<?xml version="1.0" encoding="utf-8"?>
<posthistory>
  <row Id="1" PostHistoryTypeId="2" PostId="1" RevisionGUID="e073d5df-60a9-483f-9a5b-f1daf46f4a0f" CreationDate="2015-08-04T18:05:05.010" UserId="21" Text="I saw a [video][1] on YouTube where a person uses a transparant, knotted pyramid to display holograms using their smartphone. (I have not been able to reproduce this yet, so I can't tell for sure if it works).&#xD;&#xA;&#xD;&#xA;I was wondering, given a model, which transformations I should apply to get the different projections needed to turn it into a hologram? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=7YWTtCsvgvg&amp;feature=youtu.be" ContentLicense="CC BY-SA 3.0" />
  <row Id="2" PostHistoryTypeId="1" PostId="1" RevisionGUID="e073d5df-60a9-483f-9a5b-f1daf46f4a0f" CreationDate="2015-08-04T18:05:05.010" UserId="21" Text="What transformations should I apply to a model to get this hologram?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3" PostHistoryTypeId="3" PostId="1" RevisionGUID="e073d5df-60a9-483f-9a5b-f1daf46f4a0f" CreationDate="2015-08-04T18:05:05.010" UserId="21" Text="|holograms|transformations|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4" PostHistoryTypeId="2" PostId="2" RevisionGUID="f45a1e11-576e-44aa-ba74-bdd6e1cf7f35" CreationDate="2015-08-04T18:10:11.117" UserId="36" Text="The convention in graphics is that fewer state changes is better than more state changes (switching shaders, binding data, binding textures, etc.). For textures, it is faster to render many polygons using a single atlas (for rendering sprites/text) than to individually bind a new texture for each polygon.&#xD;&#xA;&#xD;&#xA;Does this hold true if I am continually painting to a texture via `glTexSubImage2D`? I have a stream of data coming in (over a network) that undergoes processing and is then painted to a texture one row at a time. Would I be better off painting to one texture rendered on one large rectangle (scrolling the painted data into view)? Or should I paint lots of little rectangles (only revealing the rectangle when painting is done)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5" PostHistoryTypeId="1" PostId="2" RevisionGUID="f45a1e11-576e-44aa-ba74-bdd6e1cf7f35" CreationDate="2015-08-04T18:10:11.117" UserId="36" Text="Is painting on a texture considered a &quot;state change&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6" PostHistoryTypeId="3" PostId="2" RevisionGUID="f45a1e11-576e-44aa-ba74-bdd6e1cf7f35" CreationDate="2015-08-04T18:10:11.117" UserId="36" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7" PostHistoryTypeId="2" PostId="3" RevisionGUID="9616fdd4-02f8-45e4-b0aa-1cc22f4f0ca2" CreationDate="2015-08-04T18:13:47.903" UserId="17" Text="Sometimes I use Vector graphics, simply because they look just *slightly* nicer in some cases, and other times, I use Bitmap/Raster graphics.&#xD;&#xA;&#xD;&#xA;I was wondering, are there any significant performance differences between using Vector graphics over Bitmap/Raster graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8" PostHistoryTypeId="1" PostId="3" RevisionGUID="9616fdd4-02f8-45e4-b0aa-1cc22f4f0ca2" CreationDate="2015-08-04T18:13:47.903" UserId="17" Text="Performance of Vector graphics versus Bitmap/Raster graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="9" PostHistoryTypeId="3" PostId="3" RevisionGUID="9616fdd4-02f8-45e4-b0aa-1cc22f4f0ca2" CreationDate="2015-08-04T18:13:47.903" UserId="17" Text="|texture|bitmap-graphics|vector-graphics|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10" PostHistoryTypeId="5" PostId="2" RevisionGUID="814cb3fa-f4c1-4a66-b791-464306970c9e" CreationDate="2015-08-04T18:15:46.497" UserId="36" Comment="added 53 characters in body; edited title" Text="The convention in graphics is that fewer state changes is better than more state changes (switching shaders, binding data, binding textures, etc.). For textures, it is faster to render many polygons using a single atlas (for rendering sprites/text) than to individually bind a new texture for each polygon.&#xD;&#xA;&#xD;&#xA;Does this hold true if I am continually painting to a texture via `glTexSubImage2D`? I have a stream of data coming in (over a network) that undergoes processing and is then painted to a texture one row at a time. The data is presented visually in an endless scroll. Would I be better off painting to one texture rendered on one large rectangle (scrolling the painted data into view)? Or should I paint lots of little rectangles (only revealing the rectangle when painting is done)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11" PostHistoryTypeId="4" PostId="2" RevisionGUID="814cb3fa-f4c1-4a66-b791-464306970c9e" CreationDate="2015-08-04T18:15:46.497" UserId="36" Comment="added 53 characters in body; edited title" Text="Is modifying a texture (painting on it) considered a &quot;state change&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="12" PostHistoryTypeId="2" PostId="4" RevisionGUID="2567916b-c95b-4d41-9b66-8238b2f2abf8" CreationDate="2015-08-04T18:15:49.023" UserId="56" Text="I just implemented some interpolated texture sampling by sampling the 4x4 nearest pixels then doing Lagrange interpolation across the x axis to get four values to use Lagrange interpolation on across the y axis.&#xD;&#xA;&#xD;&#xA;Is this the same as bicubic interpolation or is it different?  Or are there different kinds of bicubic interpolation, and this is just one of them perhaps?&#xD;&#xA;&#xD;&#xA;Webgl Shadertoy implementation here: https://www.shadertoy.com/view/MllSzX&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13" PostHistoryTypeId="1" PostId="4" RevisionGUID="2567916b-c95b-4d41-9b66-8238b2f2abf8" CreationDate="2015-08-04T18:15:49.023" UserId="56" Text="Is a cubic Lagrange interpolation tensor product the same as bicubic interpolation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14" PostHistoryTypeId="3" PostId="4" RevisionGUID="2567916b-c95b-4d41-9b66-8238b2f2abf8" CreationDate="2015-08-04T18:15:49.023" UserId="56" Text="|texture|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15" PostHistoryTypeId="5" PostId="4" RevisionGUID="c9e0fc63-df1d-4dc7-976c-34c3b7960ca7" CreationDate="2015-08-04T18:21:09.167" UserId="56" Comment="Added relevant GLSL" Text="I just implemented some interpolated texture sampling by sampling the 4x4 nearest pixels then doing Lagrange interpolation across the x axis to get four values to use Lagrange interpolation on across the y axis.&#xD;&#xA;&#xD;&#xA;Is this the same as bicubic interpolation or is it different?  Or are there different kinds of bicubic interpolation, and this is just one of them perhaps?&#xD;&#xA;&#xD;&#xA;Webgl Shadertoy implementation here and relevant GLSL (WebGL) code below: https://www.shadertoy.com/view/MllSzX&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;    float c_textureSize = 64.0;&#xD;&#xA;    &#xD;&#xA;    float c_onePixel = 1.0 / c_textureSize;&#xD;&#xA;    float c_twoPixels = 2.0 / c_textureSize;&#xD;&#xA;    &#xD;&#xA;    float c_x0 = -1.0;&#xD;&#xA;    float c_x1 =  0.0;&#xD;&#xA;    float c_x2 =  1.0;&#xD;&#xA;    float c_x3 =  2.0;&#xD;&#xA;        &#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 CubicLagrange (vec3 A, vec3 B, vec3 C, vec3 D, float t)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            A * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x1) / (c_x0 - c_x1) * &#xD;&#xA;                (t - c_x2) / (c_x0 - c_x2) *&#xD;&#xA;                (t - c_x3) / (c_x0 - c_x3)&#xD;&#xA;            ) +&#xD;&#xA;            B * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x0) / (c_x1 - c_x0) * &#xD;&#xA;                (t - c_x2) / (c_x1 - c_x2) *&#xD;&#xA;                (t - c_x3) / (c_x1 - c_x3)&#xD;&#xA;            ) +&#xD;&#xA;            C * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x0) / (c_x2 - c_x0) * &#xD;&#xA;                (t - c_x1) / (c_x2 - c_x1) *&#xD;&#xA;                (t - c_x3) / (c_x2 - c_x3)&#xD;&#xA;            ) +       &#xD;&#xA;            D * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x0) / (c_x3 - c_x0) * &#xD;&#xA;                (t - c_x1) / (c_x3 - c_x1) *&#xD;&#xA;                (t - c_x2) / (c_x3 - c_x2)&#xD;&#xA;            );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 BicubicTextureSample (vec2 P)&#xD;&#xA;    {&#xD;&#xA;        vec2 pixel = P * c_textureSize + 0.5;&#xD;&#xA;        &#xD;&#xA;        vec2 frac = fract(pixel);&#xD;&#xA;        pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);&#xD;&#xA;        &#xD;&#xA;        vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;&#xD;&#xA;        &#xD;&#xA;        vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;&#xD;&#xA;        vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;&#xD;&#xA;        vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 CP0X = CubicLagrange(C00, C10, C20, C30, frac.x);&#xD;&#xA;        vec3 CP1X = CubicLagrange(C01, C11, C21, C31, frac.x);&#xD;&#xA;        vec3 CP2X = CubicLagrange(C02, C12, C22, C32, frac.x);&#xD;&#xA;        vec3 CP3X = CubicLagrange(C03, C13, C23, C33, frac.x);&#xD;&#xA;        &#xD;&#xA;        return CubicLagrange(CP0X, CP1X, CP2X, CP3X, frac.y);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="16" PostHistoryTypeId="5" PostId="2" RevisionGUID="8d6aaf43-0e32-4e8f-8233-d2d647964d39" CreationDate="2015-08-04T18:21:59.540" UserId="36" Comment="added 124 characters in body" Text="The convention in graphics is that performing fewer state changes is better than performing more state changes (switching shaders, binding buffers, binding textures, etc.). For textures, it is faster to render many polygons using a single atlas (for rendering sprites/text) than to individually bind a new texture for each polygon.&#xD;&#xA;&#xD;&#xA;Does this hold true if I am continually painting to a texture via `glTexSubImage2D`? I have a stream of data coming in (over a network) that undergoes processing and is then painted to a texture one row at a time. The data is presented visually in an endless scroll.&#xD;&#xA;&#xD;&#xA;Would I be better off painting to one texture rendered on one large rectangle (scrolling the painted data into view)? The idea here is that I would have one (or two) textures bound at any given time while I just continue to paint to it.&#xD;&#xA;&#xD;&#xA;Or should I paint lots of little rectangles (only revealing the rectangle when painting is done)? I assume I would bind one texture per rectangle." ContentLicense="CC BY-SA 3.0" />
  <row Id="17" PostHistoryTypeId="2" PostId="5" RevisionGUID="b5983be7-6ecb-4f87-b1de-495a47384a38" CreationDate="2015-08-04T18:25:11.677" UserId="16" Text="I have an OpenGL application which uses stencil tests quite extensively to render irregular shapes (a bit like a simple 2-D [CSG](https://en.wikipedia.org/wiki/Constructive_solid_geometry)). If I could find out how many fragments passed the stencil test and were actually rendered, this would be very helpful in simplifying some computations down the line. Specifically, it would allow me to determine the area of the rendered shape for free instead of having to approximate it with a Monte Carlo simulation later on.&#xD;&#xA;&#xD;&#xA;I know that there is a similar concept for primitives emitted from the geometry shader, called [transform feedback](https://www.opengl.org/wiki/Transform_Feedback). I'd like to know if a similar concept exists for fragments and the stencil test." ContentLicense="CC BY-SA 3.0" />
  <row Id="18" PostHistoryTypeId="1" PostId="5" RevisionGUID="b5983be7-6ecb-4f87-b1de-495a47384a38" CreationDate="2015-08-04T18:25:11.677" UserId="16" Text="Is it possible to find out how many fragments made it through the stencil test?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19" PostHistoryTypeId="3" PostId="5" RevisionGUID="b5983be7-6ecb-4f87-b1de-495a47384a38" CreationDate="2015-08-04T18:25:11.677" UserId="16" Text="|opengl|stencil-test|" ContentLicense="CC BY-SA 3.0" />
  <row Id="20" PostHistoryTypeId="2" PostId="6" RevisionGUID="953529ff-6630-4475-93ad-dadfda6e6804" CreationDate="2015-08-04T18:31:07.350" UserId="18" Text="I've heard that the quality of a monte carlo ray tracer (based on path tracing algorithms) is much more realistic than a distributed (stochastic) engine. I try to understand why, but I'm just at the beginning. &#xD;&#xA;&#xD;&#xA;In order to dive into this topic and understand the basics, can someone point me into the right direction? What part of the algorithm leads into a more realistic render result? &#xD;&#xA;&#xD;&#xA;*A recommendation of a solid book would be enough.* &#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="21" PostHistoryTypeId="1" PostId="6" RevisionGUID="953529ff-6630-4475-93ad-dadfda6e6804" CreationDate="2015-08-04T18:31:07.350" UserId="18" Text="What is the difference between monte carlo ray tracing and distributed ray tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="22" PostHistoryTypeId="3" PostId="6" RevisionGUID="953529ff-6630-4475-93ad-dadfda6e6804" CreationDate="2015-08-04T18:31:07.350" UserId="18" Text="|raytracing|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="26" PostHistoryTypeId="5" PostId="6" RevisionGUID="c6a78088-69a5-4bb5-b648-293c0788e3e9" CreationDate="2015-08-04T18:35:30.103" UserId="6" Comment="Removed chatter." Text="I've heard that the quality of a monte carlo ray tracer (based on path tracing algorithms) is much more realistic than a distributed (stochastic) engine. I try to understand why, but I'm just at the beginning. &#xD;&#xA;&#xD;&#xA;In order to dive into this topic and understand the basics, can someone point me into the right direction? What part of the algorithm leads into a more realistic render result? &#xD;&#xA;&#xD;&#xA;*A recommendation of a solid book would be enough.* &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="27" PostHistoryTypeId="24" PostId="6" RevisionGUID="c6a78088-69a5-4bb5-b648-293c0788e3e9" CreationDate="2015-08-04T18:35:30.103" Comment="Proposed by 6 approved by -1 edit id of 2" ContentLicense="CC BY-SA 3.0" />
  <row Id="28" PostHistoryTypeId="5" PostId="6" RevisionGUID="6b656664-4deb-4523-bbb1-41f8f0765ebf" CreationDate="2015-08-04T18:35:30.103" UserId="18" Comment="Removed chatter." Text="I've heard that the quality of a monte carlo ray tracer (based on path tracing algorithms) is much more realistic than a distributed (stochastic) engine. I try to understand why, but I'm just at the beginning. &#xD;&#xA;&#xD;&#xA;In order to dive into this topic and understand the basics, can someone point me into the right direction? What part of the algorithm leads into a more realistic render result? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="29" PostHistoryTypeId="2" PostId="8" RevisionGUID="f140d646-d0e4-4f6a-ba36-e5a52dcc1493" CreationDate="2015-08-04T18:37:00.853" UserId="59" Text="There might be.&#xD;&#xA;&#xD;&#xA;Less technical answer:&#xD;&#xA;&#xD;&#xA;If you're building a website or another application where you have nothing to do with the graphics programming then the answer is probably yes. The underlying APIs will try to guess how to render them and cache them efficiently. However, as your application runs and the API sometimes guesses incorrectly it may have to re-render things and affect performance.&#xD;&#xA;&#xD;&#xA;More technical:&#xD;&#xA;&#xD;&#xA;Keep in mind that unless you're using one of the newest GPUs and a library for drawing the vector paths on the GPU then it's all bitmap textures being rendered by the GPU.&#xD;&#xA;&#xD;&#xA;I'll consider the typical case where vector graphics are rendered to textures. Here the performance would depend on your toolchain, whether your application is dynamically creating textures from the vector assets, and whether the graphics are viewed at various zoom levels. There are two issues involved: resources and texture generation. If you're only displaying the graphics at a static size then I would say there is no difference and perhaps your toolchain can convert the assets into bitmap graphics before runtime. However, if they are being displayed in various sizes or in a 3D world then you'll need mip mapped textures which take more memory. They'll take a lot of memory if you really want to see their fidelity 'up close' with a larger texture. Having your application dynamically create the larger textures only when necessary will save memory but is costly at runtime and will affect performance.&#xD;&#xA;&#xD;&#xA;I hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="31" PostHistoryTypeId="2" PostId="9" RevisionGUID="5cc5e56f-a3c4-41a4-93e1-aeafd0a74592" CreationDate="2015-08-04T18:39:29.303" UserId="16" Text="A few years ago I tried to implement [this GPU Gem](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html) in OpenGL to generate 3D procedural terrain using [Marching Cubes](https://en.wikipedia.org/wiki/Marching_cubes). The article suggests to implement Marching Cubes in a geometry shader to maximum efficiency. This means I need to run the shader once for every voxel in the domain, and it'll generate the entire geometry in that cell.&#xD;&#xA;&#xD;&#xA;One problem I stumbled upon was how to get the geometry shader running without actually having anything to render outside of that shader. My solution (which seemed rather hacky) was to render a point in each cell, discard it with the geometry shader and emit my triangles instead. I never found a proper solution and this workaround remained in the final code.&#xD;&#xA;&#xD;&#xA;So, is there anyway to tell OpenGL to start a rendering pass from the geometry shader without any input geometry? Or will I always have to send some dummy points to the GPU to get things running." ContentLicense="CC BY-SA 3.0" />
  <row Id="32" PostHistoryTypeId="1" PostId="9" RevisionGUID="5cc5e56f-a3c4-41a4-93e1-aeafd0a74592" CreationDate="2015-08-04T18:39:29.303" UserId="16" Text="Is there any way to generate primitives in a geometry shader without any input geometry?" ContentLicense="CC BY-SA 3.0" />
  <row Id="33" PostHistoryTypeId="3" PostId="9" RevisionGUID="5cc5e56f-a3c4-41a4-93e1-aeafd0a74592" CreationDate="2015-08-04T18:39:29.303" UserId="16" Text="|opengl|geometry-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="34" PostHistoryTypeId="2" PostId="10" RevisionGUID="663007c5-acac-43b0-9c3e-b1e57100dd13" CreationDate="2015-08-04T18:40:58.597" UserId="56" Text="As TheBuzzSaw said, it does depend on lots of things, including implementations of the rasterized graphics vs the vector graphics.&#xD;&#xA;&#xD;&#xA;Here are some high performance vector graphics methods that are rendered using traditionally rasterization methods.&#xD;&#xA;&#xD;&#xA;Loop and Blinn show how to render a vector graphics quadratic bezier curve by rendering a single triangle, and using the texture coordinates in a pixel shader to say whether a pixel is above or below the curve:&#xD;&#xA;http://www.msr-waypoint.net/en-us/um/people/cloop/LoopBlinn05.pdf&#xD;&#xA;&#xD;&#xA;The basic idea is that you set your triangle corner positions to be the 3 control point positions, and you set the texture coordinates at each corner to be (0,0), (0.5,0) and (1,1) respectively.  In your shader, if the interpolated texture coordinate (x*x-y) is &lt; 0, the pixel is underneath the curve, else it's above the curve.&#xD;&#xA;&#xD;&#xA;You can see a faux implementation of it on shadertoy here:&#xD;&#xA;https://www.shadertoy.com/view/4tj3Dy&#xD;&#xA;&#xD;&#xA;As for the second method, here's a method from Valve, where distances to a shape are stored in a texture, instead of pixel data, allowing vector graphics to be drawn by using texture sampling.  The decoding is so simple, it could be implemented even on fixed function hardware using only an alpha test!&#xD;&#xA;http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf&#xD;&#xA;&#xD;&#xA;To give you an idea of how well the second technique works, this 1024x768 mustache image was ggenerated from a 64x32 source image that had a single color channel! (aka 2KB uncompressed)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I also wrote some stuff about it on my blog:&#xD;&#xA;http://blog.demofox.org/2014/06/30/distance-field-textures/&#xD;&#xA;&#xD;&#xA;Here is some sample OpenCL code to show just how simple it is:&#xD;&#xA;&#xD;&#xA;    float alpha = read_imagef(tex3dIn, g_textureSampler, textureCoords).w;&#xD;&#xA;    float3 color = (alpha &lt; 0.5f) ? (float3)(1.0f) : (float3)(0.0f);&#xD;&#xA;&#xD;&#xA;Both of these techniques are super fast, and blur the line between vector and rasterized graphics a bit.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wlC0y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="35" PostHistoryTypeId="2" PostId="11" RevisionGUID="5564e2fc-ca2f-42cd-8446-18bfbfd8979e" CreationDate="2015-08-04T18:44:21.417" UserId="54" Text="Well, updating an area of memory in the graphics device (a texture, buffer, and the like) is not quite the same as changing a rendering state. &#xD;&#xA;&#xD;&#xA;What makes a render state change expensive is the amount of work the driver has to do to validate the new state(s) and reorder the pipeline. This will most likely also incur some synchronization between CPU and graphics device. However, the amount of data transferred between the devices should be small for a state change (probably just a few commands).&#xD;&#xA;&#xD;&#xA;For a texture/buffer update on the other hand, the main cost lies in the data transfer itself. In theory, unless you're reading the texture data back to the CPU after the update, there should be no synchronization or pipeline stalls. However, another aspect should be considered: API overhead. Even if the amount of data you're sending to the graphics device is small, if you do that often enough, eventually the cost of communicating with the driver/device will become greater then the cost of the data transfer. That's another reason why batching is so important when optimizing a renderer.&#xD;&#xA;&#xD;&#xA;So in your case, the best approach, it seems to me, would be to keep a system-memory copy of the texture that you update whenever new data arrives. Set a dirty flag and consolidate as much updates as possible into one `glTexImage` for the whole texture (or a large sequential portion of it). You can also play with [Pixel Buffer Objects][1] and try to do asynchronous data transfer to reduce pipeline stalls as much as possible. If you can implement some kind of double buffering, then you can write to one copy of the texture while the other is being rendered with. [This tutorial][2] explores that scenario. That's my intuitive approach, I'd try to reduce the number of API calls and &quot;batch&quot; the texture updates. That being said, this is very speculative, and you'd have to profile and compare that to other approaches, like doing several small updates, to know for sure which is the most performant.&#xD;&#xA;&#xD;&#xA;As a side note, this presentation by NVidia is also relevant and provides a lot of good insights: [Approaching Zero Driver Overhead in OpenGL (Presented by NVIDIA)][3].&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Pixel_Buffer_Object&#xD;&#xA;  [2]: http://www.songho.ca/opengl/gl_pbo.html#unpack&#xD;&#xA;  [3]: http://gdcvault.com/play/1020791/" ContentLicense="CC BY-SA 3.0" />
  <row Id="37" PostHistoryTypeId="5" PostId="11" RevisionGUID="5f9d17a8-6e5e-46db-81b3-5a6445bdfe8d" CreationDate="2015-08-04T18:47:58.367" UserId="71" Comment="Removed &quot;well&quot; to make things a bit more formal." Text="Updating an area of memory in the graphics device (a texture, buffer, and the like) is not quite the same as changing a rendering state. &#xD;&#xA;&#xD;&#xA;What makes a render state change expensive is the amount of work the driver has to do to validate the new state(s) and reorder the pipeline. This will most likely also incur some synchronization between CPU and graphics device. However, the amount of data transferred between the devices should be small for a state change (probably just a few commands).&#xD;&#xA;&#xD;&#xA;For a texture/buffer update on the other hand, the main cost lies in the data transfer itself. In theory, unless you're reading the texture data back to the CPU after the update, there should be no synchronization or pipeline stalls. However, another aspect should be considered: API overhead. Even if the amount of data you're sending to the graphics device is small, if you do that often enough, eventually the cost of communicating with the driver/device will become greater then the cost of the data transfer. That's another reason why batching is so important when optimizing a renderer.&#xD;&#xA;&#xD;&#xA;So in your case, the best approach, it seems to me, would be to keep a system-memory copy of the texture that you update whenever new data arrives. Set a dirty flag and consolidate as much updates as possible into one `glTexImage` for the whole texture (or a large sequential portion of it). You can also play with [Pixel Buffer Objects][1] and try to do asynchronous data transfer to reduce pipeline stalls as much as possible. If you can implement some kind of double buffering, then you can write to one copy of the texture while the other is being rendered with. [This tutorial][2] explores that scenario. That's my intuitive approach, I'd try to reduce the number of API calls and &quot;batch&quot; the texture updates. That being said, this is very speculative, and you'd have to profile and compare that to other approaches, like doing several small updates, to know for sure which is the most performant.&#xD;&#xA;&#xD;&#xA;As a side note, this presentation by NVidia is also relevant and provides a lot of good insights: [Approaching Zero Driver Overhead in OpenGL (Presented by NVIDIA)][3].&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Pixel_Buffer_Object&#xD;&#xA;  [2]: http://www.songho.ca/opengl/gl_pbo.html#unpack&#xD;&#xA;  [3]: http://gdcvault.com/play/1020791/" ContentLicense="CC BY-SA 3.0" />
  <row Id="38" PostHistoryTypeId="24" PostId="11" RevisionGUID="5f9d17a8-6e5e-46db-81b3-5a6445bdfe8d" CreationDate="2015-08-04T18:47:58.367" Comment="Proposed by 71 approved by 54 edit id of 3" ContentLicense="CC BY-SA 3.0" />
  <row Id="39" PostHistoryTypeId="2" PostId="12" RevisionGUID="790a0b1d-93fd-4cbf-b741-5ff95a458070" CreationDate="2015-08-04T18:50:16.343" UserId="71" Text="Wikipedia [states](https://en.wikipedia.org/wiki/Stencil_buffer) that a stencil buffer is some arbitrary buffer a shader can use.&#xD;&#xA;&#xD;&#xA;However, it hints that it's used for clipping, or otherwise &quot;tightly binding&quot; the depth and pixel buffers, slightly contradicting itself.&#xD;&#xA;&#xD;&#xA;What does the stencil buffer *really* do, and how is it practically used in modern applications?" ContentLicense="CC BY-SA 3.0" />
  <row Id="40" PostHistoryTypeId="1" PostId="12" RevisionGUID="790a0b1d-93fd-4cbf-b741-5ff95a458070" CreationDate="2015-08-04T18:50:16.343" UserId="71" Text="What is a stencil buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="41" PostHistoryTypeId="3" PostId="12" RevisionGUID="790a0b1d-93fd-4cbf-b741-5ff95a458070" CreationDate="2015-08-04T18:50:16.343" UserId="71" Text="|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="42" PostHistoryTypeId="2" PostId="13" RevisionGUID="df3233c8-88d3-4ef6-8c35-124d3683cbba" CreationDate="2015-08-04T18:57:38.277" UserId="77" Text="In **Distributed ray tracing**, You stochastically sample many rays in directions which *may or may not* be preferred by the BRDF. Whereas, in **Monte Carlo ray tracing** or simply path tracing, you sample only one ray *in a direction preferred by the BRDF*. So, there are two obvious advantages Path Tracing would have:&#xD;&#xA;&#xD;&#xA;* Computationally less expensive. Which means with the same computing power you have the freedom of calculating over more object hits as compared to distributed ray tracing where there are multiple rays.&#xD;&#xA;* Less noise. Distributed ray tracing samples rays in directions that might not be preferred by the BRDF, therefore introducing unwanted artifacts. &#xD;&#xA;&#xD;&#xA;And so, path tracing would give you better results.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="43" PostHistoryTypeId="2" PostId="14" RevisionGUID="1d13e844-4e30-4b22-bfd6-605acec39bfb" CreationDate="2015-08-04T18:58:03.393" UserId="6" Text="No, there is not really a way to do that.&#xD;&#xA;&#xD;&#xA;A geometry shader invocation requires an input primitive and generates 0 or more output primitives. **Without an input primitive, there is not really a way to actually *invoke* the geometry shader**. Of course you can stretch the limits of the geometry shader's maximum number of output primitives for each input primitive (don't know the practical limits right now, should be on the order of thousands maybe). So you maybe could generate 1024 triangles for each point, but you always have to have *some* input primitives.&#xD;&#xA;&#xD;&#xA;What you *don't need* however is an actual notion of geometry. You don't really have to render 3D points at any reasonable location, they could as well have just some abstract index or texture coordinates or whatever as attributes and not necessarily a meaningful 3D position. **Noone dictates what attributes your vertices have. And you can even render vertices *without any* attributes** (I'd have to look up since which GL version that works exactly, though). But you have to render *some* primitives to invoke the geometry shader on them, even if those primitives don't have any actual attributes (how you then compute your output geometry in the geometry shader is a different question, though).&#xD;&#xA;&#xD;&#xA;But what you actually did, rendering a point for each grid cell and generating the marching cubes triangles for that cell from it, is exactly the straight-forward approach. Of course what attributes this cell contains is up to you, it could be a 3D position, a texcoord into a 3D texture, whatever, but those are the grid cells you render. Purely semantically spoken, you don't actually &quot;discard&quot; those points and then &quot;replace&quot; them by triangles, you &quot;convert&quot; each point into a set of triangles. That's exactly what the geometry shader is for and there's nothing &quot;hacky&quot; or &quot;improper&quot; about it. **Noone says the geometry shader has to generate the same output primitive type as was input to be &quot;proper&quot;**." ContentLicense="CC BY-SA 3.0" />
  <row Id="44" PostHistoryTypeId="5" PostId="10" RevisionGUID="c44cb1ee-5895-4eaa-8741-3a3d618d14d9" CreationDate="2015-08-04T18:58:30.893" UserId="56" Comment="added 121 characters in body" Text="As TheBuzzSaw said, it does depend on lots of things, including implementations of the rasterized graphics vs the vector graphics.&#xD;&#xA;&#xD;&#xA;Here are some high performance vector graphics methods that are rendered using traditionally rasterization methods.&#xD;&#xA;&#xD;&#xA;Loop and Blinn show how to render a vector graphics quadratic bezier curve by rendering a single triangle, and using the texture coordinates in a pixel shader to say whether a pixel is above or below the curve:&#xD;&#xA;http://www.msr-waypoint.net/en-us/um/people/cloop/LoopBlinn05.pdf&#xD;&#xA;&#xD;&#xA;The basic idea is that you set your triangle corner positions to be the 3 control point positions, and you set the texture coordinates at each corner to be (0,0), (0.5,0) and (1,1) respectively.  In your shader, if the interpolated texture coordinate (x*x-y) is &lt; 0, the pixel is underneath the curve, else it's above the curve.&#xD;&#xA;&#xD;&#xA;You can see a faux implementation of it on shadertoy here:&#xD;&#xA;https://www.shadertoy.com/view/4tj3Dy&#xD;&#xA;&#xD;&#xA;As for the second method, here's a method from Valve, where distances to a shape are stored in a texture, instead of pixel data, allowing vector graphics to be drawn by using texture sampling.  The decoding is so simple, it could be implemented even on fixed function hardware using only an alpha test!&#xD;&#xA;http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf&#xD;&#xA;&#xD;&#xA;To give you an idea of how well the second technique works, this 1024x768 mustache image was generated from a 64x32 source image that had a single color channel! (aka 2KB uncompressed)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I also wrote some stuff about it on my blog:&#xD;&#xA;http://blog.demofox.org/2014/06/30/distance-field-textures/&#xD;&#xA;&#xD;&#xA;Here is some sample OpenCL code to show just how simple it is:&#xD;&#xA;&#xD;&#xA;    float alpha = read_imagef(tex3dIn, g_textureSampler, textureCoords).w;&#xD;&#xA;    float3 color = (alpha &lt; 0.5f) ? (float3)(1.0f) : (float3)(0.0f);&#xD;&#xA;&#xD;&#xA;Both of these techniques are super fast, and blur the line between vector and rasterized graphics a bit.  They are rendered using rasterization techniques, but have zooming / scaling properties like vector graphics techniques.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wlC0y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="45" PostHistoryTypeId="2" PostId="15" RevisionGUID="eebcbdc2-63fc-4076-a255-83949d78e1d9" CreationDate="2015-08-04T18:58:36.040" UserId="70" Text="In 1978 Edwin Catmull and Jim Clark defined the recursive subdivision process that bears their names, and although those principles are applicable still today, what advances have occurred as far as optimization and accuracy?" ContentLicense="CC BY-SA 3.0" />
  <row Id="46" PostHistoryTypeId="1" PostId="15" RevisionGUID="eebcbdc2-63fc-4076-a255-83949d78e1d9" CreationDate="2015-08-04T18:58:36.040" UserId="70" Text="What subdivision algorithm advances have occurred since Catmull-Clark?" ContentLicense="CC BY-SA 3.0" />
  <row Id="47" PostHistoryTypeId="3" PostId="15" RevisionGUID="eebcbdc2-63fc-4076-a255-83949d78e1d9" CreationDate="2015-08-04T18:58:36.040" UserId="70" Text="|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="48" PostHistoryTypeId="5" PostId="14" RevisionGUID="596e4d09-4ebe-4453-83c9-e18ad4189e9f" CreationDate="2015-08-04T19:07:27.160" UserId="6" Comment="added 806 characters in body" Text="No, there is not really a way to do that.&#xD;&#xA;&#xD;&#xA;A geometry shader invocation requires an input primitive and generates 0 or more output primitives. **Without an input primitive, there is not really a way to actually *invoke* the geometry shader**. Of course you can stretch the limits of the geometry shader's maximum number of output primitives for each input primitive (don't know the practical limits right now, should be on the order of thousands maybe). So you maybe could generate 1024 triangles for each point, but you always have to have *some* input primitives.&#xD;&#xA;&#xD;&#xA;What you *don't need* however is an actual notion of geometry. You don't really have to render 3D points at any reasonable location, they could as well have just some abstract index or texture coordinates or whatever as attributes and not necessarily a meaningful 3D position. **Noone dictates what attributes your vertices have. And you can even render vertices *without any* attributes** (I'd have to look up since which GL version that works exactly, though). But you have to render *some* primitives to invoke the geometry shader on them, even if those primitives don't have any actual attributes (how you then compute your output geometry in the geometry shader is a different question, though).&#xD;&#xA;&#xD;&#xA;But what you actually did, rendering a point for each grid cell and generating the marching cubes triangles for that cell from it, is exactly the straight-forward approach. Of course what attributes this cell contains is up to you, it could be a 3D position, a texcoord into a 3D texture, whatever, but those are the grid cells you render. Purely semantically spoken, you don't actually &quot;discard&quot; those points and then &quot;replace&quot; them by triangles, you &quot;convert&quot; each point into a set of triangles. That's exactly what the geometry shader is for and there's nothing &quot;hacky&quot; or &quot;improper&quot; about it. **Noone says the geometry shader has to generate the same output primitive type as was input to be &quot;proper&quot;**.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;What you can do to achieve a largely input-less way of rendering your voxel grid (and this might be what you were actually asking for) would be to just draw a set of attributeless points. This means you don't need any attribute arrays at all and just disable them all and invoke a simple `glDrawArrays` with the number of cells you need. Then in the vertex shader or the geometry shader you can generate the necessary 3D grid cell index with a little idnex magic from the input vertex ID (i.e. `gl_VertexID`, which is the only information you have) and then compute your marching cubes geometry from a lookup into the 3D volume texture (or whatever datastructure).&#xD;&#xA;&#xD;&#xA;So, in retrospect I should relativate my statement form the beginning a bit, **you cannot generate primitives without any input *primitives*, but you can generate them without any input *geometry***." ContentLicense="CC BY-SA 3.0" />
  <row Id="49" PostHistoryTypeId="2" PostId="16" RevisionGUID="9e98b136-b9c5-4708-95dc-d33d75fdfa7b" CreationDate="2015-08-04T19:18:52.277" UserId="64" Text="&gt; A stencil buffer contains per-pixel integer data which is used to add&#xD;&#xA;&gt; more control over which pixels are rendered.&#xD;&#xA;&gt; &#xD;&#xA;&gt; A stencil buffer operates similarly to a depth buffer. So similarly,&#xD;&#xA;&gt; that stencil data is stored in a depth buffer. While depth data&#xD;&#xA;&gt; determines which pixel is closest to the camera, stencil data can be&#xD;&#xA;&gt; used as a more general purpose per-pixel mask for saving or discarding&#xD;&#xA;&gt; pixels. To create the mask, use a stencil function to compare a&#xD;&#xA;&gt; reference stencil value -- a global value -- to the value in the&#xD;&#xA;&gt; stencil buffer each time a pixel is rendered.&#xD;&#xA;&#xD;&#xA;Source: https://msdn.microsoft.com/en-us/library/bb976074.aspx&#xD;&#xA;&#xD;&#xA;The general idea is that you can set a value for each pixel and then set the operation (GREATER, SMALLER, EQUAL etc), when this evaluates to true the pixel is shaded and shown.&#xD;&#xA;&#xD;&#xA;One application is realtime reflection, when rendering the reflection texture the stencil buffer is used to create a mask for where the reflection is applied. For example only apply the reflection to the glass material shaded triangles. It can also be used to create arbitrary two dimensional masks for the whole framebuffer." ContentLicense="CC BY-SA 3.0" />
  <row Id="50" PostHistoryTypeId="5" PostId="11" RevisionGUID="4a05d947-341a-47a0-b524-3b9e2ccb7605" CreationDate="2015-08-04T19:19:15.453" UserId="54" Comment="edited body" Text="Updating an area of memory in the graphics device (a texture, buffer, and the like) is not quite the same as changing a rendering state. &#xD;&#xA;&#xD;&#xA;What makes a render state change expensive is the amount of work the driver has to do to validate the new state(s) and reorder the pipeline. This will most likely also incur some synchronization between CPU and graphics device. However, the amount of data transferred between the devices should be small for a state change (probably just a few commands).&#xD;&#xA;&#xD;&#xA;For a texture/buffer update on the other hand, the main cost lies in the data transfer itself. In theory, unless you're reading the texture data back to the CPU after the update, there should be no synchronization or pipeline stalls. However, another aspect should be considered: API overhead. Even if the amount of data you're sending to the graphics device is small, if you do that often enough, eventually the cost of communicating with the driver/device will become greater then the cost of the data transfer. That's another reason why batching is so important when optimizing a renderer.&#xD;&#xA;&#xD;&#xA;So in your case, the best approach, it seems to me, would be to keep a system-memory copy of the texture that you update whenever new data arrives. Set a dirty flag and consolidate as much updates as possible into one `glTexSubImage` for the whole texture (or a large sequential portion of it). You can also play with [Pixel Buffer Objects][1] and try to do asynchronous data transfer to reduce pipeline stalls as much as possible. If you can implement some kind of double buffering, then you can write to one copy of the texture while the other is being rendered with. [This tutorial][2] explores that scenario. That's my intuitive approach, I'd try to reduce the number of API calls and &quot;batch&quot; the texture updates. That being said, this is very speculative, and you'd have to profile and compare that to other approaches, like doing several small updates, to know for sure which is the most performant in your usage case.&#xD;&#xA;&#xD;&#xA;As a side note, this presentation by NVidia is also relevant and provides a lot of good insights: [Approaching Zero Driver Overhead in OpenGL][3].&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Pixel_Buffer_Object&#xD;&#xA;  [2]: http://www.songho.ca/opengl/gl_pbo.html#unpack&#xD;&#xA;  [3]: http://gdcvault.com/play/1020791/" ContentLicense="CC BY-SA 3.0" />
  <row Id="51" PostHistoryTypeId="5" PostId="14" RevisionGUID="27dbbb62-67ba-4b58-a0c9-50d0813d40e2" CreationDate="2015-08-04T19:20:23.330" UserId="6" Comment="deleted 7 characters in body" Text="No, there is not really a way to do that.&#xD;&#xA;&#xD;&#xA;A geometry shader invocation requires an input primitive and generates 0 or more output primitives. **Without an input primitive, there is not really a way to actually *invoke* the geometry shader**. Of course you can stretch the limits of the geometry shader's maximum number of output primitives for each input primitive (don't know the practical limits right now, should be on the order of thousands maybe). So you maybe could generate 1024 triangles for each point, but you always have to have *some* input primitives.&#xD;&#xA;&#xD;&#xA;What you *don't need* however is an actual notion of geometry. You don't really have to render 3D points at any reasonable location, they could as well have just some abstract index or texture coordinates or whatever as attributes and not necessarily a meaningful 3D position. **Noone dictates what attributes your vertices have. And you can even render vertices *without any* attributes**. But you have to render *some* primitives to invoke the geometry shader on them, even if those primitives don't have any actual attributes (how you then compute your output geometry in the geometry shader is a different question, though).&#xD;&#xA;&#xD;&#xA;But what you actually did, rendering a point for each grid cell and generating the marching cubes triangles for that cell from it, is exactly the straight-forward approach. Of course what attributes this cell contains is up to you, it could be a 3D position, a texcoord into a 3D texture, whatever, but those are the grid cells you render. Purely semantically spoken, you don't actually &quot;discard&quot; those points and then &quot;replace&quot; them by triangles, you &quot;convert&quot; each point into a set of triangles. That's exactly what the geometry shader is for and there's nothing &quot;hacky&quot; or &quot;improper&quot; about it. **Noone says the geometry shader has to generate the same output primitive type as was input to be &quot;proper&quot;**.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;What you can do to achieve a largely input-less way of rendering your voxel grid (and this might be what you were actually asking for) would be to just draw a set of attributeless points. This means you don't need any attribute arrays at all and just disable them all and invoke a simple `glDrawArrays` with the number of cells you need. Then in the vertex shader or the geometry shader you can generate the necessary 3D grid cell index with a little index magic from the input vertex ID (i.e. `gl_VertexID`, which is the only information you have) and then compute your marching cubes geometry from a lookup into the 3D volume texture (or whatever datastructure).&#xD;&#xA;&#xD;&#xA;So, in retrospect I should relativate my statement from the beginning: **You can't generate primitives without any input *primitives*, but you can generate them without any input *geometry***." ContentLicense="CC BY-SA 3.0" />
  <row Id="55" PostHistoryTypeId="4" PostId="6" RevisionGUID="a2f85bf2-a474-46f7-8e26-5f0ea5ec8ddc" CreationDate="2015-08-04T19:26:39.027" UserId="77" Comment="Corrected question to compky with explanation." Text="Why does monte carlo ray tracing perform better than distributed ray tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="56" PostHistoryTypeId="24" PostId="6" RevisionGUID="a2f85bf2-a474-46f7-8e26-5f0ea5ec8ddc" CreationDate="2015-08-04T19:26:39.027" Comment="Proposed by 77 approved by 18 edit id of 4" ContentLicense="CC BY-SA 3.0" />
  <row Id="57" PostHistoryTypeId="5" PostId="16" RevisionGUID="882e7405-948a-4de7-9b1d-929e13c69b9a" CreationDate="2015-08-04T19:30:54.387" UserId="71" Comment="Added gravemarks to potential code constants." Text="&gt; A stencil buffer contains per-pixel integer data which is used to add&#xD;&#xA;&gt; more control over which pixels are rendered.&#xD;&#xA;&gt; &#xD;&#xA;&gt; A stencil buffer operates similarly to a depth buffer. So similarly,&#xD;&#xA;&gt; that stencil data is stored in a depth buffer. While depth data&#xD;&#xA;&gt; determines which pixel is closest to the camera, stencil data can be&#xD;&#xA;&gt; used as a more general purpose per-pixel mask for saving or discarding&#xD;&#xA;&gt; pixels. To create the mask, use a stencil function to compare a&#xD;&#xA;&gt; reference stencil value -- a global value -- to the value in the&#xD;&#xA;&gt; stencil buffer each time a pixel is rendered.&#xD;&#xA;&#xD;&#xA;Source: https://msdn.microsoft.com/en-us/library/bb976074.aspx&#xD;&#xA;&#xD;&#xA;The general idea is that you can set a value for each pixel and then set the operation (`GREATER`, `SMALLER`, `EQUAL` etc), when this evaluates to true the pixel is shaded and shown.&#xD;&#xA;&#xD;&#xA;One application is realtime reflection, when rendering the reflection texture the stencil buffer is used to create a mask for where the reflection is applied. For example only apply the reflection to the glass material shaded triangles. It can also be used to create arbitrary two dimensional masks for the whole framebuffer." ContentLicense="CC BY-SA 3.0" />
  <row Id="58" PostHistoryTypeId="24" PostId="16" RevisionGUID="882e7405-948a-4de7-9b1d-929e13c69b9a" CreationDate="2015-08-04T19:30:54.387" Comment="Proposed by 71 approved by 64 edit id of 5" ContentLicense="CC BY-SA 3.0" />
  <row Id="60" PostHistoryTypeId="2" PostId="18" RevisionGUID="bfc525a3-f2ee-4b76-b283-3a542d755762" CreationDate="2015-08-04T19:33:04.573" UserId="79" Text="The term &quot;distributed ray tracing&quot; was originally coined by Robert Cook in [this 1984 paper](http://artis.inrialpes.fr/Enseignement/TRSA/CookDistributed84.pdf). His observation was that in order to perform anti-aliasing in a ray-tracer, the renderer needs to perform spatial upsampling - that is, to take more samples (i.e. shoot more rays) than the number of pixels in the image and combine their results. One way to do this is to shoot multiple rays within a pixel and average their color values, for example. However, if the renderer is already tracing multiple rays per pixel anyway to obtain an anti-aliased image, then these rays can also be &quot;distributed&quot; among additional dimensions than just the pixel position to sample effects that could not be captured by a single ray. The important bit is that this comes without any additional cost on top of spatial upsampling, since you're already tracing those additional rays anyway. For example, if you shoot multiple rays within your pixel to compute an anti-aliased result, you can get motion blur absolutely for free if you also use a different time value for each ray (or soft shadows if they connect to a different point on the light source, or depth of field if they use a different starting point on the aperture, etc.).&#xD;&#xA;&#xD;&#xA;Monte Carlo ray tracing is a term that is slightly ambiguous. In most cases, it refers to rendering techniques that solve the [rendering equation](http://www.dca.fee.unicamp.br/~leopini/DISCIPLINAS/IA725/ia725-12010/kajiya-SIG86-p143.pdf), introduced by Jim Kajiya in 1986, using Monte Carlo integration. Practically all modern rendering techniques that solve the rendering equation, such as path tracing, bidirectional path tracing, progressive photon mapping and VCM, can be classified as Monte Carlo ray tracing techniques. The idea of Monte Carlo integration is that we can compute the integral of any function by randomly choosing points in the integration domain and averaging the value of the function at these points. At a high level, in Monte Carlo ray tracing we can use this technique to integrate the amount of light arriving at the camera within a pixel in order to compute the pixel value. For example, a path tracer does this by randomly picking a point within the pixel to shoot the first ray, and then continues to randomly pick a direction to continue on the surface it lands on, and so forth. We could also randomly pick a position on the time axis if we want to do motion blur, or randomly pick a point on the aperture if wanted to do depth of field, or...&#xD;&#xA;&#xD;&#xA;If this sounds very similar to distributed ray tracing, that's because it is! We can think of distributed ray tracing as a very informal description of a Monte Carlo algorithm that samples certain effects like soft shadows. Cook's paper lacks the mathematical framework to really reason about it properly, but you could certainly implement distributed ray tracing using a simple Monte Carlo renderer. It's worth noting that distributed ray tracing lacks any description of global illumination effects, which are naturally modeled in the rendering equation (it should be mentioned that Kajiya's paper was published two years after Cook's paper).&#xD;&#xA;&#xD;&#xA;You can think of Monte Carlo ray tracing as being a more general version of distributed ray tracing. Monte Carlo ray tracing contains a general mathematical framework that allows you to handle practically any effect, including those mentioned in the distributed ray tracing paper.&#xD;&#xA;&#xD;&#xA;These days, &quot;distributed ray tracing&quot; is not really a term that's used to refer to the original algorithm. More often you will hear it in conjunction with &quot;distribution effects&quot;, which are simply effects such as motion blur, depth of field or soft shadows that cannot be handled with a single-sample raytracer." ContentLicense="CC BY-SA 3.0" />
  <row Id="61" PostHistoryTypeId="2" PostId="19" RevisionGUID="70ca3593-e73b-41e0-8545-a6af8611d985" CreationDate="2015-08-04T19:40:54.970" UserId="16" Text="[Perlin noise](https://en.wikipedia.org/wiki/Perlin_noise) is one of the most popular procedural noise functions. Perlin later developed [Simplex noise](https://en.wikipedia.org/wiki/Simplex_noise) which improves on some of the shortcomings of Perlin noise, notably its inefficiency in higher dimensions and directional artefacts (Wikipedia lists five advantages of Simplex noise). Still, Perlin noise appears to be widely used. I can imagine that the main reason is that Simplex noise is conceptually much more difficult to understand, but by now there should be enough implementations so that you don't have to re-implement it yourself.&#xD;&#xA;&#xD;&#xA;Does Perlin noise have any advantages over Simplex noise? When picking a noise function, would I ever choose Perlin instead of Simplex?" ContentLicense="CC BY-SA 3.0" />
  <row Id="62" PostHistoryTypeId="1" PostId="19" RevisionGUID="70ca3593-e73b-41e0-8545-a6af8611d985" CreationDate="2015-08-04T19:40:54.970" UserId="16" Text="Does the original Perlin noise ever have any advantage over Simplex noise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="63" PostHistoryTypeId="3" PostId="19" RevisionGUID="70ca3593-e73b-41e0-8545-a6af8611d985" CreationDate="2015-08-04T19:40:54.970" UserId="16" Text="|noise|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="64" PostHistoryTypeId="2" PostId="20" RevisionGUID="2d85c83e-071a-4c49-84fe-fe204949387c" CreationDate="2015-08-04T19:44:03.353" UserId="100" Text="The stencil buffer is an unsigned integer buffer, usually 8-bit nowadays, where you can fill per-pixel infomation as you wish based on the use of various operations ([OpenGL Ops here for example] [1]) following a stencil test. &#xD;&#xA;&#xD;&#xA;The stencil test is simply a per-pixel operation in which the current pixel stencil value is tested against the content of the stencil buffer. You set the condition to which the stencil test is passed ( e.g. ALWAYS, LESS etc. ). &#xD;&#xA;&#xD;&#xA;You can decide what happens to the stencil value depending on the outcome of the test (in OpenGL using the operation I linked you above) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the usages, well there are quite a few, the first ones that come to mind are: &#xD;&#xA;&#xD;&#xA; - Mask to be selectively render certain part of the framebuffer. This case could be for reflections for example, but also lots more. For example when dealing with multiple resolution rendering it can be used to mark up edges to b rendered at higher res. There are plenty of masking usages really. &#xD;&#xA; - A very simple overdraw filter for example. You can set the stencil test to always pass and always increment the value. The value you end up with in the stencil buffer represent your overdraw. [*] &#xD;&#xA;&#xD;&#xA;In the past it has been used also for shadowing techniques like Shadow volume.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is often quite underestimated the poor stencil buffer, but can often be a good weapon in a graphics programmer armory. &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;[*] Value to be read back in a post-process using the right SRV! &#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;Also, worth mentioning that in Shader Model 5.1 (so D3D11.3 and D3D12) you have access to the stencil reference value via &lt;code&gt;SV_StencilRef&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Stencil_Test#Stencil_operations" ContentLicense="CC BY-SA 3.0" />
  <row Id="65" PostHistoryTypeId="2" PostId="21" RevisionGUID="42f382f1-c45c-4942-aee5-487800548a58" CreationDate="2015-08-04T19:45:33.780" UserId="54" Text="The stencil buffer definition by Wikipedia is indeed not great, it focus too much on the details of modern implementations (OpenGL). I find [the disambiguated version][1] easier to understand:&#xD;&#xA;&#xD;&#xA;&gt; A stencil is a template used to draw or paint identical letters, symbols, shapes, or patterns every time it is used. The design produced by such a template is also called a stencil.&#xD;&#xA;&#xD;&#xA;That's what stencil meant before Computer Graphics. If you type *stencil* on Google Images, this is one of the first results:&#xD;&#xA;&#xD;&#xA;[![Stencil mask][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, it is simply a mask or pattern that can be used to &quot;paint&quot; the negative of the pattern onto something.&#xD;&#xA;&#xD;&#xA;The *stencil buffer* works in the exact same way. One can fill the stencil buffer with a selected pattern by doing a stencil render pass, then set the appropriate stencil function which will define how the pattern is to be interpreted on subsequent drawings, then render the final scene. Pixels that fall into the rejected areas of the stencil mask, according to the compare function, are not draw.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;When it comes to implementing the stencil buffer, sometimes it is indeed coupled with the depth buffer. Most graphics hardware uses a 1 byte (8bits) stencil buffer, which is enough for most applications. Depth buffers are usually implemented using 3 bytes (24bits), which again is normally enough for most kinds of 3D rendering. So it is only logical to pack the 8bits of the stencil buffer with the other 24 of the depth buffer, making it possible to store each depth+stencil pixel into a 32bit integer. That's what Wikipedia meant by:&#xD;&#xA;&#xD;&#xA;&gt; The depth buffer and stencil buffer often share the same area in the RAM of the graphics hardware.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;One application in which the stencil buffer used to be king was for shadow rendering, in a technique called [*shadow volumes*][3], or sometimes also appropriately called *stencil shadows*. This was a very cleaver use of the buffer, but nowadays most of the rendering field seems to have shifted towards depth-based shadow maps.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stencil_(disambiguation)&#xD;&#xA;  [2]: https://i.stack.imgur.com/bHD7z.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Shadow_volume&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="66" PostHistoryTypeId="2" PostId="22" RevisionGUID="f4a1f27c-702b-491b-a818-072805a55864" CreationDate="2015-08-04T19:48:16.840" UserId="1" Text="There are a few ways of rendering vector graphics. As TheBuzzSaw mentions, NVIDIA has an extension that can render general paths quite quickly (but of course it only works on NVIDIA GPUs). And Alan Wolfe mentions the implicit surface methods (Loop-Blinn/distance fields), which define a function which says whether you're inside or outside a shape, and color the pixels based on that function.  Another method is stencil-and-cover, where you render the path into a stencil buffer and use the even-odd count to determine whether the path covers a pixel.&#xD;&#xA;&#xD;&#xA;In general, however, the tradeoff is that rendering raster will be faster, but is more susceptible to aliasing (even distance fields break down at low and high scales). Rendering paths requires a lot of setup but in theory can be scaled to any resolution." ContentLicense="CC BY-SA 3.0" />
  <row Id="67" PostHistoryTypeId="5" PostId="20" RevisionGUID="03b87758-64dd-4397-bfeb-abcdce44fbdd" CreationDate="2015-08-04T19:52:02.667" UserId="100" Comment="deleted 8 characters in body; added 2 characters in body" Text="The stencil buffer is an unsigned integer buffer, usually 8-bit nowadays, where you can fill per-pixel infomation as you wish based on the use of various operations ([OpenGL Ops here for example] [1]) following a stencil test. &#xD;&#xA;&#xD;&#xA;The stencil test is simply a per-pixel operation in which the current pixel stencil value is tested against the content of the stencil buffer. You set the condition to which the stencil test is passed ( e.g. ALWAYS, LESS etc. ). &#xD;&#xA;&#xD;&#xA;You can decide what happens to the stencil value depending on the outcome of the test (in OpenGL using the operation I linked you above) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The stencil buffer has quite a few uses, the first ones that come to mind being:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - It can be used as a mask to selectively render certain part of the framebuffer. For example for reflections, but also lots more. When dealing with multiple resolution rendering it can be used to mark up edges that need to be rendered at an higher res. There are plenty of masking usages really. &#xD;&#xA; - A very simple overdraw filter for example. You can set the stencil test to always pass and always increment the value. The value you end up with in the stencil buffer represents your overdraw. [*] &#xD;&#xA;&#xD;&#xA;In the past it has been used also for shadowing techniques such as Shadow volume.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The poor stencil buffer is often quite underestimated, but can be a good weapon in a graphics programmer's armory. &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;[*] Value to be read back in a post-process using the right SRV! &#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;Also, worth mentioning that in Shader Model 5.1 (so D3D11.3 and D3D12) you have access to the stencil reference value via &lt;code&gt;SV_StencilRef&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Stencil_Test#Stencil_operations" ContentLicense="CC BY-SA 3.0" />
  <row Id="68" PostHistoryTypeId="5" PostId="21" RevisionGUID="bbfac917-280e-4f41-b112-26c1667dec70" CreationDate="2015-08-04T19:57:35.343" UserId="54" Comment="fixed a typo" Text="The stencil buffer definition by Wikipedia is indeed not great, it focus too much on the details of modern implementations (OpenGL). I find [the disambiguated version][1] easier to understand:&#xD;&#xA;&#xD;&#xA;&gt; A stencil is a template used to draw or paint identical letters, symbols, shapes, or patterns every time it is used. The design produced by such a template is also called a stencil.&#xD;&#xA;&#xD;&#xA;That's what stencil meant before Computer Graphics. If you type *stencil* on Google Images, this is one of the first results:&#xD;&#xA;&#xD;&#xA;[![Stencil mask][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, it is simply a mask or pattern that can be used to &quot;paint&quot; the negative of the pattern onto something.&#xD;&#xA;&#xD;&#xA;The *stencil buffer* works in the exact same way. One can fill the stencil buffer with a selected pattern by doing a stencil render pass, then set the appropriate stencil function which will define how the pattern is to be interpreted on subsequent drawings, then render the final scene. Pixels that fall into the rejected areas of the stencil mask, according to the compare function, are not draw.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;When it comes to implementing the stencil buffer, sometimes it is indeed coupled with the depth buffer. Most graphics hardware uses a 1 byte (8bits) stencil buffer, which is enough for most applications. Depth buffers are usually implemented using 3 bytes (24bits), which again is normally enough for most kinds of 3D rendering. So it is only logical to pack the 8bits of the stencil buffer with the other 24 of the depth buffer, making it possible to store each depth+stencil pixel into a 32bit integer. That's what Wikipedia meant by:&#xD;&#xA;&#xD;&#xA;&gt; The depth buffer and stencil buffer often share the same area in the RAM of the graphics hardware.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;One application in which the stencil buffer used to be king was for shadow rendering, in a technique called [*shadow volumes*][3], or sometimes also appropriately called *stencil shadows*. This was a very clever use of the buffer, but nowadays most of the rendering field seems to have shifted towards depth-based shadow maps.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stencil_(disambiguation)&#xD;&#xA;  [2]: https://i.stack.imgur.com/bHD7z.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Shadow_volume&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="69" PostHistoryTypeId="2" PostId="23" RevisionGUID="59b89084-9a0e-4c14-ba4d-fac0cf117eb4" CreationDate="2015-08-04T20:05:43.820" UserId="116" Text="I have a point cloud that is being rendered to the screen. Each point has its position and color as well as an ID.&#xD;&#xA;I was asked to render the IDs for each point to a texture so I created a FBO and attached two textures, one for color and one for depth.&#xD;&#xA;I created the necessary VAO and VBO for this off-screen rendering and uplaoded for each point its position and ID.&#xD;&#xA;Once the rendering to the FBO is done, I read the pixels of the color-texture glReadPixels() to see what the values are, but they seem to be all cleared out, i.e., the value they have is the same as glClearColor().&#xD;&#xA;Is there a way I can debug what it is being render to the color texture of my FBO? Any tips that you may provide are very welcomed." ContentLicense="CC BY-SA 3.0" />
  <row Id="70" PostHistoryTypeId="1" PostId="23" RevisionGUID="59b89084-9a0e-4c14-ba4d-fac0cf117eb4" CreationDate="2015-08-04T20:05:43.820" UserId="116" Text="How can I debug what is being rendered to a Frame Buffer Object in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="71" PostHistoryTypeId="3" PostId="23" RevisionGUID="59b89084-9a0e-4c14-ba4d-fac0cf117eb4" CreationDate="2015-08-04T20:05:43.820" UserId="116" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="73" PostHistoryTypeId="2" PostId="24" RevisionGUID="987e1290-8aad-473a-b94b-cc429e1fa609" CreationDate="2015-08-04T20:08:24.347" UserId="20" Text="Assuming your optimal viewing angle is parallel to the surface of the display and the pyramid is made from faces that are 45 degrees to its virtual (non-existant) base, it's actually just a simple non-transformed image (besides the reflection).&#xD;&#xA;&#xD;&#xA;1:1 projection. No transformations. No scaling. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="74" PostHistoryTypeId="2" PostId="25" RevisionGUID="e0b78b58-340b-4a2d-a433-b196ff9fea4e" CreationDate="2015-08-04T20:15:17.410" UserId="100" Text="Generally to see what is being rendered in the various steps of your pipeline I'd suggest the use of a tool for frame analysis. These usually provide you with a view on the content of each buffer for each API call and this can help you in your situation.&#xD;&#xA;&#xD;&#xA;A very good one is [Renderdoc][1] which is both completely free and opensource. Also it is actively supported. &#xD;&#xA;&#xD;&#xA;Another one is [Intel GPA][2] that unfortunately, according to the its page, support up to OGL 3.3 Core. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Just for the sake of adding one more, I used to use [gDEBugger][3], but it has passed long since the last update. This has evolved into [AMD CodeXL][4] that unfortunately I never used.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/baldurk/renderdoc&#xD;&#xA;  [2]: https://software.intel.com/en-us/gpa/details&#xD;&#xA;  [3]: http://www.gremedy.com/&#xD;&#xA;  [4]: http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/" ContentLicense="CC BY-SA 3.0" />
  <row Id="76" PostHistoryTypeId="5" PostId="20" RevisionGUID="7268a450-d7f0-43bb-8645-337411a40081" CreationDate="2015-08-04T20:21:59.477" UserId="100" Comment="added 38 characters in body" Text="The stencil buffer is an unsigned integer buffer, usually 8-bit nowadays, where you can fill per-pixel infomation as you wish based on the use of various operations ([OpenGL Ops here for example] [1]) following a stencil test. &#xD;&#xA;&#xD;&#xA;The stencil test is simply a per-pixel operation in which the current pixel stencil value is tested against the content of the stencil buffer. You set the condition to which the stencil test is passed ( e.g. ALWAYS, LESS etc. ). &#xD;&#xA;&#xD;&#xA;You can decide what happens to the stencil value depending on the outcome of the test (in OpenGL using the operation I linked you above) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The stencil buffer has quite a few uses, the first ones that come to mind being:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - It can be used as a mask to selectively render certain part of the framebuffer and discard the rest. This, for example, is useful for reflections, but also lots more. When dealing with multiple resolution rendering it can be used to mark up edges that need to be rendered at an higher res. There are plenty of masking usages really. &#xD;&#xA; - A very simple overdraw filter for example. You can set the stencil test to always pass and always increment the value. The value you end up with in the stencil buffer represents your overdraw. [*] &#xD;&#xA;&#xD;&#xA;In the past it has been used also for shadowing techniques such as Shadow volume.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The poor stencil buffer is often quite underestimated, but can be a good weapon in a graphics programmer's armory. &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;[*] Value to be read back in a post-process using the right SRV! &#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;Also, worth mentioning that in Shader Model 5.1 (so D3D11.3 and D3D12) you have access to the stencil reference value via &lt;code&gt;SV_StencilRef&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Stencil_Test#Stencil_operations" ContentLicense="CC BY-SA 3.0" />
  <row Id="77" PostHistoryTypeId="5" PostId="25" RevisionGUID="0e5e0dd9-433a-473b-a6a5-ff2ba10cb574" CreationDate="2015-08-04T21:18:32.987" UserId="100" Comment="deleted 1 character in body" Text="Generally to see what is being rendered in the various steps of your pipeline I'd suggest the use of a tool for frame analysis. These usually provide you with a view on the content of each buffer for each API call and this can help you in your situation.&#xD;&#xA;&#xD;&#xA;A very good one is [Renderdoc][1] which is both completely free and opensource. Also it is actively supported. &#xD;&#xA;&#xD;&#xA;Another one is [Intel GPA][2] that unfortunately, according to its webpage, support up to OGL 3.3 Core. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Just for the sake of adding one more, I used to use [gDEBugger][3], but it has passed long since the last update. This has evolved into [AMD CodeXL][4] that unfortunately I never used.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/baldurk/renderdoc&#xD;&#xA;  [2]: https://software.intel.com/en-us/gpa/details&#xD;&#xA;  [3]: http://www.gremedy.com/&#xD;&#xA;  [4]: http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/" ContentLicense="CC BY-SA 3.0" />
  <row Id="78" PostHistoryTypeId="2" PostId="26" RevisionGUID="7ad71c8a-15c2-4c99-abe5-6092ca1daf29" CreationDate="2015-08-04T21:35:01.103" UserId="79" Text="To directly answer the question: Simplex noise is [patented](https://www.google.com/patents/US6867776), whereas Perlin noise is not. Other than that, Simplex noise has many advantages that are already mentioned in your question, and apart from the slightly increased implementation difficulty, it is the better algorithm of the two.&#xD;&#xA;&#xD;&#xA;I believe the reason why many people still pick Perlin noise is simply because it's more widely known. It's also worth noting that Perlin noise is very frequently confused with a combination of [value noise](https://en.wikipedia.org/wiki/Value_noise) and Fractal Brownian Motion (FBM).&#xD;&#xA;&#xD;&#xA;Perlin noise, Simplex noise and value noise are all methods for synthesizing coherent noise. On the other hand, FBM (sometimes called &quot;FBM noise&quot;), is what is used when adding multiple layers of noise on top of each other at different scales to obtain more complex functions. The combination of FBM and value noise is simple to implement and can be very useful for terrain synthesis, procedural clouds and friends, and it is quite popular. However, it tends to be mistakenly labelled Perlin noise, misleadingly adding to its popularity." ContentLicense="CC BY-SA 3.0" />
  <row Id="80" PostHistoryTypeId="2" PostId="27" RevisionGUID="48911fe6-a0b6-424c-876f-ea5d58b1beb8" CreationDate="2015-08-04T21:47:25.783" UserId="137" Text="Both Vulkan and DirectX12 are claimed to be usable in a thread-safe manner. People seem to be excited about that.&#xD;&#xA;&#xD;&#xA;Why is this considered such a huge feature? The &quot;real&quot; processing gets thrown over the memory bridge on a separate processing unit anyway. &#xD;&#xA;&#xD;&#xA;Also if it is so big, why is it not until now that a thread safe Graphics API came out?" ContentLicense="CC BY-SA 3.0" />
  <row Id="81" PostHistoryTypeId="1" PostId="27" RevisionGUID="48911fe6-a0b6-424c-876f-ea5d58b1beb8" CreationDate="2015-08-04T21:47:25.783" UserId="137" Text="Why is thread safety such a huge deal for Graphics APIs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="82" PostHistoryTypeId="3" PostId="27" RevisionGUID="48911fe6-a0b6-424c-876f-ea5d58b1beb8" CreationDate="2015-08-04T21:47:25.783" UserId="137" Text="|directx12|" ContentLicense="CC BY-SA 3.0" />
  <row Id="84" PostHistoryTypeId="2" PostId="28" RevisionGUID="5b1501fd-15bc-4607-b734-1ba8f718ad2d" CreationDate="2015-08-04T22:20:07.923" UserId="64" Text="The main gain would be that it would be easier to divide CPU tasks into multiple threads, without having to solve all the difficult issues with accessing the graphics API. Normally you either would have to make the context current (which might have bad performance implications) or provide a queue and call the graphics api in a single thread. I don't think that any performance is gained this way, because the GPU indeed processes them sequentially anyway, but it makes the developer job a lot easier.&#xD;&#xA;&#xD;&#xA;The reason that it was not done until now probably is because directx and opengl were created in a time where multithreading was not really apparent. Also the Khronos board is very conservative in changing the API. Their view on Vulkan is also that it will coexist next to OpenGL, because both serve different purposes. It probably was not until recently that paralism became so important, as consumers get access to more and more processors." ContentLicense="CC BY-SA 3.0" />
  <row Id="85" PostHistoryTypeId="5" PostId="23" RevisionGUID="27ff767f-b139-463b-9439-86e73fcda570" CreationDate="2015-08-04T22:29:28.113" UserId="54" Comment="Added code formatting to function names; split the question into paragraphs to make it easier to read." Text="I have a point cloud that is being rendered to the screen. Each point has its position and color as well as an ID.&#xD;&#xA;&#xD;&#xA;I was asked to render the IDs for each point to a texture so I created a FBO and attached two textures, one for color and one for depth. I created the necessary VAO and VBO for this off-screen rendering and uploaded for each point its position and ID.&#xD;&#xA;&#xD;&#xA;Once the rendering to the FBO is done, I read the pixels of the color-texture with `glReadPixels()` to see what the values are, but they seem to be all cleared out, i.e., the value they have is the same as `glClearColor()`.&#xD;&#xA;&#xD;&#xA;Is there a way I can debug what it is being render to the color texture of my FBO? Any tips that you may provide are very welcomed." ContentLicense="CC BY-SA 3.0" />
  <row Id="86" PostHistoryTypeId="24" PostId="23" RevisionGUID="27ff767f-b139-463b-9439-86e73fcda570" CreationDate="2015-08-04T22:29:28.113" Comment="Proposed by 54 approved by 116 edit id of 7" ContentLicense="CC BY-SA 3.0" />
  <row Id="87" PostHistoryTypeId="5" PostId="28" RevisionGUID="7e673c01-93e9-4bd6-b143-ee21da3ea575" CreationDate="2015-08-04T22:29:59.053" UserId="64" Comment="added 297 characters in body" Text="The main gain would be that it would be easier to divide CPU tasks into multiple threads, without having to solve all the difficult issues with accessing the graphics API. Normally you either would have to make the context current (which might have bad performance implications) or provide a queue and call the graphics api in a single thread. I don't think that any performance is gained this way, because the GPU indeed processes them sequentially anyway, but it makes the developer job a lot easier.&#xD;&#xA;&#xD;&#xA;The reason that it was not done until now probably is because directx and opengl were created in a time where multithreading was not really apparent. Also the Khronos board is very conservative in changing the API. Their view on Vulkan is also that it will coexist next to OpenGL, because both serve different purposes. It probably was not until recently that paralism became so important, as consumers get access to more and more processors.&#xD;&#xA;&#xD;&#xA;EDIT: I don't mean that no performance is gained from doing work in multiple CPUs, it is not useful to split your calls into multiple threads to create textures/shaders faster. Rather the performance is gained due to having more processors busy and keeping the gpu busy with things to perform." ContentLicense="CC BY-SA 3.0" />
  <row Id="88" PostHistoryTypeId="2" PostId="29" RevisionGUID="58994817-47a4-49ff-bff3-67abc7eee802" CreationDate="2015-08-04T23:00:18.923" UserId="56" Text="It turns out that no, while you can use bicubic Lagrange interpolation for bicubic texture sampling, it isn't the highest quality option, and probably not actually likely to be used.&#xD;&#xA;&#xD;&#xA;Cubic hermite splines are a better tool for the job.&#xD;&#xA;&#xD;&#xA;Lagrange interpolation will make a curve that passes through the data points, thus preserving C0 continuity, but hermite splines preserve the derivatives at the edges while also passing through the data points, thus preserving C1 continuity and looking much better.&#xD;&#xA;&#xD;&#xA;This question has some great info on cubic hermite splines:&#xD;&#xA;http://dsp.stackexchange.com/questions/18265/bicubic-interpolation" ContentLicense="CC BY-SA 3.0" />
  <row Id="89" PostHistoryTypeId="2" PostId="30" RevisionGUID="3e64afde-4d41-4a95-b664-baa0b229ed17" CreationDate="2015-08-04T23:43:22.107" UserId="159" Text="In addition to cifz's response, you could also use glBlitFramebuffer() to transfer pixels from a framebuffer to a window.&#xD;&#xA;&#xD;&#xA;    // XXX WARNING: Untested code follows&#xD;&#xA;&#xD;&#xA;    // Blit from fbo...&#xD;&#xA;    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);&#xD;&#xA;    // ...to the front buffer.&#xD;&#xA;    glBindFramebuffer(GL_WRITE_FRAMEBUFFER, GL_FRONT);&#xD;&#xA;&#xD;&#xA;    GLsizei HalfWindowWidth = (GLsizei)(WindowWidth / 2.0f);&#xD;&#xA;    GLsizei HalfWindowHeight = (GLsizei)(WindowHeight / 2.0f);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 0 to the upper-left quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT0);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      0, 0, HalfWidth, HalfHeight, GL_COLOR_BUFFER_BIT,&#xD;&#xA;                      GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 1 to the upper-right quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT1);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      HalfWidth, 0, WindowWidth, HalfHeight, GL_COLOR_BUFFER_BIT,&#xD;&#xA;                      GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // ...and so on. You can even switch FBOs if you like.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="90" PostHistoryTypeId="2" PostId="31" RevisionGUID="a9ba57ae-243e-479b-8e2d-688a93a5ec3c" CreationDate="2015-08-05T00:01:57.733" UserId="157" Text="There are 2 main factors that seem to lead to [digital artifacts][1] when creating JPEG images: Aliasing and Compression.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;&gt; Converting a PNG with characters on it to a JPEG or placing vector images over a photograph, will result in pixelization on their edges. The antialiasing generally creates a kind of blur around them, but if the image is [lossy compressed][2], part of the details are also lost, therefore the blur and the pixelization may become less noticeable.&#xD;&#xA;&#xD;&#xA;Is this the right thing to do? I.e. since a lossless compression generates a highly detailed image, the artifacts resulting from aliasing will be more noticeable, so a balance may be found by using the right compression, although compromising the image quality.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Digital_artifact&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lossy_compression" ContentLicense="CC BY-SA 3.0" />
  <row Id="91" PostHistoryTypeId="1" PostId="31" RevisionGUID="a9ba57ae-243e-479b-8e2d-688a93a5ec3c" CreationDate="2015-08-05T00:01:57.733" UserId="157" Text="When creating a JPEG, how can I minimize the occurence of artifacts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="92" PostHistoryTypeId="3" PostId="31" RevisionGUID="a9ba57ae-243e-479b-8e2d-688a93a5ec3c" CreationDate="2015-08-05T00:01:57.733" UserId="157" Text="|image|compression|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="93" PostHistoryTypeId="5" PostId="30" RevisionGUID="906babdf-421e-4a16-bf4d-ae49a5f24c9c" CreationDate="2015-08-05T00:06:22.133" UserId="159" Comment="added 64 characters in body" Text="In addition to cifz's response, another way to visualise FBOs which doesn't cost very much code is to use glBlitFramebuffer() to transfer pixels from a framebuffer to a window.&#xD;&#xA;&#xD;&#xA;    // XXX WARNING: Untested code follows&#xD;&#xA;&#xD;&#xA;    // Blit from fbo...&#xD;&#xA;    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);&#xD;&#xA;    // ...to the front buffer.&#xD;&#xA;    glBindFramebuffer(GL_WRITE_FRAMEBUFFER, GL_FRONT);&#xD;&#xA;&#xD;&#xA;    GLsizei HalfWindowWidth = (GLsizei)(WindowWidth / 2.0f);&#xD;&#xA;    GLsizei HalfWindowHeight = (GLsizei)(WindowHeight / 2.0f);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 0 to the upper-left quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT0);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      0, 0, HalfWidth, HalfHeight, GL_COLOR_BUFFER_BIT,&#xD;&#xA;                      GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 1 to the upper-right quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT1);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      HalfWidth, 0, WindowWidth, HalfHeight, GL_COLOR_BUFFER_BIT,&#xD;&#xA;                      GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // ...and so on. You can switch FBOs if you have more than one.&#xD;&#xA;&#xD;&#xA;There are a few obvious &quot;gotchas&quot;, in that HDR buffers probably won't visualise the way you expect them to, you probably can't &quot;see&quot; depth/stencil buffers in the obvious way, and if the size of the FBO doesn't match the area being blitted to, the magnification/minification method might be extremely naive.&#xD;&#xA;&#xD;&#xA;But as quick 'n dirty hacks go, it's pretty good." ContentLicense="CC BY-SA 3.0" />
  <row Id="94" PostHistoryTypeId="5" PostId="30" RevisionGUID="9784acd8-8f4e-400f-a694-406d47b3b39a" CreationDate="2015-08-05T00:11:28.870" UserId="159" Comment="added 64 characters in body" Text="In addition to cifz's response, another way to visualise FBOs which doesn't cost very much code is to use glBlitFramebuffer() to transfer pixels from a framebuffer to a window.&#xD;&#xA;&#xD;&#xA;    // XXX WARNING: Untested code follows&#xD;&#xA;&#xD;&#xA;    // Blit from fbo...&#xD;&#xA;    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);&#xD;&#xA;    // ...to the front buffer.&#xD;&#xA;    glBindFramebuffer(GL_WRITE_FRAMEBUFFER, GL_FRONT);&#xD;&#xA;&#xD;&#xA;    GLsizei HalfWindowWidth = (GLsizei)(WindowWidth / 2.0f);&#xD;&#xA;    GLsizei HalfWindowHeight = (GLsizei)(WindowHeight / 2.0f);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 0 to the upper-left quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT0);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      0, 0, HalfWindowWidth, HalfWindowHeight, GL_COLOR_BUFFER_BIT,&#xD;&#xA;                      GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 1 to the upper-right quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT1);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      HalfWindowWidth, 0, WindowWidth, HalfWindowHeight, GL_COLOR_BUFFER_BIT,&#xD;&#xA;                      GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // ...and so on. You can switch FBOs if you have more than one.&#xD;&#xA;&#xD;&#xA;There are a few obvious &quot;gotchas&quot;, in that HDR buffers probably won't visualise the way you expect them to, you probably can't &quot;see&quot; depth/stencil buffers in the obvious way, and if the size of the FBO doesn't match the area being blitted to, the magnification/minification method might be extremely naive.&#xD;&#xA;&#xD;&#xA;But as quick 'n dirty hacks go, it's pretty good." ContentLicense="CC BY-SA 3.0" />
  <row Id="95" PostHistoryTypeId="5" PostId="30" RevisionGUID="380b9fd1-27db-42f3-b703-5acf9ce5fba7" CreationDate="2015-08-05T00:26:44.483" UserId="159" Comment="added 13 characters in body" Text="In addition to cifz's response, another way to visualise FBOs which doesn't cost very much code is to use glBlitFramebuffer() to transfer pixels from a framebuffer to a window.&#xD;&#xA;&#xD;&#xA;    // XXX WARNING: Untested code follows&#xD;&#xA;&#xD;&#xA;    // Blit from fbo...&#xD;&#xA;    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);&#xD;&#xA;    // ...to the front buffer.&#xD;&#xA;    glBindFramebuffer(GL_WRITE_FRAMEBUFFER, GL_FRONT);&#xD;&#xA;&#xD;&#xA;    GLsizei HalfWindowWidth = (GLsizei)(WindowWidth / 2.0f);&#xD;&#xA;    GLsizei HalfWindowHeight = (GLsizei)(WindowHeight / 2.0f);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 0 to the lower-left quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT0);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      0, 0, HalfWindowWidth, HalfWindowHeight,&#xD;&#xA;                      GL_COLOR_BUFFER_BIT, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // Blit attachment 1 to the lower-right quadrant of the window&#xD;&#xA;    glReadBuffer(GL_COLOR_ATTACHMENT1);&#xD;&#xA;    glBlitFramebuffer(0, 0, FboWidth, FboHeight,&#xD;&#xA;                      HalfWindowWidth, 0, WindowWidth, HalfWindowHeight,&#xD;&#xA;                      GL_COLOR_BUFFER_BIT, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    // ...and so on. You can switch FBOs if you have more than one to read from.&#xD;&#xA;&#xD;&#xA;There are a few obvious &quot;gotchas&quot;, in that HDR buffers probably won't visualise the way you expect them to, you probably can't &quot;see&quot; depth/stencil buffers in the obvious way, and if the size of the FBO doesn't match the area being blitted to, the magnification/minification method might be extremely naive.&#xD;&#xA;&#xD;&#xA;But as quick 'n dirty hacks go, it's pretty good." ContentLicense="CC BY-SA 3.0" />
  <row Id="96" PostHistoryTypeId="2" PostId="32" RevisionGUID="771ee9bb-9f7c-4e77-a952-89ec95a1f67b" CreationDate="2015-08-05T01:13:26.897" UserId="17" Text="From my basic understanding, a Vertex Buffer Object works something like this (psuedo code):&#xD;&#xA;&#xD;&#xA;&gt; Normally, if one wanted to say, draw a square, one could issue line drawing commands.&#xD;&#xA;&#xD;&#xA;&gt;     line (0, 0) -&gt; (1, 0)&#xD;&#xA;&gt;     line (1, 0) -&gt; (1, 1)&#xD;&#xA;&gt;     line (1, 1) -&gt; (0, 1)&#xD;&#xA;&gt;     line (0, 1) -&gt; (0, 0)&#xD;&#xA;&#xD;&#xA;&gt; Using a Vertex Buffer Object, if I understand correctly, would load the vertices into a Vertex Buffer Object.&#xD;&#xA;&#xD;&#xA;&gt;     define VBO&#xD;&#xA;&gt;     load (0,0) -&gt; VBO&#xD;&#xA;&gt;     load (1,0) -&gt; VBO&#xD;&#xA;&gt;     load (1,1) -&gt; VBO&#xD;&#xA;&gt;     load (0,1) -&gt; VBO&#xD;&#xA;&gt;     load (0,0) -&gt; VBO&#xD;&#xA;&#xD;&#xA;&gt; Then you can issue one drawing command.&#xD;&#xA;&#xD;&#xA;&gt;     draw VBO vertices&#xD;&#xA;    &#xD;&#xA;While I understand how Vertex Buffer Objects work, I don't know why they improve performance. &#xD;&#xA;&#xD;&#xA;How do Vertex Buffer Objects improve performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="97" PostHistoryTypeId="1" PostId="32" RevisionGUID="771ee9bb-9f7c-4e77-a952-89ec95a1f67b" CreationDate="2015-08-05T01:13:26.897" UserId="17" Text="Why do Vertex Buffer Objects improve performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="98" PostHistoryTypeId="3" PostId="32" RevisionGUID="771ee9bb-9f7c-4e77-a952-89ec95a1f67b" CreationDate="2015-08-05T01:13:26.897" UserId="17" Text="|performance|rendering|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="99" PostHistoryTypeId="2" PostId="33" RevisionGUID="f8b876c2-d0fb-44f8-8cdd-5757b1bd7d13" CreationDate="2015-08-05T01:34:47.203" UserId="174" Text="In general, when you render an object in an immediate mode—issuing line drawing commands for instance—you build up a series of commands that you submit to the graphics card to draw. If you're drawing a lot of data, or drawing very frequently, you can waste a lot of time sending this data over and over again.&#xD;&#xA;&#xD;&#xA;A vertex buffer allows you to produce a single object that you submit to the graphics card once. If you don't need to change your geometry, you can leave it on the graphics card and simply send the graphics card a request to draw that object. Since it avoids the copy every time you draw, there's much less overhead for each draw.&#xD;&#xA;&#xD;&#xA;Note that using a vertex buffer object doesn't always provide a very significant speedup. If you're only drawing the object once per frame, and you're replacing the geometry in between each frame, then you don't get the benefits of avoiding the copy each frame.&#xD;&#xA;&#xD;&#xA;Most of my experience comes from writing programs using graphics APIs like OpenGL, so someone who's messed with the backend of a graphics driver can probably provide a more detailed answer, but I hope this makes things a bit clearer." ContentLicense="CC BY-SA 3.0" />
  <row Id="100" PostHistoryTypeId="2" PostId="34" RevisionGUID="e27ef713-4f43-45c6-b8cb-193f2bd86490" CreationDate="2015-08-05T01:36:09.247" UserId="144" Text="By using an immediate mode interface (e.g. old style OpenGL glBegin()/glEnd()/glVertex()) you're effectively drip feeding data to the driver one piece at a time. It then has to take that single piece of data, reformat it and pass it on to the hardware (which these days means putting it into a command buffer).&#xD;&#xA;&#xD;&#xA;By using a vertex buffer object, you're providing a (hopefully) large block of data to the driver ahead of when it needs to be used. It can perform a number of optimizations (reformatting, placing into video memory) as well as not having to feed the GPU piecemeal.&#xD;&#xA;&#xD;&#xA;In practice if you're only drawing a small number of primitives then it probably won't make much difference, however if you're drawing a multi-million triangle mesh then VBOs in video memory are the way to go.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="103" PostHistoryTypeId="2" PostId="35" RevisionGUID="047f60c9-fbd8-44a6-8a3d-c744bb6476ab" CreationDate="2015-08-05T02:23:49.107" UserId="182" Text="If what you are interested in is the area, you could downsize the stencil buffer until you reach one pixel and deduce that area from its color.&#xD;&#xA;&#xD;&#xA;Steps would be:&#xD;&#xA;&#xD;&#xA; - Copy the stencil to a texture, using a format with enough precision.&#xD;&#xA; - Load a shader that outputs a color proportional to the number of texels with a given color.&#xD;&#xA; - Ping-pong between to framebuffers to reduce the size by half until reaching one pixel.&#xD;&#xA; - The color of the pixel is the percentage of the viewport covered by the area: just multiply it by the area of the viewport." ContentLicense="CC BY-SA 3.0" />
  <row Id="104" PostHistoryTypeId="2" PostId="36" RevisionGUID="94470f43-6bc2-4c9e-8655-6c1b4870d869" CreationDate="2015-08-05T02:55:44.850" UserId="182" Text="There are two steps that make the VBO more efficient than immediate mode.&#xD;&#xA;&#xD;&#xA;Immediate mode ([glBegin/glEnd][1], [glVertex*][2], etc.) means that at each frame, you spoon feed the vertices, attribute per attribute (position, normal, color, etc.), to the driver, which then reformats them and finally sends the whole package as a command to the GPU.&#xD;&#xA;&#xD;&#xA;By using vertex arrays (see [glDrawArrays][3], [glDrawElements][4], [glVertexPointer][5], etc.), you can give the driver the whole thing at once and save it the burden of reformatting the vertices. You're effectively replacing several function calls per vertex by just a handful of calls for the whole mesh. But you still need to do that once a frame.&#xD;&#xA;&#xD;&#xA;VBO (see [glGenBuffers][6], [glBindBuffer][7], etc.) go one step further and store the data on the GPU side: you send it only once, and then just refer to it by a handle. You save bandwidth by not sending the same data over and over at each frame.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man2/xhtml/glVertex.xml&#xD;&#xA;  [3]: https://www.opengl.org/sdk/docs/man/html/glDrawArrays.xhtml&#xD;&#xA;  [4]: https://www.opengl.org/sdk/docs/man/html/glDrawElements.xhtml&#xD;&#xA;  [5]: https://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml&#xD;&#xA;  [6]: https://www.opengl.org/sdk/docs/man/html/glGenBuffers.xhtml&#xD;&#xA;  [7]: https://www.opengl.org/sdk/docs/man/html/glBindBuffer.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="105" PostHistoryTypeId="2" PostId="37" RevisionGUID="fa40a540-136d-4aa2-acff-b6ee4008f801" CreationDate="2015-08-05T03:23:24.500" UserId="182" Text="Programmers are supposed to have a fairly good idea of the cost of certain operations: for example the cost of an instruction on CPU, the cost of a L1, L2, or L3 cache miss, the cost of a LHS.&#xD;&#xA;&#xD;&#xA;When it comes to graphics, I realize I have little to no idea what they are. I have in mind that if we order them by cost, state changes are something like:&#xD;&#xA;&#xD;&#xA;1. Shader uniform change.&#xD;&#xA;1. Active vertex buffer change.&#xD;&#xA;1. Active texture unit change.&#xD;&#xA;1. Active shader program change.&#xD;&#xA;1. Active frame buffer change.&#xD;&#xA;&#xD;&#xA;But that is a very rough rule of thumb, it might not even be correct, and I have no idea what are the orders of magnitude. If we try to put units, ns, clock cycles or number of instructions, how much are we talking about?" ContentLicense="CC BY-SA 3.0" />
  <row Id="106" PostHistoryTypeId="1" PostId="37" RevisionGUID="fa40a540-136d-4aa2-acff-b6ee4008f801" CreationDate="2015-08-05T03:23:24.500" UserId="182" Text="What is the cost of changing state?" ContentLicense="CC BY-SA 3.0" />
  <row Id="107" PostHistoryTypeId="3" PostId="37" RevisionGUID="fa40a540-136d-4aa2-acff-b6ee4008f801" CreationDate="2015-08-05T03:23:24.500" UserId="182" Text="|gpu|optimisation|cost|" ContentLicense="CC BY-SA 3.0" />
  <row Id="109" PostHistoryTypeId="2" PostId="38" RevisionGUID="2d6e0c8f-8a72-498a-9e36-8a97d15c276c" CreationDate="2015-08-05T03:41:52.363" UserId="104" Text="Tiled rendering is used in modern mobile GPU architectures to increase the coherency of memory access by subdividing image space into a regular grid of small (e.g., 32x32 pixel) tiles. Information is scarce on the types of data structures used to track the primitives that are associated with each tile, considering that arbitrarily many primitives may overlap any given tile. &#xD;&#xA;&#xD;&#xA;From the perspective of a driver developer, what data structures are commonly used to represent the primitive sets that belong to a tile, and are such structures dynamically allocated/resized according to the geometry that overlaps a particular tile?" ContentLicense="CC BY-SA 3.0" />
  <row Id="110" PostHistoryTypeId="1" PostId="38" RevisionGUID="2d6e0c8f-8a72-498a-9e36-8a97d15c276c" CreationDate="2015-08-05T03:41:52.363" UserId="104" Text="Data structures for tile-based (deferred) rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="111" PostHistoryTypeId="3" PostId="38" RevisionGUID="2d6e0c8f-8a72-498a-9e36-8a97d15c276c" CreationDate="2015-08-05T03:41:52.363" UserId="104" Text="|tile-based-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="112" PostHistoryTypeId="6" PostId="37" RevisionGUID="c572d045-a55a-4da6-94dd-8723c69c35e1" CreationDate="2015-08-05T03:51:09.420" UserId="17" Comment="Re-tagged with performance" Text="|performance|gpu|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="113" PostHistoryTypeId="24" PostId="37" RevisionGUID="c572d045-a55a-4da6-94dd-8723c69c35e1" CreationDate="2015-08-05T03:51:09.420" Comment="Proposed by 17 approved by 182 edit id of 8" ContentLicense="CC BY-SA 3.0" />
  <row Id="114" PostHistoryTypeId="2" PostId="39" RevisionGUID="34a12f18-8628-4376-b810-b685ca2c88ab" CreationDate="2015-08-05T03:58:22.973" UserId="56" Text="I've read that blur is done in real time graphics by doing it on one axis and then the other.&#xA;&#xA;I've done a bit of convolution in 1d in the past but am not super comfortable with it, nor know what to convolve in this case exactly.&#xA;&#xA;Can anyone explain in plain terms how a 2d Gaussian Blur of an image is done?&#xA;&#xA;I've also heard that the radius of the Blur can impact performance, is that due to having to do a larger convolution?&#xA;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="115" PostHistoryTypeId="1" PostId="39" RevisionGUID="34a12f18-8628-4376-b810-b685ca2c88ab" CreationDate="2015-08-05T03:58:22.973" UserId="56" Text="How is Gaussian Blur Implemented?" ContentLicense="CC BY-SA 3.0" />
  <row Id="116" PostHistoryTypeId="3" PostId="39" RevisionGUID="34a12f18-8628-4376-b810-b685ca2c88ab" CreationDate="2015-08-05T03:58:22.973" UserId="56" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="118" PostHistoryTypeId="2" PostId="40" RevisionGUID="106397ce-084a-4cc2-b399-0e21afb942d4" CreationDate="2015-08-05T04:32:27.193" UserId="174" Text="In general, a convolution is performed by taking the integral of the product of two functions in a sliding window, but if you're not from a math background, that's not a very helpful explanation, and certainly won't give you a useful intuition for it. More intuitively, a convolution allows multiple points in an input signal to affect a single point on an output signal.&#xD;&#xA;&#xD;&#xA;Since you're not super comfortable with convolutions, let's first review  what a convolution means in a discrete context like this, and then go over a simpler blur.&#xD;&#xA;&#xD;&#xA;In our discrete context, we can multiply our two signals by simply multiplying each corresponding sample. The integral is also simple to do discretely, we just add up each sample in the interval we're integrating over. One simple discrete convolution is computing a moving average. If you want to take the moving average of 10 samples, this can be thought of as convolving your signal by a distribution 10 samples long and 0.1 tall, each sample in the window first gets multiplied by 0.1, then all 10 are added together to produce the average. This also reveals an interesting and important distinction, when you're blurring with a convolution, the distribution that you use should sum to 1.0 over all its samples, otherwise it will increase or decrease the overall brightness of the image when you apply it. If the distribution for our average had been 1 over its whole interval, then the total signal would be 10x brighter after the convolution.&#xD;&#xA;&#xD;&#xA;Now that we've looked at convolutions, we can move on to blurs. A Gaussian blur is implemented by convolving an image by a Gaussian distribution. Other blurs are generally implemented by convolving the image by other distributions. The simplest blur is the box blur, and it uses the same distribution we described above, a box with unit area. If we want to blur a 10x10 area, then we multiply each sample in the box by 0.01, and then sum them all together to produce the center pixel. We still need to ensure that the total sum of all the samples in our blur distribution are 1.0 to make sure the image doesn't get brighter or darker.&#xD;&#xA;&#xD;&#xA;A gaussian blur follows the same broad procedure as a box blur, but it uses a more complex formula to determine the weights. The distribution can be computed based on the distance from the center `r`, by evaluating `exp(-x*x/2)/sqrt(2*pi)`. The sum of all the samples in a gaussian will eventually be approximately 1.0 if you sample every single pixel, but the fact that a gaussian has infinite support (it has values everywhere) means that you need to use a slightly modified version that sums to 1.0 using only a few values.&#xD;&#xA;&#xD;&#xA;Of course both of these processes can be very expensive if you perform them on a very large radius, since you need to sample a lot of pixels in order to compute the blur. This is where the final trick comes in: both a gaussian blur and a box blur are what's called a &quot;seperable&quot; blur. This means that if you perform the blur along one axis, and then perform it along the other axis, it produces the exact same result as if you'd performed it along both axes at the same time. This can be tremendously important. If your blur is 10px across, it requires 100 samples in the naive form, but only 20 when separated. The difference only gets bigger, since the combined blur is `O(n^2)`, while the separated form in `O(n)`." ContentLicense="CC BY-SA 3.0" />
  <row Id="119" PostHistoryTypeId="2" PostId="41" RevisionGUID="94e6fa75-cad4-4507-b425-f673b6053bc9" CreationDate="2015-08-05T04:46:43.567" UserId="194" Text="In convolution, two mathematical functions are combined to produce a third function. In image processing functions are usually called kernels. A kernel is nothing more than a (square) array of pixels (a small image so to speak). Usually, the values in the kernel add up to one. This is to make sure noe energy is added or removed from the image after the operation.&#xD;&#xA;&#xD;&#xA;Specifically, a Gaussian kernal (used for Gaussian blur) is a square array of pixels where the pixel values correspond to the values of a Gaussian curve (in 2d).&#xD;&#xA;&#xD;&#xA;[![Image linked from http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm][1]][1]&#xD;&#xA;&#xD;&#xA;Each pixel in the image gets multiplied by the Gaussian kernel. This is done by placing the center pixel of the kernel on the image pixel and multiplying the values in the original image with the pixels in the kernel that overlap. The values resulting from these multiplications are added up and that result is used for the value at the destination pixel. Looking at the image, you would multiply the value at (0,0) in the input array by the value a (i) in the kernel array, the value at (1,0) in the input array by the value a (h) in the kernel array, etc. and then add all these values to get the value for (1,1) at the output image.&#xD;&#xA;&#xD;&#xA;[![Image linked from http://www.songho.ca/dsp/convolution/convolution.html][2]][2]&#xD;&#xA;&#xD;&#xA;To answer your second question first, the larger the kernel, the more expensive the operation. So, the larger the radius of the blur, the longer the operation will take.&#xD;&#xA;&#xD;&#xA;To answer your first question, as explained above, convolution can be done by multiplying each input pixel with the entire kernel. However, if the kernel is symmetrical (wich a Gaussian kernel is) you can also multiply each axis (x and y) independently, which will decrease the total number of multiplications. In proper mathematical terms, if a matrix is separable it can be decomposed into (M×1) and (1×N) matrices. For the Gaussian kernel above this means you can also use the following kernels:&#xD;&#xA;&#xD;&#xA;[![Image linked from http://dsp.stackexchange.com/questions/8501/when-should-the-sum-of-all-elements-of-a-gaussian-kernel-be-zero][3]][3]&#xD;&#xA;&#xD;&#xA;You would now multiply each pixel in the input image with both kernels and add the resulting values to get the value for the output pixel.&#xD;&#xA;&#xD;&#xA;For more information on how to see if a kernel is separable, follow this [link][4].&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Qc4Mq.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/bRN2c.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UsU96.gif&#xD;&#xA;  [4]: http://stackoverflow.com/questions/5886529/how-can-i-determine-if-my-convolution-is-separable" ContentLicense="CC BY-SA 3.0" />
  <row Id="120" PostHistoryTypeId="5" PostId="29" RevisionGUID="825dd32f-1c0c-4e4e-9be1-c823d8f33779" CreationDate="2015-08-05T04:55:47.647" UserId="56" Comment="Added code of the correct solution, and a screenshot to compare the various techniques" Text="It turns out that no, while you can use bicubic Lagrange interpolation for bicubic texture sampling, it isn't the highest quality option, and probably not actually likely to be used.&#xD;&#xA;&#xD;&#xA;Cubic hermite splines are a better tool for the job.&#xD;&#xA;&#xD;&#xA;Lagrange interpolation will make a curve that passes through the data points, thus preserving C0 continuity, but hermite splines preserve the derivatives at the edges while also passing through the data points, thus preserving C1 continuity and looking much better.&#xD;&#xA;&#xD;&#xA;This question has some great info on cubic hermite splines:&#xD;&#xA;http://dsp.stackexchange.com/questions/18265/bicubic-interpolation&#xD;&#xA;&#xD;&#xA;Here is the cubic hermite version of the code I posted in the question:&#xD;&#xA;&#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 CubicHermite (vec3 A, vec3 B, vec3 C, vec3 D, float t)&#xD;&#xA;    {&#xD;&#xA;    	float t2 = t*t;&#xD;&#xA;        float t3 = t*t*t;&#xD;&#xA;        vec3 a = -A/2.0 + (3.0*B)/2.0 - (3.0*C)/2.0 + D/2.0;&#xD;&#xA;        vec3 b = A - (5.0*B)/2.0 + 2.0*C - D / 2.0;&#xD;&#xA;        vec3 c = -A/2.0 + C/2.0;&#xD;&#xA;       	vec3 d = B;&#xD;&#xA;        &#xD;&#xA;        return a*t3 + b*t2 + c*t + d;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 BicubicHermiteTextureSample (vec2 P)&#xD;&#xA;    {&#xD;&#xA;        vec2 pixel = P * c_textureSize + 0.5;&#xD;&#xA;        &#xD;&#xA;        vec2 frac = fract(pixel);&#xD;&#xA;        pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);&#xD;&#xA;        &#xD;&#xA;        vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;&#xD;&#xA;        &#xD;&#xA;        vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;&#xD;&#xA;        vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;&#xD;&#xA;        vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 CP0X = CubicHermite(C00, C10, C20, C30, frac.x);&#xD;&#xA;        vec3 CP1X = CubicHermite(C01, C11, C21, C31, frac.x);&#xD;&#xA;        vec3 CP2X = CubicHermite(C02, C12, C22, C32, frac.x);&#xD;&#xA;        vec3 CP3X = CubicHermite(C03, C13, C23, C33, frac.x);&#xD;&#xA;        &#xD;&#xA;        return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a picture showing the difference between sampling methods.  From left to right: Nearest Neighbor, Bilinear, Lagrange Bicubic, Hermite Bicubic&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/h0Ot0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="121" PostHistoryTypeId="2" PostId="42" RevisionGUID="bcd7eccb-dc82-48c9-9338-c0709f3096aa" CreationDate="2015-08-05T05:11:19.993" UserId="182" Text="Here is the best article I've read on the topic:&#xD;&#xA;[_Efficient Gaussian blur with linear sampling_][1]. It addresses all your questions and is really accessible.&#xD;&#xA;&#xD;&#xA;For the layman very short explanation: Gaussian is a function with the nice property of being separable, which means that a 2D Gaussian function can be computed by combining two 1D Gaussian functions.&#xD;&#xA;&#xD;&#xA;So for a *n×n* size (*O(n²)*), you only need to evaluate *2×n* values (*O(n)*), which is significantly less. If your operation consists in reading a texture element (commonly called a *&quot;tap&quot;*), it is good news: less taps is cheaper because a texture fetch has a cost.&#xD;&#xA;&#xD;&#xA;That's why blurring algorithms use that property by doing two passes, one to blur horizontally by gathering the *n* horizontal pixels, and one to blur vertically by gathering the *n* vertical pixels. The result is the final blurred pixel color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/" ContentLicense="CC BY-SA 3.0" />
  <row Id="122" PostHistoryTypeId="2" PostId="43" RevisionGUID="0d4e2323-d17d-4921-b051-ee6e4a0539fa" CreationDate="2015-08-05T05:38:47.300" UserId="196" Text="The actual cost of any particular state change varies with so many factors that a general answer is nigh impossible.&#xD;&#xA;&#xD;&#xA;First, every state change can potentially have both a CPU-side cost and a GPU-side cost. The CPU cost may, depending on your driver and graphics API, be paid entirely on the main thread or partially on a background thread.&#xD;&#xA;&#xD;&#xA;Second, the GPU cost may depend on the amount of work in flight. Modern GPUs are very pipelined and love to get lots of work in flight at once, and the biggest slowdown you can get is from stalling the pipeline so that everything that's currently in flight must retire before the state changes. What can cause a pipeline stall? Well, it depends on your GPU!&#xD;&#xA;&#xD;&#xA;The thing you actually need to know to understand the performance here is: what does the driver and GPU need to do to process your state change? This of course depends on your GPU, and also on details that ISVs often don't share publicly. However, there are some **general principles**.&#xD;&#xA;&#xD;&#xA;GPUs generally are split into a frontend and a backend. The frontend handles a stream of commands generated by the driver, while the backend does all the real work. Like I said before, the backend loves to have lots of work in flight, but it needs some information to store information about that work (perhaps filled in by the frontend). If you kick enough small batches and use up all the silicon keeping track of the work, then the frontend will have to stall even if there's lots of unused horsepower sitting around. So a principle here: **the more state changes (and small draws), the more likely you are to starve the GPU backend**.&#xD;&#xA;&#xD;&#xA;While a draw is actually being processed, you're basically just running shader programs, which are doing memory accesses to fetch your uniforms, your vertex buffer data, your textures, but also the control structures that tell the shader units where your vertex buffers and your textures are. And the GPU has caches in front of those memory accesses as well. So whenever you throw new uniforms or new texture/buffer bindings at the GPU, it'll likely suffer a cache miss the first time it has to read them. Another principle: **most state changes will cause a GPU cache miss.** (This is most meaningful when you are managing constant buffers yourself: if you keep constant buffers the same between draws, then they are more likely to stay in cache on the GPU.)&#xD;&#xA;&#xD;&#xA;A big part of the cost for state changes for shader resources is the CPU side. Whenever you set a new constant buffer, the driver is most likely copying the contents of that constant buffer into a command stream for the GPU. If you set a single uniform, the driver is very likely turning that into a big constant buffer behind your back, so it has to go look up the offset for that uniform in the constant buffer, copy the value in, then mark the constant buffer as dirty so it can get copied into the command stream before the next draw call. If you bind a new texture or vertex buffer, the driver is probably copying a control structure for that resource around. Also, if you're using a discrete GPU on a multitasking OS, the driver needs to track every resource you use and when you start using it so that the kernel's GPU memory manager can guarantee that the memory for that resource is resident in the GPU's VRAM when the draw happens. Principle: **state changes make the driver shuffle memory around to generate a minimal command stream for the GPU.**&#xD;&#xA;&#xD;&#xA;When you change the current shader, you're probably causing a GPU cache miss (they have an instruction cache too!). In principle, the CPU work should be limited to putting a new command in the command stream saying &quot;use the shader.&quot; In reality, though, there's a whole mess of shader compilation to deal with. GPU drivers very often lazily compile shaders, even if you've created the shader ahead of time. More relevant to this topic, though, some states are not supported natively by the GPU hardware and are instead compiled into the shader program. One popular example is vertex formats: these may be compiled into the vertex shader instead of being separate state on the chip. So if you use vertex formats that you haven't used with a particular vertex shader before, you may now be paying a bunch of CPU cost to patch the shader and copy the shader program up to the GPU. Additionally, the driver and shader compiler may conspire to do all sorts of things to optimize the execution of the shader program. This might mean optimizing the memory layout of your uniforms and resource control structures so that they are nicely packed into adjacent memory or shader registers. So when you change shaders, it may cause the driver to look at everything you have already bound to the pipeline and repack it into an entirely different format for the new shader, and then copy that into the command stream. Principle: **changing shaders can cause a lot of CPU memory shuffling.**&#xD;&#xA;&#xD;&#xA;Frame buffer changes are probably the most implementation-dependent, but are generally pretty expensive on the GPU. Your GPU may not be able to handle multiple draw calls to different render targets at the same time, so it may need to stall the pipeline between those two draw calls. It may need to flush caches so that the render target can be read later. It may need to resolve work that it has postponed during the drawing. (It is very common to be accumulating a separate data structure along with depth buffers, MSAA render targets, and more. This may need to be finalized when you switch away from that render target. If you are on a GPU that is tile-based, like many mobile GPUs, a fairly large amount of actual shading work might need to be flushed when you switch away from a frame buffer.) Principle: **changing render targets is expensive on the GPU.**&#xD;&#xA;&#xD;&#xA;I'm sure that's all very confusing, and unfortunately it's hard to get too specific because details are often not public, but I'm hoping it's a half-decent overview of some of the things that are actually going on when you call some state changing function in your favorite graphics API." ContentLicense="CC BY-SA 3.0" />
  <row Id="123" PostHistoryTypeId="2" PostId="44" RevisionGUID="fc9d85c1-0538-43d6-8e29-597f3843b3aa" CreationDate="2015-08-05T05:47:39.463" UserId="197" Text="I've heard a lot of people working on VR talk about scanline racing and that it's supposed  to help improve latency for motion-to-photon. However, it isn't clear to me how this can be done with OpenGL. Could someone explain how scanline racing works, and how it can be implemented on modern GPUs." ContentLicense="CC BY-SA 3.0" />
  <row Id="124" PostHistoryTypeId="1" PostId="44" RevisionGUID="fc9d85c1-0538-43d6-8e29-597f3843b3aa" CreationDate="2015-08-05T05:47:39.463" UserId="197" Text="What is &quot;Scanline Racing&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="125" PostHistoryTypeId="3" PostId="44" RevisionGUID="fc9d85c1-0538-43d6-8e29-597f3843b3aa" CreationDate="2015-08-05T05:47:39.463" UserId="197" Text="|virtual-reality|scanline|" ContentLicense="CC BY-SA 3.0" />
  <row Id="126" PostHistoryTypeId="2" PostId="45" RevisionGUID="67d24fb2-3b51-40fa-8501-168754c19fe8" CreationDate="2015-08-05T05:55:08.537" UserId="196" Text="Modern GPUs generally have a single frontend section that processes an entirely linear stream of commands from the CPU. Whether this is a natural hardware design or if it simply evolved out of the days when there was a single CPU core generating commands for the GPU is debatable, but it's the reality for now. So if you generate a single linear stream of stateful commands, of course it makes sense to generate that stream linearly on a single thread on the CPU! Right?&#xD;&#xA;&#xD;&#xA;Well, modern GPUs also generally have a very flexible unified backend that can work on lots of different things at once. Generally speaking, the GPU works on vertices and pixels at fairly fine granularity. There's not a whole lot of difference between a GPU processing 1024 vertices in one draw and 512+512 vertices in two different draws.&#xD;&#xA;&#xD;&#xA;That suggests a fairly natural way to do less work: instead of throwing huge number of vertices at the GPU in a single draw call, split your model into sections, do cheap coarse culling on those sections, and submit each chunk individually if it passes the culling test. If you do it at the right granularity you should get a nice speedup!&#xD;&#xA;&#xD;&#xA;Unfortunately, in the current graphics API reality, draw calls are extremely expensive on the CPU. A simplified explanation of why: state changes on the GPU may not directly correspond to graphics API calls, so many graphics API calls simply set some state inside the driver, and the draw call that would depend on this new state goes and looks at all the state that is marked as having changed since the last draw, writes it into the command stream for the GPU, then actually initiates the draw. This is all work that is done in an attempt to get a lean and mean command stream for the GPU frontend unit.&#xD;&#xA;&#xD;&#xA;What this boils down to is that you have a **budget for draw calls which is entirely imposed by the overhead of the driver**. (I think I heard that these days you can get away with about 5,000 per frame for a 60 FPS title.) You can increase that by a large percentage by building this command stream in parallel chunks.&#xD;&#xA;&#xD;&#xA;There are other reasons too (for example, asynchronous timewarp for VR latency improvements), but this is a big one for graphics-bound games and other drawcall-heavy software (like 3D modeling packages)." ContentLicense="CC BY-SA 3.0" />
  <row Id="128" PostHistoryTypeId="2" PostId="46" RevisionGUID="ee5a04b7-3f46-49f6-8628-0326066cba1c" CreationDate="2015-08-05T06:06:19.940" UserId="48" Text="The most data I've seen is on the relative expense of various state changes is from Cass Everitt and John McDonald's [talk on reducing OpenGL API overhead](https://www.youtube.com/watch?v=-bCeNzgiJ8I&amp;list=PLckFgM6dUP2hc4iy-IdKFtqR9TeZWMPjm) from January 2014.  Their talk included this slide (at 31:55):&#xD;&#xA;&#xD;&#xA;[![Relative costs of state changes][1]][1]&#xD;&#xA;&#xD;&#xA;The talk doesn't give any more info on how they measured this (or even whether they're measuring CPU or GPU cost, or both!).  But at least it dovetails with the conventional wisdom: render target and shader program changes are the most expensive, uniform updates the least, with vertex buffers and texture changes somewhere in the middle.  The rest of their talk also has a lot of interesting wisdom about reducing state-change overhead.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JgrSc.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="133" PostHistoryTypeId="2" PostId="48" RevisionGUID="274875c5-5266-4e5e-bb0e-99346fb0ff52" CreationDate="2015-08-05T07:23:16.503" UserId="48" Text="JPEG compression involves three main steps:&#xD;&#xA;&#xD;&#xA;1. [Chroma subsampling](https://en.wikipedia.org/wiki/Chroma_subsampling). The image is converted from RGB into YCbCr color space, in which the *luma* or brightness (Y) is stored separately from the *chroma* or color components, Cb and Cr.  The Y component is kept at full resolution, but Cb and Cr are downsampled, typically to half resolution on each axis.  This exploits the fact that the human visual system is more sensitive to fine details of brightness than of color.&#xD;&#xA;&#xD;&#xA;2. [Frequency quantization.](https://en.wikipedia.org/wiki/Quantization_%28image_processing%29#Frequency_quantization_for_image_compression) The Y, Cb, and Cr images are converted into a frequency representation, by breaking them up into 8x8 blocks and applying the [discrete cosine transform](https://en.wikipedia.org/wiki/Discrete_cosine_transform) (a variant of the Fourier transform) to each block.  The result is a matrix of numbers that describe the amplitudes of different spatial frequencies in the block.  These numbers can then be quantized (rounded off to a chosen number of bits of precision). Different levels of quantization are used for different frequencies, exploiting our visual system's relatively lower sensitivity to high frequencies.  This is where the JPEG encoder's quality setting comes into play: lower qualities use coarser quantization.&#xD;&#xA;&#xD;&#xA;3. [Entropy coding](https://en.wikipedia.org/wiki/Entropy_encoding). The  quantized DCT values are passed through an entropy coder, which losslessly compresses the bit stream by using fewer bits to represent the more common values, sort of like a zip file.&#xD;&#xA;&#xD;&#xA;Steps 1 and 2 are the lossy ones, and each produces its own type of artifacts (though there is some overlap).  Chroma subsampling tends to blur sharp edges between regions of different colors.  This is particularly visible in vector art, where brightly colored shapes pick up vicious jaggies around their edges. Frequency quantization blurs fine details in general, and also creates block-shaped artifacts at low quality settings, because the DCT is done on a block-by-block basis.  It is particularly visible on text.&#xD;&#xA;&#xD;&#xA;This is why JPEG usually isn't used for images containing vector graphics or text&amp;mdash;its compression algorithms are poorly suited for those cases, although they work well for photographs and other images with complex texture and not-too-sharp edges." ContentLicense="CC BY-SA 3.0" />
  <row Id="134" PostHistoryTypeId="2" PostId="49" RevisionGUID="5c340719-5b2a-430e-abbd-2dc4fa11fd63" CreationDate="2015-08-05T08:07:39.323" UserId="48" Text="There's a lot of work needed on the CPU to set up a frame for the GPU, and a good chunk of that work is inside the graphics driver.  Prior to DX12 / Vulkan, that graphics driver work was essentially forced to be single-threaded by the design of the API.&#xD;&#xA;&#xD;&#xA;The hope is that DX12 / Vulkan lift that restriction, allowing driver work to be performed in parallel on multiple CPU threads within a frame.  This will enable more efficient use of multicore CPUs, allowing game engines to push more complex scenes without becoming CPU-bound.  That's the hope&amp;mdash;whether it will be realized in practice is something we'll have to wait to see over the next few years.&#xD;&#xA;&#xD;&#xA;To elaborate a bit: the output of a game engine renderer is a stream of DX/GL API calls that describe the sequence of operations to render a frame.  However, there's a great distance between the stream of API calls and the actual binary command buffers that the GPU hardware consumes.  The driver has to &quot;compile&quot; the API calls into the GPU's machine language, so to speak.  That isn't a trivial process&amp;mdash;it involves a lot of translation of API concepts into low-level hardware realities, validation to make sure the GPU is never set into an invalid state, wrangling memory allocations and data, tracking state changes to issue the correct low-level commands, and so on and on.  The graphics driver is responsible for all this stuff.&#xD;&#xA;&#xD;&#xA;In DX11 / GL4 and earlier APIs, this work is typically done by a single driver thread.  Even if you call the API from multiple threads (which you can do using DX11 deferred command lists, for example), it just adds some work to a queue for the driver thread to chew through later.  One big reason for this is the state tracking I mentioned before.  Many of the hardware-level GPU configuration details require knowledge of the current graphics pipeline state, so there's no good way to break up the command list into chunks that can be processed in parallel&amp;mdash;each chunk would have to know exactly what state it should start with, even though the previous chunk hasn't been processed yet.&#xD;&#xA;&#xD;&#xA;That's one of the big things that changed in DX12 / Vulkan.  For one thing, they incorporate almost all the graphics pipeline state into one object, and for another (at least in DX12) when you start creating a command list you *must* provide an initial pipeline state; the state isn't inherited from one command list to the next.  In principle, this allows the driver not to have to know anything about previous command lists before it can start compiling&amp;mdash;and that in turn allows the application to break up its rendering into parallelizable chunks, producing fully-compiled command lists, which can then be concatenated together and sent to the GPU with a minimum of fuss.&#xD;&#xA;&#xD;&#xA;Of course, there are many other changes in the new APIs, but as far as multithreading goes, that's the most important part." ContentLicense="CC BY-SA 3.0" />
  <row Id="136" PostHistoryTypeId="2" PostId="50" RevisionGUID="24451e9a-0f72-4192-b7fd-3c12fb2d2c2a" CreationDate="2015-08-05T08:13:38.827" UserId="197" Text="In traditional computer graphics, most 3D models are rendered by rasterizing or ray tracing against a subdivided mesh of primitives, usually triangles or quads. [More recently](https://docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/RayTracedDistanceFieldShadowing/index.html), some real-time techniques have been predicated on ray-tracing against signed distance fields (SDFs). Intuitively, these distance fields cannot be the same triangles and quads of traditional rendering and must be something like 3D geometric primitives (cubes, spheres, etc.) in order to get proper shading. Is this true? If not, can complex scenes of &quot;traditional&quot; 3D models be represented using SDFs? If it is true, then how do artists create high-detail models used in SDF renderers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="137" PostHistoryTypeId="1" PostId="50" RevisionGUID="24451e9a-0f72-4192-b7fd-3c12fb2d2c2a" CreationDate="2015-08-05T08:13:38.827" UserId="197" Text="Asset creation for signed distance field rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="138" PostHistoryTypeId="3" PostId="50" RevisionGUID="24451e9a-0f72-4192-b7fd-3c12fb2d2c2a" CreationDate="2015-08-05T08:13:38.827" UserId="197" Text="|raytracing|signed-distance-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="139" PostHistoryTypeId="2" PostId="51" RevisionGUID="75f28b79-4906-4f1d-a0cc-e4bc9078ea12" CreationDate="2015-08-05T08:19:21.280" UserId="16" Text="I would like to generate procedural noise on the surface of a sphere (e.g. to procedurally generate planets or marble-textured balls). Of course, I could just take a standard noise algorithm and map it onto the sphere, but this has all the issues of projecting a plane onto a sphere, like distortions on the poles or elsewhere.&#xD;&#xA;&#xD;&#xA;I suppose I could generate volume noise and &quot;cut out&quot; the sphere, but this seems unnecessarily inefficient - and if the noise has some grid-based artefacts, these would still not appear uniformly on the sphere. Furthermore, at least in the case of Simplex noise, cutting 2D slices out of 3D noise generally looks different than generating 2D noise right away.&#xD;&#xA;&#xD;&#xA;Is there any way to avoid these issues, e.g. by generating noise natively on the sphere? The noise should have at least the quality of [Perlin noise](https://en.wikipedia.org/wiki/Perlin_noise), ideally that of [Simplex noise](https://en.wikipedia.org/wiki/Simplex_noise)." ContentLicense="CC BY-SA 3.0" />
  <row Id="140" PostHistoryTypeId="1" PostId="51" RevisionGUID="75f28b79-4906-4f1d-a0cc-e4bc9078ea12" CreationDate="2015-08-05T08:19:21.280" UserId="16" Text="How can I generate procedural noise on a sphere?" ContentLicense="CC BY-SA 3.0" />
  <row Id="141" PostHistoryTypeId="3" PostId="51" RevisionGUID="75f28b79-4906-4f1d-a0cc-e4bc9078ea12" CreationDate="2015-08-05T08:19:21.280" UserId="16" Text="|projections|noise|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="142" PostHistoryTypeId="2" PostId="52" RevisionGUID="1b72ad9b-e64d-4c26-a276-a4feeca09d0b" CreationDate="2015-08-05T08:40:01.477" UserId="79" Text="Signed distance fields are popular in minimal graphics applications, such as the demo scene, where interesting objects can be synthesized from few simple analytic primitives such as spheres or cubes. However, signed distance fields are not restricted to these simple objects, and they do not necessarily need to be designed by a human. For example, you can synthesize the analytic signed distance field of a triangle mesh without any artist interaction - the SDF is just the signed distance to the closest triangle after all, which can be easily computed. This allows you to keep using your traditional mesh pipeline while also using SDFs in the background.&#xD;&#xA;&#xD;&#xA;In the case of the Unreal Engine, the SDF is precomputed automatically once for all static meshes and is then sampled into a low-resolution 3D texture. It can then be cheaply evaluated everywhere using a simple texture lookup, allowing them to do soft shadows and similar at runtime. [This Unreal presentation](http://www.nvidia.com/content/pdf/gdc2011/epic.pdf) at GDC 2011 mentions the 3D textures briefly (slide 27)." ContentLicense="CC BY-SA 3.0" />
  <row Id="143" PostHistoryTypeId="2" PostId="53" RevisionGUID="89958d6e-875c-43f2-9435-0ae8e2394fab" CreationDate="2015-08-05T09:04:59.070" UserId="48" Text="When your GPU displays a new frame on the screen, it transfers the image over the HDMI cable (or whatever kind) in a process called &quot;scanout&quot;.  The pixels are sent out in linear order, usually left-to-right and top-to-bottom.  The process is timed so that it takes most of the duration of a refresh interval to do this.  For instance, at 60Hz, one frame is ~17 ms.  Each scanout will take probably around 15-16 ms, with 1-2 ms of vblank in between (the exact values vary according to the display and video mode).&#xD;&#xA;&#xD;&#xA;Traditionally, rendering is double-buffered, which means there are two buffers stored in GPU memory: one that is currently being scanned out (&quot;front buffer&quot;), and one that is being rendered to (&quot;back buffer&quot;).  Each frame, the two are swapped.  The GPU never renders to the same buffer that's being scanned out, which prevents artifacts due to potentially seeing parts of an incomplete frame.  However, a side effect of this is increased latency, since each frame may sit around in the buffer for several ms before it starts being scanned out.&#xD;&#xA;&#xD;&#xA;VR is very latency-sensitive, so this isn't desirable. An alternative approach is to render directly to the front buffer, but time things out very carefully so that you have rendered each line of the image shortly before the scanout gets there. That's called &quot;scanline racing&quot; or &quot;racing the beam&quot; (the &quot;beam&quot; harkening back to the CRT days of yore). This more or less requires that you render the image in scanline order, i.e. the same order that the pixels get scanned out.  It doesn't literally have to be rendered one line at a time&amp;mdash;it could be rendered in thin strips a few pixels high, but it does have to be done in order, as you can't go back and edit pixels that have already been scanned out.&#xD;&#xA;&#xD;&#xA;There are a lot of disadvantages to this approach; it has very stringent performance requirements, has to be timed very carefully against vsync, and it greatly complicates the rendering process. But in principle it can shave milliseconds off your latency, which why VR folks are interested in it." ContentLicense="CC BY-SA 3.0" />
  <row Id="144" PostHistoryTypeId="2" PostId="54" RevisionGUID="e5c7a175-1f3a-4908-bb37-d12d1596fee1" CreationDate="2015-08-05T09:30:30.980" UserId="48" Text="Image filtering operations such as blurs, SSAO, bloom and so forth are usually done using pixel shaders and &quot;gather&quot; operations, where each pixel shader invocation issues a number of texture fetches to access the neighboring pixel values, and computes a single pixel's worth of the result.  This approach has a theoretical inefficiency in that many redundant fetches are done: nearby shader invocations will re-fetch many of the same texels.&#xD;&#xA;&#xD;&#xA;Another way to do it is with compute shaders. These have the potential advantage of being able to share a small amount of memory across a group of shader invocations. For instance, you could have each invocation fetch one texel and store it in shared memory, then calculate the results from there.  This might or might not be faster.&#xD;&#xA;&#xD;&#xA;The question is under what circumstances (if ever) is the compute-shader method *actually* faster than the pixel-shader method?  Does it depend on the size of the kernel, what kind of filtering operation it is, etc.?  Clearly the answer will vary from one model of GPU to another, but I'm interested in hearing if there are any general trends." ContentLicense="CC BY-SA 3.0" />
  <row Id="145" PostHistoryTypeId="1" PostId="54" RevisionGUID="e5c7a175-1f3a-4908-bb37-d12d1596fee1" CreationDate="2015-08-05T09:30:30.980" UserId="48" Text="When is a compute shader more efficient than a pixel shader for image filtering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="146" PostHistoryTypeId="3" PostId="54" RevisionGUID="e5c7a175-1f3a-4908-bb37-d12d1596fee1" CreationDate="2015-08-05T09:30:30.980" UserId="48" Text="|performance|rendering|compute-shader|pixel-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="147" PostHistoryTypeId="2" PostId="55" RevisionGUID="9acddd85-71b0-4055-bfe5-f3cb61d2bfce" CreationDate="2015-08-05T09:42:12.257" UserId="141" Text="The most important thing to consider when implementing the Gaussian blur is, as others have pointed out, to separate the 2D convolution filter into two 1D convolutions because it brings the complexity down from O(n^2) to O(n).&#xD;&#xA;&#xD;&#xA;But there are two more tricks you might want to consider in an actual implementation:&#xD;&#xA;&#xD;&#xA;The filter has a certain radius and because of that, at the very borders, you will need to calculate with pixels which fall outside of the image. In such case, you could try one of the following: for the outside pixels you simply take the last possible value (i.e. the pixel at the very border, as in `max(x, 0)`. Or you could &quot;reflect&quot; the image towards outside (as in `x &lt; 0 ? -x : x`). Or you could simply stop at the border but then you would need to adjust the denominator in convolution filter so that it sums up to 1. For example:&#xD;&#xA;&#xD;&#xA;        |1  4  6  4 1|          |0  0  0  0 0|&#xD;&#xA;     1  |4 16 24 16 4|       1  |0 16 24 16 4|&#xD;&#xA;    --- |6 24 36 24 6|  -&gt;  --- |0 24 36 24 6|&#xD;&#xA;    256 |4 16 24 16 4|      225 |0 16 24 16 4|&#xD;&#xA;        |1  4  6  4 1|          |0  4  6  4 1|&#xD;&#xA;&#xD;&#xA;Another trick concerns how to calculate the actual coefficients of the kernel. Obviously you could try to implement the [Gaussian function](https://en.wikipedia.org/wiki/Gaussian_function) but much faster way is to observe that the 1D kernel reassembles [Pascal's triangle](https://en.wikipedia.org/wiki/Pascal%27s_triangle). For example:&#xD;&#xA;&#xD;&#xA;         1&#xD;&#xA;        1 1&#xD;&#xA;       1 2 1&#xD;&#xA;      1 3 3 1&#xD;&#xA;    [1 4 6 4 1]&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="149" PostHistoryTypeId="5" PostId="31" RevisionGUID="727d29cb-4666-4098-ab45-777052aee804" CreationDate="2015-08-05T10:49:45.417" UserId="157" Comment="images example" Text="There are 2 main factors that seem to lead to [digital artifacts][1] when creating JPEG images: Aliasing and Compression.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;&gt; Converting a PNG with characters on it to a JPEG or placing vector images over a photograph, will result in pixelization on their edges. The antialiasing generally creates a kind of blur around them, but if the image is [lossy compressed][2], part of the details are also lost, therefore the blur and the pixelization may become less noticeable.&#xD;&#xA;&#xD;&#xA;Is this the right thing to do? I.e. since a lossless compression generates a highly detailed image, the artifacts resulting from aliasing will be more noticeable, so a balance may be found by using the right compression, although compromising the image quality.&#xD;&#xA;&#xD;&#xA;Edit&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I just saved this JPEG in mspaint:&#xD;&#xA;&#xD;&#xA;[![Lossless][3]][3]&#xD;&#xA;&#xD;&#xA;Here's the same JPEG with maximum compression (lowest quality):&#xD;&#xA;&#xD;&#xA;[![Lossy][4]][4]&#xD;&#xA;&#xD;&#xA;Here's yet the same JPEG with 50% compression (notice the difference in size):&#xD;&#xA;&#xD;&#xA;[![Half-no-options][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The same 50% compression but saved as &quot;progressive JPG&quot;, kept the original EXIF and XMP data, and &quot;tried to save with original JPG quality&quot; (you can notice that there are no grey pixels around):&#xD;&#xA;&#xD;&#xA;[![Half-options][6]][6]&#xD;&#xA;&#xD;&#xA;And finally the same as before with **chroma subsampling disabled** (same file size):&#xD;&#xA;&#xD;&#xA;[![Half-no-chroma][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Digital_artifact&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lossy_compression&#xD;&#xA;  [3]: https://i.stack.imgur.com/uPlhy.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/5HPZJ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/kS88V.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/i5A7q.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/V8FMk.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="150" PostHistoryTypeId="2" PostId="56" RevisionGUID="40cb0cbc-0f56-483e-9cc7-76d255d9037d" CreationDate="2015-08-05T10:50:13.490" UserId="215" Text="In GLSL, perspective correct interpolation of vertex attributes is the default setting - one can disable it for specific vertex attributes by using the *noperspective* qualifier. Other than in post-processing shaders, I've never seen the perspective correct interpolation disabled - are there any other use cases? Also, does it even make a difference, performance-wise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="151" PostHistoryTypeId="1" PostId="56" RevisionGUID="40cb0cbc-0f56-483e-9cc7-76d255d9037d" CreationDate="2015-08-05T10:50:13.490" UserId="215" Text="When to disable perspective correct interpolation ( noperspective )" ContentLicense="CC BY-SA 3.0" />
  <row Id="152" PostHistoryTypeId="3" PostId="56" RevisionGUID="40cb0cbc-0f56-483e-9cc7-76d255d9037d" CreationDate="2015-08-05T10:50:13.490" UserId="215" Text="|opengl|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="153" PostHistoryTypeId="5" PostId="31" RevisionGUID="76e783c4-41b0-4d28-bbe8-3d5d646a42c1" CreationDate="2015-08-05T10:55:35.593" UserId="157" Comment="images example" Text="There are 2 main factors that seem to lead to [digital artifacts][1] when creating JPEG images: Aliasing and Compression.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;&gt; Converting a PNG with characters on it to a JPEG or placing vector images over a photograph, will result in pixelization on their edges. The antialiasing generally creates a kind of blur around them, but if the image is [lossy compressed][2], part of the details are also lost, therefore the blur and the pixelization may become less noticeable.&#xD;&#xA;&#xD;&#xA;Is this the right thing to do? I.e. since a lossless compression generates a highly detailed image, the artifacts resulting from aliasing will be more noticeable, so a balance may be found by using the right compression, although compromising the image quality.&#xD;&#xA;&#xD;&#xA;Edit&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I just saved this JPEG in mspaint (3.46KB):&#xD;&#xA;&#xD;&#xA;[![Lossless][3]][3]&#xD;&#xA;&#xD;&#xA;Here's the same JPEG with maximum compression (lowest quality, 0.5KB):&#xD;&#xA;&#xD;&#xA;[![Lossy][4]][4]&#xD;&#xA;&#xD;&#xA;Here's yet the same JPEG with 50% compression (notice the difference in size, 1.29KB):&#xD;&#xA;&#xD;&#xA;[![Half-no-options][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The same 50% compression but saved as &quot;progressive JPG&quot;, kept the original EXIF and XMP data, and &quot;tried to save with original JPG quality&quot; (you can notice that there are no grey pixels around, 2.96KB):&#xD;&#xA;&#xD;&#xA;[![Half-options][6]][6]&#xD;&#xA;&#xD;&#xA;And finally the same as before with **chroma subsampling disabled** (same file size, 2.96KB):&#xD;&#xA;&#xD;&#xA;[![Half-no-chroma][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Digital_artifact&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lossy_compression&#xD;&#xA;  [3]: https://i.stack.imgur.com/uPlhy.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/5HPZJ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/kS88V.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/i5A7q.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/V8FMk.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="160" PostHistoryTypeId="2" PostId="57" RevisionGUID="5555e7c8-de19-4d9e-9eaa-6708cde4006e" CreationDate="2015-08-05T11:25:51.847" UserId="231" Text="How can I distribute points unevenly over an implicit surface, to concentrate points more densely in areas of higher curvature?&#xD;&#xA;&#xD;&#xA;I've considered adding points randomly and rejecting points not required based on the curvature, but I'd like to know if there is a better approach giving a more even distribution over areas of similar curvature, while still giving the higher density required in high curvature regions.&#xD;&#xA;&#xD;&#xA;I'm looking specifically at using these points for a triangulation of the surface, and I don't want to create more triangles than I need for relatively flat parts.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="161" PostHistoryTypeId="1" PostId="57" RevisionGUID="5555e7c8-de19-4d9e-9eaa-6708cde4006e" CreationDate="2015-08-05T11:25:51.847" UserId="231" Text="How can I concentrate points in areas of higher curvature?" ContentLicense="CC BY-SA 3.0" />
  <row Id="162" PostHistoryTypeId="3" PostId="57" RevisionGUID="5555e7c8-de19-4d9e-9eaa-6708cde4006e" CreationDate="2015-08-05T11:25:51.847" UserId="231" Text="|algorithm|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="163" PostHistoryTypeId="2" PostId="58" RevisionGUID="d48d5154-1dc6-414d-b3c3-028a50cef16d" CreationDate="2015-08-05T11:31:47.607" UserId="231" Text="I want to model rays with a continuous range of frequencies so that I can get raytraced images with colour separation on refraction. I can model a light source with a specified frequency distribution by using the distribution to affect the probability of a random ray lying in a given frequency range, or alternatively I can choose frequencies from a uniform random distribution and make the brightness of each ray proportional to the frequency distribution at its particular frequency. I see the first as more physically accurate, but I suspect the second will give images that look &quot;finished&quot; with fewer rays. Is this intuitive suspicion correct? Are there any features that will be lost from the image with the second approach? Is there a way to get some of the speed increase without compromising the image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="164" PostHistoryTypeId="1" PostId="58" RevisionGUID="d48d5154-1dc6-414d-b3c3-028a50cef16d" CreationDate="2015-08-05T11:31:47.607" UserId="231" Text="What are the side effects of biasing brightness in continuous spectrum raytracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="165" PostHistoryTypeId="3" PostId="58" RevisionGUID="d48d5154-1dc6-414d-b3c3-028a50cef16d" CreationDate="2015-08-05T11:31:47.607" UserId="231" Text="|raytracing|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="168" PostHistoryTypeId="5" PostId="57" RevisionGUID="ae6a9714-fef5-4456-9328-bfe43e198df8" CreationDate="2015-08-05T14:02:27.393" UserId="231" Comment="Clarify following comment questions" Text="How can I distribute points over an implicit surface, to concentrate them more densely in areas of higher curvature?&#xD;&#xA;&#xD;&#xA;I've considered adding points randomly and rejecting points not required based on the curvature, but I'd like to know if there is a better approach giving a more even distribution over areas of similar curvature, while still giving the higher density required in high curvature regions.&#xD;&#xA;&#xD;&#xA;I'm looking specifically at using these points for a triangulation of the surface, and I don't want to create more triangles than I need for relatively flat parts.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;This will be applied to shapes with a known derivative so the curvature at a given point can be calculated.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="169" PostHistoryTypeId="2" PostId="59" RevisionGUID="d9985e86-c9c5-4f2c-8685-c501239faa24" CreationDate="2015-08-05T14:03:44.697" UserId="196" Text="Use cases are only limited by your imagination! `noperspective` means that the attribute is interpolated across the triangle as though the triangle was completely flat on the surface of the screen. You can do [antialiased wireframe rendering][1] with this: output a screen-space distance to the nearest edge as a `noperspective` varying and use that as coverage in the pixel shader.&#xD;&#xA;&#xD;&#xA;Or if you're doing non-photorealistic rendering and want a pattern in screen-space like [halftoning][2], you can enable `noperspective` on your UVs used for texturing.&#xD;&#xA;&#xD;&#xA;Does it make a performance difference? Probably, but you probably won't notice (with the potential exception of less powerful graphics hardware). Most GPUs are composed of a series of pipeline stages that execute in parallel, and in some sense you only pay the cost for the most expensive stage. If rasterization is the most limiting part for you, then you may see a difference from the divisions that you're skipping per-pixel. I would guess that is most likely when rendering a shadow map or a depth prepass, but those also have the fewest attributes to interpolate.&#xD;&#xA;&#xD;&#xA;  [1]: http://orbit.dtu.dk/fedora/objects/orbit:55459/datastreams/file_3735323/content&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Halftone" ContentLicense="CC BY-SA 3.0" />
  <row Id="170" PostHistoryTypeId="2" PostId="60" RevisionGUID="046530c6-e90f-4eb6-920c-d9f67823febc" CreationDate="2015-08-05T14:30:50.343" UserId="196" Text="An architectural *advantage* of compute shaders for image processing is that they skip the [ROP][1] step. It's very likely that writes from pixel shaders go through all the regular blending hardware even if you don't use it. Generally speaking compute shaders can write directly to memory, so you may avoid a bottleneck that you would otherwise have. I've heard of fairly sizable performance wins attributed to this.&#xD;&#xA;&#xD;&#xA;An architectural *disadvantage* of compute shaders is that the GPU no longer knows which work unit retires to which set of pixels. If you are using the pixel shading pipeline, the GPU has the opportunity to pack work into a warp/wavefront that write to an area of the render target which is contiguous in memory (which may be [Z-order tiled][2] or something like that for performance reasons). If you are using a compute pipeline, the GPU may no longer kick work in optimal batches, leading to more bandwidth use.&#xD;&#xA;&#xD;&#xA;You may be able to turn that altered warp/wavefront packing into an advantage again, though, if you know that your particular operation has a substructure that you can exploit by packing related work into the same thread group. Like you said, you could in theory give the sampling hardware a break by sampling one value per lane and putting the result in groupshared memory for other lanes to access without sampling. Whether this is a win depends on how expensive your groupshared memory is: if it's cheaper than the lowest-level texture cache, then this may be a win, but there's no guarantee of that. GPUs already deal pretty well with highly local texture fetches (by necessity).&#xD;&#xA;&#xD;&#xA;If you have an intermediate stages in the operation where you want to share results, it may make more sense to use groupshared memory (since you can't fall back on the texture sampling hardware without having actually written out your intermediate result to memory). Unfortunately you also can't depend on having results from any other thread group, so the second stage would have to limit itself to only what is available in the same tile. I think the canonical example here is computing the average luminance of the screen for auto-exposure. I could also imagine combining texture upsampling with some other operation (since upsampling, unlike downsampling and blurs, doesn't depend on any values outside a given tile).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Render_output_unit&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Z-order_curve" ContentLicense="CC BY-SA 3.0" />
  <row Id="171" PostHistoryTypeId="2" PostId="61" RevisionGUID="a1deb0ab-6e91-4c89-ae64-19c4283404f0" CreationDate="2015-08-05T14:56:21.613" UserId="88" Text="The [OpenGL documentation][1] states that fwidth `returns the sum of the absolute value of derivatives in x and y`.&#xD;&#xA;&#xD;&#xA;What does this mean in less mathematical terms, and is there a way to visualize it?&#xD;&#xA;&#xD;&#xA;Based on my understanding of the function, `fwidth(p)` has access to the value of `p` in neighboring pixels. How does this work on the GPU without drastically impacting performance, and does it work reliably and uniformly across all pixels?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/fwidth.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="172" PostHistoryTypeId="1" PostId="61" RevisionGUID="a1deb0ab-6e91-4c89-ae64-19c4283404f0" CreationDate="2015-08-05T14:56:21.613" UserId="88" Text="What is fwidth and how does it work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="173" PostHistoryTypeId="3" PostId="61" RevisionGUID="a1deb0ab-6e91-4c89-ae64-19c4283404f0" CreationDate="2015-08-05T14:56:21.613" UserId="88" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="174" PostHistoryTypeId="2" PostId="62" RevisionGUID="fe2fc4eb-6f0d-482d-b386-c8e2c0b10576" CreationDate="2015-08-05T14:56:45.127" UserId="196" Text="I'd consider just going with 3D noise and evaluating it on the surface of the sphere.&#xD;&#xA;&#xD;&#xA;For gradient noise which is naturally in the domain of the surface of the sphere, you need a regular pattern of sample points on the surface that have natural connectivity information, with roughly equal area in each cell, so you can interpolate or sum adjacent values. I wonder if something like a [Fibonacci grid][1] might work:&#xD;&#xA;&#xD;&#xA;[![Fibonacci grid on the surface of a sphere][2]][2]&#xD;&#xA;&#xD;&#xA;I haven't chewed through the math to determine how much work it would be to figure out the indices of and distance to your four neighbors (I don't even know if you end up having four well-defined neighbors in all cases), and I suspect it may be less efficient than simply using 3D noise.&#xD;&#xA;&#xD;&#xA;  [1]: http://onlinelibrary.wiley.com/doi/10.1256/qj.05.227/epdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/sQQb3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="175" PostHistoryTypeId="2" PostId="63" RevisionGUID="55f0ccfd-ebf7-43a3-bd5c-96ad285c084c" CreationDate="2015-08-05T15:10:50.933" UserId="196" Text="Pixel screen-space derivatives *do* drastically impact performance, but they impact performance whether you use them or not, so from a certain point of view they're free!&#xD;&#xA;&#xD;&#xA;Every GPU in recent history packs a quad of four pixels together and puts them in the same warp/wavefront, which essentially means that they're running right next to each other on the GPU, so accessing values from them is very cheap. Because warps/wavefronts are run in lockstep, the other pixels will also be at exactly the same place in the shader as you are, so the value of `p` for those pixels will just be sitting in a register waiting for you. These other three pixels will *always* be executed, even if their results will be thrown away. So a triangle that covers a single pixel will always shade four pixels and throw away the results of three of them, just so that these derivative features work!&#xD;&#xA;&#xD;&#xA;This is considered an acceptable cost (for current hardware) because it isn't just functions like `fwidth` that use these derivatives: every single texture sample does as well, in order to pick what mipmap of your texture to read from. Consider: if you are very close to a surface, the UV coordinate you are using to sample the texture will have a very small derivative in screen space, meaning you need to use a larger mipmap, and if you are farther the UV coordinate will have a larger derivative in screen space, meaning you need to use a smaller mipmap.&#xD;&#xA;&#xD;&#xA;As far as what it means in less mathematical terms: `fwidth` is equivalent to `abs(dFdx(p)) + abs(dFdy(p))`. `dFdx(p)` is simply the difference between the value of `p` at pixel x+1 and the value of `p` at pixel x, and similarly for `dFdy(p)`." ContentLicense="CC BY-SA 3.0" />
  <row Id="176" PostHistoryTypeId="2" PostId="64" RevisionGUID="b35e4ea1-8177-439f-8cfd-b580fcf03b2d" CreationDate="2015-08-05T15:13:45.657" UserId="6" Text="In entirely technical terms, `fwidth(p)` is defined as&#xD;&#xA;&#xD;&#xA;    fwidth(p) := abs(dFdx(p)) + abs(dFdy(p))&#xD;&#xA;&#xD;&#xA;And `dFdx(p)`/`dFdy(p)` are the partial derivates of the value `p` with respect to the `x` and `y` screen dimensions. So they denote how the value of `p` behaves when going one pixel to the right (`x`) or one pixel up (`y`).&#xD;&#xA;&#xD;&#xA;Now how are they be practically computed? Well, if you know the neighbour pixels' values for `p`, you can just compute those derivates as direct **finite differences** as an approximation for their actual mathematical derivatives (which might not have an exact analytical solution at all):&#xD;&#xA;&#xD;&#xA;    dFdx(p) := p(x+1) - p(x)&#xD;&#xA;&#xD;&#xA;But of course now you may ask, how do we even know the values of `p` (which could afterall be any arbitrarily computed value inside the shader program) for the neighbouring pixels? How do we compute those values without incurring major overhead by doing the whole shader computation two (or three) times?&#xD;&#xA;&#xD;&#xA;Well, you know what, those neighbouring values are computed anyway, since for the neighbouring pixel you also run a fragment shader. So all that you need is access to this neighbouring fragment shader invocation when run for the neighbouring pixel. But it's even easier, because those neighbouring values are also computed at the exact same time.&#xD;&#xA;&#xD;&#xA;Modern rasterizers call fragment shaders in larger tiles of more than one neighbouring pixels. At the smallest those would be a 2x2 grid of pixels. And for each such a pixel block the fragment shader is invoked for each pixel and those invocations run **in perfectly parallel lock-step** so that all computations are done in the exact same order and at the exact same time for each of those pixels in the block (which is also why branching in the fragment shader, while not deadly, should be avoided if possible, since each invocation of a block would have to explore every branch that is taken by at least one of the invocations, even if it just throws away the results afterwards). So at any moment, a fragment shader theoretically has access to its neighbouring pixels' fragment shader values. And while you don't have direct access to those values, you have access to values computed from them, like the derivative functions `dFdx`, `dFdy`, `fwidth`, ..." ContentLicense="CC BY-SA 3.0" />
  <row Id="177" PostHistoryTypeId="2" PostId="65" RevisionGUID="37ace01c-ee6f-4ad6-868f-0bde55f717eb" CreationDate="2015-08-05T15:36:21.923" UserId="231" Text="Using a gaussian distribution of points on an image plane to calculate a pixel value, what radius will give the most information in the final image? Too large a radius gives a blurred image, and too small a radius neglects information that is smaller than a pixel so that it does not contribute to the final image. Where is the optimal compromise? Is there a single answer to this question or are there circumstances under which it can vary?&#xD;&#xA;&#xD;&#xA;I'm thinking of this in relation to raytracing but I imagine it will apply equally to things like downsizing an image.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="178" PostHistoryTypeId="1" PostId="65" RevisionGUID="37ace01c-ee6f-4ad6-868f-0bde55f717eb" CreationDate="2015-08-05T15:36:21.923" UserId="231" Text="What is the optimal radius of gaussian distribution for determining pixel colour?" ContentLicense="CC BY-SA 3.0" />
  <row Id="179" PostHistoryTypeId="3" PostId="65" RevisionGUID="37ace01c-ee6f-4ad6-868f-0bde55f717eb" CreationDate="2015-08-05T15:36:21.923" UserId="231" Text="|sampling|pixels|" ContentLicense="CC BY-SA 3.0" />
  <row Id="180" PostHistoryTypeId="2" PostId="66" RevisionGUID="c77e298c-0d1a-477e-aad3-60d87423144a" CreationDate="2015-08-05T16:03:41.260" UserId="56" Text="I know that depth of field involves blurring.&#xD;&#xA;&#xD;&#xA;There's some great information about how to do a Gaussian blur in the question http://computergraphics.stackexchange.com/questions/39/how-is-gaussian-blur-implemented&#xD;&#xA;&#xD;&#xA;But, other than that, how is depth of field implemented?&#xD;&#xA;&#xD;&#xA;What are the rules about how you blur each pixel, and how do you handle the case of when there is a pixel that wants to blur a lot next to a pixel that doesn't want to blur as much?&#xD;&#xA;&#xD;&#xA;I've also heard of the &quot;circle of confusion&quot; but have no idea what that is.&#xD;&#xA;&#xD;&#xA;Can anyone explain DOF in a plain, easy to understand way?&#xD;&#xA;&#xD;&#xA;Thanks!! (:" ContentLicense="CC BY-SA 3.0" />
  <row Id="181" PostHistoryTypeId="1" PostId="66" RevisionGUID="c77e298c-0d1a-477e-aad3-60d87423144a" CreationDate="2015-08-05T16:03:41.260" UserId="56" Text="How is Depth of Field Implemented?" ContentLicense="CC BY-SA 3.0" />
  <row Id="182" PostHistoryTypeId="3" PostId="66" RevisionGUID="c77e298c-0d1a-477e-aad3-60d87423144a" CreationDate="2015-08-05T16:03:41.260" UserId="56" Text="|blur|post-processing|depth-of-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="183" PostHistoryTypeId="5" PostId="65" RevisionGUID="0625e6ea-eba6-47ec-921e-9741042532d5" CreationDate="2015-08-05T16:25:31.173" UserId="231" Comment="added 220 characters in body" Text="Using a gaussian distribution of points on an image plane to calculate a pixel value, what radius/standard deviation will give the most information in the final image? Too large a radius gives a blurred image, and too small a radius neglects information that is smaller than a pixel so that it does not contribute to the final image. Where is the optimal compromise? Is there a single answer to this question or are there circumstances under which it can vary?&#xD;&#xA;&#xD;&#xA;I'm thinking of this in relation to raytracing but I imagine it will apply equally to things like downsizing an image. Where the answers would differ, I am interested in what applies when sampling a continuous image plane, so that the positions of pixels in a larger image cannot be used to determine an optimal radius.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="184" PostHistoryTypeId="2" PostId="67" RevisionGUID="1d9f6010-b393-461d-9623-678bb89ac484" CreationDate="2015-08-05T16:28:50.313" UserId="231" Text="Most computer monitors and televisions have a rectangular array of pixels arranged on a square (or nearly square) lattice. Would a hexagonal lattice give better image quality for the same number of pixels? In other words, would the same amount of memory allow storage of more detail?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Even if the answer is &quot;yes&quot;, I don't expect monitor manufacturers to suddenly start making hexagonally arranged pixels. However, I ask the question because I wonder whether there would be anything to be gained from storing images as hexagonal lattices of pixels, even if they are translated to square lattices of pixels for display purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="185" PostHistoryTypeId="1" PostId="67" RevisionGUID="1d9f6010-b393-461d-9623-678bb89ac484" CreationDate="2015-08-05T16:28:50.313" UserId="231" Text="Could a hexgaonal pixel array store an image more efficiently?" ContentLicense="CC BY-SA 3.0" />
  <row Id="186" PostHistoryTypeId="3" PostId="67" RevisionGUID="1d9f6010-b393-461d-9623-678bb89ac484" CreationDate="2015-08-05T16:28:50.313" UserId="231" Text="|pixels|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="187" PostHistoryTypeId="2" PostId="68" RevisionGUID="1eeb6981-21aa-4dff-9eec-46072322dc68" CreationDate="2015-08-05T16:33:33.160" UserId="231" Text="Do different monitors (including mobile screens) still use significantly different gamma functions when displaying colour images? Is there a standardised way to represent colour that can then be translated according to the gamma of the monitor, or are they all sufficiently similar to preclude the need for this nowadays?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="188" PostHistoryTypeId="1" PostId="68" RevisionGUID="1eeb6981-21aa-4dff-9eec-46072322dc68" CreationDate="2015-08-05T16:33:33.160" UserId="231" Text="Is gamma still important to take into account?" ContentLicense="CC BY-SA 3.0" />
  <row Id="189" PostHistoryTypeId="3" PostId="68" RevisionGUID="1eeb6981-21aa-4dff-9eec-46072322dc68" CreationDate="2015-08-05T16:33:33.160" UserId="231" Text="|color|gamma|compatibility|" ContentLicense="CC BY-SA 3.0" />
  <row Id="190" PostHistoryTypeId="2" PostId="69" RevisionGUID="d7eeb3af-dde6-4258-b6b0-4736c8fc32c4" CreationDate="2015-08-05T16:40:58.147" UserId="231" Text="If rendering an image in 2d, adding depth of field effects (blurring objects further from the focal distance) adds realism and draws the eye to the object of the image. With a 3d image, looking at an object in the image at a given depth will makes objects at all other depths defocused (not blurred, but incorrectly aligned by the eyes, giving a double image). This means that if depth of field effects are used, there will be conflicting results: looking at an object that is at a different depth will cause that depth to be the only depth not having a double image, but it is also a depth that is blurred. This gives the object a property of being focused upon, and a property of not being focused upon. In a 3d still image, are depth of field effects detrimental to the acceptance of the image by the eye, or are there ways around this?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="191" PostHistoryTypeId="1" PostId="69" RevisionGUID="d7eeb3af-dde6-4258-b6b0-4736c8fc32c4" CreationDate="2015-08-05T16:40:58.147" UserId="231" Text="Is depth of field incongruous in a 3d still image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="192" PostHistoryTypeId="3" PostId="69" RevisionGUID="d7eeb3af-dde6-4258-b6b0-4736c8fc32c4" CreationDate="2015-08-05T16:40:58.147" UserId="231" Text="|depth-of-field|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="193" PostHistoryTypeId="4" PostId="67" RevisionGUID="791497f8-39ba-4561-abc3-95bb37e0ae3e" CreationDate="2015-08-05T16:54:38.320" UserId="36" Comment="typo in title" Text="Could a hexagonal pixel array store an image more efficiently?" ContentLicense="CC BY-SA 3.0" />
  <row Id="194" PostHistoryTypeId="24" PostId="67" RevisionGUID="791497f8-39ba-4561-abc3-95bb37e0ae3e" CreationDate="2015-08-05T16:54:38.320" Comment="Proposed by 36 approved by 231 edit id of 10" ContentLicense="CC BY-SA 3.0" />
  <row Id="195" PostHistoryTypeId="5" PostId="69" RevisionGUID="8375eab8-3ee1-4f5b-b395-2f08418558fe" CreationDate="2015-08-05T16:56:09.080" UserId="6" Comment="Adding relevant tags and clarifications" Text="If rendering an image into 2D, adding depth of field effects (blurring objects further from the focal distance) adds realism and draws the eye to the object of the image. With a 3D (i.e. stereo) image, looking at an object in the image at a given depth will makes objects at all other depths defocused (not blurred, but incorrectly aligned by the eyes, giving a double image). This means that if depth of field effects are used, there will be conflicting results: looking at an object that is at a different depth will cause that depth to be the only depth not having a double image, but it is also a depth that is blurred. This gives the object a property of being focused upon, and a property of not being focused upon. In a 3d still image, are depth of field effects detrimental to the acceptance of the image by the eye, or are there ways around this?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="196" PostHistoryTypeId="6" PostId="69" RevisionGUID="8375eab8-3ee1-4f5b-b395-2f08418558fe" CreationDate="2015-08-05T16:56:09.080" UserId="6" Comment="Adding relevant tags and clarifications" Text="|depth-of-field|3d|stereo-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="197" PostHistoryTypeId="24" PostId="69" RevisionGUID="8375eab8-3ee1-4f5b-b395-2f08418558fe" CreationDate="2015-08-05T16:56:09.080" Comment="Proposed by 6 approved by -1 edit id of 11" ContentLicense="CC BY-SA 3.0" />
  <row Id="198" PostHistoryTypeId="5" PostId="69" RevisionGUID="bd968459-71d1-4924-a179-ce0b1292b888" CreationDate="2015-08-05T16:56:09.080" UserId="231" Comment="Adding relevant tags and clarifications" Text="If rendering an image in 2D, adding depth of field effects (blurring objects further from the focal distance) adds realism and draws the eye to the object of the image. With a 3D (i.e. stereo) image, looking at an object in the image at a given depth will makes objects at all other depths defocused (not blurred, but incorrectly aligned by the eyes, giving a double image). This means that if depth of field effects are used, there will be conflicting results: looking at an object that is at a different depth will cause that depth to be the only depth not having a double image, but it is also a depth that is blurred. This gives the object a property of being focused upon, and a property of not being focused upon. In a 3d still image, are depth of field effects detrimental to the acceptance of the image by the eye, or are there ways around this?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="199" PostHistoryTypeId="4" PostId="69" RevisionGUID="bd968459-71d1-4924-a179-ce0b1292b888" CreationDate="2015-08-05T16:56:09.080" UserId="231" Comment="Adding relevant tags and clarifications" Text="Is depth of field incongruous in a 3D still image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="200" PostHistoryTypeId="2" PostId="70" RevisionGUID="a83d956f-4a95-4eda-bc5b-850b0aa7b223" CreationDate="2015-08-05T17:03:21.057" UserId="100" Text="The depth of field is a characteristic of a camera lens, although the name &quot;Depth of Field&quot; is commonly used to describe the effect caused by such characteristic. &#xD;&#xA;&#xD;&#xA;Camera lenses can only perfectly focus on one single point, but there is a distance for which the image will still look reasonably sharp. Such distance is what actually the Depth Of Field is. This distance is variable depending on various factors, but let's say for the sake of brevity that the easiest way to adjust it is by changing your camera aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the circle of confusion it is helpful to look a pic from wikipedia: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;In both three cases a single point is &quot;captured&quot; onto our image plane. &#xD;&#xA;&#xD;&#xA;Basically because, as I said, not everything is perfectly in focus (that is the focal point is on the image plane), a point can be projected to our image plane not to a single point but to an area. This, as it is clear from the pic, is because the focal point is either before or after the image plane. This &quot;circle&quot; that is created on the image plane is what is called the circle of confusion. &#xD;&#xA;&#xD;&#xA;Now from this should be clear that varying the depth of field you vary the CoC size, hence it can be used as a measure of the DoF itself and an intuitive one when thinking in terms of blurring. &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;As per how it is implemented in rendering there are really lots of methods out there. Usually in games is done as a post process using the depth information to define different &quot;planes&quot; to which split your scene; for example a focus plane that does not need to be blurred, a near plane and a far/background plane that need to be blurred. Once you blurred your planes you can composite them back together to get your final image. &#xD;&#xA;How much you blur the various planes it is dependent on the effect you want to achieve. Advanced system usually implement this and other &quot;lenses&quot; effect using appropriate parameters coming from the photography world like the aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ezhSb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/g7MnD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="201" PostHistoryTypeId="5" PostId="70" RevisionGUID="d61e9dd5-23bf-47c3-9d0d-e272f378ac0d" CreationDate="2015-08-05T17:08:26.177" UserId="100" Comment="added 260 characters in body" Text="The depth of field is a characteristic of a camera lens, although the name &quot;Depth of Field&quot; is commonly used to describe the effect caused by such characteristic. &#xD;&#xA;&#xD;&#xA;Camera lenses can only perfectly focus on one single point, but there is a distance for which the image will still look reasonably sharp. Such distance is what actually the Depth Of Field is. This distance is variable depending on various factors, but let's say for the sake of brevity that the easiest way to adjust it is by changing your camera aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the circle of confusion it is helpful to look a pic from wikipedia: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;In all of the three cases a single point is &quot;projected&quot; onto our image plane. &#xD;&#xA;&#xD;&#xA;Basically because, as I said, not everything is perfectly in focus (that is the focal point is on the image plane), a point can be projected to our image plane not to a single point but to an area. This, as it is clear from the pic, is because the focal point is either before or after the image plane. This &quot;circle&quot; that is created on the image plane is what is called the circle of confusion. &#xD;&#xA;&#xD;&#xA;Now from this should be clear that varying the depth of field you vary the CoC size, hence it can be used as a measure of the DoF itself and an intuitive one when thinking in terms of blurring. &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;As per how it is implemented in rendering there are really lots of methods out there. Usually in games is done as a post process using the depth information to split your scene in different &quot;planes&quot;; for example a focus plane that does not need to be blurred, a near plane and a far/background plane that need to be blurred. Once you blurred your planes you can composite them back together to get your final image. &#xD;&#xA;How much you blur the various planes it is dependent on the effect you want to achieve. Advanced system usually implement this and other &quot;lenses&quot; effect using appropriate parameters coming from the photography world like the aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note that there are many ways to implement the effect, the one I described is just one way that also has variations (for example performing the whole thing at lower res). The limit is dependent on what your target is and how much you budgeted for this effect. You can go from adopting the &quot;3 planes&quot; method at extremely low res to computing the circle of confusion for each pixel and applying the consequent ad-hoc blur to that pixel. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ezhSb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/g7MnD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="202" PostHistoryTypeId="2" PostId="71" RevisionGUID="99c3f847-9fec-4b17-a997-a03ba661100a" CreationDate="2015-08-05T17:39:24.690" UserId="79" Text="In traditional stereo 3D, I don't believe that there is a way to make a fixed focal plane feel natural to the viewer. When looking at an out-of-focus object in stereo 3D, the object remains out-of-focus, causing conflicting cues. The lens in the eye tries to adjust to bring the object into focus, but of course it won't succeed, causing eye strain and headaches.&#xD;&#xA;&#xD;&#xA;However, there is hope outside stereo 3D: Lightfield displays, such as [this nvidia prototype](https://research.nvidia.com/publication/near-eye-light-field-displays), go a different route. In stereo 3D, the light in the scene is already captured by two virtual (or physical) cameras, &quot;baking&quot; in the focal plane. Head-mounted displays like Oculus Rift then attempt to tape two displays in front of your eyes in such a way that the retina receives the exact same image that was captured by the camera. Lightfield displays go a different route: Instead of capturing two images ahead of time, they reproduce the entire 4D light field in front of your eyes, allowing your eyes to capture the image as if they were sitting directly inside the virtual scene. This has a number of benefits, including much smaller and lighter hardware as well as giving your eyes the ability to refocus.&#xD;&#xA;&#xD;&#xA;If there is a way to make lightfield displays technically and commercially viable, then I believe they can remove the need for depth of field and fixed focal planes entirely and make VR feel a whole lot more comfortable for the viewer. However, it is likely not possible to construct lightfield screens, so televisions and cinemas won't be able to use this technology." ContentLicense="CC BY-SA 3.0" />
  <row Id="203" PostHistoryTypeId="2" PostId="72" RevisionGUID="5b3a8a8b-2e9d-47f9-9cfd-bd00b17c6d56" CreationDate="2015-08-05T17:53:18.857" UserId="38" Text="Yes, while many screens and OS operations are using a gamma of 2.2 your hardware and computation result still need to be corrected. There are also special mediums such as broadcast TV's that have a different gamma. Sensor equipment like cameras are mostly linear so they need to be adjusted accordingly. Besides this the user can set their system to whatever gamma they like. &#xD;&#xA;&#xD;&#xA;In computer graphics primary reason to account for gamma is that your computation is most likely done in linear space or summing light contributions becomes unnecessarily complicated. In any case gamma is really a simplification of things, you'd be much much better of doing profile to profile conversions if its possible to invest the computational time to do so.&#xD;&#xA;&#xD;&#xA;## Mathematical explanation&#xD;&#xA;&#xD;&#xA;This may be a simpler to understand. Your monitor has a display error of g(x) which is no problem if your data is conforming to g(x), however if you want to calculate:&#xD;&#xA;&#xD;&#xA;    a+b+c+d&#xD;&#xA;&#xD;&#xA;and a, b, c, d, have the error of g(x) you would actually need to calculate.&#xD;&#xA;&#xD;&#xA;     g(g^-1(a)+g^-1(b)+g^-1(c)+g^-1(d))&#xD;&#xA;&#xD;&#xA;You would need to do this for each sub element over and over again. Therefore instead of running the transform each time you transform all once to linear and then once back. &#xD;&#xA;&#xD;&#xA;## And finally a artistic reason&#xD;&#xA;&#xD;&#xA;It may just look better with a different gamma. Many games have a gamma adjustment for this reason." ContentLicense="CC BY-SA 3.0" />
  <row Id="204" PostHistoryTypeId="5" PostId="70" RevisionGUID="a5095bd4-4712-4cba-a89e-a82e8b59ce7f" CreationDate="2015-08-05T17:57:50.167" UserId="100" Comment="added 8 characters in body" Text="The depth of field is a characteristic of a camera lens setting, although the name &quot;Depth of Field&quot; is commonly used to describe the effect caused by such characteristic. &#xD;&#xA;&#xD;&#xA;Camera lenses can only perfectly focus on one single point, but there is a distance for which the image will still look reasonably sharp. Such distance is what actually the Depth Of Field is. This distance is variable depending on various factors, but let's say for the sake of brevity that the easiest way to adjust it is by changing your camera aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the circle of confusion it is helpful to look a pic from wikipedia: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;In all of the three cases a single point is &quot;projected&quot; onto our image plane. &#xD;&#xA;&#xD;&#xA;Basically because, as I said, not everything is perfectly in focus (that is the focal point is on the image plane), a point can be projected to our image plane not to a single point but to an area. This, as it is clear from the pic, is because the focal point is either before or after the image plane. This &quot;circle&quot; that is created on the image plane is what is called the circle of confusion. &#xD;&#xA;&#xD;&#xA;Now from this should be clear that varying the depth of field you vary the CoC size, hence it can be used as a measure of the DoF itself and an intuitive one when thinking in terms of blurring. &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;As per how it is implemented in rendering there are really lots of methods out there. Usually in games is done as a post process using the depth information to split your scene in different &quot;planes&quot;; for example a focus plane that does not need to be blurred, a near plane and a far/background plane that need to be blurred. Once you blurred your planes you can composite them back together to get your final image. &#xD;&#xA;How much you blur the various planes it is dependent on the effect you want to achieve. Advanced system usually implement this and other &quot;lenses&quot; effect using appropriate parameters coming from the photography world like the aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note that there are many ways to implement the effect, the one I described is just one way that also has variations (for example performing the whole thing at lower res). The limit is dependent on what your target is and how much you budgeted for this effect. You can go from adopting the &quot;3 planes&quot; method at extremely low res to computing the circle of confusion for each pixel and applying the consequent ad-hoc blur to that pixel. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ezhSb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/g7MnD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="205" PostHistoryTypeId="5" PostId="70" RevisionGUID="cc7081aa-054e-4577-8fba-a8dd0b626dd8" CreationDate="2015-08-05T18:04:02.870" UserId="100" Comment="added 2 characters in body" Text="The depth of field is a characteristic of a camera lens setting, although the name &quot;Depth of Field&quot; is commonly used to describe the effect caused by such characteristic. &#xD;&#xA;&#xD;&#xA;Camera lenses can only perfectly focus on one single point, but there is a distance for which the image will still look reasonably sharp. Such distance is what actually the Depth Of Field is. This distance is variable depending on various factors, but let's say for the sake of brevity that the easiest way to adjust it is by changing your camera aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the circle of confusion it is helpful to look a pic from wikipedia: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;&#xD;&#xA;In all of the three cases a single point is &quot;projected&quot; onto our image plane. &#xD;&#xA;&#xD;&#xA;Basically because, as I said, not everything is perfectly in focus (that is the focal point is on the image plane), a point can be projected to our image plane not to a single point but to an area. This, as it is clear from the pic, is because the focal point is either before or after the image plane. This &quot;circle&quot; that is created on the image plane is what is called the circle of confusion. &#xD;&#xA;&#xD;&#xA;Now from this should be clear that varying the depth of field you vary the CoC size, hence it can be used as a measure of the DoF itself and an intuitive one when thinking in terms of blurring. &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;As per how it is implemented in rendering there are really lots of methods out there. Usually in games is done as a post process using the depth information to split your scene in different &quot;planes&quot;; for example a focus plane that does not need to be blurred, a near plane and a far/background plane that need to be blurred. Once you blurred your planes you can composite them back together to get your final image. &#xD;&#xA;How much you blur the various planes it is dependent on the effect you want to achieve. Advanced system usually implement this and other &quot;lenses&quot; effect using appropriate parameters coming from the photography world like the aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note that there are many ways to implement the effect, the one I described is just one way that also has variations (for example performing the whole thing at lower res). The limit is dependent on what your target is and how much you budgeted for this effect. You can go from adopting the &quot;3 planes&quot; method at extremely low res to computing the circle of confusion for each pixel and applying the consequent ad-hoc blur to that pixel. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ezhSb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/g7MnD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="206" PostHistoryTypeId="2" PostId="73" RevisionGUID="9333d963-e19c-429d-8c7a-a304912479f5" CreationDate="2015-08-05T18:15:47.057" UserId="228" Text="The idea i would try to apply would be the following, i make the example for the curve but it should be straightforward the application for the surface.&#xD;&#xA;&#xD;&#xA;Let's say we have a curve &lt;code&gt;gamma&lt;/code&gt; uniformely parametrized, let's say the parameter of the curve is &lt;code&gt;s&lt;/code&gt;. Your goal is to sample point corresponding to value of &lt;code&gt;s&lt;/code&gt; such that the curvature is high.&#xD;&#xA;&#xD;&#xA;If you get the magnitude of the curvature &lt;code&gt;c&lt;/code&gt; this will be function of &lt;code&gt;s&lt;/code&gt; too, so if you normalize the function &lt;code&gt;|c|&lt;/code&gt; you will get a probability distribution. If you get the integral of such distribution you will have the cumulative distribution, let's call the cumulative function &lt;code&gt;C(s)&lt;/code&gt;.&#xD;&#xA;&#xD;&#xA;The sampling problem from a distribution given the cumulative function is well known, so basically once you have sampled a set of value &lt;code&gt;s0,s1,...,sn&lt;/code&gt; such value will be related to the points of interest.&#xD;&#xA;&#xD;&#xA;The application of this method to the case of surface should be straight since basically you have a two dimensional cumulative distribution function, but the sampling problem is exactly the same.&#xD;&#xA;&#xD;&#xA;Just to give some detail... basically sampling from a distribution given the cumulative function involves two steps. 1. take a random value in the interval [0,1], let's say &lt;code&gt;k&lt;/code&gt; 2. solve the equation &lt;code&gt;C(s) = k&lt;/code&gt;.&#xD;&#xA;&#xD;&#xA;This approach is exact, of course it is expensive, but if you like such approach you can work on optimization.&#xD;&#xA;&#xD;&#xA;(By the way... is that normal i can't write any formula here?)." ContentLicense="CC BY-SA 3.0" />
  <row Id="208" PostHistoryTypeId="5" PostId="72" RevisionGUID="ffabbfd0-ac27-4089-82b0-6a2535d17db7" CreationDate="2015-08-05T18:42:54.767" UserId="38" Comment="added 104 characters in body" Text="Yes, while many screens and OS operations are using a gamma of 2.2 your hardware and computation result still need to be corrected. There are also special mediums such as broadcast TV's that have a different gamma. Sensor equipment like cameras are mostly linear so they need to be adjusted accordingly. Besides this the user can set their system to whatever gamma they like. &#xD;&#xA;&#xD;&#xA;In computer graphics primary reason to account for gamma is that your computation is most likely done in linear space\* or summing light contributions becomes unnecessarily complicated. In any case gamma is really a simplification of things, you'd be much much better of doing profile to profile conversions if its possible to invest the computational time to do so.&#xD;&#xA;&#xD;&#xA;## Mathematical explanation&#xD;&#xA;&#xD;&#xA;This may be a simpler to understand. Your monitor has a display error of g(x) which is no problem if your data is conforming to g(x), however if you want to calculate:&#xD;&#xA;&#xD;&#xA;    a+b+c+d&#xD;&#xA;&#xD;&#xA;and a, b, c, d, have the error of g(x) you would actually need to calculate.&#xD;&#xA;&#xD;&#xA;     g(g^-1(a)+g^-1(b)+g^-1(c)+g^-1(d))&#xD;&#xA;&#xD;&#xA;You would need to do this for each sub element over and over again. Therefore instead of running the transform each time you transform all once to linear and then once back. &#xD;&#xA;&#xD;&#xA;## And finally a artistic reason&#xD;&#xA;&#xD;&#xA;It may just look better with a different gamma. Many games have a gamma adjustment for this reason.&#xD;&#xA;&#xD;&#xA;\* Worst case is that you think your computations as linear but do not compensate for the moniter." ContentLicense="CC BY-SA 3.0" />
  <row Id="209" PostHistoryTypeId="2" PostId="74" RevisionGUID="8b50a537-4a57-4bfc-b150-64fc33e2a569" CreationDate="2015-08-05T18:53:15.353" UserId="56" Text="Here's my take on it.  A pixel is not a square, and it isn't even a rectangle.  A pixel is a point (infinitely small) that has a color associated with it.&#xD;&#xA;&#xD;&#xA;The only way I personally have ever seen pixels viewed (interpreted) by a display is to use &quot;nearest neighbor&quot; sampling where the pixels were on a rectangular grid, which means that the color of any given space on a display is the color of the pixel that it is nearest to.&#xD;&#xA;&#xD;&#xA;This is a fancy way of saying &quot;pixels are rectangular and laid out on a grid&quot;, but stay with me on this :P&#xD;&#xA;&#xD;&#xA;As a result, image formats have their pixels stored in a grid as well, with the assumption that nearest neighbor in a grid will also be used to display it.  For instance, many images will have anti aliasing built into them so that they will look good when displayed on a &quot;nearest neighbor grid&quot;.&#xD;&#xA;&#xD;&#xA;Interactive applications (games), may use textures that are not meant to be displayed as is on nearest neighbor grids so are kind of an exception to that rule.  They do this because as part of their execution, they do anti aliasing, bilinear texture sampling, etc, so that whatever picture they push out to the display will look good, when the display shows it as a nearest neighbor grid!&#xD;&#xA;&#xD;&#xA;Now, getting closer to your question: would a hexagonal grid have any advantages?&#xD;&#xA;&#xD;&#xA;I think that yes, it would!&#xD;&#xA;&#xD;&#xA;First off, I think nearest neighbor would look better.  I don't have any real proof of that sorry, but the hexagon more closely approximates a circle, and since it isn't a regular grid of data, i think your eye is getting a better distribution of data.  Sorry, that is a little hand wavey.&#xD;&#xA;&#xD;&#xA;I think the big part of why it would look better though is that linear filtering would be taking information from 6 neighbors instead of 4, and would be interpolating on 3 axis instead of 2.  More information from less regularly spaced samples than a grid gives you = better resulting image.&#xD;&#xA;&#xD;&#xA;Doing cubic interpolation would also be better than cubic interpolation on a grid, so the quality scales up as you scale up the quality of your algorithm too.&#xD;&#xA;&#xD;&#xA;As far as whether it stores data more efficiently, the fact that it can do better filtering with less data means to me that yes, it could store data more efficiently.&#xD;&#xA;&#xD;&#xA;And i guess lastly... maybe you could use these properties to your advantage.  Maybe you could have an image format stored in a lower res hexagonal format, and then before you needed to display the image at runtime, you could use sampling algorithms to convert it back to a grid.&#xD;&#xA;&#xD;&#xA;Maybe there'd even be a good way to do this efficiently in a pixel shader, so it would use less memory at runtime too?&#xD;&#xA;&#xD;&#xA;It's an interesting idea (:&#xD;&#xA;&#xD;&#xA;PS - how cool would it be to have an analog display (no individual pixels, but a continuous colored surface) that looked at the pixel data you sent not as rectangles, but instead as sample points on a continuous surface.  Maybe a bit out there though...." ContentLicense="CC BY-SA 3.0" />
  <row Id="210" PostHistoryTypeId="5" PostId="73" RevisionGUID="0a2d622b-241a-4685-a5e2-50ed8449b9e6" CreationDate="2015-08-05T19:30:06.990" UserId="38" Comment="not a answer part deleted" Text="The idea i would try to apply would be the following, i make the example for the curve but it should be straightforward the application for the surface.&#xD;&#xA;&#xD;&#xA;Let's say we have a curve &lt;code&gt;gamma&lt;/code&gt; uniformely parametrized, let's say the parameter of the curve is &lt;code&gt;s&lt;/code&gt;. Your goal is to sample point corresponding to value of &lt;code&gt;s&lt;/code&gt; such that the curvature is high.&#xD;&#xA;&#xD;&#xA;If you get the magnitude of the curvature &lt;code&gt;c&lt;/code&gt; this will be function of &lt;code&gt;s&lt;/code&gt; too, so if you normalize the function &lt;code&gt;|c|&lt;/code&gt; you will get a probability distribution. If you get the integral of such distribution you will have the cumulative distribution, let's call the cumulative function &lt;code&gt;C(s)&lt;/code&gt;.&#xD;&#xA;&#xD;&#xA;The sampling problem from a distribution given the cumulative function is well known, so basically once you have sampled a set of value &lt;code&gt;s0,s1,...,sn&lt;/code&gt; such value will be related to the points of interest.&#xD;&#xA;&#xD;&#xA;The application of this method to the case of surface should be straight since basically you have a two dimensional cumulative distribution function, but the sampling problem is exactly the same.&#xD;&#xA;&#xD;&#xA;Just to give some detail... basically sampling from a distribution given the cumulative function involves two steps. 1. take a random value in the interval [0,1], let's say &lt;code&gt;k&lt;/code&gt; 2. solve the equation &lt;code&gt;C(s) = k&lt;/code&gt;.&#xD;&#xA;&#xD;&#xA;This approach is exact, of course it is expensive, but if you like such approach you can work on optimization." ContentLicense="CC BY-SA 3.0" />
  <row Id="211" PostHistoryTypeId="24" PostId="73" RevisionGUID="0a2d622b-241a-4685-a5e2-50ed8449b9e6" CreationDate="2015-08-05T19:30:06.990" Comment="Proposed by 38 approved by 53 edit id of 12" ContentLicense="CC BY-SA 3.0" />
  <row Id="212" PostHistoryTypeId="5" PostId="70" RevisionGUID="dbd1bbf3-25b4-4431-9489-9e675c39ea05" CreationDate="2015-08-05T19:44:37.170" UserId="100" Comment="added 64 characters in body" Text="The depth of field is a characteristic of a camera lens setting, although the name &quot;Depth of Field&quot; is commonly used to describe the effect caused by such characteristic. &#xD;&#xA;&#xD;&#xA;Camera lenses can only perfectly focus on one single point, but there is a distance for which the image will still look reasonably sharp. Such distance is what actually the Depth Of Field is. This distance is variable depending on various factors, but let's say for the sake of brevity that the easiest way to adjust it is by changing your camera aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the circle of confusion it is helpful to look a pic from wikipedia: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;&#xD;&#xA;In all of the three cases a single point is &quot;projected&quot; onto our image plane, but as you can see that is at different distances from the lens.&#xD;&#xA;&#xD;&#xA;Basically because, as I said, not everything is perfectly in focus (that is the focal point is on the image plane), a point can be projected to our image plane not to a single point but to an area. This, as it is clear from the pic, is because the focal point is either before or after the image plane. This &quot;circle&quot; that is created on the image plane is what is called the circle of confusion. &#xD;&#xA;&#xD;&#xA;Now from this should be clear that varying the depth of field you vary the CoC size, hence it can be used as a measure of the DoF itself and an intuitive one when thinking in terms of blurring. &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;As per how it is implemented in rendering there are really lots of methods out there. Usually in games is done as a post process using the depth information to split your scene in different &quot;planes&quot;; for example a focus plane that does not need to be blurred, a near plane and a far/background plane that need to be blurred. Once you blurred your planes you can composite them back together to get your final image. &#xD;&#xA;How much you blur the various planes it is dependent on the effect you want to achieve. Advanced system usually implement this and other &quot;lenses&quot; effect using appropriate parameters coming from the photography world like the aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note that there are many ways to implement the effect, the one I described is just one way that also has variations (for example performing the whole thing at lower res). The limit is dependent on what your target is and how much you budgeted for this effect. You can go from adopting the &quot;3 planes&quot; method at extremely low res to computing the circle of confusion for each pixel and applying the consequent ad-hoc blur to that pixel. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ezhSb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/g7MnD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="213" PostHistoryTypeId="5" PostId="67" RevisionGUID="8076550b-8eb0-4048-99ba-441f5e760786" CreationDate="2015-08-05T19:57:24.753" UserId="231" Comment="Add detail following comment" Text="Most computer monitors and televisions have a rectangular array of pixels arranged on a square (or nearly square) lattice. Would a hexagonal lattice give better image quality for the same number of pixels? In other words, would the same amount of memory allow storage of more detail?&#xD;&#xA;&#xD;&#xA;I have an intuitive feeling that (at least slightly) more detail should be possible from the same number of pixels with a hexagonal lattice because (for a fixed area image) the average distance to the nearest pixel centre will be lower than with a square lattice. I'd like to see the difference defined more concretely.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Even if the answer is &quot;yes&quot;, I don't expect monitor manufacturers to suddenly start making hexagonally arranged pixels. However, I ask the question because I wonder whether there would be anything to be gained from storing images as hexagonal lattices of pixels, even if they are translated to square lattices of pixels for display purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="214" PostHistoryTypeId="5" PostId="66" RevisionGUID="f45f0690-62a4-4ee5-86a6-3719a404df87" CreationDate="2015-08-05T19:59:00.067" UserId="71" Comment="Removed thanks" Text="I know that depth of field involves blurring.&#xD;&#xA;&#xD;&#xA;There's some great information about how to do a Gaussian blur in the question http://computergraphics.stackexchange.com/questions/39/how-is-gaussian-blur-implemented&#xD;&#xA;&#xD;&#xA;But, other than that, how is depth of field implemented?&#xD;&#xA;&#xD;&#xA;What are the rules about how you blur each pixel, and how do you handle the case of when there is a pixel that wants to blur a lot next to a pixel that doesn't want to blur as much?&#xD;&#xA;&#xD;&#xA;I've also heard of the &quot;circle of confusion&quot; but have no idea what that is.&#xD;&#xA;&#xD;&#xA;Can anyone explain DOF in a plain, easy to understand way?" ContentLicense="CC BY-SA 3.0" />
  <row Id="215" PostHistoryTypeId="24" PostId="66" RevisionGUID="f45f0690-62a4-4ee5-86a6-3719a404df87" CreationDate="2015-08-05T19:59:00.067" Comment="Proposed by 71 approved by 56 edit id of 13" ContentLicense="CC BY-SA 3.0" />
  <row Id="216" PostHistoryTypeId="2" PostId="75" RevisionGUID="9e47decd-953c-4dca-b5c9-9df3ee131c9a" CreationDate="2015-08-05T20:52:43.003" UserId="48" Text="I'm not sure that there's a truly *optimal* radius&amp;mdash;it's going to be a subjective matter based on what the image looks like.  As you say, too large a radius results in blurring and too small a radius results in aliasing.&#xD;&#xA;&#xD;&#xA;I like to set sigma = 0.5 px, so that the overall radius is about 1.5 px (since the Gaussian has the majority of its weight within ±3 sigma of its mean).  In my experience that gives a good trade-off between blurring and aliasing, but that's just my taste, not based on any objective considerations.&#xD;&#xA;&#xD;&#xA;By the way, as part of [a blog post on antialiasing](http://www.reedbeta.com/blog/2014/11/15/antialiasing-to-splat-or-not/) I wrote last year (which was based on an answer I posted on the previous incarnation of this site!), I tested a variety of antialiasing kernels against a synthetic test image and came out with 0.5 px Gaussian as my subjective favorite." ContentLicense="CC BY-SA 3.0" />
  <row Id="217" PostHistoryTypeId="2" PostId="76" RevisionGUID="81b12d3a-ab88-43bc-a8c1-4a31cbfe1068" CreationDate="2015-08-05T20:58:28.940" UserId="228" Text="In my opinion and experience i don't think there exists an univocal answer... since basically in literature you can easily find example of adaptive filters too (i.e. of variable size). &#xD;&#xA;&#xD;&#xA;I think the actual answer should be related to the both context of applications (i.e. hardware or sofware, real time or not) and kind of scene you're going to synthesize (some scenes usually involves different kind of aliasing when are synthetized (i use this general term on purpose)). Basically computer graphics is the study of algorithms and data structure for image synthesis, and such definition isn't stricly related to any kind of application.&#xD;&#xA;&#xD;&#xA;Of course an important factor is even the goal to be achieved by a filtering process (i.e. not necessary an excessive blurring could be bad...).&#xD;&#xA;&#xD;&#xA;If you're speaking of &quot;nice to see&quot; i think you could agree with me when i say that there's no specific measure of &quot;pleasant image&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="218" PostHistoryTypeId="5" PostId="70" RevisionGUID="c1a70ad9-3ec4-4a07-be1b-bc4840f6b0b8" CreationDate="2015-08-05T21:07:18.557" UserId="100" Comment="added 447 characters in body" Text="The depth of field is a characteristic of a camera lens setting, although the name &quot;Depth of Field&quot; is commonly used to describe the effect caused by such characteristic. &#xD;&#xA;&#xD;&#xA;Camera lenses can only perfectly focus on one single point, but there is a distance for which the image will still look reasonably sharp. Such distance is what actually the Depth Of Field is. This distance is variable depending on various factors, but let's say for the sake of brevity that the easiest way to adjust it is by changing your camera aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As for the circle of confusion it is helpful to look a pic from wikipedia: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;&#xD;&#xA;In all of the three cases a single point is &quot;projected&quot; onto our image plane, but as you can see that is at different distances from the lens.&#xD;&#xA;&#xD;&#xA;Basically because, as I said, not everything is perfectly in focus (that is the focal point is on the image plane), a point can be projected to our image plane not to a single point but to an area. This, as it is clear from the pic, is because the focal point is either before or after the image plane. This &quot;circle&quot; that is created on the image plane is what is called the circle of confusion. &#xD;&#xA;&#xD;&#xA;Now from this should be clear that varying the depth of field you vary the CoC size, hence it can be used as a measure of the DoF itself and an intuitive one when thinking in terms of blurring. &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;As per how it is implemented in rendering there are really lots of methods out there. Usually in games is done as a post process using the depth information to split your scene in different &quot;planes&quot;; for example a focus plane that does not need to be blurred, a near plane and a far/background plane that need to be blurred. Once you blurred your planes you can composite them back together to get your final image. &#xD;&#xA;How much you blur the various planes it is dependent on the effect you want to achieve. Advanced system usually implement this and other &quot;lenses&quot; effect using appropriate parameters coming from the photography world like the aperture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note that there are many ways to implement the effect, the one I described is just one way that also has variations (for example performing the whole thing at lower res). The limit is dependent on what your target is and how much you budgeted for this effect. You can go from adopting the &quot;3 planes&quot; method at extremely low res to computing the circle of confusion for each pixel and applying the consequent ad-hoc blur to that pixel. &#xD;&#xA;&#xD;&#xA;________&#xD;&#xA;&#xD;&#xA;EDIT: The comment from @NathanReed needs to be more in evidence as part of the answer: &#xD;&#xA;&#xD;&#xA;&gt; Matt Pettineo's blog posts [How To Fake Bokeh][3] and [Bokeh II: The Sequel][4] are great introductions to how to practically implement post-process DoF and address the typical artifacts you get from it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ezhSb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/g7MnD.png&#xD;&#xA;  [3]: https://mynameismjp.wordpress.com/2011/02/28/bokeh/&#xD;&#xA;  [4]: https://mynameismjp.wordpress.com/2011/04/19/bokeh-ii-the-sequel/" ContentLicense="CC BY-SA 3.0" />
  <row Id="219" PostHistoryTypeId="2" PostId="77" RevisionGUID="291e35ed-4c96-4f70-8813-1ed379c58850" CreationDate="2015-08-05T22:04:17.097" UserId="48" Text="Generally, uniformly-weighted samples with a variable distribution (importance sampling) gives lower variance in the final average than uniformly-distributed samples with variable weights.  This is a common rule of thumb in Monte Carlo raytracing.&#xD;&#xA;&#xD;&#xA;However, another thing to consider is that you'll eventually be converting the images to RGB for display (I assume).  So a potential problem might be that if a light source has very little energy in the blue part of the spectrum, for instance, then you'll put few samples in the blue frequencies, and the blue channel of the final RGB image could end up excessively noisy compared to the other channels.&#xD;&#xA;&#xD;&#xA;One way to resolve this might be to consider the product of the light source's spectrum with the RGB color-matching curves used to generate the output.  You could normalize the three against each other to ensure you get enough samples in all three channels, but still distribute the samples to the most important frequencies for each channel.&#xD;&#xA;&#xD;&#xA;On balance, I suspect that simply using a uniform frequency distribution of samples will be simpler and give good results as long as the light source spectra are fairly smooth.  But if you have spectra with sharp spikes (e.g. LEDs, lasers, fluorescent lamps) then spectral importance sampling will probably be necessary." ContentLicense="CC BY-SA 3.0" />
  <row Id="221" PostHistoryTypeId="2" PostId="78" RevisionGUID="14afbeb7-c088-46ab-a401-6e4653795c26" CreationDate="2015-08-05T22:23:19.080" UserId="259" Text="That blog post that John mentions is a pretty good start (if I do say so myself!), but there's a bit of extra detail that might be helpful.&#xD;&#xA;&#xD;&#xA;For the PowerVR architecture, the intermediate data structure -- variously called the primitive list or parameter buffer (PB) -- that stores the per-tile data, after all vertex shading and the tiling process is complete, is actually mostly generated and managed by the hardware, rather than the driver.&#xD;&#xA;&#xD;&#xA;The PB's in-memory structures are physically split into two. First, blocks of transformed vertex data, including vertex attributes. The blocks are compressed, and as you can imagine they're just packed and compressed floating point data for the most part. The second in-memory structure is the tiling data, which is effectively a list of lists.&#xD;&#xA;&#xD;&#xA;The top level list in that data structure is called a region, and it can encode a set of tiles rather than single tile at a time, for a given primitive block. A region is therefore a set of locations of screen tiles, tile states, and then a list of the compressed blocks that hold geometry in that region. Regions are what the rasteriser works on, and you can imagine that empty tiles are just automatically skipped, although there's a good reason in some cases for the rasteriser to visit empty regions.&#xD;&#xA;&#xD;&#xA;The memory the GPU uses for the PB is dynamically allocated in all modern PowerVR implementations. A pointer to that memory is provided by the driver, and the driver, with the GPU's help, will size it as required. That mechanism is a tradeoff between having to reallocate frequently and minimising the amount of allocated PB space.&#xD;&#xA;&#xD;&#xA;Modern GPUs try really hard to minimise memory indirection, but walking the PB to feed the rasterisation stage is one of those cases where it's really difficult and there's no other choice. Thankfully the pointer chasing wraps up large blocks that cache well and are streamed into the core.&#xD;&#xA;&#xD;&#xA;Other architectures don't work exactly the same as PowerVR, because part of the reason the PB is the way it is in our architecture is to help the fully deferred pixel shading concept we implement, but the general concept applies to all other tilers in the mobile space that I'm aware of." ContentLicense="CC BY-SA 3.0" />
  <row Id="224" PostHistoryTypeId="2" PostId="79" RevisionGUID="e68cc552-366b-4c7f-ba3a-628b252351e0" CreationDate="2015-08-06T04:25:20.727" UserId="262" Text="I tested several applications/APIs/libraries to get data from FBOs in applications which use gbuffer for example. After months of suffering I discovered [apitrace][1] available con Github to debug OpenGL, Direct3D and WebGL. I used in Windows and Linux without problems.&#xD;&#xA;I hope that be useful for you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://apitrace.github.io/" ContentLicense="CC BY-SA 3.0" />
  <row Id="225" PostHistoryTypeId="5" PostId="79" RevisionGUID="1198057d-ea8a-46c0-9408-7c10e8bf32dc" CreationDate="2015-08-06T04:28:51.917" UserId="260" Comment="fixed a minor typo" Text="I tested several applications/APIs/libraries to get data from FBOs in applications which use gbuffer for example. After months of suffering I discovered [apitrace][1] available on Github to debug OpenGL, Direct3D and WebGL. I used in Windows and Linux without problems.&#xD;&#xA;&#xD;&#xA;I hope that could be useful for you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://apitrace.github.io/" ContentLicense="CC BY-SA 3.0" />
  <row Id="226" PostHistoryTypeId="24" PostId="79" RevisionGUID="1198057d-ea8a-46c0-9408-7c10e8bf32dc" CreationDate="2015-08-06T04:28:51.917" Comment="Proposed by 260 approved by 262 edit id of 14" ContentLicense="CC BY-SA 3.0" />
  <row Id="229" PostHistoryTypeId="2" PostId="80" RevisionGUID="062a3631-a0be-4ca8-9f7b-8dbf91d3c6b2" CreationDate="2015-08-06T06:12:42.647" UserId="48" Text="The de facto standard color space for digital images these days is [sRGB](https://en.wikipedia.org/wiki/SRGB).  sRGB is a good default assumption if working with a display whose exact color space is not known (i.e. most random displays someone might run your app on), or images whose color space encoding is not known (i.e. most random image files you might encounter).&#xD;&#xA;&#xD;&#xA;The sRGB standard defines the [CIE chromaticity](https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space) of the pure red, green, and blue primaries and the white point&amp;mdash;in other words, it defines what those primaries and white should perceptually look like relative to pure wavelengths.&#xD;&#xA;&#xD;&#xA;sRGB also defines a gamma curve that's used for encoding the RGB values.  The gamma curve is the part that graphics programmers are usually concerned with, as we have to convert colors back and forth between sRGB and linear to do lighting math physically-correctly.  All modern GPUs have sRGB support built in: they can automatically apply the gamma transformations in hardware when sampling a texture, or writing a pixel value to a render target.&#xD;&#xA;&#xD;&#xA;As far as monitors are concerned, with a high-quality one it should be possible to calibrate its settings (or it may come pre-calibrated) so that its output matches sRGB as faithfully as possible.  In case the monitor itself can't do it, a limited amount of color correction can also be done on the GPU during scan-out; there are some small hardware lookup tables that the RGB values are mapped through before being sent out over the wire.&#xD;&#xA;&#xD;&#xA;You might also come across [Rec. 709](https://en.wikipedia.org/wiki/Rec._709), which is the standard color space for HDTVs; it's very similar to sRGB, using the same primaries and white point, but a slightly different gamma curve.  Some high-end monitors use the [Adobe RGB](https://en.wikipedia.org/wiki/Adobe_RGB_color_space) color space, which is somewhat wider-gamut than sRGB; photographers tend to like those because they more faithfully represent what photos will look like when printed.  The next generation of HDR TVs coming out (hopefully) in the next few years will use [Rec. 2020](https://en.wikipedia.org/wiki/Rec._2020), which has a huge gamut and requires 10 or 12 bits per component rather than 8.&#xD;&#xA;&#xD;&#xA;So to come back to your question whether you need to worry about different monitors having different gamma: not much.  For gaming and general PC graphics you can pretty much assume sRGB, and figure that if the user really cares about color accuracy, they'll have a good, calibrated monitor.  If you're producing software for photographers or print media, or for next-gen HDR video standards, then you might have to start worrying about wide-gamut color spaces." ContentLicense="CC BY-SA 3.0" />
  <row Id="230" PostHistoryTypeId="2" PostId="81" RevisionGUID="222d1434-eeb5-45ba-aacb-c1209561259c" CreationDate="2015-08-06T06:34:33.160" UserId="48" Text="If you read papers about subsurface scattering, you'll frequently come across references to something called the &quot;dipole approximation&quot;.  This term seems to go back to the paper [A Practical Model for Subsurface Light Transport](https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf) by Henrik Wann Jensen et al, but this paper is pretty difficult to understand.&#xD;&#xA;&#xD;&#xA;Can anyone explain in relatively simple terms what the dipole approximation is and how it's used in rendering subsurface scattering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="231" PostHistoryTypeId="1" PostId="81" RevisionGUID="222d1434-eeb5-45ba-aacb-c1209561259c" CreationDate="2015-08-06T06:34:33.160" UserId="48" Text="What is the &quot;dipole approximation&quot; for subsurface scattering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="232" PostHistoryTypeId="3" PostId="81" RevisionGUID="222d1434-eeb5-45ba-aacb-c1209561259c" CreationDate="2015-08-06T06:34:33.160" UserId="48" Text="|rendering|subsurface-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="233" PostHistoryTypeId="5" PostId="72" RevisionGUID="83461e6c-295d-423b-a71e-35b090270d64" CreationDate="2015-08-06T06:38:38.203" UserId="38" Comment="added 34 characters in body" Text="Yes, while many screens and OS operations are using a gamma of 2.2 your hardware and computation result still need to be corrected. There are also special mediums such as broadcast TV's that have a different gamma. Sensor equipment like cameras are mostly linear so they need to be adjusted accordingly. Besides this the user can set their system to whatever gamma they like. &#xD;&#xA;&#xD;&#xA;In computer graphics primary reason to account for gamma is that your computation is most likely done in linear space\* or summing light contributions becomes unnecessarily complicated. In any case gamma is really a simplification of things, you'd be much much better of doing profile to profile conversions if its possible to invest the computational time to do so.&#xD;&#xA;&#xD;&#xA;## Mathematical explanation&#xD;&#xA;&#xD;&#xA;This may be a simpler to understand. Your monitor has a display error of g(x) which is no problem if your data is conforming to g(x), however if you want to calculate:&#xD;&#xA;&#xD;&#xA;    a+b+c+d&#xD;&#xA;&#xD;&#xA;and a, b, c, d, have the error of g(x) you would actually need to calculate.&#xD;&#xA;&#xD;&#xA;     g(g^-1(a)+g^-1(b)+g^-1(c)+g^-1(d))&#xD;&#xA;&#xD;&#xA;You would need to do this for each sub element over and over again. Therefore instead of running the transform each time you transform all once to linear and then once back. &#xD;&#xA;&#xD;&#xA;## And finally a artistic reason&#xD;&#xA;&#xD;&#xA;It may just look better with a different gamma. Many games have a gamma adjustment for this reason.&#xD;&#xA;&#xD;&#xA;\* Worst case is that you think your computations as linear but do not compensate for the monitors nonlinear output charachteristics." ContentLicense="CC BY-SA 3.0" />
  <row Id="234" PostHistoryTypeId="2" PostId="82" RevisionGUID="165b6851-2e7e-494b-afc5-6634f1f45730" CreationDate="2015-08-06T07:31:40.703" UserId="100" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem. &#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where Ft are Fresnel transmittance and R is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This R is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the ||x_i - x_o|| above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my old thesis where the reflectance profile is described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="235" PostHistoryTypeId="5" PostId="82" RevisionGUID="18f88f95-4d13-4045-a900-ec4c1a242f51" CreationDate="2015-08-06T07:38:19.577" UserId="100" Comment="added 409 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem. &#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where Ft are Fresnel transmittance and R is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This R is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the ||x_i - x_o|| above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my old thesis where the reflectance profile is described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="236" PostHistoryTypeId="5" PostId="82" RevisionGUID="9dddda19-912a-47dd-ae8f-ef4900ed3314" CreationDate="2015-08-06T07:43:21.543" UserId="100" Comment="added 409 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where Ft are Fresnel transmittance and R is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This R is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the ||x_i - x_o|| above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="237" PostHistoryTypeId="5" PostId="82" RevisionGUID="227c26a8-ce7d-48db-a793-fd31f3967033" CreationDate="2015-08-06T09:10:01.717" UserId="100" Comment="deleted 8 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where Ft are Fresnel terms and R is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This R is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the ||x_i - x_o|| above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="240" PostHistoryTypeId="2" PostId="83" RevisionGUID="541d99ba-910c-42a0-8786-b2032ade158f" CreationDate="2015-08-06T13:41:45.743" UserId="157" Text="[Trichoplax question][1] aroused my curiosity and [the answers in this question](http://graphicdesign.stackexchange.com/questions/11445/gamma-vs-brightness-any-difference) also reminded me why I sometimes use different gamma &quot;amounts&quot; to enhance images.&#xD;&#xA;&#xD;&#xA;Therefore, is it possible to determine the amount of gamma applied to an image by knowing its source (the original image)? I.e. can the mathematical formula be applied to compare two images and determine the difference in gamma &quot;amount&quot;?&#xD;&#xA;&#xD;&#xA;Example: which of the following have a different gamma amount (I'll give you a non-edible cookie if you find out, and sorry trichoplax for snatching [your ball][2]):&#xD;&#xA;&#xD;&#xA;[![t_1][3]][3][![t_2][4]][4][![t_3][5]][5][![t_4][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/68/is-gamma-still-important-to-take-into-account&#xD;&#xA;  [2]: https://i.stack.imgur.com/iukw5.png?s=328&amp;g=1&#xD;&#xA;  [3]: https://i.stack.imgur.com/msMpT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/qMPrK.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/5GsqI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/NxJLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="241" PostHistoryTypeId="1" PostId="83" RevisionGUID="541d99ba-910c-42a0-8786-b2032ade158f" CreationDate="2015-08-06T13:41:45.743" UserId="157" Text="Brightness and contrast VS Gamma, is it possible to identify the gamma &quot;correction amount&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="242" PostHistoryTypeId="3" PostId="83" RevisionGUID="541d99ba-910c-42a0-8786-b2032ade158f" CreationDate="2015-08-06T13:41:45.743" UserId="157" Text="|color|gamma|brightness|image-comparison|" ContentLicense="CC BY-SA 3.0" />
  <row Id="243" PostHistoryTypeId="2" PostId="84" RevisionGUID="a93cc122-1fc4-4a25-8113-797e921b7ec1" CreationDate="2015-08-06T14:04:38.327" UserId="100" Text="If I get correctly what you are asking you basically just need to find the G in this equation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This could be easily solved as &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because usally gamma is applied in a uniform fashion on the image, you can just pick any two non zero pixel values (one for source and one for destination) to find out the gamma value applied.  &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nnAol.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/sXcwf.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="244" PostHistoryTypeId="5" PostId="84" RevisionGUID="d4d9ac06-71eb-44f0-90bf-8653b3abd890" CreationDate="2015-08-06T14:21:50.947" UserId="100" Comment="added 208 characters in body" Text="If I get correctly what you are asking you basically just need to find the G in this equation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This could be easily solved as &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because usally gamma is applied in a uniform fashion on the image, you can just pick any two non zero pixel values (one for source and one for destination) to find out the gamma value applied.  &#xD;&#xA;&#xD;&#xA;EDIT: As @ChristianRau pointed out, if you don't actually know if the image has been modified with gamma correction, you have to take an higher amount of samples and trying to fit a gamma function on those. If a fit to a gamma function results in too many significant outliers, then probably gamma correction wasn't the function applied. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nnAol.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/sXcwf.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="246" PostHistoryTypeId="2" PostId="85" RevisionGUID="e3ed8da0-a1ef-4ca7-adec-6534107ddb5c" CreationDate="2015-08-06T14:53:38.463" UserId="56" Text="Bicubic sampling is pretty good for up sampling an image and making it larger,  but is it a good choice for down sampling as well? Are there better choices?" ContentLicense="CC BY-SA 3.0" />
  <row Id="247" PostHistoryTypeId="1" PostId="85" RevisionGUID="e3ed8da0-a1ef-4ca7-adec-6534107ddb5c" CreationDate="2015-08-06T14:53:38.463" UserId="56" Text="Algorithms for down sampling an image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="248" PostHistoryTypeId="3" PostId="85" RevisionGUID="e3ed8da0-a1ef-4ca7-adec-6534107ddb5c" CreationDate="2015-08-06T14:53:38.463" UserId="56" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="249" PostHistoryTypeId="2" PostId="86" RevisionGUID="d6ce0057-da7d-4ad4-9ae4-3cd37da1104e" CreationDate="2015-08-06T15:07:23.013" UserId="125" Text="When Sean and I wrote [stb_image_resize][1] we chose Mitchell for downsizing. Mitchell is similar to Cubic, you can read about the cubic class of sampling filters in [Mitchell Netravali 1988][2]. They are all pretty similar and will get you very similar results.&#xD;&#xA;&#xD;&#xA;I can't find any written record between Sean and I of why we decided to go with Mitchell, but if memory serves we just resampled a bunch of images and used the algorithm that we thought looked best. I wouldn't say that there is one authoritative or best filter, you should use the one that looks best on your data.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/nothings/stb/blob/master/stb_image_resize.h&#xD;&#xA;  [2]: http://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="250" PostHistoryTypeId="5" PostId="86" RevisionGUID="b9ca884a-40d0-4eaa-80e8-59c933d1a49e" CreationDate="2015-08-06T18:02:02.100" UserId="125" Comment="added 219 characters in body" Text="When Sean and I wrote [stb_image_resize][1] we chose Mitchell for downsizing. Mitchell is similar to Cubic, you can read about the cubic class of sampling filters in [Mitchell Netravali 1988][2]. They are all pretty similar and will get you very similar results.&#xD;&#xA;&#xD;&#xA;I can't find any written record between Sean and I of why we decided to go with Mitchell, but if memory serves we just resampled a bunch of images and used the algorithm that we thought looked best. I wouldn't say that there is one authoritative or best filter, you should use the one that looks best on your data.&#xD;&#xA;&#xD;&#xA;Edit: Like joojaa says, a windowed sinc filter is also good, if not quite as cheap. You can find some implementations [here][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/nothings/stb/blob/master/stb_image_resize.h&#xD;&#xA;  [2]: http://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf&#xD;&#xA;  [3]: https://code.google.com/p/imageresampler/source/browse/trunk/resampler.cpp#266" ContentLicense="CC BY-SA 3.0" />
  <row Id="255" PostHistoryTypeId="2" PostId="87" RevisionGUID="776f8444-fc88-4b0e-a532-56b2170d721f" CreationDate="2015-08-06T19:04:26.033" UserId="281" Text="One possible approach could be the use of Hardware Occlusion Query.&#xD;&#xA;&#xD;&#xA;You can use the facts that, by specification, the Stencil Test is executed before the depth test, and only the fragments that pass the depth test are counted by the Occlusion Query.&#xD;&#xA;&#xD;&#xA;You can set the depth test as always pass and therefore count just the fragments that pass the Stencil Test:&#xD;&#xA;&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glDepthFunc(GL_ALWAYS);&#xD;&#xA;        glEnable(GL_STENCIL_TEST);" ContentLicense="CC BY-SA 3.0" />
  <row Id="256" PostHistoryTypeId="2" PostId="88" RevisionGUID="e5f02942-9359-42ab-902e-195cd4ab146b" CreationDate="2015-08-06T21:21:07.490" UserId="231" Text="Start with a precalculated &quot;ray cloud&quot; - the starting point and direction of a large number of rays, most of which will not contribute to the image. The image plane's position and orientation are then specified, and the task is to search the ray cloud for rays that intersect the image plane without occlusion by other objects, and output the resulting pixel values. No ray reflections would be required, as all of the work has already been done in generating the ray cloud. The only step left is to convert the rays to an image. This means that a single ray cloud can be used to generate images from arbitrary view angles.&#xD;&#xA;&#xD;&#xA;How could I go about accelerating this process using a GPU? The decision for each ray of whether it intersects the image plane is parallelisable as these decisions are independent, but each requires access to the objects in the scene as some rays will reach some potential image planes but not others. The final step of sampling the relevant rays across the pixels of the image requires each ray to contribute to a number of the surrounding pixels. Is this also parallelisable using a GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="257" PostHistoryTypeId="1" PostId="88" RevisionGUID="e5f02942-9359-42ab-902e-195cd4ab146b" CreationDate="2015-08-06T21:21:07.490" UserId="231" Text="Can I accelerate rendering an image from a ray cloud using a GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="258" PostHistoryTypeId="3" PostId="88" RevisionGUID="e5f02942-9359-42ab-902e-195cd4ab146b" CreationDate="2015-08-06T21:21:07.490" UserId="231" Text="|raytracing|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="259" PostHistoryTypeId="2" PostId="89" RevisionGUID="74358e29-2cf7-4a1c-9ada-a1c1a96beff6" CreationDate="2015-08-06T21:41:28.387" UserId="231" Text="I want to render realistic images of water in an orbiting space habitat. The image does not need to be generated in real time, although I wouldn't want it to take weeks either. I'm looking for an approach that can generate realistic images in hours or days.&#xD;&#xA;&#xD;&#xA;The habitat is cylindrical with the curved inner surface being the living space. Rotation of the cylinder about it's axis provides an approximation of gravity. I'm not looking for details of simulating the physics of this, just the rendering of an image.&#xD;&#xA;&#xD;&#xA;The specific aspect I want to know about is polarisation. Light reflected from the surface of water is polarised, leaving the light that passed into the water polarised perpendicularly to the reflected light. Ignoring this effect and simply modelling the proportions of light that are reflected and transmitted works reasonably well when there is only one water surface, but if the cylindrical habitat has bodies of water that take up large proportions of the curved surface then a given ray will make multiple reflections at a wide range of different angles. This means the proportion of light that is reflected will depend on the polarisation angle previously applied to it.&#xD;&#xA;&#xD;&#xA;Are there existing approaches that incorporate such effects that could give realistic images of multiple reflections from a curved water surface? They would also need to model refraction with polarisation. The water will be shallow in places so I'm expecting polarised refraction to influence the results.&#xD;&#xA;&#xD;&#xA;If not, could I adapt an existing ray tracer or would this need an approach starting from scratch?&#xD;&#xA;&#xD;&#xA;I'm looking for realism in order to discover unexpected effects, not just to pass as realistic to a casual observer. Obviously most observers (including me) won't know the effects to look for since they aren't familiar from everyday life, so I'm looking for &quot;reasonably physically correct&quot; rather than just &quot;convincing&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="260" PostHistoryTypeId="1" PostId="89" RevisionGUID="74358e29-2cf7-4a1c-9ada-a1c1a96beff6" CreationDate="2015-08-06T21:41:28.387" UserId="231" Text="Polarising reflection and refraction for a wrap around water surface" ContentLicense="CC BY-SA 3.0" />
  <row Id="261" PostHistoryTypeId="3" PostId="89" RevisionGUID="74358e29-2cf7-4a1c-9ada-a1c1a96beff6" CreationDate="2015-08-06T21:41:28.387" UserId="231" Text="|raytracing|physically-based|reflection|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="262" PostHistoryTypeId="2" PostId="90" RevisionGUID="096917f2-a8df-44df-a018-a53f952eb7ee" CreationDate="2015-08-06T21:47:38.553" UserId="231" Text="[Young's double slit experiment] is very simple to set up and simple to explain, but it is an example of both diffraction and interference, neither of which are modelled by conventional raytracing.&#xD;&#xA;&#xD;&#xA;It is straightforward to render an approximation of the result using textures, but that would require knowing in advance what the result should be. For an arbitrary set up, where the number and arrangement of slits is not known in advance, are there any existing algorithms for modelling the effect in order to generate the correct resulting image?&#xD;&#xA;&#xD;&#xA;If not, what would a model need to include in order to accurately produce these effects? Can ray tracing be adapted to use rays carrying additional information, or would an entirely new approach be required?&#xD;&#xA;&#xD;&#xA;  [Young's double slit experiment]: http://en.wikipedia.org/wiki/Double-slit_experiment" ContentLicense="CC BY-SA 3.0" />
  <row Id="263" PostHistoryTypeId="1" PostId="90" RevisionGUID="096917f2-a8df-44df-a018-a53f952eb7ee" CreationDate="2015-08-06T21:47:38.553" UserId="231" Text="Modelling Young's double slit experiment" ContentLicense="CC BY-SA 3.0" />
  <row Id="264" PostHistoryTypeId="3" PostId="90" RevisionGUID="096917f2-a8df-44df-a018-a53f952eb7ee" CreationDate="2015-08-06T21:47:38.553" UserId="231" Text="|raytracing|algorithm|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="265" PostHistoryTypeId="2" PostId="91" RevisionGUID="ccdf99b2-44e0-488c-b243-2b800ff93763" CreationDate="2015-08-06T22:03:19.767" UserId="231" Text="Is it realistic to render a super-high resolution image over an array of 3 by 3 or 5 by 5 (for example) stacked screens? Could I do this by combining several different GPUs, or would the only way be to use a GPU per screen and simply divide the image to be rendered?&#xD;&#xA;&#xD;&#xA;Ideally I'd like to be able to use fewer GPUs than screens. Even though one GPU is insufficient I'm hoping I won't need n GPUs for n screens.&#xD;&#xA;&#xD;&#xA;If this is possible I'd also need to know whether this requires using the same make and model of GPU or whether unrelated ones could still share processing." ContentLicense="CC BY-SA 3.0" />
  <row Id="266" PostHistoryTypeId="1" PostId="91" RevisionGUID="ccdf99b2-44e0-488c-b243-2b800ff93763" CreationDate="2015-08-06T22:03:19.767" UserId="231" Text="Can I use several GPUs for a grid multi screen image" ContentLicense="CC BY-SA 3.0" />
  <row Id="267" PostHistoryTypeId="3" PostId="91" RevisionGUID="ccdf99b2-44e0-488c-b243-2b800ff93763" CreationDate="2015-08-06T22:03:19.767" UserId="231" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="269" PostHistoryTypeId="2" PostId="92" RevisionGUID="891cad34-97ae-4beb-b705-ae9a3c46da46" CreationDate="2015-08-06T22:12:49.037" UserId="79" Text="It is in fact possible to augment a ray tracer to make it capable of simulating wave effects. The paper [Rendering Wave Effects with Augmented Light Field&#xD;&#xA;](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.369.2189&amp;rep=rep1&amp;type=pdf) describes one way to do it. In summary, they introduce a framework called Augmented Light Field that allows them to model wave effects with a ray-based representation. In this framework, rays can carry negative radiance in addition to positive radiance; intuitively, rays carrying negative radiance can &quot;subtract&quot; light from surfaces that it cannot reach because of interference effects, for example.&#xD;&#xA;&#xD;&#xA;I haven't implemented it personally, and I can't speak for its implementation complexity, but I believe it is a good starting point." ContentLicense="CC BY-SA 3.0" />
  <row Id="271" PostHistoryTypeId="2" PostId="93" RevisionGUID="b5d0c3c9-63a6-45b2-8738-dd9828f016a9" CreationDate="2015-08-07T04:01:49.707" UserId="125" Text="It sounds like the tricky part is that last step where each ray affects neighboring pixels. I would consider an approach where you do the first steps as normal (parallelized as on the CPU) without the last step, and then you do that last bit in a new pass. I'm not sure exactly how your ray contributions work so it's tough to say, but it seems like you should be able to use the results from the first part as input and then do your operation in a second pass.&#xD;&#xA;&#xD;&#xA;Blur is done in a similar manner. The blur is done in one dimension, and then the output of that pass is used as the input of the second pass to blur the other dimension. The result is that the value of some pixel ends up contributing to neighboring pixels, so it's similar to your problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="273" PostHistoryTypeId="2" PostId="94" RevisionGUID="69d7a92c-a202-40d9-ab19-903c24cb1a0f" CreationDate="2015-08-07T05:02:41.923" UserId="87" Text="Say I have render targets 0 through N and RT 0 happens to have in its fourth component an alpha channel specified by a material or mask or something.&#xD;&#xA;&#xD;&#xA;Is it possible to have the hardware compositor blend render targets 1 through N using the alpha of the first render target?" ContentLicense="CC BY-SA 3.0" />
  <row Id="274" PostHistoryTypeId="1" PostId="94" RevisionGUID="69d7a92c-a202-40d9-ab19-903c24cb1a0f" CreationDate="2015-08-07T05:02:41.923" UserId="87" Text="Is it possible to alpha blend multiple render targets using a specified alpha?" ContentLicense="CC BY-SA 3.0" />
  <row Id="275" PostHistoryTypeId="3" PostId="94" RevisionGUID="69d7a92c-a202-40d9-ab19-903c24cb1a0f" CreationDate="2015-08-07T05:02:41.923" UserId="87" Text="|opengl|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="276" PostHistoryTypeId="2" PostId="95" RevisionGUID="bd80db92-adf9-4f78-85b7-f50a1dd461f1" CreationDate="2015-08-07T07:38:01.290" UserId="158" Text="When rendering two overlapping co-planar surfaces, a common issue is &quot;z-fighting&quot;, where the renderer can't decide which of the two surfaces is closer to the camera, giving visual artifacts in the area of overlap.&#xD;&#xA;&#xD;&#xA;The standard solution to this is to give the surfaces a slight offset when designing the model.  Is there any other solution?" ContentLicense="CC BY-SA 3.0" />
  <row Id="277" PostHistoryTypeId="1" PostId="95" RevisionGUID="bd80db92-adf9-4f78-85b7-f50a1dd461f1" CreationDate="2015-08-07T07:38:01.290" UserId="158" Text="Avoiding z-fighting with coincident surfaces" ContentLicense="CC BY-SA 3.0" />
  <row Id="278" PostHistoryTypeId="3" PostId="95" RevisionGUID="bd80db92-adf9-4f78-85b7-f50a1dd461f1" CreationDate="2015-08-07T07:38:01.290" UserId="158" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="279" PostHistoryTypeId="2" PostId="96" RevisionGUID="757474a2-52a0-4572-908b-7d98406e853f" CreationDate="2015-08-07T08:24:33.827" UserId="16" Text="When writing non-trivial shaders (just as when writing any other piece of non-trivial code), people make mistakes.&lt;sup&gt;[citation needed]&lt;/sup&gt; However, I can't just debug it like any other code - you can't just attach gdb or the Visual Studio debugger after all. You can't even do printf debugging, because there's no form of console output. What I usually do is render the data I want to look at as colour, but that is a very rudimentary and amateurish solution. I'm sure people have come up with better solutions.&#xD;&#xA;&#xD;&#xA;So how can I actually debug a shader? Is there a way to step through a shader? Can I look at the execution of the shader on a specific vertex/primitive/fragment?&#xD;&#xA;&#xD;&#xA;(This question is specifically about how to debug shader code akin to how one would debug &quot;normal&quot; code, not about debugging things like state changes.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="280" PostHistoryTypeId="1" PostId="96" RevisionGUID="757474a2-52a0-4572-908b-7d98406e853f" CreationDate="2015-08-07T08:24:33.827" UserId="16" Text="How can I debug GLSL shaders?" ContentLicense="CC BY-SA 3.0" />
  <row Id="281" PostHistoryTypeId="3" PostId="96" RevisionGUID="757474a2-52a0-4572-908b-7d98406e853f" CreationDate="2015-08-07T08:24:33.827" UserId="16" Text="|opengl|glsl|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="282" PostHistoryTypeId="4" PostId="91" RevisionGUID="915a61dd-6c68-455c-b8bd-5ed05634e09f" CreationDate="2015-08-07T08:46:51.577" UserId="231" Comment="edited title" Text="Can I use several GPUs for a grid multi screen image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="283" PostHistoryTypeId="5" PostId="87" RevisionGUID="c2d36f86-4b47-47e6-9325-60b00264659d" CreationDate="2015-08-07T08:58:26.940" UserId="281" Comment="added a more complete example to the answer" Text="One possible approach could be the use of Hardware Occlusion Query.&#xD;&#xA;&#xD;&#xA;You can use the facts that, by specification, the Stencil Test is executed before the depth test, and only the fragments that pass the depth test are counted by the Occlusion Query.&#xD;&#xA;&#xD;&#xA;A simple example (not tested) would be like:&#xD;&#xA;&#xD;&#xA;        GLuint samples_query = 0;&#xD;&#xA;        GLuint samples_passed = 0;&#xD;&#xA;        glGenQueries(1, &amp;samples_query);&#xD;&#xA;        // Initialize your buffers and textures ...&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glEnable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;        // Set up the values on the stencil buffer ...&#xD;&#xA;&#xD;&#xA;        // Now we count the fragments that pass the stencil test&#xD;&#xA;        glDepthFunc(GL_ALWAYS); // Set up the depth test to always pass&#xD;&#xA;        glBeginQuery(GL_SAMPLES_PASSED, samples_query);&#xD;&#xA;        // Render your meshes here&#xD;&#xA;        glEndQuery(GL_SAMPLES_PASSED);&#xD;&#xA;        glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT, &amp;samples_passed);&#xD;&#xA;        // samples_passed holds the number of fragments that passed the stencil test (if any)&#xD;&#xA;        &#xD;&#xA;        // Release your resources ...&#xD;&#xA;        glDeleteQueries(1, &amp;samples_query);&#xD;&#xA;        &#xD;&#xA;Note that the call to obtain the number of samples will call forcibly the flush of the pipeline and wait for the query to finish.&#xD;&#xA;If you need a more asynchronous approach you can query wether the occlusion query is done or not by using:&#xD;&#xA;&#xD;&#xA;        GLuint query_done = 0;&#xD;&#xA;        glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT_AVAILABLE, &amp;query_done);&#xD;&#xA;        if (query_done != 0)&#xD;&#xA;            // Your query result is ready&#xD;&#xA;        else&#xD;&#xA;            // Maybe check the next frame?&#xD;&#xA;        if (query_done" ContentLicense="CC BY-SA 3.0" />
  <row Id="284" PostHistoryTypeId="5" PostId="87" RevisionGUID="ca5fb6b2-c723-4951-9582-180ac4a19cdc" CreationDate="2015-08-07T09:06:45.063" UserId="281" Comment="Fixed a typo" Text="One possible approach could be the use of Hardware Occlusion Query.&#xD;&#xA;&#xD;&#xA;You can use the facts that, by specification, the Stencil Test is executed before the depth test, and only the fragments that pass the depth test are counted by the Occlusion Query.&#xD;&#xA;&#xD;&#xA;A simple example (not tested) would be like:&#xD;&#xA;&#xD;&#xA;        GLuint samples_query = 0;&#xD;&#xA;        GLuint samples_passed = 0;&#xD;&#xA;        glGenQueries(1, &amp;samples_query);&#xD;&#xA;        // Initialize your buffers and textures ...&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glEnable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;        // Set up the values on the stencil buffer ...&#xD;&#xA;&#xD;&#xA;        // Now we count the fragments that pass the stencil test&#xD;&#xA;        glDepthFunc(GL_ALWAYS); // Set up the depth test to always pass&#xD;&#xA;        glBeginQuery(GL_SAMPLES_PASSED, samples_query);&#xD;&#xA;        // Render your meshes here&#xD;&#xA;        glEndQuery(GL_SAMPLES_PASSED);&#xD;&#xA;        glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT, &amp;samples_passed);&#xD;&#xA;        // samples_passed holds the number of fragments that passed the stencil test (if any)&#xD;&#xA;        &#xD;&#xA;        // Release your resources ...&#xD;&#xA;        glDeleteQueries(1, &amp;samples_query);&#xD;&#xA;        &#xD;&#xA;Note that the call to obtain the number of samples will call forcibly the flush of the pipeline and wait for the query to finish.&#xD;&#xA;If you need a more asynchronous approach you can query wether the occlusion query is done or not by using:&#xD;&#xA;&#xD;&#xA;        GLuint query_done = 0;&#xD;&#xA;        glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT_AVAILABLE, &amp;query_done);&#xD;&#xA;        if (query_done != 0)&#xD;&#xA;            // Your query result is ready&#xD;&#xA;        else&#xD;&#xA;            // Maybe check the next frame?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="285" PostHistoryTypeId="2" PostId="97" RevisionGUID="d4898901-2e14-4de5-aebf-391311e4a3d5" CreationDate="2015-08-07T09:39:47.633" UserId="21" Text="While it doesn't seem to be possible to actually step through an OpenGL shader, it is possible to get the compilation results.  &#xD;&#xA;The following is taken from the [Android Cardboard Sample](https://github.com/googlesamples/cardboard-java/blob/master/CardboardSample/src/main/java/com/google/vrtoolkit/cardboard/samples/treasurehunt/MainActivity.java).&#xD;&#xA;&#xD;&#xA;    while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {&#xD;&#xA;        Log.e(TAG, label + &quot;: glError &quot; + error);&#xD;&#xA;        throw new RuntimeException(label + &quot;: glError &quot; + error);&#xD;&#xA;&#xD;&#xA;If your code compiles properly, then you have little choice but to try out a different way of communicating the program's state to you. You could signal that a part of the code was reached by, for example, changing the color of a vertex or using a different texture. Which is awkward, but seems to be the only way for now.&#xD;&#xA;&#xD;&#xA;EDIT: For WebGL, I am looking at [this project](http://benvanik.github.io/WebGL-Inspector/), but I've only just found it... can't vouch for it. " ContentLicense="CC BY-SA 3.0" />
  <row Id="286" PostHistoryTypeId="2" PostId="98" RevisionGUID="42cef100-1efa-474c-ba3e-946b70246f6d" CreationDate="2015-08-07T10:27:48.687" UserId="231" Text="I'm looking to use my GPU for non-graphical calculations (artificial life simulations) but ideally I would like to leave this running for weeks at a time, 24 hours a day.&#xD;&#xA;&#xD;&#xA;Is there anything I should take into account before trying this? Is a GPU subject to overheating or shortening of its lifespan by continuous use?&#xD;&#xA;&#xD;&#xA;What about the computer in general (it's a laptop in my case, but I'm interested in the differences in case it's worth me getting a desktop computer for this)? Will running the GPU non-stop place any strain on connected parts of the computer? Are there known problems that result from this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="287" PostHistoryTypeId="1" PostId="98" RevisionGUID="42cef100-1efa-474c-ba3e-946b70246f6d" CreationDate="2015-08-07T10:27:48.687" UserId="231" Text="Is long term continuous use of GPGPU safe for my GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="288" PostHistoryTypeId="3" PostId="98" RevisionGUID="42cef100-1efa-474c-ba3e-946b70246f6d" CreationDate="2015-08-07T10:27:48.687" UserId="231" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="289" PostHistoryTypeId="2" PostId="99" RevisionGUID="840f3ffb-eb00-43f1-b7bb-fa4adca1daab" CreationDate="2015-08-07T10:43:06.360" UserId="296" Text="No, and yes.&#xD;&#xA;&#xD;&#xA;You're well advised to stay away from stress testing your GPU, or CPU, or any tool for that matter that can be exhausted. In this case it's your GPU, and it definitely can be exhausted.&#xD;&#xA;&#xD;&#xA;That said, if you are using a GPU as a GPU, it's much like using a car as a car. If you use it appropriately it will last a long time and do it's functions, vice versa for inappropriate use.&#xD;&#xA;&#xD;&#xA;Using the GPU a lot will put strain on the motherboard, i.e. physical connectors, PCI-e bus, etc. But so will using it once a week for a year.&#xD;&#xA;Overheating will only be a problem if your simulation is spending most if not all of the GPU's resources and a fault occurs in the cooling.&#xD;&#xA;&#xD;&#xA;&gt; it's a laptop in my case, &#xD;&#xA;&#xD;&#xA;I definitely would not run a laptop more than 12 hours a day without expecting a fast and hot demise." ContentLicense="CC BY-SA 3.0" />
  <row Id="290" PostHistoryTypeId="2" PostId="100" RevisionGUID="b5eec2e8-5db4-4b39-8f3a-a4555f639270" CreationDate="2015-08-07T12:37:50.097" UserId="16" Text="I often find myself copy-pasting code between several shaders. This includes both certain computations or data shared between all shaders in a single pipeline, and common computations which all of my vertex shaders need (or any other stage).&#xD;&#xA;&#xD;&#xA;Of course, that's horrible practice: if I need to change the code anywhere, I need to make sure I change it everywhere else.&#xD;&#xA;&#xD;&#xA;Is there an accepted best practice for keeping [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)? Do people just prepend a single common file to all their shaders? Do they write their own rudimentary C-style preprocessor which parses `#include` directives? If there are accepted patterns in the industry, I'd like to follow them." ContentLicense="CC BY-SA 3.0" />
  <row Id="291" PostHistoryTypeId="1" PostId="100" RevisionGUID="b5eec2e8-5db4-4b39-8f3a-a4555f639270" CreationDate="2015-08-07T12:37:50.097" UserId="16" Text="Sharing code between multiple GLSL shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="292" PostHistoryTypeId="3" PostId="100" RevisionGUID="b5eec2e8-5db4-4b39-8f3a-a4555f639270" CreationDate="2015-08-07T12:37:50.097" UserId="16" Text="|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="293" PostHistoryTypeId="2" PostId="101" RevisionGUID="ab4e4844-6c17-4818-b987-9d71f3fd20d4" CreationDate="2015-08-07T13:14:59.983" UserId="100" Text="As far as I know there are no tools that allows you to steps through code in a shader (also, in that case you would have to be able to select just a pixel/vertex you want to &quot;debug&quot;, the execution is likely to vary depending on that). &#xD;&#xA;&#xD;&#xA;What I personally do is a very hacky &quot;colourful debugging&quot;. So I sprinkle a bunch of dynamic branches with &lt;code&gt;#if DEBUG / #endif&lt;/code&gt; guards that basically say &#xD;&#xA; &#xD;&#xA;    &#xD;&#xA;	#if DEBUG&#xD;&#xA;	if( condition ) &#xD;&#xA;		outDebugColour = aColorSignal;&#xD;&#xA;	#endif&#xD;&#xA;	&#xD;&#xA;	.. rest of code .. &#xD;&#xA;	&#xD;&#xA;	// Last line of the pixel shader&#xD;&#xA;	#if DEBUG&#xD;&#xA;	OutColor = outDebugColour;&#xD;&#xA;	#endif&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you can &quot;observe&quot; debug info this way. I usually do various tricks like lerping or blending between various &quot;colour codes&quot; to test various more complex events or non-binary stuff. &#xD;&#xA;&#xD;&#xA;In this &quot;framework&quot; I also find useful to have a set of fixed conventions for common cases so that if I don't have to constantly go back and check what colour I associated with what. &#xD;&#xA;The important thing is have a good support for hot-reloading of shader code, so you can almost interactively change your tracked data/event and switch easily on/off the debug visualization. &#xD;&#xA;&#xD;&#xA;If need to debug something that you cannot display on screen easily, you can always do the same and use one frame analyser tool to inspect your results. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Obv, it goes without saying that if I am not &quot;debugging&quot; a pixel shader or compute shader, I pass this &quot;debugColor&quot; info throughout the pipeline without interpolating it (in GLSL with &lt;code&gt; flat &lt;/code&gt; keyword ) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, this is very hacky and far from proper debugging, but is what I am stuck with not knowing any proper alternative." ContentLicense="CC BY-SA 3.0" />
  <row Id="294" PostHistoryTypeId="5" PostId="101" RevisionGUID="e2dadbbf-7f55-47ff-9a5c-a36e7ba6c392" CreationDate="2015-08-07T14:07:50.750" UserId="100" Comment="added 214 characters in body" Text="As far as I know there are no tools that allows you to steps through code in a shader (also, in that case you would have to be able to select just a pixel/vertex you want to &quot;debug&quot;, the execution is likely to vary depending on that). &#xD;&#xA;&#xD;&#xA;What I personally do is a very hacky &quot;colourful debugging&quot;. So I sprinkle a bunch of dynamic branches with &lt;code&gt;#if DEBUG / #endif&lt;/code&gt; guards that basically say &#xD;&#xA; &#xD;&#xA;    &#xD;&#xA;	#if DEBUG&#xD;&#xA;	if( condition ) &#xD;&#xA;		outDebugColour = aColorSignal;&#xD;&#xA;	#endif&#xD;&#xA;	&#xD;&#xA;	.. rest of code .. &#xD;&#xA;	&#xD;&#xA;	// Last line of the pixel shader&#xD;&#xA;	#if DEBUG&#xD;&#xA;	OutColor = outDebugColour;&#xD;&#xA;	#endif&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you can &quot;observe&quot; debug info this way. I usually do various tricks like lerping or blending between various &quot;colour codes&quot; to test various more complex events or non-binary stuff. &#xD;&#xA;&#xD;&#xA;In this &quot;framework&quot; I also find useful to have a set of fixed conventions for common cases so that if I don't have to constantly go back and check what colour I associated with what. &#xD;&#xA;The important thing is have a good support for hot-reloading of shader code, so you can almost interactively change your tracked data/event and switch easily on/off the debug visualization. I've listed a couple of them [as answer of this other question.][1]&#xD;&#xA;&#xD;&#xA;If need to debug something that you cannot display on screen easily, you can always do the same and use one frame analyser tool to inspect your results. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Obv, it goes without saying that if I am not &quot;debugging&quot; a pixel shader or compute shader, I pass this &quot;debugColor&quot; info throughout the pipeline without interpolating it (in GLSL with &lt;code&gt; flat &lt;/code&gt; keyword ) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, this is very hacky and far from proper debugging, but is what I am stuck with not knowing any proper alternative.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/23/how-can-i-debug-what-is-being-rendered-to-a-frame-buffer-object-in-opengl/25#25" ContentLicense="CC BY-SA 3.0" />
  <row Id="295" PostHistoryTypeId="2" PostId="102" RevisionGUID="c02f9fe6-9ae3-4bbe-a89e-b6f37a1e7a6a" CreationDate="2015-08-07T14:26:32.683" UserId="281" Text="I generally just use the fact that glShaderSource(...) accepts an array of strings as it's input.&#xD;&#xA;&#xD;&#xA;I use a json-based shader definition file, which specifies how a shader (or a program to be more correct) is composed, and there I specify the preprocessor defines I may need, the uniforms it uses, the vertex/fragment shaders file, and all the additional &quot;dependency&quot; files.&#xD;&#xA;These are just collections of functions that gets appended to the source before the actual shader source.&#xD;&#xA;&#xD;&#xA;Just to add, AFAIK, the Unreal Engine 4 uses an #include directive that gets parsed and append all the relevant files, before the compilation, as you were suggesting." ContentLicense="CC BY-SA 3.0" />
  <row Id="296" PostHistoryTypeId="2" PostId="103" RevisionGUID="545e086d-f1e0-482b-95ef-b99a771155e3" CreationDate="2015-08-07T14:42:38.660" UserId="56" Text="Apparently bicubic pixel interpolation is good for scaling up or down an image (in real time or not).&#xD;&#xA;&#xD;&#xA;Is it recommended to use a lowpass filter before downsizing though, or does the bicubic sampling handle aliasing problems at all?" ContentLicense="CC BY-SA 3.0" />
  <row Id="297" PostHistoryTypeId="1" PostId="103" RevisionGUID="545e086d-f1e0-482b-95ef-b99a771155e3" CreationDate="2015-08-07T14:42:38.660" UserId="56" Text="Do you need to use a lowpass filter before downsizing an image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="298" PostHistoryTypeId="3" PostId="103" RevisionGUID="545e086d-f1e0-482b-95ef-b99a771155e3" CreationDate="2015-08-07T14:42:38.660" UserId="56" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="299" PostHistoryTypeId="6" PostId="23" RevisionGUID="8103c590-3c54-4d5a-9cec-181c62bb80cf" CreationDate="2015-08-07T15:58:52.093" UserId="16" Comment="add debugging tag" Text="|opengl|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="300" PostHistoryTypeId="24" PostId="23" RevisionGUID="8103c590-3c54-4d5a-9cec-181c62bb80cf" CreationDate="2015-08-07T15:58:52.093" Comment="Proposed by 16 approved by 100, 116 edit id of 15" ContentLicense="CC BY-SA 3.0" />
  <row Id="301" PostHistoryTypeId="6" PostId="90" RevisionGUID="b0c06fe9-daec-4ee4-be52-967eb3d3418e" CreationDate="2015-08-07T16:52:10.167" UserId="30" Comment="add wave-optics tag" Text="|raytracing|algorithm|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="302" PostHistoryTypeId="24" PostId="90" RevisionGUID="b0c06fe9-daec-4ee4-be52-967eb3d3418e" CreationDate="2015-08-07T16:52:10.167" Comment="Proposed by 30 approved by 100, 231 edit id of 17" ContentLicense="CC BY-SA 3.0" />
  <row Id="304" PostHistoryTypeId="2" PostId="104" RevisionGUID="3d451bb3-84ff-4de8-b131-ab22293175a2" CreationDate="2015-08-07T18:39:26.880" UserId="307" Text="There is also [GLSL-Debugger][1]. It is a debugger used to be known as &quot;GLSL Devil&quot;.&#xD;&#xA;&#xD;&#xA;The Debugger itself is super handy not only for GLSL code, but for OpenGL itself as well. You have the ability to jump between draw calls and break on Shader switches. It also shows you error messages communicated by OpenGL back to the application itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/GLSL-Debugger/GLSL-Debugger" ContentLicense="CC BY-SA 3.0" />
  <row Id="306" PostHistoryTypeId="2" PostId="105" RevisionGUID="8343676b-9656-4ddf-bd80-39571bf9ca02" CreationDate="2015-08-07T18:57:35.670" UserId="158" Text="Running a GPU at full capacity will reduce its lifespan through [electromigration][1]; the speed at which the chips are damaged depends on how hot it is.&#xD;&#xA;&#xD;&#xA;A desktop computer has enough room that the designer can put in a cooling system to handle the worst-case thermal situation.  Running your GPU at continuous full load won't overheat it too badly, and you can expect it to last several years.&#xD;&#xA;&#xD;&#xA;A laptop, on the other hand, is strongly space-constrained.  Typically, the cooling system is designed to handle brief bursts of heat interspersed with long periods of near-idle operation.  You may not be *able* to run it at full load 24/7: the BIOS or operating system will slow things down to keep from overheating.  In any case, running at full capacity will likely cause things to burn out in a year or less.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Electromigration" ContentLicense="CC BY-SA 3.0" />
  <row Id="307" PostHistoryTypeId="2" PostId="106" RevisionGUID="6f2e96f5-01fa-43aa-b2c0-1da182070d0b" CreationDate="2015-08-07T19:11:21.303" UserId="54" Text="I don't think there is a common convention, but if I'd take a guess, I'd say that almost everyone implements some simple form of textual inclusion as a preprocessing step (an `#include` extension), because it is very easy to do so. (In JavaScript/WebGL, you can do that with a simple regular-expression, for example).&#xD;&#xA;&#xD;&#xA;In fact, an indication that this approach is common is the fact that an ARB extension was introduced for that: [`GL_ARB_shading_language_include`](https://www.opengl.org/registry/specs/ARB/shading_language_include.txt).&#xD;&#xA;&#xD;&#xA;I'm not sure if this became a core feature by now or not, but the extension was written against OpenGL 3.2.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="308" PostHistoryTypeId="2" PostId="107" RevisionGUID="dabee4c3-76b7-4f50-9834-33c8cbb50a81" CreationDate="2015-08-07T20:33:07.803" UserId="310" Text="If the surfaces are exactly co-planer, your fate is up to the FPU gods; you'll more than likely have Z-fighting. If the triangles are *identical* and you do the *exact* same math to each, theoretically you *might* be able to avoid Z-fighting. But, that's up the hardware.&#xD;&#xA;&#xD;&#xA;One possible solution is to not use the Z-buffer at all. Rather you can use the [Painter's Algorithm](https://en.wikipedia.org/wiki/Painter%27s_algorithm). Granted, this comes with all the problems of the painters algorithm as well. But, it would solve the Z-fighting.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="309" PostHistoryTypeId="5" PostId="106" RevisionGUID="6e252530-3a38-4a3b-a82f-7b322eed1796" CreationDate="2015-08-07T23:09:16.677" UserId="54" Comment="added 152 characters in body" Text="I don't think there is a common convention, but if I'd take a guess, I'd say that almost everyone implements some simple form of textual inclusion as a preprocessing step (an `#include` extension), because it is very easy to do so. (In JavaScript/WebGL, you can do that with a simple regular-expression, for example). The upside of this is that you can perform the preprocessing in an offline step for &quot;release&quot; builds, when the shader code no longer needs to be changed.&#xD;&#xA;&#xD;&#xA;In fact, an indication that this approach is common is the fact that an ARB extension was introduced for that: [`GL_ARB_shading_language_include`](https://www.opengl.org/registry/specs/ARB/shading_language_include.txt).&#xD;&#xA;I'm not sure if this became a core feature by now or not, but the extension was written against OpenGL 3.2.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="310" PostHistoryTypeId="5" PostId="107" RevisionGUID="0b4836df-d25f-4c1a-a05c-e43ba602873c" CreationDate="2015-08-08T00:26:12.253" UserId="310" Comment="Added section for SSDs" Text="If the surfaces are exactly co-planer, your fate is up to the FPU gods; you'll more than likely have Z-fighting. If the triangles are *identical* and you do the *exact* same math to each, theoretically you *might* be able to avoid Z-fighting. But, that's up the hardware.&#xD;&#xA;&#xD;&#xA;One possible solution is to not use the Z-buffer at all. Rather you can use the [Painter's Algorithm](https://en.wikipedia.org/wiki/Painter%27s_algorithm). Granted, this comes with all the problems of the painters algorithm as well. But, it would solve the Z-fighting.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In your example case of Screen Space Decals (SSDs), the common solution is to use an offset, aka a simple thin cube. See Warhammer 40k's [presentation](http://www.slideshare.net/blindrenderer/screen-space-decals-in-warhammer-40000-space-marine-14699854) about SSDs for reference. Or Bart Wronski's [post](http://bartwronski.com/2015/03/12/fixing-screen-space-deferred-decals/) which addresses some other issues with decals, but also links to a few other presentations about SSDs" ContentLicense="CC BY-SA 3.0" />
  <row Id="311" PostHistoryTypeId="2" PostId="108" RevisionGUID="06679925-211c-445e-95bd-679a835af646" CreationDate="2015-08-08T01:15:07.103" UserId="310" Text="I'm not quite sure I fully understand the problem, this is what I think you're asking:&#xD;&#xA;&#xD;&#xA; - You start with a set of rays pointing a all sorts of directions&#xD;&#xA; - You want to know which of these rays intersect with the image plane, taking into account occlusion. &#xD;&#xA; - I'm going to assume these rays carry some kind of color information along with them. IE. when they hit the image plane, they will accumulate color.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;With that goal in mind, I would do the following:&#xD;&#xA;&#xD;&#xA; 1. Create 2 image buffers&#xD;&#xA;  1. For accumulated color&#xD;&#xA;  2. To keep track of the number of hits&#xD;&#xA; 2. Clear the accumulation buffer to black, and the hitCount buffer to all zeros&#xD;&#xA; 3. Create a kernel per ray&#xD;&#xA;  1. Use classic ray tracing math to find the nearest intersection&#xD;&#xA;   - Here you can do anything from a simple 'iterate through all the object in the scene' to something like BVHs, or kd-trees.&#xD;&#xA;  2. If the closest intersection is the image plane, use the WorldView matrix for the image plane to transform the intersection point from world coordinates to view space coordinates.&#xD;&#xA;  3. Use the x, y coordinates of the image space intersection point to get the pixel coordinates of the image buffer&#xD;&#xA;  4. Add the color of the ray to the corresponding pixel in the accumulation buffer&#xD;&#xA;  5. Increment the value of the corresponding pixel in the hitCount buffer&#xD;&#xA;   - For 4 and 5 you could also use a filter in order to apply the color to multiple pixels, rather than just one. In that case, you would add a value less than 1 to the hitCount buffer&#xD;&#xA; 4. On the CPU, or in another pass per pixel: &#xD;&#xA;  1. Divide the accumulated color buffer by the hitCount buffer&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;I don't see any problem with doing these steps on the GPU. Any of the compute languages should handle it fine. You might get some divergence in the actual ray tracing code, but it should be ok. The biggest potential problem is that you have to store the entire scene in VRAM.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="313" PostHistoryTypeId="2" PostId="109" RevisionGUID="47b96ab2-e278-4f76-bf27-c3ac7b384734" CreationDate="2015-08-08T01:33:56.490" UserId="311" Text="Some people like to use the array of strings passed to `glShaderSource` as a way to prepend common definitions before your code, but this has some disadvantages:&#xD;&#xA;&#xD;&#xA;1. It's harder to control what needs to be included from within the shader (you need a separate system for this.)&#xD;&#xA;2. It means the shader author cannot specify the GLSL `#version`, due to the following statement in the GLSL spec:&#xD;&#xA;&#xD;&#xA;&gt;  The **#version** directive must occur in a shader before anything else, except for comments and white space.&#xD;&#xA;&#xD;&#xA;Due to this statement, `glShaderSource` cannot be used to prepend text before the `#version` declarations. This means that the `#version` line needs to be included in your `glShaderSource` arguments, which means that your GLSL compiler interface needs to somehow be told what version of GLSL is expected to be used. Additionally, not specifying a `#version` will make the GLSL compiler default to using GLSL version 1.10. If you want to let shader authors specify the `#version` within the script in a standard way, then you need to somehow insert `#include`-s after the `#version` statement. This could be done by explicitly parsing the GLSL shader to find the `#version` string (if present) and make your inclusions after it, but having access to an `#include` directive might be preferable to control more easily when those inclusions need to be made. On the other hand, since GLSL ignores comments before the `#version` line, you could add metadata for includes within comments at the top of your file (yuck.)&#xD;&#xA;&#xD;&#xA;The question now is: Is there a standard solution for `#include`, or do you need to roll your own preprocessor extension?&#xD;&#xA;&#xD;&#xA;There is the `GL_ARB_shading_language_include` extension, but it has two main drawbacks:&#xD;&#xA;&#xD;&#xA;1. It is only supported by NVIDIA (http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include)&#xD;&#xA;2. It works by specifying the include strings ahead of time. Therefore, before compiling, you need to specify that the string `&quot;/buffers.glsl&quot;` (as used in `#include &quot;/buffers.glsl&quot;`) corresponds to the contents of the file `buffer.glsl` (which you have loaded previously).&#xD;&#xA;&#xD;&#xA;A common design is to implement your own `#include` mechanism, but this can be tricky since you also need to parse (and evaluate) other preprocessor instructions like `#if` in order to properly handle conditional compilation (like header guards.)&#xD;&#xA;&#xD;&#xA;If you implement your own `#include`, you also have some liberties in how you want to implement it:&#xD;&#xA;&#xD;&#xA;* You could pass strings ahead of time (like `GL_ARB_shading_language_include`).&#xD;&#xA;* You could specify an include callback (this is done by DirectX's D3DCompiler library.)&#xD;&#xA;* You could implement a system that always reads directly from the filesystem, as done in typical C applications.&#xD;&#xA;&#xD;&#xA;As a simplification, you can automatically insert header guards for each include in your preprocessing layer, so your processor layer looks like:&#xD;&#xA;&#xD;&#xA;    if (#include and not_included_yet) include_file();&#xD;&#xA;&#xD;&#xA;(Credit to Trent Reed for showing me the above technique.)&#xD;&#xA;&#xD;&#xA;**In conclusion**, there exists no automatic, standard, and simple solution. As a forward-looking solution, you could wait for some eventual SPIR-V OpenGL interface. In that case, the GLSL to SPIR-V compiler would be outside of the GL API, which simplifies implementing things like `#include` greatly. I believe the current widespread method is to just implement a custom preprocessor that works in a way any C programmer should be familiar with." ContentLicense="CC BY-SA 3.0" />
  <row Id="314" PostHistoryTypeId="5" PostId="109" RevisionGUID="02bf7c6b-8f64-4ebb-a3f0-7d0ca5df7cdc" CreationDate="2015-08-08T01:44:20.050" UserId="311" Comment="minor cleanup" Text="Some people like to use the array of strings passed to `glShaderSource` as a way to prepend common definitions before your code, but this has some disadvantages:&#xD;&#xA;&#xD;&#xA;1. It's harder to control what needs to be included from within the shader (you need a separate system for this.)&#xD;&#xA;2. It means the shader author cannot specify the GLSL `#version`, due to the following statement in the GLSL spec:&#xD;&#xA;&#xD;&#xA;&gt;  The **#version** directive must occur in a shader before anything else, except for comments and white space.&#xD;&#xA;&#xD;&#xA;Due to this statement, `glShaderSource` cannot be used to prepend text before the `#version` declarations. This means that the `#version` line needs to be included in your `glShaderSource` arguments, which means that your GLSL compiler interface needs to somehow be told what version of GLSL is expected to be used. Additionally, not specifying a `#version` will make the GLSL compiler default to using GLSL version 1.10. If you want to let shader authors specify the `#version` within the script in a standard way, then you need to somehow insert `#include`-s after the `#version` statement. This could be done by explicitly parsing the GLSL shader to find the `#version` string (if present) and make your inclusions after it, but having access to an `#include` directive might be preferable to control more easily when those inclusions need to be made. On the other hand, since GLSL ignores comments before the `#version` line, you could add metadata for includes within comments at the top of your file (yuck.)&#xD;&#xA;&#xD;&#xA;The question now is: Is there a standard solution for `#include`, or do you need to roll your own preprocessor extension?&#xD;&#xA;&#xD;&#xA;There is the `GL_ARB_shading_language_include` extension, but it has two main drawbacks:&#xD;&#xA;&#xD;&#xA;1. It is only supported by NVIDIA (http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include)&#xD;&#xA;2. It works by specifying the include strings ahead of time. Therefore, before compiling, you need to specify that the string `&quot;/buffers.glsl&quot;` (as used in `#include &quot;/buffers.glsl&quot;`) corresponds to the contents of the file `buffer.glsl` (which you have loaded previously).&#xD;&#xA;3. As you may have noticed in point (2), your paths need to start with `&quot;/&quot;`, like Linux-style absolute paths. This notation is generally unfamiliar to C programmers, and means you can't specify relative paths.&#xD;&#xA;&#xD;&#xA;A common design is to implement your own `#include` mechanism, but this can be tricky since you also need to parse (and evaluate) other preprocessor instructions like `#if` in order to properly handle conditional compilation (like header guards.)&#xD;&#xA;&#xD;&#xA;If you implement your own `#include`, you also have some liberties in how you want to implement it:&#xD;&#xA;&#xD;&#xA;* You could pass strings ahead of time (like `GL_ARB_shading_language_include`).&#xD;&#xA;* You could specify an include callback (this is done by DirectX's D3DCompiler library.)&#xD;&#xA;* You could implement a system that always reads directly from the filesystem, as done in typical C applications.&#xD;&#xA;&#xD;&#xA;As a simplification, you can automatically insert header guards for each include in your preprocessing layer, so your processor layer looks like:&#xD;&#xA;&#xD;&#xA;    if (#include and not_included_yet) include_file();&#xD;&#xA;&#xD;&#xA;(Credit to Trent Reed for showing me the above technique.)&#xD;&#xA;&#xD;&#xA;**In conclusion**, there exists no automatic, standard, and simple solution. As a forward-looking solution, you could wait for some eventual SPIR-V OpenGL interface. In that case, the GLSL to SPIR-V compiler would be outside of the GL API, which simplifies implementing things like `#include` greatly. I believe the current widespread method is to just implement a custom preprocessor that works in a way any C programmer should be familiar with." ContentLicense="CC BY-SA 3.0" />
  <row Id="315" PostHistoryTypeId="5" PostId="109" RevisionGUID="50d5e111-0839-4feb-ab1f-852ae5d7b40e" CreationDate="2015-08-08T02:43:55.763" UserId="311" Comment="little changes in conclusion" Text="Some people like to use the array of strings passed to `glShaderSource` as a way to prepend common definitions before your code, but this has some disadvantages:&#xD;&#xA;&#xD;&#xA;1. It's harder to control what needs to be included from within the shader (you need a separate system for this.)&#xD;&#xA;2. It means the shader author cannot specify the GLSL `#version`, due to the following statement in the GLSL spec:&#xD;&#xA;&#xD;&#xA;&gt;  The **#version** directive must occur in a shader before anything else, except for comments and white space.&#xD;&#xA;&#xD;&#xA;Due to this statement, `glShaderSource` cannot be used to prepend text before the `#version` declarations. This means that the `#version` line needs to be included in your `glShaderSource` arguments, which means that your GLSL compiler interface needs to somehow be told what version of GLSL is expected to be used. Additionally, not specifying a `#version` will make the GLSL compiler default to using GLSL version 1.10. If you want to let shader authors specify the `#version` within the script in a standard way, then you need to somehow insert `#include`-s after the `#version` statement. This could be done by explicitly parsing the GLSL shader to find the `#version` string (if present) and make your inclusions after it, but having access to an `#include` directive might be preferable to control more easily when those inclusions need to be made. On the other hand, since GLSL ignores comments before the `#version` line, you could add metadata for includes within comments at the top of your file (yuck.)&#xD;&#xA;&#xD;&#xA;The question now is: Is there a standard solution for `#include`, or do you need to roll your own preprocessor extension?&#xD;&#xA;&#xD;&#xA;There is the `GL_ARB_shading_language_include` extension, but it has two main drawbacks:&#xD;&#xA;&#xD;&#xA;1. It is only supported by NVIDIA (http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include)&#xD;&#xA;2. It works by specifying the include strings ahead of time. Therefore, before compiling, you need to specify that the string `&quot;/buffers.glsl&quot;` (as used in `#include &quot;/buffers.glsl&quot;`) corresponds to the contents of the file `buffer.glsl` (which you have loaded previously).&#xD;&#xA;3. As you may have noticed in point (2), your paths need to start with `&quot;/&quot;`, like Linux-style absolute paths. This notation is generally unfamiliar to C programmers, and means you can't specify relative paths.&#xD;&#xA;&#xD;&#xA;A common design is to implement your own `#include` mechanism, but this can be tricky since you also need to parse (and evaluate) other preprocessor instructions like `#if` in order to properly handle conditional compilation (like header guards.)&#xD;&#xA;&#xD;&#xA;If you implement your own `#include`, you also have some liberties in how you want to implement it:&#xD;&#xA;&#xD;&#xA;* You could pass strings ahead of time (like `GL_ARB_shading_language_include`).&#xD;&#xA;* You could specify an include callback (this is done by DirectX's D3DCompiler library.)&#xD;&#xA;* You could implement a system that always reads directly from the filesystem, as done in typical C applications.&#xD;&#xA;&#xD;&#xA;As a simplification, you can automatically insert header guards for each include in your preprocessing layer, so your processor layer looks like:&#xD;&#xA;&#xD;&#xA;    if (#include and not_included_yet) include_file();&#xD;&#xA;&#xD;&#xA;(Credit to Trent Reed for showing me the above technique.)&#xD;&#xA;&#xD;&#xA;**In conclusion**, there exists no automatic, standard, and simple solution. In a future solution, you could use some SPIR-V OpenGL interface, in which case the GLSL to SPIR-V compiler could be outside of the GL API. Having the compiler outside the OpenGL runtime greatly simplifies implementing things like `#include` since it's a more appropriate place to interface with the filesystem. I believe the current widespread method is to just implement a custom preprocessor that works in a way any C programmer should be familiar with." ContentLicense="CC BY-SA 3.0" />
  <row Id="316" PostHistoryTypeId="2" PostId="110" RevisionGUID="c4c9d29e-8387-41f8-a9a2-0b7bf808cdf2" CreationDate="2015-08-08T05:31:58.103" UserId="182" Text="Some people have already pointed out that `glShaderSource` can take an array of strings.&#xD;&#xA;&#xD;&#xA;On top of that, in GLSL the compilation (`glShaderSource`, `glCompileShader`) and linking (`glAttachShader`, `glLinkProgram`) of shader is separate.&#xD;&#xA;&#xD;&#xA;I have used that in some projects to split shaders between the specific part, and the parts common to most shaders, which is then compiled and shared with all shader programs. This works and is not difficult to implement: you just have to maintain a dependency list.&#xD;&#xA;&#xD;&#xA;In terms of maintainability though, I am not sure it is a win. The observation was the same, let's try to factorize. While it indeed avoids repetition, the overhead of the technique feels significant. Moreover, the final shader is more difficult to extract: you cannot just concatenate the shader sources, as the declarations end in an order that some compilers will reject, or will be duplicated. So it makes it more difficult to do a quick shader test in a separate tool.&#xD;&#xA;&#xD;&#xA;In the end this technique addresses some DRY issues, but it's far from ideal.&#xD;&#xA;&#xD;&#xA;On a side topic, I am not sure if this approach has any impact in terms of compilation time; I have read that some drivers only really compile the shader program on linking, but I haven't measured." ContentLicense="CC BY-SA 3.0" />
  <row Id="317" PostHistoryTypeId="2" PostId="111" RevisionGUID="aa3fa005-0f34-41fa-82fd-88be8c51b3ce" CreationDate="2015-08-08T06:30:49.560" UserId="48" Text="As far as I'm aware there's no way in either DX or GL to re-use RT 0's alpha for all the blending operations.  Unfortunately, it doesn't seem to be something that's supported by hardware.&#xD;&#xA;&#xD;&#xA;You can configure different blend modes for each render target, or enable blending for some and disable for others; however, if blending is enabled for a render target, it always uses its own alpha.&#xD;&#xA;&#xD;&#xA;There's also a mode called &quot;dual-source blending&quot; (see [DX11 doc](https://msdn.microsoft.com/en-us/library/windows/desktop/bb205120.aspx#dual_source) and [OGL doc](https://www.opengl.org/wiki/Blending#Dual_Source_Blending)), which allows you to specify the alpha for blending with an entirely separate output from the pixel shader, not the render target's alpha channel.  However, this mode only works with one render target on current hardware.&#xD;&#xA;&#xD;&#xA;So as far as I can tell, the only options for blending several render targets with the same alpha are:&#xD;&#xA;&#xD;&#xA;* Output the same alpha on all render targets (sacrificing the ability to store other values to the alpha channel as you would in deferred shading, for instance).&#xD;&#xA;* Repeat the rendering in a separate pass for each render target, using dual-source blending.&#xD;&#xA;* Use UAVs / image load-store to execute the blending in the pixel shader (only works if geometry is non-self-overlapping in screen space, because there's no protection against race conditions; also probably kinda slow).&#xD;&#xA;* On hardware that supports it, [DX11.3/DX12 Rasterizer-Order Views](https://msdn.microsoft.com/en-us/library/windows/desktop/dn914601.aspx), [NV_fragment_shader_interlock](https://www.opengl.org/registry/specs/NV/fragment_shader_interlock.txt), or [INTEL_fragment_shader_ordering](https://www.opengl.org/registry/specs/INTEL/fragment_shader_ordering.txt) (the latter also exposed by AMD GPUs).  These are three names for the same thing: basically a &quot;critical section&quot; in the pixel shader that lets you read-modify-write a texture atomically with respect to other pixel shader invocations. It essentially enables arbitrary programmable blending, but it's probably fairly slow, and only available on recent hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="319" PostHistoryTypeId="2" PostId="112" RevisionGUID="5d017d37-0819-437e-b224-609ebc5f4aa4" CreationDate="2015-08-08T07:11:05.800" UserId="48" Text="If the downsampling pass is properly designed, it will effectively perform low-pass filtering as part of the downsampling.  There is no need for a separate low-pass filter operation.&#xD;&#xA;&#xD;&#xA;Essentially, when you downsample, you are performing a filter over the source (high-res) image pixels, but only evaluating it at the locations of the destination (low-res) pixels.  The footprint of this filter needs to be approximately the spacing between destination pixels, to avoid missing information by skipping over in-between source pixels.  But that means the filter footprint will be several source pixels wide, so it will effectively low-pass the source.&#xD;&#xA;&#xD;&#xA;For example, let's suppose you downsample an image by exactly 10x on each axis.  With a box filter (for example's sake), you would set each destination pixel to the average of a 10x10 box of source pixels.  That would wipe out any features smaller than 10px, so it's effectively a low-pass filter.&#xD;&#xA;&#xD;&#xA;You mention bicubic interpolation; we have to make a distinction between filtering and interpolation here.  Interpolation is appropriate for upsampling, not downsampling.  Bicubic interpolation works by fitting a bicubic spline patch to a 4x4 neighborhood of pixels, then evaluating the patch at interpolated points. While it may work well enough for downsampling images by a small factor (up to 2x or so), it will fail if you go much further than that.  For instance, if downsampling by 10x as in the previous example, you can see that bicubic will miss the majority of the source pixels, and the result may be quite aliased.&#xD;&#xA;&#xD;&#xA;On the other hand, bicubic *filtering* is just standard filtering, using a kernel that's a bicubic function (as opposed to a box, triangle, Gaussian, Lanczos, etc. kernel).  The Mitchell-Netravali kernel is the classic example of this type.  If used for downsampling, the kernel should be sized appropriately for the destination pixel spacing as discussed earlier, and you would sum over all the pixels in the footprint, not just a 4x4 or other fixed-size neighborhood." ContentLicense="CC BY-SA 3.0" />
  <row Id="320" PostHistoryTypeId="5" PostId="101" RevisionGUID="68b8d0cb-7e34-4ad4-b0ab-f7e2283bde31" CreationDate="2015-08-08T07:38:06.277" UserId="100" Comment="edited body" Text="As far as I know there are no tools that allows you to steps through code in a shader (also, in that case you would have to be able to select just a pixel/vertex you want to &quot;debug&quot;, the execution is likely to vary depending on that). &#xD;&#xA;&#xD;&#xA;What I personally do is a very hacky &quot;colourful debugging&quot;. So I sprinkle a bunch of dynamic branches with &lt;code&gt;#if DEBUG / #endif&lt;/code&gt; guards that basically say &#xD;&#xA; &#xD;&#xA;    &#xD;&#xA;	#if DEBUG&#xD;&#xA;	if( condition ) &#xD;&#xA;		outDebugColour = aColorSignal;&#xD;&#xA;	#endif&#xD;&#xA;	&#xD;&#xA;	.. rest of code .. &#xD;&#xA;	&#xD;&#xA;	// Last line of the pixel shader&#xD;&#xA;	#if DEBUG&#xD;&#xA;	OutColor = outDebugColour;&#xD;&#xA;	#endif&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you can &quot;observe&quot; debug info this way. I usually do various tricks like lerping or blending between various &quot;colour codes&quot; to test various more complex events or non-binary stuff. &#xD;&#xA;&#xD;&#xA;In this &quot;framework&quot; I also find useful to have a set of fixed conventions for common cases so that if I don't have to constantly go back and check what colour I associated with what. &#xD;&#xA;The important thing is have a good support for hot-reloading of shader code, so you can almost interactively change your tracked data/event and switch easily on/off the debug visualization. &#xD;&#xA;&#xD;&#xA;If need to debug something that you cannot display on screen easily, you can always do the same and use one frame analyser tool to inspect your results. I've listed a couple of them [as answer of this other question.][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Obv, it goes without saying that if I am not &quot;debugging&quot; a pixel shader or compute shader, I pass this &quot;debugColor&quot; info throughout the pipeline without interpolating it (in GLSL with &lt;code&gt; flat &lt;/code&gt; keyword ) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, this is very hacky and far from proper debugging, but is what I am stuck with not knowing any proper alternative.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/23/how-can-i-debug-what-is-being-rendered-to-a-frame-buffer-object-in-opengl/25#25" ContentLicense="CC BY-SA 3.0" />
  <row Id="321" PostHistoryTypeId="2" PostId="113" RevisionGUID="0c2e851a-f174-4fe4-8f40-8b306d8e97be" CreationDate="2015-08-08T07:46:26.633" UserId="48" Text="Yes, it's certainly possible to do this kind of thing.  First of all, you can typically connect 3 or 4 displays to each GPU, and (with an appropriate motherboard) you can have up to 4 GPUs per machine.  That would give you 16 screens.  With multiple machines, you could have even more.&#xD;&#xA;&#xD;&#xA;Rendering to multiple displays from a single GPU is no big deal.  You can create a single window that stretches across all the displays, render to it, and it should &quot;just work&quot;.&#xD;&#xA;&#xD;&#xA;Rendering the same scene on multiple GPUs is a bit trickier.  One way is to create a separate rendering context on each GPU, and essentially repeat all the rendering&amp;mdash;re-upload all buffers and textures to each GPU, and re-submit the draw calls to each one every frame.  Another possibility is to use the [built-in multi-GPU support in DX12](https://msdn.microsoft.com/en-us/library/windows/desktop/dn933253.aspx), which allows you to manage several GPUs in one rendering context." ContentLicense="CC BY-SA 3.0" />
  <row Id="325" PostHistoryTypeId="5" PostId="82" RevisionGUID="65afda86-8c9a-4990-9865-d05b2d068225" CreationDate="2015-08-08T08:57:34.433" UserId="100" Comment="added 2505 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where Ft are Fresnel terms and R is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This R is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the ||x_i - x_o|| above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;I am putting here the answers to a couple of @NathanReed 's questions in the comment section:&#xD;&#xA;&#xD;&#xA;&gt; Even with the diffusion profile approximation, the BSSRDF model still requires integrating over a radius of nearby points on the surface to gather incoming light, correct? How is that accomplished in, say, a path tracer? Do you have to build some data structure so you can sample points on the surface nearby a given point?&#xD;&#xA;&#xD;&#xA;The BSSRDF approximation still need to be integrated over a certain area, yes. &#xD;&#xA;&#xD;&#xA;In the paper linked they used a Montecarlo ray-tracer randomly sampling around a point with a density defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Where that sigma value is the effective extinction coefficient defined below ( it is dependent on scattering and absorbing coefficient, which are properties of the material) and d is the distance to the point we are evaluating. This density is this way defined because the diffusion term has exponential fall-off. &#xD;&#xA;&#xD;&#xA;In [\[Jensen and Buhler 2002\]][6] they proposed an acceleration technique. One of the main concepts was to decouple the sampling from the evaluation of the diffusion term. This way they perform a hierarchical evaluation of the information computed during the sampling phase to cluster together distant samples when it comes to evaluating the diffusion. The implementation described in the paper uses an octree as structure. &#xD;&#xA;This technique, according to the paper, is order of magnitude faster than the full Monte Carlo integration.  &#xD;&#xA;Unfortunately I never got myself into an off-line implementation, so I can't help more than this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the real-time sum-of-Gaussians approximations the correct radius is implicitly set when defining the variance of the Gaussian blurs that need to be applied.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&gt; Why one positive and one negative light? Is the goal for them to cancel each other in some way?&#xD;&#xA;&#xD;&#xA;Yes, the dipole source method (which dates way before Jensen's paper) is such defined to satisfy some boundary condition. Specifically the fluence must be zero at a certain extrapolated boundary that has a distance from the surface of 2AD where &#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Being F_dr the fresnel reflectivity of the slab considered and that sigma value is the reduced extinction coefficient described below. &#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/q48vD.png&#xD;&#xA;  [6]: http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/fast_bssrdf.pdf&#xD;&#xA;  [7]: https://i.stack.imgur.com/rOdqD.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="326" PostHistoryTypeId="5" PostId="1" RevisionGUID="2686ca6a-0f08-4d81-ac3f-5ee93ab0eebf" CreationDate="2015-08-08T11:28:35.067" UserId="30" Comment="not a true hologram, remove term from title and tag to prevent confusion" Text="I saw a [video](https://www.youtube.com/watch?v=7YWTtCsvgvg) on YouTube where a person uses a transparant, knotted pyramid to display &quot;holograms&quot; using their smartphone. (I have not been able to reproduce this yet, so I can't tell for sure if it works).&#xD;&#xA;&#xD;&#xA;I was wondering, given a model, which transformations I should apply to get the different projections needed to produce this effect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="327" PostHistoryTypeId="4" PostId="1" RevisionGUID="2686ca6a-0f08-4d81-ac3f-5ee93ab0eebf" CreationDate="2015-08-08T11:28:35.067" UserId="30" Comment="not a true hologram, remove term from title and tag to prevent confusion" Text="What transformations should I apply to a model to produce this 3D effect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="328" PostHistoryTypeId="6" PostId="1" RevisionGUID="2686ca6a-0f08-4d81-ac3f-5ee93ab0eebf" CreationDate="2015-08-08T11:28:35.067" UserId="30" Comment="not a true hologram, remove term from title and tag to prevent confusion" Text="|projections|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="329" PostHistoryTypeId="24" PostId="1" RevisionGUID="2686ca6a-0f08-4d81-ac3f-5ee93ab0eebf" CreationDate="2015-08-08T11:28:35.067" Comment="Proposed by 30 approved by 48, 100 edit id of 16" ContentLicense="CC BY-SA 3.0" />
  <row Id="331" PostHistoryTypeId="2" PostId="115" RevisionGUID="abdb250e-234d-4994-880f-dd6e3e9c0969" CreationDate="2015-08-08T18:28:16.773" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="332" PostHistoryTypeId="2" PostId="116" RevisionGUID="509cce47-daca-49e8-9d31-6be557db7f46" CreationDate="2015-08-08T18:28:16.773" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="333" PostHistoryTypeId="2" PostId="117" RevisionGUID="d994d31d-3f73-4363-bf45-e41c874e71fb" CreationDate="2015-08-08T18:33:55.790" UserId="38" Text="How would one do a color separation if there are more than 3 color primaries, or the primaries are nonstandard. In Standard  CMYK conversion K is relatively easy conceptually to figure out. Its just a constant value off all the channels. &#xD;&#xA;&#xD;&#xA;How would one construct a CMY + orange for instance. Or in the case of a led array with say Red, Yellow, Blue and Violet for example. How would one approach this problem. &#xD;&#xA;&#xD;&#xA;I'm fine with a conceptual answer no need to do LAB to end result conversion for example. Though that would be nice." ContentLicense="CC BY-SA 3.0" />
  <row Id="334" PostHistoryTypeId="1" PostId="117" RevisionGUID="d994d31d-3f73-4363-bf45-e41c874e71fb" CreationDate="2015-08-08T18:33:55.790" UserId="38" Text="How to do a color separation with many pirmary colors" ContentLicense="CC BY-SA 3.0" />
  <row Id="335" PostHistoryTypeId="3" PostId="117" RevisionGUID="d994d31d-3f73-4363-bf45-e41c874e71fb" CreationDate="2015-08-08T18:33:55.790" UserId="38" Text="|color|color-separation|conversion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="336" PostHistoryTypeId="2" PostId="118" RevisionGUID="15f0a034-263f-473e-aac3-0e0ca2d24cf5" CreationDate="2015-08-08T19:51:13.280" UserId="327" Text="The mathematical approach to this is to represent the other colors/light sources in terms of your standard primaries in the color space. Represent your target color and available light sources as vectors with, say, the RGB color space as the basis. Figuring out how to display your target color using your available sources then becomes a [change of basis][1], a standard linear algebra operation, where the target basis consists of your LEDs/nonstandard primaries.&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/a/340991/166490" ContentLicense="CC BY-SA 3.0" />
  <row Id="337" PostHistoryTypeId="4" PostId="117" RevisionGUID="fd97cd76-098d-47fb-85d4-217e7ef4de8c" CreationDate="2015-08-08T21:19:14.473" UserId="38" Comment="edited title" Text="How to do a color separation with more than 3 pirmary colors" ContentLicense="CC BY-SA 3.0" />
  <row Id="338" PostHistoryTypeId="5" PostId="109" RevisionGUID="bd679e96-d8d7-43bd-a5d4-833f0b19ac1f" CreationDate="2015-08-08T23:03:34.097" UserId="311" Comment="add note about glAttachShader" Text="There's a bunch of a approaches, but none is perfect.&#xD;&#xA;&#xD;&#xA;It's possible to share code by using `glAttachShader` to combine shaders, but this doesn't make it possible to share things like struct declarations or `#define`-d constants. It does work for sharing functions.&#xD;&#xA;&#xD;&#xA;Some people like to use the array of strings passed to `glShaderSource` as a way to prepend common definitions before your code, but this has some disadvantages:&#xD;&#xA;&#xD;&#xA;1. It's harder to control what needs to be included from within the shader (you need a separate system for this.)&#xD;&#xA;2. It means the shader author cannot specify the GLSL `#version`, due to the following statement in the GLSL spec:&#xD;&#xA;&#xD;&#xA;&gt;  The **#version** directive must occur in a shader before anything else, except for comments and white space.&#xD;&#xA;&#xD;&#xA;Due to this statement, `glShaderSource` cannot be used to prepend text before the `#version` declarations. This means that the `#version` line needs to be included in your `glShaderSource` arguments, which means that your GLSL compiler interface needs to somehow be told what version of GLSL is expected to be used. Additionally, not specifying a `#version` will make the GLSL compiler default to using GLSL version 1.10. If you want to let shader authors specify the `#version` within the script in a standard way, then you need to somehow insert `#include`-s after the `#version` statement. This could be done by explicitly parsing the GLSL shader to find the `#version` string (if present) and make your inclusions after it, but having access to an `#include` directive might be preferable to control more easily when those inclusions need to be made. On the other hand, since GLSL ignores comments before the `#version` line, you could add metadata for includes within comments at the top of your file (yuck.)&#xD;&#xA;&#xD;&#xA;The question now is: Is there a standard solution for `#include`, or do you need to roll your own preprocessor extension?&#xD;&#xA;&#xD;&#xA;There is the `GL_ARB_shading_language_include` extension, but it has two main drawbacks:&#xD;&#xA;&#xD;&#xA;1. It is only supported by NVIDIA (http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include)&#xD;&#xA;2. It works by specifying the include strings ahead of time. Therefore, before compiling, you need to specify that the string `&quot;/buffers.glsl&quot;` (as used in `#include &quot;/buffers.glsl&quot;`) corresponds to the contents of the file `buffer.glsl` (which you have loaded previously).&#xD;&#xA;3. As you may have noticed in point (2), your paths need to start with `&quot;/&quot;`, like Linux-style absolute paths. This notation is generally unfamiliar to C programmers, and means you can't specify relative paths.&#xD;&#xA;&#xD;&#xA;A common design is to implement your own `#include` mechanism, but this can be tricky since you also need to parse (and evaluate) other preprocessor instructions like `#if` in order to properly handle conditional compilation (like header guards.)&#xD;&#xA;&#xD;&#xA;If you implement your own `#include`, you also have some liberties in how you want to implement it:&#xD;&#xA;&#xD;&#xA;* You could pass strings ahead of time (like `GL_ARB_shading_language_include`).&#xD;&#xA;* You could specify an include callback (this is done by DirectX's D3DCompiler library.)&#xD;&#xA;* You could implement a system that always reads directly from the filesystem, as done in typical C applications.&#xD;&#xA;&#xD;&#xA;As a simplification, you can automatically insert header guards for each include in your preprocessing layer, so your processor layer looks like:&#xD;&#xA;&#xD;&#xA;    if (#include and not_included_yet) include_file();&#xD;&#xA;&#xD;&#xA;(Credit to Trent Reed for showing me the above technique.)&#xD;&#xA;&#xD;&#xA;**In conclusion**, there exists no automatic, standard, and simple solution. In a future solution, you could use some SPIR-V OpenGL interface, in which case the GLSL to SPIR-V compiler could be outside of the GL API. Having the compiler outside the OpenGL runtime greatly simplifies implementing things like `#include` since it's a more appropriate place to interface with the filesystem. I believe the current widespread method is to just implement a custom preprocessor that works in a way any C programmer should be familiar with." ContentLicense="CC BY-SA 3.0" />
  <row Id="339" PostHistoryTypeId="2" PostId="119" RevisionGUID="427b9f2e-fc35-403f-9b0c-b9fb5ca8fbb1" CreationDate="2015-08-09T01:57:50.783" UserId="56" Text="Temporal anti aliasing (and other temporal algorithms) work by matching pixels this frame with pixels from the last frame and then using that information.&#xA;&#xA;I get that you can use the last and current frame matrices along with motion vector information to match the pixels between frames.&#xA;&#xA;What I don't get though is how do you know whether the reprojected pixel is valid or not?&#xA;&#xA;Is it by color only? If so, how are animated textures or changing light conditions handled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="340" PostHistoryTypeId="1" PostId="119" RevisionGUID="427b9f2e-fc35-403f-9b0c-b9fb5ca8fbb1" CreationDate="2015-08-09T01:57:50.783" UserId="56" Text="How does temporal reprojection work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="341" PostHistoryTypeId="3" PostId="119" RevisionGUID="427b9f2e-fc35-403f-9b0c-b9fb5ca8fbb1" CreationDate="2015-08-09T01:57:50.783" UserId="56" Text="|post-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="342" PostHistoryTypeId="5" PostId="119" RevisionGUID="52037afd-a785-4279-bc68-59b4f31b8a6b" CreationDate="2015-08-09T03:34:13.070" UserId="56" Comment="added 73 characters in body" Text="Temporal anti aliasing (and other temporal algorithms) work by matching pixels this frame with pixels from the last frame and then using that information.&#xA;&#xA;I get that you can use the last and current frame matrices along with motion vector information to match the pixels between frames.&#xA;&#xA;What I don't get though is how do you know whether the reprojected pixel is valid or not?  For instance the old pixel may now be hidden behind a different object.&#xA;&#xA;Is it by color only? If so, how are animated textures or changing light conditions handled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="343" PostHistoryTypeId="2" PostId="120" RevisionGUID="de497efa-cc19-4150-bb9d-bcea3e683e60" CreationDate="2015-08-09T06:39:28.673" UserId="196" Text="One strategy mentioned in [Brian Karis's talk about TAA][1] is neighborhood clamping. The general idea is that, for the previous frame's pixel to be valid, its color should be in the color range found in the neighborhood (say 3x3 pixels) of the current pixel this frame.&#xD;&#xA;&#xD;&#xA;This rejects history from changing light conditions, which is probably what you want anyway if you don't want moving shadows to produce ghosting.&#xD;&#xA;&#xD;&#xA;(Animated textures, depending on the speed of the animation, could also be handled with a motion vector, if you have a predictable UV mapping or can guess reasonably well.)&#xD;&#xA;&#xD;&#xA;  [1]: http://advances.realtimerendering.com/s2014/epic/TemporalAA.pptx" ContentLicense="CC BY-SA 3.0" />
  <row Id="344" PostHistoryTypeId="4" PostId="117" RevisionGUID="ba5839dd-4b59-440a-8d0e-a223c627abba" CreationDate="2015-08-09T07:16:48.483" UserId="316" Comment="&quot;primary&quot; spelling" Text="How to do a color separation with more than 3 primary colors" ContentLicense="CC BY-SA 3.0" />
  <row Id="345" PostHistoryTypeId="24" PostId="117" RevisionGUID="ba5839dd-4b59-440a-8d0e-a223c627abba" CreationDate="2015-08-09T07:16:48.483" Comment="Proposed by 316 approved by 38 edit id of 20" ContentLicense="CC BY-SA 3.0" />
  <row Id="346" PostHistoryTypeId="2" PostId="121" RevisionGUID="a178baff-f778-43e7-82bb-2d186eabbb75" CreationDate="2015-08-09T08:29:04.527" UserId="198" Text="Alpha blending can be turned on to make surfaces transparent, like so:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;&#xD;&#xA;But this only works if objects are rendered in back to front order. Otherwise things in the background appear in front of closer objects, like the floor in the image below. For particles and GUI elements sorting would be OK, but for triangle meshes it seems like it'd be too much effort and slow, as discussed here: https://www.opengl.org/wiki/Transparency_Sorting.&#xD;&#xA;&#xD;&#xA;What are the common methods to deal with this? I know this is quite broad and am not after in-depth implementation details, just a brief description of some approaches and what might be involved.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/G3Ybm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="347" PostHistoryTypeId="1" PostId="121" RevisionGUID="a178baff-f778-43e7-82bb-2d186eabbb75" CreationDate="2015-08-09T08:29:04.527" UserId="198" Text="What are some methods to render transparency in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="348" PostHistoryTypeId="3" PostId="121" RevisionGUID="a178baff-f778-43e7-82bb-2d186eabbb75" CreationDate="2015-08-09T08:29:04.527" UserId="198" Text="|opengl|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="349" PostHistoryTypeId="5" PostId="121" RevisionGUID="e0982632-9b75-4904-a42a-90f092cc5b42" CreationDate="2015-08-09T08:35:20.127" UserId="198" Comment="added 86 characters in body" Text="Alpha blending can be turned on to make surfaces transparent, like so:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_DEPTH_TEST); //or glDepthMask(GL_FALSE)? depth tests break blending&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;&#xD;&#xA;But this only works if objects are rendered in back to front order. Otherwise things in the background appear in front of closer objects, like the floor in the image below. For particles and GUI elements sorting would be OK, but for triangle meshes it seems like it'd be too much effort and slow, as discussed here: https://www.opengl.org/wiki/Transparency_Sorting.&#xD;&#xA;&#xD;&#xA;What are the common methods to deal with this? I know this is quite broad and am not after in-depth implementation details, just a brief description of some approaches and what might be involved.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/G3Ybm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="350" PostHistoryTypeId="2" PostId="122" RevisionGUID="431afc54-7f3a-493f-bc30-036900219f76" CreationDate="2015-08-09T08:46:52.920" UserId="231" Text="I'm looking for an algorithm that can identify edges across which colour is changing sharply, rather than just finding changes in brightness.&#xD;&#xA;&#xD;&#xA;Is this just a matter of using a different colour space with existing edge detection algorithms, or is there a better approach?" ContentLicense="CC BY-SA 3.0" />
  <row Id="351" PostHistoryTypeId="1" PostId="122" RevisionGUID="431afc54-7f3a-493f-bc30-036900219f76" CreationDate="2015-08-09T08:46:52.920" UserId="231" Text="How can I detect edges between different colours of the same brightness?" ContentLicense="CC BY-SA 3.0" />
  <row Id="352" PostHistoryTypeId="3" PostId="122" RevisionGUID="431afc54-7f3a-493f-bc30-036900219f76" CreationDate="2015-08-09T08:46:52.920" UserId="231" Text="|color|algorithm|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="353" PostHistoryTypeId="2" PostId="123" RevisionGUID="5b4f4b89-eeb8-47e7-96cd-e7d67da4f0da" CreationDate="2015-08-09T08:56:08.447" UserId="198" Text="I'm aware of glFog, which blends between the fog and surface colour based on distance to the camera, like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The equations are even given in the [docs](https://www.opengl.org/sdk/docs/man2/xhtml/glFog.xml).&#xD;&#xA;But the fog is applied immediately in front of the camera. I'm trying to render a water surface and want it to have some depth, for example:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;At the moment I'm just rendering the water surface with alpha blending, as below. What I need is to have the fog based on the distance from the water surface to the bottom of the water. How can I get this distance? For the moment I'm assuming the camera will always be above the water.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2pERbm.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/uEXcwm.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/GsYC5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="354" PostHistoryTypeId="1" PostId="123" RevisionGUID="5b4f4b89-eeb8-47e7-96cd-e7d67da4f0da" CreationDate="2015-08-09T08:56:08.447" UserId="198" Text="Rendering fog underneath water" ContentLicense="CC BY-SA 3.0" />
  <row Id="355" PostHistoryTypeId="3" PostId="123" RevisionGUID="5b4f4b89-eeb8-47e7-96cd-e7d67da4f0da" CreationDate="2015-08-09T08:56:08.447" UserId="198" Text="|opengl|fog|" ContentLicense="CC BY-SA 3.0" />
  <row Id="356" PostHistoryTypeId="2" PostId="124" RevisionGUID="9142b53e-9043-4251-aae6-117d82568787" CreationDate="2015-08-09T08:57:55.630" UserId="170" Text="One option is to use depth peeling. &#xD;&#xA;&#xD;&#xA;Essentially, one processes the scene a set number of times (say, `n` times) in order to determine the closest, second-closest, all the way to `n`th-closest fragments of the scene. &#xD;&#xA;&#xD;&#xA;This processing is done by first applying a regular depth test to the entire scene (which naturally returns the closest surface). One then uses the result of the depth test to filter out the first layer, by ignoring everything with a lesser depth than returned in the depth test.&#xD;&#xA;&#xD;&#xA;Applying the depth test again will then return the second layer. Repeat as needed.&#xD;&#xA;&#xD;&#xA;Once you have the layers, you can just draw all the layers in reverse order (assuming you kept track of the RGBA colors for each layer), blending normally, since the layers are in front-to-back order.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="357" PostHistoryTypeId="2" PostId="125" RevisionGUID="24ce1e01-9aa7-4a2d-98f1-37c0649e0308" CreationDate="2015-08-09T08:58:52.810" UserId="231" Text="Raytracing an image can be performed in parallel by calculating the colour of different pixels on different machines. However, this still requires each machine to have access to the entire scene to be rendered. Is there a way of also subdividing the scene so that different machines have access to different parts of it but can still calculate their assigned pixels correctly?&#xD;&#xA;&#xD;&#xA;I cannot imagine a way in which this could be possible in general. Are there any particular circumstances in which this can be achieved?" ContentLicense="CC BY-SA 3.0" />
  <row Id="358" PostHistoryTypeId="1" PostId="125" RevisionGUID="24ce1e01-9aa7-4a2d-98f1-37c0649e0308" CreationDate="2015-08-09T08:58:52.810" UserId="231" Text="Can I parallelise the scene for a raytraced image, rather than just the pixels?" ContentLicense="CC BY-SA 3.0" />
  <row Id="359" PostHistoryTypeId="3" PostId="125" RevisionGUID="24ce1e01-9aa7-4a2d-98f1-37c0649e0308" CreationDate="2015-08-09T08:58:52.810" UserId="231" Text="|raytracing|scene-description|" ContentLicense="CC BY-SA 3.0" />
  <row Id="360" PostHistoryTypeId="2" PostId="126" RevisionGUID="196a2f05-e504-4089-8b90-3af836013280" CreationDate="2015-08-09T09:07:37.560" UserId="231" Text="If the scene to be raytraced cannot be stored in memory, then without adding more RAM to the machine it seems unrealistic to render it in a practical time span, due to the need to load different parts of the scene from disk potentially several times per pixel.&#xD;&#xA;&#xD;&#xA;Is there any way around this? I'm trying to think of some way of performing a large number of the calculations involving a particular subset of the scene all at once, to reduce the number of times it needs to be loaded into memory. Is there any other way of improving the speed in such a case?" ContentLicense="CC BY-SA 3.0" />
  <row Id="361" PostHistoryTypeId="1" PostId="126" RevisionGUID="196a2f05-e504-4089-8b90-3af836013280" CreationDate="2015-08-09T09:07:37.560" UserId="231" Text="How can I raytrace a scene that does not fit into memory?" ContentLicense="CC BY-SA 3.0" />
  <row Id="362" PostHistoryTypeId="3" PostId="126" RevisionGUID="196a2f05-e504-4089-8b90-3af836013280" CreationDate="2015-08-09T09:07:37.560" UserId="231" Text="|raytracing|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="363" PostHistoryTypeId="2" PostId="127" RevisionGUID="167a3794-09bc-4df2-9570-7015f95beefc" CreationDate="2015-08-09T09:07:40.690" UserId="158" Text="In the general case, no.  Reflection, refraction, and shadows can all generate secondary rays that could go anywhere, requiring the entire scene to be available.&#xD;&#xA;&#xD;&#xA;In the special case of rendering with no secondary rays, you can quickly generate a vista buffer (essentially a mapping of your acceleration hierarchy to the screen) to figure out which objects are potentially visible from each pixel and distribute portions of the scene accordingly." ContentLicense="CC BY-SA 3.0" />
  <row Id="364" PostHistoryTypeId="2" PostId="128" RevisionGUID="f6a8bb47-cefc-4366-86be-d3008698bc18" CreationDate="2015-08-09T09:31:04.153" UserId="100" Text="A set of techniques to avoid explicit ordering go under the name of Order Independent Transparency (OIT for short). &#xD;&#xA;&#xD;&#xA;There are lots of OIT techniques. &#xD;&#xA;&#xD;&#xA;Historically one is **Depth Peeling**. In this approach you first render the front-most fragments/pixels, then you find the closest to the one found in the previous step and so forth, going on with as many &quot;layer&quot; as you need. &#xD;&#xA;It is called depth peeling because at each pass you &quot;peel&quot; one layer of depth. All your layer can be then normally recombined from back to front. &#xD;&#xA;To implement this algorithm you need to have a copy of the depth buffer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another set of techniques are the blendend OIT ones. One the most recent and interesting one is the **Weighted Blended OIT** proposed by [McGuire and Bavoil][1]. It basically apply a weighted sum for all the surfaces that occupies a given a fragment.  The weighting scheme they propose is based on camera-space Z (as an approximation to occlusion) and opacity.  &#xD;&#xA;The idea is that if you can reduce the problem to a weighted sum, you don't really care about ordering. &#xD;&#xA;&#xD;&#xA;Other than the original paper, a great resource for implementation details and problems of Weighted Blended OIT is in [Matt Pettineo's blog][2].  As you can read from his post this technique is not a silver bullet, whilst it works fine for relatively low and medium opacity, it is failing when opacity approaches 1 and so could not be used when big part of the surface is opaque (he makes the example of foliage)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0002/02/09/&#xD;&#xA;  [2]: https://mynameismjp.wordpress.com/2014/02/03/weighted-blended-oit/" ContentLicense="CC BY-SA 3.0" />
  <row Id="365" PostHistoryTypeId="5" PostId="128" RevisionGUID="0d3f8f00-a7f6-4b4b-a923-ef2b571b206f" CreationDate="2015-08-09T09:36:23.203" UserId="100" Comment="added 209 characters in body" Text="A set of techniques to avoid explicit ordering go under the name of Order Independent Transparency (OIT for short). &#xD;&#xA;&#xD;&#xA;There are lots of OIT techniques. &#xD;&#xA;&#xD;&#xA;Historically one is **Depth Peeling**. In this approach you first render the front-most fragments/pixels, then you find the closest to the one found in the previous step and so forth, going on with as many &quot;layer&quot; as you need. &#xD;&#xA;It is called depth peeling because at each pass you &quot;peel&quot; one layer of depth. All your layer can be then normally recombined from back to front. &#xD;&#xA;To implement this algorithm you need to have a copy of the depth buffer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another set of techniques are the blendend OIT ones. One the most recent and interesting one is the **Weighted Blended OIT** proposed by [McGuire and Bavoil][1]. It basically apply a weighted sum for all the surfaces that occupies a given a fragment.  The weighting scheme they propose is based on camera-space Z (as an approximation to occlusion) and opacity.  &#xD;&#xA;The idea is that if you can reduce the problem to a weighted sum, you don't really care about ordering. &#xD;&#xA;&#xD;&#xA;Other than the original paper, a great resource for implementation details and problems of Weighted Blended OIT is in [Matt Pettineo's blog][2].  As you can read from his post this technique is not a silver bullet. The main problem is that the weighting scheme is central and it needs to be tuned according to your scene/content. &#xD;&#xA;From his experiments, whilst the technique seems to work fine for relatively low and medium opacity, it is failing when opacity approaches 1 and so could not be used from materials where big part of the surface is opaque (he makes the example of foliage). &#xD;&#xA;&#xD;&#xA;Again, all come down to how you tune your depth-weights and finding the ones that fit perfectly your use-cases is not necessarily trivial. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0002/02/09/&#xD;&#xA;  [2]: https://mynameismjp.wordpress.com/2014/02/03/weighted-blended-oit/" ContentLicense="CC BY-SA 3.0" />
  <row Id="366" PostHistoryTypeId="6" PostId="121" RevisionGUID="6634cc97-d76f-47cf-a04a-be8c6cae92a4" CreationDate="2015-08-09T09:40:54.873" UserId="100" Comment="edited tags" Text="|opengl|rendering|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="367" PostHistoryTypeId="5" PostId="128" RevisionGUID="e2d2a33f-7f0e-4f95-8c41-58ee9b019759" CreationDate="2015-08-09T10:01:50.560" UserId="100" Comment="added 248 characters in body" Text="A set of techniques to avoid explicit ordering go under the name of Order Independent Transparency (OIT for short). &#xD;&#xA;&#xD;&#xA;There are lots of OIT techniques. &#xD;&#xA;&#xD;&#xA;Historically one is **Depth Peeling**. In this approach you first render the front-most fragments/pixels, then you find the closest to the one found in the previous step and so forth, going on with as many &quot;layer&quot; as you need. &#xD;&#xA;It is called depth peeling because at each pass you &quot;peel&quot; one layer of depth. All your layer can be then normally recombined from back to front. &#xD;&#xA;To implement this algorithm you need to have a copy of the depth buffer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another set of techniques are the blendend OIT ones. One the most recent and interesting one is the **Weighted Blended OIT** proposed by [McGuire and Bavoil][1]. It basically apply a weighted sum for all the surfaces that occupies a given a fragment.  The weighting scheme they propose is based on camera-space Z (as an approximation to occlusion) and opacity.  &#xD;&#xA;The idea is that if you can reduce the problem to a weighted sum, you don't really care about ordering. &#xD;&#xA;&#xD;&#xA;Other than the original paper, a great resource for implementation details and problems of Weighted Blended OIT is in [Matt Pettineo's blog][2].  As you can read from his post this technique is not a silver bullet. The main problem is that the weighting scheme is central and it needs to be tuned according to your scene/content. &#xD;&#xA;From his experiments, whilst the technique seems to work fine for relatively low and medium opacity, it is failing when opacity approaches 1 and so could not be used from materials where big part of the surface is opaque (he makes the example of foliage). &#xD;&#xA;&#xD;&#xA;Again, all come down to how you tune your depth-weights and finding the ones that fit perfectly your use-cases is not necessarily trivial. &#xD;&#xA;&#xD;&#xA;As for what is needed to for the Weighted Blended OIT, nothing more than two extra render targets. One that you fill with the premultiplied alpha color ( color * alpha) and alpha, both weighted accordingly. The other one for the weights only.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0002/02/09/&#xD;&#xA;  [2]: https://mynameismjp.wordpress.com/2014/02/03/weighted-blended-oit/" ContentLicense="CC BY-SA 3.0" />
  <row Id="368" PostHistoryTypeId="2" PostId="129" RevisionGUID="afcfc1ff-10ab-423c-a00e-a1374c0bffcc" CreationDate="2015-08-09T10:15:53.817" UserId="170" Text="To render a scene with a single light source using phong shading, one can calculate the final color of each fragment passed into the fragment shader based on the ambient/diffuse/specular components of both the material and the light source.&#xD;&#xA;&#xD;&#xA;This can be easily extended to accommodate for multiple light sources by adding together the results of applying each individual light source onto the fragment as such:&#xD;&#xA;&#xD;&#xA;    final_color = (0, 0, 0, 1)&#xD;&#xA;    for each light:&#xD;&#xA;        final_color += apply_light(material, light)&#xD;&#xA;    final_color = clamp(final_color, (0,0,0,1), (1,1,1,1))&#xD;&#xA;&#xD;&#xA;However, with a very large number of light sources, this process is quite slow; with `N` lights, this approach requires calculations for phong shading to be done `N` times per fragment. &#xD;&#xA;&#xD;&#xA;Is there a better approach to rendering scenes with a very large number of light sources (hundreds, thousands, etc.)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="369" PostHistoryTypeId="1" PostId="129" RevisionGUID="afcfc1ff-10ab-423c-a00e-a1374c0bffcc" CreationDate="2015-08-09T10:15:53.817" UserId="170" Text="Efficient rendering with many light sources" ContentLicense="CC BY-SA 3.0" />
  <row Id="370" PostHistoryTypeId="3" PostId="129" RevisionGUID="afcfc1ff-10ab-423c-a00e-a1374c0bffcc" CreationDate="2015-08-09T10:15:53.817" UserId="170" Text="|rendering|shader|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="371" PostHistoryTypeId="2" PostId="130" RevisionGUID="c34665d5-a29b-467b-9fa0-0b6a0f0c7c0a" CreationDate="2015-08-09T10:18:03.970" UserId="83" Text="I am trying to implement microfacet BRDF model. I am reading [Sebastien Lagarde's slides][1]. I implemented formulas to my code but i think result image is wrong. &#xD;&#xA;&#xD;&#xA;Yellow is base color of material. Specular color is red to see properly.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // Fragment Shader&#xD;&#xA;    #version 330 core&#xD;&#xA;    &#xD;&#xA;    in vec3 Position;&#xD;&#xA;    in vec2 TexCoord0;&#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec3 Tangent;&#xD;&#xA;    out vec4 FinalColor;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 uCameraPosition; // init value: vec3(0, 0, 5)&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926f&#xD;&#xA;    #define EPSILON 10e-5f&#xD;&#xA;    #define saturate(value) clamp(value, 0.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;    float BRDF_Lambert(float NdotL)&#xD;&#xA;    {&#xD;&#xA;    	return NdotL;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Got these BRDF formulas Moving Frostbite to PBR slide by Sebastien Lagarde &amp; Charles de Rousiers &#xD;&#xA;    // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf&#xD;&#xA;    float BRDF_D_GGX(float NdotH, float Roughness)&#xD;&#xA;    {&#xD;&#xA;    	float Roughness2 = Roughness * Roughness;&#xD;&#xA;    	float f = (NdotH * Roughness2 - NdotH) * NdotH + 1.0f;&#xD;&#xA;    	return Roughness2 / (f * f + EPSILON);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    float BRDF_F_FresnelSchlick(float LdotH, float F0)&#xD;&#xA;    {&#xD;&#xA;    	float f = F0 + (1.0f - F0) * pow((1.0f - LdotH), 5);&#xD;&#xA;    	return f;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float BRDF_G_SmithGGXCorrelated(float NdotL, float NdotV, float Roughness)&#xD;&#xA;    {&#xD;&#xA;    	float Roughness2 = Roughness * Roughness;&#xD;&#xA;    	float GV = NdotL * sqrt((-NdotV * Roughness2 + NdotV) * NdotV + Roughness2);&#xD;&#xA;    	float GL = NdotV * sqrt((-NdotL * Roughness2 + NdotL) * NdotL + Roughness2);&#xD;&#xA;    &#xD;&#xA;    	return 0.5f / (GV + GL + EPSILON);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float BRDF_Specular(float NdotV, float NdotL, float NdotH, float LdotH, float Roughness, float F0)&#xD;&#xA;    {&#xD;&#xA;    	float D = BRDF_D_GGX(NdotH, Roughness);&#xD;&#xA;    	float F = BRDF_F_FresnelSchlick(LdotH, F0);&#xD;&#xA;    	float G = BRDF_G_SmithGGXCorrelated(NdotL, NdotV, Roughness);&#xD;&#xA;    	return (D * F * G) / PI;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	FinalColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);&#xD;&#xA;    	vec4 BaseColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);&#xD;&#xA;    	vec4 SpecularColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    	vec3 LightDirection = normalize(vec3(0, 4, 4));&#xD;&#xA;    	vec3 ViewDirection = normalize(Position - uCameraPosition);&#xD;&#xA;    	vec3 HalfVector = normalize(ViewDirection + LightDirection);&#xD;&#xA;    	float Roughness = 0.9f; // [0.04 - 0.1f] -&gt; Dielectric, [0.7, 1.0f] -&gt; Metallic&#xD;&#xA;    	&#xD;&#xA;    	float RefractiveIndex = 0.27049f; // RI for Gold materials. I got this from http://refractiveindex.info/&#xD;&#xA;    	float F0 = pow(((1.0f - RefractiveIndex) / (1.0f + RefractiveIndex)), 2);&#xD;&#xA;    &#xD;&#xA;    	float NdotL = saturate(dot(LightDirection, Normal));&#xD;&#xA;    	float NdotV = abs(dot(ViewDirection, Normal)) + EPSILON; // Avoid artifact - Ref: SIGGRAPH14 - Moving Frosbite to PBR&#xD;&#xA;    	float LdotH = saturate(dot(LightDirection, HalfVector));&#xD;&#xA;    	float NdotH = saturate(dot(Normal, HalfVector));&#xD;&#xA;    &#xD;&#xA;    	float DiffuseFactor = BRDF_Lambert(NdotL);&#xD;&#xA;    	float SpecularFactor = BRDF_Specular(NdotV, NdotL, NdotH, LdotH, Roughness, F0);&#xD;&#xA;    	&#xD;&#xA;    	FinalColor = BaseColor * DiffuseFactor + SpecularColor * SpecularFactor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Wrong result][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/vwRZ8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="372" PostHistoryTypeId="1" PostId="130" RevisionGUID="c34665d5-a29b-467b-9fa0-0b6a0f0c7c0a" CreationDate="2015-08-09T10:18:03.970" UserId="83" Text="Trying to implement Microfacet BRDF but my result images are wrong" ContentLicense="CC BY-SA 3.0" />
  <row Id="373" PostHistoryTypeId="3" PostId="130" RevisionGUID="c34665d5-a29b-467b-9fa0-0b6a0f0c7c0a" CreationDate="2015-08-09T10:18:03.970" UserId="83" Text="|rendering|glsl|shading|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="374" PostHistoryTypeId="2" PostId="131" RevisionGUID="a1b43d28-73e2-4162-8320-b49313913de2" CreationDate="2015-08-09T11:23:55.003" UserId="100" Text="Yes, but you need a paradigm shift. &#xD;&#xA;&#xD;&#xA;What you are accustomed is called forward rendering. You submit your geometry and then you proceed immediately with the shading pass. In the basic forward rendering you can either loop inside the shader for each light or perform one pass per light and blend the result together (with additive blending). &#xD;&#xA;&#xD;&#xA;But things have evolved quite a lot. Enters: **Deferred Rendering**&#xD;&#xA;&#xD;&#xA;Now that are so many variants that describe them all in details will take way more than acceptable for an answer here. So here I am just going to describe the gist of Deferred shading, there are plenty of other resources that you can easily find using google, hopefully after reading this you'll have the right keywords to find what you need. &#xD;&#xA;&#xD;&#xA;The basic idea is to defer the shading to after down the pipeline. You have two main steps: &#xD;&#xA;&#xD;&#xA; 1. Render your geometry and all the information needed for shading into multiple render targets. This means that typically in a basic implementation you would have a depth buffer, a buffer containing the normals of your geometry and the albedo colour. You'll soon find that you need other information of the materials (e.g. roughness, &quot;metallic&quot; factor etc.). &#xD;&#xA;&#xD;&#xA;This image from wikipedia shows three buffer (color, depth and normals) &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Again, the amount, type and content of the buffers used varies quite a lot among different projects. You will find the set of buffers with the name of GBuffers.&#xD;&#xA;&#xD;&#xA; 2. After this is the time of applying the actual lighting. During the lighting pass for each light you want to draw a light volume that depends on the type of light:&#xD;&#xA;       - For a directional light you render a full screen quad. &#xD;&#xA;       - For a point light you render a sphere where the radius is based on the attenuation of your point light. &#xD;&#xA;       - For a spot-light you render a cone which dimensions again depend on the characteristics of your light. &#xD;&#xA;&#xD;&#xA;In the pixel shader of this pass you pass your GBuffers and perform your lighting and shading using the information in them. This way you process only the pixels affected by each of the lights having a sensible speed-up if compared to the classical forward rendering. &#xD;&#xA;&#xD;&#xA;It has also various disadvantages, most notably the handling of transparent  objects and higher consumption of bandwidth and video memory. But also it is trickier to handle various models for materials. &#xD;&#xA;&#xD;&#xA;You have other side-advantages (as having lots of info ready for post-processing) and is also pretty easy to implement. But this is not the coolest thing around for lots of lights anymore. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Newer techniques are for example Tiled rendering ones. The main idea of those is to subdivide the scene in screen space &quot;tiles&quot; and assign to each tile the lights affecting it. This exists both in a deferred and forward fashion.  These techniques lead to some problems when you have various depth discontinuities in a tile, but is generally faster than the classical deferred and it solves various problems of it. &#xD;&#xA;&#xD;&#xA;Further evolution on this side is the [Clustered shading][2] which is conceptually similar to the tiled based approaches, having instead of screen space tile, clusters with a 3D extent. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**IMPORTANT NOTE:** I have described the basics of the deferred shading. There are multiple variations, optimizations and improvements around so I urge you to experiment with a simple version and then do some researches on other techniques such the one I mentioned above. &#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But Forward rendering has made a come back, although with some &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fmaeF.png&#xD;&#xA;  [2]: http://www.cse.chalmers.se/~uffe/clustered_shading_preprint.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="375" PostHistoryTypeId="2" PostId="132" RevisionGUID="8e173569-2b7e-4b95-a0ca-355f9be2d58b" CreationDate="2015-08-09T11:28:28.467" UserId="38" Text="Color difference is a difference in brightness, in some color channel. So while the sum of individual channels stay the same, there is a intensity difference if there is a color difference.&#xD;&#xA;&#xD;&#xA;Now the basic algorithms do not really specify how you should hadle the multi channel data. So there is nothing wrong with using a different color space. On the other hand nothing says you can not apply the convolution on all channels and then pick the result that is most contrasting." ContentLicense="CC BY-SA 3.0" />
  <row Id="376" PostHistoryTypeId="5" PostId="131" RevisionGUID="8ebffd81-146f-4109-967c-3cda5ef47128" CreationDate="2015-08-09T11:30:52.127" UserId="100" Comment="added 229 characters in body" Text="Yes, but you need a paradigm shift. &#xD;&#xA;&#xD;&#xA;What you are accustomed is called forward rendering. You submit your geometry and then you proceed immediately with the shading pass. In the basic forward rendering you can either loop inside the shader for each light or perform one pass per light and blend the result together (with additive blending). &#xD;&#xA;&#xD;&#xA;But things have evolved quite a lot. Enters: **Deferred Rendering**&#xD;&#xA;&#xD;&#xA;Now that are so many variants that describe them all in details will take way more than acceptable for an answer here. So here I am just going to describe the gist of Deferred shading, there are plenty of other resources that you can easily find using google, hopefully after reading this you'll have the right keywords to find what you need. &#xD;&#xA;&#xD;&#xA;The basic idea is to defer the shading to after down the pipeline. You have two main steps: &#xD;&#xA;&#xD;&#xA; 1. Render your geometry and all the information needed for shading into multiple render targets. This means that typically in a basic implementation you would have a depth buffer, a buffer containing the normals of your geometry and the albedo colour. You'll soon find that you need other information of the materials (e.g. roughness, &quot;metallic&quot; factor etc.). &#xD;&#xA;&#xD;&#xA;This image from wikipedia shows three buffer (color, depth and normals) &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Again, the amount, type and content of the buffers used varies quite a lot among different projects. You will find the set of buffers with the name of GBuffers.&#xD;&#xA;&#xD;&#xA; 2. After this is the time of applying the actual lighting. During the lighting pass for each light you want to draw a light volume that depends on the type of light:&#xD;&#xA;       - For a directional light you render a full screen quad. &#xD;&#xA;       - For a point light you render a sphere where the radius is based on the attenuation of your point light. &#xD;&#xA;       - For a spot-light you render a cone which dimensions again depend on the characteristics of your light. &#xD;&#xA;&#xD;&#xA;In the pixel shader of this pass you pass your GBuffers and perform your lighting and shading using the information in them. This way you process only the pixels affected by each of the lights having a sensible speed-up if compared to the classical forward rendering. &#xD;&#xA;&#xD;&#xA;It has also various disadvantages, most notably the handling of transparent  objects and higher consumption of bandwidth and video memory. But also it is trickier to handle various models for materials. &#xD;&#xA;&#xD;&#xA;You have other side-advantages (as having lots of info ready for post-processing) and is also pretty easy to implement. But this is not the coolest thing around for lots of lights anymore. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Newer techniques are for example Tiled rendering ones. The main idea of those is to subdivide the scene in screen space &quot;tiles&quot; and assign to each tile the lights affecting it. This exists both in a deferred and forward fashion.  These techniques lead to some problems when you have various depth discontinuities in a tile, but is generally faster than the classical deferred and it solves various problems of it. For example, among the advantages, with tiled deferred you read the GBuffers once per lit fragment and pixels in the same tile coherently process the same lights. &#xD;&#xA;&#xD;&#xA;Further evolution on this side is the [Clustered shading][2] which is conceptually similar to the tiled based approaches, having instead of screen space tile, clusters with a 3D extent. This method handles better the depth discontinuities problem and generally performs better than the tiled methods. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**IMPORTANT NOTE:** I have described the basics of the deferred shading. There are multiple variations, optimizations and improvements around so I urge you to experiment with a simple version and then do some researches on other techniques such the one I mentioned above. &#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But Forward rendering has made a come back, although with some &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fmaeF.png&#xD;&#xA;  [2]: http://www.cse.chalmers.se/~uffe/clustered_shading_preprint.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="377" PostHistoryTypeId="5" PostId="131" RevisionGUID="92d6e55e-ab79-4d66-b13c-bb07aab1e762" CreationDate="2015-08-09T11:36:54.697" UserId="100" Comment="Deleted dead phrases" Text="Yes, but you need a paradigm shift. &#xD;&#xA;&#xD;&#xA;What you are accustomed is called forward rendering. You submit your geometry and then you proceed immediately with the shading pass. In the basic forward rendering you can either loop inside the shader for each light or perform one pass per light and blend the result together (with additive blending). &#xD;&#xA;&#xD;&#xA;But things have evolved quite a lot. Enters: **Deferred Rendering**&#xD;&#xA;&#xD;&#xA;Now that are so many variants that describe them all in details will take way more than acceptable for an answer here. So here I am just going to describe the gist of Deferred shading, there are plenty of other resources that you can easily find using google, hopefully after reading this you'll have the right keywords to find what you need. &#xD;&#xA;&#xD;&#xA;The basic idea is to defer the shading to after down the pipeline. You have two main steps: &#xD;&#xA;&#xD;&#xA; 1. Render your geometry and all the information needed for shading into multiple render targets. This means that typically in a basic implementation you would have a depth buffer, a buffer containing the normals of your geometry and the albedo colour. You'll soon find that you need other information of the materials (e.g. roughness, &quot;metallic&quot; factor etc.). &#xD;&#xA;&#xD;&#xA;This image from wikipedia shows three buffer (color, depth and normals) &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Again, the amount, type and content of the buffers used varies quite a lot among different projects. You will find the set of buffers with the name of GBuffers.&#xD;&#xA;&#xD;&#xA; 2. After this is the time of applying the actual lighting. During the lighting pass for each light you want to draw a light volume that depends on the type of light:&#xD;&#xA;       - For a directional light you render a full screen quad. &#xD;&#xA;       - For a point light you render a sphere where the radius is based on the attenuation of your point light. &#xD;&#xA;       - For a spot-light you render a cone which dimensions again depend on the characteristics of your light. &#xD;&#xA;&#xD;&#xA;In the pixel shader of this pass you pass your GBuffers and perform your lighting and shading using the information in them. This way you process only the pixels affected by each of the lights having a sensible speed-up if compared to the classical forward rendering. &#xD;&#xA;&#xD;&#xA;It has also various disadvantages, most notably the handling of transparent  objects and higher consumption of bandwidth and video memory. But also it is trickier to handle various models for materials. &#xD;&#xA;&#xD;&#xA;You have other side-advantages (as having lots of info ready for post-processing) and is also pretty easy to implement. But this is not the coolest thing around for lots of lights anymore. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Newer techniques are for example **Tiled rendering** ones. The main idea of those is to subdivide the scene in screen space &quot;tiles&quot; and assign to each tile the lights affecting it. This exists both in a deferred and forward fashion.  These techniques lead to some problems when you have various depth discontinuities in a tile, but is generally faster than the classical deferred and it solves various problems of it. For example, among the advantages, with tiled deferred you read the GBuffers once per lit fragment and pixels in the same tile coherently process the same lights. &#xD;&#xA;&#xD;&#xA;Further evolution on this side is the **[Clustered shading][2]** which is conceptually similar to the tiled based approaches, having instead of screen space tiles, clusters with a 3D extent. This method handles better the depth discontinuities problem and generally performs better than the tiled methods. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**IMPORTANT NOTE:** I have described the basics of the deferred shading. There are multiple variations, optimizations and improvements around so I urge you to experiment with a simple version and then do some researches on other techniques such the one I mentioned above. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fmaeF.png&#xD;&#xA;  [2]: http://www.cse.chalmers.se/~uffe/clustered_shading_preprint.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="378" PostHistoryTypeId="2" PostId="133" RevisionGUID="bd27777d-644c-48c6-8f89-16838d713a0c" CreationDate="2015-08-09T11:38:54.363" UserId="182" Text="If you organize your scene in a spatial structure (the usual way being a [Bounding Volume Hierarchy][1]), you can use a sort of virtual scene (I am making up this term, in reference to [virtual textures][2]).&#xD;&#xA;&#xD;&#xA;A memory manager would keep only a limited number of bounding boxes loaded at a time, and abstract the operation consisting in retrieving one.&#xD;&#xA;&#xD;&#xA;This way, a box would be loaded only as needed: when a ray hits a bounding box, the box get loaded to resolve the collision. Later on when another box needs to be loaded, the unused one is deleted to make room for the new one.&#xD;&#xA;&#xD;&#xA;With all these boxes getting loaded and deleted, the ray coherency would be a major factor in speed. I suppose a further improvement could be to defer loading, by reordering rays to treat first the boxes that are already loaded.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bounding_volume_hierarchy&#xD;&#xA;  [2]: https://developer.nvidia.com/sites/default/files/akamai/gameworks/events/gdc14/GDC_14_Real%20Virtual%20Texturing%20-%20Taking%20Advantage%20of%20DirectX%2011.2%20Tiled%20Resources.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="379" PostHistoryTypeId="2" PostId="134" RevisionGUID="c25e0b82-1881-4890-b057-6dd6a964981d" CreationDate="2015-08-09T11:39:04.653" UserId="38" Text="What you do is you load triangles into memory from disk based on what has been hit previously. You can begin with triangles in colpse proximity first. The reasoning is that in one area the rays are likely to hit same triangles repeatedly. Snd eventually you will be somewhat efficient. (For this reason it is a good idea to cache last hit triangle in occlusion tracing that dont care of order)&#xD;&#xA;&#xD;&#xA;Second you store the triangles in a spatial tree that allows you to do quick searching from the disk, to renew what portions you are having in memory by proxilimity. So load only branches that will be in the way of the ray. If its somekind of voxel tree like a octree you can even sort secondary rays and solve them by coherence.&#xD;&#xA;&#xD;&#xA;There are cases where this fails but its reasonably efficient." ContentLicense="CC BY-SA 3.0" />
  <row Id="380" PostHistoryTypeId="5" PostId="134" RevisionGUID="8924bdc9-8419-425f-b1f4-f99e3a10a3d8" CreationDate="2015-08-09T11:44:51.380" UserId="38" Comment="added 51 characters in body" Text="What you do is you load triangles into memory from disk based on what has been hit previously. You can begin with triangles in colse proximity first. The reasoning is that in one area the rays are likely to hit same triangles repeatedly. And eventually you will be somewhat efficient. (For this reason it is a good idea to cache last hit triangle in occlusion tracing that dont care of order)&#xD;&#xA;&#xD;&#xA;Second you store the triangles in a spatial tree that allows you to do quick searching from the disk, to renew what portions you are having in memory by proxilimity. So load only branches that will be in the way of the ray. If its somekind of voxel tree like a octree you can even sort secondary rays and solve them by coherence. A BSP tree is also somewhat good at prruning areas.&#xD;&#xA;&#xD;&#xA;There are cases where this fails but its reasonably efficient in most scene buckets if your not renderimg noise..." ContentLicense="CC BY-SA 3.0" />
  <row Id="381" PostHistoryTypeId="2" PostId="135" RevisionGUID="24bf646a-f25a-471d-b292-b7f32e93df29" CreationDate="2015-08-09T11:52:38.473" UserId="38" Text="You can raytrace the distance to the second surface. This nay be conceptually easiest.&#xD;&#xA;&#xD;&#xA;But there is a neat trick, you can multipass render a depth map to the water surface from the camera. The distance in water is now pixel depth minus the depthmap depth. This does not work in all situations sich as when you exit water and re enter later. But should work in many cases, like the one depicted. You can even use same technique for boolean operations." ContentLicense="CC BY-SA 3.0" />
  <row Id="383" PostHistoryTypeId="5" PostId="134" RevisionGUID="e610e577-31ad-412f-a49e-88cfcbca0653" CreationDate="2015-08-09T11:59:09.313" UserId="38" Comment="deleted 1 character in body" Text="What you do is you load triangles into memory from disk based on what has been hit previously. You can begin with triangles in close proximity first. The reasoning is that in one area the rays are likely to hit same triangles repeatedly. And eventually you will be somewhat efficient. (For this reason it is a good idea to cache last hit triangle in occlusion tracing that dont care of order)&#xD;&#xA;&#xD;&#xA;Second you store the triangles in a spatial tree that allows you to do quick searching from the disk, to renew what portions you are having in memory by proximity. So load only branches that will be in the way of the ray. If its some kind of voxel tree, like a octree you can even sort secondary rays and solve them by coherence. A BSP tree is also somewhat good at pruning areas.&#xD;&#xA;&#xD;&#xA;There are cases where this fails but its reasonably efficient in most scene buckets if your not rendering noise..." ContentLicense="CC BY-SA 3.0" />
  <row Id="384" PostHistoryTypeId="5" PostId="135" RevisionGUID="64049a42-28f6-41d4-a8c2-c45c77eeda3b" CreationDate="2015-08-09T12:00:00.260" UserId="38" Comment="added 3 characters in body" Text="You can ray trace the distance to the second surface. This nay be conceptually easiest.&#xD;&#xA;&#xD;&#xA;But there is a neat trick, you can multi pass render a depth map to the water surface from the camera. The distance in water is now pixel depth minus the depth map depth. This does not work in all situations such as when you exit water and re-enter later. But should work in many cases, like the one depicted. You can even use same technique for Boolean operations." ContentLicense="CC BY-SA 3.0" />
  <row Id="385" PostHistoryTypeId="5" PostId="135" RevisionGUID="572e058d-c700-4961-93f8-46a25c231b1e" CreationDate="2015-08-09T12:12:53.717" UserId="38" Comment="added 156 characters in body" Text="You can ray trace the distance to the second surface. This nay be conceptually easiest.&#xD;&#xA;&#xD;&#xA;But there is a neat trick, you can multi pass render a depth map to the water surface from the camera. The distance in water is now pixel depth minus the depth map depth. This does not work in all situations such as when you exit water and re-enter later. But should work in many cases, like the one depicted. You can even use same technique for Boolean operations.&#xD;&#xA;&#xD;&#xA;[![dmap][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Render depth map, consult depth map when shading the bottom of your pond.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UcYKY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="386" PostHistoryTypeId="2" PostId="137" RevisionGUID="469f4eff-4d6b-42da-98fa-7f15091ea707" CreationDate="2015-08-09T12:13:20.517" UserId="316" Text="I think you can convert from the RGB space to the HSV one, or whatever color space has the HUE in a single channel.&#xD;&#xA;&#xD;&#xA;Take the HUE channel, and make the edge detection on that one.&#xD;&#xA;&#xD;&#xA;Here a simple Matlab script to achieve the result.&#xD;&#xA;&#xD;&#xA;    I = imread('image.png');&#xD;&#xA;    hsv = rgb2hsv(I);&#xD;&#xA;    hue = hsv(:,:,1);&#xD;&#xA;    edges = edge(uint8(hue),'sobel');" ContentLicense="CC BY-SA 3.0" />
  <row Id="388" PostHistoryTypeId="2" PostId="138" RevisionGUID="0eae5b26-adc0-4e66-acce-9e1d344729e7" CreationDate="2015-08-09T12:39:35.540" UserId="170" Text="Quaternions (a four-dimensional extension of complex numbers) can used to represent rotation and scaling of a 3D vector, and the application of a quaternion onto a 3D vector involves two quaternion multiplications, thus requiring fewer operations than multiplication by the corresponding transformation matrix. However, linear and affine transformation matrixes are often used instead, especially in shader code.&#xD;&#xA;&#xD;&#xA;When is it appropriate and preferable (due to speed, stability, etc.) to use a quaternion to represent scaling and rotation in three dimensions, instead of the corresponding transformation matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="389" PostHistoryTypeId="1" PostId="138" RevisionGUID="0eae5b26-adc0-4e66-acce-9e1d344729e7" CreationDate="2015-08-09T12:39:35.540" UserId="170" Text="When should quaternions be used to represent rotation and scaling in 3D?" ContentLicense="CC BY-SA 3.0" />
  <row Id="390" PostHistoryTypeId="3" PostId="138" RevisionGUID="0eae5b26-adc0-4e66-acce-9e1d344729e7" CreationDate="2015-08-09T12:39:35.540" UserId="170" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="392" PostHistoryTypeId="5" PostId="135" RevisionGUID="43e2ba18-9c89-4162-8ec2-e7198400649b" CreationDate="2015-08-09T12:54:20.610" UserId="38" Comment="added 74 characters in body" Text="You can ray trace the distance to the second surface. This may be conceptually easiest, but not necessarily fastest method\*.&#xD;&#xA;&#xD;&#xA;But there is a neat trick, you can multi pass render a depth map to the water surface from the camera. The distance in water is now pixel depth minus the depth map depth. This does not work in all situations such as when you exit water and re-enter later. But should work in many cases, like the one depicted. You can even use same technique for Boolean operations.&#xD;&#xA;&#xD;&#xA;[![dmap][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Render depth map, consult depth map when shading the bottom of your pond.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UcYKY.png&#xD;&#xA;&#xD;&#xA;\* It might be in certain cases." ContentLicense="CC BY-SA 3.0" />
  <row Id="393" PostHistoryTypeId="2" PostId="140" RevisionGUID="79c5f81c-dda7-4f56-a9db-4acef96cfc41" CreationDate="2015-08-09T13:16:41.053" UserId="38" Text="Matrices offer more possible transforms than quaternions, it is possible to skew, mirror and non uniformly scale the matrix. There is nothing that states you can not make your engine do just quaternion based transforms, if you have no need for the additional transform features.&#xD;&#xA;&#xD;&#xA;Matrices are just very convenient when you need to build spaces where you know the basis vectors. Such as when doing projections into orthographic. Also doing perspective transform in a matrix space is easy. Matrices may be superior when it comes to projecting stuff.&#xD;&#xA;&#xD;&#xA;In a way matrices are usually used because they represent the most common denomination and aren't too complicated to master and understand. The befits of standardization far outweighs the benefit you get form a custom workflow. Its well known how to do the matrix operations. Whereas quats are not something most get immediate introduction to in uni. Just ask around how many know how to invert a quaternion, whereas you dont find many students in higher education who dont know how to invert a matrix. &#xD;&#xA;&#xD;&#xA;Note that graphics cards also have dedicated pipes for matrix operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="394" PostHistoryTypeId="2" PostId="141" RevisionGUID="b2d99bab-8976-4ee5-938f-e7edbc5bf31d" CreationDate="2015-08-09T13:27:07.007" UserId="137" Text="A quaternion can only represent uniform scaling and rotation so if you need anything else you would need to add something to represent that. &#xD;&#xA;&#xD;&#xA;Translation can be done with a single additional vec3 (or using [dual quaternions][1]). However non-uniform scaling and sheering is represented better by a mat4. Projection transforms cannot be represented by a quaternion.&#xD;&#xA;&#xD;&#xA;Quaternions have a major advantage when interpolating. The slerp is most easily calculated using quaternions. &#xD;&#xA;&#xD;&#xA;Applying a quaternion (or dual quaternion) is not built into the GPU so you would need to implement that using the vector operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Dual_quaternion" ContentLicense="CC BY-SA 3.0" />
  <row Id="395" PostHistoryTypeId="5" PostId="140" RevisionGUID="b6078db0-bb52-4355-aa8e-dbf0e65c3533" CreationDate="2015-08-09T13:30:27.103" UserId="38" Comment="added 2 characters in body" Text="Matrices offer more possible transforms than quaternions, it is possible to skew, mirror and non uniformly scale the matrix. There is nothing that states you can not make your engine do just quaternion based transforms, if you have no need for the additional transform features.&#xD;&#xA;&#xD;&#xA;Matrices are just very convenient when you need to build spaces where you know the basis vectors. Such as when doing projections into orthographic. Also doing perspective transform in a matrix space is easy. Matrices are superior when it comes to projecting stuff.&#xD;&#xA;&#xD;&#xA;In a way matrices are usually used because they represent the most common denomination and aren't too complicated to master and understand. The benefits of standardization far outweighs the benefit you get form a custom workflow. Its well known how to do the matrix operations. Whereas quats are not something most get immediate introduction to in uni. Just ask around how many know how to invert a quaternion, whereas you dont find many students in higher education who dont know how to invert a matrix. &#xD;&#xA;&#xD;&#xA;Note that graphics cards also have dedicated pipes for matrix operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="396" PostHistoryTypeId="5" PostId="141" RevisionGUID="d04b3546-bd52-4f83-a326-57dc4e420f03" CreationDate="2015-08-09T13:32:53.620" UserId="137" Comment="added 55 characters in body" Text="A quaternion can only represent uniform scaling and rotation so if you need anything else you would need to add something to represent that. &#xD;&#xA;&#xD;&#xA;Translation can be done with a single additional vec3 (or using [dual quaternions][1]). However non-uniform scaling and sheering is represented better by a mat4. Projection transforms (essentially non-uniform scaling and swapping z and w) cannot be represented by a quaternion.&#xD;&#xA;&#xD;&#xA;Quaternions have a major advantage when interpolating. The slerp is most easily calculated using quaternions. &#xD;&#xA;&#xD;&#xA;Applying a quaternion (or dual quaternion) is not built into the GPU so you would need to implement that using the vector operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Dual_quaternion" ContentLicense="CC BY-SA 3.0" />
  <row Id="398" PostHistoryTypeId="6" PostId="123" RevisionGUID="33dec0dd-779c-42ba-87bb-344b31d9c092" CreationDate="2015-08-09T14:27:04.993" UserId="38" Comment="added tag to reflect answer" Text="|opengl|fog|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="399" PostHistoryTypeId="24" PostId="123" RevisionGUID="33dec0dd-779c-42ba-87bb-344b31d9c092" CreationDate="2015-08-09T14:27:04.993" Comment="Proposed by 38 approved by 198 edit id of 21" ContentLicense="CC BY-SA 3.0" />
  <row Id="400" PostHistoryTypeId="2" PostId="143" RevisionGUID="2c04a870-3920-4056-aa81-7146145177a5" CreationDate="2015-08-09T15:58:55.490" UserId="125" Text="(A lot of information here I shamelessly borrowed from joojaa's and ratchet freak's answers, with some notes of my own.)&#xD;&#xA;&#xD;&#xA;Matrix Advantages&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;* Non uniform scaling and rotation, skewing, projection&#xD;&#xA;* Translation (unless using dual quaternions)&#xD;&#xA;* Native hardware support&#xD;&#xA;* Quaternions often require transcendental functions to construct&#xD;&#xA;* Easier to understand&#xD;&#xA;&#xD;&#xA;Quaternion Advantages&#xD;&#xA;---------------------&#xD;&#xA;&#xD;&#xA;* Transforming a vector requires fewer operations&#xD;&#xA;* Transforming by another quat requires many fewer operations&#xD;&#xA;* Quaternions occupy 4 floats, (8 if it's a dual) but Matrices occupy 9-16 floats&#xD;&#xA;&#xD;&#xA;If you know you're only going to be doing uniform rigid body transforms, a vector/quat pair is usually a solid win on a 3x4 matrix in terms of storage space (vector/quat: 7 or 8 floats vs mat3x4: 12 floats) and processing speed. If Quaternions are still mystical voodoo to you, try [this web series on them][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLW3Zl3wyJwWNWsJIPZrmY19urkYHXOH3N" ContentLicense="CC BY-SA 3.0" />
  <row Id="401" PostHistoryTypeId="5" PostId="141" RevisionGUID="034b2d1d-6623-4497-8378-f9731612eead" CreationDate="2015-08-09T16:44:50.557" UserId="137" Comment="added 128 characters in body" Text="A quaternion can only represent uniform scaling and rotation so if you need anything else you would need to add something to represent that. &#xD;&#xA;&#xD;&#xA;Translation can be done with a single additional vec3 (or using [dual quaternions][1]). However non-uniform scaling and sheering is represented better by a mat4. Projection transforms (essentially non-uniform scaling and swapping z and w) cannot be represented by a quaternion.&#xD;&#xA;&#xD;&#xA;Quaternions have a major advantage when interpolating. The slerp is most easily calculated using quaternions. &#xD;&#xA;&#xD;&#xA;Applying a quaternion (or dual quaternion) is not built into the GPU so you would need to implement that using the vector operations. Most quaternion libraries assume that you won't be using the quaternion to represent scale so that's something to look out for.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Dual_quaternion" ContentLicense="CC BY-SA 3.0" />
  <row Id="402" PostHistoryTypeId="5" PostId="137" RevisionGUID="8dba610b-16f4-435e-8ba6-5522c6d7052f" CreationDate="2015-08-09T17:03:58.693" UserId="316" Comment="added 20 characters in body" Text="I think you can convert from the RGB space to the HSV one, or whatever color space has the HUE in a single channel.&#xD;&#xA;&#xD;&#xA;Take the HUE channel, and make the edge detection on that one.&#xD;&#xA;&#xD;&#xA;Here a simple Matlab script to achieve the result.&#xD;&#xA;&#xD;&#xA;    I = imread('image.png');&#xD;&#xA;    hsv = rgb2hsv(I);&#xD;&#xA;    hue = hsv(:,:,1);&#xD;&#xA;    edges = edge(uint8(hue),'sobel');&#xD;&#xA;    imshow(edges);" ContentLicense="CC BY-SA 3.0" />
  <row Id="403" PostHistoryTypeId="2" PostId="144" RevisionGUID="5403742d-0d7c-4891-8c42-1271e1d98138" CreationDate="2015-08-09T17:16:24.560" UserId="196" Text="I want to start with misconceptions:&#xD;&#xA;&#xD;&#xA;Modern GPUs (NVIDIA for quite a while, and AMD since Southern Islands) do not meaningfully support vector/matrix operations natively in hardware. They are vector architectures in a different direction: each component of a vector (x, y, z) are generally 32- or 64-valued, containing values for each element in a lane. So a 3D dot product is not usually an instruction, it is a multiply and two multiply-adds.&#xD;&#xA;&#xD;&#xA;Additionally, counting primitive operations like multiply-add, transforming a vector by a quaternion is more expensive than transforming a vector by a matrix. Transforming a vector by a 3x3 matrix is 3 multiplies and 6 multiply-adds, and transforming a vector by a quaternion is two quaternion multiplies, each of which consist of 4 multiplies and 12 multiply-adds. (You can get less naive than this—[here's a writeup on a faster way][1]—but it's still not as cheap as multiplying a vector by a matrix.)&#xD;&#xA;&#xD;&#xA;However, performance is not always determined simply by counting the number of ALU operations it performs. Quaternions require less space than the equivalent matrix (assuming you are only doing pure rotation/scale), and that means less storage space and less memory traffic. This is often important in animation (which is conveniently also often where the nice interpolation properties of quaternions show up).&#xD;&#xA;&#xD;&#xA;  [1]: https://molecularmusings.wordpress.com/2013/05/24/a-faster-quaternion-vector-multiplication/" ContentLicense="CC BY-SA 3.0" />
  <row Id="404" PostHistoryTypeId="5" PostId="143" RevisionGUID="1756eb5f-4e10-4ca0-a880-585f4ac65573" CreationDate="2015-08-09T17:20:16.970" UserId="125" Comment="added 29 characters in body" Text="(A lot of information here I shamelessly borrowed from joojaa's and ratchet freak's answers, with some notes of my own.)&#xD;&#xA;&#xD;&#xA;Matrix Advantages&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;* Non uniform scaling and rotation, skewing, projection&#xD;&#xA;* Translation (unless using dual quaternions)&#xD;&#xA;* Native hardware support&#xD;&#xA;* Quaternions often require transcendental functions to construct&#xD;&#xA;* Easier to understand&#xD;&#xA;&#xD;&#xA;Quaternion Advantages&#xD;&#xA;---------------------&#xD;&#xA;&#xD;&#xA;* Transforming a vector requires fewer operations (Or not - See John's answer)&#xD;&#xA;* Transforming by another quat requires many fewer operations&#xD;&#xA;* Quaternions occupy 4 floats, (8 if it's a dual) but Matrices occupy 9-16 floats&#xD;&#xA;&#xD;&#xA;If you know you're only going to be doing uniform rigid body transforms, a vector/quat pair is usually a solid win on a 3x4 matrix in terms of storage space (vector/quat: 7 or 8 floats vs mat3x4: 12 floats) and processing speed. If Quaternions are still mystical voodoo to you, try [this web series on them][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLW3Zl3wyJwWNWsJIPZrmY19urkYHXOH3N" ContentLicense="CC BY-SA 3.0" />
  <row Id="405" PostHistoryTypeId="5" PostId="144" RevisionGUID="fc31e996-3fe9-4cec-8ca2-b57e049b10b9" CreationDate="2015-08-09T17:22:51.250" UserId="196" Comment="naïve &gt; naive" Text="I want to start with misconceptions:&#xD;&#xA;&#xD;&#xA;Modern GPUs (NVIDIA for quite a while, and AMD since Southern Islands) do not meaningfully support vector/matrix operations natively in hardware. They are vector architectures in a different direction: each component of a vector (x, y, z) are generally 32- or 64-valued, containing values for each element in a lane. So a 3D dot product is not usually an instruction, it is a multiply and two multiply-adds.&#xD;&#xA;&#xD;&#xA;Additionally, counting primitive operations like multiply-add, transforming a vector by a quaternion is more expensive than transforming a vector by a matrix. Transforming a vector by a 3x3 matrix is 3 multiplies and 6 multiply-adds, and transforming a vector by a quaternion is two quaternion multiplies, each of which consist of 4 multiplies and 12 multiply-adds. (You can get less naïve than this—[here's a writeup on a faster way][1]—but it's still not as cheap as multiplying a vector by a matrix.)&#xD;&#xA;&#xD;&#xA;However, performance is not always determined simply by counting the number of ALU operations it performs. Quaternions require less space than the equivalent matrix (assuming you are only doing pure rotation/scale), and that means less storage space and less memory traffic. This is often important in animation (which is conveniently also often where the nice interpolation properties of quaternions show up).&#xD;&#xA;&#xD;&#xA;Other than that:&#xD;&#xA;&#xD;&#xA;- Matrices use more space because they support more operations. A 3x3 matrix can contain nonuniform scale, skew, reflection, and orthogonal projection.&#xD;&#xA;- Matrices can be naturally thought of as basis vectors, and easily constructed from those vectors.&#xD;&#xA;- Multiplying one quaternion by another (composing two rotations) is less operations than multiplying one matrix by another.&#xD;&#xA;&#xD;&#xA;  [1]: https://molecularmusings.wordpress.com/2013/05/24/a-faster-quaternion-vector-multiplication/" ContentLicense="CC BY-SA 3.0" />
  <row Id="406" PostHistoryTypeId="5" PostId="21" RevisionGUID="39a4a607-741a-466f-8772-4e484b696e3f" CreationDate="2015-08-09T17:31:32.827" UserId="231" Comment="Minor typos" Text="The stencil buffer definition by Wikipedia is indeed not great, it focuses too much on the details of modern implementations (OpenGL). I find [the disambiguated version][1] easier to understand:&#xD;&#xA;&#xD;&#xA;&gt; A stencil is a template used to draw or paint identical letters, symbols, shapes, or patterns every time it is used. The design produced by such a template is also called a stencil.&#xD;&#xA;&#xD;&#xA;That's what stencil meant before Computer Graphics. If you type *stencil* on Google Images, this is one of the first results:&#xD;&#xA;&#xD;&#xA;[![Stencil mask][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, it is simply a mask or pattern that can be used to &quot;paint&quot; the negative of the pattern onto something.&#xD;&#xA;&#xD;&#xA;The *stencil buffer* works in the exact same way. One can fill the stencil buffer with a selected pattern by doing a stencil render pass, then set the appropriate stencil function which will define how the pattern is to be interpreted on subsequent drawings, then render the final scene. Pixels that fall into the rejected areas of the stencil mask, according to the compare function, are not drawn.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;When it comes to implementing the stencil buffer, sometimes it is indeed coupled with the depth buffer. Most graphics hardware uses a 1 byte (8 bits) stencil buffer, which is enough for most applications. Depth buffers are usually implemented using 3 bytes (24 bits), which again is normally enough for most kinds of 3D rendering. So it is only logical to pack the 8 bits of the stencil buffer with the other 24 of the depth buffer, making it possible to store each depth + stencil pixel into a 32 bit integer. That's what Wikipedia meant by:&#xD;&#xA;&#xD;&#xA;&gt; The depth buffer and stencil buffer often share the same area in the RAM of the graphics hardware.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;One application in which the stencil buffer used to be king was for shadow rendering, in a technique called [*shadow volumes*][3], or sometimes also appropriately called *stencil shadows*. This was a very clever use of the buffer, but nowadays most of the rendering field seems to have shifted towards depth-based shadow maps.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stencil_(disambiguation)&#xD;&#xA;  [2]: https://i.stack.imgur.com/bHD7z.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Shadow_volume&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="407" PostHistoryTypeId="24" PostId="21" RevisionGUID="39a4a607-741a-466f-8772-4e484b696e3f" CreationDate="2015-08-09T17:31:32.827" Comment="Proposed by 231 approved by 100, 196 edit id of 22" ContentLicense="CC BY-SA 3.0" />
  <row Id="408" PostHistoryTypeId="2" PostId="145" RevisionGUID="fa8de4db-1bcb-4847-8f43-21a1c1ac00e3" CreationDate="2015-08-09T18:05:02.017" UserId="196" Text="Literature on rendering volumetric materials and effects tends to use a lot of mathematical physics terminology. Let's say that I have a decent handle on the concepts involved in surface rendering. What concepts do I need to understand for volumetric rendering? (Both real-time and offline rendering.)&#xD;&#xA;&#xD;&#xA;- What exactly is meant by light scattering in the context of volumetric rendering? (And why is it split into in-scattering and out-scattering?)&#xD;&#xA;&#xD;&#xA;- What is the relationship between transmission, attenuation, and absorption?&#xD;&#xA;&#xD;&#xA;- What is a phase function and how does it play into volumetric rendering? (In particular, the Henyey-Greenstein phase function.)&#xD;&#xA;&#xD;&#xA;- What is the Beer-Lambert law and how is it related to light scattering?&#xD;&#xA;&#xD;&#xA;Basically, how do I make sense out of diagrams like this?&#xD;&#xA;&#xD;&#xA;[![Confusing diagram][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TZ5vY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="409" PostHistoryTypeId="1" PostId="145" RevisionGUID="fa8de4db-1bcb-4847-8f43-21a1c1ac00e3" CreationDate="2015-08-09T18:05:02.017" UserId="196" Text="Volumetric rendering fundamental concepts and terminology" ContentLicense="CC BY-SA 3.0" />
  <row Id="410" PostHistoryTypeId="3" PostId="145" RevisionGUID="fa8de4db-1bcb-4847-8f43-21a1c1ac00e3" CreationDate="2015-08-09T18:05:02.017" UserId="196" Text="|volumetric|atmospherics|scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="411" PostHistoryTypeId="5" PostId="107" RevisionGUID="bba5ae6e-f3da-41a4-8b56-1e3fb1f268c9" CreationDate="2015-08-09T18:44:10.750" UserId="310" Comment="Corrected with Nathan Reed's comment" Text="If the surfaces are exactly co-planer, your fate is up to the FPU gods; you'll more than likely have Z-fighting. If the triangles are *identical* and you do the *exact* same math to each, you *will* end up with the same Z-values for both. But again, this will only happen if your math operations are identical for both. (Since, in general, FPU operations are not commutative)&#xD;&#xA;&#xD;&#xA;One possible solution is to not use the Z-buffer at all. Rather you can use the [Painter's Algorithm](https://en.wikipedia.org/wiki/Painter%27s_algorithm). Granted, this comes with all the problems of the painters algorithm as well. But, it would solve the Z-fighting.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In your example case of Screen Space Decals (SSDs), the common solution is to use an offset, aka a simple thin cube. See Warhammer 40k's [presentation](http://www.slideshare.net/blindrenderer/screen-space-decals-in-warhammer-40000-space-marine-14699854) about SSDs for reference. Or Bart Wronski's [post](http://bartwronski.com/2015/03/12/fixing-screen-space-deferred-decals/) which addresses some other issues with decals, but also links to a few other presentations about SSDs" ContentLicense="CC BY-SA 3.0" />
  <row Id="412" PostHistoryTypeId="2" PostId="146" RevisionGUID="26f04e29-59b7-4432-8b24-23777ca8646e" CreationDate="2015-08-09T19:33:44.087" UserId="196" Text="Forward rendering is the process of computing a radiance value for a surface fragment directly from input geometry and lighting information. Deferred rendering splits that process into two steps: first producing a screen-space buffer containing material properties (a geometry buffer, or G-buffer) built by rasterizing the input geometry, and second producing a radiance value for each pixel by combining the G-buffer with lighting information.&#xD;&#xA;&#xD;&#xA;Deferred rendering is often presented as an optimization of forward rendering. One explanation is that lighting is fairly expensive and if you have any overdraw then you are lighting pixels that will never be seen on screen, whereas if you store material properties into a G-buffer and light afterwards, you are only lighting a pixel that will actually appear on-screen. Is this actually an advantage of deferred, given that you can also do a depth pre-pass and then do a forward rendering pass with depth test set to `D3D11_COMPARISON_EQUAL` or `GL_EQUAL` or the equivalent?&#xD;&#xA;&#xD;&#xA;Deferred rendering also has the potential to schedule better on the GPU. Splitting one large warp/wavefront into a smaller geometry wavefront and then smaller lighting wavefronts later improves occupancy (more wavefronts in flight simultaneously). But you also end up with a lot more bandwidth use (writing out a large number of channels to the G-buffer, then reading them back in during lighting). Obviously the specifics here depend a lot on your GPU, but what are the general principles?&#xD;&#xA;&#xD;&#xA;Are there other practical performance considerations when deciding between forward and deferred rendering? (Assume that we can use variations of each technique if necessary: i.e. we can compare tiled forward to tiled deferred as well.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="413" PostHistoryTypeId="1" PostId="146" RevisionGUID="26f04e29-59b7-4432-8b24-23777ca8646e" CreationDate="2015-08-09T19:33:44.087" UserId="196" Text="What is the performance tradeoff between forward and deferred rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="414" PostHistoryTypeId="3" PostId="146" RevisionGUID="26f04e29-59b7-4432-8b24-23777ca8646e" CreationDate="2015-08-09T19:33:44.087" UserId="196" Text="|performance|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="415" PostHistoryTypeId="2" PostId="147" RevisionGUID="8d0514c9-ce9a-4691-9943-4b52665ecf35" CreationDate="2015-08-09T19:33:44.087" UserId="196" Text="It is possible to avoid overdraw from opaque objects even with forward rendering by doing a depth pre-pass and using that information to reject any pixel that is not actually visible. However, depending on the vertex cost of your scene, a depth pre-pass may add an unacceptable amount of performance overhead. Additionally, rendering using the pixel shading pipeline of the GPU means that you don't pay a cost per pixel that is rendered, you pay a cost per 2x2 pixel *quad* that is rendered. So even doing a depth pre-pass still causes triangle edges to waste work shading pixels that will be discarded.&#xD;&#xA;&#xD;&#xA;GPU scheduling is a complex topic, and the tradeoff between forward and deferred does not boil down simply to &quot;runs faster but uses more bandwidth.&quot; If you have two equally cheap operations that run in sequence and each use the same number of resources, there's no reason to split them into separate shaders: two small wavefronts that each use X resources don't fundamentally work better than a single longer wavefront that also uses X resources. If you have a cheap operation and an expensive operation to run in sequence, though, it may benefit from splitting into separate shaders: the shader in general will reserve the maximum amount of resources that it might use at any point. It's conceivable that forward rendering may not be able to use all the bandwidth of your GPU because there are so few wavefronts in flight that it cannot issue enough operations to saturate the bandwidth. But if you *are* bandwidth limited, there may be no advantage to deferred rendering (since it will probably use more bandwidth).&#xD;&#xA;&#xD;&#xA;An additional performance concern is that forward rendering supports different material types (different BRDFs, say) simply by using a different shader for that object. A straightforward deferred renderer needs to handle different material types in a different way (potentially a branch in the shader), since work is no longer grouped into warps/wavefronts coherently depending on the object being rendered. This can be mitigated with a tiled renderer—if only specific areas of the screen use an alternate material type (say, for hair), then you can use the shader variation with a material type branch only for tiles that contain any pixels with that material." ContentLicense="CC BY-SA 3.0" />
  <row Id="416" PostHistoryTypeId="2" PostId="148" RevisionGUID="f7c80125-9b51-40f7-8463-c33552c81e78" CreationDate="2015-08-09T20:02:43.317" UserId="196" Text="Antialiasing of 2D shapes boils down to computing the fraction of a pixel that is covered by the shape. For simple non-overlapping shapes, this is not too difficult: clip the shape against the pixel rectangle and calculate the resulting shape's area. But it becomes more difficult if multiple shapes overlap the same pixel. Simply summing areas can cause the computed coverage to be too high, if it neglects the amount that one shape covers another shape. For example, see [the Limitations section of this article on font rendering][1]. You might also be in a situation where the two curves come from different objects with different colors (so it's not about the total coverage for the union of the two shapes, but the coverage of each one separately).&#xD;&#xA;&#xD;&#xA;How would this be computed if you cared about complete accuracy? Even trickier, how do you compute coverage accurately for overlapping non-polygonal shapes like curves? Is there some point when you have no choice but to fall back to multisampling or stochastic techniques?&#xD;&#xA;&#xD;&#xA;  [1]: http://nothings.org/gamedev/rasterize/" ContentLicense="CC BY-SA 3.0" />
  <row Id="417" PostHistoryTypeId="1" PostId="148" RevisionGUID="f7c80125-9b51-40f7-8463-c33552c81e78" CreationDate="2015-08-09T20:02:43.317" UserId="196" Text="How do I accurately compute coverage of overlapping analytical curves?" ContentLicense="CC BY-SA 3.0" />
  <row Id="418" PostHistoryTypeId="3" PostId="148" RevisionGUID="f7c80125-9b51-40f7-8463-c33552c81e78" CreationDate="2015-08-09T20:02:43.317" UserId="196" Text="|antialiasing|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="419" PostHistoryTypeId="5" PostId="130" RevisionGUID="88f3ce2d-602c-4dd1-8554-9e1c70acef10" CreationDate="2015-08-09T20:20:02.463" UserId="83" Comment="Added new images" Text="I am trying to implement microfacet BRDF model. I am reading [Sebastien Lagarde's slides][1]. I implemented formulas to my code but i think result image is wrong. &#xD;&#xA;&#xD;&#xA;Yellow is base color of material. Specular color is red to see properly.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // Fragment Shader&#xD;&#xA;    #version 330 core&#xD;&#xA;    &#xD;&#xA;    in vec3 Position;&#xD;&#xA;    in vec2 TexCoord0;&#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec3 Tangent;&#xD;&#xA;    out vec4 FinalColor;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 uCameraPosition; // init value: vec3(0, 0, 5)&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926f&#xD;&#xA;    #define EPSILON 10e-5f&#xD;&#xA;    #define saturate(value) clamp(value, 0.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;    float BRDF_Lambert(float NdotL)&#xD;&#xA;    {&#xD;&#xA;    	return NdotL;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Got these BRDF formulas Moving Frostbite to PBR slide by Sebastien Lagarde &amp; Charles de Rousiers &#xD;&#xA;    // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf&#xD;&#xA;    float BRDF_D_GGX(float NdotH, float Roughness)&#xD;&#xA;    {&#xD;&#xA;    	float Roughness2 = Roughness * Roughness;&#xD;&#xA;    	float f = (NdotH * Roughness2 - NdotH) * NdotH + 1.0f;&#xD;&#xA;    	return Roughness2 / (f * f + EPSILON);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    float BRDF_F_FresnelSchlick(float LdotH, float F0)&#xD;&#xA;    {&#xD;&#xA;    	float f = F0 + (1.0f - F0) * pow((1.0f - LdotH), 5);&#xD;&#xA;    	return f;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float BRDF_G_SmithGGXCorrelated(float NdotL, float NdotV, float Roughness)&#xD;&#xA;    {&#xD;&#xA;    	float Roughness2 = Roughness * Roughness;&#xD;&#xA;    	float GV = NdotL * sqrt((-NdotV * Roughness2 + NdotV) * NdotV + Roughness2);&#xD;&#xA;    	float GL = NdotV * sqrt((-NdotL * Roughness2 + NdotL) * NdotL + Roughness2);&#xD;&#xA;    &#xD;&#xA;    	return 0.5f / (GV + GL + EPSILON);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float BRDF_Specular(float NdotV, float NdotL, float NdotH, float LdotH, float Roughness, float F0)&#xD;&#xA;    {&#xD;&#xA;    	float D = BRDF_D_GGX(NdotH, Roughness);&#xD;&#xA;    	float F = BRDF_F_FresnelSchlick(LdotH, F0);&#xD;&#xA;    	float G = BRDF_G_SmithGGXCorrelated(NdotL, NdotV, Roughness);&#xD;&#xA;    	return (D * F * G) / PI;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	FinalColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);&#xD;&#xA;    	vec4 BaseColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);&#xD;&#xA;    	vec4 SpecularColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    	vec3 LightDirection = normalize(vec3(0, 4, 4));&#xD;&#xA;    	vec3 ViewDirection = normalize(Position - uCameraPosition);&#xD;&#xA;    	vec3 HalfVector = normalize(ViewDirection + LightDirection);&#xD;&#xA;    	float Roughness = 0.9f; // [0.04 - 0.1f] -&gt; Dielectric, [0.7, 1.0f] -&gt; Metallic&#xD;&#xA;    	&#xD;&#xA;    	float RefractiveIndex = 0.27049f; // RI for Gold materials. I got this from http://refractiveindex.info/&#xD;&#xA;    	float F0 = pow(((1.0f - RefractiveIndex) / (1.0f + RefractiveIndex)), 2);&#xD;&#xA;    &#xD;&#xA;    	float NdotL = saturate(dot(LightDirection, Normal));&#xD;&#xA;    	float NdotV = abs(dot(ViewDirection, Normal)) + EPSILON; // Avoid artifact - Ref: SIGGRAPH14 - Moving Frosbite to PBR&#xD;&#xA;    	float LdotH = saturate(dot(LightDirection, HalfVector));&#xD;&#xA;    	float NdotH = saturate(dot(Normal, HalfVector));&#xD;&#xA;    &#xD;&#xA;    	float DiffuseFactor = BRDF_Lambert(NdotL);&#xD;&#xA;    	float SpecularFactor = BRDF_Specular(NdotV, NdotL, NdotH, LdotH, Roughness, F0);&#xD;&#xA;    	&#xD;&#xA;    	FinalColor = BaseColor * DiffuseFactor + SpecularColor * SpecularFactor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Wrong result][4]][4]&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;Roughness = 0.2f;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Roughness = 0.04f;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/89aAW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/SlEtb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/vwRZ8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="420" PostHistoryTypeId="2" PostId="149" RevisionGUID="cd8a025b-5eb5-4074-865b-23fa7af861d9" CreationDate="2015-08-09T20:27:41.297" UserId="100" Text="It is common knowledge that hair simulation and rendering is particularly challenging and in fact rare are the examples in games that propose believable hairs. It is pretty easy to imagine how hard it is to actually simulate the high amount of fibres and to simulate the various scattering events that may happen between so many strands, let alone the fact that each of them is translucent. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can someone formalize what are the main challenges in hair rendering, especially for real time scenarios? How these are overcome by state-of-art techniques? Are there some de-facto standard theoretical models used? &#xD;&#xA;&#xD;&#xA;To clarify, for real time I don't necessarily mean in a game context. " ContentLicense="CC BY-SA 3.0" />
  <row Id="421" PostHistoryTypeId="1" PostId="149" RevisionGUID="cd8a025b-5eb5-4074-865b-23fa7af861d9" CreationDate="2015-08-09T20:27:41.297" UserId="100" Text="How state of the art real time hair rendering works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="422" PostHistoryTypeId="3" PostId="149" RevisionGUID="cd8a025b-5eb5-4074-865b-23fa7af861d9" CreationDate="2015-08-09T20:27:41.297" UserId="100" Text="|shading|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="423" PostHistoryTypeId="2" PostId="150" RevisionGUID="7ca663c5-b129-48e0-9c0e-56e3dd9c46ac" CreationDate="2015-08-09T21:07:03.407" UserId="38" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most of all commercial 2D renderers that attempt to do analytic coverage calculation make a predictable errors, that multisampling methods do not do.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thinn white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling qhere its most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solition could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow fow variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/Tfs4k.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="424" PostHistoryTypeId="16" PostId="150" RevisionGUID="12b0c5de-6362-4214-8f55-ae0788df6041" CreationDate="2015-08-09T21:07:03.407" UserId="38" />
  <row Id="426" PostHistoryTypeId="2" PostId="151" RevisionGUID="1b2f6d0e-3d69-4469-a4d9-3a1d8f63846c" CreationDate="2015-08-09T22:06:50.547" UserId="116" Text="After so much reading about transformations it is time to implement a trackball for my app.&#xD;&#xA;I understand I have to create a vector from the origin to where the mouse is clicked and then another from the origin to where the mouse is released.&#xD;&#xA;&#xD;&#xA;My question is, do I have to transfor the (x,y) pixel coords to world-coords or should I just do everything in image space (considering image space is the 2D projection of the scene measured in pixels)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="427" PostHistoryTypeId="1" PostId="151" RevisionGUID="1b2f6d0e-3d69-4469-a4d9-3a1d8f63846c" CreationDate="2015-08-09T22:06:50.547" UserId="116" Text="How to implement a trackball in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="428" PostHistoryTypeId="3" PostId="151" RevisionGUID="1b2f6d0e-3d69-4469-a4d9-3a1d8f63846c" CreationDate="2015-08-09T22:06:50.547" UserId="116" Text="|opengl|trackball|" ContentLicense="CC BY-SA 3.0" />
  <row Id="429" PostHistoryTypeId="2" PostId="152" RevisionGUID="369a06bf-c43e-41b5-9dc9-4861bd788a4c" CreationDate="2015-08-09T22:09:49.603" UserId="79" Text="Yes, such a thing is possible. There are a few different ways of doing it, but the basic idea is to split up the scene into chunks and assign these chunks to different machines. Each machine then traces rays locally within their assigned chunk.&#xD;&#xA;&#xD;&#xA;The tricky bit is of course when rays leave a chunk, in which case machines need to synchronize and exchange rays that cross the local chunk boundaries. A recent paper from this year's EGSR, [Distributed Out-of-Core&#xD;&#xA;Stochastic Progressive Photon Mapping](http://vc.cs.ovgu.de/files/publications/2014/Guenther_2014_CGF.pdf), describes how to do this efficiently for Progressive Photon Mapping, although other light transport methods might be feasible.&#xD;&#xA;&#xD;&#xA;Although such distributed ray tracing is possible, it is certainly not the most efficient form of parallelization, and non-uniform lighting directly translates into non-uniform distribution of the workload. It is really only beneficial when the size of the scene far exceeds the memory of a single machine." ContentLicense="CC BY-SA 3.0" />
  <row Id="432" PostHistoryTypeId="2" PostId="153" RevisionGUID="a5a91637-9aa9-4010-84d9-eee905658b3b" CreationDate="2015-08-09T22:47:46.967" UserId="79" Text="If the scene does not entirely fit into memory, you are entering the field of out-of-core rendering. There are essentially two approaches here: a) Generate your scene on-demand b) Load your scene on-demand&#xD;&#xA;&#xD;&#xA;The former approach aligns well with most animation workflows, where models are heavily subdivided using e.g. Catmull-Clark and can become very memory-intensive, but the base meshes themselves easily fit into memory. Pixar have a few papers about this (e.g. [Ray Differentials and Multiresolution Geometry Caching&#xD;&#xA;for Distribution Ray Tracing in Complex Scenes](http://www.pixar.com/companyinfo/research/per/eg03.pdf)), but the gist of it is that models are only subdivided when they are hit by a ray, and only subdivided as much as is reasonable for such a ray (e.g. diffuse interreflection need less accuracy than mirror reflections). The rest is handled by a geometry cache, which keeps the subdivided models in memory and hopefully makes the process efficient by a good eviction strategy.&#xD;&#xA;&#xD;&#xA;As long as all your base meshes comfortably fit into memory, you can easily go out-of-core and render meshes at subdivision levels that would never fit into memory. The geometry cache also scales nicely with the amount of memory you have, allowing you to weigh RAM vs. render times. This was also used in [Cars](http://graphics.pixar.com/library/RayTracingCars/paper.pdf) I believe.&#xD;&#xA;&#xD;&#xA;The second approach is more general and does not rely on heavy use of subdivision. Instead, it relies on the fact that your scene was most likely made by an artist and already comes partitioned into reasonably small objects that fit into memory individually. The idea is then to keep two hierarchies (kD-tree or bounding volume hierarchy): A top-level hierarchy that only stores bounding boxes of the objects in your scene, and a low-level hierarchy that stores the actual geometry. There is one such low-level hierarchy for each object.&#xD;&#xA;&#xD;&#xA;In this approach, you ideally already store a bounding box along with each object on disk. As the scene is loaded, you only build the top-level hierarchy initially, meaning you only have to look at the bounding boxes and not the geometry. You then start tracing rays and traverse them through the hierarchy. Whenever a ray hits a leaf node in the top-level hierarchy (i.e. it hits the bounding box of an object), that object is loaded into memory and its low-level hierarchy is built. The ray then continues down into tracing that object. Combined with an object cache that keeps as much of the low-level hierarchy in memory as possible, this can perform reasonably well.&#xD;&#xA;&#xD;&#xA;The first benefit of such an approach is that objects that are never hit are never loaded, meaning that it automatically adapts to the visibility in your scene. The second benefit is that if you are tracing many rays, you don't have to load an object immediately as it is hit by a ray; instead, you can hold that ray and wait until enough rays have hit that object, amortizing the load over multiple ray hits.&#xD;&#xA;&#xD;&#xA;You can also combine this approach with a ray sorting algorithm such as [Sorted Deferred Shading for Production Path Tracing](https://disney-animation.s3.amazonaws.com/uploads/production/publication_asset/70/asset/Sorted_Deferred_Shading_For_Production_Path_Tracing.pdf) to avoid thrashing due to incoherent rays. The mentioned paper describes the architecture of Disney's Hyperion renderer, used for Big Hero 6 I believe, so it most likely can handle scenes at production scale." ContentLicense="CC BY-SA 3.0" />
  <row Id="433" PostHistoryTypeId="2" PostId="154" RevisionGUID="662a387d-a72c-44a2-a31f-a8f06f6acceb" CreationDate="2015-08-09T23:11:11.807" UserId="231" Text="I'd like to be able to render a large population of small independently moving objects in real time. They may move in a swarm-like manner, but their relative positions will not be coherent - their position may change arbitrarily within a swarm and swarms may break up and reform at any point.&#xD;&#xA;&#xD;&#xA;What approach to building a bounding volume hierarchy would best suit this situation? Is there a way to maintain a hierarchy which is sub-optimal but good enough, that only requires a partial update each frame? Or is there a way of building a hierarchy from scratch each frame that is fast enough for smooth animation?&#xD;&#xA;&#xD;&#xA;The number of objects will be too large to render without a hierarchy, but for the same reason I expect building the hierarchy to be time consuming. " ContentLicense="CC BY-SA 3.0" />
  <row Id="434" PostHistoryTypeId="1" PostId="154" RevisionGUID="662a387d-a72c-44a2-a31f-a8f06f6acceb" CreationDate="2015-08-09T23:11:11.807" UserId="231" Text="How can I create a bounding volume hierarchy for constantly moving objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="435" PostHistoryTypeId="3" PostId="154" RevisionGUID="662a387d-a72c-44a2-a31f-a8f06f6acceb" CreationDate="2015-08-09T23:11:11.807" UserId="231" Text="|real-time|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 3.0" />
  <row Id="436" PostHistoryTypeId="5" PostId="150" RevisionGUID="d30f875c-2477-40f5-aafd-f619b7a0578e" CreationDate="2015-08-09T23:12:12.247" UserId="196" Comment="deleted 10 characters in body" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/Tfs4k.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="438" PostHistoryTypeId="2" PostId="155" RevisionGUID="9bef298d-a34d-4214-a375-d2285b455caa" CreationDate="2015-08-09T23:26:06.717" UserId="141" Text="There are at least two approaches:&#xD;&#xA;&#xD;&#xA;Try to simply make the bounding volumes a bit larger than necessary so that the objects don't cross their boundaries on every move but then again, you would have to rebuild the structure now-and-then anyway.&#xD;&#xA;&#xD;&#xA;Or, there is [Bounding interval hierarchy](https://en.wikipedia.org/wiki/Bounding_interval_hierarchy) which tries to address precisely this scenario." ContentLicense="CC BY-SA 3.0" />
  <row Id="439" PostHistoryTypeId="5" PostId="154" RevisionGUID="57f80667-08ab-4a5d-80d0-d88b2ed99c57" CreationDate="2015-08-09T23:32:10.547" UserId="231" Comment="Clarification following query" Text="I'd like to be able to render a large population of small independently moving objects in real time. They may move in a swarm-like manner, but their relative positions will not be coherent - their position may change arbitrarily within a swarm and swarms may break up and reform at any point.&#xD;&#xA;&#xD;&#xA;What approach to building a bounding volume hierarchy would best suit this situation? Is there a way to maintain a hierarchy which is sub-optimal but good enough, that only requires a partial update each frame? Or is there a way of building a hierarchy from scratch each frame that is fast enough for smooth animation?&#xD;&#xA;&#xD;&#xA;The number of objects will be too large to render without a hierarchy, but for the same reason I expect building the hierarchy to be time consuming. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Following the comment from John Calsbeek, if my focus on bounding volume hierarchies is misguided, and there is a better space partitioning approach for this situation, please answer accordingly. I'm looking for something that can deal with what I describe, including anything I haven't thought of." ContentLicense="CC BY-SA 3.0" />
  <row Id="440" PostHistoryTypeId="5" PostId="155" RevisionGUID="502fe20b-e68d-46e0-840c-2e2525d37cd1" CreationDate="2015-08-09T23:36:06.820" UserId="141" Comment="added 228 characters in body" Text="You could try to simply make the bounding volumes a bit larger than necessary so that the objects don't cross their boundaries on every move but then again, you would have to rebuild the structure now-and-then anyway.&#xD;&#xA;&#xD;&#xA;Or, there is [Bounding interval hierarchy](https://en.wikipedia.org/wiki/Bounding_interval_hierarchy) which tries to address precisely this scenario.&#xD;&#xA;&#xD;&#xA;Or, the paper by Ingo Wald, Solomon Boulos and Peter Shirley titled [Ray Tracing Deformable Scenes Using Dynamic Bounding Volume Hierarchies](http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/wald07_packetbvh.pdf) might be of interest." ContentLicense="CC BY-SA 3.0" />
  <row Id="441" PostHistoryTypeId="2" PostId="156" RevisionGUID="f4abd84c-8359-4e98-9c0b-a715d695486e" CreationDate="2015-08-09T23:37:56.080" UserId="329" Text="When I was first reading about all of this I stumbled upon this [link][1] which helped me better understand this large subject.  Also [this][2] goes into some more detail on things mentioned here.&#xD;&#xA;&#xD;&#xA;Light scattering is a natural phenomenon which arises when light interacts with particles distributed in a media as it travels through it.  From [Wikipedia][3]:&#xD;&#xA;&#xD;&#xA;&gt; Light scattering can be thought of as the deflection of a ray from a straight path, for example by irregularities in the propagation medium, particles, or in the interface between two media&#xD;&#xA;&#xD;&#xA;In computer graphics there are models that have been developed to simulate the effect of light traversing volume objects from an entry point (*Point A*) to an exit point (*Point B*).  As the light travels from *A* to *B* it is changed due to interactions with particles and these interactions are often referred to as **Absorption**, **Out Scattering** and **In Scattering**.  Often you will see these split into two groups; *Transmittance* (Absorption and Out Scattering) which I like to think of as 'light lost' and *In-Scattering* ('light gained').&#xD;&#xA;&#xD;&#xA;**Absorption** is basically incident light energy that is transformed into some other form of energy and therefore 'lost'.&#xD;&#xA;&#xD;&#xA;###Transmittance###&#xD;&#xA;Transmittance describes how light reflected behind a volume will be attenuated due to Absorption as it travels through a medium from *A* to *B*.  This is usually calculated with the Beer-Lambert law which relates the attenuation of light to the properties of the material through which it is travelling.  &#xD;&#xA;&#xD;&#xA;As the light travels through the medium there is a chance that the photons can be scattered away from their incident direction and therefore not make it to the eye of the observer and this is referred to as Out-Scattering.  In most models the Transmittance equation is changed slightly to introduce the concept of Out-Scattering. &#xD;&#xA;&#xD;&#xA;###In Scattering###&#xD;&#xA;Above we have seen how light can be lost due to photons been scattered away from the viewing direction.  At the same time light can be scattered back into the viewing direction as it is travelling from *A* to *B* and this is called In-Scattering. &#xD;&#xA;&#xD;&#xA;Particle In-Scattering itself is a pretty complex topic but basically you can split it into Isotropic and Anisotropic scattering.  Modelling Anisotropic scattering would take a considerable amount of time so usually in computer graphics this is simplified by using a Phase Function which describes the amount of light from the incident light direction that is scattered into the viewing direction as it travels from *A* to *B*.&#xD;&#xA;&#xD;&#xA;One commonly used non-isotropic Phase Function is called the Henyey-Greenstein phase function which can model Backward and Forward scattering.  It usually has a single parameter, g ∈ [−1,1], that determines the relative strength of forward and backward scattering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/volume-rendering/volume-rendering-for-artists/&#xD;&#xA;  [2]: http://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/chapter4.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Light_scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="442" PostHistoryTypeId="2" PostId="157" RevisionGUID="82ca876a-0b0f-4433-87dc-02082a7e89d2" CreationDate="2015-08-09T23:50:26.667" UserId="196" Text="Consider using spatial hashing, especially if your objects are similarly sized.&#xD;&#xA;&#xD;&#xA;Basically, divide your world into uniformly-sized grid cells (2D and 3D are both valid possibilities depending on the amount of vertical motion). Each update, assign your object to each bin that it overlaps—if the cells are decently sized relative to the objects, most objects should end up in a single bin.&#xD;&#xA;&#xD;&#xA;Each bin is inserted into a hash table, with the key being the coordinates of the bin. (You can also think of it as a hash table with multiple values for the same key, and inserting an object once for every cell that it overlaps.)&#xD;&#xA;&#xD;&#xA;There's no hierarchy to rebuild in this scheme, which makes it well suited for dynamic scenes. You can still test the cell's dimensions against the frustum or against occluders at a coarse level and discard many objects at once. Also, it's easier to manage this structure incrementally—you can keep the hash table the same from frame to frame and only move objects from one bin to another when they cross the boundary of a cell." ContentLicense="CC BY-SA 3.0" />
  <row Id="443" PostHistoryTypeId="33" PostId="89" RevisionGUID="6410f1dc-c9be-4540-a49f-7766753769e5" CreationDate="2015-08-10T00:32:23.767" UserId="231" Comment="1" />
  <row Id="447" PostHistoryTypeId="2" PostId="158" RevisionGUID="2b00a665-ca3b-4dc9-ae68-eadf4d3fc750" CreationDate="2015-08-10T01:11:41.027" UserId="110" Text="[Sorry for the very bad quality of my answer. I do not have access to a computer currently and editing from my phone is not a straightforward task. In particular I would love to be able to paste images.]  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;Here is a list of references I gathered on the subject, ordered chronologically.  &#xD;&#xA;  &#xD;&#xA;JAMES T. KAJIYA, TIMOTHY L. KAY, [Rendering Fur With Three Dimensional Textures](https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf), 1989  &#xD;&#xA;JEROME LENGYEL, EMIL PRAUN, ADAM FINKELSTEIN, HUGUES HOPPE, [Real-Time Fur over Arbitrary Surfaces](http://research.microsoft.com/en-us/um/people/hoppe/fur.pdf), 2000  &#xD;&#xA;STEPHEN R. MARSCHNER, HENRIK WANN JENSEN, MIKE CAMMARANO, [Light Scattering from Human Hair Fibers](http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf), 2003  &#xD;&#xA;ARMIN BRUDERLIN, SUNIL HADAP, TAE-YONG KIM, NADIA MAGNENAT-THALMANN , ULRICH NEUMANN, YIZHOU YU, STEVE WORLEY, [Photorealistic Hair Modeling, Animation, and Rendering](http://www.graphics.stanford.edu/courses/cs448-05-winter/papers/course34.pdf), Siggraph 2003 Course  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://bookzz.org/book/487747/b3254e), ShaderX3, 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairRendering.pdf), ATI / GDC 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketch.pdf), ATI / Siggraph 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf), ATI / Siggraph 2004 (slides)  &#xD;&#xA;MARTIN KOSTER, JORG HABER, HANS-PETER SEIDEL, [Real-Time Rendering of Human Hair using Programmable Graphics Hardware](http://resources.mpi-inf.mpg.de/FAM/publ/cgi2004.pdf), 2004  &#xD;&#xA;HUBERT NGUYEN, WILLIAM DONNELLY, [Hair Animation and Rendering in the Nalu Demo](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html), GPU Gems 2 (Chapter 23), 2005  &#xD;&#xA;LENA PETROVIC, MARK HENNE, JOHN ANDERSON, [Volumetric Methods for Simulation and Rendering of Hair](http://graphics.pixar.com/library/Hair/paper.pdf), Pixar 2006  &#xD;&#xA;CHRISTOPHE HERY, RAVI RAMAMOORTHI, [Importance Sampling of Reflections from Hair Fibers](http://graphics.pixar.com/library/ImportanceSamplingHair/paper.pdf), Pixar 2007  &#xD;&#xA;SARAH TARIQ, LOUIS BAVOIL, [Real-Time Hair Rendering on the GPU](http://www.nvidia.com/object/siggraph-2008-hair.html), Siggraph 2008. &#xD;&#xA;ARNO ZINKE, CEM YUKSEL, ANDREAS WEBER, JOHN KEYSER, [Dual Scattering Approximation for Fast Multiple Scattering in Hair](http://research.cs.tamu.edu/keyser/Papers/Siggraph08_dualscattering.pdf), Siggraph 2008  &#xD;&#xA;IMAN SADEGHI, HEATHER PRITCHETT, HENRIK WANN JENSEN, RASMUS TAMSTORF, [An Artist Friendly Hair Shading System](http://graphics.ucsd.edu/~henrik/papers/artist_hair.pdf), 2010  &#xD;&#xA;EUGENE D’EON, GUILLAUME FRANCOIS, MARTIN HILL, JOE LETTERI, JEAN-MARIE AUBRY, [An Energy-Conserving Hair Reflectance Model](http://www.eugenedeon.com/project/an-energy-conserving-hair-reflectance-model/), 2011  &#xD;&#xA;XUAN YU, JASON C. YANG, JUSTIN HENSLEY, TAKAHIRO HARADA, JINGYI YU, [A Framework for Rendering Complex Scattering Effects on Hair](http://www.eecis.udel.edu/~xyu/publications/frameworkhair124.pdf), 2012  &#xD;&#xA;JIAWEI OU, FENG XIE, PARASHAR KRISHNAMACHARI, FABIO PELLACINI, [ISHair: Importance Sampling for Hair Scattering](http://pellacini.di.uniroma1.it/publications/ishair12/ishair12-paper.pdf), 2012  &#xD;&#xA;SARAH INVERNIZZI, [On Physically Based Hair Rendering](http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/07/MSc_thesis_On_physically_based_hair_rendering.pdf), 2013  &#xD;&#xA;WOLFGANG ENGEL, [Hair Rendering in Tomb Raider](http://www.slideshare.net/WolfgangEngel/hair-intombraider-final), 2013  &#xD;&#xA;EUGENE D’EON, STEVE MARSCHNER, JOHANNES HANIKA, [Importance Sampling for Physically-Based Hair Fiber Models](https://cg.ivd.kit.edu/publications/pubhanika/2013_hairbrief.pdf), 2013  &#xD;&#xA;TIMOTHY MARTIN, WOLFGANG ENGEL, NICOLAS THIBIEROZ, JASON YANG, AND JASON LACROIX, [TressFX: Advanced Real-Time Hair Rendering](http://bookzz.org/book/2373940/c298ee), GPU Pro 5, 2015  &#xD;&#xA;LEONID PEKELIS, CHRISTOPHE HERY, RYUSUKE VILLEMIN, JUNYI LING, [A Data-Driven Light Scattering Model for Hair](http://graphics.pixar.com/library/DataDrivenHairScattering/paper.pdf), Pixar 2015  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;I must confess I unfortunately did not read all of those references yet. Also, I am more interested by the real-time solutions. Here is the little I think I understood:  &#xD;&#xA;- Kajiya-kay laid the basis for realistic hair / fur rendering  &#xD;&#xA;- Marschner proposed an improved model, and noted that hair has two distinct specular highlights (one white due to direct reflection, the other colored and sparkling due to reflection inside of the hair fiber)  &#xD;&#xA;- Scheuermann proposed approximations to simulate the behaviour described by Marschner, approximations suited for real-time (using tricks such as two separate specular highlights, artist-designed specular offset and exponent, noise textures)  &#xD;&#xA;- Most of the games I heard of seem to use Scheuermann approaches for hair shading. However, this is not an energy-conserving solution. Nevertheless, I think d'Eon attempts to fix this problem in the 2011 paper.   &#xD;&#xA;  &#xD;&#xA;The offline rendering world offers other solutions that I did not study yet, but whose main ones I believe are in the references above.  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="448" PostHistoryTypeId="5" PostId="158" RevisionGUID="dbacc285-93cf-46c2-a099-e00ffb285637" CreationDate="2015-08-10T01:19:20.040" UserId="110" Comment="added 143 characters in body" Text="[Sorry for the very bad quality of my answer. I do not have access to a computer currently and editing from my phone is not a straightforward task. In particular I would love to be able to paste images.]  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;Here is a list of references I gathered on the subject, ordered chronologically.  &#xD;&#xA;  &#xD;&#xA;JAMES T. KAJIYA, TIMOTHY L. KAY, [Rendering Fur With Three Dimensional Textures](https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf), 1989  &#xD;&#xA;JEROME LENGYEL, EMIL PRAUN, ADAM FINKELSTEIN, HUGUES HOPPE, [Real-Time Fur over Arbitrary Surfaces](http://research.microsoft.com/en-us/um/people/hoppe/fur.pdf), 2000  &#xD;&#xA;STEPHEN R. MARSCHNER, HENRIK WANN JENSEN, MIKE CAMMARANO, [Light Scattering from Human Hair Fibers](http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf), 2003  &#xD;&#xA;ARMIN BRUDERLIN, SUNIL HADAP, TAE-YONG KIM, NADIA MAGNENAT-THALMANN , ULRICH NEUMANN, YIZHOU YU, STEVE WORLEY, [Photorealistic Hair Modeling, Animation, and Rendering](http://www.graphics.stanford.edu/courses/cs448-05-winter/papers/course34.pdf), Siggraph 2003 Course  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://bookzz.org/book/487747/b3254e), ShaderX3, 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairRendering.pdf), ATI / GDC 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketch.pdf), ATI / Siggraph 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf), ATI / Siggraph 2004 (slides)  &#xD;&#xA;MARTIN KOSTER, JORG HABER, HANS-PETER SEIDEL, [Real-Time Rendering of Human Hair using Programmable Graphics Hardware](http://resources.mpi-inf.mpg.de/FAM/publ/cgi2004.pdf), 2004  &#xD;&#xA;HUBERT NGUYEN, WILLIAM DONNELLY, [Hair Animation and Rendering in the Nalu Demo](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html), GPU Gems 2 (Chapter 23), 2005  &#xD;&#xA;LENA PETROVIC, MARK HENNE, JOHN ANDERSON, [Volumetric Methods for Simulation and Rendering of Hair](http://graphics.pixar.com/library/Hair/paper.pdf), Pixar 2006  &#xD;&#xA;CHRISTOPHE HERY, RAVI RAMAMOORTHI, [Importance Sampling of Reflections from Hair Fibers](http://graphics.pixar.com/library/ImportanceSamplingHair/paper.pdf), Pixar 2007  &#xD;&#xA;SARAH TARIQ, LOUIS BAVOIL, [Real-Time Hair Rendering on the GPU](http://www.nvidia.com/object/siggraph-2008-hair.html), Siggraph 2008. &#xD;&#xA;ARNO ZINKE, CEM YUKSEL, ANDREAS WEBER, JOHN KEYSER, [Dual Scattering Approximation for Fast Multiple Scattering in Hair](http://research.cs.tamu.edu/keyser/Papers/Siggraph08_dualscattering.pdf), Siggraph 2008  &#xD;&#xA;IMAN SADEGHI, HEATHER PRITCHETT, HENRIK WANN JENSEN, RASMUS TAMSTORF, [An Artist Friendly Hair Shading System](http://graphics.ucsd.edu/~henrik/papers/artist_hair.pdf), 2010  &#xD;&#xA;EUGENE D’EON, GUILLAUME FRANCOIS, MARTIN HILL, JOE LETTERI, JEAN-MARIE AUBRY, [An Energy-Conserving Hair Reflectance Model](http://www.eugenedeon.com/project/an-energy-conserving-hair-reflectance-model/), 2011  &#xD;&#xA;XUAN YU, JASON C. YANG, JUSTIN HENSLEY, TAKAHIRO HARADA, JINGYI YU, [A Framework for Rendering Complex Scattering Effects on Hair](http://www.eecis.udel.edu/~xyu/publications/frameworkhair124.pdf), 2012  &#xD;&#xA;JIAWEI OU, FENG XIE, PARASHAR KRISHNAMACHARI, FABIO PELLACINI, [ISHair: Importance Sampling for Hair Scattering](http://pellacini.di.uniroma1.it/publications/ishair12/ishair12-paper.pdf), 2012  &#xD;&#xA;SARAH INVERNIZZI, [On Physically Based Hair Rendering](http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/07/MSc_thesis_On_physically_based_hair_rendering.pdf), 2013  &#xD;&#xA;WOLFGANG ENGEL, [Hair Rendering in Tomb Raider](http://www.slideshare.net/WolfgangEngel/hair-intombraider-final), 2013  &#xD;&#xA;EUGENE D’EON, STEVE MARSCHNER, JOHANNES HANIKA, [Importance Sampling for Physically-Based Hair Fiber Models](https://cg.ivd.kit.edu/publications/pubhanika/2013_hairbrief.pdf), 2013  &#xD;&#xA;TIMOTHY MARTIN, WOLFGANG ENGEL, NICOLAS THIBIEROZ, JASON YANG, AND JASON LACROIX, [TressFX: Advanced Real-Time Hair Rendering](http://bookzz.org/book/2373940/c298ee), GPU Pro 5, 2015  &#xD;&#xA;LEONID PEKELIS, CHRISTOPHE HERY, RYUSUKE VILLEMIN, JUNYI LING, [A Data-Driven Light Scattering Model for Hair](http://graphics.pixar.com/library/DataDrivenHairScattering/paper.pdf), Pixar 2015  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;I must confess I unfortunately did not read all of those references yet. Also, I am more interested by the real-time solutions. Here is a little of what I think I read:  &#xD;&#xA;- Kajiya-kay laid the basis for realistic hair / fur rendering  &#xD;&#xA;- Marschner proposed an improved model, and noted that hair has two distinct specular highlights (one white due to direct reflection, the other colored and sparkling due to reflection inside of the hair fiber)  &#xD;&#xA;- Scheuermann proposed approximations to simulate the behaviour described by Marschner, approximations suited for real-time (using tricks such as two separate specular highlights, artist-designed specular offset and exponent, noise textures). He also proposed using three rendering passes (opaque, transparent back and front) of polygons to simulate the &quot;volumetric&quot; qualities of hair  &#xD;&#xA;- Most of the games I heard of seem to use Scheuermann approaches for hair shading. However, this is not an energy-conserving solution. Nevertheless, I think d'Eon attempts to fix this problem in the 2011 paper.   &#xD;&#xA;  &#xD;&#xA;The offline rendering world offers other solutions that I did not study yet, but whose main ones I believe are in the references above.  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="450" PostHistoryTypeId="2" PostId="159" RevisionGUID="b6f95195-d658-4d9a-8ec3-5e807ae7c184" CreationDate="2015-08-10T01:52:02.447" UserId="231" Text="The iris (the colourful ring surrounding the pupil of the eye) is covered in a layer of water, and appears to have opaque elements embedded in transparent and translucent elements. What effects do I need to model in order for the iris to appear realistic close up (the iris taking up over 20% of the image area)?&#xD;&#xA;&#xD;&#xA;Is sub surface scattering necessary or is transparency sufficient? Is it necessary to take into account light from within the eye that entered via the pupil, or can the back of the iris be regarded as completely opaque? Are there other effects that I haven't considered?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="451" PostHistoryTypeId="1" PostId="159" RevisionGUID="b6f95195-d658-4d9a-8ec3-5e807ae7c184" CreationDate="2015-08-10T01:52:02.447" UserId="231" Text="Which effects do I need to take into account for the iris of the eye?" ContentLicense="CC BY-SA 3.0" />
  <row Id="452" PostHistoryTypeId="3" PostId="159" RevisionGUID="b6f95195-d658-4d9a-8ec3-5e807ae7c184" CreationDate="2015-08-10T01:52:02.447" UserId="231" Text="|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="453" PostHistoryTypeId="2" PostId="160" RevisionGUID="3f0bd7d4-6e5d-4c82-8f4e-03a5faaad8f2" CreationDate="2015-08-10T02:02:02.570" UserId="231" Text="Close up, rain can be modeled as transparent balls of water with appropriate motion blur. This seems impractical for large volumes, which would be necessary for scenes of rain in the distance.&#xD;&#xA;&#xD;&#xA;At distances for which the human eye cannot resolve individual raindrops, how can the effect of rain-filled atmosphere be modeled? This does not need to be efficient enough for real time use, but it does need to allow multiple frames to be produced offline for animation without jarring discontinuities or flickering.&#xD;&#xA;&#xD;&#xA;What approaches are available for this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="454" PostHistoryTypeId="1" PostId="160" RevisionGUID="3f0bd7d4-6e5d-4c82-8f4e-03a5faaad8f2" CreationDate="2015-08-10T02:02:02.570" UserId="231" Text="How can I model distant rain?" ContentLicense="CC BY-SA 3.0" />
  <row Id="455" PostHistoryTypeId="3" PostId="160" RevisionGUID="3f0bd7d4-6e5d-4c82-8f4e-03a5faaad8f2" CreationDate="2015-08-10T02:02:02.570" UserId="231" Text="|atmospherics|offline|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="456" PostHistoryTypeId="33" PostId="15" RevisionGUID="b7cd4034-0d99-454a-8925-2c7116e84a19" CreationDate="2015-08-10T02:12:22.143" UserId="48" Comment="2" />
  <row Id="457" PostHistoryTypeId="5" PostId="41" RevisionGUID="0cec0a0f-7dee-4624-b2e6-88b7aa2d0d2a" CreationDate="2015-08-10T04:40:19.637" UserId="194" Comment="As suggested by user trichoplax information on the different values for the two kernels was added, as well as some leads into why a convolution kernel needs to be flipped." Text="In convolution, two mathematical functions are combined to produce a third function. In image processing functions are usually called kernels. A kernel is nothing more than a (square) array of pixels (a small image so to speak). Usually, the values in the kernel add up to one. This is to make sure noe energy is added or removed from the image after the operation.&#xD;&#xA;&#xD;&#xA;Specifically, a Gaussian kernal (used for Gaussian blur) is a square array of pixels where the pixel values correspond to the values of a Gaussian curve (in 2d).&#xD;&#xA;&#xD;&#xA;[![Image linked from http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm][1]][1]&#xD;&#xA;&#xD;&#xA;Each pixel in the image gets multiplied by the Gaussian kernel. This is done by placing the center pixel of the kernel on the image pixel and multiplying the values in the original image with the pixels in the kernel that overlap. The values resulting from these multiplications are added up and that result is used for the value at the destination pixel. Looking at the image, you would multiply the value at (0,0) in the input array by the value a (i) in the kernel array, the value at (1,0) in the input array by the value a (h) in the kernel array, etc. and then add all these values to get the value for (1,1) at the output image.&#xD;&#xA;&#xD;&#xA;[![Image linked from http://www.songho.ca/dsp/convolution/convolution.html][2]][2]&#xD;&#xA;&#xD;&#xA;To answer your second question first, the larger the kernel, the more expensive the operation. So, the larger the radius of the blur, the longer the operation will take.&#xD;&#xA;&#xD;&#xA;To answer your first question, as explained above, convolution can be done by multiplying each input pixel with the entire kernel. However, if the kernel is symmetrical (wich a Gaussian kernel is) you can also multiply each axis (x and y) independently, which will decrease the total number of multiplications. In proper mathematical terms, if a matrix is separable it can be decomposed into (M×1) and (1×N) matrices. For the Gaussian kernel above this means you can also use the following kernels:&#xD;&#xA;&#xD;&#xA;[![Image linked from http://dsp.stackexchange.com/questions/8501/when-should-the-sum-of-all-elements-of-a-gaussian-kernel-be-zero][3]][3]&#xD;&#xA;&#xD;&#xA;You would now multiply each pixel in the input image with both kernels and add the resulting values to get the value for the output pixel.&#xD;&#xA;&#xD;&#xA;For more information on how to see if a kernel is separable, follow this [link][4].&#xD;&#xA;&#xD;&#xA;Edit: the two kernels shown above use slightly different values. This is because the (sigma) parameter used for the Gaussian curve to create these kernels were slightly different in both cases. For an explanation on which parameters influence the shape of the Gaussian curve and thus the values in the kernel follow this [link][5]&#xD;&#xA;&#xD;&#xA;Edit: in the second image above it says the kernel that is used is flipped. This of course only makes any difference if the kernel you use is not symmetric. The reason why you need to flip the kernel has to do with the mathematical properties of the convolution operation (see [link][6] for a more in depth explanation on convolution). Simply put: if you would not flip the kernel, the result of the convolution operation will be flipped. By flipping the kernel, you get the correct result.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Qc4Mq.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/bRN2c.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UsU96.gif&#xD;&#xA;  [4]: http://stackoverflow.com/questions/5886529/how-can-i-determine-if-my-convolution-is-separable&#xD;&#xA;  [5]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;  [6]: http://songho.ca/dsp/convolution/convolution.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="460" PostHistoryTypeId="5" PostId="4" RevisionGUID="9aa687e4-4601-40e1-ba69-0f1f689b14ff" CreationDate="2015-08-10T05:07:39.443" UserId="231" Comment="Add syntax highlighting" Text="I just implemented some interpolated texture sampling by sampling the 4x4 nearest pixels then doing Lagrange interpolation across the x axis to get four values to use Lagrange interpolation on across the y axis.&#xD;&#xA;&#xD;&#xA;Is this the same as bicubic interpolation or is it different?  Or are there different kinds of bicubic interpolation, and this is just one of them perhaps?&#xD;&#xA;&#xD;&#xA;Webgl Shadertoy implementation here and relevant GLSL (WebGL) code below: https://www.shadertoy.com/view/MllSzX&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    float c_textureSize = 64.0;&#xD;&#xA;    &#xD;&#xA;    float c_onePixel = 1.0 / c_textureSize;&#xD;&#xA;    float c_twoPixels = 2.0 / c_textureSize;&#xD;&#xA;    &#xD;&#xA;    float c_x0 = -1.0;&#xD;&#xA;    float c_x1 =  0.0;&#xD;&#xA;    float c_x2 =  1.0;&#xD;&#xA;    float c_x3 =  2.0;&#xD;&#xA;        &#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 CubicLagrange (vec3 A, vec3 B, vec3 C, vec3 D, float t)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            A * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x1) / (c_x0 - c_x1) * &#xD;&#xA;                (t - c_x2) / (c_x0 - c_x2) *&#xD;&#xA;                (t - c_x3) / (c_x0 - c_x3)&#xD;&#xA;            ) +&#xD;&#xA;            B * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x0) / (c_x1 - c_x0) * &#xD;&#xA;                (t - c_x2) / (c_x1 - c_x2) *&#xD;&#xA;                (t - c_x3) / (c_x1 - c_x3)&#xD;&#xA;            ) +&#xD;&#xA;            C * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x0) / (c_x2 - c_x0) * &#xD;&#xA;                (t - c_x1) / (c_x2 - c_x1) *&#xD;&#xA;                (t - c_x3) / (c_x2 - c_x3)&#xD;&#xA;            ) +       &#xD;&#xA;            D * &#xD;&#xA;            (&#xD;&#xA;                (t - c_x0) / (c_x3 - c_x0) * &#xD;&#xA;                (t - c_x1) / (c_x3 - c_x1) *&#xD;&#xA;                (t - c_x2) / (c_x3 - c_x2)&#xD;&#xA;            );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 BicubicTextureSample (vec2 P)&#xD;&#xA;    {&#xD;&#xA;        vec2 pixel = P * c_textureSize + 0.5;&#xD;&#xA;        &#xD;&#xA;        vec2 frac = fract(pixel);&#xD;&#xA;        pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);&#xD;&#xA;        &#xD;&#xA;        vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;&#xD;&#xA;        &#xD;&#xA;        vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;&#xD;&#xA;        vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;&#xD;&#xA;        vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 CP0X = CubicLagrange(C00, C10, C20, C30, frac.x);&#xD;&#xA;        vec3 CP1X = CubicLagrange(C01, C11, C21, C31, frac.x);&#xD;&#xA;        vec3 CP2X = CubicLagrange(C02, C12, C22, C32, frac.x);&#xD;&#xA;        vec3 CP3X = CubicLagrange(C03, C13, C23, C33, frac.x);&#xD;&#xA;        &#xD;&#xA;        return CubicLagrange(CP0X, CP1X, CP2X, CP3X, frac.y);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="461" PostHistoryTypeId="24" PostId="4" RevisionGUID="9aa687e4-4601-40e1-ba69-0f1f689b14ff" CreationDate="2015-08-10T05:07:39.443" Comment="Proposed by 231 approved by 48, 56 edit id of 23" ContentLicense="CC BY-SA 3.0" />
  <row Id="462" PostHistoryTypeId="2" PostId="161" RevisionGUID="22dabe20-8716-4b4a-a606-a0f4f4de5768" CreationDate="2015-08-10T06:26:07.000" UserId="316" Text="A lot of ShaderToy demos share the Ray Marching algorithm to render the scene, but they are often written with a very compact style and i can't find any straightforward examples or explanation.&#xD;&#xA;&#xD;&#xA;So what is Ray Marching? Some comments suggests that it is a variation of Sphere Tracing. What are the computational advantages of a such approach?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="463" PostHistoryTypeId="1" PostId="161" RevisionGUID="22dabe20-8716-4b4a-a606-a0f4f4de5768" CreationDate="2015-08-10T06:26:07.000" UserId="316" Text="What is Ray Marching? Is Sphere Tracing the same thing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="464" PostHistoryTypeId="3" PostId="161" RevisionGUID="22dabe20-8716-4b4a-a606-a0f4f4de5768" CreationDate="2015-08-10T06:26:07.000" UserId="316" Text="|raytracing|demoscene|raymarching|" ContentLicense="CC BY-SA 3.0" />
  <row Id="465" PostHistoryTypeId="4" PostId="149" RevisionGUID="40b32cf4-f8a3-4bcf-bd9d-13fb1d694403" CreationDate="2015-08-10T07:13:13.427" UserId="36" Comment="Converted title to proper sentence." Text="How does state of the art real time hair rendering work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="466" PostHistoryTypeId="24" PostId="149" RevisionGUID="40b32cf4-f8a3-4bcf-bd9d-13fb1d694403" CreationDate="2015-08-10T07:13:13.427" Comment="Proposed by 36 approved by 48, 100 edit id of 24" ContentLicense="CC BY-SA 3.0" />
  <row Id="467" PostHistoryTypeId="5" PostId="158" RevisionGUID="e44a5c9d-5b69-40d5-8e3b-7517083ef29f" CreationDate="2015-08-10T07:31:55.630" UserId="110" Comment="added 289 characters in body" Text="[Sorry for the very bad quality of my answer. I do not have access to a computer currently and editing from my phone is not a straightforward task. In particular I would love to be able to paste images.]  &#xD;&#xA;  &#xD;&#xA;I would say that the main challenges of stimulating hair are:   &#xD;&#xA;- replicating their very specific reaction to lighting (as a material)  &#xD;&#xA;- replicating their volumetric property (as a geometry)  &#xD;&#xA;- animating them in a realistic manner  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;Here is a list of references I gathered on the subject, ordered chronologically (mainly about the rendering part).  &#xD;&#xA;  &#xD;&#xA;JAMES T. KAJIYA, TIMOTHY L. KAY, [Rendering Fur With Three Dimensional Textures](https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf), 1989  &#xD;&#xA;JEROME LENGYEL, EMIL PRAUN, ADAM FINKELSTEIN, HUGUES HOPPE, [Real-Time Fur over Arbitrary Surfaces](http://research.microsoft.com/en-us/um/people/hoppe/fur.pdf), 2000  &#xD;&#xA;STEPHEN R. MARSCHNER, HENRIK WANN JENSEN, MIKE CAMMARANO, [Light Scattering from Human Hair Fibers](http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf), 2003  &#xD;&#xA;ARMIN BRUDERLIN, SUNIL HADAP, TAE-YONG KIM, NADIA MAGNENAT-THALMANN , ULRICH NEUMANN, YIZHOU YU, STEVE WORLEY, [Photorealistic Hair Modeling, Animation, and Rendering](http://www.graphics.stanford.edu/courses/cs448-05-winter/papers/course34.pdf), Siggraph 2003 Course  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://bookzz.org/book/487747/b3254e), ShaderX3, 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairRendering.pdf), ATI / GDC 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketch.pdf), ATI / Siggraph 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf), ATI / Siggraph 2004 (slides)  &#xD;&#xA;MARTIN KOSTER, JORG HABER, HANS-PETER SEIDEL, [Real-Time Rendering of Human Hair using Programmable Graphics Hardware](http://resources.mpi-inf.mpg.de/FAM/publ/cgi2004.pdf), 2004  &#xD;&#xA;HUBERT NGUYEN, WILLIAM DONNELLY, [Hair Animation and Rendering in the Nalu Demo](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html), GPU Gems 2 (Chapter 23), 2005  &#xD;&#xA;LENA PETROVIC, MARK HENNE, JOHN ANDERSON, [Volumetric Methods for Simulation and Rendering of Hair](http://graphics.pixar.com/library/Hair/paper.pdf), Pixar 2006  &#xD;&#xA;CHRISTOPHE HERY, RAVI RAMAMOORTHI, [Importance Sampling of Reflections from Hair Fibers](http://graphics.pixar.com/library/ImportanceSamplingHair/paper.pdf), Pixar 2007  &#xD;&#xA;SARAH TARIQ, LOUIS BAVOIL, [Real-Time Hair Rendering on the GPU](http://www.nvidia.com/object/siggraph-2008-hair.html), Siggraph 2008. &#xD;&#xA;ARNO ZINKE, CEM YUKSEL, ANDREAS WEBER, JOHN KEYSER, [Dual Scattering Approximation for Fast Multiple Scattering in Hair](http://research.cs.tamu.edu/keyser/Papers/Siggraph08_dualscattering.pdf), Siggraph 2008  &#xD;&#xA;IMAN SADEGHI, HEATHER PRITCHETT, HENRIK WANN JENSEN, RASMUS TAMSTORF, [An Artist Friendly Hair Shading System](http://graphics.ucsd.edu/~henrik/papers/artist_hair.pdf), 2010  &#xD;&#xA;EUGENE D’EON, GUILLAUME FRANCOIS, MARTIN HILL, JOE LETTERI, JEAN-MARIE AUBRY, [An Energy-Conserving Hair Reflectance Model](http://www.eugenedeon.com/project/an-energy-conserving-hair-reflectance-model/), 2011  &#xD;&#xA;XUAN YU, JASON C. YANG, JUSTIN HENSLEY, TAKAHIRO HARADA, JINGYI YU, [A Framework for Rendering Complex Scattering Effects on Hair](http://www.eecis.udel.edu/~xyu/publications/frameworkhair124.pdf), 2012  &#xD;&#xA;JIAWEI OU, FENG XIE, PARASHAR KRISHNAMACHARI, FABIO PELLACINI, [ISHair: Importance Sampling for Hair Scattering](http://pellacini.di.uniroma1.it/publications/ishair12/ishair12-paper.pdf), 2012  &#xD;&#xA;SARAH INVERNIZZI, [On Physically Based Hair Rendering](http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/07/MSc_thesis_On_physically_based_hair_rendering.pdf), 2013  &#xD;&#xA;WOLFGANG ENGEL, [Hair Rendering in Tomb Raider](http://www.slideshare.net/WolfgangEngel/hair-intombraider-final), 2013  &#xD;&#xA;EUGENE D’EON, STEVE MARSCHNER, JOHANNES HANIKA, [Importance Sampling for Physically-Based Hair Fiber Models](https://cg.ivd.kit.edu/publications/pubhanika/2013_hairbrief.pdf), 2013  &#xD;&#xA;TIMOTHY MARTIN, WOLFGANG ENGEL, NICOLAS THIBIEROZ, JASON YANG, AND JASON LACROIX, [TressFX: Advanced Real-Time Hair Rendering](http://bookzz.org/book/2373940/c298ee), GPU Pro 5, 2015  &#xD;&#xA;LEONID PEKELIS, CHRISTOPHE HERY, RYUSUKE VILLEMIN, JUNYI LING, [A Data-Driven Light Scattering Model for Hair](http://graphics.pixar.com/library/DataDrivenHairScattering/paper.pdf), Pixar 2015  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;I must confess I unfortunately did not read all of those references yet. Also, I am more interested by the real-time solutions. Here is a little of what I think I read:  &#xD;&#xA;- Kajiya-kay laid the basis for realistic hair / fur rendering  &#xD;&#xA;- Marschner proposed an improved model, and noted that hair has two distinct specular highlights (one white due to direct reflection, the other colored and sparkling due to reflection inside of the hair fiber)  &#xD;&#xA;- Scheuermann proposed approximations to simulate the behaviour described by Marschner, approximations suited for real-time (using tricks such as two separate specular highlights, artist-designed specular offset and exponent, noise textures). He also proposed using three rendering passes (opaque, transparent back and front) of polygons to simulate the &quot;volumetric&quot; qualities of hair  &#xD;&#xA;- Most of the games I heard of seem to use Scheuermann approaches for hair shading. However, this is not an energy-conserving solution. Nevertheless, I think d'Eon attempts to fix this problem in the 2011 paper.  &#xD;&#xA;Also, tessellation has also been used to replace the polygonal approach and stimulate hair stands individually.     &#xD;&#xA;  &#xD;&#xA;The offline rendering world offers other solutions that I did not study yet, but whose main ones I believe are in the references above.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="468" PostHistoryTypeId="2" PostId="162" RevisionGUID="0d29ce0c-3949-41a5-8abf-d09c6cbae08b" CreationDate="2015-08-10T07:34:19.733" UserId="198" Text="Ray marching is an iterative ray intersection test in which you step along a ray and test for intersections, normally used to find intersections with *solid* geometry, where inside/outside tests are fast.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&lt;br/&gt;&lt;sup&gt;Images from [Rendering Geometry with Relief Textures](http://artis.imag.fr/Publications/2006/BD06/relief05.pdf)&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;A fixed step size is pretty common if you really have no idea where an intersection may occur, but sometimes root finding methods such as a binary or secant search are used instead. Often a fixed step size is used to find the first intersection, followed by a binary search. I first came across ray marching in per-pixel displacement mapping techniques. [Relief Mapping of Non-Height-Field Surface Details](http://www.inf.ufrgs.br/~oliveira/pubs_files/Policarpo_Oliveira_RTM_multilayer_I3D2006.pdf) is a good read!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;It's commonly used with space leaping, an acceleration technique where some preprocessing gives a safety distance that you can move along the ray without intersecting geometry, or better yet, without intersecting and then leaving geometry so that you miss it. For example, cone step mapping, and relaxed cone step mapping.&#xD;&#xA;&#xD;&#xA;Sphere tracing may refer to an implicit ray-sphere intersection test, but it's also the name of a space leaping technique by William Donnelly ([*Per-Pixel Displacement Mapping with Distance Functions*](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter08.html)), where a 3D texture encodes spheres radii in which no geometry exists.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JhSP2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/msLZp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="469" PostHistoryTypeId="2" PostId="163" RevisionGUID="33758dbd-a866-4183-b959-798db4ef8ad5" CreationDate="2015-08-10T07:35:06.200" UserId="38" Text="###Raymarching a definition&#xD;&#xA;&#xD;&#xA;Raymarching is a technique a but like traditional raytracing where the surface function is not easy to solve. In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xD;&#xA;&#xD;&#xA;This can be useful if you:&#xD;&#xA;&#xD;&#xA;* Need to render volumetrics that arenot uniform&#xD;&#xA;* Rendering implicit functions, fractals&#xD;&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xD;&#xA;* Etc&#xD;&#xA;&#xD;&#xA;Related posts:&#xD;&#xA;&#xD;&#xA;* [how-do-raymarch-shaders-work](http://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Sphere tracing &#xD;&#xA;&#xD;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xD;&#xA;&#xD;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xD;&#xA;&#xD;&#xA;    F(X,Y,Z) = 0&#xD;&#xA;&#xD;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step. You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xD;&#xA;&#xD;&#xA;For more info see: &#xD;&#xA;&#xD;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="470" PostHistoryTypeId="5" PostId="162" RevisionGUID="09c2bf4d-0829-4260-b39f-2ba2f2ffc06a" CreationDate="2015-08-10T07:41:52.513" UserId="198" Comment="added 57 characters in body" Text="Ray marching is an iterative ray intersection test in which you step along a ray and test for intersections, normally used to find intersections with *solid* geometry, where inside/outside tests are fast.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&lt;br/&gt;&lt;sup&gt;Images from [Rendering Geometry with Relief Textures](http://artis.imag.fr/Publications/2006/BD06/relief05.pdf)&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;A fixed step size is pretty common if you really have no idea where an intersection may occur, but sometimes root finding methods such as a binary or secant search are used instead. Often a fixed step size is used to find the first intersection, followed by a binary search. I first came across ray marching in per-pixel displacement mapping techniques. [Relief Mapping of Non-Height-Field Surface Details](http://www.inf.ufrgs.br/~oliveira/pubs_files/Policarpo_Oliveira_RTM_multilayer_I3D2006.pdf) is a good read!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;It's commonly used with space leaping, an acceleration technique where some preprocessing gives a safety distance that you can move along the ray without intersecting geometry, or better yet, without intersecting and then leaving geometry so that you miss it. For example, cone step mapping, and relaxed cone step mapping.&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;Sphere tracing may refer to an implicit ray-sphere intersection test,&lt;/strike&gt; but it's also the name of a space leaping technique by John Hart, as @joojaa mentions, and used by William Donnelly ([*Per-Pixel Displacement Mapping with Distance Functions*](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter08.html)), where a 3D texture encodes spheres radii in which no geometry exists.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JhSP2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/msLZp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="471" PostHistoryTypeId="5" PostId="163" RevisionGUID="c3ed5d95-6471-41d4-b8f3-4086fffef25f" CreationDate="2015-08-10T07:45:51.870" UserId="38" Comment="Added image" Text="###Raymarching a definition&#xD;&#xA;&#xD;&#xA;Raymarching is a technique a but like traditional raytracing where the surface function is not easy to solve. In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xD;&#xA;&#xD;&#xA;This can be useful if you:&#xD;&#xA;&#xD;&#xA;* Need to render volumetrics that arenot uniform&#xD;&#xA;* Rendering implicit functions, fractals&#xD;&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xD;&#xA;* Etc&#xD;&#xA;&#xD;&#xA;Related posts:&#xD;&#xA;&#xD;&#xA;* [how-do-raymarch-shaders-work](http://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Sphere tracing &#xD;&#xA;&#xD;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xD;&#xA;&#xD;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xD;&#xA;&#xD;&#xA;    F(X,Y,Z) = 0&#xD;&#xA;&#xD;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xD;&#xA;&#xD;&#xA;![Sphere tracing has a adaptive step size][1]&#xD;&#xA;&#xD;&#xA;**Image 2**: Sphere tracing in action note how the step size is adaptive&#xD;&#xA;&#xD;&#xA;For more info see: &#xD;&#xA;&#xD;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dFHFY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="472" PostHistoryTypeId="5" PostId="163" RevisionGUID="13762700-84f3-4ee7-b629-edfdea2b395e" CreationDate="2015-08-10T08:02:18.893" UserId="38" Comment="added 137 characters in body" Text="###Raymarching a definition&#xD;&#xA;&#xD;&#xA;Raymarching is a technique a but like traditional raytracing where the surface function is not easy to solve (or impossible without numeric iterative methods). In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xD;&#xA;&#xD;&#xA;This can be useful if you:&#xD;&#xA;&#xD;&#xA;* Need to render volumetrics that arenot uniform&#xD;&#xA;* Rendering implicit functions, fractals&#xD;&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xD;&#xA;* Etc&#xD;&#xA;&#xD;&#xA;![Traditional raymarching][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Traditional ray marching for surface finding&#xD;&#xA;&#xD;&#xA;Related posts:&#xD;&#xA;&#xD;&#xA;* [how-do-raymarch-shaders-work](http://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Sphere tracing &#xD;&#xA;&#xD;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xD;&#xA;&#xD;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xD;&#xA;&#xD;&#xA;    F(X,Y,Z) = 0&#xD;&#xA;&#xD;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xD;&#xA;&#xD;&#xA;![Sphere tracing has a adaptive step size][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Sphere tracing\* in action note how the step size is adaptive&#xD;&#xA;&#xD;&#xA;For more info see: &#xD;&#xA;&#xD;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bc4D5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;&#xD;&#xA;\* Perhaps in 2d it's should be called circle tracing :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="473" PostHistoryTypeId="5" PostId="163" RevisionGUID="4a3f8fe8-1caa-4510-bb5a-c8b51b296365" CreationDate="2015-08-10T08:09:05.480" UserId="38" Comment="added 137 characters in body" Text="### TL;DR&#xD;&#xA;&#xD;&#xA;They belong to the same family of solvers, where sphere tracing is one method of ray marching, which is the family name.&#xD;&#xA;&#xD;&#xA;###Raymarching a definition&#xD;&#xA;&#xD;&#xA;Raymarching is a technique a but like traditional raytracing where the surface function is not easy to solve (or impossible without numeric iterative methods). In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xD;&#xA;&#xD;&#xA;This can be useful if you:&#xD;&#xA;&#xD;&#xA;* Need to render volumetrics that arenot uniform&#xD;&#xA;* Rendering implicit functions, fractals&#xD;&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xD;&#xA;* Etc&#xD;&#xA;&#xD;&#xA;![Traditional raymarching][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Traditional ray marching for surface finding&#xD;&#xA;&#xD;&#xA;Related posts:&#xD;&#xA;&#xD;&#xA;* [how-do-raymarch-shaders-work](http://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Sphere tracing &#xD;&#xA;&#xD;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xD;&#xA;&#xD;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xD;&#xA;&#xD;&#xA;    F(X,Y,Z) = 0&#xD;&#xA;&#xD;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xD;&#xA;&#xD;&#xA;![Sphere tracing has a adaptive step size][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Sphere tracing\* in action note how the step size is adaptive&#xD;&#xA;&#xD;&#xA;For more info see: &#xD;&#xA;&#xD;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bc4D5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;&#xD;&#xA;\* Perhaps in 2d it's should be called circle tracing :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="474" PostHistoryTypeId="2" PostId="164" RevisionGUID="35ca585a-b03b-4cf6-a8bd-2eb18117c33b" CreationDate="2015-08-10T08:09:19.900" UserId="118" Text="When you think about rain in the distance (generally), you will have rain at several different depths from the camera, some close up, some very far away, all of which will look slightly different as you won't be able to focus on all of them. But the effect of them all layering on top of each other as they go off into the distance is what helps give the look you're aiming for, you need to recreate that depth and layering to really give the look of rain further in the distance.&#xD;&#xA;&#xD;&#xA;Particle emitters are the general method of creating rain, as usually they use very small meshes, or even just a texture sprite of a drop. This keeps them pretty efficient - to a degree as the more particles you use and have on-screen at a time will change how heavy or resource dependant the effect becomes.&#xD;&#xA;&#xD;&#xA;Generally you would only use large detailed meshes for rain, when you have a close up of a puddle and wanted to animate the splash, or even a close up of the single drop for some reason.&#xD;&#xA;&#xD;&#xA;This can be combined with distance fog to further increase the sense of depth in your scene by occluding the objects in the far distance.&#xD;&#xA;&#xD;&#xA;Again you could use another particle emitter to create dark, heavy clouds that go off into the distance, as having clouds in the scene will help to sell the look.&#xD;&#xA;&#xD;&#xA;A lot of this will depend on what software you're using, as well as its intended platform, as different software have different solutions but particles and fog are pretty commonplace.&#xD;&#xA;&#xD;&#xA;tldr: Particle Effects &amp; Distance Fog" ContentLicense="CC BY-SA 3.0" />
  <row Id="475" PostHistoryTypeId="6" PostId="160" RevisionGUID="dc507305-1932-43db-bc30-ab507fbd9de3" CreationDate="2015-08-10T09:12:33.097" UserId="198" Comment="added fog tag to reflect answer" Text="|atmospherics|offline|animation|fog|" ContentLicense="CC BY-SA 3.0" />
  <row Id="476" PostHistoryTypeId="24" PostId="160" RevisionGUID="dc507305-1932-43db-bc30-ab507fbd9de3" CreationDate="2015-08-10T09:12:33.097" Comment="Proposed by 198 approved by 231 edit id of 25" ContentLicense="CC BY-SA 3.0" />
  <row Id="477" PostHistoryTypeId="2" PostId="165" RevisionGUID="e21265dc-6425-4cf3-94d4-28e6781f67c0" CreationDate="2015-08-10T09:39:33.647" UserId="198" Text="I recently had an [issue with sub-pixel anti-aliasing of text](http://superuser.com/q/930036/264276), which produces very harsh colours:&#xD;&#xA;&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've drawn some cases of a black tile covering thirds of pixels below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The colours match the ones I'm seeing, however when I look at properly antialiased text, the result is not nearly as bright and distracting:&#xD;&#xA;&#xD;&#xA;&gt; ![from www.lagom.nl](https://i.stack.imgur.com/4Vrfz.png)&#xD;&#xA;&#xD;&#xA;I assume there has to be a balance between a good light intensity and the right colour. What methods are used for sub-pixel anti-aliasing that give such good results?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SQWSI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CE16y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="478" PostHistoryTypeId="1" PostId="165" RevisionGUID="e21265dc-6425-4cf3-94d4-28e6781f67c0" CreationDate="2015-08-10T09:39:33.647" UserId="198" Text="Sub-pixel antialiasing rules" ContentLicense="CC BY-SA 3.0" />
  <row Id="479" PostHistoryTypeId="3" PostId="165" RevisionGUID="e21265dc-6425-4cf3-94d4-28e6781f67c0" CreationDate="2015-08-10T09:39:33.647" UserId="198" Text="|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="480" PostHistoryTypeId="5" PostId="165" RevisionGUID="ef95b233-3ad0-427f-ad6e-5ebd2932d31f" CreationDate="2015-08-10T09:54:10.433" UserId="198" Comment="added 55 characters in body" Text="I recently had an [issue with sub-pixel anti-aliasing of text](http://superuser.com/q/930036/264276), which produces very harsh colours and made me wonder how it is meant to be done properly:&#xD;&#xA;&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've drawn some cases of a black tile covering thirds of pixels below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The colours match the ones I'm seeing, however when I look at properly antialiased text, the result is not nearly as bright and distracting:&#xD;&#xA;&#xD;&#xA;&gt; ![from www.lagom.nl](https://i.stack.imgur.com/4Vrfz.png)&#xD;&#xA;&#xD;&#xA;I assume there has to be a balance between a good light intensity and the right colour. What methods are used for sub-pixel anti-aliasing that give such good results?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SQWSI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CE16y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="481" PostHistoryTypeId="2" PostId="166" RevisionGUID="4d0bbfeb-a91a-4f1a-bcbd-e2b7102532df" CreationDate="2015-08-10T10:05:56.743" UserId="141" Text="How to quickly draw a curved shape?&#xD;&#xA;&#xD;&#xA;- by &quot;quickly&quot; I presume one should use hardware facilities as much as possible&#xD;&#xA;&#xD;&#xA;- by &quot;curved&quot; I mean boundaries defined by either quadratic or cubic Bezier curves&#xD;&#xA;&#xD;&#xA;- by &quot;shape&quot; I mean either a &quot;fat&quot; stroke (i.e. more than 1px wide) or even-odd/non-zero filled &quot;2D curved polygon&quot;, possibly with holes (i.e. letter &quot;O&quot;)&#xD;&#xA;&#xD;&#xA;I'm asking because the options I know of have several drawbacks:&#xD;&#xA;&#xD;&#xA;- triangulating the shape and sending it to OpenGL - does the most difficult work on CPU and might use too many/few triangles (i.e. wasteful/coarse)&#xD;&#xA;&#xD;&#xA;- texture atlas - has to recompute/upload the texture on every change (shape, scale, rotation, ...)&#xD;&#xA;&#xD;&#xA;- Signed distance field - on large scales the details don't look pretty or has to recompute/upload the texture&#xD;&#xA;&#xD;&#xA;- NV_path_rendering - could be it, if it was not working only on Nvidia's cards&#xD;&#xA;&#xD;&#xA;- OpenVG - could be it, if it was not working only on mobile&#xD;&#xA;&#xD;&#xA;- ?&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;\* It seems to me that OpenVG is not exactly moving forward, to put it mildly. Does anyone know anything about its future prospects? Is it worth at all to keep an eye on in the present day?&#xD;&#xA;&#xD;&#xA;** OpenGL 4+ provides means of on-fly tessellation of polygons. Could it be somehow used to refine the the mesh from the &quot;triangulating&quot; option so that the shape boundary at least wont look &quot;angled&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="482" PostHistoryTypeId="1" PostId="166" RevisionGUID="4d0bbfeb-a91a-4f1a-bcbd-e2b7102532df" CreationDate="2015-08-10T10:05:56.743" UserId="141" Text="Hardware-accelerated drawing of curved shapes" ContentLicense="CC BY-SA 3.0" />
  <row Id="483" PostHistoryTypeId="3" PostId="166" RevisionGUID="4d0bbfeb-a91a-4f1a-bcbd-e2b7102532df" CreationDate="2015-08-10T10:05:56.743" UserId="141" Text="|drawing|2d|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="484" PostHistoryTypeId="2" PostId="167" RevisionGUID="af27d30e-bdb4-4845-a19d-27337b7cafb2" CreationDate="2015-08-10T10:38:50.383" UserId="141" Text="&gt; What methods are used for sub-pixel anti-aliasing that give such good results?&#xD;&#xA;&#xD;&#xA;You simply rasterize the letters as if they were 3x as wide.&#xD;&#xA;&#xD;&#xA;The results differ in the way you rasterize the curves, most notably what kind of anti-aliasing/sampling scheme does it use and whether it makes use of [font hinting](https://en.wikipedia.org/wiki/Font_hinting). For great overview see [Texts Rasterization Exposures](http://www.antigrain.com/research/font_rasterization/) by Anti-Grain Geometry (IIRC this is what Chromium/PDFium uses) or [Subpixel rendering](https://en.wikipedia.org/wiki/Subpixel_rendering) on Wikipedia.&#xD;&#xA;&#xD;&#xA;What the attached image goes, I don't believe it has anything to do with sub-pixel rendering. It could be anything: wrong [pixel geometry](https://en.wikipedia.org/wiki/Pixel_geometry), wrong gamma, wrong color space conversion, ...&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="485" PostHistoryTypeId="5" PostId="29" RevisionGUID="c33b85af-3aae-402b-87e8-108db5427121" CreationDate="2015-08-10T10:40:04.633" UserId="231" Comment="Add syntax highlighting (feel free to change to a different language)" Text="It turns out that no, while you can use bicubic Lagrange interpolation for bicubic texture sampling, it isn't the highest quality option, and probably not actually likely to be used.&#xD;&#xA;&#xD;&#xA;Cubic hermite splines are a better tool for the job.&#xD;&#xA;&#xD;&#xA;Lagrange interpolation will make a curve that passes through the data points, thus preserving C0 continuity, but hermite splines preserve the derivatives at the edges while also passing through the data points, thus preserving C1 continuity and looking much better.&#xD;&#xA;&#xD;&#xA;This question has some great info on cubic hermite splines:&#xD;&#xA;http://dsp.stackexchange.com/questions/18265/bicubic-interpolation&#xD;&#xA;&#xD;&#xA;Here is the cubic hermite version of the code I posted in the question:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 CubicHermite (vec3 A, vec3 B, vec3 C, vec3 D, float t)&#xD;&#xA;    {&#xD;&#xA;    	float t2 = t*t;&#xD;&#xA;        float t3 = t*t*t;&#xD;&#xA;        vec3 a = -A/2.0 + (3.0*B)/2.0 - (3.0*C)/2.0 + D/2.0;&#xD;&#xA;        vec3 b = A - (5.0*B)/2.0 + 2.0*C - D / 2.0;&#xD;&#xA;        vec3 c = -A/2.0 + C/2.0;&#xD;&#xA;       	vec3 d = B;&#xD;&#xA;        &#xD;&#xA;        return a*t3 + b*t2 + c*t + d;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 BicubicHermiteTextureSample (vec2 P)&#xD;&#xA;    {&#xD;&#xA;        vec2 pixel = P * c_textureSize + 0.5;&#xD;&#xA;        &#xD;&#xA;        vec2 frac = fract(pixel);&#xD;&#xA;        pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);&#xD;&#xA;        &#xD;&#xA;        vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;&#xD;&#xA;        &#xD;&#xA;        vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;&#xD;&#xA;        vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;&#xD;&#xA;        vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 CP0X = CubicHermite(C00, C10, C20, C30, frac.x);&#xD;&#xA;        vec3 CP1X = CubicHermite(C01, C11, C21, C31, frac.x);&#xD;&#xA;        vec3 CP2X = CubicHermite(C02, C12, C22, C32, frac.x);&#xD;&#xA;        vec3 CP3X = CubicHermite(C03, C13, C23, C33, frac.x);&#xD;&#xA;        &#xD;&#xA;        return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a picture showing the difference between sampling methods.  From left to right: Nearest Neighbor, Bilinear, Lagrange Bicubic, Hermite Bicubic&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/h0Ot0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="486" PostHistoryTypeId="2" PostId="168" RevisionGUID="b788eb20-3202-488b-a1ff-4b0efdf75a76" CreationDate="2015-08-10T12:07:14.027" UserId="310" Text="Assuming you mean a camera that rotates based on mouse movement:&#xA;&#xA;One way to implement it is to keep track of the camera position and its rotation in space. Spherical coordinates happen to be convenient for this, since you can represent the angles directly.&#xA;&#xA;    float m_theta;&#xA;    float m_phi;&#xA;    float m_radius;&#xA;    float m_up;&#xA;    &#xA;    float3 m_target;&#xA;&#xA;So, when the user moves the mouse, use the native OS API to find out how many pixels the mouse moved. The change in X pixels coresponds to one rotation angle, and the change in Y to the other. &#xA;&#xA;&#xA;    void MouseDown(WPARAM buttonState, int x, int y) {&#xA;    	m_mouseLastPos.x = x;&#xA;    	m_mouseLastPos.y = y;&#xA;    &#xA;    	SetCapture(m_hwnd);&#xA;    }&#xA;    &#xA;    void MouseUp(WPARAM buttonState, int x, int y) {&#xA;    	ReleaseCapture();&#xA;    }&#xA;    &#xA;    void MouseMove(WPARAM buttonState, int x, int y) {&#xA;    	if ((buttonState &amp; MK_LBUTTON) != 0) {&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xA;    			// Calculate the new phi and theta based on mouse position relative to where the user clicked&#xA;    			float dPhi = ((float)(m_mouseLastPos.y - y) / 300);&#xA;    			float dTheta = ((float)(m_mouseLastPos.x - x) / 300);&#xA;    &#xA;    			m_camera.Rotate(-dTheta, dPhi);&#xA;    		}&#xA;    	} else if ((buttonState &amp; MK_MBUTTON) != 0) {&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xA;    			float dx = ((float)(m_mouseLastPos.x - x));&#xA;    			float dy = ((float)(m_mouseLastPos.y - y));&#xA;    &#xA;    			m_camera.Pan(-dx * m_cameraPanFactor, dy * m_cameraPanFactor);&#xA;    		}&#xA;    	}&#xA;    &#xA;    	m_mouseLastPos.x = x;&#xA;    	m_mouseLastPos.y = y;&#xA;    }&#xA;    &#xA;    void MouseWheel(int zDelta) {&#xA;    	// Make each wheel dedent correspond to a size based on the scene&#xA;    	m_camera.Zoom((float)zDelta * m_cameraScrollFactor);&#xA;    }&#xA;&#xA;&#xA;Where, Rotate(), Zoom(), and Pan() modify the internal variables accordingly. Rather than copy paste the code here, I'll reference the camera implementation I created for a side project: [camera.h](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.h) and [camera.cpp](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.cpp). The camera tries to imitate the Maya camera system. &#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="487" PostHistoryTypeId="2" PostId="169" RevisionGUID="22e0fbf9-68c6-4020-871b-4a790911b58b" CreationDate="2015-08-10T13:00:41.330" UserId="231" Text="Different screens can have different [pixel geometry], so that the red, green and blue components are arranged in different patterns. Using sub-pixel rendering to give a higher apparent resolution is only possible if the pixel geometry is known (what will give an improvement in clarity on one type of monitor will make things worse on another).&#xD;&#xA;&#xD;&#xA;This is particularly relevant if an application needs to run on both a desktop/laptop and a mobile screen, as different pixel geometry is quite common in mobile screens.&#xD;&#xA;&#xD;&#xA;Is there a way to determine which geometry the screen uses at runtime, without having to ask the user? I'm interested in whether this is possible in general, but ideally I'd like to know whether this is possible when using JavaScript with WebGL.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [pixel geometry]: https://en.wikipedia.org/wiki/Pixel_geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="488" PostHistoryTypeId="1" PostId="169" RevisionGUID="22e0fbf9-68c6-4020-871b-4a790911b58b" CreationDate="2015-08-10T13:00:41.330" UserId="231" Text="Can I determine the pixel geometry programmatically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="489" PostHistoryTypeId="3" PostId="169" RevisionGUID="22e0fbf9-68c6-4020-871b-4a790911b58b" CreationDate="2015-08-10T13:00:41.330" UserId="231" Text="|webgl|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="490" PostHistoryTypeId="2" PostId="170" RevisionGUID="2ec5a70b-04dd-4aa8-8d12-e60f10004fed" CreationDate="2015-08-10T13:03:23.800" UserId="333" Text="It is not a secret that according to the [official documentation][1] extensions are not available under OpenGL ES 2.0, but nevertheless, *glext.h* file present in the NDK platform-include directories, which makes me think that extensions are yet available. As I know, working with OpenGL under NDK doesn't differ from working with OpenGL on standalone. So, if I make something like JNI bridge between my java engine interface and these extensions, I could use them.&#xD;&#xA;&#xD;&#xA;So the question is: what architectural solution should I use if I want to use available OpenGL ES extensions on ES2.0 devices?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.android.com/reference/android/opengl/package-summary.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="491" PostHistoryTypeId="1" PostId="170" RevisionGUID="2ec5a70b-04dd-4aa8-8d12-e60f10004fed" CreationDate="2015-08-10T13:03:23.800" UserId="333" Text="Using extensions in Android OpenGL ES 2.0" ContentLicense="CC BY-SA 3.0" />
  <row Id="492" PostHistoryTypeId="3" PostId="170" RevisionGUID="2ec5a70b-04dd-4aa8-8d12-e60f10004fed" CreationDate="2015-08-10T13:03:23.800" UserId="333" Text="|opengl|android|" ContentLicense="CC BY-SA 3.0" />
  <row Id="493" PostHistoryTypeId="5" PostId="170" RevisionGUID="beb0f31f-c295-4a9f-b5be-b54fce4c8d3c" CreationDate="2015-08-10T13:08:42.690" UserId="231" Comment="Minor tidying" Text="It is no secret that according to the [official documentation][1] extensions are not available under OpenGL ES 2.0. Nevertheless, the *glext.h* file present in the NDK platform-include directories makes me think that extensions are indeed available. I know that working with OpenGL under NDK doesn't differ from working with standalone OpenGL. So, if I make something like a JNI bridge between my java engine interface and these extensions, I could use them.&#xD;&#xA;&#xD;&#xA;So the question is: what architectural solution should I use if I want to use available OpenGL ES extensions on ES2.0 devices?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.android.com/reference/android/opengl/package-summary.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="494" PostHistoryTypeId="2" PostId="171" RevisionGUID="f4087e09-1b25-4602-90e2-0dc318d930d4" CreationDate="2015-08-10T13:15:04.140" UserId="135" Text="I have encountered devices that advertise certain extensions via glGetString(GL_EXTENSIONS) and do not expose the entry points. I have also encountered the opposite, the extension was not in the extension strings but the entry points were there and it worked. It depends on whether the vendor has disabled any features in the driver from the GPU provider.&#xD;&#xA;&#xD;&#xA;You will need to check both the extension strings and check if the entry point is not NULL via [eglGetProcAddress][1].&#xD;&#xA;&#xD;&#xA;Apart from that, each extension should conform to the [Khronos registry of extensions][2] so you can include gl2ext.h directly from there if you wanted.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/egl/sdk/docs/man/html/eglGetProcAddress.xhtml&#xD;&#xA;  [2]: https://www.khronos.org/registry/gles/#headers2" ContentLicense="CC BY-SA 3.0" />
  <row Id="498" PostHistoryTypeId="2" PostId="173" RevisionGUID="e9b84e21-bff7-495a-a9ec-9d9e52bc21b1" CreationDate="2015-08-10T13:21:38.380" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="499" PostHistoryTypeId="2" PostId="174" RevisionGUID="67ae99c6-a93a-4651-a4b7-8a51b4ab7c18" CreationDate="2015-08-10T13:21:38.380" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="500" PostHistoryTypeId="5" PostId="163" RevisionGUID="cc87c46d-9bf3-49e0-b97b-67333ae7b052" CreationDate="2015-08-10T13:44:05.627" UserId="38" Comment="edited body" Text="### TL;DR&#xD;&#xA;&#xD;&#xA;They belong to the same family of solvers, where sphere tracing is one method of ray marching, which is the family name.&#xD;&#xA;&#xD;&#xA;###Raymarching a definition&#xD;&#xA;&#xD;&#xA;Raymarching is a technique a bit like traditional raytracing where the surface function is not easy to solve (or impossible without numeric iterative methods). In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xD;&#xA;&#xD;&#xA;This can be useful if you:&#xD;&#xA;&#xD;&#xA;* Need to render volumetrics that arenot uniform&#xD;&#xA;* Rendering implicit functions, fractals&#xD;&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xD;&#xA;* Etc&#xD;&#xA;&#xD;&#xA;![Traditional raymarching][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Traditional ray marching for surface finding&#xD;&#xA;&#xD;&#xA;Related posts:&#xD;&#xA;&#xD;&#xA;* [how-do-raymarch-shaders-work](http://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Sphere tracing &#xD;&#xA;&#xD;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xD;&#xA;&#xD;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xD;&#xA;&#xD;&#xA;    F(X,Y,Z) = 0&#xD;&#xA;&#xD;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xD;&#xA;&#xD;&#xA;![Sphere tracing has a adaptive step size][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Sphere tracing\* in action note how the step size is adaptive&#xD;&#xA;&#xD;&#xA;For more info see: &#xD;&#xA;&#xD;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bc4D5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;&#xD;&#xA;\* Perhaps in 2d it's should be called circle tracing :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="501" PostHistoryTypeId="5" PostId="165" RevisionGUID="4a272057-d4e0-479c-9627-8c3d122110f5" CreationDate="2015-08-10T14:18:09.920" UserId="198" Comment="added 921 characters in body" Text="I recently had an [issue with sub-pixel anti-aliasing of text](http://superuser.com/q/930036/264276), which produces very harsh colours and made me wonder how it is meant to be done properly:&#xD;&#xA;&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've drawn some cases of a black tile covering thirds of pixels below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The colours match the ones I'm seeing, however when I look at properly antialiased text, the result is not nearly as bright and distracting:&#xD;&#xA;&#xD;&#xA;&gt; ![from www.lagom.nl](https://i.stack.imgur.com/4Vrfz.png)&#xD;&#xA;&#xD;&#xA;I assume there has to be a balance between a good light intensity and the right colour. What methods are used for sub-pixel anti-aliasing that give such good results?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;*Update:*&#xD;&#xA;&#xD;&#xA;I've rendered a white teapot to an image with 3x width and with multisampling. Below I compare averaging every 3 pixels with assigning each to RGB. The colours still seem overly bright in some cases (especially compared to the example above from [here](http://www.lagom.nl/lcd-test/subpixel.php)), not that my phone captures them well.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5][![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7][![enter image description here][8]][8]&#xD;&#xA;&lt;sup&gt;OK, so my monitor needs a little dusting&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SQWSI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CE16y.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/19ABb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/RE5Jv.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/BZxjL.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/WT6ci.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/qveN5m.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/wPGG7m.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="502" PostHistoryTypeId="2" PostId="175" RevisionGUID="351fabc9-2091-4827-a00f-8ad27021d695" CreationDate="2015-08-10T14:38:40.183" UserId="157" Text="How do [ICC profiles][1] really work? If I were to analyze or change the existing one(s) embedded in an image, how should I proceed?&#xD;&#xA;&#xD;&#xA;I'd also be glad to understand how an &quot;end-user&quot; is able to create these with a [tristimulus colorimeter][2] or a [spectrophotometer][3] and if/how this new profile can be added to a color capturing device (i.e. a camera).&#xD;&#xA;&#xD;&#xA;My curiosity comes from images that were taken by a professional photographer. When I open them in GIMP, there's a pop-up referring &quot;there is an embedded ICC profile&quot; and if I &quot;would like to convert the image to RGB (sRGB built-in)&quot;. I always convert all of them before using them, since the colors are slightly improved.&#xD;&#xA;&#xD;&#xA;This is the image as it was provided by the photographer:&#xD;&#xA;[![No ICC][4]][4]&#xD;&#xA;&#xD;&#xA;And this is after the embedded ICC profile was applied:&#xD;&#xA;[![With ICC][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/ICC_profile&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Tristimulus_colorimeter&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Spectrophotometer&#xD;&#xA;  [4]: https://i.stack.imgur.com/Y4TQL.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/M1Dt0.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="503" PostHistoryTypeId="1" PostId="175" RevisionGUID="351fabc9-2091-4827-a00f-8ad27021d695" CreationDate="2015-08-10T14:38:40.183" UserId="157" Text="How is an ICC profile embedded or built into an image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="504" PostHistoryTypeId="3" PostId="175" RevisionGUID="351fabc9-2091-4827-a00f-8ad27021d695" CreationDate="2015-08-10T14:38:40.183" UserId="157" Text="|color|color-management|" ContentLicense="CC BY-SA 3.0" />
  <row Id="505" PostHistoryTypeId="5" PostId="175" RevisionGUID="717293d5-cdc4-4104-af61-78a21a4aa528" CreationDate="2015-08-10T14:46:49.100" UserId="157" Comment="minor rephrasing" Text="If I were to analyze or change an [ICC profile][1] embedded in an image, how should I proceed?&#xD;&#xA;&#xD;&#xA;I'd also be glad to understand how an &quot;end-user&quot; is able to create these with a [tristimulus colorimeter][2] or a [spectrophotometer][3] and if/how this new profile can be added to a color capturing device (i.e. a camera).&#xD;&#xA;&#xD;&#xA;My curiosity comes from images that were taken by a professional photographer. When I open them in GIMP, there's a pop-up referring &quot;there is an embedded ICC profile&quot; and if I &quot;would like to convert the image to RGB (sRGB built-in)&quot;. I always convert all of them before using them, since the colors are slightly improved.&#xD;&#xA;&#xD;&#xA;This is the image as it was provided by the photographer:&#xD;&#xA;[![No ICC][4]][4]&#xD;&#xA;&#xD;&#xA;And this is after the embedded ICC profile was applied:&#xD;&#xA;[![With ICC][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/ICC_profile&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Tristimulus_colorimeter&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Spectrophotometer&#xD;&#xA;  [4]: https://i.stack.imgur.com/Y4TQL.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/M1Dt0.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="506" PostHistoryTypeId="5" PostId="118" RevisionGUID="6dae6feb-bc36-4aad-91f8-84aca1379deb" CreationDate="2015-08-10T16:17:29.513" UserId="327" Comment="Expounded on how to deal with basis of differing dimensions." Text="The mathematical approach to this is to represent the other colors/light sources in terms of your standard primaries in the color space. Represent your target color and available light sources as vectors with, say, the RGB color space as the basis. Figuring out how to display your target color using your available sources then becomes a [change of basis][1], a standard linear algebra operation, where the target basis consists of your LEDs/nonstandard primaries.&#xD;&#xA;&#xD;&#xA;If the dimensions of the source and destination bases are different, the change of basis matrix won't be square and thus won't be invertible. In that case, you need to solve a system of linear equations, expressed in matrix form:&#xD;&#xA;&#xD;&#xA;    c_RGB = [r y b v] x c_RYBV&#xD;&#xA;&#xD;&#xA;Where `c_RGB` and `c_RYBV` are the coordinate vectors of your desired color expressed in terms of RGB and custom primaries, respectively, and `r`, `y`, `b` and `v` are your custom primaries (basis vectors) in RGB coordinates.&#xD;&#xA;&#xD;&#xA;Solving this system is another common linear algebra operation, and there are a variety of numerical and symbolical algorithms to do so. The system is over-constrained, so solutions will likely have a free variable, however since we can't physically produce negative light, nor do the primaries have infinite dynamic range, for most practical purposes each coefficient will have to be limited to be within the `[0, 1]` range. This will render many colors unrepresentable under certain sets of primaries.&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/a/340991/166490" ContentLicense="CC BY-SA 3.0" />
  <row Id="507" PostHistoryTypeId="5" PostId="168" RevisionGUID="337fad8e-48c7-466a-a936-853947a9a71a" CreationDate="2015-08-10T16:18:46.230" UserId="310" Comment="Heavily upgraded the response to improve the explanation rather than just linking code" Text="Assuming you mean a camera that rotates based on mouse movement:&#xD;&#xA;&#xD;&#xA;One way to implement it is to keep track of the camera position and its rotation in space. Spherical coordinates happen to be convenient for this, since you can represent the angles directly.&#xD;&#xA;&#xD;&#xA;[![Spherical Coordinates Image][1]][1]&#xD;&#xA;&#xD;&#xA;    float m_theta;&#xD;&#xA;    float m_phi;&#xD;&#xA;    float m_radius;&#xD;&#xA;    &#xD;&#xA;    float3 m_target;&#xD;&#xA;&#xD;&#xA;The camera is located at some position defined by m_theta, m_phi, and m_radius. We're can rotate and move freely wherever we want by changing those three values. However, we always look at, and rotate around, m_target.&#xD;&#xA;&#xD;&#xA;There are three main camera functions:&#xD;&#xA;&#xD;&#xA;    void Rotate(float dTheta, float dPhi);&#xD;&#xA;    void Zoom(float distance);&#xD;&#xA;    void Pan(float dx, float dy);&#xD;&#xA;&#xD;&#xA;In their simplest forms, Rotate() and Zoom() are trivial. The just modify m_theta, m_phi, and m_radius respectively:&#xD;&#xA;&#xD;&#xA;    void Camera::Rotate(float dTheta, float dPhi) {&#xD;&#xA;    	m_theta += dTheta;&#xD;&#xA;    	m_phi += dPhi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Camera::Zoom(float distance) {&#xD;&#xA;    	m_radius -= distance;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Panning is a bit more complicated. A camera pan is defined as moving the camera to the left/right and/or up/down respective to the current camera view. The easiest way we can accomplish this is to convert our current camera view from spherical coordinates to cartesian coordinates. This will give us an *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;    void Camera::Pan(float dx, float dy) {&#xD;&#xA;    	float3 look = normalize(ToCartesian());&#xD;&#xA;    	float3 worldUp = float3(0.0f, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	float3 right = cross(look, worldUp);&#xD;&#xA;    	float3 up = cross(look, right);&#xD;&#xA;    &#xD;&#xA;    	m_target = m_target + (right * dx) + (up * dy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    inline float3 ToCartesian() {&#xD;&#xA;    	float x = m_radius * sinf(m_phi) * sinf(m_theta);&#xD;&#xA;    	float y = m_radius * cosf(m_phi);&#xD;&#xA;    	float z = m_radius * sinf(m_phi) * cosf(m_theta);&#xD;&#xA;    	float w = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return float3(x, y, z, w);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So, first, we convert our spherical coordinate system to cartesian to get our *look* vector. Next, we do the vector cross product with the world *up* vector, in order to get a *right* vector. This is a vector that points directly right of the camera view. Lastly, we do another vector cross product to get the camera *up* vector.&#xD;&#xA;&#xD;&#xA;To finish the pan, we move m_target along the *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;One question you might be asking is: Why convert between cartesian and spherical all the time (you will also have to convert in order to create the View matrix). &#xD;&#xA;&#xD;&#xA;Good question. I too had this question and tried to exclusively use cartesian. You end up with problems with rotations. Since floating point operations are not exactly precise, multiple rotations end up accumulating errors, which corresponded to the camera slowly, and unintentionally rolling. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So, in the end, I stuck with spherical coordinates. In order to counter the extra calculations, I ended up caching the view matrix, and only calculate it when the camera moves.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code I have above is a simplified pseudo-code version of the camera system I made for a side project: [camera.h](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.h) and [camera.cpp](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.cpp). The camera tries to imitate the Maya camera system. The code is free and open source, so feel free to use it in your own project. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9kXOr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1OFpX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="508" PostHistoryTypeId="5" PostId="168" RevisionGUID="bc0c2626-6b1e-4150-8f53-a8780d9a5e63" CreationDate="2015-08-10T16:25:06.497" UserId="310" Comment="Heavily upgraded the response to improve the explanation rather than just linking code" Text="Assuming you mean a camera that rotates based on mouse movement:&#xD;&#xA;&#xD;&#xA;One way to implement it is to keep track of the camera position and its rotation in space. Spherical coordinates happen to be convenient for this, since you can represent the angles directly.&#xD;&#xA;&#xD;&#xA;[![Spherical Coordinates Image][1]][1]&#xD;&#xA;&#xD;&#xA;    float m_theta;&#xD;&#xA;    float m_phi;&#xD;&#xA;    float m_radius;&#xD;&#xA;    &#xD;&#xA;    float3 m_target;&#xD;&#xA;&#xD;&#xA;The camera is located *P* defined by m_theta, m_phi, and m_radius. We're can rotate and move freely wherever we want by changing those three values. However, we always look at, and rotate around, m_target. m_target is the local origin of the sphere. However, we are free to move this origin wherever we want in world space.&#xD;&#xA;&#xD;&#xA;There are three main camera functions:&#xD;&#xA;&#xD;&#xA;    void Rotate(float dTheta, float dPhi);&#xD;&#xA;    void Zoom(float distance);&#xD;&#xA;    void Pan(float dx, float dy);&#xD;&#xA;&#xD;&#xA;In their simplest forms, Rotate() and Zoom() are trivial. The just modify m_theta, m_phi, and m_radius respectively:&#xD;&#xA;&#xD;&#xA;    void Camera::Rotate(float dTheta, float dPhi) {&#xD;&#xA;    	m_theta += dTheta;&#xD;&#xA;    	m_phi += dPhi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Camera::Zoom(float distance) {&#xD;&#xA;    	m_radius -= distance;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Panning is a bit more complicated. A camera pan is defined as moving the camera to the left/right and/or up/down respective to the current camera view. The easiest way we can accomplish this is to convert our current camera view from spherical coordinates to cartesian coordinates. This will give us an *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;    void Camera::Pan(float dx, float dy) {&#xD;&#xA;    	float3 look = normalize(ToCartesian());&#xD;&#xA;    	float3 worldUp = float3(0.0f, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	float3 right = cross(look, worldUp);&#xD;&#xA;    	float3 up = cross(look, right);&#xD;&#xA;    &#xD;&#xA;    	m_target = m_target + (right * dx) + (up * dy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    inline float3 ToCartesian() {&#xD;&#xA;    	float x = m_radius * sinf(m_phi) * sinf(m_theta);&#xD;&#xA;    	float y = m_radius * cosf(m_phi);&#xD;&#xA;    	float z = m_radius * sinf(m_phi) * cosf(m_theta);&#xD;&#xA;    	float w = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return float3(x, y, z, w);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So, first, we convert our spherical coordinate system to cartesian to get our *look* vector. Next, we do the vector cross product with the world *up* vector, in order to get a *right* vector. This is a vector that points directly right of the camera view. Lastly, we do another vector cross product to get the camera *up* vector.&#xD;&#xA;&#xD;&#xA;To finish the pan, we move m_target along the *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;One question you might be asking is: Why convert between cartesian and spherical all the time (you will also have to convert in order to create the View matrix). &#xD;&#xA;&#xD;&#xA;Good question. I too had this question and tried to exclusively use cartesian. You end up with problems with rotations. Since floating point operations are not exactly precise, multiple rotations end up accumulating errors, which corresponded to the camera slowly, and unintentionally rolling. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So, in the end, I stuck with spherical coordinates. In order to counter the extra calculations, I ended up caching the view matrix, and only calculate it when the camera moves.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last step is to *use* this Camera class. Just call the appropriate member function inside your app's MouseDown/Up/Scroll functions:&#xD;&#xA;&#xD;&#xA;    void MouseDown(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	m_mouseLastPos.x = x;&#xD;&#xA;    	m_mouseLastPos.y = y;&#xD;&#xA;    &#xD;&#xA;    	SetCapture(m_hwnd);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseUp(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	ReleaseCapture();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseMove(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	if ((buttonState &amp; MK_LBUTTON) != 0) {&#xD;&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xD;&#xA;    			// Calculate the new phi and theta based on mouse position relative to where the user clicked&#xD;&#xA;    			float dPhi = ((float)(m_mouseLastPos.y - y) / 300);&#xD;&#xA;    			float dTheta = ((float)(m_mouseLastPos.x - x) / 300);&#xD;&#xA;    &#xD;&#xA;    			m_camera.Rotate(-dTheta, dPhi);&#xD;&#xA;    		}&#xD;&#xA;    	} else if ((buttonState &amp; MK_MBUTTON) != 0) {&#xD;&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xD;&#xA;    			float dx = ((float)(m_mouseLastPos.x - x));&#xD;&#xA;    			float dy = ((float)(m_mouseLastPos.y - y));&#xD;&#xA;    &#xD;&#xA;    			m_camera.Pan(-dx * m_cameraPanFactor, dy * m_cameraPanFactor);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	m_mouseLastPos.x = x;&#xD;&#xA;    	m_mouseLastPos.y = y;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseWheel(int zDelta) {&#xD;&#xA;    	// Make each wheel dedent correspond to a size based on the scene&#xD;&#xA;    	m_camera.Zoom((float)zDelta * m_cameraScrollFactor);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The m_camera*Factor variables are just scale factors that change how quickly your camera rotates/pans/scrolls&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code I have above is a simplified pseudo-code version of the camera system I made for a side project: [camera.h](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.h) and [camera.cpp](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.cpp). The camera tries to imitate the Maya camera system. The code is free and open source, so feel free to use it in your own project. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9kXOr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1OFpX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="509" PostHistoryTypeId="5" PostId="168" RevisionGUID="89247764-1320-409f-b8a3-7d9be21f4a93" CreationDate="2015-08-10T16:30:22.603" UserId="310" Comment="Heavily upgraded the response to improve the explanation rather than just linking code" Text="Assuming you mean a camera that rotates based on mouse movement:&#xD;&#xA;&#xD;&#xA;One way to implement it is to keep track of the camera position and its rotation in space. Spherical coordinates happen to be convenient for this, since you can represent the angles directly.&#xD;&#xA;&#xD;&#xA;[![Spherical Coordinates Image][1]][1]&#xD;&#xA;&#xD;&#xA;    float m_theta;&#xD;&#xA;    float m_phi;&#xD;&#xA;    float m_radius;&#xD;&#xA;    &#xD;&#xA;    float3 m_target;&#xD;&#xA;&#xD;&#xA;The camera is located at *P* which is defined by m_theta, m_phi, and m_radius. We're can rotate and move freely wherever we want by changing those three values. However, we always look at, and rotate around, m_target. m_target is the local origin of the sphere. However, we are free to move this origin wherever we want in world space. &#xD;&#xA;&#xD;&#xA;There are three main camera functions:&#xD;&#xA;&#xD;&#xA;    void Rotate(float dTheta, float dPhi);&#xD;&#xA;    void Zoom(float distance);&#xD;&#xA;    void Pan(float dx, float dy);&#xD;&#xA;&#xD;&#xA;In their simplest forms, Rotate() and Zoom() are trivial. The just modify m_theta, m_phi, and m_radius respectively:&#xD;&#xA;&#xD;&#xA;    void Camera::Rotate(float dTheta, float dPhi) {&#xD;&#xA;    	m_theta += dTheta;&#xD;&#xA;    	m_phi += dPhi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Camera::Zoom(float distance) {&#xD;&#xA;    	m_radius -= distance;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Panning is a bit more complicated. A camera pan is defined as moving the camera to the left/right and/or up/down respective to the current camera view. The easiest way we can accomplish this is to convert our current camera view from spherical coordinates to cartesian coordinates. This will give us an *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;    void Camera::Pan(float dx, float dy) {&#xD;&#xA;    	float3 look = normalize(ToCartesian());&#xD;&#xA;    	float3 worldUp = float3(0.0f, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	float3 right = cross(look, worldUp);&#xD;&#xA;    	float3 up = cross(look, right);&#xD;&#xA;    &#xD;&#xA;    	m_target = m_target + (right * dx) + (up * dy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    inline float3 ToCartesian() {&#xD;&#xA;    	float x = m_radius * sinf(m_phi) * sinf(m_theta);&#xD;&#xA;    	float y = m_radius * cosf(m_phi);&#xD;&#xA;    	float z = m_radius * sinf(m_phi) * cosf(m_theta);&#xD;&#xA;    	float w = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return float3(x, y, z, w);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So, first, we convert our spherical coordinate system to cartesian to get our *look* vector. Next, we do the vector cross product with the world *up* vector, in order to get a *right* vector. This is a vector that points directly right of the camera view. Lastly, we do another vector cross product to get the camera *up* vector.&#xD;&#xA;&#xD;&#xA;To finish the pan, we move m_target along the *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;One question you might be asking is: Why convert between cartesian and spherical all the time (you will also have to convert in order to create the View matrix). &#xD;&#xA;&#xD;&#xA;Good question. I too had this question and tried to exclusively use cartesian. You end up with problems with rotations. Since floating point operations are not exactly precise, multiple rotations end up accumulating errors, which corresponded to the camera slowly, and unintentionally rolling. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So, in the end, I stuck with spherical coordinates. In order to counter the extra calculations, I ended up caching the view matrix, and only calculate it when the camera moves.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last step is to *use* this Camera class. Just call the appropriate member function inside your app's MouseDown/Up/Scroll functions:&#xD;&#xA;&#xD;&#xA;    void MouseDown(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	m_mouseLastPos.x = x;&#xD;&#xA;    	m_mouseLastPos.y = y;&#xD;&#xA;    &#xD;&#xA;    	SetCapture(m_hwnd);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseUp(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	ReleaseCapture();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseMove(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	if ((buttonState &amp; MK_LBUTTON) != 0) {&#xD;&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xD;&#xA;    			// Calculate the new phi and theta based on mouse position relative to where the user clicked&#xD;&#xA;    			float dPhi = ((float)(m_mouseLastPos.y - y) / 300);&#xD;&#xA;    			float dTheta = ((float)(m_mouseLastPos.x - x) / 300);&#xD;&#xA;    &#xD;&#xA;    			m_camera.Rotate(-dTheta, dPhi);&#xD;&#xA;    		}&#xD;&#xA;    	} else if ((buttonState &amp; MK_MBUTTON) != 0) {&#xD;&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xD;&#xA;    			float dx = ((float)(m_mouseLastPos.x - x));&#xD;&#xA;    			float dy = ((float)(m_mouseLastPos.y - y));&#xD;&#xA;    &#xD;&#xA;    			m_camera.Pan(-dx * m_cameraPanFactor, dy * m_cameraPanFactor);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	m_mouseLastPos.x = x;&#xD;&#xA;    	m_mouseLastPos.y = y;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseWheel(int zDelta) {&#xD;&#xA;    	// Make each wheel dedent correspond to a size based on the scene&#xD;&#xA;    	m_camera.Zoom((float)zDelta * m_cameraScrollFactor);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The m_camera*Factor variables are just scale factors that change how quickly your camera rotates/pans/scrolls&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code I have above is a simplified pseudo-code version of the camera system I made for a side project: [camera.h](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.h) and [camera.cpp](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.cpp). The camera tries to imitate the Maya camera system. The code is free and open source, so feel free to use it in your own project. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9kXOr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1OFpX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="510" PostHistoryTypeId="2" PostId="176" RevisionGUID="3f37d4af-5b90-4a7d-a9b9-2d904cd59c11" CreationDate="2015-08-10T17:43:35.103" UserId="127" Text="While rendering my scene with OpenGL, I sometimes add an overlay which contains information, settings and a few draggable items. Currently, the overlay has a slightly transparent background to make text easily readable while still allowing the scene to shine through and to let the user see the scene behind/through the overlay.&#xD;&#xA;&#xD;&#xA;I would like to replace the transparent background with a translucent background, which (as far as I know) requires the clear image of the scene to be heavily blurred*. And especially on mobile devices (e.g. iPad) with high resolutions and limited processing power, lots of texture lookups and real-time rendering don't work well together.&#xD;&#xA;&#xD;&#xA;Is there a way to make real-time translucency feasible on mobile devices like the iPad? Or is there a way to avoid the need to heavily blur the scene in every frame?&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;*I know there is the two-pass blur (first blur in one and then in the other direction) to reduce texture lookups. But for translucency this still requires quite a large number of texture lookups.&lt;/sup&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="511" PostHistoryTypeId="1" PostId="176" RevisionGUID="3f37d4af-5b90-4a7d-a9b9-2d904cd59c11" CreationDate="2015-08-10T17:43:35.103" UserId="127" Text="Real-time translucency effect" ContentLicense="CC BY-SA 3.0" />
  <row Id="512" PostHistoryTypeId="3" PostId="176" RevisionGUID="3f37d4af-5b90-4a7d-a9b9-2d904cd59c11" CreationDate="2015-08-10T17:43:35.103" UserId="127" Text="|opengl|real-time|mobile|" ContentLicense="CC BY-SA 3.0" />
  <row Id="513" PostHistoryTypeId="5" PostId="109" RevisionGUID="6f1891e5-aef9-4de5-a659-19b1b5aeafce" CreationDate="2015-08-10T19:16:27.473" UserId="311" Comment="edited: two -&gt; some" Text="There's a bunch of a approaches, but none is perfect.&#xD;&#xA;&#xD;&#xA;It's possible to share code by using `glAttachShader` to combine shaders, but this doesn't make it possible to share things like struct declarations or `#define`-d constants. It does work for sharing functions.&#xD;&#xA;&#xD;&#xA;Some people like to use the array of strings passed to `glShaderSource` as a way to prepend common definitions before your code, but this has some disadvantages:&#xD;&#xA;&#xD;&#xA;1. It's harder to control what needs to be included from within the shader (you need a separate system for this.)&#xD;&#xA;2. It means the shader author cannot specify the GLSL `#version`, due to the following statement in the GLSL spec:&#xD;&#xA;&#xD;&#xA;&gt;  The **#version** directive must occur in a shader before anything else, except for comments and white space.&#xD;&#xA;&#xD;&#xA;Due to this statement, `glShaderSource` cannot be used to prepend text before the `#version` declarations. This means that the `#version` line needs to be included in your `glShaderSource` arguments, which means that your GLSL compiler interface needs to somehow be told what version of GLSL is expected to be used. Additionally, not specifying a `#version` will make the GLSL compiler default to using GLSL version 1.10. If you want to let shader authors specify the `#version` within the script in a standard way, then you need to somehow insert `#include`-s after the `#version` statement. This could be done by explicitly parsing the GLSL shader to find the `#version` string (if present) and make your inclusions after it, but having access to an `#include` directive might be preferable to control more easily when those inclusions need to be made. On the other hand, since GLSL ignores comments before the `#version` line, you could add metadata for includes within comments at the top of your file (yuck.)&#xD;&#xA;&#xD;&#xA;The question now is: Is there a standard solution for `#include`, or do you need to roll your own preprocessor extension?&#xD;&#xA;&#xD;&#xA;There is the `GL_ARB_shading_language_include` extension, but it has some drawbacks:&#xD;&#xA;&#xD;&#xA;1. It is only supported by NVIDIA (http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include)&#xD;&#xA;2. It works by specifying the include strings ahead of time. Therefore, before compiling, you need to specify that the string `&quot;/buffers.glsl&quot;` (as used in `#include &quot;/buffers.glsl&quot;`) corresponds to the contents of the file `buffer.glsl` (which you have loaded previously).&#xD;&#xA;3. As you may have noticed in point (2), your paths need to start with `&quot;/&quot;`, like Linux-style absolute paths. This notation is generally unfamiliar to C programmers, and means you can't specify relative paths.&#xD;&#xA;&#xD;&#xA;A common design is to implement your own `#include` mechanism, but this can be tricky since you also need to parse (and evaluate) other preprocessor instructions like `#if` in order to properly handle conditional compilation (like header guards.)&#xD;&#xA;&#xD;&#xA;If you implement your own `#include`, you also have some liberties in how you want to implement it:&#xD;&#xA;&#xD;&#xA;* You could pass strings ahead of time (like `GL_ARB_shading_language_include`).&#xD;&#xA;* You could specify an include callback (this is done by DirectX's D3DCompiler library.)&#xD;&#xA;* You could implement a system that always reads directly from the filesystem, as done in typical C applications.&#xD;&#xA;&#xD;&#xA;As a simplification, you can automatically insert header guards for each include in your preprocessing layer, so your processor layer looks like:&#xD;&#xA;&#xD;&#xA;    if (#include and not_included_yet) include_file();&#xD;&#xA;&#xD;&#xA;(Credit to Trent Reed for showing me the above technique.)&#xD;&#xA;&#xD;&#xA;**In conclusion**, there exists no automatic, standard, and simple solution. In a future solution, you could use some SPIR-V OpenGL interface, in which case the GLSL to SPIR-V compiler could be outside of the GL API. Having the compiler outside the OpenGL runtime greatly simplifies implementing things like `#include` since it's a more appropriate place to interface with the filesystem. I believe the current widespread method is to just implement a custom preprocessor that works in a way any C programmer should be familiar with." ContentLicense="CC BY-SA 3.0" />
  <row Id="514" PostHistoryTypeId="2" PostId="177" RevisionGUID="ea70a99d-2b6b-48e2-b3c0-7fca4c96333b" CreationDate="2015-08-10T19:59:58.817" UserId="231" Text="I can model ice cubes as slightly misshapen transparent cubes with the refractive index of water, but they don't look convincing. They look like lumps of glass rather than ice.&#xD;&#xA;&#xD;&#xA;Looking at real ice cubes I can intuitively describe some differences but I don't know what physical properties to change to match them:&#xD;&#xA;&#xD;&#xA;- Ice cubes are wet. Mine look like dry glass.&#xD;&#xA;- Ice cubes are transparent in places and not in others.&#xD;&#xA;- Ice cubes often have cracks that are visible despite not separating.&#xD;&#xA;&#xD;&#xA;In this instance I am trying to model ice cubes on a surface (in air, not floating in water).&#xD;&#xA;&#xD;&#xA;What techniques do I need to include in order to increase the realism?" ContentLicense="CC BY-SA 3.0" />
  <row Id="515" PostHistoryTypeId="1" PostId="177" RevisionGUID="ea70a99d-2b6b-48e2-b3c0-7fca4c96333b" CreationDate="2015-08-10T19:59:58.817" UserId="231" Text="How can I make my ice cubes look real?" ContentLicense="CC BY-SA 3.0" />
  <row Id="516" PostHistoryTypeId="3" PostId="177" RevisionGUID="ea70a99d-2b6b-48e2-b3c0-7fca4c96333b" CreationDate="2015-08-10T19:59:58.817" UserId="231" Text="|refraction|transparency|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="517" PostHistoryTypeId="2" PostId="178" RevisionGUID="b1153261-3e89-4d82-a045-609a4881277d" CreationDate="2015-08-10T20:16:23.327" UserId="158" Text="&#xD;&#xA;Two big ones you're missing:&#xD;&#xA;&#xD;&#xA;1. [Angle-dependent reflection][1].  This is one possible cause of your &quot;transparent in places and not in others&quot; effect, and the most likely cause of the missing wetness.&#xD;&#xA;&#xD;&#xA;2. Ice cubes usually have air bubbles trapped inside.  This shows up as a white volumetric haze denser in the center of the cube (for small bubbles) or distinct bubbles (for large ones).  This is the other likely cause of your &quot;transparent in places and not in others&quot;.&#xD;&#xA;&#xD;&#xA;The techniques for modeling these depend on what rendering method you're using.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Fresnel_equations" ContentLicense="CC BY-SA 3.0" />
  <row Id="518" PostHistoryTypeId="2" PostId="179" RevisionGUID="a42f4a0a-678e-4a3f-84cc-ff935a8d35a7" CreationDate="2015-08-10T20:17:10.753" UserId="327" Text="According to [Wikipedia][1], ice has a slightly lower IOR than non-frozen water, though I don't know how much that difference would affect the results.&#xD;&#xA;&#xD;&#xA;The &quot;opaque&quot;-looking parts of an ice cube are caused by clusters of microscopic bubbles formed during freezing. You might be able to model those using geometry, but given the scale and number I suspect that some kind of participating media model would probably be a better fit. (Though I don't know of any.)&#xD;&#xA;&#xD;&#xA;Also, remember that most non-submerged ice you'll see is going to very soon form a thin layer of liquid water interfacing it with the air, so this might significantly alter its appearance too.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/List_of_refractive_indices" ContentLicense="CC BY-SA 3.0" />
  <row Id="519" PostHistoryTypeId="2" PostId="180" RevisionGUID="7b564f19-03c6-422f-b6c6-ef6e6ff6fb07" CreationDate="2015-08-10T20:30:20.923" UserId="327" Text="There's no way around it. If you want the area behind the textboxes to appear blurry... you're gonna have to blur it.&#xD;&#xA;&#xD;&#xA;One way to mitigate the performance cost is to be sure to use a 2-pass separable blur.&#xD;&#xA;&#xD;&#xA;Another measure that will probably help (depending on how much of the screen your textboxes cover) is to use scissoring or a stencil test to only compute the blur in the areas of the screen that will later be covered by textboxes. If you do this, be sure to leave an extra vertical padding of at least half the width of your blur kernel, otherwise, the second blurring pass will try to sample uncomputed texels in the intermediate texture, leading to artifacts or darkening of the blur near the edges of the textbox areas. (This isn't an issue for the first pass since you'll be sampling from the original unmasked texture there.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="520" PostHistoryTypeId="2" PostId="181" RevisionGUID="e4317887-9c19-40e7-aae9-c05e6a56318b" CreationDate="2015-08-10T20:40:17.313" UserDisplayName="user349" Text="I'm currently preparing to implement variance shadow mapping based on [this article](https://a248.e.akamai.net/f/1890/806/6/http.developer.nvidia.com/GPUGems3/gpugems3_ch08.html). However, one point it makes concerns me:&#xD;&#xA;&#xD;&#xA;&gt; Rendering only casters (and not receivers) into the variance shadow map is incorrect! For the interpolation to work properly, the receiving surface must be represented in the depth distribution. If it is not, shadow penumbrae will be improperly sized and fail to fade smoothly from light to dark.&#xD;&#xA;&#xD;&#xA;This means that the naive method of rendering an object that does not cast a shadow, but can recieve shadows from other objects - simply skip rendering it into the shadow map - will not work. How else can this be accomplished?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="521" PostHistoryTypeId="1" PostId="181" RevisionGUID="e4317887-9c19-40e7-aae9-c05e6a56318b" CreationDate="2015-08-10T20:40:17.313" UserDisplayName="user349" Text="How to render an object that recieves shadows but does not cast them in a variance shadow mapping system?" ContentLicense="CC BY-SA 3.0" />
  <row Id="522" PostHistoryTypeId="3" PostId="181" RevisionGUID="e4317887-9c19-40e7-aae9-c05e6a56318b" CreationDate="2015-08-10T20:40:17.313" UserDisplayName="user349" Text="|opengl|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="523" PostHistoryTypeId="5" PostId="176" RevisionGUID="d4578eac-ff77-48f8-9002-150fc9631e31" CreationDate="2015-08-10T20:41:17.287" UserId="127" Comment="Added image" Text="While rendering my scene with OpenGL, I sometimes add an overlay which contains information, settings and a few draggable items. Currently, the overlay has a slightly transparent background to make text easily readable while still allowing the scene to shine through and to let the user see the scene behind/through the overlay.&#xD;&#xA;&#xD;&#xA;I would like to replace the transparent background with a translucent background, which (as far as I know) requires the clear image of the scene to be heavily blurred*. And especially on mobile devices (e.g. iPad) with high resolutions and limited processing power, lots of texture lookups and real-time rendering don't work well together.&#xD;&#xA;&#xD;&#xA;Is there a way to make real-time translucency feasible on mobile devices like the iPad? Or is there a way to avoid the need to heavily blur the scene in every frame?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;As suggested in the comments, here is an image I just found in the Wikipedia that describes the difference between transparency (right column) and translucency (middle column). &#xD;&#xA;&#xD;&#xA;[![Opacity, translucency and transparency][1]][1]&#xD;&#xA;&#xD;&#xA;(Image source: [Wikipedia][2])&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;*I know there is the two-pass blur (first blur in one and then in the other direction) to reduce texture lookups. But for translucency this still requires quite a large number of texture lookups.&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iKXOo.png&#xD;&#xA;  [2]: https://commons.wikimedia.org/wiki/File:Opacity_Translucency_Transparency.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="528" PostHistoryTypeId="2" PostId="183" RevisionGUID="99c3a690-5623-4a12-8849-4153981f4ae9" CreationDate="2015-08-10T21:39:52.303" UserId="231" Text="I want to be able to model an opaque liquid being dropped into a transparent liquid with sufficient velocity to cause turbulence and the resulting chaotic mixing. Assuming the two liquids are of the same density and viscosity, how could I model this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="529" PostHistoryTypeId="1" PostId="183" RevisionGUID="99c3a690-5623-4a12-8849-4153981f4ae9" CreationDate="2015-08-10T21:39:52.303" UserId="231" Text="How can I model ink dropped into still water?" ContentLicense="CC BY-SA 3.0" />
  <row Id="530" PostHistoryTypeId="3" PostId="183" RevisionGUID="99c3a690-5623-4a12-8849-4153981f4ae9" CreationDate="2015-08-10T21:39:52.303" UserId="231" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="531" PostHistoryTypeId="2" PostId="184" RevisionGUID="1efdce48-6244-4515-a38c-79ca33e7dd05" CreationDate="2015-08-10T23:21:28.050" UserId="79" Text="Simulating drops of ink is probably one of the best applications of the [Vorton Method](http://doc.utwente.nl/56247/1/K227____.pdf).&#xD;&#xA;&#xD;&#xA;Unlike fluid solvers based on the velocity form of the Navier-Stokes equations, which track the density and velocity of a fluid, the Vorton Method tracks vorticity instead. It does so by simulating a large number of vortons, each carrying a small amount of vorticity; you can think of a vorton as being a tiny particle that induces a small spinning vortex around itself. The sum of velocities caused by each vortex defines a velocity field in the fluid, which is used to in turn advect the vortons themselves.&#xD;&#xA;&#xD;&#xA;Vorton methods are difficult to combine with boundary conditions and have a few efficiency caveats, but for fluid flow where intricate turbulance is the key feature and boundaries can be avoided, the Vorton method far outshines e.g. Eulerian grid solvers, which would need a large resolution to simulate turbulence at a comparable scale.&#xD;&#xA;&#xD;&#xA;Michael Gourlay has a very accessible [article series](http://www.mijagourlay.com/fluid) on the vorton method. Although his articles are targeted at video games, they hold up similarly for off-line simulation. Here's also an [example video](https://www.youtube.com/watch?v=LD6JfO41JIE) of a drop of ink simulated using the vorton method." ContentLicense="CC BY-SA 3.0" />
  <row Id="532" PostHistoryTypeId="2" PostId="185" RevisionGUID="2c4b8640-8737-4b17-8671-0e693ff0bec0" CreationDate="2015-08-10T23:43:46.900" UserId="79" Text="Most descriptions of Monte Carlo rendering methods, such as path tracing or bidirectional path tracing, assume that samples are generated independently; that is, a standard random number generator is used that generates a stream of independent, uniformly distributed numbers.&#xD;&#xA;&#xD;&#xA;We know that samples that are not chosen independently can be beneficial in terms of noise. For example, stratified sampling and low-discrepancy sequences are two examples of correlated sampling schemes that almost always improve render times.&#xD;&#xA;&#xD;&#xA;However, there are many cases where the impact of sample correlation is not as clear-cut. For example, Markov Chain Monte Carlo methods such as [Metropolis Light Transport](https://graphics.stanford.edu/papers/metro/metro.pdf) generate a stream of correlated samples using a Markov chain; [many-light methods](http://www.csie.ntu.edu.tw/~cyy/courses/rendering/13fall/lectures/handouts/ManyLight-I.pdf) reuse a small set of light paths for many camera paths, creating many correlated shadow connections; even [photon mapping](http://graphics.stanford.edu/~henrik/papers/ewr7/egwr96.pdf) gains its efficiency from reusing light paths across many pixels, also increasing sample correlation (although in a biased way).&#xD;&#xA;&#xD;&#xA;All of these rendering methods can prove beneficial in certain scenes, but seem to make things worse in others. It's not clear how to quantify the quality of error introduced by these techniques, other than rendering a scene with different rendering algorithms and eyeballing whether one looks better than the other.&#xD;&#xA;&#xD;&#xA;So the question is: How does sample correlation influence the variance and the convergence of a Monte Carlo estimator? Can we somehow mathematically quantify which kind of sample correlation is better than others? Are there any other considerations that could influence whether sample correlation is beneficial or detrimental (e.g. perceptual error, animation flicker)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="533" PostHistoryTypeId="1" PostId="185" RevisionGUID="2c4b8640-8737-4b17-8671-0e693ff0bec0" CreationDate="2015-08-10T23:43:46.900" UserId="79" Text="How do correlated samples influence the behavior of a Monte Carlo renderer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="534" PostHistoryTypeId="3" PostId="185" RevisionGUID="2c4b8640-8737-4b17-8671-0e693ff0bec0" CreationDate="2015-08-10T23:43:46.900" UserId="79" Text="|raytracing|rendering|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="535" PostHistoryTypeId="2" PostId="186" RevisionGUID="9ca66bb1-300a-43d4-944f-f78a474a455b" CreationDate="2015-08-11T00:37:44.757" UserId="96" Text="I'm reading a [book on computer graphics][1], and at some point, it shows a 3D model, created from a .dat file.&#xD;&#xA;&#xD;&#xA;Here are a few rules for the .dat file creation:&#xD;&#xA;&#xD;&#xA; - Made of a list of vertex positions / faces&#xD;&#xA; - Written counter-clockwise&#xD;&#xA; - Faces end with a dot (.)&#xD;&#xA; - Fractions are also acceptable&#xD;&#xA;&#xD;&#xA;I want to know if this is the standard, and if not, what is the standard way of defining a 3D object.&#xD;&#xA;&#xD;&#xA;Also, if there is a specification, who defined it and where to find it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com.br/books/about/Computer_graphics_for_Java_programmers.html?id=vY5RAAAAMAAJ&amp;redir_esc=y" ContentLicense="CC BY-SA 3.0" />
  <row Id="536" PostHistoryTypeId="1" PostId="186" RevisionGUID="9ca66bb1-300a-43d4-944f-f78a474a455b" CreationDate="2015-08-11T00:37:44.757" UserId="96" Text="Is there a standard specification for 3D graphic representation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="537" PostHistoryTypeId="3" PostId="186" RevisionGUID="9ca66bb1-300a-43d4-944f-f78a474a455b" CreationDate="2015-08-11T00:37:44.757" UserId="96" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="538" PostHistoryTypeId="5" PostId="183" RevisionGUID="a8ae5fa9-b37a-4a92-9bac-fe4559667de3" CreationDate="2015-08-11T00:57:30.500" UserId="231" Comment="added 190 characters in body" Text="I want to be able to model an opaque liquid being dropped into a transparent liquid with sufficient velocity to cause turbulence and the resulting chaotic mixing. Assuming the two liquids are of the same density and viscosity, how could I model this?&#xD;&#xA;&#xD;&#xA;This doesn't need to be rendered in real time. I would like the turbulent flow to gradually settle down as the two fluids mix, but it will not be required to interact with other objects." ContentLicense="CC BY-SA 3.0" />
  <row Id="540" PostHistoryTypeId="2" PostId="187" RevisionGUID="091961f0-e974-4cb6-9033-1b414deafd36" CreationDate="2015-08-11T02:49:30.960" UserId="54" Text="When talking about file formats, we are talking about persisting some data related to a 3D model/geometry. There is no universal standard on file formats for persisting 3D geometry. There are only a few formats more dominant than others.&#xD;&#xA;&#xD;&#xA;Just as it is with image file formats, the PNGs and JPEGs are the most common formats out there today, but there is no universal agreement between applications on using one or the other. Each app uses the best fit for its purposes.&#xD;&#xA;&#xD;&#xA;The same happens with file formats storing 3D data. Each 3D modeling software will generally have one or a set of preferred formats. Most actually define custom formats that only work with the specific version of the tool. This can happen for many reasons, from simplifying the inner workings of the application, making loading of files faster, to binding the user to a given tool on purpose.&#xD;&#xA;&#xD;&#xA;This `.dat` format the you describe is a custom format created by the authors of the book, which was probably designed with simplicity in mind. It seems to be a text file similar to the [Wavefront OBJ][1] format, which in turn is a very popular format for storing static geometry, though a bit outdated by now. One could say that the `.OBJ` format is the `.BMP` of 3D model formats.&#xD;&#xA;&#xD;&#xA;Other popular 3D model formats include:&#xD;&#xA;&#xD;&#xA;- The [Collada][2] format.&#xD;&#xA;&#xD;&#xA;- The [3DS][3] format.&#xD;&#xA;&#xD;&#xA;- The [PLY][4] format.&#xD;&#xA;&#xD;&#xA;And many others. More general explanation [here][5].&#xD;&#xA;&#xD;&#xA;Also note that I said at the beginning that these are formats for storing/persisting a 3D model or geometry on an offline storage. It doesn't mean (and it usually isn't the case) that the applications that use them will store the data internally in memory using the same layout as the file. Normally, this kind of data will undergo a lot of processing after being loaded from a file until it is, for instance, displayed on the screen.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Wavefront_.obj_file&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/COLLADA&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/.3ds&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/PLY_(file_format)&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Polygon_mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="541" PostHistoryTypeId="2" PostId="188" RevisionGUID="d4a3bd1e-8219-4cd8-878a-10d2a2607198" CreationDate="2015-08-11T02:57:02.380" UserId="64" Text="There is not a single standard that defines the storage of 3D models. The graphics API only cares about triangles, which are defined by vertices and indices indicating which vertices form a triangle.&#xD;&#xA;&#xD;&#xA;Many companies have created their own model formats with different features and goals. One of the simplest is the .obj (Wavefront Object) format. Which contains lists of vertex positions, normals and texture coordinates and a list of indices that make up the triangles. It also contains materials, with some basic properties as textures, diffuse and specular colors.&#xD;&#xA;&#xD;&#xA;More advanced model formats, such as .fbx (FilmBox) used by Autodesk contain additional information required by the modeling software. These might include bones, hierarchies and even more vertex properties used for skinning etc. So there are &quot;standards&quot;, but they are not really unified as every program might require different information. But wavefront is a very good choice, because many modelling applications can export to it and it is easy to write (find) an importer for." ContentLicense="CC BY-SA 3.0" />
  <row Id="542" PostHistoryTypeId="2" PostId="189" RevisionGUID="67d8bc46-7add-4fc6-9ac7-35d866c848c1" CreationDate="2015-08-11T03:00:43.867" UserId="125" Text="There is no standard format for 3D models. Some common ones are listed in glampert's answer, more can be found [in this SE answer][1].&#xD;&#xA;&#xD;&#xA;If you are designing your own format for your own purposes, (a fairly common thing to do, actually) it's a good first step to look at how you are using your model data. For example, if you are focused on rendering, you can use the format that the graphics library expects. If you want to reduce the load time of your software as much as possible then reducing the amount of parsing and processing you have to do can help. A simple utility that can output a file in the format that your engine expects will mean you can simply map the file into memory and then pass a pointer into your graphics library.&#xD;&#xA;&#xD;&#xA;On the other hand, if rendering is not your main concern and editing is more important to you, you might consider a format more amenable to editing, such as [winged edge][2]. Using a general purpose model format may suit your purposes at the beginning of a project, but ultimately there are many things you can do with 3D models and each format has its own benefits and drawbacks, so you can choose the one that works best for you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/13600158/recommended-file-formats-and-graphics-libraries-for-importing-3d-model-into-open&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Winged_edge" ContentLicense="CC BY-SA 3.0" />
  <row Id="543" PostHistoryTypeId="5" PostId="187" RevisionGUID="3ebc41a8-3d98-4ea4-ab3c-2e93684dcc42" CreationDate="2015-08-11T03:01:33.010" UserId="54" Comment="deleted 1 character in body" Text="When talking about file formats, we are talking about persisting some data related to a 3D model/geometry. There is no universal standard on file formats for persisting 3D geometry. There are only a few formats more dominant than others.&#xD;&#xA;&#xD;&#xA;Just as it is with image file formats, the PNGs and JPEGs are the most common formats out there today, but there is no universal agreement between applications on using one or the other. Each app uses the best fit for its purposes.&#xD;&#xA;&#xD;&#xA;The same happens with file formats storing 3D data. Each 3D modeling software will generally have one or a set of preferred formats. Most actually define custom formats that only work with the specific version of the tool. This can happen for many reasons, from simplifying the inner workings of the application, or making loading of files faster, to binding the user to a given tool on purpose.&#xD;&#xA;&#xD;&#xA;This `.dat` format you describe is a custom format created by the authors of the book, which was probably designed with simplicity in mind. It seems to be a text file similar to the [Wavefront OBJ][1] format, which in turn is a very popular format for storing static geometry, though a bit outdated by now. One could say that the `.OBJ` format is the `.BMP` of 3D model formats.&#xD;&#xA;&#xD;&#xA;Other popular 3D model formats include:&#xD;&#xA;&#xD;&#xA;- The [Collada][2] format.&#xD;&#xA;&#xD;&#xA;- The [3DS][3] format.&#xD;&#xA;&#xD;&#xA;- The [PLY][4] format.&#xD;&#xA;&#xD;&#xA;And many others. More general explanation [here][5].&#xD;&#xA;&#xD;&#xA;Also note that I said at the beginning that these are formats for storing/persisting a 3D model or geometry on an offline storage. It doesn't mean (and it usually isn't the case) that the applications that use them will store the data internally in memory using the same layout as the file. Normally, this kind of data will undergo a lot of processing after being loaded from a file until it is, for instance, displayed on the screen.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Wavefront_.obj_file&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/COLLADA&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/.3ds&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/PLY_(file_format)&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Polygon_mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="544" PostHistoryTypeId="5" PostId="115" RevisionGUID="c51ddf44-55dc-4d80-ac05-528707d741cd" CreationDate="2015-08-11T04:40:02.740" UserId="21" Comment="added 387 characters in body" Text="Transformations are the mathematical operations that can be applied to an object (often a set of vertices that belong together) to move it, rotate it, or otherwise transform it.  &#xD;&#xA;Transformations are usually applied using a matrix.&#xD;&#xA;&#xD;&#xA;Transformations are not necessarily bijective; data may be lost, for example, in a projection from a 3D object to it's 2D representation on a screen.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="545" PostHistoryTypeId="24" PostId="115" RevisionGUID="c51ddf44-55dc-4d80-ac05-528707d741cd" CreationDate="2015-08-11T04:40:02.740" Comment="Proposed by 21 approved by 100, 196 edit id of 18" ContentLicense="CC BY-SA 3.0" />
  <row Id="546" PostHistoryTypeId="2" PostId="190" RevisionGUID="b4ecb80f-4451-4eff-b3b1-3836e7c32ffb" CreationDate="2015-08-11T04:49:54.333" UserId="355" Text="Not rendering a shadow caster could work but your mileage can vary. When variance is &quot;large&quot; a VSM is not able to exactly localize the occluders, which causes light leaks. Not rendering a large receiver (let say the floor of a room, a road, etc..) can dramatically increase the variance of the depth samples within a region of the shadow map that include the missing receiver(s) (e.g. the receiver depth is replaced by something much more distant, like the far plane).&#xD;&#xA;&#xD;&#xA;On the other hand, if you skip rendering in the VSM some little object that is unlikely to ever be the most distant receiver in the scene, then you have some hope that things will work out (compatibly with the limitations of variance shadow maps). If you can afford the cost I suggest you to use something more robust like exponential variance shadow maps (see this work: https://software.intel.com/en-us/articles/sample-distribution-shadow-maps)." ContentLicense="CC BY-SA 3.0" />
  <row Id="547" PostHistoryTypeId="2" PostId="191" RevisionGUID="092dacab-c85a-40bd-9a6f-efb9a16de858" CreationDate="2015-08-11T04:50:21.863" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="548" PostHistoryTypeId="2" PostId="192" RevisionGUID="a17abe16-5b10-469d-97d4-ea5c5ae7adf5" CreationDate="2015-08-11T04:50:21.863" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="549" PostHistoryTypeId="2" PostId="193" RevisionGUID="bd8f3d27-25e5-4f7b-ae84-30efd4628ee8" CreationDate="2015-08-11T05:07:01.950" UserId="196" Text="I think you may want to take another look at the iOS user interface if you consider real-time blurs to be out of range of mobile hardware:&#xD;&#xA;&#xD;&#xA;[![iOS control center][1]][1]&#xD;&#xA;[![iOS notification center][2]][2]&#xD;&#xA;&#xD;&#xA;Blurs are totally in range of mobile hardware. Yes, you need a fairly large number of texture samples for a blur with a large kernel, but the texture samples are also cached very well, and you can use a [separable blur][3], which effectively means that an MxN blur requires M + N samples, not M * N samples. You can also take advantage of hardware bilinear sampling to [reduce the number of samples][4] that your blur requires.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dRT54.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Dt2Sg.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Separable_filter&#xD;&#xA;  [4]: http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/" ContentLicense="CC BY-SA 3.0" />
  <row Id="551" PostHistoryTypeId="2" PostId="194" RevisionGUID="649ad6e3-1a11-42c2-aa80-b5cf01d414c3" CreationDate="2015-08-11T05:26:44.280" UserId="196" Text="It appears that Microsoft has punted on this in Windows 7:&#xD;&#xA;&#xD;&#xA;[![ClearType Text Tuner][1]][1]&#xD;&#xA;&#xD;&#xA;This is the method available in the control panel for selecting what layout ClearType uses.&#xD;&#xA;&#xD;&#xA;Additionally, it seems that iOS and the Windows modern UI style de-emphasize subpixel antialiasing heavily, due to the prevalence of animations and screen rotations. As a result I expect the OS vendors to not spend a lot of effort trying to figure out the subpixel layout of every screen.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KbzW2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="552" PostHistoryTypeId="2" PostId="195" RevisionGUID="a5537ff7-0cb9-4827-8b76-a4823782e156" CreationDate="2015-08-11T05:45:18.720" UserId="196" Text="The most commonly suggested method seems to be [Mueller calculus][1], which boils down to tracking the [Stokes parameters][2] of a light ray to represent the polarization of light transmitted along that ray. A ray might be unpolarized—Stokes parameters of (1, 0, 0, 0)—or it may be circularly or linearly polarized in various directions, which is a property of light in the aggregate. At the surface light is scattered according to the polarization and the Stokes vector is propagated by multiplying it by the Mueller matrix of the surface.&#xD;&#xA;&#xD;&#xA;Here's a [writeup by Toshiya Hachisuka][3] about ray tracing while tracking light polarization. It seems like a good introduction, and there are several references that seem promising. The article argues for *direct tracking* of the polarization state of the ray: instead of an aggregate representation, individually tracking the direction and frequency of the two harmonic oscillations of a given light ray. This may have the disadvantage that you need more samples to reproduce the polarization effects accurately, but it may be able to reproduce more effects (in the article, thin-film interference).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Mueller_calculus&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Stokes_parameters&#xD;&#xA;  [3]: http://cs.au.dk/~toshiya/mcp.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="553" PostHistoryTypeId="2" PostId="196" RevisionGUID="a61a455f-e854-4e38-8bc7-2b3be5453313" CreationDate="2015-08-11T05:57:28.187" UserId="56" Text="I've found that bump mapping can add a lot to the look of ice.&#xA;&#xA;Check this out: https://www.shadertoy.com/view/MdXGDX" ContentLicense="CC BY-SA 3.0" />
  <row Id="554" PostHistoryTypeId="2" PostId="197" RevisionGUID="21b28196-49e6-4e2b-9d4e-cf5da64ac785" CreationDate="2015-08-11T05:57:44.960" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="555" PostHistoryTypeId="2" PostId="198" RevisionGUID="656a0ee7-34a7-4594-974e-161498472230" CreationDate="2015-08-11T05:57:44.960" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="556" PostHistoryTypeId="2" PostId="199" RevisionGUID="c9699f36-09c2-41f1-bcf7-2dcd03bcf0a3" CreationDate="2015-08-11T06:25:24.990" UserId="168" Text="As an alternative you could also check Jon Stam's paper [&quot;Stable Fluids&quot;][1], that method is usually called the semi-Lagrangian approach to fluid simulations. You can find several implementations of it. You said that you don't need it to be real time, so this might do the work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://dx.doi.org/10.1145/311535.311548" ContentLicense="CC BY-SA 3.0" />
  <row Id="557" PostHistoryTypeId="2" PostId="200" RevisionGUID="5480b744-317a-4a32-bf02-050444c13396" CreationDate="2015-08-11T07:10:16.647" UserId="67" Text="To add to other answers, there are actually two kinds of formats, intermediate and runtime. Intermediate formats (example: COLLADA) are more verbose/slower and are converted between tools ultimately to the custom runtime format that is optimized for a specific application/hardware. Simple applications that do not care much about performance can directly use intermediate formats." ContentLicense="CC BY-SA 3.0" />
  <row Id="558" PostHistoryTypeId="2" PostId="201" RevisionGUID="b99b9439-6272-4ceb-8466-a38d53cf84f6" CreationDate="2015-08-11T07:12:44.110" UserId="158" Text="I'm working on a program to use randomly-selected images as a desktop background.  Now, not all images are the same shape as a computer monitor.  One idea I had for dealing with this is to set a background color that is perceptually similar to the image.  How would I go about finding this color?&#xD;&#xA;&#xD;&#xA;Simple RGB averaging doesn't take into account nonlinearities such as monitor gamma, and doesn't deal with the human vision system." ContentLicense="CC BY-SA 3.0" />
  <row Id="559" PostHistoryTypeId="1" PostId="201" RevisionGUID="b99b9439-6272-4ceb-8466-a38d53cf84f6" CreationDate="2015-08-11T07:12:44.110" UserId="158" Text="Finding a color perceptually similar to an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="560" PostHistoryTypeId="3" PostId="201" RevisionGUID="b99b9439-6272-4ceb-8466-a38d53cf84f6" CreationDate="2015-08-11T07:12:44.110" UserId="158" Text="|color|human-vision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="561" PostHistoryTypeId="2" PostId="202" RevisionGUID="9674a838-af98-43f3-a820-97c48e4cfcbe" CreationDate="2015-08-11T07:53:30.297" UserId="83" Text="Problem fixed by RichieSams, trichoplax and xpicox. Thanks all of you for the answers. &#xD;&#xA;&#xD;&#xA;I lower the roughness, change the color of material and reversed the ViewDirection then finally I start to see proper specular :).&#xD;&#xA;&#xD;&#xA;Fixed Code:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec3 Position;&#xD;&#xA;    in vec2 TexCoord0;&#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec3 Tangent;&#xD;&#xA;    out vec4 FinalColor;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 uCameraPosition;&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926f&#xD;&#xA;    #define EPSILON 10e-5f&#xD;&#xA;    #define saturate(value) clamp(value, 0.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;    float BRDF_Lambert(float NdotL)&#xD;&#xA;    {&#xD;&#xA;    	return NdotL;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Got these BRDF formulas Moving Frostbite to PBR slide by Sebastien Lagarde &amp; Charles de Rousiers &#xD;&#xA;    // http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf&#xD;&#xA;    float BRDF_D_GGX(float NdotH, float Roughness)&#xD;&#xA;    {&#xD;&#xA;    	float Roughness2 = Roughness * Roughness;&#xD;&#xA;    	float f = (NdotH * Roughness2 - NdotH) * NdotH + 1.0f;&#xD;&#xA;    	return Roughness2 / (f * f + EPSILON);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    float BRDF_F_FresnelSchlick(float LdotH, float F0)&#xD;&#xA;    {&#xD;&#xA;    	float f = F0 + (1.0f - F0) * pow((1.0f - LdotH), 5);&#xD;&#xA;    	return f;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float BRDF_G_SmithGGXCorrelated(float NdotL, float NdotV, float Roughness)&#xD;&#xA;    {&#xD;&#xA;    	float Roughness2 = Roughness * Roughness;&#xD;&#xA;    	float GV = NdotL * sqrt((-NdotV * Roughness2 + NdotV) * NdotV + Roughness2);&#xD;&#xA;    	float GL = NdotV * sqrt((-NdotL * Roughness2 + NdotL) * NdotL + Roughness2);&#xD;&#xA;    &#xD;&#xA;    	return 0.5f / (GV + GL + EPSILON);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float BRDF_Specular(float NdotV, float NdotL, float NdotH, float LdotH, float Roughness, float F0)&#xD;&#xA;    {&#xD;&#xA;    	float D = BRDF_D_GGX(NdotH, Roughness);&#xD;&#xA;    	float F = BRDF_F_FresnelSchlick(LdotH, F0);&#xD;&#xA;    	float G = BRDF_G_SmithGGXCorrelated(NdotL, NdotV, Roughness);&#xD;&#xA;    	return (D * F * G) / PI;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	vec3 normal = normalize(Normal);&#xD;&#xA;    &#xD;&#xA;    	vec4 BaseColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    	vec4 SpecularColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;    	vec3 LightDirection = normalize(vec3(0, 4, 4) - Position);&#xD;&#xA;    	vec3 ViewDirection = normalize(uCameraPosition - Position);&#xD;&#xA;    	vec3 HalfVector = normalize(ViewDirection + LightDirection);&#xD;&#xA;    	float Roughness = 0.04f;&#xD;&#xA;    	&#xD;&#xA;    	float RefractiveIndex = 0.24f; // RI for Gold materials. I got this from http://refractiveindex.info/&#xD;&#xA;    	float F0 = pow(((1.0f - RefractiveIndex) / (1.0f + RefractiveIndex)), 2);&#xD;&#xA;    &#xD;&#xA;    	float NdotL = saturate(dot(LightDirection, normal));&#xD;&#xA;    	float NdotV = abs(dot(ViewDirection, normal)) + EPSILON; // Avoid artifact - Ref: SIGGRAPH14 - Moving Frosbite to PBR&#xD;&#xA;    	float LdotH = saturate(dot(LightDirection, HalfVector));&#xD;&#xA;    	float NdotH = saturate(dot(normal, HalfVector));&#xD;&#xA;    &#xD;&#xA;    	float DiffuseFactor = BRDF_Lambert(NdotL);&#xD;&#xA;    	float SpecularFactor = 0.0f;&#xD;&#xA;    	if(DiffuseFactor &gt; 0.0f)&#xD;&#xA;    	{&#xD;&#xA;    		SpecularFactor = BRDF_Specular(NdotV, NdotL, NdotH, LdotH, Roughness, F0);&#xD;&#xA;    	}&#xD;&#xA;    	FinalColor = BaseColor * DiffuseFactor + SpecularColor * SpecularFactor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Final Image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j7Ft6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="562" PostHistoryTypeId="5" PostId="158" RevisionGUID="03dc1fc1-691b-48f9-a184-08b5f2339825" CreationDate="2015-08-11T08:25:31.447" UserId="110" Comment="deleted 1 character in body" Text="[Sorry for the very bad quality of my answer. I do not have access to a computer currently and editing from my phone is not a straightforward task. In particular I would love to be able to paste images.]  &#xD;&#xA;  &#xD;&#xA;I would say that the main challenges of simulating hair are:   &#xD;&#xA;- replicating their very specific reaction to lighting (as a material)  &#xD;&#xA;- replicating their volumetric property (as a geometry)  &#xD;&#xA;- animating them in a realistic manner  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;Here is a list of references I gathered on the subject, ordered chronologically (mainly about the rendering part).  &#xD;&#xA;  &#xD;&#xA;JAMES T. KAJIYA, TIMOTHY L. KAY, [Rendering Fur With Three Dimensional Textures](https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf), 1989  &#xD;&#xA;JEROME LENGYEL, EMIL PRAUN, ADAM FINKELSTEIN, HUGUES HOPPE, [Real-Time Fur over Arbitrary Surfaces](http://research.microsoft.com/en-us/um/people/hoppe/fur.pdf), 2000  &#xD;&#xA;STEPHEN R. MARSCHNER, HENRIK WANN JENSEN, MIKE CAMMARANO, [Light Scattering from Human Hair Fibers](http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf), 2003  &#xD;&#xA;ARMIN BRUDERLIN, SUNIL HADAP, TAE-YONG KIM, NADIA MAGNENAT-THALMANN , ULRICH NEUMANN, YIZHOU YU, STEVE WORLEY, [Photorealistic Hair Modeling, Animation, and Rendering](http://www.graphics.stanford.edu/courses/cs448-05-winter/papers/course34.pdf), Siggraph 2003 Course  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://bookzz.org/book/487747/b3254e), ShaderX3, 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairRendering.pdf), ATI / GDC 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketch.pdf), ATI / Siggraph 2004  &#xD;&#xA;THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf), ATI / Siggraph 2004 (slides)  &#xD;&#xA;MARTIN KOSTER, JORG HABER, HANS-PETER SEIDEL, [Real-Time Rendering of Human Hair using Programmable Graphics Hardware](http://resources.mpi-inf.mpg.de/FAM/publ/cgi2004.pdf), 2004  &#xD;&#xA;HUBERT NGUYEN, WILLIAM DONNELLY, [Hair Animation and Rendering in the Nalu Demo](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html), GPU Gems 2 (Chapter 23), 2005  &#xD;&#xA;LENA PETROVIC, MARK HENNE, JOHN ANDERSON, [Volumetric Methods for Simulation and Rendering of Hair](http://graphics.pixar.com/library/Hair/paper.pdf), Pixar 2006  &#xD;&#xA;CHRISTOPHE HERY, RAVI RAMAMOORTHI, [Importance Sampling of Reflections from Hair Fibers](http://graphics.pixar.com/library/ImportanceSamplingHair/paper.pdf), Pixar 2007  &#xD;&#xA;SARAH TARIQ, LOUIS BAVOIL, [Real-Time Hair Rendering on the GPU](http://www.nvidia.com/object/siggraph-2008-hair.html), Siggraph 2008. &#xD;&#xA;ARNO ZINKE, CEM YUKSEL, ANDREAS WEBER, JOHN KEYSER, [Dual Scattering Approximation for Fast Multiple Scattering in Hair](http://research.cs.tamu.edu/keyser/Papers/Siggraph08_dualscattering.pdf), Siggraph 2008  &#xD;&#xA;IMAN SADEGHI, HEATHER PRITCHETT, HENRIK WANN JENSEN, RASMUS TAMSTORF, [An Artist Friendly Hair Shading System](http://graphics.ucsd.edu/~henrik/papers/artist_hair.pdf), 2010  &#xD;&#xA;EUGENE D’EON, GUILLAUME FRANCOIS, MARTIN HILL, JOE LETTERI, JEAN-MARIE AUBRY, [An Energy-Conserving Hair Reflectance Model](http://www.eugenedeon.com/project/an-energy-conserving-hair-reflectance-model/), 2011  &#xD;&#xA;XUAN YU, JASON C. YANG, JUSTIN HENSLEY, TAKAHIRO HARADA, JINGYI YU, [A Framework for Rendering Complex Scattering Effects on Hair](http://www.eecis.udel.edu/~xyu/publications/frameworkhair124.pdf), 2012  &#xD;&#xA;JIAWEI OU, FENG XIE, PARASHAR KRISHNAMACHARI, FABIO PELLACINI, [ISHair: Importance Sampling for Hair Scattering](http://pellacini.di.uniroma1.it/publications/ishair12/ishair12-paper.pdf), 2012  &#xD;&#xA;SARAH INVERNIZZI, [On Physically Based Hair Rendering](http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/07/MSc_thesis_On_physically_based_hair_rendering.pdf), 2013  &#xD;&#xA;WOLFGANG ENGEL, [Hair Rendering in Tomb Raider](http://www.slideshare.net/WolfgangEngel/hair-intombraider-final), 2013  &#xD;&#xA;EUGENE D’EON, STEVE MARSCHNER, JOHANNES HANIKA, [Importance Sampling for Physically-Based Hair Fiber Models](https://cg.ivd.kit.edu/publications/pubhanika/2013_hairbrief.pdf), 2013  &#xD;&#xA;TIMOTHY MARTIN, WOLFGANG ENGEL, NICOLAS THIBIEROZ, JASON YANG, AND JASON LACROIX, [TressFX: Advanced Real-Time Hair Rendering](http://bookzz.org/book/2373940/c298ee), GPU Pro 5, 2015  &#xD;&#xA;LEONID PEKELIS, CHRISTOPHE HERY, RYUSUKE VILLEMIN, JUNYI LING, [A Data-Driven Light Scattering Model for Hair](http://graphics.pixar.com/library/DataDrivenHairScattering/paper.pdf), Pixar 2015  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;I must confess I unfortunately did not read all of those references yet. Also, I am more interested by the real-time solutions. Here is a little of what I think I read:  &#xD;&#xA;- Kajiya-kay laid the basis for realistic hair / fur rendering  &#xD;&#xA;- Marschner proposed an improved model, and noted that hair has two distinct specular highlights (one white due to direct reflection, the other colored and sparkling due to reflection inside of the hair fiber)  &#xD;&#xA;- Scheuermann proposed approximations to simulate the behaviour described by Marschner, approximations suited for real-time (using tricks such as two separate specular highlights, artist-designed specular offset and exponent, noise textures). He also proposed using three rendering passes (opaque, transparent back and front) of polygons to simulate the &quot;volumetric&quot; qualities of hair  &#xD;&#xA;- Most of the games I heard of seem to use Scheuermann approaches for hair shading. However, this is not an energy-conserving solution. Nevertheless, I think d'Eon attempts to fix this problem in the 2011 paper.  &#xD;&#xA;Also, tessellation has also been used to replace the polygonal approach and stimulate hair stands individually.     &#xD;&#xA;  &#xD;&#xA;The offline rendering world offers other solutions that I did not study yet, but whose main ones I believe are in the references above.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="564" PostHistoryTypeId="33" PostId="51" RevisionGUID="56582168-b2d2-4ef1-bc73-147b12e03090" CreationDate="2015-08-11T09:03:11.017" UserId="16" Comment="3" />
  <row Id="565" PostHistoryTypeId="5" PostId="197" RevisionGUID="e90ee3f4-9e9c-41be-9c4d-c6ad43345c74" CreationDate="2015-08-11T09:06:48.117" UserId="196" Comment="added 240 characters in body" Text="The [OpenGL shading language][1] is a high-level language that can be used to write [shader programs][2] that can execute on a GPU.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/OpenGL_Shading_Language&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="566" PostHistoryTypeId="24" PostId="197" RevisionGUID="e90ee3f4-9e9c-41be-9c4d-c6ad43345c74" CreationDate="2015-08-11T09:06:48.117" Comment="Proposed by 196 approved by 79, 100 edit id of 28" ContentLicense="CC BY-SA 3.0" />
  <row Id="567" PostHistoryTypeId="5" PostId="174" RevisionGUID="b1a8c5d9-9d6c-40be-989a-cdab39fe24df" CreationDate="2015-08-11T09:07:02.583" UserId="231" Comment="added 59 characters in body" Text="For questions involving use of the OpenGL graphics library." ContentLicense="CC BY-SA 3.0" />
  <row Id="568" PostHistoryTypeId="24" PostId="174" RevisionGUID="b1a8c5d9-9d6c-40be-989a-cdab39fe24df" CreationDate="2015-08-11T09:07:02.583" Comment="Proposed by 231 approved by 79, 196 edit id of 26" ContentLicense="CC BY-SA 3.0" />
  <row Id="570" PostHistoryTypeId="6" PostId="6" RevisionGUID="7fc29b84-e068-4425-89bf-374b37ec9afe" CreationDate="2015-08-11T09:22:47.723" UserId="18" Comment="monte carlo tag added" Text="|raytracing|algorithm|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="573" PostHistoryTypeId="2" PostId="203" RevisionGUID="754a0510-c503-4482-961f-90477ea8a790" CreationDate="2015-08-11T11:24:41.203" UserId="231" Text="In graphics we use RGB and other color spaces as an approximation to the full spectrum of light wavelengths. This evidently works pretty well in general, but are there any reasonably common objects/materials/phenomena, things you might encounter in your everyday life, whose appearance isn't represented well by RGB rendering due to having a complex emission/reflection/absorption spectrum?&#xD;&#xA;&#xD;&#xA;While the current answers are focusing mainly on colors outside a given RGB gamut, I'm also interested in hearing if there are examples where, for instance, the color of an object appears &quot;wrong&quot; when rendered in RGB because of an interaction between the light source spectrum and the object's reflection spectrum. In other words, a case where a spectral renderer would give you more correct results.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*Credit: I liked this question in the previous private beta so I'm reproducing it here. It was originally asked by [Nathan Reed]*&#xD;&#xA;&#xD;&#xA;  [Nathan Reed]: http://computergraphics.stackexchange.com/users/48/nathan-reed" ContentLicense="CC BY-SA 3.0" />
  <row Id="574" PostHistoryTypeId="1" PostId="203" RevisionGUID="754a0510-c503-4482-961f-90477ea8a790" CreationDate="2015-08-11T11:24:41.203" UserId="231" Text="Are there common materials that aren't represented well by RGB?" ContentLicense="CC BY-SA 3.0" />
  <row Id="575" PostHistoryTypeId="3" PostId="203" RevisionGUID="754a0510-c503-4482-961f-90477ea8a790" CreationDate="2015-08-11T11:24:41.203" UserId="231" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="576" PostHistoryTypeId="5" PostId="57" RevisionGUID="809a5674-4a4e-48e7-897b-bb2bb77393bc" CreationDate="2015-08-11T11:30:46.930" UserId="231" Comment="Rule out the need for real-time" Text="How can I distribute points over an implicit surface, to concentrate them more densely in areas of higher curvature?&#xD;&#xA;&#xD;&#xA;I've considered adding points randomly and rejecting points not required based on the curvature, but I'd like to know if there is a better approach giving a more even distribution over areas of similar curvature, while still giving the higher density required in high curvature regions.&#xD;&#xA;&#xD;&#xA;I'm looking specifically at using these points for a triangulation of the surface, and I don't want to create more triangles than I need for relatively flat parts.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;This will be applied to shapes with a known derivative so the curvature at a given point can be calculated.&#xD;&#xA;&#xD;&#xA;This does not need to be a real-time approach.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="578" PostHistoryTypeId="5" PostId="88" RevisionGUID="030daec7-73b9-4ef4-aaa2-d5eae6f0a380" CreationDate="2015-08-11T12:14:14.533" UserId="231" Comment="Confirm RichieSams' understanding." Text="Start with a precalculated &quot;ray cloud&quot; - the starting point and direction of a large number of rays, most of which will not contribute to the image. The image plane's position and orientation are then specified, and the task is to search the ray cloud for rays that intersect the image plane without occlusion by other objects, and output the resulting pixel values. No ray reflections would be required, as all of the work has already been done in generating the ray cloud. The only step left is to convert the rays to an image. This means that a single ray cloud can be used to generate images from arbitrary view angles.&#xD;&#xA;&#xD;&#xA;How could I go about accelerating this process using a GPU? The decision for each ray of whether it intersects the image plane is parallelisable as these decisions are independent, but each requires access to the objects in the scene as some rays will reach some potential image planes but not others. The final step of sampling the relevant rays across the pixels of the image requires each ray to contribute to a number of the surrounding pixels. Is this also parallelisable using a GPU?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To clarify, [RichieSams]' understanding is correct:&#xD;&#xA;&#xD;&#xA;- Start with a set of rays pointing in arbitrary directions.&#xD;&#xA;- Find which of these rays intersect with the image plane, taking into account occlusion. &#xD;&#xA;- Calculate the colour of each pixel based on the rays that hit the image plane.&#xD;&#xA;&#xD;&#xA;Ideally I would like to be able to accelerate this process sufficiently to move around a scene in real time, given a precomputed ray cloud over the whole scene.&#xD;&#xA;&#xD;&#xA;  [RichieSams]: http://computergraphics.stackexchange.com/users/310/richiesams" ContentLicense="CC BY-SA 3.0" />
  <row Id="579" PostHistoryTypeId="5" PostId="158" RevisionGUID="e60a9a45-c00d-41d0-afe7-c1369b9ac0f1" CreationDate="2015-08-11T12:15:52.837" UserId="18" Comment="Added list markup for readability" Text="*Sorry for the very bad quality of my answer. I do not have access to a computer currently and editing from my phone is not a straightforward task. In particular I would love to be able to paste images.*  &#xD;&#xA;  &#xD;&#xA;I would say that the main challenges of simulating hair are:  &#xD;&#xA;&#xD;&#xA; - replicating their very specific reaction to lighting (as a material)  &#xD;&#xA; - replicating their volumetric property (as a geometry)  &#xD;&#xA; - animating them in a realistic manner  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;---&#xD;&#xA;  &#xD;&#xA;Here is a list of references I gathered on the subject, ordered chronologically *(mainly about the rendering part)*:  &#xD;&#xA;  &#xD;&#xA;1. JAMES T. KAJIYA, TIMOTHY L. KAY, [Rendering Fur With Three Dimensional Textures](https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf), 1989  &#xD;&#xA;1. JEROME LENGYEL, EMIL PRAUN, ADAM FINKELSTEIN, HUGUES HOPPE, [Real-Time Fur over Arbitrary Surfaces](http://research.microsoft.com/en-us/um/people/hoppe/fur.pdf), 2000  &#xD;&#xA;1. STEPHEN R. MARSCHNER, HENRIK WANN JENSEN, MIKE CAMMARANO, [Light Scattering from Human Hair Fibers](http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf), 2003  &#xD;&#xA;1. ARMIN BRUDERLIN, SUNIL HADAP, TAE-YONG KIM, NADIA MAGNENAT-THALMANN , ULRICH NEUMANN, YIZHOU YU, STEVE WORLEY, [Photorealistic Hair Modeling, Animation, and Rendering](http://www.graphics.stanford.edu/courses/cs448-05-winter/papers/course34.pdf), Siggraph 2003 Course  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://bookzz.org/book/487747/b3254e), ShaderX3, 2004  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairRendering.pdf), ATI / GDC 2004  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketch.pdf), ATI / Siggraph 2004  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf), ATI / Siggraph 2004 (slides)  &#xD;&#xA;1. MARTIN KOSTER, JORG HABER, HANS-PETER SEIDEL, [Real-Time Rendering of Human Hair using Programmable Graphics Hardware](http://resources.mpi-inf.mpg.de/FAM/publ/cgi2004.pdf), 2004  &#xD;&#xA;1. HUBERT NGUYEN, WILLIAM DONNELLY, [Hair Animation and Rendering in the Nalu Demo](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html), GPU Gems 2 (Chapter 23), 2005  &#xD;&#xA;1. LENA PETROVIC, MARK HENNE, JOHN ANDERSON, [Volumetric Methods for Simulation and Rendering of Hair](http://graphics.pixar.com/library/Hair/paper.pdf), Pixar 2006  &#xD;&#xA;1. CHRISTOPHE HERY, RAVI RAMAMOORTHI, [Importance Sampling of Reflections from Hair Fibers](http://graphics.pixar.com/library/ImportanceSamplingHair/paper.pdf), Pixar 2007  &#xD;&#xA;1. SARAH TARIQ, LOUIS BAVOIL, [Real-Time Hair Rendering on the GPU](http://www.nvidia.com/object/siggraph-2008-hair.html), Siggraph 2008. &#xD;&#xA;1. ARNO ZINKE, CEM YUKSEL, ANDREAS WEBER, JOHN KEYSER, [Dual Scattering Approximation for Fast Multiple Scattering in Hair](http://research.cs.tamu.edu/keyser/Papers/Siggraph08_dualscattering.pdf), Siggraph 2008  &#xD;&#xA;1. IMAN SADEGHI, HEATHER PRITCHETT, HENRIK WANN JENSEN, RASMUS TAMSTORF, [An Artist Friendly Hair Shading System](http://graphics.ucsd.edu/~henrik/papers/artist_hair.pdf), 2010  &#xD;&#xA;1. EUGENE D’EON, GUILLAUME FRANCOIS, MARTIN HILL, JOE LETTERI, JEAN-MARIE AUBRY, [An Energy-Conserving Hair Reflectance Model](http://www.eugenedeon.com/project/an-energy-conserving-hair-reflectance-model/), 2011  &#xD;&#xA;1. XUAN YU, JASON C. YANG, JUSTIN HENSLEY, TAKAHIRO HARADA, JINGYI YU, [A Framework for Rendering Complex Scattering Effects on Hair](http://www.eecis.udel.edu/~xyu/publications/frameworkhair124.pdf), 2012  &#xD;&#xA;1. JIAWEI OU, FENG XIE, PARASHAR KRISHNAMACHARI, FABIO PELLACINI, [ISHair: Importance Sampling for Hair Scattering](http://pellacini.di.uniroma1.it/publications/ishair12/ishair12-paper.pdf), 2012  &#xD;&#xA;1. SARAH INVERNIZZI, [On Physically Based Hair Rendering](http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/07/MSc_thesis_On_physically_based_hair_rendering.pdf), 2013  &#xD;&#xA;1. WOLFGANG ENGEL, [Hair Rendering in Tomb Raider](http://www.slideshare.net/WolfgangEngel/hair-intombraider-final), 2013  &#xD;&#xA;1. EUGENE D’EON, STEVE MARSCHNER, JOHANNES HANIKA, [Importance Sampling for Physically-Based Hair Fiber Models](https://cg.ivd.kit.edu/publications/pubhanika/2013_hairbrief.pdf), 2013  &#xD;&#xA;1. TIMOTHY MARTIN, WOLFGANG ENGEL, NICOLAS THIBIEROZ, JASON YANG, AND JASON LACROIX, [TressFX: Advanced Real-Time Hair Rendering](http://bookzz.org/book/2373940/c298ee), GPU Pro 5, 2015  &#xD;&#xA;1. LEONID PEKELIS, CHRISTOPHE HERY, RYUSUKE VILLEMIN, JUNYI LING, [A Data-Driven Light Scattering Model for Hair](http://graphics.pixar.com/library/DataDrivenHairScattering/paper.pdf), Pixar 2015  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;I must confess I unfortunately did not read all of those references yet. Also, I am more interested by the real-time solutions. Here is a little of what I think I read:&#xD;&#xA;  &#xD;&#xA;- Kajiya-kay laid the basis for realistic hair / fur rendering  &#xD;&#xA;- Marschner proposed an improved model, and noted that hair has two distinct specular highlights (one white due to direct reflection, the other colored and sparkling due to reflection inside of the hair fiber)  &#xD;&#xA;- Scheuermann proposed approximations to simulate the behaviour described by Marschner, approximations suited for real-time (using tricks such as two separate specular highlights, artist-designed specular offset and exponent, noise textures). He also proposed using three rendering passes (opaque, transparent back and front) of polygons to simulate the &quot;volumetric&quot; qualities of hair  &#xD;&#xA;- Most of the games I heard of seem to use Scheuermann approaches for hair shading. However, this is not an energy-conserving solution. Nevertheless, I think d'Eon attempts to fix this problem in the 2011 paper.  &#xD;&#xA;Also, tessellation has also been used to replace the polygonal approach and stimulate hair stands individually.     &#xD;&#xA;  &#xD;&#xA;The offline rendering world offers other solutions that I did not study yet, but whose main ones I believe are in the references above.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="580" PostHistoryTypeId="24" PostId="158" RevisionGUID="e60a9a45-c00d-41d0-afe7-c1369b9ac0f1" CreationDate="2015-08-11T12:15:52.837" Comment="Proposed by 18 approved by 110, 231 edit id of 30" ContentLicense="CC BY-SA 3.0" />
  <row Id="581" PostHistoryTypeId="2" PostId="204" RevisionGUID="44deec6b-ed01-4f14-8a8e-0e5c04718470" CreationDate="2015-08-11T13:05:13.567" UserId="79" Text="I believe the most prominent spectral effect that can't be faithfully reproduced with RGB is [dispersion](https://en.wikipedia.org/wiki/Dispersion_(optics)), caused by dielectrics with spectrally varying index of refraction (usually modelled with the [Sellmeier equation](https://en.wikipedia.org/wiki/Sellmeier_equation)).&#xD;&#xA;&#xD;&#xA;Other spectral phenomena are usually caused by wave effects. One example that is encountered in real life every now and then is [thin-film interference](https://en.wikipedia.org/wiki/Thin-film_interference), which is caused by one or more reflective surfaces layered closely on top of each other (e.g. oil slicks, soap bubbles). Another wave effect that can sometimes be observed is [diffraction](https://en.wikipedia.org/wiki/Diffraction), caused e.g. by [diffraction gratings](https://en.wikipedia.org/wiki/Diffraction_grating), which is what causes the funky appearance of CDs." ContentLicense="CC BY-SA 3.0" />
  <row Id="588" PostHistoryTypeId="5" PostId="159" RevisionGUID="ec8225b5-002d-4764-b8fb-92e3b07122d2" CreationDate="2015-08-11T13:47:10.233" UserId="231" Comment="Add detail and what I've tried" Text="The iris (the colourful ring surrounding the pupil of the eye) is covered in a layer of water, and appears to have opaque elements embedded in transparent and translucent elements. What effects do I need to model in order for the iris to appear realistic close up (the iris taking up over 20% of the image area)?&#xD;&#xA;&#xD;&#xA;Is sub surface scattering necessary or is transparency sufficient? Is it necessary to take into account light from within the eye that entered via the pupil, or can the back of the iris be regarded as completely opaque? Are there other effects that I haven't considered?&#xD;&#xA;&#xD;&#xA;I'm looking to produce still images offline - the approach does not need to work in real time.&#xD;&#xA;&#xD;&#xA;So far I've tried covering the eye in a thin transparent film to simulate a water layer, and treating the iris as a section of a transparent ball with coloured transparent radially arranged strands, offset as they are layered front to back. To prevent unwanted effects from light that gets all the way through, I have backed the iris with a matt black sphere section. This still seems to give an eye that looks somewhat artificial (inorganic) and disconnected though.&#xD;&#xA;&#xD;&#xA;I'm trying to make this work with geometric primitives such as spheres, cones and cylinders, but I'm open to an approach using triangle meshes if that opens up new possibilities.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="589" PostHistoryTypeId="5" PostId="177" RevisionGUID="824b20b8-5412-4c52-a084-6afd76509d57" CreationDate="2015-08-11T14:03:55.660" UserId="231" Comment="Add detail and what I've tried" Text="I can model ice cubes as slightly misshapen transparent cubes with the refractive index of water, but they don't look convincing. They look like lumps of glass rather than ice.&#xD;&#xA;&#xD;&#xA;Looking at real ice cubes I can intuitively describe some differences but I don't know what physical properties to change to match them:&#xD;&#xA;&#xD;&#xA;- Ice cubes are wet. Mine look like dry glass.&#xD;&#xA;- Ice cubes are transparent in places and not in others.&#xD;&#xA;- Ice cubes often have cracks that are visible despite not separating.&#xD;&#xA;&#xD;&#xA;In this instance I am trying to model ice cubes on a surface (in air, not floating in water).&#xD;&#xA;&#xD;&#xA;What techniques do I need to include in order to increase the realism?&#xD;&#xA;&#xD;&#xA;I am not looking for real time techniques, just to produce still images. I would like the ice to be photorealistic even close up, and to cast realistic caustics and shadows.&#xD;&#xA;&#xD;&#xA;I've tried using curved edges and coating my ice cubes with a thin layer of transparent material to simulate a melted layer of water, but it doesn't seem to give the impression of being wet. I've also tried embedding a transparent sphere half the size of the cube at its centre, with a fog effect, but it doesn't blend into the cube naturally - it just looks embedded. Even a series of nested spheres with gradually increasing fog still doesn't look right.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="590" PostHistoryTypeId="5" PostId="183" RevisionGUID="f80d1e3c-6404-495b-8676-062b44a0c3b9" CreationDate="2015-08-11T14:45:32.540" UserId="231" Comment="Add detail and what I've tried" Text="I want to be able to model an opaque liquid being dropped into a transparent liquid with sufficient velocity to cause turbulence and the resulting chaotic mixing. Assuming the two liquids are of the same density and viscosity, how could I model this?&#xD;&#xA;&#xD;&#xA;This doesn't need to be rendered in real time. I would like the turbulent flow to gradually settle down as the two fluids mix, but it will not be required to interact with other objects.&#xD;&#xA;&#xD;&#xA;I've tried modelling an expanding interface between the two fluids, and accelerating the vertices of the interface based on the local curvature, adding new vertices as they move apart. This seemed to work in the early stages, giving a constant exaggeration of small surface imperfections to create at least the appearance of turbulence, but it ran into problems very early which seemed to result from the interface self-intersecting. I've been trying to think of ways to redirect vertices that are near to causing a surface self-intersection, but I wonder if I would be better off starting from scratch with a more amenable method." ContentLicense="CC BY-SA 3.0" />
  <row Id="591" PostHistoryTypeId="5" PostId="62" RevisionGUID="f7749cb0-dcd5-4582-8ebf-2ac4a155a372" CreationDate="2015-08-11T15:01:09.533" UserId="196" Comment="added a possible method using a geodesic sphere" Text="I'd consider just going with 3D noise and evaluating it on the surface of the sphere.&#xD;&#xA;&#xD;&#xA;For gradient noise which is naturally in the domain of the surface of the sphere, you need a regular pattern of sample points on the surface that have natural connectivity information, with roughly equal area in each cell, so you can interpolate or sum adjacent values. I wonder if something like a [Fibonacci grid][1] might work:&#xD;&#xA;&#xD;&#xA;[![Fibonacci grid on the surface of a sphere][2]][2]&#xD;&#xA;&#xD;&#xA;I haven't chewed through the math to determine how much work it would be to figure out the indices of and distance to your four neighbors (I don't even know if you end up having four well-defined neighbors in all cases), and I suspect it may be less efficient than simply using 3D noise.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If you are rendering a sphere, not just evaluating noise on the surface of a sphere, and are fine with tessellating your sphere to the resolution of your noise lattice, you can create a [geodesic grid][3] on the surface of the sphere (a subdivided icosahedron, usually):&#xD;&#xA;&#xD;&#xA;[![Geodesic sphere][4]][4]&#xD;&#xA;&#xD;&#xA;Each vertex of the sphere can have a randomly generated gradient for gradient noise. To get this information to the pixel shader (unless you want straightforward interpolation like value noise), you may need a technique like this article's [wireframe rendering with barycentric coordinates][5]: do unindexed rendering, with each vertex containing the barycentric coordinates of that vertex in the triangle. You can then read from `SV_PrimitiveID` (or the OpenGL equivalent) in the pixel shader, read the three noise gradients from the vertices based on what triangle you are on, and use whatever noise calculation you like using the interpolated barycentric coordinates.&#xD;&#xA;&#xD;&#xA;I think the most difficult part of this method is coming up with a scheme to map your triangle ID to three samples in order to look up the noise values at each vertex.&#xD;&#xA;&#xD;&#xA;If you need multiple octaves of noise or noise at a finer resolution than your sphere model, you may be able to do a coarse geodesic grid with vertices and do a few levels of subdivision in the pixel shader. i.e. from the barycentric coordinates, figure out which subdivided triangle you *would* be in if the mesh was further tessellated, and then figure out what the primitive ID and barycentric coordinates would be for that triangle.&#xD;&#xA;&#xD;&#xA;  [1]: http://onlinelibrary.wiley.com/doi/10.1256/qj.05.227/epdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/sQQb3.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Geodesic_grid&#xD;&#xA;  [4]: https://i.stack.imgur.com/pjVBA.png&#xD;&#xA;  [5]: http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/" ContentLicense="CC BY-SA 3.0" />
  <row Id="592" PostHistoryTypeId="2" PostId="206" RevisionGUID="0e4779db-cc7e-4831-97b2-23b3ccee8f5d" CreationDate="2015-08-11T15:45:12.683" UserId="196" Text="You could try some form of color quantization algorithm, which generally extract the most dominant N colors. The one I've seen referenced most is [modified median cut quantization][1] [.pdf], which is based on [median cut quantization][2] [.doc]. The benefit to this kind of algorithm is that instead of simply averaging every color in the image, it extracts and discards other highly prominent colors instead of allowing them to pollute the average.&#xD;&#xA;&#xD;&#xA;The concept is that color space (RGB space) is partitioned into 3D axis-aligned rectangular regions (the paper calls them vboxes) and iteratively subdivided by splitting vboxes, attempting to leave half of the pixels on each side of the split. The result is color clusters that should correspond to color clusters in the image. The largest color has a strong likelihood of being &quot;perceptually similar&quot; to the image.&#xD;&#xA;&#xD;&#xA;There's a [JavaScript implementation and demo of this algorithm called Color Thief][3].&#xD;&#xA;&#xD;&#xA;  [1]: http://www.leptonica.com/papers/mediancut.pdf&#xD;&#xA;  [2]: http://dcis.uohyd.ernet.in/~mravi/downloads/CIP/OLD-CIP/Median-cut.doc&#xD;&#xA;  [3]: http://lokeshdhakar.com/projects/color-thief/" ContentLicense="CC BY-SA 3.0" />
  <row Id="593" PostHistoryTypeId="2" PostId="207" RevisionGUID="5a3e3a09-9866-42cd-acd9-5110f87d58d8" CreationDate="2015-08-11T15:46:12.543" UserId="38" Text="RGB works because that's how our sensory apparatus works. Ina addition to dispersion, some man made materials and insect bodies sometimes have surfaces that have very tight color bands. These might benefit from a wide spectrum rendering. &#xD;&#xA;&#xD;&#xA;However since many of these  effects are pretty localized, you can often get away with making the shader just work weird. This does not work right in reflections and refractions but nobody is likely to notice. Unless you are doing some physics simulation its not really a big deal. But if you design optics this might be a big deal.&#xD;&#xA;&#xD;&#xA;Some materials, like snow, also convert incoming ultraviolet into visible light. Again this kind of effect can usually be handled by shaders/ special light groups.&#xD;&#xA;&#xD;&#xA;Butterfly wings are also a curiosity as they manipulate the waves phases and the forms of the incoming light. So if you want to do physics simulation on those then its a big deal.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Polarisation of light is also a big factor in insects and water effects." ContentLicense="CC BY-SA 3.0" />
  <row Id="594" PostHistoryTypeId="5" PostId="196" RevisionGUID="86e90542-aee6-4a26-80a3-cbf983ac694b" CreationDate="2015-08-11T15:54:47.880" UserId="56" Comment="Added images, fixed link" Text="I've found that bump mapping can add a lot to the look of ice.  Or rather, just using bump maps when calculating refraction rays.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here's my shadertoy where I got the screenshots from: https://www.shadertoy.com/view/ldj3zz#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t5t5K.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4NJbX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/sPo4R.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="595" PostHistoryTypeId="5" PostId="196" RevisionGUID="d4862e7f-3d7b-4f67-bc99-927c87e8ddc1" CreationDate="2015-08-11T16:20:02.963" UserId="56" Comment="added 20 characters in body" Text="I've found that bump mapping can add a lot to the look of ice.  Using bump maps both when calculating refraction rays, and when calculating lighting:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here's my shadertoy where I got the screenshots from: https://www.shadertoy.com/view/ldj3zz#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t5t5K.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4NJbX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/sPo4R.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="596" PostHistoryTypeId="2" PostId="208" RevisionGUID="94ae7357-71b8-4d4d-971f-e69fd9075268" CreationDate="2015-08-11T16:46:35.160" UserId="363" Text="The creme de la creme of single-pass no (or few) compromises transparency in OpenGL is an A-buffer. With modern OpenGL, it is possible to implement:&#xD;&#xA;&#xD;&#xA;http://blog.icare3d.org/2010/06/fast-and-accurate-single-pass-buffer.html&#xD;&#xA;&#xD;&#xA;It avoids the multiple passes of depth peeling and doesn't require onerous sorting." ContentLicense="CC BY-SA 3.0" />
  <row Id="600" PostHistoryTypeId="2" PostId="209" RevisionGUID="d7ca6d06-8890-427d-9b79-60b195e2f9dd" CreationDate="2015-08-11T21:54:24.663" UserId="158" Text="Bresenham's line algorithm is a way of drawing straight lines using only fast integer operations (addition, subtraction, and multiplication by 2).  However, it generates aliased lines.  Is there a similarly fast way to draw antialiased lines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="601" PostHistoryTypeId="1" PostId="209" RevisionGUID="d7ca6d06-8890-427d-9b79-60b195e2f9dd" CreationDate="2015-08-11T21:54:24.663" UserId="158" Text="Fast antialiased line drawing" ContentLicense="CC BY-SA 3.0" />
  <row Id="602" PostHistoryTypeId="3" PostId="209" RevisionGUID="d7ca6d06-8890-427d-9b79-60b195e2f9dd" CreationDate="2015-08-11T21:54:24.663" UserId="158" Text="|antialiasing|pixel-graphics|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="604" PostHistoryTypeId="5" PostId="196" RevisionGUID="4098af87-8443-4926-b228-26630f5356d2" CreationDate="2015-08-11T23:20:59.580" UserId="56" Comment="added 318 characters in body" Text="I've found that bump mapping when calculating lighting and refraction rays can add a lot to the look of ice. It makes the ice look textured and imperfect, like a melting ice cube would look.&#xD;&#xA;&#xD;&#xA;I sort of wonder if maybe animating a bump map could help make it look wet, as water sheets / droplets ran down it's surface.&#xD;&#xA;&#xD;&#xA;The images below look pretty nice, but they would probably look even better with the internal imperfections that other people are talking about.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here's my shadertoy where I got the screenshots from: https://www.shadertoy.com/view/ldj3zz#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t5t5K.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4NJbX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/sPo4R.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="605" PostHistoryTypeId="2" PostId="210" RevisionGUID="c8e10d4a-be04-4fd1-b946-75013b81e02e" CreationDate="2015-08-11T23:25:16.290" UserId="231" Text="I'm trying to implement ambient occlusion in Python 3 and I'm seeing shadows beneath my reflective spheres but they seem very faint. I'm not sure if that means I've missed something, or if I just have a false impression of how much shadow results from ambient occlusion.&#xD;&#xA;&#xD;&#xA;The result looks like this:&#xD;&#xA;&#xD;&#xA;[![4 reflective spheres under a uniform white sky][1]][1]&#xD;&#xA;&#xD;&#xA;This is modeled as spheres (rather than triangle meshes). The 4 yellowish mirror spheres are hovering just above a very large sphere to approximate a plane, and the whole scene is surrounded by a very large white emissive sphere that provides the ambient sky light.&#xD;&#xA;&#xD;&#xA;For each pixel sample rays are chosen with a Gaussian distribution around the pixel centre and more samples are chosen until the variance is sufficiently low. Rays reflect in the single specular reflection direction from the mirror spheres, and in any direction from the hemisphere of possible directions when hitting the floor. All rays eventually hit the white sky sphere and the colour is determined based on the losses along the way.&#xD;&#xA;&#xD;&#xA;Is there some vital step I'm overlooking?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/etDFe.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="606" PostHistoryTypeId="1" PostId="210" RevisionGUID="c8e10d4a-be04-4fd1-b946-75013b81e02e" CreationDate="2015-08-11T23:25:16.290" UserId="231" Text="Am I missing something for ambient occlusion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="607" PostHistoryTypeId="3" PostId="210" RevisionGUID="c8e10d4a-be04-4fd1-b946-75013b81e02e" CreationDate="2015-08-11T23:25:16.290" UserId="231" Text="|ambient-occlusion|shadow|second-opinion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="608" PostHistoryTypeId="6" PostId="210" RevisionGUID="14a2fe1b-a2e8-43e0-a439-599457250ad1" CreationDate="2015-08-11T23:39:48.350" UserId="231" Comment="edited tags" Text="|raytracing|ambient-occlusion|shadow|second-opinion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="609" PostHistoryTypeId="2" PostId="211" RevisionGUID="8d141787-2fb5-435c-9dd6-47bb851ed8fb" CreationDate="2015-08-11T23:41:33.870" UserId="79" Text="It's a bit hard to tell from your image, but it does look a bit faint. When debugging these kinds of things, it's always useful to strip down your scene as much as possible to remove any unnecessary complexity from the picture. In your case, try only creating a single diffuse sphere that touches the ground in one point. Give the ground and the sphere an albedo of 1. If ambient occlusion is implemented correctly, the point where the sphere touches the ground should have a pixel value of 0; the further away from the sphere you get, the closer the pixel values should go to 1 (not above - make sure nothing gets clamped when you output the image). Make sure to gamma correct your images.&#xD;&#xA;&#xD;&#xA;The one thing that sticks out from your description is &#xD;&#xA;&#xD;&#xA;&gt; Rays reflect [...] in any direction from the hemisphere of possible directions when hitting the floor&#xD;&#xA;&#xD;&#xA;That by itself is fine, but you need to make sure to multiply the rays by the Lambertian BRDF (i.e. dot(normal, ray)/Pi). Even better is to directly sample from a cosine hemisphere, in which case all factors cancel out. [This blog post](http://www.rorydriscoll.com/2009/01/07/better-sampling/) has all the important info in one place." ContentLicense="CC BY-SA 3.0" />
  <row Id="610" PostHistoryTypeId="2" PostId="212" RevisionGUID="249a23bf-4e80-48df-a270-8f61af20ff0f" CreationDate="2015-08-12T00:31:52.567" UserId="158" Text="When computing ray-object intersections against a transformed object, most raytracers apply the inverse transform to each ray and compute the intersection against a non-transformed object.  Wouldn't applying the forward transform to the object be faster and more efficient, because you only need to compute the transform once?" ContentLicense="CC BY-SA 3.0" />
  <row Id="611" PostHistoryTypeId="1" PostId="212" RevisionGUID="249a23bf-4e80-48df-a270-8f61af20ff0f" CreationDate="2015-08-12T00:31:52.567" UserId="158" Text="Raytracing: Why are inverse transformations applied to rays rather than forward transformations to objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="612" PostHistoryTypeId="3" PostId="212" RevisionGUID="249a23bf-4e80-48df-a270-8f61af20ff0f" CreationDate="2015-08-12T00:31:52.567" UserId="158" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="613" PostHistoryTypeId="2" PostId="213" RevisionGUID="208af3f3-a530-4859-a3a9-a63242ad36df" CreationDate="2015-08-12T00:44:23.180" UserId="327" Text="Most ray intersection algorithms can be greatly simplified if you can assume the shape you're intersecting is at the origin, unrotated and with unit size. There are a few exceptions (Like spheres, which have rotational symmetry.) but the more general versions of the algorithms mathematically usually end up basically translating both the shape and raw to the origin before calculating the intersection. With that in mind it's simpler and more consistent to simply transform rays so that the intersection always happens in object-space." ContentLicense="CC BY-SA 3.0" />
  <row Id="614" PostHistoryTypeId="2" PostId="214" RevisionGUID="5619206a-d37b-40d0-b599-c425f35f23bd" CreationDate="2015-08-12T00:46:42.240" UserId="231" Text="*I'm trying to learn about raytracing by implementing things in Python 3. I know this is always going to be slower than something like C++, and I know the speed could also be improved by using GPU raytracing, but for this question I'm not looking for general ways of speeding up, but specifically ways of reducing the number of samples required, which will then be useful for any language I may work with in future.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I have a partly formed idea which I'd like to work on, but first I wanted to run this past the experts to see if this is a pre-existing technique so I don't repeat work that has already been done.&#xD;&#xA;&#xD;&#xA;I've searched for &quot;sampling solid angle&quot; and &quot;voronoi sphere sampling&quot; but I can't see any sign of prior work. I'll describe my idea in case it goes by a name I can't think of.&#xD;&#xA;&#xD;&#xA;### Example image&#xD;&#xA;&#xD;&#xA;[![3 spheres on a plane][1]][1]&#xD;&#xA;&#xD;&#xA;This is an image of three spheres on a plane (which is actually a very large sphere). One is emissive, one is reflective, and one is matt (as is the floor). Sampling is adaptive so that pixels that quickly reach a stable colour do not take up much time. I limit the total number of samples per pixel to avoid the rendering continuing for too long. Even allowed to run overnight, the resulting image is very grainy, and experimenting with smaller images suggests this size image (1366 by 768) would take weeks to converge with my current approach.&#xD;&#xA;&#xD;&#xA;### My idea: concentrating samples along colour boundaries&#xD;&#xA;&#xD;&#xA;I'd like to be able to concentrate samples where they are needed, and to do this adaptively based on previous samples for the same intersection point or pixel. This will give an unknown bias in the distribution of samples, which means taking the average of the samples will give an inaccurate result. Instead I would like to consider the size of the voronoi cell on the surface of the unit hemisphere centred on the point of intersection (for sampling light incident at a point on a matt surface) or on the surface of a small circle (for sampling around a pixel).&#xD;&#xA;&#xD;&#xA;Assume that all points within that voronoi cell are receiving rays of the same colour as the centre of the voronoi cell. Now an estimate of the average colour can be obtained by weighting according to the area of each voronoi cell. Choosing new samples on the boundary between the two voronoi cells with the greatest difference in colour leads to an improvement in the estimate without needing to sample the entire hemisphere. Samples should end up more densely concentrated in areas of higher colour gradient. Areas of flat colour should end up being ignored once they have a few points near their boundary.&#xD;&#xA;&#xD;&#xA;The extra complication is that in both cases (sampling from a point on a matt surface, or sampling over a circle around a pixel centre) the simplified approach I have described is roughly equivalent to a large number of samples distributed uniformly. To make this work I would need to be able to bias the average by both the voronoi cell areas *and* the required distribution (cosine around the surface normal for a matt surface or gaussian around a pixel centre).&#xD;&#xA;&#xD;&#xA;So I have some more thinking to do before I could test this idea, but I wanted to check first if this has either already been done, or already ruled out as unworkable.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FzJUi.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="615" PostHistoryTypeId="1" PostId="214" RevisionGUID="5619206a-d37b-40d0-b599-c425f35f23bd" CreationDate="2015-08-12T00:46:42.240" UserId="231" Text="Speeding up convergence: am I reinventing the wheel?" ContentLicense="CC BY-SA 3.0" />
  <row Id="616" PostHistoryTypeId="3" PostId="214" RevisionGUID="5619206a-d37b-40d0-b599-c425f35f23bd" CreationDate="2015-08-12T00:46:42.240" UserId="231" Text="|raytracing|sampling|efficiency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="617" PostHistoryTypeId="5" PostId="213" RevisionGUID="cf251b5f-9158-49a6-9eb1-ee23b611b521" CreationDate="2015-08-12T00:54:41.007" UserId="327" Comment="edited body" Text="Most ray intersection algorithms can be greatly simplified if you can assume the shape you're intersecting is at the origin, unrotated and with unit size. There are a few exceptions (Like spheres, which have rotational symmetry.) but the more general versions of the algorithms mathematically usually end up basically translating both the shape and ray to the origin before calculating the intersection. With that in mind it's simpler and more consistent to simply transform rays so that the intersection always happens in object-space." ContentLicense="CC BY-SA 3.0" />
  <row Id="618" PostHistoryTypeId="5" PostId="151" RevisionGUID="bff23cbc-5097-4d7a-8fa0-b9171e3b4181" CreationDate="2015-08-12T00:55:29.510" UserId="116" Comment="added 1439 characters in body" Text="After so much reading about transformations it is time to implement a trackball for my app.&#xD;&#xA;I understand I have to create a vector from the origin to where the mouse is clicked and then another from the origin to where the mouse is released.&#xD;&#xA;&#xD;&#xA;My question is, do I have to transfor the (x,y) pixel coords to world-coords or should I just do everything in image space (considering image space is the 2D projection of the scene measured in pixels)?&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;Richie Sams' answer is a very good one. However, I think I'm following a slightly different approach, please correct me if I'm wrong or I'm misunderstanding something.&#xD;&#xA;&#xD;&#xA;In my application I have a `SimplePerspectiveCamera` class that receives the `position` of the camera, the `position of the target` we are looking at, the `up` vector, the `fovy`, `aspectRatio`, `near` and `far` distances.&#xD;&#xA;&#xD;&#xA;With those I build my View and Projection matrices. Now, If I want to zoom in/out I update the field of view and update my projection matrix. If I want to pan I move the position of the camera and look at by the delta the mouse produces.&#xD;&#xA;&#xD;&#xA;Finally, for rotations I can use either angle-axis transformation or quaternions. For this, I save the pixel-coords where the mouse was pressed and then when the mouse moves I also save the pixel-coords.&#xD;&#xA;&#xD;&#xA;For each pair of coords I can compute the Z-value given the formula for a sphere, i.e., sqrt(1-x^2-y^2), then compute to vectors that go from the `target` to `PointMousePressed` and from `target` to `PointMouseMoved`, do cross product to get the axis of rotation and use any method to compute the new camera position.&#xD;&#xA;&#xD;&#xA;However, my biggest doubt is that the (x,y,z) values are given in pixel-coords, and when computing the vectors I'm using `target` which is a point in world-coords. Isn't this mixing of coordinate system affecting the result of the rotation I'm trying to do?" ContentLicense="CC BY-SA 3.0" />
  <row Id="619" PostHistoryTypeId="2" PostId="215" RevisionGUID="8b9e71bc-113d-4da4-adb1-24070e2c4e4f" CreationDate="2015-08-12T01:30:57.970" UserId="327" Text="(Note: This has been cross posted from my [ompf2 post](http://ompf2.com/viewtopic.php?f=15&amp;t=1977).)&#xD;&#xA;&#xD;&#xA;Recently I've implemented Multiple Importance Sampling for the sampling of surfaces in my ray tracer. I do this by, on each intersection, sampling both a random direction from the BRDF and also sampling a random light, then combining both using the power heuristic.&#xD;&#xA;&#xD;&#xA;When I have only a single light, the results are beautiful. Whereas previously I had this:&#xD;&#xA;&#xD;&#xA;![BRDF sampling only](https://i.stack.imgur.com/kElUN.png)&#xD;&#xA;&#xD;&#xA;Now I have this, with the same amount (1024 per pixel) of samples:&#xD;&#xA;&#xD;&#xA;![BRDF+Light sampling](https://i.stack.imgur.com/H0JbB.png)&#xD;&#xA;&#xD;&#xA;So the algorithm seems to work well. The problem is when I add a second light source to the scene, the noise comes back! This is a render with a second light source. Even though it uses 4096 samples per pixel it is significantly noisier:&#xD;&#xA;&#xD;&#xA;![BRDF+Light with 2 lights](http://i.imgur.com/CfPZWV4.png)&#xD;&#xA;&#xD;&#xA;I am probably using the technique incorrectly. Perhaps I need to sample all light sources at once, instead of randomly picking one like I'm doing now? That doesn't seem like it would scale well as the number of lights go up, however. The implementation was loosely based on pbrt's DirectLightingIntegrator, and I suspect the reason why it doesn't work properly is that I also have multi-bounce indirect lighting. You can see my core integration function here: [main.cpp#L174][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]: https://github.com/yuriks/NoiseRay/blob/18828368b3a06f7d4405edd8fe1dbf80431169eb/src/main.cpp#L174" ContentLicense="CC BY-SA 3.0" />
  <row Id="620" PostHistoryTypeId="1" PostId="215" RevisionGUID="8b9e71bc-113d-4da4-adb1-24070e2c4e4f" CreationDate="2015-08-12T01:30:57.970" UserId="327" Text="Multiple Importance Sampling with more than one light" ContentLicense="CC BY-SA 3.0" />
  <row Id="621" PostHistoryTypeId="3" PostId="215" RevisionGUID="8b9e71bc-113d-4da4-adb1-24070e2c4e4f" CreationDate="2015-08-12T01:30:57.970" UserId="327" Text="|raytracing|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="622" PostHistoryTypeId="5" PostId="212" RevisionGUID="8b81620d-2b81-4978-ae00-00007e7a167e" CreationDate="2015-08-12T04:25:36.420" UserId="158" Comment="added 28 characters in body" Text="When computing ray-object intersections against a transformed object, most raytracers apply the inverse transform to each ray and compute the intersection against a non-transformed object.  Wouldn't applying the forward transform, putting the object into a flat world-space, be faster and more efficient, because you only need to compute the transform once?" ContentLicense="CC BY-SA 3.0" />
  <row Id="623" PostHistoryTypeId="5" PostId="215" RevisionGUID="4cb24bf7-f0fd-4e63-98f6-8101d2ee026f" CreationDate="2015-08-12T05:48:52.233" UserId="327" Comment="Replaced the problem image with one with an equivalent number of samples, for a better comparison." Text="(Note: This has been cross posted from my [ompf2 post](http://ompf2.com/viewtopic.php?f=15&amp;t=1977).)&#xD;&#xA;&#xD;&#xA;Recently I've implemented Multiple Importance Sampling for the sampling of surfaces in my ray tracer. I do this by, on each intersection, sampling both a random direction from the BRDF and also sampling a random light, then combining both using the power heuristic.&#xD;&#xA;&#xD;&#xA;When I have only a single light, the results are beautiful. Whereas previously I had this:&#xD;&#xA;&#xD;&#xA;![BRDF sampling only](https://i.stack.imgur.com/kElUN.png)&#xD;&#xA;&#xD;&#xA;Now I have this, with the same amount (1024 per pixel) of samples:&#xD;&#xA;&#xD;&#xA;![BRDF+Light sampling](https://i.stack.imgur.com/H0JbB.png)&#xD;&#xA;&#xD;&#xA;So the algorithm seems to work well. The problem is when I add a second light source to the scene, the noise comes back! This is a render with a second light source added:&#xD;&#xA;&#xD;&#xA;[![BRDF+Light with 2 lights][1]][1]&#xD;&#xA;&#xD;&#xA;I am probably using the technique incorrectly. Perhaps I need to sample all light sources at once, instead of randomly picking one like I'm doing now? That doesn't seem like it would scale well as the number of lights go up, however. The implementation was loosely based on pbrt's DirectLightingIntegrator, and I suspect the reason why it doesn't work properly is that I also have multi-bounce indirect lighting. You can see my core integration function here: [main.cpp#L174][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zVdm7.png&#xD;&#xA;  [2]: https://github.com/yuriks/NoiseRay/blob/18828368b3a06f7d4405edd8fe1dbf80431169eb/src/main.cpp#L174" ContentLicense="CC BY-SA 3.0" />
  <row Id="624" PostHistoryTypeId="2" PostId="216" RevisionGUID="93d0b326-fc41-44f1-bb7b-cf36ffae226e" CreationDate="2015-08-12T07:12:46.860" UserId="209" Text="Just to add to the excellent suggestions above, it occurred to me that, without an ultraviolet channel, fluorescent materials would be tricky to model." ContentLicense="CC BY-SA 3.0" />
  <row Id="625" PostHistoryTypeId="2" PostId="217" RevisionGUID="f4c6e8da-40c3-408a-9040-979cc2197964" CreationDate="2015-08-12T08:17:24.157" UserId="327" Text="It seems that the answer to my question is that my approach inherently can't work. After doing thinking about it some more and researching existing renderers, none seem to implement what I'm doing, and I think the noise comes from contributions from lights other than the one randomly picked will not be estimated with the PDF. To do it correctly I would need to loop through all the lights, which gives me essentially path tracing.&#xD;&#xA;&#xD;&#xA;(Note however, that at Mitsuba and PBRT implement a Direct Illumination integrator which uses the approach I do, but only works when excluding indirect illumination, which is also true of my approach.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="626" PostHistoryTypeId="2" PostId="218" RevisionGUID="9bce8a80-e376-401f-b752-88bfbd82c3dd" CreationDate="2015-08-12T08:55:30.060" UserId="113" Text="How can I overlay graphics on particle simulations? For instance if I am representing a liquid or gas with tons of little points how can I make those points look like a liquid or gas? Take Nvidia Flex for instance, they simulate liquids and gases with tons of small points but can render them as realistic liquids and gases instead of small balls." ContentLicense="CC BY-SA 3.0" />
  <row Id="627" PostHistoryTypeId="1" PostId="218" RevisionGUID="9bce8a80-e376-401f-b752-88bfbd82c3dd" CreationDate="2015-08-12T08:55:30.060" UserId="113" Text="Overlaying graphics on particle simulation" ContentLicense="CC BY-SA 3.0" />
  <row Id="628" PostHistoryTypeId="3" PostId="218" RevisionGUID="9bce8a80-e376-401f-b752-88bfbd82c3dd" CreationDate="2015-08-12T08:55:30.060" UserId="113" Text="|simulation|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="629" PostHistoryTypeId="4" PostId="212" RevisionGUID="15104820-a4c0-4df0-9755-c41dc9b39fa5" CreationDate="2015-08-12T09:31:56.920" UserId="6" Comment="Removed tags from title." Text="Why are inverse transformations applied to rays rather than forward transformations to objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="630" PostHistoryTypeId="24" PostId="212" RevisionGUID="15104820-a4c0-4df0-9755-c41dc9b39fa5" CreationDate="2015-08-12T09:31:56.920" Comment="Proposed by 6 approved by 79, 100 edit id of 31" ContentLicense="CC BY-SA 3.0" />
  <row Id="631" PostHistoryTypeId="6" PostId="218" RevisionGUID="0cec0177-763c-4e69-81c9-1569a228545c" CreationDate="2015-08-12T09:32:44.950" UserId="6" Comment="Added relevant tags." Text="|simulation|physics|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="632" PostHistoryTypeId="24" PostId="218" RevisionGUID="0cec0177-763c-4e69-81c9-1569a228545c" CreationDate="2015-08-12T09:32:44.950" Comment="Proposed by 6 approved by 100, 231 edit id of 32" ContentLicense="CC BY-SA 3.0" />
  <row Id="633" PostHistoryTypeId="2" PostId="219" RevisionGUID="5255ae11-3488-4791-964e-0be7052ae992" CreationDate="2015-08-12T10:17:33.037" UserId="228" Text="A good reference for game physics is [this](https://books.google.it/books?id=ynQZBwAAQBAJ&amp;printsec=frontcover&amp;dq=game+physics+eberly&amp;hl=en&amp;sa=X&amp;ved=0CCAQ6AEwAGoVChMIkKr24aSjxwIVwS4aCh3nrg55#v=onepage&amp;q=game%20physics%20eberly&amp;f=false) chapter 4 describes the basic free deformable surfaces (nurbs and bspline are of course cited and treated enough well) fluid and gases are instead treated in chapter five (basically the author derivate simplified model of navier stokes equations, suitable for real time applications).&#xD;&#xA;&#xD;&#xA;So actually i guess what i've written commenting your post was correct, i.e. combine the physical deformation of the point that controls the shape of the surface with a ffd computations.&#xD;&#xA;&#xD;&#xA;The book i cited should provide somewhere/somehow on the web source code, and itself it cites some example involving the technique i cited. If that is what you need let me know for a more specific explanation." ContentLicense="CC BY-SA 3.0" />
  <row Id="634" PostHistoryTypeId="5" PostId="198" RevisionGUID="88c6d1c6-61be-4884-9efc-cce19eca5f28" CreationDate="2015-08-12T14:23:38.907" UserId="196" Comment="added 24 characters in body" Text="OpenGL shading language." ContentLicense="CC BY-SA 3.0" />
  <row Id="635" PostHistoryTypeId="24" PostId="198" RevisionGUID="88c6d1c6-61be-4884-9efc-cce19eca5f28" CreationDate="2015-08-12T14:23:38.907" Comment="Proposed by 196 approved by 53 edit id of 29" ContentLicense="CC BY-SA 3.0" />
  <row Id="636" PostHistoryTypeId="2" PostId="220" RevisionGUID="3900f7bc-c8c6-480c-902f-9bbfa3c5d4a6" CreationDate="2015-08-12T14:27:25.487" UserId="196" Text="Most raytracers do both!&#xD;&#xA;&#xD;&#xA;Have you ever seen a ray-triangle intersection test where the triangle is transformed so that one vertex is at the origin and the triangle is flat along one of the axes? That would simplify the test, but storing the inverse transformation to apply it to the ray takes more space than the triangle itself. So you could say that almost all ray-triangle tests *do* apply the forward transformation to the object.&#xD;&#xA;&#xD;&#xA;And yet most of the time you are rendering a mesh of many triangles, and &quot;most raytracers&quot; don't transform every vertex in the mesh by the object's transform matrix, they inverse transform the ray into object space. There isn't necessarily a good reason for this—it can definitely be more performant in some cases to preprocess the mesh and put every vertex in world space.&#xD;&#xA;&#xD;&#xA;But then say you're doing animation studio-scale path tracing. Now your scene geometry might not all fit in RAM at once. It's no longer a performance win to pre-transform all your vertices/control points, because (a) you need one copy of the object per instance, and (b) you need to transform it each time you read it into RAM. When data bound, the cost of two matrix multiplies per ray is insignificant anyway.&#xD;&#xA;&#xD;&#xA;Floating point precision is a potential reason as well: when you have an object a long way from the origin, you get more error from floating point positions, and if you pre-transform the object you apply that error in different directions to each vertex, whereas if you inverse transform the ray you have one fixed error amount from the imprecise position of the ray, but your vertices have less error relative to each other.&#xD;&#xA;&#xD;&#xA;Although I suspect the real answer to &quot;why do most raytracers inverse transform the ray&quot; is that most raytracers with public source code implement a wide range of geometric primitives, either for educational purposes or as a proof-of-concept, and it's easier to implement one cheap ray inverse transform than N shape forward transforms. (Plus, as has been mentioned, some intersection algorithms are much simpler if the object is in its canonical space.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="637" PostHistoryTypeId="2" PostId="221" RevisionGUID="28be3732-9b18-4fce-ad65-9bf5c5c7cf88" CreationDate="2015-08-12T16:16:49.647" UserId="56" Text="I know in the not so long ago (5-10 years?) that it was popular / efficient to bake data out into textures and then read the data from the textures, often using the built in texture interpolation to get linear interpolation of the baked out data.&#xD;&#xA;&#xD;&#xA;Now that computing time is cheaper compared to texture lookup time, this practice has definitely lessened if not all together disappeared.&#xD;&#xA;&#xD;&#xA;My question is, are baked out textures still used for anything?  Does anyone have any usage cases for them in modern architecture?  Does it seem likely they will ever make a come back? (say, if memory technology or basic GPU architecture changes)" ContentLicense="CC BY-SA 3.0" />
  <row Id="638" PostHistoryTypeId="1" PostId="221" RevisionGUID="28be3732-9b18-4fce-ad65-9bf5c5c7cf88" CreationDate="2015-08-12T16:16:49.647" UserId="56" Text="Are lookup textures still used for anything?" ContentLicense="CC BY-SA 3.0" />
  <row Id="639" PostHistoryTypeId="3" PostId="221" RevisionGUID="28be3732-9b18-4fce-ad65-9bf5c5c7cf88" CreationDate="2015-08-12T16:16:49.647" UserId="56" Text="|texture|gpu|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="640" PostHistoryTypeId="2" PostId="222" RevisionGUID="1b3a911a-7e05-4135-943d-a3ee35d3f6ea" CreationDate="2015-08-12T16:19:26.997" UserId="56" Text="I've seen mention of tiled raytracing, but haven't been able to find much on google about it.&#xD;&#xA;&#xD;&#xA;Can anyone explain what it is and how it works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="641" PostHistoryTypeId="1" PostId="222" RevisionGUID="1b3a911a-7e05-4135-943d-a3ee35d3f6ea" CreationDate="2015-08-12T16:19:26.997" UserId="56" Text="What is &quot;tiled&quot; raytracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="642" PostHistoryTypeId="3" PostId="222" RevisionGUID="1b3a911a-7e05-4135-943d-a3ee35d3f6ea" CreationDate="2015-08-12T16:19:26.997" UserId="56" Text="|raytracing|tile-based-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="643" PostHistoryTypeId="2" PostId="223" RevisionGUID="386cf494-4f6a-4488-b6de-c56a7eca57f5" CreationDate="2015-08-12T16:42:14.817" UserId="196" Text="Yes, lookup textures are still used. For example, pre-integrated BRDFs (for ambient lighting, say), or arbitrarily complicated curves baked down to a 1D texture, or a 3D lookup texture for color grading, or a noise texture instead of a PRNG in the shader.&#xD;&#xA;&#xD;&#xA;ALU is generally cheaper than a texture sample, true, but you still have a limited amount of ALU per frame. GPUs are good at latency hiding and small lookup textures are likely to be in the cache. If your function is complicated enough, it may still be worth using a lookup texture." ContentLicense="CC BY-SA 3.0" />
  <row Id="644" PostHistoryTypeId="2" PostId="224" RevisionGUID="1317d7a8-c58d-41f3-a35b-57d39859ea42" CreationDate="2015-08-12T16:55:26.340" UserId="327" Text="For rendering of gases, I think the usual approach is to simply render each particle as a tiny disc. Gases don't really coalesce into surfaces like liquids do, so this should produce acceptable results. You could perhaps apply a light blur over the gas layer afterwards to soften it and hide the fact that it is made of discrete elements.&#xD;&#xA;&#xD;&#xA;Liquids, on the other hand, tend to coalesce together to form droplets and smooth surfaces, so you need to derive a surface from the particles somehow. One way to do this is to use [Metaballs][1], which also display this behavior and can be tweaked to suit different liquids and particle densities. By interpreting each particle as a metaball, you will have an implicit equation representing your liquid surface. To render this implicit surface you can then use an algorithm like [Marching Tetrahedra][2] to convert it to triangles, or utilize [Ray Marching][3] to directly render it. (Ray marching can be easily done in realtime in a fragment shader these days.) You can also use this approach for liquids if you want a somewhat softer look.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Metaballs&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Marching_tetrahedra&#xD;&#xA;  [3]: http://gamedev.stackexchange.com/a/67745/5337" ContentLicense="CC BY-SA 3.0" />
  <row Id="645" PostHistoryTypeId="5" PostId="224" RevisionGUID="7cc56c57-b080-4d72-85e1-34b068491e17" CreationDate="2015-08-12T17:01:00.427" UserId="327" Comment="deleted 2 characters in body" Text="For rendering of gases, I think the usual approach is to simply render each particle as a tiny disc. Gases don't really coalesce into surfaces like liquids do, so this should produce acceptable results. You could perhaps apply a light blur over the gas layer afterwards to soften it and hide the fact that it is made of discrete elements.&#xD;&#xA;&#xD;&#xA;Liquids, on the other hand, tend to coalesce together to form droplets and smooth surfaces, so you need to derive a surface from the particles somehow. One way to do this is to use [Metaballs][1], which also display this behavior and can be tweaked to suit different liquids and particle densities. By interpreting each particle as a metaball, you will have an implicit equation representing your liquid surface. To render this implicit surface you can then use an algorithm like [Marching Tetrahedra][2] to convert it to triangles, or utilize [Ray Marching][3] to directly render it. (Ray marching can be easily done in realtime in a fragment shader these days.) You can also use this approach for gases if you want a somewhat softer look.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Metaballs&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Marching_tetrahedra&#xD;&#xA;  [3]: http://gamedev.stackexchange.com/a/67745/5337" ContentLicense="CC BY-SA 3.0" />
  <row Id="646" PostHistoryTypeId="5" PostId="215" RevisionGUID="993b1c98-ca83-40af-8462-e97cf75eeab8" CreationDate="2015-08-12T17:10:01.963" UserId="327" Comment="Inlined code snippet" Text="(Note: This has been cross posted from my [ompf2 post](http://ompf2.com/viewtopic.php?f=15&amp;t=1977).)&#xD;&#xA;&#xD;&#xA;Recently I've implemented Multiple Importance Sampling for the sampling of surfaces in my ray tracer. I do this by, on each intersection, sampling both a random direction from the BRDF and also sampling a random light, then combining both using the power heuristic.&#xD;&#xA;&#xD;&#xA;When I have only a single light, the results are beautiful. Whereas previously I had this:&#xD;&#xA;&#xD;&#xA;![BRDF sampling only](https://i.stack.imgur.com/kElUN.png)&#xD;&#xA;&#xD;&#xA;Now I have this, with the same amount (1024 per pixel) of samples:&#xD;&#xA;&#xD;&#xA;![BRDF+Light sampling](https://i.stack.imgur.com/H0JbB.png)&#xD;&#xA;&#xD;&#xA;So the algorithm seems to work well. The problem is when I add a second light source to the scene, the noise comes back! This is a render with a second light source added:&#xD;&#xA;&#xD;&#xA;[![BRDF+Light with 2 lights][1]][1]&#xD;&#xA;&#xD;&#xA;I am probably using the technique incorrectly. Perhaps I need to sample all light sources at once, instead of randomly picking one like I'm doing now? That doesn't seem like it would scale well as the number of lights go up, however. The implementation was loosely based on pbrt's DirectLightingIntegrator, and I suspect the reason why it doesn't work properly is that I also have multi-bounce indirect lighting. This is my core integration function:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    vec3 calc_light_incidence(const Scene&amp; scene, Rng&amp; rng, const Ray&amp; ray, int depth) {&#xD;&#xA;    	float ray_weight = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	depth += 1;&#xD;&#xA;    	if (depth &gt; 2) {&#xD;&#xA;    		const float live_probability = 0.75f;&#xD;&#xA;    &#xD;&#xA;    		if (rng.canonical() &gt; live_probability) {&#xD;&#xA;    			return vec3_0;&#xD;&#xA;    		} else {&#xD;&#xA;    			ray_weight = 1.0f / live_probability;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	vec3 color = vec3_0;&#xD;&#xA;    &#xD;&#xA;    	const Optional&lt;Intersection&gt; surface_hit = find_nearest_intersection(scene, ray);&#xD;&#xA;    	if (surface_hit) {&#xD;&#xA;    		const vec3 out_dir = -normalized(ray.direction);&#xD;&#xA;    &#xD;&#xA;    		const size_t light_index = (size_t)(rng.canonical() * scene.lights.size());&#xD;&#xA;    		const SceneObject* light = &amp;scene.objects[scene.lights[light_index]];&#xD;&#xA;    		const float light_weight = (float)scene.lights.size();&#xD;&#xA;    &#xD;&#xA;    		// Sample BRDF&#xD;&#xA;    		{&#xD;&#xA;    			const vec3 in_dir = cosine_weighted_point_on_hemisphere(rng.canonical(), rng.canonical(), surface_hit-&gt;normal);&#xD;&#xA;    			const vec3 reflectance = surface_hit-&gt;object-&gt;material.diffuse_brdf(*surface_hit, in_dir, out_dir);&#xD;&#xA;    			const float cos_term = dot(in_dir, surface_hit-&gt;normal);&#xD;&#xA;    &#xD;&#xA;    			const float brdf_pdf = cos_term / pi;&#xD;&#xA;    &#xD;&#xA;    			const Optional&lt;Intersection&gt; light_hit = light-&gt;shape-&gt;intersect(ray_from_surface(*surface_hit, in_dir));&#xD;&#xA;    			const float light_pdf = (light_hit ? light-&gt;shape-&gt;areaPdf(surface_hit-&gt;position, in_dir) : 0.f);&#xD;&#xA;    &#xD;&#xA;    			if (brdf_pdf != 0.f &amp;&amp; reflectance != vec3_0) {&#xD;&#xA;    				const vec3 illuminance = calc_light_incidence(scene, rng, ray_from_surface(*surface_hit, in_dir), depth);&#xD;&#xA;    				color += (1.0f / brdf_pdf) * cos_term * reflectance * illuminance * power_heuristic(brdf_pdf, light_pdf);&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		// Sample lights&#xD;&#xA;    		{&#xD;&#xA;    			const ShapeSample light_sample = light-&gt;shape-&gt;sampleArea(rng, surface_hit-&gt;position);&#xD;&#xA;    			const vec3 light_vec = light_sample.point - surface_hit-&gt;position;&#xD;&#xA;    			const vec3 in_dir = normalized(light_vec);&#xD;&#xA;    			const float cos_term = vmax(0.f, dot(in_dir, surface_hit-&gt;normal));&#xD;&#xA;    &#xD;&#xA;    			const Optional&lt;Intersection&gt; light_hit = find_nearest_intersection(scene, ray_from_surface(*surface_hit, light_vec));&#xD;&#xA;    			bool occluded = !light_hit || light_hit-&gt;object != light;&#xD;&#xA;    			const float light_pdf = light_weight * light_sample.pdf;&#xD;&#xA;    &#xD;&#xA;    			const float brdf_pdf = cos_term / pi;&#xD;&#xA;    &#xD;&#xA;    			const vec3 reflectance = surface_hit-&gt;object-&gt;material.diffuse_brdf(*surface_hit, in_dir, out_dir);&#xD;&#xA;    			if (!occluded &amp;&amp; light_pdf != 0.f &amp;&amp; reflectance != vec3_0) {&#xD;&#xA;    				const vec3 illuminance = calc_light_incidence(scene, rng, ray_from_surface(*surface_hit, in_dir), depth);&#xD;&#xA;    				const float differential_area = -dot(light_hit-&gt;normal, in_dir) / length_sqr(light_vec);&#xD;&#xA;    				color += light_weight * (1.0f / light_pdf) * differential_area * cos_term * reflectance * illuminance * power_heuristic(light_pdf, brdf_pdf);&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		if (dot(out_dir, surface_hit-&gt;normal) &gt;= 0.f) {&#xD;&#xA;    			color += surface_hit-&gt;object-&gt;material.emmision-&gt;getValue(*surface_hit);&#xD;&#xA;    		}&#xD;&#xA;    	} else {&#xD;&#xA;    		//color = lerp(mvec3(1.0f, 0.2f, 0.0f), mvec3(0.35f, 0.9f, 1.0f), 1.0f - std::pow(1.0f - vmax(0.0f, dot(ray.direction, vec3_y)), 2)) * 0.5f;&#xD;&#xA;    		color = lerp(mvec3(0.02f, 0.06f, 0.36f), mvec3(0.0f, 0.0f, 0.0f), 1.0f - std::pow(1.0f - vmax(0.0f, dot(ray.direction, vec3_y)), 2)) * 0.5f;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return color * ray_weight;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zVdm7.png&#xD;&#xA;  [2]: https://github.com/yuriks/NoiseRay/blob/18828368b3a06f7d4405edd8fe1dbf80431169eb/src/main.cpp#L174" ContentLicense="CC BY-SA 3.0" />
  <row Id="647" PostHistoryTypeId="5" PostId="150" RevisionGUID="42997ec7-97dc-4f28-a5fa-6c08fe592c8e" CreationDate="2015-08-12T17:52:53.173" UserId="38" Comment="added 176 characters in body" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;### How to do it analytically&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Analytic scene][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Suppose you have this scene, exploded view on right&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/Tfs4k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CihEg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="648" PostHistoryTypeId="5" PostId="150" RevisionGUID="8226c87d-b6fa-49fa-a0ef-4651a5ba8f19" CreationDate="2015-08-12T18:05:36.017" UserId="38" Comment="added 176 characters in body" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;### How to do it analytically&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Analytic scene][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Suppose you have this scene, exploded view on right&#xD;&#xA;&#xD;&#xA;Now you can not just do this analytically. each piece separately and then merge the data. Because it results in wrong data. See alpha blending would let the blue shine trough the gaps if you did so.&#xD;&#xA;&#xD;&#xA;What you have to so is split the scene up so that each shape eliminates what is under the other:&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;Now if everything is opaque then this is all straight forward. just calculate the area of each piece and multiply that by color and sum them together. Except not so funky, see theres no analytic solution for how to compute area of a form surrounded by beziers so youd have to numerically integrate this. (its easy for polygons se [here](http://stackoverflow.com/a/18175481/1335032))&#xD;&#xA;&#xD;&#xA;This all breaks down if your individual shapes aren't opaque off course but even that can be done at some level.&#xD;&#xA;&#xD;&#xA;Remember:&#xD;&#xA;&#xD;&#xA;* AA calculation need to be done in linear color space, and converted back to use space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/Tfs4k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CihEg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rJu1X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="649" PostHistoryTypeId="5" PostId="150" RevisionGUID="8679e8c5-f8b6-4ac6-b4e4-432aedc1a6a8" CreationDate="2015-08-12T18:32:37.170" UserId="38" Comment="deleted 47 characters in body" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;### How to do it analytically&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Analytic scene][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Suppose you have this scene, exploded view on right&#xD;&#xA;&#xD;&#xA;Now you can not just do this analytically. each piece separately and then merge the data. Because it results in wrong data. See alpha blending would let the blue shine trough the gaps if you did so.&#xD;&#xA;&#xD;&#xA;What you have to so is split the scene up so that each shape eliminates what is under the other:&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;Now if everything is opaque then this is all straight forward. just calculate the area of each piece and multiply that by color and sum them together. Except not so funky, see theres no analytic solution for how to compute area of a form surrounded by beziers so you'd have to numerically integrate this. (its easy for polygons though)&#xD;&#xA;&#xD;&#xA;This all breaks down if your individual shapes aren't opaque off course but even that can be done at some level.&#xD;&#xA;&#xD;&#xA;Remember:&#xD;&#xA;&#xD;&#xA;* AA calculation need to be done in linear color space, and converted back to use space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/Tfs4k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CihEg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rJu1X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="650" PostHistoryTypeId="5" PostId="150" RevisionGUID="786122b4-da40-4993-9c72-5b6cf542782c" CreationDate="2015-08-12T18:49:13.010" UserId="38" Comment="edited body" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;### How to do it analytically&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Analytic scene][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Suppose you have this scene, exploded view on right&#xD;&#xA;&#xD;&#xA;Now you can not just do this analytically, each piece separately and then merge the data. Because it results in wrong data. See alpha blending would let the blue shine trough the gaps if you did so.&#xD;&#xA;&#xD;&#xA;What you have to so is split the scene up so that each shape eliminates what is under the other:&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: You need to cut the underlying surfaces.&#xD;&#xA;&#xD;&#xA;Now if everything is opaque then this is all straight forward. just calculate the area of each piece and multiply that by color and sum them together. Except not so funky, see theres no analytic solution for how to compute area of a form surrounded by beziers so you'd have to numerically integrate this. (its easy for polygons though)&#xD;&#xA;&#xD;&#xA;This all breaks down if your individual shapes aren't opaque off course but even that can be done at some level.&#xD;&#xA;&#xD;&#xA;Remember:&#xD;&#xA;&#xD;&#xA;* AA calculation need to be done in linear color space, and converted back to use space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/Tfs4k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CihEg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rJu1X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="651" PostHistoryTypeId="2" PostId="225" RevisionGUID="bb332dfc-b648-4ca9-9d70-927c2601750e" CreationDate="2015-08-12T19:34:12.640" UserId="158" Text="There are a number of terms for rendering techniques based on the particle model of light: forward ray-tracing, reverse ray-tracing, ray-casting, ray-marching, and possibly others.  What's the difference between them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="652" PostHistoryTypeId="1" PostId="225" RevisionGUID="bb332dfc-b648-4ca9-9d70-927c2601750e" CreationDate="2015-08-12T19:34:12.640" UserId="158" Text="Ray-based rendering terms" ContentLicense="CC BY-SA 3.0" />
  <row Id="653" PostHistoryTypeId="3" PostId="225" RevisionGUID="bb332dfc-b648-4ca9-9d70-927c2601750e" CreationDate="2015-08-12T19:34:12.640" UserId="158" Text="|raytracing|raymarching|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="654" PostHistoryTypeId="2" PostId="226" RevisionGUID="6d2eb6ac-8938-43ae-83ca-92ce9e74fd0f" CreationDate="2015-08-13T00:20:04.227" UserId="64" Text="Forward ray-tracing means that rays starts from the light source and are traced towards the eye (light-surface-eye), this is a highly inefficient but accurate method. Reverse raytracing is simply starting in the eye and then trace them towards the light source. These are two classes of ray tracers.&#xD;&#xA;&#xD;&#xA;&gt; Ray casting is the use of ray-surface intersection tests to solve a variety of problems in computer graphics and computational geometry. The distinction is that ray casting is a rendering algorithm that never recursively traces secondary rays, whereas other ray tracing-based rendering algorithms may do so. &#xD;&#xA;&#xD;&#xA;Ray-marching is an implementation of a ray tracer, often used to visualize volumes. Normally ray casting uses a formulae to determine the point of intersection with the surface. In ray marching such a function is not required, instead the intersection is evaluated at several points along the ray. Either these points have a fixed distance between them or every iteration the distance to the next point is based on the distance to the closest surface.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The difference between those are that ray-tracing is a concept to solve the rendering equation, in the end resulting in a certain color for each pixel. Forward and reverse ray-tracing are classes of ray-tracers, ray-casting is a simple algorithm to do ray-tracing and ray-marching is another algorithm to do ray-tracing. As by the comment many other algorithms have been developed to solve the problem with different advantages and disadvantages." ContentLicense="CC BY-SA 3.0" />
  <row Id="655" PostHistoryTypeId="2" PostId="227" RevisionGUID="8d2d9e8e-2f42-4cc2-998b-a4a66c796517" CreationDate="2015-08-13T01:10:15.263" UserId="158" Text="How are volumetric effects such as smoke, fog, or clouds rendered by a raytracer?  Unlike solid objects, these don't have a well-defined surface to compute an intersection with." ContentLicense="CC BY-SA 3.0" />
  <row Id="656" PostHistoryTypeId="1" PostId="227" RevisionGUID="8d2d9e8e-2f42-4cc2-998b-a4a66c796517" CreationDate="2015-08-13T01:10:15.263" UserId="158" Text="How are volumetric effects handled in raytracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="657" PostHistoryTypeId="3" PostId="227" RevisionGUID="8d2d9e8e-2f42-4cc2-998b-a4a66c796517" CreationDate="2015-08-13T01:10:15.263" UserId="158" Text="|raytracing|volumetric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="658" PostHistoryTypeId="2" PostId="228" RevisionGUID="75a9a226-39e1-453d-9e5c-23ce5b6cd08f" CreationDate="2015-08-13T02:04:11.007" UserId="56" Text="One way to do it - which isn't exactly the &quot;go to&quot; solution, but can work nicely, is to find the distance that the ray traveled through the volume and use integration of some density function to calculate how much &quot;stuff&quot; was hit.&#xA;&#xA;Here is a link with more info:&#xA;http://blog.demofox.org/2014/06/22/analytic-fog-density/" ContentLicense="CC BY-SA 3.0" />
  <row Id="659" PostHistoryTypeId="2" PostId="229" RevisionGUID="59e9d896-d3fe-40b0-a6c7-36a61f052692" CreationDate="2015-08-13T02:32:23.337" UserId="377" Text="I *believe* it's where you batch it and do a block of pixels at once, or a &quot;tile&quot;.&#xD;&#xA;&#xD;&#xA;This causes speed boosts for lots of different reasons, depending on your implementation and hardware. If you can, check out Ingo Wald's PhD thesis about real time raytracing, he makes a lot of references to batching to get speed using things like AVX (advanced vectoring extensions) in the processor. These provide speed boosts when you calculate the color for a certain amount of similar pixels. It's all cool and definitely worth looking into, and I'm sure I botched the explanation :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also when doing real time raytracing, you may be using the graphics card and sending all the data over the bus is a large bottleneck. You don't want to send all the data over to the card to calculate the value of only one pixel because of the bus overhead - so you want to send a reasonable amount of data to chew on while you work on getting the next chunk ready.&#xD;&#xA;&#xD;&#xA;I hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="660" PostHistoryTypeId="5" PostId="229" RevisionGUID="353d4a9b-764e-4a4a-a61e-675d893a90e1" CreationDate="2015-08-13T02:55:36.173" UserId="377" Comment="added 326 characters in body" Text="I *believe* it's where you batch it and do a block of pixels at once, or a &quot;tile&quot;. &#xD;&#xA;&#xD;&#xA;This causes speed boosts for lots of different reasons, depending on your implementation and hardware. If you can, check out Ingo Wald's PhD thesis about real time raytracing, he makes a lot of references to batching to get speed using things like AVX (advanced vectoring extensions) in the processor. These provide speed boosts when you calculate the color for a certain amount of similar pixels. It's all cool and definitely worth looking into, and you can read more here: https://en.wikipedia.org/wiki/Advanced_Vector_Extensions&#xD;&#xA;&#xD;&#xA;Basically your represent similar data for similar pixels using a vector of floats and do the same calculations to all at once, saving cycles. Picture Bart Simpson writing out the same words on the chalkboard all at once instead of line-by-line in the Simpsons opening :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also when doing real time raytracing, you may be using the graphics card and sending all the data over the bus is a large bottleneck. You don't want to send all the data over to the card to calculate the value of only one pixel because of the bus overhead - so you want to send a reasonable amount of data to chew on while you work on getting the next chunk ready.&#xD;&#xA;&#xD;&#xA;I hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="661" PostHistoryTypeId="5" PostId="229" RevisionGUID="f72fe89b-dbfa-4784-b451-b8387f284380" CreationDate="2015-08-13T03:03:27.287" UserId="377" Comment="added 72 characters in body" Text="I *believe* it's where you batch it and do a block of pixels at once, or a &quot;tile&quot;. &#xD;&#xA;&#xD;&#xA;This causes speed boosts for lots of different reasons, depending on your implementation and hardware. If you can, check out Ingo Wald's PhD thesis about real time raytracing, he makes a lot of references to batching to get speed using things like AVX (advanced vectoring extensions) in the processor. These provide speed boosts when you calculate the color for a certain amount of similar pixels. It's all cool and definitely worth looking into, and you can read more here: https://en.wikipedia.org/wiki/Advanced_Vector_Extensions&#xD;&#xA;&#xD;&#xA;Basically your represent similar data for similar pixels using a vector of floats and do the same calculations to all at once, saving cycles. Picture Bart Simpson writing out the same words on the chalkboard all at once instead of line-by-line in the Simpsons opening :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also when doing real time raytracing, you may be using the graphics card and sending all the data over the bus is a large bottleneck. You don't want to send all the data over to the card to calculate the value of only one pixel because of the bus overhead - so you want to send a reasonable amount of data to chew on while you work on getting the next chunk ready.&#xD;&#xA;&#xD;&#xA;So, to me at least, &quot;tiled&quot; raytracing is just &quot;batched&quot; raytracing.&#xD;&#xA;&#xD;&#xA;I hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="662" PostHistoryTypeId="5" PostId="228" RevisionGUID="604354c9-0764-43de-a1d3-b759dfeac8d1" CreationDate="2015-08-13T03:31:06.013" UserId="56" Comment="added 22 characters in body" Text="One way to do it - which isn't exactly the &quot;go to&quot; solution, but can work nicely, is to find the distance that the ray traveled through the volume and use integration of some density function to calculate how much &quot;stuff&quot; was hit.&#xD;&#xA;&#xD;&#xA;Here is a link with an example implementation:&#xD;&#xA;http://blog.demofox.org/2014/06/22/analytic-fog-density/" ContentLicense="CC BY-SA 3.0" />
  <row Id="663" PostHistoryTypeId="2" PostId="230" RevisionGUID="611bf14e-98b8-4aca-92fd-1fed0208fa07" CreationDate="2015-08-13T03:32:42.397" UserId="56" Text="I know how to program directional lights, point lights and spot lights.  Sometimes though, people have lights that are shaped - like bars, or even a torus.&#xD;&#xA;&#xD;&#xA;How does that work from either a ray based or rasterization perspective?" ContentLicense="CC BY-SA 3.0" />
  <row Id="664" PostHistoryTypeId="1" PostId="230" RevisionGUID="611bf14e-98b8-4aca-92fd-1fed0208fa07" CreationDate="2015-08-13T03:32:42.397" UserId="56" Text="How do shaped lights work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="665" PostHistoryTypeId="3" PostId="230" RevisionGUID="611bf14e-98b8-4aca-92fd-1fed0208fa07" CreationDate="2015-08-13T03:32:42.397" UserId="56" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="666" PostHistoryTypeId="2" PostId="231" RevisionGUID="41d1810f-d230-418a-a7aa-82312c3870b1" CreationDate="2015-08-13T03:36:58.337" UserId="158" Text="Tiled raytracing is a way of speeding up rendering.  Instead of rendering pixels on a row-by-row basis down the entire image, you render them in 2D groups (say, 32x32 tiles).  Since adjacent rays tend to intersect the same objects, this improves the cache hit rate at the CPU level.&#xD;&#xA;&#xD;&#xA;At a smaller scale, tiling at the 2x2 level lets you use SSE/AVX/etc to compute four rays with a single CPU instruction, further speeding things up." ContentLicense="CC BY-SA 3.0" />
  <row Id="667" PostHistoryTypeId="2" PostId="232" RevisionGUID="be3479f9-82ee-4d25-a33c-7002dfa78180" CreationDate="2015-08-13T04:33:04.053" UserId="196" Text="In a path tracer, when tracing a ray to a light with a shape other than a point (&quot;area light&quot; is the usual terminology), you generally select a random point on the surface of the light. When enough samples are taken, this results in both softer specular highlights and softer shadow penumbras: light will be reflected off a surface from a random distribution of incoming directions, and rays cast towards an area light with an obstruction in the way may or may not intersect the obstruction depending on which point on the light was sampled.&#xD;&#xA;&#xD;&#xA;In real time, approximations to area lights are used. This [Unreal Engine 4 white paper][1] describes some of the considerations. One possibility is the &quot;representative point&quot; method, which per-pixel selects a point in the light's volume (brightest or nearest) and uses that as though it was a point light. Another option is modifying the roughness that is fed into the specular calculation based on a cone that approximates the area light (in the paper as &quot;Specular D Modification&quot;).&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="668" PostHistoryTypeId="2" PostId="233" RevisionGUID="2e203f94-d901-4f5f-85ad-55ea3455ec22" CreationDate="2015-08-13T05:24:10.437" UserId="56" Text="Looking at a light probe texture, it looks like a blurry environment map.&#xA;&#xA;What's the difference between the two, how is a light probe made, and what is the benefit of it being blurry?" ContentLicense="CC BY-SA 3.0" />
  <row Id="669" PostHistoryTypeId="1" PostId="233" RevisionGUID="2e203f94-d901-4f5f-85ad-55ea3455ec22" CreationDate="2015-08-13T05:24:10.437" UserId="56" Text="How is a light probe different than an environmental cube map?" ContentLicense="CC BY-SA 3.0" />
  <row Id="670" PostHistoryTypeId="3" PostId="233" RevisionGUID="2e203f94-d901-4f5f-85ad-55ea3455ec22" CreationDate="2015-08-13T05:24:10.437" UserId="56" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="671" PostHistoryTypeId="2" PostId="234" RevisionGUID="4ada869f-34a0-483c-833a-241633d72f66" CreationDate="2015-08-13T05:50:52.547" UserId="38" Text="Depends on the volume efffect. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Uniform volume effects that do not belong do scattering can be simulated by just calculating ray enter and ray exit distances.&#xD;&#xA;&#xD;&#xA;Otherwise you need to do integration of the ray path, also known as ray marching. To avoid needing to shoot secondary rays the raymarching is often coupled with some sort of cache, like depthmap, deepmaps, brick maps or voxel clouds for light shadowing. This way you dont necceserily need to march the whole scene. Similar caching is often done to the volume procedural texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is also possible to convert the texture to surface primitives like boxes, spheres or planes that have some suitable soft edged texture. You can then use normal rendering techniques to solve the volumetric effect. The problem with this is that you usually need lots of primitives. Additionally the shape of the may show up as too uniform." ContentLicense="CC BY-SA 3.0" />
  <row Id="672" PostHistoryTypeId="5" PostId="234" RevisionGUID="2f39836d-5d0c-432a-b0ef-5c38851279cd" CreationDate="2015-08-13T06:04:53.237" UserId="38" Comment="added 5 characters in body" Text="Depends on the volume efffect. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Uniform volume effects that do not belong do scattering can be simulated by just calculating ray enter and ray exit distances.&#xD;&#xA;&#xD;&#xA;Otherwise you need to do integration of the ray path, also known as ray marching. To avoid needing to shoot secondary rays the raymarching is often coupled with some sort of cache, like depthmap, deepmaps, brick maps or voxel clouds for light shadowing, etc. This way you dont necceserily need to march the whole scene. Similar caching is often done to the volume procedural texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is also possible to convert the texture to surface primitives like boxes, spheres or planes that have some suitable soft edged texture. You can then use normal rendering techniques to solve the volumetric effect. The problem with this is that you usually need lots of primitives. Additionally the shape of the primitive may show up as too uniform sampling." ContentLicense="CC BY-SA 3.0" />
  <row Id="673" PostHistoryTypeId="2" PostId="235" RevisionGUID="aed592fe-28e0-4748-b8fa-fbc37aece48d" CreationDate="2015-08-13T07:33:20.873" UserId="158" Text="Say I've got a photograph of a scene, and measurements for part of it (eg. a room where I know the dimensions of the walls).  Assuming a rectilinear lens, how would I go about setting up a virtual camera so that 3D objects are rendered as if they were in the physical scene?" ContentLicense="CC BY-SA 3.0" />
  <row Id="674" PostHistoryTypeId="1" PostId="235" RevisionGUID="aed592fe-28e0-4748-b8fa-fbc37aece48d" CreationDate="2015-08-13T07:33:20.873" UserId="158" Text="Matching a virtual camera to a physical camera" ContentLicense="CC BY-SA 3.0" />
  <row Id="675" PostHistoryTypeId="3" PostId="235" RevisionGUID="aed592fe-28e0-4748-b8fa-fbc37aece48d" CreationDate="2015-08-13T07:33:20.873" UserId="158" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="677" PostHistoryTypeId="2" PostId="236" RevisionGUID="9062914e-2bc0-4be3-8b42-736ca4f40539" CreationDate="2015-08-13T11:51:27.977" UserId="79" Text="Overview&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;The appearance of volumes (also called participating media) in nature is caused by tiny particles, such as dust, water droplets or plankton, that are suspended in the surrounding fluid, such as air or water. These particles are solid objects, and light refracts or reflects off of these objects as it would on a normal surface. In theory, participating media could therefore be handled by a traditional ray tracer with only surface intersections.&#xD;&#xA;&#xD;&#xA;Statistical Model&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;Of course, the _sheer number_ of these particles makes it infeasible to actually raytrace them individually. Instead, they are approximated with a statistical model: Because the particles are very small, and the distance between the particles is much larger than the particle size, individual interactions of light with the particles can be modelled as statistically independent. Therefore, it is a reasonable approximation to replace the individual particles with continuous quantities that describe the &quot;average&quot; light-particle interaction at that certain region in space.&#xD;&#xA;&#xD;&#xA;For physically based volumetric light transport, we replace the inconceivably many particles with a continuous participating medium that has two properties: The absorption coefficient, and the scattering coefficient. These coefficients are very convenient for ray tracing, as they allow us to compute the probability of a ray interacting with the medium - that is, the probability of striking one of the particles - as a function of distance.&#xD;&#xA;&#xD;&#xA;The absorption coefficient is denoted `sigma_a`. Say a ray of light wants to travel `t` meters inside the participating medium; the probability of making it through unabsorbed -- i.e. not hitting one of the particles and being absorbed by it -- is `exp(-t*sigma_a)`. As t increases, we can see that this probability goes to zero, that is, the longer we travel through the medium, the more likely it is to hit something and be absorbed. Very similar things hold for the scattering coefficient `sigma_s`: The probability of the ray not hitting a particle and being scattered is `exp(-t*sigma_s)`; that is, the longer we travel through a medium, the more likely it is that we hit a particle and are scattered into a different direction.&#xD;&#xA;&#xD;&#xA;Usually, these two quantities are folded into a single extinction coefficient, `sigma_t = sigma_a + sigma_s`. The probability of travelling `t` meters through a medium without interacting with it (neither being absorbed or scattered) is then `exp(-t*sigma_t)`. On the other hand, the probability of interacting with a medium after `t` meters is `1 - exp(-t*sigma_t)`.&#xD;&#xA;&#xD;&#xA;Rendering with Participating Media&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;The way this is used in physically based renderers is as follows: When a ray enters a medium, we probabilistically stop it inside the medium and have it interact with a particle. Importance sampling the interaction probability `1 - exp(-t*sigma_t)` yields a distance `t`; this tells us that the ray travelled `t` meters in the medium before striking a particle, and now one of two things happens: Either the ray gets absorbed by the particle (with probability `sigma_a/sigma_t`), or it gets scattered (with probability `sigma_s/sigma_t`).&#xD;&#xA;&#xD;&#xA;How the ray is scattered is described by the _phase function_ and depends on the nature of the particles; the Rayleigh phase function describes scattering from spherical particles smaller than the wavelength of light (e.g. our atmosphere); the Mie phase function descibes scattering from spherical particles of similar size than the wavelength (e.g. water droplets); in graphics, usually the [Henyey-Greenstein](http://www.astro.umd.edu/~jph/HG_note.pdf) phase function is used, originally applied to scattering from interstellar dust.&#xD;&#xA;&#xD;&#xA;Now, in graphics, we don't normally render pictures of an infinite medium, but render media inside a scene consisting of hard surfaces as well. In that case, we first fully trace the ray until it hits the next surface, completely ignoring the participating medium; this gives us the distance to the next surface, `tMax`. We then sample an interaction distance `t` in the medium as described before. If `t &lt; tMax`, the ray hit a particle on the way to the next surface and we either absorb it or scatter it. If `t &gt;= tMax`, the ray made it through unscathed and interacts with the surface as usual.&#xD;&#xA;&#xD;&#xA;Outlook&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;This post was only a small introduction to rendering with participating media; among other things, I completely ignored spatially varying coefficients (which you need for clouds, smoke, etc.). [Steve Marschner's notes](http://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf) are a good resource, if you're interested. In general, participating media are very difficult to render efficiently, and you can go a lot more sophisticated than what I described here; there's [Volumetric Photon Mapping](http://www.cs.dartmouth.edu/~wjarosz/publications/jarosz08beam.pdf), [Photon Beams](http://www.cs.dartmouth.edu/~wjarosz/publications/jarosz11progressive.pdf), [Diffusion approximations](https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf), [Joint Importance Sampling](http://www.cs.dartmouth.edu/~wjarosz/publications/georgiev13joint.pdf) and more. There's also interesting work on [granular media](http://www.cs.dartmouth.edu/~wjarosz/publications/meng15granular.pdf) that describes what to do when the statistical model breaks down, i.e. particle interactions are no longer statistically independent." ContentLicense="CC BY-SA 3.0" />
  <row Id="678" PostHistoryTypeId="2" PostId="237" RevisionGUID="85984141-5e80-452a-9290-a1eed24bfb52" CreationDate="2015-08-13T12:25:00.457" UserId="21" Text="This is the [Camera re-sectioning problem](https://en.wikipedia.org/wiki/Camera_resectioning). &#xD;&#xA;&#xD;&#xA;We need to have a few points, like the end points of the walls, to take the roles of x&lt;sub&gt;w&lt;/sub&gt;, y&lt;sub&gt;w&lt;/sub&gt; and z&lt;sub&gt;w&lt;/sub&gt; in the following equation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here A is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;These are the values of the camera itself.&#xD;&#xA;&#xD;&#xA;R and T are defined as the Rotation and Translation matrices for the camera, and are the values we need to solve for. The position, C, of the camera expressed in world coordinates is C = -R&lt;sup&gt;-1&lt;/sup&gt;T = -R&lt;sup&gt;T&lt;/sup&gt; T .&#xD;&#xA;&#xD;&#xA;The linked Wikipedia article mentions a few algorithms to solve these equations.&#xD;&#xA;&#xD;&#xA;An example of a practical application of these is also found on [Math Stack Exchange](http://math.stackexchange.com/questions/82602/how-to-find-camera-position-and-rotation-from-a-4x4-matrix).&#xD;&#xA;&#xD;&#xA;Another example, with some code samples that you may want to use, is found [Stack Overflow](http://stackoverflow.com/questions/76134/how-do-i-reverse-project-2d-points-into-3d).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qXr4W.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Xs4BR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="679" PostHistoryTypeId="2" PostId="238" RevisionGUID="ed3d01c5-91b4-4149-97b0-f36a52dd3bba" CreationDate="2015-08-13T12:38:56.643" UserId="376" Text="In my torus light implementation(Unity3D) I use the same real-time method @JohnCalsbeek talks about above. Just treat it the same way you treat your regular point/spot light and calculate a single direction and distance.&#xD;&#xA;&#xD;&#xA;I use the torus distance equation from Inigo Quilez's site http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm and&#xD;&#xA;here's the function I made to get the direction to a torus&#xD;&#xA;&#xD;&#xA;    float3 torusDirection(float3 p) {&#xD;&#xA;	float3 torusRel;&#xD;&#xA;	torusRel.xz = normalize(p.xz-_TorusLocation.xz);&#xD;&#xA;	torusRel.y = 0;&#xD;&#xA;	&#xD;&#xA;	return -normalize(p-(TorusLocation+torusRel*TorusCenterRadius));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Overall I think it works well minus a few areas that look off where the torus loops around [![enter image description here][1]][1]. &#xD;&#xA;&#xD;&#xA;The specular hint is also off but @JohnCalsbeek 's point of modifying the roughness seems like it should fix that :). &#xD;&#xA;&#xD;&#xA;The hardest challenge for me with the light right now is making a forward shader that supports different kinds of area lights and multiple lights. I don't know how I would do this besides just having a whole bunch of shader properties for all the different lights though. Currently I apply the light as a deferred pass so it only works with opaque objects but soon I'll need to make a forward version for transparent objects. That's the real challenge I think, getting multiple area lights in a forward shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And here's a Shadertoy demo of a torus light I made to test mine, its based off of BeyondTheStatics shape light demo https://www.shadertoy.com/view/MllSWS&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gBzMT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="682" PostHistoryTypeId="5" PostId="229" RevisionGUID="4bfd58ac-17d1-47d6-9279-15959785f2c7" CreationDate="2015-08-13T18:55:35.500" UserId="377" Comment="added 216 characters in body" Text="I believe it's where you batch it and do a block of pixels at once, or a &quot;tile&quot;. &#xD;&#xA;&#xD;&#xA;This means calculating the final color for multiple pixels at a time. Imagine breaking up your window into squares of pixels, usually around 4x4, 16x16, or some other nice power of two and then working through them.&#xD;&#xA;&#xD;&#xA;This causes speed boosts for lots of different reasons, depending on your implementation and hardware. If you can, check out Ingo Wald's PhD thesis about real time raytracing, he makes a lot of references to batching to get speed using things like AVX (advanced vectoring extensions) in the processor. These provide speed boosts when you calculate the color for a certain amount of similar pixels. It's all cool and definitely worth looking into, and you can read more here: https://en.wikipedia.org/wiki/Advanced_Vector_Extensions&#xD;&#xA;&#xD;&#xA;Basically you represent similar data for similar pixels using a vector of floats and do the same calculations to all at once, saving cycles. Picture Bart Simpson writing out the same words on the chalkboard all at once instead of line-by-line in the Simpsons opening :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also when doing real time raytracing, you may be using the graphics card and sending all the data over the bus is a large bottleneck. You don't want to send all the data over to the card to calculate the value of only one pixel because of the bus overhead - so you want to send a reasonable amount of data to chew on while you work on getting the next chunk ready.&#xD;&#xA;&#xD;&#xA;So, to me at least, &quot;tiled&quot; raytracing is just &quot;batched&quot; raytracing.&#xD;&#xA;&#xD;&#xA;I hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="683" PostHistoryTypeId="2" PostId="239" RevisionGUID="044de63e-2f52-43fe-a371-6fcb87fa4c7d" CreationDate="2015-08-13T18:55:38.310" UserId="158" Text="Given an arbitrary triangle mesh, is it possible to automatically generate a UV mapping for it, and if so, how is it done?" ContentLicense="CC BY-SA 3.0" />
  <row Id="684" PostHistoryTypeId="1" PostId="239" RevisionGUID="044de63e-2f52-43fe-a371-6fcb87fa4c7d" CreationDate="2015-08-13T18:55:38.310" UserId="158" Text="Automatic generation of UV maps" ContentLicense="CC BY-SA 3.0" />
  <row Id="685" PostHistoryTypeId="3" PostId="239" RevisionGUID="044de63e-2f52-43fe-a371-6fcb87fa4c7d" CreationDate="2015-08-13T18:55:38.310" UserId="158" Text="|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="686" PostHistoryTypeId="5" PostId="229" RevisionGUID="400dc5ea-9ba4-4bc8-8b67-57ed02079baa" CreationDate="2015-08-13T19:05:22.927" UserId="377" Comment="added 2 characters in body" Text="I believe it's where you batch it and do a block of pixels at once, or a &quot;tile&quot;. &#xD;&#xA;&#xD;&#xA;This means calculating the final color for multiple pixels at a time. Imagine breaking up your window of pixels into squares containing the pixels, usually around 2x2 pixels per square. Then simply work through them.&#xD;&#xA;&#xD;&#xA;This causes speed boosts for lots of different reasons, depending on your implementation and hardware. If you can, check out Ingo Wald's PhD thesis about real time raytracing, he makes a lot of references to batching to get speed using things like AVX (advanced vectoring extensions) in the processor. These provide speed boosts when you calculate the color for a certain amount of similar pixels. It's all cool and definitely worth looking into, and you can read more here: https://en.wikipedia.org/wiki/Advanced_Vector_Extensions&#xD;&#xA;&#xD;&#xA;Basically you represent similar data for similar pixels using a vector of floats and do the same calculations to all at once, saving cycles. Picture Bart Simpson writing out the same words on the chalkboard all at once instead of line-by-line in the Simpsons opening :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also when doing real time raytracing, you may be using the graphics card and sending all the data over the bus is a large bottleneck. You don't want to send all the data over to the card to calculate the value of only one pixel because of the bus overhead - so you want to send a reasonable amount of data to chew on while you work on getting the next chunk ready. &#xD;&#xA;&#xD;&#xA;So, to me at least, &quot;tiled&quot; raytracing is just &quot;batched&quot; raytracing.&#xD;&#xA;&#xD;&#xA;I hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="687" PostHistoryTypeId="2" PostId="240" RevisionGUID="b67e8784-b108-4a7c-86e1-d692ea765e80" CreationDate="2015-08-13T19:10:59.400" UserId="310" Text="Short answer: Yes, but it won't be pretty.&#xA;&#xA;Explaination: While there *are* [algorithms](http://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Create-UVs--Automatic-Mapping-htm.html) to automagically UV map polygon soup, the mapping probably wont be ideal. UV mapping is an art really. Choosing where to hide the seams and where to put them to limit stretching and optimize texture space.&#xA;&#xA;That said, there *are* lots of tools that can make the process a heck of a lot easier to do UV mapping manually. For example: http://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Create-UVs--Automatic-Mapping-htm.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="688" PostHistoryTypeId="2" PostId="241" RevisionGUID="17f38a68-261e-4fef-ab2a-c69d076927cd" CreationDate="2015-08-13T19:20:21.843" UserId="38" Text="In chromatography charts the CMYK color space is usually four sided. Ive lately had to read quite a few charts and it suddenly dawned to me that I don't really understand why. It has just not been something I've needed to think about until now.&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A sample CIE31 chromatography graph shown the spaces\*.&#xD;&#xA;&#xD;&#xA;One of working hypotheses is that it is actually a trianglee. This triangle just clips for some reason. But there might be other reasons such as non-ideality of the color primaries, or bad plane. So why is it squarish.&#xD;&#xA;&#xD;&#xA;\* This image is not so clearly a polygon, like its usually depicted as, but its the best one I had at hand.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pfP8P.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="689" PostHistoryTypeId="1" PostId="241" RevisionGUID="17f38a68-261e-4fef-ab2a-c69d076927cd" CreationDate="2015-08-13T19:20:21.843" UserId="38" Text="Why is the CMYK space four sided in chromatography charts" ContentLicense="CC BY-SA 3.0" />
  <row Id="690" PostHistoryTypeId="3" PostId="241" RevisionGUID="17f38a68-261e-4fef-ab2a-c69d076927cd" CreationDate="2015-08-13T19:20:21.843" UserId="38" Text="|color|color-management|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="691" PostHistoryTypeId="5" PostId="241" RevisionGUID="fe2f7ed5-bdd9-43bb-80ba-4e5c3a1f96af" CreationDate="2015-08-13T19:59:48.217" UserId="48" Comment="grammar, chromaticity (chromatography is something else)" Text="In chromaticity charts the CMYK color space is usually four-sided. I've lately had to read quite a few charts and it suddenly dawned to me that I don't really understand why. It has just not been something I've needed to think about until now.&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A sample CIE31 chromaticity graph showing the spaces\*.&#xD;&#xA;&#xD;&#xA;One of my working hypotheses is that it is actually a triangle. This triangle just clips for some reason. But there might be other reasons such as non-ideality of the color primaries, or bad plane. So why is it squarish?&#xD;&#xA;&#xD;&#xA;\* This image is not so clearly a polygon, like it's usually depicted as, but it's the best one I had at hand.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pfP8P.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="692" PostHistoryTypeId="4" PostId="241" RevisionGUID="fe2f7ed5-bdd9-43bb-80ba-4e5c3a1f96af" CreationDate="2015-08-13T19:59:48.217" UserId="48" Comment="grammar, chromaticity (chromatography is something else)" Text="Why is the CMYK space four sided in chromaticity charts" ContentLicense="CC BY-SA 3.0" />
  <row Id="693" PostHistoryTypeId="5" PostId="238" RevisionGUID="0059b1bc-7b01-4e63-ac28-25bb9bb91b27" CreationDate="2015-08-13T20:00:08.343" UserId="376" Comment="added 53 characters in body" Text="In my torus light implementation(Unity3D) I use the same real-time method @JohnCalsbeek talks about above(http://computergraphics.stackexchange.com/a/232/376). Just treat it the same way you treat your regular point/spot light and calculate a single direction and distance.&#xD;&#xA;&#xD;&#xA;I use the torus distance equation from Inigo Quilez's site http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm and&#xD;&#xA;here's the function I made to get the direction to a torus&#xD;&#xA;&#xD;&#xA;    float3 torusDirection(float3 p) {&#xD;&#xA;	float3 torusRel;&#xD;&#xA;	torusRel.xz = normalize(p.xz-_TorusLocation.xz);&#xD;&#xA;	torusRel.y = 0;&#xD;&#xA;	&#xD;&#xA;	return -normalize(p-(TorusLocation+torusRel*TorusCenterRadius));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Overall I think it works well minus a few areas that look off where the torus loops around [![enter image description here][1]][1]. &#xD;&#xA;&#xD;&#xA;The specular hint is also off but @JohnCalsbeek 's point of modifying the roughness seems like it should fix that :). &#xD;&#xA;&#xD;&#xA;The hardest challenge for me with the light right now is making a forward shader that supports different kinds of area lights and multiple lights. I don't know how I would do this besides just having a whole bunch of shader properties for all the different lights though. Currently I apply the light as a deferred pass so it only works with opaque objects but soon I'll need to make a forward version for transparent objects. That's the real challenge I think, getting multiple area lights in a forward shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And here's a Shadertoy demo of a torus light I made to test mine, its based off of BeyondTheStatics shape light demo https://www.shadertoy.com/view/MllSWS&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gBzMT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="694" PostHistoryTypeId="5" PostId="238" RevisionGUID="1d902d55-de1d-40c6-abe2-a4908b8dc635" CreationDate="2015-08-13T20:48:19.837" UserId="231" Comment="Hide bare URLs for readability" Text="In my torus light implementation(Unity3D) I use the same real-time method [described in @JohnCalsbeek's answer](http://computergraphics.stackexchange.com/a/232/376). Just treat it the same way you treat your regular point/spot light and calculate a single direction and distance.&#xD;&#xA;&#xD;&#xA;I use the torus distance equation from [Inigo Quilez's site](http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) and&#xD;&#xA;here's the function I made to get the direction to a torus&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    float3 torusDirection(float3 p) {&#xD;&#xA;	float3 torusRel;&#xD;&#xA;	torusRel.xz = normalize(p.xz-_TorusLocation.xz);&#xD;&#xA;	torusRel.y = 0;&#xD;&#xA;	&#xD;&#xA;	return -normalize(p-(TorusLocation+torusRel*TorusCenterRadius));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Overall I think it works well minus a few areas that look off where the torus loops around [![Example scene lit by a torus][1]][1]. &#xD;&#xA;&#xD;&#xA;The specular hint is also off but @JohnCalsbeek's point of modifying the roughness seems like it should fix that :). &#xD;&#xA;&#xD;&#xA;The hardest challenge for me with the light right now is making a forward shader that supports different kinds of area lights and multiple lights. I don't know how I would do this besides just having a whole bunch of shader properties for all the different lights though. Currently I apply the light as a deferred pass so it only works with opaque objects but soon I'll need to make a forward version for transparent objects. That's the real challenge I think, getting multiple area lights in a forward shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And here's a [Shadertoy demo](https://www.shadertoy.com/view/MllSWS) of a torus light I made to test mine, its based off of BeyondTheStatics shape light demo.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gBzMT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="695" PostHistoryTypeId="2" PostId="242" RevisionGUID="1702cb5d-ae92-4a2b-a5a6-79947f4d26ff" CreationDate="2015-08-13T21:08:56.523" UserId="158" Text="There are two aspects to this:&#xD;&#xA;&#xD;&#xA;1. The traditional chromaticity graph is actually a two-dimensional slice of a three-dimensional volume.  The slice usually used is one that matches up (more or less) to the fully-saturated primaries of an RGB-based colorspace; the full RGB colorspace is a tetrahedron.&#xD;&#xA;&#xD;&#xA;2. CMYK is a four-primary colorspace, with primaries that are not linearly independent.  This makes the full volume a complex shape.  Further, at least one (black) and possibly all four of the primaries don't lie on the plane of the 2D chromaticity graph.&#xD;&#xA;&#xD;&#xA;The CMYK space is four-sided because it's a 2D slice of a complex 3D shape that (probably) doesn't lie on any of the surfaces of that shape." ContentLicense="CC BY-SA 3.0" />
  <row Id="696" PostHistoryTypeId="5" PostId="240" RevisionGUID="d02b575c-f1c5-4f1f-80d1-0b5833879641" CreationDate="2015-08-13T21:25:01.247" UserId="310" Comment="Fixed grammar" Text="Short answer: Yes, but it won't be pretty.&#xD;&#xA;&#xD;&#xA;Explaination: While there *are* [algorithms](http://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Create-UVs--Automatic-Mapping-htm.html) to automagically UV map polygon soup, the mapping probably wont be ideal. UV mapping is an art really. Choosing where to hide the seams and where to put them to limit stretching and optimize texture space.&#xD;&#xA;&#xD;&#xA;That said, there *are* lots of tools that can make manual UV mapping a heck of a lot easier. For example: http://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Create-UVs--Automatic-Mapping-htm.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="697" PostHistoryTypeId="2" PostId="243" RevisionGUID="52f9a25f-4f5b-4c98-b226-529fa3c3dbf0" CreationDate="2015-08-14T02:19:08.863" UserId="158" Text="The Gimp has two different options in how you can perform Gaussian blur: &quot;IIR&quot; and &quot;RLE&quot;.  What's the difference between them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="698" PostHistoryTypeId="1" PostId="243" RevisionGUID="52f9a25f-4f5b-4c98-b226-529fa3c3dbf0" CreationDate="2015-08-14T02:19:08.863" UserId="158" Text="Different types of Gaussian blur?" ContentLicense="CC BY-SA 3.0" />
  <row Id="699" PostHistoryTypeId="3" PostId="243" RevisionGUID="52f9a25f-4f5b-4c98-b226-529fa3c3dbf0" CreationDate="2015-08-14T02:19:08.863" UserId="158" Text="|2d|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="701" PostHistoryTypeId="2" PostId="244" RevisionGUID="39b04d7c-4b44-4cb9-a65e-8d0a75af5bd3" CreationDate="2015-08-14T05:31:08.123" UserId="48" Text="There are two different common meanings of &quot;light probe&quot; that I'm aware of. Both of them represent the light around a single point in a scene, i.e. what you would see around you in all directions if you were shrunk down to a tiny size and stood at that point.&#xD;&#xA;&#xD;&#xA;One meaning is a spherical harmonic representation of the light around a point.  [Spherical harmonics](https://en.wikipedia.org/wiki/Spherical_harmonics) are a collection of functions defined over a spherical domain, which are analogous to sine waves that oscillate a certain number of times around the equator and from pole to pole on the sphere.&#xD;&#xA;&#xD;&#xA;Spherical harmonics can be used to create a smooth, low-res approximation of any spherical function, by scaling and adding together some number of spherical harmonics&amp;mdash;usually 4 (known as linear, first-degree, or one-band SH) or 9 (called quadratic, second-degree, or two-band SH). This is very compact because you only have to store the scaling factors. For instance, for quadratic SH with RGB data, you only need 9*3 = 27 values per probe. So SH makes a very compact, but also necessarily very soft and blurry, representation of the light around a point. This is suitable for diffuse lighting, and perhaps specular with a high roughness.&#xD;&#xA;&#xD;&#xA;This screenshot from [Simon's Tech Blog](http://simonstechblog.blogspot.com/2014_10_01_archive.html) shows an array of SH light probes spaced throughout a scene, each one showing the indirect lighting received at that point:&#xD;&#xA;&#xD;&#xA;[![SH light probe array][1]][1]&#xD;&#xA;&#xD;&#xA;The other currently common meaning of &quot;light probe&quot; is an environment cube-map whose mip levels have been pre-blurred to different extends so it can be used for specular lighting with varying levels of roughness. This image from [Seb Lagarde's blog](https://seblagarde.wordpress.com/2011/08/17/hello-world/) shows the basic idea:&#xD;&#xA;&#xD;&#xA;[![Prefiltered cubemap mip levels][2]][2]&#xD;&#xA;&#xD;&#xA;The higher-resolution mips (toward the left) are used for highly polished surfaces where you need a detailed reflected image. Toward the right, the lower-res mip levels are increasingly blurred, and are used for reflections from rougher surfaces. In a shader, when sampling this cubemap, you can calculate your requested mip level based on the material roughness, and take advantage of the trilinear filtering hardware.&#xD;&#xA;&#xD;&#xA;Both of these types of light probes are used in real-time graphics to approximate indirect lighting. While direct lighting can be calculated in real-time (or at least approximated well for area lights), indirect lighting is usually still baked in an offline preprocess due to its complexity and computational overhead.&#xD;&#xA;&#xD;&#xA;Traditionally, the result of the baking process would be lightmaps, but lightmaps only work for diffuse lighting on static geometry, and they take up a lot of memory besides. Baking a bunch of SH light probes (you can afford a lot of them because they're very compact), plus a sparser sprinkling of cubemap light probes, allows you to get decent diffuse and specular indirect lighting on both static and dynamic objects. They're a popular option in games today.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xgMCf.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/y2ICS.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="703" PostHistoryTypeId="5" PostId="150" RevisionGUID="507c00df-e2d7-456c-ad5a-6552df4e6be5" CreationDate="2015-08-14T07:36:33.963" UserId="38" Comment="deleted 54 characters in body" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;### How to do it analytically&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Analytic scene][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Suppose you have this scene, exploded view on right&#xD;&#xA;&#xD;&#xA;Now you can not just do this analytically, each piece separately and then merge the data. Because it results in wrong data. See alpha blending would let the blue shine trough the gaps if you did so.&#xD;&#xA;&#xD;&#xA;What you have to so is split the scene up so that each shape eliminates what is under the other:&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: You need to cut the underlying surfaces.&#xD;&#xA;&#xD;&#xA;Now if everything is opaque then this is all straight forward. just calculate the area of each piece and multiply that by color and sum them together. Now you can use something like [this](http://stackoverflow.com/questions/10039679/how-can-i-calculate-the-area-of-a-bezier-curve).&#xD;&#xA;&#xD;&#xA;This all breaks down if your individual shapes aren't opaque off course but even that can be done at some level.&#xD;&#xA;&#xD;&#xA;Remember:&#xD;&#xA;&#xD;&#xA;* AA calculation need to be done in linear color space, and converted back to use space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/Tfs4k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CihEg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rJu1X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="704" PostHistoryTypeId="2" PostId="245" RevisionGUID="f375ee79-0a4a-4a53-a820-aaa41c5d3743" CreationDate="2015-08-14T17:42:22.480" UserId="56" Text="I've played with real time raytracing (and raymarching etc) quite a bit, but haven't spent that much time on non real time raytracing - for higher quality images or for pre-rendering videos and the like.&#xD;&#xA;&#xD;&#xA;I know one common technique to improve image quality in the non real time case is to just cast A LOT more rays per pixel and average the results.&#xD;&#xA;&#xD;&#xA;Are there any other techniques which stand out as good ways to improve image quality in the non real time case, over what you would normally do in the real time case?" ContentLicense="CC BY-SA 3.0" />
  <row Id="705" PostHistoryTypeId="1" PostId="245" RevisionGUID="f375ee79-0a4a-4a53-a820-aaa41c5d3743" CreationDate="2015-08-14T17:42:22.480" UserId="56" Text="Non Real Time Raytracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="706" PostHistoryTypeId="3" PostId="245" RevisionGUID="f375ee79-0a4a-4a53-a820-aaa41c5d3743" CreationDate="2015-08-14T17:42:22.480" UserId="56" Text="|raytracing|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="707" PostHistoryTypeId="2" PostId="246" RevisionGUID="d9d90e9a-a022-4c5c-b9a0-b58745951afa" CreationDate="2015-08-14T17:45:21.800" UserId="34" Text="I have written a small path-tracer after learning and experimenting on [smallpt][1].&#xD;&#xA;&#xD;&#xA;The only thing that I did not write (and understood) myself is how the initial rays are computed and fired from the camera. I got the principle right, but I'm looking for some resources describing how to:&#xD;&#xA;&#xD;&#xA;- Compute the initial direction of rays&#xD;&#xA;- Modelize a real lens (as opposed to pinhole camera), supposedly allowing effects like depth of field ?&#xD;&#xA;&#xD;&#xA;State of the art maths and physics are not required, but OK if explained thoroughly.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.kevinbeason.com/smallpt/" ContentLicense="CC BY-SA 3.0" />
  <row Id="708" PostHistoryTypeId="1" PostId="246" RevisionGUID="d9d90e9a-a022-4c5c-b9a0-b58745951afa" CreationDate="2015-08-14T17:45:21.800" UserId="34" Text="How to build a decent lens/camera objective model for path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="709" PostHistoryTypeId="3" PostId="246" RevisionGUID="d9d90e9a-a022-4c5c-b9a0-b58745951afa" CreationDate="2015-08-14T17:45:21.800" UserId="34" Text="|raytracing|lighting|monte-carlo|physically-based|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="710" PostHistoryTypeId="2" PostId="247" RevisionGUID="808e8c7f-1e9b-431e-9468-17364340a53a" CreationDate="2015-08-14T17:58:47.153" UserId="158" Text="One of the big ones is the use of [constructive solid geometry][1] rather than triangle meshes.  Ray-triangle intersections are faster than almost any other ray-shape intersection, but it takes huge numbers of triangles to approximate the surface of a cylinder or torus, not to mention some of the really exotic shapes such as julia fractals or generalized parametric functions that some renderers support.&#xD;&#xA;&#xD;&#xA;Another is the use of render-time [photon mapping][2] and [diffuse interreflection][3] calculations: this lets you get accurate lighting effects in a changing scene.  In realtime raytracing, these are too expensive to compute, so either light sources and major geometry elements are forced to be stationary (to permit pre-calculation), or the effects are omitted entirely.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Constructive_solid_geometry&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photon_mapping&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Diffuse_reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="711" PostHistoryTypeId="2" PostId="248" RevisionGUID="01aaa944-5c20-45a6-b234-32fdaf34ec08" CreationDate="2015-08-14T21:24:23.393" UserId="48" Text="The next step up from a pinhole camera model is a [thin lens](https://en.wikipedia.org/wiki/Thin_lens) model, where we model the lens as being an infinitely thin disc. This is still an idealization that pretty far from modeling a real camera, but it will give you basic depth of field effects.&#xD;&#xA;&#xD;&#xA;[![Thin lens model][1]][1]&#xD;&#xA;&#xD;&#xA;The image above, from [panohelp.com](http://www.panohelp.com/thinlensformula.html), shows the basic idea. For each point on the image, there are multiple rays arriving at that image point, via every point on the 2D lens surface. Therefore, generating an image like this using Monte Carlo will require picking, for each ray, both a 2D sample point on the image plane and an independent 2D sample point on the lens surface.&#xD;&#xA;&#xD;&#xA;The user-facing parameters to set will be the lens radius (as a physical radius in scene units), which controls how shallow the focus range is (larger lens = shallower focus range), and the distance at which you want objects to be in focus.&#xD;&#xA;&#xD;&#xA;To generate eye rays into the scene, you can calculate the position and direction of rays leaving the lens surface; in this model there's no need to explicitly simulate the image plane and the refraction through the lens.  Basically, think of the lens as centered at the camera position and oriented to face the camera direction.&#xD;&#xA;&#xD;&#xA;Based on the image location, construct a ray from the camera position (lens center) into the scene, just as you would in the pinhole model; then find its intersection with the focal plane. That's where all the rays from that image location should converge.  Now you can offset the starting point of the ray to a randomly chosen point on the lens, and set its direction to be toward the convergence point.&#xD;&#xA;&#xD;&#xA;You can generalize this a bit by allowing the focal plane to be something other than a plane, or the lens to be something other than a circular disc, and following the same process. That can produce some interesting if not-quite-physical effects.  It's also possible to go beyond this simple model with a more physically realistic simulation of a camera's lens elements&amp;mdash;but that's beyond my expertise.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7QOTx.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="712" PostHistoryTypeId="2" PostId="249" RevisionGUID="f5bbf38c-fd3b-4b1a-b366-aa6d4e370f39" CreationDate="2015-08-14T21:40:51.403" UserId="231" Text="There are various different types of limitation to take into consideration.&#xD;&#xA;&#xD;&#xA;## Effects for which the path of a ray is dependent on its wavelength&#xD;&#xA;&#xD;&#xA;These are a class of effects for which spectral rendering is required, and a number of interesting examples have already been given in [Benedikt Bitterli's answer]. A simple example is a prism splitting white light into a spectrum, giving rainbow colours. Rays of different wavelength are refracted by different angles as they pass through the prism, resulting in the light striking the wall behind the prism being split into its constituent colours.&#xD;&#xA;&#xD;&#xA;This means that in real life, shining monochromatic yellow light through a prism will result in yellow light coming out, but shining a mixture of red and green light that approximates yellow will result in separate red and green light emerging. When rendering using only 3 primary colours, white light will split into only those three colours, giving rainbow effects that look discontinuous, and monochromatic light that should not split at all will split into its approximating primary colour components. The splitting of white light can be improved by using a larger number of primary colours, but this will still give discontinuities close up, and the results for monochromatic light will still be split, albeit more narrowly. For accurate results a continuous spectrum must be sampled, with wavelengths distributed according to the light source being simulated.&#xD;&#xA;&#xD;&#xA;## Surface effects that cannot be captured in a single still image&#xD;&#xA;&#xD;&#xA;[Iridescence], for example, shows a different colour to each eye so that a still image will not look the same as the original object. There are many everyday examples that you might not notice at first. Many common birds have iridescent feathers even though they appear black or grey from a distance. Close up they are surprisingly colourful. &#xD;&#xA;&#xD;&#xA;A renderer using only 3 primary colours will not be able to produce the spreading of light based on wavelength required for this effect. A spectral renderer can simulate the spreading correctly, but the full effect still cannot be captured in a single image. Even a 2d photograph cannot capture this correctly, whereas a 3d photograph of an iridescent object will give that shimmering effect as the photographs corresponding to left and right eyes will be coloured differently. This is a limitation of 2d images rather than the RGB colour space itself. However, even in a 3d image there will be colours in the iridescent object that are not displayed correctly, due to the inability of RGB to display monochromatic colours as described below.&#xD;&#xA;&#xD;&#xA;## Colours that the human eye can detect that cannot be displayed in RGB&#xD;&#xA;&#xD;&#xA;RGB was historically device dependent and therefore unreliable between platforms. There are device independent perceptually uniform improvements such as the colour space [Lab], but these are still trichromatic (having 3 components). It is not immediately obvious why three components is insufficient to display all the colours that can be perceived by a trichromatic eye, but [this paper] explains it well, and accessibly. From page 7:&#xD;&#xA;&#xD;&#xA;&gt; For example, using a modern laser-display system with monochromatic primaries at 635 nm (red), 532 nm (green), and 447 nm (blue), lets see if we can simulate the perception of a monochromatic light at 580 nm (an orange color). Since the monochromatic orange stimulus excites the greenish and reddish cones, a contribution is required by both the green and red primaries, while no contribution is required from the blue primary. The problem is that the green primary also excites the bluish cones, making it impossible to exactly replicate the orange stimulus&#xD;&#xA;&#xD;&#xA;The diagram of human eye cones sensitivities (also on page 7) shows how wide the overlap is and helps to visualise this explanation. I've included a similar graph from Wikipedia here: (click on the graph for the Wikipedia location)&#xD;&#xA;&#xD;&#xA;[![Graph of the sensitivities of the 3 different cones in the human eye][cones sensitivities graph]][cones sensitivities wikipedia location]&#xD;&#xA;&#xD;&#xA;In short, the overlap between the range of colours that can be picked up by each of the three different cones (colour sensors) of the human eye means that a monochromatic colour can be distinguished from an approximating mixture of primary colours, and therefore mixing primary colours can never accurately display all monochromatic colours.&#xD;&#xA;&#xD;&#xA;This difference is not usually noticeable in everyday life as most of our surroundings emit or reflect light across a wide range of frequencies rather than single monochromatic colours. However, a notable exception is sodium lamps. If you live in a part of the world that uses these yellow-orange street lights, the light emitted is monochromatic and will look subtly different from a printed photograph or an image on a screen. The wavelength of sodium light happens to be the 580 nm from the example quoted above. If you don't live somewhere that has sodium street lights, you can see the same single wavelength light by sprinkling finely crushed table salt (sodium chloride) over a flame. The scintillating yellow points of light cannot be accurately captured on film or displayed on a screen. Whatever three primary colours you choose, there will always be a range of monochromatic colours that cannot be displayed.&#xD;&#xA;&#xD;&#xA;Note that this limitation applies equally to mixing 3 primary colours of paint, using 3 photoreactive chemicals on a camera film, or taking a photograph with a digital camera with 3 different colour sensors, or a single sensor with 3 different primary colour filters. It isn't just a digital problem, and isn't just restricted to the RGB colour space. Even the improvements introduced by the Lab colour space and its variants cannot recover the missing colours.&#xD;&#xA;&#xD;&#xA;# Miscellaneous effects&#xD;&#xA;&#xD;&#xA;### Multiple diffuse reflections (colour bleeding)&#xD;&#xA;&#xD;&#xA;If a brightly coloured matt surface is near a white matt surface, the white surface will show some of the colour of the other surface. This can be modeled reasonably well using purely red, green and blue components. The same combination of red, green and blue that gave the colour of the coloured surface can reflect off the white surface and show some of that colour again. However, this only works if the second surface is white. If the second surface is also coloured, then the colour bleeding will be inaccurate, in some cases drastically.&#xD;&#xA;&#xD;&#xA;Imagine two surfaces that look a similar colour. One reflects a narrow range of wavelengths around yellow. The other reflects a wide range of wavelengths between red and green, and as a result also looks yellow. In real life, the light showing on one surface due to the other will not be symmetrical. Most of the light reaching the wide wavelength range surface from the other will be reflected again, as the narrow range of incoming wavelengths are all within the wider range. However, most of the light reaching the narrow wavelength range surface from the other will be outside the narrow range, and will not be reflected. In an RGB renderer, both surfaces will be modelled as a mixture of monochromatic red and monochromatic green, giving no difference in reflected light.&#xD;&#xA;&#xD;&#xA;This is an extreme example where the difference will be instantly noticeable to the eye, but there will be at least a subtle difference in most images that include colour bleeding.&#xD;&#xA;&#xD;&#xA;### Materials that absorb one wavelength and emit another&#xD;&#xA;&#xD;&#xA;[joojaa's answer] describes the absorption of ultraviolet light by snow, to be re-emitted as visible light. I hadn't heard of this happening with snow before (and frustratingly I've been unable to find any evidence to support it - although it would explain why snow is &quot;whiter than white&quot;). However, there is plenty of evidence of it happening with a wide range of other materials, some of which are added to clothes washing detergents and paper, to give extra bright whites. This allows the total visible light outgoing from a surface to be more than the total visible light received by that surface, which again is not modelled well using only RGB. If you want to read more about it, the term to search for is [Fluorescence].&#xD;&#xA;&#xD;&#xA;### Eyes with more than 3 primary colours&#xD;&#xA;&#xD;&#xA;There are animals that have more than 3 types of cones in their eyes, allowing them to perceive more than 3 primary colours. For example, many birds, insects and fish are [tetrachromats], perceiving four primary colours. Some are even [pentachromats], perceiving five. The range of colours that such creatures can see dwarfs the range displayable using only RGB. Far beyond them is the [mantis shrimp], which is a dodecachromat, seeing colours based on 12 different cones. None of these animals would be satisfied by an RGB display.&#xD;&#xA;&#xD;&#xA;But more seriously, even for images intended for human eyes, there are believed to be [human tetrachromats] who see in 4 primary colours, and possibly some who see as many as 5 or 6. At present, such people don't seem to be present in sufficient numbers to make displays with more than 3 primary colours commercially viable, but if in future it becomes easier to identify how many primary colours a person can see, this may become an attractive trait leading to it spreading throughout the population in future generations. So if you want your great grandchildren to appreciate your work you may need to make it compatible with a hexachromatic monitor...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*Not really relevant to this question, but related: If you want to see colours that are not available in either the real world* **or** *RGB images, have a look at [Chimerical Colours]...*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Benedikt Bitterli's answer]: http://computergraphics.stackexchange.com/a/204/231&#xD;&#xA;&#xD;&#xA;  [Iridescence]: http://en.wikipedia.org/wiki/Iridescence&#xD;&#xA;&#xD;&#xA;  [Lab]: http://en.wikipedia.org/wiki/Lab_color_space&#xD;&#xA;&#xD;&#xA;  [this paper]: http://www.babelcolor.com/download/A%20review%20of%20RGB%20color%20spaces.pdf&#xD;&#xA;&#xD;&#xA;  [cones sensitivities graph]: https://upload.wikimedia.org/wikipedia/commons/1/1e/Cones_SMJ2_E.svg&#xD;&#xA;&#xD;&#xA;  [cones sensitivities wikipedia location]: https://en.wikipedia.org/wiki/Spectral_sensitivity#/media/File:Cones_SMJ2_E.svg&#xD;&#xA;&#xD;&#xA;  [joojaa's answer]: http://computergraphics.stackexchange.com/a/207/231&#xD;&#xA;&#xD;&#xA;  [Fluorescence]: https://en.wikipedia.org/wiki/Fluorescence&#xD;&#xA;&#xD;&#xA;  [tetrachromats]: https://en.wikipedia.org/wiki/Tetrachromacy&#xD;&#xA;&#xD;&#xA;  [pentachromats]: https://en.wikipedia.org/wiki/Pentachromacy&#xD;&#xA;&#xD;&#xA;  [mantis shrimp]: https://en.wikipedia.org/wiki/Mantis_shrimp#Eyes&#xD;&#xA;&#xD;&#xA;  [human tetrachromats]:https://en.wikipedia.org/wiki/Tetrachromacy#Human_tetrachromats&#xD;&#xA;&#xD;&#xA;  [Chimerical Colours]: https://en.wikipedia.org/wiki/Impossible_color#Chimerical_colors&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="713" PostHistoryTypeId="2" PostId="250" RevisionGUID="8dafaa46-4c44-43c0-8e7a-e2a9eaca73a5" CreationDate="2015-08-14T22:11:19.027" UserId="231" Text="I've seen in several places that making Perlin noise loop seamlessly requires calculating it twice in slightly different ways, and summing the two results.&#xD;&#xA;&#xD;&#xA;[This Perlin noise math FAQ] gives a formula:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Floop(x, y, z) = ( (t - z) * F(x, y, z) + (z) * F(x, y, z - t) ) / (t)][formula image]][formula link]&#xD;&#xA;&#xD;&#xA;to make a noise function F loop in the z direction. It also mentions that extending this, to loop in 2 dimensions would take 4 evaluations of F and to loop in 3 dimensions would take 8 evaluations of F.&#xD;&#xA;&#xD;&#xA;I understand that this gives a seamless join between tiles that is not only continuous but continously differentiable, but I intuitively expect that to be the case if the noise function is simply evaluated once with grid points reduced modulo the required tile size. If the noise function is only ever based on the immediately surrounding grid points (4 for 2D noise, 8 for 3D noise) then surely just using the leftmost grid points when the point to calculate gets past the right hand edge of the tile will give the same quality of noise as between any other grid points?&#xD;&#xA;&#xD;&#xA;Since I've seen this multiple calculation approach in several places I assume it must have some advantage, but I'm struggling to see the disadvantage with simply wrapping the grid points back to the start when they get too big. What am I missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [This Perlin noise math FAQ]: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html#loop&#xD;&#xA;&#xD;&#xA;  [formula image]: http://mathurl.com/ornj2oq.png&#xD;&#xA;&#xD;&#xA;  [formula link]: http://mathurl.com/ornj2oq" ContentLicense="CC BY-SA 3.0" />
  <row Id="714" PostHistoryTypeId="1" PostId="250" RevisionGUID="8dafaa46-4c44-43c0-8e7a-e2a9eaca73a5" CreationDate="2015-08-14T22:11:19.027" UserId="231" Text="Why is it twice as expensive to make a noise function that can be tiled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="715" PostHistoryTypeId="3" PostId="250" RevisionGUID="8dafaa46-4c44-43c0-8e7a-e2a9eaca73a5" CreationDate="2015-08-14T22:11:19.027" UserId="231" Text="|algorithm|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="719" PostHistoryTypeId="5" PostId="158" RevisionGUID="a7eb5948-2e82-4f44-8b4e-ca5a4e008249" CreationDate="2015-08-14T22:40:35.007" UserId="110" Comment="added 2 characters in body" Text="*Sorry for the bad quality of my answer. I do not have access to a computer currently and editing from my phone is not a straightforward task. In particular I would love to be able to paste images.*  &#xD;&#xA;  &#xD;&#xA;I would say that the main challenges of simulating hair are:  &#xD;&#xA;&#xD;&#xA; - replicating their very specific reaction to lighting (as a material)  &#xD;&#xA; - replicating their volumetric property (as a geometry)  &#xD;&#xA; - animating them in a realistic manner  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;---&#xD;&#xA;  &#xD;&#xA;Here is a list of references I gathered on the subject, ordered chronologically *(mainly about the rendering part)*:  &#xD;&#xA;  &#xD;&#xA;1. JAMES T. KAJIYA, TIMOTHY L. KAY, [Rendering Fur With Three Dimensional Textures](https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf), 1989  &#xD;&#xA;1. JEROME LENGYEL, EMIL PRAUN, ADAM FINKELSTEIN, HUGUES HOPPE, [Real-Time Fur over Arbitrary Surfaces](http://research.microsoft.com/en-us/um/people/hoppe/fur.pdf), 2000  &#xD;&#xA;1. STEPHEN R. MARSCHNER, HENRIK WANN JENSEN, MIKE CAMMARANO, [Light Scattering from Human Hair Fibers](http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf), 2003  &#xD;&#xA;1. ARMIN BRUDERLIN, SUNIL HADAP, TAE-YONG KIM, NADIA MAGNENAT-THALMANN , ULRICH NEUMANN, YIZHOU YU, STEVE WORLEY, [Photorealistic Hair Modeling, Animation, and Rendering](http://www.graphics.stanford.edu/courses/cs448-05-winter/papers/course34.pdf), Siggraph 2003 Course  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://bookzz.org/book/487747/b3254e), ShaderX3, 2004  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairRendering.pdf), ATI / GDC 2004  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketch.pdf), ATI / Siggraph 2004  &#xD;&#xA;1. THORSTEN SCHEUERMANN, [Practical Real-Time Hair Rendering and Shading](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf), ATI / Siggraph 2004 (slides)  &#xD;&#xA;1. MARTIN KOSTER, JORG HABER, HANS-PETER SEIDEL, [Real-Time Rendering of Human Hair using Programmable Graphics Hardware](http://resources.mpi-inf.mpg.de/FAM/publ/cgi2004.pdf), 2004  &#xD;&#xA;1. HUBERT NGUYEN, WILLIAM DONNELLY, [Hair Animation and Rendering in the Nalu Demo](http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html), GPU Gems 2 (Chapter 23), 2005  &#xD;&#xA;1. LENA PETROVIC, MARK HENNE, JOHN ANDERSON, [Volumetric Methods for Simulation and Rendering of Hair](http://graphics.pixar.com/library/Hair/paper.pdf), Pixar 2006  &#xD;&#xA;1. CHRISTOPHE HERY, RAVI RAMAMOORTHI, [Importance Sampling of Reflections from Hair Fibers](http://graphics.pixar.com/library/ImportanceSamplingHair/paper.pdf), Pixar 2007  &#xD;&#xA;1. SARAH TARIQ, LOUIS BAVOIL, [Real-Time Hair Rendering on the GPU](http://www.nvidia.com/object/siggraph-2008-hair.html), Siggraph 2008. &#xD;&#xA;1. ARNO ZINKE, CEM YUKSEL, ANDREAS WEBER, JOHN KEYSER, [Dual Scattering Approximation for Fast Multiple Scattering in Hair](http://research.cs.tamu.edu/keyser/Papers/Siggraph08_dualscattering.pdf), Siggraph 2008  &#xD;&#xA;1. IMAN SADEGHI, HEATHER PRITCHETT, HENRIK WANN JENSEN, RASMUS TAMSTORF, [An Artist Friendly Hair Shading System](http://graphics.ucsd.edu/~henrik/papers/artist_hair.pdf), 2010  &#xD;&#xA;1. EUGENE D’EON, GUILLAUME FRANCOIS, MARTIN HILL, JOE LETTERI, JEAN-MARIE AUBRY, [An Energy-Conserving Hair Reflectance Model](http://www.eugenedeon.com/project/an-energy-conserving-hair-reflectance-model/), 2011  &#xD;&#xA;1. XUAN YU, JASON C. YANG, JUSTIN HENSLEY, TAKAHIRO HARADA, JINGYI YU, [A Framework for Rendering Complex Scattering Effects on Hair](http://www.eecis.udel.edu/~xyu/publications/frameworkhair124.pdf), 2012  &#xD;&#xA;1. JIAWEI OU, FENG XIE, PARASHAR KRISHNAMACHARI, FABIO PELLACINI, [ISHair: Importance Sampling for Hair Scattering](http://pellacini.di.uniroma1.it/publications/ishair12/ishair12-paper.pdf), 2012  &#xD;&#xA;1. SARAH INVERNIZZI, [On Physically Based Hair Rendering](http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/07/MSc_thesis_On_physically_based_hair_rendering.pdf), 2013  &#xD;&#xA;1. WOLFGANG ENGEL, [Hair Rendering in Tomb Raider](http://www.slideshare.net/WolfgangEngel/hair-intombraider-final), 2013  &#xD;&#xA;1. EUGENE D’EON, STEVE MARSCHNER, JOHANNES HANIKA, [Importance Sampling for Physically-Based Hair Fiber Models](https://cg.ivd.kit.edu/publications/pubhanika/2013_hairbrief.pdf), 2013  &#xD;&#xA;1. TIMOTHY MARTIN, WOLFGANG ENGEL, NICOLAS THIBIEROZ, JASON YANG, AND JASON LACROIX, [TressFX: Advanced Real-Time Hair Rendering](http://bookzz.org/book/2373940/c298ee), GPU Pro 5, 2015  &#xD;&#xA;1. LEONID PEKELIS, CHRISTOPHE HERY, RYUSUKE VILLEMIN, JUNYI LING, [A Data-Driven Light Scattering Model for Hair](http://graphics.pixar.com/library/DataDrivenHairScattering/paper.pdf), Pixar 2015  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;I did not read all of these material yet, but here is a little of what I remember (I am more interested by the real-time solutions) :&#xD;&#xA;  &#xD;&#xA;- Kajiya-kay laid the basis for realistic hair / fur rendering  &#xD;&#xA;- Marschner proposed an improved model, and noted that hair has two distinct specular highlights (one white due to direct reflection, the other colored and sparkling due to reflection inside of the hair fiber)  &#xD;&#xA;- Scheuermann proposed approximations to simulate the behaviour described by Marschner, approximations suited for real-time (using tricks such as two separate specular highlights, artist-designed specular offset and exponent, noise textures). He also proposed using three rendering passes (opaque, transparent back and front) of polygons to simulate the &quot;volumetric&quot; qualities of hair  &#xD;&#xA;- Most of the games I heard of seem to use Scheuermann approaches for hair shading. However, this is not an energy-conserving solution. Nevertheless, I think d'Eon attempts to fix this problem in the 2011 paper.  &#xD;&#xA;An other topic of interest is the use of tessellation, that has also been used recently to replace the polygonal approach and simulate hair strands individually.     &#xD;&#xA;  &#xD;&#xA;The offline rendering world attempts to solve more advanced challenges. I think most of them are described in the references above.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="720" PostHistoryTypeId="2" PostId="251" RevisionGUID="f13601ed-7fe0-49be-92f6-5f38a2bb5736" CreationDate="2015-08-15T00:14:29.170" UserId="192" Text="A good starting point is the classic paper [Using particles to sample and control implicit surfaces](http://dl.acm.org/citation.cfm?id=192227).&#xD;&#xA;&#xD;&#xA;A simple particle simulation described in the paper [Sampling implicit objects with physically-based particle systems&#xD;&#xA;](http://dx.doi.org/10.1016/0097-8493(96)00005-2) for curves works for surfaces as well; see [Dynamic Texture for Implicit Surfaces](http://www.visgraf.impa.br/Projects/dtexture/) for examples.&#xD;&#xA;&#xD;&#xA;For a more recent example, see [Shape and tone depiction for implicit surfaces](http://dx.doi.org/10.1016/j.cag.2010.09.017). " ContentLicense="CC BY-SA 3.0" />
  <row Id="722" PostHistoryTypeId="2" PostId="252" RevisionGUID="a136be5d-c554-46c2-9776-ca4884144dae" CreationDate="2015-08-15T05:55:52.820" UserId="48" Text="It's unfortunate that people commonly recommend this.  Blending between two (or four, etc.) translated copies of a noise function in that way is a pretty bad idea. Not only is it expensive, it doesn't even produce correct-looking results!&#xD;&#xA;&#xD;&#xA;![Perlin noise][1] ![Blended Perlin noise][2]&#xD;&#xA;&#xD;&#xA;On the left is some Perlin noise. On the right is two instances of Perlin noise, stacked and blended left-to-right.&#xD;&#xA;&#xD;&#xA;The difference is kind of subtle, but you can see that the second image has lower contrast in a vertical column running down the middle.  That's where it's a 50% blend between two different instances of the noise function. Such a blend doesn't look like the original noise function: it just looks like a muddy mess.&#xD;&#xA;&#xD;&#xA;OK, so it's not quite *that* bad just looking at the raw noise...but if you then do any nonlinear transformations on the image, the nonuniform contrast can cause issues. For instance, here are those images thresholded at 60%. (Think of generating islands in an ocean, for instance.)&#xD;&#xA;&#xD;&#xA;![Thresholded Perlin noise][3] ![Thresholded blended Perlin noise][4]&#xD;&#xA;&#xD;&#xA;Now you can plainly see how the image on the right has fewer, smaller white areas in the middle.&#xD;&#xA;&#xD;&#xA;Like you mentioned, for grid-based noise like Perlin, a better way is to tile the pseudorandom gradients at the grid points. That's easy and cheap to do, and then you can apply the interpolation algorithm to the gradients as usual (much like bilinear interpolation of a tiling texture). This produces tiling noise without any weird artifacts, because it works *with* the underlying noise algorithm rather than over the top of it. You can use a similar strategy with Worley noise (cellular noise) by tiling the random feature points it uses as a basis.&#xD;&#xA;&#xD;&#xA;With multiple octaves of noise it's not always so easy, though. If the relative scale between the octaves (aka &quot;lacunarity&quot;) isn't an integer or simple rational number, then you may not be able to find a convenient tiling point where all the octaves' grids match up. You could tile each octave independently, but the overall noise would still not be tilable in that case.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DgnQE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/949SB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/elyF1.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Micts.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="725" PostHistoryTypeId="2" PostId="253" RevisionGUID="7d33beeb-dbef-4fcf-90d8-1a8aee1e5067" CreationDate="2015-08-15T10:35:37.133" UserId="231" Text="From the [GIMP docs]:&#xD;&#xA;&#xD;&#xA;&gt; ### IIR&#xD;&#xA;&#xD;&#xA;&gt; IIR stands for “infinite impulse response”. This blur works best for large radius values and for images which are not computer generated.&#xD;&#xA;&#xD;&#xA;&gt; ### RLE&#xD;&#xA;&#xD;&#xA;&gt; RLE stands for “run-length encoding”. RLE Gaussian Blur is best used on computer-generated images or those with large areas of constant intensity.&#xD;&#xA;&#xD;&#xA;and also&#xD;&#xA;&#xD;&#xA;&gt; They both produce the same results, but each one can be faster in some cases. &#xD;&#xA;&#xD;&#xA;So the short answer is that IIR is optimised for photographs, and RLE is optimised for images with areas of flat colour.&#xD;&#xA;&#xD;&#xA;The claim seems to be that the only difference is the time taken to calculate the blur, and that the end results are identical. I haven't tested this, so if you need to rely on that claim you should test both and check for any differences in the results.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [GIMP docs]: http://docs.gimp.org/en/plug-in-gauss.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="726" PostHistoryTypeId="2" PostId="254" RevisionGUID="1ce4c3ad-14ff-46c2-b29e-3f0a35681776" CreationDate="2015-08-15T13:07:08.230" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="727" PostHistoryTypeId="2" PostId="255" RevisionGUID="aa01ff31-90b1-49f8-a253-c47734f3105a" CreationDate="2015-08-15T13:07:08.230" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="730" PostHistoryTypeId="2" PostId="256" RevisionGUID="9a8135ae-1cfb-4842-94b2-006771dad121" CreationDate="2015-08-15T18:33:42.943" UserId="56" Text="To make Gaussian blurring a 2d image faster, I know that you can do one axis and then the other.&#xD;&#xA;&#xD;&#xA;I'm wondering though, if i did two Gaussian blurs of size N, would that be the same mathematically as doing one Gaussian blur of size N*2?" ContentLicense="CC BY-SA 3.0" />
  <row Id="731" PostHistoryTypeId="1" PostId="256" RevisionGUID="9a8135ae-1cfb-4842-94b2-006771dad121" CreationDate="2015-08-15T18:33:42.943" UserId="56" Text="Is doing multiple Gaussian blurs the same as doing one larger blur?" ContentLicense="CC BY-SA 3.0" />
  <row Id="732" PostHistoryTypeId="3" PostId="256" RevisionGUID="9a8135ae-1cfb-4842-94b2-006771dad121" CreationDate="2015-08-15T18:33:42.943" UserId="56" Text="|real-time|post-processing|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="733" PostHistoryTypeId="2" PostId="257" RevisionGUID="9bff24cc-80df-4d1b-9709-3f1a6caab9dd" CreationDate="2015-08-15T18:38:26.450" UserId="56" Text="In image editing software, you often have the ability to do a directional blur where you can choose and angle and a magnitude of a blur.&#xD;&#xA;&#xD;&#xA;How does this actually work in practice with Gaussian blurring?&#xD;&#xA;&#xD;&#xA;I could see possibly doing something like making the blur go across the axis specified by the angle and use some sort of texture sampling to find the appropriate sample (bilinear or bicubic sampling), but that seems like it probably isn't correct.&#xD;&#xA;&#xD;&#xA;How does directional blurring usually work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="734" PostHistoryTypeId="1" PostId="257" RevisionGUID="9bff24cc-80df-4d1b-9709-3f1a6caab9dd" CreationDate="2015-08-15T18:38:26.450" UserId="56" Text="How does directional Gaussian blurring work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="735" PostHistoryTypeId="3" PostId="257" RevisionGUID="9bff24cc-80df-4d1b-9709-3f1a6caab9dd" CreationDate="2015-08-15T18:38:26.450" UserId="56" Text="|real-time|post-processing|gaussian-blur|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="736" PostHistoryTypeId="2" PostId="258" RevisionGUID="28708068-1aff-4c65-8011-df97646d01ca" CreationDate="2015-08-15T19:40:53.283" UserId="79" Text="Yes, applying two Gaussian blurs is equivalent to doing one Gaussian blur, but with a slightly different size calculation.&#xD;&#xA;&#xD;&#xA;Applying a Gaussian blur to an image means doing a [convolution](https://en.wikipedia.org/wiki/Convolution) of the Gaussian with the image. Convolution is associative: Applying two Gaussian blurs to an image is equivalent to convolving the two Gaussians with each other, and convolving the resulting function with the image.&#xD;&#xA;&#xD;&#xA;As it happens, the convolution of two Gaussians with each other is another Gaussian, whose variance is the sum of variances of the two original Gaussians. A Gaussian of N pixel width has variance N^2; applying it twice is equivalent to a Gaussian with variance 2*N^2, which corresponds to a width of sqrt(2)*N pixels." ContentLicense="CC BY-SA 3.0" />
  <row Id="737" PostHistoryTypeId="5" PostId="258" RevisionGUID="2f729c63-53c2-49f5-a24f-80392406c08d" CreationDate="2015-08-15T20:22:15.167" UserId="79" Comment="Edit as suggested by the comments" Text="Yes, applying two Gaussian blurs is equivalent to doing one Gaussian blur, but with a slightly different size calculation.&#xD;&#xA;&#xD;&#xA;Applying a Gaussian blur to an image means doing a [convolution](https://en.wikipedia.org/wiki/Convolution) of the Gaussian with the image. Convolution is associative: Applying two Gaussian blurs to an image is equivalent to convolving the two Gaussians with each other, and convolving the resulting function with the image.&#xD;&#xA;&#xD;&#xA;As it happens, the convolution of two Gaussians with each other is another Gaussian, whose variance is the sum of variances of the two original Gaussians. A Gaussian of N pixel width has variance N^2; applying it twice is equivalent to a Gaussian with variance 2*N^2, which corresponds to a width of sqrt(2)*N pixels.&#xD;&#xA;&#xD;&#xA;In the same vein, applying a Gaussian of width 2*N is equivalent to applying a Gaussian of width N four times." ContentLicense="CC BY-SA 3.0" />
  <row Id="738" PostHistoryTypeId="5" PostId="257" RevisionGUID="96ca75e9-8b44-4899-b9f7-cb3bc103f562" CreationDate="2015-08-15T20:55:23.050" UserId="56" Comment="added images." Text="In image editing software, you often have the ability to do a directional blur where you can choose and angle and a magnitude of a blur.&#xD;&#xA;&#xD;&#xA;How does this actually work in practice with Gaussian blurring?&#xD;&#xA;&#xD;&#xA;I could see possibly doing something like making the blur go across the axis specified by the angle and use some sort of texture sampling to find the appropriate sample (bilinear or bicubic sampling), but that seems like it probably isn't correct.&#xD;&#xA;&#xD;&#xA;How does directional blurring usually work?&#xA;&#xA;I would say this is in fact motion blur, but I'm asking specifically about the blurring portion, not the whole set up for motion blur within a renderer.&#xA;&#xA;For instance before and after:&#xA;![enter image description here][1]&#xA;&#xA;![enter image description here][2]&#xA;&#xA;&#xA;  [1]: http://docs.gimp.org/en_GB/images/filters/examples/taj_orig.jpg&#xA;  [2]: http://docs.gimp.org/en_GB/images/filters/examples/blur-taj-mblur-linear.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="739" PostHistoryTypeId="2" PostId="259" RevisionGUID="c0a42e1b-bca4-44d3-957a-25c951d7c2f9" CreationDate="2015-08-15T21:28:31.733" UserId="16" Text="I have set up some FPS-measuring code in WebGL (based on [this SO answer](http://stackoverflow.com/a/16447895/1633117)) and have discovered some oddities with the performance of my fragment shader. The code just renders a single quad (or rather two triangles) over a 1024x1024 canvas, so all the magic happens in the fragment shader.&#xD;&#xA;&#xD;&#xA;Consider this simple shader (GLSL; the vertex shader is just a pass-through):&#xD;&#xA;&#xD;&#xA;    // some definitions&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;        // Nothing to see here...&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this just renders a white canvas. It averages around 30 fps on my machine.&#xD;&#xA;&#xD;&#xA;Now let's ramp up the number crunching and compute each fragment based on a few octaves of position-dependent noise:&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;          float noise;&#xD;&#xA;          for ( int j=0; j&lt;10; ++j)&#xD;&#xA;          {&#xD;&#xA;            noise = 0.0;&#xD;&#xA;            for ( int i=4; i&gt;0; i-- )&#xD;&#xA;            {&#xD;&#xA;                float oct = pow(2.0,float(i));&#xD;&#xA;                noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        &#xD;&#xA;          value = noise/2.0+0.5;&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;If you want to run the above code, I've been using [this implementation of `snoise`](https://github.com/ashima/webgl-noise).&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;This brings down the fps to something like 7. That makes sense.&#xD;&#xA;&#xD;&#xA;Now the weird part... let's compute only one of every 16 fragments as noise and leave the others white, by wrapping the noise computation in the following conditional:&#xD;&#xA;&#xD;&#xA;    if (int(mod(x*512.0,4.0)) == 0 &amp;&amp; int(mod(y*512.0,4.0)) == 0)) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You'd expect this to be much faster, but it's still only 7 fps.&#xD;&#xA;&#xD;&#xA;For one more test, let's instead filter the pixels with the following conditional:&#xD;&#xA;&#xD;&#xA;    if (x &gt; 0.5 &amp;&amp; y &gt; 0.5) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This gives the exact same number of noise pixels as before, but now we're back up to almost 30 fps.&#xD;&#xA;&#xD;&#xA;**What is going on here?** Shouldn't the two ways to filter out a 16th of the pixels give the exact same number of cycles? And why is the slower one as slow as rendering *all* pixels as noise?&#xD;&#xA;&#xD;&#xA;(Just to be sure, I have confirmed that the actual modulo computation does not affect the frame rate at all, by rendering every 16th pixel black instead of white.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="740" PostHistoryTypeId="1" PostId="259" RevisionGUID="c0a42e1b-bca4-44d3-957a-25c951d7c2f9" CreationDate="2015-08-15T21:28:31.733" UserId="16" Text="Why is this conditional in my fragment shader so slow?" ContentLicense="CC BY-SA 3.0" />
  <row Id="741" PostHistoryTypeId="3" PostId="259" RevisionGUID="c0a42e1b-bca4-44d3-957a-25c951d7c2f9" CreationDate="2015-08-15T21:28:31.733" UserId="16" Text="|performance|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="742" PostHistoryTypeId="5" PostId="259" RevisionGUID="e80cefa3-ce42-4dff-b103-0ae90f208e84" CreationDate="2015-08-15T21:48:12.240" UserId="16" Comment="added 188 characters in body" Text="I have set up some FPS-measuring code in WebGL (based on [this SO answer](http://stackoverflow.com/a/16447895/1633117)) and have discovered some oddities with the performance of my fragment shader. The code just renders a single quad (or rather two triangles) over a 1024x1024 canvas, so all the magic happens in the fragment shader.&#xD;&#xA;&#xD;&#xA;Consider this simple shader (GLSL; the vertex shader is just a pass-through):&#xD;&#xA;&#xD;&#xA;    // some definitions&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;        // Nothing to see here...&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this just renders a white canvas. It averages around 30 fps on my machine.&#xD;&#xA;&#xD;&#xA;Now let's ramp up the number crunching and compute each fragment based on a few octaves of position-dependent noise:&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;          float noise;&#xD;&#xA;          for ( int j=0; j&lt;10; ++j)&#xD;&#xA;          {&#xD;&#xA;            noise = 0.0;&#xD;&#xA;            for ( int i=4; i&gt;0; i-- )&#xD;&#xA;            {&#xD;&#xA;                float oct = pow(2.0,float(i));&#xD;&#xA;                noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        &#xD;&#xA;          value = noise/2.0+0.5;&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;If you want to run the above code, I've been using [this implementation of `snoise`](https://github.com/ashima/webgl-noise).&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;This brings down the fps to something like 7. That makes sense.&#xD;&#xA;&#xD;&#xA;Now the weird part... let's compute only one of every 16 fragments as noise and leave the others white, by wrapping the noise computation in the following conditional:&#xD;&#xA;&#xD;&#xA;    if (int(mod(x*512.0,4.0)) == 0 &amp;&amp; int(mod(y*512.0,4.0)) == 0)) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You'd expect this to be much faster, but it's still only 7 fps.&#xD;&#xA;&#xD;&#xA;For one more test, let's instead filter the pixels with the following conditional:&#xD;&#xA;&#xD;&#xA;    if (x &gt; 0.5 &amp;&amp; y &gt; 0.5) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This gives the exact same number of noise pixels as before, but now we're back up to almost 30 fps.&#xD;&#xA;&#xD;&#xA;**What is going on here?** Shouldn't the two ways to filter out a 16th of the pixels give the exact same number of cycles? And why is the slower one as slow as rendering *all* pixels as noise?&#xD;&#xA;&#xD;&#xA;Bonus question: **What can I do about this?** Is there any way to work around the horrible performance if I actually *do* want to speckle my canvas with only a few expensive fragments?&#xD;&#xA;&#xD;&#xA;(Just to be sure, I have confirmed that the actual modulo computation does not affect the frame rate at all, by rendering every 16th pixel black instead of white.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="743" PostHistoryTypeId="2" PostId="260" RevisionGUID="9cc400af-9a6f-49ec-9211-a05f1bdd4369" CreationDate="2015-08-15T21:51:02.300" UserId="137" Text="Pixels get grouped into little squares (how big depends on the hardware) and computed together in a single [SIMD][1] pipeline. (struct of arrays type of SIMD)&#xD;&#xA;&#xD;&#xA;This pipeline (which has several different names depending on the vendor: warps, wavefronts) will execute operations for each pixel/fragment in lockstep. This means that if 1 pixel needs a computation done then all pixels will compute it and the ones that don't need the result will throw it away.&#xD;&#xA;&#xD;&#xA;If all fragments follow the same path through a shader then the other branches won't get executed.&#xD;&#xA;&#xD;&#xA;This means that your first method of computing every 16th pixel will be worst case branching. &#xD;&#xA;&#xD;&#xA;If you want to still down size your image then just render to a smaller texture and then upscale it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SIMD" ContentLicense="CC BY-SA 3.0" />
  <row Id="745" PostHistoryTypeId="2" PostId="261" RevisionGUID="d864fa56-d87b-483c-a9d2-982861becc7b" CreationDate="2015-08-16T03:50:54.883" UserId="56" Text="When realtime renderers (such as 3d games) have motion blur, how is it usually implemented?&#xA;&#xA;I think I've heard something about needing to have motion vectors for each pixel but I'm not sure about that and not sure how it would be used." ContentLicense="CC BY-SA 3.0" />
  <row Id="746" PostHistoryTypeId="1" PostId="261" RevisionGUID="d864fa56-d87b-483c-a9d2-982861becc7b" CreationDate="2015-08-16T03:50:54.883" UserId="56" Text="How is motion blur implemented in modern realtime renderers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="747" PostHistoryTypeId="3" PostId="261" RevisionGUID="d864fa56-d87b-483c-a9d2-982861becc7b" CreationDate="2015-08-16T03:50:54.883" UserId="56" Text="|real-time|post-processing|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="748" PostHistoryTypeId="5" PostId="255" RevisionGUID="7f0845e0-8eec-4f1f-b92e-8c20b0223f02" CreationDate="2015-08-16T05:02:48.720" UserId="231" Comment="added 85 characters in body" Text="For questions about creating or working with noise functions (in 1D, 2D, 3D or more)." ContentLicense="CC BY-SA 3.0" />
  <row Id="749" PostHistoryTypeId="24" PostId="255" RevisionGUID="7f0845e0-8eec-4f1f-b92e-8c20b0223f02" CreationDate="2015-08-16T05:02:48.720" Comment="Proposed by 231 approved by 48, 56 edit id of 33" ContentLicense="CC BY-SA 3.0" />
  <row Id="750" PostHistoryTypeId="2" PostId="262" RevisionGUID="91a0ecb8-0097-4070-abdf-a53cfd7cac86" CreationDate="2015-08-16T07:33:01.567" UserId="100" Text="There are several techniques used. &#xD;&#xA;&#xD;&#xA;A simple, but limited, [ post-process approach][1] that is not really used any more consists in reconstructing the world space position of a pixel using both the view projection matrix from current and previous frame. Using these two values you can compute the velocity at a pixel and blur accordingly, sampling along the velocity vector with how many samples you want ( the more sample the blurrier, but the more expensive as well). &#xD;&#xA;&#xD;&#xA;This method unfortunately takes into account just the camera movement and therefore is not accurate enough if you have a dynamic scene with fast moving objects. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you mentioned, other more modern techniques use a velocity buffer.&#xD;&#xA;&#xD;&#xA;This velocity buffer can be created during the base pass in the deferred pipeline transforming each vertex using the world-view-projection matrix of the previous frame and then computing in the pixel shader the velocity vector using the screen space position of both frames.  &#xD;&#xA;With this velocity buffer you can, in a post-process step, sample across the per-pixel velocity direction like in the approach I described above.  The motion blur that you will get is obviously not camera-only; however you get an overhead in terms of memory (you need to keep an extra buffer) and time (you need to render additional info per pixel). &#xD;&#xA;&#xD;&#xA;One technique based on velocity buffer that I particularly like is [McGuire et al.][2] that IIRC, is used with some variations in Unreal Engine 4 and many other games. &#xD;&#xA;&#xD;&#xA;[![ From McGuire et al. 2012 ][3]][3]&#xD;&#xA;&#xD;&#xA;*From [McGuire et al. 2012]*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;They divide the scene in tiles, assuming that each of these have a dominant velocity. Then, starting from the full res velocity buffer, they locate the velocity vector with higher magnitude for each tile, producing a downsampled version of the velocity buffer where 1 pixel = 1 tile.  &#xD;&#xA;Using this buffer, in another pass, they can generate a buffer that stores for each pixel/tile the dominant velocity among the neighbourhood pixels.&#xD;&#xA;Note that the tile size is based on the max blur radius. &#xD;&#xA;&#xD;&#xA;Using these buffers they then proceed with the gathering step sampling in the neighbourhood dominant velocity direction as this is the most plausible direction of the blur for each sample (as I said, the tile size is the max-blur radius). The weighting used for the blur takes into account the full res velocity and depth informations. Note that the paper propose three different weighting for three different scenarios (blurry over sharp, sharp over blurry and blurry over blurry). &#xD;&#xA;&#xD;&#xA;Another important advantage of the method is that you can early-out if the dominant velocity in the neighbourhood is smaller than a certain threshold. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html&#xD;&#xA;  [2]: http://graphics.cs.williams.edu/papers/MotionBlurI3D12/McGuire12Blur.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/pXpdE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="751" PostHistoryTypeId="5" PostId="257" RevisionGUID="b7514d6a-a7b3-403c-ba95-e3e4ac2241f1" CreationDate="2015-08-16T07:40:27.187" UserId="100" Comment="Fixed images positioning" Text="In image editing software, you often have the ability to do a directional blur where you can choose and angle and a magnitude of a blur.&#xD;&#xA;&#xD;&#xA;How does this actually work in practice with Gaussian blurring?&#xD;&#xA;&#xD;&#xA;I could see possibly doing something like making the blur go across the axis specified by the angle and use some sort of texture sampling to find the appropriate sample (bilinear or bicubic sampling), but that seems like it probably isn't correct.&#xD;&#xA;&#xD;&#xA;How does directional blurring usually work?&#xD;&#xA;&#xD;&#xA;I would say this is in fact motion blur, but I'm asking specifically about the blurring portion, not the whole set up for motion blur within a renderer.&#xD;&#xA;&#xD;&#xA;For instance before and after:&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://docs.gimp.org/en_GB/images/filters/examples/taj_orig.jpg&#xD;&#xA;  [2]: http://docs.gimp.org/en_GB/images/filters/examples/blur-taj-mblur-linear.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="753" PostHistoryTypeId="2" PostId="263" RevisionGUID="4c1a4097-bb8f-484e-8f51-8f9c97a44697" CreationDate="2015-08-16T10:57:32.917" UserId="406" Text="If I understand your question, you are asking how to actually perform said directional blur in code? A Gaussian blur is typically done by sampling your image in all directions around your current point (or if in 2 passes, one vertical and one horizontal which equates to the same thing), with a specific set of weights for the falloff.&#xD;&#xA;For a directional blur you just need to change the shape of your kernel to &quot;not be round&quot;, for lack of better words.&#xD;&#xA;Say you wanted to smear the image to the left only, you could just accumulate samples (with whatever weights you want) with currentPixelUV.xy + float2( -1.f, 0.f) * invScreenRes.xy;&#xD;&#xA;Billinear texture filtering will be required for this to work when your resulting uvs are not hitting pixel centers.&#xD;&#xA;Magnitude of the blur is controlled by how far you sample from your original pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="754" PostHistoryTypeId="2" PostId="264" RevisionGUID="1cfa0eca-b727-4232-bb33-90dac4fc6974" CreationDate="2015-08-16T12:10:39.143" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="755" PostHistoryTypeId="2" PostId="265" RevisionGUID="69604cbc-3603-4e62-ae3f-ab407558e9d0" CreationDate="2015-08-16T12:10:39.143" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="756" PostHistoryTypeId="5" PostId="264" RevisionGUID="845733d3-2a21-432d-91f0-666bf3e08060" CreationDate="2015-08-16T12:48:12.710" UserId="16" Comment="added 293 characters in body" Text="[Shaders](https://en.wikipedia.org/wiki/Shader) are programs which are written to customise a programmable GPU pipeline.&#xD;&#xA;&#xD;&#xA;The most common shader languages are [GLSL](https://en.wikipedia.org/wiki/OpenGL_Shading_Language) and [HLSL](https://en.wikipedia.org/wiki/High-Level_Shading_Language)." ContentLicense="CC BY-SA 3.0" />
  <row Id="757" PostHistoryTypeId="24" PostId="264" RevisionGUID="845733d3-2a21-432d-91f0-666bf3e08060" CreationDate="2015-08-16T12:48:12.710" Comment="Proposed by 16 approved by 79, 231 edit id of 36" ContentLicense="CC BY-SA 3.0" />
  <row Id="758" PostHistoryTypeId="5" PostId="265" RevisionGUID="b7fe8b2e-c6c1-40ca-bd6c-f42bea7e5bdb" CreationDate="2015-08-16T12:48:36.057" UserId="16" Comment="added 162 characters in body" Text="For all questions related to shaders, i.e. the programmable part of the GPU pipeline. For language-specific shader questions, see also the [glsl] and [hlsl] tags." ContentLicense="CC BY-SA 3.0" />
  <row Id="759" PostHistoryTypeId="24" PostId="265" RevisionGUID="b7fe8b2e-c6c1-40ca-bd6c-f42bea7e5bdb" CreationDate="2015-08-16T12:48:36.057" Comment="Proposed by 16 approved by 79, 231 edit id of 37" ContentLicense="CC BY-SA 3.0" />
  <row Id="760" PostHistoryTypeId="5" PostId="198" RevisionGUID="9b8ae8cd-6e99-45ab-901e-b0dc77cef623" CreationDate="2015-08-16T12:49:01.910" UserId="16" Comment="add usage guidance to excerpt" Text="GLSL is the OpenGL shading language. Use this tag for questions which are specifically about shaders written in this language. For generic shader questions use [shader] instead." ContentLicense="CC BY-SA 3.0" />
  <row Id="761" PostHistoryTypeId="24" PostId="198" RevisionGUID="9b8ae8cd-6e99-45ab-901e-b0dc77cef623" CreationDate="2015-08-16T12:49:01.910" Comment="Proposed by 16 approved by 79, 231 edit id of 35" ContentLicense="CC BY-SA 3.0" />
  <row Id="762" PostHistoryTypeId="5" PostId="263" RevisionGUID="5f7ece03-69d9-4bf6-bf68-0a5042ae8119" CreationDate="2015-08-16T12:54:36.177" UserId="16" Comment="improve formatting" Text="If I understand your question, you are asking how to actually perform said directional blur in code? A Gaussian blur is typically done by sampling your image in all directions around your current point (or if in 2 passes, one vertical and one horizontal which equates to the same thing), with a specific set of weights for the falloff.&#xD;&#xA;&#xD;&#xA;For a directional blur you just need to change the shape of your kernel to &quot;not be round&quot;, for lack of better words.&#xD;&#xA;&#xD;&#xA;Say you wanted to smear the image to the left only, you could just accumulate samples (with whatever weights you want) with &#xD;&#xA;&#xD;&#xA;    currentPixelUV.xy + float2( -1.f, 0.f) * invScreenRes.xy;&#xD;&#xA;&#xD;&#xA;Bilinear texture filtering will be required for this to work when your resulting *uv*s are not hitting pixel centers.&#xD;&#xA;&#xD;&#xA;The magnitude of the blur is controlled by how far you sample from your original pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="763" PostHistoryTypeId="24" PostId="263" RevisionGUID="5f7ece03-69d9-4bf6-bf68-0a5042ae8119" CreationDate="2015-08-16T12:54:36.177" Comment="Proposed by 16 approved by -1, 231 edit id of 34" ContentLicense="CC BY-SA 3.0" />
  <row Id="764" PostHistoryTypeId="5" PostId="263" RevisionGUID="e97ac52b-fe67-40e4-83b4-bbb717b5d248" CreationDate="2015-08-16T12:54:36.177" UserId="406" Comment="improve formatting" Text="If I understand your question, you are asking how to actually perform said directional blur in code? A Gaussian blur is typically done by sampling your image in all directions around your current point (or if in 2 passes, one vertical and one horizontal which equates to the same thing), with a specific set of weights for the falloff.&#xD;&#xA;&#xD;&#xA;For a directional blur you just need to change the shape of your kernel to &quot;not be round&quot;, for lack of better words.&#xD;&#xA;&#xD;&#xA;Say you wanted to smear the image to the left only, you could just accumulate samples (with whatever weights you want) with &#xD;&#xA;&#xD;&#xA;    currentPixelUV.xy + float2( -1.f * someOffsetScale, 0.f) * invScreenRes.xy * currentIteration;&#xD;&#xA;&#xD;&#xA;Bilinear texture filtering will be required for this to work when your resulting *uv*s are not hitting pixel centers.&#xD;&#xA;&#xD;&#xA;The magnitude of the blur is controlled by how far you sample from your original pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="765" PostHistoryTypeId="2" PostId="266" RevisionGUID="448c0a7e-3cdc-4286-92f4-e57980d70484" CreationDate="2015-08-16T13:49:05.607" UserId="127" Text="When using textures in GLSL, it is best to calculate the final texture coordinates in the vertex shader and hand them over to the fragment shader using `varying`s. Example with a simple flip in the y coordinate:&#xD;&#xA;&#xD;&#xA;    // Vertex shader&#xD;&#xA;    attribute vec2 texture;&#xD;&#xA;    varying highp vec2 texCoord;&#xD;&#xA;    // ...&#xD;&#xA;    void main() {&#xD;&#xA;        texCoord = vec2(texture.x, 1.0-texture.y);&#xD;&#xA;        // ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Fragment shader&#xD;&#xA;    varying highp vec2 textureCoordinates;&#xD;&#xA;    uniform sampler2D tex;&#xD;&#xA;    // ...&#xD;&#xA;    void main() {&#xD;&#xA;        highp vec4 texColor = texture2D(tex, texCoord);&#xD;&#xA;        // ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the flip in the y coordinate, or an even simpler operation like adding `vec2(0.5)` to the texture coordinate is performed in the fragment shader the texture access is much slower. Why?&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;As a note, e.g. blending two textures, using a weighted sum of them, is much cheaper in terms of time and also needs to be done for each pixel, so the computation of the texture coordinate itself does not seem to be that costly." ContentLicense="CC BY-SA 3.0" />
  <row Id="766" PostHistoryTypeId="1" PostId="266" RevisionGUID="448c0a7e-3cdc-4286-92f4-e57980d70484" CreationDate="2015-08-16T13:49:05.607" UserId="127" Text="Why is accessing textures much slower when calculating the texture coordinate in the fragment shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="767" PostHistoryTypeId="3" PostId="266" RevisionGUID="448c0a7e-3cdc-4286-92f4-e57980d70484" CreationDate="2015-08-16T13:49:05.607" UserId="127" Text="|performance|glsl|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="768" PostHistoryTypeId="2" PostId="267" RevisionGUID="8d4474a4-ced2-456a-9ca3-09d09dc37b4c" CreationDate="2015-08-16T14:31:07.893" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="769" PostHistoryTypeId="2" PostId="268" RevisionGUID="d21d63de-ba7c-4845-83e4-d233b08b7c28" CreationDate="2015-08-16T14:31:07.893" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="770" PostHistoryTypeId="2" PostId="269" RevisionGUID="3ef606c9-5118-4918-a383-76c5bdbab629" CreationDate="2015-08-16T14:37:22.753" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="771" PostHistoryTypeId="2" PostId="270" RevisionGUID="f8c6756d-5d5a-4da6-8011-63a8adf73857" CreationDate="2015-08-16T14:37:22.753" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="772" PostHistoryTypeId="5" PostId="259" RevisionGUID="7c9abf00-ad65-4338-857b-35aac6993988" CreationDate="2015-08-16T14:51:28.630" UserId="16" Comment="added 37 characters in body" Text="I have set up some FPS-measuring code in WebGL (based on [this SO answer](http://stackoverflow.com/a/16447895/1633117)) and have discovered some oddities with the performance of my fragment shader. The code just renders a single quad (or rather two triangles) over a 1024x1024 canvas, so all the magic happens in the fragment shader.&#xD;&#xA;&#xD;&#xA;Consider this simple shader (GLSL; the vertex shader is just a pass-through):&#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    // some definitions&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;        // Nothing to see here...&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this just renders a white canvas. It averages around 30 fps on my machine.&#xD;&#xA;&#xD;&#xA;Now let's ramp up the number crunching and compute each fragment based on a few octaves of position-dependent noise:&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;          float noise;&#xD;&#xA;          for ( int j=0; j&lt;10; ++j)&#xD;&#xA;          {&#xD;&#xA;            noise = 0.0;&#xD;&#xA;            for ( int i=4; i&gt;0; i-- )&#xD;&#xA;            {&#xD;&#xA;                float oct = pow(2.0,float(i));&#xD;&#xA;                noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        &#xD;&#xA;          value = noise/2.0+0.5;&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;If you want to run the above code, I've been using [this implementation of `snoise`](https://github.com/ashima/webgl-noise).&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;This brings down the fps to something like 7. That makes sense.&#xD;&#xA;&#xD;&#xA;Now the weird part... let's compute only one of every 16 fragments as noise and leave the others white, by wrapping the noise computation in the following conditional:&#xD;&#xA;&#xD;&#xA;    if (int(mod(x*512.0,4.0)) == 0 &amp;&amp; int(mod(y*512.0,4.0)) == 0)) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You'd expect this to be much faster, but it's still only 7 fps.&#xD;&#xA;&#xD;&#xA;For one more test, let's instead filter the pixels with the following conditional:&#xD;&#xA;&#xD;&#xA;    if (x &gt; 0.5 &amp;&amp; y &gt; 0.5) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This gives the exact same number of noise pixels as before, but now we're back up to almost 30 fps.&#xD;&#xA;&#xD;&#xA;**What is going on here?** Shouldn't the two ways to filter out a 16th of the pixels give the exact same number of cycles? And why is the slower one as slow as rendering *all* pixels as noise?&#xD;&#xA;&#xD;&#xA;Bonus question: **What can I do about this?** Is there any way to work around the horrible performance if I actually *do* want to speckle my canvas with only a few expensive fragments?&#xD;&#xA;&#xD;&#xA;(Just to be sure, I have confirmed that the actual modulo computation does not affect the frame rate at all, by rendering every 16th pixel black instead of white.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="773" PostHistoryTypeId="2" PostId="271" RevisionGUID="fa39cca7-afda-40a5-9f7a-5593585bf30f" CreationDate="2015-08-16T16:26:37.870" UserId="127" Text="Especially when rendering particle effects, the same object needs to be rendered several times with slightly modified properties. But these changes are often limited to properties like pose or textures, and are not in the geometry of the object itself. &#xD;&#xA;&#xD;&#xA;A different pose (translation, rotation) is merely a matrix multiplication with the vertices, and a different texture with an applied texture atlas are merely different texture coordinates.&#xD;&#xA;&#xD;&#xA;Nevertheless each of the particles needs to be drawn and I currently do that by calling `glDrawElements` for every particle, while setting uniforms appropriately. Until now this is sufficient for rendering the scene in real-time, but for more complex scenes or simply for more particles emitted by the particle system this could easily lead to dropping frame rates.&#xD;&#xA;&#xD;&#xA;So, is there a way to reduce the number of draw calls for very similar objects? " ContentLicense="CC BY-SA 3.0" />
  <row Id="774" PostHistoryTypeId="1" PostId="271" RevisionGUID="fa39cca7-afda-40a5-9f7a-5593585bf30f" CreationDate="2015-08-16T16:26:37.870" UserId="127" Text="How to reduce the number of draw calls when rendering one object multiple times?" ContentLicense="CC BY-SA 3.0" />
  <row Id="775" PostHistoryTypeId="3" PostId="271" RevisionGUID="fa39cca7-afda-40a5-9f7a-5593585bf30f" CreationDate="2015-08-16T16:26:37.870" UserId="127" Text="|opengl|performance|real-time|mobile|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="776" PostHistoryTypeId="2" PostId="272" RevisionGUID="9558e709-7c20-4388-97a8-48d9760f155f" CreationDate="2015-08-16T16:26:37.870" UserId="127" Text="In OpenGL ES there is Instancing which provides allows for rendering one object multiple times. &#xD;&#xA;&#xD;&#xA;When using Instancing, you can use uniform arrays to provide different information, e.g. a transformation matrix, for each of the particles. In the shader you can then use `gl_InstanceID` to distinguish between the individual particles and pick the appropriate index from the uniform array.&#xD;&#xA;&#xD;&#xA;    attribute vec4 position;&#xD;&#xA;    uniform mat4 transformations[16];&#xD;&#xA;    // other attributes, uniforms, etc&#xD;&#xA;    void main() {&#xD;&#xA;        // ...&#xD;&#xA;        gl_Position = ... * transformations[gl_InstanceID] * position;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And you need to draw your objects using `glDrawElementsInstanced` which takes the number of objects as an additional parameter (compared to `glDrawElements`).&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;Note: In OpenGL ES 2, you need to use `gl_InstanceIDEXT` and `glDrawElementsInstancedEXT` as it is an [extension](https://www.khronos.org/registry/gles/extensions/EXT/draw_instanced.txt) there. Also you have to enable it in the shader using&#xD;&#xA;&#xD;&#xA;    #extension GL_EXT_draw_instanced : enable" ContentLicense="CC BY-SA 3.0" />
  <row Id="777" PostHistoryTypeId="5" PostId="267" RevisionGUID="d447b0e5-631b-43fa-ad4e-27bc48e47b5a" CreationDate="2015-08-16T16:50:42.327" UserId="16" Comment="added 494 characters in body" Text="Use this tag for questions about computations subject to real-time constraints. The minimum framerate for a real-time illusion is usually considered to be around 24 frames per second, at which the human will perceive a sequence of similar frames as fluid motion.&#xD;&#xA;&#xD;&#xA;For more information, [see Wikipedia](https://en.wikipedia.org/wiki/Real-time_computer_graphics).&#xD;&#xA;&#xD;&#xA;See also [tag:interactive] for less strict constraints and [tag:offline] for computations which will take significantly longer." ContentLicense="CC BY-SA 3.0" />
  <row Id="778" PostHistoryTypeId="24" PostId="267" RevisionGUID="d447b0e5-631b-43fa-ad4e-27bc48e47b5a" CreationDate="2015-08-16T16:50:42.327" Comment="Proposed by 16 approved by 56, 231 edit id of 38" ContentLicense="CC BY-SA 3.0" />
  <row Id="779" PostHistoryTypeId="5" PostId="268" RevisionGUID="c529a472-a81f-4b0b-a6b3-fa0a54727324" CreationDate="2015-08-16T16:50:55.587" UserId="16" Comment="added 290 characters in body" Text="For questions about computations subject to real-time constraints. The minimum framerate for a real-time illusion is usually considered to be around 24 frames per second. See also [interactive] for less strict constraints and [offline] for computations which will take significantly longer." ContentLicense="CC BY-SA 3.0" />
  <row Id="780" PostHistoryTypeId="24" PostId="268" RevisionGUID="c529a472-a81f-4b0b-a6b3-fa0a54727324" CreationDate="2015-08-16T16:50:55.587" Comment="Proposed by 16 approved by 56, 231 edit id of 39" ContentLicense="CC BY-SA 3.0" />
  <row Id="781" PostHistoryTypeId="5" PostId="269" RevisionGUID="7b7951b6-3fcc-4026-9436-c1675aecf8bc" CreationDate="2015-08-16T16:51:11.287" UserId="16" Comment="added 415 characters in body" Text="Use this tag for questions about computations with no or loose time constraints, which may take minutes, hours or days to complete.&#xD;&#xA;&#xD;&#xA;Offline computations are commonly used as pre-computations for real-time applications or rendering of films. They usually allow for vastly superior and more realistic effects to be incorporated.&#xD;&#xA;&#xD;&#xA;For computations with time constraints, see [tag:real-time] and [tag:interactive]." ContentLicense="CC BY-SA 3.0" />
  <row Id="782" PostHistoryTypeId="24" PostId="269" RevisionGUID="7b7951b6-3fcc-4026-9436-c1675aecf8bc" CreationDate="2015-08-16T16:51:11.287" Comment="Proposed by 16 approved by 56, 231 edit id of 40" ContentLicense="CC BY-SA 3.0" />
  <row Id="783" PostHistoryTypeId="5" PostId="270" RevisionGUID="552b96ee-4fba-43b7-a931-2de9f2995420" CreationDate="2015-08-16T16:51:16.567" UserId="16" Comment="added 193 characters in body" Text="For questions about computations with no or loose time constraints, which may take minutes, hours or days to complete. For computations with time constraints, see [real-time] and [interactive]." ContentLicense="CC BY-SA 3.0" />
  <row Id="784" PostHistoryTypeId="24" PostId="270" RevisionGUID="552b96ee-4fba-43b7-a931-2de9f2995420" CreationDate="2015-08-16T16:51:16.567" Comment="Proposed by 16 approved by 56, 231 edit id of 41" ContentLicense="CC BY-SA 3.0" />
  <row Id="785" PostHistoryTypeId="2" PostId="273" RevisionGUID="b908dae5-8724-4295-b2ca-a2837f0208d3" CreationDate="2015-08-16T18:15:33.757" UserId="157" Text="I realized that littlecms, [suggested by _joojaa_ in a comment above][1] is very complete in dealing with the ICC profiles.&#xD;&#xA;&#xD;&#xA;I did a few tests in their color translator program with different destination color spaces and the differences are great as you can see:&#xD;&#xA;&#xD;&#xA;Original&#xD;&#xA;&#xD;&#xA;[![Original][2]][2]&#xD;&#xA;&#xD;&#xA;sRGB-like&#xD;&#xA;&#xD;&#xA;[![sRGB][3]][3]&#xD;&#xA;&#xD;&#xA;adobeRGB1998 (it seems it's the original color space)&#xD;&#xA;&#xD;&#xA;[![adobeRGB][4]][4]&#xD;&#xA;&#xD;&#xA;appleRGB&#xD;&#xA;&#xD;&#xA;[![apple][5]][5]&#xD;&#xA;&#xD;&#xA;And the most desirable results in my case are within the ProPhotoRGB color space:&#xD;&#xA;&#xD;&#xA;[![prophoto][6]][6]&#xD;&#xA;&#xD;&#xA;linearProPhotoRGB&#xD;&#xA;&#xD;&#xA;[![linearProPhoto][7]][7]&#xD;&#xA;&#xD;&#xA;All of the above were following an automatic _rendering intent_ but other _intents_ bring slight variations (samples applied together with linearProPhotoRGB destination color space):&#xD;&#xA;&#xD;&#xA;Absolute Colorimetric&#xD;&#xA;&#xD;&#xA;[![ICC absolute colorimetric][8]][8]&#xD;&#xA;&#xD;&#xA;Legacy Unadapted Absolute Colorimetric&#xD;&#xA;&#xD;&#xA;[![Legacy][9]][9]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I also realized that GIMP was actually restoring the original profile (not the opposite as I thought, i.e. instead of applying an embedded ICC profile, it was taking it off) and with this littlecms, now it does seem much simpler to &quot;translate&quot; color spaces than I thought.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/175/how-is-an-icc-profile-embedded-or-built-into-an-image#comment247_175&#xD;&#xA;  [2]: https://i.stack.imgur.com/xe6IM.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/NbIee.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/P7aGm.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/iAmh5.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/gp5GS.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/MIJk4.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/ik2TL.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/vUR7g.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="786" PostHistoryTypeId="2" PostId="274" RevisionGUID="4673ba53-47ff-46f6-97ef-29695fb06407" CreationDate="2015-08-16T18:37:46.270" UserId="54" Text="There are many, many ways to draw things in OpenGL, so this is naturally confusing sometimes. The first method you describe, setting the shader parameters and issuing one draw call per object is usually the most inefficient, due to the high API overhead. The second one, using instanced drawing is a much smarter approach for objects with the same parameters.&#xD;&#xA;&#xD;&#xA;When it comes to particles, specifically, there are two other methods which I'm aware of and have tested: &#xD;&#xA;&#xD;&#xA;- The first one, more traditional and easier to implement, is to generate a unique quadrilateral for each particle in the application code. Then use one of the [several optimized buffer streaming][1] paths of OpenGL to upload this data and issue a single draw call. This is the most straightforward method and provides good results. It will involve very few API calls if you can map the vertex/index buffers (`glMapBuffer/MapBufferRange`).&#xD;&#xA;&#xD;&#xA;- Another method is to move the whole thing to a shader program, using [Transform Feedback][2]. This method is a little more complicated to get up and running, but you can find a lot of references on the subject, [such as this tutorial][3]. This one should be the optimal path, since it moves the whole simulation to the GPU.&#xD;&#xA;&#xD;&#xA;Those are some of the optimized ways of rendering particle effects. But OpenGL provides several other rendering paths that are better for different cases, one of such is [indirect draw][4], which isn't available on ES at the moment, but is probably one of the fastest drawing paths available on modern PC OpenGL. Transform Feedback also requires a geometry shader, so it is not available for current OpenGL-ES.&#xD;&#xA;&#xD;&#xA;For more on the optimized rendering paths of OpenGL, I recommend watching this very good presentation by NVidia: [Approaching Zero Driver Overhead in OpenGL][5]. At the end of the talk, they show a very interesting benchmark of several methods and how they compare with the Direct3D equivalents.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Buffer_Object_Streaming&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Transform_Feedback&#xD;&#xA;  [3]: http://ogldev.atspace.co.uk/www/tutorial28/tutorial28.html&#xD;&#xA;  [4]: https://www.opengl.org/wiki/Vertex_Rendering#Indirect_rendering&#xD;&#xA;  [5]: http://gdcvault.com/play/1020791/" ContentLicense="CC BY-SA 3.0" />
  <row Id="787" PostHistoryTypeId="2" PostId="275" RevisionGUID="077e33e7-2231-4cae-aa57-070881fe0114" CreationDate="2015-08-17T00:31:23.877" UserId="207" Text="What you're talking about is commonly called &quot;dependent texture reads&quot; in the mobile development community. It's an implementation detail of certain hardware, and therefore it really depends on the GPU as to whether or not it has any performance implications. Typically it's something you see brought up for PowerVR GPU's in Apple hardware, since it was explicitly mentioned in both [Imagination][1] and [Apple][2] documentation. If I recall correctly, the issue basically came from hardware in the GPU that would start to pre-fetch textures before the fragment shader even began running, so that it could do a better job of hiding the latency. The docs I linked mention that it's no longer an issue on Series6 hardware, so at least on newer Apple hardware it's not something that you have to worry about. I'm honestly not sure about other mobile GPU's, since that's not my area of expertise. You should try and consult their documentation to find out for sure.&#xD;&#xA;&#xD;&#xA;If you decide to do some Google searches on this issue, be aware that you'll probably find some older material that's talking about dependent texture fetches on older desktop hardware. Basic in the early days of pixel/fragment shaders, the term &quot;dependent texture fetch&quot; referred to using a UV address that relied on a previous texture fetch. The classic example was bump-mapped environment map rendering, where you wanted to use a reflection vector based on the normal map in order to sample the environment map. On this older hardware there was some major performance implications, and I think it wasn't even supported on some very old GPU's. With modern GPU's the hardware and the shader ISA is much more generalized, and so the performance situation is much more complicated. &#xD;&#xA;&#xD;&#xA;  [1]: http://cdn.imgtec.com/sdk-documentation/PowerVR.Performance%20Recommendations.pdf&#xD;&#xA;  [2]: https://developer.apple.com/library/ios/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="789" PostHistoryTypeId="2" PostId="276" RevisionGUID="5b7b4af4-da57-4abf-986e-dbdf8afa010e" CreationDate="2015-08-17T06:28:22.107" UserId="159" Text="See Kolb, et al., [*A Realistic Camera Model for Computer Graphics*][1], SIGGRAPH 95.&#xD;&#xA;&#xD;&#xA;However, do bear in mind that camera models which mimic real-world cameras aren't necessarily what you want for the rendering phase. In a visual effects/post-production scenario, the more blur/vignetting/distortion that the camera model introduces, the worse it is for the compositor/colour timer.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Cameras/Realistic%20Camera%20Model.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="790" PostHistoryTypeId="34" PostId="89" RevisionGUID="bdebf685-633f-4f1c-9bd4-8edcdc2a645d" CreationDate="2015-08-17T09:58:04.877" UserId="231" Comment="1" />
  <row Id="791" PostHistoryTypeId="2" PostId="277" RevisionGUID="cc7eca2c-8292-4dcb-aa0e-ab3fbff53e36" CreationDate="2015-08-17T14:11:11.453" UserId="56" Text="Applying multiple Gaussian blurs can result in an effect that is equivalent to a stronger Gaussian blur.&#xD;&#xA;&#xD;&#xA;For instance this question says that: http://computergraphics.stackexchange.com/questions/256/is-doing-multiple-gaussian-blurs-the-same-as-doing-one-larger-blur&#xD;&#xA;&#xD;&#xA;Wikipedia also says it, but says that it will always be just as many calculations or more to do it in multiple blurs versus doing it in a single blur.&#xD;&#xA;&#xD;&#xA;&gt; Applying multiple, successive gaussian blurs to an image has the same effect as applying a single, larger gaussian blur, whose radius is the square root of the sum of the squares of the blur radii that were actually applied. For example, applying successive gaussian blurs with radii of 6 and 8 gives the same results as applying a single gaussian blur of radius 10, since \sqrt{6^2 + 8^2} = 10. Because of this relationship, processing time cannot be saved by simulating a gaussian blur with successive, smaller blurs — the time required will be at least as great as performing the single large blur.&#xD;&#xA;&#xD;&#xA;Source: https://en.wikipedia.org/wiki/Gaussian_blur#Mechanics&#xD;&#xA;&#xD;&#xA;However, I've heard and read about people doing multiple blurs in realtime graphics to achieve a stronger blur.&#xD;&#xA;&#xD;&#xA;What benefit is there if it isn't a reduction in computation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="792" PostHistoryTypeId="1" PostId="277" RevisionGUID="cc7eca2c-8292-4dcb-aa0e-ab3fbff53e36" CreationDate="2015-08-17T14:11:11.453" UserId="56" Text="Why do multiple Gaussian Blurs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="793" PostHistoryTypeId="3" PostId="277" RevisionGUID="cc7eca2c-8292-4dcb-aa0e-ab3fbff53e36" CreationDate="2015-08-17T14:11:11.453" UserId="56" Text="|real-time|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="795" PostHistoryTypeId="2" PostId="278" RevisionGUID="229f1c25-998a-4d40-81e7-077887cd4b6a" CreationDate="2015-08-17T16:09:06.873" UserId="231" Text="Intuitively, dust settles onto surfaces at a higher rate in areas where the air flow is slower. This means instead of a surface gathering an even layer of dust, there will be more in corners - corners of a room/shelf, corners formed by the placement of objects on a surface, concavities in a surface.&#xD;&#xA;&#xD;&#xA;I can get an increase in realism simply by making the thickness/density of dust reduce with distance from an object, and combine that effect for several objects including walls. This naturally gives the expected ordering of thicknesses - the edges of a floor have more dust than the centre, the corners where the edges meet have more dust then the centre of the edges. However, the increase in realism from getting the order correct still leaves the problem of getting the ratio right. There is more dust in the places you expect to have more dust, but not necessarily the right amount more.&#xD;&#xA;&#xD;&#xA;Is there an established method of approximating a realistic ratio of thickness between different points on a surface? I don't need this to be completely physically accurate (that would need to take into account objects that move through the environment during the long period taken for dust to accumulate). I'm just looking for average behaviour that will look believable to the human eye.&#xD;&#xA;&#xD;&#xA;In searching online I've mostly found atmospheric models for suspended dust, rather than a way of modelling dust deposition on a surface.&#xD;&#xA;&#xD;&#xA;## My attempts - linear and exponential distributions&#xD;&#xA;Here is some code in Python 3 using pillow (the PIL fork) that demonstrates a couple of distributions I have experimented with:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image&#xD;&#xA;    from math import exp&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def linear(distance, scale):&#xD;&#xA;        return max(0, 64 - distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def exponential(distance, scale):&#xD;&#xA;        return 64 * exp(-distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def gamma_corrected(value):&#xD;&#xA;        corrected_value = int((value/255)**(1/2.2)*255)&#xD;&#xA;        return corrected_value&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def produce_image(image_size=(1024,1024),&#xD;&#xA;                      glasses=(((100,300),90),((300,300),110)),&#xD;&#xA;                      distribution=exponential,&#xD;&#xA;                      scale=0.1,&#xD;&#xA;                      background_level=0,&#xD;&#xA;                      gamma=2.2,&#xD;&#xA;                      filename='dusttest.png'&#xD;&#xA;                      ):&#xD;&#xA;        width, height = image_size&#xD;&#xA;        pixels = []&#xD;&#xA;        for y in range(height):&#xD;&#xA;            for x in range(width):&#xD;&#xA;                red, green, blue = pixel_value(x, y, image_size, glasses,&#xD;&#xA;                                               distribution, scale,&#xD;&#xA;                                               background_level&#xD;&#xA;                                               )&#xD;&#xA;                pixels.append((red, green, blue))&#xD;&#xA;    &#xD;&#xA;        image = Image.new('RGB', image_size, color=None)&#xD;&#xA;        image.putdata(pixels)&#xD;&#xA;        image.save(filename)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def pixel_value(x, y, image_size, glasses, distribution, scale,&#xD;&#xA;                    background_level&#xD;&#xA;                    ):&#xD;&#xA;        width, height = image_size&#xD;&#xA;        value = background_level&#xD;&#xA;        value += distribution(x, scale)&#xD;&#xA;        value += distribution(width-x, scale)&#xD;&#xA;        value += distribution(y, scale)&#xD;&#xA;        for glass in glasses:&#xD;&#xA;            coords, radius = glass&#xD;&#xA;            a, b = coords&#xD;&#xA;            distance = ((x-a) ** 2 + (y-b) ** 2) ** 0.5 - radius&#xD;&#xA;            if distance &lt; 0:&#xD;&#xA;                value = 0&#xD;&#xA;                break&#xD;&#xA;            value += distribution(distance, scale)&#xD;&#xA;        value = 255 - gamma_corrected(value)&#xD;&#xA;        return ((value, value, value))&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;        for scale in [0.1, 0.2, 0.4, 0.8]:&#xD;&#xA;            produce_image(image_size=(1024,1024),&#xD;&#xA;                      distribution=linear,&#xD;&#xA;                      scale=scale,&#xD;&#xA;                      background_level=20,&#xD;&#xA;                      filename='linear-' + str(scale) + '-dusttest.png')&#xD;&#xA;        for scale in [0.1, 0.05, 0.03, 0.01]:&#xD;&#xA;            produce_image(image_size=(1024,1024),&#xD;&#xA;                      distribution=exponential,&#xD;&#xA;                      scale=scale,&#xD;&#xA;                      background_level=0,&#xD;&#xA;                      filename='exponential-' + str(scale) + '-dusttest.png')&#xD;&#xA;&#xD;&#xA;Imagine looking down from above on a white shelf that has had drinking glasses placed on it. Some time later the glasses are removed to leave dust free circular regions and a distribution of dust over the rest of the shelf. The dust is affected by the positions of the glasses and the back and side walls. The front of the shelf (bottom of the image) is open, with no wall to increase dust.&#xD;&#xA;&#xD;&#xA;## Output&#xD;&#xA;&#xD;&#xA;*(Click for larger images)*&#xD;&#xA;&#xD;&#xA;**Linear reduction in dust density plus constant background level of dust:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][01]&#xD;&#xA;[![enter image description here][2]][02]&#xD;&#xA;[![enter image description here][3]][03]&#xD;&#xA;[![enter image description here][4]][04]&#xD;&#xA;&#xD;&#xA;**Exponential reduction in dust density (zero background level):**&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][05]&#xD;&#xA;[![enter image description here][6]][06]&#xD;&#xA;[![enter image description here][7]][07]&#xD;&#xA;[![enter image description here][8]][08]&#xD;&#xA;&#xD;&#xA;I expected the exponential version to be closer to reality, and I prefer the result visually. However, I still don't know if this is close enough.&#xD;&#xA;&#xD;&#xA;I'm looking for feedback in two ways:&#xD;&#xA;&#xD;&#xA;1. Does this distribution look right/natural to you? I want input from a wider range of human eyes, ideally with specific problems/inconsistencies.&#xD;&#xA;1. Is there a physical interpretation that would justify using the exponential distribution, or that would suggest a better one?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4FtgDm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cnyaSm.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/RXWlgm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/IgPu0m.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/4Td7bm.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/KUdEnm.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/hbgk3m.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/X29him.png&#xD;&#xA;&#xD;&#xA;  [01]: https://i.stack.imgur.com/4FtgD.png&#xD;&#xA;  [02]: https://i.stack.imgur.com/cnyaS.png&#xD;&#xA;  [03]: https://i.stack.imgur.com/RXWlg.png&#xD;&#xA;  [04]: https://i.stack.imgur.com/IgPu0.png&#xD;&#xA;  [05]: https://i.stack.imgur.com/4Td7b.png&#xD;&#xA;  [06]: https://i.stack.imgur.com/KUdEn.png&#xD;&#xA;  [07]: https://i.stack.imgur.com/hbgk3.png&#xD;&#xA;  [08]: https://i.stack.imgur.com/X29hi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="796" PostHistoryTypeId="1" PostId="278" RevisionGUID="229f1c25-998a-4d40-81e7-077887cd4b6a" CreationDate="2015-08-17T16:09:06.873" UserId="231" Text="Is there an established method of approximating dust distribution on surfaces?" ContentLicense="CC BY-SA 3.0" />
  <row Id="797" PostHistoryTypeId="3" PostId="278" RevisionGUID="229f1c25-998a-4d40-81e7-077887cd4b6a" CreationDate="2015-08-17T16:09:06.873" UserId="231" Text="|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="798" PostHistoryTypeId="5" PostId="278" RevisionGUID="07fbfff7-29ba-4ba5-8ecd-fd8c7b04a47c" CreationDate="2015-08-17T18:21:36.853" UserId="231" Comment="Add exponential squared following Alan Wolfe's suggestion of normal distribution" Text="Intuitively, dust settles onto surfaces at a higher rate in areas where the air flow is slower. This means instead of a surface gathering an even layer of dust, there will be more in corners - corners of a room/shelf, corners formed by the placement of objects on a surface, concavities in a surface.&#xD;&#xA;&#xD;&#xA;I can get an increase in realism simply by making the thickness/density of dust reduce with distance from an object, and combine that effect for several objects including walls. This naturally gives the expected ordering of thicknesses - the edges of a floor have more dust than the centre, the corners where the edges meet have more dust then the centre of the edges. However, the increase in realism from getting the order correct still leaves the problem of getting the ratio right. There is more dust in the places you expect to have more dust, but not necessarily the right amount more.&#xD;&#xA;&#xD;&#xA;Is there an established method of approximating a realistic ratio of thickness between different points on a surface? I don't need this to be completely physically accurate (that would need to take into account objects that move through the environment during the long period taken for dust to accumulate). I'm just looking for average behaviour that will look believable to the human eye.&#xD;&#xA;&#xD;&#xA;In searching online I've mostly found atmospheric models for suspended dust, rather than a way of modelling dust deposition on a surface.&#xD;&#xA;&#xD;&#xA;## My attempts - linear and exponential distributions&#xD;&#xA;Here is some code in Python 3 using pillow (the PIL fork) that demonstrates a couple of distributions I have experimented with:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;    &#xD;&#xA;    from PIL import Image&#xD;&#xA;    from math import exp&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def linear(distance, scale):&#xD;&#xA;        return max(0, 64 - distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def exponential(distance, scale):&#xD;&#xA;        return 64 * exp(-distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def exponential_squared(distance, scale):&#xD;&#xA;        return 64 * exp(-distance * distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def gamma_corrected(value):&#xD;&#xA;        corrected_value = int((value/255)**(1/2.2)*255)&#xD;&#xA;        return corrected_value&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def produce_image(image_size=(1024,1024),&#xD;&#xA;                      glasses=(((100,300),90),((300,300),110)),&#xD;&#xA;                      distribution=exponential,&#xD;&#xA;                      scale=0.1,&#xD;&#xA;                      background_level=0,&#xD;&#xA;                      gamma=2.2,&#xD;&#xA;                      filename='dusttest.png'&#xD;&#xA;                      ):&#xD;&#xA;        width, height = image_size&#xD;&#xA;        pixels = []&#xD;&#xA;        for y in range(height):&#xD;&#xA;            for x in range(width):&#xD;&#xA;                red, green, blue = pixel_value(x, y, image_size, glasses,&#xD;&#xA;                                               distribution, scale,&#xD;&#xA;                                               background_level&#xD;&#xA;                                               )&#xD;&#xA;                pixels.append((red, green, blue))&#xD;&#xA;    &#xD;&#xA;        image = Image.new('RGB', image_size, color=None)&#xD;&#xA;        image.putdata(pixels)&#xD;&#xA;        image.save(filename)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def pixel_value(x, y, image_size, glasses, distribution, scale,&#xD;&#xA;                    background_level&#xD;&#xA;                    ):&#xD;&#xA;        width, height = image_size&#xD;&#xA;        value = background_level&#xD;&#xA;        value += distribution(x, scale)&#xD;&#xA;        value += distribution(width-x, scale)&#xD;&#xA;        value += distribution(y, scale)&#xD;&#xA;        for glass in glasses:&#xD;&#xA;            coords, radius = glass&#xD;&#xA;            a, b = coords&#xD;&#xA;            distance = ((x-a) ** 2 + (y-b) ** 2) ** 0.5 - radius&#xD;&#xA;            if distance &lt; 0:&#xD;&#xA;                value = 0&#xD;&#xA;                break&#xD;&#xA;            value += distribution(distance, scale)&#xD;&#xA;        value = 255 - gamma_corrected(value)&#xD;&#xA;        return ((value, value, value))&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;        for scale in [0.1, 0.2, 0.4, 0.8]:&#xD;&#xA;            produce_image(distribution=linear,&#xD;&#xA;                          scale=scale,&#xD;&#xA;                          background_level=20,&#xD;&#xA;                          filename='linear-' + str(scale) + '-dusttest.png'&#xD;&#xA;                          )&#xD;&#xA;        for scale in [0.1, 0.05, 0.03, 0.01]:&#xD;&#xA;            produce_image(distribution=exponential,&#xD;&#xA;                          scale=scale,&#xD;&#xA;                          background_level=0,&#xD;&#xA;                          filename='exponential-' + str(scale) + '-dusttest.png'&#xD;&#xA;                          )&#xD;&#xA;        for scale in [0.01, 0.001, 0.0001, 0.00001]:&#xD;&#xA;            produce_image(distribution=exponential_squared,&#xD;&#xA;                          scale=scale,&#xD;&#xA;                          background_level=0,&#xD;&#xA;                          filename='exponential-squared-' + str(scale) + '-dusttest.png'&#xD;&#xA;                          )&#xD;&#xA;&#xD;&#xA;Imagine looking down from above on a white shelf that has had drinking glasses placed on it. Some time later the glasses are removed to leave dust free circular regions and a distribution of dust over the rest of the shelf. The dust is affected by the positions of the glasses and the back and side walls. The front of the shelf (bottom of the image) is open, with no wall to increase dust.&#xD;&#xA;&#xD;&#xA;## Output&#xD;&#xA;&#xD;&#xA;*(Click for larger images)*&#xD;&#xA;&#xD;&#xA;**Linear reduction in dust density plus constant background level of dust:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][linear1m]][linear1]&#xD;&#xA;[![enter image description here][linear2m]][linear2]&#xD;&#xA;[![enter image description here][linear3m]][linear3]&#xD;&#xA;[![enter image description here][linear4m]][linear4]&#xD;&#xA;&#xD;&#xA;**Exponential reduction in dust density (zero background level):**&#xD;&#xA;&#xD;&#xA;[![enter image description here][exp1m]][exp1]&#xD;&#xA;[![enter image description here][exp2m]][exp2]&#xD;&#xA;[![enter image description here][exp3m]][exp3]&#xD;&#xA;[![enter image description here][exp4m]][exp4]&#xD;&#xA;&#xD;&#xA;I expected the exponential version to be closer to reality, and I prefer the result visually. However, I still don't know if this is close enough.&#xD;&#xA;&#xD;&#xA;**Following [Alan Wolfe]'s suggestion of the normal distribution, I've also added images using `exp(-distance ** 2)` at a variety of scales.**&#xD;&#xA;&#xD;&#xA;[![enter image description here][exp2_1m]][exp2_1]&#xD;&#xA;[![enter image description here][exp2_2m]][exp2_2]&#xD;&#xA;[![enter image description here][exp2_3m]][exp2_3]&#xD;&#xA;[![enter image description here][exp2_4m]][exp2_4]&#xD;&#xA;&#xD;&#xA;I quite like this too, but I still couldn't guess which of this and exponential (`exp(-distance)`) is best.&#xD;&#xA;&#xD;&#xA;I'm looking for feedback in two ways:&#xD;&#xA;&#xD;&#xA;1. Do any of these distributions look right/natural to you? I want input from a wider range of human eyes, ideally with specific problems/inconsistencies.&#xD;&#xA;1. Is there a physical interpretation that would justify using one of these distributions, or that would suggest a better one?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [linear1m]: https://i.stack.imgur.com/4FtgDm.png&#xD;&#xA;  [linear1]: https://i.stack.imgur.com/4FtgD.png&#xD;&#xA;  [linear2m]: https://i.stack.imgur.com/cnyaSm.png&#xD;&#xA;  [linear2]: https://i.stack.imgur.com/cnyaS.png&#xD;&#xA;  [linear3m]: https://i.stack.imgur.com/RXWlgm.png&#xD;&#xA;  [linear3]: https://i.stack.imgur.com/RXWlg.png&#xD;&#xA;  [linear4m]: https://i.stack.imgur.com/IgPu0m.png&#xD;&#xA;  [linear4]: https://i.stack.imgur.com/IgPu0.png&#xD;&#xA;  [exp1m]: https://i.stack.imgur.com/4Td7bm.png&#xD;&#xA;  [exp1]: https://i.stack.imgur.com/4Td7b.png&#xD;&#xA;  [exp2m]: https://i.stack.imgur.com/KUdEnm.png&#xD;&#xA;  [exp2]: https://i.stack.imgur.com/KUdEn.png&#xD;&#xA;  [exp3m]: https://i.stack.imgur.com/hbgk3m.png&#xD;&#xA;  [exp3]: https://i.stack.imgur.com/hbgk3.png&#xD;&#xA;  [exp4m]: https://i.stack.imgur.com/X29him.png&#xD;&#xA;  [exp4]: https://i.stack.imgur.com/X29hi.png&#xD;&#xA;  [exp2_1m]: https://i.stack.imgur.com/n1oOrm.png&#xD;&#xA;  [exp2_1]: https://i.stack.imgur.com/n1oOr.png&#xD;&#xA;  [exp2_2m]: https://i.stack.imgur.com/2SJD9m.png&#xD;&#xA;  [exp2_2]: https://i.stack.imgur.com/2SJD9.png&#xD;&#xA;  [exp2_3m]: https://i.stack.imgur.com/LVfCgm.png&#xD;&#xA;  [exp2_3]: https://i.stack.imgur.com/LVfCg.png&#xD;&#xA;  [exp2_4m]: https://i.stack.imgur.com/M0N8om.png&#xD;&#xA;  [exp2_4]: https://i.stack.imgur.com/M0N8o.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Alan Wolfe]: http://computergraphics.stackexchange.com/users/56/alan-wolfe" ContentLicense="CC BY-SA 3.0" />
  <row Id="799" PostHistoryTypeId="5" PostId="276" RevisionGUID="b963db08-9a28-48ca-ba1c-bf1ee43f82ed" CreationDate="2015-08-18T02:02:18.880" UserId="159" Comment="added 43 characters in body" Text="See Kolb, et al., [*A Realistic Camera Model for Computer Graphics*][1], SIGGRAPH 95.&#xD;&#xA;&#xD;&#xA;However, do bear in mind that camera models which mimic real-world cameras aren't necessarily what you want for the rendering phase. In a visual effects/post-production scenario, the more blur/vignetting/distortion that the camera model introduces, the worse it is for the compositor/colour timer. It's often better to do it as a post-pass.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Cameras/Realistic%20Camera%20Model.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="801" PostHistoryTypeId="34" PostId="15" RevisionGUID="b545b3cd-a929-4e82-9bbb-499be8783392" CreationDate="2015-08-18T03:29:32.393" UserId="-1" Comment="2" />
  <row Id="803" PostHistoryTypeId="2" PostId="279" RevisionGUID="c784d46e-8baf-45b3-b88e-24d727a986ea" CreationDate="2015-08-18T05:30:15.183" UserId="192" Text="See the paper [Computer Modelling of Fallen Snow](http://dx.doi.org/10.1145/344779.344809) published in SIGGRAPH 2000.&#xD;&#xA;&#xD;&#xA;See also what seems to be its [project page](http://www.cs.ubc.ca/nest/imager/contributions/fearing/snow/snow.html).&#xD;&#xA;&#xD;&#xA;An older paper is [Simulating Dust Accumulation](http://www.cse.cuhk.edu.hk/~ttwong/papers/dust/dust.html)." ContentLicense="CC BY-SA 3.0" />
  <row Id="804" PostHistoryTypeId="2" PostId="280" RevisionGUID="3f5a6fef-a4e3-45c0-9c76-bd20d5eb38ed" CreationDate="2015-08-18T08:24:37.133" UserId="386" Text="I have a shader with some condition. But for the entire draw call I'm using the same condition from the constant. Is condition anyway will be executed every time? Or maybe it's better to have 2 different shader and switch between them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="805" PostHistoryTypeId="1" PostId="280" RevisionGUID="3f5a6fef-a4e3-45c0-9c76-bd20d5eb38ed" CreationDate="2015-08-18T08:24:37.133" UserId="386" Text="Condition in the shader. What if the condition always the same?" ContentLicense="CC BY-SA 3.0" />
  <row Id="806" PostHistoryTypeId="3" PostId="280" RevisionGUID="3f5a6fef-a4e3-45c0-9c76-bd20d5eb38ed" CreationDate="2015-08-18T08:24:37.133" UserId="386" Text="|gpu|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="807" PostHistoryTypeId="34" PostId="51" RevisionGUID="4cfb2283-bf6e-4e2a-a1e1-60d21b9aa792" CreationDate="2015-08-18T08:57:52.260" UserId="16" Comment="3" />
  <row Id="808" PostHistoryTypeId="2" PostId="281" RevisionGUID="41dd0540-5567-4d5b-820b-24bbb38adf75" CreationDate="2015-08-18T09:16:17.933" UserId="137" Text="On modern hardware if all invocations in a group follow the same path then the unused path doesn't get evaluated.&#xD;&#xA;&#xD;&#xA;in pseudo code:&#xD;&#xA;&#xD;&#xA;    if(cond){&#xD;&#xA;       res = ...&#xD;&#xA;    }else{&#xD;&#xA;       res = ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;becomes&#xD;&#xA;&#xD;&#xA;    condBallot = ballot(cond);&#xD;&#xA;    if(ANY(condBallot)){&#xD;&#xA;        res1 = ...&#xD;&#xA;    }&#xD;&#xA;    if(ANY_NOT(condBallot)){&#xD;&#xA;        res2 = ...&#xD;&#xA;    }&#xD;&#xA;    res = cond?res1:res2;&#xD;&#xA;&#xD;&#xA;Where `ballot` groups the conditions in the same group and `ANY` and `ANY_NOT` will be true if any condition is true or false respectively.&#xD;&#xA;&#xD;&#xA;If cond is derivable from uniforms alone then the driver may optimize and evaluate the condition and replace the if with a goto to the correct branch. OpenGL has a feature called uniform subroutines that makes it explicit." ContentLicense="CC BY-SA 3.0" />
  <row Id="814" PostHistoryTypeId="5" PostId="64" RevisionGUID="840c8e1c-c858-45cf-a03b-983dd6878e4b" CreationDate="2015-08-18T12:17:27.583" UserId="6" Comment="added 108 characters in body" Text="In entirely technical terms, `fwidth(p)` is defined as&#xD;&#xA;&#xD;&#xA;    fwidth(p) := abs(dFdx(p)) + abs(dFdy(p))&#xD;&#xA;&#xD;&#xA;And `dFdx(p)`/`dFdy(p)` are the partial derivates of the value `p` with respect to the `x` and `y` screen dimensions. So they denote how the value of `p` behaves when going one pixel to the right (`x`) or one pixel up (`y`).&#xD;&#xA;&#xD;&#xA;Now how can they be practically computed? Well, if you know the neighbour pixels' values for `p`, you can just compute those derivates as direct **finite differences** as an approximation for their actual mathematical derivatives (which might not have an exact analytical solution at all):&#xD;&#xA;&#xD;&#xA;    dFdx(p) := p(x+1) - p(x)&#xD;&#xA;&#xD;&#xA;But of course now you may ask, how do we even know the values of `p` (which could afterall be any arbitrarily computed value inside the shader program) for the neighbouring pixels? How do we compute those values without incurring major overhead by doing the whole shader computation two (or three) times?&#xD;&#xA;&#xD;&#xA;Well, you know what, those neighbouring values are computed anyway, since for the neighbouring pixel you also run a fragment shader. So all that you need is access to this neighbouring fragment shader invocation when run for the neighbouring pixel. But it's even easier, because those neighbouring values are also computed at the exact same time.&#xD;&#xA;&#xD;&#xA;Modern rasterizers call fragment shaders in larger tiles of more than one neighbouring pixels. At the smallest those would be a 2x2 grid of pixels. And for each such a pixel block the fragment shader is invoked for each pixel and those invocations run **in perfectly parallel lock-step** so that all computations are done in the exact same order and at the exact same time for each of those pixels in the block (which is also why branching in the fragment shader, while not deadly, should be avoided if possible, since each invocation of a block would have to explore every branch that is taken by at least one of the invocations, even if it just throws away the results afterwards, as also adressed in the answers to [this related question](http://computergraphics.stackexchange.com/q/259/6)). So at any moment, a fragment shader theoretically has access to its neighbouring pixels' fragment shader values. And while you don't have direct access to those values, you have access to values computed from them, like the derivative functions `dFdx`, `dFdy`, `fwidth`, ..." ContentLicense="CC BY-SA 3.0" />
  <row Id="815" PostHistoryTypeId="5" PostId="280" RevisionGUID="de0c375f-ea78-428f-aaf6-a67dd27fec57" CreationDate="2015-08-18T14:51:11.380" UserId="386" Comment="added 98 characters in body" Text="I have a shader with some condition. It can be any shader in any stage (vertex, compute, etc.). But for the entire draw call/dispatch I'm using the same condition from the constant. Is the condition will be executed anyway every time when the shader executed? Or maybe it's better to have 2 different shaders and switch between them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="817" PostHistoryTypeId="5" PostId="279" RevisionGUID="f328cb4e-65b0-46f2-a80b-4e5658907640" CreationDate="2015-08-18T16:05:41.870" UserId="192" Comment="added 1667 characters in body" Text="See the paper [Computer Modelling of Fallen Snow](http://dx.doi.org/10.1145/344779.344809) published in SIGGRAPH 2000:&#xD;&#xA;&#xD;&#xA;&gt; In this paper, we present a new model of snow accumulation and stability for computer graphics. Our contribution is divided into two major components, each essential for modelling the appearance of a thick layer of snowfall on the ground. Our accumulation model determines how much snow a particular surface receives, allowing for such phenomena as flake flutter, flake dusting and wind-blown snow. We compute snow accumulation by shooting particles upwards towards the sky, giving each source surface independent control over its own sampling density, accuracy and computation time. Importance ordering minimises sampling effort while maximising visual information, generating smoothly improving global results that can be interrupted at any point. Once snow lands on the ground, our stability model moves material away from physically unstable areas in a series of small, simultaneous avalanches. We use a simple local stability test that handles very steep surfaces, obstacles, edges, and wind transit. Our stability algorithm also handles other materials, such as flour, sand, and flowing water.&#xD;&#xA;&#xD;&#xA;Its [project page](http://www.cs.ubc.ca/nest/imager/contributions/fearing/snow/snow.html) contains explanations and example images. A PDF is [here](https://graphics.stanford.edu/courses/cs448-01-spring/papers/fearing.pdf).&#xD;&#xA;&#xD;&#xA;An older paper is [Simulating Dust Accumulation](http://www.cse.cuhk.edu.hk/~ttwong/papers/dust/dust.html):&#xD;&#xA;&#xD;&#xA;&gt; This paper describes a dust modeling technique. An empirical method is used to visually simulate the effect of dust accumulation on object surfaces. The dust amount is first predicted based on the properties of the surfaces: the surface inclination and stickiness. This predicted amount is then adjusted according to some external factors: surface exposure to wind and scraping off by other objects. The calculated dust amount is finally perturbed by a noise function on rendering to give a fuzzy visual effect." ContentLicense="CC BY-SA 3.0" />
  <row Id="818" PostHistoryTypeId="2" PostId="283" RevisionGUID="7ef9b91a-7bf2-42c2-b307-46f98352c9b2" CreationDate="2015-08-18T17:52:08.047" UserId="231" Text="*I'm interested in how this applies to higher numbers of dimensions too, but for this question I will focus solely on 2D grids.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I know that Perlin noise is not isotropic (direction invariant), and that the underlying square grid shows up enough to be able to identify its orientation. Simplex noise is an improvement on this but its underlying equilateral triangle grid is still not completely obscured.&#xD;&#xA;&#xD;&#xA;My intuition is that any attempt to make noise of a particular frequency on a grid will result in a lower frequency in directions not aligned to the grid. So while attempts can be made to disguise this, the noise cannot in principle be isotropic unless it is generated without reference to a grid, allowing the average frequency to be the same in all directions.&#xD;&#xA;&#xD;&#xA;For example, with a square grid without noise, with square side length [![n][n]][n link], the frequency of vertices horizontally or vertically is [![1/n][1/n]][1/n link], whereas the frequency of vertices at 45 degrees (through opposite corners of the squares) is [![1/sqrt(2)n][1/sqrt(2)n]][1/sqrt(2)n link]. &#xD;&#xA;&#xD;&#xA;[![Square grid showing length of edge and diagonal][grid]][grid]&#xD;&#xA;&#xD;&#xA;Is there a random distribution that could be applied to offset the vertex positions that would result in the frequency becoming identical in all directions? My suspicion is that there is no such distribution, but I don't have a way of proving either way.&#xD;&#xA;&#xD;&#xA;In short, is there a way of making perfect grid based noise of a given frequency, or should I be focused on other approaches (non-grid based noise or ways of disguising artefacts)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [n]: http://mathurl.com/5cmxoc.png &quot;edit on mathurl.com&quot;&#xD;&#xA;  [n link]: http://mathurl.com/5cmxoc&#xD;&#xA;  [1/n]: http://mathurl.com/bso3q2o.png &quot;edit on mathurl.com&quot;&#xD;&#xA;  [1/n link]: http://mathurl.com/bso3q2o&#xD;&#xA;  [1/sqrt(2)n]: http://mathurl.com/pme2apf.png &quot;edit on mathurl.com&quot;&#xD;&#xA;  [1/sqrt(2)n link]: http://mathurl.com/pme2apf&#xD;&#xA;&#xD;&#xA;  [grid]: https://i.stack.imgur.com/Uzc5Y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="819" PostHistoryTypeId="1" PostId="283" RevisionGUID="7ef9b91a-7bf2-42c2-b307-46f98352c9b2" CreationDate="2015-08-18T17:52:08.047" UserId="231" Text="Is all grid based noise inevitably anisotropic?" ContentLicense="CC BY-SA 3.0" />
  <row Id="820" PostHistoryTypeId="3" PostId="283" RevisionGUID="7ef9b91a-7bf2-42c2-b307-46f98352c9b2" CreationDate="2015-08-18T17:52:08.047" UserId="231" Text="|noise|grid|" ContentLicense="CC BY-SA 3.0" />
  <row Id="821" PostHistoryTypeId="5" PostId="279" RevisionGUID="45e70418-3a95-4ad9-a970-aac58652f63a" CreationDate="2015-08-18T18:22:01.660" UserId="192" Comment="added 62 characters in body" Text="See the paper [Computer Modelling of Fallen Snow](http://dx.doi.org/10.1145/344779.344809) published in SIGGRAPH 2000:&#xD;&#xA;&#xD;&#xA;&gt; In this paper, we present a new model of snow accumulation and stability for computer graphics. Our contribution is divided into two major components, each essential for modelling the appearance of a thick layer of snowfall on the ground. Our accumulation model determines how much snow a particular surface receives, allowing for such phenomena as flake flutter, flake dusting and wind-blown snow. We compute snow accumulation by shooting particles upwards towards the sky, giving each source surface independent control over its own sampling density, accuracy and computation time. Importance ordering minimises sampling effort while maximising visual information, generating smoothly improving global results that can be interrupted at any point. Once snow lands on the ground, our stability model moves material away from physically unstable areas in a series of small, simultaneous avalanches. We use a simple local stability test that handles very steep surfaces, obstacles, edges, and wind transit. Our stability algorithm also handles other materials, such as flour, sand, and flowing water.&#xD;&#xA;&#xD;&#xA;Its [project page](http://www.cs.ubc.ca/nest/imager/contributions/fearing/snow/snow.html) contains explanations and example images. A PDF is [here](https://graphics.stanford.edu/courses/cs448-01-spring/papers/fearing.pdf).&#xD;&#xA;&#xD;&#xA;An older paper is [Simulating Dust Accumulation](http://www.cse.cuhk.edu.hk/~ttwong/papers/dust/dust.html), published in *IEEE Computer Graphics &amp; Applications* in 1995:&#xD;&#xA;&#xD;&#xA;&gt; This paper describes a dust modeling technique. An empirical method is used to visually simulate the effect of dust accumulation on object surfaces. The dust amount is first predicted based on the properties of the surfaces: the surface inclination and stickiness. This predicted amount is then adjusted according to some external factors: surface exposure to wind and scraping off by other objects. The calculated dust amount is finally perturbed by a noise function on rendering to give a fuzzy visual effect." ContentLicense="CC BY-SA 3.0" />
  <row Id="822" PostHistoryTypeId="5" PostId="251" RevisionGUID="d7a4d312-b834-4824-b23a-14cd6ef6a96c" CreationDate="2015-08-18T18:26:56.627" UserId="192" Comment="added 90 characters in body" Text="A good starting point is the classic paper [Using particles to sample and control implicit surfaces](http://dl.acm.org/citation.cfm?id=192227), published in SIGGRAPH 1994.&#xD;&#xA;&#xD;&#xA;A simple particle simulation described in the paper [Sampling implicit objects with physically-based particle systems&#xD;&#xA;](http://dx.doi.org/10.1016/0097-8493(96)00005-2) (*Computers &amp; Graphics*, 1996) for curves works for surfaces as well; see [Dynamic Texture for Implicit Surfaces](http://www.visgraf.impa.br/Projects/dtexture/) for examples.&#xD;&#xA;&#xD;&#xA;For a more recent example, see [Shape and tone depiction for implicit surfaces](http://dx.doi.org/10.1016/j.cag.2010.09.017) (*Computers &amp; Graphics*, 2011). " ContentLicense="CC BY-SA 3.0" />
  <row Id="823" PostHistoryTypeId="2" PostId="284" RevisionGUID="758c3001-3d57-46e2-afc5-c458ceacfbb8" CreationDate="2015-08-19T11:08:31.647" UserId="120" Text="Suppose we already have UV coordinates assigned for mesh vertices,&#xD;&#xA;how is texture baking implemented?&#xD;&#xA;&#xD;&#xA;I guess it will be something like this:&#xD;&#xA;&#xD;&#xA;    for each coordinate (u, v) in parameter space:&#xD;&#xA;        (x, y, z) = inverse(u, v) # Get the geometric space coordinate.&#xD;&#xA;        f = faces(x, y, z) # Get the corresponding face. We may need face's normal for rendering.&#xD;&#xA;        pixels[u, v] = render(x, y, z, f)&#xD;&#xA;&#xD;&#xA;What is the `inverse` function? Is it a projective transformation, or a bilinear transformation?&#xD;&#xA;&#xD;&#xA;And how to get the corresponding face of one coordinate (u, v) efficiently?" ContentLicense="CC BY-SA 3.0" />
  <row Id="824" PostHistoryTypeId="1" PostId="284" RevisionGUID="758c3001-3d57-46e2-afc5-c458ceacfbb8" CreationDate="2015-08-19T11:08:31.647" UserId="120" Text="How is texture baking implemented?" ContentLicense="CC BY-SA 3.0" />
  <row Id="825" PostHistoryTypeId="3" PostId="284" RevisionGUID="758c3001-3d57-46e2-afc5-c458ceacfbb8" CreationDate="2015-08-19T11:08:31.647" UserId="120" Text="|rendering|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="827" PostHistoryTypeId="2" PostId="285" RevisionGUID="861b12a4-6005-42bd-882c-b2dd01ebe9e1" CreationDate="2015-08-19T14:31:40.733" UserId="38" Text="The inverse coordinate is not entirely trivial in all cases. But basically, for a basic triangle mesh with nothing exotic and has nonoverlapping UV's, you need something like this:&#xD;&#xA;&#xD;&#xA;1. For the UV coordinate you need to find the corresponding  UV triangle. &#xD;&#xA;&#xD;&#xA;2. Then calculate the barycentric triangle coordinate. Most raytracers have simple implementations for this.&#xD;&#xA;&#xD;&#xA;3. From bary coordinate  to 3d its just&#xD;&#xA;&#xD;&#xA;        b1*p1_3d + b2*p2_3d+ b3*p3_3d&#xD;&#xA;&#xD;&#xA;    Where b are barycentric cords from step 2. and p's triangle point vectors&#xD;&#xA;&#xD;&#xA;##How to accelerate the triangle finding. &#xD;&#xA;&#xD;&#xA;You can do a a sweeping search in O(log(n)) time. You can also use a a bsp tree to do much the same. This would produce a  O(m*log(n)) algorithm where m is number of samples and n triangles. Sounds good.&#xD;&#xA;&#xD;&#xA;**Wait**, we can do better! What if instead of baking each pixel in order we bake each triangle in order. Then you dont have to go find the triangle. Finding the points in a triangle should be trivial. So you get something more akin to a theroretical O(m) algorithm. Which should be both conceptually easier and atleast theoretically faster." ContentLicense="CC BY-SA 3.0" />
  <row Id="828" PostHistoryTypeId="2" PostId="286" RevisionGUID="7fc234e4-40b5-49a7-a653-2740ac917c7b" CreationDate="2015-08-19T14:36:39.547" UserId="250" Text="I was looking into ways to implement multiple lights shading and I've noticed Unity uses multiple passes to achieve it [1]. It performs a base pass to apply the brightest directional pixel light + 4 vertex lights + SHs and a additional pass for each pixel light up to a limit defined by user on editor.&#xD;&#xA;&#xD;&#xA;I'm wondering, since I previously know how many pixels lights I need to shade, why not doing it in a single pass like vertex lights are done? What are the problems of doing so?&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;[1] http://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="829" PostHistoryTypeId="1" PostId="286" RevisionGUID="7fc234e4-40b5-49a7-a653-2740ac917c7b" CreationDate="2015-08-19T14:36:39.547" UserId="250" Text="Multiple Lights Shading - One Pass vs Multiple Passes" ContentLicense="CC BY-SA 3.0" />
  <row Id="830" PostHistoryTypeId="3" PostId="286" RevisionGUID="7fc234e4-40b5-49a7-a653-2740ac917c7b" CreationDate="2015-08-19T14:36:39.547" UserId="250" Text="|lighting|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="831" PostHistoryTypeId="5" PostId="285" RevisionGUID="98fa482f-4c2d-41b8-95b4-2b3d1139ff51" CreationDate="2015-08-19T14:40:05.967" UserId="38" Comment="added 26 characters in body" Text="The inverse coordinate is not entirely trivial in all cases. But basically, for a basic triangle mesh with nothing exotic and has nonoverlapping UV's, you need something like this:&#xD;&#xA;&#xD;&#xA;1. For the UV coordinate you need to find the corresponding  UV triangle. (step can be eliminated see below)&#xD;&#xA;&#xD;&#xA;2. Then calculate the barycentric triangle coordinate. Most raytracers have simple implementations for this.&#xD;&#xA;&#xD;&#xA;3. From bary coordinate  to 3d its just&#xD;&#xA;&#xD;&#xA;        b1*p1_3d + b2*p2_3d+ b3*p3_3d&#xD;&#xA;&#xD;&#xA;    Where b are barycentric cords from step 2. and p's triangle point vectors&#xD;&#xA;&#xD;&#xA;##How to accelerate the triangle finding. &#xD;&#xA;&#xD;&#xA;You can do a a sweeping search in O(log(n)) time. You can also use a a bsp tree to do much the same. This would produce a  O(m*log(n)) algorithm where m is number of samples and n triangles. Sounds good.&#xD;&#xA;&#xD;&#xA;**Wait**, we can do better! What if instead of baking each pixel in order we bake each triangle in order. Then you dont have to go find the triangle. Finding the points in a triangle should be trivial. So you get something more akin to a theroretical O(m) algorithm. Which should be both conceptually easier and atleast theoretically faster as you eliminate step 1." ContentLicense="CC BY-SA 3.0" />
  <row Id="832" PostHistoryTypeId="5" PostId="285" RevisionGUID="11e6b0ec-09dd-43c9-aae7-998bf3b8af1e" CreationDate="2015-08-19T15:06:40.013" UserId="38" Comment="added 127 characters in body" Text="The inverse coordinate is not entirely trivial in all cases. But basically, for a basic triangle mesh with nothing exotic and has nonoverlapping UV's, you need something like this:&#xD;&#xA;&#xD;&#xA;1. For the UV coordinate you need to find the corresponding  UV triangle. (step can be eliminated see below)&#xD;&#xA;&#xD;&#xA;2. Then calculate the barycentric triangle coordinate. Most raytracers have simple implementations for this.&#xD;&#xA;&#xD;&#xA;3. From bary coordinate  to 3d its just&#xD;&#xA;&#xD;&#xA;        b1*p1_3d + b2*p2_3d+ b3*p3_3d&#xD;&#xA;&#xD;&#xA;    Where b are barycentric cords from step 2. and p's triangle point vectors&#xD;&#xA;&#xD;&#xA;##How to accelerate the triangle finding. &#xD;&#xA;&#xD;&#xA;You can do a a sweeping search in O(log(n)) time. You can also use a a bsp tree to do much the same. This would produce a  O(m*log(n)) algorithm where m is number of samples and n triangles. Sounds good.&#xD;&#xA;&#xD;&#xA;**Wait**, we can do better! What if instead of baking each pixel in order we bake each triangle in order. Then you dont have to go find the triangle. Finding the points in a triangle should be trivial. So you get something more akin to a theroretical O(m) algorithm. Which should be both conceptually easier and atleast theoretically faster as you eliminate step 1.&#xD;&#xA;&#xD;&#xA;Also in the second case you can forego barycentric calculation if you so wish and use an alternate formulation if ypu wish." ContentLicense="CC BY-SA 3.0" />
  <row Id="833" PostHistoryTypeId="5" PostId="286" RevisionGUID="400b304a-dd0a-4d2d-a407-99eff93a5a08" CreationDate="2015-08-19T17:39:10.050" UserId="54" Comment="Moved hyperlink to text; Fixed a couple minor typos." Text="I was looking into ways to implement multiple lights shading and I've noticed [Unity uses multiple passes to achieve it][1]. It performs a base pass to apply the brightest directional pixel light + 4 vertex lights + SHs and an additional pass for each pixel light, up to a limit defined by the user on the editor.&#xD;&#xA;&#xD;&#xA;I'm wondering, since I previously know how many pixels lights I need to shade, why not doing it in a single pass like vertex lights are done? What are the problems of doing so?&#xD;&#xA;&#xD;&#xA;[1]: http://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="834" PostHistoryTypeId="5" PostId="285" RevisionGUID="c4ad1b97-36ad-4b62-ae4a-4938a09a7e2c" CreationDate="2015-08-19T19:29:59.697" UserId="38" Comment="added 184 characters in body" Text="The inverse coordinate is not entirely trivial in all cases. But basically, for a basic triangle mesh with nothing exotic and has non overlapping UV's, you need something like this:&#xD;&#xA;&#xD;&#xA;1. For the UV coordinate you need to find the corresponding  UV triangle. (step can be eliminated see below)&#xD;&#xA;&#xD;&#xA;2. Then calculate the barycentric triangle coordinate. Most raytracers have simple implementations for this.&#xD;&#xA;&#xD;&#xA;3. From bary coordinate  to 3d its just&#xD;&#xA;&#xD;&#xA;        b1*p1_3d + b2*p2_3d+ b3*p3_3d&#xD;&#xA;&#xD;&#xA;    Where b are barycentric cords from step 2. and p's triangle point vectors&#xD;&#xA;&#xD;&#xA;##How to accelerate the triangle finding. &#xD;&#xA;&#xD;&#xA;You can do a a sweeping search in O(log(n)) time. You can also use a a bsp tree to do much the same. This would produce a  O(m*log(n)) algorithm where m is number of samples and n triangles. Sounds good.&#xD;&#xA;&#xD;&#xA;**Wait**, we can do better! What if instead of baking each pixel in order we bake each triangle in order. Then you dont have to go find the triangle. Finding the points in a triangle should be trivial. So you get something more akin to a theoretical O(m) algorithm. Which should be both conceptually easier and at least theoretically faster as you eliminate step 1.&#xD;&#xA;&#xD;&#xA;Also in the second case you can forego barycentric calculation if you so wish and use an alternate formulation if you wish.&#xD;&#xA;&#xD;&#xA;[![Sweeping one polygon][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Sweeping one polygon at a time is easier and needs not search for polygon in question.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5FXdd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="835" PostHistoryTypeId="2" PostId="287" RevisionGUID="f00cb37c-0147-4c5c-a8bb-abfb27d8776d" CreationDate="2015-08-19T22:52:54.560" UserId="231" Text="I understand how a 1D Fourier transform separates a signal into its component frequencies, but I'm having difficulty understanding how a 2D Fourier transform affects a 2D image.&#xD;&#xA;&#xD;&#xA;From another question, [John Calsbeek] linked to an [interesting paper about measuring the quality of noise functions]. This showed various noise functions and the Fourier transform of each.&#xD;&#xA;&#xD;&#xA;Is this a discrete transform of the pixel data, or a continuous transform of the continuous interpolating function which is used to generate the noise at arbitrary points?&#xD;&#xA;&#xD;&#xA;Is the annular shape analagous to taking 1D Fourier transforms of the line through the centre of the image at every possible angle? Or is the transform for each possible angle also measured across the whole 2D space rather than only along a line through the centre? I'm trying to get an intuitive feel for what changes in the input image correspond to what changes in the Fourier transform.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [John Calsbeek]: http://computergraphics.stackexchange.com/users/196/john-calsbeek&#xD;&#xA;&#xD;&#xA;  [interesting paper about measuring the quality of noise functions]: http://www.cs.utah.edu/~aek/research/noise.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="836" PostHistoryTypeId="1" PostId="287" RevisionGUID="f00cb37c-0147-4c5c-a8bb-abfb27d8776d" CreationDate="2015-08-19T22:52:54.560" UserId="231" Text="How does a 2D Fourier Transform of an image work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="837" PostHistoryTypeId="3" PostId="287" RevisionGUID="f00cb37c-0147-4c5c-a8bb-abfb27d8776d" CreationDate="2015-08-19T22:52:54.560" UserId="231" Text="|noise|fourier-transform|" ContentLicense="CC BY-SA 3.0" />
  <row Id="839" PostHistoryTypeId="33" PostId="185" RevisionGUID="69e9efc5-7356-4c33-a7f2-1a8efc8ae18e" CreationDate="2015-08-19T23:55:27.410" UserId="231" Comment="4" />
  <row Id="840" PostHistoryTypeId="33" PostId="166" RevisionGUID="0a0a590e-0365-4199-87d7-a8a3607777cf" CreationDate="2015-08-19T23:55:58.060" UserId="231" Comment="5" />
  <row Id="841" PostHistoryTypeId="33" PostId="277" RevisionGUID="eef820fe-3140-4864-bdba-80f9858c5d39" CreationDate="2015-08-19T23:56:31.057" UserId="231" Comment="6" />
  <row Id="842" PostHistoryTypeId="2" PostId="289" RevisionGUID="7da2eb6c-207c-4126-ae33-b4eb15cd1201" CreationDate="2015-08-20T05:35:41.600" UserId="48" Text="There are two cases I can think of where multiple blurs would be performed in succession on a single image.&#xD;&#xA;&#xD;&#xA;First, when performing a large-radius blur, it may reduce the total computation if you first downsample the image (which is a blur) and then perform a smaller-radius blur on the downsampled image.  For example, downsampling an image by 4x and then performing a 10px-wide Gaussian blur on the result would approximate performing a 40px-wide Gaussian blur on the original&amp;mdash;but is likely to be significantly faster due to improved locality in sampling and fewer samples taken overall.&#xD;&#xA;&#xD;&#xA;![Box approximation of a wide Gaussian][1]&#xD;&#xA;&#xD;&#xA;The initial downsampling filter is often simply a box (as shown above), but it can also itself be something more sophisticated, such as a triangle or bicubic filter, in order to improve the approximation.&#xD;&#xA;&#xD;&#xA;![Mitchell-Netravali approximation of a wide Gaussian][2]&#xD;&#xA;&#xD;&#xA;This is a Mitchell-Netravali (cubic) downsample followed by a Gaussian. Interestingly, it turns out that using a Gaussian for the initial downsampling doesn't make such a great approximation if your goal is to use it to produce a larger Gaussian.&#xD;&#xA;&#xD;&#xA;An initial downsampling step is also frequently used when implementing visual effects like depth of field and motion blur, for similar reasons.&#xD;&#xA;&#xD;&#xA;A second reason to perform multiple Gaussian blurs is to approximate a non-separable filter by blending between various Gaussians of different radii.  This is commonly used in bloom, for example.  The standard bloom effect works by first thresholding to extract bright objects from the image, then creating several blurred copies of the bright objects (usually using the downsample-then-blur technique just discussed), and finally weighting and summing them together.  This allows artists a greater level of control over the final shape and appearance of the bloom.&#xD;&#xA;&#xD;&#xA;![Sum of three Gaussians creates a &quot;heavy-tailed&quot; function][3]&#xD;&#xA;&#xD;&#xA;Here, for example, is a weighted sum of three Gaussians (red line) which produces a shape that's more narrowly peaked and heavier-tailed than a single Gaussian (blue line).  This is a popular sort of configuration to use for bloom, as the combination of a narrow, bright center with a wide, diffuse halo is visually appealing.  But since this kind of filter shape isn't separable, it's cheaper to make it out of a mixture of Gaussians than to try to filter with it directly.&#xD;&#xA;&#xD;&#xA;Another variation on this idea is the concept of a diffusion profile used with subsurface scattering for skin rendering. Different blur radii may be used for the red, green, and blue channels to approximate the way different wavelengths of light scatter differently, as in [GPU Gems 3 skin shading chapter](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html) by Eugene d'Eon and Dave Luebke.  In fact, that paper uses a mixture of seven different Gaussians, with different R, G, and B weights for each, to approximate the complicated non-separable, wavelength-dependent scattering response of human skin.&#xD;&#xA;&#xD;&#xA;[![Diffusion profiles from GPU Gems 3 article on skin shading][4]](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ugYom.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xdbOo.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZzS3i.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YYAga.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="844" PostHistoryTypeId="2" PostId="290" RevisionGUID="bd47a039-a6ae-4999-b9d5-beffddedc732" CreationDate="2015-08-20T05:53:23.373" UserId="48" Text="Texture baking can be accomplished by simply rendering the mesh in texture space.  In other words, you set up a render target matching the size of your texture, and draw the mesh with a vertex shader that sets the output position to the vertex's UV coordinate (appropriately remapped from [0, 1] UV space to [&amp;minus;1, 1] post-projective space).&#xD;&#xA;&#xD;&#xA;The vertex shader can still calculate the world-space position, normals, and whatever else it needs and send those down to the pixel shader.  Then the pixel shader can do its thing without even being aware that it's rendering into texture space instead of the usual screen space.  Lighting and shading calculations will work as usual as long as the pixel shader inputs are hooked up correctly.&#xD;&#xA;&#xD;&#xA;You don't have to do any complicated inversion operation; you just take advantage of the GPU rasterization hardware, which is happy to draw your triangles at any coordinates you choose.&#xD;&#xA;&#xD;&#xA;Naturally, this requires that your mesh already has a non-overlapping UV mapping that fits within the unit square, but texture baking doesn't really make sense without that." ContentLicense="CC BY-SA 3.0" />
  <row Id="845" PostHistoryTypeId="2" PostId="291" RevisionGUID="cef87083-1e40-41ce-98ac-40d796dba910" CreationDate="2015-08-20T07:48:41.177" UserId="394" Text="The following naïve approach will probably not yield as nicely distributed points as the [ones given by Lhf](http://computergraphics.stackexchange.com/a/251/394), but it should be much easier to implement and computationally faster:&#xD;&#xA;&#xD;&#xA;For two points `x` and `y` let `d(x,y)` denote the average distance you want points with the average curvature of `x` and `y` to have, e.g., some constant multiplied with the inverse of the average curvature of `x` and `y`.&#xD;&#xA;&#xD;&#xA;Now build up your collection of points `A` successively:&#xD;&#xA;&#xD;&#xA;1. Select a random point `x` and add two points, such that all three points form a equilateral triangle with edge length `d(x,x)`.&#xD;&#xA;&#xD;&#xA;2. Add all points to `A` and mark them as adjacent.&#xD;&#xA;&#xD;&#xA;3. Repeatedly do the following until there are no adjacencies in `A` anymore:&#xD;&#xA;&#xD;&#xA;  1. Select two adjacent points `x` and `y` from `A`. Mark them as non-adjacent.&#xD;&#xA;  1. Consider a point `z` that has a distance of `d(x,y)` from both these points. Of the two possible such points select the one pointing outwards of `A` (this needs some work, but should be straightforward).&#xD;&#xA;  1. Check whether `z` is closer than `d(x,y)` to any point from `A` that is still adjacent to another point.&#xD;&#xA;&#xD;&#xA;    * if yes, discard it.&#xD;&#xA;    * if no, mark `x` and `z` as well as `y` and `z` as adjacent and add `z` to `A`.&#xD;&#xA;&#xD;&#xA;At the end, `A` should be a collection of points matching your criteria. You sort-of just created a triangulation but it may be pathological and thus you should probably triangulate the points afresh." ContentLicense="CC BY-SA 3.0" />
  <row Id="846" PostHistoryTypeId="2" PostId="292" RevisionGUID="b0043509-3d91-4047-b93e-93ef2aaa94f7" CreationDate="2015-08-20T10:52:25.733" UserId="231" Text="I don't know any shader languages. I've heard of GLSL and HLSL, and I'm interested in learning one or both.&#xD;&#xA;&#xD;&#xA;Are there significant differences between them that would make one or other better in certain situations? Is it useful to know both or would either cover most needs?&#xD;&#xA;&#xD;&#xA;I don't want vague answers indicating personal preference. I'm looking for specific measurable differences so that I can decide for myself which will suit me best. I don't have a specific task in mind - I'm hoping to discover whether there is one or other that I can learn and then apply to any future tasks, rather than having to learn a new language for each new task.&#xD;&#xA;&#xD;&#xA;If there are other shader languages which I have not mentioned I would be interested to hear the comparison for those too, provided they are not dependent on any particular GPU manufacturer. I want my code to be portable across different graphics cards." ContentLicense="CC BY-SA 3.0" />
  <row Id="847" PostHistoryTypeId="1" PostId="292" RevisionGUID="b0043509-3d91-4047-b93e-93ef2aaa94f7" CreationDate="2015-08-20T10:52:25.733" UserId="231" Text="What factors affect which shader language to learn?" ContentLicense="CC BY-SA 3.0" />
  <row Id="848" PostHistoryTypeId="3" PostId="292" RevisionGUID="b0043509-3d91-4047-b93e-93ef2aaa94f7" CreationDate="2015-08-20T10:52:25.733" UserId="231" Text="|gpu|glsl|shader|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="849" PostHistoryTypeId="2" PostId="293" RevisionGUID="16026442-903a-4e03-962d-d839901a7d78" CreationDate="2015-08-20T11:02:54.187" UserId="137" Text="The shader language is bound to the APIs/engines that support it (glsl to openGL &amp; WebGL and hlsl to D3D). There are tools to translate from one to the other but they aren't perfect.&#xD;&#xA;&#xD;&#xA;This means the main reason to pick one over the other is which platform you will be working on.&#xD;&#xA;&#xD;&#xA;However by the end of the year a new binary shader representation will come out called Spir-V designed for Vulkan and an OpenGL extension for it is expected to follow shortly. This will allow you to write shaders in many languages as long as a translation tool to Spir-V exists (several are in the works including a Python and Haskell tool)." ContentLicense="CC BY-SA 3.0" />
  <row Id="852" PostHistoryTypeId="2" PostId="295" RevisionGUID="7ba67d48-32f4-4f41-a0b5-12967a7ec54a" CreationDate="2015-08-20T11:42:45.213" UserId="231" Text="Are the differences between these two APIs minor implementation details that mean once I have learned one I can use it for everything? Or are there reasons for learning one rather than the other if I want to be able to use it in general without having to relearn another API in future? Is one or other more general?&#xD;&#xA;&#xD;&#xA;In particular I would like to be able to write for any graphics card, so code is not restricted to only running on a particular manuafacturer's cards or a specific model. I'd also like to be able to write code that still works in the absence of a graphics card (albeit slower).&#xD;&#xA;&#xD;&#xA;Is there a difference in how portable code will be across different platforms (operating systems/architectures)? I'm interested in the availability of other libraries that work with these, and whether one or the other leads to fewer licensing restrictions in its wider environment. Anything measurable that would make a difference to whether one of these could be the only one I learn without restricting me." ContentLicense="CC BY-SA 3.0" />
  <row Id="853" PostHistoryTypeId="1" PostId="295" RevisionGUID="7ba67d48-32f4-4f41-a0b5-12967a7ec54a" CreationDate="2015-08-20T11:42:45.213" UserId="231" Text="Does it matter whether I learn OpenGL or Direct3D?" ContentLicense="CC BY-SA 3.0" />
  <row Id="854" PostHistoryTypeId="3" PostId="295" RevisionGUID="7ba67d48-32f4-4f41-a0b5-12967a7ec54a" CreationDate="2015-08-20T11:42:45.213" UserId="231" Text="|opengl|api|direct3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="855" PostHistoryTypeId="2" PostId="296" RevisionGUID="f02cfb86-f1c2-4e41-8e6c-010fc06c80e5" CreationDate="2015-08-20T13:41:44.590" UserId="127" Text="I don't think it matters much, which API you want to use when leaning to &quot;program graphics&quot;. The more important things to learn are the typical concepts you use when working with 3D scenes. For example you want to learn how to write a simple (and later more sophisticated) Scene Graph. These concepts are much more important than the specific API method names you have to call. &#xD;&#xA;&#xD;&#xA;Compare it when learning how to write programs. If you are quite good at writing programs in e.g. Java, you won't have that much trouble learning C++, Objective-C, Swift, or some other object-oriented language. Because it's the concepts and the *thinking* which you learn.&#xD;&#xA;&#xD;&#xA;The choice between OpenGL, Direct3D and Metal is primarily the choice, which operating system you target. Direct3D is primarily available on Windows, Metal on OS X and iOS, and OpenGL is supported on most systems including OS X, iOS, Windows and Linux.&#xD;&#xA;&#xD;&#xA;The graphics card probably has little to no influence on this decision as I don't know a card that supports only one or two. If you have no dedicated graphics card, then rendering in real time will be a problem soon. Although a Intel HD Graphics and the AMD companion can already do quite much.&#xD;&#xA;&#xD;&#xA;So, choose your platform.&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;Disclaimer: As of now, I did neither use Direct3D nor Metal." ContentLicense="CC BY-SA 3.0" />
  <row Id="856" PostHistoryTypeId="2" PostId="297" RevisionGUID="60b25538-9255-4d2e-b5bb-96103c9fbfe2" CreationDate="2015-08-20T14:20:02.697" UserId="56" Text="When I implement Beer's law (color absorption over distance through an object), it never looks very good for some reason.&#xD;&#xA;&#xD;&#xA;When i have the color behind the object, i calculate the adjusted color like this:&#xD;&#xA;&#xD;&#xA;    const vec3 c_absorb = vec3(0.2,1.8,1.8);&#xD;&#xA;    vec3 absorb = exp(-c_absorb * (distanceInObject));&#xD;&#xA;    behindColor *= absorb;&#xD;&#xA;&#xD;&#xA;That will give me something that looks like this (note a little bit of refraction applied):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;That fulfills the description of what Beer's law does, but it doesn't look very good, not when compared to shots like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Specular highlights aside, I'm trying to figure out the difference.  Could it just be that my geometry is too simple to really show it off very well? Or am i implementing it incorrectly?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XQbjV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/nchoX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="857" PostHistoryTypeId="1" PostId="297" RevisionGUID="60b25538-9255-4d2e-b5bb-96103c9fbfe2" CreationDate="2015-08-20T14:20:02.697" UserId="56" Text="Is this the correct way to implement Beer's Law?" ContentLicense="CC BY-SA 3.0" />
  <row Id="858" PostHistoryTypeId="3" PostId="297" RevisionGUID="60b25538-9255-4d2e-b5bb-96103c9fbfe2" CreationDate="2015-08-20T14:20:02.697" UserId="56" Text="|3d|refraction|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="859" PostHistoryTypeId="2" PostId="298" RevisionGUID="8cf9f6b1-c752-4543-8db0-5d7358718aa6" CreationDate="2015-08-20T14:31:24.183" UserId="137" Text="We are currently in a transition of API paradigms.&#xD;&#xA;&#xD;&#xA;The old school method of binding buffers, uniforms, attribute, layout and programs as (implicit) global state and dispatching draws with that state is common across D3D11 and OpenGL. However it has a large amount of overhead (in verifying state and not knowing what the program wants to do until the last minute). They are also not thread safe (for the most part).&#xD;&#xA;&#xD;&#xA;This is why new apis have come up (or are coming soon) D3D12, vulkan and Metal being the most prominent. These APIs give more control to the program and lets it declare in advance what it want to do using command buffers. They also let you manage your own resources (vertex data, textures, ...) much more directly. Using them with multiple is much more straight forward.&#xD;&#xA;&#xD;&#xA;The choice between old and new is based on how well you can manage the video memory you allocate and build the command buffer. &#xD;&#xA;&#xD;&#xA;* If you want something that &quot;just works&quot; even on older hardware then the old school APIs are better; they also are better known and you will get more help on them online.&#xD;&#xA;&#xD;&#xA;* On the other hand if you can handle the asynchronous nature of dispatching commands and don't mind having to track all the buffers you allocate. Then the new APIs may be something for you. " ContentLicense="CC BY-SA 3.0" />
  <row Id="860" PostHistoryTypeId="2" PostId="299" RevisionGUID="f56db882-b367-4214-baa3-28d1b879071d" CreationDate="2015-08-20T15:55:56.167" UserId="64" Text="The HLSL shader language is used in DirectX family APIs and GLSL for the OpenGL family APIs. This means that the choice of graphics API will limit the shader language as well, so if cross platform is a concern then GLSL will be the choice. However, this comes with some caveats as well.&#xD;&#xA;&#xD;&#xA;One difference is that in OpenGL the shading language is compiled on driver level, this means that the binary representation is not stable and can change with driver updates. In HLSL it is compiled to a hardware independent representation that can be used on multiple GPUs. This should really be a problem for writing shaders, but it sometimes means that certain things work different with other drivers and especially operating systems.&#xD;&#xA;&#xD;&#xA;Another thing to take note is that OpenGL features extensions, these can be enabled inside GLSL to utilize extra functionality. With newer OpenGL versions some of these extensions might be added to the core profile. Vendors then have to implement these extensions to be compliant, which sometimes results in things working different. The HLSL shading language syntax only changes with new introduction of DirectX APIs.&#xD;&#xA;&#xD;&#xA;Some syntactic differences are that HLSL can use #include, in GLSL this is not default. GLSL functions cannot return a value, but you use inout or out as parameter qualifiers. When searching for GLSL tutorials you might find different syntax, because it has changed quite a lot as of OpenGL 3 and 4.&#xD;&#xA;&#xD;&#xA;Learning either of these will introduce you to some common ground which will make it easy to learn to other one. HLSL is more standardized, but it also only works on a single operating system. There are also other attempts of shader languages that compile to both OpenGL and DirectX, one example is [Cg][1] which is deprecated by now. Many game engines (Unity, Unreal Engine) also have their own flavors, but their syntax is like HLSL or GLSL.&#xD;&#xA;&#xD;&#xA;As already mentioned Vulkan will introduce an open intermediate language representation called Spir-V. This means that if a language can be compiled to this representation it can be used to write shaders.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/cg-toolkit" ContentLicense="CC BY-SA 3.0" />
  <row Id="861" PostHistoryTypeId="2" PostId="300" RevisionGUID="c04189fa-7def-4d31-a8fe-9ee80a267482" CreationDate="2015-08-20T17:35:29.830" UserId="327" Text="Imagine you have a 3D level format consisting of an arbitrary number of convex polytope brushes (or we can simplify and consider just oriented-bounding boxes) and several point entities.&#xD;&#xA;&#xD;&#xA;I want to find an algorithm to determine&#xD;&#xA;&#xD;&#xA; 1. If the level is water-tight. That is, the brushes are adjacent to each other and fit together without creating gaps or holes.&#xD;&#xA; 2. If the level is disjoint, identify the set brushes in each part.&#xD;&#xA; 3. If all entities are inside the water-tight level, and in which section (from (2)) they are in.&#xD;&#xA;&#xD;&#xA;(1) isn't strictly necessary, but it seems necessary to ensure that (2) and (3) are well defined.&#xD;&#xA;&#xD;&#xA;All engines I know that use this kind of level format (Doom, Quake, Source) seem to use a BSP algorithm for these tasks. However, they also use the resulting BSP tree as an acceleration structure for rendering, which I'm not interested in using.&#xD;&#xA;&#xD;&#xA;Is anyone aware of any other possible alternative algorithms, or is BSP the only choice?" ContentLicense="CC BY-SA 3.0" />
  <row Id="862" PostHistoryTypeId="1" PostId="300" RevisionGUID="c04189fa-7def-4d31-a8fe-9ee80a267482" CreationDate="2015-08-20T17:35:29.830" UserId="327" Text="Determining level connectivity" ContentLicense="CC BY-SA 3.0" />
  <row Id="863" PostHistoryTypeId="3" PostId="300" RevisionGUID="c04189fa-7def-4d31-a8fe-9ee80a267482" CreationDate="2015-08-20T17:35:29.830" UserId="327" Text="|space-partitioning|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="866" PostHistoryTypeId="5" PostId="300" RevisionGUID="22915369-71c9-4357-906d-9a17855587fb" CreationDate="2015-08-20T18:02:34.843" UserId="327" Comment="typo" Text="Imagine you have a 3D level format consisting of an arbitrary number of convex polytope brushes (or we can simplify and consider just oriented-bounding boxes) and several point entities.&#xD;&#xA;&#xD;&#xA;I want to find an algorithm to determine&#xD;&#xA;&#xD;&#xA; 1. If the level is water-tight. That is, the brushes are adjacent to each other and fit together to form a hull without gaps or holes.&#xD;&#xA; 2. If the level is disjoint, identify the set of brushes in each section.&#xD;&#xA; 3. If all entities are inside the water-tight level, and in which section (from (2)) they are in.&#xD;&#xA;&#xD;&#xA;(1) isn't strictly necessary, but it seems necessary to ensure that (2) and (3) are well defined.&#xD;&#xA;&#xD;&#xA;All engines I know that use this kind of level format (Doom, Quake, Source) seem to use a BSP algorithm for these tasks. However, they also use the resulting BSP tree as an acceleration structure for rendering, which I'm not interested in using.&#xD;&#xA;&#xD;&#xA;Is anyone aware of any other possible alternative algorithms, or is BSP the only choice?" ContentLicense="CC BY-SA 3.0" />
  <row Id="867" PostHistoryTypeId="5" PostId="299" RevisionGUID="a03bf4ca-b4a0-438e-89f9-f4319f90ce51" CreationDate="2015-08-20T18:34:36.977" UserId="64" Comment="Removed incorrect information." Text="The HLSL shader language is used in DirectX family APIs and GLSL for the OpenGL family APIs. This means that the choice of graphics API will limit the shader language as well, so if cross platform is a concern then GLSL will be the choice. However, this comes with some caveats as well.&#xD;&#xA;&#xD;&#xA;One difference is that in OpenGL the shading language is compiled on driver level, this means that the binary representation is not stable and can change with driver updates. In HLSL it is compiled to a hardware independent representation that can be used on multiple GPUs. This should really be a problem for writing shaders, but it sometimes means that certain things work different with other drivers and especially operating systems.&#xD;&#xA;&#xD;&#xA;Another thing to take note is that OpenGL features extensions, these can be enabled inside GLSL to utilize extra functionality. With newer OpenGL versions some of these extensions might be added to the core profile. Vendors then have to implement these extensions to be compliant, which sometimes results in things working different. The HLSL shading language syntax only changes with new introduction of DirectX APIs.&#xD;&#xA;&#xD;&#xA;Some syntactic differences are that HLSL can use #include, in GLSL this is not default. When searching for GLSL tutorials you might find different syntax, because it has changed quite a lot as of OpenGL 3 and 4. GLSL shaders have a void main() as shader entry point. In HLSL this entry point can be named and have input (vertex data) and output (pixel shader input).&#xD;&#xA;&#xD;&#xA;Learning either of these will introduce you to some common ground which will make it easy to learn to other one. HLSL is more standardized, but it also only works on a single operating system. There are also other attempts of shader languages that compile to both OpenGL and DirectX, one example is [Cg][1] which is deprecated by now. Many game engines (Unity, Unreal Engine) also have their own flavors, but their syntax is like HLSL or GLSL.&#xD;&#xA;&#xD;&#xA;As already mentioned Vulkan will introduce an open intermediate language representation called Spir-V. This means that if a language can be compiled to this representation it can be used to write shaders.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/cg-toolkit" ContentLicense="CC BY-SA 3.0" />
  <row Id="868" PostHistoryTypeId="2" PostId="301" RevisionGUID="c74d57f1-e79b-4a77-b789-cfe9140fa4b9" CreationDate="2015-08-20T18:41:21.510" UserId="38" Text="Why do we not calibrate all devices to sRGB in the factory? The assumption is that every monitor is sRGB anyway. So why not calibrate them to that? That would make people see same color as intended on a wide range of devices." ContentLicense="CC BY-SA 3.0" />
  <row Id="869" PostHistoryTypeId="1" PostId="301" RevisionGUID="c74d57f1-e79b-4a77-b789-cfe9140fa4b9" CreationDate="2015-08-20T18:41:21.510" UserId="38" Text="Why not calibrate all display devices to sRGB?" ContentLicense="CC BY-SA 3.0" />
  <row Id="870" PostHistoryTypeId="3" PostId="301" RevisionGUID="c74d57f1-e79b-4a77-b789-cfe9140fa4b9" CreationDate="2015-08-20T18:41:21.510" UserId="38" Text="|color-management|" ContentLicense="CC BY-SA 3.0" />
  <row Id="871" PostHistoryTypeId="2" PostId="302" RevisionGUID="526751f2-31c2-4ba1-97ff-0e967bdcb820" CreationDate="2015-08-20T19:05:38.003" UserId="327" Text="Simple answer: because it costs. :) Some higher-end monitor models *are* indeed calibrated at the factory (and come with a calibration report sheet) but it would not be cost-effective to do so for all monitors.&#xD;&#xA;&#xD;&#xA;Color reproduction varies even between batches of the exact same panel model, so it isn't possible to just use a set calibration for a given monitor model, it need to be done on a unit-by-unit basis. So to save costs, they instead determine the color reproduction curves of the &quot;average&quot; panel and use that for an ok but inconsistent result." ContentLicense="CC BY-SA 3.0" />
  <row Id="873" PostHistoryTypeId="5" PostId="302" RevisionGUID="a50f1125-9f1b-4dff-9fdd-61221ddf8391" CreationDate="2015-08-20T19:42:59.837" UserId="327" Comment="added 18 characters in body" Text="Simple answer: because it costs. :) Some higher-end monitor models *are* indeed calibrated at the factory (and come with a calibration report sheet) but it would not be cost-effective to do so for all models in the product line.&#xD;&#xA;&#xD;&#xA;Color reproduction varies even between batches of the exact same panel model, so it isn't possible to just use a set calibration for a given monitor model, it need to be done on a unit-by-unit basis. So to save costs, they instead determine the color reproduction curves of the &quot;average&quot; panel and use that for an ok but inconsistent result." ContentLicense="CC BY-SA 3.0" />
  <row Id="874" PostHistoryTypeId="2" PostId="303" RevisionGUID="bd461871-331b-425b-b672-92e89835c6c3" CreationDate="2015-08-20T20:34:15.230" UserId="327" Text="It's completely possible to do all pixel lights in the fragment shader (or, say, do 4 at a time) by looping over an array. However, this comes at a great performance cost: You're going to be calculating lighting for every light on every fragment of the scene, even if that geometry isn't actually affected by the light's influence.&#xD;&#xA;&#xD;&#xA;I suspect that is reason why Unity doesn't do so: it probably culls the objects and submits only geometry that might be influenced by the respective light on each pass, meaning that shading for a light is only evaluated in the fragments where it may have an effect. This is a trade off between processing less fragments but duplicating the geometry cost." ContentLicense="CC BY-SA 3.0" />
  <row Id="875" PostHistoryTypeId="2" PostId="304" RevisionGUID="c23ffe36-6f9e-4487-9f96-46dba7d66a57" CreationDate="2015-08-20T20:45:56.550" UserId="48" Text="BSP is a classic for computational geometry tasks involving polygons. However, polygonal meshes are subject to a dismaying list of pathologies such as degenerate polygons, inconsistent winding order, T-junctions, coincident vertices, cracks or holes, self-intersecting geometry, loss of coplanarity or collinearity due to roundoff error, and other such things. Making computational geometry robust on arbitrary polygon meshes is Quite Difficult™.&#xD;&#xA;&#xD;&#xA;It worked in Doom/Quake/Half-Life days because the base level geometry (made of brushes and constructed in a level editor, as opposed to a 3D modeling tool), was relatively simple, mostly axis-aligned, and all vertices were snapped to grids. More recently, the trend seems to be for level design seems to be done by creating mesh pieces in 3D modeling tools, then sticking together a bunch of instances of them to form a level. This kind of construction is a *lot* less friendly to BSP-type algorithms&amp;mdash;especially as the geometric complexity rises.&#xD;&#xA;&#xD;&#xA;An alternative approach for connectivity questions is voxelization. In short, you voxelize all your level geometry at some reasonably small resolution, like 10&amp;ndash;30 cm per voxel or so. The voxelization wipes away any geometric errors smaller than the voxel size, and it gets rid of all those annoying pathologies mentioned earlier. You can use an octree or brickmap etc. to avoid voxelizing empty space.&#xD;&#xA;&#xD;&#xA;Once you have the voxel representation of the level, you can then do all sorts of connectivity queries on it very easily because of the regular structure of the voxels. For instance, determining if a level is watertight or finding connected-components at the voxel level is basically a flood-fill. These kinds of algorithms can also be done hierarchically using the octree etc. to avoid the expense of a global flood-fill over a huge number of voxels. &#xD;&#xA;&#xD;&#xA;For more reading, there was a 2011 SIGGRAPH talk [Making Game Worlds From Polygon Soup](http://advances.realtimerendering.com/s2011/Chen,%20Silvennoinen,%20Tatarchuk%20-%20Polygon%20Soup%20Worlds%20(Siggraph%202011%20Advances%20in%20Real-Time%20Rendering%20Course).pptx), from some engineers at Bungie who used voxelization techniques on Halo Reach levels to build nav meshes, precompute visibility cells and portals, and so on." ContentLicense="CC BY-SA 3.0" />
  <row Id="876" PostHistoryTypeId="2" PostId="305" RevisionGUID="b9e14c41-683f-4f5f-b377-98a3605ab10d" CreationDate="2015-08-20T20:49:17.700" UserId="127" Text="Rendering the scene usually involves more than one shader program which, in my case, all use the same attributes and share at least some of the uniforms. To have them working properly, I currently play safe, meaning I rebind the attributes and get the appropriate uniform locations every time I switch between shader programs. So basically multiple times in every frame, which is probably not the best approach.&#xD;&#xA;&#xD;&#xA;So, is it (in general) necessary to rebind attributes and uniforms after switching shader programs? And why?&#xD;&#xA;&#xD;&#xA;If so, is there a way to do this once at start of the program and never have to touch them again (except for setting the uniform values)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="877" PostHistoryTypeId="1" PostId="305" RevisionGUID="b9e14c41-683f-4f5f-b377-98a3605ab10d" CreationDate="2015-08-20T20:49:17.700" UserId="127" Text="Do I need to rebind uniforms or attributes when changing shader programs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="878" PostHistoryTypeId="3" PostId="305" RevisionGUID="b9e14c41-683f-4f5f-b377-98a3605ab10d" CreationDate="2015-08-20T20:49:17.700" UserId="127" Text="|opengl|glsl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="879" PostHistoryTypeId="2" PostId="306" RevisionGUID="ef8537c0-ac62-4405-bc5b-5bd5f043e275" CreationDate="2015-08-20T21:04:22.240" UserId="250" Text="Signed Distance Fields (SDFs) was presented as a fast solution to achieve resolution independent font rendering by Valve [in this paper][1]. &#xD;&#xA;&#xD;&#xA;I already have the Valve solution working but I'd like to preserve sharpness around corners. Valve states that their method can achieve sharp corners by using a second texture channels ANDed with the base one, but lacks to explain how this second channel would be generated. &#xD;&#xA;&#xD;&#xA;In fact there's a lot of implementation details left out of this paper. &#xD;&#xA;&#xD;&#xA;I'd like to know if any of you could point me out a direction to get SDFs font rendering with sharp corners.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="880" PostHistoryTypeId="1" PostId="306" RevisionGUID="ef8537c0-ac62-4405-bc5b-5bd5f043e275" CreationDate="2015-08-20T21:04:22.240" UserId="250" Text="Sharp Corners with Signed Distance Fields Fonts" ContentLicense="CC BY-SA 3.0" />
  <row Id="881" PostHistoryTypeId="3" PostId="306" RevisionGUID="ef8537c0-ac62-4405-bc5b-5bd5f043e275" CreationDate="2015-08-20T21:04:22.240" UserId="250" Text="|texture|signed-distance-field|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="883" PostHistoryTypeId="2" PostId="307" RevisionGUID="209352f6-bc36-4934-9a07-587dc109ce9f" CreationDate="2015-08-20T21:17:33.460" UserId="327" Text="You don't need to rebind the attributes, so long as you ensure that their location stays the same in both shaders. (Usually using the `layout(location = X)` syntax in GLSL, but can also be done with [`glBindAttribLocation`](https://www.opengl.org/sdk/docs/man/html/glBindAttribLocation.xhtml) if former is not available.)&#xD;&#xA;&#xD;&#xA;Uniforms, however, are part of the Shader Object state, and so will need to be rebound at least once for every shader. One way to minimize the cost of this is to use a [Uniform Buffer Object](https://www.opengl.org/wiki/Uniform_Buffer_Object), which will contain all your uniform values and can then be bound to a shader with a single call." ContentLicense="CC BY-SA 3.0" />
  <row Id="884" PostHistoryTypeId="5" PostId="307" RevisionGUID="6929b4cf-1a9d-4378-8951-71c6bdfe6bae" CreationDate="2015-08-20T22:56:54.543" UserId="327" Comment="deleted 4 characters in body" Text="You don't need to rebind the attributes, so long as you ensure that their location stays the same in both shaders. (Usually using the `layout(location = X)` syntax in GLSL, but can also be done with [`glBindAttribLocation`](https://www.opengl.org/sdk/docs/man/html/glBindAttribLocation.xhtml) if former is not available.)&#xD;&#xA;&#xD;&#xA;Uniforms, however, are part of the Shader Object state, and so will need to be set at least once for every shader. One way to minimize the cost of this is to use a [Uniform Buffer Object](https://www.opengl.org/wiki/Uniform_Buffer_Object), which will contain all your uniform values and can then be bound to a shader with a single call." ContentLicense="CC BY-SA 3.0" />
  <row Id="885" PostHistoryTypeId="5" PostId="280" RevisionGUID="dd8d662f-cb06-490b-9668-fdddcb972582" CreationDate="2015-08-20T23:30:50.320" UserId="127" Comment="Clarified question and title. Edited tags." Text="In general, branching in shaders is not a good idea. But now I have a shader with a condition that is constant with respect to the entire draw call. So the branch that is executed is always the same for one draw call.&#xD;&#xA;&#xD;&#xA;Is such kind of branching still more costly than having multiple shaders without these branches and switch between them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="886" PostHistoryTypeId="4" PostId="280" RevisionGUID="dd8d662f-cb06-490b-9668-fdddcb972582" CreationDate="2015-08-20T23:30:50.320" UserId="127" Comment="Clarified question and title. Edited tags." Text="Is a constant condition more costly than switching shaders?" ContentLicense="CC BY-SA 3.0" />
  <row Id="887" PostHistoryTypeId="6" PostId="280" RevisionGUID="dd8d662f-cb06-490b-9668-fdddcb972582" CreationDate="2015-08-20T23:30:50.320" UserId="127" Comment="Clarified question and title. Edited tags." Text="|performance|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="888" PostHistoryTypeId="24" PostId="280" RevisionGUID="dd8d662f-cb06-490b-9668-fdddcb972582" CreationDate="2015-08-20T23:30:50.320" Comment="Proposed by 127 approved by 54, 231 edit id of 42" ContentLicense="CC BY-SA 3.0" />
  <row Id="891" PostHistoryTypeId="2" PostId="308" RevisionGUID="f045336c-e5ef-46c9-a671-ff6cc58e9995" CreationDate="2015-08-21T06:16:49.357" UserId="38" Text="There are 2 major factor to this.&#xD;&#xA;&#xD;&#xA;While it would certainly be possible to calibrate or profile each screen this would add cost to the process. Most users simply aren't that sensitive to this issue so it makes no economic sense to do so. &#xD;&#xA;&#xD;&#xA;Its also worth noting that color reproduction is a function of several factors. Such as panel use age, operating temperature, but also ambient surroundings. So while this could be done it would be less than stellarly useful for the user in the long run, unless they operate in standardized lighting conditions. &#xD;&#xA;&#xD;&#xA;Certainly there is value in factory calibration. It simply means that the monitor can be calibrated to sRGB.&#xD;&#xA;&#xD;&#xA;The second problem is that is not technically desireable for the panel manufacturers. Forcing something like this on the manufacturers would be a bit like telling people that the the only graphics available graphics api from now on is opengl 2.0 no innovation allowed.&#xD;&#xA;&#xD;&#xA;Business dictates that the manufacturers need to be able to innovate. Calibrating everything to sRGB would slow down development of panels that are significantly bettter in gamut than sRGB to evolve. Second not all display panels can reach sRGB. Developping ultra cheap panels also has a market function. No need to restrict innovation.&#xD;&#xA;&#xD;&#xA;Calibrating to sRGB would ultimately not solve all color problems. Convoluted profile to profile conversions would still &#xD;&#xA;be needed. Dosplay panels are precicion instruments and need to be handled like that if accuracy is drsired. If not then no big deal.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="892" PostHistoryTypeId="5" PostId="308" RevisionGUID="9c5309ff-c996-4eb0-a95f-a0053ea6e235" CreationDate="2015-08-21T06:22:23.667" UserId="38" Comment="added 30 characters in body" Text="There are 2 major factor to this.&#xD;&#xA;&#xD;&#xA;While it would certainly be possible to calibrate or profile each screen this would add cost to the process. Most users simply aren't that sensitive to this issue so it makes no economic sense to do so. &#xD;&#xA;&#xD;&#xA;Its also worth noting that color reproduction is a function of several factors. Such as panel use age, operating temperature etc., but also ambient surroundings. So while this could be done it would be less than stellarly useful for the user in the long run, unless they operate in standardized lighting conditions and never use the monitor.&#xD;&#xA;&#xD;&#xA;Certainly there is value in factory calibration. It simply means that the monitor can be calibrated to sRGB. And in some usecases the drift caused by age is acceptable.&#xD;&#xA;&#xD;&#xA;The second problem is that is not technically desireable for the panel manufacturers. Forcing something like this on the manufacturers would be a bit like telling people that the the only graphics available graphics api from now on is opengl 2.0 no innovation allowed.&#xD;&#xA;&#xD;&#xA;Business dictates that the manufacturers need to be able to innovate. Calibrating everything to sRGB would slow down development of panels that are significantly bettter in gamut than sRGB to evolve. Second not all display panels can reach sRGB. Developping ultra cheap panels also has a market function. No need to restrict innovation.&#xD;&#xA;&#xD;&#xA;Calibrating to sRGB would ultimately not solve all color problems. Convoluted profile to profile conversions would still &#xD;&#xA;be needed. Display panels are precicion instruments and need to be handled like that if accuracy is drsired. If not then no big deal.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="894" PostHistoryTypeId="2" PostId="309" RevisionGUID="bd331ef4-2f02-4756-98f9-e4302f67b17d" CreationDate="2015-08-21T07:04:56.937" UserId="197" Text="I'm trying to figure out what the best way is to generate an OpenGL texture using a compute shader. So far, I've read that pixel buffer objects are good for non-blocking CPU -&gt; GPU transfers, and that compute shaders are capable of reading and writing buffers regardless of how they're bound. Ideally, I'd like to avoid as many copies as possible. In other words, I'd like to allocate a buffer on the GPU, write compressed texture data to it, and then use that buffer as a texture object in a shader.&#xD;&#xA;&#xD;&#xA;Currently, my code looks something like this:&#xD;&#xA;&#xD;&#xA;    GLuint buffer;&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);&#xD;&#xA;    glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;    // Bind buffer to resource in compute shader&#xD;&#xA;    // execute compute shader&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);&#xD;&#xA;    glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);&#xD;&#xA;&#xD;&#xA;Is this correct? I read somewhere about guaranteeing synchronization, too. What do I need to add to make sure that my compute shader completes execution prior to copying from the buffer object?" ContentLicense="CC BY-SA 3.0" />
  <row Id="895" PostHistoryTypeId="1" PostId="309" RevisionGUID="bd331ef4-2f02-4756-98f9-e4302f67b17d" CreationDate="2015-08-21T07:04:56.937" UserId="197" Text="Generating Compressed Textures on the GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="896" PostHistoryTypeId="3" PostId="309" RevisionGUID="bd331ef4-2f02-4756-98f9-e4302f67b17d" CreationDate="2015-08-21T07:04:56.937" UserId="197" Text="|opengl|texture|compression|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="897" PostHistoryTypeId="33" PostId="283" RevisionGUID="afa1b308-2d9f-49fb-9a8e-bfa2e82b889c" CreationDate="2015-08-21T09:04:39.790" UserId="16" Comment="7" />
  <row Id="898" PostHistoryTypeId="2" PostId="310" RevisionGUID="7b62cdc7-dd32-49a5-871d-44b11f58352c" CreationDate="2015-08-21T10:07:42.677" UserId="137" Text="If you would do all lights in a single pass then you would need to loop over all lights in the shader. You would also need to get all information to the GPU at the same time.&#xD;&#xA;&#xD;&#xA;GPUs are limited in the number of uniforms you can pass into an invocation. This limitation has lessened with UBOs and SSBOs.&#xD;&#xA;&#xD;&#xA;However you are still limited with how many textures you can bind for shadow mapping.&#xD;&#xA;&#xD;&#xA;Lights often only affect a small portion of the screen so the engine may only render geometry that is close to the light or adjust the viewport to only render the area the light would affect." ContentLicense="CC BY-SA 3.0" />
  <row Id="899" PostHistoryTypeId="34" PostId="277" RevisionGUID="17a8de89-e80c-4e99-a41d-d520fd0ef407" CreationDate="2015-08-21T10:54:30.767" UserId="231" Comment="6" />
  <row Id="900" PostHistoryTypeId="2" PostId="311" RevisionGUID="160b48ad-ddb7-48e6-b51a-eca381a01932" CreationDate="2015-08-21T13:02:45.887" UserId="231" Text="Although simulation models like [Boids] give good results for bird flocks or fish shoals on a small scale, simulating every single member in real time becomes unrealistic for huge numbers. Is there a way I can model a flock in the distance where only the density of birds is visible? I'd like to have that flowing, changing density gradient with a much smaller number of variables to process.&#xD;&#xA;&#xD;&#xA;I've tried using a much smaller population and displaying each boid as a blurred area with Gaussian density so that as they overlap the density rises and falls through their interaction. This is reasonably cheap but it never leads to sharp changes in density, either spatially or temporally, which makes it look too uniform.&#xD;&#xA;&#xD;&#xA;Is there any other way of getting away with a much smaller number of individuals? Or is the only way to get realistic results to prerender?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Boids]: https://en.wikipedia.org/wiki/Boids" ContentLicense="CC BY-SA 3.0" />
  <row Id="901" PostHistoryTypeId="1" PostId="311" RevisionGUID="160b48ad-ddb7-48e6-b51a-eca381a01932" CreationDate="2015-08-21T13:02:45.887" UserId="231" Text="Is there a way to achieve the look of a distant flock or shoal without full simulation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="902" PostHistoryTypeId="3" PostId="311" RevisionGUID="160b48ad-ddb7-48e6-b51a-eca381a01932" CreationDate="2015-08-21T13:02:45.887" UserId="231" Text="|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="903" PostHistoryTypeId="2" PostId="312" RevisionGUID="3525adba-420a-4d65-80f1-981ae0abeb37" CreationDate="2015-08-21T14:51:37.063" UserId="433" Text="In most text books that I have seen, this is how the rendering equation is written:&#xD;&#xA;&#xD;&#xA;![Rendering equation][1]&#xD;&#xA;&#xD;&#xA;Where Ω is defined to be a hemisphere (and all those functions depend on more variables, omitted here for simplicity's sake).&#xD;&#xA;&#xD;&#xA;Now suppose the surface being rendered is some kind of glass, or some transparent plastic. Why would it make sense to only integrate over a hemisphere? I would imagine that there can be incoming light from any direction, and thus the integration domain should be the entire sphere. How is the light coming from behind the glass accounted for?&#xD;&#xA;&#xD;&#xA;[1]: http://latex.codecogs.com/gif.latex?L_o%28\omega_o%29%20%3D%20L_e%28\omega_o%29%20&amp;plus;\int_\Omega%20f%28\omega_i%2C%20\omega_o%29L_i%28\omega_i%29%20\%2C\mathrm{d}\omega_i" ContentLicense="CC BY-SA 3.0" />
  <row Id="904" PostHistoryTypeId="1" PostId="312" RevisionGUID="3525adba-420a-4d65-80f1-981ae0abeb37" CreationDate="2015-08-21T14:51:37.063" UserId="433" Text="Why integrate over a hemisphere (and not a sphere) to solve the rendering equation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="905" PostHistoryTypeId="3" PostId="312" RevisionGUID="3525adba-420a-4d65-80f1-981ae0abeb37" CreationDate="2015-08-21T14:51:37.063" UserId="433" Text="|transparency|theory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="906" PostHistoryTypeId="2" PostId="313" RevisionGUID="ebb87a03-9a98-4779-8ce8-f1f083a2bdb0" CreationDate="2015-08-21T15:11:24.357" UserId="196" Text="The form of the rendering equation that uses only the BRDF (*f* in your example, often called *fᵣ*) and integrates over one hemisphere does not account for transmission.&#xD;&#xA;&#xD;&#xA;When adding in transmission, it's fairly common to add a second integral over the opposite hemisphere, using a different BTDF function (bidirectional *transmission* distribution function). This is equivalent to an integral over the full sphere of directions with a BSDF function, but since that function would usually have to be defined as a piecewise function, writing it as two integrals can be more straightforward." ContentLicense="CC BY-SA 3.0" />
  <row Id="907" PostHistoryTypeId="2" PostId="314" RevisionGUID="082a0b6d-cd6a-44eb-9d73-c2fe1f9f2e10" CreationDate="2015-08-21T15:41:40.173" UserId="56" Text="One way that might work is to have boids but fender each boid as a group of birds.  This way the simulation is still simple but the rendering makes it seem complex.  You might even allow a little drift per bird in the boid." ContentLicense="CC BY-SA 3.0" />
  <row Id="908" PostHistoryTypeId="5" PostId="314" RevisionGUID="3b1ea22b-2fd8-41bf-a5b4-28f05ef77d1f" CreationDate="2015-08-21T15:52:48.360" UserId="56" Comment="added 35 characters in body" Text="One way that might work is to have boids but render each boid as a group of birds.  This way the simulation is still simple but the rendering makes it seem complex.  You might even allow a little drift per bird in the boid to make it look so obviously rigid." ContentLicense="CC BY-SA 3.0" />
  <row Id="909" PostHistoryTypeId="4" PostId="309" RevisionGUID="23cefcb2-6b14-4d05-af53-380a8f5fbd2f" CreationDate="2015-08-21T18:33:30.647" UserId="48" Comment="changed title to better reflect question" Text="Writing to a compressed texture using a compute shader, with no extra copies" ContentLicense="CC BY-SA 3.0" />
  <row Id="910" PostHistoryTypeId="2" PostId="315" RevisionGUID="50a66fe3-e8f3-47cd-b5a7-17722c5505b8" CreationDate="2015-08-21T20:00:04.647" UserId="437" Text="I wrote a 2D fluid-solver in OpenGL ([code here](https://github.com/nilspin/SDL_OpenGL_Project)) some time back. &#xD;&#xA;&#xD;&#xA;While it runs flawlessly on my onboard Intel GPU, &#xD;&#xA;&#xD;&#xA;[![when running on Intel GPU][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;the simulation very quickly &quot;blows-up&quot; when same code is run using nvidia card :  &#xD;&#xA;    &#xD;&#xA;[![mere half a second into the program][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RPBpF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Xs5Sm.png&#xD;&#xA;&#xD;&#xA;In the second picture, the fluid is being &quot;added&quot; to the system and &quot;diffusing away&quot; too, but unlike the 1st picture there is no advection.  &#xD;&#xA;&#xD;&#xA;I would like to know what might possibly cause this. Could this be because different vendors might be interpreting the standard differently?  &#xD;&#xA;&#xD;&#xA;PS : The &quot;red&quot; and &quot;green&quot; colors represent magnitude of vector-field in *x* and *y* directions respectively." ContentLicense="CC BY-SA 3.0" />
  <row Id="911" PostHistoryTypeId="1" PostId="315" RevisionGUID="50a66fe3-e8f3-47cd-b5a7-17722c5505b8" CreationDate="2015-08-21T20:00:04.647" UserId="437" Text="Code runs differently on different hardware" ContentLicense="CC BY-SA 3.0" />
  <row Id="912" PostHistoryTypeId="3" PostId="315" RevisionGUID="50a66fe3-e8f3-47cd-b5a7-17722c5505b8" CreationDate="2015-08-21T20:00:04.647" UserId="437" Text="|opengl|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="913" PostHistoryTypeId="2" PostId="316" RevisionGUID="0a5353b2-8a3c-4f66-a694-175b0d8ace22" CreationDate="2015-08-21T21:26:46.043" UserId="104" Text="Adam Simmons has done some interesting work in this area. I don't know specifically how he's achieving it, but his SDF-based vector rendering is the sharpest I've seen in practice outside of Valve. http://twitter.com/adamjsimmons/status/611677036545863680" ContentLicense="CC BY-SA 3.0" />
  <row Id="914" PostHistoryTypeId="2" PostId="317" RevisionGUID="fc590e3f-de2e-4a72-afd2-0fbe81ea2e84" CreationDate="2015-08-22T04:54:36.683" UserId="307" Text="I do not personally think it matters much. Just pick one that suits your project. I have used both D3D and OpenGL in the past. It is the concepts that matter. Whichever you grab, you need to understand (for example):&#xD;&#xA;&#xD;&#xA; * What textures are and how they are used by GPU.&#xD;&#xA; * Basic concepts of Graphics Development (Vertices, Primitives, Fragments, etc.)&#xD;&#xA; * How does the camera system work (MVP matrices in OpenGL for example).&#xD;&#xA; * What shaders are and how to use them properly.&#xD;&#xA; * How different a GPU works versus the CPU on your machine.&#xD;&#xA; * What are the differences between GPU's memory model and CPU's memory model.&#xD;&#xA; * What should be done on CPU and what should be offloaded to GPU for processing.&#xD;&#xA;&#xD;&#xA;As others mentioned here, we are in the middle of a transition to a new set of APIs (Vulkan, Metal, etc.) so at this point if you are completely new to Graphics Development, probably focusing on GLSL is a good idea since Vulkan is going to take advantage of it as well.&#xD;&#xA;&#xD;&#xA;At the end of the day, all APIs access the same hardware on your machine, it is just a matter of &quot;how&quot; they access it." ContentLicense="CC BY-SA 3.0" />
  <row Id="915" PostHistoryTypeId="5" PostId="317" RevisionGUID="e042cc69-4b36-489b-bc75-7ada339c11c8" CreationDate="2015-08-22T05:00:20.590" UserId="307" Comment="added portability notes" Text="I do not personally think it matters much. Just pick one that suits your project. I have used both D3D and OpenGL in the past. It is the concepts that matter. Whichever you grab, you need to understand (for example):&#xD;&#xA;&#xD;&#xA; * What textures are and how they are used by GPU.&#xD;&#xA; * Basic concepts of Graphics Development (Vertices, Primitives, Fragments, etc.)&#xD;&#xA; * How does the camera system work (MVP matrices in OpenGL for example).&#xD;&#xA; * What shaders are and how to use them properly.&#xD;&#xA; * How different a GPU works versus the CPU on your machine.&#xD;&#xA; * What are the differences between GPU's memory model and CPU's memory model.&#xD;&#xA; * What should be done on CPU and what should be offloaded to GPU for processing.&#xD;&#xA;&#xD;&#xA;As others mentioned here, we are in the middle of a transition to a new set of APIs (Vulkan, Metal, etc.) so at this point if you are completely new to Graphics Development, probably focusing on GLSL is a good idea since Vulkan is going to take advantage of it as well.&#xD;&#xA;&#xD;&#xA;Regarding portability, D3D is Windows only (There are rumors that the [Wine](http://winehq.com/) project is trying to get D3D working under Linux but nothing feasible so far). OpenGL is cross-platform. If you want to go mobile, then OpenGL ES is an available option. Of course both OpenGL and OpenGL ES have different versions which are not supported by all platforms.&#xD;&#xA;&#xD;&#xA;At the end of the day, all APIs access the same hardware on your machine, it is just a matter of &quot;how&quot; they access it." ContentLicense="CC BY-SA 3.0" />
  <row Id="916" PostHistoryTypeId="2" PostId="318" RevisionGUID="1dadb938-87ec-4798-a868-22ec5487eb55" CreationDate="2015-08-22T07:21:29.817" UserId="100" Text="It is a well known &quot;standard&quot; to use bilateral upscaling when it comes to comes to combine a low resolution target and an higher res one. &#xD;&#xA;&#xD;&#xA;I have personally noticed that using the basic algorithm (with weights based on depth differences between high and low res depth values) is far from perfect in situations where high res and low res are blended, say for example an high res object inside a low res effect.&#xD;&#xA;&#xD;&#xA; - Jagged edges are still noticeable&#xD;&#xA; - &quot;haloes&quot; around edges start to appear when the objects/effects in low res occupy a smaller area on the target. By this I mean holes around the silouhette. &#xD;&#xA;&#xD;&#xA;I am well aware that there is no way to eliminate completely these problems, but is there a way to improve bilateral upsampling to partially improve on one of the two points above? &#xD;&#xA;&#xD;&#xA;And as side question, is there an equivalently good algorithm or variation that is cheaper?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="917" PostHistoryTypeId="1" PostId="318" RevisionGUID="1dadb938-87ec-4798-a868-22ec5487eb55" CreationDate="2015-08-22T07:21:29.817" UserId="100" Text="How to improve on bilateral upsampling in real time scenarios" ContentLicense="CC BY-SA 3.0" />
  <row Id="918" PostHistoryTypeId="3" PostId="318" RevisionGUID="1dadb938-87ec-4798-a868-22ec5487eb55" CreationDate="2015-08-22T07:21:29.817" UserId="100" Text="|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="919" PostHistoryTypeId="2" PostId="319" RevisionGUID="e1197747-b3ac-46b6-be46-2f397a3061a1" CreationDate="2015-08-22T08:02:39.787" UserId="197" Text="I'm not sure if this counts, but you can use fluid dynamics to render large crowds (of birds, people, etc). With SPH (smoothed particle hydrodynamics) to model the &quot;fluid&quot;, you aren't really describing the motion of each bird per-se, since you can sample the crowd of birds with a representative set, and then draw birds around your samples. Take a look at this paper that compares the different methods:&#xD;&#xA;&#xD;&#xA;http://gamma.cs.unc.edu/lookahead/golas-2013-hybridcrowd.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="920" PostHistoryTypeId="2" PostId="320" RevisionGUID="0c2dc387-95d9-4573-b765-eab57010ab99" CreationDate="2015-08-22T08:13:25.317" UserId="197" Text="When an image is encoded using JPEG, the RGB pixels are first encoded into YUV, and then the UV channels are downsampled. Before actually doing the DCT and encoding the coefficients, JPEG [doesn't gamma correct](http://www.w3.org/Graphics/JPEG/jfif3.pdf) the Y channel. Is this correct? Shouldn't we determine the DCT coefficients that will most affect our viewed result?" ContentLicense="CC BY-SA 3.0" />
  <row Id="921" PostHistoryTypeId="1" PostId="320" RevisionGUID="0c2dc387-95d9-4573-b765-eab57010ab99" CreationDate="2015-08-22T08:13:25.317" UserId="197" Text="Should JPEG encoding take into account gamma?" ContentLicense="CC BY-SA 3.0" />
  <row Id="922" PostHistoryTypeId="3" PostId="320" RevisionGUID="0c2dc387-95d9-4573-b765-eab57010ab99" CreationDate="2015-08-22T08:13:25.317" UserId="197" Text="|compression|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="925" PostHistoryTypeId="2" PostId="321" RevisionGUID="b1a2c6b0-f408-48dc-b8fb-7bf2c225514a" CreationDate="2015-08-23T04:25:08.513" UserId="159" Text="The short answer is &quot;no&quot;, for reasons covered in [Alvy Ray Smith's memo, *Gamma Correction*][1]. Gamma is not about nonlinearity in human perception, it's about nonlinearity in display devices (and, I suppose, acquisition devices too).&#xD;&#xA;&#xD;&#xA;  [1]: http://www.alvyray.com/memos/CG/Microsoft/9_gamma.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="927" PostHistoryTypeId="2" PostId="323" RevisionGUID="b55dacb0-50ed-4a71-aa6d-9c1059afb45b" CreationDate="2015-08-23T13:42:45.053" UserId="231" Text="I'd like to simulate the magnification of very distant objects by the lensing effect of a less distant galaxy. Will I need to model large numbers of point masses or can I get away with just a single average point mass?&#xD;&#xA;&#xD;&#xA;I can see how to raytrace using hyperbolae for the rays influenced by a single point mass, but I wouldn't know where to begin with multiple point masses. So before I attempt to build this raytracer I'd like to know whether I'm going to be able to avoid multiple masses, and still have believable results.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="928" PostHistoryTypeId="1" PostId="323" RevisionGUID="b55dacb0-50ed-4a71-aa6d-9c1059afb45b" CreationDate="2015-08-23T13:42:45.053" UserId="231" Text="Can I raytrace gravitational lensing using only a single point source of gravity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="929" PostHistoryTypeId="3" PostId="323" RevisionGUID="b55dacb0-50ed-4a71-aa6d-9c1059afb45b" CreationDate="2015-08-23T13:42:45.053" UserId="231" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="930" PostHistoryTypeId="2" PostId="324" RevisionGUID="81994241-4c85-4795-bcfe-905ba44e210e" CreationDate="2015-08-23T19:38:23.123" UserId="231" Text="I've seen a number of 2D Poisson disc sampling algorithms online that use a grid to accelerate checking for existing points within the minimum radius [![r][r image]][r link] of a candidate point. For example:&#xD;&#xA;&#xD;&#xA;- [Dev.Mag]&#xD;&#xA;- [mbostock]&#xD;&#xA;&#xD;&#xA;They use a grid of squares of side [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link], which is the same side length that I intuitively came up with when implementing this myself.&#xD;&#xA;&#xD;&#xA;I can see the reason - that is the largest square that cannot contain more than 1 point (assuming the minimum is not attainable - the distance between two points must be *strictly* greater than [![r][r image]][r link]).&#xD;&#xA;&#xD;&#xA;However, having thought about it further, I adjusted the grid size to [![r/2][r/2 image]][r/2 link] instead. This finer grid means 4 additional squares need to be checked (the 4 corner squares are now within the radius), but the total area covered by the required squares is less, so that on average fewer points will need to go through the Euclidean distance check. The difference can be visualised using the same style as the diagram in the first linked article.&#xD;&#xA;&#xD;&#xA;[![Grid with side length r over root 2][grid r over root 2]][grid r over root 2]&#xD;&#xA;[![Grid with side length r over 2][grid r over 2]][grid r over 2]&#xD;&#xA;&#xD;&#xA;Here the two grid sizes are shown side by side, to scale, for the same radius [![r][r image]][r link]. This shows clearly that a significantly smaller area is being checked. Each square is exactly half the area of the previous approach, and even if the 4 outer corner squares are excluded, this still gives the previous approach an area [![2 * 21/25 = 1.68][equation image]][equation link] times larger.&#xD;&#xA;&#xD;&#xA;My main question is this: **Is this approach still correct, and does it give identical results?**&#xD;&#xA;&#xD;&#xA;I'm also interested to know whether there is any reason to favour the [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link] approach. Using [![r/2][r/2 image]][r/2 link] seems more efficient in time, which seems worth the cost in space efficiency. As a side-effect I happen to find the code more readable (due to the lack of a square root to wonder about, and the square region to be checked rather than a square region with removed corner squares). Is there anything I'm missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [r image]: http://mathurl.com/375ggas.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r link]: http://mathurl.com/375ggas&#xD;&#xA;  [r/sqrt(2) image]: http://mathurl.com/nty6bcv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/sqrt(2) link]: http://mathurl.com/nty6bcv&#xD;&#xA;  [r/2 image]: http://mathurl.com/qhd2pm8.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/2 link]: http://mathurl.com/qhd2pm8&#xD;&#xA;&#xD;&#xA;  [Dev.Mag]: http://devmag.org.za/2009/05/03/poisson-disk-sampling/&#xD;&#xA;  [mbostock]: http://bl.ocks.org/mbostock/dbb02448b0f93e4c82c3&#xD;&#xA;&#xD;&#xA;  [grid r over root 2]: https://i.stack.imgur.com/cE5KI.png&#xD;&#xA;  [grid r over 2]: https://i.stack.imgur.com/r3PJ9.png&#xD;&#xA;&#xD;&#xA;  [equation image]: http://mathurl.com/putyzbv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [equation link]: http://mathurl.com/putyzbv&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="931" PostHistoryTypeId="1" PostId="324" RevisionGUID="81994241-4c85-4795-bcfe-905ba44e210e" CreationDate="2015-08-23T19:38:23.123" UserId="231" Text="Is this smaller grid for Poisson disc sampling still correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="932" PostHistoryTypeId="3" PostId="324" RevisionGUID="81994241-4c85-4795-bcfe-905ba44e210e" CreationDate="2015-08-23T19:38:23.123" UserId="231" Text="|grid|" ContentLicense="CC BY-SA 3.0" />
  <row Id="933" PostHistoryTypeId="5" PostId="324" RevisionGUID="9467a03a-c7b8-440c-ac6b-bef3d5021e19" CreationDate="2015-08-23T19:49:16.347" UserId="231" Comment="Rewording" Text="I've seen a number of 2D Poisson disc sampling algorithms online that use a grid to accelerate checking for existing points within the minimum radius [![r][r image]][r link] of a candidate point. For example:&#xD;&#xA;&#xD;&#xA;- [Dev.Mag]&#xD;&#xA;- [mbostock]&#xD;&#xA;&#xD;&#xA;They use a grid of squares of side [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link], which is the same side length that I intuitively came up with when implementing this myself.&#xD;&#xA;&#xD;&#xA;I can see the reason - that is the largest square that cannot contain more than 1 point (assuming the minimum is not attainable - the distance between two points must be *strictly* greater than [![r][r image]][r link]).&#xD;&#xA;&#xD;&#xA;However, having thought about it further, I adjusted the grid size to [![r/2][r/2 image]][r/2 link] instead. This finer grid means 4 additional squares need to be checked (the 4 corner squares are now within the radius), but the total area covered by the required squares is less, so that on average fewer points will need to go through the Euclidean distance check. The difference can be visualised using the same style as the diagram in the first linked article.&#xD;&#xA;&#xD;&#xA;[![Grid with side length r over root 2][grid r over root 2]][grid r over root 2]&#xD;&#xA;[![Grid with side length r over 2][grid r over 2]][grid r over 2]&#xD;&#xA;&#xD;&#xA;For a candidate new point, existing points must be checked in all squares that are within a radius [![r][r image]][r link] of the corners of the candidate's square. Here the two grid sizes are shown side by side, to scale, for the same radius [![r][r image]][r link]. This shows clearly that a significantly smaller area is being checked. Each square is exactly half the area of the previous approach, and even if the 4 outer corner squares are excluded in the previous approach (left image), this still gives an area [![2 * 21/25 = 1.68][equation image]][equation link] times larger than in the new approach.&#xD;&#xA;&#xD;&#xA;My main question is this: **Is this approach still correct, and does it give identical results?**&#xD;&#xA;&#xD;&#xA;I'm also interested to know whether there is any reason to favour the [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link] approach. Using [![r/2][r/2 image]][r/2 link] seems more efficient in time, which seems worth the cost in space efficiency. As a side-effect I happen to find the code more readable (due to the lack of a square root to wonder about, and the square region to be checked rather than a square region with removed corner squares). Is there anything I'm missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [r image]: http://mathurl.com/375ggas.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r link]: http://mathurl.com/375ggas&#xD;&#xA;  [r/sqrt(2) image]: http://mathurl.com/nty6bcv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/sqrt(2) link]: http://mathurl.com/nty6bcv&#xD;&#xA;  [r/2 image]: http://mathurl.com/qhd2pm8.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/2 link]: http://mathurl.com/qhd2pm8&#xD;&#xA;&#xD;&#xA;  [Dev.Mag]: http://devmag.org.za/2009/05/03/poisson-disk-sampling/&#xD;&#xA;  [mbostock]: http://bl.ocks.org/mbostock/dbb02448b0f93e4c82c3&#xD;&#xA;&#xD;&#xA;  [grid r over root 2]: https://i.stack.imgur.com/cE5KI.png&#xD;&#xA;  [grid r over 2]: https://i.stack.imgur.com/r3PJ9.png&#xD;&#xA;&#xD;&#xA;  [equation image]: http://mathurl.com/putyzbv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [equation link]: http://mathurl.com/putyzbv&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="935" PostHistoryTypeId="5" PostId="324" RevisionGUID="71c64bc4-c957-4d4b-9259-ae12de077192" CreationDate="2015-08-24T00:38:32.097" UserId="231" Comment="Include jsfiddle in case I need to edit the images in future" Text="I've seen a number of 2D Poisson disc sampling algorithms online that use a grid to accelerate checking for existing points within the minimum radius [![r][r image]][r link] of a candidate point. For example:&#xD;&#xA;&#xD;&#xA;- [Dev.Mag]&#xD;&#xA;- [mbostock]&#xD;&#xA;&#xD;&#xA;They use a grid of squares of side [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link], which is the same side length that I intuitively came up with when implementing this myself.&#xD;&#xA;&#xD;&#xA;I can see the reason - that is the largest square that cannot contain more than 1 point (assuming the minimum is not attainable - the distance between two points must be *strictly* greater than [![r][r image]][r link]).&#xD;&#xA;&#xD;&#xA;However, having thought about it further, I adjusted the grid size to [![r/2][r/2 image]][r/2 link] instead. This finer grid means 4 additional squares need to be checked (the 4 corner squares are now within the radius), but the total area covered by the required squares is less, so that on average fewer points will need to go through the Euclidean distance check. The difference can be visualised using the same style as the diagram in the first linked article.&#xD;&#xA;&#xD;&#xA;[![Grid with side length r over root 2][grid r over root 2]][grid r over root 2]&#xD;&#xA;[![Grid with side length r over 2][grid r over 2]][grid r over 2]&#xD;&#xA;&#xD;&#xA;For a candidate new point, existing points must be checked in all squares that are within a radius [![r][r image]][r link] of the corners of the candidate's square. Here the two grid sizes are shown side by side, to scale, for the same radius [![r][r image]][r link]. This shows clearly that a significantly smaller area is being checked. Each square is exactly half the area of the previous approach, and even if the 4 outer corner squares are excluded in the previous approach (left image), this still gives an area [![2 * 21/25 = 1.68][equation image]][equation link] times larger than in the new approach.&#xD;&#xA;&#xD;&#xA;My main question is this: **Is this approach still correct, and does it give identical results?**&#xD;&#xA;&#xD;&#xA;I'm also interested to know whether there is any reason to favour the [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link] approach. Using [![r/2][r/2 image]][r/2 link] seems more efficient in time, which seems worth the cost in space efficiency. As a side-effect I happen to find the code more readable (due to the lack of a square root to wonder about, and the square region to be checked rather than a square region with removed corner squares). Is there anything I'm missing?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;*Images produced with this [jsfiddle](https://jsfiddle.net/wkneysgj/)*&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;  [r image]: http://mathurl.com/375ggas.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r link]: http://mathurl.com/375ggas&#xD;&#xA;  [r/sqrt(2) image]: http://mathurl.com/nty6bcv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/sqrt(2) link]: http://mathurl.com/nty6bcv&#xD;&#xA;  [r/2 image]: http://mathurl.com/qhd2pm8.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/2 link]: http://mathurl.com/qhd2pm8&#xD;&#xA;&#xD;&#xA;  [Dev.Mag]: http://devmag.org.za/2009/05/03/poisson-disk-sampling/&#xD;&#xA;  [mbostock]: http://bl.ocks.org/mbostock/dbb02448b0f93e4c82c3&#xD;&#xA;&#xD;&#xA;  [grid r over root 2]: https://i.stack.imgur.com/cE5KI.png&#xD;&#xA;  [grid r over 2]: https://i.stack.imgur.com/r3PJ9.png&#xD;&#xA;&#xD;&#xA;  [equation image]: http://mathurl.com/putyzbv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [equation link]: http://mathurl.com/putyzbv&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="936" PostHistoryTypeId="2" PostId="325" RevisionGUID="0e9fc673-4f1b-4ecf-8342-12d25420392f" CreationDate="2015-08-24T16:52:15.143" UserId="250" Text="I'd like to know if there's any performance impact based on how I struct my shader uniforms. For instance, is passing 4 floats worse than passing a single vec4?" ContentLicense="CC BY-SA 3.0" />
  <row Id="937" PostHistoryTypeId="1" PostId="325" RevisionGUID="0e9fc673-4f1b-4ecf-8342-12d25420392f" CreationDate="2015-08-24T16:52:15.143" UserId="250" Text="Shader uniform performance" ContentLicense="CC BY-SA 3.0" />
  <row Id="938" PostHistoryTypeId="3" PostId="325" RevisionGUID="0e9fc673-4f1b-4ecf-8342-12d25420392f" CreationDate="2015-08-24T16:52:15.143" UserId="250" Text="|performance|glsl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="939" PostHistoryTypeId="2" PostId="326" RevisionGUID="7961dcc1-5207-49a6-8bb0-aa82de9c1d39" CreationDate="2015-08-24T17:59:01.563" UserId="56" Text="To render an image for use with red &amp; blue 3d glasses, the usual way to do it is to render from one point of view, convert it to a single intensity (greyscale) value per pixel, and then put that into the red color channel.  Render from a slightly different point of view, convert that to greyscale again and put that into the blue channel.&#xD;&#xA;&#xD;&#xA;This can be prohibitive when rendering a single time is already very costly.&#xD;&#xA;&#xD;&#xA;Are there any methods by which you could take a single render, and corresponding depth buffer, and come up with something suitable for both red and blue channels?" ContentLicense="CC BY-SA 3.0" />
  <row Id="940" PostHistoryTypeId="1" PostId="326" RevisionGUID="7961dcc1-5207-49a6-8bb0-aa82de9c1d39" CreationDate="2015-08-24T17:59:01.563" UserId="56" Text="Is it possible to render red / blue 3d from one image and a depth buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="941" PostHistoryTypeId="3" PostId="326" RevisionGUID="7961dcc1-5207-49a6-8bb0-aa82de9c1d39" CreationDate="2015-08-24T17:59:01.563" UserId="56" Text="|rendering|3d|stereo-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="942" PostHistoryTypeId="2" PostId="327" RevisionGUID="08548a67-32fc-457a-8b0c-53648dd24ffd" CreationDate="2015-08-25T00:01:43.080" UserId="54" Text="When applying multiple textures to a mesh, like for bump-mapping, I usually bind the textures to the first few fixed texture units, e.g.: diffuse = unit 0, bump = unit 1, specular = unit 2, then keep reusing those to each different mesh with different textures. But I've always wondered why [`glActiveTexture`][1] supports so many texture units (in the previous link, it says at least 80).&#xD;&#xA;&#xD;&#xA;So it occurred to me that one possible way of managing textures is to bind distinct textures to each available unit and leave them enabled, just updating the uniform sampler index. That should improve rendering perf by reducing the number of textures switches. If you have less textures than the max texture units, you never have to unbind a texture.&#xD;&#xA;&#xD;&#xA;Is this standard practice on real-time OpenGL applications (I believe this also applies to D3D)? And are there any non obvious performance implications of taking this approach? Memory overhead perhaps?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/glActiveTexture.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="943" PostHistoryTypeId="1" PostId="327" RevisionGUID="08548a67-32fc-457a-8b0c-53648dd24ffd" CreationDate="2015-08-25T00:01:43.080" UserId="54" Text="Is it good practice to use all the available texture units?" ContentLicense="CC BY-SA 3.0" />
  <row Id="944" PostHistoryTypeId="3" PostId="327" RevisionGUID="08548a67-32fc-457a-8b0c-53648dd24ffd" CreationDate="2015-08-25T00:01:43.080" UserId="54" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="945" PostHistoryTypeId="2" PostId="328" RevisionGUID="6dd44d45-f962-4546-9f82-ab0054e5d3fc" CreationDate="2015-08-25T00:33:25.640" UserId="327" Text="Modern hardware doesn't really have the concept of texture binding points as exposed by OpenGL. Rather, the shader unit uses a descriptor (which is just some kind of fat pointer) and which can potentially address any texture as long as it's resident in video memory. This is what makes things like [bindless textures][1] possible. So the large amount of &quot;texture units&quot; available in current implementations is simply trying to handwave this now-irrelevant part of the API.&#xD;&#xA;&#xD;&#xA;That said, the recommended way of implementing what you're trying to do (avoiding re-binding of textures) is to use [texture arrays][2], which allow you to dynamically index into a set of textures in the shader, as long as they all have the same format and size. This presentation contains more details about these and other techniques for reducing driver overhead when rendering with modern OpenGL: [Approaching Zero Driver Overhead][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/registry/specs/ARB/bindless_texture.txt&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Array_Texture&#xD;&#xA;  [3]: http://www.slideshare.net/CassEveritt/approaching-zero-driver-overhead" ContentLicense="CC BY-SA 3.0" />
  <row Id="946" PostHistoryTypeId="2" PostId="329" RevisionGUID="a6873238-47d2-40cd-abbe-df04f621d0f8" CreationDate="2015-08-25T04:14:15.283" UserId="116" Text="I implemented the rotation in a simple and not very efficient way&#xD;&#xA;&#xD;&#xA;    void SimplePerspectiveCamera::&#xD;&#xA;    mouseMove(const double&amp; mouseX, const double&amp; mouseY)&#xD;&#xA;    {&#xD;&#xA;    	if(m_setPan)&#xD;&#xA;    	{&#xD;&#xA;    		float sensitivity = 0.0075f;&#xD;&#xA;    		float newX = (mouseX - m_prevX) * sensitivity;&#xD;&#xA;    		float newY = (mouseY - m_prevY) * sensitivity;&#xD;&#xA;    		// TODO: Understand if it is necessary to reset the up vector to (0,1,0)&#xD;&#xA;    		m_up = Vector(0.0f, 1.0f, 0.0f);&#xD;&#xA;    		setLookAt(m_lookAt + Vector(-newX, newY, 0.0f));&#xD;&#xA;    		setPosition(m_position + Vector(-newX, newY, 0.0f));&#xD;&#xA;    		m_prevX = mouseX;&#xD;&#xA;    		m_prevY = mouseY;&#xD;&#xA;    	}&#xD;&#xA;    	if(m_setRotate)&#xD;&#xA;    	{&#xD;&#xA;    		float sensitivity = 0.005f;&#xD;&#xA;    		float newPhi = (mouseX - m_prevX) * sensitivity;&#xD;&#xA;    		float newTheta = (mouseY - m_prevY) * sensitivity;&#xD;&#xA;    		// Transform to spherical coordinates to use mouse move as deltas for&#xD;&#xA;    		// the angles.&#xD;&#xA;    		float r = m_position.norm();&#xD;&#xA;    		float theta = std::acos(m_position.y / r);&#xD;&#xA;    		float phi = std::atan(m_position.x / m_position.z);&#xD;&#xA;    &#xD;&#xA;    		theta += newTheta;&#xD;&#xA;    		phi += newPhi;&#xD;&#xA;    &#xD;&#xA;    		m_up = Vector(0.0f, 1.0f, 0.0f);&#xD;&#xA;    		Vector newPosition(r*std::sin(theta)*std::sin(phi), r*std::cos(theta),&#xD;&#xA;    				r*std::sin(theta)*std::cos(phi));&#xD;&#xA;    		setPosition(newPosition);&#xD;&#xA;    		m_prevX = mouseX;&#xD;&#xA;    		m_prevY = mouseY;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It mostly does the rotation without problems however, there is something weird happening when rotating my cube, could someone give me a clue on what am I missing?&#xD;&#xA;&#xD;&#xA;You can check what weird swap I am talking about [this link](https://vimeo.com/137210181)" ContentLicense="CC BY-SA 3.0" />
  <row Id="947" PostHistoryTypeId="1" PostId="329" RevisionGUID="a6873238-47d2-40cd-abbe-df04f621d0f8" CreationDate="2015-08-25T04:14:15.283" UserId="116" Text="Why is the color in the cube being weirdly swapped?" ContentLicense="CC BY-SA 3.0" />
  <row Id="948" PostHistoryTypeId="3" PostId="329" RevisionGUID="a6873238-47d2-40cd-abbe-df04f621d0f8" CreationDate="2015-08-25T04:14:15.283" UserId="116" Text="|transformations|trackball|" ContentLicense="CC BY-SA 3.0" />
  <row Id="949" PostHistoryTypeId="5" PostId="328" RevisionGUID="25d2056f-0263-4b02-a76e-fb2eeb51efe2" CreationDate="2015-08-25T04:34:12.847" UserId="327" Comment="fix typo" Text="Modern hardware doesn't really have the concept of texture binding points as exposed by OpenGL. Rather, the shader unit uses a descriptor (which is just some kind of fat pointer) which can potentially address any texture as long as it's resident in video memory. This is what makes things like [bindless textures][1] possible. So the large amount of &quot;texture units&quot; available in current implementations is simply trying to handwave this now-irrelevant part of the API.&#xD;&#xA;&#xD;&#xA;That said, the recommended way of implementing what you're trying to do (avoiding re-binding of textures) is to use [texture arrays][2], which allow you to dynamically index into a set of textures in the shader, as long as they all have the same format and size. This presentation contains more details about these and other techniques for reducing driver overhead when rendering with modern OpenGL: [Approaching Zero Driver Overhead][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/registry/specs/ARB/bindless_texture.txt&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Array_Texture&#xD;&#xA;  [3]: http://www.slideshare.net/CassEveritt/approaching-zero-driver-overhead" ContentLicense="CC BY-SA 3.0" />
  <row Id="950" PostHistoryTypeId="5" PostId="329" RevisionGUID="a1c13768-af6d-4b9a-9707-7f29e74b89bf" CreationDate="2015-08-25T04:46:15.257" UserId="116" Comment="Better explain the problem and describe my setup" Text="I am implementing a trackball, i.e. a camera orbiting about a fixed point, in my case the origin. When I do left click with the mouse and start moving it, I compute delta values for the angles of a sphere centered at the origin given the displacement in x and y directions of the mouse. My implementation is as follows&#xD;&#xA;&#xD;&#xA;    void SimplePerspectiveCamera::&#xD;&#xA;    mouseMove(const double&amp; mouseX, const double&amp; mouseY)&#xD;&#xA;    {&#xD;&#xA;    	if(m_setPan)&#xD;&#xA;    	{&#xD;&#xA;    		float sensitivity = 0.0075f;&#xD;&#xA;    		float newX = (mouseX - m_prevX) * sensitivity;&#xD;&#xA;    		float newY = (mouseY - m_prevY) * sensitivity;&#xD;&#xA;    		// TODO: Understand if it is necessary to reset the up vector to (0,1,0)&#xD;&#xA;    		m_up = Vector(0.0f, 1.0f, 0.0f);&#xD;&#xA;    		setLookAt(m_lookAt + Vector(-newX, newY, 0.0f));&#xD;&#xA;    		setPosition(m_position + Vector(-newX, newY, 0.0f));&#xD;&#xA;    		m_prevX = mouseX;&#xD;&#xA;    		m_prevY = mouseY;&#xD;&#xA;    	}&#xD;&#xA;    	if(m_setRotate)&#xD;&#xA;    	{&#xD;&#xA;    		float sensitivity = 0.005f;&#xD;&#xA;    		float newPhi = (mouseX - m_prevX) * sensitivity;&#xD;&#xA;    		float newTheta = (mouseY - m_prevY) * sensitivity;&#xD;&#xA;    		// Transform to spherical coordinates to use mouse move as deltas for&#xD;&#xA;    		// the angles.&#xD;&#xA;    		float r = m_position.norm();&#xD;&#xA;    		float theta = std::acos(m_position.y / r);&#xD;&#xA;    		float phi = std::atan(m_position.x / m_position.z);&#xD;&#xA;    &#xD;&#xA;    		theta += newTheta;&#xD;&#xA;    		phi += newPhi;&#xD;&#xA;    &#xD;&#xA;    		m_up = Vector(0.0f, 1.0f, 0.0f);&#xD;&#xA;    		Vector newPosition(r*std::sin(theta)*std::sin(phi), r*std::cos(theta),&#xD;&#xA;    				r*std::sin(theta)*std::cos(phi));&#xD;&#xA;    		setPosition(newPosition);&#xD;&#xA;    		m_prevX = mouseX;&#xD;&#xA;    		m_prevY = mouseY;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What I was expecting is to be able to rotate the camera around the cube in the scene so that I can see all around it. My code almost achieves this, but I don't understand why after rotating a certain amount the camera jumps to the exact opposite side of the cube.&#xD;&#xA;&#xD;&#xA;You can check what weird swap I am talking about [this link](https://vimeo.com/137210181)&#xD;&#xA;&#xD;&#xA;What am I missing so that the rotation around the object goes all the way around it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="951" PostHistoryTypeId="2" PostId="330" RevisionGUID="1823d372-e1e3-4608-af93-9d0074eb2b05" CreationDate="2015-08-25T04:59:24.840" UserId="38" Text="Yes, this is essentially the same problem that occours in paralax mapping. What you basically have is a colored height field. That needs to be rendered from a second view.&#xD;&#xA;&#xD;&#xA;There are several ways in which you can approach this. You could cheat and just shift pixels by their depth and ignore occlusion. Or you could just render a textured height map as if every pixel woild be opaque. Or you could use any of the available paralax mapping methods to eliminate occlusion. &#xD;&#xA;&#xD;&#xA;How well this works depends on the scene multi rransparent surfaces wouldnt work very well without some deep map." ContentLicense="CC BY-SA 3.0" />
  <row Id="952" PostHistoryTypeId="2" PostId="331" RevisionGUID="1806d038-b8eb-46ee-ad40-976ff8b168fb" CreationDate="2015-08-25T05:04:30.273" UserId="327" Text="It is likely that your specific problem arises from a singularity in `atan` when `m_position.z` goes to 0. Rather than try to debug that, I'll point out that you don't need to transform your camera position into an angle to then modify it: rather, just create a rotation from your `newPhi` and `newTheta` angles, in the form of a rotation matrix or quaternion, and then apply it to your vector, directly rotating it without doing the perilous round-trip to an angle." ContentLicense="CC BY-SA 3.0" />
  <row Id="953" PostHistoryTypeId="5" PostId="330" RevisionGUID="6dc15d44-7baa-4551-bd11-96083c898cff" CreationDate="2015-08-25T05:06:26.757" UserId="38" Comment="edited body" Text="Yes, this is essentially the same problem that occours in paralax mapping. What you basically have is a colored height field. That needs to be rendered from a second view.&#xD;&#xA;&#xD;&#xA;There are several ways in which you can approach this. You could cheat and just shift pixels by their depth and ignore occlusion. Or you could just render a textured height map as if every pixel would be opaque. Or you could use any of the available paralax mapping methods to eliminate occlusion. &#xD;&#xA;&#xD;&#xA;How well this works depends on the. A scene multiple transparent surfaces wouldnt work very well without some deep map." ContentLicense="CC BY-SA 3.0" />
  <row Id="954" PostHistoryTypeId="2" PostId="332" RevisionGUID="a929173e-bf36-4be0-a30a-6277e992d777" CreationDate="2015-08-25T05:19:19.273" UserId="327" Text="In any modern desktop hardware, there shouldn't be: uniform buffers will just be memory blobs read by the shader. (See also: [Uniform Buffer Objects][1])&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Uniform_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="955" PostHistoryTypeId="2" PostId="333" RevisionGUID="343e70f0-b47b-4559-bb8d-c0318edf27ec" CreationDate="2015-08-25T05:32:18.040" UserId="38" Text="Im developping a deep texture processing engine. Right now i have a software renderer to generate the raster samples. Now, for bigger renders it would be nice to do this on hardware.&#xD;&#xA;&#xD;&#xA;Is there a standard mechanism on how to capture the data of each shader evaluation in openGL? I could do some sort of depth peeling but it seems to me as a bit too brute forcelike approach. I dont mind the time cost just as long as it does not take ages to implement the infrastructure needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="956" PostHistoryTypeId="1" PostId="333" RevisionGUID="343e70f0-b47b-4559-bb8d-c0318edf27ec" CreationDate="2015-08-25T05:32:18.040" UserId="38" Text="Is there a way for me to record every shading sample for a deep texture" ContentLicense="CC BY-SA 3.0" />
  <row Id="957" PostHistoryTypeId="3" PostId="333" RevisionGUID="343e70f0-b47b-4559-bb8d-c0318edf27ec" CreationDate="2015-08-25T05:32:18.040" UserId="38" Text="|opengl|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="958" PostHistoryTypeId="5" PostId="333" RevisionGUID="eb2975be-7365-4660-9d4d-a419952d9911" CreationDate="2015-08-25T06:12:31.683" UserId="127" Comment="Corrected spelling" Text="Im developing a deep texture processing engine. Right now I have a software renderer to generate the raster samples. Now, for bigger renders it would be nice to do this on hardware.&#xD;&#xA;&#xD;&#xA;Is there a standard mechanism on how to capture the data of each shader evaluation in OpenGL? I could do some sort of depth peeling but it seems to me as a bit too brute forcelike approach. I don't mind the time cost just as long as it does not take ages to implement the infrastructure needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="959" PostHistoryTypeId="24" PostId="333" RevisionGUID="eb2975be-7365-4660-9d4d-a419952d9911" CreationDate="2015-08-25T06:12:31.683" Comment="Proposed by 127 approved by 38 edit id of 43" ContentLicense="CC BY-SA 3.0" />
  <row Id="960" PostHistoryTypeId="2" PostId="334" RevisionGUID="69c793e1-2912-4d8a-8df7-3a612a40d955" CreationDate="2015-08-25T06:53:55.193" UserId="48" Text="If you really want to obtain every fragment (shading sample) within the camera frustum, regardless of occlusion, one way to do it would be to disable depth testing, and then use a large [SSBO](https://www.opengl.org/wiki/Shader_Storage_Buffer_Object) together with an [atomic counter](https://www.opengl.org/wiki/Atomic_Counter) to append data into the buffer from the fragment shader.  Each fragment could then store a record of its screen position, depth, color, and any other desired information into the buffer to be read out later.  The buffer has to be large enough to store every fragment rendered, as it will throw away any extra data once it's full.&#xD;&#xA;&#xD;&#xA;Using one huge SSBO for the whole screen likely isn't ideal, as there will be huge contention on its counter with every fragment trying to increment it.  A better way might be to slice up the screen in tiles with an SSBO+counter per tile.  There is a limit of 16 bound SSBOs on all current GPUs, and on AMD GPUs, there is a further limit of 8 atomic counters (source: Sascha Willem's [OpenGL Hardware Database](http://delphigl.de/glcapsviewer/gl_listreports)).  Those limits will determine how many tiles you can create. This will reduce contention and also ensure that even if you run out of memory in one tile, you'll still have valid data in the others." ContentLicense="CC BY-SA 3.0" />
  <row Id="961" PostHistoryTypeId="2" PostId="335" RevisionGUID="f7acd7d2-d927-4af9-8fbe-adee96cfd170" CreationDate="2015-08-25T10:58:31.680" UserId="141" Text="I'm trying to understand NURBS curves (surfaces later!) but I have some trouble understanding the very basics of its inner workings. Could someone please explain a few things to me? As I come from Bezier curves, a comparison between these two would be especially useful.&#xD;&#xA;&#xD;&#xA;1. The [&quot;rational basis function&quot;](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline#Technical_specifications) looks a tiny bit like Bernstein polynomial of (rational) Bezier curve. Does the parameter `u` also go from 0 to 1?&#xD;&#xA;&#xD;&#xA;2. How to &quot;add detail&quot; to a curve? I mean, with Beziers if I needed to describe a more complicated shape I would simply &quot;stitch&quot; several Beziers together. Or less often, increase the degree. I understand I can increase the degree of NURBS as well and put several NURBS curves side-by-side, but is this how it should be done?&#xD;&#xA;&#xD;&#xA;3. The benefit of NURBS over, say Beziers, is the ability to create offset curves exactly. How? Do I just translate the control points?&#xD;&#xA;&#xD;&#xA;4. The Wikipedia article, at least to me, seems not very clear about this &quot;knot vector&quot;. What is it anyway?&#xD;&#xA;&#xD;&#xA;5. How to draw a NURBS curve? With Beziers, I just evaluate the Bernstein polynomial, multiply it with control point positions and that's it. Looking at the &quot;General form of a NURBS curve&quot; I have a hard time seeing a polynomial in it. Maybe this &quot;basis function&quot; is a polynomial in the end? Is there an efficient way of constructing the basis function and evaluating it?&#xD;&#xA;&#xD;&#xA;6. Splitting Beziers is easy thanks to [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm). Is there anything similar for NURBS? How to split a NURBS curve?" ContentLicense="CC BY-SA 3.0" />
  <row Id="962" PostHistoryTypeId="1" PostId="335" RevisionGUID="f7acd7d2-d927-4af9-8fbe-adee96cfd170" CreationDate="2015-08-25T10:58:31.680" UserId="141" Text="Non-uniform rational B-spline (NURBS) Basics" ContentLicense="CC BY-SA 3.0" />
  <row Id="963" PostHistoryTypeId="3" PostId="335" RevisionGUID="f7acd7d2-d927-4af9-8fbe-adee96cfd170" CreationDate="2015-08-25T10:58:31.680" UserId="141" Text="|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="964" PostHistoryTypeId="5" PostId="324" RevisionGUID="79913443-af72-4dcf-9bc7-8f839c6848c2" CreationDate="2015-08-25T13:13:26.683" UserId="231" Comment="Remove irrelevant readability observations" Text="I've seen a number of 2D Poisson disc sampling algorithms online that use a grid to accelerate checking for existing points within the minimum radius [![r][r image]][r link] of a candidate point. For example:&#xD;&#xA;&#xD;&#xA;- [Dev.Mag]&#xD;&#xA;- [mbostock]&#xD;&#xA;&#xD;&#xA;They use a grid of squares of side [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link], which is the same side length that I intuitively came up with when implementing this myself.&#xD;&#xA;&#xD;&#xA;I can see the reason - that is the largest square that cannot contain more than 1 point (assuming the minimum is not attainable - the distance between two points must be *strictly* greater than [![r][r image]][r link]).&#xD;&#xA;&#xD;&#xA;However, having thought about it further, I adjusted the grid size to [![r/2][r/2 image]][r/2 link] instead. This finer grid means 4 additional squares need to be checked (the 4 corner squares are now within the radius), but the total area covered by the required squares is less, so that on average fewer points will need to go through the Euclidean distance check. The difference can be visualised using the same style as the diagram in the first linked article.&#xD;&#xA;&#xD;&#xA;[![Grid with side length r over root 2][grid r over root 2]][grid r over root 2]&#xD;&#xA;[![Grid with side length r over 2][grid r over 2]][grid r over 2]&#xD;&#xA;&#xD;&#xA;For a candidate new point, existing points must be checked in all squares that are within a radius [![r][r image]][r link] of the corners of the candidate's square. Here the two grid sizes are shown side by side, to scale, for the same radius [![r][r image]][r link]. This shows clearly that a significantly smaller area is being checked. Each square is exactly half the area of the previous approach, and even if the 4 outer corner squares are excluded in the previous approach (left image), this still gives an area [![2 * 21/25 = 1.68][equation image]][equation link] times larger than in the new approach.&#xD;&#xA;&#xD;&#xA;My main question is this: **Is this approach still correct, and does it give identical results?**&#xD;&#xA;&#xD;&#xA;I'm also interested to know whether there is any reason to favour the [![r/sqrt(2)][r/sqrt(2) image]][r/sqrt(2) link] approach. Using [![r/2][r/2 image]][r/2 link] seems more efficient in time, which seems worth the cost in space efficiency. Is there anything I'm missing?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;*Images produced with this [jsfiddle](https://jsfiddle.net/wkneysgj/) (in case I need to edit them later).*&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;  [r image]: http://mathurl.com/375ggas.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r link]: http://mathurl.com/375ggas&#xD;&#xA;  [r/sqrt(2) image]: http://mathurl.com/nty6bcv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/sqrt(2) link]: http://mathurl.com/nty6bcv&#xD;&#xA;  [r/2 image]: http://mathurl.com/qhd2pm8.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [r/2 link]: http://mathurl.com/qhd2pm8&#xD;&#xA;&#xD;&#xA;  [Dev.Mag]: http://devmag.org.za/2009/05/03/poisson-disk-sampling/&#xD;&#xA;  [mbostock]: http://bl.ocks.org/mbostock/dbb02448b0f93e4c82c3&#xD;&#xA;&#xD;&#xA;  [grid r over root 2]: https://i.stack.imgur.com/cE5KI.png&#xD;&#xA;  [grid r over 2]: https://i.stack.imgur.com/r3PJ9.png&#xD;&#xA;&#xD;&#xA;  [equation image]: http://mathurl.com/putyzbv.png &quot;Edit on mathurl.com&quot;&#xD;&#xA;  [equation link]: http://mathurl.com/putyzbv&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="965" PostHistoryTypeId="2" PostId="336" RevisionGUID="2c8c652c-87ae-4593-bbc5-ccca90759563" CreationDate="2015-08-25T13:58:27.733" UserId="141" Text="I'm not sure how practical this might be but is it possible to use Fast Fourier Transform to rotate a raster image?&#xD;&#xA;&#xD;&#xA;To be honest, I never really understood FFT, but I saw it being used for JPEG, for example. What I try to say is let's pretend I can grab some FFT library, what do I do next?&#xD;&#xA;&#xD;&#xA;Also, I read that there is this [Gibbs phenomenon](https://en.wikipedia.org/wiki/Gibbs_phenomenon) which causes ringing artifacts. Would it be a problem here as well?" ContentLicense="CC BY-SA 3.0" />
  <row Id="966" PostHistoryTypeId="1" PostId="336" RevisionGUID="2c8c652c-87ae-4593-bbc5-ccca90759563" CreationDate="2015-08-25T13:58:27.733" UserId="141" Text="Image rotation using FFT" ContentLicense="CC BY-SA 3.0" />
  <row Id="967" PostHistoryTypeId="3" PostId="336" RevisionGUID="2c8c652c-87ae-4593-bbc5-ccca90759563" CreationDate="2015-08-25T13:58:27.733" UserId="141" Text="|transformations|fourier-transform|raster-image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="968" PostHistoryTypeId="2" PostId="337" RevisionGUID="610c6f2e-10f3-4e3e-add5-27e7222617dc" CreationDate="2015-08-25T14:04:58.757" UserId="157" Text="Radiosity is basically what allows this:&#xD;&#xA;[![Direct Illumination VS Radiosity][1]][1]&#xD;&#xA;&#xD;&#xA;In a tutorial of [Cornell University about Radiosity][2] it is mentioned that:&#xD;&#xA;&#xD;&#xA;&gt; A ray-traced version of the image shows only the light reaching the viewer by direct reflection -- hence misses the color effects.&#xD;&#xA;&#xD;&#xA;However in [Wikipedia][3]:&#xD;&#xA;&#xD;&#xA;&gt; Radiosity is a global illumination algorithm in the sense that the illumination arriving on a surface comes not just directly from the light sources, but also from other surfaces reflecting light.&#xD;&#xA;&#xD;&#xA;&gt; ...&#xD;&#xA;&#xD;&#xA;&gt; The [radiosity method][4] in the current computer graphics context derives from (and is fundamentally the same as) the radiosity method in heat transfer.&#xD;&#xA;&#xD;&#xA;And if [ray tracing][5] is capable of:&#xD;&#xA;&#xD;&#xA;&gt; simulating a wide variety of optical effects, such as reflection ([diffuse reflection][6]) and [**scattering** (i.e. the deflection of a ray from a straight path, for example by irregularities in the propagation medium, particles, or in the interface between two media)][7]&#xD;&#xA;&#xD;&#xA;Has that tutorial not considered these effects or are there radiosity methods that can be used in ray tracing in order to enable them?&#xD;&#xA;&#xD;&#xA;If not, couldn't these optical effects simulate radiosity entirely or is the [radiosity algorithm][8] more efficient in solving the diffuse reflection problem?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j9CFM.jpg&#xD;&#xA;  [2]: http://www.graphics.cornell.edu/online/tutorial/radiosity/&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiosity_%28computer_graphics%29&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Radiosity_(computer_graphics)#Confusion_about_terminology&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Ray_tracing_%28graphics%29&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Diffuse_reflection&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Light_scattering&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Radiosity_(computer_graphics)#Overview_of_the_radiosity_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="969" PostHistoryTypeId="1" PostId="337" RevisionGUID="610c6f2e-10f3-4e3e-add5-27e7222617dc" CreationDate="2015-08-25T14:04:58.757" UserId="157" Text="Radiosity VS Ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="970" PostHistoryTypeId="3" PostId="337" RevisionGUID="610c6f2e-10f3-4e3e-add5-27e7222617dc" CreationDate="2015-08-25T14:04:58.757" UserId="157" Text="|raytracing|reflection|scattering|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="971" PostHistoryTypeId="2" PostId="338" RevisionGUID="5ebaada5-5cbf-4d35-9316-e4c7d88810ad" CreationDate="2015-08-25T14:05:06.773" UserId="141" Text="The benefit of NURBS curve over, say Bezier curve, is the ability to create offset curves exactly. How to proceed with such computation? Do I just translate the control points?" ContentLicense="CC BY-SA 3.0" />
  <row Id="972" PostHistoryTypeId="1" PostId="338" RevisionGUID="5ebaada5-5cbf-4d35-9316-e4c7d88810ad" CreationDate="2015-08-25T14:05:06.773" UserId="141" Text="NURBS curve offset" ContentLicense="CC BY-SA 3.0" />
  <row Id="973" PostHistoryTypeId="3" PostId="338" RevisionGUID="5ebaada5-5cbf-4d35-9316-e4c7d88810ad" CreationDate="2015-08-25T14:05:06.773" UserId="141" Text="|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="974" PostHistoryTypeId="2" PostId="339" RevisionGUID="4bc0b36a-8f53-468f-a285-a6d2bb4a1b6b" CreationDate="2015-08-25T14:07:20.570" UserId="141" Text="How to draw a NURBS curve?&#xD;&#xA;&#xD;&#xA;Compared with Bezier curve, I just evaluate the Bernstein polynomial, multiply it with control point positions and that's it.&#xD;&#xA;&#xD;&#xA;Looking at the &quot;General form of a NURBS curve&quot; paragraph of [NURBS Wikipedia page](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline#Technical_specifications) I have a hard time seeing a polynomial in it. Maybe this &quot;basis function&quot; is a polynomial in the end? Is there an efficient way of constructing the basis function and evaluating it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="975" PostHistoryTypeId="1" PostId="339" RevisionGUID="4bc0b36a-8f53-468f-a285-a6d2bb4a1b6b" CreationDate="2015-08-25T14:07:20.570" UserId="141" Text="NURBS curve drawing" ContentLicense="CC BY-SA 3.0" />
  <row Id="976" PostHistoryTypeId="3" PostId="339" RevisionGUID="4bc0b36a-8f53-468f-a285-a6d2bb4a1b6b" CreationDate="2015-08-25T14:07:20.570" UserId="141" Text="|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="977" PostHistoryTypeId="2" PostId="340" RevisionGUID="889517a5-1530-41a0-b7d6-8af3ae1782b3" CreationDate="2015-08-25T14:08:56.157" UserId="141" Text="Splitting Bezier curve is easy thanks to [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm). Is there a similar algorithm for NURBS curves? How to split a NURBS curve?" ContentLicense="CC BY-SA 3.0" />
  <row Id="978" PostHistoryTypeId="1" PostId="340" RevisionGUID="889517a5-1530-41a0-b7d6-8af3ae1782b3" CreationDate="2015-08-25T14:08:56.157" UserId="141" Text="Splitting of NURBS curves" ContentLicense="CC BY-SA 3.0" />
  <row Id="979" PostHistoryTypeId="3" PostId="340" RevisionGUID="889517a5-1530-41a0-b7d6-8af3ae1782b3" CreationDate="2015-08-25T14:08:56.157" UserId="141" Text="|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="980" PostHistoryTypeId="5" PostId="335" RevisionGUID="758c3a0e-2703-4906-aa14-fe8ccac05e2a" CreationDate="2015-08-25T14:13:05.510" UserId="141" Comment="deleted 706 characters in body" Text="I'm trying to understand NURBS curves (surfaces later!) but I have some trouble understanding the very basics of its inner workings. Could someone please explain a few things to me? As I come from Bezier curves, a comparison between these two would be especially useful.&#xD;&#xA;&#xD;&#xA;1. The [&quot;rational basis function&quot;](https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline#Technical_specifications) looks a tiny bit like Bernstein polynomial of (rational) Bezier curve. Does the parameter `u` also go from 0 to 1?&#xD;&#xA;&#xD;&#xA;2. How to &quot;add detail&quot; to a curve? I mean, with Beziers if I needed to describe a more complicated shape I would simply &quot;stitch&quot; several Beziers together. Or less often, increase the degree. I understand I can increase the degree of NURBS as well and put several NURBS curves side-by-side, but is this how it should be done?&#xD;&#xA;&#xD;&#xA;3. The Wikipedia article, at least to me, seems not very clear about this &quot;knot vector&quot;. What is it anyway?" ContentLicense="CC BY-SA 3.0" />
  <row Id="981" PostHistoryTypeId="5" PostId="338" RevisionGUID="c854e3e2-1770-41f5-9193-2fba7a5f5cc6" CreationDate="2015-08-25T14:17:11.867" UserId="141" Comment="added 8 characters in body" Text="One of the benefits of NURBS curve over, say Bezier curve, is the ability to create offset curves exactly. How to proceed with such computation? Do I just translate the control points?" ContentLicense="CC BY-SA 3.0" />
  <row Id="982" PostHistoryTypeId="5" PostId="340" RevisionGUID="d2aeedb5-cb40-49ec-8e5a-7c6b67e04c61" CreationDate="2015-08-25T14:18:49.773" UserId="141" Comment="added 40 characters in body" Text="Splitting Bezier curve into two parts at some parameter `t` is easy thanks to [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm).&#xD;&#xA;&#xD;&#xA;Is there a similar algorithm for NURBS curves? How to split a NURBS curve?" ContentLicense="CC BY-SA 3.0" />
  <row Id="983" PostHistoryTypeId="2" PostId="341" RevisionGUID="8e07bc22-7419-44a1-a0fb-c06ccd8ead81" CreationDate="2015-08-25T14:24:03.697" UserId="56" Text="A NURBS differs from a Bezier curve in two ways...&#xD;&#xA;&#xD;&#xA;1) It's rational which means that it's one curve divided by another. (rational comes from &quot;ratio&quot;, not anything to do with it's temperament!)&#xD;&#xA;&#xD;&#xA;Being rational is not an issue though for being simple to evaluate.  There are even such things as rational Bezier curves, where again, you just divide one Bezier curve by another to get the final result.&#xD;&#xA;&#xD;&#xA;This allows you to make shapes with Bezier curves that you wouldn't be able to otherwise, for instance, rational Bezier curves can EXACTLY represent conic sections.&#xD;&#xA;&#xD;&#xA;Here's an HTML5 demo where you can play with a rational Bezier curve:&#xD;&#xA;http://demofox.org/bezquadrational.html&#xD;&#xA;&#xD;&#xA;Also, here is a shadertoy which uses a rational Bezier curve to calculate sin!&#xD;&#xA;https://www.shadertoy.com/view/XtfSRH&#xD;&#xA;&#xD;&#xA;2) The second difference is the one that makes it more difficult to evaluate, at least for me.  The second difference is that a NURBS, like a B-spline, can have any number of control points, but has a fixed degree.  How this works is that any given point on the curve is only influenced by a specific number of control points.&#xD;&#xA;&#xD;&#xA;You could have for example a quadratic curve with 8 control points,  where each point on the curve was only defined by 3 of the control points at a time.&#xD;&#xA;&#xD;&#xA;Where the influence of the control points begin and end is called the knot vector.&#xD;&#xA;&#xD;&#xA;So basically, if you can evaluate a rational curve, and you can evaluate a b-spline, you will then know how to evaluate a NURBS.&#xD;&#xA;&#xD;&#xA;Explaining how to evaluate a b-spline is too long for an answer I think, and there is lots of info on the web, and in text books, so i'll link to a couple things that might help you!&#xD;&#xA;&#xD;&#xA;Here is a shadertoy rendering a b-spline in a pixel shader:&#xD;&#xA;https://www.shadertoy.com/view/MtfSRN&#xD;&#xA;&#xD;&#xA;Here is info on how to evaluate a b-spline:&#xD;&#xA;http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node18.html&#xD;&#xA;&#xD;&#xA;Also, here is some code (GLSL) that shows how to evaluate an 8 control point cubic B-spline:&#xD;&#xA;&#xD;&#xA;    float N_i_1 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        // return 1 if i &lt; t &lt; i+1, else return 0&#xD;&#xA;        return step(i, t) * step(t,i+1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_2 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_1(t, i)       * (t - i) +&#xD;&#xA;            N_i_1(t, i + 1.0) * (i + 2.0 - t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_3 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_2(t, i)       * (t - i) / 2.0 +&#xD;&#xA;            N_i_2(t, i + 1.0) * (i + 3.0 - t) / 2.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_4 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_3(t, i)       * (t - i) / 3.0 +&#xD;&#xA;            N_i_3(t, i + 1.0) * (i + 4.0 - t) / 3.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float SplineValue(in float t)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            P0 * N_i_4(t, 0.0) +&#xD;&#xA;            P1 * N_i_4(t, 1.0) +&#xD;&#xA;            P2 * N_i_4(t, 2.0) +&#xD;&#xA;            P3 * N_i_4(t, 3.0) +&#xD;&#xA;            P4 * N_i_4(t, 4.0) +&#xD;&#xA;            P5 * N_i_4(t, 5.0) +&#xD;&#xA;            P6 * N_i_4(t, 6.0) +&#xD;&#xA;            P7 * N_i_4(t, 7.0);   &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="984" PostHistoryTypeId="5" PostId="341" RevisionGUID="e9c1f550-4f94-4ebb-aed3-ab850b1e5199" CreationDate="2015-08-25T14:37:39.803" UserId="56" Comment="added 145 characters in body" Text="A NURBS differs from a Bezier curve in two ways...&#xD;&#xA;&#xD;&#xA;1) It's rational which means that it's one curve divided by another. (rational comes from &quot;ratio&quot;, not anything to do with it's temperament!)&#xD;&#xA;&#xD;&#xA;Being rational is not an issue though for being simple to evaluate.  There are even such things as rational Bezier curves, where again, you just divide one Bezier curve by another to get the final result.&#xD;&#xA;&#xD;&#xA;This allows you to make shapes with Bezier curves that you wouldn't be able to otherwise, for instance, rational Bezier curves can EXACTLY represent conic sections.&#xD;&#xA;&#xD;&#xA;Here's an HTML5 demo where you can play with a rational Bezier curve:&#xD;&#xA;http://demofox.org/bezquadrational.html&#xD;&#xA;&#xD;&#xA;Also, here is a shadertoy which uses a rational Bezier curve to calculate sin!&#xD;&#xA;https://www.shadertoy.com/view/XtfSRH&#xD;&#xA;&#xD;&#xA;2) The second difference is the one that makes it more difficult to evaluate, at least for me.  The second difference is that a NURBS, like a B-spline, can have any number of control points, but has a fixed degree.  How this works is that any given point on the curve is only influenced by a specific number of control points.&#xD;&#xA;&#xD;&#xA;You could have for example a quadratic curve with 8 control points,  where each point on the curve was only defined by 3 of the control points at a time.&#xD;&#xA;&#xD;&#xA;Where the influence of the control points begin and end is called the knot vector.&#xD;&#xA;&#xD;&#xA;So basically, if you can evaluate a rational curve, and you can evaluate a b-spline, you will then know how to evaluate a NURBS.&#xD;&#xA;&#xD;&#xA;Explaining how to evaluate a b-spline is too long for an answer I think, and there is lots of info on the web, and in text books, so i'll link to a couple things that might help you!&#xD;&#xA;&#xA;Read up on De Boor's algorithm, its the b-spline equivalent of De Casteljeau's algorithm:&#xA;https://en.m.wikipedia.org/wiki/De_Boor%27s_algorithm&#xA;&#xD;&#xA;Here is a shadertoy rendering a b-spline in a pixel shader:&#xD;&#xA;https://www.shadertoy.com/view/MtfSRN&#xD;&#xA;&#xD;&#xA;Here is info on how to evaluate a b-spline:&#xD;&#xA;http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node18.html&#xD;&#xA;&#xD;&#xA;Also, here is some code (GLSL) that shows how to evaluate an 8 control point cubic B-spline:&#xD;&#xA;&#xD;&#xA;    float N_i_1 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        // return 1 if i &lt; t &lt; i+1, else return 0&#xD;&#xA;        return step(i, t) * step(t,i+1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_2 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_1(t, i)       * (t - i) +&#xD;&#xA;            N_i_1(t, i + 1.0) * (i + 2.0 - t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_3 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_2(t, i)       * (t - i) / 2.0 +&#xD;&#xA;            N_i_2(t, i + 1.0) * (i + 3.0 - t) / 2.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_4 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_3(t, i)       * (t - i) / 3.0 +&#xD;&#xA;            N_i_3(t, i + 1.0) * (i + 4.0 - t) / 3.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float SplineValue(in float t)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            P0 * N_i_4(t, 0.0) +&#xD;&#xA;            P1 * N_i_4(t, 1.0) +&#xD;&#xA;            P2 * N_i_4(t, 2.0) +&#xD;&#xA;            P3 * N_i_4(t, 3.0) +&#xD;&#xA;            P4 * N_i_4(t, 4.0) +&#xD;&#xA;            P5 * N_i_4(t, 5.0) +&#xD;&#xA;            P6 * N_i_4(t, 6.0) +&#xD;&#xA;            P7 * N_i_4(t, 7.0);   &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="985" PostHistoryTypeId="2" PostId="342" RevisionGUID="467d6b19-58aa-4462-84a0-3257b9d9c9c1" CreationDate="2015-08-25T14:55:49.330" UserId="157" Text="I thought of this after my [radiosity vs ray tracing question][1].&#xD;&#xA;&#xD;&#xA;A radiosity algorithm seems to require [increased calculations because it's viewpoint independent][2] and therefore, [false radiosity][3] was born (at least it's the way it was explained). It is mentioned that in order to simulate radiosity, changes were done directly in texture maps (in PS for example) or omni-type lights are placed where radiosity effects occur.&#xD;&#xA;&#xD;&#xA;I wonder if false radiosity is still used nowadays (I'm assuming this may happen more often in games development). If so, are these techniques currently used or are there others methods to achieve the same purpose? Any examples would be a plus.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/337/radiosity-vs-ray-tracing&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Radiosity_%28computer_graphics%29&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/False_radiosity" ContentLicense="CC BY-SA 3.0" />
  <row Id="986" PostHistoryTypeId="1" PostId="342" RevisionGUID="467d6b19-58aa-4462-84a0-3257b9d9c9c1" CreationDate="2015-08-25T14:55:49.330" UserId="157" Text="Are there specific techniques for generating False Radiosity in surfaces?" ContentLicense="CC BY-SA 3.0" />
  <row Id="987" PostHistoryTypeId="3" PostId="342" RevisionGUID="467d6b19-58aa-4462-84a0-3257b9d9c9c1" CreationDate="2015-08-25T14:55:49.330" UserId="157" Text="|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="988" PostHistoryTypeId="6" PostId="335" RevisionGUID="fba01021-5f1b-44dd-ab06-4ca2448668e3" CreationDate="2015-08-25T15:31:50.937" UserId="38" Comment="edited tags" Text="|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="989" PostHistoryTypeId="2" PostId="343" RevisionGUID="991b0ead-c70e-41b2-8dcb-b9e6596e4c17" CreationDate="2015-08-25T16:12:23.277" UserId="38" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1 points. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 spans after each other, each span uses 4 points. together they form one curve.&#xD;&#xA;&#xD;&#xA;\* this means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="990" PostHistoryTypeId="5" PostId="343" RevisionGUID="a9806a09-2d5d-4581-bf98-141474d263e7" CreationDate="2015-08-25T16:18:04.143" UserId="38" Comment="added 40 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="991" PostHistoryTypeId="5" PostId="343" RevisionGUID="bdbdcca8-43e6-4ef7-80b4-6b908012b1cd" CreationDate="2015-08-25T16:27:25.053" UserId="38" Comment="added 6 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="992" PostHistoryTypeId="2" PostId="344" RevisionGUID="6b2dfdfb-9a9b-4974-95af-d5db9b6078c4" CreationDate="2015-08-25T16:47:01.460" UserId="141" Text="Radiosity does not account for specular reflections (i.e. it only handles diffuse reflections). Whitted's ray-tracing only considers glossy or diffuse reflection, possibly mirror-reflected. And finally, Kajiya's path-tracing is the most general one [2], handling any number of diffuse, glossy and specular reflections.&#xD;&#xA;&#xD;&#xA;So I think it depends on what you means by &quot;ray-tracing&quot;: the technique developed by Whitted or any kind of &quot;tracing rays&quot;...&#xD;&#xA;&#xD;&#xA;Sidenode: Heckbert [1] (or Shirley?) devised a classification of light scattering events which took place as the light traveled from the luminaire to the eye. In general it has the following form:&#xD;&#xA;&#xD;&#xA;    L(S|D)*E&#xD;&#xA;&#xD;&#xA;&quot;L&quot; stands for luminaire, &quot;D&quot; for diffuse reflection, &quot;S&quot; for specular reflection or refraction, &quot;E&quot; for eye, and the symbols &quot;*&quot;, &quot;|&quot;, &quot;()&quot;, &quot;[]&quot; come from regular languages notaion and denote &quot;zero or more&quot;, &quot;or&quot;, &quot;grouping&quot;, &quot;one of&quot;, respectively.&#xD;&#xA;&#xD;&#xA;In particualar, the following techniques are classified as:&#xD;&#xA;&#xD;&#xA;* OpenGL shading: `EDL`&#xD;&#xA;&#xD;&#xA;* Appel's ray-casting: `E(D|G)L`&#xD;&#xA;&#xD;&#xA;* Whitted's ray-tracing: `E[S*](D|G)L`&#xD;&#xA;&#xD;&#xA;* Kajiya's path-tracing: `E[(D|G|S)+(D|G)]L`&#xD;&#xA;&#xD;&#xA;* Golar's radiosity: `ED*L`&#xD;&#xA;&#xD;&#xA;[1] Paul S. Heckbert. Adaptive radiosity textures for bidirectional ray tracing. SIGGRAPH Computer Graphics, Volume 24, Number 4, August 1990&#xD;&#xA;&#xD;&#xA;[2] The Siggraph 2001 course &quot;State of the Art in Monte Carlo Ray Tracing for Realistic Image Synthesis&quot; says the following: &quot;Distributed ray tracing and path tracing&#xD;&#xA;includes multiple bounces involving non-specular scattering such as `E(D|G)*L`. However, even these methods ignore paths of the form `E(D|G)S*L`; that is, multiple specular bounces from the light source as in a caustic.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="993" PostHistoryTypeId="5" PostId="344" RevisionGUID="2c43f35b-482e-425f-8879-bfbae3587788" CreationDate="2015-08-25T16:54:53.693" UserId="141" Comment="added 288 characters in body" Text="Radiosity does not account for specular reflections (i.e. it only handles diffuse reflections). Whitted's ray-tracing only considers glossy or diffuse reflection, possibly mirror-reflected. And finally, Kajiya's path-tracing is the most general one [2], handling any number of diffuse, glossy and specular reflections.&#xD;&#xA;&#xD;&#xA;So I think it depends on what you means by &quot;ray-tracing&quot;: the technique developed by Whitted or any kind of &quot;tracing rays&quot;...&#xD;&#xA;&#xD;&#xA;Sidenode: Heckbert [1] (or Shirley?) devised a classification of light scattering events which took place as the light traveled from the luminaire to the eye. In general it has the following form:&#xD;&#xA;&#xD;&#xA;    L(S|D)*E&#xD;&#xA;&#xD;&#xA;&quot;L&quot; stands for luminaire, &quot;D&quot; for diffuse reflection, &quot;S&quot; for specular reflection or refraction, &quot;E&quot; for eye, and the symbols &quot;*&quot;, &quot;|&quot;, &quot;()&quot;, &quot;[]&quot; come from regular languages notaion and denote &quot;zero or more&quot;, &quot;or&quot;, &quot;grouping&quot;, &quot;one of&quot;, respectively. Veach [3] extended the notation in his famous dissertation by &quot;D&quot; for Lambertian, &quot;S&quot; for specular and &quot;G&quot; for glossy reflection, and &quot;T&quot; for transmission.&#xD;&#xA;&#xD;&#xA;In particular, the following techniques are classified as:&#xD;&#xA;&#xD;&#xA;* OpenGL shading: `EDL`&#xD;&#xA;&#xD;&#xA;* Appel's ray-casting: `E(D|G)L`&#xD;&#xA;&#xD;&#xA;* Whitted's ray-tracing: `E[S*](D|G)L`&#xD;&#xA;&#xD;&#xA;* Kajiya's path-tracing: `E[(D|G|S)+(D|G)]L`&#xD;&#xA;&#xD;&#xA;* Golar's radiosity: `ED*L`&#xD;&#xA;&#xD;&#xA;[1] Paul S. Heckbert. Adaptive radiosity textures for bidirectional ray tracing. SIGGRAPH Computer Graphics, Volume 24, Number 4, August 1990&#xD;&#xA;&#xD;&#xA;[2] The Siggraph 2001 course &quot;State of the Art in Monte Carlo Ray Tracing for Realistic Image Synthesis&quot; says the following: &quot;Distributed ray tracing and path tracing&#xD;&#xA;includes multiple bounces involving non-specular scattering such as `E(D|G)*L`. However, even these methods ignore paths of the form `E(D|G)S*L`; that is, multiple specular bounces from the light source as in a caustic.&quot;&#xD;&#xA;&#xD;&#xA;[3] Eric Veach. Robust Monte Carlo Methods for Light Transport Simulation. Ph.D. dissertation, Stanford University, December 1997&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="994" PostHistoryTypeId="5" PostId="341" RevisionGUID="adf53726-4727-483b-ab62-c5d18441035e" CreationDate="2015-08-25T17:05:45.507" UserId="56" Comment="added 387 characters in body" Text="A NURBS differs from a Bezier curve in two ways...&#xD;&#xA;&#xD;&#xA;1) It's rational which means that it's one curve divided by another. (rational comes from &quot;ratio&quot;, not anything to do with it's temperament!)&#xD;&#xA;&#xD;&#xA;Being rational is not an issue though for being simple to evaluate.  There are even such things as rational Bezier curves, where again, you just divide one Bezier curve by another to get the final result.&#xD;&#xA;&#xD;&#xA;This allows you to make shapes with Bezier curves that you wouldn't be able to otherwise, for instance, rational Bezier curves can EXACTLY represent conic sections.&#xD;&#xA;&#xD;&#xA;Here's an HTML5 demo where you can play with a rational Bezier curve:&#xD;&#xA;http://demofox.org/bezquadrational.html&#xD;&#xA;&#xD;&#xA;Also, here is a shadertoy which uses a rational Bezier curve to calculate sin!&#xD;&#xA;https://www.shadertoy.com/view/XtfSRH&#xD;&#xA;&#xD;&#xA;2) The second difference is the one that makes it more difficult to evaluate, at least for me.  The second difference is that a NURBS, like a B-spline, can have any number of control points, but has a fixed degree.  How this works is that any given point on the curve is only influenced by a specific number of control points.&#xD;&#xA;&#xD;&#xA;You could have for example a quadratic curve with 8 control points,  where each point on the curve was only defined by 3 of the control points at a time.&#xD;&#xA;&#xD;&#xA;Where the influence of the control points begin and end is called the knot vector.&#xD;&#xA;&#xD;&#xA;So basically, if you can evaluate a rational curve, and you can evaluate a b-spline, you will then know how to evaluate a NURBS.&#xD;&#xA;&#xD;&#xA;Explaining how to evaluate a b-spline is too long for an answer I think, and there is lots of info on the web, and in text books, so i'll link to a couple things that might help you!&#xD;&#xA;&#xD;&#xA;Read up on De Boor's algorithm, its the b-spline equivalent of De Casteljeau's algorithm:&#xD;&#xA;https://en.m.wikipedia.org/wiki/De_Boor%27s_algorithm&#xD;&#xA;&#xD;&#xA;Here is a shadertoy rendering a b-spline in a pixel shader:&#xD;&#xA;https://www.shadertoy.com/view/MtfSRN&#xD;&#xA;&#xD;&#xA;Here is info on how to evaluate a b-spline:&#xD;&#xA;http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node18.html&#xD;&#xA;&#xD;&#xA;Also, here is some code (GLSL) that shows how to evaluate an 8 control point cubic B-spline:&#xD;&#xA;&#xD;&#xA;    float N_i_1 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        // return 1 if i &lt; t &lt; i+1, else return 0&#xD;&#xA;        return step(i, t) * step(t,i+1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_2 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_1(t, i)       * (t - i) +&#xD;&#xA;            N_i_1(t, i + 1.0) * (i + 2.0 - t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_3 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_2(t, i)       * (t - i) / 2.0 +&#xD;&#xA;            N_i_2(t, i + 1.0) * (i + 3.0 - t) / 2.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float N_i_4 (in float t, in float i)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            N_i_3(t, i)       * (t - i) / 3.0 +&#xD;&#xA;            N_i_3(t, i + 1.0) * (i + 4.0 - t) / 3.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float SplineValue(in float t)&#xD;&#xA;    {&#xD;&#xA;        return&#xD;&#xA;            P0 * N_i_4(t, 0.0) +&#xD;&#xA;            P1 * N_i_4(t, 1.0) +&#xD;&#xA;            P2 * N_i_4(t, 2.0) +&#xD;&#xA;            P3 * N_i_4(t, 3.0) +&#xD;&#xA;            P4 * N_i_4(t, 4.0) +&#xD;&#xA;            P5 * N_i_4(t, 5.0) +&#xD;&#xA;            P6 * N_i_4(t, 6.0) +&#xD;&#xA;            P7 * N_i_4(t, 7.0);   &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I guess your question boils down to:  Is there a way to do De Boor's algorithm as an equivalent equation, the same way Bernstein polynomials are an equation form of De Casteljeau's algorithm.&#xD;&#xA;&#xD;&#xA;I'm not sure, but since there are &quot;branches&quot; (see N_i_1 in the glsl code), it seems like it'd be difficult.  Maybe someone else will have a more direct answer to that part of it though." ContentLicense="CC BY-SA 3.0" />
  <row Id="995" PostHistoryTypeId="5" PostId="343" RevisionGUID="72f6c5bc-9d0f-4bee-a5d5-89bd36e44850" CreationDate="2015-08-25T17:25:07.233" UserId="38" Comment="added 258 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1002" PostHistoryTypeId="5" PostId="343" RevisionGUID="280781d6-1ef1-4736-a61c-f78365d4d4ed" CreationDate="2015-08-25T19:14:14.800" UserId="38" Comment="added 164 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1003" PostHistoryTypeId="5" PostId="343" RevisionGUID="090b9ea8-fcfc-4f3a-861b-eb160baeec5b" CreationDate="2015-08-25T19:28:45.267" UserId="38" Comment="added parametrisation" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1005" PostHistoryTypeId="2" PostId="346" RevisionGUID="71c6c524-a310-4f50-bd26-a0d72106b61f" CreationDate="2015-08-25T19:42:26.127" UserId="127" Text="As of now, when rendering my scene and while iterating through the scene graph, for each node its model matrix is calculated from the parent's model matrix and the scene node's pose. This is quite simple and already reduces the number of matrix multiplications to one multiplication per node and frame. &#xD;&#xA;&#xD;&#xA;But all these matrix multiplications have to be done on the CPU and in every frame to be able to perform (multiple consecutive) movements of scene nodes very fast. The GPU, however, is probably much better suited to perform lots of matrix multiplications, so I'm thinking about sending multiple partial model matrices to the vertex shader instead of computing everything on the CPU.&#xD;&#xA;&#xD;&#xA;Sending every single part (so the pose of every node) to the GPU probably does not make much sense, as in this case all the computations are done for every vertex instead of every node, which would actually decrease performance. But maybe scene nodes with lots of children or only non-moving children (relative to its parent) could be a place to split the model matrix and shift the multiplications to the shader.&#xD;&#xA;&#xD;&#xA;So, when is it better to send partial model matrices to the shader and move the multiplication to the GPU? Or is it simply a bad idea to to this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1006" PostHistoryTypeId="1" PostId="346" RevisionGUID="71c6c524-a310-4f50-bd26-a0d72106b61f" CreationDate="2015-08-25T19:42:26.127" UserId="127" Text="When is it be better to upload partial model matrices to the vertex shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1007" PostHistoryTypeId="3" PostId="346" RevisionGUID="71c6c524-a310-4f50-bd26-a0d72106b61f" CreationDate="2015-08-25T19:42:26.127" UserId="127" Text="|opengl|performance|transformations|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1008" PostHistoryTypeId="2" PostId="347" RevisionGUID="df463852-215b-45ec-a9e8-f88fb04eaa79" CreationDate="2015-08-25T21:30:55.597" UserId="48" Text="Fourier transforms wouldn't help you with a rotation. You'd just end up having to rotate the matrix of Fourier coefficients, instead of rotating the original image.&#xD;&#xA;&#xD;&#xA;Consider for example an image made of a perfect sine wave along the x-axis with wave-vector (_k_, 0).  (The wave-vector is the spacial frequencies along the x and y axes).  The Fourier transform of this would be all black, with a single white pixel at position (_k_, 0).&#xD;&#xA;&#xD;&#xA;When you rotate the image by an angle _θ_, you'll get a perfect sine wave along an oblique axis.  If you draw a diagram and do a little trigonometry, you can see that the new wave-vector will be (_k_ cos _θ_, _k_ sin _θ_).  (It helps for this part to know that the frequency _k_ is one over the period.)&#xD;&#xA;&#xD;&#xA;Therefore, the Fourier transform of the rotated result would be all black, with a single white pixel at position (_k_ cos _θ_, _k_ sin _θ_).  But that's just what you'd get if you rotated the Fourier transform of the original wave by _θ_.&#xD;&#xA;&#xD;&#xA;As for the Gibbs phenomenon, it's an issue when downsampling an image, or compressing it by frequency quantization (as in JPEG). But simply taking the Fourier transform of an image doesn't introduce any Gibbs ringing. The Fourier transform is lossless and perfectly reversible if done properly: it represents all the information in the original image." ContentLicense="CC BY-SA 3.0" />
  <row Id="1009" PostHistoryTypeId="5" PostId="344" RevisionGUID="67d52dc9-4617-4e75-89ae-56ebe8869db0" CreationDate="2015-08-25T22:00:23.613" UserId="141" Comment="added 3 characters in body" Text="Radiosity does not account for specular reflections (i.e. it only handles diffuse reflections). Whitted's ray-tracing only considers glossy or diffuse reflection, possibly mirror-reflected. And finally, Kajiya's path-tracing is the most general one [2], handling any number of diffuse, glossy and specular reflections.&#xD;&#xA;&#xD;&#xA;So I think it depends on what you means by &quot;ray-tracing&quot;: the technique developed by Whitted or any kind of &quot;tracing rays&quot;...&#xD;&#xA;&#xD;&#xA;Side-note: Heckbert [1] (or Shirley?) devised a classification of light scattering events which took place as the light traveled from the luminaire to the eye. In general it has the following form:&#xD;&#xA;&#xD;&#xA;    L(S|D)*E&#xD;&#xA;&#xD;&#xA;&quot;L&quot; stands for luminaire, &quot;D&quot; for diffuse reflection, &quot;S&quot; for specular reflection or refraction, &quot;E&quot; for eye, and the symbols &quot;*&quot;, &quot;|&quot;, &quot;()&quot;, &quot;[]&quot; come from regular expressions notation and denote &quot;zero or more&quot;, &quot;or&quot;, &quot;grouping&quot;, &quot;one of&quot;, respectively. Veach [3] extended the notation in his famous dissertation by &quot;D&quot; for Lambertian, &quot;S&quot; for specular and &quot;G&quot; for glossy reflection, and &quot;T&quot; for transmission.&#xD;&#xA;&#xD;&#xA;In particular, the following techniques are classified as:&#xD;&#xA;&#xD;&#xA;* OpenGL shading: `EDL`&#xD;&#xA;&#xD;&#xA;* Appel's ray-casting: `E(D|G)L`&#xD;&#xA;&#xD;&#xA;* Whitted's ray-tracing: `E[S*](D|G)L`&#xD;&#xA;&#xD;&#xA;* Kajiya's path-tracing: `E[(D|G|S)+(D|G)]L`&#xD;&#xA;&#xD;&#xA;* Golar's radiosity: `ED*L`&#xD;&#xA;&#xD;&#xA;[1] Paul S. Heckbert. Adaptive radiosity textures for bidirectional ray tracing. SIGGRAPH Computer Graphics, Volume 24, Number 4, August 1990&#xD;&#xA;&#xD;&#xA;[2] The Siggraph 2001 course &quot;State of the Art in Monte Carlo Ray Tracing for Realistic Image Synthesis&quot; says the following: &quot;Distributed ray tracing and path tracing&#xD;&#xA;includes multiple bounces involving non-specular scattering such as `E(D|G)*L`. However, even these methods ignore paths of the form `E(D|G)S*L`; that is, multiple specular bounces from the light source as in a caustic.&quot;&#xD;&#xA;&#xD;&#xA;[3] Eric Veach. Robust Monte Carlo Methods for Light Transport Simulation. Ph.D. dissertation, Stanford University, December 1997&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1010" PostHistoryTypeId="2" PostId="348" RevisionGUID="1a3953a9-b135-4a00-8296-79af973c9181" CreationDate="2015-08-25T22:04:13.903" UserId="48" Text="A 2D Fourier transform is performed by first doing a 1D Fourier transform on each row of the image, then taking the result and doing a 1D Fourier transform on each column.  Or vice versa; it doesn't matter.&#xD;&#xA;&#xD;&#xA;Just as a 1D Fourier transform allows you to decompose a function into a sum of (1D) sine waves at various frequencies, a 2D Fourier transform decomposes a function as a sum of 2D sine waves.  These waves can have different frequencies along the x and y axes.  They generically have the form:&#xD;&#xA;&#xD;&#xA;&gt; exp(_i_ &amp;middot; (_k&lt;sub&gt;x&lt;/sub&gt;x_ + _k&lt;sub&gt;y&lt;/sub&gt;y_))&#xD;&#xA;&#xD;&#xA;where _k&lt;sub&gt;x&lt;/sub&gt;_ and _k&lt;sub&gt;y&lt;/sub&gt;_ are the frequencies along the x and y axes. These two values form a vector called the wave-vector.  In the spatial domain, the wave is oriented along the (_k&lt;sub&gt;x&lt;/sub&gt;_, _k&lt;sub&gt;y&lt;/sub&gt;_) vector with a frequency along its axis of √(_k&lt;sub&gt;x&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt;_ + _k&lt;sub&gt;y&lt;/sub&gt;&lt;sup&gt;2&lt;/sup&gt;_).&#xD;&#xA;&#xD;&#xA;Just as for the 1D Fourier transform, there exist both discrete and continuous versions.  The result of a discrete 2D Fourier transform is a matrix of complex amplitudes for a set of discrete (_k&lt;sub&gt;x&lt;/sub&gt;_, _k&lt;sub&gt;y&lt;/sub&gt;_) values.  This is commonly visualized (like in the paper you linked to) as an image where the pixel at coordinates (_k&lt;sub&gt;x&lt;/sub&gt;_, _k&lt;sub&gt;y&lt;/sub&gt;_) represents the amplitude of that wave-vector.&#xD;&#xA;&#xD;&#xA;So, an annular shape in a 2D Fourier transform indicates rotational invariance of the distribution of frequencies (i.e. just as much amplitude for waves in every direction), with a narrow range of magnitudes (from the inside of the annulus to the outside).  In other words, the paper is using the Fourier transform to demonstrate that their noise is reasonably isotropic and band-limited." ContentLicense="CC BY-SA 3.0" />
  <row Id="1011" PostHistoryTypeId="2" PostId="349" RevisionGUID="e9508383-6e57-4f6f-b071-4eec2228a763" CreationDate="2015-08-26T05:11:33.353" UserId="196" Text="Doing math with uniforms is a shader won't usually get you any performance over doing it on the CPU. A CPU isn't slower than a GPU at doing matrix math, it just isn't structured so as to do large amounts of math in parallel. But you have to actually do that large amount of math to get a win. Sending extra data to the GPU just to have the GPU multiply two matrices together will rarely net you anything.&#xD;&#xA;&#xD;&#xA;Now, say you have a buffer of skinning matrices. It *might* start to matter whether you transform them all into world space on the CPU or just pass an extra model-to-world-space matrix to the GPU. But even then it depends on your ratio of vertices to bones." ContentLicense="CC BY-SA 3.0" />
  <row Id="1012" PostHistoryTypeId="5" PostId="343" RevisionGUID="3e4dc39d-1d4d-4657-aa71-14684a47681f" CreationDate="2015-08-26T10:04:32.540" UserId="38" Comment="added 230 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/1LT63.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1013" PostHistoryTypeId="5" PostId="343" RevisionGUID="feaf150c-ccc9-4b8e-9000-d1f082cee2c8" CreationDate="2015-08-26T10:18:56.777" UserId="38" Comment="added 233 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;There is some implementation specific variation how the knot vector should be made. For example: Makers of the rhino modelling engine have for example a shorter description field with one less knot in their sequence at both ends.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/1LT63.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1014" PostHistoryTypeId="5" PostId="343" RevisionGUID="fa73f6d9-3590-46ed-a37e-999880dd5b41" CreationDate="2015-08-26T10:25:00.440" UserId="38" Comment="added 233 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;There is some implementation specific variation how the knot vector should be made. For example: Makers of the rhino modelling engine have for example a shorter description field with one less knot in their sequence at both ends.&#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/1LT63.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1015" PostHistoryTypeId="5" PostId="343" RevisionGUID="db99211f-b50b-42d3-adc5-9406d2b7e777" CreationDate="2015-08-26T10:36:09.800" UserId="38" Comment="edited body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;There is some implementation specific variation how the knot vector should be made. For example: Makers of the rhino modelling engine have for example a shorter description field with one less knot in their sequence at both ends.&#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/GqwK2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1016" PostHistoryTypeId="10" PostId="225" RevisionGUID="585a434e-3bff-4c3f-99e0-1df53cb6df76" CreationDate="2015-08-26T10:41:38.667" UserId="-1" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:127,&quot;DisplayName&quot;:&quot;Nero&quot;},{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:137,&quot;DisplayName&quot;:&quot;ratchet freak&quot;}]}" />
  <row Id="1017" PostHistoryTypeId="5" PostId="343" RevisionGUID="9b2f60ef-cdd5-447c-9e02-2dbf302e092b" CreationDate="2015-08-26T11:40:08.273" UserId="38" Comment="deleted 133 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the preregistration ranges of the basis functions.&#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1018" PostHistoryTypeId="5" PostId="343" RevisionGUID="cedbe87b-9630-4c80-87c0-bf5f183ef3aa" CreationDate="2015-08-26T12:01:33.567" UserId="38" Comment="added 353 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic bezier spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1019" PostHistoryTypeId="5" PostId="343" RevisionGUID="d32e9e51-1c1b-408c-a8f1-cae18545cbf9" CreationDate="2015-08-26T14:15:21.387" UserId="38" Comment="added 31 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines (or the rational part in fact) are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic bezier spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This rational in this case means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. It also means that there might not be a closed form solution for the length of a NURBS curve.&#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1020" PostHistoryTypeId="5" PostId="343" RevisionGUID="cf29dd3e-4c95-44bf-9ba6-f8ecf45f13ff" CreationDate="2015-08-26T14:17:40.810" UserId="38" Comment="deleted 93 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines (or the rational part in fact) are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the UV range. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic bezier spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This rational in this case means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. &#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1021" PostHistoryTypeId="5" PostId="287" RevisionGUID="b0a99bea-166a-4404-9058-3c55e2089b7b" CreationDate="2015-08-26T15:25:57.493" UserId="231" Comment="Add requested link to &quot;another question&quot;" Text="I understand how a 1D Fourier transform separates a signal into its component frequencies, but I'm having difficulty understanding how a 2D Fourier transform affects a 2D image.&#xD;&#xA;&#xD;&#xA;From [another question], [John Calsbeek] linked to an [interesting paper about measuring the quality of noise functions]. This showed various noise functions and the Fourier transform of each.&#xD;&#xA;&#xD;&#xA;Is this a discrete transform of the pixel data, or a continuous transform of the continuous interpolating function which is used to generate the noise at arbitrary points?&#xD;&#xA;&#xD;&#xA;Is the annular shape analagous to taking 1D Fourier transforms of the line through the centre of the image at every possible angle? Or is the transform for each possible angle also measured across the whole 2D space rather than only along a line through the centre? I'm trying to get an intuitive feel for what changes in the input image correspond to what changes in the Fourier transform.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [another question]: http://computergraphics.stackexchange.com/questions/283/is-all-grid-based-noise-inevitably-anisotropic &quot;Is all grid based noise inevitably anisotropic?&quot;&#xD;&#xA;&#xD;&#xA;  [John Calsbeek]: http://computergraphics.stackexchange.com/users/196/john-calsbeek&#xD;&#xA;&#xD;&#xA;  [interesting paper about measuring the quality of noise functions]: http://www.cs.utah.edu/~aek/research/noise.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="1022" PostHistoryTypeId="2" PostId="350" RevisionGUID="b7bd1d12-a4f3-4d73-9b07-43fb3cb1b373" CreationDate="2015-08-26T20:05:29.413" UserId="423" Text="Every time I think I understand the relationship between the two terms, I get more information that confuses me. I thought they were synonymous, but now I'm not sure.&#xD;&#xA;&#xD;&#xA;What is the difference between &quot;diffuse&quot; and &quot;albedo&quot;? Are they interchangeable terms or are they used to mean different things in practice?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1023" PostHistoryTypeId="1" PostId="350" RevisionGUID="b7bd1d12-a4f3-4d73-9b07-43fb3cb1b373" CreationDate="2015-08-26T20:05:29.413" UserId="423" Text="Albedo vs Diffuse" ContentLicense="CC BY-SA 3.0" />
  <row Id="1024" PostHistoryTypeId="3" PostId="350" RevisionGUID="b7bd1d12-a4f3-4d73-9b07-43fb3cb1b373" CreationDate="2015-08-26T20:05:29.413" UserId="423" Text="|rendering|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1025" PostHistoryTypeId="2" PostId="351" RevisionGUID="f7cae0e3-bc3b-4bc8-9e0a-8858e9f7edd7" CreationDate="2015-08-26T20:57:03.073" UserId="231" Text="The short answer: They are not interchangeable, but their meaning can sometimes appear to overlap in computer graphics literature, giving the potential for confusion.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;***Albedo*** is the proportion of incident light that is reflected away from a surface.&#xD;&#xA;&#xD;&#xA;***Diffuse reflection*** is the reflection of light in many directions, rather than in just one direction like a mirror ([specular reflection]).&#xD;&#xA;&#xD;&#xA;In the case of ideal diffuse reflection ([Lambertian reflectance]), incident light is reflected in all directions independently of the angle at which it arrived. Since in computer graphics rendering literature there is sometimes a &quot;diffuse coefficient&quot; when calculating the colour of a pixel, which indicates the proportion of light reflected diffusely, there is an opportunity for confusion with the term *albedo*, which also means the proportion of light reflected.&#xD;&#xA;&#xD;&#xA;If you are rendering a material which only has ideal diffuse reflectance, then the albedo will be equal to the diffuse coefficient. However, in general a surface may reflect some light diffusely and other light specularly or in other direction-dependent ways, so that the diffuse coefficient is only a fraction of the albedo.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that albedo is a term from observation of planets, moons and other large scale bodies, and is an average over the surface, and often an average over time. The albedo is thus not a useful value in itself for rendering a surface, where you need the specific, current surface property at any given location on the surface.&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;&#xD;&#xA;  [specular reflection]: https://en.wikipedia.org/wiki/Specular_reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="1026" PostHistoryTypeId="5" PostId="351" RevisionGUID="0233c707-006c-4335-8085-be0e1dd59f90" CreationDate="2015-08-26T21:03:51.870" UserId="231" Comment="Add link to Albedo on Wikipedia" Text="The short answer: They are not interchangeable, but their meaning can sometimes appear to overlap in computer graphics literature, giving the potential for confusion.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;***Albedo*** is the proportion of incident light that is reflected away from a surface.&#xD;&#xA;&#xD;&#xA;***Diffuse reflection*** is the reflection of light in many directions, rather than in just one direction like a mirror ([specular reflection]).&#xD;&#xA;&#xD;&#xA;In the case of ideal diffuse reflection ([Lambertian reflectance]), incident light is reflected in all directions independently of the angle at which it arrived. Since in computer graphics rendering literature there is sometimes a &quot;diffuse coefficient&quot; when calculating the colour of a pixel, which indicates the proportion of light reflected diffusely, there is an opportunity for confusion with the term *albedo*, which also means the proportion of light reflected.&#xD;&#xA;&#xD;&#xA;If you are rendering a material which only has ideal diffuse reflectance, then the albedo will be equal to the diffuse coefficient. However, in general a surface may reflect some light diffusely and other light specularly or in other direction-dependent ways, so that the diffuse coefficient is only a fraction of the albedo.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that [albedo] is a term from observation of planets, moons and other large scale bodies, and is an average over the surface, and often an average over time. The albedo is thus not a useful value in itself for rendering a surface, where you need the specific, current surface property at any given location on the surface. Also note that in astronomy the term albedo can refer to different parts of the spectrum in different contexts - it will not always be refering to human visible light.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [albedo]: https://en.wikipedia.org/wiki/Albedo&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;&#xD;&#xA;  [specular reflection]: https://en.wikipedia.org/wiki/Specular_reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="1027" PostHistoryTypeId="5" PostId="351" RevisionGUID="ac8acc74-5437-4d1c-8c46-92ecf56ef9d0" CreationDate="2015-08-26T21:11:42.617" UserId="231" Comment="Add link to Albedo on Wikipedia" Text="The short answer: They are not interchangeable, but their meaning can sometimes appear to overlap in computer graphics literature, giving the potential for confusion.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;***Albedo*** is the proportion of incident light that is reflected away from a surface.&#xD;&#xA;&#xD;&#xA;***Diffuse reflection*** is the reflection of light in many directions, rather than in just one direction like a mirror ([specular reflection]).&#xD;&#xA;&#xD;&#xA;In the case of ideal diffuse reflection ([Lambertian reflectance]), incident light is reflected in all directions independently of the angle at which it arrived. Since in computer graphics rendering literature there is sometimes a &quot;diffuse coefficient&quot; when calculating the colour of a pixel, which indicates the proportion of light reflected diffusely, there is an opportunity for confusion with the term *albedo*, which also means the proportion of light reflected.&#xD;&#xA;&#xD;&#xA;If you are rendering a material which only has ideal diffuse reflectance, then the albedo will be equal to the diffuse coefficient. However, in general a surface may reflect some light diffusely and other light specularly or in other direction-dependent ways, so that the diffuse coefficient is only a fraction of the albedo.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that [albedo] is a term from observation of planets, moons and other large scale bodies, and is an average over the surface, and often an average over time. The albedo is thus not a useful value in itself for rendering a surface, where you need the specific, current surface property at any given location on the surface. Also note that in astronomy the term albedo can refer to different parts of the spectrum in different contexts - it will not always be refering to human visible light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Another difference, as Nathan Reed points out in a comment, is that albedo is a single average value, which gives you no colour information. For basic rendering the diffuse coefficient gives proportions for red, green and blue components separately, so albedo would only allow you to render greyscale images. For more realistic images, spectral rendering requires the reflectance of a surface as a function of the whole visible spectrum - far more than a single average value.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [albedo]: https://en.wikipedia.org/wiki/Albedo&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;&#xD;&#xA;  [specular reflection]: https://en.wikipedia.org/wiki/Specular_reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="1028" PostHistoryTypeId="2" PostId="352" RevisionGUID="29403230-7f1d-4ae1-bd40-bfdbebc04873" CreationDate="2015-08-26T21:57:14.240" UserId="159" Text="The way that NURBS curves are typically split at an arbitrary point is by [knot insertion][1]. You insert knots at the split point until it is at maximum multiplicity, at which point you can just read off the two split curves.&#xD;&#xA;&#xD;&#xA;However, you may not want to split at an arbitrary point. If the ultimate goal is to draw the curves or something like that, then it's worth splitting the curve at the existing knot points (that is, performing knot insertion until all knots are at maximum multiplicity) rather than inserting new ones.&#xD;&#xA;&#xD;&#xA;This process splits the NURBS into *uniform* rational B-splines. Once you have that, you can use [de Boor's algorithm][2] to split further.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS-knot-insert.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/De_Boor%27s_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="1029" PostHistoryTypeId="2" PostId="353" RevisionGUID="13234744-a654-429b-a633-d1d7339fa6d0" CreationDate="2015-08-26T22:00:26.977" UserId="207" Text="[Nearest-depth filtering][1] is an alternative to bilaterial filtering that was specifically developed for upsampling low-resolution transparent rendering. It's a bit simpler than bilateral sampling, in that it only requires one sample from your low-resolution texture. However it can still have issues, particularly with high-frequency geometry that isn't well-represented in your low-resolution depth buffer.&#xD;&#xA;&#xD;&#xA;At SIGGRAPH 2013, Bungie presented a new approach for handling very-low-resolution particles using what they called a &quot;variance depth map&quot;. You can find the slides [here][2] in PDF and PPTX format. &#xD;&#xA;&#xD;&#xA;One interesting approach that hasn't been used yet (at least, to my knowledge) would be to leverage MSAA. The idea is that you take your full-resolution depth buffer, and then alias it (or convert it, if the API doesn't allow you to do so) as a 4xMSAA depth buffer with half the width and height. You could then render your low-resolution transparents to a half-resolution render target with 4xMSAA, using your &quot;4xMSAA&quot; depth buffer for depth testing. Then to upscale, for each high-resolution pixel you would access the corresponding subsample from your low-resolution MSAA render target, and blend it on top. This would give you full-resolution depth testing, but half-resolution shading (with framebuffer bandwidth somewhere in between full-res and half-res due to compression). The catch here is that you need programmable MSAA sample points to do this, since you'll want to use an ordered grid sampling pattern for your low-resolution rendering instead of the typical rotated grid pattern. Newer GPU's (Maxwell from Nvidia, GCN from AMD) support doing this through vendor extensions in [D3D11][3] and [OpenGL][4], and it can be done natively on consoles.&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/OpacityMappingSDKWhitePaper.pdf&#xD;&#xA;  [2]: http://advances.realtimerendering.com/s2013/index.html&#xD;&#xA;  [3]: https://developer.nvidia.com/nvapi&#xD;&#xA;  [4]: https://developer.nvidia.com/sites/default/files/akamai/opengl/specs/GL_NV_sample_locations.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="1030" PostHistoryTypeId="2" PostId="354" RevisionGUID="b24270ca-12f2-4f3f-a74b-5487190f7722" CreationDate="2015-08-26T22:13:24.200" UserId="250" Text="I'd like to know a few things about texture cache in modern GPUs.&#xD;&#xA;&#xD;&#xA;1) I know GPU prefetches textures and that's why dependent texture reads are slower, but how does it work and at what point that happens?&#xD;&#xA;&#xD;&#xA;2) How does it work with multiple cache levels (L1, L2, etc).  &#xD;&#xA;&#xD;&#xA;3) How does the GPU manages cache in the context of multiple parallel shader units?&#xD;&#xA;&#xD;&#xA;4) How does cache work with tile based rendering? Are there any tips on how to improve cache hit ratio for it? (for instance, if tiles are processed horizontally and I have vertical segments of triangles with the same texture, does it work worse for cache than if I had triangles layout out horizontally?)&#xD;&#xA;&#xD;&#xA;5) If I have many textures (say 5+ maps) in the same texture unit, does it work worse for cache than if I had only 2 or 3 textures?&#xD;&#xA;&#xD;&#xA;6) Are there any other useful tips besides compression and mipmaping to improve texture bandwidth?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1031" PostHistoryTypeId="1" PostId="354" RevisionGUID="b24270ca-12f2-4f3f-a74b-5487190f7722" CreationDate="2015-08-26T22:13:24.200" UserId="250" Text="How Texture Cache works on Modern GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="1032" PostHistoryTypeId="3" PostId="354" RevisionGUID="b24270ca-12f2-4f3f-a74b-5487190f7722" CreationDate="2015-08-26T22:13:24.200" UserId="250" Text="|opengl|texture|gpu|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1033" PostHistoryTypeId="5" PostId="351" RevisionGUID="102ac5b9-e1cc-4a78-9af0-3ac139685e1f" CreationDate="2015-08-26T22:28:28.447" UserId="231" Comment="Add link to profile for credit" Text="The short answer: They are not interchangeable, but their meaning can sometimes appear to overlap in computer graphics literature, giving the potential for confusion.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;***Albedo*** is the proportion of incident light that is reflected away from a surface.&#xD;&#xA;&#xD;&#xA;***Diffuse reflection*** is the reflection of light in many directions, rather than in just one direction like a mirror ([specular reflection]).&#xD;&#xA;&#xD;&#xA;In the case of ideal diffuse reflection ([Lambertian reflectance]), incident light is reflected in all directions independently of the angle at which it arrived. Since in computer graphics rendering literature there is sometimes a &quot;diffuse coefficient&quot; when calculating the colour of a pixel, which indicates the proportion of light reflected diffusely, there is an opportunity for confusion with the term *albedo*, which also means the proportion of light reflected.&#xD;&#xA;&#xD;&#xA;If you are rendering a material which only has ideal diffuse reflectance, then the albedo will be equal to the diffuse coefficient. However, in general a surface may reflect some light diffusely and other light specularly or in other direction-dependent ways, so that the diffuse coefficient is only a fraction of the albedo.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that [albedo] is a term from observation of planets, moons and other large scale bodies, and is an average over the surface, and often an average over time. The albedo is thus not a useful value in itself for rendering a surface, where you need the specific, current surface property at any given location on the surface. Also note that in astronomy the term albedo can refer to different parts of the spectrum in different contexts - it will not always be refering to human visible light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Another difference, as [Nathan Reed] points out in a comment, is that albedo is a single average value, which gives you no colour information. For basic rendering the diffuse coefficient gives proportions for red, green and blue components separately, so albedo would only allow you to render greyscale images. For more realistic images, spectral rendering requires the reflectance of a surface as a function of the whole visible spectrum - far more than a single average value.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Nathan Reed]: http://computergraphics.stackexchange.com/users/48/nathan-reed&#xD;&#xA;&#xD;&#xA;  [albedo]: https://en.wikipedia.org/wiki/Albedo&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;&#xD;&#xA;  [specular reflection]: https://en.wikipedia.org/wiki/Specular_reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="1034" PostHistoryTypeId="5" PostId="354" RevisionGUID="95ec04eb-f67d-4183-8fda-3d57b5102221" CreationDate="2015-08-26T22:41:04.180" UserId="250" Comment="deleted 768 characters in body; edited title" Text="I know GPU prefetches textures and that's why dependent texture reads are slower, but how does it work and at what point that happens?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Split the content of this question into others as suggested by trichoplax&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1035" PostHistoryTypeId="4" PostId="354" RevisionGUID="95ec04eb-f67d-4183-8fda-3d57b5102221" CreationDate="2015-08-26T22:41:04.180" UserId="250" Comment="deleted 768 characters in body; edited title" Text="How Texture Prefetch works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1036" PostHistoryTypeId="2" PostId="355" RevisionGUID="5b26d728-3dc4-489d-92c3-b2f9ae119d2c" CreationDate="2015-08-26T22:43:22.360" UserId="250" Text="Modern GPUs have many parallel shading units. I'd like to know how texture cache is managed in that scenario. " ContentLicense="CC BY-SA 3.0" />
  <row Id="1037" PostHistoryTypeId="1" PostId="355" RevisionGUID="5b26d728-3dc4-489d-92c3-b2f9ae119d2c" CreationDate="2015-08-26T22:43:22.360" UserId="250" Text="How does Texture Cache work considering multiple shader units" ContentLicense="CC BY-SA 3.0" />
  <row Id="1038" PostHistoryTypeId="3" PostId="355" RevisionGUID="5b26d728-3dc4-489d-92c3-b2f9ae119d2c" CreationDate="2015-08-26T22:43:22.360" UserId="250" Text="|texture|gpu|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1039" PostHistoryTypeId="2" PostId="356" RevisionGUID="d1ef3668-3de5-4b6a-acff-5cc14a70aaed" CreationDate="2015-08-26T22:44:44.380" UserId="250" Text="How does cache work with tile based rendering? &#xD;&#xA;&#xD;&#xA;Are there any tips on how to improve cache hit ratio for it? (for instance, if tiles are processed horizontally and I have vertical segments of triangles with the same texture, does it work worse for cache than if I had triangles layout out horizontally?)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1040" PostHistoryTypeId="1" PostId="356" RevisionGUID="d1ef3668-3de5-4b6a-acff-5cc14a70aaed" CreationDate="2015-08-26T22:44:44.380" UserId="250" Text="How does Texture Cache work in Tile Based Rendering GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="1041" PostHistoryTypeId="3" PostId="356" RevisionGUID="d1ef3668-3de5-4b6a-acff-5cc14a70aaed" CreationDate="2015-08-26T22:44:44.380" UserId="250" Text="|texture|gpu|shader|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1042" PostHistoryTypeId="2" PostId="357" RevisionGUID="20b6d591-80ac-4bd4-b45b-b4d8e8e4968f" CreationDate="2015-08-26T22:47:25.997" UserId="250" Text="If I have many textures (say 5+ maps) bound to the same texture unit, does it work worse for cache than if I had only 2 or 3 textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1043" PostHistoryTypeId="1" PostId="357" RevisionGUID="20b6d591-80ac-4bd4-b45b-b4d8e8e4968f" CreationDate="2015-08-26T22:47:25.997" UserId="250" Text="Is using many texture maps bad for caching?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1044" PostHistoryTypeId="3" PostId="357" RevisionGUID="20b6d591-80ac-4bd4-b45b-b4d8e8e4968f" CreationDate="2015-08-26T22:47:25.997" UserId="250" Text="|texture|shader|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1045" PostHistoryTypeId="5" PostId="354" RevisionGUID="f0b7ae9c-c426-4b1f-97b2-655e40abb0d2" CreationDate="2015-08-26T22:53:30.343" UserId="250" Comment="added 428 characters in body" Text="I know GPU prefetches textures and that's why dependent texture reads are slower, but how does it work and at what point that happens?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;___________________________________________________&#xD;&#xA;EDIT: Split the content of this question into others as suggested by trichoplax&#xD;&#xA;Here's a link to other questions:&#xD;&#xA;&#xD;&#xA;http://computergraphics.stackexchange.com/questions/355/how-does-texture-cache-work-considering-multiple-shader-units&#xD;&#xA;&#xD;&#xA;http://computergraphics.stackexchange.com/questions/356/how-does-texture-cache-work-in-tile-based-rendering-gpu&#xD;&#xA;&#xD;&#xA;http://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1046" PostHistoryTypeId="5" PostId="352" RevisionGUID="71659b25-aeac-4dcd-a63f-53bf46654c92" CreationDate="2015-08-27T01:43:13.840" UserId="159" Comment="added 1819 characters in body" Text="The way that NURBS curves are typically split at an arbitrary point is by [knot insertion][1]. You insert knots at the split point until it is at maximum multiplicity, at which point you can just read off the two split curves.&#xD;&#xA;&#xD;&#xA;However, you may not want to split at an arbitrary point. If the ultimate goal is to draw the curves or something like that, then it's worth splitting the curve at the existing knot points (that is, performing knot insertion until all knots are at maximum multiplicity) rather than inserting new ones.&#xD;&#xA;&#xD;&#xA;This process splits the NURBS into *uniform* rational B-splines. Once you have that, you can use [de Boor's algorithm][2] to split further.&#xD;&#xA;&#xD;&#xA;The number of knots in the knot vector is:&#xD;&#xA;&#xD;&#xA;    numKnots = degreeOfCurve + numControlPoints - 1&#xD;&#xA;&#xD;&#xA;Inserting a knot thus increases the number of control points by one.&#xD;&#xA;&#xD;&#xA;As you travel along a NURBS curve, each knot represents a place where one control point &quot;drops out&quot; and another one &quot;enters&quot;. If a knot value is repeated, this means that more than one control point is replaced at this place.&#xD;&#xA;&#xD;&#xA;For a curve of degree greater than 1, the and last knots are repeated multiple times for one simple reason: you need to bring in more than one point to start and you need to eject more than one point to end.&#xD;&#xA;&#xD;&#xA;Let's think about cubic curves for the moment, just to keep things simple.&#xD;&#xA;&#xD;&#xA;A curve with the knot vector [0,0,1,1] is a uniform B-spline curve. &#xD;&#xA;&#xD;&#xA;A curve with the knot vector [0,0,1,1,2,2] is non-uniform, but can be thought of as two uniform B-spline curves which connect at t=1, one corresponding to [0,0,1,1] and one corresponding to [1,1,2,2]. You can do this because the multiplicity of the knots is enough to &quot;start&quot; and &quot;end&quot; a cubic curve.&#xD;&#xA;&#xD;&#xA;If you're faced with a curve with a knot vector like [0,0,1,2,2], you can insert a knot at 1 without changing the shape of the curve (this is the knot insertion procedure). This increases the number of control points by one; the knot insertion procedure adjusts the points around the new knot to accommodate it. But once you've done that, you have two uniform B-spline curves.&#xD;&#xA;&#xD;&#xA;Knot insertion won't create overlapping control points unless you insert too many knots at the same place, and by &quot;too many&quot;, I mean the degree of the curve. So for a non-uniform cubic curve, you'd insert knots so that every knot had multiplicity 2. That gives you a number of abutting uniform cubic curves, which you can then use de Boor's algorithm to split further.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS-knot-insert.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/De_Boor%27s_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="1047" PostHistoryTypeId="5" PostId="343" RevisionGUID="90970989-a928-4b18-8cd0-ea3a5a653e6d" CreationDate="2015-08-27T04:26:15.960" UserId="38" Comment="added 3 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines (or the rational part in fact) are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying surface has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves uv range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the U parameter. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic b-spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This rational in this case means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. &#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1048" PostHistoryTypeId="5" PostId="343" RevisionGUID="63fca878-726c-437f-9d8a-bd6f5713957c" CreationDate="2015-08-27T04:31:56.460" UserId="38" Comment="added 3 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines (or the rational part in fact) are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying curve has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary value that is bigger than the next. So you can parametrize the entire curves u range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the U parameter. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic b-spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This rational in this case means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. &#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1049" PostHistoryTypeId="5" PostId="343" RevisionGUID="736b4a80-dbe3-4cde-a26a-02ed652f5a71" CreationDate="2015-08-27T04:39:05.643" UserId="38" Comment="added 3 characters in body" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines (or the rational part in fact) are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying curve has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary increasing value in the sequence. So you can parametrize the entire curves u range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This paremetrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the U parameter. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic b-spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This rational in this case means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. &#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1050" PostHistoryTypeId="4" PostId="346" RevisionGUID="7352ae2d-8b8d-4b45-a92a-9b6199afb914" CreationDate="2015-08-27T09:10:02.950" UserId="127" Comment="edited title" Text="When is it better to upload partial model matrices to the vertex shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1051" PostHistoryTypeId="2" PostId="358" RevisionGUID="dee8623c-4e4b-4bed-92df-c3924546a06b" CreationDate="2015-08-27T11:20:20.270" UserId="141" Text="In [Splitting of NURBS curves](http://computergraphics.stackexchange.com/questions/340/splitting-of-nurbs-curves) there the answer relied on &quot;maximum knot multiplicity&quot;. In order not to mix-up different topics I would like to kindly ask to answer it in another question: what is this &quot;knot multiplicity&quot; all about?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1052" PostHistoryTypeId="1" PostId="358" RevisionGUID="dee8623c-4e4b-4bed-92df-c3924546a06b" CreationDate="2015-08-27T11:20:20.270" UserId="141" Text="NURBS knot multiplicity" ContentLicense="CC BY-SA 3.0" />
  <row Id="1053" PostHistoryTypeId="3" PostId="358" RevisionGUID="dee8623c-4e4b-4bed-92df-c3924546a06b" CreationDate="2015-08-27T11:20:20.270" UserId="141" Text="|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1054" PostHistoryTypeId="2" PostId="359" RevisionGUID="f87e13bb-0c2c-4b63-b0d1-9b5978c7f51f" CreationDate="2015-08-27T11:33:54.510" UserId="231" Text="I'm interested to know whether the demoscene has historically introduced new techniques that would have otherwise taken longer to discover, contributing to the progress of computer graphics. Has it become more or less relevant over the years?&#xD;&#xA;&#xD;&#xA;I know that some of the early demos took advantage of known hardware errors and went beyond what was considered possible at the time, but what I'm interested in is whether any of the new techniques introduced were then taken up by researchers or professional programmers to become part of the mainstream accepted way of doing things." ContentLicense="CC BY-SA 3.0" />
  <row Id="1055" PostHistoryTypeId="1" PostId="359" RevisionGUID="f87e13bb-0c2c-4b63-b0d1-9b5978c7f51f" CreationDate="2015-08-27T11:33:54.510" UserId="231" Text="Is the demoscene a source of advancements in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1056" PostHistoryTypeId="3" PostId="359" RevisionGUID="f87e13bb-0c2c-4b63-b0d1-9b5978c7f51f" CreationDate="2015-08-27T11:33:54.510" UserId="231" Text="|demoscene|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1057" PostHistoryTypeId="2" PostId="360" RevisionGUID="55aa6f16-d498-4afa-a67a-73f176b68756" CreationDate="2015-08-27T11:55:04.603" UserId="38" Text="When you have a curve you can adjust the knots so that they lie on top of each other. This is essentially a bit like having several control points on top of each other, except there's only one point. &#xD;&#xA;&#xD;&#xA;When you have as many knots on top of each other as you have degrees in the curve smoothness, you end up with a cusp, also known as as sharp corner. Once you have a sharp corner you can just go and delete the points on the opposite side as they no longer affect points no the other side of the corner. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Curve and control cage (Top) and basis functions (bottom). In this case the curve acts as 2 adjoining bezier curves, The image is using the knot vector [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2].&#xD;&#xA;&#xD;&#xA;Alternatively to changing parametrization you can just add points on top of each other. This is equivalent although slight misuse of resources, but useful in surface modeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6DWhc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1058" PostHistoryTypeId="5" PostId="360" RevisionGUID="3a9f70d1-0ee8-44c3-8a71-86d8ed2df43d" CreationDate="2015-08-27T12:02:58.980" UserId="38" Comment="added 330 characters in body" Text="When you have a curve you can adjust the knots so that they lie on top of each other. This is essentially a bit like having several control points on top of each other, except there's only one point. &#xD;&#xA;&#xD;&#xA;When you have as many knots on top of each other as you have degrees in the curve smoothness, you end up with a cusp, also known as as sharp corner. Once you have a sharp corner you can just go and delete the points on the opposite side as they no longer affect points no the other side of the corner. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Curve and control cage (Top) and basis functions (bottom). In this case the curve acts as 2 adjoining bezier curves, The image is using the knot vector [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2].&#xD;&#xA;&#xD;&#xA;If we look at a knot vector then the multiplicity looks like a seqence of n knots that have the same number. Note if you do not add ecactly as many knots on top as there is smoothness then you get a partially sharp corner.&#xD;&#xA;&#xD;&#xA;Alternatively to changing parametrization you can just add points on top of each other. This is equivalent although slight misuse of resources, but useful in surface modeling. Having many control points on top could also be useful for the uniform nature of the knot distribution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6DWhc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1059" PostHistoryTypeId="2" PostId="361" RevisionGUID="3e35aa47-12a9-4610-91ec-eb500c86718a" CreationDate="2015-08-27T12:43:44.723" UserId="231" Text="In reading about [Lambertian reflectance] I found the following phrase (in bold) which doesn't sound right to me:&#xD;&#xA;&#xD;&#xA;&gt; In computer graphics, Lambertian reflection is often used as a model for diffuse reflection. This technique causes all closed polygons (such as a triangle within a 3D mesh) to reflect light equally in all directions when rendered. In effect, a point rotated around its normal vector will not change the way it reflects light. However, the point will change the way it reflects light if it is tilted away from its initial normal vector **since the area is illuminated by a smaller fraction of the incident radiation.**&#xD;&#xA;&#xD;&#xA;The way I picture the situation described in the paragraph, only tilting away from the light source would cause  less light to be incident in a given area. In general, tilting away from the initial normal vector could lead to either an increase ***or*** a decrease in incident light per area, as this says nothing about the location of the light source.&#xD;&#xA;&#xD;&#xA;Have I misunderstood the context, or is this something that should be rewritten on Wikipedia?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance#Use_in_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="1060" PostHistoryTypeId="1" PostId="361" RevisionGUID="3e35aa47-12a9-4610-91ec-eb500c86718a" CreationDate="2015-08-27T12:43:44.723" UserId="231" Text="Is this a mistake in the Wikipedia article for Lambertian Reflectance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1061" PostHistoryTypeId="3" PostId="361" RevisionGUID="3e35aa47-12a9-4610-91ec-eb500c86718a" CreationDate="2015-08-27T12:43:44.723" UserId="231" Text="|shading|second-opinion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1062" PostHistoryTypeId="5" PostId="360" RevisionGUID="c5514a01-3381-4e2e-a8d4-4342c4d52539" CreationDate="2015-08-27T12:48:08.570" UserId="38" Comment="added 195 characters in body" Text="When you have a curve you can adjust the knots so that they lie on top of each other. This is essentially a bit like having several control points on top of each other, except there's only one point. &#xD;&#xA;&#xD;&#xA;When you have as many knots on top of each other as you have degrees in the curve smoothness, you end up with a cusp, also known as as sharp corner. Once you have a sharp corner you can just go and delete the points on the opposite side as they no longer affect points no the other side of the corner. &#xD;&#xA;&#xD;&#xA;![Curve with cusp][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Curve and control cage (Top) and basis functions (bottom). In this case the curve acts as 2 adjoining bezier curves, The image is using the knot vector [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2].&#xD;&#xA;&#xD;&#xA;If we look at a knot vector then the multiplicity looks like a seqence of n knots that have the same number. Note if you do not add ecactly as many knots on top as there is smoothness then you get a partially sharp corner.&#xD;&#xA;&#xD;&#xA;![Animation][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Animation with interpolation of knot form [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2] to  [0, 0, 0, 0, 0.34, 1, 1.66, 2, 2, 2, 2] and back. If you do proper point insertion then the curve does not change. Just talking about what multiplicity is.&#xD;&#xA;&#xD;&#xA;Alternatively to changing parametrization you can just add points on top of each other. This is equivalent although slight misuse of resources, but useful in surface modeling. Having many control points on top could also be useful for the uniform nature of the knot distribution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6DWhc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/iuSp4.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1063" PostHistoryTypeId="5" PostId="360" RevisionGUID="27707c68-d1ae-4bf1-89a8-d0dac7c7f9a1" CreationDate="2015-08-27T13:02:58.983" UserId="38" Comment="added 53 characters in body" Text="When you have a curve you can adjust the knots so that they lie on top of each other. This is essentially a bit like having several control points on top of each other, except there's only one point. This is sometimes known as multiplicity or duplicity.&#xD;&#xA;&#xD;&#xA;When you have as many knots on top of each other as you have degrees in the curve smoothness, you end up with a cusp, also known as as sharp corner. Once you have a sharp corner you can just go and delete the points on the opposite side as they no longer affect points no the other side of the corner. &#xD;&#xA;&#xD;&#xA;![Curve with cusp][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Curve and control cage (Top) and basis functions (bottom). In this case the curve acts as 2 adjoining bezier curves, The image is using the knot vector [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2].&#xD;&#xA;&#xD;&#xA;If we look at a knot vector then the multiplicity looks like a seqence of n knots that have the same number. Note if you do not add ecactly as many knots on top as there is smoothness then you get a partially sharp corner.&#xD;&#xA;&#xD;&#xA;![Animation][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Animation with interpolation of knot form [0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2] to  [0, 0, 0, 0, 0.34, 1, 1.66, 2, 2, 2, 2] and back. If you do proper point insertion then the curve does not change. Just talking about what multiplicity is.&#xD;&#xA;&#xD;&#xA;Alternatively to changing parametrization you can just add points on top of each other. This is equivalent although slight misuse of resources, but useful in surface modeling. Having many control points on top could also be useful for the uniform nature of the knot distribution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6DWhc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/iuSp4.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1065" PostHistoryTypeId="34" PostId="185" RevisionGUID="0c659fe1-5c95-48da-b92e-0d1cda244e7a" CreationDate="2015-08-28T01:14:02.603" UserId="-1" Comment="4" />
  <row Id="1066" PostHistoryTypeId="34" PostId="166" RevisionGUID="77cd6618-2c3f-4006-a6fb-5f359d247fbd" CreationDate="2015-08-28T01:14:02.603" UserId="-1" Comment="5" />
  <row Id="1067" PostHistoryTypeId="2" PostId="362" RevisionGUID="67bf28db-a26b-4abf-be7b-070cd73b09da" CreationDate="2015-08-28T02:22:47.113" UserId="197" Text="I've been reading the following article on how to do a parallel scan in CUDA:&#xD;&#xA;&#xD;&#xA;http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html&#xD;&#xA;&#xD;&#xA;In the article, there is an emphasis on making the scan &quot;work efficient&quot;. In other words, a GPU algorithm should perform no more additions than a CPU algorithm, O(n). The authors present two algorithms, one &quot;naive&quot; that does O(nlogn) additions, and one that they consider &quot;work efficient&quot;. However, the work efficient algorithm does twice as many loop iterations.&#xD;&#xA;&#xD;&#xA;From my understanding, GPUs are simply giant SIMD processors and should operate in lock-step. Doing twice as many loops in the &quot;work efficient&quot; algorithm seems to imply that many threads will be idle and decrease performance in the long run. What am I  missing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1068" PostHistoryTypeId="1" PostId="362" RevisionGUID="67bf28db-a26b-4abf-be7b-070cd73b09da" CreationDate="2015-08-28T02:22:47.113" UserId="197" Text="Why is work-efficiency desired in GPU programming?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1069" PostHistoryTypeId="3" PostId="362" RevisionGUID="67bf28db-a26b-4abf-be7b-070cd73b09da" CreationDate="2015-08-28T02:22:47.113" UserId="197" Text="|gpu|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1070" PostHistoryTypeId="2" PostId="363" RevisionGUID="c8ba1988-65c2-4f4d-b957-0c291b82902e" CreationDate="2015-08-28T04:03:06.527" UserId="197" Text="Rarely, if ever. You half-answered it in your own question: a vertex shader runs once per-vertex, a fragment shader once per-fragment. If you're not doing something that's unique to that vertex or fragment, then you're doing literally the exact same thing every time you invoke a shader. That doesn't sound more efficient to me." ContentLicense="CC BY-SA 3.0" />
  <row Id="1073" PostHistoryTypeId="2" PostId="364" RevisionGUID="1b90ffa8-0f18-427b-b5d8-c3a27c41ef95" CreationDate="2015-08-28T05:27:35.067" UserId="48" Text="First of all, re: &quot;GPUs are simply giant SIMD processors and should operate in lock-step&quot;, it's a bit more complicated than that. The *entire* GPU does not run in lockstep. Shader threads are organized into groups of 32 called &quot;warps&quot; (on NVIDIA; on AMD they're groups of 64 called &quot;wavefronts&quot;, but same concept).  Within a warp, all the threads do run in lockstep as a SIMD array. However, different warps are not in lockstep with each other. In addition, some warps may be actively running while others may be suspended, much like CPU threads.  Warps can be suspended either because they're waiting for something (such as memory transactions to return or barriers to clear), or because there isn't a slot available for them (since the GPU can only actively run a certain number of warps at a time).&#xD;&#xA;&#xD;&#xA;Now, back to your question. I can see two ways that the &quot;work-efficient&quot; algorithm from that paper looks like it would be more efficient than the &quot;naive&quot; algorithm.&#xD;&#xA;&#xD;&#xA;1. The work-efficient version requires half as many threads to begin with. In the naive algorithm, they have one thread per array element; but in the work-efficient version, each thread operates on two adjacent elements of the array and so they need only half as many threads as array elements. Fewer threads means fewer warps, and so a larger fraction of the warps can be actively running.&#xD;&#xA;&#xD;&#xA;2. Although the work-efficient version requires more steps, this is offset by the fact that the number of active threads decreases faster, and the total number of active threads over all the iterations is considerably smaller. If a warp has no active threads during an iteration, that warp will just skip to the following barrier and get suspended, allowing other warps to run. So, having fewer active warps can often pay off in execution time. (Implicit in this is that GPU code needs to be designed in such a way that active threads are packed together into as few warps as possible&amp;mdash;you don't want them to be sparsely scattered, as even one active thread will force the whole warp to stay active.)&#xD;&#xA;&#xD;&#xA; Consider the number of active threads in the naive algorithm.  Looking at Figure 2 in the article, you can see that all the threads are active *except* for the first 2&lt;sup&gt;_k_&lt;/sup&gt; on the _k_​th iteration.  So with _N_ threads, the number of active threads goes like _N_ ​− 2&lt;sup&gt;_k_&lt;/sup&gt;. For example, with _N_ = 1024, the number of active threads per iteration is:&#xD;&#xA;&#xD;&#xA;        1023, 1022, 1020, 1016, 1008, 992, 960, 896, 768, 512&#xD;&#xA;&#xD;&#xA; If I convert this to number of active warps (by dividing by 32 and rounding up), I get:&#xD;&#xA;&#xD;&#xA;        32, 32, 32, 32, 32, 31, 30, 28, 24, 16&#xD;&#xA;&#xD;&#xA; for a sum of 289.  On the other hand, the work-efficient algorithm starts with half as many threads, then it halves the number of active ones on each iteration until it gets down to 1, then starts doubling until it gets back up to half the array size again:&#xD;&#xA;&#xD;&#xA;         512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512&#xD;&#xA;&#xD;&#xA; Converting this to active warps:&#xD;&#xA;&#xD;&#xA;        16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16&#xD;&#xA;&#xD;&#xA; The sum is 71, which is only a quarter as many. So you can see that over the course of the entire operation, the number of active warps is much smaller with the work-efficient algorithm. (In fact, for a lengthy run in the middle there are only a handful of active warps, which means most of the chip is not occupied. If there are additional compute tasks running, e.g. from other CUDA streams, they could expand to fill that unoccupied space.)&#xD;&#xA;&#xD;&#xA;All that being said, it's unfortunate that the GPU Gems article does not clearly explain any of this, instead focusing on big-O &quot;number of additions&quot; analysis that, while not entirely irrelevant, misses a lot of the details about why this algorithm is faster." ContentLicense="CC BY-SA 3.0" />
  <row Id="1074" PostHistoryTypeId="2" PostId="365" RevisionGUID="849db2fa-7f46-445c-8efd-54377cabe4b1" CreationDate="2015-08-28T06:49:13.630" UserId="48" Text="At the top level, a GPU is subdivided into a number of shader cores.  A small GPU in a notebook or tablet may have only a few cores while a high-end desktop GPU may have dozens.&#xD;&#xA;&#xD;&#xA;In addition to the shader cores there are also texture units. They may be grouped together with one texture unit per shader core, or one texture unit shared among two or three shader cores, depending on the GPU.&#xD;&#xA;&#xD;&#xA;The whole chip shares a single L2 cache, but the different units will have individual L1 caches.  Texture units have texture caches, and shader units have caches for instructions and constants/uniforms, and maybe a separate cache for buffer data depending on whether buffer loads are a separate path from texture loads or not (varies by GPU architecture).&#xD;&#xA;&#xD;&#xA;Texture units operate independently and asynchronously from shader cores. When a shader performs a texture read, it sends a request to the texture unit across a little bus between them; the shader can then continue executing if possible, or it may get suspended and allow other shader threads to run while it waits for the texture read to finish.&#xD;&#xA;&#xD;&#xA;The texture unit batches up a bunch of requests and performs the addressing math on them&amp;mdash;selecting mip levels and anisotropy, converting UVs to texel coordinates, applying clamp/wrap modes, etc. Once it knows which texels it needs, it reads them through the cache hierarchy, the same way that memory reads work on a CPU (look in L1 first, if not there then L2, then DRAM). If many pending texture requests all want the same or nearby texels (as they often do), then you get a lot of efficiency here, as you can satisfy many pending requests with only a few memory transactions.  All these operations are pipelined, so while the texture unit is waiting for memory on one batch it can be doing the addressing math for another batch of requests, and so on.&#xD;&#xA;&#xD;&#xA;Once the data comes back, the texture unit will decode compressed formats, do sRGB conversion and filtering as necessary, then return the results back to the shader core." ContentLicense="CC BY-SA 3.0" />
  <row Id="1076" PostHistoryTypeId="2" PostId="366" RevisionGUID="9a985a8f-7a44-42b8-ac1e-40c46f2e477c" CreationDate="2015-08-28T15:05:33.153" UserId="56" Text="The demo scene has been doing Ray marching for a long time, but only recently have main stream AAA games started using it.  The main use I've seen it for is for screenspace reflections, raymarching against the zbuffer (killzone, call of duty).  Also, shadertoy was made by inigo quillez, who is from the demo scene.  People are now using shadertoy to prototype and share graphics technique research.  So I'd say the answer is yes, but I'd like to hear more examples if other people have any (:" ContentLicense="CC BY-SA 3.0" />
  <row Id="1077" PostHistoryTypeId="2" PostId="367" RevisionGUID="df5bf9b4-936d-4bbc-89bd-d05a7b98aaaa" CreationDate="2015-08-28T18:47:48.083" UserId="231" Text="I'd like to use OpenCL to accelerate rendering of raytraced images, but I notice that the [Wikipedia page] claims that recursion is forbidden in Open CL. Is this true? As I make extensive use of recursion when raytracing, this will require a considerable amount of redesign in order to benefit from the speed up. What is the underlying restriction that prevents recursion? Is there any way around it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Wikipedia page]: https://en.wikipedia.org/wiki/OpenCL#OpenCL_C_language" ContentLicense="CC BY-SA 3.0" />
  <row Id="1078" PostHistoryTypeId="1" PostId="367" RevisionGUID="df5bf9b4-936d-4bbc-89bd-d05a7b98aaaa" CreationDate="2015-08-28T18:47:48.083" UserId="231" Text="Why is recursion forbidden in OpenCL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1079" PostHistoryTypeId="3" PostId="367" RevisionGUID="df5bf9b4-936d-4bbc-89bd-d05a7b98aaaa" CreationDate="2015-08-28T18:47:48.083" UserId="231" Text="|raytracing|opencl|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1080" PostHistoryTypeId="2" PostId="368" RevisionGUID="3c6a6609-b630-4380-80cb-1e2e5123de3e" CreationDate="2015-08-29T02:17:36.830" UserId="48" Text="It's essentially because not all GPUs can support function calls&amp;mdash;and even if they can, function calls may be quite slow or have limitations such as a very small stack depth.&#xD;&#xA;&#xD;&#xA;Shader code and GPU compute code may appear to have function calls all over the place, but under normal circumstances they're all 100% inlined by the compiler. The machine code executed by the GPU contains branches and loops, but no function calls. However, recursive function calls cannot be inlined for obvious reasons. (Unless some of the arguments are compile-time constants, in such a way that the compiler can fold them and inline the entire tree of calls.)&#xD;&#xA;&#xD;&#xA;In order to implement true function calls, you need a stack.  Most of the time, shader code doesn't use a stack at all&amp;mdash;GPUs have large register files and shaders can keep all their data in registers the whole time.  It's difficult to make a stack work because (a) you would need a lot of stack space to provide for all the many warps that can be in flight at a time, and (b) the GPU memory system is optimized for batching together a lot of memory transactions to achieve high throughput, but this comes at the expense of latency, so my guess is stack operations like saving/restoring local variables would be awfully slow.&#xD;&#xA;&#xD;&#xA;Historically, hardware-level function calls haven't been too useful on the GPU, as it has made more sense to inline everything in the compiler.  So GPU architects haven't focused on making them fast.  Probably some different tradeoffs could be made, if there is a demand for efficient hardware-level calls in the future, but (as with everything in engineering) it will incur a cost somewhere else.&#xD;&#xA;&#xD;&#xA;As far as raytracing is concerned, the way people usually handle this sort of thing is by creating queues of rays that are in the process of being traced.  Instead of recursing, you add a ray to a queue, and at the high level somewhere you have a loop that keeps processing until all the queues are empty.  It does require significant reorganization of your rendering code if you're starting from a classic recursive raytracer, though.  For more info, a good paper to read on this is [Wavefront Path Tracing](https://research.nvidia.com/publication/megakernels-considered-harmful-wavefront-path-tracing-gpus)." ContentLicense="CC BY-SA 3.0" />
  <row Id="1082" PostHistoryTypeId="2" PostId="369" RevisionGUID="48c438a7-9830-4c59-a8bb-20d39b6f2bf3" CreationDate="2015-08-29T07:00:30.047" UserId="482" Text="My postscript interpreter currently implements the [Hodgeman-Sutherland clipping algorithm](https://github.com/luser-dr00g/xpost/blob/master/data/clip.ps) but this is limited to simpler shapes and doesn't have a provision for utilizing various winding-number rules. So it doesn't help me to implement even-odd filling or handle complex self-intersecting shapes. &#xD;&#xA;&#xD;&#xA;The [Weiler-Atherton algorithm](https://en.wikipedia.org/w/index.php?title=Weiler%E2%80%93Atherton_clipping_algorithm) promises to offer all these features, but every time I sit down with it, I get hung up on implementing the basic constructs. Specifically it requires making bi-directional associations between nodes which can then be traversed in either direction. But, how do you do that?&#xD;&#xA;&#xD;&#xA;If I implement my path lists in Postscript (or any dynamic object-based language) as an array of points, the points themselves implemented as an array of coordinates, do I make a list of index pairs and do a linear search for traversing? Or can I use an associative array to make a mapping, and is it sufficient to add both (node1-&gt;node2) and (node2-&gt;node1)?&#xD;&#xA;&#xD;&#xA;Or what if the paths are in a linked-list in a C like language with pointers to the next vertex and a NULL pointer designating the end, do you just add more links (pointers) to the nodes?&#xD;&#xA;&#xD;&#xA;You don't need to address all my questions here, it should be sufficient to describe the strategy for building this data structure for 1 language, and I should be able to apply it to my specific case which is usually to prototype in Postscript and translate to C if necessary for speed.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1083" PostHistoryTypeId="1" PostId="369" RevisionGUID="48c438a7-9830-4c59-a8bb-20d39b6f2bf3" CreationDate="2015-08-29T07:00:30.047" UserId="482" Text="How to describe the bi-directional links for the Weiler-Atherton algorithm?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1084" PostHistoryTypeId="3" PostId="369" RevisionGUID="48c438a7-9830-4c59-a8bb-20d39b6f2bf3" CreationDate="2015-08-29T07:00:30.047" UserId="482" Text="|polygon|clipping|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1085" PostHistoryTypeId="34" PostId="283" RevisionGUID="48a77b76-09ca-46f1-96db-3ad378059dce" CreationDate="2015-08-29T10:53:33.020" UserId="-1" Comment="7" />
  <row Id="1086" PostHistoryTypeId="2" PostId="370" RevisionGUID="4c3f0a82-9cb8-4116-b695-9755aec9f70b" CreationDate="2015-08-29T15:15:24.327" UserId="376" Text="Looking at [Star Swarm][1], a demo for the Nitrous engine, I found this little line:&#xD;&#xA;&quot;Nitrous uses Object Space Lighting, the same techniques used in film, including real-time film-quality motion blur.&quot;&#xD;&#xA;&#xD;&#xA;I tried looking around for anything on &quot;object space lighting&quot; or &quot;object space rendering&quot; but couldn't come up with anything. When I hear &quot;object space&quot; I think of doing it per-object but I was hoping to find a more detailed description of the method.&#xD;&#xA;&#xD;&#xA;Does anyone know anything about &quot;object space lighting&quot; and if so could you go into some technical details(how its done, pros, cons, etc)?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.oxidegames.com/star-swarm/" ContentLicense="CC BY-SA 3.0" />
  <row Id="1087" PostHistoryTypeId="1" PostId="370" RevisionGUID="4c3f0a82-9cb8-4116-b695-9755aec9f70b" CreationDate="2015-08-29T15:15:24.327" UserId="376" Text="What is &quot;Object Space Lighting&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1088" PostHistoryTypeId="3" PostId="370" RevisionGUID="4c3f0a82-9cb8-4116-b695-9755aec9f70b" CreationDate="2015-08-29T15:15:24.327" UserId="376" Text="|rendering|real-time|lighting|space|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1090" PostHistoryTypeId="2" PostId="371" RevisionGUID="86b24f9d-2e8a-45ff-bf9e-4e6b77519efd" CreationDate="2015-08-29T19:29:17.383" UserId="93" Text="According to the Star Swarm developers this helps them with LOD and enables greater shading scaling. Based on this I guess its simply texture space lighting.&#xA;&#xA;&gt; Because we do what we’re calling object space lighting, we calculate the projected size of each of those objects on screen, and based on that we shade it in a priority manner based on how large they are. We can scale the shading quality at a different frequency than we scale the geometry level or something else.&#xA;&#xA;[ A deep dive into the making of the eye-popping Star Swarm demo (interview)][1]&#xA;&#xA;&#xA;  [1]: http://venturebeat.com/2014/01/21/a-deep-dive-into-the-making-of-the-eye-popping-star-swarm-demo-interview/view-all/" ContentLicense="CC BY-SA 3.0" />
  <row Id="1092" PostHistoryTypeId="2" PostId="372" RevisionGUID="630bc7e7-34ba-4937-b8b1-a6d4c4046a66" CreationDate="2015-08-30T15:46:52.053" UserId="193" Text="I've been playing around with shadow mapping in OpenGL using depth textures. The depth texture is fine and I can map it onto the scene but I have some strange artefacts on the back of the object:&#xD;&#xA;&#xD;&#xA;![Sphere casting a shadow, with artefacts on rear](https://i.stack.imgur.com/5mvOl.png)&#xD;&#xA;&#xD;&#xA;My question is what is causing this and how can I fix it?&#xD;&#xA;&#xD;&#xA;The fragment shader I'm using is fairly straightforward (I stripped out the colour for simplicity in case you're wondering why there's no blue here):&#xD;&#xA;&#xD;&#xA;	in vec4 vShadowCoord;&#xD;&#xA;&#xD;&#xA;	uniform sampler2DShadow shadowMap;&#xD;&#xA;&#xD;&#xA;	out vec4 fragColor;&#xD;&#xA;	&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		float bias = 0.005;&#xD;&#xA;		float visibility = 1.0;&#xD;&#xA;		if (texture(shadowMap, vec3(vShadowCoord.xy, vShadowCoord.z / vShadowCoord.w)) &lt; (vShadowCoord.z - bias) / vShadowCoord.w)&#xD;&#xA;			visibility = 0.25;&#xD;&#xA;&#xD;&#xA;		fragColor = vec4(visibility);&#xD;&#xA;	}" ContentLicense="CC BY-SA 3.0" />
  <row Id="1093" PostHistoryTypeId="1" PostId="372" RevisionGUID="630bc7e7-34ba-4937-b8b1-a6d4c4046a66" CreationDate="2015-08-30T15:46:52.053" UserId="193" Text="Shadow Mapping artefacts" ContentLicense="CC BY-SA 3.0" />
  <row Id="1094" PostHistoryTypeId="3" PostId="372" RevisionGUID="630bc7e7-34ba-4937-b8b1-a6d4c4046a66" CreationDate="2015-08-30T15:46:52.053" UserId="193" Text="|opengl|glsl|shadow-mapping|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1097" PostHistoryTypeId="10" PostId="359" RevisionGUID="e93798ac-b577-4ae9-b069-72682779bba3" CreationDate="2015-08-30T18:51:12.580" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:197,&quot;DisplayName&quot;:&quot;Mokosha&quot;},{&quot;Id&quot;:80,&quot;DisplayName&quot;:&quot;GµårÐïåñ&quot;},{&quot;Id&quot;:159,&quot;DisplayName&quot;:&quot;Pseudonym&quot;},{&quot;Id&quot;:21,&quot;DisplayName&quot;:&quot;S.L. Barth&quot;},{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="1098" PostHistoryTypeId="10" PostId="354" RevisionGUID="a649ab07-786d-4b60-be8e-f8caabf40532" CreationDate="2015-08-30T18:52:08.443" UserId="-1" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:80,&quot;DisplayName&quot;:&quot;GµårÐïåñ&quot;},{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="1101" PostHistoryTypeId="5" PostId="369" RevisionGUID="9fc70257-d4ab-4b43-bd18-7ba86c7221ce" CreationDate="2015-08-30T20:53:57.460" UserId="482" Comment="I can read other languages" Text="My postscript interpreter currently implements the [Hodgeman-Sutherland clipping algorithm](https://github.com/luser-dr00g/xpost/blob/master/data/clip.ps) but this is limited to simpler shapes and doesn't have a provision for utilizing various winding-number rules. So it doesn't help me to implement even-odd filling or handle complex self-intersecting shapes. &#xD;&#xA;&#xD;&#xA;The [Weiler-Atherton algorithm](https://en.wikipedia.org/w/index.php?title=Weiler%E2%80%93Atherton_clipping_algorithm) promises to offer all these features, but every time I sit down with it, I get hung up on implementing the basic constructs. Specifically it requires making bi-directional associations between nodes which can then be traversed in either direction. But, how do you do that?&#xD;&#xA;&#xD;&#xA;If I implement my path lists in Postscript (or any dynamic object-based language) as an array of points, the points themselves implemented as an array of coordinates, do I make a list of index pairs and do a linear search for traversing? Or can I use an associative array to make a mapping, and is it sufficient to add both (node1-&gt;node2) and (node2-&gt;node1)?&#xD;&#xA;&#xD;&#xA;Or what if the paths are in a linked-list in a C like language with pointers to the next vertex and a NULL pointer designating the end, do you just add more links (pointers) to the nodes?&#xD;&#xA;&#xD;&#xA;You don't need to address all my questions here, it should be sufficient to describe the strategy for building this data structure for any 1 language (not necessarily Postscript or C), and I should be able to apply it to my specific case which is usually to prototype in Postscript and translate to C if necessary for speed.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1102" PostHistoryTypeId="33" PostId="209" RevisionGUID="1e124cb1-39f8-423b-a723-e12a1ea69a8d" CreationDate="2015-08-30T21:23:36.560" UserId="231" Comment="8" />
  <row Id="1103" PostHistoryTypeId="2" PostId="374" RevisionGUID="becb0c43-429e-4325-b9f7-c2be07021c3a" CreationDate="2015-08-30T21:59:24.907" UserId="482" Text="I tried [this question on math.SE](http://math.stackexchange.com/questions/348806/intersect-a-line-with-a-bicubic-bezier-surface-patch) and surprisingly, the answer was &quot;the equations are too nasty, just feed the function it to a numerical root-finder&quot;. But if you consider yourself &quot;a graphics guy&quot; like me, and have played extensively with Bezier curves for design work, I got to believe that better can be done. There is a published algorithm by Kajiya that I don't have the background to understand (Sylvester Matrices), but the related advice on math.SE was that the result is a degree-18 polynomial in t, and you still need to solve that numerically. [I had another idea with similar result](http://math.stackexchange.com/questions/1083240/can-a-bicubic-bezier-surface-be-represented-as-a-bernstein-polynomial).&#xD;&#xA;&#xD;&#xA;So, is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically, thus making it possible to code explicitly and have super-fast super-smoothness?&#xD;&#xA;&#xD;&#xA;Barring that, what's the fastest method for performing this calculation? Can you &quot;find the wiggles&quot; to get a tight bound (and target) for recursive subdivision? If you have to use a numerical root-finder (sigh), what properties does it need and is there a best choice for speed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1104" PostHistoryTypeId="1" PostId="374" RevisionGUID="becb0c43-429e-4325-b9f7-c2be07021c3a" CreationDate="2015-08-30T21:59:24.907" UserId="482" Text="How to raytrace Bezier surfaces?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1105" PostHistoryTypeId="3" PostId="374" RevisionGUID="becb0c43-429e-4325-b9f7-c2be07021c3a" CreationDate="2015-08-30T21:59:24.907" UserId="482" Text="|raytracing|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1106" PostHistoryTypeId="5" PostId="374" RevisionGUID="7574e5dd-bb9e-42e1-9166-10b119b5c083" CreationDate="2015-08-30T22:22:33.400" UserId="482" Comment="expanded parameters" Text="I tried [this question on math.SE](http://math.stackexchange.com/questions/348806/intersect-a-line-with-a-bicubic-bezier-surface-patch) and surprisingly, the answer was &quot;the equations are too nasty, just feed the function it to a numerical root-finder&quot;. But if you consider yourself &quot;a graphics guy&quot; like me, and have played extensively with Bezier curves for design work, I got to believe that better can be done. There is a published algorithm by Kajiya that I don't have the background to understand (Sylvester Matrices), but the related advice on math.SE was that the result is a degree-18 polynomial in t, and you still need to solve that numerically. [I had another idea with similar result](http://math.stackexchange.com/questions/1083240/can-a-bicubic-bezier-surface-be-represented-as-a-bernstein-polynomial).&#xD;&#xA;&#xD;&#xA;So, is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically, thus making it possible to code explicitly and have super-fast super-smoothness?&#xD;&#xA;&#xD;&#xA;Barring that, what's the fastest method for performing this calculation? Can you &quot;find the wiggles&quot; to get a tight bound (and target) for recursive subdivision? If you have to use a numerical root-finder (sigh), what properties does it need and is there a best choice for speed?&#xD;&#xA;&#xD;&#xA;My original thought was about preparing for a specific surface, similar to Laplace expansion as described in the answer to my [other math question about triangles](http://math.stackexchange.com/questions/297588/for-bsp-generation-how-to-intersect-or-locate-a-triangle-with-a-plane-defined-b). But I'd be interested in general methods, too. I'm just thinking of a fixed set of shapes, like the Utah teaset. But I'd be very interested in ways of optimizing for temporal coherence across animated frames." ContentLicense="CC BY-SA 3.0" />
  <row Id="1107" PostHistoryTypeId="5" PostId="374" RevisionGUID="354e8002-feb5-48db-b2b9-7611166bf6e6" CreationDate="2015-08-30T22:32:51.197" UserId="482" Comment="another link into my web" Text="I tried [this question on math.SE](http://math.stackexchange.com/questions/348806/intersect-a-line-with-a-bicubic-bezier-surface-patch) and surprisingly, the answer was &quot;the equations are too nasty, just feed the function it to a numerical root-finder&quot;. But if you consider yourself &quot;a graphics guy&quot; like me, and have played extensively with Bezier curves for design work, I got to believe that better can be done. There is a published algorithm by Kajiya that I don't have the background to understand (Sylvester Matrices), but the related advice on math.SE was that the result is a degree-18 polynomial in t, and you still need to solve that numerically. [I had another idea with similar result](http://math.stackexchange.com/questions/1083240/can-a-bicubic-bezier-surface-be-represented-as-a-bernstein-polynomial).&#xD;&#xA;&#xD;&#xA;So, is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically, thus making it possible to code explicitly and have super-fast super-smoothness?&#xD;&#xA;&#xD;&#xA;Barring that, what's the fastest method for performing this calculation? Can you &quot;find the wiggles&quot; to get a tight bound (and target) for recursive subdivision? If you have to use a numerical root-finder (sigh), what properties does it need and is there a best choice for speed?&#xD;&#xA;&#xD;&#xA;My original thought was about preparing for a specific surface, similar to Laplace expansion as described in the answer to my [other math question about triangles](http://math.stackexchange.com/questions/297588/for-bsp-generation-how-to-intersect-or-locate-a-triangle-with-a-plane-defined-b). But I'd be interested in general methods, too. I'm just thinking of a fixed set of shapes, like [the Utah teapot](http://stackoverflow.com/questions/14807341/how-to-do-a-space-partitioning-of-the-utah-teapot). But I'd be very interested in ways of optimizing for temporal coherence across animated frames." ContentLicense="CC BY-SA 3.0" />
  <row Id="1109" PostHistoryTypeId="2" PostId="375" RevisionGUID="98d224aa-db12-49e0-82d6-8fce210cc6df" CreationDate="2015-08-31T01:30:55.070" UserId="480" Text="&#xD;&#xA;Wikipedia [says][1]: &quot;... represents a fixed-intensity and fixed-color light source that affects all objects in the scene equally.&quot;&#xD;&#xA;&#xD;&#xA;By saying &quot;affects all objects equally&quot; they mean all objects get the same amount of light? So if you have three houses in your scene, you would need to calculate a specific position for the ambient lightning source, in order that every object gets the same amount of light? If not, you would not have an a.l.s.? &#xD;&#xA;&#xD;&#xA;What is the difference between &quot;normal&quot; lightning from the sun and ambient lightning?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shading#Ambient_lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="1110" PostHistoryTypeId="1" PostId="375" RevisionGUID="98d224aa-db12-49e0-82d6-8fce210cc6df" CreationDate="2015-08-31T01:30:55.070" UserId="480" Text="What is ambient lightning?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1111" PostHistoryTypeId="3" PostId="375" RevisionGUID="98d224aa-db12-49e0-82d6-8fce210cc6df" CreationDate="2015-08-31T01:30:55.070" UserId="480" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1112" PostHistoryTypeId="2" PostId="376" RevisionGUID="ba8849b5-232c-4d57-b766-b8f89885906f" CreationDate="2015-08-31T01:48:27.043" UserId="480" Text="I do not understand the [explanation][1] from wikipedia.&#xD;&#xA;&#xD;&#xA;&gt; For every pixel on the screen, the pixel shader samples the depth values around the current pixel and tries to compute the amount of occlusion from each of the sampled points.&#xD;&#xA;&#xD;&#xA;How can depth values of surrounding pixels tell you something about occlusion? **Occlusion**, as I understand, happens when an object A stands in front of another object B, so you cannot see the object B. But why would you now look at the depth pixels of **surrounding** pixels? I mean you can see those pixels, so there is no occlusion. Maybe I understood occlusion wrong.&#xD;&#xA;&#xD;&#xA;And what I also did not understand is the term kernel in some other tutorials. What is a kernel and why would you use it for ssao?&#xD;&#xA;&#xD;&#xA;Could someone make a detailed explanation of the algorithm, with regard to my questions?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Screen_space_ambient_occlusion#Implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="1113" PostHistoryTypeId="1" PostId="376" RevisionGUID="ba8849b5-232c-4d57-b766-b8f89885906f" CreationDate="2015-08-31T01:48:27.043" UserId="480" Text="How is screen space ambient occlusion implemented?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1114" PostHistoryTypeId="3" PostId="376" RevisionGUID="ba8849b5-232c-4d57-b766-b8f89885906f" CreationDate="2015-08-31T01:48:27.043" UserId="480" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1115" PostHistoryTypeId="2" PostId="377" RevisionGUID="da7957ec-3be1-41d8-baa6-54d42cc2ada0" CreationDate="2015-08-31T01:58:54.870" UserId="480" Text="How do they work and what are the differences between them? In what scenario should you use which one?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1116" PostHistoryTypeId="1" PostId="377" RevisionGUID="da7957ec-3be1-41d8-baa6-54d42cc2ada0" CreationDate="2015-08-31T01:58:54.870" UserId="480" Text="Shading: Phong vs Gouraud vs Flat" ContentLicense="CC BY-SA 3.0" />
  <row Id="1117" PostHistoryTypeId="3" PostId="377" RevisionGUID="da7957ec-3be1-41d8-baa6-54d42cc2ada0" CreationDate="2015-08-31T01:58:54.870" UserId="480" Text="|algorithm|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1118" PostHistoryTypeId="2" PostId="378" RevisionGUID="eb53eee0-aed2-4c09-9044-09aeb401d315" CreationDate="2015-08-31T02:12:03.533" UserId="159" Text="First off, here's the Kajiya method I think you're thinking of: Kajiya, *Ray Tracing Parametric Patches*, SIGGRAPH 82. [The tech report version][1] might be more informative.&#xD;&#xA;&#xD;&#xA;What I hope you get from that is that it's not impossible and it's not conceptually difficult if you don't mind getting your hands dirty with some algebraic geometry and complex numbers. However, doing it directly is absurdly expensive.&#xD;&#xA;&#xD;&#xA;&quot;Real&quot; ray tracers tend to do some combination of two things:&#xD;&#xA;&#xD;&#xA; - Placing a bounding hierarchy (e.g. AABBs) on the patch to get a good &quot;initial value&quot; for a numeric root finder. If you do this well, you can avoid the &quot;wrinkle&quot; problem.&#xD;&#xA; - Tesselating the patch into [DDG shells][2] and ray tracing them like polygon meshes.&#xD;&#xA;&#xD;&#xA;That last point sounds like it kills the &quot;super-smoothness&quot; requirement, but it isn't nearly as bad as that if you're using [ray differentials][3]. Matching the tessellation level to the &quot;size&quot; of the ray bounds the error nicely. Besides, you probably need differentials for texture coordinates anyway, so you might as well use it to control the accuracy of the intersection test too.&#xD;&#xA;&#xD;&#xA;Exploiting temporal coherence isn't a bad idea, but exactly how you'd do that depends a lot on your scene graph representation. You might want to look at ray coherence. Ask your favourite search engine about [ray packet tracing][4] and [ray reordering][5].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://core.ac.uk/download/pdf/4891798.pdf&#xD;&#xA;  [2]: http://ddg.cs.columbia.edu&#xD;&#xA;  [3]: https://graphics.stanford.edu/papers/trd/&#xD;&#xA;  [4]: http://cseweb.ucsd.edu/~ravir/whitted.pdf&#xD;&#xA;  [5]: https://graphics.stanford.edu/~boulos/papers/reorder_rt08.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="1119" PostHistoryTypeId="2" PostId="379" RevisionGUID="d3316076-4716-4213-a647-0caba08fd84a" CreationDate="2015-08-31T04:28:42.567" UserId="182" Text="In this context, `Ambient lighting` refers to a very crude approximation of indirect lighting.&#xD;&#xA;&#xD;&#xA;Direct lighting from a direct source is relatively simple to evaluate and model, even in real-time. But the light that is not absorbed will bounce all over the place and cause indirect lighting. This is why for example a lamp will a lampshade will light a whole room and not only the narrow area underneath.&#xD;&#xA;&#xD;&#xA;But modeling indirect lighting is difficult and costly. So an approximation is to consider that lighting to be **constant and independent from position**: that's ambient lighting.&#xD;&#xA;&#xD;&#xA;In the case of outdoor scene, ambient lighting would represent the blue light coming from the sky dome, as opposed to the orange direct light coming from the Sun." ContentLicense="CC BY-SA 3.0" />
  <row Id="1120" PostHistoryTypeId="2" PostId="380" RevisionGUID="716b6646-b656-485e-8854-60d608530bc1" CreationDate="2015-08-31T04:42:14.127" UserId="38" Text="Traditional rendering solutions do not do account for secondary light bounces (called indirect light). Even with strategically placed fill lights you still have areas where none of the direct light hits.&#xD;&#xA;&#xD;&#xA;Ambient light tries to solve this problem by shining by a constant amount in all directions. In practice this means that light position or surface normal has no meaning, one just adds some of the shaders color multiplied by ambient light color to the shading result.&#xD;&#xA;&#xD;&#xA;Ambient light has a tendency to look artificial when overused. But the opposite problem is that surfaces look like they are on outer space. Ambient light also makes the difference between dark materials and light materials more apparent.&#xD;&#xA;&#xD;&#xA;The real problem is that ambient light does not really exist. Even if youd argue that its useful model, it certainly is not uniform. Its just a quick fix. Therefore all kinds of tricks, like ambient occlusion, have been proposed to enhance the quality of ambient light." ContentLicense="CC BY-SA 3.0" />
  <row Id="1122" PostHistoryTypeId="6" PostId="376" RevisionGUID="88082e4a-2e45-42ee-a58d-5b0b658229db" CreationDate="2015-08-31T07:00:54.113" UserId="127" Comment="Edited tags." Text="|algorithm|lighting|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1123" PostHistoryTypeId="24" PostId="376" RevisionGUID="88082e4a-2e45-42ee-a58d-5b0b658229db" CreationDate="2015-08-31T07:00:54.113" Comment="Proposed by 127 approved by 480 edit id of 44" ContentLicense="CC BY-SA 3.0" />
  <row Id="1124" PostHistoryTypeId="2" PostId="382" RevisionGUID="6d7e9aaa-6120-47e3-ba3e-373224c96a51" CreationDate="2015-08-31T08:46:16.797" UserId="158" Text="Flat shading is the simplest shading model.  Each rendered polygon has a single normal vector; shading for the entire polygon is constant across the surface of the polygon.  With a small polygon count, this gives curved surfaces a faceted look.&#xD;&#xA;&#xD;&#xA;Phong shading is the most sophisticated of the three methods you list.  Each rendered polygon has one normal vector per vertex; shading is performed by interpolating the vectors across the surface and computing the color for each point of interest.  Interpolating the normal vectors gives a reasonable approximation to a smoothly-curved surface while using a limited number of polygons.&#xD;&#xA;&#xD;&#xA;Gourard shading is in between the two: like Phong shading, each polygon has one normal vector per vertex, but instead of interpolating the vectors, the color of each vertex is computed and then interpolated across the surface of the polygon.&#xD;&#xA;&#xD;&#xA;On modern hardware, you should either use flat shading (if speed is everything) or Phong shading (if quality is important).  Or you can use a programmable-pipeline shader and avoid the whole question." ContentLicense="CC BY-SA 3.0" />
  <row Id="1126" PostHistoryTypeId="5" PostId="380" RevisionGUID="c31d5a35-aa30-4ac1-82a5-7bebd4ab0f22" CreationDate="2015-08-31T11:31:51.543" UserId="38" Comment="added 250 characters in body" Text="Traditional rendering solutions do not do account for secondary light bounces (called indirect light). Even with strategically placed fill lights you still have areas where none of the direct light hits.&#xD;&#xA;&#xD;&#xA;Ambient light tries to solve this problem by shining by a constant amount in all directions. In practice this means that light position or surface normal has no meaning, one just adds some of the shaders color multiplied by ambient light color to the shading result.&#xD;&#xA;&#xD;&#xA;Ambient light has a tendency to look artificial when overused. But the opposite problem is that surfaces look like they are on outer space. Ambient light also makes the difference between dark materials and light materials more apparent.&#xD;&#xA;&#xD;&#xA;[![Ambient light][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1:** Image without ambient light (left) looks like it was shot in space. Image with ambient (right) looks more natural, although possibly a bit flat if overused.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The real problem is that ambient light does not really exist. Even if youd argue that its useful model, it certainly is not uniform. Its just a quick fix. Therefore all kinds of tricks, like ambient occlusion, have been proposed to enhance the quality of ambient light.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eQWU1.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1128" PostHistoryTypeId="5" PostId="372" RevisionGUID="4cc8c30d-676e-47fe-b559-c1ff3c23e5b8" CreationDate="2015-08-31T13:33:46.303" UserId="193" Comment="Added extra screenshot of minimum working example" Text="I've been playing around with shadow mapping in OpenGL using depth textures. The depth texture is fine and I can map it onto the scene but I have some strange artefacts on the back of the object:&#xD;&#xA;&#xD;&#xA;![Sphere casting a shadow, with artefacts on rear](https://i.stack.imgur.com/5mvOl.png)&#xD;&#xA;&#xD;&#xA;My question is what is causing this and how can I fix it?&#xD;&#xA;&#xD;&#xA;The fragment shader I'm using is fairly straightforward (I stripped out the colour for simplicity in case you're wondering why there's no blue here):&#xD;&#xA;&#xD;&#xA;	in vec4 vShadowCoord;&#xD;&#xA;&#xD;&#xA;	uniform sampler2DShadow shadowMap;&#xD;&#xA;&#xD;&#xA;	out vec4 fragColor;&#xD;&#xA;	&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		float bias = 0.005;&#xD;&#xA;		float visibility = 1.0;&#xD;&#xA;		if (texture(shadowMap, vec3(vShadowCoord.xy, vShadowCoord.z / vShadowCoord.w)) &lt; (vShadowCoord.z - bias) / vShadowCoord.w)&#xD;&#xA;			visibility = 0.25;&#xD;&#xA;&#xD;&#xA;		fragColor = vec4(visibility);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit: As requested, minimum working example screenshot that uses only the above code (no colour).&#xD;&#xA;&#xD;&#xA;![Same sphere, minus colour](https://i.stack.imgur.com/DdrCy.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="1129" PostHistoryTypeId="2" PostId="383" RevisionGUID="2e1e4465-d5eb-4309-894e-d045f6d915f6" CreationDate="2015-08-31T19:56:41.090" UserId="93" Text="This issue looks like standard shadow map acne artifacts.&#xD;&#xA;&#xD;&#xA; - First acme source is shadow map precision. Make sure that near and far planes of shadow casting light are as tight as possible. All objects before the near plane can be pancaked, as their exact depth isn't important.&#xD;&#xA; - Second acme source is shadow map resolution. For a directional light you should be doing cascaded shadow maps with at least 3 1024x1012 cascades for ~100-200m of shadow distance. It's hard to cover similar shadow distance with one shadow map with uniform projection.&#xD;&#xA; - Third acme source is wide shadow map filter like PCF, as using a single depth depth comparison value across a wide kernel is insufficient. There are many methods to fix it, but none of them is robust.&#xD;&#xA;&#xD;&#xA;To sum up, a tight frustum with a few cascades and some bias tweaking is enough to get the general case working (directional light). Start tweaking by disabling shadow filtering and tweak for filtering only when basic shadow maps are robust enough.&#xD;&#xA;&#xD;&#xA;There are some additional interesting methods and most of them are implemented in the excellent demo: [Matt Pettineo - &quot;A sampling of shadow techniques&quot;].&#xD;&#xA;&#xD;&#xA; - Flip culling during shadow map rendering (trades acne for Peter panning).&#xD;&#xA; - Normal offset shadow mapping does wonders for bias issues, but requires to have vertex normals around during shading.&#xD;&#xA; - Variance based methods (ESM,VSM,EVSM) completely remove bias issues, but have other drawbacks (light leaking and/or performance issues).&#xD;&#xA;&#xD;&#xA;  [Matt Pettineo - &quot;A sampling of shadow techniques&quot;]: https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/" ContentLicense="CC BY-SA 3.0" />
  <row Id="1131" PostHistoryTypeId="5" PostId="375" RevisionGUID="7b2e0cf2-6497-4bfd-b383-33694701415e" CreationDate="2015-08-31T20:35:36.323" UserId="231" Comment="Minor typos" Text="Wikipedia [says][1]: &quot;... represents a fixed-intensity and fixed-color light source that affects all objects in the scene equally.&quot;&#xD;&#xA;&#xD;&#xA;By saying &quot;affects all objects equally&quot; they mean all objects get the same amount of light? So if you have three houses in your scene, you would need to calculate a specific position for the ambient lighting source, in order that every object gets the same amount of light? If not, you would not have an a.l.s.? &#xD;&#xA;&#xD;&#xA;What is the difference between &quot;normal&quot; lighting from the sun and ambient lighting?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shading#Ambient_lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="1132" PostHistoryTypeId="4" PostId="375" RevisionGUID="7b2e0cf2-6497-4bfd-b383-33694701415e" CreationDate="2015-08-31T20:35:36.323" UserId="231" Comment="Minor typos" Text="What is ambient lighting?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1137" PostHistoryTypeId="5" PostId="383" RevisionGUID="a5ef1d7f-1d8c-49fe-861a-2750a1e77d8f" CreationDate="2015-08-31T20:51:39.247" UserId="231" Comment="Minor typos" Text="This issue looks like standard shadow map acne artifacts.&#xD;&#xA;&#xD;&#xA; - First acne source is shadow map precision. Make sure that near and far planes of shadow casting light are as tight as possible. All objects before the near plane can be pancaked, as their exact depth isn't important.&#xD;&#xA; - Second acne source is shadow map resolution. For a directional light you should be doing cascaded shadow maps with at least 3 1024x1012 cascades for ~100-200m of shadow distance. It's hard to cover similar shadow distance with one shadow map with uniform projection.&#xD;&#xA; - Third acne source is wide shadow map filter like PCF, as using a single depth depth comparison value across a wide kernel is insufficient. There are many methods to fix it, but none of them is robust.&#xD;&#xA;&#xD;&#xA;To sum up, a tight frustum with a few cascades and some bias tweaking is enough to get the general case working (directional light). Start tweaking by disabling shadow filtering and tweak for filtering only when basic shadow maps are robust enough.&#xD;&#xA;&#xD;&#xA;There are some additional interesting methods and most of them are implemented in the excellent demo: [Matt Pettineo - &quot;A sampling of shadow techniques&quot;].&#xD;&#xA;&#xD;&#xA; - Flip culling during shadow map rendering (trades acne for Peter panning).&#xD;&#xA; - Normal offset shadow mapping does wonders for bias issues, but requires to have vertex normals around during shading.&#xD;&#xA; - Variance based methods (ESM, VSM, EVSM) completely remove bias issues, but have other drawbacks (light leaking and/or performance issues).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Matt Pettineo - &quot;A sampling of shadow techniques&quot;]: https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/" ContentLicense="CC BY-SA 3.0" />
  <row Id="1144" PostHistoryTypeId="5" PostId="383" RevisionGUID="980ccae0-1714-4870-b81c-59d668b9126c" CreationDate="2015-08-31T21:38:14.767" UserId="93" Comment="Added slope depth bias " Text="This issue looks like standard shadow map acne artifacts.&#xD;&#xA;&#xD;&#xA; - First acne source is shadow map precision. Make sure that near and far planes of shadow casting light are as tight as possible. All objects before the near plane can be pancaked, as their exact depth isn't important.&#xD;&#xA; - Second acne source is shadow map resolution. For a directional light you should be doing cascaded shadow maps with at least 3 1024x1012 cascades for ~100-200m of shadow distance. It's hard to cover similar shadow distance with one shadow map with uniform projection.&#xD;&#xA; - Third acne source is wide shadow map filter like PCF, as using a single depth depth comparison value across a wide kernel is insufficient. There are many methods to fix it, but none of them is robust.&#xD;&#xA;&#xD;&#xA;To sum up, a tight frustum with a few cascades and some bias tweaking is enough to get the general case working (directional light). Start tweaking by disabling shadow filtering and tweak for filtering only when basic shadow maps are robust enough. &#xD;&#xA;&#xD;&#xA;Additionally apart from the constant depth bias (which you currently use) you should also add slope depth bias and max slope depth bias. Both can be be implemented either as render state or as shader code during shadowmap rendering. Slope depth bias is simply a magic bias value scaled by dot( normal, lightDir ).&#xD;&#xA;&#xD;&#xA;There are some additional interesting methods and most of them are implemented in the excellent demo: [Matt Pettineo - &quot;A sampling of shadow techniques&quot;].&#xD;&#xA;&#xD;&#xA; - Flip culling during shadow map rendering (trades acne for Peter panning).&#xD;&#xA; - Normal offset shadow mapping does wonders for bias issues, but requires to have vertex normals around during shading.&#xD;&#xA; - Variance based methods (ESM, VSM, EVSM) completely remove bias issues, but have other drawbacks (light leaking and/or performance issues).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Matt Pettineo - &quot;A sampling of shadow techniques&quot;]: https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/" ContentLicense="CC BY-SA 3.0" />
  <row Id="1145" PostHistoryTypeId="2" PostId="385" RevisionGUID="1afcd4b4-593d-4428-8a26-879a8846de5e" CreationDate="2015-08-31T21:43:48.277" UserId="506" Text="As Alan and trichoplax mention in the comments, the effect that ambient occlusion simulates is not the occlusion of a surface from the camera but the surface’s occlusion from its surroundings.&#xD;&#xA;&#xD;&#xA;Think of it this way: say you have even illumination coming from every direction, so that the total incoming light sums up to a value of 1. If you place a flat plane in that environment and look at one side of it, that side is going to receive 50% of that illumination, because the other half is blocked by the plane itself. In other words, any point on the plane’s surface can only “see” the light coming from half of the environment, so it’s half as brightly illuminated. If you fold that plane towards your viewpoint (a “valley” fold), then you decrease the incoming illumination to that side of the plane further, because, again, each point on the plane “see”s a bit less of the light coming from the surroundings.&#xD;&#xA;&#xD;&#xA;Screen-space ambient occlusion works more or less by looking for these “folds”—areas where the depth changes sharply, as defined by comparing the depths of neighboring pixels—and darkening them to simulate the decreased illumination from the points’ environment." ContentLicense="CC BY-SA 3.0" />
  <row Id="1146" PostHistoryTypeId="5" PostId="383" RevisionGUID="53604b5f-ae76-47df-afcd-a79ae7cfe526" CreationDate="2015-08-31T22:01:39.200" UserId="93" Comment="Trying to restore formatting " Text="This issue looks like standard shadow map acne artifacts. Additionally your's lighting equation is incomplete or wrong. Light shouldn't influence faces with normals facing away from it. This also means that with a proper equation the &quot;dark&quot; side of the sphere shouldn't have any acne artifacts.&#xD;&#xA;&#xD;&#xA;There are three sources of acne artifacts:&#xD;&#xA;&#xD;&#xA; - First acne source is shadow map precision. Make sure that near and far planes of shadow casting light are as tight as possible. All objects before the near plane can be pancaked, as their exact depth isn't important.&#xD;&#xA; - Second acne source is shadow map resolution. For a directional light you should be doing cascaded shadow maps with at least 3 1024x1012 cascades for ~100-200m of shadow distance. It's hard to cover similar shadow distance with one shadow map with uniform projection.&#xD;&#xA; - Third acne source is wide shadow map filter like PCF, as using a single depth depth comparison value across a wide kernel is insufficient. There are many methods to fix it, but none of them is robust.&#xD;&#xA;&#xD;&#xA;To sum up, a tight frustum with a few cascades and some bias tweaking is enough to get the general case working (directional light). Start tweaking by disabling shadow filtering and tweak for filtering only when basic shadow maps are robust enough. &#xD;&#xA;&#xD;&#xA;Additionally apart from the constant depth bias (which you currently use) you should also add slope depth bias and max slope depth bias. Both can be be implemented either as render state or as shader code during shadowmap rendering. Slope depth bias is simply a magic bias value scaled by dot( normal, lightDir ).&#xD;&#xA;&#xD;&#xA;There are some additional interesting methods and most of them are implemented in the excellent demo: [Matt Pettineo - &quot;A sampling of shadow techniques&quot;].&#xD;&#xA;&#xD;&#xA; - Flip culling during shadow map rendering (trades acne for Peter panning).&#xD;&#xA; - Normal offset shadow mapping does wonders for bias issues, but requires to have vertex normals around during shading.&#xD;&#xA; - Variance based methods (ESM, VSM, EVSM) completely remove bias issues, but have other drawbacks (light leaking and/or performance issues).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Matt Pettineo - &quot;A sampling of shadow techniques&quot;]: https://mynameismjp.wordpress.com/2013/09/10/shadow-maps/" ContentLicense="CC BY-SA 3.0" />
  <row Id="1147" PostHistoryTypeId="2" PostId="386" RevisionGUID="8450cf46-b46b-4d82-b34e-80f2e6032f73" CreationDate="2015-08-31T22:03:38.707" UserId="511" Text="Whether it's a tile based GPU or not doesn't really affect the texture cache architecture.&#xD;&#xA;&#xD;&#xA;The memory layout of texture look like some flavor of https://en.wikipedia.org/wiki/Hilbert_curve in all GPUs.&#xD;&#xA;&#xD;&#xA;As a result, it's more efficient to render triangle that are close to isosceles triangles because GPU memory system fetch cache lines of texels.&#xD;&#xA;&#xD;&#xA;So obviously on tile borders, it may happen that you have to fetch twice texels which has a small cost as tile borders are only &quot;few&quot; pixels.&#xD;&#xA;&#xD;&#xA;Arguably desktop GPUs behave identically to tile based GPUs as experiments such as the following demonstrate:&#xD;&#xA;http://www.g-truc.net/post-0597.html&#xD;&#xA;&#xD;&#xA;The size of the tiles differ but both architecture actually process fragments into a hierarchy of tiles of different sizes.&#xD;&#xA;&#xD;&#xA;When in code to tile based GPUs my first recommendations in to always have in mind:&#xD;&#xA;1/ Don't which framebuffer objects if you really don't need it.&#xD;&#xA;2/ &quot;when in bind a new framebuffer object, should I save the contain of my current framebuffer, if not discard, should I load the contain of the new framebuffer object, if not clear.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1150" PostHistoryTypeId="2" PostId="387" RevisionGUID="3a676f5b-6a6b-43ed-b798-e0321e72d14f" CreationDate="2015-08-31T22:59:35.523" UserId="480" Text="[Ambient occlusion][1] &quot;is a shading and rendering technique used to calculate **how exposed** each point in a scene is **to ambient lighting**.&#xD;&#xA;&#xD;&#xA;Ambient lighting is regarding to http://computergraphics.stackexchange.com/questions/375/what-is-ambient-lighting/:&#xD;&#xA;&gt; ... lighting to be constant and independent from position: that's ambient&#xD;&#xA;&gt; lighting.&#xD;&#xA;&#xD;&#xA;If ambient lighting has no fixed position, how can points then be more or less **exposed** to it? Ambient lighting is &quot;[shining by a constant amount in all directions.][2]&quot; So if the light is coming from **all directions**, every point should be exposed by **the same factor** to the ambient lighting.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ambient_occlusion&#xD;&#xA;  [2]: http://computergraphics.stackexchange.com/a/380/480" ContentLicense="CC BY-SA 3.0" />
  <row Id="1151" PostHistoryTypeId="1" PostId="387" RevisionGUID="3a676f5b-6a6b-43ed-b798-e0321e72d14f" CreationDate="2015-08-31T22:59:35.523" UserId="480" Text="What is ambient occlusion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1152" PostHistoryTypeId="3" PostId="387" RevisionGUID="3a676f5b-6a6b-43ed-b798-e0321e72d14f" CreationDate="2015-08-31T22:59:35.523" UserId="480" Text="|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1153" PostHistoryTypeId="5" PostId="385" RevisionGUID="cd7b1de2-44c2-4b43-8510-593f42a1ac2d" CreationDate="2015-08-31T23:07:44.043" UserId="506" Comment="added 46 characters in body" Text="As Alan and trichoplax mention in the comments, the effect that ambient occlusion simulates is not the occlusion of a surface from the camera but the surface’s occlusion from its surroundings.&#xD;&#xA;&#xD;&#xA;Think of it this way: say you have even illumination coming from every direction, so that the total incoming light at any point sums up to a value of 1. If you place a flat plane in that environment and look at one side of it, that side is going to receive 50% of that illumination, or 0.5, because the other half is blocked by the plane itself. In other words, any point on the plane’s surface can only “see” the light coming from half of the environment, so it’s half as brightly illuminated. If you fold that plane towards your viewpoint (a “valley” fold), then you decrease the incoming illumination to that side of the plane further, to some value below 0.5, because, again, each point on the plane “sees” a bit less of the light coming from the surroundings.&#xD;&#xA;&#xD;&#xA;Screen-space ambient occlusion works more or less by looking for these “folds”—areas where the depth changes sharply, as defined by comparing the depths of neighboring pixels—and darkening them to simulate the decreased illumination from the points’ environment." ContentLicense="CC BY-SA 3.0" />
  <row Id="1154" PostHistoryTypeId="2" PostId="388" RevisionGUID="9cd3533a-3daf-4049-975c-c3518eeb661a" CreationDate="2015-08-31T23:13:35.870" UserId="480" Text="[Occlusion][1] &quot;is the effect of one object in a 3-D space blocking another object from view.&quot;&#xD;&#xA;&#xD;&#xA;With this definiton in mind I cannot understand sentences like:&#xD;&#xA;&#xD;&#xA;&gt; The interior of a tube is typically **more occluded** (and hence darker)&#xD;&#xA;&gt; than the exposed outer surfaces, and the deeper you go inside the&#xD;&#xA;&gt; tube, **the more occluded** (and darker) the lighting becomes.&#xD;&#xA;&#xD;&#xA;Occlusion is for me a question of **yes or no**. Yes an object is in front of another, or no.&#xD;&#xA;&#xD;&#xA;So how can some points be **more** or **less** occluded then others? I think I need another definiton for occlusion. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://whatis.techtarget.com/definition/occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="1155" PostHistoryTypeId="1" PostId="388" RevisionGUID="9cd3533a-3daf-4049-975c-c3518eeb661a" CreationDate="2015-08-31T23:13:35.870" UserId="480" Text="What is occlusion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1156" PostHistoryTypeId="3" PostId="388" RevisionGUID="9cd3533a-3daf-4049-975c-c3518eeb661a" CreationDate="2015-08-31T23:13:35.870" UserId="480" Text="|occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1157" PostHistoryTypeId="5" PostId="388" RevisionGUID="e2b5ed6f-27d4-4d9e-b6e1-480037b3bf7e" CreationDate="2015-08-31T23:32:18.633" UserId="480" Comment="added 7 characters in body" Text="[Occlusion][1] &quot;is the effect of one object in a 3-D space blocking another object from view.&quot;&#xD;&#xA;&#xD;&#xA;With this definiton in mind I cannot understand sentences like:&#xD;&#xA;&#xD;&#xA;&gt; The interior of a tube is typically **more occluded** (and hence darker)&#xD;&#xA;&gt; than the exposed outer surfaces, and the deeper you go inside the&#xD;&#xA;&gt; tube, **the more occluded** (and darker) the lighting becomes.&#xD;&#xA;&#xD;&#xA;Occlusion is for me a question of **yes or no**. Yes an object/point is in front of another, or not.&#xD;&#xA;&#xD;&#xA;So how can some points be **more** or **less** occluded then others? I think I need another definiton for occlusion. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://whatis.techtarget.com/definition/occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="1158" PostHistoryTypeId="2" PostId="389" RevisionGUID="8a1566f6-08a9-4cd4-b185-77fd7be8d39e" CreationDate="2015-08-31T23:39:22.343" UserId="231" Text="This quote sounds like it may relate to [ambient occlusion], which is the shielding of a surface from the light approaching from all angles. Direct lighting requires that the light source have a straight line route to the surface being lit, whereas ambient lighting is the result of light approaching along many different paths.&#xD;&#xA;&#xD;&#xA;Imagine the whole of a cloudy sky as a light source. Each point on a surface is lit according to the proportion of the sky that can directly light it. The floor next to a wall might only be able to be lit by half the sky, so will be half as bright. In this situation you could say that half of the sky is occluded, leaving only half to light the surface.&#xD;&#xA;&#xD;&#xA;Similarly with a tube. At the entrance of the tube, 50% of the sky may be able to light it. Further inside the tube only the small patch of sky visible through the end of the tube can light it, and that patch becomes smaller the further you go into the tube. The lighting in the tube therefore diminishes the further you go in.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [ambient occlusion]: https://en.wikipedia.org/wiki/Ambient_occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="1159" PostHistoryTypeId="6" PostId="387" RevisionGUID="c1d8a0c3-d2c8-46b3-89b0-6d991881f377" CreationDate="2015-08-31T23:45:58.230" UserId="480" Comment="edited tags" Text="|shading|ambient-occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1161" PostHistoryTypeId="2" PostId="390" RevisionGUID="d30ebcf9-452c-4643-b975-4585a93c4aff" CreationDate="2015-08-31T23:55:57.460" UserId="231" Text="Your point is correct when applied to [ambient lighting] as an approximation technique. This crude approach does indeed give the same lighting level to all surfaces regardless of their surroundings.&#xD;&#xA;&#xD;&#xA;However, [ambient occlusion] is a different (less crude) approach, that models how the light levels in a real scene vary depending on how much reflected light can reach a surface. The confusion is due to two very different approaches having similar names.&#xD;&#xA;&#xD;&#xA;Ambient occlusion is a much better approximation of what in real life is described as ambient light - light that arrives from the background rather than directly from a light source.&#xD;&#xA;&#xD;&#xA;&gt; If ambient lighting has no fixed position, how can points then be more or less exposed to it?&#xD;&#xA;&#xD;&#xA;When used in the context of ambient occlusion, the term &quot;ambient lighting&quot; still means background light approximated as being the same in all directions, but the surface is lit based on how many of those directions are not occluded by objects in the scene.&#xD;&#xA;&#xD;&#xA;This gives subtly varying light levels that give much more realistic images than with a single level of ambient lighting. This gives the effects seen in real life such as the corners of a room being slightly darker than elsewhere.&#xD;&#xA;&#xD;&#xA;  [ambient lighting]: https://en.wikipedia.org/wiki/Shading#Ambient_lighting&#xD;&#xA;&#xD;&#xA;  [ambient occlusion]: https://en.wikipedia.org/wiki/Ambient_occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="1162" PostHistoryTypeId="2" PostId="391" RevisionGUID="1cbc896c-f206-43db-85dc-3a5c231e2056" CreationDate="2015-09-01T00:39:04.890" UserId="482" Text="What are Affine Tranformations? Do they apply just to points or to other shapes as well? What does it mean that they can be &quot;composed&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1163" PostHistoryTypeId="1" PostId="391" RevisionGUID="1cbc896c-f206-43db-85dc-3a5c231e2056" CreationDate="2015-09-01T00:39:04.890" UserId="482" Text="What are Affine Transformations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1164" PostHistoryTypeId="3" PostId="391" RevisionGUID="1cbc896c-f206-43db-85dc-3a5c231e2056" CreationDate="2015-09-01T00:39:04.890" UserId="482" Text="|transformations|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1165" PostHistoryTypeId="2" PostId="392" RevisionGUID="aba3ce14-2d6f-4049-8d8b-af2d2e1a12e0" CreationDate="2015-09-01T00:39:04.890" UserId="482" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;    (x', y')  =  (x, y) * [a  b] + (e, f)&#xD;&#xA;                          [c  d]&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for producing a &quot;transformed&quot; coordinate pair (x', y') from the original pair (x, y) and a list of constants (a, b, c, d, e, f).&#xD;&#xA;&#xD;&#xA;    x' =  a*x + c*y + e&#xD;&#xA;    y' =  b*x + d*y + f&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operator over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;    (x', y', 1) =  (x, y, 1) * [a b 0]&#xD;&#xA;                               [c d 0]&#xD;&#xA;                               [e f 1]&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;    (x&quot;, y&quot;, 1) = ( (x, y, 1) * [a b 0] ) * [g h 0] &#xD;&#xA;                                [c d 0]     [i j 0]&#xD;&#xA;                                [e f 1]     [k m 1]&#xD;&#xA;&#xD;&#xA;                = (ax+cy+e, bx+dy+f, 1) * [g h 0]&#xD;&#xA;                                          [i j 0]&#xD;&#xA;                                          [k m 1]&#xD;&#xA;&#xD;&#xA;                = (g(ax+cy+e) + i(bx+dy+f) + k, &#xD;&#xA;                   h(ax+cy+e) + j(bx+dy+f) + m,&#xD;&#xA;                   1)&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * ( [a b 0] * [g h 0] )&#xD;&#xA;                                [c d 0]   [i j 0]&#xD;&#xA;                                [e f 1]   [k m 1]&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * [ag+bi   ah+bj   0]&#xD;&#xA;                              [cg+di   ch+dj   0]&#xD;&#xA;                              [eg+fi+k eh+fj+m 1]&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these.&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;    1 0 0&#xD;&#xA;    0 1 0&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;    Sx 0  0&#xD;&#xA;    0  Sy 0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    0  1  0&#xD;&#xA;    Tx Ty 1&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;    1  Qx 0&#xD;&#xA;    0  1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    Qy 1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;    cos -sin 0&#xD;&#xA;    sin  cos 0&#xD;&#xA;    0    0   1&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]" ContentLicense="CC BY-SA 3.0" />
  <row Id="1167" PostHistoryTypeId="2" PostId="393" RevisionGUID="75702cff-bb20-4703-bb9b-3d1eb39d37e1" CreationDate="2015-09-01T07:14:36.680" UserId="386" Text="Last time I see a lot of papers which operates on this words, i.e. *stochastic AA*, *temporal coherence* etc. What does that means? Can you provide examples with explanations in plain English?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1168" PostHistoryTypeId="1" PostId="393" RevisionGUID="75702cff-bb20-4703-bb9b-3d1eb39d37e1" CreationDate="2015-09-01T07:14:36.680" UserId="386" Text="What is the meaning of words 'stochastic', 'temporal' in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1169" PostHistoryTypeId="3" PostId="393" RevisionGUID="75702cff-bb20-4703-bb9b-3d1eb39d37e1" CreationDate="2015-09-01T07:14:36.680" UserId="386" Text="|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1170" PostHistoryTypeId="2" PostId="394" RevisionGUID="8d5decb7-7809-438c-a54c-7a193a8fe645" CreationDate="2015-09-01T07:48:57.517" UserId="38" Text="* Stochastic = Random. Stochastic AA, Anti-aliasing technique based on randomized sample distribution (as opposed to fixed sample pattern). &#xD;&#xA;   &#xD;&#xA;   Also see: [Monte Carlo Method](https://en.wikipedia.org/wiki/Monte_Carlo_method)&#xD;&#xA;&#xD;&#xA;* Temporal = depends on time. Temporal coherence, how consistent X is over time.&#xD;&#xA;&#xD;&#xA;    Typically you hear of temporal aliasing, temporal artefacts etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="1171" PostHistoryTypeId="2" PostId="395" RevisionGUID="e90c5a57-694d-45f2-a6b1-17256af3ef4b" CreationDate="2015-09-01T07:55:02.207" UserId="343" Text=" - A stochastic process is one where you gather your samples randomly. So stochastic AA is antialiasing where you gather multiple samples for the same pixel with small random changes.&#xD;&#xA; - Temporal refers to a process over time. Temporal coherence is for instance mentioned when you have no flickering artifacts, or aliasing that you see during movement. It means that frames are coherent in a certain time window.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1172" PostHistoryTypeId="2" PostId="396" RevisionGUID="1ec9cf8d-8e62-4beb-8e17-4565c86ff09f" CreationDate="2015-09-01T11:26:19.687" UserId="38" Text="Ambient light does not really exist, if we do not talk about cosmology. What we call ambient is just light form many secondary reflections.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: No ambient light (left) and ambient light (right). Both look artificial.&#xD;&#xA;&#xD;&#xA;We can approximate ambient light by a constant factor. But this looks slightly washed out as ambient light is not constant over the scene. To make the ambient look better we can use a trick. If we make a hemispherical probe for object coverage (occlusion), we get an estimate of how much the pixel lies inside a cavity. The less you live in cavity the more likely the ambient light is going to hit here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: By modulating the ambient light with local geometric occlusion we get a much nicer and realistic contribution of ambient light. Final color and contribution also tweaked slightly (right). Just plain ambient (left).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;NOTE: Ambient occlusion component is also used by other phenomena so it can also simulate dirt packing etc. In any case your NOT supposed to multiply ambient occlusion by everything. Quite many tutorials make this mistake. You should add the ambient occlusion to existing image, that is if you only estimate ambient light with it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b1FF5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/g57I5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1173" PostHistoryTypeId="2" PostId="397" RevisionGUID="eeb8f4f1-8f65-4cab-aeed-7c448ba20eda" CreationDate="2015-09-01T13:07:44.900" UserId="18" Text="Video noise is random and not correlated in time. I assume, the best method is using **wavelet denoise** in this case, right? If yes, how is wavelet denoise implemented for video? Is there something to consider in order to apply the calculation to the whole image sequence?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1174" PostHistoryTypeId="1" PostId="397" RevisionGUID="eeb8f4f1-8f65-4cab-aeed-7c448ba20eda" CreationDate="2015-09-01T13:07:44.900" UserId="18" Text="How to denoise video?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1175" PostHistoryTypeId="3" PostId="397" RevisionGUID="eeb8f4f1-8f65-4cab-aeed-7c448ba20eda" CreationDate="2015-09-01T13:07:44.900" UserId="18" Text="|image|denoise|video|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1176" PostHistoryTypeId="5" PostId="386" RevisionGUID="639184d3-c799-4edb-b40d-0f683b0b5c8d" CreationDate="2015-09-01T13:28:47.147" UserId="174" Comment="Improved the grammar, cleaned up the last paragraph" Text="Whether it's a tile based GPU or not doesn't really affect the texture cache architecture. The memory layout of texture will look like some flavor of [Hilbert curve](https://en.wikipedia.org/wiki/Hilbert_curve) in all GPUs.&#xD;&#xA;&#xD;&#xA;As a result, it's more efficient to render triangle that are close to isosceles triangles because GPU memory system fetches cache lines of texels.&#xD;&#xA;&#xD;&#xA;So obviously on tile borders, it may happen that you have to fetch texels twice. This has a small cost as tile borders are only &quot;few&quot; pixels.&#xD;&#xA;&#xD;&#xA;Arguably desktop GPUs behave identically to tile based GPUs as experiments such as the following demonstrate:&#xD;&#xA;http://www.g-truc.net/post-0597.html&#xD;&#xA;&#xD;&#xA;The size of the tiles differ but both architecture actually process fragments into a hierarchy of tiles of different sizes.&#xD;&#xA;&#xD;&#xA;When coding for tile based GPUs my recommendation is to always have in mind:&#xD;&#xA;&#xD;&#xA;1. Don't switch framebuffer objects unless you *really* need to.&#xD;&#xA;2. When binding a new framebuffer object, if you don't need to save the contents of the current framebuffer, discard it. If you're discarding contents but not loading new contents, then you should clear the framebuffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1177" PostHistoryTypeId="24" PostId="386" RevisionGUID="639184d3-c799-4edb-b40d-0f683b0b5c8d" CreationDate="2015-09-01T13:28:47.147" Comment="Proposed by 174 approved by -1 edit id of 45" ContentLicense="CC BY-SA 3.0" />
  <row Id="1178" PostHistoryTypeId="5" PostId="386" RevisionGUID="ecd6309e-1930-4582-b0d6-da2a8fd6b368" CreationDate="2015-09-01T13:28:47.147" UserId="231" Comment="Improved the grammar, cleaned up the last paragraph" Text="Whether it's a tile based GPU or not doesn't really affect the texture cache architecture. The memory layout of texture will look like some flavor of [Hilbert curve](https://en.wikipedia.org/wiki/Hilbert_curve) in all GPUs.&#xD;&#xA;&#xD;&#xA;As a result, it's more efficient to render triangles that are close to isosceles triangles because GPU memory system fetches cache lines of texels.&#xD;&#xA;&#xD;&#xA;So obviously on tile borders, it may happen that you have to fetch texels twice. This has a small cost as tile borders are only &quot;few&quot; pixels.&#xD;&#xA;&#xD;&#xA;Arguably desktop GPUs behave identically to tile based GPUs as experiments such as the following demonstrate:&#xD;&#xA;http://www.g-truc.net/post-0597.html&#xD;&#xA;&#xD;&#xA;The size of the tiles differ but both architecture actually process fragments into a hierarchy of tiles of different sizes.&#xD;&#xA;&#xD;&#xA;When coding for tile based GPUs my recommendation is to always have in mind:&#xD;&#xA;&#xD;&#xA;1. Don't switch framebuffer objects unless you *really* need to.&#xD;&#xA;2. When binding a new framebuffer object, if you don't need to save the contents of the current framebuffer, discard it. If you're discarding contents but not loading new contents, then you should clear the framebuffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1179" PostHistoryTypeId="2" PostId="398" RevisionGUID="14079338-5ead-4720-88d4-47dd1281861f" CreationDate="2015-09-01T16:16:10.817" UserId="523" Text="&gt; Is there a similarly fast way to draw antialiased lines?&#xD;&#xA;&#xD;&#xA;No, because by definition an anti-aliased line touches more pixels.  Such algorithms will be slower.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In a software rasterizer, the ubiquitous way to draw anti-aliased lines is [Xiaolin Wu's line algorithm](https://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm).  It's not hard to implement, and anyway there's unusually high-quality pseudocode at that link.&#xD;&#xA;&#xD;&#xA;In a hardware raster pipe, the line primitive is expanded to a screen-space quad by the default (or user-provided) geometry shader, and then drawn as two triangles, which can then be anti-aliased in the usual ways.&#xD;&#xA;&#xD;&#xA;In a raytracer, there are a variety of options.  It's worth thinking about how you actually want to draw a 1D object.  Maybe as a cylinder (woo shadows!).  Note that this introduces issues of perspective/foreshortening which may (or may not) be what you want.  There isn't a clear generalization.  Then, obviously, whatever you do, you just supersample it." ContentLicense="CC BY-SA 3.0" />
  <row Id="1180" PostHistoryTypeId="5" PostId="297" RevisionGUID="6352bad7-94fc-43e5-ad89-cf77b17fc896" CreationDate="2015-09-01T16:25:55.340" UserId="56" Comment="Added unrefracted image and shadertoy link" Text="When I implement Beer's law (color absorption over distance through an object), it never looks very good for some reason.&#xD;&#xA;&#xD;&#xA;When i have the color behind the object, i calculate the adjusted color like this:&#xD;&#xA;&#xD;&#xA;    const vec3 c_absorb = vec3(0.2,1.8,1.8);&#xD;&#xA;    vec3 absorb = exp(-c_absorb * (distanceInObject));&#xD;&#xA;    behindColor *= absorb;&#xD;&#xA;&#xD;&#xA;That will give me something that looks like this (note a little bit of refraction applied):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here it is without refraction:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that this is implemented as a shadertoy here: https://www.shadertoy.com/view/4lXSDf&#xD;&#xA;&#xD;&#xA;That fulfills the description of what Beer's law does, but it doesn't look very good, not when compared to shots like this:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Specular highlights aside, I'm trying to figure out the difference.  Could it just be that my geometry is too simple to really show it off very well? Or am i implementing it incorrectly?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XQbjV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gOPZn.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/nchoX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1181" PostHistoryTypeId="2" PostId="399" RevisionGUID="b672f69b-9cf5-4ce6-a8e7-d773c46154f8" CreationDate="2015-09-01T16:29:40.593" UserId="523" Text="As you have probably observed, in general, you cannot solve in closed-form the equations for ray trajectories around multiple distorting objects.&#xD;&#xA;&#xD;&#xA;The standard approach for such things is just to discretize it.  This looks like Eulerian integration.  Just step your ray a little bit toward the object, calculate gravity from all sources and bend it, then step it more, und so weiter.  This is called *raymarching*.&#xD;&#xA;&#xD;&#xA;Since you're interested in problems on an astrophysical scale, you can assume the ray is linear far enough away from the object, with minimal error.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here's a scene I rendered a while ago using a homebrew photonmapper (no QMC) using this raymarching technique.&#xD;&#xA;&#xD;&#xA;I present: relativistic photon mapping: black hole in a Cornell box!&#xD;&#xA;[![black hole in a Cornell box][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0rxaX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1182" PostHistoryTypeId="33" PostId="297" RevisionGUID="a21c7efb-484b-4e84-be5e-444282fadeb1" CreationDate="2015-09-01T17:16:31.690" UserId="56" Comment="9" />
  <row Id="1183" PostHistoryTypeId="2" PostId="400" RevisionGUID="4b136af4-27f3-4e4b-917c-0a12bd35989a" CreationDate="2015-09-01T18:18:11.607" UserId="197" Text="I have a couple of compute shaders that need to be executed in a certain order and whose outputs depend on previous inputs. Ideally, I'll never need to copy a buffer client-side and do all of my work on the GPU.&#xD;&#xA;&#xD;&#xA;Consider I have two compute shaders compiled and linked as `program_one` and `program_two`. Suppose I also have a `GL_SHADER_STORAGE_BUFFER` that contains the data that is written to by `program_one` and read by `program_two`. Can I simply do the following:&#xD;&#xA;&#xD;&#xA;    glUseProgram(program_one);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer);&#xD;&#xA;    glDispatchCompute(16, 16, 1);&#xD;&#xA;&#xD;&#xA;    glUseProgram(program_two);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer);&#xD;&#xA;    glDispatchCompute(16, 16, 1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is it guaranteed that all invocations of the first compute shader will finish before any invocations of the second (to avoid data races between reading and writing `buffer`)? If not, how do I synchronize them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1184" PostHistoryTypeId="1" PostId="400" RevisionGUID="4b136af4-27f3-4e4b-917c-0a12bd35989a" CreationDate="2015-09-01T18:18:11.607" UserId="197" Text="Synchronizing successive OpenGL Compute Shader invocations" ContentLicense="CC BY-SA 3.0" />
  <row Id="1185" PostHistoryTypeId="3" PostId="400" RevisionGUID="4b136af4-27f3-4e4b-917c-0a12bd35989a" CreationDate="2015-09-01T18:18:11.607" UserId="197" Text="|opengl|compute-shader|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1186" PostHistoryTypeId="2" PostId="401" RevisionGUID="5029d9f2-8fcf-4dd2-b791-c2ff1c73246f" CreationDate="2015-09-01T19:15:45.790" UserId="56" Text="Elaboration on temporal solve:&#xD;&#xA;&#xD;&#xA;I don't have much concrete info for you, but I'm drawing from the idea of &quot;temporal anti aliasing&quot;.&#xD;&#xA;&#xD;&#xA;Basically, if a camera was stationary, you could average pixel values over the last N frames, possibly using harmonic mean or something else like that to help filter out spikes.  The result would be a cleaner, less noisy, more correct image.&#xD;&#xA;&#xD;&#xA;But not all cameras (or objects!) are stationary, so what then?  Well, if you have some way of identifying where a pixel this frame matches a pixel on the previous N frames, you could average them in the same way.  If a current pixel has no matching previous pixel (due to something previously occluding becoming visible) you just show the raw current value.&#xD;&#xA;&#xD;&#xA;Games use this for antialiasing by simulating MSAA over time, but they have the benefit of per pixel motion vectors as well as the current and previous camera matrix, so it's a lot harder in your situation!" ContentLicense="CC BY-SA 3.0" />
  <row Id="1187" PostHistoryTypeId="5" PostId="401" RevisionGUID="9976ed3f-74dd-48fb-82ea-2eda6a39f762" CreationDate="2015-09-01T20:03:34.453" UserId="56" Comment="added 10 characters in body" Text="Elaboration on temporal solve:&#xD;&#xA;&#xD;&#xA;I don't have much concrete info for you, but I'm drawing from the idea of &quot;temporal anti aliasing&quot;.&#xD;&#xA;&#xD;&#xA;Basically, if a camera was stationary, you could average pixel values over the last N frames, possibly using harmonic mean or something else like that to help filter out spikes.  The result would be a cleaner, less noisy, more correct image.&#xD;&#xA;&#xD;&#xA;But not all cameras (or objects!) are stationary, so what then?  Well, if you have some way of identifying where a pixel this frame matches a pixel on the previous N frames, you could average them in the same way.  If a current pixel has no matching previous pixel (due to something previously occluding becoming visible) you just show the raw current value.&#xD;&#xA;&#xD;&#xA;Games use this for antialiasing by simulating super sampling over time, but they have the benefit of per pixel motion vectors as well as the current and previous camera matrix, so it's a lot harder in your situation!" ContentLicense="CC BY-SA 3.0" />
  <row Id="1188" PostHistoryTypeId="2" PostId="402" RevisionGUID="b8c7e63a-aaa8-451a-a454-2d87afe04877" CreationDate="2015-09-01T20:07:25.123" UserId="528" Text="No it is not guaranteed, since the OpenGL specification allows that two Compute Shader run concurrently or even in different order.&#xD;&#xA;&#xD;&#xA;You need to call `glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)` before the second `glDispatchCompute` to ensure visibility of the writes from `program_one`.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;[From the OpenGL.org wiki article on the memory model][1]:&#xD;&#xA;&gt; [...] invocations between stages may be executed in any order. **This includes invocations launched by different rendering commands.** While it is perhaps unlikely that two vertex shaders from different rendering operations could be running at the same time, it is also possible, so OpenGL provides **no guarantees**.&#xD;&#xA;&#xD;&#xA;[From the Opengl.org wiki article on Shader Storage Buffer][2]:&#xD;&#xA;&gt; SSBOs reads and writes use incoherent memory accesses, so they need the appropriate barriers, just as Image Load Store operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Memory_Model&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="1189" PostHistoryTypeId="5" PostId="386" RevisionGUID="f087b7df-37ce-4c67-8aa1-3bcad8c023a4" CreationDate="2015-09-01T23:14:12.020" UserId="511" Comment="deleted 7 characters in body" Text="Whether it's a tile based GPU or not doesn't really affect the texture cache architecture. The memory layout of texture will look like some flavor of [Hilbert curve](https://en.wikipedia.org/wiki/Hilbert_curve) in all GPUs.&#xD;&#xA;&#xD;&#xA;As a result, it's more efficient to render triangles that are close to isosceles triangles because GPU memory system fetches cache lines of texels.&#xD;&#xA;&#xD;&#xA;So obviously on tile borders, it may happen that you have to fetch texels twice. This has a small cost as tile borders are only &quot;few&quot; pixels.&#xD;&#xA;&#xD;&#xA;Arguably desktop GPUs behave identically to tile based GPUs as experiments such as the following demonstrate:&#xD;&#xA;http://www.g-truc.net/post-0597.html&#xD;&#xA;&#xD;&#xA;The size of the tiles differ but both architecture actually process fragments into a hierarchy of tiles of different sizes.&#xD;&#xA;&#xD;&#xA;When coding for tile based GPUs my recommendation is to always have in mind:&#xD;&#xA;&#xD;&#xA;1. Don't switch framebuffer objects unless you *really* need to.&#xD;&#xA;2. When binding a new framebuffer object, if you don't need to save the content of the current framebuffer, discard it. If don't want to load content of the new framebuffer, then you should clear the framebuffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1192" PostHistoryTypeId="2" PostId="403" RevisionGUID="8275d690-ea96-47ca-ba2d-a925b6eb0482" CreationDate="2015-09-02T01:54:45.520" UserId="523" Text="It sounds like you're trying to do adaptive subdivision on the surface of a hemisphere.&#xD;&#xA;&#xD;&#xA;This has indeed been tried before, although perhaps not in the exact way you're thinking.  Usually for hemispheric integration, people use some well-distributed, pre-defined sampling density over the hemisphere and forget about adaptive subdivision.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;But you may be missing the point.&#xD;&#xA;&#xD;&#xA;The whole idea of doing such things is to get a better estimate of the integral.  But it's not the integral over the hemisphere you care about.  You're integrating over the pixel to get AA, over the aperture to get depth-of-field, over the lights to get soft-shadowing, over the hemisphere to get GI, over time to get motion blur, over wavelength to get dispersion, and so on.  You're integrating over all that.  This is an absurdly high-dimensional space, and decades of development have shown that you need to be exploring it not more carefully, but _faster_.  That is, you get better results from breadth, not depth.&#xD;&#xA;&#xD;&#xA;All very abstract.&#xD;&#xA;&#xD;&#xA;The point is this: you don't want to sample over the hemisphere with lots of samples.  You want to sample over your hemisphere with _one_ sample and then _move on_.  This is called path tracing.  It differs from ray tracing in that the maximum width of the ray tree is 1 (or maybe 2).&#xD;&#xA;&#xD;&#xA;The key insight is that if your random samples are well-distributed with respect to all dimensions, other rays will &quot;fill-in&quot; the rest of your missing tree.&#xD;&#xA;&#xD;&#xA;For an intuitive example: say you're doing 4x AA.  So you shoot four rays through a pixel.  Probably, they hit in very similar points (creating similar reflectance hemispheres).  Then, they each shoot exactly one recursive ray.  But, since the four hemispheres are in almost the same place, the recursive rays (kindof) count for _all_ the hemispheres.  So each of the four paths gets some of the benefit of the other three.&#xD;&#xA;&#xD;&#xA;That's sortof handwavy math, but since each path is actually independent of the others, and the color you get is an unbiased estimate of the entire scene's illumination, averaging them together is unbiased.  It just converges much faster in practice.&#xD;&#xA;&#xD;&#xA;Obviously, if a cheap estimate of the hemisphere's integral is available, you can just use that--this is preintegration (cone tracing, etc.), importance sampling (next event estimation, light sampling), or better paths (BDPT, photon mapping)--but for a simple approach, it's basically always better to use path tracing instead of stochastic ray tracing.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;Also `matt` -&gt; `matte` (or `mat`, in a pinch).  It's a French loanword, not a person's name, and I don't care what the American dictionaries say.&lt;/sub&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1193" PostHistoryTypeId="2" PostId="404" RevisionGUID="02434ae9-2943-419d-b26b-8bb64773fc78" CreationDate="2015-09-02T01:59:37.613" UserId="523" Text="The answer depends on what you mean.  Modern hardware (e.g. with bindless textures) really doesn't care too much how many textures are &quot;bound&quot;.  The real question is *how many you use*.&#xD;&#xA;&#xD;&#xA;Textures generally store data in a cache-friendly way (a Morton curve, I believe).  If you use more textures, you'll get more cache misses, since now the textures compete with each other for space.&#xD;&#xA;&#xD;&#xA;This really just comes down to the well-known, old shader programming heuristic: texture taps are slow; don't use too many." ContentLicense="CC BY-SA 3.0" />
  <row Id="1194" PostHistoryTypeId="5" PostId="392" RevisionGUID="25742321-1a98-4370-b673-fd9223c6240a" CreationDate="2015-09-02T02:26:47.510" UserId="482" Comment="add images" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;    (x', y')  =  (x, y) * [a  b] + (e, f)&#xD;&#xA;                          [c  d]&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for producing a &quot;transformed&quot; coordinate pair (x', y') from the original pair (x, y) and a list of constants (a, b, c, d, e, f).&#xD;&#xA;&#xD;&#xA;    x' =  a*x + c*y + e&#xD;&#xA;    y' =  b*x + d*y + f&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operator over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;    (x', y', 1) =  (x, y, 1) * [a b 0]&#xD;&#xA;                               [c d 0]&#xD;&#xA;                               [e f 1]&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;    (x&quot;, y&quot;, 1) = ( (x, y, 1) * [a b 0] ) * [g h 0] &#xD;&#xA;                                [c d 0]     [i j 0]&#xD;&#xA;                                [e f 1]     [k m 1]&#xD;&#xA;&#xD;&#xA;                = (ax+cy+e, bx+dy+f, 1) * [g h 0]&#xD;&#xA;                                          [i j 0]&#xD;&#xA;                                          [k m 1]&#xD;&#xA;&#xD;&#xA;                = (g(ax+cy+e) + i(bx+dy+f) + k, &#xD;&#xA;                   h(ax+cy+e) + j(bx+dy+f) + m,&#xD;&#xA;                   1)&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * ( [a b 0] * [g h 0] )&#xD;&#xA;                                [c d 0]   [i j 0]&#xD;&#xA;                                [e f 1]   [k m 1]&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * [ag+bi   ah+bj   0]&#xD;&#xA;                              [cg+di   ch+dj   0]&#xD;&#xA;                              [eg+fi+k eh+fj+m 1]&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these.&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;    1 0 0&#xD;&#xA;    0 1 0&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;    Sx 0  0&#xD;&#xA;    0  Sy 0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    0  1  0&#xD;&#xA;    Tx Ty 1&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;    1  Qx 0&#xD;&#xA;    0  1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    Qy 1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;    cos -sin 0&#xD;&#xA;    sin  cos 0&#xD;&#xA;    0    0   1&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1196" PostHistoryTypeId="5" PostId="392" RevisionGUID="d4404f9d-2988-4119-91b1-e89acb500c14" CreationDate="2015-09-02T02:50:42.237" UserId="482" Comment="applicable to other shapes" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;    (x', y')  =  (x, y) * [a  b] + (e, f)&#xD;&#xA;                          [c  d]&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for producing a &quot;transformed&quot; coordinate pair (x', y') from the original pair (x, y) and a list of constants (a, b, c, d, e, f).&#xD;&#xA;&#xD;&#xA;    x' =  a*x + c*y + e&#xD;&#xA;    y' =  b*x + d*y + f&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;    (x', y', 1) =  (x, y, 1) * [a b 0]&#xD;&#xA;                               [c d 0]&#xD;&#xA;                               [e f 1]&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;    (x&quot;, y&quot;, 1) = ( (x, y, 1) * [a b 0] ) * [g h 0] &#xD;&#xA;                                [c d 0]     [i j 0]&#xD;&#xA;                                [e f 1]     [k m 1]&#xD;&#xA;&#xD;&#xA;                = (ax+cy+e, bx+dy+f, 1) * [g h 0]&#xD;&#xA;                                          [i j 0]&#xD;&#xA;                                          [k m 1]&#xD;&#xA;&#xD;&#xA;                = (g(ax+cy+e) + i(bx+dy+f) + k, &#xD;&#xA;                   h(ax+cy+e) + j(bx+dy+f) + m,&#xD;&#xA;                   1)&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * ( [a b 0] * [g h 0] )&#xD;&#xA;                                [c d 0]   [i j 0]&#xD;&#xA;                                [e f 1]   [k m 1]&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * [ag+bi   ah+bj   0]&#xD;&#xA;                              [cg+di   ch+dj   0]&#xD;&#xA;                              [eg+fi+k eh+fj+m 1]&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these.&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;    1 0 0&#xD;&#xA;    0 1 0&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;    Sx 0  0&#xD;&#xA;    0  Sy 0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    0  1  0&#xD;&#xA;    Tx Ty 1&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;    1  Qx 0&#xD;&#xA;    0  1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    Qy 1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;    cos -sin 0&#xD;&#xA;    sin  cos 0&#xD;&#xA;    0    0   1&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1197" PostHistoryTypeId="5" PostId="392" RevisionGUID="f7127af3-c916-4e08-b746-031be6b78034" CreationDate="2015-09-02T03:02:27.983" UserId="482" Comment="clarity" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;    (x', y')  =  (x, y) * [a  b] + (e, f)&#xD;&#xA;                          [c  d]&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair (x', y') from the original pair (x, y) and a list of constants (a, b, c, d, e, f).&#xD;&#xA;&#xD;&#xA;    x' =  a*x + c*y + e&#xD;&#xA;    y' =  b*x + d*y + f&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;    (x', y', 1) =  (x, y, 1) * [a b 0]&#xD;&#xA;                               [c d 0]&#xD;&#xA;                               [e f 1]&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;    (x&quot;, y&quot;, 1) = ( (x, y, 1) * [a b 0] ) * [g h 0] &#xD;&#xA;                                [c d 0]     [i j 0]&#xD;&#xA;                                [e f 1]     [k m 1]&#xD;&#xA;&#xD;&#xA;                = (ax+cy+e, bx+dy+f, 1) * [g h 0]&#xD;&#xA;                                          [i j 0]&#xD;&#xA;                                          [k m 1]&#xD;&#xA;&#xD;&#xA;                = (g(ax+cy+e) + i(bx+dy+f) + k, &#xD;&#xA;                   h(ax+cy+e) + j(bx+dy+f) + m,&#xD;&#xA;                   1)&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * ( [a b 0] * [g h 0] )&#xD;&#xA;                                [c d 0]   [i j 0]&#xD;&#xA;                                [e f 1]   [k m 1]&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * [ag+bi   ah+bj   0]&#xD;&#xA;                              [cg+di   ch+dj   0]&#xD;&#xA;                              [eg+fi+k eh+fj+m 1]&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;    1 0 0&#xD;&#xA;    0 1 0&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;    Sx 0  0&#xD;&#xA;    0  Sy 0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    0  1  0&#xD;&#xA;    Tx Ty 1&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;    1  Qx 0&#xD;&#xA;    0  1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    Qy 1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;    cos -sin 0&#xD;&#xA;    sin  cos 0&#xD;&#xA;    0    0   1&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1199" PostHistoryTypeId="2" PostId="405" RevisionGUID="37610caf-6f76-4f3d-9c88-9ac4fd8a5412" CreationDate="2015-09-02T03:23:51.497" UserId="482" Text="In my answer about [Affine Transformations](http://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392) I made some little illustrations to help the explanation.&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Ltr0w.png)&#xD;&#xA;&#xD;&#xA;How did I do that??&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1200" PostHistoryTypeId="1" PostId="405" RevisionGUID="37610caf-6f76-4f3d-9c88-9ac4fd8a5412" CreationDate="2015-09-02T03:23:51.497" UserId="482" Text="How to produce simple 2D illustrations with PostScript?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1201" PostHistoryTypeId="3" PostId="405" RevisionGUID="37610caf-6f76-4f3d-9c88-9ac4fd8a5412" CreationDate="2015-09-02T03:23:51.497" UserId="482" Text="|postscript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1202" PostHistoryTypeId="2" PostId="406" RevisionGUID="868b9b33-5691-48da-96f9-72d1941e9432" CreationDate="2015-09-02T03:23:51.497" UserId="482" Text="I wrote a very small postscript program and then saved several copies under different names and edited each one to do each different task: scale, translate, rotate. For example, here's the basic one, `ident.ps` which does nothing to change the coordinates between the red drawing and the black drawing. I made the red lines a little larger and always draw it first, so the two show up nicely superposed and visible (IMO). I previewed with ghostscript with the vi (ex) command `:!gs %`.&#xD;&#xA;&#xD;&#xA;    %!&#xD;&#xA;    /axis {&#xD;&#xA;        currentpoint 4 { &#xD;&#xA;            2 copy moveto&#xD;&#xA;                50 0 lineto&#xD;&#xA;                90 rotate&#xD;&#xA;        } repeat pop pop &#xD;&#xA;    } def &#xD;&#xA;    /shape {&#xD;&#xA;        20 0 moveto&#xD;&#xA;        30 20 lineto&#xD;&#xA;        40 0 lineto&#xD;&#xA;        closepath&#xD;&#xA;    } def &#xD;&#xA;    &#xD;&#xA;    100 100 translate&#xD;&#xA;    &#xD;&#xA;    gsave&#xD;&#xA;    % do transform here&#xD;&#xA;    currentlinewidth 1.5 mul setlinewidth&#xD;&#xA;    1 0 0 setrgbcolor&#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    grestore&#xD;&#xA;    &#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    &#xD;&#xA;    showpage&#xD;&#xA;&#xD;&#xA;I then used the `ps2eps` command from `psutils` to calculate bounding-boxes automatically&#xD;&#xA;&#xD;&#xA;    $ ps2eps -f *.ps&#xD;&#xA;    Input files: ident.ps rotate.ps scale.ps skewx.ps skewy.ps translate.ps&#xD;&#xA;    Processing: ident.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file ident.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: rotate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file rotate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: scale.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 25 25 175 175&#xD;&#xA;    Creating output file scale.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewx.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 49 150 151&#xD;&#xA;    Creating output file skewx.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewy.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 49 50 151 150&#xD;&#xA;    Creating output file skewy.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: translate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 165 165&#xD;&#xA;    Creating output file translate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;&#xD;&#xA;And finally used imagemagick's `convert` command to produce cropped png images. (I didn't think of a quick way to automate this part.)&#xD;&#xA;&#xD;&#xA;    $ convert ident.eps ident.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert scale.eps scale.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert rotate.eps rotate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewx.eps skewx.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert translate.eps translate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewy.eps skewy.png&#xD;&#xA;&#xD;&#xA;Which produces PNGs, ready to upload.&#xD;&#xA;&#xD;&#xA;    $ ls -l *.png&#xD;&#xA;    -rw-r--r-- 1 josh None  587 Sep  1 21:16 ident.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1431 Sep  1 21:21 rotate.png&#xD;&#xA;    -rw-r--r-- 1 josh None  798 Sep  1 21:19 scale.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1133 Sep  1 21:22 skewx.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1197 Sep  1 21:23 skewy.png&#xD;&#xA;    -rw-r--r-- 1 josh None  756 Sep  1 21:23 translate.png&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/gyZCZ.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="1203" PostHistoryTypeId="5" PostId="406" RevisionGUID="8f6e29dc-edf6-4672-ba20-e56058b8a78a" CreationDate="2015-09-02T03:30:04.583" UserId="482" Comment="added 100 characters in body" Text="I wrote a very small postscript program and then saved several copies under different names and edited each one to do each different task: scale, translate, rotate. For example, here's the basic one, `ident.ps` which does nothing to change the coordinates between the red drawing and the black drawing. I made the red lines a little larger and always draw it first, so the two show up nicely superposed and visible (IMO). I previewed with ghostscript with the vi (ex) command `:!gs %`. ([all source files](https://groups.google.com/d/topic/comp.lang.postscript/m2QqV4QFFaM/discussion))&#xD;&#xA;&#xD;&#xA;    %!&#xD;&#xA;    /axis {&#xD;&#xA;        currentpoint 4 { &#xD;&#xA;            2 copy moveto&#xD;&#xA;                50 0 lineto&#xD;&#xA;                90 rotate&#xD;&#xA;        } repeat pop pop &#xD;&#xA;    } def &#xD;&#xA;    /shape {&#xD;&#xA;        20 0 moveto&#xD;&#xA;        30 20 lineto&#xD;&#xA;        40 0 lineto&#xD;&#xA;        closepath&#xD;&#xA;    } def &#xD;&#xA;    &#xD;&#xA;    100 100 translate&#xD;&#xA;    &#xD;&#xA;    gsave&#xD;&#xA;    % do transform here&#xD;&#xA;    currentlinewidth 1.5 mul setlinewidth&#xD;&#xA;    1 0 0 setrgbcolor&#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    grestore&#xD;&#xA;    &#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    &#xD;&#xA;    showpage&#xD;&#xA;&#xD;&#xA;I then used the `ps2eps` command from `psutils` to calculate bounding-boxes automatically&#xD;&#xA;&#xD;&#xA;    $ ps2eps -f *.ps&#xD;&#xA;    Input files: ident.ps rotate.ps scale.ps skewx.ps skewy.ps translate.ps&#xD;&#xA;    Processing: ident.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file ident.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: rotate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file rotate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: scale.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 25 25 175 175&#xD;&#xA;    Creating output file scale.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewx.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 49 150 151&#xD;&#xA;    Creating output file skewx.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewy.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 49 50 151 150&#xD;&#xA;    Creating output file skewy.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: translate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 165 165&#xD;&#xA;    Creating output file translate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;&#xD;&#xA;And finally used imagemagick's `convert` command to produce cropped png images. (I didn't think of a quick way to automate this part.)&#xD;&#xA;&#xD;&#xA;    $ convert ident.eps ident.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert scale.eps scale.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert rotate.eps rotate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewx.eps skewx.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert translate.eps translate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewy.eps skewy.png&#xD;&#xA;&#xD;&#xA;Which produces PNGs, ready to upload.&#xD;&#xA;&#xD;&#xA;    $ ls -l *.png&#xD;&#xA;    -rw-r--r-- 1 josh None  587 Sep  1 21:16 ident.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1431 Sep  1 21:21 rotate.png&#xD;&#xA;    -rw-r--r-- 1 josh None  798 Sep  1 21:19 scale.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1133 Sep  1 21:22 skewx.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1197 Sep  1 21:23 skewy.png&#xD;&#xA;    -rw-r--r-- 1 josh None  756 Sep  1 21:23 translate.png&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/gyZCZ.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="1204" PostHistoryTypeId="2" PostId="407" RevisionGUID="36fc178a-1cd5-4804-8afd-b17cb62ba178" CreationDate="2015-09-02T11:40:47.137" UserId="205" Text="I am currently working on some simple pixel shader in HLSL. I send to shader texture and i want to make it more colorful (something like in the picture below). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the picture 1 there is original texture. Picture 2 shows an effect that i want to achieve. Is there some mathematical formula to do that? My input is rgba value of each pixel.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvcUu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="1205" PostHistoryTypeId="1" PostId="407" RevisionGUID="36fc178a-1cd5-4804-8afd-b17cb62ba178" CreationDate="2015-09-02T11:40:47.137" UserId="205" Text="Changing image so it would look like through colorful glasses" ContentLicense="CC BY-SA 3.0" />
  <row Id="1206" PostHistoryTypeId="3" PostId="407" RevisionGUID="36fc178a-1cd5-4804-8afd-b17cb62ba178" CreationDate="2015-09-02T11:40:47.137" UserId="205" Text="|texture|algorithm|pixel-shader|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1207" PostHistoryTypeId="5" PostId="407" RevisionGUID="ab62a85b-f118-483d-a94b-e945a6c43403" CreationDate="2015-09-02T11:50:30.687" UserId="205" Comment="added 235 characters in body" Text="I am currently working on some simple pixel shader in HLSL. I send to shader texture and i want to make it more colorful (something like in the picture below). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the picture 1 there is original texture. Picture 2 shows an effect that i want to achieve. Is there some mathematical formula to do that? My input is rgba value of each pixel.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I'll try to write more concrete. &#xD;&#xA;&#xD;&#xA;Let's say i want to make that garden texture more red. I suppose that what i need to do is:&#xD;&#xA;OutputR = InputR * X,&#xD;&#xA;OuputG = InputG * Y,&#xD;&#xA;OutputB = InpputB * Z&#xD;&#xA;&#xD;&#xA;But ho do I find X, Y and Z?&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvcUu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="1208" PostHistoryTypeId="5" PostId="407" RevisionGUID="8e0a90c0-ecc7-4171-b76b-2528f7490b69" CreationDate="2015-09-02T11:51:23.007" UserId="205" Comment="added 235 characters in body" Text="I am currently working on some simple pixel shader in HLSL. I send to shader texture and i want to make it more colorful (something like in the picture below). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the picture 1 there is original texture. Picture 2 shows an effect that i want to achieve. Is there some mathematical formula to do that? My input is rgba value of each pixel.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I'll try to write more concrete. &#xD;&#xA;&#xD;&#xA;Let's say i want to make that garden texture more red. I suppose that what i need to do is:&#xD;&#xA;&#xD;&#xA;    OutputR = InputR * X,&#xD;&#xA;    &#xD;&#xA;    OuputG = InputG * Y,&#xD;&#xA;    &#xD;&#xA;    OutputB = InpputB * Z&#xD;&#xA;&#xD;&#xA;But how do I find X, Y and Z?&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvcUu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="1209" PostHistoryTypeId="2" PostId="408" RevisionGUID="7d070699-1d86-4444-bb45-130b41349491" CreationDate="2015-09-02T11:58:46.027" UserId="192" Text="Choose the color RGB of your colorful glasses and choose how transparent it is by choosing an alpha value A. Then composite the glasses on top of the input image." ContentLicense="CC BY-SA 3.0" />
  <row Id="1210" PostHistoryTypeId="5" PostId="408" RevisionGUID="286bba43-86b6-4b87-bc48-c6968e4e37f4" CreationDate="2015-09-02T12:01:17.487" UserId="192" Comment="added 60 characters in body" Text="Choose the color RGB of your colorful glasses and choose how transparent they are by choosing an alpha value A. Then [alpha composite](https://en.wikipedia.org/wiki/Alpha_compositing) the glasses on top of the input image:&#xD;&#xA;&#xD;&#xA;    OutputR = R * A + InputR * (1-A)&#xD;&#xA;    OutputG = G * A + InputG * (1-A)&#xD;&#xA;    OutputB = B * A + InputB * (1-A)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1212" PostHistoryTypeId="2" PostId="409" RevisionGUID="9958f605-154f-412d-97d8-d09d29713c6b" CreationDate="2015-09-02T12:40:38.147" UserId="209" Text="Another option, which I used a couple of decades ago (yikes!), is to use  [Toth's scheme from 1985][1] that employed interval arithmetic to narrow down the search space. IIRC, eventually it will resort to Newton-Rhapson but, again IIRC, I think it rarely required more than one or two steps to get to a good solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Though I haven't looked at it (well, apart from a quick glance) [Mitchell][2] has published some more recent work on ray tracing with interval maths.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p171-toth.pdf&#xD;&#xA;  [2]: http://mentallandscape.com/Papers_graphicsinterface90b.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="1213" PostHistoryTypeId="2" PostId="410" RevisionGUID="8b8f6623-765c-40dc-befb-53e5a6d1ac8f" CreationDate="2015-09-02T13:47:43.743" UserId="270" Text="(XYZ) can be the RGB colour you want to tint your scene by. For the above scene it can be a red colour (1.0, 0.0, 0.0) or something similar with a strong red component. &#xD;&#xA;&#xD;&#xA;Bear in mind that since you are applying the colour in a multiplicative way it will act as a filter suppressing original colour components. So if your scene is mostly green but you apply (i.e. multiply it with) a red filter (1,0,0) the resulting scene will be very dark.&#xD;&#xA;&#xD;&#xA;A trick you could potentially do is such cases is to desaturate the original scene and then multiply it by the tint colour. That way you will keep the overall image intensity and achieve the colour tint you require.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1215" PostHistoryTypeId="2" PostId="411" RevisionGUID="be4029fb-77ae-4de3-a816-45e5d35e911b" CreationDate="2015-09-02T15:02:06.727" UserId="540" Text="I've inherited a system which animates a humanoid avatar by loading various models and manually calculating transformations for each one. I'm in the process of porting part of this system to Three.js, and rather than port the manual calculations across I'd prefer to pre-compose an articulated model and let the engine handle the transformations.&#xD;&#xA;&#xD;&#xA;Is there any software which would let me import the existing models, define the bone hierarchy and the model which corresponds to each bone, and export a single articulated model in T-pose?&#xD;&#xA;&#xD;&#xA;For what it's worth, I have access to both Windows and Linux, and if really necessary I can probably obtain access to OS X." ContentLicense="CC BY-SA 3.0" />
  <row Id="1216" PostHistoryTypeId="1" PostId="411" RevisionGUID="be4029fb-77ae-4de3-a816-45e5d35e911b" CreationDate="2015-09-02T15:02:06.727" UserId="540" Text="Software to compose separate models into an articulated model?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1217" PostHistoryTypeId="3" PostId="411" RevisionGUID="be4029fb-77ae-4de3-a816-45e5d35e911b" CreationDate="2015-09-02T15:02:06.727" UserId="540" Text="|transformations|3d|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1218" PostHistoryTypeId="5" PostId="411" RevisionGUID="94db8181-08d8-41d9-871a-3f6e614208d6" CreationDate="2015-09-02T15:11:55.147" UserId="540" Comment="added 130 characters in body" Text="I've inherited a system which animates a humanoid avatar by loading various models and manually calculating transformations for each one. I'm in the process of porting part of this system to Three.js, and rather than port the manual calculations across I'd prefer to pre-compose an articulated model and let the engine handle the transformations.&#xD;&#xA;&#xD;&#xA;Is there any software which would let me import the existing models, define the bone hierarchy and the model which corresponds to each bone, and export a single articulated model in T-pose?&#xD;&#xA;&#xD;&#xA;For what it's worth, I have access to both Windows and Linux, and if really necessary I can probably obtain access to OS X. The original models are in FBX format, but I have managed to export them to Three.js files, so I could import from either format." ContentLicense="CC BY-SA 3.0" />
  <row Id="1219" PostHistoryTypeId="5" PostId="410" RevisionGUID="32183230-8d14-4452-bd7e-884dfbfe9a74" CreationDate="2015-09-02T15:53:01.653" UserId="270" Comment="edited body" Text="(XYZ) can be the RGB colour you want to tint your scene by. For the above scene it can be a red colour (1.0, 0.0, 0.0) or something similar with a strong red component. &#xD;&#xA;&#xD;&#xA;Bear in mind that since you are applying the colour in a multiplicative way it will act as a filter suppressing original colour components. So if your scene is mostly green but you apply (i.e. multiply it with) a red filter (1,0,0) the resulting scene will be very dark.&#xD;&#xA;&#xD;&#xA;A trick you could potentially do in such cases is to desaturate the original scene and then multiply it by the tint colour. That way you will keep the overall image intensity and achieve the colour tint you require.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1221" PostHistoryTypeId="5" PostId="405" RevisionGUID="c79971f1-f83d-468b-82c6-0053babd889e" CreationDate="2015-09-02T21:23:26.040" UserId="482" Comment="open up the domain and tighten-up the range" Text="In my answer about [Affine Transformations](http://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392) I made some little illustrations to help the explanation.&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Ltr0w.png)&#xD;&#xA;&#xD;&#xA;How do you make an upload-able PNG quickly which expresses a geometrical or mathematical idea?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1222" PostHistoryTypeId="4" PostId="405" RevisionGUID="c79971f1-f83d-468b-82c6-0053babd889e" CreationDate="2015-09-02T21:23:26.040" UserId="482" Comment="open up the domain and tighten-up the range" Text="How to produce simple 2D illustrations to accompany geometry answers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1223" PostHistoryTypeId="5" PostId="406" RevisionGUID="7c99b9dd-b862-4ac3-9fca-e844800b50d0" CreationDate="2015-09-02T21:26:53.980" UserId="482" Comment="Subtitle the answer with tools" Text="# PostScript+ps2eps+mogrify&#xD;&#xA;&#xD;&#xA;For the [Affine Transformations answer](http://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392), I wrote a very small postscript program and then saved several copies under different names and edited each one to do each different task: scale, translate, rotate. For example, here's the basic one, `ident.ps` which does nothing to change the coordinates between the red drawing and the black drawing. I made the red lines a little larger and always draw it first, so the two show up nicely superposed and visible (IMO). I previewed with ghostscript with the vi (ex) command `:!gs %`. ([all source files](https://groups.google.com/d/topic/comp.lang.postscript/m2QqV4QFFaM/discussion))&#xD;&#xA;&#xD;&#xA;    %!&#xD;&#xA;    /axis {&#xD;&#xA;        currentpoint 4 { &#xD;&#xA;            2 copy moveto&#xD;&#xA;                50 0 lineto&#xD;&#xA;                90 rotate&#xD;&#xA;        } repeat pop pop &#xD;&#xA;    } def &#xD;&#xA;    /shape {&#xD;&#xA;        20 0 moveto&#xD;&#xA;        30 20 lineto&#xD;&#xA;        40 0 lineto&#xD;&#xA;        closepath&#xD;&#xA;    } def &#xD;&#xA;    &#xD;&#xA;    100 100 translate&#xD;&#xA;    &#xD;&#xA;    gsave&#xD;&#xA;    % do transform here&#xD;&#xA;    currentlinewidth 1.5 mul setlinewidth&#xD;&#xA;    1 0 0 setrgbcolor&#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    grestore&#xD;&#xA;    &#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    &#xD;&#xA;    showpage&#xD;&#xA;&#xD;&#xA;I then used the `ps2eps` command from `psutils` to calculate bounding-boxes automatically&#xD;&#xA;&#xD;&#xA;    $ ps2eps -f *.ps&#xD;&#xA;    Input files: ident.ps rotate.ps scale.ps skewx.ps skewy.ps translate.ps&#xD;&#xA;    Processing: ident.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file ident.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: rotate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file rotate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: scale.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 25 25 175 175&#xD;&#xA;    Creating output file scale.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewx.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 49 150 151&#xD;&#xA;    Creating output file skewx.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewy.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 49 50 151 150&#xD;&#xA;    Creating output file skewy.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: translate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 165 165&#xD;&#xA;    Creating output file translate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;&#xD;&#xA;And finally used imagemagick's `convert` command to produce cropped png images. (I didn't think of a quick way to automate this part. *Edit:* as commented, this can be done with `mogrify -format png *.eps`. Thanks, joojaa!)&#xD;&#xA;&#xD;&#xA;    $ convert ident.eps ident.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert scale.eps scale.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert rotate.eps rotate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewx.eps skewx.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert translate.eps translate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewy.eps skewy.png&#xD;&#xA;&#xD;&#xA;Which produces PNGs, ready to upload.&#xD;&#xA;&#xD;&#xA;    $ ls -l *.png&#xD;&#xA;    -rw-r--r-- 1 josh None  587 Sep  1 21:16 ident.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1431 Sep  1 21:21 rotate.png&#xD;&#xA;    -rw-r--r-- 1 josh None  798 Sep  1 21:19 scale.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1133 Sep  1 21:22 skewx.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1197 Sep  1 21:23 skewy.png&#xD;&#xA;    -rw-r--r-- 1 josh None  756 Sep  1 21:23 translate.png&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/gyZCZ.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="1224" PostHistoryTypeId="2" PostId="412" RevisionGUID="85ecc82c-b4fc-4883-b4d2-7ad5fc29d810" CreationDate="2015-09-02T21:44:15.287" UserId="14" Text="You approach will work, and in general any square of size &lt; r/sqrt(2) will work fine because the invariant &quot;at most 1 point per square&quot; is valid. Extrapolating from your idea, it means that one should get the best reduction in area checks for infinitesimally small squares. But we don't want to do that, right?&#xD;&#xA;&#xD;&#xA;There are two reasons why r/sqrt(2) is usually better than r/2:&#xD;&#xA;&#xD;&#xA; 1. How much state do you want to manage? Each square can either be &quot;occupied&quot; or &quot;unoccupied&quot; and contains a pointer to its sample point (if any).&#xD;&#xA;&#xD;&#xA;    For very large domains with small r, storage costs can be hard to manage. The problem is much worse if you're working with many dimensions. See [Gamito et al.'s paper][1], Figure 12. Even in 4D you can be severely storage limited.&#xD;&#xA;&#xD;&#xA; 2. In your proposed grid size, each candidate points checks 24 squares, as opposed to 20 in the usual method. There is a per-square cost (e.g. checking whether square is occupied and fetching sample point if it is) which increases the overall cost in your method.&#xD;&#xA;&#xD;&#xA;**Basically, your method works, but it is usually not more efficient.** &#xD;&#xA;&#xD;&#xA;However, the state of the art in unbiased Poisson-disk sampling techniques actually successively reduces the grid size as the uncovered area reduces. In addition to [Gamito et al.'s paper][1], also see [Ebeida et al.'s paper][2].&#xD;&#xA;&#xD;&#xA;  [1]: http://staffwww.dcs.shef.ac.uk/people/S.Maddock/research/gamito/papers/poisson.pdf&#xD;&#xA;  [2]: http://www.sandia.gov/~samitch/papers/eurographics_mps-final-with-appendix.pdf&#xD;&#xA;&#xD;&#xA;P.S. Sorry, I don't know how to do math formatting in Stack Exchange." ContentLicense="CC BY-SA 3.0" />
  <row Id="1225" PostHistoryTypeId="2" PostId="413" RevisionGUID="490e9ecd-5845-4415-a07b-3b04e5372df5" CreationDate="2015-09-02T21:57:49.120" UserId="14" Text="I just use Powerpoint to make such diagrams and it works great as soon as you're comfortable with its basic primitives. It supports all simple operations like rotation, translation, etc. and recent revisions also have shear and 3D transforms. Examples:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;For more complicated diagrams, especially in 3D, I sometimes use Blender with shadeless materials. I can elaborate and show examples if it is relevant to your question.&#xD;&#xA;&#xD;&#xA;Looks like [jsfiddle][3] is also popular around here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Hzmcd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ESDaY.png&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/questions/324/is-this-smaller-grid-for-poisson-disc-sampling-still-correct" ContentLicense="CC BY-SA 3.0" />
  <row Id="1226" PostHistoryTypeId="33" PostId="324" RevisionGUID="9c79322b-0a0c-445c-9851-f439abbb5f33" CreationDate="2015-09-02T23:17:42.443" UserId="231" Comment="10" />
  <row Id="1228" PostHistoryTypeId="2" PostId="414" RevisionGUID="17106325-adf1-4018-af5d-31eaa3ba6a00" CreationDate="2015-09-03T01:44:56.440" UserId="207" Text="Your image definitely does not look correct, and it appears that you are not correctly computing the internal path of light rays as they travel through your mesh. From the looks of it, I would say that you are computing the distance between the point where the view ray first enters the cube and where it first hits the interior wall, and using that as your absorption distance. This essentially assumes that light will always exit the glass the first time it hits a wall, which is a poor assumption.&#xD;&#xA;&#xD;&#xA;In reality, When light enters glass from air, it often does not immediately exit the glass. This is because when the light strikes the glass/air interface, a phenomenon known as [total internal reflection][1] (TIR) can occur. TIR occurs when light travels from a medium with a higher index of refraction (IOR) to one with a lower IOR, which is precisely what happens in the case of light hitting the interior wall of a glass object. This image from Wikipedia is a good visual demonstration of what it looks like when it occurs:&#xD;&#xA;&#xD;&#xA;[![total internal reflection][2]][2]&#xD;&#xA;&#xD;&#xA;In basic terms, what it means is that if the light hits at a shallow angle, the light will completely reflect off of the interior of the medium. To account for this, you need to evaluate the [Fresnel equations][3] every time that your light ray hits a glass/air interface (AKA the interior surface of your mesh). The Fresnel equations will tell you the ratio of reflected light to the amount of refracted light, while will be 1 in the case of TIR. You can then compute the appropriate reflected and refracted light directions, and continue to trace the light's path either through the medium or outside of it. If you assume a simple convex mesh with a uniform scattering coefficient, then the the distance to use for Beer's law will be the sum of all internal path lengths before exiting the medium. Here is what a cube looks like with your scattering coefficients and IOR of 1.526 (soda lime glass), rendered using my own path tracer that accounts for both internal and external reflections and refractions:&#xD;&#xA;&#xD;&#xA;[![path-traced glass cube][4]][4]&#xD;&#xA;&#xD;&#xA;Ultimately the internal reflections and refractions are a major part of what makes glass look like glass. Simple approximations really don't cut it, as you've already found out. It gets even worse if you add multiple meshes and/or non-convex meshes, as you not not only have to account for internal reflections but must also account for rays that leave the medium and enter it at a different point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Total_internal_reflection&#xD;&#xA;  [2]: https://i.stack.imgur.com/4lSRl.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [4]: https://i.stack.imgur.com/7MOow.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1229" PostHistoryTypeId="34" PostId="297" RevisionGUID="37889bc2-30e9-4871-9300-d583171e4c7b" CreationDate="2015-09-03T03:09:38.317" UserId="56" Comment="9" />
  <row Id="1233" PostHistoryTypeId="5" PostId="410" RevisionGUID="8da4b677-5ab8-4893-a961-655aadf4d9c5" CreationDate="2015-09-03T05:29:26.583" UserId="48" Comment="added example images" Text="(XYZ) can be the RGB colour you want to tint your scene by. For the above scene it can be a red colour (1.0, 0.0, 0.0) or something similar with a strong red component. &#xD;&#xA;&#xD;&#xA;Bear in mind that since you are applying the colour in a multiplicative way it will act as a filter suppressing original colour components. So if your scene is mostly green but you apply (i.e. multiply it with) a red filter (1,0,0) the resulting scene will be very dark.&#xD;&#xA;&#xD;&#xA;A trick you could potentially do in such cases is to desaturate the original scene and then multiply it by the tint colour. That way you will keep the overall image intensity and achieve the colour tint you require.&#xD;&#xA;&#xD;&#xA;For example, here is the image multiplied by (1, 0, 0), (1, 0.2, 0.2), and (1, 0.5, 0.5) from left to right:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] [![enter image description here][2]][2] [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N4YCV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/95LBW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/mkIgR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1235" PostHistoryTypeId="2" PostId="416" RevisionGUID="73483fb2-43a8-455d-b2a5-f6d031dec8d2" CreationDate="2015-09-03T08:16:51.817" UserId="361" Text="I'm currently researching my options on effeciently exchanging data for a webgl application. I understand the gltf format is still being [drafted][1] but I need some example data to understand whether this format is really useful for my application.&#xD;&#xA;&#xD;&#xA;I'm currently using JSON data and I need to figure out whether there are any benefits to using data formats which are closer to the hardware. As far as I understand gltf also uses some JSON structures.&#xD;&#xA;&#xD;&#xA;Are there any gltf example datasets available already?&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/master/specification/README.md" ContentLicense="CC BY-SA 3.0" />
  <row Id="1236" PostHistoryTypeId="1" PostId="416" RevisionGUID="73483fb2-43a8-455d-b2a5-f6d031dec8d2" CreationDate="2015-09-03T08:16:51.817" UserId="361" Text="Are there any gltf example datasets available?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1237" PostHistoryTypeId="3" PostId="416" RevisionGUID="73483fb2-43a8-455d-b2a5-f6d031dec8d2" CreationDate="2015-09-03T08:16:51.817" UserId="361" Text="|vertex-buffer-object|webgl|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1238" PostHistoryTypeId="2" PostId="417" RevisionGUID="8ff5f46d-b123-4250-b454-06745988601a" CreationDate="2015-09-03T08:26:17.907" UserId="361" Text="Ok sometimes you have to ask a question to figure out the answer already.&#xD;&#xA;&#xD;&#xA;Example datasets are available in the same repository as linked in the question already. &#xD;&#xA;&#xD;&#xA;Here are some:&#xD;&#xA;&#xD;&#xA; - [supermurdoc.gltf][1]&#xD;&#xA; - [duck.gltf][2]&#xD;&#xA; - [...][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/e9cf7b0de2d1daed58317f5e6c8b9a2b7d543375/model/SuperMurdoch/SuperMurdoch.gltf&#xD;&#xA;  [2]: https://github.com/KhronosGroup/glTF/blob/e9cf7b0de2d1daed58317f5e6c8b9a2b7d543375/model/duck/duck.gltf&#xD;&#xA;  [3]: https://github.com/KhronosGroup/glTF/tree/master/model" ContentLicense="CC BY-SA 3.0" />
  <row Id="1239" PostHistoryTypeId="2" PostId="418" RevisionGUID="6d56ad84-6341-4e93-9c5f-48c2fe3705ce" CreationDate="2015-09-03T09:18:23.187" UserId="38" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pich even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsment because of nessesity.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to enable the snapping grid. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implenents this snapping. PowerPoint actually comes with grid snaping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs.&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](http://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and javascript access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of gridsnap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](http://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;[2]:https://i.stack.imgur.com/Wg2jD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1240" PostHistoryTypeId="2" PostId="419" RevisionGUID="1f83bc76-d4b0-4b13-8690-82ecbf80c1aa" CreationDate="2015-09-03T09:20:31.290" UserId="209" Text="It is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**:&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of &quot;page&quot; breaks which can costly. MIP mapping helps reduce these.&#xD;&#xA;&#xD;&#xA;**Texture compression**:&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined." ContentLicense="CC BY-SA 3.0" />
  <row Id="1241" PostHistoryTypeId="5" PostId="418" RevisionGUID="832449b4-9f8c-4854-871c-af3abd0b7594" CreationDate="2015-09-03T09:35:06.857" UserId="38" Comment="added 1151 characters in body" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs.&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](http://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](http://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](http://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript.&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;[2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;[3]: https://i.stack.imgur.com/xUdRz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1242" PostHistoryTypeId="2" PostId="420" RevisionGUID="ac3d6ee1-792b-4972-b81f-49a572e88299" CreationDate="2015-09-03T09:38:08.500" UserId="213" Text="In case you want to take a look into a ready solution.I have [a port][1] of THREE.JS TrackBall controlls in C++ and C#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/sasmaster/TrackballControls" ContentLicense="CC BY-SA 3.0" />
  <row Id="1243" PostHistoryTypeId="5" PostId="418" RevisionGUID="a0a66bec-f6b0-494f-b61e-a762dff10a58" CreationDate="2015-09-03T09:44:42.147" UserId="38" Comment="added 1151 characters in body" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs.&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](http://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](http://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](http://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](http://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](http://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;[2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;[3]: https://i.stack.imgur.com/xUdRz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1244" PostHistoryTypeId="5" PostId="419" RevisionGUID="49a4c94a-ec4c-45a2-9e43-bfe0778024d2" CreationDate="2015-09-03T09:58:56.470" UserId="209" Comment="added to &quot;page&quot; break description" Text="It is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**:&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page&quot; breaks which can costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**:&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined." ContentLicense="CC BY-SA 3.0" />
  <row Id="1245" PostHistoryTypeId="5" PostId="418" RevisionGUID="d4ad3c0a-4026-45fb-a2c0-2e6a25e2f241" CreationDate="2015-09-03T10:01:27.850" UserId="38" Comment="added 461 characters in body" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](http://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](http://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](http://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](http://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](http://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;[2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;[3]: https://i.stack.imgur.com/xUdRz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1246" PostHistoryTypeId="5" PostId="418" RevisionGUID="6b7af8c1-ef4a-4045-83d4-0db5badfeaa9" CreationDate="2015-09-03T10:11:39.650" UserId="38" Comment="added 313 characters in body" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](http://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](http://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](http://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](http://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](http://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside aanimation [as per](http://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1247" PostHistoryTypeId="5" PostId="419" RevisionGUID="1443d74a-c19e-4140-9fca-46954a52e2e5" CreationDate="2015-09-03T10:17:41.813" UserId="209" Comment="minor comment on page break" Text="It is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**:&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**:&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined." ContentLicense="CC BY-SA 3.0" />
  <row Id="1250" PostHistoryTypeId="5" PostId="418" RevisionGUID="a87e6b39-b5f3-4017-bd6b-d2a620d3fd8b" CreationDate="2015-09-03T11:27:23.207" UserId="38" Comment="deleted 3 characters in body" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](http://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](http://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](http://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](http://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](http://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside a table [as per](http://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="1251" PostHistoryTypeId="2" PostId="421" RevisionGUID="326a2bf3-df9e-4e9e-98be-1780fb2303e9" CreationDate="2015-09-03T13:15:11.750" UserId="385" Text="In his classic paper [Ray Tracing with Cones][1], John Amanatides describes a variation on classical ray tracing. By extending the concept of a *ray* by an *aperture angle*, making it a cone, aliasing effects (including those originating from too few Monte Carlo samples) can be reduced.&#xD;&#xA;&#xD;&#xA;During cone-triangle-intersection a scalar coverage value is calulated. This value represents the fraction of the cone that is covered by the triangle. If it is less than one it means that the triangle doesn't fully cover the cone. Further tests are required. Without the usage of more advanced techniques however we only know how much of the cone is covered, but not which parts.&#xD;&#xA;&#xD;&#xA;Amanatides states:&#xD;&#xA;&gt; Since at present only the fractional coverage value is used in mixing&#xD;&#xA;&gt; the contributions from the various objects, overlapping surfaces will&#xD;&#xA;&gt; be calculated correctly but abutting surfaces will not.&#xD;&#xA;&#xD;&#xA;This does not make sense to me. From my point of view it is the other way around. Let's take an example: we have two *abutting* triangles, a green and a blue one, each of which covers exactly 50% of our cone. They are at the same distance from the viewer.&#xD;&#xA;&#xD;&#xA;[![Green and blue triangle][2]][2]&#xD;&#xA;&#xD;&#xA;The green triangle is tested first. It has a coverage value of 0.5, so the blue triangle is tested next. With the blue one's coverage value of 0.5 our cone is fully covered, so we're done and end up with a 50:50 green-blue mixture. Great!&#xD;&#xA;&#xD;&#xA;Now imagine that we kill the blue triangle and add a red one some distance behind the green one - *overlapping*. Greeny gives us a coverage value of 0.5 again. Since we don't have the blue one to test anymore we look further down the cone and soon find the red one. This too returns some coverage value greater than 0, which it shouldn't because it is *behind* the green one.&#xD;&#xA;&#xD;&#xA;So, from this I conclude that abutting triangles work fine, while overlapping triangles would need some more magic like coverage masks to be correct. This is the opposite of what Amanatides says. Did I misunderstand something or is this a slip in the paper?&#xD;&#xA;&#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.32.6170&#xD;&#xA;  [2]: https://i.stack.imgur.com/n5JTo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1252" PostHistoryTypeId="1" PostId="421" RevisionGUID="326a2bf3-df9e-4e9e-98be-1780fb2303e9" CreationDate="2015-09-03T13:15:11.750" UserId="385" Text="Ray Tracing with Cones: coverage, overlapping and abutting triangles" ContentLicense="CC BY-SA 3.0" />
  <row Id="1253" PostHistoryTypeId="3" PostId="421" RevisionGUID="326a2bf3-df9e-4e9e-98be-1780fb2303e9" CreationDate="2015-09-03T13:15:11.750" UserId="385" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1254" PostHistoryTypeId="2" PostId="422" RevisionGUID="d764c62f-0f60-40f0-ab79-26677589f5a3" CreationDate="2015-09-03T13:53:39.800" UserId="385" Text="Extending Kostas Anagnostou's answer, a commonly used formula for desaturation is&#xD;&#xA;&#xD;&#xA;    float value = 0.3f * InputR + 0.59f * InputG + 0.11f * InputB;&#xD;&#xA;&#xD;&#xA;This accomodates the fact that different color hues are perceived with a different intensity by a human observer.&#xD;&#xA;&#xD;&#xA;Further following the example, you would then define some tint color that is multiplied with the desaturated value. Also you could mix the tinted image with your original to get a less drastic effect. In this case, we're mixing 80% of the desaturated image tinted with (1.0, 0.2, 0.2) with 20% of the original:&#xD;&#xA;&#xD;&#xA;    float3 tint = float3(1.0f, 0.2f, 0.2f);&#xD;&#xA;    float tintMix = 0.8f;&#xD;&#xA;    OutputR = tintMix * value * tint.r + (1 - tintMix) * InputR;&#xD;&#xA;    OutputG = tintMix * value * tint.g + (1 - tintMix) * InputG;&#xD;&#xA;    OutputB = tintMix * value * tint.b + (1 - tintMix) * InputB;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1255" PostHistoryTypeId="2" PostId="423" RevisionGUID="94f8abf3-9079-45f0-a85c-b90802c8db28" CreationDate="2015-09-03T14:12:49.450" UserId="385" Text="The hemispherical intensity function, i.e. the hemispherical function of incident light multiplied by the BRDF, correlates to the number of samples required per solid angle. Take the sample distribution of any method and compare it to that hemispherical function. The more similar they are, the better the method is in that particular case.&#xD;&#xA;&#xD;&#xA;Note that since this intensity function is typically *unknown*, all of those methods use heuristics. If the assumptions of the heuristics are met, the distribution is better (= closer to the desired function) than a random distribution. If not, it's worse.&#xD;&#xA;&#xD;&#xA;For example, importance sampling uses the BRDF to distribute samples, which is simple but only uses a part of the intensity function. A very strong light source illuminating a diffuse surface at shallow angle will get few samples, although its influence might still be huge. Metropolis Light Transport generates new samples from previous one's with high intensity, which is good for few strong light sources, but doesn't help if light arrives evenly from all directions." ContentLicense="CC BY-SA 3.0" />
  <row Id="1256" PostHistoryTypeId="2" PostId="424" RevisionGUID="599dd802-4a7f-49d2-a70f-d23b9122132a" CreationDate="2015-09-03T15:00:16.987" UserId="523" Text="In font rendering, it is common to use [subpixel rendering](https://en.wikipedia.org/wiki/Subpixel_rendering).  The basic idea here is to break the pixel into its RGB components and then compute a value for each separately.  Since each component is smaller than the entire pixel, higher quality antialiasing is possible.&#xD;&#xA;&#xD;&#xA;There is an obviously analogous way to do the same for a ray tracer.  You do reconstruction filtering on each subchannel separately.&#xD;&#xA;&#xD;&#xA;I was surprised that, however, I couldn't really find reference to ray tracers doing this.  Especially if you're already doing spectral rendering, this seems like an obvious thing to do.  There's [this paper](http://wscg.zcu.cz/wscg2012/full/E03-full.pdf) from a journal I've never heard of which seems to be related.  But overall, subpixel rendering just doesn't seem to be a common thing to do.  My question: **why not**?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1257" PostHistoryTypeId="1" PostId="424" RevisionGUID="599dd802-4a7f-49d2-a70f-d23b9122132a" CreationDate="2015-09-03T15:00:16.987" UserId="523" Text="Subpixel Rendering for a Ray Tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="1258" PostHistoryTypeId="3" PostId="424" RevisionGUID="599dd802-4a7f-49d2-a70f-d23b9122132a" CreationDate="2015-09-03T15:00:16.987" UserId="523" Text="|raytracing|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1259" PostHistoryTypeId="2" PostId="425" RevisionGUID="fac27767-f68f-4d9c-b6ab-483f34c74b67" CreationDate="2015-09-03T15:09:52.093" UserId="523" Text="I've done some VR research; this comes up a lot since rendering the scene multiple times (especially at predicted VR resolutions) is expensive.&#xD;&#xA;&#xD;&#xA;The basic problem is that two views provide more information than only one.  In particular, you have two slices of the light field instead of one.  It's related to depth-of-field: screen-space methods fundamentally are incorrect.&#xD;&#xA;&#xD;&#xA;There has been some work in this area, most related to reprojection techniques that try to do some kind of geometry-aware holefilling in the final image.  This sortof works.  As far as I know, the best approach so far is to render the scene directly for the dominant eye, and then reproject it to the other one." ContentLicense="CC BY-SA 3.0" />
  <row Id="1261" PostHistoryTypeId="2" PostId="427" RevisionGUID="14bd0fe6-e0cd-4062-86da-6f113d073b1a" CreationDate="2015-09-03T16:11:42.543" UserId="209" Text="I did implement a ray tracer based on Amantides work but, as that was &lt;cough&gt; years ago, my memory of the paper is a little rusty.&#xD;&#xA;&#xD;&#xA;However, ignoring this particular case, in general when it comes to working with fractional coverage e.g. Porter and Duff's work, (see [&quot;A over B&quot;][1] ) my understanding is that the usual assumption is that the items being composited are uncorrelated.&#xD;&#xA;&#xD;&#xA;Thus if A with X% coverage is on top of B with Y% coverage and C in the background, then it's assumed that one will see    &#xD;&#xA;    X%*A + (100-X%)*Y% * B + (100-X%)(100-Y%)*C&#xD;&#xA;&#xD;&#xA;Does that make sense? Obviously this will give &quot;leaks&quot; in the case where A and B are strongly correlated.&#xD;&#xA;&#xD;&#xA;I *think* I might have put a small bit mask on the rays to avoid these problems, but it was a very long time ago.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Alpha_compositing#Description" ContentLicense="CC BY-SA 3.0" />
  <row Id="1262" PostHistoryTypeId="5" PostId="427" RevisionGUID="93781234-6535-4cdd-aad3-772ef6c3c6d9" CreationDate="2015-09-03T16:18:32.877" UserId="209" Comment="deleted 4 characters in body" Text="I did implement a ray tracer based on Amantides work but, as that was &lt;cough&gt; years ago, my memory of the paper is a little rusty.&#xD;&#xA;&#xD;&#xA;However, ignoring this particular case, in general when it comes to working with fractional coverage e.g. Alpha compositing, (see [&quot;A over B&quot;][1]) my understanding is that the usual assumption is that the items being composited are uncorrelated.&#xD;&#xA;&#xD;&#xA;Thus if A with X% coverage is on top of B with Y% coverage and C in the background, then it's assumed that one will see    &#xD;&#xA;    X%*A + (100-X%)*Y% * B + (100-X%)(100-Y%)*C&#xD;&#xA;&#xD;&#xA;Does that make sense? Obviously this will give &quot;leaks&quot; in the case where A and B are strongly correlated.&#xD;&#xA;&#xD;&#xA;I *think* I might have put a small bit mask on the rays to avoid these problems, but it was a very long time ago.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Alpha_compositing#Description" ContentLicense="CC BY-SA 3.0" />
  <row Id="1263" PostHistoryTypeId="5" PostId="409" RevisionGUID="680476a8-f200-4ad6-b6c8-8272c2ee518d" CreationDate="2015-09-03T16:41:57.353" UserId="209" Comment="added 315 characters in body" Text="Another option, which I used a couple of decades ago (yikes!), is to use  [Toth's scheme from 1985][1] that employed interval arithmetic to narrow down the search space. IIRC, eventually it will resort to Newton-Rhapson but, again IIRC, I think it rarely required more than one or two steps to get to a good solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Though I haven't looked at it (well, apart from a quick glance) [Mitchell][2] has published some more recent work on ray tracing with interval maths.&#xD;&#xA;&#xD;&#xA;*(I should add that, if you are only doing Bezier surfaces, then the interval method might be a bit &quot;overkill&quot; since you can use tricks like blossoming to get bounds and derivatives. If, however, you combine Bezier curves with other functions, e.g. rotation around an axis, then its generality is more useful.)*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p171-toth.pdf&#xD;&#xA;  [2]: http://mentallandscape.com/Papers_graphicsinterface90b.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="1264" PostHistoryTypeId="2" PostId="428" RevisionGUID="0d9ab82d-e116-4877-8b05-a8fd65c292d0" CreationDate="2015-09-03T17:28:50.833" UserId="231" Text="## This is perfectly possible&#xD;&#xA;&#xD;&#xA;Although the difference may not especially noticeable, I would expect sampling taking into account the exact [pixel geometry] to give a slightly more accurate image. You just need to offset your pixel centres per colour component according to the (average) location of the subpixel(s) of that colour. Note that not all pixel layouts have a one to one correspondence between pixels and sub pixels.&#xD;&#xA;&#xD;&#xA;I am not aware of any technical reason that would prevent this being used to produce arbitrary full colour images. In fact a colourful scene will have less noticeable colour artefacts than black on white text, which makes the colour differences hardest to camouflage.&#xD;&#xA;&#xD;&#xA;## Fonts are rendered on demand&#xD;&#xA;&#xD;&#xA;The relevant difference between rendering a raytraced scene and rendering fonts is that fonts tend to be rendered on demand, and can take into account the screen being used. A raytraced scene is often prerendered and then displayed on many different types of screen (with different pixel geometry). For example, displaying your raytraced image on a webpage will prevent tailoring it to a specific monitor type.&#xD;&#xA;&#xD;&#xA;If you were designing a realtime raytracing program and you had access to check the pixel geometry of the monitor, then you could raytrace to the specific sub pixel layout. However, offline raytracing that produces a still image can only be tailored to a single type of pixel geometry, which will then make the image look *worse* on any other pixel geometry. You could work around this by rendering a set of different images and choosing the appropriate one when it is later displayed on a particular type of monitor.&#xD;&#xA;&#xD;&#xA;## There is unlikely to be a long term benefit&#xD;&#xA;&#xD;&#xA;So there is no reason you couldn't develop sub pixel rendering for a raytracer, but it means taking into account an aspect of the monitor that is not always known. Another thing to bear in mind is that you will be developing this software for a shrinking market. Sub pixel rendering is useful for screens that have relatively low resolution. As more and more screens (even mobile screens) are approaching such high resolution that the human eye cannot detect the difference made by sub pixel rendering, you work would be more of theoretical interest than practical use.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [pixel geometry]: https://en.wikipedia.org/wiki/Pixel_geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="1265" PostHistoryTypeId="5" PostId="428" RevisionGUID="d04402b7-18a8-4399-8e98-b8705a1fe895" CreationDate="2015-09-03T17:43:37.623" UserId="231" Comment="Add image" Text="## This is perfectly possible&#xD;&#xA;&#xD;&#xA;Although the difference may not especially noticeable, I would expect sampling taking into account the exact [pixel geometry] to give a slightly more accurate image. You just need to offset your pixel centres per colour component according to the (average) location of the subpixel(s) of that colour. Note that not all pixel layouts have a one to one correspondence between pixels and sub pixels.&#xD;&#xA;&#xD;&#xA;For example, [penTile RGBG] has twice as many green subpixels as red and blue, as this image from Wikipedia shows:&#xD;&#xA;&#xD;&#xA;[![Close up image of RGBG pixel geometry]&#xD;&#xA;  [small image on imgur]][image on wikipedia]&#xD;&#xA;&#xD;&#xA;I am not aware of any technical reason that would prevent this being used to produce arbitrary full colour images. In fact a colourful scene will have less noticeable colour artefacts than black on white text, which makes the colour differences hardest to camouflage.&#xD;&#xA;&#xD;&#xA;## Fonts are rendered on demand&#xD;&#xA;&#xD;&#xA;The relevant difference between rendering a raytraced scene and rendering fonts is that fonts tend to be rendered on demand, and can take into account the screen being used. Contrasting with this, a raytraced scene is often prerendered and then displayed on many different types of screen (with different pixel geometry). For example, displaying your raytraced image on a webpage will prevent tailoring it to a specific monitor type.&#xD;&#xA;&#xD;&#xA;If you were designing a realtime raytracing program and you had access to check the pixel geometry of the monitor, then you could raytrace to the specific sub pixel layout. However, offline raytracing that produces a still image can only be tailored to a single type of pixel geometry, which will then make the image look *worse* on any other pixel geometry. You could work around this by rendering a set of different images and choosing the appropriate one when it is later displayed on a particular type of monitor.&#xD;&#xA;&#xD;&#xA;## There is unlikely to be a long term benefit&#xD;&#xA;&#xD;&#xA;So there is no reason you couldn't develop sub pixel rendering for a raytracer, but it means taking into account an aspect of the monitor that is not always known. Another thing to bear in mind is that you will be developing this software for a shrinking market. Sub pixel rendering is useful for screens that have relatively low resolution. As more and more screens (even mobile screens) are approaching such high resolution that the human eye cannot detect the difference made by sub pixel rendering, your work is likely to be more of theoretical interest than practical use.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [pixel geometry]: https://en.wikipedia.org/wiki/Pixel_geometry&#xD;&#xA;&#xD;&#xA;  [penTile RGBG]: https://en.wikipedia.org/wiki/PenTile_matrix_family#PenTile_RGBG&#xD;&#xA;&#xD;&#xA;  [small image on imgur]: https://i.stack.imgur.com/oB5Rn.png&#xD;&#xA;&#xD;&#xA;  [image on wikipedia]: https://en.wikipedia.org/wiki/PenTile_matrix_family#/media/File:Nexus_one_screen_microscope.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="1267" PostHistoryTypeId="2" PostId="429" RevisionGUID="dcd464a9-fad9-48dd-ab1c-c1f3187938d0" CreationDate="2015-09-03T19:04:15.140" UserId="48" Text="I use a variety of tools depending on the particular needs of the moment. I have a bias toward free tools, as I don't have access to things like Illustrator or Mathematica.&#xD;&#xA;&#xD;&#xA;For general vector art purposes I use the free [Inkscape](https://inkscape.org/en/). It operates on .svg files and can also render them out as high-quality .pngs or other bitmap formats. For example, here's a diagram I made in Inkscape [to explain UV mapping](https://gamedev.stackexchange.com/questions/22103/confusion-with-the-texture-coordinate-system-in-xna):&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/t99e7.png)&#xD;&#xA;&#xD;&#xA;For 2D function graphs, I often use the online graphing calculator [Desmos](https://www.desmos.com/), which has the handy capability of letting you share graphs online so others can view and modify them. You can also create sliders that can be varied to play with curve parameters in real time. For example, here is a [configurable sharpening function](https://www.desmos.com/calculator/id7k8wn7ud).&#xD;&#xA;&#xD;&#xA;For more complex graphing tasks that involve a bit of programming, I use [Maxima](http://maxima.sourceforge.net/), a free computer algebra system that also has graphing features. I used Maxima to create the graphs in [this answer about Gaussian blurs](http://computergraphics.stackexchange.com/a/289/48):&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/ugYom.png)&#xD;&#xA;&#xD;&#xA;This was a bit too complex for Demos, since it involved programmatically creating a piecewise approximation of a Gaussian.&#xD;&#xA;&#xD;&#xA;For really odd graphing tasks that aren't handled well by anything else, I've used Python with the [svgwrite](https://pypi.python.org/pypi/svgwrite/) package to programmatically generate diagrams into .svg files. These can then be touched up in Inkscape if desired and rendered to bitmaps using Inkscape or ImageMagick. I used that workflow to create the images in [this blog post on depth precision](http://www.reedbeta.com/blog/2015/07/03/depth-precision-visualized/), like this:&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/MVLUh.png)&#xD;&#xA;&#xD;&#xA;In this case I wanted to not only graph a function, but place tick marks programmatically and nonuniformly along both the axes and the graph, to illustrate discrete depth precision values.&#xD;&#xA;&#xD;&#xA;And finally, if nothing else suffices, I'll use Python with [numpy](http://www.numpy.org/) and [pillow](https://python-pillow.github.io/) to render images pixel-by-pixel. That's how I created the Perlin noise images in [this answer](http://computergraphics.stackexchange.com/a/252/48) (with the help of the [noise](https://pypi.python.org/pypi/noise/) package too, in this case).&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Micts.png)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1268" PostHistoryTypeId="5" PostId="429" RevisionGUID="a4f9103a-ec85-49fa-a1c9-6fd23d29b1f7" CreationDate="2015-09-03T20:43:56.083" UserId="48" Comment="typo" Text="I use a variety of tools depending on the particular needs of the moment. I have a bias toward free tools, as I don't have access to things like Illustrator or Mathematica.&#xD;&#xA;&#xD;&#xA;For general vector art purposes I use the free [Inkscape](https://inkscape.org/en/). It operates on .svg files and can also render them out as high-quality .pngs or other bitmap formats. For example, here's a diagram I made in Inkscape [to explain UV mapping](https://gamedev.stackexchange.com/questions/22103/confusion-with-the-texture-coordinate-system-in-xna):&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/t99e7.png)&#xD;&#xA;&#xD;&#xA;For 2D function graphs, I often use the online graphing calculator [Desmos](https://www.desmos.com/), which has the handy capability of letting you share graphs online so others can view and modify them. You can also create sliders that can be varied to play with curve parameters in real time. For example, here is a [configurable sharpening function](https://www.desmos.com/calculator/id7k8wn7ud).&#xD;&#xA;&#xD;&#xA;For more complex graphing tasks that involve a bit of programming, I use [Maxima](http://maxima.sourceforge.net/), a free computer algebra system that also has graphing features. I used Maxima to create the graphs in [this answer about Gaussian blurs](http://computergraphics.stackexchange.com/a/289/48):&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/ugYom.png)&#xD;&#xA;&#xD;&#xA;This was a bit too complex for Desmos, since it involved programmatically creating a piecewise approximation of a Gaussian.&#xD;&#xA;&#xD;&#xA;For really odd graphing tasks that aren't handled well by anything else, I've used Python with the [svgwrite](https://pypi.python.org/pypi/svgwrite/) package to programmatically generate diagrams into .svg files. These can then be touched up in Inkscape if desired and rendered to bitmaps using Inkscape or ImageMagick. I used that workflow to create the images in [this blog post on depth precision](http://www.reedbeta.com/blog/2015/07/03/depth-precision-visualized/), like this:&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/MVLUh.png)&#xD;&#xA;&#xD;&#xA;In this case I wanted to not only graph a function, but place tick marks programmatically and nonuniformly along both the axes and the graph, to illustrate discrete depth buffer values.&#xD;&#xA;&#xD;&#xA;And finally, if nothing else suffices, I'll use Python with [numpy](http://www.numpy.org/) and [pillow](https://python-pillow.github.io/) to render images pixel-by-pixel. That's how I created the Perlin noise images in [this answer](http://computergraphics.stackexchange.com/a/252/48) (with the help of the [noise](https://pypi.python.org/pypi/noise/) package too, in this case).&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Micts.png)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1269" PostHistoryTypeId="2" PostId="430" RevisionGUID="8635abde-f041-4ef5-8a8c-e14f2112a9f9" CreationDate="2015-09-03T21:46:36.893" UserId="525" Text="Sure, you [can use subpixel rendering for arbitrary images.](http://new.ics.ele.tue.nl/~dehaan/pdf/90_jsid2003.pdf)  However, subpixel rendering is really a generic 2D image processing technique &amp;mdash; it has nothing to do with ray tracing specifically.  You could just as well use it with any other 3D rendering method, or even with a simple 2D drawing, photograph or even video.&#xD;&#xA;&#xD;&#xA;Thus, I'd say that &quot;subpixel rendering for ray tracing&quot; is really conflating two distinct problem domains that are best treated separately.  About the only relevant connection is that, if you're ray tracing the scene in real time and know that the resulting image is going to be drawn on the screen using subpixel rendering, you can use this information to optimize the pixel density (and aspect ratio) of the intermediate image (e.g. using 3x horizontal pixel density for a typical RGB LCD screen).&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;A potential source of confusion may be that, on current computer system, subpixel rendering is commonly used only for text, and is typically integrated into the font rendering code.  The main reasons for this are arguably historical, but it's also where the biggest payoffs (in terms of visual improvement and readability) typically are.&#xD;&#xA;&#xD;&#xA;Also, due to the way text tends to consist of simple and repetitive vector shapes, integrating the subpixel rendering into the font renderer offers some extra optimization opportunities over just rendering the text into a high-resolution buffer and then postprocessing it.&#xD;&#xA;&#xD;&#xA;That said, I fully expect that eventually, as technology matures, we'll move to a system where subpixel rendering is simply done transparently by the GPU, or possibly by the screen itself.&#xD;&#xA;&#xD;&#xA;(This will most likely require applications that want to make full use of this feature to deal with physical pixels that are smaller, and not necessarily the same shape as, the &quot;logical pixels&quot;.  But then again, we're already moving in that direction with high-DPI screens.)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="1270" PostHistoryTypeId="2" PostId="431" RevisionGUID="e34f0fec-aa97-482c-96ee-24b2db5e97a7" CreationDate="2015-09-04T00:22:06.640" UserId="56" Text="Subpixel rendering is used most commonly to anti alias fonts. It works by leveraging the physical layout of the color components of a display to give geometry details to an image that are smaller than a pixel.&#xD;&#xA;&#xD;&#xA;For instance, this font has a height of 3 pixels but can easily be read:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;from: http://www.sitepoint.com/two-teeny-tiny-fonts/&#xD;&#xA;&#xD;&#xA;This is a monochromatic case, and i could see this possibly working in a greyscale case, but it seems like it always has to be used in situations where you have high contrast.&#xD;&#xA;&#xD;&#xA;Is it possible to use sub pixel rendering in a full color situation, such as those you'd find while doing a 3d render of a scene?&#xD;&#xA;&#xD;&#xA;I think that it must not be, since it won't be high contrast enough, but does anyone have examples to the contrary?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cq392.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="1271" PostHistoryTypeId="1" PostId="431" RevisionGUID="e34f0fec-aa97-482c-96ee-24b2db5e97a7" CreationDate="2015-09-04T00:22:06.640" UserId="56" Text="Is colorized subpixel rendering possible?" ContentLicense="CC BY-SA 3.0" />
  <row Id="1272" PostHistoryTypeId="3" PostId="431" RevisionGUID="e34f0fec-aa97-482c-96ee-24b2db5e97a7" CreationDate="2015-09-04T00:22:06.640" UserId="56" Text="|color|subpixel-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="1273" PostHistoryTypeId="2" PostId="432" RevisionGUID="eadf27ef-9630-47c6-9c06-feaf51290048" CreationDate="2015-09-04T00:53:07.067" UserId="554" Text="You are correct, it's badly worded. Illumination falls off with the cosine of the angle between the surface normal and the inverse light direction, so the wording implies the light is shining down the original surface normal, and so any tilting away would be tilting away from the lighting direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="2271" PostHistoryTypeId="2" PostId="1431" RevisionGUID="8db110c8-39af-4dc0-9331-18d96f71a498" CreationDate="2015-09-04T05:13:15.667" UserId="196" Text="Here's an example of a downsampling filter that takes pixel geometry into account: [Increasing image resolution on portable displays by subpixel rendering][1].&#xD;&#xA;&#xD;&#xA;Image (a) below is an image downsampled using pixel-based downsampling. Image (b) is downsampled using direct subpixel-based downsampling, which (as far as I can tell) effectively downsamples the R, G, and B planes of the image independently. Image (c) is downsampled using diagonal direct subpixel-based downsampling, which uses a diagonal pattern to improve apparent resolution in both horizontal and vertical directions.&#xD;&#xA;&#xD;&#xA;[![Figure 11 from the paper][2]][2]&#xD;&#xA;&#xD;&#xA;You can see that the last two images look sharper, but also have the characteristic color fringing.&#xD;&#xA;&#xD;&#xA;Here's the downsampling pattern used for the last image:&#xD;&#xA;&#xD;&#xA;![DDSD downsampling pattern][3]&#xD;&#xA;&#xD;&#xA;  [1]: http://journals.cambridge.org/article_S2048770312000030&#xD;&#xA;  [2]: https://i.stack.imgur.com/kZlsj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/cWk6g.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2272" PostHistoryTypeId="5" PostId="1431" RevisionGUID="6ffd62ec-352e-49b4-8c9f-d9494fd1b6c6" CreationDate="2015-09-04T05:59:27.147" UserId="196" Comment="smaller image" Text="Here's an example of a downsampling filter that takes pixel geometry into account: [Increasing image resolution on portable displays by subpixel rendering][1].&#xD;&#xA;&#xD;&#xA;Image (a) below is an image downsampled using pixel-based downsampling. Image (b) is downsampled using direct subpixel-based downsampling, which (as far as I can tell) effectively downsamples the R, G, and B planes of the image independently. Image (c) is downsampled using diagonal direct subpixel-based downsampling, which uses a diagonal pattern to improve apparent resolution in both horizontal and vertical directions.&#xD;&#xA;&#xD;&#xA;[![Figure 11 from the paper][3]][2]&#xD;&#xA;&#xD;&#xA;You can see that the last two images look sharper, but also have the characteristic color fringing.&#xD;&#xA;&#xD;&#xA;Here's the downsampling pattern used for the last image:&#xD;&#xA;&#xD;&#xA;![DDSD downsampling pattern][4]&#xD;&#xA;&#xD;&#xA;  [1]: http://journals.cambridge.org/article_S2048770312000030&#xD;&#xA;  [2]: https://i.stack.imgur.com/kZlsj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Z4bmt.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/cWk6g.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2273" PostHistoryTypeId="2" PostId="1432" RevisionGUID="225d066b-f1d4-4f9d-b83f-602342a008b8" CreationDate="2015-09-04T06:14:31.387" UserId="110" Text="[Anisotropic filtering](https://en.wikipedia.org/wiki/Anisotropic_filtering) &quot;retains the sharpness of a texture normally lost by MIP map texture's attempts to avoid aliasing&quot;. The Wikipedia article gives hints about how it can be implemented (&quot;probe the texture (...) for any orientation of anisotropy&quot;), but it does't read very clear to me.  &#xD;&#xA;  &#xD;&#xA;What are the concrete computations performed by (modern) GPUs to choose the correct MIP level when using anisotropic filtering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2274" PostHistoryTypeId="1" PostId="1432" RevisionGUID="225d066b-f1d4-4f9d-b83f-602342a008b8" CreationDate="2015-09-04T06:14:31.387" UserId="110" Text="How is typically implemented anisotropic filtering in modern GPUs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2275" PostHistoryTypeId="3" PostId="1432" RevisionGUID="225d066b-f1d4-4f9d-b83f-602342a008b8" CreationDate="2015-09-04T06:14:31.387" UserId="110" Text="|texture|gpu|algorithm|implementation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2276" PostHistoryTypeId="2" PostId="1433" RevisionGUID="eeeccde2-d46e-49ee-b2fa-0ad4640da360" CreationDate="2015-09-04T07:40:47.200" UserId="385" Text="I see some problems in the quote you posted.&#xD;&#xA;&#xD;&#xA;&gt; In effect, a point rotated around its normal vector will not change&#xD;&#xA;&gt; the way it reflects light.&#xD;&#xA;&#xD;&#xA;This is true, because a Lambertian reflector will **never** change the *way* it reflects light. The underlying principle stays the same. Also, Lambertian surfaces are isotropic, so the *amount* of reflected light won't change either (which is probably what this sentence is aiming for).&#xD;&#xA;&#xD;&#xA;&gt; However, the point will change the way it reflects light if it is tilted away from its initial normal vector since the area is illuminated by a smaller fraction of the incident radiation.&#xD;&#xA;&#xD;&#xA;Again not true, because the principle doesn't change. The amount *may* change, except for the special case that the cosine is &lt;= 0 before and after the tilting. The amount does not necessarily *grow*, except if we define that the cosine equals 1 before, i.e. that the normal points directly towards the light source.&#xD;&#xA;&#xD;&#xA;This whole paragraph should probably be rewritten to be less ambiguous. Including isotropy could make it more complete." ContentLicense="CC BY-SA 3.0" />
  <row Id="2278" PostHistoryTypeId="5" PostId="419" RevisionGUID="de46fca3-cae8-46fe-8283-021038e4eec4" CreationDate="2015-09-04T08:10:41.517" UserId="209" Comment="Remebered another item - scan-order VS XY interleaved formats." Text="It is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to use of Twiddled-order textures in at least some early PC HW). &#xD;&#xA;&#xD;&#xA;  [1]: http://penguin.ewu.edu/class/cscd470/Winter_13/JimBlinnsCorner/TruthAboutTextureMapping.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2279" PostHistoryTypeId="2" PostId="1434" RevisionGUID="b3bda9f6-6a80-44a3-b44f-9b31655b06cd" CreationDate="2015-09-04T08:18:09.100" UserId="385" Text="In the style of [trichoplax' question][1], I want to talk about yet another Wikipedia article: [Radiosity (computer graphics)][2]. The article states:&#xD;&#xA;&gt;Radiosity is viewpoint independent, which increases the calculations involved, but makes them useful for all viewpoints.&#xD;&#xA;&#xD;&#xA;The technique works with diffuse surfaces only. This way, form factors can be precalculated and are independent of the viewer. The lighting needs to be updated only if some light source changed. If, on the other hand, the technique would support specular reflection, the form factors would depend on the viewer. Form factors and lighting would need to be updated constantly when the camera moves.&#xD;&#xA;&#xD;&#xA;How does the limitation to diffuse surfaces *increase* calculations? Diffuse surfaces need to take light from all directions into account, which is more complex than taking light only from a smaller specular lobe. Is this what this sentence means? Is it just me or should this be rephrased?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/361/is-this-a-mistake-in-the-wikipedia-article-for-lambertian-reflectance&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Radiosity_%28computer_graphics%29" ContentLicense="CC BY-SA 3.0" />
  <row Id="2280" PostHistoryTypeId="1" PostId="1434" RevisionGUID="b3bda9f6-6a80-44a3-b44f-9b31655b06cd" CreationDate="2015-09-04T08:18:09.100" UserId="385" Text="Is this a mistake in the Wikipedia article for Radiosity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2281" PostHistoryTypeId="3" PostId="1434" RevisionGUID="b3bda9f6-6a80-44a3-b44f-9b31655b06cd" CreationDate="2015-09-04T08:18:09.100" UserId="385" Text="|radiosity|second-opinion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2283" PostHistoryTypeId="4" PostId="1432" RevisionGUID="e36e3d78-dbbc-416c-8589-12247ea49d9f" CreationDate="2015-09-04T08:45:57.997" UserId="127" Comment="Edited title (changed word order)" Text="How is anisotropic filtering typically implemented in modern GPUs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2284" PostHistoryTypeId="24" PostId="1432" RevisionGUID="e36e3d78-dbbc-416c-8589-12247ea49d9f" CreationDate="2015-09-04T08:45:57.997" Comment="Proposed by 127 approved by 100, 110 edit id of 46" ContentLicense="CC BY-SA 3.0" />
  <row Id="2285" PostHistoryTypeId="2" PostId="1436" RevisionGUID="17e5bd65-3cd4-44e5-8ed6-8f4be56f0dcc" CreationDate="2015-09-04T09:18:52.440" UserId="327" Text="The other answer (and its link) sound like they're talking about &quot;rip maps&quot;, which are *a* way of implementing anisotropic filtering, but not used in any hardware that I know of due to their prohibitive size: while mipmaps use additional 33% storage, ripmaps use 300%. This can be verified by noting that texture usage requirements don't increase when using AF, rather, only bandwidth does.&#xD;&#xA;&#xD;&#xA;Rather, the texture filtering hardware takes several samples of the various mipmap levels. (The maximum amount of samples is indicated by the AF level, though the exact amount of samples taken in a given filtering operation will depend on the proportion between the derivatives on the fragment.) If you project the cone viewing a surface at an oblique angle onto the texture space, it will result in approximately an oval shaped projection, which is more elongated for more oblique angles. Extra samples are taken along the axis of this oval (from the correct mip levels, to take advantage of the pre-filtering they offer) and combined to give a sharper texture sample." ContentLicense="CC BY-SA 3.0" />
  <row Id="2291" PostHistoryTypeId="2" PostId="1437" RevisionGUID="78db41c7-e2aa-425d-8e5d-050ed3eb1882" CreationDate="2015-09-04T21:38:10.823" UserId="14" Text="The API requirements can be found in any of the specs or extensions. Here is one: https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt&#xD;&#xA;&#xD;&#xA;All GPU vendors likely deviate from the spec because AF-quality used to be a part of many benchmarks. And current implementations will continue to keep on evolving as new workloads stress the existing approximations. Unfortunately, to know exactly what either does, you will need to be a part of one of the companies. But you can gauge the spectrum of possibilities from the following papers, listed in increasing order of quality and implementation cost:&#xD;&#xA;&#xD;&#xA; - [TexRam][1]&#xD;&#xA; - [FELINE][2]&#xD;&#xA; - [EWA][3]&#xD;&#xA;&#xD;&#xA;Quoting from the spec:&#xD;&#xA;&#xD;&#xA;     Anisotropic texture filtering substantially changes Section 3.8.5.&#xD;&#xA;     Previously a single scale factor P was determined based on the&#xD;&#xA;     pixel's projection into texture space.  Now two scale factors,&#xD;&#xA;     Px and Py, are computed.&#xD;&#xA;&#xD;&#xA;       Px = sqrt(dudx^2 + dvdx^2)&#xD;&#xA;       Py = sqrt(dudy^2 + dvdy^2)&#xD;&#xA;&#xD;&#xA;       Pmax = max(Px,Py)&#xD;&#xA;       Pmin = min(Px,Py)&#xD;&#xA;&#xD;&#xA;       N = min(ceil(Pmax/Pmin),maxAniso)&#xD;&#xA;       Lamda' = log2(Pmax/N)&#xD;&#xA;&#xD;&#xA;     where maxAniso is the smaller of the texture's value of&#xD;&#xA;     TEXTURE_MAX_ANISOTROPY_EXT or the implementation-defined value of&#xD;&#xA;     MAX_TEXTURE_MAX_ANISOTROPY_EXT.&#xD;&#xA;&#xD;&#xA;     It is acceptable for implementation to round 'N' up to the nearest&#xD;&#xA;     supported sampling rate.  For example an implementation may only&#xD;&#xA;     support power-of-two sampling rates.&#xD;&#xA;&#xD;&#xA;     It is also acceptable for an implementation to approximate the ideal&#xD;&#xA;     functions Px and Py with functions Fx and Fy subject to the following&#xD;&#xA;     conditions:&#xD;&#xA;&#xD;&#xA;       1.  Fx is continuous and monotonically increasing in |du/dx| and |dv/dx|.&#xD;&#xA;           Fy is continuous and monotonically increasing in |du/dy| and |dv/dy|.&#xD;&#xA;&#xD;&#xA;       2.  max(|du/dx|,|dv/dx|} &lt;= Fx &lt;= |du/dx| + |dv/dx|.&#xD;&#xA;           max(|du/dy|,|dv/dy|} &lt;= Fy &lt;= |du/dy| + |dv/dy|.&#xD;&#xA;&#xD;&#xA;     Instead of a single sample, Tau, at (u,v,Lamda), 'N' locations in the mipmap&#xD;&#xA;     at LOD Lamda, are sampled within the texture footprint of the pixel.&#xD;&#xA;&#xD;&#xA;     Instead of a single sample, Tau, at (u,v,lambda), 'N' locations in&#xD;&#xA;     the mipmap at LOD Lamda are sampled within the texture footprint of&#xD;&#xA;     the pixel.  This sum TauAniso is defined using the single sample Tau.&#xD;&#xA;     When the texture's value of TEXTURE_MAX_ANISOTROPHY_EXT is greater&#xD;&#xA;     than 1.0, use TauAniso instead of Tau to determine the fragment's&#xD;&#xA;     texture value.&#xD;&#xA;&#xD;&#xA;                    i=N&#xD;&#xA;                    ---&#xD;&#xA;     TauAniso = 1/N \ Tau(u(x - 1/2 + i/(N+1), y), v(x - 1/2 + i/(N+1), y)),  Px &gt; Py&#xD;&#xA;                    /&#xD;&#xA;                    ---&#xD;&#xA;                    i=1&#xD;&#xA;&#xD;&#xA;                    i=N&#xD;&#xA;                    ---&#xD;&#xA;     TauAniso = 1/N \ Tau(u(x, y - 1/2 + i/(N+1)), v(x, y - 1/2 + i/(N+1))),  Py &gt;= Px&#xD;&#xA;                    /&#xD;&#xA;                    ---&#xD;&#xA;                    i=1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     It is acceptable to approximate the u and v functions with equally spaced&#xD;&#xA;     samples in texture space at LOD Lamda:&#xD;&#xA;&#xD;&#xA;                    i=N&#xD;&#xA;                    ---&#xD;&#xA;     TauAniso = 1/N \ Tau(u(x,y)+dudx(i/(N+1)-1/2), v(x,y)+dvdx(i/(N+1)-1/2)), Px &gt; Py&#xD;&#xA;                    /&#xD;&#xA;                    ---&#xD;&#xA;                    i=1&#xD;&#xA;&#xD;&#xA;                    i=N&#xD;&#xA;                    ---&#xD;&#xA;     TauAniso = 1/N \ Tau(u(x,y)+dudy(i/(N+1)-1/2), v(x,y)+dvdy(i/(N+1)-1/2)), Py &gt;= Px&#xD;&#xA;                    /&#xD;&#xA;                    ---&#xD;&#xA;                    i=1 &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.researchgate.net/publication/3208533_Texram_a_smart_memory_for_texturing&#xD;&#xA;  [2]: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-99-1.pdf&#xD;&#xA;  [3]: http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4056910&amp;tag=1" ContentLicense="CC BY-SA 3.0" />
  <row Id="2293" PostHistoryTypeId="2" PostId="1438" RevisionGUID="f78242c0-56e6-4980-99d3-9e4636a90f23" CreationDate="2015-09-05T01:37:17.573" UserId="14" Text="How do modern games do geometry level-of-detail for object meshes like characters, terrain, and foliage? There are two parts to my question:&#xD;&#xA;&#xD;&#xA; 1. What does the asset pipeline look like? Do artists make a high-poly model which is later decimated? If so, what decimation algorithms are most popular? Are LOD meshes sometimes done by hand?&#xD;&#xA; 2. How do engines transition between different object LODs at run time? Are there any smooth or progressive transitions?&#xD;&#xA;&#xD;&#xA;The answer might be &quot;different studios use different techniques.&quot; If so, please identify some of the most common practices. It would also be great if you could point me to whitepapers/slides that cover specific examples." ContentLicense="CC BY-SA 3.0" />
  <row Id="2294" PostHistoryTypeId="1" PostId="1438" RevisionGUID="f78242c0-56e6-4980-99d3-9e4636a90f23" CreationDate="2015-09-05T01:37:17.573" UserId="14" Text="What is the state of art in geometric LOD in games?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2295" PostHistoryTypeId="3" PostId="1438" RevisionGUID="f78242c0-56e6-4980-99d3-9e4636a90f23" CreationDate="2015-09-05T01:37:17.573" UserId="14" Text="|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2296" PostHistoryTypeId="2" PostId="1439" RevisionGUID="60b83b83-7ade-4894-a112-40b5aa015cf1" CreationDate="2015-09-05T03:54:59.473" UserId="14" Text="Do modern GPUs support anisotropic filtering for 3D textures? If yes, how can one use it? The OpenGL spec doesn't seem to be very precise on this. From [this link][1]:&#xD;&#xA;&#xD;&#xA;    Should anything particular be said about anisotropic 3D texture filtering?&#xD;&#xA;&#xD;&#xA;      Not sure.  Does the implementation example shown in the spec for&#xD;&#xA;      2D anisotropic texture filtering readily extend to 3D anisotropic&#xD;&#xA;      texture filtering?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="2297" PostHistoryTypeId="1" PostId="1439" RevisionGUID="60b83b83-7ade-4894-a112-40b5aa015cf1" CreationDate="2015-09-05T03:54:59.473" UserId="14" Text="Can we use anisotropic filtering on 3D textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2298" PostHistoryTypeId="3" PostId="1439" RevisionGUID="60b83b83-7ade-4894-a112-40b5aa015cf1" CreationDate="2015-09-05T03:54:59.473" UserId="14" Text="|texture|3dtexture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2299" PostHistoryTypeId="5" PostId="419" RevisionGUID="a9399da8-da63-415e-a918-4405ca12119a" CreationDate="2015-09-05T10:00:38.803" UserId="209" Comment="typo fix" Text="It is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can be costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to use of Twiddled-order textures in at least some early PC HW). &#xD;&#xA;&#xD;&#xA;  [1]: http://penguin.ewu.edu/class/cscd470/Winter_13/JimBlinnsCorner/TruthAboutTextureMapping.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2300" PostHistoryTypeId="5" PostId="427" RevisionGUID="38b7a8a2-7f2c-4f8e-9fc5-779d5e5e39af" CreationDate="2015-09-05T10:03:50.143" UserId="209" Comment="punctuation fix" Text="I did implement a ray tracer based on Amantides' work but, as that was &lt;cough&gt; years ago, my memory of the paper is a little rusty.&#xD;&#xA;&#xD;&#xA;However, ignoring this particular case, in general when it comes to working with fractional coverage e.g. Alpha compositing, (see [&quot;A over B&quot;][1]) my understanding is that the usual assumption is that the items being composited are uncorrelated.&#xD;&#xA;&#xD;&#xA;Thus if A with X% coverage is on top of B with Y% coverage and C in the background, then it's assumed that one will see    &#xD;&#xA;    X%*A + (100-X%)*Y% * B + (100-X%)(100-Y%)*C&#xD;&#xA;&#xD;&#xA;Does that make sense? Obviously this will give &quot;leaks&quot; in the case where A and B are strongly correlated.&#xD;&#xA;&#xD;&#xA;I *think* I might have put a small bit mask on the rays to avoid these problems, but it was a very long time ago.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Alpha_compositing#Description" ContentLicense="CC BY-SA 3.0" />
  <row Id="2301" PostHistoryTypeId="2" PostId="1440" RevisionGUID="250da4ce-582b-4d43-88f0-f9224d16eb1c" CreationDate="2015-09-05T12:12:49.197" UserId="528" Text="While it may not entirely clear from the formulation of the wikipedia article, the author raises an important issue: In contrast to many other approaches, Radiosity needs to perform its calculations **for all existing patches, not only the visible ones**.&#xD;&#xA;It is not the limitation to diffuse surfaces that increases the involved computations, but the fact that radiance is computed for all surfaces in the entire scene, not only the visible ones.&#xD;&#xA;&#xD;&#xA;This is in strong contrast to other global illumination techniques like path-tracing, where radiance is computed only for visible samples. While the view-paths may still reach every point of the scene, there might be parts of a scene that are never reached by any view-rays/paths. Therefore, there are no computations at all. Comparing with local GI the &quot;problem of viewpoint independence&quot; its even more apparent.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On the other hand, as the Wikipedia article suggests, this may also be seen as a very useful property, since the computations do not need to be performed for each different viewpoint. This is not the case for most other techniques." ContentLicense="CC BY-SA 3.0" />
  <row Id="2302" PostHistoryTypeId="2" PostId="1441" RevisionGUID="0ace3b2c-69fe-4a94-81f3-6db9fb7ec559" CreationDate="2015-09-05T14:53:31.797" UserId="14" Text="I have heard that recent GPUs all support non-power-of-2 textures and all features just work. However, I don't understand how mip-mapping would work in such a scenario. Can someone explain?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2303" PostHistoryTypeId="1" PostId="1441" RevisionGUID="0ace3b2c-69fe-4a94-81f3-6db9fb7ec559" CreationDate="2015-09-05T14:53:31.797" UserId="14" Text="How does mip-mapping work with non-power-of-2 textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2304" PostHistoryTypeId="3" PostId="1441" RevisionGUID="0ace3b2c-69fe-4a94-81f3-6db9fb7ec559" CreationDate="2015-09-05T14:53:31.797" UserId="14" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2305" PostHistoryTypeId="6" PostId="424" RevisionGUID="38a1ba62-1916-4986-938a-83cd275d08df" CreationDate="2015-09-05T19:34:22.307" UserId="506" Comment="adding tag" Text="|raytracing|antialiasing|subpixel-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2306" PostHistoryTypeId="24" PostId="424" RevisionGUID="38a1ba62-1916-4986-938a-83cd275d08df" CreationDate="2015-09-05T19:34:22.307" Comment="Proposed by 506 approved by 231, 523 edit id of 47" ContentLicense="CC BY-SA 3.0" />
  <row Id="2308" PostHistoryTypeId="2" PostId="1442" RevisionGUID="fa378485-fd14-4019-8339-58365dc3b1c9" CreationDate="2015-09-05T22:42:13.970" UserId="196" Text="One way to think of it is that graphics cards often implement non-power-of-2 textures simply by padding them until they are a power of 2 in each direction. This makes most things &quot;just work&quot;: tiling and hardware filtering, for example. The only thing that needs to change is the conversion from texture coordinates to image coordinates.&#xD;&#xA;&#xD;&#xA;If implemented like that, it's obvious how to do mipmapping: nothing changes. Even if you have a GPU that supports non-power-of-2 textures without padding, the mipmap levels would end up with &quot;padding&quot;. e.g. a 3x3 texture would have a 2x2 texture as lod 1." ContentLicense="CC BY-SA 3.0" />
  <row Id="2312" PostHistoryTypeId="2" PostId="1444" RevisionGUID="15bf727e-5ed5-4167-88b8-9e3bb8069f6b" CreationDate="2015-09-06T05:18:09.663" UserId="48" Text="The rule is that to compute the next mipmap size, you divide by two and round up to the nearest integer. For example, a 57x43 image would have mipmaps like:&#xD;&#xA;&#xD;&#xA;    level 0: 57x43&#xD;&#xA;    level 1: 29x22&#xD;&#xA;    level 2: 15x11&#xD;&#xA;    level 3: 8x6&#xD;&#xA;    level 4: 4x3&#xD;&#xA;    level 5: 2x2&#xD;&#xA;    level 6: 1x1&#xD;&#xA;&#xD;&#xA;UV mapping, LOD selection, and filtering work just the same way as for power-of-two texture sizes.&#xD;&#xA;&#xD;&#xA;Generating good quality mips for a non-power-of-two texture is a little trickier, as you can't simply average a 2x2 box of pixels to downsample in all cases. However, a 2x2 box filter wasn't that great to begin with, so using a better downsampling filter such as Mitchell-Netravali is recommended regardless of the texture size." ContentLicense="CC BY-SA 3.0" />
  <row Id="2313" PostHistoryTypeId="2" PostId="1445" RevisionGUID="1f1fe18f-7adb-45ec-a2d2-37bdfa41d1d7" CreationDate="2015-09-06T05:41:42.837" UserId="1571" Text="i've recently started to read about spherical harmonics, i have a question about this equation which is mentioned in this StupidSH article :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;what is that lm() and Re() used for ?&#xD;&#xA;&#xD;&#xA;the article can be found here : http://www.ppsloan.org/publications/StupidSH36.pdf&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sBx4G.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2314" PostHistoryTypeId="1" PostId="1445" RevisionGUID="1f1fe18f-7adb-45ec-a2d2-37bdfa41d1d7" CreationDate="2015-09-06T05:41:42.837" UserId="1571" Text="Legendre Polynomial equation in Spherical Harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="2315" PostHistoryTypeId="3" PostId="1445" RevisionGUID="1f1fe18f-7adb-45ec-a2d2-37bdfa41d1d7" CreationDate="2015-09-06T05:41:42.837" UserId="1571" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2316" PostHistoryTypeId="5" PostId="1445" RevisionGUID="69bebb7d-ccc0-4499-a499-37d57df1aabc" CreationDate="2015-09-06T06:11:09.357" UserId="1571" Comment="added 38 characters in body" Text="i've recently started to read about spherical harmonics, i have a question about this  spherical harmonics basis function equation which is mentioned in this StupidSH article :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;what are those lm() and Re() used for ?&#xD;&#xA;&#xD;&#xA;the article can be found here : http://www.ppsloan.org/publications/StupidSH36.pdf&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sBx4G.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2317" PostHistoryTypeId="2" PostId="1446" RevisionGUID="5a3de704-c5d6-47b9-ac48-4605d6b39f08" CreationDate="2015-09-06T06:44:25.300" UserId="537" Text="LOD means managing layers in different display scales. which has two parts, however you may use one of them and that would be enough for most of the cases.&#xD;&#xA;&#xD;&#xA; 1. show/hide layers depend on a magnitude (display scale)&#xD;&#xA;&#xD;&#xA; 2. generalization ( which is a computer algorithm to simplify polygons)&#xD;&#xA;&#xD;&#xA;The most famous and efficient method to generalize (simplify) a polygon is known as Euler and is being used by most of the spatial databases for example PostGis modules in PostgreSQL. it simply removes smaller lats and makes a very rounded Poly.&#xD;&#xA;&#xD;&#xA;To implement LOD in a game you need to watch and save your map(scene) scale, The scale changes from Zero to Infinity and you have to divide this to a particular number of limits for example something like this&#xD;&#xA;1 :  1/zero=infinity  to  1/50&#xD;&#xA;2 : 1/50 to 1/100&#xD;&#xA;3 : 1/100 to 1/1000&#xD;&#xA;4 : 1/1000 to 1/infinity=0&#xD;&#xA;&#xD;&#xA;So when your user uses zoom in and zoom out to change the magnification he moves throw the above limits from one to the other group, and your game uses these display scales to manage level of details. read the rest to see how.&#xD;&#xA;&#xD;&#xA;The above groups 4 limits) are just an example and you need to find the best for your own by trials  and errors there is not any rule for that.&#xD;&#xA;&#xD;&#xA;You need to define which types of your objects (layers) should be visible or invisible in each of the above created groups. for example a small type of objects like a hydrant valve should not be visible when the user is in the forth group (above) because it will be very small at that scales and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xD;&#xA;&#xD;&#xA;&gt;The secound part is about Euler polyhedron theorim.&#xD;&#xA;&#xD;&#xA;In most of the case it is not needed to implement a generalization algorithm, however it is totaly depends, case by case.though it is an easy algorithm that just removes the small lats, you need to define a threshold which is multiplication of magnitude and a constant number, so bigger lats getting filltered in a much farther point of view.&#xD;&#xA;&#xD;&#xA;Another continuous method which is completely based on Euler's theory is to determine this threshold for each linear and polygonal objects and show them in case theey are big enough to be discriminated.&#xD;&#xA;&#xD;&#xA;Note : magnification is a &gt; 0 float number which is equal to 1/Scale and the scale is usually &lt; 1 since a 1:1 scale means you have Real worlds length in your game.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2319" PostHistoryTypeId="2" PostId="1448" RevisionGUID="c602f39b-5a23-4ae3-9929-8bb625820915" CreationDate="2015-09-06T08:03:12.167" UserId="48" Text="The notation Re() and Im() refer to the real and imaginary parts of a complex number.  Mathematicians and physicists are accustomed to using spherical harmonics (and Fourier transforms too) that are complex-valued, due to the factor _e&lt;sup&gt;im&amp;phi;&lt;/sup&gt;_.  You would then also have complex coefficients, in general, in the spherical harmonic expansion of a (real or complex) function.&#xD;&#xA;&#xD;&#xA;Using [Euler's formula](https://en.wikipedia.org/wiki/Euler's_formula), _e&lt;sup&gt;im&amp;phi;&lt;/sup&gt;_ = cos(_m&amp;phi;_) + _i_ sin(_m&amp;phi;_).  So that factor encodes cosine and sine waves  (that oscillate _m_ times as you move around the equator of the sphere) in its real and imaginary parts, respectively.&#xD;&#xA;&#xD;&#xA;When we know we're going to be working strictly with real-valued functions, it may be more convenient to use real-valued variants of the spherical harmonics, where _e&lt;sup&gt;im&amp;phi;&lt;/sup&gt;_ is replaced by either cos(_m&amp;phi;_) or sin(_m&amp;phi;_), and using real coefficients instead of complex ones.  We trade a single complex coefficient for two real coefficients, so we haven't lost any information or flexibility; it's essentially a change of basis.  This formulation just explicitly ensures that everything always comes out real." ContentLicense="CC BY-SA 3.0" />
  <row Id="2320" PostHistoryTypeId="5" PostId="1446" RevisionGUID="d843ae47-de85-4619-baca-589eb06b73d6" CreationDate="2015-09-06T10:43:40.573" UserId="231" Comment="Tidying of typos and formating" Text="LOD (Level of Detail) means managing layers in different display scales, which has two parts. However, you may use one of them and that would be enough for most of the cases.&#xD;&#xA;&#xD;&#xA; 1. Show/hide layers depending on magnitude (display scale).&#xD;&#xA;&#xD;&#xA; 1. Generalization (which is an algorithm to simplify polygons).&#xD;&#xA;&#xD;&#xA;The most famous and efficient method to generalize (simplify) a polygon mesh is known as [Euler operators] and is used by most of the spatial databases for example PostGis modules in PostgreSQL. It simply removes smaller lats and makes a very rounded polygon mesh.&#xD;&#xA;&#xD;&#xA;To implement LOD in a game you need to watch and save your map(scene) scale. The scale changes from zero to infinity and you have to divide this to a particular number of limits for example something like this:&#xD;&#xA;&#xD;&#xA;1. 1/zero=infinity  to  1/50&#xD;&#xA;1. 1/50 to 1/100&#xD;&#xA;1. 1/100 to 1/1000&#xD;&#xA;1. 1/1000 to 1/infinity=0&#xD;&#xA;&#xD;&#xA;So when your user uses zoom in and zoom out to change the magnification he moves through the above limits from one to the other group, and your game uses these display scales to manage level of details.&#xD;&#xA;&#xD;&#xA;The above group of 4 limits are just an example and you need to find the best for your own by trial and error. There is not any rule for that.&#xD;&#xA;&#xD;&#xA;You need to define which types of your objects (layers) should be visible or invisible in each of the above created groups. For example a small type of object like a hydrant valve should not be visible when the user is in the fourth group because it will be very small at that scale and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xD;&#xA;&#xD;&#xA;### The Euler polyhedron theorem.&#xD;&#xA;&#xD;&#xA;In most cases it is not necessary to implement a generalization algorithm, however it is totally depends, case by case. Although it is an easy algorithm that just removes the small lats, you need to define a threshold which is multiplication of magnitude and a constant number, so bigger lats getting filtered in a much farther point of view.&#xD;&#xA;&#xD;&#xA;Another continuous method which is completely based on Euler's theorem is to determine this threshold for each linear and polygonal object and show them in the case that they are big enough to be discriminated.&#xD;&#xA;&#xD;&#xA;Note : magnification is a float number &gt; 0 which is equal to 1/scale and the scale is usually &lt; 1 since a 1:1 scale means you have real world lengths in your game.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Euler operators]: https://en.wikipedia.org/wiki/Euler_operator#Euler_operators_.28Euler_operations.29" ContentLicense="CC BY-SA 3.0" />
  <row Id="2321" PostHistoryTypeId="5" PostId="1446" RevisionGUID="1dfc9427-e6a6-40cb-aa22-2b4f3d746ab9" CreationDate="2015-09-06T11:30:09.207" UserId="231" Comment="Further tidying" Text="LOD (Level of Detail) means managing layers in different display scales, which has two parts. However, you may use one of them and that would be enough for most cases.&#xD;&#xA;&#xD;&#xA; 1. Show/hide layers depending on magnitude (display scale).&#xD;&#xA;&#xD;&#xA; 1. Generalization (which is an algorithm to simplify polygons).&#xD;&#xA;&#xD;&#xA;The most famous and efficient method to generalize (simplify) a polygon mesh is known as [Euler operators] and is used by most of the spatial databases for example PostGIS modules in PostgreSQL. It simply removes smaller lats and makes a very rounded polygon mesh.&#xD;&#xA;&#xD;&#xA;To implement LOD in a game you need to watch and save your map (scene) scale. The scale changes from zero to infinity and you have to divide this into a particular number of ranges for example something like this:&#xD;&#xA;&#xD;&#xA;1. 1/zero = infinity to 1/50&#xD;&#xA;1. 1/50 to 1/100&#xD;&#xA;1. 1/100 to 1/1000&#xD;&#xA;1. 1/1000 to 1/infinity = 0&#xD;&#xA;&#xD;&#xA;So when your user uses zoom in and zoom out to change the magnification he moves through the above limits from one to the other range, and your game uses these display scales to manage level of detail.&#xD;&#xA;&#xD;&#xA;The above group of 4 ranges are just an example and you need to find the best for your own case by trial and error. There is no rule for that.&#xD;&#xA;&#xD;&#xA;You need to define which types of your objects (layers) should be visible or invisible in each of the above ranges. For example a small type of object like a hydrant valve should not be visible when the user is in the fourth range because it will be very small at that scale and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xD;&#xA;&#xD;&#xA;### The Euler polyhedron theorem.&#xD;&#xA;&#xD;&#xA;In most cases it is not necessary to implement a generalization algorithm, however it totally depends, case by case. Although it is an easy algorithm that just removes the small lats, you need to define a threshold which is the product of magnitude and a constant number, so bigger lats get filtered in a much farther point of view.&#xD;&#xA;&#xD;&#xA;Another continuous method which is completely based on Euler's theorem is to determine this threshold for each linear and polygonal object and show them only in the case that they are big enough to be discriminated.&#xD;&#xA;&#xD;&#xA;Note: magnification is a float number &gt; 0 which is equal to 1/scale and the scale is usually &lt; 1 since a 1:1 scale means you have real world lengths in your game.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Euler operators]: https://en.wikipedia.org/wiki/Euler_operator#Euler_operators_.28Euler_operations.29" ContentLicense="CC BY-SA 3.0" />
  <row Id="2322" PostHistoryTypeId="5" PostId="1446" RevisionGUID="bf36305a-b13a-4b9e-8cde-fdf436f10828" CreationDate="2015-09-06T12:50:27.540" UserId="537" Comment="added 1460 characters in body" Text="LOD (Level of Detail) means managing objects in different display scales, which could be devided by two parts. However, you may use one of them and that would be enough for most cases.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; 1. Show/hide layers ( group of objects of same type) depending on magnitude (display scale).&#xD;&#xA;&#xD;&#xA; 2. Algebraic Geomery based method, called Generalization (which is an algorithm to simplify polygons). look at the following picture&#xD;&#xA;&#xD;&#xA; ![generalization](http://i.imgur.com/pk7w0Ix.jpg)&#xD;&#xA;&#xD;&#xA;The most famous and efficient method to generalize (simplify) a polygon mesh is known as Descartes-Euler polyhedron theorem[1] and is used by most of the spatial databases for example PostGIS modules in PostgreSQL. It simply removes smaller sides of a polygon and makes a very rounded one.(above picture)&#xD;&#xA;&#xD;&#xA;To implement LOD in a game you need to save and manage the scale of your map (scene) during th zoom in/out operations. The scale changes from zero to infinity and you have to divide this into a particular number of ranges for example something like this:&#xD;&#xA;&#xD;&#xA; 1. 1/zero = infinity to 1/50&#xD;&#xA; 2. 1/50 to 1/100&#xD;&#xA; 3. 1/100 to 1/1000&#xD;&#xA; 4. 1/1000 to 1/infinity = 0&#xD;&#xA;&#xD;&#xA;Then you need to define which types of your objects (layers) should be visible or invisible in each of the above ranges. For example a small type of object like a hydrant valve should not be visible when the user is in the fourth range because it will be very small at that scale and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xD;&#xA;&#xD;&#xA;So when a user uses zoom in and zoom out to change the magnification he moves through the above limits from one to the other range, and your game uses these display scales to manage level of details by showing or hiding objects on the scene. This makes a discrete solution that objects suddenly fade during your zoom out operation, however having the display scales and magnification ranges defined carefully, the user woudn't feel anything.&#xD;&#xA;&#xD;&#xA;The above group of 4 ranges are just an example and you need to find the best for your own case by trial and error. There is no rule for that.&#xD;&#xA;&#xD;&#xA;Sometimes the games use their own LOD methods, Subway Surfer for instant, shows a small, without texture rectangle to show a building at far, and by getting close suddenly it gets texture,  gamer feels it. You didnt talk about your projection system which is very important also didn't talk about what kind of game you are creating.&#xD;&#xA;&#xD;&#xA;However suppose you are implementing a full 3D game with openGl and you wish to filter some mesh before transfering them to graphic hardware, I am sure this will help you to reduce binding/unbinding operations with buffer objects and vertex arrays (VBO,VAO) while dealing with OpenGl.&#xD;&#xA;&#xD;&#xA;&gt;Using only a layer managment or just implement Euler's Generalization&#xD;&#xA;&#xD;&#xA;In most cases it is not necessary to implement a generalization algorithm, and filtering objects just works and gets you to the efficiency(refresh rate) you need, however it totally depends, case by case. Although it is an easy algorithm that just removes the small sides of a polygon, you need to define a threshold which is the product of magnitude and a constant number, so bigger sides get filtered in a much farther point of view.&#xD;&#xA;&#xD;&#xA;Forgeting the layer manamgment and only implementing Eulers generalization algorithm, provides a very neat and continuous method in which you just check each sides and lines against a pre-defined threshold and show them only in case they are big enough to be discriminated on the screen.&#xD;&#xA;&#xD;&#xA;P.S : magnification is a float number &gt; 0 which is equal to 1/scale and the scale is usually &lt; 1 since a 1:1 scale means you have real world lengths in your game.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com/books?id=bNC1991jsFQC&amp;pg=PA218&amp;lpg=PA218&amp;dq=euler+polygon+generalization&amp;source=bl&amp;ots=Mh3RDkX3r-&amp;sig=syvn0z1c6RpJ7y7BOPRQP2c5I-4&amp;hl=en&amp;sa=X&amp;ved=0CCcQ6AEwAzgKahUKEwiix9HbsuLHAhXHuBQKHTr9AXs" ContentLicense="CC BY-SA 3.0" />
  <row Id="2323" PostHistoryTypeId="5" PostId="1446" RevisionGUID="9c095d98-af1a-4cd2-b255-fb6bc975b3bf" CreationDate="2015-09-06T12:58:28.883" UserId="537" Comment="deleted 96 characters in body" Text="LOD (Level of Detail) means managing objects in different display scales, which could be devided by two parts. However, you may use one of them and that would be enough for most cases.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; 1. Show/hide layers ( group of objects of same type) depending on magnitude (display scale).&#xD;&#xA;&#xD;&#xA; 2. Algebraic Geomery based method, called Generalization (which is an algorithm to simplify polygons). look at the following picture&#xD;&#xA;&#xD;&#xA; ![generalization](http://i.imgur.com/pk7w0Ix.jpg)&#xD;&#xA;&#xD;&#xA;The most famous and efficient method to generalize (simplify) a polygon mesh is known as [Descartes-Euler polyhedron theorem][1] (Equation 4.5 sorry if I am refering to a book, that was best I can do) and is used by most of the spatial databases for example PostGIS modules in PostgreSQL. It simply removes smaller sides of a polygon and makes a very rounded one.(above picture)&#xD;&#xA;&#xD;&#xA;To implement LOD in a game you need to save and manage the scale of your map (scene) during th zoom in/out operations. The scale changes from zero to infinity and you have to divide this into a particular number of ranges for example something like this:&#xD;&#xA;&#xD;&#xA; 1. 1/zero = infinity to 1/50&#xD;&#xA; 2. 1/50 to 1/100&#xD;&#xA; 3. 1/100 to 1/1000&#xD;&#xA; 4. 1/1000 to 1/infinity = 0&#xD;&#xA;&#xD;&#xA;Then you need to define which types of your objects (layers) should be visible or invisible in each of the above ranges. For example a small type of object like a hydrant valve should not be visible when the user is in the fourth range because it will be very small at that scale and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xD;&#xA;&#xD;&#xA;So when a user uses zoom in and zoom out to change the magnification he moves through the above limits from one to the other range, and your game uses these display scales to manage level of details by showing or hiding objects on the scene. This makes a discrete solution that objects suddenly fade during your zoom out operation, however having the display scales and magnification ranges defined carefully, the user woudn't feel anything.&#xD;&#xA;&#xD;&#xA;The above group of 4 ranges are just an example and you need to find the best for your own case by trial and error. There is no rule for that.&#xD;&#xA;&#xD;&#xA;Sometimes the games use their own LOD methods, Subway Surfer for instant, shows a small, without texture rectangle to show a building at far, and by getting close suddenly it gets texture,  gamer feels it. You didnt talk about your projection system which is very important also didn't talk about what kind of game you are creating.&#xD;&#xA;&#xD;&#xA;However suppose you are implementing a full 3D game with openGl and you wish to filter some mesh before transfering them to graphic hardware, I am sure this will help you to reduce binding/unbinding operations with buffer objects and vertex arrays (VBO,VAO) while dealing with OpenGl.&#xD;&#xA;&#xD;&#xA;&gt;Using only a layer managment or just implement Euler's Generalization&#xD;&#xA;&#xD;&#xA;In most cases it is not necessary to implement a generalization algorithm, and filtering objects just works and gets you to the efficiency(refresh rate) you need, however it totally depends, case by case. Although it is an easy algorithm that just removes the small sides of a polygon, you need to define a threshold which is the product of magnitude and a constant number, so bigger sides get filtered in a much farther point of view.&#xD;&#xA;&#xD;&#xA;Forgeting the layer manamgment and only implementing Eulers generalization algorithm, provides a very neat and continuous method in which you just check each sides and lines against a pre-defined threshold and show them only in case they are big enough to be discriminated on the screen.&#xD;&#xA;&#xD;&#xA;P.S : magnification is a float number &gt; 0 which is equal to 1/scale and the scale is usually &lt; 1 since a 1:1 scale means you have real world lengths in your game.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com/books?isbn=0080477267" ContentLicense="CC BY-SA 3.0" />
  <row Id="2324" PostHistoryTypeId="5" PostId="1446" RevisionGUID="83e31b21-91fe-4234-97d4-534fb852e960" CreationDate="2015-09-06T13:03:40.150" UserId="537" Comment="deleted 96 characters in body" Text="LOD (Level of Detail) means managing objects in different display scales, which could be devided by two parts. However, you may use one of them and that would be enough for most cases.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; 1. Show/hide layers ( group of objects of same type) depending on magnitude (display scale).&#xD;&#xA;&#xD;&#xA; 2. Algebraic Geomery based method, called Generalization (which is an algorithm to simplify polygons). look at the following picture&#xD;&#xA;&#xD;&#xA; ![generalization](https://i.stack.imgur.com/lYP5y.jpg)&#xD;&#xA;&#xD;&#xA;The most famous and efficient method to generalize (simplify) a polygon mesh is known as [Descartes-Euler polyhedron theorem][1] (Equation 4.5 sorry if I am refering to a book, that was best I can do) and is used by most of the spatial databases for example PostGIS modules in PostgreSQL. It simply removes smaller sides of a polygon and makes a very rounded one.(above picture)&#xD;&#xA;&#xD;&#xA;To implement LOD in a game you need to save and manage the scale of your map (scene) during th zoom in/out operations. The scale changes from zero to infinity and you have to divide this into a particular number of ranges for example something like this:&#xD;&#xA;&#xD;&#xA; 1. 1/zero = infinity to 1/50&#xD;&#xA; 2. 1/50 to 1/100&#xD;&#xA; 3. 1/100 to 1/1000&#xD;&#xA; 4. 1/1000 to 1/infinity = 0&#xD;&#xA;&#xD;&#xA;Then you need to define which types of your objects (layers) should be visible or invisible in each of the above ranges. For example a small type of object like a hydrant valve should not be visible when the user is in the fourth range because it will be very small at that scale and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xD;&#xA;&#xD;&#xA;So when a user uses zoom in and zoom out to change the magnification he moves through the above limits from one to the other range, and your game uses these display scales to manage level of details by showing or hiding objects on the scene. This makes a discrete solution that objects suddenly fade during your zoom out operation, however having the display scales and magnification ranges defined carefully, the user woudn't feel anything.&#xD;&#xA;&#xD;&#xA;The above group of 4 ranges are just an example and you need to find the best for your own case by trial and error. There is no rule for that.&#xD;&#xA;&#xD;&#xA;Sometimes the games use their own LOD methods, Subway Surfer for instant, shows a small, without texture rectangle to show a building at far, and by getting close suddenly it gets texture,  gamer feels it. You didnt talk about your projection system which is very important also didn't talk about what kind of game you are creating.&#xD;&#xA;&#xD;&#xA;However suppose you are implementing a full 3D game with openGl and you wish to filter some mesh before transfering them to graphic hardware, I am sure this will help you to reduce binding/unbinding operations with buffer objects and vertex arrays (VBO,VAO) while dealing with OpenGl.&#xD;&#xA;&#xD;&#xA;&gt;Using only a layer managment or just implement Euler's Generalization&#xD;&#xA;&#xD;&#xA;In most cases it is not necessary to implement a generalization algorithm, and filtering objects just works and gets you to the efficiency(refresh rate) you need, however it totally depends, case by case. Although it is an easy algorithm that just removes the small sides of a polygon, you need to define a threshold which is the product of magnitude and a constant number, so bigger sides get filtered in a much farther point of view.&#xD;&#xA;&#xD;&#xA;Forgeting the layer manamgment and only implementing Eulers generalization algorithm, provides a very neat and continuous method in which you just check each sides and lines against a pre-defined threshold and show them only in case they are big enough to be discriminated on the screen.&#xD;&#xA;&#xD;&#xA;P.S : magnification is a float number &gt; 0 which is equal to 1/scale and the scale is usually &lt; 1 since a 1:1 scale means you have real world lengths in your game.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com/books?isbn=0080477267" ContentLicense="CC BY-SA 3.0" />
  <row Id="2325" PostHistoryTypeId="2" PostId="1449" RevisionGUID="4cb4652d-6cd9-426e-b385-6acb7a403b1e" CreationDate="2015-09-06T13:21:32.750" UserId="1575" Text="Iman already prepared a complete answer but I wish to add something to it&#xD;&#xA;&#xD;&#xA;LOD can be done in two different way&#xD;&#xA;1. Continous which is called CLOD and is a polygon mesh optimization&#xD;&#xA;2. Discrete which almost every other algorithm than polygon mesh opt. considered to be in this group.&#xD;&#xA;&#xD;&#xA;For example mipmaping is a good,fast but heavy one that belongs to secound group at the above &#xD;&#xA;&#xD;&#xA;here you may find a good explanation to mipmaping and implementation code with OpenGl.&#xD;&#xA;&#xD;&#xA;http://people.cs.clemson.edu/~dhouse/courses/405/notes/OpenGL-mipmaps.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2326" PostHistoryTypeId="5" PostId="1449" RevisionGUID="d6951f34-1335-482a-b645-ee2bd3e48db7" CreationDate="2015-09-06T15:59:40.140" UserId="537" Comment="formatting correction" Text="Iman already prepared a complete answer but I wish to add something to it&#xD;&#xA;&#xD;&#xA;LOD can be done in two different way&#xD;&#xA;&#xD;&#xA; 1. Continous which is called CLOD and is a polygon mesh optimization&#xD;&#xA; 2. Discrete which almost every other algorithm than polygon mesh optimization, considered to be in this group.&#xD;&#xA;&#xD;&#xA;For example mipmaping is a good,fast but heavy one that belongs to secound group at the above &#xD;&#xA;&#xD;&#xA;here you may find a good explanation to mipmaping and implementation code with OpenGl.&#xD;&#xA;&#xD;&#xA;http://people.cs.clemson.edu/~dhouse/courses/405/notes/OpenGL-mipmaps.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2327" PostHistoryTypeId="24" PostId="1449" RevisionGUID="d6951f34-1335-482a-b645-ee2bd3e48db7" CreationDate="2015-09-06T15:59:40.140" Comment="Proposed by 537 approved by 38, 231 edit id of 48" ContentLicense="CC BY-SA 3.0" />
  <row Id="2328" PostHistoryTypeId="5" PostId="405" RevisionGUID="fcfc2fe3-6315-4aa0-bccf-df80cb695a1d" CreationDate="2015-09-06T16:07:07.420" UserId="482" Comment="Add commentary and meta links. remove postscript tag" Text="In my answer about [Affine Transformations](http://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392) I made some little illustrations to help the explanation.&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Ltr0w.png)&#xD;&#xA;&#xD;&#xA;How do you make an upload-able PNG quickly which expresses a geometrical or mathematical idea?&#xD;&#xA;&#xD;&#xA;*This question was contrived to support [my postscript answer]() but is intended to solicit other solutions that may benefit the SE network more generally. But for credibility, an answer must link to a post where this technique has in fact been used, as well as a sufficient &quot;howto&quot; portion if it involves more than something obvious like &quot;Select export from menu&quot;.*&#xD;&#xA;&#xD;&#xA;*There are two meta questions [here](http://meta.computergraphics.stackexchange.com/questions/147/simple-2d-illustrations-question-main-or-meta) and [here](http://meta.computergraphics.stackexchange.com/questions/150/2d-illustrations-question-help-crafting-the-question) concerning how to scope this question in light of the precedences it may set for our site.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="2329" PostHistoryTypeId="6" PostId="405" RevisionGUID="fcfc2fe3-6315-4aa0-bccf-df80cb695a1d" CreationDate="2015-09-06T16:07:07.420" UserId="482" Comment="Add commentary and meta links. remove postscript tag" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2330" PostHistoryTypeId="5" PostId="392" RevisionGUID="c876d840-7dde-4d59-baa5-e78079dc9048" CreationDate="2015-09-06T16:13:49.380" UserId="482" Comment="link to my underappreciated work" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;    (x', y')  =  (x, y) * [a  b] + (e, f)&#xD;&#xA;                          [c  d]&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair (x', y') from the original pair (x, y) and a list of constants (a, b, c, d, e, f).&#xD;&#xA;&#xD;&#xA;    x' =  a*x + c*y + e&#xD;&#xA;    y' =  b*x + d*y + f&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;    (x', y', 1) =  (x, y, 1) * [a b 0]&#xD;&#xA;                               [c d 0]&#xD;&#xA;                               [e f 1]&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;    (x&quot;, y&quot;, 1) = ( (x, y, 1) * [a b 0] ) * [g h 0] &#xD;&#xA;                                [c d 0]     [i j 0]&#xD;&#xA;                                [e f 1]     [k m 1]&#xD;&#xA;&#xD;&#xA;                = (ax+cy+e, bx+dy+f, 1) * [g h 0]&#xD;&#xA;                                          [i j 0]&#xD;&#xA;                                          [k m 1]&#xD;&#xA;&#xD;&#xA;                = (g(ax+cy+e) + i(bx+dy+f) + k, &#xD;&#xA;                   h(ax+cy+e) + j(bx+dy+f) + m,&#xD;&#xA;                   1)&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * ( [a b 0] * [g h 0] )&#xD;&#xA;                                [c d 0]   [i j 0]&#xD;&#xA;                                [e f 1]   [k m 1]&#xD;&#xA;&#xD;&#xA;                = (x, y, 1) * [ag+bi   ah+bj   0]&#xD;&#xA;                              [cg+di   ch+dj   0]&#xD;&#xA;                              [eg+fi+k eh+fj+m 1]&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;    1 0 0&#xD;&#xA;    0 1 0&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;    Sx 0  0&#xD;&#xA;    0  Sy 0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    0  1  0&#xD;&#xA;    Tx Ty 1&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;    1  Qx 0&#xD;&#xA;    0  1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;    1  0  0&#xD;&#xA;    Qy 1  0&#xD;&#xA;    0  0  1&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;    cos -sin 0&#xD;&#xA;    sin  cos 0&#xD;&#xA;    0    0   1&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;A matrix composed purely from scaling, rotation, and translation can be [decomposed back into these three components](http://stackoverflow.com/a/11942636/733077).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2331" PostHistoryTypeId="2" PostId="1450" RevisionGUID="5687211d-bef6-437d-a274-5dda245cb001" CreationDate="2015-09-06T17:16:09.613" UserId="1578" Text="I'm making a voxel engine in OpenGL and wondering how many 3D textures I can have at once. They are fairly large (256x256x256 in GL_R32UI format). I want it to be able to run on any graphics card supporting OpenGL 3.3, if possible. I'm accessing them all from the same fragment shader, by the way. So how many can I have? Will 8 work? Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="2332" PostHistoryTypeId="1" PostId="1450" RevisionGUID="5687211d-bef6-437d-a274-5dda245cb001" CreationDate="2015-09-06T17:16:09.613" UserId="1578" Text="How many 3D textures does OpenGL support" ContentLicense="CC BY-SA 3.0" />
  <row Id="2333" PostHistoryTypeId="3" PostId="1450" RevisionGUID="5687211d-bef6-437d-a274-5dda245cb001" CreationDate="2015-09-06T17:16:09.613" UserId="1578" Text="|opengl|3dtexture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2334" PostHistoryTypeId="2" PostId="1451" RevisionGUID="c9ee3a5d-f924-4e34-acc6-d2d47db5d372" CreationDate="2015-09-06T17:57:59.280" UserId="93" Text="For the geometry LOD most games simply switch between a number of predefined LOD meshes. For example &quot;Infamous: Second Son&quot; uses 3 LOD meshes ([Adrian Bentley - &quot;inFAMOUS: Second Son engine postmortem&quot;, GDC 2014]) and &quot;Killzone: Shadow Fall&quot; uses 7 LOD meshes per character ([Michal Valient - &quot;Killzone: Shadow fall demo postmortem&quot;, Devstation2013]). Most of them are generated, but more important ones (like main character) can be hand made. Meshes are often generated using a popular Simplygon middleware, but sometimes they are simply generated by graphics artists in their favorite 3D package.&#xD;&#xA;&#xD;&#xA;Games with a large draw distance additionally use imposters for foliage, trees and high buildings ([Adrian Bentley - &quot;inFAMOUS: Second Son engine postmortem&quot;, GDC 2014]). They also employ hierarchical LODs, which replace a set of objects with one. For example in &quot;Just Cause 2&quot; trees are first rendered individually as normal LOD meshes, then individually as imposters and finally as a single merged forest mesh ([Emil Persson, Joel de Vahl - &quot;Populating a Massive Game World&quot;, Siggraph2013]) and in &quot;Sunset Overdrive&quot; distant parts of the world are replaced by single automatically offline generated mesh ([Elan Ruskin - &quot;Streaming Sunset Overdrive's Open World&quot;, GDC2015]).&#xD;&#xA;&#xD;&#xA;Another component of a LOD system is simplification of materials and shaders. For example &quot;Killzone: Shadow Fall&quot; disables tangent space and normal mapping for the distant LODs ([Michal Valient - &quot;Killzone: Shadow fall demo postmortem&quot;, Devstation2013]). This usually is implemented by disabling globally a set of shader features per LOD, but for engines with shader graphs, where artists can create custom shaders, this needs to be done manually.&#xD;&#xA;&#xD;&#xA;For the LOD transitions some games simply switch meshes and some use dithering for smooth LOD transitions - at the LOD switch two meshes are rendered: first gradually fades out and second fades in ([Simon schreibt Blog - &quot;Assassins Creed 3 – LoD Blending&quot;]). Classic CPU progressive mesh techniques aren't used as they require a costly mesh update and upload to GPU. Hardware Tessellation is used in a few titles, but only for the refinement of a most detailed LOD, as it's slow and in general case it can't replace predefined geometry LODs.&#xD;&#xA;&#xD;&#xA;Terrain LODs are handled separately in order to exploit it's specific properties. Terrain geometry LOD is usually implemented using clipmaps ([Marcin Gollent - &quot;Landscape creation and rendering in REDengine 3&quot;]). Terrain material LODs either are handled similarly to mesh LODs or using some kind of a virtual texture [Ka Chen - &quot;Adaptive Virtual Texture Rendering In Far Cry 4].&#xD;&#xA;&#xD;&#xA;Finally if you are interested to see real game LOD pipelines then just browse through documentation of any of the modern games engines: [Unreal Engine 4 - &quot;Creating and Using LODs&quot;], [CryEgnine - Static LOD] and [Unity - LOD].&#xD;&#xA;&#xD;&#xA;  [Michal Valient - &quot;Killzone: Shadow fall demo postmortem&quot;, Devstation2013]:http://www.guerrilla-games.com/presentations/Valient_Killzone_Shadow_Fall_Demo_Postmortem.pdf&#xD;&#xA;  [Adrian Bentley - &quot;inFAMOUS: Second Son engine postmortem&quot;, GDC 2014]:http://suckerpunch.playstation.com/images/stories/GDC14_infamous_second_son_engine_postmortem.pdf&#xD;&#xA;  [Emil Persson, Joel de Vahl - &quot;Populating a Massive Game World&quot;, Siggraph2013]:http://www.humus.name/Articles/PopulatingAMassiveGameWorld.pptx&#xD;&#xA;  [Elan Ruskin - &quot;Streaming Sunset Overdrive's Open World&quot;, GDC2015]:http://s3.crashworks.org/gdc15/ElanRuskin_SunsetOverdrive_Streaming_notes.pdf&#xD;&#xA;  [Simon schreibt Blog - &quot;Assassins Creed 3 – LoD Blending&quot;]:http://simonschreibt.de/gat/assassins-creed-3-lod-blending/&#xD;&#xA;  [Unreal Engine 4 - &quot;Creating and Using LODs&quot;]:https://docs.unrealengine.com/latest/INT/Engine/Content/Types/StaticMeshes/HowTo/LODs/index.html&#xD;&#xA;  [CryEgnine - Static LOD]:http://docs.cryengine.com/pages/viewpage.action?pageId=15012200&#xD;&#xA;  [Unity - LOD]:http://docs.unity3d.com/Manual/LevelOfDetail.html&#xD;&#xA;  [Marcin Gollent - &quot;Landscape creation and rendering in REDengine 3&quot;]:http://gdcvault.com/play/1020197/Landscape-Creation-and-Rendering-in&#xD;&#xA;  [Ka Chen - &quot;Adaptive Virtual Texture Rendering In Far Cry 4]:http://twvideo01.ubm-us.net/o1/vault/gdc2015/presentations/Chen_Ka_AdaptiveVirtualTexture.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2336" PostHistoryTypeId="2" PostId="1452" RevisionGUID="f331778e-7cf9-42fa-8892-bc3e2f057a34" CreationDate="2015-09-06T20:31:32.580" UserId="528" Text="As gllampert pointed out in the comments the value is hardware dependent. You can retrieve it with [glGet][1], using `GL_MAX_COMBINED_TEXTURE_IMAGE_UNIT`. You can find how different hardware performs [here][2].&#xD;&#xA;&#xD;&#xA;However, in OpenGL 3 there is a lower bound of **at least 48 simultaneously used textures**, no matter which type. [[source][3]]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml&#xD;&#xA;  [2]: http://delphigl.de/glcapsviewer/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COMBINED_TEXTURE_IMAGE_UNIT&#xD;&#xA;  [3]: https://www.opengl.org/sdk/docs/man3/xhtml/glActiveTexture.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="2337" PostHistoryTypeId="5" PostId="1452" RevisionGUID="1f6f16de-47de-4bd7-a45c-60c919295601" CreationDate="2015-09-06T20:52:27.517" UserId="528" Comment="Fixed hardware data base link (typo)" Text="As gllampert pointed out in the comments the value is hardware dependent. You can retrieve it with [glGet][1], using `GL_MAX_COMBINED_TEXTURE_IMAGE_UNIT`. You can find how different hardware performs [here][2].&#xD;&#xA;&#xD;&#xA;However, in OpenGL 3 there is a lower bound of **at least 48 simultaneously used textures**, no matter which type. [[source][3]]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man3/xhtml/glGet.xml&#xD;&#xA;  [2]: http://delphigl.de/glcapsviewer/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS&#xD;&#xA;  [3]: https://www.opengl.org/sdk/docs/man3/xhtml/glActiveTexture.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="2338" PostHistoryTypeId="2" PostId="1453" RevisionGUID="e13cfabe-abf3-4b4e-8dc6-59fd6eb75f30" CreationDate="2015-09-06T21:08:56.360" UserId="1580" Text="Also check out the glTF models used in Cesium:&#xD;&#xA;&#xD;&#xA;* https://github.com/AnalyticalGraphicsInc/cesium/tree/master/Apps/SampleData/models&#xD;&#xA;* https://github.com/AnalyticalGraphicsInc/cesium/tree/master/Specs/Data/Models&#xD;&#xA;&#xD;&#xA;Patrick" ContentLicense="CC BY-SA 3.0" />
  <row Id="2339" PostHistoryTypeId="34" PostId="209" RevisionGUID="0bcc3d4c-eafa-40c5-ae18-fd021efe9b7a" CreationDate="2015-09-06T22:22:58.300" UserId="231" Comment="8" />
  <row Id="2340" PostHistoryTypeId="2" PostId="1454" RevisionGUID="8ff52860-727d-4418-9c4c-c720c53c71a0" CreationDate="2015-09-07T01:22:17.117" UserId="523" Text="I am not aware of hardware support for 3D anisotropic filtering.  I could be wrong about its existence though.  I believe it has been tried.&#xD;&#xA;&#xD;&#xA;The motivation for 2D anisotropic filtering is to prefilter the texture function over the screen area it falls under in a more accurate way than doing a box filter in texture space (usually, anisotropic filtering does _several_ box filters in texture space).&#xD;&#xA;&#xD;&#xA;This definition is key.  2D anisotropic filtering tries to:&#xD;&#xA;&gt; Integrate over the part of a flat surface that you can see&lt;br/&gt;(within a single pixel on the screen).&#xD;&#xA;&#xD;&#xA;What does 3D anisotropic filtering mean?&#xD;&#xA;&gt; Integrate over the part of  a . . . _volume?_ . . .  that you can . . . _see?_&lt;br/&gt;(within a single . . . _voxel?_ . . . on the screen)&#xD;&#xA;&#xD;&#xA;The best analogue I can think of would be doing some sort of 3D texture lookup anisotropically along the viewing ray.  This isn't quite a direct analogy.  Anyway, the problem with this is that when you're doing volume rendering, you actually care about how this integration is done a lot more than in the 2D case.&#xD;&#xA;&#xD;&#xA;Do you want absorption?  Emission?  (You need to do some kind of exponential to integrate.)  Do you want scattering?  (You need to do some kind of recursion or approximating blur to integrate).  And this doesn't even get into what kind of data the 3D texture stores.  Does this texture mean _opacity_, or does it mean _density_?  Is it _diffuse_ or is it _emission_?  All of these need to be integrated differently.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;New developments in volume rendering are happening all the time, and in any case there are so many variously suboptimal ways you could try to generalize 2D anisotropic filtering, the doubt expressed by the specification makes sense to me:&#xD;&#xA;&#xD;&#xA;&gt; Does the implementation . . . for 2D anisotropic texture filtering readily extend to 3D anisotropic texture filtering?&#xD;&#xA;&#xD;&#xA;No." ContentLicense="CC BY-SA 3.0" />
  <row Id="2341" PostHistoryTypeId="5" PostId="422" RevisionGUID="d22a1948-1d0e-4fcb-ac90-9b75266c819d" CreationDate="2015-09-07T07:59:28.727" UserId="385" Comment="Removed lots of float fs, shaders are float by default" Text="Extending Kostas Anagnostou's answer, a commonly used formula for desaturation is&#xD;&#xA;&#xD;&#xA;    float value = 0.3 * InputR + 0.59 * InputG + 0.11 * InputB;&#xD;&#xA;&#xD;&#xA;This accomodates the fact that different color hues are perceived with a different intensity by a human observer.&#xD;&#xA;&#xD;&#xA;Further following the example, you would then define some tint color that is multiplied with the desaturated value. Also you could mix the tinted image with your original to get a less drastic effect. In this case, we're mixing 80% of the desaturated image tinted with (1.0, 0.2, 0.2) with 20% of the original:&#xD;&#xA;&#xD;&#xA;    float3 tint = float3(1.0, 0.2, 0.2);&#xD;&#xA;    float tintMix = 0.8;&#xD;&#xA;    OutputR = tintMix * value * tint.r + (1.0 - tintMix) * InputR;&#xD;&#xA;    OutputG = tintMix * value * tint.g + (1.0 - tintMix) * InputG;&#xD;&#xA;    OutputB = tintMix * value * tint.b + (1.0 - tintMix) * InputB;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2343" PostHistoryTypeId="2" PostId="1455" RevisionGUID="311a7f7f-682e-4ea3-b848-590a4ec8708e" CreationDate="2015-09-07T11:53:53.267" UserDisplayName="user464" Text="I can draw 2D geometric primitives. I can draw points and lines in 3D.&#xD;&#xA;&#xD;&#xA;But, I can't draw 3D geometric primitives like plane, sphere, ellipsoid, cone, etc. I know the formula. But, don't know where to start from?&#xD;&#xA;&#xD;&#xA;I need to learn the inner principles. So, I am using [Colorado university's WinBGIm][1] library.&#xD;&#xA;&#xD;&#xA;How to start drawing 3D geometric primitives without using OpenGL/DirectX?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://winbgim.codecutter.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2344" PostHistoryTypeId="1" PostId="1455" RevisionGUID="311a7f7f-682e-4ea3-b848-590a4ec8708e" CreationDate="2015-09-07T11:53:53.267" UserDisplayName="user464" Text="How to get started with drawing 3D primitives without using OpenGL or DirectX?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2345" PostHistoryTypeId="3" PostId="1455" RevisionGUID="311a7f7f-682e-4ea3-b848-590a4ec8708e" CreationDate="2015-09-07T11:53:53.267" UserDisplayName="user464" Text="|3d|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2346" PostHistoryTypeId="5" PostId="1455" RevisionGUID="4b348961-5de8-4a15-911d-070bb09aafa4" CreationDate="2015-09-07T12:06:48.597" UserDisplayName="user464" Comment="added 64 characters in body" Text="I can draw 2D geometric primitives. I can draw points and lines in 3D.&#xD;&#xA;&#xD;&#xA;But, I can't draw 3D geometric primitives like plane, sphere, ellipsoid, cone, etc. &#xD;&#xA;&#xD;&#xA;I need to learn the inner principles. I need to implement some 3D algorithms like Z-buffer algorithm. I also need to learn how geometric representations like Wireframe Modelling works. So, I am using [Colorado university's WinBGIm][1] library. I know the formula of a sphere. But, don't know where to start from?&#xD;&#xA;&#xD;&#xA;How to start drawing 3D geometric primitives without using OpenGL/DirectX?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://winbgim.codecutter.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2347" PostHistoryTypeId="5" PostId="1455" RevisionGUID="d40f3b24-78b2-49a8-b22f-66399012a44b" CreationDate="2015-09-07T12:15:47.733" UserDisplayName="user464" Comment="deleted 398 characters in body" Text="I am learning computer graphics by self study. I have completed 2D part.&#xD;&#xA;&#xD;&#xA;Now, I need to learn how to deal with objects in 3D.&#xD;&#xA;&#xD;&#xA;I need to demonstrate &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://winbgim.codecutter.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2349" PostHistoryTypeId="5" PostId="1455" RevisionGUID="1722ad1b-d923-491d-9f0c-bd13e1155032" CreationDate="2015-09-07T12:18:01.663" UserDisplayName="user464" Comment="deleted 398 characters in body" Text="I am learning computer graphics by self study. I have completed 2D part.&#xD;&#xA;&#xD;&#xA;Now, I need to learn how to deal with objects in 3D. &#xD;&#xA;&#xD;&#xA;The target is to demonstrate some algorithms like clipping in 3D, hidden surface removal, etc. Then, I will advance my study by learning Geometric modeling, shading, shadowing, etc.&#xD;&#xA;&#xD;&#xA;So, first, I need to learn how to draw 3D objects using diagram format/outline of shapes.&#xD;&#xA;&#xD;&#xA;I am using a low-level library named [WinBGIm from colorado university][1].&#xD;&#xA;&#xD;&#xA;  [1]: http://winbgim.codecutter.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2351" PostHistoryTypeId="33" PostId="411" RevisionGUID="e08c6849-0a5b-4129-b73b-470ec333f06b" CreationDate="2015-09-07T16:58:58.323" UserId="231" Comment="11" />
  <row Id="2352" PostHistoryTypeId="33" PostId="309" RevisionGUID="0892a673-3c16-4f6c-b996-6cb89a8158a5" CreationDate="2015-09-07T17:01:44.800" UserId="231" Comment="12" />
  <row Id="2353" PostHistoryTypeId="5" PostId="1455" RevisionGUID="54a5e4e6-1bc0-40ec-ad51-582a2c7889fb" CreationDate="2015-09-07T19:31:07.597" UserDisplayName="user464" Comment="added 222 characters in body" Text="I am learning computer graphics by self study. I have completed 2D part.&#xD;&#xA;&#xD;&#xA;Now, I need to learn how to deal with objects in 3D. &#xD;&#xA;&#xD;&#xA;The target is to demonstrate some algorithms like clipping in 3D, hidden surface removal, etc. Then, I will advance my study by learning Geometric modeling, shading, shadowing, etc.&#xD;&#xA;&#xD;&#xA;So, first, I need to learn how to draw 3D objects using diagram format/outline of shapes.&#xD;&#xA;&#xD;&#xA;I am using a low-level library named [WinBGIm from colorado university][1].&#xD;&#xA;&#xD;&#xA;For example, how to draw this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And, this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://winbgim.codecutter.org/&#xD;&#xA;  [2]: https://i.stack.imgur.com/35GPL.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/1zy5r.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2354" PostHistoryTypeId="2" PostId="1456" RevisionGUID="8c9c2291-6445-41f8-aa40-e32fb75c590d" CreationDate="2015-09-07T23:16:56.550" UserId="1578" Text="Scratchapixel has a nice tutorial on writing a basic rasterizer [here](http://scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation). Also, you could use the projection algorithm [here](http://www.dreamincode.net/forums/topic/239174-3d-perspective-projection/) to get the position of the vertices in screen space, then use Bresenham's algorithm or DDA to draw lines in between. If you want to fill them too you can use scanline (you can find it on Wikipedia).&#xD;&#xA;&#xD;&#xA;For ellipsoids, you can either just turn them into a triangle mesh, or the approach [here](http://comp.graphics.algorithms.narkive.com/0JsT26Rp/efficiently-rasterize-ellipsoid) might work, although I haven't tried it.&#xD;&#xA;&#xD;&#xA;The Z-Buffer algorithm is very straightforward, just calculate the distance from the point to the camera and store that somewhere for each pixel, then make sure that that's less than whatever was already there." ContentLicense="CC BY-SA 3.0" />
  <row Id="2358" PostHistoryTypeId="2" PostId="1458" RevisionGUID="384cd1fc-c7ba-4186-aa82-f64fc8524754" CreationDate="2015-09-08T03:52:28.850" UserId="38" Text="FBX is a pretty common interchange format for 3D animation software. The format is originally made for a software called filmbox which handled motion capture data (since renamed to Motion Builder). Currently the format is owned by Autodesk who make and maintain a sdk for the format.&#xD;&#xA;&#xD;&#xA;The Bone structures and mesh bindings are pretty basic functions within 3D modellimg and animation applications. Possible applocations are (in alphabetic order):&#xD;&#xA;&#xD;&#xA;* 3DS Max&#xD;&#xA;* Blender&#xD;&#xA;* Cinema 4D&#xD;&#xA;* Lightwave3D&#xD;&#xA;* Maya&#xD;&#xA;* Modo&#xD;&#xA;* Motion Builder (this is the software the format is built for)&#xD;&#xA;* SoftImage3D&#xD;&#xA;&#xD;&#xA;What app to choose depends on your exact needs\*. For example do you need to retarget a existing animation to the new bone structure?&#xD;&#xA;&#xD;&#xA;Many of the game engines also suppprt FBX and possibly limited tweaking within their editor. Atleast Unreal and Unity support fbx. And if you do not try to do anything really invasive you might be able to use these tools.&#xD;&#xA;&#xD;&#xA;\* using these apps is outside the scope of this forum.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2359" PostHistoryTypeId="5" PostId="1458" RevisionGUID="c2a2b115-695c-4fa2-875e-0bd1ccf62b6e" CreationDate="2015-09-08T03:58:26.653" UserId="38" Comment="edited body" Text="FBX is a pretty common interchange format for 3D animation software. The format is originally made for a software called filmbox which handled motion capture data (since renamed to Motion Builder). Currently the format is owned by Autodesk who make and maintain a sdk for the format.&#xD;&#xA;&#xD;&#xA;The Bone structures and mesh bindings are pretty basic functions within 3D modellimg and animation applications. Possible applications are (in alphabetic order):&#xD;&#xA;&#xD;&#xA;* 3DS Max&#xD;&#xA;* Blender&#xD;&#xA;* Cinema 4D&#xD;&#xA;* Lightwave3D&#xD;&#xA;* Maya&#xD;&#xA;* Modo&#xD;&#xA;* Motion Builder (this is the software the format is built for)&#xD;&#xA;* SoftImage3D&#xD;&#xA;&#xD;&#xA;What app to choose depends on your exact needs\*. For example do you need to retarget a existing animation to the new bone structure?&#xD;&#xA;&#xD;&#xA;Many of the game engines also suppprt FBX and possibly limited tweaking within their editor. Atleast Unreal and Unity support fbx. And if you do not try to do anything really invasive you might be able to use these tools.&#xD;&#xA;&#xD;&#xA;\* using these apps is outside the scope of this forum.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2361" PostHistoryTypeId="2" PostId="1459" RevisionGUID="b748a841-b3af-4f67-a6fb-e0f71c56cb21" CreationDate="2015-09-08T11:56:20.203" UserDisplayName="user464" Text="What is the practical difference between 3D Graphics Engine (OGRE), 3D Game Engine (Quake), 3D Software Rendering Engine(??), 3D Graphics API (OpenGL/DitectX)?&#xD;&#xA;&#xD;&#xA;Is OpenGL/DitectX 3D Graphics API or 3D Software Rendering Engine?&#xD;&#xA;&#xD;&#xA;If I want to start learning 3D computer graphics and geometric modeling, which one do I need?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2362" PostHistoryTypeId="1" PostId="1459" RevisionGUID="b748a841-b3af-4f67-a6fb-e0f71c56cb21" CreationDate="2015-09-08T11:56:20.203" UserDisplayName="user464" Text="What is the practical difference between 3D Graphics Engine, 3D Game Engine, 3D ........?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2363" PostHistoryTypeId="3" PostId="1459" RevisionGUID="b748a841-b3af-4f67-a6fb-e0f71c56cb21" CreationDate="2015-09-08T11:56:20.203" UserDisplayName="user464" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2364" PostHistoryTypeId="2" PostId="1460" RevisionGUID="785fd4bf-b97d-42f6-a35d-7e61ed299b1e" CreationDate="2015-09-08T12:35:15.227" UserId="385" Text="At the base, **rendering APIs** like OpenGL or Direct3D provide a unified interface to communicate with graphics adapters at a low level. Differences in hardware are hidden behind the abstraction which simplifies development a lot.&#xD;&#xA;&#xD;&#xA;The low-level APIs provide basic functionality, which gives you total control but leaves you without a lot of desired features. **3D Rendering Frameworks** like OGRE or Irrlicht introduce the more understandable concept of 3D objects that can be moved in space (without having to worry about transformation matrices most of the time), introduce light sources and algorithms for shadow casting (e.g. shadow mapping), loading of common mesh formats, and the list goes on. I call this a *framework*, because you still need to develop the application yourself using actual code, while an *engine* provides you with an application to develop your software in. This is just my personal distinction and both terms are used differently in a variety of contexts.&#xD;&#xA;&#xD;&#xA;In a **3D Authoring / Rendering Software** like Blender or Autodesk Maya (offline) or 3DExcite DeltaGen (realtime) you can load, display or create meshes using the built-in functionality. These applications target the creation of 3D data, images or movies, and you can't usually create interactive applications with it.&#xD;&#xA;&#xD;&#xA;A **3D Game Engine** finally provides you with all the tools to make it easy for you to develop a game. You will usually be provided with a level editor, a material editor and maybe a visible scripting language (like Unreal's Blueprint or earlier Kismet) to implement dynamic behaviour and interactivity. You don't have to worry about rendering algorithms, because they are already implemented for you. Your engine of choice may for example feature [SSAO][1] and [cascaded shadow maps][2] for dynamic objects and a solution to bake global illumination for static geometry. Also, a game engine includes way more than only rendering, e.g. artifical intelligence, sound, loading of assets, exporting your content into a ready-to-install package etc.&#xD;&#xA;&#xD;&#xA;As you can see, each software package puts another layer of abstraction on, ideally making your life simpler. Each has its own purpose and allows you to do different things.&#xD;&#xA;&#xD;&#xA;  [1]: http://people.mpi-inf.mpg.de/~ritschel/Papers/SSDO.pdf&#xD;&#xA;  [2]: http://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2365" PostHistoryTypeId="5" PostId="412" RevisionGUID="de91cd29-6dec-4051-870a-20b7931dd4f2" CreationDate="2015-09-08T18:22:51.277" UserId="14" Comment="used mathurl" Text="You approach will work, and in general any square of size &lt; [![enter image description here][1]][1] will work fine because the invariant &quot;at most 1 point per square&quot; is valid. Extrapolating from your idea, it means that one should get the best reduction in area checks for infinitesimally small squares. But we don't want to do that, right?&#xD;&#xA;&#xD;&#xA;There are two reasons why [![enter image description here][2]][2] is usually better than [![enter image description here][3]][3]:&#xD;&#xA;&#xD;&#xA; 1. How much state do you want to manage? Each square can either be &quot;occupied&quot; or &quot;unoccupied&quot; and contains a pointer to its sample point (if any).&#xD;&#xA;&#xD;&#xA;    For very large domains with small r, storage costs can be hard to manage. The problem is much worse if you're working with many dimensions. See [Gamito et al.'s paper][4], Figure 12. Even in 4D you can be severely storage limited.&#xD;&#xA;&#xD;&#xA; 2. In your proposed grid size, each candidate points checks 24 squares, as opposed to 20 in the usual method. There is a per-square cost (e.g. checking whether square is occupied and fetching sample point if it is) which increases the overall cost in your method.&#xD;&#xA;&#xD;&#xA;**Basically, your method works, but it is usually not more efficient.** &#xD;&#xA;&#xD;&#xA;However, the state of the art in unbiased Poisson-disk sampling techniques actually successively reduces the grid size as the uncovered area reduces. In addition to [Gamito et al.'s paper][4], also see [Ebeida et al.'s paper][5].&#xD;&#xA;&#xD;&#xA;P.S. Sorry, I don't know how to do math formatting in Stack Exchange.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sYEU8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SnBBv.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/qH0GY.png&#xD;&#xA;  [4]: http://staffwww.dcs.shef.ac.uk/people/S.Maddock/research/gamito/papers/poisson.pdf&#xD;&#xA;  [5]: http://www.sandia.gov/~samitch/papers/eurographics_mps-final-with-appendix.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2367" PostHistoryTypeId="2" PostId="1461" RevisionGUID="602b9ee7-926c-46ce-88c4-457669dc5738" CreationDate="2015-09-08T23:27:42.983" UserId="14" Text="I have heard from many sources that having T-junctions in 3D meshes is a bad idea because it could result in cracks during rendering. Can someone explain why that happens, and what one can do to avoid them?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2368" PostHistoryTypeId="1" PostId="1461" RevisionGUID="602b9ee7-926c-46ce-88c4-457669dc5738" CreationDate="2015-09-08T23:27:42.983" UserId="14" Text="Why do T-junctions in meshes result in cracks?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2369" PostHistoryTypeId="3" PostId="1461" RevisionGUID="602b9ee7-926c-46ce-88c4-457669dc5738" CreationDate="2015-09-08T23:27:42.983" UserId="14" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2371" PostHistoryTypeId="2" PostId="1462" RevisionGUID="b2443fd2-f9a7-4c7e-aed2-3a90afabd32a" CreationDate="2015-09-09T01:44:12.587" UserId="192" Text="When modeling parametric surfaces with a mesh in the parameter domain, T-junctions will most probably appear as *discontinuities* in the surface. These will show up as gaps in the rendering. See below.&#xD;&#xA;&#xD;&#xA;More generally, T-junctions in triangle meshes will probably result in discontinuities of interpolated attributes, such as color and normals.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ma41k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/d2248.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2372" PostHistoryTypeId="5" PostId="1462" RevisionGUID="b1bda786-2c61-4e5f-86f8-efca1d1ba391" CreationDate="2015-09-09T01:52:32.200" UserId="192" Comment="added 2 characters in body" Text="When modeling parametric surfaces with a mesh in the parameter domain, T-junctions will most probably appear as *discontinuities* in the surface. These will show up as gaps in the rendering. See below.&#xD;&#xA;&#xD;&#xA;More generally, T-junctions in triangle meshes will probably result in discontinuities of interpolated attributes, such as color and normals.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5U2ei.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/d2248.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2373" PostHistoryTypeId="2" PostId="1463" RevisionGUID="26de26de-ba62-4bff-ab2d-817b05e7497f" CreationDate="2015-09-09T08:04:11.530" UserId="137" Text="Floating-point rounding error.&#xD;&#xA;&#xD;&#xA;After you transform the T junction and the point in the T can get rounded away from the edge.&#xD;&#xA;&#xD;&#xA;Then it can happen that a fragment that gets sampled for a pixel lies in the gap between the 2 surfaces.&#xD;&#xA;&#xD;&#xA;This can be fixed by not having a T-junction in the first place." ContentLicense="CC BY-SA 3.0" />
  <row Id="2375" PostHistoryTypeId="2" PostId="1464" RevisionGUID="c434ece0-b5b1-42a4-96b3-e83420b986a1" CreationDate="2015-09-09T08:38:29.530" UserId="209" Text="lhf's answer is good from the perspective of tessellation, but these can occur with simpler triangle mesh use cases.&#xD;&#xA;&#xD;&#xA;Take this simple example of three triangles, ABC, ADE and DBE...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;Although point E was, mathematically, intended to be exactly on the line segment AB, the modelling and rendering system won't be using fully precise value, such as rational numbers (e.g. https://gmplib.org/). Instead, it will likely be using floats, and so some approximation/error will be introduced. The result is likely to be something like:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that *all* of the vertices may have inaccuracies. Although the example above shows a crack, the T-junction may instead result in overlap along the edge causing pixels to be drawn twice. This might not seem as bad, but can cause problems with transparency or stencil operations.&#xD;&#xA;&#xD;&#xA;You *might* then think that with floating-point the error introduced will be insignificant, but in a renderer, the vertex positions *are nearly always represented by fixed-point numbers* and so the displacement from the ideal location will usually be much greater. Further, as the rendering hardware &quot;interpolates&quot; the line segment pixel-by-pixel with its own internal precision, there is even more chance it will diverge from the rounded location of E.&#xD;&#xA;&#xD;&#xA;If the T-junction is &quot;removed&quot; by, say, also dividing triangle ABC into two, i.e. AEC and EBC, the problem will go away as the shifts introduced by the errors will all be consistent.&#xD;&#xA;&#xD;&#xA;Now, you might ask why do renderers (especially HW) use fixed-point maths for the vertex XY coordinates? Why don't they use floating-point in order to reduce the problem? Although some did (e.g. Sega's Dreamcast) it can lead to another problem where the triangle set-up maths becomes catastrophically inaccurate, particularly for long-thin triangles, and they change size in unpleasant ways.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sFxmG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QYZw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2376" PostHistoryTypeId="2" PostId="1465" RevisionGUID="9d5ab094-61c0-45c8-97d8-922fae15d377" CreationDate="2015-09-09T09:04:21.967" UserId="118" Text="The simple way to avoid this is to ensure that all your vertices are welded&#xD;&#xA;&#xD;&#xA;You issue is that you have cuts along edges with a vertex, but you do not have a corresponding vertex on the adjacent edge to weld/connect it to, if you think of it like a button on a shirt, you've sown on a button to the edge, but haven't given it a hole so the fabric is open.&#xD;&#xA;&#xD;&#xA;In the picture below, the red dots represent correctly welded vertices, the blue dots all need an additional vertex to be cut in to the adjacent edge.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Generally speaking it is good practice to keep your modelling in quad's &amp; tri's, this helps to alleviate this issue as you should always have a corresponding vertex to weld too. It also helps to keep to quads if you plan to use any subdivision methods on the mesh.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xy7f2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2378" PostHistoryTypeId="5" PostId="1464" RevisionGUID="bfc1d8bf-c895-4775-9a25-5db0fd7322f0" CreationDate="2015-09-09T09:41:51.910" UserId="209" Comment="fixed some repetitive text" Text="lhf's answer is good from the perspective of tessellation, but these can occur with simpler triangle mesh use cases.&#xD;&#xA;&#xD;&#xA;Take this simple example of three triangles, ABC, ADE and DBE...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;Although point E was, mathematically, intended to be exactly on the line segment AB, the modelling and rendering system won't be using fully precise values, such as rational numbers (e.g. https://gmplib.org/). Instead, it will likely be using floats, and so some approximation/error will be introduced. The result is probably going to be something like:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that *all* of the vertices may have inaccuracies. Although the example above shows a crack, the T-junction may instead result in overlap along the edge causing pixels to be drawn twice. This might not seem as bad, but can cause problems with transparency or stencil operations.&#xD;&#xA;&#xD;&#xA;You *might* then think that with floating-point the error introduced will be insignificant, but in a renderer, the vertex positions *are nearly always represented by fixed-point numbers* and so the displacement from the ideal location will usually be much greater. Further, as the rendering hardware &quot;interpolates&quot; the line segment pixel-by-pixel with its own internal precision, there is even more chance it will diverge from the rounded location of E.&#xD;&#xA;&#xD;&#xA;If the T-junction is &quot;removed&quot; by, say, also dividing triangle ABC into two, i.e. AEC and EBC, the problem will go away as the shifts introduced by the errors will all be consistent.&#xD;&#xA;&#xD;&#xA;Now, you might ask why do renderers (especially HW) use fixed-point maths for the vertex XY coordinates? Why don't they use floating-point in order to reduce the problem? Although some did (e.g. Sega's Dreamcast) it can lead to another problem where the triangle set-up maths becomes catastrophically inaccurate, particularly for long-thin triangles, and they change size in unpleasant ways.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sFxmG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QYZw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2379" PostHistoryTypeId="5" PostId="1464" RevisionGUID="9ceab9f5-1b0a-4ec2-b8f2-965bc1a51fd3" CreationDate="2015-09-09T11:06:15.587" UserId="209" Comment="improved grammar" Text="lhf's answer is good from the perspective of tessellation, but these can occur with simpler triangle mesh use cases.&#xD;&#xA;&#xD;&#xA;Take this simple example of three triangles, ABC, ADE and DBE...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;Although point E was, mathematically, intended to be exactly on the line segment AB, the modelling and rendering system won't be using fully precise values, such as rational numbers (e.g. https://gmplib.org/). Instead, it will likely be using floats, and so some approximation/error will be introduced. The result is probably going to be something like:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that *all* of the vertices may have inaccuracies. Although the example above shows a crack, the T-junction may instead result in overlap along the edge causing pixels to be drawn twice. This might not seem as bad, but it can cause problems with transparency or stencil operations.&#xD;&#xA;&#xD;&#xA;You *might* then think that with floating-point the error introduced will be insignificant, but in a renderer, the vertex positions *are nearly always represented by fixed-point numbers* and so the displacement from the ideal location will usually be much greater. Further, as the rendering hardware &quot;interpolates&quot; the line segment pixel-by-pixel with its own internal precision, there is even more chance it will diverge from the rounded location of E.&#xD;&#xA;&#xD;&#xA;If the T-junction is &quot;removed&quot; by, say, also dividing triangle ABC into two, i.e. AEC and EBC, the problem will go away as the shifts introduced by the errors will all be consistent.&#xD;&#xA;&#xD;&#xA;Now, you might ask why do renderers (especially HW) use fixed-point maths for the vertex XY coordinates? Why don't they use floating-point in order to reduce the problem? Although some did (e.g. Sega's Dreamcast) it can lead to another problem where the triangle set-up maths becomes catastrophically inaccurate, particularly for long-thin triangles, and they change size in unpleasant ways.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sFxmG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QYZw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2380" PostHistoryTypeId="5" PostId="1464" RevisionGUID="50af1b14-ee7d-410d-9a8b-1097114c5578" CreationDate="2015-09-09T12:40:37.310" UserId="209" Comment="Made it more specific that's it's the X&amp;Y values that are going to be fixed-point" Text="lhf's answer is good from the perspective of tessellation, but these can occur with simpler triangle mesh use cases.&#xD;&#xA;&#xD;&#xA;Take this simple example of three triangles, ABC, ADE and DBE...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;Although point E was, mathematically, intended to be exactly on the line segment AB, the modelling and rendering system won't be using fully precise values, such as rational numbers (e.g. https://gmplib.org/). Instead, it will likely be using floats, and so some approximation/error will be introduced. The result is probably going to be something like:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that *all* of the vertices may have inaccuracies. Although the example above shows a crack, the T-junction may instead result in overlap along the edge causing pixels to be drawn twice. This might not seem as bad, but it can cause problems with transparency or stencil operations.&#xD;&#xA;&#xD;&#xA;You *might* then think that with floating-point the error introduced will be insignificant, but in a renderer, the vertex (X,Y) values *are nearly always represented by fixed-point numbers* and so the displacement from the ideal location will usually be much greater. Further, as the rendering hardware &quot;interpolates&quot; the line segment pixel-by-pixel with its own internal precision, there is even more chance it will diverge from the rounded location of E.&#xD;&#xA;&#xD;&#xA;If the T-junction is &quot;removed&quot; by, say, also dividing triangle ABC into two, i.e. AEC and EBC, the problem will go away as the shifts introduced by the errors will all be consistent.&#xD;&#xA;&#xD;&#xA;Now, you might ask why do renderers (especially HW) use fixed-point maths for the vertex XY coordinates? Why don't they use floating-point in order to reduce the problem? Although some did (e.g. Sega's Dreamcast) it can lead to another problem where the triangle set-up maths becomes catastrophically inaccurate, particularly for long-thin triangles, and they change size in unpleasant ways.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sFxmG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QYZw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2382" PostHistoryTypeId="36" PostId="1466" RevisionGUID="493337a3-355f-4271-a611-1e73d1f9d796" CreationDate="2015-09-09T13:31:16.620" UserId="-1" Comment="from http://blender.stackexchange.com/questions/38271/physically-based-rendering-and-ray-tracing" />
  <row Id="2383" PostHistoryTypeId="2" PostId="1466" RevisionGUID="bb2e9eb7-e16c-4640-919c-74915aa73dcc" CreationDate="2015-09-09T09:08:28.230" UserId="1605" UserDisplayName="Marina Cooper" Text="I've got a lot of confusion and I need to clarify some terminology and put together the knowledge.  &#xD;&#xA;If I say that an engine is a ray tracer (so it uses the ray tracing algorithm to render the scene), is it automatically a physically based engine? I mean, ray tracing is by its definition physically based or there could be some ray tracers that are not physically based? (and, symmetrically, are there some non-ray tracers that are physically based?)  &#xD;&#xA;Also, is it true that &quot;physically based&quot; means also that &quot;resolves the light transport equation&quot; ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2384" PostHistoryTypeId="1" PostId="1466" RevisionGUID="bb2e9eb7-e16c-4640-919c-74915aa73dcc" CreationDate="2015-09-09T09:08:28.230" UserId="1605" UserDisplayName="Marina Cooper" Text="Physically based rendering and ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="2385" PostHistoryTypeId="3" PostId="1466" RevisionGUID="bb2e9eb7-e16c-4640-919c-74915aa73dcc" CreationDate="2015-09-09T09:08:28.230" UserId="1605" UserDisplayName="Marina Cooper" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2386" PostHistoryTypeId="5" PostId="1436" RevisionGUID="d3f4ff00-cf31-4cfd-80cb-961ff7ca1750" CreationDate="2015-09-09T13:35:01.780" UserId="385" Comment="I'll delete my (referenced) incomplete answer, so I added the additional information from it to this answer." Text="The texture filtering hardware takes several samples of the various mipmap levels (the maximum amount of samples is indicated by the anisotropic filtering level, though the exact amount of samples taken in a given filtering operation will depend on the proportion between the derivatives on the fragment.) If you project the cone viewing a surface at an oblique angle onto the texture space, it will result in approximately an oval shaped projection, which is more elongated for more oblique angles. Extra samples are taken along the axis of this oval (from the correct mip levels, to take advantage of the pre-filtering they offer) and combined to give a sharper texture sample.&#xD;&#xA;&#xD;&#xA;Another technique know as [rip-mapping][3] (mentioned in the Wikipedia article on Mipmapping), which is *not* commonly found in contemporary GPUs, uses prefiltering of textures. In contrast to mips, the texture is not scaled down uniformly but using various height-width-ratios (up to a ratio dependent on your chosen anisotropic filtering level). The variant - or maybe two variants if using trilinear filtering - of the texture is then chosen based on the angle of the surface to minimize distortion. Pixel values are fetched using default filtering techniques (bilinear or trilinear). Rip-maps are not used in any hardware that I know of due to their prohibitive size: while mipmaps use additional 33% storage, ripmaps use 300%. This can be verified by noting that texture usage requirements don't increase when using AF, rather, only bandwidth does.&#xD;&#xA;&#xD;&#xA;For futher reading, you might want to take a look at [High-Performance Software Rasterization on GPUs][4] (Laine, Karras). They have indeed implemented a complete software graphics pipeline on a GPU and provide lots of valuable information on the inner workings of current hardware.&#xD;&#xA;&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Mipmap&#xD;&#xA;  [4]: https://mediatech.aalto.fi/~samuli/publications/laine2011hpg_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2387" PostHistoryTypeId="24" PostId="1436" RevisionGUID="d3f4ff00-cf31-4cfd-80cb-961ff7ca1750" CreationDate="2015-09-09T13:35:01.780" Comment="Proposed by 385 approved by 56, 231 edit id of 49" ContentLicense="CC BY-SA 3.0" />
  <row Id="2388" PostHistoryTypeId="2" PostId="1467" RevisionGUID="5c62cc17-a108-452a-b727-f068c1549f3b" CreationDate="2015-09-09T14:23:46.073" UserId="1606" Text="I am looking for a good introduction to Lane-Riesenfeld algorithms, which are a family of subdivision methods for generating uniform B-splines. Any suggestions?&#xD;&#xA;&#xD;&#xA;Note: This is a copy of the question I asked on Mathematics StackExchange. One of the users there suggested this site might have more answers to offer." ContentLicense="CC BY-SA 3.0" />
  <row Id="2389" PostHistoryTypeId="1" PostId="1467" RevisionGUID="5c62cc17-a108-452a-b727-f068c1549f3b" CreationDate="2015-09-09T14:23:46.073" UserId="1606" Text="An introduction to Lane-Riesenfeld algorithms" ContentLicense="CC BY-SA 3.0" />
  <row Id="2390" PostHistoryTypeId="3" PostId="1467" RevisionGUID="5c62cc17-a108-452a-b727-f068c1549f3b" CreationDate="2015-09-09T14:23:46.073" UserId="1606" Text="|algorithm|geometry|subdivision|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2391" PostHistoryTypeId="5" PostId="1467" RevisionGUID="fe3b6979-9493-49bd-b534-3981be6cf9fd" CreationDate="2015-09-09T15:59:58.710" UserId="1606" Comment="added 113 characters in body" Text="I am looking for a good introduction to Lane-Riesenfeld algorithms, which are a family of subdivision methods for generating uniform B-splines. Any suggestions?&#xD;&#xA;&#xD;&#xA;*Note.* This is a copy of [the question I asked on Mathematics StackExchange][1]. One of the users there suggested this site might have more answers to offer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/questions/1428101/an-introduction-to-lane-riesenfeld-algorithms" ContentLicense="CC BY-SA 3.0" />
  <row Id="2392" PostHistoryTypeId="2" PostId="1468" RevisionGUID="4e986745-1607-4071-8eda-7cfc1b5d4b39" CreationDate="2015-09-09T16:46:00.053" UserId="79" Text="&quot;Physically based&quot; is not a very well defined term, so it's difficult to answer this question exactly.&#xD;&#xA;&#xD;&#xA;In general, &quot;physically based&quot; refers to the fact that the algorithm in question is derived from physically based principles. It's not physically correct (because we can't afford that) and some approximations usually have to be made, but it's well known what those approximations are and ideally there is some intuition as to what kind of error it introduces.&#xD;&#xA;&#xD;&#xA;This is in contrast to ad hoc models, which are usually made by an artist who observes an effect in real life and tries to write a shader or similar that somehow mimics the look of it. Usually ad hoc models are simpler and cheaper and tend to be the first solutions to turn up for a given problem, but they don't offer any particular insight into what's actually happening. It's also practically impossible to say how accurately such a model is able to reproduce the effect that it attempts to simulate.&#xD;&#xA;&#xD;&#xA;In the context of rendering, a &quot;physically based renderer&quot; would therefore be simply something that renders an image using physically based principles, which is a very vague classification. A ray tracer is not inherently physically based, and most early ray tracers in fact used ad hoc models for lighting and similar. From my personal experience, &quot;physically based rendering&quot; used to usually refer to solving the rendering equation. However, it seems that in recent years, many game engines have claimed this term as well to mean &quot;we do energy conservation&quot; or &quot;we no longer use phong&quot;.&#xD;&#xA;&#xD;&#xA;So really, there's no hard classification of what &quot;physically based rendering&quot; means, and using ray tracing by itself does not make a renderer physically based. In offline rendering, this term is still mostly used to refer to renderers that solve the rendering equation, whereas in real-time rendering, it more likely refers to the use of microfacet models or similar. But it's possible that the meaning of this term will change over the years." ContentLicense="CC BY-SA 3.0" />
  <row Id="2393" PostHistoryTypeId="5" PostId="1436" RevisionGUID="2e77379e-91b4-40f8-b96e-57feff88ce54" CreationDate="2015-09-09T18:33:28.380" UserId="327" Comment="Replaced paper link with a reference to the EXT_texture_filter_anisotropic extension spec" Text="The texture filtering hardware takes several samples of the various mipmap levels (the maximum amount of samples is indicated by the anisotropic filtering level, though the exact amount of samples taken in a given filtering operation will depend on the proportion between the derivatives on the fragment.) If you project the cone viewing a surface at an oblique angle onto the texture space, it will result in approximately an oval shaped projection, which is more elongated for more oblique angles. Extra samples are taken along the axis of this oval (from the correct mip levels, to take advantage of the pre-filtering they offer) and combined to give a sharper texture sample.&#xD;&#xA;&#xD;&#xA;Another technique know as [rip-mapping][3] (mentioned in the Wikipedia article on Mipmapping), which is *not* commonly found in contemporary GPUs, uses prefiltering of textures. In contrast to mips, the texture is not scaled down uniformly but using various height-width-ratios (up to a ratio dependent on your chosen anisotropic filtering level). The variant - or maybe two variants if using trilinear filtering - of the texture is then chosen based on the angle of the surface to minimize distortion. Pixel values are fetched using default filtering techniques (bilinear or trilinear). Rip-maps are not used in any hardware that I know of due to their prohibitive size: while mipmaps use additional 33% storage, ripmaps use 300%. This can be verified by noting that texture usage requirements don't increase when using AF, rather, only bandwidth does.&#xD;&#xA;&#xD;&#xA;For futher reading, you might want to take a look at the specification for the [EXT_texture_filter_anisotropic][4] OpenGL extension. It details the formulas used to calculate samples and how to combine them when using anisotropic filtering.&#xD;&#xA;&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Mipmap&#xD;&#xA;  [4]: https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="2395" PostHistoryTypeId="5" PostId="386" RevisionGUID="abe74131-7efd-493f-9021-53cbb45ec62b" CreationDate="2015-09-09T21:13:03.580" UserId="511" Comment="added 63 characters in body" Text="Whether it's a tile based GPU or not doesn't really affect the texture cache architecture. The memory layout of texture will look like some flavor of [Morton order](https://en.wikipedia.org/wiki/Z-order_curve) or [Hilbert curve](https://en.wikipedia.org/wiki/Hilbert_curve) in all GPUs.&#xD;&#xA;&#xD;&#xA;As a result, it's more efficient to render triangles that are close to equilateral triangles because GPU memory system fetches cache lines of texels.&#xD;&#xA;&#xD;&#xA;So obviously on tile borders, it may happen that you have to fetch texels twice. This has a small cost as tile borders are only &quot;few&quot; pixels.&#xD;&#xA;&#xD;&#xA;Arguably desktop GPUs behave identically to tile based GPUs as experiments such as the following demonstrate:&#xD;&#xA;http://www.g-truc.net/post-0597.html&#xD;&#xA;&#xD;&#xA;The size of the tiles differ but both architecture actually process fragments into a hierarchy of tiles of different sizes.&#xD;&#xA;&#xD;&#xA;When coding for tile based GPUs my recommendation is to always have in mind:&#xD;&#xA;&#xD;&#xA;1. Don't switch framebuffer objects unless you *really* need to.&#xD;&#xA;2. When binding a new framebuffer object, if you don't need to save the content of the current framebuffer, discard it. If don't want to load content of the new framebuffer, then you should clear the framebuffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2396" PostHistoryTypeId="5" PostId="1464" RevisionGUID="e061bbfa-6ff4-4129-a9fd-6ae03513b0c7" CreationDate="2015-09-10T05:45:00.667" UserId="209" Comment="After Nathan's comment, tried to make it clearer that fixed-point refrs to screen space" Text="lhf's answer is good from the perspective of tessellation, but these can occur with simpler triangle mesh use cases.&#xD;&#xA;&#xD;&#xA;Take this simple example of three, *screen-space* triangles, ABC, ADE and DBE...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;Although point E was, mathematically, intended to be exactly on the line segment AB, the pipeline won't be using fully precise values, such as rational numbers (e.g. https://gmplib.org/). Instead, it will likely be using floats, and so some approximation/error will be introduced. The result is probably going to be something like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that *all* of the vertices may have inaccuracies. Although the example above shows a crack, the T-junction may instead result in overlap along the edge causing pixels to be drawn twice. This might not seem as bad, but it can cause problems with transparency or stencil operations.&#xD;&#xA;&#xD;&#xA;You *might* then think that with floating-point the error introduced will be insignificant, but in a renderer, the screen-space vertex (X,Y) values *are nearly always represented by fixed-point numbers* and so the displacement from the ideal location will usually be much greater. Further, as the rendering hardware &quot;interpolates&quot; the line segment pixel-by-pixel with its own internal precision, there is even more chance it will diverge from the rounded location of E.&#xD;&#xA;&#xD;&#xA;If the T-junction is &quot;removed&quot; by, say, also dividing triangle ABC into two, i.e. AEC and EBC, the problem will go away as the shifts introduced by the errors will all be consistent.&#xD;&#xA;&#xD;&#xA;Now, you might ask why do renderers (especially HW) use fixed-point maths for the vertex XY coordinates? Why don't they use floating-point in order to reduce the problem? Although some did (e.g. Sega's Dreamcast) it can lead to another problem where the triangle set-up maths becomes catastrophically inaccurate, particularly for long-thin triangles, and they change size in unpleasant ways.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sFxmG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QYZw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2397" PostHistoryTypeId="2" PostId="1469" RevisionGUID="c6227e7d-d9be-470c-9c3e-78fcf0e319b6" CreationDate="2015-09-10T05:55:21.797" UserId="38" Text="No, simply:&#xD;&#xA;&#xD;&#xA;* Physically based rendering does not necessitate raytracing. One can use other means.&#xD;&#xA;&#xD;&#xA;* Raytracing can be used to do other effects than physically based rendering. &#xD;&#xA;&#xD;&#xA;Raytracing is often easiest to implement and think out. Therefore its widely deployed for physically based rendering. But for same reason many nonrealistic renders use raytracing tricks to get what they need." ContentLicense="CC BY-SA 3.0" />
  <row Id="2398" PostHistoryTypeId="5" PostId="1469" RevisionGUID="88040fba-987c-415d-9db6-e1e569ce4e11" CreationDate="2015-09-10T06:14:22.217" UserId="38" Comment="added 78 characters in body" Text="No, simply:&#xD;&#xA;&#xD;&#xA;* Physically based rendering does not necessitate raytracing. One can use other means.\*&#xD;&#xA;&#xD;&#xA;* Raytracing can be used to do other effects than physically based rendering. &#xD;&#xA;&#xD;&#xA;Raytracing is often easiest to implement and think out. Therefore its widely deployed for physically based rendering. But for same reason many nonrealistic renders use raytracing tricks to get what they need.&#xD;&#xA;&#xD;&#xA;\* Personally ive been toying with unstructured FEM for rendering images" ContentLicense="CC BY-SA 3.0" />
  <row Id="2399" PostHistoryTypeId="34" PostId="324" RevisionGUID="c0d5453e-3523-44cd-96da-3abc48763bb2" CreationDate="2015-09-10T08:08:16.970" UserId="231" Comment="10" />
  <row Id="2400" PostHistoryTypeId="2" PostId="1470" RevisionGUID="6422085c-af96-4bc4-afc3-0710da5d06f4" CreationDate="2015-09-10T08:28:52.850" UserId="1613" Text="When I was reading theory behind physical based rendering I noticed that definition of BSDF and radiance has some problems. For example BSDF of purely specular surfaces is zero almost everywhere and infinite in one point or radiance of directional light is zero for almost all directions except for one where it is again infinite.&#xD;&#xA;&#xD;&#xA;This causes problems in rendering equation.&#xD;&#xA;&#xD;&#xA;[![rendering equation][1]][1]&#xD;&#xA;&#xD;&#xA;For purely specular surface this integral has to be zero, from strict mathematical point of view. This is because the BSDF is zero (solid angle)-almost everywhere. You can argue that BSDF is infinite in one point and you have to take this point into account. But how do you know what is the reflectance of the surface at that point? From the infinity you can really tell. Furthermore from mathematical standpoint of view you cannot integrate infinite valued function, even if you could than the only sensible answers would be zero or infinity.&#xD;&#xA;&#xD;&#xA;I know these are subtle problems and in practice can be solved with few `if`s but I would like to have theory without holes. I believe that if you embrace these problems in theory than it helps you with placing those `if`s in the right place.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;How to deal with this problem? &#xD;&#xA;&#xD;&#xA;Not sure entirely but as I can remember Erich Veach in his thesis address this problem only slightly and tries to get away with it by saying that BSDF and radiance are [distributions][2]. This is problematic, you cannot multiply two distributions, which is needed in rendering equation. For example when a light from  directional light hits specular surface than you need to multiply two Dirac delta functions together.&#xD;&#xA;&#xD;&#xA;The question is: Is there any work which reformulates rendering equation, BSDF and radiance in such a way that it does not suffer from mentioned problems?&#xD;&#xA;&#xD;&#xA;What is the state of the art theory behind raytracing? Is is still Erich Veach's thesis?&#xD;&#xA;&#xD;&#xA;(I'm only aware of [work][3] of Christian Lessig, but his work is still beyond my mathematical reach.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FODai.gif&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Distribution_(mathematics)&#xD;&#xA;  [3]: http://cybertron.cg.tu-berlin.de/lessig/projects/dissertation/index.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2401" PostHistoryTypeId="1" PostId="1470" RevisionGUID="6422085c-af96-4bc4-afc3-0710da5d06f4" CreationDate="2015-09-10T08:28:52.850" UserId="1613" Text="Problem with definition of BSDF and radiance" ContentLicense="CC BY-SA 3.0" />
  <row Id="2402" PostHistoryTypeId="3" PostId="1470" RevisionGUID="6422085c-af96-4bc4-afc3-0710da5d06f4" CreationDate="2015-09-10T08:28:52.850" UserId="1613" Text="|raytracing|radiosity|theory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2403" PostHistoryTypeId="5" PostId="1460" RevisionGUID="4333ff7f-3112-40bf-9fc6-e896ffb4b395" CreationDate="2015-09-10T09:25:22.543" UserId="385" Comment="Incorporated information from the comments" Text="At the base, **rendering APIs** like OpenGL or Direct3D provide a unified interface to communicate with graphics adapters at a low level. Differences in hardware are hidden behind the abstraction which simplifies development a lot.&#xD;&#xA;&#xD;&#xA;The low-level APIs provide basic functionality, which gives you total control but leaves you without a lot of desired features. **3D Rendering Frameworks** like OGRE or Irrlicht introduce the more understandable concept of 3D objects that can be moved in space (without having to worry about transformation matrices most of the time), introduce light sources and algorithms for shadow casting (e.g. shadow mapping), loading of common mesh formats, and the list goes on. I call this a *framework*, because you still need to develop the application yourself using actual code, while an *engine* provides you with an application to develop your software in. This is just my personal distinction and both terms are used differently in a variety of contexts.&#xD;&#xA;&#xD;&#xA;In a **3D Authoring / Rendering Software** like Blender or Autodesk Maya (offline) or 3DExcite DeltaGen (real-time) you can load, display or create meshes using the built-in functionality. These applications target the creation of 3D data, images or movies, and usually you can't create interactive applications easily with it. Be aware that some 3D Authoring have modules specifically targeting this, e.g. Blender and the integrated Blender Game Engine.&#xD;&#xA;&#xD;&#xA;A **3D Game Engine** finally provides you with all the tools to make it easy for you to develop a game. You will usually be provided with a level editor, a material editor and maybe a visible scripting language (like Unreal's Blueprint or earlier Kismet) to implement dynamic behavior and interactivity. You don't have to worry about rendering algorithms, because they are already implemented for you. Your engine of choice may for example feature [SSAO][1] and [cascaded shadow maps][2] for dynamic objects and a solution to bake global illumination for static geometry. Also, a game engine includes way more than only rendering, e.g. artificial intelligence, sound, loading of assets, exporting your content into a ready-to-install package etc.&#xD;&#xA;&#xD;&#xA;As you can see, each software package generally puts another layer of abstraction on, ideally making your life simpler. Each has its own purpose and allows you to do different things. Note that said terms are very broad and people have different opinions and sometimes even debates about where one category ends and the next one begins. My advice is to not lose sleep over it.&#xD;&#xA;&#xD;&#xA;  [1]: http://people.mpi-inf.mpg.de/~ritschel/Papers/SSDO.pdf&#xD;&#xA;  [2]: http://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2404" PostHistoryTypeId="5" PostId="1470" RevisionGUID="624ee340-c058-4948-91f3-c7785977053f" CreationDate="2015-09-10T10:12:17.887" UserId="1613" Comment="added 464 characters in body" Text="When I was reading theory behind physical based rendering I noticed that definition of BSDF and radiance has some problems. For example BSDF of purely specular surfaces is zero almost everywhere and infinite in one point or radiance of directional light is zero for almost all directions except for one where it is again infinite.&#xD;&#xA;&#xD;&#xA;This causes problems in rendering equation.&#xD;&#xA;&#xD;&#xA;[![rendering equation][1]][1]&#xD;&#xA;&#xD;&#xA;For purely specular surface this integral has to be zero, from strict mathematical point of view. This is because the BSDF is zero (solid angle)-almost everywhere. You can argue that BSDF is infinite in one point and you have to take this point into account. But how do you know what is the reflectance of the surface at that point? From the infinity you can really tell. Furthermore from mathematical standpoint of view you cannot integrate infinite valued function, even if you could than the only sensible answers would be zero or infinity.&#xD;&#xA;&#xD;&#xA;I know these are subtle problems and in practice can be solved with few `if`s but I would like to have theory without holes. I believe that if you embrace these problems in theory than it helps you with placing those `if`s in the right place.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;How to deal with this problem? &#xD;&#xA;&#xD;&#xA;Not sure entirely but as I can remember Erich Veach in his thesis address this problem only slightly and tries to get away with it by saying that BSDF and radiance are [distributions][2]. This is problematic, you cannot multiply two distributions, which is needed in rendering equation. For example when a light from  directional light hits specular surface than you need to multiply two Dirac delta functions together.&#xD;&#xA;&#xD;&#xA;The question is: Is there any work which reformulates rendering equation, BSDF and radiance in such a way that it does not suffer from mentioned problems?&#xD;&#xA;&#xD;&#xA;What is the state of the art theory behind raytracing? Is is still Erich Veach's thesis?&#xD;&#xA;&#xD;&#xA;(I'm only aware of [work][3] of Christian Lessig, but his work is still beyond my mathematical reach.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I already have [proposal][4] how to deal with this problem. I define BSDF and radiance as measure. The basic idea works fine, but the whole theory of light transport needs to be redone to find out if it really works.&#xD;&#xA;&#xD;&#xA;The main purpose of this question is to find out if someone else already did it, so I can read it and then focus my energy somewhere else.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FODai.gif&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Distribution_(mathematics)&#xD;&#xA;  [3]: http://cybertron.cg.tu-berlin.de/lessig/projects/dissertation/index.html&#xD;&#xA;  [4]: http://tomsmathjourneys.blogspot.cz/2015/09/better-code-with-radiance-and-bsdf-as.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2405" PostHistoryTypeId="5" PostId="1470" RevisionGUID="d298b70f-d37a-4697-bf47-29ddc0236132" CreationDate="2015-09-10T10:46:33.507" UserId="385" Comment="Added link to Erich Veach's thesis" Text="When I was reading theory behind physical based rendering I noticed that definition of BSDF and radiance has some problems. For example BSDF of purely specular surfaces is zero almost everywhere and infinite in one point or radiance of directional light is zero for almost all directions except for one where it is again infinite.&#xD;&#xA;&#xD;&#xA;This causes problems in rendering equation.&#xD;&#xA;&#xD;&#xA;[![rendering equation][1]][1]&#xD;&#xA;&#xD;&#xA;For purely specular surface this integral has to be zero, from strict mathematical point of view. This is because the BSDF is zero (solid angle)-almost everywhere. You can argue that BSDF is infinite in one point and you have to take this point into account. But how do you know what is the reflectance of the surface at that point? From the infinity you can really tell. Furthermore from mathematical standpoint of view you cannot integrate infinite valued function, even if you could than the only sensible answers would be zero or infinity.&#xD;&#xA;&#xD;&#xA;I know these are subtle problems and in practice can be solved with few `if`s but I would like to have theory without holes. I believe that if you embrace these problems in theory than it helps you with placing those `if`s in the right place.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;How to deal with this problem? &#xD;&#xA;&#xD;&#xA;Not sure entirely but as I can remember Erich Veach [in his thesis][2] address this problem only slightly and tries to get away with it by saying that BSDF and radiance are [distributions][3]. This is problematic, you cannot multiply two distributions, which is needed in rendering equation. For example when a light from  directional light hits specular surface than you need to multiply two Dirac delta functions together.&#xD;&#xA;&#xD;&#xA;The question is: Is there any work which reformulates rendering equation, BSDF and radiance in such a way that it does not suffer from mentioned problems?&#xD;&#xA;&#xD;&#xA;What is the state of the art theory behind raytracing? Is is still Erich Veach's thesis?&#xD;&#xA;&#xD;&#xA;(I'm only aware of [work][4] of Christian Lessig, but his work is still beyond my mathematical reach.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I already have [proposal][5] how to deal with this problem. I define BSDF and radiance as measure. The basic idea works fine, but the whole theory of light transport needs to be redone to find out if it really works.&#xD;&#xA;&#xD;&#xA;The main purpose of this question is to find out if someone else already did it, so I can read it and then focus my energy somewhere else.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FODai.gif&#xD;&#xA;  [2]: https://graphics.stanford.edu/papers/veach_thesis/&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Distribution_(mathematics)&#xD;&#xA;  [4]: http://cybertron.cg.tu-berlin.de/lessig/projects/dissertation/index.html&#xD;&#xA;  [5]: http://tomsmathjourneys.blogspot.cz/2015/09/better-code-with-radiance-and-bsdf-as.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2406" PostHistoryTypeId="24" PostId="1470" RevisionGUID="d298b70f-d37a-4697-bf47-29ddc0236132" CreationDate="2015-09-10T10:46:33.507" Comment="Proposed by 385 approved by 1613 edit id of 51" ContentLicense="CC BY-SA 3.0" />
  <row Id="2407" PostHistoryTypeId="2" PostId="1471" RevisionGUID="017d0c40-bd2b-4b73-bd40-7198843c73a3" CreationDate="2015-09-10T11:11:54.013" UserId="1613" Text="There is one important distinction to make. &#xD;&#xA;&#xD;&#xA;Markov Chain Monte Carlo (such as Metropolis Light Transport) methods fully acknowledge the fact that they produce lots of highly correlated, it is actually the backbone of the algorithm. &#xD;&#xA;&#xD;&#xA;On other hand there are algorithms as Bidirectional Path Tracing, Many Light Method, Photon Mapping where the crucial role plays Multiple Importance Sampling and its balance heuristics. Optimality of balance heuristic is proven only for samples that are independent. Many modern algorithms have correlated samples and for some of them this causes troubles and for some it doesn't.&#xD;&#xA;&#xD;&#xA;The problem with correlated samples was acknowledged in the paper [Probabilistic Connections for Bidirectional Path Tracing][1]. Where they have altered balance heuristics to take into account the correlation. Have a look at figure 17 in the paper to see the result.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I would like to point out that correlation is &quot;always&quot; bad. If you can afford to make brand new sample than do it. But most of the time you can't afford it so you hope that the error due to the correlation is small.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://scholar.google.com/citations?view_op=view_citation&amp;hl=en&amp;user=Glq3dWkAAAAJ&amp;citation_for_view=Glq3dWkAAAAJ:WF5omc3nYNoC" ContentLicense="CC BY-SA 3.0" />
  <row Id="2408" PostHistoryTypeId="5" PostId="1471" RevisionGUID="dace2fa3-f8a9-40e0-b1f7-49b06f8755bc" CreationDate="2015-09-10T11:35:09.577" UserId="1613" Comment="added 487 characters in body" Text="There is one important distinction to make. &#xD;&#xA;&#xD;&#xA;Markov Chain Monte Carlo (such as Metropolis Light Transport) methods fully acknowledge the fact that they produce lots of highly correlated, it is actually the backbone of the algorithm. &#xD;&#xA;&#xD;&#xA;On other hand there are algorithms as Bidirectional Path Tracing, Many Light Method, Photon Mapping where the crucial role plays Multiple Importance Sampling and its balance heuristics. Optimality of balance heuristic is proven only for samples that are independent. Many modern algorithms have correlated samples and for some of them this causes troubles and for some it doesn't.&#xD;&#xA;&#xD;&#xA;The problem with correlated samples was acknowledged in the paper [Probabilistic Connections for Bidirectional Path Tracing][1]. Where they have altered balance heuristics to take into account the correlation. Have a look at figure 17 in the paper to see the result.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I would like to point out that correlation is &quot;always&quot; bad. If you can afford to make brand new sample than do it. But most of the time you can't afford it so you hope that the error due to the correlation is small.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;And the deal with stratified sampling is that it is basically not a Monte Carlo method. Stratified sampling comes from standard quadrature rules for numerical integration which works great for integrating smooth function in low dimensions. This is why it is used for handling direct illumination which is low dimensional problem, but its smoothness is disputable.&#xD;&#xA;&#xD;&#xA;So stratified sampling is yet different kind of correlation than for example correlation in Many Light methods.&#xD;&#xA;&#xD;&#xA;  [1]: https://scholar.google.com/citations?view_op=view_citation&amp;hl=en&amp;user=Glq3dWkAAAAJ&amp;citation_for_view=Glq3dWkAAAAJ:WF5omc3nYNoC" ContentLicense="CC BY-SA 3.0" />
  <row Id="2409" PostHistoryTypeId="5" PostId="1471" RevisionGUID="fddd2f5f-dbc2-4a66-a239-c7ba1f2c4611" CreationDate="2015-09-10T12:19:49.680" UserId="1613" Comment="added 828 characters in body" Text="There is one important distinction to make. &#xD;&#xA;&#xD;&#xA;Markov Chain Monte Carlo (such as Metropolis Light Transport) methods fully acknowledge the fact that they produce lots of highly correlated, it is actually the backbone of the algorithm. &#xD;&#xA;&#xD;&#xA;On other hand there are algorithms as Bidirectional Path Tracing, Many Light Method, Photon Mapping where the crucial role plays Multiple Importance Sampling and its balance heuristics. Optimality of balance heuristic is proven only for samples that are independent. Many modern algorithms have correlated samples and for some of them this causes troubles and for some it doesn't.&#xD;&#xA;&#xD;&#xA;The problem with correlated samples was acknowledged in the paper [Probabilistic Connections for Bidirectional Path Tracing][1]. Where they have altered balance heuristics to take into account the correlation. Have a look at figure 17 in the paper to see the result.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I would like to point out that correlation is &quot;always&quot; bad. If you can afford to make brand new sample than do it. But most of the time you can't afford it so you hope that the error due to the correlation is small.&#xD;&#xA;&#xD;&#xA;**Edit to explain the &quot;always&quot;**: I mean this in the context of MC integration&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Where you measure the error with variance of the estimator&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If the samples are independent that the covariance term is zero. Correlated samples make always this term nonzero thus increasing variance of the final estimator.&#xD;&#xA;&#xD;&#xA;This is at first sight somewhat contradictory what we encounter with stratified sampling because stratification lowers the error. But you can't prove that stratified sampling converges to the desired result just from the probabilistic point of view. You need some smoothness of the function `f` in order to prove that stratified sampling works.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;And the deal with stratified sampling is that it is basically not a Monte Carlo method. Stratified sampling comes from standard quadrature rules for numerical integration which works great for integrating smooth function in low dimensions. This is why it is used for handling direct illumination which is low dimensional problem, but its smoothness is disputable.&#xD;&#xA;&#xD;&#xA;So stratified sampling is yet different kind of correlation than for example correlation in Many Light methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://scholar.google.com/citations?view_op=view_citation&amp;hl=en&amp;user=Glq3dWkAAAAJ&amp;citation_for_view=Glq3dWkAAAAJ:WF5omc3nYNoC&#xD;&#xA;  [2]: https://i.stack.imgur.com/st1XC.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/wEs1y.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="2410" PostHistoryTypeId="5" PostId="1471" RevisionGUID="f89dc0b1-352f-4280-ad0a-85396b7e19d4" CreationDate="2015-09-10T12:27:27.860" UserId="1613" Comment="added 828 characters in body" Text="There is one important distinction to make. &#xD;&#xA;&#xD;&#xA;Markov Chain Monte Carlo (such as Metropolis Light Transport) methods fully acknowledge the fact that they produce lots of highly correlated, it is actually the backbone of the algorithm. &#xD;&#xA;&#xD;&#xA;On other hand there are algorithms as Bidirectional Path Tracing, Many Light Method, Photon Mapping where the crucial role plays Multiple Importance Sampling and its balance heuristics. Optimality of balance heuristic is proven only for samples that are independent. Many modern algorithms have correlated samples and for some of them this causes troubles and for some it doesn't.&#xD;&#xA;&#xD;&#xA;The problem with correlated samples was acknowledged in the paper [Probabilistic Connections for Bidirectional Path Tracing][1]. Where they have altered balance heuristics to take into account the correlation. Have a look at figure 17 in the paper to see the result.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I would like to point out that correlation is &quot;always&quot; bad. If you can afford to make brand new sample than do it. But most of the time you can't afford it so you hope that the error due to the correlation is small.&#xD;&#xA;&#xD;&#xA;**Edit to explain the &quot;always&quot;**: I mean this in the context of MC integration&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Where you measure the error with variance of the estimator&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If the samples are independent that the covariance term is zero. Correlated samples make always this term nonzero thus increasing variance of the final estimator.&#xD;&#xA;&#xD;&#xA;This is at first sight somewhat contradictory what we encounter with stratified sampling because stratification lowers the error. But you can't prove that stratified sampling converges to the desired result just from the probabilistic point of view, because in the core of stratified sampling there is no probability involved.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;And the deal with stratified sampling is that it is basically not a Monte Carlo method. Stratified sampling comes from standard quadrature rules for numerical integration which works great for integrating smooth function in low dimensions. This is why it is used for handling direct illumination which is low dimensional problem, but its smoothness is disputable.&#xD;&#xA;&#xD;&#xA;So stratified sampling is yet different kind of correlation than for example correlation in Many Light methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://scholar.google.com/citations?view_op=view_citation&amp;hl=en&amp;user=Glq3dWkAAAAJ&amp;citation_for_view=Glq3dWkAAAAJ:WF5omc3nYNoC&#xD;&#xA;  [2]: https://i.stack.imgur.com/st1XC.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/wEs1y.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="2411" PostHistoryTypeId="2" PostId="1472" RevisionGUID="1707eb9b-5923-46f9-bf9d-b3426f268526" CreationDate="2015-09-10T13:20:30.943" UserId="205" Text="I have an issue with rendering my textures. When I look at it from above everything looks fine:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But if I only change angle of watching it it looks terrible:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am using very simple pixel shader (hlsl):&#xD;&#xA;&#xD;&#xA;    float4 main(VsOutput vertex) : COLOR&#xD;&#xA;    {&#xD;&#xA;            float4 texColor = tex2D(textureSampler, texCoord);&#xD;&#xA;    &#xD;&#xA;            return texColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I don' t use that pixel shader and load texture via BasicEffect like:&#xD;&#xA;&#xD;&#xA;    BasicEffect.texture = myTexture&#xD;&#xA;&#xD;&#xA;Everything looks fine. Why my pixel shader affects texture so bad?&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;I expect that it might be somehow connected with mipmapping, but I am not sure - my texture is pretty small so I guess it shouldn' t have such a big effect. Anyway I need some advices :).&#xD;&#xA;  [1]: https://i.stack.imgur.com/zjAeu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4b2AU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2412" PostHistoryTypeId="1" PostId="1472" RevisionGUID="1707eb9b-5923-46f9-bf9d-b3426f268526" CreationDate="2015-09-10T13:20:30.943" UserId="205" Text="Texture glitch when using simple pixel shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="2413" PostHistoryTypeId="3" PostId="1472" RevisionGUID="1707eb9b-5923-46f9-bf9d-b3426f268526" CreationDate="2015-09-10T13:20:30.943" UserId="205" Text="|texture|rendering|pixel-shader|hlsl|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2414" PostHistoryTypeId="5" PostId="1472" RevisionGUID="18cea7e2-2dee-4512-8842-db214996f467" CreationDate="2015-09-10T13:26:03.863" UserId="205" Comment="Added extra info" Text="I have an issue with rendering my textures in Silverlight. When I look at it from above everything looks fine:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But if I only change angle of watching it it looks terrible:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am using very simple pixel shader (hlsl):&#xD;&#xA;&#xD;&#xA;    float4 main(VsOutput vertex) : COLOR&#xD;&#xA;    {&#xD;&#xA;            float4 texColor = tex2D(textureSampler, texCoord);&#xD;&#xA;    &#xD;&#xA;            return texColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I don' t use that pixel shader and load texture via BasicEffect like:&#xD;&#xA;&#xD;&#xA;    BasicEffect.texture = myTexture&#xD;&#xA;&#xD;&#xA;Everything looks fine. Why my pixel shader affects texture so bad?&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;I expect that it might be somehow connected with mipmapping, but I am not sure - my texture is pretty small so I guess it shouldn' t have such a big effect. Anyway I need some advices :).&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;  [1]: https://i.stack.imgur.com/zjAeu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4b2AU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2415" PostHistoryTypeId="2" PostId="1473" RevisionGUID="7730d874-e06f-4410-aef7-4fab2b2e5012" CreationDate="2015-09-10T16:45:30.430" UserId="528" Text="DirectX 12 exposes command queues for either graphics (called &quot;Direct&quot;), compute or copy tasks. In terms of provided functionality, each one is a super-set of the following one. The [specification][1] states that command queues can be executed concurrently by the device.  However, the API does not limit the number of command queues in any way (at least I am not aware any limitation).&#xD;&#xA;&#xD;&#xA;Apparently, different vendors handle this very different:&#xD;&#xA;&#xD;&#xA; - Intel states in a [recent presentation][2] (slide 23) that currently their GPUs are not able to handle Graphics &amp; Compute in parallel and that the copy engine has a weak throughput. They advise against the use of multiple graphics/compute queues.&#xD;&#xA; - AMD started [long time ago][3] to advertise the use of queues / &quot;asynchronous shaders&quot; starting with Mantle and the current gen consoles. There are also some developers ([example][4]) that confirm significant performance gains by executing compute and graphics tasks in parallel.&#xD;&#xA; - There has been recently [some fuss][5] about Nvidia not supporting asynchronous shader in the hardware: Using separate Graphics and Compute queue at once seems to make things slower which indicates driver emulation. Parallel copy operations, on the other hand, have been supported by CUDA for a very long time, which makes it clear that the DMA engine can work independently.&#xD;&#xA;&#xD;&#xA;**Is there any way to decide at runtime if it is meaningful to commit CommandLists to multiple CommandQueues instead of a single one?** (given that former case does not involve much engineering-overhead)&#xD;&#xA;&#xD;&#xA;While I can easily see how it is useful to perform memory operations parallel to compute/graphics operations, it strikes me as unnecessarily complicated to run multiple compute and graphics processes in parallel (unless there is no major perf. benefit).&#xD;&#xA;It is also not clear to me, how this can lead to significantly better performance anyways; except for pathological cases where many small sequential tasks are not able to generate enough GPU load.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn899124%28v=vs.85%29.aspx&#xD;&#xA;  [2]: https://software.intel.com/sites/default/files/managed/4a/38/Efficient-Rendering-with-DirectX-12-on-Intel-Graphics.pdf&#xD;&#xA;  [3]: http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Asynchronous-Shaders-White-Paper-FINAL.pdf&#xD;&#xA;  [4]: http://fumufumu.q-games.com/archives/TheTechnologyOfTomorrowsChildrenFinal.pdf&#xD;&#xA;  [5]: http://www.guru3d.com/news-story/nvidia-wanted-oxide-dev-dx12-benchmark-to-disable-certain-settings.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2416" PostHistoryTypeId="1" PostId="1473" RevisionGUID="7730d874-e06f-4410-aef7-4fab2b2e5012" CreationDate="2015-09-10T16:45:30.430" UserId="528" Text="How many Direct/Compute/Copy Queues are meaningful?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2417" PostHistoryTypeId="3" PostId="1473" RevisionGUID="7730d874-e06f-4410-aef7-4fab2b2e5012" CreationDate="2015-09-10T16:45:30.430" UserId="528" Text="|directx12|api|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2423" PostHistoryTypeId="2" PostId="1476" RevisionGUID="2e38a867-fbea-43c7-abbb-9b2f5f31b00f" CreationDate="2015-09-11T06:22:54.503" UserId="205" Text="So I followed Alan Wolfe suggestion (in comment to my question) And turned out he was right. I was using `SamplerState.LinearWrap` and that was the issue. When I changed this to `AnisotropicWrap` it looked much better. Below are some examples of different sampling types and how they affect texture:&#xD;&#xA;&#xD;&#xA;    graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    graphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p7YQk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pldvb.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xNkBM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2425" PostHistoryTypeId="2" PostId="1477" RevisionGUID="0ec10a23-4e46-4406-bb02-40d73e1fc472" CreationDate="2015-09-11T08:22:01.553" UserId="209" Text="According to Wikipedia (insert standard disclaimer RE accuracy):&#xD;&#xA;&gt;JPEG does not define which color encoding is to be used for images. JFIF&#xD;&#xA;&gt;defines the color model to be used: either Y for greyscale, or YCbCr as&#xD;&#xA;&gt;defined by CCIR 601.&#xD;&#xA;&#xD;&#xA;YCbCr is a non-linear format. As I mentioned earlier, &quot;Video Demystified&quot; states:&#xD;&#xA;&gt;&quot;YCbCr is the color space originally defined by BT.601, and now used for&#xD;&#xA;&gt;all digital component video formats. .... The technically correct notation&#xD;&#xA;&gt;is Y'Cb'Cr' since all three components are derived from R'G'B'.&quot;&#xD;&#xA;&#xD;&#xA;and Charles' Poynton's [Colour FAQ](http://poynton.com/notes/colour_and_gamma/ColorFAQ.html) states&#xD;&#xA;&#xD;&#xA;&gt;Video systems approximate the lightness response of vision using R'G'B'&#xD;&#xA;&gt;signals that are each subject to a 0.45 power function.&#xD;&#xA;&#xD;&#xA;With compression we are after the best visual representation per bit and, as the eye is non-linear in approximately this way, it makes sense to use non-linear representations." ContentLicense="CC BY-SA 3.0" />
  <row Id="2426" PostHistoryTypeId="5" PostId="1476" RevisionGUID="69ff261c-cddd-4f5b-9629-a53397974c73" CreationDate="2015-09-11T08:28:29.850" UserId="385" Comment="2nd example is not point sampling again, but linear sampling" Text="So I followed Alan Wolfe suggestion (in comment to my question) And turned out he was right. I was using `SamplerState.LinearWrap` and that was the issue. When I changed this to `AnisotropicWrap` it looked much better. Below are some examples of different sampling types and how they affect texture:&#xD;&#xA;&#xD;&#xA;    graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    graphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p7YQk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pldvb.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xNkBM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2427" PostHistoryTypeId="24" PostId="1476" RevisionGUID="69ff261c-cddd-4f5b-9629-a53397974c73" CreationDate="2015-09-11T08:28:29.850" Comment="Proposed by 385 approved by 205, 231 edit id of 52" ContentLicense="CC BY-SA 3.0" />
  <row Id="2430" PostHistoryTypeId="10" PostId="1455" RevisionGUID="9d899fe0-75e7-4940-8ed1-b966cc7660d2" CreationDate="2015-09-11T12:10:57.173" UserId="53" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:53,&quot;DisplayName&quot;:&quot;Robert Cartaino&quot;}]}" />
  <row Id="2432" PostHistoryTypeId="2" PostId="1478" RevisionGUID="b4f8679c-d8e2-430a-ae5f-c2466d1428f1" CreationDate="2015-09-11T13:43:28.783" UserId="1622" Text="There's a thing called [ENB][1] for PC which works by modifying render functions calls of the games and applying additional effects. I wonder if there is a similar way for console games.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://enbdev.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2433" PostHistoryTypeId="1" PostId="1478" RevisionGUID="b4f8679c-d8e2-430a-ae5f-c2466d1428f1" CreationDate="2015-09-11T13:43:28.783" UserId="1622" Text="Is it possible to modify a console game graphics (Xbox 360)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2434" PostHistoryTypeId="3" PostId="1478" RevisionGUID="b4f8679c-d8e2-430a-ae5f-c2466d1428f1" CreationDate="2015-09-11T13:43:28.783" UserId="1622" Text="|rendering|3d|direct3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2435" PostHistoryTypeId="2" PostId="1479" RevisionGUID="296065a4-e185-43d3-99d1-054d884120cf" CreationDate="2015-09-11T18:12:10.897" UserId="14" Text="Space-filling curves are important in many graphics applications because they help expose spatial locality. We often hear about different algorithms using Z-curves, Morton codes, Hilbert curves, etc. What are the differences between some of these different curves and how do they apply to various applications?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2436" PostHistoryTypeId="1" PostId="1479" RevisionGUID="296065a4-e185-43d3-99d1-054d884120cf" CreationDate="2015-09-11T18:12:10.897" UserId="14" Text="What is the difference between various space-filling curves?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2437" PostHistoryTypeId="3" PostId="1479" RevisionGUID="296065a4-e185-43d3-99d1-054d884120cf" CreationDate="2015-09-11T18:12:10.897" UserId="14" Text="|space-filling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2439" PostHistoryTypeId="2" PostId="1480" RevisionGUID="9d8e9416-f782-41e9-9a0d-c22e379118d1" CreationDate="2015-09-11T21:24:34.860" UserId="141" Text="The difference is how well a mapping preserves locality and how easy it is to encode/decode the keys. The paper &quot;Linear Clustering of Objects with Multiple Attributes&quot; by H V Jagadish says: &quot;Through algebraic analysis, and through computer simulation, we showed that under most circumstances, the Hilbert mapping performed as well as or better than the best of alternative mappings suggested in the literature&quot;. On the other hand, z-order is a bit simpler to use, for example compare the various methods listed in [Bit Twiddling Hacks](https://graphics.stanford.edu/~seander/bithacks.html#InterleaveTableObvious) for z-order and [Wikipedia](https://en.wikipedia.org/wiki/Hilbert_curve#Applications_and_mapping_algorithms) for Hilbert-order.&#xD;&#xA;&#xD;&#xA;As for the applications, I think the main advantage in using space filling curves is that they map points from higher dimensional space to space of lower dimension. For example, they make it possible to window query for points using traditional B-tree database index. Again, on the other hand again, the disadvantage is that one needs to know the bounds of the input in advance as it is difficult to &quot;resize&quot; the mapping later.&#xD;&#xA;&#xD;&#xA;PS: &quot;Z-order&quot; is the same as &quot;Morton order&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="2440" PostHistoryTypeId="5" PostId="1480" RevisionGUID="cfadca17-d7f6-4356-9cc1-7739dfc2e422" CreationDate="2015-09-11T21:36:23.550" UserId="141" Comment="added 167 characters in body" Text="The difference is how well a mapping preserves locality and how easy it is to encode/decode the keys. The paper &quot;Linear Clustering of Objects with Multiple Attributes&quot; by H V Jagadish says: &quot;Through algebraic analysis, and through computer simulation, we showed that under most circumstances, the Hilbert mapping performed as well as or better than the best of alternative mappings suggested in the literature&quot;. On the other hand, z-order is a bit simpler to use, for example compare the various methods listed in [Bit Twiddling Hacks](https://graphics.stanford.edu/~seander/bithacks.html#InterleaveTableObvious) for z-order and [Wikipedia](https://en.wikipedia.org/wiki/Hilbert_curve#Applications_and_mapping_algorithms) for Hilbert-order.&#xD;&#xA;&#xD;&#xA;As for the applications, I think the main advantage in using space filling curves is that they map points from higher dimensional space to space of lower dimension. For example, they make it possible to window query for points using traditional B-tree database index. Again, on the other hand, the disadvantage is that one needs to know the bounds of the input in advance as it is difficult to &quot;resize&quot; the mapping later.&#xD;&#xA;&#xD;&#xA;PS: &quot;Z-curve&quot; is the same as &quot;Morton code&quot;.&#xD;&#xA;&#xD;&#xA;PPS: Additional mappings include [Peano curve](https://en.wikipedia.org/wiki/Peano_curve) and for applications see also [Geohash](https://en.wikipedia.org/wiki/Geohash)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2441" PostHistoryTypeId="2" PostId="1481" RevisionGUID="ae0cc7fa-4ad4-49dd-b4ac-e757135d0de1" CreationDate="2015-09-12T05:55:26.723" UserId="105" Text="Those space filling curves allow to keep locality in multiple dimensions when you &quot;walk&quot; linearly along the curve.&#xD;&#xA;&#xD;&#xA;From what I have seen, Z-Order (also known as Morton code) is the most employed because of its computational cost which is constant (and cheap) to access any point of the curve directly. (And easy to implement in hardware with 0 cycle penalty, as it corresponds to &quot;just switching&quot; address wires).&#xD;&#xA;&#xD;&#xA;A concrete example of Z-Order curve is texture swizzling : which is basically increasing the cache-hit rate for texture read on GPUs.&#xD;&#xA;(See images in the article about Z-Curve https://en.wikipedia.org/wiki/Z-order_curve)&#xD;&#xA;&#xD;&#xA;If the texture is simply stored linearly, you get the maximum cache hit if you render just the texture as 2D image, but if you rotated it by 90 degree on screen, you get into the worst case scenario (cache miss for every texture read).&#xD;&#xA;&#xD;&#xA;As a result, it is better to trade off a little and lower your best case scenario and have better cache hit for most of the patterns." ContentLicense="CC BY-SA 3.0" />
  <row Id="2442" PostHistoryTypeId="5" PostId="1481" RevisionGUID="ad2107bd-ec9e-4082-a358-60571f28f39d" CreationDate="2015-09-12T06:03:22.127" UserId="105" Comment="added 342 characters in body" Text="Those space filling curves allow to keep locality in multiple dimensions when you &quot;walk&quot; linearly along the curve.&#xD;&#xA;&#xD;&#xA;From what I have seen, Z-Order (also known as Morton code) is the most employed because of its computational cost which is constant (and cheap) to access any point of the curve directly. (And easy to implement in hardware with 0 cycle penalty, as it corresponds to &quot;just switching&quot; address wires).&#xD;&#xA;&#xD;&#xA;A concrete example of Z-Order curve is texture swizzling : which is basically increasing the cache-hit rate for texture read on GPUs.&#xD;&#xA;(See images in the article about Z-Curve https://en.wikipedia.org/wiki/Z-order_curve)&#xD;&#xA;&#xD;&#xA;If the texture is simply stored linearly, you get the maximum cache hit if you render just the texture as 2D image, but if you rotated it by 90 degree on screen, you get into the worst case scenario (cache miss for every texture read).&#xD;&#xA;&#xD;&#xA;As a result, it is better to trade off a little and lower your best case scenario and have better cache hit for most of the patterns.&#xD;&#xA;&#xD;&#xA;As a personal note, from what I have seen, other curves may require recursive step for their computation and result in bigger cost than Z-Curve with a minimal gain in term of locality coherence. So, I have not heard about those curve used with a practical purpose, except as a research subject in mathematic or creative/funny rendering.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2446" PostHistoryTypeId="2" PostId="1482" RevisionGUID="e64c0834-4176-491f-b971-f87ace932434" CreationDate="2015-09-13T06:13:54.857" UserId="38" Text="Gobal illumination, radiosity, etc is not a mutually exclusive set with using a fill light to adjust the feeling. Sometimes the artist can do wonders with a few well placed lights.&#xD;&#xA;&#xD;&#xA;So yes they are used, each game and situation is different. Perhaps they are just going for a unrealistic mood or the artist wants to tweak the result a bit." ContentLicense="CC BY-SA 3.0" />
  <row Id="2447" PostHistoryTypeId="2" PostId="1483" RevisionGUID="96248e8a-6453-437b-a899-daa06c2144b7" CreationDate="2015-09-13T07:36:40.457" UserId="38" Text="It turns out that the chromaticity chart is harder to read than I anticipated. The CMYK slice is actually triangular of sorts its just that the chromaticity chart is not really linear. The cmy space *is triangular of sorts*.&#xD;&#xA;&#xD;&#xA;The chromaticity chart is made with the assumption that light is a spectra. The curved arc is the pure spectral color of the rainbow. Everything in between is interpolated edge values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Visible specturm on the edge, interpolations on surface. &#xD;&#xA;&#xD;&#xA;Now magentas are a bit peculiar. They only exist in our brains interpretation, thus they can not be measured. Magentas are sort of virtual colors that make the color circle full. This means that when you move from absence of blue towards absence of green your line kinks since the graph has no well defined direction for magenta's. This makes a 4th corner where none should be located.&#xD;&#xA;&#xD;&#xA;Magentas are thus a bit of virtual colors that only exist in our brain. Not in physics, they are 2 spectra interleaved. There are off course many such metamers.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/COa4K.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2448" PostHistoryTypeId="5" PostId="1483" RevisionGUID="699dfb92-ea7f-437e-867d-fa27034447e6" CreationDate="2015-09-13T11:52:18.847" UserId="38" Comment="deleted 40 characters in body" Text="It turns out that the chromaticity chart is harder to read than I anticipated. The CMYK slice is actually triangular of sorts its just that the chromaticity chart is not really linear.&#xD;&#xA;&#xD;&#xA;The chromaticity chart is made with the assumption that light is a spectra. The curved arc is the pure spectral color of the rainbow. Everything in between is interpolated edge values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Visible specturm on the edge, interpolations on surface. &#xD;&#xA;&#xD;&#xA;Now magentas are a bit peculiar. They only exist in our brains interpretation, thus they can not be measured. Magentas are sort of virtual colors that make the color circle full. This means that when you move from absence of blue towards absence of green your line kinks since the graph has no well defined direction for magenta's. This makes a 4th corner where none should be located.&#xD;&#xA;&#xD;&#xA;Magentas are thus a bit of virtual colors that only exist in our brain. Not in physics, they are 2 spectra interleaved. There are off course many such metamers.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/COa4K.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2449" PostHistoryTypeId="2" PostId="1484" RevisionGUID="4e26bce4-e08d-4ae8-b882-69516c632493" CreationDate="2015-09-13T12:04:33.700" UserId="1630" Text="How do I can about defining this without using piecewise function?&#xD;&#xA;&#xD;&#xA;I think it has something to do with Bilinear Surface but not sure how to get started.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MpA53.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2450" PostHistoryTypeId="1" PostId="1484" RevisionGUID="4e26bce4-e08d-4ae8-b882-69516c632493" CreationDate="2015-09-13T12:04:33.700" UserId="1630" Text="two-dimensional bounded area defined parametrically" ContentLicense="CC BY-SA 3.0" />
  <row Id="2451" PostHistoryTypeId="3" PostId="1484" RevisionGUID="4e26bce4-e08d-4ae8-b882-69516c632493" CreationDate="2015-09-13T12:04:33.700" UserId="1630" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2452" PostHistoryTypeId="2" PostId="1485" RevisionGUID="c1b611b5-3ab8-458d-a3c8-eb0114b63da4" CreationDate="2015-09-13T14:07:26.800" UserId="1628" Text="Assume my 3d model is a pyramid with a rectangular base and I numerate four corners of the base with 1,2,3,4 and give the 5 to the top point. If I project this pyramid into a 2d star-shaped objects , would not all four outer points of the star be associated with the point number 5 in the 3d model ? " ContentLicense="CC BY-SA 3.0" />
  <row Id="2453" PostHistoryTypeId="1" PostId="1485" RevisionGUID="c1b611b5-3ab8-458d-a3c8-eb0114b63da4" CreationDate="2015-09-13T14:07:26.800" UserId="1628" Text="Does UV-mapping generate for some points of the 3D model several points in the 2D Projection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2454" PostHistoryTypeId="3" PostId="1485" RevisionGUID="c1b611b5-3ab8-458d-a3c8-eb0114b63da4" CreationDate="2015-09-13T14:07:26.800" UserId="1628" Text="|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2455" PostHistoryTypeId="5" PostId="1485" RevisionGUID="f0cc0774-70a3-44de-9547-af10ffbc28bb" CreationDate="2015-09-13T14:13:56.003" UserId="1628" Comment="added 90 characters in body" Text="Assume my 3d model is a pyramid with a rectangular base and I numerate four corners of the base with 1,2,3,4 and give the 5 to the top point. If I project this pyramid into a 2d star-shaped objects , would not all four outer points of the star be associated with the point number 5 in the 3d model ? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4jnxw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2456" PostHistoryTypeId="2" PostId="1486" RevisionGUID="8d5932a7-6fc8-4325-bde9-190f1414cb3a" CreationDate="2015-09-13T14:24:06.633" UserId="192" Text="One solution is bilinear mapping, which works for every quadrilateral.&#xD;&#xA;&#xD;&#xA;Let $A$, $B$, $C$, $D$ be the vertices of a quadrilateral $Q$ in the plane, in this order.&#xD;&#xA;&#xD;&#xA;Then $f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD$ maps the square $[0,1] \times [0,1]$ to $Q$." ContentLicense="CC BY-SA 3.0" />
  <row Id="2457" PostHistoryTypeId="5" PostId="1484" RevisionGUID="0b308b02-e6c2-46ac-be58-56dad2ccf2c1" CreationDate="2015-09-13T15:45:49.400" UserId="231" Comment="Tidying" Text="How do I go about defining this area without using a piecewise function?&#xD;&#xA;&#xD;&#xA;I think it has something to do with Bilinear Surfaces but I'm not sure how to get started.&#xD;&#xA;&#xD;&#xA;[![Graph showing an area composed of a square region adjoining a triangular region][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MpA53.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2458" PostHistoryTypeId="4" PostId="1484" RevisionGUID="0b308b02-e6c2-46ac-be58-56dad2ccf2c1" CreationDate="2015-09-13T15:45:49.400" UserId="231" Comment="Tidying" Text="Two-dimensional bounded area defined parametrically" ContentLicense="CC BY-SA 3.0" />
  <row Id="2459" PostHistoryTypeId="5" PostId="1485" RevisionGUID="e42d8333-2aef-451c-880e-232c4a9b3074" CreationDate="2015-09-13T15:56:23.850" UserId="231" Comment="Tidying" Text="Assume my 3D model is a pyramid with a rectangular base and I numerate four corners of the base with 1, 2, 3, 4 and give 5 to the top point. If I project this pyramid into a 2D star-shaped object, would not all four outer points of the star be associated with the point number 5 in the 3D model? &#xD;&#xA;&#xD;&#xA;[![Hand drawn image of a square base pyramid and its star shaped 2D net][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4jnxw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2460" PostHistoryTypeId="4" PostId="1485" RevisionGUID="e42d8333-2aef-451c-880e-232c4a9b3074" CreationDate="2015-09-13T15:56:23.850" UserId="231" Comment="Tidying" Text="Does UV-mapping generate for some points of the 3D model several points in the 2D projection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2461" PostHistoryTypeId="2" PostId="1487" RevisionGUID="a83cd1f3-90f6-4c3a-8321-f8aada03628a" CreationDate="2015-09-13T17:18:59.183" UserId="14" Text="The way it is usually defined, every vertex in a mesh corresponds to a UV-coordinate, and there must be exactly one such coordinate per vertex, because that is how a renderer would fetch texels. So it is impossible to have multiple UV coordinates for a single vertex unless you have multiple parameterizations for your mesh.&#xD;&#xA;&#xD;&#xA;However, meshes often get split up during parameterizations and the same vertices can end up in multiple locations, just like in your example. Most often, those vertices are simply replicated while loading/rendering so the vertex-to-uv mapping remains 1-to-1 or many-to-1. So a renderer will likely interpret your example as the following (v5 is split into 4 copies):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gqVkk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2462" PostHistoryTypeId="5" PostId="413" RevisionGUID="8b5de2fe-18fc-44ac-9386-0fc3ffe70b19" CreationDate="2015-09-13T17:20:53.280" UserId="14" Comment="added link to answer which uses this method" Text="I just use Powerpoint to make such diagrams and it works great as soon as you're comfortable with its basic primitives. It supports all simple operations like rotation, translation, etc. and recent revisions also have shear and 3D transforms. Examples:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here is an [example of a Powerpoint diagram][3] I made for an answer.&#xD;&#xA;&#xD;&#xA;For more complicated diagrams, especially in 3D, I sometimes use Blender with shadeless materials. I can elaborate and show examples if it is relevant to your question.&#xD;&#xA;&#xD;&#xA;Looks like [jsfiddle][4] is also popular around here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Hzmcd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ESDaY.png&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/a/1487/14&#xD;&#xA;  [4]: http://computergraphics.stackexchange.com/questions/324/is-this-smaller-grid-for-poisson-disc-sampling-still-correct" ContentLicense="CC BY-SA 3.0" />
  <row Id="2463" PostHistoryTypeId="5" PostId="1487" RevisionGUID="1b0c06bb-5205-4ca7-811b-b6dd26d231c1" CreationDate="2015-09-13T17:26:02.537" UserId="14" Comment="deleted 7 characters in body" Text="The way it is usually defined, every vertex in a mesh corresponds to a UV-coordinate, and there must be exactly one such coordinate per vertex, because that is how a renderer would fetch texels. So it is impossible to have multiple UV coordinates for a single vertex unless you have multiple parameterizations for your mesh.&#xD;&#xA;&#xD;&#xA;However, meshes often get split up during parameterizations and the same vertices can end up in multiple locations, just like in your example. Most often, those vertices are simply replicated while loading/rendering so the vertex-to-uv mapping remains 1-to-1 or many-to-1. So a renderer will likely interpret your example as the following (v5 is split into 4):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gqVkk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2464" PostHistoryTypeId="2" PostId="1488" RevisionGUID="a63850b2-7f88-4596-b5da-5cc1d7797c18" CreationDate="2015-09-13T17:41:06.043" UserId="1632" Text="i'm using unity 5 to make a small game (im a beginner) and i want to make a 3d model of a character. Im not sure what software there is to do this and if there is some, i would like it to be prefferably free, but if anyone can help or give advice i would appreciate it, just want to be able to make a 3d model, then import to unity 5. Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="2465" PostHistoryTypeId="1" PostId="1488" RevisionGUID="a63850b2-7f88-4596-b5da-5cc1d7797c18" CreationDate="2015-09-13T17:41:06.043" UserId="1632" Text="How to make a 3d model for unity 5" ContentLicense="CC BY-SA 3.0" />
  <row Id="2466" PostHistoryTypeId="3" PostId="1488" RevisionGUID="a63850b2-7f88-4596-b5da-5cc1d7797c18" CreationDate="2015-09-13T17:41:06.043" UserId="1632" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2467" PostHistoryTypeId="2" PostId="1489" RevisionGUID="ee52dee1-ac02-43c8-8423-72d73b16a9f0" CreationDate="2015-09-13T18:04:12.780" UserId="14" Text="[Blender][1] likely meets your requirements. I have used it in the past to make 3D models and export to OBJ files which Unity can import.&#xD;&#xA;&#xD;&#xA;I would highly recommend watching some tutorial videos before using it:&#xD;&#xA;&#xD;&#xA; - [one][2]&#xD;&#xA; - [two][3]&#xD;&#xA; - [three][4]&#xD;&#xA;&#xD;&#xA;[Blender StackExchange][5] can help answer more questions about Blender.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blender.org/&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=gF6qkByl-_M&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=y__uzGKmxt8&#xD;&#xA;  [4]: https://www.youtube.com/watch?v=2zd1AI198I8&#xD;&#xA;  [5]: http://blender.stackexchange.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2468" PostHistoryTypeId="5" PostId="1486" RevisionGUID="6011cfd0-9ac7-490f-ae41-d6f56d570ffe" CreationDate="2015-09-13T18:11:22.583" UserId="192" Comment="deleted 21 characters in body" Text="One solution is bilinear mapping, which works for every quadrilateral.&#xD;&#xA;&#xD;&#xA;Let A, B, C, D be the vertices of a quadrilateral Q in the plane, in this order.&#xD;&#xA;&#xD;&#xA;Then f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD maps the square [0,1] x [0,1] to Q." ContentLicense="CC BY-SA 3.0" />
  <row Id="2469" PostHistoryTypeId="5" PostId="1486" RevisionGUID="252bcc38-f75c-4ed3-9705-e904ded49120" CreationDate="2015-09-13T19:54:46.733" UserId="192" Comment="added 174 characters in body" Text="One solution is bilinear mapping, which works for every quadrilateral.&#xD;&#xA;&#xD;&#xA;Let A, B, C, D be the vertices of a quadrilateral Q in the plane, in this order.&#xD;&#xA;&#xD;&#xA;Then f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD maps the square [0,1] x [0,1] to Q.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DKYWs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3OIsg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2471" PostHistoryTypeId="5" PostId="1489" RevisionGUID="9b2d233d-4be9-4057-967c-9abd858bb926" CreationDate="2015-09-13T23:39:40.247" UserId="14" Comment="removed reference to OBJ" Text="[Blender][1] likely meets your requirements. I have used it in the past to make 3D models and export to model files which Unity can import.&#xD;&#xA;&#xD;&#xA;I would highly recommend watching some tutorial videos before using it:&#xD;&#xA;&#xD;&#xA; - [one][2]&#xD;&#xA; - [two][3]&#xD;&#xA; - [three][4]&#xD;&#xA;&#xD;&#xA;[Blender StackExchange][5] can help answer more questions about Blender.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blender.org/&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=gF6qkByl-_M&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=y__uzGKmxt8&#xD;&#xA;  [4]: https://www.youtube.com/watch?v=2zd1AI198I8&#xD;&#xA;  [5]: http://blender.stackexchange.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2472" PostHistoryTypeId="2" PostId="1490" RevisionGUID="60725c67-1fb8-4d6c-bafb-f66ee2aa250e" CreationDate="2015-09-14T06:51:06.910" UserId="1636" Text="In all computer graphics books there are algorithms for scan converting simple primitives like lines, circles, ellipse,...&#xD;&#xA;&#xD;&#xA;I can't find algorithms for more advanced curves like bezier curves, b-spline, nurbs.&#xD;&#xA;&#xD;&#xA;Where can I find the references ?&#xD;&#xA;&#xD;&#xA;I have also another doubt: are scan converting and rastering the same thing ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2473" PostHistoryTypeId="1" PostId="1490" RevisionGUID="60725c67-1fb8-4d6c-bafb-f66ee2aa250e" CreationDate="2015-09-14T06:51:06.910" UserId="1636" Text="Algorithms for scan converting b-spline and nurbs" ContentLicense="CC BY-SA 3.0" />
  <row Id="2474" PostHistoryTypeId="3" PostId="1490" RevisionGUID="60725c67-1fb8-4d6c-bafb-f66ee2aa250e" CreationDate="2015-09-14T06:51:06.910" UserId="1636" Text="|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2475" PostHistoryTypeId="5" PostId="1486" RevisionGUID="430245f5-d18f-41e7-b920-98f5032bd122" CreationDate="2015-09-14T12:32:06.717" UserId="205" Comment="Changed math formulas to code samples (mathJax not avalible yet)" Text="One solution is bilinear mapping, which works for every quadrilateral.&#xD;&#xA;&#xD;&#xA;Let `A, B, C, D` be the vertices of a quadrilateral `Q` in the plane, in this order.&#xD;&#xA;&#xD;&#xA;Then `f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD` maps the square `[0,1] x [0,1]` to `Q`.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DKYWs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3OIsg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2476" PostHistoryTypeId="24" PostId="1486" RevisionGUID="430245f5-d18f-41e7-b920-98f5032bd122" CreationDate="2015-09-14T12:32:06.717" Comment="Proposed by 205 approved by 100, 231 edit id of 53" ContentLicense="CC BY-SA 3.0" />
  <row Id="2477" PostHistoryTypeId="2" PostId="1491" RevisionGUID="c994ebc6-034c-4342-85a1-f82b29d0be83" CreationDate="2015-09-14T13:10:41.883" UserId="209" Text="Ignoring Non-uniform B-splines (rational or not), I have had some experience with rasterisation of Beziers and, since there is a trivial mapping from _Uniform_ B-Splines to Beziers, those too.&#xD;&#xA;&#xD;&#xA;I have used two different techniques: The first was a scan-line renderer that used Newton-Rhapson to compute the intersection of the current scanline with the curve. This requires the first derivative but, as that can be trivially derived, again as a Bezier representation, from the control points of the parent curve, it's easy to obtain. Further, the bounding box of the control points of the 1st derivative can be useful to detect if the region might have more than 1 intersection with the scan line.&#xD;&#xA;The current scanline can use the previous scanline's solution as a starting point - usually that gives a highly accurate solution with one iteration.&#xD;&#xA;&#xD;&#xA;Alternatively, a second approach is to simply apply binary subdivision of the curve and render it as series of straight line segments with your favourite polygonal renderer. If I recall correctly, at least with cubic Beziers, with each subdivision the error between the line segment joining the end points of the (sub)Bezier and the true curve decreases by a factor of 4. In most cases it therefore doesn't take many subdivisions before the difference between the polygonal approximation and the true curve is insignificant.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2478" PostHistoryTypeId="5" PostId="1491" RevisionGUID="f12bc86a-3a33-4516-b0ad-85e4982a42d9" CreationDate="2015-09-14T13:18:08.537" UserId="209" Comment="added 214 characters in body" Text="Ignoring Non-uniform B-splines (rational or not), I have had some experience with rasterisation of Beziers and, since there is a trivial mapping from _Uniform_ B-Splines to Beziers, those too.&#xD;&#xA;&#xD;&#xA;I have used two different techniques: The first was a scan-line renderer that used Newton-Rhapson to compute the intersection of the current scanline with the curve. This requires the first derivative but, as that can be trivially derived, again as a Bezier representation, from the control points of the parent curve, it's easy to obtain. Further, the bounding box of the control points of the 1st derivative can be useful to detect if the region might have more than 1 intersection with the scan line.&#xD;&#xA;The current scanline can use the previous scanline's solution as a starting point - usually that gives a highly accurate solution with one iteration.&#xD;&#xA;&#xD;&#xA;Alternatively, a second approach is to simply apply binary subdivision of the curve and render it as series of straight line segments with your favourite polygonal renderer. If I recall correctly, at least with cubic Beziers, with each subdivision the error between the line segment joining the end points of the (sub)Bezier and the true curve decreases by a factor of 4. In most cases it therefore doesn't take many subdivisions before the difference between the polygonal approximation and the true curve is insignificant.&#xD;&#xA;&#xD;&#xA;Finally, if you need info on derivatives of Beziers (or almost everything else related to them), [this astounding web-page appeared][1] in my twitter feed recently.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pomax.github.io/bezierinfo/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2479" PostHistoryTypeId="5" PostId="1486" RevisionGUID="66a9ba0a-9455-46e1-a624-8269d01b16a6" CreationDate="2015-09-14T13:57:00.920" UserId="192" Comment="added 7 characters in body" Text="One solution is bilinear mapping, which works for every convex quadrilateral.&#xD;&#xA;&#xD;&#xA;Let `A, B, C, D` be the vertices of a quadrilateral `Q` in the plane, in this order.&#xD;&#xA;&#xD;&#xA;Then `f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD` maps the square `[0,1] x [0,1]` to `Q`.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DKYWs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3OIsg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2480" PostHistoryTypeId="34" PostId="411" RevisionGUID="7ca4b9ec-0610-41ec-9027-10dd32772c16" CreationDate="2015-09-14T22:13:48.193" UserId="231" Comment="11" />
  <row Id="2481" PostHistoryTypeId="2" PostId="1492" RevisionGUID="26b6fb0f-9283-4d5c-ae8d-035b0a74bd05" CreationDate="2015-09-15T02:18:19.527" UserId="1614" Text="I just need to add a bit to ap_'s answer.  &#xD;&#xA;Of course you can have multiple UV for one vertex, this is called UV layers. This is how engines have displayed lightmaps and albedo maps on the same time, since the advent of lightmaps. (quake engine in 1996 maybe ?)  &#xD;&#xA;You can have more UV layers, if you want to do multitexturing like for terrains, lightmap, albedo large, albedo detail, normal map...&#xD;&#xA;&#xD;&#xA;Unfortunately, the rasterizer will never chose a UV layer depending on the primitive it is rendering. Such a renderer could be done with a supplementary index buffer (primitive to UV layer mapping buffer) but no graphic cards and no graphics API supports this. This is an unnecessary violation to KISS anyway.  &#xD;&#xA;&#xD;&#xA;So, what one would do in this case is to separate your pyramid apex into 4 distinct vertices during design time. Anyway the first reason for this, not being UV unwrapping but mostly normal definition. If you want sharp edges, you need to break the shading, therefore you need to have different normals, they too, like UV, are usually defined 1-1 in the vertex stream.  &#xD;&#xA;&#xD;&#xA;Final suggestion, maybe you dont really want to use this unwrapping, I would rather suggest this:  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This way you have seamless continuity for filtering and looks on the edges and on the apex.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r1OYC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2482" PostHistoryTypeId="5" PostId="419" RevisionGUID="6f6ba063-fcd7-4c06-b439-e0123c700510" CreationDate="2015-09-15T08:55:58.333" UserId="209" Comment="Acknowledged the other answer." Text="Just adding to imallett's answer, it is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can significantly influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can be costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to use of Twiddled-order textures in at least some early PC HW). &#xD;&#xA;&#xD;&#xA;  [1]: http://penguin.ewu.edu/class/cscd470/Winter_13/JimBlinnsCorner/TruthAboutTextureMapping.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2484" PostHistoryTypeId="2" PostId="1493" RevisionGUID="7cb362d8-d32c-4c1e-b066-35cd0c254b5c" CreationDate="2015-09-15T11:55:18.913" UserId="1647" Text="My intuition has always been that when any sphere is projected into 2D space that the result will always mathematically be an ellipse (or a circle in degenerate cases).&#xD;&#xA;&#xD;&#xA;In the past when I was actively doing my own graphics programming and brought this up with other people they were adamant that I was wrong.&#xD;&#xA;&#xD;&#xA;Who was correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2485" PostHistoryTypeId="1" PostId="1493" RevisionGUID="7cb362d8-d32c-4c1e-b066-35cd0c254b5c" CreationDate="2015-09-15T11:55:18.913" UserId="1647" Text="Does a sphere projected into 2D space always result in an ellipse?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2486" PostHistoryTypeId="3" PostId="1493" RevisionGUID="7cb362d8-d32c-4c1e-b066-35cd0c254b5c" CreationDate="2015-09-15T11:55:18.913" UserId="1647" Text="|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2487" PostHistoryTypeId="2" PostId="1494" RevisionGUID="953d8fd9-0640-4a5e-a1d0-24e09f3aac37" CreationDate="2015-09-15T12:01:59.980" UserId="157" Text="In 2009 it seems there was a development of an hierarchical and comparison motion detection algorithm that was proposed in this paper:&#xD;&#xA;&#xD;&#xA;[Motion detection: fast and robust algorithms for embedded systems][1]&#xD;&#xA;&#xD;&#xA;They managed to get a decent reduction of noise, as you can see in the last image of the paper. It seems it's the &quot;morphological post-processing&quot; that removes stand-alone pixels (section **2.4 New hierarchical algorithm**). Perhaps a similar technique can be applied to denoise the video.&#xD;&#xA;&#xD;&#xA;  [1]: http://perso.ensta-paristech.fr/~manzaner/Publis/icip09.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2488" PostHistoryTypeId="2" PostId="1495" RevisionGUID="fdc1fa2c-cbd0-4329-ba40-3b151bc5c522" CreationDate="2015-09-15T12:02:02.450" UserId="157" Text="I first read [Alan's answer about video noise removal][1] which lead me to this question. I found later [some algorithms ideas][2] which capture motion in a similar way (frame comparison, as Alan described).&#xD;&#xA;&#xD;&#xA;And then I found this [&quot;motion detection: fast and robust algorithms&quot; paper][3] where they propose a hierarchical and conditional motion detection algorithm... I didn't read it throughly, but they seem to have isolated well all the objects in motion, since noise was almost completely removed (last image of the paper). However they say:&#xD;&#xA;&#xD;&#xA;&gt; As its complexity remains low, this algorithm is well suited for very&#xD;&#xA;&gt; light embedded systems. Future work will consider other difficult&#xD;&#xA;&gt; sequences with the presence of clutter like snow, rain or moving&#xD;&#xA;&gt; trees.&#xD;&#xA;&#xD;&#xA;What if my intention was actually use their &quot;morphological post-processing&quot; technique to remove the detection of small objects instead of &quot;stand-alone pixels&quot; (their size would be defined according to the frame resolution)? This paper was published in 2009 and I found [this related paper][4], also from 2009... Are there any newer updates on this or different techniques?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/a/401/157&#xD;&#xA;  [2]: http://www.codeproject.com/Articles/10248/Motion-Detection-Algorithms&#xD;&#xA;  [3]: http://perso.ensta-paristech.fr/~manzaner/Publis/icip09.pdf&#xD;&#xA;  [4]: http://link.springer.com/article/10.1007%2Fs11554-008-0096-7" ContentLicense="CC BY-SA 3.0" />
  <row Id="2489" PostHistoryTypeId="1" PostId="1495" RevisionGUID="fdc1fa2c-cbd0-4329-ba40-3b151bc5c522" CreationDate="2015-09-15T12:02:02.450" UserId="157" Text="How to ignore rain or smaller objects movements in motion detection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2490" PostHistoryTypeId="3" PostId="1495" RevisionGUID="fdc1fa2c-cbd0-4329-ba40-3b151bc5c522" CreationDate="2015-09-15T12:02:02.450" UserId="157" Text="|algorithm|denoise|motion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2491" PostHistoryTypeId="2" PostId="1496" RevisionGUID="ee0a02b2-7673-4e01-9336-76f411bd854d" CreationDate="2015-09-15T12:06:48.257" UserId="1647" Text="Back in the day when you often had to write your own low level rendering algorithms we all used to learn the Bresenham algorithsm for lines and circles.&#xD;&#xA;&#xD;&#xA;It was almost trivially easy to extend the Bresenham circle algorithm to cover ellipses whose axes were parallel to the X and Y axes.&#xD;&#xA;&#xD;&#xA;But it always eluded me if there was some Bresenham-style way to render an arbitrary ellipse whose axes were at some arbitrary.&#xD;&#xA;&#xD;&#xA;Does such a scanline method for rotated ellipses exist?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2492" PostHistoryTypeId="1" PostId="1496" RevisionGUID="ee0a02b2-7673-4e01-9336-76f411bd854d" CreationDate="2015-09-15T12:06:48.257" UserId="1647" Text="Is there some kind of Bresenham algorithm or equivalent for scanline rendering a rotated ellipse?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2493" PostHistoryTypeId="3" PostId="1496" RevisionGUID="ee0a02b2-7673-4e01-9336-76f411bd854d" CreationDate="2015-09-15T12:06:48.257" UserId="1647" Text="|rendering|algorithm|curve|scanline|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2494" PostHistoryTypeId="6" PostId="1459" RevisionGUID="9b731882-2074-4e91-96d9-696c29c7e19c" CreationDate="2015-09-15T13:42:47.657" UserId="1647" Comment="add terminology tag" Text="|vector-graphics|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2495" PostHistoryTypeId="24" PostId="1459" RevisionGUID="9b731882-2074-4e91-96d9-696c29c7e19c" CreationDate="2015-09-15T13:42:47.657" Comment="Proposed by 1647 approved by 464 edit id of 54" ContentLicense="CC BY-SA 3.0" />
  <row Id="2496" PostHistoryTypeId="2" PostId="1497" RevisionGUID="fb7dacc2-1e25-450d-8d23-a95673bb1bda" CreationDate="2015-09-15T14:39:41.883" UserId="537" Text="Projection systems is being used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection systems, different results and shapes like rectangle, pie, ellipse, circle, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA; Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I like to use a very touchable and common example that we all have seen it before, Earth sphere and global wide maps, they are every where.&#xD;&#xA;&#xD;&#xA;#Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in real like iceland which is 1/14 of africa continent in reality but the map shows them both as equal. this is because when we are omiting one dimension we would loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;#Different Projection Systems and Their Results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesnt conserve distance,angles or area, the red circles shows the amount of exaggeration that is product of this projection*&#xD;&#xA;&#xD;&#xA;![first](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at the ice land and africa in this one and compare with above*&#xD;&#xA;&#xD;&#xA;![secound](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classifed by what they preserve&#xD;&#xA;&#xD;&#xA; 1. equal area &#xD;&#xA; 2. equal angle which preserve the shape without distortion (conformal)&#xD;&#xA; 3. equal distance&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is being used in many applications, Your sphere is a recangle here!&#xD;&#xA;&#xD;&#xA;&gt;So you can not say sphere will be projected to ellipse always, as mentioned above sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics(equal angle,distance,shape,area) look at the following picture, or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of above projection systems can be done with an iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you find this answer usfull.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2497" PostHistoryTypeId="5" PostId="1493" RevisionGUID="cd699b27-bfea-4574-af2f-415cf06e1356" CreationDate="2015-09-15T14:59:19.620" UserId="1647" Comment="clarify that i meant to ask about perspective projection. sorry!" Text="My intuition has always been that when any sphere is projected into 2D space that the result will always mathematically be an ellipse (or a circle in degenerate cases).&#xD;&#xA;&#xD;&#xA;In the past when I was actively doing my own graphics programming and brought this up with other people they were adamant that I was wrong.&#xD;&#xA;&#xD;&#xA;Who was correct?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Since there is already one answer submitted, I don't wish to totally change my question but I realize I left out an important factor.&#xD;&#xA;&#xD;&#xA;I was interested only in **perspective projection**!&#xD;&#xA;&#xD;&#xA;The other projections are of course interesting for many uses so I wouldn't want them removed at this point. But it would be great if answers could have perspective projection as their most prominent section." ContentLicense="CC BY-SA 3.0" />
  <row Id="2498" PostHistoryTypeId="2" PostId="1498" RevisionGUID="d4161653-09a4-45b3-bc62-57b8b249fb40" CreationDate="2015-09-15T15:22:22.677" UserId="209" Text="Assuming a perspective projection and a view point external to the sphere, then the 'boundary' formed by the view point and the circle on the sphere which forms the horizon WRT the view point, will be a cone. &#xD;&#xA;&#xD;&#xA;Doing a perspective projection is then equivalent to intersecting this cone with a plane, which then produces a conic section. FYI the four cases are shown in this image from Wikipedia [![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;An ellipse/circle is thus a possibility, but not the only one - unbounded parabolas or hyperbolas (and I guess if the plane passes through the eye, even degenerate cases ) are possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RAwDQ.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Conic_section#/media/File:Conic_Sections.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2499" PostHistoryTypeId="2" PostId="1499" RevisionGUID="ceb1154b-82b1-4f42-ad86-b29f3c4c81b7" CreationDate="2015-09-15T16:14:06.920" UserId="192" Text="The classic book *Computer Graphics: Principles and Practice* (second edition) by Foley, van Dam, et al. describes such an algorithm in section 19.2.&#xD;&#xA;&#xD;&#xA;See also these papers:&#xD;&#xA;&#xD;&#xA;-  [Curve-drawing algorithms for raster displays](http://dx.doi.org/10.1145/282918.282943) by Van Aken and Novak (*ACM TOG*, 1985). &#xD;&#xA;&#xD;&#xA;- [A tracking algorithm for implicitly defined curves](http://doi.ieeecomputersociety.org/10.1109/38.506) by Chandler (*IEEE Computer Graphics and Applications*, 1988)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2500" PostHistoryTypeId="5" PostId="1499" RevisionGUID="4dce4a59-71f3-4d4b-8677-3b2c9f1db131" CreationDate="2015-09-15T16:22:50.447" UserId="192" Comment="added 189 characters in body" Text="The classic book *Computer Graphics: Principles and Practice* (second edition) by Foley, van Dam, et al. describes such an algorithm in section 19.2.&#xD;&#xA;&#xD;&#xA;The explanation in the book seems to come from a MSc thesis, [Raster Algorithms for 2D Primitives](http://cs.brown.edu/research/pubs/theses/masters/1989/dasilva.pdf) by Dilip Da Silva. &#xD;&#xA;&#xD;&#xA;See also these papers:&#xD;&#xA;&#xD;&#xA;-  [Curve-drawing algorithms for raster displays](http://dx.doi.org/10.1145/282918.282943) by Van Aken and Novak (*ACM TOG*, 1985). &#xD;&#xA;&#xD;&#xA;- [A tracking algorithm for implicitly defined curves](http://doi.ieeecomputersociety.org/10.1109/38.506) by Chandler (*IEEE Computer Graphics and Applications*, 1988)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2501" PostHistoryTypeId="5" PostId="1499" RevisionGUID="7033cc91-a857-4be3-b558-c1e2e6513e09" CreationDate="2015-09-15T16:31:12.100" UserId="192" Comment="added 1 character in body" Text="The classic book *Computer Graphics: Principles and Practice* (second edition) by Foley, van Dam, et al. describes such an algorithm in section 19.2.&#xD;&#xA;&#xD;&#xA;The explanation in the book seems to come from an MSc thesis, [Raster Algorithms for 2D Primitives](http://cs.brown.edu/research/pubs/theses/masters/1989/dasilva.pdf) by Dilip Da Silva. &#xD;&#xA;&#xD;&#xA;See also these papers:&#xD;&#xA;&#xD;&#xA;-  [Curve-drawing algorithms for raster displays](http://dx.doi.org/10.1145/282918.282943) by Van Aken and Novak (*ACM TOG*, 1985). &#xD;&#xA;&#xD;&#xA;- [A tracking algorithm for implicitly defined curves](http://doi.ieeecomputersociety.org/10.1109/38.506) by Chandler (*IEEE Computer Graphics and Applications*, 1988)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2502" PostHistoryTypeId="5" PostId="1497" RevisionGUID="3f1ad0e6-53bc-4daa-b2a9-998ffae0eb1a" CreationDate="2015-09-15T16:39:35.683" UserId="537" Comment="added 87 characters in body" Text="Projection systems is being used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection systems, different results and shapes like rectangle, pie, ellipse, circle, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA; Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I like to use a very touchable and common example that we all have seen it before, Earth sphere and global wide maps, they are every where.&#xD;&#xA;&#xD;&#xA;#Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in real like iceland which is 1/14 of africa continent in reality but the map shows them both as equal. this is because when we are omiting one dimension we would loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;#Different Projection Systems and Their Results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesnt conserve distance,angles or area, the red circles shows the amount of exaggeration that is product of this projection*&#xD;&#xA;&#xD;&#xA;![first](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at the ice land and africa in this one and compare with above*&#xD;&#xA;&#xD;&#xA;![secound](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classifed by what they preserve&#xD;&#xA;&#xD;&#xA; 1. equal area &#xD;&#xA; 2. equal angle which preserve the shape without distortion (conformal)&#xD;&#xA; 3. equal distance&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is being used in many applications, Your sphere is a recangle here!&#xD;&#xA;&#xD;&#xA;&gt;So you can not say sphere will be projected to ellipse always, as mentioned above sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics(equal angle,distance,shape,area) look at the following picture, or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of above projection systems can be done with an iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you find this answer usfull.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;&gt;Perspective projections are equi angle and yes its only produce ellipse out of spheres" ContentLicense="CC BY-SA 3.0" />
  <row Id="2503" PostHistoryTypeId="5" PostId="1496" RevisionGUID="de8ce8e9-c411-4a20-992a-d3846baa605e" CreationDate="2015-09-15T17:11:50.930" UserId="1647" Comment="typo" Text="Back in the day when you often had to write your own low level rendering algorithms we all used to learn the Bresenham algorithms for lines and circles.&#xD;&#xA;&#xD;&#xA;It was almost trivially easy to extend the Bresenham circle algorithm to cover ellipses whose axes were parallel to the X and Y axes.&#xD;&#xA;&#xD;&#xA;But it always eluded me if there was some Bresenham-style way to render an arbitrary ellipse whose axes were at some arbitrary.&#xD;&#xA;&#xD;&#xA;Does such a scanline method for rotated ellipses exist?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2504" PostHistoryTypeId="34" PostId="309" RevisionGUID="4e3181e2-1eec-4927-b1df-afeb63c4f432" CreationDate="2015-09-15T18:40:04.397" UserId="-1" Comment="12" />
  <row Id="2505" PostHistoryTypeId="2" PostId="1500" RevisionGUID="e0442ebb-1c96-4a92-bb16-a10ebad92fc1" CreationDate="2015-09-15T19:36:41.750" UserId="38" Text="This is more like a long comment to @SimonF's answer that I'm trying to make somewhat self contained.&#xD;&#xA;&#xD;&#xA;All cuts of cone are possible, hyperbola, parabola and ovals. This is easy to test by drawing images in a 3D engine by a extremely wide angle camera. Rotate the camera to say in 30 degree angle so the object is not in the middle of your focus. Then gradually move the camera closer to the sphere.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1:** Flying very close to a sphere looking slightly sideways. Notice how we suddenly puncture the surface form inside.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So to recap when the sphere is very close so it exits the picture in wide image it can be a parabola or hyperbola. But the shape will just exit the frame to do so.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zi6eX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="2506" PostHistoryTypeId="2" PostId="1501" RevisionGUID="9988d4e3-f574-4f93-a220-ed1d514f1aac" CreationDate="2015-09-15T20:39:57.047" UserId="48" Text="SimonF's reasoning basically convinced me, but I decided to do a sanity check. I loaded up a UE4 level that happens to have some spheres, like this one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I set the camera FOV up to 160 degrees to give lots of perspective distortion, and positioned it so the sphere was near the corner of the image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Then I took this into Inkscape and used the ellipse tool to draw on it:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Surprise! It's a perfect fit!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RQ16v.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/yzF3C.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/LuSyP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2507" PostHistoryTypeId="2" PostId="1502" RevisionGUID="3bab8231-02e6-40f2-a724-e839610af1ac" CreationDate="2015-09-15T21:08:13.860" UserId="127" Text="When rendering 3D scenes with transformations applied to the objects, normals have to be transformed with the transposed inverse of the model view matrix. So,&#xD;&#xA;&#xD;&#xA;    transpose(inverse(modelViewMatrix)) * normal&#xD;&#xA;&#xD;&#xA;When transforming the objects, it is clear that the normals need to be transformed accordingly. But why, mathematically, is this the corresponding transformation matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2508" PostHistoryTypeId="1" PostId="1502" RevisionGUID="3bab8231-02e6-40f2-a724-e839610af1ac" CreationDate="2015-09-15T21:08:13.860" UserId="127" Text="Why is the transposed inverse of the model view matrix used to transform the normal vectors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2509" PostHistoryTypeId="3" PostId="1502" RevisionGUID="3bab8231-02e6-40f2-a724-e839610af1ac" CreationDate="2015-09-15T21:08:13.860" UserId="127" Text="|transformations|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2510" PostHistoryTypeId="2" PostId="1503" RevisionGUID="99aa6e7a-f563-4622-9ed6-cc3131616490" CreationDate="2015-09-15T21:15:36.447" UserId="14" Text="This is simply because normals are not really vectors! They are created by cross products, which results in [bivectors][1], not vectors. Algebra works much different for these coordinates, and geometric transformation is just one operation that behaves differently.&#xD;&#xA;&#xD;&#xA;A great resource for learning more about this is [Eric Lengyel's presentation on Grassman Algebra][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bivector&#xD;&#xA;  [2]: http://www.terathon.com/gdc12_lengyel.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2515" PostHistoryTypeId="5" PostId="1497" RevisionGUID="4104b657-460d-483f-b245-35317707d6ad" CreationDate="2015-09-15T22:51:36.923" UserId="537" Comment="deleted 5 characters in body" Text="Projection systems is being used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection systems, different results and shapes like rectangle, pie, ellipse, circle, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA; Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I like to use a very touchable and common example that we all have seen it before, Earth sphere and global wide maps, they are every where.&#xD;&#xA;&#xD;&#xA;#Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in real like iceland which is 1/14 of africa continent in reality but the map shows them both as equal. this is because when we are omiting one dimension we would loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;#Different Projection Systems and Their Results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesnt conserve distance,angles or area, the red circles shows the amount of exaggeration that is product of this projection*&#xD;&#xA;&#xD;&#xA;![first](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at the ice land and africa in this one and compare with above*&#xD;&#xA;&#xD;&#xA;![secound](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classifed by what they preserve&#xD;&#xA;&#xD;&#xA; 1. equal area &#xD;&#xA; 2. equal angle which preserve the shape without distortion (conformal)&#xD;&#xA; 3. equal distance&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is being used in many applications, Your sphere is a recangle here!&#xD;&#xA;&#xD;&#xA;&gt;So you can not say sphere will be projected to ellipse always, as mentioned above sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics(equal angle,distance,shape,area) look at the following picture, or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of above projection systems can be done with an iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you find this answer usfull.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;&gt;In perspective projections I say yes only ellipse will be produced out of spheres" ContentLicense="CC BY-SA 3.0" />
  <row Id="2516" PostHistoryTypeId="2" PostId="1505" RevisionGUID="e632fe4a-8601-49ef-9b7a-57b56e6af429" CreationDate="2015-09-15T23:13:13.823" UserId="525" Text="A fairly basic but effective technique is [median filtering](https://en.wikipedia.org/wiki/Median_filter).  For video, you can apply it (spatio)temporally by replacing the value of each pixel in each frame by the median of the values of the pixel (and its neighbors) in the current and the *N* previous and later frames.&#xD;&#xA;&#xD;&#xA;A nice feature of median filtering is that it preserves linear edges (and, when used temporally, edges that move at a steady rate).  It does, however, tend to erode sharp corners and narrow ridges (and, temporally, narrow fast-moving features).  When overused, spatial median filtering has a tendency to create an over-smooth &quot;plastic&quot; appearance, while excessive temporal median filtering can even make small, fast-moving objects disappear completely.  ([Sometimes](http://photo.stackexchange.com/a/20960) this is considered a [feature.](http://www.deke.com/content/dekes-techniques-022-removing-people-with-image-stacks))&#xD;&#xA;&#xD;&#xA;It's possible to fine-tune and improve median filtering further with advanced techniques like motion tracking and threshold detection, but those also introduce an extra layer of complexity, and thus extra opportunities for unwanted artifacts if applied carelessly.  For many purposes, a simple median filter *of moderate size and strength* is often all you really need." ContentLicense="CC BY-SA 3.0" />
  <row Id="2517" PostHistoryTypeId="2" PostId="1506" RevisionGUID="8b5c4515-741a-4fd0-ae8d-2978a58cff2a" CreationDate="2015-09-15T23:32:23.543" UserId="48" Text="Here's a simple proof that the inverse transpose is required. Suppose we have a plane, defined by a plane equation _n_ &amp;middot; _x_ + _d_ = 0, where _n_ is the normal. Now I want to transform this plane by some matrix _M_. In other words, I want to find a new plane equation _n'_ &amp;middot; _Mx_ + _d'_ = 0 that is satisfied for exactly the same _x_ values that satisfy the previous plane equation.&#xD;&#xA;&#xD;&#xA;To do this, it suffices to set the two plane equations equal. (This gives up the ability to rescale the plane equations arbitrarily, but that's not important to the argument.) Then we can set _d'_ = _d_ and subtract it out. What we have left is:&#xD;&#xA;&#xD;&#xA;&gt; _n'_ &amp;middot; _Mx_ = _n_ &amp;middot; x&#xD;&#xA;&#xD;&#xA;I'll rewrite this with the dot products expressed in matrix notation (thinking of the vectors as 1-column matrices):&#xD;&#xA;&#xD;&#xA;&gt; _n'_&lt;sup&gt; T&lt;/sup&gt;_Mx_ = _n_&lt;sup&gt;T&lt;/sup&gt;_x_&#xD;&#xA;&#xD;&#xA;Now to satisfy this for _all_ _x_, we must have:&#xD;&#xA;&#xD;&#xA;&gt; _n'_&lt;sup&gt; T&lt;/sup&gt;_M_ = _n_&lt;sup&gt;T&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Now solving for _n'_ in terms of _n_,&#xD;&#xA;&#xD;&#xA;&gt; _n'_&lt;sup&gt; T&lt;/sup&gt; = _n_&lt;sup&gt;T&lt;/sup&gt;_M_&lt;sup&gt; &amp;ndash;1&lt;/sup&gt;&lt;br/&gt;&#xD;&#xA;&gt; _n'_ = (_n_&lt;sup&gt;T&lt;/sup&gt;_M_&lt;sup&gt; &amp;ndash;1&lt;/sup&gt;)&lt;sup&gt;T&lt;/sup&gt;&lt;br/&gt;&#xD;&#xA;&gt; _n'_ = (_M_&lt;sup&gt; &amp;ndash;1&lt;/sup&gt;)&lt;sup&gt;T&lt;/sup&gt; _n_&#xD;&#xA;&#xD;&#xA;Presto! If points _x_ are transformed by a matrix _M_, then plane normals must transform by the inverse transpose of _M_ in order to preserve the plane equation.&#xD;&#xA;&#xD;&#xA;This is basically a property of the dot product. In order for the dot product to remain invariant when a transformation is applied, the two vectors being dotted have to transform in corresponding but different ways.&#xD;&#xA;&#xD;&#xA;Mathematically, this can be described by saying that the normal vector isn't an ordinary vector, but a thing called a [covector](https://en.wikipedia.org/wiki/Linear_form) (aka covariant vector, dual vector, or linear form). A covector is basically defined as &quot;a thing that can be dotted with a vector to produce an invariant scalar&quot;. In order to achieve that, it has to transform using the inverse transpose of whatever matrix is operating on ordinary vectors. This holds in any number of dimensions.&#xD;&#xA;&#xD;&#xA;Note that in 3D specifically, a bivector is similar to a covector. They're not *quite* the same since they have different units: a covector has units of inverse length while a bivector has units of length squared (area), so they behave differently under scaling. However, they do transform the same way with respect to their orientation, which is what matters for normals. We usually don't care about the magnitude of a normal (we always normalize them to unit length anyway), so we usually don't need to worry about the difference between a bivector and a covector." ContentLicense="CC BY-SA 3.0" />
  <row Id="2519" PostHistoryTypeId="2" PostId="1507" RevisionGUID="49718312-2ecf-4f63-b98d-3fb51f0302cb" CreationDate="2015-09-16T06:04:16.483" UserId="14" Text="I notice that most photorealistic renderers have very similar material test scenes. Here are a few examples:&#xD;&#xA;&#xD;&#xA;Blender&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Mitsuba&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Vray&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;My question is: why is this specific model / style chosen to test materials? Does it have some advantage over teapots, spheres, and suzannes? Are there other common scenes for material testing?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3uG1m.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/EJIHh.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/dlDd6.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2520" PostHistoryTypeId="1" PostId="1507" RevisionGUID="49718312-2ecf-4f63-b98d-3fb51f0302cb" CreationDate="2015-09-16T06:04:16.483" UserId="14" Text="Why are material test scenes designed this way?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2521" PostHistoryTypeId="3" PostId="1507" RevisionGUID="49718312-2ecf-4f63-b98d-3fb51f0302cb" CreationDate="2015-09-16T06:04:16.483" UserId="14" Text="|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2522" PostHistoryTypeId="2" PostId="1508" RevisionGUID="bbec45f7-b35a-4dbc-9075-909a76dce8c9" CreationDate="2015-09-16T06:05:56.157" UserId="1657" Text="More of an extended comment than an answer:&#xD;&#xA;&#xD;&#xA;What do you mean by &quot;optimization and accuracy&quot;? Do you mean computational efficiency for some particular application, like ray tracing, physical simulation, CAD modeling, ....?&#xD;&#xA;&#xD;&#xA;Note that the idea of &quot;accuracy&quot; for a subdivision scheme is not well-posed. Different schemes will have different limit surfaces, but there is no canonical way of declaring one limit surface to be &quot;more accurate&quot; than any another. One can pose some constraints on the type of limit surface one desires, but these constraints are again very application-dependent: one person might ask for $G^n$ everywhere, the next will complain because this precludes preserving sharp creases.&#xD;&#xA;&#xD;&#xA;Catmull-Clark (and Loop, for triangle meshes) remains popular because of its simplicity, which in many cases outweigh its weaknesses (no handling of sharp features; loss of regularity at extraordinary vertices). Countless alternative schemes (which may or may not be improvements over Catmull-Clark, depending on the specific application) have been proposed -- if you have a *specific* application in mind, with specific requirements, we may be better able to help you navigate your options." ContentLicense="CC BY-SA 3.0" />
  <row Id="2523" PostHistoryTypeId="5" PostId="1493" RevisionGUID="2928b390-82d3-42ac-8ce8-9bde354339bc" CreationDate="2015-09-16T06:18:41.487" UserId="1647" Comment="tweak wording" Text="My intuition has always been that when any sphere is projected into 2D space that the result will always mathematically be an ellipse (or a circle in degenerate cases).&#xD;&#xA;&#xD;&#xA;In the past when I was actively doing my own graphics programming and brought this up with other people they were adamant that I was wrong. If I recall correctly they believed the result could be something vaguely &quot;egg shaped&quot;.&#xD;&#xA;&#xD;&#xA;Who was correct?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Since there is already one answer submitted, I don't wish to totally change my question but I realize I left out important details due to losing familiarity with the field over the years.&#xD;&#xA;&#xD;&#xA;I intended to ask specifically about **perspective projection where the projection is a linear application**.&#xD;&#xA;&#xD;&#xA;The other projections are of course interesting for many uses so I wouldn't want them removed at this point. But it would be great if answers could have perspective projection as their most prominent section." ContentLicense="CC BY-SA 3.0" />
  <row Id="2524" PostHistoryTypeId="2" PostId="1509" RevisionGUID="d8d868b6-2da3-4f46-a34b-fedc8523410f" CreationDate="2015-09-16T06:48:47.123" UserId="1659" Text="Not the definitive toolbox you might be looking for, but just an extra tool I use myself: for 3d graphics, Blender might come in handy. Especially if you use the Export_SVG plugin (available from http://dl.dropbox.com/u/16486113/Blender/archivos/temp/SVG/export_svg.py and http://blenderartists.org/forum/showthread.php?282824-SVG-output-script )&#xD;&#xA;&#xD;&#xA;This allows you to get Blenders 3d objects as vector graphics in Illustrator or AI. I find it gives me a nice quick start for creating **simple** 3d illustrations.&#xD;&#xA;&#xD;&#xA;Allow  me to paste an example. (In this example I use a lot of colors, but ofcourse, it can be all made black-and-red-on-white instead)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dIyo9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2525" PostHistoryTypeId="2" PostId="1510" RevisionGUID="fc82efd6-cf48-400c-8b9d-6df80672a834" CreationDate="2015-09-16T07:47:23.190" UserId="385" Text="While teapot, spheres and trusty Suzanne are not per se bad test scenes for materials, here are some things to consider. You can apply them to said examples to forge your own opinion.&#xD;&#xA;&#xD;&#xA;First and foremost, the viewer needs to be able to examine the behavior of the BRDF. Since it is dependent on both the direction of incident light and the direction from surface to viewer, you need to have as many combinations as possible in your test scene. A spheroid nicely covers all possible viewer angles.&#xD;&#xA;&#xD;&#xA;Notice that all three scenes feature some sharper edges or creases too. Differences in reflective behavior across a smooth surface (like a sphere) may be hard to conceive, so these edges put emphasis on this.&#xD;&#xA;&#xD;&#xA;Since the observed brightness and color is a combination of the material (i.e. the BRDF) and the lighting environment, it may be hard to tell one from another. The Vray test scene takes care of this. The 100% white 'core' and the 25% black floor help you get an idea of what the lighting in the scene is like.&#xD;&#xA;&#xD;&#xA;Blender and Vray both feature a grid that helps you estimate the total size of the scene. This helps with evaluating grain or surface texture." ContentLicense="CC BY-SA 3.0" />
  <row Id="2526" PostHistoryTypeId="2" PostId="1511" RevisionGUID="a91332bd-cb78-4387-aef6-4c0bc059bbe5" CreationDate="2015-09-16T07:58:58.323" UserId="38" Text="You can choose whatever you want offcourse. A good material sample ideally has a few properties.&#xD;&#xA;&#xD;&#xA;* It needs to show how the light falls of as the angle between light and surface normal changes. &#xD;&#xA;&#xD;&#xA;  A sphere is pretty good for this.&#xD;&#xA;&#xD;&#xA;* It needs to show how any possible environment, maps, reflects, refraction etc.&#xD;&#xA;&#xD;&#xA;  A sphere is pretty good for this.&#xD;&#xA;&#xD;&#xA;* It may need to show how nonlocal effects happen such as global lightning, incandescence, subsurface scattering work&#xD;&#xA;&#xD;&#xA;  Some cavities and variation would be nice. A sphere is abysmal for this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* The sample should be able to show how displacement looks like.&#xD;&#xA;&#xD;&#xA;  A simple shape demonstrates this better. Complex shapes can cause displacements to self intersect. And its hard to know what is modeling and what is not.&#xD;&#xA;&#xD;&#xA;Also it would be nice to see, different surface thicknesses, sharp corners, one way curved surfaces and doublecurvature surfaces. A neutral but nonuniform  environment would be nice too..." ContentLicense="CC BY-SA 3.0" />
  <row Id="2527" PostHistoryTypeId="5" PostId="1511" RevisionGUID="90d911d1-80d2-4b01-bb56-90244b19b14a" CreationDate="2015-09-16T08:06:13.643" UserId="38" Comment="added 87 characters in body" Text="You can choose whatever you want offcourse. A good material sample ideally has a few properties.&#xD;&#xA;&#xD;&#xA;* It needs to show how the light falls of as the angle between light and surface normal changes. &#xD;&#xA;&#xD;&#xA;  A sphere is pretty good for this.&#xD;&#xA;&#xD;&#xA;* It needs to show how any possible environment, maps, reflects, refraction etc.&#xD;&#xA;&#xD;&#xA;  A sphere is pretty good for this.&#xD;&#xA;&#xD;&#xA;* It may need to show how nonlocal effects happen such as global lightning, incandescence, subsurface scattering work&#xD;&#xA;&#xD;&#xA;  Some cavities and variation would be nice. A sphere is abysmal for this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* The sample should be able to show how displacement looks like.&#xD;&#xA;&#xD;&#xA;  A simple shape demonstrates this better. Complex shapes can cause displacements to self intersect. And its hard to know what is modeling and what is not.&#xD;&#xA;&#xD;&#xA;Also it would be nice to see, different surface thicknesses, sharp corners, one way curved surfaces and doublecurvature surfaces. A neutral but nonuniform  environment would be nice too. Object should have a reasonable uv map. Apparent scale might be needed in some projects." ContentLicense="CC BY-SA 3.0" />
  <row Id="2529" PostHistoryTypeId="5" PostId="1509" RevisionGUID="44bf50e9-f195-4981-bc9d-4715e0e7a43c" CreationDate="2015-09-16T08:30:31.280" UserId="1659" Comment="fixed error" Text="Not the definitive toolbox you might be looking for, but just an extra tool I use myself: for 3d graphics, Blender might come in handy. Especially if you use the Export_SVG plugin (available from http://dl.dropbox.com/u/16486113/Blender/archivos/temp/SVG/export_svg.py and http://blenderartists.org/forum/showthread.php?282824-SVG-output-script )&#xD;&#xA;&#xD;&#xA;This allows you to get Blenders 3d objects as vector graphics in Illustrator or Inkscape. I find it gives me a nice quick start for creating **simple** 3d illustrations.&#xD;&#xA;&#xD;&#xA;Allow  me to paste an example. (In this example I use a lot of colors, but ofcourse, it can be all made black-and-red-on-white instead)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dIyo9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2530" PostHistoryTypeId="5" PostId="1497" RevisionGUID="38a7267b-53d8-49ff-8c82-9d7df54fb925" CreationDate="2015-09-16T10:33:30.560" UserId="537" Comment="added 1204 characters in body" Text="Projection systems is being used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection systems, different results and shapes like rectangle, pie, ellipse, circle, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA; Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I like to use a very touchable and common example that we all have seen it before, Earth sphere and global wide maps, they are every where.&#xD;&#xA;&#xD;&#xA;#Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in real like iceland which is 1/14 of africa continent in reality but the map shows them both as equal. this is because when we are omiting one dimension we would loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;#Different Projection Systems and Their Results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesnt conserve distance,angles or area, the red circles shows the amount of exaggeration that is product of this projection*&#xD;&#xA;&#xD;&#xA;![first](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at the ice land and africa in this one and compare with above*&#xD;&#xA;&#xD;&#xA;![secound](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classifed by what they preserve&#xD;&#xA;&#xD;&#xA; 1. equal area &#xD;&#xA; 2. equal angle which preserve the shape without distortion (conformal)&#xD;&#xA; 3. equal distance&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is being used in many applications, Your sphere is a recangle here!&#xD;&#xA;&#xD;&#xA;&gt;So you can not say sphere will be projected to ellipse always, as mentioned above sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics(equal angle,distance,shape,area) look at the following picture, or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of above projection systems can be done with an iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you find this answer usfull.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;&gt;In perspective projections I say yes only ellipse will be produced out of spheres&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cutting a conic with a horizontal plane creates a circle.&#xD;&#xA;Cutting with an oblique plane creates a bevel which would be an ellipsis or a hyperbola depending on the cuttage angle, and when this angle inclines to be vertical in will creates a parabola.&#xD;&#xA;&#xD;&#xA;Maybe this obvious but take a look at their equations &#xD;&#xA;for simplicity I assumed all gemetries are origin centered&#xD;&#xA;&#xD;&#xA;#Equations :&#xD;&#xA;&#xD;&#xA;Circle : x2+y2=r2&#xD;&#xA;&#xD;&#xA;Ellipsis : ax2 + by2 = 0&#xD;&#xA;&#xD;&#xA;Hyperbola : ax2 - by2  = 0&#xD;&#xA;&#xD;&#xA;Parabola : ax2 = 0&#xD;&#xA;&#xD;&#xA;#Morphology :&#xD;&#xA;&#xD;&#xA;Ellipsis has two foci obviously, circle as a special kind of ellipsis has two foci two but they are coincident, hyperbola however is a y axis mirror of its equal ellipsis and it has two foci too, Parabola has one focus but actually it has two because the secound one is at infinity, when the cuttage plan inclines to 90 degree (bearing angle), secound focus goes to infinity.&#xD;&#xA;&#xD;&#xA;#Conclusion&#xD;&#xA;&#xD;&#xA;As you see all are ellipsis, however you may name them defferently to describe special cases, but if you are going to implement it in a game, you need to assume an ellipsis equation and it is enough. I can't tell which one of you guys are right, you or your friend, cause both could be right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2531" PostHistoryTypeId="5" PostId="1498" RevisionGUID="828df73b-4210-4b2c-a0bf-47c3692a177c" CreationDate="2015-09-16T10:39:10.450" UserId="209" Comment="Someone suggested that the projection should mention that it's explicitly on to a plane." Text="Assuming a perspective projection and a view point external to the sphere, then the 'boundary' formed by the view point and the circle on the sphere which forms the horizon WRT the view point, will be a cone. &#xD;&#xA;&#xD;&#xA;Doing a perspective projection (onto a plane) is then equivalent to intersecting this cone with the plane which thus produces a conic section. FYI the four cases are shown in this image from Wikipedia [![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;An ellipse/circle is thus a possibility, but not the only one - unbounded parabolas or hyperbolas (and I guess if the plane passes through the eye, even degenerate cases ) are possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RAwDQ.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Conic_section#/media/File:Conic_Sections.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2532" PostHistoryTypeId="5" PostId="1497" RevisionGUID="ca93aae6-4a60-4310-88d1-ab993b2e6a97" CreationDate="2015-09-16T10:43:42.953" UserId="537" Comment="added 67 characters in body" Text="Projection systems is being used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection systems, different results and shapes like rectangle, pie, ellipse, circle, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA; Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I like to use a very touchable and common example that we all have seen it before, Earth sphere and global wide maps, they are every where.&#xD;&#xA;&#xD;&#xA;#Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in real like iceland which is 1/14 of africa continent in reality but the map shows them both as equal. this is because when we are omiting one dimension we would loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;#Different Projection Systems and Their Results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesnt conserve distance,angles or area, the red circles shows the amount of exaggeration that is product of this projection*&#xD;&#xA;&#xD;&#xA;![first](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at the ice land and africa in this one and compare with above*&#xD;&#xA;&#xD;&#xA;![secound](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classifed by what they preserve&#xD;&#xA;&#xD;&#xA; 1. equal area &#xD;&#xA; 2. equal angle which preserve the shape without distortion (conformal)&#xD;&#xA; 3. equal distance&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is being used in many applications, Your sphere is a recangle here!&#xD;&#xA;&#xD;&#xA;&gt;So you can not say sphere will be projected to ellipse always, as mentioned above sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics(equal angle,distance,shape,area) look at the following picture, or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of above projection systems can be done with an iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you find this answer usfull.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;&gt;In perspective projections I say yes only ellipse will be produced out of spheres&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cutting a conic with a horizontal plane creates a circle.&#xD;&#xA;Cutting with an oblique plane creates a bevel which would be an ellipsis or a hyperbola depending on the cuttage angle, and when this angle inclines to be vertical in will creates a parabola. (following picture)&#xD;&#xA;&#xD;&#xA;![ellipsis](https://i.stack.imgur.com/RSoYm.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Maybe this obvious but take a look at their equations &#xD;&#xA;for simplicity I assumed all gemetries are origin centered&#xD;&#xA;&#xD;&#xA;#Equations :&#xD;&#xA;&#xD;&#xA;Circle : x2+y2=r2&#xD;&#xA;&#xD;&#xA;Ellipsis : ax2 + by2 = 0&#xD;&#xA;&#xD;&#xA;Hyperbola : ax2 - by2  = 0&#xD;&#xA;&#xD;&#xA;Parabola : ax2 = 0&#xD;&#xA;&#xD;&#xA;#Morphology :&#xD;&#xA;&#xD;&#xA;Ellipsis has two foci obviously, circle as a special kind of ellipsis has two foci two but they are coincident, hyperbola however is a y axis mirror of its equal ellipsis and it has two foci too, Parabola has one focus but actually it has two because the secound one is at infinity, when the cuttage plan inclines to 90 degree (bearing angle), secound focus goes to infinity.&#xD;&#xA;&#xD;&#xA;#Conclusion&#xD;&#xA;&#xD;&#xA;As you see all are ellipsis, however you may name them defferently to describe special cases, but if you are going to implement it in a game, you need to assume an ellipsis equation and it is enough. I can't tell which one of you guys are right, you or your friend, cause both could be right.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2533" PostHistoryTypeId="5" PostId="1459" RevisionGUID="cc530ee5-5c20-4947-86bb-aaf590455aeb" CreationDate="2015-09-16T13:05:43.533" UserId="528" Comment="Removed &quot;vector-graphics&quot; tag, fixed spelling of DirectX" Text="What is the practical difference between 3D Graphics Engine (OGRE), 3D Game Engine (Quake), 3D Software Rendering Engine, 3D Graphics API (OpenGL/DirectX)?&#xD;&#xA;&#xD;&#xA;Is OpenGL/DirectX a 3D Graphics API or a 3D Software Rendering Engine?&#xD;&#xA;&#xD;&#xA;If I want to start learning 3D computer graphics and geometric modeling, which one do I need?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2534" PostHistoryTypeId="6" PostId="1459" RevisionGUID="cc530ee5-5c20-4947-86bb-aaf590455aeb" CreationDate="2015-09-16T13:05:43.533" UserId="528" Comment="Removed &quot;vector-graphics&quot; tag, fixed spelling of DirectX" Text="|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2535" PostHistoryTypeId="24" PostId="1459" RevisionGUID="cc530ee5-5c20-4947-86bb-aaf590455aeb" CreationDate="2015-09-16T13:05:43.533" Comment="Proposed by 528 approved by 38, 100 edit id of 55" ContentLicense="CC BY-SA 3.0" />
  <row Id="2536" PostHistoryTypeId="5" PostId="1507" RevisionGUID="202802f6-596b-4861-bec0-5dc2946170ec" CreationDate="2015-09-16T13:26:11.833" UserId="4" Comment="Clarified the title somewhat for search results" Text="I notice that most photorealistic renderers have very similar material test scenes. Here are a few examples:&#xD;&#xA;&#xD;&#xA;Blender&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;Mitsuba&#xD;&#xA;&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA;Vray&#xD;&#xA;&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;My question is: why is this specific model / style chosen to test materials? Does it have some advantage over teapots, spheres, and suzannes? Are there other common scenes for material testing?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3uG1m.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/EJIHh.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/dlDd6.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2537" PostHistoryTypeId="4" PostId="1507" RevisionGUID="202802f6-596b-4861-bec0-5dc2946170ec" CreationDate="2015-09-16T13:26:11.833" UserId="4" Comment="Clarified the title somewhat for search results" Text="Why do most photorealistic renderers have a similar material test scene?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2538" PostHistoryTypeId="24" PostId="1507" RevisionGUID="202802f6-596b-4861-bec0-5dc2946170ec" CreationDate="2015-09-16T13:26:11.833" Comment="Proposed by 4 approved by -1 edit id of 56" ContentLicense="CC BY-SA 3.0" />
  <row Id="2539" PostHistoryTypeId="5" PostId="1507" RevisionGUID="3a04a1f3-cf8b-492a-a776-9c3ed8e09831" CreationDate="2015-09-16T13:26:11.833" UserId="38" Comment="Clarified the title somewhat for search results" Text="I notice that most photorealistic renderers have very similar material test scenes. Here are a few examples:&#xD;&#xA;&#xD;&#xA;Blender&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;Mitsuba&#xD;&#xA;&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA;Vray&#xD;&#xA;&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;My question is: why is this specific model / style chosen to test materials? Does it have some advantage over [teapots](http://i9.photobucket.com/albums/a90/thatsmessedup/teapot74hoursl24.png), spheres, and [suzannes](http://www.flickr.com/photos/thomasberglund/5215885180/)? Are there other common scenes for material testing?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3uG1m.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/EJIHh.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/dlDd6.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2540" PostHistoryTypeId="4" PostId="1507" RevisionGUID="3a04a1f3-cf8b-492a-a776-9c3ed8e09831" CreationDate="2015-09-16T13:26:11.833" UserId="38" Comment="Clarified the title somewhat for search results" Text="Why do most photorealistic renderers have a similar material test scenes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2541" PostHistoryTypeId="4" PostId="1507" RevisionGUID="a6cc0e10-a5c8-4413-a001-2d9eb843da0c" CreationDate="2015-09-16T13:37:34.167" UserId="38" Comment="edited title" Text="Why do most photorealistic renderers have similar material test scenes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2543" PostHistoryTypeId="5" PostId="1510" RevisionGUID="35090393-5d0c-4525-852d-34b72fc15693" CreationDate="2015-09-17T08:12:13.910" UserId="385" Comment="Added IBL link" Text="While teapot, spheres and trusty Suzanne are not per se bad test scenes for materials, here are some things to consider. You can apply them to said examples to forge your own opinion.&#xD;&#xA;&#xD;&#xA;First and foremost, the viewer needs to be able to examine the behavior of the BRDF. Since it is dependent on both the direction of incident light and the direction from surface to viewer, you need to have as many combinations as possible in your test scene. A spheroid nicely covers all possible viewer angles.&#xD;&#xA;&#xD;&#xA;Notice that all three scenes feature some sharper edges or creases too. Differences in reflective behavior across a smooth surface (like a sphere) may be hard to conceive, so these edges put emphasis on this.&#xD;&#xA;&#xD;&#xA;Since the observed brightness and color is a combination of the material (i.e. the BRDF) and the lighting environment, it may be hard to tell one from another. The Vray test scene takes care of this. The 100% white 'core' and the 25% black floor help you get an idea of what the lighting in the scene is like.&#xD;&#xA;&#xD;&#xA;Blender and Vray both feature a grid that helps you estimate the total size of the scene. This helps with evaluating grain or surface texture.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here is a side-by-side comparison of a cube, notched sphere and Suzanne for a glossy test material with a slight normal map (rendered in Blender with Cycles, lit with the [Dutch Skies 360 - Free 002][1] HDR):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The cube does a pretty good job on depicting the normal map. Suzanne really has some tough luck here - neither gloss nor normals can be seen clearly. The sphere, as expected, is reasonably good for both.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.hdrlabs.com/sibl/archive.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/aw7CZ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2547" PostHistoryTypeId="5" PostId="1510" RevisionGUID="f5df94ba-4f13-426a-930a-44bacb27c12a" CreationDate="2015-09-17T10:55:21.367" UserId="385" Comment="Updated test render" Text="While teapot, spheres and trusty Suzanne are not per se bad test scenes for materials, here are some things to consider. You can apply them to said examples to forge your own opinion.&#xD;&#xA;&#xD;&#xA;First and foremost, the viewer needs to be able to examine the behavior of the BRDF. Since it is dependent on both the direction of incident light and the direction from surface to viewer, you need to have as many combinations as possible in your test scene. A spheroid nicely covers all possible viewer angles.&#xD;&#xA;&#xD;&#xA;Notice that all three scenes feature some sharper edges or creases too. Differences in reflective behavior across a smooth surface (like a sphere) may be hard to conceive, so these edges put emphasis on this.&#xD;&#xA;&#xD;&#xA;Since the observed brightness and color is a combination of the material (i.e. the BRDF) and the lighting environment, it may be hard to tell one from another. The Vray test scene takes care of this. The 100% white 'core' and the 25% black floor help you get an idea of what the lighting in the scene is like.&#xD;&#xA;&#xD;&#xA;Blender and Vray both feature a grid that helps you estimate the total size of the scene. This helps with evaluating grain or surface texture.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here is a side-by-side comparison of a cube, notched sphere and Suzanne for a glossy test material with a slight normal map (rendered in Blender with Cycles, lit with the [Dutch Skies 360 - Free 002][1] HDR):&#xD;&#xA;&#xD;&#xA;[![Material test scene comparing cube, spheroid and Suzanne][2]][2]&#xD;&#xA;&#xD;&#xA;The cube does a pretty good job on depicting the normal map. The sphere, as expected, is reasonably good for normals and gloss. Suzanne, arguably, makes both a bit harder to perceive than the spheroid.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.hdrlabs.com/sibl/archive.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/wtFVi.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2549" PostHistoryTypeId="2" PostId="1513" RevisionGUID="8d01722e-8f98-41ce-a223-66d0828b85a6" CreationDate="2015-09-17T12:29:48.510" UserId="385" Text="The classical way of shading surfaces in real-time computer graphics is a combination of a (Lambertian) diffuse term and a specular term, most likely Phong or Blinn-Phong.&#xD;&#xA;&#xD;&#xA;[![Image from Wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;Now with the trend going towards physically-based rendering and thus material models in engines such as [Frostbite][2], [Unreal Engine][3] or [Unity 3D][3] these BRDFs have changed. For example (a pretty universal one at that), the latest Unreal Engine still uses Lambertian diffuse, but in combination with the Cook-Torrance microfacet model for specular reflection (specifically using GGX/Trowbridge-Reitz and a modified Slick approximation for the Fresnel term). Furthermore, a 'Metalness' value is be used to distinguish between conductor and dielectric.&#xD;&#xA;&#xD;&#xA;For dielectrics, diffuse is colored using the albedo of the material, while specular is always colorless. For metals, diffuse is not used and the specular term is multiplied with the albedo of the material.&#xD;&#xA;&#xD;&#xA;Regarding real-world physical materials, does the strict separation between diffuse and specular exist and if so, where does it come from? Why is one colored while the other is not? Why do conductors behave differently?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VOfxv.png&#xD;&#xA;  [2]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [3]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2550" PostHistoryTypeId="1" PostId="1513" RevisionGUID="8d01722e-8f98-41ce-a223-66d0828b85a6" CreationDate="2015-09-17T12:29:48.510" UserId="385" Text="How physically-based is the diffuse and specular distinction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2551" PostHistoryTypeId="3" PostId="1513" RevisionGUID="8d01722e-8f98-41ce-a223-66d0828b85a6" CreationDate="2015-09-17T12:29:48.510" UserId="385" Text="|physically-based|physics|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2553" PostHistoryTypeId="2" PostId="1514" RevisionGUID="84780c75-0b93-45f7-baa1-db8fc7b9f5e3" CreationDate="2015-09-17T17:02:42.913" UserId="310" Text="To start, I highly suggest reading Naty Hoffman's Siggraph [presentation][1] covering the physics of rendering. That said, I will try to answer your specific questions, borrowing images from his presentation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Looking at a single light particle hitting a point on the surface of a material, it can do 2 things: reflect, or refract. Reflected light will bounce away from the surface, similar to a mirror. Refracted light bounces around inside the material, and may exit the material some distance away from where it entered. Finally, every time the light interacts with the molecules of the material, it loses some energy. If it loses enough of its energy, we consider it to be fully absorbed.&#xD;&#xA;&#xD;&#xA;To quote Naty, &quot;Light is composed of electromagnetic waves. So the optical properties of a substance are closely linked to its electric properties.&quot; This is why we group materials as metals or non-metals.&#xD;&#xA;&#xD;&#xA;Non metals will exhibit both reflection and refraction.&#xD;&#xA;[![Non-Metals][2]][2]&#xD;&#xA;&#xD;&#xA;Metallic materials only have reflection. All refracted light is absorbed.&#xD;&#xA;[![Metals][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It would be prohibitively expensive to try to model the light particle's interaction with the molecules of the material. We instead, make some assumptions and simplifications.&#xD;&#xA;&#xD;&#xA;[![Simplifying refraction][4]][4]&#xD;&#xA;&#xD;&#xA;If the pixel size or shading area is large compared to the entry-exit distances, we can make the assumption that the distances are effectively zero.&#xD;&#xA;For convenience, we split the light interactions into two different terms. We call the surface reflection term &quot;specular&quot; and the term resulting from refraction, absorption, scattering, and re-refraction we call &quot;diffuse&quot;.&#xD;&#xA;[![Splitting into diffuse and specular][5]][5]&#xD;&#xA;&#xD;&#xA;However, this is a pretty large assumption. For most opaque materials, this assumption is ok and doesn't differ too much from real-life. However, for materials with any kind of transparency, the assumption fails. For example, milk, skin, soap, etc. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A material's observed color is the light that is not absorbed. This is a combination of both the reflected light, as well as any refracted light that exits the material. For example, a pure green material will absorb all light that is not green, so the only light to reach our eyes is the green light.&#xD;&#xA;&#xD;&#xA;Therefore an artist models the color of a material by giving us the attenuation function for the material, ie how the light will be absorbed by the material. In our simplified diffuse/specular model, this can be represented by two colors, the diffuse color, and the specular color. Back before physically-based materials were used, the artist would arbitrarily choose each of these colors. However, it should seem obvious that these two colors should be related. This is where the albedo color comes in. For example, in UE4, they calculate diffuse and specular color as follows:&#xD;&#xA;&#xD;&#xA;    DiffuseColor = AlbedoColor - AlbedoColor * Metallic;&#xD;&#xA;	SpecColor = lerp(0.08 * Specular.xxx, AlbedoColor, Metallic)&#xD;&#xA;&#xD;&#xA;where Metallic is 0 for non-metals and 1 for metals.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/ECwfp.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JyBy3.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/PXEQW.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/85Pmg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2558" PostHistoryTypeId="5" PostId="1514" RevisionGUID="e6b629ac-5681-4728-a6f1-2100fa33bbe3" CreationDate="2015-09-17T21:52:08.073" UserId="310" Comment="Explained the Specular.xxx in the last formula" Text="To start, I highly suggest reading Naty Hoffman's Siggraph [presentation][1] covering the physics of rendering. That said, I will try to answer your specific questions, borrowing images from his presentation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Looking at a single light particle hitting a point on the surface of a material, it can do 2 things: reflect, or refract. Reflected light will bounce away from the surface, similar to a mirror. Refracted light bounces around inside the material, and may exit the material some distance away from where it entered. Finally, every time the light interacts with the molecules of the material, it loses some energy. If it loses enough of its energy, we consider it to be fully absorbed.&#xD;&#xA;&#xD;&#xA;To quote Naty, &quot;Light is composed of electromagnetic waves. So the optical properties of a substance are closely linked to its electric properties.&quot; This is why we group materials as metals or non-metals.&#xD;&#xA;&#xD;&#xA;Non metals will exhibit both reflection and refraction.&#xD;&#xA;[![Non-Metals][2]][2]&#xD;&#xA;&#xD;&#xA;Metallic materials only have reflection. All refracted light is absorbed.&#xD;&#xA;[![Metals][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It would be prohibitively expensive to try to model the light particle's interaction with the molecules of the material. We instead, make some assumptions and simplifications.&#xD;&#xA;&#xD;&#xA;[![Simplifying refraction][4]][4]&#xD;&#xA;&#xD;&#xA;If the pixel size or shading area is large compared to the entry-exit distances, we can make the assumption that the distances are effectively zero.&#xD;&#xA;For convenience, we split the light interactions into two different terms. We call the surface reflection term &quot;specular&quot; and the term resulting from refraction, absorption, scattering, and re-refraction we call &quot;diffuse&quot;.&#xD;&#xA;[![Splitting into diffuse and specular][5]][5]&#xD;&#xA;&#xD;&#xA;However, this is a pretty large assumption. For most opaque materials, this assumption is ok and doesn't differ too much from real-life. However, for materials with any kind of transparency, the assumption fails. For example, milk, skin, soap, etc. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A material's observed color is the light that is not absorbed. This is a combination of both the reflected light, as well as any refracted light that exits the material. For example, a pure green material will absorb all light that is not green, so the only light to reach our eyes is the green light.&#xD;&#xA;&#xD;&#xA;Therefore an artist models the color of a material by giving us the attenuation function for the material, ie how the light will be absorbed by the material. In our simplified diffuse/specular model, this can be represented by two colors, the diffuse color, and the specular color. Back before physically-based materials were used, the artist would arbitrarily choose each of these colors. However, it should seem obvious that these two colors should be related. This is where the albedo color comes in. For example, in UE4, they calculate diffuse and specular color as follows:&#xD;&#xA;&#xD;&#xA;    DiffuseColor = AlbedoColor - AlbedoColor * Metallic;&#xD;&#xA;	SpecColor = lerp(0.08 * Specular.xxx, AlbedoColor, Metallic)&#xD;&#xA;&#xD;&#xA;where Metallic is 0 for non-metals and 1 for metals. The 'Specular' parameter controls the specularity of an object (but it's usually a constant 0.5 for 99% of materials)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/ECwfp.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JyBy3.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/PXEQW.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/85Pmg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2560" PostHistoryTypeId="2" PostId="1515" RevisionGUID="d21c692b-5877-4319-8c52-d6c33a11864a" CreationDate="2015-09-18T04:29:45.047" UserId="14" Text="Most modern renderers use physically-based materials and their models are often parameterized over roughness. Since this wasn't always the case with renderers, conventional assets often don't have a notion of roughness. Instead, we see &quot;shininess&quot; or &quot;specular power&quot; as a common material parameter.&#xD;&#xA;&#xD;&#xA;I understand that there is no exact conversion between the two, but is there a rule-of-thumb / approximate way to get roughness for a material whose specular power or shininess is known?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2561" PostHistoryTypeId="1" PostId="1515" RevisionGUID="d21c692b-5877-4319-8c52-d6c33a11864a" CreationDate="2015-09-18T04:29:45.047" UserId="14" Text="What is the accepted method of converting shininess to roughness, and vice versa?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2562" PostHistoryTypeId="3" PostId="1515" RevisionGUID="d21c692b-5877-4319-8c52-d6c33a11864a" CreationDate="2015-09-18T04:29:45.047" UserId="14" Text="|specular|brdf|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2565" PostHistoryTypeId="2" PostId="1517" RevisionGUID="6cafc115-f3d6-4342-b67f-74695344c812" CreationDate="2015-09-18T07:30:54.973" UserId="528" Text="As you already note, there is no clear cut interpretation/conversion for these values. I think it is even much worse: Depending on your BRDF and internal limitations (like having defined exponents ranging from 2-2048) the interpretation is _completely_ different. Like suggested in the comments, it might be the best to render a series with different values and fit a conversion curve until the value looks intuitive.&#xD;&#xA;&#xD;&#xA;A few examples I was able to find some blog posts that mention something about that topic:&#xD;&#xA;&#xD;&#xA; - At Dontnod entertainment they use a &quot;perceptual linear distribution&quot;. &#xD;&#xA;Sébastien Lagarde acknowledges the problem in [this blog post][1] and writes a few notes on that.&#xD;&#xA; - Brian Karis uses a squared roughness values in this [Microfacet BRDF overview][2]. This illustrates also nicely how differently  roughness is used in different Normal Distribution Functions. Blinn-Phong power is here defined as `2/roughness^4 - 2`.&#xD;&#xA; - [This blog post][3] suggests to define the roughness for a Beckmann distribution from the roughness alpha as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/&#xD;&#xA;  [2]: http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html&#xD;&#xA;  [3]: http://simonstechblog.blogspot.de/2011/12/microfacet-brdf.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/1NWdA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2567" PostHistoryTypeId="6" PostId="1493" RevisionGUID="7a8f4478-f8dd-4f94-ac6d-7d0ef4f20441" CreationDate="2015-09-18T08:03:39.967" UserId="231" Comment="Add tag" Text="|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2569" PostHistoryTypeId="5" PostId="1497" RevisionGUID="fb944161-7a49-47d6-87ad-605287e1ab79" CreationDate="2015-09-18T09:32:14.693" UserId="231" Comment="Add mathurl.com equations until we get MathJax, plus edit for consistency and typos." Text="Projection systems are used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection system, different results and shapes like rectangles, pies, ellipses, circles, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA;Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I would like to use a very touchable and common example that we have all seen before, Earth sphere and global wide maps, they are everywhere.&#xD;&#xA;&#xD;&#xA;# Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in reality, like Iceland which is 1/14 of Africa continent in reality but the map shows them both as equal. This is because when we are omitting one dimension we loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;# Different projection systems and their results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesn't conserve distance, angles or area. The red circles show the amount of exaggeration that is the product of this projection.*&#xD;&#xA;&#xD;&#xA;![First](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at Iceland and Africa in this one and compare with above.*&#xD;&#xA;&#xD;&#xA;![Second](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classified by what they preserve.&#xD;&#xA;&#xD;&#xA; 1. Equal area.&#xD;&#xA; 2. Equal angle which preserve the shape without distortion (conformal).&#xD;&#xA; 3. Equal distance.&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is used in many applications. Your sphere is a rectangle here!&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;### So you cannot say a sphere will be projected to an ellipse always. As mentioned above a sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics (equal angle, distance, shape, area - see the following picture), or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of the above projection systems can be applied with iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you to find this answer useful.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;### In perspective projections I say yes only ellipses will be produced out of spheres&#xD;&#xA;&#xD;&#xA;Cutting a conic with a horizontal plane creates a circle.&#xD;&#xA;&#xD;&#xA;Cutting with an oblique plane creates a bevel which would be an ellipse or a hyperbola depending on the cutting angle, and when this angle inclines to be vertical in will create a parabola (following picture).&#xD;&#xA;&#xD;&#xA;![Ellipse](https://i.stack.imgur.com/RSoYm.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Maybe this is obvious but take a look at their equations.&#xD;&#xA;&#xD;&#xA;For simplicity I assumed all geometries are origin centered.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Equations:&#xD;&#xA;&#xD;&#xA;Circle: [![Circle formula][circle formula image]][circle formula link]&#xD;&#xA;&#xD;&#xA;Ellipse: [![Ellipse formula][ellipse formula image]][ellipse formula link]&#xD;&#xA;&#xD;&#xA;Hyperbola : [![Hyperbola formula][hyperbola formula image]][hyperbola formula link]&#xD;&#xA;&#xD;&#xA;Parabola : [![Parabola formula][parabola formula image]][parabola formula link]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Morphology :&#xD;&#xA;&#xD;&#xA;An ellipse has two foci obviously. A circle as a special kind of ellipsis has two foci too but they are coincident. A hyperbola however is a y axis mirror of its equal ellipsis and it has two foci too. A parabola has one focus but actually it has two because the second one is at infinity: when the cutting plane inclines to 90 degrees (bearing angle), second focus goes to infinity.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Conclusion&#xD;&#xA;&#xD;&#xA;As you see all are ellipses, however you may name them differently to describe special cases, but if you are going to implement it in a game, you need to assume an ellipse equation and it is enough. I can't tell which one of you guys are right, you or your friend, because both could be right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[circle formula link]: http://mathurl.com/p2a55su&#xD;&#xA;&#xD;&#xA;[ellipse formula link]: http://mathurl.com/qha4vpo&#xD;&#xA;&#xD;&#xA;[hyperbola formula link]: http://mathurl.com/2dvnym7&#xD;&#xA;&#xD;&#xA;[parabola formula link]: http://mathurl.com/ooj7n62&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[circle formula image]: http://mathurl.com/p2a55su.png &quot;Click to edit on mathurl.com&quot;&#xD;&#xA;&#xD;&#xA;[ellipse formula image]: http://mathurl.com/qha4vpo.png &quot;Click to edit on mathurl.com&quot;&#xD;&#xA;&#xD;&#xA;[hyperbola formula image]: http://mathurl.com/2dvnym7.png &quot;Click to edit on mathurl.com&quot;&#xD;&#xA;&#xD;&#xA;[parabola formula image]: http://mathurl.com/ooj7n62.png &quot;Click to edit on mathurl.com&quot;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2570" PostHistoryTypeId="10" PostId="1488" RevisionGUID="ccd73a15-d519-4e20-a0b3-7ddba44eaab6" CreationDate="2015-09-18T11:02:08.207" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:385,&quot;DisplayName&quot;:&quot;David Kuri&quot;}]}" />
  <row Id="2571" PostHistoryTypeId="5" PostId="1517" RevisionGUID="4bd98a43-d679-474e-a2ca-12ed0f9e12b2" CreationDate="2015-09-18T16:01:43.147" UserId="310" Comment="Added a note on what Frostbite uses" Text="As you already note, there is no clear cut interpretation/conversion for these values. I think it is even much worse: Depending on your BRDF and internal limitations (like having defined exponents ranging from 2-2048) the interpretation is _completely_ different. Like suggested in the comments, it might be the best to render a series with different values and fit a conversion curve until the value looks intuitive.&#xD;&#xA;&#xD;&#xA;A few examples I was able to find some blog posts that mention something about that topic:&#xD;&#xA;&#xD;&#xA; - At Dontnod entertainment they use a &quot;perceptual linear distribution&quot;. &#xD;&#xA;Sébastien Lagarde acknowledges the problem in [this blog post][1] and writes a few notes on that.&#xD;&#xA; - Brian Karis uses a squared roughness values in this [Microfacet BRDF overview][2]. This illustrates also nicely how differently  roughness is used in different Normal Distribution Functions. Blinn-Phong power is here defined as `2/roughness^4 - 2`.&#xD;&#xA; - Frostbite uses a squared remapping. ie. Roughness =  (1 − Smoothness)^2&#xD;&#xA;Details about it and their entire material system is explained in section 3.2 of Sebastien Lagarde's [writeup][3].&#xD;&#xA; - [This blog post][4] suggests to define the roughness for a Beckmann distribution from the roughness alpha as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/&#xD;&#xA;  [2]: http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html&#xD;&#xA;  [3]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [4]: http://simonstechblog.blogspot.de/2011/12/microfacet-brdf.html&#xD;&#xA;  [5]: https://i.stack.imgur.com/1NWdA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2572" PostHistoryTypeId="24" PostId="1517" RevisionGUID="4bd98a43-d679-474e-a2ca-12ed0f9e12b2" CreationDate="2015-09-18T16:01:43.147" Comment="Proposed by 310 approved by 528 edit id of 57" ContentLicense="CC BY-SA 3.0" />
  <row Id="2573" PostHistoryTypeId="2" PostId="1518" RevisionGUID="0f39991a-90d6-4774-b11e-32fe56891237" CreationDate="2015-09-19T00:23:24.103" UserId="197" Text="After looking into this for a while, I found out a couple of things:&#xD;&#xA;&#xD;&#xA; 1. **You cannot avoid a memcpy**: You cannot write directly into texture storage allocated for a compressed texture using only OpenGL API calls. This means that you cannot avoid the call to `glCompressedTexImage2D` with a bound PBO. That being said, you may be able to use a 16-bit RGBA texture and a &#xD;&#xA;&#xD;&#xA; 2. **You do need to synchronize memory**: In order to make sure that your compute shader finishes writing to your storage buffer, you must make sure that all reads and writes to it finish. This is done by calling `glMemoryBarrier` with `GL_SHADER_STORAGE_BARRIER_BIT`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The full code for something that writes into a buffer to be used as a compressed texture looks like this:&#xD;&#xA;&#xD;&#xA;    GLuint buffer;&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);&#xD;&#xA;    glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);&#xD;&#xA;&#xD;&#xA;    glUseProgram(compute_shader_prog);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, compute_shader_bind_point, buffer);&#xD;&#xA;    glDispatchCompute(wg_x, wg_y, wg_z);&#xD;&#xA;    glMemoryBarrier(GL_SHADER_STORAGE_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);&#xD;&#xA;    glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);" ContentLicense="CC BY-SA 3.0" />
  <row Id="2574" PostHistoryTypeId="5" PostId="1518" RevisionGUID="ba4aaaec-28b8-46af-a2bf-11b14b494689" CreationDate="2015-09-19T01:13:41.147" UserId="197" Comment="added 39 characters in body" Text="After looking into this for a while, I found out a couple of things:&#xD;&#xA;&#xD;&#xA; 1. **You cannot avoid a memcpy**: You cannot write directly into texture storage allocated for a compressed texture using only OpenGL API calls. This means that you cannot avoid the call to `glCompressedTexImage2D` with a bound PBO. That being said, you may be able to use a 16-bit RGBA texture and a GLSL image type in your compute shader.&#xD;&#xA;&#xD;&#xA; 2. **You do need to synchronize memory**: In order to make sure that your compute shader finishes writing to your storage buffer, you must make sure that all reads and writes to it finish. This is done by calling `glMemoryBarrier` with `GL_SHADER_STORAGE_BARRIER_BIT`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The full code for something that writes into a buffer to be used as a compressed texture looks like this:&#xD;&#xA;&#xD;&#xA;    GLuint buffer;&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);&#xD;&#xA;    glBufferStorage(GL_SHADER_STORAGE_BUFFER, tex_size_in_bytes, 0, 0);&#xD;&#xA;&#xD;&#xA;    glUseProgram(compute_shader_prog);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, compute_shader_bind_point, buffer);&#xD;&#xA;    glDispatchCompute(wg_x, wg_y, wg_z);&#xD;&#xA;    glMemoryBarrier(GL_SHADER_STORAGE_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);&#xD;&#xA;    glCompressedTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size_in_bytes, 0);" ContentLicense="CC BY-SA 3.0" />
  <row Id="2575" PostHistoryTypeId="2" PostId="1519" RevisionGUID="928f1d84-2b90-4b1c-9195-65761785007c" CreationDate="2015-09-21T04:47:42.927" UserId="523" Text="I was actually wondering about exactly this a few days ago.  Not finding any resources within the graphics community, I actually walked over to the Physics department at my university and *asked*.&#xD;&#xA;&#xD;&#xA;It turns out that there are a lot of lies we graphics people believe.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First, when light hits a surface, the Fresnel equations apply.  The proportions of reflected/refracted light depend on them.  You probably knew this.&#xD;&#xA;&#xD;&#xA;**There's no such thing as a &quot;specular color&quot;**&#xD;&#xA;&#xD;&#xA;What you might not have known is that the Fresnel equations vary based on wavelength, because the *refractive index* varies based on wavelength.  The variation is relatively small for dielectrics (dispersion, anyone?), but can be enormous for metals (I presume this has to do with these materials' differing electric structures).&#xD;&#xA;&#xD;&#xA;Therefore, the Fresnel reflection term varies by wavelength, and therefore *different wavelengths are reflected preferentially*.  Seen under broad-spectrum illumination, this is what leads to specular color.  But in particular, there is *no absorption* that magically happens at the surface (the other colors are just refracted).&#xD;&#xA;&#xD;&#xA;**There's no such thing as &quot;diffuse reflection&quot;**&#xD;&#xA;&#xD;&#xA;As Naty Hoffman says in the talk linked in the other answer, this is really an approximation to outscattered subsurface scattering.&#xD;&#xA;&#xD;&#xA;**Metals DO transmit light**&#xD;&#xA;&#xD;&#xA;Naty Hoffman is wrong (more precisely, simplifying).  Light does *not* get absorbed immediately by metals.  In fact, it will pass quite handily through materials several nanometers thick.  (For example, for gold, it takes 11.6633nm to attenuate 587.6nm light (yellow) by half.)&#xD;&#xA;&#xD;&#xA;Absorption, as in dielectrics, is due to the Beer-Lambert Law.  For metals, the absorption coefficient is just much larger (α=4πκ/λ, where κ is the imaginary component of the refractive index (for metals ~0.5 and up), and λ is given in *meters*).&#xD;&#xA;&#xD;&#xA;This transmission (or more accurately the SSS it produces) is actually responsible for a significant portion of metals' colors (although it is true that metals' appearances are dominated by their specular)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2577" PostHistoryTypeId="2" PostId="1521" RevisionGUID="04288934-e8f7-47fd-b229-a69199fe116f" CreationDate="2015-09-21T16:16:37.923" UserId="1692" Text="I encountered this problem doing my project. Suppose there is a 3D mesh model, e.g. a human face, I need the 3D visibility map at each of the vertices of this model. By the &quot;3D visibility map&quot;, I mean the binary image covering the spherical surface indicating whether the point is visible from each spherical angle(different from ambient occlusion). So, it is like a mask image. For example, the visibility map for any point on a convex surface is all ones (occlusion by other objects is ignored, only self-occlusion). See the following figure for illustration &#xD;&#xA;&#xD;&#xA;[![visibility map in two cases][1]][1]&#xD;&#xA;&#xD;&#xA;I want to know is there some efficient algorithms solving this problem? I need to apply it to all vertices. All I have in mind is doing brute force verification for all sampling directions. Any suggestions and links are welcome. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mekKc.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2578" PostHistoryTypeId="1" PostId="1521" RevisionGUID="04288934-e8f7-47fd-b229-a69199fe116f" CreationDate="2015-09-21T16:16:37.923" UserId="1692" Text="How can I get a spherical visibility mask map for a point on a concave surface?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2579" PostHistoryTypeId="3" PostId="1521" RevisionGUID="04288934-e8f7-47fd-b229-a69199fe116f" CreationDate="2015-09-21T16:16:37.923" UserId="1692" Text="|algorithm|lighting|occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2580" PostHistoryTypeId="5" PostId="1521" RevisionGUID="a6005ce5-191a-449b-9f17-07dce32a2340" CreationDate="2015-09-21T16:22:57.670" UserId="1692" Comment="added 10 characters in body" Text="I encountered this problem doing my project. Suppose there is a 3D mesh model, e.g. a human face, I need the 3D visibility map at each of the vertices of this model. By the &quot;3D visibility map&quot;, I mean the binary image covering the spherical surface indicating whether the point is visible from each spherical angle(different from ambient occlusion). So, it is like a mask image. For example, the visibility map for any point on a convex surface is all ones (occlusion by other objects is ignored, only self-occlusion). See the following figure for illustration &#xD;&#xA;&#xD;&#xA;[![spherical visibility map in two cases][1]][1]&#xD;&#xA;&#xD;&#xA;I want to know is there some efficient algorithms solving this problem? I need to apply it to all vertices. All I have in mind is doing brute force verification for all sampling directions. Any suggestions and links are welcome. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iPtZq.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2585" PostHistoryTypeId="2" PostId="1523" RevisionGUID="d1439ca2-c7bc-4455-a32f-96b5789f2f85" CreationDate="2015-09-21T20:41:30.860" UserId="137" Text="That it compresses the data compared to the pixel array is obvious.&#xD;&#xA;&#xD;&#xA;But what makes it different from from normal compression? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2586" PostHistoryTypeId="1" PostId="1523" RevisionGUID="d1439ca2-c7bc-4455-a32f-96b5789f2f85" CreationDate="2015-09-21T20:41:30.860" UserId="137" Text="How does hardware texture compression work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2587" PostHistoryTypeId="3" PostId="1523" RevisionGUID="d1439ca2-c7bc-4455-a32f-96b5789f2f85" CreationDate="2015-09-21T20:41:30.860" UserId="137" Text="|texture|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2588" PostHistoryTypeId="5" PostId="1523" RevisionGUID="f4dcdd0e-21ec-44ec-b105-651b1c91631e" CreationDate="2015-09-21T21:22:30.087" UserId="137" Comment="added 17 characters in body" Text="That it compresses the data compared to the pixel array is obvious.&#xD;&#xA;&#xD;&#xA;But what makes it different from from normal compression (like png, jpeg)? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2589" PostHistoryTypeId="5" PostId="1521" RevisionGUID="d8a83641-a42a-4d0f-8f03-00b88fe334a4" CreationDate="2015-09-22T01:52:57.000" UserId="1692" Comment="added 113 characters in body; edited tags" Text="I encountered this problem doing my project. Suppose there is a 3D mesh model, e.g. a human face, I need the 3D visibility map at each of the vertices of this model. By the &quot;3D visibility map&quot;, I mean the binary image covering the spherical surface indicating whether the point is visible from each spherical angle(different from ambient occlusion). So, it is like a mask image. For example, the visibility map for any point on a convex surface is all ones (occlusion by other objects is ignored, only self-occlusion). See the following figure for illustration &#xD;&#xA;&#xD;&#xA;[![spherical visibility map in two cases][1]][1]&#xD;&#xA;&#xD;&#xA;I want to know is there some efficient ways solving this problem? I need to apply it to all vertices. All I have in mind is doing brute force verification for all sampling directions. What's more, is there any existing software or tool (e.g. pbrt, Unity, Blender) that is capable of this functionality? Any suggestions and links are welcome. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iPtZq.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="2590" PostHistoryTypeId="6" PostId="1521" RevisionGUID="d8a83641-a42a-4d0f-8f03-00b88fe334a4" CreationDate="2015-09-22T01:52:57.000" UserId="1692" Comment="added 113 characters in body; edited tags" Text="|lighting|occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2592" PostHistoryTypeId="2" PostId="1524" RevisionGUID="69649b02-b3b1-4a33-ad29-1dd3614140ba" CreationDate="2015-09-22T09:04:58.360" UserId="1697" Text="I wrote a particle based fluid simulating program. It's hard to tell if I get the right result. The visualized result seems reasonable, but some part of it looks weird. I don't know wether it's a feature of fluid. Is there some accurate method to verify if my program is right?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2593" PostHistoryTypeId="1" PostId="1524" RevisionGUID="69649b02-b3b1-4a33-ad29-1dd3614140ba" CreationDate="2015-09-22T09:04:58.360" UserId="1697" Text="How could I check the correctness of my result of fluid simulation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2594" PostHistoryTypeId="3" PostId="1524" RevisionGUID="69649b02-b3b1-4a33-ad29-1dd3614140ba" CreationDate="2015-09-22T09:04:58.360" UserId="1697" Text="|physics|simulation|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2595" PostHistoryTypeId="5" PostId="1519" RevisionGUID="3c37e2b5-809a-41d5-a05e-2a25c95f5694" CreationDate="2015-09-22T09:51:46.387" UserId="231" Comment="Link acronym for anyone unfamiliar with it" Text="I was actually wondering about exactly this a few days ago.  Not finding any resources within the graphics community, I actually walked over to the Physics department at my university and *asked*.&#xD;&#xA;&#xD;&#xA;It turns out that there are a lot of lies we graphics people believe.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First, when light hits a surface, the Fresnel equations apply.  The proportions of reflected/refracted light depend on them.  You probably knew this.&#xD;&#xA;&#xD;&#xA;**There's no such thing as a &quot;specular color&quot;**&#xD;&#xA;&#xD;&#xA;What you might not have known is that the Fresnel equations vary based on wavelength, because the *refractive index* varies based on wavelength.  The variation is relatively small for dielectrics (dispersion, anyone?), but can be enormous for metals (I presume this has to do with these materials' differing electric structures).&#xD;&#xA;&#xD;&#xA;Therefore, the Fresnel reflection term varies by wavelength, and therefore *different wavelengths are reflected preferentially*.  Seen under broad-spectrum illumination, this is what leads to specular color.  But in particular, there is *no absorption* that magically happens at the surface (the other colors are just refracted).&#xD;&#xA;&#xD;&#xA;**There's no such thing as &quot;diffuse reflection&quot;**&#xD;&#xA;&#xD;&#xA;As Naty Hoffman says in the talk linked in the other answer, this is really an approximation to outscattered subsurface scattering.&#xD;&#xA;&#xD;&#xA;**Metals DO transmit light**&#xD;&#xA;&#xD;&#xA;Naty Hoffman is wrong (more precisely, simplifying).  Light does *not* get absorbed immediately by metals.  In fact, it will pass quite handily through materials several nanometers thick.  (For example, for gold, it takes 11.6633nm to attenuate 587.6nm light (yellow) by half.)&#xD;&#xA;&#xD;&#xA;Absorption, as in dielectrics, is due to the Beer-Lambert Law.  For metals, the absorption coefficient is just much larger (α=4πκ/λ, where κ is the imaginary component of the refractive index (for metals ~0.5 and up), and λ is given in *meters*).&#xD;&#xA;&#xD;&#xA;This transmission (or more accurately the [SSS] it produces) is actually responsible for a significant portion of metals' colors (although it is true that metals' appearances are dominated by their specular).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [SSS]: https://en.wikipedia.org/wiki/Subsurface_scattering &quot;Subsurface scattering&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2596" PostHistoryTypeId="2" PostId="1525" RevisionGUID="ee53fb77-c541-4cee-8c9b-0126263fc001" CreationDate="2015-09-22T11:30:06.133" UserId="1613" Text="Compare it with someone else's software. Run some standardized test and find out if you get roughly the same answer as others. If you get the same answer, than the probability of having your code right is quite high.&#xD;&#xA;&#xD;&#xA;Some tests:&#xD;&#xA;&#xD;&#xA;1. Flow past cylinder. In 2d take rectangular domain, cylinder in the middle, inflow on the left, outflow on the fight and calculate the force on the cylinder. Here is [benchmark][1] comparing handful of codes.&#xD;&#xA;&#xD;&#xA;2. Buoyancy flow. Closed box, hot plate on bottom, cold plate on top, hot fluid starts to rise due to the buoyancy force. Here is [benchmark][2].&#xD;&#xA;&#xD;&#xA;3. Rising bubble, [benchmark][3].&#xD;&#xA;&#xD;&#xA;But unfortunately it might be quite difficult to compare your code to scientific codes in those benchmarks. I guess you implemented something as SPH or stable fluids which are not made for accuracy but for stability. &#xD;&#xA;&#xD;&#xA;Take for example the flow past a cylinder. I would start the test with very small Reynolds number and then measure the force on cylinder as you increase accuracy of your simulation(lower time step, increase subdivision or increase number of particles). Does the force converges to some number? If no, than you have a problem, if yes, than have a look at the benchmark paper and compare your result with others.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA; &#xD;&#xA;This method is very similar technique to one I use for testing my raytracer. I just render test scene with someone else's renderer and compare it with my result. Do they converge to the same result? If yes than I have it right, if no, than I have it wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.karlin.mff.cuni.cz/~hron/NMMO403/dfg_benchmark_results.pdf&#xD;&#xA;  [2]: http://www.karlin.mff.cuni.cz/~hron/NMMO403/mit_bench.pdf&#xD;&#xA;  [3]: http://www.karlin.mff.cuni.cz/~hron/NMMO403/1934_ftp.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2597" PostHistoryTypeId="2" PostId="1526" RevisionGUID="170c5fa3-8613-4a4d-950d-d1482dd95147" CreationDate="2015-09-22T12:22:01.213" UserId="1699" Text="For a realistic Iris, you need:&#xD;&#xA;&#xD;&#xA;1. **Geometry**: Irides are very different for different people and their appearance changes drastically depending on whether the pupil is dilated (sphicter muscle relaxed) or not. You will not get anywhere with primitives only. The whole structure is like a thick stretchy wrinkly cloth suspended in water. Wrinkles appear and disappear as it moves. Use a sculpting software and an anatomy textbook.&#xD;&#xA;&#xD;&#xA;2. **Material**: There is almost no specular on the iris since it is suspended in (basically) water which has a similar refractive index as tissue. I do not know the roughness values since I have never seen a dry Iris. With the GGX specular model, roughness 0.4 looks okay. Brown irides seem to be more rough, almost like very fine sand. A shading model that uses roughness in the diffuse component would be nice.&#xD;&#xA;&#xD;&#xA;3. **Textures**: While some are colorful, the vast majority of irides in the world are brown. You don't need too much variation inside the texture, it can be quite uniform. Make it relatively saturated and don't try to hint at geometry inside the texture by drawing dark areas for shadows or occlusion. Have a normal map. If the eye is animated, you need to blend between at least two normal maps for the dilated and undilated pupil. I don't think you need a roughness map, but especially for blue irides it might help.&#xD;&#xA;&#xD;&#xA;4. **Refraction and reflection** at the cornea: The cornea (the fluid layer coating it) acts as a lens. This distorts the image of the iris as seen by the camera. Without this, it will not look real, especially when looking at the eye from the side. The unusual thing about the eye is that, from a graphics point of view, the object is *inside* the lens. So there's no thin lens equation going to come to your rescue. You have to refract light once, at the interface between the tear layer and air.&#xD;&#xA;The other interfaces (tear layer to outside of cornea, layers and membranes inside the cornea, inside of cornea to chamber fluid) are not relevant since the indices of refraction are all very similar or the structures are extremely thin. The only other optically important structure is the lens, which is behind the iris and can be ignored.&#xD;&#xA;The shape of the cornea is critical, as it will distort everything. People with cornea deformations such as a keratoconus have weird-looking eyes. Also the whole scene must reflect on the cornea/liquid. We expect to see reflections of light sources over the iris/pupil.&#xD;&#xA;&#xD;&#xA;5. The **limbus**: Looking frontally at the eye, there is a greyish ring around the Iris. This is the part where the cornea merges into the sclera (the &quot;white&quot; of the eye), transitioning from transparent to nontransparent. Behind the limbus, anatomically, is the iridocorneal angle, where the iris meets the rest of the eye. This area is impossible to see due to the refraction mentioned above, it is literally a place that has never seen any light. Light emitted from there experiences total internal refraction at the interface of the cornea, you can't look at it from the outside. Thus, it looks very very weird when the transition from iris to the rest of the eye is visible. You need both the refraction and the gradual transition from cornea to sclera to get this transition right.&#xD;&#xA;&#xD;&#xA;6. **Subsurface scattering**: You might possibly get away without it on the iris itself since there will never be light coming from the back, especially with a brown iris (more heavily pigmented -&gt; more attenuation during scattering). For some light directions, it will make a difference though. And you need it on the surrounding skin and sclera anyway. But it is not the most important effect.&#xD;&#xA;&#xD;&#xA;7. **Ambient occlusion**: You need good SSAO (or GI) to make the fine structure stand out. There's almost no specular, so you need other visual cues for the geometry. Choose a method that uses your normals from the normal map. HBAO will work well. For offline rendering, the GI will be done by your renderer of choice.&#xD;&#xA;&#xD;&#xA;8. **Lighting**: Using some physically based method goes without saying. Image based lighting, especially for the cornea reflection. Under certain angles, refraction of the light at the cornea may become relevant as well (only for analytic lights). Postprocessing (bloom), especially for the cornea reflex.&#xD;&#xA;&#xD;&#xA;Backscattered light from the retina, although it can be seen through the iris in very extreme viewing conditions during some medical examinations, is completely irrelevant for normal purposes. Basically, paint the retina black. If you want to go that far, you can add a little orange-red to the retina color whenever a strong light comes from a direction very very similar to the camera and the pupil is dilated (like a flash from a camera). But it will still not be strong enough to shine through the iris, by far. Black is an okay approximation.&#xD;&#xA;&#xD;&#xA;That list looks big, but you asked for photorealism ;) It will still look good if you only do the easy half and fake the rest.&#xD;&#xA;&#xD;&#xA;(Source: I do graphics programming for medical simulations with a focus on the human eye)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2598" PostHistoryTypeId="5" PostId="1524" RevisionGUID="bdef9236-ed48-44d5-af84-d142b1df1086" CreationDate="2015-09-22T14:29:58.353" UserId="1697" Comment="added 1329 characters in body" Text="I wrote a particle based fluid simulating program. It's hard to tell if I get the right result. The visualized result seems reasonable, but some part of it looks weird. I don't know wether it's a feature of fluid. Is there some accurate method to verify if my program is right?&#xD;&#xA;&#xD;&#xA;Amending some details：&#xD;&#xA;&#xD;&#xA;My program is a 2D particle-based simulating program. The fluid is compressible. The implementation is almost based on a classical paper:&#xD;&#xA;&#xD;&#xA;&gt; Müller, Matthias, David Charypar, and Markus Gross. &quot;Particle-based fluid simulation for interactive applications.&quot; Proceedings of the 2003 ACM SIGGRAPH&#xD;&#xA;&#xD;&#xA;I solved the Navier-Stokes equation with iteration method. It only considered pressure, gravity, viscosity and surface tension.&#xD;&#xA;&#xD;&#xA;&lt;a href=&quot;http://www.codecogs.com/eqnedit.php?latex=\rho&amp;space;(\frac{\mathbf{\partial&amp;space;v}}{\partial&amp;space;t}&amp;space;&amp;plus;&amp;space;\mathbf{v}&amp;space;\cdot&amp;space;\bigtriangledown&amp;space;\mathbf{v})&amp;space;=&amp;space;-\bigtriangledown&amp;space;p&amp;space;&amp;plus;&amp;space;\rho\mathbf{g}&amp;space;&amp;plus;&amp;space;\mu&amp;space;\bigtriangledown^2&amp;space;\mathbf{v}&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://latex.codecogs.com/gif.latex?\rho&amp;space;(\frac{\mathbf{\partial&amp;space;v}}{\partial&amp;space;t}&amp;space;&amp;plus;&amp;space;\mathbf{v}&amp;space;\cdot&amp;space;\bigtriangledown&amp;space;\mathbf{v})&amp;space;=&amp;space;-\bigtriangledown&amp;space;p&amp;space;&amp;plus;&amp;space;\rho\mathbf{g}&amp;space;&amp;plus;&amp;space;\mu&amp;space;\bigtriangledown^2&amp;space;\mathbf{v}&quot; title=&quot;\rho (\frac{\mathbf{\partial v}}{\partial t} + \mathbf{v} \cdot \bigtriangledown \mathbf{v}) = -\bigtriangledown p + \rho\mathbf{g} + \mu \bigtriangledown^2 \mathbf{v}&quot; /&gt;&lt;/a&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2599" PostHistoryTypeId="2" PostId="1527" RevisionGUID="73747c81-b422-423a-bce0-f9380cb859bb" CreationDate="2015-09-22T17:04:29.490" UserId="38" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pas rough projection circles center. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated. You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fbM8b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2600" PostHistoryTypeId="5" PostId="1527" RevisionGUID="a7e94a6c-2912-48e9-91fe-29e59c1d5fdc" CreationDate="2015-09-22T17:20:47.007" UserId="38" Comment="added 33 characters in body" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pass through projection circles center forming circles on the sphera. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated. You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fbM8b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2601" PostHistoryTypeId="5" PostId="1527" RevisionGUID="a28ab2fb-eb3d-4065-a058-73d4c247e798" CreationDate="2015-09-22T17:56:27.947" UserId="38" Comment="added 29 characters in body" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pass through projection circles center forming circles on the sphera. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated (if its on a open face edge). You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fbM8b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2602" PostHistoryTypeId="5" PostId="1527" RevisionGUID="dd1110a2-236b-42ab-bbda-cb6d6027d4c8" CreationDate="2015-09-22T18:08:33.543" UserId="38" Comment="added 135 characters in body" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pass through projection circles center forming circles on the sphera. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;![Project triangle on sphere][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated (if its on a open face edge). You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Local horizon map][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Horizon map of a simple all local geometry.&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fbM8b.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/kKID6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2603" PostHistoryTypeId="5" PostId="1527" RevisionGUID="019fb270-a574-4522-a548-0a833831f562" CreationDate="2015-09-22T18:57:43.897" UserId="38" Comment="updated images" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pass through projection circles center forming circles on the sphera. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;[![Project triangle on sphere][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated (if its on a open face edge). You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;[![Local horizon map][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Horizon map of a simple all local geometry.&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JZHaM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/j6qF1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2604" PostHistoryTypeId="2" PostId="1528" RevisionGUID="4e2aa766-0899-449f-a998-e17210be7d06" CreationDate="2015-09-22T22:09:32.430" UserDisplayName="user1703" Text="All conics (including rotated ellipses) can be described by an implicit equation of the form&#xD;&#xA;&#xD;&#xA;    H(x, y) = Ax² + B xy + C y² + D x + E y + F = 0&#xD;&#xA;&#xD;&#xA;The basic principle of the incremental line tracing algorithms (I wouldn't call them scanline) is to follow the pixels that fulfill the equation as much as possible.&#xD;&#xA;&#xD;&#xA;Depending on the local slope of the line, you progress more in the x or y direction, following either a lateral or diagonal move. This decision is made so that you minimize the absolute value of H(x, y).&#xD;&#xA;&#xD;&#xA;In the case of a straight line, the slope is a constant so that lateral and diagonal moves are always in the same direction.&#xD;&#xA;&#xD;&#xA;In the case of a circular arc, the slope varies and one can distinguish 8 cases corresponding to 8 octants of the curve (there are four possible lateral moves and for each two diagonal moves).&#xD;&#xA;&#xD;&#xA;For the ellipse and other conics, you can generalize the octant decomposition. This leads to a rather tedious discussion.&#xD;&#xA;&#xD;&#xA;You can avoid the octant discussion and modify the algorithm to look at all neighbors of the current pixel. This leads to a general contour tracing algorithm like [Moore's neighborhood][1], where you will follow the outline of the area `H(x, y) &gt;= 0`.&#xD;&#xA;&#xD;&#xA;Note that lines, circles and axis-aligned ellipses can be described by an implicit equation with integer coefficients. This is no more possible with general conics and you will need to resort to floating-point, or good rational approximations.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/moore.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2605" PostHistoryTypeId="2" PostId="1529" RevisionGUID="20915ffc-c33b-4b6d-84ce-fedba80c0922" CreationDate="2015-09-23T04:09:55.423" UserId="110" Text="I recently noticed that in some locations you could switch to a 3d mapping mode in Google Street View.  &#xD;&#xA;Which algorithm(s) did they use to generate the 3d models of the streets? I assume it was more than just capture, given the huge amount of data that would be necessary to produce an accurate representation of the streets." ContentLicense="CC BY-SA 3.0" />
  <row Id="2606" PostHistoryTypeId="1" PostId="1529" RevisionGUID="20915ffc-c33b-4b6d-84ce-fedba80c0922" CreationDate="2015-09-23T04:09:55.423" UserId="110" Text="What algorithm(s) are behind Google Street View's 3d mapping mode?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2607" PostHistoryTypeId="3" PostId="1529" RevisionGUID="20915ffc-c33b-4b6d-84ce-fedba80c0922" CreationDate="2015-09-23T04:09:55.423" UserId="110" Text="|algorithm|3d|mapping|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2608" PostHistoryTypeId="5" PostId="1528" RevisionGUID="d7f7a2ec-5575-420d-aadb-2379b370e2f8" CreationDate="2015-09-23T06:17:17.140" UserDisplayName="user1703" Comment="added 150 characters in body" Text="All conics (including rotated ellipses) can be described by an implicit equation of the form&#xD;&#xA;&#xD;&#xA;    H(x, y) = Ax² + B xy + C y² + D x + E y + F = 0&#xD;&#xA;&#xD;&#xA;The basic principle of the incremental line tracing algorithms (I wouldn't call them scanline) is to follow the pixels that fulfill the equation as much as possible.&#xD;&#xA;&#xD;&#xA;Depending on the local slope of the line, you progress more in the x or y direction, following either a lateral or diagonal move. This decision is made so that you minimize the absolute value of H(x, y).&#xD;&#xA;&#xD;&#xA;In the case of a straight line, the slope is a constant so that lateral and diagonal moves are always in the same direction.&#xD;&#xA;&#xD;&#xA;In the case of a circular arc, the slope varies and one can distinguish 8 cases corresponding to 8 octants of the curve (there are four possible lateral moves and for each two diagonal moves).&#xD;&#xA;&#xD;&#xA;For the ellipse and other conics, you can generalize the octant decomposition. This leads to a rather tedious discussion.&#xD;&#xA;&#xD;&#xA;You can avoid the octant discussion and modify the algorithm to look at all neighbors of the current pixel. This leads to a general contour tracing algorithm like [Moore's neighborhood][1], where you will follow the outline of the area `H(x, y) &gt;= 0`.&#xD;&#xA;&#xD;&#xA;Note that lines, circles and axis-aligned ellipses can be described by an implicit equation with integer coefficients. This is no more possible with general conics and you will need to resort to floating-point, or good rational approximations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Lastly, note that incremental computation saves work when evaluating H, on the line of&#xD;&#xA;&#xD;&#xA;    H(x+1, y) = H(x, y) + A(2x+1) + By + D&#xD;&#xA;&#xD;&#xA;  [1]: http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/moore.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2610" PostHistoryTypeId="5" PostId="1527" RevisionGUID="b2019729-e54c-4e3f-a13d-01db6b08928e" CreationDate="2015-09-23T08:41:41.847" UserId="38" Comment="edited body" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pass through projection circles center forming circles on the sphere. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;[![Project triangle on sphere][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated (if its on a open face edge). You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;[![Local horizon map][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Horizon map of a simple all local geometry.&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JZHaM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/j6qF1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2614" PostHistoryTypeId="5" PostId="1526" RevisionGUID="f6ecbdd0-2d55-42ce-b601-e00783b051cc" CreationDate="2015-09-23T13:51:07.393" UserId="1699" Comment="added links to material" Text="For a realistic Iris, you need:&#xD;&#xA;&#xD;&#xA;1. **Geometry**: Irides are very different for different people and their appearance changes drastically depending on whether the pupil is dilated (sphicter muscle relaxed) or not. You will not get anywhere with primitives only. The whole structure is like a thick stretchy wrinkly cloth suspended in water. Wrinkles appear and disappear as it moves. Use a sculpting software and an anatomy textbook.&#xD;&#xA;&#xD;&#xA;2. **Material**: There is almost no specular on the iris since it is suspended in (basically) water which has a similar refractive index as tissue. I do not know the roughness values since I have never seen a dry Iris. With the GGX specular model, roughness 0.4 looks okay. Brown irides seem to be more rough, almost like very fine sand. A shading model that uses roughness in the diffuse component would be nice.&#xD;&#xA;&#xD;&#xA;3. **Textures**: While some are colorful, the vast majority of irides in the world are brown. You don't need too much variation inside the texture, it can be quite uniform. Make it relatively saturated and don't try to hint at geometry inside the texture by drawing dark areas for shadows or occlusion. Have a normal map. If the eye is animated, you need to blend between at least two normal maps for the dilated and undilated pupil. I don't think you need a roughness map, but especially for blue irides it might help.&#xD;&#xA;&#xD;&#xA;4. **Refraction and reflection** at the cornea: The cornea (the fluid layer coating it) acts as a lens. This distorts the image of the iris as seen by the camera. Without this, it will not look real, especially when looking at the eye from the side. The unusual thing about the eye is that, from a graphics point of view, the object is *inside* the lens. So there's no thin lens equation going to come to your rescue. You have to refract light once, at the interface between the tear layer and air.&#xD;&#xA;The other interfaces (tear layer to outside of cornea, layers and membranes inside the cornea, inside of cornea to chamber fluid) are not relevant since the indices of refraction are all very similar or the structures are extremely thin. The only other optically important structure is the lens, which is behind the iris and can be ignored.&#xD;&#xA;The shape of the cornea is critical, as it will distort everything. People with cornea deformations such as a keratoconus have weird-looking eyes. Also the whole scene must reflect on the cornea/liquid. We expect to see reflections of light sources over the iris/pupil.&#xD;&#xA;&#xD;&#xA;5. The **limbus**: Looking frontally at the eye, there is a greyish ring around the Iris. This is the part where the cornea merges into the sclera (the &quot;white&quot; of the eye), transitioning from transparent to nontransparent. Behind the limbus, anatomically, is the iridocorneal angle, where the iris meets the rest of the eye. This area is impossible to see due to the refraction mentioned above, it is literally a place that has never seen any light. Light emitted from there experiences total internal refraction at the interface of the cornea, you can't look at it from the outside. Thus, it looks very very weird when the transition from iris to the rest of the eye is visible. You need both the refraction and the gradual transition from cornea to sclera to get this transition right.&#xD;&#xA;&#xD;&#xA;6. **Subsurface scattering**: You might possibly get away without it on the iris itself since there will never be light coming from the back, especially with a brown iris (more heavily pigmented -&gt; more attenuation during scattering). For some light directions, it will make a difference though. And you need it on the surrounding skin and sclera anyway. But it is not the most important effect.&#xD;&#xA;&#xD;&#xA;7. **Ambient occlusion**: You need good SSAO (or GI) to make the fine structure stand out. There's almost no specular, so you need other visual cues for the geometry. Choose a method that uses your normals from the normal map. HBAO will work well. For offline rendering, the GI will be done by your renderer of choice.&#xD;&#xA;&#xD;&#xA;8. **Lighting**: Using some physically based method goes without saying. Image based lighting, especially for the cornea reflection. Under certain angles, refraction of the light at the cornea may become relevant as well (only for analytic lights). Postprocessing (bloom), especially for the cornea reflex.&#xD;&#xA;&#xD;&#xA;Backscattered light from the retina, although it can be seen through the iris in very extreme viewing conditions during some medical examinations, is completely irrelevant for normal purposes. Basically, paint the retina black. If you want to go that far, you can add a little orange-red to the retina color whenever a strong light comes from a direction very very similar to the camera and the pupil is dilated (like a flash from a camera). But it will still not be strong enough to shine through the iris, by far. Black is an okay approximation.&#xD;&#xA;&#xD;&#xA;That list looks big, but you asked for photorealism ;) It will still look good if you only do the easy half and fake the rest.&#xD;&#xA;&#xD;&#xA;(Source: I do graphics programming for medical simulations with a focus on the human eye)&#xD;&#xA;&#xD;&#xA;Material:&#xD;&#xA;&#xD;&#xA; - [Anatomically accurate modeling and rendering of the human eye][1] (2007)&#xD;&#xA; - [High-Quality Capture of Eyes][2] (Disney Research, Siggraph Asia 2014)&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/inria-00166304/&#xD;&#xA;  [2]: http://www.disneyresearch.com/publication/high-quality-capture-of-eyes/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2615" PostHistoryTypeId="5" PostId="1527" RevisionGUID="7bbf50b8-6390-40b3-accf-e95d66a39348" CreationDate="2015-09-23T15:57:04.210" UserId="38" Comment="added 649 characters in body" Text="This can be done analytically at least for polygonal meshes. You can convert points into polar coordinates and project on a sphere. Edges form planes that pass through projection circles center forming circles on the sphere. These lines are all great circles, because they must pass sphere center. Great circles form linear interpolations in polar coordinates.&#xD;&#xA;&#xD;&#xA;[![Project triangle on sphere][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Projecting a geometry on a sphere.&#xD;&#xA;&#xD;&#xA;Converting these great circles into either Cartesian coordinates is quite well known math. Projecting them onto 2d representation by Mercator projection is well known math on account fo this being central to map making. Since overlap is not a  problem you can just slap these triangles on top of each other and merge the vector results. Or use the polar coordinates for pixel graphics and even use z buffered overlap just like a normal camera.&#xD;&#xA;&#xD;&#xA;The only problematic point is the one where your sphere is generated (if its on a open face edge). You can simply project the point on center into its inverse normal direction on the projection sphere. Or if for example Mercator projection is desired, you can align the sphere with surface normal. then just project them to a point on the south pole.&#xD;&#xA;&#xD;&#xA;You can even interpolate the results of individual polygons positions to get any point on the triangle. And a analytic surface coverage for the triangle.&#xD;&#xA;&#xD;&#xA;I haven't implemented this, but Ive done it manually a few times\* so i know its possible. Should be pretty easy to do as the maths involved aren't all that complicated only problem is solving which side of the problem to keep.&#xD;&#xA;&#xD;&#xA;[![Local horizon map][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Horizon map of a simple all local geometry.&#xD;&#xA;&#xD;&#xA;### Comparison with raytracing&#xD;&#xA;&#xD;&#xA;Both sampling triangles analytically is O(N) algorithm, if vector data is sufficient. Conditioning this data may push you over to O(N^2). Raytracing is O(N log(N)). Raytracing algorithms are easier to find of the shelf so implementing analytic polygon to sphere rendering is harder. In terms of speed analytical rendering is faster as long as theres a limited number of triangles, much like how scanline rendering is still sometimes faster than tracing despite being algorithmically more complex. This similarity is not just a coincidence it can be shown that this method can be turned into a scanline renderer.&#xD;&#xA;&#xD;&#xA;### Resources for drawing great circles in Mercator projection:&#xD;&#xA;&#xD;&#xA;* [Wolfram demonstration](http://demonstrations.wolfram.com/GreatCirclesOnMercatorsChart/) on subject.&#xD;&#xA;&#xD;&#xA;* [The Projection of Circles on a Mercator Map](http://adsabs.harvard.edu/full/1932JRASC..26..161G)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* About 20-25 times. I also did it for this image (yes in 3d), its as accurate as a single span Bezier curve can represent a circle. Ive also done this in map making software a few times.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JZHaM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/j6qF1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2616" PostHistoryTypeId="5" PostId="1526" RevisionGUID="01d13eff-aa2f-41e8-aa89-9db03f6a8c32" CreationDate="2015-09-23T16:24:11.350" UserId="231" Comment="Add links and hover text to acronyms" Text="For a realistic Iris, you need:&#xD;&#xA;&#xD;&#xA;1. **Geometry**: Irides are very different for different people and their appearance changes drastically depending on whether the pupil is dilated (sphicter muscle relaxed) or not. You will not get anywhere with primitives only. The whole structure is like a thick stretchy wrinkly cloth suspended in water. Wrinkles appear and disappear as it moves. Use a sculpting software and an anatomy textbook.&#xD;&#xA;&#xD;&#xA;2. **Material**: There is almost no specular on the iris since it is suspended in (basically) water which has a similar refractive index as tissue. I do not know the roughness values since I have never seen a dry Iris. With the [GGX specular model], roughness 0.4 looks okay. Brown irides seem to be more rough, almost like very fine sand. A shading model that uses roughness in the diffuse component would be nice.&#xD;&#xA;&#xD;&#xA;3. **Textures**: While some are colorful, the vast majority of irides in the world are brown. You don't need too much variation inside the texture, it can be quite uniform. Make it relatively saturated and don't try to hint at geometry inside the texture by drawing dark areas for shadows or occlusion. Have a normal map. If the eye is animated, you need to blend between at least two normal maps for the dilated and undilated pupil. I don't think you need a roughness map, but especially for blue irides it might help.&#xD;&#xA;&#xD;&#xA;4. **Refraction and reflection** at the cornea: The cornea (the fluid layer coating it) acts as a lens. This distorts the image of the iris as seen by the camera. Without this, it will not look real, especially when looking at the eye from the side. The unusual thing about the eye is that, from a graphics point of view, the object is *inside* the lens. So there's no thin lens equation going to come to your rescue. You have to refract light once, at the interface between the tear layer and air.&#xD;&#xA;The other interfaces (tear layer to outside of cornea, layers and membranes inside the cornea, inside of cornea to chamber fluid) are not relevant since the indices of refraction are all very similar or the structures are extremely thin. The only other optically important structure is the lens, which is behind the iris and can be ignored.&#xD;&#xA;The shape of the cornea is critical, as it will distort everything. People with cornea deformations such as a keratoconus have weird-looking eyes. Also the whole scene must reflect on the cornea/liquid. We expect to see reflections of light sources over the iris/pupil.&#xD;&#xA;&#xD;&#xA;5. The **limbus**: Looking frontally at the eye, there is a greyish ring around the Iris. This is the part where the cornea merges into the sclera (the &quot;white&quot; of the eye), transitioning from transparent to nontransparent. Behind the limbus, anatomically, is the iridocorneal angle, where the iris meets the rest of the eye. This area is impossible to see due to the refraction mentioned above, it is literally a place that has never seen any light. Light emitted from there experiences total internal refraction at the interface of the cornea, you can't look at it from the outside. Thus, it looks very very weird when the transition from iris to the rest of the eye is visible. You need both the refraction and the gradual transition from cornea to sclera to get this transition right.&#xD;&#xA;&#xD;&#xA;6. **Subsurface scattering**: You might possibly get away without it on the iris itself since there will never be light coming from the back, especially with a brown iris (more heavily pigmented -&gt; more attenuation during scattering). For some light directions, it will make a difference though. And you need it on the surrounding skin and sclera anyway. But it is not the most important effect.&#xD;&#xA;&#xD;&#xA;7. **Ambient occlusion**: You need good [SSAO] (or [GI]) to make the fine structure stand out. There's almost no specular, so you need other visual cues for the geometry. Choose a method that uses your normals from the normal map. [HBAO] will work well. For offline rendering, the GI will be done by your renderer of choice.&#xD;&#xA;&#xD;&#xA;8. **Lighting**: Using some physically based method goes without saying. Image based lighting, especially for the cornea reflection. Under certain angles, refraction of the light at the cornea may become relevant as well (only for analytic lights). Postprocessing (bloom), especially for the cornea reflex.&#xD;&#xA;&#xD;&#xA;Backscattered light from the retina, although it can be seen through the iris in very extreme viewing conditions during some medical examinations, is completely irrelevant for normal purposes. Basically, paint the retina black. If you want to go that far, you can add a little orange-red to the retina color whenever a strong light comes from a direction very very similar to the camera and the pupil is dilated (like a flash from a camera). But it will still not be strong enough to shine through the iris, by far. Black is an okay approximation.&#xD;&#xA;&#xD;&#xA;That list looks big, but you asked for photorealism ;) It will still look good if you only do the easy half and fake the rest.&#xD;&#xA;&#xD;&#xA;(Source: I do graphics programming for medical simulations with a focus on the human eye)&#xD;&#xA;&#xD;&#xA;Material:&#xD;&#xA;&#xD;&#xA; - [Anatomically accurate modeling and rendering of the human eye][1] (2007)&#xD;&#xA; - [High-Quality Capture of Eyes][2] (Disney Research, Siggraph Asia 2014)&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/inria-00166304/&#xD;&#xA;  [2]: http://www.disneyresearch.com/publication/high-quality-capture-of-eyes/&#xD;&#xA;&#xD;&#xA;  [GGX specular model]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf &quot;Microfacet Models for Refraction through Rough Surfaces (2007)&quot;&#xD;&#xA;&#xD;&#xA;  [SSAO]: https://en.wikipedia.org/wiki/Screen_space_ambient_occlusion &quot;Screen Space Ambient Occlusion&quot;&#xD;&#xA;&#xD;&#xA;  [GI]: https://en.wikipedia.org/wiki/Global_illumination &quot;Global Illumination&quot;&#xD;&#xA;&#xD;&#xA;  [HBAO]: http://www.twistedsanity.org/rdimitrov/HBAO_SIGGRAPH08.pdf &quot;Image-Space Horizon-Based Ambient Occlusion&quot;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2617" PostHistoryTypeId="2" PostId="1531" RevisionGUID="7d502da4-0f2b-42dc-bace-76cf2df79fd6" CreationDate="2015-09-23T16:46:18.353" UserId="1705" Text="I'm working on an assignment and I need to draw using only GL_POINTS. I realize this is an expensive approach but it's for the homework, so no GL_TRIANGLES / GL_POLYGON / GL_LINES etc.&#xD;&#xA;&#xD;&#xA;First, I'm trying to understand the concept of using only points. Say I want to draw a square that's 100 x 100 pixels. Would I need four for-loops drawing 100 pixels each in straight lines to create the square? What if I want to fill the square with color?&#xD;&#xA;&#xD;&#xA;I understand drawing a square using GL_POLYGON as that's fairly straight forward. We're using the GLUT library just to draw shapes with points." ContentLicense="CC BY-SA 3.0" />
  <row Id="2618" PostHistoryTypeId="1" PostId="1531" RevisionGUID="7d502da4-0f2b-42dc-bace-76cf2df79fd6" CreationDate="2015-09-23T16:46:18.353" UserId="1705" Text="GLUT OpenGL - Drawing Shapes using only GL_POINTS" ContentLicense="CC BY-SA 3.0" />
  <row Id="2619" PostHistoryTypeId="3" PostId="1531" RevisionGUID="7d502da4-0f2b-42dc-bace-76cf2df79fd6" CreationDate="2015-09-23T16:46:18.353" UserId="1705" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2623" PostHistoryTypeId="2" PostId="1533" RevisionGUID="24d3a0f9-dc13-4e0b-9bf3-c006c94d52b7" CreationDate="2015-09-23T20:49:14.113" UserId="523" Text="Quickly Googling produces:&#xD;&#xA;&#xD;&#xA;1. [This related question](http://stackoverflow.com/questions/4148831/how-to-offset-a-cubic-bezier-curve) on StackOverflow&#xD;&#xA;2. &quot;Computing offsets of NURBS curves and surfaces&quot; (paper)&#xD;&#xA;3. Discussions of 2.&#xD;&#xA;&#xD;&#xA;To summarize them:&#xD;&#xA;&#xD;&#xA;1. Suggests that this is impossible to do exactly.&#xD;&#xA;2. Gives an algorithm to compute an offset curve approximately (though to within a tiny epsilon).  If you can't access the paper, then:&#xD;&#xA;3. Look at any of these.  [This presentation](https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=7&amp;cad=rja&amp;uact=8&amp;ved=0CDwQFjAGahUKEwiihLzeg47IAhVHN4gKHfsmCaM&amp;url=http%3A%2F%2Fwww.math.zju.edu.cn%2Fcagd%2FSeminar%2F2005_AutumnWinter%2F2005_Master_LH.ppt&amp;usg=AFQjCNGlb556TMftSL8d4xU7kT1x7Q9G7Q&amp;sig2=9rYaCjpqD-VMKu94ke5O7w) for example seems to cover it." ContentLicense="CC BY-SA 3.0" />
  <row Id="2628" PostHistoryTypeId="2" PostId="1535" RevisionGUID="5c63f321-85ac-40a6-a688-4e0a5943a12a" CreationDate="2015-09-24T10:41:59.760" UserId="385" Text="[Spherical Harmonics][1] (SH) are a way to represent low-frequency spherical functions with only a handful of coefficients. They have some nice mathematical properties, e.g. a convolution with a kernel function *h(x)* (that has circular symmetry) can be calculated as&#xD;&#xA;&#xD;&#xA;[![(h * f)^m_l = \sqrt{\frac{4\pi}{2l+1}} h^0_l f^m_l][2]][2]&#xD;&#xA;&#xD;&#xA;In the case of a [convolution with a cosine lobe][3] for rank 3 SH this results in a simple scaling of the bands with the factors&#xD;&#xA;&#xD;&#xA;[![[\pi, \frac{2\pi}{3}, \frac{\pi}{4}]][4]][4]&#xD;&#xA;&#xD;&#xA;In many cases, e.g. incident light for a given point on an opaque surface, full spherical information is not needed, since half of the sphere is zero / undefined / unused anyway. Thus, [Hemispherical Harmonics][5] (HSH) were born.&#xD;&#xA;&#xD;&#xA;How does convolution with an arbitrary kernel (with circular symmetry) work for HSH? Can the convolution from SH be extended or is there any paper that goes into details on this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.ppsloan.org/publications/StupidSH36.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/oh3mt.gif&#xD;&#xA;  [3]: https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/&#xD;&#xA;  [4]: https://i.stack.imgur.com/tIf94.gif&#xD;&#xA;  [5]: http://www.cs.ucf.edu/~ceh/Publications/Papers/Rendering/EGSR04GautronEtAl.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2629" PostHistoryTypeId="1" PostId="1535" RevisionGUID="5c63f321-85ac-40a6-a688-4e0a5943a12a" CreationDate="2015-09-24T10:41:59.760" UserId="385" Text="Convolution of Hemispherical Harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="2630" PostHistoryTypeId="3" PostId="1535" RevisionGUID="5c63f321-85ac-40a6-a688-4e0a5943a12a" CreationDate="2015-09-24T10:41:59.760" UserId="385" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2632" PostHistoryTypeId="2" PostId="1536" RevisionGUID="7c896b7c-8c70-4eae-b651-3f49604dda25" CreationDate="2015-09-25T00:13:21.510" UserDisplayName="user464" Text="Why are Homogeneous Coordinates used in Computer Graphics?&#xD;&#xA;&#xD;&#xA;What would be the problem if Homogeneous Coordinates were not used in matrix transformations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2633" PostHistoryTypeId="1" PostId="1536" RevisionGUID="7c896b7c-8c70-4eae-b651-3f49604dda25" CreationDate="2015-09-25T00:13:21.510" UserDisplayName="user464" Text="Why are Homogeneous Coordinates used in Computer Graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2634" PostHistoryTypeId="3" PostId="1536" RevisionGUID="7c896b7c-8c70-4eae-b651-3f49604dda25" CreationDate="2015-09-25T00:13:21.510" UserDisplayName="user464" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2635" PostHistoryTypeId="2" PostId="1537" RevisionGUID="c1bc3b6e-79ee-4dc3-9725-0b3d49c507a6" CreationDate="2015-09-25T01:49:44.247" UserId="192" Text="They simplify and unify the mathematics used in graphics:&#xD;&#xA;&#xD;&#xA;- They allow you to represent translations with matrices.&#xD;&#xA;&#xD;&#xA;- They allow you to represent the division by depth in perspective projections.&#xD;&#xA;&#xD;&#xA;The first one is related to affine geometry.&#xD;&#xA;The second one is related to projective geometry.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2636" PostHistoryTypeId="2" PostId="1538" RevisionGUID="1451bf13-23f5-41e6-aeea-6c7795399470" CreationDate="2015-09-25T03:16:41.270" UserId="110" Text="For normalization purposes, how to &quot;extract&quot; a BRDF function from an ad-hoc piece of pixel shading code ?  &#xD;&#xA;  &#xD;&#xA;If we have a shader function like:&#xD;&#xA;&#xD;&#xA;    float4 MyShadingFunction(float3 incomingLightDirection, float incomingRadiance)&#xD;&#xA;    {&#xD;&#xA;        float4 lightContributionToPixelColor;&#xD;&#xA;&#xD;&#xA;        // ...&#xD;&#xA;        // several complicated formulas (to which we have access)&#xD;&#xA;        // ...&#xD;&#xA;    &#xD;&#xA;        return lightContributionToPixelColor;&#xD;&#xA;    }&#xD;&#xA; &#xD;&#xA;What is the procedure to translate the &quot;complicated formulas&quot; into a BRDF function f that can then be mathematically integrated ?  &#xD;&#xA;&#xD;&#xA;*For example to use f in an expression such as:*  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/InSPM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2637" PostHistoryTypeId="1" PostId="1538" RevisionGUID="1451bf13-23f5-41e6-aeea-6c7795399470" CreationDate="2015-09-25T03:16:41.270" UserId="110" Text="How to extract a BRDF from a shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="2638" PostHistoryTypeId="3" PostId="1538" RevisionGUID="1451bf13-23f5-41e6-aeea-6c7795399470" CreationDate="2015-09-25T03:16:41.270" UserId="110" Text="|shader|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2639" PostHistoryTypeId="2" PostId="1539" RevisionGUID="522352ed-2bee-438b-8593-8f271e6a0b22" CreationDate="2015-09-25T04:08:40.117" UserDisplayName="user1713" Text="Calculations in affine coordinates often require divisions, which are expensive as compared to additions or multiplications. One usually does not need to divide when using projective coordinates.&#xD;&#xA;&#xD;&#xA;Using projective coordinates (and more generally, projective geometry) tends to eliminate special cases too, making everything simpler and more uniform." ContentLicense="CC BY-SA 3.0" />
  <row Id="2640" PostHistoryTypeId="2" PostId="1540" RevisionGUID="fa2396a3-df65-4ae3-93bd-1739714192e3" CreationDate="2015-09-25T07:03:11.327" UserDisplayName="user1703" Text="As a personal taste I have always abstained (when possible) from using homogeneous coordinates and preferred the plain Cartesian formulation.&#xD;&#xA;&#xD;&#xA;Main reason is the fact that homogeneous coordinates uses 4 trivial entries in the transformation matrices (0, 0, 0, 1), involving useless storage and computation.&#xD;&#xA;&#xD;&#xA;The downside is that you need more care when writing the equations and lose support of matrix theory, but so far I have survived." ContentLicense="CC BY-SA 3.0" />
  <row Id="2641" PostHistoryTypeId="5" PostId="1540" RevisionGUID="cef3146d-13fb-4a0c-982b-462d7e36c04c" CreationDate="2015-09-25T07:09:26.657" UserDisplayName="user1703" Comment="added 105 characters in body" Text="As a personal taste I have always abstained (when possible) from using homogeneous coordinates and preferred the plain Cartesian formulation.&#xD;&#xA;&#xD;&#xA;Main reason is the fact that homogeneous coordinates uses 4 trivial entries in the transformation matrices (0, 0, 0, 1), involving useless storage and computation (also the overhead of general-purpose matrix computation routines which are &quot;by default&quot; used in this case).&#xD;&#xA;&#xD;&#xA;The downside is that you need more care when writing the equations and lose support of matrix theory, but so far I have survived." ContentLicense="CC BY-SA 3.0" />
  <row Id="2642" PostHistoryTypeId="2" PostId="1541" RevisionGUID="39d42d1b-c571-4c75-b322-04a80c92f693" CreationDate="2015-09-25T08:28:40.463" UserId="1714" Text="It's in the name: Homogeneous coordinates are well ... homogeneous.&#xD;&#xA;Being homogeneous means a uniform representation of rotation, translation, scaling and other transformations.&#xD;&#xA;&#xD;&#xA;A uniform representation allows for optimizations. 3D graphics hardware can be specialized to perform matrix multiplications on 4x4 matrices. It can even be specialized to recognize and save on multiplications by 0 or 1, because those are often used.&#xD;&#xA;&#xD;&#xA;Not using homogeneous coordinates may make it hard to use strongly optimized hardware to its fullest. Whatever program recognizes that optimized instructions of the hardware can be used (typically a compiler but things are more complicated sometimes) for homogeneous coordinates will have a hard time with optimizing for other representations. It will choose less optimized instructions and thus not use the potential of the hardware.&#xD;&#xA;&#xD;&#xA;As there were calls for examples:&#xD;&#xA;Sony's PS4 can perform massive matrix multiplications. It's so good at it that it was sold out for some time, because clusters of them were used instead of more expensive super-computers. Sony subsequently demanded that their hardware may not be used for military purposes. Yes, super-computers are military equipment.&#xD;&#xA;&#xD;&#xA;It has become quite usual for researchers to use graphic cards to calculate their matrix multiplications even if no graphic is involved. Simply because they are magnitudes better in it than general purpose CPUs.&#xD;&#xA;For comparison modern multi-core CPUs have on the order of 16 pipelines (x0.5 or x2 doesn't matter so much) while GPUs have on the order of 1024 pipelines.&#xD;&#xA;&#xD;&#xA;It's not so much the cores than the pipelines that allow for actual parallel processing. Cores work on threads. Threads have to be programmed explicitly. Pipelines work on instruction level. The chip can parallelize instructions more or less on its own." ContentLicense="CC BY-SA 3.0" />
  <row Id="2646" PostHistoryTypeId="2" PostId="1542" RevisionGUID="4702fc39-0074-4b38-ac7e-caf9be2d6ed3" CreationDate="2015-09-26T04:38:14.037" UserId="1723" Text="Forgive me in advance for my ignorance.&#xD;&#xA;&#xD;&#xA;Using the PHP function imagecolorat, I have a solution that presently delivers a set of the most dominant hex color codes available inside of an image.&#xD;&#xA;&#xD;&#xA;Is there a known library that will allow me to then take the hex color code, RGB code (or any other standard color code) and simplify them down, or rather &quot;match&quot; them to a limited set of &quot;common colors&quot;, such as red, brown, green, yellow, grey, blue, etc?&#xD;&#xA;&#xD;&#xA;For example, #944D70, which is a shade of purple, would be matched to the color 'purple'.&#xD;&#xA;&#xD;&#xA;**Alternatively:**&#xD;&#xA;&#xD;&#xA;Is there a particular pattern or range to RGB colors that would allow me to write such a library myself?&#xD;&#xA;&#xD;&#xA;For example, 0,0,0 thru 20,20,20 might all be considered a &quot;black&quot; color. However, it seems as if organizing such a library would be very exhausting if done manually.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2647" PostHistoryTypeId="1" PostId="1542" RevisionGUID="4702fc39-0074-4b38-ac7e-caf9be2d6ed3" CreationDate="2015-09-26T04:38:14.037" UserId="1723" Text="Convert RGB, Hex or any other color format to &quot;Standard Color&quot; Programmatically" ContentLicense="CC BY-SA 3.0" />
  <row Id="2648" PostHistoryTypeId="3" PostId="1542" RevisionGUID="4702fc39-0074-4b38-ac7e-caf9be2d6ed3" CreationDate="2015-09-26T04:38:14.037" UserId="1723" Text="|conversion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2649" PostHistoryTypeId="2" PostId="1543" RevisionGUID="be6b2d16-cdd5-43d3-9ef0-9a2a2801e275" CreationDate="2015-09-26T09:19:28.477" UserId="38" Text="Problem is that people do not really agree on a 1:1 mapping of color names. But yes such tools exists, this is a simple nearest neighborhood test. You could use any spatial query module to do this. Here is a simple (naive) python example: &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-py --&gt;&#xD;&#xA;&#xD;&#xA;    from __future__ import print_function&#xD;&#xA;    import webcolors&#xD;&#xA;    from scipy.spatial import KDTree&#xD;&#xA;    &#xD;&#xA;    # lets populate some names into spatial name database&#xD;&#xA;    hexnames = webcolors.css3_hex_to_names&#xD;&#xA;    names = []&#xD;&#xA;    positions = []&#xD;&#xA;    &#xD;&#xA;    for hex, name in hexnames.iteritems():&#xD;&#xA;        names.append(name)&#xD;&#xA;        positions.append(webcolors.hex_to_rgb(hex))&#xD;&#xA;    &#xD;&#xA;    spacedb = KDTree(positions)&#xD;&#xA;    &#xD;&#xA;    # query nearest point&#xD;&#xA;    querycolor = (10,88, 200)&#xD;&#xA;    dist, index = spacedb.query(querycolor)&#xD;&#xA;    &#xD;&#xA;    print('The color %r is closest to %s.'%(querycolor, names[index]))&#xD;&#xA;&#xD;&#xA;Which results in: `The color (10, 88, 200) is closest to royalblue.`" ContentLicense="CC BY-SA 3.0" />
  <row Id="2650" PostHistoryTypeId="5" PostId="1543" RevisionGUID="74ee3467-05c1-4b08-aa8f-0056beca3853" CreationDate="2015-09-26T09:27:16.427" UserId="38" Comment="added 104 characters in body" Text="Problem is that people do not really agree on a 1:1 mapping of color names. But yes such tools exists, this is a simple nearest neighborhood test. You could use any spatial query module to do this. Here is a simple (naive) python example: &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-py --&gt;&#xD;&#xA;&#xD;&#xA;    from __future__ import print_function&#xD;&#xA;    import webcolors&#xD;&#xA;    from scipy.spatial import KDTree&#xD;&#xA;    &#xD;&#xA;    # lets populate some names into spatial name database&#xD;&#xA;    hexnames = webcolors.css3_hex_to_names&#xD;&#xA;    names = []&#xD;&#xA;    positions = []&#xD;&#xA;    &#xD;&#xA;    for hex, name in hexnames.iteritems():&#xD;&#xA;        names.append(name)&#xD;&#xA;        positions.append(webcolors.hex_to_rgb(hex))&#xD;&#xA;    &#xD;&#xA;    spacedb = KDTree(positions)&#xD;&#xA;    &#xD;&#xA;    # query nearest point&#xD;&#xA;    querycolor = (10,88, 200)&#xD;&#xA;    dist, index = spacedb.query(querycolor)&#xD;&#xA;    &#xD;&#xA;    print('The color %r is closest to %s.'%(querycolor, names[index]))&#xD;&#xA;&#xD;&#xA;Which results in: `The color (10, 88, 200) is closest to royalblue.`&#xD;&#xA;&#xD;&#xA;I'm using here the 140 css3 defined colors. Bigger and more comprehensive lists can be found online." ContentLicense="CC BY-SA 3.0" />
  <row Id="2651" PostHistoryTypeId="5" PostId="1543" RevisionGUID="1ec2881c-4025-4cd9-beb2-f614deb187f0" CreationDate="2015-09-26T09:36:03.800" UserId="38" Comment="added 217 characters in body" Text="Problem is that people do not really agree on a 1:1 mapping of color names. But yes such tools exists, this is a simple nearest neighborhood test. You could use any spatial query module to do this. Here is a simple (naive) python example: &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-py --&gt;&#xD;&#xA;&#xD;&#xA;    from __future__ import print_function&#xD;&#xA;    import webcolors&#xD;&#xA;    from scipy.spatial import KDTree&#xD;&#xA;    &#xD;&#xA;    # lets populate some names into spatial name database&#xD;&#xA;    hexnames = webcolors.css3_hex_to_names&#xD;&#xA;    names = []&#xD;&#xA;    positions = []&#xD;&#xA;    &#xD;&#xA;    for hex, name in hexnames.iteritems():&#xD;&#xA;        names.append(name)&#xD;&#xA;        positions.append(webcolors.hex_to_rgb(hex))&#xD;&#xA;    &#xD;&#xA;    spacedb = KDTree(positions)&#xD;&#xA;    &#xD;&#xA;    # query nearest point&#xD;&#xA;    querycolor = (10,88, 200)&#xD;&#xA;    dist, index = spacedb.query(querycolor)&#xD;&#xA;    &#xD;&#xA;    print('The color %r is closest to %s.'%(querycolor, names[index]))&#xD;&#xA;&#xD;&#xA;Which results in: `The color (10, 88, 200) is closest to royalblue.`&#xD;&#xA;&#xD;&#xA;I'm using here the 140 css3 defined colors. Bigger and more comprehensive lists can be found online. Theres all kinds of possible things you could do, you could for example linearize the sRGB space before calculating distances to name. You could ask for 3 closest names and give double names if the names are halfway." ContentLicense="CC BY-SA 3.0" />
  <row Id="2652" PostHistoryTypeId="5" PostId="1543" RevisionGUID="38bef95e-7448-4eec-843a-6895400eb126" CreationDate="2015-09-26T09:49:36.913" UserId="38" Comment="added 49 characters in body" Text="Problem is that people do not really agree on a 1:1 mapping of color names. But yes such tools exists, this is a simple nearest neighborhood test. You could use any spatial query module to do this. Here is a simple (naive) python example: &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-py --&gt;&#xD;&#xA;&#xD;&#xA;    from __future__ import print_function&#xD;&#xA;    import webcolors&#xD;&#xA;    from scipy.spatial import KDTree&#xD;&#xA;    &#xD;&#xA;    # lets populate some names into spatial name database&#xD;&#xA;    hexnames = webcolors.css3_hex_to_names&#xD;&#xA;    names = []&#xD;&#xA;    positions = []&#xD;&#xA;    &#xD;&#xA;    for hex, name in hexnames.iteritems():&#xD;&#xA;        names.append(name)&#xD;&#xA;        positions.append(webcolors.hex_to_rgb(hex))&#xD;&#xA;    &#xD;&#xA;    spacedb = KDTree(positions)&#xD;&#xA;    &#xD;&#xA;    # query nearest point&#xD;&#xA;    querycolor = (10,88, 200)&#xD;&#xA;    dist, index = spacedb.query(querycolor)&#xD;&#xA;    &#xD;&#xA;    print('The color %r is closest to %s.'%(querycolor, names[index]))&#xD;&#xA;&#xD;&#xA;Which results in: `The color (10, 88, 200) is closest to royalblue.`&#xD;&#xA;&#xD;&#xA;I'm using here the 140 css3 defined colors. Bigger and more comprehensive lists can be found [online](https://en.wikipedia.org/wiki/Lists_of_colors). Theres all kinds of possible things you could do, you could for example linearize the sRGB space before calculating distances to name. You could ask for 3 closest names and give double names if the names are halfway." ContentLicense="CC BY-SA 3.0" />
  <row Id="2653" PostHistoryTypeId="5" PostId="1543" RevisionGUID="8122af48-f35f-4131-8286-1d1d98e691c4" CreationDate="2015-09-26T14:34:19.023" UserId="38" Comment="added 48 characters in body" Text="Problem is that people do not really agree on a 1:1 mapping of color names. But yes such tools exists, this is a simple nearest neighborhood test. You could use any spatial query module to do this. Here is a simple (naive) python example: &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-py --&gt;&#xD;&#xA;&#xD;&#xA;    from __future__ import print_function&#xD;&#xA;    import webcolors&#xD;&#xA;    from scipy.spatial import KDTree&#xD;&#xA;    &#xD;&#xA;    # lets populate some names into spatial name database&#xD;&#xA;    hexnames = webcolors.css3_hex_to_names&#xD;&#xA;    names = []&#xD;&#xA;    positions = []&#xD;&#xA;    &#xD;&#xA;    for hex, name in hexnames.iteritems():&#xD;&#xA;        names.append(name)&#xD;&#xA;        positions.append(webcolors.hex_to_rgb(hex))&#xD;&#xA;    &#xD;&#xA;    spacedb = KDTree(positions)&#xD;&#xA;    &#xD;&#xA;    # query nearest point&#xD;&#xA;    querycolor = (10,88, 200)&#xD;&#xA;    dist, index = spacedb.query(querycolor)&#xD;&#xA;    &#xD;&#xA;    print('The color %r is closest to %s.'%(querycolor, names[index]))&#xD;&#xA;&#xD;&#xA;Which results in: `The color (10, 88, 200) is closest to royalblue.`&#xD;&#xA;&#xD;&#xA;I'm using here the 140 css3 defined colors. Bigger and more comprehensive lists can be found [online](https://en.wikipedia.org/wiki/Lists_of_colors), if you want a smallerlist that would also work. Theres all kinds of possible things you could do, you could for example linearize the sRGB space before calculating distances to name. You could ask for 3 closest names and give double names if the names are halfway." ContentLicense="CC BY-SA 3.0" />
  <row Id="2654" PostHistoryTypeId="5" PostId="1496" RevisionGUID="81eeb12a-37d8-4903-a589-5ce7f93b784f" CreationDate="2015-09-26T21:37:14.117" UserId="231" Comment="Add missing word" Text="Back in the day when you often had to write your own low level rendering algorithms we all used to learn the Bresenham algorithms for lines and circles.&#xD;&#xA;&#xD;&#xA;It was almost trivially easy to extend the Bresenham circle algorithm to cover ellipses whose axes were parallel to the X and Y axes.&#xD;&#xA;&#xD;&#xA;But it always eluded me if there was some Bresenham-style way to render an arbitrary ellipse whose axes were at some arbitrary angle.&#xD;&#xA;&#xD;&#xA;Does such a scanline method for rotated ellipses exist?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2658" PostHistoryTypeId="2" PostId="1545" RevisionGUID="8f99d8f5-e10f-495c-a390-8c2878e71e15" CreationDate="2015-09-27T02:32:20.067" UserId="48" Text="As Simon's comment alluded to, one major difference between hardware texture compression and other commonly used image compression is that the former does not use entropy coding. Entropy coding is the use of shorter bit-strings to represent commonly-occurring or repeating patterns in the source data&amp;mdash;as seen in container formats like ZIP, many common image formats such as GIF, JPEG, and PNG, and also in many common audio and video formats.&#xD;&#xA;&#xD;&#xA;Entropy coding is good at compressing all sorts of data, but it intrinsically produces a variable compression ratio. Some areas of the image may have little detail (or the detail is predicted well by the coding model you're using) and require very few bits, but other areas may have complex detail that requires more bits to encode. This makes it difficult to implement random access, as there is no straightforward way to calculate where in the compressed data you can find the pixel at given (_x_,&amp;nbsp;_y_) coordinates. Also, most entropy coding schemes are stateful, so it's not possible to simply start decoding at an arbitrary place in the stream; you have to start from the beginning to build up the correct state. However, random access is necessary for texture sampling, since a shader may sample from any location in a texture at any time.&#xD;&#xA;&#xD;&#xA;So, rather than entropy coding, hardware compression uses fixed-ratio, block-based schemes.  For example, in [DXT / BCn compression](http://www.reedbeta.com/blog/2012/02/12/understanding-bcn-texture-compression-formats/), the texture is sliced up into 4&amp;times;4 pixel blocks, each of which is encoded in either 64 or 128 bits (depending on which format is picked); in [ASTC](https://en.wikipedia.org/wiki/Adaptive_Scalable_Texture_Compression), different formats use block sizes from 4&amp;times;4 up to 12&amp;times;12, and all blocks are encoded in 128 bits. The details of how the bits represent the image data vary between formats (and may even vary from one block to the next within the same image), but because the ratio is fixed, it's easy for hardware to calculate where in memory to find the block containing a given (_x_, _y_) pixel, and each block is self-contained, so it can be decoded independently of any other blocks.&#xD;&#xA;&#xD;&#xA;Another consideration in hardware texture compression is that the decoding should be efficiently implementable in hardware. This means that heavy math operations and complex dataflow are strongly disfavored. The BCn formats, for instance, can be decoded by doing a handful of 8-bit integer math operations per block to populate a small lookup table, then just looking up the appropriate table entry per pixel.  This requires very little area on-chip, which is important because you probably want to decode several blocks in parallel, and thus need several copies of the decode hardware.&#xD;&#xA;&#xD;&#xA;In contrast, DCT-based formats like JPEG require a nontrivial amount of math per pixel, not to mention a complex dataflow that swaps and broadcasts various intermediate values across pixels within a block. (Look at [this article](https://fgiesen.wordpress.com/2013/11/04/bink-2-2-integer-dct-design-part-1/) for some of the gory details of DCT decoding.) This would be a lot grosser for hardware implementation, which I'm guessing is why AFAICT, no GPU hardware has ever implemented DCT-based or wavelet-based texture compression." ContentLicense="CC BY-SA 3.0" />
  <row Id="2659" PostHistoryTypeId="2" PostId="1546" RevisionGUID="6e808c0b-9c63-418a-bff5-0d6093334738" CreationDate="2015-09-27T05:14:24.863" UserId="1735" Text="Suppose we have a 64-bit word-addressable computer and we want to program it to output a 5x7 character stored as a binary image bitmap (such as the one below) to a memory-mapped display.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Since we have 5 x 7 = 35 pixels per character, we could store a character using 35 bits in a single word. With the least significant bit starting on the left side of the word and with each pixel in the image being represented by the *n*th bit as shown above, the number &quot;3&quot; above would be stored in memory as: 01110100010000100110000011000101110, followed by 29 unused bits set to 0.&#xD;&#xA;&#xD;&#xA;Is this how characters were/are stored in old/modern computers? Or do they use a single byte/word per pixel instead?&#xD;&#xA;&#xD;&#xA;If they are stored in this manner, what would the routine in assembly/machine-code (using nothing more than elementary instructions such as bitwise, arithmetic and data transport operations from the computer's Instruction Set Architecture) used to convert this data into an image on the display look like? Would it be something like:&#xD;&#xA;&#xD;&#xA;1. Store the x and y display coordinate for the current pixel to be updated in a certain register.&#xD;&#xA;2. Store the two chosen RGB values (in this case 0,255,0 for green and 0,0,0 for black) in two other separate registers.&#xD;&#xA;3. Have two further registers act as counters initialized to 5 and 7 to keep track of the current row and column of the image being rendered.&#xD;&#xA;4. Test if the column register is not 0. If it isn't, test if the LSB of the bitmap is set to 1, then AND the respective RGB value register with the x and y coordinate register depending on the result, then MOV that result to the display output register.&#xD;&#xA;5. Decrement the row counter register by 1, test to see if it is 0. If it is, then set it back to 5 and increment the y coordinate by 1 and decrement the column counter by 1.&#xD;&#xA;6. Shift the register holding the bitmap 1 bit to the left.&#xD;&#xA;7. JMP to instruction 4.&#xD;&#xA;&#xD;&#xA;Is there a simpler or more efficient way to do this? It seems as though even something as simple as rendering a single small text character takes quite a large number of operations and would take around 200 CPU cycles.&#xD;&#xA;&#xD;&#xA;Finally, are there any good books or resources on machine-level code for displaying images from scratch, because I haven't been able to find any as they either gloss over this particular subject or the code is written in a high level language or an assembler using macros, all of which are &quot;cheating&quot; and don't explain what is fundamentally going on at the lowest level.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LfHfE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jaPjM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2660" PostHistoryTypeId="1" PostId="1546" RevisionGUID="6e808c0b-9c63-418a-bff5-0d6093334738" CreationDate="2015-09-27T05:14:24.863" UserId="1735" Text="Fundamentally, how are 2D bitmaps rendered?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2661" PostHistoryTypeId="3" PostId="1546" RevisionGUID="6e808c0b-9c63-418a-bff5-0d6093334738" CreationDate="2015-09-27T05:14:24.863" UserId="1735" Text="|rendering|2d|bitmap-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2663" PostHistoryTypeId="2" PostId="1547" RevisionGUID="f0d14e43-a5db-48c4-be3d-9f9c31def1a1" CreationDate="2015-09-27T19:22:57.333" UserDisplayName="user1703" Text="You have to distinguish the text and graphical modes of the graphics board of your machine.&#xD;&#xA;&#xD;&#xA;In the old days, mostly the text mode was supported. In this mode the board took care of storing the bitmap definition of the characters and displaying them at the current cursor position. All you had to do was to provide the ASCII code of the character (one byte per character) in a small text buffer.&#xD;&#xA;&#xD;&#xA;Nowadays, a high-resolution raster buffer is provided, which is pixel accessible and to which you write color information in some supported format (in the &quot;highest&quot; mode, 3 bytes (RGB) per pixel, for a megapixel or more).&#xD;&#xA;&#xD;&#xA;Originally, simple (packed) binary bitmaps of different sizes were used and &quot;[blittted][1]&quot; to the raster memory via a request to the device driver, with possible format translation.&#xD;&#xA;&#xD;&#xA;Nowadays, characters are mostly defined as [vector drawings][2], which are a resolution-independent description of the outlines, and need to undergo a complex rendering process that includes [antialising][3] for smooth results.&#xD;&#xA;&#xD;&#xA;The rendered output can be cached for fast display, again by blitting.&#xD;&#xA;&#xD;&#xA;The overall process is complex, can be hardware accelerated, and handled by the operating system (GUI management) in a transparent way, together with other graphical primitive drawing operations.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bit_blit&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Vector_graphics&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Spatial_anti-aliasing" ContentLicense="CC BY-SA 3.0" />
  <row Id="2664" PostHistoryTypeId="5" PostId="1547" RevisionGUID="59cc6f79-06fa-4f47-bd19-1e2cf52b434d" CreationDate="2015-09-27T20:29:01.950" UserDisplayName="user1703" Comment="added 1 character in body" Text="You have to distinguish the text and graphical modes of the graphics board of your machine.&#xD;&#xA;&#xD;&#xA;In the old days, mostly the text mode was supported. In this mode the board took care of storing the bitmap definition of the characters and displaying them at the current cursor position. All you had to do was to provide the ASCII code of the character (one byte per character) in a small text buffer.&#xD;&#xA;&#xD;&#xA;Nowadays, a high-resolution raster buffer is provided, which is pixel accessible and to which you write color information in some supported format (in the &quot;highest&quot; mode, 3 bytes (RGB) per pixel, for a megapixel or more).&#xD;&#xA;&#xD;&#xA;Originally, simple (packed) binary bitmaps of different sizes were used and &quot;[blittted][1]&quot; to the raster memory via a request to the device driver, with possible format translation.&#xD;&#xA;&#xD;&#xA;Nowadays, characters are mostly defined as [vector drawings][2], which are a resolution-independent description of the outlines, and need to undergo a complex rendering process that includes [antialiasing][3] for smooth results.&#xD;&#xA;&#xD;&#xA;The rendered output can be cached for fast display, again by blitting.&#xD;&#xA;&#xD;&#xA;The overall process is complex, can be hardware accelerated, and is handled by the operating system (GUI management) in a transparent way, together with other graphical primitive drawing operations.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bit_blit&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Vector_graphics&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Spatial_anti-aliasing" ContentLicense="CC BY-SA 3.0" />
  <row Id="2666" PostHistoryTypeId="5" PostId="1464" RevisionGUID="95726bda-af91-4064-ad4b-526ef3feb648" CreationDate="2015-09-28T10:31:28.150" UserId="209" Comment="Reduced word repetition." Text="lhf's answer is good from the perspective of tessellation, but these can occur with simpler triangle mesh use cases.&#xD;&#xA;&#xD;&#xA;Take this trivial example of three, *screen-space* triangles, ABC, ADE and DBE...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;Although point E was, mathematically, intended to be exactly on the line segment AB, the pipeline won't be using fully precise values, such as rational numbers (e.g. https://gmplib.org/). Instead, it will likely be using floats, and so some approximation/error will be introduced. The result is probably going to be something like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that *all* of the vertices may have inaccuracies. Although the example above shows a crack, the T-junction may instead result in overlap along the edge causing pixels to be drawn twice. This might not seem as bad, but it can cause problems with transparency or stencil operations.&#xD;&#xA;&#xD;&#xA;You *might* then think that with floating-point the error introduced will be insignificant, but in a renderer, the screen-space vertex (X,Y) values *are nearly always represented by fixed-point numbers* and so the displacement from the ideal location will usually be much greater. Further, as the rendering hardware &quot;interpolates&quot; the line segment pixel-by-pixel with its own internal precision, there is even more chance it will diverge from the rounded location of E.&#xD;&#xA;&#xD;&#xA;If the T-junction is &quot;removed&quot; by, say, also dividing triangle ABC into two, i.e. AEC and EBC, the problem will go away as the shifts introduced by the errors will all be consistent.&#xD;&#xA;&#xD;&#xA;Now, you might ask why do renderers (especially HW) use fixed-point maths for the vertex XY coordinates? Why don't they use floating-point in order to reduce the problem? Although some did (e.g. Sega's Dreamcast) it can lead to another problem where the triangle set-up maths becomes catastrophically inaccurate, particularly for long-thin triangles, and they change size in unpleasant ways.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sFxmG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QYZw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2670" PostHistoryTypeId="2" PostId="1548" RevisionGUID="1a173bfe-3c93-4bec-93b0-4416586c3838" CreationDate="2015-09-28T22:41:47.203" UserId="528" Text="This answer tries to give a short overview over some important aspects. Since the HSH definition is rather complex and I couldn't find an overview over some pre-evaluated functions, I didn't provide examples simply because it would take me too much time right now.&#xD;&#xA;&#xD;&#xA;Problem Description &amp; Brute Force&#xD;&#xA;-------------------&#xD;&#xA;&#xD;&#xA;To determine the convolution any with any set of basis function and thus computing the coefficients we generally need to compute the integral over the domain (= sphere for SH, hemisphere for HSH). Everything we need to do, to represent the hemispherical function *f*, which is defined over the angles *theta* (&quot;up/down&quot;) and *phi* (&quot;left/right&quot;), via a coefficient *c* for HSH basis functions *H* is the following:&#xD;&#xA;&#xD;&#xA;[![\int_0^{2\pi}\int_0^{\frac{2}{\pi}} f(\theta,\phi) \cdot H_l^m(\theta,\phi) \cdot sin(\theta) \,\, \mathrm{d}\theta\mathrm{d}\phi][2]][2]&#xD;&#xA;&#xD;&#xA;The *sin(theta)* is there because we integrate over the surface of a (hemi-)sphere. Conceptually, the size of a piece of area that comes from changing *phi* is bigger or smaller on the current theta. More on this [here][3]&#xD;&#xA;&#xD;&#xA;If we don't care too much about accuracy or computing time we can solve this simply by sampling: Generate equally distributed (!) directions on the hemisphere, compute the product of f and H and average the outcomes (if you have truly equally distributed points you don't need the *sin(theta)*).&#xD;&#xA;&#xD;&#xA;Get Started with an Analytical Solution&#xD;&#xA;----------------------------------------&#xD;&#xA;&#xD;&#xA;Of course we would love to have an analytical solution for our function, but this is where things can get very difficult. As a first step we may need to convert a function that is given on Cartesian directions into spherical coordinates. This part is still easy, just replace all your x, y and z as following:&#xD;&#xA;&#xD;&#xA;[![(x,y,z) \rightarrow (\sin\theta \cos\phi, \sin\theta \sin\phi, \cos\theta)][4]][4]&#xD;&#xA;&#xD;&#xA;Note that this gives us a system where the z-axis is the &quot;up&quot; of the hemisphere (theta=0) which should be represented by the HSH. After that it may already be possible to insert everything into a computer algebra system and solve the equation. Do not try to solve for all *m* &amp; *l* but rather try one coefficient at a time, since it is unlikely that there is a compact expression that describes all of them at once. The definition of HSH is relatively complex, which makes it very tedious to evaluate these functions. In [this paper][5] the zero and 1st order HSH basis functions are mentioned in cartesian coordinates.&#xD;&#xA;&#xD;&#xA;Notes on Rotations &amp; Zonal Harmonics&#xD;&#xA;------------------------&#xD;&#xA;&#xD;&#xA;Functions that are rotational symmetric around this z-axis are very good candidates for a successful analytic derivation, since they only affect the *zonal* coefficients, which are all coefficients with index *m* equals zero. This is especially helpful for the more general Spherical Harmonics where an easy formula exists that allows to rotate any Zonal Spherical Harmonics representation to an arbitrary direction, resulting in a Spherical Harmonics representation without any data loss (see [here][6]). This means that you can derive ZSH coefficients by assuming that your radial symmetric &quot;function points to z&quot; and rotate it then it into any desired direction. This works perfectly for example with various cosine lobe variations and also gives you the factors you mentioned in the question.&#xD;&#xA;&#xD;&#xA;Now the bad news: For HSH, any rotation of a function around another axis than z is lossy, since your function will &quot;touch&quot; the lower undefined hemisphere after the rotation. Therefore, there is also no convenient &quot;Hemi Zonal to HSH&quot; rotation formula. Instead, there are multiple ways to do it with different drawbacks. For more details see the [paper][7] and the [presentation][8].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;By the way: All this is easier with the [H-Basis][1], which is hemispherical as well (but originally only defined for a limited number of frequency-bands).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cg.tuwien.ac.at/research/publications/2010/Habel-2010-EIN/&#xD;&#xA;  [2]: https://i.stack.imgur.com/gkb7K.gif&#xD;&#xA;  [3]: http://tutorial.math.lamar.edu/Classes/CalcIII/TISphericalCoords.aspx&#xD;&#xA;  [4]: https://i.stack.imgur.com/m0jJv.gif&#xD;&#xA;  [5]: http://www.researchgate.net/publication/221121831_On_the_use_of_hemispherical_harmonics_for_modeling_images_of_objects_under_unknown_distant_illumination&#xD;&#xA;  [6]: http://simonstechblog.blogspot.de/2011/12/spherical-harmonic-lighting.html&#xD;&#xA;  [7]: http://www.cs.ucf.edu/~ceh/Publications/Papers/Rendering/EGSR04GautronEtAl.pdf&#xD;&#xA;  [8]: https://www.google.de/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=2&amp;ved=0CDEQFjABahUKEwj6joP13ZrIAhVFVxQKHQliBik&amp;url=http%3A%2F%2Fcgg.mff.cuni.cz%2F~jaroslav%2Fpapers%2Fegsr2004%2Fgautron-egsr2004-hemispherical.ppt&amp;usg=AFQjCNG7U0b1JYorPpGQ3qTkr8C4AOqDpg&amp;sig2=yHEuWgzlvroc65C7wxD2uA&amp;cad=rja" ContentLicense="CC BY-SA 3.0" />
  <row Id="2674" PostHistoryTypeId="2" PostId="1550" RevisionGUID="61728373-df85-41f3-84bf-c6f59404a3ca" CreationDate="2015-09-29T07:42:29.213" UserId="1752" Text="I reckon your instructor is encouraging you to implement low-level rendering algorithms.&#xD;&#xA;&#xD;&#xA;The obstacle to draw shapes using just points is the contradiction between continuous and discrete. Shapes are logically continuous if in its area every pixel is shaded. But you can not draw an actually continuous line using discrete points because infinite points are needed. If you draw points directly in the &quot;world&quot;, you can not guarantee every pixel on the screen can be covered after projection, unless you set the interval small enough(which may be of quite low performance).&#xD;&#xA;&#xD;&#xA;My advice is to maintain the world coordinates of the vertices of the shape but not draw it. Get the &quot;projected&quot; coordinates on screen and fill the area later using [DDA][1] or some other interpolation algorithms. &quot;Projected&quot; is the coordinates obtained by the three matrices(Projection, View, Model), I think you've heard of these. So in the filling process GLUT is used to draw points on the 2D screen, and cover every pixel in the area.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Digital_differential_analyzer_%28graphics_algorithm%29" ContentLicense="CC BY-SA 3.0" />
  <row Id="2675" PostHistoryTypeId="2" PostId="1551" RevisionGUID="f70354db-368a-4c06-99aa-b658ebccf45d" CreationDate="2015-09-29T13:36:53.633" UserId="209" Text="**[NOTE: Unfinished ... just saving as a work in progress...]**&#xD;&#xA;&#xD;&#xA;*&quot;How does (hardware) texture compression work&quot;* &#xD;&#xA;&#xD;&#xA;Goodness, this is a big topic. Hopefully I can provide some insights without duplicating the content of Nathan's answer.&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/).&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't (easily) predict which texels will be required during a render. If the texels come from, say, the middle of the image, you also don't want to have to decode all of the 'previous' lines of texture in order to work out what those texels are! (With JPEG and PNG this might be necessary).  (Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample &quot;willy-nilly&quot;](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419) )&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (...but I will admit that compression of PVRTC, ETC2 and some others at max-quality could be faster!)&#xD;&#xA;&#xD;&#xA;## Earlier History ##&#xD;&#xA;It may surprise you to learn that texture compression has been around for perhaps over three decades. Flight simulators from the 80s needed access to relatively large amounts of texture data and, in the days where even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) would set you back the price of large house, compressing textures was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or, cough, patents) you can find references to techniques including  &#xD;&#xA; a) crude form of texture synthesis, &#xD;&#xA; b) using a single channel (e.g. 4bpp) multiplied by a fixed RGB value, &#xD;&#xA; c) YUV, and &#xD;&#xA; d) palettes (even suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;Of course early game consoles, and PC games such as Descent, often used palette images, a form of Vector Quantisation (VQ), to reduce texture data costs. Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2 or even and 2x4 blocks with single codes.&#xD;&#xA;&#xD;&#xA;## More Modern Approaches ##&#xD;&#xA;The problem with VQ approaches is that &#xD;&#xA;&#xD;&#xA;[SAVING as a work in progress...]&#xD;&#xA;&#xD;&#xA;*FWIW I've been considering doing a talk at work on Texture Compression. If that goes ahead I may add some of that material here*" ContentLicense="CC BY-SA 3.0" />
  <row Id="2676" PostHistoryTypeId="5" PostId="1528" RevisionGUID="d7dd88be-e200-42c1-8714-fd2326f4e832" CreationDate="2015-09-29T14:52:45.510" UserDisplayName="user1703" Comment="added 2 characters in body" Text="All conics (including rotated ellipses) can be described by an implicit equation of the form&#xD;&#xA;&#xD;&#xA;    H(x, y) = Ax² + B xy + C y² + D x + E y + F = 0&#xD;&#xA;&#xD;&#xA;The basic principle of the incremental line tracing algorithms (I wouldn't call them scanline) is to follow the pixels that fulfill the equation as much as possible.&#xD;&#xA;&#xD;&#xA;Depending on the local slope of the line, you progress more in the x or y direction, following either a lateral or diagonal move. This decision is made so that you minimize the absolute value of H(x, y).&#xD;&#xA;&#xD;&#xA;In the case of a straight line, the slope is a constant so that lateral and diagonal moves are always in the same direction.&#xD;&#xA;&#xD;&#xA;In the case of a circular arc, the slope varies and one can distinguish 8 cases corresponding to 8 octants of the curve (there are four possible lateral moves and for each two diagonal moves).&#xD;&#xA;&#xD;&#xA;For the ellipse and other conics, you can generalize the octant decomposition. This leads to a rather tedious discussion.&#xD;&#xA;&#xD;&#xA;You can avoid the octant discussion and modify the algorithm to look at all neighbors of the current pixel. This leads to a general contour tracing algorithm like [Moore's neighborhood][1], where you will follow the outline of the area `H(x, y) &gt;= 0`.&#xD;&#xA;&#xD;&#xA;Note that lines, circles and axis-aligned ellipses can be described by an implicit equation with integer coefficients. This is no more possible with general conics and you will need to resort to floating-point, or good rational approximations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Lastly, note that incremental computation saves work when evaluating H, on the line of&#xD;&#xA;&#xD;&#xA;    H(x+1, y) = H(x, y) + A.(2x+1) + B.y + D = H(x, y) + (2A).x + (A + B.y + D)&#xD;&#xA;&#xD;&#xA;  [1]: http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/moore.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2677" PostHistoryTypeId="5" PostId="1528" RevisionGUID="4f5da142-052e-4930-9d86-8a27dee1ce72" CreationDate="2015-09-29T15:00:23.567" UserDisplayName="user1703" Comment="added 2 characters in body" Text="All conics (including rotated ellipses) can be described by an implicit equation of the form&#xD;&#xA;&#xD;&#xA;    H(x, y) = A x² + B xy + C y² + D x + E y + F = 0&#xD;&#xA;&#xD;&#xA;The basic principle of the incremental line tracing algorithms (I wouldn't call them scanline) is to follow the pixels that fulfill the equation as much as possible.&#xD;&#xA;&#xD;&#xA;Depending on the local slope of the line, you progress more in the x or y direction, following either a lateral or diagonal move. This decision is made so that you minimize the absolute value of H(x, y).&#xD;&#xA;&#xD;&#xA;In the case of a straight line, the slope is a constant so that lateral and diagonal moves are always in the same direction.&#xD;&#xA;&#xD;&#xA;In the case of a circular arc, the slope varies and one can distinguish 8 cases corresponding to 8 octants of the curve (there are four possible lateral moves and for each two diagonal moves).&#xD;&#xA;&#xD;&#xA;For the ellipse and other conics, you can generalize the octant decomposition. This leads to a rather tedious discussion.&#xD;&#xA;&#xD;&#xA;You can avoid the octant discussion and modify the algorithm to look at all neighbors of the current pixel. This leads to a general contour tracing algorithm like [Moore's neighborhood][1], where you will follow the outline of the area `H(x, y) &gt;= 0`.&#xD;&#xA;&#xD;&#xA;Note that lines, circles and axis-aligned ellipses can be described by an implicit equation with integer coefficients. This is no more possible with general conics and you will need to resort to floating-point, or good rational approximations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Lastly, note that incremental computation saves work when evaluating H, on the line of&#xD;&#xA;&#xD;&#xA;    H(x+1, y) = H(x, y) + A.(2x+1) + B.y + D = H(x, y) + (2A).x + (A + B.y + D)&#xD;&#xA;&#xD;&#xA;  [1]: http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/moore.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;A true scanline solution is also possible. Let `y` vary incrementally, and solve the `H` equation for `x`:&#xD;&#xA;&#xD;&#xA;    H(x, y) = A x² + (B y + D) x + (C y² + E y + F) = 0&#xD;&#xA;&#xD;&#xA;This will yield two `x` values for each `y`. The resulting curve will be much less pleasant as it will always count two pixels per row, which will leave holes when the slope is below `1`. You can cope by filling the stretch of pixels between the roots on the successive rows." ContentLicense="CC BY-SA 3.0" />
  <row Id="2678" PostHistoryTypeId="5" PostId="1551" RevisionGUID="45b5f553-a0f0-4e78-bbe7-257071dd935c" CreationDate="2015-09-29T15:03:57.740" UserId="209" Comment="Additional link, slight format change" Text="**[NOTE: Unfinished ... just saving as a work in progress...]**&#xD;&#xA;&#xD;&#xA;## *&quot;How does (hardware) texture compression work&quot;* ##&#xD;&#xA;&#xD;&#xA;Goodness, this is a big topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/).&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should thus also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware (and power) costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't (easily) predict which texels will be required during a given render. If some subset of the texels come from, say, the middle of the image, you also don't want to have to decode all of the 'previous' lines of texture in order to work out what those texels are; with JPEG and PNG this might be necessary.  (Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample &quot;willy-nilly&quot;](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419) )&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (...but I will admit that compression of PVRTC, ETC2 and some others at max-quality could be faster!)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days where even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, compressing textures was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or, cough, patents) you can find references to techniques including  &#xD;&#xA; a) simple forms of mathematical/procedural texture synthesis, &#xD;&#xA; b) use a single channel texture (e.g. 4bpp) which is then multiplied by a fixed RGB value, &#xD;&#xA; c) YUV, and &#xD;&#xA; d) palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;Of course, early game consoles and PC games such as Descent, often used palette images, a form of Vector Quantisation (VQ), to reduce texture data costs. Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2 or even and 2x4 blocks with single bytes.&#xD;&#xA;&#xD;&#xA;## More Modern Approaches ##&#xD;&#xA;Even though VQ schemes can achieve satisfactory quality with ~2bpp,   The problem with VQ approaches is that &#xD;&#xA;&#xD;&#xA;[SAVING as a work in progress...]&#xD;&#xA;&#xD;&#xA;*FWIW I've been considering doing a talk at work on Texture Compression. If that goes ahead I may add some of that material here*" ContentLicense="CC BY-SA 3.0" />
  <row Id="2679" PostHistoryTypeId="2" PostId="1552" RevisionGUID="1a752be1-a40c-4ace-95c0-85df6ac54ad9" CreationDate="2015-09-30T05:40:15.270" UserId="1695" Text="*[I got a warning that the question will be closed].*&#xD;&#xA;&#xD;&#xA;I have identified that CG is the place where all the advanced algorithms and computations are taking place. &#xD;&#xA;&#xD;&#xA;What is the best way to start from rudimentary and progress gradually in CG programming?&#xD;&#xA;&#xD;&#xA;Please express language choices (C, C++, etc.) and other topics you find relevant. I also found out  [Michael Abrash's book](www.jagregory.com/abrash-black-book/)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2680" PostHistoryTypeId="1" PostId="1552" RevisionGUID="1a752be1-a40c-4ace-95c0-85df6ac54ad9" CreationDate="2015-09-30T05:40:15.270" UserId="1695" Text="What are the best ways to start graphics programming?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2681" PostHistoryTypeId="3" PostId="1552" RevisionGUID="1a752be1-a40c-4ace-95c0-85df6ac54ad9" CreationDate="2015-09-30T05:40:15.270" UserId="1695" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2682" PostHistoryTypeId="2" PostId="1553" RevisionGUID="71fb65af-0d87-4914-adfd-f4a636c32f2b" CreationDate="2015-09-30T07:17:01.497" UserId="67" Text="There are many possible answers depending on your OS, goals and wanted level of abstraction. For low-level programming you can start by learning OpenGL, Metal or Direct3D. Most used shader languages are HLSL based. For higher level there are things like ShaderToy and engines like Unity (C#) or Unreal (C++) where you can experiment with graphics coding." ContentLicense="CC BY-SA 3.0" />
  <row Id="2683" PostHistoryTypeId="10" PostId="1538" RevisionGUID="15d87d1c-7a04-4c8f-8416-d4d47d988a5d" CreationDate="2015-09-30T07:48:52.413" UserId="-1" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:385,&quot;DisplayName&quot;:&quot;David Kuri&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:100,&quot;DisplayName&quot;:&quot;cifz&quot;}]}" />
  <row Id="2684" PostHistoryTypeId="2" PostId="1554" RevisionGUID="ed3d2130-79de-4188-af9c-f1e34e680a08" CreationDate="2015-09-30T09:46:04.110" UserId="105" Text="The short answer is YES, you can not avoid doing a lot of bit manipulation if your format needs it.&#xD;&#xA;&#xD;&#xA;Drawing a bitmap basically mean copy a pixel from a source to a destination and you have to do what it takes to do it. (Quoting Captain Obvious)&#xD;&#xA;&#xD;&#xA;A longer answer is that if you write a software rasterizer, you can have some algorithm and trick to save you cpu time (by knowing which part you DO NOT NEED TO DRAW (transparency optimization), by having a pixel format of the source the same as the destination (directly or in a form of cache), optimally perform memcopy, etc... Basically consider the drawing loop of your rasterizer and see how you can restructure them to save CPU time. (ex : you could generate at runtime a piece of assembler code just specifically to print the letter A or have meta to your source bitmap info to tell you how to skip transparent area, etc..)&#xD;&#xA;Each use case may have a different solution based on CPU instruction set, buffer format, cache etc...&#xD;&#xA;&#xD;&#xA;So yes anyway, it TOOK a lot of CPU cycle to write single pixel in the old days were weird encoding, small memory was the norm. :-)&#xD;&#xA;But it didnt forbid 16 / 32 bit machines with 8 MHZ CPU to do things like that : https://www.youtube.com/watch?v=GWwPJU6pp30 (And a big chunk of the CPU was used also for the music)&#xD;&#xA;&#xD;&#xA;In the case of HW rendering, HW will perform the conversion from the source format to destination format and while it will not use much of the tricks available to SW rasterizer, its generic implementation in HW will most likely beat most of the SW implementation.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2685" PostHistoryTypeId="5" PostId="1554" RevisionGUID="a682da29-78a1-4232-b5cf-c3404fbab5d0" CreationDate="2015-09-30T10:08:55.720" UserId="105" Comment="added 129 characters in body" Text="The short answer is YES, you can not avoid doing a lot of bit manipulation if your format needs it.&#xD;&#xA;&#xD;&#xA;Drawing a bitmap basically mean copy a pixel from a source to a destination and you have to do what it takes to do it. (Quoting Captain Obvious)&#xD;&#xA;&#xD;&#xA;A longer answer is that if you write a software rasterizer, you can have some algorithm and trick to save you cpu time (by knowing which part you DO NOT NEED TO DRAW (transparency optimization), by having a pixel format of the source the same as the destination (directly or in a form of cache), optimally perform memcopy, etc... Basically consider the drawing loop of your rasterizer and see how you can restructure them to save CPU time. (ex : you could generate at runtime a piece of assembler code just specifically to print the letter A or have meta to your source bitmap info to tell you how to skip transparent area, etc..)&#xD;&#xA;Each use case may have a different solution based on CPU instruction set, buffer format, the algorithm of your rendering primitive (rotating ? stretching bitmaps ? what kind of filtering ? etc...), CPU register and cache etc...&#xD;&#xA;&#xD;&#xA;So yes anyway, it TOOK a lot of CPU cycle to write single pixel in the old days when weird encoding &amp; small memory were the norm. :-)&#xD;&#xA;But it didn't forbid 16 / 32 bit machines with 8 MHZ CPU to do things like that : https://www.youtube.com/watch?v=GWwPJU6pp30 (And a big chunk of the CPU was used also for the music)&#xD;&#xA;&#xD;&#xA;In the case of HW rendering, HW will perform the conversion from the source format to destination format and while it will not use much of the tricks available to SW rasterizer, its generic implementation in HW will most likely beat most of the SW implementation.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2686" PostHistoryTypeId="2" PostId="1555" RevisionGUID="16b97927-0039-42ac-a45e-baf3e55ba4c3" CreationDate="2015-09-30T10:57:29.540" UserId="213" Text="Asking it here and not on SO as it seems to be appropriate question for CG.&#xD;&#xA;I am learning [NVIDIA NVENC][1] API.The SDK supplies a sampled called &quot;NvEncoderCudaInterop&quot; .There is a chunk of code which copies YUV plane arrays from CPU to GPU buffers.&#xD;&#xA;This is the code:&#xD;&#xA;&#xD;&#xA;     // copy luma&#xD;&#xA;     CUDA_MEMCPY2D copyParam;&#xD;&#xA;    memset(&amp;copyParam, 0, sizeof(copyParam));&#xD;&#xA;    copyParam.dstMemoryType = CU_MEMORYTYPE_DEVICE;&#xD;&#xA;    copyParam.dstDevice = pEncodeBuffer-&gt;stInputBfr.pNV12devPtr;&#xD;&#xA;    copyParam.dstPitch = pEncodeBuffer-&gt;stInputBfr.uNV12Stride;&#xD;&#xA;    copyParam.srcMemoryType = CU_MEMORYTYPE_HOST;&#xD;&#xA;    copyParam.srcHost = yuv[0];&#xD;&#xA;    copyParam.srcPitch = width;&#xD;&#xA;    copyParam.WidthInBytes = width;&#xD;&#xA;    copyParam.Height = height;&#xD;&#xA;    __cu(cuMemcpy2D(&amp;copyParam));&#xD;&#xA;&#xD;&#xA;    // copy chroma&#xD;&#xA;&#xD;&#xA;    __cu(cuMemcpyHtoD(m_ChromaDevPtr[0], yuv[1], width*height / 4));&#xD;&#xA;    __cu(cuMemcpyHtoD(m_ChromaDevPtr[1], yuv[2], width*height / 4));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I do understand the rationale behind the procedure.The memory is copied to GPU  for the kernel to process it.What I don't understand is why,in order to copy Y plane, cuMemcpy2D is used and for UV [cuMemcpyHtoD][2]?Why Y can't be copied using cuMemcpyHtoD as well?As far as I understand,YUV planes have the same linear memory layout.The only difference is their size.&#xD;&#xA;&#xD;&#xA;PS:Btw,anyone can add CUDA tag?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/nvidia-video-codec-sdk&#xD;&#xA;  [2]: http://developer.download.nvidia.com/compute/cuda/4_1/rel/toolkit/docs/online/group__CUDA__MEM_g4d32266788c440b0220b1a9ba5795169.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2687" PostHistoryTypeId="1" PostId="1555" RevisionGUID="16b97927-0039-42ac-a45e-baf3e55ba4c3" CreationDate="2015-09-30T10:57:29.540" UserId="213" Text="CUDA cuMemcpuHtoD vs cuMemcpy2D" ContentLicense="CC BY-SA 3.0" />
  <row Id="2688" PostHistoryTypeId="3" PostId="1555" RevisionGUID="16b97927-0039-42ac-a45e-baf3e55ba4c3" CreationDate="2015-09-30T10:57:29.540" UserId="213" Text="|gpu|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2689" PostHistoryTypeId="2" PostId="1556" RevisionGUID="ba369220-d06d-40a9-804a-5227edc64e92" CreationDate="2015-09-30T11:27:36.453" UserId="385" Text="I've been trying to understand some of the [physical principles][1] behind light and material interaction lately. In his talk [Physics and Math of Shading][2], Naty Hoffman explains Fresnel reflectance and defines the characteristic specular color **F&lt;sub&gt;0&lt;/sub&gt;** of a material as the Fresnel reflectance at 0° incident light angle.&#xD;&#xA;&#xD;&#xA;On slide 65, **F&lt;sub&gt;0&lt;/sub&gt;** of gold is given as *1.022, 0.782, 0.344* (linear). Hoffman adds: &#xD;&#xA;&#xD;&#xA;&gt; its red channel value is greater than 1 (it’s outside sRGB gamut)&#xD;&#xA;&#xD;&#xA;All of this doesn't make too much sense to me. A value greater than 1 would mean that in the wavelengths contributing to the red channel, *more energy is reflected than is received*. Does this really happen, and if so, how and why?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In addition, here is a reflectance curve from [Wikipedia][3] for some materials including gold (Au). The curve is certainly high for red wavelengths around 600nm but does not seem to go over 100%.&#xD;&#xA;&#xD;&#xA;[![Reflectance (Au)][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/1513/how-physically-based-is-the-diffuse-and-specular-distinction&#xD;&#xA;  [2]: http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Reflectance&#xD;&#xA;  [4]: https://i.stack.imgur.com/P2Vwr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2690" PostHistoryTypeId="1" PostId="1556" RevisionGUID="ba369220-d06d-40a9-804a-5227edc64e92" CreationDate="2015-09-30T11:27:36.453" UserId="385" Text="Fresnel reflectance of gold: red channel greater than 1?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2691" PostHistoryTypeId="3" PostId="1556" RevisionGUID="ba369220-d06d-40a9-804a-5227edc64e92" CreationDate="2015-09-30T11:27:36.453" UserId="385" Text="|physics|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2692" PostHistoryTypeId="2" PostId="1557" RevisionGUID="684509e5-1a9e-4a23-a4ba-a217208584af" CreationDate="2015-09-30T13:21:43.827" UserId="385" Text="**Photorealistic rendering** has the goal of rendering an image as a *real camera* would capture it. While this is already an ambitious goal, for certain scenarios you might want to take it further: render an image as the *human eye* would capture it or even as the *human being* would perceive it. You could call it *visiorealistic* or *perceptiorealistic rendering*, but if anyone could come up with a catchier term (or tell me that there is one already in existence) I'd appreciate that.&#xD;&#xA;&#xD;&#xA;Here are some examples to make my point clear. When you take a picture with a camera at a low illumination level, you either have a good lens or get a noisy image. For a human observer, [scotopic vision][1] kicks in and gives rise to the [Purkinje effect][2] (colors are shifted towards blue). This effect depends on the HDR luminance information, which are lost when I display the image on a LDR display. In addition, the human brain may use depth information to 'filter' the perceived image - information which are lost in a final (non-stereo) rendering.&#xD;&#xA;&#xD;&#xA;Which effects of the eye and the brain do I need to consider?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Scotopic_vision&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Purkinje_effect&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Peripheral_vision" ContentLicense="CC BY-SA 3.0" />
  <row Id="2693" PostHistoryTypeId="1" PostId="1557" RevisionGUID="684509e5-1a9e-4a23-a4ba-a217208584af" CreationDate="2015-09-30T13:21:43.827" UserId="385" Text="Realistic rendering: which processes of the human eye and brain do I need to consider?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2694" PostHistoryTypeId="3" PostId="1557" RevisionGUID="684509e5-1a9e-4a23-a4ba-a217208584af" CreationDate="2015-09-30T13:21:43.827" UserId="385" Text="|human-vision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2698" PostHistoryTypeId="5" PostId="1555" RevisionGUID="2bf4abeb-fe35-4c43-ab30-84cf6a32cce3" CreationDate="2015-09-30T14:26:47.203" UserId="385" Comment="Added a CUDA tag" Text="Asking it here and not on SO as it seems to be appropriate question for CG.&#xD;&#xA;I am learning [NVIDIA NVENC][1] API.The SDK supplies a sampled called &quot;NvEncoderCudaInterop&quot; .There is a chunk of code which copies YUV plane arrays from CPU to GPU buffers.&#xD;&#xA;This is the code:&#xD;&#xA;&#xD;&#xA;     // copy luma&#xD;&#xA;     CUDA_MEMCPY2D copyParam;&#xD;&#xA;    memset(&amp;copyParam, 0, sizeof(copyParam));&#xD;&#xA;    copyParam.dstMemoryType = CU_MEMORYTYPE_DEVICE;&#xD;&#xA;    copyParam.dstDevice = pEncodeBuffer-&gt;stInputBfr.pNV12devPtr;&#xD;&#xA;    copyParam.dstPitch = pEncodeBuffer-&gt;stInputBfr.uNV12Stride;&#xD;&#xA;    copyParam.srcMemoryType = CU_MEMORYTYPE_HOST;&#xD;&#xA;    copyParam.srcHost = yuv[0];&#xD;&#xA;    copyParam.srcPitch = width;&#xD;&#xA;    copyParam.WidthInBytes = width;&#xD;&#xA;    copyParam.Height = height;&#xD;&#xA;    __cu(cuMemcpy2D(&amp;copyParam));&#xD;&#xA;&#xD;&#xA;    // copy chroma&#xD;&#xA;&#xD;&#xA;    __cu(cuMemcpyHtoD(m_ChromaDevPtr[0], yuv[1], width*height / 4));&#xD;&#xA;    __cu(cuMemcpyHtoD(m_ChromaDevPtr[1], yuv[2], width*height / 4));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I do understand the rationale behind the procedure.The memory is copied to GPU  for the kernel to process it.What I don't understand is why,in order to copy Y plane, cuMemcpy2D is used and for UV [cuMemcpyHtoD][2]?Why Y can't be copied using cuMemcpyHtoD as well?As far as I understand,YUV planes have the same linear memory layout.The only difference is their size.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/nvidia-video-codec-sdk&#xD;&#xA;  [2]: http://developer.download.nvidia.com/compute/cuda/4_1/rel/toolkit/docs/online/group__CUDA__MEM_g4d32266788c440b0220b1a9ba5795169.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2699" PostHistoryTypeId="6" PostId="1555" RevisionGUID="2bf4abeb-fe35-4c43-ab30-84cf6a32cce3" CreationDate="2015-09-30T14:26:47.203" UserId="385" Comment="Added a CUDA tag" Text="|gpu|gpgpu|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2700" PostHistoryTypeId="24" PostId="1555" RevisionGUID="2bf4abeb-fe35-4c43-ab30-84cf6a32cce3" CreationDate="2015-09-30T14:26:47.203" Comment="Proposed by 385 approved by 213 edit id of 58" ContentLicense="CC BY-SA 3.0" />
  <row Id="2706" PostHistoryTypeId="10" PostId="1552" RevisionGUID="d787c0ba-aacb-41db-b4ae-69cedac74b49" CreationDate="2015-09-30T20:21:58.790" UserId="-1" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:100,&quot;DisplayName&quot;:&quot;cifz&quot;},{&quot;Id&quot;:385,&quot;DisplayName&quot;:&quot;David Kuri&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;}]}" />
  <row Id="2708" PostHistoryTypeId="2" PostId="1560" RevisionGUID="efe88b49-3912-4a4a-b48f-02f06a715b8f" CreationDate="2015-10-01T05:34:20.937" UserId="38" Text="RGB color is a bit more complicated subject than readily seems apparent. The reflectance wavelength diagram shows the reason quite well actually.&#xD;&#xA;&#xD;&#xA;RGB color model has several central problems:&#xD;&#xA;&#xD;&#xA;* What the colors represent: They represent 3 spikes in a continnious spectra  The R, G and B arent even evenly spaced in that spectra let alone evenly spaced.&#xD;&#xA;* What their range is: The colors do not actually mean anything without information of what space they span. In the assumed sRGB colorspace the space does not span the entire sensable range. So energeticaly equal but more vivid colors exist.&#xD;&#xA;* Human sensory aparatus isnt actually reading 3 color spikes but the sensors nonlineary overlap.&#xD;&#xA;&#xD;&#xA;As a result one can not draw the conclusion that a reflectance color channel of greater than 1 automatically means that energy is inserted into the system. That is simply one of the possible interpretations. &#xD;&#xA;&#xD;&#xA;Another interpretation is that the color is more intense than your colorspace allows. as a result your color vector component could be over 1.&#xD;&#xA;&#xD;&#xA;Human eyes may also bleed color from one sensor to another due to overlap of the sensors. Such things happen with the sky which seems light blue, but is actually far darker blue but so intense that we see it as light blue. But in 50% reflections it would look wrong if we wouldn't account for this.&#xD;&#xA;&#xD;&#xA;In the end. It can also mean energy is inserted into the system. Either the energy comes from elsewhere or is generated by the surface.&#xD;&#xA;&#xD;&#xA;Rendering is often not a scientific measure of things. No energy principle is still needed to broken to achieve this.&#xD;&#xA;&#xD;&#xA;### Summa summarum (tl;dr)&#xD;&#xA;&#xD;&#xA;Color is often a compound attribute at the same time as it measures energy levels it also measures something other. Namely the location in the colorspace. Thus you can not&#xD;&#xA; differentiate the two signals (energy and color intensity) easily.&#xD;&#xA;&#xD;&#xA;In this case it is a more intense color because the source says so: Outside of sRGB gamut = more intense color than the colorspace can make." ContentLicense="CC BY-SA 3.0" />
  <row Id="2709" PostHistoryTypeId="2" PostId="1561" RevisionGUID="aff49e5a-02a4-44bc-9ce7-ef903f5af076" CreationDate="2015-10-01T05:35:46.373" UserId="196" Text="Here's a chromaticity diagram that includes a projection of the sRGB color space: a triangle whose vertices are red (1,0,0), green (0,1,0), and blue (0,0,1).&#xD;&#xA;&#xD;&#xA;[![CIE chart with sRGB gamut from Wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;Encoding the reflectance of a surface as the color at **F&lt;sub&gt;0&lt;/sub&gt;** and getting a value that is outside of the (somewhat arbitrary chosen) sRGB gamut is totally reasonable. It just means that gold is &quot;more red&quot; than sRGB can represent, because it reserves valuable area of its dynamic range for other colors.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eYuuN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2710" PostHistoryTypeId="5" PostId="1560" RevisionGUID="53f890b4-5a33-4f22-a2fb-91b57a354cf5" CreationDate="2015-10-01T05:41:19.590" UserId="38" Comment="deleted 9 characters in body" Text="RGB color is a bit more complicated subject than readily seems apparent. The reflectance wavelength diagram shows the reason quite well actually.&#xD;&#xA;&#xD;&#xA;RGB color model has several central problems:&#xD;&#xA;&#xD;&#xA;* What the colors represent: They represent 3 spikes in a continnious spectra  The R, G and B arent energetically eqivivalent let alone evenly spaced.&#xD;&#xA;* What their range is: The colors do not actually mean anything without information of what space they span. In the assumed sRGB colorspace the space does not span the entire sensable range. So energeticaly equal but more vivid colors exist.&#xD;&#xA;* Human sensory aparatus isnt actually reading 3 color spikes but the sensors nonlineary overlap.&#xD;&#xA;&#xD;&#xA;As a result one can not draw the conclusion that a reflectance color channel of greater than 1 automatically means that energy is inserted into the system. That is simply one of the possible interpretations. &#xD;&#xA;&#xD;&#xA;Another interpretation is that the color is more intense than your colorspace allows. as a result your color vector component could be over 1.&#xD;&#xA;&#xD;&#xA;Human eyes may also bleed color from one sensor to another due to overlap of the sensors. Such things happen with the sky which seems light blue, but is actually far darker blue but so intense that we see it as light blue. But in 50% reflections it would look wrong if we wouldn't account for this.&#xD;&#xA;&#xD;&#xA;In the end. It can also mean energy is inserted into the system. Either the energy comes from elsewhere or is generated by the surface.&#xD;&#xA;&#xD;&#xA;Rendering is often not a scientific measure of things. No energy principle is still needed to broken to achieve this.&#xD;&#xA;&#xD;&#xA;### Summa summarum (tl;dr)&#xD;&#xA;&#xD;&#xA;Color is often a compound attribute at the same time as it measures energy levels it also measures something other. Namely the location in the colorspace. Thus you can not&#xD;&#xA; differentiate the two signals (energy and color intensity) easily.&#xD;&#xA;&#xD;&#xA;In this case it is a more intense color because the source says so: Outside of sRGB gamut = more intense color than the colorspace can make." ContentLicense="CC BY-SA 3.0" />
  <row Id="2711" PostHistoryTypeId="5" PostId="1560" RevisionGUID="1d251604-8ab0-40cf-a0dc-222a26477a51" CreationDate="2015-10-01T07:03:15.983" UserId="38" Comment="added 7 characters in body" Text="RGB color is a bit more complicated subject than readily seems apparent. The reflectance wavelength diagram shows the reason quite well actually.&#xD;&#xA;&#xD;&#xA;RGB color model has several central problems:&#xD;&#xA;&#xD;&#xA;* What the colors represent: They represent 3 spikes in a continuous spectra  The R, G and B aren't energetically equivalent let alone evenly spaced.&#xD;&#xA;* What their range is: The colors do not actually mean anything without information of what space they span. In the assumed sRGB color space the space does not span the entire sensable range. So energeticaly equal but more vivid colors exist.&#xD;&#xA;* Human sensory apparatus isn't actually reading 3 color spikes but the sensors nonlinearily overlap.&#xD;&#xA;&#xD;&#xA;As a result one can not draw the conclusion that a reflectance color channel of greater than 1 automatically means that energy is inserted into the system. That is simply one of the possible interpretations. &#xD;&#xA;&#xD;&#xA;Another interpretation is that the color is more intense than your color space allows. as a result your color vector component could be over 1.&#xD;&#xA;&#xD;&#xA;Human eyes may also bleed color from one sensor to another due to overlap of the sensors. Such things happen with the sky which seems light blue, but is actually far darker blue but so intense that we see it as light blue. But in 50% reflections it would look wrong if we wouldn't account for this.&#xD;&#xA;&#xD;&#xA;In the end. It can also mean energy is inserted into the system. Either the energy comes from elsewhere or is generated by the surface.&#xD;&#xA;&#xD;&#xA;Rendering is often not a scientific measure of things. No energy principle is still needed to broken to achieve this.&#xD;&#xA;&#xD;&#xA;### Summa summarum (tl;dr)&#xD;&#xA;&#xD;&#xA;Color is often a compound attribute at the same time as it measures energy levels it also measures something other. Namely the location in the color space. Thus you can not&#xD;&#xA; differentiate the two signals (energy and color intensity) easily.&#xD;&#xA;&#xD;&#xA;In this case it is a more intense color because the source says so: Outside of sRGB gamut = more intense color than the color space can make." ContentLicense="CC BY-SA 3.0" />
  <row Id="2713" PostHistoryTypeId="5" PostId="1557" RevisionGUID="c44b23b6-63f9-425c-974c-e0dd1b8dc7d2" CreationDate="2015-10-01T08:34:38.210" UserId="385" Comment="Clarified: accepting incomplete answers" Text="**Photorealistic rendering** has the goal of rendering an image as a *real camera* would capture it. While this is already an ambitious goal, for certain scenarios you might want to take it further: render an image as the *human eye* would capture it or even as the *human being* would perceive it. You could call it *visiorealistic* or *perceptiorealistic rendering*, but if anyone could come up with a catchier term (or tell me that there is one already in existence) I'd appreciate that.&#xD;&#xA;&#xD;&#xA;Here are some examples to make my point clear. When you take a picture with a camera at a low illumination level, you either have a good lens or get a noisy image. For a human observer, [scotopic vision][1] kicks in and gives rise to the [Purkinje effect][2] (colors are shifted towards blue). This effect depends on the HDR luminance information, which are lost when I display the image on a LDR display. In addition, the human brain may use depth information to 'filter' the perceived image - information which are lost in a final (non-stereo) rendering.&#xD;&#xA;&#xD;&#xA;Assembling an exhaustive list is probably an elusive goal. Could you suggest some of the effects of the eye and the brain that I would need to consider?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Scotopic_vision&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Purkinje_effect&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Peripheral_vision" ContentLicense="CC BY-SA 3.0" />
  <row Id="2715" PostHistoryTypeId="5" PostId="1551" RevisionGUID="70985541-291e-4d40-be10-20f08cab9db6" CreationDate="2015-10-01T17:16:03.587" UserId="209" Comment="Still unfinished." Text="**[NOTE: Unfinished ... Sorry... still working on this. ]**&#xD;&#xA;&#xD;&#xA;## *&quot;How does (hardware) texture compression work&quot;* ##&#xD;&#xA;&#xD;&#xA;Goodness, this is a big topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/).&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should thus also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware (and power) costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't (easily) predict which texels will be required during a given render. If some subset of the texels come from, say, the middle of the image, you also don't want to have to decode all of the 'previous' lines of texture in order to work out what those texels are; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded pixels.  (Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample &quot;willy-nilly&quot;](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419) )&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (...but I will admit that compression of PVRTC, ETC2 and some others at max-quality could be faster!)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days where even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reduction the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or, cough, patents) you can find references to techniques including  &#xD;&#xA; a) simple forms of mathematical/procedural texture synthesis, &#xD;&#xA; b) use a single channel texture (e.g. 4bpp) which is then multiplied by a fixed RGB value, &#xD;&#xA; c) YUV, and &#xD;&#xA; d) palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;Some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ), to reduce data costs. The problem with palette textures are that the compression rates for the achieved quality are generally rather modest.&#xD;&#xA;&#xD;&#xA;*VQ*&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2 or even and 2x4 blocks with single bytes. Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads - 'one' read to determine the code for the pixel and then a second to actually fetch the data associated with that code. Caches can help alleviate some of the incurred latency, but it adds complexity. &#xD;&#xA;&#xD;&#xA;*Colour Space Transformations*&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler scheme that allowed the user to specify, for the entire texture, two end colours along with a 4bpp monochrome texture. The monochrome value then blended these end colours with appropriate weights.&#xD;&#xA;&#xD;&#xA;*BTC-based schemes*&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. (This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data). In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is S3TC, much of which, ironically, was a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119). In S3TC each 4x4 block is replaced by two end colours, *A* and *B* and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. &#xD;&#xA;&#xD;&#xA;*to do:  Insert diagram*&#xD;&#xA;&#xD;&#xA;[SAVING as a work in progress...]&#xD;&#xA;&#xD;&#xA;*FWIW I've been considering doing a talk at work on Texture Compression. If that goes ahead I may add some of that material here*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2716" PostHistoryTypeId="2" PostId="1562" RevisionGUID="e57fe306-12ce-454a-a59e-7df0af43f9f7" CreationDate="2015-10-02T00:14:52.133" UserId="1774" Text="I have a class that generates a 3D shape based on inputs from the calling code. The inputs are things like length, depth, arc, etc. My code generates the geometry perfectly, however I am running into trouble when calculating the surface normals. When lit, my shape has very bizzare coloring/texture from the incorrect surface normals that are being calculated. From all my research I believe my math is correct, it seems that something is wrong with my technique or method.&#xD;&#xA;&#xD;&#xA;At a high level how does one go about programmatically calculating the surface normals for a generated shape? I am using Swift/SceneKit on iOS for my code but a generic answer is fine.&#xD;&#xA;&#xD;&#xA;I can add more detail about my specific use case as needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="2717" PostHistoryTypeId="1" PostId="1562" RevisionGUID="e57fe306-12ce-454a-a59e-7df0af43f9f7" CreationDate="2015-10-02T00:14:52.133" UserId="1774" Text="How to Calculate Surface Normals for a Generated Geomtery" ContentLicense="CC BY-SA 3.0" />
  <row Id="2718" PostHistoryTypeId="3" PostId="1562" RevisionGUID="e57fe306-12ce-454a-a59e-7df0af43f9f7" CreationDate="2015-10-02T00:14:52.133" UserId="1774" Text="|lighting|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2719" PostHistoryTypeId="5" PostId="1562" RevisionGUID="c2173b9e-744f-4119-a2f5-123e9c64f108" CreationDate="2015-10-02T01:36:46.883" UserId="1774" Comment="added more detail" Text="I have a class that generates a 3D shape based on inputs from the calling code. The inputs are things like length, depth, arc, etc. My code generates the geometry perfectly, however I am running into trouble when calculating the surface normals. When lit, my shape has very bizzare coloring/texture from the incorrect surface normals that are being calculated. From all my research I believe my math is correct, it seems that something is wrong with my technique or method.&#xD;&#xA;&#xD;&#xA;At a high level how does one go about programmatically calculating the surface normals for a generated shape? I am using Swift/SceneKit on iOS for my code but a generic answer is fine.&#xD;&#xA;&#xD;&#xA;I have two arrays that represent my shape. One is an array of 3D points that represents the vertices that make up the shape. The other array is a list of indexes of the first array that map the vertices into triangles. I need to take that data and generate a 3rd array that is a set of surface normals that aid in the lighting of the shape. (see: https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SceneKit_Constants/index.html#//apple_ref/c/data/SCNGeometrySourceSemanticNormal)&#xD;&#xA;&#xD;&#xA;The list of vertices and indexes is always different depending on the inputs to the class so I cannot pre-calculate or hard code the surface normals." ContentLicense="CC BY-SA 3.0" />
  <row Id="2720" PostHistoryTypeId="2" PostId="1563" RevisionGUID="59c58c52-d2a7-482c-8ef0-c25953d40725" CreationDate="2015-10-02T06:01:39.200" UserId="38" Text="You simply dont want fully smooth results. While the commented method by Nathan Reed: &quot;Calculate each vertex to face normal, sum them, normalize sum&quot;, generally works it sometimes fails spectacularly. But that is of no importance here, we can use that method by adding a rejection clause to it.&#xD;&#xA;&#xD;&#xA;In this case you simply want certain parts not to be smoothed against certain other parts. You want selective hard edges. So for example the flat top and bottom is separate form the triangle strip on the side, as is each flat area.&#xD;&#xA;&#xD;&#xA;[![Image we are after][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The result you want.&#xD;&#xA;&#xD;&#xA;In effect you only want to average the vertices of the curved area all others can use the normal they get form their triangle alone. So you are better of thinking of the mesh as 9 separate regions that are handled without the others.&#xD;&#xA;&#xD;&#xA;[![Showing mesh and normals][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 2**: Image showing the mesh structure and normal's.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can certainly automatically deduce this by not including normals that are outside certain angle from the primary vertexes normal. Pseudocode:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    For vertex in faceVertex:&#xD;&#xA;        normal = vertex.normal&#xD;&#xA;        For adjVertex in adjacentVertices:&#xD;&#xA;            if anglebetween(vertex.normal, adjVertex.normal )  &lt; treshold:&#xD;&#xA;                normal += adjVertex.normal&#xD;&#xA;        normal = normalize(normal)&#xD;&#xA; &#xD;&#xA;That works, but you can simply avoid all of this at creation time because you understand that separate planes are working differently. So only the curved sides need normal direction merging. And in fact you can just directly calulate them from the underlying mathematical shape.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JLntk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vKpLC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2721" PostHistoryTypeId="5" PostId="1563" RevisionGUID="673c15c0-cd0e-43a7-b9e3-8d255e3444f7" CreationDate="2015-10-02T06:08:16.183" UserId="38" Comment="added 124 characters in body" Text="You simply dont want fully smooth results. While the commented method by Nathan Reed: &quot;Calculate each vertex to face normal, sum them, normalize sum&quot;, generally works it sometimes fails spectacularly. But that is of no importance here, we can use that method by adding a rejection clause to it.&#xD;&#xA;&#xD;&#xA;In this case you simply want certain parts not to be smoothed against certain other parts. You want selective hard edges. So for example the flat top and bottom is separate form the triangle strip on the side, as is each flat area.&#xD;&#xA;&#xD;&#xA;[![Image we are after][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The result you want.&#xD;&#xA;&#xD;&#xA;In effect you only want to average the vertices of the curved area all others can use the normal they get form their triangle alone. So you are better of thinking of the mesh as 9 separate regions that are handled without the others.&#xD;&#xA;&#xD;&#xA;[![Showing mesh and normals][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 2**: Image showing the mesh structure and normal's. note: If the normals at the edges of the triangle look odd it was because i neglected to do some of the back faces of the triangle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can certainly automatically deduce this by not including normals that are outside certain angle from the primary vertexes normal. Pseudocode:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    For vertex in faceVertex:&#xD;&#xA;        normal = vertex.normal&#xD;&#xA;        For adjVertex in adjacentVertices:&#xD;&#xA;            if anglebetween(vertex.normal, adjVertex.normal )  &lt; treshold:&#xD;&#xA;                normal += adjVertex.normal&#xD;&#xA;        normal = normalize(normal)&#xD;&#xA; &#xD;&#xA;That works, but you can simply avoid all of this at creation time because you understand that separate planes are working differently. So only the curved sides need normal direction merging. And in fact you can just directly calulate them from the underlying mathematical shape.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JLntk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vKpLC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2722" PostHistoryTypeId="5" PostId="1563" RevisionGUID="c129e4d2-0058-4920-910f-1959d89fef40" CreationDate="2015-10-02T06:45:12.693" UserId="38" Comment="Fixed normals" Text="You simply dont want fully smooth results. While the commented method by Nathan Reed: &quot;Calculate each vertex to face normal, sum them, normalize sum&quot;, generally works it sometimes fails spectacularly. But that is of no importance here, we can use that method by adding a rejection clause to it.&#xD;&#xA;&#xD;&#xA;In this case you simply want certain parts not to be smoothed against certain other parts. You want selective hard edges. So for example the flat top and bottom is separate form the triangle strip on the side, as is each flat area.&#xD;&#xA;&#xD;&#xA;[![Image we are after][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The result you want.&#xD;&#xA;&#xD;&#xA;In effect you only want to average the vertices of the curved area all others can use the normal they get form their triangle alone. So you are better of thinking of the mesh as 9 separate regions that are handled without the others.&#xD;&#xA;&#xD;&#xA;[![Showing mesh and normals][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Image showing the mesh structure and the normals. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can certainly automatically deduce this by not including normals that are outside certain angle from the primary vertexes normal. Pseudocode:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    For vertex in faceVertex:&#xD;&#xA;        normal = vertex.normal&#xD;&#xA;        For adjVertex in adjacentVertices:&#xD;&#xA;            if anglebetween(vertex.normal, adjVertex.normal )  &lt; treshold:&#xD;&#xA;                normal += adjVertex.normal&#xD;&#xA;        normal = normalize(normal)&#xD;&#xA; &#xD;&#xA;That works, but you can simply avoid all of this at creation time because you understand that separate planes are working differently. So only the curved sides need normal direction merging. And in fact you can just directly calulate them from the underlying mathematical shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JLntk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RzAir.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2723" PostHistoryTypeId="5" PostId="1562" RevisionGUID="5c719b9a-dcfb-43b4-b50a-74979bacebd5" CreationDate="2015-10-02T07:15:44.110" UserId="127" Comment="Added some text to not display the link directly, edited title" Text="I have a class that generates a 3D shape based on inputs from the calling code. The inputs are things like length, depth, arc, etc. My code generates the geometry perfectly, however I am running into trouble when calculating the surface normals. When lit, my shape has very bizzare coloring/texture from the incorrect surface normals that are being calculated. From all my research I believe my math is correct, it seems that something is wrong with my technique or method.&#xD;&#xA;&#xD;&#xA;At a high level how does one go about programmatically calculating the surface normals for a generated shape? I am using Swift/SceneKit on iOS for my code but a generic answer is fine.&#xD;&#xA;&#xD;&#xA;I have two arrays that represent my shape. One is an array of 3D points that represents the vertices that make up the shape. The other array is a list of indexes of the first array that map the vertices into triangles. I need to take that data and generate a 3rd array that is a set of surface normals that aid in the lighting of the shape. (see [`SCNGeometrySourceSemanticNormal` in SceneKit`](https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SceneKit_Constants/index.html#//apple_ref/c/data/SCNGeometrySourceSemanticNormal))&#xD;&#xA;&#xD;&#xA;The list of vertices and indexes is always different depending on the inputs to the class so I cannot pre-calculate or hard code the surface normals." ContentLicense="CC BY-SA 3.0" />
  <row Id="2724" PostHistoryTypeId="4" PostId="1562" RevisionGUID="5c719b9a-dcfb-43b4-b50a-74979bacebd5" CreationDate="2015-10-02T07:15:44.110" UserId="127" Comment="Added some text to not display the link directly, edited title" Text="How to Calculate Surface Normals for Generated Geomtery" ContentLicense="CC BY-SA 3.0" />
  <row Id="2725" PostHistoryTypeId="24" PostId="1562" RevisionGUID="5c719b9a-dcfb-43b4-b50a-74979bacebd5" CreationDate="2015-10-02T07:15:44.110" Comment="Proposed by 127 approved by 38, 100 edit id of 59" ContentLicense="CC BY-SA 3.0" />
  <row Id="2726" PostHistoryTypeId="2" PostId="1564" RevisionGUID="d2ed9992-6300-40d1-9afd-9ba8501a2373" CreationDate="2015-10-02T08:10:48.497" UserId="333" Text="I have a shader which has several uniform variables:&#xD;&#xA;&#xD;&#xA;    unifrom vec4 a;&#xD;&#xA;    unifrom vec4 b;&#xD;&#xA;    unifrom vec4 c;&#xD;&#xA;   &#xD;&#xA;I'm getting these handles using `glGetUniformLocation()` and store them in the array. The game was suspended, then resumed and [onSurfaceCreated()][1] has been called. The question is: whether there will handles be valid or I need to re-get them using `glGetUniformLocation()` once again?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2727" PostHistoryTypeId="1" PostId="1564" RevisionGUID="d2ed9992-6300-40d1-9afd-9ba8501a2373" CreationDate="2015-10-02T08:10:48.497" UserId="333" Text="Can the uniform id be changed from run to run on the same machine?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2728" PostHistoryTypeId="3" PostId="1564" RevisionGUID="d2ed9992-6300-40d1-9afd-9ba8501a2373" CreationDate="2015-10-02T08:10:48.497" UserId="333" Text="|opengl|shader|android|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2729" PostHistoryTypeId="2" PostId="1565" RevisionGUID="ba40053e-e674-40b4-97ce-a930b4a7fcbd" CreationDate="2015-10-02T08:53:07.807" UserId="137" Text="The uniform locations are set when the program is linked and are tied to the program.&#xD;&#xA;&#xD;&#xA;This means that when you create a new program then the uniform locations can change. " ContentLicense="CC BY-SA 3.0" />
  <row Id="2730" PostHistoryTypeId="5" PostId="1563" RevisionGUID="41909e13-4898-43cc-a6cd-6e7572a56809" CreationDate="2015-10-02T08:59:22.163" UserId="38" Comment="added 1 character in body" Text="You simply dont want fully smooth results. While the commented method by Nathan Reed: &quot;Calculate each vertex to face normal, sum them, normalize sum&quot;, generally works it sometimes fails spectacularly. But that is of no importance here, we can use that method by adding a rejection clause to it.&#xD;&#xA;&#xD;&#xA;In this case you simply want certain parts not to be smoothed against certain other parts. You want selective hard edges. So for example the flat top and bottom is separate form the triangle strip on the side, as is each flat area.&#xD;&#xA;&#xD;&#xA;[![Image we are after][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The result you want.&#xD;&#xA;&#xD;&#xA;In effect you only want to average the vertices of the curved area all others can use the normal they get form their triangle alone. So you are better of thinking of the mesh as 9 separate regions that are handled without the others.&#xD;&#xA;&#xD;&#xA;[![Showing mesh and normals]][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Image showing the mesh structure and the normals. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can certainly automatically deduce this by not including normals that are outside certain angle from the primary vertexes normal. Pseudocode:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    For vertex in faceVertex:&#xD;&#xA;        normal = vertex.normal&#xD;&#xA;        For adjVertex in adjacentVertices:&#xD;&#xA;            if anglebetween(vertex.normal, adjVertex.normal )  &lt; treshold:&#xD;&#xA;                normal += adjVertex.normal&#xD;&#xA;        normal = normalize(normal)&#xD;&#xA; &#xD;&#xA;That works, but you can simply avoid all of this at creation time because you understand that separate planes are working differently. So only the curved sides need normal direction merging. And in fact you can just directly calulate them from the underlying mathematical shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JLntk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ityq6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2731" PostHistoryTypeId="2" PostId="1566" RevisionGUID="a156db9d-ae90-4657-917a-fc99c6d5bb32" CreationDate="2015-10-02T09:36:58.310" UserId="1778" Text="I'm in the process of making a tool that requires rendered texture to follow the contours of a piece of clothing. An example would be this website https://knyttan.com/editor/jumper-editor/. The effect here is achieved by using a colour map:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pcCgx.jpg&#xD;&#xA;&#xD;&#xA;I looked at the shaders that are used for this and it seems that the texture offset is calculated based on the colour channels from this map. &#xD;&#xA;&#xD;&#xA;Now I was wondering if this is a complete bespoke way of doing this, or if this is a known technique and if it is what is it called ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2732" PostHistoryTypeId="1" PostId="1566" RevisionGUID="a156db9d-ae90-4657-917a-fc99c6d5bb32" CreationDate="2015-10-02T09:36:58.310" UserId="1778" Text="Help me find out what this is called" ContentLicense="CC BY-SA 3.0" />
  <row Id="2733" PostHistoryTypeId="3" PostId="1566" RevisionGUID="a156db9d-ae90-4657-917a-fc99c6d5bb32" CreationDate="2015-10-02T09:36:58.310" UserId="1778" Text="|texture|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2734" PostHistoryTypeId="2" PostId="1567" RevisionGUID="801021a4-0bc3-4b45-905a-07532e7f757f" CreationDate="2015-10-02T11:00:20.730" UserId="38" Text="What you see in the image called a UV map. That is, it is simply texture coordinates to be looked up encoded in a image. Same thing happens in all texture lookup in 3D there is a underlying driver that picks where to texture.&#xD;&#xA;&#xD;&#xA;* [Demo](http://webglplayground.net/saved/CZTXXQeZFH) showing the UV map&#xD;&#xA;&#xD;&#xA;You can now bind a texture to this." ContentLicense="CC BY-SA 3.0" />
  <row Id="2735" PostHistoryTypeId="12" PostId="1567" RevisionGUID="2aec2721-281a-4996-b599-0cff3922491c" CreationDate="2015-10-02T11:09:38.600" UserId="38" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;}]}" />
  <row Id="2736" PostHistoryTypeId="13" PostId="1567" RevisionGUID="3afa37f9-b7f1-408b-8ed8-daae351bdb6f" CreationDate="2015-10-02T11:26:36.610" UserId="38" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;}]}" />
  <row Id="2737" PostHistoryTypeId="5" PostId="1567" RevisionGUID="3bc2f1a8-3f6b-4692-a0e9-080d30a7874c" CreationDate="2015-10-02T11:27:16.227" UserId="38" Comment="added 75 characters in body" Text="What you see in the image called a UV map. That is, it is simply texture coordinates to be looked up encoded in a image. Same thing happens in all texture lookup in 3D there is a underlying driver that picks where to texture.&#xD;&#xA;&#xD;&#xA;* [Demo](http://webglplayground.net/saved/CZTXXQeZFH) showing the UV map&#xD;&#xA;* [Demo](http://webglplayground.net/saved/tTnh7zvUc6) showing the texture&#xD;&#xA;&#xD;&#xA;You can now bind a texture to this." ContentLicense="CC BY-SA 3.0" />
  <row Id="2738" PostHistoryTypeId="5" PostId="1567" RevisionGUID="b56a6bc4-0738-4b7c-abfd-3ea2d617fc0f" CreationDate="2015-10-02T11:33:12.307" UserId="38" Comment="added 75 characters in body" Text="What you see in the image called a UV map. That is, it is simply texture coordinates to be looked up encoded in a image. Same thing happens in all texture lookup in 3D there is a underlying sampler that picks where to pick texture color from.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Image showing UV map and sampled texture with said map &#xD;&#xA;&#xD;&#xA;Here are the sources for those images, please do not overwrite the sources.&#xD;&#xA;&#xD;&#xA;* [Demo](http://webglplayground.net/saved/CZTXXQeZFH) showing the UV map&#xD;&#xA;* [Demo](http://webglplayground.net/saved/tTnh7zvUc6) showing the texture&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BhNr6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2739" PostHistoryTypeId="5" PostId="1567" RevisionGUID="dde4a745-ca8e-4b21-afca-37e8077d9ede" CreationDate="2015-10-02T11:39:23.227" UserId="38" Comment="added 44 characters in body" Text="What you see in the image called a [UV map](https://en.wikipedia.org/wiki/UV_mapping). That is, it is simply texture coordinates to be looked up encoded in a image. Same thing happens in all texture lookup in 3D there is a underlying sampler that picks where to pick texture color from.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Image showing UV map of two overlapped triangles and sampled texture with same UV coords&#xD;&#xA;&#xD;&#xA;Here are the sources for those images, please do not overwrite the sources.&#xD;&#xA;&#xD;&#xA;* [Demo](http://webglplayground.net/saved/CZTXXQeZFH) showing the UV map&#xD;&#xA;* [Demo](http://webglplayground.net/saved/tTnh7zvUc6) showing the texture&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BhNr6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2740" PostHistoryTypeId="5" PostId="1551" RevisionGUID="6cf8d5bf-4b41-4a41-badb-4193ef88da15" CreationDate="2015-10-02T13:59:53.903" UserId="209" Comment="Still unfinished." Text="**[NOTE: I apologise that this is still unfinished]**&#xD;&#xA;&#xD;&#xA;*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;### Requirements ###&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/).&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should thus also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware (and power) costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset of the texels come from, say, the middle of the image, you also don't want to have to decode all of the 'previous' lines of texture in order to work out what those texels are; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample &quot;willy-nilly&quot;](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (...but I will admit that compression of PVRTC, ETC2 and some others at max-quality could be faster!)&#xD;&#xA;&#xD;&#xA;### Early History &amp; Techniques ###&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days where even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or, cough, patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;### Modelling Image Data ###&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;### PC and (post mid 90s) Console Texture compression ###&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;#### *VQ with larger vectors*&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;#### *Colour Space Transformations*&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;#### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. (This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data). In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is S3TC, much of which, ironically, was a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119). In S3TC each 4x4 block is replaced by two end colours, *A* and *B* and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. &#xD;&#xA;&#xD;&#xA;*to do:  Insert diagram*&#xD;&#xA;&#xD;&#xA;#### ETC&#xD;&#xA;[SAVING as a work in progress...]&#xD;&#xA;&#xD;&#xA;*FWIW I've been considering doing a talk at work on Texture Compression. If that goes ahead I may add some of that material here*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2742" PostHistoryTypeId="2" PostId="1568" RevisionGUID="e7cb31da-7309-4aaa-a21b-6b08c88037c8" CreationDate="2015-10-03T15:44:17.840" UserId="34" Text="I am wondering if the various PBR models used in modern game engines for real time are heavier in terms of computation, that more classic approaches to rendering.&#xD;&#xA;&#xD;&#xA;Worded differently, is PBR just a different way to organize one's rendering pipeline, or does it add serious complexity (especially in regards to lighting) ?&#xD;&#xA;&#xD;&#xA;Depending on the answer, what would be the bottleneck for a low-resource implementation ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2743" PostHistoryTypeId="1" PostId="1568" RevisionGUID="e7cb31da-7309-4aaa-a21b-6b08c88037c8" CreationDate="2015-10-03T15:44:17.840" UserId="34" Text="Does PBR incur a performance penalty by design?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2744" PostHistoryTypeId="3" PostId="1568" RevisionGUID="e7cb31da-7309-4aaa-a21b-6b08c88037c8" CreationDate="2015-10-03T15:44:17.840" UserId="34" Text="|rendering|real-time|lighting|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2745" PostHistoryTypeId="2" PostId="1569" RevisionGUID="addbd238-1794-4003-ae7f-b8c422764a9f" CreationDate="2015-10-03T18:06:30.183" UserId="310" Text="As mentioned in [this][1] answer, Physically-Based Rendering isn't a set number of things. It's a *concept*. It's akin to saying something is 'Environmentally Friendly'. There are many different techniques to be environmentally friendly *and* someone can implement those techniques to varying degrees. The same is for PBR.&#xD;&#xA;&#xD;&#xA;In the end, Physically Based Rendering is just that, based on Physics in some way, shape, or form. One of the most basic 'physical' rendering techniques I can think of is using [Lambert shading][2]. While you may say, &quot;Well that doesn't take into account specular light, or etc, etc. etc.&quot;, I agree. Lambert shading is a crude representation of the physics of light. But, pedantically, it *is* PBR, because it is based off the physical observation that light intensity decreases with viewing angle.&#xD;&#xA;&#xD;&#xA;A renderer can implement as many, or as few PBR techniques as they choose. Some can be very computationally expensive, others, quite cheap. They can also choose to enable or disable certain techniques for different targets. For example, UE4 has a different set of techniques for mobile games, than for high end PC games. &#xD;&#xA;&#xD;&#xA;Now, that all said, when today's modern renderers talk about being &quot;Physically-based&quot;, they are generally referring to using a modern BRDF, generally some form of [Cook-Torrance][3], and physically plausible inputs. Inputs being: materials with physically-plausible color values and lights with physically based intensity values. &#xD;&#xA;&#xD;&#xA;Using a modern BRDF can be very computationally expensive, but, there are many approximations that can make it more friendly.&#xD;&#xA;&#xD;&#xA;Using physically-plausible inputs is generally not that difficult to implement on the renderer side, rather it's more difficult for artists. IE. teaching them what the different material values mean, and what are physically plausible values. This can be a huge task, depending on your artists, as seen in the presentations [here][4], [here][5], and [here][6], for example. In my opinion, this is the hardest task in switching a studio.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last question, what do you mean by 'low-resource'? Less powerful hardware? Small studio? Could you elaborate?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/a/1468/310&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;  [3]: http://ruh.li/GraphicsCookTorrance.html&#xD;&#xA;  [4]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [5]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf&#xD;&#xA;  [6]: http://www.slideshare.net/guerrillagames/lighting-of-killzone-shadow-fall" ContentLicense="CC BY-SA 3.0" />
  <row Id="2753" PostHistoryTypeId="2" PostId="1571" RevisionGUID="159d4a08-776f-42ea-81ac-e51c8756a56d" CreationDate="2015-10-05T05:25:54.713" UserId="523" Text="&gt; you might want to take it further: render an image as the human eye would capture it or even as the human being would perceive it.&#xD;&#xA;&#xD;&#xA;There are two ways to interpret this.  I'll do both.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Interpretation 1: Render an image that looks perceptually realistic.**&#xD;&#xA;&#xD;&#xA;At the end of the day, your image still needs to be _displayed_ somewhere.  Here's the key: you want to _render your image in such a way that when you *display* that image on a particular display device, it will produce the same sensation the original radiometric image would have produced._&#xD;&#xA;&#xD;&#xA;Here's how to unpack that idea.&#xD;&#xA;&#xD;&#xA;In the real world, radiometric spectra (i.e., real distributions of light) enter your eye and stimulate approximately&lt;sup&gt;1&lt;/sup&gt; four light receptors.  The stimulations of the receptors produce the sensations of color we associate with images.&#xD;&#xA;&#xD;&#xA;In rendering, we don't have arbitrary control over the spectra we produce.  Fortunately, since we (usually) have only three cones, each of which produces only a scalar value, color vision can be reproduced by using exactly three primaries.  The bottom line is you can _produce any color sensation by using a linear combination of three wavelengths only_ (up to a few colors that might have to be negative, in which case, you just use different primaries).&#xD;&#xA;&#xD;&#xA;You don't have a choice of primaries.  Almost all color display devices use the sRGB standard, which provides three primaries (which actually usually don't have a single wavelength).  That's fine because it turns out it's all abstracted and you don't have to care.&#xD;&#xA;&#xD;&#xA;To clarify the mess that is perceptually accurate rendering, here's the algorithm:&#xD;&#xA;&#xD;&#xA;1. Render your image using correct radiometric calculations.  You trace individual wavelengths of light or buckets of wavelengths.  Whatever.  In the end, you have an image that has a representation of the spectrum received at every point.&#xD;&#xA;2. At each pixel, you take the spectrum you rendered, and convert it to the [CIE XYZ color space](https://en.wikipedia.org/wiki/CIE_1931_color_space).  This works out to be integrating the product of the spectrum with the [standard observer functions (see CIE XYZ definition)](https://en.wikipedia.org/wiki/CIE_1931_color_space#Color_matching_functions).&#xD;&#xA;3. This produces three scalar values, which are the CIE XYZ colors.&#xD;&#xA;4. [Use a matrix transform to convert this to linear RGB, and then from there use a linear/power transform to convert linear RGB to sRGB](https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29).&#xD;&#xA;5. Convert from floating point to uint8 and save, clamping values out of range (your monitor can't represent them).&#xD;&#xA;6. Send the uint8 pixels to the framebuffer.&#xD;&#xA;7. The display takes the sRGB colors, does the inverse transform to produce three primaries of particular intensities.  Each scales the output of whatever picture element it is responsible for.  The picture elements light up, producing a spectrum.  This spectrum will be (hopefully) a [metamer](https://en.wikipedia.org/wiki/Metamerism_%28color%29) for the original spectrum you rendered.&#xD;&#xA;8. You perceive the spectrum as you would have perceived the rendered spectrum.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Interpretation 2: Attempt to simulate the end data the human eye might receive for visualization purposes or compensation for LDR displays.**&#xD;&#xA;&#xD;&#xA;This one has a less useful meaning, I think.  Essentially, you're trying to produce an image that tweaks the way the brain perceives it for fun/profit.&#xD;&#xA;&#xD;&#xA;For example, there was a [paper at SIGGRAPH this year](http://graphics.stanford.edu/papers/gazehdr/) where they simulated afterimages and color reduction to make images appear perceptually different.  Of course, the only reason they do this at all is because the displays we're working with are all low-dynamic range (LDR).  The point is to simulate the effects someone might see if exposed to a real high-dynamic range (HDR) display as actual image data.&#xD;&#xA;&#xD;&#xA;In practice, this turns out to not work very well.  For afterimages, for example, we see afterimages because of a very bright stimulus exhausting color cells.  If you instead try to stimulate the effect with a fake afterimage, it might look kindof similar--but since it's a completely different mechanism, it's not very convincing.&#xD;&#xA;&#xD;&#xA;This sort of graphics is actually underexplored in the literature if you want to make a go at it.  The mentioned paper is an example of more-or-less the most state-of-the-art approaches we have.  I think the current consensus, though, is that it is not really worth trying to simulate (at least at this time), since at best you'd only be approximating real vision effects by substituting different ones, and that this doesn't really work.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;1&lt;/sup&gt;Rod+3*cones, the usual case.  Approximate because humans may have as few as zero functional light receptors up to a conjectured maximum of seven (with the highest ever observed being five)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2754" PostHistoryTypeId="2" PostId="1572" RevisionGUID="5e0b18d7-5861-4f87-8240-73235b035ce6" CreationDate="2015-10-05T09:16:15.527" UserId="182" Text="Display lists were an OpenGL feature that could, in theory, accelerate any part of the API by storing a group of commands for later use. In my understanding, this makes a lot of sense with regards to the current effort to reduce the driver overhead.&#xD;&#xA;&#xD;&#xA;Display lists were deprecated in version 3.1 though. What is the modern API equivalent and does DirectX expose a similar feature? If there is no such functionality anymore, what is the rationale?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2755" PostHistoryTypeId="1" PostId="1572" RevisionGUID="5e0b18d7-5861-4f87-8240-73235b035ce6" CreationDate="2015-10-05T09:16:15.527" UserId="182" Text="What is the modern equivalent of display lists?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2756" PostHistoryTypeId="3" PostId="1572" RevisionGUID="5e0b18d7-5861-4f87-8240-73235b035ce6" CreationDate="2015-10-05T09:16:15.527" UserId="182" Text="|opengl|display-lists|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2757" PostHistoryTypeId="2" PostId="1573" RevisionGUID="8892ec74-772a-4391-aa7c-b4e0ed9dd556" CreationDate="2015-10-05T09:30:15.083" UserId="137" Text="Nvidia has an [extension for creating command buffers in modern GL][1].&#xD;&#xA;&#xD;&#xA;The reason for the lack of similar functionality is that there is a lot of state involved regarding how to render and the display list be affected by a lot of different state.&#xD;&#xA;&#xD;&#xA;NVidia solved it by capturing *all* state and reseting to the state after a dispatch:&#xD;&#xA;&#xD;&#xA;&gt; 1) What motivates the design?&#xD;&#xA;&gt; &#xD;&#xA;&gt; The primary goal is to be able to reuse pre-validated command buffers.&#xD;&#xA;&gt; Other APIs and proposals have addressed this with various incarnations&#xD;&#xA;&gt; of command  lists or state objects, but a recurring problem is that&#xD;&#xA;&gt; interactions between various stages of the pipeline prevent this&#xD;&#xA;&gt; prevalidation and reuse. These  interactions are often&#xD;&#xA;&gt; hardware-specific (and differ from vendor to vendor  or even&#xD;&#xA;&gt; generation to generation) and new interactions are introduced by  new&#xD;&#xA;&gt; features that were not imagined when the prevalidation scheme was &#xD;&#xA;&gt; proposed.&#xD;&#xA;&gt; &#xD;&#xA;&gt; We attempt to address this by having a monolithic state object that &#xD;&#xA;&gt; encompasses (almost) the entire state of the pipeline. This should&#xD;&#xA;&gt; provide enough information for all implementations to do any needed&#xD;&#xA;&gt; cross- validation. We try to create these in a way that minimizes the&#xD;&#xA;&gt; new API  footprint - since we want ALL state (including any added in&#xD;&#xA;&gt; the future), we just capture it from the current state of the context.&#xD;&#xA;&gt; &#xD;&#xA;&gt; [...]&#xD;&#xA;&gt;&#xD;&#xA;&gt; 23) In what condition is the state left, that is modified by tokens,&#xD;&#xA;&gt; after the dispatch call?&#xD;&#xA;&gt; &#xD;&#xA;&gt; RESOLVED: state is reset.  &#xD;&#xA;&#xD;&#xA;(from the extension text linked above)&#xD;&#xA;&#xD;&#xA;However the true successor is the command buffer functionality in DX12 and vulkan. Those will also capture all render state into a single object to use when creating and filling the command buffer. The NVidia extension is based on that architecture as a result of its involvement in the Vulkan design.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/opengl/specs/GL_NV_command_list.txt&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2758" PostHistoryTypeId="5" PostId="1573" RevisionGUID="7a8b93cd-7bd5-4e15-b85f-4df710c2e68b" CreationDate="2015-10-05T12:46:08.927" UserId="137" Comment="added 5 characters in body" Text="Nvidia has an [extension for creating command buffers in modern GL][1].&#xD;&#xA;&#xD;&#xA;The reason for the lack of similar functionality is that there is a lot of state involved regarding how to render and the display list be affected by a lot of different state.&#xD;&#xA;&#xD;&#xA;NVidia solved it by capturing *all* state and reseting to the state after a dispatch:&#xD;&#xA;&#xD;&#xA;&gt; 1) What motivates the design?&#xD;&#xA;&gt; &#xD;&#xA;&gt; The primary goal is to be able to reuse pre-validated command buffers.&#xD;&#xA;&gt; Other APIs and proposals have addressed this with various incarnations&#xD;&#xA;&gt; of command  lists or state objects, but a recurring problem is that&#xD;&#xA;&gt; interactions between various stages of the pipeline prevent this&#xD;&#xA;&gt; prevalidation and reuse. These  interactions are often&#xD;&#xA;&gt; hardware-specific (and differ from vendor to vendor  or even&#xD;&#xA;&gt; generation to generation) and new interactions are introduced by  new&#xD;&#xA;&gt; features that were not imagined when the prevalidation scheme was &#xD;&#xA;&gt; proposed.&#xD;&#xA;&gt; &#xD;&#xA;&gt; We attempt to address this by having a monolithic state object that &#xD;&#xA;&gt; encompasses (almost) the entire state of the pipeline. This should&#xD;&#xA;&gt; provide enough information for all implementations to do any needed&#xD;&#xA;&gt; cross- validation. We try to create these in a way that minimizes the&#xD;&#xA;&gt; new API  footprint - since we want ALL state (including any added in&#xD;&#xA;&gt; the future), we just capture it from the current state of the context.&#xD;&#xA;&gt; &#xD;&#xA;&gt; [...]&#xD;&#xA;&gt;&#xD;&#xA;&gt; 23) In what condition is the state left, that is modified by tokens,&#xD;&#xA;&gt; after the dispatch call?&#xD;&#xA;&gt; &#xD;&#xA;&gt; RESOLVED: state is reset.  &#xD;&#xA;&#xD;&#xA;(from the extension text linked above)&#xD;&#xA;&#xD;&#xA;However the true successor is the command buffer functionality in DX12 and vulkan. Those will also capture all render state into a single object to use when creating and filling the command buffer. The NVidia extension is based on that architecture as a result of NVidia's involvement in the Vulkan design.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/opengl/specs/GL_NV_command_list.txt&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2759" PostHistoryTypeId="2" PostId="1574" RevisionGUID="1bbb7e58-21c2-4c8d-a3e4-0f7d28f9a3da" CreationDate="2015-10-05T14:41:15.337" UserId="1800" Text="I'd like to know (if it is possible), how I would go about getting at the rendered scene from an application.&#xD;&#xA;&#xD;&#xA;For example, say I am using some 3D modelling tool (eg Blender, 3DS Max, Maya) and I have my model (eg a coffee mug that rotates constantly). Rendering has completed and the 3d model (The output from the 3D modelling application) is running remotely (perhaps on AWS EC2) and so this coffee mug is rotating... &#xD;&#xA;&#xD;&#xA;If I were to log into the remote server using some remote desktop application, I'd see the cup rotating, however, I'd like to rather grab the output from that application and stream it to my laptop (or another client).&#xD;&#xA;&#xD;&#xA;I know of NVidia's AppStream, but I'd like to know how to get at that rendered on the remote server?&#xD;&#xA;&#xD;&#xA;I realise my question may seem vague (possibly even not making sense), but I'm very new to this and so any help or pointers would be great.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2760" PostHistoryTypeId="1" PostId="1574" RevisionGUID="1bbb7e58-21c2-4c8d-a3e4-0f7d28f9a3da" CreationDate="2015-10-05T14:41:15.337" UserId="1800" Text="Accessing rendered data from an appliation" ContentLicense="CC BY-SA 3.0" />
  <row Id="2761" PostHistoryTypeId="3" PostId="1574" RevisionGUID="1bbb7e58-21c2-4c8d-a3e4-0f7d28f9a3da" CreationDate="2015-10-05T14:41:15.337" UserId="1800" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2762" PostHistoryTypeId="2" PostId="1575" RevisionGUID="f9554d14-e5d3-43bd-9a6a-538da5ccb6e1" CreationDate="2015-10-05T17:05:33.907" UserId="310" Text="I think you're confused on how rendering and animation work. &#xD;&#xA;&#xD;&#xA;A traditional model is nothing more than a bunch of triangles. So a model file coming from say Blender, etc. is just a list of vertices for the triangles. (with some added stuff if you want)&#xD;&#xA;&#xD;&#xA;Rendering takes the scene definition and transforms a 3D scene (aka the models oriented somewhere in space) and creates a 2D picture.&#xD;&#xA;&#xD;&#xA;Animation creates the illusion of movement by showing static pictures very fast (24 frames per second or more). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Therefore, to have a spinning mug, your application would render each frame, then present them, at, say 30 fps.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, to stream the data, you can take two paths:&#xD;&#xA;&#xD;&#xA; 1. Render each frame on the server and stream them to the client with something like H.264&#xD;&#xA; 2. Stream the graphics commands to the client, and let them render them.&#xD;&#xA;&#xD;&#xA;The first option is what something like OBS or Fraps and (maybe) Nvidia GameStream is doing. &#xD;&#xA;There's a paper that covers the 2nd option [here][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.informatik.hu-berlin.de/de/forschung/gebiete/viscom/papers/icip08a.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2763" PostHistoryTypeId="5" PostId="1574" RevisionGUID="da750578-47f2-4260-a6e0-5862df252000" CreationDate="2015-10-05T18:19:44.533" UserId="1800" Comment="added 26 characters in body" Text="I'd like to know (if it is possible), how I would go about getting at the rendered frames from an application.&#xD;&#xA;&#xD;&#xA;For example, say I am using some 3D modelling tool (eg Blender, 3DS Max, Maya) and I have my model (eg a coffee mug that rotates constantly). Animation rendering has completed remotely (perhaps on AWS EC2) and so this coffee mug is rotating... &#xD;&#xA;&#xD;&#xA;If I were to log into the remote server using some remote desktop application, I'd see the cup rotating, however, I'd like to rather grab the output from that application (the frames) and stream it to my laptop (or another client).&#xD;&#xA;&#xD;&#xA;I know of NVidia's AppStream, but I'd like to know how to get at that rendered frames on the remote server and pipe them to a client, without using some remote desktop software.&#xD;&#xA;&#xD;&#xA;I realise my question may seem vague (possibly even not making sense), but I'm very new to this and so any help or pointers would be great.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2764" PostHistoryTypeId="4" PostId="1574" RevisionGUID="cc005875-10ea-4e0c-ad96-8c41c863426b" CreationDate="2015-10-05T18:35:52.187" UserId="48" Comment="edit title to better reflect question" Text="How to capture rendered frames from an application and stream over network" ContentLicense="CC BY-SA 3.0" />
  <row Id="2765" PostHistoryTypeId="6" PostId="1574" RevisionGUID="cc005875-10ea-4e0c-ad96-8c41c863426b" CreationDate="2015-10-05T18:35:52.187" UserId="48" Comment="edit title to better reflect question" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2766" PostHistoryTypeId="5" PostId="1569" RevisionGUID="5c5bff38-aff9-4f1b-a41f-e82fc4f06632" CreationDate="2015-10-05T20:55:39.827" UserId="310" Comment="Added a section explaining the additional difficulties of implementing a modern BRDF, as suggested by @NathanReed" Text="As mentioned in [this][1] answer, Physically-Based Rendering isn't a set number of things. It's a *concept*. It's akin to saying something is 'Environmentally Friendly'. There are many different techniques to be environmentally friendly *and* someone can implement those techniques to varying degrees. The same is for PBR.&#xD;&#xA;&#xD;&#xA;In the end, Physically Based Rendering is just that, based on Physics in some way, shape, or form. One of the most basic 'physical' rendering techniques I can think of is using [Lambert shading][2]. While you may say, &quot;Well that doesn't take into account specular light, or etc, etc. etc.&quot;, I agree. Lambert shading is a crude representation of the physics of light. But, pedantically, it *is* PBR, because it is based off the physical observation that light intensity decreases with viewing angle.&#xD;&#xA;&#xD;&#xA;A renderer can implement as many, or as few PBR techniques as they choose. Some can be very computationally expensive, others, quite cheap. They can also choose to enable or disable certain techniques for different targets. For example, UE4 has a different set of techniques for mobile games, than for high end PC games. &#xD;&#xA;&#xD;&#xA;Now, that all said, when today's modern renderers talk about being &quot;Physically-based&quot;, they are generally referring to using a modern BRDF, generally some form of [Cook-Torrance][3], and physically plausible inputs. Inputs being: materials with physically-plausible color values and lights with physically based intensity values. &#xD;&#xA;&#xD;&#xA;Using a modern BRDF can be very computationally expensive, but, there are many approximations that can make it more friendly.&#xD;&#xA;&#xD;&#xA;Using physically-plausible inputs is generally not that difficult to implement on the renderer side, rather it's more difficult for artists. IE. teaching them what the different material values mean, and what are physically plausible values. This can be a huge task, depending on your artists, as seen in the presentations [here][4], [here][5], and [here][6], for example. In my opinion, this is the hardest task in switching a studio.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;One last issue, as brought up by @NathanReed in the comments:&#xD;&#xA;&#xD;&#xA;Implementing a modern BRDF in the shader doesn't necessarily immediately make the rendering better. In many cases, it can make other parts of the pipeline a glaring issue. Below are some additional things that are important in getting the most out of a modern BRDF:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - HDR lights and doing all rendering calculations in HDR&#xD;&#xA; - Gamma correct rendering&#xD;&#xA; - Indirect lighting of some kind (skybox lighting, static environment probes, screen space reflections, etc)&#xD;&#xA;   - This is huge for metals. [Metals have no diffuse reflectance][7], so most of the surface of the metal will be black if you don't have indirect reflections&#xD;&#xA;   - This is also one of the more difficult things to get real-time, especially for dynamic scenes. &#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/a/1468/310&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;  [3]: http://ruh.li/GraphicsCookTorrance.html&#xD;&#xA;  [4]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [5]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf&#xD;&#xA;  [6]: http://www.slideshare.net/guerrillagames/lighting-of-killzone-shadow-fall&#xD;&#xA;  [7]: http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2768" PostHistoryTypeId="2" PostId="1576" RevisionGUID="f3e4b434-3b99-4186-9703-ad8f5264f3f9" CreationDate="2015-10-06T02:53:06.210" UserId="182" Text="I see mainly three ways of computing normals for a generated shape.&#xD;&#xA;&#xD;&#xA;#Analytic normals&#xD;&#xA;&#xD;&#xA;In some cases you have enough information about the surface to generate the normals. For example, the normal of any point on a sphere is trivial to compute. Put simply, when you know the derivative of the function, you also know the normal.&#xD;&#xA;&#xD;&#xA;If your case is narrow enough to allow you to use analytic normals, they will probably give the best result in terms of precision. The technique doesn't scale too well though: if you also need to handle cases where you cannot use analytic normals, it may be easier to keep the technique that handles the general case and drop the analytic one altogether.&#xD;&#xA;&#xD;&#xA;#Vertex normals&#xD;&#xA;&#xD;&#xA;The cross product of two vectors gives a vector perpendicular to the plane they belong to. So getting the normal of a triangle is straightforward:&#xD;&#xA;&#xD;&#xA;    vec3 computeNormal(vec3 a, vec3 b, vec3 c)&#xD;&#xA;    {&#xD;&#xA;        return normalize(crossProduct(b - a, c - a));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Moreover, in the above example, the length of the cross product is proportional to the area inside _abc_. So the smoothed normal at a vertex shared by several triangles can be computed by summing up the cross products and normalizing as a last step, thus weighting each triangle by its area.&#xD;&#xA;&#xD;&#xA;    vec3 computeNormal(vertex a)&#xD;&#xA;    {&#xD;&#xA;        vec3 sum = vec3(0, 0, 0);&#xD;&#xA;        list&lt;vertex&gt; adjacentVertices = getAdjacentVertices(a);&#xD;&#xA;        for (int i = 1; i &lt; adjacentVertices; ++i)&#xD;&#xA;        {&#xD;&#xA;            vec3 b = adjacentVertices[i - 1];&#xD;&#xA;            vec3 c = adjacentVertices[i];&#xD;&#xA;            sum += crossProduct(b - a, c - a);&#xD;&#xA;        }&#xD;&#xA;        if (norm(sum) == 0)&#xD;&#xA;        {&#xD;&#xA;            // Degenerate case&#xD;&#xA;            return sum;&#xD;&#xA;        }&#xD;&#xA;        return normalize(sum);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are working with quads, there is a nice trick you can use: for a quad _abcd_, use `crossProduct(c - a, b -b)` and it will handle nicely cases where the quad is in fact a triangle.&#xD;&#xA;&#xD;&#xA;Iñigo quilez wrote a few short articles on the topic: [clever normalization of a mesh](http://www.iquilezles.org/www/articles/normals/normals.htm), and [normal and area of n sided polygons](http://iquilezles.org/www/articles/areas/areas.htm).&#xD;&#xA;&#xD;&#xA;#Normals from partial derivatives&#xD;&#xA;&#xD;&#xA;Normals can be computed in the fragment shader from the partial derivatives. The math behind is the same, except this time it is done in screen space. This article by Angelo Pesce describes the technique: [Normals without normals](http://c0de517e.blogspot.jp/2008/10/normals-without-normals.html).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2772" PostHistoryTypeId="2" PostId="1578" RevisionGUID="489bcde2-f19d-4d89-8c84-2fa94b2ddfc3" CreationDate="2015-10-06T06:56:25.257" UserId="182" Text="In the section _6.4 Constant Buffers_ of the book [_Practical Rendering &amp; Computation with Direct3D 11_](http://www.amazon.com/dp/B00DIKUB7G) (pages 325, 326) it is mentioned:&#xD;&#xA;&gt; By default, the HLSL compiler will attempt to align constants such that they don't span multiple float4 registers. [...] The packing for an HLSL constant buffer can also be manually specified through the packoffset keyword.&#xD;&#xA;&#xD;&#xA;I assume a similar rule will apply to the OpenGL equivalent, Uniform Buffer Objects, since they map to the same hardware feature.&#xD;&#xA;&#xD;&#xA;What about vanilla uniforms though? What are the rules that apply when declaring uniforms?&#xD;&#xA;&#xD;&#xA;    uniform vec2 xy; // Can we expect the compiler to pack xy&#xD;&#xA;    uniform vec2 zw; // into a same four component register?&#xD;&#xA;&#xD;&#xA;    uniform vec2 rg;&#xD;&#xA;    uniform float foo; // Will this prevent from packing rg and ba?&#xD;&#xA;    uniform vec2 ba;   // If so, will foo eat up a full four components register?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If the compiler can do such optimizations, how good are they? Can we explicitly tell the compiler to pack or not, and when should we?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2773" PostHistoryTypeId="1" PostId="1578" RevisionGUID="489bcde2-f19d-4d89-8c84-2fa94b2ddfc3" CreationDate="2015-10-06T06:56:25.257" UserId="182" Text="Do the alignement and declaration order of uniforms matter?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2774" PostHistoryTypeId="3" PostId="1578" RevisionGUID="489bcde2-f19d-4d89-8c84-2fa94b2ddfc3" CreationDate="2015-10-06T06:56:25.257" UserId="182" Text="|opengl|directx11|constant-buffer|uniform-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2776" PostHistoryTypeId="2" PostId="1579" RevisionGUID="b9afea3b-a9e6-40c1-9f3f-8c05ad4b4c7f" CreationDate="2015-10-06T10:43:35.327" UserId="1792" Text="Raytracing &quot;sees&quot; the pixel on the other side of the screen;&#xD;&#xA;but doesn't this mean the rays traced can be computationally reflected and refracted imitating the properties of actual light?&#xD;&#xA;&#xD;&#xA;It'd be exciting if it were possible. Any visual scene possible outside computer graphics will be possible just using physics equations." ContentLicense="CC BY-SA 3.0" />
  <row Id="2777" PostHistoryTypeId="1" PostId="1579" RevisionGUID="b9afea3b-a9e6-40c1-9f3f-8c05ad4b4c7f" CreationDate="2015-10-06T10:43:35.327" UserId="1792" Text="Can raytracing be used to imitate the behavior of light to a higher degree?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2778" PostHistoryTypeId="3" PostId="1579" RevisionGUID="b9afea3b-a9e6-40c1-9f3f-8c05ad4b4c7f" CreationDate="2015-10-06T10:43:35.327" UserId="1792" Text="|raytracing|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2784" PostHistoryTypeId="2" PostId="1581" RevisionGUID="65b9fbe6-914b-4230-af9f-e0c22e4da892" CreationDate="2015-10-06T15:50:25.017" UserDisplayName="user1806" Text="Computer graphics files are in Windows rendered by components such as the [Graphics Device Interface][1] and [Direct2D][2].&#xD;&#xA;&#xD;&#xA;Is it possible to create a graphic file that, besides displaying a graphic also utilizes custom code inside the graphic file?&#xD;&#xA;&#xD;&#xA;With custom code I am referring to functionality such as:&#xD;&#xA;&#xD;&#xA; 1. Incrementing a counter or date that is displayed on the graphic.&#xD;&#xA; 2. Accessing a web URL to retrieve data that is displayed on the graphic.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Graphics_Device_Interface&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Direct2D" ContentLicense="CC BY-SA 3.0" />
  <row Id="2785" PostHistoryTypeId="1" PostId="1581" RevisionGUID="65b9fbe6-914b-4230-af9f-e0c22e4da892" CreationDate="2015-10-06T15:50:25.017" UserDisplayName="user1806" Text="To what degree, if at all, can custom code be embedded in a PNG, GIF, or JPG?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2786" PostHistoryTypeId="3" PostId="1581" RevisionGUID="65b9fbe6-914b-4230-af9f-e0c22e4da892" CreationDate="2015-10-06T15:50:25.017" UserDisplayName="user1806" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2787" PostHistoryTypeId="2" PostId="1582" RevisionGUID="cbff564e-2457-447a-b1af-bac3f70e7cbf" CreationDate="2015-10-06T15:52:54.030" UserId="1801" Text="I went looking for an answer, so I downloaded AMD's shader analyzer to view the assembly produced when compiled for GCN. In the assembly below vector registers are v# and scalar registers are s#.&#xD;&#xA;&#xD;&#xA;It would appear that the uniforms even vector uniforms are passed into the shader as separate scalars, so a vec3 would use 3 scalar registers. The bit I found confusing was the v0 to v4, I'm not sure if v0 is a full 4 float register or a single float in a register, with a full vector register spanning v0 to v3. One way or another it didn't appear to change between the two versions so I can assume the definition order didn't affect the assembly.&#xD;&#xA; &#xD;&#xA;http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/07/AMD_GCN3_Instruction_Set_Architecture.pdf&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    uniform vec2 xy; &#xD;&#xA;    uniform vec2 zw;&#xD;&#xA;     &#xD;&#xA;    out vec4 v;&#xD;&#xA;    &#xD;&#xA;    void main(){ &#xD;&#xA;    	v.xy = xy; &#xD;&#xA;    	v.zw = zw; &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    shader &#xD;&#xA;      asic(VI)&#xD;&#xA;      type(VS)&#xD;&#xA;    &#xD;&#xA;      v_cndmask_b32  v0, s0, v0, vcc               &#xD;&#xA;      v_mov_b32     v0, 0                          &#xD;&#xA;      v_mov_b32     v1, 1.0                        &#xD;&#xA;      exp           pos0, v0, v0, v0, v1 done      &#xD;&#xA;      s_andn2_b32   s0, s5, 0x3fff0000             &#xD;&#xA;      s_mov_b32     s1, s0                         &#xD;&#xA;      s_mov_b32     s2, s6                         &#xD;&#xA;      s_mov_b32     s3, s7                         &#xD;&#xA;      s_mov_b32     s0, s4                         &#xD;&#xA;      s_buffer_load_dwordx2  s[4:5], s[0:3], 0x00  &#xD;&#xA;      s_buffer_load_dwordx2  s[0:1], s[0:3], 0x10  &#xD;&#xA;      s_waitcnt     expcnt(0) &amp; lgkmcnt(0)         &#xD;&#xA;      v_mov_b32     v0, s4                         &#xD;&#xA;      v_mov_b32     v1, s5                         &#xD;&#xA;      v_mov_b32     v2, s0                         &#xD;&#xA;      v_mov_b32     v3, s1                         &#xD;&#xA;      exp           param0, v0, v1, v2, v3         &#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    uniform vec2 xy;&#xD;&#xA;    uniform float z;&#xD;&#xA;    uniform vec2 zw;&#xD;&#xA;     &#xD;&#xA;    out vec4 v;&#xD;&#xA;    &#xD;&#xA;    void main(){ &#xD;&#xA;    	v.xy = xy; &#xD;&#xA;    	v.zw = zw;&#xD;&#xA;    	v.w += z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    shader &#xD;&#xA;      asic(VI)&#xD;&#xA;      type(VS)&#xD;&#xA;    &#xD;&#xA;      v_cndmask_b32  v0, s0, v0, vcc              &#xD;&#xA;      v_mov_b32     v0, 0                         &#xD;&#xA;      v_mov_b32     v1, 1.0                       &#xD;&#xA;      s_andn2_b32   s0, s5, 0x3fff0000            &#xD;&#xA;      exp           pos0, v0, v0, v0, v1 done     &#xD;&#xA;      s_mov_b32     s1, s0                        &#xD;&#xA;      s_mov_b32     s2, s6                        &#xD;&#xA;      s_mov_b32     s3, s7                        &#xD;&#xA;      s_mov_b32     s0, s4                        &#xD;&#xA;      s_buffer_load_dword  s4, s[0:3], 0x10       &#xD;&#xA;      s_buffer_load_dwordx2  s[6:7], s[0:3], 0x00 &#xD;&#xA;      s_buffer_load_dwordx2  s[0:1], s[0:3], 0x20 &#xD;&#xA;      s_waitcnt     expcnt(0) &amp; lgkmcnt(0)        &#xD;&#xA;      v_mov_b32     v0, s4                        &#xD;&#xA;      v_add_f32     v0, s1, v0                    &#xD;&#xA;      v_mov_b32     v1, s6                        &#xD;&#xA;      v_mov_b32     v2, s7                        &#xD;&#xA;      v_mov_b32     v3, s0                        &#xD;&#xA;      exp           param0, v1, v2, v3, v0        &#xD;&#xA;    end" ContentLicense="CC BY-SA 3.0" />
  <row Id="2789" PostHistoryTypeId="5" PostId="1551" RevisionGUID="49c29579-d934-48de-82b1-f9eca351b62e" CreationDate="2015-10-06T17:38:11.333" UserId="209" Comment="added 1483 characters in body" Text="**[NOTE: I apologise that this is still unfinished]**&#xD;&#xA;&#xD;&#xA;*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;### Requirements ###&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/).&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should thus also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware (and power) costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset of the texels come from, say, the middle of the image, you also don't want to have to decode all of the 'previous' lines of texture in order to work out what those texels are; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample &quot;willy-nilly&quot;](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (...but I will admit that compression of PVRTC, ETC2 and some others at max-quality could be faster!)&#xD;&#xA;&#xD;&#xA;### Early History &amp; Techniques ###&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days where even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or, cough, patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;### Modelling Image Data ###&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;### PC and (post mid 90s) Console Texture compression ###&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;#### *VQ with larger vectors*&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;#### *Colour Space Transformations*&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;#### *BTC-based schemes*&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data. In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;*S3TC*:&#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is S3TC, much of which, ironically, was a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119).&#xD;&#xA;&#xD;&#xA;In S3TC each 4x4 block is replaced by two end colours, *A* and *B*, and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. As an example the following is a 4x4 pixel section of the example image compressed with the AMD/ATI Compressenator tool. (Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update it).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis along with two 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;*ETC1*:&#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour.&#xD;&#xA;&#xD;&#xA;[Still saving as a work in progress...]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2790" PostHistoryTypeId="2" PostId="1583" RevisionGUID="bf657a90-f07e-431c-9927-2510b3493c37" CreationDate="2015-10-06T19:25:49.710" UserId="1810" Text="complement: &#xD;&#xA;&#xD;&#xA;homogeneous coordinates also allows to represent infinity: (x,y, z, 0) = (x,y,z)/0 in 3D, i.e., the point at infinity in direction x,y,z. TYpically, light sources at finite or infinite position can be represented the same way.&#xD;&#xA;&#xD;&#xA;About perspective transform, it even allows to interpolate correctly with no perspective distortion (contrary to early graphics hardware on PC )." ContentLicense="CC BY-SA 3.0" />
  <row Id="2791" PostHistoryTypeId="2" PostId="1584" RevisionGUID="eb4d39e1-61bd-48fe-9183-e3cb9281da71" CreationDate="2015-10-06T19:49:41.333" UserId="273" Text="Raytracing is one of the techniques that trace the light as it moves through the scene.&#xD;&#xA;This can, depending on the implementation, also include effects such as refraction, reflection and scattering.&#xD;&#xA;&#xD;&#xA;Raytracing and similar techniques (see Monte-Carlo Pathtracing for example) all are based on the idea to solve the so called rendering equation.&#xD;&#xA;The equation is a long known equation that describes the physically correct amount of light we can see for at each point (this means mathematical infinitesimal point, not pixel!).&#xD;&#xA;By (approximally) solving this equation the mentioned rendering techniques are indeed able to render &quot;all&quot; scenes. The only real limiting factors are that it is hard to solve the equation for some effects and the huge amount of computation you need to solve it." ContentLicense="CC BY-SA 3.0" />
  <row Id="2793" PostHistoryTypeId="2" PostId="1585" RevisionGUID="26a58299-9711-445f-9df3-bdcb8d0e0c1a" CreationDate="2015-10-06T22:06:01.717" UserDisplayName="user1703" Text="You are late by about 35 years. This was addressed in the historical paper &quot;Whitted, T., An improved illumination model for shaded display. Communications of the ACM, Volume 23 Issue 6, June 1980, Pages 343-349&quot;, using  ray tracing.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qKlTI.jpg&#xD;&#xA;&#xD;&#xA;Since then radiosity has been introduced to better deal with diffuse phenomena. Correct physical modeling of the image formation process was discussed six years later in the seminal &quot;Kajiya, James T. (1986), &quot;The rendering equation&quot;, Siggraph 1986: 143&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="2794" PostHistoryTypeId="2" PostId="1586" RevisionGUID="8191a038-955d-4edc-839f-8d22b7a441c9" CreationDate="2015-10-06T22:34:12.600" UserId="48" Text="Common graphics formats such as JPEG, PNG and GIF are not designed to have any form of code inside them. They just store a compressed array of pixels&amp;mdash;they can't generate anything on command or contact a web service, etc.&#xD;&#xA;&#xD;&#xA;(There have occasionally been vulnerabilities discovered in image decoders, that would allow a maliciously constructed image to cause code execution when viewed, via a buffer overflow exploit or similar. But this is of course not part of the design of the format.)&#xD;&#xA;&#xD;&#xA;Some vector graphics formats such as EPS and SVG actually do allow embedding code. However, being vector formats instead of bitmap ones, these formats often aren't supported by ordinary image viewers (although SVG is supported by browsers), and can't be edited in ordinary paint programs. One needs specialized vector graphics programs to work with them.&#xD;&#xA;&#xD;&#xA;In order to generate an image that updates with new data, you could create a web service that regenerates the image on the server each time it's requested. However, if a client caches the resulting image rather than re-requesting it each time it's viewed, they would see old data." ContentLicense="CC BY-SA 3.0" />
  <row Id="2795" PostHistoryTypeId="2" PostId="1587" RevisionGUID="b2e4ff39-e11b-43f0-88de-85bbce282a22" CreationDate="2015-10-07T00:07:08.770" UserId="1812" Text="In this video https://www.youtube.com/watch?v=LKnqECcg6Gw from about 1:15 it is stated that if you have an RGB value of (0.5,0.5,0.5) it is only 22% as bright as (1,1,1) rather than the expected 50% as bright.&#xD;&#xA;&#xD;&#xA;Does this mean that RGB is adjusted for a logarithmic scale so that we perceive the (0.5,0.5,0.5) to be half as bright or have a misunderstood the video?&#xD;&#xA;&#xD;&#xA;Despite searching around a lot I can not find any other source of information that discusses this.&#xD;&#xA;&#xD;&#xA;Thanks heaps!" ContentLicense="CC BY-SA 3.0" />
  <row Id="2796" PostHistoryTypeId="1" PostId="1587" RevisionGUID="b2e4ff39-e11b-43f0-88de-85bbce282a22" CreationDate="2015-10-07T00:07:08.770" UserId="1812" Text="Actual vs Perceived Brightness of RGB Colour" ContentLicense="CC BY-SA 3.0" />
  <row Id="2797" PostHistoryTypeId="3" PostId="1587" RevisionGUID="b2e4ff39-e11b-43f0-88de-85bbce282a22" CreationDate="2015-10-07T00:07:08.770" UserId="1812" Text="|color|brightness|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2798" PostHistoryTypeId="2" PostId="1588" RevisionGUID="e26d707f-6f52-4175-8aef-1de1330bb658" CreationDate="2015-10-07T02:46:58.663" UserId="182" Text="Two different effects are causing the observation mentioned in the video.&#xD;&#xA;&#xD;&#xA;On one side, the vast majority of screens have a non linear response: if the RGB value is half as much, the emitted light intensity is not half as much. This behavior originally comes from [cathode ray tube (CRT)][1] displays, which produced different light intensities by varying the voltage used to generate the electron beam. From the article:&#xD;&#xA;&gt; CRTs have a pronounced triode characteristic, which results in significant gamma (a nonlinear relationship in an electron gun between applied video voltage and beam intensity).&#xD;&#xA;&#xD;&#xA;As CRT became ubiquitous, systems assumed this behavior to be present and took it into account. Nowadays CRT have mostly been replaced by LCD technology, which emulate this behavior for compatibility.&#xD;&#xA;&#xD;&#xA;Gamma is usually considered to be around 2.2, which means the light intensity follows a function _I=pow(x, 2.2)_. This is where the 22% mentioned in the video comes from: _pow(0.5, 2.2) ~= 0.218_.&#xD;&#xA;&#xD;&#xA;On the other side, the human vision is not linear either. [According to Wikipedia][2], a typical sunset on a clear day is about 400 lux, and clear sky daylight is about 10000 to 25000 lux. Yet the latter doesn't feel over 25 times as bright as the former.&#xD;&#xA;&#xD;&#xA;In the end, the non linear response of screens is a good thing, because it gives more precision where it is needed. Note that it is not logarithmic though, but closer to a square function. If you want to read more on the topic, you can look for articles on _&quot;gamma correction&quot;_.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cathode_ray_tube&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lux#Illuminance" ContentLicense="CC BY-SA 3.0" />
  <row Id="2800" PostHistoryTypeId="4" PostId="1566" RevisionGUID="50fd7a45-4ba1-4053-b513-6f5f6cc96994" CreationDate="2015-10-07T07:13:04.297" UserId="231" Comment="edited title" Text="Help me find out what this texture mapping technique is called" ContentLicense="CC BY-SA 3.0" />
  <row Id="2801" PostHistoryTypeId="5" PostId="1564" RevisionGUID="14fb8110-9045-4b76-a4c6-55fe37f75089" CreationDate="2015-10-07T07:15:14.157" UserId="231" Comment="Typos and clarity" Text="I have a shader which has several uniform variables:&#xD;&#xA;&#xD;&#xA;    uniform vec4 a;&#xD;&#xA;    uniform vec4 b;&#xD;&#xA;    uniform vec4 c;&#xD;&#xA;   &#xD;&#xA;I'm getting these handles using `glGetUniformLocation()` and storing them in the array. The game was suspended, then resumed and [onSurfaceCreated()][1] has been called. The question is: whether these handles will be valid or I need to re-get them using `glGetUniformLocation()` once again?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="2802" PostHistoryTypeId="5" PostId="1560" RevisionGUID="e338fdc6-33e1-4dc9-9b31-94d741ef5dd4" CreationDate="2015-10-07T07:53:43.003" UserId="231" Comment="Minor typos" Text="RGB color is a bit more complicated a subject than readily seems apparent. The reflectance wavelength diagram shows the reason quite well actually.&#xD;&#xA;&#xD;&#xA;RGB color model has several central problems:&#xD;&#xA;&#xD;&#xA;* What the colors represent: They represent 3 spikes in a continuous spectrum. The R, G and B aren't energetically equivalent let alone evenly spaced.&#xD;&#xA;* What their range is: The colors do not actually mean anything without information of what space they span. In the assumed sRGB color space the space does not span the entire sensable range. So energetically equal but more vivid colors exist.&#xD;&#xA;* Human sensory apparatus isn't actually reading 3 color spikes but the sensors nonlinearly overlap.&#xD;&#xA;&#xD;&#xA;As a result one can not draw the conclusion that a reflectance color channel of greater than 1 automatically means that energy is inserted into the system. That is simply one of the possible interpretations. &#xD;&#xA;&#xD;&#xA;Another interpretation is that the color is more intense than your color space allows. As a result your color vector component could be over 1.&#xD;&#xA;&#xD;&#xA;Human eyes may also bleed color from one sensor to another due to overlap of the sensors. Such things happen with the sky which seems light blue, but is actually far darker blue but so intense that we see it as light blue. But in 50% reflections it would look wrong if we wouldn't account for this.&#xD;&#xA;&#xD;&#xA;In the end, it can also mean energy is inserted into the system. Either the energy comes from elsewhere or is generated by the surface.&#xD;&#xA;&#xD;&#xA;Rendering is often not a scientific measure of things. No energy principle needs to be broken to achieve this.&#xD;&#xA;&#xD;&#xA;### Summa summarum (tl;dr)&#xD;&#xA;&#xD;&#xA;Color is often a compound attribute at the same time as it measures energy levels it also measures something other. Namely the location in the color space. Thus you can not differentiate the two signals (energy and color intensity) easily.&#xD;&#xA;&#xD;&#xA;In this case it is a more intense color because the source says so: Outside of sRGB gamut = more intense color than the color space can make." ContentLicense="CC BY-SA 3.0" />
  <row Id="2804" PostHistoryTypeId="5" PostId="1587" RevisionGUID="0c64fdb5-5ca2-41c3-9ed2-225f6f34d8bc" CreationDate="2015-10-07T08:36:47.367" UserId="54" Comment="Fixed formatting of the external link. Removed last &quot;thanks&quot; sentence." Text="[In this video](https://www.youtube.com/watch?v=LKnqECcg6Gw) from about 1:15, it is stated that if you have an RGB value of (0.5,0.5,0.5) it is only 22% as bright as (1,1,1) rather than the expected 50% as bright.&#xD;&#xA;&#xD;&#xA;Does this mean that RGB is adjusted for a logarithmic scale so that we perceive the (0.5,0.5,0.5) to be half as bright, or have a misunderstood the video?&#xD;&#xA;&#xD;&#xA;Despite searching around a lot I can not find any other source of information that discusses this." ContentLicense="CC BY-SA 3.0" />
  <row Id="2805" PostHistoryTypeId="24" PostId="1587" RevisionGUID="0c64fdb5-5ca2-41c3-9ed2-225f6f34d8bc" CreationDate="2015-10-07T08:36:47.367" Comment="Proposed by 54 approved by 38, 231 edit id of 60" ContentLicense="CC BY-SA 3.0" />
  <row Id="2806" PostHistoryTypeId="2" PostId="1589" RevisionGUID="ff71a80a-0637-402c-8183-2c4bc0afeb72" CreationDate="2015-10-07T08:36:55.203" UserId="1800" Text="Say I am running a game in the cloud and I am playing that game on my client, be it a laptop, phone or calculator.&#xD;&#xA;&#xD;&#xA;How can I work out how long a frame (of the game being played) takes to arrive at the client?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2807" PostHistoryTypeId="1" PostId="1589" RevisionGUID="ff71a80a-0637-402c-8183-2c4bc0afeb72" CreationDate="2015-10-07T08:36:55.203" UserId="1800" Text="Measure how long a rendered frame takes to arrive on a client from the cloud" ContentLicense="CC BY-SA 3.0" />
  <row Id="2808" PostHistoryTypeId="3" PostId="1589" RevisionGUID="ff71a80a-0637-402c-8183-2c4bc0afeb72" CreationDate="2015-10-07T08:36:55.203" UserId="1800" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2809" PostHistoryTypeId="5" PostId="1551" RevisionGUID="143096d7-3e70-440a-9ce9-c9e6981b9b20" CreationDate="2015-10-07T08:54:35.380" UserId="209" Comment="Adding more example images." Text="**[NOTE: I apologise that this is still unfinished]**&#xD;&#xA;&#xD;&#xA;*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data. In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;_S3TC_:  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is S3TC, much of which, ironically, was a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119).&#xD;&#xA;&#xD;&#xA;In S3TC each 4x4 block is replaced by two end colours, *A* and *B*, and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. As an example the following is a 4x4 pixel section of the example image compressed with the AMD/ATI Compressenator tool. (Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update it).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis along with two 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour.&#xD;&#xA;&#xD;&#xA;[Still saving as a work in progress...]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2810" PostHistoryTypeId="2" PostId="1590" RevisionGUID="bcc2f7ed-1727-40d9-9456-52cb2a3b42af" CreationDate="2015-10-07T11:11:51.073" UserId="1818" Text="Try putting a timestamp over some key frames as the last step on your render pipeline. Then compare it to the local systems time. If both clocks are correct you should get a delay in ms (using unix rime-stamps).&#xD;&#xA;&#xD;&#xA;Another idea to measure the round-trip-delay (might be important for UX reasons):&#xD;&#xA;input to server,&#xD;&#xA;server render,&#xD;&#xA;result from to server on your screen&#xD;&#xA;is to have a bot give an input than measure the time till the result is back" ContentLicense="CC BY-SA 3.0" />
  <row Id="2811" PostHistoryTypeId="5" PostId="1589" RevisionGUID="9c3007e7-7dc6-462c-bea6-33a829cfbb82" CreationDate="2015-10-07T11:30:11.603" UserId="1800" Comment="added 58 characters in body" Text="Say I am running a game in the cloud and I am playing that game on my client (the game is being streamed from the cloud to the client), be it a laptop, phone or calculator.&#xD;&#xA;&#xD;&#xA;How can I work out how long a frame (of the game being played) takes to arrive at the client?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2812" PostHistoryTypeId="2" PostId="1591" RevisionGUID="68ed116a-61e9-4b0b-9188-c9647e4fb69b" CreationDate="2015-10-07T12:12:45.563" UserId="1810" Text="As usual with numerical methods and samplings, it also depends of your quality threshold of what you consider &quot;isotropic&quot;. And of what you would consider or not as a being or not a &quot;grid-based noise algorithm&quot;.&#xD;&#xA;&#xD;&#xA;For instance Gabor Noise reproduces a target spectrum, for instance blue noise, which in Fourier domain is a simple isotropic ring.&#xD;&#xA;Now if you consider that this ring is not analytic but rasterized, as such it is not perfectly symmetrical. Also if the ring wavelength get too close to the maximum frequency, it will be truncated (and thus no longer symmetrical). &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2813" PostHistoryTypeId="2" PostId="1592" RevisionGUID="6798ec06-17a2-4748-a64f-3c88c9e819f1" CreationDate="2015-10-07T13:15:33.013" UserId="205" Text="I am working on Silverlight app. I am trying to render floor covered with tiles. Although I am using mip maps I am still getting awful Moire patterns, when trying to render big area.&#xD;&#xA;&#xD;&#xA;What I am doing is creating cuboid and then cover it with single tile:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In my pixel shader I am multiplying texture coordinates in order to create tiled floor (otherwise I would get one tile stretched over my cuboid). Pixel shader code:&#xD;&#xA;&#xD;&#xA;    float Width					: register(c3);                  //Width of cuboid&#xD;&#xA;    float Height				: register(c4);                  //Height of cuboid&#xD;&#xA;    &#xD;&#xA;    texture texTexture;&#xD;&#xA;    sampler textureSampler	: register(s0) = sampler_state {&#xD;&#xA;    	Texture = (texTexture);&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VsOutput&#xD;&#xA;    {&#xD;&#xA;    	float4 position : POSITION;&#xD;&#xA;    	float3 dirLightPosition	: COLOR;&#xD;&#xA;    	float2 texCoord	: TEXCOORD0;&#xD;&#xA;    	float3 normal	: TEXCOORD1;&#xD;&#xA;    	float3 view : TEXCOORD2;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float4 main(VsOutput IN) : COLOR&#xD;&#xA;    {&#xD;&#xA;    	float2 texCoord = float2(IN.texCoord.x * Width / 4.0f, &#xD;&#xA;                                 IN.texCoord.y * Height / 4.0f); //multiplying texture coordinates&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    	float4 texColor = tex2D(textureSampler, texCoord);&#xD;&#xA;    &#xD;&#xA;    	return float4(color.r, color.g, color.b, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My output is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What else can I do to prevent from creating Moires patterns on texture?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fZhKQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pPOY1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2814" PostHistoryTypeId="1" PostId="1592" RevisionGUID="6798ec06-17a2-4748-a64f-3c88c9e819f1" CreationDate="2015-10-07T13:15:33.013" UserId="205" Text="Moires patterns despite using mipmaps" ContentLicense="CC BY-SA 3.0" />
  <row Id="2815" PostHistoryTypeId="3" PostId="1592" RevisionGUID="6798ec06-17a2-4748-a64f-3c88c9e819f1" CreationDate="2015-10-07T13:15:33.013" UserId="205" Text="|rendering|texture|pixel-shader|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2816" PostHistoryTypeId="5" PostId="1551" RevisionGUID="48ea2114-7034-438a-8a6a-c0f52707a852" CreationDate="2015-10-07T13:32:22.013" UserId="209" Comment="added 2280 characters in body" Text="&#xD;&#xA;*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data. In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;_S3TC_:  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;In S3TC each 4x4 block is replaced by two end colours, *A* and *B*, and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. As an example the following is a 4x4 pixel section of the example image compressed with the AMD/ATI Compressenator tool. (Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update it).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis along with two 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).&#xD;&#xA;&#xD;&#xA;The latter assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - which is a superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma' &#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp block-based system. Apart from HDR modes, these use a more complex partitioning system to that of ETC to attempt to better model image colour distribution&#xD;&#xA;&#xD;&#xA; - PVRTC2 : This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : Another block based system but has a large number of possible block sizes targetting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and or colour precision.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2817" PostHistoryTypeId="5" PostId="1551" RevisionGUID="f5b28677-ca94-4a22-81d0-69549420fb67" CreationDate="2015-10-07T13:39:24.443" UserId="209" Comment="added 2280 characters in body" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data. In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;_S3TC_:  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;In S3TC each 4x4 block is replaced by two end colours, *A* and *B*, and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. As an example the following is a 4x4 pixel section of the example image compressed with the AMD/ATI Compressenator tool. (Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update it).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis along with two 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).&#xD;&#xA;&#xD;&#xA;The latter assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - which is a superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma' &#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp block-based system. Apart from HDR modes, these use a more complex partitioning system to that of ETC to attempt to better model image colour distribution&#xD;&#xA;&#xD;&#xA; - PVRTC2 : This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : Another block based system but has a large number of possible block sizes targetting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and or colour precision.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2818" PostHistoryTypeId="2" PostId="1593" RevisionGUID="286a6660-06b6-43f7-8c0f-74744625cbcc" CreationDate="2015-10-07T13:54:55.197" UserId="209" Text="Two things come to mind:&#xD;&#xA;&#xD;&#xA; 1. When generating your smaller mip map levels try to avoid using a simple 2x2 box filter because, though cheap and cheerful, they do a really poor job of removing high frequency information (that exceeds the Nyquist limit) as well as *over filtering* some of the lower frequency information you need to keep. (Also, as an aside, you need to perform the MIP map generation in linear space. If your source data is sRGB, you thus need to map to and from linear)&#xD;&#xA;&#xD;&#xA; 2. Standard Trilinear filtering will also over- and under-filter parts of the texture. If you don't like the aliasing you may have to a) adjust the bias to increase the filtering (which will increase blurring) and/or b) try using anisotropic filtering." ContentLicense="CC BY-SA 3.0" />
  <row Id="2820" PostHistoryTypeId="5" PostId="1593" RevisionGUID="d1196a28-89b4-4928-ac1e-9a76a67feba5" CreationDate="2015-10-07T14:21:16.043" UserId="209" Comment="added 176 characters in body" Text="Two things come to mind:&#xD;&#xA;&#xD;&#xA; 1. When generating your smaller mip map levels try to avoid using a simple 2x2 box filter because, though cheap and cheerful, they do a really poor job of removing high frequency information (that exceeds the Nyquist limit) as well as *over filtering* some of the lower frequency information you need to keep. (Also, as an aside, you need to perform the MIP map generation in linear space. If your source data is sRGB, you thus need to map to and from linear).  FWIW, In Williams' original paper on MIP mapping, he said he used a &quot;box (Fourier) window&quot; to generate the prefiltered levels, which would be a sinc function in image space.&#xD;&#xA;&#xD;&#xA; 2. Standard Trilinear filtering will also over- and under-filter parts of the texture. If you don't like the aliasing you may have to a) adjust the bias to increase the filtering (which will increase blurring) and/or b) try using anisotropic filtering." ContentLicense="CC BY-SA 3.0" />
  <row Id="2821" PostHistoryTypeId="5" PostId="1591" RevisionGUID="6b64adb7-d71f-4abd-8e49-a78528fd4d5e" CreationDate="2015-10-07T15:02:19.063" UserId="1810" Comment="added 34 characters in body" Text="As usual with numerical methods and samplings, it also depends of your quality threshold of what you consider &quot;isotropic&quot;. And of what you would consider or not as a being or not a &quot;grid-based noise algorithm&quot;.&#xD;&#xA;&#xD;&#xA;For instance Gabor Noise reproduces a target spectrum, for instance blue noise, which in Fourier domain is a simple isotropic ring.&#xD;&#xA;Now if you consider that this ring is not analytic but rasterized, as such it is not perfectly symmetrical. Also if the ring radius (i.e., frequency) get too close to the window size (i.e., maximum frequency), it will be truncated (and thus no longer symmetrical). &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2823" PostHistoryTypeId="2" PostId="1594" RevisionGUID="2235ce37-2bdf-4368-ace7-c69540b713ab" CreationDate="2015-10-07T16:59:14.693" UserId="1810" Text="When it comes to perception, there is also the issue of what we are almost blind to (in terms of properties or artifacts), and what we have enforced perception of.&#xD;&#xA;&#xD;&#xA;For instance as for sound, you have contrast or frequencies that let you less or not aware of other contents (an old siggraph paper illustrate how texture can mask mesh resolution), plus all the time aspects (google for &quot;change blindness&quot;). Similarilty details of surface, normals, brdf might or might not be seen depending of values and relative values.&#xD;&#xA;Also since our perceptive system tend to adapt locally and globally for low frequency values it is important to have maxima and minima at the right place, but their exact value won't be really noticed.&#xD;&#xA;Sometime cognition might be there to, like you allow a lot of errors in clouds and trees but surely less in human faces. (Sometime you might downgrade this to statistics of parameter for a given category).&#xD;&#xA;That's what I prefer using the word &quot;plausible&quot; rather than &quot;photorealistic&quot;.&#xD;&#xA;&#xD;&#xA;Contrarily, we are ultra-sensitive to artifacts such as false pixels or flickering pixels, ultra-sensitive to correlations like fronts of error of 1 grey level only, unwanted patterns such in Moiré, aliasing or bad random, etc. BTW it's one of the reason that optimizations-based solution summing everything in a simple energy can be very bad idea perceptively speaking as in all paradoxical situation this can prone the concentration of errors in lines or point.&#xD;&#xA;&#xD;&#xA;An (quite general) otherview about perception for graphics can be found in this SigAsia'11 course on [&quot;Perception in Graphics, Visualization,Virtual Environments and Animation&quot;][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://dl.acm.org/citation.cfm?id=2077448" ContentLicense="CC BY-SA 3.0" />
  <row Id="2824" PostHistoryTypeId="5" PostId="1594" RevisionGUID="dd785651-e4c7-4f1b-82f5-102be449b031" CreationDate="2015-10-07T17:04:22.360" UserId="1810" Comment="added 236 characters in body" Text="When it comes to perception, there is also the issue of what we are almost blind to (in terms of properties or artifacts), and what we have enforced perception of.&#xD;&#xA;&#xD;&#xA;For instance as for sound, you have contrast or frequencies that let you less or not aware of other contents (an old siggraph paper illustrate how texture can mask mesh resolution), plus all the time aspects (google for &quot;change blindness&quot;). Similarily, details of surface, normals, brdf might or might not be seen depending of values and relative values.&#xD;&#xA;Also since our perceptive system tend to adapt locally and globally, for low frequency values it is important to have maximas and minimas at the right place, but their exact value won't be really noticed.&#xD;&#xA;Sometime cognition might be there to, like you allow a lot of errors in clouds and trees but surely less in human faces. (Sometime you might downgrade this to statistics of parameter for a given category).&#xD;&#xA;That's why I prefer using the word &quot;plausible&quot; rather than &quot;photorealistic&quot;.&#xD;&#xA;&#xD;&#xA;Contrarily, we are ultra-sensitive to artifacts such as false pixels or flickering pixels, ultra-sensitive to correlations like fronts of error of 1 grey level only, unwanted patterns such in Moiré, aliasing or bad random, etc. BTW it's one of the reason that optimizations-based solution summing everything in a simple energy can be a very bad idea perceptively speaking as in all paradoxical situation this can prone the concentration of errors in lines or point. For the same reason early global illumination people where really disappointed that energy exact solution where less accepted that anti-aliased approximate shadows (and then came from quad-tree based to mesh-based adaptive methods).&#xD;&#xA;&#xD;&#xA;A (quite general) otherview about perception for graphics can be found in this SigAsia'11 course on [&quot;Perception in Graphics, Visualization,Virtual Environments and Animation&quot;][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://dl.acm.org/citation.cfm?id=2077448" ContentLicense="CC BY-SA 3.0" />
  <row Id="2825" PostHistoryTypeId="5" PostId="1591" RevisionGUID="f05eb5eb-c7cc-48f3-922a-9ada47c79b30" CreationDate="2015-10-07T17:13:28.980" UserId="1810" Comment="deleted 7 characters in body" Text="As usual with numerical methods and samplings, it also depends of your quality threshold of what you consider &quot;isotropic&quot;. And of what you would consider as a being or not a &quot;grid-based noise algorithm&quot;.&#xD;&#xA;&#xD;&#xA;For instance Gabor Noise reproduces a target spectrum, for instance blue noise, which in Fourier domain is a simple isotropic ring.&#xD;&#xA;Now if you consider that this ring is not analytic but rasterized, as such it is not perfectly symmetrical. Also if the ring radius (i.e., frequency) get too close to the window size (i.e., maximum frequency), it will be truncated (and thus no longer symmetrical). &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2826" PostHistoryTypeId="2" PostId="1595" RevisionGUID="063e8c68-95a8-4aa8-aea0-677208c348d6" CreationDate="2015-10-07T18:10:08.277" UserId="18" Text="*Just out of interest:* Is there any strategy to detect the focus of an image in order to separate the background? I've tried using [edge detection][1] methods but without any success. &#xD;&#xA;&#xD;&#xA;*In other words:* Is it possible to determine if an area of an image is blurred (out of focus) or not?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Edge_detection" ContentLicense="CC BY-SA 3.0" />
  <row Id="2827" PostHistoryTypeId="1" PostId="1595" RevisionGUID="063e8c68-95a8-4aa8-aea0-677208c348d6" CreationDate="2015-10-07T18:10:08.277" UserId="18" Text="Detecting image background" ContentLicense="CC BY-SA 3.0" />
  <row Id="2828" PostHistoryTypeId="3" PostId="1595" RevisionGUID="063e8c68-95a8-4aa8-aea0-677208c348d6" CreationDate="2015-10-07T18:10:08.277" UserId="18" Text="|algorithm|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2830" PostHistoryTypeId="2" PostId="1597" RevisionGUID="9b0f857d-1bf3-4c51-a2c9-085bf1ae5456" CreationDate="2015-10-07T18:53:23.187" UserId="1820" Text="Radiosity, by definition, handles only the diffuse component. You cannot 'limit' Radiosity to diffuse, because it already is handling just that diffuse component (remember - the diffuse lighting is just one (albeit popular) application of the energy distribution).&#xD;&#xA;&#xD;&#xA;So, you just misinterpreted the quote.&#xD;&#xA;&#xD;&#xA;Also, contrary to popular misconception, you **do *not* have to distribute all energy** to get great results. Look into **Progressive Refinement method**, which only processes the largest emitors, thus allowing to converge to 'close enough' solution much sooner.&#xD;&#xA;&#xD;&#xA;Usually, you set some threshold (e.g. I want to redistribute 85% if all energy) and before processing the next Shooter patch, you do a simple check for the running total of the distributed energy (and quit the loop). This is usually few orders of magnitude faster (for a very minor implementation cost) than the reference brute-force method.&#xD;&#xA;&#xD;&#xA;Of course, to get true benefits of Radiosity (e.g. color bleeding) it's best to redistribute as much as possible (given the resources available)." ContentLicense="CC BY-SA 3.0" />
  <row Id="2831" PostHistoryTypeId="2" PostId="1598" RevisionGUID="4f7a3fbb-c990-4e7c-a7c7-cb424abfe3be" CreationDate="2015-10-07T20:34:05.963" UserId="316" Text="Google said how in 2012, avoiding explaining too many details&#xD;&#xA;&#xD;&#xA;[The never-ending quest for the perfect map][1]&#xD;&#xA;&#xD;&#xA;&gt; ...new imagery rendering techniques and computer vision that let us&#xD;&#xA;&gt; automatically create 3D cityscapes, complete with buildings, terrain&#xD;&#xA;&gt; and even landscaping, from 45-degree aerial imagery&#xD;&#xA;&#xD;&#xA;and here it's a [video][2] of the feature.&#xD;&#xA;&#xD;&#xA;So we know that &quot;Computer Vision&quot; is used. I guess the edges are detected, along with the shadows, to build the elevation of the object. Then the segmented image is used as a texture on the built mesh.&#xD;&#xA;&#xD;&#xA;However, i saw [this paper][3] linked, and i think a similar technique is used in Google to extract the 3d mesh from different 45° images.&#xD;&#xA;&#xD;&#xA;There are a lot of papers (a book too) about &quot;building extraction/detection&quot;.&#xD;&#xA;&#xD;&#xA;- [Detection of buildings in urban and suburban areas using very high resolution satellite][4]&#xD;&#xA;- [Google Scholar: Building Detection][5]&#xD;&#xA;- [Google Scholar: Building Detection from Satellite Images][6]&#xD;&#xA;&#xD;&#xA;src: [How does the new google maps make buildings and cityscapes 3D?][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://googleblog.blogspot.it/2012/06/never-ending-quest-for-perfect-map.html&#xD;&#xA;  [2]: https://www.youtube.com/watch?t=44&amp;v=N6Douyfa7l8&#xD;&#xA;  [3]: http://iris.usc.edu/outlines/papers/1998/lin-cviu98.pdf&#xD;&#xA;  [4]: http://www.asprs.org/a/publications/proceedings/Louisville2014/Jabari_1.pdf&#xD;&#xA;  [5]: https://scholar.google.it/scholar?q=Building+Detection&#xD;&#xA;  [6]: https://scholar.google.it/scholar?q=Building%20Detection%20from%20Satellite%20Images&amp;btnG=&amp;hl=en&amp;as_sdt=0%2C5&amp;as_vis=1&#xD;&#xA;  [7]: http://programmers.stackexchange.com/questions/202599/how-does-the-new-google-maps-make-buildings-and-cityscapes-3d" ContentLicense="CC BY-SA 3.0" />
  <row Id="2832" PostHistoryTypeId="2" PostId="1599" RevisionGUID="e31fa5d0-2de9-4e51-b5c4-8fb4472963d2" CreationDate="2015-10-07T21:07:45.853" UserId="1810" Text="it is quite easy to measure the local max frequency in an image (at least as a low resolution mask, with some regularization).&#xD;&#xA;Several papers of the MIT graphics group have been around detecting and processing from this kind of clue, with regular or coded aperture cameras.&#xD;&#xA;e.g. [Defocus Magnification][1] and [Image and Depth from a Conventional Camera with a Coded Aperture][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/soonmin/dof/&#xD;&#xA;  [2]: http://groups.csail.mit.edu/graphics/CodedAperture/" ContentLicense="CC BY-SA 3.0" />
  <row Id="2842" PostHistoryTypeId="2" PostId="1601" RevisionGUID="43f3a746-99f3-4d08-b87c-fb8563441bc3" CreationDate="2015-10-08T07:48:39.857" UserDisplayName="user1703" Text="The sentence says it: radiosity precomputes an &quot;image&quot; for all potential viewpoints at the same time, i.e. it doesn't focus on just the rays that hit a particular observer, hence there are implicitly many more rays to consider." ContentLicense="CC BY-SA 3.0" />
  <row Id="2843" PostHistoryTypeId="5" PostId="1591" RevisionGUID="80e4af9c-7d5a-4127-9d58-5013b6a254f0" CreationDate="2015-10-08T07:52:06.393" UserId="1810" Comment="images" Text="As usual with numerical methods and samplings, it also depends of your quality threshold of what you consider &quot;isotropic&quot;. And of what you would consider as a being or not a &quot;grid-based noise algorithm&quot;.&#xD;&#xA;&#xD;&#xA;For instance Gabor Noise reproduces a target spectrum, for instance blue noise, which in Fourier domain is a simple isotropic ring.&#xD;&#xA;Now if you consider that this ring is not analytic but rasterized, as such it is not perfectly symmetrical. Also if the ring radius (i.e., frequency) get too close to the window size (i.e., maximum frequency), it will be truncated (and thus no longer symmetrical). Up to you to accept or not these as anisotropic ;-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![&quot;this is not a circle&quot; - Magritte][2]][2]&#xD;&#xA;[![&quot;this is not a circle&quot; - Nyquist][1]][1]&#xD;&#xA;*&quot;This is not a circle&quot; - Magritte . . . . . . . . . . . . . . . .   &quot;This is not a circle&quot; - Nyquist*&#xD;&#xA;  [1]: https://i.stack.imgur.com/c4Xaj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vFj2M.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2844" PostHistoryTypeId="5" PostId="1601" RevisionGUID="9c3eebac-cc7d-45e2-8426-f37b6f0970e2" CreationDate="2015-10-08T07:54:36.873" UserDisplayName="user1703" Comment="added 87 characters in body" Text="The sentence says it: radiosity precomputes an &quot;image&quot; for all potential viewpoints at the same time, i.e. it doesn't focus on just the rays that hit a particular observer, hence there are naturally many more rays to consider.&#xD;&#xA;&#xD;&#xA;Whether the surfaces are specular or diffuse isn't really relevant in regard to this statement." ContentLicense="CC BY-SA 3.0" />
  <row Id="2845" PostHistoryTypeId="5" PostId="1601" RevisionGUID="000e74a4-3ad0-4cea-a007-b939a9366245" CreationDate="2015-10-08T08:00:27.290" UserDisplayName="user1703" Comment="added 87 characters in body" Text="The sentence says it: radiosity precomputes an &quot;image&quot; for all potential viewpoints at the same time, i.e. it doesn't focus on just the rays that hit a particular observer. Hence there are naturally many more rays to consider, as you are actually rendering a multitude of views simultaneously.&#xD;&#xA;&#xD;&#xA;Whether the surfaces are specular or diffuse isn't really relevant in regard to this statement.&#xD;&#xA;&#xD;&#xA;To make the approach viable, radiosity performs very gross rendering, using large &quot;beams&quot; instead of thin rays." ContentLicense="CC BY-SA 3.0" />
  <row Id="2846" PostHistoryTypeId="5" PostId="1591" RevisionGUID="93ebbf8f-1187-496f-a2d7-6a9b0e0492c2" CreationDate="2015-10-08T08:08:20.757" UserId="1810" Comment="added 220 characters in body" Text="As usual with numerical methods and samplings, it also depends of your quality threshold of what you consider &quot;isotropic&quot;. And of what you would consider as a being or not a &quot;grid-based noise algorithm&quot;.&#xD;&#xA;&#xD;&#xA;For instance Gabor Noise reproduces a target spectrum, for instance blue noise, which in Fourier domain is a simple isotropic ring.&#xD;&#xA;Now if you consider that this ring is not analytic but rasterized, as such it is not perfectly symmetrical. Also if the ring radius (i.e., frequency) get too close to the window size (i.e., maximum frequency), it will be truncated (and thus no longer symmetrical). Up to you to accept or not these as anisotropic ;-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![&quot;this is not a circle&quot; - Magritte][2]][2]&#xD;&#xA;[![&quot;this is not a circle&quot; - Nyquist][1]][1]&#xD;&#xA;*&quot;This is not a circle&quot; - Magritte . . . . . . . . . . . . . . . .   &quot;This is not a circle&quot; - Nyquist*&#xD;&#xA;&#xD;&#xA;You might or might not accept a rasterized ring in Fourier space to be &quot;isotropic&quot;. Still, in the extreme cases where the ring get thinner than the resolution, or larger than the window, isotropy is objectively lost.&#xD;&#xA;  [1]: https://i.stack.imgur.com/c4Xaj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vFj2M.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2847" PostHistoryTypeId="5" PostId="1601" RevisionGUID="db8361c7-b797-4890-9816-53e159cd4e68" CreationDate="2015-10-08T08:19:00.467" UserDisplayName="user1703" Comment="added 4 characters in body" Text="The sentence says it: radiosity precomputes an &quot;image&quot; for all potential viewpoints at the same time, i.e. it doesn't focus on just the rays that hit a particular observer. Hence there are naturally many more rays to consider, as you are actually rendering a multitude of views simultaneously.&#xD;&#xA;&#xD;&#xA;Whether the surfaces are specular or diffuse isn't really relevant in regard to this statement.&#xD;&#xA;&#xD;&#xA;To make the approach viable, radiosity performs very gross rendering, as if using large beams instead of thin rays." ContentLicense="CC BY-SA 3.0" />
  <row Id="2848" PostHistoryTypeId="2" PostId="1602" RevisionGUID="25054e58-69ed-44fa-a3ef-b29eaee1b54b" CreationDate="2015-10-08T08:27:22.417" UserId="1614" Text="What one has to do in this matter is first define the quantities that are physically at play here, so that everybody speaks about the same thing.&#xD;&#xA;&#xD;&#xA;There is:&#xD;&#xA;&#xD;&#xA; - radiance ([wikipedia][1])  &#xD;&#xA;Flux emitted by a surface per solid angle per projected area.  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Unit is **W·sr−1·m−2**&#xD;&#xA; - radiant intensity ([wikipedia][3])  &#xD;&#xA;Origin of radiance, you take the surface area out of the unit.  &#xD;&#xA;Unit is **W·sr−1**&#xD;&#xA; - intensity ([wikipedia][4])  &#xD;&#xA;A perception-based unit of power per solid angle.  &#xD;&#xA;Unit is **candela**&#xD;&#xA; - luminance ([wikipedia][5])  &#xD;&#xA; *The luminance is normally obtained by dividing the luminous intensity by the light source area* ([source][6])  &#xD;&#xA;therefore this is also perception based.  &#xD;&#xA;Unit is **cd·m−2**&#xD;&#xA; - luminuous flux ([wikipedia][7])  &#xD;&#xA;Same thing but not related to solid angle.  &#xD;&#xA;quote:  &#xD;&#xA;*Luminous flux is a measure of the total amount of light a lamp puts out. The luminous intensity (in candelas) is a measure of how bright the beam in a particular direction is*  &#xD;&#xA;Unit is **lumen**&#xD;&#xA;&#xD;&#xA;You can also talk of irradiance ([wiki][8]) when speaking of received radiance.  &#xD;&#xA;And one can also talk of total-irradiance when speaking of the irradiance taken for the whole hemisphere.&#xD;&#xA;&#xD;&#xA;refer to: http://www.crompton.com/light/index.html  &#xD;&#xA;and why not: http://www.nvc-lighting.com/showuseInfo.Aspx?typeID=42&amp;ID=94&#xD;&#xA;&#xD;&#xA;As you can see, there are two classes of units, the perception based and the absolute physical units.  &#xD;&#xA;the **radiance** is the measure you want to look at to understand Lambert, you can actually see the cosine falloff directly in the formula.  &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Radiance&#xD;&#xA;  [2]: https://i.stack.imgur.com/N2ziI.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiant_intensity&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Luminous_intensity&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Luminance&#xD;&#xA;  [6]: http://www.rohm.com/web/eu/faq_search/-/faq_search/FaqId/260&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Luminous_flux&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Irradiance" ContentLicense="CC BY-SA 3.0" />
  <row Id="2849" PostHistoryTypeId="5" PostId="1551" RevisionGUID="cee46033-dcc5-433d-b555-876666c29519" CreationDate="2015-10-08T10:38:38.140" UserId="209" Comment="Reference to ATC encoding plus BPP and supported colour formats" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called *Block Truncation Coding*. This also included the method of compression but, for our purposes, we are only interested in the resulting compressed data. In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)&#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, and each texel in the block is a 2bit index that determines how to select one of four blends of those end colours. As an example the following is a 4x4 pixel section of the example image compressed with the AMD/ATI Compressenator tool. (Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update it).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis along with two 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB&#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA&#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - which is a superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma' &#xD;&#xA;&#xD;&#xA; - ATC - IIRC, is effectively a small [variation on S3TC][13].&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system to that of ETC to attempt to better model image colour distribution&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : Another block based system but has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and or colour precision.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2854" PostHistoryTypeId="6" PostId="361" RevisionGUID="732cee04-0503-4ff5-94d3-d2538de5be84" CreationDate="2015-10-08T21:29:14.777" UserId="231" Comment="Remove pointless tag" Text="|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2855" PostHistoryTypeId="6" PostId="210" RevisionGUID="f1e8a0d8-4b71-48b6-9880-343a47f296a1" CreationDate="2015-10-08T21:30:05.937" UserId="231" Comment="Remove pointless tag" Text="|raytracing|ambient-occlusion|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2856" PostHistoryTypeId="2" PostId="1604" RevisionGUID="cb2fcda5-85a1-4728-8768-60e6540d9bf9" CreationDate="2015-10-09T01:44:16.853" UserId="1614" Text="I'll add some guidelines to help readers understand Benedikt Bitterli's statement &quot;Make sure to gamma correct your images&quot;.&#xD;&#xA;&#xD;&#xA;Gamma correcting images does not mean applying a power filter at the end.&#xD;&#xA;It means working in linear space during all calculations, and finally encoding the output into gamma space.&#xD;&#xA;&#xD;&#xA;Gamma space is the color space into which all display machines of this age expect RGB values to be presented to them.&#xD;&#xA;&#xD;&#xA;Linear space in opposition, is the fact of working with values which are proportional to physical emissions.&#xD;&#xA;&#xD;&#xA;Therefore, when the artist edit the values of the albedos colors of the world surfaces, and the colors of the lights of the scene, he does it in gamma space because no edition software dare to modify what the user has input and just saves as-is. So the artist was looking at something that looked good for him, while stored in gamma space.&#xD;&#xA;&#xD;&#xA;So the first step of all rendering engine, should be to convert all human edited input to linear space first. In your case that means all sphere colors and emissions values.&#xD;&#xA;&#xD;&#xA;Then, you do your usual raytracing, brdf evaluation, monte carlo sampling, whatever process, in HDR if possible using `float32` components if possible. (usually works nice with 128 bits SIMD as `r,g,b,a` vectors).&#xD;&#xA;&#xD;&#xA;Finally you tone filter the HDR image according to the exposure value you choose, heuristically or manually. This operation could be very simple like a `clamp`. And then and only then, you encode the final image to gamma space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The base is: a monitor will take an input value x and apply the formula x^2.2 to create the physical radiance on the output pixel.&#xD;&#xA;&#xD;&#xA;Thus, the conversion formulas goes as follow:&#xD;&#xA;&#xD;&#xA;linear to gamma: x^(1/2.2)  &#xD;&#xA;gamma to linear: x^2.2&#xD;&#xA;&#xD;&#xA;Please note as trivia that sRGB space has a complex formula, a `if`, and some offset. But viewed from afar the curve is very very close to simple gamma.&#xD;&#xA;&#xD;&#xA;Second thing to take into account, are you sure your sampling is fair ?  &#xD;&#xA;You could be sampling too much in the directions that privileges more rays to reach the sky. check the uniformity of your sampling. You said you use a gaussian that seems to me like you are going to ask for bias. Just use the classic Lambert distribution sampling: https://pathtracing.wordpress.com/&#xD;&#xA;this way you reduce the number of samples necessary to get a variance equivalent with a purely uniform sphere. and you also save the cosine evaluation because its embedded in the distribution.&#xD;&#xA;&#xD;&#xA;Lastly, if your spheres are really mirrors and your GI is supposedly actually working, it will accumulate reflected energy on the ground, therefore compensating your shadows from occlusion. I even expect to see more energy than darkening in such cases." ContentLicense="CC BY-SA 3.0" />
  <row Id="2857" PostHistoryTypeId="5" PostId="1602" RevisionGUID="8455026f-a36a-4cd7-a6b1-372f9dfe7040" CreationDate="2015-10-09T01:49:20.690" UserId="1614" Comment="add https://pathtracing.wordpress.com/" Text="What one has to do in this matter is first define the quantities that are physically at play here, so that everybody speaks about the same thing.&#xD;&#xA;&#xD;&#xA;There is:&#xD;&#xA;&#xD;&#xA; - radiance ([wikipedia][1])  &#xD;&#xA;Flux emitted by a surface per solid angle per projected area.  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Unit is **W·sr−1·m−2**&#xD;&#xA; - radiant intensity ([wikipedia][3])  &#xD;&#xA;Origin of radiance, you take the surface area out of the unit.  &#xD;&#xA;Unit is **W·sr−1**&#xD;&#xA; - intensity ([wikipedia][4])  &#xD;&#xA;A perception-based unit of power per solid angle.  &#xD;&#xA;Unit is **candela**&#xD;&#xA; - luminance ([wikipedia][5])  &#xD;&#xA; *The luminance is normally obtained by dividing the luminous intensity by the light source area* ([source][6])  &#xD;&#xA;therefore this is also perception based.  &#xD;&#xA;Unit is **cd·m−2**&#xD;&#xA; - luminuous flux ([wikipedia][7])  &#xD;&#xA;Same thing but not related to solid angle.  &#xD;&#xA;quote:  &#xD;&#xA;*Luminous flux is a measure of the total amount of light a lamp puts out. The luminous intensity (in candelas) is a measure of how bright the beam in a particular direction is*  &#xD;&#xA;Unit is **lumen**&#xD;&#xA;&#xD;&#xA;You can also talk of irradiance ([wiki][8]) when speaking of received radiance.  &#xD;&#xA;And one can also talk of total-irradiance when speaking of the irradiance taken for the whole hemisphere.&#xD;&#xA;&#xD;&#xA;refer to: http://www.crompton.com/light/index.html  &#xD;&#xA;and: https://pathtracing.wordpress.com/  &#xD;&#xA;and why not: http://www.nvc-lighting.com/showuseInfo.Aspx?typeID=42&amp;ID=94&#xD;&#xA;&#xD;&#xA;As you can see, there are two classes of units, the perception based and the absolute physical units.  &#xD;&#xA;the **radiance** is the measure you want to look at to understand Lambert, you can actually see the cosine falloff directly in the formula.  &#xD;&#xA;&#xD;&#xA;You can see the intuition of this in this blog: https://pathtracing.wordpress.com/ chapter &quot;Lambert's cosine law&quot;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Radiance&#xD;&#xA;  [2]: https://i.stack.imgur.com/N2ziI.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiant_intensity&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Luminous_intensity&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Luminance&#xD;&#xA;  [6]: http://www.rohm.com/web/eu/faq_search/-/faq_search/FaqId/260&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Luminous_flux&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Irradiance" ContentLicense="CC BY-SA 3.0" />
  <row Id="2859" PostHistoryTypeId="4" PostId="1595" RevisionGUID="031d01c8-b8cf-4369-ac3f-9c2c42f4a543" CreationDate="2015-10-09T07:51:17.833" UserId="18" Comment="title" Text="Detect focus area of an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="2860" PostHistoryTypeId="5" PostId="1551" RevisionGUID="27b5fd7d-d1e2-4d03-9d2c-3c35f8e79c94" CreationDate="2015-10-09T09:17:46.803" UserId="209" Comment="Added 2bpp PVRTC results and a note on decompression costs" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant is, naturally, noisier than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma' &#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2861" PostHistoryTypeId="6" PostId="1434" RevisionGUID="b4f11dcf-5991-4379-84e7-cc21aee88370" CreationDate="2015-10-09T15:08:49.073" UserId="53" Comment="edited tags" Text="|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2862" PostHistoryTypeId="5" PostId="1592" RevisionGUID="2aa1a374-9aab-41d4-91f6-a3630c4e5c56" CreationDate="2015-10-09T15:27:32.843" UserId="205" Comment="Added solution" Text="I am working on Silverlight app. I am trying to render floor covered with tiles. Although I am using mip maps I am still getting awful Moire patterns, when trying to render big area.&#xD;&#xA;&#xD;&#xA;What I am doing is creating cuboid and then cover it with single tile:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In my pixel shader I am multiplying texture coordinates in order to create tiled floor (otherwise I would get one tile stretched over my cuboid). Pixel shader code:&#xD;&#xA;&#xD;&#xA;    float Width					: register(c3);                  //Width of cuboid&#xD;&#xA;    float Height				: register(c4);                  //Height of cuboid&#xD;&#xA;    &#xD;&#xA;    texture texTexture;&#xD;&#xA;    sampler textureSampler	: register(s0) = sampler_state {&#xD;&#xA;    	Texture = (texTexture);&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VsOutput&#xD;&#xA;    {&#xD;&#xA;    	float4 position : POSITION;&#xD;&#xA;    	float3 dirLightPosition	: COLOR;&#xD;&#xA;    	float2 texCoord	: TEXCOORD0;&#xD;&#xA;    	float3 normal	: TEXCOORD1;&#xD;&#xA;    	float3 view : TEXCOORD2;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float4 main(VsOutput IN) : COLOR&#xD;&#xA;    {&#xD;&#xA;    	float2 texCoord = float2(IN.texCoord.x * Width / 4.0f, &#xD;&#xA;                                 IN.texCoord.y * Height / 4.0f); //multiplying texture coordinates&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    	float4 texColor = tex2D(textureSampler, texCoord);&#xD;&#xA;    &#xD;&#xA;    	return float4(color.r, color.g, color.b, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My output is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What else can I do to prevent from creating Moires patterns on texture?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;______________________________________&#xD;&#xA;**SOLUTION**&#xD;&#xA;&#xD;&#xA;I managed to solve my problem by increacing size of texture 2048x2048px so there would be generated more mipmaps. Also it seems like changing my SamplerState form anisotropic to something like that helped:&#xD;&#xA;&#xD;&#xA;    SamplerState MirrorTexCoord = new SamplerState()&#xD;&#xA;            {&#xD;&#xA;                AddressU = TextureAddressMode.Mirror,&#xD;&#xA;                AddressV = TextureAddressMode.Mirror,&#xD;&#xA;                .&#xD;&#xA;                .&#xD;&#xA;                .&#xD;&#xA;            };&#xD;&#xA;&#xD;&#xA;Actually I don' t know what is TextureAdressMode.Mirror, but it helped a lot, now it looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fZhKQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pPOY1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/2acRT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2863" PostHistoryTypeId="5" PostId="1592" RevisionGUID="f8bd5447-f041-4d45-986c-23973e2623bd" CreationDate="2015-10-09T15:56:02.890" UserId="205" Comment="Moved solution from question to answer section" Text="I am working on Silverlight app. I am trying to render floor covered with tiles. Although I am using mip maps I am still getting awful Moire patterns, when trying to render big area.&#xD;&#xA;&#xD;&#xA;What I am doing is creating cuboid and then cover it with single tile:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In my pixel shader I am multiplying texture coordinates in order to create tiled floor (otherwise I would get one tile stretched over my cuboid). Pixel shader code:&#xD;&#xA;&#xD;&#xA;    float Width					: register(c3);                  //Width of cuboid&#xD;&#xA;    float Height				: register(c4);                  //Height of cuboid&#xD;&#xA;    &#xD;&#xA;    texture texTexture;&#xD;&#xA;    sampler textureSampler	: register(s0) = sampler_state {&#xD;&#xA;    	Texture = (texTexture);&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VsOutput&#xD;&#xA;    {&#xD;&#xA;    	float4 position : POSITION;&#xD;&#xA;    	float3 dirLightPosition	: COLOR;&#xD;&#xA;    	float2 texCoord	: TEXCOORD0;&#xD;&#xA;    	float3 normal	: TEXCOORD1;&#xD;&#xA;    	float3 view : TEXCOORD2;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float4 main(VsOutput IN) : COLOR&#xD;&#xA;    {&#xD;&#xA;    	float2 texCoord = float2(IN.texCoord.x * Width / 4.0f, &#xD;&#xA;                                 IN.texCoord.y * Height / 4.0f); //multiplying texture coordinates&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    	float4 texColor = tex2D(textureSampler, texCoord);&#xD;&#xA;    &#xD;&#xA;    	return float4(color.r, color.g, color.b, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My output is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What else can I do to prevent from creating Moires patterns on texture?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fZhKQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pPOY1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2864" PostHistoryTypeId="2" PostId="1605" RevisionGUID="f1b142c5-b354-4175-972f-8bdc33d18292" CreationDate="2015-10-09T15:56:19.853" UserId="205" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;I managed to solve my problem by increacing size of texture 2048x2048px so there would be generated more mipmaps. Also it seems like changing my SamplerState form anisotropic to something like that helped:&#xD;&#xA;&#xD;&#xA;    SamplerState MirrorTexCoord = new SamplerState()&#xD;&#xA;            {&#xD;&#xA;                AddressU = TextureAddressMode.Mirror,&#xD;&#xA;                AddressV = TextureAddressMode.Mirror,&#xD;&#xA;                .&#xD;&#xA;                .&#xD;&#xA;                .&#xD;&#xA;            };&#xD;&#xA;&#xD;&#xA;Actually I don' t know what is TextureAdressMode.Mirror, but it helped a lot, now it looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [3]: https://i.stack.imgur.com/2acRT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2865" PostHistoryTypeId="2" PostId="1606" RevisionGUID="2deaf44b-8eaa-4a93-aefd-2cf4888a2c35" CreationDate="2015-10-09T18:03:51.633" UserId="1836" Text="I have the following problem:&#xD;&#xA;&#xD;&#xA;Give a matrix that will transform the point (x,y,z) into the point (2/(x+y), (5y + z)/(2x + 2y), 3)&#xD;&#xA;&#xD;&#xA;I have been reading my book to find a way to solve it without success. I will very much appreciate your feedback about how to solve it.&#xD;&#xA;&#xD;&#xA;Repsectfully,&lt;br /&gt;&#xD;&#xA;Jorge Maldonado&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2866" PostHistoryTypeId="1" PostId="1606" RevisionGUID="2deaf44b-8eaa-4a93-aefd-2cf4888a2c35" CreationDate="2015-10-09T18:03:51.633" UserId="1836" Text="Transform a point into another point" ContentLicense="CC BY-SA 3.0" />
  <row Id="2867" PostHistoryTypeId="3" PostId="1606" RevisionGUID="2deaf44b-8eaa-4a93-aefd-2cf4888a2c35" CreationDate="2015-10-09T18:03:51.633" UserId="1836" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2868" PostHistoryTypeId="5" PostId="1595" RevisionGUID="041c1952-0c6d-421a-887a-bee071a53a29" CreationDate="2015-10-09T18:36:05.377" UserId="48" Comment="edit title and wording to be clearer" Text="Is there any strategy to detect the region of an image that is sharp and in-focus, in order to separate the out-of-focus background? I've tried using [edge detection][1] methods but without any success. &#xD;&#xA;&#xD;&#xA;In other words, is it possible to determine if an area of an image is blurred (out of focus) or not?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Edge_detection" ContentLicense="CC BY-SA 3.0" />
  <row Id="2869" PostHistoryTypeId="4" PostId="1595" RevisionGUID="041c1952-0c6d-421a-887a-bee071a53a29" CreationDate="2015-10-09T18:36:05.377" UserId="48" Comment="edit title and wording to be clearer" Text="Detect in-focus regions of an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="2870" PostHistoryTypeId="6" PostId="1595" RevisionGUID="041c1952-0c6d-421a-887a-bee071a53a29" CreationDate="2015-10-09T18:36:05.377" UserId="48" Comment="edit title and wording to be clearer" Text="|algorithm|blur|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2871" PostHistoryTypeId="2" PostId="1607" RevisionGUID="67e4f4b8-2900-4b5a-82bf-3480cd8b232f" CreationDate="2015-10-09T18:37:37.273" UserId="137" Text="The hint is to use the perspective divide inherent in homegeneous coordinate. So the resulting point you are looking for is `(2, (5y+z)/2, 3x+3y, x+y)`&#xD;&#xA;&#xD;&#xA;That matrix then ends up as&#xD;&#xA;&#xD;&#xA;    0   0   0   2&#xD;&#xA;    0   2.5 0.5 0&#xD;&#xA;    3   3   0   0&#xD;&#xA;    1   1   0   0" ContentLicense="CC BY-SA 3.0" />
  <row Id="2872" PostHistoryTypeId="10" PostId="1589" RevisionGUID="7a66f4e6-4d5c-4e02-bd05-31591e1ba00e" CreationDate="2015-10-09T19:18:07.210" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;}]}" />
  <row Id="2873" PostHistoryTypeId="2" PostId="1608" RevisionGUID="d7047b7c-3850-4df3-82a6-f53402a520aa" CreationDate="2015-10-09T19:40:42.943" UserId="1836" Text="I already know about the matrices I have to use in order to perform rotations. If I have to rotate in z-axis and then in x-axis, I would do it in 2 steps. My question is, is it possible to combine both rotations into a single matrix? I will appreciate your feedback." ContentLicense="CC BY-SA 3.0" />
  <row Id="2874" PostHistoryTypeId="1" PostId="1608" RevisionGUID="d7047b7c-3850-4df3-82a6-f53402a520aa" CreationDate="2015-10-09T19:40:42.943" UserId="1836" Text="How to combine rotation in 2 axis into one matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="2875" PostHistoryTypeId="3" PostId="1608" RevisionGUID="d7047b7c-3850-4df3-82a6-f53402a520aa" CreationDate="2015-10-09T19:40:42.943" UserId="1836" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2876" PostHistoryTypeId="2" PostId="1609" RevisionGUID="5a216c01-8913-4669-bd78-6900a54d4b57" CreationDate="2015-10-09T19:58:32.230" UserId="1826" Text="Yes, just multiply them in reverse order:&#xD;&#xA;&#xD;&#xA;    Matrix myrotation = Matrix.CreateRotationX(xrot) * Matrix.CreateRotationZ(zrot);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2878" PostHistoryTypeId="5" PostId="1606" RevisionGUID="b82dad0c-bdba-4236-a9d2-5eb4ba101e0d" CreationDate="2015-10-10T05:45:30.667" UserId="38" Comment="deleted 40 characters in body" Text="I have the following problem:&#xD;&#xA;&#xD;&#xA;Give a matrix that will transform the point (x,y,z) into the point (2/(x+y), (5y + z)/(2x + 2y), 3)&#xD;&#xA;&#xD;&#xA;I have been reading my book to find a way to solve it without success. I will very much appreciate your feedback about how to solve it.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2879" PostHistoryTypeId="5" PostId="1606" RevisionGUID="6cbc0e8a-dd5f-4af3-a152-be2ccafe64c7" CreationDate="2015-10-10T16:59:01.980" UserId="1836" Comment="added 458 characters in body" Text="I have the following 2 parts of one problem:&#xD;&#xA;&#xD;&#xA;1) Give a matrix that will transform the point (x,y,z) into the point (2/(x+y), (5y + z)/(2x + 2y), 3)&#xD;&#xA;&#xD;&#xA;2) Assume you have performed the projection on the canonical view volume. Give the matrix you would use to make the final image of size 5 units wide and 3 units tall. I think the answer is &lt;br /&gt;[5, 0, 0, 0]&lt;br /&gt;[0, 3, 0, 0]&lt;br /&gt;[0, 0, 1, 0]&lt;br /&gt;[0, 0, 0, 1]&lt;br /&gt;I only considered to scale x and y by multiplying the identity matrix by 5 and by 3. Also, as far as I understand, the canonical view is the one with the original (x, y, z) coordinates without w. I mean, we go from canonical to homogeneous and viceversa.&#xD;&#xA;&#xD;&#xA;I will very much appreciate your feedback about how to solve it.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2880" PostHistoryTypeId="2" PostId="1610" RevisionGUID="3dabe777-dc9e-4962-ae99-e622a69075a5" CreationDate="2015-10-10T17:25:56.540" UserId="1836" Text="I have the following question in an exam review and I am looking for feedback about how to approach the solution. Any advice will be highly appreciated.&#xD;&#xA;&#xD;&#xA;&quot;Using a parametric line intersection test, give the parameter values of the endpoints of a line from (3,3,4) to (11,8,7) clipped to the cube extending from 0 to 5 in x, y, and z&quot;&#xD;&#xA;&#xD;&#xA;Regards,&lt;br /&gt;&#xD;&#xA;Jorge Maldonado" ContentLicense="CC BY-SA 3.0" />
  <row Id="2881" PostHistoryTypeId="1" PostId="1610" RevisionGUID="3dabe777-dc9e-4962-ae99-e622a69075a5" CreationDate="2015-10-10T17:25:56.540" UserId="1836" Text="Parametric line intersection test" ContentLicense="CC BY-SA 3.0" />
  <row Id="2882" PostHistoryTypeId="3" PostId="1610" RevisionGUID="3dabe777-dc9e-4962-ae99-e622a69075a5" CreationDate="2015-10-10T17:25:56.540" UserId="1836" Text="|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2883" PostHistoryTypeId="2" PostId="1611" RevisionGUID="4e793c60-50b4-4669-8a94-a11e378f459f" CreationDate="2015-10-11T08:59:56.547" UserDisplayName="user1703" Text="**Hint**:&#xD;&#xA;&#xD;&#xA;The three coordinates can be handled independently.&#xD;&#xA;&#xD;&#xA;For instance in $x$, you need to solve&#xD;&#xA;&#xD;&#xA;$$x_0+t(x_1-x0)=0$$ and &#xD;&#xA;$$x_0+t(x_1-x0)=x_{max}.$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="2884" PostHistoryTypeId="5" PostId="1611" RevisionGUID="978d5215-9c7f-44bc-a416-1222b4cd1bbd" CreationDate="2015-10-11T18:41:42.943" UserDisplayName="user1703" Comment="added 2 characters in body" Text="**Hint**:&#xD;&#xA;&#xD;&#xA;The three coordinates can be handled independently.&#xD;&#xA;&#xD;&#xA;For instance in $x$, you need to solve&#xD;&#xA;&#xD;&#xA;$$x_0+t(x_1-x_0)=0$$ and &#xD;&#xA;$$x_0+t(x_1-x_0)=x_{max}.$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="2885" PostHistoryTypeId="8" PostId="1606" RevisionGUID="4660dfb8-739b-42ae-a8e3-eeb181595268" CreationDate="2015-10-11T20:05:40.437" UserId="231" Comment="Rollback to [b82dad0c-bdba-4236-a9d2-5eb4ba101e0d]" Text="I have the following problem:&#xD;&#xA;&#xD;&#xA;Give a matrix that will transform the point (x,y,z) into the point (2/(x+y), (5y + z)/(2x + 2y), 3)&#xD;&#xA;&#xD;&#xA;I have been reading my book to find a way to solve it without success. I will very much appreciate your feedback about how to solve it.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2890" PostHistoryTypeId="2" PostId="1613" RevisionGUID="446053d3-d982-43ca-ad14-6d5ba394c38d" CreationDate="2015-10-12T15:17:48.963" UserId="16" Text="(This answer is essentially the same as Stefan's but I wanted to add some detail about row and column vectors, and how to determine which you are using.)&#xD;&#xA;&#xD;&#xA;Yes, this is possible, but the details depend on whether you represent your vectors as rows or columns.&#xD;&#xA;&#xD;&#xA;### Column vectors&#xD;&#xA;&#xD;&#xA;If you are using *column* vectors, you will normally transform them by *left*-multiplying your matrices:&#xD;&#xA;&#xD;&#xA;    vector = mRotateZ * vector;&#xD;&#xA;    vector = mRotateX * vector;&#xD;&#xA;&#xD;&#xA;Of course, you can also do this in one step:&#xD;&#xA;&#xD;&#xA;    vector = mRotateX * mRotateZ * vector;&#xD;&#xA;&#xD;&#xA;But matrix multiplication is associative, which means it doesn't matter which multiplication is performed first, so if we write&#xD;&#xA;&#xD;&#xA;    Matrix mRotate = mRotateX * mRotateZ;&#xD;&#xA;    vector = mRotate * vector;&#xD;&#xA;&#xD;&#xA;we have now created a single matrix, which is equivalent to *first* rotating about `Z` and *second* about `X`. This generalises trivially for any number of transformations. Notice that transformations are applied from right to left.&#xD;&#xA;&#xD;&#xA;### Row vectors&#xD;&#xA;&#xD;&#xA;If, on the other hand, you are using *row* vectors, you will normally *right*-multiply your matrices:&#xD;&#xA;&#xD;&#xA;    vector = vector * mRotateZ;&#xD;&#xA;    vector = vector * mRotateX;&#xD;&#xA;&#xD;&#xA;Again, writing it in one step, we get&#xD;&#xA;&#xD;&#xA;    vector = vector * mRotateZ * mRotateX;&#xD;&#xA;&#xD;&#xA;which can be rewritten as&#xD;&#xA;&#xD;&#xA;    Matrix mRotate = mRotateZ * mRotateX;&#xD;&#xA;    vector = vector * mRotate;&#xD;&#xA;&#xD;&#xA;Notice that in this case, the transformations applied from left to right." ContentLicense="CC BY-SA 3.0" />
  <row Id="2891" PostHistoryTypeId="5" PostId="1611" RevisionGUID="231a3466-7f32-4c3a-8f52-ed0e37167561" CreationDate="2015-10-12T16:30:25.687" UserId="4" Comment="Replaced mathjax formatting with code formatting. Mathjax isn't available unfortunately, and its formatting makes the answer hard to read" Text="**Hint**:&#xD;&#xA;&#xD;&#xA;The three coordinates can be handled independently.&#xD;&#xA;&#xD;&#xA;For instance in `x`, you need to solve&#xD;&#xA;&#xD;&#xA;`x_0+t(x_1-x_0)=0` and  &#xD;&#xA;`x_0+t(x_1-x_0)=x_{max}.`" ContentLicense="CC BY-SA 3.0" />
  <row Id="2892" PostHistoryTypeId="24" PostId="1611" RevisionGUID="231a3466-7f32-4c3a-8f52-ed0e37167561" CreationDate="2015-10-12T16:30:25.687" Comment="Proposed by 4 approved by 100, 231 edit id of 62" ContentLicense="CC BY-SA 3.0" />
  <row Id="2893" PostHistoryTypeId="5" PostId="1610" RevisionGUID="15e67fd9-e3d9-4599-b34f-0c3b395532c7" CreationDate="2015-10-12T16:31:21.303" UserId="4" Comment="Removed signing, added quote formatting. " Text="I have the following question in an exam review and I am looking for feedback about how to approach the solution. Any advice will be highly appreciated.&#xD;&#xA;&#xD;&#xA;&gt; &quot;Using a parametric line intersection test, give the parameter values of the endpoints of a line from (3,3,4) to (11,8,7) clipped to the cube extending from 0 to 5 in x, y, and z&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2894" PostHistoryTypeId="24" PostId="1610" RevisionGUID="15e67fd9-e3d9-4599-b34f-0c3b395532c7" CreationDate="2015-10-12T16:31:21.303" Comment="Proposed by 4 approved by 100, 231 edit id of 61" ContentLicense="CC BY-SA 3.0" />
  <row Id="2895" PostHistoryTypeId="5" PostId="1611" RevisionGUID="9a7fae27-51bf-41a0-8191-2ec2adbd9969" CreationDate="2015-10-12T16:46:32.637" UserDisplayName="user1703" Comment="deleted 5 characters in body" Text="**Hint**:&#xD;&#xA;&#xD;&#xA;The three coordinates can be handled independently.&#xD;&#xA;&#xD;&#xA;For instance in `x`, you need to solve&#xD;&#xA;&#xD;&#xA;`x0 + t (x1-x0) = 0` and  &#xD;&#xA;`x0 + t (x1-x0) = xmax.`" ContentLicense="CC BY-SA 3.0" />
  <row Id="2896" PostHistoryTypeId="2" PostId="1614" RevisionGUID="d38dcd4d-5ce4-49bc-9453-d5fd08d87f54" CreationDate="2015-10-12T21:04:12.770" UserId="1699" Text="I have a sequence of compute shaders that generates an indexed mesh.The last one of those writes the generated indices like this:&#xD;&#xA;&#xD;&#xA;    void addTriangle (uint i0, uint i1, uint i2) {&#xD;&#xA;    	uint ic = atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;    	meshIndices[ic*3+0] = i0;&#xD;&#xA;    	meshIndices[ic*3+1] = i1;&#xD;&#xA;    	meshIndices[ic*3+2] = i2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After the mesh has been generated, it is drawn with [glDrawElementsIndirect][1]. The *indirectIndexCount* in the code above is an *atomic_uint* counter at position 0 inside the *GL_DRAW_INDIRECT_BUFFER* (see the struct called *DrawElementsIndirectCommand*). This counter is now obviously too small by a factor of three, since it was incremented only once for each triangle. Currently, I multiply it by 3 afterwards just before issuing the draw call.&#xD;&#xA;&#xD;&#xA;(At the moment this is done by mapping the buffer and multiplying on the CPU, which is of course nonsense, but shows that the whole thing basically works. Everything is drawn correctly. I could do it with an invocation of a single 1x1x1x1x1x1 compute shader, but that seems only slightly less silly.)&#xD;&#xA;&#xD;&#xA;How do I get rid of this extra multiplication step?&#xD;&#xA;&#xD;&#xA;Since this seems to be an obvious problem whenever meshes with variable index count are generated, I guess there must be some easy solution that I'm overlooking?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://docs.gl/gl4/glDrawElementsIndirect" ContentLicense="CC BY-SA 3.0" />
  <row Id="2897" PostHistoryTypeId="1" PostId="1614" RevisionGUID="d38dcd4d-5ce4-49bc-9453-d5fd08d87f54" CreationDate="2015-10-12T21:04:12.770" UserId="1699" Text="OpenGL Compute Shader generating triangle indices: How to get correct element count for glDrawElementsIndirect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2898" PostHistoryTypeId="3" PostId="1614" RevisionGUID="d38dcd4d-5ce4-49bc-9453-d5fd08d87f54" CreationDate="2015-10-12T21:04:12.770" UserId="1699" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2899" PostHistoryTypeId="2" PostId="1615" RevisionGUID="eb7bc6af-a73b-4947-ba40-7e4eb539a822" CreationDate="2015-10-13T05:32:32.323" UserId="1846" Text="I don't know if you would consider this to be a stretch for an answer to your question seeing as how I am a bit unsure how it was intended to be interpreted. That being considered, 2d barcodes can be graphics with which store code and interact with variable data elements defined throughout such symbologies as PDF417, DataMatrix, etc. " ContentLicense="CC BY-SA 3.0" />
  <row Id="2900" PostHistoryTypeId="5" PostId="1613" RevisionGUID="df0f80c5-9068-4721-8e3e-34e17841b25e" CreationDate="2015-10-13T07:36:02.573" UserId="16" Comment="added 49 characters in body" Text="(This answer is essentially the same as Stefan's but I wanted to add some detail about row and column vectors, and how to determine which you are using.)&#xD;&#xA;&#xD;&#xA;Yes, this is possible, but the details depend on whether you represent your vectors as rows or columns.&#xD;&#xA;&#xD;&#xA;### Column vectors&#xD;&#xA;&#xD;&#xA;If you are using *column* vectors, you will normally transform them by *left*-multiplying your matrices:&#xD;&#xA;&#xD;&#xA;    vector = mRotateZ * vector;&#xD;&#xA;    vector = mRotateX * vector;&#xD;&#xA;&#xD;&#xA;Of course, you can also do this in one step:&#xD;&#xA;&#xD;&#xA;    vector = mRotateX * mRotateZ * vector;&#xD;&#xA;&#xD;&#xA;But matrix multiplication is associative, which means it doesn't matter which multiplication is performed first:&#xD;&#xA;&#xD;&#xA;    A * B * C = (A * B) * C = A * (B * C)&#xD;&#xA;&#xD;&#xA;So we can write&#xD;&#xA;&#xD;&#xA;    Matrix mRotate = mRotateX * mRotateZ;&#xD;&#xA;    vector = mRotate * vector;&#xD;&#xA;&#xD;&#xA;We have now created a single matrix, which is equivalent to *first* rotating about `Z` and *second* about `X`. This generalises trivially for any number of transformations. Notice that transformations are applied from right to left.&#xD;&#xA;&#xD;&#xA;### Row vectors&#xD;&#xA;&#xD;&#xA;If, on the other hand, you are using *row* vectors, you will normally *right*-multiply your matrices:&#xD;&#xA;&#xD;&#xA;    vector = vector * mRotateZ;&#xD;&#xA;    vector = vector * mRotateX;&#xD;&#xA;&#xD;&#xA;Again, writing it in one step, we get&#xD;&#xA;&#xD;&#xA;    vector = vector * mRotateZ * mRotateX;&#xD;&#xA;&#xD;&#xA;which can be rewritten as&#xD;&#xA;&#xD;&#xA;    Matrix mRotate = mRotateZ * mRotateX;&#xD;&#xA;    vector = vector * mRotate;&#xD;&#xA;&#xD;&#xA;Notice that in this case, the transformations applied from left to right." ContentLicense="CC BY-SA 3.0" />
  <row Id="2901" PostHistoryTypeId="5" PostId="419" RevisionGUID="ff802a88-ab98-463e-9eb0-9d9546e4b16b" CreationDate="2015-10-13T08:00:28.470" UserId="209" Comment="added a missing &quot;to&quot;" Text="Just adding to imallett's answer, it is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can significantly influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can be costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting between 8bpp down to 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in HW, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how to spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to use of Twiddled-order textures in at least some early PC HW). &#xD;&#xA;&#xD;&#xA;  [1]: http://penguin.ewu.edu/class/cscd470/Winter_13/JimBlinnsCorner/TruthAboutTextureMapping.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2902" PostHistoryTypeId="2" PostId="1616" RevisionGUID="df8a1de6-c7ed-494b-a471-a67116646812" CreationDate="2015-10-13T08:36:08.430" UserId="137" Text="If you have access to glsl 4.3+ (or glsl ES 3.1) you can use [atomicAdd][1] &#xD;&#xA;&#xD;&#xA;The next option is to use a `barrier()` after all vertices are generated in the compute and then multiplying the value in the counter:&#xD;&#xA;&#xD;&#xA;    main(){&#xD;&#xA;    &#xD;&#xA;        // generate vertices&#xD;&#xA;    &#xD;&#xA;        barrier();&#xD;&#xA;        if(gl_localInvocationID == vec3(0)){&#xD;&#xA;            indirectCount = atomicCounter(indirectIndexCount)*3;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Otherwise you can use a second atomic to hold the vertexcount:&#xD;&#xA;&#xD;&#xA;    void addTriangle (uint i0, uint i1, uint i2) {&#xD;&#xA;        uint ic = atomicCounterIncrement(indirectIndex);&#xD;&#xA;        meshIndices[ic*3+0] = i0;&#xD;&#xA;        meshIndices[ic*3+1] = i1;&#xD;&#xA;        meshIndices[ic*3+2] = i2;&#xD;&#xA;        atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;        atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;        atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Both `indirectIndex` and `indirectIndexCount` are initialized to 0 and `indirectIndexCount` is what is passed through to  `glDrawElementsIndirect`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://docs.gl/sl4/atomicAdd" ContentLicense="CC BY-SA 3.0" />
  <row Id="2903" PostHistoryTypeId="5" PostId="1609" RevisionGUID="f59964ae-12ac-4aa5-bc9f-17cdb4807b2c" CreationDate="2015-10-13T11:58:18.750" UserId="1826" Comment="added 110 characters in body" Text="Yes, just multiply them in reverse order:&#xD;&#xA;&#xD;&#xA;    Matrix myrotation = Matrix.CreateRotationX(xrot) * Matrix.CreateRotationZ(zrot);&#xD;&#xA;&#xD;&#xA;**EDIT.** &#xD;&#xA;My answer only applies if you are using column vectors. Please see Martin Büttner detailed answer." ContentLicense="CC BY-SA 3.0" />
  <row Id="2904" PostHistoryTypeId="5" PostId="1616" RevisionGUID="e1505381-59ad-4534-b1d8-018c2422f49b" CreationDate="2015-10-13T14:44:20.010" UserId="137" Comment="added 77 characters in body" Text="If you have access to glsl 4.3+ (or glsl ES 3.1) you can use [atomicAdd][1] &#xD;&#xA;&#xD;&#xA;The next option is to use a `barrier()` after all vertices are generated in the compute and then multiplying the value in the counter:&#xD;&#xA;&#xD;&#xA;    main(){&#xD;&#xA;    &#xD;&#xA;        // generate vertices&#xD;&#xA;    &#xD;&#xA;        barrier();&#xD;&#xA;        if(gl_localInvocationID == vec3(0)){&#xD;&#xA;            indirectCount = atomicCounter(indirectIndexCount)*3;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This emulates running another 1x1x1 compute shader to multiply the index.&#xD;&#xA;&#xD;&#xA;Otherwise you can use a second atomic to hold the vertexcount:&#xD;&#xA;&#xD;&#xA;    void addTriangle (uint i0, uint i1, uint i2) {&#xD;&#xA;        uint ic = atomicCounterIncrement(indirectIndex);&#xD;&#xA;        meshIndices[ic*3+0] = i0;&#xD;&#xA;        meshIndices[ic*3+1] = i1;&#xD;&#xA;        meshIndices[ic*3+2] = i2;&#xD;&#xA;        atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;        atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;        atomicCounterIncrement(indirectIndexCount);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Both `indirectIndex` and `indirectIndexCount` are initialized to 0 and `indirectIndexCount` is what is passed through to  `glDrawElementsIndirect`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://docs.gl/sl4/atomicAdd" ContentLicense="CC BY-SA 3.0" />
  <row Id="2912" PostHistoryTypeId="5" PostId="1576" RevisionGUID="edd81c4d-7254-4d19-8b8d-0e894e4430d8" CreationDate="2015-10-14T11:43:16.537" UserId="182" Comment="Fixed a typo." Text="I see mainly three ways of computing normals for a generated shape.&#xD;&#xA;&#xD;&#xA;#Analytic normals&#xD;&#xA;&#xD;&#xA;In some cases you have enough information about the surface to generate the normals. For example, the normal of any point on a sphere is trivial to compute. Put simply, when you know the derivative of the function, you also know the normal.&#xD;&#xA;&#xD;&#xA;If your case is narrow enough to allow you to use analytic normals, they will probably give the best result in terms of precision. The technique doesn't scale too well though: if you also need to handle cases where you cannot use analytic normals, it may be easier to keep the technique that handles the general case and drop the analytic one altogether.&#xD;&#xA;&#xD;&#xA;#Vertex normals&#xD;&#xA;&#xD;&#xA;The cross product of two vectors gives a vector perpendicular to the plane they belong to. So getting the normal of a triangle is straightforward:&#xD;&#xA;&#xD;&#xA;    vec3 computeNormal(vec3 a, vec3 b, vec3 c)&#xD;&#xA;    {&#xD;&#xA;        return normalize(crossProduct(b - a, c - a));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Moreover, in the above example, the length of the cross product is proportional to the area inside _abc_. So the smoothed normal at a vertex shared by several triangles can be computed by summing up the cross products and normalizing as a last step, thus weighting each triangle by its area.&#xD;&#xA;&#xD;&#xA;    vec3 computeNormal(vertex a)&#xD;&#xA;    {&#xD;&#xA;        vec3 sum = vec3(0, 0, 0);&#xD;&#xA;        list&lt;vertex&gt; adjacentVertices = getAdjacentVertices(a);&#xD;&#xA;        for (int i = 1; i &lt; adjacentVertices; ++i)&#xD;&#xA;        {&#xD;&#xA;            vec3 b = adjacentVertices[i - 1];&#xD;&#xA;            vec3 c = adjacentVertices[i];&#xD;&#xA;            sum += crossProduct(b - a, c - a);&#xD;&#xA;        }&#xD;&#xA;        if (norm(sum) == 0)&#xD;&#xA;        {&#xD;&#xA;            // Degenerate case&#xD;&#xA;            return sum;&#xD;&#xA;        }&#xD;&#xA;        return normalize(sum);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are working with quads, there is a nice trick you can use: for a quad _abcd_, use `crossProduct(c - a, d - b)` and it will handle nicely cases where the quad is in fact a triangle.&#xD;&#xA;&#xD;&#xA;Iñigo quilez wrote a few short articles on the topic: [clever normalization of a mesh](http://www.iquilezles.org/www/articles/normals/normals.htm), and [normal and area of n sided polygons](http://iquilezles.org/www/articles/areas/areas.htm).&#xD;&#xA;&#xD;&#xA;#Normals from partial derivatives&#xD;&#xA;&#xD;&#xA;Normals can be computed in the fragment shader from the partial derivatives. The math behind is the same, except this time it is done in screen space. This article by Angelo Pesce describes the technique: [Normals without normals](http://c0de517e.blogspot.jp/2008/10/normals-without-normals.html).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2913" PostHistoryTypeId="2" PostId="1618" RevisionGUID="429979fd-d520-4d98-a406-707d26da5fd1" CreationDate="2015-10-14T16:51:06.533" UserId="523" Text="My raytracer supports a wide variety of objects.  To intersect them, I use the standard technique of transforming rays into object-space.  This works fantastically until I add motion blur.&#xD;&#xA;&#xD;&#xA;I model motion blur as a sequence of transforms (to simplify discussion, let's say exactly two) instead of one.  My approach is to take the inverse transform of the ray at both keyframes and lerp the positions/directions.&#xD;&#xA;&#xD;&#xA;This seems to work fine for translations, but it breaks down for rotations.  E.g. here's a triangle undergoing a 30 degree rotation:&#xD;&#xA;&#xD;&#xA;[![rotation 1][1]][1]&lt;br/&gt;&#xD;&#xA;&lt;sup&gt;(4 samples, MN reconstruction, the red samples came from near the two keyframes)&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;At the corners, I would expect the lerped samples to lie on a straight line between the the two vertices.  Instead, they bulge outward.  This is wrong.  In more interesting scenes with more interesting transformations, it causes a variety of failure modes.  E.g. here's a propeller undergoing a 45 rotation:&#xD;&#xA;&#xD;&#xA;[![rotation 2][2]][2]&lt;br/&gt;&#xD;&#xA;&lt;sup&gt;(100 samples, normals visualized)&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Some problems are due to the BVH breaking (it assumes the extrema of objects lie at keyframes), but even a brute force render is incorrect.&#xD;&#xA;&#xD;&#xA;I can fix all this by doing forward transforms only (transform object, not the ray), but this only works for objects where that is possible (only triangles, really).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**How can I make my raytracer produce linear approximations to transformation (especially rotation) by transforming rays, not objects?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zePY5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/8kcIi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2914" PostHistoryTypeId="1" PostId="1618" RevisionGUID="429979fd-d520-4d98-a406-707d26da5fd1" CreationDate="2015-10-14T16:51:06.533" UserId="523" Text="Ray Transformation to Object Space for Motion Blur" ContentLicense="CC BY-SA 3.0" />
  <row Id="2915" PostHistoryTypeId="3" PostId="1618" RevisionGUID="429979fd-d520-4d98-a406-707d26da5fd1" CreationDate="2015-10-14T16:51:06.533" UserId="523" Text="|raytracing|transformations|motion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2916" PostHistoryTypeId="2" PostId="1619" RevisionGUID="ba46a8d6-9670-42ee-9f36-fc3647e20f11" CreationDate="2015-10-14T17:48:09.203" UserId="48" Text="Lerping the ray positions/directions between keyframes should be equivalent to lerping the inverse matrices between keyframes and transforming by the lerped matrix. Trouble is, if the keyframes have different rotations, that lerped matrix will in general be something &quot;weird&quot;, with shearing, nonuniform scale, etc.&#xD;&#xA;&#xD;&#xA;I wouldn't be surprised if some of your intersection and shading routines don't work properly in such a distorted coordinate system, unless you've specifically tested and hardened them against such cases. (For example, taking the dot product of two unit vectors doesn't give the same answer in a sheared coordinate system as in an orthonormal one.)&#xD;&#xA;&#xD;&#xA;This is just a guess, but it might work better if you choose an interpolation method where the translation, rotation, and scale (if applicable) are lerped separately (using quaternions for the rotation part) and re-combined." ContentLicense="CC BY-SA 3.0" />
  <row Id="2917" PostHistoryTypeId="2" PostId="1620" RevisionGUID="d60a83d9-5b9e-4f3a-8bd8-89a33d3708e2" CreationDate="2015-10-14T17:56:16.040" UserId="209" Text="I don't think you'll get terribly far with, AFAICS, a single linear approximation to a rather non-linear interpolation, but perhaps this [paper / presentation](http://fileadmin.cs.lth.se/graphics/research/papers/2013/highorder/) by Gribel et al on motion blur in rasterisation may help.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2918" PostHistoryTypeId="2" PostId="1621" RevisionGUID="ecec970b-9ef6-4ace-bc19-41670cf38e8a" CreationDate="2015-10-14T18:02:21.180" UserId="127" Text="The hint with the perspective division was already [mentioned by ratchet freak](http://computergraphics.stackexchange.com/a/1607/127), but I'd like to add some explanation of how to come up with the solution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First of all, remember that homogenous coordinates add a fourth value `w` to your 3D vector. For points in the 3D space, `w != 0` holds and `[x, y, z, w] == [n*x, n*y, n*z, n*w]` also holds for every `n`.&#xD;&#xA;&#xD;&#xA;Now the goal is to find a transformation matrix `T`, which solves&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;       2/(x + y)                       x         t11 t21 t31 t41       x&#xD;&#xA;    5(y + z)/(2x + 2y)                 y         t12 t22 t32 t42       y&#xD;&#xA;           3              =    T   *   z    =    t13 t23 t33 t43   *   z&#xD;&#xA;           1                           1         t14 t24 t34 t44       1&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;Imagine some fancy typesetting and brackets around the vectors and the matrix.&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;These are basically four equations, but having a look at the first row, being&#xD;&#xA;&#xD;&#xA;    2/(x + y) = t11*x + t21*y + t31z + t41&#xD;&#xA;&#xD;&#xA;and trying to find values for the `t`s, you'll see that this is not possible without further restructuring. The main problems are the `x` and `y` in the denominator. But as we can make use of the fourth value in the vector, we can expand the w.&#xD;&#xA;&#xD;&#xA;       2/(x + y)                   2/(x + y)                  2&#xD;&#xA;    5(y + z)/(2x + 2y)         2.5(y + z)/(x + y)         2.5(y + z)&#xD;&#xA;           3              =           3              =     3(x + y)&#xD;&#xA;           1                          1                     x + y&#xD;&#xA;&#xD;&#xA;In the first step, I removed the factor of `2` from the second values denominator, leading to every values denominator either being `1` or `(x + y)`. In the second step, I made use of the above mentioned rule (`[x, y, z, w] == [n*x, n*y, n*z, n*w]`), setting `n = (x + y)`, thus eliminating the denominator of the first two values.&#xD;&#xA;&#xD;&#xA;Now we've got&#xD;&#xA;&#xD;&#xA;        2              t11 t21 t31 t41       x&#xD;&#xA;    2.5(y + z)         t12 t22 t32 t42       y&#xD;&#xA;     3(x + y)     =    t13 t23 t33 t43   *   z&#xD;&#xA;      x + y            t14 t24 t34 t44       1&#xD;&#xA;&#xD;&#xA;which is not that hard anymore.&#xD;&#xA;&#xD;&#xA;        2              0    0    0    2       x&#xD;&#xA;    2.5(y + z)         0   2.5  2.5   0       y&#xD;&#xA;     3(x + y)     =    3    3    0    0   *   z&#xD;&#xA;      x + y            1    1    0    0       1&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;* Remember the advantage of homogenous coordinates `w`.&#xD;&#xA;* `[x, y, z, w] == [n*x, n*y, n*z, n*w]` is the key.&#xD;&#xA;* Push everything that's in the denominator to the `w` coordinate." ContentLicense="CC BY-SA 3.0" />
  <row Id="2919" PostHistoryTypeId="5" PostId="1618" RevisionGUID="3f90d7c5-c997-4dd8-af3d-bf20533640c9" CreationDate="2015-10-14T20:56:33.537" UserId="523" Comment="update image to composite with another example" Text="My raytracer supports a wide variety of objects.  To intersect them, I use the standard technique of transforming rays into object-space.  This works fantastically until I add motion blur.&#xD;&#xA;&#xD;&#xA;I model motion blur as a sequence of transforms (to simplify discussion, let's say exactly two) instead of one.  My approach is to take the inverse transform of the ray at both keyframes and lerp the positions/directions.&#xD;&#xA;&#xD;&#xA;This seems to work fine for translations, but it breaks down for rotations.  E.g. here are two triangles undergoing 30 and 90 degree rotations:&#xD;&#xA;&#xD;&#xA;[![rotation1][1]][1]&lt;br/&gt;&#xD;&#xA;&lt;sup&gt;(4 samples, MN reconstruction, the red samples came from near the two keyframes)&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;At the corners, I would expect the lerped samples to lie on a straight line between the the two vertices.  Instead, they bulge outward.  This is wrong.  In more interesting scenes with more interesting transformations, it causes a variety of failure modes.  E.g. here's a propeller undergoing a 45 rotation:&#xD;&#xA;&#xD;&#xA;[![rotation 2][2]][2]&lt;br/&gt;&#xD;&#xA;&lt;sup&gt;(100 samples, normals visualized)&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Some problems are due to the BVH breaking (it assumes the extrema of objects lie at keyframes), but even a brute force render is incorrect.&#xD;&#xA;&#xD;&#xA;I can fix all this by doing forward transforms only (transform object, not the ray), but this only works for objects where that is possible (only triangles, really).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**How can I make my raytracer produce linear approximations to transformation (especially rotation) by transforming rays, not objects?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DRHf1.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/8kcIi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2921" PostHistoryTypeId="2" PostId="1622" RevisionGUID="0831bf55-b775-4c0a-b02f-ff9b54926f6a" CreationDate="2015-10-15T07:33:36.113" UserId="1861" Text="I'm trying to learn GLSL, I'm following [this][1] tutorial. Iv done everything according to the tutorials but I cant get any output from my code, As you see I'm checking for both compile errors and linker errors and everything is fine, GLSL code compiles and links fine but there is no output but a red window. Here is my code:&#xD;&#xA; &#xD;&#xA;maain.cpp &#xD;&#xA;&#xD;&#xA;    #include &lt;QApplication&gt;&#xD;&#xA;    #include &lt;GlWindow.h&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char *argv[]){&#xD;&#xA;        QApplication app(argc, argv);&#xD;&#xA;    &#xD;&#xA;        GlWindow glWindow;&#xD;&#xA;        glWindow.show();&#xD;&#xA;    &#xD;&#xA;        return app.exec();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;GLWindow.h&#xD;&#xA;&#xD;&#xA;    #ifndef GLWINDOW_H&#xD;&#xA;    #define GLWINDOW_H&#xD;&#xA;    #include &lt;QtOpenGL/QGLWidget&gt;&#xD;&#xA;    #include &lt;QOpenGLWidget&gt;&#xD;&#xA;    &#xD;&#xA;    class GlWindow : public QGLWidget{&#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    protected:&#xD;&#xA;        void initializeGL();&#xD;&#xA;        void paintGL();&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    #endif // GLWINDOW_H&#xD;&#xA;&#xD;&#xA;GLWindow.cpp&#xD;&#xA;&#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &quot;GlWindow.h&quot;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    extern const char* vertexShaderCode;&#xD;&#xA;    extern const char* fragmentShaderCode;&#xD;&#xA;    &#xD;&#xA;    void sendDataToOpenGL(){&#xD;&#xA;        GLfloat verts[] = {&#xD;&#xA;            +0.0f, +0.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        GLuint verexBufferID;&#xD;&#xA;        glGenBuffers(1, &amp;verexBufferID);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, verexBufferID);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0,2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5,0);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat), (char*)(sizeof(GLfloat) * 2));&#xD;&#xA;    &#xD;&#xA;        GLuint indices [] = {0,1,2, 0,3,4};&#xD;&#xA;        GLuint indexBufferID;&#xD;&#xA;        glGenBuffers(1,&amp;indexBufferID);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool checkShaderStatus(GLuint shaderID){&#xD;&#xA;        GLint compileStatus;&#xD;&#xA;        glGetShaderiv(shaderID, GL_COMPILE_STATUS, &amp;compileStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(compileStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetShaderInfoLog(shaderID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool checkProgramStatus(GLuint programID){&#xD;&#xA;        GLint linkStatus;&#xD;&#xA;        glGetProgramiv(programID, GL_LINK_STATUS, &amp;linkStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(linkStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetProgramInfoLog(programID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;    &#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void installShaders(){&#xD;&#xA;    &#xD;&#xA;        GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;        GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    &#xD;&#xA;        const char *adapter[1];&#xD;&#xA;        adapter[0] = vertexShaderCode;&#xD;&#xA;    &#xD;&#xA;        glShaderSource(vertexShaderID, 1, adapter, 0);&#xD;&#xA;        adapter[0] = fragmentShaderCode;&#xD;&#xA;        glShaderSource(fragmentShaderID, 1, adapter, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        glCompileShader(vertexShaderID);&#xD;&#xA;        glCompileShader(fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(vertexShaderID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;Sth wrong with vertex shader&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(fragmentShaderID)){&#xD;&#xA;           std::cerr&lt;&lt;&quot;Sth wrong with fragment shader&quot;&lt;&lt;std::endl;&#xD;&#xA;           return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        GLuint programID = glCreateProgram();&#xD;&#xA;        glAttachShader(programID, vertexShaderID);&#xD;&#xA;        glAttachShader(programID, fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        glLinkProgram(programID);&#xD;&#xA;    &#xD;&#xA;        if(!checkProgramStatus(programID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed to link&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glUseProgram(programID);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void GlWindow::paintGL(){&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        glViewport(0,0,width(), height());&#xD;&#xA;    &#xD;&#xA;        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void GlWindow::initializeGL(){&#xD;&#xA;        glewInit();&#xD;&#xA;    &#xD;&#xA;        const GLubyte *shaderVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);&#xD;&#xA;        std::cout&lt;&lt;shaderVersion&lt;&lt;std::endl;&#xD;&#xA;    &#xD;&#xA;        sendDataToOpenGL();&#xD;&#xA;        installShaders();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and finaly my shader code: &#xD;&#xA;&#xD;&#xA;    const char* vertexShaderCode  =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;in layout(location=0) vec2 position;\n&quot;&#xD;&#xA;            &quot;in layout(location=1) vec3 vertexColor;\n&quot;&#xD;&#xA;            &quot;&quot;&#xD;&#xA;            &quot;out vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;gl_Position = vec4(position, 0.0, 1.0);\n&quot;&#xD;&#xA;            &quot;theColor = vertexColor; \n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    const char* fragmentShaderCode =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;out vec4 daColor;\n&quot;&#xD;&#xA;            &quot;in vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot; daColor = vec4(theColor,1.0);\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;&#xD;&#xA;I know that my shader code looks stupid but I'm just trying to learn. &#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2922" PostHistoryTypeId="1" PostId="1622" RevisionGUID="0831bf55-b775-4c0a-b02f-ff9b54926f6a" CreationDate="2015-10-15T07:33:36.113" UserId="1861" Text="Cant get output from a GLSL code" ContentLicense="CC BY-SA 3.0" />
  <row Id="2923" PostHistoryTypeId="3" PostId="1622" RevisionGUID="0831bf55-b775-4c0a-b02f-ff9b54926f6a" CreationDate="2015-10-15T07:33:36.113" UserId="1861" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2924" PostHistoryTypeId="2" PostId="1623" RevisionGUID="7a683230-9f5c-41f0-a460-9eb3997da3f9" CreationDate="2015-10-15T08:06:54.277" UserId="110" Text="Spherical harmonics appear in several computer graphics techniques.&#xD;&#xA;I feel that in order to be a better computer graphics developer, I need to have a deep understanding of what they are and how they are used.&#xD;&#xA;&#xD;&#xA;It seems that the reference most often recommended to understand Spherical Harmonics is [&quot;Stupid Spherical Harmonics Tricks&quot; by Peter-Pike Sloan][1].&#xD;&#xA;&#xD;&#xA;I started reading it but did not find a &quot;satisfying&quot; definition of SH, it seems like the document mostly relies on other references for the &quot;basics&quot;.&#xD;&#xA;Other references introduce the Fourier Basis functions as a &quot;simpler version&quot; of SH, but once again it seems hard to find good material explaining them.&#xD;&#xA;&#xD;&#xA;What are thorough, accessible references to understand Fourier basis functions and Spherical Harmonics ?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.ppsloan.org/publications/StupidSH36.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2925" PostHistoryTypeId="1" PostId="1623" RevisionGUID="7a683230-9f5c-41f0-a460-9eb3997da3f9" CreationDate="2015-10-15T08:06:54.277" UserId="110" Text="Thorough, accessible material about Fourier basis functions and Spherical Harmonics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2926" PostHistoryTypeId="3" PostId="1623" RevisionGUID="7a683230-9f5c-41f0-a460-9eb3997da3f9" CreationDate="2015-10-15T08:06:54.277" UserId="110" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2929" PostHistoryTypeId="2" PostId="1624" RevisionGUID="436e3810-bd2d-4cb4-9232-7fe266ac2953" CreationDate="2015-10-15T09:09:14.390" UserId="1863" Text="So I need to print out [this][1] model, however with default sizes, one of the pieces is too large for my printer (M3D). I will need to scale it down.. the question is, do I need to scale the rest of the individual objects (pieces) in the same proportions, so I will be able to assemble all the parts afterwards ? This might be a bit of a stupid question, but I don't have any experience with 3D printing yet.. thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.myminifactory.com/object/engine-1406&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2930" PostHistoryTypeId="1" PostId="1624" RevisionGUID="436e3810-bd2d-4cb4-9232-7fe266ac2953" CreationDate="2015-10-15T09:09:14.390" UserId="1863" Text="Scaling models for 3D print" ContentLicense="CC BY-SA 3.0" />
  <row Id="2931" PostHistoryTypeId="3" PostId="1624" RevisionGUID="436e3810-bd2d-4cb4-9232-7fe266ac2953" CreationDate="2015-10-15T09:09:14.390" UserId="1863" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2934" PostHistoryTypeId="5" PostId="419" RevisionGUID="56a20ae7-aa82-4349-a710-dac685df54fe" CreationDate="2015-10-15T10:17:25.033" UserId="209" Comment="Fixed some of the expressions, expanded some contractions, and added a reference." Text="Just adding to imallett's answer, it is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can significantly influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can be costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting from 8bpp down to, say, 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in hardware, that the data *could* stay compressed throughout the entire cache hierarchy, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how to spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading, try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to the use of Twiddled-order (i.e. Morton order) textures in [at least some early PC hardware](http://worldwide.espacenet.com/publicationDetails/originalDocument?FT=D&amp;date=19960814&amp;DB=EPODOC&amp;locale=en_ep&amp;CC=GB&amp;NR=2297886A&amp;KC=A&amp;ND=4)). &#xD;&#xA;&#xD;&#xA;  [1]: http://penguin.ewu.edu/class/cscd470/Winter_13/JimBlinnsCorner/TruthAboutTextureMapping.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2935" PostHistoryTypeId="2" PostId="1625" RevisionGUID="c1a58351-7ffc-43fc-a40d-3ccab81c4ba7" CreationDate="2015-10-15T11:16:19.893" UserId="1810" Text="Just like for any reduction or drawing, if you scale one part and not the other, their relative proportion is changed, so yes, aesthetic, matching, functionality are affected: scale everything in the same proportion. Nothing specific to 3D printing here." ContentLicense="CC BY-SA 3.0" />
  <row Id="2937" PostHistoryTypeId="5" PostId="1622" RevisionGUID="0fed60f1-6510-4c04-bfd9-6389f933a216" CreationDate="2015-10-15T12:52:11.063" UserId="1861" Comment="Fixed a little bug in code " Text="I'm trying to learn GLSL, I'm following [this][1] tutorial. Iv done everything according to the tutorials but I cant get any output from my code, As you see I'm checking for both compile errors and linker errors and everything is fine, GLSL code compiles and links fine but there is no output but a red window. Here is my code:&#xD;&#xA; &#xD;&#xA;maain.cpp &#xD;&#xA;&#xD;&#xA;    #include &lt;QApplication&gt;&#xD;&#xA;    #include &lt;GlWindow.h&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char *argv[]){&#xD;&#xA;        QApplication app(argc, argv);&#xD;&#xA;    &#xD;&#xA;        GlWindow glWindow;&#xD;&#xA;        glWindow.show();&#xD;&#xA;    &#xD;&#xA;        return app.exec();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;GLWindow.h&#xD;&#xA;&#xD;&#xA;    #ifndef GLWINDOW_H&#xD;&#xA;    #define GLWINDOW_H&#xD;&#xA;    #include &lt;QtOpenGL/QGLWidget&gt;&#xD;&#xA;    #include &lt;QOpenGLWidget&gt;&#xD;&#xA;    &#xD;&#xA;    class GlWindow : public QGLWidget{&#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    protected:&#xD;&#xA;        void initializeGL();&#xD;&#xA;        void paintGL();&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    #endif // GLWINDOW_H&#xD;&#xA;&#xD;&#xA;GLWindow.cpp&#xD;&#xA;&#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &quot;GlWindow.h&quot;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    extern const char* vertexShaderCode;&#xD;&#xA;    extern const char* fragmentShaderCode;&#xD;&#xA;    &#xD;&#xA;    void sendDataToOpenGL(){&#xD;&#xA;        GLfloat verts[] = {&#xD;&#xA;            +0.0f, +0.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        GLuint verexBufferID;&#xD;&#xA;        glGenBuffers(1, &amp;verexBufferID);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, verexBufferID);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0,2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5,0);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (char*)(sizeof(GLfloat) * 2));&#xD;&#xA;    &#xD;&#xA;        GLuint indices [] = {0,1,2, 0,3,4};&#xD;&#xA;        GLuint indexBufferID;&#xD;&#xA;        glGenBuffers(1,&amp;indexBufferID);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool checkShaderStatus(GLuint shaderID){&#xD;&#xA;        GLint compileStatus;&#xD;&#xA;        glGetShaderiv(shaderID, GL_COMPILE_STATUS, &amp;compileStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(compileStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetShaderInfoLog(shaderID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool checkProgramStatus(GLuint programID){&#xD;&#xA;        GLint linkStatus;&#xD;&#xA;        glGetProgramiv(programID, GL_LINK_STATUS, &amp;linkStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(linkStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetProgramInfoLog(programID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;    &#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void installShaders(){&#xD;&#xA;    &#xD;&#xA;        GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;        GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    &#xD;&#xA;        const char *adapter[1];&#xD;&#xA;        adapter[0] = vertexShaderCode;&#xD;&#xA;    &#xD;&#xA;        glShaderSource(vertexShaderID, 1, adapter, 0);&#xD;&#xA;        adapter[0] = fragmentShaderCode;&#xD;&#xA;        glShaderSource(fragmentShaderID, 1, adapter, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        glCompileShader(vertexShaderID);&#xD;&#xA;        glCompileShader(fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(vertexShaderID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;Sth wrong with vertex shader&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(fragmentShaderID)){&#xD;&#xA;           std::cerr&lt;&lt;&quot;Sth wrong with fragment shader&quot;&lt;&lt;std::endl;&#xD;&#xA;           return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        GLuint programID = glCreateProgram();&#xD;&#xA;        glAttachShader(programID, vertexShaderID);&#xD;&#xA;        glAttachShader(programID, fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        glLinkProgram(programID);&#xD;&#xA;    &#xD;&#xA;        if(!checkProgramStatus(programID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed to link&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glUseProgram(programID);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void GlWindow::paintGL(){&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        glViewport(0,0,width(), height());&#xD;&#xA;    &#xD;&#xA;        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void GlWindow::initializeGL(){&#xD;&#xA;        glewInit();&#xD;&#xA;    &#xD;&#xA;        const GLubyte *shaderVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);&#xD;&#xA;        std::cout&lt;&lt;shaderVersion&lt;&lt;std::endl;&#xD;&#xA;    &#xD;&#xA;        sendDataToOpenGL();&#xD;&#xA;        installShaders();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and finaly my shader code: &#xD;&#xA;&#xD;&#xA;    const char* vertexShaderCode  =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;in layout(location=0) vec2 position;\n&quot;&#xD;&#xA;            &quot;in layout(location=1) vec3 vertexColor;\n&quot;&#xD;&#xA;            &quot;&quot;&#xD;&#xA;            &quot;out vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;gl_Position = vec4(position, 0.0, 1.0);\n&quot;&#xD;&#xA;            &quot;theColor = vertexColor; \n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    const char* fragmentShaderCode =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;out vec4 daColor;\n&quot;&#xD;&#xA;            &quot;in vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot; daColor = vec4(theColor,1.0);\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;&#xD;&#xA;I know that my shader code looks stupid but I'm just trying to learn. &#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2938" PostHistoryTypeId="5" PostId="1622" RevisionGUID="aafb1522-a007-4ddc-bc38-0657cac9a607" CreationDate="2015-10-15T12:59:34.860" UserId="1861" Comment="Fixed a little bug in code, some details added, an other tag added" Text="I'm trying to learn GLSL, I'm following [this][1] tutorial. Iv done everything according to the tutorials but I cant get any output from my code, As you see I'm checking for both compile errors and linker errors and everything is fine, GLSL code compiles and links fine but there is no output but a red window. Here is my code:&#xD;&#xA; &#xD;&#xA;main.cpp &#xD;&#xA;&#xD;&#xA;    #include &lt;QApplication&gt;&#xD;&#xA;    #include &lt;GlWindow.h&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char *argv[]){&#xD;&#xA;        QApplication app(argc, argv);&#xD;&#xA;    &#xD;&#xA;        GlWindow glWindow;&#xD;&#xA;        glWindow.show();&#xD;&#xA;    &#xD;&#xA;        return app.exec();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;GLWindow.h&#xD;&#xA;&#xD;&#xA;    #ifndef GLWINDOW_H&#xD;&#xA;    #define GLWINDOW_H&#xD;&#xA;    #include &lt;QtOpenGL/QGLWidget&gt;&#xD;&#xA;    #include &lt;QOpenGLWidget&gt;&#xD;&#xA;    &#xD;&#xA;    class GlWindow : public QGLWidget{&#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    protected:&#xD;&#xA;        void initializeGL();&#xD;&#xA;        void paintGL();&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    #endif // GLWINDOW_H&#xD;&#xA;&#xD;&#xA;GLWindow.cpp&#xD;&#xA;&#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &quot;GlWindow.h&quot;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    extern const char* vertexShaderCode;&#xD;&#xA;    extern const char* fragmentShaderCode;&#xD;&#xA;    &#xD;&#xA;    void sendDataToOpenGL(){&#xD;&#xA;        GLfloat verts[] = {&#xD;&#xA;            +0.0f, +0.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        GLuint verexBufferID;&#xD;&#xA;        glGenBuffers(1, &amp;verexBufferID);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, verexBufferID);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0,2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5,0);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (char*)(sizeof(GLfloat) * 2));&#xD;&#xA;    &#xD;&#xA;        GLuint indices [] = {0,1,2, 0,3,4};&#xD;&#xA;        GLuint indexBufferID;&#xD;&#xA;        glGenBuffers(1,&amp;indexBufferID);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool checkShaderStatus(GLuint shaderID){&#xD;&#xA;        GLint compileStatus;&#xD;&#xA;        glGetShaderiv(shaderID, GL_COMPILE_STATUS, &amp;compileStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(compileStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetShaderInfoLog(shaderID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool checkProgramStatus(GLuint programID){&#xD;&#xA;        GLint linkStatus;&#xD;&#xA;        glGetProgramiv(programID, GL_LINK_STATUS, &amp;linkStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(linkStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetProgramInfoLog(programID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;    &#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void installShaders(){&#xD;&#xA;    &#xD;&#xA;        GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;        GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    &#xD;&#xA;        const char *adapter[1];&#xD;&#xA;        adapter[0] = vertexShaderCode;&#xD;&#xA;    &#xD;&#xA;        glShaderSource(vertexShaderID, 1, adapter, 0);&#xD;&#xA;        adapter[0] = fragmentShaderCode;&#xD;&#xA;        glShaderSource(fragmentShaderID, 1, adapter, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        glCompileShader(vertexShaderID);&#xD;&#xA;        glCompileShader(fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(vertexShaderID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;Sth wrong with vertex shader&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(fragmentShaderID)){&#xD;&#xA;           std::cerr&lt;&lt;&quot;Sth wrong with fragment shader&quot;&lt;&lt;std::endl;&#xD;&#xA;           return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        GLuint programID = glCreateProgram();&#xD;&#xA;        glAttachShader(programID, vertexShaderID);&#xD;&#xA;        glAttachShader(programID, fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        glLinkProgram(programID);&#xD;&#xA;    &#xD;&#xA;        if(!checkProgramStatus(programID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed to link&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glUseProgram(programID);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void GlWindow::paintGL(){&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        glViewport(0,0,width(), height());&#xD;&#xA;    &#xD;&#xA;        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void GlWindow::initializeGL(){&#xD;&#xA;        glewInit();&#xD;&#xA;    &#xD;&#xA;        const GLubyte *shaderVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);&#xD;&#xA;        std::cout&lt;&lt;shaderVersion&lt;&lt;std::endl;&#xD;&#xA;    &#xD;&#xA;        sendDataToOpenGL();&#xD;&#xA;        installShaders();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and finaly my shader code: &#xD;&#xA;&#xD;&#xA;    const char* vertexShaderCode  =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;in layout(location=0) vec2 position;\n&quot;&#xD;&#xA;            &quot;in layout(location=1) vec3 vertexColor;\n&quot;&#xD;&#xA;            &quot;&quot;&#xD;&#xA;            &quot;out vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;gl_Position = vec4(position, 0.0, 1.0);\n&quot;&#xD;&#xA;            &quot;theColor = vertexColor; \n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    const char* fragmentShaderCode =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;out vec4 daColor;\n&quot;&#xD;&#xA;            &quot;in vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot; daColor = vec4(theColor,1.0);\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;&#xD;&#xA;I know that my shader code looks stupid but I'm just trying to learn. &#xD;&#xA;&#xD;&#xA;**EDIT:** I dont know if thats relevant But Im using ubuntu 15.0 and `glGetString(GL_SHADING_LANGUAGE_VERSION)` returns: `4.4 nvidia via cg compiler`.  &#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2939" PostHistoryTypeId="6" PostId="1622" RevisionGUID="aafb1522-a007-4ddc-bc38-0657cac9a607" CreationDate="2015-10-15T12:59:34.860" UserId="1861" Comment="Fixed a little bug in code, some details added, an other tag added" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2942" PostHistoryTypeId="5" PostId="1622" RevisionGUID="1f4ecd25-4648-43f3-8e3b-2bc01f2a088b" CreationDate="2015-10-15T15:12:19.413" UserId="127" Comment="Improved grammar" Text="I'm trying to learn GLSL, I'm following [this][1] tutorial. I've done everything according to the tutorials but I can't get any output from my code. As you see I'm checking for both compile errors and linker errors and everything is fine, GLSL code compiles and links fine but there is no output but a red window. Here is my code:&#xD;&#xA; &#xD;&#xA;main.cpp &#xD;&#xA;&#xD;&#xA;    #include &lt;QApplication&gt;&#xD;&#xA;    #include &lt;GlWindow.h&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char *argv[]){&#xD;&#xA;        QApplication app(argc, argv);&#xD;&#xA;    &#xD;&#xA;        GlWindow glWindow;&#xD;&#xA;        glWindow.show();&#xD;&#xA;    &#xD;&#xA;        return app.exec();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;GLWindow.h&#xD;&#xA;&#xD;&#xA;    #ifndef GLWINDOW_H&#xD;&#xA;    #define GLWINDOW_H&#xD;&#xA;    #include &lt;QtOpenGL/QGLWidget&gt;&#xD;&#xA;    #include &lt;QOpenGLWidget&gt;&#xD;&#xA;    &#xD;&#xA;    class GlWindow : public QGLWidget{&#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    protected:&#xD;&#xA;        void initializeGL();&#xD;&#xA;        void paintGL();&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    #endif // GLWINDOW_H&#xD;&#xA;&#xD;&#xA;GLWindow.cpp&#xD;&#xA;&#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &quot;GlWindow.h&quot;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    extern const char* vertexShaderCode;&#xD;&#xA;    extern const char* fragmentShaderCode;&#xD;&#xA;    &#xD;&#xA;    void sendDataToOpenGL(){&#xD;&#xA;        GLfloat verts[] = {&#xD;&#xA;            +0.0f, +0.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, +1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            -1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;            +1.0f, -1.0f,&#xD;&#xA;                 1.0f, 0.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        GLuint verexBufferID;&#xD;&#xA;        glGenBuffers(1, &amp;verexBufferID);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, verexBufferID);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0,2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5,0);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (char*)(sizeof(GLfloat) * 2));&#xD;&#xA;    &#xD;&#xA;        GLuint indices [] = {0,1,2, 0,3,4};&#xD;&#xA;        GLuint indexBufferID;&#xD;&#xA;        glGenBuffers(1,&amp;indexBufferID);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool checkShaderStatus(GLuint shaderID){&#xD;&#xA;        GLint compileStatus;&#xD;&#xA;        glGetShaderiv(shaderID, GL_COMPILE_STATUS, &amp;compileStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(compileStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetShaderInfoLog(shaderID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool checkProgramStatus(GLuint programID){&#xD;&#xA;        GLint linkStatus;&#xD;&#xA;        glGetProgramiv(programID, GL_LINK_STATUS, &amp;linkStatus);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if(linkStatus != GL_TRUE){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed&quot;&lt;&lt;std::endl;&#xD;&#xA;            GLint infoLogLength;&#xD;&#xA;            glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &amp;infoLogLength);&#xD;&#xA;            GLchar* buffer = new GLchar [infoLogLength];&#xD;&#xA;    &#xD;&#xA;            GLsizei bufferSize;&#xD;&#xA;            glGetProgramInfoLog(programID, infoLogLength, &amp;bufferSize, buffer);&#xD;&#xA;            std::cout&lt;&lt;buffer&lt;&lt;std::endl;&#xD;&#xA;            return false;&#xD;&#xA;    &#xD;&#xA;            delete []buffer;&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void installShaders(){&#xD;&#xA;    &#xD;&#xA;        GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;        GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    &#xD;&#xA;        const char *adapter[1];&#xD;&#xA;        adapter[0] = vertexShaderCode;&#xD;&#xA;    &#xD;&#xA;        glShaderSource(vertexShaderID, 1, adapter, 0);&#xD;&#xA;        adapter[0] = fragmentShaderCode;&#xD;&#xA;        glShaderSource(fragmentShaderID, 1, adapter, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        glCompileShader(vertexShaderID);&#xD;&#xA;        glCompileShader(fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(vertexShaderID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;Sth wrong with vertex shader&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if(!checkShaderStatus(fragmentShaderID)){&#xD;&#xA;           std::cerr&lt;&lt;&quot;Sth wrong with fragment shader&quot;&lt;&lt;std::endl;&#xD;&#xA;           return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        GLuint programID = glCreateProgram();&#xD;&#xA;        glAttachShader(programID, vertexShaderID);&#xD;&#xA;        glAttachShader(programID, fragmentShaderID);&#xD;&#xA;    &#xD;&#xA;        glLinkProgram(programID);&#xD;&#xA;    &#xD;&#xA;        if(!checkProgramStatus(programID)){&#xD;&#xA;            std::cerr&lt;&lt;&quot;failed to link&quot;&lt;&lt;std::endl;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glUseProgram(programID);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void GlWindow::paintGL(){&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        glViewport(0,0,width(), height());&#xD;&#xA;    &#xD;&#xA;        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void GlWindow::initializeGL(){&#xD;&#xA;        glewInit();&#xD;&#xA;    &#xD;&#xA;        const GLubyte *shaderVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);&#xD;&#xA;        std::cout&lt;&lt;shaderVersion&lt;&lt;std::endl;&#xD;&#xA;    &#xD;&#xA;        sendDataToOpenGL();&#xD;&#xA;        installShaders();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and finally my shader code: &#xD;&#xA;&#xD;&#xA;    const char* vertexShaderCode  =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;in layout(location=0) vec2 position;\n&quot;&#xD;&#xA;            &quot;in layout(location=1) vec3 vertexColor;\n&quot;&#xD;&#xA;            &quot;&quot;&#xD;&#xA;            &quot;out vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;gl_Position = vec4(position, 0.0, 1.0);\n&quot;&#xD;&#xA;            &quot;theColor = vertexColor; \n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    const char* fragmentShaderCode =&#xD;&#xA;            &quot;#version 430\r\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;out vec4 daColor;\n&quot;&#xD;&#xA;            &quot;in vec3 theColor;\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot;void main()\n&quot;&#xD;&#xA;            &quot;{\n&quot;&#xD;&#xA;            &quot;\n&quot;&#xD;&#xA;            &quot; daColor = vec4(theColor,1.0);\n&quot;&#xD;&#xA;            &quot;}\n&quot;&#xD;&#xA;            ;&#xD;&#xA;&#xD;&#xA;I know that my shader code looks stupid but I'm just trying to learn. &#xD;&#xA;&#xD;&#xA;**EDIT:** I don't know if thats relevant, but I'm using Ubuntu 15.0 and `glGetString(GL_SHADING_LANGUAGE_VERSION)` returns: `4.4 nvidia via cg compiler`.  &#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2943" PostHistoryTypeId="4" PostId="1622" RevisionGUID="1f4ecd25-4648-43f3-8e3b-2bc01f2a088b" CreationDate="2015-10-15T15:12:19.413" UserId="127" Comment="Improved grammar" Text="Can't get output from a GLSL code" ContentLicense="CC BY-SA 3.0" />
  <row Id="2944" PostHistoryTypeId="24" PostId="1622" RevisionGUID="1f4ecd25-4648-43f3-8e3b-2bc01f2a088b" CreationDate="2015-10-15T15:12:19.413" Comment="Proposed by 127 approved by 1861 edit id of 63" ContentLicense="CC BY-SA 3.0" />
  <row Id="2945" PostHistoryTypeId="2" PostId="1626" RevisionGUID="1c7835ae-ff06-426a-a9e6-fdd9184a996d" CreationDate="2015-10-15T20:44:30.027" UserDisplayName="user464" Text="[Scratchpad was a constraint-based graphics system.][1]&#xD;&#xA;&#xD;&#xA;What does it mean  by a Constraint-based Graphics System?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Sketchpad" ContentLicense="CC BY-SA 3.0" />
  <row Id="2946" PostHistoryTypeId="1" PostId="1626" RevisionGUID="1c7835ae-ff06-426a-a9e6-fdd9184a996d" CreationDate="2015-10-15T20:44:30.027" UserDisplayName="user464" Text="What does it mean by a Constraint-based Graphics System?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2947" PostHistoryTypeId="3" PostId="1626" RevisionGUID="1c7835ae-ff06-426a-a9e6-fdd9184a996d" CreationDate="2015-10-15T20:44:30.027" UserDisplayName="user464" Text="|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2948" PostHistoryTypeId="2" PostId="1627" RevisionGUID="fb7cf9f8-5d8f-478b-b751-837079e5e2e0" CreationDate="2015-10-15T22:31:29.023" UserDisplayName="user464" Text="What is the basic difference between Radar Screen, PC CRT Monitor, and, Oscilloscope displays?&#xD;&#xA;&#xD;&#xA;All of them use CRT. So, what is the difference?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2949" PostHistoryTypeId="1" PostId="1627" RevisionGUID="fb7cf9f8-5d8f-478b-b751-837079e5e2e0" CreationDate="2015-10-15T22:31:29.023" UserDisplayName="user464" Text="What is the basic difference between Radar Screen, CRT and Oscilloscope displays?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2950" PostHistoryTypeId="3" PostId="1627" RevisionGUID="fb7cf9f8-5d8f-478b-b751-837079e5e2e0" CreationDate="2015-10-15T22:31:29.023" UserDisplayName="user464" Text="|display-lists|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2951" PostHistoryTypeId="2" PostId="1628" RevisionGUID="af5945f7-ce20-4781-85bd-68947bc047a8" CreationDate="2015-10-16T02:54:45.827" UserId="48" Text="Sketchpad was a system that allowed you to draw simple shapes using lines and curves in 2D.  It maintained constraints between the shapes. For example, an endpoint of one line could be constrained to lie on another line. Also, as mentioned in the Wikipedia article, the user could set a fixed length for a line, or an angle between two connected lines. These constraints would be automatically applied by the system while editing the diagrams&amp;mdash;e.g., when moving one line, other lines would be adjusted to maintain the constraints." ContentLicense="CC BY-SA 3.0" />
  <row Id="2954" PostHistoryTypeId="2" PostId="1629" RevisionGUID="ab9d437f-7dbc-4a09-8006-d71c50fdf4aa" CreationDate="2015-10-16T06:07:31.000" UserId="1614" Text="wil, you largely have enough scholar background, you must have done Fourier and Laplace transforms in second year, and maybe in your engineering school again as part of signal processing classes.&#xD;&#xA;&#xD;&#xA;If you read &quot;stupid tricks&quot; there is not much more you can do to find a condensed course at this point.&#xD;&#xA;&#xD;&#xA;The second most famous paper that goes with SH for graphics is by Robin Green called &quot;the gritty details&quot;:  &#xD;&#xA;**http://www.research.scea.com/gdc2003/spherical-harmonic-lighting.pdf**&#xD;&#xA;&#xD;&#xA;And the third most important is the one by Ramamoorthi (the original paper preceding &quot;[An Efficient Representation for Irradiance Environment Maps][1]&quot;), which was called [**On the relationship between radiance and&#xD;&#xA;irradiance: determining&#xD;&#xA;the illumination from&#xD;&#xA;images of a convex Lambertian object**][2]&#xD;&#xA;&#xD;&#xA;And I think they mention somewhere that SH were previously most used by another science field, forgot which one, physics maybe, and that most of their base material came from these papers. So if you want to dig in the roots, you've got to pull out these mid last century references.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphics.stanford.edu/papers/envmap/&#xD;&#xA;  [2]: http://graphics.stanford.edu/papers/invlamb/josa.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="2955" PostHistoryTypeId="5" PostId="1594" RevisionGUID="4c64d278-2228-4077-801d-26bce5114d13" CreationDate="2015-10-16T08:20:53.373" UserId="231" Comment="Add additional newlines for paragraphs that were not rendered separately, plus typos and grammar." Text="When it comes to perception, there is also the issue of what we are almost blind to (in terms of properties or artifacts), and what we have enforced perception of.&#xD;&#xA;&#xD;&#xA;For instance as for sound, you have contrast or frequencies that make you less or not aware of other contents (an old SIGGRAPH paper illustrated how texture can mask mesh resolution), plus all the time aspects (google for &quot;change blindness&quot;). Similarly, details of surface, normals, BRDF might or might not be seen depending of values and relative values.&#xD;&#xA;&#xD;&#xA;Also since our perceptive system tends to adapt locally and globally, for low frequency values it is important to have maxima and minima at the right places, but their exact value won't really be noticed.&#xD;&#xA;&#xD;&#xA;Sometimes cognition might be there to, like you allow a lot of errors in clouds and trees but surely less in human faces. (Sometimes you might downgrade this to statistics of parameter for a given category.)&#xD;&#xA;&#xD;&#xA;That's why I prefer using the word &quot;plausible&quot; rather than &quot;photorealistic&quot;.&#xD;&#xA;&#xD;&#xA;Contrarily, we are ultra-sensitive to artifacts such as false pixels or flickering pixels, ultra-sensitive to correlations like fronts of error of 1 grey level only, unwanted patterns such as Moiré, aliasing or bad random, etc. &#xD;&#xA;&#xD;&#xA;By the way it's one of the reasons that optimization-based solutions summing everything in a simple energy can be a very bad idea perceptively speaking as in all paradoxical situations this can be prone to concentration of errors in lines or points. For the same reason early global illumination people were really disappointed that energy exact solutions were less accepted than anti-aliased approximate shadows (and then came from quad-tree based to mesh-based adaptive methods).&#xD;&#xA;&#xD;&#xA;A (quite general) overview about perception for graphics can be found in this SigAsia'11 course on [&quot;Perception in Graphics, Visualization, Virtual Environments and Animation&quot;][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://dl.acm.org/citation.cfm?id=2077448" ContentLicense="CC BY-SA 3.0" />
  <row Id="2957" PostHistoryTypeId="2" PostId="1630" RevisionGUID="29df5c20-5c92-42c7-a9f6-685655f1ebe2" CreationDate="2015-10-16T15:13:25.457" UserId="38" Text="If you have a geometric drawing with measurements you can solve what the shape has to be. This is valuable for example in engineering as it allows you specify the requirements and the computer can then solve the constrained drawing via a solver. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Constraint solver in action, red constraints are fixed while blue ones are free to change.&#xD;&#xA;&#xD;&#xA;There are several ways how the solver might work, it could be a numeric nonlinear based on gradient descent. Or it can be fully algebraic. Usually its a gradient descent solver as this is easier to implement, and possibly faster.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/80tMB.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="2958" PostHistoryTypeId="2" PostId="1631" RevisionGUID="b38568f8-d82a-45ea-b8c0-95cb0f9922bb" CreationDate="2015-10-16T18:55:16.347" UserId="1810" Text="At many places in CG hardwares and algorithms you have the choice between vector description and raster description. Oscilloscops, radar, lasers shows, plotting tables, laser cuts directly follow lines and curves; these are the vectorials devices. LCD, inkjet and laser printers, stereolithographic 3D printing, follow pixels and voxels; these are the raster devices. The CRT, but also some laser shows, use the oscilloscope technology to implement raster: the &quot;curve&quot; is a repeated Z narrowly sweeping the screen line after line, with intensity modulation making the &quot;pixels&quot;.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="2959" PostHistoryTypeId="5" PostId="1631" RevisionGUID="d037f650-c09d-4af0-8f98-12eef844bb67" CreationDate="2015-10-16T19:00:45.773" UserId="1810" Comment="added 226 characters in body" Text="At many places in CG hardwares and algorithms you have the choice between vector description and raster description. Oscilloscops, radar, lasers shows, plotting tables, laser cuts directly follow lines and curves; these are the vectorials devices. LCD, inkjet and laser printers, stereolithographic 3D printing, follow pixels and voxels; these are the raster devices. The CRT, but also some laser shows, use the oscilloscope technology to implement raster: the &quot;curve&quot; is a repeated Z narrowly sweeping the screen line after line, with intensity modulation making the &quot;pixels&quot;.&#xD;&#xA;&#xD;&#xA;( About representations, the vector/raster dichotomy corresponds to inkscape/illustrator vs gimp/photoshop, 3D meshes vs 3D voxels, list of lobes vs angular or SH decomposition, Lagrangian animation vs Eulerian animation, etc. )" ContentLicense="CC BY-SA 3.0" />
  <row Id="2960" PostHistoryTypeId="2" PostId="1632" RevisionGUID="ec0d841d-a6dc-4b6e-8d6f-cc4d5129f641" CreationDate="2015-10-16T19:54:28.523" UserId="523" Text="I am trying to sample from the Blinn-Phong BRDF.&#xD;&#xA;&#xD;&#xA;For testing, I use a spherical light source (Lambertian emission) sitting on a specular plane.  Here's a reference image using energy-conserving Phong with exponent `30000`:&#xD;&#xA;&#xD;&#xA;[![Phong][1]][1]&#xD;&#xA;&#xD;&#xA;Notice that no energy is lost.  **I would now like to achieve the same thing for Blinn-Phong**.&#xD;&#xA;&#xD;&#xA;Here's my attempt (same exponent, but on Blinn-Phong BRDF):&#xD;&#xA;&#xD;&#xA;[![Blinn-Phong][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, a substantial portion of energy is lost.  The normalization term I am using comes from [here](http://www.thetenthplanet.de/archives/255) and is `(n+1)/(2*pi)`.  The problem is this is a _normalization_ term, not a _conservation_ term.&#xD;&#xA;&#xD;&#xA;I believe this is the expected result.  It is common in graphics to make BRDFs reflect less than the input amount of energy, as opposed to exactly the right amount, as this is usually less difficult.&lt;sup&gt;1, 2&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;My question:&#xD;&#xA;&#xD;&#xA;1. Is there a version that conserves all energy exactly?&#xD;&#xA;2. Iff not, can someone at least confirm this is expected?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;N.B. I am fairly confident this is not a ray generation/PDF issue.  These images were importance sampled using a method given in the PBRT book pg. 695 - pg. 699.  Moreover, a non-importance sampled version looks very similar (though I had to use a lower exponent to get it to converge fast enough, and it still took 10,000 s/p).&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;1&lt;/sup&gt;This can be argued from a shadowing/masking argument on microfacets.  Unfortunately, it ignores multiple scattering.  The correct answer is somewhere in-between.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;2&lt;/sup&gt;Indeed, I had to derive the Phong conservation term myself.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R3uLF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xKlyz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="2961" PostHistoryTypeId="1" PostId="1632" RevisionGUID="ec0d841d-a6dc-4b6e-8d6f-cc4d5129f641" CreationDate="2015-10-16T19:54:28.523" UserId="523" Text="Energy Conservation for Blinn-Phong BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="2962" PostHistoryTypeId="3" PostId="1632" RevisionGUID="ec0d841d-a6dc-4b6e-8d6f-cc4d5129f641" CreationDate="2015-10-16T19:54:28.523" UserId="523" Text="|raytracing|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2963" PostHistoryTypeId="10" PostId="1624" RevisionGUID="60a4515e-6408-4cec-8770-ce100fd2a85d" CreationDate="2015-10-16T20:22:49.063" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:137,&quot;DisplayName&quot;:&quot;ratchet freak&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;}]}" />
  <row Id="2964" PostHistoryTypeId="10" PostId="1627" RevisionGUID="416ee934-b996-4a37-8b47-a2967851a864" CreationDate="2015-10-16T20:22:59.230" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;}]}" />
  <row Id="2965" PostHistoryTypeId="5" PostId="1631" RevisionGUID="ee026830-93eb-4682-8315-2258c1624085" CreationDate="2015-10-16T21:05:01.800" UserId="1810" Comment="added 160 characters in body" Text="At many places in CG hardwares and algorithms you have the choice between vector description and raster description. Oscilloscops, radar, lasers shows, plotting tables, laser cuts directly follow lines and curves; these are the vectorials devices. LCD, inkjet and laser printers, stereolithographic 3D printing, follow pixels and voxels; these are the raster devices. The CRT, but also some laser shows, use the oscilloscope technology to implement raster: the &quot;curve&quot; is a repeated Z narrowly sweeping the screen line after line, with intensity modulation making the &quot;pixels&quot;. Radars are indeed between this and pure vectors since rotation angle is swept. Details about various forms of radar display and oscilloscope is available on the [wikipedia page][1].&#xD;&#xA;&#xD;&#xA;( About representations, the vector/raster dichotomy corresponds to inkscape/illustrator vs gimp/photoshop, 3D meshes vs 3D voxels, list of lobes vs angular or SH decomposition, Lagrangian animation vs Eulerian animation, etc. )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Radar_display" ContentLicense="CC BY-SA 3.0" />
  <row Id="2966" PostHistoryTypeId="2" PostId="1633" RevisionGUID="dd6cfa43-5418-4da8-ad7a-be4080af0283" CreationDate="2015-10-17T02:04:20.943" UserId="56" Text="In PC game development, after loading models, textures, shaders, etc in a loading screen, some games will render the models once to an off screen target to make sure the driver and gpu have done all the work required to keep there from being a hitch the first time the models render.&#xA;&#xA;Does anyone know how much that actually helps? Does it only affect certain cards and drivers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2967" PostHistoryTypeId="1" PostId="1633" RevisionGUID="dd6cfa43-5418-4da8-ad7a-be4080af0283" CreationDate="2015-10-17T02:04:20.943" UserId="56" Text="Does prerendering actually help performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2968" PostHistoryTypeId="3" PostId="1633" RevisionGUID="dd6cfa43-5418-4da8-ad7a-be4080af0283" CreationDate="2015-10-17T02:04:20.943" UserId="56" Text="|gpu|real-time|direct3d|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="2972" PostHistoryTypeId="2" PostId="1634" RevisionGUID="33327115-d651-44bd-9797-0e155b9280f7" CreationDate="2015-10-17T07:29:49.867" UserId="48" Text="As far as I know, this sort of thing is mainly about shader compilation. One of the main reasons why a game may experience hitches the first time something renders is that the shaders necessary to render it haven't finished compiling yet, and the driver has to finish that work before the frame can proceed.&#xD;&#xA;&#xD;&#xA;A little bit of background. When you write shaders in HLSL, you compile them with Microsoft's HLSL compiler (fxc.exe), which outputs a hardware-independent bytecode. When you call CreateVertexShader etc. in D3D, that bytecode gets passed to the underlying driver, which ultimately compiles it into the machine code for the specific GPU you're running on.&#xD;&#xA;&#xD;&#xA;This internal compilation step isn't trivial&amp;mdash;it's a full-blown optimizing compiler. So it can take a little while on a complicated shader. Because of this, when you call D3D's CreateVertexShader, the driver doesn't necessarily *finish* compiling the shader right then and there; it may add it to a queue, then return control to the application. Meanwhile, a background thread (perhaps more than one) consumes the queue and compiles the shaders. (The driver may also have a disk cache of previously-compiled shaders, so that it doesn't have to redo all this work every time the game is launched.)&#xD;&#xA;&#xD;&#xA;This background-thread compilation means the main game thread can get on with other work, e.g. loading other data or building a scene graph or what-have-you, so it's generally a win for overall loading times. But the consequence of it is that the shaders may not all be finished compiling when the game starts rendering. Unfortunately, there is no way with DX11 and earlier APIs for the app to tell when the shaders are done. The best you can do is to render something with the shader&amp;mdash;this effectively makes the app wait for the compiler to finish. That's why games sometimes do this offscreen pre-rendering business.&#xD;&#xA;&#xD;&#xA;I don't have any hard numbers handy, but qualitatively, one can reduce the impact of shader compilation by front-loading it during loading. Create all your shaders first, then the compiler will run through those while you load everything else. However, with real-time streaming  (e.g. open-world games) it can still be quite difficult to ensure no hitches.&#xD;&#xA;&#xD;&#xA;It's also worth noting that there are some cases where state changes can cause a shader recompile. Things like vertex buffer formats, render target formats, and shader linking details (e.g. re-using the same pixel shader with different vertex shaders, or with tessellation shaders) can potentially cause the driver to have to generate different versions of the shader under the hood. The details vary by vendor and hardware. This isn't necessarily a full from-scratch recompile&amp;mdash;often it's just sticking on some prologue or epilogue code&amp;mdash;but it's something to be aware of.&#xD;&#xA;&#xD;&#xA;This is one place where the new APIs (DX12 and Vulkan) are in a good position to solve the problem. These APIs have &quot;pipeline state&quot; objects where all shader stages and all possibly relevant states are rolled up into a single object, and when you create one of these, the driver has all the information it needs to actually and completely finalize all the shaders. DX12 also makes shader caching explicit. Also, at least for NVIDIA DX12 drivers (I don't know about others), shader compilation is done fully inside the pipeline state creation method, and the app can use multiple threads itself in order to parallelize shader compilation and other work. So, the practice of offscreen pre-rendering to ensure shaders are finalized should no longer be necessary in DX12." ContentLicense="CC BY-SA 3.0" />
  <row Id="2973" PostHistoryTypeId="2" PostId="1635" RevisionGUID="36c89507-8a20-481c-a800-3eaface00e9d" CreationDate="2015-10-17T09:22:33.657" UserId="79" Text="First off, this is probably not the best way of testing energy conservation, because not all incident inclinations are visible in the image. Most of the environment is also black, so a less &quot;peaky&quot; BRDF such as Lambert would come out very dark with no way of telling whether it's energy conserving or not.&#xD;&#xA;&#xD;&#xA;What is more commonly used is a so-called &quot;furnace test&quot;, where you place a single sphere into a white environment map. When you render this sphere using the BRDF of interest, it should blend into the environment perfectly if the BRDF is energy conserving (make sure no color channels are clipping). Because it is a sphere, you will be able to see the BRDF at all incident inclinations. Additionally, the sphere is convex, so lacking any other objects in the scene, no reflected ray will be occluded, and every pixel of the sphere in the image will be an integral over the BRDF at a different inclination.&#xD;&#xA;&#xD;&#xA;If you did this test, you would also notice that your Phong BRDF is most likely not energy conserving. The commonly used normalization term of `(n+1)/(2 Pi)` (or `(n+2)/(2 Pi)`, depending on who you ask) only holds at normal incidence. At other inclinations, and particularly at grazing angle, up to half of the reflected rays will land below the surface and are usually terminated (because transmitting through a reflective surface does not make sense).  &#xD;&#xA;The correct normalization term that accounts for the part of the Phong lobe that is clipped below the hemisphere is very difficult to compute. Jim Arvo derived a closed-form solution for integer exponents using double-axis moments, summarised in the [Global Illumination Compendium](http://people.cs.kuleuven.be/~philip.dutre/GI/TotalCompendium.pdf), paragraph 31a) and 31b) (page 17/18). These formulas are not very practical for use in a renderer though and I don't suggest implementing them.&#xD;&#xA;&#xD;&#xA;It should be clear that if a simple model such as Phong is already this difficult to normalize, then Blinn-Phong is even more difficult. First of all, the `(n+1)/(2*pi)` normalization term you mention is only correct if you use Blinn-Phong as a microfacet distribution inside a full microfacet BRDF (e.g. Torrance-Sparrow or Walter). If you directly use the Blinn-Phong BRDF, then a more correct normalization term is `(n+2)(n+4)/(8 Pi 2^(-n/2) + n)`, derived in [this short article](http://www.farbrausch.de/~fg/stuff/phong.pdf) by Fabian Giesen (second page) and also listed on the page you mention. However, this normalization term is again only correct at normal incidence and will not be exact at other inclinations. From what I can tell, no exact normalization term exists." ContentLicense="CC BY-SA 3.0" />
  <row Id="2976" PostHistoryTypeId="5" PostId="1634" RevisionGUID="482bba85-7d88-421b-a39d-9512c02d08e4" CreationDate="2015-10-17T20:38:19.193" UserId="504" Comment="added other &quot;new&quot; API" Text="As far as I know, this sort of thing is mainly about shader compilation. One of the main reasons why a game may experience hitches the first time something renders is that the shaders necessary to render it haven't finished compiling yet, and the driver has to finish that work before the frame can proceed.&#xD;&#xA;&#xD;&#xA;A little bit of background. When you write shaders in HLSL, you compile them with Microsoft's HLSL compiler (fxc.exe), which outputs a hardware-independent bytecode. When you call CreateVertexShader etc. in D3D, that bytecode gets passed to the underlying driver, which ultimately compiles it into the machine code for the specific GPU you're running on.&#xD;&#xA;&#xD;&#xA;This internal compilation step isn't trivial&amp;mdash;it's a full-blown optimizing compiler. So it can take a little while on a complicated shader. Because of this, when you call D3D's CreateVertexShader, the driver doesn't necessarily *finish* compiling the shader right then and there; it may add it to a queue, then return control to the application. Meanwhile, a background thread (perhaps more than one) consumes the queue and compiles the shaders. (The driver may also have a disk cache of previously-compiled shaders, so that it doesn't have to redo all this work every time the game is launched.)&#xD;&#xA;&#xD;&#xA;This background-thread compilation means the main game thread can get on with other work, e.g. loading other data or building a scene graph or what-have-you, so it's generally a win for overall loading times. But the consequence of it is that the shaders may not all be finished compiling when the game starts rendering. Unfortunately, there is no way with DX11 and earlier APIs for the app to tell when the shaders are done. The best you can do is to render something with the shader&amp;mdash;this effectively makes the app wait for the compiler to finish. That's why games sometimes do this offscreen pre-rendering business.&#xD;&#xA;&#xD;&#xA;I don't have any hard numbers handy, but qualitatively, one can reduce the impact of shader compilation by front-loading it during loading. Create all your shaders first, then the compiler will run through those while you load everything else. However, with real-time streaming  (e.g. open-world games) it can still be quite difficult to ensure no hitches.&#xD;&#xA;&#xD;&#xA;It's also worth noting that there are some cases where state changes can cause a shader recompile. Things like vertex buffer formats, render target formats, and shader linking details (e.g. re-using the same pixel shader with different vertex shaders, or with tessellation shaders) can potentially cause the driver to have to generate different versions of the shader under the hood. The details vary by vendor and hardware. This isn't necessarily a full from-scratch recompile&amp;mdash;often it's just sticking on some prologue or epilogue code&amp;mdash;but it's something to be aware of.&#xD;&#xA;&#xD;&#xA;This is one place where the new APIs (DX12, Metal, and Vulkan) are in a good position to solve the problem. These APIs have &quot;pipeline state&quot; objects where all shader stages and all possibly relevant states are rolled up into a single object, and when you create one of these, the driver has all the information it needs to actually and completely finalize all the shaders. DX12 also makes shader caching explicit. Also, at least for NVIDIA DX12 drivers (I don't know about others), shader compilation is done fully inside the pipeline state creation method, and the app can use multiple threads itself in order to parallelize shader compilation and other work. So, the practice of offscreen pre-rendering to ensure shaders are finalized should no longer be necessary in DX12." ContentLicense="CC BY-SA 3.0" />
  <row Id="2977" PostHistoryTypeId="24" PostId="1634" RevisionGUID="482bba85-7d88-421b-a39d-9512c02d08e4" CreationDate="2015-10-17T20:38:19.193" Comment="Proposed by 504 approved by 231, 48 edit id of 66" ContentLicense="CC BY-SA 3.0" />
  <row Id="2978" PostHistoryTypeId="2" PostId="1636" RevisionGUID="c74c8928-9cbc-4659-932c-93d0bbbf610d" CreationDate="2015-10-18T06:09:20.450" UserId="523" Text="From math:&#xD;&#xA;&#xD;&#xA;&gt; There is a 2:1 homomorphism from the unit [quaternions](https://en.wikipedia.org/wiki/Quaternion) to [SO(3)](https://en.wikipedia.org/wiki/Rotation_group_SO%283%29) (the rotation group).&#xD;&#xA;&#xD;&#xA;What this (essentially) means is that:&#xD;&#xA;&#xD;&#xA;1. Every orientation can be represented as a quaternion&#xD;&#xA;2. Quaternions represent a single rotation&#xD;&#xA;3. Multiplication of quaternions produces another quaternion (closure), and is equivalent to composing the rotations.&#xD;&#xA;4. **Therefore *any* number of rotations can be represented as a single rotation!**&#xD;&#xA;&#xD;&#xA;Think about that.  Starting from object space, you can rotate your object into *any* orientation using only a *single* rotation.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I would like to point out that bringing quaternions in wasn't just random math-ese.  In contrast to the other answers, the *favored* approach in graphics is actually to represent rotations as quaternions, since they take up less space and are faster to combine.&#xD;&#xA;&#xD;&#xA;There are easily-Googleable ways to convert between rotation matrices and quaternions, depending on which you prefer.  The point is that rotations *are* the quaternions in a mathematical sense, so combinations thereof are also single rotations." ContentLicense="CC BY-SA 3.0" />
  <row Id="2980" PostHistoryTypeId="5" PostId="375" RevisionGUID="3d621d49-80e8-4ec4-8c28-87784db0afd6" CreationDate="2015-10-18T12:21:55.560" UserId="480" Comment="added 14 characters in body" Text="Wikipedia [says][1]: &quot;... represents a fixed-intensity and fixed-color light source that affects all objects in the scene equally.&quot;&#xD;&#xA;&#xD;&#xA;By saying &quot;affects all objects equally&quot; they mean all objects get the same amount of light? So if you have three houses in your scene, you would need to calculate a specific position for the ambient lighting source, in order that every object gets the same amount of light? If not, you would not have an ambient light source? &#xD;&#xA;&#xD;&#xA;What is the difference between &quot;normal&quot; lighting from the sun and ambient lighting?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shading#Ambient_lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="2981" PostHistoryTypeId="5" PostId="375" RevisionGUID="0bf67d33-3ac0-4411-b398-5f59af311ec3" CreationDate="2015-10-18T14:48:44.737" UserId="127" Comment="Put the quote into a quote block." Text="Wikipedia [says][1]: &#xD;&#xA;&#xD;&#xA;&gt; An ambient light source represents a fixed-intensity and fixed-color light source that affects all objects in the scene equally.&#xD;&#xA;&#xD;&#xA;By saying &quot;affects all objects equally&quot; they mean all objects get the same amount of light? So if you have three houses in your scene, you would need to calculate a specific position for the ambient lighting source, in order that every object gets the same amount of light? If not, you would not have an ambient light source? &#xD;&#xA;&#xD;&#xA;What is the difference between &quot;normal&quot; lighting from the sun and ambient lighting?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shading#Ambient_lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="2982" PostHistoryTypeId="24" PostId="375" RevisionGUID="0bf67d33-3ac0-4411-b398-5f59af311ec3" CreationDate="2015-10-18T14:48:44.737" Comment="Proposed by 127 approved by 79, 38 edit id of 67" ContentLicense="CC BY-SA 3.0" />
  <row Id="2985" PostHistoryTypeId="2" PostId="1637" RevisionGUID="d52b2462-7938-4ae8-a1f2-6d3a91effc99" CreationDate="2015-10-19T04:39:43.037" UserId="1879" Text="Given a 3D space and a light source, I use ray casting to determine the shadows generated in the scene. If I'm to store the shadow data (boundary of the shadow, object which cast the shadow, etc.) what is an efficient way to go about it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="2986" PostHistoryTypeId="1" PostId="1637" RevisionGUID="d52b2462-7938-4ae8-a1f2-6d3a91effc99" CreationDate="2015-10-19T04:39:43.037" UserId="1879" Text="Storing shadow data" ContentLicense="CC BY-SA 3.0" />
  <row Id="2987" PostHistoryTypeId="3" PostId="1637" RevisionGUID="d52b2462-7938-4ae8-a1f2-6d3a91effc99" CreationDate="2015-10-19T04:39:43.037" UserId="1879" Text="|shadow-mapping|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3000" PostHistoryTypeId="2" PostId="1639" RevisionGUID="67e5db7c-7abd-4bac-bc56-010b17e5d36e" CreationDate="2015-10-20T08:45:52.520" UserDisplayName="user1703" Text="If the goal is mouse interactivity, you can do with a simple &quot;shadow buffer&quot;, i.e. an image that holds the identity of the occluding object (if any) on every rendered pixel. You will compute this map during the casting process as you shoot the rays to the source.&#xD;&#xA;&#xD;&#xA;In case there are several occluding objects, it is up to you to choose which one to consider (or keep a linked list of all occluding objects). If there are several sources, you can keep one map per source." ContentLicense="CC BY-SA 3.0" />
  <row Id="3001" PostHistoryTypeId="2" PostId="1640" RevisionGUID="e74b88e4-d3fe-478e-8581-d057df565c4c" CreationDate="2015-10-20T13:38:20.027" UserId="281" Text="I've written an implementation of the sphere tracing algorithm in OpenGL 4+.&#xD;&#xA;As an experiment/toy project, i'm reimplementing it using the OpenGL 4.3 compute shader, but i'm having trouble with the whole local/global invocation ID thing.&#xD;&#xA;The basic idea is to use the compute shader to calculate the image and output it in a texture, than use a trivial program to copy it onto the framebuffer.&#xD;&#xA;&#xD;&#xA;This is the compute shader i'm using:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (binding = 0, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA; &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec2 coord = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;        imageStore(output_image, coord, vec4(0.0, 0.0, 1.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is how I initialize the texture:&#xD;&#xA;&#xD;&#xA;    GLuint offscreen_texture;&#xD;&#xA;  	glGenTextures(1, &amp;offscreen_texture);&#xD;&#xA;&#xD;&#xA; 	glActiveTexture(GL_TEXTURE0);&#xD;&#xA; 	glBindTexture(GL_TEXTURE_2D, offscreen_texture);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, nullptr);&#xD;&#xA;	glBindImageTexture(0, offscreen_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;And these are the trivial vertex shader i'm using:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        const vec4 verts[4] = vec4[4](vec4(-1.0, -1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4( 1.0, -1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4(-1.0,  1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4( 1.0,  1.0, 0.5, 1.0));&#xD;&#xA;&#xD;&#xA;        gl_Position = verts[gl_VertexID];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And fragment:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 color_out;&#xD;&#xA;    layout(binding = 0) uniform sampler2D source_image;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    color_out = texture(source_image, gl_FragCoord.xy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is the render code:&#xD;&#xA;&#xD;&#xA;    compute_program.use();&#xD;&#xA;    glDispatchCompute(WINDOW_WIDTH / 16, WINDOW_HEIGHT / 16, 1);&#xD;&#xA;	glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;	copy_program.use();&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;&#xD;&#xA;Up to this point everything works correctly and i see my screen completely blue instead of the usual clear color.&#xD;&#xA;&#xD;&#xA;Things start to break down when i try to use the Invocation ID the generate actual data (like the rays from the camera).&#xD;&#xA;I tried to switch to a compute shader like:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (binding = 0, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec2 coord = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;        imageStore(output_image, coord, vec4(0.0, 0.0, coord.x / 1280.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;which uses the global ID to generate the blue tint of the pixel.&#xD;&#xA;As I understand from the OpenGL Suberbible book and the OpenGL wiki, I should be able to use the global ID as screen space coordinates (it's pretty easy to do the math using local IDs and work groups IDs and confirm that), much like gl_FragCoord, and this is confirmed by the previous trivial compute shader which paint every pixel.&#xD;&#xA;&#xD;&#xA;I would expect a sort of horizontal gradient going from black to blue as an output of this compute shader, but instead everything turns black.&#xD;&#xA;I've tried several combination of &quot;painting&quot; based on the local/global IDs of the threads, but i haven't got any luck no matter what.&#xD;&#xA;&#xD;&#xA;Did I misunderstood the way the whole threads ID work?&#xD;&#xA;What is the correct way to use them/map them to screen space coordinates like gl_FragCoord?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3002" PostHistoryTypeId="1" PostId="1640" RevisionGUID="e74b88e4-d3fe-478e-8581-d057df565c4c" CreationDate="2015-10-20T13:38:20.027" UserId="281" Text="How to convert a thread ID into Screen Space Coord in an OpenGL Compute Shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3003" PostHistoryTypeId="3" PostId="1640" RevisionGUID="e74b88e4-d3fe-478e-8581-d057df565c4c" CreationDate="2015-10-20T13:38:20.027" UserId="281" Text="|opengl|glsl|compute-shader|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3004" PostHistoryTypeId="2" PostId="1641" RevisionGUID="3e2786aa-4296-441f-9ba8-5021a3b32c2b" CreationDate="2015-10-20T15:04:28.460" UserId="1895" Text="I would like to implement a Maya plugin (this question is independent from Maya) to create 3D Voronoi patterns, Something like &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I just know that I have to start from point sampling (I implemented the adaptive poisson sampling algorithm described in [this paper][2]). &#xD;&#xA;&#xD;&#xA;I thought that, from those points, I should create the 3D wire of the mesh applying Voronoi (I tried to use (Python) scipy.spatial.Voronoi but the result was something different from what I expected). &#xD;&#xA;&#xD;&#xA;I am missing something? Can anyone suggest the proper pipeline and algorithms I have to implement to create such patterns?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8RYgU.jpg&#xD;&#xA;  [2]: http://link.springer.com/article/10.1007%2Fs11432-011-4322-8#/page-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="3005" PostHistoryTypeId="1" PostId="1641" RevisionGUID="3e2786aa-4296-441f-9ba8-5021a3b32c2b" CreationDate="2015-10-20T15:04:28.460" UserId="1895" Text="Pipeline to create Voronoi Meshes" ContentLicense="CC BY-SA 3.0" />
  <row Id="3006" PostHistoryTypeId="3" PostId="1641" RevisionGUID="3e2786aa-4296-441f-9ba8-5021a3b32c2b" CreationDate="2015-10-20T15:04:28.460" UserId="1895" Text="|3d|geometry|mesh|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3007" PostHistoryTypeId="5" PostId="1640" RevisionGUID="de349080-6a93-4c6d-a65e-b84cd74ec9fa" CreationDate="2015-10-20T18:16:43.390" UserId="281" Comment="added 175 characters in body" Text="I've written an implementation of the sphere tracing algorithm in OpenGL 4+.&#xD;&#xA;As an experiment/toy project, i'm reimplementing it using the OpenGL 4.3 compute shader, but i'm having trouble with the whole local/global invocation ID thing.&#xD;&#xA;The basic idea is to use the compute shader to calculate the image and output it in a texture, then use a trivial program to copy it onto the framebuffer.&#xD;&#xA;&#xD;&#xA;This is the compute shader i'm using:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (binding = 0, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA; &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec2 coord = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;        imageStore(output_image, coord, vec4(0.0, 0.0, 1.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is how I initialize the texture:&#xD;&#xA;&#xD;&#xA;    GLuint offscreen_texture;&#xD;&#xA;  	glGenTextures(1, &amp;offscreen_texture);&#xD;&#xA;&#xD;&#xA; 	glActiveTexture(GL_TEXTURE0);&#xD;&#xA; 	glBindTexture(GL_TEXTURE_2D, offscreen_texture);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, nullptr);&#xD;&#xA;	glBindImageTexture(0, offscreen_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;And these are the trivial vertex shader i'm using:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        const vec4 verts[4] = vec4[4](vec4(-1.0, -1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4( 1.0, -1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4(-1.0,  1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4( 1.0,  1.0, 0.5, 1.0));&#xD;&#xA;&#xD;&#xA;        gl_Position = verts[gl_VertexID];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And fragment:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 color_out;&#xD;&#xA;    layout(binding = 0) uniform sampler2D source_image;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    color_out = texture(source_image, gl_FragCoord.xy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is the render code:&#xD;&#xA;&#xD;&#xA;    compute_program.use();&#xD;&#xA;    glDispatchCompute(WINDOW_WIDTH / 16, WINDOW_HEIGHT / 16, 1);&#xD;&#xA;	glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;	copy_program.use();&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;&#xD;&#xA;Up to this point everything works correctly and i see my screen completely blue instead of the usual clear color.&#xD;&#xA;&#xD;&#xA;Things start to break down when i try to use the Invocation ID to generate actual data (like the rays from the camera).&#xD;&#xA;I tried to switch to a compute shader like:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (binding = 0, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec2 coord = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;        imageStore(output_image, coord, vec4(0.0, 0.0, coord.x / 1280.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;which uses the global ID to generate the blue tint of the pixel.&#xD;&#xA;As I understand from the OpenGL Suberbible book and the OpenGL wiki, I should be able to use the global ID as screen space coordinates (it's pretty easy to do the math using local IDs and work groups IDs and confirm that), much like gl_FragCoord, and this is confirmed by the previous trivial compute shader which paint every pixel.&#xD;&#xA;&#xD;&#xA;I would expect a sort of horizontal gradient going from black to blue as an output of this compute shader, but instead everything turns black.&#xD;&#xA;I've tried several combination of &quot;painting&quot; based on the local/global IDs of the threads, but i haven't got any luck no matter what.&#xD;&#xA;&#xD;&#xA;Did I misunderstood the way the whole threads ID work?&#xD;&#xA;What is the correct way to use them/map them to screen space coordinates like gl_FragCoord?&#xD;&#xA;&#xD;&#xA;EDIT: Just to add, i've tested this with both my integrated Intel HD 5100 and my discrete Nvidia 765M GPUs and the result is the same, so there is clearly something wrong on my side." ContentLicense="CC BY-SA 3.0" />
  <row Id="3008" PostHistoryTypeId="2" PostId="1642" RevisionGUID="0f1624de-3aaa-4ffb-aa09-ae66e8a4c414" CreationDate="2015-10-20T20:06:11.753" UserId="40" Text="The problem is actually in your fragment shader:&#xD;&#xA;&#xD;&#xA;    color_out = texture(source_image, gl_FragCoord.xy);&#xD;&#xA;&#xD;&#xA;The texture() function accepts normalized coordinates which range from 0.0 to 1.0. The gl_FragCoord built in contains window coordinates which range from (0.0, 0.0) to (window width, window height).&#xD;&#xA;&#xD;&#xA;To fix this, change the fragment shader to this:&#xD;&#xA;&#xD;&#xA;    color_out = texture(source_image, gl_FragCoord.xy / vec2(1280.0, 720.0));&#xD;&#xA;&#xD;&#xA;That is assuming your window is 1280x720, change as necessary." ContentLicense="CC BY-SA 3.0" />
  <row Id="3009" PostHistoryTypeId="2" PostId="1643" RevisionGUID="688a7aba-98ea-4284-8a7a-cdbacea005e3" CreationDate="2015-10-20T21:21:24.110" UserId="40" Text="There are two problems:&#xD;&#xA;&#xD;&#xA;1. Your indices are unsigned integers (4 bytes per index) but the call to glDrawElements specifies GL_UNSIGNED_SHORT. You need to change this to GL_UNSIGNED_INT.&#xD;&#xA;&#xD;&#xA;2. You are drawing two red triangles onto a buffer that has been cleared to red." ContentLicense="CC BY-SA 3.0" />
  <row Id="3011" PostHistoryTypeId="5" PostId="419" RevisionGUID="0648c0e7-a4f2-440b-a07c-a3d7e33dc253" CreationDate="2015-10-21T07:37:20.547" UserId="209" Comment="Added link to other answer since it was referenced" Text="Just adding to [imallett's answer](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/404#404), it is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can significantly influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can be costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting from 8bpp down to, say, 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in hardware, that the data *could* stay compressed throughout the entire cache hierarchy and only be decompressed in the texture unit, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how to spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading, try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to the use of Twiddled-order (i.e. Morton order) textures in [at least some early PC hardware](http://worldwide.espacenet.com/publicationDetails/originalDocument?FT=D&amp;date=19960814&amp;DB=EPODOC&amp;locale=en_ep&amp;CC=GB&amp;NR=2297886A&amp;KC=A&amp;ND=4)). &#xD;&#xA;&#xD;&#xA;  [1]: http://penguin.ewu.edu/class/cscd470/Winter_13/JimBlinnsCorner/TruthAboutTextureMapping.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3012" PostHistoryTypeId="5" PostId="1641" RevisionGUID="6b2d830b-2a57-44cd-837b-0b1f1893af34" CreationDate="2015-10-21T11:38:38.460" UserId="1895" Comment="add example results" Text="I would like to implement a Maya plugin (this question is independent from Maya) to create 3D Voronoi patterns, Something like &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I just know that I have to start from point sampling (I implemented the adaptive poisson sampling algorithm described in [this paper][2]). &#xD;&#xA;&#xD;&#xA;I thought that, from those points, I should create the 3D wire of the mesh applying Voronoi (I tried to use (Python) scipy.spatial.Voronoi but the result was something different from what I expected).&#xD;&#xA;&#xD;&#xA;I am missing something? Can anyone suggest the proper pipeline and algorithms I have to implement to create such patterns?&#xD;&#xA;&#xD;&#xA;[EDIT] Here are a few example of what I get handling the result i get from scipy.spatial.Voronoi like this (as suggested [here][3]):&#xD;&#xA;&#xD;&#xA;    vor = Voronoi(points)&#xD;&#xA;    for vpair in vor.ridge_vertices:&#xD;&#xA;        for i in range(len(vpair) - 1):&#xD;&#xA;            if all(x &gt;= 0 for x in vpair):&#xD;&#xA;                v0 = vor.vertices[vpair[i]]&#xD;&#xA;                v1 = vor.vertices[vpair[i+1]]&#xD;&#xA;                create_line(v0.tolist(), v1.tolist())&#xD;&#xA;&#xD;&#xA;The grey vertices are the sampled points (the original shape was a simple sphere):&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Here is a more complex shape (an arm)&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8RYgU.jpg&#xD;&#xA;  [2]: http://link.springer.com/article/10.1007%2Fs11432-011-4322-8#/page-1&#xD;&#xA;  [3]: http://stackoverflow.com/questions/23658776/voronoi-diagram-edges-how-to-get-edges-in-the-form-point1-point2-from-a-scip&#xD;&#xA;  [4]: https://i.stack.imgur.com/gz8hD.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/mCkPm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3013" PostHistoryTypeId="2" PostId="1644" RevisionGUID="a7ae8bd2-fa7b-465b-886d-53a107b635e1" CreationDate="2015-10-21T15:46:02.827" UserId="1902" Text="Most information about memory mapped displays on the net are about those in which there is essentially a location in main memory for each pixel on the display. A hypothetical 1024 x 512 display would therefore have 524,288 locations each mapped to a unique pixel. To set a pixel to a particular color, all you basically need to do is write an RGB value into the corresponding memory location for that pixel, eg: MOV 0xFF3C0A, 0x00BB75. The first argument in that instruction is the address holding the RGB value and the second is the address of the pixel you are copying it to.&#xD;&#xA;&#xD;&#xA;However, this can use up a quite a lot of main memory, which might not be ideal for certain systems. In a machine with a 32 bit or higher word size, it could instead be possible to have a single &quot;display output register&quot; into which you would write a single word of data containing the X and Y coordinates as well as the RGB value for the pixel you want to set. For a 1024 x 512 display with a 12-bit color depth, 31 bits would suffice to specify all this. The data 'written' into that register would either be sent to a display adapter or sent directly to the display and decoded there. This would save over half a megabyte of memory while still retaining the memory-mapped model.&#xD;&#xA;&#xD;&#xA;So is this actually a thing or not?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3014" PostHistoryTypeId="1" PostId="1644" RevisionGUID="a7ae8bd2-fa7b-465b-886d-53a107b635e1" CreationDate="2015-10-21T15:46:02.827" UserId="1902" Text="Does this type of memory-mapping for a display exist?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3015" PostHistoryTypeId="3" PostId="1644" RevisionGUID="a7ae8bd2-fa7b-465b-886d-53a107b635e1" CreationDate="2015-10-21T15:46:02.827" UserId="1902" Text="|pixels|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3030" PostHistoryTypeId="2" PostId="1648" RevisionGUID="e6901e86-f37a-4774-af5b-b7d29e744411" CreationDate="2015-10-23T17:26:14.500" UserId="56" Text="In your 31 bit solution, the thing moat likely to happen there is that youd give an extra bit to green and make  32 bit solution.  In 16 bit color for instance, r and b get 5 bits while g gets 6 bits, because your eye can distinguish more greens.&#xA;&#xA;As far as the rest, whether you have a gpu or not, writing to single pixels at a time is bad form.&#xA;&#xA;Instead you want to do block operations that either fill or copy large strips of memory ideally.&#xA;&#xA;For some things, like alpha blending, that isn't able to be done as a block operation so easily.&#xA;&#xA;As a solution to this, modern computers have a processor that is closer to the video memory, so there isn't too much latency when pushing pixels back and forth across the main bus.&#xA;&#xA;Also, instead of fewer more powerful cores, there are a multitude of less powerful cores, which helps address the situation I mentioned in alpha blending.&#xA;&#xA;That processor is the gpu and the programs you write for it are called shaders (;&#xA;&#xA;What you are asking about doesn't exist to my knowledge and seems like a bad usage pattern." ContentLicense="CC BY-SA 3.0" />
  <row Id="3031" PostHistoryTypeId="5" PostId="1648" RevisionGUID="d92634cf-f6df-429d-8daa-fb8bea4c1604" CreationDate="2015-10-23T17:33:02.260" UserId="56" Comment="added 304 characters in body" Text="In your 31 bit solution, the thing most likely to happen there is that you'd give an extra bit to green and make a 32 bit solution.  In 16 bit color for instance, r and b get 5 bits while g gets 6 bits, because your eye can distinguish more greens.&#xD;&#xA;&#xD;&#xA;Or maybe you'd use that extra bit to have 1 bit alpha? Not sure if that'd be very useful though...&#xD;&#xA;&#xD;&#xA;As far as the rest, whether you have a gpu or not, writing to single pixels at a time is bad form.&#xD;&#xA;&#xD;&#xA;Instead, you ideally want to do block operations that either fill or copy large strips of memory.&#xD;&#xA;&#xD;&#xA;For some things, like alpha blending, that isn't able to be done as a block operation very easily so is a more expensive operation in general.&#xD;&#xA;&#xD;&#xA;As a solution to this, modern computers have a processor that is closer to the video memory, so there isn't too much latency when pushing pixels back and forth across the main bus to do things like calculate alpha blended values involving the source and destination pixel.&#xD;&#xA;&#xD;&#xA;Also, instead of fewer more powerful cores, there are many less powerful cores, which helps address the situation of needing &quot;one off&quot; pixel operations.&#xD;&#xA;&#xD;&#xA;That processor I'm referring to is the gpu and the programs you write for it are called shaders (;&#xD;&#xA;&#xD;&#xA;What you are asking about doesn't exist to my knowledge and seems like a bad usage pattern, so seems unlikely to exist IMO." ContentLicense="CC BY-SA 3.0" />
  <row Id="3033" PostHistoryTypeId="2" PostId="1649" RevisionGUID="13dc4706-4a69-469b-8f8f-00f6a1387fe9" CreationDate="2015-10-24T02:42:58.883" UserId="113" Text="I'm playing around with directX 12 and I'm having some problems loading geometry in. I have a std::vector&lt;VertexPositionColor&gt; vertices definition and I do exactly what the dx12 template does with it.&#xD;&#xA;&#xD;&#xA;      const UINT vertexBufferSize = sizeof(vertices);&#xD;&#xA;&#xD;&#xA;      // Create the vertex buffer resource in the GPU's default heap and copy vertex data into it using the upload heap.&#xD;&#xA;      // The upload resource must not be released until after the GPU has finished using it.&#xD;&#xA;      Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; vertexBufferUpload;&#xD;&#xA;&#xD;&#xA;      CD3DX12_HEAP_PROPERTIES defaultHeapProperties(D3D12_HEAP_TYPE_DEFAULT);&#xD;&#xA;      CD3DX12_RESOURCE_DESC vertexBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize);&#xD;&#xA;      DX::ThrowIfFailed(d3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;         &amp;defaultHeapProperties,&#xD;&#xA;         D3D12_HEAP_FLAG_NONE,&#xD;&#xA;         &amp;vertexBufferDesc,&#xD;&#xA;         D3D12_RESOURCE_STATE_COPY_DEST,&#xD;&#xA;         nullptr,&#xD;&#xA;         IID_PPV_ARGS(&amp;mVertexBuffer)));&#xD;&#xA;&#xD;&#xA;      CD3DX12_HEAP_PROPERTIES uploadHeapProperties(D3D12_HEAP_TYPE_UPLOAD);&#xD;&#xA;      DX::ThrowIfFailed(d3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;         &amp;uploadHeapProperties,&#xD;&#xA;         D3D12_HEAP_FLAG_NONE,&#xD;&#xA;         &amp;vertexBufferDesc,&#xD;&#xA;         D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;         nullptr,&#xD;&#xA;         IID_PPV_ARGS(&amp;vertexBufferUpload)));&#xD;&#xA;&#xD;&#xA;      mVertexBuffer-&gt;SetName(L&quot;Vertex Buffer Resource&quot;);&#xD;&#xA;      vertexBufferUpload-&gt;SetName(L&quot;Vertex Buffer Upload Resource&quot;);&#xD;&#xA;&#xD;&#xA;      // Upload the vertex buffer to the GPU.&#xD;&#xA;      {&#xD;&#xA;         D3D12_SUBRESOURCE_DATA vertexData = {};&#xD;&#xA;         vertexData.pData = reinterpret_cast&lt;BYTE*&gt;(vertices.data());&#xD;&#xA;         vertexData.RowPitch = vertexBufferSize;&#xD;&#xA;         vertexData.SlicePitch = vertexData.RowPitch;&#xD;&#xA;&#xD;&#xA;         UpdateSubresources(mCommandList.Get(), mVertexBuffer.Get(), vertexBufferUpload.Get(), 0, 0, 1, &amp;vertexData);&#xD;&#xA;&#xD;&#xA;         CD3DX12_RESOURCE_BARRIER vertexBufferResourceBarrier =&#xD;&#xA;            CD3DX12_RESOURCE_BARRIER::Transition(mVertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);&#xD;&#xA;         mCommandList-&gt;ResourceBarrier(1, &amp;vertexBufferResourceBarrier);&#xD;&#xA;      }&#xD;&#xA;But this is what I get in the graphics debugger when it was suppossed to be a sphere. I can confirm that the data in vertices is correct.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/a6cL7.png&#xD;&#xA;&#xD;&#xA;If I change vertices to be what the template code had it works and renders the default cube. The only real difference mine is using a vector instead of an array.&#xD;&#xA;&#xD;&#xA;    VertexPositionColor cubeVertices[] =&#xD;&#xA;    {&#xD;&#xA;		{ XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f) },&#xD;&#xA;		{ XMFLOAT3(-0.5f, -0.5f,  0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) },&#xD;&#xA;		{ XMFLOAT3(-0.5f,  0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) },&#xD;&#xA;		{ XMFLOAT3(-0.5f,  0.5f,  0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f) },&#xD;&#xA;		{ XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) },&#xD;&#xA;		{ XMFLOAT3(0.5f, -0.5f,  0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f) },&#xD;&#xA;		{ XMFLOAT3(0.5f,  0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f) },&#xD;&#xA;		{ XMFLOAT3(0.5f,  0.5f,  0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f) },&#xD;&#xA;	};&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3034" PostHistoryTypeId="1" PostId="1649" RevisionGUID="13dc4706-4a69-469b-8f8f-00f6a1387fe9" CreationDate="2015-10-24T02:42:58.883" UserId="113" Text="Dx12 Vertex Buffer incorrect" ContentLicense="CC BY-SA 3.0" />
  <row Id="3035" PostHistoryTypeId="3" PostId="1649" RevisionGUID="13dc4706-4a69-469b-8f8f-00f6a1387fe9" CreationDate="2015-10-24T02:42:58.883" UserId="113" Text="|directx12|vertex-buffer-object|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3036" PostHistoryTypeId="2" PostId="1650" RevisionGUID="db7eaecd-2da5-4e32-af6b-1cb8d6013215" CreationDate="2015-10-24T03:58:23.510" UserId="137" Text="Vector has a few different semantics. For one it's a struct containing a pointer a capacity and a length (at the very least). That means that `sizeof` will not reflect how much data is actually stored in there.&#xD;&#xA;&#xD;&#xA;If you need to get the size in bytes of the data then you need&#xD;&#xA;&#xD;&#xA;    const UINT vertexBufferSize = sizeof(vertices::value_type) * vertices.size();" ContentLicense="CC BY-SA 3.0" />
  <row Id="3037" PostHistoryTypeId="2" PostId="1651" RevisionGUID="6404504a-ae60-4c1f-8012-1b191b896483" CreationDate="2015-10-24T15:06:21.040" UserId="1800" Text="I'd like to &quot;hook&quot; into a running game, say Mario Bros, and capture each frame rendered... saving that frame to an image file. A good example of something similar is FRAPS. --Note: I don't want to capture the whole screen/desktop. I want to capture a targeted window.&#xD;&#xA;&#xD;&#xA;I have had a look at [OBS][1] (Open Broadcasting Software) but it is not particularly fast and worst of all, there is no/poor documentation, making a massive project written in c and c++ nearly inaccessible for a new-to-c++ programmer.&#xD;&#xA;&#xD;&#xA;I know that this can be done with OpenGL, GDI and with Direct3D, but I am unable to find some good examples on the net. &#xD;&#xA;&#xD;&#xA;I read that glReadlPixels (using OpenGL) can be used and I've read the [documentation][2], but the post mentioned nothing about hooking into a running game/application graphics.&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA; 1. Can I hook into the graphics of a game developed with OpenGL, using,&#xD;&#xA;    say, Direct3D? Does the library used for hooking have to be the same&#xD;&#xA;    as the one used by the game?&#xD;&#xA;    &#xD;&#xA; 2. How do I hook into the game's rendered frames so that I can output&#xD;&#xA;    those frames to image files or to a video file? (Just some links or&#xD;&#xA;    brief explanation of what I need to do would be great)&#xD;&#xA;    &#xD;&#xA; 3. BackBuffer - I read that it is very fast accessing the BackBuffer to&#xD;&#xA;    retrieve the frames. Does someone have an example for me on how to&#xD;&#xA;    do this with the latest libraries? I have found that most examples&#xD;&#xA;    are out of date.&#xD;&#xA;&#xD;&#xA; 4. For my purposes, is there any clearly &quot;this is faster than that&quot;? What I mean is, would, say, OpenGL, be faster for my purposes? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If someone knows of an open-source project (that does essentially what I need) that is actively developed and well documented, I'd love to know about it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://obsproject.com/&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man2/xhtml/glReadPixels.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="3038" PostHistoryTypeId="1" PostId="1651" RevisionGUID="6404504a-ae60-4c1f-8012-1b191b896483" CreationDate="2015-10-24T15:06:21.040" UserId="1800" Text="Screen capture of game video" ContentLicense="CC BY-SA 3.0" />
  <row Id="3039" PostHistoryTypeId="3" PostId="1651" RevisionGUID="6404504a-ae60-4c1f-8012-1b191b896483" CreationDate="2015-10-24T15:06:21.040" UserId="1800" Text="|opengl|direct3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3040" PostHistoryTypeId="5" PostId="1651" RevisionGUID="d7889a90-3681-4c5c-9076-bf5aca0a9812" CreationDate="2015-10-24T17:48:05.633" UserId="1800" Comment="added 42 characters in body" Text="I'd like to &quot;hook&quot; into a running game, say Mario Bros, and capture each frame rendered... saving that frame to an image file. A good example of something similar is FRAPS. --Note: I don't want to capture the whole screen/desktop. I want to capture a targeted window.&#xD;&#xA;&#xD;&#xA;I have had a look at [OBS][1] (Open Broadcasting Software) but it is not particularly fast. Don't get me wrong, it's great software, but unfortunately there is no/poor documentation, making a massive project written in c and c++ nearly inaccessible for a new-to-c++ programmer.&#xD;&#xA;&#xD;&#xA;I know that this can be done with OpenGL, GDI and with Direct3D, but I am unable to find some good examples on the net. &#xD;&#xA;&#xD;&#xA;I read that glReadlPixels (using OpenGL) can be used and I've read the [documentation][2], but the post mentioned nothing about hooking into a running game/application graphics.&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA; 1. Can I hook into the graphics of a game developed with OpenGL, using,&#xD;&#xA;    say, Direct3D? Does the library used for hooking have to be the same&#xD;&#xA;    as the one used by the game?&#xD;&#xA;    &#xD;&#xA; 2. How do I hook into the game's rendered frames so that I can output&#xD;&#xA;    those frames to image files or to a video file? (Just some links or&#xD;&#xA;    brief explanation of what I need to do would be great)&#xD;&#xA;    &#xD;&#xA; 3. BackBuffer - I read that it is very fast accessing the BackBuffer to&#xD;&#xA;    retrieve the frames. Does someone have an example for me on how to&#xD;&#xA;    do this with the latest libraries? I have found that most examples&#xD;&#xA;    are out of date.&#xD;&#xA;&#xD;&#xA; 4. For my purposes, is there any clearly &quot;this is faster than that&quot;? What I mean is, would, say, OpenGL, be faster for my purposes? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If someone knows of an open-source project (that does essentially what I need) that is actively developed and well documented, I'd love to know about it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://obsproject.com/&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man2/xhtml/glReadPixels.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="3041" PostHistoryTypeId="2" PostId="1652" RevisionGUID="f92f519f-ea07-4e70-8c33-77bb7110c857" CreationDate="2015-10-24T17:49:58.717" UserId="54" Text="It is possible to do what you describe, but I'm afraid it is not a trivial process. Actually, this will be very tied to the Operating Systems you are targeting and possibly also requiring specific tweaks for the given game/application.&#xD;&#xA;&#xD;&#xA;I would start looking into [DLL injection][1] techniques, which should allow, for instance, intercepting calls to the Direct3D (Windows) or OpenGL APIs, which you can then use to copy de framebuffers of the application. A quick Internet search turns up [this][2] and [this][3] with detailed explanation. &#xD;&#xA;&#xD;&#xA;I once wrote a small-scale OpenGL interceptor on MacOS by injecting a custom shared module, but it was under very controlled circumstances and making a lot of assumptions, such as having root privileges in the system, so for a production tool, it would be a lot more complicated. You can find another very interesting project [here][4] about intercepting the D3D API to install an automated AI bot on Starcraft, which should touch on very similar concepts to what you are looking for.&#xD;&#xA;&#xD;&#xA;Once you manage to intercept the underlying rendering API, you could then perhaps hook your code into each `SwapBuffers` or equivalent call to just copy the previous framebuffer before the swap, then save it (this is where something like `glReadPixels` would come into play).&#xD;&#xA;&#xD;&#xA;Copying and saving the framebuffer in an efficient manner is also challenging. The easy way is to just dump each frame as an uncompressed RBG image, but then you'll wind up with hundreds of gigabytes of data for just a couple of minutes of gameplay, so unless you have a nice HDD array at the corner of your table `;)`, you'll need to look into compressing the frames somehow. &#xD;&#xA;&#xD;&#xA;The downside of compressing the frames now is that it takes a lot of processing, so a naive approach might turn the once interactive application you are trying to record into an interactive slide-show `:(`. So at this stage you'd have to start thinking about optimizations.&#xD;&#xA;&#xD;&#xA;Don't know of any projects out there providing a library for efficient frame capture for games, but this would certainly be something nice to have! I think one thing that might be holding such project back is, like I mentioned at the beginning, that this is a very system dependent thing, so cases of use will most likely be limited to a single platform or OS.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/DLL_injection&#xD;&#xA;  [2]: http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html&#xD;&#xA;  [3]: http://www.evilsocket.net/2015/05/01/dynamically-inject-a-shared-library-into-a-running-process-on-androidarm/&#xD;&#xA;  [4]: https://graphics.stanford.edu/~mdfisher/D3D9Interceptor.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3042" PostHistoryTypeId="5" PostId="1652" RevisionGUID="f1f4b345-279a-4714-b29f-8dcd575ad219" CreationDate="2015-10-24T17:57:52.740" UserId="54" Comment="added 8 characters in body" Text="It is possible to do what you describe, but I'm afraid it is not a trivial process. Actually, this will be very tied to the Operating Systems you are targeting and possibly also requiring specific tweaks for the given game/application.&#xD;&#xA;&#xD;&#xA;I would start looking into [DLL injection][1] techniques, which should allow, for instance, intercepting calls to the Direct3D (Windows) or OpenGL APIs, which you can then use to copy de framebuffers of the application. A quick Internet search turns up [this][2] and [this][3] with detailed explanation. &#xD;&#xA;&#xD;&#xA;I once wrote a small-scale OpenGL interceptor on MacOS by injecting a custom shared module, but it was under very controlled circumstances and making a lot of assumptions, such as having root privileges in the system, so for a production tool, it would be a lot more complicated. You can find another very interesting project [here][4] about intercepting the D3D API to install an automated AI bot on Starcraft, which should touch on very similar concepts to what you are looking for.&#xD;&#xA;&#xD;&#xA;Once you manage to intercept the underlying rendering API, you could then perhaps hook your code into each `SwapBuffers` or equivalent call to just copy the previous framebuffer before the swap, then save it (this is where something like `glReadPixels` would come into play).&#xD;&#xA;&#xD;&#xA;Copying and saving the framebuffer in an efficient manner is also challenging. The easy way is to just dump each frame as an uncompressed RGB image, but then you'll wind up with hundreds of gigabytes of data for just a couple of minutes of gameplay, so unless you have a nice HDD array sitting at the corner of your table `;)`, you'll need to look into compressing the frames somehow. &#xD;&#xA;&#xD;&#xA;The downside of compressing the frames now is that it takes a lot of processing, so a naive approach might turn the once interactive application you are trying to record into an interactive slide-show `:(`. So at this stage you'd have to start thinking about optimizations.&#xD;&#xA;&#xD;&#xA;Don't know of any projects out there providing a library for efficient frame capture for games, but this would certainly be something nice to have! I think one thing that might be holding such project back is, like I mentioned at the beginning, that this is a very system dependent thing, so cases of use will most likely be limited to a single platform or OS.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/DLL_injection&#xD;&#xA;  [2]: http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics.html&#xD;&#xA;  [3]: http://www.evilsocket.net/2015/05/01/dynamically-inject-a-shared-library-into-a-running-process-on-androidarm/&#xD;&#xA;  [4]: https://graphics.stanford.edu/~mdfisher/D3D9Interceptor.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3043" PostHistoryTypeId="5" PostId="1650" RevisionGUID="b5fa962a-beaa-4e93-b51e-4bfbefdc9a7a" CreationDate="2015-10-24T19:05:30.400" UserId="137" Comment="added 53 characters in body" Text="Vector has a few different semantics from static arrays. For one it's a struct containing a pointer a capacity and a length (at the very least). That means that `sizeof` will not reflect how much data is actually stored in there (that only works on static arrays.&#xD;&#xA;&#xD;&#xA;If you need to get the size in bytes of the data then you need&#xD;&#xA;&#xD;&#xA;    const UINT vertexBufferSize = sizeof(vertices::value_type) * vertices.size();" ContentLicense="CC BY-SA 3.0" />
  <row Id="3052" PostHistoryTypeId="5" PostId="1651" RevisionGUID="92a5f86d-c72b-4a1e-9a3a-e2901fcfb16d" CreationDate="2015-10-25T17:07:58.357" UserId="1800" Comment="added 298 characters in body" Text="I'd like to &quot;hook&quot; into a running game, say Mario Bros, and capture each frame rendered... saving that frame to an image file. A good example of something similar is FRAPS. --Note: I don't want to capture the whole screen/desktop. I want to capture a targeted window.&#xD;&#xA;&#xD;&#xA;I have had a look at [OBS][1] (Open Broadcasting Software) but it is not particularly fast. Don't get me wrong, it's great software, but unfortunately there is no/poor documentation, making a massive project written in c and c++ nearly inaccessible for a new-to-c++ programmer.&#xD;&#xA;&#xD;&#xA;I've also had a look at [GamingAnywhere][2], but unfortunately, I am unable to get it to work, there is very little/no documentation, runs in VS2010 only and is messy (with poor variable naming). However, it is a research project and so it is understandably undocumented and messy.&#xD;&#xA;&#xD;&#xA;I know that this can be done with OpenGL, GDI and with Direct3D, but I am unable to find some good examples on the net. &#xD;&#xA;&#xD;&#xA;I read that glReadlPixels (using OpenGL) can be used and I've read the [documentation][3], but the post mentioned nothing about hooking into a running game/application graphics.&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA; 1. Can I hook into the graphics of a game developed with OpenGL, using,&#xD;&#xA;    say, Direct3D? Does the library used for hooking have to be the same&#xD;&#xA;    as the one used by the game?&#xD;&#xA;    &#xD;&#xA; 2. How do I hook into the game's rendered frames so that I can output&#xD;&#xA;    those frames to image files or to a video file? (Just some links or&#xD;&#xA;    brief explanation of what I need to do would be great)&#xD;&#xA;    &#xD;&#xA; 3. BackBuffer - I read that it is very fast accessing the BackBuffer to&#xD;&#xA;    retrieve the frames. Does someone have an example for me on how to&#xD;&#xA;    do this with the latest libraries? I have found that most examples&#xD;&#xA;    are out of date.&#xD;&#xA;&#xD;&#xA; 4. For my purposes, is there any clearly &quot;this is faster than that&quot;? What I mean is, would, say, OpenGL, be faster for my purposes? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If someone knows of an open-source project (that does essentially what I need) that is actively developed and well documented, I'd love to know about it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://obsproject.com/&#xD;&#xA;  [2]: http://gaminganywhere.org/perf.html&#xD;&#xA;  [3]: https://www.opengl.org/sdk/docs/man2/xhtml/glReadPixels.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="3053" PostHistoryTypeId="2" PostId="1656" RevisionGUID="8c6ee6e0-779e-43f9-80b5-e4f872b166c1" CreationDate="2015-10-25T21:03:06.477" UserId="214" Text="I'm trying to use `glMultiDrawArraysIndirect` to render a batch of object.&#xD;&#xA;&#xD;&#xA;In my example I have a cube and a sphere **(in this order)** in a `VBO` and a `GL_SHADER_STORAGE_BUFFER (SSBO)` that contains matrix transforms as well as a `GL_DRAW_INDIRECT_BUFFER (DIB)` that contains the draw commands.&#xD;&#xA;&#xD;&#xA;The allocation of both the `SSBO` and `DIB` are managed by a custom class.&#xD;&#xA;&#xD;&#xA;I can currently render both objects successfully, each using their own transform. The problem I'm encountering is rendering just the sphere by specifying an offset. As per the OpenGL spec:&#xD;&#xA;&#xD;&#xA;&gt; If a buffer is bound to the `GL_DRAW_INDIRECT_BUFFER` binding at the&#xD;&#xA;&gt; time of a call to **glMultiDrawArraysIndirect**, *indirect* is interpreted&#xD;&#xA;&gt; as an offset, in basic machine units, into that buffer and the&#xD;&#xA;&gt; parameter data is read from the buffer rather than from client memory.&#xD;&#xA;&#xD;&#xA;but doing the following code to render results in nothing being rendered:&#xD;&#xA;&#xD;&#xA;    // Calculates the offset &amp; size and calls BindBufferRange &#xD;&#xA;    this-&gt;_indrMatrixBuffer.BindBufferRange(0, 1, 1);&#xD;&#xA;    // A simple call to glBindBuffer, binding to GL_DRAW_INDIRECT_BUFFER&#xD;&#xA;    this-&gt;_indrBuffer.BindBuffer();&#xD;&#xA;    // Render&#xD;&#xA;    glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0);&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;The `DAICmd` is a struct of four `unsigned int` (as per the [spec][1])&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;At first I though it might be my custom class but calling `glMultiDrawArraysIndirect(GL_TRIANGLES, 0, 1, 0);` and keeping the matrix buffer offset renders the cube in the spheres position!&#xD;&#xA;&#xD;&#xA;What am I missing to get this to work?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Extra notes**&#xD;&#xA;&#xD;&#xA; - Both the `SSBO` &amp; `DIB` are mapped using the flags `GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT and GL_MAP_COHERENT_BIT` and are created with the same flags plus `GL_DYNAMIC_STORAGE_BIT`&#xD;&#xA; - I'm using OpenGL 4.5&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/glMultiDrawArraysIndirect.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="3054" PostHistoryTypeId="1" PostId="1656" RevisionGUID="8c6ee6e0-779e-43f9-80b5-e4f872b166c1" CreationDate="2015-10-25T21:03:06.477" UserId="214" Text="glMultiDrawArraysIndirect does not work when specifying an offset" ContentLicense="CC BY-SA 3.0" />
  <row Id="3055" PostHistoryTypeId="3" PostId="1656" RevisionGUID="8c6ee6e0-779e-43f9-80b5-e4f872b166c1" CreationDate="2015-10-25T21:03:06.477" UserId="214" Text="|opengl|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3056" PostHistoryTypeId="2" PostId="1657" RevisionGUID="fc2e7ed2-ab2f-4f83-9bfc-0be3495206e1" CreationDate="2015-10-26T01:10:09.947" UserId="1886" Text="3D math covers vector algebra and matrix algebra, which are easily calculated on paper, but not so easy when coding them effectively. I only leant some basic algorithms on matrix in my Data Structure course, which is not enough when it comes to accurate and effective operations.&#xD;&#xA;&#xD;&#xA;Is there some books on this topic?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3057" PostHistoryTypeId="1" PostId="1657" RevisionGUID="fc2e7ed2-ab2f-4f83-9bfc-0be3495206e1" CreationDate="2015-10-26T01:10:09.947" UserId="1886" Text="Is there some book about how to design a 3D math lib?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3058" PostHistoryTypeId="3" PostId="1657" RevisionGUID="fc2e7ed2-ab2f-4f83-9bfc-0be3495206e1" CreationDate="2015-10-26T01:10:09.947" UserId="1886" Text="|algorithm|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3060" PostHistoryTypeId="2" PostId="1658" RevisionGUID="740ba680-81d4-41ca-b9e7-9c06d7c62e06" CreationDate="2015-10-26T06:33:58.150" UserId="212" Text="Books: http://www.essentialmath.com/book.htm is the one.&#xD;&#xA;&#xD;&#xA;Best algos on the real 3D topics (and some tricky 2D like image resize and premult-alpha ), explained and with source most of the time.&#xD;&#xA;&#xD;&#xA;The website is very nice too, the &quot;tutorial&quot; full of gems" ContentLicense="CC BY-SA 3.0" />
  <row Id="3061" PostHistoryTypeId="5" PostId="1658" RevisionGUID="e76adab8-f35c-4959-89e4-b42f57526152" CreationDate="2015-10-26T07:07:56.683" UserId="212" Comment="adding geometric tools websitet" Text="Books: http://www.essentialmath.com/book.htm is the one.&#xD;&#xA;&#xD;&#xA;Best algos on the real 3D topics (and some tricky 2D like image resize and premult-alpha ), explained and with source most of the time.&#xD;&#xA;&#xD;&#xA;The website is very nice too, the &quot;tutorial&quot; full of gems&#xD;&#xA;&#xD;&#xA;Adding http://www.geometrictools.com/index.html which is the most complete source code repository on the topic, with loads of very precise algos implemented." ContentLicense="CC BY-SA 3.0" />
  <row Id="3062" PostHistoryTypeId="5" PostId="1656" RevisionGUID="f55c881f-9257-4ff3-9fc4-2cf8444843cf" CreationDate="2015-10-26T08:38:52.687" UserId="214" Comment="extra note" Text="I'm trying to use `glMultiDrawArraysIndirect` to render a batch of object.&#xD;&#xA;&#xD;&#xA;In my example I have a cube and a sphere **(in this order)** in a `VBO` and a `GL_SHADER_STORAGE_BUFFER (SSBO)` that contains matrix transforms as well as a `GL_DRAW_INDIRECT_BUFFER (DIB)` that contains the draw commands.&#xD;&#xA;&#xD;&#xA;The allocation of both the `SSBO` and `DIB` are managed by a custom class.&#xD;&#xA;&#xD;&#xA;I can currently render both objects successfully, each using their own transform. The problem I'm encountering is rendering just the sphere by specifying an offset. As per the OpenGL spec:&#xD;&#xA;&#xD;&#xA;&gt; If a buffer is bound to the `GL_DRAW_INDIRECT_BUFFER` binding at the&#xD;&#xA;&gt; time of a call to **glMultiDrawArraysIndirect**, *indirect* is interpreted&#xD;&#xA;&gt; as an offset, in basic machine units, into that buffer and the&#xD;&#xA;&gt; parameter data is read from the buffer rather than from client memory.&#xD;&#xA;&#xD;&#xA;but doing the following code to render results in nothing being rendered:&#xD;&#xA;&#xD;&#xA;    // Calculates the offset &amp; size and calls BindBufferRange &#xD;&#xA;    this-&gt;_indrMatrixBuffer.BindBufferRange(0, 1, 1);&#xD;&#xA;    // A simple call to glBindBuffer, binding to GL_DRAW_INDIRECT_BUFFER&#xD;&#xA;    this-&gt;_indrBuffer.BindBuffer();&#xD;&#xA;    // Render&#xD;&#xA;    glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0);&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;The `DAICmd` is a struct of four `unsigned int` (as per the [spec][1])&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;At first I though it might be my custom class but calling `glMultiDrawArraysIndirect(GL_TRIANGLES, 0, 1, 0);` and keeping the matrix buffer offset renders the cube in the spheres position!&#xD;&#xA;&#xD;&#xA;What am I missing to get this to work?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Extra notes**&#xD;&#xA;&#xD;&#xA; - Both the `SSBO` &amp; `DIB` are mapped using the flags `GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT and GL_MAP_COHERENT_BIT` and are created with the same flags plus `GL_DYNAMIC_STORAGE_BIT`&#xD;&#xA; - I'm using OpenGL 4.5&#xD;&#xA; - Using `glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0);` does not produce an error when using `glGetError()`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/glMultiDrawArraysIndirect.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="3063" PostHistoryTypeId="5" PostId="1656" RevisionGUID="ef72ee66-d6aa-4c68-822f-f2c96c7a7865" CreationDate="2015-10-26T09:10:22.040" UserId="214" Comment="extra note" Text="I'm trying to use `glMultiDrawArraysIndirect` to render a batch of object.&#xD;&#xA;&#xD;&#xA;In my example I have a cube and a sphere **(in this order)** in a `VBO` and a `GL_SHADER_STORAGE_BUFFER (SSBO)` that contains matrix transforms as well as a `GL_DRAW_INDIRECT_BUFFER (DIB)` that contains the draw commands.&#xD;&#xA;&#xD;&#xA;The allocation of both the `SSBO` and `DIB` are managed by a custom class.&#xD;&#xA;&#xD;&#xA;I can currently render both objects successfully, each using their own transform. The problem I'm encountering is rendering just the sphere by specifying an offset. As per the OpenGL spec:&#xD;&#xA;&#xD;&#xA;&gt; If a buffer is bound to the `GL_DRAW_INDIRECT_BUFFER` binding at the&#xD;&#xA;&gt; time of a call to **glMultiDrawArraysIndirect**, *indirect* is interpreted&#xD;&#xA;&gt; as an offset, in basic machine units, into that buffer and the&#xD;&#xA;&gt; parameter data is read from the buffer rather than from client memory.&#xD;&#xA;&#xD;&#xA;but doing the following code to render results in nothing being rendered:&#xD;&#xA;&#xD;&#xA;    // Calculates the offset &amp; size and calls BindBufferRange &#xD;&#xA;    this-&gt;_indrMatrixBuffer.BindBufferRange(0, 1, 1);&#xD;&#xA;    // A simple call to glBindBuffer, binding to GL_DRAW_INDIRECT_BUFFER&#xD;&#xA;    this-&gt;_indrBuffer.BindBuffer();&#xD;&#xA;    // Render&#xD;&#xA;    glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0);&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;The `DAICmd` is a struct of four `unsigned int` (as per the [spec][1])&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;At first I though it might be my custom class but calling `glMultiDrawArraysIndirect(GL_TRIANGLES, 0, 1, 0);` and keeping the matrix buffer offset renders the cube in the spheres position!&#xD;&#xA;&#xD;&#xA;What am I missing to get this to work?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Extra notes**&#xD;&#xA;&#xD;&#xA; - Both the `SSBO` &amp; `DIB` are mapped using the flags `GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT and GL_MAP_COHERENT_BIT` and are created with the same flags plus `GL_DYNAMIC_STORAGE_BIT`&#xD;&#xA; - I'm using OpenGL 4.5&#xD;&#xA; - Using `glMultiDrawArraysIndirect(GL_TRIANGLES, (void*)sizeof(DAICmd), 1, 0);` does not produce an error when using `glGetError()`&#xD;&#xA; - Using KHR_debug produces no errors either&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/glMultiDrawArraysIndirect.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="3064" PostHistoryTypeId="2" PostId="1659" RevisionGUID="736c004f-b65e-4573-b7c7-81b5296a2853" CreationDate="2015-10-26T16:24:09.740" UserId="214" Text="The problem was my class handling the population fo the `draw indirect commands`.&#xD;&#xA;&#xD;&#xA;Each time I added a new command to the indirect buffer I also incremented the `baseInstance`, so the cube had `baseInstance = 0` and the sphere had `baseInstance = 1`.&#xD;&#xA; &#xD;&#xA;The reason why it doesn't render the sphere is because `glMultiDrawArraysIndirect` pretty much evaluates as `glDrawArraysInstancedBaseInstance(mode,  cmd-&gt;first,  cmd-&gt;count,  cmd-&gt;instanceCount, cmd-&gt;baseInstance);` (as per the [OGL wiki][1]).&#xD;&#xA;&#xD;&#xA;The drawID is calculated as `(gl_InstanceID / divisor) + `**`baseInstance`** ([link][2]), which means that the drawID is out of range when trying to render with an offset, as the sphere now appears as the first element in the indirect buffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/GLAPI/glMultiDrawArraysIndirect&#xD;&#xA;  [2]: https://www.opengl.org/wiki/GLAPI/glDrawArraysInstancedBaseInstance" ContentLicense="CC BY-SA 3.0" />
  <row Id="3065" PostHistoryTypeId="2" PostId="1660" RevisionGUID="2d14dd4c-b7a7-4da4-95cd-f190e3f4671f" CreationDate="2015-10-26T20:29:26.973" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3066" PostHistoryTypeId="2" PostId="1661" RevisionGUID="a344e5d0-87f3-41ac-b0f7-e1d6459b8cbb" CreationDate="2015-10-26T20:29:26.973" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3067" PostHistoryTypeId="2" PostId="1662" RevisionGUID="fc86d42c-bb27-47d6-94a1-f21569005a78" CreationDate="2015-10-27T06:52:32.947" UserId="1937" Text="first post, I'm sure there'll be plenty more where this came from :)&#xD;&#xA;&#xD;&#xA;I'm exploring isosurface algorithms on GPU for a bachelor's project (specifically concentrating on just binary in/out voxel data rather than real-valued fields). So I have a CPU implementation of good old marching cubes up and running in OpenFrameworks, and now at the stage of trying to port it to GLSL compute shaders, and considering the pitfalls before I dive in. I've only written vert and frag shaders before so it's all new to me.&#xD;&#xA;&#xD;&#xA;My first issue is how to efficiently use a lookup table across dozens or hundreds of threads in a workgroup? I understand a GPU has different kinds of memory for different tasks but not fully sure on how each operates or which type to use.&#xD;&#xA;&#xD;&#xA;Paul Bourke's classic copypasta table is a 256*16 array so if using a scalar byte type this can presumably be packed into a 4kb texture or SSBO.&#xD;&#xA;&#xD;&#xA;The question is, how to stop the different threads from tripping each other up? Many cubes in each work group can potentially have the same configuration therefore trying to access the same location in the buffer at the same time. Is there a workaround or optimization to deal with this?&#xD;&#xA;&#xD;&#xA;Thanks in advance, &#xD;&#xA;Russ" ContentLicense="CC BY-SA 3.0" />
  <row Id="3068" PostHistoryTypeId="1" PostId="1662" RevisionGUID="fc86d42c-bb27-47d6-94a1-f21569005a78" CreationDate="2015-10-27T06:52:32.947" UserId="1937" Text="Optimal memory access when using lookup tables on GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3069" PostHistoryTypeId="3" PostId="1662" RevisionGUID="fc86d42c-bb27-47d6-94a1-f21569005a78" CreationDate="2015-10-27T06:52:32.947" UserId="1937" Text="|opengl|algorithm|gpgpu|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3070" PostHistoryTypeId="2" PostId="1663" RevisionGUID="5fc3915f-c81e-4080-af86-9fdb54bb01db" CreationDate="2015-10-27T08:05:36.913" UserId="1938" Text="Previously, to render a bunch of quads, I was simply using a few uniforms (One for a model matrix and another for the texture layer ID), however, I'd rather not have to loop through each quad and set both uniforms each time, each frame.&#xD;&#xA;&#xD;&#xA;So I went ahead and looked for better alternatives with which I could render everything with a single call.&#xD;&#xA;&#xD;&#xA;Now I'm using instanced rendering:&#xD;&#xA;&#xD;&#xA;    // In VAO definition            &#xD;&#xA;    glGenBuffers(1, &amp;instanceVBO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    glEnableVertexAttribArray(3);&#xD;&#xA;    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), nullptr);&#xD;&#xA;    glVertexAttribDivisor(3, 1);&#xD;&#xA;    glEnableVertexAttribArray(4);&#xD;&#xA;    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4)));&#xD;&#xA;    glVertexAttribDivisor(4, 1);&#xD;&#xA;    glEnableVertexAttribArray(5);&#xD;&#xA;    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 2));&#xD;&#xA;    glVertexAttribDivisor(5, 1);&#xD;&#xA;    glEnableVertexAttribArray(6);&#xD;&#xA;    glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 3));&#xD;&#xA;    glVertexAttribDivisor(6, 1);&#xD;&#xA;    glEnableVertexAttribArray(7);&#xD;&#xA;    glVertexAttribIPointer(7, 1, GL_UNSIGNED_INT, sizeof(RenderingData), (GLvoid*)(sizeof(glm::mat4)));&#xD;&#xA;    glVertexAttribDivisor(7, 1);&#xD;&#xA;&#xD;&#xA;    // In quad adding function&#xD;&#xA;    instanceData.push_back(quad-&gt;data);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;I'm using 2 VBOs: one for per-vertex data (Position, normal, etc vectors) and another for per-instance data (Model matrix and texture layer ID).&#xD;&#xA;&#xD;&#xA;My problem is the following: http://imgur.com/20Wb9pQ&#xD;&#xA;&#xD;&#xA;As you can see, the middle and bottom images aren't rendering correctly (Middle one is way too stretched, whereas bottom one's UV are incorrect, since they aren't filling the whole quad), however, I'm 98% sure both my vertex and instance data are correct, since when I was using the previously mentioned uniforms, they were rendering correctly.&#xD;&#xA;&#xD;&#xA;Also, I ***might*** 've spotted the problem: the indices. Somehow, if I change my glDrawElementsInstanced's count value to say, 12 indices, the middle one renders correctly, whereas the other 2, do not (Proof: http://imgur.com/PDQqbuT), same thing happens if I change them to 18 (The last one renders correctly and the other 2, do not).&#xD;&#xA;&#xD;&#xA;What might the problem be?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3071" PostHistoryTypeId="1" PostId="1663" RevisionGUID="5fc3915f-c81e-4080-af86-9fdb54bb01db" CreationDate="2015-10-27T08:05:36.913" UserId="1938" Text="Incorrect instanced rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="3072" PostHistoryTypeId="3" PostId="1663" RevisionGUID="5fc3915f-c81e-4080-af86-9fdb54bb01db" CreationDate="2015-10-27T08:05:36.913" UserId="1938" Text="|opengl|rendering|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3073" PostHistoryTypeId="5" PostId="1661" RevisionGUID="a865cd2b-2683-4d51-a4f6-18db82cc3da6" CreationDate="2015-10-27T08:33:48.850" UserId="1810" Comment="added 124 characters in body" Text="For questions related to textures: procedural generation, encodings, aspect characterisation, filtering, mapping, storage..." ContentLicense="CC BY-SA 3.0" />
  <row Id="3074" PostHistoryTypeId="24" PostId="1661" RevisionGUID="a865cd2b-2683-4d51-a4f6-18db82cc3da6" CreationDate="2015-10-27T08:33:48.850" Comment="Proposed by 1810 approved by 48, 231 edit id of 69" ContentLicense="CC BY-SA 3.0" />
  <row Id="3076" PostHistoryTypeId="2" PostId="1664" RevisionGUID="9b9616af-c1e7-4550-b12c-4ee1e7f21b78" CreationDate="2015-10-27T21:03:54.563" UserId="116" Text="I'm developing with OpenGL 4.1 and have good understanding of the modern pipeline. I was thinking on doing it with GL_LINE_LOOP for each face, but I think this will require several draw calls which certainly is not optimal. What could be a better approach?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3077" PostHistoryTypeId="1" PostId="1664" RevisionGUID="9b9616af-c1e7-4550-b12c-4ee1e7f21b78" CreationDate="2015-10-27T21:03:54.563" UserId="116" Text="How to render the wireframe of a cube without the diagonals on the faces?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3078" PostHistoryTypeId="3" PostId="1664" RevisionGUID="9b9616af-c1e7-4550-b12c-4ee1e7f21b78" CreationDate="2015-10-27T21:03:54.563" UserId="116" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3079" PostHistoryTypeId="2" PostId="1665" RevisionGUID="ba8ff183-c35b-4954-93c1-cd0ea394ac05" CreationDate="2015-10-27T22:11:26.847" UserId="528" Text="Things like that are usually done using an [index buffer][1]. The idea is that you have you have two buffers: One for all the vertices and one that determines the topology of what to draw. Then you can draw all the lines at once with a single [glDrawElements][2] call, using GL_LINES as mode.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Vertex_Specification#Index_buffers&#xD;&#xA;  [2]: https://www.opengl.org/wiki/GLAPI/glDrawElements" ContentLicense="CC BY-SA 3.0" />
  <row Id="3080" PostHistoryTypeId="10" PostId="1657" RevisionGUID="b9e03a9e-69af-4ec4-ab4a-bb1273fcf386" CreationDate="2015-10-28T05:37:33.750" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;},{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;}]}" />
  <row Id="3081" PostHistoryTypeId="2" PostId="1666" RevisionGUID="960ab2a8-465e-4809-a9c3-b3e701f945f3" CreationDate="2015-10-28T06:18:44.837" UserId="1944" Text="I can't understand math equations. I'm a graphic designer.&#xD;&#xA;&#xD;&#xA;What is &quot;the importance sampling&quot;?&#xD;&#xA;Could you explain that easily and using illustrations? using no math equations,&#xD;&#xA;&#xD;&#xA;and what is &quot;the multiple importance sampling&quot;?&#xD;&#xA;Could you explain that easily and using illustrations? using no math equations. what is the difference between &quot;the importance sampling&quot; and &quot;the multiple importance sampling&quot;?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3082" PostHistoryTypeId="1" PostId="1666" RevisionGUID="960ab2a8-465e-4809-a9c3-b3e701f945f3" CreationDate="2015-10-28T06:18:44.837" UserId="1944" Text="importance sampling and mutiple importance sampling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3083" PostHistoryTypeId="3" PostId="1666" RevisionGUID="960ab2a8-465e-4809-a9c3-b3e701f945f3" CreationDate="2015-10-28T06:18:44.837" UserId="1944" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3084" PostHistoryTypeId="5" PostId="1666" RevisionGUID="6dd3cb00-6a5e-4154-ab7a-6669cc5b956c" CreationDate="2015-10-28T10:11:30.387" UserId="231" Comment="Tidying of formating" Text="I can't understand math equations. I'm a graphic designer.&#xD;&#xA;&#xD;&#xA;- What is &quot;importance sampling&quot;?&#xD;&#xA;&#xD;&#xA;- What is &quot;multiple importance sampling&quot;?&#xD;&#xA;&#xD;&#xA;Could you explain easily, using illustrations and no math equations? What is the difference between &quot;importance sampling&quot; and &quot;multiple importance sampling&quot;?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3085" PostHistoryTypeId="4" PostId="1666" RevisionGUID="6dd3cb00-6a5e-4154-ab7a-6669cc5b956c" CreationDate="2015-10-28T10:11:30.387" UserId="231" Comment="Tidying of formating" Text="What is the difference between importance sampling and mutiple importance sampling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3086" PostHistoryTypeId="6" PostId="1666" RevisionGUID="6dd3cb00-6a5e-4154-ab7a-6669cc5b956c" CreationDate="2015-10-28T10:11:30.387" UserId="231" Comment="Tidying of formating" Text="|raytracing|sampling|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3087" PostHistoryTypeId="2" PostId="1667" RevisionGUID="b64f3f8e-e24c-475e-b28f-5ab4ea931e06" CreationDate="2015-10-28T10:12:19.223" UserId="385" Text="When shading a point on an opaque surface, you need to gather incoming light and weight it with the bidirectional reflectance distribution function (BRDF) of the material.&#xD;&#xA;&#xD;&#xA;The naive approach is to distribute samples equally over the hemisphere and probe all directions equally for incoming light. This is called **uniform sampling** (Fig. 1). While this works in most cases, it can take a long time to converge towards the correct result.&#xD;&#xA;&#xD;&#xA;[![Uniform sampling on the hemisphere][1]][1]&lt;br&gt;&#xD;&#xA;**Figure 1:** Uniform sampling on the hemisphere&#xD;&#xA;&#xD;&#xA;To speed things up, let's consider the properties of the surface in question. A diffuse surface needs to take light from all directions on the hemisphere into account, where light coming from flat angles has less influence. A perfect mirror only needs a single direction according to the law of reflection. **Importance sampling** takes this into account and distributes samples where light is expected to have a greater influence, judging from the BRDF. For the diffuse surface, a cosine sampling would be used (Fig. 2). For the perfect mirror, only a single ray is shot because all other directions have zero influence anyway.&#xD;&#xA;&#xD;&#xA;[![Cosine sampling on the hemisphere][2]][2]&lt;br&gt;&#xD;&#xA;**Figure 2:** Cosine sampling on the hemisphere&#xD;&#xA;&#xD;&#xA;Now, the BRDF is not the only thing that can be taken into account. When you have known light sources with strong intensity, it is often desirable to direct more rays towards these light sources, as these directions presumably have a greater impact on the result (i.e. there is more light coming from these directions). The idea to combine various different importance sampling strategies into one is called **multiple importance sampling**. This technique is not limited to the given example of BRDF + known lights, but can be used with any kind of sensible heuristic you can come up with.&#xD;&#xA;&#xD;&#xA;Images were generated using Holger Dammertz' [Hammersley Points on the Hemisphere][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sG2z5.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/uJksp.jpg&#xD;&#xA;  [3]: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3088" PostHistoryTypeId="5" PostId="1662" RevisionGUID="270cc3e0-782b-4f4d-b6b8-6f957663939d" CreationDate="2015-10-28T13:29:36.397" UserId="385" Comment="Edited out empty phrases" Text="I'm exploring isosurface algorithms on GPU for a bachelor's project (specifically concentrating on just binary in/out voxel data rather than real-valued fields). So I have a CPU implementation of good old marching cubes up and running in OpenFrameworks, and now at the stage of trying to port it to GLSL compute shaders, and considering the pitfalls before I dive in. I've only written vert and frag shaders before so it's all new to me.&#xD;&#xA;&#xD;&#xA;My first issue is how to efficiently use a lookup table across dozens or hundreds of threads in a workgroup? I understand a GPU has different kinds of memory for different tasks but not fully sure on how each operates or which type to use.&#xD;&#xA;&#xD;&#xA;Paul Bourke's classic copypasta table is a 256*16 array so if using a scalar byte type this can presumably be packed into a 4kb texture or SSBO.&#xD;&#xA;&#xD;&#xA;The question is, how to stop the different threads from tripping each other up? Many cubes in each work group can potentially have the same configuration therefore trying to access the same location in the buffer at the same time. Is there a workaround or optimization to deal with this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3089" PostHistoryTypeId="24" PostId="1662" RevisionGUID="270cc3e0-782b-4f4d-b6b8-6f957663939d" CreationDate="2015-10-28T13:29:36.397" Comment="Proposed by 385 approved by 231, 100 edit id of 70" ContentLicense="CC BY-SA 3.0" />
  <row Id="3090" PostHistoryTypeId="5" PostId="1667" RevisionGUID="9266405d-9abb-4aef-add5-1d30dea96b94" CreationDate="2015-10-28T13:37:44.837" UserId="385" Comment="Clarified cosine sampling" Text="When shading a point on an opaque surface, you need to gather incoming light and weight it with the bidirectional reflectance distribution function (BRDF) of the material.&#xD;&#xA;&#xD;&#xA;The naive approach is to distribute samples equally over the hemisphere and probe all directions equally for incoming light. This is called **uniform sampling** (Fig. 1). While this works in most cases, it can take a long time to converge towards the correct result.&#xD;&#xA;&#xD;&#xA;[![Uniform sampling on the hemisphere][1]][1]&lt;br&gt;&#xD;&#xA;**Figure 1:** Uniform sampling on the hemisphere&#xD;&#xA;&#xD;&#xA;To speed things up, let's consider the properties of the surface in question. A diffuse surface needs to take light from all directions on the hemisphere into account, where light coming from flat angles has less influence. A perfect mirror only needs a single direction according to the law of reflection. **Importance sampling** takes this into account and distributes samples where light is expected to have a greater influence, judging from the BRDF. For the diffuse surface, a cosine sampling would be used (Fig. 2), resulting in fewer samples at flat angles that presumably have a lower influence. For the perfect mirror, only a single ray is shot because all other directions have zero influence anyway.&#xD;&#xA;&#xD;&#xA;[![Cosine sampling on the hemisphere][2]][2]&lt;br&gt;&#xD;&#xA;**Figure 2:** Cosine sampling on the hemisphere&#xD;&#xA;&#xD;&#xA;Now, the BRDF is not the only thing that can be taken into account. When you have known light sources with strong intensity, it is often desirable to direct more rays towards these light sources, as these directions presumably have a greater impact on the result (i.e. there is more light coming from these directions). The idea to combine various different importance sampling strategies into one is called **multiple importance sampling**. This technique is not limited to the given example of BRDF + known lights, but can be used with any kind of sensible heuristic you can come up with.&#xD;&#xA;&#xD;&#xA;Images were generated using Holger Dammertz' [Hammersley Points on the Hemisphere][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sG2z5.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/uJksp.jpg&#xD;&#xA;  [3]: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3093" PostHistoryTypeId="5" PostId="1551" RevisionGUID="7717bea9-5d65-4de6-9044-b9e7a2bd67d1" CreationDate="2015-10-30T06:56:41.840" UserId="209" Comment="Added note on 3dfx's FXT1" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant is, naturally, noisier than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma' &#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3097" PostHistoryTypeId="2" PostId="1669" RevisionGUID="263d9aa4-0621-4ab1-9e3e-796521104f9b" CreationDate="2015-10-30T14:08:45.240" UserId="1636" Text="Why for perfect reflections a surface must have G2 continuity (class A surface)?&#xD;&#xA;&#xD;&#xA;I would like a mathematical answer." ContentLicense="CC BY-SA 3.0" />
  <row Id="3098" PostHistoryTypeId="1" PostId="1669" RevisionGUID="263d9aa4-0621-4ab1-9e3e-796521104f9b" CreationDate="2015-10-30T14:08:45.240" UserId="1636" Text="Why for perfect reflections a surface must have G2 continuity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3099" PostHistoryTypeId="3" PostId="1669" RevisionGUID="263d9aa4-0621-4ab1-9e3e-796521104f9b" CreationDate="2015-10-30T14:08:45.240" UserId="1636" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3100" PostHistoryTypeId="2" PostId="1670" RevisionGUID="cc4bb7e7-574e-4303-a9e3-65698b006de7" CreationDate="2015-10-30T20:11:09.003" UserId="1810" Text="What you see on reflects is the n-continuity of normals, which are the derivative of positions. -&gt; a G1-only surface would have G0-only normal field, i.e.,  with sudden change of gradient in the normals (and thus, the reflects), that the eyes can notice. G2 surfaces have G1 normals fields, which is smooth enough for your eyes." ContentLicense="CC BY-SA 3.0" />
  <row Id="3101" PostHistoryTypeId="2" PostId="1671" RevisionGUID="358f74f8-7d51-48a8-a647-bd142ad9486e" CreationDate="2015-10-31T06:50:49.570" UserId="1957" Text="I am pursuing my research in Texture Interpolation. After digging deep into it, I'm stuck at a point. It is proven that textures can be modeled as Markov Random Fields and that each texture can be synthesized from a collection of neighborhoods. How exactly do we get these neighborhoods that can characterize a texture and if we have them, how can we synthesize the texture back ? And, how does MRF help in any of the above ? Can anyone please provide me with a explanation that helps a layman understand concepts above ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3102" PostHistoryTypeId="1" PostId="1671" RevisionGUID="358f74f8-7d51-48a8-a647-bd142ad9486e" CreationDate="2015-10-31T06:50:49.570" UserId="1957" Text="MRF and Textures" ContentLicense="CC BY-SA 3.0" />
  <row Id="3103" PostHistoryTypeId="3" PostId="1671" RevisionGUID="358f74f8-7d51-48a8-a647-bd142ad9486e" CreationDate="2015-10-31T06:50:49.570" UserId="1957" Text="|texture|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3104" PostHistoryTypeId="2" PostId="1672" RevisionGUID="b43fcde5-f87f-4b69-8ad1-a4bf55b4ef90" CreationDate="2015-10-31T11:10:42.477" UserId="1958" Text="In Computer Animation, which algorithms are use to animate object from point A to point B given  matrix transformations that describe next position? &#xD;&#xA;&#xD;&#xA;(In 2D and 3D I think is the same except matrix dimension)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3105" PostHistoryTypeId="1" PostId="1672" RevisionGUID="b43fcde5-f87f-4b69-8ad1-a4bf55b4ef90" CreationDate="2015-10-31T11:10:42.477" UserId="1958" Text="Animation Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="3106" PostHistoryTypeId="3" PostId="1672" RevisionGUID="b43fcde5-f87f-4b69-8ad1-a4bf55b4ef90" CreationDate="2015-10-31T11:10:42.477" UserId="1958" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3107" PostHistoryTypeId="10" PostId="1672" RevisionGUID="5c21b7bb-3b47-4a0e-bcd3-17c0a7249c54" CreationDate="2015-10-31T14:54:48.140" UserId="53" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:53,&quot;DisplayName&quot;:&quot;Robert Cartaino&quot;}]}" />
  <row Id="3108" PostHistoryTypeId="5" PostId="1672" RevisionGUID="bfcf04ba-d5d1-4917-9e15-49207ebc3c49" CreationDate="2015-10-31T21:10:16.213" UserId="137" Comment="tried to make it more concrete." Text="How are objects moved smoothly from point A to point B given  matrix transformations that describe next position? " ContentLicense="CC BY-SA 3.0" />
  <row Id="3109" PostHistoryTypeId="4" PostId="1672" RevisionGUID="bfcf04ba-d5d1-4917-9e15-49207ebc3c49" CreationDate="2015-10-31T21:10:16.213" UserId="137" Comment="tried to make it more concrete." Text="How is smooth animation accomplished?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3110" PostHistoryTypeId="6" PostId="1672" RevisionGUID="bfcf04ba-d5d1-4917-9e15-49207ebc3c49" CreationDate="2015-10-31T21:10:16.213" UserId="137" Comment="tried to make it more concrete." Text="|transformations|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3111" PostHistoryTypeId="24" PostId="1672" RevisionGUID="bfcf04ba-d5d1-4917-9e15-49207ebc3c49" CreationDate="2015-10-31T21:10:16.213" Comment="Proposed by 137 approved by 231, 48 edit id of 71" ContentLicense="CC BY-SA 3.0" />
  <row Id="3113" PostHistoryTypeId="2" PostId="1673" RevisionGUID="9af92412-66f9-4cd1-a815-44b7898d6ead" CreationDate="2015-11-01T07:12:43.850" UserId="1938" Text="I had posted about this issue in a previous thread, however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (Which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly (I said **somewhat** because the output is the [following](http://imgur.com/20Wb9pQ): middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background), so long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;[My code](http://hastebin.com/samoketimo.cpp)&#xD;&#xA;&#xD;&#xA;NOTE: I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3114" PostHistoryTypeId="1" PostId="1673" RevisionGUID="9af92412-66f9-4cd1-a815-44b7898d6ead" CreationDate="2015-11-01T07:12:43.850" UserId="1938" Text="First quad being re-used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3115" PostHistoryTypeId="3" PostId="1673" RevisionGUID="9af92412-66f9-4cd1-a815-44b7898d6ead" CreationDate="2015-11-01T07:12:43.850" UserId="1938" Text="|opengl|rendering|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3117" PostHistoryTypeId="2" PostId="1674" RevisionGUID="18138f8e-4043-437c-828e-29b1d62805f7" CreationDate="2015-11-01T12:56:51.173" UserId="38" Text="* G0 Continuity means that the separate surfaces meet,&#xD;&#xA;* G1 Continuity that the surfaces meet at same angle,&#xD;&#xA;* G2 Continuity means that the change in angle matches in point of contact.&#xD;&#xA;&#xD;&#xA;The G2 requirement does not mean that the surface is good quality. Just means that without this the surface is not going to have a continuous reflection flow so humans can see the difference. That may or may not be a good thing depends on what you want.&#xD;&#xA;&#xD;&#xA;Mathematically the surface normal is:&#xD;&#xA;&#xD;&#xA;&amp;#8706;f(u,v)/&amp;#8706;u &amp;#10060; &amp;#8706;f(u,v)/&amp;#8706;v&#xD;&#xA;&#xD;&#xA;Since both sides are derived that means that the function field of the surface normal has on degree less than the original surface. So for the reflection to be first degree continuous it has to have a second degree continuity.&#xD;&#xA;&#xD;&#xA;So far we have established the relationship between the continuity of the surface and the continuity of the reflection. Nothing thus far proves that the surface needs to be first degree continuous. To understand why we must exit the realm of mathematics and enter the realm of biology.&#xD;&#xA;&#xD;&#xA;They eye is equipped with a edge detection algorithm on a structural level right on the retina. This edge detection algorithm in essence works as a discrete derivative of the input signal. So, if your surface is not G2 continuous then the human edge detection kicks in and shows itself up. For references read on [Mach Bands](https://en.wikipedia.org/wiki/Mach_bands) and so forth.&#xD;&#xA;&#xD;&#xA;Since the edge detection is discrete G2 continuity is not enough. The change has to not only be locally satisfied but also satisfied on the retina. So the change should still be shallow enough not to cause problems." ContentLicense="CC BY-SA 3.0" />
  <row Id="3118" PostHistoryTypeId="5" PostId="1674" RevisionGUID="74faec28-0ad9-47f8-ae31-328195215121" CreationDate="2015-11-01T13:54:46.360" UserId="38" Comment="added 11 characters in body" Text="* G0 Continuity means that the separate surfaces meet,&#xD;&#xA;* G1 Continuity that the surfaces meet at same angle,&#xD;&#xA;* G2 Continuity means that the change in angle matches in point of contact.&#xD;&#xA;&#xD;&#xA;The G2 requirement does not mean that the surface is good quality. Just means that without this the surface is not going to have a continuous reflection flow so humans can see the difference. That may or may not be a good thing depends on what you want.&#xD;&#xA;&#xD;&#xA;Mathematically the surface normal is:&#xD;&#xA;&#xD;&#xA;&amp;#8706;f(u,v)/&amp;#8706;u &amp;#10060; &amp;#8706;f(u,v)/&amp;#8706;v&#xD;&#xA;&#xD;&#xA;Since both sides are derived that means that the function field of the surface normal has on degree less than the original surface. So for the reflection to be first degree continuous it has to have a second degree continuity.&#xD;&#xA;&#xD;&#xA;So far we have established the relationship between the continuity of the surface and the continuity of the reflection. Nothing thus far proves that the surface reflection needs to be first degree continuous. To understand why we must exit the realm of mathematics and enter the realm of biology.&#xD;&#xA;&#xD;&#xA;They eye is equipped with a edge detection algorithm on a structural level right on the retina. This edge detection algorithm in essence works as a discrete derivative of the input signal. So, if your surface is not G2 continuous then the human edge detection kicks in and shows itself up. For references read on [Mach Bands](https://en.wikipedia.org/wiki/Mach_bands) and so forth.&#xD;&#xA;&#xD;&#xA;Since the edge detection is discrete G2 continuity is not enough. The change has to not only be locally satisfied but also satisfied on the retina. So the change should still be shallow enough not to cause problems." ContentLicense="CC BY-SA 3.0" />
  <row Id="3119" PostHistoryTypeId="5" PostId="1673" RevisionGUID="f1dcd406-2a77-4e48-b54b-f415b0f23e55" CreationDate="2015-11-01T14:22:31.773" UserId="127" Comment="Edited in image, code and link to the previous question" Text="I had posted about this issue in a [previous question](http://computergraphics.stackexchange.com/questions/1663/incorrect-instanced-rendering), however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly. I said **somewhat** because the output is the following: &#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched and the last one's UV coords are wrong][1]][1]&#xD;&#xA;&#xD;&#xA;The middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background. So long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // VAO definition&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /*** VBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;VBO);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** Vertex Format ***/&#xD;&#xA;        //Position Vertex&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;        //Normal Vertex&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3)));&#xD;&#xA;        //Texture Coordinate Vertex&#xD;&#xA;        glEnableVertexAttribArray(2);&#xD;&#xA;        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3) * 2));&#xD;&#xA;    /*** EBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;EBO);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** SSBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;SSBO);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Quad adding function&#xD;&#xA;    auto iter = std::find(quads.begin(), quads.end(), quad);&#xD;&#xA;&#xD;&#xA;    if(iter == quads.end())&#xD;&#xA;    {&#xD;&#xA;        quads.push_back(quad);&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;            vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;&#xD;&#xA;        GLuint start = (indices.empty()) ? 0 : indices[indices.size() - 1] + 1;&#xD;&#xA;&#xD;&#xA;        GLuint newIndices[] = {&#xD;&#xA;            start, start + 1, start + 2,&#xD;&#xA;            start, start + 2, start + 3&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;            indices.push_back(newIndices[i]);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;        instanceData.push_back(quad-&gt;data);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, SSBO, 0, sizeof(RenderingData) * quads.size());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    program-&gt;Use();&#xD;&#xA;&#xD;&#xA;    program-&gt;SetStorageBlock(&quot;RenderingData&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY, texture-&gt;GetTexture());&#xD;&#xA;    program-&gt;SetInteger(&quot;diffuseTextureArray&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;NOTE: I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ULWbw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3120" PostHistoryTypeId="24" PostId="1673" RevisionGUID="f1dcd406-2a77-4e48-b54b-f415b0f23e55" CreationDate="2015-11-01T14:22:31.773" Comment="Proposed by 127 approved by -1 edit id of 73" ContentLicense="CC BY-SA 3.0" />
  <row Id="3121" PostHistoryTypeId="5" PostId="1673" RevisionGUID="a1564abb-322f-41ad-b823-325ca42faf70" CreationDate="2015-11-01T14:22:31.773" UserId="231" Comment="Edited in image, code and link to the previous question" Text="I had posted about this issue in a [previous question](http://computergraphics.stackexchange.com/questions/1663/incorrect-instanced-rendering), however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly. I said **somewhat** because the output is the following: &#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched and the last one's UV coords are wrong][1]][1]&#xD;&#xA;&#xD;&#xA;The middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background. So long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;[My code](http://hastebin.com/samoketimo.cpp)&#xD;&#xA;&#xD;&#xA;NOTE: I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ULWbw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3122" PostHistoryTypeId="5" PostId="1663" RevisionGUID="87760668-2155-4358-99ce-5b2355b6b0ee" CreationDate="2015-11-01T14:29:34.893" UserId="127" Comment="Embedded the images into the question, edited capitalization" Text="Previously, to render a bunch of quads, I was simply using a few uniforms (one for a model matrix and another for the texture layer ID). However, I'd rather not have to loop through each quad and set both uniforms each time, each frame.&#xD;&#xA;&#xD;&#xA;So I went ahead and looked for better alternatives with which I could render everything with a single call. Now I'm using instanced rendering:&#xD;&#xA;&#xD;&#xA;    // In VAO definition            &#xD;&#xA;    glGenBuffers(1, &amp;instanceVBO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    glEnableVertexAttribArray(3);&#xD;&#xA;    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), nullptr);&#xD;&#xA;    glVertexAttribDivisor(3, 1);&#xD;&#xA;    glEnableVertexAttribArray(4);&#xD;&#xA;    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4)));&#xD;&#xA;    glVertexAttribDivisor(4, 1);&#xD;&#xA;    glEnableVertexAttribArray(5);&#xD;&#xA;    glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 2));&#xD;&#xA;    glVertexAttribDivisor(5, 1);&#xD;&#xA;    glEnableVertexAttribArray(6);&#xD;&#xA;    glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(RenderingData), (GLvoid*)(sizeof(glm::vec4) * 3));&#xD;&#xA;    glVertexAttribDivisor(6, 1);&#xD;&#xA;    glEnableVertexAttribArray(7);&#xD;&#xA;    glVertexAttribIPointer(7, 1, GL_UNSIGNED_INT, sizeof(RenderingData), (GLvoid*)(sizeof(glm::mat4)));&#xD;&#xA;    glVertexAttribDivisor(7, 1);&#xD;&#xA;&#xD;&#xA;    // In quad adding function&#xD;&#xA;    instanceData.push_back(quad-&gt;data);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;I'm using 2 VBOs: one for per-vertex data (position, normal, etc vectors) and another for per-instance data (model matrix and texture layer ID).&#xD;&#xA;&#xD;&#xA;My problem is the following:&#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched, whereas bottom one's UV are incorrect, since they aren't filling the whole quad][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the middle and bottom images aren't rendering correctly (middle one is way too stretched, whereas bottom one's UV are incorrect, since they aren't filling the whole quad), however, I'm 98% sure both my vertex and instance data are correct, since when I was using the previously mentioned uniforms, they were rendering correctly.&#xD;&#xA;&#xD;&#xA;Also, I ***might*** 've spotted the problem: the indices. Somehow, if I change my `glDrawElementsInstanced`'s count value to say, 12 indices, the middle one renders correctly, whereas the other 2, do not (see picture below). Same thing happens if I change them to 18 (the last one renders correctly and the other 2, do not).&#xD;&#xA;&#xD;&#xA;[![middle one renders correctly, whereas the other 2, do not][2]][2]&#xD;&#xA;&#xD;&#xA;What might the problem be?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9UAOQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2QSBs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3123" PostHistoryTypeId="24" PostId="1663" RevisionGUID="87760668-2155-4358-99ce-5b2355b6b0ee" CreationDate="2015-11-01T14:29:34.893" Comment="Proposed by 127 approved by 1938 edit id of 72" ContentLicense="CC BY-SA 3.0" />
  <row Id="3124" PostHistoryTypeId="8" PostId="1673" RevisionGUID="bc88e60b-567f-402b-beac-9d5225050f90" CreationDate="2015-11-01T14:30:46.627" UserId="1938" Comment="Rollback to [f1dcd406-2a77-4e48-b54b-f415b0f23e55]" Text="I had posted about this issue in a [previous question](http://computergraphics.stackexchange.com/questions/1663/incorrect-instanced-rendering), however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly. I said **somewhat** because the output is the following: &#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched and the last one's UV coords are wrong][1]][1]&#xD;&#xA;&#xD;&#xA;The middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background. So long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // VAO definition&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /*** VBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;VBO);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** Vertex Format ***/&#xD;&#xA;        //Position Vertex&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;        //Normal Vertex&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3)));&#xD;&#xA;        //Texture Coordinate Vertex&#xD;&#xA;        glEnableVertexAttribArray(2);&#xD;&#xA;        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3) * 2));&#xD;&#xA;    /*** EBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;EBO);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** SSBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;SSBO);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Quad adding function&#xD;&#xA;    auto iter = std::find(quads.begin(), quads.end(), quad);&#xD;&#xA;&#xD;&#xA;    if(iter == quads.end())&#xD;&#xA;    {&#xD;&#xA;        quads.push_back(quad);&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;            vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;&#xD;&#xA;        GLuint start = (indices.empty()) ? 0 : indices[indices.size() - 1] + 1;&#xD;&#xA;&#xD;&#xA;        GLuint newIndices[] = {&#xD;&#xA;            start, start + 1, start + 2,&#xD;&#xA;            start, start + 2, start + 3&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;            indices.push_back(newIndices[i]);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;        instanceData.push_back(quad-&gt;data);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, SSBO, 0, sizeof(RenderingData) * quads.size());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    program-&gt;Use();&#xD;&#xA;&#xD;&#xA;    program-&gt;SetStorageBlock(&quot;RenderingData&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY, texture-&gt;GetTexture());&#xD;&#xA;    program-&gt;SetInteger(&quot;diffuseTextureArray&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;NOTE: I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ULWbw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3125" PostHistoryTypeId="2" PostId="1675" RevisionGUID="84c1cb73-3d3e-4c51-9074-c14f28b29da7" CreationDate="2015-11-02T11:05:12.347" UserId="1970" Text="I am very eager to know what technology might been used to implement this piece of wonder:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MFCAK.gif&#xD;&#xA;&#xD;&#xA;Any idea?&#xD;&#xA;&#xD;&#xA;I think, it's ray tracing. What do you think?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3126" PostHistoryTypeId="1" PostId="1675" RevisionGUID="84c1cb73-3d3e-4c51-9074-c14f28b29da7" CreationDate="2015-11-02T11:05:12.347" UserId="1970" Text="How to design something like this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3127" PostHistoryTypeId="3" PostId="1675" RevisionGUID="84c1cb73-3d3e-4c51-9074-c14f28b29da7" CreationDate="2015-11-02T11:05:12.347" UserId="1970" Text="|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3131" PostHistoryTypeId="5" PostId="1673" RevisionGUID="0dfd7908-ef94-489d-a90b-26c481bb6f77" CreationDate="2015-11-02T16:30:19.460" UserId="1938" Comment="added 9956 characters in body" Text="I had posted about this issue in a [previous question](http://computergraphics.stackexchange.com/questions/1663/incorrect-instanced-rendering), however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly. I said **somewhat** because the output is the following: &#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched and the last one's UV coords are wrong][1]][1]&#xD;&#xA;&#xD;&#xA;The middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background. So long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // VAO definition&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /*** VBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;VBO);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** Vertex Format ***/&#xD;&#xA;        //Position Vertex&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;        //Normal Vertex&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3)));&#xD;&#xA;        //Texture Coordinate Vertex&#xD;&#xA;        glEnableVertexAttribArray(2);&#xD;&#xA;        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3) * 2));&#xD;&#xA;    /*** EBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;EBO);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** SSBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;SSBO);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Quad adding function&#xD;&#xA;    auto iter = std::find(quads.begin(), quads.end(), quad);&#xD;&#xA;&#xD;&#xA;    if(iter == quads.end())&#xD;&#xA;    {&#xD;&#xA;        quads.push_back(quad);&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;            vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;&#xD;&#xA;        GLuint start = (indices.empty()) ? 0 : indices[indices.size() - 1] + 1;&#xD;&#xA;&#xD;&#xA;        GLuint newIndices[] = {&#xD;&#xA;            start, start + 1, start + 2,&#xD;&#xA;            start, start + 2, start + 3&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;            indices.push_back(newIndices[i]);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;        instanceData.push_back(quad-&gt;data);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, SSBO, 0, sizeof(RenderingData) * quads.size());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    program-&gt;Use();&#xD;&#xA;&#xD;&#xA;    program-&gt;SetStorageBlock(&quot;RenderingData&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY, texture-&gt;GetTexture());&#xD;&#xA;    program-&gt;SetInteger(&quot;diffuseTextureArray&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;NOTE: I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?&#xD;&#xA;&#xD;&#xA;EDIT: I made a sample code which replicates the problem; it should render a green quad and a red quad, however, it just renders 2 red quads. Also, even if you try to change the second quads' attributes (even like placing all 0s), it'll still just render. Somehow only the first quads' vertices are getting read and used for each subsequent quad.&#xD;&#xA;&#xD;&#xA;**C++ code:**&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    #include &lt;string&gt;&#xD;&#xA;    #include &lt;sstream&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #define GLEW_STATIC&#xD;&#xA;    #include &quot;GL/glew.h&quot;&#xD;&#xA;    #include &quot;GLFW/glfw3.h&quot;&#xD;&#xA;    #include &lt;IL/il.h&gt;&#xD;&#xA;    #include &lt;IL/ilu.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;&#xD;&#xA;    struct Vertex{&#xD;&#xA;        glm::vec2 pos, tex;&#xD;&#xA;        glm::vec3 color;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Quad{&#xD;&#xA;        std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;        glm::mat4 model;&#xD;&#xA;    &#xD;&#xA;        Quad(glm::vec2 pos, glm::vec2 size, const std::vector&lt;Vertex&gt; &amp;v){&#xD;&#xA;            vertices = v;&#xD;&#xA;            model = glm::mat4();&#xD;&#xA;            model = glm::translate(model, glm::vec3(pos, 0.f));&#xD;&#xA;            model = glm::scale(model, glm::vec3(size, 1.f));&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    class Renderer{&#xD;&#xA;        private:&#xD;&#xA;            GLuint VAO, VBO, instanceVBO, EBO;&#xD;&#xA;            std::vector&lt;Quad*&gt; quads;&#xD;&#xA;            std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;            std::vector&lt;glm::mat4&gt; models;&#xD;&#xA;            std::vector&lt;GLuint&gt; indices;&#xD;&#xA;    &#xD;&#xA;        public:&#xD;&#xA;            Renderer(){&#xD;&#xA;                /*** VAO ***/&#xD;&#xA;                glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;                glBindVertexArray(VAO);&#xD;&#xA;                /*** Per-vertex VBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;VBO);&#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;                glEnableVertexAttribArray(0);   // Position&#xD;&#xA;                glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;                glEnableVertexAttribArray(1);   // Tex Coord&#xD;&#xA;                glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec2)));&#xD;&#xA;                glEnableVertexAttribArray(2);   // Color&#xD;&#xA;                glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec2) * 2));&#xD;&#xA;                /*** Per-instance VBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;instanceVBO);&#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;                glEnableVertexAttribArray(3);   // Model matrix - row1&#xD;&#xA;                glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), nullptr);&#xD;&#xA;                glVertexAttribDivisor(3, 1);&#xD;&#xA;                glEnableVertexAttribArray(4);   // Model matrix - row2&#xD;&#xA;                glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4)));&#xD;&#xA;                glVertexAttribDivisor(4, 1);&#xD;&#xA;                glEnableVertexAttribArray(5);   // Model matrix - row3&#xD;&#xA;                glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * 2));&#xD;&#xA;                glVertexAttribDivisor(5, 1);&#xD;&#xA;                glEnableVertexAttribArray(6);   // Model matrix - row4&#xD;&#xA;                glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * 3));&#xD;&#xA;                glVertexAttribDivisor(6, 1);&#xD;&#xA;                /*** EBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;EBO);&#xD;&#xA;                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;                glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;            }&#xD;&#xA;            ~Renderer(){&#xD;&#xA;                glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;                glDeleteBuffers(1, &amp;instanceVBO);&#xD;&#xA;                glDeleteBuffers(1, &amp;EBO);&#xD;&#xA;                glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;            }&#xD;&#xA;            void AddQuad(Quad *const quad){&#xD;&#xA;                quads.push_back(quad);&#xD;&#xA;    &#xD;&#xA;                for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;                    vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;    &#xD;&#xA;                models.push_back(quad-&gt;model);&#xD;&#xA;    &#xD;&#xA;                GLuint start = ((indices.empty()) ? 0 : indices[indices.size() - 1] + 1);&#xD;&#xA;    &#xD;&#xA;                GLuint newIndices[] = {&#xD;&#xA;                    start,  start + 1,  start + 2,&#xD;&#xA;                    start,  start + 3,  start + 2&#xD;&#xA;                };&#xD;&#xA;&#xD;&#xA;                for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;                    indices.push_back(newIndices[i]);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * quads.size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;            }&#xD;&#xA;            void Render(GLuint &amp;program){&#xD;&#xA;                glUseProgram(program);&#xD;&#xA;    &#xD;&#xA;                glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;            }&#xD;&#xA;            void CheckQuads(){&#xD;&#xA;                for(unsigned int i = 0; i &lt; quads.size(); i++)&#xD;&#xA;                {&#xD;&#xA;                    std::cout &lt;&lt; &quot;Quad n.&quot; &lt;&lt; i &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                    for(unsigned int j = 0; j &lt; 4; j++)&#xD;&#xA;                    {&#xD;&#xA;                        std::cout &lt;&lt; &quot;\tVert &quot; &lt;&lt; j &lt;&lt; &quot;:\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].pos.x &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].pos.y &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].tex.x &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].tex.y &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].color.r &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].color.g &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].color.b &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    GLuint GenerateShader(const std::string &amp;filename, GLenum shaderType)&#xD;&#xA;    {&#xD;&#xA;        GLuint shader;&#xD;&#xA;        std::ifstream file(filename.c_str());&#xD;&#xA;        std::stringstream ss;&#xD;&#xA;        ss &lt;&lt; file.rdbuf();&#xD;&#xA;        file.close();&#xD;&#xA;        const GLchar *source = ss.str().c_str();&#xD;&#xA;        shader = glCreateShader(shaderType);&#xD;&#xA;        glShaderSource(shader, 1, &amp;source, nullptr);&#xD;&#xA;        glCompileShader(shader);&#xD;&#xA;        return shader;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        /*** Window + Context ***/&#xD;&#xA;        glfwInit();&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;        GLFWwindow *window = glfwCreateWindow(640, 480, &quot;OpenGL Incorrect Rendering Test&quot;, nullptr, nullptr);&#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;        glewExperimental = GL_TRUE;&#xD;&#xA;        glewInit();&#xD;&#xA;        glViewport(0, 0, 640, 480);&#xD;&#xA;        glClearColor(0.f, 0.f, 0.f, 1.f);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projection = glm::ortho(0.f, 640.f, 480.f, 0.f, -1.f, 1.f);&#xD;&#xA;    &#xD;&#xA;        /*** Shader Program ***/&#xD;&#xA;        GLuint program = glCreateProgram();&#xD;&#xA;        glAttachShader(program, GenerateShader(&quot;vertex_shader.glsl&quot;, GL_VERTEX_SHADER));&#xD;&#xA;        glAttachShader(program, GenerateShader(&quot;fragment_shader.glsl&quot;, GL_FRAGMENT_SHADER));&#xD;&#xA;        glLinkProgram(program);&#xD;&#xA;    &#xD;&#xA;        glUseProgram(program);&#xD;&#xA;        glUniformMatrix4fv(glGetUniformLocation(program, &quot;projection&quot;), 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;        /*** Renderer ***/&#xD;&#xA;        Renderer *renderer = new Renderer();&#xD;&#xA;        // Quad 1&#xD;&#xA;        Vertex v1 = {glm::vec2(0.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v2 = {glm::vec2(1.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v3 = {glm::vec2(1.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v4 = {glm::vec2(0.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        renderer-&gt;AddQuad(new Quad(glm::vec2(300, 10), glm::vec2(150, 150), {v1, v2, v3, v4}));&#xD;&#xA;        // Quad 2&#xD;&#xA;        Vertex v5 = {glm::vec2(0.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v6 = {glm::vec2(1.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v7 = {glm::vec2(1.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v8 = {glm::vec2(0.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        renderer-&gt;AddQuad(new Quad(glm::vec2(30, 10), glm::vec2(150, 150), {v5, v6, v7, v8}));&#xD;&#xA;&#xD;&#xA;        while(!glfwWindowShouldClose(window))&#xD;&#xA;        {&#xD;&#xA;            glfwPollEvents();&#xD;&#xA;    &#xD;&#xA;            if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;                glfwSetWindowShouldClose(window, true);&#xD;&#xA;    &#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;            renderer-&gt;Render(program);&#xD;&#xA;    &#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        delete renderer;&#xD;&#xA;    &#xD;&#xA;        glfwDestroyWindow(window);&#xD;&#xA;        glfwTerminate();&#xD;&#xA;    &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**vertex_shader.glsl:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    layout (location = 0) in vec2 position;&#xD;&#xA;    layout (location = 1) in vec2 texCoord;&#xD;&#xA;    layout (location = 2) in vec3 color;&#xD;&#xA;    layout (location = 3) in mat4 model;&#xD;&#xA;    &#xD;&#xA;    out vec2 uv;&#xD;&#xA;    out vec3 col;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uv = texCoord;&#xD;&#xA;        col = color;&#xD;&#xA;    &#xD;&#xA;        gl_Position = projection * model * vec4(position, 0.f, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**fragment_shader.glsl:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    in vec2 uv;&#xD;&#xA;    in vec3 col;&#xD;&#xA;    out vec4 color;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        color = vec4(col, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ULWbw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3138" PostHistoryTypeId="2" PostId="1678" RevisionGUID="09398c5d-78d7-4946-9ee6-d3a6ee0c1752" CreationDate="2015-11-03T02:18:02.977" UserId="56" Text="It does look like raytracing to me as well.  It could also possibly be ray marching, which would be easier to make the tubes with since ray marching is all based on distances from things (center of tube in this case).&#xA;&#xA;Refraction is what's used to bend the light that goes through the tubes.&#xA;&#xA;You are then just left with how to model the tubes. One way could be to use 3d bezier curves (: &#xA;&#xA;This may not have been made in real time, but may have been rendered frame by frame and then assembled into the smooth &quot;movie&quot; you are showing." ContentLicense="CC BY-SA 3.0" />
  <row Id="3140" PostHistoryTypeId="2" PostId="1679" RevisionGUID="24acba07-38dc-4ba1-ab37-fc44169e065d" CreationDate="2015-11-03T03:12:17.680" UserId="56" Text="You might want to look into signed distance field textures.  They are very efficient and high quality for monochromatic images like shadows.  They work by storing a clamped, signed distance from the pixel to the shape.  Working this way, the distances play nicely with the bilinear interpolation of texture sampling, so you can have very nice results for very low resolution.  You can also give them a soft edge to have a soft shadow look." ContentLicense="CC BY-SA 3.0" />
  <row Id="3144" PostHistoryTypeId="10" PostId="1675" RevisionGUID="8416874b-2a4b-422b-af83-b22c2c71763a" CreationDate="2015-11-03T08:57:47.263" UserId="16" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="3145" PostHistoryTypeId="2" PostId="1680" RevisionGUID="55b31f3e-1542-409d-82a4-e7017b260a1e" CreationDate="2015-11-03T09:05:16.970" UserId="1938" Text="Seems like I had misunderstood instancing, that's why my code was acting strange: I was trying to use instancing while also trying to render different quads using different vertex data.&#xD;&#xA;&#xD;&#xA;How do I close / mark as answered the question?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3146" PostHistoryTypeId="5" PostId="1680" RevisionGUID="91130580-42d3-4319-b6b8-e87712a60c0f" CreationDate="2015-11-03T10:01:38.730" UserId="1938" Comment="deleted 51 characters in body" Text="Seems like I had misunderstood instancing, that's why my code was acting strange: I was trying to use instancing while also trying to render different quads using different vertex data." ContentLicense="CC BY-SA 3.0" />
  <row Id="3147" PostHistoryTypeId="5" PostId="72" RevisionGUID="bc023295-2500-4708-90b5-597a8589bc9c" CreationDate="2015-11-03T12:45:56.093" UserId="16" Comment="mathjax" Text="Yes, while many screens and OS operations are using a gamma of 2.2 your hardware and computation result still need to be corrected. There are also special mediums such as broadcast TV's that have a different gamma. Sensor equipment like cameras are mostly linear so they need to be adjusted accordingly. Besides this the user can set their system to whatever gamma they like. &#xD;&#xA;&#xD;&#xA;In computer graphics primary reason to account for gamma is that your computation is most likely done in linear space\* or summing light contributions becomes unnecessarily complicated. In any case gamma is really a simplification of things, you'd be much much better of doing profile to profile conversions if its possible to invest the computational time to do so.&#xD;&#xA;&#xD;&#xA;## Mathematical explanation&#xD;&#xA;&#xD;&#xA;This may be a simpler to understand. Your monitor has a display error of $g(x)$ which is no problem if your data is conforming to $g(x)$, however if you want to calculate:&#xD;&#xA;&#xD;&#xA;$$ a+b+c+d $$&#xD;&#xA;&#xD;&#xA;and $a$, $b$, $c$, $d$, have the error of $g(x)$ you would actually need to calculate.&#xD;&#xA;&#xD;&#xA;$$ g(g^{-1}(a)+g^{-1}(b)+g^{-1}(c)+g^{-1}(d)) $$&#xD;&#xA;&#xD;&#xA;You would need to do this for each sub element over and over again. Therefore instead of running the transform each time you transform all once to linear and then once back. &#xD;&#xA;&#xD;&#xA;## And finally a artistic reason&#xD;&#xA;&#xD;&#xA;It may just look better with a different gamma. Many games have a gamma adjustment for this reason.&#xD;&#xA;&#xD;&#xA;\* Worst case is that you think your computations as linear but do not compensate for the monitors nonlinear output charachteristics." ContentLicense="CC BY-SA 3.0" />
  <row Id="3148" PostHistoryTypeId="5" PostId="1607" RevisionGUID="710b05b5-01a6-4598-89d5-1ffde4674f1a" CreationDate="2015-11-03T12:54:16.087" UserId="137" Comment="added 68 characters in body" Text="The hint is to use the perspective divide inherent in homegeneous coordinate. So the resulting point you are looking for is $(2, (5y+z)/2, 3x+3y, x+y)$&#xD;&#xA;&#xD;&#xA;That matrix then ends up as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    0 &amp;  0 &amp;  0 &amp;  2  \\&#xD;&#xA;    0 &amp;  2.5&amp; 0.5&amp; 0  \\&#xD;&#xA;    3 &amp;  3 &amp;  0 &amp;  0  \\&#xD;&#xA;    1 &amp;  1 &amp;  0 &amp;  0  \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="3149" PostHistoryTypeId="5" PostId="1606" RevisionGUID="25c46c5e-5f4a-4e0c-8eca-5634d3f7bce3" CreationDate="2015-11-03T12:56:46.733" UserId="16" Comment="added 15 characters in body" Text="I have the following problem:&#xD;&#xA;&#xD;&#xA;Give a matrix that will transform the point $(x,y,z)$ into the point $(\frac{2}{x+y}, \frac{5y + z}{2x + 2y}, 3)$.&#xD;&#xA;&#xD;&#xA;I have been reading my book to find a way to solve it without success. I will very much appreciate your feedback about how to solve it.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3150" PostHistoryTypeId="5" PostId="347" RevisionGUID="453ea806-7753-45c4-a101-90b65691e927" CreationDate="2015-11-03T13:11:13.553" UserId="137" Comment="mathjax it up" Text="Fourier transforms wouldn't help you with a rotation. You'd just end up having to rotate the matrix of Fourier coefficients, instead of rotating the original image.&#xD;&#xA;&#xD;&#xA;Consider for example an image made of a perfect sine wave along the x-axis with wave-vector $(k, 0)$.  (The wave-vector is the spacial frequencies along the $x$ and $y$ axes).  The Fourier transform of this would be all black, with a single white pixel at position $(k, 0)$.&#xD;&#xA;&#xD;&#xA;When you rotate the image by an angle $\theta$, you'll get a perfect sine wave along an oblique axis.  If you draw a diagram and do a little trigonometry, you can see that the new wave-vector will be $(k \cos \theta, k \sin \theta)$.  (It helps for this part to know that the frequency $k$ is one over the period.)&#xD;&#xA;&#xD;&#xA;Therefore, the Fourier transform of the rotated result would be all black, with a single white pixel at position $(k \cos \theta, k \sin \theta)$.  But that's just what you'd get if you rotated the Fourier transform of the original wave by \theta.&#xD;&#xA;&#xD;&#xA;As for the Gibbs phenomenon, it's an issue when downsampling an image, or compressing it by frequency quantization (as in JPEG). But simply taking the Fourier transform of an image doesn't introduce any Gibbs ringing. The Fourier transform is lossless and perfectly reversible if done properly: it represents all the information in the original image." ContentLicense="CC BY-SA 3.0" />
  <row Id="3151" PostHistoryTypeId="24" PostId="347" RevisionGUID="453ea806-7753-45c4-a101-90b65691e927" CreationDate="2015-11-03T13:11:13.553" Comment="Proposed by 137 approved by 231 edit id of 76" ContentLicense="CC BY-SA 3.0" />
  <row Id="3152" PostHistoryTypeId="5" PostId="1621" RevisionGUID="67041038-82dd-4745-b29e-52b0d966e0fc" CreationDate="2015-11-03T13:13:28.230" UserId="137" Comment="mathjax it up" Text="The hint with the perspective division was already [mentioned by ratchet freak](http://computergraphics.stackexchange.com/a/1607/127), but I'd like to add some explanation of how to come up with the solution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First of all, remember that homogenous coordinates add a fourth value $w$ to your 3D vector. For points in the 3D space, $w \neq 0$ holds and $[x, y, z, w] = [n*x, n*y, n*z, n*w]$ also holds for every $n$.&#xD;&#xA;&#xD;&#xA;Now the goal is to find a transformation matrix $T$, which solves&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    \begin{bmatrix} \frac{2}{x + y} \\ \frac{5(y + z)}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;= T \cdot &#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t11 &amp; t21 &amp; t31 &amp; t41  \\ t12 &amp; t22 &amp; t32 &amp; t42 \\ t13 &amp; t23 &amp; t33 &amp; t43 \\ t14 &amp; t24 &amp; t34 &amp; t44 \end{bmatrix}&#xD;&#xA;\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These are basically four equations, but having a look at the first row, being&#xD;&#xA;&#xD;&#xA;$$\frac{2}{x + y} = t11\cdot x + t21\cdot y + t31 \cdot z + t4 \cdot 1$$&#xD;&#xA;&#xD;&#xA;and trying to find values for the $t$s, you'll see that this is not possible without further restructuring. The main problems are the $x$ and $y$ in the denominator. But as we can make use of the fourth value in the vector, we can expand the $w$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{5(y + z)}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{2.5(y + z)}{x + y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the first step, I removed the factor of $2$ from the second values denominator, leading to every values denominator either being $1$ or $(x + y)$. In the second step, I made use of the above mentioned rule ($[x, y, z, w] == [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$), setting $n = (x + y)$, thus eliminating the denominator of the first two values.&#xD;&#xA;&#xD;&#xA;Now we've got&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t11 &amp; t21 &amp; t31 &amp; t41  \\ t12 &amp; t22 &amp; t32 &amp; t42 \\ t13 &amp; t23 &amp; t33 &amp; t43 \\ t14 &amp; t24 &amp; t34 &amp; t44 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which is not that hard anymore.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 0  &amp;  0 &amp;   0  &amp;  2   \\ 0 &amp;  2.5 &amp; 2.5 &amp;  0 \\ 3 &amp;   3  &amp;  0 &amp;   0 \\ 1  &amp;  1  &amp;  0  &amp;  0 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;* Remember the advantage of homogenous coordinates $w$.&#xD;&#xA;* $[x, y, z, w] == [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$ is the key.&#xD;&#xA;* Push everything that's in the denominator to the $w$ coordinate." ContentLicense="CC BY-SA 3.0" />
  <row Id="3153" PostHistoryTypeId="24" PostId="1621" RevisionGUID="67041038-82dd-4745-b29e-52b0d966e0fc" CreationDate="2015-11-03T13:13:28.230" Comment="Proposed by 137 approved by -1 edit id of 75" ContentLicense="CC BY-SA 3.0" />
  <row Id="3154" PostHistoryTypeId="5" PostId="1621" RevisionGUID="de0f8169-b35f-4e62-9cc6-7fc651196f64" CreationDate="2015-11-03T13:13:28.230" UserId="127" Comment="mathjax it up" Text="The hint with the perspective division was already [mentioned by ratchet freak](http://computergraphics.stackexchange.com/a/1607/127), but I'd like to add some explanation of how to come up with the solution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First of all, remember that homogenous coordinates add a fourth value $w$ to your 3D vector. For points in the 3D space, $w \neq 0$ holds and $[x, y, z, w] = [n*x, n*y, n*z, n*w]$ also holds for every $n$.&#xD;&#xA;&#xD;&#xA;Now the goal is to find a transformation matrix $T$, which solves&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    \begin{bmatrix} \frac{2}{x + y} \\ \frac{5(y + z)}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;= T \cdot &#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These are basically four equations, but having a look at the first row, being&#xD;&#xA;&#xD;&#xA;$$\frac{2}{x + y} = t_{11}\cdot x + t_{21}\cdot y + t_{31} \cdot z + t_{41}$$&#xD;&#xA;&#xD;&#xA;and trying to find values for the $t$s, you'll see that this is not possible without further restructuring. The main problems are the $x$ and $y$ in the denominator. But as we can make use of the fourth value in the vector, we can expand the $w$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{5(y + z)}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{2.5(y + z)}{x + y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the first step, I removed the factor of $2$ from the second values denominator, leading to every values denominator either being $1$ or $(x + y)$. In the second step, I made use of the above mentioned rule ($[x, y, z, w] == [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$), setting $n = (x + y)$, thus eliminating the denominator of the first two values.&#xD;&#xA;&#xD;&#xA;Now we've got&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which is not that hard anymore.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 0  &amp;  0 &amp;   0  &amp;  2   \\ 0 &amp;  2.5 &amp; 2.5 &amp;  0 \\ 3 &amp;   3  &amp;  0 &amp;   0 \\ 1  &amp;  1  &amp;  0  &amp;  0 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;* Remember the advantage of homogenous coordinates $w$.&#xD;&#xA;* $[x, y, z, w] == [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$ is the key.&#xD;&#xA;* Push everything that's in the denominator to the $w$ coordinate." ContentLicense="CC BY-SA 3.0" />
  <row Id="3155" PostHistoryTypeId="5" PostId="1621" RevisionGUID="2ef505c4-92e9-4abf-a343-5e3129a73cee" CreationDate="2015-11-03T13:14:42.490" UserId="16" Comment="deleted 2 characters in body" Text="The hint with the perspective division was already [mentioned by ratchet freak](http://computergraphics.stackexchange.com/a/1607/127), but I'd like to add some explanation of how to come up with the solution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First of all, remember that homogenous coordinates add a fourth value $w$ to your 3D vector. For points in the 3D space, $w \neq 0$ holds and $[x, y, z, w] = [n*x, n*y, n*z, n*w]$ also holds for every $n$.&#xD;&#xA;&#xD;&#xA;Now the goal is to find a transformation matrix $T$, which solves&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    \begin{bmatrix} \frac{2}{x + y} \\ \frac{5(y + z)}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;= T \cdot &#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These are basically four equations, but having a look at the first row, being&#xD;&#xA;&#xD;&#xA;$$\frac{2}{x + y} = t_{11}\cdot x + t_{21}\cdot y + t_{31} \cdot z + t_{41}$$&#xD;&#xA;&#xD;&#xA;and trying to find values for the $t$s, you'll see that this is not possible without further restructuring. The main problems are the $x$ and $y$ in the denominator. But as we can make use of the fourth value in the vector, we can expand the $w$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{5(y + z)}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{2.5(y + z)}{x + y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the first step, I removed the factor of $2$ from the second values denominator, leading to every values denominator either being $1$ or $(x + y)$. In the second step, I made use of the above mentioned rule ($[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$), setting $n = (x + y)$, thus eliminating the denominator of the first two values.&#xD;&#xA;&#xD;&#xA;Now we've got&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which is not that hard anymore.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5(y + z) \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 0  &amp;  0 &amp;   0  &amp;  2   \\ 0 &amp;  2.5 &amp; 2.5 &amp;  0 \\ 3 &amp;   3  &amp;  0 &amp;   0 \\ 1  &amp;  1  &amp;  0  &amp;  0 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;* Remember the advantage of homogenous coordinates $w$.&#xD;&#xA;* $[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$ is the key.&#xD;&#xA;* Push everything that's in the denominator to the $w$ coordinate." ContentLicense="CC BY-SA 3.0" />
  <row Id="3156" PostHistoryTypeId="5" PostId="1674" RevisionGUID="0b80bd03-8792-40db-922c-71773bd43a46" CreationDate="2015-11-03T13:30:51.730" UserId="38" Comment="added 9 characters in body" Text="* G0 Continuity means that the separate surfaces meet,&#xD;&#xA;* G1 Continuity that the surfaces meet at same angle,&#xD;&#xA;* G2 Continuity means that the change in angle matches in point of contact.&#xD;&#xA;&#xD;&#xA;The G2 requirement does not mean that the surface is good quality. Just means that without this the surface is not going to have a continuous reflection flow so humans can see the difference. That may or may not be a good thing depends on what you want.&#xD;&#xA;&#xD;&#xA;Mathematically the surface normal is:&#xD;&#xA;&#xD;&#xA;$f(u,v) \frac{\partial}{\partial u} \times f(u,v) \frac{\partial}{\partial v}$&#xD;&#xA;&#xD;&#xA;Since both sides are derived that means that the function field of the surface normal has on degree less than the original surface. So for the reflection to be first degree continuous it has to have a second degree continuity.&#xD;&#xA;&#xD;&#xA;So far we have established the relationship between the continuity of the surface and the continuity of the reflection. Nothing thus far proves that the surface reflection needs to be first degree continuous. To understand why we must exit the realm of mathematics and enter the realm of biology.&#xD;&#xA;&#xD;&#xA;They eye is equipped with a edge detection algorithm on a structural level right on the retina. This edge detection algorithm in essence works as a discrete derivative of the input signal. So, if your surface is not G2 continuous then the human edge detection kicks in and shows itself up. For references read on [Mach Bands](https://en.wikipedia.org/wiki/Mach_bands) and so forth.&#xD;&#xA;&#xD;&#xA;Since the edge detection is discrete G2 continuity is not enough. The change has to not only be locally satisfied but also satisfied on the retina. So the change should still be shallow enough not to cause problems." ContentLicense="CC BY-SA 3.0" />
  <row Id="3157" PostHistoryTypeId="5" PostId="118" RevisionGUID="d01fcd0f-0133-45d3-ae5e-4a0207bdc97b" CreationDate="2015-11-03T13:38:30.523" UserId="38" Comment="Matjax has landed" Text="The mathematical approach to this is to represent the other colors/light sources in terms of your standard primaries in the color space. Represent your target color and available light sources as vectors with, say, the RGB color space as the basis. Figuring out how to display your target color using your available sources then becomes a [change of basis][1], a standard linear algebra operation, where the target basis consists of your LEDs/nonstandard primaries.&#xD;&#xA;&#xD;&#xA;If the dimensions of the source and destination bases are different, the change of basis matrix won't be square and thus won't be invertible. In that case, you need to solve a system of linear equations, expressed in matrix form:&#xD;&#xA;&#xD;&#xA;$c_{RGB} = [r y b v] \times c_{RYBV}$&#xD;&#xA;&#xD;&#xA;Where `c_RGB` and `c_RYBV` are the coordinate vectors of your desired color expressed in terms of RGB and custom primaries, respectively, and `r`, `y`, `b` and `v` are your custom primaries (basis vectors) in RGB coordinates.&#xD;&#xA;&#xD;&#xA;Solving this system is another common linear algebra operation, and there are a variety of numerical and symbolical algorithms to do so. The system is over-constrained, so solutions will likely have a free variable, however since we can't physically produce negative light, nor do the primaries have infinite dynamic range, for most practical purposes each coefficient will have to be limited to be within the `[0, 1]` range. This will render many colors unrepresentable under certain sets of primaries.&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/a/340991/166490" ContentLicense="CC BY-SA 3.0" />
  <row Id="3158" PostHistoryTypeId="5" PostId="118" RevisionGUID="9d63d2a0-9b34-448f-a8b1-a3e2084b4bed" CreationDate="2015-11-03T13:53:01.553" UserId="16" Comment="more mathjax" Text="The mathematical approach to this is to represent the other colors/light sources in terms of your standard primaries in the color space. Represent your target color and available light sources as vectors with, say, the RGB color space as the basis. Figuring out how to display your target color using your available sources then becomes a [change of basis][1], a standard linear algebra operation, where the target basis consists of your LEDs/nonstandard primaries.&#xD;&#xA;&#xD;&#xA;If the dimensions of the source and destination bases are different, the change of basis matrix won't be square and thus won't be invertible. In that case, you need to solve a system of linear equations, expressed in matrix form:&#xD;&#xA;&#xD;&#xA;$$c_{RGB} = [r, y, b, v] \cdot c_{RYBV}$$&#xD;&#xA;&#xD;&#xA;Where $c_{RGB}$ and $c_{RYBV}$ are the coordinate vectors of your desired color expressed in terms of RGB and custom primaries, respectively, and $r$, $y$, $b$ and $v$ are your custom primaries (basis vectors) in RGB coordinates.&#xD;&#xA;&#xD;&#xA;Solving this system is another common linear algebra operation, and there are a variety of numerical and symbolical algorithms to do so. The system is over-constrained, so solutions will likely have a free variable, however since we can't physically produce negative light, nor do the primaries have infinite dynamic range, for most practical purposes each coefficient will have to be limited to be within the $[0, 1]$ range. This will render many colors unrepresentable under certain sets of primaries.&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/a/340991/166490" ContentLicense="CC BY-SA 3.0" />
  <row Id="3159" PostHistoryTypeId="5" PostId="392" RevisionGUID="738d184a-b64e-4a41-af83-f50d4ed3bff6" CreationDate="2015-11-03T13:55:53.667" UserId="137" Comment="mathjax it up" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b \\ c&amp;d\end{bmatrix}&#xD;&#xA;+&#xD;&#xA;\begin{bmatrix}e&amp; f\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair $(x', y')$ from the original pair $(x, y)$ and a list of constants $(a, b, c, d, e, f)$.&#xD;&#xA;$$&#xD;&#xA;    x' =  a\cdot x + c\cdot y + e \\&#xD;&#xA;    y' =  b\cdot x + d\cdot y + f&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'&amp;1\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}x''&amp; y''&amp;1\end{bmatrix}&#xD;&#xA;&amp; = &amp;&#xD;&#xA;(&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix})&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}a \cdot x + c \cdot y+e &amp; b \cdot x + d \cdot y+f &amp;1 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}g(a \cdot x + c \cdot y+e) + i( b \cdot x + d \cdot y+f) + k &#xD;&#xA;\\&#xD;&#xA;h(a \cdot x + c \cdot y+e) + j( b \cdot x + d \cdot y+f) + m&#xD;&#xA;\\1 \end{bmatrix}^T&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;(&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;)&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\begin{bmatrix}ag+bi&amp; ah+bj &amp;0\\ cg+di&amp;ch+dj&amp;0 \\ eg+fi+k&amp;eh+fj+m&amp;1\end{bmatrix}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    S_x &amp; 0 &amp; 0 \\&#xD;&#xA;    0  &amp; S_y &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    T_x &amp; T_y &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    Q_y &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    \cos\theta &amp; -sin\theta &amp; 0\\&#xD;&#xA;    \sin\theta &amp; \cos\theta &amp; 0\\&#xD;&#xA;    0  &amp;  0 &amp;  1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;A matrix composed purely from scaling, rotation, and translation can be [decomposed back into these three components](http://stackoverflow.com/a/11942636/733077).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3160" PostHistoryTypeId="24" PostId="392" RevisionGUID="738d184a-b64e-4a41-af83-f50d4ed3bff6" CreationDate="2015-11-03T13:55:53.667" Comment="Proposed by 137 approved by -1 edit id of 79" ContentLicense="CC BY-SA 3.0" />
  <row Id="3161" PostHistoryTypeId="5" PostId="392" RevisionGUID="07cec362-3b4b-427b-8a7d-7bfe8b1ef849" CreationDate="2015-11-03T13:55:53.667" UserId="16" Comment="mathjax it up" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b \\ c&amp;d\end{bmatrix}&#xD;&#xA;+&#xD;&#xA;\begin{bmatrix}e&amp; f\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair $(x', y')$ from the original pair $(x, y)$ and a list of constants $(a, b, c, d, e, f)$.&#xD;&#xA;$$&#xD;&#xA;    x' =  a\cdot x + c\cdot y + e \\&#xD;&#xA;    y' =  b\cdot x + d\cdot y + f&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'&amp;1\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}x''&amp; y''&amp;1\end{bmatrix}&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}\right)&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}a \cdot x + c \cdot y+e &amp; b \cdot x + d \cdot y+f &amp;1 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}g(a \cdot x + c \cdot y+e) + i( b \cdot x + d \cdot y+f) + k &#xD;&#xA;\\&#xD;&#xA;h(a \cdot x + c \cdot y+e) + j( b \cdot x + d \cdot y+f) + m&#xD;&#xA;\\1 \end{bmatrix}^T&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\right)&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\begin{bmatrix}ag+bi&amp; ah+bj &amp;0\\ cg+di&amp;ch+dj&amp;0 \\ eg+fi+k&amp;eh+fj+m&amp;1\end{bmatrix}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    S_x &amp; 0 &amp; 0 \\&#xD;&#xA;    0  &amp; S_y &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    T_x &amp; T_y &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    Q_y &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    \cos\theta &amp; -sin\theta &amp; 0\\&#xD;&#xA;    \sin\theta &amp; \cos\theta &amp; 0\\&#xD;&#xA;    0  &amp;  0 &amp;  1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;A matrix composed purely from scaling, rotation, and translation can be [decomposed back into these three components](http://stackoverflow.com/a/11942636/733077).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3162" PostHistoryTypeId="5" PostId="236" RevisionGUID="6541df46-9e24-4d03-8575-7ac6500c7417" CreationDate="2015-11-03T13:56:14.140" UserId="137" Comment="mathjax it up" Text="Overview&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;The appearance of volumes (also called participating media) in nature is caused by tiny particles, such as dust, water droplets or plankton, that are suspended in the surrounding fluid, such as air or water. These particles are solid objects, and light refracts or reflects off of these objects as it would on a normal surface. In theory, participating media could therefore be handled by a traditional ray tracer with only surface intersections.&#xD;&#xA;&#xD;&#xA;Statistical Model&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;Of course, the _sheer number_ of these particles makes it infeasible to actually raytrace them individually. Instead, they are approximated with a statistical model: Because the particles are very small, and the distance between the particles is much larger than the particle size, individual interactions of light with the particles can be modeled as statistically independent. Therefore, it is a reasonable approximation to replace the individual particles with continuous quantities that describe the &quot;average&quot; light-particle interaction at that certain region in space.&#xD;&#xA;&#xD;&#xA;For physically based volumetric light transport, we replace the inconceivably many particles with a continuous participating medium that has two properties: The absorption coefficient, and the scattering coefficient. These coefficients are very convenient for ray tracing, as they allow us to compute the probability of a ray interacting with the medium - that is, the probability of striking one of the particles - as a function of distance.&#xD;&#xA;&#xD;&#xA;The absorption coefficient is denoted $\sigma_a$. Say a ray of light wants to travel $t$ meters inside the participating medium; the probability of making it through unabsorbed -- i.e. not hitting one of the particles and being absorbed by it -- is $e^{-t\cdot\sigma_a}$`. As t increases, we can see that this probability goes to zero, that is, the longer we travel through the medium, the more likely it is to hit something and be absorbed. Very similar things hold for the scattering coefficient $\sigma_s$: The probability of the ray not hitting a particle and being scattered is $e^{-t\cdot\sigma_s}$; that is, the longer we travel through a medium, the more likely it is that we hit a particle and are scattered into a different direction.&#xD;&#xA;&#xD;&#xA;Usually, these two quantities are folded into a single extinction coefficient, $\sigma_t = \sigma_a + \sigma_s$. The probability of traveling $t$ meters through a medium without interacting with it (neither being absorbed or scattered) is then $e^{-t\cdot\sigma_t}$. On the other hand, the probability of interacting with a medium after $t$ meters is $1 - e^{-t\cdot\sigma_t}$.&#xD;&#xA;&#xD;&#xA;Rendering with Participating Media&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;The way this is used in physically based renderers is as follows: When a ray enters a medium, we probabilistically stop it inside the medium and have it interact with a particle. Importance sampling the interaction probability$1 - e^{-t\cdot\sigma_t}$ yields a distance $t$; this tells us that the ray traveled $t$ meters in the medium before striking a particle, and now one of two things happens: Either the ray gets absorbed by the particle (with probability $\frac{\sigma_a}{\sigma_t}$), or it gets scattered (with probability $\frac{\sigma_s}{\sigma_t}$).&#xD;&#xA;&#xD;&#xA;How the ray is scattered is described by the _phase function_ and depends on the nature of the particles; the Rayleigh phase function describes scattering from spherical particles smaller than the wavelength of light (e.g. our atmosphere); the Mie phase function describes scattering from spherical particles of similar size than the wavelength (e.g. water droplets); in graphics, usually the [Henyey-Greenstein](http://www.astro.umd.edu/~jph/HG_note.pdf) phase function is used, originally applied to scattering from interstellar dust.&#xD;&#xA;&#xD;&#xA;Now, in graphics, we don't normally render pictures of an infinite medium, but render media inside a scene consisting of hard surfaces as well. In that case, we first fully trace the ray until it hits the next surface, completely ignoring the participating medium; this gives us the distance to the next surface, $t_{Max}$. We then sample an interaction distance $t$ in the medium as described before. If $t \lt t_{Max}$, the ray hit a particle on the way to the next surface and we either absorb it or scatter it. If $t \geq t_{Max}$, the ray made it through unscathed and interacts with the surface as usual.&#xD;&#xA;&#xD;&#xA;Outlook&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;This post was only a small introduction to rendering with participating media; among other things, I completely ignored spatially varying coefficients (which you need for clouds, smoke, etc.). [Steve Marschner's notes](http://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf) are a good resource, if you're interested. In general, participating media are very difficult to render efficiently, and you can go a lot more sophisticated than what I described here; there's [Volumetric Photon Mapping](http://www.cs.dartmouth.edu/~wjarosz/publications/jarosz08beam.pdf), [Photon Beams](http://www.cs.dartmouth.edu/~wjarosz/publications/jarosz11progressive.pdf), [Diffusion approximations](https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf), [Joint Importance Sampling](http://www.cs.dartmouth.edu/~wjarosz/publications/georgiev13joint.pdf) and more. There's also interesting work on [granular media](http://www.cs.dartmouth.edu/~wjarosz/publications/meng15granular.pdf) that describes what to do when the statistical model breaks down, i.e. particle interactions are no longer statistically independent." ContentLicense="CC BY-SA 3.0" />
  <row Id="3163" PostHistoryTypeId="24" PostId="236" RevisionGUID="6541df46-9e24-4d03-8575-7ac6500c7417" CreationDate="2015-11-03T13:56:14.140" Comment="Proposed by 137 approved by 16 edit id of 77" ContentLicense="CC BY-SA 3.0" />
  <row Id="3164" PostHistoryTypeId="5" PostId="1588" RevisionGUID="1256f28b-7006-4ae9-b3e6-7c3fa65cb219" CreationDate="2015-11-03T13:56:29.593" UserId="137" Comment="a bit of mathjax" Text="Two different effects are causing the observation mentioned in the video.&#xD;&#xA;&#xD;&#xA;On one side, the vast majority of screens have a non linear response: if the RGB value is half as much, the emitted light intensity is not half as much. This behavior originally comes from [cathode ray tube (CRT)][1] displays, which produced different light intensities by varying the voltage used to generate the electron beam. From the article:&#xD;&#xA;&gt; CRTs have a pronounced triode characteristic, which results in significant gamma (a nonlinear relationship in an electron gun between applied video voltage and beam intensity).&#xD;&#xA;&#xD;&#xA;As CRT became ubiquitous, systems assumed this behavior to be present and took it into account. Nowadays CRT have mostly been replaced by LCD technology, which emulate this behavior for compatibility.&#xD;&#xA;&#xD;&#xA;Gamma is usually considered to be around $2.2$, which means the light intensity follows a function $I=x^{2.2}$. This is where the 22% mentioned in the video comes from: ($0.5^{2.2} \approx 0.218$).&#xD;&#xA;&#xD;&#xA;On the other side, the human vision is not linear either. [According to Wikipedia][2], a typical sunset on a clear day is about 400 lux, and clear sky daylight is about 10000 to 25000 lux. Yet the latter doesn't feel over 25 times as bright as the former.&#xD;&#xA;&#xD;&#xA;In the end, the non linear response of screens is a good thing, because it gives more precision where it is needed. Note that it is not logarithmic though, but closer to a square function. If you want to read more on the topic, you can look for articles on _&quot;gamma correction&quot;_.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cathode_ray_tube&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lux#Illuminance" ContentLicense="CC BY-SA 3.0" />
  <row Id="3165" PostHistoryTypeId="24" PostId="1588" RevisionGUID="1256f28b-7006-4ae9-b3e6-7c3fa65cb219" CreationDate="2015-11-03T13:56:29.593" Comment="Proposed by 137 approved by 16 edit id of 78" ContentLicense="CC BY-SA 3.0" />
  <row Id="3166" PostHistoryTypeId="5" PostId="84" RevisionGUID="c5c5fb07-04b7-492c-b451-6dd19d3a9c7c" CreationDate="2015-11-03T14:47:58.327" UserId="137" Comment="mathjax it up" Text="If I get correctly what you are asking you basically just need to find the G in this equation: &#xD;&#xA;&#xD;&#xA;$$Image_{out} = Image_{in}^G$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This could be easily solved as &#xD;&#xA;&#xD;&#xA;$$G = \frac{\log{Image_{out}}}{\log{Image_{in}}}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because usually gamma is applied in a uniform fashion on the image, you can just pick any two non zero pixel values (one for source and one for destination) to find out the gamma value applied.  &#xD;&#xA;&#xD;&#xA;EDIT: As @ChristianRau pointed out, if you don't actually know if the image has been modified with gamma correction, you have to take an higher amount of samples and trying to fit a gamma function on those. If a fit to a gamma function results in too many significant outliers, then probably gamma correction wasn't the function applied. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3167" PostHistoryTypeId="24" PostId="84" RevisionGUID="c5c5fb07-04b7-492c-b451-6dd19d3a9c7c" CreationDate="2015-11-03T14:47:58.327" Comment="Proposed by 137 approved by 127 edit id of 80" ContentLicense="CC BY-SA 3.0" />
  <row Id="3168" PostHistoryTypeId="5" PostId="283" RevisionGUID="45554373-26df-464b-aab2-a44178a30987" CreationDate="2015-11-03T14:48:52.220" UserId="137" Comment="mathjax it up" Text="*I'm interested in how this applies to higher numbers of dimensions too, but for this question I will focus solely on 2D grids.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I know that Perlin noise is not isotropic (direction invariant), and that the underlying square grid shows up enough to be able to identify its orientation. Simplex noise is an improvement on this but its underlying equilateral triangle grid is still not completely obscured.&#xD;&#xA;&#xD;&#xA;My intuition is that any attempt to make noise of a particular frequency on a grid will result in a lower frequency in directions not aligned to the grid. So while attempts can be made to disguise this, the noise cannot in principle be isotropic unless it is generated without reference to a grid, allowing the average frequency to be the same in all directions.&#xD;&#xA;&#xD;&#xA;For example, with a square grid without noise, with square side length $n$, the frequency of vertices horizontally or vertically is $\frac1n$, whereas the frequency of vertices at 45 degrees (through opposite corners of the squares) is $\frac1{\sqrt{2}n}$. &#xD;&#xA;&#xD;&#xA;[![Square grid showing length of edge and diagonal][grid]][grid]&#xD;&#xA;&#xD;&#xA;Is there a random distribution that could be applied to offset the vertex positions that would result in the frequency becoming identical in all directions? My suspicion is that there is no such distribution, but I don't have a way of proving either way.&#xD;&#xA;&#xD;&#xA;In short, is there a way of making perfect grid based noise of a given frequency, or should I be focused on other approaches (non-grid based noise or ways of disguising artifacts)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [grid]: https://i.stack.imgur.com/Uzc5Y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3169" PostHistoryTypeId="24" PostId="283" RevisionGUID="45554373-26df-464b-aab2-a44178a30987" CreationDate="2015-11-03T14:48:52.220" Comment="Proposed by 137 approved by 231 edit id of 82" ContentLicense="CC BY-SA 3.0" />
  <row Id="3170" PostHistoryTypeId="5" PostId="250" RevisionGUID="2bc75bb5-f54d-46ae-8cbb-9848a502f4d8" CreationDate="2015-11-03T14:50:56.633" UserId="137" Comment="mathjax it up" Text="I've seen in several places that making Perlin noise loop seamlessly requires calculating it twice in slightly different ways, and summing the two results.&#xD;&#xA;&#xD;&#xA;[This Perlin noise math FAQ] gives a formula:&#xD;&#xA;&#xD;&#xA;$$Floop(x, y, z) = \frac{ (t - z) \cdot F(x, y, z) + z \cdot F(x, y, z - t) }{ t}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;to make a noise function $F$ loop in the $z$ direction. It also mentions that extending this, to loop in 2 dimensions would take 4 evaluations of $F$ and to loop in 3 dimensions would take 8 evaluations of $F$.&#xD;&#xA;&#xD;&#xA;I understand that this gives a seamless join between tiles that is not only continuous but continuously differentiable, but I intuitively expect that to be the case if the noise function is simply evaluated once with grid points reduced modulo the required tile size. If the noise function is only ever based on the immediately surrounding grid points (4 for 2D noise, 8 for 3D noise) then surely just using the leftmost grid points when the point to calculate gets past the right hand edge of the tile will give the same quality of noise as between any other grid points?&#xD;&#xA;&#xD;&#xA;Since I've seen this multiple calculation approach in several places I assume it must have some advantage, but I'm struggling to see the disadvantage with simply wrapping the grid points back to the start when they get too big. What am I missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [This Perlin noise math FAQ]: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html#loop&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3171" PostHistoryTypeId="24" PostId="250" RevisionGUID="2bc75bb5-f54d-46ae-8cbb-9848a502f4d8" CreationDate="2015-11-03T14:50:56.633" Comment="Proposed by 137 approved by 231 edit id of 81" ContentLicense="CC BY-SA 3.0" />
  <row Id="3172" PostHistoryTypeId="5" PostId="250" RevisionGUID="6e05c70a-e0cf-437a-8117-a41ac4e6ae76" CreationDate="2015-11-03T14:51:01.303" UserId="127" Comment="mathjax it up" Text="I've seen in several places that making Perlin noise loop seamlessly requires calculating it twice in slightly different ways, and summing the two results.&#xD;&#xA;&#xD;&#xA;[This Perlin noise math FAQ] gives a formula:&#xD;&#xA;&#xD;&#xA;$$F_{loop}(x, y, z) = \frac{ (t - z) \cdot F(x, y, z) + z \cdot F(x, y, z - t) }{ t}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;to make a noise function $F$ loop in the $z$ direction. It also mentions that extending this, to loop in 2 dimensions would take 4 evaluations of $F$ and to loop in 3 dimensions would take 8 evaluations of $F$.&#xD;&#xA;&#xD;&#xA;I understand that this gives a seamless join between tiles that is not only continuous but continuously differentiable, but I intuitively expect that to be the case if the noise function is simply evaluated once with grid points reduced modulo the required tile size. If the noise function is only ever based on the immediately surrounding grid points (4 for 2D noise, 8 for 3D noise) then surely just using the leftmost grid points when the point to calculate gets past the right hand edge of the tile will give the same quality of noise as between any other grid points?&#xD;&#xA;&#xD;&#xA;Since I've seen this multiple calculation approach in several places I assume it must have some advantage, but I'm struggling to see the disadvantage with simply wrapping the grid points back to the start when they get too big. What am I missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [This Perlin noise math FAQ]: http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html#loop&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3173" PostHistoryTypeId="5" PostId="1486" RevisionGUID="586fdd46-635b-4c42-a126-1c8415d14e34" CreationDate="2015-11-03T15:12:26.733" UserId="137" Comment="mathjax it up" Text="One solution is bilinear mapping, which works for every convex quadrilateral.&#xD;&#xA;&#xD;&#xA;Let $A, B, C, D$ be the vertices of a quadrilateral $Q$ in the plane, in this order.&#xD;&#xA;&#xD;&#xA;Then $f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD$ maps the square $[0,1] \times [0,1]$ to $Q$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DKYWs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3OIsg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3174" PostHistoryTypeId="24" PostId="1486" RevisionGUID="586fdd46-635b-4c42-a126-1c8415d14e34" CreationDate="2015-11-03T15:12:26.733" Comment="Proposed by 137 approved by 192 edit id of 85" ContentLicense="CC BY-SA 3.0" />
  <row Id="3175" PostHistoryTypeId="5" PostId="1583" RevisionGUID="14d7f3d4-c4f0-42e4-b222-e86195ed4a86" CreationDate="2015-11-03T15:15:14.507" UserId="137" Comment="mathjax it up" Text="complement: &#xD;&#xA;&#xD;&#xA;homogeneous coordinates also allows to represent infinity: $(x,y, z, 0) = \frac{x,y,z}0$ in 3D, i.e., the point at infinity in direction $x,y,z$. Typically, light sources at finite or infinite position can be represented the same way.&#xD;&#xA;&#xD;&#xA;About perspective transform, it even allows to interpolate correctly with no perspective distortion (contrary to early graphics hardware on PC )." ContentLicense="CC BY-SA 3.0" />
  <row Id="3176" PostHistoryTypeId="24" PostId="1583" RevisionGUID="14d7f3d4-c4f0-42e4-b222-e86195ed4a86" CreationDate="2015-11-03T15:15:14.507" Comment="Proposed by 137 approved by 1810 edit id of 84" ContentLicense="CC BY-SA 3.0" />
  <row Id="3177" PostHistoryTypeId="5" PostId="1611" RevisionGUID="3a1cab0a-d6a8-4e72-9c76-687a6f97c3ff" CreationDate="2015-11-03T15:15:16.903" UserId="137" Comment="mathjax it up" Text="**Hint**:&#xD;&#xA;&#xD;&#xA;The three coordinates can be handled independently.&#xD;&#xA;&#xD;&#xA;For instance in $x$, you need to solve&#xD;&#xA;&#xD;&#xA;$$x0 + t (x1-x0) = 0$$&#xD;&#xA; and  &#xD;&#xA;$$x0 + t (x1-x0) = xmax$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="3178" PostHistoryTypeId="24" PostId="1611" RevisionGUID="3a1cab0a-d6a8-4e72-9c76-687a6f97c3ff" CreationDate="2015-11-03T15:15:16.903" Comment="Proposed by 137 approved by -1 edit id of 86" ContentLicense="CC BY-SA 3.0" />
  <row Id="3179" PostHistoryTypeId="5" PostId="1611" RevisionGUID="1e2e618e-fc62-498e-a5a7-ea0e86bf27a1" CreationDate="2015-11-03T15:15:16.903" UserDisplayName="user1703" Comment="mathjax it up" Text="**Hint**:&#xD;&#xA;&#xD;&#xA;The three coordinates can be handled independently.&#xD;&#xA;&#xD;&#xA;For instance in $x$, you need to solve&#xD;&#xA;&#xD;&#xA;$$x_0 + t (x_1-x_0) = 0$$&#xD;&#xA; and  &#xD;&#xA;$$x_0 + t (x_1-x_0) = x_{max}$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="3180" PostHistoryTypeId="5" PostId="1497" RevisionGUID="6b645bdb-5cb4-4d9e-81f0-8e52f44c0fbc" CreationDate="2015-11-03T15:17:54.333" UserId="137" Comment="mathjax it up" Text="Projection systems are used to convert a 3D shape to a planar (2D) shape.&#xD;&#xA;&#xD;&#xA;According to the type of projection system, different results and shapes like rectangles, pies, ellipses, circles, ... can be produced out of a sphere.&#xD;&#xA;&#xD;&#xA;Projection systems can be classified by the characteristics of the result they generate. &#xD;&#xA;&#xD;&#xA;To continue, I would like to use a very touchable and common example that we have all seen before, Earth sphere and global wide maps, they are everywhere.&#xD;&#xA;&#xD;&#xA;# Suppose your sphere is the earth!&#xD;&#xA;&#xD;&#xA;Imagine the earth as your sphere and a planar world map that is created from the spherical shape of the earth. In most of the world maps you see the countries near to the poles are getting much bigger than they are in reality, like Iceland which is 1/14 of Africa continent in reality but the map shows them both as equal. This is because when we are omitting one dimension we loose one characteristic of our shapes.&#xD;&#xA;&#xD;&#xA;# Different projection systems and their results&#xD;&#xA;&#xD;&#xA;*This is a planar projection which doesn't conserve distance, angles or area. The red circles show the amount of exaggeration that is the product of this projection.*&#xD;&#xA;&#xD;&#xA;![First](https://i.stack.imgur.com/xtjLy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Equal-Area, look at Iceland and Africa in this one and compare with above.*&#xD;&#xA;&#xD;&#xA;![Second](https://i.stack.imgur.com/EdLTy.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Projection systems can be classified by what they preserve.&#xD;&#xA;&#xD;&#xA; 1. Equal area.&#xD;&#xA; 2. Equal angle which preserve the shape without distortion (conformal).&#xD;&#xA; 3. Equal distance.&#xD;&#xA; 4. ......&#xD;&#xA; &#xD;&#xA;Conformal projections preserve the shapes but area will not be preserved (the first above picture) this one is the most famous projection system that is used in many applications. Your sphere is a rectangle here!&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;### So you cannot say a sphere will be projected to an ellipse always. As mentioned above a sphere can be projected to a rectangle (first shape) or can be an ellipse but with different characteristics (equal angle, distance, shape, area - see the following picture), or you may also project a sphere into a conic and then open the conic so you will have a pie.&#xD;&#xA;&#xD;&#xA;Each of the above projection systems can be applied with iterative or direct algorithms that can be found on the internet. I didn't talk about the formula and transformations because you didn't ask. Although I wish you to find this answer useful.&#xD;&#xA;&#xD;&#xA;![Third](https://i.stack.imgur.com/iOekb.jpg)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;### In perspective projections I say yes only ellipses will be produced out of spheres&#xD;&#xA;&#xD;&#xA;Cutting a conic with a horizontal plane creates a circle.&#xD;&#xA;&#xD;&#xA;Cutting with an oblique plane creates a bevel which would be an ellipse or a hyperbola depending on the cutting angle, and when this angle inclines to be vertical in will create a parabola (following picture).&#xD;&#xA;&#xD;&#xA;![Ellipse](https://i.stack.imgur.com/RSoYm.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Maybe this is obvious but take a look at their equations.&#xD;&#xA;&#xD;&#xA;For simplicity I assumed all geometries are origin centered.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Equations:&#xD;&#xA;&#xD;&#xA;Circle: $x^2+y^2=r^2$&#xD;&#xA;&#xD;&#xA;Ellipse: $x^2/a^2+y^2/b^2=1$&#xD;&#xA;&#xD;&#xA;Hyperbola: $x^2/a^2-y^2/b^2=1$&#xD;&#xA;&#xD;&#xA;Parabola: $y^2=4ax$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Morphology :&#xD;&#xA;&#xD;&#xA;An ellipse has two foci obviously. A circle as a special kind of ellipsis has two foci too but they are coincident. A hyperbola however is a y axis mirror of its equal ellipsis and it has two foci too. A parabola has one focus but actually it has two because the second one is at infinity: when the cutting plane inclines to 90 degrees (bearing angle), second focus goes to infinity.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Conclusion&#xD;&#xA;&#xD;&#xA;As you see all are ellipses, however you may name them differently to describe special cases, but if you are going to implement it in a game, you need to assume an ellipse equation and it is enough. I can't tell which one of you guys are right, you or your friend, because both could be right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3181" PostHistoryTypeId="24" PostId="1497" RevisionGUID="6b645bdb-5cb4-4d9e-81f0-8e52f44c0fbc" CreationDate="2015-11-03T15:17:54.333" Comment="Proposed by 137 approved by 127 edit id of 90" ContentLicense="CC BY-SA 3.0" />
  <row Id="3182" PostHistoryTypeId="5" PostId="258" RevisionGUID="bf08819e-e3bd-4a43-aabf-7266cd4f0f5b" CreationDate="2015-11-03T15:17:56.897" UserId="137" Comment="mathjax again..." Text="Yes, applying two Gaussian blurs is equivalent to doing one Gaussian blur, but with a slightly different size calculation.&#xD;&#xA;&#xD;&#xA;Applying a Gaussian blur to an image means doing a [convolution](https://en.wikipedia.org/wiki/Convolution) of the Gaussian with the image. Convolution is associative: Applying two Gaussian blurs to an image is equivalent to convolving the two Gaussians with each other, and convolving the resulting function with the image.&#xD;&#xA;&#xD;&#xA;As it happens, the convolution of two Gaussians with each other is another Gaussian, whose variance is the sum of variances of the two original Gaussians. A Gaussian of N pixel width has variance $N^2$; applying it twice is equivalent to a Gaussian with variance $2\cdot N^2$, which corresponds to a width of $\sqrt{2}\cdot N$ pixels.&#xD;&#xA;&#xD;&#xA;In the same vein, applying a Gaussian of width $2\cdot N$ is equivalent to applying a Gaussian of width $N$ four times." ContentLicense="CC BY-SA 3.0" />
  <row Id="3183" PostHistoryTypeId="24" PostId="258" RevisionGUID="bf08819e-e3bd-4a43-aabf-7266cd4f0f5b" CreationDate="2015-11-03T15:17:56.897" Comment="Proposed by 137 approved by 16 edit id of 87" ContentLicense="CC BY-SA 3.0" />
  <row Id="3184" PostHistoryTypeId="5" PostId="1635" RevisionGUID="fa90da25-4b76-4420-8361-663ab426426f" CreationDate="2015-11-03T15:18:17.490" UserId="137" Comment="mathjax some more" Text="First off, this is probably not the best way of testing energy conservation, because not all incident inclinations are visible in the image. Most of the environment is also black, so a less &quot;peaky&quot; BRDF such as Lambert would come out very dark with no way of telling whether it's energy conserving or not.&#xD;&#xA;&#xD;&#xA;What is more commonly used is a so-called &quot;furnace test&quot;, where you place a single sphere into a white environment map. When you render this sphere using the BRDF of interest, it should blend into the environment perfectly if the BRDF is energy conserving (make sure no color channels are clipping). Because it is a sphere, you will be able to see the BRDF at all incident inclinations. Additionally, the sphere is convex, so lacking any other objects in the scene, no reflected ray will be occluded, and every pixel of the sphere in the image will be an integral over the BRDF at a different inclination.&#xD;&#xA;&#xD;&#xA;If you did this test, you would also notice that your Phong BRDF is most likely not energy conserving. The commonly used normalization term of $\frac{n+1}{2 \pi}$ (or $\frac{n+2}{2 \pi}$, depending on who you ask) only holds at normal incidence. At other inclinations, and particularly at grazing angle, up to half of the reflected rays will land below the surface and are usually terminated (because transmitting through a reflective surface does not make sense).  &#xD;&#xA;The correct normalization term that accounts for the part of the Phong lobe that is clipped below the hemisphere is very difficult to compute. Jim Arvo derived a closed-form solution for integer exponents using double-axis moments, summarised in the [Global Illumination Compendium](http://people.cs.kuleuven.be/~philip.dutre/GI/TotalCompendium.pdf), paragraph 31a) and 31b) (page 17/18). These formulas are not very practical for use in a renderer though and I don't suggest implementing them.&#xD;&#xA;&#xD;&#xA;It should be clear that if a simple model such as Phong is already this difficult to normalize, then Blinn-Phong is even more difficult. First of all, the $\frac{n+1}{2 \pi}$ normalization term you mention is only correct if you use Blinn-Phong as a microfacet distribution inside a full microfacet BRDF (e.g. Torrance-Sparrow or Walter). If you directly use the Blinn-Phong BRDF, then a more correct normalization term is $\frac{(n+2)(n+4)}{(8 \pi 2^{-n/2} + n)}$, derived in [this short article](http://www.farbrausch.de/~fg/stuff/phong.pdf) by Fabian Giesen (second page) and also listed on the page you mention. However, this normalization term is again only correct at normal incidence and will not be exact at other inclinations. From what I can tell, no exact normalization term exists." ContentLicense="CC BY-SA 3.0" />
  <row Id="3185" PostHistoryTypeId="24" PostId="1635" RevisionGUID="fa90da25-4b76-4420-8361-663ab426426f" CreationDate="2015-11-03T15:18:17.490" Comment="Proposed by 137 approved by 16 edit id of 89" ContentLicense="CC BY-SA 3.0" />
  <row Id="3186" PostHistoryTypeId="5" PostId="1632" RevisionGUID="6da4d4b4-4647-4f0c-9ccb-3295b5f5fe98" CreationDate="2015-11-03T15:18:26.990" UserId="137" Comment="mathjax it up" Text="I am trying to sample from the Blinn-Phong BRDF.&#xD;&#xA;&#xD;&#xA;For testing, I use a spherical light source (Lambertian emission) sitting on a specular plane.  Here's a reference image using energy-conserving Phong with exponent `30000`:&#xD;&#xA;&#xD;&#xA;[![Phong][1]][1]&#xD;&#xA;&#xD;&#xA;Notice that no energy is lost.  **I would now like to achieve the same thing for Blinn-Phong**.&#xD;&#xA;&#xD;&#xA;Here's my attempt (same exponent, but on Blinn-Phong BRDF):&#xD;&#xA;&#xD;&#xA;[![Blinn-Phong][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, a substantial portion of energy is lost.  The normalization term I am using comes from [here](http://www.thetenthplanet.de/archives/255) and is $\frac{n+1}{2 \pi}$.  The problem is this is a _normalization_ term, not a _conservation_ term.&#xD;&#xA;&#xD;&#xA;I believe this is the expected result.  It is common in graphics to make BRDFs reflect less than the input amount of energy, as opposed to exactly the right amount, as this is usually less difficult.&lt;sup&gt;1, 2&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;My question:&#xD;&#xA;&#xD;&#xA;1. Is there a version that conserves all energy exactly?&#xD;&#xA;2. Iff not, can someone at least confirm this is expected?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;N.B. I am fairly confident this is not a ray generation/PDF issue.  These images were importance sampled using a method given in the PBRT book pg. 695 - pg. 699.  Moreover, a non-importance sampled version looks very similar (though I had to use a lower exponent to get it to converge fast enough, and it still took 10,000 s/p).&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;1&lt;/sup&gt;This can be argued from a shadowing/masking argument on microfacets.  Unfortunately, it ignores multiple scattering.  The correct answer is somewhere in-between.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;2&lt;/sup&gt;Indeed, I had to derive the Phong conservation term myself.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R3uLF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xKlyz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3187" PostHistoryTypeId="24" PostId="1632" RevisionGUID="6da4d4b4-4647-4f0c-9ccb-3295b5f5fe98" CreationDate="2015-11-03T15:18:26.990" Comment="Proposed by 137 approved by 127 edit id of 88" ContentLicense="CC BY-SA 3.0" />
  <row Id="3188" PostHistoryTypeId="5" PostId="1470" RevisionGUID="19253f7f-df86-4fd5-b028-fa7d9bf9bfff" CreationDate="2015-11-03T15:19:40.177" UserId="137" Comment="mathjax it up" Text="When I was reading theory behind physical based rendering I noticed that definition of BSDF and radiance has some problems. For example BSDF of purely specular surfaces is zero almost everywhere and infinite in one point or radiance of directional light is zero for almost all directions except for one where it is again infinite.&#xD;&#xA;&#xD;&#xA;This causes problems in rendering equation.&#xD;&#xA;&#xD;&#xA;$$L_0(x, w_0)= \int_{S^2}{\rho(x, w_i,w_0)L_0(x, w_i)d\sigma_\perp(w_i)}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For purely specular surface this integral has to be zero, from strict mathematical point of view. This is because the BSDF is zero (solid angle)-almost everywhere. You can argue that BSDF is infinite in one point and you have to take this point into account. But how do you know what is the reflectance of the surface at that point? From the infinity you can really tell. Furthermore from mathematical standpoint of view you cannot integrate infinite valued function, even if you could than the only sensible answers would be zero or infinity.&#xD;&#xA;&#xD;&#xA;I know these are subtle problems and in practice can be solved with few `if`s but I would like to have theory without holes. I believe that if you embrace these problems in theory than it helps you with placing those `if`s in the right place.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;How to deal with this problem? &#xD;&#xA;&#xD;&#xA;Not sure entirely but as I can remember Erich Veach [in his thesis][2] address this problem only slightly and tries to get away with it by saying that BSDF and radiance are [distributions][3]. This is problematic, you cannot multiply two distributions, which is needed in rendering equation. For example when a light from  directional light hits specular surface than you need to multiply two Dirac delta functions together.&#xD;&#xA;&#xD;&#xA;The question is: Is there any work which reformulates rendering equation, BSDF and radiance in such a way that it does not suffer from mentioned problems?&#xD;&#xA;&#xD;&#xA;What is the state of the art theory behind raytracing? Is is still Erich Veach's thesis?&#xD;&#xA;&#xD;&#xA;(I'm only aware of [work][4] of Christian Lessig, but his work is still beyond my mathematical reach.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I already have [proposal][5] how to deal with this problem. I define BSDF and radiance as measure. The basic idea works fine, but the whole theory of light transport needs to be redone to find out if it really works.&#xD;&#xA;&#xD;&#xA;The main purpose of this question is to find out if someone else already did it, so I can read it and then focus my energy somewhere else.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FODai.gif&#xD;&#xA;  [2]: https://graphics.stanford.edu/papers/veach_thesis/&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Distribution_(mathematics)&#xD;&#xA;  [4]: http://cybertron.cg.tu-berlin.de/lessig/projects/dissertation/index.html&#xD;&#xA;  [5]: http://tomsmathjourneys.blogspot.cz/2015/09/better-code-with-radiance-and-bsdf-as.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3189" PostHistoryTypeId="24" PostId="1470" RevisionGUID="19253f7f-df86-4fd5-b028-fa7d9bf9bfff" CreationDate="2015-11-03T15:19:40.177" Comment="Proposed by 137 approved by -1 edit id of 83" ContentLicense="CC BY-SA 3.0" />
  <row Id="3190" PostHistoryTypeId="5" PostId="1470" RevisionGUID="c58bad3d-917f-4a32-8211-be0bcc77ab8f" CreationDate="2015-11-03T15:19:40.177" UserId="16" Comment="mathjax it up" Text="When I was reading theory behind physical based rendering I noticed that definition of BSDF and radiance has some problems. For example BSDF of purely specular surfaces is zero almost everywhere and infinite in one point or radiance of directional light is zero for almost all directions except for one where it is again infinite.&#xD;&#xA;&#xD;&#xA;This causes problems in rendering equation.&#xD;&#xA;&#xD;&#xA;$$L_0(x, \omega_0)= \int_{S^2}{\rho(x, \omega_i,\omega_0)L(x, \omega_i)\,\mathrm{d}\sigma_\perp(\omega_i)}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For purely specular surface this integral has to be zero, from strict mathematical point of view. This is because the BSDF is zero (solid angle)-almost everywhere. You can argue that BSDF is infinite in one point and you have to take this point into account. But how do you know what is the reflectance of the surface at that point? From the infinity you can really tell. Furthermore from mathematical standpoint of view you cannot integrate infinite valued function, even if you could than the only sensible answers would be zero or infinity.&#xD;&#xA;&#xD;&#xA;I know these are subtle problems and in practice can be solved with few `if`s but I would like to have theory without holes. I believe that if you embrace these problems in theory than it helps you with placing those `if`s in the right place.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;How to deal with this problem? &#xD;&#xA;&#xD;&#xA;Not sure entirely but as I can remember Erich Veach [in his thesis][2] address this problem only slightly and tries to get away with it by saying that BSDF and radiance are [distributions][3]. This is problematic, you cannot multiply two distributions, which is needed in rendering equation. For example when a light from  directional light hits specular surface than you need to multiply two Dirac delta functions together.&#xD;&#xA;&#xD;&#xA;The question is: Is there any work which reformulates rendering equation, BSDF and radiance in such a way that it does not suffer from mentioned problems?&#xD;&#xA;&#xD;&#xA;What is the state of the art theory behind raytracing? Is is still Erich Veach's thesis?&#xD;&#xA;&#xD;&#xA;(I'm only aware of [work][4] of Christian Lessig, but his work is still beyond my mathematical reach.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I already have [proposal][5] how to deal with this problem. I define BSDF and radiance as measure. The basic idea works fine, but the whole theory of light transport needs to be redone to find out if it really works.&#xD;&#xA;&#xD;&#xA;The main purpose of this question is to find out if someone else already did it, so I can read it and then focus my energy somewhere else.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FODai.gif&#xD;&#xA;  [2]: https://graphics.stanford.edu/papers/veach_thesis/&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Distribution_(mathematics)&#xD;&#xA;  [4]: http://cybertron.cg.tu-berlin.de/lessig/projects/dissertation/index.html&#xD;&#xA;  [5]: http://tomsmathjourneys.blogspot.cz/2015/09/better-code-with-radiance-and-bsdf-as.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3191" PostHistoryTypeId="5" PostId="256" RevisionGUID="651feff8-701b-4778-a65f-878a5a61d216" CreationDate="2015-11-03T15:21:02.520" UserId="16" Comment="added 3 characters in body" Text="To make Gaussian blurring a 2d image faster, I know that you can do one axis and then the other.&#xD;&#xA;&#xD;&#xA;I'm wondering though, if I did two Gaussian blurs of size $N$, would that be the same mathematically as doing one Gaussian blur of size $2N$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3192" PostHistoryTypeId="5" PostId="1621" RevisionGUID="ed4036cd-c946-42a6-94de-0ccccaedd0e8" CreationDate="2015-11-03T15:32:59.350" UserId="127" Comment="Corrected mistake when copying the formula from the question" Text="The hint with the perspective division was already [mentioned by ratchet freak](http://computergraphics.stackexchange.com/a/1607/127), but I'd like to add some explanation of how to come up with the solution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First of all, remember that homogenous coordinates add a fourth value $w$ to your 3D vector. For points in the 3D space, $w \neq 0$ holds and $[x, y, z, w] = [n*x, n*y, n*z, n*w]$ also holds for every $n$.&#xD;&#xA;&#xD;&#xA;Now the goal is to find a transformation matrix $T$, which solves&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    \begin{bmatrix} \frac{2}{x + y} \\ \frac{5y + z}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;= T \cdot &#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These are basically four equations, but having a look at the first row, being&#xD;&#xA;&#xD;&#xA;$$\frac{2}{x + y} = t_{11}\cdot x + t_{21}\cdot y + t_{31} \cdot z + t_{41}$$&#xD;&#xA;&#xD;&#xA;and trying to find values for the $t$s, you'll see that this is not possible without further restructuring. The main problems are the $x$ and $y$ in the denominator. But as we can make use of the fourth value in the vector, we can expand the $w$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{5y + z}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{2.5y + 0.5z}{x + y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the first step, I removed the factor of $2$ from the second values denominator, leading to every values denominator either being $1$ or $(x + y)$. In the second step, I made use of the above mentioned rule ($[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$), setting $n = (x + y)$, thus eliminating the denominator of the first two values.&#xD;&#xA;&#xD;&#xA;Now we've got&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which is not that hard anymore.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 0  &amp;  0 &amp;   0  &amp;  2   \\ 0 &amp;  2.5 &amp; 0.5 &amp;  0 \\ 3 &amp;   3  &amp;  0 &amp;   0 \\ 1  &amp;  1  &amp;  0  &amp;  0 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;* Remember the advantage of homogenous coordinates $w$.&#xD;&#xA;* $[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$ is the key.&#xD;&#xA;* Push everything that's in the denominator to the $w$ coordinate." ContentLicense="CC BY-SA 3.0" />
  <row Id="3193" PostHistoryTypeId="5" PostId="1502" RevisionGUID="66b8ee86-8f02-4709-872d-580abe5ed845" CreationDate="2015-11-03T16:02:39.780" UserId="127" Comment="Applied MathJax" Text="When rendering 3D scenes with transformations applied to the objects, normals have to be transformed with the transposed inverse of the model view matrix. So, with a normal $n$, modelViewMatrix $M$, the transformed normal $n'$ is &#xD;&#xA;&#xD;&#xA;$$n' = (M^{-1})^{T} \cdot n $$&#xD;&#xA;&#xD;&#xA;When transforming the objects, it is clear that the normals need to be transformed accordingly. But why, mathematically, is this the corresponding transformation matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3194" PostHistoryTypeId="5" PostId="1506" RevisionGUID="8c117bf5-7d28-4eb4-80fb-ba1a7782f6c9" CreationDate="2015-11-03T16:13:20.533" UserId="127" Comment="Applied MathJax" Text="Here's a simple proof that the inverse transpose is required. Suppose we have a plane, defined by a plane equation $n \cdot x + d = 0$, where $n$ is the normal. Now I want to transform this plane by some matrix $M$. In other words, I want to find a new plane equation $n' \cdot Mx + d' = 0$ that is satisfied for exactly the same $x$ values that satisfy the previous plane equation.&#xD;&#xA;&#xD;&#xA;To do this, it suffices to set the two plane equations equal. (This gives up the ability to rescale the plane equations arbitrarily, but that's not important to the argument.) Then we can set $d' = d$ and subtract it out. What we have left is:&#xD;&#xA;&#xD;&#xA;$$n' \cdot Mx = n \cdot x$$&#xD;&#xA;&#xD;&#xA;I'll rewrite this with the dot products expressed in matrix notation (thinking of the vectors as 1-column matrices):&#xD;&#xA;&#xD;&#xA;$${n'}^T Mx = n^T x$$&#xD;&#xA;&#xD;&#xA;Now to satisfy this for _all_ $x$, we must have:&#xD;&#xA;&#xD;&#xA;$${n'}^T M = n^T$$&#xD;&#xA;&#xD;&#xA;Now solving for $n'$ in terms of $n$,&#xD;&#xA;&#xD;&#xA;$${n'}^T = n^T M^{-1} \\&#xD;&#xA;n' = (n^T M^{-1})^T\\&#xD;&#xA;n' = (M^{-1})^T n$$&#xD;&#xA;&#xD;&#xA;Presto! If points $x$ are transformed by a matrix $M$, then plane normals must transform by the inverse transpose of $M$ in order to preserve the plane equation.&#xD;&#xA;&#xD;&#xA;This is basically a property of the dot product. In order for the dot product to remain invariant when a transformation is applied, the two vectors being dotted have to transform in corresponding but different ways.&#xD;&#xA;&#xD;&#xA;Mathematically, this can be described by saying that the normal vector isn't an ordinary vector, but a thing called a [covector](https://en.wikipedia.org/wiki/Linear_form) (aka covariant vector, dual vector, or linear form). A covector is basically defined as &quot;a thing that can be dotted with a vector to produce an invariant scalar&quot;. In order to achieve that, it has to transform using the inverse transpose of whatever matrix is operating on ordinary vectors. This holds in any number of dimensions.&#xD;&#xA;&#xD;&#xA;Note that in 3D specifically, a bivector is similar to a covector. They're not *quite* the same since they have different units: a covector has units of inverse length while a bivector has units of length squared (area), so they behave differently under scaling. However, they do transform the same way with respect to their orientation, which is what matters for normals. We usually don't care about the magnitude of a normal (we always normalize them to unit length anyway), so we usually don't need to worry about the difference between a bivector and a covector." ContentLicense="CC BY-SA 3.0" />
  <row Id="3195" PostHistoryTypeId="5" PostId="62" RevisionGUID="92803f45-99eb-4080-84f0-bbdf696a5d50" CreationDate="2015-11-03T16:14:57.213" UserId="196" Comment="added a link to Spherical Fibonacci Mapping" Text="I'd consider just going with 3D noise and evaluating it on the surface of the sphere.&#xD;&#xA;&#xD;&#xA;For gradient noise which is naturally in the domain of the surface of the sphere, you need a regular pattern of sample points on the surface that have natural connectivity information, with roughly equal area in each cell, so you can interpolate or sum adjacent values. I wonder if something like a [Fibonacci grid][1] might work:&#xD;&#xA;&#xD;&#xA;[![Fibonacci grid on the surface of a sphere][2]][2]&#xD;&#xA;&#xD;&#xA;I haven't chewed through the math to determine how much work it would be to figure out the indices of and distance to your four neighbors (I don't even know if you end up having four well-defined neighbors in all cases), and I suspect it may be less efficient than simply using 3D noise.&#xD;&#xA;&#xD;&#xA;**Edit:** Someone else has chewed through the math! See this new paper on [Spherical Fibonacci Mapping][3]. It seems that it would be straightforward to adapt it to sphere noise.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If you are rendering a sphere, not just evaluating noise on the surface of a sphere, and are fine with tessellating your sphere to the resolution of your noise lattice, you can create a [geodesic grid][4] on the surface of the sphere (a subdivided icosahedron, usually):&#xD;&#xA;&#xD;&#xA;[![Geodesic sphere][5]][5]&#xD;&#xA;&#xD;&#xA;Each vertex of the sphere can have a randomly generated gradient for gradient noise. To get this information to the pixel shader (unless you want straightforward interpolation like value noise), you may need a technique like this article's [wireframe rendering with barycentric coordinates][6]: do unindexed rendering, with each vertex containing the barycentric coordinates of that vertex in the triangle. You can then read from `SV_PrimitiveID` (or the OpenGL equivalent) in the pixel shader, read the three noise gradients from the vertices based on what triangle you are on, and use whatever noise calculation you like using the interpolated barycentric coordinates.&#xD;&#xA;&#xD;&#xA;I think the most difficult part of this method is coming up with a scheme to map your triangle ID to three samples in order to look up the noise values at each vertex.&#xD;&#xA;&#xD;&#xA;If you need multiple octaves of noise or noise at a finer resolution than your sphere model, you may be able to do a coarse geodesic grid with vertices and do a few levels of subdivision in the pixel shader. i.e. from the barycentric coordinates, figure out which subdivided triangle you *would* be in if the mesh was further tessellated, and then figure out what the primitive ID and barycentric coordinates would be for that triangle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://onlinelibrary.wiley.com/doi/10.1256/qj.05.227/epdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/sQQb3.png&#xD;&#xA;  [3]: http://lgdv.cs.fau.de/uploads/publications/spherical_fibonacci_mapping.pdf&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Geodesic_grid&#xD;&#xA;  [5]: https://i.stack.imgur.com/pjVBA.png&#xD;&#xA;  [6]: http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3196" PostHistoryTypeId="5" PostId="73" RevisionGUID="b5a8e9c6-7797-41f5-b739-f9ca7d3b88eb" CreationDate="2015-11-03T17:03:42.513" UserId="137" Comment="mathjax some more" Text="The idea i would try to apply would be the following, i make the example for the curve but it should be straightforward the application for the surface.&#xD;&#xA;&#xD;&#xA;Let's say we have a curve $\gamma$ uniformly parametrized, let's say the parameter of the curve is $s$. Your goal is to sample point corresponding to value of $s$ such that the curvature is high.&#xD;&#xA;&#xD;&#xA;If you get the magnitude of the curvature $c$ this will be function of $s$ too, so if you normalize the function $|c|$ you will get a probability distribution. If you get the integral of such distribution you will have the cumulative distribution, let's call the cumulative function $C(s)$.&#xD;&#xA;&#xD;&#xA;The sampling problem from a distribution given the cumulative function is well known, so basically once you have sampled a set of value $s0,s1,\dots,sn$ such value will be related to the points of interest.&#xD;&#xA;&#xD;&#xA;The application of this method to the case of surface should be straight since basically you have a two dimensional cumulative distribution function, but the sampling problem is exactly the same.&#xD;&#xA;&#xD;&#xA;Just to give some detail... basically sampling from a distribution given the cumulative function involves two steps. &#xD;&#xA;&#xD;&#xA;1. take a random value in the interval $[0,1]$, let's say $k$ &#xD;&#xA;&#xD;&#xA;2. solve the equation $C(s) = k$.&#xD;&#xA;&#xD;&#xA;This approach is exact, of course it is expensive, but if you like such approach you can work on optimization." ContentLicense="CC BY-SA 3.0" />
  <row Id="3197" PostHistoryTypeId="24" PostId="73" RevisionGUID="b5a8e9c6-7797-41f5-b739-f9ca7d3b88eb" CreationDate="2015-11-03T17:03:42.513" Comment="Proposed by 137 approved by 228 edit id of 91" ContentLicense="CC BY-SA 3.0" />
  <row Id="3198" PostHistoryTypeId="5" PostId="313" RevisionGUID="a29630cc-077e-4532-b499-cb52494ad975" CreationDate="2015-11-03T17:19:11.853" UserId="137" Comment="a bit of mathjax" Text="The form of the rendering equation that uses only the BRDF ($f$ in your example, often called $f_r$) and integrates over one hemisphere does not account for transmission.&#xD;&#xA;&#xD;&#xA;When adding in transmission, it's fairly common to add a second integral over the opposite hemisphere, using a different BTDF function (bidirectional *transmission* distribution function). This is equivalent to an integral over the full sphere of directions with a BSDF function, but since that function would usually have to be defined as a piecewise function, writing it as two integrals can be more straightforward." ContentLicense="CC BY-SA 3.0" />
  <row Id="3199" PostHistoryTypeId="24" PostId="313" RevisionGUID="a29630cc-077e-4532-b499-cb52494ad975" CreationDate="2015-11-03T17:19:11.853" Comment="Proposed by 137 approved by 196 edit id of 94" ContentLicense="CC BY-SA 3.0" />
  <row Id="3200" PostHistoryTypeId="5" PostId="41" RevisionGUID="aea1a13e-7fba-4745-be95-9dcd5ab56597" CreationDate="2015-11-03T17:34:07.373" UserId="137" Comment="even more mathjax" Text="In convolution, two mathematical functions are combined to produce a third function. In image processing functions are usually called kernels. A kernel is nothing more than a (square) array of pixels (a small image so to speak). Usually, the values in the kernel add up to one. This is to make sure noe energy is added or removed from the image after the operation.&#xD;&#xA;&#xD;&#xA;Specifically, a Gaussian kernal (used for Gaussian blur) is a square array of pixels where the pixel values correspond to the values of a Gaussian curve (in 2d).&#xD;&#xA;&#xD;&#xA;[![Image linked from http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm][1]][1]&#xD;&#xA;&#xD;&#xA;Each pixel in the image gets multiplied by the Gaussian kernel. This is done by placing the center pixel of the kernel on the image pixel and multiplying the values in the original image with the pixels in the kernel that overlap. The values resulting from these multiplications are added up and that result is used for the value at the destination pixel. Looking at the image, you would multiply the value at (0,0) in the input array by the value a (i) in the kernel array, the value at (1,0) in the input array by the value a (h) in the kernel array, etc. and then add all these values to get the value for (1,1) at the output image.&#xD;&#xA;&#xD;&#xA;[![Image linked from http://www.songho.ca/dsp/convolution/convolution.html][2]][2]&#xD;&#xA;&#xD;&#xA;To answer your second question first, the larger the kernel, the more expensive the operation. So, the larger the radius of the blur, the longer the operation will take.&#xD;&#xA;&#xD;&#xA;To answer your first question, as explained above, convolution can be done by multiplying each input pixel with the entire kernel. However, if the kernel is symmetrical (wich a Gaussian kernel is) you can also multiply each axis (x and y) independently, which will decrease the total number of multiplications. In proper mathematical terms, if a matrix is separable it can be decomposed into (M×1) and (1×N) matrices. For the Gaussian kernel above this means you can also use the following kernels:&#xD;&#xA;&#xD;&#xA;$$\frac1{256}\cdot\begin{bmatrix}&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1\\&#xD;&#xA;4&amp;16&amp;24&amp;16&amp;4\\&#xD;&#xA;6&amp;24&amp;36&amp;24&amp;6\\&#xD;&#xA;4&amp;16&amp;24&amp;16&amp;4\\&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\frac1{256}\cdot\begin{bmatrix}&#xD;&#xA;1\\4\\6\\4\\1&#xD;&#xA;\end{bmatrix}\cdot\begin{bmatrix}&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You would now multiply each pixel in the input image with both kernels and add the resulting values to get the value for the output pixel.&#xD;&#xA;&#xD;&#xA;For more information on how to see if a kernel is separable, follow this [link][4].&#xD;&#xA;&#xD;&#xA;Edit: the two kernels shown above use slightly different values. This is because the (sigma) parameter used for the Gaussian curve to create these kernels were slightly different in both cases. For an explanation on which parameters influence the shape of the Gaussian curve and thus the values in the kernel follow this [link][5]&#xD;&#xA;&#xD;&#xA;Edit: in the second image above it says the kernel that is used is flipped. This of course only makes any difference if the kernel you use is not symmetric. The reason why you need to flip the kernel has to do with the mathematical properties of the convolution operation (see [link][6] for a more in depth explanation on convolution). Simply put: if you would not flip the kernel, the result of the convolution operation will be flipped. By flipping the kernel, you get the correct result.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Qc4Mq.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/bRN2c.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UsU96.gif&#xD;&#xA;  [4]: http://stackoverflow.com/questions/5886529/how-can-i-determine-if-my-convolution-is-separable&#xD;&#xA;  [5]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;  [6]: http://songho.ca/dsp/convolution/convolution.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3201" PostHistoryTypeId="24" PostId="41" RevisionGUID="aea1a13e-7fba-4745-be95-9dcd5ab56597" CreationDate="2015-11-03T17:34:07.373" Comment="Proposed by 137 approved by 127 edit id of 92" ContentLicense="CC BY-SA 3.0" />
  <row Id="3202" PostHistoryTypeId="5" PostId="324" RevisionGUID="464aa08d-2cf0-4d53-b06f-3cea03adc48c" CreationDate="2015-11-03T17:35:05.190" UserId="137" Comment="mathjax yet again" Text="I've seen a number of 2D Poisson disc sampling algorithms online that use a grid to accelerate checking for existing points within the minimum radius [![r][r image]][r link] of a candidate point. For example:&#xD;&#xA;&#xD;&#xA;- [Dev.Mag]&#xD;&#xA;- [mbostock]&#xD;&#xA;&#xD;&#xA;They use a grid of squares of side $\frac{r}{\sqrt2}$, which is the same side length that I intuitively came up with when implementing this myself.&#xD;&#xA;&#xD;&#xA;I can see the reason - that is the largest square that cannot contain more than 1 point (assuming the minimum is not attainable - the distance between two points must be *strictly* greater than $r$).&#xD;&#xA;&#xD;&#xA;However, having thought about it further, I adjusted the grid size to $\frac{r}2$ instead. This finer grid means 4 additional squares need to be checked (the 4 corner squares are now within the radius), but the total area covered by the required squares is less, so that on average fewer points will need to go through the Euclidean distance check. The difference can be visualized using the same style as the diagram in the first linked article.&#xD;&#xA;&#xD;&#xA;[![Grid with side length r over root 2][grid r over root 2]][grid r over root 2]&#xD;&#xA;[![Grid with side length r over 2][grid r over 2]][grid r over 2]&#xD;&#xA;&#xD;&#xA;For a candidate new point, existing points must be checked in all squares that are within a radius $r$ of the corners of the candidate's square. Here the two grid sizes are shown side by side, to scale, for the same radius $r$. This shows clearly that a significantly smaller area is being checked. Each square is exactly half the area of the previous approach, and even if the 4 outer corner squares are excluded in the previous approach (left image), this still gives an area $2 \cdot \frac{21}{25} = 1.68$ times larger than in the new approach.&#xD;&#xA;&#xD;&#xA;My main question is this: **Is this approach still correct, and does it give identical results?**&#xD;&#xA;&#xD;&#xA;I'm also interested to know whether there is any reason to favor the $\frac{r}{\sqrt2}$ approach. Using $\frac{r}{2}$ seems more efficient in time, which seems worth the cost in space efficiency. Is there anything I'm missing?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;*Images produced with this [jsfiddle](https://jsfiddle.net/wkneysgj/) (in case I need to edit them later).*&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Dev.Mag]: http://devmag.org.za/2009/05/03/poisson-disk-sampling/&#xD;&#xA;  [mbostock]: http://bl.ocks.org/mbostock/dbb02448b0f93e4c82c3&#xD;&#xA;&#xD;&#xA;  [grid r over root 2]: https://i.stack.imgur.com/cE5KI.png&#xD;&#xA;  [grid r over 2]: https://i.stack.imgur.com/r3PJ9.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3203" PostHistoryTypeId="24" PostId="324" RevisionGUID="464aa08d-2cf0-4d53-b06f-3cea03adc48c" CreationDate="2015-11-03T17:35:05.190" Comment="Proposed by 137 approved by 127 edit id of 96" ContentLicense="CC BY-SA 3.0" />
  <row Id="3204" PostHistoryTypeId="5" PostId="291" RevisionGUID="f81c4447-833d-4bbd-b877-bd741dca4725" CreationDate="2015-11-03T17:35:30.317" UserId="137" Comment="some more mathjax" Text="The following naïve approach will probably not yield as nicely distributed points as the [ones given by Lhf](http://computergraphics.stackexchange.com/a/251/394), but it should be much easier to implement and computationally faster:&#xD;&#xA;&#xD;&#xA;For two points $x$ and $y$ let $d(x,y)$ denote the average distance you want points with the average curvature of $x$ and $y$ to have, e.g., some constant multiplied with the inverse of the average curvature of $x$ and $y$.&#xD;&#xA;&#xD;&#xA;Now build up your collection of points $A$ successively:&#xD;&#xA;&#xD;&#xA;1. Select a random point $x$ and add two points, such that all three points form a equilateral triangle with edge length $d(x,x)$.&#xD;&#xA;&#xD;&#xA;2. Add all points to $A$ and mark them as adjacent.&#xD;&#xA;&#xD;&#xA;3. Repeatedly do the following until there are no adjacencies in $A$ anymore:&#xD;&#xA;&#xD;&#xA;  1. Select two adjacent points $x$ and $y$ from $A$. Mark them as non-adjacent.&#xD;&#xA;  1. Consider a point $z$ that has a distance of $d(x,y)$ from both these points. Of the two possible such points select the one pointing outwards of $A$ (this needs some work, but should be straightforward).&#xD;&#xA;  1. Check whether $z$ is closer than $d(x,y)$ to any point from $A$ that is still adjacent to another point.&#xD;&#xA;&#xD;&#xA;    * if yes, discard it.&#xD;&#xA;    * if no, mark $x$ and $z$ as well as $y$ and $z$ as adjacent and add $z$ to $A$.&#xD;&#xA;&#xD;&#xA;At the end, $A$ should be a collection of points matching your criteria. You sort-of just created a triangulation but it may be pathological and thus you should probably triangulate the points afresh." ContentLicense="CC BY-SA 3.0" />
  <row Id="3205" PostHistoryTypeId="24" PostId="291" RevisionGUID="f81c4447-833d-4bbd-b877-bd741dca4725" CreationDate="2015-11-03T17:35:30.317" Comment="Proposed by 137 approved by 127 edit id of 95" ContentLicense="CC BY-SA 3.0" />
  <row Id="3206" PostHistoryTypeId="5" PostId="312" RevisionGUID="07dc0818-f160-4fc6-809e-c5047fc230e6" CreationDate="2015-11-03T17:35:49.767" UserId="137" Comment="some more mathjax" Text="In most text books that I have seen, this is how the rendering equation is written:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$L_0( \omega_0)= L_e(\omega_0)+\int_{\Omega}{f(\omega_i, \omega_0)L_i(\omega_i)\,\mathrm{d}\omega_i}$$&#xD;&#xA;&#xD;&#xA;Where $\Omega$ is defined to be a hemisphere (and all those functions depend on more variables, omitted here for simplicity's sake).&#xD;&#xA;&#xD;&#xA;Now suppose the surface being rendered is some kind of glass, or some transparent plastic. Why would it make sense to only integrate over a hemisphere? I would imagine that there can be incoming light from any direction, and thus the integration domain should be the entire sphere. How is the light coming from behind the glass accounted for?&#xD;&#xA;&#xD;&#xA;[1]: http://latex.codecogs.com/gif.latex?L_o%28\omega_o%29%20%3D%20L_e%28\omega_o%29%20&amp;plus;\int_\Omega%20f%28\omega_i%2C%20\omega_o%29L_i%28\omega_i%29%20\%2C\mathrm{d}\omega_i" ContentLicense="CC BY-SA 3.0" />
  <row Id="3207" PostHistoryTypeId="24" PostId="312" RevisionGUID="07dc0818-f160-4fc6-809e-c5047fc230e6" CreationDate="2015-11-03T17:35:49.767" Comment="Proposed by 137 approved by 127 edit id of 93" ContentLicense="CC BY-SA 3.0" />
  <row Id="3208" PostHistoryTypeId="5" PostId="1637" RevisionGUID="93496b17-dae3-47a3-b014-a34619404e61" CreationDate="2015-11-03T19:03:47.043" UserId="1879" Comment="added 460 characters in body" Text="Given a 3D space and a light source, I use ray casting to determine the shadows generated in the scene. If I'm to store the shadow data (boundary of the shadow, object which cast the shadow, etc.) what is an efficient way to go about it?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA; Its basically for an application where I want to be able to move the shadow around manually to see the change in the 3d objects position. Say I apply a force to the shadow of a ball, I can actually see the ball move and also the change in the shadow. So I need to be able to set up colliders for the shadow and hence need a way to be able to store the boundary of the shadow and information about the object that cast it to carry out the actions." ContentLicense="CC BY-SA 3.0" />
  <row Id="3209" PostHistoryTypeId="5" PostId="1506" RevisionGUID="d355c852-1d75-4ec6-a419-8ac10326745d" CreationDate="2015-11-03T19:14:57.103" UserId="48" Comment="align the equal signs in the multi-line equation" Text="Here's a simple proof that the inverse transpose is required. Suppose we have a plane, defined by a plane equation $n \cdot x + d = 0$, where $n$ is the normal. Now I want to transform this plane by some matrix $M$. In other words, I want to find a new plane equation $n' \cdot Mx + d' = 0$ that is satisfied for exactly the same $x$ values that satisfy the previous plane equation.&#xD;&#xA;&#xD;&#xA;To do this, it suffices to set the two plane equations equal. (This gives up the ability to rescale the plane equations arbitrarily, but that's not important to the argument.) Then we can set $d' = d$ and subtract it out. What we have left is:&#xD;&#xA;&#xD;&#xA;$$n' \cdot Mx = n \cdot x$$&#xD;&#xA;&#xD;&#xA;I'll rewrite this with the dot products expressed in matrix notation (thinking of the vectors as 1-column matrices):&#xD;&#xA;&#xD;&#xA;$${n'}^T Mx = n^T x$$&#xD;&#xA;&#xD;&#xA;Now to satisfy this for _all_ $x$, we must have:&#xD;&#xA;&#xD;&#xA;$${n'}^T M = n^T$$&#xD;&#xA;&#xD;&#xA;Now solving for $n'$ in terms of $n$,&#xD;&#xA;&#xD;&#xA;$$\begin{aligned}{n'}^T &amp;= n^T M^{-1} \\&#xD;&#xA;n' &amp;= (n^T M^{-1})^T\\&#xD;&#xA;n' &amp;= (M^{-1})^T n\end{aligned}$$&#xD;&#xA;&#xD;&#xA;Presto! If points $x$ are transformed by a matrix $M$, then plane normals must transform by the inverse transpose of $M$ in order to preserve the plane equation.&#xD;&#xA;&#xD;&#xA;This is basically a property of the dot product. In order for the dot product to remain invariant when a transformation is applied, the two vectors being dotted have to transform in corresponding but different ways.&#xD;&#xA;&#xD;&#xA;Mathematically, this can be described by saying that the normal vector isn't an ordinary vector, but a thing called a [covector](https://en.wikipedia.org/wiki/Linear_form) (aka covariant vector, dual vector, or linear form). A covector is basically defined as &quot;a thing that can be dotted with a vector to produce an invariant scalar&quot;. In order to achieve that, it has to transform using the inverse transpose of whatever matrix is operating on ordinary vectors. This holds in any number of dimensions.&#xD;&#xA;&#xD;&#xA;Note that in 3D specifically, a bivector is similar to a covector. They're not *quite* the same since they have different units: a covector has units of inverse length while a bivector has units of length squared (area), so they behave differently under scaling. However, they do transform the same way with respect to their orientation, which is what matters for normals. We usually don't care about the magnitude of a normal (we always normalize them to unit length anyway), so we usually don't need to worry about the difference between a bivector and a covector." ContentLicense="CC BY-SA 3.0" />
  <row Id="3210" PostHistoryTypeId="5" PostId="347" RevisionGUID="9b4ef008-faaa-4c65-843c-437782bfdc01" CreationDate="2015-11-03T19:15:29.400" UserId="48" Comment="missing a couple dollar signs" Text="Fourier transforms wouldn't help you with a rotation. You'd just end up having to rotate the matrix of Fourier coefficients, instead of rotating the original image.&#xD;&#xA;&#xD;&#xA;Consider for example an image made of a perfect sine wave along the x-axis with wave-vector $(k, 0)$.  (The wave-vector is the spacial frequencies along the $x$ and $y$ axes).  The Fourier transform of this would be all black, with a single white pixel at position $(k, 0)$.&#xD;&#xA;&#xD;&#xA;When you rotate the image by an angle $\theta$, you'll get a perfect sine wave along an oblique axis.  If you draw a diagram and do a little trigonometry, you can see that the new wave-vector will be $(k \cos \theta, k \sin \theta)$.  (It helps for this part to know that the frequency $k$ is one over the period.)&#xD;&#xA;&#xD;&#xA;Therefore, the Fourier transform of the rotated result would be all black, with a single white pixel at position $(k \cos \theta, k \sin \theta)$.  But that's just what you'd get if you rotated the Fourier transform of the original wave by $\theta$.&#xD;&#xA;&#xD;&#xA;As for the Gibbs phenomenon, it's an issue when downsampling an image, or compressing it by frequency quantization (as in JPEG). But simply taking the Fourier transform of an image doesn't introduce any Gibbs ringing. The Fourier transform is lossless and perfectly reversible if done properly: it represents all the information in the original image." ContentLicense="CC BY-SA 3.0" />
  <row Id="3211" PostHistoryTypeId="5" PostId="348" RevisionGUID="15042e24-21b9-4d9d-aa82-ec5870ab44a2" CreationDate="2015-11-03T19:18:26.903" UserId="48" Comment="math formatting" Text="A 2D Fourier transform is performed by first doing a 1D Fourier transform on each row of the image, then taking the result and doing a 1D Fourier transform on each column.  Or vice versa; it doesn't matter.&#xD;&#xA;&#xD;&#xA;Just as a 1D Fourier transform allows you to decompose a function into a sum of (1D) sine waves at various frequencies, a 2D Fourier transform decomposes a function as a sum of 2D sine waves.  These waves can have different frequencies along the x and y axes.  They generically have the form:&#xD;&#xA;&#xD;&#xA;$$ \exp \bigl(i \cdot (k_x x + k_y y) \bigr) $$&#xD;&#xA;&#xD;&#xA;where $k_x$ and $k_y$ are the frequencies along the $x$ and $y$ axes. These two values form a vector called the wave-vector.  In the spatial domain, the wave is oriented along the $(k_x, k_y)$ vector with a frequency along its axis of $\sqrt{k_x^2 + k_y^2}$.&#xD;&#xA;&#xD;&#xA;Just as for the 1D Fourier transform, there exist both discrete and continuous versions.  The result of a discrete 2D Fourier transform is a matrix of complex amplitudes for a set of discrete $(k_x, k_y)$ values.  This is commonly visualized (like in the paper you linked to) as an image where the pixel at coordinates $(k_x, k_y)$ represents the amplitude of that wave-vector.&#xD;&#xA;&#xD;&#xA;So, an annular shape in a 2D Fourier transform indicates rotational invariance of the distribution of frequencies (i.e. just as much amplitude for waves in every direction), with a narrow range of magnitudes (from the inside of the annulus to the outside).  In other words, the paper is using the Fourier transform to demonstrate that their noise is reasonably isotropic and band-limited." ContentLicense="CC BY-SA 3.0" />
  <row Id="3212" PostHistoryTypeId="5" PostId="1448" RevisionGUID="39d2b398-0879-4f47-8f79-567969c18abd" CreationDate="2015-11-03T20:25:54.380" UserId="48" Comment="math formatting" Text="The notation Re() and Im() refer to the real and imaginary parts of a complex number.  Mathematicians and physicists are accustomed to using spherical harmonics (and Fourier transforms too) that are complex-valued, due to the factor $e^{im\phi}$.  You would then also have complex coefficients, in general, in the spherical harmonic expansion of a (real or complex) function.&#xD;&#xA;&#xD;&#xA;Using [Euler's formula](https://en.wikipedia.org/wiki/Euler's_formula), $e^{im\phi} = \cos(m\phi) + i\sin(m\phi)$.  So that factor encodes cosine and sine waves  (that oscillate $m$ times as you move around the equator of the sphere) in its real and imaginary parts, respectively.&#xD;&#xA;&#xD;&#xA;When we know we're going to be working strictly with real-valued functions, it may be more convenient to use real-valued variants of the spherical harmonics, where $e^{im\phi}$ is replaced by either $\cos(m\phi)$ or $\sin(m\phi)$, and using real coefficients instead of complex ones.  We trade a single complex coefficient for two real coefficients, so we haven't lost any information or flexibility; it's essentially a change of basis.  This formulation just explicitly ensures that everything always comes out real." ContentLicense="CC BY-SA 3.0" />
  <row Id="3213" PostHistoryTypeId="2" PostId="1681" RevisionGUID="bdfc6d18-b17c-4906-abbc-0b69ae1a7332" CreationDate="2015-11-03T20:49:40.587" UserId="1987" Text="I'm trying to implement an ocean scene with C++ and DirectX11. Currently I have a projected grid, Gerstner waves and a basic shading. My problem is that when I aim my camera horizontally, so I can see the water horizon, in the distance, the projected grid becomes insufficient, even at high vertex numbers. These screenshots illustrate the problem:&#xD;&#xA;&#xD;&#xA;[![shaded water surface][1]][1]&#xD;&#xA;&#xD;&#xA;[![wireframe water surface][2]][2]&#xD;&#xA;&#xD;&#xA;I know the cause of the problem is in the concept of the projected grid (the grid is detailed near the camera, rough far from it), but there has to be a best practice to solve this.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/F1Nqx.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1qsKc.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3214" PostHistoryTypeId="1" PostId="1681" RevisionGUID="bdfc6d18-b17c-4906-abbc-0b69ae1a7332" CreationDate="2015-11-03T20:49:40.587" UserId="1987" Text="Projected grid water horizon detail" ContentLicense="CC BY-SA 3.0" />
  <row Id="3215" PostHistoryTypeId="3" PostId="1681" RevisionGUID="bdfc6d18-b17c-4906-abbc-0b69ae1a7332" CreationDate="2015-11-03T20:49:40.587" UserId="1987" Text="|real-time|geometry|c++|directx11|grid|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3217" PostHistoryTypeId="2" PostId="1682" RevisionGUID="46018a7f-d0c3-4e18-8318-f03c15c3e1f9" CreationDate="2015-11-04T02:55:53.690" UserId="79" Text="I believe a common solution is to split the camera transform used to project the grid from the camera transform that is used to render the grid. At perspectives close to top-down, the two cameras coincide, but as the viewing camera gets close to a horizontal perspective, the projection camera deviates and tries to keep a minimum inclination, i.e. it hovers somewhere above the view camera and looks down slightly.&#xD;&#xA;&#xD;&#xA;The tricky bit is making sure that the field of view of the projection camera always covers the region of the scene seen from the render camera. I don't have a resource at hand that details how to compute the appropriate transforms, and it might be tedious to derive by hand.&#xD;&#xA;&#xD;&#xA;A different solution is to grab the signal processing toolbox: The artifacts seen in your image are essentially aliasing, caused by insufficient sampling of the wave heightfield by the projected grid. Therefore, one solution is to filter the heightfield appropriately, depending on the projected area of a grid cell. I believe this is used in offline rendering of oceans, and it essentially makes sure that waves at the horizon go flat. However, I'm not sure how feasible this is in real-time rendering, since you would need high-quality anisotropic filtering to make this approach look reasonable." ContentLicense="CC BY-SA 3.0" />
  <row Id="3220" PostHistoryTypeId="2" PostId="1683" RevisionGUID="251c98d8-521d-4113-903c-e51251e69103" CreationDate="2015-11-04T05:25:47.107" UserId="38" Text="Some software like Maya, solve this by using a polar (but not linear) grid centered on the camera position. This setup adds more detail where it counts most Then they rely on the shaders normal processing at further ranges. There is room for improvemenet offcourse. You cold modify this approach a bit, and have any other shape that increases the mesh density towards the camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The benefit of this is you can stretch the  effect up to the horizon without worryinf about the seam." ContentLicense="CC BY-SA 3.0" />
  <row Id="3221" PostHistoryTypeId="5" PostId="1683" RevisionGUID="1a7a2830-b0c2-42f7-b828-f057c9266adb" CreationDate="2015-11-04T05:35:31.823" UserId="38" Comment="added 115 characters in body" Text="Some software like Maya, solve this by using a polar (but not linear) grid centered on the camera position. This setup adds more detail where it counts most Then they rely on the shaders normal processing at further ranges. There is room for improvemenet offcourse. You cold modify this approach a bit, and have any other shape that increases the mesh density towards the camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The benefit of this is you can stretch the  effect up to the horizon without worrying about the seam. You also can gradually reduce the displacement by just normal modification in the pixel shader as you get further." ContentLicense="CC BY-SA 3.0" />
  <row Id="3228" PostHistoryTypeId="2" PostId="1685" RevisionGUID="0298b3d5-5f81-4f81-85c9-b0bf7dc833b4" CreationDate="2015-11-04T09:32:20.727" UserId="228" Text="In homogeneous coordinates i would do something like this:&#xD;&#xA;&#xD;&#xA;$$\vec{p} = \left(\frac{2}{x+y}, \frac{5y + z}{2x + 2y}, 3\right)^T = \left(\frac{2}{x+y}, \frac{\frac{5y + z}{2}}{x + y}, \frac{3x + 3y}{x + y}\right)^T$$ adding the fourth coordinate&#xD;&#xA;&#xD;&#xA;$$\vec{p}^H = \left(2, \frac{5y + z}{2}, 3x + 3y, x + y\right)^T = &#xD;&#xA;\begin{pmatrix} &#xD;&#xA; 0 &amp; 0 &amp; 0 &amp; 2 \\ &#xD;&#xA; 0 &amp; \frac{5}{2} &amp; \frac{1}{2} &amp; 0 \\&#xD;&#xA; 3 &amp; 3 &amp; 0 &amp; 0 \\&#xD;&#xA; 1 &amp; 1 &amp; 0 &amp; 0&#xD;&#xA;\end{pmatrix} \cdot \begin{pmatrix}x \\ y \\ z \\ 1\end{pmatrix}$$,&#xD;&#xA;&#xD;&#xA;If you want a systematic way, since a linear transformation is completely characterized from the transformation of a basis, take the canonical bases i.e.&#xD;&#xA;($\vec{e}^H_0 = (1,0,0,0), \vec{e}^H_1 = (0,1,0,0),...$) apply the transformation in $\vec{p}^H$ it will give you for $i = 0,...,3$ the columns of the matrix." ContentLicense="CC BY-SA 3.0" />
  <row Id="3229" PostHistoryTypeId="5" PostId="1551" RevisionGUID="c08c0d39-fcd9-453b-a1e8-4c5210705072" CreationDate="2015-11-04T13:48:25.293" UserId="209" Comment="Added missing information on extended ETC2 modes" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel and then a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant is, naturally, noisier than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3230" PostHistoryTypeId="2" PostId="1686" RevisionGUID="4bad5ec5-93d8-41ca-814c-f9605fe8094b" CreationDate="2015-11-04T15:47:36.557" UserId="196" Text="The [Multiple Scattering Microfacet BSDFs with the Smith Model][1] paper describes a statistical model for replacing the masking-shadowing functions in microfacet BSDFs (which account for paths with more than one surface intersection by setting their contribution to 0) with a distribution which can be path traced and allows the a ray to intersect a microfacet surface several times before exiting.&#xD;&#xA;&#xD;&#xA;They do this by modifying a volumetric (microflake) model to behave like a heightfield: to never collide with anything &quot;above&quot; the surface and to always collide with anything &quot;below&quot; the surface.&#xD;&#xA;&#xD;&#xA;[![Microsurface vs modified microflake volume][2]][2]&#xD;&#xA;&#xD;&#xA;The result, using wording from their slides, is that &quot;the ray can never go through the Smith volume; the model creates an opaque surface-like interface.&quot;&#xD;&#xA;&#xD;&#xA;Is this model compatible with traditional diffuse subsurface scattering, where a path can travel a perceptible (macro-scale) distance through a surface before exiting? Or is this simply a specular BSDF with no intention of modeling long paths internal to a surface, to be combined with a diffuse BSDF that adds that component?&#xD;&#xA;&#xD;&#xA;(Does the microflake model of volumetric rendering normally separate diffuse and specular, or is &quot;diffuse&quot; simply a path that bounces around so many times that the outgoing direction is uniformly distributed?)&#xD;&#xA;&#xD;&#xA;  [1]: https://eheitzresearch.wordpress.com/240-2/&#xD;&#xA;  [2]: https://i.stack.imgur.com/kTAw4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3231" PostHistoryTypeId="1" PostId="1686" RevisionGUID="4bad5ec5-93d8-41ca-814c-f9605fe8094b" CreationDate="2015-11-04T15:47:36.557" UserId="196" Text="How does Smith multiple scattering interact with diffuse subsurface scattering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3232" PostHistoryTypeId="3" PostId="1686" RevisionGUID="4bad5ec5-93d8-41ca-814c-f9605fe8094b" CreationDate="2015-11-04T15:47:36.557" UserId="196" Text="|brdf|scattering|subsurface-scattering|microfacet|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3233" PostHistoryTypeId="5" PostId="1551" RevisionGUID="43eb166d-9857-4321-b81d-c3f934743c7d" CreationDate="2015-11-04T16:09:10.813" UserId="209" Comment="had missed a verb" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant is, naturally, noisier than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3234" PostHistoryTypeId="2" PostId="1687" RevisionGUID="27280285-6dd8-4c51-9374-548d986ae897" CreationDate="2015-11-04T21:41:15.603" UserId="1994" Text="I need a source code that takes as input a COLLADA file and/or an OBJ file, and gives as output basic information about the file, such as file size, model dimension, volume and if possible texture issues." ContentLicense="CC BY-SA 3.0" />
  <row Id="3235" PostHistoryTypeId="1" PostId="1687" RevisionGUID="27280285-6dd8-4c51-9374-548d986ae897" CreationDate="2015-11-04T21:41:15.603" UserId="1994" Text="Is there any open code to get information about COLLADA or OBJ files?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3236" PostHistoryTypeId="3" PostId="1687" RevisionGUID="27280285-6dd8-4c51-9374-548d986ae897" CreationDate="2015-11-04T21:41:15.603" UserId="1994" Text="|implementation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3237" PostHistoryTypeId="5" PostId="1683" RevisionGUID="008592f0-36c1-4e2e-ae95-f87154f4f5a5" CreationDate="2015-11-04T21:52:47.867" UserId="38" Comment="added 258 characters in body" Text="Some software like Maya, solve this by using a polar (or actually cartesian that turns polar at a distance) much in the same way as you grid centered on the camera position. This setup adds more detail where it counts most Then they rely on the shaders normal processing at further ranges. There is room for improvemenet offcourse. You cold modify this approach a bit, and have any other shape that increases the mesh density towards the camera. The benefit of this is you can stretch the  effect up to the horizon without worrying about the seam. &#xD;&#xA;&#xD;&#xA;The trick to not get the displacenent jumbled up in this case is that you gradually reduce the displacement as you move further away. You then just use normal modification in the pixel shader as you get further. This is easier to filter than having to filter an accurate shiluette edge. Also if you can see that far away then your vawes are likely sufficiently flat anyway." ContentLicense="CC BY-SA 3.0" />
  <row Id="3238" PostHistoryTypeId="2" PostId="1688" RevisionGUID="c973e6d7-f4ae-4e74-8902-9b006d3f8477" CreationDate="2015-11-04T22:31:27.753" UserId="14" Text="**For OBJ Files**&#xD;&#xA;&#xD;&#xA;Free tools like [MeshLab][1], [Blender][2], and [GLC_Player][3] are able to load OBJ files and give you basic information about their content.&#xD;&#xA;&#xD;&#xA;Apparently, GLC_Player can also load COLLADA.&#xD;&#xA;&#xD;&#xA;In code you can use the following standard tools:&#xD;&#xA;&#xD;&#xA;1. [Assimp][4] - Library for loading many common formats including OBJ&#xD;&#xA;2. [TinyObjLoader][5] - .h/.cc only, no external dependencies&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://meshlab.sourceforge.net/&#xD;&#xA;  [2]: https://www.blender.org/&#xD;&#xA;  [3]: http://www.glc-player.net/&#xD;&#xA;  [4]: https://github.com/assimp/assimp&#xD;&#xA;  [5]: https://github.com/syoyo/tinyobjloader" ContentLicense="CC BY-SA 3.0" />
  <row Id="3240" PostHistoryTypeId="2" PostId="1689" RevisionGUID="d3082875-c947-4e24-aa24-d74329b0ba80" CreationDate="2015-11-05T01:57:04.717" UserId="79" Text="The goal of Heitz et al.'s model is pretty much the opposite of subsurface scattering: They only consider surface scattering, i.e. the ray can never enter the material.&#xD;&#xA;&#xD;&#xA;Because microfacets are statistical in nature, they can recast their problem in such a way that it can be solved by microflakes, which allows them to compute properties such as the mean free path to derive a heightfield sampling procedure. However, even though they use microflake theory, they still solve the same problem of multiple scattering on microfacets, and their result is still a BSDF, not a subsurface scattering model.&#xD;&#xA;&#xD;&#xA;Because it is a BSDF, the path exits at the same location as it hit the surface. This is also mentioned in the introduction:&#xD;&#xA;&gt; Note that our volume-scattering process models the interaction with a surface, but its application in rendering is virtual in that no displacements occur, i.e. the incident and exitant location are the same and the resulting plane-parallel radiometry produces a BSDF." ContentLicense="CC BY-SA 3.0" />
  <row Id="3245" PostHistoryTypeId="2" PostId="1691" RevisionGUID="b0267558-dac2-46f1-b2e1-d420304bfece" CreationDate="2015-11-05T10:08:52.910" UserId="385" Text="I have a spectral power distribution (SPD, 5 nm steps) for all light sources in the scene and SPDs for the reflectance of all surfaces under any light / viewer angle in question.&#xD;&#xA;&#xD;&#xA;I'm going to calculate in floating point precision and not clamp any values. Ignoring uncommon effects like dispersion, does it make a difference whether I render using the spectrum, XYZ color space or linear RGB color space?&#xD;&#xA;&#xD;&#xA;Specifically, is it invariant at which point (before or after multiplication of surface BRDF with light intensity) I integrate to convert spectrum to XYZ? Does the introduction of reference white in XYZ / RGB distort the colors when working with light sources of a different color / SPD?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3246" PostHistoryTypeId="1" PostId="1691" RevisionGUID="b0267558-dac2-46f1-b2e1-d420304bfece" CreationDate="2015-11-05T10:08:52.910" UserId="385" Text="How correct is rendering in XYZ / linear RGB space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3247" PostHistoryTypeId="3" PostId="1691" RevisionGUID="b0267558-dac2-46f1-b2e1-d420304bfece" CreationDate="2015-11-05T10:08:52.910" UserId="385" Text="|rendering|physically-based|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3248" PostHistoryTypeId="5" PostId="1691" RevisionGUID="fc76a944-14ce-416b-89a2-f7846ffb41c8" CreationDate="2015-11-05T11:36:46.390" UserId="385" Comment="Added sRGB clarification" Text="I have a spectral power distribution (SPD, 5 nm steps) for all light sources in the scene and SPDs for the reflectance of all surfaces under any light / viewer angle in question.&#xD;&#xA;&#xD;&#xA;I'm going to calculate in floating point precision and not clamp any values. Except for pathological cases like monochromatic light or special things like dispersion effects, does it make a difference whether I render using the spectrum, XYZ color space or linear RGB color space? Note that I will convert the result to sRGB as a last step in any case.&#xD;&#xA;&#xD;&#xA;Specifically, is it invariant at which point (before or after multiplication of surface BRDF with light intensity) I integrate to convert spectrum to XYZ? Does the introduction of reference white in XYZ / RGB distort the colors when working with light sources of a different color / SPD?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3249" PostHistoryTypeId="2" PostId="1692" RevisionGUID="5b794555-b4ff-466b-a6cf-85723ad391fd" CreationDate="2015-11-05T12:57:12.430" UserId="8" Text="This a follow up for a question I answered on gamedev SE. The question was simply [Is glDrawArraysInstanced in OpenGL parallel when drawing those instances?][1]&#xD;&#xA;&#xD;&#xA;My answer was in the lines of &quot;the GPU might execute multiple draw calls in parallel depending on multiple things, for instance if two draw calls use the same vertex shaders.&quot; [Here is the full answer][2].&#xD;&#xA;&#xD;&#xA;In the comments the OP mentioned, &quot;I think it should be sequential. After all, some of blending mode depends of sequence&quot;&#xD;&#xA;&#xD;&#xA;Now, I am little bit confused, is my answer of it will still parallelize them when it can valid? can someone clarify this ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/questions/110781/is-gldrawarraysinstanced-in-opengl-parallel-when-drawing-those-instances&#xD;&#xA;  [2]: http://gamedev.stackexchange.com/questions/110781/is-gldrawarraysinstanced-in-opengl-parallel-when-drawing-those-instances/110806#110806" ContentLicense="CC BY-SA 3.0" />
  <row Id="3250" PostHistoryTypeId="1" PostId="1692" RevisionGUID="5b794555-b4ff-466b-a6cf-85723ad391fd" CreationDate="2015-11-05T12:57:12.430" UserId="8" Text="Are draw calls executed in parallel or sequentially or both?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3251" PostHistoryTypeId="3" PostId="1692" RevisionGUID="5b794555-b4ff-466b-a6cf-85723ad391fd" CreationDate="2015-11-05T12:57:12.430" UserId="8" Text="|opengl|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3252" PostHistoryTypeId="2" PostId="1693" RevisionGUID="eb0c68f6-43ea-4cc9-84bb-39c415cbb074" CreationDate="2015-11-05T13:30:39.553" UserId="137" Text="The result should be *as if* it was executed sequentially one triangle at a time. This is important so that each frame is deterministic. If it wasn't then drawing the same frame multiple times could create different results and create a flickering image on screen.&#xD;&#xA;&#xD;&#xA;However that *does not mean parallelization is impossible*. Vertices can be computed in parallel. Their results will be ordered and fed to the rasterizer which will feed the fragment shader stage.&#xD;&#xA;&#xD;&#xA;The same happens with pixels. Typically a group of pixels from a triangle can be computed in parallel and blended. A non overlapping triangle can then also be filled at the same time however a overlapping triangle must have pixels in the overlapping area wait the corresponding pixels of the previous triangle are done." ContentLicense="CC BY-SA 3.0" />
  <row Id="3253" PostHistoryTypeId="5" PostId="82" RevisionGUID="960ccbe7-edb3-4d4a-bc3d-9131c39528b8" CreationDate="2015-11-05T14:42:21.157" UserId="231" Comment="MathJax where it improves clarity" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where Ft are Fresnel terms and R is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This R is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the $\|x_i - x_o\|$ above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;I am putting here the answers to a couple of @NathanReed 's questions in the comment section:&#xD;&#xA;&#xD;&#xA;&gt; Even with the diffusion profile approximation, the BSSRDF model still requires integrating over a radius of nearby points on the surface to gather incoming light, correct? How is that accomplished in, say, a path tracer? Do you have to build some data structure so you can sample points on the surface nearby a given point?&#xD;&#xA;&#xD;&#xA;The BSSRDF approximation still need to be integrated over a certain area, yes. &#xD;&#xA;&#xD;&#xA;In the paper linked they used a Montecarlo ray-tracer randomly sampling around a point with a density defined as: &#xD;&#xA;&#xD;&#xA;$\sigma_{tr}e^{-\sigma_{tr}d}$&#xD;&#xA;&#xD;&#xA;Where that sigma value is the effective extinction coefficient defined below ( it is dependent on scattering and absorbing coefficient, which are properties of the material) and d is the distance to the point we are evaluating. This density is this way defined because the diffusion term has exponential fall-off. &#xD;&#xA;&#xD;&#xA;In [\[Jensen and Buhler 2002\]][6] they proposed an acceleration technique. One of the main concepts was to decouple the sampling from the evaluation of the diffusion term. This way they perform a hierarchical evaluation of the information computed during the sampling phase to cluster together distant samples when it comes to evaluating the diffusion. The implementation described in the paper uses an octree as structure. &#xD;&#xA;This technique, according to the paper, is order of magnitude faster than the full Monte Carlo integration.  &#xD;&#xA;Unfortunately I never got myself into an off-line implementation, so I can't help more than this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the real-time sum-of-Gaussians approximations the correct radius is implicitly set when defining the variance of the Gaussian blurs that need to be applied.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&gt; Why one positive and one negative light? Is the goal for them to cancel each other in some way?&#xD;&#xA;&#xD;&#xA;Yes, the dipole source method (which dates way before Jensen's paper) is such defined to satisfy some boundary condition. Specifically the fluence must be zero at a certain extrapolated boundary that has a distance from the surface of 2AD where &#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Being F_dr the fresnel reflectivity of the slab considered and that sigma value is the reduced extinction coefficient described below. &#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/q48vD.png&#xD;&#xA;  [6]: http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/fast_bssrdf.pdf&#xD;&#xA;  [7]: https://i.stack.imgur.com/rOdqD.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3254" PostHistoryTypeId="5" PostId="1693" RevisionGUID="a1bbf4fe-52b8-43ed-b67f-f090bbd9d9b1" CreationDate="2015-11-05T14:46:13.837" UserId="137" Comment="added 77 characters in body" Text="The result should be *as if* it was executed sequentially one triangle at a time. This is important so that each frame is deterministic. If it wasn't then drawing the same frame multiple times could create different results and create a flickering image on screen.&#xD;&#xA;&#xD;&#xA;However that *does not mean parallelization is impossible*. Vertices can be computed in parallel. Their results will be ordered and fed to the rasterizer which will feed the fragment shader stage.&#xD;&#xA;&#xD;&#xA;The same happens with pixels. Typically a group of pixels from a triangle can be computed in parallel and blended. A non-overlapping triangle can then also be filled at the same time however if triangle overlaps one currently busy then the result of the fragment shader must be buffered until the corresponding pixels of the previous triangle are done so blending can happen in the correct order." ContentLicense="CC BY-SA 3.0" />
  <row Id="3256" PostHistoryTypeId="5" PostId="73" RevisionGUID="ad83191c-fb10-44ab-94c9-cb016832d113" CreationDate="2015-11-05T17:09:56.003" UserId="127" Comment="Made indices actual indices" Text="The idea i would try to apply would be the following, i make the example for the curve but it should be straightforward the application for the surface.&#xD;&#xA;&#xD;&#xA;Let's say we have a curve $\gamma$ uniformly parametrized, let's say the parameter of the curve is $s$. Your goal is to sample point corresponding to value of $s$ such that the curvature is high.&#xD;&#xA;&#xD;&#xA;If you get the magnitude of the curvature $c$ this will be function of $s$ too, so if you normalize the function $|c|$ you will get a probability distribution. If you get the integral of such distribution you will have the cumulative distribution, let's call the cumulative function $C(s)$.&#xD;&#xA;&#xD;&#xA;The sampling problem from a distribution given the cumulative function is well known, so basically once you have sampled a set of value $s_0,s_1,\dots,s_n$ such value will be related to the points of interest.&#xD;&#xA;&#xD;&#xA;The application of this method to the case of surface should be straight since basically you have a two dimensional cumulative distribution function, but the sampling problem is exactly the same.&#xD;&#xA;&#xD;&#xA;Just to give some detail... basically sampling from a distribution given the cumulative function involves two steps. &#xD;&#xA;&#xD;&#xA;1. take a random value in the interval $[0,1]$, let's say $k$ &#xD;&#xA;&#xD;&#xA;2. solve the equation $C(s) = k$.&#xD;&#xA;&#xD;&#xA;This approach is exact, of course it is expensive, but if you like such approach you can work on optimization." ContentLicense="CC BY-SA 3.0" />
  <row Id="3257" PostHistoryTypeId="5" PostId="1692" RevisionGUID="6371d668-0907-4d3a-bbfe-e899183d4a86" CreationDate="2015-11-05T20:20:08.097" UserId="127" Comment="Improved formatting" Text="This a follow up for a question I answered on GameDev SE. The question was simply [Is glDrawArraysInstanced in OpenGL parallel when drawing those instances?][1]&#xD;&#xA;&#xD;&#xA;My answer was in the lines of &quot;the GPU might execute multiple draw calls in parallel depending on multiple things, for instance if two draw calls use the same vertex shaders.&quot; [Here is the full answer][2].&#xD;&#xA;&#xD;&#xA;In the comments the OP mentioned, &quot;I think it should be sequential. After all, some of blending mode depends of sequence&quot;&#xD;&#xA;&#xD;&#xA;Now, I am little bit confused. Is my answer of *it will still parallelize them when it can* valid? Can someone clarify this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/questions/110781/is-gldrawarraysinstanced-in-opengl-parallel-when-drawing-those-instances&#xD;&#xA;  [2]: http://gamedev.stackexchange.com/questions/110781/is-gldrawarraysinstanced-in-opengl-parallel-when-drawing-those-instances/110806#110806" ContentLicense="CC BY-SA 3.0" />
  <row Id="3258" PostHistoryTypeId="5" PostId="82" RevisionGUID="d3538053-28e7-4493-88a1-d07f6f4dd862" CreationDate="2015-11-06T07:41:50.613" UserId="100" Comment="added 7 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where $F_t$ are Fresnel terms and $R$ is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This $R$ is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the $\|x_i - x_o\|$ above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;I am putting here the answers to a couple of @NathanReed 's questions in the comment section:&#xD;&#xA;&#xD;&#xA;&gt; Even with the diffusion profile approximation, the BSSRDF model still requires integrating over a radius of nearby points on the surface to gather incoming light, correct? How is that accomplished in, say, a path tracer? Do you have to build some data structure so you can sample points on the surface nearby a given point?&#xD;&#xA;&#xD;&#xA;The BSSRDF approximation still need to be integrated over a certain area, yes. &#xD;&#xA;&#xD;&#xA;In the paper linked they used a Montecarlo ray-tracer randomly sampling around a point with a density defined as: &#xD;&#xA;&#xD;&#xA;$\sigma_{tr}e^{-\sigma_{tr}d}$&#xD;&#xA;&#xD;&#xA;Where that sigma value is the effective extinction coefficient defined below ( it is dependent on scattering and absorbing coefficient, which are properties of the material) and d is the distance to the point we are evaluating. This density is this way defined because the diffusion term has exponential fall-off. &#xD;&#xA;&#xD;&#xA;In [\[Jensen and Buhler 2002\]][6] they proposed an acceleration technique. One of the main concepts was to decouple the sampling from the evaluation of the diffusion term. This way they perform a hierarchical evaluation of the information computed during the sampling phase to cluster together distant samples when it comes to evaluating the diffusion. The implementation described in the paper uses an octree as structure. &#xD;&#xA;This technique, according to the paper, is order of magnitude faster than the full Monte Carlo integration.  &#xD;&#xA;Unfortunately I never got myself into an off-line implementation, so I can't help more than this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the real-time sum-of-Gaussians approximations the correct radius is implicitly set when defining the variance of the Gaussian blurs that need to be applied.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&gt; Why one positive and one negative light? Is the goal for them to cancel each other in some way?&#xD;&#xA;&#xD;&#xA;Yes, the dipole source method (which dates way before Jensen's paper) is such defined to satisfy some boundary condition. Specifically the fluence must be zero at a certain extrapolated boundary that has a distance from the surface of 2AD where &#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Being F_dr the fresnel reflectivity of the slab considered and that sigma value is the reduced extinction coefficient described below. &#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/q48vD.png&#xD;&#xA;  [6]: http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/fast_bssrdf.pdf&#xD;&#xA;  [7]: https://i.stack.imgur.com/rOdqD.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3260" PostHistoryTypeId="2" PostId="1694" RevisionGUID="98260e08-3968-4318-8508-a871886906d9" CreationDate="2015-11-06T09:26:09.643" UserId="386" Text="I have some material which I want to represent as ф collection of spheres (atoms) and a particle of light (photon). I'm firing this particle and checking for the collision against atoms. What should happen if collision occurs? I see two possible solutions:&#xD;&#xA;&#xD;&#xA; 1. Light particle can be either absorbed or reflected, depends on some probability.&#xD;&#xA; 2. Light particle reflected, but loses some part of it's energy. When the energy is zero, particle is absorbed." ContentLicense="CC BY-SA 3.0" />
  <row Id="3261" PostHistoryTypeId="1" PostId="1694" RevisionGUID="98260e08-3968-4318-8508-a871886906d9" CreationDate="2015-11-06T09:26:09.643" UserId="386" Text="Does light particle loses energy when it hits something?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3262" PostHistoryTypeId="3" PostId="1694" RevisionGUID="98260e08-3968-4318-8508-a871886906d9" CreationDate="2015-11-06T09:26:09.643" UserId="386" Text="|lighting|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3265" PostHistoryTypeId="2" PostId="1696" RevisionGUID="fe54f259-2d4d-437d-a2b1-f92c34959152" CreationDate="2015-11-06T15:49:43.377" UserId="1810" Text="You can be both realistical and real-time. the secret is to change representation each time the information get under the Shannon-Nyquist (i.e. grid) scale: from geometry to normal maps to shading models. This paper is made for you: http://maverick.inria.fr/Publications/2010/BNH10/index.php (see also Yoube videos)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3266" PostHistoryTypeId="5" PostId="1694" RevisionGUID="363940da-55cf-4627-a595-99a799f49bb1" CreationDate="2015-11-06T16:25:41.327" UserId="386" Comment="added 555 characters in body" Text="I have some material which I want to represent as a collection of spheres (atoms) and a particle of light (photon). I'm firing this particle and checking for the collision against atoms. What should happen if collision occurs? I see two possible solutions:&#xD;&#xA;&#xD;&#xA; 1. Light particle can be either absorbed or reflected, depends on some probability.&#xD;&#xA; 2. Light particle reflected, but loses some part of it's energy. When the energy is zero, particle is absorbed.&#xD;&#xA;&#xD;&#xA;Update: I want to see the general behavior of the particle. The particle itself I want to simulate as a ray. Also I want to simulate a variety of materials - I think small spheres placed near each other can lead to specular material. Big spheres placed far from each other can lead to Lambertian material and subsurface scattering. The light transport is nor stochastic nor full valuated - a ray after collision will reflect correctly, not randomly. In the end I want to see the number of photons reflected, transmitted, scattered and their direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="3270" PostHistoryTypeId="2" PostId="1698" RevisionGUID="7f8e3dd0-76f1-4dd9-ba1c-035141fb8dc0" CreationDate="2015-11-07T10:17:34.330" UserId="113" Text="I can't really seem to figure out how to bind two constant buffers to my shaders. I have them described like so. One in slot b0 and the other in slot b1.&#xD;&#xA;&#xD;&#xA;    cbuffer WVPData : register(b0)&#xD;&#xA;    {&#xD;&#xA;	    matrix model;&#xD;&#xA;	    matrix view;&#xD;&#xA;	    matrix projection;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    cbuffer DirLightData : register(b1)&#xD;&#xA;    {&#xD;&#xA;       float4 Ambient;&#xD;&#xA;       float4 Diffuse;&#xD;&#xA;       float4 Specular;&#xD;&#xA;       float3 Direction;&#xD;&#xA;       float pad;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Then for the root signature it's described like so.&#xD;&#xA;&#xD;&#xA;    CD3DX12_DESCRIPTOR_RANGE range[2];&#xD;&#xA;    CD3DX12_ROOT_PARAMETER parameter[1];&#xD;&#xA;&#xD;&#xA;    range[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);&#xD;&#xA;    range[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 1);&#xD;&#xA;    parameter[0].InitAsDescriptorTable(_countof(range), range, D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;&#xD;&#xA;    D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =&#xD;&#xA;    D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer.&#xD;&#xA;    D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |&#xD;&#xA;    D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |&#xD;&#xA;    D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS;&#xD;&#xA;&#xD;&#xA;    CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;&#xD;&#xA;    descRootSignature.Init(_countof(parameter), parameter, 0, nullptr, rootSignatureFlags);&#xD;&#xA;&#xD;&#xA;    ComPtr&lt;ID3DBlob&gt; pSignature;&#xD;&#xA;    ComPtr&lt;ID3DBlob&gt; pError;&#xD;&#xA;    DX::ThrowIfFailed(D3D12SerializeRootSignature(&amp;descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf()));&#xD;&#xA;    DX::ThrowIfFailed(d3dDevice-&gt;CreateRootSignature(0, pSignature-&gt;GetBufferPointer(), pSignature-&gt;GetBufferSize(), IID_PPV_ARGS(&amp;mRootSignature)));&#xD;&#xA;&#xD;&#xA;I believe that's correct. I think the problem I have is when I create the constant buffer and the cbv below. Specifically right under the &quot;Describe and create the constant buffer view.&quot; comment. I don't really understand what's going on.&#xD;&#xA;&#xD;&#xA;    // Create a descriptor heap for the constant buffers.&#xD;&#xA;    {&#xD;&#xA;        D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};&#xD;&#xA;        heapDesc.NumDescriptors = 2;&#xD;&#xA;        heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;        // This flag indicates that this descriptor heap can be bound to the pipeline and that descriptors contained in it can be referenced by a root table.&#xD;&#xA;        heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;        DX::ThrowIfFailed(d3dDevice-&gt;CreateDescriptorHeap(&amp;heapDesc, IID_PPV_ARGS(&amp;mCbvHeap)));&#xD;&#xA;&#xD;&#xA;        mCbvHeap-&gt;SetName(L&quot;Constant Buffer View Descriptor Heap&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Create the constant buffer.&#xD;&#xA;    DX::ThrowIfFailed(d3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;      &amp;uploadHeapProperties,&#xD;&#xA;      D3D12_HEAP_FLAG_NONE,&#xD;&#xA;      &amp;CD3DX12_RESOURCE_DESC::Buffer(CAlignedWVPDataSize),&#xD;&#xA;      D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;      nullptr,&#xD;&#xA;      IID_PPV_ARGS(&amp;mWVPConstantBuffer)));&#xD;&#xA;&#xD;&#xA;    DX::ThrowIfFailed(d3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;      &amp;uploadHeapProperties,&#xD;&#xA;      D3D12_HEAP_FLAG_NONE,&#xD;&#xA;      &amp;CD3DX12_RESOURCE_DESC::Buffer(CAlignedDirLightDataSize),&#xD;&#xA;      D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;      nullptr,&#xD;&#xA;      IID_PPV_ARGS(&amp;mDirLightConstantBuffer)));&#xD;&#xA;&#xD;&#xA;    // Describe and create a constant buffer view.&#xD;&#xA;    D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc[2];// = {};&#xD;&#xA;    cbvDesc[0].BufferLocation = mWVPConstantBuffer-&gt;GetGPUVirtualAddress();&#xD;&#xA;    cbvDesc[0].SizeInBytes = CAlignedWVPDataSize;&#xD;&#xA;    cbvDesc[1].BufferLocation = mDirLightConstantBuffer-&gt;GetGPUVirtualAddress();&#xD;&#xA;    cbvDesc[1].SizeInBytes = CAlignedDirLightDataSize;&#xD;&#xA;&#xD;&#xA;    CD3DX12_CPU_DESCRIPTOR_HANDLE cbvHandle0(mCbvHeap-&gt;GetCPUDescriptorHandleForHeapStart(), 0, 0);&#xD;&#xA;    d3dDevice-&gt;CreateConstantBufferView(cbvDesc, cbvHandle0);&#xD;&#xA;&#xD;&#xA;    CD3DX12_CPU_DESCRIPTOR_HANDLE cbvHandle1(mCbvHeap-&gt;GetCPUDescriptorHandleForHeapStart(), d3dDevice-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV), 1);&#xD;&#xA;    d3dDevice-&gt;CreateConstantBufferView(cbvDesc, cbvHandle1);&#xD;&#xA;&#xD;&#xA;    // Initialize and map the constant buffers. We don't unmap this until the&#xD;&#xA;    // app closes. Keeping things mapped for the lifetime of the resource is okay.&#xD;&#xA;    DX::ThrowIfFailed(mWVPConstantBuffer-&gt;Map(0, nullptr, reinterpret_cast&lt;void**&gt;(&amp;mMappedWVPBuffer)));&#xD;&#xA;    memcpy(mMappedWVPBuffer, &amp;mWVPData, sizeof(mWVPData));  &#xD;&#xA;&#xD;&#xA;    DX::ThrowIfFailed(mDirLightConstantBuffer-&gt;Map(0, nullptr, reinterpret_cast&lt;void**&gt;(&amp;mMappedDirLightBuffer)));&#xD;&#xA;    memcpy(mMappedDirLightBuffer, &amp;mDirLightData, sizeof(mDirLightData));&#xD;&#xA;&#xD;&#xA;Note: Slot b0 works perfect. I can change world view projection data just fine. But b1 does not work at all. What am I doing wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3271" PostHistoryTypeId="1" PostId="1698" RevisionGUID="7f8e3dd0-76f1-4dd9-ba1c-035141fb8dc0" CreationDate="2015-11-07T10:17:34.330" UserId="113" Text="DirectX 12 Constant Buffer Binding" ContentLicense="CC BY-SA 3.0" />
  <row Id="3272" PostHistoryTypeId="3" PostId="1698" RevisionGUID="7f8e3dd0-76f1-4dd9-ba1c-035141fb8dc0" CreationDate="2015-11-07T10:17:34.330" UserId="113" Text="|c++|directx12|constant-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3274" PostHistoryTypeId="2" PostId="1699" RevisionGUID="f55ed989-dd7d-40ca-9227-1496cad1bfb5" CreationDate="2015-11-07T18:26:36.093" UserId="48" Text="The problem looks like it's in this line:&#xD;&#xA;&#xD;&#xA;    d3dDevice-&gt;CreateConstantBufferView(cbvDesc, cbvHandle1);&#xD;&#xA;&#xD;&#xA;The first parameter should be `&amp;cbvDesc[1]`. As it is now, you're setting up two copies of `cbvDesc[0]`.&#xD;&#xA;&#xD;&#xA;Also, it looks like you've reversed the second and third arguments to the `cbvHandle1` constructor: the second argument should be the offset (1) and the third should be the increment size. Not that it really matters, since those two values just get multiplied together anyway.&#xD;&#xA;&#xD;&#xA;By the way, I don't think you need to set up two separate descriptor ranges when creating the root signature; since they're contiguous, you could just use a single range of two descriptors. But it shouldn't make a difference to the results." ContentLicense="CC BY-SA 3.0" />
  <row Id="3276" PostHistoryTypeId="5" PostId="40" RevisionGUID="90416f22-ec93-4ee4-bbe7-b8a6787e58b3" CreationDate="2015-11-07T23:21:50.137" UserId="231" Comment="Add MathJax" Text="In general, a convolution is performed by taking the integral of the product of two functions in a sliding window, but if you're not from a math background, that's not a very helpful explanation, and certainly won't give you a useful intuition for it. More intuitively, a convolution allows multiple points in an input signal to affect a single point on an output signal.&#xD;&#xA;&#xD;&#xA;Since you're not super comfortable with convolutions, let's first review  what a convolution means in a discrete context like this, and then go over a simpler blur.&#xD;&#xA;&#xD;&#xA;In our discrete context, we can multiply our two signals by simply multiplying each corresponding sample. The integral is also simple to do discretely, we just add up each sample in the interval we're integrating over. One simple discrete convolution is computing a moving average. If you want to take the moving average of 10 samples, this can be thought of as convolving your signal by a distribution 10 samples long and 0.1 tall, each sample in the window first gets multiplied by 0.1, then all 10 are added together to produce the average. This also reveals an interesting and important distinction, when you're blurring with a convolution, the distribution that you use should sum to 1.0 over all its samples, otherwise it will increase or decrease the overall brightness of the image when you apply it. If the distribution for our average had been 1 over its whole interval, then the total signal would be 10x brighter after the convolution.&#xD;&#xA;&#xD;&#xA;Now that we've looked at convolutions, we can move on to blurs. A Gaussian blur is implemented by convolving an image by a Gaussian distribution. Other blurs are generally implemented by convolving the image by other distributions. The simplest blur is the box blur, and it uses the same distribution we described above, a box with unit area. If we want to blur a 10x10 area, then we multiply each sample in the box by 0.01, and then sum them all together to produce the center pixel. We still need to ensure that the total sum of all the samples in our blur distribution are 1.0 to make sure the image doesn't get brighter or darker.&#xD;&#xA;&#xD;&#xA;A Gaussian blur follows the same broad procedure as a box blur, but it uses a more complex formula to determine the weights. The distribution can be computed based on the distance from the center `r`, by evaluating $$\frac{e^{-x^2/2}}{\sqrt{2\pi}}$$ The sum of all the samples in a Gaussian will eventually be approximately 1.0 if you sample every single pixel, but the fact that a Gaussian has infinite support (it has values everywhere) means that you need to use a slightly modified version that sums to 1.0 using only a few values.&#xD;&#xA;&#xD;&#xA;Of course both of these processes can be very expensive if you perform them on a very large radius, since you need to sample a lot of pixels in order to compute the blur. This is where the final trick comes in: both a Gaussian blur and a box blur are what's called a &quot;separable&quot; blur. This means that if you perform the blur along one axis, and then perform it along the other axis, it produces the exact same result as if you'd performed it along both axes at the same time. This can be tremendously important. If your blur is 10px across, it requires 100 samples in the naive form, but only 20 when separated. The difference only gets bigger, since the combined blur is $O(n^2)$, while the separated form is $O(n)$." ContentLicense="CC BY-SA 3.0" />
  <row Id="3277" PostHistoryTypeId="2" PostId="1700" RevisionGUID="a0bc650c-202d-47ac-ac18-a1a46a7ba589" CreationDate="2015-11-08T23:43:16.020" UserId="1636" Text="If I want to model a large environment, how can I solve the problem of earth curvature and horizon ?&#xD;&#xA;&#xD;&#xA;I use an environment map for the sky, but for the ground what can I do ?&#xD;&#xA;&#xD;&#xA;Do I have to model the ground with a big plane, disk or a spherical cap ?&#xD;&#xA;&#xD;&#xA;Is there a general procedure to solve this problem in computer graphics ?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3278" PostHistoryTypeId="1" PostId="1700" RevisionGUID="a0bc650c-202d-47ac-ac18-a1a46a7ba589" CreationDate="2015-11-08T23:43:16.020" UserId="1636" Text="Earth curvature and horizon in modeling large scenes" ContentLicense="CC BY-SA 3.0" />
  <row Id="3279" PostHistoryTypeId="3" PostId="1700" RevisionGUID="a0bc650c-202d-47ac-ac18-a1a46a7ba589" CreationDate="2015-11-08T23:43:16.020" UserId="1636" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3280" PostHistoryTypeId="2" PostId="1701" RevisionGUID="cf5df196-8e94-4946-9e37-1d9befcac4f9" CreationDate="2015-11-09T00:13:20.613" UserId="137" Text="Having the horizon fall off is simply dropping the ground in the distance down somewhat.&#xD;&#xA;&#xD;&#xA;A point $x$ km away if you follow the curve of the planet will be $r-r\cdot \cos \frac{x}{r}$ down and $r\cdot \sin \frac{x}{r}$ out horizontally where $r$ is the radius of the planet you are modeling (~6.3k km for earth). In the vertex shader you can account for that before you apply the view and projection matrix.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3281" PostHistoryTypeId="5" PostId="42" RevisionGUID="cadb4b2d-5208-4d35-9811-90d1830bf857" CreationDate="2015-11-09T04:32:25.737" UserId="174" Comment="Add MathJax" Text="Here is the best article I've read on the topic:&#xD;&#xA;[_Efficient Gaussian blur with linear sampling_][1]. It addresses all your questions and is really accessible.&#xD;&#xA;&#xD;&#xA;For the layman very short explanation: Gaussian is a function with the nice property of being separable, which means that a 2D Gaussian function can be computed by combining two 1D Gaussian functions.&#xD;&#xA;&#xD;&#xA;So for a $n \times n$ size ($O(n^2)$), you only need to evaluate $2 \times n$ values ($O(n)$), which is significantly less. If your operation consists in reading a texture element (commonly called a *&quot;tap&quot;*), it is good news: less taps is cheaper because a texture fetch has a cost.&#xD;&#xA;&#xD;&#xA;That's why blurring algorithms use that property by doing two passes, one to blur horizontally by gathering the $n$ horizontal pixels, and one to blur vertically by gathering the $n$ vertical pixels. The result is the final blurred pixel color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3282" PostHistoryTypeId="24" PostId="42" RevisionGUID="cadb4b2d-5208-4d35-9811-90d1830bf857" CreationDate="2015-11-09T04:32:25.737" Comment="Proposed by 174 approved by 79, 56 edit id of 98" ContentLicense="CC BY-SA 3.0" />
  <row Id="3283" PostHistoryTypeId="5" PostId="55" RevisionGUID="6d8ef428-214b-4799-be45-39bbada34e08" CreationDate="2015-11-09T04:32:44.627" UserId="174" Comment="Add MathJax" Text="The most important thing to consider when implementing the Gaussian blur is, as others have pointed out, to separate the 2D convolution filter into two 1D convolutions because it brings the complexity down from $O(n^2)$ to $O(n)$.&#xD;&#xA;&#xD;&#xA;But there are two more tricks you might want to consider in an actual implementation:&#xD;&#xA;&#xD;&#xA;The filter has a certain radius and because of that, at the very borders, you will need to calculate with pixels which fall outside of the image. In such case, you could try one of the following: for the outside pixels you simply take the last possible value (i.e. the pixel at the very border, as in `max(x, 0)`. Or you could &quot;reflect&quot; the image towards outside (as in `x &lt; 0 ? -x : x`). Or you could simply stop at the border but then you would need to adjust the denominator in convolution filter so that it sums up to 1. For example:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\operatorname{sum}&#xD;&#xA;\frac{1}{256}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 4  &amp; 6  &amp; 4  &amp; 1 \\&#xD;&#xA;4 &amp; 16 &amp; 24 &amp; 16 &amp; 4 \\&#xD;&#xA;6 &amp; 24 &amp; 36 &amp; 24 &amp; 6 \\&#xD;&#xA;4 &amp; 16 &amp; 24 &amp; 16 &amp; 4 \\&#xD;&#xA;1 &amp; 4  &amp; 6  &amp; 4  &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\operatorname{sum}&#xD;&#xA;\frac{1}{225}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 &amp; 0  &amp; 0  &amp; 0  &amp; 0 \\&#xD;&#xA;0 &amp; 16 &amp; 24 &amp; 16 &amp; 0 \\&#xD;&#xA;0 &amp; 24 &amp; 36 &amp; 16 &amp; 0 \\&#xD;&#xA;0 &amp; 16 &amp; 24 &amp; 16 &amp; 0 \\&#xD;&#xA;0 &amp; 0  &amp; 0  &amp; 0  &amp; 0 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= 1.&#xD;&#xA;$$&#xD;&#xA;Another trick concerns how to calculate the actual coefficients of the kernel. Obviously you could try to implement the [Gaussian function](https://en.wikipedia.org/wiki/Gaussian_function) but much faster way is to observe that the 1D kernel reassembles [Pascal's triangle](https://en.wikipedia.org/wiki/Pascal%27s_triangle). For example:&#xD;&#xA;&#xD;&#xA;         1&#xD;&#xA;        1 1&#xD;&#xA;       1 2 1&#xD;&#xA;      1 3 3 1&#xD;&#xA;    [1 4 6 4 1]&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3284" PostHistoryTypeId="24" PostId="55" RevisionGUID="6d8ef428-214b-4799-be45-39bbada34e08" CreationDate="2015-11-09T04:32:44.627" Comment="Proposed by 174 approved by 79, 56 edit id of 97" ContentLicense="CC BY-SA 3.0" />
  <row Id="3286" PostHistoryTypeId="2" PostId="1702" RevisionGUID="87429d09-bc4e-4e4c-95fc-5cb732ff4175" CreationDate="2015-11-10T06:18:54.503" UserId="141" Text="Could anyone please explain to me how drawing works with respect to scrolling?&#xD;&#xA;&#xD;&#xA;Suppose there is a window, which has an area where one can draw to (a &quot;canvas&quot;). Are there two copies of this canvas? One for CPU and one for GPU? I mean, I know one could copy from main memory to graphic card memory very quickly with OpenGL (PBO) so one way to draw is first draw with software in main memory and the &quot;blit&quot; it to GPU, right?&#xD;&#xA;&#xD;&#xA;Now, I would assume that when the window scrolls there is some GPU functionality which would rapidly copy over the non-dirty parts in the appropriate positions without leaving GPU-land and then ask the CPU for redrawing the dirty/missing parts. But now I have two un-synced copies of the canvas! So how does it work? Do I do the scrolling in main memory in software and upload the whole canvas to GPU as the first time? Or perhaps I scroll the canvas in GPU and &quot;download&quot; then download it to CPU-land and &quot;repair&quot; it there? Or something else entirely? Perhaps somehow I don't have to care that the copies are unsynchronized?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3287" PostHistoryTypeId="1" PostId="1702" RevisionGUID="87429d09-bc4e-4e4c-95fc-5cb732ff4175" CreationDate="2015-11-10T06:18:54.503" UserId="141" Text="Blit and scroll" ContentLicense="CC BY-SA 3.0" />
  <row Id="3288" PostHistoryTypeId="3" PostId="1702" RevisionGUID="87429d09-bc4e-4e4c-95fc-5cb732ff4175" CreationDate="2015-11-10T06:18:54.503" UserId="141" Text="|gpu|drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3289" PostHistoryTypeId="2" PostId="1703" RevisionGUID="b4fd4ba1-2d3d-4992-8b29-b75d055b58fc" CreationDate="2015-11-10T15:27:38.280" UserId="2024" Text="I am trying to implement (in C#) an image perturbation algorithm presented in the book &quot;Texturing and modeling - K. Perlin et al&quot; (page 91 if anyone has it), which distorts an image.&#xD;&#xA;The following code is in Renderman language:&#xD;&#xA;the texture access&#xD;&#xA;&#xD;&#xA;&lt;code&gt;Ct = texture(&quot;example.tx&quot;, s, t);&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;is replaced by&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&lt;code&gt;point Psh;&#xD;&#xA;float ss, tt;&#xD;&#xA;Psh = transform(&quot;shader&quot;, P);&#xD;&#xA;ss = s + 0.2 * snoise(Psh);&#xD;&#xA;tt = t + 0.2 * snoise(Psh+(l.5,6.7,3.4));&#xD;&#xA;Ct = texture(&quot;example.tx&quot;, ss, tt);&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&#xD;&#xA;transforming the image on the left to that on the right&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;from what I undestood, instead of accessing coordinate $(s,t)\in[0,1]$ we access slighty perturbed coordinates $(ss,tt)$ and display them at place $(s,t)$, thus creating an image that looks slightly perturbed&#xD;&#xA;&#xD;&#xA;$snoise(x)$ is defined as $(noise(x)*2)-1$, mapping noise from $[0,1]$ to $[-1,1]$, and in the RenderMan documentation $noise(P)$ where P is a point, returns a value based on some noise (most likely perlin or lattice).&#xD;&#xA;(http://renderman.pixar.com/resources/current/RenderMan/noiseFunctions.html)&#xD;&#xA;&#xD;&#xA;what I don't understand is what the transform function does, which is supposed to map the 3d point P into the &quot;shader&quot; space, and how can it be implemented.&#xD;&#xA;Also, I'm not sure whether noise(x) returns a 3d point, a float (would make more sense) and if I can use a simple 2d implementation of Perlin's noise to reach the same desired effect.&#xD;&#xA;&#xD;&#xA;Many thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vxxJX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3290" PostHistoryTypeId="1" PostId="1703" RevisionGUID="b4fd4ba1-2d3d-4992-8b29-b75d055b58fc" CreationDate="2015-11-10T15:27:38.280" UserId="2024" Text="Perturbed image texture implementation from renderman language" ContentLicense="CC BY-SA 3.0" />
  <row Id="3291" PostHistoryTypeId="3" PostId="1703" RevisionGUID="b4fd4ba1-2d3d-4992-8b29-b75d055b58fc" CreationDate="2015-11-10T15:27:38.280" UserId="2024" Text="|rendering|texture|algorithm|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3292" PostHistoryTypeId="2" PostId="1704" RevisionGUID="a2a80ccf-0043-4df2-9a36-4076377d2e1e" CreationDate="2015-11-10T16:52:41.847" UserId="310" Text="Traditionally, there are two ways to display something on the screen:&#xD;&#xA;&#xD;&#xA; 1. Re-draw it from scratch every frame (or, every time something changes)&#xD;&#xA; 2. Track the sections of the screen (ie. &quot;dirty rectangles&quot;) that change each frame, and update only those portions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The first option is what most modern games / animations will do. Each frame, you re-submit all the draw calls / re-upload any textures to the GPU that have changed, then ask the GPU to draw everything and show it on the screen.&#xD;&#xA;&#xD;&#xA;The second option is what most old 2D games did, as well as most window applications (ie. GUI programs that don't have a lot of change going on). One implementation would be to have a local CPU copy of the screen, a GPU copy, and a series of buffers to transfer data between them.&#xD;&#xA;So for every frame where there were changes:&#xD;&#xA;&#xD;&#xA; 1. Blit pixel data of the dirty rectangle areas to one of the data transfer buffers. &#xD;&#xA; 2. Copy the buffer to the GPU&#xD;&#xA; 3. Use the GPU to blit the pixel data from the data transfer buffer to the GPU copy.&#xD;&#xA; 4. Present&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For more info, I suggest looking up how some window managers do compositing. There is a decent explaination of how WPF works [here][1]. And an excellent post about how Chrome accelerates their browser rendering [here][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jeremiahmorrill.wordpress.com/2011/02/14/a-critical-deep-dive-into-the-wpf-rendering-system/&#xD;&#xA;  [2]: https://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome" ContentLicense="CC BY-SA 3.0" />
  <row Id="3293" PostHistoryTypeId="5" PostId="1703" RevisionGUID="c0ee73db-b08d-49e3-909b-301779100cb5" CreationDate="2015-11-10T16:54:52.340" UserId="127" Comment="Removed salutation, edited capitalization and punctuation" Text="I am trying to implement (in C#) an image perturbation algorithm presented in the book &quot;Texturing and modeling - K. Perlin et al&quot; (page 91 if anyone has it), which distorts an image.&#xD;&#xA;The following code is in Renderman language:&#xD;&#xA;The texture access&#xD;&#xA;&#xD;&#xA;&lt;code&gt;Ct = texture(&quot;example.tx&quot;, s, t);&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;is replaced by&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&lt;code&gt;point Psh;&#xD;&#xA;float ss, tt;&#xD;&#xA;Psh = transform(&quot;shader&quot;, P);&#xD;&#xA;ss = s + 0.2 * snoise(Psh);&#xD;&#xA;tt = t + 0.2 * snoise(Psh+(l.5,6.7,3.4));&#xD;&#xA;Ct = texture(&quot;example.tx&quot;, ss, tt);&lt;/code&gt;&lt;/pre&gt;&#xD;&#xA;&#xD;&#xA;transforming the image on the left to that on the right.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;From what I undestood, instead of accessing coordinate $(s,t)\in[0,1]$ we access slighty perturbed coordinates $(ss,tt)$ and display them at place $(s,t)$, thus creating an image that looks slightly perturbed.&#xD;&#xA;&#xD;&#xA;$snoise(x)$ is defined as $(noise(x)*2)-1$, mapping noise from $[0,1]$ to $[-1,1]$, and in the RenderMan documentation $noise(P)$ where P is a point, returns a value based on some noise (most likely perlin or lattice).&#xD;&#xA;(http://renderman.pixar.com/resources/current/RenderMan/noiseFunctions.html)&#xD;&#xA;&#xD;&#xA;What I don't understand is what the transform function does, which is supposed to map the 3d point P into the &quot;shader&quot; space, and how can it be implemented.&#xD;&#xA;Also, I'm not sure whether noise(x) returns a 3d point, a float (would make more sense) and if I can use a simple 2d implementation of Perlin's noise to reach the same desired effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vxxJX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3294" PostHistoryTypeId="5" PostId="1700" RevisionGUID="075e6c06-3aa7-497a-8d0f-f23e2ac5f0f8" CreationDate="2015-11-10T16:57:18.720" UserId="127" Comment="Removed unnecessary blanks" Text="If I want to model a large environment, how can I solve the problem of earth curvature and horizon?&#xD;&#xA;&#xD;&#xA;I use an environment map for the sky, but for the ground what can I do?&#xD;&#xA;&#xD;&#xA;Do I have to model the ground with a big plane, disk or a spherical cap?&#xD;&#xA;&#xD;&#xA;Is there a general procedure to solve this problem in computer graphics?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3299" PostHistoryTypeId="2" PostId="1706" RevisionGUID="dcf9b052-3895-4b81-9b82-4bd68b14313c" CreationDate="2015-11-11T04:18:18.883" UserId="113" Text="With directX12 they introduced heap descriptors. A way for us to describe the table for resources we wanted to send to the shaders. I'm admittedly very new at computer graphics and only tinkered a bit in directX11. I have not toyed with instancing or any more complicated things right now so I have a object for every mesh that has these defintions.&#xD;&#xA;&#xD;&#xA;    Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; mVertexBuffer;&#xD;&#xA;    D3D12_VERTEX_BUFFER_VIEW mVertexBufferView;&#xD;&#xA;&#xD;&#xA;    // Index Buffer&#xD;&#xA;    Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; mIndexBuffer;&#xD;&#xA;    D3D12_INDEX_BUFFER_VIEW mIndexBufferView;&#xD;&#xA;&#xD;&#xA;    // World View Projection Constant Buffer&#xD;&#xA;    Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; mWVPConstantBuffer;&#xD;&#xA;    WVPData mWVPData;      &#xD;&#xA;    UINT8* mMappedWVPBuffer;&#xD;&#xA;&#xD;&#xA;    // Directional Light Constant Buffer&#xD;&#xA;    Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; mDirLightConstantBuffer;&#xD;&#xA;    DirLightData mDirLightData;&#xD;&#xA;    UINT8* mMappedDirLightBuffer;&#xD;&#xA;&#xD;&#xA;    // CBVHeap&#xD;&#xA;    Microsoft::WRL::ComPtr&lt;ID3D12DescriptorHeap&gt; mCbvHeap;&#xD;&#xA;    UINT mCbvDescriptorSize;&#xD;&#xA;&#xD;&#xA;A vertex buffer, index buffer, the cbvHeap, and two constant buffers. One for the transformation matrices and one for the directional light data. &#xD;&#xA;&#xD;&#xA;I wasn't really sure what the cbvHeap (constant buffer view heap) was really doing. I just knew how to use it to my content to the screen. So I experimented. I took the cbvHeap and mCbvDescriptorSize out of the mesh object and put it in the scene object (where the array of meshes were contained) and then used the same cbvheap across all my meshes. This did not work as it gave one consistent color across the whole mesh. (ie: The same constant buffer was used for every mesh giving them the same diffuse and ambient light data.) What exactly is the descriptor heap doing that caused this? And are my definitions right per mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3300" PostHistoryTypeId="1" PostId="1706" RevisionGUID="dcf9b052-3895-4b81-9b82-4bd68b14313c" CreationDate="2015-11-11T04:18:18.883" UserId="113" Text="DirectX12 CbvHeap" ContentLicense="CC BY-SA 3.0" />
  <row Id="3301" PostHistoryTypeId="3" PostId="1706" RevisionGUID="dcf9b052-3895-4b81-9b82-4bd68b14313c" CreationDate="2015-11-11T04:18:18.883" UserId="113" Text="|c++|directx12|constant-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3302" PostHistoryTypeId="2" PostId="1707" RevisionGUID="e661048e-21dd-4ea2-abb2-9eb02c338a8f" CreationDate="2015-11-11T22:47:47.257" UserId="48" Text="In DX12, a descriptor is a small record, basically a pointer, that tells the GPU where to find some data such as a constant buffer. Since each object is going to have its own constant buffer data with its own particular transforms, lighting/material properties, etc., each object also has to end up with a separate set of descriptors to point to its individual data.&#xD;&#xA;&#xD;&#xA;There are a couple of ways to set up descriptors in DX12. First, you can add commands in a command list that update descriptors directly in the root table. For example, you can use [`SetGraphicsRootConstantBufferView()`](https://msdn.microsoft.com/en-us/library/windows/desktop/dn903911.aspx) to set up descriptors for an object's constant buffers, then draw the object. Repeat for multiple objects. These descriptors will be saved in the command list, and will get applied in-order as the command list is executed on the GPU.&#xD;&#xA;&#xD;&#xA;The other way to do it is use descriptor heaps. A descriptor heap is basically a buffer that stores an array of descriptors. With this approach, the command list doesn't save descriptors for you; you have to manage them yourself. If you overwrite any descriptors before the GPU consumes them, then you'll get wrong results. This sounds like what's happening in your program: you're likely overwriting the same descriptor in the heap every time you issue an object's draw commands on the CPU, so by the time the GPU executes the command list, only the last descriptor written is still there, and that descriptor gets applied to all of the objects.&#xD;&#xA;&#xD;&#xA;To fix this, you have to allocate enough space in the descriptor heap to store all the descriptors you're going to use for the frame. Write all the objects' descriptors to the heap. Then when drawing each object, point the shader at the that object's data using [`SetGraphicsRootDescriptorTable()`](https://msdn.microsoft.com/en-us/library/windows/desktop/dn903912.aspx) with an offset handle that points to the spot in the heap where that object's descriptors live.&#xD;&#xA;&#xD;&#xA;As long as you're still just trying to learn and get a simple app running, I would probably stick with the root table approach as much as possible. For a more serious high-performance app, there are probably optimizations you can do with descriptor heaps, such as keeping all the constants and textures for a given material together so you can reuse them across many objects and bind them all in one call. You'd probably also want to avoid having a constant buffer and descriptor heap per object, but rather aggregate many objects' data into a few large buffers; this will be more efficient when you have lots of objects.&#xD;&#xA;&#xD;&#xA;It's also worth noting that a serious 3D app will want to have multiple frames' command lists in flight at the same time, to obtain CPU/GPU parallelism, and this will require constant buffers and descriptor heaps to be lengthened to store multiple frames' worth of data. Again, this is something you can gloss over for learning/bringup purposes by just building a single command list at a time, submitting it, and waiting for it to finish before going on to the next frame." ContentLicense="CC BY-SA 3.0" />
  <row Id="3304" PostHistoryTypeId="2" PostId="1708" RevisionGUID="813d1b69-d394-4aa3-9bfe-25469607266c" CreationDate="2015-11-12T10:42:17.850" UserId="2040" Text="Let's say I have an image of an object against a white background. I want to crop so that the image fills the available space.&#xD;&#xA;This takes 10px off:&#xD;&#xA;&#xD;&#xA;    convert original.png -shave 10x10 shaved.png&#xD;&#xA;&#xD;&#xA;How would I implement something like this that detects the edges of the object, thus cropping a variable number of pixels from each side?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3305" PostHistoryTypeId="1" PostId="1708" RevisionGUID="813d1b69-d394-4aa3-9bfe-25469607266c" CreationDate="2015-11-12T10:42:17.850" UserId="2040" Text="How to crop with edge-detection using imagemagick" ContentLicense="CC BY-SA 3.0" />
  <row Id="3306" PostHistoryTypeId="3" PostId="1708" RevisionGUID="813d1b69-d394-4aa3-9bfe-25469607266c" CreationDate="2015-11-12T10:42:17.850" UserId="2040" Text="|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3307" PostHistoryTypeId="5" PostId="82" RevisionGUID="e2e4fc22-cc10-46db-ab08-f46722596b5c" CreationDate="2015-11-12T11:18:57.520" UserId="100" Comment="added 6 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where $F_t$ are Fresnel terms and $R$ is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This $R$ is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the $\|x_i - x_o\|$ above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;I am putting here the answers to a couple of @NathanReed 's questions in the comment section:&#xD;&#xA;&#xD;&#xA;&gt; Even with the diffusion profile approximation, the BSSRDF model still requires integrating over a radius of nearby points on the surface to gather incoming light, correct? How is that accomplished in, say, a path tracer? Do you have to build some data structure so you can sample points on the surface nearby a given point?&#xD;&#xA;&#xD;&#xA;The BSSRDF approximation still need to be integrated over a certain area, yes. &#xD;&#xA;&#xD;&#xA;In the paper linked they used a Montecarlo ray-tracer randomly sampling around a point with a density defined as: &#xD;&#xA;&#xD;&#xA;$\sigma_{tr}e^{-\sigma_{tr}d}$&#xD;&#xA;&#xD;&#xA;Where that sigma value is the effective extinction coefficient defined below ( it is dependent on scattering and absorbing coefficient, which are properties of the material) and d is the distance to the point we are evaluating. This density is this way defined because the diffusion term has exponential fall-off. &#xD;&#xA;&#xD;&#xA;In [\[Jensen and Buhler 2002\]][6] they proposed an acceleration technique. One of the main concepts was to decouple the sampling from the evaluation of the diffusion term. This way they perform a hierarchical evaluation of the information computed during the sampling phase to cluster together distant samples when it comes to evaluating the diffusion. The implementation described in the paper uses an octree as structure. &#xD;&#xA;This technique, according to the paper, is order of magnitude faster than the full Monte Carlo integration.  &#xD;&#xA;Unfortunately I never got myself into an off-line implementation, so I can't help more than this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the real-time sum-of-Gaussians approximations the correct radius is implicitly set when defining the variance of the Gaussian blurs that need to be applied.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&gt; Why one positive and one negative light? Is the goal for them to cancel each other in some way?&#xD;&#xA;&#xD;&#xA;Yes, the dipole source method (which dates way before Jensen's paper) is such defined to satisfy some boundary condition. Specifically the fluence must be zero at a certain extrapolated boundary that has a distance from the surface of $2AD$ where &#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Being $F_{dr}$ the fresnel reflectivity of the slab considered and that sigma value is the reduced extinction coefficient described below. &#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/q48vD.png&#xD;&#xA;  [6]: http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/fast_bssrdf.pdf&#xD;&#xA;  [7]: https://i.stack.imgur.com/rOdqD.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3308" PostHistoryTypeId="2" PostId="1709" RevisionGUID="a64b6af9-ed92-48ee-89f3-10b794f6cb9b" CreationDate="2015-11-12T13:36:52.010" UserId="192" Text="Try `-trim` instead of `-shave`:&#xD;&#xA;&#xD;&#xA;    convert original.png -trim trimmed.png&#xD;&#xA;&#xD;&#xA;See the [docs](http://www.imagemagick.org/Usage/crop/#trim) for this and other options.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3309" PostHistoryTypeId="2" PostId="1710" RevisionGUID="244b68d8-a1a3-4b0e-8717-bbfe8ec2d83f" CreationDate="2015-11-12T13:40:36.583" UserId="2041" Text="As you've surmised, the `transform()` function transforms points from one co-ordinate space to another. (There are also `vtransform()` and `ntransform()` for transforming direction vectors and normal vectors, respectively.) The string argument names the co-ordinate space to transform into.&#xD;&#xA;&#xD;&#xA;The [Renderman Shading Guidelines](http://renderman.pixar.com/resources/current/RenderMan/rslGuidelines97.html#part-2-coordinate-spaces) have this to say about it:&#xD;&#xA;&#xD;&#xA;&gt; At the start of shader execution, all point, vector, normal, and matrix variables are expressed in the &quot;current&quot; coordinate system. Exactly which coordinate system is &quot;current&quot; is implementation-dependent. It just so happens to be that &quot;current&quot; is &quot;camera&quot; for PRMan*, but you should never count on this behavior - it is entirely possible that other RenderMan compliant renderers (including future renderers from Pixar) may use some other space (like &quot;world&quot;) as &quot;current&quot; space.&#xD;&#xA;&#xD;&#xA;It goes on to give a case like this as an example. Most lighting calculations should be done in camera space, but evaluating a noise function should be in the object's co-ordinate system, because you want the noise to stay the same as the object moves through world space.&#xD;&#xA;&#xD;&#xA;In your C# implementation, you'll also need to transform the point being shaded from camera space to the object's co-ordinate system. Maybe you've done this already before computing the texture co-ordinates. If not, you'll need to multiply by the object's transformation matrix. Remember that the only use of this transformed point is as an input (like a seed) to the Perlin noise generator. It sets the domain that the noise varies over: world space co-ordinates.&#xD;&#xA;&#xD;&#xA;In RSL, the `noise()` function can return any type you like: a `float`, a `color`, a `point`, or a `vector`. As you're adding it to another `float` (`u` or `v`), you'll get a `float` in this code. Really, the two `noise()` calls, added to `s` and `t`, are acting to generate a single 2D noise vector. In your own code, if you are using a 2D vector to store your texture co-ordinates, you can use a single noise function that returns a 2D vector, to get the same effect in one line of code.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If you're interested in making a nice noise generator, [Shadertoy](https://www.shadertoy.com/results?query=noise) has a lot of noise shaders featuring different variants of Perlin noise with different properties (isotropic or not, configurable smoothness and bandwidth) and is worth looking at for inspiration as well as implementation hints." ContentLicense="CC BY-SA 3.0" />
  <row Id="3310" PostHistoryTypeId="6" PostId="1703" RevisionGUID="023ddd6e-ac75-4919-a161-fb47c476c415" CreationDate="2015-11-12T14:54:50.120" UserId="16" Comment="edited tags" Text="|rendering|texture|algorithm|noise|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3312" PostHistoryTypeId="2" PostId="1711" RevisionGUID="21982154-f2b0-43ef-9165-0e84fb094bcd" CreationDate="2015-11-12T17:01:58.687" UserId="2049" Text="You can use OpenGl 4.x tessellation shaders to convert Bezier control points into polygons." ContentLicense="CC BY-SA 3.0" />
  <row Id="3317" PostHistoryTypeId="2" PostId="1713" RevisionGUID="6463ed57-32c8-448d-ac0d-32ddb6a4bcc1" CreationDate="2015-11-13T06:01:34.150" UserId="2055" Text="please help me tackle the below question&#xD;&#xA;Explain THREE forms of affine transformations using relevant examples for each case.&#xD;&#xA;the answers i already give are scaling, rotation and reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="3318" PostHistoryTypeId="1" PostId="1713" RevisionGUID="6463ed57-32c8-448d-ac0d-32ddb6a4bcc1" CreationDate="2015-11-13T06:01:34.150" UserId="2055" Text="what are forms of affine transformations, give relevant examples for each case" ContentLicense="CC BY-SA 3.0" />
  <row Id="3319" PostHistoryTypeId="3" PostId="1713" RevisionGUID="6463ed57-32c8-448d-ac0d-32ddb6a4bcc1" CreationDate="2015-11-13T06:01:34.150" UserId="2055" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3320" PostHistoryTypeId="2" PostId="1714" RevisionGUID="62b3fea8-3336-4b06-a7bc-ec680a357c27" CreationDate="2015-11-13T09:32:27.343" UserId="100" Text="Affine transformations (surprise!) map affine spaces to affine spaces. An affine space is substantially a vector space where you can establish an origin and define points as tuples of their coordinates. This is far from a formal definition, if you are interested in one I can edit the answer. &#xD;&#xA;&#xD;&#xA;Now an affine transformation $T$ transform points into points and must preserve affine combinations: &#xD;&#xA;&#xD;&#xA;$T(\lambda_1 P_1 + \lambda_2 P_2 + ...  +  \lambda_n P_n) = \lambda_1 T(P_1) + \lambda_2 T(P_2) + ... + \lambda_n T(P_n)  $   &#xD;&#xA;&#xD;&#xA;Given $\sum_{i}^{n} \lambda_i = 1 $&#xD;&#xA;&#xD;&#xA;However these transformations can't be arbitrary as the following must be preserved: &#xD;&#xA;&#xD;&#xA;- **Parallelism is preserved**. This means that if you transform parallel lines they remain parallel after the affine transformation.&#xD;&#xA;&#xD;&#xA;- **Relative ratios are preserved**. This means that if you have $R = (1-\beta) P + \beta Q$  then $T(R) = (1 - \beta) T(P) + \beta T(Q)$ &#xD;&#xA;&#xD;&#xA;- **Addition between vector and points are preserved**. Meaning that $T( P + \vec{v} ) = T(P) + T(\vec{v})$&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;With these properties in mind you can come up with a very big number of affine transforms yourself. A couple of obvious ones other the ones you mentioned are: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Translation** &#xD;&#xA;&#xD;&#xA;[![*Image taken from wikipedia*][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Image from wikipedia to show the matrix for a 3D point in homogeneous coordinates*&#xD;&#xA;&#xD;&#xA;That moves a point into a specific direction by a specific amount specified by a displacement vector. &#xD;&#xA;&#xD;&#xA;**Shearing** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*Again, from wikipedia*&#xD;&#xA;&#xD;&#xA;That is a transform that displace all points in a given direction by an amount that is proportional to their perpendicular distance to a line parallel to that direction. &#xD;&#xA;&#xD;&#xA;For example the transform matrix for an horizontal shear in a 2D space is given by: &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;*Guess what? Image from wiki again :)*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q0Fne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fpg2D.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vTy3J.png&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, these two are just example, the important information you should really keep is the definition (and properties) of an affine transform; with that in mind it shouldn't be too hard to recognize an affine transform.  Also note that combining affine transforms will give you an affine transform! " ContentLicense="CC BY-SA 3.0" />
  <row Id="3321" PostHistoryTypeId="5" PostId="1714" RevisionGUID="c5585ce4-5e26-44d9-8707-6a2e9bcc47ed" CreationDate="2015-11-13T09:44:32.787" UserId="100" Comment="added 6 characters in body" Text="Affine transformations (surprise!) map affine spaces to affine spaces. An affine space is substantially a vector space where you can establish an origin and define points as tuples of their coordinates. This is far from a formal definition, if you are interested in one I can edit the answer. &#xD;&#xA;&#xD;&#xA;Now an affine transformation $T$ transform points into points and must preserve affine combinations: &#xD;&#xA;&#xD;&#xA;$T(\lambda_1 P_1 + \lambda_2 P_2 + ...  +  \lambda_n P_n) = \lambda_1 T(P_1) + \lambda_2 T(P_2) + ... + \lambda_n T(P_n)  $   &#xD;&#xA;&#xD;&#xA;Given $\sum_{i}^{n} \lambda_i = 1 $&#xD;&#xA;&#xD;&#xA;However these transformations can't be arbitrary as the following must be preserved: &#xD;&#xA;&#xD;&#xA;- ***Parallelism is preserved***. This means that if you transform parallel lines they remain parallel after the affine transformation.&#xD;&#xA;&#xD;&#xA;- ***Relative ratios are preserved***. This means that if you have $R = (1-\beta) P + \beta Q$  then $T(R) = (1 - \beta) T(P) + \beta T(Q)$ &#xD;&#xA;&#xD;&#xA;- ***Addition between vector and points are preserved***. Meaning that $T( P + \vec{v} ) = T(P) + T(\vec{v})$&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;With these properties in mind you can come up with a very big number of affine transforms yourself. A couple of obvious ones other the ones you mentioned are: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Translation** &#xD;&#xA;&#xD;&#xA;[![*Image taken from wikipedia*][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Image from wikipedia to show the matrix for a 3D point in homogeneous coordinates*&#xD;&#xA;&#xD;&#xA;That moves a point into a specific direction by a specific amount specified by a displacement vector. &#xD;&#xA;&#xD;&#xA;**Shearing** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*Again, from wikipedia*&#xD;&#xA;&#xD;&#xA;That is a transform that displace all points in a given direction by an amount that is proportional to their perpendicular distance to a line parallel to that direction. &#xD;&#xA;&#xD;&#xA;For example the transform matrix for an horizontal shear in a 2D space is given by: &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;*Guess what? Image from wiki again :)*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q0Fne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fpg2D.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vTy3J.png&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, these two are just example, the important information you should really keep is the definition (and properties) of an affine transform; with that in mind it shouldn't be too hard to recognize an affine transform.  Also note that combining affine transforms will give you an affine transform! " ContentLicense="CC BY-SA 3.0" />
  <row Id="3322" PostHistoryTypeId="5" PostId="1713" RevisionGUID="23d3cf26-98f6-4007-9acb-8b0a6751b4e2" CreationDate="2015-11-13T09:46:36.130" UserId="205" Comment="Improved readibilty" Text="Please help me tackle the below question:&#xD;&#xA;&#xD;&#xA;&gt; Explain THREE forms of affine transformations using relevant examples&#xD;&#xA;&gt; for each case.&#xD;&#xA;&#xD;&#xA;The answers i already give are scaling, rotation and reflection." ContentLicense="CC BY-SA 3.0" />
  <row Id="3323" PostHistoryTypeId="24" PostId="1713" RevisionGUID="23d3cf26-98f6-4007-9acb-8b0a6751b4e2" CreationDate="2015-11-13T09:46:36.130" Comment="Proposed by 205 approved by 231 edit id of 99" ContentLicense="CC BY-SA 3.0" />
  <row Id="3324" PostHistoryTypeId="5" PostId="1713" RevisionGUID="7ca9329f-07aa-4f55-9f5b-8332b4f0eab8" CreationDate="2015-11-13T09:52:29.547" UserId="231" Comment="Minor tidying" Text="Please help me tackle the below question:&#xD;&#xA;&#xD;&#xA;&gt; Explain THREE forms of affine transformations using relevant examples for each case.&#xD;&#xA;&#xD;&#xA;The answers I want to see are scaling, rotation and reflection." ContentLicense="CC BY-SA 3.0" />
  <row Id="3325" PostHistoryTypeId="4" PostId="1713" RevisionGUID="7ca9329f-07aa-4f55-9f5b-8332b4f0eab8" CreationDate="2015-11-13T09:52:29.547" UserId="231" Comment="Minor tidying" Text="What are forms of affine transformations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3326" PostHistoryTypeId="6" PostId="1713" RevisionGUID="7ca9329f-07aa-4f55-9f5b-8332b4f0eab8" CreationDate="2015-11-13T09:52:29.547" UserId="231" Comment="Minor tidying" Text="|vector-graphics|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3327" PostHistoryTypeId="5" PostId="1714" RevisionGUID="3cde253b-c72c-4311-98c8-289972579cd6" CreationDate="2015-11-13T10:02:04.647" UserId="100" Comment="added 236 characters in body" Text="&#xD;&#xA;*Note: I have answered before the edit from trichoplax and I thought you were searching for other transformations other than the one you mentioned. The informations below are still useful for the purpose so I will keep the answer here.*&#xD;&#xA;____ &#xD;&#xA;&#xD;&#xA;Affine transformations (surprise!) map affine spaces to affine spaces. An affine space is substantially a vector space where you can establish an origin and define points as tuples of their coordinates. This is far from a formal definition, if you are interested in one I can edit the answer. &#xD;&#xA;&#xD;&#xA;Now an affine transformation $T$ transform points into points and must preserve affine combinations: &#xD;&#xA;&#xD;&#xA;$T(\lambda_1 P_1 + \lambda_2 P_2 + ...  +  \lambda_n P_n) = \lambda_1 T(P_1) + \lambda_2 T(P_2) + ... + \lambda_n T(P_n)  $   &#xD;&#xA;&#xD;&#xA;Given $\sum_{i}^{n} \lambda_i = 1 $&#xD;&#xA;&#xD;&#xA;However these transformations can't be arbitrary as the following must be preserved: &#xD;&#xA;&#xD;&#xA;- ***Parallelism is preserved***. This means that if you transform parallel lines they remain parallel after the affine transformation.&#xD;&#xA;&#xD;&#xA;- ***Relative ratios are preserved***. This means that if you have $R = (1-\beta) P + \beta Q$  then $T(R) = (1 - \beta) T(P) + \beta T(Q)$ &#xD;&#xA;&#xD;&#xA;- ***Addition between vector and points are preserved***. Meaning that $T( P + \vec{v} ) = T(P) + T(\vec{v})$&#xD;&#xA;*Note: I replied before the edits from trichoplax and I misunderstood the question thinking you were searching for 3 other transformations. The informations below are still relevant to understand the problem and solve yours.*&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;With these properties in mind you can come up with a very big number of affine transforms yourself. A couple of obvious ones other the ones you mentioned are: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Translation** &#xD;&#xA;&#xD;&#xA;[![*Image taken from wikipedia*][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Image from wikipedia to show the matrix for a 3D point in homogeneous coordinates*&#xD;&#xA;&#xD;&#xA;That moves a point into a specific direction by a specific amount specified by a displacement vector. &#xD;&#xA;&#xD;&#xA;**Shearing** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*Again, from wikipedia*&#xD;&#xA;&#xD;&#xA;That is a transform that displace all points in a given direction by an amount that is proportional to their perpendicular distance to a line parallel to that direction. &#xD;&#xA;&#xD;&#xA;For example the transform matrix for an horizontal shear in a 2D space is given by: &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;*Guess what? Image from wiki again :)*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q0Fne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fpg2D.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vTy3J.png&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, these two are just example, the important information you should really keep is the definition (and properties) of an affine transform; with that in mind it shouldn't be too hard to recognize an affine transform.  Also note that combining affine transforms will give you an affine transform! " ContentLicense="CC BY-SA 3.0" />
  <row Id="3328" PostHistoryTypeId="5" PostId="1714" RevisionGUID="bf3b3933-40f6-488b-b26c-a52ea24ad16e" CreationDate="2015-11-13T10:27:36.183" UserId="100" Comment="added 29 characters in body" Text="*Note: I have answered before the edit from trichoplax and I thought you were searching for other transformations other than the one you mentioned. The informations below are still useful so I will keep the answer here, but it does not directly answer your question.*&#xD;&#xA;____ &#xD;&#xA;&#xD;&#xA;Affine transformations (surprise!) map affine spaces to affine spaces. An affine space is substantially a vector space where you can establish an origin and define points as tuples of their coordinates. This is far from a formal definition, if you are interested in one I can edit the answer. &#xD;&#xA;&#xD;&#xA;Now an affine transformation $T$ transform points into points and must preserve affine combinations: &#xD;&#xA;&#xD;&#xA;$T(\lambda_1 P_1 + \lambda_2 P_2 + ...  +  \lambda_n P_n) = \lambda_1 T(P_1) + \lambda_2 T(P_2) + ... + \lambda_n T(P_n)  $   &#xD;&#xA;&#xD;&#xA;Given $\sum_{i}^{n} \lambda_i = 1 $&#xD;&#xA;&#xD;&#xA;However these transformations can't be arbitrary as the following must be preserved: &#xD;&#xA;&#xD;&#xA;- ***Parallelism is preserved***. This means that if you transform parallel lines they remain parallel after the affine transformation.&#xD;&#xA;&#xD;&#xA;- ***Relative ratios are preserved***. This means that if you have $R = (1-\beta) P + \beta Q$  then $T(R) = (1 - \beta) T(P) + \beta T(Q)$ &#xD;&#xA;&#xD;&#xA;- ***Addition between vector and points are preserved***. Meaning that $T( P + \vec{v} ) = T(P) + T(\vec{v})$&#xD;&#xA;*Note: I replied before the edits from trichoplax and I misunderstood the question thinking you were searching for 3 other transformations. The informations below are still relevant to understand the problem and solve yours.*&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;With these properties in mind you can come up with a very big number of affine transforms yourself. A couple of obvious ones other the ones you mentioned are: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Translation** &#xD;&#xA;&#xD;&#xA;[![*Image taken from wikipedia*][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Image from wikipedia to show the matrix for a 3D point in homogeneous coordinates*&#xD;&#xA;&#xD;&#xA;That moves a point into a specific direction by a specific amount specified by a displacement vector. &#xD;&#xA;&#xD;&#xA;**Shearing** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*Again, from wikipedia*&#xD;&#xA;&#xD;&#xA;That is a transform that displace all points in a given direction by an amount that is proportional to their perpendicular distance to a line parallel to that direction. &#xD;&#xA;&#xD;&#xA;For example the transform matrix for an horizontal shear in a 2D space is given by: &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;*Guess what? Image from wiki again :)*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q0Fne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fpg2D.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vTy3J.png&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, these two are just example, the important information you should really keep is the definition (and properties) of an affine transform; with that in mind it shouldn't be too hard to recognize an affine transform.  Also note that combining affine transforms will give you an affine transform! " ContentLicense="CC BY-SA 3.0" />
  <row Id="3329" PostHistoryTypeId="2" PostId="1715" RevisionGUID="0de621bc-acee-415c-a537-05da3a3ce5a8" CreationDate="2015-11-13T10:38:50.640" UserId="2041" Text="Let's take web browsers as an example. On mobile, both Chrome and Firefox draw the page content on the GPU, and they typically have a lot of scrolling, so it's a relevant example.&#xD;&#xA;&#xD;&#xA;They work a little like Google Maps or Open Street Map's tileserver. They slice the page up into tiles and draw each tile into a texture. (The textures may well be in a texture atlas; I'm afraid I don't know the specifics.) Drawing the final screen simply consists of drawing a small number of textured squares in the correct positions. This approach makes scrolling very easy.&#xD;&#xA;&#xD;&#xA;When you scroll, it doesn't have to regenerate the whole page starting from the DOM (the web page equivalent of the scene graph): it just moves the quads around so that each textured tile moves around the viewport. When a new row or column of tiles is about to come into view, the page renderer has to draw the new tiles before you want to see them. At the other end of the screen, you can keep tiles that are no longer in view, but they can be disposed of if you start to run out of texture memory. Because all the tiles are the same size, you can simply draw the new tiles over old textures you don't want any more.&#xD;&#xA;&#xD;&#xA;It's just the same as in Google Maps: when you scroll in that, you can usually see a placeholder texture if new tiles are visible before they've finished downloading. And the page keeps a cache of tiles you've looked at before, but it can destroy any that are no longer visible in order to free some memory if necessary.&#xD;&#xA;&#xD;&#xA;The tile technique also allows progressive refinement, which is important to let you scroll at 60 fps on a mobile platform without enough compute power. If it's rendering the tiles too slowly, it can draw the textures at lower resolution first (while you're scrolling), and then redraw them at full resolution later, if they stay on screen.&#xD;&#xA;&#xD;&#xA;In short, there isn't any special functionality for blitting some of the last frame into a new position in the new frame, but by rendering to texture, we can access the same texture from the next frame, throwing away any parts that are no longer useful. Some games also use this technique for mostly static content backgrounds, 2D world maps, &amp;c.&#xD;&#xA;&#xD;&#xA;If you have to update small portions of the scrolling content, it's easy: just redraw the tiles that changed. The code that updates the tiles doesn't care what screen position they're being displayed, because the final frame renderer puts each tile in the right place. You don't have &quot;two un-synced copies of the canvas&quot; and it doesn't matter whether you're drawing each tile on the CPU or GPU (or both).&#xD;&#xA;&#xD;&#xA;The word &quot;static&quot; there was important. If much of the background is changing every frame, you don't get any advantage from tiles, because you have to update every tile every frame. In that case, you should just throw away the old frame and draw the new frame from scratch. That's why many 2D games don't use this technique even if they show scrolling content (e.g. a Mario game).&#xD;&#xA;&#xD;&#xA;### In summary:&#xD;&#xA;&#xD;&#xA;* If your scrolling content is completely static and small enough to fit in memory, draw it in a big texture and render a textured quad per-frame.&#xD;&#xA;* If your scrolling content is too big to fit in memory, or small regions of it need updating sometimes, draw it in tiles, render all the visible tiles per-frame, and add something to load and unload tiles when necessary.&#xD;&#xA;* If most tiles change most frames, just draw the visible region every frame.&#xD;&#xA;&#xD;&#xA;Knowing which case you're in, and being able to separate out the static parts from the changing parts, constitutes a lot of the work of the graphics developer :-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3330" PostHistoryTypeId="2" PostId="1716" RevisionGUID="a3a5cdf2-339b-4643-a0dc-f868660eaa46" CreationDate="2015-11-13T10:48:15.710" UserId="2040" Text="I have a small project that needs to extract the perceptually-salient colors of an image, in javascript. There are a few libraries out there (color-thief.js, vibrant.js). The trouble is, I'm finding that [adobe color's][1] image extraction does a noticeably better job of recognizing the little high-contrast highlight colors which make a big visual aesthetic difference, even though they represent a small number of pixels. (This is the &quot;color mood&quot; option). For example, the color of lipstick a person wears, or small decorations on a big cake.&#xD;&#xA;&#xD;&#xA;I think (?) Adobe doesn't provide an API for their Color CC any more, but in any case I'd rather not rely on it. Is there a javascript library out there with similar functionality?&#xD;&#xA;&#xD;&#xA;  [1]: https://color.adobe.com/create/image/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3331" PostHistoryTypeId="1" PostId="1716" RevisionGUID="a3a5cdf2-339b-4643-a0dc-f868660eaa46" CreationDate="2015-11-13T10:48:15.710" UserId="2040" Text="Javascript color extraction library" ContentLicense="CC BY-SA 3.0" />
  <row Id="3332" PostHistoryTypeId="3" PostId="1716" RevisionGUID="a3a5cdf2-339b-4643-a0dc-f868660eaa46" CreationDate="2015-11-13T10:48:15.710" UserId="2040" Text="|color|color-separation|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3333" PostHistoryTypeId="5" PostId="1716" RevisionGUID="ee3b83bc-c1ca-4edf-82d3-ed2120bc1bae" CreationDate="2015-11-13T10:59:19.023" UserId="2040" Comment="added 93 characters in body" Text="I have a small project that needs to extract the perceptually-salient colors of an image, in javascript. There are a few libraries out there (color-thief.js, vibrant.js). The trouble is, I'm finding that [adobe color's][1] image extraction does a noticeably better job of recognizing the little high-contrast highlight colors which make a big visual aesthetic difference, even though they represent a small number of pixels. (This is the &quot;color mood&quot; option). For example, the color of lipstick a person wears, or small decorations on a big cake.&#xD;&#xA;&#xD;&#xA;I think (?) Adobe doesn't provide an API for their Color CC any more, but in any case I'd rather not rely on it. Is there a javascript library out there with similar functionality that provides access to some sort of functionality that maximizes dissimilarity between hues?&#xD;&#xA;&#xD;&#xA;  [1]: https://color.adobe.com/create/image/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3334" PostHistoryTypeId="5" PostId="1714" RevisionGUID="02c25d6d-704d-4c11-98d5-6f429b188153" CreationDate="2015-11-13T11:31:51.037" UserId="137" Comment="added 99 characters in body" Text="*Note: I have answered before the edit from trichoplax and I thought you were searching for other transformations other than the one you mentioned. The informations below are still useful so I will keep the answer here, but it does not directly answer your question.*&#xD;&#xA;____ &#xD;&#xA;&#xD;&#xA;Affine transformations (surprise!) map affine spaces to affine spaces. An affine space is substantially a vector space where you can establish an origin and define points as tuples of their coordinates. This is far from a formal definition, if you are interested in one I can edit the answer. &#xD;&#xA;&#xD;&#xA;Now an affine transformation $T$ transform points into points and must preserve affine combinations: &#xD;&#xA;&#xD;&#xA;$T(\lambda_1 P_1 + \lambda_2 P_2 + ...  +  \lambda_n P_n) = \lambda_1 T(P_1) + \lambda_2 T(P_2) + ... + \lambda_n T(P_n)  $   &#xD;&#xA;&#xD;&#xA;Given $\sum_{i}^{n} \lambda_i = 1 $&#xD;&#xA;&#xD;&#xA;However these transformations can't be arbitrary as the following must be preserved: &#xD;&#xA;&#xD;&#xA;- ***Parallelism is preserved***. This means that if you transform parallel lines they remain parallel after the affine transformation.&#xD;&#xA;&#xD;&#xA;- ***Relative ratios are preserved***. This means that if you have $R = (1-\beta) P + \beta Q$  then $T(R) = (1 - \beta) T(P) + \beta T(Q)$ &#xD;&#xA;&#xD;&#xA;- ***Addition between vector and points are preserved***. Meaning that $T( P + \vec{v} ) = T(P) + T(\vec{v})$&#xD;&#xA;*Note: I replied before the edits from trichoplax and I misunderstood the question thinking you were searching for 3 other transformations. The informations below are still relevant to understand the problem and solve yours.*&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;With these properties in mind you can come up with a very big number of affine transforms yourself. A couple of obvious ones other the ones you mentioned are: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Translation** &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$T_vp = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1&amp;0&amp;0&amp;v_x\\0&amp;1&amp;0&amp;v_y\\0&amp;0&amp;1&amp;v_z\\0&amp;0&amp;0&amp;1\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;p_x+v_x\\p_x+v_y\\p_z+v_z\\1\end{bmatrix}=p+v$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;That moves a point into a specific direction by a specific amount specified by a displacement vector. &#xD;&#xA;&#xD;&#xA;**Shearing** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*image from wikipedia*&#xD;&#xA;&#xD;&#xA;That is a transform that displace all points in a given direction by an amount that is proportional to their perpendicular distance to a line parallel to that direction. &#xD;&#xA;&#xD;&#xA;For example the transform matrix for an horizontal shear in a 2D space is given by: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'\\y'\end{bmatrix} = \begin{bmatrix}x+my\\y\end{bmatrix} = &#xD;&#xA;\begin{bmatrix}1&amp;m\\0&amp;1\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q0Fne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fpg2D.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vTy3J.png&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, these two are just example, the important information you should really keep is the definition (and properties) of an affine transform; with that in mind it shouldn't be too hard to recognize an affine transform.  Also note that combining affine transforms will give you an affine transform! " ContentLicense="CC BY-SA 3.0" />
  <row Id="3335" PostHistoryTypeId="5" PostId="1714" RevisionGUID="0cb302f8-e870-4d05-9702-e60cc413447a" CreationDate="2015-11-13T13:08:52.040" UserId="100" Comment="deleted 232 characters in body" Text="*Note: I have answered before the edit from trichoplax and I thought you were searching for other transformations other than the one you mentioned. The informations below are still useful so I will keep the answer here, but it does not directly answer your question.*&#xD;&#xA;____ &#xD;&#xA;&#xD;&#xA;Affine transformations (surprise!) map affine spaces to affine spaces. An affine space is substantially a vector space where you can establish an origin and define points as tuples of their coordinates. This is far from a formal definition, if you are interested in one I can edit the answer. &#xD;&#xA;&#xD;&#xA;Now an affine transformation $T$ transform points into points and must preserve affine combinations: &#xD;&#xA;&#xD;&#xA;$T(\lambda_1 P_1 + \lambda_2 P_2 + ...  +  \lambda_n P_n) = \lambda_1 T(P_1) + \lambda_2 T(P_2) + ... + \lambda_n T(P_n)  $   &#xD;&#xA;&#xD;&#xA;Given $\sum_{i}^{n} \lambda_i = 1 $&#xD;&#xA;&#xD;&#xA;However these transformations can't be arbitrary as the following must be preserved: &#xD;&#xA;&#xD;&#xA;- ***Parallelism is preserved***. This means that if you transform parallel lines they remain parallel after the affine transformation.&#xD;&#xA;&#xD;&#xA;- ***Relative ratios are preserved***. This means that if you have $R = (1-\beta) P + \beta Q$  then $T(R) = (1 - \beta) T(P) + \beta T(Q)$ &#xD;&#xA;&#xD;&#xA;- ***Addition between vector and points are preserved***. Meaning that $T( P + \vec{v} ) = T(P) + T(\vec{v})$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With these properties in mind you can come up with a very big number of affine transforms yourself. A couple of obvious ones other the ones you mentioned are: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Translation** &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$T_vp = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1&amp;0&amp;0&amp;v_x\\0&amp;1&amp;0&amp;v_y\\0&amp;0&amp;1&amp;v_z\\0&amp;0&amp;0&amp;1\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;p_x+v_x\\p_x+v_y\\p_z+v_z\\1\end{bmatrix}=p+v$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;That moves a point into a specific direction by a specific amount specified by a displacement vector. &#xD;&#xA;&#xD;&#xA;**Shearing** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*image from wikipedia*&#xD;&#xA;&#xD;&#xA;That is a transform that displace all points in a given direction by an amount that is proportional to their perpendicular distance to a line parallel to that direction. &#xD;&#xA;&#xD;&#xA;For example the transform matrix for an horizontal shear in a 2D space is given by: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'\\y'\end{bmatrix} = \begin{bmatrix}x+my\\y\end{bmatrix} = &#xD;&#xA;\begin{bmatrix}1&amp;m\\0&amp;1\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q0Fne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fpg2D.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vTy3J.png&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, these two are just example, the important information you should really keep is the definition (and properties) of an affine transform; with that in mind it shouldn't be too hard to recognize an affine transform.  Also note that combining affine transforms will give you an affine transform! " ContentLicense="CC BY-SA 3.0" />
  <row Id="3336" PostHistoryTypeId="2" PostId="1717" RevisionGUID="ec24cd70-cd37-466b-828a-96571fbedaef" CreationDate="2015-11-13T16:50:33.490" UserId="2041" Text="Both of your two proposed solutions are valid, with different properties. Which you choose is purely a design issue. The difference is that your probabilistic rays/particles (1) don't need to store their energy: they all have the same amount of energy, so you can just count particles to sum the energy. Your partial particles (2) need to store an energy so you can split them up.&#xD;&#xA;&#xD;&#xA;The advantage of 1 is that each ray is smaller. Also, it's easy to keep track of where the energy ended up, because you can use the intersections where the ray was dropped.&#xD;&#xA;&#xD;&#xA;Because you're only reflecting or discarding rays, the number of in-flight rays will decrease with each bounce, so you might find it harder to keep batches of rays together for better SIMD or parallel performance.&#xD;&#xA;&#xD;&#xA;Also, because you're probabilistically discarding rays, you'll get a lot more noise in your results for the same number of rays.&#xD;&#xA;&#xD;&#xA;The second solution is closer to a traditional ray-tracer, so you may find it easier to use existing algorithms and code. You can use fewer primary rays, and the number of rays in each batch is constant at first (but gets worse when the brightnesses start to reach zero).&#xD;&#xA;&#xD;&#xA;It's also a lot more efficient to track multiple frequencies this way. If you give each ray a spectrum or RGB energies, the material can have a different effect on different colours without you having to fire multiple batches of rays (duplicating the ray intersection work).&#xD;&#xA;&#xD;&#xA;On the other hand, you'll need a second data structure to count up where energy was absorbed, if you want to track that.&#xD;&#xA;&#xD;&#xA;In your place, I'd probably use the second solution, but it depends on what other software you're trying to integrate with e.g. an existing ray-tracing library or photon representation, and what you need to do with the output/results." ContentLicense="CC BY-SA 3.0" />
  <row Id="3337" PostHistoryTypeId="2" PostId="1718" RevisionGUID="fc5fbf03-ac48-4344-93c7-9d3f87b1ef40" CreationDate="2015-11-13T17:38:28.863" UserId="14" Text="I have a mesh and in the region around each triangle, I want to compute an estimate of the principal curvature directions. I have never done this sort of thing before and [Wikipedia][1] does not help a lot. Can you describe or point me to a simple algorithm that can help me compute this estimate?&#xD;&#xA;&#xD;&#xA;Assume that I know positions and normals of all vertices.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Principal_curvature" ContentLicense="CC BY-SA 3.0" />
  <row Id="3338" PostHistoryTypeId="1" PostId="1718" RevisionGUID="fc5fbf03-ac48-4344-93c7-9d3f87b1ef40" CreationDate="2015-11-13T17:38:28.863" UserId="14" Text="What is the simplest way to compute principal curvature for a mesh triangle?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3339" PostHistoryTypeId="3" PostId="1718" RevisionGUID="fc5fbf03-ac48-4344-93c7-9d3f87b1ef40" CreationDate="2015-11-13T17:38:28.863" UserId="14" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3340" PostHistoryTypeId="5" PostId="1711" RevisionGUID="786b2e4a-1650-45b6-a830-7ee9ea89c190" CreationDate="2015-11-13T19:53:20.723" UserId="2049" Comment="added 311 characters in body" Text="You can use OpenGl 4.x tessellation shaders to convert Bezier control points into polygons.&#xD;&#xA;&#xD;&#xA;A google search for &quot;tessellation shader bezier&quot; found this outline describing the tessellation of Bezier surfaces and curves:&#xD;&#xA;&#xD;&#xA;http://web.engr.oregonstate.edu/~mjb/cs519/Handouts/tessellation.1pp.pdf&#xD;&#xA;&#xD;&#xA;This offloads the Bezier evaluation from the CPU to the GPU and reduces the data flow across the bus." ContentLicense="CC BY-SA 3.0" />
  <row Id="3341" PostHistoryTypeId="2" PostId="1719" RevisionGUID="d7950dc3-bf15-4451-98fb-2659231d2094" CreationDate="2015-11-14T00:43:02.683" UserId="48" Text="When I needed an estimate of mesh curvature for a skin shader, the algorithm I ended up settling on was this:&#xD;&#xA;&#xD;&#xA;First, I computed a scalar curvature for each edge in the mesh. If the edge has positions $p_0, p_1$ and normals $n_0, n_1$, then I estimated its curvature as:&#xD;&#xA;&#xD;&#xA;$$\frac{(n_1 - n_0) \cdot (p_1 - p_0)}{(p_1 - p_0)^2}$$&#xD;&#xA;&#xD;&#xA;This calculates the difference in normals, projected along the edge, as a fraction of the length of the edge. You can verify that if applied to two points on a circle of radius $r$, this gives the correct curvature $1/r$. It also correctly gives a negative curvature if you invert the normals.&#xD;&#xA;&#xD;&#xA;Then, for each vertex I looked at the curvatures of all the edges touching it. In my case, I just wanted a scalar estimate of &quot;average curvature&quot;, so I ended up taking the geometric mean of the absolute values of all the edge curvatures at each vertex. For your case, you might find the minimum and maximum curvatures, and take those edges to be the principal curvature directions (maybe orthonormalizing them with the vertex normal). That's a bit rough, but it might give you a good enough result for what you want to do.&#xD;&#xA;&#xD;&#xA;Another approach I can imagine using, but haven't tried, would be to estimate the [second fundamental form](https://en.wikipedia.org/wiki/Second_fundamental_form) of the surface at each vertex. This could be done by setting up a tangent basis at the vertex, then converting all neighboring vertices into that tangent space, and using least-squares to find the best-fit 2FF matrix. Then the principal curvature directions would be the eigenvectors of that matrix. This seems interesting as it could let you find curvature directions &quot;implied&quot; by the neighboring vertices without any edges explicitly pointing in those directions, but on the other hand is a lot more code, more computation, and perhaps less numerically robust." ContentLicense="CC BY-SA 3.0" />
  <row Id="3342" PostHistoryTypeId="2" PostId="1720" RevisionGUID="f1fc36e0-b517-425b-b737-3826eb463c33" CreationDate="2015-11-14T03:57:21.970" UserId="2061" Text="I am trying to understand why meshes that are smoothed in 3D studio (Modifiers/Smoother) end up having the same amount of vertices/faces before or after that process, as well as the exact same geometry.&#xD;&#xA;&#xD;&#xA;In the following example, both meshes have 32 vertices and 60 faces.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Although I have experience working with programming (c++ and c#), I am quite a beginner with computer graphics. Thus my expectation was that the smoothed look of a smoothed mesh would require additional vertices, i.e. subdivision of triangles, in order to end up having a more detailed final mesh. However, that seems to be not the case.&#xD;&#xA;&#xD;&#xA;Therefore I ask:&#xD;&#xA;&#xD;&#xA;1) how is the smoothing possible without increasing the detailing of the mesh geometry?&#xD;&#xA;&#xD;&#xA;2) does the smoothing at least increase the memory allocated/used for storing the new mesh in comparison to the original one?&#xD;&#xA;&#xD;&#xA;Explanations are super welcome, but references (academic or not) are also appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JQ1KW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dvqdb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3343" PostHistoryTypeId="1" PostId="1720" RevisionGUID="f1fc36e0-b517-425b-b737-3826eb463c33" CreationDate="2015-11-14T03:57:21.970" UserId="2061" Text="Why smoothed meshes in 3D studio end up with the same number of vertices/triangles? How then can they be smoothed with the same geometry?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3344" PostHistoryTypeId="3" PostId="1720" RevisionGUID="f1fc36e0-b517-425b-b737-3826eb463c33" CreationDate="2015-11-14T03:57:21.970" UserId="2061" Text="|3d|geometry|mesh|memory|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3345" PostHistoryTypeId="2" PostId="1721" RevisionGUID="8c34fcfa-01be-40e7-b280-6e58a84ba3ff" CreationDate="2015-11-14T09:36:56.117" UserId="100" Text="Just to an add another way to the excellent @NathanReed answer, you can use mean and gaussian curvature that can be obtained with a discrete Laplace-Beltrami.  &#xD;&#xA;&#xD;&#xA;So suppose that the 1-ring neighbourhood of $v_i$ in your mesh looks like this&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$A(v_i)$ can be simply the average area of the triangles that form this ring and the indicated $v_j$ is one of the neighbouring vertices. &#xD;&#xA;&#xD;&#xA;Now let's call $f(v_i)$ the function defined by your mesh (must be a differentiable manifold) at a certain point. The most popular discretization of the Laplace-Beltrami operator that I know is the cotangent discretization and is given by: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\Delta_S f(v_i) = \frac{1}{2A(v_i)} \sum_{v_j \in N_1(v_i)} (cot \alpha_{ij} + cot \beta_{ij}) (f(v_j) - f(v_i)) $$&#xD;&#xA;&#xD;&#xA;Where $v_j \in N_1(v_i)$ means every vertex in the one ring neighbourhood of $v_i$. &#xD;&#xA;&#xD;&#xA;With this is pretty simple to compute the mean curvature (now calling the vertex of interest simply $v$ ) is&#xD;&#xA;&#xD;&#xA;$$H = \frac{1}{2} || \Delta_S v || $$&#xD;&#xA;&#xD;&#xA;Now let's introduce the angle $\theta_j$ as &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The Gaussian curvature is:&#xD;&#xA;&#xD;&#xA;$$K = (2\pi - \sum_j \theta_j) / A$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After all of this pain, the principal discrete curvatures are given by: &#xD;&#xA;&#xD;&#xA;$$k_1 = H + \sqrt{H^2 - K} \ \  \text{and} \ \  k_2 = H - \sqrt{H^2 - K}$$&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aWaSm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysAHy.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3346" PostHistoryTypeId="5" PostId="1721" RevisionGUID="9059249b-9764-47eb-a9b9-07564f0a5651" CreationDate="2015-11-14T09:43:07.320" UserId="100" Comment="added 480 characters in body" Text="Just to an add another way to the excellent @NathanReed answer, you can use mean and gaussian curvature that can be obtained with a discrete Laplace-Beltrami.  &#xD;&#xA;&#xD;&#xA;So suppose that the 1-ring neighbourhood of $v_i$ in your mesh looks like this&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$A(v_i)$ can be simply a $\frac{1}{3}$ of the areas of the triangles that form this ring and the indicated $v_j$ is one of the neighbouring vertices. &#xD;&#xA;&#xD;&#xA;Now let's call $f(v_i)$ the function defined by your mesh (must be a differentiable manifold) at a certain point. The most popular discretization of the Laplace-Beltrami operator that I know is the cotangent discretization and is given by: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\Delta_S f(v_i) = \frac{1}{2A(v_i)} \sum_{v_j \in N_1(v_i)} (cot \alpha_{ij} + cot \beta_{ij}) (f(v_j) - f(v_i)) $$&#xD;&#xA;&#xD;&#xA;Where $v_j \in N_1(v_i)$ means every vertex in the one ring neighbourhood of $v_i$. &#xD;&#xA;&#xD;&#xA;With this is pretty simple to compute the mean curvature (now for simplicity let's call the function of your mesh at the vertex of interest simply $v$ ) is&#xD;&#xA;&#xD;&#xA;$$H = \frac{1}{2} || \Delta_S v || $$&#xD;&#xA;&#xD;&#xA;Now let's introduce the angle $\theta_j$ as &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The Gaussian curvature is:&#xD;&#xA;&#xD;&#xA;$$K = (2\pi - \sum_j \theta_j) / A$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After all of this pain, the principal discrete curvatures are given by: &#xD;&#xA;&#xD;&#xA;$$k_1 = H + \sqrt{H^2 - K} \ \  \text{and} \ \  k_2 = H - \sqrt{H^2 - K}$$&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aWaSm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysAHy.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3347" PostHistoryTypeId="5" PostId="1721" RevisionGUID="e11bd530-9a99-4e33-a02b-c2aa411adc11" CreationDate="2015-11-14T09:54:46.410" UserId="100" Comment="added 403 characters in body" Text="Just to an add another way to the excellent @NathanReed answer, you can use mean and gaussian curvature that can be obtained with a discrete Laplace-Beltrami.  &#xD;&#xA;&#xD;&#xA;So suppose that the 1-ring neighbourhood of $v_i$ in your mesh looks like this&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$A(v_i)$ can be simply a $\frac{1}{3}$ of the areas of the triangles that form this ring and the indicated $v_j$ is one of the neighbouring vertices. &#xD;&#xA;&#xD;&#xA;Now let's call $f(v_i)$ the function defined by your mesh (must be a differentiable manifold) at a certain point. The most popular discretization of the Laplace-Beltrami operator that I know is the cotangent discretization and is given by: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\Delta_S f(v_i) = \frac{1}{2A(v_i)} \sum_{v_j \in N_1(v_i)} (cot \alpha_{ij} + cot \beta_{ij}) (f(v_j) - f(v_i)) $$&#xD;&#xA;&#xD;&#xA;Where $v_j \in N_1(v_i)$ means every vertex in the one ring neighbourhood of $v_i$. &#xD;&#xA;&#xD;&#xA;With this is pretty simple to compute the mean curvature (now for simplicity let's call the function of your mesh at the vertex of interest simply $v$ ) is&#xD;&#xA;&#xD;&#xA;$$H = \frac{1}{2} || \Delta_S v || $$&#xD;&#xA;&#xD;&#xA;Now let's introduce the angle $\theta_j$ as &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The Gaussian curvature is:&#xD;&#xA;&#xD;&#xA;$$K = (2\pi - \sum_j \theta_j) / A$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After all of this pain, the principal discrete curvatures are given by: &#xD;&#xA;&#xD;&#xA;$$k_1 = H + \sqrt{H^2 - K} \ \  \text{and} \ \  k_2 = H - \sqrt{H^2 - K}$$&#xD;&#xA;&#xD;&#xA;___ &#xD;&#xA;&#xD;&#xA;If you are interested in the subject (and to add some reference to this post) an excellent read is:   [Discrete Differential-Geometry Operators&#xD;&#xA;for Triangulated 2-Manifolds][3] [Meyer et al. 2003]. &#xD;&#xA;&#xD;&#xA;For the images I thank my ex-professor Niloy Mitra as I found them in some notes I took for his lectures.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aWaSm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysAHy.png&#xD;&#xA;  [3]: http://http.cs.berkeley.edu/~jrs/meshpapers/MeyerDesbrunSchroderBarr.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3348" PostHistoryTypeId="2" PostId="1722" RevisionGUID="278ff82b-2f07-4ac3-87b3-cecaad8f7f90" CreationDate="2015-11-14T13:52:00.097" UserId="38" Text="Smooth in this case just makes the surface normals at vertices point the same way, when interpolated it looks smooth. Meshsmooth would add vertices.&#xD;&#xA;&#xD;&#xA;### 1) how is the smoothing possible without increasing the detailing of the mesh geometry?&#xD;&#xA;&#xD;&#xA;Human eyes cant actually see curvature except on the edges of objects. All they can do is approximate the smoothness and process the gradient slope. So having a continuous field does give a air of smoothness. The eye however is extremely sensitive to abrupt changes in color, and interprets that as a hard crease.&#xD;&#xA;&#xD;&#xA;By interpolating the vertex normals your surface will get the appearance of smooth flowing. Since this normal is used to calculate the final reflected color you get a smooth color field.&#xD;&#xA;&#xD;&#xA;[![Flat shaded vs smooth shaded][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: a flat shaded normal versus the normals of a smooth interplation. The black normal's lie on a vertex. The colored ones are interpolated.&#xD;&#xA;&#xD;&#xA;There is nothing that says we need to do a linear interpolation. In fact by perturbing the normals we can cause the flat surface to change appearance. This is how bump mapping and normal mapping works. The effect can be convincing unless the surfaces edge plays a too big part in which place the illusion breaks.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: a flat shaded surface (back), Smooth shaded (middle) and a mapped smooth normal. The illusion of a wavy surface breaks because the edge plays so prominent part in the image, you could instead increase the normals&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### 2) does the smoothing at least increase the memory allocated&#xD;&#xA;&#xD;&#xA;Hard to say definitive things about the underlying graphics engine. The normals need to be emitted to the graphics card anyway, most likely this data is cached, but could be calculated on the fly (in both cases).&#xD;&#xA;&#xD;&#xA;Since Max uses smoothing groups it seems to me that memory usage is constant regardless. Hard to say, even if its not cached then it wouldn't make a big difference. It makes the shader tiny a bit more complicated, but only just most likely this complexity is present use it or not.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EqJkQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/l62Ov.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3351" PostHistoryTypeId="2" PostId="1723" RevisionGUID="63178fc3-06e8-410d-ba62-44d937b70444" CreationDate="2015-11-15T12:12:19.667" UserId="38" Text="One can do curved drawing with hardware. There is a method described in **GPU Gems 3** that describes how to do this. User @yuriks actually comments this. I have actually made a quick a dirty demo for you to take a look at.&#xD;&#xA;&#xD;&#xA;[![curve][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: HW accelerated curve and [webgl source](http://webglplayground.net/saved/9ZD4Uoi72Q)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/D9F9k.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3352" PostHistoryTypeId="5" PostId="1723" RevisionGUID="c6f4cf7f-6a80-496c-8aba-f1755fdcbbce" CreationDate="2015-11-15T12:17:42.913" UserId="38" Comment="added 32 characters in body" Text="One can do curved drawing with hardware. There is a method described in **GPU Gems 3** that describes how to do this. User @yuriks actually comments this. I have actually made a quick a dirty demo for you to take a look at.&#xD;&#xA;&#xD;&#xA;[![curve][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: HW accelerated curve shapen (drawn usung a triangle) and [webgl source](http://webglplayground.net/saved/9ZD4Uoi72Q)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/D9F9k.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3355" PostHistoryTypeId="10" PostId="1708" RevisionGUID="df2eec7a-6cce-485a-885d-cdc5fd8b27dc" CreationDate="2015-11-16T09:49:11.447" UserId="16" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="3356" PostHistoryTypeId="2" PostId="1724" RevisionGUID="344bf77a-8305-47e3-b2dc-d90e7cd4a405" CreationDate="2015-11-16T10:33:47.740" UserId="2040" Text="In the end I decided to use Leon Sorokin's RGBQuant.js for quantization, because it offered better flexibility over the color histogram/clustering method. I'm probably going to convert the quantized palette RGB output to HSV and implement custom clustering that picks out the &quot;highlight&quot; colors, favoring diversity of hue for colors with high value and saturation, and low occurrence frequency." ContentLicense="CC BY-SA 3.0" />
  <row Id="3358" PostHistoryTypeId="2" PostId="1725" RevisionGUID="69cd5503-6d65-425e-9e57-6016a6fc7a53" CreationDate="2015-11-16T15:25:18.107" UserId="2041" Text="There have been lots of papers over the years on different techniques for drawing height-field terrain in a ray-tracer. Some algorithms ray-march the grid directly (or via a quadtree); others transform the terrain into a polygon mesh and use a standard ray-triangle intersection test. The research seems to have moved on in the last few years, and it's hard to find papers written in the last decade, but the balance between memory and compute (both CPU and GPU) is still changing.&#xD;&#xA;&#xD;&#xA;What kind of algorithm gives best performance on high-end desktop machines nowadays? Or if there isn't a single answer, how do the performance characteristics of the current best algorithms differ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3359" PostHistoryTypeId="1" PostId="1725" RevisionGUID="69cd5503-6d65-425e-9e57-6016a6fc7a53" CreationDate="2015-11-16T15:25:18.107" UserId="2041" Text="What's the current state-of-the-art algorithm for ray-tracing height-fields?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3360" PostHistoryTypeId="3" PostId="1725" RevisionGUID="69cd5503-6d65-425e-9e57-6016a6fc7a53" CreationDate="2015-11-16T15:25:18.107" UserId="2041" Text="|raytracing|height-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3361" PostHistoryTypeId="2" PostId="1726" RevisionGUID="b8e2a498-9333-4412-94b8-0f1b284df905" CreationDate="2015-11-16T15:46:10.380" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3362" PostHistoryTypeId="2" PostId="1727" RevisionGUID="0efc15d0-5307-4b0e-a131-7e3519fffa21" CreationDate="2015-11-16T15:46:10.380" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3363" PostHistoryTypeId="5" PostId="192" RevisionGUID="8e2c8f78-48f5-4cab-a73b-4fcd54d41875" CreationDate="2015-11-16T15:47:42.347" UserId="2041" Comment="add usage guidance and some useful links" Text="Questions specific to raytracing (as opposed to scanline rendering), the 3D graphics technique of intersecting rays from the camera with objects in the scene." ContentLicense="CC BY-SA 3.0" />
  <row Id="3364" PostHistoryTypeId="24" PostId="192" RevisionGUID="8e2c8f78-48f5-4cab-a73b-4fcd54d41875" CreationDate="2015-11-16T15:47:42.347" Comment="Proposed by 2041 approved by 127 edit id of 101" ContentLicense="CC BY-SA 3.0" />
  <row Id="3365" PostHistoryTypeId="5" PostId="1726" RevisionGUID="eab0c4a9-fd4d-4f22-bcb5-b95962622c1a" CreationDate="2015-11-16T15:51:57.453" UserId="2041" Comment="added 698 characters in body" Text="A height-field is a way of defining a surface with an image, where the co-ordinates of the image represent co-ordinates on a plane, and the intensity of the image at each point represents the height of the surface from the plane at that point.&#xD;&#xA;&#xD;&#xA;It's a compact representation of 2.5D surfaces such as mountainous terrain, and is easier to create and modify in use than a polygon-based representation, but can't represent holes in the height field (such as a cave system or bridge).&#xD;&#xA;&#xD;&#xA;Compare *displacement map*, which is essentially a height field on a smaller scale to represent microgeometry on a polygon mesh.&#xD;&#xA;&#xD;&#xA;See also:&#xD;&#xA;&#xD;&#xA;* [Heightmap on Wikipedia](https://en.wikipedia.org/wiki/Heightmap)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3366" PostHistoryTypeId="24" PostId="1726" RevisionGUID="eab0c4a9-fd4d-4f22-bcb5-b95962622c1a" CreationDate="2015-11-16T15:51:57.453" Comment="Proposed by 2041 approved by 127 edit id of 102" ContentLicense="CC BY-SA 3.0" />
  <row Id="3367" PostHistoryTypeId="5" PostId="1727" RevisionGUID="e07ccded-a7ae-4e5c-a15d-d3f558f90a1c" CreationDate="2015-11-16T15:52:11.630" UserId="2041" Comment="added 95 characters in body" Text="Questions about image-based height-field representations, commonly used to represent a terrain." ContentLicense="CC BY-SA 3.0" />
  <row Id="3368" PostHistoryTypeId="24" PostId="1727" RevisionGUID="e07ccded-a7ae-4e5c-a15d-d3f558f90a1c" CreationDate="2015-11-16T15:52:11.630" Comment="Proposed by 2041 approved by 127 edit id of 103" ContentLicense="CC BY-SA 3.0" />
  <row Id="3369" PostHistoryTypeId="2" PostId="1728" RevisionGUID="d2b0bdff-ef3b-455f-80ee-2cc97298f61b" CreationDate="2015-11-16T18:19:51.997" UserId="56" Text="The best I've personally seen is the stuff inigo quillez does, which is used in demoscene stuff. Ray March the terrain, taking larger steps the farther you get from the camera since (usually) detail matters less at a distance (exception = thin walls!). He uses penetration info and other easily gotten metrics to simulate ambient occlusion and other sophisticated lighting techniques.&#xD;&#xA;&#xD;&#xA;Here's a demo of the stuff in action:&#xD;&#xA;https://www.youtube.com/watch?v=_YWMGuh15nE&#xD;&#xA;&#xD;&#xA;And here is IQ's page on the terrain raymarching which is a pretty interesting read:&#xD;&#xA;http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="3370" PostHistoryTypeId="5" PostId="1728" RevisionGUID="70cc029d-8e35-487e-ac62-7dd518d958dc" CreationDate="2015-11-16T19:00:24.480" UserId="56" Comment="Added info on screen space reflections" Text="The best I've personally seen is the stuff inigo quillez does, which is used in demoscene stuff. Ray March the terrain, taking larger steps the farther you get from the camera since (usually) detail matters less at a distance (exception = thin walls!). He uses penetration info and other easily gotten metrics to simulate ambient occlusion and other sophisticated lighting techniques.&#xD;&#xA;&#xD;&#xA;Here's a demo of the stuff in action:&#xD;&#xA;https://www.youtube.com/watch?v=_YWMGuh15nE&#xD;&#xA;&#xD;&#xA;And here is IQ's page on the terrain raymarching which is a pretty interesting read:&#xD;&#xA;http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm&#xD;&#xA;&#xD;&#xA;BTW, in modern games, the technique of &quot;screen space reflection&quot; often is just a ray march against the Z buffer of the rendered scene.  The Z buffer is really just a heightfield.&#xD;&#xA;&#xD;&#xA;I saw some talks on this at siggraph 2014, and while some of the people were using similar techniques as IQ, a few were doing things not even as well as IQ, which was interesting to see :P" ContentLicense="CC BY-SA 3.0" />
  <row Id="3371" PostHistoryTypeId="2" PostId="1729" RevisionGUID="d66254d7-7fd0-4070-ae31-fb3c84301806" CreationDate="2015-11-16T22:52:48.660" UserId="2064" Text="I'm using hardware tessellation to render a terrain mesh with variable LOD.&#xD;&#xA;&#xD;&#xA;I have this snippet on my tessellation control shader:&#xD;&#xA;&#xD;&#xA;    int edge1 = gl_InvocationID;&#xD;&#xA;    int edge2 = (gl_InvocationID + 1) % 3;&#xD;&#xA;    tcs_out[gl_InvocationID].color = vec4(computeLODColor(gl_TessLevelOuter[edge1], gl_TessLevelOuter[edge2]), 1.0);&#xD;&#xA;&#xD;&#xA;This should compute a color for the control point based on the tessellation level of the two edges that intersect on the point (using quad patches).&#xD;&#xA;&#xD;&#xA;It's all working fine except for this: `gl_TessLevelOuter[edge1]` and `gl_TessLevelOuter[edge1]`.&#xD;&#xA;&#xD;&#xA;This indexing always return 0 (I've tried using it directly as a color). To test the problem, I tried this: `gl_TessLevelOuter[gl_InvocationID]`. It also has the same behavior.&#xD;&#xA;&#xD;&#xA;If I do something like this: &#xD;&#xA;&#xD;&#xA;    if(gl_InvocationID == 0) {&#xD;&#xA;    	tcs_out[gl_InvocationID].color = vec4(computeLODColor(gl_TessLevelOuter[0], gl_TessLevelOuter[1]), 1.0);&#xD;&#xA;    }&#xD;&#xA;    else if(gl_InvocationID == 1) {&#xD;&#xA;    	tcs_out[gl_InvocationID].color = vec4(computeLODColor(gl_TessLevelOuter[1], gl_TessLevelOuter[2]), 1.0);&#xD;&#xA;    }&#xD;&#xA;    else if(gl_InvocationID == 2) {&#xD;&#xA;    	tcs_out[gl_InvocationID].color = vec4(computeLODColor(gl_TessLevelOuter[2], gl_TessLevelOuter[3]), 1.0);&#xD;&#xA;    }&#xD;&#xA;    else if(gl_InvocationID == 3) {&#xD;&#xA;    	tcs_out[gl_InvocationID].color = vec4(computeLODColor(gl_TessLevelOuter[3], gl_TessLevelOuter[0]), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;then it all works as expected.&#xD;&#xA;&#xD;&#xA;I've checked the OpenGL specification and couldn't find anything about undefined behavior when indexing `gl_TessLevelOuter` by a non-constant value.&#xD;&#xA;&#xD;&#xA;So the question is, am I misunderstanding something, doing something against the specification or is it a GL implementation bug?&#xD;&#xA;&#xD;&#xA;I'm using an AMD Radeon HD 6700 with updated drivers, and there are no warnings compiling the shaders. (I've never seen a single shader compiler warning  though, so not sure if that's another problem)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3372" PostHistoryTypeId="1" PostId="1729" RevisionGUID="d66254d7-7fd0-4070-ae31-fb3c84301806" CreationDate="2015-11-16T22:52:48.660" UserId="2064" Text="Indexing gl_TessLevelOuter[] with gl_InvocationID on a tessellation control shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="3373" PostHistoryTypeId="3" PostId="1729" RevisionGUID="d66254d7-7fd0-4070-ae31-fb3c84301806" CreationDate="2015-11-16T22:52:48.660" UserId="2064" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3374" PostHistoryTypeId="2" PostId="1730" RevisionGUID="e83d158b-6fd7-43f9-aa5c-42c316b44bbc" CreationDate="2015-11-17T16:21:39.400" UserId="1588" Text="I have been trying to implement the following functionality in my code:&#xD;&#xA;&lt;br&gt;There are 2 flags editMode and deleteMode, both set to zero.&#xD;&#xA;&lt;br&gt;with the help of keys function in glutKeyBoardFunc(keys) the user can press keys ( 'c' and 'd' respectively) to set editMode and deleteMode to 1.The following is the algo for my mouse fucntion.:&#xD;&#xA;&#xD;&#xA;    when ( editMode == 0)&#xD;&#xA;           left click plots the point&#xD;&#xA;           right click plots beizer curve&#xD;&#xA;    when ( editMode == 1)&#xD;&#xA;           left click to displace the point to new postion and draw new beizer curve&#xD;&#xA;           right click to exit editMode(i.e set editMode to 0)&#xD;&#xA;    when (deleteMode = 1)&#xD;&#xA;           left click to click any point to delete it and draw new beizer curve&#xD;&#xA;           right click to exit delete mode(i.e set deleteMode to 0)&#xD;&#xA;The problem is when I am in editMode == 1, on first instance of left click my delete function is called to delete a point in beizer curve.&#xD;&#xA;&lt;br&gt; Is there anything specific to the mouse listener which I am missing?&#xD;&#xA;&lt;br&gt; Any new way to set controls for the above functions is welcome..&#xD;&#xA;&lt;br&gt; Thank you.. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3375" PostHistoryTypeId="1" PostId="1730" RevisionGUID="e83d158b-6fd7-43f9-aa5c-42c316b44bbc" CreationDate="2015-11-17T16:21:39.400" UserId="1588" Text="How does function for mouse in glutMouseFunc(mouse) work in openGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3376" PostHistoryTypeId="3" PostId="1730" RevisionGUID="e83d158b-6fd7-43f9-aa5c-42c316b44bbc" CreationDate="2015-11-17T16:21:39.400" UserId="1588" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3377" PostHistoryTypeId="2" PostId="1731" RevisionGUID="a4ab7a2f-9a45-44fc-8e30-e075110d98ae" CreationDate="2015-11-17T21:51:32.030" UserId="2076" Text="I have two rectangles—one with a fill (blue) and one with a stroke (red). The red rectangle is being offset (depending on the stroke width) so that it appears snug and outside the edge of the blue rectangle.&#xD;&#xA;&#xD;&#xA;This set up works great except when I need to round the corners. &#xD;&#xA;&#xD;&#xA;As you can see I'm getting gaps between the rectangles and I'm stuck trying to figure out the math to calculate the right roundness amount for the outside rectangle (red).&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;![Rectangles](https://dl.dropboxusercontent.com/u/1414976/rectangles.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3378" PostHistoryTypeId="1" PostId="1731" RevisionGUID="a4ab7a2f-9a45-44fc-8e30-e075110d98ae" CreationDate="2015-11-17T21:51:32.030" UserId="2076" Text="How to calculate matching roundness of two offset rectangles" ContentLicense="CC BY-SA 3.0" />
  <row Id="3379" PostHistoryTypeId="3" PostId="1731" RevisionGUID="a4ab7a2f-9a45-44fc-8e30-e075110d98ae" CreationDate="2015-11-17T21:51:32.030" UserId="2076" Text="|curve|2d|bezier-curve|vector-graphics|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3380" PostHistoryTypeId="2" PostId="1732" RevisionGUID="17cfb849-825e-4817-8002-bee5bada58ef" CreationDate="2015-11-18T07:56:05.453" UserId="127" Text="What you (probably) want to achieve is something like this:&#xD;&#xA;&#xD;&#xA;[![box][1]][1]&#xD;&#xA;&#xD;&#xA;When having a closer look at one of the corners and add a few lines, we see this:&#xD;&#xA;&#xD;&#xA;[![corner][2]][2]&#xD;&#xA;&#xD;&#xA;The black lines indicate that the center points of the circles along the borders of the red and blue boxes is the same. If the outer radius of the red box, for example, is $50px$, and the distance between the outer borders of the red and blue boxes is $25px$, this leads to a border radius of $50px - 25px = 25px$ for the blue box. The distance, obviously, is dependent on the stroke width of your red stroke.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note: When creating the above images, I simply drew two filled boxes with rounded corners. So first a filled red box and then a smaller filled blue box above it. This also avoids some pixels being left white due to rounding errors (no pun intended).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Y1crM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4w6mA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3381" PostHistoryTypeId="5" PostId="1731" RevisionGUID="ff46ba7f-cee6-4643-87f5-eec98f6c7013" CreationDate="2015-11-18T08:22:57.373" UserId="127" Comment="Added question mark to title" Text="I have two rectangles — one with a fill (blue) and one with a stroke (red). The red rectangle is being offset (depending on the stroke width) so that it appears snug and outside the edge of the blue rectangle.&#xD;&#xA;&#xD;&#xA;This set up works great except when I need to round the corners. &#xD;&#xA;&#xD;&#xA;As you can see I'm getting gaps between the rectangles and I'm stuck trying to figure out the math to calculate the right roundness amount for the outside rectangle (red).&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;![Rectangles](https://dl.dropboxusercontent.com/u/1414976/rectangles.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3382" PostHistoryTypeId="4" PostId="1731" RevisionGUID="ff46ba7f-cee6-4643-87f5-eec98f6c7013" CreationDate="2015-11-18T08:22:57.373" UserId="127" Comment="Added question mark to title" Text="How to calculate matching roundness of two offset rectangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3388" PostHistoryTypeId="2" PostId="1734" RevisionGUID="1fc96264-819d-4ffc-8e20-dbfe66be3f3d" CreationDate="2015-11-19T01:58:30.133" UserId="2084" Text="After spending a few days making very little headway with a simple Raytracing program that implements Phong illumination (with shadows and no attenuation), I'm convinced I've made a logic error that I'm overlooking.  &#xD;&#xA;&#xD;&#xA;As I understand it, the pseudo-code should look like this:&#xD;&#xA;&#xD;&#xA;    ambient light&#xD;&#xA;    for each light source&#xD;&#xA;    	direction of light = light point - point on the object&#xD;&#xA;    	test for an intersection starting at the point on the object, until you hit something&#xD;&#xA;    	if (the intersection test returned a distance &gt; distance from point on object to light point)&#xD;&#xA;    	(do  diffuse and specular shading)&#xD;&#xA;&#xD;&#xA;A one quick thing to mention about my implementation: the intersection test will return 9999999 if there is no intersection.&#xD;&#xA;&#xD;&#xA;Some of the things I've tried are: inverting the direction of the shadow ray - no effect. Making the comparison intersection distance - light distance &gt; (some small epsilon value) - no change.  Manually moving the light source to the opposite side - the specular reflection moved to a new spot, but otherwise, no change.   &#xD;&#xA;&#xD;&#xA;Here's a picture of my most recent output, I'm trying to get a shadow in the bottom left corner of the light gray plane.  &#xD;&#xA;&#xD;&#xA;[![The shadow should be in the lower left corner of the plane][1]][1]&#xD;&#xA;&#xD;&#xA;Any help would be greatly appreciated.  &#xD;&#xA;&#xD;&#xA;Here's the relevant part of my code:&#xD;&#xA;&#xD;&#xA;    	//iterate through all lights&#xD;&#xA;    	if (myLights.size() &gt; 0)&#xD;&#xA;    	{&#xD;&#xA;    		for (int i = 0; i &lt; myLights.size(); i++)&#xD;&#xA;    		{&#xD;&#xA;    			//calculate the direction of the light&#xD;&#xA;    			glm::vec3 ldir = (myLights[i].position - surfacePoint);&#xD;&#xA;    			//this the length of the distance between the light and the surface&#xD;&#xA;    			float ldist= sqrt(pow(ldir.x, 2.0f) + pow(ldir.y, 2.0f) + pow(ldir.z, 2.0f)); &#xD;&#xA;    //check if the light can see the surface point&#xD;&#xA;    			float intersections = myObjGroup-&gt;testIntersections(surfacePoint, normalize(ldir));&#xD;&#xA;    			if (abs(intersections-ldist)  &gt; 0.0000001f)&#xD;&#xA;    			{&#xD;&#xA;    				//diffuse and specular shading have been cut for brevity&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jnsiR.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3389" PostHistoryTypeId="1" PostId="1734" RevisionGUID="1fc96264-819d-4ffc-8e20-dbfe66be3f3d" CreationDate="2015-11-19T01:58:30.133" UserId="2084" Text="Shadow rays in Raytracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="3390" PostHistoryTypeId="3" PostId="1734" RevisionGUID="1fc96264-819d-4ffc-8e20-dbfe66be3f3d" CreationDate="2015-11-19T01:58:30.133" UserId="2084" Text="|raytracing|c++|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3394" PostHistoryTypeId="2" PostId="1736" RevisionGUID="63aeb665-ed22-4844-a8de-9a69b5fe6ba1" CreationDate="2015-11-19T04:10:30.597" UserId="288" Text="When rendering VR ( stereo view ) environments, do you guys recommend just doing 2 frustum checks for determining what is to be drawn during the frustum culling pass or is there some other check that would be able to combine both frusta?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3395" PostHistoryTypeId="1" PostId="1736" RevisionGUID="63aeb665-ed22-4844-a8de-9a69b5fe6ba1" CreationDate="2015-11-19T04:10:30.597" UserId="288" Text="VR and frustum culling" ContentLicense="CC BY-SA 3.0" />
  <row Id="3396" PostHistoryTypeId="3" PostId="1736" RevisionGUID="63aeb665-ed22-4844-a8de-9a69b5fe6ba1" CreationDate="2015-11-19T04:10:30.597" UserId="288" Text="|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3397" PostHistoryTypeId="2" PostId="1737" RevisionGUID="e04e6454-2b3c-4006-8ad7-5f694026296a" CreationDate="2015-11-19T05:09:30.257" UserId="48" Text="It's pretty easy to create a single frustum that encloses both of the individual eye frusta, as shown in this diagram created by Cass Everitt at Oculus. You just have to place the vertex of this frustum between the eyes and behind them a little bit. You can also increase the near plane distance to match the original near plane of the eye frusta.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Such a frustum includes a little space that wasn't in the union of the original two frusta. There's a small volume horizontally between the two eyes; also, the diagram doesn't show the vertical dimension, but pulling the frustum vertex back makes it include some space above and below the original frusta. However, for practical culling purposes it probably doesn't matter. Frustum culling is usually conservative anyway, and the extra space is only a few centimeters in thickness.&#xD;&#xA;&#xD;&#xA;It's also possible to simply cull against the original frustum top and bottom planes (which are shared between eyes) together with the outer side planes. These planes don't form a frustum, technically, but if using &quot;the usual&quot; culling algorithm that tests against one plane at a time, the algorithm will happily work on any set of planes you care to give it.&#xD;&#xA;&#xD;&#xA;Sharing frustum culling, LOD selection, etc. between eyes, rather than re-doing it twice every frame, is a great way to optimize the CPU cost of stereo rendering. This is also a prerequisite if you want to use a rendering method that draws both eyes in a single pass, such as [instanced stereo rendering](https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TpHYa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3398" PostHistoryTypeId="5" PostId="1730" RevisionGUID="a749b407-1c13-490d-a081-fa1737bfb663" CreationDate="2015-11-19T07:41:36.640" UserId="1588" Comment="added the new way I tried to solve the problem" Text="I have been trying to implement the following functionality in my code:&#xD;&#xA;&lt;br&gt;There are 2 flags editMode and deleteMode, both set to zero.&#xD;&#xA;&lt;br&gt;with the help of keys function in glutKeyBoardFunc(keys) the user can press keys ( 'c' and 'd' respectively) to set editMode and deleteMode to 1.The following is the algo for my mouse fucntion.:&#xD;&#xA;&#xD;&#xA;    when ( editMode == 0)&#xD;&#xA;           left click plots the point&#xD;&#xA;           right click plots beizer curve&#xD;&#xA;    when ( editMode == 1)&#xD;&#xA;           left click to displace the point to new postion and draw new beizer curve&#xD;&#xA;           right click to exit editMode(i.e set editMode to 0)&#xD;&#xA;    when (deleteMode = 1)&#xD;&#xA;           left click to click any point to delete it and draw new beizer curve&#xD;&#xA;           right click to exit delete mode(i.e set deleteMode to 0)&#xD;&#xA;The problem is when I am in editMode == 1, on first instance of left click my delete function is called to delete a point in beizer curve.&#xD;&#xA;&lt;br&gt; Is there anything specific to the mouse listener which I am missing?&#xD;&#xA;&lt;br&gt; Any new way to set controls for the above functions is welcome..&#xD;&#xA;&lt;br&gt; Thank you.. &#xD;&#xA;&lt;br&gt; EDIT  1:&#xD;&#xA;&lt;br&gt; I modified the logic a bit. So I have:&#xD;&#xA;&#xD;&#xA;    when( deleteMode == 0)&#xD;&#xA;    {       when (editMode == 0)&#xD;&#xA;               left click to plot points &#xD;&#xA;               right click to plot beizer&#xD;&#xA;            else when (editFlag == 1)&#xD;&#xA;               left click to displace points and draw new beizer curve&#xD;&#xA;               right click to exit editMode(i.e set editMode to 0)&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;           when ( left_mouse_button == TRUE)&#xD;&#xA;           { if(editMode == 0 ) delete chosen point and draw new beizer curve}&#xD;&#xA;           when ( right_mouse_button == TRUE)&#xD;&#xA;           { exit deleteMode e(i.e set deleteMode to 0) }&#xD;&#xA;    }&#xD;&#xA;This works fairly for most of the time.And is serving my purpose for now.I have the assumption that the user goes to one mode and exits from that mode before going into other mode.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3399" PostHistoryTypeId="5" PostId="191" RevisionGUID="70571451-caee-48a0-bc92-2d6cc8ec6cff" CreationDate="2015-11-19T08:50:06.257" UserId="2041" Comment="add usage guidance and some useful links" Text="See also:&#xD;&#xA;&#xD;&#xA;* [Ray tracing on Wikipedia](https://en.wikipedia.org/wiki/Ray_tracing_%28graphics%29)&#xD;&#xA;* [Raytracing implementation questions on Stack Overflow](http://stackoverflow.com/questions/tagged/raytracing)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3400" PostHistoryTypeId="24" PostId="191" RevisionGUID="70571451-caee-48a0-bc92-2d6cc8ec6cff" CreationDate="2015-11-19T08:50:06.257" Comment="Proposed by 2041 approved by 48, 16 edit id of 100" ContentLicense="CC BY-SA 3.0" />
  <row Id="3401" PostHistoryTypeId="2" PostId="1738" RevisionGUID="460e5fa2-1b17-450b-8aac-4dbf4e21977b" CreationDate="2015-11-19T10:11:47.387" UserId="2041" Text="Your `if` condition makes me suspicious. You should include the diffuse and specular shading if the intersection test **didn't** hit an object; that is, if `intersections &gt; ldist`. So, your code should look as follows:&#xD;&#xA;&#xD;&#xA;    if (intersections &gt; ldist)&#xD;&#xA;    {&#xD;&#xA;        colour += diffuse(...);&#xD;&#xA;        colour += specular(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Your comparison with 0.0000001f suggests that you've also been having trouble with self-intersections (that is, with the ray intersecting the object being shaded). In a one-hit tracer, you can't fix that problem by simply discarding the intersection, because you still don't know whether the shadow ray would have intersected another object further along. To avoid self-intersections, you need to push the start point of the ray along its direction by epsilon:&#xD;&#xA;&#xD;&#xA;    glm::vec3 direction = normalize(ldir);&#xD;&#xA;    glm::vec3 start = surfacePoint + epsilon * direction;&#xD;&#xA;    float intersections = myObjGroup-&gt;testIntersections(start, direction);" ContentLicense="CC BY-SA 3.0" />
  <row Id="3403" PostHistoryTypeId="2" PostId="1739" RevisionGUID="811c2d7f-f7dd-48d2-bb24-c3f62b33d37b" CreationDate="2015-11-19T13:01:01.153" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3404" PostHistoryTypeId="2" PostId="1740" RevisionGUID="90033fd1-eab0-48f7-8c00-329d9ecee8e5" CreationDate="2015-11-19T13:01:01.153" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3405" PostHistoryTypeId="5" PostId="1739" RevisionGUID="35f7026c-acda-486a-933d-687839d629c9" CreationDate="2015-11-19T13:48:46.187" UserId="2041" Comment="added 998 characters in body" Text="A shadow is a dark region caused when light from an emitter is blocked by a shadowing object, causing a contrast between the dark region and the surrounding region which is fully lit. The emitter might be a point, cone, cylindrical light, an area light or image-based light. The shadowing object might be fully opaque or partially transparent, in which case it will cast coloured shadows (like stained glass). The dark region might be the lighting on another surface (the shadowed object), or it might be an environment shadow in some kind of volumetric medium.&#xD;&#xA;&#xD;&#xA;This tag is appropriate whatever technique you're using to simulate shadows, whether by shadow rays in a raytracer, some kind of shadow maps or volumes, or something else completely.&#xD;&#xA;&#xD;&#xA;If your problem is with shadowing indirect light in a global illumination system, you probably want a more specific tag. If your problem is with self-shadowing of micro-geometry, e.g. in the derivation of a shader, you should use a tag about that." ContentLicense="CC BY-SA 3.0" />
  <row Id="3406" PostHistoryTypeId="24" PostId="1739" RevisionGUID="35f7026c-acda-486a-933d-687839d629c9" CreationDate="2015-11-19T13:48:46.187" Comment="Proposed by 2041 approved by 16 edit id of 104" ContentLicense="CC BY-SA 3.0" />
  <row Id="3407" PostHistoryTypeId="5" PostId="1740" RevisionGUID="28c69e49-377c-45c0-849c-8161ea66b0dd" CreationDate="2015-11-19T13:48:52.383" UserId="2041" Comment="added 114 characters in body" Text="Shadows cast by objects in front of lights, whether raytraced, shadow maps, shadow volumes, or any other technique" ContentLicense="CC BY-SA 3.0" />
  <row Id="3408" PostHistoryTypeId="24" PostId="1740" RevisionGUID="28c69e49-377c-45c0-849c-8161ea66b0dd" CreationDate="2015-11-19T13:48:52.383" Comment="Proposed by 2041 approved by 16 edit id of 105" ContentLicense="CC BY-SA 3.0" />
  <row Id="3409" PostHistoryTypeId="2" PostId="1741" RevisionGUID="03c764c8-7951-4824-9f1c-c789e9fdce9e" CreationDate="2015-11-19T18:17:37.720" UserId="2091" Text="I'm doing a quick and dirty automated deformation routine on a polygon body.  If it was a tree, and my axis was in the center of the tree, I would like to bend the body by bending the axis.  I would use a simple influencing algorithm to determine vertex point xyz displacement.  &#xD;&#xA;&#xD;&#xA;On the concave side of the bend, how can I check for polygons that have overlapped or passed through each other, and how can I fix such polygons?&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="3410" PostHistoryTypeId="1" PostId="1741" RevisionGUID="03c764c8-7951-4824-9f1c-c789e9fdce9e" CreationDate="2015-11-19T18:17:37.720" UserId="2091" Text="After a deformation operation on polygons, how can I check for and fix inverted polys?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3411" PostHistoryTypeId="3" PostId="1741" RevisionGUID="03c764c8-7951-4824-9f1c-c789e9fdce9e" CreationDate="2015-11-19T18:17:37.720" UserId="2091" Text="|algorithm|3d|transformations|mesh|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3414" PostHistoryTypeId="2" PostId="1743" RevisionGUID="cc97615c-bd6e-4640-acd2-2420c161f10b" CreationDate="2015-11-19T22:31:31.463" UserId="2092" Text="I'm cross-posting this from regular Stack Overflow because I just heard about this community. Hope you guys can help :)&#xD;&#xA;&#xD;&#xA;I've been trying to implement the [Moller-Trumbore ray-triangle intersection algorithm](https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm) in my raytracing code. The code is supposed to read in a mesh and light sources, fire off rays from the light source, and return the triangle from the mesh which each ray intersects. Here is my implementation of the algorithm:&#xD;&#xA;&#xD;&#xA;    //Moller-Trumbore intersection algorithm&#xD;&#xA;    void getFaceIntersect(modelStruct m, ray r, hitFaceStruct&amp; hitFaces)&#xD;&#xA;    {&#xD;&#xA;	// Constant thoughout loop&#xD;&#xA;	point origin = r.p0;&#xD;&#xA;	point direction = r.u;&#xD;&#xA;	hitFaces.isHit = false;&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; m.faces; i++)&#xD;&#xA;	{&#xD;&#xA;		// Get face vertices&#xD;&#xA;		point v1 = m.vertList[m.faceList[i].v1];&#xD;&#xA;		point v2 = m.vertList[m.faceList[i].v2];&#xD;&#xA;		point v3 = m.vertList[m.faceList[i].v3];&#xD;&#xA;		&#xD;&#xA;		// Get two edgess&#xD;&#xA;		point edge1 = v2 - v1;&#xD;&#xA;		point edge2 = v3 - v1;&#xD;&#xA;		&#xD;&#xA;		// Get p&#xD;&#xA;		point p = direction.cross(direction, edge2);&#xD;&#xA;		// Use p to find determinant&#xD;&#xA;		double det = p.dot(edge1, p);&#xD;&#xA;		&#xD;&#xA;		// If the determinant is about 0, the ray lies in the plane of the triangle&#xD;&#xA;		if (abs(det) &lt; 0.00000000001)&#xD;&#xA;        {&#xD;&#xA;			continue;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		double inverseDet = 1 / det;&#xD;&#xA;&#xD;&#xA;		point v1ToOrigin = (origin - v1);&#xD;&#xA;&#xD;&#xA;		double u = v1ToOrigin.dot(v1ToOrigin, p) * inverseDet;&#xD;&#xA;&#xD;&#xA;		// If u is not between 0 and 1, no hit&#xD;&#xA;		if (u &lt; 0 || u &gt; 1)&#xD;&#xA;        {&#xD;&#xA;			continue;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		// Used for calculating v&#xD;&#xA;		point q = v1ToOrigin.cross(v1ToOrigin, edge1);&#xD;&#xA;		double v = direction.dot(direction, q) * inverseDet;&#xD;&#xA;&#xD;&#xA;		if (v &lt; 0 || (u + v) &gt; 1)&#xD;&#xA;		{&#xD;&#xA;			continue;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		double t = q.dot(edge2, q) * inverseDet;&#xD;&#xA;&#xD;&#xA;		// gets closest face&#xD;&#xA;		if (t &lt; abs(hitFaces.s)) {&#xD;&#xA;&#xD;&#xA;			hitFaceStruct goodStruct = hitFaceStruct();&#xD;&#xA;			goodStruct.face = i;&#xD;&#xA;			goodStruct.hitPoint = p;&#xD;&#xA;			goodStruct.isHit = true;&#xD;&#xA;			goodStruct.s = t;&#xD;&#xA;			hitFaces = goodStruct;&#xD;&#xA;			break;&#xD;&#xA;		}&#xD;&#xA;	  }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The relevant code for hitFaceStruct and modelStruct is as follows:       &#xD;&#xA;&#xD;&#xA;    typedef struct _hitFaceStruct&#xD;&#xA;    {&#xD;&#xA;    int face; //the index of the sphere in question in the list of faces&#xD;&#xA;    float s; //the distance from the ray that hit it&#xD;&#xA;	bool isHit;&#xD;&#xA;	point hitPoint;&#xD;&#xA;        } hitFaceStruct;&#xD;&#xA;&#xD;&#xA;    typedef struct _modelStruct {&#xD;&#xA;	char *fileName;&#xD;&#xA;	float scale;&#xD;&#xA;	float rot_x, rot_y, rot_z;&#xD;&#xA;	float x, y, z;&#xD;&#xA;	float r_amb, g_amb, b_amb;&#xD;&#xA;	float r_dif, g_dif, b_dif;&#xD;&#xA;	float r_spec, g_spec, b_spec;&#xD;&#xA;	float k_amb, k_dif, k_spec, k_reflective, k_refractive;&#xD;&#xA;	float spec_exp, index_refraction;&#xD;&#xA;	int verts, faces, norms = 0;    // Number of vertices, faces, normals, and spheres in the system&#xD;&#xA;	point *vertList, *normList; // Vertex and Normal Lists&#xD;&#xA;	faceStruct *faceList;	    // Face List&#xD;&#xA;    } modelStruct;&#xD;&#xA;&#xD;&#xA;Whenever I shoot a ray, the values of u or v in the algorithm code always come out to a large negative number, rather than the expected small, positive one. The direction vector of the ray is normalized before I pass it on to the intersection code, and I'm positive I'm firing rays that would normally hit the mesh. Can anyone please help me spot my error here?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="3415" PostHistoryTypeId="1" PostId="1743" RevisionGUID="cc97615c-bd6e-4640-acd2-2420c161f10b" CreationDate="2015-11-19T22:31:31.463" UserId="2092" Text="Ray-triangle intersection algorithm not intersecting (C++)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3416" PostHistoryTypeId="3" PostId="1743" RevisionGUID="cc97615c-bd6e-4640-acd2-2420c161f10b" CreationDate="2015-11-19T22:31:31.463" UserId="2092" Text="|opengl|raytracing|algorithm|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3417" PostHistoryTypeId="5" PostId="1734" RevisionGUID="eeddbb13-873b-4be8-b964-38717fd8a790" CreationDate="2015-11-19T23:55:07.770" UserId="2084" Comment="added 86 characters in body" Text="After spending a few days making very little headway with a simple Raytracing program that implements Phong illumination (with shadows and no attenuation), I'm convinced I've made a logic error that I'm overlooking.  &#xD;&#xA;&#xD;&#xA;As I understand it, the pseudo-code should look like this:&#xD;&#xA;&#xD;&#xA;    ambient light&#xD;&#xA;    for each light source&#xD;&#xA;    	direction of light = light point - point on the object&#xD;&#xA;    	test for an intersection starting at the point on the object, until you hit something&#xD;&#xA;    	if (the intersection test returned a distance &gt; distance from point on object to light point)&#xD;&#xA;    	(do  diffuse and specular shading)&#xD;&#xA;&#xD;&#xA;A one quick thing to mention about my implementation: the intersection test will return 9999999 if there is no intersection.&#xD;&#xA;&#xD;&#xA;Some of the things I've tried are: inverting the direction of the shadow ray - no effect. Making the comparison intersection distance - light distance &gt; (some small epsilon value) - no change.  Manually moving the light source to the opposite side - the specular reflection moved to a new spot, but otherwise, no change.   &#xD;&#xA;&#xD;&#xA;Here's a picture of my most recent output, I'm trying to get a shadow in the bottom left corner of the light gray plane.  &#xD;&#xA;&#xD;&#xA;[![The shadow should be in the lower left corner of the plane][1]][1]&#xD;&#xA;&#xD;&#xA;Any help would be greatly appreciated.  &#xD;&#xA;&#xD;&#xA;Here's the relevant part of my code:&#xD;&#xA;&#xD;&#xA;    	//iterate through all lights&#xD;&#xA;    	if (myLights.size() &gt; 0)&#xD;&#xA;    	{&#xD;&#xA;    		for (int i = 0; i &lt; myLights.size(); i++)&#xD;&#xA;    		{&#xD;&#xA;    			//calculate the direction of the light&#xD;&#xA;    			glm::vec3 ldir = (myLights[i].position - surfacePoint);&#xD;&#xA;    			//this the length of the distance between the light and the surface&#xD;&#xA;    			float ldist= sqrt(pow(ldir.x, 2.0f) + pow(ldir.y, 2.0f) + pow(ldir.z, 2.0f)); &#xD;&#xA;    //check if the light can see the surface point&#xD;&#xA;    			float intersections = myObjGroup-&gt;testIntersections(surfacePoint, normalize(ldir));&#xD;&#xA;    			if (abs(intersections-ldist)  &gt; 0.0000001f)&#xD;&#xA;    			{&#xD;&#xA;    				//diffuse and specular shading have been cut for brevity&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;edit: New image:&#xD;&#xA;[![New image!][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jnsiR.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/2pAxT.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3419" PostHistoryTypeId="5" PostId="1738" RevisionGUID="bcd31957-d180-4b2e-86cf-941d261f3e7a" CreationDate="2015-11-20T09:15:00.770" UserId="2041" Comment="Add a note on shadowing too." Text="Your `if` condition makes me suspicious. You should include the diffuse and specular shading if the intersection test **didn't** hit an object; that is, if `intersections &gt; ldist`. So, your code should look as follows:&#xD;&#xA;&#xD;&#xA;    if (intersections &gt; ldist)&#xD;&#xA;    {&#xD;&#xA;        colour += diffuse(...);&#xD;&#xA;        colour += specular(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Your comparison with 0.0000001f suggests that you've also been having trouble with self-intersections (that is, with the ray intersecting the object being shaded). In a one-hit tracer, you can't fix that problem by simply discarding the intersection, because you still don't know whether the shadow ray would have intersected another object further along. To avoid self-intersections, you need to push the start point of the ray along its direction by epsilon:&#xD;&#xA;&#xD;&#xA;    glm::vec3 direction = normalize(ldir);&#xD;&#xA;    glm::vec3 start = surfacePoint + epsilon * direction;&#xD;&#xA;    float intersections = myObjGroup-&gt;testIntersections(start, direction);&#xD;&#xA;&#xD;&#xA;One more thing: don't forget to test that the light is in front of the surface that you're illuminating. You can do this with the dot product of `ldir` and the surface normal: if the dot product is positive, the light is on the correct side; if it's negative, the light is behind the surface and thus shadowed before you even cast a ray." ContentLicense="CC BY-SA 3.0" />
  <row Id="3420" PostHistoryTypeId="2" PostId="1744" RevisionGUID="d18a524b-81f8-4e93-b3cb-5408dda0ce8b" CreationDate="2015-11-20T12:41:12.840" UserId="2100" Text="I am looking for smooth way to enhance scans of golden emboss on. For now it takes sometimes hours to select out the golden part and then manipulate into suitable color. But I hope to learn some more neat way to do it.&#xD;&#xA;&#xD;&#xA;So here I provide 2 sample images, one before and other after:&#xD;&#xA;&#xD;&#xA;[![image after scan][1]][1]&#xD;&#xA;&#xD;&#xA;[![image with enhanced golden emboss][2]][2]&#xD;&#xA;&#xD;&#xA;So, after lot of annoying work to select out the golden part from background it still looks out clumsy. So, how it might work out smoothly? Is there some tutorial for that?&#xD;&#xA;&#xD;&#xA;Basicly, what I did now? &#xD;&#xA;&#xD;&#xA;1. made duplicate layer of background&#xD;&#xA;2. selected and erased background on duplicate layer with different tools (most work of which I'd like to get rid of)&#xD;&#xA;3. selected background and inverted selection&#xD;&#xA;4. feathered selection 5px&#xD;&#xA;5. with Colorize got it to some goldish tone&#xD;&#xA;6. slide layer opacity ca 60%&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vQvZi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LFW5N.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3421" PostHistoryTypeId="1" PostId="1744" RevisionGUID="d18a524b-81f8-4e93-b3cb-5408dda0ce8b" CreationDate="2015-11-20T12:41:12.840" UserId="2100" Text="How to enchance scans of golden emboss?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3422" PostHistoryTypeId="3" PostId="1744" RevisionGUID="d18a524b-81f8-4e93-b3cb-5408dda0ce8b" CreationDate="2015-11-20T12:41:12.840" UserId="2100" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3423" PostHistoryTypeId="4" PostId="1744" RevisionGUID="e3bc18a8-318d-42b0-9f7e-eb1fe180cd35" CreationDate="2015-11-20T15:53:18.737" UserId="16" Comment="edited title" Text="How to enhance scans of golden emboss?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3425" PostHistoryTypeId="5" PostId="1741" RevisionGUID="6cd12abf-3ca9-45f0-8ceb-23a37b14db5f" CreationDate="2015-11-20T18:26:08.183" UserId="2091" Comment="added rough illustration" Text="I'm doing a quick and dirty automated deformation routine on a polygon body.  If it was a tree, and my axis was in the center of the tree, I would like to bend the body by bending the axis.  I would use a simple influencing algorithm to determine vertex point xyz displacement.  &#xD;&#xA;&#xD;&#xA;On the concave side of the bend, how can I check for polygons that have overlapped or passed through each other, and how can I fix such polygons?&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;[![Rough Illustration of concept][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ObYbr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3426" PostHistoryTypeId="36" PostId="1745" RevisionGUID="2d5ec9c0-fd70-4f89-8254-f1d927a50994" CreationDate="2015-11-21T06:58:02.370" UserId="-1" Comment="from http://physics.stackexchange.com/questions/219433/what-would-be-the-correct-way-to-calculate-saturation-in-this-case" />
  <row Id="3427" PostHistoryTypeId="2" PostId="1745" RevisionGUID="a37012de-afff-4beb-bf1e-6b99eb850a2f" CreationDate="2015-11-19T16:45:14.177" UserId="2110" UserDisplayName="abcd5555" Text="I'm trying to make a HSV representation of the xyY color space. To calculate hue from an (x, y) color, I use the angle between that color and red (wavelength 745) on the xy chromacity diagram, with white (1/3, 1/3) as the center.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The saturation is the ratio between the distance between white and (x, y), and white and a fully-saturated version of (x, y) (which is the intersection between the line between (1/3, 1/3) and (x, y) and the edge of the chromacity diagram).&#xD;&#xA;&#xD;&#xA;*xy chromacity diagram:*&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/SzQiv.png&quot; width=&quot;300&quot;&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem that I'm having is that when I plot my color space (at value=1) and compare it to the HSV representation of RGB, the saturation (distance from center) doesn't seem to match how &quot;colorful&quot; the color actually is:&#xD;&#xA;&#xD;&#xA;*My color space (saturation seems wrong):*&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/t1rfO.png&quot; width=&quot;300&quot;&gt;&#xD;&#xA;&#xD;&#xA;*HSV color space of RGB:*&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/g0a9x.png&quot; width=&quot;300&quot;&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How should I calculate saturation instead?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3428" PostHistoryTypeId="1" PostId="1745" RevisionGUID="a37012de-afff-4beb-bf1e-6b99eb850a2f" CreationDate="2015-11-19T16:45:14.177" UserId="2110" UserDisplayName="abcd5555" Text="What would be the correct way to calculate saturation in this case?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3429" PostHistoryTypeId="3" PostId="1745" RevisionGUID="a37012de-afff-4beb-bf1e-6b99eb850a2f" CreationDate="2015-11-19T16:45:14.177" UserId="2110" UserDisplayName="abcd5555" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3430" PostHistoryTypeId="5" PostId="1745" RevisionGUID="8175616c-7d99-429b-a380-a9a66f435423" CreationDate="2015-11-21T08:33:17.890" UserId="127" Comment="Edited tags, added MathJax" Text="I'm trying to make a HSV representation of the xyY color space. To calculate hue from an $(x, y)$ color, I use the angle between that color and red (wavelength 745) on the xy chromacity diagram, with white $(\frac{1}{3}, \frac{1}{3})$ as the center.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The saturation is the ratio between the distance between white and $(x, y)$, and white and a fully-saturated version of $(x, y)$ (which is the intersection between the line between $(\frac{1}{3}, \frac{1}{3})$ and $(x, y)$ and the edge of the chromacity diagram).&#xD;&#xA;&#xD;&#xA;*xy chromacity diagram:*&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/SzQiv.png&quot; width=&quot;300&quot;&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem that I'm having is that when I plot my color space (at value=1) and compare it to the HSV representation of RGB, the saturation (distance from center) doesn't seem to match how &quot;colorful&quot; the color actually is:&#xD;&#xA;&#xD;&#xA;*My color space (saturation seems wrong):*&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/t1rfO.png&quot; width=&quot;300&quot;&gt;&#xD;&#xA;&#xD;&#xA;*HSV color space of RGB:*&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/g0a9x.png&quot; width=&quot;300&quot;&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How should I calculate saturation instead?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3431" PostHistoryTypeId="6" PostId="1745" RevisionGUID="8175616c-7d99-429b-a380-a9a66f435423" CreationDate="2015-11-21T08:33:17.890" UserId="127" Comment="Edited tags, added MathJax" Text="|color|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3433" PostHistoryTypeId="2" PostId="1746" RevisionGUID="20c0b3b1-d680-4b4a-97cf-bb3e9d31fe18" CreationDate="2015-11-21T12:04:06.943" UserId="38" Text="There is unfortunately no good answer to this question. Simply it wont work. There is no good way to define colorful, it this context. XYZ is trying to capture the physical measurement. It however does not succeed very well in relating the colors to each other.&#xD;&#xA;&#xD;&#xA;Colors on the very outer arc represent spectral distributions of close to [Dirac delta function](https://en.wikipedia.org/wiki/Dirac_delta_function). So one could construct a model that says that a color is very colorful when it is a Dirac delta. &#xD;&#xA;&#xD;&#xA;There is a unforeseen consequence of this definition though. Namely the magenta colors do not exist as Dirac Deltas. As these colors do not exist in the spectrum. So they consist of mixture of 2 wavelengths only. This would mean they are less colorful than most other colors.&#xD;&#xA;&#xD;&#xA;Other problems&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;Unfortunately, xyY is not linear. So a straight line on the xyY does not represent interpolations between 2 color mixtures. Therefore making a polar transformation means you will have different color bases on same coordinates. Also precieved color do not really move over to your model. To do this properly you would need to do a extremely sophisticated transformation.&#xD;&#xA;&#xD;&#xA;There are many problems with converting color to a polar coordinates in that that is exactly contrary how vision works. White is also a bit problematic in this context. The distance to full saturated signal is different for each of the 3 different cones in the eye. Hell, even what is while depends on the surrounding colors and ambient color conditions. So aim afraid your trying to force a worldview that does not exist.&#xD;&#xA;&#xD;&#xA;Finally&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;What would this be useful for? " ContentLicense="CC BY-SA 3.0" />
  <row Id="3434" PostHistoryTypeId="5" PostId="1746" RevisionGUID="cf52eedf-a3b6-49e4-b577-1bda93af4a74" CreationDate="2015-11-21T13:18:12.253" UserId="38" Comment="edited body" Text="There is unfortunately no good answer to this question. Simply it wont work. There is no good way to define colorful, it this context. Cie is trying to capture the physical measurement. It however does not succeed very well in relating the colors to each other.&#xD;&#xA;&#xD;&#xA;Colors on the very outer arc represent spectral distributions of close to [Dirac delta function](https://en.wikipedia.org/wiki/Dirac_delta_function). So one could construct a model that says that a color is very colorful when it is a Dirac delta. &#xD;&#xA;&#xD;&#xA;There is a unforeseen consequence of this definition though. Namely the magenta colors do not exist as Dirac Deltas. As these colors do not exist in the spectrum. So they consist of mixture of 2 wavelengths only. This would mean they are less colorful than most other colors.&#xD;&#xA;&#xD;&#xA;Other problems&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;Unfortunately, xyY is not linear. So a straight line on the xyY does not represent interpolations between 2 color mixtures. Therefore making a polar transformation means you will have different color bases on same coordinates. Also precieved color do not really move over to your model. To do this properly you would need to do a extremely sophisticated transformation.&#xD;&#xA;&#xD;&#xA;There are many problems with converting color to a polar coordinates in that that is exactly contrary how vision works. White is also a bit problematic in this context. The distance to full saturated signal is different for each of the 3 different cones in the eye. Hell, even what is while depends on the surrounding colors and ambient color conditions. So aim afraid your trying to force a worldview that does not exist.&#xD;&#xA;&#xD;&#xA;Finally&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;What would this be useful for? " ContentLicense="CC BY-SA 3.0" />
  <row Id="3436" PostHistoryTypeId="2" PostId="1747" RevisionGUID="338c8a13-bf97-4621-a0dd-4e9998e28a43" CreationDate="2015-11-22T04:39:39.110" UserId="2111" Text="For example, while it's the current top-of-the-line GPU, the GTX 980 has a staggering 72.1 gigapixels/second fillrate, which with back-to-front rendering and/or Z buffer checks, seems almost ridiculously large, possibly even at 4k resolutions. As far as polygon counts go, modern GPUs can do tens to hundreds of millions of textured triangles without a hitch if you batch and/or instantiate them properly.&#xD;&#xA;&#xD;&#xA;With forward rendering, the amount of fragments that shaders will run on can quickly become overwhelming, but with deferred rendering, the cost is usually more-or-less constant, depending on the resolution, and we long since passed a point where most shading or post-processing effects can be done in realtime in 1080p.&#xD;&#xA;&#xD;&#xA;Either way, the limiting factors nowadays are most commonly draw call counts, and shading costs, both of which are kept relatively low by proper deferred rendering and geometry batching, so with that in mind, is culling more than just backfaces and out-of-frustrum polygons of any substantial benefit? Wouldn't the costs(CPU/GPU time, programmer time) outweight the benefits, a lot of the time?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3437" PostHistoryTypeId="1" PostId="1747" RevisionGUID="338c8a13-bf97-4621-a0dd-4e9998e28a43" CreationDate="2015-11-22T04:39:39.110" UserId="2111" Text="With modern fillrates and deferred rendering, is occlussion culling still relevant?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3438" PostHistoryTypeId="3" PostId="1747" RevisionGUID="338c8a13-bf97-4621-a0dd-4e9998e28a43" CreationDate="2015-11-22T04:39:39.110" UserId="2111" Text="|occlusion|space-filling|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3439" PostHistoryTypeId="6" PostId="1747" RevisionGUID="1ca378ca-e85b-44f5-98d9-1b8421bbe716" CreationDate="2015-11-22T08:37:40.507" UserId="127" Comment="Edited tags." Text="|performance|occlusion|space-filling|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3440" PostHistoryTypeId="2" PostId="1748" RevisionGUID="6b82e25c-7a0d-4b7b-afa2-3afae2d409d5" CreationDate="2015-11-22T09:00:02.117" UserId="2040" Text="I'm trying to create a RYB color wheel with a smooth-looking gradient across the RYB spectrum. The angles of the HSV wheel are incorrect (yellow at 60deg instead of 120deg etc).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I just do a few linear transformations the results is still not appropriate; perceptually red occupies too many angles and yellow not enough. Even if I do a bit of a hack and try a non-linear polynomial gradient it's difficult to get the right &quot;spread&quot;:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is there an &quot;official&quot; function that maps HSV hue angle to RYB hue angle?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0u3Ea.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bq1cd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3441" PostHistoryTypeId="1" PostId="1748" RevisionGUID="6b82e25c-7a0d-4b7b-afa2-3afae2d409d5" CreationDate="2015-11-22T09:00:02.117" UserId="2040" Text="Function to convert HSV angle to RYB angle" ContentLicense="CC BY-SA 3.0" />
  <row Id="3442" PostHistoryTypeId="3" PostId="1748" RevisionGUID="6b82e25c-7a0d-4b7b-afa2-3afae2d409d5" CreationDate="2015-11-22T09:00:02.117" UserId="2040" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3443" PostHistoryTypeId="5" PostId="1748" RevisionGUID="dad14a01-97f8-479f-ae85-e184e093f877" CreationDate="2015-11-22T09:23:12.730" UserId="2040" Comment="added 359 characters in body" Text="I'm trying to create a RYB color wheel with a smooth-looking gradient across the RYB spectrum. The angles of the HSV wheel are incorrect (yellow at 60deg instead of 120deg etc).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I just do a few linear transformations the results is still not appropriate; perceptually red occupies too many angles and yellow not enough. Even if I do a bit of a hack and try a non-linear polynomial gradient it's difficult to get the right &quot;spread&quot;:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is there an &quot;official&quot; function that maps HSV hue angle to RYB hue angle?&#xD;&#xA;&#xD;&#xA;Update: Reading [this][3] gives some ideas, but the part about excluding cyan confused me more because of Adobe's RYB color wheel: Is this true RYB or is it CMY with hue angles shifted in the blue range?&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0u3Ea.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bq1cd.png&#xD;&#xA;  [3]: http://blufiro.blogspot.fr/2013/02/ryb-color-wheel.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/U7kPu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3444" PostHistoryTypeId="2" PostId="1749" RevisionGUID="247acdb5-72ae-4009-a76d-5e03ba7ba66b" CreationDate="2015-11-22T14:56:34.147" UserId="2040" Text="I just discovered that Adobe color source includes HSV-RYB hue mapping functions (replicated in Ben Knight's Kuler-d3). Apparently Adobe uses uses piecewise linear gradients rather than the polynomial that I was trying to use (and technically it is a CMY wheel not a RBY one, I believe). Here are the relevant stops:&#xD;&#xA;&#xD;&#xA;    RYBstop HSVstop&#xD;&#xA;    60      35&#xD;&#xA;    122     60&#xD;&#xA;    165     120&#xD;&#xA;    218     180&#xD;&#xA;    275     240&#xD;&#xA;    330     300&#xD;&#xA;&#xD;&#xA;Here is the graph of these showing the perceptual mapping:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So there'll be artifacts at the junctions where the mapping function is not smooth (which can be seen in the original Adobe image). And here is the imagemagick script for creating the color wheel.&#xD;&#xA;&#xD;&#xA;    #!/bin/bash&#xD;&#xA;    #assemble gradient pieces (pre-caculated stops), then join them all&#xD;&#xA;    convert -size 600x300 gradient:#000000-#181818 -rotate -90 grad1.png&#xD;&#xA;    convert -size 600x310 gradient:#181818-#2A2A2A -rotate -90 grad2.png&#xD;&#xA;    convert -size 600x215 gradient:#2A2A2A-#555555 -rotate -90 grad3.png&#xD;&#xA;    convert -size 600x265 gradient:#555555-#7F7F7F -rotate -90 grad4.png&#xD;&#xA;    convert -size 600x285 gradient:#7F7F7F-#AAAAAA -rotate -90 grad5.png&#xD;&#xA;    convert -size 600x275 gradient:#AAAAAA-#D4D4D4 -rotate -90 grad6.png&#xD;&#xA;    convert -size 600x150 gradient:#D4D4D4-#FFFFFF -rotate -90 grad7.png&#xD;&#xA;    convert grad?.png +append grad.png&#xD;&#xA;    #create hue&#xD;&#xA;    convert grad.png -alpha set -virtual-pixel Transparent -rotate 180 -distort Arc '360 -90 300' +repage -gravity center -crop 600x600+0+0 +repage h.png&#xD;&#xA;    #create saturation&#xD;&#xA;    convert -size 600x600 -alpha on radial-gradient:white-none s.png&#xD;&#xA;    #create value&#xD;&#xA;    convert -size 600x600 -alpha on radial-gradient:none-white v.png&#xD;&#xA;    #combine h,s,v in hsv colorspace&#xD;&#xA;    convert h.png s.png v.png -combine -set colorspace HSV -colorspace sRGB hsv.png&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PGcnP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ds5KS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3445" PostHistoryTypeId="5" PostId="1749" RevisionGUID="4c452ce7-cf68-4f4a-8c4e-c84e92913927" CreationDate="2015-11-22T15:21:37.757" UserId="2040" Comment="deleted 1 character in body" Text="I just discovered that Adobe color source includes HSV-RYB hue mapping functions (replicated in Ben Knight's Kuler-d3). Apparently Adobe uses uses piecewise linear gradients rather than the polynomial that I was trying to use (and technically it is a CMY wheel not a RBY one, I believe). Here are the relevant stops:&#xD;&#xA;&#xD;&#xA;    RYBstop HSVstop&#xD;&#xA;    60      35&#xD;&#xA;    122     60&#xD;&#xA;    165     120&#xD;&#xA;    218     180&#xD;&#xA;    275     240&#xD;&#xA;    330     300&#xD;&#xA;&#xD;&#xA;Here is the graph of these showing the perceptual mapping:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So there'll be artifacts at the junctions where the mapping function is not smooth (which can be seen in the original Adobe image). And here is an imagemagick script for creating the color wheel.&#xD;&#xA;&#xD;&#xA;    #!/bin/bash&#xD;&#xA;    #assemble gradient pieces (pre-caculated stops), then join them all&#xD;&#xA;    convert -size 600x300 gradient:#000000-#181818 -rotate -90 grad1.png&#xD;&#xA;    convert -size 600x310 gradient:#181818-#2A2A2A -rotate -90 grad2.png&#xD;&#xA;    convert -size 600x215 gradient:#2A2A2A-#555555 -rotate -90 grad3.png&#xD;&#xA;    convert -size 600x265 gradient:#555555-#7F7F7F -rotate -90 grad4.png&#xD;&#xA;    convert -size 600x285 gradient:#7F7F7F-#AAAAAA -rotate -90 grad5.png&#xD;&#xA;    convert -size 600x275 gradient:#AAAAAA-#D4D4D4 -rotate -90 grad6.png&#xD;&#xA;    convert -size 600x150 gradient:#D4D4D4-#FFFFFF -rotate -90 grad7.png&#xD;&#xA;    convert grad?.png +append grad.png&#xD;&#xA;    #create hue&#xD;&#xA;    convert grad.png -alpha set -virtual-pixel Transparent -rotate 180 -distort Arc '360 -90 300' +repage -gravity center -crop 600x600+0+0 +repage h.png&#xD;&#xA;    #create saturation&#xD;&#xA;    convert -size 600x600 -alpha on radial-gradient:white-none s.png&#xD;&#xA;    #create value&#xD;&#xA;    convert -size 600x600 -alpha on radial-gradient:none-white v.png&#xD;&#xA;    #combine h,s,v in hsv colorspace&#xD;&#xA;    convert h.png s.png v.png -combine -set colorspace HSV -colorspace sRGB ryb.png&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PGcnP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ds5KS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3446" PostHistoryTypeId="2" PostId="1750" RevisionGUID="b8bea726-0b99-4a06-ba82-ff204cbb51b4" CreationDate="2015-11-22T16:08:24.660" UserId="56" Text="It depends on the game style just how much culling is needed. For instance first person shooters benefit from this a lot, having a lot of stuff in the frustrum at any one time, while an overhead view RTS does not since you are effectively looking at a plane with things on that plane.  Even in an RTS though, doing a &quot;depth only render&quot; to eliminate overdraw is still useful." ContentLicense="CC BY-SA 3.0" />
  <row Id="3447" PostHistoryTypeId="2" PostId="1751" RevisionGUID="56cca1ed-7823-4744-bcfc-0677cce975e7" CreationDate="2015-11-23T07:36:55.853" UserId="196" Text="Yes, occlusion culling is still worth it.&#xD;&#xA;&#xD;&#xA;At minimum, a draw call that you skipped due to culling is a draw call that doesn't have to run the vertex shader. Triangle count goes up as quickly as GPUs start supporting more triangles, because why not? With unified architectures, vertex shaders use the exact same hardware that pixel shaders do, so every vertex that you skip because of culling is more compute time for the stuff that you *can* see. Not to mention all the other stuff you're skipping (CPU draw call processing, and throwing the tris far enough through the pipeline that the rasterizer realizes that it doesn't need to shade them).&#xD;&#xA;&#xD;&#xA;There was a [great presentation from two Ubisoft studios at SIGGRAPH 2015][1] about GPU-driven rendering pipelines. On the surface it's about some of the things you mentioned: batching and instancing, reducing draw call counts. But one of the major advantages they get out of a GPU-driven pipeline is incredibly fine-grained occlusion culling: better culling than you would normally see at the draw-call level. It's all in the service of asymptotically approaching the goal: processing only what you can see, which means that what you can see looks better.&#xD;&#xA;&#xD;&#xA;(Also: consider console, mobile, VR, and desktop-without-the-latest-and-greatest-GPU-that-money-can-buy. Even if all your tris disappear into the gaping maw of your top-of-the-line GPU, you may not be the primary target.)&#xD;&#xA;&#xD;&#xA;  [1]: http://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3452" PostHistoryTypeId="5" PostId="361" RevisionGUID="8e73e523-c67c-443f-b930-d64af15ce0e8" CreationDate="2015-11-23T13:16:19.920" UserId="2041" Comment="Rephrase title as per http://meta.computergraphics.stackexchange.com/questions/152/is-this-a-mistake-in-the-wikipedia-article-for-questions" Text="In reading about [Lambertian reflectance] on Wikipedia I found the following phrase (in bold) which doesn't sound right to me:&#xD;&#xA;&#xD;&#xA;&gt; In computer graphics, Lambertian reflection is often used as a model for diffuse reflection. This technique causes all closed polygons (such as a triangle within a 3D mesh) to reflect light equally in all directions when rendered. In effect, a point rotated around its normal vector will not change the way it reflects light. However, the point will change the way it reflects light if it is tilted away from its initial normal vector **since the area is illuminated by a smaller fraction of the incident radiation.**&#xD;&#xA;&#xD;&#xA;The way I picture the situation described in the paragraph, only tilting away from the light source would cause  less light to be incident in a given area. In general, tilting away from the initial normal vector could lead to either an increase ***or*** a decrease in incident light per area, as this says nothing about the location of the light source.&#xD;&#xA;&#xD;&#xA;Have I misunderstood the context, or is this something that should be rewritten on Wikipedia?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance#Use_in_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="3453" PostHistoryTypeId="4" PostId="361" RevisionGUID="8e73e523-c67c-443f-b930-d64af15ce0e8" CreationDate="2015-11-23T13:16:19.920" UserId="2041" Comment="Rephrase title as per http://meta.computergraphics.stackexchange.com/questions/152/is-this-a-mistake-in-the-wikipedia-article-for-questions" Text="Is a Lambertian reflector illuminated by a smaller fraction of the incident radiation when it's tilted?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3454" PostHistoryTypeId="24" PostId="361" RevisionGUID="8e73e523-c67c-443f-b930-d64af15ce0e8" CreationDate="2015-11-23T13:16:19.920" Comment="Proposed by 2041 approved by 127 edit id of 106" ContentLicense="CC BY-SA 3.0" />
  <row Id="3455" PostHistoryTypeId="4" PostId="1434" RevisionGUID="1da444b3-b173-48c5-8d5d-e4a30cda66e3" CreationDate="2015-11-23T13:17:09.853" UserId="2041" Comment="Rephrase title as per http://meta.computergraphics.stackexchange.com/questions/152/is-this-a-mistake-in-the-wikipedia-article-for-questions" Text="How does the view-independence of radiosity increase the calculations involved?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3456" PostHistoryTypeId="24" PostId="1434" RevisionGUID="1da444b3-b173-48c5-8d5d-e4a30cda66e3" CreationDate="2015-11-23T13:17:09.853" Comment="Proposed by 2041 approved by 127 edit id of 107" ContentLicense="CC BY-SA 3.0" />
  <row Id="3458" PostHistoryTypeId="2" PostId="1753" RevisionGUID="9be13ce8-634f-488a-b7ef-6fc59623065f" CreationDate="2015-11-23T19:04:20.070" UserId="2123" Text="I have a analysis management web system developed using Ruby on Rails, I need to analyse a uploaded image in my system. Using Java I used to have ImageJ included im my projects, since I'm new in Ruby on Rails I don't know any library/gem to manage Image processing.&#xD;&#xA;&#xD;&#xA;Do you know any image processing gem for Rails like ImageJ on Java ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3459" PostHistoryTypeId="1" PostId="1753" RevisionGUID="9be13ce8-634f-488a-b7ef-6fc59623065f" CreationDate="2015-11-23T19:04:20.070" UserId="2123" Text="ImageJ alternative for Ruby on Rails Development" ContentLicense="CC BY-SA 3.0" />
  <row Id="3460" PostHistoryTypeId="3" PostId="1753" RevisionGUID="9be13ce8-634f-488a-b7ef-6fc59623065f" CreationDate="2015-11-23T19:04:20.070" UserId="2123" Text="|image-processing|image-comparison|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3464" PostHistoryTypeId="2" PostId="1754" RevisionGUID="b67a6104-0409-4f7a-92fd-7afede25883a" CreationDate="2015-11-25T19:09:52.097" UserId="2138" Text="Good afternoon,&#xD;&#xA;&#xD;&#xA;I am currently doing a research on projection on a sphere, specifically for NOAA's project Science on a Sphere. What I'm trying to do is to find out how exactly do you create a video material for such a device, because it's not as simple as making a regular video since the projection on the sphere warps the final image a lot etc.&#xD;&#xA;&#xD;&#xA;However, I'm struggling with finding any reasonable material source. I only found NOAA's creation guidelines, and even though they do describe all the problems with warping and having a seamless video pretty well, they do not describe specific methods, or the whole process of creating this kind of a video. They only mention several programs and plugins for Adobe's AE, but that's it.&#xD;&#xA;&#xD;&#xA;Link: http://sos.noaa.gov/_downloads/docs/sos-content-creation-guidelines.pdf&#xD;&#xA;&#xD;&#xA;I can't get any reasonable source from Google either, since all links are directing me to topics related to projecting a sphere (Earth) onto a plane, which is not what I'm trying to find at all.&#xD;&#xA;&#xD;&#xA;I decided to give this site a shot and ask you whether you know any source/tutorial that could help me with this issue, or whether is here someone who understands this topic better than I do.&#xD;&#xA;&#xD;&#xA;Thank you very much for any advice!" ContentLicense="CC BY-SA 3.0" />
  <row Id="3465" PostHistoryTypeId="1" PostId="1754" RevisionGUID="b67a6104-0409-4f7a-92fd-7afede25883a" CreationDate="2015-11-25T19:09:52.097" UserId="2138" Text="Materials for research on spherical projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="3466" PostHistoryTypeId="3" PostId="1754" RevisionGUID="b67a6104-0409-4f7a-92fd-7afede25883a" CreationDate="2015-11-25T19:09:52.097" UserId="2138" Text="|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3467" PostHistoryTypeId="2" PostId="1755" RevisionGUID="b72fdc6d-36f0-42e2-9b63-05c87cc2ac80" CreationDate="2015-11-26T03:08:06.657" UserId="2141" Text="I am interested in duplicating a figure (shown below, ch 1 fig 1.21) in the book Algorithmic Beauty of Plants. The book is available here&#xD;&#xA;&#xD;&#xA;http://algorithmicbotany.org/papers/#abop&#xD;&#xA;&#xD;&#xA;[![Plant generated with an axial L-system][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V6EHc.png&#xD;&#xA;&#xD;&#xA;This image appears in several resources but I have been unable to find the exact rules for the axial system that produced it. &#xD;&#xA;&#xD;&#xA;In the book, this figure is presented in the context of L-systems and is referenced in the text as follows.&#xD;&#xA;&#xD;&#xA;&gt; Of special interest are methods proposed by Horton [70, 71] and Strahler, &#xD;&#xA;&gt; which served as a basis for synthesizing botanical trees [37, 152] (Figure &#xD;&#xA;&gt; 1.21).&#xD;&#xA;&#xD;&#xA;I am unable to find a copy of the PhD thesis (ref 37) and ref 152 does not produce this figure.&#xD;&#xA;&#xD;&#xA;Performing a Google image search with this image points to material related to the book, such as slides.&#xD;&#xA;&#xD;&#xA;Has anyone here reproduced this figure?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3468" PostHistoryTypeId="1" PostId="1755" RevisionGUID="b72fdc6d-36f0-42e2-9b63-05c87cc2ac80" CreationDate="2015-11-26T03:08:06.657" UserId="2141" Text="What exact algorithm and parameters reproduce L-system plant growth figure in Algorithmic Beauty of Plants" ContentLicense="CC BY-SA 3.0" />
  <row Id="3469" PostHistoryTypeId="3" PostId="1755" RevisionGUID="b72fdc6d-36f0-42e2-9b63-05c87cc2ac80" CreationDate="2015-11-26T03:08:06.657" UserId="2141" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3470" PostHistoryTypeId="2" PostId="1756" RevisionGUID="f6d42eb4-ed28-4fee-90af-24e34d8984d3" CreationDate="2015-11-26T05:11:59.980" UserId="1636" Text="In what sense a NURBS surface can only have the topology of a plane, cylinder or torus ?&#xD;&#xA;&#xD;&#xA;For example I can do a NURBS sphere.&#xD;&#xA;Is the sphere homeomorphic to one of the above surfaces ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3471" PostHistoryTypeId="1" PostId="1756" RevisionGUID="f6d42eb4-ed28-4fee-90af-24e34d8984d3" CreationDate="2015-11-26T05:11:59.980" UserId="1636" Text="NURBS topology classification" ContentLicense="CC BY-SA 3.0" />
  <row Id="3472" PostHistoryTypeId="3" PostId="1756" RevisionGUID="f6d42eb4-ed28-4fee-90af-24e34d8984d3" CreationDate="2015-11-26T05:11:59.980" UserId="1636" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3473" PostHistoryTypeId="2" PostId="1757" RevisionGUID="e731163a-4532-420e-8063-e2fc4a7ec682" CreationDate="2015-11-26T08:04:16.070" UserId="38" Text="A NURBS surface can make a sphere. In a typical configuration, it will be 'open' at the poles. That is the mathematical function of the surface does not wrap over the pole. Topographically the sphere is in this typical configuration a cylinder. &#xD;&#xA;&#xD;&#xA;It is possible to leave the other direction open too in which case it is topographically a plane. Several CAD applications choose this approach. A torus is also possible if you allow a thin no volume sliver at the center of your sphere.&#xD;&#xA;&#xD;&#xA;### Why only 3 topographic families?&#xD;&#xA;&#xD;&#xA;Simply a nurbs surface has only 4 possible configuration of wrapping around the parameter space:&#xD;&#xA;&#xD;&#xA;* It does not wrap at all. Topography: Plane.&#xD;&#xA;* It wraps around the U direction. Topography: Cylinder.&#xD;&#xA;* It wraps around V direction. Same as above. Topography: Cylinder.&#xD;&#xA;* It wraps around both U and V. Topography: Torus.&#xD;&#xA;&#xD;&#xA;A wrap is allways periodic so it goes from - direction to + direction. It can not arbitrarily connect  (on a mathematical level)&#xD;&#xA;&#xD;&#xA;PS: Please do not confuse the shape of a thing with topography. Topography is about how the surface is self connected." ContentLicense="CC BY-SA 3.0" />
  <row Id="3474" PostHistoryTypeId="5" PostId="1757" RevisionGUID="06f6841f-97cc-4302-98a9-107550b7bb89" CreationDate="2015-11-26T09:01:09.957" UserId="2041" Comment="Topography is the features of the physical landscape; topology is the surface characteristics you're talking about." Text="A NURBS surface can make a sphere. In a typical configuration, it will be 'open' at the poles. That is the mathematical function of the surface does not wrap over the pole. Topologically the sphere is in this typical configuration a cylinder. &#xD;&#xA;&#xD;&#xA;It is possible to leave the other direction open too in which case it is topologically a plane. Several CAD applications choose this approach. A torus is also possible if you allow a thin no volume sliver at the center of your sphere.&#xD;&#xA;&#xD;&#xA;### Why only 3 topological families?&#xD;&#xA;&#xD;&#xA;Simply a NURBS surface has only 4 possible configuration of wrapping around the parameter space:&#xD;&#xA;&#xD;&#xA;* It does not wrap at all. Topology: Plane.&#xD;&#xA;* It wraps around the U direction. Topology: Cylinder.&#xD;&#xA;* It wraps around V direction. Same as above. Topology: Cylinder.&#xD;&#xA;* It wraps around both U and V. Topology: Torus.&#xD;&#xA;&#xD;&#xA;A wrap is always periodic so it goes from - direction to + direction. It can not arbitrarily connect  (on a mathematical level).&#xD;&#xA;&#xD;&#xA;PS: Please do not confuse the shape of a thing with topology. Topology is about how the surface is self connected." ContentLicense="CC BY-SA 3.0" />
  <row Id="3475" PostHistoryTypeId="24" PostId="1757" RevisionGUID="06f6841f-97cc-4302-98a9-107550b7bb89" CreationDate="2015-11-26T09:01:09.957" Comment="Proposed by 2041 approved by 100, 38 edit id of 108" ContentLicense="CC BY-SA 3.0" />
  <row Id="3476" PostHistoryTypeId="6" PostId="1756" RevisionGUID="c49a16c0-25fc-4008-b951-bd3d1756036a" CreationDate="2015-11-26T09:01:10.860" UserId="2041" Comment="Add relevant NURBS tag" Text="|3d|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3477" PostHistoryTypeId="24" PostId="1756" RevisionGUID="c49a16c0-25fc-4008-b951-bd3d1756036a" CreationDate="2015-11-26T09:01:10.860" Comment="Proposed by 2041 approved by 100, 16 edit id of 109" ContentLicense="CC BY-SA 3.0" />
  <row Id="3478" PostHistoryTypeId="5" PostId="1754" RevisionGUID="91c202b6-08f0-44f0-a9a4-8e750b42ea70" CreationDate="2015-11-26T09:16:59.913" UserId="16" Comment="greetings and signatures are discouraged around here: http://computergraphics.stackexchange.com/help/behavior" Text="I am currently doing a research on projection on a sphere, specifically for NOAA's project Science on a Sphere. What I'm trying to do is to find out how exactly do you create a video material for such a device, because it's not as simple as making a regular video since the projection on the sphere warps the final image a lot etc.&#xD;&#xA;&#xD;&#xA;However, I'm struggling with finding any reasonable material source. I only found NOAA's creation guidelines, and even though they do describe all the problems with warping and having a seamless video pretty well, they do not describe specific methods, or the whole process of creating this kind of a video. They only mention several programs and plugins for Adobe's AE, but that's it.&#xD;&#xA;&#xD;&#xA;Link: http://sos.noaa.gov/_downloads/docs/sos-content-creation-guidelines.pdf&#xD;&#xA;&#xD;&#xA;I can't get any reasonable source from Google either, since all links are directing me to topics related to projecting a sphere (Earth) onto a plane, which is not what I'm trying to find at all.&#xD;&#xA;&#xD;&#xA;I decided to give this site a shot and ask you whether you know any source/tutorial that could help me with this issue, or whether is here someone who understands this topic better than I do." ContentLicense="CC BY-SA 3.0" />
  <row Id="3479" PostHistoryTypeId="6" PostId="1755" RevisionGUID="06abc130-6fa9-44a5-bdd5-db3f1306ee09" CreationDate="2015-11-26T10:19:55.960" UserId="2041" Comment="Since the question's not about algorithms, but parameters for an L-system, I think it's good to introduce a new tag." Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3480" PostHistoryTypeId="24" PostId="1755" RevisionGUID="06abc130-6fa9-44a5-bdd5-db3f1306ee09" CreationDate="2015-11-26T10:19:55.960" Comment="Proposed by 2041 approved by 16 edit id of 110" ContentLicense="CC BY-SA 3.0" />
  <row Id="3481" PostHistoryTypeId="5" PostId="1757" RevisionGUID="811d5455-dcd0-4f76-a8d4-0d34ff033a10" CreationDate="2015-11-26T10:31:16.310" UserId="38" Comment="added 267 characters in body" Text="Before we begin, let us differentiate between two things:&#xD;&#xA;&#xD;&#xA;* The shape of a sphere,&#xD;&#xA;* and the topology of a sphere.&#xD;&#xA;&#xD;&#xA;A NURBS surface can make the *shape* of a sphere. In a typical configuration, it will be 'open' at the poles. That is the mathematical function of the surface does not wrap over the pole in that its is not a true sphere (it has the shape of a sphere). Topologically the sphere is in this typical configuration a cylinder. &#xD;&#xA;&#xD;&#xA;It is possible to leave the other direction open too in which case it is topologically a plane. Several CAD applications choose this approach. A torus is also possible if you allow a thin no volume sliver at the center of your sphere.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Is the sphere homeomorphic to one of the above surfaces ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;No, but you can still have a spherical shape even if it does not satisfy the topology condition of mathematics.&#xD;&#xA;### Why only 3 topological families?&#xD;&#xA;&#xD;&#xA;Simply a NURBS surface has only 4 possible configuration of wrapping around the parameter space:&#xD;&#xA;&#xD;&#xA;* It does not wrap at all. Topology: Plane.&#xD;&#xA;* It wraps around the U direction. Topology: Cylinder.&#xD;&#xA;* It wraps around V direction. Same as above. Topology: Cylinder.&#xD;&#xA;* It wraps around both U and V. Topology: Torus.&#xD;&#xA;&#xD;&#xA;A wrap is always periodic so it goes from - direction to + direction. It can not arbitrarily connect  (on a mathematical level).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3482" PostHistoryTypeId="5" PostId="1757" RevisionGUID="c19a0712-070e-4e5a-a815-ceb0cf1cbad3" CreationDate="2015-11-26T11:39:06.033" UserId="38" Comment="added 246 characters in body" Text="Before we begin, let us differentiate between two things:&#xD;&#xA;&#xD;&#xA;* The shape of a sphere,&#xD;&#xA;* and the topology of a sphere.&#xD;&#xA;&#xD;&#xA;A NURBS surface can make the *shape* of a sphere. In a typical configuration, it will be 'open' at the poles. That is the mathematical function of the surface does not wrap over the pole in that its is not a true sphere (it has the shape of a sphere). Topologically the sphere is in this typical configuration a cylinder. &#xD;&#xA;&#xD;&#xA;It is possible to leave the other direction open too in which case it is topologically a plane. Several CAD applications choose this approach. A torus is also possible if you allow a thin no volume sliver at the center of your sphere.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Turning cylinder to sphere. Note this is not a topological sphere it is still a cylinder as the top is open (even tough infinitesimally small).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Is the sphere homeomorphic to one of the above surfaces ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;No, but you can still have a spherical shape even if it does not satisfy the topology condition of mathematics.&#xD;&#xA;### Why only 3 topological families?&#xD;&#xA;&#xD;&#xA;Simply a NURBS surface has only 4 possible configuration of wrapping around the parameter space:&#xD;&#xA;&#xD;&#xA;* It does not wrap at all. Topology: Plane.&#xD;&#xA;* It wraps around the U direction. Topology: Cylinder.&#xD;&#xA;* It wraps around V direction. Same as above. Topology: Cylinder.&#xD;&#xA;* It wraps around both U and V. Topology: Torus.&#xD;&#xA;&#xD;&#xA;A wrap is always periodic so it goes from - direction to + direction. It can not arbitrarily connect  (on a mathematical level).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kP30Z.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3483" PostHistoryTypeId="2" PostId="1758" RevisionGUID="4969dee3-2d62-4bce-af4d-b8ae2d6fb276" CreationDate="2015-11-26T13:10:01.193" UserId="2144" Text="Is there a library to do mesh processing (slicing, repairing, etc.) on big models in a distributed way using Hadoop?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3484" PostHistoryTypeId="1" PostId="1758" RevisionGUID="4969dee3-2d62-4bce-af4d-b8ae2d6fb276" CreationDate="2015-11-26T13:10:01.193" UserId="2144" Text="Distributed Mesh Processing with Hadoop" ContentLicense="CC BY-SA 3.0" />
  <row Id="3485" PostHistoryTypeId="3" PostId="1758" RevisionGUID="4969dee3-2d62-4bce-af4d-b8ae2d6fb276" CreationDate="2015-11-26T13:10:01.193" UserId="2144" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3486" PostHistoryTypeId="5" PostId="1757" RevisionGUID="1d8a4293-1845-4426-be25-c83e63673fc1" CreationDate="2015-11-26T20:12:21.563" UserId="38" Comment="added 1 character in body" Text="Before we begin, let us differentiate between two things:&#xD;&#xA;&#xD;&#xA;* The shape of a sphere,&#xD;&#xA;* and the topology of a sphere.&#xD;&#xA;&#xD;&#xA;A NURBS surface can make the *shape* of a sphere. In a typical configuration, it will be 'open' at the poles. That is the mathematical function of the surface does not wrap over the pole in that its is not a true sphere (it has the shape of a sphere). Topologically the sphere is in this typical configuration a cylinder. &#xD;&#xA;&#xD;&#xA;It is possible to leave the other direction open too in which case it is topologically a plane. Several CAD applications choose this approach. A torus is also possible if you allow a thin no volume sliver at the center of your sphere.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Turning cylinder to sphere. Note this is not a topological sphere it is still a cylinder as the top is open (even though infinitesimally small).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Is the sphere homeomorphic to one of the above surfaces ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;No, but you can still have a spherical shape even if it does not satisfy the topology condition of mathematics.&#xD;&#xA;### Why only 3 topological families?&#xD;&#xA;&#xD;&#xA;Simply a NURBS surface has only 4 possible configuration of wrapping around the parameter space:&#xD;&#xA;&#xD;&#xA;* It does not wrap at all. Topology: Plane.&#xD;&#xA;* It wraps around the U direction. Topology: Cylinder.&#xD;&#xA;* It wraps around V direction. Same as above. Topology: Cylinder.&#xD;&#xA;* It wraps around both U and V. Topology: Torus.&#xD;&#xA;&#xD;&#xA;A wrap is always periodic so it goes from - direction to + direction. It can not arbitrarily connect  (on a mathematical level).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kP30Z.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3487" PostHistoryTypeId="2" PostId="1759" RevisionGUID="72e7e1b9-700a-4687-b92d-b1623007e468" CreationDate="2015-11-27T10:59:41.930" UserId="2154" Text="I've got a homework in which I have to calculate and plot some points using a pespective transformation, but I'm not sure my results are correct, since the 3d plot using Camera coordinates looks very different from the 2d plot using the image coordinates. Can you help me understand what's wrong?&#xD;&#xA;&#xD;&#xA;This is what is given:&#xD;&#xA;The camera is at the point $_WT^C = [−1, 1, 5]^T$, specified in world coordinates (in meters). The camera coordinate system is rotated around the Y axis of the world reference by $\theta = 160^o$, so it's rotation matrix is $^wR_c = \begin{bmatrix}cos(\theta) &amp; 0 &amp; sin(\theta)\\ 0 &amp; 1 &amp; 0 \\ -sin(\theta) &amp; 0 &amp; cos(\theta)\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Camera parameter are: $f = 16mm$, $s_x = s_y = 0.01 mm/px$, $o_x = 320 px$, $o_y = 240px$&#xD;&#xA;&#xD;&#xA;Sample points (in world coordinates):&#xD;&#xA; &#xD;&#xA;$^WP_1 = [1, 1, 0.5]^T$&#xD;&#xA;&#xD;&#xA;$^WP_2 = [1, 1.5, 0.5]^T$&#xD;&#xA;&#xD;&#xA;$^WP_3 = [1.5, 1.5, 0.5]^T$&#xD;&#xA;&#xD;&#xA;$^WP_4 = [1.5, 1, 0.5]^T$&#xD;&#xA;&#xD;&#xA;I have to calculate and plot the points in camera coordinates and in image coordinates, so I wrote the following code in Octave:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-matlab --&gt;&#xD;&#xA;&#xD;&#xA;    %camera intrinsic parameters&#xD;&#xA;    f = 16&#xD;&#xA;    Sx = 0.01&#xD;&#xA;    Sy = 0.01&#xD;&#xA;    Ox = 320&#xD;&#xA;    Oy = 240&#xD;&#xA;    &#xD;&#xA;    %given points, in world coordinate&#xD;&#xA;    wP1 = transpose([1, 1, 0.5])&#xD;&#xA;    wP2 = transpose([1, 1.5, 0.5])&#xD;&#xA;    wP3 = transpose([1.5, 1.5, 0.5])&#xD;&#xA;    wP4 = transpose([1.5, 1, 0.5])&#xD;&#xA;    &#xD;&#xA;    % camera translation matrix&#xD;&#xA;    wTc = transpose([-1, 1, 5])&#xD;&#xA;    &#xD;&#xA;    % rotation angle converted to rad&#xD;&#xA;    theta = 160 / 180 * pi&#xD;&#xA;    &#xD;&#xA;    %camera rotation matrix&#xD;&#xA;    wRc = transpose([cos(theta), 0, sin(theta); 0, 1, 0; -sin(theta), 0, cos(theta)])&#xD;&#xA;    &#xD;&#xA;    %transform the points to homogeneous coordinates&#xD;&#xA;    wP1h = [wP1; 1]&#xD;&#xA;    wP2h = [wP2; 1]&#xD;&#xA;    wP3h = [wP3; 1]&#xD;&#xA;    wP4h = [wP4; 1]&#xD;&#xA;    &#xD;&#xA;    %separate each line of the rotation matrix&#xD;&#xA;    R1 = transpose(wRc(1 , :))&#xD;&#xA;    R2 = transpose(wRc(2 , :))&#xD;&#xA;    R3 = transpose(wRc(3 , :))&#xD;&#xA;    &#xD;&#xA;    %generate the extrinsic parameters matrix&#xD;&#xA;    Mext = [wRc, [-transpose(R1) * wTc; -transpose(R2) * wTc; -transpose(R3) * wTc]]&#xD;&#xA;    &#xD;&#xA;    %intrinsic parameters matrix&#xD;&#xA;    Mint = [-f/Sx, 0, Ox; 0, -f/Sy, Oy; 0, 0, 1]&#xD;&#xA;    &#xD;&#xA;    % calculate coordinates in camera coordinates&#xD;&#xA;    cP1 = wRc * (wP1 - wTc)&#xD;&#xA;    cP2 = wRc * (wP2 - wTc)&#xD;&#xA;    cP3 = wRc * (wP3 - wTc)&#xD;&#xA;    cP4 = wRc * (wP4 - wTc)&#xD;&#xA;    &#xD;&#xA;    % put coordinates in a list for plotting&#xD;&#xA;    &#xD;&#xA;    x = [cP1(1), cP2(1), cP3(1), cP4(1), cP1(1)]&#xD;&#xA;    y = [cP1(2), cP2(2), cP3(2), cP4(2), cP1(2)]&#xD;&#xA;    z = [cP1(3), cP2(3), cP3(3), cP4(3), cP1(3)]&#xD;&#xA;    &#xD;&#xA;    %plot the points in 3D using camera coordinates&#xD;&#xA;    plot3(x, y, z, &quot;o-r&quot;)&#xD;&#xA;    &#xD;&#xA;    pause()&#xD;&#xA;    &#xD;&#xA;    % calculate the points in image coordinates&#xD;&#xA;    iP1 = Mint * (Mext * wP1h)&#xD;&#xA;    iP2 = Mint * (Mext * wP2h)&#xD;&#xA;    iP3 = Mint * (Mext * wP3h)&#xD;&#xA;    iP4 = Mint * (Mext * wP4h)&#xD;&#xA;    &#xD;&#xA;    %generate a list of points for plotting&#xD;&#xA;    x = [iP1(1) / iP1(3), iP2(1) / iP2(3), iP3(1) / iP3(3), iP4(1) / iP4(3), iP1(1) / iP1(3)]&#xD;&#xA;    y = [iP1(2) / iP1(3), iP2(2) / iP2(3), iP3(2) / iP3(3), iP4(2) / iP4(3), iP1(2) / iP1(3)]&#xD;&#xA;    &#xD;&#xA;    plot(x, y, &quot;o-r&quot;)&#xD;&#xA;    &#xD;&#xA;    pause()&#xD;&#xA;&#xD;&#xA;And these are the plots I've got from the script:&#xD;&#xA;I was expecting they were somewhat similar, but they don't look so.&#xD;&#xA;&#xD;&#xA;[![3D plot][1]][1]&#xD;&#xA;&#xD;&#xA;Plot in camera coordinates&#xD;&#xA;&#xD;&#xA;[![2D plot][2]][2]&#xD;&#xA;&#xD;&#xA;Plot in image coordinates&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AkLN0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/p83mD.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3488" PostHistoryTypeId="1" PostId="1759" RevisionGUID="72e7e1b9-700a-4687-b92d-b1623007e468" CreationDate="2015-11-27T10:59:41.930" UserId="2154" Text="Is my perspective math correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3489" PostHistoryTypeId="3" PostId="1759" RevisionGUID="72e7e1b9-700a-4687-b92d-b1623007e468" CreationDate="2015-11-27T10:59:41.930" UserId="2154" Text="|3d|mathematics|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3491" PostHistoryTypeId="2" PostId="1760" RevisionGUID="979a384b-a05a-4ef9-b3ed-1d23ecd2f287" CreationDate="2015-11-28T09:51:24.587" UserId="38" Text="You need to use a cylindrical projection. So the key issue is how to prepare data for a cylindrical projection. Basically what you do is: &#xD;&#xA;&#xD;&#xA;1. You project your data on a sphere &#xD;&#xA;2. And then you project it back to a cylinder&#xD;&#xA;&#xD;&#xA;Both steps can be easily taken care of by your cartography software. Will the data distort... yes but since you project information onto a sphere from whatever source onto a sphere and to cylimdrical coorinates it will just interpolate the distortion away. If anything your just going to have slight over resolution at poles.&#xD;&#xA;&#xD;&#xA;Quite a lot of data is in fact in this format to begin with. But nearly all 3D applications can use projected textures and texture baking to do these steps for you." ContentLicense="CC BY-SA 3.0" />
  <row Id="3492" PostHistoryTypeId="5" PostId="1760" RevisionGUID="b3509041-7f7c-4357-8b9a-b51a3707ea1f" CreationDate="2015-11-28T10:09:59.843" UserId="38" Comment="added 117 characters in body" Text="You need to use a cylindrical projection. So the key issue is how to prepare data for a cylindrical projection. Basically what you do is: &#xD;&#xA;&#xD;&#xA;1. You project your data on a sphere, it may be that this process was already done for you.&#xD;&#xA;2. And then you project it back to a cylinder&#xD;&#xA;&#xD;&#xA;Both steps can be easily taken care of by your cartography software. Will the data distort... yes but since you project information onto a sphere from whatever source onto a sphere and to cylimdrical coorinates it will just interpolate the distortion away. If anything your just going to have slight over resolution at poles.&#xD;&#xA;&#xD;&#xA;Quite a lot of data is in fact in this format to begin with. But nearly all 3D applications can use projected textures and texture baking to do these steps for you.&#xD;&#xA;&#xD;&#xA;The real question is what your original image data is like?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3493" PostHistoryTypeId="5" PostId="1756" RevisionGUID="cbaece9e-d61f-49c5-a23e-928909a45754" CreationDate="2015-11-28T16:41:47.460" UserId="231" Comment="Minor formating; edited tags" Text="In what sense is it true that a NURBS surface can only have the topology of a plane, cylinder or torus?&#xD;&#xA;&#xD;&#xA;For example I can do a NURBS sphere.&#xD;&#xA;&#xD;&#xA;Is the sphere homeomorphic to one of the above surfaces?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3494" PostHistoryTypeId="6" PostId="1756" RevisionGUID="cbaece9e-d61f-49c5-a23e-928909a45754" CreationDate="2015-11-28T16:41:47.460" UserId="231" Comment="Minor formating; edited tags" Text="|3d|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3495" PostHistoryTypeId="5" PostId="1757" RevisionGUID="12bc6987-b441-40f4-b3ac-a332af22ae8d" CreationDate="2015-11-28T16:48:14.650" UserId="231" Comment="Minor formating" Text="Before we begin, let us differentiate between two things:&#xD;&#xA;&#xD;&#xA;* The shape of a sphere,&#xD;&#xA;* and the topology of a sphere.&#xD;&#xA;&#xD;&#xA;A NURBS surface can make the *shape* of a sphere. In a typical configuration, it will be 'open' at the poles. That is the mathematical function of the surface does not wrap over the pole in that it is not a true sphere (it has the shape of a sphere). Topologically the sphere is in this typical configuration a cylinder. &#xD;&#xA;&#xD;&#xA;It is possible to leave the other direction open too in which case it is topologically a plane. Several CAD applications choose this approach. A torus is also possible if you allow a thin no volume sliver at the center of your sphere.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Turning cylinder to sphere. Note this is not a topological sphere it is still a cylinder as the top is open (even though infinitesimally small).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Is the sphere homeomorphic to one of the above surfaces?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;No, but you can still have a spherical shape even if it does not satisfy the topology condition of mathematics.&#xD;&#xA;&#xD;&#xA;### Why only 3 topological families?&#xD;&#xA;&#xD;&#xA;Simply, a NURBS surface has only 4 possible configurations of wrapping around the parameter space:&#xD;&#xA;&#xD;&#xA;* It does not wrap at all. Topology: Plane.&#xD;&#xA;* It wraps around the U direction. Topology: Cylinder.&#xD;&#xA;* It wraps around V direction. Same as above. Topology: Cylinder.&#xD;&#xA;* It wraps around both U and V. Topology: Torus.&#xD;&#xA;&#xD;&#xA;A wrap is always periodic so it goes from - direction to + direction. It can not arbitrarily connect (on a mathematical level).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kP30Z.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3496" PostHistoryTypeId="5" PostId="1753" RevisionGUID="ff0431a5-1276-41e1-86bf-d2e23187a87a" CreationDate="2015-11-28T16:58:17.920" UserId="231" Comment="Minor typos" Text="I have an analysis management web system developed using Ruby on Rails and I need to analyse an uploaded image in my system. Using Java I used to have ImageJ included im my projects. Since I'm new in Ruby on Rails I don't know any library/gem to manage Image processing.&#xD;&#xA;&#xD;&#xA;Do you know any image processing gem for Rails like ImageJ on Java?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3497" PostHistoryTypeId="5" PostId="1760" RevisionGUID="e47eef04-6365-4a12-bb33-ab75ec12deda" CreationDate="2015-11-28T20:44:34.907" UserId="38" Comment="added 134 characters in body" Text="You need to use a cylindrical projection. So the key issue is how to prepare data for a cylindrical projection. Basically what you do is: &#xD;&#xA;&#xD;&#xA;1. You project your data on a sphere, it may be that this process was already done for you.&#xD;&#xA;2. And then you project it back to a cylinder&#xD;&#xA;&#xD;&#xA;Both steps can be easily taken care of by your cartography software. Will the data distort... yes but since you project information onto a sphere from whatever source onto a sphere and to cylindrical coordinates it will just interpolate the distortion away. If anything your just going to have slight over resolution at poles.&#xD;&#xA;&#xD;&#xA;Quite a lot of data is in fact in this format to begin with. But nearly all 3D applications can use projected textures and texture baking to do these steps for you. Also most 2D applications like Photoshop have tools for turning rectangular coordinates to polar coordinates which do the same thing&#xD;&#xA;&#xD;&#xA;The real question is what your original image data is like?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3500" PostHistoryTypeId="2" PostId="1761" RevisionGUID="778580ea-3563-4b1e-a6c6-78ca5f37a9aa" CreationDate="2015-11-29T12:55:29.020" UserId="2161" Text="I have to connect two given points with a line. Then again two new points are selected and these have to be connected as well however without intersecting previously drawn lines and so on for any number of given point pairs. The lines don't have to be straight.&#xD;&#xA;&#xD;&#xA;What is the easiest way of finding and drawing these lines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3501" PostHistoryTypeId="1" PostId="1761" RevisionGUID="778580ea-3563-4b1e-a6c6-78ca5f37a9aa" CreationDate="2015-11-29T12:55:29.020" UserId="2161" Text="Strategy for connecting 2 points without intersecting previously drawn lines" ContentLicense="CC BY-SA 3.0" />
  <row Id="3502" PostHistoryTypeId="3" PostId="1761" RevisionGUID="778580ea-3563-4b1e-a6c6-78ca5f37a9aa" CreationDate="2015-11-29T12:55:29.020" UserId="2161" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3503" PostHistoryTypeId="2" PostId="1762" RevisionGUID="557d652a-b49c-4282-89a2-0af82e46df68" CreationDate="2015-11-29T15:00:13.707" UserId="2162" Text="Given the 4 coordinates of a 2D shape in a 3D space I want to calculate its aspect ratio.&#xD;&#xA;&#xD;&#xA;The 3D space is created with 2 vanishing points.&#xD;&#xA;&#xD;&#xA;The 4 coordinates - marked blue - are the 2D coordinates on the display.&#xD;&#xA;in the example they should be roughly (14, 5.5), (19, 5), (20.3, 7.3), (25.3, 6).&#xD;&#xA;&#xD;&#xA;I'm not sure if this is possible at all, if someone could find proof that for 2 different aspect ratios the 2D coordinates are the same this problem would be unsolvable.&#xD;&#xA;&#xD;&#xA;For the example the aspect ratio would be (by intuition) something like &#xD;&#xA;&#xD;&#xA;My exapmle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/omyRz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3504" PostHistoryTypeId="1" PostId="1762" RevisionGUID="557d652a-b49c-4282-89a2-0af82e46df68" CreationDate="2015-11-29T15:00:13.707" UserId="2162" Text="Calculate aspect ratio from 2D shape in 3D space" ContentLicense="CC BY-SA 3.0" />
  <row Id="3505" PostHistoryTypeId="3" PostId="1762" RevisionGUID="557d652a-b49c-4282-89a2-0af82e46df68" CreationDate="2015-11-29T15:00:13.707" UserId="2162" Text="|transformations|geometry|projections|perspective|space|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3506" PostHistoryTypeId="2" PostId="1763" RevisionGUID="ff0bdc96-0226-41ac-b767-2cc74ed8b869" CreationDate="2015-11-29T20:19:22.653" UserId="38" Text="The ratio is with a quick and dirty visual measurement $665:501$ which is approximately $5:4$. You can measure it by taking the ratio of the vanishing angles $\alpha/\beta$ (*see picture 1*).&#xD;&#xA;&#xD;&#xA;[![Angles][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Ratio of the inbound angles&#xD;&#xA;&#xD;&#xA;We can check the situation visually by drawing a 2 point perceptive grid. For this we need the centerline between the wanishing points.&#xD;&#xA;&#xD;&#xA;[![Perspective grid][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Seems about right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IeTey.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9gjvk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3507" PostHistoryTypeId="5" PostId="1763" RevisionGUID="1abbeac8-8bf9-4ed3-9019-26973f7f73ab" CreationDate="2015-11-29T20:25:02.290" UserId="38" Comment="Typos fixed" Text="The ratio is with a quick and dirty visual measurement $665:501$ which is approximately $5:4$. You can measure it by taking the ratio of the vanishing angles $\alpha/\beta$ (*see picture 1*).&#xD;&#xA;&#xD;&#xA;[![Angles][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Ratio of the inbound angles&#xD;&#xA;&#xD;&#xA;We can check the situation visually by drawing a 2 point perspective grid. For this we need the center line between the vanishing points.&#xD;&#xA;&#xD;&#xA;[![Perspective grid][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Seems about right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IeTey.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9gjvk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3508" PostHistoryTypeId="5" PostId="1763" RevisionGUID="0b8cff75-3b64-4e01-9e69-a1eaf926cb38" CreationDate="2015-11-29T20:30:21.200" UserId="38" Comment="added 38 characters in body" Text="The ratio is with a quick and dirty visual measurement $665:501$ which is approximately $5:4$. You can measure it by taking the ratio of the vanishing angles $\alpha/\beta$ (*see picture 1*) because we are so close to the center.&#xD;&#xA;&#xD;&#xA;[![Angles][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Ratio of the inbound angles&#xD;&#xA;&#xD;&#xA;We can check the situation visually by drawing a 2 point perspective grid. For this we need the center line between the vanishing points.&#xD;&#xA;&#xD;&#xA;[![Perspective grid][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Seems about right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IeTey.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9gjvk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3509" PostHistoryTypeId="5" PostId="1761" RevisionGUID="e4989bb2-c8b8-46dc-9d23-3f15ddc4f452" CreationDate="2015-11-29T22:30:35.507" UserId="310" Comment="By definutuon a line is straight. if you dont want straight lines, you either want line segments or a curve" Text="I have to connect two given points with a set of line segments. Then again two new points are selected and these have to be connected as well however without intersecting previously drawn lines and so on for any number of given point pairs.&#xA;&#xD;&#xA;What is the easiest way of finding and drawing these line segments?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3510" PostHistoryTypeId="4" PostId="1761" RevisionGUID="e4989bb2-c8b8-46dc-9d23-3f15ddc4f452" CreationDate="2015-11-29T22:30:35.507" UserId="310" Comment="By definutuon a line is straight. if you dont want straight lines, you either want line segments or a curve" Text="Strategy for connecting 2 points without intersecting previously drawn line segments" ContentLicense="CC BY-SA 3.0" />
  <row Id="3511" PostHistoryTypeId="24" PostId="1761" RevisionGUID="e4989bb2-c8b8-46dc-9d23-3f15ddc4f452" CreationDate="2015-11-29T22:30:35.507" Comment="Proposed by 310 approved by 38, -1 edit id of 111" ContentLicense="CC BY-SA 3.0" />
  <row Id="3512" PostHistoryTypeId="5" PostId="1761" RevisionGUID="4b5fdaed-7733-4ab1-b912-8165f873c8b2" CreationDate="2015-11-29T22:30:35.507" UserId="2161" Comment="By definition a line is straight. Instead of that it's only important that the points are connected, therefore a segment of curve is also OK." Text="I have to connect point pairs without intersection. &#xD;&#xA;Let's say I have two given points that I connect with a segment of a curve. Then again two new endpoints are selected and these new points have to be connected as well however without intersecting previously drawn curves and so on for any number of given point pairs.&#xD;&#xA;&#xD;&#xA;What is the easiest way of finding and drawing these segments of curves?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3513" PostHistoryTypeId="4" PostId="1761" RevisionGUID="4b5fdaed-7733-4ab1-b912-8165f873c8b2" CreationDate="2015-11-29T22:30:35.507" UserId="2161" Comment="By definition a line is straight. Instead of that it's only important that the points are connected, therefore a segment of curve is also OK." Text="Strategy for connecting 2 points without intersecting previously drawn segments of curves" ContentLicense="CC BY-SA 3.0" />
  <row Id="3514" PostHistoryTypeId="2" PostId="1764" RevisionGUID="a9df4837-6550-4ba7-bb48-95726b6d8f3b" CreationDate="2015-11-30T00:51:28.830" UserId="192" Text="The general problem is called [graph drawing](https://en.wikipedia.org/wiki/Graph_drawing) and is not an easy problem.&#xD;&#xA;&#xD;&#xA;The graphs that can be drawn on the plane without crossings are called [planar](https://en.wikipedia.org/wiki/Planar_graph), but all graphs are planar: the typical graphs that are not planar are the complete graph on $5$ vertices $K_5$ and the complete bipartite graph on 6 vertices $K_{3,3}, famous because of the [three utilities problem](https://en.wikipedia.org/wiki/Three_utilities_problem).&#xD;&#xA;&#xD;&#xA;You may want to try [Graphviz - Graph Visualization Software](http://www.graphviz.org/) to produce nice drawings." ContentLicense="CC BY-SA 3.0" />
  <row Id="3515" PostHistoryTypeId="5" PostId="1764" RevisionGUID="a69923ba-207d-482b-b2df-2b8f065ece89" CreationDate="2015-11-30T00:57:59.097" UserId="192" Comment="added 256 characters in body" Text="The general problem is called [graph drawing](https://en.wikipedia.org/wiki/Graph_drawing) and is not an easy problem.&#xD;&#xA;&#xD;&#xA;The graphs that can be drawn on the plane without crossings are called [planar](https://en.wikipedia.org/wiki/Planar_graph), but all graphs are planar: the typical graphs that are not planar are the complete graph on $5$ vertices $K_5$ and the complete bipartite graph on 6 vertices $K_{3,3}$, famous because of the [three utilities problem](https://en.wikipedia.org/wiki/Three_utilities_problem).&#xD;&#xA;&#xD;&#xA;You may want to try [Graphviz - Graph Visualization Software](http://www.graphviz.org/) to produce nice drawings.&#xD;&#xA;&#xD;&#xA;See also &#xD;&#xA;&#xD;&#xA;&gt; Szirmay-Kalos, László, [Dynamic layout algorithm to display general graphs](http://www.iit.bme.hu/~szirmay/lsgraph.ps.gz), in *Graphics Gems IV*, 1994. [code](http://www.realtimerendering.com/resources/GraphicsGems/gemsiv/graph_layout/)&#xD;&#xA;&#xD;&#xA;&gt; Rosati, Claudio, A simple connection algorithm for 2-d drawing, *Graphics Gems III*, 1992, [code](http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/con2d.c)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3516" PostHistoryTypeId="5" PostId="1764" RevisionGUID="3de59955-c72a-428b-9dc8-f19c1310b703" CreationDate="2015-11-30T03:58:02.933" UserId="38" Comment="added 4 characters in body" Text="The general problem is called [graph drawing](https://en.wikipedia.org/wiki/Graph_drawing) and is not an easy problem.&#xD;&#xA;&#xD;&#xA;The graphs that can be drawn on the plane without crossings are called [planar](https://en.wikipedia.org/wiki/Planar_graph), but not all graphs are planar: the typical graphs that are not planar are the complete graph on $5$ vertices $K_5$ and the complete bipartite graph on 6 vertices $K_{3,3}$, famous because of the [three utilities problem](https://en.wikipedia.org/wiki/Three_utilities_problem).&#xD;&#xA;&#xD;&#xA;You may want to try [Graphviz - Graph Visualization Software](http://www.graphviz.org/) to produce nice drawings.&#xD;&#xA;&#xD;&#xA;See also &#xD;&#xA;&#xD;&#xA;&gt; Szirmay-Kalos, László, [Dynamic layout algorithm to display general graphs](http://www.iit.bme.hu/~szirmay/lsgraph.ps.gz), in *Graphics Gems IV*, 1994. [code](http://www.realtimerendering.com/resources/GraphicsGems/gemsiv/graph_layout/)&#xD;&#xA;&#xD;&#xA;&gt; Rosati, Claudio, A simple connection algorithm for 2-d drawing, *Graphics Gems III*, 1992, [code](http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/con2d.c)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3517" PostHistoryTypeId="2" PostId="1765" RevisionGUID="19949426-fe23-4791-a86e-733835fa9f2f" CreationDate="2015-11-30T15:36:34.443" UserId="2173" Text="I am working on the move tool in a 3D modeling software. I need to know how much to extrude when the user drags an axis of the [gizmo](http://www.finalclap.com/ressources/images/3dsmax-tracking6.jpg) (for example along the x axis). &#xD;&#xA;&#xD;&#xA;I have the 2D vector describing how much the mouse moved on the screen `MouseDelta`, and the vector corresponding to the selected axis `AxisVector`. &#xD;&#xA;&#xD;&#xA;I would like to know the best way to compute the amount of extrusion I should apply. &#xD;&#xA;&#xD;&#xA;Currently I try to project the `AxisVector` in screen space, project `MouseDelta` on it and get the ratio between the size of the `AxisVectorOnScreen` and the computed projection. Then I have to clamp the result and multiply it by a factor. Here is a pseudo code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Vector3 AxisVectorOnScreen = GetViewProjMatrix().TransformVector(AxisVector);&#xD;&#xA;    Vector2 AxisVectorOnScreen2D(AxisVectorOnScreen .X * 0.5f * Screen.Width(), AxisVectorOnScreen .Y * 0.5f * Screen.Height());&#xD;&#xA;    Vector2 MouseDelta = EndMousePosition - BeginMousePosition;&#xD;&#xA;    float Size = AxisVectorOnScreen2D.Length();&#xD;&#xA;    float ProjectionLength = MouseDelta | AxisVectorOnScreen2D.GetSafeNormal();&#xD;&#xA;    float Ratio = Size / ProjectionLength;&#xD;&#xA;    float Amount = 10.f * FMath::Clamp(Ratio, -2.5f, 2.5f);&#xD;&#xA;&#xD;&#xA;I think I could also project my mouse vector on a place perpendicular to the camera and do the same maths on this plane. What is the best solution?&#xD;&#xA;&#xD;&#xA;*Note: I have the same problem to get the amount of extrusion I should apply with my extrude tool (along the normal of a face).*" ContentLicense="CC BY-SA 3.0" />
  <row Id="3518" PostHistoryTypeId="1" PostId="1765" RevisionGUID="19949426-fe23-4791-a86e-733835fa9f2f" CreationDate="2015-11-30T15:36:34.443" UserId="2173" Text="How to get the transform amount from a screen vector and a direction vector?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3519" PostHistoryTypeId="3" PostId="1765" RevisionGUID="19949426-fe23-4791-a86e-733835fa9f2f" CreationDate="2015-11-30T15:36:34.443" UserId="2173" Text="|algorithm|3d|transformations|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3520" PostHistoryTypeId="5" PostId="1765" RevisionGUID="f23b5b5c-df05-4a7d-936a-dfff871d680c" CreationDate="2015-11-30T15:50:54.160" UserId="2173" Comment="deleted 3 characters in body" Text="I am working on the move tool in a 3D modeling software. I need to know how much to move when the user drags an axis of the [gizmo](http://www.finalclap.com/ressources/images/3dsmax-tracking6.jpg) (for example along the x axis). &#xD;&#xA;&#xD;&#xA;I have the 2D vector describing how much the mouse moved on the screen `MouseDelta`, and the vector corresponding to the selected axis `AxisVector`. &#xD;&#xA;&#xD;&#xA;I would like to know the best way to compute the amount of extrusion I should apply. &#xD;&#xA;&#xD;&#xA;Currently I try to project the `AxisVector` in screen space, project `MouseDelta` on it and get the ratio between the size of the `AxisVectorOnScreen` and the computed projection. Then I have to clamp the result and multiply it by a factor. Here is a pseudo code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Vector3 AxisVectorOnScreen = GetViewProjMatrix().TransformVector(AxisVector);&#xD;&#xA;    Vector2 AxisVectorOnScreen2D(AxisVectorOnScreen .X * 0.5f * Screen.Width(), AxisVectorOnScreen .Y * 0.5f * Screen.Height());&#xD;&#xA;    Vector2 MouseDelta = EndMousePosition - BeginMousePosition;&#xD;&#xA;    float Size = AxisVectorOnScreen2D.Length();&#xD;&#xA;    float ProjectionLength = MouseDelta | AxisVectorOnScreen2D.GetSafeNormal();&#xD;&#xA;    float Ratio = Size / ProjectionLength;&#xD;&#xA;    float Amount = 10.f * FMath::Clamp(Ratio, -2.5f, 2.5f);&#xD;&#xA;&#xD;&#xA;I think I could also project my mouse vector on a place perpendicular to the camera and do the same maths on this plane. What is the best solution?&#xD;&#xA;&#xD;&#xA;*Note: I have the same problem to get the amount of extrusion I should apply with my extrude tool (along the normal of a face).*" ContentLicense="CC BY-SA 3.0" />
  <row Id="3521" PostHistoryTypeId="2" PostId="1766" RevisionGUID="21ae2aed-9026-49af-b00a-3e14d22be427" CreationDate="2015-11-30T16:12:56.893" UserId="2173" Text="I try to project a 3D vector (a direction, not a position) in screen space, but it does not return satisfying results:&#xD;&#xA;&#xD;&#xA;     FVector LineDirectionOnScreen = EdMode-&gt;ViewMatrices.GetViewProjMatrix().TransformVector(LineDirection);&#xD;&#xA;     FVector2D LineDirectionOnScreen2D(LineDirectionOnScreen.X * 0.5f * (float)EdMode-&gt;ViewRect.Width(), LineDirectionOnScreen.Y * 0.5f * (float)EdMode-&gt;ViewRect.Height());&#xD;&#xA;&#xD;&#xA;When `LineDirection` is (0,0,1) it always returns a something like (0,Y) (Y can be anything), no matter how the camera is rotated.&#xD;&#xA;&#xD;&#xA;What is wrong with my code?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3522" PostHistoryTypeId="1" PostId="1766" RevisionGUID="21ae2aed-9026-49af-b00a-3e14d22be427" CreationDate="2015-11-30T16:12:56.893" UserId="2173" Text="How to use GetViewProjMatrix().TransformVector(LineDirection) in UE4?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3523" PostHistoryTypeId="3" PostId="1766" RevisionGUID="21ae2aed-9026-49af-b00a-3e14d22be427" CreationDate="2015-11-30T16:12:56.893" UserId="2173" Text="|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3525" PostHistoryTypeId="2" PostId="1767" RevisionGUID="82ef7d77-2b31-4707-aea4-cdbbf6e949c2" CreationDate="2015-12-01T08:06:23.860" UserId="1634" Text="I have three points P&lt;sub&gt;0&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, P&lt;sub&gt;2&lt;/sub&gt;, which are located on an arbitrarily oriented ellipse in 3D space. I have a square texture map with a circle on it. I would like to render a textured quad (with the obvious UV mapping) so that the circle in the texture map projects onto the ellipse that P&lt;sub&gt;0&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, P&lt;sub&gt;2&lt;/sub&gt; are on. &#xD;&#xA;&#xD;&#xA;How do I calculate the vertices of the quad to project the ellipse correctly?&#xD;&#xA;&#xD;&#xA;(Alternately, instead of P&lt;sub&gt;0&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, P&lt;sub&gt;2&lt;/sub&gt;, I have the [Keplerian elements][1] of an elliptical orbit, if that's more straightforward.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orbital_elements#Keplerian_elements" ContentLicense="CC BY-SA 3.0" />
  <row Id="3526" PostHistoryTypeId="1" PostId="1767" RevisionGUID="82ef7d77-2b31-4707-aea4-cdbbf6e949c2" CreationDate="2015-12-01T08:06:23.860" UserId="1634" Text="Project quad onto ellipse in 3D" ContentLicense="CC BY-SA 3.0" />
  <row Id="3527" PostHistoryTypeId="3" PostId="1767" RevisionGUID="82ef7d77-2b31-4707-aea4-cdbbf6e949c2" CreationDate="2015-12-01T08:06:23.860" UserId="1634" Text="|3d|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3528" PostHistoryTypeId="5" PostId="1767" RevisionGUID="1ec76bc6-9c80-4c74-91ed-789cae9c4929" CreationDate="2015-12-01T08:34:20.093" UserId="1634" Comment="added 4 characters in body" Text="I have three points P&lt;sub&gt;0&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, P&lt;sub&gt;2&lt;/sub&gt;, which are located on an arbitrarily oriented ellipse in 3D space. I have a square texture map with a circle on it. I would like to render a textured quad (with the obvious UV mapping) so that the circle in the texture map projects onto the ellipse that P&lt;sub&gt;0&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, P&lt;sub&gt;2&lt;/sub&gt; are on. &#xD;&#xA;&#xD;&#xA;How do I calculate the vertices of the quad to project the ellipse correctly?&#xD;&#xA;&#xD;&#xA;(Alternately, in addition to P&lt;sub&gt;0&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, P&lt;sub&gt;2&lt;/sub&gt;, I have the [Keplerian elements][1] of an elliptical orbit, if that's more straightforward.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orbital_elements#Keplerian_elements" ContentLicense="CC BY-SA 3.0" />
  <row Id="3529" PostHistoryTypeId="5" PostId="1766" RevisionGUID="a2f98004-f198-4813-a7b8-f6f055063a39" CreationDate="2015-12-02T09:58:57.457" UserId="2173" Comment="added 27 characters in body" Text="I try to project a 3D vector (a direction, not a position) in screen space, but it does not return satisfying results:&#xD;&#xA;&#xD;&#xA;     FVector LineDirectionOnScreen = &#xD;&#xA;       EdMode-&gt;ViewMatrices.GetViewProjMatrix().TransformVector(LineDirection);&#xD;&#xA;     FVector2D LineDirectionOnScreen2D(&#xD;&#xA;       LineDirectionOnScreen.X * 0.5f * (float)EdMode-&gt;ViewRect.Width(), &#xD;&#xA;       LineDirectionOnScreen.Y * 0.5f * (float)EdMode-&gt;ViewRect.Height());&#xD;&#xA;&#xD;&#xA;When `LineDirection` is (0,0,1) it always returns a something like (0,Y) (Y can be anything), no matter how the camera is rotated.&#xD;&#xA;&#xD;&#xA;What is wrong with my code?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3530" PostHistoryTypeId="2" PostId="1768" RevisionGUID="17b67f2a-c1e1-4e08-8280-74cd01dd3cd5" CreationDate="2015-12-02T10:07:54.247" UserId="2111" Text="I've been skimming some papers and publications related to it lately, and what I don't understand is how it can possibly be efficient. Doesn't it require constant recalculation of UV coordinates from the &quot;global texture page&quot; space into the virtual texture coordinates? And how doesn't that curb most attempts at batching geometry altogether? How can it allow arbitrary zooming in? Wouldn't it at some point require subdividing polygons?&#xD;&#xA;&#xD;&#xA;There just is so much I don't understand, and I have been unable to find any actually easily approachable resources on the topic." ContentLicense="CC BY-SA 3.0" />
  <row Id="3531" PostHistoryTypeId="1" PostId="1768" RevisionGUID="17b67f2a-c1e1-4e08-8280-74cd01dd3cd5" CreationDate="2015-12-02T10:07:54.247" UserId="2111" Text="How can virtual texturing actually be efficient?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3532" PostHistoryTypeId="3" PostId="1768" RevisionGUID="17b67f2a-c1e1-4e08-8280-74cd01dd3cd5" CreationDate="2015-12-02T10:07:54.247" UserId="2111" Text="|rendering|texture|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3534" PostHistoryTypeId="5" PostId="1765" RevisionGUID="979c2734-d7c4-4953-8fea-2cd225484a6d" CreationDate="2015-12-02T12:16:51.070" UserId="2173" Comment="edited body" Text="I am working on the move tool in a 3D modeling software. I need to know how much to move when the user drags an axis of the [gizmo](http://www.finalclap.com/ressources/images/3dsmax-tracking6.jpg) (for example along the x axis). &#xD;&#xA;&#xD;&#xA;I have the 2D vector describing how much the mouse moved on the screen `MouseDelta`, and the vector corresponding to the selected axis `AxisVector`. &#xD;&#xA;&#xD;&#xA;I would like to know the best way to compute the amount of extrusion I should apply. &#xD;&#xA;&#xD;&#xA;Currently I try to project the `AxisVector` in screen space, project `MouseDelta` on it and get the ratio between the size of the `AxisVectorOnScreen` and the computed projection. Then I have to clamp the result and multiply it by a factor. Here is a pseudo code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Vector3 AxisVectorOnScreen = GetViewProjMatrix().TransformVector(AxisVector);&#xD;&#xA;    Vector2 AxisVectorOnScreen2D(AxisVectorOnScreen .X * 0.5f * Screen.Width(), AxisVectorOnScreen .Y * 0.5f * Screen.Height());&#xD;&#xA;    Vector2 MouseDelta = EndMousePosition - BeginMousePosition;&#xD;&#xA;    float Size = AxisVectorOnScreen2D.Length();&#xD;&#xA;    float ProjectionLength = MouseDelta | AxisVectorOnScreen2D.GetSafeNormal();&#xD;&#xA;    float Ratio = Size / ProjectionLength;&#xD;&#xA;    float Amount = 10.f * FMath::Clamp(Ratio, -2.5f, 2.5f);&#xD;&#xA;&#xD;&#xA;I think I could also project my mouse vector on a plane perpendicular to the camera and do the same maths on this plane. What is the best solution?&#xD;&#xA;&#xD;&#xA;*Note: I have the same problem to get the amount of extrusion I should apply with my extrude tool (along the normal of a face).*" ContentLicense="CC BY-SA 3.0" />
  <row Id="3535" PostHistoryTypeId="2" PostId="1769" RevisionGUID="696fc63a-353d-4f9d-85e4-143fd08a3870" CreationDate="2015-12-02T13:32:22.497" UserId="2179" Text="Can I get to know the difference between the three? A good example would add up too." ContentLicense="CC BY-SA 3.0" />
  <row Id="3536" PostHistoryTypeId="1" PostId="1769" RevisionGUID="696fc63a-353d-4f9d-85e4-143fd08a3870" CreationDate="2015-12-02T13:32:22.497" UserId="2179" Text="World coordinates, Normalised device coordinates and device coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="3537" PostHistoryTypeId="3" PostId="1769" RevisionGUID="696fc63a-353d-4f9d-85e4-143fd08a3870" CreationDate="2015-12-02T13:32:22.497" UserId="2179" Text="|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3538" PostHistoryTypeId="2" PostId="1770" RevisionGUID="168e48f3-7c19-4faa-baea-d709176a2a54" CreationDate="2015-12-02T18:08:11.140" UserId="310" Text="Are you perhaps confusing Virtual Texturing and Texture Atlases?&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;A texture atlas is a single giant texture that contains textures for individual meshes inside it:&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;Texture atlases became popular due to the fact that changing textures causes a full pipeline flush on the GPU. &#xD;&#xA;&#xD;&#xA;When creating the meshes, the UVs are compressed/shifted so that they represent the correct 'portion' of the whole texture atlas. This is the main drawback of texture atlases. Floating point math is not exact. The more textures you try to compress into an atlas, the less precise their UV coordinate become. This can lead to bleeding artifacts.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;Virtual textures solve a different problem. In many graphics algorithms it's mathematically/logically convenient to store your data in a solid 1D/2D/3D block of memory/textures (Voxels, fluid simulations, GI calculations, etc.). However, you usually only use a small portion of the whole block of memory, ie. the data is sparse. Therefore, it would be incredibly wasteful to allocate the entire block of memory when we need only a small potion of it. Virtual textures solve this problem by only allocating memory for the portions that you need.&#xD;&#xA;&#xD;&#xA;In their simplest form, virtual textures are nothing more than a table of pointers. &#xD;&#xA;&#xD;&#xA;![Virtual Texture Table][2]&#xD;&#xA;&#xD;&#xA;When the user requests a portion of the memory block, the GPU will create a chunk of memory for them, and update the pointer in the table. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.gamasutra.com/features/20060126/figure1.jpg&#xD;&#xA;  [2]: http://i.imgur.com/lbiZUMx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3539" PostHistoryTypeId="10" PostId="1730" RevisionGUID="83a01418-06a4-451d-a0e6-8e8a6267ead6" CreationDate="2015-12-02T18:12:39.340" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:54,&quot;DisplayName&quot;:&quot;glampert&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:528,&quot;DisplayName&quot;:&quot;Wumpf&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;}]}" />
  <row Id="3540" PostHistoryTypeId="5" PostId="1768" RevisionGUID="43f46875-e84f-46a7-a3e9-7513cd90ea65" CreationDate="2015-12-02T18:54:07.313" UserId="2111" Comment="added 312 characters in body" Text="For reference, what I'm referring to is the &quot;generic name&quot; for the technique first(I believe) introduced with idTech 5's [MegaTexture](https://en.wikipedia.org/wiki/MegaTexture) technology. See the video [here](http://holger.dammertz.org/stuff/notes_VirtualTexturing.html) for a quick glance on how it works.&#xD;&#xA;&#xD;&#xA;I've been skimming some papers and publications related to it lately, and what I don't understand is how it can possibly be efficient. Doesn't it require constant recalculation of UV coordinates from the &quot;global texture page&quot; space into the virtual texture coordinates? And how doesn't that curb most attempts at batching geometry altogether? How can it allow arbitrary zooming in? Wouldn't it at some point require subdividing polygons?&#xD;&#xA;&#xD;&#xA;There just is so much I don't understand, and I have been unable to find any actually easily approachable resources on the topic." ContentLicense="CC BY-SA 3.0" />
  <row Id="3541" PostHistoryTypeId="2" PostId="1771" RevisionGUID="87fc8a08-d328-4a96-a1f9-e0723790a794" CreationDate="2015-12-02T22:27:09.273" UserId="48" Text="**World coordinates** are at the bedrock of your game world. The 3D positions of all objects are ultimately specified in world space, either directly or through a node hierarchy. The ground, buildings, trees, and other stationary things will be fixed in world space. Gameplay calculations and physics will be done in world space (perhaps with some local recentering for precision purposes, if the world is large). The axes of world coordinates are often taken to represent compass directions, such as X = east, Y = north, Z = up.&#xD;&#xA;&#xD;&#xA;**Local coordinates** are attached to an object (there is one local coordinate space for each object). The axes may represent something meaningful to the object, for instance X = forward, Y = left, Z = up for an object such as a character, vehicle, gun, etc. that has an inherent orientation. As the object moves around, the relationship between local and world space (as expressed by a transformation matrix) will change. For instance if you flip your car upside down, its local Z axis (&quot;up&quot; in local space) will now be pointing &quot;down&quot; in world space.&#xD;&#xA;&#xD;&#xA;**Camera or view coordinates** are local coordinates attached to the camera. This is still a 3D coordinate system, without any projection or anything, but with the axes aligned to match the screen orientation: usually X = right, Y = up, Z = backward. The transformation from world to view space is often known as the &quot;view matrix&quot;.&#xD;&#xA;&#xD;&#xA;**Clip space coordinates** are the coordinates output by a vertex shader: coordinates to which the projection matrix has been applied, but not the perspective divide. This is a 4D (homogeneous) space. (World, local, and view space are 3D with an implicit w = 1.) It's so named because this is the space in which view frustum clipping and culling takes place (conceptually, at least).&#xD;&#xA;&#xD;&#xA;**Normalized device coordinates**, also commonly known as &quot;screen space&quot; although that term is a little loose, are what you get after applying the perspective divide to clip space coordinates. The 3D coordinates now represent the 2D positions of points on screen, with X and Y in [−1, 1], together with the depth within the depth buffer range, Z in [0, 1] for D3D or [−1, 1] for OpenGL. The axis orientation is X = right, Y = up, and Z can be either forward or backward depending on the depth buffer configuration.&#xD;&#xA;&#xD;&#xA;**Device coordinates** are 2D pixel coordinates within the render target, with (0, 0) in the upper-left corner, X = right, Y = down. One arrives at device coordinates by applying the viewport transform to the normalized device coordinates; the viewport controls at what pixel offset and resolution the image appears in the render target. One thing that's important to note is that device coordinates are not integer values; they aren't indices of pixels. They're a continuous 2D coordinate system, using pixel-sized units, but in which fractional (subpixel) values are perfectly valid. Pixel centers lie at 0.5 offsets (like 0.5, 1.5, 2.5, ...) in this coordinate system." ContentLicense="CC BY-SA 3.0" />
  <row Id="3542" PostHistoryTypeId="2" PostId="1772" RevisionGUID="2a6c8fd7-e5eb-4d98-8b84-8c76e2d60c96" CreationDate="2015-12-02T22:52:08.860" UserId="48" Text="I don't think you can simply use `TransformVector` when the matrix you're transforming by involves a projection matrix. To fully project to screen space, you have to divide by W, which `TransformVector` doesn't do (it simply multiplies by the matrix without translation).&#xD;&#xA;&#xD;&#xA;Also, because of the divide by W, transforming *vectors* (as opposed to *points*) by a projection matrix is probably not what you actually want. If what you want is the screen-space vector between two points, you should transform and divide-by-W each point, then subtract them to get a screen-space vector. Otherwise the vector will likely be inaccurate." ContentLicense="CC BY-SA 3.0" />
  <row Id="3544" PostHistoryTypeId="2" PostId="1773" RevisionGUID="8fa58596-a29f-4f4a-b277-6c1253eed818" CreationDate="2015-12-03T04:05:20.233" UserId="54" Text="The main reason for Virtual Texturing (VT), or Sparse Virtual Textures, as it is sometimes called, is as a memory optimization. The gist of the thing is to only page into video memory the actual texels (generalized as tiles/pages) that you might need for a rendered frame. So it will allow you to have much more texture data in offline storage (HDD, Optic-Disk, cloud) than it would otherwise fit on video memory or even main memory. If you understand the concept of [Virtual Memory][1] used by modern Operating Systems, it is the same thing in its essence.&#xD;&#xA;&#xD;&#xA;It does not require recomputing UVs in the sense that you'd do that each frame before rendering a mesh, but it does require some substantial work in the Vertex and Fragment shaders to perform the indirect lookup from the incoming UVs. In a good implementation, however, it should be completely transparent for the application if it is using a virtual texture or a traditional one. Actually, most of the time an application will mix both types of texturing, virtual and traditional.&#xD;&#xA;&#xD;&#xA;Batching can in theory work very well, though I have never looked into the details of this. The usual criteria for grouping geometry is textures, and with VT, every polygon in the scene can share the same &quot;infinitely large&quot; texture, so theoretically, you could achieve full scene drawing with 1 draw call.&#xD;&#xA;&#xD;&#xA;The zooming in/out and abrupt camera movement are the hardest things to handle in a VT setup. It can look very appealing for a static scene, but once things start moving, more texture pages/tiles will be requested than you can stream for external storage. Async file IO and threading can help, but if it is a real-time system, like in a game, you'll just have to render for a few frames with lower resolution tiles until the hi-res ones arrive every now and then, resulting in a blurry texture. There's no silver bullet here and that's the biggest issue with the technique, IMO.&#xD;&#xA;&#xD;&#xA;Virtual Texturing also doesn't handle transparency in an easy way, so transparent polygons need a tradition rendering path for them.&#xD;&#xA;&#xD;&#xA;All in all, VT is interesting, but I wouldn't recommend it for everyone. It can work well, but it is hard to implement and there's just too many corner cases and case-specific tweaks needed for my taste. But for large open-world games or data visualization apps, it might be the only possible approach to fit all the content into the available hardware. With a lot of work, it can be made to run fairly efficiently even on limited devices, like we can see in the PS3 and XBOX360 versions of id's *Rage*. &#xD;&#xA;&#xD;&#xA;I have also personally managed to get it working on iOS with OpenGL-ES, to a certain degree. My implementation is not &quot;shippable&quot;, but I could conceivably make it so if I wanted and had the need. [You can view the source code here][2], it might help getting a better idea of how the pieces fit together.&#xD;&#xA;&#xD;&#xA;Others resources I'd also suggest checking out:&#xD;&#xA;&#xD;&#xA;- The first book in the [GPU Pro series][3]. It has two very good articles on VT.&#xD;&#xA;&#xD;&#xA;- Mandatory paper by MrElusive: [Software Virtual Textures][4].&#xD;&#xA;&#xD;&#xA;- The Crytek paper by Martin Mittring: [Advanced Virtual Texture Topics][5].&#xD;&#xA;&#xD;&#xA;- And [Sean's presentation on youtube][6], which I see you've already found. &#xD;&#xA;&#xD;&#xA;VT is still a somewhat hot topic on Computer Graphics, so there's tons of good material available, you should be able to find a lot more. If there's anything else I can add to this answer, please feel free to ask. I'm a bit rusty on the topic, haven't read much about it for the past year, but it is alway good for the memory to revisit stuff :)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Virtual_memory&#xD;&#xA;  [2]: https://bitbucket.org/glampert/vt-mobile&#xD;&#xA;  [3]: http://gpupro.blogspot.com.br/&#xD;&#xA;  [4]: http://www.mrelusive.com/publications/papers/Software-Virtual-Textures.pdf&#xD;&#xA;  [5]: http://developer.amd.com/wordpress/media/2013/01/Chapter02-Mittring-Advanced_Virtual_Texture_Topics.pdf&#xD;&#xA;  [6]: http://silverspaceship.com/src/svt/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3546" PostHistoryTypeId="2" PostId="1774" RevisionGUID="ab4334cd-1fd6-4d26-a82a-532e7d65e674" CreationDate="2015-12-03T09:47:23.183" UserId="2111" Text="For example, let's assume I'm rendering cascaded shadow mapping, but for whatever reason, instead of one of the typical approach, I do the following:&#xD;&#xA;&#xD;&#xA; * Render the lowest resolution shadowmap&#xD;&#xA;&#xD;&#xA; * Copy part of the shadowmap to the next shadowmap, covering a smaller area(and thus more dense)&#xD;&#xA;&#xD;&#xA; * Compute a stencil mask based on different points' distance from camera, e.g. more detail on edges, and on points closer to the camera, reusing the old shadowmap elsewhere.&#xD;&#xA;&#xD;&#xA; * Render the next, higher-density shadowmap with the aforementioned stencil.&#xD;&#xA;&#xD;&#xA;What performance can I realistically expect from that? If only 50% of the pixels(or should I say fragments here?) pass the stencil test, do I save 50% of the rendering time, less, none?&#xD;&#xA;&#xD;&#xA;If this is a poor example, my fallback question scenario is a static scene, where the previous frame's result is reprojected, with an error accumulator in alpha, and a stencil mask is computed based on misses or too high error rates(e.g. position of the previous frame's reprojected pixel is too far from the new target pixel)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3547" PostHistoryTypeId="1" PostId="1774" RevisionGUID="ab4334cd-1fd6-4d26-a82a-532e7d65e674" CreationDate="2015-12-03T09:47:23.183" UserId="2111" Text="How much processing power does stenciling actually save?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3548" PostHistoryTypeId="3" PostId="1774" RevisionGUID="ab4334cd-1fd6-4d26-a82a-532e7d65e674" CreationDate="2015-12-03T09:47:23.183" UserId="2111" Text="|optimisation|stencil-test|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3549" PostHistoryTypeId="5" PostId="1773" RevisionGUID="f1eede1d-7840-493b-8586-0c7f64dd476c" CreationDate="2015-12-03T18:43:24.437" UserId="54" Comment="Expanded the answer per OPs request." Text="## Overview&#xD;&#xA;&#xD;&#xA;The main reason for Virtual Texturing (VT), or *Sparse Virtual Textures*, as it is sometimes called, is as a memory optimization. The gist of the thing is to only move into video memory the actual texels (generalized as pages/tiles) that you might need for a rendered frame. So it will allow you to have much more texture data in offline or slow storage (HDD, Optical-Disk, Cloud) than it would otherwise fit on video memory or even main memory. If you understand the concept of [Virtual Memory][1] used by modern Operating Systems, it is the same thing in its essence (the name is not given by accident).&#xD;&#xA;&#xD;&#xA;VT does not require recomputing UVs in the sense that you'd do that each frame before rendering a mesh, then resubmit vertex data, but it does require some substantial work in the Vertex and Fragment shaders to perform the indirect lookup from the incoming UVs. In a good implementation however, it should be completely transparent for the application if it is using a virtual texture or a traditional one. Actually, most of the time an application will mix both types of texturing, virtual and traditional.&#xD;&#xA;&#xD;&#xA;Batching can in theory work very well, though I have never looked into the details of this. Since the usual criteria for grouping geometry are the textures, and with VT, every polygon in the scene can share the same &quot;infinitely large&quot; texture, theoretically, you could achieve full scene drawing with 1 draw call. But in reality, other factors come into play making this impractical.&#xD;&#xA;&#xD;&#xA;## Issues with VT&#xD;&#xA;&#xD;&#xA;Zooming in/out and abrupt camera movement are the hardest things to handle in a VT setup. It can look very appealing for a static scene, but once things start moving, more texture pages/tiles will be requested than you can stream for external storage. Async file IO and threading can help, but if it is a real-time system, like in a game, you'll just have to render for a few frames with lower resolution tiles until the hi-res ones arrive, every now and then, resulting in a blurry texture. There's no silver bullet here and that's the biggest issue with the technique, IMO.&#xD;&#xA;&#xD;&#xA;Virtual Texturing also doesn't handle transparency in an easy way, so transparent polygons need a separate traditional rendering path for them.&#xD;&#xA;&#xD;&#xA;All in all, VT is interesting, but I wouldn't recommend it for everyone. It can work well, but it is hard to implement and optimize, plus there's just too many corner cases and case-specific tweaks needed for my taste. But for large open-world games or data visualization apps, it might be the only possible approach to fit all the content into the available hardware. With a lot of work, it can be made to run fairly efficiently even on limited hardware, like we can see in the PS3 and XBOX360 versions of id's *Rage*. &#xD;&#xA;&#xD;&#xA;## Implementation&#xD;&#xA;&#xD;&#xA;I have managed to get VT working on iOS with OpenGL-ES, to a certain degree. My implementation is not &quot;shippable&quot;, but I could conceivably make it so if I wanted and had the resources. [You can view the source code here][2], it might help getting a better idea of how the pieces fit together. [Here's a video][3] of a demo running on the iOS Sim. It looks very laggy because the simulator is terrible at emulating shaders, but it runs smoothly on a device.&#xD;&#xA;&#xD;&#xA;The following diagram outlines the main components of the system in my implementation. It differs quite a bit from Sean's SVT demo (link down bellow), but it is closer in architecture to the one presented by the paper *Accelerating Virtual Texturing Using CUDA*, found in the first GPU Pro book (link bellow).&#xD;&#xA;&#xD;&#xA;[![virtual texturing system][4]][4]&#xD;&#xA;&#xD;&#xA;- `Page Files` are the virtual textures, already cut into tiles (AKA pages) as a preprocessing step, so they are ready to be moved from disk into video memory whenever needed. A page file also contains the whole set of mipmaps, also called *virtual mipmaps*.&#xD;&#xA;&#xD;&#xA;- `Page Cache Manager` keeps an application-side representation of the `Page Table` and `Page Indirection` textures. Since moving a page from offline storage to memory is expensive, we need a cache to avoid reloading what is already available. This cache is a very simple *Least Recently Used* (LRU) cache. The cache is also the component responsible for keeping the physical textures up-to-date with its own local representation of the data.&#xD;&#xA;&#xD;&#xA;- The `Page Provider` is an async job queue that will fetch the pages needed for a given view of the scene and send them to the cache.&#xD;&#xA;&#xD;&#xA;- The `Page Indirection` texture is a texture with one pixel for each page/tile in the virtual texture, that will map the incoming UVs to the `Page Table` cache texture that has the actual texel data. This texture can get quite large, so it must use some compact format, like RGBA 8:8:8:8 or RGB 5:6:5.&#xD;&#xA;&#xD;&#xA;But we are still missing a key piece here, and that's how to determine which pages must be loaded from storage into the cache and consequently into the `Page Table`. That's where the *Feedback Pass* and the `Page Resolver` enter.&#xD;&#xA;&#xD;&#xA;The Feedback Pass is a pre-render of the view, with a custom shader and at a much lower resolution, that will write the ids of the required pages to the color framebuffer. That colorful patchwork of the cube and sphere above are actual page indexes encoded as an RGBA color. This pre-pass rendering is then read into main memory and processed by the `Page Resolver` to decode the page indexes and fire the new requests with the `Page Provider`.&#xD;&#xA;&#xD;&#xA;After the Feedback pre-pass, the scene can be rendered normally with the VT lookup shaders. But note that we don't wait for new page request to finish, that would be terrible, because we'd simply block on synchronous file IO. The requests are asynchronous and might or might not be ready by the time the final view is rendered. If they are ready, sweet, but if not, we always keep a locked page of a low-res mipmap in the cache as a fallback, so we have some texture data in there to use, but it is going to be blurry.&#xD;&#xA;&#xD;&#xA;## Others resources worth checking out&#xD;&#xA;&#xD;&#xA;- The first book in the [GPU Pro series][5]. It has two very good articles on VT.&#xD;&#xA;&#xD;&#xA;- Mandatory paper by MrElusive: [Software Virtual Textures][6].&#xD;&#xA;&#xD;&#xA;- The Crytek paper by Martin Mittring: [Advanced Virtual Texture Topics][7].&#xD;&#xA;&#xD;&#xA;- And [Sean's presentation on youtube][8], which I see you've already found. &#xD;&#xA;&#xD;&#xA;VT is still a somewhat hot topic on Computer Graphics, so there's tons of good material available, you should be able to find a lot more. If there's anything else I can add to this answer, please feel free to ask. I'm a bit rusty on the topic, haven't read much about it for the past year, but it is alway good for the memory to revisit stuff :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Virtual_memory&#xD;&#xA;  [2]: https://bitbucket.org/glampert/vt-mobile&#xD;&#xA;  [3]: https://youtu.be/sWz45m0QKj4&#xD;&#xA;  [4]: https://i.stack.imgur.com/F3liK.jpg&#xD;&#xA;  [5]: http://gpupro.blogspot.com.br/&#xD;&#xA;  [6]: http://www.mrelusive.com/publications/papers/Software-Virtual-Textures.pdf&#xD;&#xA;  [7]: http://developer.amd.com/wordpress/media/2013/01/Chapter02-Mittring-Advanced_Virtual_Texture_Topics.pdf&#xD;&#xA;  [8]: http://silverspaceship.com/src/svt/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3550" PostHistoryTypeId="2" PostId="1775" RevisionGUID="f86d7b1d-ed20-4150-9a8e-7bc0e68ec35f" CreationDate="2015-12-03T19:44:36.010" UserId="2187" Text="I am bit new here, so I hope you could me resolve my problem. &#xD;&#xA;I am trying to draw a angles line i raster grid, &#xD;&#xA;&#xD;&#xA;The idea is to create a function that given a start point, a length and a angle,  would give me the pixel positions that combined would give me a line that angled the angle which is given in a raster grid.. &#xD;&#xA;&#xD;&#xA;I tried implement in c++.. but seem to get some weird points.. &#xD;&#xA;&#xD;&#xA;the way i do it, is I compute the equation of the line, and thereby also the endpoint, and then use bresenham line algorithm to find the pixels position that create the line between the start point and end point.  &#xD;&#xA;Some of the points though, don't seem right.. some of the traversing points makes no sense, or goes to infinity?.. What is wrong with my implementation.. &#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    using namespace std;&#xD;&#xA;    &#xD;&#xA;    int sign(double x ){ return (x &gt; 0) ? 1 : ((x &lt; 0) ? -1 : 0); }&#xD;&#xA;    &#xD;&#xA;    std::pair&lt;int,int&gt; endpoint(double angle, int x1 , int y1, int lenght)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        if(angle == 90)&#xD;&#xA;        {&#xD;&#xA;            double y2 = y1+lenght;&#xD;&#xA;            return std::make_pair(x1, -y2);&#xD;&#xA;        }&#xD;&#xA;        if(angle == 180)&#xD;&#xA;        {&#xD;&#xA;            double x2 = x1+lenght;&#xD;&#xA;            return std::make_pair(-x2, y1);&#xD;&#xA;        }&#xD;&#xA;        if(angle == 270)&#xD;&#xA;        {&#xD;&#xA;            double y2 = y1+lenght;&#xD;&#xA;            return std::make_pair(x1, y2);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        double x2 = x1 + (lenght * cos(angle));&#xD;&#xA;        double y2 = y1 + (lenght * sin(angle));&#xD;&#xA;        return std::make_pair(x2,y2);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void bresenham(int x0, int y0, int x1, int y1)&#xD;&#xA;    {&#xD;&#xA;        int dx = x1-x0;&#xD;&#xA;        int dy = y1 - y0;&#xD;&#xA;        if (abs(dx) &gt; abs(dy))&#xD;&#xA;        {&#xD;&#xA;            // x-axis&#xD;&#xA;            int j = y0;&#xD;&#xA;            double e = dy - dx;&#xD;&#xA;            &#xD;&#xA;            for (int i = x0; i&lt;x1; i++)&#xD;&#xA;            {&#xD;&#xA;                std::cout &lt;&lt; &quot;marked: &quot; &lt;&lt; i &lt;&lt; &quot;,&quot;&lt;&lt; j &lt;&lt; std::endl;&#xD;&#xA;                if( e &gt;= 0)&#xD;&#xA;                {&#xD;&#xA;                    j += 1;&#xD;&#xA;                    e -= dx;&#xD;&#xA;                }&#xD;&#xA;                e += dy;&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        else if(abs(dx)&lt;abs(dy))&#xD;&#xA;        {&#xD;&#xA;            // y-axis&#xD;&#xA;    &#xD;&#xA;            int j = x0;&#xD;&#xA;            double e = dx - dy;&#xD;&#xA;            &#xD;&#xA;            for (int i = y0; i&lt;y1; i++)&#xD;&#xA;            {&#xD;&#xA;                std::cout &lt;&lt; &quot;marked: &quot; &lt;&lt; j&lt;&lt; &quot;,&quot;&lt;&lt; i &lt;&lt; std::endl;&#xD;&#xA;                if( e &gt;= 0)&#xD;&#xA;                {&#xD;&#xA;                    j += 1;&#xD;&#xA;                    e -= dy;&#xD;&#xA;                }&#xD;&#xA;                e += dx;&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void line(int x0, int y0, int x1, int y1)&#xD;&#xA;    {&#xD;&#xA;        &#xD;&#xA;        if(x1 &lt; x0)&#xD;&#xA;        {&#xD;&#xA;            swap(x1, x0);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        if(y1 &lt; y0)&#xD;&#xA;        {&#xD;&#xA;            swap(y1, y0);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        int dx = x1-x0;&#xD;&#xA;        int dy = y1-y0;&#xD;&#xA;        double e = 0;&#xD;&#xA;        if(dx == 0)&#xD;&#xA;        {&#xD;&#xA;            if (sign(dy) == -1)&#xD;&#xA;            {&#xD;&#xA;                cout &lt;&lt; &quot;new&quot; &lt;&lt; endl;&#xD;&#xA;                for (int y = y0; y != y1; y--)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x1 &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                for (int y = y0; y != y1; y++)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x1 &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        else if(dy == 0)&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;            if (sign(dx) == -1)&#xD;&#xA;            {&#xD;&#xA;                cout &lt;&lt; &quot;new&quot; &lt;&lt; endl;&#xD;&#xA;                &#xD;&#xA;                for (int x = x0; x != x1; x--)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y1 &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                for (int y = y0; y != y1; y++)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x1 &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        cout &lt;&lt; &quot;bressenham: &quot; &lt;&lt; endl;&#xD;&#xA;        double de = abs(dy/dx);&#xD;&#xA;        int y = y0;&#xD;&#xA;        for (int x = x0; x != x1; x++)&#xD;&#xA;        {&#xD;&#xA;            cout &lt;&lt; &quot;mark: &quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;            e = e + de;&#xD;&#xA;            while (e &gt;= 0.5)&#xD;&#xA;            {&#xD;&#xA;                cout &lt;&lt; &quot;mark: &quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                y = y + sign(y1-y0);&#xD;&#xA;                e = e -1;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main(int argc, const char * argv[])&#xD;&#xA;    {&#xD;&#xA;        for (int angle = 0; angle &lt; 180; angle++)&#xD;&#xA;        {&#xD;&#xA;            cout &lt;&lt; &quot;angle: &quot; &lt;&lt; angle &lt;&lt; endl;&#xD;&#xA;            pair&lt;int, int&gt; end = endpoint(angle, 3, 3, 20);&#xD;&#xA;            cout &lt;&lt; end.first &lt;&lt; end.second &lt;&lt; endl;&#xD;&#xA;            line(3, 3, end.first, end.second);&#xD;&#xA;            cout &lt;&lt; end.first &lt;&lt; end.second &lt;&lt; endl;&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="3551" PostHistoryTypeId="1" PostId="1775" RevisionGUID="f86d7b1d-ed20-4150-9a8e-7bc0e68ec35f" CreationDate="2015-12-03T19:44:36.010" UserId="2187" Text="Draw lines angling from 0 to 2pi in a raster grid" ContentLicense="CC BY-SA 3.0" />
  <row Id="3552" PostHistoryTypeId="3" PostId="1775" RevisionGUID="f86d7b1d-ed20-4150-9a8e-7bc0e68ec35f" CreationDate="2015-12-03T19:44:36.010" UserId="2187" Text="|c++|grid|line-drawing|raster-image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3553" PostHistoryTypeId="5" PostId="1770" RevisionGUID="6d064d6c-1073-4e19-8100-a03bcfd79eea" CreationDate="2015-12-03T20:26:40.657" UserId="310" Comment="added 4239 characters in body" Text="Virtual Texturing is the logical extreme of texture atlases.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;A texture atlas is a single giant texture that contains textures for individual meshes inside it:&#xD;&#xA;&#xD;&#xA;![Texture Atlas Example][1]&#xD;&#xA;&#xD;&#xA;Texture atlases became popular due to the fact that changing textures causes a full pipeline flush on the GPU. When creating the meshes, the UVs are compressed/shifted so that they represent the correct 'portion' of the whole texture atlas. &#xD;&#xA;&#xD;&#xA;One of the main drawbacks of texture atlases is losing wrap modes such as repeat, clamp, border, etc. In addition, if the textures don't have enough border around them, you can accidentally sample from an adjacent texture when doing filtering. This can lead to bleeding artifacts.&#xD;&#xA;&#xD;&#xA;Texture Atlases do have one major limitation: size. Graphics APIs place a soft limit on how big a texture can be. That said, graphics memory is only so big. So there is also a hard limit on texture size, given by the size of your v-ram. Virtual textures solve this problem, by borrowing concepts from [virtual memory][2]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Virtual textures exploit the fact that in most scenes, you only see a small portion of all the textures. So, only that subset of textures need to be in vram. The rest can be in main RAM, or on disk.&#xD;&#xA;&#xD;&#xA;There are a few ways to implement it, but I will explain the implementation described by Sean Barrett in his [GDC talk][3]. (which I highly recommend watching)&#xD;&#xA;&#xD;&#xA;We have three main elements: the virtual texture, the physical texture, and the lookup table.&#xD;&#xA;&#xD;&#xA;![Virtual Texture][4]&#xD;&#xA;&#xD;&#xA;The virtual texture represents the theoretical mega atlas we would have if we had enough vram to fit everything. It doesn't actually exist in memory anywhere. The physical texture represents what pixel data we actually have in vram. The lookup table is the mapping between the two. For convenience, we break all three elements into equal sized tiles, or pages. &#xD;&#xA;&#xD;&#xA;The lookup table stores the location of the top-left corner of the tile in the physical texture. So, given a UV to the entire virtual texture, how do we get the corresponding UV for the physical texture?&#xD;&#xA;&#xD;&#xA;First, we need to find the location of the page within the physical texture. Then we need to calculate the location of the UV within the page. Finally we can add these two offsets together to get the location of the UV within the physical texture&#xD;&#xA;&#xD;&#xA;    float2 pageLocInPhysicalTex = ...&#xD;&#xA;    float2 inPageLocation = ...&#xD;&#xA;    float2 physicalTexUV = pageLocationInPhysicalTex + inPageLocation;&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Calculating pageLocInPhysicalTex** &#xD;&#xA;&#xD;&#xA;If we make the lookup table the same size as the number of tiles in the virtual texture, we can just sample the lookup table with nearest neighbor sampling and we will get the location of the top-left corner of the page within the physical texture.&#xD;&#xA;&#xD;&#xA;    float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);&#xD;&#xA;&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;**Calculating inPageLocation**&#xD;&#xA;&#xD;&#xA;inPageLocation is a UV coordinate that is relative to the top-left of the page, rather than to the top-left of the whole texture. &#xD;&#xA;&#xD;&#xA;One way to calculate this is by subtracting off the UV of the top left of the page, then scaling to the size of the page. However, this is quite a bit of math. Instead, we can exploit how IEEE floating point is represented. IEEE floating point stores the fractional part of a number by a series of base 2 fractions.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;In this example, the number is:&#xD;&#xA;&#xD;&#xA;    number = 0 + (1/2) + (1/8) + (1/16) = 0.6875&#xD;&#xA;&#xD;&#xA;Now lets look at a simplified version of the virtual texture:&#xD;&#xA;&#xD;&#xA;![Simple Virtual Texture][6]&#xD;&#xA;&#xD;&#xA;The 1/2 bit tells us if we're in the left half of the texture or the right. The 1/4 bit tells us which quarter of the half we're in. In this example, since the texture is split into 16, or 4 to a side, these first two bits tell us what page we're in. The remaining bits tell us the location inside the page.&#xD;&#xA;&#xD;&#xA;We can get the remaining bits by shifting the float with exp2() and stripping them out with fract()&#xD;&#xA;&#xD;&#xA;    float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));&#xD;&#xA;    inPageLocation = fract(inPageLocation);&#xD;&#xA;&#xD;&#xA;Where numTiles is a int2 giving the number of tiles per side of the texture. In our example, this would be (4, 4)&#xD;&#xA;&#xD;&#xA;So let's calculate the inPageLocation for the green point, (x,y) = (0.6875, 0.375)&#xD;&#xA;&#xD;&#xA;    inPageLocation = float2(0.6875, 0.375) * exp2(sqrt(int2(4, 4));&#xD;&#xA;                   = float2(0.6875, 0.375) * int2(2, 2);&#xD;&#xA;                   = float2(1.375, 0.75);&#xD;&#xA;    &#xD;&#xA;    inPageLocation = fract(float2(1.375, 0.75));&#xD;&#xA;                   = float2(0.375, 0.75);&#xD;&#xA;&#xD;&#xA;One last thing to do before we're done. Currently, inPageLocation is a UV coordinate in the virtual texture 'space'. However, we want a UV coordinate in the physical texture 'space'. To do this we just have to scale inPageLocation by the ratio of virtual texture size to physical texture size&#xD;&#xA;&#xD;&#xA;    inPageLocation *= physicalTextureSize / virtualTextureSize;&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So the finished function is:&#xD;&#xA;&#xD;&#xA;    float2 CalculatePhysicalTexUV(float2 virtTexUV, Texture2D&lt;float2&gt; lookupTable, uint2 physicalTexSize, uint2 virtualTexSize, uint2 numTiles) {&#xD;&#xA;        float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);&#xD;&#xA;        &#xD;&#xA;        float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));&#xD;&#xA;        inPageLocation = fract(inPageLocation);&#xD;&#xA;        inPageLocation *= physicalTexSize / virtualTexSize;&#xD;&#xA;        &#xD;&#xA;        return pageLocInPhysicalTex + inPageLocation;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: http://www.gamasutra.com/features/20060126/figure1.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Virtual_memory&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=MejJL87yNgI&#xD;&#xA;  [4]: https://i.stack.imgur.com/SFNvJ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/48VfH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Jj8K9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3554" PostHistoryTypeId="12" PostId="1770" RevisionGUID="49e3324a-ff14-49b9-a282-278a73b615ec" CreationDate="2015-12-03T20:27:08.373" UserId="310" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;}]}" />
  <row Id="3555" PostHistoryTypeId="13" PostId="1770" RevisionGUID="f18e0010-a244-4f0f-a463-754ca6f2df7a" CreationDate="2015-12-03T20:28:36.913" UserId="310" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;}]}" />
  <row Id="3556" PostHistoryTypeId="5" PostId="1770" RevisionGUID="050eca3d-d4b6-42be-aa3f-6a937df59465" CreationDate="2015-12-03T20:51:12.677" UserId="310" Comment="added 43 characters in body" Text="Virtual Texturing is the logical extreme of texture atlases.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;A texture atlas is a single giant texture that contains textures for individual meshes inside it:&#xD;&#xA;&#xD;&#xA;![Texture Atlas Example][1]&#xD;&#xA;&#xD;&#xA;Texture atlases became popular due to the fact that changing textures causes a full pipeline flush on the GPU. When creating the meshes, the UVs are compressed/shifted so that they represent the correct 'portion' of the whole texture atlas. &#xD;&#xA;&#xD;&#xA;As @nathan-reed mentioned in the comments, one of the main drawbacks of texture atlases is losing wrap modes such as repeat, clamp, border, etc. In addition, if the textures don't have enough border around them, you can accidentally sample from an adjacent texture when doing filtering. This can lead to bleeding artifacts.&#xD;&#xA;&#xD;&#xA;Texture Atlases do have one major limitation: size. Graphics APIs place a soft limit on how big a texture can be. That said, graphics memory is only so big. So there is also a hard limit on texture size, given by the size of your v-ram. Virtual textures solve this problem, by borrowing concepts from [virtual memory][2]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Virtual textures exploit the fact that in most scenes, you only see a small portion of all the textures. So, only that subset of textures need to be in vram. The rest can be in main RAM, or on disk.&#xD;&#xA;&#xD;&#xA;There are a few ways to implement it, but I will explain the implementation described by Sean Barrett in his [GDC talk][3]. (which I highly recommend watching)&#xD;&#xA;&#xD;&#xA;We have three main elements: the virtual texture, the physical texture, and the lookup table.&#xD;&#xA;&#xD;&#xA;![Virtual Texture][4]&#xD;&#xA;&#xD;&#xA;The virtual texture represents the theoretical mega atlas we would have if we had enough vram to fit everything. It doesn't actually exist in memory anywhere. The physical texture represents what pixel data we actually have in vram. The lookup table is the mapping between the two. For convenience, we break all three elements into equal sized tiles, or pages. &#xD;&#xA;&#xD;&#xA;The lookup table stores the location of the top-left corner of the tile in the physical texture. So, given a UV to the entire virtual texture, how do we get the corresponding UV for the physical texture?&#xD;&#xA;&#xD;&#xA;First, we need to find the location of the page within the physical texture. Then we need to calculate the location of the UV within the page. Finally we can add these two offsets together to get the location of the UV within the physical texture&#xD;&#xA;&#xD;&#xA;    float2 pageLocInPhysicalTex = ...&#xD;&#xA;    float2 inPageLocation = ...&#xD;&#xA;    float2 physicalTexUV = pageLocationInPhysicalTex + inPageLocation;&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Calculating pageLocInPhysicalTex** &#xD;&#xA;&#xD;&#xA;If we make the lookup table the same size as the number of tiles in the virtual texture, we can just sample the lookup table with nearest neighbor sampling and we will get the location of the top-left corner of the page within the physical texture.&#xD;&#xA;&#xD;&#xA;    float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);&#xD;&#xA;&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;**Calculating inPageLocation**&#xD;&#xA;&#xD;&#xA;inPageLocation is a UV coordinate that is relative to the top-left of the page, rather than to the top-left of the whole texture. &#xD;&#xA;&#xD;&#xA;One way to calculate this is by subtracting off the UV of the top left of the page, then scaling to the size of the page. However, this is quite a bit of math. Instead, we can exploit how IEEE floating point is represented. IEEE floating point stores the fractional part of a number by a series of base 2 fractions.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;In this example, the number is:&#xD;&#xA;&#xD;&#xA;    number = 0 + (1/2) + (1/8) + (1/16) = 0.6875&#xD;&#xA;&#xD;&#xA;Now lets look at a simplified version of the virtual texture:&#xD;&#xA;&#xD;&#xA;![Simple Virtual Texture][6]&#xD;&#xA;&#xD;&#xA;The 1/2 bit tells us if we're in the left half of the texture or the right. The 1/4 bit tells us which quarter of the half we're in. In this example, since the texture is split into 16, or 4 to a side, these first two bits tell us what page we're in. The remaining bits tell us the location inside the page.&#xD;&#xA;&#xD;&#xA;We can get the remaining bits by shifting the float with exp2() and stripping them out with fract()&#xD;&#xA;&#xD;&#xA;    float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));&#xD;&#xA;    inPageLocation = fract(inPageLocation);&#xD;&#xA;&#xD;&#xA;Where numTiles is a int2 giving the number of tiles per side of the texture. In our example, this would be (4, 4)&#xD;&#xA;&#xD;&#xA;So let's calculate the inPageLocation for the green point, (x,y) = (0.6875, 0.375)&#xD;&#xA;&#xD;&#xA;    inPageLocation = float2(0.6875, 0.375) * exp2(sqrt(int2(4, 4));&#xD;&#xA;                   = float2(0.6875, 0.375) * int2(2, 2);&#xD;&#xA;                   = float2(1.375, 0.75);&#xD;&#xA;    &#xD;&#xA;    inPageLocation = fract(float2(1.375, 0.75));&#xD;&#xA;                   = float2(0.375, 0.75);&#xD;&#xA;&#xD;&#xA;One last thing to do before we're done. Currently, inPageLocation is a UV coordinate in the virtual texture 'space'. However, we want a UV coordinate in the physical texture 'space'. To do this we just have to scale inPageLocation by the ratio of virtual texture size to physical texture size&#xD;&#xA;&#xD;&#xA;    inPageLocation *= physicalTextureSize / virtualTextureSize;&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So the finished function is:&#xD;&#xA;&#xD;&#xA;    float2 CalculatePhysicalTexUV(float2 virtTexUV, Texture2D&lt;float2&gt; lookupTable, uint2 physicalTexSize, uint2 virtualTexSize, uint2 numTiles) {&#xD;&#xA;        float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);&#xD;&#xA;        &#xD;&#xA;        float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));&#xD;&#xA;        inPageLocation = fract(inPageLocation);&#xD;&#xA;        inPageLocation *= physicalTexSize / virtualTexSize;&#xD;&#xA;        &#xD;&#xA;        return pageLocInPhysicalTex + inPageLocation;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: http://www.gamasutra.com/features/20060126/figure1.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Virtual_memory&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=MejJL87yNgI&#xD;&#xA;  [4]: https://i.stack.imgur.com/SFNvJ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/48VfH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Jj8K9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3557" PostHistoryTypeId="2" PostId="1776" RevisionGUID="a4316ef4-70a4-43f5-9f86-f3038c821bf1" CreationDate="2015-12-04T08:30:44.973" UserId="2190" Text="Code:&#xD;&#xA;&#xD;&#xA;	#include &lt;math.h&gt;&#xD;&#xA;	#include &lt;GL/glut.h&gt;&#xD;&#xA;	#pragma comment(lib, &quot;opengl32&quot;)&#xD;&#xA;	#include &lt;gl/gl.h&gt;&#xD;&#xA;	#include &lt;gl/glu.h&gt;&#xD;&#xA;&#xD;&#xA;	//Initialize OpenGL &#xD;&#xA;	void init(void) {&#xD;&#xA;		glClearColor(0, 0, 0, 0);&#xD;&#xA;&#xD;&#xA;		glViewport(0, 0, 500, 500);&#xD;&#xA;&#xD;&#xA;		glMatrixMode(GL_PROJECTION);&#xD;&#xA;		glLoadIdentity();&#xD;&#xA;&#xD;&#xA;		glOrtho(0, 500, 0, 500, 1, -1);&#xD;&#xA;&#xD;&#xA;		glMatrixMode(GL_MODELVIEW);&#xD;&#xA;		glLoadIdentity();&#xD;&#xA;	} &#xD;&#xA;&#xD;&#xA;	void drawLines(void) {&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT);  &#xD;&#xA;		glColor3f(1.0,1.0,1.0); &#xD;&#xA;&#xD;&#xA;		glBegin(GL_LINES);&#xD;&#xA;	&#xD;&#xA;		glVertex3d(0.5,		    0.999,	0.0f);&#xD;&#xA;		glVertex3d(499.501,		0.999,	0.0f);&#xD;&#xA;	&#xD;&#xA;		glEnd();&#xD;&#xA;&#xD;&#xA;		glFlush();&#xD;&#xA;	} &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	int _tmain(int argc, _TCHAR* argv[])&#xD;&#xA;	{&#xD;&#xA;		glutInit(&amp;argc, argv);  &#xD;&#xA;		glutInitWindowPosition(10,10); &#xD;&#xA;		glutInitWindowSize(500,500); &#xD;&#xA;		glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); &#xD;&#xA;&#xD;&#xA;		glutCreateWindow(&quot;Example&quot;); &#xD;&#xA;		init(); &#xD;&#xA;		glutDisplayFunc(drawLines); &#xD;&#xA;		glutMainLoop();&#xD;&#xA;&#xD;&#xA;		return 0;&#xD;&#xA;	}&#xD;&#xA;Problem description:&#xD;&#xA;&#xD;&#xA; - Above code will put the entire bottom row pixels of the window client area to white.&#xD;&#xA; - If I swap the command order, from `glVertex3d(0.5, 0.999, 0.0f);glVertex3d(499.501, 0.999, 0.0f);` to `glVertex3d(499.501, 0.999, 0.0f);glVertex3d(0.5, 0.999, 0.0f);`, then only the left bottom pixel will not draw.&#xD;&#xA;&#xD;&#xA;My understandings:&#xD;&#xA;&#xD;&#xA; - The two vertices will be finally transformed to 2D pixel center coordinate which are (0.0, 0.499) and (499.001, 0.499).&#xD;&#xA; - The line drawing algorithm only accept pixel center integer points as input.&#xD;&#xA; - So the two vertices will using int(x + 0.5) and will be (0, 0) and (499 , 0). This conforms to first result but contradict to the result when input order changed. Why?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3558" PostHistoryTypeId="1" PostId="1776" RevisionGUID="a4316ef4-70a4-43f5-9f86-f3038c821bf1" CreationDate="2015-12-04T08:30:44.973" UserId="2190" Text="Why different result when change input order in GL_LINES?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3559" PostHistoryTypeId="3" PostId="1776" RevisionGUID="a4316ef4-70a4-43f5-9f86-f3038c821bf1" CreationDate="2015-12-04T08:30:44.973" UserId="2190" Text="|opengl|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3561" PostHistoryTypeId="2" PostId="1777" RevisionGUID="681b02cd-81c6-4216-a074-e8619f3ca482" CreationDate="2015-12-04T11:19:36.937" UserId="273" Text="The syntax for your dot- and cross-product are a bit strange.&#xD;&#xA;The methods are members of a vector, but still take two arguments. Are they static methods? Or are you really sure they do what you would expect?&#xD;&#xA;&#xD;&#xA;Otherwise the only real difference in your implementation and the one you linked that I can see is your test against the parameter t.&#xD;&#xA;&#xD;&#xA;The implementation you linked tests for&#xD;&#xA;&#xD;&#xA;    if(t &gt; EPSILON)&#xD;&#xA;&#xD;&#xA;your code tests for&#xD;&#xA;&#xD;&#xA;    if(t &lt; abs(hitFaces.s))&#xD;&#xA;&#xD;&#xA;I don't see in your code how you set the value for hitFaces.s since you fire this ray against a model and don't know jet if it has hit anything.&#xD;&#xA;My understanding would be, that you first test if t is large enough to signal a hit ( &gt; EPSILON ) and then in a second step sort for the smallest t (closest to the ray origin).&#xD;&#xA;&#xD;&#xA;In my head you can't get a value for hitFaces.s without calculating this intersection test as you wrote it, and the intersection test needs the hitFaces.s to determine if an intersection was made. But I could be in the wrong here." ContentLicense="CC BY-SA 3.0" />
  <row Id="3562" PostHistoryTypeId="2" PostId="1778" RevisionGUID="a098e214-97bd-4d07-b7a8-1c605ddc6d60" CreationDate="2015-12-04T14:12:45.167" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3563" PostHistoryTypeId="2" PostId="1779" RevisionGUID="b683a904-bb34-4901-8eb1-640689a0aa6c" CreationDate="2015-12-04T14:12:45.167" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="3564" PostHistoryTypeId="5" PostId="1779" RevisionGUID="7c18550a-3ca7-4323-be2a-55e04365ade3" CreationDate="2015-12-04T15:40:12.640" UserId="1908" Comment="added 132 characters in body" Text="WebGL extends the capability of the HTML canvas element to allow it to render accelerated 3D graphics in any compatible web browser." ContentLicense="CC BY-SA 3.0" />
  <row Id="3565" PostHistoryTypeId="24" PostId="1779" RevisionGUID="7c18550a-3ca7-4323-be2a-55e04365ade3" CreationDate="2015-12-04T15:40:12.640" Comment="Proposed by 1908 approved by 127 edit id of 113" ContentLicense="CC BY-SA 3.0" />
  <row Id="3566" PostHistoryTypeId="5" PostId="1778" RevisionGUID="5c7bc5cb-b037-486a-a4d4-9497a385d08c" CreationDate="2015-12-04T21:37:54.457" UserId="1908" Comment="added 1919 characters in body" Text="WebGL is [OpenGL][1] 3D graphics for web pages. It extends the capability of the [HTML canvas element][2] to allow it to render accelerated 3D graphics in any compatible web browser. &#xD;&#xA;&#xD;&#xA;WebGL is based on [OpenGL ES][3] and is driven via a JavaScript API. It does not require the use of plug-ins. Official specifications and additional information can be found at [Khronos][4].&#xD;&#xA;&#xD;&#xA;**Engines:**&#xD;&#xA;&#xD;&#xA;There are also many different webGL based 3D engines available:&#xD;&#xA;&#xD;&#xA; - [Three.js][5] - the most popular and the most used&#xD;&#xA; - [Goo Engine][9]&#xD;&#xA; - [SceneJS][8]&#xD;&#xA; - [BabylonJS][7]&#xD;&#xA; - [GLGE][14]&#xD;&#xA; - [PhiloGL][17]&#xD;&#xA; - [CopperLicht][6]&#xD;&#xA; - [KickJS][10]&#xD;&#xA; - [A3][11]&#xD;&#xA; - [CubicVR][12]&#xD;&#xA; - [C3DL][13]&#xD;&#xA; - [Kuda][15]&#xD;&#xA; - [O3D][16]&#xD;&#xA; - [SpiderGL][18]&#xD;&#xA;&#xD;&#xA;  [1]: http://en.wikipedia.org/wiki/OpenGL&#xD;&#xA;  [2]: http://en.wikipedia.org/wiki/Canvas_element&#xD;&#xA;  [3]: http://en.wikipedia.org/wiki/OpenGL_ES&#xD;&#xA;  [4]: http://www.khronos.org/webgl/&#xD;&#xA;  [5]: http://threejs.org/&#xD;&#xA;  [6]: http://www.ambiera.com/copperlicht/&#xD;&#xA;  [7]: http://www.babylonjs.com/&#xD;&#xA;  [8]: http://scenejs.org/&#xD;&#xA;  [9]: http://www.gooengine.com/&#xD;&#xA;  [10]: http://www.kickjs.org/&#xD;&#xA;  [11]: http://www.aerotwist.com/a3/&#xD;&#xA;  [12]: http://www.cubicvr.org/cubicvr-js/webgl-cubicvr&#xD;&#xA;  [13]: http://www.c3dl.org/&#xD;&#xA;  [14]: http://www.glge.org/&#xD;&#xA;  [15]: https://code.google.com/p/kuda/&#xD;&#xA;  [16]: https://code.google.com/p/o3d/&#xD;&#xA;  [17]: http://www.sencha.com/blog/introducing-philogl-a-webgl-javascript-library-from-sencha-labs/&#xD;&#xA;  [18]: http://www.spidergl.org/&#xD;&#xA;  [19]: http://learningwebgl.com/&#xD;&#xA;  [20]: http://learningthreejs.com/&#xD;&#xA;&#xD;&#xA;**Getting started with webGL:**&#xD;&#xA;&#xD;&#xA;The head-first place for all new webGL developers - [LearningWebGL][19]. LearningWebGL has basic tutorials required to understand the API and pipeline, and is also a blog site that publishes newest information about webGL every week.&#xD;&#xA;&#xD;&#xA;Website with plenty of Three.js tutorials and examples - [LearningThreeJS][20]." ContentLicense="CC BY-SA 3.0" />
  <row Id="3567" PostHistoryTypeId="24" PostId="1778" RevisionGUID="5c7bc5cb-b037-486a-a4d4-9497a385d08c" CreationDate="2015-12-04T21:37:54.457" Comment="Proposed by 1908 approved by 127 edit id of 112" ContentLicense="CC BY-SA 3.0" />
  <row Id="3568" PostHistoryTypeId="5" PostId="1743" RevisionGUID="4409a81e-5810-44a1-b118-2b3f92da69de" CreationDate="2015-12-04T21:46:16.450" UserId="127" Comment="Removed salutation, edited formatting" Text="I've been trying to implement the [Moller-Trumbore ray-triangle intersection algorithm](https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm) in my raytracing code. The code is supposed to read in a mesh and light sources, fire off rays from the light source, and return the triangle from the mesh which each ray intersects. Here is my implementation of the algorithm:&#xD;&#xA;&#xD;&#xA;    //Moller-Trumbore intersection algorithm&#xD;&#xA;    void getFaceIntersect(modelStruct m, ray r, hitFaceStruct&amp; hitFaces)&#xD;&#xA;    {&#xD;&#xA;	    // Constant thoughout loop&#xD;&#xA;    	point origin = r.p0;&#xD;&#xA;	    point direction = r.u;&#xD;&#xA;    	hitFaces.isHit = false;&#xD;&#xA;&#xD;&#xA;	    for (int i = 0; i &lt; m.faces; i++)&#xD;&#xA;    	{&#xD;&#xA;	    	// Get face vertices&#xD;&#xA;	    	point v1 = m.vertList[m.faceList[i].v1];&#xD;&#xA;	    	point v2 = m.vertList[m.faceList[i].v2];&#xD;&#xA;	    	point v3 = m.vertList[m.faceList[i].v3];&#xD;&#xA;		&#xD;&#xA;			// Get two edgess&#xD;&#xA;			point edge1 = v2 - v1;&#xD;&#xA;			point edge2 = v3 - v1;&#xD;&#xA;		&#xD;&#xA;			// Get p&#xD;&#xA;			point p = direction.cross(direction, edge2);&#xD;&#xA;			// Use p to find determinant&#xD;&#xA;			double det = p.dot(edge1, p);&#xD;&#xA;		&#xD;&#xA;			// If the determinant is about 0, the ray lies in the plane of the triangle&#xD;&#xA;			if (abs(det) &lt; 0.00000000001)&#xD;&#xA;			{&#xD;&#xA;				continue;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			double inverseDet = 1 / det;&#xD;&#xA;&#xD;&#xA;			point v1ToOrigin = (origin - v1);&#xD;&#xA;&#xD;&#xA;			double u = v1ToOrigin.dot(v1ToOrigin, p) * inverseDet;&#xD;&#xA;&#xD;&#xA;			// If u is not between 0 and 1, no hit&#xD;&#xA;			if (u &lt; 0 || u &gt; 1)&#xD;&#xA;   	        {&#xD;&#xA;				continue;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			// Used for calculating v&#xD;&#xA;			point q = v1ToOrigin.cross(v1ToOrigin, edge1);&#xD;&#xA;			double v = direction.dot(direction, q) * inverseDet;&#xD;&#xA;&#xD;&#xA;			if (v &lt; 0 || (u + v) &gt; 1)&#xD;&#xA;			{&#xD;&#xA;				continue;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			double t = q.dot(edge2, q) * inverseDet;&#xD;&#xA;&#xD;&#xA;			// gets closest face&#xD;&#xA;			if (t &lt; abs(hitFaces.s)) &#xD;&#xA;			{&#xD;&#xA;				hitFaceStruct goodStruct = hitFaceStruct();&#xD;&#xA;				goodStruct.face = i;&#xD;&#xA;				goodStruct.hitPoint = p;&#xD;&#xA;				goodStruct.isHit = true;&#xD;&#xA;				goodStruct.s = t;&#xD;&#xA;				hitFaces = goodStruct;&#xD;&#xA;				break;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The relevant code for hitFaceStruct and modelStruct is as follows:       &#xD;&#xA;&#xD;&#xA;    typedef struct _hitFaceStruct&#xD;&#xA;    {&#xD;&#xA;	    int face; //the index of the sphere in question in the list of faces&#xD;&#xA;	    float s; //the distance from the ray that hit it&#xD;&#xA;		bool isHit;&#xD;&#xA;		point hitPoint;&#xD;&#xA;    } hitFaceStruct;&#xD;&#xA;&#xD;&#xA;    typedef struct _modelStruct {&#xD;&#xA;		char *fileName;&#xD;&#xA;		float scale;&#xD;&#xA;		float rot_x, rot_y, rot_z;&#xD;&#xA;		float x, y, z;&#xD;&#xA;		float r_amb, g_amb, b_amb;&#xD;&#xA;		float r_dif, g_dif, b_dif;&#xD;&#xA;		float r_spec, g_spec, b_spec;&#xD;&#xA;		float k_amb, k_dif, k_spec, k_reflective, k_refractive;&#xD;&#xA;		float spec_exp, index_refraction;&#xD;&#xA;		int verts, faces, norms = 0;    // Number of vertices, faces, normals, and spheres in the system&#xD;&#xA;		point *vertList, *normList; // Vertex and Normal Lists&#xD;&#xA;		faceStruct *faceList;	    // Face List&#xD;&#xA;    } modelStruct;&#xD;&#xA;&#xD;&#xA;Whenever I shoot a ray, the values of `u` or `v` in the algorithm code always come out to a large negative number, rather than the expected small, positive one. The direction vector of the ray is normalized before I pass it on to the intersection code, and I'm positive I'm firing rays that would normally hit the mesh. Can anyone please help me spot my error here?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3572" PostHistoryTypeId="2" PostId="1781" RevisionGUID="7d774bdd-2eca-4d12-9553-2483eb424441" CreationDate="2015-12-05T15:20:54.810" UserDisplayName="user1703" Text="I assume that your texture is deemed to belong to the plane of the trajectory.&#xD;&#xA;&#xD;&#xA;Looking at the unprojected ellipse, you can map the circle to it by an anisotropic scaling. If necessary, rotate the texture first if there is any orientation requirement.&#xD;&#xA;&#xD;&#xA;To achieve this first mapping, you will compute the four corners of a rectangle, presumably related to the frame formed by the ellipse axis.&#xD;&#xA;&#xD;&#xA;Then transform those vertices to the global scene coordinates, the same way to transform the ellipse." ContentLicense="CC BY-SA 3.0" />
  <row Id="3574" PostHistoryTypeId="2" PostId="1782" RevisionGUID="97cad8e5-c424-4fbe-b3e4-0bac6104b317" CreationDate="2015-12-05T22:17:50.043" UserId="48" Text="The difference in which pixels are covered depending on the vertex order is related to [rasterization rules](https://msdn.microsoft.com/en-us/library/windows/desktop/cc627092.aspx). They're the rules that the GPU hardware uses to determine exactly which pixels are covered by a primitive.&#xD;&#xA;&#xD;&#xA;Rasterization rules are a bit subtle. One of their goals is to ensure that whenever you draw multiple primitives that are connected water-tightly, the rasterization never produces any cracks between them, nor are any pixels covered twice (that's important for blending). To achieve that, the rules have some very specific edge and corner cases. Literally...they're cases having to do with primitive edges and corners. :)&#xD;&#xA;&#xD;&#xA;In the case of lines, it works as follows. There's a diamond-shaped region around each pixel center, as shown in this snippet of the diagram from the MSDN article linked above.&#xD;&#xA;&#xD;&#xA;![diamond rule for line rasterization][1]&#xD;&#xA;&#xD;&#xA;The rule is that a pixel is covered if the line *exits* the diamond, when tracing from the start to the end of the line. Note that a pixel doesn't get covered if the line enters, but doesn't exit, the diamond. This ensures that if you have two line segments connected end to end, that the pixel at their shared endpoint only belongs to one of the segments and thus doesn't get rasterized twice.&#xD;&#xA;&#xD;&#xA;You can also see in the above diagram how changing the order of the vertices can affect which pixels are covered (which doesn't happen with triangles, BTW). The diagram shows two line segments that are identical except for swapping the endpoint order, and you can see it makes a difference which pixel gets covered. &#xD;&#xA;&#xD;&#xA;Your line segment is somewhat analogous to this. The left end, at (0.5, 0.999) is inside the diamond of the (0, 0) pixel, so it gets covered when it's the first vertex (the line starts inside the diamond, then exits it) and not when it's the second vertex (the line enters the diamond, and ends inside it, so it never exits).&#xD;&#xA;&#xD;&#xA;On the other hand, the right end of your line, at (499.501, 0.999) is outside of the diamond of the (499, 0) pixel, so it always gets covered, as the line segment enters and then exits the diamond in either direction. &lt;sub&gt;(Actually, this point is exactly on the top-right edge of the diamond, which is defined as not being included in the diamond by the rasterization rules. [*Actually* actually, the vertices are snapped to fixed-point with 8 subpixel bits before rasterization, so they end up rounded to (499.5, 1.0), which is exactly on the top corner of the diamond, which is *still* not included by the rasterization rules.])&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GJ5Zw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3575" PostHistoryTypeId="5" PostId="1782" RevisionGUID="e5cb4388-47b4-4edf-a857-d8e5d91b426f" CreationDate="2015-12-05T22:57:33.030" UserId="48" Comment="correction about GL rasterization rules not being entirely specified" Text="The difference in which pixels are covered depending on the vertex order is related to [rasterization rules](https://msdn.microsoft.com/en-us/library/windows/desktop/cc627092.aspx). They're the rules that the GPU hardware uses to determine exactly which pixels are covered by a primitive.&#xD;&#xA;&#xD;&#xA;Rasterization rules are a bit subtle. One of their goals is to ensure that whenever you draw multiple primitives that are connected water-tightly, the rasterization never produces any cracks between them, nor are any pixels covered twice (that's important for blending). To achieve that, the rules have some very specific edge and corner cases. Literally...they're cases having to do with primitive edges and corners. :)&#xD;&#xA;&#xD;&#xA;In the case of lines, it works as follows. There's a diamond-shaped region around each pixel center, as shown in this snippet of the diagram from the MSDN article linked above.&#xD;&#xA;&#xD;&#xA;![diamond rule for line rasterization][1]&#xD;&#xA;&#xD;&#xA;The rule is that a pixel is covered if the line *exits* the diamond, when tracing from the start to the end of the line. Note that a pixel doesn't get covered if the line enters, but doesn't exit, the diamond. This ensures that if you have two line segments connected end to end, that the pixel at their shared endpoint only belongs to one of the segments and thus doesn't get rasterized twice.&#xD;&#xA;&#xD;&#xA;You can also see in the above diagram how changing the order of the vertices can affect which pixels are covered (which doesn't happen with triangles, BTW). The diagram shows two line segments that are identical except for swapping the endpoint order, and you can see it makes a difference which pixel gets covered. &#xD;&#xA;&#xD;&#xA;Your line segment is somewhat analogous to this. The left end, at (0.5, 0.999) is inside the diamond of the (0, 0) pixel, so it gets covered when it's the first vertex (the line starts inside the diamond, then exits it) and not when it's the second vertex (the line enters the diamond, and ends inside it, so it never exits). &lt;sub&gt;Actually, the vertices are snapped to fixed-point with 8 subpixel bits before rasterization, so this one ends up rounded to (0.5, 1.0), which is exactly on the top corner of the diamond. Depending on the rasterization rules, this might or might not be considered inside the diamond; it seems as if on your GPU it's considered inside, but this can vary between implementations, as the GL spec doesn't nail down the rules entirely.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GJ5Zw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3581" PostHistoryTypeId="5" PostId="1775" RevisionGUID="82bfb2df-35c4-42d8-8c74-59e3c7fc5bbd" CreationDate="2015-12-07T11:38:35.267" UserId="231" Comment="Minor tidying" Text="I am trying to draw an angled line in a raster grid.&#xD;&#xA;&#xD;&#xA;The idea is to create a function that given a start point, a length and an angle, would give me the pixel positions that combined would give me a line at the specified angle, in a raster grid.&#xD;&#xA;&#xD;&#xA;I tried to implement this in C++ but I seem to get some weird points... &#xD;&#xA;&#xD;&#xA;The way I do it, is I compute the equation of the line, and thereby also the endpoint, and then use Bresenham's line algorithm to find the pixel positions that create the line between the start point and the end point.&#xD;&#xA;  &#xD;&#xA;Some of the points though, don't seem right. Some of the traversing points make no sense, or go to infinity. What is wrong with my implementation? &#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    using namespace std;&#xD;&#xA;    &#xD;&#xA;    int sign(double x ){ return (x &gt; 0) ? 1 : ((x &lt; 0) ? -1 : 0); }&#xD;&#xA;    &#xD;&#xA;    std::pair&lt;int,int&gt; endpoint(double angle, int x1 , int y1, int lenght)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        if(angle == 90)&#xD;&#xA;        {&#xD;&#xA;            double y2 = y1+lenght;&#xD;&#xA;            return std::make_pair(x1, -y2);&#xD;&#xA;        }&#xD;&#xA;        if(angle == 180)&#xD;&#xA;        {&#xD;&#xA;            double x2 = x1+lenght;&#xD;&#xA;            return std::make_pair(-x2, y1);&#xD;&#xA;        }&#xD;&#xA;        if(angle == 270)&#xD;&#xA;        {&#xD;&#xA;            double y2 = y1+lenght;&#xD;&#xA;            return std::make_pair(x1, y2);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        double x2 = x1 + (lenght * cos(angle));&#xD;&#xA;        double y2 = y1 + (lenght * sin(angle));&#xD;&#xA;        return std::make_pair(x2,y2);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void bresenham(int x0, int y0, int x1, int y1)&#xD;&#xA;    {&#xD;&#xA;        int dx = x1-x0;&#xD;&#xA;        int dy = y1 - y0;&#xD;&#xA;        if (abs(dx) &gt; abs(dy))&#xD;&#xA;        {&#xD;&#xA;            // x-axis&#xD;&#xA;            int j = y0;&#xD;&#xA;            double e = dy - dx;&#xD;&#xA;            &#xD;&#xA;            for (int i = x0; i&lt;x1; i++)&#xD;&#xA;            {&#xD;&#xA;                std::cout &lt;&lt; &quot;marked: &quot; &lt;&lt; i &lt;&lt; &quot;,&quot;&lt;&lt; j &lt;&lt; std::endl;&#xD;&#xA;                if( e &gt;= 0)&#xD;&#xA;                {&#xD;&#xA;                    j += 1;&#xD;&#xA;                    e -= dx;&#xD;&#xA;                }&#xD;&#xA;                e += dy;&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        else if(abs(dx)&lt;abs(dy))&#xD;&#xA;        {&#xD;&#xA;            // y-axis&#xD;&#xA;    &#xD;&#xA;            int j = x0;&#xD;&#xA;            double e = dx - dy;&#xD;&#xA;            &#xD;&#xA;            for (int i = y0; i&lt;y1; i++)&#xD;&#xA;            {&#xD;&#xA;                std::cout &lt;&lt; &quot;marked: &quot; &lt;&lt; j&lt;&lt; &quot;,&quot;&lt;&lt; i &lt;&lt; std::endl;&#xD;&#xA;                if( e &gt;= 0)&#xD;&#xA;                {&#xD;&#xA;                    j += 1;&#xD;&#xA;                    e -= dy;&#xD;&#xA;                }&#xD;&#xA;                e += dx;&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void line(int x0, int y0, int x1, int y1)&#xD;&#xA;    {&#xD;&#xA;        &#xD;&#xA;        if(x1 &lt; x0)&#xD;&#xA;        {&#xD;&#xA;            swap(x1, x0);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        if(y1 &lt; y0)&#xD;&#xA;        {&#xD;&#xA;            swap(y1, y0);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        int dx = x1-x0;&#xD;&#xA;        int dy = y1-y0;&#xD;&#xA;        double e = 0;&#xD;&#xA;        if(dx == 0)&#xD;&#xA;        {&#xD;&#xA;            if (sign(dy) == -1)&#xD;&#xA;            {&#xD;&#xA;                cout &lt;&lt; &quot;new&quot; &lt;&lt; endl;&#xD;&#xA;                for (int y = y0; y != y1; y--)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x1 &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                for (int y = y0; y != y1; y++)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x1 &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        else if(dy == 0)&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;            if (sign(dx) == -1)&#xD;&#xA;            {&#xD;&#xA;                cout &lt;&lt; &quot;new&quot; &lt;&lt; endl;&#xD;&#xA;                &#xD;&#xA;                for (int x = x0; x != x1; x--)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y1 &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                for (int y = y0; y != y1; y++)&#xD;&#xA;                {&#xD;&#xA;                    cout &lt;&lt; &quot;mark&quot; &lt;&lt; x1 &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        cout &lt;&lt; &quot;bressenham: &quot; &lt;&lt; endl;&#xD;&#xA;        double de = abs(dy/dx);&#xD;&#xA;        int y = y0;&#xD;&#xA;        for (int x = x0; x != x1; x++)&#xD;&#xA;        {&#xD;&#xA;            cout &lt;&lt; &quot;mark: &quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;            e = e + de;&#xD;&#xA;            while (e &gt;= 0.5)&#xD;&#xA;            {&#xD;&#xA;                cout &lt;&lt; &quot;mark: &quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;                y = y + sign(y1-y0);&#xD;&#xA;                e = e -1;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main(int argc, const char * argv[])&#xD;&#xA;    {&#xD;&#xA;        for (int angle = 0; angle &lt; 180; angle++)&#xD;&#xA;        {&#xD;&#xA;            cout &lt;&lt; &quot;angle: &quot; &lt;&lt; angle &lt;&lt; endl;&#xD;&#xA;            pair&lt;int, int&gt; end = endpoint(angle, 3, 3, 20);&#xD;&#xA;            cout &lt;&lt; end.first &lt;&lt; end.second &lt;&lt; endl;&#xD;&#xA;            line(3, 3, end.first, end.second);&#xD;&#xA;            cout &lt;&lt; end.first &lt;&lt; end.second &lt;&lt; endl;&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="3582" PostHistoryTypeId="4" PostId="1775" RevisionGUID="82bfb2df-35c4-42d8-8c74-59e3c7fc5bbd" CreationDate="2015-12-07T11:38:35.267" UserId="231" Comment="Minor tidying" Text="Draw lines angled from 0 to 2 pi in a raster grid" ContentLicense="CC BY-SA 3.0" />
  <row Id="3583" PostHistoryTypeId="2" PostId="1784" RevisionGUID="60f80f19-2457-47e8-99d7-4a9e923dacc3" CreationDate="2015-12-07T12:04:58.077" UserId="2219" Text="in my SharpGL application I do a very simple, mouse controlled rotation of the scene.&#xD;&#xA;&#xD;&#xA;    gl.Rotate(cameraRotation.X, cameraRotation.Y, 0.0f);&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;    cameraRotation.Y += MousePosition.X - previousMousePositionX;&#xD;&#xA;    cameraRotation.X += MousePosition.Y - previousMousePositionY;&#xD;&#xA;&#xD;&#xA;The problem with this is that the x rotation always comes first, so if I rotate the object around the x axis by 180° and then move my mouse left, the object will rotate to the right instead of left (since the y axis is now inversed). Is there a way to change this so that the object always rotates into the mouse movement direction, regardless of its current position? (like netfabb does it for example)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3584" PostHistoryTypeId="1" PostId="1784" RevisionGUID="60f80f19-2457-47e8-99d7-4a9e923dacc3" CreationDate="2015-12-07T12:04:58.077" UserId="2219" Text="SharpGL - Always rotate in the direction of mouse movement" ContentLicense="CC BY-SA 3.0" />
  <row Id="3585" PostHistoryTypeId="3" PostId="1784" RevisionGUID="60f80f19-2457-47e8-99d7-4a9e923dacc3" CreationDate="2015-12-07T12:04:58.077" UserId="2219" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3587" PostHistoryTypeId="2" PostId="1785" RevisionGUID="b3cef6b7-5090-49a7-b3fd-65ee6e417cf1" CreationDate="2015-12-08T13:03:25.073" UserId="2226" Text="I at the moment trying to draw some angled lines using bresenham line algorithm which can circulate a 2d array of size 21x21, as a line angled from 0 - 2pi. &#xD;&#xA;&#xD;&#xA;[![Angled line][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c3X52.png&#xD;&#xA;&#xD;&#xA;So the idea is that the program has to output the values which the lines pass through in the grid.. &#xD;&#xA;&#xD;&#xA;So an example with 5x5&#xD;&#xA;&#xD;&#xA;    Angle:0&#xD;&#xA;         _ _ _ _ _ &#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|.|.|.|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;   &#xD;&#xA;    Angle: 45&#xD;&#xA;         _ _ _ _ _ &#xD;&#xA;        |_|_|_|_|.|&#xD;&#xA;        |_|_|_|.|_|&#xD;&#xA;        |_|_|.|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;   and so on..&#xD;&#xA;&#xD;&#xA;The problem here is that it doesn't look like that my program does that.. The endpoint lies within the given radius length.. &#xD;&#xA;&#xD;&#xA;I am sure am might that I might be messing up with the math.. So i hope some of you could help me here.. &#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    using namespace std;&#xD;&#xA;    typedef std::pair&lt;int,int&gt; coordinate;&#xD;&#xA;    &#xD;&#xA;    int sign(double x ){ return (x &gt; 0) ? 1 : ((x &lt; 0) ? -1 : 0); }&#xD;&#xA;    &#xD;&#xA;    coordinate endpoint(double angle, int x1 , int y1, int lenght)&#xD;&#xA;    {&#xD;&#xA;        double radians = (M_PI/180)*angle;&#xD;&#xA;        &#xD;&#xA;        double x2 = x1 + (lenght * cos(radians));&#xD;&#xA;        double y2 = y1 + (lenght * sin(radians));&#xD;&#xA;        &#xD;&#xA;        return std::make_pair(round(x2),round(y2));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void bresenham(coordinate start, coordinate end)&#xD;&#xA;    {&#xD;&#xA;        //restriction a.x &lt; b.x  and 0 &lt; H/W &lt; 1&#xD;&#xA;        int y =  start.second;&#xD;&#xA;        int w = end.first - start.first;&#xD;&#xA;        int h = end.second - start.second;&#xD;&#xA;        int f = 2*h-w; // current error term&#xD;&#xA;        &#xD;&#xA;        for (int x = start.first; x&lt;= end.first; x++)&#xD;&#xA;        {&#xD;&#xA;            cout &lt;&lt; &quot;mark: &quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;            if (f &lt; 0)&#xD;&#xA;            {&#xD;&#xA;                f = f + 2*h;&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                y++;&#xD;&#xA;                f=f+2*(h-w);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int main(int argc, const char * argv[])&#xD;&#xA;    {&#xD;&#xA;       &#xD;&#xA;        coordinate start = make_pair(0,0);&#xD;&#xA;        for (int i = 0; i &lt;= 45; i++)&#xD;&#xA;        {&#xD;&#xA;            coordinate end = endpoint(i,0,0,10);&#xD;&#xA;            cout &lt;&lt; &quot;    endPos: &quot;&lt;&lt; &quot;(&quot; &lt;&lt; end.first &lt;&lt;&quot;,&quot;  &lt;&lt; end.second   &lt;&lt;&quot;)&quot;    &lt;&lt; &quot; Angle: &quot; &lt;&lt; i &lt;&lt; &quot;       &quot; &lt;&lt; endl;&#xD;&#xA;            cout &lt;&lt; &quot;--------------------------------------------&quot; &lt;&lt; endl;&#xD;&#xA;            bresenham(start, end);&#xD;&#xA;            cout &lt;&lt; &quot;--------------------------------------------&quot; &lt;&lt; endl;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the output. &#xD;&#xA;&#xD;&#xA;        endPos: (10,0) Angle: 0       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,0&#xD;&#xA;    mark: 6,0&#xD;&#xA;    mark: 7,0&#xD;&#xA;    mark: 8,0&#xD;&#xA;    mark: 9,0&#xD;&#xA;    mark: 10,0&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,0) Angle: 1       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,0&#xD;&#xA;    mark: 6,0&#xD;&#xA;    mark: 7,0&#xD;&#xA;    mark: 8,0&#xD;&#xA;    mark: 9,0&#xD;&#xA;    mark: 10,0&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,0) Angle: 2       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,0&#xD;&#xA;    mark: 6,0&#xD;&#xA;    mark: 7,0&#xD;&#xA;    mark: 8,0&#xD;&#xA;    mark: 9,0&#xD;&#xA;    mark: 10,0&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 3       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 4       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 5       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 6       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 7       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 8       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 9       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 10       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 11       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 12       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 13       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 14       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 15       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 16       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 17       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 18       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,3) Angle: 19       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,3&#xD;&#xA;    mark: 9,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,3) Angle: 20       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,3&#xD;&#xA;    mark: 9,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 21       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 22       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 23       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 24       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 25       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 26       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 27       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 28       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 29       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 30       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 31       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,5) Angle: 32       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,4&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,5) Angle: 33       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,4&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 34       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 35       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 36       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 37       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 38       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 39       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 40       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,7) Angle: 41       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,6&#xD;&#xA;    mark: 8,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 42       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 43       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 44       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 45       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;&#xD;&#xA;What am i doing wrong?... I know that the bresenham algorithm might have to be modified to overcome slopes greater 1 and lower that 0. " ContentLicense="CC BY-SA 3.0" />
  <row Id="3588" PostHistoryTypeId="1" PostId="1785" RevisionGUID="b3cef6b7-5090-49a7-b3fd-65ee6e417cf1" CreationDate="2015-12-08T13:03:25.073" UserId="2226" Text="Draw angles lines in raster graphics using bresenham line algorithm." ContentLicense="CC BY-SA 3.0" />
  <row Id="3589" PostHistoryTypeId="3" PostId="1785" RevisionGUID="b3cef6b7-5090-49a7-b3fd-65ee6e417cf1" CreationDate="2015-12-08T13:03:25.073" UserId="2226" Text="|c++|line-drawing|mathematics|raster-image|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3590" PostHistoryTypeId="2" PostId="1786" RevisionGUID="1d97743e-f9d2-476a-98c0-368e17aec34f" CreationDate="2015-12-08T14:23:11.243" UserId="2111" Text="Whew, that was a long title.&#xD;&#xA;&#xD;&#xA;Either way, I'm asking this question, since I like to think about various things, and it occurred to me that there isn't really any simple, open source layers on top of GLSL, even if only to add simple things such as includes, or commonly used functions.&#xD;&#xA;&#xD;&#xA;As research of sorts, I'm asking this question, since my own awareness of such languages is minuscule to say the least - I know of bgfx's shading language, and Unity's ShaderLab, but I don't really know what they accomplish - or why - being a relative newbie to computer graphics.&#xD;&#xA;&#xD;&#xA;Alternatively, what would your wishlist for a shading language like this be? Mine so far is includes, some compatibility between versions, optional &quot;hidden&quot; inputs that allow easily accessing textures at pixel offsets, or image sizes, etc. and probably passes - for, say, two-pass gaussian blur.&#xD;&#xA;&#xD;&#xA;Thoughts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3591" PostHistoryTypeId="1" PostId="1786" RevisionGUID="1d97743e-f9d2-476a-98c0-368e17aec34f" CreationDate="2015-12-08T14:23:11.243" UserId="2111" Text="There are many shading languages built on top of GLSL or HLSL - what problems do they typically solve, and what worthwhile advancements do they make?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3592" PostHistoryTypeId="3" PostId="1786" RevisionGUID="1d97743e-f9d2-476a-98c0-368e17aec34f" CreationDate="2015-12-08T14:23:11.243" UserId="2111" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3598" PostHistoryTypeId="2" PostId="1788" RevisionGUID="7652359a-76b0-4ad9-9a87-663e2d0e92fe" CreationDate="2015-12-08T18:48:35.203" UserId="2228" Text="First of all, I want to say that I've read a lot of post about shadow mapping using depth maps and cubemaps and I understand how they work and also, I have working experience with them using OpenGL, but, I have an issue implementing Omnidirectional Shadow Mapping technique using a single point light source in my 3D graphics engine named &quot;EZ3&quot;. My engine uses WebGL as a 3D graphics API and JavaScript as programming language, this is for my bachelor's thesis in Computer Science. &#xD;&#xA;&#xD;&#xA;Basically this is how I've implemented my shadow mapping algorithm, but I'll only focus on point lights case because with them I can archive omnidirectional shadow mapping.&#xD;&#xA;&#xD;&#xA;First, I active front-face culling like this:&#xD;&#xA;&#xD;&#xA;    if (this.state.faceCulling !== EZ3.Material.FRONT) {&#xD;&#xA;        if (this.state.faceCulling === EZ3.Material.NONE)&#xD;&#xA;          gl.enable(gl.CULL_FACE);&#xD;&#xA;    &#xD;&#xA;        gl.cullFace(gl.FRONT);&#xD;&#xA;        this.state.faceCulling = EZ3.Material.FRONT;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;Second, I create a depth program in order to record depth values for each cubemap face, this is my depth program code in GLSL 1.0:&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    vec4 packDepth(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);&#xD;&#xA;      vec4 res = mod(depth * bitShift * vec4(255), vec4(256)) / vec4(255);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_FragData[0] = packDepth(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Third, this is my JavaScript function's body that &quot;archives&quot; omnidirectional shadow mapping&#xD;&#xA;&#xD;&#xA;    program.bind(gl);&#xD;&#xA;    &#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Updates pointlight's projection matrix&#xD;&#xA;        &#xD;&#xA;        light.updateProjection();&#xD;&#xA;&#xD;&#xA;        // Binds point light's depth framebuffer&#xD;&#xA;    &#xD;&#xA;        light.depthFramebuffer.bind(gl);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution changes, it'll be created again.&#xD;&#xA;    &#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Sets viewport dimensions with depth framebuffer's dimensions&#xD;&#xA;        &#xD;&#xA;        this.viewport(new EZ3.Vector2(), light.depthFramebuffer.size);&#xD;&#xA;    &#xD;&#xA;        if (light instanceof EZ3.PointLight) {&#xD;&#xA;    &#xD;&#xA;          up = new EZ3.Vector3();&#xD;&#xA;          view = new EZ3.Matrix4();&#xD;&#xA;          origin = new EZ3.Vector3();&#xD;&#xA;          target = new EZ3.Vector3();&#xD;&#xA;    &#xD;&#xA;          for (j = 0; j &lt; 6; j++) {&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;    &#xD;&#xA;            switch (j) {&#xD;&#xA;              case EZ3.Cubemap.POSITIVE_X:&#xD;&#xA;                target.set(1, 0, 0);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;              case EZ3.Cubemap.NEGATIVE_X:&#xD;&#xA;                target.set(-1, 0, 0);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;              case EZ3.Cubemap.POSITIVE_Y:&#xD;&#xA;                target.set(0, 1, 0);&#xD;&#xA;                up.set(0, 0, 1);&#xD;&#xA;                break;&#xD;&#xA;              case EZ3.Cubemap.NEGATIVE_Y:&#xD;&#xA;                target.set(0, -1, 0);&#xD;&#xA;                up.set(0, 0, -1);&#xD;&#xA;                break;&#xD;&#xA;              case EZ3.Cubemap.POSITIVE_Z:&#xD;&#xA;                target.set(0, 0, 1);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;              case EZ3.Cubemap.NEGATIVE_Z:&#xD;&#xA;                target.set(0, 0, -1);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;        // Creates a view matrix using target and up vectors according to each face of pointlight's&#xD;&#xA;        // cubemap. Furthermore, I translate it in minus light position in order to place&#xD;&#xA;        // the point light in the world's origin and render each cubemap's face at this &#xD;&#xA;        // point of view&#xD;&#xA;&#xD;&#xA;            view.lookAt(origin, target, up);&#xD;&#xA;            view.mul(new EZ3.Matrix4().translate(light.position.clone().negate()));&#xD;&#xA;&#xD;&#xA;        // Flips the Y-coordinate of each cubemap face&#xD;&#xA;        // scaling the projection matrix by (1, -1, 1).&#xD;&#xA;&#xD;&#xA;        // This is a perspective projection matrix which has:&#xD;&#xA;        // 90 degress of FOV.&#xD;&#xA;        // 1.0 of aspect ratio.&#xD;&#xA;        // Near clipping plane at 0.01.&#xD;&#xA;        // Far clipping plane at 2000.0.&#xD;&#xA;&#xD;&#xA;            projection = light.projection.clone();&#xD;&#xA;            projection.scale(new EZ3.Vector3(1, -1, 1));&#xD;&#xA;&#xD;&#xA;        // Attaches a cubemap face to current framebuffer in order to record depth values for the face with this line&#xD;&#xA;        // gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + j, id, 0);&#xD;&#xA;    &#xD;&#xA;            light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;        // Clears current framebuffer's color with these lines:&#xD;&#xA;        // gl.clearColor(1.0,1.0,1.0,1.0);&#xD;&#xA;        // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;            this.clear(color);&#xD;&#xA;&#xD;&#xA;        // Renders shadow caster meshes using the depth program&#xD;&#xA;    &#xD;&#xA;            for (k = 0; k &lt; shadowCasters.length; k++)&#xD;&#xA;              this._renderShadowCaster(shadowCasters[k], program, view, projection);&#xD;&#xA;          }&#xD;&#xA;        } else {&#xD;&#xA;           // Directional light &amp; Spotlight case ...&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;Fourth, this is how I compute Omnidirectional Shadow Mapping using my depth cubemap in my main Vertex Shader &amp; Fragment Shader:&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;&#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModel;&#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    varying vec3 vPosition;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;   &#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader:&#xD;&#xA;&#xD;&#xA;    float unpackDepth(in vec4 color) {&#xD;&#xA;    	return dot(color, vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0 ));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float pointShadow(const in PointLight light, const in samplerCube shadowSampler) {&#xD;&#xA;    	vec3 direction = vPosition - light.position;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpackDepth(textureCube(shadowSampler, direction));&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? light.shadowDarkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Finally, this is the result that I'm getting , my scene has a plane, a cube and a sphere. Besides, the red bright sphere is the point light source:&#xD;&#xA;&#xD;&#xA;[![Omnidirectional Shadow Mapping Issue][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, I seems like point light depth framebuffer's cubemap it is not doing a good interpolation among their faces.&#xD;&#xA;&#xD;&#xA;Until now, I've no idea how to solve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/YM04V.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3599" PostHistoryTypeId="1" PostId="1788" RevisionGUID="7652359a-76b0-4ad9-9a87-663e2d0e92fe" CreationDate="2015-12-08T18:48:35.203" UserId="2228" Text="WebGL Omnidirectional Shadow Mapping Issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="3600" PostHistoryTypeId="3" PostId="1788" RevisionGUID="7652359a-76b0-4ad9-9a87-663e2d0e92fe" CreationDate="2015-12-08T18:48:35.203" UserId="2228" Text="|glsl|webgl|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3602" PostHistoryTypeId="2" PostId="1789" RevisionGUID="9031d01c-6799-4e6b-9f62-257e49260eb2" CreationDate="2015-12-08T22:46:58.063" UserId="127" Text="Transformations, and especially rotations, may have different visual effects, depending on the order they are applied to the target object. For example, using a rotation $M_R$ and a translation $M_T$ to the object's vertices $v_i$, $M_R \cdot M_T \cdot v_i$ will usually&lt;sup&gt;1&lt;/sup&gt; result in a different pose than $M_T \cdot M_R \cdot v_i$ does.&#xD;&#xA;&#xD;&#xA;The key here is to keep in mind to which coordinate system the transformation is applied. Assuming that your to be rotated object initially is in the origin without transformations applied, the first rotation will always yield the desired effect. This is because you're applying the first transformation to the object.&#xD;&#xA;&#xD;&#xA;But once your object is already transformed (rotated, translated, whatever) by $M_1$, technically you can already apply the next transformation $M_2$ in two places. Namely, &#xD;&#xA;&#xD;&#xA;1. $M_1 \cdot M_2 \cdot v_i$ or &#xD;&#xA;2. $M_2 \cdot M_1 \cdot v_i$&#xD;&#xA;&#xD;&#xA;You describe that &#xD;&#xA;&#xD;&#xA;&gt; so if I rotate the object around the x axis by 180° and then move my mouse left, the object will rotate to the right instead of left (since the y axis is now inverted).&#xD;&#xA;&#xD;&#xA;This is, because the second rotation is applied to the object itself, which is case 1 of the above. But you want to have the second case, so you need to apply the rotations the other way around. That way, the new rotation will be applied to the already rotated object, i.e. the outer coordinate system.&#xD;&#xA;&#xD;&#xA;Ideally, as long as the user holds the mouse button down you adjust that transformation $M_2$ and once the mouse button is released, you can finalize the transformation and multiply it into $M_1$, which is the identity matrix in the beginning. (Assuming you always want to rotate around the world's center.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;1&lt;/sup&gt; There are some special cases where the result is the same, e.g. if the translation direction matches the rotation axis.&lt;/sub&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3603" PostHistoryTypeId="5" PostId="1784" RevisionGUID="5a7891b2-8ff6-4eda-8cf9-ec4d87e34d7f" CreationDate="2015-12-08T22:52:52.573" UserId="127" Comment="Moved SharpGL from the title to tags" Text="In my SharpGL application I do a very simple, mouse controlled rotation of the scene.&#xD;&#xA;&#xD;&#xA;    gl.Rotate(cameraRotation.X, cameraRotation.Y, 0.0f);&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;    cameraRotation.Y += MousePosition.X - previousMousePositionX;&#xD;&#xA;    cameraRotation.X += MousePosition.Y - previousMousePositionY;&#xD;&#xA;&#xD;&#xA;The problem with this is that the x rotation always comes first, so if I rotate the object around the x axis by 180° and then move my mouse left, the object will rotate to the right instead of left (since the y axis is now inverted). Is there a way to change this so that the object always rotates into the mouse movement direction, regardless of its current position? (like netfabb does it for example)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3604" PostHistoryTypeId="4" PostId="1784" RevisionGUID="5a7891b2-8ff6-4eda-8cf9-ec4d87e34d7f" CreationDate="2015-12-08T22:52:52.573" UserId="127" Comment="Moved SharpGL from the title to tags" Text="Always rotate in the direction of mouse movement" ContentLicense="CC BY-SA 3.0" />
  <row Id="3605" PostHistoryTypeId="6" PostId="1784" RevisionGUID="5a7891b2-8ff6-4eda-8cf9-ec4d87e34d7f" CreationDate="2015-12-08T22:52:52.573" UserId="127" Comment="Moved SharpGL from the title to tags" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3606" PostHistoryTypeId="2" PostId="1790" RevisionGUID="0dae3d3e-5119-4163-9fa4-cbcbe722c5ac" CreationDate="2015-12-08T23:04:42.087" UserId="116" Text="I was reading [this paper](https://research.nvidia.com/sites/default/files/publications/voxel-pipe.pdf) about Voxelpipe, a voxelization library from NVIDIA and I found on section 2 Voxelization the terms ***6-separating*** and ***26-separating***&#xD;&#xA;&#xD;&#xA;I found [this website](http://labs.cs.sunysb.edu/labs/projects/volume/Papers/Voxel/) that tries to explain the basic ideas on voxelization but it wasn't very much helpful understanding the terms mentioned.&#xD;&#xA;&#xD;&#xA;Can anybody explain or point out to some other resource that can help me understand?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3607" PostHistoryTypeId="1" PostId="1790" RevisionGUID="0dae3d3e-5119-4163-9fa4-cbcbe722c5ac" CreationDate="2015-12-08T23:04:42.087" UserId="116" Text="What does &quot;6-separating&quot; and &quot;26-separating&quot; voxelization mean?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3608" PostHistoryTypeId="3" PostId="1790" RevisionGUID="0dae3d3e-5119-4163-9fa4-cbcbe722c5ac" CreationDate="2015-12-08T23:04:42.087" UserId="116" Text="|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3609" PostHistoryTypeId="2" PostId="1791" RevisionGUID="144eb995-e6c8-42c9-a6b4-f4c140488b95" CreationDate="2015-12-09T00:20:05.397" UserId="48" Text="The terms have to do with the &quot;thickness&quot; of the voxelization. I'll illustrate with the help of a diagram about 2D line rasterization (from [this unrelated question](https://stackoverflow.com/questions/4381269/line-rasterisation-cover-all-pixels-regardless-of-line-gradient)).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;On the right is the typical line rasterization: the algorithm finds the one pixel nearest the line within each row (or column, depending on slope). This produces what we usually think of as a &quot;1-pixel-thick&quot; line. On the left is a conservative rasterization, which finds every pixel whose rectangle is touched by the line, and it produces a thicker line.&#xD;&#xA;&#xD;&#xA;6-separating voxelization is like the thin line on the right, and 26-separating is like the thick line on the left, but in 3D. If you imagine the line is actually a triangle viewed on-edge, this is analogous to what the voxelization would look like.&#xD;&#xA;&#xD;&#xA;Different types of voxelization may be better depending on what you're going to do with the voxelized data later. If you're using the voxels as a spatial hierarchy to find triangles that intersect a given region, you probably want the thick voxelization, as it's conservative. The thick voxelization might also be preferable for ray-marching, as the thin voxelization could be missed by a diagonal ray. On the other hand, the thin voxelization is a more faithful representation of the original surface, which is probably better for visibility tests, collision detection, fluid simulation, and suchlike.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7911d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3611" PostHistoryTypeId="2" PostId="1792" RevisionGUID="0a6f929d-74ca-4d80-9dd3-10688b1ed33e" CreationDate="2015-12-09T12:11:36.917" UserId="2219" Text="Alright, using ArcBall in SharpGL.SceneGraph.Core for my mouse controlled rotations fixed the problem. &#xD;&#xA;&#xD;&#xA;Just had to edit the following&#xD;&#xA;&#xD;&#xA;    if (length &gt; 1.0f)&#xD;&#xA;            {&#xD;&#xA;                //  Get normalising factor.&#xD;&#xA;                float norm = 1.0f / (float)Math.Sqrt(length);&#xD;&#xA;&#xD;&#xA;                //  Return normalised vector, a point on the sphere.&#xD;&#xA;                newVector = new Vertex(scaledX * norm, scaledY * norm, 0);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                //  Return a vector to a point mapped inside the sphere.&#xD;&#xA;                newVector = new Vertex(scaledX, scaledY, (float)Math.Sqrt(1.0f - length));&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;in ArcBall.MapToSphere so side movements rotate the object around the y axis instead of the z axis. Works as intended now." ContentLicense="CC BY-SA 3.0" />
  <row Id="3613" PostHistoryTypeId="5" PostId="1785" RevisionGUID="cedc139f-fa21-4d35-966d-5b6121bd4f75" CreationDate="2015-12-09T16:44:25.213" UserId="2226" Comment="added 1153 characters in body; edited title" Text="I at the moment trying to draw some angled lines using bresenham line algorithm which can circulate a 2d array of size 21x21, as a line angled from 0 - 2pi. &#xD;&#xA;&#xD;&#xA;[![Angled line][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c3X52.png&#xD;&#xA;&#xD;&#xA;So the idea is that the program has to output the values which the lines pass through in the grid.. &#xD;&#xA;&#xD;&#xA;So an example with 5x5&#xD;&#xA;&#xD;&#xA;    Angle:0&#xD;&#xA;         _ _ _ _ _ &#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|.|.|.|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;   &#xD;&#xA;    Angle: 45&#xD;&#xA;         _ _ _ _ _ &#xD;&#xA;        |_|_|_|_|.|&#xD;&#xA;        |_|_|_|.|_|&#xD;&#xA;        |_|_|.|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;        |_|_|_|_|_|&#xD;&#xA;   and so on..&#xD;&#xA;&#xD;&#xA;The problem here is that it doesn't look like that my program does that.. The endpoint lies within the given radius length.. &#xD;&#xA;&#xD;&#xA;I am sure am might that I might be messing up with the math.. So i hope some of you could help me here.. &#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    using namespace std;&#xD;&#xA;    typedef std::pair&lt;int,int&gt; coordinate;&#xD;&#xA;    &#xD;&#xA;    int sign(double x ){ return (x &gt; 0) ? 1 : ((x &lt; 0) ? -1 : 0); }&#xD;&#xA;    &#xD;&#xA;    coordinate endpoint(double angle, int x1 , int y1, int lenght)&#xD;&#xA;    {&#xD;&#xA;        double radians = (M_PI/180)*angle;&#xD;&#xA;        &#xD;&#xA;        double x2 = x1 + (lenght * cos(radians));&#xD;&#xA;        double y2 = y1 + (lenght * sin(radians));&#xD;&#xA;        &#xD;&#xA;        return std::make_pair(round(x2),round(y2));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void bresenham(coordinate start, coordinate end)&#xD;&#xA;    {&#xD;&#xA;        //restriction a.x &lt; b.x  and 0 &lt; H/W &lt; 1&#xD;&#xA;        int y =  start.second;&#xD;&#xA;        int w = end.first - start.first;&#xD;&#xA;        int h = end.second - start.second;&#xD;&#xA;        int f = 2*h-w; // current error term&#xD;&#xA;        &#xD;&#xA;        for (int x = start.first; x&lt;= end.first; x++)&#xD;&#xA;        {&#xD;&#xA;            cout &lt;&lt; &quot;mark: &quot; &lt;&lt; x &lt;&lt; &quot;,&quot; &lt;&lt; y &lt;&lt; endl;&#xD;&#xA;            if (f &lt; 0)&#xD;&#xA;            {&#xD;&#xA;                f = f + 2*h;&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                y++;&#xD;&#xA;                f=f+2*(h-w);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int main(int argc, const char * argv[])&#xD;&#xA;    {&#xD;&#xA;       &#xD;&#xA;        coordinate start = make_pair(0,0);&#xD;&#xA;        for (int i = 0; i &lt;= 45; i++)&#xD;&#xA;        {&#xD;&#xA;            coordinate end = endpoint(i,0,0,10);&#xD;&#xA;            cout &lt;&lt; &quot;    endPos: &quot;&lt;&lt; &quot;(&quot; &lt;&lt; end.first &lt;&lt;&quot;,&quot;  &lt;&lt; end.second   &lt;&lt;&quot;)&quot;    &lt;&lt; &quot; Angle: &quot; &lt;&lt; i &lt;&lt; &quot;       &quot; &lt;&lt; endl;&#xD;&#xA;            cout &lt;&lt; &quot;--------------------------------------------&quot; &lt;&lt; endl;&#xD;&#xA;            bresenham(start, end);&#xD;&#xA;            cout &lt;&lt; &quot;--------------------------------------------&quot; &lt;&lt; endl;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the output. &#xD;&#xA;&#xD;&#xA;        endPos: (10,0) Angle: 0       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,0&#xD;&#xA;    mark: 6,0&#xD;&#xA;    mark: 7,0&#xD;&#xA;    mark: 8,0&#xD;&#xA;    mark: 9,0&#xD;&#xA;    mark: 10,0&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,0) Angle: 1       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,0&#xD;&#xA;    mark: 6,0&#xD;&#xA;    mark: 7,0&#xD;&#xA;    mark: 8,0&#xD;&#xA;    mark: 9,0&#xD;&#xA;    mark: 10,0&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,0) Angle: 2       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,0&#xD;&#xA;    mark: 6,0&#xD;&#xA;    mark: 7,0&#xD;&#xA;    mark: 8,0&#xD;&#xA;    mark: 9,0&#xD;&#xA;    mark: 10,0&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 3       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 4       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 5       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 6       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 7       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,1) Angle: 8       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,0&#xD;&#xA;    mark: 4,0&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,1&#xD;&#xA;    mark: 9,1&#xD;&#xA;    mark: 10,1&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 9       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 10       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 11       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 12       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 13       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,2) Angle: 14       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,0&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,1&#xD;&#xA;    mark: 6,1&#xD;&#xA;    mark: 7,1&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,2&#xD;&#xA;    mark: 10,2&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 15       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 16       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 17       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (10,3) Angle: 18       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,2&#xD;&#xA;    mark: 9,3&#xD;&#xA;    mark: 10,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,3) Angle: 19       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,3&#xD;&#xA;    mark: 9,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,3) Angle: 20       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,1&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,2&#xD;&#xA;    mark: 7,2&#xD;&#xA;    mark: 8,3&#xD;&#xA;    mark: 9,3&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 21       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 22       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 23       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 24       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 25       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,4) Angle: 26       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,0&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,1&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,2&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,3&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,4&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 27       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 28       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 29       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 30       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (9,5) Angle: 31       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,2&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,3&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,4&#xD;&#xA;    mark: 9,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,5) Angle: 32       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,4&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,5) Angle: 33       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,1&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,3&#xD;&#xA;    mark: 6,4&#xD;&#xA;    mark: 7,4&#xD;&#xA;    mark: 8,5&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 34       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 35       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 36       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 37       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 38       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 39       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,6) Angle: 40       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,2&#xD;&#xA;    mark: 4,3&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,5&#xD;&#xA;    mark: 8,6&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (8,7) Angle: 41       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,4&#xD;&#xA;    mark: 6,5&#xD;&#xA;    mark: 7,6&#xD;&#xA;    mark: 8,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 42       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 43       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 44       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;        endPos: (7,7) Angle: 45       &#xD;&#xA;    --------------------------------------------&#xD;&#xA;    mark: 0,0&#xD;&#xA;    mark: 1,1&#xD;&#xA;    mark: 2,2&#xD;&#xA;    mark: 3,3&#xD;&#xA;    mark: 4,4&#xD;&#xA;    mark: 5,5&#xD;&#xA;    mark: 6,6&#xD;&#xA;    mark: 7,7&#xD;&#xA;    --------------------------------------------&#xD;&#xA;&#xD;&#xA;What am i doing wrong?... I know that the bresenham algorithm might have to be modified to overcome slopes greater 1 and lower that 0. &#xD;&#xA;&#xD;&#xA;**Clarifying the problem**&#xD;&#xA;&#xD;&#xA;I am trying the iterate the 2d array in a circular manner, using bresenham line algorithm . &#xD;&#xA;&#xD;&#xA;The algorithm should start from the center of the 2d array, and &quot;shoot out&quot; a beam at angles between 0 - 2pi. The beam has to start from the center and end at the edge of the matrix, Hope it makes more sense..&#xD;&#xA;&#xD;&#xA;     _ _ _ _ _ _ _ _ _ _ _ &#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|.|.|.|.|.|.|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    &#xD;&#xA;     _ _ _ _ _ _ _ _ _ _ _ &#xD;&#xA;    |_|_|_|_|_|_|_|_|_|.|.|&#xD;&#xA;    |_|_|_|_|_|_|_|_|.|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|.|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|.|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|.|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;    |_|_|_|_|_|_|_|_|_|_|_|&#xD;&#xA;&#xD;&#xA;I want to output the values the beam hits on the matrix, at each angle..  Which i don't get..  I want to sample the points which the beam intersect in the matrix.. " ContentLicense="CC BY-SA 3.0" />
  <row Id="3614" PostHistoryTypeId="4" PostId="1785" RevisionGUID="cedc139f-fa21-4d35-966d-5b6121bd4f75" CreationDate="2015-12-09T16:44:25.213" UserId="2226" Comment="added 1153 characters in body; edited title" Text="Draw angles lines in raster graphics using bresenham line algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="3615" PostHistoryTypeId="2" PostId="1793" RevisionGUID="3ad629b9-2d8c-474d-9f60-564e8a5380be" CreationDate="2015-12-09T17:40:28.850" UserId="2111" Text="A fairly basic, in some ways, question, but one that many people, myself included, don't really know the answer to. GPU manufacturers often cite extremely high numbers, and the spread between polygon counts that various game engines claim to support often spans multiple orders of magnitude, and then still depends heavily on a lot of variables.&#xD;&#xA;&#xD;&#xA;I'm aware that this is a broad, pretty much open-ended question, and I apologize for that, I just thought that it would be a valuable question to have on here nonetheless." ContentLicense="CC BY-SA 3.0" />
  <row Id="3616" PostHistoryTypeId="1" PostId="1793" RevisionGUID="3ad629b9-2d8c-474d-9f60-564e8a5380be" CreationDate="2015-12-09T17:40:28.850" UserId="2111" Text="How many polygons in a scene can modern hardware reach while maintaining realtime, and how to get there?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3617" PostHistoryTypeId="3" PostId="1793" RevisionGUID="3ad629b9-2d8c-474d-9f60-564e8a5380be" CreationDate="2015-12-09T17:40:28.850" UserId="2111" Text="|gpu|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3618" PostHistoryTypeId="5" PostId="1791" RevisionGUID="89af9e1d-eeda-4125-b663-7195d1a4e641" CreationDate="2015-12-09T18:19:15.953" UserId="48" Comment="add note about what the &quot;n-separating&quot; terminology means" Text="The terms have to do with the &quot;thickness&quot; of the voxelization. I'll illustrate with the help of a diagram about 2D line rasterization (from [this unrelated question](https://stackoverflow.com/questions/4381269/line-rasterisation-cover-all-pixels-regardless-of-line-gradient)).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;On the right is the typical line rasterization: the algorithm finds the one pixel nearest the line within each row (or column, depending on slope). This produces what we usually think of as a &quot;1-pixel-thick&quot; line. On the left is a conservative rasterization, which finds every pixel whose rectangle is touched by the line, and it produces a thicker line.&#xD;&#xA;&#xD;&#xA;6-separating voxelization is like the thin line on the right, and 26-separating is like the thick line on the left, but in 3D. If you imagine the line is actually a triangle viewed on-edge, this is analogous to what the voxelization would look like.&#xD;&#xA;&#xD;&#xA;Different types of voxelization may be better depending on what you're going to do with the voxelized data later. If you're using the voxels as a spatial hierarchy to find triangles that intersect a given region, you probably want the thick voxelization, as it's conservative. The thick voxelization might also be preferable for ray-marching, as the thin voxelization could be missed by a diagonal ray. On the other hand, the thin voxelization is a more faithful representation of the original surface, which is probably better for visibility tests, collision detection, fluid simulation, and suchlike.&#xD;&#xA;&#xD;&#xA;The &quot;n-separating&quot; terminology is a bit unfortunate, but here's what it's getting at. Imagine you're doing a 3D flood-fill in the voxel grid, but in the flood-fill you only look at the 6 direct neighbors of each voxel (±1 step along each axis). Then the &quot;6-separating&quot; (thin) voxelization will stop the flood-fill: it suffices to separate the two sides of the surface, if only 6 neighbors are considered. On the other hand, suppose your flood-fill was allowed to go to diagonal neighbors as well—26 neighbors in all (3×3×3 neighborhood of voxels). Then the 6-separating voxelization wouldn't stop the flood fill, but the 26-separating (thick) one would.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7911d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3619" PostHistoryTypeId="2" PostId="1794" RevisionGUID="7e170b4c-a189-4b77-af29-7e782ac9e35d" CreationDate="2015-12-09T18:29:56.273" UserId="2233" Text="I'm new to computer graphics. These days I've been trying to understand how ray tracing using an acceleration data structure works. I came across the term &quot;early ray termination&quot; several times, I looked it over the internet several times too, but I haven't been able to find a satisfactory explanation of it.&#xD;&#xA;What does it mean to terminate a ray early, and why do we have to do it?&lt;br/&gt;&#xD;&#xA;Besides, I noticed that the term &quot;front-to-back traversal&quot; is mentioned almost every time there's a mention of &quot;early ray termination&quot;.&#xD;&#xA;Concretely how does front-to-back traversal work (in the case of a kd-tree for example) ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3620" PostHistoryTypeId="1" PostId="1794" RevisionGUID="7e170b4c-a189-4b77-af29-7e782ac9e35d" CreationDate="2015-12-09T18:29:56.273" UserId="2233" Text="The meaning of early ray termination and front-to-back traversal in ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="3621" PostHistoryTypeId="3" PostId="1794" RevisionGUID="7e170b4c-a189-4b77-af29-7e782ac9e35d" CreationDate="2015-12-09T18:29:56.273" UserId="2233" Text="|raytracing|c++|optimisation|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3622" PostHistoryTypeId="2" PostId="1795" RevisionGUID="8e7470e5-1224-4ce3-a7c6-00195f6ef460" CreationDate="2015-12-09T18:40:17.690" UserId="48" Text="The endpoint of the line doesn't extend out to the edge of the box because you're using the circle equation with a fixed radius:&#xD;&#xA;&#xD;&#xA;    double x2 = x1 + (lenght * cos(radians));&#xD;&#xA;    double y2 = y1 + (lenght * sin(radians));&#xD;&#xA;&#xD;&#xA;This makes the endpoint trace out a circle as the angle is changed.&#xD;&#xA;&#xD;&#xA;If you want the endpoint to be on the edge of the box, one way is to set up a ray from the center of the box at the desired angle, then calculate the intersection point of the ray with the box. [This article shows how to calculate ray/box intersections](http://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection).&#xD;&#xA;&#xD;&#xA;Another way is to loop over the points around the sides of the box, rather than looping over angles. You would have four separate loops, one for each side, and holding one of x or y fixed while iterating the other. For example, holding x = 10 and iterating y from -10 to +10 would go up the right side.&#xD;&#xA;&#xD;&#xA;As for the slopes outside [0, 1], you must extend your Bresenham algorithm for it. This can be found in any tutorial or sample of Bresenham, for example [the implementations here](http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#C.2B.2B)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3623" PostHistoryTypeId="5" PostId="1789" RevisionGUID="af07c435-281f-4c71-a0e3-5340e7b00327" CreationDate="2015-12-09T21:44:33.037" UserId="127" Comment="Added 2D case for rotation/translation, added more detail to implementation" Text="Transformations, and especially rotations, may have different visual effects, depending on the order they are applied to the target object. For example, using a rotation $M_R$ and a translation $M_T$ to the object's vertices $v_i$, $M_R \cdot M_T \cdot v_i$ will usually&lt;sup&gt;1&lt;/sup&gt; result in a different pose than $M_T \cdot M_R \cdot v_i$ does.&#xD;&#xA;&#xD;&#xA;[![rotation and translation][1]][1]&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;90 degree rotation and translation along the x axis applied to the box. Left: translation first ($M_R \cdot M_T \cdot v_i$). Right: rotation first ($M_T \cdot M_R \cdot v_i$).&lt;/sup&gt;&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;The key here is to keep in mind to which coordinate system the transformation is applied. Assuming that your to be rotated object initially is in the origin without transformations applied, the first rotation will always yield the desired effect. This is because you're applying the first transformation to the object.&#xD;&#xA;&#xD;&#xA;But once your object is already transformed (rotated, translated, whatever) by $M_1$, technically you can already apply the next transformation $M_2$ in two places. Namely, &#xD;&#xA;&#xD;&#xA;1. $M_1 \cdot M_2 \cdot v_i$ or &#xD;&#xA;2. $M_2 \cdot M_1 \cdot v_i$&#xD;&#xA;&#xD;&#xA;You describe that &#xD;&#xA;&#xD;&#xA;&gt; so if I rotate the object around the x axis by 180° and then move my mouse left, the object will rotate to the right instead of left (since the y axis is now inverted).&#xD;&#xA;&#xD;&#xA;This is, because the second rotation is applied to the object itself, which is case 1 of the above. But you want to have the second case, so you need to apply the rotations the other way around. That way, the new rotation will be applied to the already rotated object, i.e. the outer coordinate system.&#xD;&#xA;&#xD;&#xA;Ideally, as long as the user holds the mouse button down you adjust that transformation $M_2$. Calculate the distance the mouse moved from the point the user pressed the button, recalculate the whole rotation ($M_2$) and drop whatever you calculated in the time between the mouse-down event and the previous frame. So for the ongoing rotation, pretend that the user moved the mouse instantly from the start to the current position.&#xD;&#xA;&#xD;&#xA;Once the mouse button is released, you can finalize the transformation and multiply it into $M_1$, which is the identity matrix in the beginning. (Assuming you always want to rotate around the world's center.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;1&lt;/sup&gt; There are some special cases where the result is the same, e.g. if the translation direction matches the rotation axis.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lE2zn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3624" PostHistoryTypeId="5" PostId="1762" RevisionGUID="c5d67585-b447-46ba-baff-c917f7ab7c16" CreationDate="2015-12-09T21:59:15.067" UserId="2162" Comment="deleted 76 characters in body" Text="Given the 4 coordinates of a 2D shape in a 3D space I want to calculate its aspect ratio.&#xD;&#xA;&#xD;&#xA;The 3D space is created with 2 vanishing points.&#xD;&#xA;&#xD;&#xA;The 4 coordinates - marked blue - are the 2D coordinates on the display.&#xD;&#xA;in the example they should be roughly (14, 5.5), (19, 5), (20.3, 7.3), (25.3, 6).&#xD;&#xA;&#xD;&#xA;I'm not sure if this is possible at all, if someone could find proof that for 2 different aspect ratios the 2D coordinates are the same this problem would be unsolvable.&#xD;&#xA;&#xD;&#xA;My exapmle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/omyRz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3625" PostHistoryTypeId="2" PostId="1796" RevisionGUID="38421df9-ff8e-4ece-bdfe-71fc18cef0a4" CreationDate="2015-12-09T22:37:12.460" UserId="2226" Text="I am at the moment having some issues with computing an endpoint in a raster grid that is also a valid position in a graph. &#xD;&#xA;I am trying to draw a line between these two points, but as the point i am computing becomes negative, its position becomes invalid. &#xD;&#xA;&#xD;&#xA;How do i compute the right endpoint value within a 20x20 matrix where my start point is (10,10), and the endpoint has to be 10 steps away from the center at any angle...&#xD;&#xA;&#xD;&#xA;this is how i compute the angle now. &#xD;&#xA;&#xD;&#xA;    coordinate endpoint(double angle, coordinate start, int lenght)&#xD;&#xA;    {&#xD;&#xA;        double radians = (M_PI/180)*angle;&#xD;&#xA;        &#xD;&#xA;        double x2 = start.first + (lenght * cos(radians));&#xD;&#xA;        double y2 = start.second + (lenght * sin(radians));&#xD;&#xA;        &#xD;&#xA;        return std::make_pair(round(x2),round(y2));&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3626" PostHistoryTypeId="1" PostId="1796" RevisionGUID="38421df9-ff8e-4ece-bdfe-71fc18cef0a4" CreationDate="2015-12-09T22:37:12.460" UserId="2226" Text="Compute angles in a raster grid?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3627" PostHistoryTypeId="3" PostId="1796" RevisionGUID="38421df9-ff8e-4ece-bdfe-71fc18cef0a4" CreationDate="2015-12-09T22:37:12.460" UserId="2226" Text="|mathematics|raster-image|triangulation|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3628" PostHistoryTypeId="4" PostId="1796" RevisionGUID="18a8f348-0260-4c03-902b-cd9793c51962" CreationDate="2015-12-09T22:53:32.043" UserId="2226" Comment="edited title" Text="Compute angles and thereby endpoints in a raster grid?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3629" PostHistoryTypeId="2" PostId="1797" RevisionGUID="4fe33c2a-1bb5-44a6-a6b2-ed009a59bdee" CreationDate="2015-12-10T03:11:35.820" UserId="54" Text="I think it is fair to say that the reason there are so many niche variations of GLSL/HLSL/Cg/whatnot is because no programming language is nor will ever be a one size fits all tool. Different problems require different tools, so sometimes it is worth the effort of developing a custom built tool if it is going to pay off in the long run.&#xD;&#xA;&#xD;&#xA;Stock GLSL is by itself pretty much unusable. It hasn't even acquired much stability across versions, so for a program that targets more than one OpenGL version, some sort of preprocessing is a must. HLSL is a bit more stable across versions, but again, if targeting more than one D3D version, some work will need to done to get good portability.&#xD;&#xA;&#xD;&#xA;The kinds of things people usually do are pretty much what you said, like a adding support for basic programming features such as modules and uniform syntax across versions, or even portability across different APIs (GL/D3D) without having to rewrite the shader code. More sophisticated things include fully fledged material systems or things like [generating shader programs on-the-fly][1].&#xD;&#xA;&#xD;&#xA;Shading languages will probably get better and more generic in the future, incorporating things that today are commonly hand-rolled as core features. The new [GCN architecture][2] is a sign of that. So shading languages will be more usable out-of-the-box a while from now, but custom built solutions will never go away because there's only so much you can generalize.&#xD;&#xA;&#xD;&#xA;  [1]: http://gameangst.com/?p=441&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Graphics_Core_Next" ContentLicense="CC BY-SA 3.0" />
  <row Id="3630" PostHistoryTypeId="2" PostId="1798" RevisionGUID="b13f2c75-ad6f-4f73-8134-c46b25ec7014" CreationDate="2015-12-10T05:20:02.120" UserId="48" Text="Front-to-back traversal is the idea that when traversing a ray through the acceleration structure, we want to examine nodes that are in front, i.e. closer to the camera, before other nodes. If you only want the first intersection with a surface (as usual in ray tracing), then if you get an intersection in the front node you don't need to traverse any nodes behind it; as any possible intersection there would be later than the one you already found. This saves time.&#xD;&#xA;&#xD;&#xA;For example, in a kd-tree, at each node you have a splitting plane dividing space into two child nodes. You would first descend to the child closer to the camera, and only if no intersections are found there do you descend to the other child.&#xD;&#xA;&#xD;&#xA;Early ray termination seems to be a term used in the context of volume rendering. When you're traversing a ray through a medium that attenuates light, such as fog, smoke, cloudy liquids, etc., then beyond a certain distance there is no possibility of the ray having any more effect on the image. If you have thick fog with a visibility of 10 meters, then an object 11 meters away cannot be seen.&#xD;&#xA;&#xD;&#xA;You can precalculate the distance at which the attenuation reaches 99% or so (it never quite reaches 100%, but approaches it exponentially). There is no reason to intersect the ray against objects farther than that, so when using the acceleration structure, you can simply discard any nodes beyond that distance. In effect, the ray becomes a line segment terminated at a fixed length. If it doesn't hit anything within that length, there's no point checking further. (Another case where limited-length rays are handy is for shadow rays. You only want to trace them back to the originating light source; any intersections beyond that are irrelevant for the shadow.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3631" PostHistoryTypeId="2" PostId="1799" RevisionGUID="354da3a0-c9ed-4197-ba04-0747e3e2712d" CreationDate="2015-12-10T13:00:04.673" UserId="2237" Text="I developed a ray tracer that use standard phong/blinn phong lighting model. Now I'm modifying it to support physically based rendering, so I'm implementing various BRDF models. At the moment I'm focused on Oren-Nayar and Torrance-Sparrow model. Each one of these is based on spherical coordinates used to express incident wi and outgoing wo light direction. &#xD;&#xA;&#xD;&#xA;**My question is: which way is the right one convert wi and wo from cartesian coordinate to spherical coordinate?** &#xD;&#xA;&#xD;&#xA;I'm applying the standard formula reported here https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions but I'm not sure I'm doing the right thing, **because my vector are not with tail at the origin of the cartesian coordinate system, but are centered on the intersection point of the ray with the object.**&#xD;&#xA;&#xD;&#xA;Here you can find my current implementation:&#xD;&#xA;&#xD;&#xA; - https://github.com/chicio/Multispectral-Ray-tracing/tree/brdf/RayTracing/RayTracer/Objects/BRDF&#xD;&#xA;   &#xD;&#xA; - https://github.com/chicio/Multispectral-Ray-tracing/blob/brdf/RayTracing/RayTracer/Math/Vector3D.cpp&#xD;&#xA;&#xD;&#xA;Can anyone help me giving an explanation of the correct way to convert the wi and wo vector from cartesian to spherical coordinate?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I copy here the relevant part of code:&#xD;&#xA;&#xD;&#xA;spherical coordinate calculation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float Vector3D::sphericalTheta() const {&#xD;&#xA;    &#xD;&#xA;        float sphericalTheta = acosf(Utils::clamp(y, -1.f, 1.f));&#xD;&#xA;    &#xD;&#xA;        return sphericalTheta;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float Vector3D::sphericalPhi() const {&#xD;&#xA;        &#xD;&#xA;        float phi = atan2f(z, x);&#xD;&#xA;        &#xD;&#xA;        return (phi &lt; 0.f) ? phi + 2.f * M_PI : phi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Oren Nayar&#xD;&#xA;&#xD;&#xA;    OrenNayar::OrenNayar(Spectrum&lt;constant::spectrumSamples&gt; reflectanceSpectrum, float degree) : reflectanceSpectrum{reflectanceSpectrum} {&#xD;&#xA;    &#xD;&#xA;        float sigma = Utils::degreeToRadian(degree);&#xD;&#xA;        float sigmaPowerTwo = sigma * sigma;&#xD;&#xA;        &#xD;&#xA;        A = 1.0f - (sigmaPowerTwo / 2.0f * (sigmaPowerTwo + 0.33f));&#xD;&#xA;        B = 0.45f * sigmaPowerTwo / (sigmaPowerTwo + 0.09f);&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Spectrum&lt;constant::spectrumSamples&gt; OrenNayar::f(const Vector3D&amp; wi, const Vector3D&amp; wo, const Intersection* intersection) const {&#xD;&#xA;    &#xD;&#xA;        float thetaI = wi.sphericalTheta();&#xD;&#xA;        float phiI = wi.sphericalPhi();&#xD;&#xA;        &#xD;&#xA;        float thetaO = wo.sphericalTheta();&#xD;&#xA;        float phiO = wo.sphericalPhi();&#xD;&#xA;        &#xD;&#xA;        float alpha = std::fmaxf(thetaI, thetaO);&#xD;&#xA;        float beta = std::fminf(thetaI, thetaO);&#xD;&#xA;        &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; orenNayar = reflectanceSpectrum * constant::inversePi * (A + B * std::fmaxf(0, cosf(phiI - phiO) * sinf(alpha) * tanf(beta)));&#xD;&#xA;        &#xD;&#xA;        return orenNayar;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Torrance-Sparrow&#xD;&#xA;&#xD;&#xA;    float TorranceSparrow::G(const Vector3D&amp; wi, const Vector3D&amp; wo, const Vector3D&amp; wh, const Intersection* intersection) const {&#xD;&#xA;        &#xD;&#xA;        Vector3D normal = intersection-&gt;normal;&#xD;&#xA;        normal.normalize();&#xD;&#xA;        &#xD;&#xA;        float normalDotWh = fabsf(normal.dot(wh));&#xD;&#xA;        float normalDotWo = fabsf(normal.dot(wo));&#xD;&#xA;        float normalDotWi = fabsf(normal.dot(wi));&#xD;&#xA;        float woDotWh = fabsf(wo.dot(wh));&#xD;&#xA;        &#xD;&#xA;        float G = fminf(1.0f, std::fminf((2.0f * normalDotWh * normalDotWo)/woDotWh, (2.0f * normalDotWh * normalDotWi)/woDotWh));&#xD;&#xA;        &#xD;&#xA;        return G;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float TorranceSparrow::D(const Vector3D&amp; wh, const Intersection* intersection) const {&#xD;&#xA;        &#xD;&#xA;        Vector3D normal = intersection-&gt;normal;&#xD;&#xA;        normal.normalize();&#xD;&#xA;    &#xD;&#xA;        float cosThetaH = fabsf(wh.dot(normal));&#xD;&#xA;        &#xD;&#xA;        float Dd = (exponent + 2) * constant::inverseTwoPi * powf(cosThetaH, exponent);&#xD;&#xA;        &#xD;&#xA;        return Dd;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Spectrum&lt;constant::spectrumSamples&gt; TorranceSparrow::f(const Vector3D&amp; wi, const Vector3D&amp; wo, const Intersection* intersection) const {&#xD;&#xA;    &#xD;&#xA;        Vector3D normal = intersection-&gt;normal;&#xD;&#xA;        normal.normalize();&#xD;&#xA;        &#xD;&#xA;        float thetaI = wi.sphericalTheta();&#xD;&#xA;        float thetaO = wo.sphericalTheta();&#xD;&#xA;        &#xD;&#xA;        float cosThetaO = fabsf(cosf(thetaO));&#xD;&#xA;        float cosThetaI = fabsf(cosf(thetaI));&#xD;&#xA;        &#xD;&#xA;        if(cosThetaI == 0 || cosThetaO == 0) {&#xD;&#xA;            &#xD;&#xA;            return reflectanceSpectrum * 0.0f;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        Vector3D wh = (wi + wo);&#xD;&#xA;        wh.normalize();&#xD;&#xA;        &#xD;&#xA;        float cosThetaH = wi.dot(wh);&#xD;&#xA;        &#xD;&#xA;        float F = Fresnel::dieletricFresnel(cosThetaH, refractiveIndex);&#xD;&#xA;        float g = G(wi, wo, wh, intersection);&#xD;&#xA;        float d = D(wh, intersection);&#xD;&#xA;    &#xD;&#xA;        printf(&quot;f %f g %f d %f \n&quot;, F, g, d);&#xD;&#xA;        printf(&quot;result %f \n&quot;, ((d * g * F) / (4.0f * cosThetaI * cosThetaO)));&#xD;&#xA;        &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; torranceSparrow = reflectanceSpectrum * ((d * g * F) / (4.0f * cosThetaI * cosThetaO));&#xD;&#xA;        &#xD;&#xA;        return torranceSparrow;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;After some search I found this implementation of Oren-Nayar BRDF.&#xD;&#xA;&#xD;&#xA;http://content.gpwiki.org/index.php/D3DBook:(Lighting)_Oren-Nayar&#xD;&#xA;&#xD;&#xA;In the implementation above theta for wi and wo is obtained simply doing arccos(wo.dotProduct(Normal)) and arccos(wi.dotProduct(Normal)). This seems reasonable to me, as we can use the normal of the intersection point as the zenith direction for our spherical coordinate system and do the calculation. The calculation of gamma = cos(phi_wi - phi_wo) do some sort of projection of wi and wo on what it calls &quot;tangent space&quot;. Assuming everything is correct in this implementation, can i just use the formulas |View - Normal x (View.dotProduct(Normal))| and |Light - Normal x (Light.dotProduct(Normal))| to obtain the phi coordinate (instead of using arctan(&quot;something&quot;))? " ContentLicense="CC BY-SA 3.0" />
  <row Id="3632" PostHistoryTypeId="1" PostId="1799" RevisionGUID="354da3a0-c9ed-4197-ba04-0747e3e2712d" CreationDate="2015-12-10T13:00:04.673" UserId="2237" Text="BRDF and Spherical coordinate in ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="3633" PostHistoryTypeId="3" PostId="1799" RevisionGUID="354da3a0-c9ed-4197-ba04-0747e3e2712d" CreationDate="2015-12-10T13:00:04.673" UserId="2237" Text="|raytracing|brdf|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3635" PostHistoryTypeId="5" PostId="1799" RevisionGUID="5bd42726-4c39-40bc-a3a5-affa46d8a157" CreationDate="2015-12-10T13:17:57.277" UserId="2237" Comment="added 502 characters in body" Text="I developed a ray tracer that use standard phong/blinn phong lighting model. Now I'm modifying it to support physically based rendering, so I'm implementing various BRDF models. At the moment I'm focused on Oren-Nayar and Torrance-Sparrow model. Each one of these is based on spherical coordinates used to express incident wi and outgoing wo light direction. &#xD;&#xA;&#xD;&#xA;**My question is: which way is the right one convert wi and wo from cartesian coordinate to spherical coordinate?** &#xD;&#xA;&#xD;&#xA;I'm applying the standard formula reported here https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions but I'm not sure I'm doing the right thing, **because my vector are not with tail at the origin of the cartesian coordinate system, but are centered on the intersection point of the ray with the object.** &#xD;&#xA;&#xD;&#xA;Here you can find my current implementation:&#xD;&#xA;&#xD;&#xA; - https://github.com/chicio/Multispectral-Ray-tracing/tree/brdf/RayTracing/RayTracer/Objects/BRDF&#xD;&#xA;   &#xD;&#xA; - https://github.com/chicio/Multispectral-Ray-tracing/blob/brdf/RayTracing/RayTracer/Math/Vector3D.cpp&#xD;&#xA;&#xD;&#xA;Can anyone help me giving an explanation of the correct way to convert the wi and wo vector from cartesian to spherical coordinate?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I copy here the relevant part of code:&#xD;&#xA;&#xD;&#xA;spherical coordinate calculation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float Vector3D::sphericalTheta() const {&#xD;&#xA;    &#xD;&#xA;        float sphericalTheta = acosf(Utils::clamp(y, -1.f, 1.f));&#xD;&#xA;    &#xD;&#xA;        return sphericalTheta;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float Vector3D::sphericalPhi() const {&#xD;&#xA;        &#xD;&#xA;        float phi = atan2f(z, x);&#xD;&#xA;        &#xD;&#xA;        return (phi &lt; 0.f) ? phi + 2.f * M_PI : phi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Oren Nayar&#xD;&#xA;&#xD;&#xA;    OrenNayar::OrenNayar(Spectrum&lt;constant::spectrumSamples&gt; reflectanceSpectrum, float degree) : reflectanceSpectrum{reflectanceSpectrum} {&#xD;&#xA;    &#xD;&#xA;        float sigma = Utils::degreeToRadian(degree);&#xD;&#xA;        float sigmaPowerTwo = sigma * sigma;&#xD;&#xA;        &#xD;&#xA;        A = 1.0f - (sigmaPowerTwo / 2.0f * (sigmaPowerTwo + 0.33f));&#xD;&#xA;        B = 0.45f * sigmaPowerTwo / (sigmaPowerTwo + 0.09f);&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Spectrum&lt;constant::spectrumSamples&gt; OrenNayar::f(const Vector3D&amp; wi, const Vector3D&amp; wo, const Intersection* intersection) const {&#xD;&#xA;    &#xD;&#xA;        float thetaI = wi.sphericalTheta();&#xD;&#xA;        float phiI = wi.sphericalPhi();&#xD;&#xA;        &#xD;&#xA;        float thetaO = wo.sphericalTheta();&#xD;&#xA;        float phiO = wo.sphericalPhi();&#xD;&#xA;        &#xD;&#xA;        float alpha = std::fmaxf(thetaI, thetaO);&#xD;&#xA;        float beta = std::fminf(thetaI, thetaO);&#xD;&#xA;        &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; orenNayar = reflectanceSpectrum * constant::inversePi * (A + B * std::fmaxf(0, cosf(phiI - phiO) * sinf(alpha) * tanf(beta)));&#xD;&#xA;        &#xD;&#xA;        return orenNayar;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Torrance-Sparrow&#xD;&#xA;&#xD;&#xA;    float TorranceSparrow::G(const Vector3D&amp; wi, const Vector3D&amp; wo, const Vector3D&amp; wh, const Intersection* intersection) const {&#xD;&#xA;        &#xD;&#xA;        Vector3D normal = intersection-&gt;normal;&#xD;&#xA;        normal.normalize();&#xD;&#xA;        &#xD;&#xA;        float normalDotWh = fabsf(normal.dot(wh));&#xD;&#xA;        float normalDotWo = fabsf(normal.dot(wo));&#xD;&#xA;        float normalDotWi = fabsf(normal.dot(wi));&#xD;&#xA;        float woDotWh = fabsf(wo.dot(wh));&#xD;&#xA;        &#xD;&#xA;        float G = fminf(1.0f, std::fminf((2.0f * normalDotWh * normalDotWo)/woDotWh, (2.0f * normalDotWh * normalDotWi)/woDotWh));&#xD;&#xA;        &#xD;&#xA;        return G;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float TorranceSparrow::D(const Vector3D&amp; wh, const Intersection* intersection) const {&#xD;&#xA;        &#xD;&#xA;        Vector3D normal = intersection-&gt;normal;&#xD;&#xA;        normal.normalize();&#xD;&#xA;    &#xD;&#xA;        float cosThetaH = fabsf(wh.dot(normal));&#xD;&#xA;        &#xD;&#xA;        float Dd = (exponent + 2) * constant::inverseTwoPi * powf(cosThetaH, exponent);&#xD;&#xA;        &#xD;&#xA;        return Dd;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Spectrum&lt;constant::spectrumSamples&gt; TorranceSparrow::f(const Vector3D&amp; wi, const Vector3D&amp; wo, const Intersection* intersection) const {&#xD;&#xA;    &#xD;&#xA;        Vector3D normal = intersection-&gt;normal;&#xD;&#xA;        normal.normalize();&#xD;&#xA;        &#xD;&#xA;        float thetaI = wi.sphericalTheta();&#xD;&#xA;        float thetaO = wo.sphericalTheta();&#xD;&#xA;        &#xD;&#xA;        float cosThetaO = fabsf(cosf(thetaO));&#xD;&#xA;        float cosThetaI = fabsf(cosf(thetaI));&#xD;&#xA;        &#xD;&#xA;        if(cosThetaI == 0 || cosThetaO == 0) {&#xD;&#xA;            &#xD;&#xA;            return reflectanceSpectrum * 0.0f;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        Vector3D wh = (wi + wo);&#xD;&#xA;        wh.normalize();&#xD;&#xA;        &#xD;&#xA;        float cosThetaH = wi.dot(wh);&#xD;&#xA;        &#xD;&#xA;        float F = Fresnel::dieletricFresnel(cosThetaH, refractiveIndex);&#xD;&#xA;        float g = G(wi, wo, wh, intersection);&#xD;&#xA;        float d = D(wh, intersection);&#xD;&#xA;    &#xD;&#xA;        printf(&quot;f %f g %f d %f \n&quot;, F, g, d);&#xD;&#xA;        printf(&quot;result %f \n&quot;, ((d * g * F) / (4.0f * cosThetaI * cosThetaO)));&#xD;&#xA;        &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; torranceSparrow = reflectanceSpectrum * ((d * g * F) / (4.0f * cosThetaI * cosThetaO));&#xD;&#xA;        &#xD;&#xA;        return torranceSparrow;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;After some search I found this implementation of Oren-Nayar BRDF.&#xD;&#xA;&#xD;&#xA;http://content.gpwiki.org/index.php/D3DBook:(Lighting)_Oren-Nayar&#xD;&#xA;&#xD;&#xA;In the implementation above theta for wi and wo is obtained simply doing arccos(wo.dotProduct(Normal)) and arccos(wi.dotProduct(Normal)). This seems reasonable to me, as we can use the normal of the intersection point as the zenith direction for our spherical coordinate system and do the calculation. The calculation of gamma = cos(phi_wi - phi_wo) do some sort of projection of wi and wo on what it calls &quot;tangent space&quot;. Assuming everything is correct in this implementation, can i just use the formulas |View - Normal x (View.dotProduct(Normal))| and |Light - Normal x (Light.dotProduct(Normal))| to obtain the phi coordinate (instead of using arctan(&quot;something&quot;))? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;N.B.: I'm also reading &quot;Physically based rendering: from theory to implementation&quot;, that is the book released to pbrt (http://www.pbrt.org). In this implementation there's some sort of change of coordinate system for the point of intersection (using partial derivates and the parametric coordinate of the surface) (I'm reading it now so what I'm saying could not be accurate). I want to find a straight way (maybe the one above in UPDATE 2 is what I'm searching for, if anyone could confirm it).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3636" PostHistoryTypeId="5" PostId="1796" RevisionGUID="a548e8b3-898f-462e-b0ee-260ffa4e0004" CreationDate="2015-12-10T16:14:28.097" UserId="127" Comment="Corrected capitalization of the I" Text="I am at the moment having some issues with computing an endpoint in a raster grid that is also a valid position in a graph. &#xD;&#xA;I am trying to draw a line between these two points, but as the point I am computing becomes negative, its position becomes invalid. &#xD;&#xA;&#xD;&#xA;How do I compute the right endpoint value within a 20x20 matrix where my start point is $(10,10)$, and the endpoint has to be 10 steps away from the center at any angle?&#xD;&#xA;&#xD;&#xA;This is how I compute the angle now: &#xD;&#xA;&#xD;&#xA;    coordinate endpoint(double angle, coordinate start, int lenght)&#xD;&#xA;    {&#xD;&#xA;        double radians = (M_PI/180)*angle;&#xD;&#xA;        &#xD;&#xA;        double x2 = start.first + (lenght * cos(radians));&#xD;&#xA;        double y2 = start.second + (lenght * sin(radians));&#xD;&#xA;        &#xD;&#xA;        return std::make_pair(round(x2),round(y2));&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3637" PostHistoryTypeId="2" PostId="1800" RevisionGUID="531cc0d2-5e7a-4c99-ba9d-f78e3e406b37" CreationDate="2015-12-11T06:18:50.267" UserId="48" Text="The polar coordinate system commonly used in BRDF definitions is set up relative to the surface being shaded, i.e. in tangent space. The $\theta$ angle measures how far you are from the surface normal while $\phi$ angle is the azimuth around the plane of the surface relative to some reference direction (which doesn't matter unless the BRDF is anisotropic). So if you want to convert to these coordinates, you have to first get your vector in tangent space (with the origin at the intersection point and two of the axes aligned with the surface), then apply the usual Cartesian-to-spherical transformation.&#xD;&#xA;&#xD;&#xA;However, normally you can and should evaluate BRDFs *without* using polar coordinates, trigonometric functions, or angles at all, but just using vector math primitives such as dot products. This is usually more efficient *and* it's more robust, as you don't have to deal with angle wraparound, factors of pi, out-of-range arguments to inverse trig functions and so on. For instance, you probably know that the cosine of the angle between vectors can be obtained by just dotting the (normalized) vectors. The sine and tangent can be obtained through trig identities from the cosine (i.e. from the dot product).&#xD;&#xA;&#xD;&#xA;Fabian Giesen wrote an article on this topic, [Finish your derivations, please](https://fgiesen.wordpress.com/2010/10/21/finish-your-derivations-please/), that refers to the exact Oren-Nayar article you linked and gives an alternate, trig-free form:&#xD;&#xA;&#xD;&#xA;&gt;Time to brush up your trigonometric identities. A particularly bad offender can be found here – the relevant section from the simplified shader is this:&#xD;&#xA;&#xD;&#xA;&gt;     float alpha = max( acos( dot( v, n ) ), acos( dot( l, n ) ) );&#xD;&#xA;&gt;     float beta  = min( acos( dot( v, n ) ), acos( dot( l, n ) ) );&#xD;&#xA;&gt;     C = sin(alpha) * tan(beta);&#xD;&#xA;&#xD;&#xA;&gt;Ouch! If you use some trig identities and the fact that acos is monotonically decreasing over its domain, this reduces to:&#xD;&#xA;&#xD;&#xA;&gt;     float vdotn = dot(v, n);&#xD;&#xA;&gt;     float ldotn = dot(l, n);&#xD;&#xA;&gt;     C = sqrt((1.0 - vdotn*vdotn) * (1.0 - ldotn*ldotn))&#xD;&#xA;&gt;       / max(vdotn, ldotn);&#xD;&#xA;&#xD;&#xA;&gt;..and suddenly there’s no need to use a lookup texture anymore (and by the way, this has way higher accuracy too)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3638" PostHistoryTypeId="5" PostId="1800" RevisionGUID="c04aeeee-0571-453c-99e2-b98c4101609e" CreationDate="2015-12-11T06:27:07.310" UserId="48" Comment="added 127 characters in body" Text="The polar coordinate system commonly used in BRDF definitions is set up relative to the surface being shaded, i.e. in tangent space. The $\theta$ angle measures how far you are from the surface normal while $\phi$ is the azimuth around the plane of the surface relative to some reference direction (which doesn't matter unless the BRDF is anisotropic). So if you want to convert to these coordinates, you have to first get your vector in tangent space (with the origin at the intersection point and two of the axes aligned with the surface), then apply the usual Cartesian-to-spherical transformation.&#xD;&#xA;&#xD;&#xA;However, normally you can and should evaluate BRDFs *without* using polar coordinates, trigonometric functions, or angles at all, but just using vector math primitives such as dot products. This is usually more efficient *and* it's more robust, as you don't have to deal with angle wraparound, factors of pi, out-of-range arguments to inverse trig functions and so on. For instance, you probably know that the cosine of the angle between vectors can be obtained by just dotting the (normalized) vectors. The sine and tangent can be obtained through trig identities from the cosine (i.e. from the dot product).&#xD;&#xA;&#xD;&#xA;Fabian Giesen wrote an article on this topic, [Finish your derivations, please](https://fgiesen.wordpress.com/2010/10/21/finish-your-derivations-please/), that refers to the exact Oren-Nayar article you linked and gives an alternate, trig-free form:&#xD;&#xA;&#xD;&#xA;&gt;Time to brush up your trigonometric identities. A particularly bad offender can be found here – the relevant section from the simplified shader is this:&#xD;&#xA;&#xD;&#xA;&gt;     float alpha = max( acos( dot( v, n ) ), acos( dot( l, n ) ) );&#xD;&#xA;&gt;     float beta  = min( acos( dot( v, n ) ), acos( dot( l, n ) ) );&#xD;&#xA;&gt;     C = sin(alpha) * tan(beta);&#xD;&#xA;&#xD;&#xA;&gt;Ouch! If you use some trig identities and the fact that acos is monotonically decreasing over its domain, this reduces to:&#xD;&#xA;&#xD;&#xA;&gt;     float vdotn = dot(v, n);&#xD;&#xA;&gt;     float ldotn = dot(l, n);&#xD;&#xA;&gt;     C = sqrt((1.0 - vdotn*vdotn) * (1.0 - ldotn*ldotn))&#xD;&#xA;&gt;       / max(vdotn, ldotn);&#xD;&#xA;&#xD;&#xA;&gt;..and suddenly there’s no need to use a lookup texture anymore (and by the way, this has way higher accuracy too).&#xD;&#xA;&#xD;&#xA;And note that this formulation only has one transcendental function (`sqrt`) in place of four (two `acos`, a `sin`, and a `tan`)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3639" PostHistoryTypeId="2" PostId="1801" RevisionGUID="158f3eed-7b94-4b8a-bf0b-186ce51b9708" CreationDate="2015-12-11T11:00:40.783" UserId="2244" Text="Thinking about hybrid raytracing, hence the following question:&#xD;&#xA;&#xD;&#xA;Suppose I have two solid spheres $s_1$ and $s_2$. We know their centres and radii, and we know that they have some overlapping volume in space.&#xD;&#xA;&#xD;&#xA;We have a typical 3D graphics setup: assume eye is at the origin, and we are projecting the spheres onto a view plane at $z = f$ for some positive $f$. The spheres are beyond the view plane and don't intersect it.&#xD;&#xA;&#xD;&#xA;Let $c$ be the circle in space that is points on the surface of both spheres, i.e. the visible (from some angles) 'join' of their overlapping volumes.&#xD;&#xA;&#xD;&#xA;I want to calculate if any of $c$ is visible when projected onto our view plane. It might not be, if $s_1$ or $s_2$ get completely in the way.&#xD;&#xA;&#xD;&#xA;Any ideas for approaching this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3640" PostHistoryTypeId="1" PostId="1801" RevisionGUID="158f3eed-7b94-4b8a-bf0b-186ce51b9708" CreationDate="2015-12-11T11:00:40.783" UserId="2244" Text="Sphere intersection occlusion (for hybrid raytracing)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3641" PostHistoryTypeId="3" PostId="1801" RevisionGUID="158f3eed-7b94-4b8a-bf0b-186ce51b9708" CreationDate="2015-12-11T11:00:40.783" UserId="2244" Text="|raytracing|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3642" PostHistoryTypeId="10" PostId="1775" RevisionGUID="e4cf0875-fa5f-4ff4-9788-b5820fc92dd2" CreationDate="2015-12-11T12:34:54.760" UserId="16" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[1785],&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="3647" PostHistoryTypeId="2" PostId="1803" RevisionGUID="d5186bfd-589d-4929-a53a-da42355027fa" CreationDate="2015-12-12T11:23:46.880" UserId="127" Text="Given that I didn't miss anything, you can probably cut this down to a problem in the 2D space. Viewing onto the plane defined by the center points of the spheres and your camera origin, the scene looks like this:&#xD;&#xA;&#xD;&#xA;[![scene with visible intersection][1]][1]&#xD;&#xA;&#xD;&#xA;The spheres become circles with the center points $C_1$ and $C_2$, and the intersection circle is now only 2 points with only the closer one $P$ being interesting. The camera/eye is arbitrarily set to the point $E$.&#xD;&#xA;&#xD;&#xA;Calculating if one point on the spheres is visible or not is easy: Simply check whether or not the angles at point $P$ between $E$ and $C_1$ respectively $E$ and $C_2$ are both greater (or equal to) 90 degree&lt;sup&gt;1&lt;/sup&gt;.&#xD;&#xA;&#xD;&#xA;If $P$ is visible, some part (e.g. at least that point) of the intersection circle is visible. Otherwise the whole intersection circle must be occluded by one of your spheres, namely the one which creates an angle of less than 90 degree.&#xD;&#xA;&#xD;&#xA;Here is how it looks if $P$ is not visible from $E$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;You can clearly see how that point is occluded by the circle around $C_2$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;1&lt;/sup&gt; Having an angle of exactly 90 degree means that the line between $E$ and $P$ just touches the respective circle/sphere in point $P$ as a tangent.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IhbVx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tAnbC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3648" PostHistoryTypeId="5" PostId="1803" RevisionGUID="327a925f-cc0c-4eb6-a6d2-086fc7c4d292" CreationDate="2015-12-12T11:29:06.757" UserId="127" Comment="added 71 characters in body" Text="Given that I didn't miss anything, you can probably cut this down to a problem in the 2D space. Viewing onto the plane defined by the center points of the spheres and your camera origin, the scene looks like this:&#xD;&#xA;&#xD;&#xA;[![scene with visible intersection][1]][1]&#xD;&#xA;&#xD;&#xA;The spheres become circles with the center points $C_1$ and $C_2$, and the intersection circle is now only 2 points with only the closer one $P$ being interesting. The camera/eye is arbitrarily set to the point $E$.&#xD;&#xA;&#xD;&#xA;Calculating if one point on the spheres is visible or not is easy: Simply check whether or not the angles at point $P$ between $E$ and $C_1$ respectively $E$ and $C_2$ are both greater (or equal to) 90 degree&lt;sup&gt;1&lt;/sup&gt;.&#xD;&#xA;&#xD;&#xA;If $P$ is visible, some part (e.g. at least that point) of the intersection circle is visible. Otherwise the whole intersection circle must be occluded by one of your spheres, namely the one which creates an angle of less than 90 degree.&#xD;&#xA;&#xD;&#xA;Here is how it looks if $P$ is not visible from $E$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;You can clearly see how that point is occluded by the circle around $C_2$ and that the angle between $E$ and $C_2$ in $P$ is less than 90 degree.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;&lt;sup&gt;1&lt;/sup&gt; Having an angle of exactly 90 degree means that the line between $E$ and $P$ just touches the respective circle/sphere in point $P$ as a tangent.&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IhbVx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tAnbC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3649" PostHistoryTypeId="6" PostId="1801" RevisionGUID="570e9d45-5de2-47e6-93cd-bbcb3c919840" CreationDate="2015-12-12T11:31:30.270" UserId="127" Comment="edited tags" Text="|raytracing|3d|occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3650" PostHistoryTypeId="10" PostId="1753" RevisionGUID="b01e10c0-db2d-4aa6-94bb-7c4b7a6197e1" CreationDate="2015-12-12T11:44:58.767" UserId="127" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:127,&quot;DisplayName&quot;:&quot;Nero&quot;}]}" />
  <row Id="3651" PostHistoryTypeId="12" PostId="1788" RevisionGUID="ab7fe9ce-6cec-4e28-b650-507b3acb2c5e" CreationDate="2015-12-12T15:12:58.607" UserId="2228" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2228,&quot;DisplayName&quot;:&quot;CZC91&quot;}]}" />
  <row Id="3661" PostHistoryTypeId="2" PostId="1806" RevisionGUID="12e58ec8-ab3a-4d3b-b765-d556680e35c4" CreationDate="2015-12-14T02:15:36.533" UserId="1614" Text="I think it is commonly accepted that real time is everything that is above interactive. And interactive is defined as &quot;responds to input but is not smooth in the fact that the animation seems jaggy&quot;.  &#xD;&#xA;So real time will depend on the speed of the movements one needs to represent, cinema projects at 24 FPS and is sufficiently real time for many cases.&#xD;&#xA;&#xD;&#xA;Then how many polygons a machine can deal with is easily verifiable by checking for yourself. Just create a little VBO patch as a simple test and a FPS counter, many DirectX or OpenGL samples will give you the perfect test bed for this benchmark.&#xD;&#xA;&#xD;&#xA;You'll find if you have a high end graphics card that you can display about 1 million polygons in real time. However as you said, engines will not claim support so easily because real world scene data will cause a number of performance hogs that is unrelated to polygon count.&#xD;&#xA;&#xD;&#xA;You have:&#xD;&#xA;&#xD;&#xA;- fill rate&#xD;&#xA; - texture sampling&#xD;&#xA; - ROP output&#xD;&#xA;- draw calls&#xD;&#xA;- render target switches&#xD;&#xA;- buffer updates (uniform or other)&#xD;&#xA;- overdraw&#xD;&#xA;- shader complexity&#xD;&#xA;- pipeline complexity (any feedback used? iterative geometry shading? occlusion?)&#xD;&#xA;- synch points with CPU (pixel readback?)&#xD;&#xA;- polygon richness&#xD;&#xA;&#xD;&#xA;Depending on the weak and strong points of a particlar graphic card, one or another of these points is going to be the bottleneck. it's not like you can say for sure &quot;here, that's the one&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="3662" PostHistoryTypeId="5" PostId="1806" RevisionGUID="3a5eb4ff-fca2-4131-a2d3-30feff2497e5" CreationDate="2015-12-14T09:39:22.270" UserId="1614" Comment="explanation about vertex pushing particulars" Text="I think it is commonly accepted that real time is everything that is above interactive. And interactive is defined as &quot;responds to input but is not smooth in the fact that the animation seems jaggy&quot;.  &#xD;&#xA;So real time will depend on the speed of the movements one needs to represent, cinema projects at 24 FPS and is sufficiently real time for many cases.&#xD;&#xA;&#xD;&#xA;Then how many polygons a machine can deal with is easily verifiable by checking for yourself. Just create a little VBO patch as a simple test and a FPS counter, many DirectX or OpenGL samples will give you the perfect test bed for this benchmark.&#xD;&#xA;&#xD;&#xA;You'll find if you have a high end graphics card that you can display about 1 million polygons in real time. However as you said, engines will not claim support so easily because real world scene data will cause a number of performance hogs that is unrelated to polygon count.&#xD;&#xA;&#xD;&#xA;You have:&#xD;&#xA;&#xD;&#xA;- fill rate&#xD;&#xA; - texture sampling&#xD;&#xA; - ROP output&#xD;&#xA;- draw calls&#xD;&#xA;- render target switches&#xD;&#xA;- buffer updates (uniform or other)&#xD;&#xA;- overdraw&#xD;&#xA;- shader complexity&#xD;&#xA;- pipeline complexity (any feedback used? iterative geometry shading? occlusion?)&#xD;&#xA;- synch points with CPU (pixel readback?)&#xD;&#xA;- polygon richness&#xD;&#xA;&#xD;&#xA;Depending on the weak and strong points of a particlar graphic card, one or another of these points is going to be the bottleneck. it's not like you can say for sure &quot;here, that's the one&quot;.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I wanted to add that, one cannot use the GFlops spec figure of one specific card and map it linearly to polygon pushing capacity. Because of the fact that polygon treatment has to sip through a sequential bottleneck in the graphics pipeline as explained in great details here:  [https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/][1]  &#xD;&#xA;TLDR: the vertices has to fit into a small cache before primitive assembly which is natively a sequential thing (the vertex buffer order matters).  &#xD;&#xA;&#xD;&#xA;If you compare the geforce 7800 (9yr old?) to this year's 980, it seems the number of operations per second it is capable of has increased one thousand fold. But you can bet your sister's bra that it's not going to push polygons a thousand times faster (which would be around 200 billion a second by this simple metric).&#xD;&#xA;&#xD;&#xA;  [1]: https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3664" PostHistoryTypeId="13" PostId="1788" RevisionGUID="f586f853-9c8b-4f93-aa48-19a6a5a67ebc" CreationDate="2015-12-14T21:53:06.630" UserId="2228" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2228,&quot;DisplayName&quot;:&quot;CZC91&quot;}]}" />
  <row Id="3665" PostHistoryTypeId="2" PostId="1807" RevisionGUID="256fb460-e4d9-4c01-b196-5ddf8ffba871" CreationDate="2015-12-15T00:12:41.023" UserId="2228" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;After a couple of days I realized that **I was computing my projection matrix using a FOV angle in degrees and It should be in radians**. I made the conversion and now everything works great. The interpolation among faces of my depth framebuffer's cubemap is now perfect. For this reason, It is important to handle every single trigonometric function's angle in radians.&#xD;&#xA;&#xD;&#xA;Moreover, I realized that you can compute your view matrix either as I said in the question and in this way:&#xD;&#xA;&#xD;&#xA;    view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;This approach means that your point of view is placed in pointlight's center and you just render in each direction of your cubemap, but which are these directions? well, **these directions are computed adding each target that I've in the switch block (according to each cubemap's face) with your pointlight's position**.&#xD;&#xA; &#xD;&#xA;Furthermore, **It is not necessary to flip Y-Coordinate of the projection matrix**, In this case, It is ok dispatch pointlight's perspective projection matrix to your GLSL shader without scaling It by (1, -1, 1) because **I'm working with textures that don't have a flipped Y-Coordinate**, I think you should flip Y-Coordinate of your pointlight's projection matrix **only if you are working with a flipped texture's Y-Coordinate**, this in order to have a correct omnidirectional shadow mapping effect.&#xD;&#xA;&#xD;&#xA;Finally, I'll leave here my final version of my omnidirectional shadow mapping algorithm on CPU side, my depth program's vertex/fragment shader &amp; omnidirectional shadow mapping algorithm in GPU using a fragment shader with comments, this in order to help somebody who could be learning this technique, or solve future doubts about this algoritm:&#xD;&#xA;&#xD;&#xA;**CPU**&#xD;&#xA;&#xD;&#xA;      // For each pointlight source do&#xD;&#xA;&#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Get each pointlight's world position&#xD;&#xA;&#xD;&#xA;        position = light.worldPosition();&#xD;&#xA;    &#xD;&#xA;        // Binds pointlight's depth framebuffer. Besides, in this function,&#xD;&#xA;        // viewport's dimensions are set according to depth framebuffer's dimension.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.bind(gl, this.state);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution have changed, it'll be created again.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;&#xD;&#xA;        for (j = 0; j &lt; 6; j++) {&#xD;&#xA;          switch (j) {&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_X:&#xD;&#xA;              target.set(1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_X:&#xD;&#xA;              target.set(-1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_Y:&#xD;&#xA;              target.set(0, 1, 0);&#xD;&#xA;              up.set(0, 0, 1);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_Y:&#xD;&#xA;              target.set(0, -1, 0);&#xD;&#xA;              up.set(0, 0, -1);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_Z:&#xD;&#xA;              target.set(0, 0, 1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_Z:&#xD;&#xA;              target.set(0, 0, -1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          // Creates a view matrix using target and up vectors &#xD;&#xA;          // according to each face of pointlight's cubemap.&#xD;&#xA;    &#xD;&#xA;          view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;          // Attaches cubemap's face to current framebuffer &#xD;&#xA;          // in order to record depth values in that direction.&#xD;&#xA;    &#xD;&#xA;          light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;          // Clears color &amp; depth buffers of your current framebuffer&#xD;&#xA;    &#xD;&#xA;          this.clear();&#xD;&#xA;&#xD;&#xA;          // Render each shadow caster mesh using your depth program&#xD;&#xA;    &#xD;&#xA;          for (k = 0; k &lt; meshes.length; k++)&#xD;&#xA;            this._renderMeshDepth(program, meshes[k], view, light.projection);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;On renderMeshDepth function I've:&#xD;&#xA;&#xD;&#xA;      // Computes pointlight's model-view matrix &#xD;&#xA;&#xD;&#xA;      modelView.mul(view, mesh.world);&#xD;&#xA;&#xD;&#xA;      // I send each matrix to my depth program&#xD;&#xA;    &#xD;&#xA;      program.loadUniformMatrix(gl, 'uModelView', modelView);&#xD;&#xA;      program.loadUniformMatrix(gl, 'uProjection', projection);&#xD;&#xA;    &#xD;&#xA;      // Renders a mesh using vertex buffer objects (VBO)&#xD;&#xA;&#xD;&#xA;      mesh.render(gl, program.attributes, this.state, this.extensions);&#xD;&#xA;&#xD;&#xA;**GPU**&#xD;&#xA;&#xD;&#xA;Depth Program Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Depth Program Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    // The pack function distributes fragment's depth precision storing &#xD;&#xA;    // it throughout (R,G,B,A) color channels and not just R color channel &#xD;&#xA;    // as usual in shadow mapping algorithms. This is because I'm working&#xD;&#xA;    // with textures that have 8-bits for each channel or UNSIGNED_BYTE type.&#xD;&#xA;    &#xD;&#xA;    vec4 pack(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);&#xD;&#xA;    &#xD;&#xA;      vec4 res = fract(depth * bitShift);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      // Packs normalized fragment's Z-Coordinate which is in [0,1] interval.&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = pack(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Omnidirectional Shadow Mapping function in my main fragment shader:&#xD;&#xA;&#xD;&#xA;    // Unpacks fragment's Z-Coordinate which was packed &#xD;&#xA;    // on the depth program's fragment shader.&#xD;&#xA;    &#xD;&#xA;    float unpack(in vec4 color) {&#xD;&#xA;       const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);&#xD;&#xA;       return dot(color, bitShift);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Computes Omnidirectional Shadow Mapping technique using a samplerCube&#xD;&#xA;    // vec3 lightPosition is your pointlight's position in world coordinates.&#xD;&#xA;    // vec3 vPosition is your vertex's position in world coordinates, in code&#xD;&#xA;    // I mean this -&gt; vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;    // where uModel is your World/Model matrix.&#xD;&#xA;&#xD;&#xA;    float omnidirectionalShadow(in vec3 lightPosition, in float bias, in float darkness, in samplerCube sampler) {&#xD;&#xA;    	vec3 direction = vPosition - lightPosition;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpack(textureCube(sampler, direction)) + bias;&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? darkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here you have a final render of the algorithm&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Have fun coding beautiful graphics, good luck :) &#xD;&#xA;&#xD;&#xA;C.Z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvMHa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3666" PostHistoryTypeId="5" PostId="1807" RevisionGUID="5b0ff937-f409-4bae-84fc-847622d69ab2" CreationDate="2015-12-15T00:22:58.870" UserId="2228" Comment="added 148 characters in body" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;After a couple of days I realized that **I was computing my projection matrix using a FOV angle in degrees and It should be in radians**. I made the conversion and now everything works great. The interpolation among faces of my depth framebuffer's cubemap is now perfect. For this reason, It is important to handle every single trigonometric function's angle in radians.&#xD;&#xA;&#xD;&#xA;Moreover, I realized that you can compute your view matrix either as I said in the question and in this way:&#xD;&#xA;&#xD;&#xA;    view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;This approach means that your point of view is placed in pointlight's center and you just render in each direction of your cubemap, but which are these directions? well, **these directions are computed adding each target that I've in the switch block (according to each cubemap's face) with your pointlight's position**.&#xD;&#xA; &#xD;&#xA;Furthermore, **It is not necessary to flip Y-Coordinate of the projection matrix**, In this case, It is ok dispatch pointlight's perspective projection matrix to your GLSL shader without scaling It by (1, -1, 1) because **I'm working with textures that don't have a flipped Y-Coordinate**, I think you should flip Y-Coordinate of your pointlight's projection matrix **only if you are working with a flipped texture's Y-Coordinate**, this in order to have a correct omnidirectional shadow mapping effect.&#xD;&#xA;&#xD;&#xA;Finally, I'll leave here the final version of my Omnidirectional Shadow Mapping algorithm on CPU side. Also, in GPU side my depth program's vertex/fragment shader &amp; omnidirectional shadow mapping fuction in my main fragment shader. For botch sides (CPU/GPU) you'll see comments about what is exactly doing each line, this in order to help somebody who could be learning this technique, or solve future doubts about this algoritm:&#xD;&#xA;&#xD;&#xA;**CPU**&#xD;&#xA;&#xD;&#xA;      // Binds depth program&#xD;&#xA;       &#xD;&#xA;      program.bind(gl);&#xD;&#xA;&#xD;&#xA;      // For each pointlight source do&#xD;&#xA;&#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Get each pointlight's world position&#xD;&#xA;&#xD;&#xA;        position = light.worldPosition();&#xD;&#xA;    &#xD;&#xA;        // Binds pointlight's depth framebuffer. Besides, in this function,&#xD;&#xA;        // viewport's dimensions are set according to depth framebuffer's dimension.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.bind(gl, this.state);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution have changed, it'll be created again.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;&#xD;&#xA;        for (j = 0; j &lt; 6; j++) {&#xD;&#xA;          switch (j) {&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_X:&#xD;&#xA;              target.set(1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_X:&#xD;&#xA;              target.set(-1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_Y:&#xD;&#xA;              target.set(0, 1, 0);&#xD;&#xA;              up.set(0, 0, 1);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_Y:&#xD;&#xA;              target.set(0, -1, 0);&#xD;&#xA;              up.set(0, 0, -1);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_Z:&#xD;&#xA;              target.set(0, 0, 1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_Z:&#xD;&#xA;              target.set(0, 0, -1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          // Creates a view matrix using target and up vectors &#xD;&#xA;          // according to each face of pointlight's cubemap.&#xD;&#xA;    &#xD;&#xA;          view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;          // Attaches cubemap's face to current framebuffer &#xD;&#xA;          // in order to record depth values in that direction.&#xD;&#xA;    &#xD;&#xA;          light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;          // Clears color &amp; depth buffers of your current framebuffer&#xD;&#xA;    &#xD;&#xA;          this.clear();&#xD;&#xA;&#xD;&#xA;          // Render each shadow caster mesh using your depth program&#xD;&#xA;    &#xD;&#xA;          for (k = 0; k &lt; meshes.length; k++)&#xD;&#xA;            this._renderMeshDepth(program, meshes[k], view, light.projection);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;On renderMeshDepth function I've:&#xD;&#xA;&#xD;&#xA;      // Computes pointlight's model-view matrix &#xD;&#xA;&#xD;&#xA;      modelView.mul(view, mesh.world);&#xD;&#xA;&#xD;&#xA;      // I send each matrix to my depth program&#xD;&#xA;    &#xD;&#xA;      program.loadUniformMatrix(gl, 'uModelView', modelView);&#xD;&#xA;      program.loadUniformMatrix(gl, 'uProjection', projection);&#xD;&#xA;    &#xD;&#xA;      // Renders a mesh using vertex buffer objects (VBO)&#xD;&#xA;&#xD;&#xA;      mesh.render(gl, program.attributes, this.state, this.extensions);&#xD;&#xA;&#xD;&#xA;**GPU**&#xD;&#xA;&#xD;&#xA;Depth Program Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Depth Program Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    // The pack function distributes fragment's depth precision storing &#xD;&#xA;    // it throughout (R,G,B,A) color channels and not just R color channel &#xD;&#xA;    // as usual in shadow mapping algorithms. This is because I'm working&#xD;&#xA;    // with textures that have 8-bits for each channel or UNSIGNED_BYTE type.&#xD;&#xA;    &#xD;&#xA;    vec4 pack(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);&#xD;&#xA;    &#xD;&#xA;      vec4 res = fract(depth * bitShift);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      // Packs normalized fragment's Z-Coordinate which is in [0,1] interval.&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = pack(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Omnidirectional Shadow Mapping function in my main fragment shader:&#xD;&#xA;&#xD;&#xA;    // Unpacks fragment's Z-Coordinate which was packed &#xD;&#xA;    // on the depth program's fragment shader.&#xD;&#xA;    &#xD;&#xA;    float unpack(in vec4 color) {&#xD;&#xA;       const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);&#xD;&#xA;       return dot(color, bitShift);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Computes Omnidirectional Shadow Mapping technique using a samplerCube&#xD;&#xA;    // vec3 lightPosition is your pointlight's position in world coordinates.&#xD;&#xA;    // vec3 vPosition is your vertex's position in world coordinates, in code&#xD;&#xA;    // I mean this -&gt; vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;    // where uModel is your World/Model matrix.&#xD;&#xA;&#xD;&#xA;    float omnidirectionalShadow(in vec3 lightPosition, in float bias, in float darkness, in samplerCube sampler) {&#xD;&#xA;    	vec3 direction = vPosition - lightPosition;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpack(textureCube(sampler, direction)) + bias;&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? darkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here you have a final render of the algorithm&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Have fun coding beautiful graphics, good luck :) &#xD;&#xA;&#xD;&#xA;C.Z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvMHa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3667" PostHistoryTypeId="4" PostId="1788" RevisionGUID="adcd11f7-1316-4aec-aef3-6f91a9884095" CreationDate="2015-12-15T00:25:15.637" UserId="2228" Comment="edited title" Text="WebGL Omnidirectional Shadow Mapping Issue (SOLVED)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3668" PostHistoryTypeId="5" PostId="1807" RevisionGUID="da2aef8a-168d-49a1-a8d5-e39426b575e1" CreationDate="2015-12-15T00:34:22.457" UserId="2228" Comment="added 71 characters in body" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;After a couple of days I realized that **I was computing my projection matrix using a FOV angle in degrees and It should be in radians**. I made the conversion and now everything works great. The interpolation among faces of my depth framebuffer's cubemap is now perfect. For this reason, It is important to handle every single trigonometric function's angle in radians.&#xD;&#xA;&#xD;&#xA;Moreover, I realized that you can compute your view matrix either as I said in the question and in this way:&#xD;&#xA;&#xD;&#xA;    view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;This approach means that your point of view is placed in pointlight's center and you just render in each direction of your cubemap, but which are these directions? well, **these directions are computed adding each target that I've in the switch block (according to each cubemap's face) with your pointlight's position**.&#xD;&#xA; &#xD;&#xA;Furthermore, **It is not necessary to flip Y-Coordinate of the projection matrix**, In this case, It is ok dispatch pointlight's perspective projection matrix to your GLSL shader without scaling It by (1, -1, 1) because **I'm working with textures that don't have a flipped Y-Coordinate**, I think you should flip Y-Coordinate of your pointlight's projection matrix **only if you are working with a flipped texture's Y-Coordinate**, this in order to have a correct omnidirectional shadow mapping effect.&#xD;&#xA;&#xD;&#xA;Finally, I'll leave here the final version of my Omnidirectional Shadow Mapping algorithm on CPU/GPU side. On CPU side I'll explain every step that you have to do in order to compute a correct shadow map for each cubemap's face. On the other hand in GPU side, I'll explain my depth program's vertex/fragment shader and omnidirectional shadow mapping function in my main fragment shader, this in order to help somebody who could be learning this technique, or solve future doubts about this algorithm:&#xD;&#xA;&#xD;&#xA;**CPU**&#xD;&#xA;&#xD;&#xA;      // Binds depth program&#xD;&#xA;       &#xD;&#xA;      program.bind(gl);&#xD;&#xA;&#xD;&#xA;      // For each pointlight source do&#xD;&#xA;&#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Get each pointlight's world position&#xD;&#xA;&#xD;&#xA;        position = light.worldPosition();&#xD;&#xA;    &#xD;&#xA;        // Binds pointlight's depth framebuffer. Besides, in this function,&#xD;&#xA;        // viewport's dimensions are set according to depth framebuffer's dimension.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.bind(gl, this.state);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution have changed, it'll be created again.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;&#xD;&#xA;        for (j = 0; j &lt; 6; j++) {&#xD;&#xA;          switch (j) {&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_X:&#xD;&#xA;              target.set(1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_X:&#xD;&#xA;              target.set(-1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_Y:&#xD;&#xA;              target.set(0, 1, 0);&#xD;&#xA;              up.set(0, 0, 1);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_Y:&#xD;&#xA;              target.set(0, -1, 0);&#xD;&#xA;              up.set(0, 0, -1);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.POSITIVE_Z:&#xD;&#xA;              target.set(0, 0, 1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case EZ3.Cubemap.NEGATIVE_Z:&#xD;&#xA;              target.set(0, 0, -1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          // Creates a view matrix using target and up vectors &#xD;&#xA;          // according to each face of pointlight's cubemap.&#xD;&#xA;    &#xD;&#xA;          view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;          // Attaches cubemap's face to current framebuffer &#xD;&#xA;          // in order to record depth values in that direction.&#xD;&#xA;    &#xD;&#xA;          light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;          // Clears color &amp; depth buffers of your current framebuffer&#xD;&#xA;    &#xD;&#xA;          this.clear();&#xD;&#xA;&#xD;&#xA;          // Render each shadow caster mesh using your depth program&#xD;&#xA;    &#xD;&#xA;          for (k = 0; k &lt; meshes.length; k++)&#xD;&#xA;            this._renderMeshDepth(program, meshes[k], view, light.projection);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;On renderMeshDepth function I've:&#xD;&#xA;&#xD;&#xA;      // Computes pointlight's model-view matrix &#xD;&#xA;&#xD;&#xA;      modelView.mul(view, mesh.world);&#xD;&#xA;&#xD;&#xA;      // I send each matrix to my depth program&#xD;&#xA;    &#xD;&#xA;      program.loadUniformMatrix(gl, 'uModelView', modelView);&#xD;&#xA;      program.loadUniformMatrix(gl, 'uProjection', projection);&#xD;&#xA;    &#xD;&#xA;      // Renders a mesh using vertex buffer objects (VBO)&#xD;&#xA;&#xD;&#xA;      mesh.render(gl, program.attributes, this.state, this.extensions);&#xD;&#xA;&#xD;&#xA;**GPU**&#xD;&#xA;&#xD;&#xA;Depth Program Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Depth Program Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    // The pack function distributes fragment's depth precision storing &#xD;&#xA;    // it throughout (R,G,B,A) color channels and not just R color channel &#xD;&#xA;    // as usual in shadow mapping algorithms. This is because I'm working&#xD;&#xA;    // with textures that have 8-bits for each channel or UNSIGNED_BYTE type.&#xD;&#xA;    &#xD;&#xA;    vec4 pack(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);&#xD;&#xA;    &#xD;&#xA;      vec4 res = fract(depth * bitShift);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      // Packs normalized fragment's Z-Coordinate which is in [0,1] interval.&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = pack(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Omnidirectional Shadow Mapping function in my main fragment shader:&#xD;&#xA;&#xD;&#xA;    // Unpacks fragment's Z-Coordinate which was packed &#xD;&#xA;    // on the depth program's fragment shader.&#xD;&#xA;    &#xD;&#xA;    float unpack(in vec4 color) {&#xD;&#xA;       const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);&#xD;&#xA;       return dot(color, bitShift);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Computes Omnidirectional Shadow Mapping technique using a samplerCube&#xD;&#xA;    // vec3 lightPosition is your pointlight's position in world coordinates.&#xD;&#xA;    // vec3 vPosition is your vertex's position in world coordinates, in code&#xD;&#xA;    // I mean this -&gt; vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;    // where uModel is your World/Model matrix.&#xD;&#xA;&#xD;&#xA;    float omnidirectionalShadow(in vec3 lightPosition, in float bias, in float darkness, in samplerCube sampler) {&#xD;&#xA;    	vec3 direction = vPosition - lightPosition;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpack(textureCube(sampler, direction)) + bias;&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? darkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here you have a final render of the algorithm&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Have fun coding beautiful graphics, good luck :) &#xD;&#xA;&#xD;&#xA;C.Z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvMHa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3669" PostHistoryTypeId="4" PostId="1788" RevisionGUID="b00c31c2-5ca6-406b-8651-5a1187dcccef" CreationDate="2015-12-15T00:39:13.480" UserId="2228" Comment="edited title" Text="WebGL Omnidirectional Shadow Mapping Issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="3670" PostHistoryTypeId="5" PostId="1806" RevisionGUID="14311e59-05ff-45fa-921e-f1fde3c334e4" CreationDate="2015-12-15T02:11:33.433" UserId="1614" Comment="added 2976 characters in body" Text="I think it is commonly accepted that real time is everything that is above interactive. And interactive is defined as &quot;responds to input but is not smooth in the fact that the animation seems jaggy&quot;.  &#xD;&#xA;So real time will depend on the speed of the movements one needs to represent, cinema projects at 24 FPS and is sufficiently real time for many cases.&#xD;&#xA;&#xD;&#xA;Then how many polygons a machine can deal with is easily verifiable by checking for yourself. Just create a little VBO patch as a simple test and a FPS counter, many DirectX or OpenGL samples will give you the perfect test bed for this benchmark.&#xD;&#xA;&#xD;&#xA;You'll find if you have a high end graphics card that you can display about 1 million polygons in real time. However as you said, engines will not claim support so easily because real world scene data will cause a number of performance hogs that is unrelated to polygon count.&#xD;&#xA;&#xD;&#xA;You have:&#xD;&#xA;&#xD;&#xA;- fill rate&#xD;&#xA; - texture sampling&#xD;&#xA; - ROP output&#xD;&#xA;- draw calls&#xD;&#xA;- render target switches&#xD;&#xA;- buffer updates (uniform or other)&#xD;&#xA;- overdraw&#xD;&#xA;- shader complexity&#xD;&#xA;- pipeline complexity (any feedback used? iterative geometry shading? occlusion?)&#xD;&#xA;- synch points with CPU (pixel readback?)&#xD;&#xA;- polygon richness&#xD;&#xA;&#xD;&#xA;Depending on the weak and strong points of a particlar graphic card, one or another of these points is going to be the bottleneck. it's not like you can say for sure &quot;here, that's the one&quot;.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I wanted to add that, one cannot use the GFlops spec figure of one specific card and map it linearly to polygon pushing capacity. Because of the fact that polygon treatment has to sip through a sequential bottleneck in the graphics pipeline as explained in great details here:  [https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/][1]  &#xD;&#xA;TLDR: the vertices has to fit into a small cache before primitive assembly which is natively a sequential thing (the vertex buffer order matters).  &#xD;&#xA;&#xD;&#xA;If you compare the geforce 7800 (9yr old?) to this year's 980, it seems the number of operations per second it is capable of has increased one thousand fold. But you can bet your sister's bra that it's not going to push polygons a thousand times faster (which would be around 200 billion a second by this simple metric).&#xD;&#xA;&#xD;&#xA;EDIT2:&#xD;&#xA;&#xD;&#xA;To answer the question &quot;what can one do to optimize an engine&quot;, as in &quot;not to lose too much efficiency in state switches and other overheads&quot;.  &#xD;&#xA;That is a question as old as engines themselves. And is becoming more complex as history progress.  &#xD;&#xA;&#xD;&#xA;Indeed in real world situation, a typical scene data will contain many materials, many textures, many different shaders, many render targets and passes, and many vertex buffers and so on. One engine I worked with worked with the notion of packets:&#xD;&#xA;&#xD;&#xA;one packet is what can be rendered with one draw call.  &#xD;&#xA;It contains identifiers to:&#xD;&#xA;&#xD;&#xA;- vertex buffer&#xD;&#xA;- index buffer&#xD;&#xA;- camera (gives the pass and render target)&#xD;&#xA;- material id (gives shader, textures and UBO)&#xD;&#xA;- distance to eye&#xD;&#xA;- is visible&#xD;&#xA;&#xD;&#xA;So the first step of each frame is to run a quick sort on the packet list using a sort function with an operator that gives priority to visibility, then pass, then material, then geometry and finally distance.&#xD;&#xA;&#xD;&#xA;drawing close objects gets prirority to maximize early Z culling.  &#xD;&#xA;passes are fixed steps, so we have no choice but to respect them.  &#xD;&#xA;material is the most expensive thing to state-switch after render targets.  &#xD;&#xA;&#xD;&#xA;Even in-between different materials IDs, a sub-ordering can been made using a heuristical criterion to diminish the number of shader changes (most expensive within material state-switch operations), and secondly texture binding changes.  &#xD;&#xA;&#xD;&#xA;After all this ordering, one can apply, mega texturing, virtual texturing, and attribute-less rendering ([link][2]) it deemed necessary.  &#xD;&#xA;&#xD;&#xA;About engine API also one common thing is to defer the issuing of the state-setting commands required by the client. If a client requests &quot;set camera 0&quot;, it is best to just store this request and if later the client calls &quot;set camera 1&quot; but with no other commands in between, the engine can detect the uselessness of the first command and drop it. This is redundancy elimination, which is possible by using a &quot;fully retained&quot; paradigm. By opposition to &quot;immediate&quot; paradigm, which would be just a wrapper above the native API and issue the commands right as ordered by client code. ([example: virtrev][3])&#xD;&#xA;&#xD;&#xA;And finally, with modern hardware, a very expensive (to develop), but potentially highly rewarding step to take is to switch API to metal/mantle/DX12-style and preparing the rendering commands by hand.  &#xD;&#xA;&#xD;&#xA;An engine that prepares rendering commands creates a buffer that holds &quot;command list&quot; that is overwritten at each frame.&#xD;&#xA;&#xD;&#xA;Usually there is a notion of frame &quot;budget&quot;, a game can afford. You need to do everything in 16 milliseconds, so you clearly partition GPU time &quot;2 ms for lightpre pass&quot;, &quot;4 ms for materials pass&quot;, &quot;6 ms for indirect lighting&quot;, &quot;4 ms for postprocesses&quot;...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/&#xD;&#xA;  [2]: http://renderingpipeline.com/2012/03/are-vertex-shaders-obsolete/&#xD;&#xA;  [3]: http://virtrev.git.sourceforge.net/git/gitweb.cgi?p=virtrev/virtrev;a=tree;f=coding/opencl_opengl_sharing/src;hb=HEAD" ContentLicense="CC BY-SA 3.0" />
  <row Id="3671" PostHistoryTypeId="5" PostId="1788" RevisionGUID="8cc0be0b-4c54-493c-b20f-3aecf62cf895" CreationDate="2015-12-15T02:12:45.093" UserId="2228" Comment="deleted 56 characters in body" Text="First of all, I want to say that I've read a lot of post about shadow mapping using depth maps and cubemaps and I understand how they work and also, I have working experience with them using OpenGL, but, I have an issue implementing Omnidirectional Shadow Mapping technique using a single point light source in my 3D graphics engine named &quot;EZ3&quot;. My engine uses WebGL as a 3D graphics API and JavaScript as programming language, this is for my bachelor's thesis in Computer Science. &#xD;&#xA;&#xD;&#xA;Basically this is how I've implemented my shadow mapping algorithm, but I'll only focus on point lights case because with them I can archive omnidirectional shadow mapping.&#xD;&#xA;&#xD;&#xA;First, I active front-face culling like this:&#xD;&#xA;&#xD;&#xA;    if (this.state.faceCulling !== Material.FRONT) {&#xD;&#xA;        if (this.state.faceCulling === Material.NONE)&#xD;&#xA;          gl.enable(gl.CULL_FACE);&#xD;&#xA;    &#xD;&#xA;        gl.cullFace(gl.FRONT);&#xD;&#xA;        this.state.faceCulling = Material.FRONT;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;Second, I create a depth program in order to record depth values for each cubemap face, this is my depth program code in GLSL 1.0:&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    vec4 packDepth(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);&#xD;&#xA;      vec4 res = mod(depth * bitShift * vec4(255), vec4(256)) / vec4(255);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_FragData[0] = packDepth(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Third, this is my JavaScript function's body that &quot;archives&quot; omnidirectional shadow mapping&#xD;&#xA;&#xD;&#xA;    program.bind(gl);&#xD;&#xA;    &#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Updates pointlight's projection matrix&#xD;&#xA;        &#xD;&#xA;        light.updateProjection();&#xD;&#xA;&#xD;&#xA;        // Binds point light's depth framebuffer&#xD;&#xA;    &#xD;&#xA;        light.depthFramebuffer.bind(gl);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution changes, it'll be created again.&#xD;&#xA;    &#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Sets viewport dimensions with depth framebuffer's dimensions&#xD;&#xA;        &#xD;&#xA;        this.viewport(new Vector2(), light.depthFramebuffer.size);&#xD;&#xA;    &#xD;&#xA;        if (light instanceof PointLight) {&#xD;&#xA;    &#xD;&#xA;          up = new Vector3();&#xD;&#xA;          view = new Matrix4();&#xD;&#xA;          origin = new Vector3();&#xD;&#xA;          target = new Vector3();&#xD;&#xA;    &#xD;&#xA;          for (j = 0; j &lt; 6; j++) {&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;    &#xD;&#xA;            switch (j) {&#xD;&#xA;              case Cubemap.POSITIVE_X:&#xD;&#xA;                target.set(1, 0, 0);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;              case Cubemap.NEGATIVE_X:&#xD;&#xA;                target.set(-1, 0, 0);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;              case Cubemap.POSITIVE_Y:&#xD;&#xA;                target.set(0, 1, 0);&#xD;&#xA;                up.set(0, 0, 1);&#xD;&#xA;                break;&#xD;&#xA;              case Cubemap.NEGATIVE_Y:&#xD;&#xA;                target.set(0, -1, 0);&#xD;&#xA;                up.set(0, 0, -1);&#xD;&#xA;                break;&#xD;&#xA;              case Cubemap.POSITIVE_Z:&#xD;&#xA;                target.set(0, 0, 1);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;              case Cubemap.NEGATIVE_Z:&#xD;&#xA;                target.set(0, 0, -1);&#xD;&#xA;                up.set(0, -1, 0);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;        // Creates a view matrix using target and up vectors according to each face of pointlight's&#xD;&#xA;        // cubemap. Furthermore, I translate it in minus light position in order to place&#xD;&#xA;        // the point light in the world's origin and render each cubemap's face at this &#xD;&#xA;        // point of view&#xD;&#xA;&#xD;&#xA;            view.lookAt(origin, target, up);&#xD;&#xA;            view.mul(new EZ3.Matrix4().translate(light.position.clone().negate()));&#xD;&#xA;&#xD;&#xA;        // Flips the Y-coordinate of each cubemap face&#xD;&#xA;        // scaling the projection matrix by (1, -1, 1).&#xD;&#xA;&#xD;&#xA;        // This is a perspective projection matrix which has:&#xD;&#xA;        // 90 degress of FOV.&#xD;&#xA;        // 1.0 of aspect ratio.&#xD;&#xA;        // Near clipping plane at 0.01.&#xD;&#xA;        // Far clipping plane at 2000.0.&#xD;&#xA;&#xD;&#xA;            projection = light.projection.clone();&#xD;&#xA;            projection.scale(new EZ3.Vector3(1, -1, 1));&#xD;&#xA;&#xD;&#xA;        // Attaches a cubemap face to current framebuffer in order to record depth values for the face with this line&#xD;&#xA;        // gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + j, id, 0);&#xD;&#xA;    &#xD;&#xA;            light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;        // Clears current framebuffer's color with these lines:&#xD;&#xA;        // gl.clearColor(1.0,1.0,1.0,1.0);&#xD;&#xA;        // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;            this.clear(color);&#xD;&#xA;&#xD;&#xA;        // Renders shadow caster meshes using the depth program&#xD;&#xA;    &#xD;&#xA;            for (k = 0; k &lt; shadowCasters.length; k++)&#xD;&#xA;              this._renderShadowCaster(shadowCasters[k], program, view, projection);&#xD;&#xA;          }&#xD;&#xA;        } else {&#xD;&#xA;           // Directional light &amp; Spotlight case ...&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;Fourth, this is how I compute Omnidirectional Shadow Mapping using my depth cubemap in my main Vertex Shader &amp; Fragment Shader:&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;&#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModel;&#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    varying vec3 vPosition;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;   &#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader:&#xD;&#xA;&#xD;&#xA;    float unpackDepth(in vec4 color) {&#xD;&#xA;    	return dot(color, vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0 ));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float pointShadow(const in PointLight light, const in samplerCube shadowSampler) {&#xD;&#xA;    	vec3 direction = vPosition - light.position;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpackDepth(textureCube(shadowSampler, direction));&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? light.shadowDarkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Finally, this is the result that I'm getting , my scene has a plane, a cube and a sphere. Besides, the red bright sphere is the point light source:&#xD;&#xA;&#xD;&#xA;[![Omnidirectional Shadow Mapping Issue][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, I seems like point light depth framebuffer's cubemap it is not doing a good interpolation among their faces.&#xD;&#xA;&#xD;&#xA;Until now, I've no idea how to solve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/YM04V.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3672" PostHistoryTypeId="5" PostId="1807" RevisionGUID="3ff1a427-5d81-4e65-a5c7-96e7d4432684" CreationDate="2015-12-15T02:14:56.193" UserId="2228" Comment="deleted 24 characters in body" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;After a couple of days I realized that **I was computing my projection matrix using a FOV angle in degrees and It should be in radians**. I made the conversion and now everything works great. The interpolation among faces of my depth framebuffer's cubemap is now perfect. For this reason, It is important to handle every single trigonometric function's angle in radians.&#xD;&#xA;&#xD;&#xA;Moreover, I realized that you can compute your view matrix either as I said in the question and in this way:&#xD;&#xA;&#xD;&#xA;    view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;This approach means that your point of view is placed in pointlight's center and you just render in each direction of your cubemap, but which are these directions? well, **these directions are computed adding each target that I've in the switch block (according to each cubemap's face) with your pointlight's position**.&#xD;&#xA; &#xD;&#xA;Furthermore, **It is not necessary to flip Y-Coordinate of the projection matrix**, In this case, It is ok dispatch pointlight's perspective projection matrix to your GLSL shader without scaling It by (1, -1, 1) because **I'm working with textures that don't have a flipped Y-Coordinate**, I think you should flip Y-Coordinate of your pointlight's projection matrix **only if you are working with a flipped texture's Y-Coordinate**, this in order to have a correct omnidirectional shadow mapping effect.&#xD;&#xA;&#xD;&#xA;Finally, I'll leave here the final version of my Omnidirectional Shadow Mapping algorithm on CPU/GPU side. On CPU side I'll explain every step that you have to do in order to compute a correct shadow map for each cubemap's face. On the other hand in GPU side, I'll explain my depth program's vertex/fragment shader and omnidirectional shadow mapping function in my main fragment shader, this in order to help somebody who could be learning this technique, or solve future doubts about this algorithm:&#xD;&#xA;&#xD;&#xA;**CPU**&#xD;&#xA;&#xD;&#xA;      // Disable blending and enable front face culling.&#xD;&#xA;&#xD;&#xA;      this.state.disable(gl.BLEND);&#xD;&#xA;    &#xD;&#xA;      this.state.enable(gl.CULL_FACE);&#xD;&#xA;      this.state.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;      // Binds depth program&#xD;&#xA;       &#xD;&#xA;      program.bind(gl);&#xD;&#xA;&#xD;&#xA;      // For each pointlight source do&#xD;&#xA;&#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Get each pointlight's world position&#xD;&#xA;&#xD;&#xA;        position = light.worldPosition();&#xD;&#xA;    &#xD;&#xA;        // Binds pointlight's depth framebuffer. Besides, in this function,&#xD;&#xA;        // viewport's dimensions are set according to depth framebuffer's dimension.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.bind(gl, this.state);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution have changed, it'll be created again.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;&#xD;&#xA;        for (j = 0; j &lt; 6; j++) {&#xD;&#xA;          switch (j) {&#xD;&#xA;            case Cubemap.POSITIVE_X:&#xD;&#xA;              target.set(1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_X:&#xD;&#xA;              target.set(-1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.POSITIVE_Y:&#xD;&#xA;              target.set(0, 1, 0);&#xD;&#xA;              up.set(0, 0, 1);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_Y:&#xD;&#xA;              target.set(0, -1, 0);&#xD;&#xA;              up.set(0, 0, -1);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.POSITIVE_Z:&#xD;&#xA;              target.set(0, 0, 1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_Z:&#xD;&#xA;              target.set(0, 0, -1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          // Creates a view matrix using target and up vectors &#xD;&#xA;          // according to each face of pointlight's cubemap.&#xD;&#xA;    &#xD;&#xA;          view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;          // Attaches cubemap's face to current framebuffer &#xD;&#xA;          // in order to record depth values in that direction.&#xD;&#xA;    &#xD;&#xA;          light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;          // Clears color &amp; depth buffers of your current framebuffer&#xD;&#xA;    &#xD;&#xA;          this.clear();&#xD;&#xA;&#xD;&#xA;          // Render each shadow caster mesh using your depth program&#xD;&#xA;    &#xD;&#xA;          for (k = 0; k &lt; meshes.length; k++)&#xD;&#xA;            this._renderMeshDepth(program, meshes[k], view, light.projection);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;On renderMeshDepth function I've:&#xD;&#xA;&#xD;&#xA;      // Computes pointlight's model-view matrix &#xD;&#xA;&#xD;&#xA;      modelView.mul(view, mesh.world);&#xD;&#xA;&#xD;&#xA;      // I send each matrix to my depth program&#xD;&#xA;    &#xD;&#xA;      program.loadUniformMatrix(gl, 'uModelView', modelView);&#xD;&#xA;      program.loadUniformMatrix(gl, 'uProjection', projection);&#xD;&#xA;    &#xD;&#xA;      // Renders a mesh using vertex buffer objects (VBO)&#xD;&#xA;&#xD;&#xA;      mesh.render(gl, program.attributes, this.state, this.extensions);&#xD;&#xA;&#xD;&#xA;**GPU**&#xD;&#xA;&#xD;&#xA;Depth Program Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Depth Program Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    // The pack function distributes fragment's depth precision storing &#xD;&#xA;    // it throughout (R,G,B,A) color channels and not just R color channel &#xD;&#xA;    // as usual in shadow mapping algorithms. This is because I'm working&#xD;&#xA;    // with textures that have 8-bits for each channel or UNSIGNED_BYTE type.&#xD;&#xA;    &#xD;&#xA;    vec4 pack(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);&#xD;&#xA;    &#xD;&#xA;      vec4 res = fract(depth * bitShift);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      // Packs normalized fragment's Z-Coordinate which is in [0,1] interval.&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = pack(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Omnidirectional Shadow Mapping function in my main fragment shader:&#xD;&#xA;&#xD;&#xA;    // Unpacks fragment's Z-Coordinate which was packed &#xD;&#xA;    // on the depth program's fragment shader.&#xD;&#xA;    &#xD;&#xA;    float unpack(in vec4 color) {&#xD;&#xA;       const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);&#xD;&#xA;       return dot(color, bitShift);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Computes Omnidirectional Shadow Mapping technique using a samplerCube&#xD;&#xA;    // vec3 lightPosition is your pointlight's position in world coordinates.&#xD;&#xA;    // vec3 vPosition is your vertex's position in world coordinates, in code&#xD;&#xA;    // I mean this -&gt; vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;    // where uModel is your World/Model matrix.&#xD;&#xA;&#xD;&#xA;    float omnidirectionalShadow(in vec3 lightPosition, in float bias, in float darkness, in samplerCube sampler) {&#xD;&#xA;    	vec3 direction = vPosition - lightPosition;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpack(textureCube(sampler, direction)) + bias;&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? darkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here you have a final render of the algorithm&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Have fun coding beautiful graphics, good luck :) &#xD;&#xA;&#xD;&#xA;C.Z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvMHa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3673" PostHistoryTypeId="5" PostId="1807" RevisionGUID="653f24d9-1ce9-4816-a1ce-4981db0e86e1" CreationDate="2015-12-15T02:22:02.863" UserId="2228" Comment="deleted 24 characters in body" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;After a couple of days I realized that **I was computing my projection matrix using a FOV angle in degrees and It should be in radians**. I made the conversion and now everything works great. The interpolation among faces of my depth framebuffer's cubemap is now perfect. For this reason, It is important to handle every single trigonometric function's angle in radians.&#xD;&#xA;&#xD;&#xA;Moreover, I realized that you can compute your view matrix either as I said in the question and in this way:&#xD;&#xA;&#xD;&#xA;    view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;This approach means that your point of view is placed in pointlight's center and you just render in each direction of your cubemap, but which are these directions? well, **these directions are computed adding each target that I've in the switch block (according to each cubemap's face) with your pointlight's position**.&#xD;&#xA; &#xD;&#xA;Furthermore, **It is not necessary to flip Y-Coordinate of the projection matrix**, In this case, It is ok dispatch pointlight's perspective projection matrix to your GLSL shader without scaling It by (1, -1, 1) because **I'm working with textures that don't have a flipped Y-Coordinate**, I think you should flip Y-Coordinate of your pointlight's projection matrix **only if you are working with a flipped texture's Y-Coordinate**, this in order to have a correct omnidirectional shadow mapping effect.&#xD;&#xA;&#xD;&#xA;Finally, I'll leave here the final version of my Omnidirectional Shadow Mapping algorithm on CPU/GPU side. On CPU side I'll explain every step that you have to do in order to compute a correct shadow map for each cubemap's face. On the other hand in GPU side, I'll explain my depth program's vertex/fragment shader and omnidirectional shadow mapping function in my main fragment shader, this in order to help somebody who could be learning this technique, or solve future doubts about this algorithm:&#xD;&#xA;&#xD;&#xA;**CPU**&#xD;&#xA;&#xD;&#xA;      // Disable blending and enable front face culling.&#xD;&#xA;&#xD;&#xA;      this.state.disable(gl.BLEND);&#xD;&#xA;    &#xD;&#xA;      this.state.enable(gl.CULL_FACE);&#xD;&#xA;      this.state.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;      // Binds depth program&#xD;&#xA;       &#xD;&#xA;      program.bind(gl);&#xD;&#xA;&#xD;&#xA;      // For each pointlight source do&#xD;&#xA;&#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Get each pointlight's world position&#xD;&#xA;&#xD;&#xA;        position = light.worldPosition();&#xD;&#xA;    &#xD;&#xA;        // Binds pointlight's depth framebuffer. Besides, in this function,&#xD;&#xA;        // viewport's dimensions are set according to depth framebuffer's dimension.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.bind(gl, this.state);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution have changed, it'll be created again.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;&#xD;&#xA;        for (j = 0; j &lt; 6; j++) {&#xD;&#xA;          switch (j) {&#xD;&#xA;            case Cubemap.POSITIVE_X:&#xD;&#xA;              target.set(1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_X:&#xD;&#xA;              target.set(-1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.POSITIVE_Y:&#xD;&#xA;              target.set(0, 1, 0);&#xD;&#xA;              up.set(0, 0, 1);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_Y:&#xD;&#xA;              target.set(0, -1, 0);&#xD;&#xA;              up.set(0, 0, -1);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.POSITIVE_Z:&#xD;&#xA;              target.set(0, 0, 1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_Z:&#xD;&#xA;              target.set(0, 0, -1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          // Creates a view matrix using target and up vectors &#xD;&#xA;          // according to each face of pointlight's cubemap.&#xD;&#xA;    &#xD;&#xA;          view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;          // Attaches cubemap's face to current framebuffer &#xD;&#xA;          // in order to record depth values in that direction.&#xD;&#xA;    &#xD;&#xA;          light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;          // Clears color &amp; depth buffers of your current framebuffer&#xD;&#xA;    &#xD;&#xA;          this.clear();&#xD;&#xA;&#xD;&#xA;          // Render each shadow caster mesh using your depth program&#xD;&#xA;    &#xD;&#xA;          for (k = 0; k &lt; meshes.length; k++)&#xD;&#xA;            this._renderMeshDepth(program, meshes[k], view, light.projection);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;On renderMeshDepth function I've:&#xD;&#xA;&#xD;&#xA;      // Computes pointlight's model-view matrix &#xD;&#xA;&#xD;&#xA;      modelView.mul(view, mesh.world);&#xD;&#xA;&#xD;&#xA;      // I send each matrix to my depth program&#xD;&#xA;    &#xD;&#xA;      program.loadUniformMatrix(gl, 'uModelView', modelView);&#xD;&#xA;      program.loadUniformMatrix(gl, 'uProjection', projection);&#xD;&#xA;    &#xD;&#xA;      // Renders a mesh using vertex buffer objects (VBO)&#xD;&#xA;&#xD;&#xA;      mesh.render(gl, program.attributes, this.state, this.extensions);&#xD;&#xA;&#xD;&#xA;**GPU**&#xD;&#xA;&#xD;&#xA;Depth Program Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Depth Program Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    // The pack function distributes fragment's depth precision storing &#xD;&#xA;    // it throughout (R,G,B,A) color channels and not just R color channel &#xD;&#xA;    // as usual in shadow mapping algorithms. This is because I'm working&#xD;&#xA;    // with 8-bit textures and one color channel hasn't enough precision &#xD;&#xA;    // to store a depth value.&#xD;&#xA;    &#xD;&#xA;    vec4 pack(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);&#xD;&#xA;    &#xD;&#xA;      vec4 res = fract(depth * bitShift);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      // Packs normalized fragment's Z-Coordinate which is in [0,1] interval.&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = pack(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Omnidirectional Shadow Mapping function in my main fragment shader:&#xD;&#xA;&#xD;&#xA;    // Unpacks fragment's Z-Coordinate which was packed &#xD;&#xA;    // on the depth program's fragment shader.&#xD;&#xA;    &#xD;&#xA;    float unpack(in vec4 color) {&#xD;&#xA;       const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);&#xD;&#xA;       return dot(color, bitShift);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Computes Omnidirectional Shadow Mapping technique using a samplerCube&#xD;&#xA;    // vec3 lightPosition is your pointlight's position in world coordinates.&#xD;&#xA;    // vec3 vPosition is your vertex's position in world coordinates, in code&#xD;&#xA;    // I mean this -&gt; vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;    // where uModel is your World/Model matrix.&#xD;&#xA;&#xD;&#xA;    float omnidirectionalShadow(in vec3 lightPosition, in float bias, in float darkness, in samplerCube sampler) {&#xD;&#xA;    	vec3 direction = vPosition - lightPosition;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpack(textureCube(sampler, direction)) + bias;&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? darkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here you have a final render of the algorithm&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Have fun coding beautiful graphics, good luck :) &#xD;&#xA;&#xD;&#xA;C.Z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvMHa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3678" PostHistoryTypeId="2" PostId="1809" RevisionGUID="f99659b8-03a8-4548-88f3-e047763503d6" CreationDate="2015-12-15T18:51:57.800" UserId="88" Text="I thought I had formed a general understanding of how OpenGL naming conventions and extensions worked, until I stumbled upon a case that confused me.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here's my understanding so far:&#xD;&#xA;&#xD;&#xA;**No suffix** -- e.g. `glGenBuffers()`. This function is a part of the core profile. The [wiki page](https://www.opengl.org/wiki/GLAPI/glGenBuffers) tells me that this was added to the core profile starting from version 1.5.&#xD;&#xA;&#xD;&#xA;**ARB** -- e.g. `glGenBuffersARB()`. This function is part of the standardized `GL_ARB_vertex_buffer_object` extension. The [spec](https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt) of this extension clearly declares `GenBuffersARB()` in the &quot;New Procedures and Functions&quot; section. The &quot;Dependencies&quot; section tells me that I can potentially access this from a 1.4+ context, if the hardware supports the extension.&#xD;&#xA;&#xD;&#xA;**EXT** -- These are vendor-specific extensions and functions that only some vendors may support. Vertex buffer object doesn't seem to have an EXT extension in the registry.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here's where my understanding breaks down:&#xD;&#xA;&#xD;&#xA;`glGenFramebuffers`, as the [wiki](https://www.opengl.org/wiki/GLAPI/glGenFramebuffers) shows, was added to the core in 3.0.&#xD;&#xA;&#xD;&#xA;Now I want to access the frame buffer features at a lower core profile version than 3.0. So I want to use it as an extension. The spec registry tells me that there are two available extensions - [ARB](https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt) and [EXT](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt).&#xD;&#xA;&#xD;&#xA;**Question 1** -- If an ARB extension exists, why does an EXT extension exist? Wouldn't you always choose the standardized one over the vendor-specific one?&#xD;&#xA;&#xD;&#xA;A look at the ARB spec in the &quot;New procedures and functions&quot; section tells me that the extension defines the `GenRenderbuffers()` function. No ARB suffix this time. GLEW doesn't have a function prototype for `GenRenderbuffersARB()` at all. Weird.&#xD;&#xA;&#xD;&#xA;The EXT spec does however have a `GenRenderbuffersEXT()` function in the new functions section.&#xD;&#xA;&#xD;&#xA;**Question 2** -- Why no ARB suffix if there's an EXT suffix? How does this work for ARB, given that the names of the ARB function and the core function are the same? &#xD;&#xA;&#xD;&#xA;**Question 3** -- I ultimately want Framebuffer features from a 1.4 profile. Which extension and which function-set should I use so that I get maximum hardware compatibility coverage?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3679" PostHistoryTypeId="1" PostId="1809" RevisionGUID="f99659b8-03a8-4548-88f3-e047763503d6" CreationDate="2015-12-15T18:51:57.800" UserId="88" Text="OpenGL compatibility, naming conventions and ARB vs EXT" ContentLicense="CC BY-SA 3.0" />
  <row Id="3680" PostHistoryTypeId="3" PostId="1809" RevisionGUID="f99659b8-03a8-4548-88f3-e047763503d6" CreationDate="2015-12-15T18:51:57.800" UserId="88" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3681" PostHistoryTypeId="5" PostId="1809" RevisionGUID="3f06bb76-00af-4e33-8a58-ab4150e7c6d7" CreationDate="2015-12-15T18:58:07.407" UserId="88" Comment="added 46 characters in body" Text="I thought I had formed a general understanding of how OpenGL naming conventions and extensions worked, until I stumbled upon a case that confused me.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here's my understanding so far:&#xD;&#xA;&#xD;&#xA;**No suffix** -- e.g. `glGenBuffers()`. This function is a part of the core profile. The [wiki page](https://www.opengl.org/wiki/GLAPI/glGenBuffers) tells me that this was added to the core profile starting from version 1.5.&#xD;&#xA;&#xD;&#xA;**ARB** -- e.g. `glGenBuffersARB()`. This function is part of the standardized `GL_ARB_vertex_buffer_object` extension. The [spec](https://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt) of this extension clearly declares `GenBuffersARB()` in the &quot;New Procedures and Functions&quot; section. The &quot;Dependencies&quot; section tells me that I can potentially access this from a 1.4+ context, if the hardware supports the extension.&#xD;&#xA;&#xD;&#xA;**EXT** -- These are vendor-specific extensions and functions that only some vendors may support. Vertex buffer object doesn't seem to have an EXT extension in the registry.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here's where my understanding breaks down:&#xD;&#xA;&#xD;&#xA;`glGenFramebuffers`, as the [wiki](https://www.opengl.org/wiki/GLAPI/glGenFramebuffers) shows, was added to the core in 3.0.&#xD;&#xA;&#xD;&#xA;Now I want to access the frame buffer features at a lower core profile version than 3.0. So I want to use it as an extension. The spec registry tells me that there are two available extensions - [ARB](https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt) and [EXT](https://www.opengl.org/registry/specs/EXT/framebuffer_object.txt).&#xD;&#xA;&#xD;&#xA;**Question 1** -- If an ARB extension exists, why does an EXT extension exist? Wouldn't you always choose the standardized one over the vendor-specific one?&#xD;&#xA;&#xD;&#xA;A look at the ARB spec in the &quot;New procedures and functions&quot; section tells me that the extension defines the `GenRenderbuffers()` function. No ARB suffix this time. GLEW doesn't have a function prototype for `glGenRenderbuffersARB()` at all. Weird.&#xD;&#xA;&#xD;&#xA;The EXT spec does however have a `GenRenderbuffersEXT()` function in the new functions section, and GLEW also has`glGenRenderbuffersEXT()`.&#xD;&#xA;&#xD;&#xA;**Question 2** -- Why no ARB suffix if there's an EXT suffix? How does this work for ARB, given that the names of the ARB function and the core function are the same? &#xD;&#xA;&#xD;&#xA;**Question 3** -- I ultimately want Framebuffer features from a 1.4 profile. Which extension and which function-set should I use so that I get maximum hardware compatibility coverage?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3685" PostHistoryTypeId="2" PostId="1811" RevisionGUID="b2028843-109c-4453-9ea7-9820fe63cc06" CreationDate="2015-12-16T01:03:39.430" UserId="40" Text="**Question 1** -- Usually the EXT version comes first as a collaboration between two or more vendors. ARB extensions require more discussion among voting members of Khronos and can have changes from the EXT version before getting approved. See the GL_ARB_direct_state_access extension which has many changes compared to GL_EXT_direct_state_access.&#xD;&#xA;&#xD;&#xA;**Question 2** --&#xD;&#xA;The Issues section of the GL_ARB_framebuffer_object extension states why the functions do not have ARB suffixes:&#xD;&#xA;&#xD;&#xA;&gt; (8) Why don't the new tokens and entry points in this extension have suffixes like other ARB extensions?&#xD;&#xA;&gt;&#xD;&#xA;&gt;        RESOLVED: Unlike most ARB extensions, this is a strict subset of&#xD;&#xA;&gt;        functionality already approved in OpenGL 3.0. This extension&#xD;&#xA;&gt;        exists only to support that functionality on older hardware that&#xD;&#xA;&gt;        cannot implement a full OpenGL 3.0 driver. Since there are no&#xD;&#xA;&gt;        possible behavior changes between the ARB extension and core&#xD;&#xA;&gt;        features, source code compatibility is improved by not using&#xD;&#xA;&gt;        suffixes on the extension.&#xD;&#xA;&#xD;&#xA;**Question 3** --&#xD;&#xA;If you want to use framebuffer objects on a context where the GL version is less than 3.0 you need to look at the extension string:&#xD;&#xA;&#xD;&#xA;1. If GL_ARB_framebuffer_object is supported, use the non ARB functions.&#xD;&#xA;2. If only GL_EXT_framebuffer_object is supported, use the EXT functions.&#xD;&#xA;3. If neither extension are supported, you need to fall back to OS level offscreen rendering like pbuffers." ContentLicense="CC BY-SA 3.0" />
  <row Id="3702" PostHistoryTypeId="5" PostId="1806" RevisionGUID="4fcf4ae7-4599-44ea-95fa-d6f623f0c41e" CreationDate="2015-12-17T12:49:21.307" UserId="231" Comment="Minor tidying" Text="I think it is commonly accepted that real time is everything that is above interactive. And interactive is defined as &quot;responds to input but is not smooth in the fact that the animation seems jaggy&quot;.  &#xD;&#xA;So real time will depend on the speed of the movements one needs to represent. Cinema projects at 24 FPS and is sufficiently real time for many cases.&#xD;&#xA;&#xD;&#xA;Then how many polygons a machine can deal with is easily verifiable by checking for yourself. Just create a little VBO patch as a simple test and a FPS counter, many DirectX or OpenGL samples will give you the perfect test bed for this benchmark.&#xD;&#xA;&#xD;&#xA;You'll find if you have a high end graphics card that you can display about 1 million polygons in real time. However, as you said, engines will not claim support so easily because real world scene data will cause a number of performance hogs that are unrelated to polygon count.&#xD;&#xA;&#xD;&#xA;You have:&#xD;&#xA;&#xD;&#xA;- fill rate&#xD;&#xA; - texture sampling&#xD;&#xA; - ROP output&#xD;&#xA;- draw calls&#xD;&#xA;- render target switches&#xD;&#xA;- buffer updates (uniform or other)&#xD;&#xA;- overdraw&#xD;&#xA;- shader complexity&#xD;&#xA;- pipeline complexity (any feedback used? iterative geometry shading? occlusion?)&#xD;&#xA;- synch points with CPU (pixel readback?)&#xD;&#xA;- polygon richness&#xD;&#xA;&#xD;&#xA;Depending on the weak and strong points of a particular graphic card, one or another of these points is going to be the bottleneck. It's not like you can say for sure &quot;there, that's the one&quot;.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I wanted to add that, one cannot use the GFlops spec figure of one specific card and map it linearly to polygon pushing capacity. Because of the fact that polygon treatment has to go through a sequential bottleneck in the graphics pipeline as explained in great detail here:  [https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/][1]  &#xD;&#xA;TLDR: the vertices have to fit into a small cache before primitive assembly which is natively a sequential thing (the vertex buffer order matters).  &#xD;&#xA;&#xD;&#xA;If you compare the GeForce 7800 (9yr old?) to this year's 980, it seems the number of operations per second it is capable of has increased one thousand fold. But you can bet that it's not going to push polygons a thousand times faster (which would be around 200 billion a second by this simple metric).&#xD;&#xA;&#xD;&#xA;EDIT2:&#xD;&#xA;&#xD;&#xA;To answer the question &quot;what can one do to optimize an engine&quot;, as in &quot;not to lose too much efficiency in state switches and other overheads&quot;.  &#xD;&#xA;That is a question as old as engines themselves. And is becoming more complex as history progress.  &#xD;&#xA;&#xD;&#xA;Indeed in real world situation, typical scene data will contain many materials, many textures, many different shaders, many render targets and passes, and many vertex buffers and so on. One engine I worked with worked with the notion of packets:&#xD;&#xA;&#xD;&#xA;One packet is what can be rendered with one draw call.  &#xD;&#xA;It contains identifiers to:&#xD;&#xA;&#xD;&#xA;- vertex buffer&#xD;&#xA;- index buffer&#xD;&#xA;- camera (gives the pass and render target)&#xD;&#xA;- material id (gives shader, textures and UBO)&#xD;&#xA;- distance to eye&#xD;&#xA;- is visible&#xD;&#xA;&#xD;&#xA;So the first step of each frame is to run a quick sort on the packet list using a sort function with an operator that gives priority to visibility, then pass, then material, then geometry and finally distance.&#xD;&#xA;&#xD;&#xA;Drawing close objects gets prirority to maximize early Z culling.  &#xD;&#xA;Passes are fixed steps, so we have no choice but to respect them.  &#xD;&#xA;Material is the most expensive thing to state-switch after render targets.  &#xD;&#xA;&#xD;&#xA;Even in-between different materials IDs, a sub-ordering can been made using a heuristical criterion to diminish the number of shader changes (most expensive within material state-switch operations), and secondly texture binding changes.  &#xD;&#xA;&#xD;&#xA;After all this ordering, one can apply mega texturing, virtual texturing, and attribute-less rendering ([link][2]) if deemed necessary.  &#xD;&#xA;&#xD;&#xA;About engine API also one common thing is to defer the issuing of the state-setting commands required by the client. If a client requests &quot;set camera 0&quot;, it is best to just store this request and if later the client calls &quot;set camera 1&quot; but with no other commands in between, the engine can detect the uselessness of the first command and drop it. This is redundancy elimination, which is possible by using a &quot;fully retained&quot; paradigm. By opposition to &quot;immediate&quot; paradigm, which would be just a wrapper above the native API and issue the commands right as ordered by client code. ([example: virtrev][3])&#xD;&#xA;&#xD;&#xA;And finally, with modern hardware, a very expensive (to develop), but potentially highly rewarding step to take is to switch API to metal/mantle/DX12-style and preparing the rendering commands by hand.  &#xD;&#xA;&#xD;&#xA;An engine that prepares rendering commands creates a buffer that holds a &quot;command list&quot; that is overwritten at each frame.&#xD;&#xA;&#xD;&#xA;Usually there is a notion of frame &quot;budget&quot;, a game can afford. You need to do everything in 16 milliseconds, so you clearly partition GPU time &quot;2 ms for lightpre pass&quot;, &quot;4 ms for materials pass&quot;, &quot;6 ms for indirect lighting&quot;, &quot;4 ms for postprocesses&quot;...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/&#xD;&#xA;  [2]: http://renderingpipeline.com/2012/03/are-vertex-shaders-obsolete/&#xD;&#xA;  [3]: http://virtrev.git.sourceforge.net/git/gitweb.cgi?p=virtrev/virtrev;a=tree;f=coding/opencl_opengl_sharing/src;hb=HEAD" ContentLicense="CC BY-SA 3.0" />
  <row Id="3705" PostHistoryTypeId="2" PostId="1815" RevisionGUID="a436d23f-6753-4580-8aeb-5d692d1f6d45" CreationDate="2015-12-18T13:45:43.347" UserId="2173" Text="I computed a Voronoï diagram from a set of point (with [Boost.polygon](http://www.boost.org/doc/libs/1_60_0/libs/polygon/doc/voronoi_diagram.htm)). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I try to find a Delaunay triangulation, connecting each cell center for each Voronoï edge, but I miss some edges.&#xD;&#xA;&#xD;&#xA;In the following image, the red dots are my initial points, the blue lines are the Voronoï edges (I ignored infinite edges), and the green lines are the triangulation edges (on green edge for each blue edge, connecting two cell origins).&#xD;&#xA;&#xD;&#xA;We can see that diagonal edges are missing. What am I missing?&#xD;&#xA;&#xD;&#xA;[![voronoi diagram][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JXNcc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3706" PostHistoryTypeId="1" PostId="1815" RevisionGUID="a436d23f-6753-4580-8aeb-5d692d1f6d45" CreationDate="2015-12-18T13:45:43.347" UserId="2173" Text="How to triangulate from a Voronoï diagram?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3707" PostHistoryTypeId="3" PostId="1815" RevisionGUID="a436d23f-6753-4580-8aeb-5d692d1f6d45" CreationDate="2015-12-18T13:45:43.347" UserId="2173" Text="|triangulation|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3708" PostHistoryTypeId="5" PostId="1815" RevisionGUID="563be5d1-8caa-40f6-8385-6ec77655ab27" CreationDate="2015-12-18T17:47:13.000" UserId="231" Comment="Minor tidying" Text="I computed a Voronoï diagram from a set of points (with [Boost.polygon]). &#xD;&#xA;&#xD;&#xA;I try to find a Delaunay triangulation, connecting each cell center for each Voronoï edge, but I miss some edges.&#xD;&#xA;&#xD;&#xA;In the following image, the red dots are my initial points, the blue lines are the Voronoï edges (I ignored infinite edges), and the green lines are the triangulation edges (one green edge for each blue edge, connecting two cell origins).&#xD;&#xA;&#xD;&#xA;We can see that diagonal edges are missing. What am I missing?&#xD;&#xA;&#xD;&#xA;[![voronoi diagram][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JXNcc.png&#xD;&#xA;  [Boost.polygon]: http://www.boost.org/doc/libs/1_60_0/libs/polygon/doc/voronoi_diagram.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="3709" PostHistoryTypeId="2" PostId="1816" RevisionGUID="a1c5d924-ce39-4ba0-bb66-f5b76571054f" CreationDate="2015-12-18T20:44:40.927" UserId="16" Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 can only happen when two vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3710" PostHistoryTypeId="5" PostId="1816" RevisionGUID="f4d6532d-421c-4cf0-a8cd-406bf9eb9e93" CreationDate="2015-12-18T20:52:55.610" UserId="16" Comment="added 186 characters in body" Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3711" PostHistoryTypeId="5" PostId="1816" RevisionGUID="a7c00ec6-a7a1-4920-b490-2984e19d5e7e" CreationDate="2015-12-18T21:08:31.020" UserId="16" Comment="added 639 characters in body" Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These animations also show that (even in a non-degenerate case), the corresponding Voronoi and Delaunay edges do not necessarily actually cross within their finite extent. That might make it harder to see that the 2 (or 3) edges that triangulate the regular polygon at the end actually correspond to several degenerate edges which are all at the centre. Also note that in total there are 5 different triangulations of the pentagon and 9 triangulations of the hexagon.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/5DgNy.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/AddyS.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3712" PostHistoryTypeId="5" PostId="1816" RevisionGUID="143168a5-e776-4a3b-925e-65a69d3f9540" CreationDate="2015-12-18T21:19:09.710" UserId="16" Comment="added 1 character in body" Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These animations also show that (even in a non-degenerate case), the corresponding Voronoi and Delaunay edges do not necessarily actually cross within their finite extent. That might make it harder to see that the 2 (or 3) edges that triangulate the regular polygon at the end actually correspond to several degenerate edges which are all at the centre. Also note that in total there are 5 different triangulations of the pentagon and 14 triangulations of the hexagon.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/5DgNy.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/AddyS.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3713" PostHistoryTypeId="5" PostId="1816" RevisionGUID="25b62ceb-e416-4b4c-8e65-ba0707cb39cc" CreationDate="2015-12-18T23:14:31.383" UserId="16" Comment="added 99 characters in body" Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These animations also show that (even in a non-degenerate case), the corresponding Voronoi and Delaunay edges do not necessarily actually cross within their finite extent. That might make it harder to see that the 2 (or 3) edges that triangulate the regular polygon at the end actually correspond to several degenerate edges which are all at the centre. Also note that in total there are 5 different triangulations of the pentagon and 14 triangulations of the hexagon (although I don't know whether all 14 can be obtained by deforming a non-degenerate triangulation).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/5DgNy.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/AddyS.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3715" PostHistoryTypeId="5" PostId="1816" RevisionGUID="002a15b9-4fd3-408a-844b-642eb6385454" CreationDate="2015-12-19T11:31:59.897" UserId="2173" Comment="Explained how it is possible to get triangles from Voronoï Diagram in boost." Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These animations also show that (even in a non-degenerate case), the corresponding Voronoi and Delaunay edges do not necessarily actually cross within their finite extent. That might make it harder to see that the 2 (or 3) edges that triangulate the regular polygon at the end actually correspond to several degenerate edges which are all at the centre. Also note that in total there are 5 different triangulations of the pentagon and 14 triangulations of the hexagon (although I don't know whether all 14 can be obtained by deforming a non-degenerate triangulation).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;Voronoï diagrams computed with [Boost.polygon](http://www.boost.org/doc/libs/1_60_0/libs/polygon/doc/index.htm) enable to walk through each Voronoï vertices, and each edges linked to those vertices (clockwise or counter clockwise). In this way, it is possible to create one triangle for each pair of edges (two connected edges will link to 3 cells).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/5DgNy.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/AddyS.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3716" PostHistoryTypeId="24" PostId="1816" RevisionGUID="002a15b9-4fd3-408a-844b-642eb6385454" CreationDate="2015-12-19T11:31:59.897" Comment="Proposed by 2173 approved by -1 edit id of 114" ContentLicense="CC BY-SA 3.0" />
  <row Id="3717" PostHistoryTypeId="5" PostId="1816" RevisionGUID="e2acfce3-4d10-4d2e-a0cc-cac9c226895a" CreationDate="2015-12-19T11:31:59.897" UserId="16" Comment="Explained how it is possible to get triangles from Voronoï Diagram in boost." Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you start off with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These animations also show that (even in a non-degenerate case), the corresponding Voronoi and Delaunay edges do not necessarily actually cross within their finite extent. That might make it harder to see that the 2 (or 3) edges that triangulate the regular polygon at the end actually correspond to several degenerate edges which are all at the centre. Also note that in total there are 5 different triangulations of the pentagon and 14 triangulations of the hexagon (although I don't know whether all 14 can be obtained by deforming a non-degenerate triangulation).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit** (by OP)&#xD;&#xA;&#xD;&#xA;Voronoï diagrams computed with [Boost.polygon](http://www.boost.org/doc/libs/1_60_0/libs/polygon/doc/index.htm) enable to walk through each Voronoï vertix, and each edge linked to those vertices (clockwise or counter-clockwise). In this way, it is possible to create one triangle for each pair of edges (two connected edges will link to 3 cells).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/5DgNy.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/AddyS.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="3723" PostHistoryTypeId="2" PostId="1818" RevisionGUID="3a715b28-9b5a-4355-8e55-a749cb6600ad" CreationDate="2015-12-21T07:14:25.690" UserId="2308" Text="So I have wondered for awhile.  With opengl and such I can render some pretty amazing looking things in &quot;real time&quot; 60 fps.  However if I was trying to make a video of that same scene in lets say Maya, or 3DS max it would take MUCH MUCH longer for it to render even though it is the same resolution and FPS.&#xD;&#xA;&#xD;&#xA;How come these two types of rendering take different periods of time for the same result.&#xD;&#xA;&#xD;&#xA;Note: Yes I do realize that 3D animation software can produce highly superior images to what could be done real time. But for this question I am referring to a scene of equal complexity." ContentLicense="CC BY-SA 3.0" />
  <row Id="3724" PostHistoryTypeId="1" PostId="1818" RevisionGUID="3a715b28-9b5a-4355-8e55-a749cb6600ad" CreationDate="2015-12-21T07:14:25.690" UserId="2308" Text="Difference between two types of rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="3725" PostHistoryTypeId="3" PostId="1818" RevisionGUID="3a715b28-9b5a-4355-8e55-a749cb6600ad" CreationDate="2015-12-21T07:14:25.690" UserId="2308" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3726" PostHistoryTypeId="2" PostId="1819" RevisionGUID="d267fdae-3825-4099-b6d3-45445b705d3b" CreationDate="2015-12-21T09:30:23.303" UserId="239" Text="The main difference would be that with OpenGL in lets say a video game you will have a process called *rasterization* which basically takes care of determining what part of the scene you see.&#xD;&#xA;&#xD;&#xA;It needs to be fast so we can experience it as realtime.&#xD;&#xA;&#xD;&#xA;Therefore the algorithm does a few simple steps.&#xD;&#xA;&#xD;&#xA; * check if a certain part of the scene is in my view frustum&#xD;&#xA;&#xD;&#xA;[![Frustum Culling][1]][1]&#xD;&#xA;&#xD;&#xA; * check if something is in front of it which may needs to be rendered later using a depth buffer&#xD;&#xA;&#xD;&#xA;[![Depth Buffer][2]][2]&#xD;&#xA;&#xD;&#xA; * order the objects we found to draw &#xD;&#xA; * *draw them* by projecting them on the screen&#xD;&#xA; * *shade them* based on textures / Shaders / lights / ...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On the other hand a rendering software (Blender/Max/Maya/...) most likely uses some kind of *raytracing*&#xD;&#xA;&#xD;&#xA;This involves alot more math to achieve a higher degree of realism.&#xD;&#xA;It basically works in the same way :&#xD;&#xA;&#xD;&#xA;* create a camera and an image plane infront of it&#xD;&#xA;* shoot one ray (or multiple sample rays) through each pixel&#xD;&#xA;* check if the ray hits anything in the scene&#xD;&#xA;* closest hit is the one to be drawn in the pixel finally (like depth buffer)&#xD;&#xA;* calculate the light for the given point&#xD;&#xA;[![Light Calculation][3]][3]&#xD;&#xA;&#xD;&#xA;....&#xD;&#xA;&#xD;&#xA;I'll stopped listing here since this is the point where raytracing takes of.&#xD;&#xA;&#xD;&#xA;Instead of only checking if a point is hit most raytracer now begin to calculate: &#xD;&#xA;&#xD;&#xA;* the amount of light a surface penetrates&#xD;&#xA;* how much light gets reflected&#xD;&#xA;* cast new rays from the hitpoint into the scene until it may hit a light source&#xD;&#xA;&#xD;&#xA;There are a ton of techniques with different degrees of realism which can be used to calculate the light of a certain point in the scene.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;The gist would be that a raytracer mostly tries to be physically accurate when it comes the lighting and therefore has a lot of more calculations to do per pixel ( sometimes shoot thousands of rays ) and on the other hand games get their speed by drawing bigger chunks of the screen with simpler light calculations and a lot of shader tricks which let it look realistic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TqkCF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7N5cL.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/jmB0K.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3727" PostHistoryTypeId="5" PostId="1818" RevisionGUID="4f08cd33-2e16-490b-bcf2-9893b6ca698b" CreationDate="2015-12-21T10:50:34.440" UserId="127" Comment="Edited title, corrected capitalization, edited tags" Text="With OpenGL and such I can render some pretty amazing looking things in &quot;real time&quot; 60 FPS.  However, if I try to make a video of that same scene in let's say Maya, or 3ds Max it would take MUCH MUCH longer for it to render even though it is the same resolution and FPS.&#xD;&#xA;&#xD;&#xA;Why do these two types of rendering take different periods of time for the same result?&#xD;&#xA;&#xD;&#xA;Note: Yes I do realize that 3D animation software can produce highly superior images to what could be done real time. But for this question I am referring to a scene of equal complexity." ContentLicense="CC BY-SA 3.0" />
  <row Id="3728" PostHistoryTypeId="4" PostId="1818" RevisionGUID="4f08cd33-2e16-490b-bcf2-9893b6ca698b" CreationDate="2015-12-21T10:50:34.440" UserId="127" Comment="Edited title, corrected capitalization, edited tags" Text="Difference between rendering in OpenGL and 3D animation software" ContentLicense="CC BY-SA 3.0" />
  <row Id="3729" PostHistoryTypeId="6" PostId="1818" RevisionGUID="4f08cd33-2e16-490b-bcf2-9893b6ca698b" CreationDate="2015-12-21T10:50:34.440" UserId="127" Comment="Edited title, corrected capitalization, edited tags" Text="|rendering|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3730" PostHistoryTypeId="5" PostId="1819" RevisionGUID="c53b078a-0a22-4b70-8a6f-969ca53a21e6" CreationDate="2015-12-21T10:57:34.817" UserId="127" Comment="Edited formatting" Text="The main difference would be that with OpenGL in let's say a video game you will have a process called *rasterization* which basically takes care of determining what part of the scene you see.&#xD;&#xA;&#xD;&#xA;It needs to be fast so we can experience it as realtime.&#xD;&#xA;&#xD;&#xA;Therefore the algorithm does a few simple steps.&#xD;&#xA;&#xD;&#xA;* check if a certain part of the scene is in my view frustum&#xD;&#xA;&#xD;&#xA;  [![Frustum Culling][1]][1]&#xD;&#xA;&#xD;&#xA;* check if something is in front of it which may needs to be rendered later using a depth buffer&#xD;&#xA;&#xD;&#xA;  [![Depth Buffer][2]][2]&#xD;&#xA;&#xD;&#xA;* order the objects we found to draw&#xD;&#xA;* *draw them* by projecting them on the screen&#xD;&#xA;* *shade them* based on textures / shaders / lights / ...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On the other hand a rendering software (Blender/Max/Maya/...) most likely uses some kind of *raytracing*&#xD;&#xA;&#xD;&#xA;This involves alot more math to achieve a higher degree of realism.&#xD;&#xA;It basically works in the same way:&#xD;&#xA;&#xD;&#xA;* create a camera and an image plane infront of it&#xD;&#xA;* shoot one ray (or multiple sample rays) through each pixel&#xD;&#xA;* check if the ray hits anything in the scene&#xD;&#xA;* closest hit is the one to be drawn in the pixel finally (like depth buffer)&#xD;&#xA;* calculate the light for the given point&#xD;&#xA; [![Light Calculation][3]][3]&#xD;&#xA;&#xD;&#xA;....&#xD;&#xA;&#xD;&#xA;I'll stopped listing here since this is the point where raytracing takes off.&#xD;&#xA;&#xD;&#xA;Instead of only checking if a point is hit, most raytracer now begins to calculate: &#xD;&#xA;&#xD;&#xA;* the amount of light a surface penetrates&#xD;&#xA;* how much light gets reflected&#xD;&#xA;* cast new rays from the hitpoint into the scene until it may hit a light source&#xD;&#xA;&#xD;&#xA;There are a ton of techniques with different degrees of realism which can be used to calculate the light of a certain point in the scene.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;The gist would be that a raytracer mostly tries to be physically accurate when it comes the lighting and therefore has a lot of more calculations to do per pixel (sometimes shoot thousands of rays) and on the other hand games get their speed by drawing bigger chunks of the screen with simpler light calculations and a lot of shader tricks which let it look realistic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TqkCF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7N5cL.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/jmB0K.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3731" PostHistoryTypeId="2" PostId="1820" RevisionGUID="0c2ac681-0b0f-4a3c-986d-205d2af36b33" CreationDate="2015-12-21T11:58:38.770" UserId="2248" Text="Im trying to plot the x and y positions of an Archimedean spiral in C++&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Archimedean_spiral&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wSmFI.png&#xD;&#xA;&#xD;&#xA;At the moment this code draws a wave line&#xD;&#xA;&#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = 0;&#xD;&#xA;    &#xD;&#xA;    for (x = 0; x &lt; maxPoints; x++)&#xD;&#xA;    {&#xD;&#xA;    	y = sin(x) - 0.5*x;&#xD;&#xA;    &#xD;&#xA;    	plot(x, y);    &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3732" PostHistoryTypeId="1" PostId="1820" RevisionGUID="0c2ac681-0b0f-4a3c-986d-205d2af36b33" CreationDate="2015-12-21T11:58:38.770" UserId="2248" Text="Archimedean spiral in C++" ContentLicense="CC BY-SA 3.0" />
  <row Id="3733" PostHistoryTypeId="3" PostId="1820" RevisionGUID="0c2ac681-0b0f-4a3c-986d-205d2af36b33" CreationDate="2015-12-21T11:58:38.770" UserId="2248" Text="|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3734" PostHistoryTypeId="5" PostId="1820" RevisionGUID="870d3a91-aafe-4c07-8228-eff4c5a8dc51" CreationDate="2015-12-21T12:12:24.577" UserId="2248" Comment="added 64 characters in body" Text="Im trying to plot the x and y positions of an Archimedean spiral in C++&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Archimedean_spiral&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wSmFI.png&#xD;&#xA;&#xD;&#xA;So far ive been trying something like this but no luck.&#xD;&#xA;&#xD;&#xA;	int dx = 0;&#xD;&#xA;	int dy = 0;&#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		dx = sin(i * PI / 2);&#xD;&#xA;		dy = cos(-i * PI / 2);&#xD;&#xA;		x += dx;&#xD;&#xA;		y += dy;&#xD;&#xA;    &#xD;&#xA;    	plot(x, y);    &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3735" PostHistoryTypeId="2" PostId="1821" RevisionGUID="1594a7d9-cc63-46e4-8673-08f1e72b91f3" CreationDate="2015-12-21T12:24:56.043" UserId="2248" Text="Figured it out :)&#xD;&#xA;  &#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = 0;&#xD;&#xA;	float angle = 0.0f;&#xD;&#xA;	int a = 4, b = 4;&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		angle = 0.1 * i;&#xD;&#xA;		x = (a + b * angle) * cos(angle);&#xD;&#xA;		y = (a + b * angle) * sin(angle);&#xD;&#xA;&#xD;&#xA;        plot(x, y);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3736" PostHistoryTypeId="6" PostId="1820" RevisionGUID="58cecd9f-0da2-4d17-bd18-06282df0d872" CreationDate="2015-12-21T12:25:48.257" UserId="16" Comment="edited tags" Text="|c++|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3737" PostHistoryTypeId="5" PostId="1821" RevisionGUID="6ece5d31-4130-4cc2-87d7-14fc930ed993" CreationDate="2015-12-21T12:32:26.177" UserId="2248" Comment="added 4 characters in body" Text="Figured it out :)&#xD;&#xA;  &#xD;&#xA;    float x = 0;&#xD;&#xA;    float y = 0;&#xD;&#xA;	float angle = 0.0f;&#xD;&#xA;	int a = 4, b = 4;&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		angle = 0.1 * i;&#xD;&#xA;		x = (a + b * angle) * cos(angle);&#xD;&#xA;		y = (a + b * angle) * sin(angle);&#xD;&#xA;&#xD;&#xA;        plot(x, y);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3738" PostHistoryTypeId="2" PostId="1822" RevisionGUID="5f2d2265-5b51-4ed5-a45a-2319d5d5e6fb" CreationDate="2015-12-21T13:15:35.117" UserId="38" Text="There is no reason why you can not get realtime graphics that are very good out of modeling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just loke games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (Ive done full hd renders at 30 fps from maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do. Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they arent so much faster just better organized. Baking your indirect illumination will beat nonbaked results every day.&#xD;&#xA;&#xD;&#xA;#Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they arent much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speedimess instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faser to do things once you optimize for it.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster." ContentLicense="CC BY-SA 3.0" />
  <row Id="3739" PostHistoryTypeId="5" PostId="1822" RevisionGUID="3ee3d7e5-ad6a-43ab-9cbb-ccbf4a9c1cca" CreationDate="2015-12-21T13:26:32.987" UserId="38" Comment="added 88 characters in body" Text="There is no reason why you can not get realtime graphics that are very good out of modeling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just loke games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (Ive done full hd renders at 30 fps from maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do. Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they arent so much faster just better organized. Baking your indirect illumination will beat nonbaked results every day.&#xD;&#xA;&#xD;&#xA;#Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they arent much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speedimess instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faser to do things once you optimize for it.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**YL;DR** The difference is mostly in optimization and available external resources." ContentLicense="CC BY-SA 3.0" />
  <row Id="3740" PostHistoryTypeId="5" PostId="1807" RevisionGUID="db0fedb0-ea12-43f0-b6db-ca0b6ad7a144" CreationDate="2015-12-21T15:05:18.920" UserId="2228" Comment="added 4 characters in body" Text="**SOLUTION**&#xD;&#xA;&#xD;&#xA;After a couple of days I realized that **I was computing my projection matrix using a FOV angle in degrees and It should be in radians**. I made the conversion and now everything works great. The interpolation among faces of my depth framebuffer's cubemap is now perfect. For this reason, It is important to handle every single trigonometric function's angle in radians.&#xD;&#xA;&#xD;&#xA;Moreover, I realized that you can compute your view matrix either as I said in the question and in this way:&#xD;&#xA;&#xD;&#xA;    view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;This approach means that your point of view is placed in pointlight's center and you just render in each direction of your cubemap, but which are these directions? well, **these directions are computed adding each target that I've in the switch block (according to each cubemap's face) with your pointlight's position**.&#xD;&#xA; &#xD;&#xA;Furthermore, **It is not necessary to flip Y-Coordinate of the projection matrix**, In this case, It is ok dispatch pointlight's perspective projection matrix to your GLSL shader without scaling It by (1, -1, 1) because **I'm working with textures that don't have a flipped Y-Coordinate**, I think you should flip Y-Coordinate of your pointlight's projection matrix **only if you are working with a flipped texture's Y-Coordinate**, this in order to have a correct omnidirectional shadow mapping effect.&#xD;&#xA;&#xD;&#xA;Finally, I'll leave here the final version of my Omnidirectional Shadow Mapping algorithm on CPU/GPU side. On CPU side I'll explain every step that you have to do in order to compute a correct shadow map for each cubemap's face. On the other hand in GPU side, I'll explain my depth program's vertex/fragment shader and omnidirectional shadow mapping function in my main fragment shader, this in order to help somebody who could be learning this technique, or solve future doubts about this algorithm:&#xD;&#xA;&#xD;&#xA;**CPU**&#xD;&#xA;&#xD;&#xA;      // Disable blending and enable front face culling.&#xD;&#xA;&#xD;&#xA;      this.state.disable(gl.BLEND);&#xD;&#xA;    &#xD;&#xA;      this.state.enable(gl.CULL_FACE);&#xD;&#xA;      this.state.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;      // Binds depth program&#xD;&#xA;       &#xD;&#xA;      program.bind(gl);&#xD;&#xA;&#xD;&#xA;      // For each pointlight source do&#xD;&#xA;&#xD;&#xA;      for (i = 0; i &lt; lights.length; i++) {&#xD;&#xA;        light = lights[i];&#xD;&#xA;&#xD;&#xA;        // Get each pointlight's world position&#xD;&#xA;&#xD;&#xA;        position = light.worldPosition();&#xD;&#xA;    &#xD;&#xA;        // Binds pointlight's depth framebuffer. Besides, in this function,&#xD;&#xA;        // viewport's dimensions are set according to depth framebuffer's dimension.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.bind(gl, this.state);&#xD;&#xA;&#xD;&#xA;        // Updates point light's framebuffer in order to create it &#xD;&#xA;        // or if it's resolution have changed, it'll be created again.&#xD;&#xA;&#xD;&#xA;        light.depthFramebuffer.update(gl);&#xD;&#xA;&#xD;&#xA;        // Check in which cubemap's face we are ...&#xD;&#xA;&#xD;&#xA;        for (j = 0; j &lt; 6; j++) {&#xD;&#xA;          switch (j) {&#xD;&#xA;            case Cubemap.POSITIVE_X:&#xD;&#xA;              target.set(1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_X:&#xD;&#xA;              target.set(-1, 0, 0);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.POSITIVE_Y:&#xD;&#xA;              target.set(0, 1, 0);&#xD;&#xA;              up.set(0, 0, 1);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_Y:&#xD;&#xA;              target.set(0, -1, 0);&#xD;&#xA;              up.set(0, 0, -1);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.POSITIVE_Z:&#xD;&#xA;              target.set(0, 0, 1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;            case Cubemap.NEGATIVE_Z:&#xD;&#xA;              target.set(0, 0, -1);&#xD;&#xA;              up.set(0, -1, 0);&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          // Creates a view matrix using target and up vectors &#xD;&#xA;          // according to each face of pointlight's cubemap.&#xD;&#xA;    &#xD;&#xA;          view.lookAt(position, target.add(position.clone()), up);&#xD;&#xA;&#xD;&#xA;          // Attaches cubemap's face to current framebuffer &#xD;&#xA;          // in order to record depth values in that direction.&#xD;&#xA;    &#xD;&#xA;          light.depthFramebuffer.texture.attach(gl, j);&#xD;&#xA;&#xD;&#xA;          // Clears color &amp; depth buffers of your current framebuffer&#xD;&#xA;    &#xD;&#xA;          this.clear();&#xD;&#xA;&#xD;&#xA;          // Render each shadow caster mesh using your depth program&#xD;&#xA;    &#xD;&#xA;          for (k = 0; k &lt; meshes.length; k++)&#xD;&#xA;            this._renderMeshDepth(program, meshes[k], view, light.projection);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;On renderMeshDepth function I've:&#xD;&#xA;&#xD;&#xA;      // Computes pointlight's model-view matrix &#xD;&#xA;&#xD;&#xA;      modelView.mul(view, mesh.world);&#xD;&#xA;&#xD;&#xA;      // Dispatch each matrix to the GLSL depth program&#xD;&#xA;    &#xD;&#xA;      program.loadUniformMatrix(gl, 'uModelView', modelView);&#xD;&#xA;      program.loadUniformMatrix(gl, 'uProjection', projection);&#xD;&#xA;    &#xD;&#xA;      // Renders a mesh using vertex buffer objects (VBO)&#xD;&#xA;&#xD;&#xA;      mesh.render(gl, program.attributes, this.state, this.extensions);&#xD;&#xA;&#xD;&#xA;**GPU**&#xD;&#xA;&#xD;&#xA;Depth Program Vertex Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec3 position;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelView;&#xD;&#xA;    uniform mat4 uProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = uProjection * uModelView * vec4(position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Depth Program Fragment Shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    // The pack function distributes fragment's depth precision storing &#xD;&#xA;    // it throughout (R,G,B,A) color channels and not just R color channel &#xD;&#xA;    // as usual in shadow mapping algorithms. This is because I'm working&#xD;&#xA;    // with 8-bit textures and one color channel hasn't enough precision &#xD;&#xA;    // to store a depth value.&#xD;&#xA;    &#xD;&#xA;    vec4 pack(const in float depth) {&#xD;&#xA;      const vec4 bitShift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);&#xD;&#xA;      const vec4 bitMask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);&#xD;&#xA;    &#xD;&#xA;      vec4 res = fract(depth * bitShift);&#xD;&#xA;      res -= res.xxyz * bitMask;&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      // Packs normalized fragment's Z-Coordinate which is in [0,1] interval.&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = pack(gl_FragCoord.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Omnidirectional Shadow Mapping function in my main fragment shader:&#xD;&#xA;&#xD;&#xA;    // Unpacks fragment's Z-Coordinate which was packed &#xD;&#xA;    // on the depth program's fragment shader.&#xD;&#xA;    &#xD;&#xA;    float unpack(in vec4 color) {&#xD;&#xA;       const vec4 bitShift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);&#xD;&#xA;       return dot(color, bitShift);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Computes Omnidirectional Shadow Mapping technique using a samplerCube&#xD;&#xA;    // vec3 lightPosition is your pointlight's position in world coordinates.&#xD;&#xA;    // vec3 vPosition is your vertex's position in world coordinates, in code&#xD;&#xA;    // I mean this -&gt; vPosition = vec3(uModel * vec4(position, 1.0));&#xD;&#xA;    // where uModel is your World/Model matrix.&#xD;&#xA;&#xD;&#xA;    float omnidirectionalShadow(in vec3 lightPosition, in float bias, in float darkness, in samplerCube sampler) {&#xD;&#xA;    	vec3 direction = vPosition - lightPosition;&#xD;&#xA;    	float vertexDepth = clamp(length(direction), 0.0, 1.0);&#xD;&#xA;    	float shadowMapDepth = unpack(textureCube(sampler, direction)) + bias;&#xD;&#xA;    &#xD;&#xA;    	return (vertexDepth &gt; shadowMapDepth) ? darkness : 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here you have a final render of the algorithm&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Have fun coding beautiful graphics, good luck :) &#xD;&#xA;&#xD;&#xA;C.Z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvMHa.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3741" PostHistoryTypeId="5" PostId="1822" RevisionGUID="202eef95-8bbb-4fde-957e-bedc4e633a5d" CreationDate="2015-12-21T15:47:12.277" UserId="38" Comment="added 413 characters in body" Text="### Your comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modeling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (Ive done full hd renders at 30 fps from maya). All you have to do is stop using the provided software ray tracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do. Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been pre computed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xD;&#xA;&#xD;&#xA;###Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they aren't much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**YL;DR** The difference is mostly in optimization and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because its more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game. In fact many games use really good models while quite many modellers do not." ContentLicense="CC BY-SA 3.0" />
  <row Id="3742" PostHistoryTypeId="5" PostId="1822" RevisionGUID="7eb0bc04-3d9d-4b7c-ac41-d74058e25b5b" CreationDate="2015-12-21T15:52:36.557" UserId="38" Comment="added 8 characters in body" Text="### Your comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modeling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (Ive done full hd renders at 30 fps from maya). All you have to do is stop using the provided software ray tracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do. Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been pre computed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xD;&#xA;&#xD;&#xA;###Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they aren't much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**YL;DR** The difference is mostly in optimization and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because its more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game. In fact many games use really good models while quite many modellers do not." ContentLicense="CC BY-SA 3.0" />
  <row Id="3743" PostHistoryTypeId="5" PostId="1822" RevisionGUID="c2133055-b679-42d1-a2bb-4d4b76a7cf78" CreationDate="2015-12-21T16:18:37.727" UserId="-1" Comment="Grammar and spelling." Text="### You're comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modelling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (I've done full HD renders at 30 fps from Maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do. Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xD;&#xA;&#xD;&#xA;###Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they aren't much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**TL;DR** The difference is mostly in optimization and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because it is more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game. In fact many games use really good models while quite many modelers do not." ContentLicense="CC BY-SA 3.0" />
  <row Id="3744" PostHistoryTypeId="24" PostId="1822" RevisionGUID="c2133055-b679-42d1-a2bb-4d4b76a7cf78" CreationDate="2015-12-21T16:18:37.727" Comment="Proposed by anonymous approved by 38 edit id of 115" ContentLicense="CC BY-SA 3.0" />
  <row Id="3745" PostHistoryTypeId="5" PostId="1822" RevisionGUID="520b1adc-87e6-494e-9cc1-7916ecd7d0b3" CreationDate="2015-12-21T16:31:54.683" UserId="38" Comment="added 22 characters in body" Text="### You're comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modelling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (I've done full HD renders at 30 fps from Maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do (optimization is using all the tricks in the book). Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xD;&#xA;&#xD;&#xA;###Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they aren't much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**TL;DR** The difference is mostly in optimization (read lots of tricks) and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because it is more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game. In fact many games use really good models while quite many modelers do not." ContentLicense="CC BY-SA 3.0" />
  <row Id="3746" PostHistoryTypeId="5" PostId="1822" RevisionGUID="087e63c6-3a94-4f3d-bc59-7e3cd90df23c" CreationDate="2015-12-21T19:33:16.610" UserId="38" Comment="added 25 characters in body" Text="### You're comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modelling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (I've done full HD renders at 30 fps from Maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do (optimization is using all the tricks in the book). Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xD;&#xA;&#xD;&#xA;###Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't. Feature by feature they aren't much slower in computation cycles. If you do not use the features then it is another thing. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**TL;DR** The difference is mostly in optimization (read lots of tricks) and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because it is more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game or any other computation. In fact many games use really good models while quite many modelers do not." ContentLicense="CC BY-SA 3.0" />
  <row Id="3749" PostHistoryTypeId="5" PostId="1820" RevisionGUID="79a991e7-d6a6-4ec0-b662-933421b51d6a" CreationDate="2015-12-21T21:27:54.283" UserId="54" Comment="Fixed link; added language markup so syntax highlighting works." Text="Im trying to plot the x and y positions of an [Archimedean spiral](https://en.wikipedia.org/wiki/Archimedean_spiral) in C++.&#xD;&#xA;&#xD;&#xA;[![Archimedean spiral][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wSmFI.png&#xD;&#xA;&#xD;&#xA;So far I've been trying something like this, but no luck:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;	int dx = 0;&#xD;&#xA;	int dy = 0;&#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		dx = sin(i * PI / 2);&#xD;&#xA;		dy = cos(-i * PI / 2);&#xD;&#xA;		x += dx;&#xD;&#xA;		y += dy;&#xD;&#xA;    &#xD;&#xA;    	plot(x, y);    &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="3750" PostHistoryTypeId="24" PostId="1820" RevisionGUID="79a991e7-d6a6-4ec0-b662-933421b51d6a" CreationDate="2015-12-21T21:27:54.283" Comment="Proposed by 54 approved by 127 edit id of 116" ContentLicense="CC BY-SA 3.0" />
  <row Id="3751" PostHistoryTypeId="5" PostId="1455" RevisionGUID="b2990f7e-3b51-4e22-bab5-1b4813ab203a" CreationDate="2015-12-22T00:24:07.023" UserDisplayName="user464" Comment="deleted 348 characters in body; edited title" Text="I know that there are 3 techniques to draw 3D objects:&#xD;&#xA;(1) Wireframe Modeling and rendering&#xD;&#xA;(2) Additive Modeling&#xD;&#xA;(3) Subtractive Modeling&#xD;&#xA;&#xD;&#xA;Am I correct?&#xD;&#xA;&#xD;&#xA;What formula or algorithm can I use to draw a 3D Sphere?&#xD;&#xA;&#xD;&#xA;I am using a low-level library named [WinBGIm from colorado university][1].&#xD;&#xA;&#xD;&#xA;For example, how to draw this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And, this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://winbgim.codecutter.org/&#xD;&#xA;  [2]: https://i.stack.imgur.com/35GPL.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/1zy5r.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3752" PostHistoryTypeId="4" PostId="1455" RevisionGUID="b2990f7e-3b51-4e22-bab5-1b4813ab203a" CreationDate="2015-12-22T00:24:07.023" UserDisplayName="user464" Comment="deleted 348 characters in body; edited title" Text="What formula or algorithm can I use to draw a 3D Sphere without using OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3756" PostHistoryTypeId="2" PostId="1824" RevisionGUID="878d7480-46f4-4caa-b411-0a41d6316018" CreationDate="2015-12-22T02:47:08.040" UserId="2319" Text="[base_image]: https://i.stack.imgur.com/J4ocR.png&#xD;&#xA;[software_rendering]: https://i.stack.imgur.com/OCJdY.png&#xD;&#xA;[upscaled_rendering]: https://i.stack.imgur.com/6DBZt.png&#xD;&#xA;[svg_browser]: https://i.stack.imgur.com/wUHjQ.png&#xD;&#xA;[image_recomposition]: https://i.stack.imgur.com/iXbo2.png&#xD;&#xA;[image_recomposition_result]: https://i.stack.imgur.com/qq7Gr.png&#xD;&#xA;[blender_viewport]: https://i.stack.imgur.com/oOwG9.png&#xD;&#xA;[blender_render]: https://i.stack.imgur.com/2NZfe.png&#xD;&#xA;&#xD;&#xA;I am currently trying to understand a few things about vector graphics rasterization and the different ways it is implemented in various application types.&#xD;&#xA;&#xD;&#xA;I tested and compared few programs and noticed that there is a major difference in the way **anti-aliasing** behaves in the rasterization process. **I am especially interested in the rendering behavior in Illustrator**. You will see why by reading further.&#xD;&#xA;&#xD;&#xA;![Base image][base_image]&#xD;&#xA;&#xD;&#xA;For my testing, I used a really simple composition of triangles organized in an irregular hexagon with different colors.&#xD;&#xA;&#xD;&#xA;## Vector graphics softwares&#xD;&#xA;&#xD;&#xA;Here are three renders of the same vector graphic in Illustrator, Affinity and Inkscape. (The image produced in Affinity and Inkscape are exactly the same.)&#xD;&#xA;&#xD;&#xA;![Images rendered in popular graphic editing tools][software_rendering]&#xD;&#xA;&#xD;&#xA;As you can see there is an undesired white line on each of the edges in the image rendered with Affinity and Inkscape. The anti-aliasing does not fill this area with a solid color which results in a small gap between each shape.&#xD;&#xA;&#xD;&#xA;Although there is no gap in the Illustrator render, the edges of the shapes looks as smooth as the Affinity render.&#xD;&#xA;&#xD;&#xA;Here is an image showing the same area of each image upscaled.&#xD;&#xA;&#xD;&#xA;![Upscale render showing anti-aliasing][upscaled_rendering]&#xD;&#xA;&#xD;&#xA;There is a very subtle difference between the two images. The Affinity render is a tiny bit smoother but it is almost impossible to see the difference when looking at the images in their original sizes.&#xD;&#xA;&#xD;&#xA;## Browsers&#xD;&#xA;&#xD;&#xA;### SVG rendering&#xD;&#xA;&#xD;&#xA;Displaying the same graphics exported as SVG in a browser looks very similar to the raster image both produced by Affinity and Inkscape.&#xD;&#xA;&#xD;&#xA;![SVG file rendered in browser][svg_browser]&#xD;&#xA;&#xD;&#xA;There are very tiny differences in edges anti-aliasing (that are not really worth showing here) but SVG rasterization in common browsers behaves pretty much the same.&#xD;&#xA;&#xD;&#xA;## Decomposed render&#xD;&#xA;&#xD;&#xA;Testing Illustrator rendering a bit further, I tried splitting parts of my graphics and exporting them individually then composing them back together with a raster editing software.&#xD;&#xA;&#xD;&#xA;![Image recomposition scheme][image_recomposition]&#xD;&#xA;&#xD;&#xA;In theory it would result in the same image as having it in a single piece, but the result is slightly different using this method.&#xD;&#xA;&#xD;&#xA;![Result of recomposed image][image_recomposition_result]&#xD;&#xA;&#xD;&#xA;As shown, when the two parts are composed, there is a tiny gap between them. Though it is more subtle, it is very similar to the graphic rendered in Affinity.&#xD;&#xA;&#xD;&#xA;## Polygon rendering&#xD;&#xA;&#xD;&#xA;### Blender (3D software)&#xD;&#xA;&#xD;&#xA;![SVG in Blender viewport][blender_viewport]&#xD;&#xA;&#xD;&#xA;Blender allow to import SVG files and manipulate them as curve objects. Here is the imported graphic shown in the 3D viewport. (By default material will be affected by lights in the scene. Checking the shadeless property in the material property panel will allow the shapes to be rendered with their original colors.)&#xD;&#xA;&#xD;&#xA;Here is a render made of the SVG inside Blender.&#xD;&#xA;&#xD;&#xA;![Actual render in Blender][blender_render]&#xD;&#xA;&#xD;&#xA;It does not have any gap between the triangles. Other 3D softwares are very likely to work the same way. So Blender behaves just like **Illustrator**, or does it? Maybe it is the other way around?&#xD;&#xA;&#xD;&#xA;## The real questions&#xD;&#xA;&#xD;&#xA;* Which vector drawing library Illustrator uses behind the scene?&#xD;&#xA;* Could it be possible that Illustrator makes use of a sort of 3D rendering engine? Is it open source? (probably not?)&#xD;&#xA;* Can any of the well known vector drawing library such as Cairo and Skia achieve the same rendering behavior? (No gap between shapes)&#xD;&#xA;* Is there any less known vector drawing library out there that has the same behavior?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3757" PostHistoryTypeId="1" PostId="1824" RevisionGUID="878d7480-46f4-4caa-b411-0a41d6316018" CreationDate="2015-12-22T02:47:08.040" UserId="2319" Text="What is Illustrator's vector rendering process?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3758" PostHistoryTypeId="3" PostId="1824" RevisionGUID="878d7480-46f4-4caa-b411-0a41d6316018" CreationDate="2015-12-22T02:47:08.040" UserId="2319" Text="|3d|antialiasing|vector-graphics|blender|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3759" PostHistoryTypeId="4" PostId="1824" RevisionGUID="75ed1f8e-a266-4c80-bcff-0bcd7aeb9cde" CreationDate="2015-12-22T02:53:18.680" UserId="2319" Comment="edited title" Text="What is Illustrator's vector rasterization process?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3760" PostHistoryTypeId="6" PostId="1824" RevisionGUID="4edf3fc0-af7b-4dd3-91c6-29804c5f456b" CreationDate="2015-12-22T03:17:49.237" UserId="2319" Comment="Remove tags" Text="|antialiasing|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3761" PostHistoryTypeId="2" PostId="1825" RevisionGUID="b236d3ba-07ca-4fd4-87e1-25a4b9d88c42" CreationDate="2015-12-22T08:01:30.097" UserId="38" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap arrtfacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;It is simply a un-antialiased image that has been subjected to a box filtering. Which is indeed a similar technology as what the multi pixel filter. &#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3762" PostHistoryTypeId="5" PostId="1825" RevisionGUID="f702997d-e1b4-4540-821a-b0faec56e929" CreationDate="2015-12-22T08:11:36.640" UserId="38" Comment="added 485 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap arrtfacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;It is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a box filtering. Which is indeed a similar technology as what the multi pixel filter used in your blender render. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0. Also it does not know how the coverage is distributed so it will do it wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3763" PostHistoryTypeId="5" PostId="1825" RevisionGUID="d8b06c6f-5f29-4ec0-bec1-7bdac8baccc3" CreationDate="2015-12-22T08:16:59.577" UserId="38" Comment="added 485 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;It is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3764" PostHistoryTypeId="5" PostId="1825" RevisionGUID="26731d81-09e0-4edf-8d2c-09993d16a8a1" CreationDate="2015-12-22T08:24:18.353" UserId="38" Comment="added 220 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;It is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](http://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3765" PostHistoryTypeId="5" PostId="1825" RevisionGUID="86e3186f-7905-473a-9e06-dc96134af859" CreationDate="2015-12-22T08:32:17.413" UserId="38" Comment="added 220 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;It is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters and computing in linear color space.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Click to zoom to see result. Multi pixel filtering, on left illustrator native 'Art Optimized'. On right same image at 16x16 pixels with multi lobed [Lanczos filter in linear space](http://graphicdesign.stackexchange.com/questions/58162/how-to-draw-smooth-curved-shapes-in-illustrator/58175#58175).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](http://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EfM61.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3766" PostHistoryTypeId="5" PostId="1825" RevisionGUID="6259777b-abad-48ee-9545-7601ea40dccf" CreationDate="2015-12-22T08:50:27.217" UserId="38" Comment="added 417 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;[![Art optimized versus screen preview of illustrator][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The different render modes of illustrator. Art optimized on left and hinted on right. Note that hinted shows slight background through. I dont have the new CC version so i can not show the third.&#xD;&#xA;&#xD;&#xA;Art optimized render mode is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render uses. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters and computing in linear color space.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Multi pixel filtering, on left illustrator native 'Art Optimized'. On right same image at 16x16 pixels with multi lobed [Lanczos filter in linear space](http://graphicdesign.stackexchange.com/questions/58162/how-to-draw-smooth-curved-shapes-in-illustrator/58175#58175). Make sure your zoom is 1:1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](http://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tf7V4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EfM61.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3767" PostHistoryTypeId="5" PostId="1825" RevisionGUID="2d112d98-b02b-4db9-98d8-49f6d3061503" CreationDate="2015-12-22T08:56:16.380" UserId="38" Comment="added 69 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;[![Art optimized versus screen preview of illustrator][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The different render modes of illustrator. Art optimized on left and hinted on right. Note that hinted shows slight background through. I dont have the new CC version so i can not show the third.&#xD;&#xA;&#xD;&#xA;Art optimized render mode is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render uses. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters and computing in linear color space.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Multi pixel filtering, on left illustrator native 'Art Optimized'. On right same image at 16x16 pixels with multi lobed [Lanczos filter in linear space](http://graphicdesign.stackexchange.com/questions/58162/how-to-draw-smooth-curved-shapes-in-illustrator/58175#58175). Make sure your zoom is 1:1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0 when chained over semitransparent surfaces so background show trough. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](http://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tf7V4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EfM61.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3768" PostHistoryTypeId="5" PostId="1825" RevisionGUID="30efb491-9d03-478f-86e7-f875f282a26f" CreationDate="2015-12-22T09:11:41.397" UserId="38" Comment="added 446 characters in body" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;[![Art optimized versus screen preview of illustrator][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The different render modes of illustrator. Art optimized on left and hinted on right. Note that hinted shows slight background through. I dont have the new CC version so i can not show the third.&#xD;&#xA;&#xD;&#xA;### How does art optimized work then&#xD;&#xA;&#xD;&#xA;Art optimized render mode is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render uses. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters and computing in linear color space. All multi sample methods exhibit the same correct rendering (given enough samples even mathematically correct).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Multi pixel filtering, on left illustrator native 'Art Optimized'. On right same image at 16x16 pixels with multi lobed [Lanczos filter in linear space](http://graphicdesign.stackexchange.com/questions/58162/how-to-draw-smooth-curved-shapes-in-illustrator/58175#58175). Make sure your zoom is 1:1.&#xD;&#xA;&#xD;&#xA;### The problem&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0 when chained over semitransparent surfaces so background show trough. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](http://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;**Other questions** You can get same result in any other engine by just simply multisampling a non-antialiased image. You can not get the effect in on screen renderings without doing the overlap trick because they optimize for speed. Does illustrator use 3D? New CC might depends on your interpretation of what 3D is. This issue has nothing to do with 3D just about signal reconstruction methods so its not applicable to the question really.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tf7V4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EfM61.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3772" PostHistoryTypeId="5" PostId="1822" RevisionGUID="c4e3e64e-fc37-4901-bdf4-6b3a173a04c8" CreationDate="2015-12-22T10:05:13.287" UserId="38" Comment="added 124 characters in body" Text="### You're comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modelling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (I've done full HD renders at 30 fps from Maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do (optimization is using all the tricks in the book). Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xD;&#xA;&#xD;&#xA;###Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't\*, one just tends to do more work on a ray tracer because its easy. Feature by feature they aren't much slower in computation cycles. For example theres no need for a ray tracer to cast secondary rays (life reflections in that case the ray tracer will cull geometry away, or not even load it, in fact mental ray does just that). Its just usually done because it trivial to do so and that's the clear advantage of ray tracers. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**TL;DR** The difference is mostly in optimization (read lots of tricks) and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because it is more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game or any other computation. In fact many games use really good models while quite many modelers do not.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* See http://www.graphics.cornell.edu/~bjw/mca.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3774" PostHistoryTypeId="5" PostId="1824" RevisionGUID="23dda706-c84d-4520-8954-2bd9aab1e1b6" CreationDate="2015-12-22T12:30:04.157" UserId="231" Comment="Minor tidying" Text="[base_image]: https://i.stack.imgur.com/J4ocR.png&#xD;&#xA;[software_rendering]: https://i.stack.imgur.com/OCJdY.png&#xD;&#xA;[upscaled_rendering]: https://i.stack.imgur.com/6DBZt.png&#xD;&#xA;[svg_browser]: https://i.stack.imgur.com/wUHjQ.png&#xD;&#xA;[image_recomposition]: https://i.stack.imgur.com/iXbo2.png&#xD;&#xA;[image_recomposition_result]: https://i.stack.imgur.com/qq7Gr.png&#xD;&#xA;[blender_viewport]: https://i.stack.imgur.com/oOwG9.png&#xD;&#xA;[blender_render]: https://i.stack.imgur.com/2NZfe.png&#xD;&#xA;&#xD;&#xA;I am currently trying to understand a few things about vector graphics rasterization and the different ways it is implemented in various application types.&#xD;&#xA;&#xD;&#xA;I tested and compared a few programs and noticed that there is a major difference in the way **anti-aliasing** behaves in the rasterization process. **I am especially interested in the rendering behavior in Illustrator**. You will see why by reading further.&#xD;&#xA;&#xD;&#xA;![Base image][base_image]&#xD;&#xA;&#xD;&#xA;For my testing, I used a really simple composition of triangles organized in an irregular hexagon with different colors.&#xD;&#xA;&#xD;&#xA;## Vector graphics softwares&#xD;&#xA;&#xD;&#xA;Here are three renders of the same vector graphic in Illustrator, Affinity and Inkscape. (The image produced in Affinity and Inkscape are exactly the same.)&#xD;&#xA;&#xD;&#xA;![Images rendered in popular graphic editing tools][software_rendering]&#xD;&#xA;&#xD;&#xA;As you can see there is an undesired white line on each of the edges in the image rendered with Affinity and Inkscape. The anti-aliasing does not fill this area with a solid color which results in a small gap between adjacent shapes.&#xD;&#xA;&#xD;&#xA;Although there is no gap in the Illustrator render, the edges of the shapes look as smooth as the Affinity render.&#xD;&#xA;&#xD;&#xA;Here is an image showing the same area of each image upscaled.&#xD;&#xA;&#xD;&#xA;![Upscale render showing anti-aliasing][upscaled_rendering]&#xD;&#xA;&#xD;&#xA;There is a very subtle difference between the two images. The Affinity render is a tiny bit smoother but it is almost impossible to see the difference when looking at the images in their original sizes.&#xD;&#xA;&#xD;&#xA;## Browsers&#xD;&#xA;&#xD;&#xA;### SVG rendering&#xD;&#xA;&#xD;&#xA;Displaying the same graphics exported as SVG in a browser looks very similar to the raster image produced by both Affinity and Inkscape.&#xD;&#xA;&#xD;&#xA;![SVG file rendered in browser][svg_browser]&#xD;&#xA;&#xD;&#xA;There are very tiny differences in edges anti-aliasing (that are not really worth showing here) but SVG rasterization in common browsers behaves pretty much the same.&#xD;&#xA;&#xD;&#xA;## Decomposed render&#xD;&#xA;&#xD;&#xA;Testing Illustrator rendering a bit further, I tried splitting parts of my graphics and exporting them individually then composing them back together with a raster editing software.&#xD;&#xA;&#xD;&#xA;![Image recomposition scheme][image_recomposition]&#xD;&#xA;&#xD;&#xA;In theory it would result in the same image as having it in a single piece, but the result is slightly different using this method.&#xD;&#xA;&#xD;&#xA;![Result of recomposed image][image_recomposition_result]&#xD;&#xA;&#xD;&#xA;As shown, when the two parts are composed, there is a tiny gap between them. Though it is more subtle, it is very similar to the graphic rendered in Affinity.&#xD;&#xA;&#xD;&#xA;## Polygon rendering&#xD;&#xA;&#xD;&#xA;### Blender (3D software)&#xD;&#xA;&#xD;&#xA;![SVG in Blender viewport][blender_viewport]&#xD;&#xA;&#xD;&#xA;Blender allows you to import SVG files and manipulate them as curve objects. Here is the imported graphic shown in the 3D viewport. (By default material will be affected by lights in the scene. Checking the shadeless property in the material property panel will allow the shapes to be rendered with their original colors.)&#xD;&#xA;&#xD;&#xA;Here is a render made of the SVG inside Blender.&#xD;&#xA;&#xD;&#xA;![Actual render in Blender][blender_render]&#xD;&#xA;&#xD;&#xA;It does not have any gap between the triangles. Other 3D softwares are very likely to work the same way. So Blender behaves just like **Illustrator**, or does it? Maybe it is the other way around?&#xD;&#xA;&#xD;&#xA;## The real questions&#xD;&#xA;&#xD;&#xA;* Which vector drawing library does Illustrator use behind the scenes?&#xD;&#xA;* Could it be possible that Illustrator makes use of a sort of 3D rendering engine? Is it open source? (probably not?)&#xD;&#xA;* Can any of the well known vector drawing libraries such as Cairo and Skia achieve the same rendering behavior? (No gap between shapes)&#xD;&#xA;* Is there any less known vector drawing library out there that has the same behavior?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3775" PostHistoryTypeId="5" PostId="1820" RevisionGUID="68e5887a-540d-449a-a982-972be19f5762" CreationDate="2015-12-22T21:28:53.727" UserId="2248" Comment="added 394 characters in body" Text="Im trying to plot the x and y positions of an [Archimedean spiral](https://en.wikipedia.org/wiki/Archimedean_spiral) in C++.&#xD;&#xA;&#xD;&#xA;[![Archimedean spiral][1]][1]&#xD;&#xA;&#xD;&#xA;So far I've been trying something like this, but no luck:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;	int dx = 0;&#xD;&#xA;	int dy = 0;&#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		dx = sin(i * PI / 2);&#xD;&#xA;		dy = cos(-i * PI / 2);&#xD;&#xA;		x += dx;&#xD;&#xA;		y += dy;&#xD;&#xA;    &#xD;&#xA;    	plot(x, y);    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;EDIT: More info&#xD;&#xA;&#xD;&#xA;I'm developing a 3D game application that demonstrates the use of the [Bullet][2] physics engine by simulating dominos. Instead of placing the dominos in the scene manually I want to use some math to do it for me :)&#xD;&#xA;&#xD;&#xA;For anyone who is interested here it is on [GitHub][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wSmFI.png&#xD;&#xA;  [2]: http://bulletphysics.org/wordpress/&#xD;&#xA;  [3]: https://github.com/damorton/bullet-dominos" ContentLicense="CC BY-SA 3.0" />
  <row Id="3776" PostHistoryTypeId="5" PostId="1821" RevisionGUID="917e811f-904e-435e-9602-84a9f15d32c4" CreationDate="2015-12-22T21:33:01.800" UserId="2248" Comment="added 94 characters in body" Text="Figured it out :) The dominos are now being placed along the X and Y coordinates generated by the function.&#xD;&#xA;  &#xD;&#xA;    float x = 0;&#xD;&#xA;    float y = 0;&#xD;&#xA;	float angle = 0.0f;&#xD;&#xA;	int a = 2, b = 2;&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		angle = 0.1 * i;&#xD;&#xA;		x = (a + b * angle) * cos(angle);&#xD;&#xA;		y = (a + b * angle) * sin(angle);&#xD;&#xA;&#xD;&#xA;        plot(x, y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3777" PostHistoryTypeId="5" PostId="1821" RevisionGUID="5096bf13-75f8-4bfd-b609-a15a104bafe3" CreationDate="2015-12-22T21:48:24.973" UserId="2248" Comment="added 94 characters in body" Text="Figured it out :) The dominos are now being placed along the X and Y coordinates generated by the function. &#xD;&#xA;&#xD;&#xA;The original code in the question was plotting a wave of points outwards from the centre position or origin and was not what I wanted. What I needed was for each point to follow the `Archimedean spiral` with a certain space between the spirals. &#xD;&#xA;&#xD;&#xA;Initially I used `integer` values to store the `x` and `y` coordinates but this was causing a precision error by truncating the `floating point` value in order to store it in the `integer` data type.&#xD;&#xA;  &#xD;&#xA;The below example generates points along the spiral continuously, relative to the `maxPoints` value. &#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float y = 0;&#xD;&#xA;	float angle = 0.0f;&#xD;&#xA;&#xD;&#xA;    // Space between the spirals&#xD;&#xA;	int a = 2, b = 2;&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;	{&#xD;&#xA;		angle = 0.1 * i;&#xD;&#xA;		x = (a + b * angle) * cos(angle);&#xD;&#xA;		y = (a + b * angle) * sin(angle);&#xD;&#xA;&#xD;&#xA;        plot(x, y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Code for the project is on [GitHub][1], you will need [Bullet][2] and [freeglut][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/damorton/bullet-dominos/blob/master/CAPhysics/Chapter4.2/BasicDemo.cpp&#xD;&#xA;  [2]: http://bulletphysics.org/wordpress/&#xD;&#xA;  [3]: http://freeglut.sourceforge.net/" ContentLicense="CC BY-SA 3.0" />
  <row Id="3778" PostHistoryTypeId="2" PostId="1827" RevisionGUID="ae083c09-8ee6-4b59-90c7-fee1789d038e" CreationDate="2015-12-23T00:17:52.060" UserId="2247" Text="**Real-Time Preview**&#xD;&#xA;&#xD;&#xA;Working in the VFX side of the industry, if you're talking about real-time viewport previews and not production rendering, then Maya and 3DS Max typically also use OpenGL (or possibly DirectX -- pretty much the same).&#xD;&#xA;&#xD;&#xA;One of the main conceptual differences between VFX animation software and games is the level of assumptions they can make. For example, in VFX software, it's not uncommon for the artist to load a single, seamless character mesh that spans hundreds of thousands to millions of polygons. Games tend to optimize most for a large scene consisting of a boatload of simple, optimized meshes (thousands of triangles each).&#xD;&#xA;&#xD;&#xA;**Production Rendering and Path Tracing**&#xD;&#xA;&#xD;&#xA;VFX software also places the emphasis not on the real-time preview but on production rendering where light rays are actually simulated one at a time. The real-time preview often is just that, a &quot;preview&quot; of the higher-quality production result.&#xD;&#xA;&#xD;&#xA;Games are doing a beautiful job of approximating a lot of those effects lately like real-time depth of field, soft shadows, diffuse reflections, etc., but they're in the heavy-duty approximation category (ex: blurry cube maps for diffuse reflections instead of actually simulating light rays).&#xD;&#xA;&#xD;&#xA;**Content**&#xD;&#xA;&#xD;&#xA;Coming back to this subject, the content assumptions between a VFX software and game wildly differ. A VFX software's main focus is to allow any possible kind of content to be created (at least that's the ideal, although in practically it's often nowhere close). Games focus on content with a lot more heavier assumptions (all models should be in the range of thousands of triangles, normal maps should be applied to fake details, we shouldn't actually have 13 billion particles, etc).&#xD;&#xA;&#xD;&#xA;Due to those assumptions, game engines can often more easily apply acceleration techniques like frustum culling which enable them to maintain a high, interactive frame rate. VFX software can't easily make those kinds of assumptions given the much higher degree of flexibility in content creation and support.&#xD;&#xA;&#xD;&#xA;**Games Do it Better**&#xD;&#xA;&#xD;&#xA;This might be kind of a controversial view, but the game industry is a much more lucrative industry than VFX software. Their budgets for a single game can span in the hundreds of millions of dollars, and they can afford to keep releasing next-generation engines every few years. Their R&amp;D efforts are amazing, and there are hundreds upon hundreds of game titles being released all the time.&#xD;&#xA;&#xD;&#xA;VFX and CAD software, on the other hand, is nowhere near as lucrative. R&amp;D is often outsourced by researchers working in academic settings, with a lot of the industry often implementing techniques published many years before as though it's something new. So VFX software, even coming from companies as large as AutoDesk, often isn't quite as &quot;state-of-the-art&quot; as the latest AAA game engines.&#xD;&#xA;&#xD;&#xA;They also tend to have a much longer legacy. Maya is a 17-year old product, for example. It's been refurbished a lot, but its core architecture is still the same. This might be analogous to trying to take Quake 2 and keep updating and updating it all the way up until 2015. The efforts can be great but probably won't match Unreal Engine 4.&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;So anyway, that's a little take on that side of the topic. I couldn't make out whether you were talking about real-time previews in viewports or production rendering, so I tried to cover a bit of both." ContentLicense="CC BY-SA 3.0" />
  <row Id="3779" PostHistoryTypeId="5" PostId="1827" RevisionGUID="47c26a0c-1065-4738-bc9c-7ef404e05c37" CreationDate="2015-12-23T00:23:12.710" UserId="2247" Comment="added 90 characters in body" Text="**Real-Time Preview**&#xD;&#xA;&#xD;&#xA;Working in the VFX side of the industry, if you're talking about real-time viewport previews and not production rendering, then Maya and 3DS Max typically also use OpenGL (or possibly DirectX -- pretty much the same).&#xD;&#xA;&#xD;&#xA;One of the main conceptual differences between VFX animation software and games is the level of assumptions they can make. For example, in VFX software, it's not uncommon for the artist to load a single, seamless character mesh that spans hundreds of thousands to millions of polygons. Games tend to optimize most for a large scene consisting of a boatload of simple, optimized meshes (thousands of triangles each).&#xD;&#xA;&#xD;&#xA;**Production Rendering and Path Tracing**&#xD;&#xA;&#xD;&#xA;VFX software also places the emphasis not on the real-time preview but on production rendering where light rays are actually simulated one at a time. The real-time preview often is just that, a &quot;preview&quot; of the higher-quality production result.&#xD;&#xA;&#xD;&#xA;Games are doing a beautiful job of approximating a lot of those effects lately like real-time depth of field, soft shadows, diffuse reflections, etc., but they're in the heavy-duty approximation category (ex: blurry cube maps for diffuse reflections instead of actually simulating light rays).&#xD;&#xA;&#xD;&#xA;**Content**&#xD;&#xA;&#xD;&#xA;Coming back to this subject, the content assumptions between a VFX software and game wildly differ. A VFX software's main focus is to allow any possible kind of content to be created (at least that's the ideal, although in practically it's often nowhere close). Games focus on content with a lot more heavier assumptions (all models should be in the range of thousands of triangles, normal maps should be applied to fake details, we shouldn't actually have 13 billion particles, characters aren't actually animated by muscle rigs and tension maps, etc).&#xD;&#xA;&#xD;&#xA;Due to those assumptions, game engines can often more easily apply acceleration techniques like frustum culling which enable them to maintain a high, interactive frame rate. VFX software can't easily make those kinds of assumptions given the much higher degree of flexibility in content creation and support. They can make assumptions that some content is going to be static, baked down in advance.&#xD;&#xA;&#xD;&#xA;**Games Do it Better**&#xD;&#xA;&#xD;&#xA;This might be kind of a controversial view, but the game industry is a much more lucrative industry than VFX software. Their budgets for a single game can span in the hundreds of millions of dollars, and they can afford to keep releasing next-generation engines every few years. Their R&amp;D efforts are amazing, and there are hundreds upon hundreds of game titles being released all the time.&#xD;&#xA;&#xD;&#xA;VFX and CAD software, on the other hand, is nowhere near as lucrative. R&amp;D is often outsourced by researchers working in academic settings, with a lot of the industry often implementing techniques published many years before as though it's something new. So VFX software, even coming from companies as large as AutoDesk, often isn't quite as &quot;state-of-the-art&quot; as the latest AAA game engines.&#xD;&#xA;&#xD;&#xA;They also tend to have a much longer legacy. Maya is a 17-year old product, for example. It's been refurbished a lot, but its core architecture is still the same. This might be analogous to trying to take Quake 2 and keep updating and updating it all the way up until 2015. The efforts can be great but probably won't match Unreal Engine 4.&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;So anyway, that's a little take on that side of the topic. I couldn't make out whether you were talking about real-time previews in viewports or production rendering, so I tried to cover a bit of both." ContentLicense="CC BY-SA 3.0" />
  <row Id="3781" PostHistoryTypeId="5" PostId="1827" RevisionGUID="5d0dbb82-ef1d-41a7-8e2d-044c10d63b5a" CreationDate="2015-12-23T05:00:45.190" UserId="2247" Comment="deleted 11 characters in body" Text="**Real-Time Preview**&#xD;&#xA;&#xD;&#xA;Working in the VFX side of the industry, if you're talking about real-time viewport previews and not production rendering, then Maya and 3DS Max typically also use OpenGL (or possibly DirectX -- pretty much the same).&#xD;&#xA;&#xD;&#xA;One of the main conceptual differences between VFX animation software and games is the level of assumptions they can make. For example, in VFX software, it's not uncommon for the artist to load a single, seamless character mesh that spans hundreds of thousands to millions of polygons. Games tend to optimize most for a large scene consisting of a boatload of simple, optimized meshes (thousands of triangles each).&#xD;&#xA;&#xD;&#xA;**Production Rendering and Path Tracing**&#xD;&#xA;&#xD;&#xA;VFX software also places the emphasis not on the real-time preview but on production rendering where light rays are actually simulated one at a time. The real-time preview often is just that, a &quot;preview&quot; of the higher-quality production result.&#xD;&#xA;&#xD;&#xA;Games are doing a beautiful job of approximating a lot of those effects lately like real-time depth of field, soft shadows, diffuse reflections, etc., but they're in the heavy-duty approximation category (ex: blurry cube maps for diffuse reflections instead of actually simulating light rays).&#xD;&#xA;&#xD;&#xA;**Content**&#xD;&#xA;&#xD;&#xA;Coming back to this subject, the content assumptions between a VFX software and game wildly differ. A VFX software's main focus is to allow any possible kind of content to be created (at least that's the ideal, although in practically it's often nowhere close). Games focus on content with a lot more heavier assumptions (all models should be in the range of thousands of triangles, normal maps should be applied to fake details, we shouldn't actually have 13 billion particles, characters aren't actually animated by muscle rigs and tension maps, etc).&#xD;&#xA;&#xD;&#xA;Due to those assumptions, game engines can often more easily apply acceleration techniques like frustum culling which enable them to maintain a high, interactive frame rate. They can make assumptions that some content is going to be static, baked down in advance. VFX software can't easily make those kinds of assumptions given the much higher degree of flexibility in content creation. &#xD;&#xA;&#xD;&#xA;**Games Do it Better**&#xD;&#xA;&#xD;&#xA;This might be kind of a controversial view, but the game industry is a much more lucrative industry than VFX software. Their budgets for a single game can span in the hundreds of millions of dollars, and they can afford to keep releasing next-generation engines every few years. Their R&amp;D efforts are amazing, and there are hundreds upon hundreds of game titles being released all the time.&#xD;&#xA;&#xD;&#xA;VFX and CAD software, on the other hand, is nowhere near as lucrative. R&amp;D is often outsourced by researchers working in academic settings, with a lot of the industry often implementing techniques published many years before as though it's something new. So VFX software, even coming from companies as large as AutoDesk, often isn't quite as &quot;state-of-the-art&quot; as the latest AAA game engines.&#xD;&#xA;&#xD;&#xA;They also tend to have a much longer legacy. Maya is a 17-year old product, for example. It's been refurbished a lot, but its core architecture is still the same. This might be analogous to trying to take Quake 2 and keep updating and updating it all the way up until 2015. The efforts can be great but probably won't match Unreal Engine 4.&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;So anyway, that's a little take on that side of the topic. I couldn't make out whether you were talking about real-time previews in viewports or production rendering, so I tried to cover a bit of both." ContentLicense="CC BY-SA 3.0" />
  <row Id="3782" PostHistoryTypeId="2" PostId="1828" RevisionGUID="fd879287-8c5d-4747-886d-9b41ac743384" CreationDate="2015-12-23T13:22:21.527" UserId="2317" Text="This isn't really a direct answer to this question (that already has an answer anyway), but might interest people who want to implement this algorithm in 3D. If you guys moderating this page think this is inappropriate feel free to delete it.&#xD;&#xA;&#xD;&#xA;I had to try implementing this algorithm to generate 3D spirals in blender using Python (could easily be converted to drawing with PIL or Matplotlib in 2D). So here's the algorithm and result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    import bpy&#xD;&#xA;    from math import cos, sin&#xD;&#xA;    S = bpy.context.scene&#xD;&#xA;    &#xD;&#xA;    def add_archimedian_spiral( size = 0.1, length = 500, height = 1, name = 'archispiral' ):&#xD;&#xA;        mesh = bpy.data.meshes.new( name = name )&#xD;&#xA;    &#xD;&#xA;        o = bpy.data.objects.new(name, mesh)&#xD;&#xA;        o.location = (0,0,0) # place at object origin&#xD;&#xA;        S.objects.link( o )&#xD;&#xA;    &#xD;&#xA;        z     = 0&#xD;&#xA;        verts = []  &#xD;&#xA;        for i in range( length ):&#xD;&#xA;            angle = 0.1 * i&#xD;&#xA;            x     = ( 2 * size * angle ) * cos( angle )&#xD;&#xA;            y     = ( 2 * size * angle ) * sin( angle )&#xD;&#xA;            z    += i / 10000 * height&#xD;&#xA;            verts.append((x,y,z))&#xD;&#xA;    &#xD;&#xA;        edges = []&#xD;&#xA;        for i in range( len( verts ) ):&#xD;&#xA;            if i == len( verts ) - 1: break&#xD;&#xA;            edges.append((i, i+1))&#xD;&#xA;                &#xD;&#xA;        mesh.from_pydata( verts, edges, [] )&#xD;&#xA;        &#xD;&#xA;    add_archimedian_spiral( size = 0.2, length = 500, height = 6 )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dcoM7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3784" PostHistoryTypeId="2" PostId="1829" RevisionGUID="e9257269-3f82-4916-9fe7-7dd3fed0a912" CreationDate="2015-12-23T23:52:07.863" UserId="113" Text="I need to be able to click on this polygon in 2d that has its vertices in another space. I need to convert my mouse coordinates to its space. I have a view matrix for the view (of course) and transform matrix for the polygon. I imagine I need to multiply the matrices in some way then multiply them with the mouse coordinate but I don't know how? Do I need the inverse of one of the matrices?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3785" PostHistoryTypeId="1" PostId="1829" RevisionGUID="e9257269-3f82-4916-9fe7-7dd3fed0a912" CreationDate="2015-12-23T23:52:07.863" UserId="113" Text="How to get mouse coordinates in world space" ContentLicense="CC BY-SA 3.0" />
  <row Id="3786" PostHistoryTypeId="3" PostId="1829" RevisionGUID="e9257269-3f82-4916-9fe7-7dd3fed0a912" CreationDate="2015-12-23T23:52:07.863" UserId="113" Text="|transformations|2d|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3787" PostHistoryTypeId="2" PostId="1830" RevisionGUID="d8ba54a2-f1dd-4464-ad28-2072b1cacfb8" CreationDate="2015-12-24T13:10:00.983" UserId="2335" Text="Suppose i have a 400*300 gray scale image.Now I want to scan each line horizontally and make the average of that line 128,such that the values get scaled as per their difference from mean(128) which will not cause any distortion to image." ContentLicense="CC BY-SA 3.0" />
  <row Id="3788" PostHistoryTypeId="1" PostId="1830" RevisionGUID="d8ba54a2-f1dd-4464-ad28-2072b1cacfb8" CreationDate="2015-12-24T13:10:00.983" UserId="2335" Text="Average intensity of an gray image" ContentLicense="CC BY-SA 3.0" />
  <row Id="3789" PostHistoryTypeId="3" PostId="1830" RevisionGUID="d8ba54a2-f1dd-4464-ad28-2072b1cacfb8" CreationDate="2015-12-24T13:10:00.983" UserId="2335" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3790" PostHistoryTypeId="2" PostId="1831" RevisionGUID="32be93be-c99b-4bd6-9dc8-0ffecabdf681" CreationDate="2015-12-24T14:41:00.023" UserId="2317" Text="Here's an example on how to do this with Python, Numpy and Matplotlib.&#xD;&#xA;Image on the right has been averaged (row by row), while the left is the origianl.&#xD;&#xA;&#xD;&#xA;[![Before-After][1]][1]&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    from matplotlib import image as mpimg&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    &#xD;&#xA;    def rgb2gray(rgb):&#xD;&#xA;        return np.dot( rgb[...,:3], [0.299, 0.587, 0.144] )&#xD;&#xA;    &#xD;&#xA;    imgPath = &quot;C:/myImg.jpg&quot;&#xD;&#xA;    &#xD;&#xA;    # Convert image to numpy array and transpose (PIL and Numpy have a reveresed representation of rows/cols)&#xD;&#xA;    im = mpimg.imread( imgPath )&#xD;&#xA;    gs = rgb2gray( im )&#xD;&#xA;    &#xD;&#xA;    averaged = gs.copy()&#xD;&#xA;    &#xD;&#xA;    for row in averaged:&#xD;&#xA;        rowAvg = sum( row ) / len( row )&#xD;&#xA;        row *= 128 / rowAvg # Scale each row by ratio between 128 and current row avg&#xD;&#xA;    &#xD;&#xA;    plt.subplot( 1, 2, 1 ), plt.imshow( gs,       'gray' )&#xD;&#xA;    plt.subplot( 1, 2, 2 ), plt.imshow( averaged, 'gray' )&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b7pYW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3791" PostHistoryTypeId="5" PostId="1831" RevisionGUID="c1510c9f-598f-46e7-9972-93334e9c0588" CreationDate="2015-12-24T14:49:14.033" UserId="2317" Comment="Another example and syntax highlighting" Text="Here's an example on how to do this with Python, Numpy and Matplotlib.&#xD;&#xA;Image on the right has been averaged (row by row), while the left is the origianl.&#xD;&#xA;&#xD;&#xA;[![Before-After][1]][1]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    from matplotlib import image as mpimg&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    &#xD;&#xA;    def rgb2gray(rgb):&#xD;&#xA;        return np.dot( rgb[...,:3], [0.299, 0.587, 0.144] )&#xD;&#xA;    &#xD;&#xA;    imgPath = &quot;C:/myImg.jpg&quot;&#xD;&#xA;    &#xD;&#xA;    # Convert image to numpy array and transpose (PIL and Numpy have a reveresed representation of rows/cols)&#xD;&#xA;    im = mpimg.imread( imgPath )&#xD;&#xA;    gs = rgb2gray( im )&#xD;&#xA;    &#xD;&#xA;    averaged = gs.copy()&#xD;&#xA;    &#xD;&#xA;    for row in averaged:&#xD;&#xA;        rowAvg = sum( row ) / len( row )&#xD;&#xA;        row *= 128 / rowAvg # Scale each row by ratio between 128 and current row avg&#xD;&#xA;    &#xD;&#xA;    plt.subplot( 1, 2, 1 ), plt.imshow( gs,       'gray' )&#xD;&#xA;    plt.subplot( 1, 2, 2 ), plt.imshow( averaged, 'gray' )&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: python --&gt;&#xD;&#xA;&#xD;&#xA;Here's another test with a simple gradient image (left is the original):&#xD;&#xA;[![Before-After2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b7pYW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DhczR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3792" PostHistoryTypeId="5" PostId="1831" RevisionGUID="e5b21469-99f6-4288-a25f-0bc0689f0d73" CreationDate="2015-12-24T15:32:31.437" UserId="2317" Comment="Removing old and no longer relevant comment" Text="Here's an example on how to do this with Python, Numpy and Matplotlib.&#xD;&#xA;Image on the right has been averaged (row by row), while the left is the origianl.&#xD;&#xA;&#xD;&#xA;[![Before-After][1]][1]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    from matplotlib import image as mpimg&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    &#xD;&#xA;    def rgb2gray(rgb):&#xD;&#xA;        return np.dot( rgb[...,:3], [0.299, 0.587, 0.144] )&#xD;&#xA;    &#xD;&#xA;    imgPath = &quot;C:/myImg.jpg&quot;&#xD;&#xA;    &#xD;&#xA;    im = mpimg.imread( imgPath )&#xD;&#xA;    gs = rgb2gray( im )&#xD;&#xA;    &#xD;&#xA;    averaged = gs.copy()&#xD;&#xA;    &#xD;&#xA;    for row in averaged:&#xD;&#xA;        rowAvg = sum( row ) / len( row )&#xD;&#xA;        row *= 128 / rowAvg # Scale each row by ratio between 128 and current row avg&#xD;&#xA;    &#xD;&#xA;    plt.subplot( 1, 2, 1 ), plt.imshow( gs,       'gray' )&#xD;&#xA;    plt.subplot( 1, 2, 2 ), plt.imshow( averaged, 'gray' )&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: python --&gt;&#xD;&#xA;&#xD;&#xA;Here's another test with a simple gradient image (left is the original):&#xD;&#xA;[![Before-After2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b7pYW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DhczR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3794" PostHistoryTypeId="2" PostId="1832" RevisionGUID="d666040d-23f3-4223-9d73-1719ab440b37" CreationDate="2015-12-24T23:16:22.657" UserId="2339" Text="I'm not too versed in computer graphics so my question may be vague.&#xD;&#xA;&#xD;&#xA;I'm given a sequence of GPS coordinates which I draw on an iOS map, and they define bus routes. Some of the bus routes happen to share sections of certain streets however, and when multiple routes are being drawn on the map the colored line segments are just being overlapped currently.&#xD;&#xA;&#xD;&#xA;I'm currently looking into computationally separating the lines from each other before drawing, but I'm not sure that will get any success. So my backup is: are there any good techniques to draw the lines in a way that somehow does not hide the lower line segments, and retains at least partially their color?&#xD;&#xA;&#xD;&#xA;Again as a disclosure, I'm not very knowledgable in this area. I know from Photoshop there are different color modes on the layers that have different effects when overlapped. Would something of that sort help in this situation? Or maybe there's a way to dash the lines such that it alternates each color, but I imagine that would be fairly difficult.&#xD;&#xA;&#xD;&#xA;I'm just probing around for different techniques for this problem. Thank you for your help." ContentLicense="CC BY-SA 3.0" />
  <row Id="3795" PostHistoryTypeId="1" PostId="1832" RevisionGUID="d666040d-23f3-4223-9d73-1719ab440b37" CreationDate="2015-12-24T23:16:22.657" UserId="2339" Text="Best technique to draw overlapping colored line segments that follow the same route" ContentLicense="CC BY-SA 3.0" />
  <row Id="3796" PostHistoryTypeId="3" PostId="1832" RevisionGUID="d666040d-23f3-4223-9d73-1719ab440b37" CreationDate="2015-12-24T23:16:22.657" UserId="2339" Text="|rendering|shader|color|line-drawing|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3797" PostHistoryTypeId="2" PostId="1833" RevisionGUID="a2bd4289-264d-4583-b690-88ce9bff824c" CreationDate="2015-12-25T03:54:51.673" UserId="2341" Text="I'm not sure whether this is the right community to ask this question, but there did not seem to a more appropriate one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the pixel-level explanation of the fade effect, that was first popularized by Instagram. I want to implement this effect programmatically—that is, I want to understand what this effect is doing to each pixel.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Also, if anyone could point me to resources from which I can learn more about how image filters are implemented, that would be great.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IVdTT.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3798" PostHistoryTypeId="1" PostId="1833" RevisionGUID="a2bd4289-264d-4583-b690-88ce9bff824c" CreationDate="2015-12-25T03:54:51.673" UserId="2341" Text="Instagram's fade effect" ContentLicense="CC BY-SA 3.0" />
  <row Id="3799" PostHistoryTypeId="3" PostId="1833" RevisionGUID="a2bd4289-264d-4583-b690-88ce9bff824c" CreationDate="2015-12-25T03:54:51.673" UserId="2341" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3800" PostHistoryTypeId="5" PostId="1833" RevisionGUID="49de2788-3693-4253-ad17-6a3f57498ff6" CreationDate="2015-12-25T08:57:16.757" UserId="2341" Comment="edited body" Text="I'm not sure whether this is the right community to ask this question, but there did not seem to a more appropriate one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the pixel-level explanation of the fade effect, that was first popularized by Instagram? I want to implement this effect programmatically—that is, I want to understand what this effect is doing to each pixel.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Also, if anyone could point me to resources from which I can learn more about how image filters are implemented, that would be great.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IVdTT.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3801" PostHistoryTypeId="5" PostId="1831" RevisionGUID="97d4841c-e278-4b82-8279-5a59984ea7a3" CreationDate="2015-12-25T09:40:22.547" UserId="2317" Comment="Fixed issues with max value and zero value row average, setting up syntax highlighting finally" Text="Here's an example on how to do this with Python, Numpy and Matplotlib.&#xD;&#xA;Image on the right has been averaged (row by row), while the left is the origianl.&#xD;&#xA;&#xD;&#xA;[![Before-After-Edited][1]][1]&#xD;&#xA;&#xD;&#xA;**EDITED**: As suggested by @Nathan Reed, I avoided flipping colors when row average is 0. Rows with an average of 0 now get a value of 0.5 (128). The dark image encountered previously was due to values higher than 1 (255) due to scaling, that were represented as white matplotlib in the image renderer. I fixed this by setting the max value in any pixel to be 1.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    from matplotlib import image as mpimg&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    &#xD;&#xA;    def rgb2gray(rgb):&#xD;&#xA;        return np.dot( rgb[...,:3], [0.299, 0.587, 0.144] )&#xD;&#xA;    &#xD;&#xA;    imgPath = &quot;C:/myImg.jpg&quot;&#xD;&#xA;    &#xD;&#xA;    im = mpimg.imread( imgPath )&#xD;&#xA;    gs = rgb2gray( im )&#xD;&#xA;    &#xD;&#xA;    averaged = gs.copy()&#xD;&#xA;    &#xD;&#xA;    for row in averaged:&#xD;&#xA;        rowAvg = sum( row ) / len( row )&#xD;&#xA;        if rowAvg == 0:&#xD;&#xA;            row = 0.5&#xD;&#xA;        else:&#xD;&#xA;            # Scale each row by ratio between 128 and current row avg&#xD;&#xA;            row *= 0.5 / rowAvg&#xD;&#xA;    &#xD;&#xA;        if rowAvg &gt; 0: row[row&gt;1] = 1&#xD;&#xA;    &#xD;&#xA;    plt.subplot( 1, 2, 1 ), plt.imshow( gs,       'gray' )&#xD;&#xA;    plt.subplot( 1, 2, 2 ), plt.imshow( averaged, 'gray' )&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;Here's another test with a simple gradient image (left is the original):&#xD;&#xA;[![Before-After2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V4wFH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DhczR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3802" PostHistoryTypeId="2" PostId="1834" RevisionGUID="e9875ca0-5582-4b34-8cf7-5089a8c89013" CreationDate="2015-12-25T12:28:38.090" UserId="1988" Text="# If you want to do it geometrically...&#xA;&#xA;The inverse of the view-projection matrix, K^{-1} is the matrix you want. Where $K = View * Projection$&#xA;&#xA;If $\vec{v}$ is a point in homogeneous screen coordinates, $[x, y, 1]$ where x and y are whatever coordinates your K matrix projects onto. &#xA;&#xA;$\vec{d} = K^{-1} * \vec{v}$&#xA;&#xA;Where $\vec{d}$ now represents a **line** in homogeneous coordinates, coming out of your camera origin. Now you'd iterate through the objects in view, and choose the closest one in front of the camera that this line intersects with.&#xA;&#xA;# But there are other ways!&#xA;&#xA;### Color Picking&#xA;Here, we render (into a buffer) each object in view with a slightly different color, which corresponds to the object ID. We then read it using glReadPixels(mouse_coordinates...) and decide which object we clicked. This is pretty easy to do in the new pipeline - you just write a color passthrough shader. Would not recommend pre Opengl 3.0 (You'll have to do shenanigans to render the scene without interference)&#xA;&#xA;### Selection Buffer (Old pipeline)&#xA;&#xA;If you're on the fixed pipeline, you get a nice little toy called the [selection buffer](http://www.glprogramming.com/red/chapter13.html) to do the work for you.&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3803" PostHistoryTypeId="2" PostId="1835" RevisionGUID="7b102c78-c521-430d-b73e-b38ef4866af0" CreationDate="2015-12-25T15:40:21.760" UserId="2343" Text="I need to build terrain using one cube with dimensions 1x1x1, the coordinates are provided in a .txt file and there are about 11M triplets.&#xD;&#xA;&#xD;&#xA;The problem is that using my current code I can only draw about 60k of them, then the browser tab is resetted and a prompt to stop an unresponsive script comes out, so I use too much memory and time to generate them.&#xD;&#xA;&#xD;&#xA;Here is the chunk of code I use to draw them:&#xD;&#xA;&#xD;&#xA;    function generateCubes(data) {&#xD;&#xA;        var cubeGeometry = new THREE.CubeGeometry(cubeSize, cubeSize, cubeSize);&#xD;&#xA;        var material = new THREE.MeshLambertMaterial({color: 0x587058});&#xD;&#xA;        var mesh = new THREE.Mesh(cubeGeometry, material);&#xD;&#xA;        var mergedGeo = new THREE.Geometry();&#xD;&#xA;        var instance;&#xD;&#xA;        var line = data[0].split(';');&#xD;&#xA;        var translateX = line[0], translateY = line[1], translateZ = line[2];&#xD;&#xA;        //var group = new THREE.Object3d();&#xD;&#xA;        for(var i = 0; i &lt; 100000; i++) { // should go to data.length&#xD;&#xA;            line = data[i].split(';');&#xD;&#xA;            //instance = mesh.clone();&#xD;&#xA;            //instance.position.set(line[0] - translateX, line[2] - translateZ, line[1] - translateY);&#xD;&#xA;            //group.add(instance);&#xD;&#xA;            mesh.position.x = Number(line[0]) - translateX;&#xD;&#xA;            mesh.position.y = Math.round(Number(line[2]) - translateZ);&#xD;&#xA;            mesh.position.z = Number(line[1]) - translateY;&#xD;&#xA;            mesh.updateMatrix();&#xD;&#xA;            mergedGeo.merge(instance.geometry, instance.matrix);&#xD;&#xA;        }&#xD;&#xA;        group = new THREE.Mesh(mergedGeo, material);&#xD;&#xA;        scene.add(group);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The function is called from a success in an $.ajax call.&#xD;&#xA;&#xD;&#xA;The commented parts are used without merged geometry, that way I can draw around 100k of the data.&#xD;&#xA;&#xD;&#xA;Thank you for helping me." ContentLicense="CC BY-SA 3.0" />
  <row Id="3804" PostHistoryTypeId="1" PostId="1835" RevisionGUID="7b102c78-c521-430d-b73e-b38ef4866af0" CreationDate="2015-12-25T15:40:21.760" UserId="2343" Text="Drawing a cube a million times" ContentLicense="CC BY-SA 3.0" />
  <row Id="3805" PostHistoryTypeId="3" PostId="1835" RevisionGUID="7b102c78-c521-430d-b73e-b38ef4866af0" CreationDate="2015-12-25T15:40:21.760" UserId="2343" Text="|geometry|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3806" PostHistoryTypeId="5" PostId="1831" RevisionGUID="b9d0c9b0-6a8e-4de2-9c02-833bc8234bfe" CreationDate="2015-12-25T22:48:07.470" UserId="2317" Comment="grammar nazi in action, and comment added" Text="Here's an example on how to do this with Python, Numpy and Matplotlib.&#xD;&#xA;Image on the right has been averaged (row by row), while the left is the original.&#xD;&#xA;&#xD;&#xA;[![Before-After-Edited][1]][1]&#xD;&#xA;&#xD;&#xA;**EDITED**: As suggested by @Nathan Reed, I avoided flipping colors when row average is 0. Rows with an average of 0 now get a value of 0.5 (128). The dark image encountered previously was due to values higher than 1 (255) due to scaling, that were represented as white in matplotlib's image renderer. I fixed this by setting the max value in any pixel to be 1.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    from matplotlib import image as mpimg&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    &#xD;&#xA;    def rgb2gray(rgb):&#xD;&#xA;        return np.dot( rgb[...,:3], [0.299, 0.587, 0.144] )&#xD;&#xA;    &#xD;&#xA;    imgPath = &quot;C:/myImg.jpg&quot;&#xD;&#xA;    &#xD;&#xA;    im = mpimg.imread( imgPath )&#xD;&#xA;    gs = rgb2gray( im )&#xD;&#xA;    &#xD;&#xA;    averaged = gs.copy()&#xD;&#xA;    &#xD;&#xA;    for row in averaged:&#xD;&#xA;        rowAvg = sum( row ) / len( row )&#xD;&#xA;        if rowAvg == 0:&#xD;&#xA;            row = 0.5&#xD;&#xA;        else:&#xD;&#xA;            # Scale each row by ratio between 128 and current row avg&#xD;&#xA;            row *= 0.5 / rowAvg&#xD;&#xA;    &#xD;&#xA;        # Make sure that no pixel has a higher value than 1&#xD;&#xA;        if rowAvg &gt; 0: row[row&gt;1] = 1&#xD;&#xA;    &#xD;&#xA;    plt.subplot( 1, 2, 1 ), plt.imshow( gs,       'gray' )&#xD;&#xA;    plt.subplot( 1, 2, 2 ), plt.imshow( averaged, 'gray' )&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;Here's another test with a simple gradient image (left is the original):&#xD;&#xA;[![Before-After2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V4wFH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DhczR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3807" PostHistoryTypeId="2" PostId="1836" RevisionGUID="9e0bbf02-4d5c-4c08-9fac-59bed47c688e" CreationDate="2015-12-26T02:28:48.480" UserId="1988" Text="You could:&#xA;&#xA;- Draw them all with different widths and make each transparent (fiddling with alpha blend to make it look nice). Or make the depth proportional to the width, so the widest is always drawn at the bottom of the pyramid. The naive implementation would suffer with many routes.&#xA;&#xA;- Not do anything special at intersections, and expect the user to infer what is going on from context.&#xA;&#xA;- &quot;PWM&quot; the colors of the lines, one way to do this might be to make a chessboard-like grid texture of 0's and 1's, and depending on whether there is a zero or a one where the road falls, choose the color to draw. &#xA;&#xA;- You could use the above technique for multiple line colors by further subdividing the grid with multiple colors. This would be tedious to do in a shader, but is trivial using a normal CPU image manipulation library.&#xA;&#xA;Here is a bus routing app (Transloc Rider) that does this pretty well. &#xA;&#xA;[![transloc rider][1]][1]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/LFHFj.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3809" PostHistoryTypeId="2" PostId="1837" RevisionGUID="93d08777-13b4-485f-9dd5-4ffb0dfd777c" CreationDate="2015-12-26T14:05:08.853" UserId="38" Text="This question should most probably be asked on [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](http://ux.stackexchange.com/). These sites specialize in how to design the graphics and how to choose the graphics for your purpose. But since you are here basic options are:&#xD;&#xA;&#xD;&#xA;1. Routes dont overlap but are parallel like electronic layouts (image 1, A), Works well unless you have many overlapping things.&#xD;&#xA;2. Space interleaved lines, differently colored line regions (image 1, B). Such as dashed lines, however many other interleaved shapes are possible. &#xD;&#xA;3. Spatial solutions, lines on top of each other but laid over in 3d (image 1, C), Works well in isometric drawing.&#xD;&#xA;4. Different line widths (image 1, D)&#xD;&#xA;5. User suggested, overlay (image 1, E).&#xD;&#xA;6. Same color but labels on segments (image 1, F), note not all segments need to be labeled as humans can interpolate values somewhat. This has benefit of being able to be paired with any other effect and works well with selection highlights with info intact. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 1**: Differenet overlay methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note none except the labeling works of there are very many different lines as humans capability to see different colors in this kind of context as differing data is not very good (ask [UX.SE](http://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;As for what is best depends. None of these are particularity hard to do in code or vector drawing application (but that is out of scope ask [GD.SE](http://graphicdesign.stackexchange.com/)). Whichever is best for the user or the design is also not within the scope of this software (ask  [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](http://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ZfX0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3810" PostHistoryTypeId="5" PostId="1837" RevisionGUID="983249c1-b017-4c46-9385-af29dae9bff4" CreationDate="2015-12-26T14:11:00.000" UserId="38" Comment="deleted 1 character in body" Text="This question should most probably be asked on [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](http://ux.stackexchange.com/). These sites specialize in how to design the graphics and how to choose the graphics for your purpose. But since you are here basic options are:&#xD;&#xA;&#xD;&#xA;1. Routes dont overlap but are parallel like electronic layouts (image 1, A), Works well unless you have many overlapping things.&#xD;&#xA;2. Space interleaved lines, differently colored line regions (image 1, B). Such as dashed lines, however many other interleaved shapes are possible. &#xD;&#xA;3. Spatial solutions, lines on top of each other but laid over in 3d (image 1, C), Works well in isometric drawing.&#xD;&#xA;4. Different line widths (image 1, D)&#xD;&#xA;5. User suggested, overlay (image 1, E).&#xD;&#xA;6. Same color but labels on segments (image 1, F), note not all segments need to be labeled as humans can interpolate values somewhat. This has benefit of being able to be paired with any other effect and works well with selection highlights with info intact. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 1**: Different overlay methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note none except the labeling works of there are very many different lines as humans capability to see different colors in this kind of context as differing data is not very good (ask [UX.SE](http://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;As for what is best depends. None of these are particularity hard to do in code or vector drawing application (but that is out of scope ask [GD.SE](http://graphicdesign.stackexchange.com/)). Whichever is best for the user or the design is also not within the scope of this software (ask  [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](http://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ZfX0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3811" PostHistoryTypeId="5" PostId="1828" RevisionGUID="25067843-61d6-4d16-8b36-a7bb117284ca" CreationDate="2015-12-26T15:50:42.340" UserId="127" Comment="Removed note to moderators." Text="This isn't really a direct answer to this question (that already has an answer anyway), but might interest people who want to implement this algorithm in 3D.&#xD;&#xA;&#xD;&#xA;I had to try implementing this algorithm to generate 3D spirals in blender using Python (could easily be converted to drawing with PIL or Matplotlib in 2D). So here's the algorithm and result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    import bpy&#xD;&#xA;    from math import cos, sin&#xD;&#xA;    S = bpy.context.scene&#xD;&#xA;    &#xD;&#xA;    def add_archimedian_spiral( size = 0.1, length = 500, height = 1, name = 'archispiral' ):&#xD;&#xA;        mesh = bpy.data.meshes.new( name = name )&#xD;&#xA;    &#xD;&#xA;        o = bpy.data.objects.new(name, mesh)&#xD;&#xA;        o.location = (0,0,0) # place at object origin&#xD;&#xA;        S.objects.link( o )&#xD;&#xA;    &#xD;&#xA;        z     = 0&#xD;&#xA;        verts = []  &#xD;&#xA;        for i in range( length ):&#xD;&#xA;            angle = 0.1 * i&#xD;&#xA;            x     = ( 2 * size * angle ) * cos( angle )&#xD;&#xA;            y     = ( 2 * size * angle ) * sin( angle )&#xD;&#xA;            z    += i / 10000 * height&#xD;&#xA;            verts.append((x,y,z))&#xD;&#xA;    &#xD;&#xA;        edges = []&#xD;&#xA;        for i in range( len( verts ) ):&#xD;&#xA;            if i == len( verts ) - 1: break&#xD;&#xA;            edges.append((i, i+1))&#xD;&#xA;                &#xD;&#xA;        mesh.from_pydata( verts, edges, [] )&#xD;&#xA;        &#xD;&#xA;    add_archimedian_spiral( size = 0.2, length = 500, height = 6 )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dcoM7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3812" PostHistoryTypeId="5" PostId="1834" RevisionGUID="4758c5a1-a1a3-40dd-9601-e96504ab38d0" CreationDate="2015-12-26T15:57:53.930" UserId="127" Comment="Edited formatting" Text="# If you want to do it geometrically...&#xD;&#xA;&#xD;&#xA;The inverse of the view-projection matrix, $K^{-1}$ is the matrix you want. Where $K = View * Projection$&#xD;&#xA;&#xD;&#xA;If $\vec{v}$ is a point in homogeneous screen coordinates, $[x, y, 1]$ where $x$ and $y$ are whatever coordinates your $K$ matrix projects onto. &#xD;&#xA;&#xD;&#xA;$$\vec{d} = K^{-1} * \vec{v}$$&#xD;&#xA;&#xD;&#xA;Where $\vec{d}$ now represents a **line** in homogeneous coordinates, coming out of your camera origin. Now you'd iterate through the objects in view, and choose the closest one in front of the camera that this line intersects with.&#xD;&#xA;&#xD;&#xA;# But there are other ways!&#xD;&#xA;&#xD;&#xA;### Color Picking&#xD;&#xA;Here, we render (into a buffer) each object in view with a slightly different color, which corresponds to the object ID. We then read it using `glReadPixels(mouse_coordinates...)` and decide which object we clicked. This is pretty easy to do in the new pipeline - you just write a color passthrough shader. Would not recommend pre OpenGL 3.0 (You'll have to do shenanigans to render the scene without interference)&#xD;&#xA;&#xD;&#xA;### Selection Buffer (Old pipeline)&#xD;&#xA;&#xD;&#xA;If you're on the fixed pipeline, you get a nice little toy called the [selection buffer](http://www.glprogramming.com/red/chapter13.html) to do the work for you.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3813" PostHistoryTypeId="5" PostId="1835" RevisionGUID="a3be1477-f5a8-4e1b-947a-725db46d824c" CreationDate="2015-12-26T16:10:07.643" UserId="127" Comment="Added proper syntax-highlighting, removed salutation" Text="I need to build terrain using one cube with dimensions 1x1x1, the coordinates are provided in a .txt file and there are about 11M triplets.&#xD;&#xA;&#xD;&#xA;The problem is that using my current code I can only draw about 60k of them, then the browser tab is resetted and a prompt to stop an unresponsive script comes out, so I use too much memory and time to generate them.&#xD;&#xA;&#xD;&#xA;Here is the chunk of code I use to draw them:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;    function generateCubes(data) {&#xD;&#xA;        var cubeGeometry = new THREE.CubeGeometry(cubeSize, cubeSize, cubeSize);&#xD;&#xA;        var material = new THREE.MeshLambertMaterial({color: 0x587058});&#xD;&#xA;        var mesh = new THREE.Mesh(cubeGeometry, material);&#xD;&#xA;        var mergedGeo = new THREE.Geometry();&#xD;&#xA;        var instance;&#xD;&#xA;        var line = data[0].split(';');&#xD;&#xA;        var translateX = line[0], translateY = line[1], translateZ = line[2];&#xD;&#xA;        //var group = new THREE.Object3d();&#xD;&#xA;        for(var i = 0; i &lt; 100000; i++) { // should go to data.length&#xD;&#xA;            line = data[i].split(';');&#xD;&#xA;            //instance = mesh.clone();&#xD;&#xA;            //instance.position.set(line[0] - translateX, line[2] - translateZ, line[1] - translateY);&#xD;&#xA;            //group.add(instance);&#xD;&#xA;            mesh.position.x = Number(line[0]) - translateX;&#xD;&#xA;            mesh.position.y = Math.round(Number(line[2]) - translateZ);&#xD;&#xA;            mesh.position.z = Number(line[1]) - translateY;&#xD;&#xA;            mesh.updateMatrix();&#xD;&#xA;            mergedGeo.merge(instance.geometry, instance.matrix);&#xD;&#xA;        }&#xD;&#xA;        group = new THREE.Mesh(mergedGeo, material);&#xD;&#xA;        scene.add(group);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The function is called from a success in an `$.ajax` call.&#xD;&#xA;&#xD;&#xA;The commented parts are used without merged geometry, that way I can draw around 100k of the data." ContentLicense="CC BY-SA 3.0" />
  <row Id="3817" PostHistoryTypeId="5" PostId="1832" RevisionGUID="05bf5385-d4dd-4e60-a56a-afc8a116bd26" CreationDate="2015-12-26T18:34:47.877" UserId="127" Comment="Removed salutation" Text="I'm not too versed in computer graphics so my question may be vague.&#xD;&#xA;&#xD;&#xA;I'm given a sequence of GPS coordinates which I draw on an iOS map, and they define bus routes. Some of the bus routes happen to share sections of certain streets however, and when multiple routes are being drawn on the map the colored line segments are just being overlapped currently.&#xD;&#xA;&#xD;&#xA;I'm currently looking into computationally separating the lines from each other before drawing, but I'm not sure that will get any success. So my backup is: are there any good techniques to draw the lines in a way that somehow does not hide the lower line segments, and retains at least partially their color?&#xD;&#xA;&#xD;&#xA;Again as a disclosure, I'm not very knowledgable in this area. I know from Photoshop there are different color modes on the layers that have different effects when overlapped. Would something of that sort help in this situation? Or maybe there's a way to dash the lines such that it alternates each color, but I imagine that would be fairly difficult.&#xD;&#xA;&#xD;&#xA;I'm just probing around for different techniques for this problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="3819" PostHistoryTypeId="5" PostId="1829" RevisionGUID="468125b2-8cfa-42b9-8331-630018d34a4f" CreationDate="2015-12-26T18:50:11.920" UserId="113" Comment="deleted 24 characters in body; edited title" Text="I need to be able to click on this polygon in 2d. This polygons set of vertices aren't in the same space as the screen. (Ie: the edge of the screen may be a value of 20 in one space but 1920 in the other) the scale is different. How can I convert the vertices of the polygon to the screen space so that I can use the mouse coordinates to click on it. (This is only 2d)" ContentLicense="CC BY-SA 3.0" />
  <row Id="3820" PostHistoryTypeId="4" PostId="1829" RevisionGUID="468125b2-8cfa-42b9-8331-630018d34a4f" CreationDate="2015-12-26T18:50:11.920" UserId="113" Comment="deleted 24 characters in body; edited title" Text="How to get polygon coordinates in screen space" ContentLicense="CC BY-SA 3.0" />
  <row Id="3821" PostHistoryTypeId="5" PostId="1834" RevisionGUID="e372df0b-bd56-4ef1-89d6-710265e4a243" CreationDate="2015-12-26T22:21:54.680" UserId="1988" Comment="added 45 characters in body" Text="**Edit:** This answer is only helpful in 3D&#xA;&#xA;# If you want to do it geometrically...&#xD;&#xA;&#xD;&#xA;The inverse of the view-projection matrix, $K^{-1}$ is the matrix you want. Where $K = View * Projection$&#xD;&#xA;&#xD;&#xA;If $\vec{v}$ is a point in homogeneous screen coordinates, $[x, y, 1]$ where $x$ and $y$ are whatever coordinates your $K$ matrix projects onto. &#xD;&#xA;&#xD;&#xA;$$\vec{d} = K^{-1} * \vec{v}$$&#xD;&#xA;&#xD;&#xA;Where $\vec{d}$ now represents a **line** in homogeneous coordinates, coming out of your camera origin. Now you'd iterate through the objects in view, and choose the closest one in front of the camera that this line intersects with.&#xD;&#xA;&#xD;&#xA;# But there are other ways!&#xD;&#xA;&#xD;&#xA;### Color Picking&#xD;&#xA;Here, we render (into a buffer) each object in view with a slightly different color, which corresponds to the object ID. We then read it using `glReadPixels(mouse_coordinates...)` and decide which object we clicked. This is pretty easy to do in the new pipeline - you just write a color passthrough shader. Would not recommend pre OpenGL 3.0 (You'll have to do shenanigans to render the scene without interference)&#xD;&#xA;&#xD;&#xA;### Selection Buffer (Old pipeline)&#xD;&#xA;&#xD;&#xA;If you're on the fixed pipeline, you get a nice little toy called the [selection buffer](http://www.glprogramming.com/red/chapter13.html) to do the work for you.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3822" PostHistoryTypeId="5" PostId="1837" RevisionGUID="27fe2911-35e9-4149-b0a3-ac13f9754b7b" CreationDate="2015-12-26T23:34:56.133" UserId="38" Comment="added 9 characters in body" Text="This question should most probably be asked on [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](http://ux.stackexchange.com/). These sites specialize in how to design the graphics and how to choose the graphics for your purpose. But since you are here basic options are:&#xD;&#xA;&#xD;&#xA;1. Routes dont overlap but are parallel like electronic layouts (image 1, A), Works well unless you have many overlapping things.&#xD;&#xA;2. Space interleaved lines, differently colored line regions (image 1, B). Such as dashed lines, however many other interleaved shapes are possible. &#xD;&#xA;3. Spatial solutions, lines on top of each other but laid over in 3d (image 1, C), Works well in isometric drawing.&#xD;&#xA;4. Different line widths (image 1, D)&#xD;&#xA;5. User suggested, overlay (image 1, E).&#xD;&#xA;6. Same color but labels on segments (image 1, F), note not all segments need to be labeled as humans can interpolate values somewhat. This has benefit of being able to be paired with any other effect and works well with selection highlights with info intact. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 1**: Different overlay methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: None, except the labeling works well when there are very many different lines as humans capability to see different colors in this kind of context as differing data is not very good (ask [UX.SE](http://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;As for what is best depends. None of these are particularity hard to do in code or vector drawing application (but that is out of scope ask [GD.SE](http://graphicdesign.stackexchange.com/)). Whichever is best for the user or the design is also not within the scope of this software (ask  [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](http://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ZfX0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3823" PostHistoryTypeId="2" PostId="1839" RevisionGUID="52a54f27-57e7-4d12-931c-4b21fd5969e1" CreationDate="2015-12-27T13:29:16.620" UserId="2248" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(z - previousZ, x - previousX) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4YZbt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3824" PostHistoryTypeId="1" PostId="1839" RevisionGUID="52a54f27-57e7-4d12-931c-4b21fd5969e1" CreationDate="2015-12-27T13:29:16.620" UserId="2248" Text="Angle between two points in Cartesian coordinate system C++" ContentLicense="CC BY-SA 3.0" />
  <row Id="3825" PostHistoryTypeId="3" PostId="1839" RevisionGUID="52a54f27-57e7-4d12-931c-4b21fd5969e1" CreationDate="2015-12-27T13:29:16.620" UserId="2248" Text="|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3826" PostHistoryTypeId="5" PostId="1833" RevisionGUID="ddc612fe-772d-4769-8af2-745aa0e94d09" CreationDate="2015-12-27T13:35:16.263" UserId="231" Comment="Remove preamble" Text="What is the pixel-level explanation of the fade effect, that was first popularized by Instagram? I want to implement this effect programmatically—that is, I want to understand what this effect is doing to each pixel.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Also, if anyone could point me to resources from which I can learn more about how image filters are implemented, that would be great.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IVdTT.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="3828" PostHistoryTypeId="5" PostId="1839" RevisionGUID="b6e7e76c-9d84-4935-8190-f615c2b4aaca" CreationDate="2015-12-27T14:12:43.057" UserId="2248" Comment="added 2 characters in body" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(previousZ - z, previousX - x) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sk2W2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3829" PostHistoryTypeId="2" PostId="1840" RevisionGUID="bf968aa3-fd43-4eaa-a655-fb9c8fc8ea36" CreationDate="2015-12-27T14:20:42.503" UserId="38" Text="The parametric equation for a spiral is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA;    x &amp;= &amp;(a + b \theta) \times \cos(\theta)\\&#xD;&#xA;    z &amp;= &amp;(a + b \theta) \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The direction on the spiral point is simply the derivative of the system with respect to $\theta$. Thus the direction is: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA; x &amp;=&amp;-(a + b \theta) \times \sin(\theta) + b \times \cos(\theta)\\&#xD;&#xA; y &amp;=&amp;(a + b \theta) \times \cos(\theta) + b \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Finally angle is is simply atan2 of the direction equation. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3830" PostHistoryTypeId="5" PostId="1840" RevisionGUID="6db3cc85-bd12-41b5-a38b-78467846487b" CreationDate="2015-12-27T14:49:49.010" UserId="38" Comment="edited body" Text="The parametric equation for a spiral is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA;    x &amp;= &amp;(a + b \theta) \times \cos(\theta)\\&#xD;&#xA;    z &amp;= &amp;(a + b \theta) \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The direction on the spiral point is simply the derivative of the system with respect to $\theta$. Thus the direction is: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA; x &amp;=&amp;-(a + b \theta) \times \sin(\theta) + b \times \cos(\theta)\\&#xD;&#xA; z &amp;=&amp;(a + b \theta) \times \cos(\theta) + b \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Finally angle is is simply atan2 of the direction equation. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3831" PostHistoryTypeId="5" PostId="1840" RevisionGUID="20145554-2948-4e4a-a356-1644defc89d7" CreationDate="2015-12-27T15:10:36.987" UserId="38" Comment="added 179 characters in body" Text="The parametric equation for a spiral is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA;    x &amp;= &amp;(a + b \theta) \times \cos(\theta)\\&#xD;&#xA;    z &amp;= &amp;(a + b \theta) \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The direction on the spiral point is simply the derivative of the system with respect to $\theta$. Thus the direction is: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA; x_{dir} &amp;=&amp;-(a + b \theta) \times \sin(\theta) + b \times \cos(\theta)\\&#xD;&#xA; z_{dir} &amp;=&amp;(a + b \theta) \times \cos(\theta) + b \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Finally angle is is simply atan2 of the direction equation. &#xD;&#xA;&#xD;&#xA;[![Spiral][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: This is what I get when i plot squares at $(x, y)$ with direction $(x_{dir}, y_{dir})$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bcKzY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3832" PostHistoryTypeId="5" PostId="1840" RevisionGUID="bf38162c-e3b8-4a8a-856a-15e70fdb7d2b" CreationDate="2015-12-27T15:16:17.587" UserId="38" Comment="added 62 characters in body" Text="The parametric equation for a spiral is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA;    x &amp;= &amp;(a + b \theta) \times \cos(\theta)\\&#xD;&#xA;    z &amp;= &amp;(a + b \theta) \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The direction on the spiral point is simply the derivative of the system with respect to $\theta$. Thus the direction is: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\begin{aligned}&#xD;&#xA; x_{dir} &amp;=&amp;-(a + b \theta) \times \sin(\theta) + b \times \cos(\theta)\\&#xD;&#xA; z_{dir} &amp;=&amp;(a + b \theta) \times \cos(\theta) + b \times \sin(\theta)&#xD;&#xA;\end{aligned}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Finally angle is is simply atan2 of the direction equation. &#xD;&#xA;&#xD;&#xA;[![Spiral][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: This is what I get when i plot squares at $(x, z)$ with direction $(x_{dir}, z_{dir})$&#xD;&#xA;&#xD;&#xA;Mathematica [source](http://pastebin.com/ukNFUiPc) for image&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bcKzY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3833" PostHistoryTypeId="5" PostId="1839" RevisionGUID="aaf3e876-93d7-4d78-adce-fba5572dfa43" CreationDate="2015-12-27T15:16:46.360" UserId="2248" Comment="added 817 characters in body" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(previousZ - z, previousX - x) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT: After trying the below code&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float dirX = -(a + b * angle) * sin(angle) + b * cos(angle);&#xD;&#xA;		float dirZ = (a + b * angle) * cos(angle) + b * sin(angle);&#xD;&#xA;		float newAngle = atan2(dirZ, dirX) * 180 / PI;&#xD;&#xA;		temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sk2W2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/0imwa.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3834" PostHistoryTypeId="5" PostId="1839" RevisionGUID="bbae2d06-25d1-4b34-8ef0-6a107cdec5c4" CreationDate="2015-12-27T15:39:11.223" UserId="2248" Comment="added 74 characters in body" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xA;Im using the Bullet pyhics library and freeglut for the 3d application. &#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(previousZ - z, previousX - x) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT: After trying the below code&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float dirX = -(a + b * angle) * sin(angle) + b * cos(angle);&#xD;&#xA;		float dirZ = (a + b * angle) * cos(angle) + b * sin(angle);&#xD;&#xA;		float newAngle = atan2(dirZ, dirX) * 180 / PI;&#xD;&#xA;		temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sk2W2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/0imwa.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3835" PostHistoryTypeId="5" PostId="1839" RevisionGUID="27e954e5-d70a-4711-b183-64cc18c889c5" CreationDate="2015-12-27T16:13:58.153" UserId="2248" Comment="added 107 characters in body" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xD;&#xA;Im using the Bullet pyhics library and freeglut for the 3d application. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(previousZ - z, previousX - x) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT: After trying the below code&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float dirX = -(a + b * angle) * sin(angle) + b * cos(angle);&#xD;&#xA;		float dirZ = (a + b * angle) * cos(angle) + b * sin(angle);&#xD;&#xA;		float newAngle = atan2(dirZ, dirX) * 180 / PI;&#xD;&#xA;		temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Console output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sk2W2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/0imwa.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/PAdKT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3840" PostHistoryTypeId="2" PostId="1842" RevisionGUID="76a97ebc-bcfb-4709-854e-a9faa43e065e" CreationDate="2015-12-27T23:25:14.957" UserId="2355" Text="Well, Im programming on mac (I really like it because the well, the terminal) and I'm learning opengl in the lib glfw. The problem is that mac has until the version 4.1 of opengl, but when I try to compile the shaders with `version 410` it says `ERROR: 0:1: '' :  version '410' is not supported`. So I would like to know how to set the version that glfw should use." ContentLicense="CC BY-SA 3.0" />
  <row Id="3841" PostHistoryTypeId="1" PostId="1842" RevisionGUID="76a97ebc-bcfb-4709-854e-a9faa43e065e" CreationDate="2015-12-27T23:25:14.957" UserId="2355" Text="How to set the GLFW opengl target?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3842" PostHistoryTypeId="3" PostId="1842" RevisionGUID="76a97ebc-bcfb-4709-854e-a9faa43e065e" CreationDate="2015-12-27T23:25:14.957" UserId="2355" Text="|opengl|c++|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3843" PostHistoryTypeId="2" PostId="1843" RevisionGUID="6f340e9f-aa0e-4fae-823f-bf83928b9de7" CreationDate="2015-12-28T00:35:18.687" UserId="2355" Text="I changed the core profile to `4.1` by setting the window hints.&#xD;&#xA;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);" ContentLicense="CC BY-SA 3.0" />
  <row Id="3844" PostHistoryTypeId="2" PostId="1844" RevisionGUID="40fea377-14d3-40a7-867d-07cad1d2f526" CreationDate="2015-12-28T00:38:29.163" UserId="48" Text="The effect in the photo is very close to a simple scale-bias per pixel. After a bit of tweaking, I found that applying the transformation: $x' = 0.77x + 38$ to the raw pixel values (as bytes) gives something quite close to your output:&#xD;&#xA;&#xD;&#xA;[![transformed image][1]][2]&#xD;&#xA;&#xD;&#xA;In this case the effect of the scale-bias is to reduce the contrast (scale factor &lt; 1) while keeping the overall brightness about the same.&#xD;&#xA;&#xD;&#xA;Example Python code (with numpy and pillow) to do this transformation:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    from PIL import Image&#xD;&#xA;    a = np.array(Image.open(&quot;input.png&quot;), dtype=np.float32)&#xD;&#xA;    b = a * 0.77 + 38&#xD;&#xA;    Image.fromarray(np.uint8(np.rint(b))).save(&quot;output.png&quot;)&#xD;&#xA;&#xD;&#xA;For learning how to implement many basic image processing operations, I've found these [Image Processing Operator Worksheets](http://homepages.inf.ed.ac.uk/rbf/HIPR2/wksheets.htm) from the University of Edinburgh helpful.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ti9Pvm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ti9Pv.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3845" PostHistoryTypeId="2" PostId="1845" RevisionGUID="da1b96c2-2ced-48e9-8011-b0f9d33106dd" CreationDate="2015-12-28T03:59:31.130" UserId="2358" Text="A friend got an MSI GTX 950 2GD5T graphics card for xmas.&#xD;&#xA;&#xD;&#xA;I said &quot;yeah, graphics cards are super fast now, that thing probably processes 2 billion triangles per second&quot;. Then I tried to look it up to check if that was even in the right ballpark, but I was unable to find a &quot;triangles per second&quot; stat for that card, and actually for many cards.&#xD;&#xA;&#xD;&#xA;Is &quot;triangles per second&quot; even a meaningful stat? If so, what is the approximate number for this card? (given otherwise average conditions)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3846" PostHistoryTypeId="1" PostId="1845" RevisionGUID="da1b96c2-2ced-48e9-8011-b0f9d33106dd" CreationDate="2015-12-28T03:59:31.130" UserId="2358" Text="MSI GTX 950 2GD5T triangles per second" ContentLicense="CC BY-SA 3.0" />
  <row Id="3847" PostHistoryTypeId="3" PostId="1845" RevisionGUID="da1b96c2-2ced-48e9-8011-b0f9d33106dd" CreationDate="2015-12-28T03:59:31.130" UserId="2358" Text="|graphics|efficiency|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3848" PostHistoryTypeId="2" PostId="1846" RevisionGUID="d735c33b-2d46-4b78-80c1-28942fb96ba3" CreationDate="2015-12-28T15:43:36.270" UserId="2359" Text="&#xD;&#xA;[![ray tracing pseudocode][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KbrW7.png&#xD;&#xA;&#xD;&#xA;I dont understand the if(depth&gt;MAX)return Black part. Is it something to do with shadows because in other algorithms they shoot a shadow ray towards the light source to check for shadows but they dont have it here" ContentLicense="CC BY-SA 3.0" />
  <row Id="3849" PostHistoryTypeId="1" PostId="1846" RevisionGUID="d735c33b-2d46-4b78-80c1-28942fb96ba3" CreationDate="2015-12-28T15:43:36.270" UserId="2359" Text="Ray tracing pseudocode shadow" ContentLicense="CC BY-SA 3.0" />
  <row Id="3850" PostHistoryTypeId="3" PostId="1846" RevisionGUID="d735c33b-2d46-4b78-80c1-28942fb96ba3" CreationDate="2015-12-28T15:43:36.270" UserId="2359" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3851" PostHistoryTypeId="2" PostId="1847" RevisionGUID="67fd4619-c202-475c-a105-a039239d1710" CreationDate="2015-12-28T16:30:32.037" UserId="231" Text="This is a recursive function (it calls itself). Each time it calls itself it does so with `depth + 1` instead of `depth`. When it is called with `depth &gt; MAX`, it simply returns `Black` rather than call itself again. This ensures that the function will eventually stop recursing and return a value. It is the colour equivalent of returning zero.&#xD;&#xA;&#xD;&#xA;To visualise this in terms of a light ray, each time the ray reflects from a surface the same function is used to calculate the colour of the light in that direction. If you set `MAX` to 1, there will be no reflections in your resulting image. If you set `MAX` to 3, there will be reflections of reflections which will look more realistic, but take longer to calculate.&#xD;&#xA;&#xD;&#xA;Intuitively, MAX is the number of surfaces the ray will bounce off before it is decided what colour should be displayed." ContentLicense="CC BY-SA 3.0" />
  <row Id="3852" PostHistoryTypeId="5" PostId="1847" RevisionGUID="248827cd-0992-475c-9a93-bd6915faa7c6" CreationDate="2015-12-28T16:36:12.337" UserId="231" Comment="added 43 characters in body" Text="This is a recursive function (it calls itself). Each time it calls itself it does so with `depth + 1` instead of `depth`. When it is called with `depth &gt; MAX`, it simply returns `Black` rather than call itself again. This ensures that the function will eventually stop recursing and return a value. It is the colour equivalent of returning zero.&#xD;&#xA;&#xD;&#xA;You can visualise this as a light ray reflecting from multiple surfaces successively. Each time the ray reflects from a surface the same function is used to calculate the colour of the light in that direction. If you set `MAX` to 0, there will be no reflections in your resulting image. If you set `MAX` to 2, there will be reflections of reflections which will look more realistic, but take longer to calculate.&#xD;&#xA;&#xD;&#xA;Intuitively, MAX is the number of surfaces the ray will bounce off before it is decided what colour should be displayed." ContentLicense="CC BY-SA 3.0" />
  <row Id="3853" PostHistoryTypeId="5" PostId="1839" RevisionGUID="b813d05a-3417-4025-86a3-850a6b400e13" CreationDate="2015-12-28T17:27:13.590" UserId="2248" Comment="edited body" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xD;&#xA;Im using the Bullet pyhics library and freeglut for the 3d application. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(previousZ - z, previousX - x) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT: After trying the below code&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float dirX = -(a + b * angle) * sin(angle) + b * cos(angle);&#xD;&#xA;		float dirZ = (a + b * angle) * cos(angle) + b * sin(angle);&#xD;&#xA;		float newAngle = atan2(dirZ, dirX) * 180 / PI;&#xD;&#xA;		temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Console output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sk2W2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ypk6t.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/LFkYQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3854" PostHistoryTypeId="5" PostId="1839" RevisionGUID="edcc5783-a44c-41f7-be40-d24228bd77db" CreationDate="2015-12-28T18:04:05.737" UserId="2248" Comment="added 1213 characters in body" Text="I'm trying to rotate a rectangle so that it faces another rectangle in a spiral.&#xD;&#xA;&#xD;&#xA;Im using the Bullet pyhics library and freeglut for the 3d application, for anyone interested https://github.com/damorton/bullet-dominos&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 4; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float newAngle = atan2(previousZ - z, previousX - x) * 180 / PI;&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;    		&#xD;&#xA;You can see from the top view that the rectangles are not pointing towards the previous rectangles position. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT: After trying the below code&#xD;&#xA;&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        angle = 0.1 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;                    &#xD;&#xA;        float dirX = -(a + b * angle) * sin(angle) + b * cos(angle);&#xD;&#xA;		float dirZ = (a + b * angle) * cos(angle) + b * sin(angle);&#xD;&#xA;		float newAngle = atan2(dirZ, dirX) * 180 / PI;&#xD;&#xA;		temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Console output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;EDIT: Solution. Some things to note are that the result of `atan2()` was not converted to degrees using `atan2() * 180 / PI`. Also that I passed in `atan2(X, Z)` compared to `atan2(Z, X)` that is sometimes done for hysterical raisins http://www2.tcl.tk/10814.&#xD;&#xA;&#xD;&#xA;    // create spiral dominos&#xD;&#xA;    float x = 0;&#xD;&#xA;    float z = 0;&#xD;&#xA;    float angle = 0.0f;&#xD;&#xA;    int a = 2, b = 2;&#xD;&#xA;    float previousX = 0.0f;&#xD;&#xA;    float previousZ = 0.0f;&#xD;&#xA;    &#xD;&#xA;    float dominoHeight = 2.0f;&#xD;&#xA;    &#xD;&#xA;    for (int i = 2; i &lt; maxPoints; i++)&#xD;&#xA;    {&#xD;&#xA;        if (i % 30 == 0) dominoHeight++;&#xD;&#xA;    &#xD;&#xA;        angle = 0.15 * i;&#xD;&#xA;        x = (a + b * angle) * cos(angle);&#xD;&#xA;        z = (a + b * angle) * sin(angle);&#xD;&#xA;    &#xD;&#xA;        GameObject* temp = CreateGameObject(x, 0, z);&#xD;&#xA;    &#xD;&#xA;        float dirX = -(a + b * angle) * sin(angle) + (b * cos(angle));&#xD;&#xA;        float dirZ = (a + b * angle) * cos(angle) + (b * sin(angle));&#xD;&#xA;        float newAngle = atan2(dirX, dirZ);&#xD;&#xA;        printf(&quot;dirX: %f - dirZ: %f - angle: %f\n&quot;, dirX, dirZ, newAngle);&#xD;&#xA;        temp-&gt;setRotationYaw(newAngle);&#xD;&#xA;        &#xD;&#xA;        previousX = x;&#xD;&#xA;        previousZ = z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I300x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sk2W2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ypk6t.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/LFkYQ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/KmM1S.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3855" PostHistoryTypeId="2" PostId="1848" RevisionGUID="3f41f2ae-9464-4fd7-9e7b-a2646c3d8eb5" CreationDate="2015-12-28T20:04:35.557" UserId="2360" Text="I am not looking for textbooks and related how-tos, though I'm sure they can color the answer.&#xD;&#xA;&#xD;&#xA;I'd like to understand how we handle the rendering of prismatic effects — and particularly time-saving models, as different from physical simulation." ContentLicense="CC BY-SA 3.0" />
  <row Id="3856" PostHistoryTypeId="1" PostId="1848" RevisionGUID="3f41f2ae-9464-4fd7-9e7b-a2646c3d8eb5" CreationDate="2015-12-28T20:04:35.557" UserId="2360" Text="What is the basis of rendering prismatic light caustics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3857" PostHistoryTypeId="3" PostId="1848" RevisionGUID="3f41f2ae-9464-4fd7-9e7b-a2646c3d8eb5" CreationDate="2015-12-28T20:04:35.557" UserId="2360" Text="|lighting|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3858" PostHistoryTypeId="2" PostId="1849" RevisionGUID="71919d7a-184e-4fae-b36d-558da09785ea" CreationDate="2015-12-28T22:57:25.847" UserId="48" Text="For offline rendering, caustics and dispersion effects (different colors of light separating, as in a prism) are usually calculated using some form of [photon mapping](https://en.wikipedia.org/wiki/Photon_mapping). That's a fairly expensive technique, even by the standards of offline rendering, and it falls more under the &quot;physical simulation&quot; side of things.&#xD;&#xA;&#xD;&#xA;If you're looking for more approximate techniques suitable for real-time rendering, [Chris Wyman's papers](http://cwyman.appspot.com/papers.html) are a good place to look. He wrote several papers on caustics between 2006 and 2009. The one to start with is [Interactive Image-Space Techniques for Approximating Caustics](http://cwyman.appspot.com/papers/i3d06_imgSpaceCaustics.pdf) (I3D 2006), #25 on that page. This paper re-uses a GPU refraction rendering technique he developed earlier, #28 on that page, so you'll want to look at that as well for background. Later papers build on these two.&#xD;&#xA;&#xD;&#xA;The basic idea of these papers is to use GPU rasterization to perform a limited, approximate analogue of photon mapping. The scene is rendered from the light's point of view, similar to a shadow map, and each pixel is treated as a photon; its refraction through transparent objects is calculated approximately (usually considering only 1 or 2 layers of refraction), and its final location is stored in a texture. Then, one can render each photon as a small splat into a &quot;caustic map&quot;, which finally gets projected onto the scene, similar to a shadow map." ContentLicense="CC BY-SA 3.0" />
  <row Id="3859" PostHistoryTypeId="2" PostId="1850" RevisionGUID="f69be4e4-f705-4fa8-89a8-a957ea324d8d" CreationDate="2015-12-29T03:12:26.573" UserId="2308" Text="I have a game that has simple particles (basically dots) moving around the screen leaving a trail.&#xD;&#xA;&#xD;&#xA;**My ultimate goal** is to be able to change the opacity of the solid black fading texture each drawing call in a way so that I can keep the length of a particle with trails (using a accumulation buffer) is the same even though the particle movement might move with time-stepping.  The way I render my particles is I render the current frame based on the particles position, lets call this texture A.  Then I take the previous frame and draw a solid black texture over it with set opacity in order to fade this, lets call this texture B.  Then I draw texture A over texture B.  This way the particle leaves a trail based on where it has been.  I am currently time-stepping the movement of the particles so that no-mater how much latency their is it always moves the same speed (considering real-world time).&#xD;&#xA;&#xD;&#xA;In essence I want to be able to say say that the particle trial will always be 100 pixels, and have it be that way even if the frame-rate drops.  Currently when the frame rate drops the accumulation buffer gets run less times and thus the trail is longer the more latency their is.&#xD;&#xA;&#xD;&#xA;**The information I need to know to do this** is how exactly does fading work. Because I need to change the opacity of the black texture in a way that allows it to fade more when the accumulation buffer is called less times per second, and fade less when it is called many times per second.  Right now I really dont understand what happens to a pixel when a black texture with a specific opacity is on it.&#xD;&#xA;&#xD;&#xA;Here is some data I collected.&#xD;&#xA;&#xD;&#xA;*Data 1:*&#xD;&#xA;This is a chart of the particle trails.  The x axis represents the FPS it was running at, and the y axis is how many pixels long the trail was.  On the left it says what opacity the black texture used in the accumulation buffer was.&#xD;&#xA;[![Graph][1]][1]&#xD;&#xA;[You can find all the data, and some best fit line formulas at here (on desmos)][2]&#xD;&#xA;&#xD;&#xA;It is important to note I stopped counting after V was lower then 20 since the difference between colors starts getting really small.&#xD;&#xA;&#xD;&#xA;some things I noticed about this is that their seems to be either a exponential or division relationship between the numbers.  Also I noticed that their were segments for each frame before it was faded, and that the amount of them that were visible were about the same no-mater the fps when considering the same opacity of the black texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Data 2:*&#xD;&#xA;I recreated what I thought was going on with a fading texture with paint.net.  I made a 100x100 picture and colored it red. I then added a layer with one black pixel at an opacity of 25/255 then I duplicated this and added another pixel, basically I created a gradient.  Then I went through and labeled each pixel considering its rounded darkness (in hsv color space).  Then labeled the difference between the darkness values.  &#xD;&#xA;&#xD;&#xA;IMAGE IS ON ITS WAY (sorry paint.net had problems while saving and its gone at the moment)&#xD;&#xA;&#xD;&#xA;Unfortunately from this I didnt learn much.  Just reaffirmed that it is a non linear relationship. And I also noticed if I did the fade one more time that all the darkness values shifted to the square next to them.  So I could predict the darkness values if I knew how many times the fade had been applied.&#xD;&#xA;&#xD;&#xA; - **So** what happens when a semitransparent black texture is blended over another one?&#xD;&#xA; - If you are willing to put in some extra thought what would a formula&#xD;&#xA;   be that would give me the opacity the black texture needs to be in&#xD;&#xA;   order to make the particle trail be about 'N' pixels long, given the&#xD;&#xA;   dt since last frame?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iGLTQ.png&#xD;&#xA;  [2]: https://www.desmos.com/calculator/lbrpdkrpjo" ContentLicense="CC BY-SA 3.0" />
  <row Id="3860" PostHistoryTypeId="1" PostId="1850" RevisionGUID="f69be4e4-f705-4fa8-89a8-a957ea324d8d" CreationDate="2015-12-29T03:12:26.573" UserId="2308" Text="Please help me understand what happens as an image is faded to black in order to time-step particle fading" ContentLicense="CC BY-SA 3.0" />
  <row Id="3861" PostHistoryTypeId="3" PostId="1850" RevisionGUID="f69be4e4-f705-4fa8-89a8-a957ea324d8d" CreationDate="2015-12-29T03:12:26.573" UserId="2308" Text="|opengl|transparency|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3862" PostHistoryTypeId="5" PostId="1850" RevisionGUID="a908a7f6-244d-4360-bac8-3ad8d4752109" CreationDate="2015-12-29T03:21:43.787" UserId="2308" Comment="deleted 8 characters in body" Text="I have a game that has simple particles (basically dots) moving around the screen leaving a trail.&#xD;&#xA;&#xD;&#xA;**My ultimate goal** is to be able to change the opacity of the solid black fading texture each drawing call in a way so that I can keep the length of a particle with trails (using a accumulation buffer) is the same even though the particle movement might move with time-stepping.  The way I render my particles is I render the current frame based on the particles position, lets call this texture A.  Then I take the previous frame and draw a solid black texture over it with set opacity in order to fade this, lets call this texture B.  Then I draw texture A over texture B.  This way the particle leaves a trail based on where it has been.  I am currently time-stepping the movement of the particles so that no-mater how much latency their is it always moves the same speed (considering real-world time).&#xD;&#xA;&#xD;&#xA;In essence I want to be able to say say that the particle trial will always be 100 pixels, and have it be that way even if the frame-rate drops.  Currently when the frame rate drops the accumulation buffer gets run less times and thus the trail is longer the more latency their is.&#xD;&#xA;&#xD;&#xA;**The information I need to know to do this** is how exactly does fading work. Because I need to change the opacity of the black texture in a way that allows it to fade more when the accumulation buffer is called less times per second, and fade less when it is called many times per second.  Right now I really dont understand what happens to a pixel when a black texture with a specific opacity is on it.&#xD;&#xA;&#xD;&#xA;Here is some data I collected.&#xD;&#xA;&#xD;&#xA;*Data 1:*&#xD;&#xA;This is a chart of the particle trails.  The x axis represents the FPS it was running at, and the y axis is how many pixels long the trail was.  On the left it says what opacity the black texture used in the accumulation buffer was.&#xD;&#xA;[![Graph][1]][1]&#xD;&#xA;[You can find all the data, and some best fit line formulas at here (on desmos)][2]&#xD;&#xA;&#xD;&#xA;It is important to note I stopped counting after V was lower then 20 since the difference between colors starts getting really small.&#xD;&#xA;&#xD;&#xA;some things I noticed about this is that their seems to be either a exponential or division relationship between the numbers.  Also I noticed that their were segments for each frame before it was faded, and that the amount of them that were visible were about the same no-mater the fps when considering the same opacity of the black texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Data 2:*&#xD;&#xA;I recreated what I thought was going on with a fading texture with paint.net.  I made a 100x100 picture and colored it red. I then added a layer with one black pixel at an opacity of 25/255 then I duplicated this and added another pixel, basically I created a gradient.  Then I went through and labeled each pixel considering its rounded darkness (in hsv color space).  Then labeled the difference between the darkness values.  &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Unfortunately from this I didnt learn much.  Just reaffirmed that it is a non linear relationship. And I also noticed if I did the fade one more time that all the darkness values shifted to the square next to them.  So I could predict the darkness values if I knew how many times the fade had been applied.&#xD;&#xA;&#xD;&#xA; - **So** what happens when a semitransparent black texture is blended over another one?&#xD;&#xA; - If you are willing to put in some extra thought what would a formula&#xD;&#xA;   be that would give me the opacity the black texture needs to be in&#xD;&#xA;   order to make the particle trail be about 'N' pixels long, given the&#xD;&#xA;   dt since last frame?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iGLTQ.png&#xD;&#xA;  [2]: https://www.desmos.com/calculator/lbrpdkrpjo&#xD;&#xA;  [3]: https://i.stack.imgur.com/y4YqY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3863" PostHistoryTypeId="5" PostId="1850" RevisionGUID="d2e5d747-1dcc-41f7-9043-630451783f12" CreationDate="2015-12-29T03:27:14.367" UserId="2308" Comment="added 82 characters in body" Text="I have a game that has simple particles (basically dots) moving around the screen leaving a trail.&#xD;&#xA;&#xD;&#xA;**My ultimate goal** is to be able to change the opacity of the solid black fading texture each drawing call in a way so that I can keep the length of a particle with trails (using a accumulation buffer) is the same even though the particle movement might move with time-stepping.  The way I render my particles is I render the current frame based on the particles position, lets call this texture A.  Then I take the previous frame and draw a solid black texture over it with set opacity in order to fade this, lets call this texture B.  Then I draw texture A over texture B.  This way the particle leaves a trail based on where it has been.  I am currently time-stepping the movement of the particles so that no-mater how much latency their is it always moves the same speed (considering real-world time).&#xD;&#xA;&#xD;&#xA;In essence I want to be able to say say that the particle trial will always be 100 pixels, and have it be that way even if the frame-rate drops.  Currently when the frame rate drops the accumulation buffer gets run less times and thus the trail is longer the more latency their is.&#xD;&#xA;&#xD;&#xA;**The information I need to know to do this** is how exactly does fading work. Because I need to change the opacity of the black texture in a way that allows it to fade more when the accumulation buffer is called less times per second, and fade less when it is called many times per second.  Right now I really dont understand what happens to a pixel when a black texture with a specific opacity is on it.&#xD;&#xA;&#xD;&#xA;Here is some data I collected.&#xD;&#xA;&#xD;&#xA;*Data 1:*&#xD;&#xA;This is a chart of the particle trails.  The x axis represents the FPS it was running at, and the y axis is how many pixels long the trail was.  On the left it says what opacity the black texture used in the accumulation buffer was.&#xD;&#xA;[![Graph][1]][1]&#xD;&#xA;[You can find all the data, and some best fit line formulas at here (on desmos)][2]&#xD;&#xA;&#xD;&#xA;It is important to note I stopped counting after V was lower then 20 since the difference between colors starts getting really small.&#xD;&#xA;&#xD;&#xA;some things I noticed about this is that their seems to be either a exponential or division relationship between the numbers.  Also I noticed that their were segments for each frame before it was faded, and that the amount of them that were visible were about the same no-mater the fps when considering the same opacity of the black texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Data 2:*&#xD;&#xA;I recreated what I thought was going on with a fading texture with paint.net.  I made a 100x100 picture and colored it red. I then added a layer with one black pixel at an opacity of 25/255 then I duplicated this and added another pixel, basically I created a gradient.  Then I went through and labeled each pixel considering its rounded darkness (in hsv color space).  Then labeled the difference between the darkness values.  &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Unfortunately from this I didnt learn much.  Just reaffirmed that it is a non linear relationship. And I also noticed if I did the fade one more time that all the darkness values shifted to the square next to them.  So I could predict the darkness values if I knew how many times the fade had been applied.&#xD;&#xA;&#xD;&#xA; - **So** what happens when a semitransparent black texture is blended over another one?&#xD;&#xA; - If you are willing to put in some extra thought what would a formula&#xD;&#xA;   be that would give me the opacity the black texture needs to be in&#xD;&#xA;   order to make the particle trail be about 'N' pixels long, given the&#xD;&#xA;   dt since last frame?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iGLTQ.png&#xD;&#xA;  [2]: https://www.desmos.com/calculator/lbrpdkrpjo&#xD;&#xA;  [3]: https://i.stack.imgur.com/y4YqY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/1IYC3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3864" PostHistoryTypeId="5" PostId="1850" RevisionGUID="a1954f3d-bc2a-47fb-a735-6c2ed9a50995" CreationDate="2015-12-29T03:34:20.903" UserId="2308" Comment="edited body" Text="I have a game that has simple particles (basically dots) moving around the screen leaving a trail.&#xD;&#xA;&#xD;&#xA;**My ultimate goal** is to be able to change the opacity of the solid black fading texture each drawing call in a way so that I can keep the length of a particle with trails (using a accumulation buffer) is the same even though the particle movement might move with time-stepping.  The way I render my particles is I render the current frame based on the particles position, lets call this texture A.  Then I take the previous frame and draw a solid black texture over it with set opacity in order to fade this, lets call this texture B.  Then I draw texture A over texture B.  This way the particle leaves a trail based on where it has been.  I am currently time-stepping the movement of the particles so that no-mater how much latency their is it always moves the same speed (considering real-world time).&#xD;&#xA;&#xD;&#xA;In essence I want to be able to say say that the particle trial will always be 100 pixels, and have it be that way even if the frame-rate drops.  Currently when the frame rate drops the accumulation buffer gets run less times and thus the trail is longer the more latency their is.&#xD;&#xA;&#xD;&#xA;**The information I need to know to do this** is how exactly does fading work. Because I need to change the opacity of the black texture in a way that allows it to fade more when the accumulation buffer is called less times per second, and fade less when it is called many times per second.  Right now I really dont understand what happens to a pixel when a black texture with a specific opacity is on it.&#xD;&#xA;&#xD;&#xA;Here is some data I collected.&#xD;&#xA;&#xD;&#xA;*Data 1:*&#xD;&#xA;This is a chart of the particle trails.  The x axis represents the FPS it was running at, and the y axis is how many pixels long the trail was.  On the left it says what opacity the black texture used in the accumulation buffer was.&#xD;&#xA;[![Graph][1]][1]&#xD;&#xA;[You can find all the data, and some best fit line formulas at here (on desmos)][2]&#xD;&#xA;&#xD;&#xA;It is important to note I stopped counting after V was lower then 20 since the difference between colors starts getting really small.&#xD;&#xA;&#xD;&#xA;some things I noticed about this is that their seems to be either a exponential or division relationship between the numbers.  Also I noticed that their were segments for each frame before it was faded, and that the amount of them that were visible were about the same no-mater the fps when considering the same opacity of the black texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Data 2:*&#xD;&#xA;I recreated what I thought was going on with a fading texture with paint.net.  I made a 100x100 picture and colored it red. I then added a layer with one black pixel at an opacity of 25/255 then I duplicated this and added another pixel, basically I created a gradient.  Then I went through and labeled each pixel considering its rounded darkness (in hsv color space).  Then labeled the difference between the darkness values.  &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Unfortunately from this I didnt learn much.  Just reaffirmed that it is a non linear relationship. And I also noticed if I did the fade one more time that all the darkness values shifted to the square next to them.  So I could predict the darkness values if I knew how many times the fade had been applied.&#xD;&#xA;&#xD;&#xA; - **So** what happens when a semitransparent black texture is blended over another one?&#xD;&#xA; - If you are willing to put in some extra thought what would a formula&#xD;&#xA;   be that would give me the opacity the black texture needs to be in&#xD;&#xA;   order to make the particle trail be about 'N' pixels long, given the&#xD;&#xA;   dt since last frame?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iGLTQ.png&#xD;&#xA;  [2]: https://www.desmos.com/calculator/lbrpdkrpjo&#xD;&#xA;  [3]: https://i.stack.imgur.com/y4YqY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/HZ89o.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3868" PostHistoryTypeId="2" PostId="1852" RevisionGUID="5c76606b-c1a2-48e7-b7ff-348c06c3ec93" CreationDate="2015-12-29T06:35:14.433" UserId="48" Text="The basic equation for alpha blending is as follows:&#xD;&#xA;&#xD;&#xA;$$ c_\text{final} = c_\text{source} \cdot \alpha + c_\text{dest} \cdot (1 - \alpha) $$&#xD;&#xA;&#xD;&#xA;Here, $c_\text{source}$ is the color of the thing being blended, $c_\text{dest}$ is the background onto which you're blending it, and $\alpha$ is between 0 and 1.&#xD;&#xA;&#xD;&#xA;In your case, $c_\text{source} = 0$ (black fading texture), so blending black $n$ times over a background reduces to&#xD;&#xA;&#xD;&#xA;$$ c_\text{final} = c_\text{dest} \cdot (1 - \alpha)^n $$&#xD;&#xA;&#xD;&#xA;which is indeed an exponential falloff as you guessed. You can plug this formula in and get numbers pretty similar to those you posted (although when I did it, my results were off by one or two—maybe due to rounding differences; I'm not sure).&#xD;&#xA;&#xD;&#xA;Regarding your problem of making the trails appear the same regardless of framerate, a simple approach is to run the accumulation buffer passes multiple times per frame if necessary, so that there's effectively a fixed timestep for the trail regardless of framerate. That will probably give better-looking results than attempting to fiddle with the alpha based on the framerate. It might be too slow, though.&#xD;&#xA;&#xD;&#xA;A potentially more efficient approach would be to have the particles spawn a new &quot;trail particle&quot; every so often, where each trail particle stays fixed in position, with its alpha going from 100% to 0 over some length of time (and then it gets recycled). You have to re-render all the particles every frame, but it could end up being faster overall if the overhead of the full-screen blending passes for the accumulation buffer get to be too high.&#xD;&#xA;&#xD;&#xA;I should point out though that all of these approaches actually perform *time-based* fading, not distance-based as you asked for (100-pixel trails). If all the particles move at the same speed, you can just tweak the fade time to make the trails the desired length, but if different particles move at different speeds, then you would need to account for that when setting the fade times for their trails. There's also no trivial way to do that with the accumulation buffer approach, since it implicitly uses the same fade time for everything on the screen." ContentLicense="CC BY-SA 3.0" />
  <row Id="3869" PostHistoryTypeId="5" PostId="1850" RevisionGUID="1bf0eb42-1016-4abe-b96b-3c4ff557b970" CreationDate="2015-12-29T06:39:30.607" UserId="2308" Comment="added 56 characters in body" Text="I have a game that has simple particles (basically dots) moving around the screen leaving a trail.&#xD;&#xA;&#xD;&#xA;**My ultimate goal** is to be able to change the opacity of the solid black fading texture each drawing call in a way so that I can keep the length of a particle with trails (using a accumulation buffer) is the same even though the particle movement might move with time-stepping.  The way I render my particles is I render the current frame based on the particles position, lets call this texture A.  Then I take the previous frame and draw a solid black texture over it with set opacity in order to fade this, lets call this texture B.  Then I draw texture A over texture B.  This way the particle leaves a trail based on where it has been.  I am currently time-stepping the movement of the particles so that no-mater how much latency their is it always moves the same speed (considering real-world time).&#xD;&#xA;&#xD;&#xA;In essence I want to be able to say say that the particle trial will always be 100 pixels (considering the particle moves 60 pixels in a second) , and have it be that way even if the frame-rate drops.  Currently when the frame rate drops the accumulation buffer gets run less times and thus the trail is longer the more latency their is.&#xD;&#xA;&#xD;&#xA;**The information I need to know to do this** is how exactly does fading work. Because I need to change the opacity of the black texture in a way that allows it to fade more when the accumulation buffer is called less times per second, and fade less when it is called many times per second.  Right now I really dont understand what happens to a pixel when a black texture with a specific opacity is on it.&#xD;&#xA;&#xD;&#xA;Here is some data I collected.&#xD;&#xA;&#xD;&#xA;*Data 1:*&#xD;&#xA;This is a chart of the particle trails.  The x axis represents the FPS it was running at, and the y axis is how many pixels long the trail was.  On the left it says what opacity the black texture used in the accumulation buffer was.&#xD;&#xA;[![Graph][1]][1]&#xD;&#xA;[You can find all the data, and some best fit line formulas at here (on desmos)][2]&#xD;&#xA;&#xD;&#xA;It is important to note I stopped counting after V was lower then 20 since the difference between colors starts getting really small.&#xD;&#xA;&#xD;&#xA;some things I noticed about this is that their seems to be either a exponential or division relationship between the numbers.  Also I noticed that their were segments for each frame before it was faded, and that the amount of them that were visible were about the same no-mater the fps when considering the same opacity of the black texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Data 2:*&#xD;&#xA;I recreated what I thought was going on with a fading texture with paint.net.  I made a 100x100 picture and colored it red. I then added a layer with one black pixel at an opacity of 25/255 then I duplicated this and added another pixel, basically I created a gradient.  Then I went through and labeled each pixel considering its rounded darkness (in hsv color space).  Then labeled the difference between the darkness values.  &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Unfortunately from this I didnt learn much.  Just reaffirmed that it is a non linear relationship. And I also noticed if I did the fade one more time that all the darkness values shifted to the square next to them.  So I could predict the darkness values if I knew how many times the fade had been applied.&#xD;&#xA;&#xD;&#xA; - **So** what happens when a semitransparent black texture is blended over another one?&#xD;&#xA; - If you are willing to put in some extra thought what would a formula&#xD;&#xA;   be that would give me the opacity the black texture needs to be in&#xD;&#xA;   order to make the particle trail be about 'N' pixels long, given the&#xD;&#xA;   dt since last frame?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iGLTQ.png&#xD;&#xA;  [2]: https://www.desmos.com/calculator/lbrpdkrpjo&#xD;&#xA;  [3]: https://i.stack.imgur.com/y4YqY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/HZ89o.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3871" PostHistoryTypeId="5" PostId="1848" RevisionGUID="24712eb5-a00d-43be-b17d-2654fadfe66f" CreationDate="2015-12-29T20:08:54.957" UserId="2360" Comment="focus" Text="I am not looking for textbooks and related how-tos, though I'm sure they can color the answer.&#xD;&#xA;&#xD;&#xA;I'd like to understand how we handle the rendering of caustic effects — and particularly time-saving models, as different from physical simulation." ContentLicense="CC BY-SA 3.0" />
  <row Id="3872" PostHistoryTypeId="4" PostId="1848" RevisionGUID="24712eb5-a00d-43be-b17d-2654fadfe66f" CreationDate="2015-12-29T20:08:54.957" UserId="2360" Comment="focus" Text="What is the basis of rendering light caustics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3874" PostHistoryTypeId="2" PostId="1854" RevisionGUID="3a3ada4d-cadf-40aa-aba1-179823e9ca7a" CreationDate="2015-12-29T20:24:41.790" UserId="2360" Text="Is all [spectral rendering][1] handled as simulation?  Are there technique more tailored to 'consumer' rendering, such as for real-time or even just 'realistic looking without solving full physical equations'?&#xD;&#xA;&#xD;&#xA;I'd like to understand how we handle the rendering of spectral effects.  It seems like a photon needs to be described as a range of wavelengths, and incidence with a surface either &#xD;&#xA;&#xD;&#xA;* replaces the original, and resolves multiple new photons across the spectral function, each with their own new vector &#xD;&#xA;* maintains the original (or marginally modified) photon, given a threshold&#xD;&#xA;&#xD;&#xA;I would prefer to be pointed in the direction of existing work, but appreciate any *coloring* of this topic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Spectral_rendering&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3875" PostHistoryTypeId="1" PostId="1854" RevisionGUID="3a3ada4d-cadf-40aa-aba1-179823e9ca7a" CreationDate="2015-12-29T20:24:41.790" UserId="2360" Text="How is spectral rendering handled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3876" PostHistoryTypeId="3" PostId="1854" RevisionGUID="3a3ada4d-cadf-40aa-aba1-179823e9ca7a" CreationDate="2015-12-29T20:24:41.790" UserId="2360" Text="|lighting|photo-realistic|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3877" PostHistoryTypeId="6" PostId="1839" RevisionGUID="5b95dfa1-b3e1-4bac-9a81-e90b64766664" CreationDate="2015-12-29T23:04:42.653" UserId="127" Comment="edited tags" Text="|transformations|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3878" PostHistoryTypeId="5" PostId="1842" RevisionGUID="7cf6f40c-b6f0-47bc-bc5c-23c560c6c620" CreationDate="2015-12-29T23:16:44.810" UserId="127" Comment="Improved formatting, spelling and readability." Text="I'm programming on a Mac and I'm learning OpenGL in the library GLFW. &#xD;&#xA;&#xD;&#xA;My problem is that my Mac supports OpenGL up to version 4.1, but when I try to compile the shaders with `version 410` it says `ERROR: 0:1: '' :  version '410' is not supported`. &#xD;&#xA;&#xD;&#xA;How do I set the version that GLFW should use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3879" PostHistoryTypeId="4" PostId="1842" RevisionGUID="7cf6f40c-b6f0-47bc-bc5c-23c560c6c620" CreationDate="2015-12-29T23:16:44.810" UserId="127" Comment="Improved formatting, spelling and readability." Text="How to set the GLFW OpenGL target?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3896" PostHistoryTypeId="2" PostId="1857" RevisionGUID="15b1d260-576d-4d7f-b78b-6aeb87c08770" CreationDate="2016-01-01T00:05:16.793" UserId="2381" Text="I'm trying to find the angle it would take for me to rotate a polygon so that a specific side is completely horizontal and on the bottom.&#xD;&#xA;&#xD;&#xA;For example, a shape like this:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Needs to be rotated so the side with the red square on it is on the bottom and completely horizontal, like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So far I've tried several approaches but all end up having strange edge cases where the angle is incorrect.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/duCe7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/210Ot.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3897" PostHistoryTypeId="1" PostId="1857" RevisionGUID="15b1d260-576d-4d7f-b78b-6aeb87c08770" CreationDate="2016-01-01T00:05:16.793" UserId="2381" Text="Finding the angle of any side of a polygon" ContentLicense="CC BY-SA 3.0" />
  <row Id="3898" PostHistoryTypeId="3" PostId="1857" RevisionGUID="15b1d260-576d-4d7f-b78b-6aeb87c08770" CreationDate="2016-01-01T00:05:16.793" UserId="2381" Text="|graphics|vector-graphics|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3900" PostHistoryTypeId="2" PostId="1859" RevisionGUID="4e6076cd-6239-4a05-834f-33db466ebce2" CreationDate="2016-01-01T08:31:35.117" UserId="2317" Text="This algorithm is based on [this answer][1], is written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with an `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from math import degrees, sqrt, acos&#xD;&#xA;    &#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;    &#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;    &#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;      &#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;    &#xD;&#xA;    def calc_edge_vec(  poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;        &#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;    &#xD;&#xA;    p = {&#xD;&#xA;    	'points' : [ (0,0), (3,5), (7,2), (1,4) ],&#xD;&#xA;    	'edges'  : [ (0,3), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    xVec = [1,0] # Horizontal X axis vector - to align with&#xD;&#xA;    &#xD;&#xA;    for e in p['edges']:&#xD;&#xA;        edgeVec = calc_edge_vec(  p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;        print( degrees(a) )&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python" ContentLicense="CC BY-SA 3.0" />
  <row Id="3901" PostHistoryTypeId="5" PostId="1859" RevisionGUID="42ca0f85-7c3e-42e2-be07-682af5d9e2b1" CreationDate="2016-01-01T08:50:43.070" UserId="2317" Comment="Using same varnames for consistency" Text="This algorithm is based on [this answer][1], is written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with an `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from math import degrees, sqrt, acos&#xD;&#xA;    &#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;    &#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;    &#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;      &#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ a - b for a, b in zip( v1, v2 ) ]&#xD;&#xA;    &#xD;&#xA;    def calc_edge_vec(  poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;        &#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;    &#xD;&#xA;    p = {&#xD;&#xA;    	'points' : [ (0,0), (3,5), (7,2), (1,4) ],&#xD;&#xA;    	'edges'  : [ (0,3), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    xVec = [1,0] # Horizontal X axis vector - to align with&#xD;&#xA;    &#xD;&#xA;    for e in p['edges']:&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;        print( degrees(a) )&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python" ContentLicense="CC BY-SA 3.0" />
  <row Id="3904" PostHistoryTypeId="5" PostId="1859" RevisionGUID="accafd06-65e5-4ea0-86da-d696578e5b07" CreationDate="2016-01-01T17:24:30.600" UserId="2317" Comment="Added code for rotating the polygon and displaying results" Text="This algorithm is based on [this answer for finding the angle between vectors][1], and [this answer for rotating polygon points][2]. It's written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with an `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;**EDITED**: Added code for rotating the polygon and displaying the original and rotated polygons. Result of this script is displayed in the image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from math import radians, degrees, sqrt, acos, cos, sin&#xD;&#xA;&#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;&#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;&#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;      &#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;&#xD;&#xA;    def calc_edge_vec(  poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;        &#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;&#xD;&#xA;    def rotatePolygon( polygon, theta ):&#xD;&#xA;        ''' Rotates the given polygon which consists of corners represented&#xD;&#xA;            as (x,y), around the ORIGIN, clock-wise, theta degrees&#xD;&#xA;        '''&#xD;&#xA;        #theta = radians( theta )&#xD;&#xA;        rotatedPolygon = []&#xD;&#xA;        for corner in polygon:&#xD;&#xA;            rotatedPolygon.append((&#xD;&#xA;                corner[0] * cos( theta ) - corner[1] * sin( theta ), # x&#xD;&#xA;                corner[0] * sin( theta ) + corner[1] * cos( theta )  # y&#xD;&#xA;            ))&#xD;&#xA;&#xD;&#xA;        minX = min( [ c[0] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minX = minX if minX &gt; 0 else 0&#xD;&#xA;        minY = min( [ c[1] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minY = minY if minY &gt; 0 else 0&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = [ ( x + minX, y + minY ) for x, y in rotatedPolygon ]&#xD;&#xA;        &#xD;&#xA;        return rotatedPolygon&#xD;&#xA;&#xD;&#xA;    def draw_polygon( im, poly, color ):&#xD;&#xA;        draw = ImageDraw.Draw( im )&#xD;&#xA;        &#xD;&#xA;        for e in poly['edges']:&#xD;&#xA;            p1 = tuple( poly['points'][ e[0] ] )&#xD;&#xA;            p2 = tuple( poly['points'][ e[1] ] )&#xD;&#xA;            draw.line( [p1, p2], fill = color )&#xD;&#xA;&#xD;&#xA;        del draw&#xD;&#xA;&#xD;&#xA;    p = {&#xD;&#xA;        'points' : [ (50,10), (95,30), (80,20), (62,48) ],&#xD;&#xA;        'edges'  : [ (0,3), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    yVec = [0,1] # Straight up along Y Vector - to align with&#xD;&#xA;    xVec = [1,0] # Horizontal axis&#xD;&#xA;&#xD;&#xA;    imgMode = 'gray'&#xD;&#xA;    im = Image.new( 'RGB', (100,100) )&#xD;&#xA;&#xD;&#xA;    # Draw original poly in white&#xD;&#xA;    draw_polygon( im, p, (255,255,255) )&#xD;&#xA;&#xD;&#xA;    plt.subplot( 3, 2, 1), plt.imshow( im ), plt.title( 'Original' ), plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;    colors = [ (50,50,255), (255,0,0), (0,255,0), (200, 150, 50) ]&#xD;&#xA;&#xD;&#xA;    i = 2&#xD;&#xA;    for e, color in zip( p['edges'], colors ):&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec,  xVec )&#xD;&#xA;&#xD;&#xA;        rotPol = p.copy()&#xD;&#xA;        rotPol['points'] = rotatePolygon( p['points'], a )&#xD;&#xA;&#xD;&#xA;        im = Image.new( 'RGB', (100,100) )&#xD;&#xA;        draw_polygon( im, rotPol, color )&#xD;&#xA;        plt.subplot( 3, 2, i ), plt.imshow( im )&#xD;&#xA;        angleTitle = &quot;Angle: &quot; + str( round( degrees(a), 2 ) )&#xD;&#xA;        plt.title( angleTitle ), plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;        i += 1&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python&#xD;&#xA;  [2]: http://stackoverflow.com/questions/20023209/python-function-for-rotating-2d-objects&#xD;&#xA;  [3]: https://i.stack.imgur.com/0xe1k.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3905" PostHistoryTypeId="5" PostId="1859" RevisionGUID="71f446f5-0743-43ba-b99f-7cb4b8466349" CreationDate="2016-01-01T17:56:52.137" UserId="2317" Comment="Fixed minor bug in edge point representation, improved polygon display" Text="This algorithm is based on [this answer for finding the angle between vectors][1], and [this answer for rotating polygon points][2]. It's written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with an `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;**EDITED**: Added code for rotating the polygon and displaying the original and rotated polygons. Result of this script is displayed in the image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from math import radians, degrees, sqrt, acos, cos, sin&#xD;&#xA;&#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;&#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;&#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;      &#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;&#xD;&#xA;    def calc_edge_vec(  poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;        &#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;&#xD;&#xA;    def rotatePolygon( polygon, theta ):&#xD;&#xA;        ''' Rotates the given polygon which consists of corners represented&#xD;&#xA;            as (x,y), around the ORIGIN, clock-wise, theta degrees&#xD;&#xA;        '''&#xD;&#xA;        #theta = radians( theta )&#xD;&#xA;        rotatedPolygon = []&#xD;&#xA;        for corner in polygon:&#xD;&#xA;            rotatedPolygon.append((&#xD;&#xA;                corner[0] * cos( theta ) - corner[1] * sin( theta ), # x&#xD;&#xA;                corner[0] * sin( theta ) + corner[1] * cos( theta )  # y&#xD;&#xA;            ))&#xD;&#xA;&#xD;&#xA;        minX = min( [ c[0] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minX = minX if minX &gt; 0 else 0&#xD;&#xA;        minY = min( [ c[1] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minY = minY if minY &gt; 0 else 0&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = [ ( x + minX, y + minY ) for x, y in rotatedPolygon ]&#xD;&#xA;        &#xD;&#xA;        return rotatedPolygon&#xD;&#xA;&#xD;&#xA;    def draw_polygon( im, poly, color ):&#xD;&#xA;        draw = ImageDraw.Draw( im )&#xD;&#xA;        &#xD;&#xA;        for e in poly['edges']:&#xD;&#xA;            p1 = tuple( poly['points'][ e[0] ] )&#xD;&#xA;            p2 = tuple( poly['points'][ e[1] ] )&#xD;&#xA;            draw.line( [p1, p2], fill = color )&#xD;&#xA;&#xD;&#xA;        del draw&#xD;&#xA;&#xD;&#xA;    p = {&#xD;&#xA;        'points' : [ (50,10), (95,30), (80,20), (62,48) ],&#xD;&#xA;        'edges'  : [ (3,0), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    yVec = [0,1] # Straight up along Y Vector - to align with&#xD;&#xA;    xVec = [1,0] # Horizontal axis&#xD;&#xA;&#xD;&#xA;    imgMode = 'gray'&#xD;&#xA;    im = Image.new( 'RGB', (100,100) )&#xD;&#xA;&#xD;&#xA;    # Draw original poly in white&#xD;&#xA;    draw_polygon( im, p, (255,255,255) )&#xD;&#xA;&#xD;&#xA;    plt.subplot( 3, 2, 1), plt.imshow( im ), plt.title( 'Original' ), plt.xticks([]), plt.yticks([])&#xD;&#xA;    for i, c in enumerate( p['points'] ):&#xD;&#xA;        plt.text( c[0], c[1], &quot;ABCD&quot;[i], color = 'white' )&#xD;&#xA;&#xD;&#xA;    colors = [ (50,50,255), (255,0,0), (0,255,0), (200, 150, 50) ]&#xD;&#xA;&#xD;&#xA;    i = 2&#xD;&#xA;    for e, color in zip( p['edges'], colors ):&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;&#xD;&#xA;        rotPol = p.copy()&#xD;&#xA;        rotPol['points'] = rotatePolygon( p['points'], a )&#xD;&#xA;&#xD;&#xA;        im = Image.new( 'RGB', (100,100) )&#xD;&#xA;        draw_polygon( im, rotPol, color )&#xD;&#xA;        plt.subplot( 3, 2, i ), plt.imshow( im )&#xD;&#xA;        angleTitle = &quot;Angle: &quot; + str( round( degrees(a), 2 ) )&#xD;&#xA;        plt.title( angleTitle ), plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;        for idx, c in enumerate( rotPol['points'] ):&#xD;&#xA;            plt.text( c[0], c[1], &quot;ABCD&quot;[idx], color = 'white' )&#xD;&#xA;&#xD;&#xA;        i += 1&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python&#xD;&#xA;  [2]: http://stackoverflow.com/questions/20023209/python-function-for-rotating-2d-objects&#xD;&#xA;  [3]: https://i.stack.imgur.com/oeSfK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3906" PostHistoryTypeId="5" PostId="1859" RevisionGUID="3c8b4c65-c366-43f3-9c1e-ebdc91c25170" CreationDate="2016-01-01T18:10:21.290" UserId="2317" Comment="A bit more organized" Text="This algorithm is based on [this answer for finding the angle between vectors][1], and [this answer for rotating polygon points][2]. It's written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with an `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;**EDITED**: Added code for rotating the polygon and displaying the original and rotated polygons. Result of this script is displayed in the image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from math import radians, degrees, sqrt, acos, cos, sin&#xD;&#xA;&#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;&#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;&#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;      &#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;&#xD;&#xA;    def calc_edge_vec(  poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;        &#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;&#xD;&#xA;    def rotatePolygon( polygon, theta ):&#xD;&#xA;        ''' Rotates the given polygon which consists of corners represented&#xD;&#xA;            as (x,y), around the ORIGIN, clock-wise, theta degrees&#xD;&#xA;        '''&#xD;&#xA;        #theta = radians( theta )&#xD;&#xA;        rotatedPolygon = []&#xD;&#xA;        for corner in polygon:&#xD;&#xA;            rotatedPolygon.append((&#xD;&#xA;                corner[0] * cos( theta ) - corner[1] * sin( theta ), # x&#xD;&#xA;                corner[0] * sin( theta ) + corner[1] * cos( theta )  # y&#xD;&#xA;            ))&#xD;&#xA;&#xD;&#xA;        minX = min( [ c[0] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minX = minX if minX &gt; 0 else 0&#xD;&#xA;        minY = min( [ c[1] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minY = minY if minY &gt; 0 else 0&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = [ ( x + minX, y + minY ) for x, y in rotatedPolygon ]&#xD;&#xA;        &#xD;&#xA;        return rotatedPolygon&#xD;&#xA;&#xD;&#xA;    def draw_polygon( im, poly, color ):&#xD;&#xA;        draw = ImageDraw.Draw( im )&#xD;&#xA;        &#xD;&#xA;        for e in poly['edges']:&#xD;&#xA;            p1 = tuple( poly['points'][ e[0] ] )&#xD;&#xA;            p2 = tuple( poly['points'][ e[1] ] )&#xD;&#xA;            draw.line( [p1, p2], fill = color )&#xD;&#xA;&#xD;&#xA;        del draw&#xD;&#xA;&#xD;&#xA;    p = {&#xD;&#xA;        'points' : [ (50,10), (95,30), (80,20), (62,48) ],&#xD;&#xA;        'edges'  : [ (3,0), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    xVec = [1,0] # Horizontal axis&#xD;&#xA;&#xD;&#xA;    # Draw original poly in white&#xD;&#xA;    im = Image.new( 'RGB', (100,100) )&#xD;&#xA;    draw_polygon( im, p, (255,255,255) )&#xD;&#xA;&#xD;&#xA;    plt.subplot( 3, 2, 1), plt.imshow( im ), plt.title( 'Original' ), plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;    # Draw point names (ABCD)&#xD;&#xA;    for i, c in enumerate( p['points'] ):&#xD;&#xA;        plt.text( c[0], c[1], &quot;ABCD&quot;[i], color = 'white' )&#xD;&#xA;&#xD;&#xA;    colors = [ (50,50,255), (255,0,0), (0,255,0), (200, 150, 50) ]&#xD;&#xA;&#xD;&#xA;    i = 2&#xD;&#xA;    for e, color in zip( p['edges'], colors ):&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;&#xD;&#xA;        rotPol = p.copy()&#xD;&#xA;        rotPol['points'] = rotatePolygon( p['points'], a )&#xD;&#xA;&#xD;&#xA;        # Draw rotated polygon&#xD;&#xA;        im = Image.new( 'RGB', (100,100) )&#xD;&#xA;        draw_polygon( im, rotPol, color )&#xD;&#xA;        plt.subplot( 3, 2, i ), plt.imshow( im )&#xD;&#xA;        angleTitle = &quot;Angle: &quot; + str( round( degrees(a), 2 ) )&#xD;&#xA;        plt.title( angleTitle ), plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;        # Draw point names (ABCD)&#xD;&#xA;        for idx, c in enumerate( rotPol['points'] ):&#xD;&#xA;            plt.text( c[0], c[1], &quot;ABCD&quot;[idx], color = 'white' )&#xD;&#xA;&#xD;&#xA;        i += 1&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python&#xD;&#xA;  [2]: http://stackoverflow.com/questions/20023209/python-function-for-rotating-2d-objects&#xD;&#xA;  [3]: https://i.stack.imgur.com/oeSfK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3909" PostHistoryTypeId="5" PostId="1857" RevisionGUID="1384c293-2dfc-4630-8867-a5179d70e911" CreationDate="2016-01-01T21:59:54.580" UserId="127" Comment="Made the second image appear after the &quot;like this&quot;, edited tags" Text="I'm trying to find the angle it would take for me to rotate a polygon so that a specific side is completely horizontal and on the bottom.&#xD;&#xA;&#xD;&#xA;For example, a shape like this:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Needs to be rotated so the side with the red square on it is on the bottom and completely horizontal, like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So far I've tried several approaches but all end up having strange edge cases where the angle is incorrect.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/duCe7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/210Ot.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3910" PostHistoryTypeId="6" PostId="1857" RevisionGUID="1384c293-2dfc-4630-8867-a5179d70e911" CreationDate="2016-01-01T21:59:54.580" UserId="127" Comment="Made the second image appear after the &quot;like this&quot;, edited tags" Text="|transformations|graphics|vector-graphics|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3912" PostHistoryTypeId="5" PostId="1859" RevisionGUID="a82358b6-f0ca-4098-b0c1-bea93927ec56" CreationDate="2016-01-02T07:00:38.827" UserId="2317" Comment="Refactoring for readability" Text="This algorithm is based on [this answer for finding the angle between vectors][1], and [this answer for rotating polygon points][2]. It's written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with a `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;**EDITED**: Added code for rotating the polygon and displaying the original and rotated polygons. Result of this script is displayed in the image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from math import radians, degrees, sqrt, acos, cos, sin&#xD;&#xA;&#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;&#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;&#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;      &#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;&#xD;&#xA;    def calc_edge_vec( poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;        &#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;&#xD;&#xA;    def rotatePolygon( poly, theta ):&#xD;&#xA;        ''' Rotates the given polygon which consists of corners represented&#xD;&#xA;            as (x,y), around the ORIGIN, clock-wise, theta degrees&#xD;&#xA;        '''&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = []&#xD;&#xA;        for corner in poly:&#xD;&#xA;            rotatedPolygon.append((&#xD;&#xA;                corner[0] * cos( theta ) - corner[1] * sin( theta ), # x&#xD;&#xA;                corner[0] * sin( theta ) + corner[1] * cos( theta )  # y&#xD;&#xA;            ))&#xD;&#xA;&#xD;&#xA;        # Make sure rotated polygon coordinates are within image boundaries&#xD;&#xA;        minX = min( [ c[0] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minX = minX if minX &gt; 0 else 0&#xD;&#xA;        minY = min( [ c[1] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minY = minY if minY &gt; 0 else 0&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = [ ( x + minX, y + minY ) for x, y in rotatedPolygon ]&#xD;&#xA;        &#xD;&#xA;        return rotatedPolygon&#xD;&#xA;&#xD;&#xA;    def draw_and_plot_polygon( im, poly, color, plotTitle, plotIndex ):&#xD;&#xA;        draw = ImageDraw.Draw( im )&#xD;&#xA;        &#xD;&#xA;        for e in poly['edges']:&#xD;&#xA;            p1 = tuple( poly['points'][ e[0] ] )&#xD;&#xA;            p2 = tuple( poly['points'][ e[1] ] )&#xD;&#xA;            draw.line( [p1, p2], fill = color )&#xD;&#xA;&#xD;&#xA;        del draw&#xD;&#xA;&#xD;&#xA;        plt.subplot( 3, 2, plotIndex ),&#xD;&#xA;        plt.imshow( im ),&#xD;&#xA;        plt.title( plotTitle ),&#xD;&#xA;        plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;        # Draw point names (ABCD)&#xD;&#xA;        for i, c in enumerate( poly['points'] ):&#xD;&#xA;            plt.text( c[0], c[1], &quot;ABCD&quot;[i], color = 'white' )&#xD;&#xA;&#xD;&#xA;    # Define polygon as dictionary of point coordinates and edges&#xD;&#xA;    # each edge is a pair of point indices&#xD;&#xA;    p = {&#xD;&#xA;        'points' : [ (50,10), (95,30), (80,20), (62,48) ],&#xD;&#xA;        'edges'  : [ (3,0), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    xVec = [1,0] # Horizontal axis&#xD;&#xA;&#xD;&#xA;    # Draw original poly in white&#xD;&#xA;    im = Image.new( 'RGB', (100,100) )&#xD;&#xA;    draw_and_plot_polygon( im, p, (255,255,255), 'Original', 1 )&#xD;&#xA;&#xD;&#xA;    colors = [ (50,50,255), (255,0,0), (0,255,0), (200, 150, 50) ]&#xD;&#xA;&#xD;&#xA;    i = 2&#xD;&#xA;    for e, color in zip( p['edges'], colors ):&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;&#xD;&#xA;        rotPol = p.copy()&#xD;&#xA;        rotPol['points'] = rotatePolygon( p['points'], a )&#xD;&#xA;&#xD;&#xA;        # Draw rotated polygon&#xD;&#xA;        im = Image.new( 'RGB', (100,100) )&#xD;&#xA;        angleTitle = &quot;Angle: &quot; + str( round( degrees(a), 2 ) )&#xD;&#xA;        draw_and_plot_polygon( im, rotPol, color, angleTitle, i )&#xD;&#xA;&#xD;&#xA;        i += 1&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python&#xD;&#xA;  [2]: http://stackoverflow.com/questions/20023209/python-function-for-rotating-2d-objects&#xD;&#xA;  [3]: https://i.stack.imgur.com/oeSfK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3913" PostHistoryTypeId="2" PostId="1860" RevisionGUID="0edc1a05-5455-4a0c-888e-d247bd60b9f4" CreationDate="2016-01-02T08:46:03.247" UserId="1571" Text="I currently try to implement [light propagation volumes][1] in DirectX 11 and I already done the RSM part which contains position, normal, depth and flux map generation. but for Injecting Virtual point lights into light propagation volumes, we have to inject lights into x*y*z Grid that each element of grid consists of 3 vectors for each red, green and blue channels and each of vectors consists of four coefficients of  a two-band spherical harmonics.&#xD;&#xA;&#xD;&#xA;to do this here are my steps:&#xD;&#xA;&#xD;&#xA; 1. prepare 3 texture arrays, each slice is a slice of the grid&#xD;&#xA; 2. inject RSM to texture array with calculating grid space position&#xD;&#xA;&#xD;&#xA;can someone briefly explain how this injection can be done and how each virtual point lights can be used inside of each Grid units ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.crytek.com/download/Light_Propagation_Volumes.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3914" PostHistoryTypeId="1" PostId="1860" RevisionGUID="0edc1a05-5455-4a0c-888e-d247bd60b9f4" CreationDate="2016-01-02T08:46:03.247" UserId="1571" Text="Injecting Virtual point lights into 3D Grid" ContentLicense="CC BY-SA 3.0" />
  <row Id="3915" PostHistoryTypeId="3" PostId="1860" RevisionGUID="0edc1a05-5455-4a0c-888e-d247bd60b9f4" CreationDate="2016-01-02T08:46:03.247" UserId="1571" Text="|lighting|directx11|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3916" PostHistoryTypeId="2" PostId="1861" RevisionGUID="3aa4b508-40fb-4f6b-8b99-8b90214ef0b9" CreationDate="2016-01-02T13:46:45.817" UserId="2388" Text="i am wondering how professional light visualizer softwares (like Capture Argo - WYSIWYG - Realizzer - LightConverse) project the lights on the objects (like stage, floor, peoples), even projecting the various gobos ( shapes).&#xD;&#xA;Here are some screenshots:&#xD;&#xA;&#xD;&#xA;http://www.diversitronics.de/tl_files/Bilder/Produkte/Capture/renderings/capture1.jpg&#xD;&#xA;&#xD;&#xA;http://www.selightingdesign.co.uk/images/portfolio/capture%20hairspray/production%20photos/fullscreen/01.jpg&#xD;&#xA;&#xD;&#xA;How they can calculate the various intersections, and project beams for so many light sources in an efficient way? Whats the simplest way?&#xD;&#xA;I assume they are projecting a texture but how?&#xD;&#xA;&#xD;&#xA;Sorry for my horrible english :)&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="3917" PostHistoryTypeId="1" PostId="1861" RevisionGUID="3aa4b508-40fb-4f6b-8b99-8b90214ef0b9" CreationDate="2016-01-02T13:46:45.817" UserId="2388" Text="Projecting light shapes" ContentLicense="CC BY-SA 3.0" />
  <row Id="3918" PostHistoryTypeId="3" PostId="1861" RevisionGUID="3aa4b508-40fb-4f6b-8b99-8b90214ef0b9" CreationDate="2016-01-02T13:46:45.817" UserId="2388" Text="|opengl|rendering|texture|performance|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3919" PostHistoryTypeId="2" PostId="1862" RevisionGUID="d8df479c-2716-49ec-b3ed-fa82ece5903a" CreationDate="2016-01-02T22:38:07.437" UserId="2393" Text="Without there being black bars I mean. 1080 isn't any multiple of 768 so is there some sort of data loss?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3920" PostHistoryTypeId="1" PostId="1862" RevisionGUID="d8df479c-2716-49ec-b3ed-fa82ece5903a" CreationDate="2016-01-02T22:38:07.437" UserId="2393" Text="How does a computer upscale 1024x768 resolution to 1920x1080?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3921" PostHistoryTypeId="3" PostId="1862" RevisionGUID="d8df479c-2716-49ec-b3ed-fa82ece5903a" CreationDate="2016-01-02T22:38:07.437" UserId="2393" Text="|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3922" PostHistoryTypeId="5" PostId="1861" RevisionGUID="12e1c21a-1478-40bf-829e-ed1357eb6ae0" CreationDate="2016-01-02T23:24:23.343" UserId="231" Comment="Minor tidying" Text="I am wondering how professional light visualizer software (like Capture Argo - WYSIWYG - Realizzer - LightConverse) project the lights on the objects (like stage, floor, people), even projecting the various [gobos] (shapes).&#xD;&#xA;&#xD;&#xA;Here are some screenshots:&#xD;&#xA;&#xD;&#xA;http://www.diversitronics.de/tl_files/Bilder/Produkte/Capture/renderings/capture1.jpg&#xD;&#xA;&#xD;&#xA;http://www.selightingdesign.co.uk/images/portfolio/capture%20hairspray/production%20photos/fullscreen/01.jpg&#xD;&#xA;&#xD;&#xA;How do they calculate the various intersections, and project beams for so many light sources in an efficient way? What's the simplest way?&#xD;&#xA;&#xD;&#xA;I assume they are projecting a texture but how?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [gobos]: https://en.wikipedia.org/wiki/Gobo_%28lighting%29 &quot;a physical stencil or template slotted inside, or placed in front of, a lighting source, used to control the shape of emitted light.&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3923" PostHistoryTypeId="5" PostId="1860" RevisionGUID="cd4e8117-29a1-451b-9644-ece7b20c6e70" CreationDate="2016-01-02T23:38:25.120" UserId="231" Comment="Minor tidying" Text="I am currently trying to implement [light propagation volumes][1] in DirectX 11 and I have already done the RSM part which contains position, normal, depth and flux map generation. But for Injecting Virtual point lights into light propagation volumes, we have to inject lights into an x,y,z grid for which each element consists of 3 vectors for each of red, green and blue channels and each vector consists of four coefficients of a two-band spherical harmonic.&#xD;&#xA;&#xD;&#xA;To do this, here are my steps:&#xD;&#xA;&#xD;&#xA; 1. Prepare 3 texture arrays. Each slice is a slice of the grid.&#xD;&#xA; 1. Inject RSM into the texture array by calculating grid space position.&#xD;&#xA;&#xD;&#xA;Can someone briefly explain how this injection can be done and how each virtual point light can be used inside each grid unit?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.crytek.com/download/Light_Propagation_Volumes.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3924" PostHistoryTypeId="5" PostId="1859" RevisionGUID="5b58cf6d-98be-49d4-953d-a38517cff89b" CreationDate="2016-01-03T05:34:40.750" UserId="2317" Comment="Added code that positions aligned edge at bottom" Text="This algorithm is based on [this answer for finding the angle between vectors][1], and [this answer for rotating polygon points][2]. It's written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with a `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;**EDITED**: Added code for rotating the polygon and displaying the original and rotated polygons. Result of this script is displayed in the image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from math import radians, degrees, sqrt, acos, cos, sin&#xD;&#xA;&#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;&#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;&#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;&#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;&#xD;&#xA;    def calc_edge_vec( poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;&#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;&#xD;&#xA;    def rotatePolygon( poly, theta ):&#xD;&#xA;        ''' Rotates the given polygon which consists of corners represented&#xD;&#xA;            as (x,y), around the ORIGIN, clock-wise, theta degrees&#xD;&#xA;        '''&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = []&#xD;&#xA;        for corner in poly:&#xD;&#xA;            rotatedPolygon.append((&#xD;&#xA;                corner[0] * cos( theta ) - corner[1] * sin( theta ), # x&#xD;&#xA;                corner[0] * sin( theta ) + corner[1] * cos( theta )  # y&#xD;&#xA;            ))&#xD;&#xA;&#xD;&#xA;        # Make sure rotated polygon coordinates are within image boundaries&#xD;&#xA;        minX = min( [ c[0] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minX = minX if minX &gt; 0 else 0&#xD;&#xA;        minY = min( [ c[1] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minY = minY if minY &gt; 0 else 0&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = [ ( x + minX, y + minY ) for x, y in rotatedPolygon ]&#xD;&#xA;&#xD;&#xA;        return rotatedPolygon&#xD;&#xA;&#xD;&#xA;    def draw_and_plot_polygon( im, poly, color, plotTitle, plotIndex ):&#xD;&#xA;        draw = ImageDraw.Draw( im )&#xD;&#xA;&#xD;&#xA;        for e in poly['edges']:&#xD;&#xA;            p1 = tuple( poly['points'][ e[0] ] )&#xD;&#xA;            p2 = tuple( poly['points'][ e[1] ] )&#xD;&#xA;            draw.line( [p1, p2], fill = color )&#xD;&#xA;&#xD;&#xA;        del draw&#xD;&#xA;&#xD;&#xA;        plt.subplot( 3, 2, plotIndex ),&#xD;&#xA;        plt.imshow( im ),&#xD;&#xA;        plt.title( plotTitle ),&#xD;&#xA;        plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;        # Draw point names (ABCD)&#xD;&#xA;        for i, c in enumerate( poly['points'] ):&#xD;&#xA;            plt.text( c[0], c[1], &quot;ABCD&quot;[i], color = 'white' )&#xD;&#xA;&#xD;&#xA;    # Define polygon as dictionary of point coordinates and edges&#xD;&#xA;    # each edge is a pair of point indices&#xD;&#xA;    p = {&#xD;&#xA;        'points' : [ (50,10), (95,30), (80,20), (62,48) ],&#xD;&#xA;        'edges'  : [ (3,0), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    xVec = [1,0] # Horizontal axis&#xD;&#xA;&#xD;&#xA;    # Draw original poly in white&#xD;&#xA;    im = Image.new( 'RGB', (100,100) )&#xD;&#xA;    draw_and_plot_polygon( im, p, (255,255,255), 'Original', 1 )&#xD;&#xA;&#xD;&#xA;    colors = [ (50,50,255), (255,0,0), (0,255,0), (200, 150, 50) ]&#xD;&#xA;&#xD;&#xA;    i = 2&#xD;&#xA;    for e, color in zip( p['edges'], colors ):&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;&#xD;&#xA;        rotPol = p.copy()&#xD;&#xA;        rotPol['points'] = rotatePolygon( p['points'], a )&#xD;&#xA;&#xD;&#xA;        im = Image.new( 'RGB', (100,100) )&#xD;&#xA;&#xD;&#xA;        # Place aligned edge at bottom&#xD;&#xA;        alingedEdgeY = im.size[1] - rotPol['points'][ e[0] ][ 1 ] # Current edge height&#xD;&#xA;        rotPol['points'] = [ ( p[0], p[1] + alingedEdgeY ) for p in rotPol['points'] ]&#xD;&#xA;&#xD;&#xA;        # Draw rotated polygon&#xD;&#xA;        angleTitle = &quot;Angle: &quot; + str( round( degrees(a), 2 ) )&#xD;&#xA;        draw_and_plot_polygon( im, rotPol, color, angleTitle, i )&#xD;&#xA;&#xD;&#xA;        i += 1&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;**EDITED 2**: Added some code to position the rotated polygon so that the aligned edge is on the floor (lines 90-91). Here's the result:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python&#xD;&#xA;  [2]: http://stackoverflow.com/questions/20023209/python-function-for-rotating-2d-objects&#xD;&#xA;  [3]: https://i.stack.imgur.com/oeSfK.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/SRPg3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3925" PostHistoryTypeId="2" PostId="1863" RevisionGUID="02875bcf-4fa2-42ee-8996-93dd169b74f0" CreationDate="2016-01-03T18:02:07.997" UserId="38" Text="Deducing the angle and rotating bu that angle works quite well in 2D. This strategy, does not extend very well into three-dimensional realm. I will provide an alternative solution that shows a general strategy that works in a larger set of cases. As a bonus this without needing to think of trigonometry as it can be encoded away.&#xD;&#xA;&#xD;&#xA;1. First identify the vector that you want to be transformed to orientation in your reference space. Let us call this vector $\vec{a}$, or a along vector.&#xD;&#xA;&#xD;&#xA;2. Next you will need to identify a vector that is perpendicular to this vector. Let us call this vector $\vec{b}$, it is sometimes also called a up vector. In three-dimensions you need 3 vectors but once you identify 2 you can compute the third.&#xD;&#xA;&#xD;&#xA;  Finding out the $\vec{b}$ in 2-D realm is especially easy you could just rotate the vector by $90^{\circ}$ or simply swap the coordinates and make the x coordinate negative (see 1). Alternatively you can use the same procedure as in 3D.&#xD;&#xA;&#xD;&#xA;   $$\vec(b) = rotate(90^{\circ})\cdot\vec{a} =&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         \cos(\pi/2) &amp; -\sin(\pi/2) \\ &#xD;&#xA;         \sin(\pi/2) &amp; \cos(\pi/2) &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         x \\ &#xD;&#xA;         y &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;         =       &#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         -y \\ &#xD;&#xA;         x &#xD;&#xA;      \end{bmatrix} &#xD;&#xA;     \tag{1}$$&#xD;&#xA;&#xD;&#xA;  In 3-D this usually requires a trick. Since each triangle is flat, one can use this to ones advantage. This gives us a perpendicular direction, now we still need a third one and we can get it by cross product of the 2 known vectors. You now have 3 vector.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: Vector $\vec{a}$ and derived $\vec{b}$&#xD;&#xA;3. Normalize the vectors&#xD;&#xA;&#xD;&#xA;4. Use these vectors to produce a a rotation matrix (or a affine matrix wich allows you to specify point to be at zero, your choice). This matrix represents the local coordinate of the rotated object. &#xD;&#xA;&#xD;&#xA;5. All you now need is to invert this matrix and point matrix multiply your polygon corner vectors for a aligned version of the polygon.&#xD;&#xA;&#xD;&#xA;What is especially nifty is the sidestepping of trigonometrical operations. Now i see no point i defining basic matrix operations but i see value in code. So i will use numpy.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    import pylab&#xD;&#xA;&#xD;&#xA;    pts = np.array([&#xD;&#xA;            [0.,0.], [10.,1.], [12.,12.], [-2.,11.], [0.,0.]&#xD;&#xA;          ]).transpose()&#xD;&#xA;         &#xD;&#xA;    # visualize&#xD;&#xA;    f = pylab.figure(facecolor=&quot;1.&quot;)     &#xD;&#xA;    pylab.axis('off')&#xD;&#xA;    pylab.plot(pts[0], pts[1])  &#xD;&#xA;&#xD;&#xA;    # 1. Get the vector&#xD;&#xA;    vec_a = np.copy(pts[:,1])&#xD;&#xA;&#xD;&#xA;    # 2. up vector&#xD;&#xA;    vec_b = np.copy(vec_a[::-1])&#xD;&#xA;    vec_b[0] *= -1&#xD;&#xA;&#xD;&#xA;    # 3. normalize&#xD;&#xA;    vec_a /= np.linalg.norm(vec_a)&#xD;&#xA;    vec_b /= np.linalg.norm(vec_b)&#xD;&#xA;&#xD;&#xA;    # 4. build rotation matrix&#xD;&#xA;    mtx_R = np.concatenate(([vec_a], [vec_b])).transpose()&#xD;&#xA;    mtx_R = np.linalg.inv(mtx_R)&#xD;&#xA;&#xD;&#xA;    # 5. transform, or set hierarchy matrix&#xD;&#xA;    pts2 = np.copy(pts)&#xD;&#xA;    for i in range(len(pts2[0])):&#xD;&#xA;        pts2[:,i] =  np.dot(mtx_R, pts2[:,i])&#xD;&#xA;&#xD;&#xA;    # visualize 2&#xD;&#xA;    pylab.plot(pts2[0],pts2[1])&#xD;&#xA;    pylab.show()&#xD;&#xA;&#xD;&#xA;I admit it cold be have slightly shorter by refactoring the code and eliminate redundant manipulations but its a demo only so... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Polygon, in blue axis fixed in green.&#xD;&#xA;&#xD;&#xA;Same method works well for straightening, skew and other problems such as perspective correction.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BcxhU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/U0rbI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3926" PostHistoryTypeId="5" PostId="1863" RevisionGUID="4738e69b-12fb-4fad-adef-bf99aeb815f3" CreationDate="2016-01-03T18:17:19.630" UserId="38" Comment="added 1 character in body" Text="Deducing the angle and rotating bu that angle works quite well in 2D (describe in [TLousky's post](http://computergraphics.stackexchange.com/a/1859/38)). This strategy, does not extend very well into three-dimensional realm. I will provide an alternative solution that shows a general strategy that works in a larger set of cases. As a bonus this without needing to think of trigonometry as it can be encoded away.&#xD;&#xA;&#xD;&#xA;1. First identify the vector that you want to be transformed to orientation in your reference space. Let us call this vector $\vec{a}$, or a along vector.&#xD;&#xA;&#xD;&#xA;2. Next you will need to identify a vector that is perpendicular to this vector. Let us call this vector $\vec{b}$, it is sometimes also called a up vector. In three-dimensions you need 3 vectors but once you identify 2 you can compute the third.&#xD;&#xA;&#xD;&#xA;  Finding out the $\vec{b}$ in 2-D realm is especially easy you could just rotate the vector by $90^{\circ}$ or simply swap the coordinates and make the x coordinate negative (see 1). Alternatively you can use the same procedure as in 3D.&#xD;&#xA;&#xD;&#xA;   $$\vec(b) = rotate(90^{\circ})\cdot\vec{a} =&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         \cos(\pi/2) &amp; -\sin(\pi/2) \\ &#xD;&#xA;         \sin(\pi/2) &amp; \cos(\pi/2) &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         x \\ &#xD;&#xA;         y &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;         =       &#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         -y \\ &#xD;&#xA;         x &#xD;&#xA;      \end{bmatrix} &#xD;&#xA;     \tag{1}$$&#xD;&#xA;&#xD;&#xA;  In 3-D this usually requires a trick. Since each triangle is flat, one can use this to ones advantage. This gives us a perpendicular direction, now we still need a third one and we can get it by cross product of the 2 known vectors. You now have 3 vector.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: Vector $\vec{a}$ and derived $\vec{b}$&#xD;&#xA;3. Normalize the vectors&#xD;&#xA;&#xD;&#xA;4. Use these vectors to produce a a rotation matrix (or a affine matrix wich allows you to specify point to be at zero, your choice). This matrix represents the local coordinate of the rotated object. &#xD;&#xA;&#xD;&#xA;5. All you now need is to invert this matrix and point matrix multiply your polygon corner vectors for a aligned version of the polygon.&#xD;&#xA;&#xD;&#xA;What is especially nifty is the sidestepping of trigonometrical operations. Now i see no point i defining basic matrix operations but i see value in code. So i will use numpy.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np, pylab&#xD;&#xA;&#xD;&#xA;    pts = np.array([&#xD;&#xA;            [0.,0.],[10.,1.],[12.,12.],[-2.,11.],[0.,0.]&#xD;&#xA;          ]).transpose()&#xD;&#xA;         &#xD;&#xA;    f = pylab.figure(facecolor=&quot;1.&quot;)     &#xD;&#xA;    pylab.axis('off')&#xD;&#xA;    pylab.axis('equal')&#xD;&#xA;    pylab.plot(pts[0], pts[1])  &#xD;&#xA;&#xD;&#xA;    # 1. Get the vector&#xD;&#xA;    vec_a = np.copy(pts[:,2]) - np.copy(pts[:,1])&#xD;&#xA;&#xD;&#xA;    # 2. up vector&#xD;&#xA;    vec_b = np.copy(vec_a[::-1])&#xD;&#xA;    vec_b[0] *= -1&#xD;&#xA;&#xD;&#xA;    # 3. normalize&#xD;&#xA;    vec_a /= np.linalg.norm(vec_a)&#xD;&#xA;    vec_b /= np.linalg.norm(vec_b)&#xD;&#xA;&#xD;&#xA;    # 4. build rotation matrix&#xD;&#xA;    mtx_R = np.concatenate(([vec_a], [vec_b])).transpose()&#xD;&#xA;    mtx_R = np.linalg.inv(mtx_R)&#xD;&#xA;&#xD;&#xA;    # 5. transform, or set hierarchy transform&#xD;&#xA;    pts2 = np.copy(pts)&#xD;&#xA;    for i in range(len(pts2[0])):&#xD;&#xA;        pts2[:,i] =  np.dot(mtx_R, pts2[:,i])&#xD;&#xA;&#xD;&#xA;    pylab.plot(pts2[0],pts2[1])&#xD;&#xA;    pylab.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I admit it cold be have slightly shorter by refactoring the code and eliminate redundant manipulations but its a demo only so... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Polygon, in blue axis fixed in green.&#xD;&#xA;&#xD;&#xA;Same method works well for straightening, skew and other problems such as perspective correction. You can extend this to affine matrices that way you can encode the translation into the calculation with just 2 more lines. In essence you specify what point is at origin and with 1 more operation around what to rotate.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BcxhU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xkgLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3927" PostHistoryTypeId="5" PostId="1863" RevisionGUID="81a7e163-fe5f-4161-8300-1ec28eee6d2b" CreationDate="2016-01-03T18:23:01.200" UserId="38" Comment="added 42 characters in body" Text="Deducing the angle and rotating bu that angle works quite well in 2D (describe in [TLousky's post](http://computergraphics.stackexchange.com/a/1859/38)). This strategy, does not extend very well into three-dimensional realm. I will provide an alternative solution that shows a general strategy that works in a larger set of cases. As a bonus this without needing to think of trigonometry as it can be encoded away.&#xD;&#xA;&#xD;&#xA;1. First identify the vector that you want to be transformed to orientation in your reference space. Let us call this vector $\vec{a}$, or a along vector.&#xD;&#xA;&#xD;&#xA;2. Next you will need to identify a vector that is perpendicular to this vector. Let us call this vector $\vec{b}$, it is sometimes also called a up vector. In three-dimensions you need 3 vectors but once you identify 2 you can compute the third.&#xD;&#xA;&#xD;&#xA;  Finding out the $\vec{b}$ in 2-D realm is especially easy you could just rotate the vector by $90^{\circ}$ or simply swap the coordinates and make the x coordinate negative (see 1). Alternatively you can use the same procedure as in 3D.&#xD;&#xA;&#xD;&#xA;   $$\vec(b) = rotate(90^{\circ})\cdot\vec{a} =&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         \cos(\pi/2) &amp; -\sin(\pi/2) \\ &#xD;&#xA;         \sin(\pi/2) &amp; \cos(\pi/2) &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         x \\ &#xD;&#xA;         y &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;         =       &#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         -y \\ &#xD;&#xA;         x &#xD;&#xA;      \end{bmatrix} &#xD;&#xA;     \tag{1}$$&#xD;&#xA;&#xD;&#xA;  In 3-D this usually requires a trick. Since each triangle is flat, one can use this to ones advantage. This gives us a perpendicular direction, now we still need a third one and we can get it by cross product of the 2 known vectors. You now have 3 vector.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: Vector $\vec{a}$ and derived $\vec{b}$&#xD;&#xA;3. Normalize the vectors&#xD;&#xA;&#xD;&#xA;4. Use these vectors to produce a a rotation matrix (or a affine matrix wich allows you to specify point to be at zero, your choice). This matrix represents the local coordinate of the rotated object. &#xD;&#xA;&#xD;&#xA;5. All you now need is to invert this matrix and point matrix multiply your polygon corner vectors for a aligned version of the polygon.&#xD;&#xA;&#xD;&#xA;What is especially nifty is the sidestepping of trigonometrical operations. Now i see no point i defining basic matrix operations but i see value in code. So i will use numpy.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np, pylab&#xD;&#xA;&#xD;&#xA;    pts = np.array([&#xD;&#xA;            [0.,0.],[10.,1.],[12.,12.],[-2.,11.],[0.,0.]&#xD;&#xA;          ]).transpose()&#xD;&#xA;         &#xD;&#xA;    f = pylab.figure(facecolor=&quot;1.&quot;)     &#xD;&#xA;    pylab.axis('off')&#xD;&#xA;    pylab.axis('equal')&#xD;&#xA;    pylab.plot(pts[0], pts[1])  &#xD;&#xA;&#xD;&#xA;    # 1. Get the vector&#xD;&#xA;    vec_a = np.copy(pts[:,2]) - np.copy(pts[:,1])&#xD;&#xA;&#xD;&#xA;    # 2. up vector&#xD;&#xA;    vec_b = np.copy(vec_a[::-1])&#xD;&#xA;    vec_b[0] *= -1&#xD;&#xA;&#xD;&#xA;    # 3. normalize&#xD;&#xA;    vec_a /= np.linalg.norm(vec_a)&#xD;&#xA;    vec_b /= np.linalg.norm(vec_b)&#xD;&#xA;&#xD;&#xA;    # 4. build rotation matrix&#xD;&#xA;    mtx_R = np.concatenate(([vec_a], [vec_b])).transpose()&#xD;&#xA;    mtx_R = np.linalg.inv(mtx_R)&#xD;&#xA;&#xD;&#xA;    # 5. transform, or set hierarchy transform&#xD;&#xA;    pts2 = np.copy(pts)&#xD;&#xA;    for i in range(len(pts2[0])):&#xD;&#xA;        pts2[:,i] =  np.dot(mtx_R, pts2[:,i])&#xD;&#xA;&#xD;&#xA;    pylab.plot(pts2[0],pts2[1])&#xD;&#xA;    pylab.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I admit it cold be have slightly shorter by refactoring the code and eliminate redundant manipulations but its a demo only so... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Polygon, in blue axis fixed in green.&#xD;&#xA;&#xD;&#xA;Same method works well for straightening, skew and other problems such as perspective correction. You can extend this to affine matrices that way you can encode the translation into the calculation with just 1 more lines. In essence you specify what point is at origin and with 2 more operations one could define around what to rotate. Now it just just rotates about the origin.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BcxhU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xkgLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3929" PostHistoryTypeId="5" PostId="1863" RevisionGUID="7f9b3623-64a0-46c5-badb-5a08d0ce766a" CreationDate="2016-01-04T06:08:12.827" UserId="38" Comment="edited body" Text="Deducing the angle and rotating by that angle works quite well in 2D (describe in [TLousky's post](http://computergraphics.stackexchange.com/a/1859/38)). This strategy, does not extend very well into three-dimensional realm. I will provide an alternative solution that shows a general strategy that works in a larger set of cases. As a bonus this without needing to think of trigonometry as it can be encoded away.&#xD;&#xA;&#xD;&#xA;1. First identify the vector that you want to be transformed to orientation in your reference space. Let us call this vector $\vec{a}$, or a along vector.&#xD;&#xA;&#xD;&#xA;2. Next you will need to identify a vector that is perpendicular to this vector. Let us call this vector $\vec{b}$, it is sometimes also called a up vector. In three-dimensions you need 3 vectors but once you identify 2 you can compute the third.&#xD;&#xA;&#xD;&#xA;  Finding out the $\vec{b}$ in 2-D realm is especially easy you could just rotate the vector by $90^{\circ}$ or simply swap the coordinates and make the x coordinate negative (see 1). Alternatively you can use the same procedure as in 3D.&#xD;&#xA;&#xD;&#xA;   $$\vec(b) = rotate(90^{\circ})\cdot\vec{a} =&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         \cos(\pi/2) &amp; -\sin(\pi/2) \\ &#xD;&#xA;         \sin(\pi/2) &amp; \cos(\pi/2) &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         x \\ &#xD;&#xA;         y &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;         =       &#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         -y \\ &#xD;&#xA;         x &#xD;&#xA;      \end{bmatrix} &#xD;&#xA;     \tag{1}$$&#xD;&#xA;&#xD;&#xA;  In 3-D this usually requires a trick. Since each triangle is flat, one can use this to ones advantage. This gives us a perpendicular direction, now we still need a third one and we can get it by cross product of the 2 known vectors. You now have 3 vector.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: Vector $\vec{a}$ and derived $\vec{b}$&#xD;&#xA;3. Normalize the vectors&#xD;&#xA;&#xD;&#xA;4. Use these vectors to produce a a rotation matrix (or a affine matrix wich allows you to specify point to be at zero, your choice). This matrix represents the local coordinate of the rotated object. &#xD;&#xA;&#xD;&#xA;5. All you now need is to invert this matrix and point matrix multiply your polygon corner vectors for a aligned version of the polygon.&#xD;&#xA;&#xD;&#xA;What is especially nifty is the sidestepping of trigonometrical operations. Now i see no point i defining basic matrix operations but i see value in code. So i will use numpy.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np, pylab&#xD;&#xA;&#xD;&#xA;    pts = np.array([&#xD;&#xA;            [0.,0.],[10.,1.],[12.,12.],[-2.,11.],[0.,0.]&#xD;&#xA;          ]).transpose()&#xD;&#xA;         &#xD;&#xA;    f = pylab.figure(facecolor=&quot;1.&quot;)     &#xD;&#xA;    pylab.axis('off')&#xD;&#xA;    pylab.axis('equal')&#xD;&#xA;    pylab.plot(pts[0], pts[1])  &#xD;&#xA;&#xD;&#xA;    # 1. Get the vector&#xD;&#xA;    vec_a = np.copy(pts[:,2]) - np.copy(pts[:,1])&#xD;&#xA;&#xD;&#xA;    # 2. up vector&#xD;&#xA;    vec_b = np.copy(vec_a[::-1])&#xD;&#xA;    vec_b[0] *= -1&#xD;&#xA;&#xD;&#xA;    # 3. normalize&#xD;&#xA;    vec_a /= np.linalg.norm(vec_a)&#xD;&#xA;    vec_b /= np.linalg.norm(vec_b)&#xD;&#xA;&#xD;&#xA;    # 4. build rotation matrix&#xD;&#xA;    mtx_R = np.concatenate(([vec_a], [vec_b])).transpose()&#xD;&#xA;    mtx_R = np.linalg.inv(mtx_R)&#xD;&#xA;&#xD;&#xA;    # 5. transform, or set hierarchy transform&#xD;&#xA;    pts2 = np.copy(pts)&#xD;&#xA;    for i in range(len(pts2[0])):&#xD;&#xA;        pts2[:,i] =  np.dot(mtx_R, pts2[:,i])&#xD;&#xA;&#xD;&#xA;    pylab.plot(pts2[0],pts2[1])&#xD;&#xA;    pylab.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I admit it cold be have slightly shorter by refactoring the code and eliminate redundant manipulations but its a demo only so... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Polygon, in blue axis fixed in green.&#xD;&#xA;&#xD;&#xA;Same method works well for straightening, skew and other problems such as perspective correction. You can extend this to affine matrices that way you can encode the translation into the calculation with just 1 more lines. In essence you specify what point is at origin and with 2 more operations one could define around what to rotate. Now it just just rotates about the origin.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BcxhU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xkgLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3930" PostHistoryTypeId="5" PostId="1863" RevisionGUID="87ec210e-d731-4c71-ae48-5cbb3638e384" CreationDate="2016-01-04T12:03:57.130" UserId="38" Comment="edited body" Text="Deducing the angle and rotating by that angle works quite well in 2D (describe in [TLousky's post](http://computergraphics.stackexchange.com/a/1859/38)). This strategy, does not extend very well into three-dimensional realm. I will provide an alternative solution that shows a general strategy that works in a larger set of cases. As a bonus this without needing to think of trigonometry as it can be encoded away.&#xD;&#xA;&#xD;&#xA;1. First identify the vector that you want to be transformed to orientation in your reference space. Let us call this vector $\vec{a}$, or a along vector.&#xD;&#xA;&#xD;&#xA;2. Next you will need to identify a vector that is perpendicular to this vector. Let us call this vector $\vec{b}$, it is sometimes also called a up vector. In three-dimensions you need 3 vectors but once you identify 2 you can compute the third.&#xD;&#xA;&#xD;&#xA;  Finding out the $\vec{b}$ in 2-D realm is especially easy you could just rotate the vector by $90^{\circ}$ or simply swap the coordinates and make the x coordinate negative (see 1). Alternatively you can use the same procedure as in 3D.&#xD;&#xA;&#xD;&#xA;   $$\vec{b} = rotate(90^{\circ})\cdot\vec{a} =&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         \cos(\pi/2) &amp; -\sin(\pi/2) \\ &#xD;&#xA;         \sin(\pi/2) &amp; \cos(\pi/2) &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         x \\ &#xD;&#xA;         y &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;         =       &#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         -y \\ &#xD;&#xA;         x &#xD;&#xA;      \end{bmatrix} &#xD;&#xA;     \tag{1}$$&#xD;&#xA;&#xD;&#xA;  In 3-D this usually requires a trick. Since each triangle is flat, one can use this to ones advantage. This gives us a perpendicular direction, now we still need a third one and we can get it by cross product of the 2 known vectors. You now have 3 vector.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: Vector $\vec{a}$ and derived $\vec{b}$&#xD;&#xA;3. Normalize the vectors&#xD;&#xA;&#xD;&#xA;4. Use these vectors to produce a a rotation matrix (or a affine matrix wich allows you to specify point to be at zero, your choice). This matrix represents the local coordinate of the rotated object. &#xD;&#xA;&#xD;&#xA;5. All you now need is to invert this matrix and point matrix multiply your polygon corner vectors for a aligned version of the polygon.&#xD;&#xA;&#xD;&#xA;What is especially nifty is the sidestepping of trigonometrical operations. Now i see no point i defining basic matrix operations but i see value in code. So i will use numpy.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np, pylab&#xD;&#xA;&#xD;&#xA;    pts = np.array([&#xD;&#xA;            [0.,0.],[10.,1.],[12.,12.],[-2.,11.],[0.,0.]&#xD;&#xA;          ]).transpose()&#xD;&#xA;         &#xD;&#xA;    f = pylab.figure(facecolor=&quot;1.&quot;)     &#xD;&#xA;    pylab.axis('off')&#xD;&#xA;    pylab.axis('equal')&#xD;&#xA;    pylab.plot(pts[0], pts[1])  &#xD;&#xA;&#xD;&#xA;    # 1. Get the vector&#xD;&#xA;    vec_a = np.copy(pts[:,2]) - np.copy(pts[:,1])&#xD;&#xA;&#xD;&#xA;    # 2. up vector&#xD;&#xA;    vec_b = np.copy(vec_a[::-1])&#xD;&#xA;    vec_b[0] *= -1&#xD;&#xA;&#xD;&#xA;    # 3. normalize&#xD;&#xA;    vec_a /= np.linalg.norm(vec_a)&#xD;&#xA;    vec_b /= np.linalg.norm(vec_b)&#xD;&#xA;&#xD;&#xA;    # 4. build rotation matrix&#xD;&#xA;    mtx_R = np.concatenate(([vec_a], [vec_b])).transpose()&#xD;&#xA;    mtx_R = np.linalg.inv(mtx_R)&#xD;&#xA;&#xD;&#xA;    # 5. transform, or set hierarchy transform&#xD;&#xA;    pts2 = np.copy(pts)&#xD;&#xA;    for i in range(len(pts2[0])):&#xD;&#xA;        pts2[:,i] =  np.dot(mtx_R, pts2[:,i])&#xD;&#xA;&#xD;&#xA;    pylab.plot(pts2[0],pts2[1])&#xD;&#xA;    pylab.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I admit it cold be have slightly shorter by refactoring the code and eliminate redundant manipulations but its a demo only so... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Polygon, in blue axis fixed in green.&#xD;&#xA;&#xD;&#xA;Same method works well for straightening, skew and other problems such as perspective correction. You can extend this to affine matrices that way you can encode the translation into the calculation with just 1 more lines. In essence you specify what point is at origin and with 2 more operations one could define around what to rotate. Now it just just rotates about the origin.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BcxhU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xkgLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3931" PostHistoryTypeId="2" PostId="1864" RevisionGUID="e3c4a7fb-187d-4985-84bd-747caef48b1a" CreationDate="2016-01-04T22:06:06.210" UserId="127" Text="**Computer Graphics Stack Exchange** is for computer graphics researchers and programmers.&#xA;&#xA;Topics that are usually a good fit for this site include:&#xA;&#xA;* Questions about math related to computer graphics,&#xA;* Questions about a specific graphics [programming](http://meta.computergraphics.stackexchange.com/questions/67/are-questions-about-api-specific-stuff-on-topic) or [debugging](http://meta.computergraphics.stackexchange.com/questions/1/are-questions-about-debugging-opengl-shaders-on-topic) problem,&#xA;* Questions about a specific [graphics API](http://meta.computergraphics.stackexchange.com/questions/67/are-questions-about-api-specific-stuff-on-topic),&#xA;* Questions about a specific graphics algorithm or concept.&#xA;&#xA;If your question generally covers (one of) these topics, then you’re in the right place to ask your question!&#xA;&#xA;---&#xA;&#xA;However, some questions are still off-topic, although they might fit into the above criteria.&#xA;&#xA;* Questions asking for [off-site resources](http://meta.computergraphics.stackexchange.com/questions/146/are-questions-asking-for-off-site-resources-on-topic) including books, tools and tutorials are off-topic as they tend to attract opinionated answers and spam. Also, the other sites may remove their content, which makes the question here useless for future visitors. Instead, ask about the specific problem you have.&#xA;* The same applies to questions asking for [software recommendations](http://meta.computergraphics.stackexchange.com/questions/141/are-questions-about-software-recommendation-in-scope). You may ask such questions on [Software Recommendations Stack Exchange](http://softwarerecs.stackexchange.com/), but please first read over their [Help Center](https://softwarerecs.stackexchange.com/help/on-topic) and [quality guidelines](http://meta.softwarerecs.stackexchange.com/questions/336/what-is-required-for-a-question-to-contain-enough-information).&#xA;* Questions about [how to use (a feature of) modeling software](http://meta.computergraphics.stackexchange.com/questions/13/is-asking-about-maya-or-3ds-max-blender-api-on-topic) are off-topic here, but may be suitable to [Super User](http://superuser.com). Questions specific to Blender may even be asked on [Blender Stack Exchange](http://blender.stackexchange.com). Again, please have a look into their Help Centers before asking.&#xA;* Questions about [Computer Vision](http://meta.computergraphics.stackexchange.com/questions/176/is-computer-vision-in-scope) are off-topic, except where it overlaps with computer graphics. As there is a significant part of overlap between these two topics, the line is blurry. Also, a site dedicated to Image Processing and Computer Vision is [already proposed](http://area51.stackexchange.com/proposals/86832/image-processing-and-computer-vision), or have a look at [Signal Processing Stack Exchange](http://dsp.stackexchange.com) and their Help Center.&#xA;&#xA;---&#xA;&#xA;&lt;p&gt;Please &lt;a href=&quot;/search&quot;&gt;look around&lt;/a&gt; to see if your question has been asked before. It’s also OK to &lt;a href=&quot;/helpcenter/self-answer&quot;&gt;ask and answer your own question&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your question is not specifically on-topic for $SiteName, it may be on topic for another Stack Exchange site. If no site currently exists that will accept your question, you may &lt;a href=&quot;http://area51.stackexchange.com/faq&quot;&gt;commit to&lt;/a&gt; or &lt;a href=&quot;http://meta.stackexchange.com/questions/76974/how-can-i-propose-a-new-site&quot;&gt;propose&lt;/a&gt; a new site at &lt;a href=&quot;http://area51.stackexchange.com/&quot;&gt;Area51&lt;/a&gt;, the place where new Stack Exchange communities are democratically created.&lt;/p&gt;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3932" PostHistoryTypeId="2" PostId="1865" RevisionGUID="294571cf-f169-4201-aa28-64ba41202d44" CreationDate="2016-01-05T01:14:34.330" UserId="56" Text="One hacky method I've seen in real time raytracers / ray marching is to cast a ray per color channel (rgb) and do things Iike have different refraction indices per color channel." ContentLicense="CC BY-SA 3.0" />
  <row Id="3934" PostHistoryTypeId="2" PostId="1866" RevisionGUID="e2519b08-ef2b-4654-9901-45fa3aa58990" CreationDate="2016-01-05T15:53:46.143" UserId="2214" Text="I want to find the texture coordinates for point P. I have the vertices of the triangle and their corresponding uv coordinates. &#xD;&#xA;&#xD;&#xA;The numbers in the little squares in the texture represent color values.&#xD;&#xA;&#xD;&#xA;What are the steps of computing the uv coordinates of P?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cVDiT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3935" PostHistoryTypeId="1" PostId="1866" RevisionGUID="e2519b08-ef2b-4654-9901-45fa3aa58990" CreationDate="2016-01-05T15:53:46.143" UserId="2214" Text="How to map square texture to triangle?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3936" PostHistoryTypeId="3" PostId="1866" RevisionGUID="e2519b08-ef2b-4654-9901-45fa3aa58990" CreationDate="2016-01-05T15:53:46.143" UserId="2214" Text="|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3937" PostHistoryTypeId="2" PostId="1867" RevisionGUID="c757fa08-ae82-429c-b27d-34295c33b359" CreationDate="2016-01-05T17:45:59.417" UserId="457" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of `P`. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles `ABP`, `PBC` and `PCA`.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex `A` on the point `P` is proportional to the ratio of the triangle `PBC` to the whole triangle `ABC`.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as `P` moves towards `A` the triangle `PBC` grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the 3 coordinates of a point **inside a triangle** always equals `1`. So it is enough to find two of the points.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates:&#xD;&#xA;&#xD;&#xA;    BaryA = ((By-Cy)(Px-Cx) + (Cx-Bx)(Py-Cy)) / ((By-Cy)(Ax-Cx) + (Cx-Bx)(Ay-Cy))&#xD;&#xA;    BaryB = ((Cy-Ay)(Px-Cx) + (Ax-Cx)(Py-Cy)) / ((By-Cy)(Ax-Cx) + (Cx-Bx)(Ay-Cy))&#xD;&#xA;    BaryC = 1 - BaryA - BaryB&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of `P` by interpolating using the barycentric coordinates as weights.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Puv = BaryA * Auv + BaryB * Buv + BaryC * Cuv&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3938" PostHistoryTypeId="5" PostId="1867" RevisionGUID="4080b0fa-96ab-45ab-878a-230e2521b7ed" CreationDate="2016-01-05T17:52:24.227" UserId="457" Comment="deleted 3 characters in body" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of `P`. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles `ABP`, `PBC` and `PCA`.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex `A` on the point `P` is proportional to the ratio of the triangle `PBC` to the whole triangle `ABC`.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as `P` approaches `A` the triangle `PBC` grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the 3 coordinates of a point **inside a triangle** always equals `1`. So it is enough to find two of the points.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;    BaryA = ((By-Cy)(Px-Cx) + (Cx-Bx)(Py-Cy)) / ((By-Cy)(Ax-Cx) + (Cx-Bx)(Ay-Cy))&#xD;&#xA;    BaryB = ((Cy-Ay)(Px-Cx) + (Ax-Cx)(Py-Cy)) / ((By-Cy)(Ax-Cx) + (Cx-Bx)(Ay-Cy))&#xD;&#xA;    BaryC = 1 - BaryA - BaryB&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of `P` by interpolating using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Puv = BaryA * Auv + BaryB * Buv + BaryC * Cuv&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3939" PostHistoryTypeId="5" PostId="1867" RevisionGUID="fcc855d0-67f4-460d-b3d5-770840a3d359" CreationDate="2016-01-05T18:40:04.530" UserId="127" Comment="Replaced code formatting with MathJax" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of $P$. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles $ABP$, $PBC$ and $PCA$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex $A$ on the point $P$ is proportional to the ratio of the triangle $PBC$ to the whole triangle $ABC$.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as $P$ approaches $A$ the triangle $PBC$ grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the 3 coordinates of a point **inside a triangle** always equals $1$. So it is enough to find two of the points.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;{Bary}_A &amp;= \frac{(B_y-C_y)(P_x-C_x) + (C_x-B_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_B &amp;= \frac{(C_y-A_y)(P_x-C_x) + (A_x-C_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_C &amp;= 1 - {Bary}_A - {Bary}_B&#xD;&#xA;\end{aligned}$$&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of $P$ by interpolating using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;$$P_{uv} = {Bary}_A \cdot A_{uv} + {Bary}_B \cdot B_{uv} + {Bary}_C \cdot C_{uv}$$&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3940" PostHistoryTypeId="5" PostId="1867" RevisionGUID="ef60b427-480d-442e-9fe7-ec00e00b6699" CreationDate="2016-01-05T18:40:07.897" UserId="457" Comment="deleted 85 characters in body" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of `P`. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles `ABP`, `PBC` and `PCA`.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex `A` on the point `P` is proportional to the ratio of the triangle `PBC` to the whole triangle `ABC`.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as `P` approaches `A` the triangle `PBC` grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the 3 coordinates of a point **inside a triangle** always equals `1`. So it is enough to find two of the points.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;    BaryA = ((By-Cy)(Px-Cx) + (Cx-Bx)(Py-Cy)) / ((By-Cy)(Ax-Cx) + (Cx-Bx)(Ay-Cy))&#xD;&#xA;    BaryB = ((Cy-Ay)(Px-Cx) + (Ax-Cx)(Py-Cy)) / ((By-Cy)(Ax-Cx) + (Cx-Bx)(Ay-Cy))&#xD;&#xA;    BaryC = 1 - BaryA - BaryB&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of `P` by interpolating the values at the vertices using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Puv = BaryA * Auv + BaryB * Buv + BaryC * Cuv&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3941" PostHistoryTypeId="5" PostId="1867" RevisionGUID="d2268169-2bd3-4b5d-9d91-0c074025edfc" CreationDate="2016-01-05T18:56:07.947" UserId="127" Comment="Replaced code formatting with MathJax" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of $P$. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles $ABP$, $PBC$ and $PCA$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex $A$ on the point $P$ is proportional to the ratio of the triangle $PBC$ to the whole triangle $ABC$.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as $P$ approaches $A$ the triangle $PBC$ grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the 3 coordinates of a point **inside a triangle** always equals $1$. So it is enough to find two of the points.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;{Bary}_A &amp;= \frac{(B_y-C_y)(P_x-C_x) + (C_x-B_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_B &amp;= \frac{(C_y-A_y)(P_x-C_x) + (A_x-C_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_C &amp;= 1 - {Bary}_A - {Bary}_B&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of $P$ by interpolating the values at the vertices using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;$$P_{uv} = {Bary}_A \cdot A_{uv} + {Bary}_B \cdot B_{uv} + {Bary}_C \cdot C_{uv}$$&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="3944" PostHistoryTypeId="5" PostId="1867" RevisionGUID="7f8e9a97-07d3-432a-bab4-1168a5c732dd" CreationDate="2016-01-06T07:52:35.400" UserId="457" Comment="added 187 characters in body" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of $P$. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles $ABP$, $PBC$ and $PCA$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex $A$ on the point $P$ is proportional to the ratio of the triangle $PBC$ to the whole triangle $ABC$.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as $P$ approaches $A$ the triangle $PBC$ grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the 3 coordinates of a point **inside a triangle** always equals $1$. So it is enough to find two of the points.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;{Bary}_A &amp;= \frac{(B_y-C_y)(P_x-C_x) + (C_x-B_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_B &amp;= \frac{(C_y-A_y)(P_x-C_x) + (A_x-C_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_C &amp;= 1 - {Bary}_A - {Bary}_B&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of $P$ by interpolating the values at the vertices using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;$$P_{uv} = {Bary}_A \cdot A_{uv} + {Bary}_B \cdot B_{uv} + {Bary}_C \cdot C_{uv}$$&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation.&#xD;&#xA;&#xD;&#xA;Also see [this question][4] for efficient methods of computation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf&#xD;&#xA;  [4]: http://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="3948" PostHistoryTypeId="2" PostId="1869" RevisionGUID="74dfb505-2e9b-4cb8-8b86-68a51558b2c8" CreationDate="2016-01-06T07:59:53.697" UserId="1683" Text="There are numerous upscaling and downscaling algorithms available to scale images from any resolution to any other arbitrary resolution. Each algorithm typically involves a trade-off between efficiency, smoothness and sharpness, with varying degrees of each trade-off for different algorithms.&#xD;&#xA;&#xD;&#xA;Check out [this Wikipedia article][1] for such algorithms and examples of such algorithms.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Image_scaling#Scaling_methods" ContentLicense="CC BY-SA 3.0" />
  <row Id="3949" PostHistoryTypeId="5" PostId="1869" RevisionGUID="88631dda-df40-49d9-98af-fa58d24d3e2d" CreationDate="2016-01-06T12:39:30.780" UserId="1683" Comment="added 1121 characters in body" Text="There are numerous upscaling and downscaling algorithms available to scale images from any resolution to any other arbitrary resolution. Each algorithm typically involves a trade-off between efficiency, smoothness and sharpness, with varying degrees of each trade-off for different algorithms.&#xD;&#xA;&#xD;&#xA;Check out [this Wikipedia article][1] for such algorithms and examples of such algorithms.&#xD;&#xA;&#xD;&#xA;The most popularly known (and used) algorithm is the [Bicubic interpolation][2] algorithm. It interpolates between 2D points on a rectangular grid. Using [Cubic Splines][3] (or Cubic Interpolation), It first interpolates on one dimension (finds the interpolated row/column), then interpolates the interpolated row/column in the other dimension.&#xD;&#xA;&#xD;&#xA;Bilinear interpolation is similar to Bicubic interpolation, except the former interpolates using a linear function and can interpolate only between two values and the latter uses a cubic function and can interpolate between four values.&#xD;&#xA;&#xD;&#xA;The simple function for Bicubic interpolation is as follows:&#xD;&#xA;&#xD;&#xA;f(f(p00, p01, p02, p03, y), f(p10, p11, p12, p13, y), f(p20, p21, p22, p23, y), f(p30, p31, p32, p33, y), x)&#xD;&#xA;&#xD;&#xA;where (x, y) is the interpolated position and p[][] is the 2d array representing the 4 * 4 grid.&#xD;&#xA;&#xD;&#xA;Check [this link][4] for more information and example code, which really helps a lot!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Image_scaling#Scaling_methods&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bicubic_interpolation&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline&#xD;&#xA;  [4]: http://www.paulinternet.nl/?page=bicubic" ContentLicense="CC BY-SA 3.0" />
  <row Id="3950" PostHistoryTypeId="5" PostId="1867" RevisionGUID="4e7926c8-8b4d-419f-a965-e6320a389e9f" CreationDate="2016-01-06T13:48:06.523" UserId="457" Comment="added 26 characters in body" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of $P$. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles $ABP$, $PBC$ and $PCA$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex $A$ on the point $P$ is proportional to the ratio of the area of inner triangle $PBC$ to the area of the whole triangle $ABC$.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as $P$ approaches $A$ the triangle $PBC$ grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the barycentric coordinates of a point **inside a triangle** always equals $1$. So, it is enough to find only two of the coordinates to derive the 3rd.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;{Bary}_A &amp;= \frac{(B_y-C_y)(P_x-C_x) + (C_x-B_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_B &amp;= \frac{(C_y-A_y)(P_x-C_x) + (A_x-C_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_C &amp;= 1 - {Bary}_A - {Bary}_B&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of $P$ by interpolating the values at the vertices using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;$$P_{uv} = {Bary}_A \cdot A_{uv} + {Bary}_B \cdot B_{uv} + {Bary}_C \cdot C_{uv}$$&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation.&#xD;&#xA;&#xD;&#xA;Also see [this question][4] for efficient methods of computation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf&#xD;&#xA;  [4]: http://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="3953" PostHistoryTypeId="2" PostId="1870" RevisionGUID="6808ec44-5dc7-40d0-ad78-2222e59ac6c9" CreationDate="2016-01-06T18:56:31.283" UserId="38" Text="In essence a image is  a group of point samples (read [A pixels are not small square&lt;sup&gt;3&lt;/sup&gt;](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf)). When you transform or scale the image you need to resample it. So what you do, theoretically, is essentially you take the point samples and convert them into a continuous function. Then you sample that continuous function and reconstruct a signal. Now there are two or three different phases here.&#xD;&#xA;&#xD;&#xA;1. Converting the samples to a continuous, (function reconstruction).&#xD;&#xA;2. (Transforming)&#xD;&#xA;3. Re-sampling the signal&#xD;&#xA;&#xD;&#xA;Note that neither of these steps have a fixed form or in practice when optimized its impossible to tell that there are steps. The transformation does not really have to be simple it could be mapping the shape into a spiral etc. &#xD;&#xA;&#xD;&#xA;[![recostruction of signal][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A 1-D signal reconstructed by different filters.&#xD;&#xA;&#xD;&#xA;In practice quite a bit of lore is known about signal reconstruction in the signal processing field. Designing these filters and choosing the right one is a art form on its own. But in essence choice of filter is a tradeof between blurring and ringing, of course the algorithm also has other qualities such as how many instructions it takes to implement and how fast and how much memory it needs etc. Which can be of essence in realtime or embedded applications.&#xD;&#xA;&#xD;&#xA;[![The process][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Overview of entire process.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WWaeC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XNqUx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3954" PostHistoryTypeId="2" PostId="1871" RevisionGUID="56030a95-350a-4de4-bdd3-d199a46fa5ef" CreationDate="2016-01-06T20:48:37.160" UserId="141" Text="The most common way I saw is to have photons of several different wavelengths. One then renders with each wavelength and blends the results into the final image.&#xD;&#xA;&#xD;&#xA;&quot;Existing work&quot;: [Psychopath Renderer](http://psychopath.io/spectral-rendering/) and [The Secret Life of Photons](http://benedikt-bitterli.me/tantalum/).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3955" PostHistoryTypeId="2" PostId="1872" RevisionGUID="a82b1386-1772-4c1e-a7ea-451f60d60451" CreationDate="2016-01-06T21:44:45.993" UserId="141" Text="And just to add: it is called &quot;conflation&quot; artifact and this is what AntiGrain Geometry used the [compound shapes](http://agg.sourceforge.net/antigrain.com/news/release_notes/v24.agdoc.html#toc0007) rasterizer for, see:&#xD;&#xA;&#xD;&#xA; ![flash_rasterizer.png](http://agg.sourceforge.net/antigrain.com/demo/flash_rasterizer.png)&#xD;&#xA;&#xD;&#xA;Also, this is what NV Path Rendering claims to improve on:&#xD;&#xA;&#xD;&#xA;[An Introduction to&#xD;&#xA;NV_path_rendering](http://developer.download.nvidia.com/assets/gamedev/files/An_Introduction_to_NV_path_rendering.pdf) (p. 67) or [NV_path_rendering FAQ](http://developer.download.nvidia.com/assets/gamedev/files/NV_path_rendering_FAQ.pdf) (#29)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3956" PostHistoryTypeId="2" PostId="1873" RevisionGUID="17367d17-9b35-4edb-927f-74525c2f61db" CreationDate="2016-01-07T07:42:51.627" UserId="120" Text="I am taking a Computer Graphics course this quarter.&#xD;&#xA;One of our lab project is about software rasterization.&#xD;&#xA;&#xD;&#xA;Now I am planing the project proposal and&#xD;&#xA;thinking about how to make it useful for other people in contemporary game development.&#xD;&#xA;&#xD;&#xA;After some brief search,&#xD;&#xA;I learned a technique called Software Occlusion Culling.&#xD;&#xA;It does software rasterization on buffers of various resolutions.&#xD;&#xA;And we can query for occlusion using the hierarchical z buffers.&#xD;&#xA;&#xD;&#xA;**My question**: What are the usages of software rasterization&#xD;&#xA;in *modern* game engines besides the Software Occlusion Culling?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3957" PostHistoryTypeId="1" PostId="1873" RevisionGUID="17367d17-9b35-4edb-927f-74525c2f61db" CreationDate="2016-01-07T07:42:51.627" UserId="120" Text="What are the usages of software rasterization in modern game engines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3958" PostHistoryTypeId="3" PostId="1873" RevisionGUID="17367d17-9b35-4edb-927f-74525c2f61db" CreationDate="2016-01-07T07:42:51.627" UserId="120" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3959" PostHistoryTypeId="2" PostId="1874" RevisionGUID="0dc6e088-8a64-42e0-95cd-5c36acbf62e5" CreationDate="2016-01-07T12:26:55.137" UserId="2417" Text="Rasterization is a huge topic with many parts and I'm no engine programmer, but I'll do my best to give some sort of overview (this will be far from a complete list!). &#xD;&#xA;&#xD;&#xA;Some very basic, lowlevel stuff include:&#xD;&#xA;&#xD;&#xA;* **Frustrum culling:** throws away everything outside the camera's frustrum (think of it as the viewing area of the camera).&#xD;&#xA;* **Backface culling:** throw away every polygon not directing to the camera.&#xD;&#xA;* **Painter's algorithm:** draw objects in order of their distance to the camera, start with objects far away, then go toward to the camera.&#xD;&#xA;&#xD;&#xA;More advaned stuff used in games include things like:&#xD;&#xA;&#xD;&#xA;* **Tesselation**: actually pretty much like LOD (see below), but now the latest DirectX Versions introduced tesselation, which provides automatic mesh division or reduction. This gives huge boost in graphics performance, because you can get polys if you need them and get rid of them if you don't want them any more. &#xD;&#xA;* **LOD**: A level-of-detail system replaces the mesh of an object based on the distance between object and camera. for example, your character has three meshes: one with 10,000, one whith 5,000 and another with 1,000 polys. if you stay right in front of him, the high resolution mesh (10,000 polys) is shown, if you move away, after 100m the character is replaced by the medium mesh and after another 100m it is replaced by the low resolution mesh. Instead of replacing the mesh you can reduce it, but this would be more complex to code. &#xD;&#xA;* **binary space partitions**: the space is divided into two volumes. this will be repeated until you reach your goal, e.g. until the space does contain only polys that should be drawn on screen&#xD;&#xA;* **Portals and cells**: (aka Portal culling) is used in indoor scenes and/or first person shooters. The scene is divided into cells (e.g. rooms of a building) that are connected throw portals (e.g. doors). you can set portals to be open and closed.&#xD;&#xA;&#xD;&#xA;Assuming you have a basic understanding of the graphics pipeline, I tried to focus on rasterization. you may also take a look at lighting and shading or other stuff..&#xD;&#xA;&#xD;&#xA;These include just a few possible technologies to include into your project. since i have not enough reputation on stackexchange, I cannot provide many links, but you'll find all that stuff in google :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3960" PostHistoryTypeId="2" PostId="1875" RevisionGUID="26c58fac-8652-4efe-9984-e0aff4e93ca7" CreationDate="2016-01-07T13:09:28.180" UserId="385" Text="To my knowledge, [Software Occlusion Culling][1] (which you already mentioned), is pretty much the only thing a software rasterizer would still be used for. [Procworld][2] makes use of a similar technique to display its huge voxel environments.&#xD;&#xA;&#xD;&#xA;Most other culling methods like frustum culling do work on the CPU, but, to stick with the example, the test against the frustum happens on object level, probably with an axis-aligned bounding box (AABB). This intersection test is way simpler than using a full-blown software rasterizer.&#xD;&#xA;&#xD;&#xA;In certain cases, software rasterization could be used for mouse picking of objects. In game engines, this is often solved using a physics engine and ray-triangle collision with a simplified mesh.&#xD;&#xA;&#xD;&#xA;With the CPU being idle while waiting for the GPU in modern interactive 3D applications, one could think that it might be beneficial to use these idle cycles to render on the CPU using a software rasterizer. The problem here, besides the rendering getting horribly complex and convoluted, will often be the bandwidth. Images rendered on the CPU need to be transferred to the GPU before getting displayed, which might cancel out the benefit.&#xD;&#xA;&#xD;&#xA;  [1]: https://software.intel.com/en-us/articles/software-occlusion-culling&#xD;&#xA;  [2]: http://procworld.blogspot.fr/2015/08/voxel-occlusion.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="3961" PostHistoryTypeId="2" PostId="1876" RevisionGUID="95c907ac-cec2-4c1f-b7eb-72d5c60045ef" CreationDate="2016-01-07T13:49:57.700" UserId="56" Text="Games with the concept of &quot;fog of war&quot; often have a visibility grid to define the state of the fog of war at each location.  Rasterization is sometimes used to modify the fog of war state for specific shapes on the grid.&#xA;&#xA;For instance, using an ability that reveals a circle of the map with a specific radius, or perhaps something that reveals a square.&#xA;&#xA;Not strictly graphics related, but definitely a use of rasterization in modern games, and a technique ive seen used in RTSs." ContentLicense="CC BY-SA 3.0" />
  <row Id="3966" PostHistoryTypeId="2" PostId="1878" RevisionGUID="99c46b57-36d7-43c5-8420-e9b6f23f2055" CreationDate="2016-01-08T14:03:31.510" UserId="2425" Text="i have wirtten a fragment shader that works just fine with a single light. Now I am trying to adpat it to work with 8 lights, the implement it in Processing. Clearly I am doing something wrong in the math and I cannot see what it is... I have read other posts about this and try to adapt the answer to my problem, no luck though...&#xD;&#xA;&#xD;&#xA;////Fragment/////&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelview;&#xD;&#xA;    uniform mat4 normalMatrix;&#xD;&#xA;    &#xD;&#xA;    uniform int lightCount;&#xD;&#xA;    uniform vec4 lightPosition[8];&#xD;&#xA;    &#xD;&#xA;    attribute vec4 vertex;&#xD;&#xA;    attribute vec3 normal;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main() {  &#xD;&#xA;    	&#xD;&#xA;    	vec3 vertexCamera = vec3(modelview * vertex);&#xD;&#xA;        vec3 transformedNormal = normalize(normalMatrix * normal);&#xD;&#xA;     &#xD;&#xA;    float intensity = 0.0;&#xD;&#xA;     &#xD;&#xA;     for(int i = 0 ; i&lt;lightCount;i++){&#xD;&#xA;    	&#xD;&#xA;    	vec3 direction = normalize(lightPosition[i].xyz - vertexCamera);&#xD;&#xA;    	intensity += max(0.0, dot(direction, transformedNormal));&#xD;&#xA;    	&#xD;&#xA;    	}&#xD;&#xA;     &#xD;&#xA;     gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;////vertex/////&#xD;&#xA;&#xD;&#xA;        #define PROCESSING_LIGHT_SHADER&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        uniform mat4 transform;&#xD;&#xA;        uniform mat3 normalMatrix;&#xD;&#xA;        &#xD;&#xA;        attribute vec4 vertex;&#xD;&#xA;        attribute vec4 color;&#xD;&#xA;        &#xD;&#xA;        varying vec4 vertColor;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        void main() {&#xD;&#xA;          gl_Position = transform * vertex;    &#xD;&#xA;            &#xD;&#xA;          vertColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3967" PostHistoryTypeId="1" PostId="1878" RevisionGUID="99c46b57-36d7-43c5-8420-e9b6f23f2055" CreationDate="2016-01-08T14:03:31.510" UserId="2425" Text="Multiple light pixel Shader in GLSL" ContentLicense="CC BY-SA 3.0" />
  <row Id="3968" PostHistoryTypeId="3" PostId="1878" RevisionGUID="99c46b57-36d7-43c5-8420-e9b6f23f2055" CreationDate="2016-01-08T14:03:31.510" UserId="2425" Text="|opengl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3970" PostHistoryTypeId="5" PostId="1878" RevisionGUID="b4df8453-7b73-4011-a7c6-e927057075bc" CreationDate="2016-01-08T14:46:37.310" UserId="2425" Comment="added 88 characters in body" Text="&#xD;&#xA;&#xD;&#xA;I have wirtten a fragment shader that works just fine with a single light. Now I am trying to adpat it to work with 8 lights, the implement it in Processing. Clearly I am doing something wrong in the math and I cannot see what it is... I have read other posts about this and try to adapt the answer to my problem, no luck though...&#xD;&#xA;&#xD;&#xA;[![Working with 1 light setup][1]][1]&#xD;&#xA;&#xD;&#xA;////Fragment/////&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelview;&#xD;&#xA;    uniform mat4 normalMatrix;&#xD;&#xA;    &#xD;&#xA;    uniform int lightCount;&#xD;&#xA;    uniform vec4 lightPosition[8];&#xD;&#xA;    &#xD;&#xA;    attribute vec4 vertex;&#xD;&#xA;    attribute vec3 normal;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main() {  &#xD;&#xA;    	&#xD;&#xA;    	vec3 vertexCamera = vec3(modelview * vertex);&#xD;&#xA;        vec3 transformedNormal = normalize(normalMatrix * normal);&#xD;&#xA;     &#xD;&#xA;    float intensity = 0.0;&#xD;&#xA;     &#xD;&#xA;     for(int i = 0 ; i&lt;lightCount;i++){&#xD;&#xA;    	&#xD;&#xA;    	vec3 direction = normalize(lightPosition[i].xyz - vertexCamera);&#xD;&#xA;    	intensity += max(0.0, dot(direction, transformedNormal));&#xD;&#xA;    	&#xD;&#xA;    	}&#xD;&#xA;     &#xD;&#xA;     gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;////vertex/////&#xD;&#xA;&#xD;&#xA;        #define PROCESSING_LIGHT_SHADER&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        uniform mat4 transform;&#xD;&#xA;        uniform mat3 normalMatrix;&#xD;&#xA;        &#xD;&#xA;        attribute vec4 vertex;&#xD;&#xA;        attribute vec4 color;&#xD;&#xA;        &#xD;&#xA;        varying vec4 vertColor;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        void main() {&#xD;&#xA;          gl_Position = transform * vertex;    &#xD;&#xA;            &#xD;&#xA;          vertColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/s5ems.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3971" PostHistoryTypeId="2" PostId="1879" RevisionGUID="fbbd1636-4854-4141-ba7e-11c4a992b20c" CreationDate="2016-01-08T15:22:36.260" UserId="137" Text="From the error message the problem is in line 24 of your fragment shader:&#xD;&#xA;&#xD;&#xA;    vec3 transformedNormal = normalize(normalMatrix * normal);&#xD;&#xA;&#xD;&#xA;`normalMatrix` is a `mat4` but `normal` is a `vec3`. &#xD;&#xA;&#xD;&#xA;The solution is to make normalMatrix a mat3 instead." ContentLicense="CC BY-SA 3.0" />
  <row Id="3972" PostHistoryTypeId="5" PostId="1878" RevisionGUID="77a82062-1f83-4cf7-8aa2-040ffa8aa32a" CreationDate="2016-01-08T15:35:27.393" UserId="2425" Comment="POsted original working code for a single light" Text="I have wirtten a fragment shader that works just fine with a single light. Now I am trying to adpat it to work with 8 lights, the implement it in Processing. Clearly I am doing something wrong in the math and I cannot see what it is... I have read other posts about this and try to adapt the answer to my problem, no luck though...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    ////Fragment/////&#xD;&#xA;    &#xD;&#xA;        #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    varying vec3 ecNormal;&#xD;&#xA;    varying vec3 lightDir;&#xD;&#xA;    &#xD;&#xA;    void main() {  &#xD;&#xA;      vec3 direction = normalize(lightDir);&#xD;&#xA;      vec3 normal = normalize(ecNormal);&#xD;&#xA;      float intensity = max(0.0, dot(direction, normal));&#xD;&#xA;      gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    ////vertex/////&#xD;&#xA;    &#xD;&#xA;            #define PROCESSING_LIGHT_SHADER&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelview;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 lightPosition;&#xD;&#xA;    uniform vec3 lightNormal;&#xD;&#xA;    &#xD;&#xA;    attribute vec4 vertex;&#xD;&#xA;    attribute vec4 color;&#xD;&#xA;    attribute vec3 normal;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    varying vec3 ecNormal;&#xD;&#xA;    varying vec3 lightDir;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = transform * vertex;    &#xD;&#xA;      vec3 ecVertex = vec3(modelview * vertex);  &#xD;&#xA;    &#xD;&#xA;      ecNormal = normalize(normalMatrix * normal);&#xD;&#xA;      lightDir = normalize(lightPosition.xyz - ecVertex);  &#xD;&#xA;      vertColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9u1P9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3973" PostHistoryTypeId="2" PostId="1880" RevisionGUID="f68f7330-7bbd-4188-bf8c-103270f3f8bb" CreationDate="2016-01-08T19:44:45.150" UserId="2427" Text="TWO PART QUESTION - We've all seen the movies/TV shows where the police/feds/spies use computer software to take a grainy photo and do a &quot;clean-up&quot; to see a better picture and more details. I assume the concept is executed by some sort of **uber-power** pixel-smoothing or anti-aliasing type of algorithms to fill in the blanks based on deductive processing.&#xD;&#xA;&#xD;&#xA;PART 1: How *real* is this technology in the public/commercial software world? I'm not asking about any *speculation* on alleged secret gov software or such, I just want to know where we actually are with this concept today? How much is fully automated vs human-assisted. &#xD;&#xA;&#xD;&#xA;PART 2: Assuming there actually is *some* reality with this technology for photographs the second part of this question is how (if at all) has this been applied to videos? Again the issue of fully automated vs human assisted is of interest here.&#xD;&#xA;&#xD;&#xA;At the heart of this post is the ultimate question of how viable is today's software for being able to take an old VHS or DVD recording and process the frames to create a new HD-resolution remaster. Considering that doing this would mean cleaning up tens-of-thousands of frames for even a simple wedding video I am **not** expecting this technology to be fast of course." ContentLicense="CC BY-SA 3.0" />
  <row Id="3974" PostHistoryTypeId="1" PostId="1880" RevisionGUID="f68f7330-7bbd-4188-bf8c-103270f3f8bb" CreationDate="2016-01-08T19:44:45.150" UserId="2427" Text="What is the state-of-the-art on using computers to &quot;clean-up&quot; images?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3975" PostHistoryTypeId="3" PostId="1880" RevisionGUID="f68f7330-7bbd-4188-bf8c-103270f3f8bb" CreationDate="2016-01-08T19:44:45.150" UserId="2427" Text="|image-processing|photo-realistic|video|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3976" PostHistoryTypeId="2" PostId="1881" RevisionGUID="7f9a5b75-739a-46d5-86c4-d619bd9dd96d" CreationDate="2016-01-08T22:50:50.167" UserId="48" Text="The closest thing I know of to the &quot;_computer: enhance!_&quot; trope in real life is the family of [Single Image Super-Resolution](http://www.wisdom.weizmann.ac.il/~vision/SingleImageSR.html) techniques. That page shows a number of examples of the results on various images. You can see that while it improves the visual quality of the enlarged images, it's a long way from what you see on TV where they can read the text on a letter that's reflected in a wine glass, or recognize the face of someone standing in the shadows, etc.&#xD;&#xA;&#xD;&#xA;The technique basically works by observing that a single image often contains recurring instances of the same patterns or structures. When you have multiple copies of the same pattern, they often occur at different sub-pixel offsets, i.e. aligned differently to the pixel grid, which means that each copy contains slightly different information about the underlying pattern, and by putting them together you can recover (really, guess at) a higher-resolution version of that pattern. This can then be used to &quot;fill in the missing detail&quot; wherever that pattern occurs. This is a very handwavy explanation, but you can see the paper (linked from the above site) for more details. Most of it is automated, but I'd guess it still requires a fair amount of human parameter-tuning to get good results.&#xD;&#xA;&#xD;&#xA;The paper is from 2009, and it looks like there have been a few follow-ups since then, but only incremental improvements.&#xD;&#xA;&#xD;&#xA;Also note that if you have a specific use case such as reading vehicle license plates, I'd guess it's possible to use machine-learning techniques to get much better results than you can in general. In that case, you have a concrete, known set of possible shapes (the characters that can appear on a license plate, in the particular font used for license plates), and rather than &quot;enhancing&quot; an image of literally anything, you're just trying to find the set of characters that best matches the image you're looking at. That's not my area of expertise, though." ContentLicense="CC BY-SA 3.0" />
  <row Id="3978" PostHistoryTypeId="2" PostId="1882" RevisionGUID="e3a42eae-a520-4c40-a72d-dabbb35f8d4f" CreationDate="2016-01-09T12:40:33.980" UserId="2173" Text="This is a good solution. &#xD;&#xA;&#xD;&#xA;I just had a problem transforming `AxisVector` in screen coordinates, it turns out I must project two points from this vector on the screen, as explained in [this answer](http://computergraphics.stackexchange.com/a/1772/2173)." ContentLicense="CC BY-SA 3.0" />
  <row Id="3979" PostHistoryTypeId="2" PostId="1883" RevisionGUID="c7c42940-6438-4bf3-8deb-d91829f4df4d" CreationDate="2016-01-09T12:41:12.300" UserId="2433" Text="I would not recommend to correlate the extrusion direction with its screen projection because of the asymptotic behaviour in case the axis points toward the screen or the resulting extrusion crosses the focal point of the camera.&#xD;&#xA;&#xD;&#xA;One consistent way of doing it would be computing the extrusion height independently of the axis direction:&#xD;&#xA;&#xD;&#xA;1. Find a virtual construction plane of your operation which is parallel to the screen. For example, in the real world, this plane would be a plane of your computer monitor screen reachable by hand as you sit at your computer.&#xD;&#xA;&#xD;&#xA;Usually, you have some kind of central point which serves as a center of screen camera rotation as you navigate your viewport. You can draw your construction plane through this point.&#xD;&#xA;&#xD;&#xA;Another way is drawing your construction plane through the intersection of the mouse cursor and your object as you start your extrusion operation.&#xD;&#xA;&#xD;&#xA;Either way, the construction plane must be parallel to the screen and in front of your camera view for this method to work.&#xD;&#xA;&#xD;&#xA;If you are using an orthogonal projection (camera without a Field of View) then you can draw the construction plane through any point.&#xD;&#xA;&#xD;&#xA;2. Compute the length of the projection of mouse motion on the construction plane your figured out in point (1). This is your desired extrusion height.&#xD;&#xA;&#xD;&#xA;3. Provide a means of moving the construction plane back and forth along the view axis, if the current viewport has FOV. You don't need to display and the move the construction plane if your viewport uses orthogonal projection.&#xD;&#xA;&#xD;&#xA;Using this method your extrusion operation height would be visually consistent with what user expects with mouse motion, and the user would not experience any asymptotic and singularity issues as with the axis projection method." ContentLicense="CC BY-SA 3.0" />
  <row Id="3980" PostHistoryTypeId="2" PostId="1884" RevisionGUID="443e0c6f-4598-4152-9afd-a6286541be45" CreationDate="2016-01-09T16:08:47.323" UserId="2096" Text="Why do I need to specify the same name for color input in fragment shader same as output color from vertex shader.&#xA;&#xA;    //Vertex shader&#xA;    out vec3 vertex_color;&#xA;    &#xA;    void main()&#xA;{&#xA;    vertex_color=vec3(1.0,0.0,0.0);&#xA;}&#xA;&#xA;&#xA;    //Fragment shader &#xA;    &#xA;     in vec3 vertex_color;&#xA;     out vec4 frag_color;&#xA;     void main()&#xA;{&#xA;    frag_color=vec4(vertex_color,1.0);&#xA;}&#xA;&#xA;Since we are already giving the color value from vertex shader to fragment shader...why do we need same names!!!?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3981" PostHistoryTypeId="1" PostId="1884" RevisionGUID="443e0c6f-4598-4152-9afd-a6286541be45" CreationDate="2016-01-09T16:08:47.323" UserId="2096" Text="OpenGL vertex color" ContentLicense="CC BY-SA 3.0" />
  <row Id="3982" PostHistoryTypeId="3" PostId="1884" RevisionGUID="443e0c6f-4598-4152-9afd-a6286541be45" CreationDate="2016-01-09T16:08:47.323" UserId="2096" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3983" PostHistoryTypeId="5" PostId="1880" RevisionGUID="9883fc29-a70c-4275-ad0e-eb636cc46445" CreationDate="2016-01-09T16:11:12.893" UserId="2427" Comment="added NOTE on crosspost" Text="TWO PART QUESTION - We've all seen the movies/TV shows where the police/feds/spies use computer software to take a grainy photo and do a &quot;clean-up&quot; to see a better picture and more details. I assume the concept is executed by some sort of **uber-power** pixel-smoothing or anti-aliasing type of algorithms to fill in the blanks based on deductive processing.&#xD;&#xA;&#xD;&#xA;PART 1: How *real* is this technology in the public/commercial software world? I'm not asking about any *speculation* on alleged secret gov software or such, I just want to know where we actually are with this concept today? How much is fully automated vs human-assisted. &#xD;&#xA;&#xD;&#xA;PART 2: Assuming there actually is *some* reality with this technology for photographs the second part of this question is how (if at all) has this been applied to videos? Again the issue of fully automated vs human assisted is of interest here.&#xD;&#xA;&#xD;&#xA;At the heart of this post is the ultimate question of how viable is today's software for being able to take an old VHS or DVD recording and process the frames to create a new HD-resolution remaster. Considering that doing this would mean cleaning up tens-of-thousands of frames for even a simple wedding video I am **not** expecting this technology to be fast of course.&#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;NOTE: Per in-topic and meta discussions I went ahead and cross-posted this in two other suggested SE forums to acquire their viewpoints and expertise on this matter. So far (it is still a little &quot;early in the day&quot; so to speak) I have received some pretty interesting information in 2 of the 3.&#xD;&#xA;&#xD;&#xA;When this is all done (when good answers have been selected) I would appreciate a way to merge these **for the benefit of all three SE communities**:&#xD;&#xA;&#xD;&#xA; - Computer Graphics: http://computergraphics.stackexchange.com/questions/1880&#xD;&#xA; - Signal Processing: http://dsp.stackexchange.com/questions/28168&#xD;&#xA; - Video Production: http://video.stackexchange.com/questions/17363" ContentLicense="CC BY-SA 3.0" />
  <row Id="3984" PostHistoryTypeId="5" PostId="1884" RevisionGUID="0923cdaa-682d-40d3-af03-7f2095370996" CreationDate="2016-01-09T17:22:14.240" UserId="127" Comment="Edited formatting" Text="Why do I need to specify the same name for color input in fragment shader and output color from vertex shader?&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;    out vec3 vertex_color;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vertex_color=vec3(1.0,0.0,0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;!-- --&gt;&#xD;&#xA;&#xD;&#xA;    //Fragment shader &#xD;&#xA;    in vec3 vertex_color;&#xD;&#xA;    out vec4 frag_color;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        frag_color=vec4(vertex_color,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since we already hand the color value from vertex shader to fragment shader, why do we need same names?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3985" PostHistoryTypeId="2" PostId="1885" RevisionGUID="c8aa7dca-6be0-464c-96e8-4ecc283943dc" CreationDate="2016-01-09T20:12:41.833" UserId="48" Text="Using the same name is exactly how you tell OpenGL that you want the value passed through from vertex to fragment.&#xD;&#xA;&#xD;&#xA;You say &quot;we already hand the color value from vertex shader to fragment shader&quot;, but that's not correct. Usually, the only value that's passed between shaders _automatically_ is position, and that's only because it feeds into the GPU's rasterization hardware to draw the triangle on the screen.&#xD;&#xA;&#xD;&#xA;Any other values such as color, normal, texture coordinates, etc. that you want passed between shader stages have to be explicitly hooked up by the shader author. And the way you do that in GLSL is to create an `out` variable in one stage, and an `in` variable in the next stage, with the same name." ContentLicense="CC BY-SA 3.0" />
  <row Id="3986" PostHistoryTypeId="2" PostId="1886" RevisionGUID="2e57edef-8cdb-408e-8af3-cd6b86ae565c" CreationDate="2016-01-09T23:16:32.433" UserId="137" Text="Because you may want to pass more than one attribute through to the fragment shader. 2 which are essential are normal vector and the texture coordinates once you start doing lighting and textured meshes.&#xD;&#xA;&#xD;&#xA;You can in newer openGL versions give a numbered location to the attributes you pass through using `layout(location=1)`. Then the names don't have to match.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="3987" PostHistoryTypeId="5" PostId="1876" RevisionGUID="b203d431-fca8-4316-a9d2-bf1542bca88e" CreationDate="2016-01-10T01:38:35.283" UserId="56" Comment="added 80 characters in body" Text="Games with the concept of &quot;fog of war&quot; often have a visibility grid to define the state of the fog of war at each location.  Rasterization is sometimes used to modify the fog of war state for specific shapes on the grid.&#xA;&#xA;For instance, using an ability that reveals a circle of the map with a specific radius, or perhaps something that reveals a square.&#xA;&#xA;Not strictly graphics related, but definitely a use of rasterization in modern games, and a technique ive seen used in RTSs.&#xA;&#xA;Other grid based data in games could use rasterization for similar situations." ContentLicense="CC BY-SA 3.0" />
  <row Id="3988" PostHistoryTypeId="2" PostId="1887" RevisionGUID="10654aee-ad4f-450a-bf0c-5fd970131453" CreationDate="2016-01-10T04:54:51.350" UserId="2437" Text="Since long ago I wanted to implement a 2D lightning algorithm based on an idea I saw on Youtube: https://www.youtube.com/watch?v=74uXA7SmDqE The video is realtime, but it runs on the CPU and the resolution is pretty low. Im curious if anyone has an idea how to do this on the GPU.&#xD;&#xA;&#xD;&#xA;The algorithm works the following way:    &#xD;&#xA;- We have light data maps, these hold the color of the material (e.g. a red glass has 0xFF0000) and how transparent that pixel is.    &#xD;&#xA;- Work out the light values of each pixel in growing circles from a light source. In other words first calculate values right next to the light (8 pixels), then the neighbours of these pixels and so on. The color of a pixel is its value from the lightning data map, its alpha equals: (alpha of the pixel next to it closest to the light source - own alpha). So its some kind of ray casting algorithm that calculates value for each pixel.&#xD;&#xA;&#xD;&#xA;So the CPU implementation is pretty trivial, my problem is that I want to use this in a mobile game...just I dont know how this would work as a shader.&#xD;&#xA;Anyone has got ideas how to implement this on the GPU (that would run on mobile, so with OpenGL ES 2.0/3.0, maybe with Metal - so no stuff like CUDA or OpenCL)?&#xD;&#xA;&#xD;&#xA;Note: I am not looking for full implementations, just ideas/shader pseudocode how this would be possible." ContentLicense="CC BY-SA 3.0" />
  <row Id="3989" PostHistoryTypeId="1" PostId="1887" RevisionGUID="10654aee-ad4f-450a-bf0c-5fd970131453" CreationDate="2016-01-10T04:54:51.350" UserId="2437" Text="How to implement a realtime 2D light renderer with fog/colored light on the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="3990" PostHistoryTypeId="3" PostId="1887" RevisionGUID="10654aee-ad4f-450a-bf0c-5fd970131453" CreationDate="2016-01-10T04:54:51.350" UserId="2437" Text="|opengl|raytracing|algorithm|shader|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3991" PostHistoryTypeId="5" PostId="1887" RevisionGUID="305b1511-0f3e-4a8f-89c2-2613210b3c9a" CreationDate="2016-01-10T10:14:02.010" UserId="127" Comment="Edited formatting, spelling, tags" Text="Since long ago I wanted to implement a 2D lightning algorithm based on an [idea I saw on YouTube](https://www.youtube.com/watch?v=74uXA7SmDqE). The video is realtime, but it runs on the CPU and the resolution is pretty low. I'm curious if anyone has an idea how to do this on the GPU.&#xD;&#xA;&#xD;&#xA;The algorithm works the following way:&#xD;&#xA;&#xD;&#xA;- We have light data maps, these hold the color of the material (e.g. a red glass has 0xFF0000) and how transparent that pixel is.    &#xD;&#xA;- Work out the light values of each pixel in growing circles from a light source. In other words, first calculate values right next to the light (8 pixels), then the neighbours of these pixels and so on. The color of a pixel is its value from the lightning data map, its alpha equals: (alpha of the pixel next to it closest to the light source - own alpha). So it is some kind of ray casting algorithm that calculates value for each pixel.&#xD;&#xA;&#xD;&#xA;So the CPU implementation is pretty trivial. My problem is that I want to use this in a mobile game, but I don't know how this would work as a shader.&#xD;&#xA;How can this be implemented on the GPU (that would run on mobile, so with OpenGL ES 2.0/3.0, maybe with Metal - but without CUDA or OpenCL)?&#xD;&#xA;&#xD;&#xA;Note: I am not looking for full implementations, just ideas/shader pseudocode how this would be possible." ContentLicense="CC BY-SA 3.0" />
  <row Id="3992" PostHistoryTypeId="6" PostId="1887" RevisionGUID="305b1511-0f3e-4a8f-89c2-2613210b3c9a" CreationDate="2016-01-10T10:14:02.010" UserId="127" Comment="Edited formatting, spelling, tags" Text="|raytracing|algorithm|shader|real-time|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3993" PostHistoryTypeId="2" PostId="1888" RevisionGUID="58e0241f-c791-4ebd-af2d-476537d18ff7" CreationDate="2016-01-10T12:25:09.853" UserId="2440" Text="I'm trying to figure out how to properly implement flat shading for a mesh containing non-planar polygons (using OpenGL/GLSL). The aim is to obtain something similar to the result *Blender* gives (all quads below are non-planar):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In case of a triangle mesh, I'm aware of the following approaches to implement flat shading —&#xD;&#xA;&#xD;&#xA; 1. Compute the cross product of `dFdx` and `dFdy` in the fragment shader&#xD;&#xA; 2. Use the geometry shader to compute the triangle normal by taking the cross product of two sides of the triangle&#xD;&#xA; 3. When using `glDrawElements`, use the `flat` interpolation qualifier (which basically uses the normal associated with the provoking vertex for all fragments)&#xD;&#xA; 4. When using `glDrawArrays`, most vertices (usually all of them) are copied to the GPU multiple times. Therefore, a different normal can be used each time&#xD;&#xA;&#xD;&#xA;For a mesh containing non-planar polygons the first three options don't yield the result I'm after. In my implementation (using the Qt framework) I use `GL_TRIANGLE_FAN`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The fourth option could work, but isn't very elegant — I'd like to use either `glDrawElements` or `glDrawMultiElements`. One other option would be to use `glDrawElements` while looping over the faces one by one (instead of invoking it once using `glPrimitiveRestartIndex`). In that case, one could upload a `uniform` normal for each face. However, this does not seem very efficient. Any other ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2Whne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4ujWL.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3994" PostHistoryTypeId="1" PostId="1888" RevisionGUID="58e0241f-c791-4ebd-af2d-476537d18ff7" CreationDate="2016-01-10T12:25:09.853" UserId="2440" Text="Flat shading for non-planar polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="3995" PostHistoryTypeId="3" PostId="1888" RevisionGUID="58e0241f-c791-4ebd-af2d-476537d18ff7" CreationDate="2016-01-10T12:25:09.853" UserId="2440" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="3996" PostHistoryTypeId="2" PostId="1889" RevisionGUID="ac15f92b-8161-4c06-bbe5-35ab1e325d89" CreationDate="2016-01-10T17:37:36.223" UserId="38" Text="If your wall geometry is vector graphics you can simply extrude the segment away from the light position. This means 2 triangles per draw call, all the extrusion offsets can  can be handled in the vertex shader.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: For each wall generate a shadow volume extrusion.&#xD;&#xA;&#xD;&#xA;Quick and extremely dirty sample implementation here:&#xD;&#xA;&#xD;&#xA;* http://webglplayground.net/saved/AeN6yoNGih (please do not save your own version, fork instead)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/u80e2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3997" PostHistoryTypeId="5" PostId="1888" RevisionGUID="748c79d0-867c-4440-b0a0-e18e608a25dc" CreationDate="2016-01-10T17:57:38.047" UserId="2440" Comment="added 216 characters in body" Text="I'm trying to figure out how to properly implement flat shading for a mesh containing non-planar polygons (using OpenGL/GLSL). The aim is to obtain something similar to the result *Blender* gives (all quads below are non-planar):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To provide a bit of context — the non-planar polygons (e.g. quads, pentagons, ...) are either present in the mesh I load or appear as a result of applying a subdivision scheme (such as Catmull-Clark) to the mesh.&#xD;&#xA;&#xD;&#xA;In case of a triangle mesh, I'm aware of the following approaches to implement flat shading —&#xD;&#xA;&#xD;&#xA; 1. Compute the cross product of `dFdx` and `dFdy` in the fragment shader&#xD;&#xA; 2. Use the geometry shader to compute the triangle normal by taking the cross product of two sides of the triangle&#xD;&#xA; 3. When using `glDrawElements`, use the `flat` interpolation qualifier (which basically uses the normal associated with the provoking vertex for all fragments)&#xD;&#xA; 4. When using `glDrawArrays`, most vertices (usually all of them) are copied to the GPU multiple times. Therefore, a different normal can be used each time&#xD;&#xA;&#xD;&#xA;For a mesh containing non-planar polygons the first three options don't yield the result I'm after. In my implementation (using the Qt framework) I use `GL_TRIANGLE_FAN`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The fourth option could work, but isn't very elegant — I'd like to use either `glDrawElements` or `glDrawMultiElements`. One other option would be to use `glDrawElements` while looping over the faces one by one (instead of invoking it once using `glPrimitiveRestartIndex`). In that case, one could upload a `uniform` normal for each face. However, this does not seem very efficient. Any other ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2Whne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4ujWL.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="3998" PostHistoryTypeId="5" PostId="1887" RevisionGUID="a9569a5c-12b4-4927-9578-5580d95fb531" CreationDate="2016-01-10T17:59:21.980" UserId="2437" Comment="added 62 characters in body" Text="Since long ago I wanted to implement a 2D lightning algorithm based on an [idea I saw on YouTube](https://www.youtube.com/watch?v=74uXA7SmDqE). The video is realtime, but it runs on the CPU and the resolution is pretty low. I'm curious if anyone has an idea how to do this on the GPU.&#xD;&#xA;&#xD;&#xA;The algorithm works the following way:&#xD;&#xA;&#xD;&#xA;- We have light data maps, these hold the color of the material (e.g. a red glass has 0xFF0000) and how transparent that pixel is.    &#xD;&#xA;- Work out the light values of each pixel in growing circles from a light source. In other words, first calculate values right next to the light (8 pixels), then the neighbours of these pixels and so on. The color of a pixel is its value from the lightning data map, its alpha equals: (alpha of the pixel next to it closest to the light source - own alpha). So it is some kind of ray casting algorithm that calculates value for each pixel and can handle colored glass and fog/smoke.&#xD;&#xA;&#xD;&#xA;So the CPU implementation is pretty trivial. My problem is that I want to use this in a mobile game, but I don't know how this would work as a shader.&#xD;&#xA;How can this be implemented on the GPU (that would run on mobile, so with OpenGL ES 2.0/3.0, maybe with Metal - if this is not possible then with OpenCL/CUDA)?&#xD;&#xA;&#xD;&#xA;Note: I am not looking for full implementations, just ideas/shader pseudocode how this would be possible." ContentLicense="CC BY-SA 3.0" />
  <row Id="3999" PostHistoryTypeId="5" PostId="1888" RevisionGUID="9f6aae51-5a55-4eab-adee-e5845ff822e7" CreationDate="2016-01-10T18:16:30.373" UserId="2440" Comment="added 3 characters in body" Text="I'm trying to figure out how to properly implement flat shading for meshes containing non-planar polygons (using OpenGL/GLSL). The aim is to obtain something similar to the result *Blender* gives (all polygons below are non-planar):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To provide a bit of context — the non-planar polygons (e.g. quads, pentagons, ...) are either present in the mesh I load or appear as a result of applying a subdivision scheme (such as Catmull-Clark) to the mesh.&#xD;&#xA;&#xD;&#xA;In case of a triangle mesh, I'm aware of the following approaches to implement flat shading —&#xD;&#xA;&#xD;&#xA; 1. Compute the cross product of `dFdx` and `dFdy` in the fragment shader&#xD;&#xA; 2. Use the geometry shader to compute the triangle normal by taking the cross product of two sides of the triangle&#xD;&#xA; 3. When using `glDrawElements`, use the `flat` interpolation qualifier (which basically uses the normal associated with the provoking vertex for all fragments)&#xD;&#xA; 4. When using `glDrawArrays`, most vertices (usually all of them) are copied to the GPU multiple times. Therefore, a different normal can be used each time&#xD;&#xA;&#xD;&#xA;For a mesh containing non-planar polygons the first three options don't yield the result I'm after. In my implementation (using the Qt framework) I use `GL_TRIANGLE_FAN`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The fourth option could work, but isn't very elegant — I'd like to use either `glDrawElements` or `glDrawMultiElements`. One other option would be to use `glDrawElements` while looping over the faces one by one (instead of invoking it once using `glPrimitiveRestartIndex`). In that case, one could upload a `uniform` normal for each face. However, this does not seem very efficient. Any other ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2Whne.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4ujWL.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4000" PostHistoryTypeId="5" PostId="1889" RevisionGUID="0f70308f-edee-40d0-a8ef-b50c5419c517" CreationDate="2016-01-10T19:23:45.380" UserId="38" Comment="added 498 characters in body" Text="If your wall geometry is vector graphics you can simply extrude the segment away from the light position. This means 2 triangles per draw call, all the extrusion offsets can  can be handled in the vertex shader.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: For each wall generate a shadow volume extrusion.&#xD;&#xA;&#xD;&#xA;Quick and extremely dirty sample implementation of shadow volumes here:&#xD;&#xA;&#xD;&#xA;* http://webglplayground.net/saved/AeN6yoNGih (please do not save your own version, fork instead)&#xD;&#xA;&#xD;&#xA;Now since your shader can color the triangles as they see fit you can apply a shader on the triangles that is colored. Just like you would render transparent surfaces. To do this proper you may need a offscreen buffer for getting a proper color accumulation mode.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Coloring the volumes based on distance to light.&#xD;&#xA;&#xD;&#xA;Certainly the coloring algorithm may be whatever you like. for example the color could become darker the nearer you are to the extrude edge etc.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/u80e2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/o2KTd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4001" PostHistoryTypeId="2" PostId="1890" RevisionGUID="bea27173-8da9-4a78-92bd-f16632e739da" CreationDate="2016-01-10T22:15:57.840" UserId="2408" Text="I'm working on implementing [Bruneton's cloud rendering paper][1], which requires one to render a pair of depth maps, similar to how shadow mapping works. In this case, my light source is the sun (or possibly the moon), which I represent in my rendering engine as a normalized vector pointing in the direction of the sun or moon, which is essentially located at infinity from the current camera position.&#xD;&#xA;&#xD;&#xA;Since the light source doesn't have a traditional &quot;position,&quot; I'm having a little trouble determining how best to create the viewpoint transformations for the source. &#xD;&#xA;&#xD;&#xA;Since I would also essentially use the same transformation for sun/moon shadowing, it'd kill two birds with one stone.&#xD;&#xA;&#xD;&#xA;So my question is thus:&#xD;&#xA;**How can I generate a view transform for generating depth maps of area light sources located at infinity?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www-ljk.imag.fr/Publications/Basilic/com.lmc.publi.PUBLI_Inproceedings@117681e94b6_1e9c7f4/clouds.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4002" PostHistoryTypeId="1" PostId="1890" RevisionGUID="bea27173-8da9-4a78-92bd-f16632e739da" CreationDate="2016-01-10T22:15:57.840" UserId="2408" Text="How should I generate the view position for a light at infinity when creating depth maps?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4003" PostHistoryTypeId="3" PostId="1890" RevisionGUID="bea27173-8da9-4a78-92bd-f16632e739da" CreationDate="2016-01-10T22:15:57.840" UserId="2408" Text="|c++|shadow-mapping|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4004" PostHistoryTypeId="5" PostId="1889" RevisionGUID="6c5732cd-3126-4a14-9ff5-840f3df27f6c" CreationDate="2016-01-10T22:37:46.283" UserId="38" Comment="added 172 characters in body" Text="If your wall geometry is vector graphics you can simply extrude the segment away from the light position. This means 2 triangles per draw call, all the extrusion offsets can  can be handled in the vertex shader.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: For each wall generate a shadow volume extrusion.&#xD;&#xA;&#xD;&#xA;Quick and extremely dirty sample implementation of shadow volumes here:&#xD;&#xA;&#xD;&#xA;* http://webglplayground.net/saved/AeN6yoNGih (please do not save your own version, fork instead)&#xD;&#xA;&#xD;&#xA;Now since your shader can color the triangles as they see fit you can apply a shader on the triangles that is colored. Just like you would render transparent surfaces. To do this proper you may need a offscreen buffer for getting a proper color accumulation mode.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Coloring the volumes based on distance to light.&#xD;&#xA;&#xD;&#xA;Certainly the coloring algorithm may be whatever you like. for example the color could become darker the nearer you are to the extrude edge etc.&#xD;&#xA;&#xD;&#xA;This is just one way hopefully others will elborate. You can also use the exact same methods as you would in 3d. As for nonuniform fog, you could just use a raymarcher.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/u80e2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/o2KTd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4005" PostHistoryTypeId="2" PostId="1891" RevisionGUID="96c2bfab-78d7-4b29-8f5f-1227c0e7a65d" CreationDate="2016-01-10T22:54:46.133" UserId="137" Text="Instead of using a perspective projection you would use a [orthographic projection][1].&#xD;&#xA;&#xD;&#xA;Then the trick is to position the bounding box to in front of the normal camera.&#xD;&#xA;&#xD;&#xA;An additional option is to add a [skew/shear operation][2] so it maps the light direction to the vertical and keeps the horizontal ground plane horizontal.&#xD;&#xA;&#xD;&#xA;This avoids leaving a large dead zone underground near the light source.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orthographic_projection&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Shear_mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="4006" PostHistoryTypeId="2" PostId="1892" RevisionGUID="5ebcbc26-8f37-4c52-bfd8-3f2430499730" CreationDate="2016-01-11T00:14:00.453" UserId="2413" Text="&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;I've recently rebuild shaders for my program and it stopped &quot;working&quot; ( black screen ) on OS X ( El Capitan ), but **it's ok on Linux**.&#xD;&#xA;&#xD;&#xA;There are no shader compilation errors, and here is my shader code:&#xD;&#xA;&#xD;&#xA;https://github.com/Marqin/YuriaViewer/blob/master/vertex.glsl&#xD;&#xA;&#xD;&#xA;Keep in mind that this software worked on El Capitan with OpenGL 4.1 before shader rewrite. Here are my glfw hints:&#xD;&#xA;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;&#xD;&#xA;My program also is checking for `GL_ARB_gpu_shader_fp64` and it's available on my Macbook ( Macbook Air 2013 mid ).&#xD;&#xA;&#xD;&#xA;I've &quot;debugged&quot; it a little and it looks that `i` is always lesser than `vis` on OS X, that's why it's black.&#xD;&#xA;&#xD;&#xA;I've also made a simple test - I've typed all uniform values in shader by hand and now it wasn't black, but I've got some gibberish on screen. Then I've changed every `dvec3` and `dvec2` to float versions and it showed nice fractal. So it looks like `double` is not working on OS X. But how can it be? It's saying that `GL_ARB_gpu_shader_fp64` is available and it even doesn't complain when I request it in vertex shader.&#xD;&#xA;&#xD;&#xA;How can I make it work on OS X Macbook?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4007" PostHistoryTypeId="1" PostId="1892" RevisionGUID="5ebcbc26-8f37-4c52-bfd8-3f2430499730" CreationDate="2016-01-11T00:14:00.453" UserId="2413" Text="How to make double working in OpenGL 4.1 on OS X? ( shader works on Linux )" ContentLicense="CC BY-SA 3.0" />
  <row Id="4008" PostHistoryTypeId="3" PostId="1892" RevisionGUID="5ebcbc26-8f37-4c52-bfd8-3f2430499730" CreationDate="2016-01-11T00:14:00.453" UserId="2413" Text="|opengl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4009" PostHistoryTypeId="5" PostId="281" RevisionGUID="7dea0808-a9db-42b4-b671-faee4add5af0" CreationDate="2016-01-11T12:12:48.303" UserId="137" Comment="added 81 characters in body" Text="On modern hardware if all invocations in a group follow the same path then the unused path doesn't get evaluated.&#xD;&#xA;&#xD;&#xA;in pseudo code:&#xD;&#xA;&#xD;&#xA;    if(cond){&#xD;&#xA;       res = ...&#xD;&#xA;    }else{&#xD;&#xA;       res = ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;becomes&#xD;&#xA;&#xD;&#xA;    if(anyInvocationEXT(cond)){&#xD;&#xA;        res1 = ...&#xD;&#xA;    }&#xD;&#xA;    if(anyInvocationEXT(!cond)){&#xD;&#xA;        res2 = ...&#xD;&#xA;    }&#xD;&#xA;    res = cond?res1:res2;&#xD;&#xA;&#xD;&#xA;Where `anyInvocationEXT` will be true if any invocation of the shader will have true as `cond`. (from the opengl extension [EXT_shader_group_vote][1])&#xD;&#xA;&#xD;&#xA;If cond is derivable from uniforms alone then the driver may optimize and evaluate the condition and replace the if with a goto to the correct branch. OpenGL has a feature called uniform subroutines that makes it explicit.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/gles/extensions/EXT/EXT_shader_group_vote.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="4010" PostHistoryTypeId="5" PostId="1892" RevisionGUID="9e1b5ab5-2912-49f6-9bca-0032701cd929" CreationDate="2016-01-11T14:42:33.647" UserId="2413" Comment="added 173 characters in body; edited title" Text="&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;I've recently rebuild shaders for my program and it stopped &quot;working&quot; ( black screen ) on OS X ( El Capitan ), but **it's ok on Linux on GTX 660**.&#xD;&#xA;&#xD;&#xA;I've tested it on another Apple hardware and **it worked on OS X on R9 395** ( but super slow ). So I suppose it's problem with my **Intel HD Graphics 5000**.&#xD;&#xA;&#xD;&#xA;There are no shader compilation errors, and here is my shader code:&#xD;&#xA;&#xD;&#xA;https://github.com/Marqin/YuriaViewer/blob/master/vertex.glsl&#xD;&#xA;&#xD;&#xA;Keep in mind that this software worked on El Capitan with OpenGL 4.1 before shader rewrite. Here are my glfw hints:&#xD;&#xA;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;&#xD;&#xA;My program also is checking for `GL_ARB_gpu_shader_fp64` and it's available on my Macbook ( Macbook Air 2013 mid ).&#xD;&#xA;&#xD;&#xA;I've &quot;debugged&quot; it a little and it looks that `i` is always lesser than `vis` on OS X, that's why it's black.&#xD;&#xA;&#xD;&#xA;I've also made a simple test - I've typed all uniform values in shader by hand and now it wasn't black, but I've got some gibberish on screen. Then I've changed every `dvec3` and `dvec2` to float versions and it showed nice fractal. So it looks like `double` is not working on OS X. But how can it be? It's saying that `GL_ARB_gpu_shader_fp64` is available and it even doesn't complain when I request it in vertex shader.&#xD;&#xA;&#xD;&#xA;How can I make it work on OS X Macbook?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4011" PostHistoryTypeId="4" PostId="1892" RevisionGUID="9e1b5ab5-2912-49f6-9bca-0032701cd929" CreationDate="2016-01-11T14:42:33.647" UserId="2413" Comment="added 173 characters in body; edited title" Text="How to make double working in OpenGL 4.1 on OS X ( Intel HD Graphics 5000 )?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4012" PostHistoryTypeId="2" PostId="1893" RevisionGUID="d3221613-3694-4b31-8405-ccdf8ebef55f" CreationDate="2016-01-11T14:52:59.460" UserId="2233" Text="I want to select a pixel within a circle of a certain radius. But the radius is expressed in a decimal form (0.12). What does it mean to have a radius equal to 0.12? And concretely how to pick a pixel within a circle having such a radius?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ksGCK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4013" PostHistoryTypeId="1" PostId="1893" RevisionGUID="d3221613-3694-4b31-8405-ccdf8ebef55f" CreationDate="2016-01-11T14:52:59.460" UserId="2233" Text="Selecting pixels within a circle having a decimal (non integer) radius" ContentLicense="CC BY-SA 3.0" />
  <row Id="4014" PostHistoryTypeId="3" PostId="1893" RevisionGUID="d3221613-3694-4b31-8405-ccdf8ebef55f" CreationDate="2016-01-11T14:52:59.460" UserId="2233" Text="|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4015" PostHistoryTypeId="5" PostId="1892" RevisionGUID="a13cae23-7deb-48d4-9a22-49e81344fe86" CreationDate="2016-01-11T14:59:52.950" UserId="2413" Comment="added 19 characters in body" Text="&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;I've recently rebuild shaders for my program and it stopped &quot;working&quot; ( black screen ) on OS X ( El Capitan ), but **it's ok on Linux on GTX 660**.&#xD;&#xA;&#xD;&#xA;I've tested it on another Apple hardware and **it worked on OS X on R9 395** ( but super slow, because of double ). So I suppose it's problem with my **Intel HD Graphics 5000**.&#xD;&#xA;&#xD;&#xA;There are no shader compilation errors, and here is my shader code:&#xD;&#xA;&#xD;&#xA;https://github.com/Marqin/YuriaViewer/blob/master/vertex.glsl&#xD;&#xA;&#xD;&#xA;Keep in mind that this software worked on El Capitan with OpenGL 4.1 before shader rewrite. Here are my glfw hints:&#xD;&#xA;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;&#xD;&#xA;My program also is checking for `GL_ARB_gpu_shader_fp64` and it's available on my Macbook ( Macbook Air 2013 mid ).&#xD;&#xA;&#xD;&#xA;I've &quot;debugged&quot; it a little and it looks that `i` is always lesser than `vis` on OS X, that's why it's black.&#xD;&#xA;&#xD;&#xA;I've also made a simple test - I've typed all uniform values in shader by hand and now it wasn't black, but I've got some gibberish on screen. Then I've changed every `dvec3` and `dvec2` to float versions and it showed nice fractal. So it looks like `double` is not working on OS X. But how can it be? It's saying that `GL_ARB_gpu_shader_fp64` is available and it even doesn't complain when I request it in vertex shader.&#xD;&#xA;&#xD;&#xA;How can I make it work on OS X Macbook?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4016" PostHistoryTypeId="5" PostId="1889" RevisionGUID="f0d622f9-4836-44e8-b320-1331b723c8f8" CreationDate="2016-01-11T17:39:42.400" UserId="38" Comment="added 240 characters in body" Text="If your wall geometry is vector graphics you can simply extrude the segment away from the light position. This means 2 triangles per draw call, all the extrusion offsets can  can be handled in the vertex shader.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: For each wall generate a shadow volume extrusion.&#xD;&#xA;&#xD;&#xA;Quick and extremely dirty sample implementation of shadow volumes here:&#xD;&#xA;&#xD;&#xA;* http://webglplayground.net/saved/AeN6yoNGih (please do not save your own version, fork instead)&#xD;&#xA;&#xD;&#xA;Now since your shader can color the triangles as they see fit you can apply a shader on the triangles that is colored. Just like you would render transparent surfaces. To do this proper you may need a offscreen buffer for getting a proper color accumulation mode.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Coloring the volumes based on distance to light.&#xD;&#xA;&#xD;&#xA;Certainly the coloring algorithm may be whatever you like. for example the color could become darker the nearer you are to the extrude edge etc. &#xD;&#xA;&#xD;&#xA;And here is very quickly done *extremely dirty* live example of colored shadow volumes:&#xD;&#xA;&#xD;&#xA;* http://webglplayground.net/saved/9xgxDbtY7f (please do not save your own version, fork instead), very bad code style done on the run (and on my phone).&#xD;&#xA;&#xD;&#xA;This is just one way hopefully others will elborate. You can also use the exact same methods as you would in 3d. As for nonuniform fog, you could just use a raymarcher.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/u80e2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/o2KTd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4017" PostHistoryTypeId="2" PostId="1894" RevisionGUID="04354687-4b22-4b10-b55e-1189a4270f6d" CreationDate="2016-01-11T19:51:14.097" UserId="2451" Text="https://www.youtube.com/watch?v=twUz99ek5do&amp;list=WL&amp;index=5  &#xD;&#xA;&#xD;&#xA;There is a process from 1:51, where the guy start making polygons around the bodyparts. I think this is this part is where (with later transformations) you can make a single draw like a 3D animation (with transforming the triangles). What is the name of the process, and is this effect available in other animation softver? &#xD;&#xA;I'm thinking about mostly maya, spriter or unity.&#xD;&#xA;Ty " ContentLicense="CC BY-SA 3.0" />
  <row Id="4018" PostHistoryTypeId="1" PostId="1894" RevisionGUID="04354687-4b22-4b10-b55e-1189a4270f6d" CreationDate="2016-01-11T19:51:14.097" UserId="2451" Text="Spine. What is the name of the process?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4019" PostHistoryTypeId="3" PostId="1894" RevisionGUID="04354687-4b22-4b10-b55e-1189a4270f6d" CreationDate="2016-01-11T19:51:14.097" UserId="2451" Text="|3d|animation|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4020" PostHistoryTypeId="2" PostId="1895" RevisionGUID="000ca7b8-3c2f-4fbe-b664-73372472cd83" CreationDate="2016-01-11T20:09:00.557" UserId="2447" Text="I have been working on a graphics library for some time now and have gotten to the point where I have to draw Bezier and line based fonts. Up to this point I am stuck with this:&#xD;&#xA;&#xD;&#xA;![i](https://cdn.discordapp.com/attachments/132932473242910720/136193149239427073/unknown.png)&#xD;&#xA;&#xD;&#xA;![a](https://cdn.discordapp.com/attachments/132932473242910720/136196291146285056/unknown.png)&#xD;&#xA;&#xD;&#xA;The green lines are the Bezier paths, and the white part is what gets rendered.&#xD;&#xA;&#xD;&#xA;The code I use for Beziers is [here][1]. The one for lines is [here][2]. For those who don't know that is Lua. &#xD;&#xA;&#xD;&#xA;Path rendering (lines) : 32 - 39&#xD;&#xA;  The algorithm is as follows:&#xD;&#xA;     &#xD;&#xA; 1. Iterating from 0 to 1 at certain intervals&#xD;&#xA; 2. calculating the x and y with this formula: `(1-index)^2*x1+2*(1-index)*index*x2+index^2*x3`&#xD;&#xA;&#xD;&#xA;Up to this point everything works fine. The green lines are generated using the path method.&#xD;&#xA;&#xD;&#xA;The white part is rendered in a completely different way:&#xD;&#xA;&#xD;&#xA; 1. I get the x coordinates of the Beziers and lines at a particular Y, the put them into a table.&#xD;&#xA; 2. I iterate through the table and each time I encounter a point I change the value of state. In the same for loop is also check whether state is on. If it is, I draw a pixel to the screen.&#xD;&#xA;&#xD;&#xA;To find the x values of a y, I use the getX method (line 46 in Bezier and line 31 in Line).&#xD;&#xA;&#xD;&#xA;The code I use for the drawing itself is this one:&#xD;&#xA;&#xD;&#xA;    local xBuffer = {}&#xD;&#xA;    local state = false&#xD;&#xA;    &#xD;&#xA;    for i=0,500 do&#xD;&#xA;    	for k,v in pairs(beziers) do&#xD;&#xA;    		a,b = v.getX(i)&#xD;&#xA;    		if a then&#xD;&#xA;    			xBuffer[round(a)] = 1&#xD;&#xA;    			if b then&#xD;&#xA;    				xBuffer[round(a)] = 1&#xD;&#xA;    			end&#xD;&#xA;    		end&#xD;&#xA;    	end&#xD;&#xA;    	for k,v in pairs(lines) do&#xD;&#xA;    		a = v.getX(i)&#xD;&#xA;    		if a then&#xD;&#xA;    			xBuffer[round(a)] = 1&#xD;&#xA;    		end&#xD;&#xA;    	end&#xD;&#xA;    	state = false&#xD;&#xA;    	for x=0,600 do&#xD;&#xA;    		if xBuffer[x] then&#xD;&#xA;    			state = not state&#xD;&#xA;    		end&#xD;&#xA;    		if state then&#xD;&#xA;    			love.graphics.points(x,i)&#xD;&#xA;    		end&#xD;&#xA;    	end&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;Quick explanation: for i,v in pairs iterates through the table given as an argument to pairs. love.graphics.points(x,y) sets a point at x,y.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://pastebin.com/s8qDC4NH&#xD;&#xA;  [2]: http://pastebin.com/bKv55tch" ContentLicense="CC BY-SA 3.0" />
  <row Id="4021" PostHistoryTypeId="1" PostId="1895" RevisionGUID="000ca7b8-3c2f-4fbe-b664-73372472cd83" CreationDate="2016-01-11T20:09:00.557" UserId="2447" Text="How should I fill a shape consisting of Bezier cures and straight lines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4022" PostHistoryTypeId="3" PostId="1895" RevisionGUID="000ca7b8-3c2f-4fbe-b664-73372472cd83" CreationDate="2016-01-11T20:09:00.557" UserId="2447" Text="|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4023" PostHistoryTypeId="2" PostId="1896" RevisionGUID="e295b40d-1fca-4d27-bffe-464140134457" CreationDate="2016-01-11T21:47:54.283" UserId="2425" Text="I have managed to implement a garoud shader with specular lighting efects in Processing 3.0 . Now I am trying with a fragment Phong shader but cannot make it work. I can´t find where is the error. It should just implent the phong illumination model, with specular and diffuse components.&#xD;&#xA;&#xD;&#xA;Vertex Shader: &#xD;&#xA;&#xD;&#xA;    #define PROCESSING_LIGHT_SHADER&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelview;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    attribute vec4 vertex;&#xD;&#xA;    attribute vec4 color;&#xD;&#xA;    attribute vec3 normal;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    &#xD;&#xA;    varying vec3 transformedNormal;&#xD;&#xA;    varying vec3 vertexCamera;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = transform * vertex;    &#xD;&#xA;      &#xD;&#xA;      vertexCamera = vec3(modelview * vertex);  &#xD;&#xA;      transformedNormal = normalize(normalMatrix * normal);&#xD;&#xA;      vertColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragement Shader:&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform vec3 lightPosition;&#xD;&#xA;    uniform vec3 eye_Position;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    varying vec3 lightDir;&#xD;&#xA;    &#xD;&#xA;    varying vec3 transformedNormal; //world pos&#xD;&#xA;    varying vec3 vertexCamera; // world normal&#xD;&#xA;    &#xD;&#xA;    void main() {  &#xD;&#xA;      &#xD;&#xA;     vec3 normalizedPos =  normalize(lightPosition.xyz -vertexCamera);&#xD;&#xA;     vec3 direction = normalize(eye_Position - vertexCamera); &#xD;&#xA;        &#xD;&#xA;     &#xD;&#xA;     float intensity = 0.0;&#xD;&#xA;     float specular = 0.0;&#xD;&#xA;     &#xD;&#xA;     &#xD;&#xA;     float LdotN = max(0, dot(normalizedPos,direction));&#xD;&#xA;     float diffuse = 1 * LdotN;&#xD;&#xA;      &#xD;&#xA;     vec3 R = -normalize(reflect(normalizedPos,transformedNormal));&#xD;&#xA;     specular = pow( max(0, dot( R, direction)), 16);&#xD;&#xA;           &#xD;&#xA;      &#xD;&#xA;      intensity += (diffuse + specular);&#xD;&#xA;          &#xD;&#xA;      gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4024" PostHistoryTypeId="1" PostId="1896" RevisionGUID="e295b40d-1fca-4d27-bffe-464140134457" CreationDate="2016-01-11T21:47:54.283" UserId="2425" Text="Shader won't work" ContentLicense="CC BY-SA 3.0" />
  <row Id="4025" PostHistoryTypeId="3" PostId="1896" RevisionGUID="e295b40d-1fca-4d27-bffe-464140134457" CreationDate="2016-01-11T21:47:54.283" UserId="2425" Text="|opengl|shader|glsl|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4026" PostHistoryTypeId="5" PostId="1896" RevisionGUID="336a5fa3-4157-4e7e-b80f-3d7cae89d198" CreationDate="2016-01-11T22:15:05.193" UserId="2425" Comment="added 84 characters in body" Text="I have managed to implement a garoud shader with specular lighting efects in Processing 3.0 . Now I am trying with a fragment Phong shader but cannot make it work. I can´t find where is the error. It should just implent the phong illumination model, with specular and diffuse components.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex Shader: &#xD;&#xA;&#xD;&#xA;    #define PROCESSING_LIGHT_SHADER&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelview;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    attribute vec4 vertex;&#xD;&#xA;    attribute vec4 color;&#xD;&#xA;    attribute vec3 normal;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    &#xD;&#xA;    varying vec3 transformedNormal;&#xD;&#xA;    varying vec3 vertexCamera;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = transform * vertex;    &#xD;&#xA;      &#xD;&#xA;      vertexCamera = vec3(modelview * vertex);  &#xD;&#xA;      transformedNormal = normalize(normalMatrix * normal);&#xD;&#xA;      vertColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragement Shader:&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform vec3 lightPosition;&#xD;&#xA;    uniform vec3 eye_Position;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    varying vec3 lightDir;&#xD;&#xA;    &#xD;&#xA;    varying vec3 transformedNormal; //world pos&#xD;&#xA;    varying vec3 vertexCamera; // world normal&#xD;&#xA;    &#xD;&#xA;    void main() {  &#xD;&#xA;      &#xD;&#xA;     vec3 normalizedPos =  normalize(lightPosition.xyz -vertexCamera);&#xD;&#xA;     vec3 direction = normalize(eye_Position - vertexCamera); &#xD;&#xA;        &#xD;&#xA;     &#xD;&#xA;     float intensity = 0.0;&#xD;&#xA;     float specular = 0.0;&#xD;&#xA;     &#xD;&#xA;     &#xD;&#xA;     float LdotN = max(0, dot(normalizedPos,direction));&#xD;&#xA;     float diffuse = 1 * LdotN;&#xD;&#xA;      &#xD;&#xA;     vec3 R = -normalize(reflect(normalizedPos,transformedNormal));&#xD;&#xA;     specular = pow( max(0, dot( R, direction)), 16);&#xD;&#xA;           &#xD;&#xA;      &#xD;&#xA;      intensity += (diffuse + specular);&#xD;&#xA;          &#xD;&#xA;      gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eKOTe.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4027" PostHistoryTypeId="2" PostId="1897" RevisionGUID="2b7ca9bb-4dfd-4ed2-bc70-5b22452f4275" CreationDate="2016-01-11T22:22:05.730" UserId="48" Text="This appears to be simply [skeletal animation](https://en.wikipedia.org/wiki/Skeletal_animation), which is a standard technique that is available in all modern animation packages. Whether applied to 3D meshes or (as here) 2D ones, the principle is the same.&#xD;&#xA;&#xD;&#xA;The pseudo-3D effect on the sprites is created by using a mesh where vertices are placed along the contours of the sprite texture, then animated to squash and stretch parts the image in such a way that it creates the illusion of 3D motion, even though the sprite images are authored in 2D. There's [a description of the technique in the Spine docs](http://esotericsoftware.com/spine-meshes#Deformation)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4028" PostHistoryTypeId="6" PostId="1895" RevisionGUID="92a62e48-17dc-447c-a9c5-2ecc0375dd0a" CreationDate="2016-01-11T22:25:58.387" UserId="2447" Comment="edited tags" Text="|rendering|algorithm|geometry|line-drawing|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4033" PostHistoryTypeId="2" PostId="1899" RevisionGUID="6d623652-62a8-4e1b-b10a-e8e9dbdcf735" CreationDate="2016-01-12T12:53:59.170" UserId="209" Text="If you are in a hurry to get your renderer working *and* you already have the filled polygonal routine *functioning correctly*, can I suggest an alternative, possibly easier approach? Though I'm not familiar with Lua, it seems you are solving for the exact intersection of a scan line with the quadratic Bezier which, though admirable, is possibly overkill.&#xD;&#xA;&#xD;&#xA;Instead, just tessellate your Beziers into line segments and then throw those into polygon scan converter. I suggest just using (recursive) binary subdivision: i.e. the quadratic Bezier with control points, $(\overline {A} , \overline {B} , \overline {C})$ can be split into two Beziers, $(\overline {A} , \overline {D} , \overline {E})$ and $(\overline {E} , \overline {F} , \overline {C})$ &#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;\begin{align*} &amp; \overline {D}=\dfrac {\overline {A}+\overline {B}} {2}\\ &amp; &#xD;&#xA;\overline {E} =\dfrac {\overline {A}+2\overline {B}+\overline {C}}{4}\\ &amp;&#xD;&#xA;\overline {F}=\dfrac {\overline {B}+\overline {C}} {2}&#xD;&#xA;\end{align*}&#xD;&#xA;$$&#xD;&#xA;(which is also great if you only have fixed point maths).&#xD;&#xA;&#xD;&#xA;IIRC, each time you subdivide, the error between the Bezier and just a straight line segment joining the end points goes down by a factor of 4x, so it doesn't take many subdivisions before it will be indistinguishable from the original. You can also use the bounding box of the control points to decide if you can skip out of the subdivision process early since that will also be a conservative bound on the curve.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4034" PostHistoryTypeId="5" PostId="1899" RevisionGUID="bb4837f7-3e1a-4cc3-adf1-c9f0d7e452c7" CreationDate="2016-01-12T16:03:03.003" UserId="209" Comment="fixed grammar" Text="If you are in a hurry to get your renderer working *and* you already have the filled polygonal routine *functioning correctly*, can I suggest an alternative, possibly easier approach? Though I'm not familiar with Lua, it seems you are solving for the exact intersection of a scan line with the quadratic Bezier which, though admirable, is possibly overkill.&#xD;&#xA;&#xD;&#xA;Instead, tessellate your Beziers into line segments and then throw those into the polygon scan converter. I suggest just using (recursive) binary subdivision: i.e. the quadratic Bezier with control points, $(\overline {A} , \overline {B} , \overline {C})$ can be split into two Beziers, $(\overline {A} , \overline {D} , \overline {E})$ and $(\overline {E} , \overline {F} , \overline {C})$ &#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;\begin{align*} &amp; \overline {D}=\dfrac {\overline {A}+\overline {B}} {2}\\ &amp; &#xD;&#xA;\overline {E} =\dfrac {\overline {A}+2\overline {B}+\overline {C}}{4}\\ &amp;&#xD;&#xA;\overline {F}=\dfrac {\overline {B}+\overline {C}} {2}&#xD;&#xA;\end{align*}&#xD;&#xA;$$&#xD;&#xA;(which is also great if you only have fixed point maths).&#xD;&#xA;&#xD;&#xA;IIRC, each time you subdivide, the error between the Bezier and just a straight line segment joining the end points goes down by a factor of ~4x, so it doesn't take many subdivisions before it will be indistinguishable from the original. You can also use the bounding box of the control points to decide if you can skip out of the subdivision process early since that will also be a conservative bound on the curve.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4035" PostHistoryTypeId="2" PostId="1900" RevisionGUID="5f680967-d986-4e07-91bd-426c87a54df1" CreationDate="2016-01-12T16:36:27.080" UserId="2064" Text="If you are using Processing the variable `lightPosition` must be declared as a `vec4`, otherwise it won't be passed in, and will be always 0.&#xD;&#xA;&#xD;&#xA;Then your diffuse computation is not correct, the dot product we want it's between the normal and the light direction:&#xD;&#xA;&#xD;&#xA;    float LdotN = max(0, dot(normalizedPos,transformedNormal));&#xD;&#xA;&#xD;&#xA;I'm not sure about the uniform `eye_Position`, I believe it's always 0 as nobody is setting it. Anyway, it is not needed. Since the fragment position it's already on camera space, the camera direction is simply: &#xD;&#xA;&#xD;&#xA;    vec3 direction = -normalize(vertexCamera);&#xD;&#xA;&#xD;&#xA;The complete fragment shader should be:&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform vec4 lightPosition;&#xD;&#xA;    &#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    varying vec3 transformedNormal;&#xD;&#xA;    varying vec3 vertexCamera;&#xD;&#xA;    &#xD;&#xA;    void main() {  &#xD;&#xA;    &#xD;&#xA;     vec3 normalizedPos =  normalize(lightPosition.xyz -vertexCamera);&#xD;&#xA;     vec3 direction = -normalize(vertexCamera); &#xD;&#xA;    &#xD;&#xA;     float intensity = 0.0;&#xD;&#xA;     float specular = 0.0;&#xD;&#xA;    &#xD;&#xA;     float LdotN = max(0, dot(normalizedPos,transformedNormal));&#xD;&#xA;     float diffuse = 1 * LdotN;&#xD;&#xA;    &#xD;&#xA;     vec3 R = -normalize(reflect(normalizedPos,transformedNormal));&#xD;&#xA;     specular = pow( max(0, dot( R, direction)), 16);&#xD;&#xA;    &#xD;&#xA;      intensity += (diffuse + specular);&#xD;&#xA;    &#xD;&#xA;      gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="4036" PostHistoryTypeId="5" PostId="1551" RevisionGUID="7bf24fc8-c357-48a8-805d-b3d68d641246" CreationDate="2016-01-12T17:06:14.510" UserId="209" Comment="Added link to historical memory costs." Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential. (For example, in 1980, [1MB of RAM was &gt; $6000](http://www.jcmit.com/memoryprice.htm) (and that probably doesn't account for inflation!))&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx system provided an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant is, naturally, noisier than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4037" PostHistoryTypeId="2" PostId="1901" RevisionGUID="375edd27-449f-45a7-a2c8-c2229bf605fb" CreationDate="2016-01-12T22:43:34.653" UserId="56" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I'm working on a shadertoy &quot;snake&quot; game, using the new multi pass rendering abilities to save game state between frames.&#xD;&#xA;&#xD;&#xA;I'm using raytracing to render the board (an AABB), and am planning on using spheres to render sections of the snake's body.&#xD;&#xA;&#xD;&#xA;The game board is a 16x16 grid and each grid can either have a sphere there (a segment of the snake's body) or not.  Snake body segments don't move, they are just either there on the grid or not.  When the snake moves, a new sphere appears in the front and an old sphere disappears from the back.&#xD;&#xA;&#xD;&#xA;The problem I'm trying to solve is how to render the snake body spheres.&#xD;&#xA;&#xD;&#xA;For instance, a naive approach would be to store a 16x16 grid in pixels specifying whether there was a snake body in that grid cell or not.&#xD;&#xA;&#xD;&#xA;I would then do a ray vs sphere check for up to 256 different spheres within my pixel shader, which seems like a no go.&#xD;&#xA;&#xD;&#xA;Another method might be to figure out where the ray begins and ends on the game board (when it's between the high and low height values of where the spheres are) and then use something like bressenham line algorithm to go from the start to the end of the line the ray takes on the board, and check only the grid cells that the ray hits.&#xD;&#xA;&#xD;&#xA;The problem there is that it requires a dynamic loop.&#xD;&#xA;&#xD;&#xA;Maybe a more practical solution would be to make the camera have a nearly top down view and where the ray enters the playable game world, test any sphere in the cell it hits as well as the 8 neighboring cells.&#xD;&#xA;&#xD;&#xA;I'm betting there are some much better solutions that I'm not thinking of.&#xD;&#xA;&#xD;&#xA;Does anyone know of any interesting techniques or creative solutions?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MZosQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4038" PostHistoryTypeId="1" PostId="1901" RevisionGUID="375edd27-449f-45a7-a2c8-c2229bf605fb" CreationDate="2016-01-12T22:43:34.653" UserId="56" Text="Methods for grid traversal in a glsl pixel shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4039" PostHistoryTypeId="3" PostId="1901" RevisionGUID="375edd27-449f-45a7-a2c8-c2229bf605fb" CreationDate="2016-01-12T22:43:34.653" UserId="56" Text="|raytracing|real-time|glsl|pixel-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4043" PostHistoryTypeId="5" PostId="1901" RevisionGUID="1d64dd17-f9a8-4f1e-87c1-97093e5ba58b" CreationDate="2016-01-12T22:53:49.307" UserId="56" Comment="added 214 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I'm working on a shadertoy &quot;snake&quot; game, using the new multi pass rendering abilities to save game state between frames.&#xD;&#xA;&#xD;&#xA;I'm using raytracing to render the board (an AABB), and am planning on using spheres to render sections of the snake's body.&#xD;&#xA;&#xD;&#xA;The game board is a 16x16 grid and each grid can either have a sphere there (a segment of the snake's body) or not.  Snake body segments don't move, they are just either there on the grid or not.  When the snake moves, a new sphere appears in the front and an old sphere disappears from the back.&#xD;&#xA;&#xD;&#xA;The problem I'm trying to solve is how to render the snake body spheres.&#xD;&#xA;&#xD;&#xA;For instance, a naive approach would be to store a 16x16 grid in pixels specifying whether there was a snake body in that grid cell or not.&#xD;&#xA;&#xD;&#xA;I would then do a ray vs sphere check for up to 256 different spheres within my pixel shader, which seems like a no go.&#xD;&#xA;&#xD;&#xA;Another method might be to figure out where the ray begins and ends on the game board (when it's between the high and low height values of where the spheres are) and then use something like bressenham line algorithm to go from the start to the end of the line the ray takes on the board, and check only the grid cells that the ray hits.&#xD;&#xA;&#xD;&#xA;The problem there is that it requires a dynamic loop.&#xD;&#xA;&#xD;&#xA;Maybe a more practical solution would be to make the camera have a nearly top down view and where the ray enters the playable game world, test any sphere in the cell it hits as well as the 8 neighboring cells.&#xD;&#xA;&#xD;&#xA;I'm betting there are some much better solutions that I'm not thinking of.&#xD;&#xA;&#xD;&#xA;Does anyone know of any interesting techniques or creative solutions?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;Edit: here is an older version of this game i made, which was CPU / software rendered, to give an idea of what I'm planning.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MZosQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/y7OLJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4046" PostHistoryTypeId="2" PostId="1903" RevisionGUID="702fb962-e133-4c16-98d1-ecf1b0a3fb09" CreationDate="2016-01-13T08:17:56.753" UserId="2459" Text="I want a help. In R software, I want plot graph by using cox regression with restricted cubic spline method. However, there are some wrong. I want someone can help me to resolve it.  Thanks!&#xD;&#xA;&#xD;&#xA;The code shown as the follows:&#xD;&#xA;&#xD;&#xA;library(rms); require(rms); library(Hmisc)&#xD;&#xA;&#xD;&#xA;d&lt;-curve.men&#xD;&#xA;&#xD;&#xA;dd &lt;- datadist(d)&#xD;&#xA;&#xD;&#xA;options(datadist=&quot;dd&quot;)&#xD;&#xA;&#xD;&#xA;fit &lt;- cph(Surv(time,death) ~ rcs(bmi,4)&#xD;&#xA;           + systolic +glucose + l_chol + age &#xD;&#xA;           + edu_g2 + smoke_s + l_chol + drink + activity_l+activity_w,&#xD;&#xA;             data=d, nk=5)&#xD;&#xA;&#xD;&#xA;plot(Predict(fit,bmi), xlab=&quot;bmi&quot;, ylab=&quot;Relative Risk&quot;, lty=1, lwd=2)&#xD;&#xA;&#xD;&#xA;###the results shows the plot in the below&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1] (A)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###However, I want to plot the following graph&#xD;&#xA;[![enter image description here][2]][2] (B)&#xD;&#xA;&#xD;&#xA;###question 1: &#xD;&#xA; how to set the reference point  (for example:  bmi=24.21429 as the reference point))&#xD;&#xA;###question 2:  &#xD;&#xA;I want to add a line, use the following code; However, it did not work.&#xD;&#xA;abline(h=1)&#xD;&#xA;###question 3, &#xD;&#xA;so how to plot the graph show like (B)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MoyLw.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fx5Qx.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4047" PostHistoryTypeId="1" PostId="1903" RevisionGUID="702fb962-e133-4c16-98d1-ecf1b0a3fb09" CreationDate="2016-01-13T08:17:56.753" UserId="2459" Text="Problems in using cox regression with restricted cubic spline plot with R software" ContentLicense="CC BY-SA 3.0" />
  <row Id="4048" PostHistoryTypeId="3" PostId="1903" RevisionGUID="702fb962-e133-4c16-98d1-ecf1b0a3fb09" CreationDate="2016-01-13T08:17:56.753" UserId="2459" Text="|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4049" PostHistoryTypeId="5" PostId="1551" RevisionGUID="a5f8b20a-542c-410b-82d7-cc2ab9209396" CreationDate="2016-01-13T08:52:58.930" UserId="209" Comment="Found a link to 3dfx YAB format." Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of memory (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of large house, reducing the texture footprint was essential. (For example, in 1980, [1MB of RAM was &gt; $6000](http://www.jcmit.com/memoryprice.htm) (and that probably doesn't account for inflation!))&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature (or patents) you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parametrised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant has, naturally, higher error than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4050" PostHistoryTypeId="5" PostId="1551" RevisionGUID="956e05e0-002a-47da-81ca-1c4ce1a48948" CreationDate="2016-01-13T09:02:01.997" UserId="209" Comment="Found a link to 3dfx YAB format + various spelling mistakes." Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 80s needed access to *relatively* large amounts of texture data and, in the days when even a small amount of hight speed memory and logic (e.g. enough for a modest sub-512x512 frame buffer) could set you back the price of small house, reducing the texture footprint was essential. (For example, in 1980, [1MB of RAM was &gt; $6000](http://www.jcmit.com/memoryprice.htm) (and that probably doesn't account for inflation))&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature or patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334)) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant has, naturally, higher error than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4051" PostHistoryTypeId="5" PostId="1551" RevisionGUID="4e6bd12b-3863-4e1f-9892-0f49b0338898" CreationDate="2016-01-13T09:18:15.050" UserId="209" Comment="Fixed some details on prices of memory etc" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  The problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant has, naturally, higher error than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4052" PostHistoryTypeId="2" PostId="1904" RevisionGUID="384be43d-b471-4575-a9fd-09537a049801" CreationDate="2016-01-13T09:47:21.997" UserId="2383" Text="I want to extract colors from images like in Adobe Kuler.When I select colorful or muted corresponding  colors are shown. But what is the definition for colorful or muted colors or what does colorful,deep,muted refer to? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4053" PostHistoryTypeId="1" PostId="1904" RevisionGUID="384be43d-b471-4575-a9fd-09537a049801" CreationDate="2016-01-13T09:47:21.997" UserId="2383" Text="Extract Color from image like Kuler" ContentLicense="CC BY-SA 3.0" />
  <row Id="4054" PostHistoryTypeId="3" PostId="1904" RevisionGUID="384be43d-b471-4575-a9fd-09537a049801" CreationDate="2016-01-13T09:47:21.997" UserId="2383" Text="|color|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4058" PostHistoryTypeId="5" PostId="1903" RevisionGUID="e48bb4a1-fdec-49bb-afb4-48720bbf7df5" CreationDate="2016-01-13T12:40:46.480" UserId="16" Comment="deleted 58 characters in body" Text="In R software, I want to plot a graph by using cox regression with the restricted cubic spline method. However, I can't quite get it to work.&#xD;&#xA;&#xD;&#xA;This is the code I'm using:&#xD;&#xA;&#xD;&#xA;    library(rms); require(rms); library(Hmisc)&#xD;&#xA;    d&lt;-curve.men&#xD;&#xA;    dd &lt;- datadist(d)&#xD;&#xA;    options(datadist=&quot;dd&quot;)&#xD;&#xA;    fit &lt;- cph(Surv(time,death) ~ rcs(bmi,4)&#xD;&#xA;               + systolic +glucose + l_chol + age &#xD;&#xA;               + edu_g2 + smoke_s + l_chol + drink + activity_l+activity_w,&#xD;&#xA;                 data=d, nk=5)&#xD;&#xA;    plot(Predict(fit,bmi), xlab=&quot;bmi&quot;, ylab=&quot;Relative Risk&quot;, lty=1, lwd=2)&#xD;&#xA;&#xD;&#xA;Which creates the following plot **(A)**:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, I want to plot the following graph **(B)**:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;1. How do I set the reference point? (for example: `bmi = 24.21429` as the reference point)&#xD;&#xA;2. I want to add the horizontal line. I tried using `abline(h=1)`, but it did not work.&#xD;&#xA;3. All in all, how do I make the graph look like (B)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MoyLw.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fx5Qx.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4059" PostHistoryTypeId="2" PostId="1906" RevisionGUID="14e4f20f-dddc-4182-9151-bd07903e9092" CreationDate="2016-01-13T14:29:53.797" UserId="2463" Text="Without knowing the internals of Blender, I would say it uses shared normals for the quads, splitting the normals only on edges between the quads, not between the triangles. So your idea of uploading a normal per quad is probably close to the result you are looking for.&#xD;&#xA;&#xD;&#xA;If you load the mesh as quads, you are set. If you are using an old version of OpenGL where quads still exist, you may even be able to use solution 3).&#xD;&#xA;&#xD;&#xA;If you load the mesh as triangles, you will have to figure out which triangles originated in quads. You can likely do this simply by enforcing split normals beyond a fixed angle between adjacent triangles.&#xD;&#xA;&#xD;&#xA;I am not sure there is a simple dynamic solution, where you just render any mesh. You may be able to use the geometry shader to look at the adjacent vertices, but the easiest version is to smooth the normals once before upload." ContentLicense="CC BY-SA 3.0" />
  <row Id="4060" PostHistoryTypeId="5" PostId="1904" RevisionGUID="2928f652-1ca7-42ef-8cf5-fe4858f58813" CreationDate="2016-01-13T21:53:55.230" UserId="231" Comment="Minor tidying" Text="I want to extract colors from images like in Adobe Kuler. When I select colorful or muted corresponding colors are shown. But what is the definition for colorful or muted colors? What do the words &quot;colorful&quot;, &quot;deep&quot; and &quot;muted&quot; refer to? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4061" PostHistoryTypeId="4" PostId="1904" RevisionGUID="2928f652-1ca7-42ef-8cf5-fe4858f58813" CreationDate="2016-01-13T21:53:55.230" UserId="231" Comment="Minor tidying" Text="What does &quot;muted&quot; mean in the context of color?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4062" PostHistoryTypeId="2" PostId="1907" RevisionGUID="0a8aa057-097c-449f-8662-b207512e9a46" CreationDate="2016-01-13T22:52:26.323" UserId="48" Text="In terms of the HSV color space, [&quot;muted&quot; colors are those with lower saturation and/or value](http://designshack.net/articles/graphics/the-evolution-of-flat-design-muted-colors/).&#xD;&#xA;&#xD;&#xA;&quot;Deep&quot; colors are saturated but not too high in value (e.g. [deep red](https://www.google.com/search?q=deep+red&amp;tbm=isch)) while colors with both high saturation and value might be called &quot;bright&quot; (e.g. [bright red](https://www.google.com/search?q=bright+red&amp;tbm=isch)).&#xD;&#xA;&#xD;&#xA;&quot;Colorful&quot; is somewhat more vague; it might mean bright colors, but it also might mean having a range of different hues within an image or palette, such as including complementary colors or analogous colors rather than just variations on a single hue.&#xD;&#xA;&#xD;&#xA;Note that these are general terms that would be understood by any graphic designer or artist, but the specific algorithms that Adobe Kuler attaches to these words are proprietary and only known to Adobe." ContentLicense="CC BY-SA 3.0" />
  <row Id="4069" PostHistoryTypeId="2" PostId="1909" RevisionGUID="0d4a8211-b44d-431d-998f-c0f3c0821f7d" CreationDate="2016-01-14T22:55:11.760" UserId="2372" Text="I am quite new to shadow mapping and graphic programming.&#xD;&#xA;&#xD;&#xA;I've achieve to project the shadow map onto this sphere but I am facing an issue at grazing shadows. This might be a logical issue but I would like to know if it's possible to avoid it or to correct it as I am using the raw depth data of the texture and this issue is breaking my effect.&#xD;&#xA;&#xD;&#xA;Thanks a lot !&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sGOqR.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4070" PostHistoryTypeId="1" PostId="1909" RevisionGUID="0d4a8211-b44d-431d-998f-c0f3c0821f7d" CreationDate="2016-01-14T22:55:11.760" UserId="2372" Text="Shadow map projection issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="4071" PostHistoryTypeId="3" PostId="1909" RevisionGUID="0d4a8211-b44d-431d-998f-c0f3c0821f7d" CreationDate="2016-01-14T22:55:11.760" UserId="2372" Text="|opengl|algorithm|shader|glsl|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4072" PostHistoryTypeId="5" PostId="1909" RevisionGUID="f58e7f93-2657-470d-bc77-057e474712ce" CreationDate="2016-01-15T07:26:34.417" UserId="2372" Comment="added 194 characters in body" Text="I am using Unity but this question might not be proper to this engine.&#xD;&#xA;&#xD;&#xA;I have projected the shadow map onto this sphere but there are grazing shadows. Is it possible to avoid it or to correct it as I am using the raw depth data of the texture.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the pseudo-shader code.&#xD;&#xA;&#xD;&#xA;    uniform sampler2D _ShadowMap;&#xD;&#xA;    float4 shadowCoord : TEXCOORD1;&#xD;&#xA;    &#xD;&#xA;    // vertex shader&#xD;&#xA;    o.shadowCoord = mul(unity_World2Shadow[0], mul(_Object2World, v.vertex));&#xD;&#xA;    &#xD;&#xA;    // fragment shader&#xD;&#xA;    color.rgb = tex2D(_ShadowMap, i.shadowCoord);&#xD;&#xA;    return color;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sGOqR.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4077" PostHistoryTypeId="2" PostId="1911" RevisionGUID="896de9e0-5f0c-4975-8975-030d72b356aa" CreationDate="2016-01-15T22:37:17.597" UserId="2214" Text="What advantages do the outcodes offer in this algorithm ? Do they help in simplifying the algorithm ? Do they decrease the number of calculations ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4078" PostHistoryTypeId="1" PostId="1911" RevisionGUID="896de9e0-5f0c-4975-8975-030d72b356aa" CreationDate="2016-01-15T22:37:17.597" UserId="2214" Text="Outcodes in Cohen-Sutherland Clipping Algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="4079" PostHistoryTypeId="3" PostId="1911" RevisionGUID="896de9e0-5f0c-4975-8975-030d72b356aa" CreationDate="2016-01-15T22:37:17.597" UserId="2214" Text="|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4081" PostHistoryTypeId="5" PostId="1911" RevisionGUID="97d68594-20bd-466d-ba2b-4b658488e77a" CreationDate="2016-01-16T09:46:49.020" UserId="457" Comment="Link to algorithm on Wikpedia" Text="What advantages do the outcodes offer in [this algorithm][1] ? Do they help in simplifying the algorithm ? Do they decrease the number of calculations ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="4082" PostHistoryTypeId="24" PostId="1911" RevisionGUID="97d68594-20bd-466d-ba2b-4b658488e77a" CreationDate="2016-01-16T09:46:49.020" Comment="Proposed by 457 approved by 2214 edit id of 119" ContentLicense="CC BY-SA 3.0" />
  <row Id="4083" PostHistoryTypeId="2" PostId="1912" RevisionGUID="99a1ca9f-a862-42aa-99c2-a7a2d1af0321" CreationDate="2016-01-16T14:05:16.673" UserId="273" Text="I try to implement a position based cloth simulation using hardware tesselation.&#xD;&#xA;This means I want to just upload a control quad to the graphics card and then use tesselation and geometry shading to create the nodes in the cloth.&#xD;&#xA;&#xD;&#xA;This idea follows the paper:&#xD;&#xA;&#xD;&#xA;Huynh, David, &quot;Cloth simulation using hardware tessellation&quot; (2011). Thesis. Rochester Institute of Technology&#xD;&#xA;http://scholarworks.rit.edu/theses/265/&#xD;&#xA;&#xD;&#xA;I know how to use tesselation to create the simulated points.&#xD;&#xA;What I don't know is how to store the computated information into a framebuffer.&#xD;&#xA;&#xD;&#xA;The geometry and also the tesselation evaluation shaders have informations needed for the per-vertex computations. But can they directly write into the framebuffer?&#xD;&#xA;&#xD;&#xA;The fragment-shader I know can write to the framebuffer, but my information would be interpolated and I would no longer know what to write at which position." ContentLicense="CC BY-SA 3.0" />
  <row Id="4084" PostHistoryTypeId="1" PostId="1912" RevisionGUID="99a1ca9f-a862-42aa-99c2-a7a2d1af0321" CreationDate="2016-01-16T14:05:16.673" UserId="273" Text="Per Vertex Computation in OpenGL Tesselation" ContentLicense="CC BY-SA 3.0" />
  <row Id="4085" PostHistoryTypeId="3" PostId="1912" RevisionGUID="99a1ca9f-a862-42aa-99c2-a7a2d1af0321" CreationDate="2016-01-16T14:05:16.673" UserId="273" Text="|opengl|shader|gpgpu|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4087" PostHistoryTypeId="5" PostId="1650" RevisionGUID="42a15393-3acf-4bbb-a5bc-e6c8e8cabc43" CreationDate="2016-01-16T16:32:24.677" UserId="137" Comment="added 1 character in body" Text="Vector has a few different semantics from static arrays. For one it's a struct containing a pointer a capacity and a length (at the very least). That means that `sizeof` will not reflect how much data is actually stored in there (that only works on static arrays).&#xD;&#xA;&#xD;&#xA;If you need to get the size in bytes of the data then you need&#xD;&#xA;&#xD;&#xA;    const UINT vertexBufferSize = sizeof(vertices::value_type) * vertices.size();" ContentLicense="CC BY-SA 3.0" />
  <row Id="4094" PostHistoryTypeId="2" PostId="1914" RevisionGUID="a3b7c978-e60c-4380-b5b5-06ecffe2c7ee" CreationDate="2016-01-18T11:58:50.560" UserId="2463" Text="The outcodes just represent four boolean flags as a bitfield. Codewise it is easier to move a bitfield around than four booleans. Functionality-wise it becomes very easy to check if *any* bits are set (just check if zero), and combining outcodes is as simple as a bitwise OR.&#xD;&#xA;&#xD;&#xA;On a side-note: Since bit-operations are fast, it is not a performance issue that the individual bits need to be extracted (e.g. outcode &amp; BOTTOM)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4097" PostHistoryTypeId="5" PostId="1551" RevisionGUID="89c031a5-d073-4ef5-befa-d2becbf754a1" CreationDate="2016-01-18T13:04:53.083" UserId="209" Comment="Fixed a grammatical error" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  A problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This also included the method of compression but, for our purposes, we are mainly interested in the resulting compressed data and decompression algorithm.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant has, naturally, higher error than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4098" PostHistoryTypeId="2" PostId="1915" RevisionGUID="dcb5923b-ff04-4d99-a4ca-1940f5ea55e5" CreationDate="2016-01-18T13:40:31.857" UserId="2463" Text="One of the downsides to shadowmapping is that you need to offset, or bias, the point used for shadowmap-lookups. This is done in a variety of ways - typically by a constant (shadowmap-depth) distance or based on the slope of the casting triangle. Both of these tend to be done during the shadowmap-rendering pass.&#xD;&#xA;&#xD;&#xA;I think what you need to solve your sphere-problem, is to offset the point you are shading a bit along its surface normal, before doing the shadowmap-lookup. This happens during shading, when sampling the shadowmap, not during shadowmap-rendering. Incidentally it is also part of the Unity standard rendering pipeline, so you can steal it from the shader include-files.&#xD;&#xA;&#xD;&#xA;ref http://www.dissidentlogic.com/old/images/NormalOffsetShadows/GDC_Poster_NormalOffset.png&#xD;&#xA;ref http://www.digitalrune.com/Blog/Post/1765/Shadow-Acne" ContentLicense="CC BY-SA 3.0" />
  <row Id="4099" PostHistoryTypeId="2" PostId="1916" RevisionGUID="835f8b2d-89d0-41bb-bd1a-02ab91a95520" CreationDate="2016-01-18T13:43:31.223" UserId="2489" Text="I've stumbled upon this question on a CG exam:&#xD;&#xA;&#xD;&#xA;&gt; Which of the following techniques/optimizations doesn't apply to ray tracing?&#xD;&#xA;&#xD;&#xA;&gt; A: Back-face culling&#xD;&#xA;&#xD;&#xA;&gt; B: &quot;Shadow-feeler&quot; rays&#xD;&#xA;&#xD;&#xA;&gt; C: Recursive tracing of rays&#xD;&#xA;&#xD;&#xA;&gt; D: Calculation of refraction rays&#xD;&#xA;&#xD;&#xA;&gt; E: None of the above&#xD;&#xA;&#xD;&#xA;B, C and D are obviously false, but what about A? [Here](http://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/single-vs-double-sided-triangle-backface-culling), is says that &quot;with ray tracing, this feature is not as useful. Generally with ray tracing, we want geometry in the scene to cast shadows for example, regardless of the orientation of the object's surface with respect to the ray direction however the backface culling option might still be desired for primary rays&quot;.&#xD;&#xA;&#xD;&#xA;I feel that the question is a bit ambiguous, since back-face culling can be applied to ray tracing but it's not (correct me if I'm wrong) a &quot;native&quot; feature as the other techniques." ContentLicense="CC BY-SA 3.0" />
  <row Id="4100" PostHistoryTypeId="1" PostId="1916" RevisionGUID="835f8b2d-89d0-41bb-bd1a-02ab91a95520" CreationDate="2016-01-18T13:43:31.223" UserId="2489" Text="Is back-face culling considered a technique/optimization of ray tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4101" PostHistoryTypeId="3" PostId="1916" RevisionGUID="835f8b2d-89d0-41bb-bd1a-02ab91a95520" CreationDate="2016-01-18T13:43:31.223" UserId="2489" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4108" PostHistoryTypeId="2" PostId="1919" RevisionGUID="19e5a2dd-b4b2-4ff6-a753-436b6663578a" CreationDate="2016-01-18T23:03:14.117" UserId="2457" Text="http://renderman.pixar.com/view/implementing-a-skin-bssrdf&#xD;&#xA;&#xD;&#xA;In this paper on subsurface scattering, I'm trying to understand how importance sampling is used to compute single scattering.&#xD;&#xA;&#xD;&#xA;It says that the outscattered radiance for the single term, $L_o$, can be rewritten as the product of the exponential falloff in $s'_o$ with another function:&#xD;&#xA;&#xD;&#xA;&gt; $L_o(x_o,\vec{\omega}_o) = \bigg[&#xD;&#xA; L_i(x_i,\vec{\omega}_i)\cfrac{\sigma_s(x_o)F_p(\vec{\omega}'_i \cdotp&#xD;&#xA; \vec{\omega}'_o )}{\sigma_{tc}}e^{-s'_i \sigma_t(x_i)} \bigg]&#xD;&#xA; e^{-s_o\sigma(x_o)}$&#xD;&#xA;&gt; &#xD;&#xA;&gt; By picking samples according to $x \sim \sigma_t e^{-\sigma_t x}$, the&#xD;&#xA;&gt; integration in $L_o$ can be approximated by a summation by applying&#xD;&#xA;&gt; importance sampling. Also by choosing $s'_o =&#xD;&#xA; \cfrac{-\mathbb{log(random())}}{\sigma_{tr}}$, you can sum up all&#xD;&#xA;&gt; contributions without computing the falloff term in $s_o$.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;I understand you can approximate an integral using importance sampling, but I didn't follow how it applies to the rendering equation. Are there any books/blog posts/Youtube videos/etc. that describe how this works in greater detail?&#xD;&#xA;&#xD;&#xA;$E[f(x)]=\int f(x)p(x) = \int f(x)\cfrac{p(x)}{q(x)}q(x) \approx \cfrac{1}{n}\sum \limits_{i=1}^n  f(x_i)\cfrac{p(x_i)}{q(x_i)}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, where does single scattering fit into the general rendering equation?&#xD;&#xA;&#xD;&#xA;$L_{\text{o}}(\mathbf x,\, \omega_{\text{o}}) \,=\, L_e(\mathbf x,\, \omega_{\text{o}}) \ +\, \int_\Omega f_r(\mathbf x,\, \omega_{\text{i}},\, \omega_{\text{o}})\, L_{\text{i}}(\mathbf x,\, \omega_{\text{i}})\, (\omega_{\text{i}}\,\cdot\,\mathbf n)\, \operatorname d \omega_{\text{i}}$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4109" PostHistoryTypeId="1" PostId="1919" RevisionGUID="19e5a2dd-b4b2-4ff6-a753-436b6663578a" CreationDate="2016-01-18T23:03:14.117" UserId="2457" Text="using importance sampling to reduce the error of outscattered radiance" ContentLicense="CC BY-SA 3.0" />
  <row Id="4110" PostHistoryTypeId="3" PostId="1919" RevisionGUID="19e5a2dd-b4b2-4ff6-a753-436b6663578a" CreationDate="2016-01-18T23:03:14.117" UserId="2457" Text="|rendering|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4111" PostHistoryTypeId="5" PostId="1919" RevisionGUID="227cd463-241d-4172-8952-e93cd43613db" CreationDate="2016-01-18T23:26:41.137" UserId="231" Comment="Remove request for off site resources to prevent question being closed" Text="http://renderman.pixar.com/view/implementing-a-skin-bssrdf&#xD;&#xA;&#xD;&#xA;In this paper on subsurface scattering, I'm trying to understand how importance sampling is used to compute single scattering.&#xD;&#xA;&#xD;&#xA;It says that the outscattered radiance for the single term, $L_o$, can be rewritten as the product of the exponential falloff in $s'_o$ with another function:&#xD;&#xA;&#xD;&#xA;&gt; $L_o(x_o,\vec{\omega}_o) = \bigg[&#xD;&#xA; L_i(x_i,\vec{\omega}_i)\cfrac{\sigma_s(x_o)F_p(\vec{\omega}'_i \cdotp&#xD;&#xA; \vec{\omega}'_o )}{\sigma_{tc}}e^{-s'_i \sigma_t(x_i)} \bigg]&#xD;&#xA; e^{-s_o\sigma(x_o)}$&#xD;&#xA;&gt; &#xD;&#xA;&gt; By picking samples according to $x \sim \sigma_t e^{-\sigma_t x}$, the&#xD;&#xA;&gt; integration in $L_o$ can be approximated by a summation by applying&#xD;&#xA;&gt; importance sampling. Also by choosing $s'_o =&#xD;&#xA; \cfrac{-\mathbb{log(random())}}{\sigma_{tr}}$, you can sum up all&#xD;&#xA;&gt; contributions without computing the falloff term in $s_o$.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;I understand you can approximate an integral using importance sampling, but I didn't follow how it applies to the rendering equation. Please could you describe how this works in greater detail?&#xD;&#xA;&#xD;&#xA;$E[f(x)]=\int f(x)p(x) = \int f(x)\cfrac{p(x)}{q(x)}q(x) \approx \cfrac{1}{n}\sum \limits_{i=1}^n  f(x_i)\cfrac{p(x_i)}{q(x_i)}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, where does single scattering fit into the general rendering equation?&#xD;&#xA;&#xD;&#xA;$L_{\text{o}}(\mathbf x,\, \omega_{\text{o}}) \,=\, L_e(\mathbf x,\, \omega_{\text{o}}) \ +\, \int_\Omega f_r(\mathbf x,\, \omega_{\text{i}},\, \omega_{\text{o}})\, L_{\text{i}}(\mathbf x,\, \omega_{\text{i}})\, (\omega_{\text{i}}\,\cdot\,\mathbf n)\, \operatorname d \omega_{\text{i}}$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4112" PostHistoryTypeId="2" PostId="1920" RevisionGUID="e7bf6066-793e-43dc-a310-71e5db4b308e" CreationDate="2016-01-19T07:19:41.533" UserId="110" Text="The paper [Microfacet Models for Refraction through Rough Surfaces][1] (among others) reminds us the following assumptions about the microfacet distribution function D:&#xD;&#xA;&#xD;&#xA; 1. Microfacet density is positive valued&#xD;&#xA; 2. Total microsurface area is at least as large as the corresponding&#xD;&#xA;macrosurface’s area&#xD;&#xA; 3. The (signed) projected area of the microsurface is the&#xD;&#xA;same as the projected area of the macrosurface for any&#xD;&#xA;direction v&#xD;&#xA;&#xD;&#xA;I can see why 1) a distribution density is a positive value, and intuitively believe that 2) means that the total area of sloped microfacets cannot be smaller than their projection.  &#xD;&#xA;However I am not sure to understand the justification for 3). What does the third condition mean mean?&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4113" PostHistoryTypeId="1" PostId="1920" RevisionGUID="e7bf6066-793e-43dc-a310-71e5db4b308e" CreationDate="2016-01-19T07:19:41.533" UserId="110" Text="Reasons of the assumptions for the microfacet distribution function?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4114" PostHistoryTypeId="3" PostId="1920" RevisionGUID="e7bf6066-793e-43dc-a310-71e5db4b308e" CreationDate="2016-01-19T07:19:41.533" UserId="110" Text="|brdf|distribution|function|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4116" PostHistoryTypeId="6" PostId="1904" RevisionGUID="e2ef7435-2def-4187-9621-003076d9fdd8" CreationDate="2016-01-19T13:03:05.540" UserId="231" Comment="edited tags" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4117" PostHistoryTypeId="6" PostId="1895" RevisionGUID="e093efc6-9c24-42d4-a830-64b461970c3a" CreationDate="2016-01-19T13:03:59.860" UserId="231" Comment="edited tags" Text="|rendering|algorithm|geometry|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4118" PostHistoryTypeId="6" PostId="1857" RevisionGUID="68dd59c3-264a-4046-8080-d010751db681" CreationDate="2016-01-19T13:04:21.223" UserId="231" Comment="edited tags" Text="|transformations|vector-graphics|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4119" PostHistoryTypeId="6" PostId="1845" RevisionGUID="129021ce-b103-4872-bd67-c7274b27d341" CreationDate="2016-01-19T13:04:35.450" UserId="231" Comment="edited tags" Text="|efficiency|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4120" PostHistoryTypeId="6" PostId="1799" RevisionGUID="c8f140d2-7456-4a86-9dd0-d420b63fa90c" CreationDate="2016-01-19T13:04:54.080" UserId="231" Comment="edited tags" Text="|raytracing|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4121" PostHistoryTypeId="6" PostId="1626" RevisionGUID="5b963f50-14ab-4101-8541-1c9f5e81f46c" CreationDate="2016-01-19T13:05:40.117" UserId="231" Comment="edited tags" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4122" PostHistoryTypeId="6" PostId="1903" RevisionGUID="5a07b74e-9279-4fdf-aa07-118bf5df81cb" CreationDate="2016-01-19T13:07:28.377" UserId="231" Comment="edited tags" Text="|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4123" PostHistoryTypeId="2" PostId="1921" RevisionGUID="507a8c81-afbc-484d-ab7a-1e45d7eccb98" CreationDate="2016-01-19T13:10:44.163" UserId="2041" Text="It's a geometric assumption like the other two. Consider a flat macrosurface. Its projected area in any direction $v$ is just $v\dot\ \hat N$ times its area (where $\hat N$ is the surface normal). In particular, the case where you're looking at it along the normal is simplest: the projected area is equal to the area of the surface.&#xD;&#xA;&#xD;&#xA;Now split the macrosurface into microfacets. The total area of the microfacets is at least as much (assumption 2), but each 'kink' in the surface bends the normals of the separate microfacets away from the original normal. Whatever the shape of the microfacets, the sum of their projected areas doesn't change. In the case where you're looking along the normal, it's easy to see that the total projected area is the same: the surface would have to get larger or smaller for it to change.&#xD;&#xA;&#xD;&#xA;For any direction, the microfacet has to cover a portion of the original projected area of the surface. Changing the orientation of the microfacet while still filling that portion doesn't change its projected area.&#xD;&#xA;&#xD;&#xA;There's one tricky case, which is where the microfacets overhang each other. In this case, the total area is greater, because some area is covered by more than one microfacet. But in this case, at least one of the microfacets has to end up pointing away from the view direction, back into the surface. In this case, the dot product is negative, so this cancels out the area covered by more than one microfacet. This is why the text is careful to single out that it's the **signed** projected area.&#xD;&#xA;&#xD;&#xA;There's one more tricky case, which is where the microfacets extend past the silhouette of the object. This might happen when you're looking from very glancing angles, or where overhanging facets overhang outside the perimeter of the surface. In this case, the projected area of the microfacets will be greater, violating the third assumption. We don't generally consider this case. Intuitively, it matches up with the fact that techniques like bump-mapping don't change the shape of the silhouette of the object." ContentLicense="CC BY-SA 3.0" />
  <row Id="4124" PostHistoryTypeId="2" PostId="1922" RevisionGUID="38c5e674-617f-43e1-822e-7452f332eb34" CreationDate="2016-01-19T13:12:59.820" UserId="231" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="4125" PostHistoryTypeId="2" PostId="1923" RevisionGUID="358425c7-be56-4108-8d9b-961ac1eea3ee" CreationDate="2016-01-19T13:12:59.820" UserId="231" Text="This tag is scheduled for deletion. It is not to be used." ContentLicense="CC BY-SA 3.0" />
  <row Id="4126" PostHistoryTypeId="2" PostId="1924" RevisionGUID="13fa944b-0e2c-4508-9f99-abac1de676d1" CreationDate="2016-01-19T22:34:16.603" UserId="2237" Text="i wrote a ray tracer that implements various BRDF models (Oren Nayar, Lamber, Torrance Sparrow and so on). &#xD;&#xA;Now I'm trying to implement a BRDF from measured data.&#xD;&#xA;I choose the Cornell database data available here:&#xD;&#xA;&#xD;&#xA;http://www.graphics.cornell.edu/online/measurements/reflectance/spraypaints/index.html&#xD;&#xA;&#xD;&#xA;I want to use them because there's a representation of the data as spectrum with 31 sample (my ray tracer use spectral data for light calculation and then convert them to CIE XYZ and then RGB values for the final image rendering).&#xD;&#xA;&#xD;&#xA;Which is the correct way to use this data?&#xD;&#xA;Which sample technique must be used? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4127" PostHistoryTypeId="1" PostId="1924" RevisionGUID="13fa944b-0e2c-4508-9f99-abac1de676d1" CreationDate="2016-01-19T22:34:16.603" UserId="2237" Text="Ray tracing - BRDF using Cornell measured spectral data" ContentLicense="CC BY-SA 3.0" />
  <row Id="4128" PostHistoryTypeId="3" PostId="1924" RevisionGUID="13fa944b-0e2c-4508-9f99-abac1de676d1" CreationDate="2016-01-19T22:34:16.603" UserId="2237" Text="|raytracing|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4129" PostHistoryTypeId="5" PostId="1924" RevisionGUID="7c7fc642-0e34-4d26-88d5-05c79aae3ecf" CreationDate="2016-01-19T22:39:26.780" UserId="2237" Comment="edited body" Text="I wrote a ray tracer that implements various BRDF models (Oren Nayar, Lamber, Torrance Sparrow and so on). &#xD;&#xA;Now I'm trying to implement a BRDF from measured data.&#xD;&#xA;I choose the Cornell database data available here:&#xD;&#xA;&#xD;&#xA;http://www.graphics.cornell.edu/online/measurements/reflectance/spraypaints/index.html&#xD;&#xA;&#xD;&#xA;I want to use them because there's a representation of the data as spectrum with 31 sample (my ray tracer use spectral data for light calculation and then convert them to CIE XYZ and then RGB values for the final image rendering).&#xD;&#xA;&#xD;&#xA;Which is the correct way to use this data?&#xD;&#xA;Which sample technique must be used? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4130" PostHistoryTypeId="5" PostId="1924" RevisionGUID="2f99ab9a-9173-4fbb-a079-6b41c0c5734e" CreationDate="2016-01-19T23:45:20.283" UserId="2237" Comment="added 188 characters in body" Text="I wrote a ray tracer that implements various BRDF models (Oren Nayar, Lamber, Torrance Sparrow and so on). &#xD;&#xA;Now I'm trying to implement a BRDF from measured data.&#xD;&#xA;I choose the Cornell database data available here:&#xD;&#xA;&#xD;&#xA;http://www.graphics.cornell.edu/online/measurements/reflectance/spraypaints/index.html&#xD;&#xA;&#xD;&#xA;I want to use them because there's a representation of the data as spectrum with 31 sample (my ray tracer use spectral data for light calculation and then convert them to CIE XYZ and then RGB values for the final image rendering).&#xD;&#xA;&#xD;&#xA; - Which is the correct way to use this data?&#xD;&#xA; - Which sample technique must be used? &#xD;&#xA; - **Why phi_out is has all negative value?**&#xD;&#xA; - **Can I calculate phi_out using the same approximation as the one I used in Oren Nayar, so ||View - Normal * (View.dot(normal)||**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4131" PostHistoryTypeId="2" PostId="1925" RevisionGUID="04359201-64bc-4f5c-875e-a4b0777ee7d3" CreationDate="2016-01-20T05:42:51.430" UserDisplayName="user2500" Text="Yes, it's a meaningful stat: GPUs have dedicated triangle setup HW and the rate measured in triangles/GPU clock. Older GPUs (pre tessellation HW) 1/clock was common, because it was very hard to hit this limit in real apps (for the reasons RichieSams mentioned). IIRC AMD's Hawaii was 2/clock - at ~ 1Ghz, 2 Billion/second is the right ballpark. I am less familiar with NV, but will update if I learn details." ContentLicense="CC BY-SA 3.0" />
  <row Id="4132" PostHistoryTypeId="2" PostId="1926" RevisionGUID="f9faffe5-7882-4252-bec0-b8d8cb89a436" CreationDate="2016-01-20T06:15:29.523" UserId="310" Text="The MATLab data file has 3 arrays&#xD;&#xA;&#xD;&#xA; 1. Input vector - aka, the light source (In Cartesian coordinates)&#xD;&#xA; 2. Output vector - aka, the eye (Also in Cartesian coordinates)&#xD;&#xA; 3. Spectral data (spectral data is discretized into 31 bins)&#xD;&#xA;&#xD;&#xA;So input[n], with output[n] results in spectral[n]&#xD;&#xA;&#xD;&#xA;The ASTM file is a flattened version of the MATLab data file, with one major difference: the input and output vectors are in spherical coordinates, specifically the traditional physics notation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The data is defined in the following range:&#xD;&#xA;&#xD;&#xA;For input vector, $\theta$ (theta) varies from $0$ to $\frac{\pi}{2}$, and $\phi$ (phi) is always a constant $0$.&#xD;&#xA;&#xD;&#xA;The output vectors are uniformally distributed across the hemisphere. Since $\phi$ is periodic on $2\pi$, mathematically you can define the bounds of $\phi$  in an infinite number of ways. In this data set they chose:&#xD;&#xA;$$\phi = [-\pi, \pi]$$&#xD;&#xA;but it would be perfectly fine to choose&#xD;&#xA;$$\phi = [0, 2\pi]$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, in order to use the data:&#xD;&#xA;&#xD;&#xA; 1. Since the input vectors only vary over a quarter semi circle ($\theta = [0, \frac{\pi}{2}]$ and $\phi = 0$), not the whole hemisphere, you will need to find the matrix transform that transforms your input vector to the quarter semi circle.&#xD;&#xA; 2. Apply the same transform to the output vector.&#xD;&#xA; 3. Using the transformed input and output vectors, look up the spectral response of the BRDF.&#xD;&#xA;  * I'm not sure of the best way to do this. I defer to others' opinions. I'm sure there is some kind of data structure / algorithm to do the search.&#xD;&#xA;  * The naive way would be to do a O(n) search of all the input and output directions to find the two or three that are closest, then LERP between them.&#xD;&#xA; 4. Use the spectral values as the BRDF in the rendering equation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yQqTA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4133" PostHistoryTypeId="5" PostId="1926" RevisionGUID="a9df7f33-8f34-449f-8d56-eaed5a8ef258" CreationDate="2016-01-20T06:21:05.277" UserId="310" Comment="deleted 5 characters in body" Text="The MATLab data file has 3 arrays&#xD;&#xA;&#xD;&#xA; 1. Input vector - aka, the light source (In Cartesian coordinates)&#xD;&#xA; 2. Output vector - aka, the eye (Also in Cartesian coordinates)&#xD;&#xA; 3. Spectral data (spectral data is discretized into 31 bins)&#xD;&#xA;&#xD;&#xA;So input[n], with output[n] results in spectral[n]&#xD;&#xA;&#xD;&#xA;The ASTM file is a flattened version of the MATLab data file, with one major difference: the input and output vectors are in spherical coordinates, specifically the traditional physics notation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The data is defined in the following range:&#xD;&#xA;&#xD;&#xA;For input vector, $\theta$ (theta) varies from $0$ to $\frac{\pi}{2}$, and $\phi$ (phi) is always a constant $0$.&#xD;&#xA;&#xD;&#xA;The output vectors are uniformally distributed across the hemisphere. Since $\phi$ is periodic on $2\pi$, mathematically you can define the bounds of $\phi$  in an infinite number of ways. In this data set they chose:&#xD;&#xA;$$\phi = [-\pi, \pi]$$&#xD;&#xA;but it would be perfectly fine to choose&#xD;&#xA;$$\phi = [0, 2\pi]$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, in order to use the data:&#xD;&#xA;&#xD;&#xA; 1. Since the input vectors only vary over a quarter circle ($\theta = [0, \frac{\pi}{2}]$ and $\phi = 0$), not the whole hemisphere, you will need to find the matrix transform that transforms your input vector to the quarter circle.&#xD;&#xA; 2. Apply the same transform to the output vector.&#xD;&#xA; 3. Using the transformed input and output vectors, look up the spectral response of the BRDF.&#xD;&#xA;  * I'm not sure of the best way to do this. I defer to others' opinions. I'm sure there is some kind of data structure / algorithm to do the search.&#xD;&#xA;  * The naive way would be to do a O(n) search of all the input and output directions to find the two or three that are closest, then LERP between them.&#xD;&#xA; 4. Use the spectral values as the BRDF in the rendering equation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yQqTA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4134" PostHistoryTypeId="2" PostId="1927" RevisionGUID="e0cc04ab-03ed-442d-907d-9b72b5ec4aad" CreationDate="2016-01-20T18:38:14.507" UserId="2506" Text="I'm using NASA WorldWind to place a rectangle on the Earth ('sphere'). When I drag the rectangle on the sphere, the rectangle changes shape and size but the dimensions should be preserved.&#xD;&#xA;&#xD;&#xA;What is needed to preserve the rectangle's original dimensions when it is dragged along the Earth/sphere?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4135" PostHistoryTypeId="1" PostId="1927" RevisionGUID="e0cc04ab-03ed-442d-907d-9b72b5ec4aad" CreationDate="2016-01-20T18:38:14.507" UserId="2506" Text="Slide a rectangle along a sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="4136" PostHistoryTypeId="3" PostId="1927" RevisionGUID="e0cc04ab-03ed-442d-907d-9b72b5ec4aad" CreationDate="2016-01-20T18:38:14.507" UserId="2506" Text="|rendering|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4137" PostHistoryTypeId="2" PostId="1928" RevisionGUID="c5cc1647-5df8-4c3a-b76b-84ce1e97198d" CreationDate="2016-01-20T22:21:47.147" UserId="2507" Text="I've set up a test project for learning Metal on iOS to do some rendering, but I'm a bit stumped on how to get a prism rotating correctly about its y axis. &#xD;&#xA;&#xD;&#xA;Here is the prism rendered without depth testing so all sides can be seen, so it looks like this part is at least correct:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Tz8CE.png&#xD;&#xA;&#xD;&#xA;These are the vertices:&#xD;&#xA;&#xD;&#xA;    static const float vertexData[] = {&#xD;&#xA;         0.f,  1.f,  0.5f,&#xD;&#xA;         1.f, -1.f,  0.f,&#xD;&#xA;        -1.f, -1.f,  0.f,&#xD;&#xA;    &#xD;&#xA;         0.f,  1.f,  0.5f,&#xD;&#xA;         1.f, -1.f,  1.f,&#xD;&#xA;         1.f, -1.f,  0.f,&#xD;&#xA;&#xD;&#xA;         0.f,  1.f,  0.5f,&#xD;&#xA;        -1.f, -1.f,  1.f,&#xD;&#xA;         1.f, -1.f,  1.f,&#xD;&#xA;&#xD;&#xA;         0.f,  1.f,  0.5f,&#xD;&#xA;        -1.f, -1.f,  0.f,&#xD;&#xA;        -1.f, -1.f,  1.f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;However, when I turn on rotation, this is what happens:&#xD;&#xA;https://www.dropbox.com/s/esg41j3ibncofox/prism_rotate.mov?dl=0&#xD;&#xA;&#xD;&#xA;(The video has depth testing turned on). Why is the prism clipping like that (and/or *what* is it clipping through)? And it's not rotating about it's centre.&#xD;&#xA;&#xD;&#xA;Here are how the MVP matrices are being calculated:&#xD;&#xA;&#xD;&#xA;    static simd::float3 viewEye = {0.f, 0.f, -2.f};&#xD;&#xA;    static simd::float3 viewCenter = {0.f, 0.f, 1.f};&#xD;&#xA;    static simd::float3 viewUp = {0.f, 1.f, 0.f};&#xD;&#xA;    static float fov = 45.f;&#xD;&#xA;    &#xD;&#xA;    CGSize size = self.view.bounds.size;&#xD;&#xA;    Uniforms *uniforms = (Uniforms *)[uniformBuffer contents];&#xD;&#xA;    uniforms-&gt;view = AAPL::lookAt(viewEye, viewCenter, viewUp);&#xD;&#xA;    uniforms-&gt;projection = AAPL::perspective_fov(fov, size.width, size.height, 0.1f, 100.f);&#xD;&#xA;    &#xD;&#xA;    uniforms-&gt;model = AAPL::translate(0.f, 0.f, 12.f) * AAPL::rotate(tAngle, 0.f, 1.f, 0.f);&#xD;&#xA;    tAngle += 0.5f;&#xD;&#xA;&#xD;&#xA;The `transform`, `lookAt`, `rotate`, and `perspective_fov` functions are lifted straight from Apple sample code I used as reference.&#xD;&#xA;&#xD;&#xA;Here is the shader:&#xD;&#xA;&#xD;&#xA;    typedef struct {&#xD;&#xA;        float4 pos [[ position ]];&#xD;&#xA;        half4 color;&#xD;&#xA;        float mod;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    vertex VertexOut basic_vertex(const device packed_float3* vertex_array [[ buffer(0) ]],&#xD;&#xA;                                  const device packed_float3* colors [[ buffer(1) ]],&#xD;&#xA;                                  constant Uniforms&amp; uniform [[ buffer(2) ]],&#xD;&#xA;                                  uint vid [[ vertex_id ]],&#xD;&#xA;                                  uint iid [[ instance_id ]])&#xD;&#xA;    {&#xD;&#xA;        float4 v = float4(vertex_array[vid], 1.f);&#xD;&#xA;        float4x4 mvp_matrix = uniform.projection * uniform.view * uniform.model;&#xD;&#xA;        &#xD;&#xA;        VertexOut out;&#xD;&#xA;        out.pos = v * mvp_matrix;&#xD;&#xA;        uint colorIndex = vid / 3;&#xD;&#xA;        out.color = half4(half3(colors[colorIndex]), 1.f);&#xD;&#xA;        return out;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    fragment half4 basic_fragment(VertexOut f [[ stage_in ]]) {&#xD;&#xA;        return f.color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Any help/tips would be appreciated!" ContentLicense="CC BY-SA 3.0" />
  <row Id="4138" PostHistoryTypeId="1" PostId="1928" RevisionGUID="c5cc1647-5df8-4c3a-b76b-84ce1e97198d" CreationDate="2016-01-20T22:21:47.147" UserId="2507" Text="Why is rotating this prism in iOS Metal not rendering correctly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4139" PostHistoryTypeId="3" PostId="1928" RevisionGUID="c5cc1647-5df8-4c3a-b76b-84ce1e97198d" CreationDate="2016-01-20T22:21:47.147" UserId="2507" Text="|shader|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4140" PostHistoryTypeId="2" PostId="1929" RevisionGUID="a55d287d-931c-408b-97b9-ccee0b78e7f9" CreationDate="2016-01-21T00:41:04.463" UserId="2507" Text="The problem was in the shader, and I had the order of multiplication wrong with the MVP matrix. &#xD;&#xA;&#xD;&#xA;So this: &#xD;&#xA;&#xD;&#xA;    out.pos = v * mvp_matrix;&#xD;&#xA;&#xD;&#xA;should be: &#xD;&#xA;&#xD;&#xA;    out.pos = mvp_matrix * v;&#xD;&#xA;&#xD;&#xA;For whatever reason, I'm used to dealing with row vectors and had myself convinced the problem was due to the matrices themselves and the clip region.." ContentLicense="CC BY-SA 3.0" />
  <row Id="4141" PostHistoryTypeId="6" PostId="1928" RevisionGUID="415de67a-2e3c-4080-8c32-50bbd7d7e95a" CreationDate="2016-01-21T06:22:40.970" UserId="127" Comment="Edited tags" Text="|shader|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4142" PostHistoryTypeId="2" PostId="1930" RevisionGUID="63b5f0b3-ff9d-4511-98de-20fec37e2c83" CreationDate="2016-01-21T06:38:18.427" UserId="197" Text="I would exclude (A) for the following reasons:&#xD;&#xA;&#xD;&#xA;1. In any modern ray-tracer, the acceleration structure (BVH, k-d tree, etc) holding your geometry is the primary source of culling. The final list of primitives to trace for a given ray may include non-visible triangles, but ideally there should be very few with good acceleration structures.&#xD;&#xA;&#xD;&#xA;2. Ray tracers support many more primitives than just triangles. (How do you back-face cull a sphere?)&#xD;&#xA;&#xD;&#xA;The following problems with back-face culling in general are also more relevant to ray tracing:&#xD;&#xA;&#xD;&#xA;1. Transparent materials (such as glass) will make certain objects render incorrectly with back-face culling applied.&#xD;&#xA;&#xD;&#xA;2. Non-closed meshes (like plants) need to render the back-facing triangles." ContentLicense="CC BY-SA 3.0" />
  <row Id="4143" PostHistoryTypeId="2" PostId="1931" RevisionGUID="bd867940-b132-4d79-8d4c-a6924226bfad" CreationDate="2016-01-21T07:44:20.010" UserId="48" Text="In general, the idea of importance sampling is to distribute samples in a way that matches the function being integrated (or more practically, matching some factor in it). This reduces the variance of the output values, allowing the Monte Carlo integration to converge faster.&#xD;&#xA;&#xD;&#xA;In volume scattering, when a medium is homogeneous, we have the [Beer–Lambert law](https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law), which states that the transmittance falls off exponentially with depth. That's the source of factors like $e^{-\sigma x}$ in those equations. So when raymarching through a medium, the regions closer to the start of the ray generally contribute more light to the output, while the farther regions have more of their light absorbed along the way.&#xD;&#xA;&#xD;&#xA;So, if you sample points along the ray from an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution), the samples cluster toward the closer, more important regions. Then you just have to evaluate the scattering at those points and average over them.&#xD;&#xA;&#xD;&#xA;BTW, importance sampling in the context of *surface* scattering is explained pretty well by [this answer](http://computergraphics.stackexchange.com/a/1667/48) to another question.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;On your second question, &quot;where does single scattering fit into the general rendering equation?&quot;, well, it doesn't! What people call the &quot;general rendering equation&quot; actually only includes surface scattering, not volume scattering. So it's not really that &quot;general&quot;. A general rendering equation for volume scattering might look something like:&#xD;&#xA;&#xD;&#xA;$$ \nabla_\omega \, L(x, \omega) = \sigma_e(x) L_e(x, \omega) - \sigma_t(x) L(x, \omega) + \sigma_s(x) \int p(\omega, \omega') \, L(x, \omega') \, d\omega' $$&#xD;&#xA;&#xD;&#xA;This states that the derivative of radiance as you move along a ray is given by the sum of emitted light from the volume, minus extinction, plus in-scattering.&#xD;&#xA;&#xD;&#xA;To combine surface and volume scattering, we usually just say that the surface version of the equation applies at points on surfaces, and the volume version applies everywhere else." ContentLicense="CC BY-SA 3.0" />
  <row Id="4144" PostHistoryTypeId="5" PostId="281" RevisionGUID="15d32ba7-728f-456a-a609-7c4246a6a852" CreationDate="2016-01-21T10:12:02.363" UserId="137" Comment="added 13 characters in body" Text="On modern hardware if all invocations in a group follow the same path then the unused path doesn't get evaluated.&#xD;&#xA;&#xD;&#xA;in pseudo code:&#xD;&#xA;&#xD;&#xA;    if(cond){&#xD;&#xA;       res = ...&#xD;&#xA;    }else{&#xD;&#xA;       res = ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;becomes&#xD;&#xA;&#xD;&#xA;    if(anyInvocationARB(cond)){&#xD;&#xA;        res1 = ...&#xD;&#xA;    }&#xD;&#xA;    if(anyInvocationARB(!cond)){&#xD;&#xA;        res2 = ...&#xD;&#xA;    }&#xD;&#xA;    res = cond?res1:res2;&#xD;&#xA;&#xD;&#xA;Where `anyInvocationARB` will be true if any invocation of the shader will have true as `cond` (from the opengl extension [ARB_shader_group_vote][1]). &#xD;&#xA;&#xD;&#xA;If cond is derivable from uniforms alone then the driver may optimize and evaluate the condition before starting the render and replace the if with a goto to the correct branch. OpenGL has a feature called uniform subroutines that makes it explicit.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/registry/specs/ARB/shader_group_vote.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="4145" PostHistoryTypeId="2" PostId="1932" RevisionGUID="916692e0-a1ec-4257-b86b-5869974740c3" CreationDate="2016-01-21T12:07:46.430" UserId="2463" Text="If I understand you correctly, the problem could be defined as the (edge) intersection of a cube with a sphere. In that case, you could shade the edges by calculating the distance to the edges of the cube.&#xD;&#xA;&#xD;&#xA;    //note: from http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;    float udBox( vec3 p, vec3 b )&#xD;&#xA;    {&#xD;&#xA;      return length(max(abs(p)-b,0.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Aligning the cube poses another &quot;interesting&quot; issue - you probably want to use the sphere-normal and screen-up to generate a basis." ContentLicense="CC BY-SA 3.0" />
  <row Id="4146" PostHistoryTypeId="2" PostId="1933" RevisionGUID="645855af-ed4a-42f9-a4f9-6254a8e858e4" CreationDate="2016-01-21T12:20:38.830" UserId="273" Text="Based on the comment of &quot;ratchet freak&quot; I researched Transform Feedback Buffers and solved my problem that way.&#xD;&#xA;&#xD;&#xA;I now generate the simulated points on the CPU and put them into a VertexBufferObject.&#xD;&#xA;I generate a second VBO for the points (along with some others for velocity).&#xD;&#xA;The connectivity of the cloth is given as an vertex-attribute in ivec4.&#xD;&#xA;&#xD;&#xA;Using the transform feedback buffers and a Double-buffering trick using the two VBOs i can always read from the last step (using the connectivity info) and write to another buffer. This is in order to solve problems with concurrency. &#xD;&#xA;&#xD;&#xA;The calculations are done in the vertex-shader as GL_POINTS.&#xD;&#xA;Binding the output of the first shader into another regular shader using additional index-buffer to generate triangles I can without trouble render the cloth any way I want.&#xD;&#xA;&#xD;&#xA;This idea follows the transform feedback buffer example made in the book &quot;OpenGL Superbible&quot; http://www.openglsuperbible.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="4148" PostHistoryTypeId="2" PostId="1934" RevisionGUID="f8d29bfc-ce09-4de4-a99b-cc3ba03a79cc" CreationDate="2016-01-21T13:11:14.720" UserId="361" Text="I'm am currently looking into [glTF][1] to use as a transfer format for my WebGL project. I already have the geometries I wish to render on my WebGL client available as preprocessed vertex and index buffers (and color buffers, but let's ignore them for now).&#xD;&#xA;&#xD;&#xA;For example:&#xD;&#xA;&#xD;&#xA;    [       // vertex buffer&#xD;&#xA;      0,0,0,&#xD;&#xA;      0,1,0,&#xD;&#xA;      1,0,0,&#xD;&#xA;      1,1,0,&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;And to draw simple `LINES`:&#xD;&#xA;&#xD;&#xA;    [       // index buffer&#xD;&#xA;      0,2,&#xD;&#xA;      2,4,&#xD;&#xA;      4,0,&#xD;&#xA;      0,1,&#xD;&#xA;      1,4,&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;I wonder how to create glTF files containing these buffers? Is this possible?&#xD;&#xA;&#xD;&#xA;I want to avoid using COLLADA and [COLLADA2GLTF][2] as this would only add an additional step and might just bloat the resulting glTF files.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/master/specification/README.md&#xD;&#xA;  [2]: https://github.com/KhronosGroup/glTF/wiki/converter" ContentLicense="CC BY-SA 3.0" />
  <row Id="4149" PostHistoryTypeId="1" PostId="1934" RevisionGUID="f8d29bfc-ce09-4de4-a99b-cc3ba03a79cc" CreationDate="2016-01-21T13:11:14.720" UserId="361" Text="Is it possible to create minimal glTF files with vertex and index buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4150" PostHistoryTypeId="3" PostId="1934" RevisionGUID="f8d29bfc-ce09-4de4-a99b-cc3ba03a79cc" CreationDate="2016-01-21T13:11:14.720" UserId="361" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4151" PostHistoryTypeId="5" PostId="1927" RevisionGUID="a9a77d59-dc81-4258-a76f-818e44edd5c6" CreationDate="2016-01-21T15:39:20.490" UserId="2506" Comment="added 752 characters in body" Text="I'm using NASA WorldWind to place a rectangle on the Earth ('sphere'). When I drag the rectangle on the sphere, the rectangle changes shape and size but the dimensions should be preserved.&#xD;&#xA;&#xD;&#xA;What is needed to preserve the rectangle's original dimensions when it is dragged along the Earth/sphere?&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;It looks like most of the code in use was copied from this example: http://worldwind31.arc.nasa.gov/svn/trunk/WorldWind/src/gov/nasa/worldwind/util/BasicDragger.java&#xD;&#xA;&#xD;&#xA;The line of code in the example that confuses me the most is&#xD;&#xA;&#xD;&#xA;    double y = event.getMouseEvent().getComponent().getSize().height -&#xD;&#xA;                                           this.dragRefObjectPoint.y + dy - 1;&#xD;&#xA;&#xD;&#xA;The resulting behavior is the 'rectangle' that is mapped to the globe changes shape and size.&#xD;&#xA;&#xD;&#xA;I also want to point out my experience with computer graphics and NASA worldwind are limited. I'm especially rusty on linear algebra and very weak with geomtery. I'd appreciate suggestions on resources (outside of the obvious NASA WorldWind reference)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4152" PostHistoryTypeId="2" PostId="1935" RevisionGUID="e79a9bab-2815-402f-bab0-9ef0b60239e5" CreationDate="2016-01-21T17:47:18.833" UserId="2214" Text="Is it possible that low pass filtering can be applied to Ray tracing ? &#xD;&#xA;&#xD;&#xA;My guess is that since after the algorithm runs we have an image then low pass filtering helps in order to prevent aliasing from happening. Yet, I am not sure about this. Can someone elaborate on that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4153" PostHistoryTypeId="1" PostId="1935" RevisionGUID="e79a9bab-2815-402f-bab0-9ef0b60239e5" CreationDate="2016-01-21T17:47:18.833" UserId="2214" Text="Low Pass filtering" ContentLicense="CC BY-SA 3.0" />
  <row Id="4154" PostHistoryTypeId="3" PostId="1935" RevisionGUID="e79a9bab-2815-402f-bab0-9ef0b60239e5" CreationDate="2016-01-21T17:47:18.833" UserId="2214" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4155" PostHistoryTypeId="2" PostId="1936" RevisionGUID="dca687e4-0bd7-4724-8563-7db914cbf90e" CreationDate="2016-01-22T06:19:21.960" UserDisplayName="user2500" Text="You can run a low pass filter on the final image, which will reduce the aliasing but also blur the image - to then reduce blurring, you would have to scale it down - effectively implementing supersampling with a regular sample pattern (and a filter other than a pixel sized box). Explicitly implementing supersampling with jittering is a standard technique to antialias. Classic paper: http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/cook86_sampling.pdf." ContentLicense="CC BY-SA 3.0" />
  <row Id="4156" PostHistoryTypeId="2" PostId="1937" RevisionGUID="4871b380-fc42-4567-a8b3-001d1baa7653" CreationDate="2016-01-22T06:50:48.907" UserId="2448" Text="I'm currently working working on a unbiased path tracer. To test how accurate it is. I created a scene in my path tracer and LuxRender then compare the rendered image. I found that the shadow in the image that my path tracer rendered is too dark. Why? Any possible reason?&#xD;&#xA;&#xD;&#xA;Also, I have implemented Gamma 2.2 in my renderer. So it won't be the issue of gamma correction.&#xD;&#xA;&#xD;&#xA;Here are the rendering result from LuxRender and my own renderer.(Please ignore the back triangle(light source) in Lux. It's how Lux behaves.)&#xD;&#xA;&#xD;&#xA;Scene Rendered by LuxRender (PBRT gives me the same result)&lt;br&gt;&#xD;&#xA;Renderer: Sampler, Sampler : metropolis, (Other settings are defalut)&#xD;&#xA;[![Scene Rendered by LuxRender][1]][1]&#xD;&#xA;&#xD;&#xA;The same scene rendered my by renderer. Note the scene is a bit darker and shadow is way too dark.&#xD;&#xA;[![Same Scene rendered my by renderer][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tsd5v.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A2knm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4157" PostHistoryTypeId="1" PostId="1937" RevisionGUID="4871b380-fc42-4567-a8b3-001d1baa7653" CreationDate="2016-01-22T06:50:48.907" UserId="2448" Text="Shadow appears to be too dark in my ray tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="4158" PostHistoryTypeId="3" PostId="1937" RevisionGUID="4871b380-fc42-4567-a8b3-001d1baa7653" CreationDate="2016-01-22T06:50:48.907" UserId="2448" Text="|raytracing|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4159" PostHistoryTypeId="5" PostId="1937" RevisionGUID="b0010e23-05c5-4c6f-80ad-144025124a84" CreationDate="2016-01-22T06:58:18.047" UserId="2448" Comment="added 88 characters in body" Text="I'm currently working working on a unbiased path tracer. To test how accurate it is. I created a scene in my path tracer and LuxRender then compare the rendered image. I found that the shadow in the image that my path tracer rendered is too dark. Why? Any possible reason?&#xD;&#xA;&#xD;&#xA;Also, I have implemented Gamma 2.2 in my renderer. So it won't be the issue of gamma correction. And, recursive path tracing IS enabled. both image are rendered in global illumination.&#xD;&#xA;&#xD;&#xA;Here are the rendering result from LuxRender and my own renderer.(Please ignore the back triangle(light source) in Lux. It's how Lux behaves.)&#xD;&#xA;&#xD;&#xA;Scene Rendered by LuxRender (PBRT gives me the same result)&lt;br&gt;&#xD;&#xA;Renderer: Sampler, Sampler : metropolis, (Other settings are defalut)&#xD;&#xA;[![Scene Rendered by LuxRender][1]][1]&#xD;&#xA;&#xD;&#xA;The same scene rendered my by renderer. Note the scene is a bit darker and shadow is way too dark.&#xD;&#xA;[![Same Scene rendered my by renderer][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tsd5v.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A2knm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4160" PostHistoryTypeId="2" PostId="1938" RevisionGUID="2cab1bb2-9feb-439f-8dc0-a9b56e51a953" CreationDate="2016-01-22T10:47:42.003" UserId="385" Text="Low-pass filtering is a classic tool from signal theory that will effectively remove noise, as you suggested, but will also cancel out desired high-frequency information in the image such as sharp edges. The image will look blurry.&#xD;&#xA;&#xD;&#xA;Post-filtering Monte Carlo rendering results is an open field of research and many advances have been made over the years, and overview of which can be found in the *Denoising Your Monte Carlo Renders: Recent Advances in Image-Space Adaptive Sampling and Reconstruction* SIGGRAPH Course [here][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://cgg.unibe.ch/publications/denoising-your-monte-carlo-renders" ContentLicense="CC BY-SA 3.0" />
  <row Id="4161" PostHistoryTypeId="2" PostId="1939" RevisionGUID="10d49f56-fa92-4a06-8e38-5fb96aa7a32f" CreationDate="2016-01-22T13:10:24.747" UserId="2520" Text="I writing the this video process app which requires the each video frame to be processed such that parts of the video are enlarged. As a reference, one of the snapchat lens filter enlarges the eyes of a person in the video. This is the exact effect I want to achieve. Which mage processing algorithm should I use? Are there any good sites or books for this kind of topics?&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 3.0" />
  <row Id="4162" PostHistoryTypeId="1" PostId="1939" RevisionGUID="10d49f56-fa92-4a06-8e38-5fb96aa7a32f" CreationDate="2016-01-22T13:10:24.747" UserId="2520" Text="How enlarge parts of a video like snapchat lens filter" ContentLicense="CC BY-SA 3.0" />
  <row Id="4163" PostHistoryTypeId="3" PostId="1939" RevisionGUID="10d49f56-fa92-4a06-8e38-5fb96aa7a32f" CreationDate="2016-01-22T13:10:24.747" UserId="2520" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4165" PostHistoryTypeId="5" PostId="1936" RevisionGUID="f3103ada-3440-4311-a415-350b680d5ab6" CreationDate="2016-01-22T14:28:31.440" UserDisplayName="user2500" Comment="deleted 245 characters in body" Text="David Kuri's answer yields a modern approach, but a simple-to-implement solution is to explicitly supersample with jittering. Classic paper: http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/cook86_sampling.pdf." ContentLicense="CC BY-SA 3.0" />
  <row Id="4166" PostHistoryTypeId="2" PostId="1940" RevisionGUID="2442e686-e4ec-42a1-9485-9886474f7577" CreationDate="2016-01-22T14:41:41.680" UserId="2524" Text="I'm drawing a contour map representing gravity. &#xD;&#xA;&#xD;&#xA;The algorithm is:&#xD;&#xA;&#xD;&#xA;For each point on the screen (1 pixel per point) I calculate the gravitational pull for each object and combine (using Newtons law of universal gravitation) where M1 is a unit point mass.&#xD;&#xA;&#xD;&#xA;Next I get the min and max values and create a palette of 10 colors scaled over this range.&#xD;&#xA;&#xD;&#xA;I then generate a texture from this data.&#xD;&#xA;&#xD;&#xA;For resolutions such as 1024 * 768 or greater this is expensive (takes &gt; 1sec)&#xD;&#xA;&#xD;&#xA;I'd like to be able to move the masses and see the contour map change in real time.&#xD;&#xA;&#xD;&#xA;Any suggestions on how to optimise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4167" PostHistoryTypeId="1" PostId="1940" RevisionGUID="2442e686-e4ec-42a1-9485-9886474f7577" CreationDate="2016-01-22T14:41:41.680" UserId="2524" Text="Optimise drawing contour maps representing gravity" ContentLicense="CC BY-SA 3.0" />
  <row Id="4168" PostHistoryTypeId="3" PostId="1940" RevisionGUID="2442e686-e4ec-42a1-9485-9886474f7577" CreationDate="2016-01-22T14:41:41.680" UserId="2524" Text="|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4169" PostHistoryTypeId="2" PostId="1941" RevisionGUID="5a87b7a2-d5f6-40f9-bbd2-7e7b0b1753a1" CreationDate="2016-01-22T14:59:56.743" UserId="2521" Text="There are several offerings by GPU vendors like AMD's [CodeXL](http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/) or NVIDIA's [nSight](https://www.nvidia.com/object/nsight.html) which allow stepping through shaders but are tied to the respective vendor's hardware.&#xD;&#xA;&#xD;&#xA;Let me note that, although they are available under Linux, I always had very little success with using them there. I can't comment on the situation under Windows.&#xD;&#xA;&#xD;&#xA;The option which I have come to use recently, is to modularize my shader code via [`#includes`](https://computergraphics.stackexchange.com/questions/100/sharing-code-between-multiple-glsl-shaders) and restrict the included code to a common subset of GLSL and C++&amp;[glm](http://glm.g-truc.net).&#xD;&#xA;&#xD;&#xA;When I hit a problem I try to reproduce it on another device to see if the problem is the same which hints at a logic error (instead of a driver problem/undefined behavior). There is also the chance of passing wrong data to the GPU (e.g. by incorrectly bound buffers etc.) which I usually rule out either by output debugging like in [cifz answer](https://computergraphics.stackexchange.com/a/101) or by inspecting the data via [apitrace](https://apitrace.github.io/).&#xD;&#xA;&#xD;&#xA;When it is a logic error I try to rebuild the situation from the GPU on CPU by calling the included code on CPU with the same data.&#xD;&#xA;Then I can step through it on CPU.&#xD;&#xA;&#xD;&#xA;Building upon the modularity of the code you can also try to write unittest for it and compare the results between a GPU run and a CPU run. However, you have to be aware that there are corner cases where C++ might behave differently than GLSL, thus giving you false positives in these comparisons.&#xD;&#xA;&#xD;&#xA;Finally, when you can't reproduce the problem on another device, you can only start to dig down where the difference comes from. Unittests might help you to narrow down where that happens but in the end you will probably need to write out additional debug information from the shader like in [cifz answer](https://computergraphics.stackexchange.com/a/101).&#xD;&#xA;&#xD;&#xA;And to give you an overview here is a flowchart of my debugging process:&#xD;&#xA;[![Flow chart of the procedure described in the text][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YLv6u.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4170" PostHistoryTypeId="5" PostId="1937" RevisionGUID="d2802f55-81eb-454f-99c5-89647af3ebaa" CreationDate="2016-01-22T15:03:56.907" UserId="2448" Comment="Edit in some code" Text="I'm currently working working on a unbiased path tracer. To test how accurate it is. I created a scene in my path tracer and LuxRender then compare the rendered image. I found that the shadow in the image that my path tracer rendered is too dark. Why? Any possible reason?&#xD;&#xA;&#xD;&#xA;Also, I have implemented Gamma 2.2 in my renderer. So it won't be the issue of gamma correction. And, recursive path tracing IS enabled. both image are rendered in global illumination.&#xD;&#xA;&#xD;&#xA;Here are the rendering result from LuxRender and my own renderer.(Please ignore the back triangle(light source) in Lux. It's how Lux behaves.)&#xD;&#xA;&#xD;&#xA;---- Edit ----&lt;br&gt;&#xD;&#xA;Edit: Here are the trace() function(get radiance)&lt;br&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c++ --&gt;&#xD;&#xA;&#xD;&#xA;    float4 Renderer::trace(Ray ray, Scene* scene)&#xD;&#xA;	{&#xD;&#xA;		const int BOUNCE_DEPTH = getBounceDepth();&#xD;&#xA;		//Russian roulette: starting at depth 5&#xD;&#xA;		const int RUSSIAN_ROULETTE_START_DEPTH = 16;&#xD;&#xA;		const float FACTOR_CUT_OFF = 1e-5;&#xD;&#xA;&#xD;&#xA;		float4 factor(1.0f,1.0f,1.0f,1.0f);&#xD;&#xA;		float4 renderedColor;&#xD;&#xA;		Ray currentRay = ray;&#xD;&#xA;		float4 lastNormal = ray.direction;&#xD;&#xA;		float rrFactor = 1.0f;&#xD;&#xA;&#xD;&#xA;		for(int i=0;i&lt;BOUNCE_DEPTH||BOUNCE_DEPTH &lt; 0;i++)//To ignore bounce limit. set bounceDepth to -1&#xD;&#xA;		{&#xD;&#xA;			if(i &gt;= RUSSIAN_ROULETTE_START_DEPTH)&#xD;&#xA;			{&#xD;&#xA;				const float stopProbability = 0.1f;&#xD;&#xA;				if(((float)rand()/RAND_MAX) &lt; (1.0-stopProbability))&#xD;&#xA;					break;&#xD;&#xA;			vrrFactor *= 1.0f/(1.0f-stopProbability);&#xD;&#xA;			//cout &lt;&lt; rrFactor &lt;&lt; endl;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		//stop bouncing if factor is too small.&#xD;&#xA;		//This is a biased method. Remove this if you want unbiased rendering&#xD;&#xA;		if(factor.x + factor.y + factor.z &lt;= FACTOR_CUT_OFF)&#xD;&#xA;			break;&#xD;&#xA;&#xD;&#xA;		RayHit hit = acclerator-&gt;raycast(currentRay);&#xD;&#xA;		if(hit.distance &gt; 0)&#xD;&#xA;		{&#xD;&#xA;			int index = hit.index;&#xD;&#xA;			Triangle emit(scene-&gt;emitColor[scene-&gt;indices[index*3]],&#xD;&#xA;				scene-&gt;emitColor[scene-&gt;indices[index*3+1]],&#xD;&#xA;				scene-&gt;emitColor[scene-&gt;indices[index*3+2]]);&#xD;&#xA;			Triangle triangle(scene-&gt;vertices[scene-&gt;indices[index*3]],&#xD;&#xA;				scene-&gt;vertices[scene-&gt;indices[index*3+1]],&#xD;&#xA;				scene-&gt;vertices[scene-&gt;indices[index*3+2]]);&#xD;&#xA;			Triangle reflectColor(scene-&gt;reflectColor[scene-&gt;indices[index*3]],&#xD;&#xA;				scene-&gt;reflectColor[scene-&gt;indices[index*3+1]],&#xD;&#xA;				scene-&gt;reflectColor[scene-&gt;indices[index*3+2]]);&#xD;&#xA;&#xD;&#xA;			//if(i &gt; 1)//Only collect indirect lighting&#xD;&#xA;			renderedColor += factor*emit.interpolation(hit.u,hit.v)*rrFactor;&#xD;&#xA;			factor *= reflectColor.interpolation(hit.u,hit.v);&#xD;&#xA;&#xD;&#xA;			//randomly sample on a hemisphere&#xD;&#xA;			Ray reflecRay;&#xD;&#xA;			reflecRay = createRandomReflect(currentRay, triangle,&#xD;&#xA;				currentRay.origin + normalize(currentRay.direction)*hit.distance);&#xD;&#xA;&#xD;&#xA;			float4 triangleNormal = triangle.normal();&#xD;&#xA;			if(dot(triangleNormal,currentRay.direction) &lt; 0)&#xD;&#xA;				triangleNormal = -triangleNormal;&#xD;&#xA;&#xD;&#xA;			currentRay = reflecRay;&#xD;&#xA;			lastNormal = triangle.normal();&#xD;&#xA;			if(dot(currentRay.direction,lastNormal) &lt; 0)&#xD;&#xA;				lastNormal = -lastNormal;&#xD;&#xA;			factor *= dot(normalize(currentRay.direction),lastNormal);//Difduse BRDF&#xD;&#xA;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;			break;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return renderedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;And the render() function (generate image)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c++ --&gt;&#xD;&#xA;&#xD;&#xA;    void Renderer::render(Scene* scene)&#xD;&#xA;	{&#xD;&#xA;		//srand(5000);&#xD;&#xA;		memset(frameBuffer,0,bufferWidth*bufferHeight*sizeof(float4));&#xD;&#xA;		int pixelCount = bufferWidth*bufferHeight;&#xD;&#xA;&#xD;&#xA;		high_resolution_clock::time_point t1 = high_resolution_clock::now();&#xD;&#xA;&#xD;&#xA;		int renderIndex = 0;&#xD;&#xA;&#xD;&#xA;		acclerator-&gt;setScene(scene);&#xD;&#xA;		acclerator-&gt;build();&#xD;&#xA;&#xD;&#xA;		const int SAMPLE_NUM = getSampleNum();&#xD;&#xA;&#xD;&#xA;		float4 origin = scene-&gt;camera.position&#xD;&#xA;			+ 2.0f*scene-&gt;camera.right/(float)scene-&gt;camera.width&#xD;&#xA;			+ 2.0f*scene-&gt;camera.up/(float)scene-&gt;camera.height;&#xD;&#xA;&#xD;&#xA;		#pragma omp parallel for schedule(dynamic)&#xD;&#xA;		for(int i=0;i&lt;pixelCount;i++)&#xD;&#xA;		{&#xD;&#xA;			float4 renderedColor = float4(0.0f,0.0f,0.0f,0.0f);&#xD;&#xA;			//Create camera ray&#xD;&#xA;			int x = i % bufferWidth;&#xD;&#xA;			int y = i / bufferWidth;&#xD;&#xA;&#xD;&#xA;			float4 rayVec = (x/(float)scene-&gt;camera.width-0.5f)*scene-&gt;camera.right*scene-&gt;camera.pixelAspectRatio&#xD;&#xA;				+ (0.5f-y/(float)scene-&gt;camera.height)*scene-&gt;camera.up&#xD;&#xA;				+ scene-&gt;camera.direction;&#xD;&#xA;			for(int j=0;j&lt;SAMPLE_NUM;j++)&#xD;&#xA;			{&#xD;&#xA;				Ray ray(origin, rayVec);&#xD;&#xA;				renderedColor += trace(ray,scene);&#xD;&#xA;			}&#xD;&#xA;			renderedColor /= (float)SAMPLE_NUM;&#xD;&#xA;&#xD;&#xA;			//simple gamma correction&#xD;&#xA;			const float gamma = 2.2;&#xD;&#xA;			const float inversedGamma = 1.0f/gamma;&#xD;&#xA;			float4 correctedColor = pow(renderedColor,float4(inversedGamma,inversedGamma,inversedGamma,0));&#xD;&#xA;			((float4*)frameBuffer)[i] = correctedColor;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;			#pragma omp atomic&#xD;&#xA;				renderIndex++;&#xD;&#xA;&#xD;&#xA;			#pragma omp critical&#xD;&#xA;			if(renderIndex%500 == 0)&#xD;&#xA;				cout &lt;&lt; &quot;Rendering &quot; &lt;&lt; renderIndex &lt;&lt; &quot;/&quot; &lt;&lt; pixelCount &lt;&lt; &quot;. &quot; &lt;&lt; (float)renderIndex*100.0/pixelCount &lt;&lt; &quot;\r&quot;;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		high_resolution_clock::time_point t2 = high_resolution_clock::now();&#xD;&#xA;		double elapsed = duration_cast&lt;duration&lt;double&gt;&gt;( t2 - t1 ).count();&#xD;&#xA;		cout &lt;&lt; endl &lt;&lt; &quot;elapsed: &quot; &lt;&lt; elapsed &lt;&lt; &quot; ,&quot; &lt;&lt; pixelCount*SAMPLE_NUM/elapsed/1000/1000 &lt;&lt; &quot; MSamples/s&quot;&lt;&lt; endl;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;---- End Edit ----&lt;br&gt;&#xD;&#xA;&#xD;&#xA;Scene Rendered by LuxRender (PBRT gives me the same result)&lt;br&gt;&#xD;&#xA;Renderer: Sampler, Sampler : metropolis, (Other settings are defalut)&#xD;&#xA;[![Scene Rendered by LuxRender][1]][1]&#xD;&#xA;&#xD;&#xA;The same scene rendered my by renderer. Note the scene is a bit darker and shadow is way too dark.&#xD;&#xA;[![Same Scene rendered my by renderer][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tsd5v.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A2knm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4171" PostHistoryTypeId="5" PostId="1937" RevisionGUID="58a25fb9-2326-4739-81fb-9a9909b6fba4" CreationDate="2016-01-22T15:12:34.297" UserId="2448" Comment="added 1 character in body" Text="I'm currently working working on a unbiased path tracer. To test how accurate it is. I created a scene in my path tracer and LuxRender then compare the rendered image. I found that the shadow in the image that my path tracer rendered is too dark. Why? Any possible reason?&#xD;&#xA;&#xD;&#xA;Also, I have implemented Gamma 2.2 in my renderer. So it won't be the issue of gamma correction. And, recursive path tracing IS enabled. both image are rendered in global illumination.&#xD;&#xA;&#xD;&#xA;Here are the rendering result from LuxRender and my own renderer.(Please ignore the back triangle(light source) in Lux. It's how Lux behaves.)&#xD;&#xA;&#xD;&#xA;---- Edit ----&lt;br&gt;&#xD;&#xA;Edit: Here are the trace() function(get radiance)&lt;br&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c++ --&gt;&#xD;&#xA;&#xD;&#xA;    float4 Renderer::trace(Ray ray, Scene* scene)&#xD;&#xA;	{&#xD;&#xA;		const int BOUNCE_DEPTH = getBounceDepth();&#xD;&#xA;		//Russian roulette: starting at depth 5&#xD;&#xA;		const int RUSSIAN_ROULETTE_START_DEPTH = 16;&#xD;&#xA;		const float FACTOR_CUT_OFF = 1e-5;&#xD;&#xA;&#xD;&#xA;		float4 factor(1.0f,1.0f,1.0f,1.0f);&#xD;&#xA;		float4 renderedColor;&#xD;&#xA;		Ray currentRay = ray;&#xD;&#xA;		float4 lastNormal = ray.direction;&#xD;&#xA;		float rrFactor = 1.0f;&#xD;&#xA;&#xD;&#xA;		for(int i=0;i&lt;BOUNCE_DEPTH||BOUNCE_DEPTH &lt; 0;i++)//To ignore bounce limit. set bounceDepth to -1&#xD;&#xA;		{&#xD;&#xA;			if(i &gt;= RUSSIAN_ROULETTE_START_DEPTH)&#xD;&#xA;			{&#xD;&#xA;				const float stopProbability = 0.1f;&#xD;&#xA;				if(((float)rand()/RAND_MAX) &lt; (1.0-stopProbability))&#xD;&#xA;					break;&#xD;&#xA;				vrrFactor *= 1.0f/(1.0f-stopProbability);&#xD;&#xA;				//cout &lt;&lt; rrFactor &lt;&lt; endl;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			//stop bouncing if factor is too small.&#xD;&#xA;			//This is a biased method. Remove this if you want unbiased rendering&#xD;&#xA;			if(factor.x + factor.y + factor.z &lt;= FACTOR_CUT_OFF)&#xD;&#xA;				break;&#xD;&#xA;&#xD;&#xA;			RayHit hit = acclerator-&gt;raycast(currentRay);&#xD;&#xA;			if(hit.distance &gt; 0)&#xD;&#xA;			{&#xD;&#xA;				int index = hit.index;&#xD;&#xA;				Triangle emit(scene-&gt;emitColor[scene-&gt;indices[index*3]],&#xD;&#xA;					scene-&gt;emitColor[scene-&gt;indices[index*3+1]],&#xD;&#xA;					scene-&gt;emitColor[scene-&gt;indices[index*3+2]]);&#xD;&#xA;				Triangle triangle(scene-&gt;vertices[scene-&gt;indices[index*3]],&#xD;&#xA;					scene-&gt;vertices[scene-&gt;indices[index*3+1]],&#xD;&#xA;					scene-&gt;vertices[scene-&gt;indices[index*3+2]]);&#xD;&#xA;				Triangle reflectColor(scene-&gt;reflectColor[scene-&gt;indices[index*3]],&#xD;&#xA;					scene-&gt;reflectColor[scene-&gt;indices[index*3+1]],&#xD;&#xA;					scene-&gt;reflectColor[scene-&gt;indices[index*3+2]]);&#xD;&#xA;&#xD;&#xA;				//if(i &gt; 1)//Only collect indirect lighting&#xD;&#xA;				renderedColor += factor*emit.interpolation(hit.u,hit.v)*rrFactor;&#xD;&#xA;				factor *= reflectColor.interpolation(hit.u,hit.v);&#xD;&#xA;&#xD;&#xA;				//randomly sample on a hemisphere&#xD;&#xA;				Ray reflecRay;&#xD;&#xA;				reflecRay = createRandomReflect(currentRay, triangle,&#xD;&#xA;					currentRay.origin + normalize(currentRay.direction)*hit.distance);&#xD;&#xA;&#xD;&#xA;				float4 triangleNormal = triangle.normal();&#xD;&#xA;				if(dot(triangleNormal,currentRay.direction) &lt; 0)&#xD;&#xA;					triangleNormal = -triangleNormal;&#xD;&#xA;&#xD;&#xA;				currentRay = reflecRay;&#xD;&#xA;				lastNormal = triangle.normal();&#xD;&#xA;				if(dot(currentRay.direction,lastNormal) &lt; 0)&#xD;&#xA;					lastNormal = -lastNormal;&#xD;&#xA;				factor *= dot(normalize(currentRay.direction),lastNormal);//Difduse BRDF&#xD;&#xA;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;			break;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return renderedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;And the render() function (generate image)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c++ --&gt;&#xD;&#xA;&#xD;&#xA;    void Renderer::render(Scene* scene)&#xD;&#xA;	{&#xD;&#xA;		//srand(5000);&#xD;&#xA;		memset(frameBuffer,0,bufferWidth*bufferHeight*sizeof(float4));&#xD;&#xA;		int pixelCount = bufferWidth*bufferHeight;&#xD;&#xA;&#xD;&#xA;		high_resolution_clock::time_point t1 = high_resolution_clock::now();&#xD;&#xA;&#xD;&#xA;		int renderIndex = 0;&#xD;&#xA;&#xD;&#xA;		acclerator-&gt;setScene(scene);&#xD;&#xA;		acclerator-&gt;build();&#xD;&#xA;&#xD;&#xA;		const int SAMPLE_NUM = getSampleNum();&#xD;&#xA;&#xD;&#xA;		float4 origin = scene-&gt;camera.position&#xD;&#xA;			+ 2.0f*scene-&gt;camera.right/(float)scene-&gt;camera.width&#xD;&#xA;			+ 2.0f*scene-&gt;camera.up/(float)scene-&gt;camera.height;&#xD;&#xA;&#xD;&#xA;		#pragma omp parallel for schedule(dynamic)&#xD;&#xA;		for(int i=0;i&lt;pixelCount;i++)&#xD;&#xA;		{&#xD;&#xA;			float4 renderedColor = float4(0.0f,0.0f,0.0f,0.0f);&#xD;&#xA;			//Create camera ray&#xD;&#xA;			int x = i % bufferWidth;&#xD;&#xA;			int y = i / bufferWidth;&#xD;&#xA;&#xD;&#xA;			float4 rayVec = (x/(float)scene-&gt;camera.width-0.5f)*scene-&gt;camera.right*scene-&gt;camera.pixelAspectRatio&#xD;&#xA;				+ (0.5f-y/(float)scene-&gt;camera.height)*scene-&gt;camera.up&#xD;&#xA;				+ scene-&gt;camera.direction;&#xD;&#xA;			for(int j=0;j&lt;SAMPLE_NUM;j++)&#xD;&#xA;			{&#xD;&#xA;				Ray ray(origin, rayVec);&#xD;&#xA;				renderedColor += trace(ray,scene);&#xD;&#xA;			}&#xD;&#xA;			renderedColor /= (float)SAMPLE_NUM;&#xD;&#xA;&#xD;&#xA;			//simple gamma correction&#xD;&#xA;			const float gamma = 2.2;&#xD;&#xA;			const float inversedGamma = 1.0f/gamma;&#xD;&#xA;			float4 correctedColor = pow(renderedColor,float4(inversedGamma,inversedGamma,inversedGamma,0));&#xD;&#xA;			((float4*)frameBuffer)[i] = correctedColor;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;			#pragma omp atomic&#xD;&#xA;				renderIndex++;&#xD;&#xA;&#xD;&#xA;			#pragma omp critical&#xD;&#xA;			if(renderIndex%500 == 0)&#xD;&#xA;				cout &lt;&lt; &quot;Rendering &quot; &lt;&lt; renderIndex &lt;&lt; &quot;/&quot; &lt;&lt; pixelCount &lt;&lt; &quot;. &quot; &lt;&lt; (float)renderIndex*100.0/pixelCount &lt;&lt; &quot;\r&quot;;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		high_resolution_clock::time_point t2 = high_resolution_clock::now();&#xD;&#xA;		double elapsed = duration_cast&lt;duration&lt;double&gt;&gt;( t2 - t1 ).count();&#xD;&#xA;		cout &lt;&lt; endl &lt;&lt; &quot;elapsed: &quot; &lt;&lt; elapsed &lt;&lt; &quot; ,&quot; &lt;&lt; pixelCount*SAMPLE_NUM/elapsed/1000/1000 &lt;&lt; &quot; MSamples/s&quot;&lt;&lt; endl;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;---- End Edit ----&lt;br&gt;&#xD;&#xA;&#xD;&#xA;Scene Rendered by LuxRender (PBRT gives me the same result)&lt;br&gt;&#xD;&#xA;Renderer: Sampler, Sampler : metropolis, (Other settings are defalut)&#xD;&#xA;[![Scene Rendered by LuxRender][1]][1]&#xD;&#xA;&#xD;&#xA;The same scene rendered my by renderer. Note the scene is a bit darker and shadow is way too dark.&#xD;&#xA;[![Same Scene rendered my by renderer][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tsd5v.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A2knm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4178" PostHistoryTypeId="2" PostId="1943" RevisionGUID="397e1300-e49a-42f0-9809-9dbff36ebb37" CreationDate="2016-01-22T16:25:27.713" UserId="137" Text="In a post processing step instead of sampling the origin pixel directly from where the target pixel is you instead sample the origin pixel slightly offset.&#xD;&#xA;&#xD;&#xA;Where you get the offset can differ. For example you could provide an extra texture with the offsets encoded in the red and green channels." ContentLicense="CC BY-SA 3.0" />
  <row Id="4182" PostHistoryTypeId="5" PostId="1939" RevisionGUID="e232565a-bf50-4005-b57d-5d430b5cce85" CreationDate="2016-01-22T19:15:30.730" UserId="127" Comment="Removed salutation and the off-topic question for off-site resources." Text="I writing the this video process app which requires the each video frame to be processed such that parts of the video are enlarged. As a reference, one of the snapchat lens filter enlarges the eyes of a person in the video. This is the exact effect I want to achieve. &#xD;&#xA;&#xD;&#xA;How can I achieve this effect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4183" PostHistoryTypeId="2" PostId="1945" RevisionGUID="f80e768f-4189-4e57-bca0-74853b5b2c7a" CreationDate="2016-01-22T19:21:10.987" UserId="2237" Text="In a ray tracer, given a point on a sphere (point_of_intersection with a ray) and its normal for that point (point_of_intersection - center_of_sphere) **how do I calculate the tangent space for that point? Do I need other data to calculate the tangent space?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="4184" PostHistoryTypeId="1" PostId="1945" RevisionGUID="f80e768f-4189-4e57-bca0-74853b5b2c7a" CreationDate="2016-01-22T19:21:10.987" UserId="2237" Text="Ray tracing - tangent space for a point on a sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="4185" PostHistoryTypeId="3" PostId="1945" RevisionGUID="f80e768f-4189-4e57-bca0-74853b5b2c7a" CreationDate="2016-01-22T19:21:10.987" UserId="2237" Text="|raytracing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4186" PostHistoryTypeId="2" PostId="1946" RevisionGUID="1f60e9cb-5538-4408-a9e0-a32a48a1a4e9" CreationDate="2016-01-22T20:15:57.553" UserId="273" Text="The tangent space is spanned by the tangent to the point and the bitangent (which is orthogonal to both tangent and normal).&#xD;&#xA;&#xD;&#xA;So you need to calculate the tangent which is achieved by calculating the cross-product of the ray-direction and the normal. **T = N x DIR**&#xD;&#xA;The resulting vector will be orthogonal to the normal and thereby be the tangent.&#xD;&#xA;&#xD;&#xA;Now calculate the cross-product of the tangent and the normal **BT = T x N** to create a vector orthogonal to both. This vector is the bitangent.&#xD;&#xA;&#xD;&#xA;Tangent **T** and bitangent **BT** span a plane which is the tangent-space of your intersection-point.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4187" PostHistoryTypeId="5" PostId="1946" RevisionGUID="e945646f-45ae-4134-9193-28660fe58d6c" CreationDate="2016-01-22T20:41:40.293" UserId="127" Comment="Applied MathJax" Text="The tangent space is spanned by the tangent to the point and the bitangent (which is orthogonal to both tangent and normal).&#xD;&#xA;&#xD;&#xA;So you need to calculate the tangent which is achieved by calculating the cross-product of the ray-direction and the normal. $T = N \times DIR$&#xD;&#xA;The resulting vector will be orthogonal to the normal and thereby be the tangent.&#xD;&#xA;&#xD;&#xA;Now calculate the cross-product of the tangent and the normal $BT = T \times N$ to create a vector orthogonal to both. This vector is the bitangent.&#xD;&#xA;&#xD;&#xA;Tangent $T$ and bitangent $BT$ span a plane which is the tangent-space of your intersection-point.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4188" PostHistoryTypeId="5" PostId="1941" RevisionGUID="a3867e60-4f84-427e-8141-098e0823c274" CreationDate="2016-01-22T21:50:54.843" UserId="2521" Comment="Added link to GFX debugger" Text="There are several offerings by GPU vendors like AMD's [CodeXL](http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/) or NVIDIA's [nSight](https://www.nvidia.com/object/nsight.html)/[Linux GFX Debugger](https://developer.nvidia.com/linux-graphics-debugger) which allow stepping through shaders but are tied to the respective vendor's hardware.&#xD;&#xA;&#xD;&#xA;Let me note that, although they are available under Linux, I always had very little success with using them there. I can't comment on the situation under Windows.&#xD;&#xA;&#xD;&#xA;The option which I have come to use recently, is to modularize my shader code via [`#includes`](https://computergraphics.stackexchange.com/questions/100/sharing-code-between-multiple-glsl-shaders) and restrict the included code to a common subset of GLSL and C++&amp;[glm](http://glm.g-truc.net).&#xD;&#xA;&#xD;&#xA;When I hit a problem I try to reproduce it on another device to see if the problem is the same which hints at a logic error (instead of a driver problem/undefined behavior). There is also the chance of passing wrong data to the GPU (e.g. by incorrectly bound buffers etc.) which I usually rule out either by output debugging like in [cifz answer](https://computergraphics.stackexchange.com/a/101) or by inspecting the data via [apitrace](https://apitrace.github.io/).&#xD;&#xA;&#xD;&#xA;When it is a logic error I try to rebuild the situation from the GPU on CPU by calling the included code on CPU with the same data.&#xD;&#xA;Then I can step through it on CPU.&#xD;&#xA;&#xD;&#xA;Building upon the modularity of the code you can also try to write unittest for it and compare the results between a GPU run and a CPU run. However, you have to be aware that there are corner cases where C++ might behave differently than GLSL, thus giving you false positives in these comparisons.&#xD;&#xA;&#xD;&#xA;Finally, when you can't reproduce the problem on another device, you can only start to dig down where the difference comes from. Unittests might help you to narrow down where that happens but in the end you will probably need to write out additional debug information from the shader like in [cifz answer](https://computergraphics.stackexchange.com/a/101).&#xD;&#xA;&#xD;&#xA;And to give you an overview here is a flowchart of my debugging process:&#xD;&#xA;[![Flow chart of the procedure described in the text][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YLv6u.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4189" PostHistoryTypeId="5" PostId="1924" RevisionGUID="09361113-81d2-4138-8f68-aebe5a3c208c" CreationDate="2016-01-23T00:14:44.033" UserId="2237" Comment="deleted 3 characters in body" Text="I wrote a ray tracer that implements various BRDF models (Oren Nayar, Lamber, Torrance Sparrow and so on). &#xD;&#xA;Now I'm trying to implement a BRDF from measured data.&#xD;&#xA;I choose the Cornell database data available here:&#xD;&#xA;&#xD;&#xA;http://www.graphics.cornell.edu/online/measurements/reflectance/spraypaints/index.html&#xD;&#xA;&#xD;&#xA;I want to use them because there's a representation of the data as spectrum with 31 sample (my ray tracer use spectral data for light calculation and then convert them to CIE XYZ and then RGB values for the final image rendering).&#xD;&#xA;&#xD;&#xA; - Which is the correct way to use this data?&#xD;&#xA; - Which sample technique must be used? &#xD;&#xA; - **Why phi_out has all negative value?**&#xD;&#xA; - **Can I calculate phi_out using the same approximation as the one I used in Oren Nayar, so ||View - Normal * (View.dot(normal)||**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4190" PostHistoryTypeId="5" PostId="1925" RevisionGUID="31a12d77-9182-4f2a-b3f0-4033d3d4efeb" CreationDate="2016-01-23T03:16:54.280" UserDisplayName="user2500" Comment="Updated with info from NV white papers." Text="Yes, it's a meaningful stat: GPUs have dedicated triangle setup HW and the rate is measured in triangles/GPU clock. According to white papers available on NV's website, the 680 (Kepler) could issue one triangle per SM every other clock - with 8 SMs, this yielded 4 triangles/clock. The Maxwell white paper doesn't indicate a change in this rate per SM - the 980 has 16 SMs so, if there is really is no rate change per SM, it can produce 8 triangles/clock. While the 980 has 2048 CUDA cores, the 950 has 768, implying 6 SMs and 3 triangles/clock. The chip runs around 1 Ghz, so the 950 is probably limited to 3 billion triangles per second." ContentLicense="CC BY-SA 3.0" />
  <row Id="4191" PostHistoryTypeId="5" PostId="1939" RevisionGUID="5d639cf6-a321-4795-8703-ecbc7edd863b" CreationDate="2016-01-23T04:52:36.790" UserId="2520" Comment="added 162 characters in body" Text="I writing the this video process app which requires the each video frame to be processed such that parts of the video are enlarged. As a reference, one of the snapchat lens filter enlarges the eyes of a person in the video. This is the exact effect I want to achieve. &#xD;&#xA;&#xD;&#xA;How can I achieve this effect?&#xD;&#xA;&#xD;&#xA;Update:&#xD;&#xA;&#xD;&#xA;I have attached an example of eye enlargement from the web.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XESgE.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4192" PostHistoryTypeId="2" PostId="1947" RevisionGUID="2870be04-6d2e-42a8-9aa0-210c2d4e8602" CreationDate="2016-01-23T14:39:03.033" UserDisplayName="user2500" Text="For each of major vendor's latest GPU architectures, is there a clear maximum &quot;triangles/second&quot; bottleneck? If so, what is it architecturally and what is the performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4193" PostHistoryTypeId="1" PostId="1947" RevisionGUID="2870be04-6d2e-42a8-9aa0-210c2d4e8602" CreationDate="2016-01-23T14:39:03.033" UserDisplayName="user2500" Text="GPU Architecture: What are the theoretical limits on triangle throughput in modern GPUs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4194" PostHistoryTypeId="3" PostId="1947" RevisionGUID="2870be04-6d2e-42a8-9aa0-210c2d4e8602" CreationDate="2016-01-23T14:39:03.033" UserDisplayName="user2500" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4195" PostHistoryTypeId="2" PostId="1948" RevisionGUID="8a8af29c-9c7e-4d7a-80cb-6a9eccbeee87" CreationDate="2016-01-23T15:42:58.707" UserId="273" Text="Your questions is not that easy to answer, as there is no standard definition of what &quot;triangles/second&quot; actually means.&#xD;&#xA;&#xD;&#xA;What shading is used? What calculations are done? How are the triangles represented? This and much more has to be taken into account when looking for benchmarks on GPU-performance.&#xD;&#xA;&#xD;&#xA;To actually compare the performance of GPUs you would have to look at a range of different measurements. GFlop/s and Memory-speed as some basic ones, but also look at full benchmark-scores (which there are I am sure many).&#xD;&#xA;There are websites that copmile these measurements and display them in a comparison mode. A quick search brought me to this page which seems to have everything needed http://gpuboss.com/gpus/GeForce-GTX-760-vs-GeForce-GTX-750 (i entered a example search).&#xD;&#xA;&#xD;&#xA;This helps to compare the performance of two GPUs but if you want to know if a specific GPU is able to do the specific thing you want it to do, that may be very hard to anwser and impossible without much more knowledge about what you want to do.&#xD;&#xA;&#xD;&#xA;Calculating the maximum performance is also very hard because I belief the GPU vendors do not share everything they do on their GPUs so it can is hard to estimate the actual performance." ContentLicense="CC BY-SA 3.0" />
  <row Id="4203" PostHistoryTypeId="2" PostId="1950" RevisionGUID="739f209b-0b0a-4fb8-8df2-f2984bb83cb8" CreationDate="2016-01-23T22:59:21.727" UserId="2537" Text="I am facing a though challange - I need to perform repetitive Image formating. Firstly, I need resize picture A so that it has some fixed width in pixels. Then, I need to place picture A in the middle of picture B. I need to perform this task repetitively for hundreds of images. Is there any way to script this, so that I can just type in for example:&#xD;&#xA;&#xD;&#xA;    perform pictureA.png pictureB.png output.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any help is more than welcome!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4204" PostHistoryTypeId="1" PostId="1950" RevisionGUID="739f209b-0b0a-4fb8-8df2-f2984bb83cb8" CreationDate="2016-01-23T22:59:21.727" UserId="2537" Text="Is there a way to script image creation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4205" PostHistoryTypeId="3" PostId="1950" RevisionGUID="739f209b-0b0a-4fb8-8df2-f2984bb83cb8" CreationDate="2016-01-23T22:59:21.727" UserId="2537" Text="|transformations|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4206" PostHistoryTypeId="2" PostId="1951" RevisionGUID="cff9c21a-7347-4231-a76d-184172adadc0" CreationDate="2016-01-23T23:59:51.367" UserId="48" Text="[ImageMagick](http://www.imagemagick.org) is a set of command-line tools that can do the sort of things you describe. For example, this command line will overlay picture B with a centered copy of picture A, resized to 100 pixels wide (keeping aspect ratio):&#xD;&#xA;&#xD;&#xA;    convert pictureB.png ( pictureA.png -resize 100 ) -gravity center -composite output.png&#xD;&#xA;&#xD;&#xA;See [the ImageMagick docs](http://www.imagemagick.org/script/command-line-processing.php) for more info about its command lines are structured...it's a powerful piece of software, but it takes a bit of work to get the hang of how to use it." ContentLicense="CC BY-SA 3.0" />
  <row Id="4208" PostHistoryTypeId="5" PostId="1948" RevisionGUID="37a754f1-75c0-4a1b-87b2-424ea713c9a4" CreationDate="2016-01-24T12:17:00.900" UserId="231" Comment="Minor tidying. Feel free to roll back anything that changes your intent." Text="Your question is not that easy to answer, as there is no standard definition of what &quot;triangles/second&quot; actually means.&#xD;&#xA;&#xD;&#xA;What shading is used? What calculations are done? How are the triangles represented? This and much more has to be taken into account when looking for benchmarks on GPU-performance.&#xD;&#xA;&#xD;&#xA;To actually compare the performance of GPUs you would have to look at a range of different measurements. GFlop/s and memory-speed as some basic ones, but also look at full benchmark scores (of which there are I am sure many).&#xD;&#xA;&#xD;&#xA;There are websites that compile these measurements and display them in a comparison mode. A quick search brought me to [this page which seems to have everything needed] (I entered an example search).&#xD;&#xA;&#xD;&#xA;This helps to compare the performance of two GPUs but if you want to know if a specific GPU is able to do the specific thing you want it to do, that may be very hard to answer and impossible without much more knowledge about what you want to do.&#xD;&#xA;&#xD;&#xA;Calculating the maximum performance is also very hard because I believe the GPU vendors do not share everything they do on their GPUs so it can be hard to estimate the actual performance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [this page which seems to have everything needed]: http://gpuboss.com/gpus/GeForce-GTX-760-vs-GeForce-GTX-750 &quot;gpuboss.com/gpus/GeForce-GTX-760-vs-GeForce-GTX-750&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4209" PostHistoryTypeId="2" PostId="1952" RevisionGUID="2f6822c6-f6e4-4a53-92f9-9874f2d88e29" CreationDate="2016-01-24T13:34:51.840" UserId="2540" Text="Raster scan display forms an image with pixel whereas a Random scan display works with Geometric primitives, but even a geometric primitve( a line) is made up of pixels so what is the difference?&#xD;&#xA;r" ContentLicense="CC BY-SA 3.0" />
  <row Id="4210" PostHistoryTypeId="1" PostId="1952" RevisionGUID="2f6822c6-f6e4-4a53-92f9-9874f2d88e29" CreationDate="2016-01-24T13:34:51.840" UserId="2540" Text="How is Raster and Random Scan Display different?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4211" PostHistoryTypeId="3" PostId="1952" RevisionGUID="2f6822c6-f6e4-4a53-92f9-9874f2d88e29" CreationDate="2016-01-24T13:34:51.840" UserId="2540" Text="|raster-image|display-lists|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4212" PostHistoryTypeId="2" PostId="1953" RevisionGUID="6df8add1-3711-4587-9e0b-fbdabba87d15" CreationDate="2016-01-24T13:51:51.840" UserId="273" Text="A raster display draws every pixel on the screen in every frame whether there is something to show or not.&#xD;&#xA;&#xD;&#xA;A random scan display activates only those pixel which are occupied by an geometric primitive.&#xD;&#xA;&#xD;&#xA;So yes, they both use pixels, but the difference is in how they draw the pixels onto the screen." ContentLicense="CC BY-SA 3.0" />
  <row Id="4213" PostHistoryTypeId="5" PostId="1952" RevisionGUID="506e114f-44eb-4889-9b88-0b1549ad0724" CreationDate="2016-01-24T14:38:09.480" UserId="2540" Comment="deleted 1 character in body" Text="Raster scan display forms an image with pixel whereas a Random scan display works with Geometric primitives, but even a geometric primitve( a line) is made up of pixels so what is the difference?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4215" PostHistoryTypeId="2" PostId="1954" RevisionGUID="ea9490b4-9266-4da9-892f-a6104bd78e90" CreationDate="2016-01-24T21:15:17.677" UserId="386" Text="Right now I'm trying to implement some sort of depth buffer in software and I have a huge problem when I'm writing to it. Having one mutex is absolute overkill. So I created a number of mutexes equal to the number of threads. I'm locking a mutex based on current pixel (pixel_index % mutexes_number) and this works better, but still very very slow. And I wonder how it's done in a real GPU? Is there a clever algorithm or hardware handles it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4216" PostHistoryTypeId="1" PostId="1954" RevisionGUID="ea9490b4-9266-4da9-892f-a6104bd78e90" CreationDate="2016-01-24T21:15:17.677" UserId="386" Text="How updating a depth buffer works in GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4217" PostHistoryTypeId="3" PostId="1954" RevisionGUID="ea9490b4-9266-4da9-892f-a6104bd78e90" CreationDate="2016-01-24T21:15:17.677" UserId="386" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4218" PostHistoryTypeId="2" PostId="1955" RevisionGUID="dfaa6bf4-f8fd-40b8-9954-b156ecc34f84" CreationDate="2016-01-24T22:50:29.833" UserDisplayName="user2500" Text="Highly specialized hardware handles it. A typical strategy is for a GPU to tile rasterization and store depth information in compressed formats (e.g. the z-equation when a polygon completely covers a tile). This allows testing across an entire tile at once; other cool HW tricks include depth testing before the pixel shader is run (assuming conditions permit - the shader cannot write a depth value). You might consider something similar in software, such as having each thread &quot;own&quot; a subset of tiles and walk each primitive independently, or mimic multi-gpu strategies such as alternate frames or alternate raster lines." ContentLicense="CC BY-SA 3.0" />
  <row Id="4219" PostHistoryTypeId="2" PostId="1956" RevisionGUID="b3e22990-646e-4133-9918-97d9d45dc8f9" CreationDate="2016-01-25T01:50:49.570" UserId="48" Text="In a real GPU, instead of having multiple cores trying to read/write the same region of the depth buffer and attempting to synchronize between them, the depth buffer is divided into tiles (such as 16×16 or 32×32), and each tile is assigned to a single core. That core is then responsible for all rasterization in that tile: any triangles that touch that tile will be rasterized (within that tile) by the owning core. Then there is no interference between cores, and no need for them to synchronize when accessing their part of the framebuffer.&#xD;&#xA;&#xD;&#xA;This implies that triangles that touch multiple tiles will need to be rasterized by multiple cores. So, there is a work redistribution step between geometry processing (operations on vertices and triangles) and pixel processing.&#xD;&#xA;&#xD;&#xA;In the geometry stage, each core might process a chunk of input primitives; then for each primitive, it can quickly determine which tiles the primitive touches (this is called &quot;coarse rasterization&quot;), and add the primitive to a queue for each core that owns one of the affected tiles.&#xD;&#xA;&#xD;&#xA;Then, in the pixel stage, each core can read out the list of primitives in its queue, calculate pixel coverage for the tiles the core owns, and proceed to depth testing, pixel shading and updating the framebuffer, with no need of any further coordination with other cores." ContentLicense="CC BY-SA 3.0" />
  <row Id="4221" PostHistoryTypeId="2" PostId="1957" RevisionGUID="29f3958b-a335-426c-8443-ece3b30b7456" CreationDate="2016-01-25T06:33:01.137" UserId="1870" Text="[Please (kindly) let me know if this is not the place for this question]&#xD;&#xA;&#xD;&#xA;I'm hoping to learn about GPU programming, but as a college student, I've a quite limited budget.  I'm wondering whether I should buy a modestly more expensive GPU that uses GDDR5 memory, or if DDR3 memory is sufficient.&#xD;&#xA;&#xD;&#xA;I can see some potential pros and cons:&#xD;&#xA;&#xD;&#xA; - GDDR5 is standard in nearly all but the lowest-end GPUs, so I'd be getting experience that would transfer to most popular cards&#xD;&#xA; - However, is it possible that learning with DDR3 memory will only help me learn to be more efficient, thus my skills would translate (probably with a bit more difficulty) to even better programming abilities on a higher-end GPU&#xD;&#xA;&#xD;&#xA;Any advice or words of wisdom?&#xD;&#xA;&#xD;&#xA;Note that I don't want the card for gaming purposes (although I would gladly use it in such a capacity, but that would be a happy by-product of having it around to learn to program on).  I also don't really care too much about being able to run programs faster on the GPU; I mainly want the ability to learn how to program on a GPU.  I'm currently considering only NVIDIA GPUs, as I've learned a smidgen about CUDA programming." ContentLicense="CC BY-SA 3.0" />
  <row Id="4222" PostHistoryTypeId="1" PostId="1957" RevisionGUID="29f3958b-a335-426c-8443-ece3b30b7456" CreationDate="2016-01-25T06:33:01.137" UserId="1870" Text="GDDR5 vs. DDR3 for learning GPU programming on a limited budget?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4223" PostHistoryTypeId="3" PostId="1957" RevisionGUID="29f3958b-a335-426c-8443-ece3b30b7456" CreationDate="2016-01-25T06:33:01.137" UserId="1870" Text="|gpu|memory|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4224" PostHistoryTypeId="2" PostId="1958" RevisionGUID="a63d76fc-b2e9-4c10-829f-c476383bf818" CreationDate="2016-01-25T07:34:55.527" UserId="48" Text="If your goal is to learn GPU programming, it doesn't matter at all whether you have DDR3 or GDDR5 memory. The way you program it isn't going to change based on how fast the memory is. It will affect performance, but if that's not a primary consideration for you, then you don't need to worry about it.&#xD;&#xA;&#xD;&#xA;Do make sure that you get a GPU that supports the latest graphics APIs (DX12 and OpenGL 4.5). I think that's essentially all GPUs made in the past 5 years or so." ContentLicense="CC BY-SA 3.0" />
  <row Id="4226" PostHistoryTypeId="2" PostId="1959" RevisionGUID="d30166ed-6938-44c3-b1d3-d2e03592dfa5" CreationDate="2016-01-25T09:04:13.653" UserId="16" Text="I'm implementing [improved Perlin noise](http://mrl.nyu.edu/~perlin/noise/). Its key feature for randomisation is the hardcoded permutation table, which gives essentially random but reproducible gradients at the cells of the grid. The permutation table is just a permutation of the integers `0..255`, and is usually the following table (copied straight from Perlin's original implementation):&#xD;&#xA;&#xD;&#xA;    {151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7,&#xD;&#xA;    225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247,&#xD;&#xA;    120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,&#xD;&#xA;    88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134,&#xD;&#xA;    139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220,&#xD;&#xA;    105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80,&#xD;&#xA;    73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,&#xD;&#xA;    164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38,&#xD;&#xA;    147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189,&#xD;&#xA;    28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,&#xD;&#xA;    155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,&#xD;&#xA;    178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12,&#xD;&#xA;    191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181,&#xD;&#xA;    199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236,&#xD;&#xA;    205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180};&#xD;&#xA;&#xD;&#xA;For reference, a small patch drawn from the noise generated by this table looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, I would like the code to be a bit more flexible and allow this table to be reshuffled so that I can create a completely new noise field (instead of just sampling it at a different offset). But not all permutations are equally well shuffled. In the unlikely event that the random permutation is just the sorted array from `0` to `255`, the noise would look like this instead:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;That's kinda bad. Of course, at a chance of $1$ in $256!$, this is not a case I need to be worried about. But surely, this is not the only permutation that yields very noticeable artefacts. Say the code would be used in a popular game to generate a random world up front, it would still be annoying if every 100,000th generated world would look remotely regular.&#xD;&#xA;&#xD;&#xA;So the question is, what exactly makes a good (or a bad) permutation table, and how do I assess the quality of a permutation table programmatically, such that I can reshuffle the table once more in the unlikely event that I roll a &quot;bad&quot; table?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gyuqs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3uC8M.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4227" PostHistoryTypeId="1" PostId="1959" RevisionGUID="d30166ed-6938-44c3-b1d3-d2e03592dfa5" CreationDate="2016-01-25T09:04:13.653" UserId="16" Text="What makes a good permutation table?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4228" PostHistoryTypeId="3" PostId="1959" RevisionGUID="d30166ed-6938-44c3-b1d3-d2e03592dfa5" CreationDate="2016-01-25T09:04:13.653" UserId="16" Text="|noise|mathematics|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4229" PostHistoryTypeId="5" PostId="1959" RevisionGUID="ec0e45df-6e6b-4ae3-abed-4cc886e97df4" CreationDate="2016-01-25T09:11:09.293" UserId="16" Comment="added 130 characters in body" Text="I'm implementing [improved Perlin noise](http://mrl.nyu.edu/~perlin/noise/). Its key feature for randomisation is the hardcoded permutation table, which gives essentially random but reproducible gradients at the cells of the grid. The permutation table is just a permutation of the integers `0..255`, and is usually the following table (copied straight from Perlin's original implementation):&#xD;&#xA;&#xD;&#xA;    {151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7,&#xD;&#xA;    225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247,&#xD;&#xA;    120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,&#xD;&#xA;    88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134,&#xD;&#xA;    139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220,&#xD;&#xA;    105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80,&#xD;&#xA;    73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,&#xD;&#xA;    164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38,&#xD;&#xA;    147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189,&#xD;&#xA;    28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,&#xD;&#xA;    155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,&#xD;&#xA;    178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12,&#xD;&#xA;    191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181,&#xD;&#xA;    199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236,&#xD;&#xA;    205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180};&#xD;&#xA;&#xD;&#xA;For reference, a small patch drawn from the noise generated by this table looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, I would like the code to be a bit more flexible and allow this table to be reshuffled so that I can create a completely new noise field (instead of just sampling it at a different offset). But not all permutations are equally well shuffled. In the unlikely event that the random permutation is just the sorted array from `0` to `255`, the noise would look like this instead:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;That's kinda bad. Of course, at a chance of $1$ in $256!$, this is not a case I need to be worried about. But surely, this is not the only permutation that yields very noticeable artefacts. Reverse sorted and almost sorted permutations would likely have the same problems. So how many other permutations are unsuitable? Say the code would be used in a popular game to generate a random world up front, it would still be annoying if every 100,000th generated world would look remotely regular.&#xD;&#xA;&#xD;&#xA;So the question is, what exactly makes a good (or a bad) permutation table, and how do I assess the quality of a permutation table programmatically, such that I can reshuffle the table once more in the unlikely event that I roll a &quot;bad&quot; table?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gyuqs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3uC8M.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4230" PostHistoryTypeId="2" PostId="1960" RevisionGUID="974dd90b-1a6e-4fa2-8d89-d265ce6bf0f6" CreationDate="2016-01-25T11:25:51.673" UserId="1790" Text="**First of all** - a number must not occur twice, that is implied since we're talking about permutations. So filling the table with a simple random(255) function won't work.&#xD;&#xA;&#xD;&#xA;**Secondly**, you need to ensure that there are no premature recurrence patterns:&#xD;&#xA;&#xD;&#xA;Consider the values 1,2,3,4 - the permutation table 4,3,2,1 is not a very good one because recurrence happens immediately, i.e. 1 -&gt; 4, 4 -&gt; 1. Likewise with 4,2,3,1 or 1,2,3,4. The optimal tables take you all the way through all positions: 3,1,4,2 or 2,4,1,3.&#xD;&#xA;&#xD;&#xA;This property becomes increasingly  important as you increase the number of dimensions and perform recursive lookups.&#xD;&#xA;&#xD;&#xA;**Thirdly**, For larger tables like one with 256 values you need to ensure a uniform random distribution, so you may want to constrain the random step distance to a certain min and max range, e.g. 5..120 or something. These numbers are worth experimenting with." ContentLicense="CC BY-SA 3.0" />
  <row Id="4231" PostHistoryTypeId="5" PostId="1960" RevisionGUID="2b09ae5b-11f4-4d06-b97e-7676a94c16d7" CreationDate="2016-01-25T11:51:00.367" UserId="1790" Comment="added 207 characters in body" Text="**First of all** - a number must not occur twice, that is implied since we're talking about permutations. So filling the table with a simple random(255) function won't work.&#xD;&#xA;&#xD;&#xA;**Secondly**, you need to ensure that there are no premature recurrence patterns:&#xD;&#xA;&#xD;&#xA;Consider the values 1,2,3,4 - the permutation table 4,3,2,1 is not a very good one because of its short cyclic properties, i.e. 1 -&gt; 4, 4 -&gt; 1. Likewise with 4,2,3,1 or 1,2,3,4. The optimal tables take you all the way through all positions: 3,1,4,2 or 2,4,1,3.&#xD;&#xA;&#xD;&#xA;This property becomes increasingly  important as you increase the number of dimensions and perform recursive lookups.&#xD;&#xA;&#xD;&#xA;However this approach alone may create clusters of too similar values, which may or may not be wanted, which leads me to next point.&#xD;&#xA;&#xD;&#xA;**Thirdly**, When you generate a table with the non cyclic properties, you need to step through remaining unassigned indices in a random manner. When possible constrain the random step distance here to a certain min and max range, e.g. 5..120 to avoid clustered groups of similar values. These numbers are worth experimenting with. " ContentLicense="CC BY-SA 3.0" />
  <row Id="4232" PostHistoryTypeId="2" PostId="1961" RevisionGUID="abd3ce7a-6e58-48f7-9f31-320758c14651" CreationDate="2016-01-25T13:09:10.607" UserId="209" Text="One possibility might be to borrow from the cryptographic community and, in particular, the 8-bit to 8-bit substitution used in the AES/Rijndael cipher. &#xD;&#xA;The table and code to generate it [can be found on wikipedia.](https://en.wikipedia.org/wiki/Rijndael_S-box)&#xD;&#xA;&#xD;&#xA;Having said that, (and please forgive me if I've got some of the details wrong) in a past life I implemented Perlin noise using a relatively simple RNG/Hash function but found the correlation in X/Y/Z due to my simple mapping of 2 or 3 dimensions to a scalar value was problematic.  I found that a very simple fix was just to use a CRC, eg. *something like*&#xD;&#xA;  &#xD;&#xA;    InputToRNGHash = CRC(Z xor CRC( Y xor CRC(X))). &#xD;&#xA;&#xD;&#xA;Given CRCs intrinsics may be built in to CPU HW, this can be fast approach." ContentLicense="CC BY-SA 3.0" />
  <row Id="4233" PostHistoryTypeId="5" PostId="1961" RevisionGUID="59c4dd7d-64f4-4dbc-85f6-cde04a13f9b8" CreationDate="2016-01-25T14:06:52.043" UserId="209" Comment="added 229 characters in body" Text="One possibility might be to borrow from the cryptographic community and, in particular, the 8-bit to 8-bit substitution used in the AES/Rijndael cipher. &#xD;&#xA;The table and code to generate it [can be found on wikipedia.](https://en.wikipedia.org/wiki/Rijndael_S-box)&#xD;&#xA;&#xD;&#xA;I'd guess that, in order to generate up to 256 additional tables, you could just do something like:&#xD;&#xA;&#xD;&#xA;    Func(U8 input, U8 TableNum) = SBox( (TableNum + Sbox(input)) Mod256 )&#xD;&#xA;&#xD;&#xA;(since the SBox function is quite non-linear)&#xD;&#xA;&#xD;&#xA;Having said that, (and please forgive me if I've got some of the details wrong) in a past life I implemented Perlin noise using a relatively simple RNG/Hash function but found the correlation in X/Y/Z due to my simple mapping of 2 or 3 dimensions to a scalar value was problematic.  I found that a very simple fix was just to use a CRC, eg. *something like*&#xD;&#xA;  &#xD;&#xA;    InputToRNGHash = CRC(Z xor CRC( Y xor CRC(X))). &#xD;&#xA;&#xD;&#xA;Given CRCs intrinsics may be built in to CPU HW, this can be fast approach." ContentLicense="CC BY-SA 3.0" />
  <row Id="4235" PostHistoryTypeId="2" PostId="1962" RevisionGUID="a09c115b-874b-40bc-92d7-4007fb987def" CreationDate="2016-01-25T19:25:52.957" UserId="273" Text="If I have a std::vector&lt;Foo&gt; and want to store it's size in a GLuint, my compiler gives a warning that there is possible loss of data.&#xD;&#xA;    &#xD;&#xA;    GLuint size = vec.size(); // &quot;conversion from 'size_t' to 'GLuint', possible loss of data&quot;&#xD;&#xA;&#xD;&#xA;How do I correctly do this type of casting?&#xD;&#xA;Are there more pitfalls of this kind with for example float to GLfloat?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4236" PostHistoryTypeId="1" PostId="1962" RevisionGUID="a09c115b-874b-40bc-92d7-4007fb987def" CreationDate="2016-01-25T19:25:52.957" UserId="273" Text="Type conversion to GL-types" ContentLicense="CC BY-SA 3.0" />
  <row Id="4237" PostHistoryTypeId="3" PostId="1962" RevisionGUID="a09c115b-874b-40bc-92d7-4007fb987def" CreationDate="2016-01-25T19:25:52.957" UserId="273" Text="|opengl|types|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4238" PostHistoryTypeId="5" PostId="1962" RevisionGUID="26b32737-af8e-4ceb-b277-05e30739e357" CreationDate="2016-01-25T19:31:30.200" UserId="16" Comment="added 7 characters in body; edited tags" Text="If I have a `std::vector&lt;Foo&gt;` and want to store its size in a `GLuint`, my compiler gives a warning that there is possible loss of data.&#xD;&#xA;    &#xD;&#xA;    GLuint size = vec.size(); // &quot;conversion from 'size_t' to 'GLuint', possible loss of data&quot;&#xD;&#xA;&#xD;&#xA;How do I correctly do this type of casting?&#xD;&#xA;Are there more pitfalls of this kind with for example `float` to `GLfloat`?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4239" PostHistoryTypeId="6" PostId="1962" RevisionGUID="26b32737-af8e-4ceb-b277-05e30739e357" CreationDate="2016-01-25T19:31:30.200" UserId="16" Comment="added 7 characters in body; edited tags" Text="|opengl|c++|types|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4240" PostHistoryTypeId="2" PostId="1963" RevisionGUID="ef15b82a-644a-486c-a4b6-3a5be91a2f9d" CreationDate="2016-01-25T19:39:23.373" UserId="31" Text="Assume there is some value `p`, calculated per-frame, that varies continuously over the surface of an object. The value of `p` determines the density of some pattern on the surface. For example, in a case with only two possible densities if `p &lt; 0.3` it is high density, otherwise it is low.&#xD;&#xA;&#xD;&#xA;I've thought of a simple high-level solution: create two textures, each of different densities, and based on the value of `p` sample from the appropriate one. However, there's a problem with the boundary between high- and low-densities.&#xD;&#xA;&#xD;&#xA;Here is an example to illustrate the problem:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here is the threshold between low- and high- (displayed on the high density texture but that's not relevant.) If under the line, it implies the high-density texture should be sampled.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally here is the comparison between what is desired and what would actually happen using this method:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The problem is that when a high-density-only circle crosses the line, it will be ignored when `p` indicates the low-density texture to be sampled, resulting in a truncated circle. I don't know how to solve this problem because `p` varies every frame, so I can't just 'bake' a boundary between the two densities. It's easy to prevent the reverse problem by creating the high-density texture from the lower one (i.e. if a circle is on the low-density texture ensure it is on the high-density texture.) &#xD;&#xA;&#xD;&#xA;I'm interested if anyone has a way to improve my solution or even has another method entirely. The constraint here is that `p` is calculated per-frame in real-time. I'm not familiar with the research in this field so I wasn't sure which keywords to search, so I'd even appreciate if anyone could point me in the right direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/krVHY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6WmhA.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DFsgY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4241" PostHistoryTypeId="1" PostId="1963" RevisionGUID="ef15b82a-644a-486c-a4b6-3a5be91a2f9d" CreationDate="2016-01-25T19:39:23.373" UserId="31" Text="How to create a patterned object with variable pattern density in real-time?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4242" PostHistoryTypeId="3" PostId="1963" RevisionGUID="ef15b82a-644a-486c-a4b6-3a5be91a2f9d" CreationDate="2016-01-25T19:39:23.373" UserId="31" Text="|texture|shader|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4243" PostHistoryTypeId="2" PostId="1964" RevisionGUID="44ed2c2a-2e5b-465f-a160-7cebf8203217" CreationDate="2016-01-25T21:35:09.860" UserDisplayName="user2500" Text="Practically speaking, probably not - try printing the size of each type using sizeof. Probably GLuint is 32 bits and size_t is 64 bits - so 32 bits are thrown out; but float and GLfloat are probably both 32 bit IEEE 754 numbers. &quot;Probably&quot; sprinkled above, because technically speaking the sizes of C ints, floats and the float format are compiler dependent, but GL type sizes (and formats) should be standard (see https://www.opengl.org/wiki/OpenGL_Type). Chances are, GLfloat is just typedef'd as a float.&#xD;&#xA;&#xD;&#xA;You may be able to turn off this warning in your compiler - I choose to explicitly cast so I am reminded of what's happening." ContentLicense="CC BY-SA 3.0" />
  <row Id="4244" PostHistoryTypeId="5" PostId="1964" RevisionGUID="d7e036ff-0d29-42e7-80f0-ec710f98d18a" CreationDate="2016-01-25T22:47:38.023" UserDisplayName="user2500" Comment="Added cast example." Text="Practically speaking, probably not - try printing the size of each type using sizeof. Probably GLuint is 32 bits and size_t is 64 bits - so 32 bits are thrown out; but float and GLfloat are probably both 32 bit IEEE 754 numbers. &quot;Probably&quot; sprinkled above, because technically speaking the sizes of C ints, floats and the float format are compiler dependent, but GL type sizes (and formats) should be standard (see https://www.opengl.org/wiki/OpenGL_Type). Chances are, GLfloat is just typedef'd as a float.&#xD;&#xA;&#xD;&#xA;You may be able to turn off this warning in your compiler - I choose to explicitly cast (&quot;GLuint size = GLuint(vec.size())&quot; works) so I am reminded of what's happening." ContentLicense="CC BY-SA 3.0" />
  <row Id="4245" PostHistoryTypeId="2" PostId="1965" RevisionGUID="c976f5ed-3c2a-45b7-9cc6-2486f9aa8adc" CreationDate="2016-01-26T00:17:15.313" UserDisplayName="user2500" Text="NV Maxwell: According to the NVIDIA GeForce GTX 680 white paper, each Streaming Multiprocessor (called an SMX in Kepler) in the Kepler architecture could process 1 polygon every other clock. The 680 has 8 SMX units, yielding 4 polygons/clock. The NVIDIA GeForce GTX 980 white paper only mentions that geometry performance of 980 should be double that of the 680; the 980 has twice as many Streaming Multiprocessors (called a SMM in Maxwell), implying each Maxwell SMM has the same polygon throughput per clock as a Kepler SMX. The number of SMMs in a particular GPU isn't always easy to find, but the number of cuda cores is usually publicized; since Maxwell has 128 cuda cores per SMM (there are 192 in a Kepler SMX), we can conclude that Maxwell based GPUs can handle 1 polygon/clock for each 256 cuda cores." ContentLicense="CC BY-SA 3.0" />
  <row Id="4246" PostHistoryTypeId="5" PostId="1941" RevisionGUID="376ede12-6703-41f7-ad71-9da3b5443e11" CreationDate="2016-01-26T11:23:57.880" UserId="2521" Comment="Improved image phrasing; added pro/con-list" Text="There are several offerings by GPU vendors like AMD's [CodeXL](http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/) or NVIDIA's [nSight](https://www.nvidia.com/object/nsight.html)/[Linux GFX Debugger](https://developer.nvidia.com/linux-graphics-debugger) which allow stepping through shaders but are tied to the respective vendor's hardware.&#xD;&#xA;&#xD;&#xA;Let me note that, although they are available under Linux, I always had very little success with using them there. I can't comment on the situation under Windows.&#xD;&#xA;&#xD;&#xA;The option which I have come to use recently, is to modularize my shader code via [`#includes`](https://computergraphics.stackexchange.com/questions/100/sharing-code-between-multiple-glsl-shaders) and restrict the included code to a common subset of GLSL and C++&amp;[glm](http://glm.g-truc.net).&#xD;&#xA;&#xD;&#xA;When I hit a problem I try to reproduce it on another device to see if the problem is the same which hints at a logic error (instead of a driver problem/undefined behavior). There is also the chance of passing wrong data to the GPU (e.g. by incorrectly bound buffers etc.) which I usually rule out either by output debugging like in [cifz answer](https://computergraphics.stackexchange.com/a/101) or by inspecting the data via [apitrace](https://apitrace.github.io/).&#xD;&#xA;&#xD;&#xA;When it is a logic error I try to rebuild the situation from the GPU on CPU by calling the included code on CPU with the same data.&#xD;&#xA;Then I can step through it on CPU.&#xD;&#xA;&#xD;&#xA;Building upon the modularity of the code you can also try to write unittest for it and compare the results between a GPU run and a CPU run. However, you have to be aware that there are corner cases where C++ might behave differently than GLSL, thus giving you false positives in these comparisons.&#xD;&#xA;&#xD;&#xA;Finally, when you can't reproduce the problem on another device, you can only start to dig down where the difference comes from. Unittests might help you to narrow down where that happens but in the end you will probably need to write out additional debug information from the shader like in [cifz answer](https://computergraphics.stackexchange.com/a/101).&#xD;&#xA;&#xD;&#xA;And to give you an overview here is a flowchart of my debugging process:&#xD;&#xA;[![Flow chart of the procedure described in the text][1]][1]&#xD;&#xA;&#xD;&#xA;To round this off here is a list of random pros and cons:&#xD;&#xA;&#xD;&#xA;**pro**&#xD;&#xA;&#xD;&#xA;- step through with usual debugger&#xD;&#xA;- additional (often better) compiler diagnostics&#xD;&#xA;&#xD;&#xA;**con**&#xD;&#xA;&#xD;&#xA;- subtle differences in some mathematic primitives (e.g. [different return values in corner cases](https://stackoverflow.com/questions/31915601/pow1-inf-nan))&#xD;&#xA;- additional code to reproduce call environment on CPU&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S1jUQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4248" PostHistoryTypeId="2" PostId="1967" RevisionGUID="f8b55dda-79f6-44ea-9dcf-d54cfb666c1a" CreationDate="2016-01-26T14:39:09.130" UserId="2551" Text="I have a video that record the drawing sequence with a pencil by a painter.&#xD;&#xA;[![video screen][1]][1]&#xD;&#xA;I want to reconstruction the sequence from the video.&#xD;&#xA;And I have google some keywords like `drawing sequence reconstruction` `sketch reconstruction` and have searched like `moving object detection` but cannot found what I want to find.&#xD;&#xA;&#xD;&#xA;`I want to know how to detect and recognize the drawing between different frames.` I have thought the `line detect` algorithm may work but fail. And pixel comparison seems to be bad idea. Because that the new drawing may overlap the old ones. &#xD;&#xA;&#xD;&#xA;Could you give me some information that I can read or some keywords to search? Sorry about that because I am not familiar with Computer Image Processing.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/D9UbO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4249" PostHistoryTypeId="1" PostId="1967" RevisionGUID="f8b55dda-79f6-44ea-9dcf-d54cfb666c1a" CreationDate="2016-01-26T14:39:09.130" UserId="2551" Text="reconstruction drawing sequence from video" ContentLicense="CC BY-SA 3.0" />
  <row Id="4250" PostHistoryTypeId="3" PostId="1967" RevisionGUID="f8b55dda-79f6-44ea-9dcf-d54cfb666c1a" CreationDate="2016-01-26T14:39:09.130" UserId="2551" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4251" PostHistoryTypeId="2" PostId="1968" RevisionGUID="1085b4c9-d07e-4b62-933a-df225b4dbddb" CreationDate="2016-01-26T15:37:28.180" UserId="2463" Text="The answer is surprisingly simple: You move the vertices of the face-geometry.&#xD;&#xA;&#xD;&#xA;To elaborate, the white wireframe mesh on the left of your image is placed so the geometry aligns with the photo. It is then texture-mapped with the photo, meaning that for each vertex in the mesh, a texture-coordinate is assigned (the point on the photo that should map to the vertex).&#xD;&#xA;&#xD;&#xA;With every vertex assigned a texture-coordinate you can deform the mesh, doing ordinary texture-sampling at the interpolated texture-coordinates to have the image stretch - as if it was painted onto the head.&#xD;&#xA;&#xD;&#xA;If you need to do this in realtime, you can use your graphics-card to do this; texture mapping is one of the things GPUs are really good at.&#xD;&#xA;&#xD;&#xA;Now, if you want to do this on a video, you need to track the facial features to continuously align the geometry to the video. This is not an easy task, but you can probably find a wealth of libraries to help you out.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am a bit uncertain which of the above would be difficult, so please feel free to ask any questions." ContentLicense="CC BY-SA 3.0" />
  <row Id="4252" PostHistoryTypeId="2" PostId="1969" RevisionGUID="f1a67044-3bc0-42bc-ab62-99d46b3de48c" CreationDate="2016-01-26T18:25:00.073" UserDisplayName="user1703" Text="True random scan displays aren't used anymore. They were based on cathode-ray tubes where the electron beam wasn't driven in a scanline pattern but as arbitrary line segments, with &quot;direct access&quot;.&#xD;&#xA;&#xD;&#xA;The early devices were similar to oscilloscopes, requiring frequent refreshing of the trace. Later appeared the memory devices, able to retain the image without refreshment, so that they could render arbitrarily complex drawings (with the drawback that modifying a part of the image wasn't possible).&#xD;&#xA;&#xD;&#xA;They indeed didn't really suffer from jaggies, as they were analogic devices, anyway because of digital-to-analog limitations, they had a finite resolution in practice (typically 4K x 4K).&#xD;&#xA;&#xD;&#xA;These dinosaurs have been superseded by digital frame buffers and raster displays. But sometimes the concepts of random scan and display list are mixed up." ContentLicense="CC BY-SA 3.0" />
  <row Id="4253" PostHistoryTypeId="5" PostId="1969" RevisionGUID="3f4d492d-4f97-4717-b513-29127e978ba2" CreationDate="2016-01-26T18:30:25.750" UserDisplayName="user1703" Comment="added 46 characters in body" Text="True random scan displays aren't used anymore. They were based on cathode-ray tubes where the electron beam wasn't driven in a scanline pattern but as arbitrary line segments, with &quot;direct access&quot;.&#xD;&#xA;&#xD;&#xA;The early devices were similar to oscilloscopes, requiring frequent refreshing of the trace. Later appeared the memory devices, able to retain the image without refreshment, so that they could render arbitrarily complex drawings (with the drawback that modifying a part of the image wasn't possible).&#xD;&#xA;&#xD;&#xA;They indeed didn't really suffer from jaggies, as they were analogic devices, anyway because of digital-to-analog limitations, they had a finite resolution in practice (typically 4K x 4K). They supported monochrome line drawings only.&#xD;&#xA;&#xD;&#xA;These dinosaurs have been superseded by digital frame buffers and raster displays. But sometimes the concepts of random scan and display list are mixed up." ContentLicense="CC BY-SA 3.0" />
  <row Id="4254" PostHistoryTypeId="5" PostId="1969" RevisionGUID="40c620f0-e94e-4871-961d-5ef929811a60" CreationDate="2016-01-26T18:38:52.100" UserDisplayName="user1703" Comment="added 22 characters in body" Text="True random scan displays aren't used anymore. They were based on cathode-ray tubes where the electron beam wasn't driven in a scanline pattern but as arbitrary line segments, with &quot;direct access&quot;.&#xD;&#xA;&#xD;&#xA;The early devices were similar to oscilloscopes, requiring frequent refreshing of the trace. Later appeared the memory devices, able to retain the image without refreshing, so that they could render arbitrarily complex drawings (with the drawback that modifying a part of the image wasn't possible).&#xD;&#xA;&#xD;&#xA;They indeed didn't really suffer from jaggies, as they were analogic devices, anyway because of digital-to-analog limitations, they had a finite resolution in practice (typically 1K x 1K, a wonder at the time). They allowed monochrome line drawings only.&#xD;&#xA;&#xD;&#xA;These dinosaurs have been superseded by digital frame buffers and raster displays. But sometimes the concepts of random scan and display list are mixed up." ContentLicense="CC BY-SA 3.0" />
  <row Id="4258" PostHistoryTypeId="2" PostId="1971" RevisionGUID="29aab62d-c211-468e-8691-89f43bc0f1f7" CreationDate="2016-01-27T00:08:04.783" UserId="273" Text="This is more a Computer vision question I think.&#xD;&#xA;I don't know how exactly you can achieve that but some ideas and keywords you may use to find additional resources:&#xD;&#xA;&#xD;&#xA;Feature tracking of hand and pen can yield the movement of said things. Assuming you know that the camera is not moving I think that would give you good results. Related is maybe motion tracking. Any information you have about the hand and the camera can in some way be used to make more accurate estimates.&#xD;&#xA;&#xD;&#xA;Removing the hand from the video could be much harder. I don't remember that part from my lecture. We copied parts of the image onto the part we want to remove and used image metrics to make sure it fits best possible... But since the hand covers a drawing we don't know much about this could be very hard to do in an convincing way." ContentLicense="CC BY-SA 3.0" />
  <row Id="4262" PostHistoryTypeId="2" PostId="1972" RevisionGUID="52ff1b89-dade-4d60-9647-3d6bfda55b80" CreationDate="2016-01-27T03:28:11.743" UserId="288" Text="I have been reading this paper by Timothy Wilson [Fast Stereo Rendering for VR][1]&#xD;&#xA;and it would suit our game engine (DirectX 11) to use this method of stereo rendering. I have managed to get the game rendering Instanced and the screen squished into left and right areas like he mentions but am unable to get the SV_ClipDistance working correctly, when I use his methods or the method the jMonkeyEngine uses I get 4 views of the world! &#xD;&#xA;&#xD;&#xA;My question is does anyone know if you can write SV_RenderTargetArrayIndex in a pixel shader according to MSDN it says it can be read and written by the pixel shader but in all my experimentation I am unable to get the shader to compile, it complains about too many outputs. If I could get this to work the instancing would work by just setting the SV_RenderTargetArrayIndex to SV_InstanceId. Any help would be much appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/edit#slide=id.p" ContentLicense="CC BY-SA 3.0" />
  <row Id="4263" PostHistoryTypeId="1" PostId="1972" RevisionGUID="52ff1b89-dade-4d60-9647-3d6bfda55b80" CreationDate="2016-01-27T03:28:11.743" UserId="288" Text="VR stereo rendering with Instancing" ContentLicense="CC BY-SA 3.0" />
  <row Id="4264" PostHistoryTypeId="3" PostId="1972" RevisionGUID="52ff1b89-dade-4d60-9647-3d6bfda55b80" CreationDate="2016-01-27T03:28:11.743" UserId="288" Text="|directx11|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4265" PostHistoryTypeId="5" PostId="1963" RevisionGUID="efb727de-e2be-42db-9fba-bb662bcd4b34" CreationDate="2016-01-27T04:12:43.070" UserId="31" Comment="added 357 characters in body" Text="Assume there is some value `p`, calculated per-frame, that varies continuously over the surface of an object. The value of `p` determines the density of some pattern on the surface. For example, in a case with only two possible densities if `p &lt; 0.3` it is high density, otherwise it is low.&#xD;&#xA;&#xD;&#xA;I've thought of a simple high-level solution: create two textures, each of different densities, and based on the value of `p` sample from the appropriate one. However, there's a problem with the boundary between high- and low-densities.&#xD;&#xA;&#xD;&#xA;Here is an example to illustrate the problem:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here is the threshold between low- and high- (displayed on the high density texture but that's not relevant.) If under the line, it implies the high-density texture should be sampled.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally here is the comparison between what is desired and what would actually happen using this method:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The problem is that when a high-density-only circle crosses the line, it will be ignored when `p` indicates the low-density texture to be sampled, resulting in a truncated circle. I don't know how to solve this problem because `p` varies every frame, so I can't just 'bake' a boundary between the two densities. It's easy to prevent the reverse problem by creating the high-density texture from the lower one (i.e. if a circle is on the low-density texture ensure it is on the high-density texture.) &#xD;&#xA;&#xD;&#xA;I'm interested if anyone has a way to improve my solution or even has another method entirely. The constraint here is that `p` is calculated per-frame in real-time. Another constraint is related to the pattern texture: the pattern is black and white, where black is the pattern and white is the background (like the circles in the example). The pattern may not just be identical shapes repeated, but any arrangement of arbitrary black shapes over a white background. (Maybe pattern is the wrong choice of word.)   &#xD;&#xA;&#xD;&#xA;I'm not familiar with the research in this field so I wasn't sure which keywords to search, so I'd even appreciate if anyone could point me in the right direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/krVHY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6WmhA.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DFsgY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4266" PostHistoryTypeId="5" PostId="1963" RevisionGUID="359aaec0-aed7-42aa-9dc8-5950cd9f7aaf" CreationDate="2016-01-27T04:24:43.543" UserId="31" Comment="added 118 characters in body" Text="Assume there is some value `p`, calculated per-frame, that varies continuously over the surface of an object. The value of `p` determines the density of some pattern on the surface. For example, in a case with only two possible densities if `p &lt; 0.3` it is high density, otherwise it is low.&#xD;&#xA;&#xD;&#xA;I've thought of a simple high-level solution: create two textures, each of different densities, and based on the value of `p` sample from the appropriate one. However, there's a problem with the boundary between high- and low-densities.&#xD;&#xA;&#xD;&#xA;Here is an example to illustrate the problem (note my problem is NOT exclusive to this example pattern of dots. I describe the patterns I'm working with later on):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here is the threshold between low- and high- (displayed on the high density texture but that's not relevant.) If under the line, it implies the high-density texture should be sampled.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally here is the comparison between what is desired and what would actually happen using this method:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The problem is that when a high-density-only circle crosses the line, it will be ignored when `p` indicates the low-density texture to be sampled, resulting in a truncated circle. I don't know how to solve this problem because `p` varies every frame, so I can't just 'bake' a boundary between the two densities. It's easy to prevent the reverse problem by creating the high-density texture from the lower one (i.e. if a circle is on the low-density texture ensure it is on the high-density texture.) &#xD;&#xA;&#xD;&#xA;I'm interested if anyone has a way to improve my solution or even has another method entirely. The constraint here is that `p` is calculated per-frame in real-time. Another constraint is related to the pattern texture: the pattern is black and white, where black is the pattern and white is the background (like the circles in the example). The pattern may not just be identical shapes repeated, but any arrangement of arbitrary black shapes over a white background. (Maybe pattern is the wrong choice of word.)   &#xD;&#xA;&#xD;&#xA;I'm not familiar with the research in this field so I wasn't sure which keywords to search, so I'd even appreciate if anyone could point me in the right direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/krVHY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6WmhA.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DFsgY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4267" PostHistoryTypeId="2" PostId="1973" RevisionGUID="573570d2-8af7-4a0d-abba-8fde5111bf0c" CreationDate="2016-01-27T07:15:21.190" UserId="48" Text="While [this MSDN page](https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647%28v=vs.85%29.aspx) does claim that SV_RenderTargetArrayIndex can be written in a pixel shader, I believe this is incorrect. Viewport array index and RT array index values are both intended to be output by the geometry shader stage. They can then be read by the pixel shader (and have a constant value per-primitive, based on the GS output). However, it is not possible to set these values from the pixel shader.&#xD;&#xA;&#xD;&#xA;The stereo instancing approach detailed in those slides is interesting precisely because it avoids using slow geometry shaders. However, if you're not using GS, you can't use multiple viewports or render target arrays. That's why the stereo instancing approach uses one large viewport and bakes each eye's viewport transform into its projection matrix, and requires clip planes.&#xD;&#xA;&#xD;&#xA;Clip planes should work, so if you're having problems with them, you could post another question detailing the specific issues (preferably with screenshots) and we can try to figure that out.&#xD;&#xA;&#xD;&#xA;(For completeness, note that if you're using OpenGL, the [GL_AMD_vertex_shader_viewport_index](https://www.opengl.org/registry/specs/AMD/vertex_shader_viewport_index.txt) extension is available on [recent GPUs from all three IHVs](http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_AMD_vertex_shader_viewport_index) and allows setting the viewport index from the vertex shader.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4268" PostHistoryTypeId="5" PostId="1967" RevisionGUID="20eac29d-1a39-4265-9ffa-f869ad0fbc29" CreationDate="2016-01-27T08:58:35.977" UserId="2041" Comment="Don't use `code formatting` for things that aren't code, as it makes your questoin harder to read, and screws up screen-readers." Text="I have a video that record the drawing sequence with a pencil by a painter.&#xD;&#xA;[![video screen][1]][1]&#xD;&#xA;&#xD;&#xA;I want to reconstruction the sequence from the video.&#xD;&#xA;And I have google some keywords like *drawing sequence reconstruction*, *sketch reconstruction*, and have searched like *moving object detection* but cannot found what I want to find.&#xD;&#xA;&#xD;&#xA;I want to know how to detect and recognize the drawing between different frames. I have thought the *line detect* algorithm may work but fail. And pixel comparison seems to be bad idea. Because that the new drawing may overlap the old ones. &#xD;&#xA;&#xD;&#xA;Could you give me some information that I can read or some keywords to search? Sorry about that because I am not familiar with Computer Image Processing.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/D9UbO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4269" PostHistoryTypeId="24" PostId="1967" RevisionGUID="20eac29d-1a39-4265-9ffa-f869ad0fbc29" CreationDate="2016-01-27T08:58:35.977" Comment="Proposed by 2041 approved by 38, 100 edit id of 120" ContentLicense="CC BY-SA 3.0" />
  <row Id="4272" PostHistoryTypeId="2" PostId="1974" RevisionGUID="afa9f563-c024-416e-949f-00a84bcd6b78" CreationDate="2016-01-28T12:31:35.720" UserId="141" Text="How to reliably find out whether two Bezier curves intersect? By &quot;reliably&quot; I mean the test will answer &quot;yes&quot; only when the curves intersect, and &quot;no&quot; only when they don't intersect. I don't need to know what parameters the intersection was found at. I also would like to use floating-point numbers in the implementation.&#xD;&#xA;&#xD;&#xA;I found several answers on StackOverflow which use the curves' bounding-boxes for the test: this is not what I'm after as such test may report intersection even if the curves don't intersect.&#xD;&#xA;&#xD;&#xA;The closest thing I found so far is the &quot;bounding wedge&quot; by Sederberg and Meyers but it &quot;only&quot; distinguishes between at-most-one and two-or-more intersection, whereas I want to know if there is at-most-zero and one-or-more intersections." ContentLicense="CC BY-SA 3.0" />
  <row Id="4273" PostHistoryTypeId="1" PostId="1974" RevisionGUID="afa9f563-c024-416e-949f-00a84bcd6b78" CreationDate="2016-01-28T12:31:35.720" UserId="141" Text="Reliable test for intersection of two Bezier curves" ContentLicense="CC BY-SA 3.0" />
  <row Id="4274" PostHistoryTypeId="3" PostId="1974" RevisionGUID="afa9f563-c024-416e-949f-00a84bcd6b78" CreationDate="2016-01-28T12:31:35.720" UserId="141" Text="|computational-geometry|bezier-curve|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4275" PostHistoryTypeId="2" PostId="1975" RevisionGUID="0aba4399-732f-46ec-9135-8ae07d2254c8" CreationDate="2016-01-28T13:15:28.897" UserId="2479" Text="I don't know whether this is the only cause of your problems, but the Russian roulette is messed up for sure. stopProbability acts as the survivalProbability in your code; therefore, you compensate the estimate with a different factor than you should, which makes the result heavily biased in one direction.&#xD;&#xA;&#xD;&#xA;I would put the code as follows to make it more comprehensible:&#xD;&#xA;&#xD;&#xA;    const float survivalProbability = 0.9f;&#xD;&#xA;    if(((float)rand()/RAND_MAX) &gt; survivalProbability)&#xD;&#xA;        break;&#xD;&#xA;    rrFactor *= 1.0f/survivalProbability;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4276" PostHistoryTypeId="5" PostId="1975" RevisionGUID="712c3101-d2eb-4829-9bca-c6d232257581" CreationDate="2016-01-28T13:24:04.733" UserId="2479" Comment="minor" Text="I don't know whether this is the only cause of your problems, but the Russian roulette is messed up for sure. stopProbability acts as the survivalProbability in your code; therefore, you compensate the estimate with a different factor than you should, which makes the result heavily biased.&#xD;&#xA;&#xD;&#xA;I would put the code as follows to make it more comprehensible:&#xD;&#xA;&#xD;&#xA;    const float survivalProbability = 0.9f;&#xD;&#xA;    if(((float)rand()/RAND_MAX) &gt; survivalProbability)&#xD;&#xA;        break;&#xD;&#xA;    rrFactor *= 1.0f/survivalProbability;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4277" PostHistoryTypeId="5" PostId="1974" RevisionGUID="cf8182ca-c7c3-4f31-937b-efc9cb02c7ee" CreationDate="2016-01-28T15:24:46.867" UserId="141" Comment="added 43 characters in body" Text="How to reliably find out whether two Bezier curves intersect? By &quot;reliably&quot; I mean the test will answer &quot;yes&quot; only when the curves intersect, and &quot;no&quot; only when they don't intersect. I don't need to know what parameters the intersection was found at. I also would like to use floating-point numbers in the implementation.&#xD;&#xA;&#xD;&#xA;I found several answers on StackOverflow which use the curves' bounding-boxes for the test: this is not what I'm after as such test may report intersection even if the curves don't intersect.&#xD;&#xA;&#xD;&#xA;The closest thing I found so far is the &quot;[bounding wedge](http://dl.acm.org/citation.cfm?id=49188)&quot; by Sederberg and Meyers but it &quot;only&quot; distinguishes between at-most-one and two-or-more intersection, whereas I want to know if there is at-most-zero and one-or-more intersections." ContentLicense="CC BY-SA 3.0" />
  <row Id="4278" PostHistoryTypeId="2" PostId="1976" RevisionGUID="e2b0e208-995e-4839-9b22-8cc2996c7781" CreationDate="2016-01-28T18:47:33.133" UserId="2233" Text="I want to ray trace a triangular mesh that I load from a file. The vertices' coordinates are expressed in the reference frame associated with the object  (i.e the mesh) and I don't know the object-to-world matrix. Is there a way to calculate this matrix given these coordinates? If no, how can I ensure that the mesh's triangles are transformed to the world's reference frame? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4279" PostHistoryTypeId="1" PostId="1976" RevisionGUID="e2b0e208-995e-4839-9b22-8cc2996c7781" CreationDate="2016-01-28T18:47:33.133" UserId="2233" Text="How to determine the object-to-world matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="4280" PostHistoryTypeId="3" PostId="1976" RevisionGUID="e2b0e208-995e-4839-9b22-8cc2996c7781" CreationDate="2016-01-28T18:47:33.133" UserId="2233" Text="|raytracing|rendering|transformations|mesh|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4281" PostHistoryTypeId="2" PostId="1977" RevisionGUID="04003996-0e59-4e36-94ac-d76894dee374" CreationDate="2016-01-28T18:56:25.217" UserId="38" Text="No! If you dont have this info and must have a extra frame, just assume the reference frame is a identity matrix\*. The point of the extra reference frame is just to be able to move the object but if you have no info about how the object should relate to other objects it does not really matter operator can move it where they want. Everything is relative, if theres no relation then no problems.&#xD;&#xA;&#xD;&#xA;\* choosing identity is like choosing a arbitrary constant to be 1, its numerically easy to work with." ContentLicense="CC BY-SA 3.0" />
  <row Id="4282" PostHistoryTypeId="2" PostId="1978" RevisionGUID="257b7ee6-4e6b-45b6-a911-ebc00a86f7c9" CreationDate="2016-01-28T20:06:48.473" UserId="273" Text="The Object-To-World matrix is often called &quot;model-matrix&quot;.&#xD;&#xA;&#xD;&#xA;This martix tells us how the object relates to some &quot;World&quot;. This world is relative and arbitrary but really convenient because we can place all our objects and even the camera in it and the math works out pretty well.&#xD;&#xA;&#xD;&#xA;The short answer is, that you imagine that the model is defined in the origin of the world, so that the center of gravity of the object lies exactly in the $(0.0, 0.0, 0.0)$ position of the world.&#xD;&#xA;&#xD;&#xA;Now if you want to place multiple objects in the same scene, you have to give them a position, and it is really convenient to give all objects a position relative to this world-origin. So you just create a matrix for each object that tells you how you move the object in relation to the world-origin.&#xD;&#xA;&#xD;&#xA;For example translating an object is $\begin{bmatrix} 0 &amp; 0 &amp; 0 &amp; x \\ 0 &amp; 0 &amp; 0 &amp; y \\ 0 &amp; 0 &amp; 0 &amp; z \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix} $ then your object will have the world-relative position of $(x, y, z)$ (I will omit the useage of homogeneous coordinates which would be better suited for another question).&#xD;&#xA;&#xD;&#xA;In a similar fashion you can use translation, scaling and rotation (take care of what order you apply these transformations)&#xD;&#xA;&#xD;&#xA;Things get a bit complicated if you want to do camera-space computations and projections and stuff like that, but in the simplest version you can just build your model-matrix this way.&#xD;&#xA;&#xD;&#xA;Multiplying each point of your model with this model-matrix gives you the position of the point in world-space (meaning relative to the origin of the world!) and for meshes this moves the whole model just as you would expect." ContentLicense="CC BY-SA 3.0" />
  <row Id="4283" PostHistoryTypeId="2" PostId="1979" RevisionGUID="26d7025b-802a-4768-a32d-522e79a331ab" CreationDate="2016-01-29T01:04:29.930" UserId="2572" Text="I'm a Computer Science student who's been getting into bitmaps &amp; pixmaps recently. I clearly understand what pixmaps do. A pixmap, as I understand, defines each pixel individually. So, maybe I could write a pixmap filelike this:&#xD;&#xA;&#xD;&#xA;255,0,0 0,255,0 0,0,255&#xD;&#xA;&#xD;&#xA;which would give me a red pixel, a green pixel, and a blue pixel.&#xD;&#xA;&#xD;&#xA;Seems pretty straightforward.&#xD;&#xA;&#xD;&#xA;However, I fail to understand exactly how bitmaps work. I mean, I understand that a bitmap simply maps a bit to some color at some point on the screen. I watched a YouTube video on how to create a bitmap file, but the guy's explanation of what a bitmap file is went over my head." ContentLicense="CC BY-SA 3.0" />
  <row Id="4284" PostHistoryTypeId="1" PostId="1979" RevisionGUID="26d7025b-802a-4768-a32d-522e79a331ab" CreationDate="2016-01-29T01:04:29.930" UserId="2572" Text="How do I create my own bitmap using a text editor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4285" PostHistoryTypeId="3" PostId="1979" RevisionGUID="26d7025b-802a-4768-a32d-522e79a331ab" CreationDate="2016-01-29T01:04:29.930" UserId="2572" Text="|bitmap-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4286" PostHistoryTypeId="5" PostId="1979" RevisionGUID="ccff85d6-c151-4a6b-93c1-31e14a89ed93" CreationDate="2016-01-29T01:26:15.110" UserId="2572" Comment="added 251 characters in body" Text="I'm a Computer Science student who's been getting into bitmaps &amp; pixmaps recently. I clearly understand what pixmaps do. A pixmap, as I understand, defines each pixel individually. So, maybe I could write a pixmap filelike this:&#xD;&#xA;&#xD;&#xA;255,0,0 0,255,0 0,0,255&#xD;&#xA;&#xD;&#xA;which would give me a red pixel, a green pixel, and a blue pixel.&#xD;&#xA;&#xD;&#xA;Seems pretty straightforward.&#xD;&#xA;&#xD;&#xA;However, I fail to understand exactly how bitmaps work. I mean, I understand that a bitmap simply maps a bit to some color at some point on the screen. I watched a YouTube video on how to create a bitmap file, but the guy's explanation of what a bitmap file is went over my head.&#xD;&#xA;&#xD;&#xA;Edit: I feel I now have a better conceptual grasp of what a bitmap is. Well, maybe not. Each bit in a bitmap corresponds to a certain color that is defined somewhere in the file. But how does the computer know which bit corresponds to which color?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4287" PostHistoryTypeId="2" PostId="1980" RevisionGUID="967d02d7-16c5-40b8-8d33-bf04afa113fa" CreationDate="2016-01-29T02:57:40.227" UserId="231" Text="In addition to the pixel values, the width and height of the image are also required, and the colour depth (how many colours are available per pixel). Some formats also specify an alpha value, for transparency, which may be defined per pixel in addition to the red, green and blue components.&#xD;&#xA;&#xD;&#xA;There are many different image file formats but a simple one to experiment with to gain understanding is ppm, one of the [Netpbm formats].&#xD;&#xA;&#xD;&#xA;Netpbm defines the following file types:&#xD;&#xA;&#xD;&#xA;- **PBM:** portable bitmap (pixels are either on or off)&#xD;&#xA;- **PGM:** portable graymap (grayscale pixels)&#xD;&#xA;- **PPM:** portable pixmap (full colour pixels)&#xD;&#xA;&#xD;&#xA;These have the advantages of being simple to understand, and easy to generate in a text editor for working with simple examples.&#xD;&#xA;&#xD;&#xA;For example, a PPM file is simply the characters &quot;P3&quot; to identify it as PPM, followed by the width, height, maximum colour value and the pixel values in English reading order (left to right then top to bottom). All these values are space separated and human readable. While this makes the format very easy to work with for small examples, it will also make the file size much larger than other formats which include compression (either lossless or lossy).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Netpbm formats]: https://en.wikipedia.org/wiki/Netpbm_format" ContentLicense="CC BY-SA 3.0" />
  <row Id="4288" PostHistoryTypeId="5" PostId="1980" RevisionGUID="13aababf-be7e-4dbd-9323-ac4ef3b4a8aa" CreationDate="2016-01-29T03:22:10.900" UserId="231" Comment="Add detail" Text="In addition to the pixel values, the width and height of the image are also required, and the colour depth (how many colours are available per pixel). Some formats also specify an alpha value, for transparency, which may be defined per pixel in addition to the red, green and blue components.&#xD;&#xA;&#xD;&#xA;There are many different image file formats but a simple one to experiment with to gain understanding is ppm, one of the [Netpbm formats].&#xD;&#xA;&#xD;&#xA;Netpbm defines the following file types:&#xD;&#xA;&#xD;&#xA;- **PBM:** portable bitmap (pixels are either on or off)&#xD;&#xA;- **PGM:** portable graymap (grayscale pixels)&#xD;&#xA;- **PPM:** portable pixmap (full colour pixels)&#xD;&#xA;&#xD;&#xA;These have the advantages of being simple to understand, and easy to generate in a text editor for working with simple examples.&#xD;&#xA;&#xD;&#xA;For example, a PPM file is simply the characters &quot;P3&quot; to identify it as PPM, followed by the width, height, maximum colour value and the pixel values in English reading order (left to right then top to bottom). Each pixel colour is a red value, a green value, and a blue value. All these values are space separated and human readable. &#xD;&#xA;&#xD;&#xA;    P3                         # Indicates an ASCII PPM file&#xD;&#xA;    2 2                        # Width and height of the image&#xD;&#xA;    255                        # Maximum colour value&#xD;&#xA;    255 0 0     0   255 0      # A red pixel (255 0 0) followed by a green pixel&#xD;&#xA;    0   0 255   255 255 255    # A blue pixel followed by a white pixel&#xD;&#xA;&#xD;&#xA;While this makes the format very easy to work with for small examples, it will also make the file size much larger than other formats which use bytes to represent colour components instead of writing out the human readable numbers. Many formats also include compression (either lossless or lossy).&#xD;&#xA;&#xD;&#xA;Once you are accustomed to writing PPM files in ASCII characters, indicated by the file starting with &quot;P3&quot;, you can move on to PPM files using bytes, indicated by the file starting with &quot;P6&quot;. This is a similar format to what many programs use internally, but is no longer human readable in a text editor as not every byte will correspond to a printable ASCII character.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Netpbm formats]: https://en.wikipedia.org/wiki/Netpbm_format&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4289" PostHistoryTypeId="5" PostId="1980" RevisionGUID="bcaa5675-38cf-4ea6-aa81-21a8de508daa" CreationDate="2016-01-29T03:33:40.947" UserId="231" Comment="Add detail" Text="In addition to the pixel values, the width and height of the image are also required, and the colour depth (how many colours are available per pixel). Some formats also specify an alpha value, for transparency, which may be defined per pixel in addition to the red, green and blue components.&#xD;&#xA;&#xD;&#xA;There are many different image file formats but a simple one to experiment with to gain understanding is ppm, one of the [Netpbm formats].&#xD;&#xA;&#xD;&#xA;Netpbm defines the following file types:&#xD;&#xA;&#xD;&#xA;- **PBM:** portable bitmap (pixels are either on or off)&#xD;&#xA;- **PGM:** portable graymap (grayscale pixels)&#xD;&#xA;- **PPM:** portable pixmap (full colour pixels)&#xD;&#xA;&#xD;&#xA;These have the advantages of being simple to understand, and easy to generate in a text editor for working with simple examples.&#xD;&#xA;&#xD;&#xA;For example, a PPM file is simply the characters &quot;P3&quot; to identify it as PPM, followed by the width, height, maximum colour value and the pixel values in English reading order (left to right then top to bottom). Each pixel colour is a red value, a green value, and a blue value. All these values are space separated and human readable. &#xD;&#xA;&#xD;&#xA;    P3                         # Indicates an ASCII PPM file&#xD;&#xA;    2 2                        # Width and height of the image&#xD;&#xA;    255                        # Maximum colour value&#xD;&#xA;    255 0 0     0   255 0      # A red pixel (255 0 0) followed by a green pixel&#xD;&#xA;    0   0 255   255 255 255    # A blue pixel followed by a white pixel&#xD;&#xA;&#xD;&#xA;While this makes the format very easy to work with for small examples, it will also make the file size much larger than other formats which use bytes to represent colour components instead of writing out the human readable numbers. Many formats also include compression (either lossless or lossy).&#xD;&#xA;&#xD;&#xA;Once you are accustomed to writing PPM files in ASCII characters, indicated by the file starting with &quot;P3&quot;, you can move on to PPM files using bytes, indicated by the file starting with &quot;P6&quot;. This is a similar format to what many programs use internally, but is no longer human readable in a text editor as not every byte will correspond to a printable ASCII character.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;You also mention that a pixmap can have pixel values that refer to colours stored elsewhere in the file. I have avoided this format as it is not necessary for understanding how a pixmap works. This is known as using a palette (a list of predefined colours so each pixel is represented by an index of a colour in the palette). This is necessary for formats that only allow a small number of distinct colours, but for full colour images there is no need for a palette - each pixel is defined as red, green and blue components without having to refer to anything else.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Netpbm formats]: https://en.wikipedia.org/wiki/Netpbm_format&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4290" PostHistoryTypeId="5" PostId="1978" RevisionGUID="d131bde9-fba8-465b-a15c-26b13f38d74e" CreationDate="2016-01-29T03:35:00.793" UserDisplayName="user2500" Comment="Added ones on the diagonal." Text="The Object-To-World matrix is often called &quot;model-matrix&quot;.&#xD;&#xA;&#xD;&#xA;This martix tells us how the object relates to some &quot;World&quot;. This world is relative and arbitrary but really convenient because we can place all our objects and even the camera in it and the math works out pretty well.&#xD;&#xA;&#xD;&#xA;The short answer is, that you imagine that the model is defined in the origin of the world, so that the center of gravity of the object lies exactly in the $(0.0, 0.0, 0.0)$ position of the world.&#xD;&#xA;&#xD;&#xA;Now if you want to place multiple objects in the same scene, you have to give them a position, and it is really convenient to give all objects a position relative to this world-origin. So you just create a matrix for each object that tells you how you move the object in relation to the world-origin.&#xD;&#xA;&#xD;&#xA;For example translating an object is $\begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; x \\ 0 &amp; 1 &amp; 0 &amp; y \\ 0 &amp; 0 &amp; 1 &amp; z \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix} $ then your object will have the world-relative position of $(x, y, z)$ (I will omit the useage of homogeneous coordinates which would be better suited for another question).&#xD;&#xA;&#xD;&#xA;In a similar fashion you can use translation, scaling and rotation (take care of what order you apply these transformations)&#xD;&#xA;&#xD;&#xA;Things get a bit complicated if you want to do camera-space computations and projections and stuff like that, but in the simplest version you can just build your model-matrix this way.&#xD;&#xA;&#xD;&#xA;Multiplying each point of your model with this model-matrix gives you the position of the point in world-space (meaning relative to the origin of the world!) and for meshes this moves the whole model just as you would expect." ContentLicense="CC BY-SA 3.0" />
  <row Id="4291" PostHistoryTypeId="24" PostId="1978" RevisionGUID="d131bde9-fba8-465b-a15c-26b13f38d74e" CreationDate="2016-01-29T03:35:00.793" Comment="Proposed by 2500 approved by 231 edit id of 121" ContentLicense="CC BY-SA 3.0" />
  <row Id="4292" PostHistoryTypeId="2" PostId="1981" RevisionGUID="a6224d49-49dc-4ab3-b3fc-b524489f62e1" CreationDate="2016-01-29T09:03:42.017" UserId="38" Text="Bitmap is simply means to convert a data range to bits. How that internally works and what the conversion function is, is application dependent. Each format can work differently. &#xD;&#xA;&#xD;&#xA;Simplest possible bitmaps just store the values directly in the bits themselves. Think of the the simplest form, a pixmap but instead of ASCII values you are using full byte per color. Off course the data does not need to be byte aligned so 3 values may be crammed to 2 bytes for example. Some formats may be using indexed colors (which is what you describe in your edit), this is a form of a compression scheme.&#xD;&#xA;&#xD;&#xA;[![A hypothethical bitmap][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A hypothetical bitmap with 15 bits per pixel (for 5 bits per color), similar arrangement is used by some bitmap formats (this actual pattern is available in BMP). For a actual format read for example about the [BMP format](https://en.wikipedia.org/wiki/BMP_file_format) on wikipedia.&#xD;&#xA;&#xD;&#xA;Because the lower bit depths have very little space for color values these formats are often accompanied by a lookup table instead. This allows you to store a custom set of colors very tightly packed while allowing for a sensible variance.&#xD;&#xA;&#xD;&#xA;[![indexed bitmap][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Indexed bitmaps store a lookup array from where they take the actual color. &#xD;&#xA;&#xD;&#xA;There are many such formats that you could type in with a text editor if you must. However, since your dealing with individual bits its much easier to do this with a **[hex editor](https://en.wikipedia.org/wiki/Hex_editor)** instead as the data is essentially binary. In practice it is easier to write a script to dump full values in the file, except perhaps in the 1 byte is one channel scenario where a hex editor works fine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j130t.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/iurjI.gif&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4293" PostHistoryTypeId="5" PostId="1981" RevisionGUID="d70c86df-3755-4350-bfcd-5efdc51c072a" CreationDate="2016-01-29T09:22:36.483" UserId="38" Comment="added 391 characters in body" Text="Bitmap is simply means to convert a data range to bits. How that internally works and what the conversion function is, is application dependent. Each format can work differently. &#xD;&#xA;&#xD;&#xA;Simplest possible bitmaps just store the values directly in the bits themselves. Think of the the simplest form, a pixmap but instead of ASCII values you are using full byte per color. Off course the data does not need to be byte aligned so 3 values may be crammed to 2 bytes for example. Some formats may be using indexed colors (which is what you describe in your edit), this is a form of a compression scheme.&#xD;&#xA;&#xD;&#xA;[![A hypothethical bitmap][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A hypothetical bitmap with 15 bits per pixel (for 5 bits per color), similar arrangement is used by some bitmap formats (this actual pattern is available in BMP). For a actual format read for example about the [BMP format](https://en.wikipedia.org/wiki/BMP_file_format) on wikipedia.&#xD;&#xA;&#xD;&#xA;Because the lower bit depths have very little space for color values these formats are often accompanied by a lookup table instead. This allows you to store a custom set of colors very tightly packed while allowing for a sensible variance.&#xD;&#xA;&#xD;&#xA;[![indexed bitmap][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Indexed bitmaps store a lookup array from where they take the actual color. &#xD;&#xA;&#xD;&#xA;Note that some formats may have pretty sophisticated transforms, or the data is compressed further by some more elaborate compression scheme. But even so a compression of $2/3$ and especially the indexed $1/6$ is pretty good for something that naturally tends to take up space. Off course if we compare with a ASCII pixmap those compression ratios are already quite significantly higher.&#xD;&#xA;&#xD;&#xA;There are many such formats that you could type in with a text editor if you must. However, since your dealing with individual bits its much easier to do this with a **[hex editor](https://en.wikipedia.org/wiki/Hex_editor)** instead as the data is essentially binary. In practice it is easier to write a script to dump full values in the file, except perhaps in the 1 byte is one channel scenario where a hex editor works fine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j130t.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/iurjI.gif&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4294" PostHistoryTypeId="5" PostId="1974" RevisionGUID="efc0a1d2-ce62-4c01-9a8b-ef39be2e0e53" CreationDate="2016-01-29T09:47:24.390" UserId="141" Comment="added 7 characters in body" Text="How to reliably find out whether two planar Bezier curves intersect? By &quot;reliably&quot; I mean the test will answer &quot;yes&quot; only when the curves intersect, and &quot;no&quot; only when they don't intersect. I don't need to know what parameters the intersection was found at. I also would like to use floating-point numbers in the implementation.&#xD;&#xA;&#xD;&#xA;I found several answers on StackOverflow which use the curves' bounding-boxes for the test: this is not what I'm after as such test may report intersection even if the curves don't intersect.&#xD;&#xA;&#xD;&#xA;The closest thing I found so far is the &quot;[bounding wedge](http://dl.acm.org/citation.cfm?id=49188)&quot; by Sederberg and Meyers but it &quot;only&quot; distinguishes between at-most-one and two-or-more intersection, whereas I want to know if there is at-most-zero and one-or-more intersections." ContentLicense="CC BY-SA 3.0" />
  <row Id="4296" PostHistoryTypeId="2" PostId="1982" RevisionGUID="a256e87b-563f-4ab9-b8e9-932d70e002e4" CreationDate="2016-01-29T14:04:26.613" UserId="209" Text="[Disclaimer: I think the following should work but have not actually coded it myself]&#xD;&#xA;&#xD;&#xA;I couldn't think of a &quot;trivial&quot; method of producing a yes/no answer but the following would be a reasonable approach to a practical solution to the question.&#xD;&#xA;&#xD;&#xA;Let's assume our curves are _A(s)_ and _B(t)_ with control points {A0, A1..An} and {B0..Bm} respectively.&#xD;&#xA;&#xD;&#xA;It seems to me that, given a pair of 2D Beziers for which we wish to determine do or don't intersect, there are six cases to consider:&#xD;&#xA;&#xD;&#xA; 1. Case where we can &quot;trivially&quot; determine they do *not* intersect.&#xD;&#xA;&#xD;&#xA; 2. Case where they intersect a finite number of times and we can &quot;easily&quot; determine they definitely intersect at least once (but we don't actually care where that/those intersections occur)&#xD;&#xA;&#xD;&#xA; 3. One of the Beziers is degenerate, i.e. a point (which will occur if all the control points are identical). We canassume we've already handled the case where both are points.&#xD;&#xA;&#xD;&#xA; 4. One or more of the curves are closed, eg. A0==An. To make life simpler, we'll subdivide such curve and start again.&#xD;&#xA;&#xD;&#xA; 4. There are an infinite number of points of intersection because each is a overlapping subset of a &quot;parent&quot; Bezier.&#xD;&#xA;&#xD;&#xA; 5. We aren't certain about the above cases and need further investigation&#xD;&#xA;&#xD;&#xA;For the moment we'll ignore 3 and 4, but come back to them later.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 1 ###&#xD;&#xA;As you hint in your question, if the respective bounding boxes of the control points of _A_ and _B_), don't intersect, then the curves can't intersect. Obviously this is a quick reject test but it's overly conservative.&#xD;&#xA;As you probably know, with a Bezier curve, the convex hull of its control points forms a (tighter) bound on the curve. We can thus use the separating axis technique to decide if the hulls of _A_ and _B_ don't intersect. (e.g. as shown in Wikipedia:)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Case 2 ###&#xD;&#xA;If the case 1 test fails, you could then check for the &quot;trivial&quot; existence of an intersection. Now there are probably better ways to do this, but the following, relatively cheap, approach occurred to me:&#xD;&#xA;&#xD;&#xA;Consider just curve A:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;We know the curve starts at A0, terminates at An, and will lie inside the convex hull. For simplicity let us compute the direction of the line segment A0_An and the compute the bounds on either side (i.e. take dot products of the remaining control points against the perpendicular to A0_An).&#xD;&#xA;&#xD;&#xA;If we do the same with curve B we get the following (possible) case:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we find A0 and An are on the outsides of the bounds of B _AND_ that B0 and Bm are on the outsides of the bounds of A, then, by the continuity of Beziers, there must be at least one intersection.&#xD;&#xA;&#xD;&#xA;### Case 5 ###&#xD;&#xA;If we can't immediately show either of the above cases, then split each of the Beziers into two &quot;halves&quot;, i.e. AP1, AP2, BP1, BP2. This is relatively straightforward (left as an exercise to the reader) but is [particularly trivial for quadratic Beziers](https://computergraphics.stackexchange.com/questions/1895/how-should-i-fill-a-shape-consisting-of-bezier-cures-and-straight-lines/1899#1899): &#xD;&#xA;&#xD;&#xA;Recursively compare the 4 combinations: (AP1,BP1), (AP2, BP1)...(AP2, BP2).&#xD;&#xA;Clearly if all pass case 1, there is no intersection.&#xD;&#xA;If any fail 1, then continue with the rest of the tests.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 3 &amp; 4 ###&#xD;&#xA;This is where it becomes tedious. If case 3 gets past the &quot;case 1&quot; test, it seems to me that you need to solve for&#xD;&#xA;&#xD;&#xA;(SORRY INCOMPLETE... will come back when I have spare time)&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/u4AxW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2An9z.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dX6l0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4297" PostHistoryTypeId="5" PostId="1982" RevisionGUID="1a174115-44bb-409f-807c-425d69b98ea7" CreationDate="2016-01-29T15:53:10.070" UserId="209" Comment="added 14 characters in body" Text="[Disclaimer: I think the following should work but have not actually coded it myself]&#xD;&#xA;&#xD;&#xA;I couldn't think of a &quot;trivial&quot; method of producing a yes/no answer but the following would be a reasonable approach to a practical solution to the question.&#xD;&#xA;&#xD;&#xA;Let's assume our curves are _A(s)_ and _B(t)_ with control points {_A0, A1..An_} and {_B0,..Bm_} respectively.&#xD;&#xA;&#xD;&#xA;It seems to me that, given a pair of 2D Beziers for which we wish to determine do or don't intersect, there are six cases to consider:&#xD;&#xA;&#xD;&#xA; 1. Case where we can &quot;trivially&quot; determine they do *not* intersect.&#xD;&#xA;&#xD;&#xA; 2. Case where they intersect a finite number of times and we can &quot;easily&quot; determine they definitely intersect at least once (but we don't actually care where that/those intersections occur)&#xD;&#xA;&#xD;&#xA; 3. One of the Beziers is degenerate, i.e. a point (which will occur if all the control points are identical). We canassume we've already handled the case where both are points.&#xD;&#xA;&#xD;&#xA; 4. One or more of the curves are closed, eg. A0==An. To make life simpler, we'll subdivide such curve and start again.&#xD;&#xA;&#xD;&#xA; 4. There are an infinite number of points of intersection because each is a overlapping subset of a &quot;parent&quot; Bezier.&#xD;&#xA;&#xD;&#xA; 5. We aren't certain about the above cases and need further investigation&#xD;&#xA;&#xD;&#xA;For the moment we'll ignore 3 and 4, but come back to them later.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 1 ###&#xD;&#xA;As you hint in your question, if the respective bounding boxes of the control points of _A_ and _B_), don't intersect, then the curves can't intersect. Obviously this is a quick reject test but it's overly conservative.&#xD;&#xA;As you probably know, with a Bezier curve, the convex hull of its control points forms a (tighter) bound on the curve. We can thus use the separating axis technique to decide if the hulls of _A_ and _B_ don't intersect. (e.g. as shown in Wikipedia:)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Case 2 ###&#xD;&#xA;If the case 1 test fails, you could then check for the &quot;trivial&quot; existence of an intersection. Now there are probably better ways to do this, but the following, relatively cheap, approach occurred to me:&#xD;&#xA;&#xD;&#xA;Consider just curve A:&#xD;&#xA;&#xD;&#xA;[![&quot;Fat line&quot; bounds of a Bezier][2]][2]&#xD;&#xA;&#xD;&#xA;We know the curve starts at _A0_, terminates at _An_, and will lie inside the convex hull. For simplicity let us compute the direction of the line segment A0_An and the compute the bounds on either side (i.e. take dot products of the remaining control points against the perpendicular to A0_An).&#xD;&#xA;&#xD;&#xA;If we do the same with curve B we get the following (possible) case:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we find A0 and An are on the outsides of the bounds of B _AND_ that B0 and Bm are on the outsides of the bounds of A, then, by the continuity of Beziers, there must be at least one intersection.&#xD;&#xA;&#xD;&#xA;### Case 5 ###&#xD;&#xA;If we can't immediately show either of the above cases, then split each of the Beziers into two &quot;halves&quot;, i.e. AP1, AP2, BP1, BP2. This is relatively straightforward (left as an exercise to the reader) but is [particularly trivial for quadratic Beziers](https://computergraphics.stackexchange.com/questions/1895/how-should-i-fill-a-shape-consisting-of-bezier-cures-and-straight-lines/1899#1899): &#xD;&#xA;&#xD;&#xA;Recursively compare the 4 combinations: (AP1,BP1), (AP2, BP1)...(AP2, BP2).&#xD;&#xA;Clearly if all pass case 1, there is no intersection.&#xD;&#xA;If any fail 1, then continue with the rest of the tests.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 3 &amp; 4 ###&#xD;&#xA;This is where it becomes tedious. If case 3 gets past the &quot;case 1&quot; test, it seems to me that you need to solve for&#xD;&#xA;&#xD;&#xA;(SORRY INCOMPLETE... will come back when I have spare time)&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/u4AxW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2An9z.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dX6l0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4298" PostHistoryTypeId="2" PostId="1983" RevisionGUID="3030c3ab-5700-496d-ab0f-2248f2a2b489" CreationDate="2016-01-29T19:14:03.043" UserId="2574" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its ban on original research.&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**A source that comes close**&#xD;&#xA;&#xD;&#xA;D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available if you google the title. Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a section of an ellipse; ***this, or something equivalent to it, is the formula for which I need a reference:***&#xD;&#xA;&#xD;&#xA;$(y(k-k^{-1})-1)^{2}+(k^{2}-1)x^{2}=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $k=\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$: $\epsilon=h/R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, where $\alpha=\pi/2$ corresponds to the point at which the pinhole camera is trained.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see this: imgur.com/gallery/Bi5cT .&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4299" PostHistoryTypeId="1" PostId="1983" RevisionGUID="3030c3ab-5700-496d-ab0f-2248f2a2b489" CreationDate="2016-01-29T19:14:03.043" UserId="2574" Text="Need a reputable source for the formula for the shape of Earth's horizon" ContentLicense="CC BY-SA 3.0" />
  <row Id="4300" PostHistoryTypeId="3" PostId="1983" RevisionGUID="3030c3ab-5700-496d-ab0f-2248f2a2b489" CreationDate="2016-01-29T19:14:03.043" UserId="2574" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4301" PostHistoryTypeId="2" PostId="1984" RevisionGUID="43e5e91a-7305-4148-9495-08533b28c600" CreationDate="2016-01-29T20:54:03.493" UserId="38" Text="I am trying to figure out how to convert a flat representation of a curve into the silhouette of a surface of revolution in a isometric projection. In essence in want the planar cut of the surface edge to be converted to the silhouette.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Starting point.&#xD;&#xA;&#xD;&#xA;The geometry in this case is a Bézier curve although if somebody has solutions for any functions or higher order curves would be fine. So in essence im open to conics and NURBS also.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: End result. How to transform the magenta curves?&#xD;&#xA;&#xD;&#xA;The way I've done this now is by sampling several forms and in this case draw the new curve over the points. But id like to do this automatically and more precise. Please note: I am perfectly aware on how to do this with discrete data, I am looking for a more analytical solution if possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: The shape was derived using an old draftsman's trick.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NV4V3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gWxcs.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CsvkZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4302" PostHistoryTypeId="1" PostId="1984" RevisionGUID="43e5e91a-7305-4148-9495-08533b28c600" CreationDate="2016-01-29T20:54:03.493" UserId="38" Text="Silhouette curve for isometric surface of revolution" ContentLicense="CC BY-SA 3.0" />
  <row Id="4303" PostHistoryTypeId="3" PostId="1984" RevisionGUID="43e5e91a-7305-4148-9495-08533b28c600" CreationDate="2016-01-29T20:54:03.493" UserId="38" Text="|bezier-curve|silhouette|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4305" PostHistoryTypeId="5" PostId="1983" RevisionGUID="c9611878-b048-4b6b-8123-3bc1d9ae21e9" CreationDate="2016-01-29T21:47:19.457" UserId="2574" Comment="added 113 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research)&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**A source that comes close**&#xD;&#xA;&#xD;&#xA;D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a section of an ellipse; ***this, or something equivalent to it, is the formula for which I need a reference:***&#xD;&#xA;&#xD;&#xA;$(y(k-k^{-1})-1)^{2}+(k^{2}-1)x^{2}=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $k=\sqrt{\epsilon(2+\epsilon)}$, where  $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4306" PostHistoryTypeId="5" PostId="1983" RevisionGUID="1e7290f1-72a9-416d-8c57-bf5e0059fa70" CreationDate="2016-01-29T21:53:59.710" UserId="2574" Comment="added 61 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research)&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**A source that comes close**&#xD;&#xA;&#xD;&#xA;D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a section of an ellipse; ***this, or something equivalent to it, is the formula for which I need a reference:***&#xD;&#xA;&#xD;&#xA;$[\,y\,(k-1/k)-1\,]^{2}+x^{2}(k^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $k=\sqrt{\epsilon(2+\epsilon)}$, where  $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4307" PostHistoryTypeId="5" PostId="1984" RevisionGUID="62885534-2cd4-4bd1-bec3-9e69f57ee550" CreationDate="2016-01-30T07:42:38.833" UserId="38" Comment="added 375 characters in body" Text="I am trying to figure out how to convert a flat representation of a curve into the silhouette of a surface of revolution in a isometric projection. In essence in want the planar cut of the surface edge to be converted to the silhouette.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Starting point.&#xD;&#xA;&#xD;&#xA;The geometry in this case is a Bézier curve although if somebody has solutions for any functions or higher order curves would be fine. So in essence im open to conics and NURBS also. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: End result. How to transform the magenta curves?&#xD;&#xA;&#xD;&#xA;The way I've done this now is by sampling several forms and in this case draw the new curve over the points. But id like to do this automatically and more precise. Please note: I am perfectly aware on how to do this with discrete data, I am looking for a more analytical solution if possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: The shape was derived using an old draftsman's trick.&#xD;&#xA;&#xD;&#xA;Please note: Most applications polygonize NURBS or Bézier surface for rendering. Let us to avoid this, as I am perfectly capable of discretisizing the solution and project the edges on the back face culling edge, and doing a secondary fitting, or even fitting on the NURBS underworld and then to 2d\*. That is exactly the same solution as I am using now. Seem to me there should be a somewhat analytical transformation possible.&#xD;&#xA;&#xD;&#xA;\* Though if you know a robust way to do the projection to a curve on surface I'm interested in that too.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NV4V3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gWxcs.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CsvkZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4308" PostHistoryTypeId="5" PostId="1984" RevisionGUID="4edc7e12-9c3c-4282-ba1c-5d00d15d6e8b" CreationDate="2016-01-30T07:58:33.270" UserId="38" Comment="added 96 characters in body" Text="I am trying to figure out how to convert a flat representation of a curve into the silhouette of a surface of revolution in a isometric projection. In essence in want the planar cut of the surface edge to be converted to the silhouette.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Starting point.&#xD;&#xA;&#xD;&#xA;The geometry in this case is a Bézier curve although if somebody has solutions for any functions or higher order curves would be fine. So in essence im open to conics and NURBS also. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: End result. How to transform the magenta curves?&#xD;&#xA;&#xD;&#xA;The way I've done this now is by sampling several forms and in this case draw the new curve over the points. But id like to do this automatically and more precise. Please note: I am perfectly aware on how to do this with discrete data, I am looking for a more analytical solution if possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: The shape was derived using an old draftsman's trick.&#xD;&#xA;&#xD;&#xA;Please note: Most applications polygonize NURBS or Bézier surface for rendering. Also trivial root finding does not really work well as result should not be pixels but a curve. Let us to avoid this, as I am perfectly capable of discretisizing the solution and project the edges on the back face culling edge, and doing a secondary fitting, or even fitting on the NURBS underworld and then to 2d\*. That is exactly the same solution as I am using now. Seem to me there should be a somewhat analytical transformation possible.&#xD;&#xA;&#xD;&#xA;\* Though if you know a robust way to do the projection to a curve on surface I'm interested in that too.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NV4V3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gWxcs.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CsvkZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4309" PostHistoryTypeId="5" PostId="1984" RevisionGUID="b4b4f119-da66-4e74-bda3-45e699f7897d" CreationDate="2016-01-30T08:18:57.707" UserId="38" Comment="added 227 characters in body" Text="I am trying to figure out how to convert a flat representation of a curve into the silhouette of a surface of revolution in a isometric projection. In essence in want the planar cut of the surface edge to be converted to the silhouette.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Starting point.&#xD;&#xA;&#xD;&#xA;The geometry in this case is a Bézier curve although if somebody has solutions for any functions or higher order curves would be fine. So in essence im open to conics and NURBS also. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: End result. How to transform the magenta curves?&#xD;&#xA;&#xD;&#xA;The way I've done this now is by sampling several forms and in this case draw the new curve over the points. But id like to do this automatically and more precise. Please note: I am perfectly aware on how to do this with discrete data, I am looking for a more analytical solution if possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: The shape was derived using an old draftsman's trick.&#xD;&#xA;&#xD;&#xA;Please note: Most applications polygonize NURBS or Bézier surface for rendering. Also trivial root finding does not really work well as result should not be pixels but a curve. Let us to avoid this, as I am perfectly capable of discretisizing the solution and project the edges on the back face culling edge, and doing a secondary fitting, or even fitting on the NURBS underworld and then to 2d\*. That is exactly the same solution as I am using now. Seem to me there should be a somewhat analytical transformation possible.&#xD;&#xA;&#xD;&#xA;[![im perfectly capable of solving this with discretionary of the domain][4]][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: I am perfectly capable of doing this with subdivision/discretisation of the domain.&#xD;&#xA;&#xD;&#xA;\* Though if you know a robust way to do the projection to a curve on surface I'm interested in that too.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NV4V3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gWxcs.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CsvkZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/2qJA5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4311" PostHistoryTypeId="5" PostId="1983" RevisionGUID="6ab9d11d-ba83-40d8-9abe-dac323fa4d40" CreationDate="2016-01-30T15:24:54.717" UserId="2574" Comment="added 615 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research)&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**A source that comes close**&#xD;&#xA;&#xD;&#xA;D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a section of an ellipse; ***this, or something equivalent to it, is the formula for which I need a reputable reference:***&#xD;&#xA;&#xD;&#xA;$[\,y\,(k-1/k)-1\,]^{2}+x^{2}(k^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $k=\sqrt{\epsilon(2+\epsilon)}$, where  $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4312" PostHistoryTypeId="5" PostId="1983" RevisionGUID="27755613-cd94-46ac-9836-ac6a594587e5" CreationDate="2016-01-31T02:34:43.370" UserId="2574" Comment="added 10 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research)&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**A source that comes close**&#xD;&#xA;&#xD;&#xA;D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a section of an ellipse; ***this, or something equivalent to it, is the formula for which I need a reputable reference:***&#xD;&#xA;&#xD;&#xA;$[\,y\,(k-1/k)-1\,]^{2}+x^{2}(k^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $k=\sqrt{\epsilon(2+\epsilon)}$, where  $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4318" PostHistoryTypeId="2" PostId="1986" RevisionGUID="0ba298c9-26d2-4e6c-beca-1db69a9df34f" CreationDate="2016-01-31T18:20:40.643" UserId="48" Text="An alternative way to formulate the problem is to define a function that gives the distance between points on the two curves, as a function of the curves' parameters. Then attempt to find the global minimum of this function. If the curves intersect, the minimum will be zero; otherwise the minimum will be some positive distance.&#xD;&#xA;&#xD;&#xA;To be explicit, given a pair of 2D curves defined by $c_1, c_2 : [0, 1] \to \mathbb{R}^2$, define the distance-squared as&#xD;&#xA;&#xD;&#xA;$$ f(u,v) : [0,1]^2 \to \mathbb{R}_{\geq 0} \equiv \bigl|c_2(v) - c_1(u)\bigr|^2 $$&#xD;&#xA;&#xD;&#xA;For cubic curves, the function $f$ is then a sixth-degree polynomial in two variables. You can then apply numerical optimization techniques such as the [simplex method](https://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method) or [conjugate gradient descent](https://en.wikipedia.org/wiki/Conjugate_gradient_method). Unfortunately the function can have several local minima (it's not convex), so optimization isn't easy. There may well be more specialized optimization methods available for polynomials, but this isn't an area of expertise for me.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4321" PostHistoryTypeId="2" PostId="1987" RevisionGUID="39c3229e-277b-4798-9799-f4832ab49286" CreationDate="2016-02-01T05:07:20.643" UserId="2457" Text="A paper I'm reading says fluence measures the incoming radiance from all directions and that fluence is similar to irradiance. It's defined by $\phi(x) = \int_{4 \pi} L(x, \vec{\omega'}) d\omega' $ (The tick mark seems to emphasize $\vec{\omega'}$ varies over the integration, rather than being a fixed direction.)&#xD;&#xA;&#xD;&#xA;Intuitively, radiance is the amount of light given off in a direction but attenuated by how far off the surface is from being perpendicular to the light direction. $L=\frac{d^2\Phi}{d\omega dA \cos \theta}$&#xD;&#xA;&#xD;&#xA;Irradiance is the area light density of a surface. $E=\frac{d\Phi}{dA}=\int_{2 \pi } L_i(\vec{\omega}) \cos \theta d\omega$&#xD;&#xA;&#xD;&#xA;Intensity is the amount of light hitting a surface from a particular direction. $I(\vec{\omega})=\frac{d\Phi}{d\omega}$&#xD;&#xA;&#xD;&#xA;It also looks like you can write the radiance as irradiance times intensity. &#xD;&#xA;$L=E\cdot I(\vec{\omega})$&#xD;&#xA;&#xD;&#xA;Looking at the formulas, it seems like irradiance sums radiance over the hemisphere over a surface point, while fluence sums up radiance over the whole sphere surrounding a point (to measure inscattering).&#xD;&#xA;&#xD;&#xA;Wikipedia says, &quot;radiant fluence is the radiant energy received by a surface per unit area, or equivalently the irradiance of a surface integrated over time of irradiation.&quot; But this definition doesn't seem to match the one given above since there's no time involved.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4322" PostHistoryTypeId="1" PostId="1987" RevisionGUID="39c3229e-277b-4798-9799-f4832ab49286" CreationDate="2016-02-01T05:07:20.643" UserId="2457" Text="What's the difference between irradiance and fluence/radiant exposure?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4323" PostHistoryTypeId="3" PostId="1987" RevisionGUID="39c3229e-277b-4798-9799-f4832ab49286" CreationDate="2016-02-01T05:07:20.643" UserId="2457" Text="|rendering|physically-based|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4324" PostHistoryTypeId="5" PostId="1987" RevisionGUID="a3b9eea2-f779-4d94-ada5-9288e3e63a19" CreationDate="2016-02-01T05:22:54.820" UserId="2457" Comment="added 71 characters in body" Text="A paper I'm reading says fluence measures the incoming radiance from all directions and that fluence is similar to irradiance. It's defined by $\phi(x) = \int_{4 \pi} L(x, \vec{\omega'}) d\omega' $ (The tick mark seems to emphasize $\vec{\omega'}$ varies over the integration, rather than being a fixed direction.)&#xD;&#xA;&#xD;&#xA;Intuitively, radiance is the amount of light given off in a direction but attenuated by how far off the surface is from being perpendicular to the light direction. $L=\frac{d^2\Phi}{d\omega dA \cos \theta}$&#xD;&#xA;&#xD;&#xA;Irradiance is the area light density of a surface. $E=\frac{d\Phi}{dA}=\int_{2 \pi } L_i(\vec{\omega}) \cos \theta d\omega$&#xD;&#xA;&#xD;&#xA;Intensity is the amount of light hitting a surface from a particular direction. $I(\vec{\omega})=\frac{d\Phi}{d\omega}$&#xD;&#xA;&#xD;&#xA;It also looks like you can write the radiance as irradiance times intensity. &#xD;&#xA;$L=E\cdot I(\vec{\omega})$&#xD;&#xA;&#xD;&#xA;Looking at the formulas, it seems like irradiance sums radiance over the hemisphere over a surface point and attenuated by how much the surface orients toward the light source, while fluence sums up radiance over the whole sphere surrounding a point (to measure inscattering).&#xD;&#xA;&#xD;&#xA;Wikipedia says, &quot;radiant fluence is the radiant energy received by a surface per unit area, or equivalently the irradiance of a surface integrated over time of irradiation.&quot; But this definition doesn't seem to match the one given above since there's no time involved.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4325" PostHistoryTypeId="5" PostId="1982" RevisionGUID="c7df9c20-81bc-4ea6-b64d-3997927abc2d" CreationDate="2016-02-01T08:52:17.220" UserId="209" Comment="Got caught by the list autonumbering changing the displayed text" Text="[Disclaimer: I think the following should work but have not actually coded it myself]&#xD;&#xA;&#xD;&#xA;I couldn't think of a &quot;trivial&quot; method of producing a yes/no answer but the following would be a reasonable approach to a practical solution to the question.&#xD;&#xA;&#xD;&#xA;Let's assume our curves are _A(s)_ and _B(t)_ with control points {_A0, A1..An_} and {_B0,..Bm_} respectively.&#xD;&#xA;&#xD;&#xA;It seems to me that, given a pair of 2D Beziers for which we wish to determine do or don't intersect, there are six cases to consider:&#xD;&#xA;&#xD;&#xA; 1. Case where we can &quot;trivially&quot; determine they do *not* intersect.&#xD;&#xA;&#xD;&#xA; 2. Case where they intersect a finite number of times and we can &quot;easily&quot; determine they definitely intersect at least once (but we don't actually care where that/those intersections occur)&#xD;&#xA;&#xD;&#xA; 3. One of the Beziers is degenerate, i.e. a point (which will occur if all the control points are identical). We canassume we've already handled the case where both are points.&#xD;&#xA;&#xD;&#xA; 4. One or more of the curves are closed, eg. A0==An. To make life simpler, we'll subdivide such curve and start again.&#xD;&#xA;&#xD;&#xA; 5. There are an infinite number of points of intersection because each is a overlapping subset of a &quot;parent&quot; Bezier.&#xD;&#xA;&#xD;&#xA; 6. We aren't certain about the above cases and need further investigation&#xD;&#xA;&#xD;&#xA;For the moment we'll ignore 3 and 4, but come back to them later.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 1 ###&#xD;&#xA;As you hint in your question, if the respective bounding boxes of the control points of _A_ and _B_), don't intersect, then the curves can't intersect. Obviously this is a quick reject test but it's overly conservative.&#xD;&#xA;As you probably know, with a Bezier curve, the convex hull of its control points forms a (tighter) bound on the curve. We can thus use the separating axis technique to decide if the hulls of _A_ and _B_ don't intersect. (e.g. as shown in Wikipedia:)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Case 2 ###&#xD;&#xA;If the case 1 test fails, you could then check for the &quot;trivial&quot; existence of an intersection. Now there are probably better ways to do this, but the following, relatively cheap, approach occurred to me:&#xD;&#xA;&#xD;&#xA;Consider just curve A:&#xD;&#xA;&#xD;&#xA;[![&quot;Fat line&quot; bounds of a Bezier][2]][2]&#xD;&#xA;&#xD;&#xA;We know the curve starts at _A0_, terminates at _An_, and will lie inside the convex hull. For simplicity let us compute the direction of the line segment A0_An and the compute the bounds on either side (i.e. take dot products of the remaining control points against the perpendicular to A0_An).&#xD;&#xA;&#xD;&#xA;If we do the same with curve B we get the following (possible) case:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we find A0 and An are on the outsides of the bounds of B _AND_ that B0 and Bm are on the outsides of the bounds of A, then, by the continuity of Beziers, there must be at least one intersection.&#xD;&#xA;&#xD;&#xA;### Case 6 ###&#xD;&#xA;If we can't immediately show either of the above cases, then split each of the Beziers into two &quot;halves&quot;, i.e. AP1, AP2, BP1, BP2. This is relatively straightforward (left as an exercise to the reader) but is [particularly trivial for quadratic Beziers](https://computergraphics.stackexchange.com/questions/1895/how-should-i-fill-a-shape-consisting-of-bezier-cures-and-straight-lines/1899#1899): &#xD;&#xA;&#xD;&#xA;Recursively compare the 4 combinations: (AP1,BP1), (AP2, BP1)...(AP2, BP2).&#xD;&#xA;Clearly if all pass case 1, there is no intersection.&#xD;&#xA;If any fail 1, then continue with the rest of the tests.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 3 &amp; 4 ###&#xD;&#xA;This is where it becomes tedious. If case 3 gets past the &quot;case 1&quot; test, it seems to me that you need to solve for&#xD;&#xA;&#xD;&#xA;(SORRY INCOMPLETE... will come back when I have spare time)&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/u4AxW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2An9z.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dX6l0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4326" PostHistoryTypeId="5" PostId="1982" RevisionGUID="341ddb7d-4521-423a-9644-f30e120643a5" CreationDate="2016-02-01T13:21:40.477" UserId="209" Comment="Added case 3 &amp; 5 (ish)" Text="[Disclaimer: I think the following should work but have not actually coded it myself]&#xD;&#xA;&#xD;&#xA;I couldn't think of a &quot;trivial&quot; method of producing a yes/no answer but the following would be a reasonable approach to a practical solution to the question.&#xD;&#xA;&#xD;&#xA;Let's assume our curves are _A(s)_ and _B(t)_ with control points {_A0, A1..An_} and {_B0,..Bm_} respectively.&#xD;&#xA;&#xD;&#xA;It seems to me that, given a pair of 2D Beziers for which we wish to determine do or don't intersect, there are six cases to consider:&#xD;&#xA;&#xD;&#xA; 1. Case where we can &quot;trivially&quot; determine they do *not* intersect.&#xD;&#xA;&#xD;&#xA; 2. Case where they intersect a finite number of times and we can &quot;easily&quot; determine they definitely intersect at least once (but we don't actually care where that/those intersections occur)&#xD;&#xA;&#xD;&#xA; 3. One of the Beziers is degenerate, i.e. a point (which will occur if all the control points are identical). We can assume we've already handled the case where both are points.&#xD;&#xA;&#xD;&#xA; 4. One or more of the curves are closed, e.g.. A0==An. To make life simpler, we'll subdivide such curve and start again.&#xD;&#xA;&#xD;&#xA; 5. There are an infinite number of points of intersection because each is an overlapping subset of a &quot;parent&quot; Bezier.&#xD;&#xA;&#xD;&#xA; 6. We aren't certain about the above cases and need further investigation&#xD;&#xA;&#xD;&#xA;For the moment we'll ignore 3 and 4, but come back to them later.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 1 ###&#xD;&#xA;As you hint in your question, if the respective bounding boxes of the control points of _A_ and _B_), don't intersect, then the curves can't intersect. Obviously this is a quick reject test but it's overly conservative.&#xD;&#xA;As you probably know, with a Bezier curve, the convex hull of its control points forms a (tighter) bound on the curve. We can thus use the separating axis technique to decide if the hulls of _A_ and _B_ don't intersect. (e.g. as shown in Wikipedia:)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Case 2 ###&#xD;&#xA;If the case 1 test fails, you could then check for the &quot;trivial&quot; existence of an intersection. Now there are probably better ways to do this, but the following, relatively cheap, approach occurred to me:&#xD;&#xA;&#xD;&#xA;Consider just curve A:&#xD;&#xA;&#xD;&#xA;[![&quot;Fat line&quot; bounds of a Bezier][2]][2]&#xD;&#xA;&#xD;&#xA;We know the curve starts at _A0_, terminates at _An_, and will lie inside the convex hull. For simplicity let us compute the direction of the line segment A0_An and the compute the bounds on either side (i.e. take dot products of the remaining control points against the perpendicular to A0_An).&#xD;&#xA;&#xD;&#xA;If we do the same with curve B we get the following (possible) case:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we find A0 and An are outside opposite bounds of B _AND_ that B0 and Bm are on the outsides of the bounds of A, then, by the continuity of Beziers, there must be at least one intersection.&#xD;&#xA;&#xD;&#xA;### Case 6 ###&#xD;&#xA;If we can't immediately show either of the above cases, then split each of the Beziers into two &quot;halves&quot;, i.e. AP1, AP2, BP1, BP2. This is relatively straightforward (left as an exercise to the reader) but is [particularly trivial for quadratic Beziers](https://computergraphics.stackexchange.com/questions/1895/how-should-i-fill-a-shape-consisting-of-bezier-cures-and-straight-lines/1899#1899): &#xD;&#xA;&#xD;&#xA;Recursively compare the 4 combinations: (AP1,BP1), (AP2, BP1)...(AP2, BP2).&#xD;&#xA;Clearly if all pass case 1, there is no intersection.&#xD;&#xA;If any fail 1, then continue with the rest of the tests.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 3 &amp; 5 ###&#xD;&#xA;This is where it becomes slightly more tedious.&#xD;&#xA;&#xD;&#xA;If &quot;case 3&quot; gets past the &quot;case 1&quot; test, it seems to me that you need to solve for an actual intersection. Given that there is a simple process to map the N control points of a Bezier, A(s), to the N-1 points of the Bezier, A'(s), representing its 1st derivative then (provided care is taken for the relatively rare, so-called &quot;degenerate&quot; situations where the 1st derivative does to zero), then Newton iteration (on one dimension) could be used to find potential solutions.  &#xD;&#xA;Note also that, since the control points of A'(s) are a bound on the derivative values, there is the potential to do early elimination of some cases.&#xD;&#xA;&#xD;&#xA;Case 5 seems relatively unlikely, so perhaps only if after a few recursions there is no conclusive proof, one could try each end point of A against curve B and vice versa. This would only give a proof of intersection - not a proof of non-intersection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/u4AxW.png&#xD;&#xA; [2]: https://i.stack.imgur.com/2An9z.png&#xD;&#xA; [3]: https://i.stack.imgur.com/dX6l0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4328" PostHistoryTypeId="5" PostId="1982" RevisionGUID="f8b130c2-aec2-4d14-8610-865b432db50b" CreationDate="2016-02-01T13:53:27.697" UserId="209" Comment="Added some latex" Text="[Disclaimer: I think the following should work but have not actually coded it myself]&#xD;&#xA;&#xD;&#xA;I couldn't think of a &quot;trivial&quot; method of producing a yes/no answer but the following would be a reasonable approach to a practical solution to the question.&#xD;&#xA;&#xD;&#xA;Let's assume our curves are _A(s)_ and _B(t)_ with control points {_A0, A1..An_} and {_B0,..Bm_} respectively.&#xD;&#xA;&#xD;&#xA;It seems to me that, given a pair of 2D Beziers for which we wish to determine do or don't intersect, there are six cases to consider:&#xD;&#xA;&#xD;&#xA; 1. Case where we can &quot;trivially&quot; determine they do *not* intersect.&#xD;&#xA;&#xD;&#xA; 2. Case where they intersect a finite number of times and we can &quot;easily&quot; determine they definitely intersect at least once (but we don't actually care where that/those intersections occur)&#xD;&#xA;&#xD;&#xA; 3. One of the Beziers is degenerate, i.e. a point (which will occur if all the control points are identical). We can assume we've already handled the case where both are points.&#xD;&#xA;&#xD;&#xA; 4. One or more of the curves are closed, e.g.. A0==An. To make life simpler, we'll subdivide such curve and start again.&#xD;&#xA;&#xD;&#xA; 5. There are an infinite number of points of intersection because each is an overlapping subset of a &quot;parent&quot; Bezier.&#xD;&#xA;&#xD;&#xA; 6. We aren't certain about the above cases and need further investigation&#xD;&#xA;&#xD;&#xA;For the moment we'll ignore 3 and 4, but come back to them later.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 1 ###&#xD;&#xA;As you hint in your question, if the respective bounding boxes of the control points of _A_ and _B_), don't intersect, then the curves can't intersect. Obviously this is a quick reject test but it's overly conservative.&#xD;&#xA;As you probably know, with a Bezier curve, the convex hull of its control points forms a (tighter) bound on the curve. We can thus use the separating axis technique to decide if the hulls of _A_ and _B_ don't intersect. (e.g. as shown in Wikipedia:)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Case 2 ###&#xD;&#xA;If the case 1 test fails, you could then check for the &quot;trivial&quot; existence of an intersection. Now there are probably better ways to do this, but the following, relatively cheap, approach occurred to me:&#xD;&#xA;&#xD;&#xA;Consider just curve A:&#xD;&#xA;&#xD;&#xA;[![&quot;Fat line&quot; bounds of a Bezier][2]][2]&#xD;&#xA;&#xD;&#xA;We know the curve starts at $A_0$, terminates at $A_n$, and will lie inside the convex hull. For simplicity let us compute the direction of the line segment $\overline{A_0A_n} $ and the compute the bounds on either side (i.e. take dot products of the remaining control points against the perpendicular to $\overline{A_0A_n}$).&#xD;&#xA;&#xD;&#xA;If we do the same with curve B we get the following (possible) case:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we find $A_0$ and $A_n$ are outside opposite bounds of B _and_ that $B_0$ and $B_m$ are on the outsides of the bounds of A, then, by the continuity of Beziers, there must be at least one intersection.&#xD;&#xA;&#xD;&#xA;### Case 6 ###&#xD;&#xA;If we can't immediately show either of the above cases, then split each of the Beziers into two &quot;halves&quot;, i.e. $A^1, A^2, B^1, B^2$. This is relatively straightforward (left as an exercise to the reader) but is [particularly trivial for quadratic Beziers](https://computergraphics.stackexchange.com/questions/1895/how-should-i-fill-a-shape-consisting-of-bezier-cures-and-straight-lines/1899#1899): &#xD;&#xA;&#xD;&#xA;Recursively compare the 4 combinations: $(A^1,B^1), (A^2, B^1)...(A^2, B^2)$.&#xD;&#xA;Clearly if all pass case 1, there is no intersection.&#xD;&#xA;If any fail 1, then continue with the rest of the tests with that reduced subset.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 3 &amp; 5 ###&#xD;&#xA;This is where it becomes slightly more tedious.&#xD;&#xA;&#xD;&#xA;If &quot;case 3&quot; gets past the &quot;case 1&quot; test, it seems to me that you need to solve for an actual intersection. Given that there is a simple process to map the N control points of a Bezier, A(s), to the N-1 points of the Bezier, A'(s), representing its 1st derivative then (provided care is taken for the relatively rare, so-called &quot;degenerate&quot; situations where the 1st derivative does to zero), then Newton iteration (on one dimension) could be used to find potential solutions.  &#xD;&#xA;Note also that, since the control points of A'(s) are a bound on the derivative values, there is the potential to do early elimination of some cases.&#xD;&#xA;&#xD;&#xA;Case 5 seems relatively unlikely, so perhaps only if after a few recursions there is no conclusive proof, one could try each end point of A against curve B and vice versa. This would only give a proof of intersection - not a proof of non-intersection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/u4AxW.png&#xD;&#xA; [2]: https://i.stack.imgur.com/2An9z.png&#xD;&#xA; [3]: https://i.stack.imgur.com/dX6l0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4329" PostHistoryTypeId="5" PostId="1987" RevisionGUID="ed57b318-d43c-45f6-acf5-c42ae2d34e2a" CreationDate="2016-02-01T17:55:32.607" UserId="2457" Comment="added 201 characters in body" Text="A [paper$^1$][1] I'm reading says fluence measures the incoming radiance from all directions and that fluence is similar to irradiance. It's defined by $\phi(x) = \int_{4 \pi} L(x, \vec{\omega'}) d\omega' $ (The tick mark seems to emphasize $\vec{\omega'}$ varies over the integration, rather than being a fixed direction.)&#xD;&#xA;&#xD;&#xA;Intuitively, radiance is the amount of light given off in a direction but attenuated by how far off the surface is from being perpendicular to the light direction. $L=\frac{d^2\Phi}{d\omega dA \cos \theta}$&#xD;&#xA;&#xD;&#xA;Irradiance is the area light density of a surface. $E=\frac{d\Phi}{dA}=\int_{2 \pi } L_i(\vec{\omega}) \cos \theta d\omega$&#xD;&#xA;&#xD;&#xA;Intensity is the amount of light hitting a surface from a particular direction. $I(\vec{\omega})=\frac{d\Phi}{d\omega}$&#xD;&#xA;&#xD;&#xA;It also looks like you can write the radiance as irradiance times intensity. &#xD;&#xA;$L=E\cdot I(\vec{\omega})$&#xD;&#xA;&#xD;&#xA;Looking at the formulas, it seems like irradiance sums radiance over the hemisphere over a surface point and attenuated by how much the surface orients toward the light source, while fluence sums up radiance over the whole sphere surrounding a point (to measure inscattering).&#xD;&#xA;&#xD;&#xA;Wikipedia says, &quot;radiant fluence is the radiant energy received by a surface per unit area, or equivalently the irradiance of a surface integrated over time of irradiation.&quot; But this definition doesn't seem to match the one given above since there's no time involved.&#xD;&#xA;&#xD;&#xA;1. Real-Time Rendering of Translucent Materials with Directional Subsurface Scattering, Alessandro Dal Corso, 2014&#xD;&#xA;&#xD;&#xA;  [1]: http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/6816/pdf/imm6816.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4330" PostHistoryTypeId="5" PostId="1983" RevisionGUID="122ec142-4ef1-47ed-8ffd-4f3285fbeacf" CreationDate="2016-02-01T19:12:47.887" UserId="2574" Comment="added 398 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**A source that comes close**&#xD;&#xA;&#xD;&#xA;D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a section of an ellipse; ***this, or something equivalent to it, is the formula for which I need a reputable reference:***&#xD;&#xA;&#xD;&#xA;$[\,y\,(k-1/k)-1\,]^{2}+x^{2}(k^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $k=\sqrt{\epsilon(2+\epsilon)}$, where  $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4331" PostHistoryTypeId="2" PostId="1989" RevisionGUID="b2c96879-05ed-488e-9a11-102b65821455" CreationDate="2016-02-01T21:28:59.743" UserId="273" Text="I can only cite what I have learned in my lecture on Global Illumination techniques which was unfortunately some time ago:&#xD;&#xA;&#xD;&#xA; - Radiant Power : The amount of energy emitted by a light source in unit time. denoted by $\Phi$ and is measured in Watt which equals to Joules per second. (This does not specify any area!)&#xD;&#xA;&#xD;&#xA; - Irradiance: The irradiance denotes the incident radiant energy on a surface. It is defined as $E=\frac{d\Phi}{dA}$ - This quantity denotes the incoming energy per area and is measure ind $\frac{W}{m^2}$ Note here: radiant energy is measured in Watt which is Joules **per second**!&#xD;&#xA;&#xD;&#xA; - Radiant exitance: This is the reverse direction of Irradiance and is the energy an area emits in unit time and has the same definiton and units as Irradiance only with reverse direction $M = B = \frac{d\Phi}{dA}$. This is also often called radiosity B.&#xD;&#xA;&#xD;&#xA; - Radiance: Is the power per projected area per solid angle. It is defined as $L=\frac{d²\Phi}{d \omega * dA * cos\theta}=[\frac{W}{sr*m^2}]$ where $\omega$ denotes the solid angle, $\theta$ denotes the angle between emitting surface normal and the direction the energy is traveling to. So this is not attenuated by the distance but by the angles.&#xD;&#xA;&#xD;&#xA;In general as I learned the distance between emitting and receiving surface is only important for Radiance because the projected area will be smaller if they are farther apart.&#xD;&#xA;&#xD;&#xA;The time you are missing in your definitions seem to come from the conversion of Watt to Joules Per Second." ContentLicense="CC BY-SA 3.0" />
  <row Id="4333" PostHistoryTypeId="5" PostId="1987" RevisionGUID="5a3ee233-8a52-4c6d-a129-6f823294c9b9" CreationDate="2016-02-02T05:03:34.853" UserId="2457" Comment="added 178 characters in body" Text="A [paper$^1$][1] I'm reading says fluence measures the incoming radiance from all directions and that fluence is similar to irradiance. It's defined by $\phi(x) = \int_{4 \pi} L(x, \vec{\omega'}) d\omega' $ (The tick mark seems to emphasize $\vec{\omega'}$ varies over the integration, rather than being a fixed direction.)&#xD;&#xA;&#xD;&#xA;Intuitively, radiance is the amount of light given off in a direction but attenuated by how far off the surface is from being perpendicular to the light direction. $L=\frac{d^2\Phi}{d\omega dA \cos \theta}$&#xD;&#xA;&#xD;&#xA;Irradiance is the area light density of a surface. $E=\frac{d\Phi}{dA}=\int_{2 \pi } L_i(\vec{\omega}) \cos \theta d\omega$&#xD;&#xA;&#xD;&#xA;Intensity is the amount of light hitting a surface from a particular direction. $I(\vec{\omega})=\frac{d\Phi}{d\omega}$&#xD;&#xA;&#xD;&#xA;It also looks like you can write the radiance as irradiance times intensity. &#xD;&#xA;$L=E\cdot I(\vec{\omega})$&#xD;&#xA;&#xD;&#xA;Looking at the formulas, it seems like irradiance sums radiance over the hemisphere over a surface point and attenuated by how much the surface orients toward the light source, while fluence sums up radiance over the whole sphere surrounding a point (to measure inscattering).&#xD;&#xA;&#xD;&#xA;Wikipedia says, &quot;radiant fluence is the radiant energy received by a surface per unit area, or equivalently the irradiance of a surface integrated over time of irradiation.&quot; But this definition doesn't seem to match the one given above since there's no time involved.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;https://www.researchgate.net/post/What_is_the_definition_and_difference_between_light_dose_and_light_fluence_rate&#xD;&#xA;&#xD;&#xA;http://omlc.org/education/ece532/class1/irradiance.html&#xD;&#xA;&#xD;&#xA;1. Real-Time Rendering of Translucent Materials with Directional Subsurface Scattering, Alessandro Dal Corso, 2014&#xD;&#xA;&#xD;&#xA;  [1]: http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/6816/pdf/imm6816.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4335" PostHistoryTypeId="2" PostId="1990" RevisionGUID="ba1a43c0-452f-42ad-a80e-2b0f91b88b77" CreationDate="2016-02-02T10:20:07.647" UserId="2592" Text="&#xD;&#xA;I installed AMD APP SDK and here my problem. The OpenCL samples do not detect the GPU. HelloWorld give me this:&#xD;&#xA;&#xD;&#xA;    [thomas@Clemence:/opt/AMDAPP/samples/opencl/bin/x86_64]$ ./HelloWorld&#xD;&#xA;    No GPU device available.&#xD;&#xA;    Choose CPU as default device.&#xD;&#xA;    input string:&#xD;&#xA;    GdkknVnqkc&#xD;&#xA;&#xD;&#xA;    output string:&#xD;&#xA;    HelloWorld&#xD;&#xA;    Passed!&#xD;&#xA;&#xD;&#xA;And here the clinfo output&#xD;&#xA;&#xD;&#xA;    [thomas@Clemence:~/Documents/radeontop]$ clinfo&#xD;&#xA;    Number of platforms:                 1&#xD;&#xA;    Platform Profile:                FULL_PROFILE&#xD;&#xA;    Platform Version:                OpenCL 1.2 AMD-APP (1214.3)&#xD;&#xA;    Platform Name:               AMD Accelerated Parallel Processing&#xD;&#xA;    Platform Vendor:                 Advanced Micro Devices, Inc.&#xD;&#xA;    Platform Extensions:                 cl_khr_icd cl_amd_event_callback      cl_amd_offline_devices&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Platform Name:               AMD Accelerated Parallel Processing&#xD;&#xA;    Number of devices:               1&#xD;&#xA;    Device Type:                     CL_DEVICE_TYPE_CPU&#xD;&#xA;    Device ID:                   4098&#xD;&#xA;    Board name:                  &#xD;&#xA;    Max compute units:               8&#xD;&#xA;    Max work items dimensions:           3&#xD;&#xA;    Max work items[0]:               1024&#xD;&#xA;    Max work items[1]:               1024&#xD;&#xA;    Max work items[2]:               1024&#xD;&#xA;    Max work group size:                 1024&#xD;&#xA;    Preferred vector width char:             16&#xD;&#xA;    Preferred vector width short:            8&#xD;&#xA;    Preferred vector width int:          4&#xD;&#xA;    Preferred vector width long:             2&#xD;&#xA;    Preferred vector width float:            8&#xD;&#xA;    Preferred vector width double:       4&#xD;&#xA;    Native vector width char:            16&#xD;&#xA;    Native vector width short:           8&#xD;&#xA;    Native vector width int:             4&#xD;&#xA;    Native vector width long:            2&#xD;&#xA;    Native vector width float:           8&#xD;&#xA;    Native vector width double:          4&#xD;&#xA;    Max clock frequency:                 3633Mhz&#xD;&#xA;    Address bits:                    64&#xD;&#xA;    Max memory allocation:           4182872064&#xD;&#xA;    Image support:               Yes&#xD;&#xA;    Max number of images read arguments:         128&#xD;&#xA;    Max number of images write arguments:        8&#xD;&#xA;    Max image 2D width:              8192&#xD;&#xA;    Max image 2D height:                 8192&#xD;&#xA;    Max image 3D width:              2048&#xD;&#xA;    Max image 3D height:                 2048&#xD;&#xA;    Max image 3D depth:              2048&#xD;&#xA;    Max samplers within kernel:          16&#xD;&#xA;    Max size of kernel argument:             4096&#xD;&#xA;    Alignment (bits) of base address:        1024&#xD;&#xA;    Minimum alignment (bytes) for any datatype:  128&#xD;&#xA;    Single precision floating point capability&#xD;&#xA;    Denorms:                     Yes&#xD;&#xA;    Quiet NaNs:                  Yes&#xD;&#xA;    Round to nearest even:           Yes&#xD;&#xA;    Round to zero:               Yes&#xD;&#xA;    Round to +ve and infinity:           Yes&#xD;&#xA;    IEEE754-2008 fused multiply-add:         Yes&#xD;&#xA;    Cache type:                  Read/Write&#xD;&#xA;    Cache line size:                 64&#xD;&#xA;    Cache size:                  32768&#xD;&#xA;    Global memory size:              16731488256&#xD;&#xA;    Constant buffer size:                65536&#xD;&#xA;    Max number of constant args:             8&#xD;&#xA;    Local memory type:               Global&#xD;&#xA;    Local memory size:               32768&#xD;&#xA;    Kernel Preferred work group size multiple:   1&#xD;&#xA;    Error correction support:            0&#xD;&#xA;    Unified memory for Host and Device:      1&#xD;&#xA;    Profiling timer resolution:          1&#xD;&#xA;    Device endianess:                Little&#xD;&#xA;    Available:                   Yes&#xD;&#xA;    Compiler available:              Yes&#xD;&#xA;    Execution capabilities:              &#xD;&#xA;    Execute OpenCL kernels:          Yes&#xD;&#xA;    Execute native function:             Yes&#xD;&#xA;    Queue properties:                &#xD;&#xA;    Out-of-Order:                No&#xD;&#xA;    Profiling :                  Yes&#xD;&#xA;    Platform ID:                     0x00007f4ef63f0fc0&#xD;&#xA;    Name:                        Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz&#xD;&#xA;    Vendor:                  GenuineIntel&#xD;&#xA;    Device OpenCL C version:             OpenCL C 1.2 &#xD;&#xA;    Driver version:              1214.3 (sse2,avx)&#xD;&#xA;    Profile:                     FULL_PROFILE&#xD;&#xA;    Version:                     OpenCL 1.2 AMD-APP (1214.3)&#xD;&#xA;    Extensions:                  cl_khr_fp64 cl_amd_fp64     cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_3d_image_writes cl_khr_byte_addressable_store cl_khr_gl_sharing cl_ext_device_fission cl_amd_device_attribute_query cl_amd_vec3 cl_amd_printf cl_amd_media_ops cl_amd_media_ops2 cl_amd_popcnt &#xD;&#xA;&#xD;&#xA;What should I do in order to have access to the GPU? Thanks in advance. I'm working on Ubuntu 14.04.3 LTS Trusty Kernel 3.9&#xD;&#xA;&#xD;&#xA;here my graphics card:&#xD;&#xA;&#xD;&#xA;    [thomas@elsa:~]$ lspci | grep -i --color 'vga'&#xD;&#xA;    00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v3/4th &#xD;&#xA;    Gen Core Processor Integrated Graphics Controller (rev 06)&#xD;&#xA;    01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] &#xD;&#xA;    Oland XT [Radeon HD 8670 / R7 250/350]&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4336" PostHistoryTypeId="1" PostId="1990" RevisionGUID="ba1a43c0-452f-42ad-a80e-2b0f91b88b77" CreationDate="2016-02-02T10:20:07.647" UserId="2592" Text="OpenCL doesn't detect GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="4337" PostHistoryTypeId="3" PostId="1990" RevisionGUID="ba1a43c0-452f-42ad-a80e-2b0f91b88b77" CreationDate="2016-02-02T10:20:07.647" UserId="2592" Text="|gpu|opencl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4339" PostHistoryTypeId="5" PostId="1498" RevisionGUID="b566e330-a18d-4840-8a6f-97b6c34b7bf7" CreationDate="2016-02-02T10:36:32.350" UserId="209" Comment="+ &quot;non-degenerate&quot;" Text="Assuming a perspective projection and a view point external to the sphere, then the 'boundary' formed by the view point and the circle on the sphere which forms the horizon WRT the view point, will be a cone. &#xD;&#xA;&#xD;&#xA;Doing a perspective projection (onto a plane) is then equivalent to intersecting this cone with the plane which thus produces a conic section. FYI the four, non-degenerate, cases are shown in this image from Wikipedia [![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;An ellipse/circle is thus a possibility, but not the only one - unbounded parabolas or hyperbolas (and I guess if the plane passes through the eye, even degenerate cases ) are possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RAwDQ.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Conic_section#/media/File:Conic_Sections.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4341" PostHistoryTypeId="2" PostId="1991" RevisionGUID="f57833b3-8633-453d-8590-dceb53e37124" CreationDate="2016-02-02T12:04:47.037" UserId="2593" Text="I encountered some problems when implementing the cloth simulation algorithm from Baraff &amp; Witkin 98's [Large Steps in Cloth Simulation](http://www.cs.cmu.edu/~baraff/papers/sig98.pdf).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Baraff &amp; Witkin 98**&#xD;&#xA;&#xD;&#xA;Consider the cloth as a particle system in 3D, which consists of N particles.&#xD;&#xA;&#xD;&#xA;1. Equation of motion&#xD;&#xA;&#xD;&#xA;In each time step, the implicit integration of particle system is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix} \Delta \mathbf x \\ \Delta \mathbf v \\ \end{pmatrix} = h\begin{pmatrix} \mathbf v_0 + \Delta \mathbf v \\ \mathbf M^{-1} \mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v) \\ \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $h$ is the time step (scalar)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. The partial derivative equation&#xD;&#xA;&#xD;&#xA;Take the 1st order Taylor expansion of $\mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v)$, and introduce constraint matrix $\mathbf S$ (make mass matrix from $\mathbf M^{-1}$ to $\mathbf M^{-1}\mathbf S$), we have: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})\Delta \mathbf v = h\mathbf M^{-1} \mathbf S(\mathbf f_0 + h\frac{\partial \mathbf f}{\partial \mathbf x} \mathbf v_0) + \mathbf z&#xD;&#xA;$$ &#xD;&#xA;&#xD;&#xA;Where all of the matrices are treated as $N\times N $ block matrices, eack block sizes $3\times 3 $; vectors as N block vector, each sized $3\times 3 $ (with N number of 3D forces/positions/velocities).&#xD;&#xA;&#xD;&#xA; - $\mathbf I$ is identical matrix&#xD;&#xA;&#xD;&#xA; - $ \mathbf M = diag(\mathbf M_1, \mathbf M_2, ..., \mathbf M_N) $, $\mathbf M_i = diag(m_i, m_i, m_i)$, mass of each particle&#xD;&#xA;&#xD;&#xA; - $ \mathbf S = diag(\mathbf S_1, \mathbf S_2, ..., \mathbf S_N) $, &#xD;&#xA;$  \mathbf S_i = \begin{cases}  \mathbf I,  &amp; \text{$ndof(i) = 3$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T,  &amp; \text{$ndof(i) = 2$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T - \mathbf q_i \mathbf q_i^T,  &amp; \text{$ndof(i) = 1$} \\ \mathbf 0,  &amp; \text{$ndof(i) = 0$} \end{cases}$, constraint matrix (Baraff98 chapter 5.1)&#xD;&#xA;&#xD;&#xA; - $\frac{\partial \mathbf f}{\partial \mathbf v}$ and $\frac{\partial \mathbf f}{\partial \mathbf x}$ are symmetrical matrices&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;3. solve the PDE&#xD;&#xA;&#xD;&#xA;The paper solves the aforementioned PDE by **Modified Preconditioning Conjugate Gradient Method** (Baraff98 chapter 5.2) for $\Delta \mathbf v$, then update the velocity $\mathbf v$ and position $\mathbf x$ of each particle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Questions**&#xD;&#xA;&#xD;&#xA;Solve $\mathbf A\mathbf x=\mathbf b$ with PCG method requires the matrix $\mathbf A$ to be symmetrical and positive-definite, where according to the aforementioned PDE, $\mathbf A = (\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})$.&#xD;&#xA;&#xD;&#xA;1. symmentrical&#xD;&#xA;&#xD;&#xA;Treat $\mathbf A$ as an $N\times N$ block matrix, $\mathbf M^{-1}$ and $\mathbf S$ are both block identity matrices, makes $\mathbf A$ a block symmetrical matrix. While $\mathbf A$ as $3N\times 3N$ matrix, $\mathbf S$ is not symmetrical, makes $\mathbf A$ not symmetrical. &#xD;&#xA;&#xD;&#xA;**Question 1**: should I treat $\mathbf A\mathbf x=\mathbf b$ as a block matrix rather than normal matrix? If not, how to make $\mathbf A$ symmetrical?&#xD;&#xA;&#xD;&#xA;I then modified the PDE as $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$, $\mathbf A^T\mathbf A$ is symmetrical.&#xD;&#xA;&#xD;&#xA;**Question 2**: How to make the `fliter` procedure (Baraff98 chapter 5.3) compatible with $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$?&#xD;&#xA;&#xD;&#xA;2. positive-definite&#xD;&#xA;&#xD;&#xA;The blocks $\mathbf S_i$ in $\mathbf S$ may become zero block when $ndof(i) = 0$, which makes $\mathbf A^T\mathbf A$ a positive-semidefinite matrix, according to Baraff98 chapter 5.3, &#xD;&#xA;&#xD;&#xA;&gt; The CG method (technically, the preconditioned CG method) takes a symmetric **positive semi-definite** matrix $\mathbf A$, a **symmetric positive definite** preconditioning matrix $\mathbf P$ of the same dimension as $\mathbf A$ ,a vector $\mathbf b$ and iteratively solves $\mathbf A \Delta \mathbf v = \mathbf b$.&#xD;&#xA;&#xD;&#xA;**Question 3**: How to find the symmetrical and positive-definite preconditioning matrix $\mathbf P$, with $\mathbf A^T\mathbf A$ symmetrical and semi PD?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4342" PostHistoryTypeId="1" PostId="1991" RevisionGUID="f57833b3-8633-453d-8590-dceb53e37124" CreationDate="2016-02-02T12:04:47.037" UserId="2593" Text="Questions about Preconditioning Conjugate Gradient method in Baraff &amp; Witkin 98?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4343" PostHistoryTypeId="3" PostId="1991" RevisionGUID="f57833b3-8633-453d-8590-dceb53e37124" CreationDate="2016-02-02T12:04:47.037" UserId="2593" Text="|real-time|mesh|physically-based|animation|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4344" PostHistoryTypeId="5" PostId="1991" RevisionGUID="4f1f8b6c-9009-4c9d-b31d-b3b41429e8da" CreationDate="2016-02-02T14:08:36.360" UserId="2593" Comment="added 107 characters in body" Text="I encountered some problems when implementing the cloth simulation algorithm from Baraff &amp; Witkin 98's [Large Steps in Cloth Simulation](http://www.cs.cmu.edu/~baraff/papers/sig98.pdf).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Baraff &amp; Witkin 98**&#xD;&#xA;&#xD;&#xA;Consider the cloth as a particle system in 3D, which consists of N particles.&#xD;&#xA;&#xD;&#xA;1. Equation of motion&#xD;&#xA;&#xD;&#xA;In each time step, the implicit integration of particle system is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix} \Delta \mathbf x \\ \Delta \mathbf v \\ \end{pmatrix} = h\begin{pmatrix} \mathbf v_0 + \Delta \mathbf v \\ \mathbf M^{-1} \mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v) \\ \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $h$ is the time step (scalar)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. The partial derivative equation&#xD;&#xA;&#xD;&#xA;Rewrite the aforementioned equality of motion into $\mathbf A \Delta \mathbf v = \mathbf b$ form, (&#xD;&#xA;Take the 1st order Taylor expansion of $\mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v)$, and introduce constraint matrix $\mathbf S$, which make mass matrix from $\mathbf M^{-1}$ to $\mathbf M^{-1}\mathbf S$), we have: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})\Delta \mathbf v = h\mathbf M^{-1} \mathbf S(\mathbf f_0 + h\frac{\partial \mathbf f}{\partial \mathbf x} \mathbf v_0) + \mathbf z&#xD;&#xA;$$ &#xD;&#xA;&#xD;&#xA;Where all of the matrices are treated as $N\times N $ block matrices, eack block sizes $3\times 3 $; vectors as $N$ block vector, each sized $3$ (with N number of 3D forces/positions/velocities).&#xD;&#xA;&#xD;&#xA; - $\mathbf I$ is identical matrix&#xD;&#xA;&#xD;&#xA; - $ \mathbf M = diag(\mathbf M_1, \mathbf M_2, ..., \mathbf M_N) $, $\mathbf M_i = diag(m_i, m_i, m_i)$, mass of each particle&#xD;&#xA;&#xD;&#xA; - $ \mathbf S = diag(\mathbf S_1, \mathbf S_2, ..., \mathbf S_N) $, &#xD;&#xA;$  \mathbf S_i = \begin{cases}  \mathbf I,  &amp; \text{$ndof(i) = 3$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T,  &amp; \text{$ndof(i) = 2$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T - \mathbf q_i \mathbf q_i^T,  &amp; \text{$ndof(i) = 1$} \\ \mathbf 0,  &amp; \text{$ndof(i) = 0$} \end{cases}$, $\mathbf p$ and $\mathbf q$ are two oithogonal constraint direction, $\mathbf S$ is constraint matrix (Baraff98 chapter 5.1)&#xD;&#xA;&#xD;&#xA; - $\frac{\partial \mathbf f}{\partial \mathbf v}$ and $\frac{\partial \mathbf f}{\partial \mathbf x}$ are force derivatives, which are symmetrical matrices&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;3. solve the PDE&#xD;&#xA;&#xD;&#xA;The paper solves the aforementioned PDE by **Modified Preconditioning Conjugate Gradient Method** (Baraff98 chapter 5.2) for $\Delta \mathbf v$, then update the velocity $\mathbf v$ and position $\mathbf x$ of each particle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Questions**&#xD;&#xA;&#xD;&#xA;Solve $\mathbf A\mathbf x=\mathbf b$ with PCG method requires the matrix $\mathbf A$ to be symmetrical and positive-definite, where according to the aforementioned PDE, $\mathbf A = (\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})$.&#xD;&#xA;&#xD;&#xA;1. symmentrical&#xD;&#xA;&#xD;&#xA;Treat $\mathbf A$ as an $N\times N$ block matrix, $\mathbf M^{-1}$ and $\mathbf S$ are both block identity matrices, makes $\mathbf A$ a block symmetrical matrix. While $\mathbf A$ as $3N\times 3N$ matrix, $\mathbf S$ is not symmetrical, makes $\mathbf A$ not symmetrical. &#xD;&#xA;&#xD;&#xA;**Question 1**: should I treat $\mathbf A\mathbf x=\mathbf b$ as a block matrix rather than normal matrix? If not, how to make $\mathbf A$ symmetrical?&#xD;&#xA;&#xD;&#xA;I then modified the PDE as $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$, $\mathbf A^T\mathbf A$ is symmetrical.&#xD;&#xA;&#xD;&#xA;**Question 2**: How to make the `fliter` procedure (Baraff98 chapter 5.3) compatible with $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$?&#xD;&#xA;&#xD;&#xA;2. positive-definite&#xD;&#xA;&#xD;&#xA;The blocks $\mathbf S_i$ in $\mathbf S$ may become zero block when $ndof(i) = 0$, which makes $\mathbf A^T\mathbf A$ a positive-semidefinite matrix, according to Baraff98 chapter 5.3, &#xD;&#xA;&#xD;&#xA;&gt; The CG method (technically, the preconditioned CG method) takes a symmetric **positive semi-definite** matrix $\mathbf A$, a **symmetric positive definite** preconditioning matrix $\mathbf P$ of the same dimension as $\mathbf A$ ,a vector $\mathbf b$ and iteratively solves $\mathbf A \Delta \mathbf v = \mathbf b$.&#xD;&#xA;&#xD;&#xA;**Question 3**: How to find the symmetrical and positive-definite preconditioning matrix $\mathbf P$, with $\mathbf A^T\mathbf A$ symmetrical and semi PD?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4345" PostHistoryTypeId="5" PostId="1991" RevisionGUID="530dd2ec-5a9a-42a1-8bab-7c92e5e6dfe6" CreationDate="2016-02-02T14:15:40.557" UserId="2593" Comment="added 20 characters in body" Text="I encountered some problems when implementing the cloth simulation algorithm from Baraff &amp; Witkin 98's [Large Steps in Cloth Simulation](http://www.cs.cmu.edu/~baraff/papers/sig98.pdf).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Baraff &amp; Witkin 98**&#xD;&#xA;&#xD;&#xA;Consider the cloth as a particle system in 3D, which consists of N particles.&#xD;&#xA;&#xD;&#xA;1. Equation of motion&#xD;&#xA;&#xD;&#xA;In each time step, the implicit integration of particle system is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix} \Delta \mathbf x \\ \Delta \mathbf v \\ \end{pmatrix} = h\begin{pmatrix} \mathbf v_0 + \Delta \mathbf v \\ \mathbf M^{-1} \mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v) \\ \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $h$ is the time step (scalar)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. The partial derivative equation&#xD;&#xA;&#xD;&#xA;Rewrite the aforementioned equality of motion into $\mathbf A \Delta \mathbf v = \mathbf b$ form, (&#xD;&#xA;Take the 1st order Taylor expansion of $\mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v)$, and introduce constraint matrix $\mathbf S$, which make mass matrix from $\mathbf M^{-1}$ to $\mathbf M^{-1}\mathbf S$), we have: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})\Delta \mathbf v = h\mathbf M^{-1} \mathbf S(\mathbf f_0 + h\frac{\partial \mathbf f}{\partial \mathbf x} \mathbf v_0) + \mathbf z&#xD;&#xA;$$ &#xD;&#xA;&#xD;&#xA;Where all of the matrices are treated as $N\times N $ block matrices, eack block sizes $3\times 3 $; vectors as $N$ block vector, each sized $3$ (with N number of 3D forces/positions/velocities).&#xD;&#xA;&#xD;&#xA; - $\mathbf I$ is identical matrix&#xD;&#xA;&#xD;&#xA; - $ \mathbf M = diag(\mathbf M_1, \mathbf M_2, ..., \mathbf M_N) $, $\mathbf M_i = diag(m_i, m_i, m_i)$, mass of each particle&#xD;&#xA;&#xD;&#xA; - $ \mathbf S = diag(\mathbf S_1, \mathbf S_2, ..., \mathbf S_N) $, &#xD;&#xA;$  \mathbf S_i = \begin{cases}  \mathbf I,  &amp; \text{$ndof(i) = 3$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T,  &amp; \text{$ndof(i) = 2$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T - \mathbf q_i \mathbf q_i^T,  &amp; \text{$ndof(i) = 1$} \\ \mathbf 0,  &amp; \text{$ndof(i) = 0$} \end{cases}$, $\mathbf p$ and $\mathbf q$ are two oithogonal constraint direction, $\mathbf S$ is constraint matrix (Baraff98 chapter 5.1)&#xD;&#xA;&#xD;&#xA; - $\frac{\partial \mathbf f}{\partial \mathbf v}$ and $\frac{\partial \mathbf f}{\partial \mathbf x}$ are force derivatives, which are symmetrical matrices&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;3. solve the PDE&#xD;&#xA;&#xD;&#xA;The paper solves the aforementioned PDE by **Modified Preconditioning Conjugate Gradient Method** (Baraff98 chapter 5.2) for $\Delta \mathbf v$, then update the velocity $\mathbf v$ and position $\mathbf x$ of each particle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Questions**&#xD;&#xA;&#xD;&#xA;Solve $\mathbf A\mathbf x=\mathbf b$ with PCG method requires the matrix $\mathbf A$ to be symmetrical and positive-definite, where according to the aforementioned PDE, $\mathbf A = (\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})$.&#xD;&#xA;&#xD;&#xA;1. symmentrical&#xD;&#xA;&#xD;&#xA;Treat $\mathbf A$ as an $N\times N$ block matrix, $\mathbf M^{-1}$ and $\mathbf S$ are both block identity matrices, makes $\mathbf A$ a block symmetrical matrix. While $\mathbf A$ as $3N\times 3N$ matrix, $\mathbf S$ is not symmetrical, makes $\mathbf A$ not symmetrical. &#xD;&#xA;&#xD;&#xA;**Question 1**: should I treat $\mathbf A\mathbf x=\mathbf b$ as a block matrix rather than normal matrix? If not, how to make $\mathbf A$ symmetrical?&#xD;&#xA;&#xD;&#xA;I then modified the PDE as $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$, $\mathbf A^T\mathbf A$ is symmetrical.&#xD;&#xA;&#xD;&#xA;**Question 2**: How to make the `fliter` procedure (Baraff98 chapter 5.3) compatible with $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$?&#xD;&#xA;&#xD;&#xA;2. positive-definite&#xD;&#xA;&#xD;&#xA;The blocks $\mathbf S_i$ in $\mathbf S$ may become zero block when $ndof(i) = 0$, which makes $\mathbf A^T\mathbf A$ a positive-semidefinite matrix. To apply PCG method, according to Baraff98 chapter 5.3:&#xD;&#xA;&#xD;&#xA;&gt; The CG method (technically, the preconditioned CG method) takes a symmetric **positive semi-definite** matrix $\mathbf A$, a **symmetric positive definite** preconditioning matrix $\mathbf P$ of the same dimension as $\mathbf A$ ,a vector $\mathbf b$ and iteratively solves $\mathbf A \Delta \mathbf v = \mathbf b$.&#xD;&#xA;&#xD;&#xA;**Question 3**: How to find the symmetrical and positive-definite preconditioning matrix $\mathbf P$, with $\mathbf A^T\mathbf A$ symmetrical and semi PD?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4346" PostHistoryTypeId="5" PostId="1991" RevisionGUID="68e252c2-e325-4be1-af3a-a5066a669696" CreationDate="2016-02-02T14:59:03.000" UserId="2593" Comment="added 332 characters in body" Text="I encountered some problems when implementing the cloth simulation algorithm from Baraff &amp; Witkin 98's [Large Steps in Cloth Simulation](http://www.cs.cmu.edu/~baraff/papers/sig98.pdf).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Baraff &amp; Witkin 98**&#xD;&#xA;&#xD;&#xA;Consider the cloth as a particle system in 3D, which consists of N particles.&#xD;&#xA;&#xD;&#xA;1. Equation of motion&#xD;&#xA;&#xD;&#xA;In each time step, the implicit integration of particle system is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix} \Delta \mathbf x \\ \Delta \mathbf v \\ \end{pmatrix} = h\begin{pmatrix} \mathbf v_0 + \Delta \mathbf v \\ \mathbf M^{-1} \mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v) \\ \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $h$ is the time step (scalar)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. The partial derivative equation&#xD;&#xA;&#xD;&#xA;Rewrite the aforementioned equality of motion into $\mathbf A \Delta \mathbf v = \mathbf b$ form, (&#xD;&#xA;Take the 1st order Taylor expansion of $\mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v)$, and introduce constraint matrix $\mathbf S$, which make mass matrix from $\mathbf M^{-1}$ to $\mathbf M^{-1}\mathbf S$), we have: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})\Delta \mathbf v = h\mathbf M^{-1} \mathbf S(\mathbf f_0 + h\frac{\partial \mathbf f}{\partial \mathbf x} \mathbf v_0) + \mathbf z&#xD;&#xA;$$ &#xD;&#xA;&#xD;&#xA;Where all of the matrices are treated as $N\times N $ block matrices, eack block sizes $3\times 3 $; vectors as $N$ block vector, each sized $3$ (with N number of 3D forces/positions/velocities).&#xD;&#xA;&#xD;&#xA; - $\mathbf I$ is identical matrix&#xD;&#xA;&#xD;&#xA; - $ \mathbf M = diag(\mathbf M_1, \mathbf M_2, ..., \mathbf M_N) $, $\mathbf M_i = diag(m_i, m_i, m_i)$, mass of each particle&#xD;&#xA;&#xD;&#xA; - $ \mathbf S = diag(\mathbf S_1, \mathbf S_2, ..., \mathbf S_N) $, &#xD;&#xA;$  \mathbf S_i = \begin{cases}  \mathbf I,  &amp; \text{$ndof(i) = 3$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T,  &amp; \text{$ndof(i) = 2$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T - \mathbf q_i \mathbf q_i^T,  &amp; \text{$ndof(i) = 1$} \\ \mathbf 0,  &amp; \text{$ndof(i) = 0$} \end{cases}$, $\mathbf p$ and $\mathbf q$ are two oithogonal constraint direction, $\mathbf S$ is constraint matrix (Baraff98 chapter 5.1)&#xD;&#xA;&#xD;&#xA; - $\frac{\partial \mathbf f}{\partial \mathbf v}$ and $\frac{\partial \mathbf f}{\partial \mathbf x}$ are force derivatives, which are symmetrical matrices&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;3. solve the PDE&#xD;&#xA;&#xD;&#xA;The paper solves the aforementioned PDE by **Modified Preconditioning Conjugate Gradient Method** (Baraff98 chapter 5.2) for $\Delta \mathbf v$, then update the velocity $\mathbf v$ and position $\mathbf x$ of each particle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Questions**&#xD;&#xA;&#xD;&#xA;Solve $\mathbf A\mathbf x=\mathbf b$ with PCG method requires the matrix $\mathbf A$ to be symmetrical and positive-definite, where according to the aforementioned PDE, $\mathbf A = (\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})$.&#xD;&#xA;&#xD;&#xA;1. symmentrical&#xD;&#xA;&#xD;&#xA;Treat $\mathbf A$ as an $N\times N$ block matrix, $\mathbf M^{-1}$ and $\mathbf S$ are both block identity matrices, makes $\mathbf A$ a block symmetrical matrix. While $\mathbf A$ as $3N\times 3N$ matrix, $\mathbf S$ is not symmetrical, makes $\mathbf A$ not symmetrical. &#xD;&#xA;&#xD;&#xA;**Question 1**: should I treat $\mathbf A\mathbf x=\mathbf b$ as a block matrix rather than normal matrix? If not, how to make $\mathbf A$ symmetrical?&#xD;&#xA;&#xD;&#xA;I then modified the PDE as $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$, $\mathbf A^T\mathbf A$ is symmetrical.&#xD;&#xA;&#xD;&#xA;**Question 2**: How to make the `fliter` procedure (Baraff98 chapter 5.3) compatible with $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$?&#xD;&#xA;&#xD;&#xA;2. positive-definite&#xD;&#xA;&#xD;&#xA;The blocks $\mathbf S_i$ in $\mathbf S$ may become zero block when $ndof(i) = 0$, which makes $\mathbf A^T\mathbf A$ a positive-semidefinite matrix. To apply PCG method, according to Baraff98 chapter 5.3:&#xD;&#xA;&#xD;&#xA;&gt; The CG method (technically, the preconditioned CG method) takes a symmetric **positive semi-definite** matrix $\mathbf A$, a **symmetric positive definite** preconditioning matrix $\mathbf P$ of the same dimension as $\mathbf A$ ,a vector $\mathbf b$ and iteratively solves $\mathbf A \Delta \mathbf v = \mathbf b$.&#xD;&#xA;&#xD;&#xA;**Question 3**: How to find the symmetrical and positive-definite preconditioning matrix $\mathbf P$, with $\mathbf A^T\mathbf A$ symmetrical and semi PD?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Some docs I also refered:&#xD;&#xA;&#xD;&#xA; - [On the modified conjugate gradient method in cloth simulation](http://www.cs.ubc.ca/~ascher/papers/ab.pdf)&#xD;&#xA; - [freecloth](http://davidpritchard.org/freecloth/docs/report-single/)&#xD;&#xA; - [Cloth Simulation slides](http://cg.informatik.uni-freiburg.de/course_notes/sim_03_cloth1.pdf)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4347" PostHistoryTypeId="2" PostId="1992" RevisionGUID="f115af4a-a1ba-4864-9c51-16a7fb30f60f" CreationDate="2016-02-02T20:01:54.463" UserId="310" Text="In traditional rendering, it is typical to do all the calculations with radiometric units, either as full spectral rendering, or component-wise (XYZ, RGB, etc).&#xD;&#xA;&#xD;&#xA;However, as modern rendering adds more physically based models, it's convenient for artists to be able to specify values in the more familiar photometric units, for example, intensity of a light in lumens. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In order to keep the pipeline all in one type of unit, you can do one of the following:&#xD;&#xA;&#xD;&#xA;  1. Convert photometric units to radiometric units using [luminous efficacy][2]&#xD;&#xA;  2. Keep the entire render pipeline in photometric units&#xD;&#xA;     - Sébastian Lagarde presents this idea very well in the course notes of his Siggraph 2014 presentation [Moving Frostbite to PBR][3]&#xD;&#xA;&#xD;&#xA;My questions then are these:&#xD;&#xA;&#xD;&#xA; 1. Are there any disadvantages to rendering exclusively in photometric units? &#xD;&#xA;   - As far as I can tell, photometric units are just radiometric units biased to the human eye. Considering that we will view the final image with our eye, I don't see this as a problem.&#xD;&#xA; 2. Frostbite is a RGB component-wise engine. Would a spectral renderer have any additional disadvantages by rendering exclusively in photometric units?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jOg65.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luminous_efficacy&#xD;&#xA;  [3]: http://www.frostbite.com/2014/11/moving-frostbite-to-pbr/" ContentLicense="CC BY-SA 3.0" />
  <row Id="4348" PostHistoryTypeId="1" PostId="1992" RevisionGUID="f115af4a-a1ba-4864-9c51-16a7fb30f60f" CreationDate="2016-02-02T20:01:54.463" UserId="310" Text="Rendering in radiometric units or photometric?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4349" PostHistoryTypeId="3" PostId="1992" RevisionGUID="f115af4a-a1ba-4864-9c51-16a7fb30f60f" CreationDate="2016-02-02T20:01:54.463" UserId="310" Text="|pbr|render|photometric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4350" PostHistoryTypeId="2" PostId="1993" RevisionGUID="ada7a2f4-1264-4ba2-992d-9ac045eb4bac" CreationDate="2016-02-02T20:30:54.753" UserId="2597" Text="I should warn you that I don't really know anything about linux or programming or device drivers, but I had your exact problem once.&#xD;&#xA;&#xD;&#xA;It could be a udev rule problem. Your usergroup might not have permission to write to the gpu device or whatever libOpenCL.so does. Does `$ sudo clinfo` find the gpu?&#xD;&#xA;&#xD;&#xA;Your program might not be using the right opencl library. I think that there is some ubuntu packages that provide libopencl.so. You don't want to use those, they won't know how to talk to your gpu. Could you post:&#xD;&#xA;&#xD;&#xA;    $ ldd /opt/AMDAPP/samples/opencl/bin/x86_64/HelloWorld&#xD;&#xA;&#xD;&#xA;If the libOpenCL.so* line (sometimes libcl.so*) doesn't point to a AMD library, you need to find the AMD libOpenCL.so library and make sure that it is found first before whatever you're using at runtime. &#xD;&#xA;&#xD;&#xA;I would do `$ sudo updatedb` then,&#xD;&#xA;    &#xD;&#xA;    $ locate libOpenCL.so&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;    $ locate libcl.so&#xD;&#xA;&#xD;&#xA;depending on which your `./HelloWorld` is trying to link to. Then set the `LD_LIBRARY_PATH` to the parent folder of the preferred library.&#xD;&#xA;    &#xD;&#xA;    $ export LD_LIBRARY_PATH=/path to lib*cl.so* that was installed by AMD driver/ &#xD;&#xA;$ clinfo&#xD;&#xA;    $ ./HelloWorld&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4352" PostHistoryTypeId="2" PostId="1994" RevisionGUID="989ff03f-c7e6-4723-acf2-83562f19d11a" CreationDate="2016-02-03T07:55:00.923" UserId="48" Text="It's fine to use photometric units as an overall scale for setting light brightnesses. However, there's a technical subtlety you should be aware of. I'll quote from [a blog post I wrote on the subject last year](http://www.reedbeta.com/blog/2014/08/17/radiometry-versus-photometry/):&#xD;&#xA;&#xD;&#xA;&gt; With RGB images, it’s important to recognize that our display devices behave more radiometrically than photometrically. A red pixel value of 255, and a green pixel value of 255, both result in about equal amounts of _radiant_ flux (watts) being generated by a pixel on a screen—_not_ equal amounts of luminous flux. By the same token, digital cameras capture pixel values that correspond to radiant flux, not luminous flux.&#xD;&#xA;&#xD;&#xA;&gt; That’s why we need to use luma coefficients when converting images to grayscale, or calculating the brightness of a pixel, to get a perceptually accurate result; and it also means that rendering RGB images proceeds more naturally in radiometric units than in photometric ones.&#xD;&#xA;&#xD;&#xA;In other words, the wavelength dependence of photometric units is different to what you might be expecting. In ordinary RGB color spaces, white is (1, 1, 1) and has a roughly flat radiometric spectrum; but in a supposed &quot;photometric RGB&quot;, (1, 1, 1) would not be white; it would be a purpleish color, with less energy in the green range and more in the red and blue ranges. A similar problem would afflict spectral renderers trying to measure all their bins in wavelength-dependent photometric units, but even worse, as the radiance needed to generate a given luminance _diverges_ toward either end of the visible spectrum, where the human luminous efficiency function goes to zero.&#xD;&#xA;&#xD;&#xA;So, if you wish to use photometric units, IMO it's better to &quot;cheat&quot; a bit and not use _true_ wavelength-dependent photometric units, but just use some fixed wavelength (such as 555 nm green, which is the peak of the human luminous efficiency function), or perhaps an average over the spectrum, as a reference unit, and apply that single unit to measure all wavelengths. This will get you in less trouble when importing RGB colors and spectra from other sources, and when generating them as outputs." ContentLicense="CC BY-SA 3.0" />
  <row Id="4353" PostHistoryTypeId="2" PostId="1995" RevisionGUID="eb1c3972-58fa-416c-941b-69f25d0d8a83" CreationDate="2016-02-03T12:23:28.790" UserId="2600" Text="I need to do planar reflection mapping in OpenGL. By using a virtual camera (with a reversed camera ray) at the back of reflective plane (a mirror), I rendered the scene to texture, which is then texture mapped to the mirror. The uvs of four corners of the mirror is specified then (using the result of gluProjection). The problem is by default, the uv coordinates are perspective-correctly interpolated, which is not desirable in this case. Is there any way to disable the perspective correction (without using GLSL)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4354" PostHistoryTypeId="1" PostId="1995" RevisionGUID="eb1c3972-58fa-416c-941b-69f25d0d8a83" CreationDate="2016-02-03T12:23:28.790" UserId="2600" Text="How to disable Perspective Correction in Texture Coordinates Interpolation in OpenGL(without using shaders)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4355" PostHistoryTypeId="3" PostId="1995" RevisionGUID="eb1c3972-58fa-416c-941b-69f25d0d8a83" CreationDate="2016-02-03T12:23:28.790" UserId="2600" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4356" PostHistoryTypeId="5" PostId="1991" RevisionGUID="5e07a02f-6d75-419c-afd7-c3fc63e38e7d" CreationDate="2016-02-03T14:05:29.153" UserId="2593" Comment="added 121 characters in body" Text="I encountered some problems when implementing the cloth simulation algorithm from Baraff &amp; Witkin 98's [Large Steps in Cloth Simulation](http://www.cs.cmu.edu/~baraff/papers/sig98.pdf).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Baraff &amp; Witkin 98**&#xD;&#xA;&#xD;&#xA;Consider the cloth as a particle system in 3D, which consists of N particles.&#xD;&#xA;&#xD;&#xA;1. Equation of motion&#xD;&#xA;&#xD;&#xA;In each time step, the implicit integration of particle system is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix} \Delta \mathbf x \\ \Delta \mathbf v \\ \end{pmatrix} = h\begin{pmatrix} \mathbf v_0 + \Delta \mathbf v \\ \mathbf M^{-1} \mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v) \\ \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $h$ is the time step (scalar)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. The partial derivative equation&#xD;&#xA;&#xD;&#xA;Rewrite the aforementioned equality of motion into $\mathbf A \Delta \mathbf v = \mathbf b$ form, (&#xD;&#xA;Take the 1st order Taylor expansion of $\mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v)$, and introduce constraint matrix $\mathbf S$, which make mass matrix from $\mathbf M^{-1}$ to $\mathbf M^{-1}\mathbf S$), we have: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})\Delta \mathbf v = h\mathbf M^{-1} \mathbf S(\mathbf f_0 + h\frac{\partial \mathbf f}{\partial \mathbf x} \mathbf v_0) + \mathbf z&#xD;&#xA;$$ &#xD;&#xA;&#xD;&#xA;Where all of the matrices are treated as $N\times N $ block matrices, eack block sizes $3\times 3 $; vectors as $N$ block vector, each sized $3$ (with N number of 3D forces/positions/velocities).&#xD;&#xA;&#xD;&#xA; - $\mathbf I$ is identical matrix&#xD;&#xA;&#xD;&#xA; - $ \mathbf M = diag(\mathbf M_1, \mathbf M_2, ..., \mathbf M_N) $, $\mathbf M_i = diag(m_i, m_i, m_i)$, mass of each particle&#xD;&#xA;&#xD;&#xA; - $ \mathbf S = diag(\mathbf S_1, \mathbf S_2, ..., \mathbf S_N) $, &#xD;&#xA;$  \mathbf S_i = \begin{cases}  \mathbf I,  &amp; \text{$ndof(i) = 3$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T,  &amp; \text{$ndof(i) = 2$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T - \mathbf q_i \mathbf q_i^T,  &amp; \text{$ndof(i) = 1$} \\ \mathbf 0,  &amp; \text{$ndof(i) = 0$} \end{cases}$, $\mathbf p$ and $\mathbf q$ are two oithogonal constraint direction, $\mathbf S$ is constraint matrix (Baraff98 chapter 5.1)&#xD;&#xA;&#xD;&#xA; - $\frac{\partial \mathbf f}{\partial \mathbf v}$ and $\frac{\partial \mathbf f}{\partial \mathbf x}$ are force derivatives, which are symmetrical matrices&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;3. solve the PDE&#xD;&#xA;&#xD;&#xA;The paper solves the aforementioned PDE by **Modified Preconditioning Conjugate Gradient Method** (Baraff98 chapter 5.2) for $\Delta \mathbf v$, then update the velocity $\mathbf v$ and position $\mathbf x$ of each particle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Questions**&#xD;&#xA;&#xD;&#xA;Solve $\mathbf A\mathbf x=\mathbf b$ with PCG method requires the matrix $\mathbf A$ to be symmetrical and positive-definite, where according to the aforementioned PDE, $\mathbf A = (\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v})$.&#xD;&#xA;&#xD;&#xA;1. symmentrical&#xD;&#xA;&#xD;&#xA;In block view: treat $\mathbf A$ as an $N\times N$ block matrix, $\mathbf M^{-1}$ and $\mathbf S$ are both block diagonal matrices, makes $\mathbf A$ a block symmetrical matrix. While in normal view: $\mathbf A$ as $3N\times 3N$ matrix, $\mathbf S$ is symmetrical, but product of $\mathbf M^{-1} \mathbf S$ and $\frac{\partial \mathbf f}{\partial \mathbf v}$ makes $\mathbf A$ not symmetrical. &#xD;&#xA;&#xD;&#xA;**Question 1**: should I treat $\mathbf A\mathbf x=\mathbf b$ as a block matrix rather than normal matrix? If not, how to make $\mathbf A$ symmetrical?&#xD;&#xA;&#xD;&#xA;I then modified the PDE as $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$, $\mathbf A^T\mathbf A$ is symmetrical.&#xD;&#xA;&#xD;&#xA;**Question 2**: How to make the `fliter` procedure (Baraff98 chapter 5.3) compatible with $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$?&#xD;&#xA;&#xD;&#xA;2. positive-definite&#xD;&#xA;&#xD;&#xA;The blocks $\mathbf S_i$ in $\mathbf S$ may become zero block when $ndof(i) = 0$, which makes $\mathbf A^T\mathbf A$ a positive-semidefinite matrix. To apply PCG method, according to Baraff98 chapter 5.3:&#xD;&#xA;&#xD;&#xA;&gt; The CG method (technically, the preconditioned CG method) takes a symmetric **positive semi-definite** matrix $\mathbf A$, a **symmetric positive definite** preconditioning matrix $\mathbf P$ of the same dimension as $\mathbf A$ ,a vector $\mathbf b$ and iteratively solves $\mathbf A \Delta \mathbf v = \mathbf b$.&#xD;&#xA;&#xD;&#xA;**Question 3**: How to find the symmetrical and positive-definite preconditioning matrix $\mathbf P$, with $\mathbf A^T\mathbf A$ symmetrical and semi PD?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Some docs I also refered:&#xD;&#xA;&#xD;&#xA; - [On the modified conjugate gradient method in cloth simulation](http://www.cs.ubc.ca/~ascher/papers/ab.pdf)&#xD;&#xA; - [freecloth](http://davidpritchard.org/freecloth/docs/report-single/)&#xD;&#xA; - [Cloth Simulation slides](http://cg.informatik.uni-freiburg.de/course_notes/sim_03_cloth1.pdf)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4361" PostHistoryTypeId="2" PostId="1997" RevisionGUID="167085dc-d969-49ce-8066-5a8fd014fbdb" CreationDate="2016-02-03T19:38:55.693" UserId="2602" Text="My FBO is divided into 2 layers which are concentric. First layer is having radius 0.3 and second layer having radius 1 so that it covers the whole screen space. Now I want to avoid to render meshes in outer layer which are already in inner layer. So I calculate the distance between line of sight(where the eye vector hits the screen) and bounding sphere center and checking it against the radius of layers. Now for the meshes which are having the center in lower layer but part of that present in outer layer, those are not rendered in outer layer. To avoid this I thought of solution to transform bounding sphere radius and center of sphere in 0-1 and check the addition of them against radius of layer. but somebody pointed out to me that its not possible to transform radius into 0-1. How do I solve this problem?&#xD;&#xA;when I say inner layer, I am using glscissor of that radius." ContentLicense="CC BY-SA 3.0" />
  <row Id="4362" PostHistoryTypeId="1" PostId="1997" RevisionGUID="167085dc-d969-49ce-8066-5a8fd014fbdb" CreationDate="2016-02-03T19:38:55.693" UserId="2602" Text="culling meshes across mulitple layers" ContentLicense="CC BY-SA 3.0" />
  <row Id="4363" PostHistoryTypeId="3" PostId="1997" RevisionGUID="167085dc-d969-49ce-8066-5a8fd014fbdb" CreationDate="2016-02-03T19:38:55.693" UserId="2602" Text="|opengl|3d|transformations|bounding-volume-hierarchy|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4364" PostHistoryTypeId="2" PostId="1998" RevisionGUID="01e9e46c-8f9f-4653-a6c4-97ddb02dc125" CreationDate="2016-02-03T20:13:24.137" UserId="56" Text="In a webgl pixel shader, all functions are inlined as i understand it, however you can have parameters that are marked as ***in*** versus being ***inout*** meaning that their value can change but the value won't persist outside of the function call.&#xD;&#xA;&#xD;&#xA;Does this mean that the shader must make a copy of the value for the function to work with when it is an ***in*** value?&#xD;&#xA;&#xD;&#xA;Are shader compilers/optimizers smart enough to know when they don't need to make a copy, or is it best to really just mark up all parameters as ***inout*** and make sure and not modify the ones you don't want modified, if performance is the primary concern?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="4365" PostHistoryTypeId="1" PostId="1998" RevisionGUID="01e9e46c-8f9f-4653-a6c4-97ddb02dc125" CreationDate="2016-02-03T20:13:24.137" UserId="56" Text="Cost of parameter passing in webgl pixel shaders?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4366" PostHistoryTypeId="3" PostId="1998" RevisionGUID="01e9e46c-8f9f-4653-a6c4-97ddb02dc125" CreationDate="2016-02-03T20:13:24.137" UserId="56" Text="|webgl|pixel-shader|efficiency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4367" PostHistoryTypeId="10" PostId="1997" RevisionGUID="9d5426f0-5651-41e7-a67a-21a67ea21fb6" CreationDate="2016-02-04T02:43:06.003" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4369" PostHistoryTypeId="2" PostId="1999" RevisionGUID="aaeeaae6-124b-47b5-8f5a-ea52171473ee" CreationDate="2016-02-04T05:55:44.517" UserId="71" Text="Geometry shaders appear to have been introduced in 3.2, which makes me wonder how common 3.2-enabled cards are, including support for Geometry shaders within WebGL contexts.&#xD;&#xA;&#xD;&#xA;Will I be cutting out a large portion of viewers by requiring the use of a geometry shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4370" PostHistoryTypeId="1" PostId="1999" RevisionGUID="aaeeaae6-124b-47b5-8f5a-ea52171473ee" CreationDate="2016-02-04T05:55:44.517" UserId="71" Text="How much should I rely on Geometry shaders in WebGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4371" PostHistoryTypeId="3" PostId="1999" RevisionGUID="aaeeaae6-124b-47b5-8f5a-ea52171473ee" CreationDate="2016-02-04T05:55:44.517" UserId="71" Text="|webgl|geometry-shader|compatibility|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4372" PostHistoryTypeId="2" PostId="2000" RevisionGUID="c6f31159-32ba-4c9b-a33a-3ead28a58bc9" CreationDate="2016-02-04T06:25:05.953" UserDisplayName="user2500" Text="In this case, if treating an &quot;in&quot; only parameter as &quot;in/out&quot; would lead to better performance, a compiler could would do that automatically - it's simple and safe. My experience working with shader compiler stacks a few years back is that they are extremely aggressive, and I doubt you will see any perf difference, but I would always recommend testing as much as you can.&#xD;&#xA;&#xD;&#xA;I would generally recommend providing the compiler (and human readers) with more information where the language allows it, marking parameters according to their usage." ContentLicense="CC BY-SA 3.0" />
  <row Id="4373" PostHistoryTypeId="5" PostId="2000" RevisionGUID="a461f971-5bb8-4193-8e76-f9bb8b67f9a0" CreationDate="2016-02-04T06:30:20.893" UserDisplayName="user2500" Comment="Treating in only parameters as in/out is subtle. Be careful!" Text="My experience working with shader compiler stacks a few years back is that they are extremely aggressive, and I doubt you will see any perf difference, but I would always recommend testing as much as you can.&#xD;&#xA;&#xD;&#xA;I would generally recommend providing the compiler (and human readers) with more information where the language allows it, marking parameters according to their usage. Treating an in-only parameter as in/out is more error prone for humans than compilers." ContentLicense="CC BY-SA 3.0" />
  <row Id="4374" PostHistoryTypeId="2" PostId="2001" RevisionGUID="304d7b8e-c0d2-4584-bcf0-a21d8dcc4a00" CreationDate="2016-02-04T09:29:22.403" UserId="71" Text="WebGL doesn't even currently support geometry shaders, so to directly answer the question: 100% of all users." ContentLicense="CC BY-SA 3.0" />
  <row Id="4379" PostHistoryTypeId="5" PostId="2000" RevisionGUID="b26aebc5-acb3-4f13-92ea-c64939a43650" CreationDate="2016-02-04T16:19:13.670" UserDisplayName="user2500" Comment="Added some explanation." Text="My experience working with shader compiler stacks a few years back is that they are extremely aggressive, and I doubt you will see any perf difference, but I would suggest testing as much as you can.&#xD;&#xA;&#xD;&#xA;I would generally recommend providing the compiler (and human readers) with more information where the language allows it, marking parameters according to their usage. Treating an in-only parameter as in/out is more error prone for humans than compilers.&#xD;&#xA;&#xD;&#xA;Some detail: shaders run almost entirely using registers for variables (I worked with architectures that supported up to 256 32 bit registers) - spilling is hugely expensive. Registers are also shared resource - fewer registers means greater parallelsim. The result is shader compilers work very hard to minimize the number of registers used - without spilling. Thus inlining is common to eliminate anything resembling a stack in memory." ContentLicense="CC BY-SA 3.0" />
  <row Id="4380" PostHistoryTypeId="2" PostId="2003" RevisionGUID="21c9aee4-02e6-4b2f-a290-5bdc937f03e6" CreationDate="2016-02-04T16:38:11.167" UserId="2606" Text="I am developing the algorithm reported in this article:&#xD;&#xA; &#xD;&#xA;[Least square conformal mapping][1]. &#xD;&#xA;&#xD;&#xA;Here is presented an algorithm to flat a 3d mesh on the parametric space, but i don't understand the segmentation step.&#xD;&#xA;&#xD;&#xA;Does anyone know an alternative segmentation approach simpler than the algorithm presented in that article?&#xD;&#xA;&#xD;&#xA;In other word, do you know a simple and efficient mesh segmentation algorithm?&#xD;&#xA;&#xD;&#xA;The requirements are:&#xD;&#xA;&#xD;&#xA;-  charts boundaries should be positioned in such a way that most&#xD;&#xA;of the discontinuities between the charts will be located in zones&#xD;&#xA;where they will not cause texture artifacts,&#xD;&#xA;&#xD;&#xA;-  boundary curves corresponding to high curvature zones of the model.&#xD;&#xA;&#xD;&#xA;Thank you for your help in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.jhu.edu/~misha/Fall09/Levy02.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4381" PostHistoryTypeId="1" PostId="2003" RevisionGUID="21c9aee4-02e6-4b2f-a290-5bdc937f03e6" CreationDate="2016-02-04T16:38:11.167" UserId="2606" Text="3D mesh segmentation simple algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="4382" PostHistoryTypeId="3" PostId="2003" RevisionGUID="21c9aee4-02e6-4b2f-a290-5bdc937f03e6" CreationDate="2016-02-04T16:38:11.167" UserId="2606" Text="|3d|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4384" PostHistoryTypeId="5" PostId="1997" RevisionGUID="3314e46a-be86-41bf-9e00-6236b55c69a8" CreationDate="2016-02-04T23:52:49.583" UserId="2602" Comment="added 38 characters in body" Text="I am implementing foveated rendering. My FBO is divided into 2 layers which are concentric. First layer is having radius 0.3 and second layer having radius 1 so that it covers the whole screen space. Now I want to avoid to render meshes in outer layer which are already in inner layer. So I calculate the distance between line of sight(where the eye vector hits the screen) and bounding sphere center and checking it against the radius of layers. Now for the meshes which are having the center in lower layer but part of that present in outer layer, those are not rendered in outer layer. To avoid this I thought of solution to transform bounding sphere radius and center of sphere in 0-1 and check the addition of them against radius of layer. but somebody pointed out to me that its not possible to transform radius into 0-1. How do I solve this problem?&#xD;&#xA;when I say inner layer, I am using glscissor of that radius." ContentLicense="CC BY-SA 3.0" />
  <row Id="4385" PostHistoryTypeId="5" PostId="2000" RevisionGUID="4a1693dc-f6a2-4e84-8993-d722aa9a5b99" CreationDate="2016-02-05T00:23:26.637" UserDisplayName="user2500" Comment="Cleaned up explanation - grammar, logic." Text="My experience working with shader compiler stacks a few years back is that they are extremely aggressive, and I doubt you will see any perf difference, but I would suggest testing as much as you can.&#xD;&#xA;&#xD;&#xA;I would generally recommend providing the compiler (and human readers) with more information where the language allows it, marking parameters according to their usage. Treating an in-only parameter as in/out is more error prone for humans than compilers.&#xD;&#xA;&#xD;&#xA;Some detail: shaders run almost entirely using registers for variables (I worked with architectures that supported up to 256 32 bit registers) - spilling is hugely expensive. Physical registers are shared between shader invocations - think of this as threads in a HyperThread sense sharing a register pool - and if the shader can be complied to use fewer registers there's greater parallelsim. The result is shader compilers work very hard to minimize the number of registers used - without spilling, of course. Thus inlining is common since it's desirable to optimize register allocation across the whole shader anyway." ContentLicense="CC BY-SA 3.0" />
  <row Id="4386" PostHistoryTypeId="6" PostId="1997" RevisionGUID="2f70a649-510f-4612-9ff5-b5c7254bd7bb" CreationDate="2016-02-05T00:56:23.273" UserId="2602" Comment="edited tags" Text="|opengl|algorithm|3d|transformations|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4387" PostHistoryTypeId="5" PostId="2000" RevisionGUID="369594a0-ffb6-46bc-8f17-ac0148e99931" CreationDate="2016-02-05T04:32:08.370" UserDisplayName="user2500" Comment="edited body" Text="My experience working with shader compiler stacks a few years back is that they are extremely aggressive, and I doubt you will see any perf difference, but I would suggest testing as much as you can.&#xD;&#xA;&#xD;&#xA;I would generally recommend providing the compiler (and human readers) with more information where the language allows it, marking parameters according to their usage. Treating an in-only parameter as in/out is more error prone for humans than compilers.&#xD;&#xA;&#xD;&#xA;Some detail: shaders run almost entirely using registers for variables (I worked with architectures that supported up to 256 32 bit registers) - spilling is hugely expensive. Physical registers are shared between shader invocations - think of this as threads in a HyperThread sense sharing a register pool - and if the shader can be complied to use fewer registers there's greater parallelism. The result is shader compilers work very hard to minimize the number of registers used - without spilling, of course. Thus inlining is common since it's desirable to optimize register allocation across the whole shader anyway." ContentLicense="CC BY-SA 3.0" />
  <row Id="4388" PostHistoryTypeId="5" PostId="1997" RevisionGUID="f1ffee2e-5486-47c0-88f6-b117bab5947c" CreationDate="2016-02-05T05:34:47.353" UserId="2602" Comment="implemented new algorithm" Text="I am implementing foveated rendering. My FBO is divided into 2 layers which are concentric. First layer is having radius 0.3 and second layer having radius 1 so that it covers the whole screen space. Now I want to avoid to render meshes in outer layer which are already in inner layer. &#xD;&#xA;I have implemented following culling algorithm which is only concerned with culling between the layers:&#xD;&#xA;&#xD;&#xA;1. I create a rectangles with min and max corner from the radius of 2 layers. Now these coordinates are in NDC. &#xD;&#xA;2. I have min and max corner of each mesh in local coordinate system. so I transform them into NDC using:&#xD;&#xA;&#xD;&#xA;    vec4 min=mvp * vec4(min_corner,1.0);&#xD;&#xA;    min=min.xyzw/min.w;&#xD;&#xA;&#xD;&#xA;3. I create bounding box using min and max corners.&#xD;&#xA;4. Check whether 2 rectangles overlap or not.&#xD;&#xA;&#xD;&#xA;Now, when I transform into clip space, the x or y coordinates of min are sometimes greater than max corner. Same issue occurs when I divide them by w. Whats going wrong here?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4389" PostHistoryTypeId="5" PostId="1997" RevisionGUID="b172069a-5fde-4426-baaa-351b4d112f8c" CreationDate="2016-02-05T05:41:48.167" UserId="2602" Comment="deleted 24 characters in body" Text="I am implementing foveated rendering. My FBO is divided into 2 layers which are concentric. First layer covers 1/3 of Framebuffer whereas second one covers rest of the screen. Now I want to avoid to render meshes in outer layer which are already in inner layer. &#xD;&#xA;I have implemented following culling algorithm which is only concerned with culling between the layers:&#xD;&#xA;&#xD;&#xA;1. I create a rectangles with min and max corner from the radius of 2 layers. Now these coordinates are in NDC. &#xD;&#xA;2. I have min and max corner of each mesh in local coordinate system. so I transform them into NDC using:&#xD;&#xA;&#xD;&#xA;    vec4 min=mvp * vec4(min_corner,1.0);&#xD;&#xA;    min=min.xyzw/min.w;&#xD;&#xA;&#xD;&#xA;3. I create bounding box using min and max corners.&#xD;&#xA;4. Check whether 2 rectangles overlap or not.&#xD;&#xA;&#xD;&#xA;Now, when I transform into clip space, the x or y coordinates of min are sometimes greater than max corner. Same issue occurs when I divide them by w. Whats going wrong here?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4390" PostHistoryTypeId="2" PostId="2004" RevisionGUID="0375f9bd-7216-4c49-bc58-fbbce9a93a64" CreationDate="2016-02-05T08:07:12.037" UserId="2609" Text="For the current state-of-the-art, look for this paper:&#xD;&#xA;&quot;Maximum Mipmaps for Fast, Accurate, and Scalable Dynamic Height Field&#xD;&#xA;Rendering&quot;, Tevs et al. 2008&#xD;&#xA;&#xD;&#xA;The basic idea is to skip a lot of space by having knowledge of the maximum value over large areas of terrain. If the ray stays above that, skip to the next large area. &#xD;&#xA;&#xD;&#xA;If you look at Figure 8, you'll see a comparison of basic linear stepping vs. maximum mipmaps. Linear stepping results in 200 steps, which can be done real-time on modern gpus but is still actually slow. Max mipmaps do the same in about 10 steps, all in shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4391" PostHistoryTypeId="5" PostId="1983" RevisionGUID="160f530b-35f2-4676-a54e-3bce8310fd4e" CreationDate="2016-02-05T10:52:57.643" UserId="2574" Comment="added 1097 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius.&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The image of the horizon is a portion of a conic section; ***this, or something equivalent to it, is the formula for which I need a reputable reference:***&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/e-e)-1\,]^{2}+x^{2}(1/e^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $e=1/\sqrt{\epsilon(2+\epsilon)}$ is the eccentricity of the conic, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole to the back of the camera is assumed to be 1 unit length. The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;Equivalently, there is the following parametric representation of the curve:&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4395" PostHistoryTypeId="5" PostId="1983" RevisionGUID="004403be-c23a-43b4-b686-4b3d5f9a3b33" CreationDate="2016-02-05T19:00:41.593" UserId="2574" Comment="added 2952 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Two different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formula, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); &#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case); and &#xD;&#xA;&#xD;&#xA;$x_{0}=0$.&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4397" PostHistoryTypeId="5" PostId="1983" RevisionGUID="f1fb02e5-5067-4066-b7fd-2c4b93d7f974" CreationDate="2016-02-05T23:40:30.883" UserId="2574" Comment="added 4 characters in body; edited tags" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formula, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); &#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case); and &#xD;&#xA;&#xD;&#xA;$x_{0}=0$.&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4398" PostHistoryTypeId="6" PostId="1983" RevisionGUID="f1fb02e5-5067-4066-b7fd-2c4b93d7f974" CreationDate="2016-02-05T23:40:30.883" UserId="2574" Comment="added 4 characters in body; edited tags" Text="|projections|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4399" PostHistoryTypeId="5" PostId="1983" RevisionGUID="de2f8e33-124c-446f-8f36-7bb5a39a9960" CreationDate="2016-02-05T23:53:21.043" UserId="2574" Comment="added 293 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. [Instead of using $\epsilon$, which is the ratio  of the *altitude* to $R$, it may be useful to use $\eta$, the ratio of *the pinhole's distance to the Earth's center*, $h+R$, to the Earth's radius: $\eta=(R+h)/R=1+\epsilon$. In terms of $\eta$, we have $\varepsilon=1/\sqrt{\eta^{2}-1}$.]&#xD;&#xA;&#xD;&#xA;The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formula, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); &#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case); and &#xD;&#xA;&#xD;&#xA;$x_{0}=0$.&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4400" PostHistoryTypeId="5" PostId="1983" RevisionGUID="38178c94-5a10-4642-b24e-3e277464ba9c" CreationDate="2016-02-06T00:01:25.783" UserId="2574" Comment="deleted 2 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. [Instead of using $\epsilon$, which is the ratio  of the *altitude* to $R$, it may be useful to use $\eta$, the ratio of *the pinhole's distance to the Earth's center*, $h+R$, to the Earth's radius: $\eta=(R+h)/R=1+\epsilon$. In terms of $\eta$, we have $\varepsilon=1/\sqrt{\eta^{2}-1}$.]&#xD;&#xA;&#xD;&#xA;The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formula, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$x_{0}=0$;&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); and&#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case).&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4404" PostHistoryTypeId="5" PostId="1997" RevisionGUID="cd67c331-bcd7-4c27-9e1e-4a84c1fa6b5a" CreationDate="2016-02-06T00:41:30.493" UserId="2602" Comment="Found the issue" Text="I am implementing foveated rendering. My FBO is divided into 2 layers which are concentric. First layer covers 1/3 of Framebuffer whereas second one covers rest of the screen. Now I want to avoid to render meshes in outer layer which are already in inner layer. &#xD;&#xA;I have implemented following culling algorithm which is only concerned with culling between the layers:&#xD;&#xA;&#xD;&#xA;1. I create a rectangles with min and max corner from the radius of 2 layers. Now these coordinates are in NDC. &#xD;&#xA;2. I have min and max corner of each mesh in local coordinate system. so I transform them into NDC using:&#xD;&#xA;&#xD;&#xA;    vec4 min=mvp * vec4(min_corner,1.0);&#xD;&#xA;    min=min.xyzw/min.w;&#xD;&#xA;&#xD;&#xA;3. I create bounding box using min and max corners.&#xD;&#xA;4. Check whether 2 rectangles overlap or not.&#xD;&#xA;&#xD;&#xA;Now, when I transform into clip space, the x or y coordinates of min are sometimes greater than max corner. Same issue occurs when I divide them by w. Whats going wrong here?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Okay. I found the problem, now I iterate over all the vertices transform each of them into NDC using MVP and then calculate min and max corner which works perfect. But this is much more overhead for each frame. Is there any optimization I can do here?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4405" PostHistoryTypeId="5" PostId="1997" RevisionGUID="9429a427-8040-4fe3-9e22-e8ae594b60d3" CreationDate="2016-02-06T13:14:25.530" UserId="231" Comment="Add links and hovertext for acronyms. Minor formating and wording." Text="I am implementing foveated rendering. My [FBO] is divided into 2 layers which are concentric. The first layer covers 1/3 of the Framebuffer whereas the second one covers the rest of the screen. Now I want to avoid rendering meshes in the outer layer which are already in the inner layer.&#xD;&#xA;&#xD;&#xA;I have implemented the following culling algorithm which is only concerned with culling between the layers:&#xD;&#xA;&#xD;&#xA;1. I create rectangles with min and max corners from the radii of the 2 layers. Now these coordinates are in [NDC]. &#xD;&#xA;2. I have the min and max corner of each mesh in the local coordinate system. So I transform them into NDC using:&#xD;&#xA;&#xD;&#xA;        vec4 min = mvp * vec4(min_corner, 1.0);&#xD;&#xA;        min = min.xyzw / min.w;&#xD;&#xA;&#xD;&#xA;3. I create a bounding box using min and max corners.&#xD;&#xA;4. I check whether 2 rectangles overlap or not.&#xD;&#xA;&#xD;&#xA;Now, when I transform into clip space, the x or y coordinates of the min are sometimes greater than the max corner. The same issue occurs when I divide them by w. What's going wrong here?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Okay. I found the problem. Now I iterate over all the vertices, transform each of them into NDC using [MVP] and then calculate the min and max corners which works perfect. But this is much more overhead for each frame. Is there any optimization I can do here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [FBO]: https://en.wikipedia.org/wiki/Framebuffer_Object &quot;Framebuffer Object&quot;&#xD;&#xA;&#xD;&#xA;  [NDC]: https://www.ncl.ucar.edu/Document/Graphics/ndc.shtml &quot;Normalized Device Coordinates&quot;&#xD;&#xA;&#xD;&#xA;  [MVP]: http://stackoverflow.com/questions/5550620/the-purpose-of-model-view-projection-matrix &quot;Model View Projection matrix&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4406" PostHistoryTypeId="11" PostId="1997" RevisionGUID="09b97211-02f5-424b-b0c5-ec665fa7c47d" CreationDate="2016-02-06T13:17:13.873" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4407" PostHistoryTypeId="5" PostId="1983" RevisionGUID="d649a252-4a9f-469c-a559-d9903330afed" CreationDate="2016-02-06T14:59:20.260" UserId="2574" Comment="added 4 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. [Instead of using $\epsilon$, which is the ratio  of the *altitude* to $R$, it may be useful to use $\eta$, the ratio of *the pinhole's distance to the Earth's center*, $h+R$, to the Earth's radius: $\eta=(R+h)/R=1+\epsilon$. In terms of $\eta$, we have $\varepsilon=1/\sqrt{\eta^{2}-1}$.]&#xD;&#xA;&#xD;&#xA;The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formula, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon^{2}) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$x_{0}=0$;&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); and&#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case).&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4408" PostHistoryTypeId="5" PostId="1983" RevisionGUID="9e24114b-623c-45ee-aa3a-49b8eec86bae" CreationDate="2016-02-06T15:11:26.737" UserId="2574" Comment="added 4 characters in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. [Instead of using $\epsilon$, which is the ratio  of the *altitude* to $R$, it may be useful to use $\eta$, the ratio of *the pinhole's distance to the Earth's center*, $h+R$, to the Earth's radius: $\eta=(R+h)/R=1+\epsilon$. In terms of $\eta$, we have $\varepsilon=1/\sqrt{\eta^{2}-1}$.]&#xD;&#xA;&#xD;&#xA;The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formula, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon^{2}) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;The advantage of the canonical form is that it can deal with all conics on an equal footing, including in particular the case of the parabola, $\varepsilon=1$. In the ``standard'' formulation (see below), the case of the parabola can only be dealt with by taking the limit $\varepsilon\to 1$.&#xD;&#xA;&#xD;&#xA;Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$x_{0}=0$;&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); and&#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case).&#xD;&#xA;&#xD;&#xA;It is obvious that the parabolic case, $\varepsilon=1$, will create problems; as mentioned above, that case must be dealt with through taking the limit $\varepsilon\to 1$.&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4409" PostHistoryTypeId="2" PostId="2007" RevisionGUID="8a9459e8-17c2-4040-b97c-80580c38992e" CreationDate="2016-02-06T17:36:28.740" UserId="273" Text="Regarding optimizations:&#xD;&#xA;&#xD;&#xA;Could you calculate the min and max corners in modelspace beforehand? Then you could check on the CPU-side the NCDs of these two points and skip the processing of the whole mesh if it is outside of the desired range. This needs only two matrix-vector multiplications on cpu side. And since for rigid bodies these two points do not change over time, you don't have to iterate the meshes in each frame." ContentLicense="CC BY-SA 3.0" />
  <row Id="4410" PostHistoryTypeId="5" PostId="2007" RevisionGUID="7ced6c66-c4fa-4c4e-a722-88b41360b77e" CreationDate="2016-02-06T21:04:52.903" UserId="273" Comment="corrected a spelling mistake" Text="Regarding optimizations:&#xD;&#xA;&#xD;&#xA;Could you calculate the min and max corners in modelspace beforehand? Then you could check on the CPU-side the NDCs of these two points and skip the processing of the whole mesh if it is outside of the desired range. This needs only two matrix-vector multiplications on cpu side. And since for rigid bodies these two points do not change over time, you don't have to iterate the meshes in each frame." ContentLicense="CC BY-SA 3.0" />
  <row Id="4411" PostHistoryTypeId="2" PostId="2008" RevisionGUID="e1d2a882-1fca-4aa1-9db3-1dc7b8e752eb" CreationDate="2016-02-07T02:38:23.367" UserId="2096" Text="[![As you can see the back face is lighting as well][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8UV6b.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hello everyone..&#xD;&#xA;I am having problem with lighting calculations.&#xD;&#xA;I am rotating a camera around the cube which was supposed to be illuminated by the light but the resulting lighting is very weird.&#xD;&#xA;check out the pic,fragment shader and vertex shader below.&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 norm;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    uniform vec3 lightPos;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    out vec3 ourNormal;&#xD;&#xA;    out vec3 fragPos;&#xD;&#xA;    out vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection*view*model*vec4(pos,1.0);&#xD;&#xA;	    fragPos = vec3(view * model * vec4(pos, 1.0f));&#xD;&#xA;        ourNormal = mat3(transpose(inverse(view * model))) * norm;&#xD;&#xA;	    ourLightPos = vec3(view * vec4(lightPos, 1.0));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    //fragment shader&#xD;&#xA;    &#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    //Output variables&#xD;&#xA;    out vec4 finalColor;&#xD;&#xA;&#xD;&#xA;    //Input variables&#xD;&#xA;    in vec3 ourNormal;&#xD;&#xA;    in vec3 fragPos;&#xD;&#xA;    in vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    //Uniform variables&#xD;&#xA;&#xD;&#xA;    struct Material&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;	    float shininess;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Light&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    uniform Light light;&#xD;&#xA;    uniform Material material;&#xD;&#xA;    uniform vec3 viewPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    //Ambient&#xD;&#xA;	    vec3 ambient = light.ambient*material.ambient;&#xD;&#xA;&#xD;&#xA;	    //Diffuse&#xD;&#xA;	    vec3 normal = normalize(ourNormal);&#xD;&#xA;	    vec3 lightDir = normalize(ourLightPos - fragPos);&#xD;&#xA;	    float diffuseStrength = max(dot(lightDir,normal),0.0);&#xD;&#xA;	    vec3 diffuse = light.diffuse*(diffuseStrength*material.diffuse);&#xD;&#xA;&#xD;&#xA;	    //Specular&#xD;&#xA;	    vec3 viewDir = normalize(viewPos - fragPos);&#xD;&#xA;	    vec3 reflectDir = reflect(-lightDir,normal);&#xD;&#xA;	    float specularStrength =         pow(max(dot(viewDir,reflectDir),0.0),material.shininess);&#xD;&#xA;	    vec3 specular = light.specular * (specularStrength*material.specular);&#xD;&#xA;&#xD;&#xA;	    //Last step&#xD;&#xA;	    vec3 result = (ambient+diffuse+specular);&#xD;&#xA;	    finalColor = vec4(result,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see I transformed all the positions,normals and light source position in view space i.e camera space but I don't know why Its not working.&#xD;&#xA;Please help.." ContentLicense="CC BY-SA 3.0" />
  <row Id="4412" PostHistoryTypeId="1" PostId="2008" RevisionGUID="e1d2a882-1fca-4aa1-9db3-1dc7b8e752eb" CreationDate="2016-02-07T02:38:23.367" UserId="2096" Text="OpenGL Lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="4413" PostHistoryTypeId="3" PostId="2008" RevisionGUID="e1d2a882-1fca-4aa1-9db3-1dc7b8e752eb" CreationDate="2016-02-07T02:38:23.367" UserId="2096" Text="|opengl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4414" PostHistoryTypeId="5" PostId="2008" RevisionGUID="faad2d3d-5709-45d5-afc2-b8f30daeb340" CreationDate="2016-02-07T04:45:01.080" UserId="2096" Comment="deleted 4 characters in body" Text="[![As you can see the back face is lighting as well][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8UV6b.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hello everyone..&#xD;&#xA;I am having problem with lighting calculations.&#xD;&#xA;I am rotating camera around a cube which was supposed to be illuminated by the light but the resulting lighting is very weird.&#xD;&#xA;check out the pic,fragment shader and vertex shader below.&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 norm;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    uniform vec3 lightPos;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    out vec3 ourNormal;&#xD;&#xA;    out vec3 fragPos;&#xD;&#xA;    out vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection*view*model*vec4(pos,1.0);&#xD;&#xA;	    fragPos = vec3(view * model * vec4(pos, 1.0f));&#xD;&#xA;        ourNormal = mat3(transpose(inverse(view * model))) * norm;&#xD;&#xA;	    ourLightPos = vec3(view * vec4(lightPos, 1.0));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    //fragment shader&#xD;&#xA;    &#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    //Output variables&#xD;&#xA;    out vec4 finalColor;&#xD;&#xA;&#xD;&#xA;    //Input variables&#xD;&#xA;    in vec3 ourNormal;&#xD;&#xA;    in vec3 fragPos;&#xD;&#xA;    in vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    //Uniform variables&#xD;&#xA;&#xD;&#xA;    struct Material&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;	    float shininess;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Light&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    uniform Light light;&#xD;&#xA;    uniform Material material;&#xD;&#xA;    uniform vec3 viewPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    //Ambient&#xD;&#xA;	    vec3 ambient = light.ambient*material.ambient;&#xD;&#xA;&#xD;&#xA;	    //Diffuse&#xD;&#xA;	    vec3 normal = normalize(ourNormal);&#xD;&#xA;	    vec3 lightDir = normalize(ourLightPos - fragPos);&#xD;&#xA;	    float diffuseStrength = max(dot(lightDir,normal),0.0);&#xD;&#xA;	    vec3 diffuse = light.diffuse*(diffuseStrength*material.diffuse);&#xD;&#xA;&#xD;&#xA;	    //Specular&#xD;&#xA;	    vec3 viewDir = normalize(viewPos - fragPos);&#xD;&#xA;	    vec3 reflectDir = reflect(-lightDir,normal);&#xD;&#xA;	    float specularStrength =         pow(max(dot(viewDir,reflectDir),0.0),material.shininess);&#xD;&#xA;	    vec3 specular = light.specular * (specularStrength*material.specular);&#xD;&#xA;&#xD;&#xA;	    //Last step&#xD;&#xA;	    vec3 result = (ambient+diffuse+specular);&#xD;&#xA;	    finalColor = vec4(result,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see I transformed all the positions,normals and light source position in view space i.e camera space but I don't know why Its not working.&#xD;&#xA;Please help.." ContentLicense="CC BY-SA 3.0" />
  <row Id="4416" PostHistoryTypeId="2" PostId="2009" RevisionGUID="331d160c-e2e4-4123-9345-ccd01338cdac" CreationDate="2016-02-07T17:31:50.120" UserId="2621" Text="I am trying to plug in a 3D game engine as the rendering engine for an existing graphic API system that uses a right-handed coordinate system.&#xD;&#xA;&#xD;&#xA;Game engines often uses a left handed coordinate system internally.  so how can I convert the API parameters, 3d vectors, transformation matrices, and quaternions that are right handed at the API boundary to left handed equivalents before passing to the engine's APIs at a lower layer, and transforms output parameters from the engine back to the right hand representations for the higher level APIs?  &#xD;&#xA;&#xD;&#xA;both coordinate systems I am referring to here are, x pointing to the right, y pointing to the top, and z point away from the eye (left hand) and towards or behinds the eye (right hand), with the eye at the origin or some distance behind the xy plane to allow the origin to be in the camera view.&#xD;&#xA;&#xD;&#xA;example: for simple 3d points. the conversion step would be just to flip the sign of the z value.&#xD;&#xA;&#xD;&#xA;Thanks for information on this" ContentLicense="CC BY-SA 3.0" />
  <row Id="4417" PostHistoryTypeId="1" PostId="2009" RevisionGUID="331d160c-e2e4-4123-9345-ccd01338cdac" CreationDate="2016-02-07T17:31:50.120" UserId="2621" Text="implementing right handed coord system APIs on top of a left-handed rendering engine" ContentLicense="CC BY-SA 3.0" />
  <row Id="4418" PostHistoryTypeId="3" PostId="2009" RevisionGUID="331d160c-e2e4-4123-9345-ccd01338cdac" CreationDate="2016-02-07T17:31:50.120" UserId="2621" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4419" PostHistoryTypeId="5" PostId="2009" RevisionGUID="5fd2390e-e4a0-4b4c-809c-a345442280f1" CreationDate="2016-02-07T19:42:58.777" UserId="273" Comment="Changed the formatting and made some sentences shorter for easier reading." Text="I am trying to plug in a 3D game engine as the rendering engine for an existing graphic API system that uses a right-handed coordinate system.&#xD;&#xA;&#xD;&#xA;Game engines often uses a left handed coordinate system internally.&#xD;&#xA;&#xD;&#xA;So how can I convert the API parameters, 3d vectors, transformation matrices, and quaternions?&#xD;&#xA;&#xD;&#xA;The right handed versions at the API boundary have to be converted to left handed equivalents before passing to the engine's APIs at a lower layer, and then the output parameters from the engine have to be converted back to the right hand representations for the higher level APIs.  &#xD;&#xA;&#xD;&#xA;Both coordinate systems I am referring to here are, x pointing to the right, y pointing to the top, and z point away from the eye (left hand) and towards or behinds the eye (right hand), with the eye at the origin or some distance behind the xy plane to allow the origin to be in the camera view.&#xD;&#xA;&#xD;&#xA;Example: For simple 3d-points, the conversion step would be just to flip the sign of the z value.&#xD;&#xA;&#xD;&#xA;Thanks for information on this." ContentLicense="CC BY-SA 3.0" />
  <row Id="4420" PostHistoryTypeId="24" PostId="2009" RevisionGUID="5fd2390e-e4a0-4b4c-809c-a345442280f1" CreationDate="2016-02-07T19:42:58.777" Comment="Proposed by 273 approved by 231 edit id of 122" ContentLicense="CC BY-SA 3.0" />
  <row Id="4421" PostHistoryTypeId="5" PostId="2009" RevisionGUID="1c15ac1a-6ffe-45ad-a0bf-0d82ea992806" CreationDate="2016-02-07T19:48:24.747" UserId="231" Comment="Remove thank you" Text="I am trying to plug in a 3D game engine as the rendering engine for an existing graphic API system that uses a right-handed coordinate system.&#xD;&#xA;&#xD;&#xA;Game engines often uses a left handed coordinate system internally.&#xD;&#xA;&#xD;&#xA;So how can I convert the API parameters, 3d vectors, transformation matrices, and quaternions?&#xD;&#xA;&#xD;&#xA;The right handed versions at the API boundary have to be converted to left handed equivalents before passing to the engine's APIs at a lower layer, and then the output parameters from the engine have to be converted back to the right hand representations for the higher level APIs.  &#xD;&#xA;&#xD;&#xA;Both coordinate systems I am referring to here are, x pointing to the right, y pointing to the top, and z point away from the eye (left hand) and towards or behinds the eye (right hand), with the eye at the origin or some distance behind the xy plane to allow the origin to be in the camera view.&#xD;&#xA;&#xD;&#xA;Example: For simple 3d-points, the conversion step would be just to flip the sign of the z value." ContentLicense="CC BY-SA 3.0" />
  <row Id="4422" PostHistoryTypeId="2" PostId="2010" RevisionGUID="0b9e0dc8-4adf-416d-ba25-fc9436cc8a2e" CreationDate="2016-02-07T22:50:50.250" UserId="2623" Text="In a modern day desktop or mobile computer, you got the CPU, the RAM, the GPU and it's own video RAM. When a modern OS renderes an image to the screen, where is the actual image data for that screen located? (Talking about a default HDMI output port)&#xD;&#xA;&#xD;&#xA;Is it within the memory of the OS Kernel in RAM, fetching the rendered image of an onscreen window from the GPU when preparing the next frame?&#xD;&#xA;&#xD;&#xA;Is it within the GPUs VRAM, accessed and manipulated by low level CPU instructions?&#xD;&#xA;&#xD;&#xA;Is it within the GPUs VRAM, mapped via DMA to the CPUs adress space?&#xD;&#xA;&#xD;&#xA;And also, where can I read up on implementing some of these basic access patterns for a custom written science project OS? A friend of mine managed to get the SVGA mode running in assembly, but I guess one can do more." ContentLicense="CC BY-SA 3.0" />
  <row Id="4423" PostHistoryTypeId="1" PostId="2010" RevisionGUID="0b9e0dc8-4adf-416d-ba25-fc9436cc8a2e" CreationDate="2016-02-07T22:50:50.250" UserId="2623" Text="Where is the shown display image actually stored and accessed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4424" PostHistoryTypeId="3" PostId="2010" RevisionGUID="0b9e0dc8-4adf-416d-ba25-fc9436cc8a2e" CreationDate="2016-02-07T22:50:50.250" UserId="2623" Text="|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4425" PostHistoryTypeId="2" PostId="2011" RevisionGUID="33ebc86e-8999-4f9e-ace1-23958bc6eb9e" CreationDate="2016-02-07T23:01:51.920" UserId="2622" Text="I am using a single VBO to store vertices in the follow format:&#xD;&#xA;&#xD;&#xA;v1X, v1Y, v1Z, v1R, v1G, v1B, v2A,&#xD;&#xA;v2X, ...&#xD;&#xA;&#xD;&#xA;Vertex positioning is fine, shapes show up where expected, however instead of using the colour provided, all shapes show up red.&#xD;&#xA;&#xD;&#xA;The code given below simply draws two triangles to form one square ground shape.&#xD;&#xA;&#xD;&#xA;Buffer data preparation method&#xD;&#xA;&#xD;&#xA;    public void prepare(float[] data) {&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, vboID);&#xD;&#xA;        FloatBuffer dataBuffer = RenderUtils.fArrayToBuffer(data);&#xD;&#xA;        if(dataLength != data.length) {&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);&#xD;&#xA;            dataLength = data.length;&#xD;&#xA;        } else {&#xD;&#xA;            glBufferSubData(GL_ARRAY_BUFFER, 0, dataBuffer);&#xD;&#xA;        }&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, false, 7*4, 0);&#xD;&#xA;        glVertexAttribPointer(3, 4, GL_FLOAT, false, 7*4, 3*4);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Render code&#xD;&#xA;&#xD;&#xA;    floorObj.prepare(new float[]{&#xD;&#xA;        -5, 0, -5,   1, 0, 0, 1,&#xD;&#xA;        5, 0, -5,   0, 1, 0, 1,&#xD;&#xA;        -5, 0, 5,   0, 0, 1, 1,&#xD;&#xA;    &#xD;&#xA;        5, 0, -5,   1, 0, 0, 1,&#xD;&#xA;        5, 0, 5,   0, 1, 0, 1,&#xD;&#xA;        -5, 0, 5,   0, 0, 1, 1,&#xD;&#xA;    });&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;Vertex shader&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec3 position;&#xD;&#xA;    in vec4 i_color;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;        gl_Position = transform * vec4(position, 1);&#xD;&#xA;        color = i_color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec4 color;&#xD;&#xA;    out vec4 f_color;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;        f_color = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As previously stated, vertex positions work fine, however colour does not.&#xD;&#xA;Just ask if any other code would be useful to determine the problem.&#xD;&#xA;&#xD;&#xA;Thanks, - Jasper" ContentLicense="CC BY-SA 3.0" />
  <row Id="4426" PostHistoryTypeId="1" PostId="2011" RevisionGUID="33ebc86e-8999-4f9e-ace1-23958bc6eb9e" CreationDate="2016-02-07T23:01:51.920" UserId="2622" Text="OpenGL - Colours not working properly" ContentLicense="CC BY-SA 3.0" />
  <row Id="4427" PostHistoryTypeId="3" PostId="2011" RevisionGUID="33ebc86e-8999-4f9e-ace1-23958bc6eb9e" CreationDate="2016-02-07T23:01:51.920" UserId="2622" Text="|opengl|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4428" PostHistoryTypeId="2" PostId="2012" RevisionGUID="d7c67e60-058f-4286-8943-b815d90aef66" CreationDate="2016-02-08T02:09:01.450" UserId="1810" Text="why not building a bounding box (or spheres) hierarchy ?&#xD;&#xA;&#xD;&#xA;(but for a shadertoy implementation, the lack of dynamic loop length might spoil the gain )." ContentLicense="CC BY-SA 3.0" />
  <row Id="4429" PostHistoryTypeId="2" PostId="2013" RevisionGUID="fcbad49f-8da7-428e-9783-0f194a94adea" CreationDate="2016-02-08T12:46:04.260" UserId="2623" Text="The documentation of &lt;code&gt;glFramebufferRenderbuffer&lt;/code&gt; only says that &lt;code&gt;renderbuffertarget&lt;/code&gt; needs to be &lt;code&gt;GL_RENDERBUFFER&lt;/code&gt;, though it does not specify that the attached renderbuffer, that is also given to the function, needs to be bound to &lt;code&gt;GL_RENDERBUFFER&lt;/code&gt; beforehand.&#xD;&#xA;&#xD;&#xA;I deem it not having to be so, because why would I have to specify the renderbuffer again if it should be bound beforehand?&#xD;&#xA;&#xD;&#xA;Especially since the glNamedFramebufferRenderbuffer was introduced, it should not be nesseccary to bind anything." ContentLicense="CC BY-SA 3.0" />
  <row Id="4430" PostHistoryTypeId="1" PostId="2013" RevisionGUID="fcbad49f-8da7-428e-9783-0f194a94adea" CreationDate="2016-02-08T12:46:04.260" UserId="2623" Text="Renderbuffer needs to be bound before glFramebufferRenderbuffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4431" PostHistoryTypeId="3" PostId="2013" RevisionGUID="fcbad49f-8da7-428e-9783-0f194a94adea" CreationDate="2016-02-08T12:46:04.260" UserId="2623" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4432" PostHistoryTypeId="2" PostId="2014" RevisionGUID="42c70fc7-ad24-495a-ae0a-6f0b5a399aa1" CreationDate="2016-02-08T13:56:57.303" UserId="2630" Text="I am implementing a simple Phong shader in OpenGL GLSL, and the test object is the utah teapot. However on the bottom I get a solid red circle, and on the top there is are sharp sectors that are coloured incorrectly.&#xD;&#xA;&#xD;&#xA;Is there any way to fix these issues? What would be the issue in the first place?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yn0z3.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/dlC2c.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4433" PostHistoryTypeId="1" PostId="2014" RevisionGUID="42c70fc7-ad24-495a-ae0a-6f0b5a399aa1" CreationDate="2016-02-08T13:56:57.303" UserId="2630" Text="Artefacts on top and bottom of utah teapot" ContentLicense="CC BY-SA 3.0" />
  <row Id="4434" PostHistoryTypeId="3" PostId="2014" RevisionGUID="42c70fc7-ad24-495a-ae0a-6f0b5a399aa1" CreationDate="2016-02-08T13:56:57.303" UserId="2630" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4439" PostHistoryTypeId="5" PostId="168" RevisionGUID="e63256ff-ddb9-4f8a-8806-a2fadf654d00" CreationDate="2016-02-09T06:19:09.250" UserId="310" Comment="Correct typo" Text="Assuming you mean a camera that rotates based on mouse movement:&#xD;&#xA;&#xD;&#xA;One way to implement it is to keep track of the camera position and its rotation in space. Spherical coordinates happen to be convenient for this, since you can represent the angles directly.&#xD;&#xA;&#xD;&#xA;[![Spherical Coordinates Image][1]][1]&#xD;&#xA;&#xD;&#xA;    float m_theta;&#xD;&#xA;    float m_phi;&#xD;&#xA;    float m_radius;&#xD;&#xA;    &#xD;&#xA;    float3 m_target;&#xD;&#xA;&#xD;&#xA;The camera is located at *P* which is defined by m_theta, m_phi, and m_radius. We can rotate and move freely wherever we want by changing those three values. However, we always look at, and rotate around, m_target. m_target is the local origin of the sphere. However, we are free to move this origin wherever we want in world space. &#xD;&#xA;&#xD;&#xA;There are three main camera functions:&#xD;&#xA;&#xD;&#xA;    void Rotate(float dTheta, float dPhi);&#xD;&#xA;    void Zoom(float distance);&#xD;&#xA;    void Pan(float dx, float dy);&#xD;&#xA;&#xD;&#xA;In their simplest forms, Rotate() and Zoom() are trivial. The just modify m_theta, m_phi, and m_radius respectively:&#xD;&#xA;&#xD;&#xA;    void Camera::Rotate(float dTheta, float dPhi) {&#xD;&#xA;    	m_theta += dTheta;&#xD;&#xA;    	m_phi += dPhi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Camera::Zoom(float distance) {&#xD;&#xA;    	m_radius -= distance;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Panning is a bit more complicated. A camera pan is defined as moving the camera to the left/right and/or up/down respective to the current camera view. The easiest way we can accomplish this is to convert our current camera view from spherical coordinates to cartesian coordinates. This will give us an *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;    void Camera::Pan(float dx, float dy) {&#xD;&#xA;    	float3 look = normalize(ToCartesian());&#xD;&#xA;    	float3 worldUp = float3(0.0f, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	float3 right = cross(look, worldUp);&#xD;&#xA;    	float3 up = cross(look, right);&#xD;&#xA;    &#xD;&#xA;    	m_target = m_target + (right * dx) + (up * dy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    inline float3 ToCartesian() {&#xD;&#xA;    	float x = m_radius * sinf(m_phi) * sinf(m_theta);&#xD;&#xA;    	float y = m_radius * cosf(m_phi);&#xD;&#xA;    	float z = m_radius * sinf(m_phi) * cosf(m_theta);&#xD;&#xA;    	float w = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return float3(x, y, z, w);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So, first, we convert our spherical coordinate system to cartesian to get our *look* vector. Next, we do the vector cross product with the world *up* vector, in order to get a *right* vector. This is a vector that points directly right of the camera view. Lastly, we do another vector cross product to get the camera *up* vector.&#xD;&#xA;&#xD;&#xA;To finish the pan, we move m_target along the *up* and *right* vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;One question you might be asking is: Why convert between cartesian and spherical all the time (you will also have to convert in order to create the View matrix). &#xD;&#xA;&#xD;&#xA;Good question. I too had this question and tried to exclusively use cartesian. You end up with problems with rotations. Since floating point operations are not exactly precise, multiple rotations end up accumulating errors, which corresponded to the camera slowly, and unintentionally rolling. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So, in the end, I stuck with spherical coordinates. In order to counter the extra calculations, I ended up caching the view matrix, and only calculate it when the camera moves.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last step is to *use* this Camera class. Just call the appropriate member function inside your app's MouseDown/Up/Scroll functions:&#xD;&#xA;&#xD;&#xA;    void MouseDown(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	m_mouseLastPos.x = x;&#xD;&#xA;    	m_mouseLastPos.y = y;&#xD;&#xA;    &#xD;&#xA;    	SetCapture(m_hwnd);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseUp(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	ReleaseCapture();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseMove(WPARAM buttonState, int x, int y) {&#xD;&#xA;    	if ((buttonState &amp; MK_LBUTTON) != 0) {&#xD;&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xD;&#xA;    			// Calculate the new phi and theta based on mouse position relative to where the user clicked&#xD;&#xA;    			float dPhi = ((float)(m_mouseLastPos.y - y) / 300);&#xD;&#xA;    			float dTheta = ((float)(m_mouseLastPos.x - x) / 300);&#xD;&#xA;    &#xD;&#xA;    			m_camera.Rotate(-dTheta, dPhi);&#xD;&#xA;    		}&#xD;&#xA;    	} else if ((buttonState &amp; MK_MBUTTON) != 0) {&#xD;&#xA;    		if (GetKeyState(VK_MENU) &amp; 0x8000) {&#xD;&#xA;    			float dx = ((float)(m_mouseLastPos.x - x));&#xD;&#xA;    			float dy = ((float)(m_mouseLastPos.y - y));&#xD;&#xA;    &#xD;&#xA;    			m_camera.Pan(-dx * m_cameraPanFactor, dy * m_cameraPanFactor);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	m_mouseLastPos.x = x;&#xD;&#xA;    	m_mouseLastPos.y = y;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void MouseWheel(int zDelta) {&#xD;&#xA;    	// Make each wheel dedent correspond to a size based on the scene&#xD;&#xA;    	m_camera.Zoom((float)zDelta * m_cameraScrollFactor);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The m_camera*Factor variables are just scale factors that change how quickly your camera rotates/pans/scrolls&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code I have above is a simplified pseudo-code version of the camera system I made for a side project: [camera.h](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.h) and [camera.cpp](https://github.com/RichieSams/thehalflingproject/blob/master/source/scene/camera.cpp). The camera tries to imitate the Maya camera system. The code is free and open source, so feel free to use it in your own project. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9kXOr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1OFpX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4440" PostHistoryTypeId="2" PostId="2016" RevisionGUID="3e6c1435-1c1c-47d0-8488-a6e0f6e10586" CreationDate="2016-02-09T07:58:32.120" UserId="2637" Text="I recently started to create a shadow mapping system in OpenTK.&#xD;&#xA;I ran into a problem: The depthtexture is always completly white -&gt; no depth. Even if the color from the shader is changed (I know it shouldn't effect anything.).&#xD;&#xA;Here is my shadow mapper class:&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    class ShadowMapper&#xD;&#xA;    {&#xD;&#xA;        static int frameBuffer = 0;&#xD;&#xA;        static int depthTexture;&#xD;&#xA;        static readonly int shadowMapResolution = 1024;&#xD;&#xA;        static ShadowShader shader;&#xD;&#xA;        public static void Init()&#xD;&#xA;        {&#xD;&#xA;            shader = new ShadowShader();&#xD;&#xA;&#xD;&#xA;            frameBuffer = GL.GenFramebuffer();&#xD;&#xA;            GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBuffer);&#xD;&#xA;            depthTexture = GL.GenTexture();&#xD;&#xA;            GL.BindTexture(TextureTarget.Texture2D, depthTexture);&#xD;&#xA;            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent16, shadowMapResolution, shadowMapResolution, 0, PixelFormat.DepthComponent, PixelType.Float, (IntPtr)null);&#xD;&#xA;            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);&#xD;&#xA;            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);&#xD;&#xA;            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);&#xD;&#xA;            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);&#xD;&#xA;&#xD;&#xA;            GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, depthTexture, 0);&#xD;&#xA;&#xD;&#xA;            GL.DrawBuffer(DrawBufferMode.None);&#xD;&#xA;            Console.WriteLine(GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) == FramebufferErrorCode.FramebufferComplete);&#xD;&#xA;            GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        public static void Render(Dictionary&lt;TexturedModel, List&lt;Entity&gt;&gt; entities, Light sun)&#xD;&#xA;        {&#xD;&#xA;            Matrix4 depthProjectionMatrix = Matrix4.CreateOrthographic(-10, 10, -10, 10);&#xD;&#xA;            Matrix4 depthViewMatrix = Matrix4.LookAt(sun.Position, sun.ToLookPosition, new Vector3(0, 1, 0));&#xD;&#xA;&#xD;&#xA;            GL.BindTexture(TextureTarget.Texture2D, 0);&#xD;&#xA;            GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBuffer);&#xD;&#xA;            GL.Viewport(0, 0, shadowMapResolution, shadowMapResolution);&#xD;&#xA;&#xD;&#xA;            GL.Enable(EnableCap.DepthTest);&#xD;&#xA;            GL.Clear(ClearBufferMask.DepthBufferBit);&#xD;&#xA;            shader.Start();&#xD;&#xA;            foreach (TexturedModel model in entities.Keys)&#xD;&#xA;            {&#xD;&#xA;                RawModel rawModel = model.Model;&#xD;&#xA;                GL.BindVertexArray(rawModel.VaoID);&#xD;&#xA;                GL.EnableVertexAttribArray(0);&#xD;&#xA;                foreach (Entity entity in entities[model])&#xD;&#xA;                {&#xD;&#xA;                    Matrix4 depthModelMatrix = Maths.CreateTransformationMatrix(entity.Position, entity.RotationX, entity.RotationY, entity.RotationZ, entity.Scale);&#xD;&#xA;                    Matrix4 depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;&#xD;&#xA;                    shader.LoadMvpMatrix(depthMVP);&#xD;&#xA;                    &#xD;&#xA;                    GL.DrawElements(PrimitiveType.Triangles, rawModel.VertexCount, DrawElementsType.UnsignedInt, 0);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            GL.DisableVertexAttribArray(0);&#xD;&#xA;            GL.BindVertexArray(0);&#xD;&#xA;            GL.Disable(EnableCap.DepthTest);&#xD;&#xA;            shader.Stop();&#xD;&#xA;            GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);&#xD;&#xA;            GL.Viewport(0, 0, Window.Instance.Width, Window.Instance.Height);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        public static int DepthTexture&#xD;&#xA;        {&#xD;&#xA;            get&#xD;&#xA;            {&#xD;&#xA;                return depthTexture;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And my vertex/fragment shaders:&#xD;&#xA; &#xD;&#xA;     Vertex Shader:&#xD;&#xA;     #version 330 core&#xD;&#xA;&#xD;&#xA;    // Input vertex data, different for all executions of this shader.&#xD;&#xA;    in vec3 vertexPosition_modelspace;&#xD;&#xA;&#xD;&#xA;    // Values that stay constant for the whole mesh.&#xD;&#xA;&#xD;&#xA;    uniform mat4 depthMVP;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;    gl_Position =  depthMVP * vec4(vertexPosition_modelspace,1);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Fragment Shader:&#xD;&#xA;     #version 330 core&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;     // Ouput data&#xD;&#xA;&#xD;&#xA;     out float fragmentdepth;&#xD;&#xA;     out vec4 out_colour;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;     void main(){&#xD;&#xA;&#xD;&#xA;     // Not really needed, OpenGL does it anyway&#xD;&#xA;&#xD;&#xA;     fragmentdepth = gl_FragCoord.z;&#xD;&#xA;	 out_colour = vec4(1.0, 0.0, 0.0, 0.0);&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Any help?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4441" PostHistoryTypeId="1" PostId="2016" RevisionGUID="3e6c1435-1c1c-47d0-8488-a6e0f6e10586" CreationDate="2016-02-09T07:58:32.120" UserId="2637" Text="Shadow Mapping Errors" ContentLicense="CC BY-SA 3.0" />
  <row Id="4442" PostHistoryTypeId="3" PostId="2016" RevisionGUID="3e6c1435-1c1c-47d0-8488-a6e0f6e10586" CreationDate="2016-02-09T07:58:32.120" UserId="2637" Text="|opengl|shader|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4443" PostHistoryTypeId="2" PostId="2017" RevisionGUID="5b321fc2-a95a-4e13-9227-13be52e25022" CreationDate="2016-02-09T09:34:49.827" UserId="209" Text="I'm fairly certain your problem lies in not handling so-called *degenerate* Bezier patches correctly, in particular (as [Joojaa](https://computergraphics.stackexchange.com/users/38/joojaa) noted), the computation of the surface normal.  I say *&quot;so-called degenerate&quot;* because, geometrically, the surfaces are often perfectly well behaved. It's just that some assumptions people frequently make regarding the parametric equations may not hold.&#xD;&#xA;&#xD;&#xA;Books such as Gerald Farin's, snappily titled, *&quot;Curves and Surfaces for CAGD. A Practical Guide&quot;* will give more details, but I'll try to summarise two simple cases. Now assuming your Bezier is defined as $\bar{B}(u,v)$ the usual two causes of problems are:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Zero derivatives: ###&#xD;&#xA;A very common situation is where one of the 1st partial derivatives at the location is zero:&#xD;&#xA;To compute the normal at $(0,0)$ one normally (pardon the pun) computes the two derivatives,&#xD;&#xA;&#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(0,0)$ and $\frac{\partial }{\partial u}\bar{B}(0,0)$&#xD;&#xA;&#xD;&#xA;two obtain two tangents and then take the cross product.&#xD;&#xA;&#xD;&#xA;In the case of the tops and bottoms of the teapot, one whole edge of (bicubic) Bezier patch has been collapsed to a point, i.e. all 4 control points are the same, and thus, say &#xD;&#xA;&#xD;&#xA; $\bar{B}(0,v)==\bar{B}(1,v)$   and   $\frac{\partial }{\partial u}\bar{B}(0,0)=\bar{0}$. &#xD;&#xA;&#xD;&#xA;The surface, however, is completely well behaved so you can simply choose another derivative that starts at that collapsed point. In this case, say, &#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(1,0)$&#xD;&#xA;&#xD;&#xA;for the second tangent.&#xD;&#xA;&#xD;&#xA;Having said this, you *still* have to check that your first derivatives are not zero for another reason (e.g coincident control points), in which case, you can fall back (thanks to L'Hopital's rule) on the second (or if that's zero, even the third!) derivative(s) to obtain valid tangents.&#xD;&#xA;&#xD;&#xA;### Parallel tangents: ###&#xD;&#xA;Another similar problem can arise if your two tangents, are *parallel*. - Farin has a good example in his book. &#xD;&#xA;&#xD;&#xA;In this case, I *think* you may need to look at using something like $\frac{\partial^2 }{\partial u \partial v}\bar{B}$ or, possibly, just fall back to using a small UV offset to approximate a vector.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4444" PostHistoryTypeId="5" PostId="2017" RevisionGUID="6cb8f293-fac5-427f-bde0-f505108ee21c" CreationDate="2016-02-09T10:22:28.977" UserId="209" Comment="added 7 characters in body" Text="I'm fairly certain your problem lies in not handling so-called *degenerate* Bezier patches correctly, in particular (as [Joojaa](https://computergraphics.stackexchange.com/users/38/joojaa) noted), the computation of the surface normal.  I say *&quot;so-called degenerate&quot;* because, geometrically, the surfaces are often perfectly well behaved. It's just that some assumptions people frequently make regarding the parametric equations may not hold.&#xD;&#xA;&#xD;&#xA;Books such as Gerald Farin's, snappily titled, *&quot;Curves and Surfaces for CAGD. A Practical Guide&quot;* will give more details, but I'll try to summarise two simple cases. Now assuming your Bezier is defined as $\bar{B}(u,v)$ the usual two causes of problems are:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Zero derivatives: ###&#xD;&#xA;A very common situation is where one of the 1st partial derivatives at the location is zero:&#xD;&#xA;To compute the normal at $(0,0)$ one normally (pardon the pun) computes the two derivatives,&#xD;&#xA;&#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(0,0)$ and $\frac{\partial }{\partial u}\bar{B}(0,0)$&#xD;&#xA;&#xD;&#xA;two obtain two tangents and then take the cross product.&#xD;&#xA;&#xD;&#xA;In the case of the tops and bottoms of the teapot, one whole edge of (bicubic) Bezier patch has been collapsed to a point, i.e. all 4 control points are the same, and thus, say &#xD;&#xA;&#xD;&#xA; $\bar{B}(0,v)==\bar{B}(1,v)$   and   $\frac{\partial }{\partial u}\bar{B}(0,0)=\bar{0}$. &#xD;&#xA;&#xD;&#xA;The surface, however, is completely well behaved so you can simply choose another derivative that starts at that collapsed point. In this case, say, &#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(1,0)$&#xD;&#xA;&#xD;&#xA;for the second tangent.&#xD;&#xA;&#xD;&#xA;Having said this, you *still* have to check that your first derivatives are not zero for another reason (e.g 2 or 3 coincident control points), in which case, you can fall back (thanks to L'Hopital's rule) on the second (or if that's zero, even the third!) derivative(s) to obtain valid tangents.&#xD;&#xA;&#xD;&#xA;### Parallel tangents: ###&#xD;&#xA;Another similar problem can arise if your two tangents, are *parallel*. - Farin has a good example in his book. &#xD;&#xA;&#xD;&#xA;In this case, I *think* you may need to look at using something like $\frac{\partial^2 }{\partial u \partial v}\bar{B}$ or, possibly, just fall back to using a small UV offset to approximate a vector.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4445" PostHistoryTypeId="5" PostId="2017" RevisionGUID="9bc3e6b0-3ab9-41c5-b3e6-170cd43a36b4" CreationDate="2016-02-09T10:37:30.387" UserId="209" Comment="Fixed a grammatical error and made a comment about scaled derivatives being equivalent." Text="I'm fairly certain your problem lies in not handling so-called *degenerate* Bezier patches correctly, in particular (as [Joojaa](https://computergraphics.stackexchange.com/users/38/joojaa) noted), the computation of the surface normal.  I say *&quot;so-called degenerate&quot;* because, geometrically, the surfaces are often perfectly well behaved. It's just that some assumptions people frequently make regarding the parametric equations may not hold.&#xD;&#xA;&#xD;&#xA;Books such as Gerald Farin's, snappily titled, *&quot;Curves and Surfaces for CAGD. A Practical Guide&quot;* will give more details, but I'll try to summarise two simple cases. Now assuming your Bezier is defined as $\bar{B}(u,v)$ the usual two causes of problems are:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Zero derivatives: ###&#xD;&#xA;A very common situation is where one of the 1st partial derivatives at the location is zero:&#xD;&#xA;To compute the normal at $(0,0)$ one normally (pardon the pun) computes the two derivatives,&#xD;&#xA;&#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(0,0)$ and $\frac{\partial }{\partial u}\bar{B}(0,0)$&#xD;&#xA;&#xD;&#xA; *or scaled versions thereof*, to obtain two tangents and then take the cross product.&#xD;&#xA;&#xD;&#xA;In the case of the tops and bottoms of the teapot, one whole edge of a number of the (bicubic) Bezier patches has been collapsed to a point, i.e. all 4 control points are the same, and thus, say &#xD;&#xA;&#xD;&#xA; $\bar{B}(0,v)==\bar{B}(1,v)$   and   $\frac{\partial }{\partial u}\bar{B}(0,0)=\bar{0}$. &#xD;&#xA;&#xD;&#xA;The surface, however, is completely well behaved so you can simply choose another derivative that starts at that collapsed point. In this case, say, &#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(1,0)$&#xD;&#xA;&#xD;&#xA;for the second tangent.&#xD;&#xA;&#xD;&#xA;Having said this, you *still* have to check that your first derivatives are not zero for another reason (e.g 2 or 3 coincident control points), in which case, you can fall back (thanks to L'Hopital's rule) on the second (or if that's zero, even the third!) derivative(s) to obtain valid tangents.&#xD;&#xA;&#xD;&#xA;### Parallel tangents: ###&#xD;&#xA;Another similar problem can arise if your two tangents, are *parallel*. - Farin has a good example in his book. &#xD;&#xA;&#xD;&#xA;In this case, I *think* you may need to look at using something like $\frac{\partial^2 }{\partial u \partial v}\bar{B}$ or, possibly, just fall back to using a small UV offset to approximate a vector.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4446" PostHistoryTypeId="2" PostId="2018" RevisionGUID="04dc026d-d64f-4cfa-8a93-c3c47c8c2e1e" CreationDate="2016-02-09T12:07:56.817" UserId="2641" Text="In recent games I have noticed something called Tessellation, Turning the thing ON destroys my frame rate.&#xD;&#xA;&#xD;&#xA;I have noticed that it when turned on it looks like Anti - Aliasing.&#xD;&#xA;&#xD;&#xA;Can someone give me further information on what exactly the GPU does." ContentLicense="CC BY-SA 3.0" />
  <row Id="4447" PostHistoryTypeId="1" PostId="2018" RevisionGUID="04dc026d-d64f-4cfa-8a93-c3c47c8c2e1e" CreationDate="2016-02-09T12:07:56.817" UserId="2641" Text="What is Tessellation in computer graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="4448" PostHistoryTypeId="3" PostId="2018" RevisionGUID="04dc026d-d64f-4cfa-8a93-c3c47c8c2e1e" CreationDate="2016-02-09T12:07:56.817" UserId="2641" Text="|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4449" PostHistoryTypeId="2" PostId="2019" RevisionGUID="11bccf72-c66f-4c1a-a604-7c71ea95f4ef" CreationDate="2016-02-09T12:59:18.023" UserId="137" Text="It activate 3 stages in the pipeline.&#xD;&#xA;&#xD;&#xA;The first is the tessellation control shader (hull shader in D3D) which looks at a set of vertices and then outputs how it should be divided up in separate triangles.&#xD;&#xA;&#xD;&#xA;The second is a fixed function stage that will generate the requested triangles.&#xD;&#xA;&#xD;&#xA;The third stage the tessellation evalutation shader (domain shader in D3D) which is run per generated vertex and will put it in the correct place based on the barycentric coordinates of the generated vertex. &#xD;&#xA;&#xD;&#xA;This is used for level of detail to generate more triangles when the mesh is closer to the camera." ContentLicense="CC BY-SA 3.0" />
  <row Id="4450" PostHistoryTypeId="2" PostId="2020" RevisionGUID="01d02110-1de2-4377-992a-670b881595bb" CreationDate="2016-02-09T13:14:58.337" UserId="273" Text="Tesselation is a technique that allows you to generate primitives (triangles, lines, points and such) on the graphics-card.&#xD;&#xA;&#xD;&#xA;This allows you to load a relatively coarse mesh on your graphics card, generate more vertices and triangles dynamically and then have a mesh on the screen that looks much smoother.&#xD;&#xA;&#xD;&#xA;Most of the time this tesselation is done anew in each single frame and this could be the reason that your frame-rate drops once you enable this.&#xD;&#xA;&#xD;&#xA;Tesselation is done in multiple stages, and it is done AFTER the vertex shader. Tesselation Control, Tesselation, and Tesselation Evaluation.&#xD;&#xA;The first and the last stage is programmable, the actual tesselation is done by the hardware in a fixed function stage.&#xD;&#xA;&#xD;&#xA;In the Tesselation Control shader you get to set how many subdivisions and what kind of divisions you want to make.&#xD;&#xA;&#xD;&#xA;The Tesselation generates the new points for you based on your previously set preferences.&#xD;&#xA;&#xD;&#xA;Lastly for each newly generated vertex the tesselation evaluation shader is called. In this shader the type of primitive you want to generate is set and how the vertices are spaced and many other things. This shader can also be used to do all sorts of per-vertex calculations just like a vertex shader. It is guaranteed to be called at least once for each generated vertex.&#xD;&#xA;&#xD;&#xA;Additionally, and this is really an addition and not part of the pure tesselation, a geometry shader could be used to further work on these generated primitives." ContentLicense="CC BY-SA 3.0" />
  <row Id="4452" PostHistoryTypeId="5" PostId="2020" RevisionGUID="c77438a6-73c7-4d74-90bb-63502806be2b" CreationDate="2016-02-09T15:26:57.463" UserId="310" Comment="Add images, and fix some grammar" Text="Tesselation is a technique that allows you to generate primitives (triangles, lines, points and such) on the graphics-card. Specifically, it lets you repeatedly subdivide the current geometry into a finer mesh.&#xD;&#xA;&#xD;&#xA;This allows you to load a relatively coarse mesh on your graphics card, generate more vertices and triangles dynamically and then have a mesh on the screen that looks much smoother.&#xD;&#xA;&#xD;&#xA;[![Tessellation example][1]][1]&#xD;&#xA;&#xD;&#xA;Most of the time this tesselation is done anew in each single frame and this could be the reason that your frame-rate drops once you enable this.&#xD;&#xA;&#xD;&#xA;Tesselation is done in multiple stages, and it is done AFTER the vertex shader. &#xD;&#xA;&#xD;&#xA;[![Stages][2]][2]&#xD;&#xA;&#xD;&#xA;The terms for each stage varies based on the API. In DirectX, it is the Hull Shader, Hardware Tessellation, and the Domain Shader. In OpenGL, they are called the Tessellation Control Shader, Hardware Tessellation, and the Tessellation Evaluation Shader.&#xD;&#xA;&#xD;&#xA;The first and the last stage is programmable, the actual tesselation is done by the hardware in a fixed function stage.&#xD;&#xA;&#xD;&#xA;In the Tesselation Control shader you set the type and number of subdivisions.&#xD;&#xA;&#xD;&#xA;Then the hardware tessellator divides the geometry according to the Control Shader.&#xD;&#xA;&#xD;&#xA;Lastly, the Tessellation Evaluation Shader is called for each newly generated vertex. In this shader, you set the type of primitive you want to generate and how the vertices are spaced and many other things. This shader can also be used to do all sorts of per-vertex calculations just like a vertex shader. It is guaranteed to be called at least once for each generated vertex.&#xD;&#xA;&#xD;&#xA;If you want to do any further work on the primitives, you can add a Geometry shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uT6do.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/31tTU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4453" PostHistoryTypeId="24" PostId="2020" RevisionGUID="c77438a6-73c7-4d74-90bb-63502806be2b" CreationDate="2016-02-09T15:26:57.463" Comment="Proposed by 310 approved by 273 edit id of 123" ContentLicense="CC BY-SA 3.0" />
  <row Id="4454" PostHistoryTypeId="2" PostId="2021" RevisionGUID="453cc9f2-bf9b-4f63-97f7-025703414278" CreationDate="2016-02-09T17:21:34.743" UserId="2645" Text="Completely stuck on how to do this. Yes, it is a homework problem, but its the first we've had in the class so not too familiar with graphics. Also, seeing as its homework, please don't just give the answer, just some pointers in the right direction would be great.&#xD;&#xA;&#xD;&#xA;I've tried to do it as a triangle fan, and as a polygon but that just ends up in really weird shapes." ContentLicense="CC BY-SA 3.0" />
  <row Id="4455" PostHistoryTypeId="1" PostId="2021" RevisionGUID="453cc9f2-bf9b-4f63-97f7-025703414278" CreationDate="2016-02-09T17:21:34.743" UserId="2645" Text="OpenGL with SFML, create an n-pointed star?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4456" PostHistoryTypeId="3" PostId="2021" RevisionGUID="453cc9f2-bf9b-4f63-97f7-025703414278" CreationDate="2016-02-09T17:21:34.743" UserId="2645" Text="|opengl|c++|mathematics|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4460" PostHistoryTypeId="2" PostId="2023" RevisionGUID="7e307297-860b-4e01-8c6b-b7815e6f6796" CreationDate="2016-02-09T18:48:52.057" UserId="2646" Text="I'm attempting to model a simple graphics pipeline - using Matlab at the moment as a modelling tool to get the transformations correct. I appreciate there are software tools that would make this easier - but I'm looking to understand the maths behind it and hence am looking to mostly use simple functions &amp; matrices that I'm learning from a [book][1] (very retro!).&#xD;&#xA;&#xD;&#xA;I've successfully got through the stages of defining simple objects and converting them into a universal world space - but have come unstuck with the mathematics required to convert an object into view space and the back face culling.&#xD;&#xA;&#xD;&#xA;I believe my view space transformation is correct because when I plot the composite vectors they appear correct - but - when I do the back-face culling, it seems to fail to remove the correct triangles. Given that it depends only on two things, the line-of-sight vector and face normals, I can't work out what I'm doing wrong.&#xD;&#xA;&#xD;&#xA;When defining the triangles in local definition space, I did it so that all the normals pointed outwards. I've put my results into the image below[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My questions are;&#xD;&#xA;- Have I gone wrong, or are my expectations incorrect?&#xD;&#xA;- If so where, and how do I fix?&#xD;&#xA;&#xD;&#xA;Thanks very much for any/all help.&#xD;&#xA;&#xD;&#xA;David&#xD;&#xA;&#xD;&#xA;============PROGRESS=================&#xD;&#xA;&#xD;&#xA;Possibly something to do with handedness of the faces being changed?&#xD;&#xA;&#xD;&#xA;(I'm very sorry for the incorrect syntax highlighting...I couldn't get it to work correctly)&#xD;&#xA;&#xD;&#xA;    clear; clc; close all;&#xD;&#xA;    %======Create World Space (hard-coded values for demo) ===========&#xD;&#xA;    ws_vtx = [0,2,0,2,1,0.5,1.5,0.5,1.5,0.5,1.5,0.5,1.5;&#xD;&#xA;        0,0,0,0,-2,0,0,2,2,0,0,2,2;&#xD;&#xA;        0,0,2,2,1,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5];&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    %==============Plot World Space==========================&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    for i = 1:length(ws_vtx) %Number vertices&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',12, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx', 'Facecolor', 'none')&#xD;&#xA;    grid on; hold on; a = 4; axis([-a,a,-a,a,-a,a]);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %==================Transform into Camera Space===================&#xD;&#xA;    focus = [1.5,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Coordinates of camera&#xD;&#xA;    position = [Cx, Cy, Cz];&#xD;&#xA;    Vspec = [0,0,1]; %Specified up/vertical direction&#xD;&#xA;    &#xD;&#xA;    %Calculations taken from http://tutorial.math.lamar.edu/Classes/CalcIII/SphericalCoords.aspx&#xD;&#xA;    vector = focus - position;&#xD;&#xA;    p = sqrt(vector(1)^2 + vector(2)^2 + vector(3)^2); %Total magnitude of vector&#xD;&#xA;    r = sqrt(vector(1)^2 + vector(2)^2);%Magnitude of flat (x &amp; y) components&#xD;&#xA;    &#xD;&#xA;    az = atan(vector(2)/vector(1)); % Azimuth: X = rsin(azimuth)&#xD;&#xA;    if(vector(1) &lt; 0) %Left hand side&#xD;&#xA;        if (vector(2) &gt; 0) %TL quad&#xD;&#xA;            az = az + pi;&#xD;&#xA;        else&#xD;&#xA;            az = az - pi;%BL quad&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    el = asin(r/p); %Elevation: r = pcos(elevation)&#xD;&#xA;    if(vector(3) &lt; 0) %If negative z, negative elevation&#xD;&#xA;        el = pi-el;&#xD;&#xA;    end;&#xD;&#xA;    &#xD;&#xA;    %Normal view from camera to object (direction of point)%&#xD;&#xA;    N = [sin(el)*cos(az), sin(el)*sin(az), cos(el)];&#xD;&#xA;    V = Vspec - cross(cross(Vspec,N),N); %Create new &quot;up&quot; direction&#xD;&#xA;    U = cross(N,V);&#xD;&#xA;    &#xD;&#xA;    R= [U(1),U(2),U(3),0; % U is direction of camera space x axis&#xD;&#xA;        V(1),V(2),V(3),0; % V is direction of camera space y axis&#xD;&#xA;        N(1),N(2),N(3),0; %View from Camera to object&#xD;&#xA;        0 , 0, 0,1];&#xD;&#xA;    Tr =[1,0,0,-Cx; % Translation matrix from camera to origin&#xD;&#xA;        0,1,0,-Cy;&#xD;&#xA;        0,0,1,-Cz;&#xD;&#xA;        0,0,0,1];&#xD;&#xA;    T = R*Tr; %Viewspace transform = rotation * translation&#xD;&#xA;    %====Plot the camera vectors into world space==========&#xD;&#xA;    scatter3(Cx,Cy,Cz,'s') %Plot the camera position&#xD;&#xA;    plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)]);&#xD;&#xA;    plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)]);&#xD;&#xA;    plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)]);&#xD;&#xA;    %=============Transform into view space ===============&#xD;&#xA;    ws_vtx = T*vertcat(ws_vtx,(ones(1, length(ws_vtx))));&#xD;&#xA;    ws_vtx = ws_vtx(1:3,:); %Remove homogenous dimension&#xD;&#xA;    %=========Get array of normals for elimination==============&#xD;&#xA;    norm_fcs = zeros(3,length(ws_fcs)); &#xD;&#xA;        for i = 1:length(ws_fcs); %For each triangle&#xD;&#xA;            points = zeros(3,3); %Contains 1 triangle&#xD;&#xA;            points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i)); %Get points for triangle&#xD;&#xA;    &#xD;&#xA;            U = points(:,2) - points(:,1); %Get two non-parallel vectors&#xD;&#xA;            V = points(:,3) - points(:,1);&#xD;&#xA;            norm_fcs(:,i) = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1&#xD;&#xA;        end&#xD;&#xA;    %====================BackFace Elimination===============&#xD;&#xA;    null_vals = 0;&#xD;&#xA;    for i = 1:length(ws_fcs) %Zero out faces that arent visible&#xD;&#xA;        if dot(norm_fcs(:,i), N) &gt; 0 %Dot product line of sight &amp; normal of faces&#xD;&#xA;            ws_fcs(:,i) = [0;0;0]; %If &lt; 0, not visibile and zero out entry&#xD;&#xA;            null_vals = null_vals + 1; %And increment counter&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    ws_fcs_cat = zeros(3, length(ws_fcs) - null_vals); %Create new array&#xD;&#xA;    null_vals = 0;&#xD;&#xA;    for i = 1:length(ws_fcs) %Create new faces array of visible faces only&#xD;&#xA;        if norm(ws_fcs(:,i)) == 0&#xD;&#xA;            null_vals = null_vals + 1;&#xD;&#xA;        else&#xD;&#xA;            ws_fcs_cat(:,i - null_vals) = ws_fcs(:,i);&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    ws_fcs = ws_fcs_cat;&#xD;&#xA;    figure()&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    for i = 1:length(ws_vtx) %Number vertices&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',12, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx', 'Facecolor', 'none') %Link arrays of points to vertices&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.amazon.co.uk/3D-Computer-Graphics-Alan-Watt/dp/0201398559&#xD;&#xA;  [2]: https://i.stack.imgur.com/XeAiI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4461" PostHistoryTypeId="1" PostId="2023" RevisionGUID="7e307297-860b-4e01-8c6b-b7815e6f6796" CreationDate="2016-02-09T18:48:52.057" UserId="2646" Text="Graphics Pipeline: Viewspace &amp; Back face culling incorrectly" ContentLicense="CC BY-SA 3.0" />
  <row Id="4462" PostHistoryTypeId="3" PostId="2023" RevisionGUID="7e307297-860b-4e01-8c6b-b7815e6f6796" CreationDate="2016-02-09T18:48:52.057" UserId="2646" Text="|transformations|3d|vector-graphics|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4463" PostHistoryTypeId="2" PostId="2024" RevisionGUID="31fa01d3-9295-4058-b357-fcd6705c35ea" CreationDate="2016-02-09T19:57:51.373" UserId="273" Text="A simple way would be to think about how you can decompose your star into triangles.&#xD;&#xA;&#xD;&#xA;And then just draw these triangles. Not as a triangle-fan since those may be a bit strange to use.&#xD;&#xA;&#xD;&#xA;Since triangles are one of the most basic and standard ways to draw all kinds of meshes and shapes (every polygon can be triangulated as far as I know), I suggest du don't use the polygon draw as a beginner. Begin with the basic stuff everyone uses." ContentLicense="CC BY-SA 3.0" />
  <row Id="4466" PostHistoryTypeId="2" PostId="2026" RevisionGUID="9dda66c7-1852-494b-a325-9df58cf88030" CreationDate="2016-02-09T21:44:18.417" UserId="2651" Text="Try starting at the origin, then dividing 360 degrees by n to find some useful angles.&#xD;&#xA;I hope this terrible drawing will help you to find a solution!&#xD;&#xA;(this method only uses triangles)&#xD;&#xA;&#xD;&#xA;[![Break it up][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v2iox.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4467" PostHistoryTypeId="5" PostId="2020" RevisionGUID="58389824-db8b-4adb-8341-8afcea466d8e" CreationDate="2016-02-09T23:53:36.433" UserId="273" Comment="added 11 characters in body" Text="Tesselation is a technique that allows you to generate primitives (triangles, lines, points and such) on the graphics-card. Specifically, it lets you repeatedly subdivide the current geometry into a finer mesh.&#xD;&#xA;&#xD;&#xA;This allows you to load a relatively coarse mesh on your graphics card, generate more vertices and triangles dynamically and then have a mesh on the screen that looks much smoother.&#xD;&#xA;&#xD;&#xA;[![Tessellation example][1]][1]&#xD;&#xA;&#xD;&#xA;Most of the time this tesselation is done anew in each single frame and this could be the reason that your frame-rate drops once you enable this.&#xD;&#xA;&#xD;&#xA;Tesselation is done in multiple stages, and it is done AFTER the vertex shader. &#xD;&#xA;&#xD;&#xA;[![Stages][2]][2]&#xD;&#xA;&#xD;&#xA;The terms for each stage varies based on the API. In DirectX, it is the Hull Shader, Hardware Tessellation, and the Domain Shader. In OpenGL, they are called the Tessellation Control Shader, Tesselation Primitive Generation, and the Tessellation Evaluation Shader.&#xD;&#xA;&#xD;&#xA;The first and the last stage is programmable, the actual tesselation is done by the hardware in a fixed function stage.&#xD;&#xA;&#xD;&#xA;In the Tesselation Control shader you set the type and number of subdivisions.&#xD;&#xA;&#xD;&#xA;Then the hardware tessellator divides the geometry according to the Control Shader.&#xD;&#xA;&#xD;&#xA;Lastly, the Tessellation Evaluation Shader is called for each newly generated vertex. In this shader, you set the type of primitive you want to generate and how the vertices are spaced and many other things. This shader can also be used to do all sorts of per-vertex calculations just like a vertex shader. It is guaranteed to be called at least once for each generated vertex.&#xD;&#xA;&#xD;&#xA;If you want to do any further work on the primitives, you can add a Geometry shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uT6do.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/31tTU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4473" PostHistoryTypeId="5" PostId="2023" RevisionGUID="ddf6e6f1-c6ec-4a03-a1c0-9a4c4094537b" CreationDate="2016-02-10T04:01:31.950" UserId="231" Comment="Minor tidying" Text="I'm attempting to model a simple graphics pipeline - using Matlab at the moment as a modelling tool to get the transformations correct. I appreciate there are software tools that would make this easier - but I'm looking to understand the maths behind it and hence am looking to mostly use simple functions &amp; matrices that I'm learning from a [book][1] (very retro!).&#xD;&#xA;&#xD;&#xA;I've successfully got through the stages of defining simple objects and converting them into a universal world space - but have come unstuck with the mathematics required to convert an object into view space and the back face culling.&#xD;&#xA;&#xD;&#xA;I believe my view space transformation is correct because when I plot the composite vectors they appear correct - but - when I do the back-face culling, it seems to fail to remove the correct triangles. Given that it depends only on two things, the line-of-sight vector and face normals, I can't work out what I'm doing wrong.&#xD;&#xA;&#xD;&#xA;When defining the triangles in local definition space, I did it so that all the normals pointed outwards. I've put my results into the image below&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;- Have I gone wrong, or are my expectations incorrect?&#xD;&#xA;- If so where, and how do I fix?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Progress&#xD;&#xA;&#xD;&#xA;Possibly something to do with handedness of the faces being changed?&#xD;&#xA;&#xD;&#xA;    clear; clc; close all;&#xD;&#xA;    %======Create World Space (hard-coded values for demo) ===========&#xD;&#xA;    ws_vtx = [0,2,0,2,1,0.5,1.5,0.5,1.5,0.5,1.5,0.5,1.5;&#xD;&#xA;        0,0,0,0,-2,0,0,2,2,0,0,2,2;&#xD;&#xA;        0,0,2,2,1,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5];&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    %==============Plot World Space==========================&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    for i = 1:length(ws_vtx) %Number vertices&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',12, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx', 'Facecolor', 'none')&#xD;&#xA;    grid on; hold on; a = 4; axis([-a,a,-a,a,-a,a]);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %==================Transform into Camera Space===================&#xD;&#xA;    focus = [1.5,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Coordinates of camera&#xD;&#xA;    position = [Cx, Cy, Cz];&#xD;&#xA;    Vspec = [0,0,1]; %Specified up/vertical direction&#xD;&#xA;    &#xD;&#xA;    %Calculations taken from http://tutorial.math.lamar.edu/Classes/CalcIII/SphericalCoords.aspx&#xD;&#xA;    vector = focus - position;&#xD;&#xA;    p = sqrt(vector(1)^2 + vector(2)^2 + vector(3)^2); %Total magnitude of vector&#xD;&#xA;    r = sqrt(vector(1)^2 + vector(2)^2);%Magnitude of flat (x &amp; y) components&#xD;&#xA;    &#xD;&#xA;    az = atan(vector(2)/vector(1)); % Azimuth: X = rsin(azimuth)&#xD;&#xA;    if(vector(1) &lt; 0) %Left hand side&#xD;&#xA;        if (vector(2) &gt; 0) %TL quad&#xD;&#xA;            az = az + pi;&#xD;&#xA;        else&#xD;&#xA;            az = az - pi;%BL quad&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    el = asin(r/p); %Elevation: r = pcos(elevation)&#xD;&#xA;    if(vector(3) &lt; 0) %If negative z, negative elevation&#xD;&#xA;        el = pi-el;&#xD;&#xA;    end;&#xD;&#xA;    &#xD;&#xA;    %Normal view from camera to object (direction of point)%&#xD;&#xA;    N = [sin(el)*cos(az), sin(el)*sin(az), cos(el)];&#xD;&#xA;    V = Vspec - cross(cross(Vspec,N),N); %Create new &quot;up&quot; direction&#xD;&#xA;    U = cross(N,V);&#xD;&#xA;    &#xD;&#xA;    R= [U(1),U(2),U(3),0; % U is direction of camera space x axis&#xD;&#xA;        V(1),V(2),V(3),0; % V is direction of camera space y axis&#xD;&#xA;        N(1),N(2),N(3),0; %View from Camera to object&#xD;&#xA;        0 , 0, 0,1];&#xD;&#xA;    Tr =[1,0,0,-Cx; % Translation matrix from camera to origin&#xD;&#xA;        0,1,0,-Cy;&#xD;&#xA;        0,0,1,-Cz;&#xD;&#xA;        0,0,0,1];&#xD;&#xA;    T = R*Tr; %Viewspace transform = rotation * translation&#xD;&#xA;    %====Plot the camera vectors into world space==========&#xD;&#xA;    scatter3(Cx,Cy,Cz,'s') %Plot the camera position&#xD;&#xA;    plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)]);&#xD;&#xA;    plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)]);&#xD;&#xA;    plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)]);&#xD;&#xA;    %=============Transform into view space ===============&#xD;&#xA;    ws_vtx = T*vertcat(ws_vtx,(ones(1, length(ws_vtx))));&#xD;&#xA;    ws_vtx = ws_vtx(1:3,:); %Remove homogenous dimension&#xD;&#xA;    %=========Get array of normals for elimination==============&#xD;&#xA;    norm_fcs = zeros(3,length(ws_fcs)); &#xD;&#xA;        for i = 1:length(ws_fcs); %For each triangle&#xD;&#xA;            points = zeros(3,3); %Contains 1 triangle&#xD;&#xA;            points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i)); %Get points for triangle&#xD;&#xA;    &#xD;&#xA;            U = points(:,2) - points(:,1); %Get two non-parallel vectors&#xD;&#xA;            V = points(:,3) - points(:,1);&#xD;&#xA;            norm_fcs(:,i) = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1&#xD;&#xA;        end&#xD;&#xA;    %====================BackFace Elimination===============&#xD;&#xA;    null_vals = 0;&#xD;&#xA;    for i = 1:length(ws_fcs) %Zero out faces that arent visible&#xD;&#xA;        if dot(norm_fcs(:,i), N) &gt; 0 %Dot product line of sight &amp; normal of faces&#xD;&#xA;            ws_fcs(:,i) = [0;0;0]; %If &lt; 0, not visibile and zero out entry&#xD;&#xA;            null_vals = null_vals + 1; %And increment counter&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    ws_fcs_cat = zeros(3, length(ws_fcs) - null_vals); %Create new array&#xD;&#xA;    null_vals = 0;&#xD;&#xA;    for i = 1:length(ws_fcs) %Create new faces array of visible faces only&#xD;&#xA;        if norm(ws_fcs(:,i)) == 0&#xD;&#xA;            null_vals = null_vals + 1;&#xD;&#xA;        else&#xD;&#xA;            ws_fcs_cat(:,i - null_vals) = ws_fcs(:,i);&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    ws_fcs = ws_fcs_cat;&#xD;&#xA;    figure()&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    for i = 1:length(ws_vtx) %Number vertices&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',12, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx', 'Facecolor', 'none') %Link arrays of points to vertices&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.amazon.co.uk/3D-Computer-Graphics-Alan-Watt/dp/0201398559&#xD;&#xA;  [2]: https://i.stack.imgur.com/XeAiI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4474" PostHistoryTypeId="5" PostId="2023" RevisionGUID="471a1484-74f6-4e02-ae54-8a54edc15ce9" CreationDate="2016-02-10T12:41:02.113" UserId="2646" Comment="Add code to show normals of polygons at each stage" Text="I'm attempting to model a simple graphics pipeline - using Matlab at the moment as a modelling tool to get the transformations correct. I appreciate there are software tools that would make this easier - but I'm looking to understand the maths behind it and hence am looking to mostly use simple functions &amp; matrices that I'm learning from a [book][1] (very retro!).&#xD;&#xA;&#xD;&#xA;I've successfully got through the stages of defining simple objects and converting them into a universal world space - but have come unstuck with the mathematics required to convert an object into view space and the back face culling.&#xD;&#xA;&#xD;&#xA;I believe my view space transformation is correct because when I plot the composite vectors they appear correct - but - when I do the back-face culling, it seems to fail to remove the correct triangles. Given that it depends only on two things, the line-of-sight vector and face normals, I can't work out what I'm doing wrong.&#xD;&#xA;&#xD;&#xA;When defining the triangles in local definition space, I did it so that all the normals pointed outwards. I've put my results into the image below&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;- Have I gone wrong, or are my expectations incorrect?&#xD;&#xA;- If so where, and how do I fix?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Progress&#xD;&#xA;&#xD;&#xA;I've plotted the normal's of all the shapes when in view space. They have all been inverted and now point inwards. Is this a property of the transformation and could it be responsible - or should this have no effect because all the polygons are affected the same?&#xD;&#xA;&#xD;&#xA;(Have changed the code to show this)&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %============Initial verticies &amp; Faces of the shape===========&#xD;&#xA;    [s1_vtx,s1_fcs] = Pyramid();&#xD;&#xA;    [s2_vtx,s2_fcs] = Cube();&#xD;&#xA;    %==============Transform Shape 1 ======================&#xD;&#xA;    Tx = 0; Ty = 0; Tz = 0; %Translation vectors for x,y,z axes&#xD;&#xA;    Sx = 2; Sy = 2; Sz = 2;%Scaling factors in x,y,z dimensions&#xD;&#xA;    Rx = pi/2; Ry = pi/4; Rz = pi/4; %Rotating factors in x,y,z dimensions&#xD;&#xA;    transform = scale(Sx,Sy,Sz)*rotate(Rx,0,0)*translate(Tx,Ty,Tz); %Merge transforms together&#xD;&#xA;    s1_vtx = transform*vertcat(s1_vtx,(ones(1,length(s1_vtx)))); %Add row of ones to end for multiplication&#xD;&#xA;    s1_vtx = s1_vtx(1:3,:); %And remove afterwards&#xD;&#xA;    %==============Transform Shape 2 ======================&#xD;&#xA;    Tx = 0.5; Ty = 0; Tz = 0.5;&#xD;&#xA;    transform = scale(1,2,1)*translate(Tx,Ty,Tz);&#xD;&#xA;    s2_vtx = transform*vertcat(s2_vtx,(ones(1,length(s2_vtx))));&#xD;&#xA;    s2_vtx = s2_vtx(1:3,:);&#xD;&#xA;    %======Create World Space ===========&#xD;&#xA;    ws_vtx = horzcat(s1_vtx(1:3,:), s2_vtx(1:3,:)); %remove homogenous column for patching&#xD;&#xA;    ws_fcs = horzcat(s1_fcs,(s2_fcs+(length(s1_vtx))));&#xD;&#xA;    %======Plot World Space ===========&#xD;&#xA;    grid on; hold on;&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none');&#xD;&#xA;    for i = 1:length(ws_vtx)&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',16, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    points = zeros(3,3); %Contains 1 triangle&#xD;&#xA;    for i = 1:length(ws_fcs); %For each triangle&#xD;&#xA;        points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i));&#xD;&#xA;        U = points(:,2) - points(:,1); %Get two non-parallel vectors&#xD;&#xA;        V = points(:,3) - points(:,1);&#xD;&#xA;        average = [0,0,0];&#xD;&#xA;        for j = 1:length(points)&#xD;&#xA;            average(j) = (points(j,1) + points(j,2) + points(j,3))/3;&#xD;&#xA;        end&#xD;&#xA;        N = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1&#xD;&#xA;        scatter3(average(1),average(2),average(3));&#xD;&#xA;        plot3([average(1), average(1)+N(1)],[average(2), average(2)+N(2)],[average(3), average(3)+N(3)]);&#xD;&#xA;    end&#xD;&#xA;    %==================Create view matrix===================&#xD;&#xA;    focus = [1.5,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Position of camera&#xD;&#xA;    Vspec = [0;0;1]; %Specified up direction&#xD;&#xA;    T = viewMat(focus, [Cx,Cy,Cz],Vspec); %Create viewspace transform matrix&#xD;&#xA;    p = norm(focus - [Cx,Cy,Cz]);&#xD;&#xA;    U = T(1,1:3); V = T(2,1:3); N = T(3,1:3); %New Up, Right &amp; View direction vectors&#xD;&#xA;    %============Plot the camera vectors=================&#xD;&#xA;    scatter3(Cx,Cy,Cz,'s') %Plot the camera position&#xD;&#xA;    plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)]);&#xD;&#xA;    plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)]);&#xD;&#xA;    plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)]);&#xD;&#xA;    %==================Transform into View Space===================&#xD;&#xA;    ws_vtx = T*vertcat(ws_vtx,(ones(1, length(ws_vtx)))); %Transform matrix&#xD;&#xA;    ws_vtx = ws_vtx(1:3,:); %Remove homogenous dimension&#xD;&#xA;    origin = T*[Cx;Cy;Cz;1]; %Transform origin&#xD;&#xA;    Cx = origin(1); Cy = origin(2); Cz = origin(3); %remove homogenous dimension&#xD;&#xA;    focus = (T*horzcat(focus,1)')';%Transform focus point&#xD;&#xA;    focus = focus(:,1:3);%remove homogenous dimension&#xD;&#xA;    %==================Plot View Space=================&#xD;&#xA;    figure(); hold on; grid on;&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none');&#xD;&#xA;    scatter3(Cx, Cy, Cz, 's');&#xD;&#xA;    scatter3(focus(1), focus(2), focus(3), 's');&#xD;&#xA;    plot3([Cx, focus(1)],[Cy, focus(2)],[Cz,focus(3)], 'g');&#xD;&#xA;    for i = 1:length(ws_vtx)&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',16, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    %================Plot normals of world space==============&#xD;&#xA;    for i = 1:length(ws_fcs); %For each triangle&#xD;&#xA;        points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i));&#xD;&#xA;        &#xD;&#xA;        U = points(:,2) - points(:,1); %Get two non-parallel vectors&#xD;&#xA;        V = points(:,3) - points(:,1);&#xD;&#xA;        &#xD;&#xA;        average = [0,0,0];&#xD;&#xA;        for j = 1:length(points)&#xD;&#xA;            average(j) = (points(j,1) + points(j,2) + points(j,3))/3;&#xD;&#xA;        end&#xD;&#xA;        N = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1&#xD;&#xA;        scatter3(average(1),average(2),average(3));&#xD;&#xA;        plot3([average(1), average(1)+N(1)],[average(2), average(2)+N(2)],[average(3), average(3)+N(3)]);&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;  [1]: http://www.amazon.co.uk/3D-Computer-Graphics-Alan-Watt/dp/0201398559&#xD;&#xA;  [2]: https://i.stack.imgur.com/XeAiI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4476" PostHistoryTypeId="2" PostId="2028" RevisionGUID="c9390ec0-78e5-4360-81f2-f98d4260b4d7" CreationDate="2016-02-10T13:29:37.180" UserId="2646" Text="I (believe) I've solved this (even if it has taken 2 days). My problem was essentially I wanted to take the dot product of the face normal, and line-of-sight vector like below&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And determine the angle to see if the face was looking towards or away from the view point.&#xD;&#xA;&#xD;&#xA;My erroneous step was that I was doing this AFTER transforming from world-space to view-space - hence the line-of-sight vector I was using was no longer valid.&#xD;&#xA;&#xD;&#xA;Hence, to solve this, I simply performed the back-face culling in world-space, prior to the world-view space transformation!&#xD;&#xA;&#xD;&#xA;I've included functioning code showing the back face culling, but not the view-space transform.&#xD;&#xA;&#xD;&#xA;    clear; clc; close all;&#xD;&#xA;    %======Create World Space (hard-coded values for demo) ===========&#xD;&#xA;    ws_vtx = [0,2,0,2,1,0.5,1.5,0.5,1.5,0.5,1.5,0.5,1.5;&#xD;&#xA;        0,0,0,0,-2,0,0,2,2,0,0,2,2;&#xD;&#xA;        0,0,2,2,1,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5];&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    %==================Create view matrix===================&#xD;&#xA;    focus = [1.5,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Position of camera&#xD;&#xA;    Vspec = [0;0;1]; %Specified up direction&#xD;&#xA;    T = viewMat(focus, [Cx,Cy,Cz],Vspec); %Create viewspace transform matrix&#xD;&#xA;    p = norm(focus - [Cx,Cy,Cz]);&#xD;&#xA;    U = T(1,1:3); V = T(2,1:3); N = T(3,1:3); %New Up, Right &amp; View direction vectors&#xD;&#xA;    %============Plot the camera vectors=================&#xD;&#xA;    grid on; hold on; scatter3(Cx,Cy,Cz,'s'); %Plot the camera position&#xD;&#xA;    plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)],'g');&#xD;&#xA;    plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)],'g');&#xD;&#xA;    plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)],'g');&#xD;&#xA;    %===========Get Face Normals============================&#xD;&#xA;    norm_fcs = zeros(3,length(ws_fcs)); &#xD;&#xA;        for i = 1:length(ws_fcs); %For each triangle&#xD;&#xA;            points = zeros(3,3); %Contains 1 triangle&#xD;&#xA;            points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i)); %Get points for triangle&#xD;&#xA;            U = points(:,2) - points(:,1); %Get two non-parallel vectors&#xD;&#xA;            V = points(:,3) - points(:,1);&#xD;&#xA;            norm_fcs(:,i) = cross(U,V); %Normal, normalised to mag 1&#xD;&#xA;        end&#xD;&#xA;    %=================Back Face Culling======================&#xD;&#xA;    null_vals = 0;&#xD;&#xA;    for i = 1:length(ws_fcs) %Take each triangle &amp; calculate normal&#xD;&#xA;        if dot(norm_fcs(:,i), N) &gt; 0 %Dot product line of sight &amp; normal of faces&#xD;&#xA;            ws_fcs(:,i) = [0;0;0]; %If &gt; 0, not visible &amp; remove&#xD;&#xA;            null_vals = null_vals + 1; %And increment counter&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    ws_fcs_cat = zeros(3, length(ws_fcs) - null_vals); %Create new array&#xD;&#xA;    null_vals = 0;&#xD;&#xA;    for i = 1:length(ws_fcs)&#xD;&#xA;        if norm(ws_fcs(:,i)) == 0&#xD;&#xA;            null_vals = null_vals + 1;&#xD;&#xA;        else&#xD;&#xA;            ws_fcs_cat(:,i - null_vals) = ws_fcs(:,i);&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    ws_fcs = ws_fcs_cat;&#xD;&#xA;    %======Plot World Space ===========&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.5);&#xD;&#xA;    for i = 1:length(ws_vtx)&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',16, 'Color','r', 'FontWeight','b');&#xD;&#xA;    end&#xD;&#xA;    points = zeros(3,3); %Contains 1 triangle&#xD;&#xA;    for i = 1:length(ws_fcs); %For each triangle&#xD;&#xA;        points(:,1:3) = ws_vtx(:,ws_fcs(1:3,i));&#xD;&#xA;        U = points(:,2) - points(:,1); %Get two non-parallel vectors&#xD;&#xA;        V = points(:,3) - points(:,1);&#xD;&#xA;        average = [0,0,0];&#xD;&#xA;        for j = 1:length(points)&#xD;&#xA;            average(j) = (points(j,1) + points(j,2) + points(j,3))/3;&#xD;&#xA;        end&#xD;&#xA;        N = cross(U,V)/norm(cross(U,V)); %Normal, normalised to mag 1&#xD;&#xA;        scatter3(average(1),average(2),average(3));&#xD;&#xA;        plot3([average(1), average(1)+N(1)],[average(2), average(2)+N(2)],[average(3), average(3)+N(3)]);&#xD;&#xA;    end&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zf6LH.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="4477" PostHistoryTypeId="5" PostId="2026" RevisionGUID="ba1cf001-fef3-44c1-bc75-9167590501cb" CreationDate="2016-02-10T15:22:58.323" UserId="2651" Comment="more detailed image, added explanation in body" Text="Try starting at the origin, then dividing 360 degrees by n to find some useful angles for the points of your star.&#xD;&#xA;I hope this drawing will help you to find a solution.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CCGsh.png&#xD;&#xA;Now that you have the angle theta, and the values of alpha and x are chosen by you, you have the tools to calculate all required vertices to make the star using trigonometry." ContentLicense="CC BY-SA 3.0" />
  <row Id="4480" PostHistoryTypeId="5" PostId="82" RevisionGUID="5e51e579-1232-49e0-ad25-6f17d32291a4" CreationDate="2016-02-10T21:24:40.410" UserId="100" Comment="added 111 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where $F_t$ are Fresnel terms and $R$ is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This $R$ is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the $\|x_i - x_o\|$ above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;I am putting here the answers to a couple of @NathanReed 's questions in the comment section:&#xD;&#xA;&#xD;&#xA;&gt; Even with the diffusion profile approximation, the BSSRDF model still requires integrating over a radius of nearby points on the surface to gather incoming light, correct? How is that accomplished in, say, a path tracer? Do you have to build some data structure so you can sample points on the surface nearby a given point?&#xD;&#xA;&#xD;&#xA;The BSSRDF approximation still need to be integrated over a certain area, yes. &#xD;&#xA;&#xD;&#xA;In the paper linked they used a Montecarlo ray-tracer randomly sampling around a point with a density defined as: &#xD;&#xA;&#xD;&#xA;$\sigma_{tr}e^{-\sigma_{tr}d}$&#xD;&#xA;&#xD;&#xA;Where that sigma value is the effective extinction coefficient defined below ( it is dependent on scattering and absorbing coefficient, which are properties of the material) and d is the distance to the point we are evaluating. This density is this way defined because the diffusion term has exponential fall-off. &#xD;&#xA;&#xD;&#xA;In [\[Jensen and Buhler 2002\]][6] they proposed an acceleration technique. One of the main concepts was to decouple the sampling from the evaluation of the diffusion term. This way they perform a hierarchical evaluation of the information computed during the sampling phase to cluster together distant samples when it comes to evaluating the diffusion. The implementation described in the paper uses an octree as structure. &#xD;&#xA;This technique, according to the paper, is order of magnitude faster than the full Monte Carlo integration.  &#xD;&#xA;Unfortunately I never got myself into an off-line implementation, so I can't help more than this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the real-time sum-of-Gaussians approximations the correct radius is implicitly set when defining the variance of the Gaussian blurs that need to be applied.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&gt; Why one positive and one negative light? Is the goal for them to cancel each other in some way?&#xD;&#xA;&#xD;&#xA;Yes, the dipole source method (which dates way before Jensen's paper) is such defined to satisfy some boundary condition. Specifically the fluence must be zero at a certain extrapolated boundary that has a distance from the surface of $2AD$ where &#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Being $F_{dr}$ the fresnel reflectivity of the slab considered and that sigma value is the reduced extinction coefficient described below. &#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;EDIT2: I have expanded some of the concepts in this answer in a blog post: http://bit.ly/1Q82rqT&#xD;&#xA;_______&#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/q48vD.png&#xD;&#xA;  [6]: http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/fast_bssrdf.pdf&#xD;&#xA;  [7]: https://i.stack.imgur.com/rOdqD.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4481" PostHistoryTypeId="5" PostId="82" RevisionGUID="b33c2910-7f34-4b7f-b77c-ae100e3fd1f3" CreationDate="2016-02-10T21:56:10.297" UserId="100" Comment="added 13 characters in body" Text="The assumption underlying such model is the same as lots of other models for skin rendering; the subsurface scattering can be approximated as a diffusion phenomenon. This is good because in highly scattering media, the distribution of light loses dependency from the angle and tends to isotropy. &#xD;&#xA;&#xD;&#xA;The dipole approximation is a formulation for the resolution of such diffusion problem in an analytical fashion.&#xD;&#xA;&#xD;&#xA;Basically they start by approximating the BSSRDF as a multiple scattering and single scattering component. The multiple scattering is then defined as: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where $F_t$ are Fresnel terms and $R$ is the diffusion profile expressed as function of the distance between the entry and exit point.  &#xD;&#xA;&#xD;&#xA;This $R$ is referred to as diffusion profile and they formulate this profile via a dipole approximation. The contribution of the incoming light ray is considered to be the one of two virtual sources: one negative beneath the surface and one positive above it (that's why dipole) &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here in the picture r is the $\|x_i - x_o\|$ above.  The contribution of those light sources is dependent on various factors such as the distance of the light from the surface, scattering coefficient etc. (See below for a more detailed description of the formula itself). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This model only account for multiple scattering events, but that's fine enough for skin. It must be noticed though that for some translucent materials (e.g. smoke and marble) the single scattering is fundamental. That paper propose a single scattering formulation, but is expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffusion profile is usually approximated for real-time application as a series of gaussian blurs (like in the seminal works of D'Eon et al. in GPU Gems 3 then used for the Jimenez's SSSSS) so to make it practical for real time scenarios. In [this wonderful paper][3] there are details on such approximation. &#xD;&#xA;A picture from that paper show actually how good is this formulation: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As side note the dipole approximation assumes that the material is semi-infinite, however this assumption doesn’t hold with thin slabs and multi-layered material such as the skin. Building on the dipole work, Donner and Jensen [2005] proposed the multi-pole approximation that accounts for the dipole problems. &#xD;&#xA;With this model instead of a single dipole, the authors use a set of them to describe the scattering phenomenon. In such formulation the reflectance and transmittance profiles can be obtained by summing up the contribution of the different dipoles involved&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;I am putting here the answers to a couple of @NathanReed 's questions in the comment section:&#xD;&#xA;&#xD;&#xA;&gt; Even with the diffusion profile approximation, the BSSRDF model still requires integrating over a radius of nearby points on the surface to gather incoming light, correct? How is that accomplished in, say, a path tracer? Do you have to build some data structure so you can sample points on the surface nearby a given point?&#xD;&#xA;&#xD;&#xA;The BSSRDF approximation still need to be integrated over a certain area, yes. &#xD;&#xA;&#xD;&#xA;In the paper linked they used a Montecarlo ray-tracer randomly sampling around a point with a density defined as: &#xD;&#xA;&#xD;&#xA;$\sigma_{tr}e^{-\sigma_{tr}d}$&#xD;&#xA;&#xD;&#xA;Where that sigma value is the effective extinction coefficient defined below ( it is dependent on scattering and absorbing coefficient, which are properties of the material) and d is the distance to the point we are evaluating. This density is this way defined because the diffusion term has exponential fall-off. &#xD;&#xA;&#xD;&#xA;In [\[Jensen and Buhler 2002\]][6] they proposed an acceleration technique. One of the main concepts was to decouple the sampling from the evaluation of the diffusion term. This way they perform a hierarchical evaluation of the information computed during the sampling phase to cluster together distant samples when it comes to evaluating the diffusion. The implementation described in the paper uses an octree as structure. &#xD;&#xA;This technique, according to the paper, is order of magnitude faster than the full Monte Carlo integration.  &#xD;&#xA;Unfortunately I never got myself into an off-line implementation, so I can't help more than this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the real-time sum-of-Gaussians approximations the correct radius is implicitly set when defining the variance of the Gaussian blurs that need to be applied.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&gt; Why one positive and one negative light? Is the goal for them to cancel each other in some way?&#xD;&#xA;&#xD;&#xA;Yes, the dipole source method (which dates way before Jensen's paper) is such defined to satisfy some boundary condition. Specifically the fluence must be zero at a certain extrapolated boundary that has a distance from the surface of $2AD$ where &#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Being $F_{dr}$ the fresnel reflectivity of the slab considered and that sigma value is the reduced extinction coefficient described below. &#xD;&#xA;&#xD;&#xA;_______ &#xD;&#xA;&#xD;&#xA;EDIT2: I have expanded (a tiny bit) some of the concepts in this answer in a blog post: http://bit.ly/1Q82rqT&#xD;&#xA;_______&#xD;&#xA;&#xD;&#xA;For those who are not scared by lots of greek letters in a formula, here's an extract from my thesis where the reflectance profile is briefly described in each term: &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3OivX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJQLF.png&#xD;&#xA;  [3]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/0GcPn.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/q48vD.png&#xD;&#xA;  [6]: http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/fast_bssrdf.pdf&#xD;&#xA;  [7]: https://i.stack.imgur.com/rOdqD.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/xtQG8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4482" PostHistoryTypeId="2" PostId="2029" RevisionGUID="17c7b72f-9e67-47c3-b415-1c7a816da602" CreationDate="2016-02-11T04:07:50.647" UserId="2651" Text="I'm a beginner in OpenGL and I've been doing some research on the topic of shaders and attributes. Most places I go say that explicit attribute binding (whether it be in the shader itself with `layout(location=x)` or with `glBindAttribLocation`) is better than letting OpenGL generate some attribute number. However, I didn't completely understand WHY explicit attribute binding is better.&#xD;&#xA;&#xD;&#xA;So I guess my question is, what are the pros/cons to explicit/automatic attribute binding, and which one is more conducive to better program design overall?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4483" PostHistoryTypeId="1" PostId="2029" RevisionGUID="17c7b72f-9e67-47c3-b415-1c7a816da602" CreationDate="2016-02-11T04:07:50.647" UserId="2651" Text="Explicit vs Automatic Attribute Binding" ContentLicense="CC BY-SA 3.0" />
  <row Id="4484" PostHistoryTypeId="3" PostId="2029" RevisionGUID="17c7b72f-9e67-47c3-b415-1c7a816da602" CreationDate="2016-02-11T04:07:50.647" UserId="2651" Text="|opengl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4485" PostHistoryTypeId="5" PostId="1982" RevisionGUID="15996d72-d4d8-4476-9ef5-0d351c966845" CreationDate="2016-02-11T08:42:57.343" UserId="209" Comment="fixed grammar" Text="[Disclaimer: I think the following should work but have not actually coded it myself]&#xD;&#xA;&#xD;&#xA;I couldn't think of a &quot;trivial&quot; method of producing a yes/no answer but the following would be a reasonable approach to a practical solution to the question.&#xD;&#xA;&#xD;&#xA;Let's assume our curves are _A(s)_ and _B(t)_ with control points {_A0, A1..An_} and {_B0,..Bm_} respectively.&#xD;&#xA;&#xD;&#xA;It seems to me that, given a pair of 2D Beziers for which we wish to determine do or don't intersect, there are six cases to consider:&#xD;&#xA;&#xD;&#xA; 1. Case where we can &quot;trivially&quot; determine they do *not* intersect.&#xD;&#xA;&#xD;&#xA; 2. Case where they intersect a finite number of times and we can &quot;easily&quot; determine they definitely intersect at least once (but we don't actually care where those intersections occur)&#xD;&#xA;&#xD;&#xA; 3. One of the Beziers is degenerate, i.e. a point (which will occur if all the control points are identical). We can assume we've already handled the case where both are points.&#xD;&#xA;&#xD;&#xA; 4. One or more of the curves are closed, e.g.. A0==An. To make life simpler, we'll subdivide such curves and start again.&#xD;&#xA;&#xD;&#xA; 5. There are an infinite number of points of intersection because each is subset of a &quot;parent&quot; Bezier and they overlap.&#xD;&#xA;&#xD;&#xA; 6. We aren't certain about the above cases and need further investigation&#xD;&#xA;&#xD;&#xA;For the moment we'll ignore 3 and 4, but come back to them later.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 1 ###&#xD;&#xA;As you hint in your question, if the respective bounding boxes of the control points of _A_ and _B_), don't intersect, then the curves can't intersect. Obviously this is a quick reject test but it's overly conservative.&#xD;&#xA;As you probably know, with a Bezier curve, the convex hull of its control points forms a (tighter) bound on the curve. We can thus use the separating axis technique to decide if the hulls of _A_ and _B_ don't intersect. (e.g. as shown in Wikipedia:)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Case 2 ###&#xD;&#xA;If the case 1 test fails, you could then check for the &quot;trivial&quot; existence of an intersection. Now there are probably better ways to do this, but the following, relatively cheap, approach occurred to me:&#xD;&#xA;&#xD;&#xA;Consider just curve A:&#xD;&#xA;&#xD;&#xA;[![&quot;Fat line&quot; bounds of a Bezier][2]][2]&#xD;&#xA;&#xD;&#xA;We know the curve starts at $A_0$, terminates at $A_n$, and will lie inside the convex hull. For simplicity let us compute the direction of the line segment $\overline{A_0A_n} $ and the compute the bounds on either side (i.e. take dot products of the remaining control points against the perpendicular to $\overline{A_0A_n}$).&#xD;&#xA;&#xD;&#xA;If we do the same with curve B we get the following (possible) case:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we find $A_0$ and $A_n$ are outside opposite bounds of B _and_ that $B_0$ and $B_m$ are on the outsides of the bounds of A, then, by the continuity of Beziers, there must be at least one intersection.&#xD;&#xA;&#xD;&#xA;### Case 6 ###&#xD;&#xA;If we can't immediately show either of the above cases, then split each of the Beziers into two &quot;halves&quot;, i.e. $A^1, A^2, B^1, B^2$. This is relatively straightforward (left as an exercise to the reader) but is [particularly trivial for quadratic Beziers](https://computergraphics.stackexchange.com/questions/1895/how-should-i-fill-a-shape-consisting-of-bezier-cures-and-straight-lines/1899#1899): &#xD;&#xA;&#xD;&#xA;Recursively compare the 4 combinations: $(A^1,B^1), (A^2, B^1)...(A^2, B^2)$.&#xD;&#xA;Clearly if all pass case 1, there is no intersection.&#xD;&#xA;If any fail 1, then continue with the rest of the tests with that reduced subset.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Case 3 &amp; 5 ###&#xD;&#xA;This is where it becomes slightly more tedious.&#xD;&#xA;&#xD;&#xA;If &quot;case 3&quot; gets past the &quot;case 1&quot; test, it seems to me that you need to solve for an actual intersection. Given that there is a simple process to map the N control points of a Bezier, A(s), to the N-1 points of the Bezier, A'(s), representing its 1st derivative then (provided care is taken for the relatively rare, so-called &quot;degenerate&quot; situations where the 1st derivative does to zero), then Newton iteration (on one dimension) could be used to find potential solutions.  &#xD;&#xA;Note also that, since the control points of A'(s) are a bound on the derivative values, there is the potential to do early elimination of some cases.&#xD;&#xA;&#xD;&#xA;Case 5 seems relatively unlikely, so perhaps only if after a few recursions there is no conclusive proof, one could try each end point of A against curve B and vice versa. This would only give a proof of intersection - not a proof of non-intersection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/u4AxW.png&#xD;&#xA; [2]: https://i.stack.imgur.com/2An9z.png&#xD;&#xA; [3]: https://i.stack.imgur.com/dX6l0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4486" PostHistoryTypeId="2" PostId="2030" RevisionGUID="ce870832-1d5b-4600-a5b7-d412cfef79e5" CreationDate="2016-02-11T10:06:35.107" UserId="2666" Text="I am implementing a simple ray tracer with OpenGL. I have a shader storage buffer with all the triangles so I can test them for intersections in a compute shader. It works fine up to a certain buffer size. But if I have more than a certain amount, it stops working and I get the following message:&#xD;&#xA;&#xD;&#xA;&gt; OpenGL: Buffer usage warning: Discarding a video memory only buffer object. The data store will be reallocated on next usage of the buffer object.&#xD;&#xA;&#xD;&#xA;The program does not crash however.&#xD;&#xA;&#xD;&#xA;The `GL_MAX_SHADER_STORAGE_BLOCK_SIZE` is 2147483647, so 2GB. The size of the buffer when it doesn't work anymore is just a couple of MB, around 6 to 7 MB.&#xD;&#xA;&#xD;&#xA;Am I overlooking something? Are there other limits I don't know about?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4487" PostHistoryTypeId="1" PostId="2030" RevisionGUID="ce870832-1d5b-4600-a5b7-d412cfef79e5" CreationDate="2016-02-11T10:06:35.107" UserId="2666" Text="Cannot use more than a couple of MB in a shader storage buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="4488" PostHistoryTypeId="3" PostId="2030" RevisionGUID="ce870832-1d5b-4600-a5b7-d412cfef79e5" CreationDate="2016-02-11T10:06:35.107" UserId="2666" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4490" PostHistoryTypeId="2" PostId="2031" RevisionGUID="cc0268ad-219d-4a02-95f5-56fb7b3c2487" CreationDate="2016-02-11T12:57:13.237" UserId="2670" Text="What 3D scene reconstruction methods does the term &quot;multi-view stereo&quot; encompass? It is only used for methods that apply binocular stereo algorithms (taking 2 views as input) in a pairwise manner? Or only methods based on disparity estimation? If not why is the term &quot;stereo&quot; used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4491" PostHistoryTypeId="1" PostId="2031" RevisionGUID="cc0268ad-219d-4a02-95f5-56fb7b3c2487" CreationDate="2016-02-11T12:57:13.237" UserId="2670" Text="What is stereo about multi-view stereo?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4492" PostHistoryTypeId="3" PostId="2031" RevisionGUID="cc0268ad-219d-4a02-95f5-56fb7b3c2487" CreationDate="2016-02-11T12:57:13.237" UserId="2670" Text="|3d|depth-map|photometric|scene-description|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4493" PostHistoryTypeId="2" PostId="2032" RevisionGUID="f57b172b-6d30-40a3-966f-8c1c5b38ba5a" CreationDate="2016-02-11T15:08:51.003" UserId="273" Text="&gt; Multi-view stereo (MVS) is the general term&#xD;&#xA;given to a group of techniques that use stereo correspondence as their&#xD;&#xA;main cue and use more than two images.&#xD;&#xA;&#xD;&#xA;A quote from ['Multi-View Stereo: A Tutorial'][1] by Yasutaka Furukawa and Carlos Hernández.&#xD;&#xA;&#xD;&#xA;So to paraphrase: We have a set of images that is larger than two, and use them in a pairwise manner by applying techniques that finde stereo correspondences to reconstruct the object shown in them.&#xD;&#xA;&#xD;&#xA;If you want to know more about MVS algorithms that paper I linked seems to be pretty good and at least Furukawa is a name that I know and have read papers from, so he seems to know the topic.&#xD;&#xA;  [1]: http://www.cse.wustl.edu/~furukawa/papers/fnt_mvs.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4494" PostHistoryTypeId="5" PostId="2017" RevisionGUID="2fafbb1c-701a-486d-9d23-43e2b94424cc" CreationDate="2016-02-11T17:05:52.757" UserId="209" Comment="Reordered a couple of sentences to make the description flow more logically." Text="I'm fairly certain your problem lies in not handling so-called *degenerate* Bezier patches correctly, in particular (as [Joojaa](https://computergraphics.stackexchange.com/users/38/joojaa) noted), the computation of the surface normal.  I say *&quot;so-called degenerate&quot;* because, geometrically, the surfaces are often perfectly well behaved. It's just that some assumptions people frequently make regarding the parametric equations may not hold.&#xD;&#xA;&#xD;&#xA;Books such as Gerald Farin's, snappily titled, *&quot;Curves and Surfaces for CAGD. A Practical Guide&quot;* will give more details, but I'll try to summarise two simple cases. Now assuming your Bezier is defined as $\bar{B}(u,v)$ the usual two causes of problems are:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Zero derivatives: ###&#xD;&#xA;To compute the normal at $(a,b)$ one normally (pardon the pun) computes the two derivatives,&#xD;&#xA;&#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(a,b)$ and $\frac{\partial }{\partial u}\bar{B}(a,b)$&#xD;&#xA;&#xD;&#xA; *or scaled versions thereof*, to obtain two tangents and then take the cross product. &#xD;&#xA;&#xD;&#xA;(*Implementation note: Since we can use a scaled version of the tangent in the calculation, we really don't have to calculate the actual derivative. For example, especially at the corners, differences of control points can yield a scaled tangent. However for brevity in this discussion we will assume the actual derivatives*).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A common occurrence, at least at the corners, is that the 1st partial derivatives at the location can be zero, which leads to an incorrect normal, i.e. a zero vector.&#xD;&#xA;&#xD;&#xA;In the case of the tops and bottoms of the teapot, one whole edge of a number of the (bicubic) Bezier patches has been collapsed to a point, i.e. all 4 control points are the same, and thus, say &#xD;&#xA;&#xD;&#xA; $\bar{B}(0,v)==\bar{B}(1,v)$   and   $\frac{\partial }{\partial u}\bar{B}(0,0)=\bar{0}$. &#xD;&#xA;&#xD;&#xA;The surface, however, is completely well behaved so you can simply choose another derivative that starts at that collapsed point. In this case, say, choosing&#xD;&#xA; &#xD;&#xA;$\frac{\partial }{\partial v}\bar{B}(1,0)$&#xD;&#xA;&#xD;&#xA;for the second tangent.&#xD;&#xA;&#xD;&#xA;Having said this, you *still* have to check that your first derivatives are not zero for another reason (e.g 2 or 3 coincident control points), in which case, you can fall back (thanks to L'Hopital's rule) on the second (or if that's zero, even the third!) derivative(s) to obtain valid tangents.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Parallel tangents: ###&#xD;&#xA;Another similar problem can arise if your two tangents, are *parallel*. - Farin has a good example in his book. &#xD;&#xA;&#xD;&#xA;In this case, I *think* you may need to look at using something like $\frac{\partial^2 }{\partial u \partial v}\bar{B}$ or, possibly, just fall back to using a small UV offset to approximate a vector.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4495" PostHistoryTypeId="5" PostId="2031" RevisionGUID="980ce796-6f6f-4ca4-917b-5f0af91c0e60" CreationDate="2016-02-11T19:48:54.940" UserId="231" Comment="Minor typo" Text="What 3D scene reconstruction methods does the term &quot;multi-view stereo&quot; encompass? Is it only used for methods that apply binocular stereo algorithms (taking 2 views as input) in a pairwise manner? Or only methods based on disparity estimation? If not why is the term &quot;stereo&quot; used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4501" PostHistoryTypeId="2" PostId="2034" RevisionGUID="59eb5591-8e39-4eb8-b7d9-553225ea4bb1" CreationDate="2016-02-12T08:05:05.823" UserId="2673" Text="Why is it that when you zoom in to some black text you find that it is made up of orange, slightly black and blue pixels like the picture below. &#xD;&#xA;&#xD;&#xA;[![Black text zoomed in][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0gIia.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4502" PostHistoryTypeId="1" PostId="2034" RevisionGUID="59eb5591-8e39-4eb8-b7d9-553225ea4bb1" CreationDate="2016-02-12T08:05:05.823" UserId="2673" Text="why does black text have orange and blue pixels" ContentLicense="CC BY-SA 3.0" />
  <row Id="4503" PostHistoryTypeId="3" PostId="2034" RevisionGUID="59eb5591-8e39-4eb8-b7d9-553225ea4bb1" CreationDate="2016-02-12T08:05:05.823" UserId="2673" Text="|antialiasing|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4504" PostHistoryTypeId="2" PostId="2035" RevisionGUID="d6bbae8c-dc7c-4dfa-9bf4-755cb5e4c5ec" CreationDate="2016-02-12T13:32:56.290" UserId="2633" Text="For a non-computer graphics expert, what happens technically when you do this? Are multiple pixels merged to one to compensate for the lower resolution? And in how far will this affect the image quality?&#xD;&#xA;&#xD;&#xA;Would a high resolution image look sharper on a low resolution display than if the same image would have the exact same resolution as the screen?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4505" PostHistoryTypeId="1" PostId="2035" RevisionGUID="d6bbae8c-dc7c-4dfa-9bf4-755cb5e4c5ec" CreationDate="2016-02-12T13:32:56.290" UserId="2633" Text="What happens when you display a high resolution image on a low resolution screen?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4506" PostHistoryTypeId="3" PostId="2035" RevisionGUID="d6bbae8c-dc7c-4dfa-9bf4-755cb5e4c5ec" CreationDate="2016-02-12T13:32:56.290" UserId="2633" Text="|texture|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4507" PostHistoryTypeId="2" PostId="2036" RevisionGUID="a3b2140b-d97e-40fb-9d96-6f606fdc7b9d" CreationDate="2016-02-12T13:50:28.900" UserId="273" Text="If you scale an image down to a screen that has a lower resolution than yout image, you have to descide what you do, there is no single way of doing this.&#xD;&#xA;&#xD;&#xA;There are many different techniques that yield very different results.&#xD;&#xA;This is very similar to displaying a low resolution image on a high resolution display where do the inverse thing by desciding how to fill the &quot;more&quot; pixels on the screen. There are also many techniques for doing this.&#xD;&#xA;&#xD;&#xA;[![Image scaling comparison. Nearest-neighbor scaling (left) and 2*Sal scaling (right).][1]][1]&#xD;&#xA;&#xD;&#xA;The image shows two upscaling-techniques and shows how different the results can look if different techniques are used. (A nearest-neighbor scaling on the left and a 2*Sal on the right.) Imagine that there are also such differences if you downscale an image.&#xD;&#xA;&#xD;&#xA;You can find a nice overview on different scaling techniques on the wikipedia page for [Image scaling][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YQKdg.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Image_scaling" ContentLicense="CC BY-SA 3.0" />
  <row Id="4509" PostHistoryTypeId="2" PostId="2037" RevisionGUID="40ae63c8-b940-45f0-9fa0-a5f7b467daac" CreationDate="2016-02-12T18:22:24.593" UserId="2646" Text="I am attempting to model a simple graphics pipeline (i.e. Local-&gt;Word-&gt;View-&gt;Screen-&gt;2D spaces).&#xD;&#xA;&#xD;&#xA;I've been looking at the algorithm required to transform from world to view-space and using the following transform[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Although I have been using U,V,N,C notation rather than Xc,Yc,Zc,e.&#xD;&#xA;&#xD;&#xA;And my matrix transformation at first glance, appears correct: When I plot the vectors onto world space, I get a vector from the camera position to the point we're looking at, and two correctly placed new X and Y vectors (see the left hand image below).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;By looking along the line of sight vector (such that it disappears,and the focus &amp; camera points overlap), as in the middle figure, should (I believe?) give an accurate example of what the resultant viewspace transformation should look like, with the green vertical and right-pointing vectors showing the new X &amp; Y vectors.&#xD;&#xA;&#xD;&#xA;However - when I actually do the view space transform I don't get the middle figure, instead, the resultant transform seems to be looking at the object from a different position possibly aligned with one of the axes? This is shown in the right hand figure - which is actually looking at the object from a slightly lower perspective &#xD;&#xA;&#xD;&#xA;My question is essentially what have I done wrong, or am I misunderstanding both the transform and thus my results?&#xD;&#xA;&#xD;&#xA;Thanks very much,&#xD;&#xA;&#xD;&#xA;David&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clear; clc; close all;&#xD;&#xA;    %======Create World Space (hard-coded values for demo) ===========&#xD;&#xA;    ws_vtx = [0,2,0,2,1,0.5,1.5,0.5,1.5,0.5,1.5,0.5,1.5;&#xD;&#xA;        0,0,0,0,-2,0,0,2,2,0,0,2,2;&#xD;&#xA;        0,0,2,2,1,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5];&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    %==================Create view matrix===================&#xD;&#xA;    focus = [1.5,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Position of camera&#xD;&#xA;    Vspec = [0;0;1]; %Specified up direction for view space (i.e. camera orientation)&#xD;&#xA;    vector = focus - [Cx,Cy,Cz]; %Vector camera to focus point &#xD;&#xA;    p = sqrt(vector(1)^2 + vector(2)^2 + vector(3)^2); %Total magnitude of vector&#xD;&#xA;    r = sqrt(vector(1)^2 + vector(2)^2);%Magnitude of flat components&#xD;&#xA;    % Calculate Azimuth&#xD;&#xA;    az = atan(vector(2)/vector(1));&#xD;&#xA;    if(vector(1) &lt; 0) %Left hand side&#xD;&#xA;        if (vector(2) &gt; 0) %TL quad&#xD;&#xA;            az = az + pi;&#xD;&#xA;        else&#xD;&#xA;            az = az - pi;%BL quad&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    % Calculate elevation&#xD;&#xA;    el = asin(r/p);&#xD;&#xA;    if(vector(3) &lt; 0)&#xD;&#xA;        el = pi-el;&#xD;&#xA;    end;&#xD;&#xA;    %Normal view from camera to object (direction of point)&#xD;&#xA;    N = [sin(el)*cos(az); sin(el)*sin(az); cos(el)]; %View plane normal&#xD;&#xA;    V = Vspec - cross(cross(Vspec,N),N); %Create new &quot;up&quot; direction&#xD;&#xA;    U = cross(N,V); %Create new x-axis&#xD;&#xA;    %Create rotational matrix to view space&#xD;&#xA;    R= [U(1),U(2),U(3),0; % U is direction of camera space X axis&#xD;&#xA;        V(1),V(2),V(3),0; % V is direction of camera space Y axis&#xD;&#xA;        N(1),N(2),N(3),0;&#xD;&#xA;        0   ,   0,   0,1];&#xD;&#xA;    Tr = [1,0,0,-Cx;&#xD;&#xA;          0,1,0,-Cy;&#xD;&#xA;          0,0,1,-Cz;&#xD;&#xA;          0,0,0,  1];&#xD;&#xA;    T = R*Tr; %Total view transform = rotation * translation&#xD;&#xA;    %============Plot the camera vectors &amp; World Space=================&#xD;&#xA;    grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(Cx,Cy,Cz,'s'); %Plot the camera position&#xD;&#xA;    plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)],'g'); %Plot camera vectors&#xD;&#xA;    plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)],'g');&#xD;&#xA;    plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)],'g');&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none');&#xD;&#xA;    for i = 1:length(ws_vtx)&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',14, 'Color','r');&#xD;&#xA;    end&#xD;&#xA;    %====================Viewspace Transform===========================&#xD;&#xA;    ws_vtx = T*vertcat(ws_vtx,(ones(1,length(ws_vtx)))); %Transform worldspace&#xD;&#xA;    ws_vtx = ws_vtx(1:3,:); %Remove homogenous column&#xD;&#xA;    position = T*[Cx;Cy;Cz;1]; focus = T*horzcat(focus,1)'; %Transform set points&#xD;&#xA;    position = position(1:3,:); focus = focus(1:3,:); %Remove homogenous columns&#xD;&#xA;    %================Plot new viewspace===============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s'); %Plot new camera vectors&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],...&#xD;&#xA;        [position(2); position(2)+focus(2)],[position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none');&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NKmCc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RavTO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4510" PostHistoryTypeId="1" PostId="2037" RevisionGUID="40ae63c8-b940-45f0-9fa0-a5f7b467daac" CreationDate="2016-02-12T18:22:24.593" UserId="2646" Text="Correct view-space transform" ContentLicense="CC BY-SA 3.0" />
  <row Id="4511" PostHistoryTypeId="3" PostId="2037" RevisionGUID="40ae63c8-b940-45f0-9fa0-a5f7b467daac" CreationDate="2016-02-12T18:22:24.593" UserId="2646" Text="|transformations|vector-graphics|matrix|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4512" PostHistoryTypeId="6" PostId="2034" RevisionGUID="f8fa1f25-79f0-4174-a8b4-652217bb6cc6" CreationDate="2016-02-12T20:14:59.897" UserId="38" Comment="edited tags" Text="|antialiasing|font-rendering|subpixel-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4513" PostHistoryTypeId="2" PostId="2038" RevisionGUID="e60e8198-488d-4c4d-b625-5a4f3bc53cf7" CreationDate="2016-02-12T20:50:25.683" UserId="38" Text="This is called subpixel rendering.&#xD;&#xA;&#xD;&#xA;The different primary colors in your monitor are not stacked on top of each other. Instead they are arranged near each other. Different monitors have different patterns but most commonly they are aligned so that the colors are side by side. &#xD;&#xA;&#xD;&#xA;If you know the physical arrangement, then you can prepare the image so that you have calculated a different sample position for each color channel. In essence your boosting the resolution of your image so that you are treating each individual color as a separate pixel. &#xD;&#xA;&#xD;&#xA;This offcourse means that you need to know the display orientation and have some data that can be shifted. The image wouldn't be all that useful on other monitors with different pixel alignments. So this is reserved for things that are dynamically generated, most often fonts.&#xD;&#xA;&#xD;&#xA;It also means that when zoomed or presented on a medium with different or no subpixels, the effect will register as a blur. So zooming in on the pixels of a subpixel rendered image is not very good idea. For this reason it migth be a good idea to disable the effect if you make images for others to use and the subpixel alignment is unknown." ContentLicense="CC BY-SA 3.0" />
  <row Id="4514" PostHistoryTypeId="2" PostId="2039" RevisionGUID="c20a1fe3-a613-491b-a4d7-57f3e3aae7c5" CreationDate="2016-02-13T01:11:18.203" UserId="231" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="4515" PostHistoryTypeId="2" PostId="2040" RevisionGUID="99995ce1-e7b2-44f6-9600-4e927a371f04" CreationDate="2016-02-13T01:11:18.203" UserId="231" Text="For questions about scalable 2D graphics based on vector operations, as opposed to raster graphics. For example, polygons, Bézier curves and ellipses." ContentLicense="CC BY-SA 3.0" />
  <row Id="4516" PostHistoryTypeId="6" PostId="2037" RevisionGUID="25c12583-27d5-4d7f-a97f-4cc66ae06488" CreationDate="2016-02-13T01:12:27.140" UserId="231" Comment="edited tags" Text="|transformations|matrix|matlab|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4517" PostHistoryTypeId="6" PostId="2023" RevisionGUID="96ee18d6-a885-4d4d-b5ac-503eba9d789a" CreationDate="2016-02-13T01:12:51.580" UserId="231" Comment="edited tags" Text="|transformations|3d|matrix|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4520" PostHistoryTypeId="5" PostId="1991" RevisionGUID="a757a0cc-b846-4255-b30f-a9c3e4e2195b" CreationDate="2016-02-13T04:02:09.840" UserId="2593" Comment="added 53 characters in body" Text="I encountered some problems when implementing the cloth simulation algorithm from Baraff &amp; Witkin 98's [Large Steps in Cloth Simulation](http://www.cs.cmu.edu/~baraff/papers/sig98.pdf).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Baraff &amp; Witkin 98**&#xD;&#xA;&#xD;&#xA;Consider the cloth as a particle system in 3D, which consists of N particles.&#xD;&#xA;&#xD;&#xA;1. Equation of motion&#xD;&#xA;&#xD;&#xA;In each time step, the implicit integration of particle system is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix} \Delta \mathbf x \\ \Delta \mathbf v \\ \end{pmatrix} = h\begin{pmatrix} \mathbf v_0 + \Delta \mathbf v \\ \mathbf M^{-1} \mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v) \\ \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $h$ is the time step (scalar)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. The partial derivative equation&#xD;&#xA;&#xD;&#xA;Rewrite the aforementioned equality of motion into $\mathbf A \Delta \mathbf v = \mathbf b$ form, (&#xD;&#xA;Take the 1st order Taylor expansion of $\mathbf f(\mathbf x_0 + \Delta \mathbf x, \mathbf v_0 + \Delta \mathbf v)$, and introduce constraint matrix $\mathbf S$, which make mass matrix from $\mathbf M^{-1}$ to $\mathbf M^{-1}\mathbf S$), we have: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf x})\Delta \mathbf v = h\mathbf M^{-1} \mathbf S(\mathbf f_0 + h\frac{\partial \mathbf f}{\partial \mathbf x} \mathbf v_0) + \mathbf z&#xD;&#xA;$$ &#xD;&#xA;&#xD;&#xA;Where all of the matrices are treated as $N\times N $ block matrices, eack block sizes $3\times 3 $; vectors as $N$ block vector, each sized $3$ (with N number of 3D forces/positions/velocities).&#xD;&#xA;&#xD;&#xA; - $\mathbf I$ is identical matrix&#xD;&#xA;&#xD;&#xA; - $ \mathbf M = diag(\mathbf M_1, \mathbf M_2, ..., \mathbf M_N) $, $\mathbf M_i = diag(m_i, m_i, m_i)$, mass of each particle&#xD;&#xA;&#xD;&#xA; - $ \mathbf S = diag(\mathbf S_1, \mathbf S_2, ..., \mathbf S_N) $, &#xD;&#xA;$  \mathbf S_i = \begin{cases}  \mathbf I,  &amp; \text{$ndof(i) = 3$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T,  &amp; \text{$ndof(i) = 2$} \\ \mathbf I - \mathbf p_i \mathbf p_i^T - \mathbf q_i \mathbf q_i^T,  &amp; \text{$ndof(i) = 1$} \\ \mathbf 0,  &amp; \text{$ndof(i) = 0$} \end{cases}$, $\mathbf p$ and $\mathbf q$ are two oithogonal constraint direction, $\mathbf S$ is constraint matrix (Baraff98 chapter 5.1)&#xD;&#xA;&#xD;&#xA; - $\frac{\partial \mathbf f}{\partial \mathbf v}$ and $\frac{\partial \mathbf f}{\partial \mathbf x}$ are force derivatives, which are symmetrical matrices&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;3. solve the PDE&#xD;&#xA;&#xD;&#xA;The paper solves the aforementioned PDE by **Modified Preconditioning Conjugate Gradient Method** (Baraff98 chapter 5.2) for $\Delta \mathbf v$, then update the velocity $\mathbf v$ and position $\mathbf x$ of each particle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Questions**&#xD;&#xA;&#xD;&#xA;Solve $\mathbf A\mathbf x=\mathbf b$ with PCG method requires the matrix $\mathbf A$ to be symmetrical and positive-definite, where according to the aforementioned PDE, $\mathbf A = (\mathbf I - h\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf v} - h^2\mathbf M^{-1} \mathbf S\frac{\partial \mathbf f}{\partial \mathbf x})$.&#xD;&#xA;&#xD;&#xA;1. symmentrical&#xD;&#xA;&#xD;&#xA;In block view: treat $\mathbf A$ as an $N\times N$ block matrix, $\mathbf M^{-1}$ and $\mathbf S$ are both block diagonal matrices, makes $\mathbf A$ a block symmetrical matrix. While in normal view: $\mathbf A$ as $3N\times 3N$ matrix, $\mathbf S$ is symmetrical, but product of $\mathbf M^{-1} \mathbf S$ and $\frac{\partial \mathbf f}{\partial \mathbf v}$ (or $\frac{\partial \mathbf f}{\partial \mathbf x}$) makes $\mathbf A$ not symmetrical. &#xD;&#xA;&#xD;&#xA;**Question 1**: should I treat $\mathbf A\mathbf x=\mathbf b$ as a block matrix rather than normal matrix? If not, how to make $\mathbf A$ symmetrical?&#xD;&#xA;&#xD;&#xA;I then modified the PDE as $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$, $\mathbf A^T\mathbf A$ is symmetrical.&#xD;&#xA;&#xD;&#xA;**Question 2**: How to make the `fliter` procedure (Baraff98 chapter 5.3) compatible with $\mathbf A^T\mathbf A\mathbf x=\mathbf A^T\mathbf b$?&#xD;&#xA;&#xD;&#xA;2. positive-definite&#xD;&#xA;&#xD;&#xA;The blocks $\mathbf S_i$ in $\mathbf S$ may become zero block when $ndof(i) = 0$, which makes $\mathbf A^T\mathbf A$ a positive-semidefinite matrix. To apply PCG method, according to Baraff98 chapter 5.3:&#xD;&#xA;&#xD;&#xA;&gt; The CG method (technically, the preconditioned CG method) takes a symmetric **positive semi-definite** matrix $\mathbf A$, a **symmetric positive definite** preconditioning matrix $\mathbf P$ of the same dimension as $\mathbf A$ ,a vector $\mathbf b$ and iteratively solves $\mathbf A \Delta \mathbf v = \mathbf b$.&#xD;&#xA;&#xD;&#xA;**Question 3**: How to find the symmetrical and positive-definite preconditioning matrix $\mathbf P$, with $\mathbf A^T\mathbf A$ symmetrical and semi PD?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Some docs I also refered:&#xD;&#xA;&#xD;&#xA; - [On the modified conjugate gradient method in cloth simulation](http://www.cs.ubc.ca/~ascher/papers/ab.pdf)&#xD;&#xA; - [freecloth](http://davidpritchard.org/freecloth/docs/report-single/)&#xD;&#xA; - [Cloth Simulation slides](http://cg.informatik.uni-freiburg.de/course_notes/sim_03_cloth1.pdf)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4521" PostHistoryTypeId="5" PostId="2037" RevisionGUID="af404590-20e0-47aa-8767-a84786a49301" CreationDate="2016-02-13T11:12:12.727" UserId="2646" Comment="deleted 66 characters in body" Text="I am attempting to model a simple graphics pipeline (i.e. Local-&gt;Word-&gt;View-&gt;Screen-&gt;2D spaces).&#xD;&#xA;&#xD;&#xA;I've been looking at the algorithm required to transform from world to view-space and using the following transform[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Although I have been using U,V,N,C notation rather than Xc,Yc,Zc,e.&#xD;&#xA;&#xD;&#xA;And my matrix transformation at first glance, appears correct: When I plot the vectors onto world space, I get a vector from the camera position to the point we're looking at, and two correctly placed new X and Y vectors (see the left hand image below).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;By looking along the line of sight vector (such that it disappears,and the focus &amp; camera points overlap), as in the middle figure, should (I believe?) give an accurate example of what the resultant viewspace transformation should look like, with the green vertical and right-pointing vectors showing the new X &amp; Y vectors.&#xD;&#xA;&#xD;&#xA;However - when I actually do the view space transform I don't get the middle figure, instead, the resultant transform seems to be looking at the object from a different position possibly aligned with one of the axes? This is shown in the right hand figure - which is actually looking at the object from a slightly lower perspective &#xD;&#xA;&#xD;&#xA;My question is essentially what have I done wrong, or am I misunderstanding both the transform and thus my results?&#xD;&#xA;&#xD;&#xA;Thanks very much,&#xD;&#xA;&#xD;&#xA;David&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATES**&#xD;&#xA;&#xD;&#xA;After stepping through the code - I discovered that my [source][3] book was having me convert the line-of-sight vector to spherical coords and then they were being converted straight back again to create R (viewspace coordination matrix). I've eliminated this redundancy (and potential source of errors) but it hasn't solved the problem...&#xD;&#xA;&#xD;&#xA;    clear; clc; close all;&#xD;&#xA;    %======Create World Space (hard-coded values for demo) ===========&#xD;&#xA;    ws_vtx = [0,2,0,2,1,0.5,1.5,0.5,1.5,0.5,1.5,0.5,1.5;&#xD;&#xA;        0,0,0,0,-2,0,0,2,2,0,0,2,2;&#xD;&#xA;        0,0,2,2,1,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5];&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    %==================Create view matrix===================&#xD;&#xA;    focus = [1.5,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Position of camera&#xD;&#xA;    Vspec = [0;0;1]; %Specified up direction for view space (i.e. camera orientation)&#xD;&#xA;    vector = focus - [Cx,Cy,Cz]; %Vector camera to focus point &#xD;&#xA;    p = sqrt(vector(1)^2 + vector(2)^2 + vector(3)^2); %Total magnitude of vector&#xD;&#xA;    N = vector'/p;&#xD;&#xA;    V = Vspec - cross(cross(Vspec,N),N); %Create new &quot;up&quot; direction&#xD;&#xA;    U = cross(N,V); %Create new x-axis&#xD;&#xA;    %Create rotational matrix to view space&#xD;&#xA;    R= [U(1),U(2),U(3),0; % U is direction of camera space X axis&#xD;&#xA;        V(1),V(2),V(3),0; % V is direction of camera space Y axis&#xD;&#xA;        N(1),N(2),N(3),0;&#xD;&#xA;        0   ,   0,   0,1];&#xD;&#xA;    Tr = [1,0,0,-Cx;&#xD;&#xA;          0,1,0,-Cy;&#xD;&#xA;          0,0,1,-Cz;&#xD;&#xA;          0,0,0,  1];&#xD;&#xA;    T = R*Tr; %Total view transform = rotation * translation&#xD;&#xA;    %============Plot the camera vectors &amp; World Space=================&#xD;&#xA;    grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(Cx,Cy,Cz,'s'); %Plot the camera position&#xD;&#xA;    plot3([Cx, Cx+p*N(1)],[Cy, Cy+p*N(2)],[Cz, Cz+p*N(3)],'g'); %Plot camera vectors&#xD;&#xA;    plot3([Cx, Cx+V(1)],[Cy, Cy+V(2)],[Cz, Cz+V(3)],'g');&#xD;&#xA;    plot3([Cx, Cx+U(1)],[Cy, Cy+U(2)],[Cz, Cz+U(3)],'g');&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)) %Plot all the points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none');&#xD;&#xA;    for i = 1:length(ws_vtx)&#xD;&#xA;        str = sprintf('%d',i);&#xD;&#xA;        text(ws_vtx(1,i),ws_vtx(2,i),ws_vtx(3,i), str,'FontSize',14, 'Color','r');&#xD;&#xA;    end&#xD;&#xA;    %====================Viewspace Transform===========================&#xD;&#xA;    ws_vtx = T*vertcat(ws_vtx,(ones(1,length(ws_vtx)))); %Transform worldspace&#xD;&#xA;    ws_vtx = ws_vtx(1:3,:); %Remove homogenous column&#xD;&#xA;    position = T*[Cx;Cy;Cz;1]; focus = T*horzcat(focus,1)'; %Transform set points&#xD;&#xA;    position = position(1:3,:); focus = focus(1:3,:); %Remove homogenous columns&#xD;&#xA;    %================Plot new viewspace===============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s'); %Plot new camera vectors&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],...&#xD;&#xA;        [position(2); position(2)+focus(2)],[position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'none');&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NKmCc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RavTO.png&#xD;&#xA;  [3]: https://books.google.co.uk/books/about/3D_Computer_Graphics.html?id=tQJEAQAAIAAJ&amp;redir_esc=y" ContentLicense="CC BY-SA 3.0" />
  <row Id="4522" PostHistoryTypeId="2" PostId="2041" RevisionGUID="c62ab46d-5e9b-44eb-990f-d1207da47928" CreationDate="2016-02-13T21:08:08.733" UserDisplayName="user2500" Text="Open GL and other graphics APIs support floating point formats smaller than 32 bits (e.g. see https://www.opengl.org/wiki/Small_Float_Formats). While GPUs seem to handle these formats natively, CPUs have limited support (x86 architecture chips can convert to/from 16 bit floats using the AVX instructions). It is sometimes convenient to pack/unpack these formats on the CPU , but it is not obvious how to do so efficiently.&#xD;&#xA;&#xD;&#xA;What are the fastest techniques to convert between 32 bit floating point and the small float formats on the CPU? Are libraries or sample implementations available?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4523" PostHistoryTypeId="1" PostId="2041" RevisionGUID="c62ab46d-5e9b-44eb-990f-d1207da47928" CreationDate="2016-02-13T21:08:08.733" UserDisplayName="user2500" Text="What are the most efficient ways to convert between f32 and smaller float formats on the CPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4524" PostHistoryTypeId="3" PostId="2041" RevisionGUID="c62ab46d-5e9b-44eb-990f-d1207da47928" CreationDate="2016-02-13T21:08:08.733" UserDisplayName="user2500" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4525" PostHistoryTypeId="2" PostId="2042" RevisionGUID="1704e063-e064-409b-bc64-ab118c2a45bf" CreationDate="2016-02-13T22:37:18.643" UserId="2684" Text="I'm reading Cook's paper &quot;Stochastic Sampling and Distributed Ray Tracing&quot;, I don't understand how the rays are generated. He says:&#xD;&#xA;&#xD;&#xA;&gt; Determine the focal point by constructing a ray from the eye point&#xD;&#xA;&gt; (center of the lens) through the screen location of the ray. The focal&#xD;&#xA;&gt; point is located on this ray so its distance from the eye point is&#xD;&#xA;&gt; equal to the focal distance.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I can't pass this image, where my screen plane is located according to this image, what is the focal point, if you see some optics picture of thin lens, the focal point is always in the same place, where all the rays converge, if it is always the same point, why do have i to calculate it for each ray?&#xD;&#xA;&#xD;&#xA;ps: computer-graphics and ray-tracing tags are forbidden for new users, this must be revised.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mxQ6c.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4526" PostHistoryTypeId="1" PostId="2042" RevisionGUID="1704e063-e064-409b-bc64-ab118c2a45bf" CreationDate="2016-02-13T22:37:18.643" UserId="2684" Text="Ray tracing with thin lens camera" ContentLicense="CC BY-SA 3.0" />
  <row Id="4527" PostHistoryTypeId="3" PostId="2042" RevisionGUID="1704e063-e064-409b-bc64-ab118c2a45bf" CreationDate="2016-02-13T22:37:18.643" UserId="2684" Text="|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4528" PostHistoryTypeId="6" PostId="2042" RevisionGUID="d8a75832-b671-44fa-aaf8-6c6d4cf31a38" CreationDate="2016-02-14T00:51:39.427" UserId="2684" Comment="edited tags" Text="|raytracing|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4529" PostHistoryTypeId="5" PostId="2042" RevisionGUID="e191a003-1b3a-40b1-92b4-e3284882d024" CreationDate="2016-02-14T01:00:16.963" UserId="231" Comment="Remove reference to tag issue which has been resolved" Text="I'm reading Cook's paper &quot;Stochastic Sampling and Distributed Ray Tracing&quot;, I don't understand how the rays are generated. He says:&#xD;&#xA;&#xD;&#xA;&gt; Determine the focal point by constructing a ray from the eye point&#xD;&#xA;&gt; (center of the lens) through the screen location of the ray. The focal&#xD;&#xA;&gt; point is located on this ray so its distance from the eye point is&#xD;&#xA;&gt; equal to the focal distance.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I can't parse this image. Where is my screen plane located according to this image? What is the focal point? If you see some optics picture of a thin lens, the focal point is always in the same place, where all the rays converge. If it is always the same point, why do have I to calculate it for each ray?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mxQ6c.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4530" PostHistoryTypeId="2" PostId="2043" RevisionGUID="ea9dc782-f9ca-4385-b02b-8857fd3070e9" CreationDate="2016-02-14T07:51:07.610" UserId="2687" Text="The title says it all, What is the benefit using Half Edge over Winged Edge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4531" PostHistoryTypeId="1" PostId="2043" RevisionGUID="ea9dc782-f9ca-4385-b02b-8857fd3070e9" CreationDate="2016-02-14T07:51:07.610" UserId="2687" Text="What is the benefit using Half Edge over Winged Edge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4532" PostHistoryTypeId="3" PostId="2043" RevisionGUID="ea9dc782-f9ca-4385-b02b-8857fd3070e9" CreationDate="2016-02-14T07:51:07.610" UserId="2687" Text="|data-structure|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4533" PostHistoryTypeId="6" PostId="2043" RevisionGUID="7b6fe57d-bd6d-43b4-bd3a-4ca54bcec7d2" CreationDate="2016-02-14T14:33:50.697" UserId="16" Comment="edited tags" Text="|mesh|polygon|data-structure|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4534" PostHistoryTypeId="2" PostId="2044" RevisionGUID="53bbba04-beb1-42ed-827f-c98da16dd14e" CreationDate="2016-02-14T16:54:51.157" UserDisplayName="user2500" Text="Generally, in ray tracing, light paths are traced backward from the image plane into the scene; the digram suggests modeling the optics explicitly to capture certain effects (in this case, depth-of-field).  Note the diagram uses the term &quot;film plane&quot; instead of image plane or screen plane, as the diagram models a camera when film use was common, before high quality CCDs were available.&#xD;&#xA;&#xD;&#xA;In this case, interaction with the lens implies the focal point: all paths originating from the same point on the image plane will converge at the focal point (assuming the paths first intersect the lens - note the diagram does not show an aperture, which would block paths that don't) - but paths are not coincident from the lens and diverge beyond the focal point - so they intersect the scene at different locations nearer and further than the focal point. The variation in scene intersection locations, given the same origin on the image plane (and therefore contributing to the same pixel in the computed image), is what gives the depth of field effect - i.e. something looking like circular blur outside of the plane of focus. Other effects are possible here, such as anti-aliasing by varying the origin of rays across a pixel's area in the image plane." ContentLicense="CC BY-SA 3.0" />
  <row Id="4535" PostHistoryTypeId="2" PostId="2045" RevisionGUID="bf9bd5be-2438-4508-89fd-bdf8026e86e6" CreationDate="2016-02-14T20:02:18.807" UserId="93" Text="You definitely want to check out meticulous half to float and float to half implementations by Fabian Giesen. I don't think there is anything faster than those:&#xD;&#xA;https://gist.github.com/rygorous/2144712&#xD;&#xA;https://gist.github.com/rygorous/2156668" ContentLicense="CC BY-SA 3.0" />
  <row Id="4536" PostHistoryTypeId="5" PostId="2043" RevisionGUID="99855a30-ffbe-4b04-bb68-c0359ef6c03a" CreationDate="2016-02-15T01:18:36.103" UserId="2687" Comment="deleted 3 characters in body" Text="For polygonal mesh, what is the benefit using Half Edge over Winged Edge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4537" PostHistoryTypeId="5" PostId="2044" RevisionGUID="7b8165f4-c2ef-4498-a73e-85603ba84736" CreationDate="2016-02-15T02:20:39.040" UserDisplayName="user2500" Comment="deleted 600 characters in body" Text="Instead of a screen plane in front of the eye, it describes a film plane, where the image is projected, to explicitly model camera optics. You don't need to compute the focal point in doing ray tracing - it's just a way to find the plane of focus for depth of field effects.&#xD;&#xA;&#xD;&#xA;For depth of field effects I use a standard perspective projection but jitter the position of the eye on a circle parallel to the focal plane -  and I make sure all my rays for a given pixel go through the same spot on the focal plane making it sharp while stuff in front of or behind that plane ends up blurry. It's a simple model of something like an aperture, and gives pretty good results." ContentLicense="CC BY-SA 3.0" />
  <row Id="4539" PostHistoryTypeId="5" PostId="2043" RevisionGUID="e546edbe-a811-4f34-8787-2454ca5f4618" CreationDate="2016-02-15T07:46:47.183" UserId="2687" Comment="added 3 characters in body" Text="For polygonal mesh, what is the benefit of using Half Edge over Winged Edge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4540" PostHistoryTypeId="5" PostId="2045" RevisionGUID="6d5cb8b1-c89a-439c-b102-e43b4c5345ff" CreationDate="2016-02-15T08:23:19.190" UserId="93" Comment="added 304 characters in body" Text="You definitely want to check out meticulous half to float and float to half implementations by Fabian Giesen. I don't think there is anything faster than those:&#xD;&#xA;https://gist.github.com/rygorous/2144712&#xD;&#xA;https://gist.github.com/rygorous/2156668&#xD;&#xA;&#xD;&#xA;For other formats you will find an implementation in DirectXMath (part of WindowsSDK), Mesa and similar libraries. For example, R11G11B10_Float conversions are implemented by DirectXMath in [XMFLOAT3PK][1] and by Mesa in [u_format_other.c][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xmfloat3pk(v=vs.85).aspx&#xD;&#xA;  [2]: https://github.com/laanwj/etna_viv/blob/master/src/minigallium/auxiliary/util/u_format_other.c" ContentLicense="CC BY-SA 3.0" />
  <row Id="4541" PostHistoryTypeId="5" PostId="2043" RevisionGUID="3c3069ed-7d3a-42be-af8d-cf6741916c7b" CreationDate="2016-02-15T08:57:06.117" UserId="2687" Comment="added 283 characters in body" Text="For mesh representation, what is the benefit of using Half Edge over Winged Edge data structure?&#xD;&#xA;&#xD;&#xA;I understand both mesh representations, the only difference is that half edge uses directional edge and winged edge uses undirectional edge. So far, I cannot think of what is the usefulness of using directional edge, yet it only gives more memory consumption." ContentLicense="CC BY-SA 3.0" />
  <row Id="4542" PostHistoryTypeId="4" PostId="2043" RevisionGUID="abed0f0d-c425-4369-860f-a9eb80625687" CreationDate="2016-02-15T09:16:27.533" UserId="2687" Comment="edited title" Text="What is the benefit of using Half Edge over Winged Edge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4543" PostHistoryTypeId="33" PostId="2037" RevisionGUID="a327957a-2c3d-4a5c-8237-715d7ee3e5f6" CreationDate="2016-02-15T09:27:58.723" UserId="2646" Comment="13" />
  <row Id="4544" PostHistoryTypeId="2" PostId="2046" RevisionGUID="7a1d1e39-b6df-49c8-98b9-4cc8062613de" CreationDate="2016-02-15T11:08:29.323" UserId="2694" Text="In the program I need to create the user should specify the hull geometry of aircraft wing and fuselage using cubic bezier polycurves. &#xD;&#xA;But to get to `m` bezier patch surfaces the user would need to introduce `4 * m` additional control points. It's not as simple task as outlining sections in Inkscape. &#xD;&#xA;&#xD;&#xA;So the question is whether there is a way to create bicubic bezier surface having only its edge curves (or maybe any additional curves user could draw) ? &#xD;&#xA;&#xD;&#xA;If the answer is no, what way would you suggest to create hull geometry (maybe a bit rough) from other 3D model? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4545" PostHistoryTypeId="1" PostId="2046" RevisionGUID="7a1d1e39-b6df-49c8-98b9-4cc8062613de" CreationDate="2016-02-15T11:08:29.323" UserId="2694" Text="Bicubic bezier surface from 4 bezier curves" ContentLicense="CC BY-SA 3.0" />
  <row Id="4546" PostHistoryTypeId="3" PostId="2046" RevisionGUID="7a1d1e39-b6df-49c8-98b9-4cc8062613de" CreationDate="2016-02-15T11:08:29.323" UserId="2694" Text="|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4547" PostHistoryTypeId="5" PostId="2046" RevisionGUID="b50d844e-cef0-4d01-b9aa-6aa3ab41fdfa" CreationDate="2016-02-15T11:14:28.393" UserId="2694" Comment="Added question about other ways to create model with curves" Text="In the program I need to create the user should specify the hull geometry of aircraft wing and fuselage using cubic bezier polycurves. &#xD;&#xA;But to get to `m` bezier patch surfaces the user would need to introduce `4 * m` additional control points. It's not as simple task as outlining sections in Inkscape. &#xD;&#xA;&#xD;&#xA;So the question is whether there is a way to create bicubic bezier surface having only its edge curves (or maybe any additional curves user could draw) ? &#xD;&#xA;&#xD;&#xA;If it isn't possible with bezier curves, is there any way to create 3d model with specifying only section curves? &#xD;&#xA;&#xD;&#xA;If the answer is no, what way would you suggest to create hull geometry (maybe a bit rough) from other 3D model? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4548" PostHistoryTypeId="2" PostId="2047" RevisionGUID="b342a975-ebf1-4096-a02a-ed4fea0b27da" CreationDate="2016-02-15T13:39:47.217" UserDisplayName="user2500" Text="To transform from world to eye coordinates, I use a &quot;lookat&quot; transform, defined by 3 vectors: $\bf{e}$, $\bf{a}$ and $\bf{u}$; in english, the eye position, the point it's looking at, and an up vector, which must not be in the same direction as $\bf{a} - \bf{e}$ (more specifically, not a multiple of it). I'm not sure how the notation given would translate, but I use these to define an orthonormal space around the eye and project into it.&#xD;&#xA;&#xD;&#xA;The space is defined using $\bf{z} = {{(\bf{e} - \bf{a})}\over{|\bf{e} - \bf{a}}|}$, which means the negative z axis points in the direction of what I'm looking at (this works well for OpenGL); $\bf{x} = {{\bf{u} \times \bf{z}}\over{|\bf{u} \times \bf{z}|}}$ and $\bf{y} = \bf{z} \times \bf{x}$, which, again, for OpenGL, makes $\bf{x}$ rightward on the screen and $\bf{y}$ upward.&#xD;&#xA;&#xD;&#xA;To transform into eye coordinates is a matter of subtracting they eye's position, then projecting into the space defined by the vectors above:&#xD;&#xA;&#xD;&#xA; $$\begin{bmatrix} \bf{x}_x &amp; \bf{x}_y &amp; \bf{x}_z &amp; 0 \\ \bf{y}_x &amp; \bf{y}_y &amp; \bf{y}_z &amp; 0 \\ \bf{z}_x &amp; \bf{z}_y &amp; \bf{z}_z &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}\begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; -\bf{e}_x \\ 0 &amp; 1 &amp; 0 &amp; -\bf{e}_y \\ 0 &amp; 0 &amp; 1 &amp; -\bf{e}_z \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix} $$" ContentLicense="CC BY-SA 3.0" />
  <row Id="4549" PostHistoryTypeId="2" PostId="2048" RevisionGUID="884a2f8f-10c3-4341-8fcf-5104db543478" CreationDate="2016-02-15T17:23:09.787" UserId="38" Text="Yes, its pretty standard stuff. Most 3D applications our there can do this. Since the nomenclature of 3d applications is not standardized, the tool has different names in different applications: Loft (Maya, 3DSMax), Blend (Creo, Catia...) and so on.&#xD;&#xA;&#xD;&#xA;[![Blend][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Blend between 3 curves, not closed but same principle applies. Open curves are easier as they clearly define the boundary conditions. (software used is Creo because that's what I had open)&#xD;&#xA;&#xD;&#xA;You usually want the first edge be from a surface edge because otherwise you will lose the tangency info. But nothing prevents you from using a natural tangent direction, you just lose control. Also you need to pay attention to how you intend the curves to connect (what point connects to what point).&#xD;&#xA;&#xD;&#xA;Personally I prefer drawing the hull or using some of the network based tools. This way allow you to specify control curves in 2 directions, thus giving control of what to connect where and how it should work mid run.&#xD;&#xA;&#xD;&#xA;[![Image 2][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Curve network.&#xD;&#xA;&#xD;&#xA;There are many ways to do this, infinite ways in fact. Also if you want to be compatible with other mainstream CAD apps use NURBS instead of beziers than its easier for you to write a exporter/importer if your data set is rich enough. Beziers are just special cases of NURBS after all so your code itself should not need to change all that much (fitting also gets easier).&#xD;&#xA;&#xD;&#xA;What you do is simply fit a curve trough your points in the second direction this will then give you the corresponding hull in the other direction. In your case you could just make a Bezier patch for each segment and then try to deduce a natural tangent direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zeKrH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Qm5Bk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4550" PostHistoryTypeId="2" PostId="2049" RevisionGUID="4a877940-1e9d-4102-ad98-b01b9673a843" CreationDate="2016-02-15T18:47:24.553" UserId="2646" Text="I'm looking into the graphics pipeline processes and at the moment in particular, perspective projection matrices.&#xD;&#xA;&#xD;&#xA;After looking in several different sources, and across the breadth of previous questions such as http://stackoverflow.com/questions/25659623/how-does-a-projection-matrix-work, I've found that most solutions seem to use the following two matrices;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;So far, I've been expecting these matrices to take the view frustum and convert it into a unit sized cube - however this doesn't seem to be happening.&#xD;&#xA;&#xD;&#xA;Taking the left matrix first (which I attempted to use first), I assumed the parameters were as such;&#xD;&#xA;&#xD;&#xA;n/f = **z** value of near and far planes&#xD;&#xA;&#xD;&#xA;r/l = **x** values of left and right planes&#xD;&#xA;&#xD;&#xA;t/b = **y** values of top and bottom planes&#xD;&#xA;&#xD;&#xA;For the right hand matrix, my book is very vague, and the only parameters that seem to fit are&#xD;&#xA;&#xD;&#xA;d/f - distances to near/far planes (but not necessarily the **z** values?)&#xD;&#xA;h - height of the near clip plane.&#xD;&#xA;&#xD;&#xA;My initial method of experimentation has been to plot the vertices of the frustum and using the transforms get a resultant that the X, Y values can be used to display the image in 2D and with Z values that can be used to decide what polygons overlay others.&#xD;&#xA;&#xD;&#xA;However, whilst I've been expecting a cube with dimensions of 1 -&gt; -1 along all axes, instead I've been getting just an inverted frustrum.&#xD;&#xA;&#xD;&#xA;I feel I'm either making an elementary mistake or am missing something key - would appreciate any help in clearing up both my uncertainties in what I need to do to convert my shape from the 3D to the 2D, and what I should be expecting. So far, my results are below. &#xD;&#xA;&#xD;&#xA;The left hand picture shows the shape in a view frustum - and the right shows the original frustum and transformed frustum in green after applying the perspective transform which I believe should be transformed to a unit sized cube and not just a reflected frustum.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I've put my code below, and tried to simplify it as much as possible to make it easier to evaluate!. Thanks very much!&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %======Create View Space (hard-coded values for demo) &amp; Plot  ===========&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    ws_vtx = [-2.4495,0.8165,-2.4495,0.8165,-2.4495,-1.633,0,0,1.633,-1.633,0,0,1.633;&#xD;&#xA;        -4,-13/3,-1/3,-2/3,-3,-19/6,-10/3,-2.5,-8/3,-4/3,-1.5,-2/3,-5/6;&#xD;&#xA;        4.899,4.0825,4.0825,3.266,2.4495,4.4907,4.0825,6.1237,5.7155,4.0825,3.6742,5.7155,5.3072];&#xD;&#xA;    &#xD;&#xA;    position = [0;0;0;1]; focus = [0;-1.5;3.6742]; %Transformed set points&#xD;&#xA;    &#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s');&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],[position(2); position(2)+focus(2)],...&#xD;&#xA;        [position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.1);&#xD;&#xA;    %====================Create View Volume===========================&#xD;&#xA;    asp_rat = 0.75; %Most displays arent square&#xD;&#xA;    focus = focus/norm(focus); %Normalise focus vector&#xD;&#xA;    nheight = 1; %height of near clip plane&#xD;&#xA;    hoz_angle = 2*pi/3;&#xD;&#xA;    ndistance = 1/tan(hoz_angle/2); %distance of near view plane from origin&#xD;&#xA;    fdistance = 5.5; %Define a far distance&#xD;&#xA;    &#xD;&#xA;    nc = ndistance*focus; %Centre point is focus vector * distance&#xD;&#xA;    ntr = nc + [asp_rat*nheight; nheight; 0]; %Go from centre to TL corner&#xD;&#xA;    nbr = ntr + [0; -2*nheight;0]; %Go down 2* height to bottom&#xD;&#xA;    nbl = nbr + [-2*asp_rat*nheight; 0; 0];&#xD;&#xA;    ntl = nbl + [0; 2*nheight;0];&#xD;&#xA;    nr_plan = [ntr, nbr, nbl, ntl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    fc = fdistance*focus;&#xD;&#xA;    fheight = tan(hoz_angle/2)*fdistance; %Find far plane height by trig&#xD;&#xA;    ftr = fc + [asp_rat*fheight; fheight; 0]; %Go from centre to TL corner&#xD;&#xA;    fbr = ftr + [0; -2*fheight;0]; %Go down 2* height to bottom&#xD;&#xA;    fbl = fbr + [-2*asp_rat*fheight; 0; 0];&#xD;&#xA;    ftl = fbl + [0; 2*fheight;0];&#xD;&#xA;    fr_plan = [ftr, fbr, fbl, ftl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    frust_vtx = horzcat(nr_plan, fr_plan); %Create frustum vertex array&#xD;&#xA;    frust_fcs = [1,8,5,6,4,5;  %Faces defined with normals inwards&#xD;&#xA;                 4,5,1,2,8,8;&#xD;&#xA;                 3,6,2,3,7,4;&#xD;&#xA;                 2,7,6,7,3,1];&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %=============Create Perspective Matrix ==============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot orig frustrum &#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    &#xD;&#xA;    left = nc(1) - asp_rat*nheight; %Get values for projection matrix&#xD;&#xA;    right = nc(1) + asp_rat*nheight;&#xD;&#xA;    top = nc(2) + nheight;&#xD;&#xA;    bottom = nc(2) -nheight;&#xD;&#xA;    near = ndistance;&#xD;&#xA;    far = fdistance;&#xD;&#xA;    &#xD;&#xA;    proj_mat = [2*near/(right - left),0,(right + left)/(right - left),0;&#xD;&#xA;        0, 2*near/(top-bottom),(top+bottom)/(top-bottom),0;&#xD;&#xA;        0,0, -(far+near)/(far-near), -2*far*near/(far-near);&#xD;&#xA;        0,0,-1,0];&#xD;&#xA;    %====================Perspective Projection Transformation=============&#xD;&#xA;    frust_vtx = proj_mat*vertcat(frust_vtx,(ones(1,length(frust_vtx)))); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/adExB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EG3Iu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/QdM63.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4551" PostHistoryTypeId="1" PostId="2049" RevisionGUID="4a877940-1e9d-4102-ad98-b01b9673a843" CreationDate="2016-02-15T18:47:24.553" UserId="2646" Text="Choosing &amp; Using a Projection Matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="4552" PostHistoryTypeId="3" PostId="2049" RevisionGUID="4a877940-1e9d-4102-ad98-b01b9673a843" CreationDate="2016-02-15T18:47:24.553" UserId="2646" Text="|transformations|3d|vector-graphics|matrix|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4553" PostHistoryTypeId="2" PostId="2050" RevisionGUID="6a05e7b0-639f-477c-946e-52e59cde1414" CreationDate="2016-02-15T21:30:17.253" UserId="2695" Text="Baraff and Witkin propose to incorporate constraints by modifying the linear system by the constraints matrices $\mathbf S_i$. As they state in the beginning of Section 5.2, the resulting system is not symmetric anymore. Therefore, the modified linear system must be computed with a linear solver that can treat non-symmetric systems (as - if I got you correctly - you proposed with the normal matrix $\mathbf A^T \mathbf A$). However, Baraff and Witkin introduce the modified conjugate gradient method, which is a variant of the original conjugate gradient method, that computes a solution of the initial linear system with considering the constraints at the same time, without the need to take care of the non-symmetry. In their paper they do not solve the normal equations ($\mathbf A^T \mathbf A$), but rather the original system $\mathbf A \Delta \mathbf v = \mathbf b$, so your questions ask something which is beyond of the paper." ContentLicense="CC BY-SA 3.0" />
  <row Id="4554" PostHistoryTypeId="5" PostId="2049" RevisionGUID="5c4e0f9b-5f2a-4bd2-8752-ff6e1ff4ff92" CreationDate="2016-02-15T22:16:39.513" UserId="2646" Comment="Edited code to reflect most recent updates" Text="I'm looking into the graphics pipeline processes and at the moment in particular, perspective projection matrices.&#xD;&#xA;&#xD;&#xA;After looking in several different sources, and across the breadth of previous questions such as http://stackoverflow.com/questions/25659623/how-does-a-projection-matrix-work, I've found that most solutions seem to use the following two matrices;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;So far, I've been expecting these matrices to take the view frustum and convert it into a unit sized cube - however this doesn't seem to be happening.&#xD;&#xA;&#xD;&#xA;Taking the left matrix first (which I attempted to use first), I assumed the parameters were as such;&#xD;&#xA;&#xD;&#xA;n/f = **z** value of near and far planes&#xD;&#xA;&#xD;&#xA;r/l = **x** values of left and right planes&#xD;&#xA;&#xD;&#xA;t/b = **y** values of top and bottom planes&#xD;&#xA;&#xD;&#xA;For the right hand matrix, my book is very vague, and the only parameters that seem to fit are&#xD;&#xA;&#xD;&#xA;d/f - distances to near/far planes (but not necessarily the **z** values?)&#xD;&#xA;h - height of the near clip plane.&#xD;&#xA;&#xD;&#xA;My initial method of experimentation has been to plot the vertices of the frustum and using the transforms get a resultant that the X, Y values can be used to display the image in 2D and with Z values that can be used to decide what polygons overlay others.&#xD;&#xA;&#xD;&#xA;However, whilst I've been expecting a cube with dimensions of 1 -&gt; -1 along all axes, instead I've been getting just an inverted frustrum.&#xD;&#xA;&#xD;&#xA;I feel I'm either making an elementary mistake or am missing something key - would appreciate any help in clearing up both my uncertainties in what I need to do to convert my shape from the 3D to the 2D, and what I should be expecting. So far, my results are below. &#xD;&#xA;&#xD;&#xA;The left hand picture shows the shape in a view frustum - and the right shows the original frustum and transformed frustum in green after applying the perspective transform which I believe should be transformed to a unit sized cube and not just a reflected frustum.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I've put my code below, and tried to simplify it as much as possible to make it easier to evaluate!. Thanks very much!&#xD;&#xA;&#xD;&#xA;**Updates**&#xD;&#xA;I've updated my coordinates for view space coordinates - using a different method generates view space coordinates that go 'back' towards negative z values. Not sure if that makes it more correct but I hope it helps (but as per the comment).&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %======Create View Space (hard-coded values for demo) &amp; Plot  ===========&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    ws_vtx = [-1.3416,0.4472,-1.3416,0.4472,-1.3416,-0.8944,0,0,0.8944,-0.8944,0,0,0.8944;&#xD;&#xA;              -1.0954,-1.4606,0.7303,0.3651,-1.0954,-0.7303,-0.9129,0,-0.1826,0.1826,0,0.9129,0.7303;&#xD;&#xA;              -4.899,-4.0825,-4.0825,-3.266,-2.4495,-4.4907,-4.0825,-6.1237,-5.7155,-4.0825,-3.6742,-5.7155,-5.3072];&#xD;&#xA;    &#xD;&#xA;    position = [0;0;0;1]; focus = [0;0;-3.6742]; %Transformed set points&#xD;&#xA;    &#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s');&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],[position(2); position(2)+focus(2)],...&#xD;&#xA;        [position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.1);&#xD;&#xA;    %====================Create View Volume===========================&#xD;&#xA;    asp_rat = 0.75; %Most displays arent square&#xD;&#xA;    focus = focus/norm(focus); %Normalise focus vector&#xD;&#xA;    nheight = 1; %height of near clip plane&#xD;&#xA;    hoz_angle = 2*pi/3;&#xD;&#xA;    ndistance = 1/tan(hoz_angle/2); %distance of near view plane from origin&#xD;&#xA;    fdistance = 5.5; %Define a far distance&#xD;&#xA;    &#xD;&#xA;    nc = ndistance*focus; %Centre point is focus vector * distance&#xD;&#xA;    ntr = nc + [asp_rat*nheight; nheight; 0]; %Go from centre to TL corner&#xD;&#xA;    nbr = ntr + [0; -2*nheight;0]; %Go down 2* height to bottom&#xD;&#xA;    nbl = nbr + [-2*asp_rat*nheight; 0; 0];&#xD;&#xA;    ntl = nbl + [0; 2*nheight;0];&#xD;&#xA;    nr_plan = [ntr, nbr, nbl, ntl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    fc = fdistance*focus;&#xD;&#xA;    fheight = tan(hoz_angle/2)*fdistance; %Find far plane height by trig&#xD;&#xA;    ftr = fc + [asp_rat*fheight; fheight; 0]; %Go from centre to TL corner&#xD;&#xA;    fbr = ftr + [0; -2*fheight;0]; %Go down 2* height to bottom&#xD;&#xA;    fbl = fbr + [-2*asp_rat*fheight; 0; 0];&#xD;&#xA;    ftl = fbl + [0; 2*fheight;0];&#xD;&#xA;    fr_plan = [ftr, fbr, fbl, ftl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    frust_vtx = horzcat(nr_plan, fr_plan); %Create frustum vertex array&#xD;&#xA;    frust_fcs = [1,8,5,6,4,5;  %Faces defined with normals inwards&#xD;&#xA;                 4,5,1,2,8,8;&#xD;&#xA;                 3,6,2,3,7,4;&#xD;&#xA;                 2,7,6,7,3,1];&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %=============Create Perspective Matrix ==============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot orig frustrum &#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    &#xD;&#xA;    left = nc(1) - asp_rat*nheight; %Get values for projection matrix&#xD;&#xA;    right = nc(1) + asp_rat*nheight;&#xD;&#xA;    top = nc(2) + nheight;&#xD;&#xA;    bottom = nc(2) -nheight;&#xD;&#xA;    near = ndistance;&#xD;&#xA;    far = fdistance;&#xD;&#xA;    &#xD;&#xA;    proj_mat = [2*near/(right - left),0,(right + left)/(right - left),0;&#xD;&#xA;        0, 2*near/(top-bottom),(top+bottom)/(top-bottom),0;&#xD;&#xA;        0,0, -(far+near)/(far-near), -2*far*near/(far-near);&#xD;&#xA;        0,0,-1,0];&#xD;&#xA;    %====================Perspective Projection Transformation=============&#xD;&#xA;    frust_vtx = proj_mat*vertcat(frust_vtx,(ones(1,length(frust_vtx)))); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/adExB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EG3Iu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/W4xni.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4558" PostHistoryTypeId="2" PostId="2052" RevisionGUID="28d345f7-7782-44fe-a436-0be4c0d4e1ee" CreationDate="2016-02-15T23:56:58.973" UserId="48" Text="The values will only form a cube after performing the perspective divide, which I don't see happening in your code.&#xD;&#xA;&#xD;&#xA;That is, you take a vector $[x, y, z, 1]$ and transform it by the projection matrix, resulting in a new vector $[x', y', z', w']$. Then divide out the fourth component to get a 3D vector, $[x'/w', y'/w', z'/w']$. This last is the one that should be within a $[-1, 1]$ cube, if the original point was within the view frustum (and if it's an OpenGL-style projection matrix—Direct3D-style ones have $[0,1]$ for the post-projective Z range, instead of $[-1, 1]$).&#xD;&#xA;&#xD;&#xA;Without the divide by $w'$, if you just look at $[x', y', z']$, indeed you'll just get a scaled and possibly reflected frustum. Matrix multiplication alone can't transform a frustum into a cube, as it's not a linear or affine transformation; instead, it's a projective transformation, and the divide by $w'$ accomplishes that." ContentLicense="CC BY-SA 3.0" />
  <row Id="4560" PostHistoryTypeId="5" PostId="2046" RevisionGUID="faaefcac-985f-464e-8778-01c2e2307153" CreationDate="2016-02-16T01:33:33.340" UserId="231" Comment="Minor tidying. Feel free to roll back anything that changes your intent." Text="In the program I need to create, the user should specify the hull geometry of an aircraft wing and fuselage using cubic bezier polycurves. &#xD;&#xA;But to get to `m` bezier patch surfaces the user would need to introduce `4 * m` additional control points. It's not as simple a task as outlining sections in Inkscape. &#xD;&#xA;&#xD;&#xA;So the question is whether there is a way to create a bicubic bezier surface having only its edge curves (or maybe any additional curves the user could draw)? &#xD;&#xA;&#xD;&#xA;If it isn't possible with bezier curves, is there any way to create a 3d model by specifying only section curves? &#xD;&#xA;&#xD;&#xA;If the answer is no, what way would you suggest to create hull geometry (maybe a bit rough) from another 3D model? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4561" PostHistoryTypeId="5" PostId="2047" RevisionGUID="82cdb4d7-d34c-49d3-bfed-eebe34f32f34" CreationDate="2016-02-16T04:09:53.407" UserDisplayName="user2500" Comment="deleted 48 characters in body" Text="Your transform looks correct. To transform from world to eye coordinates, I I always use a &quot;lookat&quot; transform, defined by 3 vectors: $\bf{e}$, $\bf{a}$ and $\bf{u}$; in english, the eye position, the point it's looking at, and an up vector, which must not be in the same direction as $\bf{a} - \bf{e}$ (more specifically, not a multiple of it).&#xD;&#xA;&#xD;&#xA;The space is defined using $\bf{z} = {{(\bf{e} - \bf{a})}\over{|\bf{e} - \bf{a}}|}$, which means the negative z axis points in the direction of what I'm looking at (this works well for OpenGL); $\bf{x} = {{\bf{u} \times \bf{z}}\over{|\bf{u} \times \bf{z}|}}$ and $\bf{y} = \bf{z} \times \bf{x}$, which, again, for OpenGL, makes $\bf{x}$ rightward on the screen and $\bf{y}$ upward.&#xD;&#xA;&#xD;&#xA;To transform into eye coordinates is a matter of subtracting they eye's position, then projecting into the space defined by the vectors above:&#xD;&#xA;&#xD;&#xA; $$\begin{bmatrix} \bf{x}_x &amp; \bf{x}_y &amp; \bf{x}_z &amp; 0 \\ \bf{y}_x &amp; \bf{y}_y &amp; \bf{y}_z &amp; 0 \\ \bf{z}_x &amp; \bf{z}_y &amp; \bf{z}_z &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}\begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; -\bf{e}_x \\ 0 &amp; 1 &amp; 0 &amp; -\bf{e}_y \\ 0 &amp; 0 &amp; 1 &amp; -\bf{e}_z \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix} $$&#xD;&#xA;&#xD;&#xA;Which is exactly what you have to begin with." ContentLicense="CC BY-SA 3.0" />
  <row Id="4562" PostHistoryTypeId="5" PostId="2049" RevisionGUID="4cdfb8cc-372d-42f5-a842-7b9ba2292339" CreationDate="2016-02-16T10:57:52.897" UserId="2646" Comment="added 835 characters in body" Text="I'm looking into the graphics pipeline processes and at the moment in particular, perspective projection matrices.&#xD;&#xA;&#xD;&#xA;After looking in several different sources, and across the breadth of previous questions such as http://stackoverflow.com/questions/25659623/how-does-a-projection-matrix-work, I've found that most solutions seem to use the following two matrices;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;So far, I've been expecting these matrices to take the view frustum and convert it into a unit sized cube - however this doesn't seem to be happening.&#xD;&#xA;&#xD;&#xA;Taking the left matrix first (which I attempted to use first), I assumed the parameters were as such;&#xD;&#xA;&#xD;&#xA;n/f = **z** value of near and far planes&#xD;&#xA;&#xD;&#xA;r/l = **x** values of left and right planes&#xD;&#xA;&#xD;&#xA;t/b = **y** values of top and bottom planes&#xD;&#xA;&#xD;&#xA;For the right hand matrix, my book is very vague, and the only parameters that seem to fit are&#xD;&#xA;&#xD;&#xA;d/f - distances to near/far planes (but not necessarily the **z** values?)&#xD;&#xA;h - height of the near clip plane.&#xD;&#xA;&#xD;&#xA;My initial method of experimentation has been to plot the vertices of the frustum and using the transforms get a resultant that the X, Y values can be used to display the image in 2D and with Z values that can be used to decide what polygons overlay others.&#xD;&#xA;&#xD;&#xA;However, whilst I've been expecting a cube with dimensions of 1 -&gt; -1 along all axes, instead I've been getting just an inverted frustrum.&#xD;&#xA;&#xD;&#xA;I feel I'm either making an elementary mistake or am missing something key - would appreciate any help in clearing up both my uncertainties in what I need to do to convert my shape from the 3D to the 2D, and what I should be expecting. So far, my results are below. &#xD;&#xA;&#xD;&#xA;The left hand picture shows the shape in a view frustum - and the right shows the original frustum and transformed frustum in green after applying the perspective transform which I believe should be transformed to a unit sized cube and not just a reflected frustum.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I've put my code below, and tried to simplify it as much as possible to make it easier to evaluate!. Thanks very much!&#xD;&#xA;&#xD;&#xA;**Updates**&#xD;&#xA;I've updated my coordinates for view space coordinates - using a different method generates view space coordinates that go 'back' towards negative z values. Not sure if that makes it more correct but I hope it helps (but as per the comment).&#xD;&#xA;&#xD;&#xA;Following the answer below I've added an attempt to perform perspective division. I've added the following code below the main bulk. Any further recommendations would be massively appreciated&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %======Create View Space (hard-coded values for demo) &amp; Plot  ===========&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    ws_vtx = [-1.3416,0.4472,-1.3416,0.4472,-1.3416,-0.8944,0,0,0.8944,-0.8944,0,0,0.8944;&#xD;&#xA;              -1.0954,-1.4606,0.7303,0.3651,-1.0954,-0.7303,-0.9129,0,-0.1826,0.1826,0,0.9129,0.7303;&#xD;&#xA;              -4.899,-4.0825,-4.0825,-3.266,-2.4495,-4.4907,-4.0825,-6.1237,-5.7155,-4.0825,-3.6742,-5.7155,-5.3072];&#xD;&#xA;    &#xD;&#xA;    position = [0;0;0;1]; focus = [0;0;-3.6742]; %Transformed set points&#xD;&#xA;    &#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s');&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],[position(2); position(2)+focus(2)],...&#xD;&#xA;        [position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.1);&#xD;&#xA;    %====================Create View Volume===========================&#xD;&#xA;    asp_rat = 0.75; %Most displays arent square&#xD;&#xA;    focus = focus/norm(focus); %Normalise focus vector&#xD;&#xA;    nheight = 1; %height of near clip plane&#xD;&#xA;    hoz_angle = 2*pi/3;&#xD;&#xA;    ndistance = 1/tan(hoz_angle/2); %distance of near view plane from origin&#xD;&#xA;    fdistance = 5.5; %Define a far distance&#xD;&#xA;    &#xD;&#xA;    nc = ndistance*focus; %Centre point is focus vector * distance&#xD;&#xA;    ntr = nc + [asp_rat*nheight; nheight; 0]; %Go from centre to TL corner&#xD;&#xA;    nbr = ntr + [0; -2*nheight;0]; %Go down 2* height to bottom&#xD;&#xA;    nbl = nbr + [-2*asp_rat*nheight; 0; 0];&#xD;&#xA;    ntl = nbl + [0; 2*nheight;0];&#xD;&#xA;    nr_plan = [ntr, nbr, nbl, ntl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    fc = fdistance*focus;&#xD;&#xA;    fheight = tan(hoz_angle/2)*fdistance; %Find far plane height by trig&#xD;&#xA;    ftr = fc + [asp_rat*fheight; fheight; 0]; %Go from centre to TL corner&#xD;&#xA;    fbr = ftr + [0; -2*fheight;0]; %Go down 2* height to bottom&#xD;&#xA;    fbl = fbr + [-2*asp_rat*fheight; 0; 0];&#xD;&#xA;    ftl = fbl + [0; 2*fheight;0];&#xD;&#xA;    fr_plan = [ftr, fbr, fbl, ftl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    frust_vtx = horzcat(nr_plan, fr_plan); %Create frustum vertex array&#xD;&#xA;    frust_fcs = [1,8,5,6,4,5;  %Faces defined with normals inwards&#xD;&#xA;                 4,5,1,2,8,8;&#xD;&#xA;                 3,6,2,3,7,4;&#xD;&#xA;                 2,7,6,7,3,1];&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %=============Create Perspective Matrix ==============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot orig frustrum &#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    &#xD;&#xA;    left = nc(1) - asp_rat*nheight; %Get values for projection matrix&#xD;&#xA;    right = nc(1) + asp_rat*nheight;&#xD;&#xA;    top = nc(2) + nheight;&#xD;&#xA;    bottom = nc(2) -nheight;&#xD;&#xA;    near = ndistance;&#xD;&#xA;    far = fdistance;&#xD;&#xA;    &#xD;&#xA;    proj_mat = [2*near/(right - left),0,(right + left)/(right - left),0;&#xD;&#xA;        0, 2*near/(top-bottom),(top+bottom)/(top-bottom),0;&#xD;&#xA;        0,0, -(far+near)/(far-near), -2*far*near/(far-near);&#xD;&#xA;        0,0,-1,0];&#xD;&#xA;    %====================Perspective Projection Transformation=============&#xD;&#xA;    frust_vtx = proj_mat*vertcat(frust_vtx,(ones(1,length(frust_vtx)))); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Perspective Division**&#xD;&#xA;&#xD;&#xA;    %========================Perspective Division==========================&#xD;&#xA;    for i = 1:length(frust_vtx) &#xD;&#xA;        frust_vtx(:,i) = frust_vtx(:,i)/frust_vtx(4,i);&#xD;&#xA;    end&#xD;&#xA;    for i = 1:length(ws_vtx) &#xD;&#xA;        ws_vtx(:,i) = ws_vtx(:,i)/ws_vtx(4,i);&#xD;&#xA;    end&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)); %Plot shape points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx(1:3,:)','FaceColor','r','FaceAlpha', 0.05); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/adExB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EG3Iu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/W4xni.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4563" PostHistoryTypeId="5" PostId="2048" RevisionGUID="7de6fe7b-4d4f-412d-86db-498338ea2ee5" CreationDate="2016-02-16T17:51:17.580" UserId="38" Comment="added 2112 characters in body" Text="Yes, its pretty standard stuff. Most 3D applications our there can do this. Since the nomenclature of 3d applications is not standardized, the tool has different names in different applications: Loft (Maya, 3DSMax), Blend (Creo, Catia...) and so on.&#xD;&#xA;&#xD;&#xA;[![Blend][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Blend between 3 curves, not closed but same principle applies. Open curves are easier as they clearly define the boundary conditions. (software used is Creo because that's what I had open)&#xD;&#xA;&#xD;&#xA;You usually want the first edge be from a surface edge because otherwise you will lose the tangency info. But nothing prevents you from using a natural tangent direction, you just lose control. Also you need to pay attention to how you intend the curves to connect (what point connects to what point).&#xD;&#xA;&#xD;&#xA;Personally I prefer drawing the hull or using some of the network based tools. This way allow you to specify control curves in 2 directions, thus giving control of what to connect where and how it should work mid run.&#xD;&#xA;&#xD;&#xA;[![Image 2][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Curve network.&#xD;&#xA;&#xD;&#xA;There are many ways to do this, infinite ways in fact. Also if you want to be compatible with other mainstream CAD apps use NURBS instead of beziers than its easier for you to write a exporter/importer if your data set is rich enough. Beziers are just special cases of NURBS after all so your code itself should not need to change all that much (fitting also gets easier).&#xD;&#xA;&#xD;&#xA;What you do is simply fit a curve trough your points in the second direction this will then give you the corresponding hull in the other direction. In your case you could just make a Bezier patch for each segment and then try to deduce a natural tangent direction.&#xD;&#xA;&#xD;&#xA;###One way &#xD;&#xA;&#xD;&#xA;Like I said theres a infinite ways of constructing these, you have an artistic freedom of doing whatever you see fit it's a over constrained problem. One way of constructing this would be to have a patch for each consecutive cross section. This is nice and tidy as it generalizes works well with an arbitrary number of cross sections.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Example of deriving one row for 2 consecutive bezier spans.&#xD;&#xA;&#xD;&#xA;First recognize there are 3 cases (ill cover 2):&#xD;&#xA;&#xD;&#xA;  1. Free edges,&#xD;&#xA;  2. Internal edges,&#xD;&#xA;  3. External constraint.&#xD;&#xA;&#xD;&#xA;I'll cover 1 and 2. First the Internal edge as its simple you want it to be smooth so the tangent length and direction in both patches must match. If that's not true then its not sufficiently continuous. You could simply take that this is the furthest point from the surrounding patches control points and due to mean value theorem it should have a tangent direction perpendicular to these (Line A-C is parallel with D-E). The tangent length should be about 1/3 of the length of the distance to the adjoining vertices (A-B or A-C, in this case the shorter of the spans. It could be longer or average. though that could pose problems). Obviously if you have more spans just repeat for one span forward and after for more internal spans if needed. &#xD;&#xA;&#xD;&#xA;For free edges find the point on the perpendicular line that is as far from the point as half distance between the points (length B-D is equal to length (A-B)/2 and length B-E is equal to length (B-D)/2). The free tangent points towards this point. The length of the tangent is as long as one third of corresponding point difference (length (A-B)/3 and (B-C)/3). Obviously the distances and points could be arbitrary but these are somewhat natural. &#xD;&#xA;&#xD;&#xA;Repeat for next point sequence in line and next and next. There are other ways but this is relatively easy to convert into a visual form without going into deeper maths. But this is pretty well known math you can find many ways to form these by searching in literature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zeKrH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Qm5Bk.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ES0Mq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4564" PostHistoryTypeId="5" PostId="2048" RevisionGUID="c973e442-5b69-433c-b734-fbfb9484ca7b" CreationDate="2016-02-16T17:58:09.817" UserId="38" Comment="added 57 characters in body" Text="Yes, its pretty standard stuff. Most 3D applications our there can do this. Since the nomenclature of 3d applications is not standardized, the tool has different names in different applications: Loft (Maya, 3DSMax), Blend (Creo, Catia...) and so on.&#xD;&#xA;&#xD;&#xA;[![Blend][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Blend between 3 curves, not closed but same principle applies. Open curves are easier as they clearly define the boundary conditions. (software used is Creo because that's what I had open)&#xD;&#xA;&#xD;&#xA;You usually want the first edge be from a surface edge because otherwise you will lose the tangency info. But nothing prevents you from using a natural tangent direction, you just lose control. Also you need to pay attention to how you intend the curves to connect (what point connects to what point).&#xD;&#xA;&#xD;&#xA;Personally I prefer drawing the hull or using some of the network based tools. This way allow you to specify control curves in 2 directions, thus giving control of what to connect where and how it should work mid run.&#xD;&#xA;&#xD;&#xA;[![Image 2][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Curve network.&#xD;&#xA;&#xD;&#xA;There are many ways to do this, infinite ways in fact. Also if you want to be compatible with other mainstream CAD apps use NURBS instead of beziers than its easier for you to write a exporter/importer if your data set is rich enough. Beziers are just special cases of NURBS after all so your code itself should not need to change all that much (fitting also gets easier).&#xD;&#xA;&#xD;&#xA;What you do is simply fit a curve trough your points in the second direction this will then give you the corresponding hull in the other direction. In your case you could just make a Bezier patch for each segment and then try to deduce a natural tangent direction.&#xD;&#xA;&#xD;&#xA;###One way &#xD;&#xA;&#xD;&#xA;Like I said theres a infinite ways of constructing these, you have an artistic freedom of doing whatever you see fit it's a over constrained problem. One way of constructing this would be to have a patch for each consecutive cross section. This is nice and tidy as it generalizes works well with an arbitrary number of cross sections.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Example of deriving one row for 2 consecutive bezier spans.&#xD;&#xA;&#xD;&#xA;First recognize there are 3 cases (ill cover 2):&#xD;&#xA;&#xD;&#xA;  1. Free edges,&#xD;&#xA;  2. Internal edges,&#xD;&#xA;  3. External constraint.&#xD;&#xA;&#xD;&#xA;I'll cover 1 and 2. First the Internal edge as its simple you want it to be smooth so the tangent length and direction in both patches must match. If that's not true then its not sufficiently continuous. You could simply take that this is the furthest point from the surrounding patches control points and due to mean value theorem it should have a tangent direction perpendicular to these (Line A-C is parallel with D-E). The tangent length should be about 1/3 of the length of the distance to the adjoining vertices (A-B or A-C, in this case the shorter of the spans. It could be longer or average. though that could pose problems). Obviously if you have more spans just repeat for one span forward and after for more internal spans if needed. &#xD;&#xA;&#xD;&#xA;For free edges find the point on the perpendicular line that is as far from the point as half distance between the points (length B-D is equal to length (A-B)/2 and length B-E is equal to length (B-D)/2). The free tangent points towards this point. The length of the tangent is as long as one third of corresponding point difference (length (A-B)/3 and (B-C)/3). Obviously the distances and points could be arbitrary but these are somewhat natural. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Repeat for next point sequence in line and next and next. You end up with 2 spans that means 2 times 16 points.  There are other ways but this is relatively easy to convert into a visual form without going into deeper maths. But this is pretty well known math you can find many ways to form these by searching in literature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zeKrH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Qm5Bk.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ES0Mq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4565" PostHistoryTypeId="2" PostId="2053" RevisionGUID="7e4c15f9-b85d-483c-bd90-8e12e9fc4512" CreationDate="2016-02-16T18:38:54.543" UserId="310" Text="In a traditional camera, the photons from the scene travel through the lens of the camera, then hit the sensor at the focal length. A consequence of the lens is that the image is upside down and backwards.&#xD;&#xA;&#xD;&#xA;[![Camera][1]][1]&#xD;&#xA;&#xD;&#xA;In ray tracing, we can optimize this by imagining the focal plane is in front of the camera. You can think that the photons from the scene travel towards the camera hole, and resolve on the image plane. &#xD;&#xA;&#xD;&#xA;[![Photons hit image plane][2]][2]&#xD;&#xA;&#xD;&#xA;Another optimization in ray tracing to to trace rays from the camera into the scene, rather than tracing them from light sources and hoping they hit the camera. Therefore, the first rays we shoot out are the ones that go from the eye through each pixel on the virtual screen.&#xD;&#xA;&#xD;&#xA;[![Shooting a Ray][3]][3]&#xD;&#xA;&#xD;&#xA;In order to create the ray, we need to know the distances a and b in world units. Therefore, we need to convert pixel units into world units. To do this we need a define a camera. Let's define an example camera as follows:&#xD;&#xA;$$origin = \begin{bmatrix} 0 &amp; 0 &amp; 0 \end{bmatrix}$$&#xD;&#xA;$$coordinateSystem = \begin{bmatrix} 1 &amp; 0 &amp; 0\\ 0 &amp; 1 &amp; 0\\ 0 &amp; 0 &amp; 1 \end{bmatrix}$$&#xD;&#xA;$$fov_{x} = 90^{\circ}$$&#xD;&#xA;$$fov_{y} = \frac{fov_{x}}{aspectRatio}$$&#xD;&#xA;$$focalDist = 1$$&#xD;&#xA;&#xD;&#xA;The field of view, or fov is an indirect way of specifying the ratio of pixel units to view units. Specifically, it is the viewing angle that is seen by the camera.&#xD;&#xA;&#xD;&#xA;[![FOV Eye Plane][4]][4]&#xD;&#xA;&#xD;&#xA;The higher the angle, the more of the scene is seen. But remember, changing the fov does not change the size of the screen, it merely squishes more or less of the scene into the same number of pixels.&#xD;&#xA;&#xD;&#xA;[![FOV Explaination][5]][5]&#xD;&#xA;&#xD;&#xA;Let's look at the triangle formed by fovx and the x-axis:&#xD;&#xA;&#xD;&#xA;[![Triangle][6]][6]&#xD;&#xA;&#xD;&#xA;We can use the definition of tangent to calculate the screenWidth in view units&#xD;&#xA;$$\tan \left (\theta  \right) = \frac{opposite}{adjacent}$$&#xD;&#xA;$$screenWidth_{view}= 2 \: \cdot \: focalDist \: \cdot \: \tan \left (\frac{fov_{x}}{2}  \right)$$&#xD;&#xA;&#xD;&#xA;Using that, we can calculate the view units of the pixel.&#xD;&#xA;$$x_{homogenous}= 2 \: \cdot \: \frac{x}{width} \: - \: 1$$&#xD;&#xA;$$x_{view} = focalDist \: \cdot \: x_{homogenous} \: \cdot \: \tan \left (\frac{fov_{x}}{2}  \right)$$&#xD;&#xA;&#xD;&#xA;The last thing to do to get the ray is to transform from view space to world space. This boils down to a simple matrix transform. We negate yview because pixel coordinates go from the top left of the screen to the bottom right, but homogeneous coordinates go from (-1, -1) at the bottom left to (1, 1) at the top right.&#xD;&#xA;$$ray_{world}= \begin{bmatrix} x_{view} &amp; -y_{view} &amp; d\end{bmatrix}\begin{bmatrix} &amp;  &amp; \\ &amp; cameraCoordinateSystem &amp; \\ &amp;  &amp; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can see an implementation of this [here][7] (In the code, I assume the focalDist is 1, so it cancels out)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e4pu7.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/iOrm3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/BW8Vy.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OyYfj.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/PBEBi.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/sSUA1.png&#xD;&#xA;  [7]: https://github.com/RichieSams/lantern/blob/669e6c9ccd33f455961a96c5cfe0a5bc3f2af59c/source/scene/camera.cpp#L86" ContentLicense="CC BY-SA 3.0" />
  <row Id="4566" PostHistoryTypeId="2" PostId="2054" RevisionGUID="de021da4-1c80-41e1-bdbe-128bc96156e3" CreationDate="2016-02-16T19:42:22.413" UserId="48" Text="As far as I can tell, the main advantage of half-edge is that traversal can be a bit simpler due to a guarantee of edges having a consistent orientation within each face.&#xD;&#xA;&#xD;&#xA;Consider the problem of iterating over all the vertices or edges of a given face, in counterclockwise order. In the half-edge structure, this can be done by starting with an arbitrary half-edge of that face and simply following the &quot;next&quot; pointers until you get back where you started.&#xD;&#xA;&#xD;&#xA;In contrast, doing this in a winged-edge structure is a bit annoying, because the edges are oriented arbitrarily; any given edge that you encounter might point either clockwise or counterclockwise relative to the face you're trying to iterate around, so you have to do an extra conditional check at each step to see if you should traverse the current edge forward or backward.&#xD;&#xA;&#xD;&#xA;Other kinds of connectivity queries behave similarly: the half-edge version lets you follow links in a consistent sequence while the winged-edge version requires orientation checks at each step.&#xD;&#xA;&#xD;&#xA;Whether the conditionals are actually a performance problem for winged-edge will probably depend on other factors. For a &quot;naive&quot; implementation with pointers every which way and data scattered across memory, I'd expect cache miss overhead to swamp any effect of the conditionals. On the other hand, if you have a tightly packed data structure with everything hot in the cache, you might see some effects from the conditionals due to incorrect branch predictions, etc. It's hard to say.&#xD;&#xA;&#xD;&#xA;Leaving performance alone, I'd prefer half-edge just because it seems easier to reason about and write correct code for, even if it results in a slight memory overhead.&#xD;&#xA;&#xD;&#xA;By the way, there are a couple of other design choices with mesh data structures that often seem to get confused with this one. A commenter mentioned singly vs doubly linked, but naturally you can do either single or double linking with either half-edge or winged-edge. Also, there's the question of whether the vertex and face structures store a list of all their edges, or just one (and require you to traverse the edges to find the rest). Having a variable-length list of edges per vertex/face considerably complicates the logic if you want to do it efficiently (i.e. not having a separate heap allocation per vertex/face), but again this is independent of whether the edges are half-edge or winged-edge." ContentLicense="CC BY-SA 3.0" />
  <row Id="4567" PostHistoryTypeId="5" PostId="2054" RevisionGUID="59b94d08-d9e2-4598-a873-b344f2151025" CreationDate="2016-02-16T19:47:22.990" UserId="48" Comment="added 191 characters in body; added 1 character in body; edited body" Text="As far as I can tell, the main advantage of half-edge is that traversal can be a bit simpler due to a guarantee of edges having a consistent orientation within each face.&#xD;&#xA;&#xD;&#xA;Consider the problem of iterating over all the vertices or edges of a given face, in counterclockwise order. In the half-edge structure, this can be done by starting with an arbitrary half-edge of that face and simply following the &quot;next&quot; pointers until you get back where you started.&#xD;&#xA;&#xD;&#xA;In contrast, doing this in a winged-edge structure is a bit annoying, because the edges are oriented arbitrarily; any given edge that you encounter might point either clockwise or counterclockwise relative to the face you're trying to iterate around, so you have to do an extra conditional check at each step to see if you should traverse the current edge forward or backward.&#xD;&#xA;&#xD;&#xA;Other kinds of connectivity queries behave similarly: the half-edge version lets you follow links in a consistent sequence while the winged-edge version requires orientation checks at each step.&#xD;&#xA;&#xD;&#xA;Whether the conditionals are actually a performance problem for winged-edge will probably depend on other factors. For a &quot;naive&quot; implementation with pointers every which way and data scattered across memory, I'd expect cache miss overhead to swamp any effect of the conditionals. On the other hand, if you have a tightly packed data structure with everything hot in the cache, you might see some effects from the conditionals due to incorrect branch predictions, etc. It's hard to say.&#xD;&#xA;&#xD;&#xA;Leaving performance alone, I'd prefer half-edge just because it seems easier to reason about and write correct code for, even if it results in a slight memory overhead.&#xD;&#xA;&#xD;&#xA;By the way, there are a couple of other design choices with mesh data structures that often seem to get confused with this one. A commenter mentioned single vs double linking, but naturally you can do either single or double linking with either half-edge or winged-edge. (Although I don't see how single linking with winged-edge would even work, since as mentioned above, you might have to traverse edges either backward or forward in the course of a query.)&#xD;&#xA;&#xD;&#xA;Also, there's the question of whether the vertex and face structures store a list of all their edges, or just one (and require you to traverse the edges to find the rest). Having a variable-length list of edges per vertex/face considerably complicates the logic if you want to do it efficiently (i.e. not having a separate heap allocation per vertex/face), but again this is independent of whether the edges are half-edge or winged-edge." ContentLicense="CC BY-SA 3.0" />
  <row Id="4568" PostHistoryTypeId="2" PostId="2055" RevisionGUID="0431ab5b-a335-40b6-b71a-fc4aa0e6bb98" CreationDate="2016-02-16T20:49:14.753" UserId="2701" Text="I have to use a propriertary graphics-engine for drawing a line. I can rotate the whole drawing by its origin point (P1). What I want, is to rotate it around its center point(M). So basically that it looks like the green line (L_correct instead of L_wrong). &#xD;&#xA;&#xD;&#xA;I think, it should be possible to correct it, by moving it from P1 to P2. But I cannot figure out what formula could be used, to determine the distance. It must probably involve the angle, with and height... Can anyone give me a hint?&#xD;&#xA;&#xD;&#xA;Just noticed the arrow shows in the wrong direction. Please ignore this mistake.&#xD;&#xA;![1][1]&#xD;&#xA;[1]: https://i.stack.imgur.com/75MpZ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4569" PostHistoryTypeId="1" PostId="2055" RevisionGUID="0431ab5b-a335-40b6-b71a-fc4aa0e6bb98" CreationDate="2016-02-16T20:49:14.753" UserId="2701" Text="Rotate line around center" ContentLicense="CC BY-SA 3.0" />
  <row Id="4570" PostHistoryTypeId="3" PostId="2055" RevisionGUID="0431ab5b-a335-40b6-b71a-fc4aa0e6bb98" CreationDate="2016-02-16T20:49:14.753" UserId="2701" Text="|line-drawing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4571" PostHistoryTypeId="5" PostId="2055" RevisionGUID="e3e6254d-be18-44f1-8ea4-e70c015c4214" CreationDate="2016-02-16T20:56:03.167" UserId="2701" Comment="deleted 82 characters in body" Text="I have to use a propriertary graphics-engine for drawing a line. I can rotate the whole drawing by its origin point (P1). What I want, is to rotate it around its center point(M). So basically that it looks like the green line (L_correct instead of L_wrong). &#xD;&#xA;&#xD;&#xA;I think, it should be possible to correct it, by moving it from P1 to P2. But I cannot figure out what formula could be used, to determine the distance. It must probably involve the angle, with and height... Can anyone give me a hint?&#xD;&#xA;&#xD;&#xA;![1][1]&#xD;&#xA;[1]: https://i.stack.imgur.com/75MpZ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4572" PostHistoryTypeId="2" PostId="2056" RevisionGUID="f344d42d-ffba-4339-91ed-ba1bdde1e5d9" CreationDate="2016-02-16T21:18:00.447" UserId="38" Text="Trick is, to move the entire object so that the point about which you want to rotate is at the center. Then rotate and after that counter move it so that the point is were it was.&#xD;&#xA;&#xD;&#xA;In fact this is not so much of a trick, as such, but in fact nearly all graphics engines work this way. It is just abstracted away in many cases. Most often you will se it done in matrix notation like this:&#xD;&#xA;&#xD;&#xA;$$ T^{-1} R T $$&#xD;&#xA;&#xD;&#xA;Where T is to transformation from world to pivot and R is the rotation matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="4573" PostHistoryTypeId="2" PostId="2057" RevisionGUID="cb6923fd-720b-4380-a585-97136f86300b" CreationDate="2016-02-16T22:09:03.930" UserId="2372" Text="I am currently reading the awesome paper by Jorge Jimenez about Character rendering : [Next Generation Character Rendering][1]&#xD;&#xA;&#xD;&#xA;In the part about multi-sampled transmittance he uses some Poisson offsets and a jitter texture which contains *[cos(x), sin(x)]* and is used to rotate the the Poisson disk samples.&#xD;&#xA;&#xD;&#xA;But I am wondering how do you generate such texture ?&#xD;&#xA;&#xD;&#xA;Here is the part of the ppt which talks about this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.iryoku.com/stare-into-the-future&#xD;&#xA;  [2]: https://i.stack.imgur.com/21iCO.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4574" PostHistoryTypeId="1" PostId="2057" RevisionGUID="cb6923fd-720b-4380-a585-97136f86300b" CreationDate="2016-02-16T22:09:03.930" UserId="2372" Text="Jitter texture generation" ContentLicense="CC BY-SA 3.0" />
  <row Id="4575" PostHistoryTypeId="3" PostId="2057" RevisionGUID="cb6923fd-720b-4380-a585-97136f86300b" CreationDate="2016-02-16T22:09:03.930" UserId="2372" Text="|opengl|rendering|texture|sampling|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4576" PostHistoryTypeId="2" PostId="2058" RevisionGUID="bd227f40-e4c2-4515-9b52-10503fc7dcc4" CreationDate="2016-02-16T23:26:31.237" UserId="273" Text="I am a bit unsure if my calculations are correct, but on my scribbling paper it seemed to work out.&#xD;&#xA;&#xD;&#xA;P1 and P2 lie on a circle around M.&#xD;&#xA;&#xD;&#xA;This allows us to measure the distance of the two points by just taking the radius (which is half the line length) of the circle and constructing two rectangular triangles. The accepted answer [here][1] provides a sketch for this construction.&#xD;&#xA;So given your rotation angle is $\gamma$ and the line is $l$ long it follows:&#xD;&#xA;&#xD;&#xA;$x = 2* sin(\frac{\gamma}{2}) * \frac{l}{2}$&#xD;&#xA;&#xD;&#xA;The lines M to P1 and M to P2 form a isosceles triangle with the third side being the line segment between P1 and P2.&#xD;&#xA;&#xD;&#xA;The angle at point M is known to be the rotation angle $\gamma$ so the remaining two angles in this triangle are given by&#xD;&#xA;&#xD;&#xA;$\alpha = \frac{180 - \gamma}{2}$ &#xD;&#xA;&#xD;&#xA;And therefore the angle between the wrong line and the needed translation vector is just &#xD;&#xA;&#xD;&#xA;$\beta = \alpha + \gamma$&#xD;&#xA;&#xD;&#xA;So now you rotate a unit vector that starts along the wrong line.&#xD;&#xA;&#xD;&#xA;You rotate it around P1 for $\beta$ and scale it to length x.&#xD;&#xA;&#xD;&#xA;This yields the translation vector from P1 to P2. The rotation of the line should indeed be correct.&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/questions/134606/distance-between-any-two-points-on-a-unit-circle" ContentLicense="CC BY-SA 3.0" />
  <row Id="4577" PostHistoryTypeId="2" PostId="2059" RevisionGUID="3c1707b6-282d-42de-89d3-0aec64c03b5e" CreationDate="2016-02-17T08:11:53.453" UserId="48" Text="The texture is probably generated by picking a random angle per pixel, and populating the image with its sine and cosine, remapped into [0, 1]:&#xD;&#xA;&#xD;&#xA;$$\theta \sim [0, 2\pi] \quad \to \quad \begin{bmatrix} \tfrac{1}{2} \cos \theta + \tfrac{1}{2} \\ \tfrac{1}{2} \sin \theta + \tfrac{1}{2} \\ 0 \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;I did a quick test and generated something that looks pretty similar (enlarged 4x):&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;If you want to be extra fancy, then instead of picking independent random angles for every pixel, you might try stratified sampling or a low-discrepancy sequence. That may give better final results for whatever effect you're using the jitter texture for, due to better local sample distribution.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4ySjS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4578" PostHistoryTypeId="5" PostId="2056" RevisionGUID="b5a4c6ee-fdef-447e-a8f7-7dd68954d8f0" CreationDate="2016-02-17T09:22:41.763" UserId="38" Comment="added picture" Text="Trick is, to move the entire object so that the point about which you want to rotate is at the center. Then rotate and after that counter move it so that the point is were it was.&#xD;&#xA;&#xD;&#xA;In fact this is not so much of a trick, as such, nearly all graphics engines work this way. It is just abstracted away in many cases. Most often you will see it done in matrix notation like this:&#xD;&#xA;&#xD;&#xA;$$ T^{-1} R T $$&#xD;&#xA;&#xD;&#xA;Where T is to transformation from world to pivot and R is the rotation matrix. Since it can be easily packaged this way you end up with a function called rotate about the pivot point. This is usually the reason why drawing API's allow for a transformation matrix.&#xD;&#xA;&#xD;&#xA;[![Rotate about a pivot][1]][1]&#xD;&#xA;&#xD;&#xA; **Image 1**: Rotate about a pivot point, [image source](http://pastebin.com/L2XpvfeG) available for investigation. Sub images in RTL reading order: Original, inverse transform, inverse and rotate, inverse rotate and move back.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kIH24.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4579" PostHistoryTypeId="6" PostId="2055" RevisionGUID="3b56e253-17b5-4745-8109-087f12055662" CreationDate="2016-02-17T09:34:32.137" UserId="38" Comment="edited tags" Text="|transformations|line-drawing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4580" PostHistoryTypeId="2" PostId="2060" RevisionGUID="dfc22214-7a5c-4722-83a1-d1ac9b326620" CreationDate="2016-02-17T14:59:49.933" UserId="116" Text="I have been playing with voxelization for a little time, I'm still very new to this technique.&#xD;&#xA;I am trying to use it for ray tracing but I've been stuck with one problem. There are some codes out there in the web that already perform voxelization however, for ray tracing I need to check the intersection between a ray and a triangle.&#xD;&#xA;Therefore, I've been thinking about what would be a good approach to create a list of triangles for each voxel in order to query the triangles once I know a ray hits a particular voxel? Should I try to modify the code of the voxelizer to benefit from the overlap-test or is it better to create a space-partitioning structure?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4581" PostHistoryTypeId="1" PostId="2060" RevisionGUID="dfc22214-7a5c-4722-83a1-d1ac9b326620" CreationDate="2016-02-17T14:59:49.933" UserId="116" Text="How to build a triangle-voxel list from a triangle mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4582" PostHistoryTypeId="3" PostId="2060" RevisionGUID="dfc22214-7a5c-4722-83a1-d1ac9b326620" CreationDate="2016-02-17T14:59:49.933" UserId="116" Text="|space-partitioning|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4583" PostHistoryTypeId="2" PostId="2061" RevisionGUID="6a56e956-c5e8-4816-bab6-089924f7d1a3" CreationDate="2016-02-18T01:47:02.473" UserId="2707" Text="Mainly talking about dual-SLI here for consistency. With past DirectX (and OpenGL) APIs, VRAM was mirrored across graphics cards. With dual-SLI, this was possible by rendering one frame with one graphics card and another frame with another one. There was also a rendering option in which one graphics card would render part of the screen. Unfortunately, there doesn't seem to be much technical information on how VRAM stacking would work. What possible techniques could graphics cards or DirectX 12 be using to allow for this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4584" PostHistoryTypeId="1" PostId="2061" RevisionGUID="6a56e956-c5e8-4816-bab6-089924f7d1a3" CreationDate="2016-02-18T01:47:02.473" UserId="2707" Text="How does DirectX 12 SLI VRAM stacking work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4585" PostHistoryTypeId="3" PostId="2061" RevisionGUID="6a56e956-c5e8-4816-bab6-089924f7d1a3" CreationDate="2016-02-18T01:47:02.473" UserId="2707" Text="|directx12|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4586" PostHistoryTypeId="5" PostId="116" RevisionGUID="45ca2016-9f93-4d6e-8402-ff412e5135fc" CreationDate="2016-02-18T02:08:04.167" UserId="38" Comment="added summary" Text="Transformations are mathematical operations that can be applied to an object to change its scale, position and orientation. " ContentLicense="CC BY-SA 3.0" />
  <row Id="4587" PostHistoryTypeId="24" PostId="116" RevisionGUID="45ca2016-9f93-4d6e-8402-ff412e5135fc" CreationDate="2016-02-18T02:08:04.167" Comment="Proposed by 38 approved by 231 edit id of 124" ContentLicense="CC BY-SA 3.0" />
  <row Id="4588" PostHistoryTypeId="2" PostId="2062" RevisionGUID="31e36d34-fa80-4a87-be27-ca5a8d515b01" CreationDate="2016-02-18T03:27:47.513" UserId="48" Text="In DX12, there is no implicit driver-implemented SLI as there was in DX11. Instead, multiple GPUs are exposed to the application as separate &quot;nodes&quot; within a single DX12 device, and each VRAM resource lives on a single node, specified at creation time. There is no implicit mirroring of resources to both GPUs as in DX11 SLI.&#xD;&#xA;&#xD;&#xA;So, the game engine or application has full control and responsibility over how data and work are distributed between the GPUs. It's up to the app developers to implement patterns like alternating frames between GPUs, or splitting the frame across GPUs, if they wish. For example, to implement alternating frames, the app would have to allocate all buffers, textures, render targets etc. on both GPUs and populate both of them. Then, when rendering a frame, it would generate a command list for the current GPU using its local copies of all resources. Any inter-GPU transfers needed (for temporal effects, for instance) would also be the app's responsibility.&#xD;&#xA;&#xD;&#xA;More information on this topic can be found on [this MSDN article on DX12 multi-GPU support](https://msdn.microsoft.com/en-us/library/windows/desktop/dn933253.aspx)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4589" PostHistoryTypeId="2" PostId="2063" RevisionGUID="a7184763-03de-47a9-9442-9b6ef55c8701" CreationDate="2016-02-18T04:08:25.213" UserId="2651" Text="I'm a newcomer to OpenGL and I was playing around with drawing triangles with different z-coordinates. From what I understand, the z axis point out of the screen, and the -z axis points into the screen. &#xD;&#xA;&#xD;&#xA;When I draw a square with 3 corners at a 0.0 z-coordinate, and the last corner at, say, 3.0 z-coordinate, I get this:&#xD;&#xA;&#xD;&#xA;[![wat][1]][1]&#xD;&#xA;&#xD;&#xA;I don't understand how it's making this shape... I thought it would be something like this, since the 4th vertex is just 'far away'.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Can someone explain?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GL2Mu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Dmw2A.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4590" PostHistoryTypeId="1" PostId="2063" RevisionGUID="a7184763-03de-47a9-9442-9b6ef55c8701" CreationDate="2016-02-18T04:08:25.213" UserId="2651" Text="Confused about z-axis behaviour" ContentLicense="CC BY-SA 3.0" />
  <row Id="4591" PostHistoryTypeId="3" PostId="2063" RevisionGUID="a7184763-03de-47a9-9442-9b6ef55c8701" CreationDate="2016-02-18T04:08:25.213" UserId="2651" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4592" PostHistoryTypeId="5" PostId="2063" RevisionGUID="96394a63-db65-4e67-9d50-852980ebcf36" CreationDate="2016-02-18T04:24:59.147" UserId="2651" Comment="added 523 characters in body" Text="I'm a newcomer to OpenGL and I was playing around with drawing triangles with different z-coordinates. From what I understand, the z axis point out of the screen, and the -z axis points into the screen. &#xD;&#xA;&#xD;&#xA;When I draw a square with 3 corners at a 0.0 z-coordinate, and the last corner at, say, 3.0 z-coordinate, I get this:&#xD;&#xA;&#xD;&#xA;[![wat][1]][1]&#xD;&#xA;&#xD;&#xA;I don't understand how it's making this shape... I thought it would be something like this, since the 4th vertex is just 'far away'.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Can someone explain?&#xD;&#xA;&#xD;&#xA;**Edit:** This is my vertex data&#xD;&#xA;&#xD;&#xA;    // vertex array&#xD;&#xA;	float vertices[] = {&#xD;&#xA;		-0.5f,  0.5f,  0.0f, 1.0f, 0.0f, 0.0f, // top left, first 3 are location, last 3 are color&#xD;&#xA;		 0.5f,  0.5f,  0.0f, 0.0f, 1.0f, 0.0f, // top right&#xD;&#xA;		-0.5f, -0.5f,  -2.0f, 0.0f, 0.0f, 1.0f, // bottom left&#xD;&#xA;		 0.5f, -0.5f,  0.0f, 1.0f, 1.0f, 1.0f // bottom right&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	// element buffer array&#xD;&#xA;	GLuint elements[] = {&#xD;&#xA;		0, 1, 2,&#xD;&#xA;		2, 1, 3&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;And I am calling the draw like:&#xD;&#xA;&#xD;&#xA;    glDrawElements(GL_TRIANGLES, 6,GL_UNSIGNED_INT,0);&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GL2Mu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Dmw2A.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4593" PostHistoryTypeId="2" PostId="2064" RevisionGUID="1366de45-694e-4315-bcc2-ae5c7d6813f4" CreationDate="2016-02-18T04:35:46.963" UserId="48" Text="The post-projective Z range in OpenGL extends between &amp;minus;1 and 1. So, a Z-value of 2 is out of range and will be clipped by the far plane.&#xD;&#xA;&#xD;&#xA;The reason the square appears with a quadrant missing is that it's split into triangles from bottom left to top right, and so each triangle has two vertices with Z = 0 and one vertex with Z = 2. So, interpolating along the triangle, it hits Z = 1 (the far plane) halfway across, and everything beyond that is clipped. This results in half of each triangle disappearing.&#xD;&#xA;&#xD;&#xA;BTW, you'll need a perspective projection matrix in order for far-away objects to appear smaller on screen. With no projection matrix, you're effectively using a parallel projection." ContentLicense="CC BY-SA 3.0" />
  <row Id="4602" PostHistoryTypeId="2" PostId="2067" RevisionGUID="c211e417-a348-4efd-a0af-4467ba71ebf8" CreationDate="2016-02-18T17:38:27.070" UserId="2623" Text="So I want to render a buttload of quads by using a single 4 point vertex array and change the position of the quad. What is quicker:&#xD;&#xA;&#xD;&#xA;Using &lt;code&gt;glBufferSubData&lt;/code&gt; to change the positional data or&#xD;&#xA;&#xD;&#xA;Using &lt;code&gt;glMapBufferRange&lt;/code&gt; to DMA the buffer and &lt;code&gt;glUnmapBuffer&lt;/code&gt; to push the data back to the GPU?&#xD;&#xA;&#xD;&#xA;When using the vertex buffer data, I need to also call &lt;code&gt;glVertexAttribArray&lt;/code&gt; to reassociate the data with the vertexArrayObject.&#xD;&#xA;&#xD;&#xA;When using uniform buffers and do it with shader magic I only need to change the uniform buffer.&#xD;&#xA;&#xD;&#xA;What is quicker?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4603" PostHistoryTypeId="1" PostId="2067" RevisionGUID="c211e417-a348-4efd-a0af-4467ba71ebf8" CreationDate="2016-02-18T17:38:27.070" UserId="2623" Text="Uniform Buffers: What is quicker?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4604" PostHistoryTypeId="3" PostId="2067" RevisionGUID="c211e417-a348-4efd-a0af-4467ba71ebf8" CreationDate="2016-02-18T17:38:27.070" UserId="2623" Text="|opengl|mapping|uniform-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4605" PostHistoryTypeId="2" PostId="2068" RevisionGUID="d6dd86ef-84dc-46ff-89ca-d36eb71f758e" CreationDate="2016-02-18T22:21:47.970" UserId="43" Text="I've done some small changes to how I usually construct my view matrix, here is what I've modified:&#xD;&#xA;&#xD;&#xA;    // put it after N = ...&#xD;&#xA;    U = cross(N, Vspec);&#xD;&#xA;    U = U / sqrt(dot(U,U)); % normalize&#xD;&#xA;    V = cross(U, N);&#xD;&#xA;&#xD;&#xA;Then I also set N vector as -N to R matrix, like this:&#xD;&#xA;&#xD;&#xA;    R= [U(1),U(2),U(3),0; % U is direction of camera space X axis&#xD;&#xA;        V(1),V(2),V(3),0; % V is direction of camera space Y axis&#xD;&#xA;        -N(1),-N(2),-N(3),0;&#xD;&#xA;        0   ,   0,   0,1];&#xD;&#xA;&#xD;&#xA;[as shown e.g. in the code for lookAt matrix for OpenGL][1]&#xD;&#xA;&#xD;&#xA;Now you can orient your first graph, as if you look through your camera, this will give you a reference of how it should look on the second graph.&#xD;&#xA;&#xD;&#xA;Then orient second graph so that you look through -Z axis, Y looks up, and X from left to right. Because your camera view vector is -Z, up is Y and right is X. Once you orient your second graph like this, you'll see that arrow looks identically to the first graph, ray on graph 2 will be drawn as point, because it is directed along -Z (your view direction), and in camera space end and start points will fall on a same pixels (another hint that it is correct).&#xD;&#xA;&#xD;&#xA;I've also modified a bit camera pos, view direction and axes (just to make it easier to observe for myself).&#xD;&#xA;&#xD;&#xA;Here are the values, that I've used:&#xD;&#xA;    focus = [1.2,0,1.5]; %The point we're looking at&#xD;&#xA;    Cx = 3; Cy = -3; Cz = 3; %Position of camera&#xD;&#xA;&#xD;&#xA;And for the axes:&#xD;&#xA;    axis([-5,5,-6,6,-7,7]);&#xD;&#xA;&#xD;&#xA;[![Here is what I've got][2]][2]&#xD;&#xA;&#xD;&#xA;I can send you whole code if you need.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/GluLookAt_code&#xD;&#xA;  [2]: https://i.stack.imgur.com/izEmQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4606" PostHistoryTypeId="2" PostId="2069" RevisionGUID="44753311-bcd7-4757-ade7-4554c49483f7" CreationDate="2016-02-18T23:29:45.807" UserId="48" Text="A key rule of thumb for high-performance code in general, and graphics in particular, is to batch large amounts of work together rather than doing it in small chunks. In your case, rather than sending one quad's worth of data at a time and drawing one quad at a time, it will be far more efficient to send many quads' data in a large batch, and draw many quads together in a single draw call.&#xD;&#xA;&#xD;&#xA;A good way to accomplish both is [instancing](https://www.opengl.org/wiki/Vertex_Rendering#Instancing). You would have a 4-point vertex buffer for the corners of a quad, and a second vertex buffer for the values that are per-quad (what you're putting in your uniform buffer now). This second buffer would be large enough to hold the data for all the quads at once, not just one quad. To populate the vertex buffer, you can map the whole thing, write all the data, and unmap. Then do a single instanced draw call to render all the quads at once.&#xD;&#xA;&#xD;&#xA;However, if instancing can't be used for some reason (for instance if each quad needs a different texture), you can still upload all the data in one batch. Create a uniform buffer large enough to hold an array of all the quads' data; map/write/unmap it all in one big batch as before; then before each draw call, use [`glBindBufferRange`](http://docs.gl/gl4/glBindBufferRange) to select one quad's data from that large buffer." ContentLicense="CC BY-SA 3.0" />
  <row Id="4608" PostHistoryTypeId="2" PostId="2070" RevisionGUID="e4ae7558-b907-43f4-b696-efdfad2609f7" CreationDate="2016-02-19T02:32:49.933" UserId="56" Text="I'm working on a webgl pixel shader which is writing to a 16 bit floating point buffer (each color channel r,g,b,a is a 16 bit floating point number).&#xD;&#xA;&#xD;&#xA;I'm trying to figure out if there are any decent ways to pack the following info into those 16 bits per color channel:&#xD;&#xA;&#xD;&#xA; - normal (x,y,z where z is always negative)&#xD;&#xA; - uv coordinates (x,y between 0 and 1)&#xD;&#xA; - material index (an integer. 0 to 3 would be plenty)&#xD;&#xA; - distance (a positive float)&#xD;&#xA;&#xD;&#xA;I could live without distance if needed but the others are required.&#xD;&#xA;&#xD;&#xA;I know that I can store just x,y of the normal and calculate z as needed since its always negative (the normal is in screenspace).&#xD;&#xA;&#xD;&#xA;That still leaves 5 values to store in four 16 bit floats: normal.xy, uv.xy, material index.&#xD;&#xA;&#xD;&#xA;Does anyone have any good methods for making this happen? It would be nice to have the distance too, otherwise I am limited to directional lighting instead of getting point lights as well.&#xD;&#xA;&#xD;&#xA;This is in shadertoy if that context changes any answers.&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4609" PostHistoryTypeId="1" PostId="2070" RevisionGUID="e4ae7558-b907-43f4-b696-efdfad2609f7" CreationDate="2016-02-19T02:32:49.933" UserId="56" Text="Bitpacking into buffers with webgl (shadertoy)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4610" PostHistoryTypeId="3" PostId="2070" RevisionGUID="e4ae7558-b907-43f4-b696-efdfad2609f7" CreationDate="2016-02-19T02:32:49.933" UserId="56" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4612" PostHistoryTypeId="2" PostId="2071" RevisionGUID="bd16c4c5-0108-49ec-b07c-019947ebe225" CreationDate="2016-02-19T05:00:16.637" UserDisplayName="user2500" Text="Assuming you are not going to filter the buffer using HW texture filtering: since you only need 4 values for the material index, pack it in the sign bits of uv x and y." ContentLicense="CC BY-SA 3.0" />
  <row Id="4613" PostHistoryTypeId="5" PostId="2070" RevisionGUID="dce038bb-756d-400d-b5f3-679f55f86724" CreationDate="2016-02-19T05:15:35.553" UserId="56" Comment="added 144 characters in body" Text="I'm working on a webgl pixel shader which is writing to a 16 bit floating point buffer (each color channel r,g,b,a is a 16 bit floating point number).&#xD;&#xA;&#xD;&#xA;I'm trying to figure out if there are any decent ways to pack the following info into those 16 bits per color channel:&#xD;&#xA;&#xD;&#xA; - normal (x,y,z where z is always negative)&#xD;&#xA; - uv coordinates (x,y between 0 and 1)&#xD;&#xA; - material index (an integer. 0 to 3 would be plenty)&#xD;&#xA; - distance (a positive float)&#xD;&#xA;&#xD;&#xA;I could live without distance if needed but the others are required.&#xD;&#xA;&#xD;&#xA;I know that I can store just x,y of the normal and calculate z as needed since its always negative (the normal is in screenspace).&#xD;&#xA;&#xD;&#xA;That still leaves 5 values to store in four 16 bit floats: normal.xy, uv.xy, material index.&#xD;&#xA;&#xD;&#xA;Does anyone have any good methods for making this happen? It would be nice to have the distance too, otherwise I am limited to directional lighting instead of getting point lights as well.&#xD;&#xA;&#xD;&#xA;This is in shadertoy if that context changes any answers.&#xD;&#xA;&#xA;I'll be sampling this buffer with nearest neighbor sampling, so you don't have to worry about it being stored in a way that interpolates well.&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4614" PostHistoryTypeId="2" PostId="2072" RevisionGUID="091e1f37-7cbf-43bd-97a8-b873fb14db02" CreationDate="2016-02-19T05:30:18.017" UserId="56" Text="If you have values on a grid and you want to find the value of a point within one of the cells, you can use techniques like bilinear or bicubic interpolation to get the data at that point.&#xA;&#xA;What technique(s) would be used if the data on the grid was a vector (a surface normal specifically)?&#xA;&#xA;I know that quaternions are good for slerping, which I think could be good in this case to do a &quot;bilinear slerp&quot;, but quaternions require basis vectors that represent an orientation, not just a single vector.&#xA;&#xA;Also, I'm not sure how you'd use quaternions to apply something like bicubic interpolation.&#xA;&#xA;What methods would be good in this case, to interpolate vectors on a grid?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4615" PostHistoryTypeId="1" PostId="2072" RevisionGUID="091e1f37-7cbf-43bd-97a8-b873fb14db02" CreationDate="2016-02-19T05:30:18.017" UserId="56" Text="Interpolating vectors on a grid" ContentLicense="CC BY-SA 3.0" />
  <row Id="4616" PostHistoryTypeId="3" PostId="2072" RevisionGUID="091e1f37-7cbf-43bd-97a8-b873fb14db02" CreationDate="2016-02-19T05:30:18.017" UserId="56" Text="|vectors|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4617" PostHistoryTypeId="2" PostId="2073" RevisionGUID="b1baf569-2743-42f2-9b8c-3f6368b8f2a1" CreationDate="2016-02-19T18:31:02.727" UserId="56" Text="The three most common ways to interpolate vectors are:&#xD;&#xA;&#xD;&#xA; 1. Slerp - short for &quot;spherical interpolation&quot;, this is the most correct way, but is also the costliest.  In practice you likely do not need the precision.&#xD;&#xA; 2. lerp - short for &quot;linear interpolation&quot;, you just do a regular linear interpolation between the vectors and use that as a result.&#xD;&#xA; 3. nlerp - short for &quot;normalized linear interpolation&quot; you just normalize the result of a lerp.  Useful if you need your interpolated vector to be a normalized vector.&#xD;&#xA;&#xD;&#xA;In practice, lerp/nlerp are pretty good at getting a pretty close interpolated direction so long as the angle they are interpolating between is sufficiently small (say, 90 degrees, or 120 like Simon mentions in his comment), and nlerp is of course good at keeping the right length, if you need a normalized vector.  If you want to preserve the length while interpolating between non normalized vectors, you could always interpolate the length and direction separately.&#xD;&#xA;&#xD;&#xA;Here is an example of the three interpolations on a large angle.  Dark grey = start vector, light grey = end vector.  Green = slerp, blue = lerp, orange = nlerp.&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is an example of a medium sized angle (~90 degrees) interpolating the same time t between the angles:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Lastly, here's a smaller angle (~45 degrees).  You can see that the results of lerp / nlerp are more accurate as the angle between the interpolated vectors gets smaller.&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If you do lerp or nlerp, you can definitely do both bilinear as well as bicubic interpolation.&#xD;&#xA;&#xD;&#xA;Using slerp, you can do bilinear interpolation, but I'm not sure how bicubic would translate.&#xD;&#xA;&#xD;&#xA;I generated these images by taking screenshots from an interactive shadertoy demo I made to demonstrate these differences.  You can see that shadertoy here:&lt;br&gt;&#xD;&#xA;https://www.shadertoy.com/view/4sV3zt&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HByyL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CK2fe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cauR1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4618" PostHistoryTypeId="5" PostId="2073" RevisionGUID="f6eb6090-1f2b-4567-9e28-b1fe4e2c249a" CreationDate="2016-02-19T18:45:43.250" UserId="56" Comment="added 61 characters in body" Text="I did some research and found the answer I was looking for.  The three most common ways to interpolate vectors are:&#xD;&#xA;&#xD;&#xA; 1. Slerp - short for &quot;spherical interpolation&quot;, this is the most correct way, but is also the costliest.  In practice you likely do not need the precision.&#xD;&#xA; 2. lerp - short for &quot;linear interpolation&quot;, you just do a regular linear interpolation between the vectors and use that as a result.&#xD;&#xA; 3. nlerp - short for &quot;normalized linear interpolation&quot; you just normalize the result of a lerp.  Useful if you need your interpolated vector to be a normalized vector.&#xD;&#xA;&#xD;&#xA;In practice, lerp/nlerp are pretty good at getting a pretty close interpolated direction so long as the angle they are interpolating between is sufficiently small (say, 90 degrees, or 120 like Simon mentions in his comment), and nlerp is of course good at keeping the right length, if you need a normalized vector.  If you want to preserve the length while interpolating between non normalized vectors, you could always interpolate the length and direction separately.&#xD;&#xA;&#xD;&#xA;Here is an example of the three interpolations on a large angle.  Dark grey = start vector, light grey = end vector.  Green = slerp, blue = lerp, orange = nlerp.&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is an example of a medium sized angle (~90 degrees) interpolating the same time t between the angles:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Lastly, here's a smaller angle (~45 degrees).  You can see that the results of lerp / nlerp are more accurate as the angle between the interpolated vectors gets smaller.&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If you do lerp or nlerp, you can definitely do both bilinear as well as bicubic interpolation.&#xD;&#xA;&#xD;&#xA;Using slerp, you can do bilinear interpolation, but I'm not sure how bicubic would translate.&#xD;&#xA;&#xD;&#xA;I generated these images by taking screenshots from an interactive shadertoy demo I made to demonstrate these differences.  You can see that shadertoy here:&lt;br&gt;&#xD;&#xA;https://www.shadertoy.com/view/4sV3zt&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HByyL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CK2fe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cauR1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4619" PostHistoryTypeId="5" PostId="2073" RevisionGUID="c115ca9a-96ca-45bc-a1c6-ec4438838a22" CreationDate="2016-02-19T19:10:06.983" UserId="56" Comment="edited body" Text="I did some research and found the answer I was looking for.  The three most common ways to interpolate vectors are:&#xD;&#xA;&#xD;&#xA; 1. Slerp - short for &quot;spherical interpolation&quot;, this is the most correct way, but is also the costliest.  In practice you likely do not need the precision.&#xD;&#xA; 2. lerp - short for &quot;linear interpolation&quot;, you just do a regular linear interpolation between the vectors and use that as a result.&#xD;&#xA; 3. nlerp - short for &quot;normalized linear interpolation&quot; you just normalize the result of a lerp.  Useful if you need your interpolated vector to be a normalized vector.&#xD;&#xA;&#xD;&#xA;In practice, lerp/nlerp are pretty good at getting a pretty close interpolated direction so long as the angle they are interpolating between is sufficiently small (say, 90 degrees, or 120 like Simon mentions in his comment), and nlerp is of course good at keeping the right length, if you need a normalized vector.  If you want to preserve the length while interpolating between non normalized vectors, you could always interpolate the length and direction separately.&#xD;&#xA;&#xD;&#xA;Here is an example of the three interpolations on a large angle.  Dark grey = start vector, light grey = end vector.  Green = slerp, blue = lerp, orange = nlerp.&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is an example of a medium sized angle (~90 degrees) interpolating the same time t between the angles:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Lastly, here's a smaller angle (~35 degrees).  You can see that the results of lerp / nlerp are more accurate as the angle between the interpolated vectors gets smaller.&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If you do lerp or nlerp, you can definitely do both bilinear as well as bicubic interpolation.&#xD;&#xA;&#xD;&#xA;Using slerp, you can do bilinear interpolation, but I'm not sure how bicubic would translate.&#xD;&#xA;&#xD;&#xA;I generated these images by taking screenshots from an interactive shadertoy demo I made to demonstrate these differences.  You can see that shadertoy here:&lt;br&gt;&#xD;&#xA;https://www.shadertoy.com/view/4sV3zt&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HByyL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CK2fe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cauR1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4620" PostHistoryTypeId="5" PostId="2069" RevisionGUID="2af2e44e-0c1a-4579-9bf6-26805215f126" CreationDate="2016-02-19T20:06:51.320" UserId="48" Comment="added note on batching with variable sizes" Text="A key rule of thumb for high-performance code in general, and graphics in particular, is to batch large amounts of work together rather than doing it in small chunks. In your case, rather than sending one quad's worth of data at a time and drawing one quad at a time, it will be far more efficient to send many quads' data in a large batch, and draw many quads together in a single draw call.&#xD;&#xA;&#xD;&#xA;A good way to accomplish both is [instancing](https://www.opengl.org/wiki/Vertex_Rendering#Instancing). You would have a 4-point vertex buffer for the corners of a quad, and a second vertex buffer for the values that are per-quad (what you're putting in your uniform buffer now). This second buffer would be large enough to hold the data for all the quads at once, not just one quad. To populate the vertex buffer, you can map the whole thing, write all the data, and unmap. Then do a single instanced draw call to render all the quads at once.&#xD;&#xA;&#xD;&#xA;However, if instancing can't be used for some reason (for instance if each quad needs a different texture, and it's not possible or desirable to put them together in an atlas), you can still upload all the data in one batch. Create a uniform buffer large enough to hold an array of all the quads' data; map/write/unmap it all in one big batch as before; then before each draw call, use [`glBindBufferRange`](http://docs.gl/gl4/glBindBufferRange) to select one quad's data from that large buffer.&#xD;&#xA;&#xD;&#xA;Batching can also be used when you don't know the number of quads in advance. Just pick a &quot;reasonably large&quot; batch size (say, 1024 quads) and size your buffers for that number. Accumulate quads into the buffer until you reach the size limit, then draw them all, and start over (using the `GL_MAP_INVALIDATE_BUFFER_BIT` flag with `glMapBufferRange` to get a fresh copy of the buffer). You'll also need to do a partial draw at the end of this process to handle any left-over quads that didn't reach the size limit." ContentLicense="CC BY-SA 3.0" />
  <row Id="4622" PostHistoryTypeId="2" PostId="2074" RevisionGUID="88f6b8ff-2220-4f50-888f-99d3d1dae4ed" CreationDate="2016-02-19T23:18:25.597" UserId="2719" Text="I'm struggling with a problem with image rotation. I'm using the idea of &quot;Rotation by area mapping&quot; in the following link:&#xD;&#xA;http://www.leptonica.com/rotation.html&#xD;&#xA;&#xD;&#xA;My c# codes are as follows. The idea is first to find the dimension of the rotated image, then find the gray level of each pixel in the rotated image. To find the gray level for each pixel, the pixel coordinates are transformed back to the coordinates in the original image (called original pixel). The original pixel has fractional coordinate values, then the bilinear interpolation method in the link is used to obtain the gray level of the pixel in the rotated image. My codes did most of the job, except there are some clipping at the corners in the rotated image. I put the rotated images of a 16*16 image, we can clearly see the effect: The bottom line in the 45 degree rotated has no gray data; in the 90 degree rotated one, the vertical line in the left has no gray data; and in the 180 degree rotated one, both the vertical line in the left and the horizontal line on the top have no gray. I believe it's caused by the coordinate computation, and I could modify my code by subtracting one of the coordinates by 1 to achieve correct rotation by a certain angle, but it doesn't work for the other case. So I guess there must be something I ignored in my codes. Any suggestions and comments are appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    public void RotateImageClockwise(double degree)&#xD;&#xA;    {&#xD;&#xA;        Image&lt;double&gt; image = (Image&lt;double&gt;)(PreservedRawImage.Clone());      &#xD;&#xA;            double sinAngle = Math.Sin(Math.PI * degree / 180.0);&#xD;&#xA;            double cosAngle = Math.Cos(Math.PI * degree / 180.0);&#xD;&#xA;            double newHeightRaw, newWidthRaw;&#xD;&#xA;&#xD;&#xA;            ////Find the new dimensions of the rotated image.&#xD;&#xA;            if (Math.Abs(degree) &lt;= 90)&#xD;&#xA;            {&#xD;&#xA;                newHeightRaw = image.Width * sinAngle + image.Height * cosAngle;&#xD;&#xA;                newWidthRaw = image.Width * cosAngle + image.Height * sinAngle;&#xD;&#xA;            }&#xD;&#xA;            else if (Math.Abs(degree) &lt;= 180)&#xD;&#xA;            {&#xD;&#xA;                newHeightRaw = image.Width * Math.Sin(Math.PI * (180 - degree) / 180.0) + image.Height * Math.Sin(Math.PI * (degree - 90) / 180.0);&#xD;&#xA;                newWidthRaw = image.Width * Math.Cos(Math.PI * (180 - degree) / 180.0) + image.Height * Math.Cos(Math.PI * (degree - 90) / 180.0);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;                throw new Exception(&quot;Rotation angle is not right.&quot;);&#xD;&#xA;            ////Done with finding the new dimensions&#xD;&#xA;&#xD;&#xA;            double newWidthHalf = newWidthRaw / 2;&#xD;&#xA;            double newHeightHalf = newHeightRaw / 2;&#xD;&#xA;&#xD;&#xA;            int newWidth = (int)Math.Round(newWidthRaw);&#xD;&#xA;            int newHeight = (int)Math.Round(newHeightRaw);&#xD;&#xA;            Image&lt;double&gt; newImage = new Image&lt;double&gt;(newWidth, newHeight);&#xD;&#xA;            byte[] bitmap = new byte[newWidth * newHeight];&#xD;&#xA;            double newMax = double.MinValue, newMin = double.MaxValue;&#xD;&#xA;            for (int x = 0; x &lt; newHeight; x++)&#xD;&#xA;            {&#xD;&#xA;                for (int y = 0; y &lt; newWidth; y++)&#xD;&#xA;                {&#xD;&#xA;                    ////Transform the coordinates to be centered at the center of the image&#xD;&#xA;                    double xt = x - newHeightHalf;&#xD;&#xA;                    double yt = y - newWidthHalf;&#xD;&#xA;&#xD;&#xA;                    double originalX = xt * cosAngle - yt * sinAngle + image.Height / 2.0;&#xD;&#xA;                    double originalY = xt * sinAngle + yt * cosAngle + image.Width / 2.0;&#xD;&#xA;&#xD;&#xA;                    double fractionX = Math.Abs(originalX - (int)Math.Round(originalX));&#xD;&#xA;                    double fractionY = Math.Abs(originalY - (int)Math.Round(originalY));&#xD;&#xA;&#xD;&#xA;                    ////Find the neighbors of the pixel in the original image&#xD;&#xA;                    IList&lt;Point&lt;int&gt;&gt; neighbors = new List&lt;Point&lt;int&gt;&gt; { new Point&lt;int&gt;{x = (int)Math.Round(originalX), y = (int)Math.Round(originalY), weight = (1 - fractionX) * (1 - fractionY)}, &#xD;&#xA;                                                               new Point&lt;int&gt;{x = (int)Math.Round(originalX), y = (int)Math.Round(originalY) + 1, weight = fractionX * (1 - fractionY)},&#xD;&#xA;                                                               new Point&lt;int&gt;{x = (int)Math.Round(originalX) + 1, y = (int)Math.Round(originalY), weight = (1 - fractionX) * fractionY},&#xD;&#xA;                                                               new Point&lt;int&gt;{x = (int)Math.Round(originalX) + 1, y = (int)Math.Round(originalY) + 1, weight = fractionX * fractionY}&#xD;&#xA;                                                             };&#xD;&#xA;                    bool hasData = false;&#xD;&#xA;                    double newData = 0;&#xD;&#xA;                    double weight = 0;&#xD;&#xA;                    foreach (var neighbor in neighbors)&#xD;&#xA;                    {&#xD;&#xA;                        if (neighbor.x &gt;= 0 &amp;&amp; neighbor.x &lt; image.Height&#xD;&#xA;                            &amp;&amp; neighbor.y &gt;= 0 &amp;&amp; neighbor.y &lt; image.Width&#xD;&#xA;                           )&#xD;&#xA;                        {&#xD;&#xA;                            hasData = true;&#xD;&#xA;                            newData += neighbor.weight * image.Data[(neighbor.x) * image.Width + neighbor.y];&#xD;&#xA;                            weight += neighbor.weight;&#xD;&#xA;                        }&#xD;&#xA;                    }                    &#xD;&#xA;                    if (hasData &amp;&amp; weight != 0)&#xD;&#xA;                    {&#xD;&#xA;                        newData /= weight;&#xD;&#xA;                        newImage.Data[x * newWidth + y] = newData;&#xD;&#xA;                    }&#xD;&#xA;                }                &#xD;&#xA;            }            &#xD;&#xA;        } &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dyDw6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4623" PostHistoryTypeId="1" PostId="2074" RevisionGUID="88f6b8ff-2220-4f50-888f-99d3d1dae4ed" CreationDate="2016-02-19T23:18:25.597" UserId="2719" Text="Rotate image around its center" ContentLicense="CC BY-SA 3.0" />
  <row Id="4624" PostHistoryTypeId="3" PostId="2074" RevisionGUID="88f6b8ff-2220-4f50-888f-99d3d1dae4ed" CreationDate="2016-02-19T23:18:25.597" UserId="2719" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4625" PostHistoryTypeId="2" PostId="2075" RevisionGUID="a9127414-a64b-4a55-9936-6258c89e73f2" CreationDate="2016-02-20T07:18:32.540" UserId="38" Text="This is more of a long comment, with an image, than an answer.&#xD;&#xA;&#xD;&#xA;Seems to me at a quick glance that you consider your pixels center to be at integer values. Instead in reality the pixel center is located 0.5 pixels of this location.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Is the pixel sample located at its integer coordinate? Or is it located offset by 0.5 pixels?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0UGXJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4626" PostHistoryTypeId="5" PostId="2075" RevisionGUID="a08c4a43-bd22-4358-861d-216baa5fb791" CreationDate="2016-02-20T07:24:04.553" UserId="38" Comment="added 3 characters in body" Text="This is more of a long comment, with an image, than an answer.&#xD;&#xA;&#xD;&#xA;Seems to me, at a quick glance, that you consider your pixels sample point to be at integer values. Instead in reality sample is located offset 0.5 pixels of this location.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Is the pixel sample located at its integer coordinate? Or is it located offset by 0.5 pixels?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0UGXJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4627" PostHistoryTypeId="2" PostId="2076" RevisionGUID="6e72400b-4d40-4029-a66e-4ca3ee39088b" CreationDate="2016-02-20T11:38:53.557" UserId="1937" Text="I've mostly succeeded at porting an implementation of Marching Cubes from CPU over to OpenGL compute shaders, but I haven't tackled normals yet and wondering the best way to go about it.&#xD;&#xA;&#xD;&#xA;My implementation deals specifically with binary valued fields (I'm trying to model 3D fractal functions that don't have a distance estimator yet), so gradient and forward differences methods won't work. I have shared vertices working, and my CPU implementation uses Quilez's method described [here](http://www.iquilezles.org/www/articles/normals/normals.htm) to accumulate face normals onto each neighbouring vertex.&#xD;&#xA;&#xD;&#xA;I could just port this implementation over to another shader, but the problem I see with this is the massive number of atomics needed. Since we can only use atomics on scalar integer types, and I cant think of a way to pack 3 signed ints into 1 in a summable way, that means 3 axes * 3 vertices = 9 atomic adds per shader invocation. They'll be spread throughout memory of course so it's not like hitting a single atomic counter 9 times, but it still seems like a hell of a lot.&#xD;&#xA;&#xD;&#xA;The other alternative is to run a shader invocation per-polygon and build the face normal list (i could probably pack to x10y10z10 this way), then a shader per-vertex to accumulate all the normals of neighbouring faces. This would be an enormous memory hog though, the storage space of the face indices would need 12 int per vertex to deal with the worst case. There's also the problem of how to write into this storage without again resorting to atomics to work out how many faces have already been written to a particular vertex.&#xD;&#xA;&#xD;&#xA;Anyone have any better ideas on how to do this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4628" PostHistoryTypeId="1" PostId="2076" RevisionGUID="6e72400b-4d40-4029-a66e-4ca3ee39088b" CreationDate="2016-02-20T11:38:53.557" UserId="1937" Text="Creating shared vertex normals on GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="4629" PostHistoryTypeId="3" PostId="2076" RevisionGUID="6e72400b-4d40-4029-a66e-4ca3ee39088b" CreationDate="2016-02-20T11:38:53.557" UserId="1937" Text="|opengl|gpu|mesh|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4630" PostHistoryTypeId="34" PostId="2037" RevisionGUID="2cc049b7-a1a3-49a9-a3a8-14627ba5dcbd" CreationDate="2016-02-20T18:30:14.977" UserId="2646" Comment="13" />
  <row Id="4631" PostHistoryTypeId="2" PostId="2077" RevisionGUID="232a10e1-9fce-4fcc-af6e-d310cb261563" CreationDate="2016-02-20T19:08:41.227" UserId="2726" Text="I've recently made the switch to Visual 2015 and the .fx files have been depreciated. My project contained .fx files for the shaders so I've been switching over.&#xD;&#xA;&#xD;&#xA;Only during the switch have I changed to using deferred rendering for lighting.&#xD;&#xA;&#xD;&#xA;The only shader I've made so far is the Pixel Shader that is used on the 2nd Pass, the shader that does the Per Pixel x Per Light calculations, sums them, and outputs final color.&#xD;&#xA;&#xD;&#xA;However, whenever I compile (I'm not actually using the shader in runtime, I'm just getting it all setup, the window is still just cleared to a color every frame, no actual rendering) I get a failure that says....&#xD;&#xA;&#xD;&#xA;error X4502: Shader model ps_4_0_level_9_3 doesn't allow reading from position semantics.&#xD;&#xA;&#xD;&#xA;Here is the only shader I have in the project that is causing this error.&#xD;&#xA;&#xD;&#xA;I omitted the getGBufferAttributes and calculateLighting methods because I know they are not the issue. &#xD;&#xA;&#xD;&#xA;    Texture2D NormalTexture					: register(t0);&#xD;&#xA;    Texture2D DiffuseAlbedoTexture			: register(t1);&#xD;&#xA;    Texture2D SpecularAlbedoTexture			: register(t2);&#xD;&#xA;    Texture2D PositionTexture				: register(t3);&#xD;&#xA;&#xD;&#xA;    cbuffer LightParams&#xD;&#xA;    {&#xD;&#xA;	    float3 LightPos;&#xD;&#xA;	    float3 LightColor;&#xD;&#xA;	    float3 LightDirection;&#xD;&#xA;	    float2 SpotlightAngles;&#xD;&#xA;	    float4 LightRange;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    cbuffer CameraParams&#xD;&#xA;    {&#xD;&#xA;	    float3 CameraPos;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    float4 main(in float4 screenPos : SV_Position) : SV_Target0&#xD;&#xA;    {&#xD;&#xA;	    float3 normal;&#xD;&#xA;	    float3 position;&#xD;&#xA;	    float3 diffuseAlbedo;&#xD;&#xA;	    float3 specularAlbedo;&#xD;&#xA;	    float specularPower;&#xD;&#xA;&#xD;&#xA;	    getGBufferAttributes(screenPos.xy, normal, position, diffuseAlbedo, specularAlbedo, specularPower);&#xD;&#xA;&#xD;&#xA;	    float3 lighting = calculateLighting(normal, position, diffuseAlbedo, specularAlbedo, specularPower);&#xD;&#xA;&#xD;&#xA;	    return float4(lighting, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code used for this shader is highly based off the code used as the deferred rendering example in the book, Practical Rendering with Direct3D 11 by Jason Zink, Matt Pettineo, and Jack Hoxley.&#xD;&#xA;&#xD;&#xA;I don't understand why they would give source code that doesn't work. Does it have something to do with the new compiler in Visual 2015 and the Runtime?&#xD;&#xA;&#xD;&#xA;Also, since I'm going from only using effects before to now raw HLSL shaders, is there anything I should be aware of that might trip somebody like me up?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4632" PostHistoryTypeId="1" PostId="2077" RevisionGUID="232a10e1-9fce-4fcc-af6e-d310cb261563" CreationDate="2016-02-20T19:08:41.227" UserId="2726" Text="HLSL Deferred Rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="4633" PostHistoryTypeId="3" PostId="2077" RevisionGUID="232a10e1-9fce-4fcc-af6e-d310cb261563" CreationDate="2016-02-20T19:08:41.227" UserId="2726" Text="|shader|directx11|pixel-shader|hlsl|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4634" PostHistoryTypeId="2" PostId="2078" RevisionGUID="12833da0-88bd-485b-9b39-068ce6b5e407" CreationDate="2016-02-20T19:43:53.280" UserId="2712" Text="I am going throug the topic scan line conversion where the scan line parallel to the x-axis is put through the intersection test with all the edges of the polygon. &#xD;&#xA;&#xD;&#xA;Would there be any large theoretical differences if we take a small line segment instead, between (x1,y1) and (x2,y2) that is parallel to the x-axis or y-axis and test for intersection with the polygon edges ? The usual case the y = a ( parallel to x-axis) and what I am asking is also parallel to x-axis or y-axis,but constrained between two points instead.&#xD;&#xA;&#xD;&#xA;Some explanations/references are eagerly requested.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 3.0" />
  <row Id="4635" PostHistoryTypeId="1" PostId="2078" RevisionGUID="12833da0-88bd-485b-9b39-068ce6b5e407" CreationDate="2016-02-20T19:43:53.280" UserId="2712" Text="scan line conversion" ContentLicense="CC BY-SA 3.0" />
  <row Id="4636" PostHistoryTypeId="3" PostId="2078" RevisionGUID="12833da0-88bd-485b-9b39-068ce6b5e407" CreationDate="2016-02-20T19:43:53.280" UserId="2712" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4637" PostHistoryTypeId="5" PostId="2073" RevisionGUID="2c9426b2-d467-43ea-bf7e-c7953037cf90" CreationDate="2016-02-20T20:09:48.967" UserId="56" Comment="The demo that made the images didn't show the right length of the lerped vector (blue). fixed and updated images" Text="I did some research and found the answer I was looking for.  The three most common ways to interpolate vectors are:&#xD;&#xA;&#xD;&#xA; 1. Slerp - short for &quot;spherical interpolation&quot;, this is the most correct way, but is also the costliest.  In practice you likely do not need the precision.&#xD;&#xA; 2. lerp - short for &quot;linear interpolation&quot;, you just do a regular linear interpolation between the vectors and use that as a result.&#xD;&#xA; 3. nlerp - short for &quot;normalized linear interpolation&quot; you just normalize the result of a lerp.  Useful if you need your interpolated vector to be a normalized vector.&#xD;&#xA;&#xD;&#xA;In practice, lerp/nlerp are pretty good at getting a pretty close interpolated direction so long as the angle they are interpolating between is sufficiently small (say, 90 degrees, or 120 like Simon mentions in his comment), and nlerp is of course good at keeping the right length, if you need a normalized vector.  If you want to preserve the length while interpolating between non normalized vectors, you could always interpolate the length and direction separately.&#xD;&#xA;&#xD;&#xA;Here is an example of the three interpolations on a large angle.  Dark grey = start vector, light grey = end vector.  Green = slerp, blue = lerp, orange = nlerp.&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is an example of a medium sized angle (~90 degrees) interpolating the same time t between the angles:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Lastly, here's a smaller angle (~35 degrees).  You can see that the results of lerp / nlerp are more accurate as the angle between the interpolated vectors gets smaller.&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If you do lerp or nlerp, you can definitely do both bilinear as well as bicubic interpolation.&#xD;&#xA;&#xD;&#xA;Using slerp, you can do bilinear interpolation, but I'm not sure how bicubic would translate.&#xD;&#xA;&#xD;&#xA;I generated these images by taking screenshots from an interactive shadertoy demo I made to demonstrate these differences.  You can see that shadertoy here:&lt;br&gt;&#xD;&#xA;https://www.shadertoy.com/view/4sV3zt&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LaV6S.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2gjmE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/mrUqf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4638" PostHistoryTypeId="2" PostId="2079" RevisionGUID="aab52045-e379-464c-8b5b-0318700a5b6e" CreationDate="2016-02-20T20:40:35.193" UserId="2726" Text="A very novice mistake, I was compiling with the old HLSL compiler. But why would that be the default? Very strange.&#xD;&#xA;&#xD;&#xA;For anybody wondering, just right click the HLSL file in the solution explorer and go to properties -&gt; HLSL Compiler -&gt; General, and switch Shader Model to the one you want which was newest one for me (5.0)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4639" PostHistoryTypeId="2" PostId="2080" RevisionGUID="b38983e8-cbd3-4145-9242-1fcf72798f51" CreationDate="2016-02-20T23:40:52.130" UserId="2684" Text="I am looking for a explanation about volume rendering in simple words, a step by step kind of, like ray tracing: &#xD;&#xA;&#xD;&#xA;&gt; for every pixel in the screen plane, trace a ray starting from the eye&#xD;&#xA;&gt; point to the screen pixel location, a compute the nearest objet&#xD;&#xA;&gt; intersection in the scene, calculate the pixel color, and so on.&#xD;&#xA;&#xD;&#xA;something like that&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4640" PostHistoryTypeId="1" PostId="2080" RevisionGUID="b38983e8-cbd3-4145-9242-1fcf72798f51" CreationDate="2016-02-20T23:40:52.130" UserId="2684" Text="Volume Rendering in simple words" ContentLicense="CC BY-SA 3.0" />
  <row Id="4641" PostHistoryTypeId="3" PostId="2080" RevisionGUID="b38983e8-cbd3-4145-9242-1fcf72798f51" CreationDate="2016-02-20T23:40:52.130" UserId="2684" Text="|volumetric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4642" PostHistoryTypeId="2" PostId="2081" RevisionGUID="d4ee0980-f45e-4c94-9114-218400ff11a4" CreationDate="2016-02-21T00:44:30.847" UserId="1810" Text="Volume rendering is not like ray-tracing, it is like &quot;scene rendering&quot;. i.e. there exists several algorithms to render volumes.&#xD;&#xA;&#xD;&#xA;One close to ray-tracing is ray-marching, and has may variants. The simplest:&#xD;&#xA;*for every pixel in the screen plane, trace a ray starting from the eye point to the screen pixel location, and advance along the ray by constant steps. At each voxel calculate the pixel color and transparency, blend it to the pixel value, and so on.*&#xD;&#xA;&#xD;&#xA;Blend = &#xD;&#xA;&#xD;&#xA;- $C_{tot} += T_{tot}*C_{pix}*(1-T_{pix})$ &#xD;&#xA;&#xD;&#xA;-  $T_{tot} *= T_{pix}$" ContentLicense="CC BY-SA 3.0" />
  <row Id="4643" PostHistoryTypeId="5" PostId="2081" RevisionGUID="42fabaff-af74-47e5-883d-3b3aa2a42928" CreationDate="2016-02-21T09:41:26.677" UserId="1810" Comment="added 148 characters in body" Text="Volume rendering is not like ray-tracing, it is like &quot;scene rendering&quot;. i.e. there exists several algorithms to render volumes.&#xD;&#xA;&#xD;&#xA;One close to ray-tracing is ray-marching, and has may variants. The simplest:&#xD;&#xA;*for every pixel in the screen plane, trace a ray starting from the eye point to the screen pixel location, and advance along the ray by constant steps. At each voxel calculate the pixel color and transparency, blend it to the pixel value, and so on.*&#xD;&#xA;&#xD;&#xA;Blend = &#xD;&#xA;&#xD;&#xA;- $C_{pix} += T_{pix}*C_{vox}*(1-T_{vox})$ &#xD;&#xA;&#xD;&#xA;-  $T_{pix} *= T_{vox}$&#xD;&#xA;&#xD;&#xA;with $C_{vox},T_{vox}$ the color and transparency of the current voxel, and $C_{pix},T_{pix}$ the cumulated color and transparency of the pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="4644" PostHistoryTypeId="5" PostId="2078" RevisionGUID="f30d361e-b949-4a08-b493-58c59f0b1218" CreationDate="2016-02-21T12:06:38.850" UserId="2712" Comment="added 1066 characters in body" Text="I am going throug the topic scan line conversion where the scan line parallel to the x-axis is put through the intersection test with all the edges of the polygon. &#xD;&#xA;&#xD;&#xA;Would there be any large theoretical differences if we take a small line segment instead, between (x1,y1) and (x2,y2) that is parallel to the x-axis or y-axis and test for intersection with the polygon edges ? The usual case the y = a ( parallel to x-axis) and what I am asking is also parallel to x-axis or y-axis,but constrained between two points instead.&#xD;&#xA;&#xD;&#xA;I am trying to develop a tool-path for 3D printing and looking forward to implement HIlbert curve as a tool-path. Generally the very same scan-line concept is used in 3D printing techniques whenever it comes to tool-path generation where parallel scan line to x-axis is used for scanline and polygon edges interesection. I have already got the typical linear scan line for 3D printing and looking forward to implement another way to maneuever the printing head according to the Hilbert curve. In Hilbert curve you have a line segments that change its orientation in such a calculated manner it never self-intersects and simple it follows the FASS characteristics. Hilbert curve containes several small line segments that are parallel to x-axis or y-axis. I am trying to narrow it down to the one line segment of Hilbert curve where the intersection test is to be conducted between one line segment [ (x1,y1) and (x2,y2) ] and the polygon edges.&#xD;&#xA;&#xD;&#xA;I hope that I explained the issue well enough to get some hints to the question asked. Please do ask if anything that I have explained so far is not clear enough.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks    &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4645" PostHistoryTypeId="2" PostId="2082" RevisionGUID="7bd57210-0085-453c-8e0e-94479ca78590" CreationDate="2016-02-21T17:39:54.433" UserId="38" Text="You could do this. Basically what you would do is generate a cube for each voxel (or actually nearby voxels could share the edges). Not exactly sure what benefit you would get form this, unless your intersection algorithm is somehow extremely finely tuned. It could be useful for real time rendering or some sort of sparse structure. While your at it why not dispense of the voxel concept altogether and go all FEM on the problem.&#xD;&#xA;&#xD;&#xA;The thing is you want a more uniform sampling across the volumes density function. Because your integrating over a volume functions you want the step size to be somewhat equally spaced so you can control the integration better. Random or pseudo random solution converges often better, but mainly you do not do cube oriented sampling this way as it will make the structure obvious which is not your goal in most cases. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Different sampling strategies. Images in RTL reading order samples along voxel grids,  Uniforms sampling and jittered ray length sampling.&#xD;&#xA;&#xD;&#xA;Think of this as solving a ODE you sample the function uniformly and if your value changes too much you might do additional samples. This is probably the reason why you wouldn't really do collision to the voxels.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HaXGH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4646" PostHistoryTypeId="2" PostId="2083" RevisionGUID="04b5a6d7-1f84-406a-bb24-35a0f4f4c188" CreationDate="2016-02-21T21:44:14.300" UserId="1810" Text="I know that by now it might be considered as a kind of sad recurrent joke, but by chance, does anyone here has the least information about the colorspace of RGB values in the MERL BRDF measurement database ? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4647" PostHistoryTypeId="1" PostId="2083" RevisionGUID="04b5a6d7-1f84-406a-bb24-35a0f4f4c188" CreationDate="2016-02-21T21:44:14.300" UserId="1810" Text="Color space of MERL BRDF database?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4648" PostHistoryTypeId="3" PostId="2083" RevisionGUID="04b5a6d7-1f84-406a-bb24-35a0f4f4c188" CreationDate="2016-02-21T21:44:14.300" UserId="1810" Text="|color-management|capture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4654" PostHistoryTypeId="2" PostId="2085" RevisionGUID="d993941e-d955-4a63-96c1-e41cf35f1e67" CreationDate="2016-02-22T21:48:31.237" UserId="2720" Text="Thanks for the replies. According to joojaa's comments, I modified my codes as below,&#xD;&#xA;&#xD;&#xA;    public void RotateImageClockwise(double degree)&#xD;&#xA;        {&#xD;&#xA;            Image&lt;double&gt; image = (Image&lt;double&gt;)(PreservedRawImage.Clone());      &#xD;&#xA;            double sinAngle = Math.Sin(Math.PI * degree / 180.0);&#xD;&#xA;            double cosAngle = Math.Cos(Math.PI * degree / 180.0);&#xD;&#xA;            double newHeightRaw, newWidthRaw;&#xD;&#xA;&#xD;&#xA;            if (Math.Abs(degree) &lt;= 90)&#xD;&#xA;            {&#xD;&#xA;                newHeightRaw = image.Width * Math.Sin(Math.PI * (Math.Abs(degree)) / 180.0) + image.Height * Math.Cos(Math.PI * Math.Abs(degree) / 180.0);&#xD;&#xA;                newWidthRaw = image.Width * Math.Cos(Math.PI * Math.Abs(degree) / 180.0) + image.Height * Math.Sin(Math.PI * (Math.Abs(degree)) / 180.0);&#xD;&#xA;            }&#xD;&#xA;            else if (Math.Abs(degree) &lt;= 180)&#xD;&#xA;            {&#xD;&#xA;                newHeightRaw = image.Width * Math.Sin(Math.PI * (180 - Math.Abs(degree)) / 180.0) + image.Height * Math.Sin(Math.PI * (Math.Abs(degree) - 90) / 180.0);&#xD;&#xA;                newWidthRaw = image.Width * Math.Cos(Math.PI * (180 - Math.Abs(degree)) / 180.0) + image.Height * Math.Cos(Math.PI * (Math.Abs(degree) - 90) / 180.0);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            int newWidth = (int)Math.Round(newWidthRaw);&#xD;&#xA;            int newHeight = (int)Math.Round(newHeightRaw);&#xD;&#xA;            Image&lt;double&gt; newImage = new Image&lt;double&gt;(newWidth, newHeight);&#xD;&#xA;            for (int x = 0; x &lt; newHeight; x++)&#xD;&#xA;            {&#xD;&#xA;                for (int y = 0; y &lt; newWidth; y++)&#xD;&#xA;                {&#xD;&#xA;                    double xt = x - (newHeightRaw - 1) / 2.0;&#xD;&#xA;                    double yt = y - (newWidthRaw - 1) / 2.0;&#xD;&#xA;&#xD;&#xA;                    double originalX = xt * cosAngle - yt * sinAngle + (image.Height - 1) / 2.0;&#xD;&#xA;                    double originalY = xt * sinAngle + yt * cosAngle + (image.Width - 1) / 2.0;&#xD;&#xA;&#xD;&#xA;                    double fractionX = Math.Abs(originalX - (int)Math.Round(originalX));&#xD;&#xA;                    double fractionY = Math.Abs(originalY - (int)Math.Round(originalY));&#xD;&#xA;&#xD;&#xA;                    IList&lt;Point&lt;int&gt;&gt; neighbors = new List&lt;Point&lt;int&gt;&gt; { new Point&lt;int&gt;{x = (int)Math.Round(originalX), y = (int)Math.Round(originalY), weight = (1 - fractionX) * (1 - fractionY)}, &#xD;&#xA;                                                               new Point&lt;int&gt;{x = (int)Math.Round(originalX), y = (int)Math.Round(originalY) + 1, weight = fractionX * (1 - fractionY)},&#xD;&#xA;                                                               new Point&lt;int&gt;{x = (int)Math.Round(originalX) + 1, y = (int)Math.Round(originalY), weight = (1 - fractionX) * fractionY},&#xD;&#xA;                                                               new Point&lt;int&gt;{x = (int)Math.Round(originalX) + 1, y = (int)Math.Round(originalY) + 1, weight = fractionX * fractionY}&#xD;&#xA;                                                             };&#xD;&#xA;                    bool hasData = false;&#xD;&#xA;                    double newData = 0;&#xD;&#xA;                    double weight = 0;&#xD;&#xA;                    foreach (var neighbor in neighbors)&#xD;&#xA;                    {&#xD;&#xA;                        if (neighbor.x &gt;= 0 &amp;&amp; neighbor.x &lt; image.Height&#xD;&#xA;                            &amp;&amp; neighbor.y &gt;= 0 &amp;&amp; neighbor.y &lt; image.Width&#xD;&#xA;                            &amp;&amp; (neighbor.x) * image.Width + neighbor.y &lt; m_preservedImageValidDataBitmap.Length &amp;&amp; m_preservedImageValidDataBitmap[(neighbor.x) * image.Width + neighbor.y] == 'T')&#xD;&#xA;                        {&#xD;&#xA;                            hasData = true;&#xD;&#xA;                            newData += neighbor.weight * image.Data[(neighbor.x) * image.Width + neighbor.y];&#xD;&#xA;                            weight += neighbor.weight;&#xD;&#xA;                        }&#xD;&#xA;                    }                    &#xD;&#xA;                    if (hasData &amp;&amp; weight != 0)&#xD;&#xA;                    {&#xD;&#xA;                        newData /= weight;&#xD;&#xA;                        newImage.Data[x * newWidth + y] = newData;                        &#xD;&#xA;                    }&#xD;&#xA;                }                &#xD;&#xA;            }&#xD;&#xA;        } &#xD;&#xA;Now it's working for 90 and 180 degree rotations. But for 45 degree rotation, the bottom line is still blank, which makes me crazy. I'm guessing it's due to the computation inaccuracy when the new image width and height are computed, but I still can't figure it out.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OQB9E.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4655" PostHistoryTypeId="2" PostId="2086" RevisionGUID="8152cf99-5f22-4693-943b-da11e4aaeb68" CreationDate="2016-02-23T09:43:40.470" UserId="110" Text="As explained in Holger Dammetz page [Hammersley Points on the Hemisphere][1], the 2D coordinates (u,v) are usually mapped to the spherical coordinates (θ, φ).&#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;As a result, the coordinate &quot;uniformly distributed&quot; - u in the 2D case - is the polar angle θ. This looks counter-intuitive to me, I would have mapped regularly spaced u values to regularly spaced azimuth φ values. To avoid &quot;empty areas&quot; like in this example:  &#xD;&#xA;[![enter image description here][3]][3]   &#xD;&#xA;which is generated by the mapping of the following 2D set:  &#xD;&#xA;[![enter image description here][4]][4]  &#xD;&#xA;What is the reason not to map (u, v) to (φ, θ) ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/zOAcc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/R0lK7.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/9DZEr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4656" PostHistoryTypeId="1" PostId="2086" RevisionGUID="8152cf99-5f22-4693-943b-da11e4aaeb68" CreationDate="2016-02-23T09:43:40.470" UserId="110" Text="Why map Hammersley 2D set's (u,v) to sphere's (θ, φ) coordinates (and not to (φ, θ) )?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4657" PostHistoryTypeId="3" PostId="2086" RevisionGUID="8152cf99-5f22-4693-943b-da11e4aaeb68" CreationDate="2016-02-23T09:43:40.470" UserId="110" Text="|2d|sampling|mapping|distribution|hemisphere|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4658" PostHistoryTypeId="2" PostId="2087" RevisionGUID="36de5d98-e866-4e3c-9eef-bbc894d5b932" CreationDate="2016-02-23T12:55:57.477" UserId="2687" Text="So, recently I followed this [tutorial](http://www.paulsprojects.net/tutorials/smt/smt.html) about shadow mapping, but in the tutorial it doesn't texture the object.. When I try to add a texture, it's distorted by the `TexGen`. Also I've tried to use `glActiveTexture()` with no success(dunno exactly how `glActiveTexture()` work).&#xD;&#xA;&#xD;&#xA;So can anyone help me by adding textures into above code base? From there, I can learn how to use `glActiveTexture()` and overcome that `TexGen` issue.&#xD;&#xA;&#xD;&#xA;Thanks in advance.. To note, I'm not using GLSL." ContentLicense="CC BY-SA 3.0" />
  <row Id="4659" PostHistoryTypeId="1" PostId="2087" RevisionGUID="36de5d98-e866-4e3c-9eef-bbc894d5b932" CreationDate="2016-02-23T12:55:57.477" UserId="2687" Text="How can I use multiple texturing with shadow mapping?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4660" PostHistoryTypeId="3" PostId="2087" RevisionGUID="36de5d98-e866-4e3c-9eef-bbc894d5b932" CreationDate="2016-02-23T12:55:57.477" UserId="2687" Text="|opengl|texture|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4661" PostHistoryTypeId="2" PostId="2088" RevisionGUID="87f08ca2-5a7f-4ad6-8a1a-6cd3c12101cd" CreationDate="2016-02-23T15:33:31.027" UserId="2562" Text="I have a set of 3D points (which I recover from a library that performs the tessellation of a solid body) that belong to a curve (i.e., an edge of the solid). That means that the curve surely passes by each of these points.&#xD;&#xA;&#xD;&#xA;Nevertheless, the point set is unordered so I need to sort them in order to be able to draw this curve correctly.&#xD;&#xA;&#xD;&#xA;Is there any known approach for these type of problem?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4662" PostHistoryTypeId="1" PostId="2088" RevisionGUID="87f08ca2-5a7f-4ad6-8a1a-6cd3c12101cd" CreationDate="2016-02-23T15:33:31.027" UserId="2562" Text="Ordering a set of unorganized points along a curve" ContentLicense="CC BY-SA 3.0" />
  <row Id="4663" PostHistoryTypeId="3" PostId="2088" RevisionGUID="87f08ca2-5a7f-4ad6-8a1a-6cd3c12101cd" CreationDate="2016-02-23T15:33:31.027" UserId="2562" Text="|geometry|mesh|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4664" PostHistoryTypeId="2" PostId="2089" RevisionGUID="38b2fbf7-b51e-43db-a78c-2d1bafe54250" CreationDate="2016-02-23T16:09:39.853" UserId="16" Text="Since you've only got floating-point representations of the points, there is no guarantee that these still lie exactly on the curve, due to rounding errors. So I think the only generic approach is to approximate where on the curve they were, by finding the closest point on the curve to your sample $(X,Y,Z)$. E.g. if your parametric curve is $(x(t), y(t), z(t))$ then you could try to minimise&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(X-x(t))^2+(Y-y(t))^2+(Z-z(t))^2&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with respect to $t$. If you know what type of curve you're dealing with there might be nice analytic solutions to this, otherwise you'll have to resort to some numerical algorithm. Since your points should be very close to the curve, this method should be reliable (provided the minimisation algorithm is), unless you have a sample exactly where the curve (almost) crosses itself. In that case you're probably out of luck anyway, though.&#xD;&#xA;&#xD;&#xA;Once you have that $t$ for each of your points, you can simply sort them by $t$. Of course, if you have any control over how you receive the points you might be able to sidestep all of this trouble by returning $t$ along with the point's coordinates right away while generating them." ContentLicense="CC BY-SA 3.0" />
  <row Id="4665" PostHistoryTypeId="5" PostId="2088" RevisionGUID="81fed0de-3613-4dbd-b340-58c6cdb3af93" CreationDate="2016-02-23T16:29:09.667" UserId="16" Comment="thanks, greetings and taglines are generally discouraged on SE" Text="I have a set of 3D points (which I recover from a library that performs the tessellation of a solid body) that belong to a curve (i.e., an edge of the solid). That means that the curve surely passes by each of these points.&#xD;&#xA;&#xD;&#xA;Nevertheless, the point set is unordered so I need to sort them in order to be able to draw this curve correctly.&#xD;&#xA;&#xD;&#xA;Is there any known approach for these type of problem?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4666" PostHistoryTypeId="5" PostId="2088" RevisionGUID="5ec50b1f-7906-4943-94bc-3471cddbdbcc" CreationDate="2016-02-23T16:47:04.640" UserId="2562" Comment="added 373 characters in body" Text="I have a set of 3D points (which I recover from a library that performs the tessellation of a solid body) that belong to a curve (i.e., an edge of the solid). That means that the curve surely passes by each of these points.&#xD;&#xA;&#xD;&#xA;Nevertheless, the point set is unordered so I need to sort them in order to be able to draw this curve correctly.&#xD;&#xA;&#xD;&#xA;Is there any known approach for these type of problem?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some additional information:&#xD;&#xA;&#xD;&#xA;The points are packed very densely (but they can be as dense as I want it to be). To give you an idea, for a curve which occupies 19 units in x, 10 units in x and 5 units in z, I quote a sequence of points in a segment of curve: (20.7622, 25.8676, 0) (20.6573, 25.856, 0) (20.5529, 25.8444, 0) (20.4489, 25.8329, 0) (20.3454, 25.8213, 0)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4667" PostHistoryTypeId="2" PostId="2090" RevisionGUID="7f09bd74-b7ff-411b-862d-08bdb4f7c531" CreationDate="2016-02-23T16:48:34.430" UserId="16" Text="After some clarifications, there is probably a much better approach that doesn't even require knowing the parametric form of the curve, and also avoids the potentially problematic numeric minimisation step. &#xD;&#xA;&#xD;&#xA;If the curve does not intersect itself and the points are sufficiently densely packed on the curve (and by that I mean they have to be closer than any two points on the curve that *don't* belong to the same segment, e.g. by the curve wrapping around on itself), then you can easily determine the previous and next point to each sample:&#xD;&#xA;&#xD;&#xA;- Determine the two nearest neighbours to each point. [That's an $O(n \log n)$ operation](https://en.wikipedia.org/wiki/Nearest_neighbor_search#All_nearest_neighbors).&#xD;&#xA;- You'll have to do some special treatment for the endpoints. Their two nearest neighbours will be the next *two* points along the curve instead of one on each side. You can either detect these heuristically if the ratio  of the distances to the two neighbours differs by more than some threshold (1.5 say, depends on the smoothness of your curve and how densely the points are packed). Or you can treat your nearest-neighbour data as a graph, in which you'll find that the endpoints' two neighbours point at each other (which shouldn't happen anywhere else in the graph).&#xD;&#xA;- Now you can simply pick one end point, and walk along the nearest neighbours (always choosing the one you didn't arrive from) to traverse the points along the curve.&#xD;&#xA;&#xD;&#xA;Especially if you can make the points very dense this should be the most reliable option unless the curve self-intersects. Even in that case, this approach might be salvageable provided the self-intersection is at a sufficiently large angle the curve smooth enough (in that case you can choose the correct neighbours based on some constraint that successive steps cannot make an angle greater than some threshold $\theta$)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4668" PostHistoryTypeId="5" PostId="2088" RevisionGUID="0a429847-5d21-4d23-8c5e-38ce8e89e443" CreationDate="2016-02-23T16:48:57.977" UserId="2562" Comment="added 373 characters in body" Text="I have a set of 3D points (which I recover from a library that performs the tessellation of a solid body) that belong to a curve (i.e., an edge of the solid). That means that the curve surely passes by each of these points.&#xD;&#xA;&#xD;&#xA;Nevertheless, the point set is unordered so I need to sort them in order to be able to draw this curve correctly.&#xD;&#xA;&#xD;&#xA;Is there any known approach for these type of problem?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some additional information:&#xD;&#xA;&#xD;&#xA; - The curves are parametric in general (splines/bezier, circle slices.. ). &#xD;&#xA; - The points are given as floating point coordinates.&#xD;&#xA; - The points are packed very densely (but they can be as dense as I want it to be). To give you an idea, for a curve which occupies 19 units in x, 10 units in x and 5 units in z, I quote a sequence of points in a segment of curve: (20.7622, 25.8676, 0) (20.6573, 25.856, 0) (20.5529, 25.8444, 0) (20.4489, 25.8329, 0) (20.3454, 25.8213, 0)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4669" PostHistoryTypeId="2" PostId="2091" RevisionGUID="19dc569e-dc90-4e1e-9307-4a820b4923a9" CreationDate="2016-02-23T17:59:07.243" UserId="192" Text="You have an instance of a problem called *curve reconstruction from unorganized points*. Now that you know what to search for you'll find several methods, such as the crust, NN-crust, etc. Here are a few links:&#xD;&#xA;&#xD;&#xA;- [The Crust Curve Reconstruction Applet](http://sarielhp.org/research/CG/applets/Crust/Crust.html)&#xD;&#xA;&#xD;&#xA;- [Curve Reconstruction](http://web.cse.ohio-state.edu/~tamaldey/curverecon.htm) by Tamal Dey&#xD;&#xA;&#xD;&#xA;- [Curve and Surface Reconstruction: Algorithms with Mathematical Analysis](https://www.cambridge.org/catalogue/catalogue.asp?isbn=9780521863704), book by Tamal K. Dey, Cambridge University Press, 2006&#xD;&#xA;&#xD;&#xA;Since you're dealing with curves and the samples are dense, I suggest you compute an Euclidean minimal spanning tree." ContentLicense="CC BY-SA 3.0" />
  <row Id="4671" PostHistoryTypeId="2" PostId="2092" RevisionGUID="3ef61374-a9a8-442e-b68d-b13106436b8f" CreationDate="2016-02-24T14:37:14.710" UserId="385" Text="You can of course, as you suggested, map (u, v) to (φ, θ). Unfortunately, it does not solve the problem for 5 points:&#xD;&#xA;&#xD;&#xA;[![Switched mapping][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/csMKn.png&#xD;&#xA;&#xD;&#xA;I've changed Holger Dammertz' code a bit (switched u and v), and you see that the problem still persists. For a higher number of points, it really doesn't seem to make a (visual) difference.&#xD;&#xA;&#xD;&#xA;The Hammersley point set is a way to **very quickly** determine points on a sphere that have good, but don't need to have a perfect distribution. In the problematic case of very few points, Hammersley might just not be the tool for the job. Pre-calculating and storing points sounds like a better option to me." ContentLicense="CC BY-SA 3.0" />
  <row Id="4673" PostHistoryTypeId="2" PostId="2093" RevisionGUID="04a2d1e5-26b7-4899-b6d0-000a306cdfcf" CreationDate="2016-02-25T17:22:44.533" UserId="2750" Text="I have a 3D model, which consists of 50 thousand vertices and 100 thousand triangles. Format is: there's array of vertices' coordinates and array of triangles, which has numbers of vertices (e.g., [1, 2, 5] -- triangle, which consists of first, second and fifth vertex from vertices' array).&#xD;&#xA;&#xD;&#xA;I calculate color of each triangle and rotate the model by myself.&#xD;&#xA;Also I &quot;render&quot; it manually, putting vertices as pixels on `PIL` image, but matrix with colors is enough for my purpose (I need only the matrix).&#xD;&#xA;&#xD;&#xA;I don't know, whether I will implement robust and correct rendering function, but I cannot find light-weight library as well.&#xD;&#xA;All I need is to display the set of triangles with specified colors and  background image fast (far less than for a second)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4674" PostHistoryTypeId="1" PostId="2093" RevisionGUID="04a2d1e5-26b7-4899-b6d0-000a306cdfcf" CreationDate="2016-02-25T17:22:44.533" UserId="2750" Text="Triangulated model rasterization: light-weight Python library" ContentLicense="CC BY-SA 3.0" />
  <row Id="4675" PostHistoryTypeId="3" PostId="2093" RevisionGUID="04a2d1e5-26b7-4899-b6d0-000a306cdfcf" CreationDate="2016-02-25T17:22:44.533" UserId="2750" Text="|3d|raster-image|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4676" PostHistoryTypeId="5" PostId="2093" RevisionGUID="662db2df-d075-4b19-bb4c-3cb596e70505" CreationDate="2016-02-25T17:56:00.497" UserId="2750" Comment="fixed information" Text="I have a 3D model, which consists of 160 thousand vertices and 100 thousand triangles. Format is: there's array of vertices' coordinates and array of triangles, which has numbers of vertices (e.g., [1, 2, 5] -- triangle, which consists of first, second and fifth vertex from vertices' array).&#xD;&#xA;&#xD;&#xA;I calculate color of each triangle and rotate the model by myself.&#xD;&#xA;Also I &quot;render&quot; it manually, putting vertices as pixels on `PIL` image, but matrix with colors is enough for my purpose (I need only the matrix).&#xD;&#xA;&#xD;&#xA;I don't know, whether I will implement robust and correct rendering function, but I cannot find light-weight library as well.&#xD;&#xA;All I need is to display the set of triangles with specified colors and  background image fast (far less than for a second)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4677" PostHistoryTypeId="2" PostId="2094" RevisionGUID="ff64d9c9-b9b9-4ee2-81a7-4d26a3f9f1b6" CreationDate="2016-02-25T22:53:01.660" UserId="2726" Text="**Some possible things that might be the issue and could be explained by someone who is knowledgeable**&#xD;&#xA;&#xD;&#xA; - Order of my indices, In all I've read, your array of indices for a triangle list is just clockwise order, see below how I ordered it for proof.&#xD;&#xA; - Keep in mind that my code runs fine, no errors, no warnings(that I know of) related to my issue.&#xD;&#xA;&#xD;&#xA;I have been banging my head over this issue for far too long. I know the answer is going to be ridiculously simple but somehow it has successfully evaded me.&#xD;&#xA;&#xD;&#xA;I've been implementing deferred rendering into my engine and my second pass, the one that actually renders to the swap chain buffer, is staying black (or whatever color I clear it to before rendering).&#xD;&#xA;&#xD;&#xA;Now I know the issue has nothing to do with anything associated with the first pass/gBuffer because I am completely bypassing that part, literally commented out the call to it in the game loop.&#xD;&#xA;&#xD;&#xA;My 2nd Pass Deferred Vertex Shader is as follows... &#xD;&#xA;&#xD;&#xA;    float4 main( float4 pos : POSITION ) : SV_POSITION&#xD;&#xA;    {&#xD;&#xA;	     return pos;&#xD;&#xA;    }&#xD;&#xA;My 2nd Pass Pixel Shader is as follows... &#xD;&#xA;I have omitted the actual lighting code because it is all commented out until I fix the issue. &#xD;&#xA;&#xD;&#xA;     float4 main(in float4 screenPos : SV_Position) : SV_Target&#xD;&#xA;     {&#xD;&#xA;	     return float4(1.0f,1.0f,1.0f, 1.0f);&#xD;&#xA;     }&#xD;&#xA;As you can see I am not doing anything related to lighting or anything, all I'm trying to do is set every pixel to white, I want to see it work.&#xD;&#xA;&#xD;&#xA;Here is my renderSecondPass function. this is what I call every frame. Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     void DirectX::renderSecondPass()&#xD;&#xA;     {&#xD;&#xA;	 nullShaders();&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;VSSetShader(deferredVertexShader, NULL, 0);&#xD;&#xA;	 d3d11DeviceContext-&gt;PSSetShader(deferredPixelShader, NULL, 0);&#xD;&#xA;&#xD;&#xA;	 HRESULT hr;&#xD;&#xA;	 float clear[] = { 1.0, 0.5, 0.0, 1.0 };&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;OMSetRenderTargets(1, &amp;d3d11RenderTargetView, NULL);&#xD;&#xA;	 d3d11DeviceContext-&gt;ClearRenderTargetView(d3d11RenderTargetView, clear);&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;IASetInputLayout(InputLayout::Deferred);&#xD;&#xA;	 d3d11DeviceContext-&gt;IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	 for (unsigned int i = 0; i &lt; lightBuffer.size(); i++)&#xD;&#xA;	 {&#xD;&#xA;		UINT stride = sizeof(Vertex::Deferred);&#xD;&#xA;		UINT offset = 0;&#xD;&#xA;&#xD;&#xA;		d3d11DeviceContext-&gt;IASetVertexBuffers(0, 1, &amp;deferredQuadVB, &amp;stride, &amp;offset);&#xD;&#xA;		d3d11DeviceContext-&gt;IASetIndexBuffer(deferredQuadIB, DXGI_FORMAT_R32_UINT, 0);&#xD;&#xA;&#xD;&#xA;		d3d11DeviceContext-&gt;DrawIndexed(deferredQuadIndiceCount, 0, 0);&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;	 hr = swapChain-&gt;Present(0, 0);&#xD;&#xA;&#xD;&#xA;	 if (FAILED(hr))&#xD;&#xA;	 {&#xD;&#xA;		 MessageBox(0, L&quot;Swap Chain Present Error.&quot;, 0, 0);&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Here is the Input Layout...&#xD;&#xA;&#xD;&#xA;     namespace Vertex&#xD;&#xA;     {&#xD;&#xA;	     struct Deferred&#xD;&#xA;	     {&#xD;&#xA;		     VECTOR&lt;float&gt; Position;&#xD;&#xA;		     float Position_W;&#xD;&#xA;	     };&#xD;&#xA;     }&#xD;&#xA;     // C++ side above &#xD;&#xA;     &#xD;&#xA;     // Shaderside below&#xD;&#xA;     namespace InputLayout&#xD;&#xA;     {&#xD;&#xA;	     static ID3D11InputLayout* Deferred;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;     const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC[] =&#xD;&#xA;     {&#xD;&#xA;	     { &quot;POSITION&quot;,	0, DXGI_FORMAT_R32G32B32A32_FLOAT,	0, 0,	D3D11_INPUT_PER_VERTEX_DATA, 0 }&#xD;&#xA;     };&#xD;&#xA;Creation of the Input Layouts and Loading of the shaders themselves from file. &#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;    bool DirectX::initShaders()&#xD;&#xA;    {&#xD;&#xA;	std::vector&lt;char&gt; shaderBuffer;&#xD;&#xA;	std::string filename;&#xD;&#xA;	HRESULT hr;&#xD;&#xA;&#xD;&#xA;	// deferredVS&#xD;&#xA;	filename = &quot;Shaders\\deferredVS.cso&quot;;&#xD;&#xA;	if (!shaderFileToMemory(filename, shaderBuffer))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Load defaultVS Shader Into Memory Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;	hr = d3d11Device-&gt;CreateVertexShader(&amp;shaderBuffer[0], shaderBuffer.size(), NULL, &amp;deferredVertexShader);&#xD;&#xA;	hr = d3d11Device-&gt;CreateInputLayout(InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC, 1, &amp;shaderBuffer[0], shaderBuffer.size(), &amp;InputLayout::Deferred);&#xD;&#xA;&#xD;&#xA;	// deferredPS&#xD;&#xA;	filename = &quot;Shaders\\deferredPS.cso&quot;;&#xD;&#xA;	if (!shaderFileToMemory(filename, shaderBuffer))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Load deferredPS Shader Into Memory Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;	hr = d3d11Device-&gt;CreatePixelShader(&amp;shaderBuffer[0], shaderBuffer.size(), NULL, &amp;deferredPixelShader);&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Vertex and Index Buffer were created using the following...&#xD;&#xA;&#xD;&#xA;     bool DirectX::initDeferredQuad()&#xD;&#xA;     {&#xD;&#xA;	std::vector&lt;Vertex::Deferred&gt; deferredQuadVertices;&#xD;&#xA;	std::vector&lt;unsigned int&gt; deferredQuadIndices;&#xD;&#xA;&#xD;&#xA;	Vertex::Deferred quadVertices[4];&#xD;&#xA;	Vertex::Deferred quadVertice;&#xD;&#xA;&#xD;&#xA;	quadVertice.Position_W	= 1.0;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(-1.0, 1.0, 0.0);&#xD;&#xA;	quadVertices[0] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(1.0, 1.0, 0.0);&#xD;&#xA;	quadVertices[1] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(-1.0, -1.0, 0.0);&#xD;&#xA;	quadVertices[2] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(1.0, -1.0, 0.0);&#xD;&#xA;	quadVertices[3] = quadVertice;&#xD;&#xA;&#xD;&#xA;	D3D11_BUFFER_DESC vbd;&#xD;&#xA;	D3D11_SUBRESOURCE_DATA vinitData;&#xD;&#xA;	HRESULT hr;&#xD;&#xA;	&#xD;&#xA;	vbd.Usage				= D3D11_USAGE_IMMUTABLE;&#xD;&#xA;	vbd.ByteWidth			= sizeof(Vertex::Deferred) * 4;&#xD;&#xA;	vbd.BindFlags			= D3D11_BIND_VERTEX_BUFFER;&#xD;&#xA;	vbd.CPUAccessFlags		= 0;&#xD;&#xA;	vbd.MiscFlags			= 0;&#xD;&#xA;	vbd.StructureByteStride = 0;&#xD;&#xA;&#xD;&#xA;	vinitData.pSysMem		= &amp;quadVertices;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateBuffer(&amp;vbd, &amp;vinitData, &amp;deferredQuadVB);&#xD;&#xA;&#xD;&#xA;	if (FAILED(hr))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Quad Vertex Buffer Creation Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	unsigned int quadIndices[] =&#xD;&#xA;	{	1, 2, 3,&#xD;&#xA;		3, 2, 4 };&#xD;&#xA;&#xD;&#xA;	deferredQuadIndiceCount = 6;&#xD;&#xA;&#xD;&#xA;	D3D11_BUFFER_DESC ibd;&#xD;&#xA;	D3D11_SUBRESOURCE_DATA iinitData;&#xD;&#xA;&#xD;&#xA;	ibd.Usage				= D3D11_USAGE_IMMUTABLE;&#xD;&#xA;	ibd.ByteWidth			= sizeof(unsigned int) * 6;&#xD;&#xA;	ibd.BindFlags			= D3D11_BIND_INDEX_BUFFER;&#xD;&#xA;	ibd.CPUAccessFlags		= 0;&#xD;&#xA;	ibd.MiscFlags			= 0;&#xD;&#xA;&#xD;&#xA;	iinitData.pSysMem		= &amp;deferredQuadIndices;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateBuffer(&amp;ibd, &amp;iinitData, &amp;deferredQuadIB);&#xD;&#xA;&#xD;&#xA;	if (FAILED(hr))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;QuadIndex Buffer Creation Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;I thought the issue was here. Since my Vertex Shader is feeding the Rasterizer data directly, the Vertex Shader has to output SV_Position in Clip Space. Wouldn't the coordinates I've made for my vertices be correct for a quad composed of 2 triangles that would take up the entire screen? (I've tried changing the z values, no change)&#xD;&#xA;&#xD;&#xA;If anyone needs more info, just ask. Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4678" PostHistoryTypeId="1" PostId="2094" RevisionGUID="ff64d9c9-b9b9-4ee2-81a7-4d26a3f9f1b6" CreationDate="2016-02-25T22:53:01.660" UserId="2726" Text="Trouble Finding Simple 2D DirecX11/HLSL Issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="4679" PostHistoryTypeId="3" PostId="2094" RevisionGUID="ff64d9c9-b9b9-4ee2-81a7-4d26a3f9f1b6" CreationDate="2016-02-25T22:53:01.660" UserId="2726" Text="|directx11|pixel-shader|hlsl|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4680" PostHistoryTypeId="2" PostId="2095" RevisionGUID="63acdf7d-2bbb-432c-807b-d56b3ee0afca" CreationDate="2016-02-26T00:06:17.400" UserId="40" Text="Your indices are wrong, they should start at 0.&#xD;&#xA;&#xD;&#xA;Correct indices:&#xD;&#xA;&#xD;&#xA;    unsigned int quadIndices[] =&#xD;&#xA;    {   0, 1, 2,&#xD;&#xA;        2, 1, 3 };&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4681" PostHistoryTypeId="2" PostId="2096" RevisionGUID="e85f3007-2f20-4e99-9122-ac88d23decc5" CreationDate="2016-02-26T00:18:30.017" UserId="2752" Text="You have not set a viewport with RSSetViewports. You need to set this to the pixel dimensions of your render target. Without this the viewport will be set to 0,0,0,0 meaning no pixels will be touched.&#xD;&#xA;&#xD;&#xA;Additionally you have not set a raster state or blend state. It is good practice to set these and can be helpful early on to set the winding order in the raster state to not cull, this can come in handy if you are working out the vertex positions by hand." ContentLicense="CC BY-SA 3.0" />
  <row Id="4682" PostHistoryTypeId="5" PostId="2094" RevisionGUID="e308f817-fadd-40a8-b41e-8c825f428c4d" CreationDate="2016-02-26T01:40:43.907" UserId="2726" Comment="Added code that is already in the project" Text="**Some possible things that might be the issue and could be explained by someone who is knowledgeable**&#xD;&#xA;&#xD;&#xA; - Order of my indices, In all I've read, your array of indices for a triangle list is just clockwise order, see below how I ordered it for proof. **EDIT - I have changed my indices according to Jason Allen's comment, no change**&#xD;&#xA; - Keep in mind that my code runs fine, no errors, no warnings(that I know of) related to my issue.&#xD;&#xA;&#xD;&#xA;I have been banging my head over this issue for far too long. I know the answer is going to be ridiculously simple but somehow it has successfully evaded me.&#xD;&#xA;&#xD;&#xA;I've been implementing deferred rendering into my engine and my second pass, the one that actually renders to the swap chain buffer, is staying black (or whatever color I clear it to before rendering).&#xD;&#xA;&#xD;&#xA;Now I know the issue has nothing to do with anything associated with the first pass/gBuffer because I am completely bypassing that part, literally commented out the call to it in the game loop.&#xD;&#xA;&#xD;&#xA;My 2nd Pass Deferred Vertex Shader is as follows... &#xD;&#xA;&#xD;&#xA;    float4 main( float4 pos : POSITION ) : SV_POSITION&#xD;&#xA;    {&#xD;&#xA;	     return pos;&#xD;&#xA;    }&#xD;&#xA;My 2nd Pass Pixel Shader is as follows... &#xD;&#xA;I have omitted the actual lighting code because it is all commented out until I fix the issue. &#xD;&#xA;&#xD;&#xA;     float4 main(in float4 screenPos : SV_Position) : SV_Target&#xD;&#xA;     {&#xD;&#xA;	     return float4(1.0f,1.0f,1.0f, 1.0f);&#xD;&#xA;     }&#xD;&#xA;As you can see I am not doing anything related to lighting or anything, all I'm trying to do is set every pixel to white, I want to see it work.&#xD;&#xA;&#xD;&#xA;Here is my renderSecondPass function. this is what I call every frame. Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     void DirectX::renderSecondPass()&#xD;&#xA;     {&#xD;&#xA;	 nullShaders();&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;VSSetShader(deferredVertexShader, NULL, 0);&#xD;&#xA;	 d3d11DeviceContext-&gt;PSSetShader(deferredPixelShader, NULL, 0);&#xD;&#xA;&#xD;&#xA;	 HRESULT hr;&#xD;&#xA;	 float clear[] = { 1.0, 0.5, 0.0, 1.0 };&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;OMSetRenderTargets(1, &amp;d3d11RenderTargetView, NULL);&#xD;&#xA;	 d3d11DeviceContext-&gt;ClearRenderTargetView(d3d11RenderTargetView, clear);&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;IASetInputLayout(InputLayout::Deferred);&#xD;&#xA;	 d3d11DeviceContext-&gt;IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	 for (unsigned int i = 0; i &lt; lightBuffer.size(); i++)&#xD;&#xA;	 {&#xD;&#xA;		UINT stride = sizeof(Vertex::Deferred);&#xD;&#xA;		UINT offset = 0;&#xD;&#xA;&#xD;&#xA;		d3d11DeviceContext-&gt;IASetVertexBuffers(0, 1, &amp;deferredQuadVB, &amp;stride, &amp;offset);&#xD;&#xA;		d3d11DeviceContext-&gt;IASetIndexBuffer(deferredQuadIB, DXGI_FORMAT_R32_UINT, 0);&#xD;&#xA;&#xD;&#xA;		d3d11DeviceContext-&gt;DrawIndexed(deferredQuadIndiceCount, 0, 0);&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;	 hr = swapChain-&gt;Present(0, 0);&#xD;&#xA;&#xD;&#xA;	 if (FAILED(hr))&#xD;&#xA;	 {&#xD;&#xA;		 MessageBox(0, L&quot;Swap Chain Present Error.&quot;, 0, 0);&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Here is the Input Layout...&#xD;&#xA;&#xD;&#xA;     namespace Vertex&#xD;&#xA;     {&#xD;&#xA;	     struct Deferred&#xD;&#xA;	     {&#xD;&#xA;		     VECTOR&lt;float&gt; Position;&#xD;&#xA;		     float Position_W;&#xD;&#xA;	     };&#xD;&#xA;     }&#xD;&#xA;     // C++ side above &#xD;&#xA;     &#xD;&#xA;     // Shaderside below&#xD;&#xA;     namespace InputLayout&#xD;&#xA;     {&#xD;&#xA;	     static ID3D11InputLayout* Deferred;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;     const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC[] =&#xD;&#xA;     {&#xD;&#xA;	     { &quot;POSITION&quot;,	0, DXGI_FORMAT_R32G32B32A32_FLOAT,	0, 0,	D3D11_INPUT_PER_VERTEX_DATA, 0 }&#xD;&#xA;     };&#xD;&#xA;Creation of the Input Layouts and Loading of the shaders themselves from file. &#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;    bool DirectX::initShaders()&#xD;&#xA;    {&#xD;&#xA;	std::vector&lt;char&gt; shaderBuffer;&#xD;&#xA;	std::string filename;&#xD;&#xA;	HRESULT hr;&#xD;&#xA;&#xD;&#xA;	// deferredVS&#xD;&#xA;	filename = &quot;Shaders\\deferredVS.cso&quot;;&#xD;&#xA;	if (!shaderFileToMemory(filename, shaderBuffer))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Load defaultVS Shader Into Memory Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;	hr = d3d11Device-&gt;CreateVertexShader(&amp;shaderBuffer[0], shaderBuffer.size(), NULL, &amp;deferredVertexShader);&#xD;&#xA;	hr = d3d11Device-&gt;CreateInputLayout(InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC, 1, &amp;shaderBuffer[0], shaderBuffer.size(), &amp;InputLayout::Deferred);&#xD;&#xA;&#xD;&#xA;	// deferredPS&#xD;&#xA;	filename = &quot;Shaders\\deferredPS.cso&quot;;&#xD;&#xA;	if (!shaderFileToMemory(filename, shaderBuffer))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Load deferredPS Shader Into Memory Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;	hr = d3d11Device-&gt;CreatePixelShader(&amp;shaderBuffer[0], shaderBuffer.size(), NULL, &amp;deferredPixelShader);&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Vertex and Index Buffer were created using the following...&#xD;&#xA;&#xD;&#xA;     bool DirectX::initDeferredQuad()&#xD;&#xA;     {&#xD;&#xA;	std::vector&lt;Vertex::Deferred&gt; deferredQuadVertices;&#xD;&#xA;	std::vector&lt;unsigned int&gt; deferredQuadIndices;&#xD;&#xA;&#xD;&#xA;	Vertex::Deferred quadVertices[4];&#xD;&#xA;	Vertex::Deferred quadVertice;&#xD;&#xA;&#xD;&#xA;	quadVertice.Position_W	= 1.0;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(-1.0, 1.0, 0.0);&#xD;&#xA;	quadVertices[0] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(1.0, 1.0, 0.0);&#xD;&#xA;	quadVertices[1] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(-1.0, -1.0, 0.0);&#xD;&#xA;	quadVertices[2] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(1.0, -1.0, 0.0);&#xD;&#xA;	quadVertices[3] = quadVertice;&#xD;&#xA;&#xD;&#xA;	D3D11_BUFFER_DESC vbd;&#xD;&#xA;	D3D11_SUBRESOURCE_DATA vinitData;&#xD;&#xA;	HRESULT hr;&#xD;&#xA;	&#xD;&#xA;	vbd.Usage				= D3D11_USAGE_IMMUTABLE;&#xD;&#xA;	vbd.ByteWidth			= sizeof(Vertex::Deferred) * 4;&#xD;&#xA;	vbd.BindFlags			= D3D11_BIND_VERTEX_BUFFER;&#xD;&#xA;	vbd.CPUAccessFlags		= 0;&#xD;&#xA;	vbd.MiscFlags			= 0;&#xD;&#xA;	vbd.StructureByteStride = 0;&#xD;&#xA;&#xD;&#xA;	vinitData.pSysMem		= &amp;quadVertices;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateBuffer(&amp;vbd, &amp;vinitData, &amp;deferredQuadVB);&#xD;&#xA;&#xD;&#xA;	if (FAILED(hr))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Quad Vertex Buffer Creation Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	unsigned int quadIndices[] =&#xD;&#xA;	{	0, 1, 2,&#xD;&#xA;		2, 1, 3 };&#xD;&#xA;&#xD;&#xA;	deferredQuadIndiceCount = 6;&#xD;&#xA;&#xD;&#xA;	D3D11_BUFFER_DESC ibd;&#xD;&#xA;	D3D11_SUBRESOURCE_DATA iinitData;&#xD;&#xA;&#xD;&#xA;	ibd.Usage				= D3D11_USAGE_IMMUTABLE;&#xD;&#xA;	ibd.ByteWidth			= sizeof(unsigned int) * 6;&#xD;&#xA;	ibd.BindFlags			= D3D11_BIND_INDEX_BUFFER;&#xD;&#xA;	ibd.CPUAccessFlags		= 0;&#xD;&#xA;	ibd.MiscFlags			= 0;&#xD;&#xA;&#xD;&#xA;	iinitData.pSysMem		= &amp;deferredQuadIndices;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateBuffer(&amp;ibd, &amp;iinitData, &amp;deferredQuadIB);&#xD;&#xA;&#xD;&#xA;	if (FAILED(hr))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;QuadIndex Buffer Creation Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;I thought the issue was here. Since my Vertex Shader is feeding the Rasterizer data directly, the Vertex Shader has to output SV_Position in Clip Space. Wouldn't the coordinates I've made for my vertices be correct for a quad composed of 2 triangles that would take up the entire screen? (I've tried changing the z values, no change)&#xD;&#xA;&#xD;&#xA;Here is resizeSwapChain, I've been bulding/rebuild the viewport in here.&#xD;&#xA;This function is called at initialization and whenever the window size changes after the window adjustment has been released (WM_EXITSIZEMOVE).&#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     void DirectX::resizeSwapChain()&#xD;&#xA;     {&#xD;&#xA;	const unsigned int clientWidth = uClient-&gt;getAppScreenWidth();&#xD;&#xA;	const unsigned int clientHeight = uClient-&gt;getAppScreenHeight();&#xD;&#xA;	HRESULT hr;&#xD;&#xA;&#xD;&#xA;	if (!(d3d11RenderTargetView == NULL))&#xD;&#xA;	{&#xD;&#xA;		d3d11RenderTargetView-&gt;Release();&#xD;&#xA;		d3d11RenderTargetView = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	if (!(d3d11DepthStencilView) == NULL)&#xD;&#xA;	{&#xD;&#xA;		d3d11DepthStencilView-&gt;Release();&#xD;&#xA;		d3d11DepthStencilView = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	if (!(d3d11StencilBuffer) == NULL)&#xD;&#xA;	{&#xD;&#xA;		d3d11StencilBuffer-&gt;Release();&#xD;&#xA;		d3d11StencilBuffer = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	hr = swapChain-&gt;ResizeBuffers(1, clientWidth, clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);&#xD;&#xA;&#xD;&#xA;	ID3D11Texture2D* backBuffer;&#xD;&#xA;&#xD;&#xA;	hr = swapChain-&gt;GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast&lt;void**&gt;(&amp;backBuffer));&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateRenderTargetView(backBuffer, 0, &amp;d3d11RenderTargetView);&#xD;&#xA;&#xD;&#xA;	backBuffer-&gt;Release();&#xD;&#xA;	backBuffer = 0;&#xD;&#xA;&#xD;&#xA;	D3D11_TEXTURE2D_DESC depthStencilDesc;&#xD;&#xA;&#xD;&#xA;	depthStencilDesc.Width = clientWidth;&#xD;&#xA;	depthStencilDesc.Height = clientHeight;&#xD;&#xA;	depthStencilDesc.MipLevels = 1;&#xD;&#xA;	depthStencilDesc.ArraySize = 1;&#xD;&#xA;	depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;&#xD;&#xA;&#xD;&#xA;	if (msaaEnabled)&#xD;&#xA;	{&#xD;&#xA;		depthStencilDesc.SampleDesc.Count = 4;&#xD;&#xA;		depthStencilDesc.SampleDesc.Quality = msaaQuality - 1;&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		depthStencilDesc.SampleDesc.Count = 1;&#xD;&#xA;		depthStencilDesc.SampleDesc.Quality = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;	depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;&#xD;&#xA;	depthStencilDesc.CPUAccessFlags = 0;&#xD;&#xA;	depthStencilDesc.MiscFlags = 0;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateTexture2D(&amp;depthStencilDesc, 0, &amp;d3d11StencilBuffer);&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateDepthStencilView(d3d11StencilBuffer, 0, &amp;d3d11DepthStencilView);&#xD;&#xA;&#xD;&#xA;	d3d11ScreenViewport.TopLeftX = 0;&#xD;&#xA;	d3d11ScreenViewport.TopLeftY = 0;&#xD;&#xA;	d3d11ScreenViewport.Width = static_cast&lt;float&gt;(clientWidth);&#xD;&#xA;	d3d11ScreenViewport.Height = static_cast&lt;float&gt;(clientHeight);&#xD;&#xA;	d3d11ScreenViewport.MinDepth = 0.0f;&#xD;&#xA;	d3d11ScreenViewport.MaxDepth = 1.0f;&#xD;&#xA;&#xD;&#xA;	d3d11DeviceContext-&gt;RSSetViewports(1, &amp;d3d11ScreenViewport);&#xD;&#xA;&#xD;&#xA;	mainCamera-&gt;setProjectionMatrix(MATRIX4X4&lt;float&gt;::perspectiveFieldOfViewLeftHandMatrix(0.25 * GenericMath::PI, GenericMath::aspectRatio(clientWidth, clientHeight), 0.001, 1000.0));&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Here is my D3D11 Initialization function, this is where I create my Rasterization states.&#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     bool DirectX::initDirectX()&#xD;&#xA;     {&#xD;&#xA;	D3D_FEATURE_LEVEL featureLevel;&#xD;&#xA;&#xD;&#xA;	HRESULT hr = D3D11CreateDevice(NULL, driverType, NULL, NULL, NULL, 0, D3D11_SDK_VERSION, &amp;d3d11Device, &amp;featureLevel, &amp;d3d11DeviceContext);&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, 4, &amp;msaaQuality);&#xD;&#xA;&#xD;&#xA;	DXGI_SWAP_CHAIN_DESC swapChainDesc;&#xD;&#xA;	swapChainDesc.BufferDesc.Width = uClient-&gt;getAppScreenWidth();&#xD;&#xA;	swapChainDesc.BufferDesc.Height = uClient-&gt;getAppScreenHeight();&#xD;&#xA;	swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;&#xD;&#xA;	swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;&#xD;&#xA;	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;&#xD;&#xA;	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;&#xD;&#xA;&#xD;&#xA;	if (msaaEnabled)&#xD;&#xA;	{&#xD;&#xA;		swapChainDesc.SampleDesc.Count = 4;&#xD;&#xA;		swapChainDesc.SampleDesc.Quality = msaaQuality - 1;&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		swapChainDesc.SampleDesc.Count = 1;&#xD;&#xA;		swapChainDesc.SampleDesc.Quality = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;&#xD;&#xA;	swapChainDesc.BufferCount = 1;&#xD;&#xA;	swapChainDesc.OutputWindow = *windowsHandle;&#xD;&#xA;	swapChainDesc.Windowed = true;&#xD;&#xA;	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;&#xD;&#xA;	swapChainDesc.Flags = 0;&#xD;&#xA;&#xD;&#xA;	IDXGIDevice* dxgiDevice = 0;&#xD;&#xA;	hr = d3d11Device-&gt;QueryInterface(__uuidof(IDXGIDevice), (void**)&amp;dxgiDevice);&#xD;&#xA;&#xD;&#xA;	IDXGIAdapter* dxgiAdapter = 0;&#xD;&#xA;	hr = dxgiDevice-&gt;GetParent(__uuidof(IDXGIAdapter), (void**)&amp;dxgiAdapter);&#xD;&#xA;&#xD;&#xA;	IDXGIFactory* dxgiFactory = 0;&#xD;&#xA;	hr = dxgiAdapter-&gt;GetParent(__uuidof(IDXGIFactory), (void**)&amp;dxgiFactory);&#xD;&#xA;&#xD;&#xA;	hr = dxgiFactory-&gt;CreateSwapChain(d3d11Device, &amp;swapChainDesc, &amp;swapChain);&#xD;&#xA;&#xD;&#xA;	dxgiDevice-&gt;Release();&#xD;&#xA;	dxgiDevice = 0;&#xD;&#xA;&#xD;&#xA;	dxgiAdapter-&gt;Release();&#xD;&#xA;	dxgiAdapter = 0;&#xD;&#xA;&#xD;&#xA;	dxgiFactory-&gt;Release();&#xD;&#xA;	dxgiFactory = 0;&#xD;&#xA;&#xD;&#xA;	resizeGBuffers();&#xD;&#xA;	resizeSwapChain();&#xD;&#xA;&#xD;&#xA;	D3D11_RASTERIZER_DESC rasterizerDesc;&#xD;&#xA;	ZeroMemory(&amp;rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));&#xD;&#xA;	rasterizerDesc.FillMode = D3D11_FILL_SOLID;&#xD;&#xA;	rasterizerDesc.CullMode = D3D11_CULL_BACK;&#xD;&#xA;	rasterizerDesc.FrontCounterClockwise = false;&#xD;&#xA;	rasterizerDesc.DepthClipEnable = true;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateRasterizerState( &amp;rasterizerDesc, &amp;d3d11SolidRS);\&#xD;&#xA;&#xD;&#xA;	ZeroMemory(&amp;rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));&#xD;&#xA;&#xD;&#xA;	rasterizerDesc.FillMode = D3D11_FILL_WIREFRAME;&#xD;&#xA;	rasterizerDesc.CullMode = D3D11_CULL_BACK;&#xD;&#xA;	rasterizerDesc.FrontCounterClockwise = false;&#xD;&#xA;	rasterizerDesc.DepthClipEnable = true;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateRasterizerState( &amp;rasterizerDesc, &amp;d3d11WireframeRS);&#xD;&#xA;&#xD;&#xA;	d3d11DeviceContext-&gt;RSSetState(d3d11SolidRS);&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;If anyone needs more info, just ask. Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4690" PostHistoryTypeId="5" PostId="2094" RevisionGUID="fc6a4151-5e9a-493f-8047-c4eb26c7c6fa" CreationDate="2016-02-26T12:17:57.383" UserId="2726" Comment="Added Picture" Text="**Some possible things that might be the issue and could be explained by someone who is knowledgeable**&#xD;&#xA;&#xD;&#xA; - Order of my indices, In all I've read, your array of indices for a triangle list is just clockwise order, see below how I ordered it for proof. **EDIT - I have changed my indices according to Jason Allen's comment, no change**&#xD;&#xA; - Keep in mind that my code runs fine, no errors, no warnings(that I know of) related to my issue.&#xD;&#xA; - Can these warnings be an issue?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have been banging my head over this issue for far too long. I know the answer is going to be ridiculously simple but somehow it has successfully evaded me.&#xD;&#xA;&#xD;&#xA;I've been implementing deferred rendering into my engine and my second pass, the one that actually renders to the swap chain buffer, is staying black (or whatever color I clear it to before rendering).&#xD;&#xA;&#xD;&#xA;Now I know the issue has nothing to do with anything associated with the first pass/gBuffer because I am completely bypassing that part, literally commented out the call to it in the game loop.&#xD;&#xA;&#xD;&#xA;My 2nd Pass Deferred Vertex Shader is as follows... &#xD;&#xA;&#xD;&#xA;    float4 main( float4 pos : POSITION ) : SV_POSITION&#xD;&#xA;    {&#xD;&#xA;	     return pos;&#xD;&#xA;    }&#xD;&#xA;My 2nd Pass Pixel Shader is as follows... &#xD;&#xA;I have omitted the actual lighting code because it is all commented out until I fix the issue. &#xD;&#xA;&#xD;&#xA;     float4 main(in float4 screenPos : SV_Position) : SV_Target&#xD;&#xA;     {&#xD;&#xA;	     return float4(1.0f,1.0f,1.0f, 1.0f);&#xD;&#xA;     }&#xD;&#xA;As you can see I am not doing anything related to lighting or anything, all I'm trying to do is set every pixel to white, I want to see it work.&#xD;&#xA;&#xD;&#xA;Here is my renderSecondPass function. this is what I call every frame. Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     void DirectX::renderSecondPass()&#xD;&#xA;     {&#xD;&#xA;	 nullShaders();&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;VSSetShader(deferredVertexShader, NULL, 0);&#xD;&#xA;	 d3d11DeviceContext-&gt;PSSetShader(deferredPixelShader, NULL, 0);&#xD;&#xA;&#xD;&#xA;	 HRESULT hr;&#xD;&#xA;	 float clear[] = { 1.0, 0.5, 0.0, 1.0 };&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;OMSetRenderTargets(1, &amp;d3d11RenderTargetView, NULL);&#xD;&#xA;	 d3d11DeviceContext-&gt;ClearRenderTargetView(d3d11RenderTargetView, clear);&#xD;&#xA;&#xD;&#xA;	 d3d11DeviceContext-&gt;IASetInputLayout(InputLayout::Deferred);&#xD;&#xA;	 d3d11DeviceContext-&gt;IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	 for (unsigned int i = 0; i &lt; lightBuffer.size(); i++)&#xD;&#xA;	 {&#xD;&#xA;		UINT stride = sizeof(Vertex::Deferred);&#xD;&#xA;		UINT offset = 0;&#xD;&#xA;&#xD;&#xA;		d3d11DeviceContext-&gt;IASetVertexBuffers(0, 1, &amp;deferredQuadVB, &amp;stride, &amp;offset);&#xD;&#xA;		d3d11DeviceContext-&gt;IASetIndexBuffer(deferredQuadIB, DXGI_FORMAT_R32_UINT, 0);&#xD;&#xA;&#xD;&#xA;		d3d11DeviceContext-&gt;DrawIndexed(deferredQuadIndiceCount, 0, 0);&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;	 hr = swapChain-&gt;Present(0, 0);&#xD;&#xA;&#xD;&#xA;	 if (FAILED(hr))&#xD;&#xA;	 {&#xD;&#xA;		 MessageBox(0, L&quot;Swap Chain Present Error.&quot;, 0, 0);&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Here is the Input Layout...&#xD;&#xA;&#xD;&#xA;     namespace Vertex&#xD;&#xA;     {&#xD;&#xA;	     struct Deferred&#xD;&#xA;	     {&#xD;&#xA;		     VECTOR&lt;float&gt; Position;&#xD;&#xA;		     float Position_W;&#xD;&#xA;	     };&#xD;&#xA;     }&#xD;&#xA;     // C++ side above &#xD;&#xA;     &#xD;&#xA;     // Shaderside below&#xD;&#xA;     namespace InputLayout&#xD;&#xA;     {&#xD;&#xA;	     static ID3D11InputLayout* Deferred;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;     const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC[] =&#xD;&#xA;     {&#xD;&#xA;	     { &quot;POSITION&quot;,	0, DXGI_FORMAT_R32G32B32A32_FLOAT,	0, 0,	D3D11_INPUT_PER_VERTEX_DATA, 0 }&#xD;&#xA;     };&#xD;&#xA;Creation of the Input Layouts and Loading of the shaders themselves from file. &#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;    bool DirectX::initShaders()&#xD;&#xA;    {&#xD;&#xA;	std::vector&lt;char&gt; shaderBuffer;&#xD;&#xA;	std::string filename;&#xD;&#xA;	HRESULT hr;&#xD;&#xA;&#xD;&#xA;	// deferredVS&#xD;&#xA;	filename = &quot;Shaders\\deferredVS.cso&quot;;&#xD;&#xA;	if (!shaderFileToMemory(filename, shaderBuffer))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Load defaultVS Shader Into Memory Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;	hr = d3d11Device-&gt;CreateVertexShader(&amp;shaderBuffer[0], shaderBuffer.size(), NULL, &amp;deferredVertexShader);&#xD;&#xA;	hr = d3d11Device-&gt;CreateInputLayout(InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC, 1, &amp;shaderBuffer[0], shaderBuffer.size(), &amp;InputLayout::Deferred);&#xD;&#xA;&#xD;&#xA;	// deferredPS&#xD;&#xA;	filename = &quot;Shaders\\deferredPS.cso&quot;;&#xD;&#xA;	if (!shaderFileToMemory(filename, shaderBuffer))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Load deferredPS Shader Into Memory Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;	hr = d3d11Device-&gt;CreatePixelShader(&amp;shaderBuffer[0], shaderBuffer.size(), NULL, &amp;deferredPixelShader);&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Vertex and Index Buffer were created using the following...&#xD;&#xA;&#xD;&#xA;     bool DirectX::initDeferredQuad()&#xD;&#xA;     {&#xD;&#xA;	std::vector&lt;Vertex::Deferred&gt; deferredQuadVertices;&#xD;&#xA;	std::vector&lt;unsigned int&gt; deferredQuadIndices;&#xD;&#xA;&#xD;&#xA;	Vertex::Deferred quadVertices[4];&#xD;&#xA;	Vertex::Deferred quadVertice;&#xD;&#xA;&#xD;&#xA;	quadVertice.Position_W	= 1.0;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(-1.0, 1.0, 0.0);&#xD;&#xA;	quadVertices[0] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(1.0, 1.0, 0.0);&#xD;&#xA;	quadVertices[1] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(-1.0, -1.0, 0.0);&#xD;&#xA;	quadVertices[2] = quadVertice;&#xD;&#xA;	quadVertice.Position = VECTOR&lt;float&gt;(1.0, -1.0, 0.0);&#xD;&#xA;	quadVertices[3] = quadVertice;&#xD;&#xA;&#xD;&#xA;	D3D11_BUFFER_DESC vbd;&#xD;&#xA;	D3D11_SUBRESOURCE_DATA vinitData;&#xD;&#xA;	HRESULT hr;&#xD;&#xA;	&#xD;&#xA;	vbd.Usage				= D3D11_USAGE_IMMUTABLE;&#xD;&#xA;	vbd.ByteWidth			= sizeof(Vertex::Deferred) * 4;&#xD;&#xA;	vbd.BindFlags			= D3D11_BIND_VERTEX_BUFFER;&#xD;&#xA;	vbd.CPUAccessFlags		= 0;&#xD;&#xA;	vbd.MiscFlags			= 0;&#xD;&#xA;	vbd.StructureByteStride = 0;&#xD;&#xA;&#xD;&#xA;	vinitData.pSysMem		= &amp;quadVertices;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateBuffer(&amp;vbd, &amp;vinitData, &amp;deferredQuadVB);&#xD;&#xA;&#xD;&#xA;	if (FAILED(hr))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;Quad Vertex Buffer Creation Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	unsigned int quadIndices[] =&#xD;&#xA;	{	0, 1, 2,&#xD;&#xA;		2, 1, 3 };&#xD;&#xA;&#xD;&#xA;	deferredQuadIndiceCount = 6;&#xD;&#xA;&#xD;&#xA;	D3D11_BUFFER_DESC ibd;&#xD;&#xA;	D3D11_SUBRESOURCE_DATA iinitData;&#xD;&#xA;&#xD;&#xA;	ibd.Usage				= D3D11_USAGE_IMMUTABLE;&#xD;&#xA;	ibd.ByteWidth			= sizeof(unsigned int) * 6;&#xD;&#xA;	ibd.BindFlags			= D3D11_BIND_INDEX_BUFFER;&#xD;&#xA;	ibd.CPUAccessFlags		= 0;&#xD;&#xA;	ibd.MiscFlags			= 0;&#xD;&#xA;&#xD;&#xA;	iinitData.pSysMem		= &amp;deferredQuadIndices;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateBuffer(&amp;ibd, &amp;iinitData, &amp;deferredQuadIB);&#xD;&#xA;&#xD;&#xA;	if (FAILED(hr))&#xD;&#xA;	{&#xD;&#xA;		MessageBox(0, L&quot;QuadIndex Buffer Creation Error.&quot;, 0, 0);&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;I thought the issue was here. Since my Vertex Shader is feeding the Rasterizer data directly, the Vertex Shader has to output SV_Position in Clip Space. Wouldn't the coordinates I've made for my vertices be correct for a quad composed of 2 triangles that would take up the entire screen? (I've tried changing the z values, no change)&#xD;&#xA;&#xD;&#xA;Here is resizeSwapChain, I've been bulding/rebuild the viewport in here.&#xD;&#xA;This function is called at initialization and whenever the window size changes after the window adjustment has been released (WM_EXITSIZEMOVE).&#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     void DirectX::resizeSwapChain()&#xD;&#xA;     {&#xD;&#xA;	const unsigned int clientWidth = uClient-&gt;getAppScreenWidth();&#xD;&#xA;	const unsigned int clientHeight = uClient-&gt;getAppScreenHeight();&#xD;&#xA;	HRESULT hr;&#xD;&#xA;&#xD;&#xA;	if (!(d3d11RenderTargetView == NULL))&#xD;&#xA;	{&#xD;&#xA;		d3d11RenderTargetView-&gt;Release();&#xD;&#xA;		d3d11RenderTargetView = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	if (!(d3d11DepthStencilView) == NULL)&#xD;&#xA;	{&#xD;&#xA;		d3d11DepthStencilView-&gt;Release();&#xD;&#xA;		d3d11DepthStencilView = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	if (!(d3d11StencilBuffer) == NULL)&#xD;&#xA;	{&#xD;&#xA;		d3d11StencilBuffer-&gt;Release();&#xD;&#xA;		d3d11StencilBuffer = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	hr = swapChain-&gt;ResizeBuffers(1, clientWidth, clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);&#xD;&#xA;&#xD;&#xA;	ID3D11Texture2D* backBuffer;&#xD;&#xA;&#xD;&#xA;	hr = swapChain-&gt;GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast&lt;void**&gt;(&amp;backBuffer));&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateRenderTargetView(backBuffer, 0, &amp;d3d11RenderTargetView);&#xD;&#xA;&#xD;&#xA;	backBuffer-&gt;Release();&#xD;&#xA;	backBuffer = 0;&#xD;&#xA;&#xD;&#xA;	D3D11_TEXTURE2D_DESC depthStencilDesc;&#xD;&#xA;&#xD;&#xA;	depthStencilDesc.Width = clientWidth;&#xD;&#xA;	depthStencilDesc.Height = clientHeight;&#xD;&#xA;	depthStencilDesc.MipLevels = 1;&#xD;&#xA;	depthStencilDesc.ArraySize = 1;&#xD;&#xA;	depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;&#xD;&#xA;&#xD;&#xA;	if (msaaEnabled)&#xD;&#xA;	{&#xD;&#xA;		depthStencilDesc.SampleDesc.Count = 4;&#xD;&#xA;		depthStencilDesc.SampleDesc.Quality = msaaQuality - 1;&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		depthStencilDesc.SampleDesc.Count = 1;&#xD;&#xA;		depthStencilDesc.SampleDesc.Quality = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;	depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;&#xD;&#xA;	depthStencilDesc.CPUAccessFlags = 0;&#xD;&#xA;	depthStencilDesc.MiscFlags = 0;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateTexture2D(&amp;depthStencilDesc, 0, &amp;d3d11StencilBuffer);&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateDepthStencilView(d3d11StencilBuffer, 0, &amp;d3d11DepthStencilView);&#xD;&#xA;&#xD;&#xA;	d3d11ScreenViewport.TopLeftX = 0;&#xD;&#xA;	d3d11ScreenViewport.TopLeftY = 0;&#xD;&#xA;	d3d11ScreenViewport.Width = static_cast&lt;float&gt;(clientWidth);&#xD;&#xA;	d3d11ScreenViewport.Height = static_cast&lt;float&gt;(clientHeight);&#xD;&#xA;	d3d11ScreenViewport.MinDepth = 0.0f;&#xD;&#xA;	d3d11ScreenViewport.MaxDepth = 1.0f;&#xD;&#xA;&#xD;&#xA;	d3d11DeviceContext-&gt;RSSetViewports(1, &amp;d3d11ScreenViewport);&#xD;&#xA;&#xD;&#xA;	mainCamera-&gt;setProjectionMatrix(MATRIX4X4&lt;float&gt;::perspectiveFieldOfViewLeftHandMatrix(0.25 * GenericMath::PI, GenericMath::aspectRatio(clientWidth, clientHeight), 0.001, 1000.0));&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Here is my D3D11 Initialization function, this is where I create my Rasterization states.&#xD;&#xA;Irrelevant code has been omitted.&#xD;&#xA;&#xD;&#xA;     bool DirectX::initDirectX()&#xD;&#xA;     {&#xD;&#xA;	D3D_FEATURE_LEVEL featureLevel;&#xD;&#xA;&#xD;&#xA;	HRESULT hr = D3D11CreateDevice(NULL, driverType, NULL, NULL, NULL, 0, D3D11_SDK_VERSION, &amp;d3d11Device, &amp;featureLevel, &amp;d3d11DeviceContext);&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, 4, &amp;msaaQuality);&#xD;&#xA;&#xD;&#xA;	DXGI_SWAP_CHAIN_DESC swapChainDesc;&#xD;&#xA;	swapChainDesc.BufferDesc.Width = uClient-&gt;getAppScreenWidth();&#xD;&#xA;	swapChainDesc.BufferDesc.Height = uClient-&gt;getAppScreenHeight();&#xD;&#xA;	swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;&#xD;&#xA;	swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;&#xD;&#xA;	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;&#xD;&#xA;	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;&#xD;&#xA;&#xD;&#xA;	if (msaaEnabled)&#xD;&#xA;	{&#xD;&#xA;		swapChainDesc.SampleDesc.Count = 4;&#xD;&#xA;		swapChainDesc.SampleDesc.Quality = msaaQuality - 1;&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		swapChainDesc.SampleDesc.Count = 1;&#xD;&#xA;		swapChainDesc.SampleDesc.Quality = 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;&#xD;&#xA;	swapChainDesc.BufferCount = 1;&#xD;&#xA;	swapChainDesc.OutputWindow = *windowsHandle;&#xD;&#xA;	swapChainDesc.Windowed = true;&#xD;&#xA;	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;&#xD;&#xA;	swapChainDesc.Flags = 0;&#xD;&#xA;&#xD;&#xA;	IDXGIDevice* dxgiDevice = 0;&#xD;&#xA;	hr = d3d11Device-&gt;QueryInterface(__uuidof(IDXGIDevice), (void**)&amp;dxgiDevice);&#xD;&#xA;&#xD;&#xA;	IDXGIAdapter* dxgiAdapter = 0;&#xD;&#xA;	hr = dxgiDevice-&gt;GetParent(__uuidof(IDXGIAdapter), (void**)&amp;dxgiAdapter);&#xD;&#xA;&#xD;&#xA;	IDXGIFactory* dxgiFactory = 0;&#xD;&#xA;	hr = dxgiAdapter-&gt;GetParent(__uuidof(IDXGIFactory), (void**)&amp;dxgiFactory);&#xD;&#xA;&#xD;&#xA;	hr = dxgiFactory-&gt;CreateSwapChain(d3d11Device, &amp;swapChainDesc, &amp;swapChain);&#xD;&#xA;&#xD;&#xA;	dxgiDevice-&gt;Release();&#xD;&#xA;	dxgiDevice = 0;&#xD;&#xA;&#xD;&#xA;	dxgiAdapter-&gt;Release();&#xD;&#xA;	dxgiAdapter = 0;&#xD;&#xA;&#xD;&#xA;	dxgiFactory-&gt;Release();&#xD;&#xA;	dxgiFactory = 0;&#xD;&#xA;&#xD;&#xA;	resizeGBuffers();&#xD;&#xA;	resizeSwapChain();&#xD;&#xA;&#xD;&#xA;	D3D11_RASTERIZER_DESC rasterizerDesc;&#xD;&#xA;	ZeroMemory(&amp;rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));&#xD;&#xA;	rasterizerDesc.FillMode = D3D11_FILL_SOLID;&#xD;&#xA;	rasterizerDesc.CullMode = D3D11_CULL_BACK;&#xD;&#xA;	rasterizerDesc.FrontCounterClockwise = false;&#xD;&#xA;	rasterizerDesc.DepthClipEnable = true;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateRasterizerState( &amp;rasterizerDesc, &amp;d3d11SolidRS);\&#xD;&#xA;&#xD;&#xA;	ZeroMemory(&amp;rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));&#xD;&#xA;&#xD;&#xA;	rasterizerDesc.FillMode = D3D11_FILL_WIREFRAME;&#xD;&#xA;	rasterizerDesc.CullMode = D3D11_CULL_BACK;&#xD;&#xA;	rasterizerDesc.FrontCounterClockwise = false;&#xD;&#xA;	rasterizerDesc.DepthClipEnable = true;&#xD;&#xA;&#xD;&#xA;	hr = d3d11Device-&gt;CreateRasterizerState( &amp;rasterizerDesc, &amp;d3d11WireframeRS);&#xD;&#xA;&#xD;&#xA;	d3d11DeviceContext-&gt;RSSetState(d3d11SolidRS);&#xD;&#xA;&#xD;&#xA;	return true;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;If anyone needs more info, just ask. Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UJYGI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4691" PostHistoryTypeId="2" PostId="2099" RevisionGUID="a59f131a-45ff-444e-8bb0-e7bf8fdb4961" CreationDate="2016-02-26T13:34:28.383" UserId="2508" Text="I'm beginner in OpenGL and I stumbled into a problem. I'm in OpenGL 2.1 for the time being, if that's of any help. &#xD;&#xA;&#xD;&#xA;I set my Frustum as such:&#xD;&#xA;&#xD;&#xA;    glFrustum(-1366, 1366, -768, 768, 1, 20000);&#xD;&#xA;&#xD;&#xA;Now, when I create a cube from quads like this:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 500.0&#xD;&#xA;    500.0, 500.0, 500.0&#xD;&#xA;    500.0, 0.0, 500.0&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;It is not a cube, as I expected. It's extremely stretched along the z axis.&#xD;&#xA;&#xD;&#xA;What am I doing wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4692" PostHistoryTypeId="1" PostId="2099" RevisionGUID="a59f131a-45ff-444e-8bb0-e7bf8fdb4961" CreationDate="2016-02-26T13:34:28.383" UserId="2508" Text="Frustum - problem with z dimension" ContentLicense="CC BY-SA 3.0" />
  <row Id="4693" PostHistoryTypeId="3" PostId="2099" RevisionGUID="a59f131a-45ff-444e-8bb0-e7bf8fdb4961" CreationDate="2016-02-26T13:34:28.383" UserId="2508" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4698" PostHistoryTypeId="5" PostId="2099" RevisionGUID="f5274609-cf5c-4ab8-98c9-1f1e6ab5582a" CreationDate="2016-02-26T14:40:19.237" UserId="2508" Comment="more details about the z axis" Text="I'm beginner in OpenGL and I stumbled into a problem. I'm in OpenGL 2.1 for the time being, if that's of any help. &#xD;&#xA;&#xD;&#xA;I set my Frustum as such:&#xD;&#xA;&#xD;&#xA;    glFrustum(-1366, 1366, -768, 768, 1, 20000);&#xD;&#xA;&#xD;&#xA;Now, when I create a cube from quads like this:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 500.0&#xD;&#xA;    500.0, 500.0, 500.0&#xD;&#xA;    500.0, 0.0, 500.0&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;It is not a cube, as I expected. It's extremely stretched along the z axis.&#xD;&#xA;&#xD;&#xA;The shape starts to resemble a cube a bit when I change the vertices to:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 0.3&#xD;&#xA;    500.0, 500.0, 0.3&#xD;&#xA;    500.0, 0.0, 0.3&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;What am I doing wrong? How to fix this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4699" PostHistoryTypeId="5" PostId="2099" RevisionGUID="136e017d-32f7-48a2-a17e-7aeff86ccaa6" CreationDate="2016-02-26T15:51:42.163" UserId="2508" Comment="added code for initializing matrices and transformations" Text="I'm beginner in OpenGL and I stumbled into a problem. I'm in OpenGL 2.1 for the time being, if that's of any help. &#xD;&#xA;&#xD;&#xA;I set my Frustum as such:&#xD;&#xA;&#xD;&#xA;    glFrustum(-1366, 1366, -768, 768, 1, 20000);&#xD;&#xA;&#xD;&#xA;Now, when I create a cube from quads like this:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 500.0&#xD;&#xA;    500.0, 500.0, 500.0&#xD;&#xA;    500.0, 0.0, 500.0&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;It is not a cube, as I expected. It's extremely stretched along the z axis.&#xD;&#xA;&#xD;&#xA;The shape starts to resemble a cube a bit when I change the vertices to:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 0.3&#xD;&#xA;    500.0, 500.0, 0.3&#xD;&#xA;    500.0, 0.0, 0.3&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;Code related to this (I am translating this from assembly which I am actually using).&#xD;&#xA;&#xD;&#xA;Matrices setup on initialization:&#xD;&#xA;&#xD;&#xA;    glMatrixMode(GL_PROJECTION);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;    glFrustum(-1366.0, 1366.0, -768.0, 768.0, 1.0, 20000.0);&#xD;&#xA;    &#xD;&#xA;    glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;&#xD;&#xA;Transformations of the cube inside the &quot;render()&quot; function:&#xD;&#xA;&#xD;&#xA;    glTranslated(1000.0, 500.0, 0.0);&#xD;&#xA;    glRotated(degrees, 0.0, 0.0, 1.0); // degrees is +=2 every frame&#xD;&#xA;    glTranslated(-250.0, -250.0, distance); // distance is -=0.001 every frame&#xD;&#xA;&#xD;&#xA;There are no other matrix operations in the code.&#xD;&#xA;&#xD;&#xA;The code uses GLUT to initialize a window with double buffer and depth buffer. Depth testing is enabled.&#xD;&#xA;&#xD;&#xA;It all seems to work as expected, the rotation is ok, movement also. I am only troubled by the fact that when I define a 500.0x500.0x500.0 cube, the actual output is not a cube.&#xD;&#xA;&#xD;&#xA;What am I doing wrong? How to fix this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4700" PostHistoryTypeId="5" PostId="2099" RevisionGUID="88b13893-2ead-439c-8df5-ff0b27de44bc" CreationDate="2016-02-26T16:00:45.180" UserId="2508" Comment="added screenshot" Text="I'm beginner in OpenGL and I stumbled into a problem. I'm in OpenGL 2.1 for the time being, if that's of any help. &#xD;&#xA;&#xD;&#xA;I set my Frustum as such:&#xD;&#xA;&#xD;&#xA;    glFrustum(-1366, 1366, -768, 768, 1, 20000);&#xD;&#xA;&#xD;&#xA;Now, when I create a cube from quads like this:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 500.0&#xD;&#xA;    500.0, 500.0, 500.0&#xD;&#xA;    500.0, 0.0, 500.0&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;It is not a cube, as I expected. It's extremely stretched along the z axis.&#xD;&#xA;&#xD;&#xA;Here's a screenshot of how it looks now: https://www.dropbox.com/s/diznfumtev7g259/Screenshot%20from%202016-02-26%2017%3A01%3A58.png?dl=0 (I removed one of the faces temporarily)&#xD;&#xA;&#xD;&#xA;The shape starts to resemble a cube a bit when I change the vertices to:&#xD;&#xA;&#xD;&#xA;    0.0, 500.0, 0.0&#xD;&#xA;    500.0, 500.0, 0.0&#xD;&#xA;    500.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 500.0, 0.3&#xD;&#xA;    500.0, 500.0, 0.3&#xD;&#xA;    500.0, 0.0, 0.3&#xD;&#xA;    etc.&#xD;&#xA;&#xD;&#xA;Code related to this (I am translating this from assembly which I am actually using).&#xD;&#xA;&#xD;&#xA;Matrices setup on initialization:&#xD;&#xA;&#xD;&#xA;    glMatrixMode(GL_PROJECTION);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;    glFrustum(-1366.0, 1366.0, -768.0, 768.0, 1.0, 20000.0);&#xD;&#xA;    &#xD;&#xA;    glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;&#xD;&#xA;Transformations of the cube inside the &quot;render()&quot; function:&#xD;&#xA;&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;    glTranslated(1000.0, 500.0, 0.0);&#xD;&#xA;    glRotated(degrees, 0.0, 0.0, 1.0); // degrees is +=2 every frame&#xD;&#xA;    glTranslated(-250.0, -250.0, distance); // distance is -=0.001 every frame&#xD;&#xA;&#xD;&#xA;There are no other matrix operations in the code.&#xD;&#xA;&#xD;&#xA;The code uses GLUT to initialize a window with double buffer and depth buffer. Depth testing is enabled.&#xD;&#xA;&#xD;&#xA;It all seems to work as expected, the rotation is ok, movement also. I am only troubled by the fact that when I define a 500.0x500.0x500.0 cube, the actual output is not a cube.&#xD;&#xA;&#xD;&#xA;What am I doing wrong? How to fix this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4701" PostHistoryTypeId="2" PostId="2101" RevisionGUID="a65fb187-2a02-4b49-a0ae-29d780cd5cdd" CreationDate="2016-02-26T16:05:40.143" UserId="2726" Text="I can't believe it has taken me this long to find this...&#xD;&#xA;&#xD;&#xA;So the array I was giving the Index Buffer Desc that contains the data was the wrong one... It was a blank one that I forgot I didn't need, the vector if you look at the code.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ruxiT.png&#xD;&#xA;&#xD;&#xA;Look at that garbage. Those are supposed to be the indices...&#xD;&#xA;Well at least I know how to use the debugger now, thanks guys got it working." ContentLicense="CC BY-SA 3.0" />
  <row Id="4702" PostHistoryTypeId="2" PostId="2102" RevisionGUID="7b647bbe-fad4-451e-a92d-0383a79b4c43" CreationDate="2016-02-26T17:49:05.657" UserId="56" Text="JFA (the algorithm described here: http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf) can be used to get an approxiation of a vornoi diagram, or a distance transform.  It does so in linear time based on the size of the resulting image, not of the number of seeds.&#xD;&#xA;&#xD;&#xA;What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;If they were similar sizes, I'm sure you could just let the shorter axis have extra JFA steps of size 1, while the larger axis finished it work (like having a 512 x 256 sized image).  For vastly different sized axis dimensions this could be a lot more inefficient though - say that you had a volume texture that was 512 x 512 x 4.&#xD;&#xA;&#xD;&#xA;Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Or at that point is a different algorithm more appropriate to use? If so, what algorithm might that be?&#xD;&#xA;&#xD;&#xA;In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="4703" PostHistoryTypeId="1" PostId="2102" RevisionGUID="7b647bbe-fad4-451e-a92d-0383a79b4c43" CreationDate="2016-02-26T17:49:05.657" UserId="56" Text="Is Jump Flood Algorithm Separable?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4704" PostHistoryTypeId="3" PostId="2102" RevisionGUID="7b647bbe-fad4-451e-a92d-0383a79b4c43" CreationDate="2016-02-26T17:49:05.657" UserId="56" Text="|signed-distance-field|vornoi|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4705" PostHistoryTypeId="5" PostId="2102" RevisionGUID="7aa3b175-8a67-4a01-b0e1-07290b7838ff" CreationDate="2016-02-26T18:34:55.903" UserId="56" Comment="added 139 characters in body" Text="JFA (the algorithm described here: http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf) can be used to get an approxiation of a vornoi diagram, or a distance transform.  It does so in linear time based on the size of the resulting image, not of the number of seeds.&#xD;&#xA;&#xD;&#xA;What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;If they were similar sizes, I'm sure you could just let the shorter axis have extra JFA steps of size 1, while the larger axis finished it work (like having a 512 x 256 sized image).  For vastly different sized axis dimensions this could be a lot more inefficient though - say that you had a volume texture that was 512 x 512 x 4.&#xD;&#xA;&#xD;&#xA;Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Or at that point is a different algorithm more appropriate to use? If so, what algorithm might that be?&#xD;&#xA;&#xD;&#xA;In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds.  Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="4706" PostHistoryTypeId="2" PostId="2103" RevisionGUID="046c91cc-532e-4023-8042-1aebb13ece11" CreationDate="2016-02-26T19:58:08.587" UserId="2748" Text="Disney have a tool that analyses the database. &#xD;&#xA;&#xD;&#xA;http://www.disneyanimation.com/technology/brdf.html&#xD;&#xA;&#xD;&#xA;Is browsing the source code for this an option?&#xD;&#xA;&#xD;&#xA;https://github.com/wdas/brdf&#xD;&#xA;&#xD;&#xA;You could contact the authors perhaps?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4707" PostHistoryTypeId="2" PostId="2104" RevisionGUID="0bb0a180-c8c2-4a2c-ac28-4fec9363a8bb" CreationDate="2016-02-26T22:46:50.040" UserId="2508" Text="Okay. So after 6 hours of tinkering with my code, trying different approaches and googling for solutions, I found this page:&#xD;&#xA;&#xD;&#xA;http://www.glprogramming.com/red/chapter03.html&#xD;&#xA;&#xD;&#xA;There is a short C listing which put me on the right track to solve this.&#xD;&#xA;&#xD;&#xA;What I did wrong was that I should have set the frustum to something like this:&#xD;&#xA;&#xD;&#xA;    GLdouble x0 = -(1366/768);&#xD;&#xA;    GLdouble x1 = 1366/768;&#xD;&#xA;    glFrustum(x0, x1, -1, 1, 1, 100);&#xD;&#xA;    // the last two values aren't critical, as long as they are positive&#xD;&#xA;&#xD;&#xA;But before that, I should have set the **glViewport** properly, before setting up the frustum:&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, 1366, 768);&#xD;&#xA;&#xD;&#xA;**I didn't do it and that's why my code produced such weird results.**&#xD;&#xA;&#xD;&#xA;Now I can create a unit cube with following vertices:&#xD;&#xA;&#xD;&#xA;    0.0, 1.0, 0.0&#xD;&#xA;    1.0, 1.0, 0.0&#xD;&#xA;    1.0, 0.0, 0.0&#xD;&#xA;    0.0, 0.0, 0.0&#xD;&#xA;    0.0, 1.0, 1.0&#xD;&#xA;    1.0, 1.0, 1.0&#xD;&#xA;    1.0, 0.0, 1.0&#xD;&#xA;    0.0, 0.0, 1.0&#xD;&#xA;&#xD;&#xA;And it will display properly as a cube of size 1 in every direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="4708" PostHistoryTypeId="6" PostId="2102" RevisionGUID="560eaf82-5d3a-428b-91bb-ffcad2e760ed" CreationDate="2016-02-27T09:22:48.793" UserId="231" Comment="edited tags" Text="|signed-distance-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4709" PostHistoryTypeId="5" PostId="2102" RevisionGUID="560eaf82-5d3a-428b-91bb-ffcad2e760ed" CreationDate="2016-02-27T09:22:48.793" UserId="231" Comment="edited tags" Text="JFA (the algorithm described here: http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf) can be used to get an approximation of a Voronoi diagram, or a distance transform.  It does so in linear time based on the size of the resulting image, not on the number of seeds.&#xD;&#xA;&#xD;&#xA;What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;If they were similar sizes, I'm sure you could just let the shorter axis have extra JFA steps of size 1, while the larger axis finished it work (like having a 512 x 256 sized image).  For vastly different sized axis dimensions this could be a lot more inefficient though - say that you had a volume texture that was 512 x 512 x 4.&#xD;&#xA;&#xD;&#xA;Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Or at that point is a different algorithm more appropriate to use? If so, what algorithm might that be?&#xD;&#xA;&#xD;&#xA;In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds.  Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence." ContentLicense="CC BY-SA 3.0" />
  <row Id="4710" PostHistoryTypeId="2" PostId="2105" RevisionGUID="d06b86d0-5c8d-4a2d-8218-d767332410f4" CreationDate="2016-02-27T18:39:16.277" UserId="2712" Text="I have a line segment defined by two end points. And I have another randomly chosen third point and I want to find out if the third point is on the line segment or not. By &quot;On the line segment&quot;, I mean that exactly on the line segment, not intersecting the line segment and end up on the other side of the line segment. I hope I explained the issue. Some mathematical explanation along with algorithm to it  is earnestly requested.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4711" PostHistoryTypeId="1" PostId="2105" RevisionGUID="d06b86d0-5c8d-4a2d-8218-d767332410f4" CreationDate="2016-02-27T18:39:16.277" UserId="2712" Text="Test if a point is on a line segment" ContentLicense="CC BY-SA 3.0" />
  <row Id="4712" PostHistoryTypeId="3" PostId="2105" RevisionGUID="d06b86d0-5c8d-4a2d-8218-d767332410f4" CreationDate="2016-02-27T18:39:16.277" UserId="2712" Text="|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4713" PostHistoryTypeId="2" PostId="2106" RevisionGUID="727a1375-4d63-4d85-9235-47da7b99b784" CreationDate="2016-02-27T22:40:53.963" UserId="2748" Text="I have the world point positions of two objects, and would like to test if there is an intersection between the two objects from this information.&#xD;&#xA;&#xD;&#xA;What methods can I use to test this, especially at the boundaries. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4714" PostHistoryTypeId="1" PostId="2106" RevisionGUID="727a1375-4d63-4d85-9235-47da7b99b784" CreationDate="2016-02-27T22:40:53.963" UserId="2748" Text="How to test if one object A intersects and is therefore partly or wholly inside object B" ContentLicense="CC BY-SA 3.0" />
  <row Id="4715" PostHistoryTypeId="3" PostId="2106" RevisionGUID="727a1375-4d63-4d85-9235-47da7b99b784" CreationDate="2016-02-27T22:40:53.963" UserId="2748" Text="|algorithm|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4716" PostHistoryTypeId="2" PostId="2107" RevisionGUID="838a4dc4-f52f-4c00-90ff-63326bd9d2e3" CreationDate="2016-02-27T22:48:44.553" UserId="2748" Text="&#xD;&#xA;Was interested in this myself and did some digging, I was wondering if they where spectral, but it appears not (although some interesting work on spectral BRDF is here http://web.cs.wpi.edu/~emmanuel/courses/cs563/write_ups/cliffl/cliffl_spectral_brdf.html )&#xD;&#xA;&#xD;&#xA;This chat seems to indicate they are camera native linear, probably with sRGB primaries.&#xD;&#xA;&#xD;&#xA;https://groups.google.com/forum/#!msg/pbrt/p9zMvZlaodA/4RD7-We8h4gJ&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4718" PostHistoryTypeId="2" PostId="2108" RevisionGUID="586cb7a6-0510-43e9-88d1-2461d80f5e66" CreationDate="2016-02-28T04:47:55.957" UserId="56" Text="Let's say you have your two points that define the line segment: $A$ and $B$, and a point $P$ that you are testing to see if it is on the line segment.&#xD;&#xA;&#xD;&#xA;Firstly, you get a normalized vector from $A$ to $B$, as well as the distance from $A$ to $B$.&#xD;&#xA;    &#xD;&#xA;    direction = normalize(B - A);&#xD;&#xA;    length = length(B-A);&#xD;&#xA;&#xD;&#xA;Next, you use dot product to project the point $P$ onto the line segment defined by $A$ and $B$.&#xD;&#xA;&#xD;&#xA;    projection = dot(P, direction);&#xD;&#xA;&#xD;&#xA;This projection value represents how far down the line segment from $A$ to $B$ that the closest point to $P$ is.  It may be a negative distance, or it might be farther from $A$ than $B$ is, so you next clamp this value to the line segment.&#xD;&#xA;&#xD;&#xA;    projection = clamp(projection, 0.0, length);&#xD;&#xA;&#xD;&#xA;Note that in your case, instead of clamping, you could just detect when the projection was out of bounds and return false at this point as well.&#xD;&#xA;&#xD;&#xA;Continuing on, you now have the distance from $A$ to $B$ that the closest point to $P$ is, as the value in $projection$.  You calculate that actual point:&#xD;&#xA;&#xD;&#xA;    closestPoint = A + projection * direction;&#xD;&#xA;&#xD;&#xA;If $closestPoint$ == $P$, you know that $P$ lies on the line segment defined by $A$ and $B$ because the closest point on that line segment is the point $P$ itself.&#xD;&#xA;&#xD;&#xA;However, in practice, you might run into some numerical precision problems due to having limited accuracy in computer calculations.&#xD;&#xA;&#xD;&#xA;To get around this, instead of checking if $closestPoint$ and $P$ are the same, you should probably instead consider them the same if the distance between them is smaller than some threshold value.  This way, if precision issues come up, you'll still get the answers you want in the cases you want them.&#xD;&#xA;&#xD;&#xA;Too large of a threshold value, and you will get points being considered on the line that you really wouldn't consider on the line (if this happens, make your threshold smaller).&#xD;&#xA;&#xD;&#xA;Too small of a threshold value, and some points that you would consider being on the line will not register as being on the line (if this happens, make your threshold larger).&#xD;&#xA;    " ContentLicense="CC BY-SA 3.0" />
  <row Id="4719" PostHistoryTypeId="2" PostId="2109" RevisionGUID="08dcc923-7c1e-4e4a-a149-99c3fbb1f278" CreationDate="2016-02-28T05:45:40.427" UserId="288" Text="Do you need exact triangle - triangle intersection test that is do you need to know exactly the points of intersection of each object? If you just need a simple yes / no they have intersected then you could get away with creating an AABB ( https://en.wikipedia.org/wiki/Bounding_volume ) that encompasses each object and do a AABB -&gt; AABB ( good info here https://studiofreya.com/3d-math-and-physics/simple-aabb-vs-aabb-collision-detection/ ) intersection test? even if you need a more complex collision check Triangle -&gt; Triangle it is always a good idea to do a simple collision check first to make sure its worth doing the complex Triangle -&gt; Triangle intersection tests. Look here ( http://www.realtimerendering.com/intersections.html ) for all the normal object -&gt; object intersection tests you could possibly need " ContentLicense="CC BY-SA 3.0" />
  <row Id="4720" PostHistoryTypeId="2" PostId="2110" RevisionGUID="706ba8c8-6e37-4195-af2d-9fe2fdeebf3d" CreationDate="2016-02-28T15:05:52.690" UserId="2479" Text="Single-scattering microfacet-based surface models like the original [Torrance-Sparrow BRDF][1] or derived models like [the BSDF for rough dielectric surfaces][2] by Walter et al. neglect inter-reflection of light between microfacets, which results in energy loss causing darkening especially at higher roughness values.&#xD;&#xA;&#xD;&#xA;The problem can be easily demonstrated using the furnace test. I present here the results of the furnace test of my implementation of BRDF using the Smith model and GGX microfacet distribution for roughness parameters from 0.2 to 1.0 (the Fresnel coefficient is set to 1 here to make the problem easier to see):&#xD;&#xA;&#xD;&#xA;[![roughness 0.2][3]][3]&#xD;&#xA;[![roughness 0.4][4]][4]&#xD;&#xA;[![roughness 0.6][5]][5]&#xD;&#xA;[![roughness 0.8][6]][6]&#xD;&#xA;[![roughness 1.0][7]][7]&#xD;&#xA;&#xD;&#xA;Furnace test of my implementation of rough dielectric (IoR 1.51) BSDF using the Smith model and GGX microfacet distribution for roughness parameters from 0.2 to 1.0:&#xD;&#xA;&#xD;&#xA;[![roughness 0.2][8]][8]&#xD;&#xA;[![roughness 0.4][9]][9]&#xD;&#xA;[![roughness 0.6][10]][10]&#xD;&#xA;[![roughness 0.8][11]][11]&#xD;&#xA;[![roughness 1.0][12]][12]&#xD;&#xA;&#xD;&#xA;Eric Heitz et al. have just recently proposed a [multiple-scattering model][13] which solves the darkening problem by solving the light interaction completely, but there are performance issues due to stochastic nature of its evaluation routine as metioned by Heitz himself in the [LuxRender forum][14].&#xD;&#xA;&#xD;&#xA;Is there a known compensation method for recovering the lost energy of single-scattering models? Not necessarily physically correct, but at least not breaking physical plausibility (Helmholtz reciprocity and energy conservation) too much and, ideally, without the necessity of hand tuning parameters.&#xD;&#xA;&#xD;&#xA;In the [Disney BSDF][15], there is a parametrized component called “sheen” (basically a Fresnel-based glossy lobe) which can be used for compensation of darkening at edges, but as they mention in their [Siggraph 2015 course][16] it is very ad hoc method: &#xD;&#xA;&#xD;&#xA;&gt; “...this is very approximate, and doesn't work as well for other&#xD;&#xA;&gt; roughness values...”&#xD;&#xA;&#xD;&#xA;The [aforementioned comment][14] from Eric Heitz in the LuxRender forum also suggests using some compensation hack but, unfortunately, doesn't go into any details:&#xD;&#xA;&#xD;&#xA;&gt; To my knowledge, you can use some simpler hacks to improve energy conservation in the single scattering models (like tweaking albedo). However, if you do that, you cannot get a perfectly energy conserving material (for instance perfect white rough glass) without breaking the reciprocity of the BSDF.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.cornell.edu/~westin/pubs/TorranceSparrowJOSA1967.pdf&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZmLm3.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/lIxSc.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/autib.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ij2yS.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/eP5XW.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/EZWNf.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/wtcLq.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/YisLW.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/SdaAG.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5PdTb.jpg&#xD;&#xA;  [13]: https://eheitzresearch.wordpress.com/240-2/&#xD;&#xA;  [14]: http://www.luxrender.net/forum/viewtopic.php?f=36&amp;t=12534#p118797&#xD;&#xA;  [15]: http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf&#xD;&#xA;  [16]: http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4721" PostHistoryTypeId="1" PostId="2110" RevisionGUID="706ba8c8-6e37-4195-af2d-9fe2fdeebf3d" CreationDate="2016-02-28T15:05:52.690" UserId="2479" Text="Compensation for energy loss in single-scattering microfacet BSDF models" ContentLicense="CC BY-SA 3.0" />
  <row Id="4722" PostHistoryTypeId="3" PostId="2110" RevisionGUID="706ba8c8-6e37-4195-af2d-9fe2fdeebf3d" CreationDate="2016-02-28T15:05:52.690" UserId="2479" Text="|rendering|brdf|physically-based|microfacet|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4723" PostHistoryTypeId="2" PostId="2111" RevisionGUID="33519f8a-1aca-485e-a0d7-4f654778be88" CreationDate="2016-02-28T21:56:21.483" UserId="1810" Text="Someone points me that *[this article][1]  describes the spectral response of the camera the MERL paper used, and even provides colour transform matrices at the end. Unfortunately, using those transforms result in even worse results than assuming sRGB primaries.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://white.stanford.edu/~brian/papers/pdc/ColorBalanceSPIE03.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4724" PostHistoryTypeId="2" PostId="2112" RevisionGUID="4c8958c4-bd15-4640-9304-ac500b9d1389" CreationDate="2016-02-28T22:16:11.020" UserId="2769" Text="To my knowledge, there is no easy and analytic way of recovering the energy lost in single-scattering models. The previous techniques precompute the energy loss and reinject it in the BRDF as a diffuse-like component:&#xD;&#xA;&#xD;&#xA;- http://sirkan.iit.bme.hu/~szirmay/scook.pdf&#xD;&#xA;- http://www.cs.cornell.edu/projects/layered-sg14/layered.pdf&#xD;&#xA;&#xD;&#xA;What they propose is energy conservative and reciprocal, and it is probably the simplest way of fixing the visual darkening due to the energy loss. The main drawback is that since the energy loss does not have an analytic expression, it has to be precomputed and stored in a look-up table. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4731" PostHistoryTypeId="2" PostId="2115" RevisionGUID="fde5d97a-2879-4626-9f80-16c7355a8c1a" CreationDate="2016-02-29T16:13:22.317" UserId="2771" Text="So I was tasked to create a model of the Cornell Box. I've managed to do everything up until casting shadows, in which case some shadows are cast when there should not be any. Here are pictures of what it looks like now and a larger picture of what it should look like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've found that for some reason, the box walls are also casting shadows. &#xD;&#xA;&#xD;&#xA;A quick run-down of how it works: we have a pinhole camera which casts rays out and finds the nearest collision point, which is everything you're seeing. It saves these points as well as the distance from some start pt (camera in this case) to the collision point in a pre-defined data structure called an Intersection. It then uses this data to calculate the distance away from the light to create the intensities in lighting. The same method that is used to find the nearest collision point is used to find the nearest object for shadows as well using the original collision point as the start and the light source as the direction of the ray vector.&#xD;&#xA;&#xD;&#xA;I've narrowed down the problem to raytracing; when checking to see if there are any objects to cast shadows from from say the upper-right region of the back gray wall, the cyan ceiling is picked up at a point from the same side of the light. E.g. say the light source is in the middle and the original point is on our right side of the light. The method somehow picks up a point that is on the same side of the light when the vector should be going straight through the light source and end somewhere on our left side.&#xD;&#xA;&#xD;&#xA;Here is my source code for the functions in question:&#xD;&#xA;&#xD;&#xA;    bool ClosestIntersection( vec3 start, vec3 dir, const vector&lt;Triangle&gt;&amp; triangles, Intersection&amp; it ) {&#xD;&#xA;    &#xD;&#xA;    	vec3 least;&#xD;&#xA;    	vec3 e1, e2, b, v0;&#xD;&#xA;    	mat3 A;&#xD;&#xA;    	&#xD;&#xA;    	least[0] = m;&#xD;&#xA;    &#xD;&#xA;    	int index = triangles.size()-1;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; int(triangles.size()); i++) {&#xD;&#xA;    &#xD;&#xA;    		v0 = triangles[i].v0;&#xD;&#xA;    		e1 = triangles[i].v1 - v0;&#xD;&#xA;    		e2 = triangles[i].v2 - v0;&#xD;&#xA;    		b = start - v0;&#xD;&#xA;    &#xD;&#xA;    		A = mat3( -dir, e1, e2);&#xD;&#xA;    &#xD;&#xA;    		if(!getInverse(A,b)) {continue;}&#xD;&#xA;    &#xD;&#xA;    		vec3 x = A * b;&#xD;&#xA;    &#xD;&#xA;    		if(x[0] &lt;= least[0] &amp;&amp; x[1] + x[2] &lt;= 1.f &amp;&amp; x[1] &gt;= 0.f &amp;&amp; x[2] &gt;= 0.f &amp;&amp; x[0] &gt;= 0.00001f) {&#xD;&#xA;    			least = x;&#xD;&#xA;    			index = i;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	if (least[0] == m) {&#xD;&#xA;    		return false;&#xD;&#xA;    	}&#xD;&#xA;    	else {&#xD;&#xA;    		it.position = least[0] * dir + start;&#xD;&#xA;    		const vec3 t = it.position-start;&#xD;&#xA;    		it.distance = sqrt(t[0]*t[0] + t[1]*t[1] + t[2]*t[2]);&#xD;&#xA;    		it.triangleIndex = index;&#xD;&#xA;    		return true;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 DirectLight( const Intersection&amp; i ){&#xD;&#xA;    	const Triangle T = triangles[i.triangleIndex];&#xD;&#xA;    	const vec3 r = lightPos - i.position;&#xD;&#xA;    	const float dist = sqrt(r[0]*r[0] + r[1]*r[1] + r[2]*r[2]);&#xD;&#xA;    &#xD;&#xA;    	Intersection t;&#xD;&#xA;    	t.distance = dist;&#xD;&#xA;    	t.position = i.position;&#xD;&#xA;    	t.triangleIndex = i.triangleIndex; &#xD;&#xA;    &#xD;&#xA;    	//ClosestIntersection( i.position, lightPos, triangles, t);&#xD;&#xA;    &#xD;&#xA;    	/*&#xD;&#xA;    	if(!ClosestIntersection( lightPos, i.position, triangles, t)) {return vec3(1,0,0);}&#xD;&#xA;    	else { return vec3(0,0,0); } */&#xD;&#xA;    &#xD;&#xA;    	if(ClosestIntersection( i.position, lightPos, triangles, t) &amp;&amp; (dist-t.distance &gt; 1.f)) {&#xD;&#xA;    &#xD;&#xA;    		return vec3(0,0,0);&#xD;&#xA;    	} else {&#xD;&#xA;    		const vec3 B = 14.f * T.color * (float(max(dot(r,T.normal),float(0)) / float(4*3.14 * dist* dist)));&#xD;&#xA;    &#xD;&#xA;    		return B; &#xD;&#xA;    	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have spent over twelve hours trying to find this problem. Even my lecturer can't figure out the problem. Any help would be much appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dSgxY.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4732" PostHistoryTypeId="1" PostId="2115" RevisionGUID="fde5d97a-2879-4626-9f80-16c7355a8c1a" CreationDate="2016-02-29T16:13:22.317" UserId="2771" Text="Raytracing Problem - Casting Shadows" ContentLicense="CC BY-SA 3.0" />
  <row Id="4733" PostHistoryTypeId="3" PostId="2115" RevisionGUID="fde5d97a-2879-4626-9f80-16c7355a8c1a" CreationDate="2016-02-29T16:13:22.317" UserId="2771" Text="|raytracing|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4734" PostHistoryTypeId="5" PostId="2108" RevisionGUID="127fcc73-d961-40bc-bc24-ccd6d1df8f2c" CreationDate="2016-02-29T16:23:22.420" UserId="56" Comment="Fixed the problem called out in the comments by the OP" Text="Let's say you have your two points that define the line segment: $A$ and $B$, and a point $P$ that you are testing to see if it is on the line segment.&#xD;&#xA;&#xD;&#xA;Firstly, you get a normalized vector from $A$ to $B$, as well as the distance from $A$ to $B$.&#xD;&#xA;    &#xD;&#xA;    direction = normalize(B - A);&#xD;&#xA;    length = length(B-A);&#xD;&#xA;&#xD;&#xA;Next, you use dot product to project the point $P$ onto the line segment defined by $A$ and $B$, by first getting the vector from $A$ to $P$ and then dot producting that against the direction vector.&#xD;&#xA;&#xD;&#xA;    PRelative = P-A;&#xD;&#xA;    projection = dot(PRelative, direction);&#xD;&#xA;&#xD;&#xA;This projection value represents how far down the line segment from $A$ to $B$ that the closest point to $P$ is.  It may be a negative distance, or it might be farther from $A$ than $B$ is, so you next clamp this value to the line segment.&#xD;&#xA;&#xD;&#xA;    projection = clamp(projection, 0.0, length);&#xD;&#xA;&#xD;&#xA;Note that in your case, instead of clamping, you could just detect when the projection was out of bounds and return false at this point as well.&#xD;&#xA;&#xD;&#xA;Continuing on, you now have the distance from $A$ to $B$ that the closest point to $P$ is, as the value in $projection$.  You calculate that actual point:&#xD;&#xA;&#xD;&#xA;    closestPoint = A + projection * direction;&#xD;&#xA;&#xD;&#xA;If $closestPoint$ == $P$, you know that $P$ lies on the line segment defined by $A$ and $B$ because the closest point on that line segment is the point $P$ itself.&#xD;&#xA;&#xD;&#xA;However, in practice, you might run into some numerical precision problems due to having limited accuracy in computer calculations.&#xD;&#xA;&#xD;&#xA;To get around this, instead of checking if $closestPoint$ and $P$ are the same, you should probably instead consider them the same if the distance between them is smaller than some threshold value.  This way, if precision issues come up, you'll still get the answers you want in the cases you want them.&#xD;&#xA;&#xD;&#xA;Too large of a threshold value, and you will get points being considered on the line that you really wouldn't consider on the line (if this happens, make your threshold smaller).&#xD;&#xA;&#xD;&#xA;Too small of a threshold value, and some points that you would consider being on the line will not register as being on the line (if this happens, make your threshold larger).&#xD;&#xA;    " ContentLicense="CC BY-SA 3.0" />
  <row Id="4740" PostHistoryTypeId="2" PostId="2117" RevisionGUID="a0254b7f-310f-49c5-8423-05da77d03a30" CreationDate="2016-02-29T19:19:41.820" UserId="2775" Text="I've been stuck on how to approach this for a while, so any suggestions would be gratefully appreciated!&#xD;&#xA;&#xD;&#xA;I want to map a texture in the form of a lower right euclidean triangle to a hyperbolic triangle on the Poincare Disk.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the texture (the top left triangle of the texture is transparent and unused). You might recognise this as part of Escher's Circle Limit I&#xD;&#xA;&#xD;&#xA;Sorry, see the comment as I am not allowed to post more than two links it seems! &#xD;&#xA;&#xD;&#xA;And this is what my polygon looks like (it's centred at the origin, which means that two edges are straight lines, however in general all three edges will be curves as in the first picture):&#xD;&#xA;&#xD;&#xA;[![Wireframe Polygon][1]][1]&#xD;&#xA;&#xD;&#xA;The centre of the polygon is the incentre of the euclidean triangle formed by its vertices and I'm UV mapping the texture using it's incentre, dividing it into the same number of faces as the polygon has and mapping each face onto the corresponding polygon face. However the the result looks like this:&#xD;&#xA;&#xD;&#xA;[![Textured Polygon][2]][2]&#xD;&#xA;&#xD;&#xA;If anybody thinks this is solvable using UV mapping I'd be happy to provide some example code, however I'm beginning to think this might not be possible and I'll have to write my own mapping functions.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1QB1E.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3Jw9I.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4741" PostHistoryTypeId="1" PostId="2117" RevisionGUID="a0254b7f-310f-49c5-8423-05da77d03a30" CreationDate="2016-02-29T19:19:41.820" UserId="2775" Text="Map a texture onto a hyperbolic triangle" ContentLicense="CC BY-SA 3.0" />
  <row Id="4742" PostHistoryTypeId="3" PostId="2117" RevisionGUID="a0254b7f-310f-49c5-8423-05da77d03a30" CreationDate="2016-02-29T19:19:41.820" UserId="2775" Text="|texture|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4743" PostHistoryTypeId="2" PostId="2118" RevisionGUID="85a541ab-9bfc-41ae-b675-11776c921f1a" CreationDate="2016-02-29T20:21:54.260" UserId="48" Text="My guess is that to get the texture to look right, you'll have to subdivide the interior of the triangle as well, and approximate the non-linear UV mapping within it.&#xD;&#xA;&#xD;&#xA;Currently, it looks like you're subdividing around the edges of the triangle, and forming a fan of smaller triangles between the edge and the incenter. This would be fine if you were just rendering the triangle in a solid color. But when applying a texture, you're getting discontinuities at the boundaries of those subdivisions, because the texture is just stretched linearly across each subdivided triangle and not correctly approximating the hyperbolic mapping along the radial direction.&#xD;&#xA;&#xD;&#xA;You'll need to subdivide along both axes, something like this:&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;and position all the vertices appropriately in screen space and UV space to approximate the hyperbolic coordinates in the interior of the triangle. If you subdivide finely enough, this should produce the illusion of a continuously curving texture mapping.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jhKX2.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="4744" PostHistoryTypeId="2" PostId="2119" RevisionGUID="460c29f7-05ad-470e-8d6a-27fc2a393c61" CreationDate="2016-02-29T20:29:24.230" UserId="231" Text="# Quick answers to your individual questions&#xD;&#xA;&#xD;&#xA;### What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;The paper uses square images with side lengths that are a power of 2. This is for ease of explanation, but is not necessary for the algorithm to work. See section 3.1:&#xD;&#xA;&#xD;&#xA;&gt; Without loss of generality, we can assume n is a power of 2.&#xD;&#xA;&#xD;&#xA;That is, this assumption is not required in order for the algorithm to work.&#xD;&#xA;&#xD;&#xA;### Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Running on each axis separately is likely to give more incorrect pixel results, *and* take longer to run in most cases. In extreme cases where one of the image side lengths is less than 8 (the number of jump directions), it may be faster as the algorithm treats those 8 directions sequentially, but for any wider image, separating the axes loses the advantage of treating them in parallel.&#xD;&#xA;&#xD;&#xA;### In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds&#xD;&#xA;&#xD;&#xA;The paper mentions arbitrary shaped seeds in section 6 under the subheading &quot;Generalized Voronoi Diagram&quot;:&#xD;&#xA;&#xD;&#xA;&gt; ...our algorithms treat such generalized seeds as collections of point seeds and thus expect to inherit the good performance obtained for point seeds.&#xD;&#xA;&#xD;&#xA;So provided it suits your purpose to model arbitrary shapes as collections of pixels, you don't need to make any adjustment to the algorithm. Simply feed in a texture that labels all pixels in an arbitrary shaped seed with the same seed number, but different locations.&#xD;&#xA;&#xD;&#xA;### Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence&#xD;&#xA;&#xD;&#xA;For &quot;weighting on seeds such as multiplicative and additive&quot;, the paper only mentions the possibility in passing in section 8, as potential future work. However, this should be straightforward to implement provided your desired weighting can be included in the seed data that is passed from pixel to pixel.&#xD;&#xA;&#xD;&#xA;The current algorithm passes `&lt;s, position(s)&gt;` to specify a seed and its position, and only one seed is stored per pixel at any one time. Extending this to store `&lt;s, position(s), weight(s)&gt;` provides all the information required to weight the distance function and calculate whether the new seed being passed to a pixel is closer to it than the one it is currently storing.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Detailed explanation of why&#xD;&#xA;&#xD;&#xA;To follow shortly.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4745" PostHistoryTypeId="5" PostId="2119" RevisionGUID="53a12ba5-b6db-4f8d-b8c6-11d8094a7703" CreationDate="2016-02-29T20:36:33.577" UserId="231" Comment="added 518 characters in body" Text="# Quick answers to your individual questions&#xD;&#xA;&#xD;&#xA;### What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;The paper uses square images with side lengths that are a power of 2. This is for ease of explanation, but is not necessary for the algorithm to work. See section 3.1:&#xD;&#xA;&#xD;&#xA;&gt; Without loss of generality, we can assume n is a power of 2.&#xD;&#xA;&#xD;&#xA;That is, this assumption is not required in order for the algorithm to work.&#xD;&#xA;&#xD;&#xA;### Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Running on each axis separately is likely to give more incorrect pixel results, *and* take longer to run in most cases. In extreme cases where one of the image side lengths is less than 8 (the number of jump directions), it may be faster as the algorithm treats those 8 directions sequentially, but for any wider image, separating the axes loses the advantage of treating them in parallel.&#xD;&#xA;&#xD;&#xA;### In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds&#xD;&#xA;&#xD;&#xA;The paper mentions arbitrary shaped seeds in section 6 under the subheading &quot;Generalized Voronoi Diagram&quot;:&#xD;&#xA;&#xD;&#xA;&gt; ...our algorithms treat such generalized seeds as collections of point seeds and thus expect to inherit the good performance obtained for point seeds.&#xD;&#xA;&#xD;&#xA;So provided it suits your purpose to model arbitrary shapes as collections of pixels, you don't need to make any adjustment to the algorithm. Simply feed in a texture that labels all pixels in an arbitrary shaped seed with the same seed number, but different locations.&#xD;&#xA;&#xD;&#xA;### Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence&#xD;&#xA;&#xD;&#xA;For &quot;weighting on seeds such as multiplicative and additive&quot;, the paper only mentions the possibility in passing in section 8, as potential future work. However, this should be straightforward to implement provided your desired weighting can be included in the seed data that is passed from pixel to pixel.&#xD;&#xA;&#xD;&#xA;The current algorithm passes `&lt;s, position(s)&gt;` to specify a seed and its position, and only one seed is stored per pixel at any one time. Extending this to store `&lt;s, position(s), weight(s)&gt;` provides all the information required to weight the distance function and calculate whether the new seed being passed to a pixel is closer to it than the one it is currently storing.&#xD;&#xA;&#xD;&#xA;You could even include two weights, one multiplicative and one additive, and just set the multiplicative one to 1 and the additive one to 0 when not required. Then your algorithm would include the possibility of being used for multiplicatively weighted seeds, additively weighted seeds, or even a combination of both at once or some of each. This would just need&#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), multiplicative(s), additive(s)&gt;`&#xD;&#xA;&#xD;&#xA;and the current algorithm would be equivalent to this new algorithm using &#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), 1, 0&gt;`&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Detailed explanation of why&#xD;&#xA;&#xD;&#xA;To follow shortly.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4746" PostHistoryTypeId="5" PostId="2119" RevisionGUID="e15956b5-6729-4848-97cf-17195dccc8b2" CreationDate="2016-02-29T21:38:49.917" UserId="231" Comment="Add explanation for arbitrary side lengths" Text="# Quick answers to your individual questions&#xD;&#xA;&#xD;&#xA;### What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;The paper uses square images with side lengths that are a power of 2. This is for ease of explanation, but is not necessary for the algorithm to work. See section 3.1:&#xD;&#xA;&#xD;&#xA;&gt; Without loss of generality, we can assume n is a power of 2.&#xD;&#xA;&#xD;&#xA;That is, this assumption is not required in order for the algorithm to work.&#xD;&#xA;&#xD;&#xA;### Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Running on each axis separately is likely to give more incorrect pixel results, *and* take longer to run in most cases. In extreme cases where one of the image side lengths is less than 8 (the number of jump directions), it may be faster as the algorithm treats those 8 directions sequentially, but for any wider image, separating the axes loses the advantage of treating them in parallel.&#xD;&#xA;&#xD;&#xA;### In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds&#xD;&#xA;&#xD;&#xA;The paper mentions arbitrary shaped seeds in section 6 under the subheading &quot;Generalized Voronoi Diagram&quot;:&#xD;&#xA;&#xD;&#xA;&gt; ...our algorithms treat such generalized seeds as collections of point seeds and thus expect to inherit the good performance obtained for point seeds.&#xD;&#xA;&#xD;&#xA;So provided it suits your purpose to model arbitrary shapes as collections of pixels, you don't need to make any adjustment to the algorithm. Simply feed in a texture that labels all pixels in an arbitrary shaped seed with the same seed number, but different locations.&#xD;&#xA;&#xD;&#xA;### Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence&#xD;&#xA;&#xD;&#xA;For &quot;weighting on seeds such as multiplicative and additive&quot;, the paper only mentions the possibility in passing in section 8, as potential future work. However, this should be straightforward to implement provided your desired weighting can be included in the seed data that is passed from pixel to pixel.&#xD;&#xA;&#xD;&#xA;The current algorithm passes `&lt;s, position(s)&gt;` to specify a seed and its position, and only one seed is stored per pixel at any one time. Extending this to store `&lt;s, position(s), weight(s)&gt;` provides all the information required to weight the distance function and calculate whether the new seed being passed to a pixel is closer to it than the one it is currently storing.&#xD;&#xA;&#xD;&#xA;You could even include two weights, one multiplicative and one additive, and just set the multiplicative one to 1 and the additive one to 0 when not required. Then your algorithm would include the possibility of being used for multiplicatively weighted seeds, additively weighted seeds, or even a combination of both at once or some of each. This would just need&#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), multiplicative(s), additive(s)&gt;`&#xD;&#xA;&#xD;&#xA;and the current algorithm would be equivalent to this new algorithm using &#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), 1, 0&gt;`&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Detailed explanation of why&#xD;&#xA;&#xD;&#xA;*As in the paper, all uses of $\log()$ refer to the base 2 logarithm.*&#xD;&#xA;&#xD;&#xA;### The algorithm does not need to be adapted for different side lengths&#xD;&#xA;&#xD;&#xA;If the side lengths are not equal, and are not powers of 2, there is no need to adapt the algorithm. It already deals with pixels on the edge of the image for which some of the jump directions lead outside the image. Since the algorithm already omits the seed information for directions that lead outside the image, a width or height that is not a power of 2 will not be a problem. For an image of width W and height H, the maximum jump size required will be&#xD;&#xA;&#xD;&#xA;$$\large2^{\lceil\log(\max(W,H))\rceil-1}$$&#xD;&#xA;&#xD;&#xA;For the case of equal width and height N, this reduces to&#xD;&#xA;&#xD;&#xA;$$\large2^{\lceil\log(N)\rceil-1}$$&#xD;&#xA;&#xD;&#xA;In the case of side lengths that are powers of 2, this reduces to&#xD;&#xA;&#xD;&#xA;$$\large2^{\log(N)-1}=N/2$$&#xD;&#xA;&#xD;&#xA;as used in the paper.&#xD;&#xA;&#xD;&#xA;In more intuitive terms, round the maximum side length up to the next power of 2, and then halve that to get the maximum jump size.&#xD;&#xA;&#xD;&#xA;This is always enough to cover every pixel in the image from every other pixel in the image, as the offset to any pixel will be in the range 0 to N-1 if the longest side length is N. Combinations of the powers of 2 from 0 to N/2 will cover every integer up to N-1 if N is a power of 2, and if N is not a power of 2 the range covered can only be larger than required, due to taking the ceiling of the logarithm (rounding up to the next power of 2).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4747" PostHistoryTypeId="5" PostId="2102" RevisionGUID="8d6db367-ba86-4d18-858e-aa33b0e290f8" CreationDate="2016-02-29T21:47:32.867" UserId="56" Comment="it's logarithmic time based on image size, not linear, fixing." Text="JFA (the algorithm described here: http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf) can be used to get an approximation of a Voronoi diagram, or a distance transform.  It does so in logarithmic time based on the size of the resulting image, not on the number of seeds.&#xD;&#xA;&#xD;&#xA;What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;If they were similar sizes, I'm sure you could just let the shorter axis have extra JFA steps of size 1, while the larger axis finished it work (like having a 512 x 256 sized image).  For vastly different sized axis dimensions this could be a lot more inefficient though - say that you had a volume texture that was 512 x 512 x 4.&#xD;&#xA;&#xD;&#xA;Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Or at that point is a different algorithm more appropriate to use? If so, what algorithm might that be?&#xD;&#xA;&#xD;&#xA;In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds.  Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence." ContentLicense="CC BY-SA 3.0" />
  <row Id="4748" PostHistoryTypeId="5" PostId="2119" RevisionGUID="b61641f0-c42b-4100-8a04-291d15283cf2" CreationDate="2016-02-29T22:11:58.790" UserId="231" Comment="Add explanation for not separating axes" Text="# Quick answers to your individual questions&#xD;&#xA;&#xD;&#xA;### What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;The paper uses square images with side lengths that are a power of 2. This is for ease of explanation, but is not necessary for the algorithm to work. See section 3.1:&#xD;&#xA;&#xD;&#xA;&gt; Without loss of generality, we can assume n is a power of 2.&#xD;&#xA;&#xD;&#xA;That is, this assumption is not required in order for the algorithm to work.&#xD;&#xA;&#xD;&#xA;### Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Running on each axis separately is likely to give more incorrect pixel results, *and* take longer to run in most cases. In extreme cases where one of the image side lengths is less than 8 (the number of jump directions), it may be faster as the algorithm treats those 8 directions sequentially, but for any wider image, separating the axes loses the advantage of treating them in parallel.&#xD;&#xA;&#xD;&#xA;### In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds&#xD;&#xA;&#xD;&#xA;The paper mentions arbitrary shaped seeds in section 6 under the subheading &quot;Generalized Voronoi Diagram&quot;:&#xD;&#xA;&#xD;&#xA;&gt; ...our algorithms treat such generalized seeds as collections of point seeds and thus expect to inherit the good performance obtained for point seeds.&#xD;&#xA;&#xD;&#xA;So provided it suits your purpose to model arbitrary shapes as collections of pixels, you don't need to make any adjustment to the algorithm. Simply feed in a texture that labels all pixels in an arbitrary shaped seed with the same seed number, but different locations.&#xD;&#xA;&#xD;&#xA;### Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence&#xD;&#xA;&#xD;&#xA;For &quot;weighting on seeds such as multiplicative and additive&quot;, the paper only mentions the possibility in passing in section 8, as potential future work. However, this should be straightforward to implement provided your desired weighting can be included in the seed data that is passed from pixel to pixel.&#xD;&#xA;&#xD;&#xA;The current algorithm passes `&lt;s, position(s)&gt;` to specify a seed and its position, and only one seed is stored per pixel at any one time. Extending this to store `&lt;s, position(s), weight(s)&gt;` provides all the information required to weight the distance function and calculate whether the new seed being passed to a pixel is closer to it than the one it is currently storing.&#xD;&#xA;&#xD;&#xA;You could even include two weights, one multiplicative and one additive, and just set the multiplicative one to 1 and the additive one to 0 when not required. Then your algorithm would include the possibility of being used for multiplicatively weighted seeds, additively weighted seeds, or even a combination of both at once or some of each. This would just need&#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), multiplicative(s), additive(s)&gt;`&#xD;&#xA;&#xD;&#xA;and the current algorithm would be equivalent to this new algorithm using &#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), 1, 0&gt;`&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Detailed explanation of why&#xD;&#xA;&#xD;&#xA;*As in the paper, all uses of $\log()$ refer to the base 2 logarithm.*&#xD;&#xA;&#xD;&#xA;### The algorithm does not need to be adapted for different side lengths&#xD;&#xA;&#xD;&#xA;If the side lengths are not equal, and are not powers of 2, there is no need to adapt the algorithm. It already deals with pixels on the edge of the image for which some of the jump directions lead outside the image. Since the algorithm already omits the seed information for directions that lead outside the image, a width or height that is not a power of 2 will not be a problem. For an image of width W and height H, the maximum jump size required will be&#xD;&#xA;&#xD;&#xA;$$\large2^{\lceil\log(\max(W,H))\rceil-1}$$&#xD;&#xA;&#xD;&#xA;For the case of equal width and height N, this reduces to&#xD;&#xA;&#xD;&#xA;$$\large2^{\lceil\log(N)\rceil-1}$$&#xD;&#xA;&#xD;&#xA;In the case of side lengths that are powers of 2, this reduces to&#xD;&#xA;&#xD;&#xA;$$\large2^{\log(N)-1}=N/2$$&#xD;&#xA;&#xD;&#xA;as used in the paper.&#xD;&#xA;&#xD;&#xA;In more intuitive terms, round the maximum side length up to the next power of 2, and then halve that to get the maximum jump size.&#xD;&#xA;&#xD;&#xA;This is always enough to cover every pixel in the image from every other pixel in the image, as the offset to any pixel will be in the range 0 to N-1 if the longest side length is N. Combinations of the powers of 2 from 0 to N/2 will cover every integer up to N-1 if N is a power of 2, and if N is not a power of 2 the range covered can only be larger than required, due to taking the ceiling of the logarithm (rounding up to the next power of 2).&#xD;&#xA;&#xD;&#xA;### Separating axes is likely to reduce quality&#xD;&#xA;&#xD;&#xA;Section 5 of the paper describes possible errors. Every pixel is reachable by a path from every other pixel, but some paths do not bring the correct nearest seed, due to that seed not being the nearest to a previous pixel in the path. A pixel that does not allow a seed to propagate past it is said to have &quot;killed&quot; that seed. If the nearest seed to a pixel is killed on all paths to that pixel, then the pixel will record some other seed and there will be an incorrect colour in the final image.&#xD;&#xA;&#xD;&#xA;Only one path needs to exist that does not kill the seed in order for the final result to be correct. Incorrect colours only occur when *all* paths from the correct seed are blocked.&#xD;&#xA;&#xD;&#xA;If a path involves alternating horizontal and vertical jumps, separating axes will make this path impossible (all horizontal jumps will be taken before all vertical jumps, making alternating impossible). Diagonal jumps will not be possible at all. So any path that alternates or contains diagonal jumps will be excluded. Every pixel will still have a path to every other pixel, but since there are now fewer paths there is more chance of a given pixel being blocked from receiving the correct seed, so the final result will be more error prone.&#xD;&#xA;&#xD;&#xA;### Separating axes is likely to make the algorithm take longer&#xD;&#xA;&#xD;&#xA;The efficiency would probably be reduced by separating axes, as the flooding would no longer be done in parallel, but would instead be repeated for each axis. For 2D this would likely take approximately twice as long, and for 3D approximately 3 times as long.&#xD;&#xA;&#xD;&#xA;This may be somewhat mitigated by the lack of diagonal jumps, but I would still expect an overall reduction in efficiency.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4749" PostHistoryTypeId="5" PostId="2119" RevisionGUID="3999d33b-6a9c-48c7-9b6a-3bb98f71750d" CreationDate="2016-02-29T22:40:15.907" UserId="231" Comment="Add explanation for not separating axes" Text="# Quick answers to your individual questions&#xD;&#xA;&#xD;&#xA;### What do you do if your image is not the same size on each axis though?&#xD;&#xA;&#xD;&#xA;The paper uses square images with side lengths that are a power of 2. This is for ease of explanation, but is not necessary for the algorithm to work. See section 3.1:&#xD;&#xA;&#xD;&#xA;&gt; Without loss of generality, we can assume n is a power of 2.&#xD;&#xA;&#xD;&#xA;That is, this assumption is not required in order for the algorithm to work.&#xD;&#xA;&#xD;&#xA;### Is it possible to run JFA on each axis separately and still get decent results?&#xD;&#xA;&#xD;&#xA;Running on each axis separately is likely to give more incorrect pixel results, *and* take longer to run in most cases. In extreme cases where one of the image side lengths is less than 8 (the number of jump directions), it may be faster as the algorithm treats those 8 directions sequentially, but for any wider image, separating the axes loses the advantage of treating them in parallel.&#xD;&#xA;&#xD;&#xA;### In my situation ideally I'm looking to support both single point seeds, as well as arbitrary shaped seeds&#xD;&#xA;&#xD;&#xA;The paper mentions arbitrary shaped seeds in section 6 under the subheading &quot;Generalized Voronoi Diagram&quot;:&#xD;&#xA;&#xD;&#xA;&gt; ...our algorithms treat such generalized seeds as collections of point seeds and thus expect to inherit the good performance obtained for point seeds.&#xD;&#xA;&#xD;&#xA;So provided it suits your purpose to model arbitrary shapes as collections of pixels, you don't need to make any adjustment to the algorithm. Simply feed in a texture that labels all pixels in an arbitrary shaped seed with the same seed number, but different locations.&#xD;&#xA;&#xD;&#xA;### Possibly even weighted seeds, where the distance to a seed is adjusted by a multiplier and/or an adder to give it more or less influence&#xD;&#xA;&#xD;&#xA;For &quot;weighting on seeds such as multiplicative and additive&quot;, the paper only mentions the possibility in passing in section 8, as potential future work. However, this should be straightforward to implement provided your desired weighting can be included in the seed data that is passed from pixel to pixel.&#xD;&#xA;&#xD;&#xA;The current algorithm passes `&lt;s, position(s)&gt;` to specify a seed and its position, and only one seed is stored per pixel at any one time. Extending this to store `&lt;s, position(s), weight(s)&gt;` provides all the information required to weight the distance function and calculate whether the new seed being passed to a pixel is closer to it than the one it is currently storing.&#xD;&#xA;&#xD;&#xA;You could even include two weights, one multiplicative and one additive, and just set the multiplicative one to 1 and the additive one to 0 when not required. Then your algorithm would include the possibility of being used for multiplicatively weighted seeds, additively weighted seeds, or even a combination of both at once or some of each. This would just need&#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), multiplicative(s), additive(s)&gt;`&#xD;&#xA;&#xD;&#xA;and the current algorithm would be equivalent to this new algorithm using &#xD;&#xA;&#xD;&#xA;`&lt;s, position(s), 1, 0&gt;`&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Detailed explanation of why&#xD;&#xA;&#xD;&#xA;*As in the paper, all uses of $\log()$ refer to the base 2 logarithm.*&#xD;&#xA;&#xD;&#xA;### The algorithm does not need to be adapted for different side lengths&#xD;&#xA;&#xD;&#xA;If the side lengths are not equal, and are not powers of 2, there is no need to adapt the algorithm. It already deals with pixels on the edge of the image for which some of the jump directions lead outside the image. Since the algorithm already omits the seed information for directions that lead outside the image, a width or height that is not a power of 2 will not be a problem. For an image of width W and height H, the maximum jump size required will be&#xD;&#xA;&#xD;&#xA;$$\large2^{\lceil\log(\max(W,H))\rceil-1}$$&#xD;&#xA;&#xD;&#xA;For the case of equal width and height N, this reduces to&#xD;&#xA;&#xD;&#xA;$$\large2^{\lceil\log(N)\rceil-1}$$&#xD;&#xA;&#xD;&#xA;In the case of a side length N that is a power of 2, this reduces to&#xD;&#xA;&#xD;&#xA;$$\large2^{\log(N)-1}=N/2$$&#xD;&#xA;&#xD;&#xA;as used in the paper.&#xD;&#xA;&#xD;&#xA;In more intuitive terms, round the maximum side length up to the next power of 2, and then halve that to get the maximum jump size.&#xD;&#xA;&#xD;&#xA;This is always enough to cover every pixel in the image from every other pixel in the image, as the offset to any pixel will be in the range 0 to N-1 if the longest side length is N. Combinations of the powers of 2 from 0 to N/2 will cover every integer up to N-1 if N is a power of 2, and if N is not a power of 2 the range covered can only be larger than required, due to taking the ceiling of the logarithm (rounding up to the next power of 2).&#xD;&#xA;&#xD;&#xA;### Images with sides not a power of 2 will not be drastically less efficient&#xD;&#xA;&#xD;&#xA;The number of jumps depends on the longest side length, say L. If L is a power of 2 then the number of jumps is $\log(L)$. If L is not a power of 2 then the number of jumps is $\lceil\log(L)\rceil$. For a reasonably large image this will not be a large difference.&#xD;&#xA;&#xD;&#xA;For example, a 1024 by 1024 image will require 10 jump iterations. A 512 by 512 image will require 9 jump iterations. Anything between the two sizes will also require 10 iterations. Even in the worst case of an image only just over a power of 2, like a 513 by 513 image, it will only require 1 additional iteration, which at this scale is approximately 11% more (10 instead of 9).&#xD;&#xA;&#xD;&#xA;### Non-square images are less efficient per area&#xD;&#xA;&#xD;&#xA;Since the number of iterations required is determined by the longest side length, the time taken for a 1024 by 1024 image will be the same as for a 1024 by 16 image. A square image allows a larger area to be covered in the same number of iterations.&#xD;&#xA;&#xD;&#xA;### Separating axes is likely to reduce quality&#xD;&#xA;&#xD;&#xA;Section 5 of the paper describes possible errors. Every pixel is reachable by a path from every other pixel, but some paths do not bring the correct nearest seed, due to that seed not being the nearest to a previous pixel in the path. A pixel that does not allow a seed to propagate past it is said to have &quot;killed&quot; that seed. If the nearest seed to a pixel is killed on all paths to that pixel, then the pixel will record some other seed and there will be an incorrect colour in the final image.&#xD;&#xA;&#xD;&#xA;Only one path needs to exist that does not kill the seed in order for the final result to be correct. Incorrect colours only occur when *all* paths from the correct seed to a given pixel are blocked.&#xD;&#xA;&#xD;&#xA;If a path involves alternating horizontal and vertical jumps, separating axes will make this path impossible (all horizontal jumps will be taken before all vertical jumps, making alternating impossible). Diagonal jumps will not be possible at all. So any path that alternates or contains diagonal jumps will be excluded. Every pixel will still have a path to every other pixel, but since there are now fewer paths there is more chance of a given pixel being blocked from receiving the correct seed, so the final result will be more error prone.&#xD;&#xA;&#xD;&#xA;### Separating axes is likely to make the algorithm take longer&#xD;&#xA;&#xD;&#xA;The efficiency would probably be reduced by separating axes, as the flooding would no longer be done in parallel, but would instead be repeated for each axis. For 2D this would likely take approximately twice as long, and for 3D approximately 3 times as long.&#xD;&#xA;&#xD;&#xA;This may be somewhat mitigated by the lack of diagonal jumps, but I would still expect an overall reduction in efficiency.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4751" PostHistoryTypeId="5" PostId="2117" RevisionGUID="15a185f3-5f54-474e-9966-015d52e8913c" CreationDate="2016-03-01T00:06:55.113" UserId="2775" Comment="deleted 17 characters in body" Text="I've been stuck on how to approach this for a while, so any suggestions would be gratefully appreciated!&#xD;&#xA;&#xD;&#xA;I want to map a texture in the form of a lower right euclidean triangle to a hyperbolic triangle on the Poincare Disk.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the texture (the top left triangle of the texture is transparent and unused). You might recognise this as part of Escher's Circle Limit I&#xD;&#xA;&#xD;&#xA;Sorry, see the comment as I am not allowed to post more than two links it seems! &#xD;&#xA;&#xD;&#xA;And this is what my polygon looks like (it's centred at the origin, which means that two edges are straight lines, however in general all three edges will be circular arcs):&#xD;&#xA;&#xD;&#xA;[![Wireframe Polygon][1]][1]&#xD;&#xA;&#xD;&#xA;The centre of the polygon is the incentre of the euclidean triangle formed by its vertices and I'm UV mapping the texture using it's incentre, dividing it into the same number of faces as the polygon has and mapping each face onto the corresponding polygon face. However the the result looks like this:&#xD;&#xA;&#xD;&#xA;[![Textured Polygon][2]][2]&#xD;&#xA;&#xD;&#xA;If anybody thinks this is solvable using UV mapping I'd be happy to provide some example code, however I'm beginning to think this might not be possible and I'll have to write my own mapping functions.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1QB1E.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3Jw9I.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4756" PostHistoryTypeId="2" PostId="2120" RevisionGUID="5d91a45c-060e-4c2d-beea-400366cd86d9" CreationDate="2016-03-01T04:28:38.383" UserId="1810" Text="are you sure you are not re-intersecting the same surface when checking for light occluder ? this is a classical precision issue. There are many way to tackle it:&#xD;&#xA;&#xD;&#xA;- first, have a good conditionning of the intersection point, by reintersecting a second time: consider your first hit distance d as approximate, create the point E' = Eye + (d-eps)*ray, recompute the intersection from here.&#xD;&#xA;&#xD;&#xA;- second, for grazing angle, depending on your shape representation, storage and computation precision and scales, tesselation, you might have dangerous imprecision here, and must still ensure you don't reintersect the same surface. if flat or convex, you can tag it an non-intersectable for the shadow-ray test. A simpler trick (more approximate) is to displace the start of the shadow ray by epsilon in the normal direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="4757" PostHistoryTypeId="5" PostId="2120" RevisionGUID="0f923376-6f32-4041-9670-959078df6aaa" CreationDate="2016-03-01T05:24:10.303" UserId="1810" Comment="added 66 characters in body" Text="are you sure you are not re-intersecting the same surface when checking for light occluder ? this is a classical precision issue. There are many way to tackle it:&#xD;&#xA;&#xD;&#xA;- First, have a good conditioning of the intersection point, by reintersecting a second time: consider your first hit distance d as approximate, create the point E' = Eye + (d-eps)*ray, recompute the intersection from here. (variant: for the first intersection, just use the bounding box).&#xD;&#xA;&#xD;&#xA;- Second, for grazing angle, depending on your shape representation, storage and computation precision and scales, tessellation, you might have dangerous imprecision here too, and must still ensure you won't reintersect the same surface. If flat or convex or tesselated, you can tag it an non-intersectable for the shadow-ray test. &#xD;&#xA;A simpler trick (more approximate) is to displace the start of the shadow ray by epsilon in the normal direction. " ContentLicense="CC BY-SA 3.0" />
  <row Id="4763" PostHistoryTypeId="2" PostId="2122" RevisionGUID="2a861069-ad9e-48c9-8a0b-5ad681167806" CreationDate="2016-03-01T09:25:42.057" UserId="2712" Text="I am quite confused over how glm library is behaving or I am using it improperly.  &#xD;&#xA;&#xD;&#xA;    glm::vec2 testVec(6,-4);&#xD;&#xA;&#xD;&#xA;    float len = testVec.length();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I get the value 2 with the above code snippet. I believe I have trying to get the length of the vector defined by testVec. You know very well that it is not the correct length of the vector. What is that I am missing here ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;   &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4764" PostHistoryTypeId="1" PostId="2122" RevisionGUID="2a861069-ad9e-48c9-8a0b-5ad681167806" CreationDate="2016-03-01T09:25:42.057" UserId="2712" Text="vector length calculation with glm" ContentLicense="CC BY-SA 3.0" />
  <row Id="4765" PostHistoryTypeId="3" PostId="2122" RevisionGUID="2a861069-ad9e-48c9-8a0b-5ad681167806" CreationDate="2016-03-01T09:25:42.057" UserId="2712" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4766" PostHistoryTypeId="2" PostId="2123" RevisionGUID="540edede-d9aa-4876-830b-54fb64cf5d36" CreationDate="2016-03-01T09:47:35.483" UserId="2712" Text="Sorry folks for posting such a trivial issue !&#xD;&#xA;The issue is solved . I was using the wrong function. Here goes the correct one:&#xD;&#xA;&#xD;&#xA;    glm::vec2 testVec(6,-4);&#xD;&#xA;    float len  = glm::length(testVec);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4769" PostHistoryTypeId="6" PostId="2122" RevisionGUID="60430621-b0e2-45a9-bc0b-adb7b5701844" CreationDate="2016-03-01T09:49:42.487" UserId="16" Comment="edited tags, small improvements to formatting and spelling, also we usually dispense with the &quot;thanks&quot; around here." Text="|c++|vectors|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4770" PostHistoryTypeId="5" PostId="2122" RevisionGUID="60430621-b0e2-45a9-bc0b-adb7b5701844" CreationDate="2016-03-01T09:49:42.487" UserId="16" Comment="edited tags, small improvements to formatting and spelling, also we usually dispense with the &quot;thanks&quot; around here." Text="I am quite confused over how GLM library is behaving or I am using it improperly.  &#xD;&#xA;&#xD;&#xA;    glm::vec2 testVec(6,-4);&#xD;&#xA;&#xD;&#xA;    float len = testVec.length();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I get the value `2` with the above code snippet. I believe I am trying to get the length of the vector defined by `testVec`. You know very well that it is not the correct length of the vector. What am I missing here?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4771" PostHistoryTypeId="5" PostId="2123" RevisionGUID="5af6eb1d-717d-4951-b150-ccd33f637e87" CreationDate="2016-03-01T09:51:55.873" UserId="16" Comment="no need for the &quot;thanks&quot; :)" Text="Sorry folks for posting such a trivial issue! The issue is solved. I was using the wrong function. Here goes the correct one:&#xD;&#xA;&#xD;&#xA;    glm::vec2 testVec(6,-4);&#xD;&#xA;    float len  = glm::length(testVec);" ContentLicense="CC BY-SA 3.0" />
  <row Id="4772" PostHistoryTypeId="4" PostId="2122" RevisionGUID="60430621-b0e2-45a9-bc0b-adb7b5701844" CreationDate="2016-03-01T09:49:42.487" UserId="16" Comment="edited tags, small improvements to formatting and spelling, also we usually dispense with the &quot;thanks&quot; around here." Text="Get vector length with GLM" ContentLicense="CC BY-SA 3.0" />
  <row Id="4773" PostHistoryTypeId="5" PostId="2123" RevisionGUID="3010a10b-b07c-4b71-ab63-be32fb527b1b" CreationDate="2016-03-01T12:20:14.087" UserId="16" Comment="added definition of the function used in the question for completeness" Text="Sorry folks for posting such a trivial issue! The issue is solved. I was using the wrong function. Here goes the correct one:&#xD;&#xA;&#xD;&#xA;    glm::vec2 testVec(6,-4);&#xD;&#xA;    float len  = glm::length(testVec);&#xD;&#xA;&#xD;&#xA;The member function of the same name returns the number of components instead (i.e. `vec2::length` will always yield `2`, `vec3::length` will always yield `3`, etc.)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4774" PostHistoryTypeId="2" PostId="2125" RevisionGUID="350dc6c6-715e-41d5-a975-02b527b2fce8" CreationDate="2016-03-01T15:43:38.867" UserId="38" Text="There is a trick that many in fact let you sidestep the issue altogether\*. The scene and the set of things to be raytraced does not have to be the same. Most ray tracers allow for objects to not participate in shadow casting, reflections, etc.&#xD;&#xA;&#xD;&#xA;In your case you could just take the outside walls of from shadow casting and therefore they would not self shadow allowing you to put lights outside the box with no problems.&#xD;&#xA;&#xD;&#xA;Anyway you could add a slight bias to the sampling and consider the objects slightly further than your calculation result gives, for shadow casting this avoids all kinds of problems.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* Yes you have a problem you should fix that. But sometimes quick and done is all thats needed" ContentLicense="CC BY-SA 3.0" />
  <row Id="4776" PostHistoryTypeId="2" PostId="2126" RevisionGUID="5d9d5ddc-ac96-478e-af47-da0700122ba8" CreationDate="2016-03-02T09:34:14.927" UserId="2784" Text="I am trying to implement svg rendering by opengl using meshes. &#xD;&#xA;In paths with opacity less than 1, the color of overlapping strokes add up. &#xD;&#xA;&#xD;&#xA;[![!\[enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But it should be like this&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;the opengl calls are:&#xD;&#xA;&#xD;&#xA;        glDepthMask(false);&#xD;&#xA;		glEnable(GL20.GL_BLEND);&#xD;&#xA;		glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;		....&#xD;&#xA;        glDrawArrays(....);&#xD;&#xA;        ....&#xD;&#xA;		glDepthMask(true);&#xD;&#xA;&#xD;&#xA;is there any opengl calls, shader or other method to have same transparent value around the whole stroke without modifying the geometry of the shape?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rarVy.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M9PbX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4777" PostHistoryTypeId="1" PostId="2126" RevisionGUID="5d9d5ddc-ac96-478e-af47-da0700122ba8" CreationDate="2016-03-02T09:34:14.927" UserId="2784" Text="SVG opengl implementation - strokes overlap on transparency" ContentLicense="CC BY-SA 3.0" />
  <row Id="4778" PostHistoryTypeId="3" PostId="2126" RevisionGUID="5d9d5ddc-ac96-478e-af47-da0700122ba8" CreationDate="2016-03-02T09:34:14.927" UserId="2784" Text="|opengl|image-processing|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4779" PostHistoryTypeId="2" PostId="2127" RevisionGUID="afae9ee7-dddd-4608-ae13-95ed1ccac443" CreationDate="2016-03-02T09:51:44.850" UserId="137" Text="You can use the depth buffer to ensure that the second time you get on a point the pixels aren't written. &#xD;&#xA;&#xD;&#xA;You start with the maximum depth value and each new path (that you want to add to the existing drawn image) you decrement the depth." ContentLicense="CC BY-SA 3.0" />
  <row Id="4780" PostHistoryTypeId="2" PostId="2128" RevisionGUID="a41e3024-3ac8-4de1-8889-af74b73a4081" CreationDate="2016-03-02T11:03:45.360" UserId="2712" Text="I have a line segment defined by two coordinate values and I need to check if the line segment is parallel to the x-axis or y-axis. I believe that it is not that difficult to find. When it comes to test for parallelism against x-axis, we just need to check if the both the end points of the line segments has the equivalent y-value, whereas parallelism test against y-axis can be found if both the coordinate point ends have the same x-value. &#xD;&#xA;&#xD;&#xA;Any other better way do it is most welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4781" PostHistoryTypeId="1" PostId="2128" RevisionGUID="a41e3024-3ac8-4de1-8889-af74b73a4081" CreationDate="2016-03-02T11:03:45.360" UserId="2712" Text="vertical or horizontal line test" ContentLicense="CC BY-SA 3.0" />
  <row Id="4782" PostHistoryTypeId="3" PostId="2128" RevisionGUID="a41e3024-3ac8-4de1-8889-af74b73a4081" CreationDate="2016-03-02T11:03:45.360" UserId="2712" Text="|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4786" PostHistoryTypeId="2" PostId="2130" RevisionGUID="b41a95be-4647-4553-b8e7-9302526f8d67" CreationDate="2016-03-02T15:28:59.727" UserId="310" Text="In ray tracing / path tracing, one of the simplest way to anti-alias the image is to supersample the pixel values and average the results. IE. instead of shooting every sample through the center of the pixel, you offset the samples by some amount.&#xD;&#xA;&#xD;&#xA;In searching around the internet, I've found two somewhat different methods to do this:&#xD;&#xA;&#xD;&#xA;1. Generate samples however you want and weigh the result with a filter&#xD;&#xA;  - One is [PBRT][1]&#xD;&#xA;2. Generate the samples with a distribution equal to a the shape of a filter&#xD;&#xA;  - Two examples are [smallpt][2] and [Benedikt Bitterli][3]'s [Tungsten Renderer][4] &#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate and Weigh**&#xD;&#xA;&#xD;&#xA;The basic process is:&#xD;&#xA;&#xD;&#xA;  1. Create samples however you want (randomly, stratified, low-discrepancy sequences, etc.) &#xD;&#xA;  2. Offset the camera ray using two samples (x and y)&#xD;&#xA;  3. Render the scene with the ray&#xD;&#xA;  4. Calculate a weight using a filter function and the distance of the sample in reference to the pixel center. For example, Box Filter, Tent Filter, Gaussian Filter, etc.)&#xD;&#xA;[![Filter Shapes][5]][5]&#xD;&#xA;  5. Apply the weight to the color from the render&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate in the shape of a filter**&#xD;&#xA;&#xD;&#xA;The basic premise is to use [Inverse Transform Sampling][6] to create samples that are distributed according to the shape of a filter. For example a histogram of a samples distrusted in the shape of a Gaussian would be:&lt;br/&gt;&#xD;&#xA;[![Gaussian Histogram][7]][7]&#xD;&#xA;&#xD;&#xA;This can either be done exactly, or by binning the function into a discrete pdf/cdf. [smallpt][2] uses the exact inverse cdf of a tent filter. Examples of binning method can be found [here][8]&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;What are the pros and cons of each method? And why would you use one over the other? I can think of a few things:&#xD;&#xA;&#xD;&#xA;Generate and Weigh seems to be the most robust, allowing any combination of any sampling method with any filter. However, it requires you to track the weights in the ImageBuffer and then do a final resolve.&#xD;&#xA;&#xD;&#xA;Generate in the Shape of a Filter can only support positive filter shapes (ie. no Mitchell, Catmull Rom, or Lanczos), since you can not have a negative pdf. But, as mentioned above, it's easier to implement, since you don't need to track any weights.&#xD;&#xA;&#xD;&#xA;Though, in the end, I guess you can think of method 2 as a simplification of method 1, since it's essentially using an implicit Box Filter weight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/core/film.h#L114&#xD;&#xA;  [2]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/users/79/benedikt-bitterli&#xD;&#xA;  [4]: https://github.com/tunabrain/tungsten/blob/master/src/core/cameras/ReconstructionFilter.hpp&#xD;&#xA;  [5]: https://i.stack.imgur.com/gz7Bg.png&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Inverse_transform_sampling&#xD;&#xA;  [7]: https://i.stack.imgur.com/7pGFS.png&#xD;&#xA;  [8]: https://gist.github.com/RichieSams/ce2ca2a201227c1de543&#xD;&#xA;  " ContentLicense="CC BY-SA 3.0" />
  <row Id="4787" PostHistoryTypeId="1" PostId="2130" RevisionGUID="b41a95be-4647-4553-b8e7-9302526f8d67" CreationDate="2016-03-02T15:28:59.727" UserId="310" Text="Anti-aliasing / Filtering in Ray Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="4788" PostHistoryTypeId="3" PostId="2130" RevisionGUID="b41a95be-4647-4553-b8e7-9302526f8d67" CreationDate="2016-03-02T15:28:59.727" UserId="310" Text="|raytracing|antialiasing|pathtracing|filtering|supersampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4789" PostHistoryTypeId="5" PostId="2130" RevisionGUID="b8301494-4715-42ec-9b53-0a6a11efae9a" CreationDate="2016-03-02T20:49:13.130" UserId="310" Comment="Minor typo fix" Text="In ray tracing / path tracing, one of the simplest way to anti-alias the image is to supersample the pixel values and average the results. IE. instead of shooting every sample through the center of the pixel, you offset the samples by some amount.&#xD;&#xA;&#xD;&#xA;In searching around the internet, I've found two somewhat different methods to do this:&#xD;&#xA;&#xD;&#xA;1. Generate samples however you want and weigh the result with a filter&#xD;&#xA;  - One is [PBRT][1]&#xD;&#xA;2. Generate the samples with a distribution equal to a the shape of a filter&#xD;&#xA;  - Two examples are [smallpt][2] and [Benedikt Bitterli][3]'s [Tungsten Renderer][4] &#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate and Weigh**&#xD;&#xA;&#xD;&#xA;The basic process is:&#xD;&#xA;&#xD;&#xA;  1. Create samples however you want (randomly, stratified, low-discrepancy sequences, etc.) &#xD;&#xA;  2. Offset the camera ray using two samples (x and y)&#xD;&#xA;  3. Render the scene with the ray&#xD;&#xA;  4. Calculate a weight using a filter function and the distance of the sample in reference to the pixel center. For example, Box Filter, Tent Filter, Gaussian Filter, etc.)&#xD;&#xA;[![Filter Shapes][5]][5]&#xD;&#xA;  5. Apply the weight to the color from the render&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate in the shape of a filter**&#xD;&#xA;&#xD;&#xA;The basic premise is to use [Inverse Transform Sampling][6] to create samples that are distributed according to the shape of a filter. For example a histogram of a samples distributed in the shape of a Gaussian would be:&lt;br/&gt;&#xD;&#xA;[![Gaussian Histogram][7]][7]&#xD;&#xA;&#xD;&#xA;This can either be done exactly, or by binning the function into a discrete pdf/cdf. [smallpt][2] uses the exact inverse cdf of a tent filter. Examples of binning method can be found [here][8]&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;What are the pros and cons of each method? And why would you use one over the other? I can think of a few things:&#xD;&#xA;&#xD;&#xA;Generate and Weigh seems to be the most robust, allowing any combination of any sampling method with any filter. However, it requires you to track the weights in the ImageBuffer and then do a final resolve.&#xD;&#xA;&#xD;&#xA;Generate in the Shape of a Filter can only support positive filter shapes (ie. no Mitchell, Catmull Rom, or Lanczos), since you can not have a negative pdf. But, as mentioned above, it's easier to implement, since you don't need to track any weights.&#xD;&#xA;&#xD;&#xA;Though, in the end, I guess you can think of method 2 as a simplification of method 1, since it's essentially using an implicit Box Filter weight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/core/film.h#L114&#xD;&#xA;  [2]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/users/79/benedikt-bitterli&#xD;&#xA;  [4]: https://github.com/tunabrain/tungsten/blob/master/src/core/cameras/ReconstructionFilter.hpp&#xD;&#xA;  [5]: https://i.stack.imgur.com/gz7Bg.png&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Inverse_transform_sampling&#xD;&#xA;  [7]: https://i.stack.imgur.com/7pGFS.png&#xD;&#xA;  [8]: https://gist.github.com/RichieSams/ce2ca2a201227c1de543&#xD;&#xA;  " ContentLicense="CC BY-SA 3.0" />
  <row Id="4790" PostHistoryTypeId="2" PostId="2131" RevisionGUID="b13506f5-e755-48a0-afe1-ef1bf64951ab" CreationDate="2016-03-02T22:58:02.173" UserId="2786" Text="I am trying to implement a 2D version of Foster and Fedkiw's paper, &quot;Practical Animation of Liquids&quot; here: http://physbam.stanford.edu/~fedkiw/papers/stanford2001-02.pdf&#xD;&#xA;&#xD;&#xA;Mostly everything works, except for section 8: &quot;Conservation of Mass.&quot; There, we set up a matrix of equations to compute the pressures needed to make the liquid divergent free. &#xD;&#xA;&#xD;&#xA;I believe my code matches the paper, however I am getting an unsolvable matrix during the conservation of mass step.&#xD;&#xA;&#xD;&#xA;Here are my steps for generating the matrix A:&#xD;&#xA; 1. Set the diagonal entries $A_{i,i}$ to the negative of number of adjacent liquid cells to cell i.&#xD;&#xA; 2. Set the entries $A_{i,j}$ and $A_{j,i}$ to 1 if both cells i and j have liquid.&#xD;&#xA;&#xD;&#xA;Note that, in my implementation, cell $i$,$j$ in the liquid grid corresponds to row $i + $gridWidth$ * j$ in the matrix.&#xD;&#xA;&#xD;&#xA;The paper mentions, &quot;Static object and empty cells don’t disrupt this&#xD;&#xA;structure. In that case pressure and velocity terms can disappear&#xD;&#xA;from both sides&quot;, so I delete the columns and rows for cells that have no liquid.&#xD;&#xA;&#xD;&#xA;So my question is: Why is my matrix singular? Am I missing some kind of boundary condition in some other place in the paper? Is it the fact that my implementation is 2D?&#xD;&#xA;&#xD;&#xA;Here is an example matrix from my implementation for a 2x2 grid where the cell at 0,0 has no liquid:&#xD;&#xA;&#xD;&#xA;    -1   0   1&#xD;&#xA;&#xD;&#xA;     0  -1   1&#xD;&#xA;&#xD;&#xA;     1   1  -2" ContentLicense="CC BY-SA 3.0" />
  <row Id="4791" PostHistoryTypeId="1" PostId="2131" RevisionGUID="b13506f5-e755-48a0-afe1-ef1bf64951ab" CreationDate="2016-03-02T22:58:02.173" UserId="2786" Text="Conserving Mass in Liquid Simulation" ContentLicense="CC BY-SA 3.0" />
  <row Id="4792" PostHistoryTypeId="3" PostId="2131" RevisionGUID="b13506f5-e755-48a0-afe1-ef1bf64951ab" CreationDate="2016-03-02T22:58:02.173" UserId="2786" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4793" PostHistoryTypeId="6" PostId="2131" RevisionGUID="76180b5e-2cfb-4d7a-9f27-55794c2d7168" CreationDate="2016-03-02T23:14:05.473" UserId="2786" Comment="edited tags" Text="|simulation|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4794" PostHistoryTypeId="5" PostId="2131" RevisionGUID="75c3b2c6-b981-46d7-8ac5-7fef51d523c6" CreationDate="2016-03-02T23:19:16.500" UserId="2786" Comment="added 2 characters in body" Text="I am trying to implement a 2D version of Foster and Fedkiw's paper, &quot;Practical Animation of Liquids&quot; here: http://physbam.stanford.edu/~fedkiw/papers/stanford2001-02.pdf&#xD;&#xA;&#xD;&#xA;Mostly everything works, except for section 8: &quot;Conservation of Mass.&quot; There, we set up a matrix of equations to compute the pressures needed to make the liquid divergent free. &#xD;&#xA;&#xD;&#xA;I believe my code matches the paper, however I am getting an unsolvable matrix during the conservation of mass step.&#xD;&#xA;&#xD;&#xA;Here are my steps for generating the matrix A:&#xD;&#xA;&#xD;&#xA; 1. Set the diagonal entries $A_{i,i}$ to the negative of number of adjacent liquid cells to cell i.&#xD;&#xA; 2. Set the entries $A_{i,j}$ and $A_{j,i}$ to 1 if both cells i and j have liquid.&#xD;&#xA;&#xD;&#xA;Note that, in my implementation, cell $i$,$j$ in the liquid grid corresponds to row $i + $gridWidth$ * j$ in the matrix.&#xD;&#xA;&#xD;&#xA;The paper mentions, &quot;Static object and empty cells don’t disrupt this&#xD;&#xA;structure. In that case pressure and velocity terms can disappear&#xD;&#xA;from both sides&quot;, so I delete the columns and rows for cells that have no liquid.&#xD;&#xA;&#xD;&#xA;So my question is: Why is my matrix singular? Am I missing some kind of boundary condition in some other place in the paper? Is it the fact that my implementation is 2D?&#xD;&#xA;&#xD;&#xA;Here is an example matrix from my implementation for a 2x2 grid where the cell at 0,0 has no liquid:&#xD;&#xA;&#xD;&#xA;    -1   0   1&#xD;&#xA;&#xD;&#xA;     0  -1   1&#xD;&#xA;&#xD;&#xA;     1   1  -2" ContentLicense="CC BY-SA 3.0" />
  <row Id="4795" PostHistoryTypeId="2" PostId="2132" RevisionGUID="4844a0de-d5ff-4506-9b17-0fcdfc44afdd" CreationDate="2016-03-03T04:59:18.810" UserId="48" Text="There is a great paper from 2006 on this topic, [Filter Importance Sampling](http://lgdv.cs.fau.de/publications/publication/Pub.2006.tech.IMMD.IMMD9.filter/). They propose your method 2, study the properties, and come out generally in favor of it. They claim that this method gives smoother rendering results because it weights all samples that contribute to a pixel equally, thereby reducing variance in the final pixel values. This makes some sense, as it's a general maxim in Monte Carlo rendering that importance-sampling will give lower variance than weighted samples.&#xD;&#xA;&#xD;&#xA;Method 2 also has the advantage of being slightly easier to parallelize because each pixel's computations are independent of all other pixels, while in method 1, sample results are shared across neighboring pixels (and therefore have to be synchronized/communicated somehow when pixels are parallelized across multiple processors). For the same reason, it's easier to do adaptive sampling (more samples in high-variance areas of the image) with method 2 than method 1.&#xD;&#xA;&#xD;&#xA;In the paper, they also experimented with a Mitchell filter, sampling from abs() of the filter and then weighting each sample with either +1 or &amp;minus;1, like @trichoplax suggested. But this ended up actually increasing the variance and being worse than method 1, so they conclude that method 2 is only usable for positive filters.&#xD;&#xA;&#xD;&#xA;That being said, the results from this paper may not be universally applicable, and it may be somewhat scene-dependent which sampling method is better. I wrote [a blog post investigating this question](http://www.reedbeta.com/blog/2014/11/15/antialiasing-to-splat-or-not/) independently in 2014, using a synthetic &quot;image function&quot; rather than full rendering, and found method 1 to give more visually pleasing results due to smoothing high-contrast edges more nicely. Benedikt Bitterli also commented on that post reporting a similar issue with his renderer (excess high-frequency noise around light sources when using method 2). Beyond that, I found the main difference between the methods was the frequency of the resulting noise: method 2 gives higher-frequency, &quot;pixel-sized&quot; noise, while method 1 gives noise &quot;grains&quot; that are 2-3 pixels across, but the amplitude of noise was similar for both, so which kind of noise looks less bad is probably a matter of personal preference." ContentLicense="CC BY-SA 3.0" />
  <row Id="4796" PostHistoryTypeId="2" PostId="2133" RevisionGUID="c84eaad9-6f3b-44b7-bf7a-0672f008fa55" CreationDate="2016-03-03T09:54:09.387" UserId="1937" Text="I'm aware that most modern GPUs, although designed for floating point, are more or less equivalent in integer performance these days, with a few caveats like the lack of a fused multiply add. I'm not sure how this applies to shift operations though. I'm doing Marching Cubes on GPU, initially writing out a 32-bit packed position for each surface cube then unpacking these in a later pass to the actual vertices in that cube, like this : &#xD;&#xA;    &#xD;&#xA;    ivec3 unpackedPos = ivec3( packedPos &gt;&gt; 20 &amp; 0x3FF,&#xD;&#xA;                             packedPos &gt;&gt; 10 &amp; 0x3FF,&#xD;&#xA;                             packedPos &amp; 0x3FF);&#xD;&#xA;&#xD;&#xA;It just occurred to me to wonder if shader units have barrel shifters in them these days? Am I doing 2 shifts here or 30?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4797" PostHistoryTypeId="1" PostId="2133" RevisionGUID="c84eaad9-6f3b-44b7-bf7a-0672f008fa55" CreationDate="2016-03-03T09:54:09.387" UserId="1937" Text="Do modern GPUs contain barrel shifters?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4798" PostHistoryTypeId="3" PostId="2133" RevisionGUID="c84eaad9-6f3b-44b7-bf7a-0672f008fa55" CreationDate="2016-03-03T09:54:09.387" UserId="1937" Text="|gpu|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4800" PostHistoryTypeId="2" PostId="2134" RevisionGUID="84f25796-f0b1-4554-a4c6-5063e680dfbc" CreationDate="2016-03-03T11:11:21.640" UserId="2788" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I use template matching to detect a specific pattern in image.The shift determined is very shaky. Currently I apply it to R,G,B channel separately and average the result to obtain float values.Please, suggest how to obtain subpixel accuracy. I was planning to resize the image and then return the data in original scale, please suggest any other better method &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I60wq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4801" PostHistoryTypeId="1" PostId="2134" RevisionGUID="84f25796-f0b1-4554-a4c6-5063e680dfbc" CreationDate="2016-03-03T11:11:21.640" UserId="2788" Text="Template matching subpixel accuracy" ContentLicense="CC BY-SA 3.0" />
  <row Id="4802" PostHistoryTypeId="3" PostId="2134" RevisionGUID="84f25796-f0b1-4554-a4c6-5063e680dfbc" CreationDate="2016-03-03T11:11:21.640" UserId="2788" Text="|algorithm|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4803" PostHistoryTypeId="2" PostId="2135" RevisionGUID="18af47bd-dc48-43e8-ac57-6d3c34c9d7d5" CreationDate="2016-03-03T11:18:33.500" UserId="2789" Text="I want to visualize a scene with simple shapes (e.g. boxes, pyramides, etc.) and I am looking for a tool or framework in C/C++ to do this. Focus of the application is to parameterize the relative coordinates (position+rotation) of the scene objects. Also defined camera view support would be much welcomed. What I actually would want is the VRML World Editor from Simulink. However I need something thats free for company in-house use. &#xD;&#xA;&#xD;&#xA;Could anybody give suggest me something suitable? " ContentLicense="CC BY-SA 3.0" />
  <row Id="4804" PostHistoryTypeId="1" PostId="2135" RevisionGUID="18af47bd-dc48-43e8-ac57-6d3c34c9d7d5" CreationDate="2016-03-03T11:18:33.500" UserId="2789" Text="Free 3D Scene Simulation Framework" ContentLicense="CC BY-SA 3.0" />
  <row Id="4805" PostHistoryTypeId="3" PostId="2135" RevisionGUID="18af47bd-dc48-43e8-ac57-6d3c34c9d7d5" CreationDate="2016-03-03T11:18:33.500" UserId="2789" Text="|3d|c++|virtual-reality|scene-description|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4806" PostHistoryTypeId="2" PostId="2136" RevisionGUID="dd1398f2-2b36-4901-a138-cbd9d6476132" CreationDate="2016-03-03T11:41:25.397" UserId="231" Text="It is not generally useful to try to optimise small parts of a program before you have profiled the program to see where the most benefit can be gained by optimisation. Make sure everything is correct and working first, and then profile to decide where to optimise (if optimisation turns out to be necessary).&#xD;&#xA;&#xD;&#xA;Mathematically, your approach is already correct for all lines. It will correctly identify all lines parallel to either axis, and it will not incorrectly identify any lines that are not parallel to an axis. However, for use in a practical setting, it's worth asking yourself about near-parallel cases and any odd exceptions. Consider all this before even thinking about optimisation, otherwise you may have to repeat all the optimisation later if something you have to change for correctness breaks your initial optimisation.&#xD;&#xA;&#xD;&#xA;One case to consider is when both the coordinates are identical. That is, the end points have the same x coordinate *and* the same y coordinate. This is a  degenerate case that doesn't define a line (it could have any direction). Check your implementation with this case and make sure it gives the output that you want it to.&#xD;&#xA;&#xD;&#xA;Depending on your purpose, you may want to detect only exactly parallel lines, or you may want to detect lines that are sufficiently near to parallel. In some cases lines near to parallel may satisfy your purpose, and in other cases it may be essential to accept lines near to parallel, if for example there is the possibility of small inaccuracies in the coordinates." ContentLicense="CC BY-SA 3.0" />
  <row Id="4807" PostHistoryTypeId="2" PostId="2137" RevisionGUID="9506addb-3029-4457-a100-9f199e5d4cbb" CreationDate="2016-03-03T11:43:44.337" UserId="304" Text="I'm wondering what is the best way to achieve an effect like here: https://matterport.com/try/ when the camera is traveling between points in space.&#xD;&#xA;&#xD;&#xA;Apart from simple color crossfade there seems to be some sort of perspective reprojection giving the illusion of movement.&#xD;&#xA;&#xD;&#xA;Any idea how to do this? All data I have is environment cube maps with color + linear depth at each pixel (so I can reconstruct view space position)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4808" PostHistoryTypeId="1" PostId="2137" RevisionGUID="9506addb-3029-4457-a100-9f199e5d4cbb" CreationDate="2016-03-03T11:43:44.337" UserId="304" Text="Seamlessly transitioning between nearby environment maps" ContentLicense="CC BY-SA 3.0" />
  <row Id="4809" PostHistoryTypeId="3" PostId="2137" RevisionGUID="9506addb-3029-4457-a100-9f199e5d4cbb" CreationDate="2016-03-03T11:43:44.337" UserId="304" Text="|opengl|shader|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4811" PostHistoryTypeId="2" PostId="2138" RevisionGUID="d35a3119-e26a-4d7e-9465-81c697cc0822" CreationDate="2016-03-03T18:41:14.743" UserId="48" Text="It looks to me like they have a coarse polygon model of the room, and texture the model by projecting the cubemaps onto it. The model seems to include the rough shapes of the walls and furniture, but not fine details such as table legs, door handles or items on shelves. When the camera moves, the geometry gives you more-or-less-correct parallax, and the crossfade between cubemaps updates the textures.&#xD;&#xA;&#xD;&#xA;You can also see the model clearly when the walkthrough first loads. Note that the camera starts outside of the house, letting you see the whole thing (much as you'd see a game level if you noclip the camera outside it), then it moves the camera into the living room. You can also get back to this view by selecting &quot;Dollhouse&quot; in their toolbar.&#xD;&#xA;&#xD;&#xA;Their model may have been constructed by an artist, but in your case if you have depth information in the cubemaps, it's probably possible to programmatically extract some geometry from them and stitch the cubemaps together to form a coherent model. I don't know much about that subject, though." ContentLicense="CC BY-SA 3.0" />
  <row Id="4812" PostHistoryTypeId="5" PostId="2131" RevisionGUID="c86f7bd3-5abd-4250-ba9c-aeda0845d145" CreationDate="2016-03-03T19:48:36.173" UserId="2786" Comment="Added code for generating the matrix." Text="I am trying to implement a 2D version of Foster and Fedkiw's paper, &quot;Practical Animation of Liquids&quot; here: http://physbam.stanford.edu/~fedkiw/papers/stanford2001-02.pdf&#xD;&#xA;&#xD;&#xA;Mostly everything works, except for section 8: &quot;Conservation of Mass.&quot; There, we set up a matrix of equations to compute the pressures needed to make the liquid divergent free. &#xD;&#xA;&#xD;&#xA;I believe my code matches the paper, however I am getting an unsolvable matrix during the conservation of mass step.&#xD;&#xA;&#xD;&#xA;Here are my steps for generating the matrix A:&#xD;&#xA;&#xD;&#xA; 1. Set the diagonal entries $A_{i,i}$ to the negative of number of adjacent liquid cells to cell i.&#xD;&#xA; 2. Set the entries $A_{i,j}$ and $A_{j,i}$ to 1 if both cells i and j have liquid.&#xD;&#xA;&#xD;&#xA;Note that, in my implementation, cell $i$,$j$ in the liquid grid corresponds to row $i + $gridWidth$ * j$ in the matrix.&#xD;&#xA;&#xD;&#xA;The paper mentions, &quot;Static object and empty cells don’t disrupt this&#xD;&#xA;structure. In that case pressure and velocity terms can disappear&#xD;&#xA;from both sides&quot;, so I delete the columns and rows for cells that have no liquid.&#xD;&#xA;&#xD;&#xA;So my question is: Why is my matrix singular? Am I missing some kind of boundary condition in some other place in the paper? Is it the fact that my implementation is 2D?&#xD;&#xA;&#xD;&#xA;Here is an example matrix from my implementation for a 2x2 grid where the cell at 0,0 has no liquid:&#xD;&#xA;&#xD;&#xA;    -1   0   1&#xD;&#xA;&#xD;&#xA;     0  -1   1&#xD;&#xA;&#xD;&#xA;     1   1  -2&#xD;&#xA;&#xD;&#xA;Here is the code I use to generate the matrix. Note that, instead of explicitly deleting columns and rows, I generate and use a map from liquid cell indices to the final matrix columns/rows.&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; cells.length; i++) {&#xD;&#xA;      for (int j = 0; j &lt; cells[i].length; j++) {&#xD;&#xA;        FluidGridCell cell = cells[i][j];&#xD;&#xA;        &#xD;&#xA;        if (!cell.hasLiquid)&#xD;&#xA;          continue;&#xD;&#xA;        &#xD;&#xA;        // get indices for the grid and matrix&#xD;&#xA;        int gridIndex = i + cells.length * j;&#xD;&#xA;        int matrixIndex = gridIndexToMatrixIndex.get((Integer)gridIndex);&#xD;&#xA;        &#xD;&#xA;        // count the number of adjacent liquid cells&#xD;&#xA;        int adjacentLiquidCellCount = 0;&#xD;&#xA;        if (i != 0) {&#xD;&#xA;          if (cells[i-1][j].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (i != cells.length-1) {&#xD;&#xA;          if (cells[i+1][j].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (j != 0) {&#xD;&#xA;          if (cells[i][j-1].hasLiquid)&#xD;&#xA;          adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (j != cells[0].length-1) {&#xD;&#xA;          if (cells[i][j+1].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        // the diagonal entries are the negative count of liquid cells&#xD;&#xA;        liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                              matrixIndex, // row&#xD;&#xA;                              -adjacentLiquidCellCount); // value&#xD;&#xA;                                &#xD;&#xA;        // set off-diagonal values of the pressure matrix&#xD;&#xA;        if (cell.hasLiquid) {&#xD;&#xA;          if (i != 0) {&#xD;&#xA;            if (cells[i-1][j].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = (i-1) + j * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (i != cells.length-1) {&#xD;&#xA;            if (cells[i+1][j].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = (i+1) + j * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (j != 0) {&#xD;&#xA;            if (cells[i][j-1].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = i + (j-1) * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (j != cells[0].length-1) {&#xD;&#xA;            if (cells[i][j+1].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = i + (j+1) * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }" ContentLicense="CC BY-SA 3.0" />
  <row Id="4816" PostHistoryTypeId="2" PostId="2139" RevisionGUID="e2b859b7-62c1-438b-80cf-74fc67d96715" CreationDate="2016-03-04T08:49:24.877" UserId="2792" Text="I'm using an affine transformation matrix to transform 2D coordinates from screen (magnitude 10e3) to small parts of fractal sets (magnitude up to 10e-15).&#xD;&#xA;&#xD;&#xA;I also need to map the other way round, so I simply inverse the matrix. It works when the magnitudes are not too far appart, but it fails when the determinant gets too close to zero to be represented with standard double numbers.&#xD;&#xA;&#xD;&#xA;Is there an alternate way of inverting the matrix? I'm not very good at mathematics, so I would need a simple solution, and one I could find the code, or an algorithm, for.&#xD;&#xA;&#xD;&#xA;An example of such a matrix:&#xD;&#xA;&#xD;&#xA;    5.654271853456468e-9    -3.2644953766644154e-9   0&#xD;&#xA;    -3.2644953766644154e-9  -5.654271853456468e-9    0&#xD;&#xA;    -0.5849384772706666     0.6620492500825931       1&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="4817" PostHistoryTypeId="1" PostId="2139" RevisionGUID="e2b859b7-62c1-438b-80cf-74fc67d96715" CreationDate="2016-03-04T08:49:24.877" UserId="2792" Text="How to invert an affine matrix with small values?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4818" PostHistoryTypeId="3" PostId="2139" RevisionGUID="e2b859b7-62c1-438b-80cf-74fc67d96715" CreationDate="2016-03-04T08:49:24.877" UserId="2792" Text="|transformations|mathematics|2d|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4819" PostHistoryTypeId="5" PostId="2139" RevisionGUID="17abc4a9-cb56-433a-81d0-720edc0c0f49" CreationDate="2016-03-04T09:23:28.067" UserId="2792" Comment="better example matrix" Text="I'm using an affine transformation matrix to transform 2D coordinates from screen (magnitude 10e3) to small parts of fractal sets (magnitude up to 10e-15).&#xD;&#xA;&#xD;&#xA;I also need to map the other way round, so I simply inverse the matrix. It works when the magnitudes are not too far appart, but it fails when the determinant gets too close to zero to be represented with standard double numbers.&#xD;&#xA;&#xD;&#xA;Is there an alternate way of inverting the matrix? I'm not very good at mathematics, so I would need a simple solution, and one I could find the code, or an algorithm, for.&#xD;&#xA;&#xD;&#xA;An example of such a matrix:&#xD;&#xA;&#xD;&#xA;     3.26091378894248e-9   -1.882689453850103e-9   -0.7172216437740687&#xD;&#xA;    -1.882689453814925e-9  -3.2609137888815494e-9  -0.23371832131832268&#xD;&#xA;     0                      0                       1&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="4820" PostHistoryTypeId="2" PostId="2140" RevisionGUID="2f1a0570-2f50-4350-9d96-5a946c979f8e" CreationDate="2016-03-04T11:53:48.777" UserId="2712" Text="I believe that the issue may already have been discussed here. I want to find if two line segments does intersect and if they do then find and store and intesection points. Now it is already confirmed that one of the line segments will always be parallel to x-axis or y-axis. &#xD;&#xA;So in that case how should we reformulate the basic algorithm that checks the line segments intersection ? &#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4821" PostHistoryTypeId="1" PostId="2140" RevisionGUID="2f1a0570-2f50-4350-9d96-5a946c979f8e" CreationDate="2016-03-04T11:53:48.777" UserId="2712" Text="intersection between line segments - narrowed precondition" ContentLicense="CC BY-SA 3.0" />
  <row Id="4822" PostHistoryTypeId="3" PostId="2140" RevisionGUID="2f1a0570-2f50-4350-9d96-5a946c979f8e" CreationDate="2016-03-04T11:53:48.777" UserId="2712" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4823" PostHistoryTypeId="6" PostId="2140" RevisionGUID="ae98aeff-fe92-44e9-801e-4494c7dd6927" CreationDate="2016-03-04T12:39:24.380" UserId="16" Comment="edited tags" Text="|geometry|mathematics|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4824" PostHistoryTypeId="5" PostId="2140" RevisionGUID="ae98aeff-fe92-44e9-801e-4494c7dd6927" CreationDate="2016-03-04T12:39:24.380" UserId="16" Comment="edited tags" Text="I believe that the issue may already have been discussed here. I want to find if two line segments does intersect and if they do then find and store and intesection points. Now it is already confirmed that one of the line segments will always be parallel to x-axis or y-axis. &#xD;&#xA;So in that case how should we reformulate the basic algorithm that checks the line segments intersection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4826" PostHistoryTypeId="2" PostId="2141" RevisionGUID="a3ff49ae-e3fd-4560-b977-7107bf17ffa4" CreationDate="2016-03-04T16:28:17.557" UserId="137" Text="The arbitrary line can be expressed as `y = a*x+b` (assuming it's not parallel to the y axis). &#xD;&#xA;&#xD;&#xA;If the other line is parallel to the y axis then you can simply fill in the x coordinate of any point on the line into the formula of the first line. Then you can check whether they intersect by ensuring the result lies between the endpoints of the second line.&#xD;&#xA;&#xD;&#xA;For the second line parallel to the x axis you just flip the x and y coordinates." ContentLicense="CC BY-SA 3.0" />
  <row Id="4827" PostHistoryTypeId="5" PostId="2117" RevisionGUID="5899366f-f923-4ee7-9f79-7d13221e1e5d" CreationDate="2016-03-04T17:15:19.837" UserId="2775" Comment="Added explanation of how I implemented the solution and example pictures." Text="I've been stuck on how to approach this for a while, so any suggestions would be gratefully appreciated!&#xD;&#xA;&#xD;&#xA;I want to map a texture in the form of a lower right euclidean triangle to a hyperbolic triangle on the Poincare Disk.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the texture (the top left triangle of the texture is transparent and unused). You might recognise this as part of Escher's Circle Limit I&#xD;&#xA;&#xD;&#xA;Sorry, see the comment as I am not allowed to post more than two links it seems! &#xD;&#xA;&#xD;&#xA;And this is what my polygon looks like (it's centred at the origin, which means that two edges are straight lines, however in general all three edges will be circular arcs):&#xD;&#xA;&#xD;&#xA;[![Wireframe Polygon][1]][1]&#xD;&#xA;&#xD;&#xA;The centre of the polygon is the incentre of the euclidean triangle formed by its vertices and I'm UV mapping the texture using it's incentre, dividing it into the same number of faces as the polygon has and mapping each face onto the corresponding polygon face. However the the result looks like this:&#xD;&#xA;&#xD;&#xA;[![Textured Polygon][2]][2]&#xD;&#xA;&#xD;&#xA;If anybody thinks this is solvable using UV mapping I'd be happy to provide some example code, however I'm beginning to think this might not be possible and I'll have to write my own mapping functions.&#xD;&#xA;&#xD;&#xA;SOLVED with some refinement of @Nathan's answer below since the lines AB, AC, BC may actually be arcs not lines. &#xD;&#xA;&#xD;&#xA;Method: pick the longest side, say BC, then subdivide this into an even number of parts. Subdivide the other two side into the same number of parts. Then the lines connecting these (DE in the answer below) must actually also be arcs, not straight lines. Subdivide these new arcs as required, add the new triangles as faces then UV map the lower right triangle of the texture to these new faces. &#xD;&#xA;&#xD;&#xA;Simple? Not at all. But it worked. &#xD;&#xA;[![Fish 1][3]][3]&#xD;&#xA;[![Fish 2][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1QB1E.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3Jw9I.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/90UQF.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/bJ08M.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4828" PostHistoryTypeId="5" PostId="2131" RevisionGUID="1ed65718-d184-4e8b-b9ee-51070d44113a" CreationDate="2016-03-04T18:02:17.307" UserId="2786" Comment="added more information I discovered from researching" Text="I am trying to implement a 2D version of Foster and Fedkiw's paper, &quot;Practical Animation of Liquids&quot; here: http://physbam.stanford.edu/~fedkiw/papers/stanford2001-02.pdf&#xD;&#xA;&#xD;&#xA;Mostly everything works, except for section 8: &quot;Conservation of Mass.&quot; There, we set up a matrix of equations to compute the pressures needed to make the liquid divergent free. &#xD;&#xA;&#xD;&#xA;I believe my code matches the paper, however I am getting an unsolvable matrix during the conservation of mass step.&#xD;&#xA;&#xD;&#xA;Here are my steps for generating the matrix A:&#xD;&#xA;&#xD;&#xA; 1. Set the diagonal entries $A_{i,i}$ to the negative of number of adjacent liquid cells to cell i.&#xD;&#xA; 2. Set the entries $A_{i,j}$ and $A_{j,i}$ to 1 if both cells i and j have liquid.&#xD;&#xA;&#xD;&#xA;Note that, in my implementation, cell $i$,$j$ in the liquid grid corresponds to row $i + $gridWidth$ * j$ in the matrix.&#xD;&#xA;&#xD;&#xA;The paper mentions, &quot;Static object and empty cells don’t disrupt this&#xD;&#xA;structure. In that case pressure and velocity terms can disappear&#xD;&#xA;from both sides&quot;, so I delete the columns and rows for cells that have no liquid.&#xD;&#xA;&#xD;&#xA;So my question is: Why is my matrix singular? Am I missing some kind of boundary condition in some other place in the paper? Is it the fact that my implementation is 2D?&#xD;&#xA;&#xD;&#xA;Here is an example matrix from my implementation for a 2x2 grid where the cell at 0,0 has no liquid:&#xD;&#xA;&#xD;&#xA;    -1   0   1&#xD;&#xA;&#xD;&#xA;     0  -1   1&#xD;&#xA;&#xD;&#xA;     1   1  -2&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;My research has led me to believe that I'm not properly handling the boundary conditions.&#xD;&#xA;&#xD;&#xA;First of all, at this point I can say that my matrix represents the discrete pressure Poisson equation. It is the discrete analog of applying the Laplacian operator coupling local pressure changes to cell divergence.&#xD;&#xA;&#xD;&#xA;As far as I can understand, since we're dealing with pressure differences, boundary conditions are needed to &quot;anchor&quot; the pressures to an absolute reference value. Otherwise there may be an infinite number of solutions to the set of equations.&#xD;&#xA;&#xD;&#xA;In [these notes][1], 3 different ways are given to apply boundary conditions, to the best of my understanding:&#xD;&#xA;&#xD;&#xA; 1. Dirichlet - specifies absolute values at the boundaries.&#xD;&#xA;&#xD;&#xA; 2. Neummann - specifies the derivative at the boundaries.&#xD;&#xA;&#xD;&#xA; 3. Robin - specifies some kind of linear combination of the absolute value and the derivative at the boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Foster and Fedki's paper does not mention any of these, but I believe that they enforce Dirichlet boundary conditions, notable because of this statement at the end of 7.1.2, &quot;The pressure in a surface cell is set to atmospheric pressure.&quot;&#xD;&#xA;&#xD;&#xA;I've read the notes I linked a few times and still don't quite understand the math going on. How exactly do we enforce these boundary conditions? Looking at other implementations, there seems to be some kind of notion of a &quot;Ghost&quot; cells that lie at the boundary. &#xD;&#xA;&#xD;&#xA;Here I've linked to a few sources that may be helpful to others reading this.&#xD;&#xA;&#xD;&#xA;[Notes on boundary conditions for Poisson Matrices][1]&#xD;&#xA;&#xD;&#xA;[Computational Science StackExchange post on Neumann boundary conditions][2]&#xD;&#xA;&#xD;&#xA;[Computational Science StackExchange post on Poisson Solver][3]&#xD;&#xA;&#xD;&#xA;[Water Physbam Implementation][4]&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the code I use to generate the matrix. Note that, instead of explicitly deleting columns and rows, I generate and use a map from liquid cell indices to the final matrix columns/rows.&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; cells.length; i++) {&#xD;&#xA;      for (int j = 0; j &lt; cells[i].length; j++) {&#xD;&#xA;        FluidGridCell cell = cells[i][j];&#xD;&#xA;        &#xD;&#xA;        if (!cell.hasLiquid)&#xD;&#xA;          continue;&#xD;&#xA;        &#xD;&#xA;        // get indices for the grid and matrix&#xD;&#xA;        int gridIndex = i + cells.length * j;&#xD;&#xA;        int matrixIndex = gridIndexToMatrixIndex.get((Integer)gridIndex);&#xD;&#xA;        &#xD;&#xA;        // count the number of adjacent liquid cells&#xD;&#xA;        int adjacentLiquidCellCount = 0;&#xD;&#xA;        if (i != 0) {&#xD;&#xA;          if (cells[i-1][j].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (i != cells.length-1) {&#xD;&#xA;          if (cells[i+1][j].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (j != 0) {&#xD;&#xA;          if (cells[i][j-1].hasLiquid)&#xD;&#xA;          adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (j != cells[0].length-1) {&#xD;&#xA;          if (cells[i][j+1].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        // the diagonal entries are the negative count of liquid cells&#xD;&#xA;        liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                              matrixIndex, // row&#xD;&#xA;                              -adjacentLiquidCellCount); // value&#xD;&#xA;                                &#xD;&#xA;        // set off-diagonal values of the pressure matrix&#xD;&#xA;        if (cell.hasLiquid) {&#xD;&#xA;          if (i != 0) {&#xD;&#xA;            if (cells[i-1][j].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = (i-1) + j * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (i != cells.length-1) {&#xD;&#xA;            if (cells[i+1][j].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = (i+1) + j * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (j != 0) {&#xD;&#xA;            if (cells[i][j-1].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = i + (j-1) * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (j != cells[0].length-1) {&#xD;&#xA;            if (cells[i][j+1].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = i + (j+1) * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.math.toronto.edu/mpugh/Teaching/Mat1062/notes2.pdf&#xD;&#xA;  [2]: http://scicomp.stackexchange.com/questions/5355/writing-the-poisson-equation-finite-difference-matrix-with-neumann-boundary-cond&#xD;&#xA;  [3]: http://scicomp.stackexchange.com/questions/19485/2d-poisson-solver-for-taylor-green-vortex-problem&#xD;&#xA;  [4]: http://physbam.stanford.edu/~mlentine/project.html#water" ContentLicense="CC BY-SA 3.0" />
  <row Id="4829" PostHistoryTypeId="2" PostId="2142" RevisionGUID="73cffbcb-eea6-412c-9c7d-50fe15c15e22" CreationDate="2016-03-04T20:43:42.453" UserId="1810" Text="Yes, with 50% of FMA 32b throughput (on nVIDIA Maxwell).&#xD;&#xA;&#xD;&#xA;See &#xD;&#xA;https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#arithmetic-instructions&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="4830" PostHistoryTypeId="5" PostId="2142" RevisionGUID="3046d57d-0074-461c-90e7-edd0dc0a55e3" CreationDate="2016-03-04T21:03:29.910" UserId="1810" Comment="added 4 characters in body" Text="Yes ( with 50% of the FMA 32b throughput on nVIDIA Maxwell).&#xD;&#xA;&#xD;&#xA;See &#xD;&#xA;https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#arithmetic-instructions&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="4831" PostHistoryTypeId="2" PostId="2143" RevisionGUID="c663fffb-5a1c-48ef-b1ee-24b8e61885d8" CreationDate="2016-03-04T21:10:52.300" UserId="2792" Text="I found a solution to my specific problem. Instead of computing the determinant and hitting the precision wall, I use the Gauss-Jordan method step by step.&#xD;&#xA;&#xD;&#xA;In my specific case of affine transformation matrices and the range of values I use, I don't hit any precision problem this way.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4832" PostHistoryTypeId="5" PostId="2139" RevisionGUID="f91aa2d6-6448-4c9b-916b-30de9581df89" CreationDate="2016-03-04T21:11:29.597" UserId="2792" Comment="More details" Text="I'm using an affine transformation matrix to transform 2D coordinates from screen (magnitude 10e3) to small parts of fractal sets (magnitude up to 10e-15).&#xD;&#xA;&#xD;&#xA;I also need to map the other way round, so I simply inverse the matrix. It works when the magnitudes are not too far appart, but it fails when the determinant gets too close to zero to be represented with standard double numbers.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The matrix I use are of the form:&#xD;&#xA;&#xD;&#xA;    a c e&#xD;&#xA;    b d f&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;And the inversion algorithm I have is:&#xD;&#xA;&#xD;&#xA;    var dt = a * d - b * c;&#xD;&#xA;    return new Matrix(d/dt, -b/dt, -c/dt, a/dt, (c * f - d * e) / dt, -(a * f - b * e) / dt);&#xD;&#xA;Is there an alternate way of inverting the matrix? I'm not very good at mathematics, so I would need a simple solution, and one I could find the code, or an algorithm, for.&#xD;&#xA;&#xD;&#xA;An example of such a matrix:&#xD;&#xA;&#xD;&#xA;     3.26091378894248e-9   -1.882689453850103e-9   -0.7172216437740687&#xD;&#xA;    -1.882689453814925e-9  -3.2609137888815494e-9  -0.23371832131832268&#xD;&#xA;     0                      0                       1&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4833" PostHistoryTypeId="2" PostId="2144" RevisionGUID="e1eb413a-6f01-464a-bbc8-63f7bc5f9aad" CreationDate="2016-03-04T21:23:22.713" UserId="1810" Text="the arbitrary line can be represented as $P = (x,y) = P_0 + \lambda. \vec{dir}$ (works in n dimensions, no special case).&#xD;&#xA;If your other line is $x=x_1$ simply inject this in to solve for $\lambda$ and get $y$: $y=y_0+(x_1-x_0).\frac{{dir}_y}{{dir}_x}$." ContentLicense="CC BY-SA 3.0" />
  <row Id="4834" PostHistoryTypeId="5" PostId="2139" RevisionGUID="6867df32-397f-4286-ac4d-435d9d5f7def" CreationDate="2016-03-05T08:29:31.863" UserId="231" Comment="Minor tidying" Text="I'm using an affine transformation matrix to transform 2D coordinates from screen (magnitude 10e3) to small parts of fractal sets (magnitude as little as 10e-15).&#xD;&#xA;&#xD;&#xA;I also need to map the other way round, so I simply invert the matrix. It works when the magnitudes are not too far apart, but it fails when the determinant gets too close to zero to be represented with standard double numbers.&#xD;&#xA;&#xD;&#xA;The matrices I use are of the form:&#xD;&#xA;&#xD;&#xA;    a c e&#xD;&#xA;    b d f&#xD;&#xA;    0 0 1&#xD;&#xA;&#xD;&#xA;And the inversion algorithm I have is:&#xD;&#xA;&#xD;&#xA;    var dt = a * d - b * c;&#xD;&#xA;    return new Matrix(d/dt, -b/dt, -c/dt, a/dt, (c * f - d * e) / dt, -(a * f - b * e) / dt);&#xD;&#xA;&#xD;&#xA;Is there an alternate way of inverting the matrix? I'm not very good at mathematics, so I would need a simple solution, and one I could find the code, or an algorithm, for.&#xD;&#xA;&#xD;&#xA;An example of such a matrix:&#xD;&#xA;&#xD;&#xA;     3.26091378894248e-9   -1.882689453850103e-9   -0.7172216437740687&#xD;&#xA;    -1.882689453814925e-9  -3.2609137888815494e-9  -0.23371832131832268&#xD;&#xA;     0                      0                       1&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4838" PostHistoryTypeId="2" PostId="2146" RevisionGUID="23b942cc-5922-4ddc-98f1-8be3d723215f" CreationDate="2016-03-06T11:51:59.727" UserId="2190" Text="Problem Description:&#xD;&#xA;&#xD;&#xA; - Reference:  &#xD;&#xA;   Original paper[http://www.terathon.com/lengyel/Lengyel-Oblique.pdf]&#xD;&#xA;&#xD;&#xA;   &quot;Mathematics for 3D Game Programming and Computer Graphics&quot; 3rd edition, chapter 5.6.&#xD;&#xA; &#xD;&#xA; - M is the original projection matrix. &#xD;&#xA;&#xD;&#xA; - Point Q is one of the four bounding points in original view frustum's far plane, and it intersects with the modified far plane F. Q'=M*Q is the projected point by M.&#xD;&#xA;&#xD;&#xA; - Plane C is the modified near plane, and C'=transpose(inverse(M))*C is the projected plane by M.&#xD;&#xA;&#xD;&#xA; - So here is the question: why Q'=(Cx, Cy, 1, 1)?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4839" PostHistoryTypeId="1" PostId="2146" RevisionGUID="23b942cc-5922-4ddc-98f1-8be3d723215f" CreationDate="2016-03-06T11:51:59.727" UserId="2190" Text="A question about derivation in oblique view frustum" ContentLicense="CC BY-SA 3.0" />
  <row Id="4840" PostHistoryTypeId="3" PostId="2146" RevisionGUID="23b942cc-5922-4ddc-98f1-8be3d723215f" CreationDate="2016-03-06T11:51:59.727" UserId="2190" Text="|transformations|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4841" PostHistoryTypeId="5" PostId="2146" RevisionGUID="809d2f6b-9ad4-4879-8838-bedbbd678ded" CreationDate="2016-03-06T13:58:48.210" UserId="38" Comment="added 2 characters in body" Text="Problem Description:&#xD;&#xA;&#xD;&#xA; - Reference:  &#xD;&#xA;   [Oblique View Frustum Depth Projection and Clipping](http://www.terathon.com/lengyel/Lengyel-Oblique.pdf)&#xD;&#xA;&#xD;&#xA;   &quot;Mathematics for 3D Game Programming and Computer Graphics&quot; 3rd edition, chapter 5.6.&#xD;&#xA; &#xD;&#xA; - M is the original projection matrix. &#xD;&#xA;&#xD;&#xA; - Point Q is one of the four bounding points in original view frustum's far plane, and it intersects with the modified far plane F. Q'=M*Q is the projected point by M.&#xD;&#xA;&#xD;&#xA; - Plane C is the modified near plane, and C'=transpose(inverse(M))*C is the projected plane by M.&#xD;&#xA;&#xD;&#xA; - So here is the question: why Q'=(Cx, Cy, 1, 1)?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4842" PostHistoryTypeId="5" PostId="2146" RevisionGUID="f4ec5138-5673-4c1a-85df-202f6852d630" CreationDate="2016-03-07T02:58:54.323" UserId="2190" Comment="deleted 116 characters in body" Text="Problem Description:&#xD;&#xA;&#xD;&#xA; - Reference:  &#xD;&#xA;   [Oblique View Frustum Depth Projection and Clipping](http://www.terathon.com/lengyel/Lengyel-Oblique.pdf)&#xD;&#xA;&#xD;&#xA;   &quot;Mathematics for 3D Game Programming and Computer Graphics&quot; 3rd edition, chapter 5.6.&#xD;&#xA; &#xD;&#xA; - M is the original projection matrix. &#xD;&#xA;&#xD;&#xA; - Plane C is the modified near plane, and C'=transpose(inverse(M))*C is the projected plane by M.&#xD;&#xA;&#xD;&#xA; - Why in NDC the corner Q' of the view frustum lying opposite the plane C' is given by Q'=(Cx, Cy, 1, 1)?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4844" PostHistoryTypeId="2" PostId="2147" RevisionGUID="f23a49bb-35ca-4463-b340-d1056dc0517e" CreationDate="2016-03-07T07:52:07.727" UserId="2644" Text="So let's assume that i have some convex surface.&#xD;&#xA;I'm moving each point of it in a normal direction in this point by some constant factor (This factor is same for all points on surface).&#xD;&#xA;&#xD;&#xA;Can I replace this operation by Uniform or Non-uniform Scaling + Translate? &#xD;&#xA;&#xD;&#xA;Will resulting surfaces be mathematically identical in these cases?&#xD;&#xA;&#xD;&#xA;For example i want to transform this surface (side view).&#xD;&#xA;[![enter image description here][1]][1]?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JuAlC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4845" PostHistoryTypeId="1" PostId="2147" RevisionGUID="f23a49bb-35ca-4463-b340-d1056dc0517e" CreationDate="2016-03-07T07:52:07.727" UserId="2644" Text="Moving each point of a surface in direction of corresponding normal" ContentLicense="CC BY-SA 3.0" />
  <row Id="4846" PostHistoryTypeId="3" PostId="2147" RevisionGUID="f23a49bb-35ca-4463-b340-d1056dc0517e" CreationDate="2016-03-07T07:52:07.727" UserId="2644" Text="|transformations|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4847" PostHistoryTypeId="2" PostId="2148" RevisionGUID="02708ab7-10ac-45f3-ad44-89d2b2b7843d" CreationDate="2016-03-07T08:23:15.437" UserId="16" Text="No this cannot be modelled by (non-uniform) scaling. It's fairly easy to construct a counterexample:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Notice that along the horizontal axis, some distances are shrunk (between the outer straight parts) while others are expanded (between the inner straight parts).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XwK52.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4848" PostHistoryTypeId="12" PostId="2148" RevisionGUID="3047dc21-0d93-4ddc-bb3f-4a2b656e8cc8" CreationDate="2016-03-07T08:25:25.447" UserId="16" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="4849" PostHistoryTypeId="5" PostId="2148" RevisionGUID="941eac13-2535-4200-b67a-a21097eb0365" CreationDate="2016-03-07T08:28:55.653" UserId="16" Comment="added 78 characters in body" Text="No this cannot be modelled by (non-uniform) scaling. It's fairly easy to construct a counterexample:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The issue is that the amount a section of the curve grows depends on its curvature, not its orientation in space. Notice here that the circular arc grows (by a factor of $3/2$) whereas the length of the horizontal segments remains unchanged at a length of $2$.&#xD;&#xA;&#xD;&#xA;Of course, if your surface is not only convex but also has constant curvature, then it's just a circular arc, and for circles your transformation is equivalent to uniform scaling. You can probably also construct curves of varying curvature where your transformation happens to correspond to non-uniform scaling, but for general convex surfaces, that's not the case.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CWujH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4850" PostHistoryTypeId="13" PostId="2148" RevisionGUID="400db368-2e00-4c25-90d1-55bc3f2a2cdd" CreationDate="2016-03-07T08:28:57.763" UserId="16" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:16,&quot;DisplayName&quot;:&quot;Martin Büttner&quot;}]}" />
  <row Id="4851" PostHistoryTypeId="5" PostId="2147" RevisionGUID="8d195cd1-5a5a-43f3-92cf-90dde4a21246" CreationDate="2016-03-07T08:39:03.620" UserId="2644" Comment="added 20 characters in body" Text="So let's assume that i have some convex smooth and unclosed surface.&#xD;&#xA;I'm moving each point of it in a normal direction in this point by some constant factor (This factor is same for all points on surface).&#xD;&#xA;&#xD;&#xA;Can I replace this operation by Uniform or Non-uniform Scaling + Translate? &#xD;&#xA;&#xD;&#xA;Will resulting surfaces be mathematically identical in these cases?&#xD;&#xA;&#xD;&#xA;For example i want to transform this surface (side view).&#xD;&#xA;[![enter image description here][1]][1]?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JuAlC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4852" PostHistoryTypeId="5" PostId="2148" RevisionGUID="aa920f2f-471d-4361-a317-d1a4b1704d46" CreationDate="2016-03-07T08:40:20.443" UserId="16" Comment="added 8 characters in body" Text="No this cannot be modelled by (non-uniform) scaling. It's fairly easy to construct a counterexample:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The issue is that the amount a section of the curve/surface grows depends on its curvature, not its orientation in space. Notice here that the circular arc grows (by a factor of $3/2$) whereas the length of the horizontal segments remains unchanged at a length of $2$.&#xD;&#xA;&#xD;&#xA;Of course, if your surface is not only convex but also has constant curvature, then it's just a circular arc, and for circles your transformation is equivalent to uniform scaling. You can probably also construct curves of varying curvature where your transformation happens to correspond to non-uniform scaling, but for general convex surfaces, that's not the case.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CWujH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4853" PostHistoryTypeId="5" PostId="2148" RevisionGUID="bfca68c4-94df-41fb-879e-66a972a94e18" CreationDate="2016-03-07T10:48:23.870" UserId="16" Comment="added 28 characters in body" Text="No this cannot be modelled by (non-uniform) scaling. It's fairly easy to construct a counterexample:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The issue is that the amount a section of the curve/surface grows depends on its curvature, not its orientation in space. Notice here that the circular arc grows uniformly in all directions (by a factor of $3/2$) whereas the length of the horizontal segments remains unchanged at a length of $2$.&#xD;&#xA;&#xD;&#xA;Of course, if your surface is not only convex but also has constant curvature, then it's just a circular arc, and for circles your transformation is equivalent to uniform scaling. You can probably also construct curves of varying curvature where your transformation happens to correspond to non-uniform scaling, but for general convex surfaces, that's not the case.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CWujH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4854" PostHistoryTypeId="2" PostId="2149" RevisionGUID="3f18fbfc-c08b-42dc-bece-9d3ab881fc0c" CreationDate="2016-03-07T11:09:43.583" UserId="2712" Text="There is an web-interface that load geometric models and show it inside the bounding volume. WebGL is used to generate it. So far no scene graph technique is used to organize the elements in the scene. Is there any javascript api that does support the scene graph technique ?&#xD;&#xA;&#xD;&#xA;If there is, I am also required to know more if there is any mechanism to transfer the scene graph related information from the javascript to C++ based API. As of right now the scene that is developed without scenegraph technique stores that scene as an .stl file and C++ based API read the .stl file and process further. I believe that it is not the optimal way to deal with it. It would have much faster and optimal if we have the scene graph system support in javascript to organize the scene and the direct scene related data transfer from javascript to C++ for further processing. &#xD;&#xA;&#xD;&#xA;Let me know if I have not explained the issue well enough. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4855" PostHistoryTypeId="1" PostId="2149" RevisionGUID="3f18fbfc-c08b-42dc-bece-9d3ab881fc0c" CreationDate="2016-03-07T11:09:43.583" UserId="2712" Text="Get data from javascript" ContentLicense="CC BY-SA 3.0" />
  <row Id="4856" PostHistoryTypeId="3" PostId="2149" RevisionGUID="3f18fbfc-c08b-42dc-bece-9d3ab881fc0c" CreationDate="2016-03-07T11:09:43.583" UserId="2712" Text="|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4857" PostHistoryTypeId="2" PostId="2150" RevisionGUID="b7307f4d-9f52-441c-803a-7e63514fd867" CreationDate="2016-03-07T12:04:51.657" UserId="2644" Text="I have bunch of surfaces, like in these two images:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0Bu6o.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EY43g.png&#xD;&#xA;&#xD;&#xA;Currently to make single surface with common parametrization I sample points uniformly from all source surfaces, and fit single NURBS surface from these points. And in most cases it works, but in some rare cases (When surfaces are more curved) this single surface fails to maintain acceptable accuracy at source regions. I tried to increase number of samples, and number of control points for NURBS, but it doesn't help. And btw, solution for images above will be simple planes, because source surfaces are trimmed planes too, but in general case source surfaces will be curvy.&#xD;&#xA;&#xD;&#xA;Additional info:&#xD;&#xA;&#xD;&#xA;1. Source surfaces are trimmed NURBS surfaces, but I can convert them to any other discrete format and work with it.&#xD;&#xA;&#xD;&#xA;2. I don't care about free space between surfaces, values of a resulting surface in this space can be linear interpolation between nearby source surfaces, or even some constant value.&#xD;&#xA;&#xD;&#xA;3. Source surfaces cannot overlap or coincide.&#xD;&#xA;&#xD;&#xA;4. Resulting surface must contain all source regions inside (With some arbitrary tolerance), with common parametrization, also it must not have self-intersections.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any other possible solution to this problem? Maybe some algorithm to order such surfaces in parameter space, or at least name of this problem to google it easily?&#xD;&#xA;&#xD;&#xA;Thanks for any help." ContentLicense="CC BY-SA 3.0" />
  <row Id="4858" PostHistoryTypeId="1" PostId="2150" RevisionGUID="b7307f4d-9f52-441c-803a-7e63514fd867" CreationDate="2016-03-07T12:04:51.657" UserId="2644" Text="Making surface with common parametrization from bunch of other surfaces" ContentLicense="CC BY-SA 3.0" />
  <row Id="4859" PostHistoryTypeId="3" PostId="2150" RevisionGUID="b7307f4d-9f52-441c-803a-7e63514fd867" CreationDate="2016-03-07T12:04:51.657" UserId="2644" Text="|algorithm|mathematics|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4860" PostHistoryTypeId="2" PostId="2151" RevisionGUID="6c70ee40-faef-42b3-ad4e-68e03f7e0056" CreationDate="2016-03-07T12:10:32.883" UserId="2811" Text="I have actually solved this exact problem over a year ago for my master's thesis. In the Valve paper, they show that you can AND two distance fields to achieve this, which works as long as you only have one convex corner. For concave corners, you also need the OR operation. [This guy][1] actually developed some obscure system to switch between the two operations using four texture channels.&#xD;&#xA;&#xD;&#xA;However, there is a much simpler operation that can facilitate both AND and OR depending on the situation, and this is the principal idea of my thesis: **the median of three**. So basically, you use exactly three channels (ideal for RGB), which are completely interchangeable, and combine them using the median operation (choose the middle value out of the three).&#xD;&#xA;&#xD;&#xA;To accomodate anti-aliasing, we don't work with just booleans, but floating point values, and the AND operation becomes the minimum, and the OR becomes the maximum of two values. The median of three can indeed do both: if *a* &lt; *b*, for (*a*, *a*, *b*), the median is the minimum, and for (*a*, *b*, *b*), it is the maximum.&#xD;&#xA;&#xD;&#xA;The rendering process is still extremely simple. The entire fragment shader including anti-aliasing can look something like this:&#xD;&#xA;&#xD;&#xA;    int main() {&#xD;&#xA;        // Bilinear sampling of the distance field&#xD;&#xA;        float s = texture2D(sdf, p).rgb;&#xD;&#xA;        // Acquire the signed distance&#xD;&#xA;        float d = median(s.r, s.g, s.b) - 0.5;&#xD;&#xA;        // Weight between inside and outside (anti-aliasing)&#xD;&#xA;        float w = clamp(d/fwidth(d) + 0.5, 0.0, 1.0);&#xD;&#xA;        // Combining the background and foreground color&#xD;&#xA;        gl_FragColor = mix(outsideColor, insideColor, w);&#xD;&#xA;    }&#xD;&#xA;So the only difference from the original method is computing the median right after sampling the texture. You will have to implement the median function though, [which can be done with just 4 min/max operations][2].&#xD;&#xA;&#xD;&#xA;Now of course, the question is, **how do I build such a three-channel distance field?** And this is the tricky part. The most obvious approach that I took in the beginning was to perform a decomposition of the input shape/glyph into three components, and then generate a conventional distance field out of each. The rules for this decomposition aren't that complicated. Firstly , the area with at least 2 out of 3 channels on is the inside. Then, if you imagine this as the RGB color channels, convex corners must be made of a secondary color, and its two primary components continue outward. Concave corners are the inverse: Two secondary colors enclose their common primary color, and the wedge between where both edges continue inward is white. I also found that some padding is necessary where two primary or two secondary colors would otherwise touch to avoid artifacts (for example, in the middle stroke of the &quot;N&quot; in the picture).&#xD;&#xA;&#xD;&#xA;The following image is an example decomposition generated by the program from my thesis:&#xD;&#xA;&#xD;&#xA;[![Multi-channel decomposition of glyphs][3]][3]&#xD;&#xA;&#xD;&#xA;This approach however has some drawbacks. One of them is that the special effects, such as outlines and shadows will no longer work correctly. Fortunatelly, I also came up with a second, much more elegant method, which generates the distance fields directly, and even supports all of the graphical effects. It is also included in my thesis and so is also over a year old. I am not going to give any more details right now, because I am currently writing a paper that describes this second technique in detail, but I will post it here as soon as it's finished.&#xD;&#xA;&#xD;&#xA;Anyway, here is an example of the difference in quality. The texture resolution is the same in each image, but the left one uses a regular texture, the middle one uses an ordinary distance field, and the right one uses my three-channel distance field. The performance overhead is only the difference between sampling an RGB texture versus a monochrome one.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lambdacube3d.wordpress.com/2014/11/12/playing-around-with-font-rendering/&#xD;&#xA;  [2]: http://stackoverflow.com/a/19045659/1189488&#xD;&#xA;  [3]: https://i.stack.imgur.com/2fVah.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/aG1NR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4863" PostHistoryTypeId="5" PostId="2133" RevisionGUID="d1a72f1b-a0c6-4389-aa73-093d52a084e6" CreationDate="2016-03-08T01:01:59.113" UserId="1937" Comment="added 284 characters in body" Text="I'm aware that most modern GPUs, although designed for floating point, are more or less equivalent in integer performance these days, with a few caveats like the lack of a fused multiply add. I'm not sure how this applies to shift operations though. I'm doing Marching Cubes on GPU, initially writing out a 32-bit packed position for each surface cube then unpacking these in a later pass to the actual vertices in that cube, like this : &#xD;&#xA;    &#xD;&#xA;    ivec3 unpackedPos = ivec3( packedPos &gt;&gt; 20 &amp; 0x3FF,&#xD;&#xA;                             packedPos &gt;&gt; 10 &amp; 0x3FF,&#xD;&#xA;                             packedPos &amp; 0x3FF);&#xD;&#xA;&#xD;&#xA;It just occurred to me to wonder if shader units have barrel shifters in them these days? Am I doing 2 shifts here or 30?&#xD;&#xA;&#xD;&#xA;EDIT&gt;&gt;&#xD;&#xA;I'm an idiot... Thanks for the answers guys, useful to know, but I've been going about this all wrong. I should just be using the RGB10_A2UI texture format then packing/ unpacking with a single image load/store instruction instead of messing around with bitshifts myself. " ContentLicense="CC BY-SA 3.0" />
  <row Id="4865" PostHistoryTypeId="2" PostId="2152" RevisionGUID="237cedfa-716d-4bb9-a6e6-27d272ebacdb" CreationDate="2016-03-08T13:10:25.380" UserId="2831" Text="The &quot;Uniform Mapping&quot; here is incorrect.  It does not transform to a uniform distribution on the sphere.  SEE: the [MathWorld](http://mathworld.wolfram.com/SpherePointPicking.html) page for the &quot;why&quot; and &quot;how&quot;.&#xD;&#xA;&#xD;&#xA;Also on the MathWorld page is the method from [1].&#xD;&#xA;&#xD;&#xA;If $u_0$ and $u_1$ are uniformly distributed in the disk (the rejection method requires on average 1.273 iterations).  The you have:&#xD;&#xA;&#xD;&#xA;$$u_0, u_1 \in (-1,1) $$&#xD;&#xA;$$d = u_0^2+u_1^2,\; d &lt; 1$$&#xD;&#xA;&#xD;&#xA;then the transform to the sphere is:&#xD;&#xA;&#xD;&#xA;$$s=2\sqrt{1-d}$$&#xD;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, 1-2d\right\} $$&#xD;&#xA;&#xD;&#xA;or if you wanted a half-sphere, say positive Z, (just to state the obvious):&#xD;&#xA;&#xD;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, d\right\} $$&#xD;&#xA;&#xD;&#xA;Also if you want to procedurally generate a LDS the additive recurrence formulation of the Weyl sequence is very cheap.&#xD;&#xA;&#xD;&#xA;[1] &quot;Choosing a Point from the Surface of a Sphere.&quot;, George Marsaglia, 1972. \([PDF](http://projecteuclid.org/euclid.aoms/1177692644;)) &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4866" PostHistoryTypeId="2" PostId="2153" RevisionGUID="a2a6565d-b524-4594-af7b-133c79a5a230" CreationDate="2016-03-08T15:42:51.960" UserId="2372" Text="I am wondering what's the best way to integrate a dynamic loop function in a shader.&#xD;&#xA;&#xD;&#xA;First, it seems that dynamic arrays are not possible, so is it better to create a maximum size array and only fill a part of it or define arrays with predefined sizes.&#xD;&#xA;&#xD;&#xA;Then, what's the best way to iterate over this array.&#xD;&#xA;&#xD;&#xA;Is it better to use an unrolled loop or a dynamic loop for something between 4 to 128 iterations.&#xD;&#xA;I've also seen that it's possible to unroll it to a maximum predefined number of iterations then stop it with a condition such as `if (i == myCurrentMaximumIterationNumber)`&#xD;&#xA;&#xD;&#xA;Any good advice ?&#xD;&#xA;Thanks !" ContentLicense="CC BY-SA 3.0" />
  <row Id="4867" PostHistoryTypeId="1" PostId="2153" RevisionGUID="a2a6565d-b524-4594-af7b-133c79a5a230" CreationDate="2016-03-08T15:42:51.960" UserId="2372" Text="Loop performances in a shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="4868" PostHistoryTypeId="3" PostId="2153" RevisionGUID="a2a6565d-b524-4594-af7b-133c79a5a230" CreationDate="2016-03-08T15:42:51.960" UserId="2372" Text="|opengl|rendering|shader|glsl|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4869" PostHistoryTypeId="2" PostId="2154" RevisionGUID="88d0b811-d32c-4e11-8b68-a9884080c0a1" CreationDate="2016-03-08T17:43:45.363" UserDisplayName="user2500" Text="Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control; if you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. If you cannot test your shader on the HW you care about, it's pretty solid to leave it to the shader compiler when it comes to many optimizations: some HW might get loops for free, and minimizing instruction count for cache hits is good; on other HW, loops may be expensive." ContentLicense="CC BY-SA 3.0" />
  <row Id="4870" PostHistoryTypeId="5" PostId="2154" RevisionGUID="bd826dff-91ed-4824-9d3c-9c5456226df7" CreationDate="2016-03-08T17:50:37.710" UserDisplayName="user2500" Comment="Address dynamic loop more rationally." Text="Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control and the cost on more recent HW can vary. If you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. Your dynamic loop is a more amenable to developer intervention than a static loop - but leaving it to the compiler is still good advice unless you have a benchmark available. With a benchmark, exploration is worthwhile (and fun)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4871" PostHistoryTypeId="5" PostId="2154" RevisionGUID="cf46e63d-cfe4-4598-aecf-231d6c7a12cf" CreationDate="2016-03-08T17:58:15.220" UserDisplayName="user2500" Comment="Add comments about wavefront/warp." Text="Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control and the cost on more recent HW can vary. If you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. Your dynamic loop is a more amenable to developer intervention than a static loop - but leaving it to the compiler is still good advice unless you have a benchmark available. With a benchmark, exploration is worthwhile (and fun).&#xD;&#xA;&#xD;&#xA;BTW, the biggest loss with a dynamic loop on a GPU is that individual &quot;threads&quot; in a wavefront/warp will finish at different times. The threads that stop later force all the ones that finish early to execute NOPs. Nested loops where inner loops are dynamic are especially worth rethinking." ContentLicense="CC BY-SA 3.0" />
  <row Id="4872" PostHistoryTypeId="2" PostId="2155" RevisionGUID="e55bc50c-fee2-4906-81f9-afda7235aba8" CreationDate="2016-03-08T20:27:51.557" UserId="2840" Text="I've never written shaders before, and now I'm trying to implement SSAO with SceneKit on OS X and iOS. I'm trying different SSAO shaders that I find, e.g. from Three.js, [this one][1], and [this one][2].&#xD;&#xA;&#xD;&#xA;On OS X they all work as they should, but on iPhone _all_ of them giving me the same artefacts (images show SSAO pass only). The lines move when I move the camera. So it must be because of some differences of OpenGL ES. Anyone knows what's wrong?&#xD;&#xA;&#xD;&#xA;[![img1][3]][3] [![img2][4]][4] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://theorangeduck.com/page/pure-depth-ssao&#xD;&#xA;  [2]: https://www.shadertoy.com/view/Ms33WB&#xD;&#xA;  [3]: https://i.stack.imgur.com/C1NhL.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3FQYE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4873" PostHistoryTypeId="1" PostId="2155" RevisionGUID="e55bc50c-fee2-4906-81f9-afda7235aba8" CreationDate="2016-03-08T20:27:51.557" UserId="2840" Text="SSAO artefacts on iPhone (OpenGL ES)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4874" PostHistoryTypeId="3" PostId="2155" RevisionGUID="e55bc50c-fee2-4906-81f9-afda7235aba8" CreationDate="2016-03-08T20:27:51.557" UserId="2840" Text="|shader|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4875" PostHistoryTypeId="6" PostId="2153" RevisionGUID="88cc21c5-8dce-4d8e-afaa-3dee4bb64979" CreationDate="2016-03-08T21:40:08.187" UserId="127" Comment="Replaced [hlsl] tag by [performance] as this question is also tagged [opengl] and HLSL is used in DirectX, edited title, removed salutation, made questions end with a question mark." Text="|opengl|rendering|shader|glsl|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4876" PostHistoryTypeId="5" PostId="2153" RevisionGUID="88cc21c5-8dce-4d8e-afaa-3dee4bb64979" CreationDate="2016-03-08T21:40:08.187" UserId="127" Comment="Replaced [hlsl] tag by [performance] as this question is also tagged [opengl] and HLSL is used in DirectX, edited title, removed salutation, made questions end with a question mark." Text="I am wondering what's the best way to integrate a dynamic loop function in a shader?&#xD;&#xA;&#xD;&#xA;First, it seems that dynamic arrays are not possible. So, is it better to create a maximum size array and only fill a part of it or define arrays with predefined sizes?&#xD;&#xA;&#xD;&#xA;Then, what's the best way to iterate over this array?&#xD;&#xA;&#xD;&#xA;Is it better to use an unrolled loop or a dynamic loop for something between 4 to 128 iterations?&#xD;&#xA;I've also seen that it's possible to unroll it to a maximum predefined number of iterations then stop it with a condition such as `if (i == myCurrentMaximumIterationNumber)`." ContentLicense="CC BY-SA 3.0" />
  <row Id="4877" PostHistoryTypeId="4" PostId="2153" RevisionGUID="88cc21c5-8dce-4d8e-afaa-3dee4bb64979" CreationDate="2016-03-08T21:40:08.187" UserId="127" Comment="Replaced [hlsl] tag by [performance] as this question is also tagged [opengl] and HLSL is used in DirectX, edited title, removed salutation, made questions end with a question mark." Text="Loop performance in a shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="4878" PostHistoryTypeId="2" PostId="2156" RevisionGUID="dc0ae894-0bd0-4626-90b5-285dd8b2cf68" CreationDate="2016-03-08T23:20:07.050" UserId="2840" Text="Resolved by adding `precision highp sampler2D` to my shaders." ContentLicense="CC BY-SA 3.0" />
  <row Id="4884" PostHistoryTypeId="5" PostId="2152" RevisionGUID="ad8dbe5d-ea25-45e2-88e8-6a9635af63e0" CreationDate="2016-03-09T12:16:36.060" UserId="2831" Comment="added 1391 characters in body" Text="&lt;strike&gt;The &quot;Uniform Mapping&quot; here is incorrect.  It does not transform to a uniform distribution on the sphere.&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;Very very bad me.  I misread the equation AND I didn't even consult my own reference [1], if I had I would have seen my mistake.&#xD;&#xA;&#xD;&#xA;Still the method from [2] is interesting and is described below.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The method from [2] starts by mapping $P$ to the unit disk.  One way we can do this is by using a rejection method.  Pseudo-code looks like this:&#xD;&#xA;&#xD;&#xA;    s = 0;&#xD;&#xA;&#xD;&#xA;    do {&#xD;&#xA;      p = uniform2d(...);  // [0,1) x [0,1)   given to be uniform&#xD;&#xA;      p = 2p;              // [0,2) x [0,2)   scaling (area-preserving)&#xD;&#xA;      p = p-1;             // (-1,1) x (-1,1) translating (area-preserving)&#xD;&#xA;      s = dot(p,p);        // is p in disk?&#xD;&#xA;    } while(s &gt;= 1);       //   if not rinse-and-repeat&#xD;&#xA;&#xD;&#xA;the area of the transformed square is $4$ and the unit disk is $\pi$, so the acceptance rate is $\frac{\pi }{4}$ (~.785) so on average requires $\frac{4}{\pi}$ (~1.273) iterations.&#xD;&#xA;&#xD;&#xA;Also non-rejection based methods exist, for example [3] which requires one square root and one trig operation.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Once we have $u_0$ and $u_1$ uniformly distributed in the disk, we have:&#xD;&#xA;&#xD;&#xA;$$ u_0, u_1 \in \left(-1,1\right) $$&#xD;&#xA;$$ d = u_0^2+u_1^2,\; d &lt; 1 $$&#xD;&#xA;&#xD;&#xA;then the transform to the sphere is:&#xD;&#xA;&#xD;&#xA;$$ s=2\sqrt{1-d} $$&#xD;&#xA;$$ p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, 1-2d\right\} $$&#xD;&#xA;&#xD;&#xA;or if you wanted a half-sphere, say positive Z, (just to state the obvious):&#xD;&#xA;&#xD;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, d\right\} $$&#xD;&#xA;&#xD;&#xA;There is a Stackexchange: Mathematics thread that discusses this method ([4],[5]).&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Also if you want to procedurally generate a LDS the additive recurrence formulation of the Weyl sequence is very cheap.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA;1. [Wolfram MathWorld: Sphere Point Picking](http://mathworld.wolfram.com/SpherePointPicking.html)&#xD;&#xA;2. &quot;Choosing a Point from the Surface of a Sphere.&quot;, George Marsaglia, 1972. \([PDF](http://projecteuclid.org/euclid.aoms/1177692644;))&#xD;&#xA;3. [Wolfram MathWorld: Disk Point Picking](http://mathworld.wolfram.com/DiskPointPicking.html)&#xD;&#xA;4. [SE Mathematics](http://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838336#838336)&#xD;&#xA;5. [SE Mathematics](http://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838882#838882)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4885" PostHistoryTypeId="5" PostId="2152" RevisionGUID="ae492447-8135-4062-816f-4992471d1068" CreationDate="2016-03-09T13:35:48.023" UserId="2831" Comment="updated the text and pseudo-code to be consistent, nuke a set def reference that got edited out." Text="&lt;strike&gt;The &quot;Uniform Mapping&quot; here is incorrect.  It does not transform to a uniform distribution on the sphere.&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;Very very bad me.  I misread the equation AND I didn't even consult my own reference [1], if I had I would have seen my mistake.&#xD;&#xA;&#xD;&#xA;Still the method from [2] is interesting and is described below.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The method from [2] starts by mapping unit square to the unit disk.  One way we can do this is by using a rejection method.  Pseudo-code looks like this:&#xD;&#xA;&#xD;&#xA;    d = 0;&#xD;&#xA;&#xD;&#xA;    do {&#xD;&#xA;      p = uniform2d(...);  // [0,1) x [0,1)   given to be uniform&#xD;&#xA;      p = 2p;              // [0,2) x [0,2)   scaling (area-preserving)&#xD;&#xA;      p = p-1;             // (-1,1) x (-1,1) translating (area-preserving)&#xD;&#xA;      d = dot(p,p);        // is p in disk?&#xD;&#xA;    } while(d &gt;= 1);       //   if not rinse-and-repeat&#xD;&#xA;&#xD;&#xA;the area of the transformed square is $4$ and the unit disk is $\pi$, so the acceptance rate is $\frac{\pi }{4}$ (~.785) so on average requires $\frac{4}{\pi}$ (~1.273) iterations.&#xD;&#xA;&#xD;&#xA;Also non-rejection based methods exist, for example [3] which requires one square root and one trig operation.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Once we have $ p = \left(u_0, u_1 \right) $ uniformly distributed in the unit disk, we have:&#xD;&#xA;&#xD;&#xA;$$ u_0, u_1 \in \left(-1,1\right) $$&#xD;&#xA;$$ d = p\cdot p = u_0^2+u_1^2,\; d &lt; 1 $$&#xD;&#xA;&#xD;&#xA;then the transform to the sphere is:&#xD;&#xA;&#xD;&#xA;$$ s=2\sqrt{1-d} $$&#xD;&#xA;$$ p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, 1-2d\right\} $$&#xD;&#xA;&#xD;&#xA;or if you wanted a half-sphere, say positive Z, (just to state the obvious):&#xD;&#xA;&#xD;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, d\right\} $$&#xD;&#xA;&#xD;&#xA;There is a Stackexchange: Mathematics thread that discusses this method ([4],[5]).&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Also if you want to procedurally generate a LDS the additive recurrence formulation of the Weyl sequence is very cheap.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA;1. [Wolfram MathWorld: Sphere Point Picking](http://mathworld.wolfram.com/SpherePointPicking.html)&#xD;&#xA;2. &quot;Choosing a Point from the Surface of a Sphere.&quot;, George Marsaglia, 1972. \([PDF](http://projecteuclid.org/euclid.aoms/1177692644;))&#xD;&#xA;3. [Wolfram MathWorld: Disk Point Picking](http://mathworld.wolfram.com/DiskPointPicking.html)&#xD;&#xA;4. [SE Mathematics](http://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838336#838336)&#xD;&#xA;5. [SE Mathematics](http://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838882#838882)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4886" PostHistoryTypeId="2" PostId="2158" RevisionGUID="570aff51-318a-4f0f-8293-0889490b3be0" CreationDate="2016-03-09T14:17:54.727" UserId="1937" Text="Ok guys, tricky one!&#xD;&#xA;&#xD;&#xA;I'm trying to modify [this](http://wiki.unity3d.com/index.php?title=MirrorReflection2) Unity script + shader to include normal mapping. The tl;dr is, it uses a single texture rather than a cubemap as it is only for reflecting in a planar surface. So it doesn't use the standard ray bounce onto an axis aligned cube. Instead it :&#xD;&#xA;&#xD;&#xA; - creates a reflection matrix from the plane (pos and normal)&#xD;&#xA; - reflects the camera position and view matrix through the plane&#xD;&#xA; - renders to texture from the reflected camera (with oblique near clipping plane set to cull everything behind the mirror)&#xD;&#xA; - creates a projection matrix and sends it as uniform to the shader (basically just a standard MVP matrix but with scale cancelled, and biased from [-1, 1] to [0, 1]&#xD;&#xA; - multiplies the object space coordinate by the projection matrix to get a texcoord and then looks up the mirror texture with this&#xD;&#xA;&#xD;&#xA;So there are no normals actually used in the shader at all at present. I know how to construct a TBN matrix and use this to warp the per-pixel normals, but I have no idea how this translates into a texture offset in this case. I have a feeling I might need screen-space normals like in the question [here](http://stackoverflow.com/questions/14317350/transform-world-space-normals-to-screen-space-normals) but pretty stumped beyond that. Any ideas?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4887" PostHistoryTypeId="1" PostId="2158" RevisionGUID="570aff51-318a-4f0f-8293-0889490b3be0" CreationDate="2016-03-09T14:17:54.727" UserId="1937" Text="Normal mapping for planar reflections" ContentLicense="CC BY-SA 3.0" />
  <row Id="4888" PostHistoryTypeId="3" PostId="2158" RevisionGUID="570aff51-318a-4f0f-8293-0889490b3be0" CreationDate="2016-03-09T14:17:54.727" UserId="1937" Text="|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4889" PostHistoryTypeId="5" PostId="2158" RevisionGUID="8934da00-dc30-4af7-adef-fc6fe3e05482" CreationDate="2016-03-09T14:40:19.247" UserId="1937" Comment="added 13061 characters in body" Text="Ok guys, tricky one!&#xD;&#xA;&#xD;&#xA;I'm trying to modify [this](http://wiki.unity3d.com/index.php?title=MirrorReflection2) Unity script + shader to include normal mapping. The tl;dr is, it uses a single texture rather than a cubemap as it is only for reflecting in a planar surface. So it doesn't use the standard ray bounce onto an axis aligned cube. Instead it :&#xD;&#xA;&#xD;&#xA; - creates a reflection matrix from the plane (pos and normal)&#xD;&#xA; - reflects the camera position and view matrix through the plane&#xD;&#xA; - renders to texture from the reflected camera (with oblique near clipping plane set to cull everything behind the mirror)&#xD;&#xA; - creates a projection matrix and sends it as uniform to the shader (basically just a standard MVP matrix but with scale cancelled, and biased from [-1, 1] to [0, 1]&#xD;&#xA; - multiplies the object space coordinate by the projection matrix to get a texcoord and then looks up the mirror texture with this&#xD;&#xA;&#xD;&#xA;So there are no normals actually used in the shader at all at present. I know how to construct a TBN matrix and use this to warp the per-pixel normals, but I have no idea how this translates into a texture offset in this case. I have a feeling I might need screen-space normals like in the question [here](http://stackoverflow.com/questions/14317350/transform-world-space-normals-to-screen-space-normals) but pretty stumped beyond that. Any ideas?&#xD;&#xA;&#xD;&#xA;EDIT -- Here's the script&#xD;&#xA;&#xD;&#xA;    using UnityEngine;&#xD;&#xA;    using System.Collections;&#xD;&#xA;&#xD;&#xA;    [ExecuteInEditMode()]&#xD;&#xA;    public class PlanarRealtimeReflection : MonoBehaviour&#xD;&#xA;    {&#xD;&#xA;	public bool m_DisablePixelLights = true;&#xD;&#xA;	public int m_TextureResolution = 1024;&#xD;&#xA;	public float m_clipPlaneOffset = 0.07f;&#xD;&#xA;	private float m_finalClipPlaneOffset = 0.0f;&#xD;&#xA;	public bool m_NormalsFromMesh = false;&#xD;&#xA;	public bool m_BaseClipOffsetFromMesh = false;&#xD;&#xA;	public bool m_BaseClipOffsetFromMeshInverted = false;&#xD;&#xA;	private Vector3 m_calculatedNormal = Vector3.zero;&#xD;&#xA;    private Vector3 m_calculatedTangent = Vector4.zero;&#xD;&#xA;	public LayerMask m_ReflectLayers = -1;&#xD;&#xA;	&#xD;&#xA;	private Hashtable m_ReflectionCameras = new Hashtable(); //Camera -&gt; Camera table&#xD;&#xA;	&#xD;&#xA;	private RenderTexture m_ReflectionTexture = null;&#xD;&#xA;	private int m_OldReflectionTextureSize = 0;&#xD;&#xA;	&#xD;&#xA;	private static bool s_InsideRendering = false;&#xD;&#xA;	&#xD;&#xA;	//This is called when it's known that the object will be rendered by some&#xD;&#xA;	//camera. We render reflections and do other updates here.&#xD;&#xA;	//Because the script executes in edit mode, reflections for the scene view&#xD;&#xA;	//camera will just work!&#xD;&#xA;	public void OnWillRenderObject()&#xD;&#xA;	{&#xD;&#xA;		if(!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled)&#xD;&#xA;			return;&#xD;&#xA;&#xD;&#xA;		Camera cam = Camera.current;&#xD;&#xA;		if(!cam)&#xD;&#xA;			return;&#xD;&#xA;		&#xD;&#xA;		if(m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;			m_calculatedNormal = transform.TransformDirection(GetComponent&lt;MeshFilter&gt;().sharedMesh.normals[0]);&#xD;&#xA;            m_calculatedTangent = transform.TransformDirection(GetComponent&lt;MeshFilter&gt;().sharedMesh.tangents[0]);&#xD;&#xA;		    &#xD;&#xA;		if(m_BaseClipOffsetFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;			m_finalClipPlaneOffset = (transform.position - transform.TransformPoint(GetComponent&lt;MeshFilter&gt;().sharedMesh.vertices[0])).magnitude + m_clipPlaneOffset;&#xD;&#xA;		else if(m_BaseClipOffsetFromMeshInverted &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;			m_finalClipPlaneOffset = -(transform.position - transform.TransformPoint(GetComponent&lt;MeshFilter&gt;().sharedMesh.vertices[0])).magnitude + m_clipPlaneOffset;&#xD;&#xA;		else&#xD;&#xA;			m_finalClipPlaneOffset = m_clipPlaneOffset;&#xD;&#xA;		&#xD;&#xA;		//Safeguard from recursive reflections.        &#xD;&#xA;		if(s_InsideRendering)&#xD;&#xA;			return;&#xD;&#xA;		s_InsideRendering = true;&#xD;&#xA;		&#xD;&#xA;		Camera reflectionCamera;&#xD;&#xA;		CreateSurfaceObjects(cam, out reflectionCamera);&#xD;&#xA;		&#xD;&#xA;		//Find out the reflection plane: position and normal in world space&#xD;&#xA;		Vector3 pos = transform.position;&#xD;&#xA;		Vector3 normal = m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null ? m_calculatedNormal : transform.up;&#xD;&#xA;        Vector3 tangent = m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null ? m_calculatedTangent : transform.right;&#xD;&#xA;        Vector3 bitangent = Vector3.Cross(normal, tangent);&#xD;&#xA;&#xD;&#xA;		//Optionally disable pixel lights for reflection&#xD;&#xA;		int oldPixelLightCount = QualitySettings.pixelLightCount;&#xD;&#xA;		if(m_DisablePixelLights)&#xD;&#xA;			QualitySettings.pixelLightCount = 0;&#xD;&#xA;		&#xD;&#xA;		UpdateCameraModes(cam, reflectionCamera);&#xD;&#xA;		&#xD;&#xA;		//Render reflection&#xD;&#xA;		//Reflect camera around reflection plane&#xD;&#xA;		float d = -Vector3.Dot (normal, pos) - m_finalClipPlaneOffset;&#xD;&#xA;		Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);&#xD;&#xA;		Matrix4x4 reflection = Matrix4x4.zero;&#xD;&#xA;		CalculateReflectionMatrix (ref reflection, reflectionPlane);&#xD;&#xA;		Vector3 oldpos = cam.transform.position;&#xD;&#xA;		Vector3 newpos = reflection.MultiplyPoint(oldpos);&#xD;&#xA;		reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;&#xD;&#xA;		&#xD;&#xA;		//Setup oblique projection matrix so that near plane is our reflection plane.&#xD;&#xA;		//This way we clip everything below/above it for free.&#xD;&#xA;		Vector4 clipPlane = CameraSpacePlane(reflectionCamera, pos, normal, 1.0f);&#xD;&#xA;		Matrix4x4 projection = cam.projectionMatrix;&#xD;&#xA;		CalculateObliqueMatrix (ref projection, clipPlane);&#xD;&#xA;		reflectionCamera.projectionMatrix = projection;&#xD;&#xA;		&#xD;&#xA;		reflectionCamera.cullingMask = ~(1&lt;&lt;4) &amp; m_ReflectLayers.value; //never render water layer&#xD;&#xA;		reflectionCamera.targetTexture = m_ReflectionTexture;&#xD;&#xA;		GL.SetRevertBackfacing (true);&#xD;&#xA;		reflectionCamera.transform.position = newpos;&#xD;&#xA;		//Vector3 euler = cam.transform.eulerAngles;&#xD;&#xA;        //reflectionCamera.transform.eulerAngles = euler; // new Vector3(0, euler.y, euler.z);&#xD;&#xA;		reflectionCamera.Render();&#xD;&#xA;		reflectionCamera.transform.position = oldpos;&#xD;&#xA;		GL.SetRevertBackfacing (false);&#xD;&#xA;		Material[] materials = renderer.sharedMaterials;&#xD;&#xA;		foreach(Material mat in materials)&#xD;&#xA;		{&#xD;&#xA;            if (mat.HasProperty(&quot;_ReflectionTex&quot;))  &#xD;&#xA;				mat.SetTexture(&quot;_ReflectionTex&quot;, m_ReflectionTexture);&#xD;&#xA;            mat.SetVector(&quot;_Normal&quot;, new Vector4(normal.x,normal.y,normal.z,0));&#xD;&#xA;            mat.SetVector(&quot;_Tangent&quot;, new Vector4(tangent.x, tangent.y, tangent.z));&#xD;&#xA;            mat.SetVector(&quot;_Bitangent&quot;, new Vector4(bitangent.x, bitangent.y, bitangent.z));&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;		//Set matrix on the shader that transforms UVs from object space into screen&#xD;&#xA;		//space. We want to just project reflection texture on screen.&#xD;&#xA;		Matrix4x4 scaleOffset = Matrix4x4.TRS(&#xD;&#xA;			new Vector3(0.5f,0.5f,0.5f), Quaternion.identity, new Vector3(0.5f,0.5f,0.5f));&#xD;&#xA;		Vector3 scale = transform.localScale;//.lossyScale;&#xD;&#xA;        Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z));&#xD;&#xA;        mtx = scaleOffset *  cam.projectionMatrix * cam.worldToCameraMatrix * mtx;&#xD;&#xA;		foreach(Material mat in materials)&#xD;&#xA;			mat.SetMatrix(&quot;_ProjMatrix&quot;, mtx);&#xD;&#xA;		//Restore pixel light count&#xD;&#xA;		if(m_DisablePixelLights)&#xD;&#xA;			QualitySettings.pixelLightCount = oldPixelLightCount;&#xD;&#xA;		&#xD;&#xA;		s_InsideRendering = false;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	//Cleanup all the objects we possibly have created&#xD;&#xA;	void OnDisable()&#xD;&#xA;	{&#xD;&#xA;		if(m_ReflectionTexture)&#xD;&#xA;		{&#xD;&#xA;			DestroyImmediate(m_ReflectionTexture);&#xD;&#xA;			m_ReflectionTexture = null;&#xD;&#xA;		}&#xD;&#xA;		foreach(DictionaryEntry kvp in m_ReflectionCameras)&#xD;&#xA;			DestroyImmediate(((Camera)kvp.Value).gameObject);&#xD;&#xA;		m_ReflectionCameras.Clear();&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	private void UpdateCameraModes(Camera src, Camera dest)&#xD;&#xA;	{&#xD;&#xA;		if(dest == null)&#xD;&#xA;			return;&#xD;&#xA;		//set camera to clear the same way as current camera&#xD;&#xA;		dest.clearFlags = src.clearFlags;&#xD;&#xA;		dest.backgroundColor = src.backgroundColor;        &#xD;&#xA;		if(src.clearFlags == CameraClearFlags.Skybox)&#xD;&#xA;		{&#xD;&#xA;			Skybox sky = src.GetComponent(typeof(Skybox)) as Skybox;&#xD;&#xA;			Skybox mysky = dest.GetComponent(typeof(Skybox)) as Skybox;&#xD;&#xA;			if(!sky || !sky.material)&#xD;&#xA;			{&#xD;&#xA;				mysky.enabled = false;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				mysky.enabled = true;&#xD;&#xA;				mysky.material = sky.material;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		//update other values to match current camera.&#xD;&#xA;		//even if we are supplying custom camera&amp;projection matrices,&#xD;&#xA;		//some of values are used elsewhere (e.g. skybox uses far plane)&#xD;&#xA;		dest.farClipPlane = src.farClipPlane;&#xD;&#xA;		dest.nearClipPlane = src.nearClipPlane;&#xD;&#xA;		dest.orthographic = src.orthographic;&#xD;&#xA;		dest.fieldOfView = src.fieldOfView;&#xD;&#xA;		dest.aspect = src.aspect;&#xD;&#xA;		dest.orthographicSize = src.orthographicSize;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	//On-demand create any objects we need&#xD;&#xA;	private void CreateSurfaceObjects(Camera currentCamera, out Camera reflectionCamera)&#xD;&#xA;	{&#xD;&#xA;		reflectionCamera = null;&#xD;&#xA;		&#xD;&#xA;		//Reflection render texture&#xD;&#xA;		if(!m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureResolution)&#xD;&#xA;		{&#xD;&#xA;			if(m_ReflectionTexture)&#xD;&#xA;				DestroyImmediate(m_ReflectionTexture);&#xD;&#xA;			m_ReflectionTexture = new RenderTexture(m_TextureResolution, m_TextureResolution, 16);&#xD;&#xA;			m_ReflectionTexture.name = &quot;__SurfaceReflection&quot; + GetInstanceID();&#xD;&#xA;			m_ReflectionTexture.isPowerOfTwo = true;&#xD;&#xA;			m_ReflectionTexture.hideFlags = HideFlags.DontSave;&#xD;&#xA;			m_OldReflectionTextureSize = m_TextureResolution;&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;		//Camera for reflection&#xD;&#xA;		reflectionCamera = m_ReflectionCameras[currentCamera] as Camera;&#xD;&#xA;		if(!reflectionCamera) //catch both not-in-dictionary and in-dictionary-but-deleted-GO&#xD;&#xA;		{&#xD;&#xA;			GameObject go = new GameObject(&quot;Surface Refl Camera id&quot; + GetInstanceID() + &quot; for &quot; + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox));&#xD;&#xA;			reflectionCamera = go.camera;&#xD;&#xA;			reflectionCamera.enabled = false;&#xD;&#xA;			reflectionCamera.transform.position = transform.position;&#xD;&#xA;			reflectionCamera.transform.rotation = transform.rotation;&#xD;&#xA;			reflectionCamera.gameObject.AddComponent(&quot;FlareLayer&quot;);&#xD;&#xA;			go.hideFlags = HideFlags.HideAndDontSave;&#xD;&#xA;			m_ReflectionCameras[currentCamera] = reflectionCamera;&#xD;&#xA;		}        &#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	//Extended sign: returns -1, 0 or 1 based on sign of a&#xD;&#xA;	private static float sgn(float a)&#xD;&#xA;	{&#xD;&#xA;		if (a &gt; 0.0f) return 1.0f;&#xD;&#xA;		if (a &lt; 0.0f) return -1.0f;&#xD;&#xA;		return 0.0f;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	//Given position/normal of the plane, calculates plane in camera space.&#xD;&#xA;	private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)&#xD;&#xA;	{&#xD;&#xA;		Vector3 offsetPos = pos + normal * m_finalClipPlaneOffset;&#xD;&#xA;		Matrix4x4 m = cam.worldToCameraMatrix;&#xD;&#xA;		Vector3 cpos = m.MultiplyPoint(offsetPos);&#xD;&#xA;		Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;&#xD;&#xA;		return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal));&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	//Adjusts the given projection matrix so that near plane is the given clipPlane&#xD;&#xA;	//clipPlane is given in camera space. See article in Game Programming Gems 5 and&#xD;&#xA;	//http://aras-p.info/texts/obliqueortho.html&#xD;&#xA;	private static void CalculateObliqueMatrix (ref Matrix4x4 projection, Vector4 clipPlane)&#xD;&#xA;	{&#xD;&#xA;		Vector4 q = projection.inverse * new Vector4(&#xD;&#xA;			sgn(clipPlane.x),&#xD;&#xA;			sgn(clipPlane.y),&#xD;&#xA;			1.0f,&#xD;&#xA;			1.0f&#xD;&#xA;			);&#xD;&#xA;		Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlane, q)));&#xD;&#xA;		//third row = clip plane - fourth row&#xD;&#xA;		projection[2] = c.x - projection[3];&#xD;&#xA;		projection[6] = c.y - projection[7];&#xD;&#xA;		projection[10] = c.z - projection[11];&#xD;&#xA;		projection[14] = c.w - projection[15];&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	//Calculates reflection matrix around the given plane&#xD;&#xA;	private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)&#xD;&#xA;	{&#xD;&#xA;		reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);&#xD;&#xA;		reflectionMat.m01 = (  - 2F*plane[0]*plane[1]);&#xD;&#xA;		reflectionMat.m02 = (  - 2F*plane[0]*plane[2]);&#xD;&#xA;		reflectionMat.m03 = (  - 2F*plane[3]*plane[0]);&#xD;&#xA;		&#xD;&#xA;		reflectionMat.m10 = (  - 2F*plane[1]*plane[0]);&#xD;&#xA;		reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);&#xD;&#xA;		reflectionMat.m12 = (  - 2F*plane[1]*plane[2]);&#xD;&#xA;		reflectionMat.m13 = (  - 2F*plane[3]*plane[1]);&#xD;&#xA;		&#xD;&#xA;		reflectionMat.m20 = (  - 2F*plane[2]*plane[0]);&#xD;&#xA;		reflectionMat.m21 = (  - 2F*plane[2]*plane[1]);&#xD;&#xA;		reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);&#xD;&#xA;		reflectionMat.m23 = (  - 2F*plane[3]*plane[2]);&#xD;&#xA;		&#xD;&#xA;		reflectionMat.m30 = 0F;&#xD;&#xA;		reflectionMat.m31 = 0F;&#xD;&#xA;		reflectionMat.m32 = 0F;&#xD;&#xA;		reflectionMat.m33 = 1F;&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;And the shader so far&#xD;&#xA;&#xD;&#xA;    Shader &quot;Realtime Reflections/New Shader&quot;&#xD;&#xA;    {&#xD;&#xA;     Properties {		&#xD;&#xA;        _MainAlpha(&quot;MainAlpha&quot;, Range(0, 1)) = 1&#xD;&#xA;		_MapAmount(&quot;Distortion Amount&quot;, Range(0, 0.05)) = 0&#xD;&#xA;        _MainTex (&quot;Base (RGB) Gloss (A)&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;        _ReflectionTex (&quot;Reflection&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;		_NormalMap (&quot;Normal Map&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;		_RefColor(&quot;Color&quot;,Color) = (1,1,1,1)&#xD;&#xA;	}&#xD;&#xA;	SubShader {&#xD;&#xA;        Tags {&#xD;&#xA;            &quot;RenderType&quot;=&quot;Opaque&quot;}&#xD;&#xA;		LOD 100&#xD;&#xA;		Pass {&#xD;&#xA;            CGPROGRAM&#xD;&#xA;			#pragma vertex vert&#xD;&#xA;			#pragma fragment frag&#xD;&#xA;			#include &quot;UnityCG.cginc&quot;&#xD;&#xA;&#xD;&#xA;			uniform float4x4	_ProjMatrix;&#xD;&#xA;			uniform float		_RefType;&#xD;&#xA;			uniform float4		_Normal;&#xD;&#xA;			uniform float4		_Tangent;&#xD;&#xA;			uniform float4		_Bitangent;&#xD;&#xA;            sampler2D			_ReflectionTex;&#xD;&#xA;			sampler2D			_MainTex;&#xD;&#xA;			sampler2D			_NormalMap;&#xD;&#xA;			float4				_MainTex_ST;&#xD;&#xA;			float4				_NormalMap_ST;       &#xD;&#xA;            float4				_RefColor;&#xD;&#xA;            float				_MainAlpha;&#xD;&#xA;			float				_MapAmount;&#xD;&#xA;&#xD;&#xA;            struct outvertex {&#xD;&#xA;                float4 pos :		SV_POSITION;&#xD;&#xA;                float2 colorUV :	TEXCOORD0;&#xD;&#xA;				float2 bumpUV :		TEXCOORD1;&#xD;&#xA;				float4 varyingPos : TEXCOORD2;&#xD;&#xA;            };&#xD;&#xA;            &#xD;&#xA;			outvertex vert(appdata_full v) {&#xD;&#xA;			&#xD;&#xA;                outvertex o;&#xD;&#xA;                o.pos = mul (UNITY_MATRIX_MVP,v.vertex);&#xD;&#xA;                o.colorUV = TRANSFORM_TEX(v.texcoord.xy,_MainTex);&#xD;&#xA;				o.bumpUV = TRANSFORM_TEX(v.texcoord1.xy,_NormalMap);&#xD;&#xA;				o.varyingPos = v.vertex;	&#xD;&#xA;				o. color = fixed4(mul(float3x3(UNITY_MATRIX_IT_MV),v.normal),1);&#xD;&#xA;				return o;&#xD;&#xA;            }&#xD;&#xA;										&#xD;&#xA;			float4 frag(outvertex i) : COLOR {          &#xD;&#xA;				float4 posProj = mul(_ProjMatrix, i.varyingPos);      &#xD;&#xA;				float2 normPosProj = posProj.xy / posProj.w;&#xD;&#xA;				float3 bump = (float3(tex2D(_NormalMap, i.bumpUV));&#xD;&#xA;				//normPosProj += ?????????&#xD;&#xA;				half4 flecol = tex2D(_ReflectionTex, normPosProj);	&#xD;&#xA;				half4 maincol =  tex2D(_MainTex, i.colorUV);									&#xD;&#xA;				half4 outcolor = half4(1,1,1,1);				&#xD;&#xA;				outcolor = maincol*_MainAlpha+flecol*(1-_MainAlpha);&#xD;&#xA;                return outcolor*_RefColor;&#xD;&#xA;            }&#xD;&#xA;			ENDCG&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;I had the idea to get the normal in screen space (so z is always toward camera) then simply find the delta between the regular normal and the warped one in x,y and use this as the texture offset, but I have no idea if this is feasible or how to do it." ContentLicense="CC BY-SA 3.0" />
  <row Id="4890" PostHistoryTypeId="5" PostId="2158" RevisionGUID="93a4bdb1-939b-4024-abef-ebd866b97e42" CreationDate="2016-03-09T14:42:48.583" UserId="16" Comment="fix indentation" Text="Ok guys, tricky one!&#xD;&#xA;&#xD;&#xA;I'm trying to modify [this](http://wiki.unity3d.com/index.php?title=MirrorReflection2) Unity script + shader to include normal mapping. The tl;dr is, it uses a single texture rather than a cubemap as it is only for reflecting in a planar surface. So it doesn't use the standard ray bounce onto an axis aligned cube. Instead it :&#xD;&#xA;&#xD;&#xA; - creates a reflection matrix from the plane (pos and normal)&#xD;&#xA; - reflects the camera position and view matrix through the plane&#xD;&#xA; - renders to texture from the reflected camera (with oblique near clipping plane set to cull everything behind the mirror)&#xD;&#xA; - creates a projection matrix and sends it as uniform to the shader (basically just a standard MVP matrix but with scale cancelled, and biased from [-1, 1] to [0, 1]&#xD;&#xA; - multiplies the object space coordinate by the projection matrix to get a texcoord and then looks up the mirror texture with this&#xD;&#xA;&#xD;&#xA;So there are no normals actually used in the shader at all at present. I know how to construct a TBN matrix and use this to warp the per-pixel normals, but I have no idea how this translates into a texture offset in this case. I have a feeling I might need screen-space normals like in the question [here](http://stackoverflow.com/questions/14317350/transform-world-space-normals-to-screen-space-normals) but pretty stumped beyond that. Any ideas?&#xD;&#xA;&#xD;&#xA;EDIT -- Here's the script&#xD;&#xA;&#xD;&#xA;    using UnityEngine;&#xD;&#xA;    using System.Collections;&#xD;&#xA;&#xD;&#xA;    [ExecuteInEditMode()]&#xD;&#xA;    public class PlanarRealtimeReflection : MonoBehaviour&#xD;&#xA;    {&#xD;&#xA;    	public bool m_DisablePixelLights = true;&#xD;&#xA;    	public int m_TextureResolution = 1024;&#xD;&#xA;    	public float m_clipPlaneOffset = 0.07f;&#xD;&#xA;    	private float m_finalClipPlaneOffset = 0.0f;&#xD;&#xA;    	public bool m_NormalsFromMesh = false;&#xD;&#xA;    	public bool m_BaseClipOffsetFromMesh = false;&#xD;&#xA;    	public bool m_BaseClipOffsetFromMeshInverted = false;&#xD;&#xA;    	private Vector3 m_calculatedNormal = Vector3.zero;&#xD;&#xA;        private Vector3 m_calculatedTangent = Vector4.zero;&#xD;&#xA;    	public LayerMask m_ReflectLayers = -1;&#xD;&#xA;    	&#xD;&#xA;    	private Hashtable m_ReflectionCameras = new Hashtable(); //Camera -&gt; Camera table&#xD;&#xA;    	&#xD;&#xA;    	private RenderTexture m_ReflectionTexture = null;&#xD;&#xA;    	private int m_OldReflectionTextureSize = 0;&#xD;&#xA;    	&#xD;&#xA;    	private static bool s_InsideRendering = false;&#xD;&#xA;    	&#xD;&#xA;    	//This is called when it's known that the object will be rendered by some&#xD;&#xA;    	//camera. We render reflections and do other updates here.&#xD;&#xA;    	//Because the script executes in edit mode, reflections for the scene view&#xD;&#xA;    	//camera will just work!&#xD;&#xA;    	public void OnWillRenderObject()&#xD;&#xA;    	{&#xD;&#xA;    		if(!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled)&#xD;&#xA;    			return;&#xD;&#xA;    &#xD;&#xA;    		Camera cam = Camera.current;&#xD;&#xA;    		if(!cam)&#xD;&#xA;    			return;&#xD;&#xA;    		&#xD;&#xA;    		if(m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;    			m_calculatedNormal = transform.TransformDirection(GetComponent&lt;MeshFilter&gt;().sharedMesh.normals[0]);&#xD;&#xA;                m_calculatedTangent = transform.TransformDirection(GetComponent&lt;MeshFilter&gt;().sharedMesh.tangents[0]);&#xD;&#xA;    		    &#xD;&#xA;    		if(m_BaseClipOffsetFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;    			m_finalClipPlaneOffset = (transform.position - transform.TransformPoint(GetComponent&lt;MeshFilter&gt;().sharedMesh.vertices[0])).magnitude + m_clipPlaneOffset;&#xD;&#xA;    		else if(m_BaseClipOffsetFromMeshInverted &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;    			m_finalClipPlaneOffset = -(transform.position - transform.TransformPoint(GetComponent&lt;MeshFilter&gt;().sharedMesh.vertices[0])).magnitude + m_clipPlaneOffset;&#xD;&#xA;    		else&#xD;&#xA;    			m_finalClipPlaneOffset = m_clipPlaneOffset;&#xD;&#xA;    		&#xD;&#xA;    		//Safeguard from recursive reflections.        &#xD;&#xA;    		if(s_InsideRendering)&#xD;&#xA;    			return;&#xD;&#xA;    		s_InsideRendering = true;&#xD;&#xA;    		&#xD;&#xA;    		Camera reflectionCamera;&#xD;&#xA;    		CreateSurfaceObjects(cam, out reflectionCamera);&#xD;&#xA;    		&#xD;&#xA;    		//Find out the reflection plane: position and normal in world space&#xD;&#xA;    		Vector3 pos = transform.position;&#xD;&#xA;    		Vector3 normal = m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null ? m_calculatedNormal : transform.up;&#xD;&#xA;            Vector3 tangent = m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null ? m_calculatedTangent : transform.right;&#xD;&#xA;            Vector3 bitangent = Vector3.Cross(normal, tangent);&#xD;&#xA;    &#xD;&#xA;    		//Optionally disable pixel lights for reflection&#xD;&#xA;    		int oldPixelLightCount = QualitySettings.pixelLightCount;&#xD;&#xA;    		if(m_DisablePixelLights)&#xD;&#xA;    			QualitySettings.pixelLightCount = 0;&#xD;&#xA;    		&#xD;&#xA;    		UpdateCameraModes(cam, reflectionCamera);&#xD;&#xA;    		&#xD;&#xA;    		//Render reflection&#xD;&#xA;    		//Reflect camera around reflection plane&#xD;&#xA;    		float d = -Vector3.Dot (normal, pos) - m_finalClipPlaneOffset;&#xD;&#xA;    		Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);&#xD;&#xA;    		Matrix4x4 reflection = Matrix4x4.zero;&#xD;&#xA;    		CalculateReflectionMatrix (ref reflection, reflectionPlane);&#xD;&#xA;    		Vector3 oldpos = cam.transform.position;&#xD;&#xA;    		Vector3 newpos = reflection.MultiplyPoint(oldpos);&#xD;&#xA;    		reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;&#xD;&#xA;    		&#xD;&#xA;    		//Setup oblique projection matrix so that near plane is our reflection plane.&#xD;&#xA;    		//This way we clip everything below/above it for free.&#xD;&#xA;    		Vector4 clipPlane = CameraSpacePlane(reflectionCamera, pos, normal, 1.0f);&#xD;&#xA;    		Matrix4x4 projection = cam.projectionMatrix;&#xD;&#xA;    		CalculateObliqueMatrix (ref projection, clipPlane);&#xD;&#xA;    		reflectionCamera.projectionMatrix = projection;&#xD;&#xA;    		&#xD;&#xA;    		reflectionCamera.cullingMask = ~(1&lt;&lt;4) &amp; m_ReflectLayers.value; //never render water layer&#xD;&#xA;    		reflectionCamera.targetTexture = m_ReflectionTexture;&#xD;&#xA;    		GL.SetRevertBackfacing (true);&#xD;&#xA;    		reflectionCamera.transform.position = newpos;&#xD;&#xA;    		//Vector3 euler = cam.transform.eulerAngles;&#xD;&#xA;            //reflectionCamera.transform.eulerAngles = euler; // new Vector3(0, euler.y, euler.z);&#xD;&#xA;    		reflectionCamera.Render();&#xD;&#xA;    		reflectionCamera.transform.position = oldpos;&#xD;&#xA;    		GL.SetRevertBackfacing (false);&#xD;&#xA;    		Material[] materials = renderer.sharedMaterials;&#xD;&#xA;    		foreach(Material mat in materials)&#xD;&#xA;    		{&#xD;&#xA;                if (mat.HasProperty(&quot;_ReflectionTex&quot;))  &#xD;&#xA;    				mat.SetTexture(&quot;_ReflectionTex&quot;, m_ReflectionTexture);&#xD;&#xA;                mat.SetVector(&quot;_Normal&quot;, new Vector4(normal.x,normal.y,normal.z,0));&#xD;&#xA;                mat.SetVector(&quot;_Tangent&quot;, new Vector4(tangent.x, tangent.y, tangent.z));&#xD;&#xA;                mat.SetVector(&quot;_Bitangent&quot;, new Vector4(bitangent.x, bitangent.y, bitangent.z));&#xD;&#xA;    		}&#xD;&#xA;    		&#xD;&#xA;    		//Set matrix on the shader that transforms UVs from object space into screen&#xD;&#xA;    		//space. We want to just project reflection texture on screen.&#xD;&#xA;    		Matrix4x4 scaleOffset = Matrix4x4.TRS(&#xD;&#xA;    			new Vector3(0.5f,0.5f,0.5f), Quaternion.identity, new Vector3(0.5f,0.5f,0.5f));&#xD;&#xA;    		Vector3 scale = transform.localScale;//.lossyScale;&#xD;&#xA;            Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z));&#xD;&#xA;            mtx = scaleOffset *  cam.projectionMatrix * cam.worldToCameraMatrix * mtx;&#xD;&#xA;    		foreach(Material mat in materials)&#xD;&#xA;    			mat.SetMatrix(&quot;_ProjMatrix&quot;, mtx);&#xD;&#xA;    		//Restore pixel light count&#xD;&#xA;    		if(m_DisablePixelLights)&#xD;&#xA;    			QualitySettings.pixelLightCount = oldPixelLightCount;&#xD;&#xA;    		&#xD;&#xA;    		s_InsideRendering = false;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	//Cleanup all the objects we possibly have created&#xD;&#xA;    	void OnDisable()&#xD;&#xA;    	{&#xD;&#xA;    		if(m_ReflectionTexture)&#xD;&#xA;    		{&#xD;&#xA;    			DestroyImmediate(m_ReflectionTexture);&#xD;&#xA;    			m_ReflectionTexture = null;&#xD;&#xA;    		}&#xD;&#xA;    		foreach(DictionaryEntry kvp in m_ReflectionCameras)&#xD;&#xA;    			DestroyImmediate(((Camera)kvp.Value).gameObject);&#xD;&#xA;    		m_ReflectionCameras.Clear();&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	private void UpdateCameraModes(Camera src, Camera dest)&#xD;&#xA;    	{&#xD;&#xA;    		if(dest == null)&#xD;&#xA;    			return;&#xD;&#xA;    		//set camera to clear the same way as current camera&#xD;&#xA;    		dest.clearFlags = src.clearFlags;&#xD;&#xA;    		dest.backgroundColor = src.backgroundColor;        &#xD;&#xA;    		if(src.clearFlags == CameraClearFlags.Skybox)&#xD;&#xA;    		{&#xD;&#xA;    			Skybox sky = src.GetComponent(typeof(Skybox)) as Skybox;&#xD;&#xA;    			Skybox mysky = dest.GetComponent(typeof(Skybox)) as Skybox;&#xD;&#xA;    			if(!sky || !sky.material)&#xD;&#xA;    			{&#xD;&#xA;    				mysky.enabled = false;&#xD;&#xA;    			}&#xD;&#xA;    			else&#xD;&#xA;    			{&#xD;&#xA;    				mysky.enabled = true;&#xD;&#xA;    				mysky.material = sky.material;&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    		//update other values to match current camera.&#xD;&#xA;    		//even if we are supplying custom camera&amp;projection matrices,&#xD;&#xA;    		//some of values are used elsewhere (e.g. skybox uses far plane)&#xD;&#xA;    		dest.farClipPlane = src.farClipPlane;&#xD;&#xA;    		dest.nearClipPlane = src.nearClipPlane;&#xD;&#xA;    		dest.orthographic = src.orthographic;&#xD;&#xA;    		dest.fieldOfView = src.fieldOfView;&#xD;&#xA;    		dest.aspect = src.aspect;&#xD;&#xA;    		dest.orthographicSize = src.orthographicSize;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//On-demand create any objects we need&#xD;&#xA;    	private void CreateSurfaceObjects(Camera currentCamera, out Camera reflectionCamera)&#xD;&#xA;    	{&#xD;&#xA;    		reflectionCamera = null;&#xD;&#xA;    		&#xD;&#xA;    		//Reflection render texture&#xD;&#xA;    		if(!m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureResolution)&#xD;&#xA;    		{&#xD;&#xA;    			if(m_ReflectionTexture)&#xD;&#xA;    				DestroyImmediate(m_ReflectionTexture);&#xD;&#xA;    			m_ReflectionTexture = new RenderTexture(m_TextureResolution, m_TextureResolution, 16);&#xD;&#xA;    			m_ReflectionTexture.name = &quot;__SurfaceReflection&quot; + GetInstanceID();&#xD;&#xA;    			m_ReflectionTexture.isPowerOfTwo = true;&#xD;&#xA;    			m_ReflectionTexture.hideFlags = HideFlags.DontSave;&#xD;&#xA;    			m_OldReflectionTextureSize = m_TextureResolution;&#xD;&#xA;    		}&#xD;&#xA;    		&#xD;&#xA;    		//Camera for reflection&#xD;&#xA;    		reflectionCamera = m_ReflectionCameras[currentCamera] as Camera;&#xD;&#xA;    		if(!reflectionCamera) //catch both not-in-dictionary and in-dictionary-but-deleted-GO&#xD;&#xA;    		{&#xD;&#xA;    			GameObject go = new GameObject(&quot;Surface Refl Camera id&quot; + GetInstanceID() + &quot; for &quot; + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox));&#xD;&#xA;    			reflectionCamera = go.camera;&#xD;&#xA;    			reflectionCamera.enabled = false;&#xD;&#xA;    			reflectionCamera.transform.position = transform.position;&#xD;&#xA;    			reflectionCamera.transform.rotation = transform.rotation;&#xD;&#xA;    			reflectionCamera.gameObject.AddComponent(&quot;FlareLayer&quot;);&#xD;&#xA;    			go.hideFlags = HideFlags.HideAndDontSave;&#xD;&#xA;    			m_ReflectionCameras[currentCamera] = reflectionCamera;&#xD;&#xA;    		}        &#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Extended sign: returns -1, 0 or 1 based on sign of a&#xD;&#xA;    	private static float sgn(float a)&#xD;&#xA;    	{&#xD;&#xA;    		if (a &gt; 0.0f) return 1.0f;&#xD;&#xA;    		if (a &lt; 0.0f) return -1.0f;&#xD;&#xA;    		return 0.0f;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Given position/normal of the plane, calculates plane in camera space.&#xD;&#xA;    	private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)&#xD;&#xA;    	{&#xD;&#xA;    		Vector3 offsetPos = pos + normal * m_finalClipPlaneOffset;&#xD;&#xA;    		Matrix4x4 m = cam.worldToCameraMatrix;&#xD;&#xA;    		Vector3 cpos = m.MultiplyPoint(offsetPos);&#xD;&#xA;    		Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;&#xD;&#xA;    		return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal));&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Adjusts the given projection matrix so that near plane is the given clipPlane&#xD;&#xA;    	//clipPlane is given in camera space. See article in Game Programming Gems 5 and&#xD;&#xA;    	//http://aras-p.info/texts/obliqueortho.html&#xD;&#xA;    	private static void CalculateObliqueMatrix (ref Matrix4x4 projection, Vector4 clipPlane)&#xD;&#xA;    	{&#xD;&#xA;    		Vector4 q = projection.inverse * new Vector4(&#xD;&#xA;    			sgn(clipPlane.x),&#xD;&#xA;    			sgn(clipPlane.y),&#xD;&#xA;    			1.0f,&#xD;&#xA;    			1.0f&#xD;&#xA;    			);&#xD;&#xA;    		Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlane, q)));&#xD;&#xA;    		//third row = clip plane - fourth row&#xD;&#xA;    		projection[2] = c.x - projection[3];&#xD;&#xA;    		projection[6] = c.y - projection[7];&#xD;&#xA;    		projection[10] = c.z - projection[11];&#xD;&#xA;    		projection[14] = c.w - projection[15];&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Calculates reflection matrix around the given plane&#xD;&#xA;    	private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)&#xD;&#xA;    	{&#xD;&#xA;    		reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);&#xD;&#xA;    		reflectionMat.m01 = (  - 2F*plane[0]*plane[1]);&#xD;&#xA;    		reflectionMat.m02 = (  - 2F*plane[0]*plane[2]);&#xD;&#xA;    		reflectionMat.m03 = (  - 2F*plane[3]*plane[0]);&#xD;&#xA;    		&#xD;&#xA;    		reflectionMat.m10 = (  - 2F*plane[1]*plane[0]);&#xD;&#xA;    		reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);&#xD;&#xA;    		reflectionMat.m12 = (  - 2F*plane[1]*plane[2]);&#xD;&#xA;    		reflectionMat.m13 = (  - 2F*plane[3]*plane[1]);&#xD;&#xA;    		&#xD;&#xA;    		reflectionMat.m20 = (  - 2F*plane[2]*plane[0]);&#xD;&#xA;    		reflectionMat.m21 = (  - 2F*plane[2]*plane[1]);&#xD;&#xA;    		reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);&#xD;&#xA;    		reflectionMat.m23 = (  - 2F*plane[3]*plane[2]);&#xD;&#xA;    		&#xD;&#xA;    		reflectionMat.m30 = 0F;&#xD;&#xA;    		reflectionMat.m31 = 0F;&#xD;&#xA;    		reflectionMat.m32 = 0F;&#xD;&#xA;    		reflectionMat.m33 = 1F;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the shader so far&#xD;&#xA;&#xD;&#xA;    Shader &quot;Realtime Reflections/New Shader&quot;&#xD;&#xA;    {&#xD;&#xA;        Properties {		&#xD;&#xA;            _MainAlpha(&quot;MainAlpha&quot;, Range(0, 1)) = 1&#xD;&#xA;    		_MapAmount(&quot;Distortion Amount&quot;, Range(0, 0.05)) = 0&#xD;&#xA;            _MainTex (&quot;Base (RGB) Gloss (A)&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;            _ReflectionTex (&quot;Reflection&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;    		_NormalMap (&quot;Normal Map&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;    		_RefColor(&quot;Color&quot;,Color) = (1,1,1,1)&#xD;&#xA;    	}&#xD;&#xA;    	SubShader {&#xD;&#xA;            Tags {&#xD;&#xA;                &quot;RenderType&quot;=&quot;Opaque&quot;}&#xD;&#xA;    		LOD 100&#xD;&#xA;    		Pass {&#xD;&#xA;                CGPROGRAM&#xD;&#xA;    			#pragma vertex vert&#xD;&#xA;    			#pragma fragment frag&#xD;&#xA;    			#include &quot;UnityCG.cginc&quot;&#xD;&#xA;    &#xD;&#xA;    			uniform float4x4	_ProjMatrix;&#xD;&#xA;    			uniform float		_RefType;&#xD;&#xA;    			uniform float4		_Normal;&#xD;&#xA;    			uniform float4		_Tangent;&#xD;&#xA;    			uniform float4		_Bitangent;&#xD;&#xA;                sampler2D			_ReflectionTex;&#xD;&#xA;    			sampler2D			_MainTex;&#xD;&#xA;    			sampler2D			_NormalMap;&#xD;&#xA;    			float4				_MainTex_ST;&#xD;&#xA;    			float4				_NormalMap_ST;       &#xD;&#xA;                float4				_RefColor;&#xD;&#xA;                float				_MainAlpha;&#xD;&#xA;    			float				_MapAmount;&#xD;&#xA;    &#xD;&#xA;                struct outvertex {&#xD;&#xA;                    float4 pos :		SV_POSITION;&#xD;&#xA;                    float2 colorUV :	TEXCOORD0;&#xD;&#xA;    				float2 bumpUV :		TEXCOORD1;&#xD;&#xA;    				float4 varyingPos : TEXCOORD2;&#xD;&#xA;                };&#xD;&#xA;                &#xD;&#xA;    			outvertex vert(appdata_full v) {&#xD;&#xA;    			&#xD;&#xA;                    outvertex o;&#xD;&#xA;                    o.pos = mul (UNITY_MATRIX_MVP,v.vertex);&#xD;&#xA;                    o.colorUV = TRANSFORM_TEX(v.texcoord.xy,_MainTex);&#xD;&#xA;    				o.bumpUV = TRANSFORM_TEX(v.texcoord1.xy,_NormalMap);&#xD;&#xA;    				o.varyingPos = v.vertex;	&#xD;&#xA;    				o. color = fixed4(mul(float3x3(UNITY_MATRIX_IT_MV),v.normal),1);&#xD;&#xA;    				return o;&#xD;&#xA;                }&#xD;&#xA;    										&#xD;&#xA;    			float4 frag(outvertex i) : COLOR {          &#xD;&#xA;    				float4 posProj = mul(_ProjMatrix, i.varyingPos);      &#xD;&#xA;    				float2 normPosProj = posProj.xy / posProj.w;&#xD;&#xA;    				float3 bump = (float3(tex2D(_NormalMap, i.bumpUV));&#xD;&#xA;    				//normPosProj += ?????????&#xD;&#xA;    				half4 flecol = tex2D(_ReflectionTex, normPosProj);	&#xD;&#xA;    				half4 maincol =  tex2D(_MainTex, i.colorUV);									&#xD;&#xA;    				half4 outcolor = half4(1,1,1,1);				&#xD;&#xA;    				outcolor = maincol*_MainAlpha+flecol*(1-_MainAlpha);&#xD;&#xA;                    return outcolor*_RefColor;&#xD;&#xA;                }&#xD;&#xA;    			ENDCG&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I had the idea to get the normal in screen space (so z is always toward camera) then simply find the delta between the regular normal and the warped one in x,y and use this as the texture offset, but I have no idea if this is feasible or how to do it." ContentLicense="CC BY-SA 3.0" />
  <row Id="4891" PostHistoryTypeId="2" PostId="2159" RevisionGUID="b2914e6a-5446-4d02-a562-30b680271d1b" CreationDate="2016-03-09T16:14:24.720" UserId="64" Text="There does not seem to be a single answer for this question, but I will try to give some directions in possible solutions. First of all I presume that &quot;the scene graph technique&quot; means storing the object data in some kind of data structure (I know what a scenegraph is, but there are many different possibilities for indoor/outdoor scenes etc). There seem to be some Javascript libraries, but they do much more then simply providing the datastructure.&#xD;&#xA;&#xD;&#xA;For defining the scenegraph structure you could look at glTF(https://github.com/KhronosGroup/glTF) defined by Khronos themselves. This really depends on what kind of features your scene graph requires.&#xD;&#xA;&#xD;&#xA;If the C++ library is required for the processing you can look into providing Javascript bindings for it. You can either try to compile the library to javascript using emscripten (https://github.com/kripken/emscripten). Otherwise provide a C-interface and call it directly using ccall(). This way you can directly share this datastructure via parameters." ContentLicense="CC BY-SA 3.0" />
  <row Id="4892" PostHistoryTypeId="2" PostId="2160" RevisionGUID="1920a51a-9664-49d3-9d76-8cbda25b7223" CreationDate="2016-03-09T18:34:38.510" UserId="2848" Text="Does anyone out there know of any software for developing real time visualisations and analysis of real time sound, say using a mike? I've found a few but none allow the user to build up their own visualisations.&#xD;&#xA;&#xD;&#xA;Thanks for any ideas, Jonathan" ContentLicense="CC BY-SA 3.0" />
  <row Id="4893" PostHistoryTypeId="1" PostId="2160" RevisionGUID="1920a51a-9664-49d3-9d76-8cbda25b7223" CreationDate="2016-03-09T18:34:38.510" UserId="2848" Text="live music visualisation" ContentLicense="CC BY-SA 3.0" />
  <row Id="4894" PostHistoryTypeId="3" PostId="2160" RevisionGUID="1920a51a-9664-49d3-9d76-8cbda25b7223" CreationDate="2016-03-09T18:34:38.510" UserId="2848" Text="|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4895" PostHistoryTypeId="5" PostId="2154" RevisionGUID="ef49c366-bb98-4ceb-b401-046f2bc1acec" CreationDate="2016-03-09T20:25:35.153" UserDisplayName="user2500" Comment="Added my case study." Text="Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control and the cost on more recent HW can vary. If you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. Your dynamic loop is a more amenable to developer intervention than a static loop - but leaving it to the compiler is still good advice unless you have a benchmark available. With a benchmark, exploration is worthwhile (and fun).&#xD;&#xA;&#xD;&#xA;BTW, the biggest loss with a dynamic loop on a GPU is that individual &quot;threads&quot; in a wavefront/warp will finish at different times. The threads that stop later force all the ones that finish early to execute NOPs. &#xD;&#xA;&#xD;&#xA;Nested loops should be carefully thought through: I implemented a block based entropy decoder that used encoded runs of zeros (for JPEG like compression). The natural implementation was to decode the runs in a tight inner loop - which meant often only one thread was making progress; by flattening the loop and explicitly testing in each thread if it was currently decoding a run, I kept all threads active through the fixed length loop (the decoded blocks were all the same size). If the threads were like CPU threads, the change would have been terrible, but on the GPU I was running on, I got a 6 fold increase in performance (which was still terrible - there weren't enough blocks to keep the GPU busy - but it was a proof of concept)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4896" PostHistoryTypeId="2" PostId="2161" RevisionGUID="c0d6419b-3736-437c-96fa-2835a1caf3da" CreationDate="2016-03-09T20:58:55.873" UserDisplayName="user2500" Text="Down the road, I'm planning to implement one or another GPU based ambient occlusion technique. My goal will be to approximate a physically based offline renderer, so I was pretty happy when Wikipedia led me to [Approximating Dynamic Global Illumination in Image Space][1], which describes SSDO. Based on the references, it looks to be from the 2008 era. Are there more modern approaches with similar accuracy goals?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://people.mpi-inf.mpg.de/~ritschel/Papers/SSDO.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="4897" PostHistoryTypeId="1" PostId="2161" RevisionGUID="c0d6419b-3736-437c-96fa-2835a1caf3da" CreationDate="2016-03-09T20:58:55.873" UserDisplayName="user2500" Text="Modern Screen Space Ambient Occlusion Techniques" ContentLicense="CC BY-SA 3.0" />
  <row Id="4898" PostHistoryTypeId="3" PostId="2161" RevisionGUID="c0d6419b-3736-437c-96fa-2835a1caf3da" CreationDate="2016-03-09T20:58:55.873" UserDisplayName="user2500" Text="|gpu|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4899" PostHistoryTypeId="5" PostId="2156" RevisionGUID="39e433b3-e4f1-4a5e-aaf0-63a5787d96c4" CreationDate="2016-03-09T21:19:12.457" UserId="2840" Comment="added 113 characters in body" Text="Resolved by adding `precision highp sampler2D` to my shaders.&#xD;&#xA;&#xD;&#xA;About default precision settings on ES - https://www.khronos.org/files/opengles_shading_language.pdf page 36." ContentLicense="CC BY-SA 3.0" />
  <row Id="4900" PostHistoryTypeId="2" PostId="2162" RevisionGUID="920a89f8-51d4-4643-9de5-f0dedc53f9b4" CreationDate="2016-03-09T22:28:11.673" UserId="48" Text="One tool I've seen people use for this sort of thing is [Processing](https://processing.org/), a Java-based language for real-time artsy stuff that supports graphics and audio. I haven't ever worked with it myself, but apparently it's pretty easy to use it for programming visualizations. [Here's an example](https://www.youtube.com/watch?v=a-Ht7d-tECY) of a simple visualization someone made; look in the video description for a link to their code&amp;mdash;it's quite short. Their example loads an mp3 file, but Processing also supports real-time input from a mic." ContentLicense="CC BY-SA 3.0" />
  <row Id="4901" PostHistoryTypeId="5" PostId="2154" RevisionGUID="f7636beb-96a6-45af-867b-d2b02fdd2cd6" CreationDate="2016-03-10T02:46:39.843" UserDisplayName="user2500" Comment="added 2 characters in body" Text="Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control and the cost on more recent HW can vary. If you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. Your dynamic loop is a more amenable to developer intervention than a static loop - but leaving it to the compiler is still good advice unless you have a benchmark available. With a benchmark, exploration is worthwhile (and fun).&#xD;&#xA;&#xD;&#xA;BTW, the biggest loss with a dynamic loop on a GPU is that individual &quot;threads&quot; in a wavefront/warp will finish at different times. The threads that stop later force all the ones that finish early to execute NOPs. &#xD;&#xA;&#xD;&#xA;Nested loops should be carefully thought through: I implemented a block based entropy decoder that encoded runs of zeros (for JPEG like compression). The natural implementation was to decode the runs in a tight inner loop - which meant often only one thread was making progress; by flattening the loop and explicitly testing in each thread if it was currently decoding a run or not, I kept all threads active through the fixed length loop (the decoded blocks were all the same size). If the threads were like CPU threads, the change would have been terrible, but on the GPU I was running on, I got a 6 fold increase in performance (which was still terrible - there weren't enough blocks to keep the GPU busy - but it was a proof of concept)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4903" PostHistoryTypeId="2" PostId="2163" RevisionGUID="3bc49f35-b17c-4697-9803-81388aa3f17e" CreationDate="2016-03-10T03:43:14.837" UserId="2853" Text="I've been searching in the internet for quite a while and i couldn't find any explanation or at least a how to create a vector graphic application (specifically in windows) where i can create a 3D vector shape , say a box. I know there is OpenGL and DirectX for that and the new Vulkan API but i don't wan't to use those API and library's. basically what i am asking is where can i find examples or at least tutorials for creating custom made API graphics library for the C++ language. If there is not a way in C++ language then any other way to do it. By example masm or nasm Assembly language.&#xD;&#xA;&#xD;&#xA;If my question is too broad please specifie any additional information you need to be able to answer my question .&#xD;&#xA;&#xD;&#xA;thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="4904" PostHistoryTypeId="1" PostId="2163" RevisionGUID="3bc49f35-b17c-4697-9803-81388aa3f17e" CreationDate="2016-03-10T03:43:14.837" UserId="2853" Text="creating vector shapes using only c++" ContentLicense="CC BY-SA 3.0" />
  <row Id="4905" PostHistoryTypeId="3" PostId="2163" RevisionGUID="3bc49f35-b17c-4697-9803-81388aa3f17e" CreationDate="2016-03-10T03:43:14.837" UserId="2853" Text="|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4906" PostHistoryTypeId="6" PostId="2163" RevisionGUID="a518eb49-14a3-4e7c-9657-b55a7aedcffa" CreationDate="2016-03-10T03:52:12.440" UserId="2853" Comment="edited tags" Text="|c++|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4907" PostHistoryTypeId="5" PostId="2152" RevisionGUID="399c9309-d410-4aef-9943-b7841c27e592" CreationDate="2016-03-10T09:11:45.747" UserId="2831" Comment="added note about potential impact on discrepancy" Text="&lt;strike&gt;The &quot;Uniform Mapping&quot; here is incorrect.  It does not transform to a uniform distribution on the sphere.&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;Very very bad me.  I misread the equation AND I didn't even consult my own reference [1], if I had I would have seen my mistake.&#xD;&#xA;&#xD;&#xA;Still the method from [2] is interesting and is described below.&#xD;&#xA;&#xD;&#xA;#Additional note:&#xD;&#xA;To map a uniform point set from the unit square to the sphere or half sphere requires an area-preserving map.  That will maintain the uniform property.  For pseudo-random that's sufficient (points are independent), however low-discrepancy point set will have its discrepancy measure effected by distortions in area introduced by the map.  I'm not aware of any references with respect to this point.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The method from [2] starts by mapping unit square to the unit disk.  One way we can do this is by using a rejection method.  Pseudo-code looks like this:&#xD;&#xA;&#xD;&#xA;    d = 0;&#xD;&#xA;&#xD;&#xA;    do {&#xD;&#xA;      p = uniform2d(...);  // [0,1) x [0,1)   given to be uniform&#xD;&#xA;      p = 2p;              // [0,2) x [0,2)   scaling (area-preserving)&#xD;&#xA;      p = p-1;             // (-1,1) x (-1,1) translating (area-preserving)&#xD;&#xA;      d = dot(p,p);        // is p in disk?&#xD;&#xA;    } while(d &gt;= 1);       //   if not rinse-and-repeat&#xD;&#xA;&#xD;&#xA;the area of the transformed square is $4$ and the unit disk is $\pi$, so the acceptance rate is $\frac{\pi }{4}$ (~.785) so on average requires $\frac{4}{\pi}$ (~1.273) iterations.&#xD;&#xA;&#xD;&#xA;Also non-rejection based methods exist, for example [3] which requires one square root and one trig operation. Note that the rejection method does not distort areas so the discrepancy measure remains the same.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Once we have $ p = \left(u_0, u_1 \right) $ uniformly distributed in the unit disk, we have:&#xD;&#xA;&#xD;&#xA;$$ u_0, u_1 \in \left(-1,1\right) $$&#xD;&#xA;$$ d = p\cdot p = u_0^2+u_1^2,\; d &lt; 1 $$&#xD;&#xA;&#xD;&#xA;then the transform to the sphere is:&#xD;&#xA;&#xD;&#xA;$$ s=2\sqrt{1-d} $$&#xD;&#xA;$$ p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, 1-2d\right\} $$&#xD;&#xA;&#xD;&#xA;or if you wanted a half-sphere, say positive Z, (just to state the obvious):&#xD;&#xA;&#xD;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, d\right\} $$&#xD;&#xA;&#xD;&#xA;There is a Stackexchange: Mathematics thread that discusses this method ([4],[5]).&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Also if you want to procedurally generate a LDS the additive recurrence formulation of the Weyl sequence is very cheap.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA;1. [Wolfram MathWorld: Sphere Point Picking](http://mathworld.wolfram.com/SpherePointPicking.html)&#xD;&#xA;2. &quot;Choosing a Point from the Surface of a Sphere.&quot;, George Marsaglia, 1972. \([PDF](http://projecteuclid.org/euclid.aoms/1177692644;))&#xD;&#xA;3. [Wolfram MathWorld: Disk Point Picking](http://mathworld.wolfram.com/DiskPointPicking.html)&#xD;&#xA;4. [SE Mathematics](http://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838336#838336)&#xD;&#xA;5. [SE Mathematics](http://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838882#838882)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4908" PostHistoryTypeId="5" PostId="2154" RevisionGUID="3df81e0c-99d6-4f11-89d3-e723a9a2a5f7" CreationDate="2016-03-10T11:49:50.090" UserDisplayName="user2500" Comment="deleted 2 characters in body" Text="Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control and the cost on more recent HW can vary. If you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. Your dynamic loop is more amenable to developer intervention than a static loop - but leaving it to the compiler is still good advice unless you have a benchmark available. With a benchmark, exploration is worthwhile (and fun).&#xD;&#xA;&#xD;&#xA;BTW, the biggest loss with a dynamic loop on a GPU is that individual &quot;threads&quot; in a wavefront/warp will finish at different times. The threads that stop later force all the ones that finish early to execute NOPs. &#xD;&#xA;&#xD;&#xA;Nested loops should be carefully thought through: I implemented a block based entropy decoder that encoded runs of zeros (for JPEG like compression). The natural implementation was to decode the runs in a tight inner loop - which meant often only one thread was making progress; by flattening the loop and explicitly testing in each thread if it was currently decoding a run or not, I kept all threads active through the fixed length loop (the decoded blocks were all the same size). If the threads were like CPU threads, the change would have been terrible, but on the GPU I was running on, I got a 6 fold increase in performance (which was still terrible - there weren't enough blocks to keep the GPU busy - but it was a proof of concept)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4909" PostHistoryTypeId="10" PostId="2160" RevisionGUID="968d3a37-96b7-4bed-b860-bf17d69bcbd9" CreationDate="2016-03-10T12:38:25.227" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4910" PostHistoryTypeId="11" PostId="2160" RevisionGUID="1eddf42e-6e30-4e17-9b18-d1a34a54e3df" CreationDate="2016-03-10T12:40:46.837" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4911" PostHistoryTypeId="2" PostId="2164" RevisionGUID="caf37520-192a-4246-a41c-7e18ee0b57d7" CreationDate="2016-03-10T12:44:09.337" UserId="2855" Text="I'm new to graphics and want to implement algorithms like dda,scan-line, clipping,etc. I'm confused which library to use. OpenGl, graphics in turbo c,or any other. Please suggest." ContentLicense="CC BY-SA 3.0" />
  <row Id="4912" PostHistoryTypeId="1" PostId="2164" RevisionGUID="caf37520-192a-4246-a41c-7e18ee0b57d7" CreationDate="2016-03-10T12:44:09.337" UserId="2855" Text="library / tool for implementing algorithms" ContentLicense="CC BY-SA 3.0" />
  <row Id="4913" PostHistoryTypeId="3" PostId="2164" RevisionGUID="caf37520-192a-4246-a41c-7e18ee0b57d7" CreationDate="2016-03-10T12:44:09.337" UserId="2855" Text="|opengl|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4914" PostHistoryTypeId="2" PostId="2165" RevisionGUID="55774071-a052-489c-9233-56f2ab7df8a0" CreationDate="2016-03-10T13:05:29.447" UserId="1937" Text="If you're completely new to graphics programming I would start with Processing. It's based on Java and JOGL but comes with a whole bunch of drawing commands built in, and its own basic IDE. It's very good for prototyping algorithms and getting quick visual feedback without having to write a ton of boilerplate code, and it insulates you from the underlying API (OpenGL in this case). Presumably you're not going for high performance, since the algorithms you mention are efficiently implemented in hardware, and you just want to familiarize yourself with how they work? If so it's a great place to start.&#xD;&#xA;&#xD;&#xA;Once you've got the hang of Processing you can move over to OpenFrameworks, which is very similar but in C++, with the option to 'drill down' and call the underlying OpenGL commands directly. From there, the sky's the limit. :-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4915" PostHistoryTypeId="2" PostId="2166" RevisionGUID="388bda09-e0f8-4e95-867c-b26199d47213" CreationDate="2016-03-10T14:09:49.317" UserId="56" Text="I know that if you turn of vsync, it synchronizes rendering with the vertical redraw cycle to prevent tearing, and that doing so caps your rendering rate (FPS) at the monitor refresh rate, which is commonly 60hz / 60 fps, although other rates exist as well.&#xD;&#xA;&#xD;&#xA;However, when you are not running at a full 60fps how does vsync affect your frame rate?  I've heard people say that you will be limited to a multiple of 60fps (well, ~16ms to be precise), but from observation, fps can fluctuate wildly." ContentLicense="CC BY-SA 3.0" />
  <row Id="4916" PostHistoryTypeId="1" PostId="2166" RevisionGUID="388bda09-e0f8-4e95-867c-b26199d47213" CreationDate="2016-03-10T14:09:49.317" UserId="56" Text="How does vsync affect fps exactly when not at full vsync fps?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4917" PostHistoryTypeId="3" PostId="2166" RevisionGUID="388bda09-e0f8-4e95-867c-b26199d47213" CreationDate="2016-03-10T14:09:49.317" UserId="56" Text="|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4918" PostHistoryTypeId="2" PostId="2167" RevisionGUID="254bd6f5-0817-4f45-a67b-776378ab9d5a" CreationDate="2016-03-10T14:17:37.640" UserId="56" Text="A signed distance field texture is a technique where you store the distance from a pixel to the surface of a shape within the color information for that pixel, allowing almost vector graphics quality rendering using textures (http://blog.demofox.org/2014/06/30/distance-field-textures/)&#xD;&#xA;&#xD;&#xA;When reading the texture data in a shader, you get values between 0 and 1, which is meant to map between -1 and 1.&#xD;&#xA;&#xD;&#xA;The distance data is essentially &quot;normalized&quot; when creating the shader, which means that instead of storing a true positive or negative distance value in the texture, you instead multiply (divide) the real distance by some constant value, clamp it to be between 0 and 1 and then store that distance value.&#xD;&#xA;&#xD;&#xA;That constant value essentially controls the width in pixels of the &quot;gradient&quot; band, where the surface of the shape goes from 0 to 1 (-1 to 1).&#xD;&#xA;&#xD;&#xA;Is there an optimal value for this based on the output texture resolution or anything else?  I always use trial and error until it looks right but feel there must be a better way.&#xD;&#xA;&#xD;&#xA;Also, is there a way to choose an optimal output texture size?  Or should you just always use a texture size smaller than the size you intend to render it at?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="4919" PostHistoryTypeId="1" PostId="2167" RevisionGUID="254bd6f5-0817-4f45-a67b-776378ab9d5a" CreationDate="2016-03-10T14:17:37.640" UserId="56" Text="Choosing width of data for signed distance field texture" ContentLicense="CC BY-SA 3.0" />
  <row Id="4920" PostHistoryTypeId="3" PostId="2167" RevisionGUID="254bd6f5-0817-4f45-a67b-776378ab9d5a" CreationDate="2016-03-10T14:17:37.640" UserId="56" Text="|texture|2d|signed-distance-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4921" PostHistoryTypeId="2" PostId="2168" RevisionGUID="4b6e2078-3afc-462d-b541-129e9613bf46" CreationDate="2016-03-10T14:17:41.987" UserId="137" Text="It depends on how a missed frame is handled by the driver.&#xD;&#xA;&#xD;&#xA;One option is to just wait until the next vsync, causing a hitch of 32 ms and if the application is just at the limit of 16 ms can cause fluctuations.&#xD;&#xA;&#xD;&#xA;The next option is to queue the frame for display next frame but don't wait on it. This will still cause a visual hitch but the application can then immediately start on the next frame instead of being forced to wait 16 ms. If the next frame is done faster then the late frame may even never be shown. &#xD;&#xA;&#xD;&#xA;The final option is to not block and push the late frame to the display immediately which can cause tearing." ContentLicense="CC BY-SA 3.0" />
  <row Id="4927" PostHistoryTypeId="5" PostId="2133" RevisionGUID="a4a7f4db-a57f-460d-b331-3d85d7ead2f0" CreationDate="2016-03-11T15:10:33.287" UserId="1937" Comment="added 116 characters in body" Text="I'm aware that most modern GPUs, although designed for floating point, are more or less equivalent in integer performance these days, with a few caveats like the lack of a fused multiply add. I'm not sure how this applies to shift operations though. I'm doing Marching Cubes on GPU, initially writing out a 32-bit packed position for each surface cube then unpacking these in a later pass to the actual vertices in that cube, like this : &#xD;&#xA;    &#xD;&#xA;    ivec3 unpackedPos = ivec3( packedPos &gt;&gt; 20 &amp; 0x3FF,&#xD;&#xA;                             packedPos &gt;&gt; 10 &amp; 0x3FF,&#xD;&#xA;                             packedPos &amp; 0x3FF);&#xD;&#xA;&#xD;&#xA;It just occurred to me to wonder if shader units have barrel shifters in them these days? Am I doing 2 shifts here or 30?&#xD;&#xA;&#xD;&#xA;EDIT&gt;&gt;&#xD;&#xA;I'm an idiot... Thanks for the answers guys, useful to know, but I've been going about this all wrong. I should just be using the RGB10_A2UI texture format then packing/ unpacking with a single image load/store instruction instead of messing around with bitshifts myself. &#xD;&#xA;&#xD;&#xA;RE_EDIT&gt;&gt; Or not... This method apparently works on red boxes but not on green ones, so it's back to bit-shifts." ContentLicense="CC BY-SA 3.0" />
  <row Id="4928" PostHistoryTypeId="2" PostId="2170" RevisionGUID="067e35fc-64f2-46c1-9db7-916892a05ad6" CreationDate="2016-03-11T17:56:09.000" UserId="2863" Text="I have a convoluted polyline composed of vertices and straight segments and a separate point that is independent of the polyline. I am trying draw a straight new line from the point at a given angle and determine if the new line intersects the polyline and get the location of that intersection. If there are multiple intersections I want the location of the closest intersection. &#xD;&#xA;&#xD;&#xA;I'm currently doing this by drawing a line an arbitrary (long) distance from the point at the desired angle and then intersecting it with the polyline using a python gis toolkit (shapely). If there are multiple intersections I sort them by distance and select the closest one. &#xD;&#xA;&#xD;&#xA;This method works but is somewhat clumsy. Is there a more efficient method of calculating the closest intersection? It almost seems like ray tracing (of which I have minimal knowledge) but I can't find much online that applies to my case. " ContentLicense="CC BY-SA 3.0" />
  <row Id="4929" PostHistoryTypeId="1" PostId="2170" RevisionGUID="067e35fc-64f2-46c1-9db7-916892a05ad6" CreationDate="2016-03-11T17:56:09.000" UserId="2863" Text="Calculating intersection of polyline and line" ContentLicense="CC BY-SA 3.0" />
  <row Id="4930" PostHistoryTypeId="3" PostId="2170" RevisionGUID="067e35fc-64f2-46c1-9db7-916892a05ad6" CreationDate="2016-03-11T17:56:09.000" UserId="2863" Text="|geometry|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4931" PostHistoryTypeId="5" PostId="2170" RevisionGUID="a24a02f8-5f2e-40f8-ab82-4010c73a37d2" CreationDate="2016-03-11T18:30:49.033" UserId="2863" Comment="added 353 characters in body" Text="I have a convoluted polyline composed of vertices and straight segments and a separate point that is independent of the polyline. I am trying draw a straight new line from the point at a given angle and determine if the new line intersects the polyline and get the location of that intersection. If there are multiple intersections I want the location of the closest intersection. &#xD;&#xA;&#xD;&#xA;I'm currently doing this by drawing a line an arbitrary (long) distance from the point at the desired angle and then intersecting it with the polyline using a python gis toolkit (shapely). If there are multiple intersections I sort them by distance and select the closest one. &#xD;&#xA;&#xD;&#xA;This method works but is somewhat clumsy. Is there a more efficient method of calculating the closest intersection? It almost seems like ray tracing (of which I have minimal knowledge) but I can't find much online that applies to my case. &#xD;&#xA;&#xD;&#xA;The other method that I contemplated was to iterate over every line segment in the polyline and use y = mx+b to see if the segment intersects the new line from the point. The polyline is potentially quite long with many segments, but I've also seen some sorting tricks online to make this method more efficient. Is there a method that I'm missing?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4935" PostHistoryTypeId="2" PostId="2172" RevisionGUID="378a85e0-456c-41d8-96fc-3c601e60e1c9" CreationDate="2016-03-11T21:16:34.320" UserId="2865" Text="Does anyone know if there is an app / library / algorithm that can reliably classify / search for photographic vs. non-photographic (hand-drawn or computer-made art, etc.) images?&#xD;&#xA;&#xD;&#xA;I've been able to find some stuff on GitHub, but it all is geared towards finding similar images or images with similar general features (e.g. a lot of one color)." ContentLicense="CC BY-SA 3.0" />
  <row Id="4936" PostHistoryTypeId="1" PostId="2172" RevisionGUID="378a85e0-456c-41d8-96fc-3c601e60e1c9" CreationDate="2016-03-11T21:16:34.320" UserId="2865" Text="Separating photos from other images algorithmically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4937" PostHistoryTypeId="3" PostId="2172" RevisionGUID="378a85e0-456c-41d8-96fc-3c601e60e1c9" CreationDate="2016-03-11T21:16:34.320" UserId="2865" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4939" PostHistoryTypeId="2" PostId="2173" RevisionGUID="92d4caaf-e2a1-4d09-b6c6-c33a8dc07194" CreationDate="2016-03-12T00:10:18.600" UserId="48" Text="The motivation behind ambient occlusion (AO) in general is to approximate the way crevices and corners are often shadowed, because less indirect light bounces into them. An example from a photo of my office&amp;mdash;note the darkening along the edges where walls and ceiling meet. The room is lit only by the light coming in through the window and bouncing around.&#xD;&#xA;&#xD;&#xA;[![photo demonstrating AO-like effect in the corner of a room][1]][1]&#xD;&#xA;&#xD;&#xA;To accurately simulate this phenomenon, offline renderers use techniques like path tracing and photon mapping. For real-time purposes, we either precalculate it offline, or we approximate it somehow.&#xD;&#xA;&#xD;&#xA;Screen-space ambient occlusion (SSAO) is based on the observation that you can detect corners and crevices by looking at the depth buffer (and possibly also the normal vectors) of a rendered image, and so you can calculate approximate AO as a post-pass. The depth buffer is a coarse representation of the geometry in the scene, so by sampling depth buffer values in the neighborhood of a target pixel, you can get an idea of the shape of the surrounding geometry, and make a guess how darkened by AO it should be.&#xD;&#xA;&#xD;&#xA;[![diagram of how depth buffer represents geometry, from Bavoil and Sainz (2008)][2]][2]&#xD;&#xA;&#xD;&#xA;This diagram, from [Bavoil and Sainz (2008)](http://developer.download.nvidia.com/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf), shows how depth buffer values, interpreted as a heightfield of sorts, represent a discretized version of some geometry. In calculating SSAO for the center pixel, you'd look at the depth values of the surrounding pixels and plug them into some formula, designed to produce a darker value when the geometry is more concave (like that in the diagram), and a lighter value when the geometry is flat or convex.&#xD;&#xA;&#xD;&#xA;The formula that the depth values go into is called the &quot;kernel&quot; by analogy with [filter kernels](https://en.wikipedia.org/wiki/Kernel_%28image_processing%29) used for blurs, edge detection and suchlike. However, SSAO is more complicated than just a linear convolution of the depth values. The devil is in the details. The distribution of samples, and the formula processing them to generate the occlusion value, has been the subject of much research over the last decade, trying to improve the realism and reduce artifacts while maintaining good performance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1JZDi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/qFOoX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4940" PostHistoryTypeId="2" PostId="2174" RevisionGUID="26b91a46-ea31-491c-a6dd-55ba4b86223e" CreationDate="2016-03-12T00:13:16.267" UserId="1810" Text="Difficulty depends on what you really want to classify, i.e. what exactly your data base of images is made ok.&#xD;&#xA;For simple hand-drawn or computer art, I would think of just looking the color histogram (but for complex art with gradients; but still these gradients are likely to induce a very smooth colormap).&#xD;&#xA;&#xD;&#xA;At the other extreme, distinguishing realistic computer graphics image from reality is probably impossible." ContentLicense="CC BY-SA 3.0" />
  <row Id="4941" PostHistoryTypeId="2" PostId="2175" RevisionGUID="a7bd53ec-c647-4ac4-99aa-825eb3eae5d3" CreationDate="2016-03-12T02:40:28.083" UserId="48" Text="In order to ensure that the pattern shapes are always either wholly present or absent, never cut off, it's necessary to ensure that the same `p` value is used for all texels within the shape. In your example of circles, all the texels in a given circle need to agree on `p`.&#xD;&#xA;&#xD;&#xA;I assume that you have some way of evaluating `p` at a given point on the surface (whether it is looked up from a texture or calculated from some function). Then one way to ensure a group of texels all get the same `p` value is to ensure they all look it up from the same point.&#xD;&#xA;&#xD;&#xA;The UVs of this evaluation point could be stored in extra channels of the pattern texture. For instance, you could have the red and green channels store the UV coordinates at which to evaluate `p`, the blue channel store the threshold at which to turn on that pattern element, and the alpha store the antialiased gray level of the pattern to display. The UV+threshold data could also be in a separate, secondary texture if desired.&#xD;&#xA;&#xD;&#xA;To generate this UV+threshold texture, starting from an input pattern texture, you could programmatically find connected components (e.g. by searching for black pixels and flood-filling). Set the evaluation point for all texels in each component to the UV of the component's center, and generate a random threshold for it. Then, when rendering, use a pixel shader that first samples this texture, then looks up `p` at the given evaluation point and compares it to the given threshold.&#xD;&#xA;&#xD;&#xA;That way, each pattern shape will see a uniform `p` value and threshold, and will either turn on or turn off fully. As `p` increases, more of the shapes will pass their threshold and appear, giving the impression of a continuously varying density." ContentLicense="CC BY-SA 3.0" />
  <row Id="4942" PostHistoryTypeId="10" PostId="2172" RevisionGUID="216584d2-545f-4357-b193-766293a09070" CreationDate="2016-03-12T11:28:35.130" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4946" PostHistoryTypeId="10" PostId="2135" RevisionGUID="6c4a77f0-bd39-4123-b6f3-cd3cc4922f70" CreationDate="2016-03-12T11:39:19.993" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4947" PostHistoryTypeId="10" PostId="1983" RevisionGUID="64cc110e-bffc-42b5-a516-d71e4d322661" CreationDate="2016-03-12T11:50:43.840" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4948" PostHistoryTypeId="10" PostId="1758" RevisionGUID="e9ca42d9-55d5-4d92-9cd4-46668d2f996f" CreationDate="2016-03-12T12:23:42.047" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="4949" PostHistoryTypeId="2" PostId="2176" RevisionGUID="4dc8f3c1-4412-4056-a88d-0815c314dea5" CreationDate="2016-03-12T20:11:20.327" UserId="56" Text="What you are looking for is a way to get access to individual pixels in an image, in a way that you can modify those pixels with CPU code.&#xA;&#xA;Once you have that you'll want to find software rendering / software rasterization methods.&#xA;&#xA;A great place to start would be reading up in the various bresenham algorithms.&#xA;&#xA;There is a lot of info out there on that. Here is one article for instance:&#xA;http://blog.demofox.org/2015/01/17/bresenhams-drawing-algorithms/" ContentLicense="CC BY-SA 3.0" />
  <row Id="4950" PostHistoryTypeId="2" PostId="2177" RevisionGUID="73d58ba7-4150-439f-a1f7-ddfcc125d19d" CreationDate="2016-03-13T08:09:05.523" UserId="48" Text="Given that you want to test for intersection against rays with many different starting points and directions, it's worth investigating raytracing-style acceleration structures, such as the [bounding volume hierarchy (BVH)](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy). In 2D, this would look like a tree of axis-aligned bounding boxes that divide up the space. Each leaf node of this tree would store a reference to a small list of nearby segments of the polyline, as well as a bounding box that contains them. Higher nodes would store a bounding box that contains all their children.&#xD;&#xA;&#xD;&#xA;There's a ton of material on BVH construction and traversal out there, so I'd recommend doing a few searches and reading up. It's not too difficult to implement a top-down construction method, by starting with the bounding box of the whole polyline and recursive splitting. Then, to use it for acceleration, when you do a ray query you can find which BVH nodes the ray touches and test only the segments in those nodes for intersections.&#xD;&#xA;&#xD;&#xA;However, all that being said, I'd like to propose a different approach to your original problem of working with contour lines. It seems to me that this is a place where [Delaunay triangulation](https://en.wikipedia.org/wiki/Delaunay_triangulation) can probably be very helpful. It basically constructs a triangle mesh that connects a set of input vertices and edges. For example, here is a contour map I found on the internet:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And now here it is with a constrained Delaunay triangulation, calculating using [Jonathan Shewchuk's &quot;Triangle&quot; program](https://www.cs.cmu.edu/~quake/triangle.html):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the triangulation gives you a lot of information about neighboring regions in the contour map, so I suspect that you could find a way to get what you want from it somehow. For instance, you could find all the triangles that touch the two contour lines you're interested in, and look at their edges, midpoints, and so on.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nEET2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EElJb.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="4951" PostHistoryTypeId="2" PostId="2178" RevisionGUID="0ec910f1-32f8-4461-a612-086f834efc60" CreationDate="2016-03-13T11:40:41.090" UserId="2096" Text="I was trying to draw a plane and cubes in a framebuffer but nothing is drawing in that framebuffer besides clearing it with a color.&#xD;&#xA;Here's the code...&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    //C++ Headers&#xD;&#xA;    #include&lt;cassert&gt;&#xD;&#xA;&#xD;&#xA;    //Third party Headers&#xD;&#xA;    #include&lt;GL/glew.h&gt;&#xD;&#xA;    #include&lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include&lt;SOIL.h&gt;&#xD;&#xA;&#xD;&#xA;    //My Headers&#xD;&#xA;    #include&quot;SLMath/SLMath.hpp&quot;&#xD;&#xA;    #include&quot;GLOBALS.h&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //Author Headers&#xD;&#xA;    #include&quot;Shader.h&quot;&#xD;&#xA;    #include&quot;Texture.h&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //linking libraries&#xD;&#xA;&#xD;&#xA;    #pragma comment(lib,&quot;OpenGL32.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;glfw3.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;glew32.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;SOIL.lib&quot;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;  	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_SAMPLES,4);&#xD;&#xA;	&#xD;&#xA;	GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, &quot;fUNKY CUBE&quot;, 0, 0);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;&#xD;&#xA;	glfwSetKeyCallback(window, keyCallback);&#xD;&#xA;	&#xD;&#xA;	assert(glGetError()!=GL_NO_ERROR);&#xD;&#xA;&#xD;&#xA;	glGenVertexArrays(1,&amp;VAOplane);&#xD;&#xA;	glGenVertexArrays(1,&amp;VAOcube);&#xD;&#xA;	glGenVertexArrays(1,&amp;VAOquad);&#xD;&#xA;	glGenBuffers(1,&amp;VBOplane);&#xD;&#xA;	glGenBuffers(1,&amp;VBOcube);&#xD;&#xA;	glGenBuffers(1, &amp;VBOquad);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER,VBOplane);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER,sizeof(plane),plane,GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER,VBOcube);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER,sizeof(cube),cube,GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER,VBOquad);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER,sizeof(quad),quad,GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(VAOplane);&#xD;&#xA;	{&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER,VBOplane);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*5,(GLvoid*)(0));&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;		glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*5,(GLvoid*)(sizeof(GLfloat)*3));&#xD;&#xA;	}&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(VAOcube);&#xD;&#xA;	{&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER,VBOcube);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*8,(GLvoid*)(0));&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;		glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*8,(GLvoid*)(sizeof(GLfloat)*6));&#xD;&#xA;	}&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(VAOquad);&#xD;&#xA;	{&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER, VBOquad);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*)(0));&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*)(sizeof(GLfloat) * 2));&#xD;&#xA;	}&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	/*Setting up framebuffer*/&#xD;&#xA;&#xD;&#xA;	GLuint fbo;&#xD;&#xA;	glGenFramebuffers(1,&amp;fbo);&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER,fbo);&#xD;&#xA;	&#xD;&#xA;	//Our color attachement&#xD;&#xA;	GLuint texColorBuffer;&#xD;&#xA;	glGenTextures(1,&amp;texColorBuffer);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D,texColorBuffer);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D,0);&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texColorBuffer,0);&#xD;&#xA;&#xD;&#xA;	//our depth attachment&#xD;&#xA;	GLuint depthRenderbuffer;&#xD;&#xA;	glGenRenderbuffers(1,&amp;depthRenderbuffer);&#xD;&#xA;	glBindRenderbuffer(GL_RENDERBUFFER,depthRenderbuffer);&#xD;&#xA;	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WIDTH, HEIGHT);&#xD;&#xA;	glBindRenderbuffer(GL_RENDERBUFFER,0);&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_RENDERBUFFER,depthRenderbuffer);&#xD;&#xA;&#xD;&#xA;	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)&#xD;&#xA;		assert(0);&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER,0);&#xD;&#xA;	&#xD;&#xA;	glViewport(0,0,WIDTH,HEIGHT);&#xD;&#xA;&#xD;&#xA;	Texture floorTex(&quot;textures/floortexture1.jpg&quot;);&#xD;&#xA;	Texture cubeTex(&quot;textures/cubetexture1.jpg&quot;);&#xD;&#xA;	&#xD;&#xA;	Shader shader(&quot;vs.txt&quot;,&quot;fs.txt&quot;);&#xD;&#xA;	Shader shader2(&quot;vs2.txt&quot;,&quot;fs2.txt&quot;);&#xD;&#xA;&#xD;&#xA;	//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);&#xD;&#xA;&#xD;&#xA;	while(!glfwWindowShouldClose(window))&#xD;&#xA;	{&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;		glBindFramebuffer(GL_FRAMEBUFFER, fbo);&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;		glClearColor(0.1,0.0,0.0,0.0);&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;		glEnable(GL_DEPTH_TEST);&#xD;&#xA;		//float radius = 5.0f;&#xD;&#xA;		//cameraPos.z = cos(SLMath::radians(glfwGetTime()*30.0f))*radius;&#xD;&#xA;		//cameraPos.x = sin(SLMath::radians(glfwGetTime()*30.0f))*radius;&#xD;&#xA;		&#xD;&#xA;		SLMath::Mat4 projection;&#xD;&#xA;		SLMath::Mat4 view;&#xD;&#xA;		SLMath::Mat4 model;&#xD;&#xA;&#xD;&#xA;		GLint projLoc = glGetUniformLocation(shader.program,&quot;projection&quot;);&#xD;&#xA;		GLint viewLoc = glGetUniformLocation(shader.program,&quot;view&quot;);&#xD;&#xA;		GLint modelLoc = glGetUniformLocation(shader.program,&quot;model&quot;);&#xD;&#xA;&#xD;&#xA;		SLMath::perspective(projection,45.0f,(float)WIDTH/(float)HEIGHT,0.1f,100.0f);&#xD;&#xA;		SLMath::lookAt(view,cameraPos,cameraDir,cameraUp);&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(projLoc,1,GL_FALSE,projection.valuePtr());&#xD;&#xA;		glUniformMatrix4fv(viewLoc,1,GL_FALSE,view.valuePtr());&#xD;&#xA;		glUniformMatrix4fv(modelLoc,1,GL_FALSE,model.valuePtr());&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;		floorTex.bind();&#xD;&#xA;		shader.Use();&#xD;&#xA;		glBindVertexArray(VAOplane);&#xD;&#xA;		glDrawArrays(GL_TRIANGLES,0,6);&#xD;&#xA;		glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;		cubeTex.bind();&#xD;&#xA;&#xD;&#xA;		for(int i=0;i&lt;3;i++)&#xD;&#xA;		{&#xD;&#xA;			model.reset();&#xD;&#xA;			SLMath::translate(model,cubePositions[i]);&#xD;&#xA;			glUniformMatrix4fv(modelLoc,1,GL_FALSE,model.valuePtr());&#xD;&#xA;		&#xD;&#xA;			glBindVertexArray(VAOcube);&#xD;&#xA;			glDrawArrays(GL_TRIANGLES,0,36);&#xD;&#xA;			glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		glBindFramebuffer(GL_FRAMEBUFFER,0);&#xD;&#xA;&#xD;&#xA;		glClearColor(1.0f,1.0f,1.0f,1.0);&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;		glDisable(GL_DEPTH_TEST);&#xD;&#xA;		&#xD;&#xA;		shader2.Use();&#xD;&#xA;		glBindTexture(GL_TEXTURE_2D, texColorBuffer);&#xD;&#xA;		glBindVertexArray(VAOquad);&#xD;&#xA;		glDrawArrays(GL_TRIANGLES,0,6);&#xD;&#xA;		glBindVertexArray(0);&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;		glfwSwapBuffers(window);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	glDeleteBuffers(1, &amp;VBOquad);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBOcube);&#xD;&#xA;	glDeleteBuffers(1,&amp;VBOplane);&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAOquad);&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAOcube);&#xD;&#xA;	glDeleteVertexArrays(1,&amp;VAOplane);&#xD;&#xA;	glfwDestroyWindow(window);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;	exit(EXIT_SUCCESS);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Why is it happening?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4952" PostHistoryTypeId="1" PostId="2178" RevisionGUID="0ec910f1-32f8-4461-a612-086f834efc60" CreationDate="2016-03-13T11:40:41.090" UserId="2096" Text="Clearing framebuffer but now drawing objects" ContentLicense="CC BY-SA 3.0" />
  <row Id="4953" PostHistoryTypeId="3" PostId="2178" RevisionGUID="0ec910f1-32f8-4461-a612-086f834efc60" CreationDate="2016-03-13T11:40:41.090" UserId="2096" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4954" PostHistoryTypeId="5" PostId="2178" RevisionGUID="8afe1534-01c6-423d-8e2e-dd40b0ef955c" CreationDate="2016-03-13T11:47:12.167" UserId="2096" Comment="added 259 characters in body" Text="I was trying to draw a plane and cubes in a framebuffer but nothing is drawing in that framebuffer besides clearing it with a color.&#xD;&#xA;Here's the code...&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    //C++ Headers&#xD;&#xA;    #include&lt;cassert&gt;&#xD;&#xA;&#xD;&#xA;    //Third party Headers&#xD;&#xA;    #include&lt;GL/glew.h&gt;&#xD;&#xA;    #include&lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include&lt;SOIL.h&gt;&#xD;&#xA;&#xD;&#xA;    //My Headers&#xD;&#xA;    #include&quot;SLMath/SLMath.hpp&quot;&#xD;&#xA;    #include&quot;GLOBALS.h&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //Author Headers&#xD;&#xA;    #include&quot;Shader.h&quot;&#xD;&#xA;    #include&quot;Texture.h&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //linking libraries&#xD;&#xA;&#xD;&#xA;    #pragma comment(lib,&quot;OpenGL32.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;glfw3.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;glew32.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;SOIL.lib&quot;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;  	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_SAMPLES,4);&#xD;&#xA;	&#xD;&#xA;	GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, &quot;fUNKY CUBE&quot;, 0, 0);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;&#xD;&#xA;	glfwSetKeyCallback(window, keyCallback);&#xD;&#xA;	&#xD;&#xA;	assert(glGetError()!=GL_NO_ERROR);&#xD;&#xA;&#xD;&#xA;	glGenVertexArrays(1,&amp;VAOplane);&#xD;&#xA;	glGenVertexArrays(1,&amp;VAOcube);&#xD;&#xA;	glGenVertexArrays(1,&amp;VAOquad);&#xD;&#xA;	glGenBuffers(1,&amp;VBOplane);&#xD;&#xA;	glGenBuffers(1,&amp;VBOcube);&#xD;&#xA;	glGenBuffers(1, &amp;VBOquad);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER,VBOplane);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER,sizeof(plane),plane,GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER,VBOcube);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER,sizeof(cube),cube,GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER,VBOquad);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER,sizeof(quad),quad,GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(VAOplane);&#xD;&#xA;	{&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER,VBOplane);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*5,(GLvoid*)(0));&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;		glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*5,(GLvoid*)(sizeof(GLfloat)*3));&#xD;&#xA;	}&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(VAOcube);&#xD;&#xA;	{&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER,VBOcube);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*8,(GLvoid*)(0));&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;		glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*8,(GLvoid*)(sizeof(GLfloat)*6));&#xD;&#xA;	}&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(VAOquad);&#xD;&#xA;	{&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER, VBOquad);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*)(0));&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid*)(sizeof(GLfloat) * 2));&#xD;&#xA;	}&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	/*Setting up framebuffer*/&#xD;&#xA;&#xD;&#xA;	GLuint fbo;&#xD;&#xA;	glGenFramebuffers(1,&amp;fbo);&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER,fbo);&#xD;&#xA;	&#xD;&#xA;	//Our color attachement&#xD;&#xA;	GLuint texColorBuffer;&#xD;&#xA;	glGenTextures(1,&amp;texColorBuffer);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D,texColorBuffer);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D,0);&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texColorBuffer,0);&#xD;&#xA;&#xD;&#xA;	//our depth attachment&#xD;&#xA;	GLuint depthRenderbuffer;&#xD;&#xA;	glGenRenderbuffers(1,&amp;depthRenderbuffer);&#xD;&#xA;	glBindRenderbuffer(GL_RENDERBUFFER,depthRenderbuffer);&#xD;&#xA;	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WIDTH, HEIGHT);&#xD;&#xA;	glBindRenderbuffer(GL_RENDERBUFFER,0);&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_STENCIL_ATTACHMENT,GL_RENDERBUFFER,depthRenderbuffer);&#xD;&#xA;&#xD;&#xA;	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)&#xD;&#xA;		assert(0);&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER,0);&#xD;&#xA;	&#xD;&#xA;	glViewport(0,0,WIDTH,HEIGHT);&#xD;&#xA;&#xD;&#xA;	Texture floorTex(&quot;textures/floortexture1.jpg&quot;);&#xD;&#xA;	Texture cubeTex(&quot;textures/cubetexture1.jpg&quot;);&#xD;&#xA;	&#xD;&#xA;	Shader shader(&quot;vs.txt&quot;,&quot;fs.txt&quot;);&#xD;&#xA;	Shader shader2(&quot;vs2.txt&quot;,&quot;fs2.txt&quot;);&#xD;&#xA;&#xD;&#xA;	//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);&#xD;&#xA;&#xD;&#xA;	while(!glfwWindowShouldClose(window))&#xD;&#xA;	{&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;		glBindFramebuffer(GL_FRAMEBUFFER, fbo);&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;		glClearColor(0.1,0.0,0.0,0.0);&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;		glEnable(GL_DEPTH_TEST);&#xD;&#xA;		//float radius = 5.0f;&#xD;&#xA;		//cameraPos.z = cos(SLMath::radians(glfwGetTime()*30.0f))*radius;&#xD;&#xA;		//cameraPos.x = sin(SLMath::radians(glfwGetTime()*30.0f))*radius;&#xD;&#xA;		&#xD;&#xA;		SLMath::Mat4 projection;&#xD;&#xA;		SLMath::Mat4 view;&#xD;&#xA;		SLMath::Mat4 model;&#xD;&#xA;&#xD;&#xA;		GLint projLoc = glGetUniformLocation(shader.program,&quot;projection&quot;);&#xD;&#xA;		GLint viewLoc = glGetUniformLocation(shader.program,&quot;view&quot;);&#xD;&#xA;		GLint modelLoc = glGetUniformLocation(shader.program,&quot;model&quot;);&#xD;&#xA;&#xD;&#xA;		SLMath::perspective(projection,45.0f,(float)WIDTH/(float)HEIGHT,0.1f,100.0f);&#xD;&#xA;		SLMath::lookAt(view,cameraPos,cameraDir,cameraUp);&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(projLoc,1,GL_FALSE,projection.valuePtr());&#xD;&#xA;		glUniformMatrix4fv(viewLoc,1,GL_FALSE,view.valuePtr());&#xD;&#xA;		glUniformMatrix4fv(modelLoc,1,GL_FALSE,model.valuePtr());&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;		floorTex.bind();&#xD;&#xA;		shader.Use();&#xD;&#xA;		glBindVertexArray(VAOplane);&#xD;&#xA;		glDrawArrays(GL_TRIANGLES,0,6);&#xD;&#xA;		glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;		cubeTex.bind();&#xD;&#xA;&#xD;&#xA;		for(int i=0;i&lt;3;i++)&#xD;&#xA;		{&#xD;&#xA;			model.reset();&#xD;&#xA;			SLMath::translate(model,cubePositions[i]);&#xD;&#xA;			glUniformMatrix4fv(modelLoc,1,GL_FALSE,model.valuePtr());&#xD;&#xA;		&#xD;&#xA;			glBindVertexArray(VAOcube);&#xD;&#xA;			glDrawArrays(GL_TRIANGLES,0,36);&#xD;&#xA;			glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		glBindFramebuffer(GL_FRAMEBUFFER,0);&#xD;&#xA;&#xD;&#xA;		glClearColor(1.0f,1.0f,1.0f,1.0);&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;		glDisable(GL_DEPTH_TEST);&#xD;&#xA;		&#xD;&#xA;		shader2.Use();&#xD;&#xA;		glBindTexture(GL_TEXTURE_2D, texColorBuffer);&#xD;&#xA;		glBindVertexArray(VAOquad);&#xD;&#xA;		glDrawArrays(GL_TRIANGLES,0,6);&#xD;&#xA;		glBindVertexArray(0);&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;		glfwSwapBuffers(window);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	glDeleteBuffers(1, &amp;VBOquad);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBOcube);&#xD;&#xA;	glDeleteBuffers(1,&amp;VBOplane);&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAOquad);&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAOcube);&#xD;&#xA;	glDeleteVertexArrays(1,&amp;VAOplane);&#xD;&#xA;	glfwDestroyWindow(window);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;	exit(EXIT_SUCCESS);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am getting this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;instead of this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cAx72.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/H3p6i.png&#xD;&#xA;&#xD;&#xA;I have checked my code several times....what is wrong??" ContentLicense="CC BY-SA 3.0" />
  <row Id="4955" PostHistoryTypeId="4" PostId="2178" RevisionGUID="6c7871b5-031a-4261-9e0c-8810c11d0e1f" CreationDate="2016-03-13T11:58:24.033" UserId="2096" Comment="edited title" Text="Clearing but not drawing objects" ContentLicense="CC BY-SA 3.0" />
  <row Id="4958" PostHistoryTypeId="2" PostId="2180" RevisionGUID="7051e3b0-7c32-4227-8627-f49d9c0af3d4" CreationDate="2016-03-13T22:52:45.323" UserId="2319" Text="I am a beginner in digital image processing and computer graphics. I would like to program a similar behavior than the Shadermap 3 normal editor (displacement layer more specifically).&#xD;&#xA;&#xD;&#xA;As shown in this [Shadermap 3 demonstration video](https://youtu.be/NIHpBNnYYU8?t=34s), the displacement brush allows the user to paint a **displacement map (grayscale)**&#xD;&#xA;&#xD;&#xA;![Shadermap 3](https://i.stack.imgur.com/n3Jq2.png)&#xD;&#xA;&#xD;&#xA;The brush strokes produce shapes with a smooth value transitioning from the middle of the shape to its edge, in this case giving the shape a slightly curved profile. As it is also shown, the shape's profile can be fine-tuned with the brush curve editor.&#xD;&#xA;&#xD;&#xA;What combination of filters and/or algorithms could Shadermap 3 possibly use to convert a pixel blob or shape to displacement map with a given width and curve?&#xD;&#xA;&#xD;&#xA;![Combination](https://i.stack.imgur.com/HSo1c.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="4959" PostHistoryTypeId="1" PostId="2180" RevisionGUID="7051e3b0-7c32-4227-8627-f49d9c0af3d4" CreationDate="2016-03-13T22:52:45.323" UserId="2319" Text="Converting raster shape/blob into displacement map" ContentLicense="CC BY-SA 3.0" />
  <row Id="4960" PostHistoryTypeId="3" PostId="2180" RevisionGUID="7051e3b0-7c32-4227-8627-f49d9c0af3d4" CreationDate="2016-03-13T22:52:45.323" UserId="2319" Text="|algorithm|image-processing|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4961" PostHistoryTypeId="2" PostId="2181" RevisionGUID="c61f4760-98c8-47a1-a6fb-9eec63971a77" CreationDate="2016-03-14T02:55:34.097" UserId="56" Text="One way I can think of is to make a &quot;signed distance transform&quot; of the image where there is information for each pixel about how far the pixel is to the closest surface of the shape.  Since it's signed, youll be able to know if the pixel is inside or outside he shape, and by how much.&#xA;&#xA;Using this knowledge, you could easily make a new image, where the pixel is black if the distance is greater than -10, else it is white.  That would make the shape shrink by 10 pixels.&#xA;&#xA;You can use smoothstep or other curves to transition between black and white over a number of pixels, to soften it anti alias the edges.&#xA;&#xA;You can make the distance transform by brute force, but another method would be to make a voronoi diagram first and then turn that into a distance transform.&#xA;&#xA;There is lots of info out there on both voronoi diagrams as well as (signed) distance transforms but these two links will probably be helpful to get you started:&#xA;&#xA;http://blog.demofox.org/2016/02/29/fast-voronoi-diagrams-and-distance-dield-textures-on-the-gpu-with-the-jump-flooding-algorithm/&#xA;&#xA;http://blog.demofox.org/2016/03/02/actually-making-signed-distance-field-textures-with-jfa/" ContentLicense="CC BY-SA 3.0" />
  <row Id="4962" PostHistoryTypeId="5" PostId="2172" RevisionGUID="46bfedf0-5046-4c32-a7e2-80935e484cb6" CreationDate="2016-03-14T05:19:00.283" UserId="2828" Comment="Moved towards a theoritcal question and not just requesting known libraries, with clarified classification tasked and a possible approach of the problem." Text="Can an algorithm be derived to classify digital images according to how they were generated, i.e. the classes would be:&#xD;&#xA; &#xD;&#xA; - Real-world photograph captured with an actual camera.&#xD;&#xA; - A Computer-Generated realistic scene.&#xD;&#xA; - A hand-drawn image or a painting.&#xD;&#xA;&#xD;&#xA;Could perhaps a Machine Learning approach, geared towards analyzing statistics of the signal provide sufficient insight on the problem ?&#xD;&#xA;In that case, is there any known implementation of such algorithm publicly available ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4963" PostHistoryTypeId="24" PostId="2172" RevisionGUID="46bfedf0-5046-4c32-a7e2-80935e484cb6" CreationDate="2016-03-14T05:19:00.283" Comment="Proposed by 2828 approved by 56, 48 edit id of 125" ContentLicense="CC BY-SA 3.0" />
  <row Id="4965" PostHistoryTypeId="2" PostId="2182" RevisionGUID="9f4622cc-7d4b-4bc1-917d-0efde3f079af" CreationDate="2016-03-14T10:32:47.963" UserId="2831" Text="Another thought is along these lines.  If you have a uniform point set defined on the plane and a mapping function from the plane to the target surface then the density function on the surface is how areas map from the plane surface to the target.  So an area preserving map would result in a uniform points on the target." ContentLicense="CC BY-SA 3.0" />
  <row Id="4966" PostHistoryTypeId="10" PostId="2163" RevisionGUID="e99f6e86-d087-44ca-bb65-38e20cf63c54" CreationDate="2016-03-14T15:53:57.133" UserId="127" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:273,&quot;DisplayName&quot;:&quot;Dragonseel&quot;},{&quot;Id&quot;:127,&quot;DisplayName&quot;:&quot;Nero&quot;}]}" />
  <row Id="4967" PostHistoryTypeId="2" PostId="2183" RevisionGUID="8bfa5fa6-2503-4f5c-b5d0-1d3fbe4fe75c" CreationDate="2016-03-14T18:22:33.197" UserId="2828" Text="You would want to provide us with the implementation of the shaders you use, or at the very least the result of shader compilation.&#xD;&#xA;&#xD;&#xA;A simple typo in a shader obviously prevents compilation and therefore successful rasterization of the object.&#xD;&#xA;&#xD;&#xA;In short, check your shader !" ContentLicense="CC BY-SA 3.0" />
  <row Id="4968" PostHistoryTypeId="2" PostId="2184" RevisionGUID="c262801c-2ad3-48e0-90be-0097d533e787" CreationDate="2016-03-14T18:38:52.403" UserId="2879" Text="I'm trying to achieve the same effect in OpenGL/GLSL as what Blender does when you add a texture, set to &quot;Reflection&quot;&#xD;&#xA;&#xD;&#xA;This ultimately is a way to fake specularity, or &quot;metallicness&quot; if I get it right.&#xD;&#xA;&#xD;&#xA;I followed this tutorial (Mid-page, &quot;Sphere Mapping&quot; section):&#xD;&#xA;http://www.ozone3d.net/tutorials/glsl_texturing_p04.php&#xD;&#xA;&#xD;&#xA;Here's the problem(some serious artifacts):&#xD;&#xA;https://www.youtube.com/watch?v=hx66_xWhVu4&amp;feature=youtu.be&#xD;&#xA;&#xD;&#xA;Everything's happening at the bottom of the Vertex Sahder:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 vertexPosition_modelspace;&#xD;&#xA;    layout(location = 1) in vec2 vertexUV;&#xD;&#xA;    layout(location = 2) in vec3 vertexNormal_modelspace;&#xD;&#xA;    layout(location = 3) in vec3 vertexTangent_modelspace;&#xD;&#xA;    &#xD;&#xA;    out vec2 uv;&#xD;&#xA;    out vec3 toLightVector[4];&#xD;&#xA;    out vec3 toCameraVector;&#xD;&#xA;    out float fog_Visibility;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 FTM;&#xD;&#xA;    uniform mat4 P;&#xD;&#xA;    uniform mat4 V;&#xD;&#xA;    uniform vec3 LP[4];&#xD;&#xA;    &#xD;&#xA;    const float fog_Density = 0.2;&#xD;&#xA;    const float fog_Gradient = 0.9;&#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;        vec4 worldPosition = FTM * vec4(vertexPosition_modelspace, 1.0);&#xD;&#xA;    	uv = vertexUV;&#xD;&#xA;    &#xD;&#xA;    	vec3 surfaceNormal = (FTM * vec4(vertexNormal_modelspace, 0.0)).xyz;&#xD;&#xA;    &#xD;&#xA;    	vec3 norm = normalize(surfaceNormal);&#xD;&#xA;    	vec3 tang = normalize((FTM * vec4(vertexTangent_modelspace, 0.0)).xyz);&#xD;&#xA;    	vec3 bitang = normalize(cross(norm, tang));&#xD;&#xA;    &#xD;&#xA;    	mat3 toTangentSpace = mat3(tang.x, bitang.x, norm.x, tang.y, bitang.y, norm.y, tang.z, bitang.z, norm.z);&#xD;&#xA;    &#xD;&#xA;    	for (int i = 0; i &lt; 4; i++) {&#xD;&#xA;    		toLightVector[i] = toTangentSpace * (LP[i] - worldPosition.xyz);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	toCameraVector = toTangentSpace * ((inverse(V) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - worldPosition.xyz);&#xD;&#xA;    &#xD;&#xA;    	vec4 positionRelativeToCam = V * worldPosition;&#xD;&#xA;    	gl_Position = P * positionRelativeToCam;&#xD;&#xA;    &#xD;&#xA;    	// Fog&#xD;&#xA;    	float fog_Distance = length(positionRelativeToCam.xyz);&#xD;&#xA;    	fog_Visibility = exp(-pow((fog_Distance * fog_Density), fog_Gradient));&#xD;&#xA;    	fog_Visibility = clamp(fog_Visibility, 0.0, 1.0);&#xD;&#xA;    &#xD;&#xA;    	// Reflection Map&#xD;&#xA;    	vec3 u = normalize(toCameraVector);&#xD;&#xA;    	vec3 r = reflect(u, norm);&#xD;&#xA;    	float m = 2.0 * sqrt(r.x*r.x + r.y*r.y + (r.z + 1.0)*(r.z + 1.0));&#xD;&#xA;    &#xD;&#xA;    	gl_TexCoord[0].s = r.x / m + 0.5;&#xD;&#xA;    	gl_TexCoord[0].t = r.y / m + 0.5;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And in the Fragment Shader, all I do is:&#xD;&#xA;&#xD;&#xA;    out_color = texture(reflectionSampler, gl_TexCoord[0].st);&#xD;&#xA;&#xD;&#xA;The reflection map seems to do it's thing similarly to the way it's seen in Blender, but not quite.&#xD;&#xA;&#xD;&#xA;I need to be able to do this without calculating lights. Thats how Blender does it, it works Shadeless mode so all it should take is the camera's vector..." ContentLicense="CC BY-SA 3.0" />
  <row Id="4969" PostHistoryTypeId="1" PostId="2184" RevisionGUID="c262801c-2ad3-48e0-90be-0097d533e787" CreationDate="2016-03-14T18:38:52.403" UserId="2879" Text="Guidance with Sphere-Map calculation in GLSL" ContentLicense="CC BY-SA 3.0" />
  <row Id="4970" PostHistoryTypeId="3" PostId="2184" RevisionGUID="c262801c-2ad3-48e0-90be-0097d533e787" CreationDate="2016-03-14T18:38:52.403" UserId="2879" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4971" PostHistoryTypeId="2" PostId="2185" RevisionGUID="d69a247f-9deb-43f3-94eb-ce16c04a5dab" CreationDate="2016-03-14T21:29:39.643" UserId="48" Text="You probably need to calculate the reflection vector per pixel, not per vertex. The calculation is non-linear, so doing it per vertex and interpolating will not give good results unless the model is finely tesselated.&#xD;&#xA;&#xD;&#xA;Send `norm` and `toCameraVector` down to the pixel shader, normalize them both and move all your calculations under `// Reflection Map` to the pixel shader. That should give you some better results." ContentLicense="CC BY-SA 3.0" />
  <row Id="4974" PostHistoryTypeId="2" PostId="2187" RevisionGUID="bdb35a3d-ae02-43db-93db-11c03f982921" CreationDate="2016-03-15T05:20:10.700" UserId="1810" Text="Color spaces issues are such a pain, especially when you create color data at the middle of the chain, and a pile of libs and apps separate this to the display... Here I only worry about gamma transform.&#xD;&#xA;&#xD;&#xA;[Shadertoy][1] addicts are coding in this web site webGLSL shaders, which in my case are rendered through google chrome on linux ubuntu and displayed on a calibrated monitor. &#xD;&#xA;&#xD;&#xA;Is one layer already doing the gamma transform, or should I do pow(color,1./2.2) at the end of my rendering ?&#xD;&#xA;For me (linux,etc), it seems I must do it. Is it also true on windows, mac OS, whether Angle or Native OpenGL is used (windows), whatever the browser ?&#xD;&#xA;The point is that often shaders look ok on windows and very dark on linux, for instance, both people being sure of their settings and qualibration.&#xD;&#xA;&#xD;&#xA;  [1]: http://shadertoy.com" ContentLicense="CC BY-SA 3.0" />
  <row Id="4975" PostHistoryTypeId="1" PostId="2187" RevisionGUID="bdb35a3d-ae02-43db-93db-11c03f982921" CreationDate="2016-03-15T05:20:10.700" UserId="1810" Text="gamma transform in webGLSL: when already done or yet to be done?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4976" PostHistoryTypeId="3" PostId="2187" RevisionGUID="bdb35a3d-ae02-43db-93db-11c03f982921" CreationDate="2016-03-15T05:20:10.700" UserId="1810" Text="|glsl|webgl|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4978" PostHistoryTypeId="2" PostId="2188" RevisionGUID="e06eca23-c841-4411-bc92-2a8d751f7a0d" CreationDate="2016-03-15T10:18:23.130" UserId="2858" Text="I am trying to model an organic object using OpenSCAD. However this will need to be ported over to older software. This restricts the primitives I can use (only cone, cylinder, torus, sphere and cubes) and the operations I can perform (difference, union, intersection, scaling and transformation). However modeling with these restrictions gives very unnatural looking objects. I need to somehow implement by hand, using only these primitives/operations the hull and minkowski operations to give my models a more organic look. Does anybody know how this could be done?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4979" PostHistoryTypeId="1" PostId="2188" RevisionGUID="e06eca23-c841-4411-bc92-2a8d751f7a0d" CreationDate="2016-03-15T10:18:23.130" UserId="2858" Text="OpenSCAD Hull/Minkowski function by hand?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4980" PostHistoryTypeId="3" PostId="2188" RevisionGUID="e06eca23-c841-4411-bc92-2a8d751f7a0d" CreationDate="2016-03-15T10:18:23.130" UserId="2858" Text="|transformations|3d|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4981" PostHistoryTypeId="2" PostId="2189" RevisionGUID="dfe7b061-d8ee-4bd1-b07d-22bcd8af5d07" CreationDate="2016-03-15T13:40:03.177" UserId="2508" Text="I am doing exercises from the OpenGL SuperBible 6th Ed. I have managed to set up rendering into a framebuffer texture and then rendering from that texture to a cube.&#xD;&#xA;&#xD;&#xA;But for some reason, **when the texture gets applied to the cube, it is rendered incorrectly. I was expecting to see a grey rotating cube on a green background, but instead half of the texture is green and half renders a part of the cube.**&#xD;&#xA;&#xD;&#xA;Here's a screenshot of my current situation:&#xD;&#xA;&#xD;&#xA;https://www.dropbox.com/s/p6scooqs9lrcdse/fbo.png?dl=0&#xD;&#xA;&#xD;&#xA;I've spent a lot of time trying to fix this. I mean, the last 5 hours or so. I rewrote most of the code once and it fixed some of my previous erros, but now I'm stuck with this last part. &#xD;&#xA;&#xD;&#xA;I used the SB sources as reference (https://github.com/openglsuperbible/sb6code/blob/master/src/basicfbo/basicfbo.cpp), but I can't find the reason why it looks like this. What did I miss?&#xD;&#xA;&#xD;&#xA;Here is my current code (the most important App class which does most of the work):&#xD;&#xA;&#xD;&#xA;    #include &quot;config.h&quot;&#xD;&#xA;    &#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &lt;GL/freeglut.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;App.h&quot;&#xD;&#xA;    #include &quot;GLSLProgram.h&quot;&#xD;&#xA;    &#xD;&#xA;    void App::renderToFramebuffer() {&#xD;&#xA;        float clearColor[] = { 0.0f, 0.5f, 0.0f, 1.0f };&#xD;&#xA;        float one = 1.0f;&#xD;&#xA;    &#xD;&#xA;        m_rotation += 1.0f;&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, 512, 512);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, clearColor);&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;one);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(-1.0f, -0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotationY = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationY);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(m_rotation), rotationX);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;start();&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;stop();&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::renderToScreen() {&#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, SCREEN_X, SCREEN_Y);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, glm::value_ptr(m_clearColor));&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;m_depthBufferDefault);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotation = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotation);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationX);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;start();&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(m_projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;stop();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::render() {&#xD;&#xA;        renderToFramebuffer();&#xD;&#xA;        renderToScreen();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::App() {&#xD;&#xA;        glEnable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;        glEnable(GL_CULL_FACE);&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glDepthFunc(GL_LEQUAL);&#xD;&#xA;    &#xD;&#xA;        m_clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        m_depthBufferDefault = 1.0f;&#xD;&#xA;        m_projectionMatrix = glm::perspective(50.0f, (float) SCREEN_X / (float) SCREEN_Y, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured = new GLSLProgram();&#xD;&#xA;        m_shaderNotTextured-&gt;addVertexShader(&quot;shaders/notex.vs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;addFragmentShader(&quot;shaders/notex.fs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured = new GLSLProgram();&#xD;&#xA;        m_shaderTextured-&gt;addVertexShader(&quot;shaders/tex.vs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;addFragmentShader(&quot;shaders/tex.fs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        glGenVertexArrays(1, &amp;m_VAO);&#xD;&#xA;        glGenBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    &#xD;&#xA;        glGenTextures(1, &amp;m_TBO);&#xD;&#xA;        glGenTextures(1, &amp;m_TDBO);&#xD;&#xA;    &#xD;&#xA;        glGenFramebuffers(1, &amp;m_FBO);&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, m_buffers[VBO]);&#xD;&#xA;            static const GLfloat vertex_data[] =&#xD;&#xA;            {&#xD;&#xA;                 // Position                 Tex Coord&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);&#xD;&#xA;            glEnableVertexAttribArray(0);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (2 * sizeof(GLfloat)));&#xD;&#xA;            glEnableVertexAttribArray(1);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512);&#xD;&#xA;    &#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TDBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_DEPTH_COMPONENT32F, 512, 512);&#xD;&#xA;    &#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_TBO, 0);&#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_TDBO, 0);&#xD;&#xA;    &#xD;&#xA;            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };&#xD;&#xA;            glDrawBuffers(1, drawBuffers);&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[IBO]);&#xD;&#xA;    &#xD;&#xA;            static const GLushort vertex_indices[] =&#xD;&#xA;            {&#xD;&#xA;                0, 1, 2,&#xD;&#xA;                2, 1, 3,&#xD;&#xA;                2, 3, 4,&#xD;&#xA;                4, 3, 5,&#xD;&#xA;                4, 5, 6,&#xD;&#xA;                6, 5, 7,&#xD;&#xA;                6, 7, 0,&#xD;&#xA;                0, 7, 1,&#xD;&#xA;                6, 0, 2,&#xD;&#xA;                2, 4, 6,&#xD;&#xA;                7, 5, 3,&#xD;&#xA;                7, 3, 1&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::~App() {&#xD;&#xA;        delete m_shaderNotTextured;&#xD;&#xA;        delete m_shaderTextured;&#xD;&#xA;        glDeleteBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void App::update() {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Also, I have no idea why in SB6 code they are creating an array of indices and then not using it. I copied the part of the code with vertex data, initialized everything and then realized the indices aren't used. But I didn't remove them yet." ContentLicense="CC BY-SA 3.0" />
  <row Id="4982" PostHistoryTypeId="1" PostId="2189" RevisionGUID="dfe7b061-d8ee-4bd1-b07d-22bcd8af5d07" CreationDate="2016-03-15T13:40:03.177" UserId="2508" Text="Drawing to framebuffer texture - only half of the texture is then drawn" ContentLicense="CC BY-SA 3.0" />
  <row Id="4983" PostHistoryTypeId="3" PostId="2189" RevisionGUID="dfe7b061-d8ee-4bd1-b07d-22bcd8af5d07" CreationDate="2016-03-15T13:40:03.177" UserId="2508" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4984" PostHistoryTypeId="5" PostId="2189" RevisionGUID="042290a9-c4f5-46c7-a38a-2f38be1bf784" CreationDate="2016-03-15T15:36:16.733" UserId="16" Comment="include image in post" Text="I am doing exercises from the OpenGL SuperBible 6th Ed. I have managed to set up rendering into a framebuffer texture and then rendering from that texture to a cube.&#xD;&#xA;&#xD;&#xA;But for some reason, **when the texture gets applied to the cube, it is rendered incorrectly. I was expecting to see a grey rotating cube on a green background, but instead half of the texture is green and half renders a part of the cube.**&#xD;&#xA;&#xD;&#xA;Here's a screenshot of my current situation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've spent a lot of time trying to fix this. I mean, the last 5 hours or so. I rewrote most of the code once and it fixed some of my previous erros, but now I'm stuck with this last part. &#xD;&#xA;&#xD;&#xA;I used the SB sources as reference (https://github.com/openglsuperbible/sb6code/blob/master/src/basicfbo/basicfbo.cpp), but I can't find the reason why it looks like this. What did I miss?&#xD;&#xA;&#xD;&#xA;Here is my current code (the most important App class which does most of the work):&#xD;&#xA;&#xD;&#xA;    #include &quot;config.h&quot;&#xD;&#xA;    &#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &lt;GL/freeglut.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;App.h&quot;&#xD;&#xA;    #include &quot;GLSLProgram.h&quot;&#xD;&#xA;    &#xD;&#xA;    void App::renderToFramebuffer() {&#xD;&#xA;        float clearColor[] = { 0.0f, 0.5f, 0.0f, 1.0f };&#xD;&#xA;        float one = 1.0f;&#xD;&#xA;    &#xD;&#xA;        m_rotation += 1.0f;&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, 512, 512);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, clearColor);&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;one);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(-1.0f, -0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotationY = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationY);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(m_rotation), rotationX);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;start();&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;stop();&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::renderToScreen() {&#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, SCREEN_X, SCREEN_Y);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, glm::value_ptr(m_clearColor));&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;m_depthBufferDefault);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotation = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotation);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationX);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;start();&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(m_projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;stop();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::render() {&#xD;&#xA;        renderToFramebuffer();&#xD;&#xA;        renderToScreen();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::App() {&#xD;&#xA;        glEnable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;        glEnable(GL_CULL_FACE);&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glDepthFunc(GL_LEQUAL);&#xD;&#xA;    &#xD;&#xA;        m_clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        m_depthBufferDefault = 1.0f;&#xD;&#xA;        m_projectionMatrix = glm::perspective(50.0f, (float) SCREEN_X / (float) SCREEN_Y, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured = new GLSLProgram();&#xD;&#xA;        m_shaderNotTextured-&gt;addVertexShader(&quot;shaders/notex.vs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;addFragmentShader(&quot;shaders/notex.fs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured = new GLSLProgram();&#xD;&#xA;        m_shaderTextured-&gt;addVertexShader(&quot;shaders/tex.vs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;addFragmentShader(&quot;shaders/tex.fs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        glGenVertexArrays(1, &amp;m_VAO);&#xD;&#xA;        glGenBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    &#xD;&#xA;        glGenTextures(1, &amp;m_TBO);&#xD;&#xA;        glGenTextures(1, &amp;m_TDBO);&#xD;&#xA;    &#xD;&#xA;        glGenFramebuffers(1, &amp;m_FBO);&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, m_buffers[VBO]);&#xD;&#xA;            static const GLfloat vertex_data[] =&#xD;&#xA;            {&#xD;&#xA;                 // Position                 Tex Coord&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);&#xD;&#xA;            glEnableVertexAttribArray(0);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (2 * sizeof(GLfloat)));&#xD;&#xA;            glEnableVertexAttribArray(1);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512);&#xD;&#xA;    &#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TDBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_DEPTH_COMPONENT32F, 512, 512);&#xD;&#xA;    &#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_TBO, 0);&#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_TDBO, 0);&#xD;&#xA;    &#xD;&#xA;            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };&#xD;&#xA;            glDrawBuffers(1, drawBuffers);&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[IBO]);&#xD;&#xA;    &#xD;&#xA;            static const GLushort vertex_indices[] =&#xD;&#xA;            {&#xD;&#xA;                0, 1, 2,&#xD;&#xA;                2, 1, 3,&#xD;&#xA;                2, 3, 4,&#xD;&#xA;                4, 3, 5,&#xD;&#xA;                4, 5, 6,&#xD;&#xA;                6, 5, 7,&#xD;&#xA;                6, 7, 0,&#xD;&#xA;                0, 7, 1,&#xD;&#xA;                6, 0, 2,&#xD;&#xA;                2, 4, 6,&#xD;&#xA;                7, 5, 3,&#xD;&#xA;                7, 3, 1&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::~App() {&#xD;&#xA;        delete m_shaderNotTextured;&#xD;&#xA;        delete m_shaderTextured;&#xD;&#xA;        glDeleteBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void App::update() {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Also, I have no idea why in SB6 code they are creating an array of indices and then not using it. I copied the part of the code with vertex data, initialized everything and then realized the indices aren't used. But I didn't remove them yet.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KCtjJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4988" PostHistoryTypeId="2" PostId="2190" RevisionGUID="986d989f-ad51-4f2b-8871-b2d75c23e208" CreationDate="2016-03-16T04:00:38.943" UserId="110" Text="Different BRDFs are usually used to compute diffuse and specular reflection.  &#xD;&#xA;Some of the most often used include for example the Lambert BRDF for diffuse reflection ; and the Cook-Torrance BRDF for specular reflection.  &#xD;&#xA;Cook-Torrance BRDFs are parametrized by the surface roughness : the rougher the surface, the &quot;blurrier&quot; the reflection.  &#xD;&#xA;  &#xD;&#xA;From a conceptual point of view, should we consider that for an extremely rough surface, the specular reflection must look like a diffuse reflection ? Can there be a continuity between both components of the reflection ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4989" PostHistoryTypeId="1" PostId="2190" RevisionGUID="986d989f-ad51-4f2b-8871-b2d75c23e208" CreationDate="2016-03-16T04:00:38.943" UserId="110" Text="Should not specular reflection on a rough surface be similar to diffuse reflection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="4990" PostHistoryTypeId="3" PostId="2190" RevisionGUID="986d989f-ad51-4f2b-8871-b2d75c23e208" CreationDate="2016-03-16T04:00:38.943" UserId="110" Text="|reflection|specular|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4991" PostHistoryTypeId="2" PostId="2191" RevisionGUID="5fc9f866-8bb4-4a38-9789-178832864382" CreationDate="2016-03-16T16:01:20.923" UserId="2096" Text="Answering my own question!&#xA;The reason for this behaviour is that I forgot to activate shader program before passing matrices to it!&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4992" PostHistoryTypeId="2" PostId="2192" RevisionGUID="8a6e4778-9311-4b90-8aaa-517d3efa82df" CreationDate="2016-03-16T16:05:17.363" UserId="2096" Text="I know how shadow mapping works but I am not getting the cause of shadow acne!&#xA;Can anyone tell me cause of shadow acne in a simple way and how is it related to depth map resolution? &#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="4993" PostHistoryTypeId="1" PostId="2192" RevisionGUID="8a6e4778-9311-4b90-8aaa-517d3efa82df" CreationDate="2016-03-16T16:05:17.363" UserId="2096" Text="Cause of shadow acne" ContentLicense="CC BY-SA 3.0" />
  <row Id="4994" PostHistoryTypeId="3" PostId="2192" RevisionGUID="8a6e4778-9311-4b90-8aaa-517d3efa82df" CreationDate="2016-03-16T16:05:17.363" UserId="2096" Text="|opengl|raytracing|rendering|shader|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="4995" PostHistoryTypeId="5" PostId="2189" RevisionGUID="579991af-4c3d-49f8-bb06-b6b47491e6a1" CreationDate="2016-03-16T17:04:02.173" UserId="2508" Comment="added 240 characters in body" Text="I am doing exercises from the OpenGL SuperBible 6th Ed. I have managed to set up rendering into a framebuffer texture and then rendering from that texture to a cube.&#xD;&#xA;&#xD;&#xA;But for some reason, **when the texture gets applied to the cube, it is rendered incorrectly. I was expecting to see a grey rotating cube on a green background, but instead half of the texture is green and half renders a part of the cube.**&#xD;&#xA;&#xD;&#xA;Here's a screenshot of my current situation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've spent a lot of time trying to fix this. I mean, the last 5 hours or so. I rewrote most of the code once and it fixed some of my previous erros, but now I'm stuck with this last part. &#xD;&#xA;&#xD;&#xA;I used the SB sources as reference (https://github.com/openglsuperbible/sb6code/blob/master/src/basicfbo/basicfbo.cpp), but I can't find the reason why it looks like this. What did I miss?&#xD;&#xA;&#xD;&#xA;Here is my current code (the most important App class which does most of the work):&#xD;&#xA;&#xD;&#xA;    #include &quot;config.h&quot;&#xD;&#xA;    &#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &lt;GL/freeglut.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;App.h&quot;&#xD;&#xA;    #include &quot;GLSLProgram.h&quot;&#xD;&#xA;    &#xD;&#xA;    void App::renderToFramebuffer() {&#xD;&#xA;        float clearColor[] = { 0.0f, 0.5f, 0.0f, 1.0f };&#xD;&#xA;        float one = 1.0f;&#xD;&#xA;    &#xD;&#xA;        m_rotation += 1.0f;&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, 512, 512);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, clearColor);&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;one);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(-1.0f, -0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotationY = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationY);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(m_rotation), rotationX);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;start();&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;stop();&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::renderToScreen() {&#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, SCREEN_X, SCREEN_Y);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, glm::value_ptr(m_clearColor));&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;m_depthBufferDefault);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotation = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotation);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationX);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;start();&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(m_projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;stop();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::render() {&#xD;&#xA;        renderToFramebuffer();&#xD;&#xA;        renderToScreen();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::App() {&#xD;&#xA;        glEnable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;        glEnable(GL_CULL_FACE);&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glDepthFunc(GL_LEQUAL);&#xD;&#xA;    &#xD;&#xA;        m_clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        m_depthBufferDefault = 1.0f;&#xD;&#xA;        m_projectionMatrix = glm::perspective(50.0f, (float) SCREEN_X / (float) SCREEN_Y, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured = new GLSLProgram();&#xD;&#xA;        m_shaderNotTextured-&gt;addVertexShader(&quot;shaders/notex.vs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;addFragmentShader(&quot;shaders/notex.fs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured = new GLSLProgram();&#xD;&#xA;        m_shaderTextured-&gt;addVertexShader(&quot;shaders/tex.vs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;addFragmentShader(&quot;shaders/tex.fs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        glGenVertexArrays(1, &amp;m_VAO);&#xD;&#xA;        glGenBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    &#xD;&#xA;        glGenTextures(1, &amp;m_TBO);&#xD;&#xA;        glGenTextures(1, &amp;m_TDBO);&#xD;&#xA;    &#xD;&#xA;        glGenFramebuffers(1, &amp;m_FBO);&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, m_buffers[VBO]);&#xD;&#xA;            static const GLfloat vertex_data[] =&#xD;&#xA;            {&#xD;&#xA;                 // Position                 Tex Coord&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);&#xD;&#xA;            glEnableVertexAttribArray(0);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (2 * sizeof(GLfloat)));&#xD;&#xA;            glEnableVertexAttribArray(1);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512);&#xD;&#xA;    &#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TDBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_DEPTH_COMPONENT32F, 512, 512);&#xD;&#xA;    &#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_TBO, 0);&#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_TDBO, 0);&#xD;&#xA;    &#xD;&#xA;            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };&#xD;&#xA;            glDrawBuffers(1, drawBuffers);&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[IBO]);&#xD;&#xA;    &#xD;&#xA;            static const GLushort vertex_indices[] =&#xD;&#xA;            {&#xD;&#xA;                0, 1, 2,&#xD;&#xA;                2, 1, 3,&#xD;&#xA;                2, 3, 4,&#xD;&#xA;                4, 3, 5,&#xD;&#xA;                4, 5, 6,&#xD;&#xA;                6, 5, 7,&#xD;&#xA;                6, 7, 0,&#xD;&#xA;                0, 7, 1,&#xD;&#xA;                6, 0, 2,&#xD;&#xA;                2, 4, 6,&#xD;&#xA;                7, 5, 3,&#xD;&#xA;                7, 3, 1&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::~App() {&#xD;&#xA;        delete m_shaderNotTextured;&#xD;&#xA;        delete m_shaderTextured;&#xD;&#xA;        glDeleteBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void App::update() {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Also, I have no idea why in SB6 code they are creating an array of indices and then not using it. I copied the part of the code with vertex data, initialized everything and then realized the indices aren't used. But I didn't remove them yet.&#xD;&#xA;&#xD;&#xA;Edit: and here is the framebuffer cube colored to show more of how it is being displayed (you may notice how on most faces the texture is applied in halves):&#xD;&#xA;&#xD;&#xA;[![the cube when colored][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KCtjJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BvEAn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4996" PostHistoryTypeId="5" PostId="2189" RevisionGUID="dede1917-86dc-4da6-bd41-88973a713070" CreationDate="2016-03-16T18:05:42.140" UserId="2508" Comment="added 21 characters in body" Text="I am doing exercises from the OpenGL SuperBible 6th Ed. I have managed to set up rendering into a framebuffer texture and then rendering from that texture to a cube.&#xD;&#xA;&#xD;&#xA;But for some reason, **when the texture gets applied to the cube, it is rendered incorrectly. I was expecting to see an entire rotating cube on a green background on each face of the main cube, but instead the faces have a texture applied as if split in half.**&#xD;&#xA;&#xD;&#xA;Here's a screenshot of my current situation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've spent a lot of time trying to fix this. I mean, the last 5 hours or so. I rewrote most of the code once and it fixed some of my previous erros, but now I'm stuck with this last part. &#xD;&#xA;&#xD;&#xA;I used the SB sources as reference (https://github.com/openglsuperbible/sb6code/blob/master/src/basicfbo/basicfbo.cpp), but I can't find the reason why it looks like this. &#xD;&#xA;&#xD;&#xA;I've also read this https://www.opengl.org/wiki/Framebuffer_Object_Examples but can't find a solution there.&#xD;&#xA;&#xD;&#xA;What did I miss?&#xD;&#xA;&#xD;&#xA;Here is my current code (the most important App class which does most of the work):&#xD;&#xA;&#xD;&#xA;    #include &quot;config.h&quot;&#xD;&#xA;    &#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &lt;GL/freeglut.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;App.h&quot;&#xD;&#xA;    #include &quot;GLSLProgram.h&quot;&#xD;&#xA;    &#xD;&#xA;    void App::renderToFramebuffer() {&#xD;&#xA;        float clearColor[] = { 0.0f, 0.5f, 0.0f, 1.0f };&#xD;&#xA;        float one = 1.0f;&#xD;&#xA;    &#xD;&#xA;        m_rotation += 1.0f;&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, 512, 512);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, clearColor);&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;one);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(-1.0f, -0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotationY = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationY);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(m_rotation), rotationX);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;start();&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;stop();&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::renderToScreen() {&#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, SCREEN_X, SCREEN_Y);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, glm::value_ptr(m_clearColor));&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;m_depthBufferDefault);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotation = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotation);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationX);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;start();&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(m_projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;stop();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::render() {&#xD;&#xA;        renderToFramebuffer();&#xD;&#xA;        renderToScreen();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::App() {&#xD;&#xA;        glEnable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;        glEnable(GL_CULL_FACE);&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glDepthFunc(GL_LEQUAL);&#xD;&#xA;    &#xD;&#xA;        m_clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        m_depthBufferDefault = 1.0f;&#xD;&#xA;        m_projectionMatrix = glm::perspective(50.0f, (float) SCREEN_X / (float) SCREEN_Y, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured = new GLSLProgram();&#xD;&#xA;        m_shaderNotTextured-&gt;addVertexShader(&quot;shaders/notex.vs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;addFragmentShader(&quot;shaders/notex.fs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured = new GLSLProgram();&#xD;&#xA;        m_shaderTextured-&gt;addVertexShader(&quot;shaders/tex.vs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;addFragmentShader(&quot;shaders/tex.fs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        glGenVertexArrays(1, &amp;m_VAO);&#xD;&#xA;        glGenBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    &#xD;&#xA;        glGenTextures(1, &amp;m_TBO);&#xD;&#xA;        glGenTextures(1, &amp;m_TDBO);&#xD;&#xA;    &#xD;&#xA;        glGenFramebuffers(1, &amp;m_FBO);&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, m_buffers[VBO]);&#xD;&#xA;            static const GLfloat vertex_data[] =&#xD;&#xA;            {&#xD;&#xA;                 // Position                 Tex Coord&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);&#xD;&#xA;            glEnableVertexAttribArray(0);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (2 * sizeof(GLfloat)));&#xD;&#xA;            glEnableVertexAttribArray(1);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512);&#xD;&#xA;    &#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TDBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_DEPTH_COMPONENT32F, 512, 512);&#xD;&#xA;    &#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_TBO, 0);&#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_TDBO, 0);&#xD;&#xA;    &#xD;&#xA;            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };&#xD;&#xA;            glDrawBuffers(1, drawBuffers);&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[IBO]);&#xD;&#xA;    &#xD;&#xA;            static const GLushort vertex_indices[] =&#xD;&#xA;            {&#xD;&#xA;                0, 1, 2,&#xD;&#xA;                2, 1, 3,&#xD;&#xA;                2, 3, 4,&#xD;&#xA;                4, 3, 5,&#xD;&#xA;                4, 5, 6,&#xD;&#xA;                6, 5, 7,&#xD;&#xA;                6, 7, 0,&#xD;&#xA;                0, 7, 1,&#xD;&#xA;                6, 0, 2,&#xD;&#xA;                2, 4, 6,&#xD;&#xA;                7, 5, 3,&#xD;&#xA;                7, 3, 1&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::~App() {&#xD;&#xA;        delete m_shaderNotTextured;&#xD;&#xA;        delete m_shaderTextured;&#xD;&#xA;        glDeleteBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void App::update() {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Also, I have no idea why in SB6 code they are creating an array of indices and then not using it. I copied the part of the code with vertex data, initialized everything and then realized the indices aren't used. But I didn't remove them yet.&#xD;&#xA;&#xD;&#xA;Edit: and here is the framebuffer cube colored to show more of how it is being displayed (you may notice how on most faces the texture is applied in halves):&#xD;&#xA;&#xD;&#xA;[![the cube when colored][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KCtjJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BvEAn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4997" PostHistoryTypeId="4" PostId="2189" RevisionGUID="490c20f0-d149-4dd8-9eda-decbe348b471" CreationDate="2016-03-16T18:26:09.243" UserId="2508" Comment="edited title" Text="Drawing to framebuffer texture - texture then split in half" ContentLicense="CC BY-SA 3.0" />
  <row Id="4998" PostHistoryTypeId="2" PostId="2193" RevisionGUID="27945a58-fee8-4221-b34c-2145df268557" CreationDate="2016-03-16T18:49:36.300" UserId="38" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A bad case of shadow acne. (Synthetic and a bit exagarated)&#xD;&#xA;&#xD;&#xA;Shadow acne is caused by the discrete nature of the shadow map. A shadow map is composed of samples, a surface is continuous. Thus, there can be a spot on the surface where the discrete surface is closer than the sample. The problem does persist even if you multi sample, but you can sample smarter in ways that can nearly eliminate this at significant cost.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2:** A side cutaway of a shadow function and its discrete samples.&#xD;&#xA;&#xD;&#xA;The canonical way to solve this is to offset the shadow map slightly so the object no longer self shadows itself. This offset is called a bias. One can use more smart offsets than just a fixed value but a fixed value works quite well and has minimal overhead.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3:** Shadow function biased (offset) forward.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/o7MUP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5HSkc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/SyZdy.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="4999" PostHistoryTypeId="5" PostId="2193" RevisionGUID="3ba918a6-d38e-4a3f-9e22-562e7e50aa53" CreationDate="2016-03-16T20:05:24.677" UserId="38" Comment="added 2 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A bad case of shadow acne. (Synthetic and a bit exaggerated)&#xD;&#xA;&#xD;&#xA;Shadow acne is caused by the discrete nature of the shadow map. A shadow map is composed of samples, a surface is continuous. Thus, there can be a spot on the surface where the discrete surface is further than the sample. The problem does persist even if you multi sample, but you can sample smarter in ways that can nearly eliminate this at significant cost.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2:** A side cutaway of a shadow function and its discrete samples.&#xD;&#xA;&#xD;&#xA;The canonical way to solve this is to offset the shadow map slightly so the object no longer self shadows itself. This offset is called a bias. One can use more smart offsets than just a fixed value but a fixed value works quite well and has minimal overhead.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 3:** Shadow function biased (offset) forward.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/o7MUP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5HSkc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/SyZdy.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5000" PostHistoryTypeId="2" PostId="2194" RevisionGUID="c750387f-0397-4d9c-b29a-2d236546283e" CreationDate="2016-03-17T08:34:35.613" UserId="1810" Text="No, because the underlying physics is not the same, nor the lobe shape - not to speak of their parameters such as color and Fresnel term.&#xD;&#xA;&#xD;&#xA;Specular is really true surface interaction with the dioptre material/air, so it has Fresnel modulation and the internal medium has no influence on colors. But the surface condition strongly influence the reflectance, of course. Think of it as the reflections on ocean surface.&#xD;&#xA;&#xD;&#xA;Diffuse is due to the subsurface scattering, light entering the medium, and thus gains the color characteristic and loose directionality. Think of it as the green color of the water turbidity. If depth of penetration is less than pixel size CG people don't call it &quot;subsurface&quot; but the physics is the same. Of course diffuse input is what specular let pass with is angle (and polarization) dependant." ContentLicense="CC BY-SA 3.0" />
  <row Id="5001" PostHistoryTypeId="5" PostId="2194" RevisionGUID="a76f4e9f-158f-4783-9a2b-642b740f9603" CreationDate="2016-03-17T08:40:39.630" UserId="1810" Comment="added 417 characters in body" Text="No, because the underlying physics is not the same, nor the lobe shape - not to speak of their parameters such as color and Fresnel term.&#xD;&#xA;&#xD;&#xA;Specular is really true surface interaction with the dioptre material/air, so it has Fresnel modulation and the internal medium has no influence on colors. But the surface condition strongly influence the reflectance, of course. Think of it as the reflections on ocean surface.&#xD;&#xA;&#xD;&#xA;Diffuse is due to the subsurface scattering, light entering the medium, and thus gains the color characteristic and loose directionality. Think of it as the green color of the water turbidity. If depth of penetration is less than pixel size CG people don't call it &quot;subsurface&quot; but the physics is the same. &#xD;&#xA;&#xD;&#xA;Of course diffuse input is what specular let pass, which is angle (and polarization) dependant. &#xD;&#xA;&#xD;&#xA;Beside, there exist transparent medium with internal dioptres (e.g. thin shells), so case exists were light goes inside but still acts specularely (or even wavely) and not diffusely. Oppositely, most plastics and paints/varnishs and biological medium are intrinsically transparent, but contain pigments (often based on a metal atom) that cause the opacity (diffusion or specular on these &quot;objects in the object&quot;). Think of them as the fishes in clear water :-) .&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5009" PostHistoryTypeId="2" PostId="2197" RevisionGUID="ed6d4cc2-faa0-4b42-b784-0c9752ea16e8" CreationDate="2016-03-17T13:44:31.807" UserId="273" Text="As an addition to the answer of joojaa:&#xD;&#xA;Using a bias to offset the shadow function does indeed solve the problem with shadow acne, but it can introduce an additional problem: Peter Panning&#xD;&#xA;&#xD;&#xA;[![Sample image that has Peter Panning][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you see in the picture on the left the shadow is disconnected from the shadow casting wall. This gives the impression that the geometry hovers over the ground (just like Peter Pan can hover, hence the name Peter Panning).&#xD;&#xA;&#xD;&#xA;To solve this problem you have to use &quot;thick&quot; geometry that has a volume and then render the shadow map using the back-faces. If the offset is smaller than the thickness of the geometry there will be no Peter Panning.&#xD;&#xA;&#xD;&#xA;[![Scene with thick geometry and thereby no Peter Panning][2]][2]&#xD;&#xA;&#xD;&#xA;Both images are taken from [this tutorial][3] where you can also learn more about how shadow mapping works, how shadow acne is created and solved and what Peter Panning is.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mdoX0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TwFxZ.png&#xD;&#xA;  [3]: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5010" PostHistoryTypeId="2" PostId="2198" RevisionGUID="a94d9807-b91f-498b-803c-787255f047db" CreationDate="2016-03-17T16:15:53.137" UserId="2896" Text="I have a set of closed loops on the surface of a non-self-intersecting triangle mesh, and I need to create inset versions of them on the surface of the mesh. In other words, I want to generate a [straight skeleton][1] from them.&#xD;&#xA;&#xD;&#xA;Within each single triangle of the mesh, this algorithm should behave just like a 2D straight skeleton.&#xD;&#xA;&#xD;&#xA;I've found several tools for offsetting loops of edges in a mesh, or generating loops equidistant from a point on the mesh, but I need to be able to input arbitrary loops of my own and offset them.&#xD;&#xA;&#xD;&#xA;I ran through various corner cases by hand on some graph paper, and it seems to me the algorithm described by [Felkel and Obdrzalek][2] should be perfectly applicable, except the wavefront may at times have to switch between contracting and expanding when it encounters geometries that give it more space.&#xD;&#xA;&#xD;&#xA;This algorithm seems like it would be useful in several CAM applications, does anyone know of an existing implementation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Straight_skeleton&#xD;&#xA;  [2]: http://www.dma.fi.upm.es/personal/mabellanas/tfcs/skeleton/html/documentacion/Straight%20Skeletons%20Implementation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="5011" PostHistoryTypeId="1" PostId="2198" RevisionGUID="a94d9807-b91f-498b-803c-787255f047db" CreationDate="2016-03-17T16:15:53.137" UserId="2896" Text="Can I run polygon insetting on the surface of a mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5012" PostHistoryTypeId="3" PostId="2198" RevisionGUID="a94d9807-b91f-498b-803c-787255f047db" CreationDate="2016-03-17T16:15:53.137" UserId="2896" Text="|geometry|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5020" PostHistoryTypeId="2" PostId="2201" RevisionGUID="a76ff930-0462-4276-9980-73303d870211" CreationDate="2016-03-18T09:08:55.750" UserId="2898" Text="Given a 3D object in Computer graphics, whose surface is represented as a 3D triangular mesh (mesh of 3D triangle objects), I need to find the maximum continual Convex patches on the surface of the given 3D object.&#xD;&#xA;&#xD;&#xA;I need to do it using OpenGl. What kind of methods or algorithms should I use to find the convex patches.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5021" PostHistoryTypeId="1" PostId="2201" RevisionGUID="a76ff930-0462-4276-9980-73303d870211" CreationDate="2016-03-18T09:08:55.750" UserId="2898" Text="maximal convex patching in Computer graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="5022" PostHistoryTypeId="3" PostId="2201" RevisionGUID="a76ff930-0462-4276-9980-73303d870211" CreationDate="2016-03-18T09:08:55.750" UserId="2898" Text="|opengl|3d|mesh|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5024" PostHistoryTypeId="5" PostId="2190" RevisionGUID="d93bd159-cca4-4e05-aab4-502e3e8922a4" CreationDate="2016-03-18T15:01:56.223" UserId="127" Comment="Edited formatting" Text="Different BRDFs are usually used to compute diffuse and specular reflection.  &#xD;&#xA;Some of the most often used include for example the Lambert BRDF for diffuse reflection and the Cook-Torrance BRDF for specular reflection.  &#xD;&#xA;Cook-Torrance BRDFs are parametrized by the surface roughness: the rougher the surface, the &quot;blurrier&quot; the reflection.  &#xD;&#xA;  &#xD;&#xA;From a conceptual point of view, should we consider that for an extremely rough surface, the specular reflection must look like a diffuse reflection? Can there be a continuity between both components of the reflection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5028" PostHistoryTypeId="6" PostId="2201" RevisionGUID="0441f09f-a24e-47a6-a225-a2a64a2abb4e" CreationDate="2016-03-19T02:20:53.197" UserId="48" Comment="edit tags" Text="|3d|mesh|computational-geometry|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5030" PostHistoryTypeId="5" PostId="2194" RevisionGUID="123e25aa-035c-486f-be2c-3d0495284db7" CreationDate="2016-03-19T04:42:47.883" UserId="1810" Comment="added 4 characters in body" Text="No, because the underlying physics is not the same, nor the lobe shape - not to speak of their parameters such as color and Fresnel term.&#xD;&#xA;&#xD;&#xA;Specular is really true surface interaction with the interface material/air, so it has Fresnel modulation and the internal medium has no influence on colors. But the surface condition strongly influence the reflectance, of course. Think of it as the reflections on ocean surface.&#xD;&#xA;&#xD;&#xA;Diffuse is due to the subsurface scattering, light entering the medium, and thus gains the color characteristic and loose directionality. Think of it as the green color of the water turbidity. If depth of penetration is less than pixel size CG people don't call it &quot;subsurface&quot; but the physics is the same. &#xD;&#xA;&#xD;&#xA;Of course diffuse input is what specular let pass, which is angle (and polarization) dependant. &#xD;&#xA;&#xD;&#xA;Beside, there exist transparent medium with internal interfaces (e.g. thin shells), so case exists were light goes inside but still acts specularely (or even wavely) and not diffusely. Oppositely, most plastics and paints/varnishs and biological medium are intrinsically transparent, but contain pigments (often based on a metal atom) that cause the opacity (diffusion or specular on these &quot;objects in the object&quot;). Think of them as the fishes in clear water :-) .&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5035" PostHistoryTypeId="5" PostId="2189" RevisionGUID="5462bc5e-9d68-41c8-9f74-97b1d9b924b4" CreationDate="2016-03-19T14:53:34.067" UserId="2508" Comment="added new screenshot to illustrate the framebuffer" Text="I am doing exercises from the OpenGL SuperBible 6th Ed. I have managed to set up rendering into a framebuffer texture and then rendering from that texture to a cube.&#xD;&#xA;&#xD;&#xA;But for some reason, **when the texture gets applied to the cube, it is rendered incorrectly. I was expecting to see an entire rotating cube on a green background on each face of the main cube, but instead the faces have a texture applied as if split in half.**&#xD;&#xA;&#xD;&#xA;Here's a screenshot of my current situation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've spent a lot of time trying to fix this. I mean, the last 5 hours or so. I rewrote most of the code once and it fixed some of my previous erros, but now I'm stuck with this last part. &#xD;&#xA;&#xD;&#xA;I used the SB sources as reference (https://github.com/openglsuperbible/sb6code/blob/master/src/basicfbo/basicfbo.cpp), but I can't find the reason why it looks like this. &#xD;&#xA;&#xD;&#xA;I've also read this https://www.opengl.org/wiki/Framebuffer_Object_Examples but can't find a solution there.&#xD;&#xA;&#xD;&#xA;What did I miss?&#xD;&#xA;&#xD;&#xA;Here is my current code (the most important App class which does most of the work):&#xD;&#xA;&#xD;&#xA;    #include &quot;config.h&quot;&#xD;&#xA;    &#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    #include &lt;GL/freeglut.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;App.h&quot;&#xD;&#xA;    #include &quot;GLSLProgram.h&quot;&#xD;&#xA;    &#xD;&#xA;    void App::renderToFramebuffer() {&#xD;&#xA;        float clearColor[] = { 0.0f, 0.5f, 0.0f, 1.0f };&#xD;&#xA;        float one = 1.0f;&#xD;&#xA;    &#xD;&#xA;        m_rotation += 1.0f;&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, 512, 512);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, clearColor);&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;one);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(-1.0f, -0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotationY = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationY);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(m_rotation), rotationX);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projectionMatrix = glm::perspective(50.0f, 1.0f, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;start();&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderNotTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured-&gt;stop();&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::renderToScreen() {&#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glViewport(0, 0, SCREEN_X, SCREEN_Y);&#xD;&#xA;        glClearBufferfv(GL_COLOR, 0, glm::value_ptr(m_clearColor));&#xD;&#xA;        glClearBufferfv(GL_DEPTH, 0, &amp;m_depthBufferDefault);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 modelView = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));&#xD;&#xA;        glm::vec3 rotation = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotation);&#xD;&#xA;        glm::vec3 rotationX = glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;        modelView = glm::rotate(modelView, glm::radians(45.0f), rotationX);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;start();&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(m_projectionMatrix, GL_PROJECTION_MATRIX);&#xD;&#xA;        m_shaderTextured-&gt;setMatrix(modelView, GL_MODELVIEW_MATRIX);&#xD;&#xA;    &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured-&gt;stop();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void App::render() {&#xD;&#xA;        renderToFramebuffer();&#xD;&#xA;        renderToScreen();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::App() {&#xD;&#xA;        glEnable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;        glEnable(GL_CULL_FACE);&#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;        glDepthFunc(GL_LEQUAL);&#xD;&#xA;    &#xD;&#xA;        m_clearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        m_depthBufferDefault = 1.0f;&#xD;&#xA;        m_projectionMatrix = glm::perspective(50.0f, (float) SCREEN_X / (float) SCREEN_Y, 1.0f, 1000.0f);&#xD;&#xA;    &#xD;&#xA;        m_shaderNotTextured = new GLSLProgram();&#xD;&#xA;        m_shaderNotTextured-&gt;addVertexShader(&quot;shaders/notex.vs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;addFragmentShader(&quot;shaders/notex.fs.glsl&quot;);&#xD;&#xA;        m_shaderNotTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        m_shaderTextured = new GLSLProgram();&#xD;&#xA;        m_shaderTextured-&gt;addVertexShader(&quot;shaders/tex.vs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;addFragmentShader(&quot;shaders/tex.fs.glsl&quot;);&#xD;&#xA;        m_shaderTextured-&gt;compile();&#xD;&#xA;    &#xD;&#xA;        glGenVertexArrays(1, &amp;m_VAO);&#xD;&#xA;        glGenBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    &#xD;&#xA;        glGenTextures(1, &amp;m_TBO);&#xD;&#xA;        glGenTextures(1, &amp;m_TDBO);&#xD;&#xA;    &#xD;&#xA;        glGenFramebuffers(1, &amp;m_FBO);&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(m_VAO);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, m_buffers[VBO]);&#xD;&#xA;            static const GLfloat vertex_data[] =&#xD;&#xA;            {&#xD;&#xA;                 // Position                 Tex Coord&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;                 0.25f,  0.25f, -0.25f,      1.0f, 1.0f,&#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f, -0.25f, -0.25f,      1.0f, 0.0f,&#xD;&#xA;                -0.25f, -0.25f, -0.25f,      0.0f, 0.0f,&#xD;&#xA;                -0.25f,  0.25f, -0.25f,      0.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;                 0.25f, -0.25f,  0.25f,      1.0f, 0.0f,&#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;    &#xD;&#xA;                 0.25f,  0.25f,  0.25f,      1.0f, 1.0f,&#xD;&#xA;                -0.25f,  0.25f,  0.25f,      0.0f, 1.0f,&#xD;&#xA;                -0.25f, -0.25f,  0.25f,      0.0f, 0.0f,&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);&#xD;&#xA;            glEnableVertexAttribArray(0);&#xD;&#xA;    &#xD;&#xA;            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *) (2 * sizeof(GLfloat)));&#xD;&#xA;            glEnableVertexAttribArray(1);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);&#xD;&#xA;    &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_RGBA8, 512, 512);&#xD;&#xA;    &#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            &#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, m_TDBO);&#xD;&#xA;                glTexStorage2D(GL_TEXTURE_2D, 9, GL_DEPTH_COMPONENT32F, 512, 512);&#xD;&#xA;    &#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_TBO, 0);&#xD;&#xA;            glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_TDBO, 0);&#xD;&#xA;    &#xD;&#xA;            GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };&#xD;&#xA;            glDrawBuffers(1, drawBuffers);&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[IBO]);&#xD;&#xA;    &#xD;&#xA;            static const GLushort vertex_indices[] =&#xD;&#xA;            {&#xD;&#xA;                0, 1, 2,&#xD;&#xA;                2, 1, 3,&#xD;&#xA;                2, 3, 4,&#xD;&#xA;                4, 3, 5,&#xD;&#xA;                4, 5, 6,&#xD;&#xA;                6, 5, 7,&#xD;&#xA;                6, 7, 0,&#xD;&#xA;                0, 7, 1,&#xD;&#xA;                6, 0, 2,&#xD;&#xA;                2, 4, 6,&#xD;&#xA;                7, 5, 3,&#xD;&#xA;                7, 3, 1&#xD;&#xA;            };&#xD;&#xA;    &#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    App::~App() {&#xD;&#xA;        delete m_shaderNotTextured;&#xD;&#xA;        delete m_shaderTextured;&#xD;&#xA;        glDeleteBuffers(NUM_BUFFERS, m_buffers);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void App::update() {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Also, I have no idea why in SB6 code they are creating an array of indices and then not using it. I copied the part of the code with vertex data, initialized everything and then realized the indices aren't used. But I didn't remove them yet.&#xD;&#xA;&#xD;&#xA;Edit: and here is the framebuffer cube colored to show more of how it is being displayed (you may notice how on most faces the texture is applied in halves):&#xD;&#xA;&#xD;&#xA;[![the cube when colored][2]][2]&#xD;&#xA;&#xD;&#xA;**Edit2: and this is what I get when I don't bind the framebuffer and instead draw to screen after changing cubes to quads** - so the image texture is being drawn correctly to the FB:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am thinking - maybe this has something to do with the size of the texture or the size of viewport when rendering? I'm still completely baffled by this...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KCtjJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BvEAn.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/SVXWI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5036" PostHistoryTypeId="5" PostId="2201" RevisionGUID="4937ed83-f1f0-417f-bc8b-adf3a80a4f32" CreationDate="2016-03-20T03:53:02.387" UserId="2898" Comment="better explain the question" Text="Given a 3D object in Computer graphics, whose surface is represented as a 3D triangular mesh (mesh of 3D triangle objects), I need to find the maximum continual Convex patches on the surface of the given 3D object.&#xD;&#xA;&#xD;&#xA;I am using OpenGl to render the graphics within a C++ program. What kind of methods or algorithms should I use to find the convex patches.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5037" PostHistoryTypeId="2" PostId="2204" RevisionGUID="520b1763-7507-4675-8b5c-3a445699ebd1" CreationDate="2016-03-20T03:54:01.847" UserId="2898" Text="&#xD;&#xA;&#xD;&#xA;Start from any triangle. Traverse it's edge's and check that the angle between the two triangles is less than 180deg. If it is add it to the current selection and continue expanding.&#xD;&#xA;&#xD;&#xA;The check is actually really simple if you use vector geometry. Say A - B is the common edge with C on the selected side and D on the other. Then just check if `dot(cross((A-B), (D-B)), cross((A-B), (C-B)) &lt; 0`.&#xD;&#xA;&#xD;&#xA;Unfortunately OpenGL doesn't help with object algorithms. It only handles converting triangles to pixels.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5038" PostHistoryTypeId="5" PostId="2204" RevisionGUID="282a8c4d-7602-483f-9f4d-6732fd9a42ac" CreationDate="2016-03-20T04:02:33.650" UserId="2898" Comment="remove unnecessary stub" Text="&#xD;&#xA;Start from any triangle. Traverse it's edge's and check that the angle between the two triangles is less than 180deg. If it is add it to the current selection and continue expanding.&#xD;&#xA;&#xD;&#xA;The check is actually really simple if you use vector geometry. Say A - B is the common edge with C on the selected side and D on the other. Then just check if `dot(cross((A-B), (D-B)), cross((A-B), (C-B)) &lt; 0`.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5039" PostHistoryTypeId="5" PostId="2201" RevisionGUID="6017497b-f37c-45d9-b475-84cb5bf7c8c0" CreationDate="2016-03-20T04:04:07.923" UserId="2898" Comment="provide more comprehensive description" Text="Given a 3D object in Computer graphics, whose surface is represented as a 3D triangular mesh (mesh of 3D triangle objects), I need to find the maximum continual Convex patches on the surface of the given 3D object.&#xD;&#xA;&#xD;&#xA;I am using OpenGl to render the graphics within a C++ program. What kind of methods or algorithms should I use to find the convex patches.&#xD;&#xA;&#xD;&#xA;I have to apply different colors to the different convex patches on the object to signify the selection. &#xD;&#xA;&#xD;&#xA;Say I have a sphere then the whole sphere is one maximal convex patch. Any portion of the sphere surface will be a convex patch, by maximal I mean the maximum continuous convex patch that can be found. Well in the rendering, depending on the viewing angles, the maximal convex patches visible to the viewer will have to colored.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5048" PostHistoryTypeId="2" PostId="2206" RevisionGUID="125d6ddf-8eef-48d0-b379-a36a5c8262b9" CreationDate="2016-03-20T21:24:10.253" UserId="2237" Text="I implemented a spectral path tracing using physically base BRDF models such as Oren-Nayar,Specular Reflection and Transmission, Lambertian. All calculation in the path tracer uses standard illuminant and macbeth color checker SPD, spectral power distribution. The result of the path tracer for each pixel is the SPD obtained as a sum of SPD obtained from each sample calculated by the pat tracer. This SPD is then converted to CIE XYZ color and to RGB. The result scene obtained is the following one (in this example taking 500 samples per pixel):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, everything seems fine, except for the brightness/luminance of the scene. Every object in the scene is darker than it have to be. The floor and the front wall of the cornell box in the scene must be white and neutral8 (from macbeth color checker), but they are dark gray.&#xD;&#xA;The following method is the one that tracer the samples for a pixel of the path tracer:&#xD;&#xA;&#xD;&#xA;    Vector3D PathTracer::getPixelColor(const Ray&amp; ray, int bounce) {&#xD;&#xA;    &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; L(0.0f);&#xD;&#xA;        int numberOfSamples = 500;&#xD;&#xA;        float sampleWeight = 1.0f/(float)numberOfSamples;&#xD;&#xA;    &#xD;&#xA;        for (int i = 0; i &lt; numberOfSamples; i++) {&#xD;&#xA;    &#xD;&#xA;            Spectrum&lt;constant::spectrumSamples&gt; spectrumSample = trace(ray, bounce);&#xD;&#xA;            L = L + spectrumSample * sampleWeight;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; Li = scene-&gt;light-&gt;spectrum;&#xD;&#xA;    &#xD;&#xA;        ColorMatchingFunction* colorMatchingFunction = new Standard2ObserverColorMatchingFunction();&#xD;&#xA;    &#xD;&#xA;        //Get tristimulus values.&#xD;&#xA;        Vector3D tristimulus = CIE1931XYZ::tristimulusValues(L, Li, colorMatchingFunction);&#xD;&#xA;    &#xD;&#xA;        //Convert tristimulus to sRGB.&#xD;&#xA;        Vector3D color = CIE1931XYZ::tristimulusTosRGB(tristimulus);&#xD;&#xA;    &#xD;&#xA;        //Apply sRGB gamma correction.&#xD;&#xA;        sRGB::sRGBGammaCorrection(color, GammaCompanding);&#xD;&#xA;    &#xD;&#xA;        //Convert to standard 0 - 255 RGB value.&#xD;&#xA;        sRGB::sRGBStandardRange(color);&#xD;&#xA;    &#xD;&#xA;        delete colorMatchingFunction;&#xD;&#xA;    &#xD;&#xA;        return color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can seen, I already apply a gamma correction to the color obtained. &#xD;&#xA;Do you have any idea why my image rendered is so dark? My concerns are in the part where I convert the SPD sum into RGB color. Do you see any error? Am I missing something? Do I need other operation to execute a correct conversion from the SPD obtained from the sampling to an RGB color?&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;To avoid to write a too long question, I will link the main classes used by the path tracer for the calculation:&#xD;&#xA;&#xD;&#xA;- Lighting/shading class used to recursive calculate the rendering equation https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Shading/PathBRDF.cpp &#xD;&#xA;- CIE XYZ conversion https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Color/CIEColorSpaces/CIEXYZ.cpp&#xD;&#xA;- sRGB utils https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Color/sRGB.hpp&#xD;&#xA;&#xD;&#xA;The other files/classes used are all on this repository (branch luminance)&#xD;&#xA;&#xD;&#xA;https://github.com/chicio/Spectrum-Clara-Lux-Tracer/tree/luminance&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Thanks you all guys, I hope someone could help me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8CdNZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5049" PostHistoryTypeId="1" PostId="2206" RevisionGUID="125d6ddf-8eef-48d0-b379-a36a5c8262b9" CreationDate="2016-03-20T21:24:10.253" UserId="2237" Text="Spectral path tracing - image color/brightness incorrect" ContentLicense="CC BY-SA 3.0" />
  <row Id="5050" PostHistoryTypeId="3" PostId="2206" RevisionGUID="125d6ddf-8eef-48d0-b379-a36a5c8262b9" CreationDate="2016-03-20T21:24:10.253" UserId="2237" Text="|color|color-science|brightness|pathtracing|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5051" PostHistoryTypeId="5" PostId="2206" RevisionGUID="67acaa69-423f-46bf-8d9d-e47f3d3bf7f5" CreationDate="2016-03-20T21:40:32.897" UserId="2237" Comment="added 28 characters in body" Text="I implemented a spectral path tracing using physically base BRDF models such as Oren-Nayar,Specular Reflection and Transmission, Lambertian. All calculation in the path tracer uses standard illuminant and macbeth color checker SPD, spectral power distribution. The result of the path tracer for each pixel is the SPD obtained as a sum of SPD obtained from each sample calculated by the pat tracer. This SPD is then converted to CIE XYZ color and to RGB. The result scene obtained is the following one (in this example taking 500 samples per pixel):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, everything seems fine, except for the brightness/luminance of the scene. Every object in the scene is darker than it have to be. The floor and the front wall of the cornell box in the scene must be white and neutral8 (from macbeth color checker), but they are dark gray.&#xD;&#xA;The following method is the one that tracer the samples for a pixel of the path tracer:&#xD;&#xA;&#xD;&#xA;    Vector3D PathTracer::getPixelColor(const Ray&amp; ray, int bounce) {&#xD;&#xA;    &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; L(0.0f);&#xD;&#xA;        int numberOfSamples = 500;&#xD;&#xA;        float sampleWeight = 1.0f/(float)numberOfSamples;&#xD;&#xA;    &#xD;&#xA;        for (int i = 0; i &lt; numberOfSamples; i++) {&#xD;&#xA;    &#xD;&#xA;            Spectrum&lt;constant::spectrumSamples&gt; spectrumSample = trace(ray, bounce);&#xD;&#xA;            L = L + spectrumSample * sampleWeight;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; Li = scene-&gt;light-&gt;spectrum;&#xD;&#xA;    &#xD;&#xA;        ColorMatchingFunction* colorMatchingFunction = new Standard2ObserverColorMatchingFunction();&#xD;&#xA;    &#xD;&#xA;        //Get tristimulus values.&#xD;&#xA;        Vector3D tristimulus = CIE1931XYZ::tristimulusValues(L, Li, colorMatchingFunction);&#xD;&#xA;    &#xD;&#xA;        //Convert tristimulus to sRGB.&#xD;&#xA;        Vector3D color = CIE1931XYZ::tristimulusTosRGB(tristimulus);&#xD;&#xA;    &#xD;&#xA;        //Apply sRGB gamma correction.&#xD;&#xA;        sRGB::sRGBGammaCorrection(color, GammaCompanding);&#xD;&#xA;    &#xD;&#xA;        //Convert to standard 0 - 255 RGB value.&#xD;&#xA;        sRGB::sRGBStandardRange(color);&#xD;&#xA;    &#xD;&#xA;        delete colorMatchingFunction;&#xD;&#xA;    &#xD;&#xA;        return color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can seen, I already apply a gamma correction to the color obtained. &#xD;&#xA;Do you have any idea why my image rendered is so dark? My concerns are in the part where I convert the SPD sum, obtained from the samples, into RGB color. Do you see any error? Am I missing something? Do I need other operation to execute a correct conversion from the SPD obtained from the sampling to an RGB color?&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;To avoid to write a too long question, I will link the main classes used by the path tracer for the calculation:&#xD;&#xA;&#xD;&#xA;- Lighting/shading class used to recursive calculate the rendering equation https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Shading/PathBRDF.cpp &#xD;&#xA;- CIE XYZ conversion https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Color/CIEColorSpaces/CIEXYZ.cpp&#xD;&#xA;- sRGB utils https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Color/sRGB.hpp&#xD;&#xA;&#xD;&#xA;The other files/classes used are all on this repository (branch luminance)&#xD;&#xA;&#xD;&#xA;https://github.com/chicio/Spectrum-Clara-Lux-Tracer/tree/luminance&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Thanks you all guys, I hope someone could help me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8CdNZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5052" PostHistoryTypeId="5" PostId="2206" RevisionGUID="04356714-42b9-49d4-9deb-d01e61a09d38" CreationDate="2016-03-20T23:21:29.253" UserId="2237" Comment="deleted 1 character in body" Text="I implemented a spectral path tracing using physically base BRDF models such as Oren-Nayar,Specular Reflection and Transmission, Lambertian. All calculation in the path tracer uses standard illuminant and macbeth color checker SPD, spectral power distribution. The result of the path tracer for each pixel is the SPD obtained as a sum of SPD obtained from each sample calculated by the pat tracer. This SPD is then converted to CIE XYZ color and to RGB. The result scene obtained is the following one (in this example taking 500 samples per pixel):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, everything seems fine, except for the brightness/luminance of the scene. Every object in the scene is darker than it have to be. The floor and the front wall of the cornell box in the scene must be white and neutral8 (from macbeth color checker), but they are dark gray.&#xD;&#xA;The following method is the one that trace the samples for a pixel of the path tracer:&#xD;&#xA;&#xD;&#xA;    Vector3D PathTracer::getPixelColor(const Ray&amp; ray, int bounce) {&#xD;&#xA;    &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; L(0.0f);&#xD;&#xA;        int numberOfSamples = 500;&#xD;&#xA;        float sampleWeight = 1.0f/(float)numberOfSamples;&#xD;&#xA;    &#xD;&#xA;        for (int i = 0; i &lt; numberOfSamples; i++) {&#xD;&#xA;    &#xD;&#xA;            Spectrum&lt;constant::spectrumSamples&gt; spectrumSample = trace(ray, bounce);&#xD;&#xA;            L = L + spectrumSample * sampleWeight;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        Spectrum&lt;constant::spectrumSamples&gt; Li = scene-&gt;light-&gt;spectrum;&#xD;&#xA;    &#xD;&#xA;        ColorMatchingFunction* colorMatchingFunction = new Standard2ObserverColorMatchingFunction();&#xD;&#xA;    &#xD;&#xA;        //Get tristimulus values.&#xD;&#xA;        Vector3D tristimulus = CIE1931XYZ::tristimulusValues(L, Li, colorMatchingFunction);&#xD;&#xA;    &#xD;&#xA;        //Convert tristimulus to sRGB.&#xD;&#xA;        Vector3D color = CIE1931XYZ::tristimulusTosRGB(tristimulus);&#xD;&#xA;    &#xD;&#xA;        //Apply sRGB gamma correction.&#xD;&#xA;        sRGB::sRGBGammaCorrection(color, GammaCompanding);&#xD;&#xA;    &#xD;&#xA;        //Convert to standard 0 - 255 RGB value.&#xD;&#xA;        sRGB::sRGBStandardRange(color);&#xD;&#xA;    &#xD;&#xA;        delete colorMatchingFunction;&#xD;&#xA;    &#xD;&#xA;        return color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can seen, I already apply a gamma correction to the color obtained. &#xD;&#xA;Do you have any idea why my image rendered is so dark? My concerns are in the part where I convert the SPD sum, obtained from the samples, into RGB color. Do you see any error? Am I missing something? Do I need other operation to execute a correct conversion from the SPD obtained from the sampling to an RGB color?&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;To avoid to write a too long question, I will link the main classes used by the path tracer for the calculation:&#xD;&#xA;&#xD;&#xA;- Lighting/shading class used to recursive calculate the rendering equation https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Shading/PathBRDF.cpp &#xD;&#xA;- CIE XYZ conversion https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Color/CIEColorSpaces/CIEXYZ.cpp&#xD;&#xA;- sRGB utils https://github.com/chicio/Spectrum-Clara-Lux-Tracer/blob/luminance/SCLT/Color/sRGB.hpp&#xD;&#xA;&#xD;&#xA;The other files/classes used are all on this repository (branch luminance)&#xD;&#xA;&#xD;&#xA;https://github.com/chicio/Spectrum-Clara-Lux-Tracer/tree/luminance&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Thanks you all guys, I hope someone could help me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8CdNZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5057" PostHistoryTypeId="2" PostId="2208" RevisionGUID="5e5abed0-a407-4bab-aa70-f81c805be7c4" CreationDate="2016-03-21T10:34:33.770" UserId="2712" Text="I have an .STL file (ascii and binary format) that contains several different CAD models. Is there any open-source api that read the file and create separate .stl files for each of the single different models. Even some hints/reference would be helpful&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="5058" PostHistoryTypeId="1" PostId="2208" RevisionGUID="5e5abed0-a407-4bab-aa70-f81c805be7c4" CreationDate="2016-03-21T10:34:33.770" UserId="2712" Text="Model Separation - Several models reside in a single .stl file" ContentLicense="CC BY-SA 3.0" />
  <row Id="5059" PostHistoryTypeId="3" PostId="2208" RevisionGUID="5e5abed0-a407-4bab-aa70-f81c805be7c4" CreationDate="2016-03-21T10:34:33.770" UserId="2712" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5060" PostHistoryTypeId="2" PostId="2209" RevisionGUID="7d3ce8b5-9ee9-4ef6-8917-cd9935564035" CreationDate="2016-03-21T10:58:05.043" UserId="38" Text="Software recommendation are not on topic. Instead I will explain how you separate the shapes. Each object is a separate volume so you can just extract all the continuous shells. You can do this simply by picking a vertex marking it as visited and then picking all connected vertices and marking them visited. You continue this visiting to new un-visited vertices until you no longer can find a connected vertex.&#xD;&#xA;&#xD;&#xA;This is a shell, in most cases a shell is a separate object. Unless there is a empty non connected cavity inside the object. This is rare but possible in 3d printing though not most other manufacturing methods. In this case you need to check that the shells do not intersect (they shouldn't or it means your model is broken anyway, nothing to fix) and if a shell lies inside another. You can do this by picking a point on the suspected interior shell and shooting a ray in a arbitrary direction. The shells that you hit a odd number of times are surrounding your main shell." ContentLicense="CC BY-SA 3.0" />
  <row Id="5064" PostHistoryTypeId="2" PostId="2210" RevisionGUID="42910e6e-cb99-4f2e-bcab-a43b7145c1bd" CreationDate="2016-03-21T12:18:35.620" UserId="2915" Text="Apparently Macintosh computers cannot handle the oculus rift, because of their 'iferior' graphics cards. But should VR not just be like an external monitor? And concerning computer graphics, how are VR games any different from other games the Macintosh can run easily?&#xD;&#xA;Where is the problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5065" PostHistoryTypeId="1" PostId="2210" RevisionGUID="42910e6e-cb99-4f2e-bcab-a43b7145c1bd" CreationDate="2016-03-21T12:18:35.620" UserId="2915" Text="How is VR different from a monitor" ContentLicense="CC BY-SA 3.0" />
  <row Id="5066" PostHistoryTypeId="3" PostId="2210" RevisionGUID="42910e6e-cb99-4f2e-bcab-a43b7145c1bd" CreationDate="2016-03-21T12:18:35.620" UserId="2915" Text="|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5067" PostHistoryTypeId="2" PostId="2211" RevisionGUID="a80b4941-2809-4f33-98d9-c91e486a2aaa" CreationDate="2016-03-21T12:25:53.360" UserId="137" Text="VR requires a much higher resolution and framerate, and a much lower latency (start of draw to showing on screen).&#xD;&#xA;&#xD;&#xA;If any of those things are missing then people tend to get nauseous. &#xD;&#xA;&#xD;&#xA;All of those require much higher bandwidth and compute power than the iferior cards are supposed to be able to handle." ContentLicense="CC BY-SA 3.0" />
  <row Id="5068" PostHistoryTypeId="2" PostId="2212" RevisionGUID="d19c3e55-a311-47c4-bde7-b0bad366bfcc" CreationDate="2016-03-21T14:18:13.233" UserId="2479" Text="The problem lies mainly in `CIE1931XYZ::tristimulusValues()` function, where you normalize the resulting color to the luminance of your illuminant which causes that directly observed light source has luminance 1, but everything else is much darker. That is a nice thing to do if you just want to visualize colours of various reflectance spectra under a given illumination, but is probably not the best thing to do in a global illumination renderer.&#xD;&#xA;&#xD;&#xA;To be more specific, you cannot expect a reflectance profile to be rendered always completely white just because it reflects all incident energy (constant spectral reflectance equal to 1 everywhere). Neglecting the material directional properties (BSDF, etc.), the properties of the light reflected from a point depend both on reflectance spectral profile of the material, and on the spectral and angular properties of the incident light. The incident light therefore depends not only on the SPD of the illuminant used for your light source, but also on its size and distance from the shaded point. The points closer to the light source will be brighter, while distant points will be darker.&#xD;&#xA;&#xD;&#xA;I would suggest removing the luminance normalization in your Spectrum-to-XYZ conversion completely and then adjusting the overall brightness of your scene by multiplying the normalized SPD of the used illuminant (D65 in your case) with some brightness parameter. Whether you multiply it before rendering, during rendering or during the XYZ conversion step is completely up to you. The choice shouldn't affect the result." ContentLicense="CC BY-SA 3.0" />
  <row Id="5069" PostHistoryTypeId="2" PostId="2213" RevisionGUID="0d79817d-254e-448d-9811-4409c2837428" CreationDate="2016-03-21T15:43:27.157" UserId="273" Text="A external monitor in most cases is only one viewport. Means you have a monoscopic image displayed.&#xD;&#xA;&#xD;&#xA;Having a HMD like Oculus Rift requires you to render your virtual scene for both eyes in order to have stereoscopic 3D. This is essential for the immersion and having immersion is the only reason to use a HMD.&#xD;&#xA;&#xD;&#xA;But rendering two viewports (one for each eye) does take additional computational power. Taking into account what ratchet freak already said it is even harder to maintain the high framerate und resolution at a low latency.&#xD;&#xA;&#xD;&#xA;To overcome this you need serious computational power and well some people think the hardware used by Apple does not provide enough of it." ContentLicense="CC BY-SA 3.0" />
  <row Id="5070" PostHistoryTypeId="5" PostId="2213" RevisionGUID="a0263354-fa4e-4192-897a-438f48e0f363" CreationDate="2016-03-21T15:46:59.243" UserId="38" Comment="edited body" Text="A external monitor in most cases is only one viewport. Means you have a monoscopic image displayed.&#xD;&#xA;&#xD;&#xA;Having a HMD like Oculus Rift requires you to render your virtual scene for both eyes in order to have stereoscopic 3D. This is essential for the immersion and having immersion is the only reason to use a HMD.&#xD;&#xA;&#xD;&#xA;But rendering two viewports (one for each eye) does take additional computational power. Taking into account what ratchet freak already said it is even harder to maintain the high framerate and resolution at a low latency.&#xD;&#xA;&#xD;&#xA;To overcome this you need serious computational power and well some people think the hardware used by Apple does not provide enough of it." ContentLicense="CC BY-SA 3.0" />
  <row Id="5071" PostHistoryTypeId="5" PostId="2211" RevisionGUID="f4bf1f58-d02b-42a2-be89-afde1d4274e3" CreationDate="2016-03-21T17:58:55.947" UserId="48" Comment="spelling" Text="VR requires a much higher resolution and framerate, and a much lower latency (start of draw to showing on screen).&#xD;&#xA;&#xD;&#xA;If any of those things are missing then people tend to get nauseous. &#xD;&#xA;&#xD;&#xA;All of those require much higher bandwidth and compute power than the inferior cards are supposed to be able to handle." ContentLicense="CC BY-SA 3.0" />
  <row Id="5072" PostHistoryTypeId="5" PostId="2210" RevisionGUID="caa1331d-211c-48a8-aa1b-528894bdc11a" CreationDate="2016-03-21T17:59:26.230" UserId="48" Comment="spelling" Text="Apparently Macintosh computers cannot handle the Oculus Rift, because of their 'inferior' graphics cards. But should VR not just be like an external monitor? And concerning computer graphics, how are VR games any different from other games the Macintosh can run easily?&#xD;&#xA;Where is the problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5073" PostHistoryTypeId="2" PostId="2214" RevisionGUID="2d081e28-bf2f-42d0-b1c1-fb741083aa3d" CreationDate="2016-03-21T20:19:13.870" UserId="2920" Text="A VR headset is a monitor, but the issue is more of software and the capabilities of Mac hardware.&#xA;&#xA;You are most likely referring to the founder of Oculus, Palmer Luckeey, and his comment on macs. He said:&#xA;&#xA;&gt;  &quot;You can buy a $6,000 Mac Pro with the top of the line AMD FirePro&#xA;&gt; D700, and it still doesn't match our recommended specs. So if they&#xA;&gt; prioritize higher-end GPUs like they used to for a while back in the&#xA;&gt; day, we'd love to support Mac. But right now, there's just not a&#xA;&gt; single machine out there that supports it.&quot;&#xA;&#xA;What he means is that not a single Mac has the high end gaming hardware necessary to provide the performance needed for a quality VR experience like the Rift.&#xA;&#xA;VR requires a very tight coupling of high performance hardware to provide low latency imagery. Macs have actually been behind other computers in terms of computer graphics performance and quality. A VR game requires a higher framerate than the average game, with minimums being much higher than the 30 or 60 frames per second that most normal games aim for. VR games need lower latency than the 60 Hz latency of 16.67 ms to be immersive and help prevent motion sickness. These requirements are not flexible. 60 Hz is doable, but it's often seen as the minimum, with many reporting sickness and physical symptoms from framerates of 60 Hz or lower that are reduced or minimized with higher framerates.&#xA;&#xA;Another factor is simply of market size. The percentage of the Mac market that has hardware capable of handling higher end games at all is an even smaller segment of an already smaller market. Apple's most popular products do not contain high end graphics chips, and instead use lower end integrated or mobile chips." ContentLicense="CC BY-SA 3.0" />
  <row Id="5074" PostHistoryTypeId="5" PostId="2214" RevisionGUID="6d636369-e7e9-4f73-a150-5367418858d6" CreationDate="2016-03-21T20:30:42.907" UserId="127" Comment="Removed doubled quote marks, capitalization of Mac" Text="A VR headset is a monitor, but the issue is more of software and the capabilities of Mac hardware.&#xD;&#xA;&#xD;&#xA;You are most likely referring to the founder of Oculus, Palmer Luckeey, and his comment on Macs. He said:&#xD;&#xA;&#xD;&#xA;&gt; You can buy a $6,000 Mac Pro with the top of the line AMD FirePro&#xD;&#xA;&gt; D700, and it still doesn't match our recommended specs. So if they&#xD;&#xA;&gt; prioritize higher-end GPUs like they used to for a while back in the&#xD;&#xA;&gt; day, we'd love to support Mac. But right now, there's just not a&#xD;&#xA;&gt; single machine out there that supports it.&#xD;&#xA;&#xD;&#xA;What he means is that not a single Mac has the high end gaming hardware necessary to provide the performance needed for a quality VR experience like the Rift.&#xD;&#xA;&#xD;&#xA;VR requires a very tight coupling of high performance hardware to provide low latency imagery. Macs have actually been behind other computers in terms of computer graphics performance and quality. A VR game requires a higher framerate than the average game, with minimums being much higher than the 30 or 60 frames per second that most normal games aim for. VR games need lower latency than the 60 Hz latency of 16.67 ms to be immersive and help prevent motion sickness. These requirements are not flexible. 60 Hz is doable, but it's often seen as the minimum, with many reporting sickness and physical symptoms from framerates of 60 Hz or lower that are reduced or minimized with higher framerates.&#xD;&#xA;&#xD;&#xA;Another factor is simply of market size. The percentage of the Mac market that has hardware capable of handling higher end games at all is an even smaller segment of an already smaller market. Apple's most popular products do not contain high end graphics chips, and instead use lower end integrated or mobile chips." ContentLicense="CC BY-SA 3.0" />
  <row Id="5075" PostHistoryTypeId="5" PostId="2214" RevisionGUID="88d2671f-8e5d-43e3-b6fc-a1c2f627c9fe" CreationDate="2016-03-21T21:00:52.663" UserId="2920" Comment="changed first sentence to clarify how a headset can be connected to but requires software" Text="A VR headset is a monitor in terms of connections that just requires special software, but the issue is more of software and the capabilities of Mac hardware.&#xD;&#xA;&#xD;&#xA;You are most likely referring to the founder of Oculus, Palmer Luckeey, and his comment on Macs. He said:&#xD;&#xA;&#xD;&#xA;&gt; You can buy a $6,000 Mac Pro with the top of the line AMD FirePro&#xD;&#xA;&gt; D700, and it still doesn't match our recommended specs. So if they&#xD;&#xA;&gt; prioritize higher-end GPUs like they used to for a while back in the&#xD;&#xA;&gt; day, we'd love to support Mac. But right now, there's just not a&#xD;&#xA;&gt; single machine out there that supports it.&#xD;&#xA;&#xD;&#xA;What he means is that not a single Mac has the high end gaming hardware necessary to provide the performance needed for a quality VR experience like the Rift.&#xD;&#xA;&#xD;&#xA;VR requires a very tight coupling of high performance hardware to provide low latency imagery. Macs have actually been behind other computers in terms of computer graphics performance and quality. A VR game requires a higher framerate than the average game, with minimums being much higher than the 30 or 60 frames per second that most normal games aim for. VR games need lower latency than the 60 Hz latency of 16.67 ms to be immersive and help prevent motion sickness. These requirements are not flexible. 60 Hz is doable, but it's often seen as the minimum, with many reporting sickness and physical symptoms from framerates of 60 Hz or lower that are reduced or minimized with higher framerates.&#xD;&#xA;&#xD;&#xA;Another factor is simply of market size. The percentage of the Mac market that has hardware capable of handling higher end games at all is an even smaller segment of an already smaller market. Apple's most popular products do not contain high end graphics chips, and instead use lower end integrated or mobile chips." ContentLicense="CC BY-SA 3.0" />
  <row Id="5076" PostHistoryTypeId="5" PostId="2211" RevisionGUID="b832d055-4837-4eec-aa69-27a33bd4f656" CreationDate="2016-03-21T21:28:50.607" UserId="137" Comment="deleted 5 characters in body" Text="VR requires a much higher resolution and framerate, and a much lower latency (start of draw to showing on screen).&#xD;&#xA;&#xD;&#xA;If any of those things are missing then people tend to get nauseous. &#xD;&#xA;&#xD;&#xA;All of those require much higher bandwidth and compute power than Apple's cards are supposed to be able to handle." ContentLicense="CC BY-SA 3.0" />
  <row Id="5077" PostHistoryTypeId="5" PostId="2211" RevisionGUID="88e8c53b-86d4-40f7-bb7e-b65455ed1d8d" CreationDate="2016-03-22T00:21:05.530" UserId="-1" Comment="nauseous -&gt; nauseated" Text="VR requires a much higher resolution and framerate, and a much lower latency (start of draw to showing on screen).&#xD;&#xA;&#xD;&#xA;If any of those things are missing then people tend to get nauseated. &#xD;&#xA;&#xD;&#xA;All of those require much higher bandwidth and compute power than Apple's cards are supposed to be able to handle." ContentLicense="CC BY-SA 3.0" />
  <row Id="5078" PostHistoryTypeId="24" PostId="2211" RevisionGUID="88e8c53b-86d4-40f7-bb7e-b65455ed1d8d" CreationDate="2016-03-22T00:21:05.530" Comment="Proposed by anonymous approved by 137 edit id of 127" ContentLicense="CC BY-SA 3.0" />
  <row Id="5083" PostHistoryTypeId="5" PostId="2213" RevisionGUID="dbae8c7c-1479-4618-94b8-da438ddebf79" CreationDate="2016-03-22T05:38:25.193" UserId="-1" Comment="added explanation for used abbreviation HMD" Text="A external monitor in most cases is only one viewport. Means you have a monoscopic image displayed.&#xD;&#xA;&#xD;&#xA;Having a HMD (Head-Mounted Display) like Oculus Rift requires you to render your virtual scene for both eyes in order to have stereoscopic 3D. This is essential for the immersion and having immersion is the only reason to use a HMD.&#xD;&#xA;&#xD;&#xA;But rendering two viewports (one for each eye) does take additional computational power. Taking into account what ratchet freak already said it is even harder to maintain the high framerate and resolution at a low latency.&#xD;&#xA;&#xD;&#xA;To overcome this you need serious computational power and well some people think the hardware used by Apple does not provide enough of it." ContentLicense="CC BY-SA 3.0" />
  <row Id="5084" PostHistoryTypeId="24" PostId="2213" RevisionGUID="dbae8c7c-1479-4618-94b8-da438ddebf79" CreationDate="2016-03-22T05:38:25.193" Comment="Proposed by anonymous approved by 127 edit id of 126" ContentLicense="CC BY-SA 3.0" />
  <row Id="5086" PostHistoryTypeId="2" PostId="2217" RevisionGUID="f7b5db2e-2d27-4b02-baab-f65bee1a76d2" CreationDate="2016-03-22T11:34:42.403" UserId="2936" Text="Macs are not gaming machines.  They never have been.  There was a time maybe 10-15 years ago when you could build a mid-tier gaming Mac, at significantly higher expense than a PC, but Macs have never catered to anything more than very casual gamers.  They don't run other games &quot;easily&quot; - they just adequately run *some* games, *barely* run others, and simply can't run a lot of popular titles (if they exist at all).&#xD;&#xA;&#xD;&#xA;Every Mac, with two exceptions, uses integrated graphics on their Intel chips.&#xD;&#xA;&#xD;&#xA;The MacBookPro can optionally can be fitted with a Radeon R9 370X, and the MacPro has the FirePro option above.  Let's look at 3D performance of these various options (The FirePro D700 is a Mac special - it's roughly in line with the specs of the W9000 PC variant):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The multi-thousand dollar FirePro is sitting there next to an old GTX 670 that you can pick up in used bargain bins these days.  So what gives?&#xD;&#xA;&#xD;&#xA;The FirePro is a professional GPU - it competes with NVidia's Quadro and Tesla line of cards.  It is designed specifically for precision workstation GPU tasks, particularly for double-precision calculations.  These are important for CAD/Architechtural and Engineering applications as well as for scientific computing.  The cards **can** be used just fine to play 3D games, but they are not optimized for that task and naturally underperform when compared to high end gaming GPUs like the GTX970/980, etc.&#xD;&#xA;&#xD;&#xA;Gaming GPUs dedicate resources to lower precision calculations (which they can do more of, and more quickly) and eye-candy goodies.  The tasks which they set themselves to are largely at odds with each other in terms of the style of hardware that is needed to get the job done.&#xD;&#xA;&#xD;&#xA;If you wanted to build a gaming mac right now, you really can't.  None of the systems available even have slots anymore to add in aftermarket GPUs (and they were twice the price of PC GPUs back in the days when you could, and came out months and months later than their PC counterparts so were always behind the cutting edge).  The only expandable Mac right now is the MacPro, and it is so ludicrously expensive that you would be crazy to try to make a gaming machine out of it (in fact, the hardware simply can't be had).  With expensive Xeon processors and FirePro graphics, the system is a highly specialized workstation that is firmly aimed at creative, scientific, and engineering professionals.  &#xD;&#xA;&#xD;&#xA;So where does that leave the Mac?  Absolutely, completely out of the gaming arena - full stop.  It's got enough juice to run a few very casual games at very modest quality for home users, but that's just about it.  The Oculus Rift needs major GPU horsepower.  For 3D it needs to compute every scene from two unique perspectives (one for each eye), instantly doubling the amount of pre-rendering calculation it needs to do.  It then needs to render each of these independent scenes to two independent displays and keep everything moving fast and smooth enough to not make you want to vomit or have some sort of seizure.  That means it needs a powerful gaming GPU, and these just aren't available for the Mac anywhere.&#xD;&#xA;  [1]: https://i.stack.imgur.com/fiOdu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5087" PostHistoryTypeId="2" PostId="2218" RevisionGUID="b741514a-a2ff-4551-8626-add42ba88cea" CreationDate="2016-03-22T13:34:43.987" UserId="2041" Text="[Shadertoy](https://www.shadertoy.com/) is a good website for playing with real-time visualizations. It uses WebGL and an in-page code editor, so you can edit a fragment shader and then run it live in your browser. One feature that was added (relatively) recently is the ability to connect a shader input to an audio stream - either from a pre-defined source, or from your microphone. You can also output sound from your shader by writing to a special `vec2` output. Here's [a list of examples that use mic input](https://www.shadertoy.com/results?query=&amp;sort=popular&amp;filter=soundinput)." ContentLicense="CC BY-SA 3.0" />
  <row Id="5089" PostHistoryTypeId="10" PostId="2160" RevisionGUID="7fef6af5-094a-47d5-a90d-8dc85500f64e" CreationDate="2016-03-22T17:20:14.490" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="5090" PostHistoryTypeId="2" PostId="2219" RevisionGUID="1c64d0b2-5baa-45f1-bab7-a8fc2d29ed19" CreationDate="2016-03-22T18:44:38.660" UserId="2287" Text="I clip a 3D triangle against a 3D Axis-Aligned Bounding Box (AABB) to obtain the largest planar polygon of the triangle contained in the AABB. My clipping algorithm is a (slightly modified) version of the robust (e.g. clipping planes have a small finite thickness) Sutherland-Hodgman algorithm as described in C. Ericson's Real-Time Collision Detection. I clip the triangle against each of the 6 planes constituting the AABB.&#xD;&#xA;&#xD;&#xA;In order to avoid heap (de)allocation, I allocated a fixed size point buffer on the stack in advance for all the vertices of the obtained planar polygon. My question now is: what is the maximum number of vertices possible one can obtain after clipping a triangle against an AABB? &#xD;&#xA;&#xD;&#xA;Based on the control flow, every examined vertex can result in two vertices during a polygon plane clipping. Thus 3*2^6 vertices. Due to symmetry this becomes 3*2^3=24 vertices. However, I always obtain less vertices in practice." ContentLicense="CC BY-SA 3.0" />
  <row Id="5091" PostHistoryTypeId="1" PostId="2219" RevisionGUID="1c64d0b2-5baa-45f1-bab7-a8fc2d29ed19" CreationDate="2016-03-22T18:44:38.660" UserId="2287" Text="Maximum #vertices after clipping a triangle against an AABB" ContentLicense="CC BY-SA 3.0" />
  <row Id="5092" PostHistoryTypeId="3" PostId="2219" RevisionGUID="1c64d0b2-5baa-45f1-bab7-a8fc2d29ed19" CreationDate="2016-03-22T18:44:38.660" UserId="2287" Text="|geometry|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5093" PostHistoryTypeId="2" PostId="2220" RevisionGUID="479bcd09-bd25-497d-904f-3fce6047529f" CreationDate="2016-03-22T19:22:55.100" UserId="48" Text="Funnily enough, I asked this exact question on Math.SE a couple years ago: [Maximum number of vertices in intersection of triangle with box](http://math.stackexchange.com/questions/859454/maximum-number-of-vertices-in-intersection-of-triangle-with-box/).&#xD;&#xA;&#xD;&#xA;The answer is 9 vertices, because each of the 6 planes of the box can cut off one corner of the polygon, replacing one vertex with two. So 3 vertices + 6 added vertices due to clipping = 9 total." ContentLicense="CC BY-SA 3.0" />
  <row Id="5095" PostHistoryTypeId="5" PostId="2219" RevisionGUID="70e3a34f-53aa-470a-9672-a8088ddda865" CreationDate="2016-03-22T20:09:13.100" UserId="127" Comment="Edited title, tags, added MathJax" Text="I clip a 3D triangle against a 3D Axis-Aligned Bounding Box (AABB) to obtain the largest planar polygon of the triangle contained in the AABB. My clipping algorithm is a (slightly modified) version of the robust (e.g. clipping planes have a small finite thickness) Sutherland-Hodgman algorithm as described in C. Ericson's Real-Time Collision Detection. I clip the triangle against each of the 6 planes constituting the AABB.&#xD;&#xA;&#xD;&#xA;In order to avoid heap (de)allocation, I allocated a fixed size point buffer on the stack in advance for all the vertices of the obtained planar polygon. My question now is: what is the maximum number of vertices possible one can obtain after clipping a triangle against an AABB? &#xD;&#xA;&#xD;&#xA;Based on the control flow, every examined vertex can result in two vertices during a polygon plane clipping. Thus $3*2^6$ vertices. Due to symmetry this becomes $3*2^3=24$ vertices. However, I always obtain less vertices in practice." ContentLicense="CC BY-SA 3.0" />
  <row Id="5096" PostHistoryTypeId="4" PostId="2219" RevisionGUID="70e3a34f-53aa-470a-9672-a8088ddda865" CreationDate="2016-03-22T20:09:13.100" UserId="127" Comment="Edited title, tags, added MathJax" Text="Maximum number of vertices after clipping a triangle against an AABB" ContentLicense="CC BY-SA 3.0" />
  <row Id="5097" PostHistoryTypeId="6" PostId="2219" RevisionGUID="70e3a34f-53aa-470a-9672-a8088ddda865" CreationDate="2016-03-22T20:09:13.100" UserId="127" Comment="Edited title, tags, added MathJax" Text="|3d|geometry|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5100" PostHistoryTypeId="2" PostId="2221" RevisionGUID="c1c97b1e-0a7a-4f35-b231-972b6cae90af" CreationDate="2016-03-23T14:26:57.420" UserId="2953" Text="Currently for a university assignment I have been given a 3D rendering engine, capable of rendering a 3D world. One task is to create a first person camera for it (I know with OpenGL you don't have a camera, you have to effect the modelview). &#xD;&#xA;&#xD;&#xA;Anyway, I have managed to get a working first person camera working, however rotation is becoming a bit of a problem. I have spent a good few hours trying to fix the problem, but can't seem to find a solution. &#xD;&#xA;&#xD;&#xA;Rotation works perfectly, until you move forward about -10 into the z axis. When you do, the camera rotation seemingly rotates around a set point, so it orbits the actual model, rather than just changing the direction the camera is looking at. &#xD;&#xA;&#xD;&#xA;So if you move out, then rotate, the camera will move around the object, not just move the object out of sight. &#xD;&#xA;&#xD;&#xA;Not sure what code you'll need to see to help, but here's some: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Camera Rotation:**&#xD;&#xA;&#xD;&#xA;    void Camera::RotateCamera(float yaw, float pitch, float roll)&#xD;&#xA;    {&#xD;&#xA;	//left and right rotation&#xD;&#xA;	Quaternion a;&#xD;&#xA;	Quaternion b;&#xD;&#xA;	Quaternion c;&#xD;&#xA;	Quaternion up;&#xD;&#xA;	Quaternion right;&#xD;&#xA;	Quaternion temp;&#xD;&#xA;	float s;&#xD;&#xA;	float vx;&#xD;&#xA;	float vy;&#xD;&#xA;	float vz;&#xD;&#xA;&#xD;&#xA;	if (yaw != 0)&#xD;&#xA;	{&#xD;&#xA;		s = cos(yaw / 2);&#xD;&#xA;		c.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_upVector[0] * sin(yaw / 2);&#xD;&#xA;		vy = m_upVector[1] * sin(yaw / 2);&#xD;&#xA;		vz = m_upVector[2] * sin(yaw / 2);&#xD;&#xA;		a.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		b.SetQuaternion(vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		up = a*c*b;&#xD;&#xA;&#xD;&#xA;		m_direction.SetVector(up[0], up[1], up[2]);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//up and down rotation&#xD;&#xA;	if (pitch != 0 &amp;&amp; curDown &lt; maxDown &amp;&amp; curDown &gt; -maxDown)&#xD;&#xA;	{&#xD;&#xA;		curDown += pitch;&#xD;&#xA;		s = cos(pitch / 2);&#xD;&#xA;&#xD;&#xA;		a.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_rightVector[0] * sin(pitch / 2);&#xD;&#xA;		vy = m_rightVector[1] * sin(pitch / 2);&#xD;&#xA;		vz = m_rightVector[2] * sin(pitch / 2);&#xD;&#xA;		b.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		c.SetQuaternion(-vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		right;&#xD;&#xA;		temp;&#xD;&#xA;		right = b * a * c;&#xD;&#xA;		m_direction.SetVector(right[0], right[1], right[2]);&#xD;&#xA;	}&#xD;&#xA;	m_direction.Normalise();&#xD;&#xA;	m_rightVector = m_direction.CrossProduct(m_upVector);&#xD;&#xA;	m_upVector = m_rightVector.CrossProduct(m_direction);&#xD;&#xA;&#xD;&#xA;	m_rightVector.Normalise();&#xD;&#xA;	m_upVector.Normalise();&#xD;&#xA;	UpdateViewMatrix();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The quaternion class is correct (so I'm assuming as it was already created for us) &#xD;&#xA;&#xD;&#xA;**Camera rotation code**&#xD;&#xA;&#xD;&#xA;    if (x - ox &gt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;	else if (x - ox &lt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(-0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	ox = x;&#xD;&#xA;	oy = y;&#xD;&#xA;&#xD;&#xA;**Applying the camera**&#xD;&#xA;&#xD;&#xA;    modelview = (*cam_pos-&gt;GetViewMatrix()) * modelview;&#xD;&#xA;	modelview = modelview*translation;&#xD;&#xA;&#xD;&#xA;	float aspect_ratio = (float)m_width / (float)m_height;&#xD;&#xA;	projection.SetPerspective(60.0f, aspect_ratio, 1.0f, 1000.0f);&#xD;&#xA;&#xD;&#xA;	glUniformMatrix4fv( m_uniform_projection, 1, GL_FALSE, projection.ToPtr() );&#xD;&#xA;	glBindSampler(0, m_texDefaultSampler);&#xD;&#xA;&#xD;&#xA;Where *cam_pos is the actual camera. &#xD;&#xA;&#xD;&#xA;Any help will greatly appreciated. The code works, just rotation goes off. &#xD;&#xA;Thanks! &#xD;&#xA;I know my variable names aren't the best, sorry!&#xD;&#xA;-R&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5101" PostHistoryTypeId="1" PostId="2221" RevisionGUID="c1c97b1e-0a7a-4f35-b231-972b6cae90af" CreationDate="2016-03-23T14:26:57.420" UserId="2953" Text="OpenGL C++ Camera Rotation Problem" ContentLicense="CC BY-SA 3.0" />
  <row Id="5102" PostHistoryTypeId="3" PostId="2221" RevisionGUID="c1c97b1e-0a7a-4f35-b231-972b6cae90af" CreationDate="2016-03-23T14:26:57.420" UserId="2953" Text="|opengl|rendering|c++|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5103" PostHistoryTypeId="11" PostId="1983" RevisionGUID="0918a9c1-3e5c-47d1-b341-f5ce00cd8ccf" CreationDate="2016-03-23T15:35:08.160" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="5104" PostHistoryTypeId="5" PostId="2221" RevisionGUID="116f848c-f5c5-40d6-8b14-4a0f8c30bc5c" CreationDate="2016-03-23T15:52:56.613" UserId="231" Comment="Minor tidying" Text="Currently for a university assignment I have been given a 3D rendering engine, capable of rendering a 3D world. One task is to create a first person camera for it (I know with OpenGL you don't have a camera, you have to effect the modelview). &#xD;&#xA;&#xD;&#xA;Anyway, I have managed to get a first person camera working, however rotation is becoming a bit of a problem. I have spent a good few hours trying to fix the problem, but can't seem to find a solution. &#xD;&#xA;&#xD;&#xA;Rotation works perfectly, until you move forward about -10 into the z axis. When you do, the camera rotation seemingly rotates around a set point, so it orbits the actual model, rather than just changing the direction the camera is looking at. &#xD;&#xA;&#xD;&#xA;So if you move out, then rotate, the camera will move around the object, not just move the object out of sight. &#xD;&#xA;&#xD;&#xA;Not sure what code you'll need to see to help, but here's some: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Camera Rotation:**&#xD;&#xA;&#xD;&#xA;    void Camera::RotateCamera(float yaw, float pitch, float roll)&#xD;&#xA;    {&#xD;&#xA;	//left and right rotation&#xD;&#xA;	Quaternion a;&#xD;&#xA;	Quaternion b;&#xD;&#xA;	Quaternion c;&#xD;&#xA;	Quaternion up;&#xD;&#xA;	Quaternion right;&#xD;&#xA;	Quaternion temp;&#xD;&#xA;	float s;&#xD;&#xA;	float vx;&#xD;&#xA;	float vy;&#xD;&#xA;	float vz;&#xD;&#xA;&#xD;&#xA;	if (yaw != 0)&#xD;&#xA;	{&#xD;&#xA;		s = cos(yaw / 2);&#xD;&#xA;		c.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_upVector[0] * sin(yaw / 2);&#xD;&#xA;		vy = m_upVector[1] * sin(yaw / 2);&#xD;&#xA;		vz = m_upVector[2] * sin(yaw / 2);&#xD;&#xA;		a.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		b.SetQuaternion(vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		up = a*c*b;&#xD;&#xA;&#xD;&#xA;		m_direction.SetVector(up[0], up[1], up[2]);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//up and down rotation&#xD;&#xA;	if (pitch != 0 &amp;&amp; curDown &lt; maxDown &amp;&amp; curDown &gt; -maxDown)&#xD;&#xA;	{&#xD;&#xA;		curDown += pitch;&#xD;&#xA;		s = cos(pitch / 2);&#xD;&#xA;&#xD;&#xA;		a.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_rightVector[0] * sin(pitch / 2);&#xD;&#xA;		vy = m_rightVector[1] * sin(pitch / 2);&#xD;&#xA;		vz = m_rightVector[2] * sin(pitch / 2);&#xD;&#xA;		b.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		c.SetQuaternion(-vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		right;&#xD;&#xA;		temp;&#xD;&#xA;		right = b * a * c;&#xD;&#xA;		m_direction.SetVector(right[0], right[1], right[2]);&#xD;&#xA;	}&#xD;&#xA;	m_direction.Normalise();&#xD;&#xA;	m_rightVector = m_direction.CrossProduct(m_upVector);&#xD;&#xA;	m_upVector = m_rightVector.CrossProduct(m_direction);&#xD;&#xA;&#xD;&#xA;	m_rightVector.Normalise();&#xD;&#xA;	m_upVector.Normalise();&#xD;&#xA;	UpdateViewMatrix();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The quaternion class is correct (so I'm assuming as it was already created for us). &#xD;&#xA;&#xD;&#xA;**Camera rotation code**&#xD;&#xA;&#xD;&#xA;    if (x - ox &gt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;	else if (x - ox &lt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(-0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	ox = x;&#xD;&#xA;	oy = y;&#xD;&#xA;&#xD;&#xA;**Applying the camera**&#xD;&#xA;&#xD;&#xA;    modelview = (*cam_pos-&gt;GetViewMatrix()) * modelview;&#xD;&#xA;	modelview = modelview*translation;&#xD;&#xA;&#xD;&#xA;	float aspect_ratio = (float)m_width / (float)m_height;&#xD;&#xA;	projection.SetPerspective(60.0f, aspect_ratio, 1.0f, 1000.0f);&#xD;&#xA;&#xD;&#xA;	glUniformMatrix4fv( m_uniform_projection, 1, GL_FALSE, projection.ToPtr() );&#xD;&#xA;	glBindSampler(0, m_texDefaultSampler);&#xD;&#xA;&#xD;&#xA;Where *cam_pos is the actual camera. &#xD;&#xA;&#xD;&#xA;The code works, just rotation goes off. &#xD;&#xA;&#xD;&#xA;I know my variable names aren't the best, sorry!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5105" PostHistoryTypeId="5" PostId="2221" RevisionGUID="7c408dc9-c8b1-491f-97a2-3c6bc6c25814" CreationDate="2016-03-23T17:20:03.783" UserId="2287" Comment="formatting" Text="Currently for a university assignment I have been given a 3D rendering engine, capable of rendering a 3D world. One task is to create a first person camera for it (I know with OpenGL you don't have a camera, you have to effect the modelview). &#xD;&#xA;&#xD;&#xA;Anyway, I have managed to get a first person camera working, however rotation is becoming a bit of a problem. I have spent a good few hours trying to fix the problem, but can't seem to find a solution. &#xD;&#xA;&#xD;&#xA;Rotation works perfectly, until you move forward about -10 into the z axis. When you do, the camera rotation seemingly rotates around a set point, so it orbits the actual model, rather than just changing the direction the camera is looking at. &#xD;&#xA;&#xD;&#xA;So if you move out, then rotate, the camera will move around the object, not just move the object out of sight. &#xD;&#xA;&#xD;&#xA;Not sure what code you'll need to see to help, but here's some: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Camera Rotation:**&#xD;&#xA;&#xD;&#xA;    void Camera::RotateCamera(float yaw, float pitch, float roll)&#xD;&#xA;    {&#xD;&#xA;	//left and right rotation&#xD;&#xA;	Quaternion a;&#xD;&#xA;	Quaternion b;&#xD;&#xA;	Quaternion c;&#xD;&#xA;	Quaternion up;&#xD;&#xA;	Quaternion right;&#xD;&#xA;	Quaternion temp;&#xD;&#xA;	float s;&#xD;&#xA;	float vx;&#xD;&#xA;	float vy;&#xD;&#xA;	float vz;&#xD;&#xA;&#xD;&#xA;	if (yaw != 0)&#xD;&#xA;	{&#xD;&#xA;		s = cos(yaw / 2);&#xD;&#xA;		c.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_upVector[0] * sin(yaw / 2);&#xD;&#xA;		vy = m_upVector[1] * sin(yaw / 2);&#xD;&#xA;		vz = m_upVector[2] * sin(yaw / 2);&#xD;&#xA;		a.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		b.SetQuaternion(vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		up = a*c*b;&#xD;&#xA;&#xD;&#xA;		m_direction.SetVector(up[0], up[1], up[2]);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//up and down rotation&#xD;&#xA;	if (pitch != 0 &amp;&amp; curDown &lt; maxDown &amp;&amp; curDown &gt; -maxDown)&#xD;&#xA;	{&#xD;&#xA;		curDown += pitch;&#xD;&#xA;		s = cos(pitch / 2);&#xD;&#xA;&#xD;&#xA;		a.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_rightVector[0] * sin(pitch / 2);&#xD;&#xA;		vy = m_rightVector[1] * sin(pitch / 2);&#xD;&#xA;		vz = m_rightVector[2] * sin(pitch / 2);&#xD;&#xA;		b.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		c.SetQuaternion(-vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		right;&#xD;&#xA;		temp;&#xD;&#xA;		right = b * a * c;&#xD;&#xA;		m_direction.SetVector(right[0], right[1], right[2]);&#xD;&#xA;	}&#xD;&#xA;	m_direction.Normalise();&#xD;&#xA;	m_rightVector = m_direction.CrossProduct(m_upVector);&#xD;&#xA;	m_upVector = m_rightVector.CrossProduct(m_direction);&#xD;&#xA;&#xD;&#xA;	m_rightVector.Normalise();&#xD;&#xA;	m_upVector.Normalise();&#xD;&#xA;	UpdateViewMatrix();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The quaternion class is correct (so I'm assuming as it was already created for us). &#xD;&#xA;&#xD;&#xA;**Camera rotation code**&#xD;&#xA;&#xD;&#xA;    if (x - ox &gt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;	else if (x - ox &lt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(-0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	ox = x;&#xD;&#xA;	oy = y;&#xD;&#xA;&#xD;&#xA;**Applying the camera**&#xD;&#xA;&#xD;&#xA;    modelview = (*cam_pos-&gt;GetViewMatrix()) * modelview;&#xD;&#xA;	modelview = modelview*translation;&#xD;&#xA;&#xD;&#xA;	float aspect_ratio = (float)m_width / (float)m_height;&#xD;&#xA;	projection.SetPerspective(60.0f, aspect_ratio, 1.0f, 1000.0f);&#xD;&#xA;&#xD;&#xA;	glUniformMatrix4fv( m_uniform_projection, 1, GL_FALSE, projection.ToPtr() );&#xD;&#xA;	glBindSampler(0, m_texDefaultSampler);&#xD;&#xA;&#xD;&#xA;Where `*cam_pos` is the actual camera. &#xD;&#xA;&#xD;&#xA;The code works, just rotation goes off." ContentLicense="CC BY-SA 3.0" />
  <row Id="5106" PostHistoryTypeId="24" PostId="2221" RevisionGUID="7c408dc9-c8b1-491f-97a2-3c6bc6c25814" CreationDate="2016-03-23T17:20:03.783" Comment="Proposed by 2287 approved by 2953 edit id of 128" ContentLicense="CC BY-SA 3.0" />
  <row Id="5107" PostHistoryTypeId="5" PostId="2221" RevisionGUID="87ac6f51-5abe-4e6c-b68c-ab96e4f35a6e" CreationDate="2016-03-23T19:39:30.300" UserId="2953" Comment="added 123 characters in body" Text="Currently for a university assignment I have been given a 3D rendering engine, capable of rendering a 3D world. One task is to create a first person camera for it (I know with OpenGL you don't have a camera, you have to effect the modelview). &#xD;&#xA;&#xD;&#xA;Anyway, I have managed to get a first person camera working, however rotation is becoming a bit of a problem. I have spent a good few hours trying to fix the problem, but can't seem to find a solution. &#xD;&#xA;&#xD;&#xA;Rotation works perfectly, until you move forward about -10 into the z axis. When you do, the camera rotation seemingly rotates around a set point, so it orbits the actual model, rather than just changing the direction the camera is looking at. &#xD;&#xA;&#xD;&#xA;So if you move out, then rotate, the camera will move around the object, not just move the object out of sight. &#xD;&#xA;&#xD;&#xA;Not sure what code you'll need to see to help, but here's some: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Camera Rotation:**&#xD;&#xA;&#xD;&#xA;    void Camera::RotateCamera(float yaw, float pitch, float roll)&#xD;&#xA;    {&#xD;&#xA;	//left and right rotation&#xD;&#xA;	Quaternion a;&#xD;&#xA;	Quaternion b;&#xD;&#xA;	Quaternion c;&#xD;&#xA;	Quaternion up;&#xD;&#xA;	Quaternion right;&#xD;&#xA;	Quaternion temp;&#xD;&#xA;	float s;&#xD;&#xA;	float vx;&#xD;&#xA;	float vy;&#xD;&#xA;	float vz;&#xD;&#xA;&#xD;&#xA;	if (yaw != 0)&#xD;&#xA;	{&#xD;&#xA;		s = cos(yaw / 2);&#xD;&#xA;		c.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_upVector[0] * sin(yaw / 2);&#xD;&#xA;		vy = m_upVector[1] * sin(yaw / 2);&#xD;&#xA;		vz = m_upVector[2] * sin(yaw / 2);&#xD;&#xA;		a.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		b.SetQuaternion(vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		up = a*c*b;&#xD;&#xA;&#xD;&#xA;		m_direction.SetVector(up[0], up[1], up[2]);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//up and down rotation&#xD;&#xA;	if (pitch != 0 &amp;&amp; curDown &lt; maxDown &amp;&amp; curDown &gt; -maxDown)&#xD;&#xA;	{&#xD;&#xA;		curDown += pitch;&#xD;&#xA;		s = cos(pitch / 2);&#xD;&#xA;&#xD;&#xA;		a.SetQuaternion(m_direction, s);&#xD;&#xA;		vx = m_rightVector[0] * sin(pitch / 2);&#xD;&#xA;		vy = m_rightVector[1] * sin(pitch / 2);&#xD;&#xA;		vz = m_rightVector[2] * sin(pitch / 2);&#xD;&#xA;		b.SetQuaternion(vx, vy, vz, s);&#xD;&#xA;		c.SetQuaternion(-vx, -vy, -vz, s);&#xD;&#xA;&#xD;&#xA;		right;&#xD;&#xA;		temp;&#xD;&#xA;		right = b * a * c;&#xD;&#xA;		m_direction.SetVector(right[0], right[1], right[2]);&#xD;&#xA;	}&#xD;&#xA;	m_direction.Normalise();&#xD;&#xA;	m_rightVector = m_direction.CrossProduct(m_upVector);&#xD;&#xA;	m_upVector = m_rightVector.CrossProduct(m_direction);&#xD;&#xA;&#xD;&#xA;	m_rightVector.Normalise();&#xD;&#xA;	m_upVector.Normalise();&#xD;&#xA;	UpdateViewMatrix();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The quaternion class is correct (so I'm assuming as it was already created for us). &#xD;&#xA;&#xD;&#xA;**Camera rotation code**&#xD;&#xA;&#xD;&#xA;    if (x - ox &gt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;	else if (x - ox &lt; 0)&#xD;&#xA;	{&#xD;&#xA;		cam_pos-&gt;RotateCamera(-0.05, 0, 0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	ox = x;&#xD;&#xA;	oy = y;&#xD;&#xA;&#xD;&#xA;**Applying the camera**&#xD;&#xA;&#xD;&#xA;    modelview = (*cam_pos-&gt;GetViewMatrix()) * modelview;&#xD;&#xA;	modelview = modelview*translation;&#xD;&#xA;&#xD;&#xA;	float aspect_ratio = (float)m_width / (float)m_height;&#xD;&#xA;	projection.SetPerspective(60.0f, aspect_ratio, 1.0f, 1000.0f);&#xD;&#xA;&#xD;&#xA;	glUniformMatrix4fv( m_uniform_projection, 1, GL_FALSE, projection.ToPtr() );&#xD;&#xA;	glBindSampler(0, m_texDefaultSampler);&#xD;&#xA;&#xD;&#xA;Where `*cam_pos` is the actual camera. &#xD;&#xA;&#xD;&#xA;The code works, just rotation goes off.&#xA;&#xA;This is what currently happens on rotation: &#xA;[![weird rotation effect][1]][1]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/5ptng.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5108" PostHistoryTypeId="2" PostId="2222" RevisionGUID="1e6f1cab-5330-4828-9203-e5562e0cc7c6" CreationDate="2016-03-23T20:28:13.507" UserId="2954" Text="I'm trying to write a raytracer to render boxes (cubes) that are arbitrarily rotated, i.e. not necessarily axis aligned. While I'm reasonably comfortable ray-tracing an axis-aligned cube, I don't know how to work with non-axis aligned objects. The geometry becomes quite difficult. I've looked through a textbook (*Ray Tracing from the Ground Up*) but couldn't find an answer.&#xD;&#xA;&#xD;&#xA;How should I do it? Detailed suggestions would be greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="5109" PostHistoryTypeId="1" PostId="2222" RevisionGUID="1e6f1cab-5330-4828-9203-e5562e0cc7c6" CreationDate="2016-03-23T20:28:13.507" UserId="2954" Text="How to convert Non-Axis Aligned Bounding Boxes to AABB" ContentLicense="CC BY-SA 3.0" />
  <row Id="5110" PostHistoryTypeId="3" PostId="2222" RevisionGUID="1e6f1cab-5330-4828-9203-e5562e0cc7c6" CreationDate="2016-03-23T20:28:13.507" UserId="2954" Text="|raytracing|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5112" PostHistoryTypeId="2" PostId="2223" RevisionGUID="edad5ec3-5a70-4c1a-83cb-f6a05dcb82d1" CreationDate="2016-03-24T01:21:13.737" UserId="2957" Text="Windows 10 ships with &quot;3D Builder&quot;, a Universal App that contains utility functions to prepare STL, OBJ, 3DS, and other files that represent geometries for 3D printing.&#xD;&#xA;&#xD;&#xA;The utility looks like this:&#xD;&#xA;[![3D Builder][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In particular, they have triangle mesh functions there that:&#xD;&#xA;&#xD;&#xA; - &quot;Detect&quot; when a mesh is not suitable for 3D printing;&#xD;&#xA; - &quot;Repair&quot; so that the mesh isn't right it prepares it, by removing internal faces, closing &quot;holes&quot; in the outer surface, etc.;&#xD;&#xA; - &quot;Simplify&quot; by removing redundant triangles, such as those found to be adjacent and co-planar; and&#xD;&#xA; - &quot;Plane Cut&quot;, slicing a mesh through an arbitrarily positioned plane and filling in a surface on that plane to re-enclose the geometry, sometimes followed by a &quot;Detect&quot; and &quot;Repair&quot;.&#xD;&#xA;&#xD;&#xA;Every copy of Windows 8.1 and 10 has this utility at no additional cost. That says to me that the functions are well-known and as far as I've been able to test, reliable for virtually all inputs to the 3D printing use case. I used some of the messiest STL files I could find to prove this thing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Which algorithms did they use for those functions? Where are they found for a .NET/WPF/UWP environment?**&#xD;&#xA;&#xD;&#xA;More to the point, did they expose the functions in an API I can use for a slightly dissimilar use case? &#xD;&#xA;&#xD;&#xA;In the builder the functions look like this:&#xD;&#xA;&#xD;&#xA;Simplify (the tractor top and sides have fewer facets):&#xD;&#xA;&#xD;&#xA;[![Simplify Output][2]][2]&#xD;&#xA;&#xD;&#xA;Slice, UI before processing:&#xD;&#xA;&#xD;&#xA;[![Slice, UI before processing][3]][3]&#xD;&#xA;&#xD;&#xA;Slice, after processing and then one &quot;Simplify&quot; pass:&#xD;&#xA;&#xD;&#xA;[![Slice, after processing][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N3VXd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qAAr2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/GYHQV.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/PDt95.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5113" PostHistoryTypeId="1" PostId="2223" RevisionGUID="edad5ec3-5a70-4c1a-83cb-f6a05dcb82d1" CreationDate="2016-03-24T01:21:13.737" UserId="2957" Text="Which 3D algorithms does Windows 10's &quot;3D Builder&quot; application use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5114" PostHistoryTypeId="3" PostId="2223" RevisionGUID="edad5ec3-5a70-4c1a-83cb-f6a05dcb82d1" CreationDate="2016-03-24T01:21:13.737" UserId="2957" Text="|algorithm|3d|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5115" PostHistoryTypeId="2" PostId="2224" RevisionGUID="b986d13f-3720-4acb-ae18-9d9d0c1f2e0e" CreationDate="2016-03-24T01:30:05.193" UserId="2957" Text="I need to find an approach to the problem of generating texture maps for non-convex polyhedrons without using a design tool like Maya. Specifically, I am mapping simulation results data onto a 3D surface, and I need to write code which generates the maps.&#xD;&#xA;&#xD;&#xA;One generic approach uses a gradient color brush as an overall texture to just map colors, but if the facets in the polyhedron are very narrow or the mapped (u,v) coordinates are very far apart on the same facet, the image gets noisy. Another approach employs Phong or Gouraud Shading, but those features are missing in some 3D libraries which favor texturing over specifying colors at each vertex. So, I'm looking for a way to get a good texture map generated.&#xD;&#xA;&#xD;&#xA;If it helps in identifying a correct algorithm, all of the surfaces entirely enclose a 3-D space, there is no facet normal data, and I'll be able to identify a &quot;parting line&quot; which segregates one part of the surface from the other, as one might in order to create a mold for the shape.&#xD;&#xA;&#xD;&#xA;The simulation results are uniform (non-sparse) 3D arrays containing single precision values. There is a neighboring array of short integers which approximates the 3D mesh; a &quot;1&quot; value in that array corresponds to a part of the enclosed region of the polyhedron. I'm mapping to non-convex 3D surfaces more complex than can be mapped with a simple unrolling texture mapper or a spherical ray casting approach. Think of an American gallon milk jug or similar shapes that can be produced in plastic or metal molds." ContentLicense="CC BY-SA 3.0" />
  <row Id="5116" PostHistoryTypeId="1" PostId="2224" RevisionGUID="b986d13f-3720-4acb-ae18-9d9d0c1f2e0e" CreationDate="2016-03-24T01:30:05.193" UserId="2957" Text="Generate complex (non-convex) polyhedron UV mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="5117" PostHistoryTypeId="3" PostId="2224" RevisionGUID="b986d13f-3720-4acb-ae18-9d9d0c1f2e0e" CreationDate="2016-03-24T01:30:05.193" UserId="2957" Text="|texture|algorithm|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5118" PostHistoryTypeId="2" PostId="2225" RevisionGUID="ca149384-c131-4bcc-83cc-10a1a0c0f0c7" CreationDate="2016-03-24T07:59:15.040" UserId="2287" Text="You can assign a coordinate system to each nAABB in such a way that the nAABB becomes an AABB in its own coordinate system. We call this a local coordinate system.&#xD;&#xA;&#xD;&#xA;I assume rays are expressed in a world or global coordinate system. In order to test an nAABB for intersection, one first needs to apply the world-to-local transformation on the ray (origin and direction). This way we obtain a transformed ray which we can intersect with an AABB. Once an intersection point is found, we need to transform this back to world space via the inverse transformation (i.e. local-to-world transformation).&#xD;&#xA;&#xD;&#xA;In practice an nAABB is thus expressed as an AABB with a pair of world-to-local and local-to-world transformation matrices.&#xD;&#xA;&#xD;&#xA;If one applies a scaling ($S$) or translation ($T$) on an AABB, one obtains another AABB. If one applies a rotation ($R$) on an AABB, one obtains a nAABB.&#xD;&#xA;Typically the corresponding transformation matrices are multiplied as follows $T * R * S$. Thus translation is applied after rotation. Since the $R$ component must be included in the world-to-local transformation, you need to include the $T$ component as well. The $S$ component can be included or directly applied to a unit AABB centered at the origin of the world-coordinate system.&#xD;&#xA;&#xD;&#xA;Including a $T$ component requires your world-to-local and local-to-world transformation matrices to be of size $4$x$4$ (expressed in homogeneous coordinates).&#xD;&#xA;&#xD;&#xA;[Here][1] you can find C++ code to construct all the $4$x$4$ world-to-local matrices and their inverses, you probably need.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v2/blob/master/src/core/transform.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="5119" PostHistoryTypeId="5" PostId="2225" RevisionGUID="70c22351-14bf-4f84-b7af-5950be0ae541" CreationDate="2016-03-24T08:06:14.213" UserId="2287" Comment="added 12 characters in body" Text="You can assign a coordinate system to each nAABB in such a way that the nAABB becomes an AABB in its own coordinate system. We call this a *local coordinate system*.&#xD;&#xA;&#xD;&#xA;I assume rays are expressed in a *world* or *global coordinate system*. In order to test an nAABB for intersection, one first needs to apply the *world-to-local transformation* on the ray (origin and direction). This way we obtain a transformed ray which we can intersect with an AABB. Once an intersection point is found, we need to transform this back to world space via the inverse transformation (i.e. *local-to-world transformation*).&#xD;&#xA;&#xD;&#xA;In practice an nAABB is thus expressed as an AABB with a pair of world-to-local and local-to-world transformation matrices.&#xD;&#xA;&#xD;&#xA;If one applies a scaling ($S$) or translation ($T$) on an AABB, one obtains another AABB. If one applies a rotation ($R$) on an AABB, one obtains a nAABB.&#xD;&#xA;Typically the corresponding transformation matrices are multiplied as follows $T * R * S$. Thus translation is applied after rotation. Since the $R$ component must be included in the world-to-local transformation, you need to include the $T$ component as well. The $S$ component can be included or directly applied to a unit AABB centered at the origin of the world-coordinate system.&#xD;&#xA;&#xD;&#xA;Including a $T$ component requires your world-to-local and local-to-world transformation matrices to be of size $4$x$4$ (expressed in *homogeneous coordinates*).&#xD;&#xA;&#xD;&#xA;[Here][1] you can find C++ code to construct all the $4$x$4$ world-to-local matrices and their inverses, you probably need.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v2/blob/master/src/core/transform.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="5120" PostHistoryTypeId="5" PostId="2225" RevisionGUID="85da64b8-7cd5-48d7-9b21-a1af720feb80" CreationDate="2016-03-24T08:14:22.637" UserId="2287" Comment="added 139 characters in body" Text="You can assign a coordinate system to each nAABB in such a way that the nAABB becomes an AABB in its own coordinate system. We call this a *local coordinate system*.&#xD;&#xA;&#xD;&#xA;I assume rays are expressed in a *world* or *global coordinate system*. In order to test an nAABB for intersection, one first needs to apply the *world-to-local transformation* on the ray (origin and direction). This way we obtain a transformed ray which we can intersect with an AABB. Once an intersection point is found, we need to transform this back to world space via the inverse transformation (i.e. *local-to-world transformation*).&#xD;&#xA;&#xD;&#xA;In practice an nAABB is thus expressed as an AABB with a pair of world-to-local and local-to-world transformation matrices.&#xD;&#xA;&#xD;&#xA;If one applies a scaling ($S$) or translation ($T$) on an AABB, one obtains another AABB. If one applies a rotation ($R$) on an AABB, one obtains a nAABB.&#xD;&#xA;Typically the corresponding transformation matrices are multiplied as follows $T * R * S$. Thus translation is applied after rotation. Since the $R$ component must be included in the world-to-local transformation, you need to include the $T$ component as well. The $S$ component can be included or directly applied to a unit AABB centered at the origin of the world-coordinate system. Including a $T$ component requires your world-to-local and local-to-world transformation matrices to be of size $4$x$4$ (expressed in *homogeneous coordinates*).&#xD;&#xA;&#xD;&#xA;[Here][1] you can find C++ code to construct all the $4$x$4$ world-to-local matrices and their inverses, you probably need.&#xD;&#xA;&#xD;&#xA;Note that this approach works for other geometrical objects as well (if the transformations involve scaling, rotation and translation).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v2/blob/master/src/core/transform.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="5121" PostHistoryTypeId="5" PostId="2225" RevisionGUID="4ee410ce-9cec-41bb-9516-61c1c443177a" CreationDate="2016-03-24T08:24:24.030" UserId="2287" Comment="deleted 1 character in body" Text="You can assign a coordinate system to each nAABB in such a way that the nAABB becomes an AABB in its own coordinate system. We call this a *local coordinate system*.&#xD;&#xA;&#xD;&#xA;I assume rays are expressed in a *world* or *global coordinate system*. In order to test an nAABB for intersection, one first needs to apply the *world-to-local transformation* on the ray (origin and direction). This way we obtain a transformed ray which we can intersect with an AABB. Once an intersection point is found, we need to transform this back to world space via the inverse transformation (i.e. *local-to-world transformation*).&#xD;&#xA;&#xD;&#xA;In practice an nAABB is thus expressed as an AABB with a pair of world-to-local and local-to-world transformation matrices.&#xD;&#xA;&#xD;&#xA;If one applies a scaling ($S$) or translation ($T$) on an AABB, one obtains another AABB. If one applies a rotation ($R$) on an AABB, one obtains a nAABB.&#xD;&#xA;Typically the corresponding transformation matrices are multiplied as follows $T * R * S$. Thus translation is applied after rotation. Since the $R$ component must be included in the world-to-local transformation, you need to include the $T$ component as well. The $S$ component can be included or directly applied to a unit AABB centered at the origin of the world-coordinate system. Including a $T$ component requires your world-to-local and local-to-world transformation matrices to be of size $4$x$4$ (expressed in *homogeneous coordinates*).&#xD;&#xA;&#xD;&#xA;[Here][1] you can find C++ code to construct all the $4$x$4$ world-to-local matrices and their inverses you probably need.&#xD;&#xA;&#xD;&#xA;Note that this approach works for other geometrical objects as well (if the transformations involve scaling, rotation and translation).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v2/blob/master/src/core/transform.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="5122" PostHistoryTypeId="5" PostId="2222" RevisionGUID="c6645d9c-19fc-4651-be03-61635a96b7e9" CreationDate="2016-03-24T08:41:02.513" UserId="2287" Comment="formatting" Text="I am trying to write a ray tracer to render boxes (cubes) that are arbitrarily rotated, i.e. not necessarily axis aligned. While I am reasonably comfortable ray tracing an axis-aligned cube (AABB), I don't know how to handle non-axis aligned objects. The geometry becomes quite difficult. I've looked through a textbook (*Ray Tracing from the Ground Up*) but couldn't find an answer.&#xD;&#xA;&#xD;&#xA;How should I do it? Detailed suggestions would be greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="5123" PostHistoryTypeId="24" PostId="2222" RevisionGUID="c6645d9c-19fc-4651-be03-61635a96b7e9" CreationDate="2016-03-24T08:41:02.513" Comment="Proposed by 2287 approved by 38, 209 edit id of 129" ContentLicense="CC BY-SA 3.0" />
  <row Id="5124" PostHistoryTypeId="5" PostId="2222" RevisionGUID="b27b29e6-6b68-484c-8040-7fc226cbaddf" CreationDate="2016-03-24T15:38:23.423" UserId="2287" Comment="cube &lt;&gt; box" Text="I am trying to write a ray tracer to render boxes that are arbitrarily rotated, i.e. not necessarily axis aligned. While I am reasonably comfortable ray tracing an axis-aligned bounding boxes (AABB), I don't know how to handle non-axis aligned objects. The geometry becomes quite difficult. I've looked through a textbook (*Ray Tracing from the Ground Up*) but couldn't find an answer.&#xD;&#xA;&#xD;&#xA;How should I do it? Detailed suggestions would be greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="5125" PostHistoryTypeId="24" PostId="2222" RevisionGUID="b27b29e6-6b68-484c-8040-7fc226cbaddf" CreationDate="2016-03-24T15:38:23.423" Comment="Proposed by 2287 approved by -1 edit id of 130" ContentLicense="CC BY-SA 3.0" />
  <row Id="5126" PostHistoryTypeId="5" PostId="2222" RevisionGUID="cd8359dc-7114-4f58-9744-f0cf4ae4e2d2" CreationDate="2016-03-24T15:38:23.423" UserId="209" Comment="cube &lt;&gt; box, removed &quot;a&quot; referencing a plural" Text="I am trying to write a ray tracer to render boxes that are arbitrarily rotated, i.e. not necessarily axis aligned. While I am reasonably comfortable ray tracing axis-aligned bounding boxes (AABB), I don't know how to handle non-axis aligned objects. The geometry becomes quite difficult. I've looked through a textbook (*Ray Tracing from the Ground Up*) but couldn't find an answer.&#xD;&#xA;&#xD;&#xA;How should I do it? Detailed suggestions would be greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="5127" PostHistoryTypeId="6" PostId="2224" RevisionGUID="a3e7917b-2bc3-40db-babd-cffb5cadfc9d" CreationDate="2016-03-24T18:45:05.230" UserId="48" Comment="add computational-geometry tag" Text="|texture|algorithm|3d|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5128" PostHistoryTypeId="6" PostId="2223" RevisionGUID="96d11ac5-24cb-4fd0-a83f-40ead5d36bc9" CreationDate="2016-03-24T18:45:08.370" UserId="48" Comment="add computational-geometry tag" Text="|algorithm|3d|mesh|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5129" PostHistoryTypeId="2" PostId="2226" RevisionGUID="b088d558-370f-4ffa-8a93-afb51c705392" CreationDate="2016-03-24T19:00:26.560" UserId="48" Text="[Computational geometry](https://en.wikipedia.org/wiki/Computational_geometry) encompasses a wide variety of topics, including:&#xD;&#xA;&#xD;&#xA;* Modeling surfaces and solids using meshes, splines, and other geometry representations&#xD;&#xA;* Generating geometry from implicit or parametric functions, point sets, or other data&#xD;&#xA;* Processing geometry to extract information about orientation, topology, curvature, or other quantities&#xD;&#xA;* Performing operations on geometry such as tessellation or triangulation, simplification, CSG operations, feature extraction, UV mapping, and cleaning up mesh errors" ContentLicense="CC BY-SA 3.0" />
  <row Id="5130" PostHistoryTypeId="2" PostId="2227" RevisionGUID="8302dc9a-12f1-4666-b325-a482303851eb" CreationDate="2016-03-24T19:00:26.560" UserId="48" Text="Problems involving meshes and other geometry representations, and manipulating, transforming, or extracting information from them; algorithms for solving geometrical problems such as computing intersections, filling holes, triangulating a shape, etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="5131" PostHistoryTypeId="2" PostId="2228" RevisionGUID="b4e478d4-483f-44e1-b422-b1665b9589a8" CreationDate="2016-03-24T19:02:43.390" UserId="48" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="5132" PostHistoryTypeId="2" PostId="2229" RevisionGUID="a43fceb8-4327-4115-aced-9fb18956ea75" CreationDate="2016-03-24T19:02:43.390" UserId="48" Text="Questions and problems dealing with three-dimensional space, including 3D meshes and other data structures, vector math, transformations, etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="5134" PostHistoryTypeId="2" PostId="2231" RevisionGUID="5879c4c4-3317-46b1-b86a-e6370dc8f576" CreationDate="2016-03-25T02:13:12.723" UserId="2964" Text="Games and other graphically intensive applications use frameworks like OpenGL and DirectX. Also they require features like pixel shader and DX12.&#xD;&#xA;&#xD;&#xA;But why would we need all these frameworks and GPU feature when we could just draw everything pixel by pixel&#xD;&#xA;&#xD;&#xA;First the game would have to be compiling in a way so it is drawn pixel by pixel. This is likely to make the game executable big but will it be faster and work on any 32-bit color GPU (even old ones)?&#xD;&#xA;&#xD;&#xA;I know that the first 3D games were drawn pixel by pixel but why aren't they doing it now?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5135" PostHistoryTypeId="1" PostId="2231" RevisionGUID="5879c4c4-3317-46b1-b86a-e6370dc8f576" CreationDate="2016-03-25T02:13:12.723" UserId="2964" Text="Why have graphics frameworks like OpenGL and DirectX when games could just draw using pixels" ContentLicense="CC BY-SA 3.0" />
  <row Id="5136" PostHistoryTypeId="3" PostId="2231" RevisionGUID="5879c4c4-3317-46b1-b86a-e6370dc8f576" CreationDate="2016-03-25T02:13:12.723" UserId="2964" Text="|3d|gpu|performance|pixel-shader|pixels|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5137" PostHistoryTypeId="2" PostId="2232" RevisionGUID="b4a73ccd-7ee7-4957-b488-1192dff68c5a" CreationDate="2016-03-25T06:40:42.843" UserId="38" Text="Speed is the most common reason why this is not done. In fact you can do what you propose, if you make your own operating system, its just going to be very slow for architectural reasons.&#xD;&#xA;&#xD;&#xA;Copying the data over from the cpu to the graphics card is a relatively slow operation. The less you copy the faster your update speed can be. So ideally you would have most of the data on your GPU and only update small chunks of data. There is a world of difference beween copying over 320x200 pixels compared to 1920x1200 or more. See the number of pixels you need to update grows exponetially when the sides grow.&#xD;&#xA;&#xD;&#xA;Example: Its cheaper to tell the cpu to move the image 10 pixels right than copy the pixels manually to the video memory in different locations.&#xD;&#xA;&#xD;&#xA;Why do you have to go trough an API? Simply because its not your system. The operating system can not allow you to do whatever you want for safety reasons. Secondly because the operating system needs to abstract harware away, even the OS is talking to the driver trough some abstracted system, an API if you will.&#xD;&#xA;&#xD;&#xA;In fact I would rate the likelyhood that your system would be faster if you just did all the work yourself close to be near zero. Its a bit like comparing C and assembly. Sure you can write assembly, but compilers are pretty smart these days and optimize better and better all the time. Its hard to be better manually, even if you can your productivity will be down the drains." ContentLicense="CC BY-SA 3.0" />
  <row Id="5138" PostHistoryTypeId="5" PostId="2232" RevisionGUID="e4e36a11-03b6-46f4-a95f-bc5a9e65b6d5" CreationDate="2016-03-25T06:49:07.893" UserId="38" Comment="added 411 characters in body" Text="Speed is the most common reason why this is **not** done. In fact you can do what you propose, if you make your own operating system, its just going to be very slow for architectural reasons. So the assumption that its faster is a bit flawed. Even if it would be faster it would be less efficient in terms of development (like 1% speed increase for 10 times the work).&#xD;&#xA;&#xD;&#xA;Copying the data over from the cpu to the graphics card is a relatively slow operation. The less you copy the faster your update speed can be. So ideally you would have most of the data on your GPU and only update small chunks of data. There is a world of difference beween copying over 320x200 pixels compared to 1920x1200 or more. See the number of pixels you need to update grows exponetially when the sides grow.&#xD;&#xA;&#xD;&#xA;Example: Its cheaper to tell the cpu to move the image 10 pixels right than copy the pixels manually to the video memory in different locations.&#xD;&#xA;&#xD;&#xA;Why do you have to go trough an API? Simply because its not your system. The operating system can not allow you to do whatever you want for safety reasons. Secondly because the operating system needs to abstract harware away, even the OS is talking to the driver trough some abstracted system, an API if you will.&#xD;&#xA;&#xD;&#xA;In fact I would rate the likelyhood that your system would be faster if you just did all the work yourself close to be near zero. Its a bit like comparing C and assembly. Sure you can write assembly, but compilers are pretty smart these days and optimize better and better all the time. Its hard to be better manually, even if you can your productivity will be down the drains.&#xD;&#xA;&#xD;&#xA;PS: An API does not make it impossible to do this update just like old games did it. Its just ineficient thats all. Not because of the API mind but because is ineficient period.&#xD;&#xA;&#xD;&#xA;PPS: This is why they are rolling out Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="5139" PostHistoryTypeId="5" PostId="2232" RevisionGUID="efb4c205-2f44-48ad-8644-d6781352d3ef" CreationDate="2016-03-25T07:08:43.500" UserId="38" Comment="deleted 3 characters in body" Text="Speed is the most common reason why this is **not** done. In fact you can do what you propose, if you make your own operating system, its just going to be very slow for architectural reasons. So the assumption that its faster is a bit flawed. Even if it would be faster it would be less efficient in terms of development (like 1% speed increase for 10 times the work).&#xD;&#xA;&#xD;&#xA;Copying the data over from the cpu to the graphics card is a relatively slow operation. The less you copy the faster your update speed can be. So ideally you would have most of the data on your GPU and only update small chunks of data. There is a world of difference beween copying over 320x200 pixels compared to 1920x1200 or more. See the number of pixels you need to update grows exponetially when the sides grow.&#xD;&#xA;&#xD;&#xA;Example: Its cheaper to tell the cpu to move the image 10 pixels right than copy the pixels manually to the video memory in different locations.&#xD;&#xA;&#xD;&#xA;Why do you have to go trough an API? Simply because its not your system. The operating system can not allow you to do whatever you want for safety reasons. Secondly because the operating system needs to abstract harware away, even the OS is talking to the driver trough some abstracted system, an API if you will.&#xD;&#xA;&#xD;&#xA;In fact I would rate the likelyhood that your system would be faster if you just did all the work yourself close to near zero. Its a bit like comparing C and assembly. Sure you can write assembly, but compilers are pretty smart these days and optimize better and better all the time. Its hard to be better manually, even if you can your productivity will be down the drains.&#xD;&#xA;&#xD;&#xA;PS: An API does not make it impossible to do this update just like old games did it. Its just ineficient thats all. Not because of the API mind but because is ineficient period.&#xD;&#xA;&#xD;&#xA;PPS: This is why they are rolling out Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="5140" PostHistoryTypeId="5" PostId="2232" RevisionGUID="6fe21a03-9c4f-4dec-9b73-a062e521a4df" CreationDate="2016-03-25T07:39:46.657" UserId="38" Comment="edited body" Text="Speed is the most common reason why this is **not** done. In fact you can do what you propose, if you make your own operating system, its just going to be very slow for architectural reasons. So the assumption that its faster is a bit flawed. Even if it would be faster it would be less efficient in terms of development (like 1% speed increase for 10 times the work).&#xD;&#xA;&#xD;&#xA;Copying the data over from the cpu to the graphics card is a relatively slow operation. The less you copy the faster your update speed can be. So ideally you would have most of the data on your GPU and only update small chunks of data. There is a world of difference beween copying over 320x200 pixels compared to 1920x1200 or more. See the number of pixels you need to update grows exponetially when the sides grow.&#xD;&#xA;&#xD;&#xA;Example: Its cheaper to tell the gpu to move the image 10 pixels right than copy the pixels manually to the video memory in different locations.&#xD;&#xA;&#xD;&#xA;Why do you have to go trough an API? Simply because its not your system. The operating system can not allow you to do whatever you want for safety reasons. Secondly because the operating system needs to abstract harware away, even the OS is talking to the driver trough some abstracted system, an API if you will.&#xD;&#xA;&#xD;&#xA;In fact I would rate the likelyhood that your system would be faster if you just did all the work yourself close to near zero. Its a bit like comparing C and assembly. Sure you can write assembly, but compilers are pretty smart these days and optimize better and better all the time. Its hard to be better manually, even if you can your productivity will be down the drains.&#xD;&#xA;&#xD;&#xA;PS: An API does not make it impossible to do this update just like old games did it. Its just ineficient thats all. Not because of the API mind but because is ineficient period.&#xD;&#xA;&#xD;&#xA;PPS: This is why they are rolling out Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="5141" PostHistoryTypeId="2" PostId="2233" RevisionGUID="2ceba65f-bb38-46dd-9cf0-6993ed85361e" CreationDate="2016-03-25T08:14:09.057" UserId="1937" Text="Just to add to joojaa's answer above, things *are* still being drawn pixel by pixel. You're just generating the pixels using a vertex shader/ assembler/ rasterizer, then texturing and lighting them using a fragment shader. This was all done in software in the 90's when your video card wasn't much more than a blitter and a frame buffer, but it was slow as hell, hence the invention of modern GPUs. The drawing maths that's happening is basically the same as it was back in the Doom days, but now it's running on hundreds/ thousands of shader ALUs rather than a handful of CPU cores. The APIs map down to basically the same set of GPU instructions behind the scenes, they're just there to stop you having to write a ton of gnarly GPU assembly across multiple vendor platforms." ContentLicense="CC BY-SA 3.0" />
  <row Id="5144" PostHistoryTypeId="5" PostId="2233" RevisionGUID="5db943b9-2afa-4dad-b4b9-f24a281c3179" CreationDate="2016-03-25T09:32:34.763" UserId="127" Comment="Edited formatting, added link to joojaa's answer as it is not necessarily above." Text="Just to add to [joojaa's answer](http://computergraphics.stackexchange.com/a/2232/), things *are* still being drawn pixel by pixel. You're just generating the pixels using a vertex shader/assembler/rasterizer, then texturing and lighting them using a fragment shader. This was all done in software in the 90's when your video card wasn't much more than a blitter and a frame buffer, but it was slow as hell. Hence the invention of modern GPUs. &#xD;&#xA;&#xD;&#xA;The drawing maths that's happening is basically the same as it was back in the Doom days, but now it's running on hundreds/thousands of shader ALUs rather than a handful of CPU cores. The APIs map down to basically the same set of GPU instructions behind the scenes. They're just there to stop you having to write a ton of gnarly GPU assembly across multiple vendor platforms." ContentLicense="CC BY-SA 3.0" />
  <row Id="5145" PostHistoryTypeId="5" PostId="2232" RevisionGUID="f9674e55-209a-486d-b53f-72e22f168e48" CreationDate="2016-03-25T09:36:43.067" UserId="127" Comment="Edited spelling." Text="Speed is the most common reason why this is **not** done. In fact you can do what you propose, if you make your own operating system, its just going to be very slow for architectural reasons. So the assumption that its faster is a bit flawed. Even if it would be faster, it would be less efficient in terms of development (like 1% speed increase for 10 times the work).&#xD;&#xA;&#xD;&#xA;Copying the data over from the CPU to the graphics card is a relatively slow operation. The less you copy the faster your update speed can be. So ideally you would have most of the data on your GPU and only update small chunks of data. There is a world of difference beween copying over 320x200 pixels compared to 1920x1200 or more. See the number of pixels you need to update grows exponetially when the sides grow.&#xD;&#xA;&#xD;&#xA;Example: It's cheaper to tell the GPU to move the image 10 pixels right than copy the pixels manually to the video memory in different locations.&#xD;&#xA;&#xD;&#xA;Why do you have to go trough an API? Simply because it's not your system. The operating system can not allow you to do whatever you want for safety reasons. Secondly because the operating system needs to abstract hardware away, even the OS is talking to the driver trough some abstracted system, an API if you will.&#xD;&#xA;&#xD;&#xA;In fact I would rate the likelyhood that your system would be faster, if you just did all the work yourself, close to near zero. It's a bit like comparing C and assembly. Sure you can write assembly, but compilers are pretty smart these days and optimize better and better all the time. It's hard to be better manually, even if you can your productivity will be down the drains.&#xD;&#xA;&#xD;&#xA;PS: An API does not make it impossible to do this update just like old games did it. It's just inefficient thats all. Not because of the API mind but because it is inefficient period.&#xD;&#xA;&#xD;&#xA;PPS: This is why they are rolling out Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="5146" PostHistoryTypeId="5" PostId="2231" RevisionGUID="6e04278b-71b4-47f7-a011-7f3b03c2967b" CreationDate="2016-03-25T09:40:55.547" UserId="127" Comment="Edited punctation, title." Text="Games and other graphically intensive applications use frameworks like OpenGL and DirectX. Also they require features like pixel shader and DX12.&#xD;&#xA;&#xD;&#xA;But why would we need all these frameworks and GPU features when we could just draw everything pixel by pixel?&#xD;&#xA;&#xD;&#xA;First, the game would have to be compiling in a way so it is drawn pixel by pixel. This is likely to make the game executable big, but will it be faster and work on any 32-bit color GPU (even old ones)?&#xD;&#xA;&#xD;&#xA;I know that the first 3D games were drawn pixel by pixel, but why aren't they doing it now?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5147" PostHistoryTypeId="4" PostId="2231" RevisionGUID="6e04278b-71b4-47f7-a011-7f3b03c2967b" CreationDate="2016-03-25T09:40:55.547" UserId="127" Comment="Edited punctation, title." Text="Why do we have graphics frameworks like OpenGL and DirectX, when games could just draw pixels directly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5148" PostHistoryTypeId="2" PostId="2234" RevisionGUID="8e64546d-70ac-49d4-8b08-8729dbb33fd2" CreationDate="2016-03-25T13:04:06.423" UserId="2971" Text="*work on any 32-bit color GPU (even old ones)?*&#xD;&#xA;&#xD;&#xA;Bit of history here: this is how games were done on PC up until graphical accelerators started to become available in the mid-90s. It did indeed work on all hardware, because the hardware wasn't doing much.&#xD;&#xA;&#xD;&#xA;A graphical accelerator allows the drawing of pixels considerably *faster* than a CPU can, by using specialized hardware and parallelism. The accelerator contains a number of processor cores. A desktop PC will have between 1-8 cores depending on age. My GTX970Ti graphics card has 1664 (one thousand six hundred and sixty-four!) cores. This obviously beats the PC for raw speed by a long way.&#xD;&#xA;&#xD;&#xA;However, accelerators aren't standardized, and often include weird computer architecture tricks in order to achieve their speed. In order to write a game which isn't customized to a specific make and model of the card, an API needs to exist. And that's what DirectX, GL and the shader languages are used for. In fact, writing shaders *is* the closest thing to writing a program that draws pixels directly - it's just that the card will run a thousand copies of that program for you in parallel, one per pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="5149" PostHistoryTypeId="5" PostId="2232" RevisionGUID="81621702-fc6d-443d-ac8a-77f40f7b51c1" CreationDate="2016-03-25T15:48:11.280" UserId="137" Comment="added 3 characters in body" Text="Speed is the most common reason why this is **not** done. In fact you can do what you propose, if you make your own operating system, its just going to be very slow for architectural reasons. So the assumption that its faster is a bit flawed. Even if it would be faster, it would be less efficient in terms of development (like 1% speed increase for 10 times the work).&#xD;&#xA;&#xD;&#xA;Copying the data over from the CPU to the graphics card is a relatively slow operation. The less you copy the faster your update speed can be. So ideally you would have most of the data on your GPU and only update small chunks of data. There is a world of difference between copying over 320x200 pixels compared to 1920x1200 or more. See the number of pixels you need to update grows quadratically when the sides grow.&#xD;&#xA;&#xD;&#xA;Example: It's cheaper to tell the GPU to move the image 10 pixels right than copy the pixels manually to the video memory in different locations.&#xD;&#xA;&#xD;&#xA;Why do you have to go trough an API? Simply because it's not your system. The operating system can not allow you to do whatever you want for safety reasons. Secondly because the operating system needs to abstract hardware away, even the OS is talking to the driver trough some abstracted system, an API if you will.&#xD;&#xA;&#xD;&#xA;In fact I would rate the likelihood that your system would be faster, if you just did all the work yourself, close to near zero. It's a bit like comparing C and assembly. Sure you can write assembly, but compilers are pretty smart these days and optimize better and better all the time. It's hard to be better manually, even if you can your productivity will be down the drains.&#xD;&#xA;&#xD;&#xA;PS: An API does not make it impossible to do this update just like old games did it. It's just inefficient that's all. Not because of the API mind but because it is inefficient period.&#xD;&#xA;&#xD;&#xA;PPS: This is why they are rolling out Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="5150" PostHistoryTypeId="2" PostId="2235" RevisionGUID="d3a9d35d-a467-4d3b-8aa5-5ed62036ac14" CreationDate="2016-03-25T21:25:36.990" UserId="2984" Text="If one examines old CRT television displays, one will observe red, green, and blue phosphor dots in a triangular lattice.  Some LCD television sets had a somewhat similar arrangement; pixels were rectangular rather than square, but successive rows of pixels were staggered so that the horizontal position of a red pixel on one row would be halfway between the positions of the nearest red pixels on the row above, and would match the position of a red pixel two rows up.&#xD;&#xA;&#xD;&#xA;When showing &quot;analog&quot; pictures, such arrangements will improve the visual quality of image that can be obtained with a given number of pixels.  On computer displays, however, there are a lot of lines that should appear perfectly horizontal, and a lot of lines that should appear perfectly vertical.  A rectangular grid can accommodate both easily.  A hexagonal grid, however, can only accommodate one or the other, and the one which isn't accommodated will appear rather nastily jagged.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5151" PostHistoryTypeId="2" PostId="2236" RevisionGUID="4ed6babf-c1e3-454e-9421-69f280fa1aec" CreationDate="2016-03-25T21:41:43.557" UserId="2984" Text="Imagine that one is rendering a picture of a flat floor with a uniform black and white checkerboard pattern that extends to the horizon; the checkers are large enough that they should be clearly visible at points near the camera but not large enough to be distinguishable near the horizon.&#xD;&#xA;&#xD;&#xA;Near the horizon, the floor should simply appear as uniform gray.  Near the camera, the checkers should appear distinct.  Between the camera and the horizon the appearance of the floor must somehow transition between those two extremes.&#xD;&#xA;&#xD;&#xA;If the scene is rendered a spacial filter that has a very sheep cut-off, there will be a certain distance where the floor goes from being checkered to being gray.  If one uses a shallower filter, the transition will be much more gradual, but things near the original &quot;cut-off&quot; distance will be less sharp than they would have been otherwise.&#xD;&#xA;&#xD;&#xA;If one were to add a &quot;wall&quot; or crop the scene to hide the distant parts of the floor, such that there was no need to have any parts of the checkered floor blurred to gray, the best results would be obtained by using the steepest filter, yielding the sharpest image.  Using a shallower filter would give up image sharpness for the purpose of preventing a nasty transition that wasn't going to be visible anyway.&#xD;&#xA;&#xD;&#xA;Figuring out what kind of filtering to use thus requires that one know something about the spacial frequency content of the information to be displayed.  If the image contains nothing of interest that would approach Nyquist, using a steep filter will produce the sharpest results.  If, however, image content exceeds Nyquist, using a gradual filter will avoid ugly &quot;transitions&quot;.  No single approach will be optimal for all cases.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5154" PostHistoryTypeId="2" PostId="2237" RevisionGUID="a4b6c678-2643-4fb0-83fd-c82bb1978fa3" CreationDate="2016-03-26T16:57:36.530" UserId="8" Text="I did a quick investigation about the topic but there doesn't seem a decent resource to find related problems without digging into latest CG papers (unlike CS problems you can easily find a Wikipedia list)&#xD;&#xA;&#xD;&#xA;With open problems I mean phenomenas that still doesn't have a solution/approximation with feasable complexity to find it's way into CG And better yet RealTime CG." ContentLicense="CC BY-SA 3.0" />
  <row Id="5155" PostHistoryTypeId="1" PostId="2237" RevisionGUID="a4b6c678-2643-4fb0-83fd-c82bb1978fa3" CreationDate="2016-03-26T16:57:36.530" UserId="8" Text="What are the current open problems in Computer Graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5156" PostHistoryTypeId="3" PostId="2237" RevisionGUID="a4b6c678-2643-4fb0-83fd-c82bb1978fa3" CreationDate="2016-03-26T16:57:36.530" UserId="8" Text="|real-time|physically-based|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5160" PostHistoryTypeId="2" PostId="2239" RevisionGUID="8f15e1af-6120-44c0-81bb-0aa2a7db65ef" CreationDate="2016-03-26T17:45:40.710" UserId="2287" Text="Computer Graphics can be divided in multiple subdomains of which I only talk about one in this answer (the one I am the most familiar with). &#xD;&#xA;&#xD;&#xA;**Physically-based rendering** (also referred to as global illumination) is *generally* far from real time at the moment. The speed we achieve is in fact no way close to what we actually try to simulate: the propagation of light through scenes. Scenes are rendered for over multiple hours or even days, far below the actual speed of light. Current research in this domain does however not aim at these speeds, a non-flickering framerate will do. Since the equations we try to solve are defined a long time ago, effort is mostly put in optimizing current algorithms which can be at a very high (introducing new formalisms) or low level (changing the right 1s in 0s).&#xD;&#xA;&#xD;&#xA;For the ones who actually want to dive in the literature, see this wonderful up-to-date [site][1] of the papers accepted at the most important conferences in the field of computer graphics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://kesen.realtimerendering.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5161" PostHistoryTypeId="5" PostId="2239" RevisionGUID="f8ecf23a-855f-44e2-b8cb-852266450924" CreationDate="2016-03-26T17:52:02.727" UserId="2287" Comment="added 121 characters in body" Text="Computer Graphics can be divided in multiple subdomains of which I only talk about one in this answer (the one I am the most familiar with). &#xD;&#xA;&#xD;&#xA;**Physically-based rendering** (also referred to as global illumination) is *generally* far from real time at the moment. The speed we achieve is in fact no way close to what we actually try to simulate: the propagation of light through scenes (see [interview with prof. Ravi Ramamoorthi][1]). Scenes are rendered for over multiple hours or even days, far below the actual speed of light. Current research in this domain does however not aim at these speeds, a non-flickering framerate will do. Since the equations we try to solve are defined a long time ago, effort is mostly put in optimizing current algorithms which can be at a very high (introducing new formalisms) or low level (changing the right 1s to 0s and vice versa).&#xD;&#xA;&#xD;&#xA;For the ones who actually want to dive in the literature, see this wonderful up-to-date [site][2] of the papers accepted at the most important conferences in the field of computer graphics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://waskul.tv/portfolio/steve-waskul-ravi-ramamoorthi-2013/&#xD;&#xA;  [2]: http://kesen.realtimerendering.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5162" PostHistoryTypeId="5" PostId="2239" RevisionGUID="b4b9b0fe-5688-4ac7-97de-4741b2bd2db1" CreationDate="2016-03-26T17:58:01.447" UserId="2287" Comment="added 121 characters in body" Text="Computer Graphics can be divided in multiple subdomains of which I will only talk about physically-based rendering (the one I am the most familiar with and probably the one you are referring to based on the tags of the question). &#xD;&#xA;&#xD;&#xA;**Physically-based rendering** (also referred to as global illumination) is *generally* far from real time at the moment. The speed we achieve is in fact no way close to what we actually try to simulate: the propagation of light through scenes (see [interview with prof. Ravi Ramamoorthi][1]). Scenes are rendered for over multiple hours or even days, far below the actual speed of light. Current research in this domain does however not aim at these speeds, a non-flickering framerate will do. Since the equations we try to solve are defined a long time ago, effort is mostly put in optimizing current algorithms which can be at a very high (introducing new formalisms) or low level (changing the right 1s to 0s and vice versa).&#xD;&#xA;&#xD;&#xA;For the ones who actually want to dive in the literature, see this wonderful up-to-date [site][2] of the papers accepted at the most important conferences in the field of computer graphics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://waskul.tv/portfolio/steve-waskul-ravi-ramamoorthi-2013/&#xD;&#xA;  [2]: http://kesen.realtimerendering.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5163" PostHistoryTypeId="5" PostId="2239" RevisionGUID="cd0a53be-4889-45cb-8551-01346d08b878" CreationDate="2016-03-26T18:18:42.260" UserId="2287" Comment="added 30 characters in body" Text="Computer Graphics can be divided in multiple subdomains of which I will only talk about physically-based rendering (the one I am the most familiar with and probably the one you are referring to based on the tags of the question). &#xD;&#xA;&#xD;&#xA;**Physically-based rendering** (also referred to as global illumination) is *generally* far from real time at the moment. The speed we achieve is in fact no way close to what we actually try to simulate: the propagation of light through scenes (see [interview with prof. Ravi Ramamoorthi][1]). Scenes are rendered for over multiple hours or even days, far below the actual speed of light. Current research in this domain does however not aim at these speeds, a non-flickering framerate perceived by a human observer will do. Since the equations we try to solve are defined a long time ago, effort is mostly put in optimizing current algorithms which can be at a very high (introducing new formalisms) or low level (changing the right 1s to 0s and vice versa).&#xD;&#xA;&#xD;&#xA;For the ones who actually want to dive in the literature, see this wonderful up-to-date [site][2] of the papers accepted at the most important conferences in the field of computer graphics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://waskul.tv/portfolio/steve-waskul-ravi-ramamoorthi-2013/&#xD;&#xA;  [2]: http://kesen.realtimerendering.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5164" PostHistoryTypeId="2" PostId="2240" RevisionGUID="6115365b-6133-4b20-9efb-a19cc8e1801d" CreationDate="2016-03-26T23:22:58.243" UserId="2359" Text="Im stuck on this question asking me to calculate the intensity of a pixel using Ray Tracing. It gives values such as I&lt;sub&gt;i&lt;/sub&gt; but doesnt give any coordinates. &#xD;&#xA;&#xD;&#xA;I know for the diffuse component, I&lt;sub&gt;i&lt;/sub&gt;k&lt;sub&gt;d&lt;/sub&gt;(n.l) can be written as I&lt;sub&gt;i&lt;/sub&gt;k&lt;sub&gt;d&lt;/sub&gt;(cos(Theta)) but for the specular component I&lt;sub&gt;i&lt;/sub&gt;k&lt;sub&gt;s&lt;/sub&gt;(h.n) is there any other way to write it so that it doesnt require any vectors such as h and n??&#xD;&#xA; &#xD;&#xA;This is the question:&#xD;&#xA;[ray tracing question][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://imgur.com/eeyGb6x" ContentLicense="CC BY-SA 3.0" />
  <row Id="5165" PostHistoryTypeId="1" PostId="2240" RevisionGUID="6115365b-6133-4b20-9efb-a19cc8e1801d" CreationDate="2016-03-26T23:22:58.243" UserId="2359" Text="phong equation of illumination specular component" ContentLicense="CC BY-SA 3.0" />
  <row Id="5166" PostHistoryTypeId="3" PostId="2240" RevisionGUID="6115365b-6133-4b20-9efb-a19cc8e1801d" CreationDate="2016-03-26T23:22:58.243" UserId="2359" Text="|raytracing|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5170" PostHistoryTypeId="2" PostId="2242" RevisionGUID="683acfc3-fc79-40f2-b007-f3f5783d660e" CreationDate="2016-03-27T15:48:30.603" UserId="93" Text="There is a vast amount of open problems in real-time graphics: shadows, aliasing, reflections, global illumination, transparencies (blending order and lighting) etc.&#xD;&#xA;&#xD;&#xA;SIGGRAPH annually hosts a course called &quot;Open Problems in Real-Time Rendering&quot;, which describes current issues in real-time graphics (mostly game dev industry standpoint). You can find last year's materials here: http://openproblems.realtimerendering.com" ContentLicense="CC BY-SA 3.0" />
  <row Id="5173" PostHistoryTypeId="5" PostId="2237" RevisionGUID="68f1a8f5-4abf-45dd-860a-a4e50a68282a" CreationDate="2016-03-28T07:28:02.187" UserId="2287" Comment="formatting" Text="I did a quick investigation about the topic but there doesn't seem a decent resource to find related problems without digging into latest CG papers (unlike CS problems you can easily find a Wikipedia list)&#xD;&#xA;&#xD;&#xA;With open problems I mean phenomenas that still do not have a tractable solution/approximation to find its way into CG and better yet real time CG." ContentLicense="CC BY-SA 3.0" />
  <row Id="5174" PostHistoryTypeId="24" PostId="2237" RevisionGUID="68f1a8f5-4abf-45dd-860a-a4e50a68282a" CreationDate="2016-03-28T07:28:02.187" Comment="Proposed by 2287 approved by 48, 8 edit id of 131" ContentLicense="CC BY-SA 3.0" />
  <row Id="5176" PostHistoryTypeId="2" PostId="2243" RevisionGUID="262f6f38-cbcf-48da-939f-a7a1d6c8dd54" CreationDate="2016-03-28T08:47:03.953" UserId="38" Text="This is a hard problem since the systems do not in fact tell you how it should operate. The problem is that there are several ways to address this issue:&#xD;&#xA;&#xD;&#xA;1. Apply a LUT to all output&#xD;&#xA;2. Let the system color manage&#xD;&#xA;3. Let each application color manage&#xD;&#xA;&#xD;&#xA;Nearly all of our color management systems are borderline braindead. There is really no sane way to ensure that you are doing the proper thing without extensively testing the system. You can not ask or specify your intent. In case of multi operating system situations. If there is reason for me to color manage something myself im at the mercy of each operating system peculiarities.&#xD;&#xA;&#xD;&#xA;For a alternate discussion on this see this [stackoverflow post](http://stackoverflow.com/questions/23026151/do-i-need-to-gamma-correct-the-final-color-output-on-a-modern-computer-monitor). But its not really a robust enough talk to cover all cases." ContentLicense="CC BY-SA 3.0" />
  <row Id="5177" PostHistoryTypeId="5" PostId="2240" RevisionGUID="f8b6a11c-650b-497d-b7cf-c3288032466a" CreationDate="2016-03-28T08:59:07.193" UserId="2287" Comment="added the image instead of url" Text="Im stuck on this question asking me to calculate the intensity of a pixel using Ray Tracing. It gives values such as I&lt;sub&gt;i&lt;/sub&gt; but doesnt give any coordinates. &#xD;&#xA;&#xD;&#xA;I know for the diffuse component, I&lt;sub&gt;i&lt;/sub&gt;k&lt;sub&gt;d&lt;/sub&gt;(n.l) can be written as I&lt;sub&gt;i&lt;/sub&gt;k&lt;sub&gt;d&lt;/sub&gt;(cos(Theta)) but for the specular component I&lt;sub&gt;i&lt;/sub&gt;k&lt;sub&gt;s&lt;/sub&gt;(h.n) is there any other way to write it so that it doesnt require any vectors such as h and n??&#xD;&#xA; &#xD;&#xA;This is the question:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3s0AC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5178" PostHistoryTypeId="24" PostId="2240" RevisionGUID="f8b6a11c-650b-497d-b7cf-c3288032466a" CreationDate="2016-03-28T08:59:07.193" Comment="Proposed by 2287 approved by 48, 38 edit id of 132" ContentLicense="CC BY-SA 3.0" />
  <row Id="5179" PostHistoryTypeId="2" PostId="2244" RevisionGUID="66f3fce5-c635-4601-9271-6f2249dcd269" CreationDate="2016-03-28T09:55:53.623" UserId="38" Text="Well obviously nobody except the makers of this program can answer the exact algorithms used. I have done a quick explanation on each. Each separate task really deserves its own question and answer.&#xD;&#xA;&#xD;&#xA;Just iterate each polygon, for each vertex check if all of them are above the cut line eliminate the face. To make this check easy you can transom each vertex to the plane orientation. If not all vertices are above the cut line then the triangle is split along one of the edge that has a eliminated vertex. Then use the internal face closing algorithm. [Heres some math](http://geomalgorithms.com/a06-_intersect-2.html).&#xD;&#xA;&#xD;&#xA;Face closing algorithm works by finding open edges and then tessellating the new polygon closed. Please note: That this produces somewhat erratic results if the open holes are not planar. See [polygon triangulation](https://en.wikipedia.org/wiki/Polygon_triangulation)&#xD;&#xA;&#xD;&#xA;Simplifying planar regions is basically the same face closing algorithm except they you first build up polygons out of regions. Also decimation might come to play. There is a lot of lore, and different algorithms for simplification and going trough all of it its way too bread for a post like this. &#xD;&#xA;&#xD;&#xA;Self intersection is a sorting problem. Quite a bit of lore on this exists too. The one that i mostly do is putting the polygons one by one into a BSP self organizing tree and checking against polygons against items in that tree to reduce the check complexity to *n* log *n*. &#xD;&#xA;&#xD;&#xA;Internal cavities can be detected by splitting each mesh into shells and then for each shell check if the other shell is contained within each other. See [this post](http://computergraphics.stackexchange.com/questions/2208/model-separation-several-models-reside-in-a-single-stl-file/2209#2209)" ContentLicense="CC BY-SA 3.0" />
  <row Id="5180" PostHistoryTypeId="2" PostId="2245" RevisionGUID="3ea810d6-e3c0-46b4-8809-7bbd1c7de4b0" CreationDate="2016-03-29T11:19:37.950" UserId="333" Text="In my graphics engine, based on OpenGL ES 2.0 I am using standardized name for shader attributes like it is done in libGDX (such as a_position, a_normal, etc.).&#xD;&#xA;&#xD;&#xA;When 'activating' my vertex buffer for drawing, just before I call `glVertexAttribPointer()` I need to enable an attribute I'm going to use by calling `glEnableVertexAttribArray()`, and then disable unused ones. Let's say there's two shaders I'm gonna use:&#xD;&#xA;&#xD;&#xA; 1. Shader1 is simple texture shader, which single attribute is `a_position_uv` which is vec4, `xy` are for position, and the remaining `zw` are for texture coordinates (attribute location is bound by name to 0).&#xD;&#xA; 2. Shader2 is solid shader, which single attribute is `a_position` which is `vec2` (attribute location is bound by name to 1).&#xD;&#xA;&#xD;&#xA;Then something strange happens. When I'm drawing with Shader1, I'm enabling 0th, and disabling 1st attribute, and it worked just fine. But then, when I'm drawing with Shader2 (and obviously I'm enabling 1st, and disabling 0th attributes) it draws nothing. Just nothing.&#xD;&#xA;&#xD;&#xA;In fact: when I'm not disabling 0th attribute for solid shader it works fine. In both cases the remaining code is identical.&#xD;&#xA;&#xD;&#xA;In fact (2): this happens only when deploying game on devices (iPhone simulator too).  I'm not a newbie in graphics programming and OpenGL, but in this case the behaviour is very strange for me." ContentLicense="CC BY-SA 3.0" />
  <row Id="5181" PostHistoryTypeId="1" PostId="2245" RevisionGUID="3ea810d6-e3c0-46b4-8809-7bbd1c7de4b0" CreationDate="2016-03-29T11:19:37.950" UserId="333" Text="Strange behaviour of glDisableVertexAttribArray() on devices" ContentLicense="CC BY-SA 3.0" />
  <row Id="5182" PostHistoryTypeId="3" PostId="2245" RevisionGUID="3ea810d6-e3c0-46b4-8809-7bbd1c7de4b0" CreationDate="2016-03-29T11:19:37.950" UserId="333" Text="|opengl|shader|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5183" PostHistoryTypeId="2" PostId="2246" RevisionGUID="325aebd4-3163-4b16-b7a5-1d904f1f048d" CreationDate="2016-03-29T12:48:44.053" UserId="3019" Text="I was about to scale this image down to 64x64 pixels:&#xD;&#xA;&#xD;&#xA;[![this][1]][1]&#xD;&#xA;&#xD;&#xA;The result I got on MS Paint on Windows 7 was surprisingly good (i.e. crisp edges):&#xD;&#xA;&#xD;&#xA;[![ms paint rescaled][2]][2] , whereas scaling it with GIMP resulted in [![cubic GIMP][3]][3] for cubic and [![lanczos3 GIMP][4]][4] for Lanczos3 interpolation, both of which look significantly worse to me. Linear and nearest-neighbor was obviously much worse still.&#xD;&#xA;&#xD;&#xA;I have also written a small program to check all of the interpolation modes available [in the System.Drawing.Drawing2D.InterpolationMode enumeration][5], to no avail. Unfortunately, most web search results on the topic of interpolation in MS Paint are still from the days before Vista, when nearest neighbor was the only option.&#xD;&#xA;&#xD;&#xA;Does anyone know which interpolation algorithm the Windows 7 version of MS Paint uses?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jAk2Z.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/RaQLu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8rPmx.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/EQ33f.png&#xD;&#xA;  [5]: https://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.interpolationmode.aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="5184" PostHistoryTypeId="1" PostId="2246" RevisionGUID="325aebd4-3163-4b16-b7a5-1d904f1f048d" CreationDate="2016-03-29T12:48:44.053" UserId="3019" Text="Which interpolation algorithm does MS Paint on Windows 7 use for image rescaling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5185" PostHistoryTypeId="3" PostId="2246" RevisionGUID="325aebd4-3163-4b16-b7a5-1d904f1f048d" CreationDate="2016-03-29T12:48:44.053" UserId="3019" Text="|algorithm|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5186" PostHistoryTypeId="2" PostId="2247" RevisionGUID="078ac294-26c7-4605-be60-2e5cd2f27bb8" CreationDate="2016-03-29T13:24:36.920" UserId="3020" Text="I'm making a game that is supposed to like like a early 90s 3D game, so i'm rendering in software on an 8-bit indexed bitmap, using lookup tables for translucency and lighting.&#xD;&#xA;&#xD;&#xA;Now I have to draw a translucent, lit sprite in front of an already-lit background (the light level of said background is lost at that point). I'm unsure whether to first darken all the pixels and then average them with the background or the other way round." ContentLicense="CC BY-SA 3.0" />
  <row Id="5187" PostHistoryTypeId="1" PostId="2247" RevisionGUID="078ac294-26c7-4605-be60-2e5cd2f27bb8" CreationDate="2016-03-29T13:24:36.920" UserId="3020" Text="In what order to apply lighting and translucency?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5188" PostHistoryTypeId="3" PostId="2247" RevisionGUID="078ac294-26c7-4605-be60-2e5cd2f27bb8" CreationDate="2016-03-29T13:24:36.920" UserId="3020" Text="|rendering|texture|real-time|lighting|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5192" PostHistoryTypeId="2" PostId="2249" RevisionGUID="0f0bf67c-b93f-4fc5-91a0-af96d8af1e56" CreationDate="2016-03-29T17:20:31.733" UserId="48" Text="Assuming that the classic Phong model is desired here, the dot product that goes into the specular calculation should be R·L, rather than N·H (which was introduced by Blinn). That is, Phong calculates specular using the angle between the reflected eye vector and the light vector.&#xD;&#xA;&#xD;&#xA;In the diagram you posted, these vectors are shown and the angle is given as 15&amp;deg;. So, R·L = cos(15&amp;deg;) = 0.96 according to the table below the diagram." ContentLicense="CC BY-SA 3.0" />
  <row Id="5198" PostHistoryTypeId="5" PostId="2201" RevisionGUID="7e5a2c85-3b72-485d-8774-1d3c7e137812" CreationDate="2016-03-30T06:44:50.887" UserId="2898" Comment="better " Text="Given a 3D object in Computer graphics, whose surface is represented as a 3D triangular mesh (mesh of 3D triangle objects), I need to find the maximum continual Convex patches on the surface of the given 3D object.&#xD;&#xA;&#xD;&#xA;I am using OpenGl to render the graphics within a C++ program. What kind of methods or algorithms should I use to find the convex patches.&#xD;&#xA;&#xD;&#xA;I have to apply different colors to the different convex patches on the object to signify the selection. &#xD;&#xA;&#xD;&#xA;Say I have a sphere then the whole sphere is one maximal convex patch. Any portion of the sphere surface will be a convex patch, by maximal I mean the maximum continuous convex patches that can be found. Well in the rendering, depending on the viewing angles, the maximal convex patches visible to the viewer will have to colored. I have to report all the convex patches, each patch being the maximal in that area.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5199" PostHistoryTypeId="5" PostId="2204" RevisionGUID="8de21517-4911-4664-a4c2-7fac37ce3f07" CreationDate="2016-03-30T06:49:02.380" UserId="2898" Comment="include further points in the answer" Text="Start from any triangle. Traverse it's edge's and check that the angle between the two triangles is less than 180deg. If it is add it to the current selection and continue expanding.&#xD;&#xA;&#xD;&#xA;The check is actually really simple if you use vector geometry. Say A - B is the common edge with C on the selected side and D on the other. Then just check if `dot(cross((A-B), (D-B)), cross((A-B), (C-B)) &lt; 0`.&#xD;&#xA;&#xD;&#xA;Single triangle patches should be ruled out, as for us to determine convexity, it has to span across several triangles.&#xD;&#xA;We have to keep sampling until we've tested everything.  When a convex patch continues further, it's size keeps on increasing by including the neighbouring triangles that satisfy convexity, until the patch reaches the maximum size it can attain." ContentLicense="CC BY-SA 3.0" />
  <row Id="5203" PostHistoryTypeId="2" PostId="2251" RevisionGUID="dd5695c2-a715-4a84-80d1-013305a9df08" CreationDate="2016-03-30T11:16:43.963" UserId="386" Text="This question bothers me since the first time I got to know about derivatives in pixel shader. Suppose we have a 2d texture:&#xD;&#xA;&#xD;&#xA;    5	10	20	30&#xD;&#xA;    6	11	50	100&#xD;&#xA;&#xD;&#xA;If I correctly understand, the derivatives for the pixel [0, 0] will be:&#xD;&#xA;&#xD;&#xA; - dx = pixel[1, 0] - pixel[0, 0] = 10 - 5 = 5&#xD;&#xA; - dy = pixel[0, 1] - pixel[0, 0] = 6 - 5 = 1&#xD;&#xA;&#xD;&#xA;And this will be 100% guaranteed because gpu executes pixels in 2x2 block. But what is the **dx-derivative** for the pixel[1, 0]? The pixel right to it is from another block which maybe not executed yet? And what about pixel[3, 0]? It doesn't have a right neighbor at all!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5204" PostHistoryTypeId="1" PostId="2251" RevisionGUID="dd5695c2-a715-4a84-80d1-013305a9df08" CreationDate="2016-03-30T11:16:43.963" UserId="386" Text="Gpu derivatives. How it's done across 2x2 boundary?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5205" PostHistoryTypeId="3" PostId="2251" RevisionGUID="dd5695c2-a715-4a84-80d1-013305a9df08" CreationDate="2016-03-30T11:16:43.963" UserId="386" Text="|gpu|pixel-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5206" PostHistoryTypeId="2" PostId="2252" RevisionGUID="6750c498-8c41-4777-a3f6-c85b85d1cbc6" CreationDate="2016-03-30T11:35:24.423" UserId="137" Text="In Vulkan the shader only looks at each 2x2 and won't attempt to look beyond the neighbourhood: http://vulkan-spec-chunked.ahcox.com/ch15s05.html&#xD;&#xA;&#xD;&#xA;$$dPdx_{0,0}=dPdx_{1, 0} = P_{1,0}−P_{0,0}\\&#xD;&#xA;dPdx_{2,0}=dPdx_{3, 0} = P_{3,0}−P_{2,0}$$&#xD;&#xA;&#xD;&#xA;For times when a pixel would fall off the geometry the shader is invoked for the values it would have if the triangle extended a pixel further. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5207" PostHistoryTypeId="2" PostId="2253" RevisionGUID="8649b55b-9bf3-41e9-853f-32cf79520a80" CreationDate="2016-03-30T16:43:19.203" UserId="38" Text="This is more of a long comment&#xD;&#xA;&#xD;&#xA;Yes you can do this. The problem lies in how you measure the surface. I tried to do this manually by progressively extruding tubes along the edges, and finding their intersection with the surface. It would work but is a bit hard to compute. Obviously you may want to take more steps than i did for a more accurate solution. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1** Straight skeleton and insets by finding the intersection of tubes along edges, and then the created edges on mesh (blue) and approximate straight skeleton (magenta) &#xD;&#xA;&#xD;&#xA;From this experiment I can conclude that are many complex cases to consider.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IbXPj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5208" PostHistoryTypeId="5" PostId="2253" RevisionGUID="a42b82d6-e4f2-4e66-beb2-18fc8f8ea553" CreationDate="2016-03-30T18:15:13.220" UserId="38" Comment="deleted 35 characters in body" Text="This is more of a long comment&#xD;&#xA;&#xD;&#xA;Yes you can do this. The problem lies in how you measure the surface. I tried to do this manually by progressively extruding tubes along the edges, and finding their intersection with the surface. It would work but is a bit hard to compute. Obviously you may want to take more steps than i did for a more accurate solution. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1** Straight skeleton (magenta)  and insets by finding the intersection of tubes along edges, and then the created edges on mesh (blue) &#xD;&#xA;From this experiment I can conclude that are many complex cases to consider.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IbXPj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5209" PostHistoryTypeId="2" PostId="2254" RevisionGUID="15a81106-ed88-41ab-89a6-031fd0df0426" CreationDate="2016-03-30T18:16:14.740" UserId="48" Text="When blending multiple layers, physically the &quot;right&quot; thing to do is calculating lighting on each layer separately, then composite the lit layers together. This way, for instance, you can have a translucent sprite standing in a spotlight, in front of a dark background, and the sprite will be well-lit while the background visible through it stays dark. Or conversely, you can have a dark sprite silhouetted against a brightly lit background.&#xD;&#xA;&#xD;&#xA;If you blended the sprite with the background before lighting, it wouldn't be clear which lighting environment you should use if the sprite and background have different ones." ContentLicense="CC BY-SA 3.0" />
  <row Id="5210" PostHistoryTypeId="2" PostId="2255" RevisionGUID="53eeea7c-362f-49d5-98b8-bcc91af1f777" CreationDate="2016-03-30T19:32:11.707" UserId="3031" Text="My goal is to create 3D meshes without the used of a 3D editor.  So I want to know what representation languages and formats there are that are designed for this or otherwise that would be good for this.  I would prefer one that is open and widely supported.  Something like a 3D version of SVG or Postscript would be ideal." ContentLicense="CC BY-SA 3.0" />
  <row Id="5211" PostHistoryTypeId="1" PostId="2255" RevisionGUID="53eeea7c-362f-49d5-98b8-bcc91af1f777" CreationDate="2016-03-30T19:32:11.707" UserId="3031" Text="Human Readable/Writable 3D Representation Formats/Languages?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5212" PostHistoryTypeId="3" PostId="2255" RevisionGUID="53eeea7c-362f-49d5-98b8-bcc91af1f777" CreationDate="2016-03-30T19:32:11.707" UserId="3031" Text="|3d|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5213" PostHistoryTypeId="2" PostId="2256" RevisionGUID="c11aaa76-669c-4aca-9697-1d925a2f8859" CreationDate="2016-03-30T21:35:06.380" UserId="38" Text="There are a number of formats that might fit the bill. Depends on what you want to achieve.&#xD;&#xA;&#xD;&#xA;Most likely your looking for a scene description language for renderers. Many of them are for that one renderer but atleast one is a standard. So you might be looking for something like:&#xD;&#xA;&#xD;&#xA;* RIB, Renderman Bytestream altough it comes with as a programming api aswell. This is a based on a standard set by pixar and is used by a number of render engines some of which are open source.&#xD;&#xA;&#xD;&#xA;* Most other rendering solutions also have textual formats im somewhat familiar with the mi formats and the now archaic Povray formats. But many others exist.&#xD;&#xA;&#xD;&#xA;It is a bit debatable whether these really are human readable but given that you specify SVG then I guess they are atleast and readable as that. Just more complex. Note like SVG these describe scenes.&#xD;&#xA;&#xD;&#xA;Then we have `dae` or collada. Which is sortof human readable has a similar niche as `RIB` but is aimed for game assets. A number of other somewhat similar formats exist like the mostly deprecated VRML format, and its successors.&#xD;&#xA;&#xD;&#xA;Then we have a bunch of polygon formats, many of them are binary. But atleast `obj` and `ply` are human readable and widely accepted. Although polygon meshes are seldom really easy to understand or craft manually if they are more complex. &#xD;&#xA;&#xD;&#xA;Then we have a bunch of application specific formats. For example the `ma`, Maya ascii, format which is human readable if you understand how maya node hierarchy works. Cant say much of the others.&#xD;&#xA;&#xD;&#xA;Then we have the CAD transpoet formats IGES and STEP. I wouldnt go and claim either to be human readable. But i have hand crafted both on a occasion. Both of these are ISO standards, alhtough STEP is insanely big and was in fact the biggest of ISO standards in page count last time I checked.&#xD;&#xA;&#xD;&#xA;There are quite many of these formats because 3D is not as uniform as 2D is. But, yes, I have hand crafted all of these at one point or another. Does not mean i would consider doing so as a productivity tool. Unlike EPS or SVG, which I craft bi weekly by hand. &#xD;&#xA;&#xD;&#xA;If I would have to guess your motives then i would say RIB is probably what you want" ContentLicense="CC BY-SA 3.0" />
  <row Id="5214" PostHistoryTypeId="5" PostId="2256" RevisionGUID="949a8336-0783-4605-9ae0-a2f61605d9d8" CreationDate="2016-03-30T21:41:38.293" UserId="38" Comment="edited body" Text="There are a number of formats that might fit the bill. Depends on what you want to achieve.&#xD;&#xA;&#xD;&#xA;Most likely your looking for a scene description language for renderers. Many of them are for that one renderer but atleast one is a standard. So you might be looking for something like:&#xD;&#xA;&#xD;&#xA;* RIB, Renderman Bytestream altough it comes with as a programming api aswell. This is a based on a standard set by pixar and is used by a number of render engines some of which are open source.&#xD;&#xA;&#xD;&#xA;* Most other rendering solutions also have textual formats im somewhat familiar with the mi formats and the now archaic Povray formats. But many others exist.&#xD;&#xA;&#xD;&#xA;It is a bit debatable whether these really are human readable but given that you specify SVG then I guess they are atleast and readable as that. Just more complex. Note like SVG these describe scenes.&#xD;&#xA;&#xD;&#xA;Then we have `dae` or collada. Which is sortof human readable has a similar niche as `RIB` but is aimed for game assets. A number of other somewhat similar formats exist like the mostly deprecated VRML format, and its successors.&#xD;&#xA;&#xD;&#xA;Then we have a bunch of polygon formats, many of them are binary. But atleast `obj` and `ply` are human readable and widely accepted. Although polygon meshes are seldom really easy to understand or craft manually if they are more complex. &#xD;&#xA;&#xD;&#xA;Then we have a bunch of application specific formats. For example the `ma`, Maya ascii, format which is human readable if you understand how maya node hierarchy works. Cant say much of the others.&#xD;&#xA;&#xD;&#xA;Then we have the CAD transport formats IGES and STEP. I wouldnt go and claim either to be human readable. But i have hand crafted both on a occasion. Both of these are ISO standards, alhtough STEP is insanely big and was in fact the biggest of ISO standards in page count last time I checked.&#xD;&#xA;&#xD;&#xA;There are quite many of these formats because 3D is not as uniform as 2D is. But, yes, I have hand crafted all of these at one point or another. Does not mean i would consider doing so as a productivity tool. Unlike EPS or SVG, which I craft bi weekly by hand. &#xD;&#xA;&#xD;&#xA;If I would have to guess your motives then i would say RIB is probably what you want" ContentLicense="CC BY-SA 3.0" />
  <row Id="5215" PostHistoryTypeId="5" PostId="2255" RevisionGUID="05476f75-35f2-4e16-a107-8a16c06ebe11" CreationDate="2016-03-30T21:44:32.470" UserId="3031" Comment="typo" Text="My goal is to create 3D meshes without the use of a 3D editor.  So I want to know what representation languages and formats there are that are designed for this or otherwise that would be good for this.  I would prefer one that is open and widely supported.  Something like a 3D version of SVG or Postscript would be ideal." ContentLicense="CC BY-SA 3.0" />
  <row Id="5216" PostHistoryTypeId="5" PostId="2256" RevisionGUID="eeec543c-cfd2-4a1c-b8bd-7154b6e5670b" CreationDate="2016-03-30T21:47:21.120" UserId="38" Comment="added 34 characters in body" Text="There are a number of formats that might fit the bill. Depends on what you want to achieve.&#xD;&#xA;&#xD;&#xA;Most likely your looking for a scene description language for renderers. Many of them are for that one renderer but atleast one is a standard. So you might be looking for something like:&#xD;&#xA;&#xD;&#xA;* RIB, Renderman Bytestream altough it comes with as a programming api aswell. This is a based on a standard set by pixar and is used by a number of render engines some of which are open source.&#xD;&#xA;&#xD;&#xA;* Most other rendering solutions also have textual formats im somewhat familiar with the mi formats and the now archaic Povray formats. But many others exist.&#xD;&#xA;&#xD;&#xA;It is a bit debatable whether these really are human readable but given that you specify SVG then I guess they are atleast and readable as that. Just more complex. Note like SVG these describe scenes.&#xD;&#xA;&#xD;&#xA;Then we have `dae` or collada. Which is sortof human readable has a similar niche as `RIB` but is aimed for game assets. A number of other somewhat similar formats exist like the mostly deprecated VRML format, and its successors.&#xD;&#xA;&#xD;&#xA;Then we have a bunch of polygon formats, many of them are binary. But atleast `obj` and `ply` are human readable and widely accepted. Although polygon meshes are seldom really easy to understand or craft manually if they are more complex. &#xD;&#xA;&#xD;&#xA;Then we have a bunch of application specific formats. For example the `ma`, Maya ascii, format which is human readable if you understand how maya node hierarchy works. Cant say much of the others.&#xD;&#xA;&#xD;&#xA;Then we have the CAD transport formats IGES and STEP. I wouldnt go and claim either to be human readable. But i have hand crafted both on a occasion. Both of these are ISO standards, alhtough STEP is insanely big and was in fact the biggest of ISO standards in page count last time I checked.&#xD;&#xA;&#xD;&#xA;There are quite many of these formats because 3D is not as uniform as 2D is. But, yes, I have hand crafted all of these at one point or another. Does not mean i would consider doing so as a productivity tool. Unlike EPS or SVG, which I craft bi weekly by hand. &#xD;&#xA;&#xD;&#xA;If I would have to guess your motives then i would say RIB is probably what you want. Or then your looking to use obj." ContentLicense="CC BY-SA 3.0" />
  <row Id="5217" PostHistoryTypeId="5" PostId="1892" RevisionGUID="8f753b66-de12-47ae-9d64-37fa8fef95de" CreationDate="2016-03-30T22:06:29.490" UserId="2413" Comment="added 34 characters in body" Text="&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;I've recently rebuild shaders for my program and it stopped &quot;working&quot; ( black screen ) on OS X ( El Capitan ), but **it's ok on Linux on GTX 660**.&#xD;&#xA;&#xD;&#xA;I've tested it on another Apple hardware and **it worked on OS X on R9 395** ( but super slow, because of double ). So I suppose it's problem with my **Intel HD Graphics 5000**.&#xD;&#xA;&#xD;&#xA;There are no shader compilation errors, and here is my shader code:&#xD;&#xA;&#xD;&#xA;https://github.com/Marqin/YuriaViewer/blob/4241e384da0f27d26cbf5557518db905a9d40039/vertex.glsl&#xD;&#xA;&#xD;&#xA;Keep in mind that this software worked on El Capitan with OpenGL 4.1 before shader rewrite. Here are my glfw hints:&#xD;&#xA;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;&#xD;&#xA;My program also is checking for `GL_ARB_gpu_shader_fp64` and it's available on my Macbook ( Macbook Air 2013 mid ).&#xD;&#xA;&#xD;&#xA;I've &quot;debugged&quot; it a little and it looks that `i` is always lesser than `vis` on OS X, that's why it's black.&#xD;&#xA;&#xD;&#xA;I've also made a simple test - I've typed all uniform values in shader by hand and now it wasn't black, but I've got some gibberish on screen. Then I've changed every `dvec3` and `dvec2` to float versions and it showed nice fractal. So it looks like `double` is not working on OS X. But how can it be? It's saying that `GL_ARB_gpu_shader_fp64` is available and it even doesn't complain when I request it in vertex shader.&#xD;&#xA;&#xD;&#xA;How can I make it work on OS X Macbook?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5223" PostHistoryTypeId="2" PostId="2258" RevisionGUID="9f57fb59-3bcc-45df-9654-45c74754afe5" CreationDate="2016-03-31T10:35:49.703" UserId="3036" Text="I am trying to align two motion capture files from different sources.&#xD;&#xA;The motion capture file consist of a skeleton specified as a hierarchy of joints. Each joint i.e. &quot;shoulder&quot; has three pieces of data: rotation order (XYZ), a translation plus direction from a parent joint (the bone vector) and an axis, which is a 3-tuple of rotations (X, Y, Z) that describe the transformation from the parent coordinate system to the local coordinate system. For each frame, a local rotation 3-tuple m_x, m_y, m_z is specified which describes how the bone vector changes from frame to frame.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To calculate the position of a particular bone for a single frame, I calculate:&#xD;&#xA;&#xD;&#xA;M = M_x * M_y * M_z where M_x, M_y, M_z are the rotation matrices correspond to m_x, m_y and m_z.&#xD;&#xA;&#xD;&#xA;L = C_inv * M * C, where C is the multiplication of 3 X, Y, Z rotation matrices corresponding to the bone axis.&#xD;&#xA;&#xD;&#xA;This is done for each bone in the hierarchy (i.e shoulder -&gt; clavicle -&gt; spine -&gt; root) and multiplied together to get the global rotation matrix for a particular bone. The bone vector is then multiplied by this rotation matrix to get the x, y, z position.&#xD;&#xA;&#xD;&#xA;The problem is now I have two motion capture files with corresponding joints: say, shoulderA and shoulderB. Since the joint axes are different, the local per-frame rotations are also different, which means I can't use the frame data for file B for skeleton A. I would like to &quot;refer&quot; shoulderB to shoulderA, so I'm wondering how I can change the per-frame rotations to do so.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Reference: &#xD;&#xA;http://research.cs.wisc.edu/graphics/Courses/cs-838-1999/Jeff/ASF-AMC.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5224" PostHistoryTypeId="1" PostId="2258" RevisionGUID="9f57fb59-3bcc-45df-9654-45c74754afe5" CreationDate="2016-03-31T10:35:49.703" UserId="3036" Text="Coordinate system transformation in motion capture files" ContentLicense="CC BY-SA 3.0" />
  <row Id="5225" PostHistoryTypeId="3" PostId="2258" RevisionGUID="9f57fb59-3bcc-45df-9654-45c74754afe5" CreationDate="2016-03-31T10:35:49.703" UserId="3036" Text="|animation|motion|capture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5226" PostHistoryTypeId="5" PostId="2030" RevisionGUID="50dc6f5b-2877-4d2d-9149-b31efab4a45f" CreationDate="2016-03-31T11:34:58.573" UserId="2666" Comment="added 70 characters in body" Text="I am implementing a simple ray tracer with OpenGL. I have a shader storage buffer with all the triangles so I can test them for intersections in a compute shader. It works fine up to a certain buffer size. But if I have more than a certain amount, it stops working and I get the following message:&#xD;&#xA;&#xD;&#xA;&gt; OpenGL: Buffer usage warning: Discarding a video memory only buffer object. The data store will be reallocated on next usage of the buffer object.&#xD;&#xA;&#xD;&#xA;The program does not crash however.&#xD;&#xA;&#xD;&#xA;The `GL_MAX_SHADER_STORAGE_BLOCK_SIZE` is 2147483647, so 2GB. The size of the buffer when it doesn't work anymore is just a couple of MB, around 6 to 7 MB.&#xD;&#xA;&#xD;&#xA;Am I overlooking something? Are there other limits I don't know about?&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;My specs: Linux Mint 17.2, GTX 980Ti with 6GB of VRAM" ContentLicense="CC BY-SA 3.0" />
  <row Id="5230" PostHistoryTypeId="5" PostId="2256" RevisionGUID="b3dcf8f5-381d-462c-8aeb-0c13252fdad0" CreationDate="2016-03-31T14:28:35.870" UserId="38" Comment="added 245 characters in body" Text="There are a number of formats that might fit the bill. Depends on what you want to achieve.&#xD;&#xA;&#xD;&#xA;Most likely your looking for a scene description language for renderers. Many of them are for that one renderer but at least one is a standard. So you might be looking for something like:&#xD;&#xA;&#xD;&#xA;* RIB, [Renderman Bytestream](https://renderman.pixar.com/products/rispec/rispec_pdf/RISpec3_2.pdf) although it comes with as a programming api as well. This is a based on a standard set by Pixar and is used by a number of render engines some of which are open source.&#xD;&#xA;&#xD;&#xA;* Most other rendering solutions also have textual formats I'm somewhat familiar with the mi (mental ray text or binary stream) formats and the now archaic Povray formats. But many others exist.&#xD;&#xA;&#xD;&#xA;It is a bit debatable whether these really are human readable but given that you specify SVG then I guess they are at least and readable as that. Just more complex. Note like SVG these describe scenes.&#xD;&#xA;&#xD;&#xA;Then we have `dae` also known as [collada](https://www.khronos.org/collada/). Which is sort of human readable has a similar niche as `RIB` but is aimed for game assets. A number of other somewhat similar formats exist like the mostly deprecated [VRML](http://gun.teipir.gr/VRML-amgem/spec/index.html) format, and its successors.&#xD;&#xA;&#xD;&#xA;Then we have a bunch of polygon formats, many of them are binary. But atleast `obj` and `ply` are human readable and widely accepted. Obj is a very simple format. Although polygon meshes are seldom really easy to understand or craft manually if they are more complex. &#xD;&#xA;&#xD;&#xA;Then we have a bunch of application specific formats. For example the `ma`, Maya ascii, format which is human readable if you understand how maya node hierarchy works. Cant say much of the others.&#xD;&#xA;&#xD;&#xA;Then we have the CAD transport formats `IGES` and `STEP`. I wouldn't go and claim either to be human readable. But I have hand crafted both on a occasion. Both of these are ISO standards, although STEP is insanely big and was in fact the biggest of ISO standards in page count last time I checked.&#xD;&#xA;&#xD;&#xA;There are quite many of these formats because 3D is not as uniform as 2D is. But, yes, I have hand crafted all of these at one point or another. Does not mean i would consider doing so as a productivity tool. Unlike EPS or SVG, which I craft bi weekly by hand. &#xD;&#xA;&#xD;&#xA;If I would have to guess your motives then i would say RIB is probably what you want. Or then your looking to use obj." ContentLicense="CC BY-SA 3.0" />
  <row Id="5231" PostHistoryTypeId="2" PostId="2259" RevisionGUID="5dc1a132-606f-4028-8456-5024996720cf" CreationDate="2016-03-31T15:38:59.380" UserId="3038" Text="What I am interested in doing is taking a 360 degree stereo video (Oculus Rift etc), and a description of how the viewing direction changes with time (rather than reading from gyroscopes) and then rendering that to a simple side by side rectangular video (so that you can stick the result on a smartphone and view it with the inbuilt video viewer).&#xD;&#xA;&#xD;&#xA;This will naturally involve something like sphere mapping the source, and rendering the result, as the smartphone apps do. I am interested in doing this transformation offline. Is there software around that already does this? Or what are the most suitable libraries to use if I want to program it myself?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5232" PostHistoryTypeId="1" PostId="2259" RevisionGUID="5dc1a132-606f-4028-8456-5024996720cf" CreationDate="2016-03-31T15:38:59.380" UserId="3038" Text="Converting from 360 degree vr to rectangular" ContentLicense="CC BY-SA 3.0" />
  <row Id="5233" PostHistoryTypeId="3" PostId="2259" RevisionGUID="5dc1a132-606f-4028-8456-5024996720cf" CreationDate="2016-03-31T15:38:59.380" UserId="3038" Text="|virtual-reality|conversion|video|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5238" PostHistoryTypeId="5" PostId="2204" RevisionGUID="f84bdb6f-8e1d-4e49-933f-79c2ef6fb719" CreationDate="2016-04-01T09:31:26.370" UserId="2898" Comment="correct answer logic" Text="Start from any triangle. Traverse it's edge's and check that the angle between the two triangles is less than 180deg. If it is add it to the current selection and continue expanding.&#xD;&#xA;&#xD;&#xA;The check is actually really simple if you use vector geometry. Say A - B is the common edge with C on the selected side and D on the other. Then just check if `dot((D-B), cross((A-B), (C-B)) &lt; 0`.&#xD;&#xA;&#xD;&#xA;Single triangle patches should be ruled out, as for us to determine convexity, it has to span across several triangles.&#xD;&#xA;We have to keep sampling until we've tested everything.  When a convex patch continues further, it's size keeps on increasing by including the neighbouring triangles that satisfy convexity, until the patch reaches the maximum size it can attain." ContentLicense="CC BY-SA 3.0" />
  <row Id="5245" PostHistoryTypeId="5" PostId="2201" RevisionGUID="0d03fff9-8855-40bd-94a9-65795f6967c6" CreationDate="2016-04-03T08:45:59.447" UserId="2898" Comment="provide more comprehensive description" Text="Given a 3D object in Computer graphics, whose surface is represented as a 3D triangular mesh (mesh of 3D triangle objects), I need to find the maximum continual Convex patches on the surface of the given 3D object.&#xD;&#xA;&#xD;&#xA;I am using OpenGl to render the graphics within a C++ program. What kind of methods or algorithms should I use to find the convex patches.&#xD;&#xA;&#xD;&#xA;I have to apply different colors to the different convex patches on the object to signify the selection. &#xD;&#xA;&#xD;&#xA;Say I have a sphere then the whole sphere is one maximal convex patch. Any portion of the sphere surface will be a convex patch, by maximal I mean the maximum continuous convex patches that can be found. Well in the rendering, depending on the viewing angles, the maximal convex patches visible to the viewer will have to colored. I have to report all the convex patches, each patch being the maximal in that area.&#xD;&#xA;&#xD;&#xA;I am using &quot;maximal&quot; to mean a convex surface which is not a subset of a larger convex surface, rather than to mean the largest convex surface that exists in the triangle mesh. The patches need to be strictly convex (never flat)." ContentLicense="CC BY-SA 3.0" />
  <row Id="5248" PostHistoryTypeId="2" PostId="2262" RevisionGUID="1a385d3d-860b-4c58-9a59-1d88eb31fbe7" CreationDate="2016-04-03T18:04:03.003" UserId="127" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="5249" PostHistoryTypeId="2" PostId="2263" RevisionGUID="64f6e7fe-2a92-4b26-a2c9-e25cbb6f4fd8" CreationDate="2016-04-03T18:04:03.003" UserId="127" Text="For questions specifically about the Geometry Shader stage in the GPU pipeline." ContentLicense="CC BY-SA 3.0" />
  <row Id="5250" PostHistoryTypeId="2" PostId="2264" RevisionGUID="7abced72-dacd-46d3-bcb5-f51b7ccada6a" CreationDate="2016-04-03T20:15:54.950" UserId="2308" Text="I recently watched [this][1] video that talked from a physics perspective how most of the ways we deal with color on the computer is incorrect because brightness is on a logarithmic not linear scale.  Being a novice graphics programmer I want to know how to deal with the information to make my graphics even better. I figure ray-tracers but for rasterizing, blur, grading, and light adjusting like HDR what am I supposed to do with this information?&#xD;&#xA;&#xD;&#xA;So I guess I have some questions. (sorry its a lot)&#xD;&#xA;&#xD;&#xA; 1. Most texture data is stored in a format where the rgb brightness is incorrect because it has not been square rooted (right?) therefore if we want to display it correctly &#xD;&#xA; 2. When using textures is the gaussian formula technically incorrect? If so what would be the mathematically correct method.&#xD;&#xA; 3. What part of this problem is the monitor responsible for? Does it square or squareroot the values it gets?&#xD;&#xA; 4. What part of the problem is the GPU responsible for when you ask it to sample a color at a point? Does it square or squareroot the values it gets?&#xD;&#xA; 5. Do people know about this property and just not act on it because square rooting a number is an expensive computation? If so do we have a good way to quickly approximate the squareroot of numbers from 0-1?&#xD;&#xA; 6. How do you apply the knowledge from that video in your graphics?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=LKnqECcg6Gw" ContentLicense="CC BY-SA 3.0" />
  <row Id="5251" PostHistoryTypeId="1" PostId="2264" RevisionGUID="7abced72-dacd-46d3-bcb5-f51b7ccada6a" CreationDate="2016-04-03T20:15:54.950" UserId="2308" Text="How are we supposed to fix brightness with square roots?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5252" PostHistoryTypeId="3" PostId="2264" RevisionGUID="7abced72-dacd-46d3-bcb5-f51b7ccada6a" CreationDate="2016-04-03T20:15:54.950" UserId="2308" Text="|physics|color-science|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5256" PostHistoryTypeId="2" PostId="2266" RevisionGUID="1a51edcb-3937-4e9b-82be-01c2b9439114" CreationDate="2016-04-04T05:41:06.400" UserId="48" Text="What the video is talking about is called [gamma correction](https://en.wikipedia.org/wiki/Gamma_correction) and it's a very familiar topic for graphics programmers. The first 30 minutes of John Hable's [talk on Uncharted 2 rendering](http://www.gdcvault.com/play/1012351/Uncharted-2-HDR) is my favorite introduction to &quot;why graphics programmers should care about gamma&quot;, as well as being a good introduction to HDR rendering. If you don't want to watch the talk (though I highly recommend it), [The Importance of Being Linear](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html) is also a good article, and Charles Poynton has a [Gamma FAQ](http://www.poynton.com/notes/colour_and_gamma/GammaFAQ.html) that goes into more technical detail and explains the terminology used.&#xD;&#xA;&#xD;&#xA;By the way, square/squareroot is only an approximation; the [sRGB gamma curve](https://en.wikipedia.org/wiki/SRGB) is what's most commonly used in practice (see the formulas there mentioning $C_\text{srgb}$ and $C_\text{linear}$). See also [this related question](http://computergraphics.stackexchange.com/questions/68/is-gamma-still-important-to-take-into-account) about gamma and color spaces. It's a bit more complicated of a topic than the video makes it sound. :)&#xD;&#xA;&#xD;&#xA;To answer your specific questions:&#xD;&#xA;&#xD;&#xA;1. Yes, most image data is stored in gamma format, so the pixel values do _not_ represent linear luminance. I wouldn't describe it as &quot;incorrect&quot;, since gamma encoding has the useful property of putting more values in the darks, which is better for perceptual precision (as mentioned in the video). Gamma encoding is absolutely necessary to make good-looking images with only 8 bits per RGB component; if you stored linear values you would need more like 12 bits per component to get enough precision in the darks.&#xD;&#xA;&#xD;&#xA;2. To be more physically correct, when blurring an image, one should convert it to linear luminance, then do the blur (Gaussian or otherwise), then convert it back to the original color space.&#xD;&#xA;&#xD;&#xA;3. The monitor accepts image data in gamma format. So the pixel values do not represent linear luminance, and the output brightness is not linearly proportional to the pixel values.&#xD;&#xA;&#xD;&#xA; If it's a good-quality, calibrated monitor, then it accepts data in a specific color space such as sRGB or Adobe RGB and reproduces the colors accurately based on the definition of that color space. If it's a crap uncalibrated monitor, then who knows what you'll get, but it'll be something _kinda_ like sRGB.&#xD;&#xA;&#xD;&#xA;4. GPUs can be configured to do various things here. Modern GPUs have hardware support to automatically convert values between gamma and linear when sampling a texture, or storing a value out to the framebuffer, but the programmer has to explicitly enable that using an API such as Direct3D or OpenGL.&#xD;&#xA;&#xD;&#xA;5. Computer graphics people certainly do know about this topic, and it's critical to get it right when building a realistic renderer for film, AAA games, and so on. However, a lot of more &quot;everyday&quot; apps like web browsers and image editors (even Photoshop, as the video mentions) don't really handle gamma correctly.&#xD;&#xA;&#xD;&#xA; It's not an issue of processing power; maybe that was a problem 20 years ago, but today even mobile phones have ample processing power to convert images between gamma and linear. The reason why web browsers and image editors still don't get this right is some combination of (a) ignorance, (b) not believing that gamma is important enough to be worth getting right, and (c) simply being stuck with bad behavior because it's been that way for a long time and users have come to expect it, so they freak out if something changes.&#xD;&#xA;&#xD;&#xA;6. As mentioned, we have to think a lot about gamma when building a renderer. Most computations (e.g. lighting) should be done in linear space, but the input textures and output image should be in gamma space. Also, maybe some parts of rendering such as UI compositing should happen in gamma space because it's more familiar to artists (it works more like Photoshop layer compositing and such). Also, we have to decide if internal render targets are going to be stored in linear or gamma space, as it will affect precision. And we have to get all the conversions right, so that data gets converted between linear and gamma at the right spots in the rendering process." ContentLicense="CC BY-SA 3.0" />
  <row Id="5258" PostHistoryTypeId="2" PostId="2267" RevisionGUID="6d79a4e1-070f-42b4-bf25-0c346172831d" CreationDate="2016-04-04T12:16:01.040" UserId="110" Text="In [Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, Section 2.2](https://hal.inria.fr/hal-01024289/document#page=8), Mr Eric Heitz defines the distribution of normals as:&#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;[![Definition of D][1]][1]&#xD;&#xA;&#xD;&#xA;And then, he goes on with the following assertion:&#xD;&#xA;&#xD;&#xA;[![Property of D][2]][2]&#xD;&#xA;&#xD;&#xA;I fail to understand how can D have such a property. Is it an assumption based on common sense or on geometrical considerations? Or can this equality be proven by manipulating the formulation of the integral?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zgYQM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cDXlW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5259" PostHistoryTypeId="1" PostId="2267" RevisionGUID="6d79a4e1-070f-42b4-bf25-0c346172831d" CreationDate="2016-04-04T12:16:01.040" UserId="110" Text="Why does the integral of NDF over a solid angle equals the area where micronormals belong to that angle?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5260" PostHistoryTypeId="3" PostId="2267" RevisionGUID="6d79a4e1-070f-42b4-bf25-0c346172831d" CreationDate="2016-04-04T12:16:01.040" UserId="110" Text="|distribution|integral|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5269" PostHistoryTypeId="2" PostId="2269" RevisionGUID="0d77a7d7-4294-47d9-9ab1-c6b1a2f3145f" CreationDate="2016-04-05T05:15:23.133" UserId="196" Text="$D(\omega)$ is defined as the area of the microsurface with normals pointing in the direction $\omega$. $\mathcal{M}'$ is defined as the portion of the microsurface with normals point in the direction $\omega \in \Omega'$. So it's natural that the integral of $D(\omega)$ over $\Omega'$ gives the area of $\mathcal{M}'$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Substituting the definition of $D$ into (4) gives:&#xD;&#xA;&#xD;&#xA;$\int_{\Omega'} D(\omega_m) d\omega_m = \int_{\Omega'} \int_{\mathcal{M}} \delta_{\omega}(\omega_m(p_m)) d p_m d\omega_m$&#xD;&#xA;&#xD;&#xA;A fundamental property of the Dirac delta function is that it integrates to 1 over its domain. Unfortunately, we are integrating over $\Omega'$, not $\Omega$. Here I will stop pretending that I am actually able to use formal mathematical terms, and I will just note that the integrand has non-zero values only where both $d p_m \in \mathcal{M'}$ and $d\omega_m \in \Omega'$, which is what (3) says. As long as at least one of our integration domains is restricted to the set we care about, we will get the same result. So I'll just move the prime around a tad:&#xD;&#xA;&#xD;&#xA;$\int_{\Omega'} D(\omega_m) d\omega_m = \int_{\Omega} \int_{\mathcal{M}'} \delta_{\omega}(\omega_m(p_m)) d p_m d\omega_m$&#xD;&#xA;&#xD;&#xA;Now we can apply the Dirac delta identity, since we're integrating over the whole domain:&#xD;&#xA;&#xD;&#xA;$\int_{\Omega'} D(\omega_m) d\omega_m = \int_{\mathcal{M}'} d p_m$&#xD;&#xA;&#xD;&#xA;Ta-da!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5270" PostHistoryTypeId="5" PostId="2269" RevisionGUID="ed048531-ca2f-406c-8149-af052249c11d" CreationDate="2016-04-05T05:46:47.927" UserId="196" Comment="unit clarification" Text="$D(\omega)$ is defined as the area ($m^2$ unit in the numerator) of the microsurface with normals pointing in the direction $\omega$. $\mathcal{M}'$ is defined as the portion of the microsurface with normals point in the direction $\omega \in \Omega'$. So it's natural that the integral of $D(\omega)$ over $\Omega'$ gives the area of $\mathcal{M}'$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Substituting the definition of $D$ into (4) gives:&#xD;&#xA;&#xD;&#xA;$\int_{\Omega'} D(\omega_m) d\omega_m = \int_{\Omega'} \int_{\mathcal{M}} \delta_{\omega}(\omega_m(p_m)) d p_m d\omega_m$&#xD;&#xA;&#xD;&#xA;A fundamental property of the Dirac delta function is that it integrates to 1 over its domain. Unfortunately, we are integrating over $\Omega'$, not $\Omega$. Here I will stop pretending that I am actually able to use formal mathematical terms, and I will just note that the integrand has non-zero values only where both $d p_m \in \mathcal{M'}$ and $d\omega_m \in \Omega'$, which is what (3) says. As long as at least one of our integration domains is restricted to the set we care about, we will get the same result. So I'll just move the prime around a tad:&#xD;&#xA;&#xD;&#xA;$\int_{\Omega'} D(\omega_m) d\omega_m = \int_{\Omega} \int_{\mathcal{M}'} \delta_{\omega}(\omega_m(p_m)) d p_m d\omega_m$&#xD;&#xA;&#xD;&#xA;Now we can apply the Dirac delta identity, since we're integrating over the whole domain:&#xD;&#xA;&#xD;&#xA;$\int_{\Omega'} D(\omega_m) d\omega_m = \int_{\mathcal{M}'} d p_m$&#xD;&#xA;&#xD;&#xA;Ta-da!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5272" PostHistoryTypeId="2" PostId="2270" RevisionGUID="5bde73c7-cdc0-4951-96d7-a72ba0ba53cf" CreationDate="2016-04-05T08:42:57.990" UserId="3058" Text="1) Update the front buffer will cause screen tearing, every one knows it.&#xD;&#xA;&#xD;&#xA;2) But V-Sync, I think it still get the same issue. Why I get this idea? &#xD;&#xA;&#xD;&#xA;2.1) When GPU flips to the back buffer, current screen displays the old image which was in previous front buffer.&#xD;&#xA;&#xD;&#xA;2.2) Now GPU sends image from &quot;current front buffer&quot; (previous back buffer) to monitor. This will last 16.7ms (60Hz). During this period, Human eyes will see half &quot;current front buffer&quot; and half &quot;previous front buffer&quot;. Is it right?&#xD;&#xA;&#xD;&#xA;2.3) If it is right, it would be same as non-V-sync.&#xD;&#xA;&#xD;&#xA;3) But, in fact, when I switch &quot;V-sync&quot; on, I can't see screen tearing. Why?&#xD;&#xA;&#xD;&#xA;Thanks a lot for the answers.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5273" PostHistoryTypeId="1" PostId="2270" RevisionGUID="5bde73c7-cdc0-4951-96d7-a72ba0ba53cf" CreationDate="2016-04-05T08:42:57.990" UserId="3058" Text="Can V-Sync avoid tearing? I think it can't. Am I wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5274" PostHistoryTypeId="3" PostId="2270" RevisionGUID="5bde73c7-cdc0-4951-96d7-a72ba0ba53cf" CreationDate="2016-04-05T08:42:57.990" UserId="3058" Text="|rendering|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5275" PostHistoryTypeId="2" PostId="2271" RevisionGUID="c430d5e5-d143-4d93-9fa3-f258220fb236" CreationDate="2016-04-05T09:09:45.963" UserId="3058" Text="According to the following assumptions, I think Cloud based VR would be the future:&#xD;&#xA;&#xD;&#xA;1) Real world scene rendering needs ray tracing or other complex computing graphics technologies. It needs a lot of computing power.&#xD;&#xA;&#xD;&#xA;2) Single GPU can't afford enough GFLOPS for that. And the powerful GPU is costly and hot. Since the moore's law is ending soon, the process of GPU will also end evolution, that means GPU can't get much faster than needed.&#xD;&#xA;&#xD;&#xA;3) Mobility is the king. But mobile GPU speed will be limited by the power and process. It won't get much faster too.&#xD;&#xA;&#xD;&#xA;4) Cloud gaming would be promise for that. The network bandwidth and latency would be the biggest issues. Since Google Fiber has been deployed, I don't think network is the issue in the future.&#xD;&#xA;&#xD;&#xA;5) Rendering a real world needs unlimited computing power, but human eye resolution is limited. Limited resolution means limited network bandwidth consumption. For example, 1Gbps is enough to transmite 8K/16K H265 streaming video in stereo format.&#xD;&#xA;&#xD;&#xA;So, I believe Cloud based VR (Rendering in Cloud and stream to the client) would be the future. Am I correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5276" PostHistoryTypeId="1" PostId="2271" RevisionGUID="c430d5e5-d143-4d93-9fa3-f258220fb236" CreationDate="2016-04-05T09:09:45.963" UserId="3058" Text="Cloud based VR would be the future?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5277" PostHistoryTypeId="3" PostId="2271" RevisionGUID="c430d5e5-d143-4d93-9fa3-f258220fb236" CreationDate="2016-04-05T09:09:45.963" UserId="3058" Text="|gpu|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5278" PostHistoryTypeId="2" PostId="2272" RevisionGUID="5c0103c5-e556-4045-bc8f-675921a827bd" CreationDate="2016-04-05T09:18:37.017" UserId="137" Text="V-sync means that the GPU won't switch buffer until the current frame is done showing. &#xD;&#xA;&#xD;&#xA;When you tell to swap the buffer with V-Sync enabled the actual swap doesn't happen until V-Blank, a small window between frames where nothing is being sent to the screen.&#xD;&#xA;&#xD;&#xA;The reason I think you cannot see the update tear is that it moves across the screen during the update. While a non v-sync tear stays in the same place on the screen for 16 milliseconds." ContentLicense="CC BY-SA 3.0" />
  <row Id="5279" PostHistoryTypeId="2" PostId="2273" RevisionGUID="9b639265-85e8-46fb-ba04-9b46f667a90b" CreationDate="2016-04-05T11:06:05.663" UserId="204" Text="Strictly speaking I think that the latency coming from transferring data over the network will not be low enough for VR. The device will need to send all the head tracking data and the user input over the network to the cloud based rendering farm. Then that data and input would need to be processed, rendered and the video streamed back to the user. Can you imagine playing a game and the the actual game stopping for buffering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5286" PostHistoryTypeId="5" PostId="2271" RevisionGUID="104dbf02-764b-4a8a-b012-75d482b09595" CreationDate="2016-04-06T00:57:54.057" UserId="3058" Comment="more detail on the time distribution in each stage, and how to achieve motion-to-photon in 20ms" Text="According to the following assumptions, I think Cloud based VR would be the future:&#xD;&#xA;&#xD;&#xA;1) Real world scene rendering needs ray tracing or other complex computing graphics technologies. It needs a lot of computing power.&#xD;&#xA;&#xD;&#xA;2) Single GPU can't afford enough GFLOPS for that. And the powerful GPU is costly and hot. Since the moore's law is ending soon, the process of GPU will also end evolution, that means GPU can't get much faster than needed.&#xD;&#xA;&#xD;&#xA;3) Mobility is the king. But mobile GPU speed will be limited by the power and process. It won't get much faster too.&#xD;&#xA;&#xD;&#xA;4) Cloud gaming would be promise for that. The network bandwidth and latency would be the biggest issues. Since Google Fiber has been deployed, I don't think network is the issue in the future.&#xD;&#xA;&#xD;&#xA;5) Rendering a real world needs unlimited computing power, but human eye resolution is limited. Limited resolution means limited network bandwidth consumption. For example, 1Gbps is enough to transmite 8K/16K H265 streaming video in stereo format.&#xD;&#xA;&#xD;&#xA;So, I believe Cloud based VR (Rendering in Cloud and stream to the client) would be the future. Am I correct?&#xD;&#xA;&#xD;&#xA;---------------------------------------------------------------------&#xD;&#xA;added more detail @20160406&#xD;&#xA;&#xD;&#xA;I did some research on it. The motion-to-photon has to be less than 20ms. Maybe only 5ms is left for round trip network. So that the Cloud DC has to be very close to the client. In case optical fiber access, only two hops ( switch and BRAS ) to local router and then to local Cloud DC. If no network congestion with good QoS policy, the network latency would be very low. At the mean time, use distributed GPU clusters to render the VR content and then stream it to the client in parallel to reduce the time further. Let's count the time consumptions during each stages. 1.5ms for head tracking and local cpu processing. 1.5ms for network transmission to Cloud. 1.5 ms for distributed GPU cluster rendering and encoding. 5ms for network transmission to client. 1ms for decoding with special decoder since current video decoder designed for video playing not for VR. 5ms for transmission to monitor (equal 200Hz monitor, or very high bandwidth transmission as display port 1.4). The total time is 1.5+1.5+1.5+5+1+5 = 15.5ms. Of course, if using Foveated Rendering technology, addition 3ms for eye tracking delay, but the network bandwidth and latency will be reduced." ContentLicense="CC BY-SA 3.0" />
  <row Id="5287" PostHistoryTypeId="5" PostId="2271" RevisionGUID="5713eb84-077d-46d9-a0de-45f8ace3e322" CreationDate="2016-04-06T01:03:53.073" UserId="3058" Comment="more detail on the time distribution in each stage, and how to achieve motion-to-photon in 20ms" Text="According to the following assumptions, I think Cloud based VR would be the future:&#xD;&#xA;&#xD;&#xA;1) Real world scene rendering needs ray tracing or other complex computing graphics technologies. It needs a lot of computing power.&#xD;&#xA;&#xD;&#xA;2) Single GPU can't afford enough GFLOPS for that. And the powerful GPU is costly and hot. Since the moore's law is ending soon, the process of GPU will also end evolution, that means GPU can't get much faster than needed.&#xD;&#xA;&#xD;&#xA;3) Mobility is the king. But mobile GPU speed will be limited by the power and process. It won't get much faster too.&#xD;&#xA;&#xD;&#xA;4) Cloud gaming would be promise for that. The network bandwidth and latency would be the biggest issues. Since Google Fiber has been deployed, I don't think network is the issue in the future.&#xD;&#xA;&#xD;&#xA;5) Rendering a real world needs unlimited computing power, but human eye resolution is limited. Limited resolution means limited network bandwidth consumption. For example, 1Gbps is enough to transmite 8K/16K H265 streaming video in stereo format.&#xD;&#xA;&#xD;&#xA;So, I believe Cloud based VR (Rendering in Cloud and stream to the client) would be the future. Am I correct?&#xD;&#xA;&#xD;&#xA;---------------------------------------------------------------------&#xD;&#xA;added more detail @20160406&#xD;&#xA;&#xD;&#xA;I did some research on it. The motion-to-photon has to be less than 20ms. Maybe only 5ms is left for round trip network. So that the Cloud DC has to be very close to the client. In case optical fiber access, only two hops ( switch and BRAS ) to local router and then to local Cloud DC. (Transmission speed in optical is 200K KM/s, so 100KM radius would take only 0.5ms. That means Cloud DC would cover 30K square KM area.)If no network congestion with good QoS policy, the network latency would be very low. At the mean time, use distributed GPU clusters to render the VR content and then stream it to the client in parallel to reduce the time further. Let's count the time consumptions during each stages. 1.5ms for head tracking and local cpu processing. 1.5ms for network transmission to Cloud. 1.5 ms for distributed GPU cluster rendering and encoding. 5ms for network transmission to client. 1ms for decoding with special decoder since current video decoder designed for video playing not for VR. 5ms for transmission to monitor (equal 200Hz monitor, or very high bandwidth transmission as display port 1.4). The total time is 1.5+1.5+1.5+5+1+5 = 15.5ms. Of course, if using Foveated Rendering technology, addition 3ms for eye tracking delay, but the network bandwidth and latency will be reduced." ContentLicense="CC BY-SA 3.0" />
  <row Id="5288" PostHistoryTypeId="2" PostId="2275" RevisionGUID="86d73d68-7526-487d-86c3-f518e940a747" CreationDate="2016-04-06T09:16:19.873" UserId="3058" Text="In virtual reality, the motion-to-photon time is very important. Oculus says it has to be less than 20ms. Maybe 10~15ms is better.&#xD;&#xA;&#xD;&#xA;Some people try to introduce Frameless rendering technology into VR. I think it's good to reduce the latency. But I don't know how the display quality is. According to the paper: &quot;Adaptive Frameless Rendering&quot; and the video (https://www.youtube.com/watch?v=ycSpSSt-yVs), it seems not very good. But, in this paper &quot;Construction and Evaluation of an Ultra Low Latency Frameless Renderer for VR&quot;, the authors used FPGA instead of GPU to render and used Frameless Rendering to reduce the latency to 1ms. &#xD;&#xA;&#xD;&#xA;In my mind, FPGA is very hard to replace GPU in 3D rendering area. And, Frameless Rendering needs &quot;racing the beam&quot;, it is also very hard to program. &#xD;&#xA;&#xD;&#xA;What do you think? Is it real to use FPGA and frameless rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5289" PostHistoryTypeId="1" PostId="2275" RevisionGUID="86d73d68-7526-487d-86c3-f518e940a747" CreationDate="2016-04-06T09:16:19.873" UserId="3058" Text="Can Frameless rendering reduce latency? And, can FPGA do 3D rendering instead of GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5290" PostHistoryTypeId="3" PostId="2275" RevisionGUID="86d73d68-7526-487d-86c3-f518e940a747" CreationDate="2016-04-06T09:16:19.873" UserId="3058" Text="|rendering|gpu|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5291" PostHistoryTypeId="5" PostId="2275" RevisionGUID="1db539a2-5c24-460d-8833-20aaf160b58c" CreationDate="2016-04-06T09:56:17.170" UserId="3058" Comment="some words corrections" Text="In virtual reality, the motion-to-photon time is very important. Oculus says it has to be less than 20ms. Maybe 10~15ms is better.&#xD;&#xA;&#xD;&#xA;Some people try to introduce Frameless rendering technology into VR. I think it's good to reduce the latency. But I don't know how the display quality is. According to the paper: &quot;Adaptive Frameless Rendering&quot; and the video (https://www.youtube.com/watch?v=ycSpSSt-yVs), it seems not very good. But, in this paper &quot;Construction and Evaluation of an Ultra Low Latency Frameless Renderer for VR&quot;, the authors used FPGA instead of GPU to render and used Frameless Rendering to reduce the latency to 1ms. &#xD;&#xA;&#xD;&#xA;In my mind, FPGA is very hard to replace GPU in 3D rendering area. And, Frameless Rendering needs &quot;racing the beam&quot;, it is also very hard to program. &#xD;&#xA;&#xD;&#xA;What do you think? Is it realistic to use FPGA and frameless rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5292" PostHistoryTypeId="2" PostId="2276" RevisionGUID="15ea4e1e-16e0-465d-967a-b87bf98b8551" CreationDate="2016-04-06T17:07:41.003" UserId="48" Text="As other people have mentioned, due to network latency issues, I think that full rendering on a cloud server and streaming video to a client device is unlikely to be workable. Even if the latency can be kept low enough in a best-case scenario, it would only work for a very limited number of users with very high-quality internet connections. (Don't forget that e.g. in the USA, there are still tens of millions of people on dialup or DSL, with no access to cable internet, let alone fiber. It will be decades still before fiber is widespread.) Also, note that many [cloud gaming services](https://en.wikipedia.org/wiki/Cloud_gaming) do exist, but that according to players, input latency is noticeably worse on these services than playing locally on a PC.&#xD;&#xA;&#xD;&#xA;However, all that being said, rendering entirely on a cloud server is not the only way to approach the problem. The most latency-sensitive aspect of VR is head tracking. Oculus's [&quot;timewarp&quot;](https://developer.oculus.com/blog/asynchronous-timewarp-examined/) technology shows that you can quickly and cheaply update a previously rendered image to respond to head rotation, as a 2D image operation: if the user turns their head to the right, you shift the image to the left, and so on. With a depth buffer, you can do positional timewarp as well, although this creates various artifacts with parallax because it's based on a single-layered 2D image.&#xD;&#xA;&#xD;&#xA;Timewarp is certainly cheap enough to run on a mobile device. So, one approach is to render frames in the cloud, stream the video to the client, then timewarp the video on the client device to obtain very low-latency head tracking. This wouldn't help the latency of other inputs such as keyboard/mouse/controller inputs, but those don't induce nausea when they're delayed, the way delayed head-tracking does.&#xD;&#xA;&#xD;&#xA;There are also other possibilities along the lines of splitting rendering between the cloud and the client. For example, object-space lighting and shading could be done on the cloud and streamed to the client as textures; then the client only needs to render simple textured geometry. This would work better than positional timewarp for getting correct parallax when you move your head around, though you'd still have some artifacts with specular shading and reflections. There are a lot of possibilities for offloading rendering to the cloud in VR-friendly ways." ContentLicense="CC BY-SA 3.0" />
  <row Id="5293" PostHistoryTypeId="5" PostId="2275" RevisionGUID="69ef5ce9-b377-4946-9d6c-8e53bfdc164d" CreationDate="2016-04-06T17:13:10.923" UserId="48" Comment="added link to the paper" Text="In virtual reality, the motion-to-photon time is very important. Oculus says it has to be less than 20ms. Maybe 10~15ms is better.&#xD;&#xA;&#xD;&#xA;Some people try to introduce Frameless rendering technology into VR. I think it's good to reduce the latency. But I don't know how the display quality is. According to the paper: [&quot;Adaptive Frameless Rendering&quot;](http://www.cs.virginia.edu/~luebke/publications/pdf/afr.egsr.pdf) and the video (https://www.youtube.com/watch?v=ycSpSSt-yVs), it seems not very good. But, in this paper &quot;Construction and Evaluation of an Ultra Low Latency Frameless Renderer for VR&quot;, the authors used FPGA instead of GPU to render and used Frameless Rendering to reduce the latency to 1ms. &#xD;&#xA;&#xD;&#xA;In my mind, FPGA is very hard to replace GPU in 3D rendering area. And, Frameless Rendering needs &quot;racing the beam&quot;, it is also very hard to program. &#xD;&#xA;&#xD;&#xA;What do you think? Is it realistic to use FPGA and frameless rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5294" PostHistoryTypeId="5" PostId="2275" RevisionGUID="1aef8402-b038-4d67-8a63-06ea47f5d50d" CreationDate="2016-04-06T17:23:15.133" UserId="48" Comment="added 144 characters in body" Text="In virtual reality, the motion-to-photon time is very important. Oculus says it has to be less than 20ms. Maybe 10~15ms is better.&#xD;&#xA;&#xD;&#xA;Some people try to introduce Frameless rendering technology into VR. I think it's good to reduce the latency. But I don't know how the display quality is. According to the paper: [&quot;Adaptive Frameless Rendering&quot;](http://www.cs.virginia.edu/~luebke/publications/pdf/afr.egsr.pdf) and the video (https://www.youtube.com/watch?v=ycSpSSt-yVs), it seems not very good. But, in this paper &quot;[Construction and Evaluation of an Ultra Low Latency Frameless Renderer for VR](http://discovery.ucl.ac.uk/1474834/1/Construction%20and%20Evaluation%20of%20an%20Ultra%20Low%20Latency%20Frameless%20Renderer%20for%20VR.pdf)&quot;, the authors used FPGA instead of GPU to render and used Frameless Rendering to reduce the latency to 1ms. &#xD;&#xA;&#xD;&#xA;In my mind, FPGA is very hard to replace GPU in 3D rendering area. And, Frameless Rendering needs &quot;racing the beam&quot;, it is also very hard to program. &#xD;&#xA;&#xD;&#xA;What do you think? Is it realistic to use FPGA and frameless rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5295" PostHistoryTypeId="2" PostId="2277" RevisionGUID="01b9d6f8-9622-455f-8185-8023a7cec484" CreationDate="2016-04-06T17:52:49.340" UserId="48" Text="First of all, the &quot;frameless rendering&quot; technique is in the context of raytracing, not rasterization. It's not obvious how it could be made to work effectively with rasterization, given that the basic idea of it is to update an image by a combination of temporal reprojection plus firing rays specifically at areas where the algorithm thinks the image is undersampled.&#xD;&#xA;&#xD;&#xA;So this technique is, prima facie, not compatible with rasterization-based graphics applications. But if you're already doing raytracing for other reasons, this technique would be interesting to look at; it certainly appears to improve quality relative to an image raytraced from scratch each frame, with the same number of rays per second.&#xD;&#xA;&#xD;&#xA;Raytracing on a GPU is certainly possible; you don't need an FPGA for that. I've only skimmed the second paper, but my reading of it is that the main reason for the FPGA is to get a close coupling between the display scanout and the rendering activity: namely they &quot;race the beam&quot; and evaluate pixels just before they're about to be scanned out, thus obtaining low latency.&#xD;&#xA;&#xD;&#xA;The GPU equivalent of this is probably to split the image in thin horizontal strips, and kick off a compute dispatch to render each strip just before it starts to be scanned out. Today, this is difficult to accomplish as it requires either millisecond-precise scheduling that desktop OSes are not currently set up for, or it requires the GPU to be able to dispatch based on an interrupt from the scanout unit&amp;mdash;a hardware feature that doesn't currently exist AFAIK (or if it does, it isn't exposed in any graphics APIs). Or you might be able to make it work with a long-running asynchronous compute dispatch, if you can find a way to stay in sync with scanout.&#xD;&#xA;&#xD;&#xA;So, there are obstacles, but they aren't insurmountable, and I think if there was sufficient interest in racing-the-beam-style rendering, then OS and GPU vendors could come up with a way to do it in the future. So I don't think an FPGA is required for this kind of technique to work. On the other hand, the fact that it's based on raytracing is a much bigger obstacle to using it in &quot;real-world&quot; apps and games.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5298" PostHistoryTypeId="2" PostId="2278" RevisionGUID="61a77b4e-4be7-4c37-87d4-fdf4f2e13447" CreationDate="2016-04-07T02:45:58.850" UserId="182" Text="This bachelor thesis briefly reviews six SSAO techniques. It could be a good start.&#xD;&#xA;&#xD;&#xA; * CryEngine 2 AO&#xD;&#xA; * StarCraft II AO&#xD;&#xA; * HBAO&#xD;&#xA; * Volumetric Obscurance&#xD;&#xA; * Alchemy AO&#xD;&#xA; * Unreal Engine 4 AO&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;http://frederikaalund.com/a-comparative-study-of-screen-space-ambient-occlusion-methods/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5299" PostHistoryTypeId="4" PostId="2008" RevisionGUID="7fd47ad0-a8c7-4298-9f51-eb0f564f7d00" CreationDate="2016-04-07T08:03:01.577" UserId="182" Comment="Tried to improve title" Text="Why does my lighting look incorrect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5300" PostHistoryTypeId="24" PostId="2008" RevisionGUID="7fd47ad0-a8c7-4298-9f51-eb0f564f7d00" CreationDate="2016-04-07T08:03:01.577" Comment="Proposed by 182 approved by 48, -1 edit id of 134" ContentLicense="CC BY-SA 3.0" />
  <row Id="5301" PostHistoryTypeId="5" PostId="2008" RevisionGUID="094517b7-126d-42f7-b373-db6fb88ab16b" CreationDate="2016-04-07T08:03:01.577" UserId="209" Comment="Tried to improve title + minor English improvements" Text="[![As you can see the back face is lighting as well][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8UV6b.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hello everyone..&#xD;&#xA;I am having problem with lighting calculations.&#xD;&#xA;I am rotating the camera around a cube which was supposed to be illuminated by the light but the resulting lighting is very weird.&#xD;&#xA;Check out the pic,fragment shader and vertex shader below.&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 norm;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    uniform vec3 lightPos;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    out vec3 ourNormal;&#xD;&#xA;    out vec3 fragPos;&#xD;&#xA;    out vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection*view*model*vec4(pos,1.0);&#xD;&#xA;	    fragPos = vec3(view * model * vec4(pos, 1.0f));&#xD;&#xA;        ourNormal = mat3(transpose(inverse(view * model))) * norm;&#xD;&#xA;	    ourLightPos = vec3(view * vec4(lightPos, 1.0));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    //fragment shader&#xD;&#xA;    &#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    //Output variables&#xD;&#xA;    out vec4 finalColor;&#xD;&#xA;&#xD;&#xA;    //Input variables&#xD;&#xA;    in vec3 ourNormal;&#xD;&#xA;    in vec3 fragPos;&#xD;&#xA;    in vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    //Uniform variables&#xD;&#xA;&#xD;&#xA;    struct Material&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;	    float shininess;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Light&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    uniform Light light;&#xD;&#xA;    uniform Material material;&#xD;&#xA;    uniform vec3 viewPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    //Ambient&#xD;&#xA;	    vec3 ambient = light.ambient*material.ambient;&#xD;&#xA;&#xD;&#xA;	    //Diffuse&#xD;&#xA;	    vec3 normal = normalize(ourNormal);&#xD;&#xA;	    vec3 lightDir = normalize(ourLightPos - fragPos);&#xD;&#xA;	    float diffuseStrength = max(dot(lightDir,normal),0.0);&#xD;&#xA;	    vec3 diffuse = light.diffuse*(diffuseStrength*material.diffuse);&#xD;&#xA;&#xD;&#xA;	    //Specular&#xD;&#xA;	    vec3 viewDir = normalize(viewPos - fragPos);&#xD;&#xA;	    vec3 reflectDir = reflect(-lightDir,normal);&#xD;&#xA;	    float specularStrength =         pow(max(dot(viewDir,reflectDir),0.0),material.shininess);&#xD;&#xA;	    vec3 specular = light.specular * (specularStrength*material.specular);&#xD;&#xA;&#xD;&#xA;	    //Last step&#xD;&#xA;	    vec3 result = (ambient+diffuse+specular);&#xD;&#xA;	    finalColor = vec4(result,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see I transformed all the positions,normals and light source position in view space i.e camera space but I don't know why Its not working.&#xD;&#xA;Please help.." ContentLicense="CC BY-SA 3.0" />
  <row Id="5302" PostHistoryTypeId="5" PostId="2008" RevisionGUID="e60a65a8-f84a-46c2-985a-ceeec8ceded9" CreationDate="2016-04-07T12:19:34.177" UserId="127" Comment="Edited tags, removed salutation, edited spelling/grammar; edited tags" Text="[![As you can see the back face is lighting as well][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8UV6b.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a problem with lighting calculations.&#xD;&#xA;I am rotating the camera around a cube which was supposed to be illuminated by the light but the resulting lighting is very weird.&#xD;&#xA;Check out the image above, fragment shader and vertex shader below.&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 norm;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    uniform vec3 lightPos;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    out vec3 ourNormal;&#xD;&#xA;    out vec3 fragPos;&#xD;&#xA;    out vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection*view*model*vec4(pos,1.0);&#xD;&#xA;	    fragPos = vec3(view * model * vec4(pos, 1.0f));&#xD;&#xA;        ourNormal = mat3(transpose(inverse(view * model))) * norm;&#xD;&#xA;	    ourLightPos = vec3(view * vec4(lightPos, 1.0));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    //fragment shader&#xD;&#xA;    &#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    //Output variables&#xD;&#xA;    out vec4 finalColor;&#xD;&#xA;&#xD;&#xA;    //Input variables&#xD;&#xA;    in vec3 ourNormal;&#xD;&#xA;    in vec3 fragPos;&#xD;&#xA;    in vec3 ourLightPos;&#xD;&#xA;&#xD;&#xA;    //Uniform variables&#xD;&#xA;&#xD;&#xA;    struct Material&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;	    float shininess;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Light&#xD;&#xA;    {&#xD;&#xA;	    vec3 ambient;&#xD;&#xA;	    vec3 diffuse;&#xD;&#xA;	    vec3 specular;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    uniform Light light;&#xD;&#xA;    uniform Material material;&#xD;&#xA;    uniform vec3 viewPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    //Ambient&#xD;&#xA;	    vec3 ambient = light.ambient*material.ambient;&#xD;&#xA;&#xD;&#xA;	    //Diffuse&#xD;&#xA;	    vec3 normal = normalize(ourNormal);&#xD;&#xA;	    vec3 lightDir = normalize(ourLightPos - fragPos);&#xD;&#xA;	    float diffuseStrength = max(dot(lightDir,normal),0.0);&#xD;&#xA;	    vec3 diffuse = light.diffuse*(diffuseStrength*material.diffuse);&#xD;&#xA;&#xD;&#xA;	    //Specular&#xD;&#xA;	    vec3 viewDir = normalize(viewPos - fragPos);&#xD;&#xA;	    vec3 reflectDir = reflect(-lightDir,normal);&#xD;&#xA;	    float specularStrength =         pow(max(dot(viewDir,reflectDir),0.0),material.shininess);&#xD;&#xA;	    vec3 specular = light.specular * (specularStrength*material.specular);&#xD;&#xA;&#xD;&#xA;	    //Last step&#xD;&#xA;	    vec3 result = (ambient+diffuse+specular);&#xD;&#xA;	    finalColor = vec4(result,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see, I transformed all the positions, normals and light source position in view space, i.e camera space, but I don't know why it's not working." ContentLicense="CC BY-SA 3.0" />
  <row Id="5303" PostHistoryTypeId="6" PostId="2008" RevisionGUID="e60a65a8-f84a-46c2-985a-ceeec8ceded9" CreationDate="2016-04-07T12:19:34.177" UserId="127" Comment="Edited tags, removed salutation, edited spelling/grammar; edited tags" Text="|opengl|shader|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5304" PostHistoryTypeId="2" PostId="2279" RevisionGUID="44de68ab-1553-4c52-b90c-eecdc63ab0c6" CreationDate="2016-04-07T12:47:27.967" UserId="3069" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5305" PostHistoryTypeId="1" PostId="2279" RevisionGUID="44de68ab-1553-4c52-b90c-eecdc63ab0c6" CreationDate="2016-04-07T12:47:27.967" UserId="3069" Text="Path tracer not rendering shadows" ContentLicense="CC BY-SA 3.0" />
  <row Id="5306" PostHistoryTypeId="3" PostId="2279" RevisionGUID="44de68ab-1553-4c52-b90c-eecdc63ab0c6" CreationDate="2016-04-07T12:47:27.967" UserId="3069" Text="|c++|lighting|shadow|pathtracing|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5307" PostHistoryTypeId="5" PostId="2279" RevisionGUID="4f61e628-ff91-43cd-809b-a24ea693567c" CreationDate="2016-04-07T13:30:40.707" UserId="3069" Comment="added 124 characters in body" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;EDIT: this is my target reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/QHG2z.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5309" PostHistoryTypeId="2" PostId="2280" RevisionGUID="3f027dd6-44bd-4e4b-a496-f3475a1d9673" CreationDate="2016-04-07T14:59:33.647" UserId="273" Text="The problem with your calculations is that you use a uniform for _viewPos_ which is the camera position.&#xD;&#xA;The rest of your calculations is in Camera-Space, so the _viewPos_ should always be $(0.0, 0.0, 0.0)$ and thereby the $viewDir$ becomes $-1*\text{fragPos}$.&#xD;&#xA;&#xD;&#xA;In general: Always be careful about the different reference frames your calculations can be done in and aim to keep this consistent." ContentLicense="CC BY-SA 3.0" />
  <row Id="5310" PostHistoryTypeId="10" PostId="1495" RevisionGUID="9f3c798b-7bb3-46ff-b995-3ad5c037b59e" CreationDate="2016-04-07T15:23:12.463" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="5311" PostHistoryTypeId="2" PostId="2281" RevisionGUID="72dcb314-a1c5-4fcd-9234-6d373846f793" CreationDate="2016-04-07T16:55:14.700" UserId="182" Text="&gt; is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;I don't see any problem with having a big area light. That said, it also depends on the scale of your scene. If the light is large compared to it, shadows will tend to be more diffuse, like under an overcast sky.&#xD;&#xA;&#xD;&#xA;&gt; shadows are missing.. [...] Can you help me understanding why?&#xD;&#xA;&#xD;&#xA;I haven't found any blatant mistake, but there are two elements that look suspicious to me.&#xD;&#xA;&#xD;&#xA;    if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)) {&#xD;&#xA;        // ...&#xD;&#xA;        return true; //light hit, path completed&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Although this part seems to be correct as far as I can tell, I would try to make sure there is no bug introducing a bias. For every bounce, it checks if there is a ray hitting the light first, and if so it breaks out of the loop: in case the code is incorrect and it happens to hit the light more often than it should, the shadows will disappear.&#xD;&#xA;&#xD;&#xA;Moreover, in the first if:&#xD;&#xA;&#xD;&#xA;    return false; //nothing hit, path non valid&#xD;&#xA;&#xD;&#xA;and the related loop:&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;    {     &#xD;&#xA;      Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Make sure you still take the paths that hit nothing into account when averaging the color of the pixel, otherwise this will also introduce a bias.&#xD;&#xA;&#xD;&#xA;As joojaa said in the comment, you should try using a simpler scene: a few spheres or cubes, no texture. If necessary, maybe even a constant sky dome first instead of a light area.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Other remarks:&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Do you need to store x and y?&#xD;&#xA;&#xD;&#xA;	float distFromObj = length(vert.p);&#xD;&#xA;	float distFromLight = length(hitLightPoint);&#xD;&#xA;&#xD;&#xA;Don't you already have two `t` that you can compare?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5312" PostHistoryTypeId="5" PostId="2279" RevisionGUID="c4252e70-b57d-4992-b8b9-e9583cad1a38" CreationDate="2016-04-07T19:50:46.947" UserId="3069" Comment="added 162 characters in body" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;EDIT: this is my target reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT 2: this is what happens in case the **depth &gt; 1** check is omitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/QHG2z.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hiqEY.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5317" PostHistoryTypeId="2" PostId="2283" RevisionGUID="81ea57c4-7235-4582-a2fb-27490a612183" CreationDate="2016-04-07T22:22:11.080" UserId="2372" Text="I am trying to implement this formula to generate bump but I am facing some issue. The result doesn't look the same it's much darker.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is my result (without same parameters) but it is much darker and I don't get why.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And here is the associated code.&#xD;&#xA;&#xD;&#xA;    // randx, randy and frequencies are array with some random values for each sin wave.&#xD;&#xA;    for (int x = 0; x &lt; _width; ++x)&#xD;&#xA;    {&#xD;&#xA;	    for (int y = 0; y &lt; _height; ++y)&#xD;&#xA;	    {&#xD;&#xA;		    float color = 0.0f;&#xD;&#xA;		    for (int i = 0; i &lt; _iterations; ++i)&#xD;&#xA;		    {&#xD;&#xA;			    val += Mathf.Sin(Mathf.Sqrt(Mathf.Pow(x - randx[i], 2.0f) + Mathf.Pow(y - randy[i], 2.0f)) * 1.0f / (2.08f + 5.0f * frequencies[i]));&#xD;&#xA;		    }&#xD;&#xA;		    color /= (float)_iterations;&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kUWt5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9GUF2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5318" PostHistoryTypeId="1" PostId="2283" RevisionGUID="81ea57c4-7235-4582-a2fb-27490a612183" CreationDate="2016-04-07T22:22:11.080" UserId="2372" Text="Sine-based Tiled Procedural Bump" ContentLicense="CC BY-SA 3.0" />
  <row Id="5319" PostHistoryTypeId="3" PostId="2283" RevisionGUID="81ea57c4-7235-4582-a2fb-27490a612183" CreationDate="2016-04-07T22:22:11.080" UserId="2372" Text="|texture|shader|mathematics|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5320" PostHistoryTypeId="5" PostId="2283" RevisionGUID="f921e839-a93e-4c1d-bfb9-658e86befb80" CreationDate="2016-04-07T22:30:03.530" UserId="2372" Comment="added 61 characters in body" Text="I am trying to implement this formula to generate bump but I am facing some issue. The result doesn't look the same it's much darker.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is my result (without same parameters) but it is much darker and I don't get why.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And here is the associated code.&#xD;&#xA;&#xD;&#xA;    // randx, randy and frequencies are array with some random values for each sin wave.&#xD;&#xA;    for (int x = 0; x &lt; _width; ++x)&#xD;&#xA;    {&#xD;&#xA;	    for (int y = 0; y &lt; _height; ++y)&#xD;&#xA;	    {&#xD;&#xA;		    float color = 0.0f;&#xD;&#xA;		    for (int i = 0; i &lt; _iterations; ++i)&#xD;&#xA;		    {&#xD;&#xA;			    val += Mathf.Sin(Mathf.Sqrt(Mathf.Pow(x - randx[i], 2.0f) + Mathf.Pow(y - randy[i], 2.0f)) * 1.0f / (2.08f + 5.0f * frequencies[i]));&#xD;&#xA;		    }&#xD;&#xA;		    color /= (float)_iterations;&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Any idea why I am getting this result ?&lt;br&gt;&#xD;&#xA;Thanks a lot !&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kUWt5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9GUF2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5321" PostHistoryTypeId="2" PostId="2284" RevisionGUID="e71b453b-aefa-4190-9ce6-1e382a75379c" CreationDate="2016-04-07T23:10:28.537" UserId="231" Text="As you are taking the mean of a number of sine waves, your colour values will range from -1 to 1. From your example image, it looks like only the top half of this range of values (from 0 to 1) is resulting in colour, with everywhere else remaining black.&#xD;&#xA;&#xD;&#xA;If whatever you are using to display the result can only handle positive values, then you will need to convert the result to the correct range of values. For example, to convert from the range [-1 to 1] into the range [0 to 1], you would add 1 and divide by 2.&#xD;&#xA;&#xD;&#xA;In the context of your example code, this could be by following the line&#xD;&#xA;&#xD;&#xA;    color /= (float)_iterations;&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    color += 1;&#xD;&#xA;    color /= 2;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5322" PostHistoryTypeId="5" PostId="36" RevisionGUID="9ff381dc-fe4f-4df8-a272-9af8951b1652" CreationDate="2016-04-08T03:29:29.717" UserId="182" Comment="Add a bit of structure to the answer, and add a note about deprecation." Text="There are two steps that make the VBO more efficient than immediate mode.&#xD;&#xA;&#xD;&#xA;0. **Immediate mode** ([glBegin/glEnd][1], [glVertex*][2], etc.) means that at each frame, you spoon feed the vertices, attribute per attribute (position, normal, color, etc.), to the driver, which then reformats them and finally sends the whole package as a command to the GPU. That a lot of function calls per vertex on each frame.&lt;br/&gt;&#xD;&#xA;  (Note that [immediate mode is deprecated since OpenGL 3.0][3], and is entirely removed from 3.1.)&#xD;&#xA;&#xD;&#xA;1. By using **vertex arrays** (see [glDrawArrays][4], [glDrawElements][5], [glVertexPointer][6], etc.), you can give the driver the whole thing at once and save it the burden of reformatting the vertices. You're effectively replacing several function calls per vertex by just a handful of calls for the whole mesh. But you still need to do that once a frame.&#xD;&#xA;&#xD;&#xA;1. **[Vertex Buffer Object][7]**, or **VBO** (see [glGenBuffers][8], [glBindBuffer][9], etc.) go one step further and store the data on the GPU side: you send it only once, and then just refer to it by a handle. You save bandwidth by not sending the same data over and over at each frame.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man2/xhtml/glVertex.xml&#xD;&#xA;  [3]: https://www.opengl.org/wiki/History_of_OpenGL#Deprecation_Model&#xD;&#xA;  [4]: https://www.opengl.org/sdk/docs/man/html/glDrawArrays.xhtml&#xD;&#xA;  [5]: https://www.opengl.org/sdk/docs/man/html/glDrawElements.xhtml&#xD;&#xA;  [6]: https://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml&#xD;&#xA;  [7]: https://www.opengl.org/wiki/Vertex_Specification#Vertex_Buffer_Object&#xD;&#xA;  [8]: https://www.opengl.org/sdk/docs/man/html/glGenBuffers.xhtml&#xD;&#xA;  [9]: https://www.opengl.org/sdk/docs/man/html/glBindBuffer.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="5323" PostHistoryTypeId="2" PostId="2285" RevisionGUID="7370f126-fa19-4f0a-95ae-edebd0b7ad11" CreationDate="2016-04-08T05:13:10.747" UserId="182" Text="As far as I understand, in a BRDF the Fresnel term is telling us the probability for a photon to be reflected or refracted when it hits a surface.&#xD;&#xA;&#xD;&#xA;The reflected photons will contribute to the specular term, while the refracted ones will contribute to the diffuse term. Therefore when determining, in a physically based manner, the contribution of a light to the color of material, I feel tempted to just write:&#xD;&#xA;&#xD;&#xA;    // Assuming for example:&#xD;&#xA;    //   diffuse = dot(L, N);&#xD;&#xA;    //   specular = pow(dot(H, N), alpha) * (alpha + 2.0) / 8.0;&#xD;&#xA;    //   fresnel = f0 + (1.0 - f0) * pow(1.0 - dot(E, H), 5.0);&#xD;&#xA;    color = lightIntensity * Lerp(diffuse * albedo, specular, fresnel);&#xD;&#xA;&#xD;&#xA;Yet, I don't think I've ever seen it written this way. I have seen the specular term being weighted according to the Fresnel term, but not the diffuse one. In his largely referenced [article on PBR][1], Sébastien Lagarde even states that using $(1 - F)$ to weight the diffuse term is incorrect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What am I missing?&lt;br/&gt;&#xD;&#xA;I would much welcome an explanation that highlights in an obvious manner why this would be incorrect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.wordpress.com/2011/08/17/hello-world/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5324" PostHistoryTypeId="1" PostId="2285" RevisionGUID="7370f126-fa19-4f0a-95ae-edebd0b7ad11" CreationDate="2016-04-08T05:13:10.747" UserId="182" Text="How to properly combine the diffuse and specular terms?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5325" PostHistoryTypeId="3" PostId="2285" RevisionGUID="7370f126-fa19-4f0a-95ae-edebd0b7ad11" CreationDate="2016-04-08T05:13:10.747" UserId="182" Text="|brdf|specular|pbr|diffuse|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5326" PostHistoryTypeId="2" PostId="2286" RevisionGUID="3536b1e1-a027-41a1-a3e8-cc1f6b8d6a29" CreationDate="2016-04-08T05:19:06.857" UserId="182" Text="While browsing to properly write my question, I actually [found the answer][1], which happens to be very simple.&#xD;&#xA;&#xD;&#xA;Another Fresnel term is also going to weight in as the photons make their way out of the material (so being refracted into the air) and become the diffuse term. Thus the correct factor for the diffuse term would be:&#xD;&#xA;&#xD;&#xA;$$(1 - F_{in}) * (1 - F_{out})$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.wordpress.com/2011/08/17/hello-world/#comment-2405" ContentLicense="CC BY-SA 3.0" />
  <row Id="5327" PostHistoryTypeId="5" PostId="36" RevisionGUID="c0f19228-72f5-4056-9db4-9494e8b983bd" CreationDate="2016-04-08T05:37:52.483" UserId="182" Comment="It was not 3.1 but 3.2; added reference." Text="There are two steps that make the VBO more efficient than immediate mode.&#xD;&#xA;&#xD;&#xA;0. **Immediate mode** ([glBegin/glEnd][1], [glVertex*][2], etc.) means that at each frame, you spoon feed the vertices, attribute per attribute (position, normal, color, etc.), to the driver, which then reformats them and finally sends the whole package as a command to the GPU. That a lot of function calls per vertex on each frame.&lt;br/&gt;&#xD;&#xA;  (Note that [immediate mode is deprecated since OpenGL 3.0][3], and is entirely [removed from 3.2][4].)&#xD;&#xA;&#xD;&#xA;1. By using **vertex arrays** (see [glDrawArrays][5], [glDrawElements][6], [glVertexPointer][7], etc.), you can give the driver the whole thing at once and save it the burden of reformatting the vertices. You're effectively replacing several function calls per vertex by just a handful of calls for the whole mesh. But you still need to do that once a frame.&#xD;&#xA;&#xD;&#xA;1. **[Vertex Buffer Object][8]**, or **VBO** (see [glGenBuffers][9], [glBindBuffer][10], etc.) go one step further and store the data on the GPU side: you send it only once, and then just refer to it by a handle. You save bandwidth by not sending the same data over and over at each frame.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man2/xhtml/glBegin.xml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man2/xhtml/glVertex.xml&#xD;&#xA;  [3]: https://www.opengl.org/wiki/History_of_OpenGL#Deprecation_Model&#xD;&#xA;  [4]: https://www.opengl.org/registry/doc/glspec32.core.20091207.pdf&#xD;&#xA;  [5]: https://www.opengl.org/sdk/docs/man/html/glDrawArrays.xhtml&#xD;&#xA;  [6]: https://www.opengl.org/sdk/docs/man/html/glDrawElements.xhtml&#xD;&#xA;  [7]: https://www.opengl.org/sdk/docs/man2/xhtml/glVertexPointer.xml&#xD;&#xA;  [8]: https://www.opengl.org/wiki/Vertex_Specification#Vertex_Buffer_Object&#xD;&#xA;  [9]: https://www.opengl.org/sdk/docs/man/html/glGenBuffers.xhtml&#xD;&#xA;  [10]: https://www.opengl.org/sdk/docs/man/html/glBindBuffer.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="5328" PostHistoryTypeId="2" PostId="2287" RevisionGUID="a98fbb6c-edb5-4c74-a94e-2eacb0e16bec" CreationDate="2016-04-08T06:34:40.257" UserId="3073" Text="For modern GPUs it's commonly stored in VRAM which for discrete GPUs are separate from the CPU memory. This usually means there is a penalty associated with letting the CPU access this as the data typically has to be copied across some bus. Mobile devices tend to use shared RAM for both GPU and CPU." ContentLicense="CC BY-SA 3.0" />
  <row Id="5329" PostHistoryTypeId="2" PostId="2288" RevisionGUID="2918fc76-1e26-464a-b819-34196813b1cd" CreationDate="2016-04-08T10:13:43.037" UserId="3074" Text="I want to generate video similar to OSX Flurry screensaver ([screenshot](https://i.stack.imgur.com/2wCyP.png)), but I have no idea how it is made. Does anyone here has an idea about how it's made, its algorithm and method?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5330" PostHistoryTypeId="1" PostId="2288" RevisionGUID="2918fc76-1e26-464a-b819-34196813b1cd" CreationDate="2016-04-08T10:13:43.037" UserId="3074" Text="How to generate OSX Flurry screensaver" ContentLicense="CC BY-SA 3.0" />
  <row Id="5331" PostHistoryTypeId="3" PostId="2288" RevisionGUID="2918fc76-1e26-464a-b819-34196813b1cd" CreationDate="2016-04-08T10:13:43.037" UserId="3074" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5332" PostHistoryTypeId="5" PostId="2288" RevisionGUID="dc8749ab-850a-4423-8931-dac7d8364dcf" CreationDate="2016-04-08T10:24:24.723" UserId="3074" Comment="added 39 characters in body" Text="I want to generate video similar to OSX Flurry screensaver ([screenshot](https://i.stack.imgur.com/2wCyP.png), [video](https://youtu.be/JWzBK87t19U)), but I have no idea how it is made. Does anyone here has an idea about how it's made, its algorithm and method?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5333" PostHistoryTypeId="2" PostId="2289" RevisionGUID="53dcdbca-a38b-48ef-bcdf-f22475469a99" CreationDate="2016-04-08T11:41:51.023" UserId="3075" Text="Using two Fresnel terms is correct in the sense that any given diffuse path will pass through the surface twice. If you're solving diffusion by tracing a path through the medium until it bounces out again then that you will get two (or more) Fresnel terms for that path as it interacts with the surface.&#xD;&#xA;&#xD;&#xA;However, that's not what you're doing with a diffuse BRDF. A diffuse BRDF is intended to represent the average of all those possible diffusion paths. In the case of an Lambertian that average is modeled as uniform reflection and a single albedo value measuring the internal energy loss during diffusion, but more complicated models are possible. Crucially: a diffuse BSDF will already include the aggregate effect of some paths being reflected back into the medium to diffuse further and some passing out immediately. $1 - F_{out}$ is already &quot;baked in&quot; to the BSDF¹ and you do not need factor it in again.&#xD;&#xA;&#xD;&#xA;What the Lambertian term does not include is the portion of energy that is lost by being reflected before light enters the medium of diffusion. This is view-dependent, but depends on the precise glossy lobe above it. There is no energy loss at a (non-metallic) surface interface so everything that isn't reflected will be refracted, meaning that what you actually want is to integrate the total energy loss at the surface over all outgoing directions, i.e. $1 - \int \texttt{glossy_bsdf}(\texttt{in}, \texttt{out}) \: \partial \texttt{out}$.&#xD;&#xA;&#xD;&#xA;It's possible to pre-compute approximations to that integral for specific BRDFS. The end result will in general depend on view direction, material roughness and IOR at least. As a first approximation you can assume that the glossy lobe is a perfectly specular reflector. That gives a weighting of $1 - \int \texttt{glossy} \: \partial \texttt{out} = 1 - F_{in}$, which is exactly what you first suggested.&#xD;&#xA;&#xD;&#xA;Additionally, note that the Lambertian BRDF is the albedo divided by $\pi$ and that the cosine term is a measure of how attenuated the incoming light is on the surface; it applies to both glossy and diffuse reflectance.&#xD;&#xA;&#xD;&#xA;So, roughly:&#xD;&#xA;&#xD;&#xA;    // Assuming for example:&#xD;&#xA;    //   diffuse = albedo / PI;&#xD;&#xA;    //   specular = my_favorite_glossy_brdf(in_dir, out_dir, roughness);&#xD;&#xA;    //   fresnel = f0 + (1.0 - f0) * pow(1.0 - dot(E, H), 5.0);&#xD;&#xA;    //   total_surface_reflection = fresnel&#xD;&#xA;    color = lightIntensity * dot(L, N) * Lerp(diffuse, specular, total_surface_reflection);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;¹ *Really the integral of $F$ over all possible incident internal diffusion exit paths that result in your out direction, but I digress.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="5334" PostHistoryTypeId="5" PostId="2289" RevisionGUID="6f6ad1a8-82b7-41b4-8a4b-ee86084f220c" CreationDate="2016-04-08T11:47:25.927" UserId="3075" Comment="making math less partial" Text="Using two Fresnel terms is correct in the sense that any given diffuse path will pass through the surface twice. If you're solving diffusion by tracing a path through the medium until it bounces out again then that you will get two (or more) Fresnel terms for that path as it interacts with the surface.&#xD;&#xA;&#xD;&#xA;However, that's not what you're doing with a diffuse BRDF. A diffuse BRDF is intended to represent the average of all those possible diffusion paths. In the case of an Lambertian that average is modeled as uniform reflection and a single albedo value measuring the internal energy loss during diffusion, but more complicated models are possible. Crucially: a diffuse BSDF will already include the aggregate effect of some paths being reflected back into the medium to diffuse further and some passing out immediately. $1 - F_{out}$ is already &quot;baked in&quot; to the BSDF¹ and you do not need factor it in again.&#xD;&#xA;&#xD;&#xA;What the Lambertian term does not include is the portion of energy that is lost by being reflected before light enters the medium of diffusion. This is view-dependent, but depends on the precise glossy lobe above it. There is no energy loss at a (non-metallic) surface interface so everything that isn't reflected will be refracted, meaning that what you actually want is to integrate the total energy loss at the surface over all outgoing directions, i.e. $1 - \int \texttt{glossy_bsdf}(\texttt{in}, \texttt{out}) \: \mathrm{d} \texttt{out}$.&#xD;&#xA;&#xD;&#xA;It's possible to pre-compute approximations to that integral for specific BRDFs. The end result will in general depend on view direction, material roughness and IOR at least. As a first approximation you can assume that the glossy lobe is a perfectly specular reflector. That gives a weighting of $1 - \int \texttt{glossy} \: \mathrm{d}\texttt{out} = 1 - F_{in}$, which is exactly what you first suggested.&#xD;&#xA;&#xD;&#xA;Additionally, note that the Lambertian BRDF is the albedo divided by $\pi$ and that the cosine term is a measure of how attenuated the incoming light is on the surface; it applies to both glossy and diffuse reflectance.&#xD;&#xA;&#xD;&#xA;So, roughly:&#xD;&#xA;&#xD;&#xA;    // Assuming for example:&#xD;&#xA;    //   diffuse = albedo / PI;&#xD;&#xA;    //   specular = my_favorite_glossy_brdf(in_dir, out_dir, roughness);&#xD;&#xA;    //   fresnel = f0 + (1.0 - f0) * pow(1.0 - dot(E, H), 5.0);&#xD;&#xA;    //   total_surface_reflection = fresnel&#xD;&#xA;    color = lightIntensity * dot(L, N) * Lerp(diffuse, specular, total_surface_reflection);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;¹ *Really the integral of $F$ over all possible incident internal diffusion exit paths that result in your out direction, but I digress.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="5335" PostHistoryTypeId="5" PostId="2283" RevisionGUID="12172f8f-b3c2-4e9d-b788-07a57676b84d" CreationDate="2016-04-08T12:17:27.073" UserId="2372" Comment="added 252 characters in body" Text="I am trying to implement this formula to generate bump but I am facing some issue. The result doesn't look the same it's much darker.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is my result (without same parameters) but it is much darker and I don't get why.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And here is the associated code.&#xD;&#xA;&#xD;&#xA;    // randx, randy and frequencies are array with some random values for each sin wave.&#xD;&#xA;    for (int x = 0; x &lt; _width; ++x)&#xD;&#xA;    {&#xD;&#xA;	    for (int y = 0; y &lt; _height; ++y)&#xD;&#xA;	    {&#xD;&#xA;		    float color = 0.0f;&#xD;&#xA;		    for (int i = 0; i &lt; _iterations; ++i)&#xD;&#xA;		    {&#xD;&#xA;			    val += Mathf.Sin(Mathf.Sqrt(Mathf.Pow(x - randx[i], 2.0f) + Mathf.Pow(y - randy[i], 2.0f)) * 1.0f / (2.08f + 5.0f * frequencies[i]));&#xD;&#xA;		    }&#xD;&#xA;		    color /= (float)_iterations;&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Any idea why I am getting this result ?&lt;br&gt;&#xD;&#xA;Thanks a lot !&#xD;&#xA;&#xD;&#xA;**EDIT**: Thanks to @trichoplax it works by doing this.&#xD;&#xA;&#xD;&#xA;    float tmp = Mathf.Sin(Mathf.Sqrt(Mathf.Pow(x - randx[i], 2.0f) + Mathf.Pow(y - randy[i], 2.0f)) * 1.0f / (2.08f + 5.0f * frequencies[i]));&#xD;&#xA;    tmp = tmp * 0.5f + 0.5f;&#xD;&#xA;    val += tmp;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kUWt5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9GUF2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5336" PostHistoryTypeId="2" PostId="2290" RevisionGUID="7d541739-54ef-4448-896d-1639f7ac49b6" CreationDate="2016-04-08T12:52:30.253" UserId="182" Text="If multi-texturing is supported, texture coordinate generation will affect the active texture unit (quote from the documentation, emphasis is mine):&#xD;&#xA;&#xD;&#xA;&gt; When the ARB_multitexture extension is supported, [glTexGen][1] sets the texture generation parameters **for the currently active texture unit, selected with glActiveTexture**.&#xD;&#xA;&#xD;&#xA;So you simply need to make sure texture coordinates generation is disabled for the color texture, but enabled for the shadow texture. As you guessed, this is done with [`glActiveTexture()`][2], by writing for example:&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0); // Assuming the color texture to be #0&#xD;&#xA;    glDisable(GL_TEXTURE_GEN_S);&#xD;&#xA;    glDisable(GL_TEXTURE_GEN_T);&#xD;&#xA;    glDisable(GL_TEXTURE_GEN_R);&#xD;&#xA;    glDisable(GL_TEXTURE_GEN_Q);&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE1); // Assuming the shadow texture to be #1&#xD;&#xA;    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);&#xD;&#xA;    glTexGenfv(GL_S, GL_EYE_PLANE, textureMatrix.GetRow(0));&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_S);&#xD;&#xA;    // [...]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;This being said, you're adding to yourself a lot of trouble by sticking with fixed pipeline instead of using GLSL.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man2/xhtml/glTexGen.xml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="5338" PostHistoryTypeId="2" PostId="2291" RevisionGUID="c11f1a7f-5779-4192-9b54-a960a8cc9add" CreationDate="2016-04-08T14:06:10.073" UserId="231" Text="## The problem appears to be unintentionally transparent surfaces&#xD;&#xA;&#xD;&#xA;Although the image is grainy, it is sufficiently clear to estimate that all of the darker regions are due to surfaces facing away from the light, rather than due to shadows cast onto surfaces facing towards the light. So it does seem that there is a problem, and the lack of shadows is not just due to having soft shadows from a large area light that don't show up well, or excessively reflective surfaces that provide too much ambient light. Somehow light is getting through your surfaces.&#xD;&#xA;&#xD;&#xA;## The probable source of this problem&#xD;&#xA;Since you check for intersection with the light and the objects separately, the crucial point where this could go wrong is where you check&#xD;&#xA;&#xD;&#xA;    if (distFromLight &lt; distFromObj)&#xD;&#xA;&#xD;&#xA;You correctly terminate the path and return the light colour if this check is true (that is, if the light is closer than the nearest object in that direction). So the problem is likely to be with one of the two variables you are comparing. If they were both correct, then you would see shadows.&#xD;&#xA;&#xD;&#xA;These are calculated on the preceding lines&#xD;&#xA;&#xD;&#xA;    float distFromObj = length(vert.p);&#xD;&#xA;    float distFromLight = length(hitLightPoint);&#xD;&#xA;&#xD;&#xA;As pointed out in [Julien Guertault's answer], these calculations may be redundant.&#xD;&#xA;&#xD;&#xA;`length(vert.p)` should still be available as `t`, used 11 lines previously in the calculation of `vert.p`. This not only avoids unnecessary calculation, but eliminates a potential source of error. Then this length is likely to be correct unless there is a problem with `checkIfRayIntersectSomething()`.&#xD;&#xA;&#xD;&#xA;This leaves only `length(hitLightPoint)` as a source of error, unless there is a more subtle problem. It would be useful to be able to eliminate the possibility of problems with `length()` or `hitLightPoint`, which is calculated by `checkRayLightIntersection()`.&#xD;&#xA;&#xD;&#xA;## We need to see the code to be able to help&#xD;&#xA;&#xD;&#xA;`length()`, `checkIfRayIntersectSomething()` and `checkRayLightIntersection()` are not currently included with the code in your question, so we can't analyse these. If you are able to share these that would help narrow down the source of the problem.&#xD;&#xA;&#xD;&#xA;## A simple way to check whether this is the real problem&#xD;&#xA;&#xD;&#xA;You could also verify whether this analysis of the problem is correct by rendering a scene which will eliminate the other possibilities (shadows too soft to distinguish, or shadows washed out by too much reflected light from the rest of the scene). If the light getting through the surfaces is the source of your problem, then it will apply even if there is no path from the light to a surface, provided that surface is facing the light. So render a simple scene that has a light with a plane beneath it, and another plane beneath that, separated by a gap big enough to easily be seen. The lower plane is completely occluded by the upper plane, so should receive no light (no soft shadows and no reflected light from elsewhere). If the lower plane is lit, then you know that this is indeed the problem and you can focus your efforts here.&#xD;&#xA;&#xD;&#xA;If the lower plane is *not* lit, then either this is not the problem, or there is a problem with the scale and the occluding plane may need to be at a different distance from the light in order for the problem to show up. You can use your existing scene as a source of estimated distances for which this problem occurs, and you can use inclined planes in order to see the effect for a variety of ratios of object distance to light distance within a single image.&#xD;&#xA;&#xD;&#xA;Sharing the images resulting from such simple scenes may help us identify the problem more precisely.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Julien Guertault's answer]: http://computergraphics.stackexchange.com/a/2281/231" ContentLicense="CC BY-SA 3.0" />
  <row Id="5339" PostHistoryTypeId="5" PostId="2291" RevisionGUID="2905bc55-e0ec-484f-b595-93e5b118e5a2" CreationDate="2016-04-08T14:14:45.583" UserId="231" Comment="Suggest ready made test scenes if own cannot be made" Text="## The problem appears to be unintentionally transparent surfaces&#xD;&#xA;&#xD;&#xA;Although the image is grainy, it is sufficiently clear to estimate that all of the darker regions are due to surfaces facing away from the light, rather than due to shadows cast onto surfaces facing towards the light. So it does seem that there is a problem, and the lack of shadows is not just due to having soft shadows from a large area light that don't show up well, or excessively reflective surfaces that provide too much ambient light. Somehow light is getting through your surfaces.&#xD;&#xA;&#xD;&#xA;## The probable source of this problem&#xD;&#xA;Since you check for intersection with the light and the objects separately, the crucial point where this could go wrong is where you check&#xD;&#xA;&#xD;&#xA;    if (distFromLight &lt; distFromObj)&#xD;&#xA;&#xD;&#xA;You correctly terminate the path and return the light colour if this check is true (that is, if the light is closer than the nearest object in that direction). So the problem is likely to be with one of the two variables you are comparing. If they were both correct, then you would see shadows.&#xD;&#xA;&#xD;&#xA;These are calculated on the preceding lines&#xD;&#xA;&#xD;&#xA;    float distFromObj = length(vert.p);&#xD;&#xA;    float distFromLight = length(hitLightPoint);&#xD;&#xA;&#xD;&#xA;As pointed out in [Julien Guertault's answer], these calculations may be redundant.&#xD;&#xA;&#xD;&#xA;`length(vert.p)` should still be available as `t`, used 11 lines previously in the calculation of `vert.p`. This not only avoids unnecessary calculation, but eliminates a potential source of error. Then this length is likely to be correct unless there is a problem with `checkIfRayIntersectSomething()`.&#xD;&#xA;&#xD;&#xA;This leaves only `length(hitLightPoint)` as a source of error, unless there is a more subtle problem. It would be useful to be able to eliminate the possibility of problems with `length()` or `hitLightPoint`, which is calculated by `checkRayLightIntersection()`.&#xD;&#xA;&#xD;&#xA;## We need to see the code to be able to help&#xD;&#xA;&#xD;&#xA;`length()`, `checkIfRayIntersectSomething()` and `checkRayLightIntersection()` are not currently included with the code in your question, so we can't analyse these. If you are able to share these that would help narrow down the source of the problem.&#xD;&#xA;&#xD;&#xA;## A simple way to check whether this is the real problem&#xD;&#xA;&#xD;&#xA;You could also verify whether this analysis of the problem is correct by rendering a scene which will eliminate the other possibilities (shadows too soft to distinguish, or shadows washed out by too much reflected light from the rest of the scene). If the light getting through the surfaces is the source of your problem, then it will apply even if there is no path from the light to a surface, provided that surface is facing the light. So render a simple scene that has a light with a plane beneath it, and another plane beneath that, separated by a gap big enough to easily be seen. The lower plane is completely occluded by the upper plane, so should receive no light (no soft shadows and no reflected light from elsewhere). If the lower plane is lit, then you know that this is indeed the problem and you can focus your efforts here.&#xD;&#xA;&#xD;&#xA;If the lower plane is *not* lit, then either this is not the problem, or there is a problem with the scale and the occluding plane may need to be at a different distance from the light in order for the problem to show up. You can use your existing scene as a source of estimated distances for which this problem occurs, and you can use inclined planes in order to see the effect for a variety of ratios of object distance to light distance within a single image.&#xD;&#xA;&#xD;&#xA;Sharing the images resulting from such simple scenes may help us identify the problem more precisely.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I notice that in a comment on the question you mention that you do not have a straightforward way of generating scenes yourself. Perhaps there are much simpler scenes already publicly available in the same file format, that you can use to test this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Julien Guertault's answer]: http://computergraphics.stackexchange.com/a/2281/231" ContentLicense="CC BY-SA 3.0" />
  <row Id="5346" PostHistoryTypeId="2" PostId="2294" RevisionGUID="2029575a-0b42-4c82-9bf4-e1c7e54e2b63" CreationDate="2016-04-08T19:21:25.237" UserId="3083" Text="A common mistake that causes this behavior is to first apply the translation and then the rotation when rendering the scene. I think that's what's happening. If you apply the rotation first and then the translation it should behave as expected. Give that a try" ContentLicense="CC BY-SA 3.0" />
  <row Id="5349" PostHistoryTypeId="2" PostId="2295" RevisionGUID="ab1b6d1a-d62c-41d7-a2d3-c4bf45730aba" CreationDate="2016-04-09T09:10:49.433" UserId="182" Text="Looking at the video you provided, I would tend to think it's something along those lines:&#xD;&#xA;&#xD;&#xA;* A particle emitter, to which all threads are attached, is moving around. I haven't really figured what its motion is dictated by.&#xD;&#xA;* Each thread is made of particles flowing away from the emitter. The thread has a direction, used for the initial speed of the particles. Once created,  they are independent from the emitter.&#xD;&#xA;* The particles use a quad or a rectangle textured with a fuzzy ellipse shape (you can see them individually when a thread suddenly changes direction) oriented in the direction of the motion. Their color is based on the duration since their creation, and they use additive alpha blending (the saturation to white is typical). After a certain duration, they fade out and die, only to be recycled into new particles.&#xD;&#xA;* I suspect the whole thing might be in a vector field, or something similar blowing wind onto the particles, which would explain why the threads sometimes suddenly change direction.&#xD;&#xA;* There might be some feedback post-processing effect to smooth everything out.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5350" PostHistoryTypeId="5" PostId="2258" RevisionGUID="b5185927-dbdf-4a3f-a9ed-8ce7eb8cd829" CreationDate="2016-04-09T09:27:12.450" UserId="182" Comment="Added math syntax." Text="I am trying to align two motion capture files from different sources.&#xD;&#xA;The motion capture file consist of a skeleton specified as a hierarchy of joints. Each joint i.e. &quot;shoulder&quot; has three pieces of data: rotation order (XYZ), a translation plus direction from a parent joint (the bone vector) and an axis, which is a 3-tuple of rotations $(X, Y, Z)$ that describe the transformation from the parent coordinate system to the local coordinate system. For each frame, a local rotation 3-tuple $m_x, m_y, m_z$ is specified which describes how the bone vector changes from frame to frame.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To calculate the position of a particular bone for a single frame, I calculate:&#xD;&#xA;&#xD;&#xA;$M = M_x \times M_y \times M_z$ where $M_x$, $M_y$, $M_z$ are the rotation matrices correspond to $m_x$, $m_y$ and $m_z$.&#xD;&#xA;&#xD;&#xA;$L = C^{-1} \times M \times C$, where $C$ is the multiplication of 3 $X$, $Y$, $Z$ rotation matrices corresponding to the bone axis.&#xD;&#xA;&#xD;&#xA;This is done for each bone in the hierarchy (i.e shoulder -&gt; clavicle -&gt; spine -&gt; root) and multiplied together to get the global rotation matrix for a particular bone. The bone vector is then multiplied by this rotation matrix to get the $x, y, z$ position.&#xD;&#xA;&#xD;&#xA;The problem is now I have two motion capture files with corresponding joints: say, `shoulderA` and `shoulderB`. Since the joint axes are different, the local per-frame rotations are also different, which means I can't use the frame data for file B for skeleton A. I would like to &quot;refer&quot; `shoulderB` to `shoulderA`, so I'm wondering how I can change the per-frame rotations to do so.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Reference: &#xD;&#xA;http://research.cs.wisc.edu/graphics/Courses/cs-838-1999/Jeff/ASF-AMC.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5351" PostHistoryTypeId="6" PostId="2258" RevisionGUID="b5185927-dbdf-4a3f-a9ed-8ce7eb8cd829" CreationDate="2016-04-09T09:27:12.450" UserId="182" Comment="Added math syntax." Text="|animation|motion|capture|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5354" PostHistoryTypeId="2" PostId="2296" RevisionGUID="9f7c5667-a449-4e03-8c04-57f34d9c2ba8" CreationDate="2016-04-10T02:55:44.603" UserId="48" Text="The short answer is It's Complicated™. :)&#xD;&#xA;&#xD;&#xA;A lot of factors can affect frame timing (and the associated problem of animation juddering, due to the game's animation delta-times not matching actual frame delivery times). Some of the factors are: how CPU-limited versus GPU-limited the game is, how the game's code measures time, how much variability there is in frame time on both the CPU and GPU, how many frames of queue-ahead the CPU is allowed to build up, double versus triple buffering, and driver behavior.&#xD;&#xA;&#xD;&#xA;On the specific question of whether you get locked to a divisor of 60 fps (30, 20, 15, etc), this seems to depend mainly on whether the application is GPU-limited or CPU-limited. If you're GPU-limited, then assuming the application is running steadily (not producing any hitches or rapid performance shifts in itself), it does lock to the highest divisor of the vsync rate that it can sustain. This timing diagram shows how it works:&#xD;&#xA;&#xD;&#xA;![vsync in GPU limited case][1]&#xD;&#xA;&#xD;&#xA;Time runs from left to right and the width of each block represents the duration of one frame's work. After the first few frames, the system settles into a state where the frames are turned out at a steady rate, one every two vsync periods (i.e. if vsync was 60 Hz, the game would be running at exactly 30 fps).&#xD;&#xA;&#xD;&#xA;Note the empty spaces (idle time) in both CPU and GPU rows. That indicates that the game could run faster if vsync were turned off. However, with vsync on, the swapchain puts back-pressure on the GPU&amp;mdash;the GPU can't start rendering the next frame until vsync releases a backbuffer for it to render into. The GPU in turn puts back-pressure on the CPU via the command queue, as the driver won't return from `Present()` / `SwapBuffers()` until the GPU starts rendering the next frame, and opens a queue slot for the CPU to continue issuing commands. The result is that everything runs at a steady 30 fps rate, and everyone's happy (except maybe the 60fps purist gamer ).&#xD;&#xA;&#xD;&#xA;Compare this to what happens when the application is CPU-limited:&#xD;&#xA;&#xD;&#xA;![vsync in CPU-limited case][2]&#xD;&#xA;&#xD;&#xA;This time we ended up with the game running at 36 fps, the maximum speed possible given the CPU load in this case. But this isn't a divisor of the refresh rate, so we get uneven frame delivery to the display, with some frames shown for two vsync periods and some for only one. This will cause judder.&#xD;&#xA;&#xD;&#xA;Here the GPU goes idle because it's waiting for the CPU to give it more work&amp;mdash;not because it's waiting for a backbuffer to be available to render into. The swapchain thus doesn't put back-pressure on the GPU (or at least doesn't do so consistently), and the GPU in turn doesn't put back-pressure on the CPU. So the CPU just runs as fast as it can, oblivious to the irregular frame times appearing on the display.&#xD;&#xA;&#xD;&#xA;It's possible to &quot;fix&quot; this so that the game still discretizes to vsync-friendly rates even in the CPU-limited case. The game code could try to recognize this situation and compensate by sleeping its CPU thread to artificially lock itself to 30 fps, or by increasing its swap interval to 2. Alternatively, the driver could do the same thing by inserting extra sleeps in `Present()` / `SwapBuffers()` (the NVIDIA drivers do have this as a control panel option; I don't know about others). But in any case, _someone_ has to detect the problem and do something about it; the game won't naturally settle on a vsync-friendly rate the way it does when it's GPU-limited.&#xD;&#xA;&#xD;&#xA;This was all a simplified case in which both CPU and GPU workloads are perfectly steady. In real life, of course, there's variability in the workloads and frame times, which can cause even more interesting things to happen. The CPU render-ahead queue and triple buffering can come into play then.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Rm3tV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mXZJo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5368" PostHistoryTypeId="5" PostId="2279" RevisionGUID="b3d8e455-cd60-48ad-a9c1-b46beb045ddc" CreationDate="2016-04-10T17:13:05.187" UserId="3069" Comment="added 1824 characters in body" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;EDIT: this is my target reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT 2: this is what happens in case the **depth &gt; 1** check is omitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;EDIT 3: after fixing the **distFromLight** and **distFromObj** I got the following results:&#xD;&#xA;&#xD;&#xA;[![some clue of shadows][4]][4]&#xD;&#xA;&#xD;&#xA;One of the 2 problems as suggested by @trichoplax could be too soft shadows. So I tried to lower the size of the light, increasing his power to compensate. Results are not good and shown here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Moreover as requested I can post some more code:&#xD;&#xA;&#xD;&#xA;    bool checkRayLightIntersection(Vec O, Vec D, Vec &amp; hitLightPoint){&#xD;&#xA;      //getting the 4 corners of my light&#xD;&#xA;	  Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;	  Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;&#xD;&#xA;	  //the majority of the methods first find out where the ray intersects the plane that the rectangle lies on Ax + By + Cz + D = 0&#xD;&#xA;	  //in our case the equation of that plane is easy -&gt; D = 20&#xD;&#xA;	  // answers.google.com/answers/threadview?id=18979&#xD;&#xA;&#xD;&#xA;	  float t = -(-O.y + lightPos.y) / (-D.y);&#xD;&#xA;	  if (t &gt; 0){&#xD;&#xA;		Vec hitPoint = O + D * t;&#xD;&#xA;		Vec V1 = (P2 - P1).norm();&#xD;&#xA;		Vec V2 = (P3 - P2).norm();&#xD;&#xA;		Vec V3 = (P4 - P3).norm();&#xD;&#xA;		Vec V4 = (P1 - P4).norm();&#xD;&#xA;		Vec V5 = (hitPoint - P1).norm();&#xD;&#xA;		Vec V6 = (hitPoint - P2).norm();&#xD;&#xA;		Vec V7 = (hitPoint - P3).norm();&#xD;&#xA;		Vec V8 = (hitPoint - P4).norm();&#xD;&#xA;&#xD;&#xA;		if (V1.dot(V5) &gt; 0.0 &amp;&amp; V2.dot(V6) &gt; 0.0 &amp;&amp; V3.dot(V7) &gt; 0.0 &amp;&amp; V4.dot(V8) &gt; 0.0){&#xD;&#xA;			hitLightPoint = hitPoint;&#xD;&#xA;			return true;&#xD;&#xA;		}&#xD;&#xA;      }&#xD;&#xA;      return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Instead, the **checkIfRayIntersectSomething** method is part of the framework itself (it has just another name), it's not done by me but it's tested and working.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/QHG2z.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hiqEY.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/JvGhf.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/8aYPH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5369" PostHistoryTypeId="2" PostId="2300" RevisionGUID="1cf22585-01a8-4208-af53-4b3d48804075" CreationDate="2016-04-10T17:26:45.990" UserId="3098" Text="I am new to OpenGL and Computer Graphics in general. &#xD;&#xA;&#xD;&#xA;Lately I was learning how to model a camera, specifically how to model the rotation of camera. I was introduced to Euler angles for this purpose. &#xD;&#xA;&#xD;&#xA;I got a rough idea about how to use Euler angles to model camera rotation from this [post][1]. Based on that, I wrote something like below:&#xD;&#xA;&#xD;&#xA;    GLfloat yaw, pitch;&#xD;&#xA;    ...&#xD;&#xA;    void mouse_callback(GLFWwindow* window, double xpos, double ypos)&#xD;&#xA;    {&#xD;&#xA;            /* &#xD;&#xA;               Here I am updating the yaw, and pitch values &#xD;&#xA;               based on mouse movement and previous mouse position&#xD;&#xA;            */&#xD;&#xA;&#xD;&#xA;            glm::mat4 yawPitchRotMat;&#xD;&#xA;            /* We want to do yaw * pitch. */&#xD;&#xA;&#xD;&#xA;            //y-axis as yaw axis&#xD;&#xA;            yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(yaw), &#xD;&#xA;                             glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;            &#xD;&#xA;            //x-axis as pitch axis&#xD;&#xA;            yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(pitch), &#xD;&#xA;                             glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;            cameraFrontDirection = glm::normalize(-1.0f * &#xD;&#xA;                     glm::vec3(yawPitchRotMat[2].x, yawPitchRotMat[2].y, yawPitchRotMat[2].z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The above code seems to work. However, I would like to hear your opinion about this approach.&#xD;&#xA;&#xD;&#xA;**Note:** &#xD;&#xA;&#xD;&#xA; 1. My math is not really very strong, so any mathematical insight would be very helpful.&#xD;&#xA; 2. Though later I also came to know about certain limitation of modelling rotation using Euler angles and use quaternions instead. However I would like to save that topic for future discussion, as I am yet to read about that in details.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/discussion_boards/showthread.php/133072-Camera-Position-Camera-Angle-Camera-Target-Position?p=986100&amp;viewfull=1#post986100" ContentLicense="CC BY-SA 3.0" />
  <row Id="5370" PostHistoryTypeId="1" PostId="2300" RevisionGUID="1cf22585-01a8-4208-af53-4b3d48804075" CreationDate="2016-04-10T17:26:45.990" UserId="3098" Text="Computing camera front direction from Euler angles" ContentLicense="CC BY-SA 3.0" />
  <row Id="5371" PostHistoryTypeId="3" PostId="2300" RevisionGUID="1cf22585-01a8-4208-af53-4b3d48804075" CreationDate="2016-04-10T17:26:45.990" UserId="3098" Text="|opengl|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5372" PostHistoryTypeId="5" PostId="2300" RevisionGUID="9c0b0c0b-1ab3-4b44-88a0-8aeb5406e994" CreationDate="2016-04-10T20:37:38.120" UserId="3098" Comment="Rephrased question." Text="I am new to OpenGL and Computer Graphics in general. &#xD;&#xA;&#xD;&#xA;Lately I was learning how to model a camera, specifically how to model the rotation of camera. I was introduced to Euler angles for this purpose. &#xD;&#xA;&#xD;&#xA;I got a rough idea about how to use Euler angles to model camera rotation from this [post][1]. Based on that, I wrote something like below:&#xD;&#xA;&#xD;&#xA;    GLfloat yaw, pitch;&#xD;&#xA;    ...&#xD;&#xA;    void mouse_callback(GLFWwindow* window, double xpos, double ypos)&#xD;&#xA;    {&#xD;&#xA;            /* &#xD;&#xA;               Here I am updating the yaw, and pitch values &#xD;&#xA;               based on mouse movement and previous mouse position&#xD;&#xA;            */&#xD;&#xA;&#xD;&#xA;            glm::mat4 yawPitchRotMat;&#xD;&#xA;            /* We want to do yaw * pitch. */&#xD;&#xA;&#xD;&#xA;            //y-axis as yaw axis&#xD;&#xA;            yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(yaw), &#xD;&#xA;                             glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;            &#xD;&#xA;            //x-axis as pitch axis&#xD;&#xA;            yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(pitch), &#xD;&#xA;                             glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;            cameraFrontDirection = glm::normalize(-1.0f * &#xD;&#xA;                     glm::vec3(yawPitchRotMat[2].x, yawPitchRotMat[2].y, yawPitchRotMat[2].z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The above code seems to work. However, I would like to hear your opinion about this approach. Specially as my math is not really very strong, so any mathematical insight regarding Euler angles would be very helpful. Also appreciate any reference to online resource on the same, that is easy to understand.&#xD;&#xA;&#xD;&#xA;**Note:** Though later I also came to know about certain limitation of modelling rotation using Euler angles and use quaternions instead. However I would like to save that topic for future discussion, as I am yet to read about that in details.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/discussion_boards/showthread.php/133072-Camera-Position-Camera-Angle-Camera-Target-Position?p=986100&amp;viewfull=1#post986100" ContentLicense="CC BY-SA 3.0" />
  <row Id="5373" PostHistoryTypeId="5" PostId="2291" RevisionGUID="1cb68c11-3551-46f6-98c1-1b4a9b0e0cf7" CreationDate="2016-04-10T22:48:51.737" UserId="231" Comment="Add additional method of testing if scene cannot be altered" Text="## The problem appears to be unintentionally transparent surfaces&#xD;&#xA;&#xD;&#xA;Although the image is grainy, it is sufficiently clear to estimate that all of the darker regions are due to surfaces facing away from the light, rather than due to shadows cast onto surfaces facing towards the light. So it does seem that there is a problem, and the lack of shadows is not just due to having soft shadows from a large area light that don't show up well, or excessively reflective surfaces that provide too much ambient light. Somehow light is getting through your surfaces.&#xD;&#xA;&#xD;&#xA;## The probable source of this problem&#xD;&#xA;Since you check for intersection with the light and the objects separately, the crucial point where this could go wrong is where you check&#xD;&#xA;&#xD;&#xA;    if (distFromLight &lt; distFromObj)&#xD;&#xA;&#xD;&#xA;You correctly terminate the path and return the light colour if this check is true (that is, if the light is closer than the nearest object in that direction). So the problem is likely to be with one of the two variables you are comparing. If they were both correct, then you would see shadows.&#xD;&#xA;&#xD;&#xA;These are calculated on the preceding lines&#xD;&#xA;&#xD;&#xA;    float distFromObj = length(vert.p);&#xD;&#xA;    float distFromLight = length(hitLightPoint);&#xD;&#xA;&#xD;&#xA;As pointed out in [Julien Guertault's answer], these calculations may be redundant.&#xD;&#xA;&#xD;&#xA;`length(vert.p)` should still be available as `t`, used 11 lines previously in the calculation of `vert.p`. This not only avoids unnecessary calculation, but eliminates a potential source of error. Then this length is likely to be correct unless there is a problem with `checkIfRayIntersectSomething()`.&#xD;&#xA;&#xD;&#xA;This leaves only `length(hitLightPoint)` as a source of error, unless there is a more subtle problem. It would be useful to be able to eliminate the possibility of problems with `length()` or `hitLightPoint`, which is calculated by `checkRayLightIntersection()`.&#xD;&#xA;&#xD;&#xA;## We need to see the code to be able to help&#xD;&#xA;&#xD;&#xA;`length()`, `checkIfRayIntersectSomething()` and `checkRayLightIntersection()` are not currently included with the code in your question, so we can't analyse these. If you are able to share these that would help narrow down the source of the problem.&#xD;&#xA;&#xD;&#xA;## A simple way to check whether this is the real problem&#xD;&#xA;&#xD;&#xA;You could also verify whether this analysis of the problem is correct by rendering a scene which will eliminate the other possibilities (shadows too soft to distinguish, or shadows washed out by too much reflected light from the rest of the scene). If the light getting through the surfaces is the source of your problem, then it will apply even if there is no path from the light to a surface, provided that surface is facing the light. So render a simple scene that has a light with a plane beneath it, and another plane beneath that, separated by a gap big enough to easily be seen. The lower plane is completely occluded by the upper plane, so should receive no light (no soft shadows and no reflected light from elsewhere). If the lower plane is lit, then you know that this is indeed the problem and you can focus your efforts here.&#xD;&#xA;&#xD;&#xA;If the lower plane is *not* lit, then either this is not the problem, or there is a problem with the scale and the occluding plane may need to be at a different distance from the light in order for the problem to show up. You can use your existing scene as a source of estimated distances for which this problem occurs, and you can use inclined planes in order to see the effect for a variety of ratios of object distance to light distance within a single image.&#xD;&#xA;&#xD;&#xA;Sharing the images resulting from such simple scenes may help us identify the problem more precisely.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I notice that in a comment on the question you mention that you do not have a straightforward way of generating scenes yourself. Perhaps there are much simpler scenes already publicly available in the same file format, that you can use to test this?&#xD;&#xA;&#xD;&#xA;If not, it sounds like the only thing you have control over is the light. In that case, you could try putting the light underground. If surfaces are not transparent, the scene should be uniformly black. If surfaces are being lit despite an occluding surface, you may see evidence for it this way that would be hard to discern when there is lots of secondary light bouncing around.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Julien Guertault's answer]: http://computergraphics.stackexchange.com/a/2281/231" ContentLicense="CC BY-SA 3.0" />
  <row Id="5374" PostHistoryTypeId="2" PostId="2301" RevisionGUID="0540c301-5561-4999-a691-489df63905a5" CreationDate="2016-04-10T22:53:17.550" UserId="3101" Text="Hello everybody i have a trouble making datatransmition with mine program just to give the idea im trying to move this blocks when i move mine cars&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hiOLG.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here I leave the encoding of mine server/client program &#xD;&#xA;&#xD;&#xA;    package com.mygdx.Xrace;&#xD;&#xA;&#xD;&#xA;import java.io.BufferedReader;&#xD;&#xA;&#xD;&#xA;import java.io.IOException;&#xD;&#xA;&#xD;&#xA;import java.io.InputStreamReader;&#xD;&#xA;&#xD;&#xA;import java.io.PrintWriter;&#xD;&#xA;&#xD;&#xA;import java.net.ServerSocket;&#xD;&#xA;&#xD;&#xA;import java.net.Socket;&#xD;&#xA;&#xD;&#xA;public class ScreenServidor extends Pantallabase{&#xD;&#xA;&#xD;&#xA;		ScreenCarrera carrera;&#xD;&#xA;		MyTextInputListener listener;&#xD;&#xA;		ServerSocket server ;&#xD;&#xA;		float delta = 0.01f;&#xD;&#xA;		int puerto=9600;&#xD;&#xA;		public ScreenServidor(Main game) {&#xD;&#xA;			super(game);&#xD;&#xA;		}&#xD;&#xA;		@Override		&#xD;&#xA;		public void show()&#xD;&#xA;		{&#xD;&#xA;			carrera=new ScreenCarrera(game);&#xD;&#xA;			carrera.show();&#xD;&#xA;			&#xD;&#xA;			try {&#xD;&#xA;				server = new ServerSocket(puerto);&#xD;&#xA;				new User(server.accept()).start();&#xD;&#xA;			} catch (IOException e) {&#xD;&#xA;				 System.out.println(e);&#xD;&#xA;				}finally{&#xD;&#xA;						try {&#xD;&#xA;							server.close();&#xD;&#xA;						} catch (IOException e) {&#xD;&#xA;							 System.out.println(e);&#xD;&#xA;						}&#xD;&#xA;				}&#xD;&#xA;	         &#xD;&#xA;		}	&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;		@Override&#xD;&#xA;		public void render(float delta)&#xD;&#xA;		{&#xD;&#xA;			carrera.render(delta);&#xD;&#xA;		}&#xD;&#xA;		@Override&#xD;&#xA;		public void dispose(){&#xD;&#xA;			carrera.dispose();&#xD;&#xA;			}&#xD;&#xA;		@Override&#xD;&#xA;		public void resize(int width, int height) {}&#xD;&#xA;		@Override&#xD;&#xA;		public void pause() {}&#xD;&#xA;		@Override&#xD;&#xA;		public void resume() {}&#xD;&#xA;		@Override&#xD;&#xA;		public void hide() {&#xD;&#xA;		}&#xD;&#xA;}&#xD;&#xA;class User extends Thread{&#xD;&#xA;&#xD;&#xA;	BufferedReader in;&#xD;&#xA;	PrintWriter out;&#xD;&#xA;	Socket conexion;&#xD;&#xA;	ScreenCarrera carrera;&#xD;&#xA;	public User(Socket serv)&#xD;&#xA;	{&#xD;&#xA;		this.conexion=serv;&#xD;&#xA;	}&#xD;&#xA;	public void run() {&#xD;&#xA;		&#xD;&#xA;		try {&#xD;&#xA;&#xD;&#xA;			in = new BufferedReader(new InputStreamReader(conexion.getInputStream())); &#xD;&#xA;			out=new PrintWriter(conexion.getOutputStream(),true);&#xD;&#xA;			**carrera.m.posx2=in.read();** //receiving data&#xD;&#xA;			**out.print(carrera.m.posx1);**//sending data&#xD;&#xA;			} catch (IOException e) {&#xD;&#xA;				 System.out.println(e);&#xD;&#xA;		}finally{&#xD;&#xA;			try {&#xD;&#xA;			in.close();&#xD;&#xA;			out.close();&#xD;&#xA;			conexion.close();&#xD;&#xA;			} catch (IOException e) {}&#xD;&#xA;	}&#xD;&#xA;		&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;package com.mygdx.Xrace;&#xD;&#xA;&#xD;&#xA;import java.net.*;&#xD;&#xA;&#xD;&#xA;import java.io.*;&#xD;&#xA;&#xD;&#xA;import com.badlogic.gdx.Gdx;&#xD;&#xA;&#xD;&#xA;public class ScreenCliente extends Pantallabase{&#xD;&#xA;&#xD;&#xA;	Socket conexion;&#xD;&#xA;	ScreenCarrera carrera;&#xD;&#xA;	PrintStream out ;&#xD;&#xA;	MyTextInputListener listener;&#xD;&#xA;	BufferedReader in;&#xD;&#xA;	float delta = 0.01f;&#xD;&#xA;	int puerto=9600;&#xD;&#xA;&#xD;&#xA;	static String ip;&#xD;&#xA;	&#xD;&#xA;	public ScreenCliente(Main game) {&#xD;&#xA;		super(game);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	@Override&#xD;&#xA;	public void show() {&#xD;&#xA;		carrera=new ScreenCarrera(game);&#xD;&#xA;		carrera.show();&#xD;&#xA;		conexion=new Socket();&#xD;&#xA;		listener = new MyTextInputListener();&#xD;&#xA;		Gdx.input.getTextInput(listener, &quot;ingrese ip&quot;, ip, ip);&#xD;&#xA;		try {&#xD;&#xA;			&#xD;&#xA;			conexion =new Socket(ip,puerto);&#xD;&#xA;			out = new PrintStream(conexion.getOutputStream(),true);&#xD;&#xA;			in = new BufferedReader(new InputStreamReader(conexion.getInputStream()));&#xD;&#xA;			&#xD;&#xA;		}catch(Exception e){e.printStackTrace();}&#xD;&#xA;	}&#xD;&#xA;	@Override&#xD;&#xA;	public void render(float delta) {&#xD;&#xA;		carrera.render(delta);&#xD;&#xA;		try{&#xD;&#xA;		**carrera.m.posx2=in.read()**;&#xD;&#xA;		} catch (IOException e) {&#xD;&#xA;			e.printStackTrace();&#xD;&#xA;			game.m.mensaje=&quot;error de conexion&quot;;&#xD;&#xA;			game.setScreen(game.m);&#xD;&#xA;		}try {&#xD;&#xA;			run();&#xD;&#xA;		} catch (IOException e) {&#xD;&#xA;			e.printStackTrace();&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;	}&#xD;&#xA;	private void run() throws IOException{&#xD;&#xA;		&#xD;&#xA;		 **out.print(carrera.m.posx1);**&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	@Override&#xD;&#xA;	public void resize(int width, int height) {&#xD;&#xA;	}&#xD;&#xA;	@Override&#xD;&#xA;	public void pause() {&#xD;&#xA;	}&#xD;&#xA;	@Override&#xD;&#xA;	public void resume() {&#xD;&#xA;	}&#xD;&#xA;	@Override&#xD;&#xA;	public void hide() {&#xD;&#xA;	}&#xD;&#xA;	@Override&#xD;&#xA;	public void dispose() {&#xD;&#xA;		carrera.dispose();&#xD;&#xA;		try {&#xD;&#xA;			in.close();&#xD;&#xA;			out.close();&#xD;&#xA;			conexion.close();&#xD;&#xA;	} catch (IOException e) {&#xD;&#xA;		e.printStackTrace();&#xD;&#xA;	}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5375" PostHistoryTypeId="1" PostId="2301" RevisionGUID="0540c301-5561-4999-a691-489df63905a5" CreationDate="2016-04-10T22:53:17.550" UserId="3101" Text="Trouble using java connectivity and data transmition on libgdx" ContentLicense="CC BY-SA 3.0" />
  <row Id="5376" PostHistoryTypeId="3" PostId="2301" RevisionGUID="0540c301-5561-4999-a691-489df63905a5" CreationDate="2016-04-10T22:53:17.550" UserId="3101" Text="|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5377" PostHistoryTypeId="5" PostId="2281" RevisionGUID="5c707ff3-7fb4-40a5-9899-055f28b81428" CreationDate="2016-04-11T01:58:24.743" UserId="182" Comment="added 89 characters in body" Text="&gt; is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;I don't see any problem with having a big area light. That said, it also depends on the scale of your scene. If the light is large compared to it, shadows will tend to be more diffuse, like under an overcast sky.&#xD;&#xA;&#xD;&#xA;&gt; shadows are missing.. [...] Can you help me understanding why?&#xD;&#xA;&#xD;&#xA;I haven't found any blatant mistake, but there are two elements that look suspicious to me.&#xD;&#xA;&#xD;&#xA;    if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)) {&#xD;&#xA;        // ...&#xD;&#xA;        return true; //light hit, path completed&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Although this part seems to be correct as far as I can tell, I would try to make sure there is no bug introducing a bias. For every bounce, it checks if there is a ray hitting the light first, and if so it breaks out of the loop: in case the code is incorrect and it happens to hit the light more often than it should, the shadows will disappear.&#xD;&#xA;&#xD;&#xA;Moreover, in the first if:&#xD;&#xA;&#xD;&#xA;    return false; //nothing hit, path non valid&#xD;&#xA;&#xD;&#xA;and the related loop:&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;    {     &#xD;&#xA;      Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Make sure you still take the paths that hit nothing into account when averaging the color of the pixel, otherwise this will also introduce a bias.&#xD;&#xA;&#xD;&#xA;As joojaa said in the comment, you should try using a simpler scene: a few spheres or cubes, no texture. You can also reduce the number of bounces to one or two to see only direct lighting. If necessary, maybe even use a constant sky dome first instead of a light area.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Other remarks:&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Do you need to store x and y?&#xD;&#xA;&#xD;&#xA;	float distFromObj = length(vert.p);&#xD;&#xA;	float distFromLight = length(hitLightPoint);&#xD;&#xA;&#xD;&#xA;Don't you already have two `t` that you can compare?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5379" PostHistoryTypeId="5" PostId="2301" RevisionGUID="26c7b1c2-12c5-484b-8b46-559fedf876b4" CreationDate="2016-04-11T07:01:07.523" UserId="16" Comment="added 716 characters in body" Text="Hello everybody i have a trouble making datatransmition with mine program just to give the idea im trying to move this blocks when i move mine cars&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hiOLG.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here I leave the encoding of mine server/client program &#xD;&#xA;&#xD;&#xA;    package com.mygdx.Xrace;&#xD;&#xA;&#xD;&#xA;    import java.io.BufferedReader;&#xD;&#xA;    &#xD;&#xA;    import java.io.IOException;&#xD;&#xA;    &#xD;&#xA;    import java.io.InputStreamReader;&#xD;&#xA;    &#xD;&#xA;    import java.io.PrintWriter;&#xD;&#xA;    &#xD;&#xA;    import java.net.ServerSocket;&#xD;&#xA;    &#xD;&#xA;    import java.net.Socket;&#xD;&#xA;    &#xD;&#xA;    public class ScreenServidor extends Pantallabase{&#xD;&#xA;    &#xD;&#xA;    		ScreenCarrera carrera;&#xD;&#xA;    		MyTextInputListener listener;&#xD;&#xA;    		ServerSocket server ;&#xD;&#xA;    		float delta = 0.01f;&#xD;&#xA;    		int puerto=9600;&#xD;&#xA;    		public ScreenServidor(Main game) {&#xD;&#xA;    			super(game);&#xD;&#xA;    		}&#xD;&#xA;    		@Override		&#xD;&#xA;    		public void show()&#xD;&#xA;    		{&#xD;&#xA;    			carrera=new ScreenCarrera(game);&#xD;&#xA;    			carrera.show();&#xD;&#xA;    			&#xD;&#xA;    			try {&#xD;&#xA;    				server = new ServerSocket(puerto);&#xD;&#xA;    				new User(server.accept()).start();&#xD;&#xA;    			} catch (IOException e) {&#xD;&#xA;    				 System.out.println(e);&#xD;&#xA;    				}finally{&#xD;&#xA;    						try {&#xD;&#xA;    							server.close();&#xD;&#xA;    						} catch (IOException e) {&#xD;&#xA;    							 System.out.println(e);&#xD;&#xA;    						}&#xD;&#xA;    				}&#xD;&#xA;    	         &#xD;&#xA;    		}	&#xD;&#xA;    		&#xD;&#xA;    		&#xD;&#xA;    		@Override&#xD;&#xA;    		public void render(float delta)&#xD;&#xA;    		{&#xD;&#xA;    			carrera.render(delta);&#xD;&#xA;    		}&#xD;&#xA;    		@Override&#xD;&#xA;    		public void dispose(){&#xD;&#xA;    			carrera.dispose();&#xD;&#xA;    			}&#xD;&#xA;    		@Override&#xD;&#xA;    		public void resize(int width, int height) {}&#xD;&#xA;    		@Override&#xD;&#xA;    		public void pause() {}&#xD;&#xA;    		@Override&#xD;&#xA;    		public void resume() {}&#xD;&#xA;    		@Override&#xD;&#xA;    		public void hide() {&#xD;&#xA;    		}&#xD;&#xA;    }&#xD;&#xA;    class User extends Thread{&#xD;&#xA;    &#xD;&#xA;    	BufferedReader in;&#xD;&#xA;    	PrintWriter out;&#xD;&#xA;    	Socket conexion;&#xD;&#xA;    	ScreenCarrera carrera;&#xD;&#xA;    	public User(Socket serv)&#xD;&#xA;    	{&#xD;&#xA;    		this.conexion=serv;&#xD;&#xA;    	}&#xD;&#xA;    	public void run() {&#xD;&#xA;    		&#xD;&#xA;    		try {&#xD;&#xA;    &#xD;&#xA;    			in = new BufferedReader(new InputStreamReader(conexion.getInputStream())); &#xD;&#xA;    			out=new PrintWriter(conexion.getOutputStream(),true);&#xD;&#xA;    			**carrera.m.posx2=in.read();** //receiving data&#xD;&#xA;    			**out.print(carrera.m.posx1);**//sending data&#xD;&#xA;    			} catch (IOException e) {&#xD;&#xA;    				 System.out.println(e);&#xD;&#xA;    		}finally{&#xD;&#xA;    			try {&#xD;&#xA;    			in.close();&#xD;&#xA;    			out.close();&#xD;&#xA;    			conexion.close();&#xD;&#xA;    			} catch (IOException e) {}&#xD;&#xA;    	}&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    package com.mygdx.Xrace;&#xD;&#xA;    &#xD;&#xA;    import java.net.*;&#xD;&#xA;    &#xD;&#xA;    import java.io.*;&#xD;&#xA;    &#xD;&#xA;    import com.badlogic.gdx.Gdx;&#xD;&#xA;    &#xD;&#xA;    public class ScreenCliente extends Pantallabase{&#xD;&#xA;    &#xD;&#xA;    	Socket conexion;&#xD;&#xA;    	ScreenCarrera carrera;&#xD;&#xA;    	PrintStream out ;&#xD;&#xA;    	MyTextInputListener listener;&#xD;&#xA;    	BufferedReader in;&#xD;&#xA;    	float delta = 0.01f;&#xD;&#xA;    	int puerto=9600;&#xD;&#xA;    &#xD;&#xA;    	static String ip;&#xD;&#xA;    	&#xD;&#xA;    	public ScreenCliente(Main game) {&#xD;&#xA;    		super(game);&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	@Override&#xD;&#xA;    	public void show() {&#xD;&#xA;    		carrera=new ScreenCarrera(game);&#xD;&#xA;    		carrera.show();&#xD;&#xA;    		conexion=new Socket();&#xD;&#xA;    		listener = new MyTextInputListener();&#xD;&#xA;    		Gdx.input.getTextInput(listener, &quot;ingrese ip&quot;, ip, ip);&#xD;&#xA;    		try {&#xD;&#xA;    			&#xD;&#xA;    			conexion =new Socket(ip,puerto);&#xD;&#xA;    			out = new PrintStream(conexion.getOutputStream(),true);&#xD;&#xA;    			in = new BufferedReader(new InputStreamReader(conexion.getInputStream()));&#xD;&#xA;    			&#xD;&#xA;    		}catch(Exception e){e.printStackTrace();}&#xD;&#xA;    	}&#xD;&#xA;    	@Override&#xD;&#xA;    	public void render(float delta) {&#xD;&#xA;    		carrera.render(delta);&#xD;&#xA;    		try{&#xD;&#xA;    		**carrera.m.posx2=in.read()**;&#xD;&#xA;    		} catch (IOException e) {&#xD;&#xA;    			e.printStackTrace();&#xD;&#xA;    			game.m.mensaje=&quot;error de conexion&quot;;&#xD;&#xA;    			game.setScreen(game.m);&#xD;&#xA;    		}try {&#xD;&#xA;    			run();&#xD;&#xA;    		} catch (IOException e) {&#xD;&#xA;    			e.printStackTrace();&#xD;&#xA;    		}&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;    	private void run() throws IOException{&#xD;&#xA;    		&#xD;&#xA;    		 **out.print(carrera.m.posx1);**&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	@Override&#xD;&#xA;    	public void resize(int width, int height) {&#xD;&#xA;    	}&#xD;&#xA;    	@Override&#xD;&#xA;    	public void pause() {&#xD;&#xA;    	}&#xD;&#xA;    	@Override&#xD;&#xA;    	public void resume() {&#xD;&#xA;    	}&#xD;&#xA;    	@Override&#xD;&#xA;    	public void hide() {&#xD;&#xA;    	}&#xD;&#xA;    	@Override&#xD;&#xA;    	public void dispose() {&#xD;&#xA;    		carrera.dispose();&#xD;&#xA;    		try {&#xD;&#xA;    			in.close();&#xD;&#xA;    			out.close();&#xD;&#xA;    			conexion.close();&#xD;&#xA;    	} catch (IOException e) {&#xD;&#xA;    		e.printStackTrace();&#xD;&#xA;    	}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5380" PostHistoryTypeId="5" PostId="2279" RevisionGUID="e93551e8-7db5-4d7e-9a22-f8ebaeaa81bb" CreationDate="2016-04-11T14:37:36.023" UserId="3069" Comment="added 309 characters in body" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;EDIT: this is my target reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT 2: this is what happens in case the **depth &gt; 1** check is omitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;EDIT 3: after fixing the **distFromLight** and **distFromObj** I got the following results:&#xD;&#xA;&#xD;&#xA;[![some clue of shadows][4]][4]&#xD;&#xA;&#xD;&#xA;One of the 2 problems as suggested by @trichoplax could be too soft shadows. So I tried to lower the size of the light, increasing his power to compensate. Results are not good and shown here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Moreover as requested I can post some more code:&#xD;&#xA;&#xD;&#xA;    bool checkRayLightIntersection(Vec O, Vec D, Vec &amp; hitLightPoint){&#xD;&#xA;      //getting the 4 corners of my light&#xD;&#xA;	  Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;	  Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;&#xD;&#xA;	  //the majority of the methods first find out where the ray intersects the plane that the rectangle lies on Ax + By + Cz + D = 0&#xD;&#xA;	  //in our case the equation of that plane is easy -&gt; D = 20&#xD;&#xA;	  // answers.google.com/answers/threadview?id=18979&#xD;&#xA;&#xD;&#xA;	  float t = -(-O.y + lightPos.y) / (-D.y);&#xD;&#xA;	  if (t &gt; 0){&#xD;&#xA;		Vec hitPoint = O + D * t;&#xD;&#xA;		Vec V1 = (P2 - P1).norm();&#xD;&#xA;		Vec V2 = (P3 - P2).norm();&#xD;&#xA;		Vec V3 = (P4 - P3).norm();&#xD;&#xA;		Vec V4 = (P1 - P4).norm();&#xD;&#xA;		Vec V5 = (hitPoint - P1).norm();&#xD;&#xA;		Vec V6 = (hitPoint - P2).norm();&#xD;&#xA;		Vec V7 = (hitPoint - P3).norm();&#xD;&#xA;		Vec V8 = (hitPoint - P4).norm();&#xD;&#xA;&#xD;&#xA;		if (V1.dot(V5) &gt; 0.0 &amp;&amp; V2.dot(V6) &gt; 0.0 &amp;&amp; V3.dot(V7) &gt; 0.0 &amp;&amp; V4.dot(V8) &gt; 0.0){&#xD;&#xA;			hitLightPoint = hitPoint;&#xD;&#xA;			return true;&#xD;&#xA;		}&#xD;&#xA;      }&#xD;&#xA;      return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Instead, the **checkIfRayIntersectSomething** method is part of the framework itself (it has just another name), it's not done by me but it's tested and working.&#xD;&#xA;&#xD;&#xA;EDIT 4: tried to render a small part of the scene with high number of spp. Tried 512 spp for the bottom right corner where should appear shadows according to the target image. Results show that shadows are not there:&#xD;&#xA;&#xD;&#xA;[![Bottom right corner at 512spp][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/QHG2z.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hiqEY.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/JvGhf.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/8aYPH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/ohZJu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5381" PostHistoryTypeId="5" PostId="2279" RevisionGUID="1df3adfb-19a4-4dcb-a7a0-015168eb55a8" CreationDate="2016-04-11T20:00:07.877" UserId="3069" Comment="added 2057 characters in body" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;EDIT: this is my target reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT 2: this is what happens in case the **depth &gt; 1** check is omitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;EDIT 3: after fixing the **distFromLight** and **distFromObj** I got the following results:&#xD;&#xA;&#xD;&#xA;[![some clue of shadows][4]][4]&#xD;&#xA;&#xD;&#xA;One of the 2 problems as suggested by @trichoplax could be too soft shadows. So I tried to lower the size of the light, increasing his power to compensate. Results are not good and shown here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Moreover as requested I can post some more code:&#xD;&#xA;&#xD;&#xA;    bool checkRayLightIntersection(Vec O, Vec D, Vec &amp; hitLightPoint){&#xD;&#xA;      //getting the 4 corners of my light&#xD;&#xA;	  Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;	  Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;&#xD;&#xA;	  //the majority of the methods first find out where the ray intersects the plane that the rectangle lies on Ax + By + Cz + D = 0&#xD;&#xA;	  //in our case the equation of that plane is easy -&gt; D = 20&#xD;&#xA;	  // answers.google.com/answers/threadview?id=18979&#xD;&#xA;&#xD;&#xA;	  float t = -(-O.y + lightPos.y) / (-D.y);&#xD;&#xA;	  if (t &gt; 0){&#xD;&#xA;		Vec hitPoint = O + D * t;&#xD;&#xA;		Vec V1 = (P2 - P1).norm();&#xD;&#xA;		Vec V2 = (P3 - P2).norm();&#xD;&#xA;		Vec V3 = (P4 - P3).norm();&#xD;&#xA;		Vec V4 = (P1 - P4).norm();&#xD;&#xA;		Vec V5 = (hitPoint - P1).norm();&#xD;&#xA;		Vec V6 = (hitPoint - P2).norm();&#xD;&#xA;		Vec V7 = (hitPoint - P3).norm();&#xD;&#xA;		Vec V8 = (hitPoint - P4).norm();&#xD;&#xA;&#xD;&#xA;		if (V1.dot(V5) &gt; 0.0 &amp;&amp; V2.dot(V6) &gt; 0.0 &amp;&amp; V3.dot(V7) &gt; 0.0 &amp;&amp; V4.dot(V8) &gt; 0.0){&#xD;&#xA;			hitLightPoint = hitPoint;&#xD;&#xA;			return true;&#xD;&#xA;		}&#xD;&#xA;      }&#xD;&#xA;      return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Instead, the **checkIfRayIntersectSomething** method is part of the framework itself (it has just another name), it's not done by me but it's tested and working.&#xD;&#xA;&#xD;&#xA;EDIT 4: tried to render a small part of the scene with high number of spp. Tried 512 spp for the bottom right corner where should appear shadows according to the target image. Results show that shadows are not there:&#xD;&#xA;&#xD;&#xA;[![Bottom right corner at 512spp][6]][6]&#xD;&#xA;&#xD;&#xA;EDIT 5:&#xD;&#xA;&#xD;&#xA;I hereby post the code used to render the target image, it does at the same time my **Sampling()** and **GeneratePath()** methods using a recursive structure.&#xD;&#xA;&#xD;&#xA;    Vec Sample(vec3 O, vec3 D, int depth)&#xD;&#xA;    {&#xD;&#xA;	  vec3 color(0, 0, 0);&#xD;&#xA;      float t;&#xD;&#xA;	  if (checkIfIntersectSomething(D, t))&#xD;&#xA;	  {&#xD;&#xA;				&#xD;&#xA;		vec3 I = O + t * D; //get to the intersection point on the object&#xD;&#xA;		vec3 diffuse = getMaterial(I);&#xD;&#xA;&#xD;&#xA;		vec3 L = vec3(-1 + Rand(2.0f), 20, 9 + Rand(2.0f)) - I; //(-1,20,9) is Hard-code of the light position, and I add Rand(2.0f) on X and Z axis&#xD;&#xA;		//so that I have an area light instead of a point light&#xD;&#xA;		L = normalize(L);&#xD;&#xA;		float ndotl = dot(I.getNormal(), L); //the closer the dotProdutc is to 1.0, the more the light and surface face each other&#xD;&#xA;		if (ndotl &gt; 0)&#xD;&#xA;		{&#xD;&#xA;			if (!checkRayLightIntersection(L)) {&#xD;&#xA;				float dist = distFromLight(I);&#xD;&#xA;				color += diffuse * ndotl * vec3(1000.0f, 1000.0f, 850.0f) * (1.0f / (dist * dist));&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		// russian roulette&#xD;&#xA;		float Psurvival = CLAMP((diffuse.r + diffuse.g + diffuse.b) * 0.33333f, 0.2f, 0.8f);&#xD;&#xA;&#xD;&#xA;		// continue random walk &#xD;&#xA;		float rand = Rand(1.0f);&#xD;&#xA;		if (depth &lt; 10 &amp;&amp; rand &lt; Psurvival)&#xD;&#xA;		{&#xD;&#xA;			//Besides russian roulette, I also do another weight, because rays that go towards the horizon will bring back very little energy&#xD;&#xA;			//so I make a random distribution that favours those rays who are close to the normal of the hit point, this is DiffuseReflectionCosineWeighted(). It creates a Random bounce but proportional to N dot R&#xD;&#xA;			vec3 R = DiffuseReflectionCosineWeighted(I.getNormal());//there is a weight&#xD;&#xA;&#xD;&#xA;			float prob = 1.0;&#xD;&#xA;			float cosTheta = fabs(dot(I.getNormal(), R));&#xD;&#xA;			if (cosTheta &gt; 1e-6) prob = cosTheta / M_PI;&#xD;&#xA;&#xD;&#xA;			color += diffuse * Sample(I + R * EPSILON, R, depth + 1) * (1.0f / Psurvival); //the cosTheta() of the attenuation of the rendering equation gets simplified with the cosTheta of the &quot;prob&quot;&#xD;&#xA;			//the PI of the prob gets simplified with the BRDF where we are using the ideal BRDF = diffuse/PI&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;	return color;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/QHG2z.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hiqEY.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/JvGhf.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/8aYPH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/ohZJu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5382" PostHistoryTypeId="5" PostId="2289" RevisionGUID="a598287a-5054-4cbe-ba42-10bff9425148" CreationDate="2016-04-11T20:25:29.450" UserId="3075" Comment="Consistently use BRDF over BSDF" Text="Using two Fresnel terms is correct in the sense that any given diffuse path will pass through the surface twice. If you're solving diffusion by tracing a path through the medium until it bounces out again then that you will get two (or more) Fresnel terms for that path as it interacts with the surface.&#xD;&#xA;&#xD;&#xA;However, that's not what you're doing with a diffuse BRDF. A diffuse BRDF is intended to represent the average of all those possible diffusion paths. In the case of an Lambertian that average is modeled as uniform reflection and a single albedo value measuring the internal energy loss during diffusion, but more complicated models are possible. Crucially: a diffuse BRDF will already include the aggregate effect of some paths being reflected back into the medium to diffuse further and some passing out immediately. $1 - F_{out}$ is already &quot;baked in&quot; to the BRDF¹ and you do not need factor it in again.&#xD;&#xA;&#xD;&#xA;What the Lambertian term does not include is the portion of energy that is lost by being reflected before light enters the medium of diffusion. This is view-dependent, but depends on the precise glossy lobe above it. There is no energy loss at a (non-metallic) surface interface so everything that isn't reflected will be refracted, meaning that what you actually want is to integrate the total energy loss at the surface over all outgoing directions, i.e. $1 - \int \texttt{glossy_bsdf}(\texttt{in}, \texttt{out}) \: \mathrm{d} \texttt{out}$.&#xD;&#xA;&#xD;&#xA;It's possible to pre-compute approximations to that integral for specific BRDFs. The end result will in general depend on view direction, material roughness and IOR at least. As a first approximation you can assume that the glossy lobe is a perfectly specular reflector. That gives a weighting of $1 - \int \texttt{glossy} \: \mathrm{d}\texttt{out} = 1 - F_{in}$, which is exactly what you first suggested.&#xD;&#xA;&#xD;&#xA;Additionally, note that the Lambertian BRDF is the albedo divided by $\pi$ and that the cosine term is a measure of how attenuated the incoming light is on the surface; it applies to both glossy and diffuse reflectance.&#xD;&#xA;&#xD;&#xA;So, roughly:&#xD;&#xA;&#xD;&#xA;    // Assuming for example:&#xD;&#xA;    //   diffuse = albedo / PI;&#xD;&#xA;    //   specular = my_favorite_glossy_brdf(in_dir, out_dir, roughness);&#xD;&#xA;    //   fresnel = f0 + (1.0 - f0) * pow(1.0 - dot(E, H), 5.0);&#xD;&#xA;    //   total_surface_reflection = fresnel&#xD;&#xA;    color = lightIntensity * dot(L, N) * Lerp(diffuse, specular, total_surface_reflection);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;¹ *Really the integral of $F$ over all possible incident internal diffusion exit paths that result in your out direction, but I digress.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="5383" PostHistoryTypeId="5" PostId="2130" RevisionGUID="e9afaabb-7c2b-4f76-89cd-c229c62624ff" CreationDate="2016-04-11T22:29:32.500" UserId="310" Comment="Fixed grammar" Text="In ray tracing / path tracing, one of the simplest way to anti-alias the image is to supersample the pixel values and average the results. IE. instead of shooting every sample through the center of the pixel, you offset the samples by some amount.&#xD;&#xA;&#xD;&#xA;In searching around the internet, I've found two somewhat different methods to do this:&#xD;&#xA;&#xD;&#xA;1. Generate samples however you want and weigh the result with a filter&#xD;&#xA;  - One example is [PBRT][1]&#xD;&#xA;2. Generate the samples with a distribution equal to a the shape of a filter&#xD;&#xA;  - Two examples are [smallpt][2] and [Benedikt Bitterli][3]'s [Tungsten Renderer][4] &#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate and Weigh**&#xD;&#xA;&#xD;&#xA;The basic process is:&#xD;&#xA;&#xD;&#xA;  1. Create samples however you want (randomly, stratified, low-discrepancy sequences, etc.) &#xD;&#xA;  2. Offset the camera ray using two samples (x and y)&#xD;&#xA;  3. Render the scene with the ray&#xD;&#xA;  4. Calculate a weight using a filter function and the distance of the sample in reference to the pixel center. For example, Box Filter, Tent Filter, Gaussian Filter, etc.)&#xD;&#xA;[![Filter Shapes][5]][5]&#xD;&#xA;  5. Apply the weight to the color from the render&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate in the shape of a filter**&#xD;&#xA;&#xD;&#xA;The basic premise is to use [Inverse Transform Sampling][6] to create samples that are distributed according to the shape of a filter. For example a histogram of a samples distributed in the shape of a Gaussian would be:&lt;br/&gt;&#xD;&#xA;[![Gaussian Histogram][7]][7]&#xD;&#xA;&#xD;&#xA;This can either be done exactly, or by binning the function into a discrete pdf/cdf. [smallpt][2] uses the exact inverse cdf of a tent filter. Examples of binning method can be found [here][8]&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;What are the pros and cons of each method? And why would you use one over the other? I can think of a few things:&#xD;&#xA;&#xD;&#xA;Generate and Weigh seems to be the most robust, allowing any combination of any sampling method with any filter. However, it requires you to track the weights in the ImageBuffer and then do a final resolve.&#xD;&#xA;&#xD;&#xA;Generate in the Shape of a Filter can only support positive filter shapes (ie. no Mitchell, Catmull Rom, or Lanczos), since you can not have a negative pdf. But, as mentioned above, it's easier to implement, since you don't need to track any weights.&#xD;&#xA;&#xD;&#xA;Though, in the end, I guess you can think of method 2 as a simplification of method 1, since it's essentially using an implicit Box Filter weight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/core/film.h#L114&#xD;&#xA;  [2]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/users/79/benedikt-bitterli&#xD;&#xA;  [4]: https://github.com/tunabrain/tungsten/blob/master/src/core/cameras/ReconstructionFilter.hpp&#xD;&#xA;  [5]: https://i.stack.imgur.com/gz7Bg.png&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Inverse_transform_sampling&#xD;&#xA;  [7]: https://i.stack.imgur.com/7pGFS.png&#xD;&#xA;  [8]: https://gist.github.com/RichieSams/ce2ca2a201227c1de543&#xD;&#xA;  " ContentLicense="CC BY-SA 3.0" />
  <row Id="5384" PostHistoryTypeId="2" PostId="2302" RevisionGUID="6373d50b-1a60-4d91-93dd-237f26019d86" CreationDate="2016-04-12T14:35:32.873" UserId="38" Text="This kind of navigation works well for situations that are centered about objects. It keeps the up vector always pointing upward which makes it less possible for confusion.&#xD;&#xA;&#xD;&#xA;Bringing quaternions into this mix is not necessarily a good idea. People often totally exaggerate the problems of Euler angles (or taint Tait–Bryan angles). Its true that Euler did not even consider the implications in interpolating the angles. True you can get into big problems if you rotate angles into certain positions and interpolate angle by angle. But this didn't bother Euler so much as he did mathematical modeling where the problem cancels itself out.&#xD;&#xA;&#xD;&#xA;* So Euler angles are perfectly fine for storing the rotation, also ok in differential rotation. And in case as no gimbal lock can really happen anyway, you get other problems before it. Euler angles are just not good at linear interpolation in a curved space. &#xD;&#xA;&#xD;&#xA;In this case there should not be any bigger problems. Euler angles are much easier to understand. Unless you need to interpolate between 2 recorded positions. However this is a no issue as your collection and interpolation dont need to be based on the same model.&#xD;&#xA;&#xD;&#xA;Its possible to look at this model in another light, you can think of it as a vector that records camera position in relation to a center as long as you keep the vector equal length you achieve same thing. You can then just form the matrix by multiplying by up vector and then that by front to get new up. This is even easier to interpolate unless you move trough the actual center but again you can keep normalizing the vector to a length." ContentLicense="CC BY-SA 3.0" />
  <row Id="5385" PostHistoryTypeId="2" PostId="2303" RevisionGUID="97af9bbe-1272-47ce-b01b-334f1c360425" CreationDate="2016-04-13T12:09:54.340" UserId="361" Text="I have a vertex buffer like this:&#xD;&#xA;&#xD;&#xA;    0.0, 0.0,&#xD;&#xA;    1.0, 0.0,&#xD;&#xA;    0.0, 0.6,&#xD;&#xA;    1.0, 0.6,&#xD;&#xA;    0.5, 1.0&#xD;&#xA;&#xD;&#xA;I have the following index buffer:&#xD;&#xA;&#xD;&#xA;    0, 2,&#xD;&#xA;    2, 4,&#xD;&#xA;    4, 3,&#xD;&#xA;    3, 2,&#xD;&#xA;    2, 1,&#xD;&#xA;    1, 0,&#xD;&#xA;    0, 3,&#xD;&#xA;    3, 1&#xD;&#xA;&#xD;&#xA;I know I want to draw `gl.LINES` using WebGL, means multiple seperated line segments.&#xD;&#xA;&#xD;&#xA;    gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, indexBuffer);&#xD;&#xA;&#xD;&#xA;It seems to enable drawing of multiple line segments in a single draw call in WebGL.&#xD;&#xA;&#xD;&#xA;Could someone ELI5 to me, what is an index buffer and how is it related to vertex buffers? How to generate index buffers from my primitives?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5386" PostHistoryTypeId="1" PostId="2303" RevisionGUID="97af9bbe-1272-47ce-b01b-334f1c360425" CreationDate="2016-04-13T12:09:54.340" UserId="361" Text="What is an index buffer and how is it related to vertex buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5387" PostHistoryTypeId="3" PostId="2303" RevisionGUID="97af9bbe-1272-47ce-b01b-334f1c360425" CreationDate="2016-04-13T12:09:54.340" UserId="361" Text="|webgl|line-drawing|mapping|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5388" PostHistoryTypeId="2" PostId="2304" RevisionGUID="de2c24d2-4b63-4bfa-b819-7df6c752b800" CreationDate="2016-04-13T12:42:50.983" UserId="457" Text="Your vertex buffer contains the X and Y coordinates of 5 vertices. They are:&#xD;&#xA;&#xD;&#xA;    index |  X  |  Y&#xD;&#xA;      0   | 0.0 | 0.0 &#xD;&#xA;      1   | 1.0 | 0.0&#xD;&#xA;      2   | 0.0 | 0.6&#xD;&#xA;      3   | 1.0 | 0.6&#xD;&#xA;      4   | 0.5 | 1.0&#xD;&#xA;&#xD;&#xA;Your index buffer contains information about which lines to draw between these vertices. It uses the index of each vertex in the vertex buffer as a value.&#xD;&#xA;&#xD;&#xA;Since you are drawing lines, each pair of consecutive values in your index buffer indicate a line segment. For example, if the index buffer starts with `0, 2`, it means draw a line between the 0th and 2nd vertices in the vertex array, which in this case would draw a line going from `[0.0, 0.0]` to `[0.0, 0.6]`.&#xD;&#xA;&#xD;&#xA;Similarly, if you were drawing triangles instead of lines, you would need to supply an index buffer where each 3 consecutive values indicate the indices of three vertices in the vertex buffer, e.g. &#xD;&#xA;    &#xD;&#xA;    0, 1, 2,&#xD;&#xA;    2, 3, 0,&#xD;&#xA;    3, 1, 4," ContentLicense="CC BY-SA 3.0" />
  <row Id="5389" PostHistoryTypeId="2" PostId="2305" RevisionGUID="8248b1b4-2498-4ccc-9b05-8404f882fbad" CreationDate="2016-04-13T12:48:19.650" UserId="361" Text="If you have a vertex buffer like this:&#xD;&#xA;&#xD;&#xA;    var vertices = [&#xD;&#xA;      0.0, 0.0, 0.0,&#xD;&#xA;      1.0, 0.0, 0.0,&#xD;&#xA;      0.0, 0.6, 0.0,&#xD;&#xA;      1.0, 0.6, 0.0,&#xD;&#xA;      0.5, 1.0, 0.0&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;And simply draw it as it is:&#xD;&#xA;&#xD;&#xA;    // Create an empty buffer object&#xD;&#xA;    var vertex_buffer = gl.createBuffer();&#xD;&#xA;&#xD;&#xA;    // Bind appropriate array buffer to it&#xD;&#xA;    gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);&#xD;&#xA;&#xD;&#xA;    // Pass the vertex data to the buffer&#xD;&#xA;    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    /* [...] */&#xD;&#xA;&#xD;&#xA;    // Draw the lines&#xD;&#xA;    gl.drawArrays(gl.LINES, 0, 5);&#xD;&#xA;&#xD;&#xA;It would require two dedicated coordinates for each line segment. With the `vertices` as defined above, it would only be possible two draw **two lines**:&#xD;&#xA;&#xD;&#xA;[![two lines][1]][1]&#xD;&#xA;&#xD;&#xA;If you have the following indices defined:&#xD;&#xA;&#xD;&#xA;    var indices = [&#xD;&#xA;      0, 2,&#xD;&#xA;      2, 4,&#xD;&#xA;      4, 3,&#xD;&#xA;      3, 2,&#xD;&#xA;      2, 1,&#xD;&#xA;      1, 0,&#xD;&#xA;      0, 3,&#xD;&#xA;      3, 1&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;It is possible to draw lines which intersect the same vertices again and again. This reduces redundancy. If you bind the index buffer and tell the GPU to draw line segments connecting the vertices by the order specified in the indecies array:&#xD;&#xA;&#xD;&#xA;    var index_buffer = gl.createBuffer();&#xD;&#xA;&#xD;&#xA;    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);&#xD;&#xA;&#xD;&#xA;    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // draw geometry lines by indices&#xD;&#xA;    gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, index_buffer);&#xD;&#xA;&#xD;&#xA;One can draw complexer figures without redefining the same vertices over and over again. This is the result:&#xD;&#xA;&#xD;&#xA;[![a house][2]][2]&#xD;&#xA;&#xD;&#xA;To achieve the same result without indices, the vertex buffer should look like the following:&#xD;&#xA;&#xD;&#xA;    var vertices = [&#xD;&#xA;      0.0, 0.0, 0.0,&#xD;&#xA;      0.0, 0.6, 0.0,&#xD;&#xA;      0.0, 0.6, 0.0,&#xD;&#xA;      0.5, 1.0, 0.0,&#xD;&#xA;      0.5, 1.0, 0.0,&#xD;&#xA;      1.0, 0.6, 0.0,&#xD;&#xA;      1.0, 0.6, 0.0,&#xD;&#xA;      0.0, 0.6, 0.0,&#xD;&#xA;      0.0, 0.6, 0.0,&#xD;&#xA;      1.0, 0.0, 0.0,&#xD;&#xA;      1.0, 0.0, 0.0,&#xD;&#xA;      0.0, 0.0, 0.0,&#xD;&#xA;      0.0, 0.0, 0.0,&#xD;&#xA;      1.0, 0.6, 0.0,&#xD;&#xA;      1.0, 0.6, 0.0,&#xD;&#xA;      1.0, 0.0, 0.0&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;    /* [...] */&#xD;&#xA;&#xD;&#xA;    // Draw the lines&#xD;&#xA;    gl.drawArrays(gl.LINES, 0, 16);&#xD;&#xA;&#xD;&#xA;Which results in the same image:&#xD;&#xA;&#xD;&#xA;[![yet another house][3]][3]&#xD;&#xA;&#xD;&#xA;Note the huge redundancy in stored vertices. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HTDG6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oBLfK.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/QOezA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5390" PostHistoryTypeId="5" PostId="2304" RevisionGUID="bc095d62-f420-472d-bdc0-13da079b404a" CreationDate="2016-04-13T12:49:28.633" UserId="457" Comment="added 98 characters in body" Text="&gt; Could someone ELI5 to me, what is an index buffer and how is it&#xD;&#xA;&gt; related to vertex buffers&#xD;&#xA;&#xD;&#xA;Your vertex buffer contains the X and Y coordinates of 5 vertices. They are:&#xD;&#xA;&#xD;&#xA;    index |  X  |  Y&#xD;&#xA;      0   | 0.0 | 0.0 &#xD;&#xA;      1   | 1.0 | 0.0&#xD;&#xA;      2   | 0.0 | 0.6&#xD;&#xA;      3   | 1.0 | 0.6&#xD;&#xA;      4   | 0.5 | 1.0&#xD;&#xA;&#xD;&#xA;Your index buffer contains information about which lines to draw between these vertices. It uses the index of each vertex in the vertex buffer as a value.&#xD;&#xA;&#xD;&#xA;Since you are drawing lines, each pair of consecutive values in your index buffer indicate a line segment. For example, if the index buffer starts with `0, 2`, it means draw a line between the 0th and 2nd vertices in the vertex array, which in this case would draw a line going from `[0.0, 0.0]` to `[0.0, 0.6]`.&#xD;&#xA;&#xD;&#xA;Similarly, if you were drawing triangles instead of lines, you would need to supply an index buffer where each 3 consecutive values indicate the indices of three vertices in the vertex buffer, e.g. &#xD;&#xA;    &#xD;&#xA;    0, 1, 2,&#xD;&#xA;    2, 3, 0,&#xD;&#xA;    3, 1, 4," ContentLicense="CC BY-SA 3.0" />
  <row Id="5391" PostHistoryTypeId="5" PostId="2304" RevisionGUID="55c043b6-d954-4327-b76e-34f12a8932f0" CreationDate="2016-04-13T13:15:37.110" UserId="457" Comment="added 189 characters in body" Text="&gt; Could someone ELI5 to me, what is an index buffer and how is it&#xD;&#xA;&gt; related to vertex buffers&#xD;&#xA;&#xD;&#xA;Your vertex buffer contains the X and Y coordinates of 5 vertices. They are:&#xD;&#xA;&#xD;&#xA;    index |  X  |  Y&#xD;&#xA;      0   | 0.0 | 0.0 &#xD;&#xA;      1   | 1.0 | 0.0&#xD;&#xA;      2   | 0.0 | 0.6&#xD;&#xA;      3   | 1.0 | 0.6&#xD;&#xA;      4   | 0.5 | 1.0&#xD;&#xA;&#xD;&#xA;Your index buffer contains information about which lines to draw between these vertices. It uses the index of each vertex in the vertex buffer as a value.&#xD;&#xA;&#xD;&#xA;Since you are drawing lines, each pair of consecutive values in your index buffer indicate a line segment. For example, if the index buffer starts with `0, 2`, it means draw a line between the 0th and 2nd vertices in the vertex array, which in this case would draw a line going from `[0.0, 0.0]` to `[0.0, 0.6]`.&#xD;&#xA;&#xD;&#xA;In the following graphics each pair on indices is color coordinated with the line it indicates:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Similarly, if you were drawing triangles instead of lines, you would need to supply an index buffer where each 3 consecutive values indicate the indices of three vertices in the vertex buffer, e.g. &#xD;&#xA;    &#xD;&#xA;    0, 1, 2,&#xD;&#xA;    2, 1, 3,&#xD;&#xA;    2, 3, 4,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0H9FS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5392" PostHistoryTypeId="2" PostId="2306" RevisionGUID="5a7e1665-03fd-46b3-8a61-1d7455f60efd" CreationDate="2016-04-13T21:53:50.753" UserId="3123" Text="What is the best way to draw unlit objects with deferred? Like skybox, particles or just glowing objects?&#xD;&#xA;I thought about mask in alpha channel, check it in light pass and just set diffuse color but it won't work with light blending.&#xD;&#xA;My second idea was stencil buffer with pass after light pass that only fill unlit space. But switching pso (dx12) only for color copy doesn't sound like a good idea.&#xD;&#xA;And of course pass only for unlit objects after light pass, but I don't want to create another list only for this (and again, i have to switch pso).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5393" PostHistoryTypeId="1" PostId="2306" RevisionGUID="5a7e1665-03fd-46b3-8a61-1d7455f60efd" CreationDate="2016-04-13T21:53:50.753" UserId="3123" Text="Unlit objects in deferred rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="5394" PostHistoryTypeId="3" PostId="2306" RevisionGUID="5a7e1665-03fd-46b3-8a61-1d7455f60efd" CreationDate="2016-04-13T21:53:50.753" UserId="3123" Text="|lighting|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5398" PostHistoryTypeId="2" PostId="2307" RevisionGUID="54d7d0f9-46af-425b-a7f5-242d3c5f40d9" CreationDate="2016-04-14T03:21:57.747" UserId="48" Text="Typically in a deferred engine, you would render unlit objects directly to the color buffer, bypassing the lighting system entirely. You would likely also output zeroes to the G-buffer so that deferred lights don't add anything to those pixels (and possibly also mark them in the stencil buffer, to avoid running the lighting shaders on them, for efficiency).&#xD;&#xA;&#xD;&#xA;Don't worry about switching PSOs for this. I'm guessing you're worried about the performance, but it's not a big deal. Game engines typically switch PSOs (or switch shaders, in DX11/GL) hundreds or thousands of times per frame. Switching a couple of times for an extra color rendering pass isn't even a blip on the radar.&#xD;&#xA;&#xD;&#xA;However, if you want to really simplify your code (possibly at the expense of performance), you could just bind the color buffer together with your G-buffers and render to it all the time, as if it were an extra G-buffer. Ordinary deferred shaders would output zero to it, while unlit objects would output their color to it." ContentLicense="CC BY-SA 3.0" />
  <row Id="5400" PostHistoryTypeId="2" PostId="2308" RevisionGUID="38a0689b-8cd4-486e-982f-65fd995c4f5d" CreationDate="2016-04-14T07:02:25.657" UserId="2712" Text="A 3D model is sliced against a plane and the resulting 2D contour is projected onto the plane. I am looking for an efficient algorithm to identify the inside and outside region of the contour. Simultaneously I need to identify outer and inner loops within the contours. &#xD;&#xA;&#xD;&#xA;Any references from articles/books is earnestly requested.&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="5401" PostHistoryTypeId="1" PostId="2308" RevisionGUID="38a0689b-8cd4-486e-982f-65fd995c4f5d" CreationDate="2016-04-14T07:02:25.657" UserId="2712" Text="inside and outside region identification from 2D contour" ContentLicense="CC BY-SA 3.0" />
  <row Id="5402" PostHistoryTypeId="3" PostId="2308" RevisionGUID="38a0689b-8cd4-486e-982f-65fd995c4f5d" CreationDate="2016-04-14T07:02:25.657" UserId="2712" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5403" PostHistoryTypeId="2" PostId="2309" RevisionGUID="d63bdfab-091c-4426-b655-aa93a15cffcb" CreationDate="2016-04-14T08:11:28.427" UserId="2817" Text="In general, I recommend the book [Real-Time Collision Detection][1].&#xD;&#xA;&#xD;&#xA;For your particular case, my first choice would be to use the 3D test for point-inside-mesh. I assume that the contour is a sequence of 2D segments (a sequence of vertices, essentially) and that the model mesh is &quot;sealed&quot;, i.e. there are no holes in its surfaces that would make distinguishing the &quot;inside&quot; and &quot;outside&quot; of it impossible.&#xD;&#xA;&#xD;&#xA; 1. Find a bounding box for your mesh.&#xD;&#xA; 2. Cast rays from an edge of the bounding box to the tested point. In your case, the ray would be coplanar with the slicing plane, and the point would be one of the vertices of the contour.&#xD;&#xA; 3. Count how many times the ray crosses mesh triangles.&#xD;&#xA; 4. Odd number of crossings means that the point is on the inside; even number means it's on the outside.&#xD;&#xA; 5. Repeat points 2-4 for all contour vertices.&#xD;&#xA; 6. Classify contour regions by whether their vertices are on the inside or outside.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://realtimecollisiondetection.net/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5404" PostHistoryTypeId="2" PostId="2310" RevisionGUID="3b7ca817-866f-43f1-adfa-ce4836f4d1c9" CreationDate="2016-04-14T09:15:04.660" UserId="38" Text="Would it be, at least theoretically, possible to render without a near clipping plane? Could raytracing ignore this perchance? &#xD;&#xA;&#xD;&#xA;Quite many budding 3d artists have a *WTF* moment the first time they encounter the clipping plane. If this could be avoided then it would be a big win for usability of 3D authoring apps. Its not one of those things a normal artist would think about until explained.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5405" PostHistoryTypeId="1" PostId="2310" RevisionGUID="3b7ca817-866f-43f1-adfa-ce4836f4d1c9" CreationDate="2016-04-14T09:15:04.660" UserId="38" Text="Could we dispense the near clipping plane?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5406" PostHistoryTypeId="3" PostId="2310" RevisionGUID="3b7ca817-866f-43f1-adfa-ce4836f4d1c9" CreationDate="2016-04-14T09:15:04.660" UserId="38" Text="|raytracing|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5407" PostHistoryTypeId="2" PostId="2311" RevisionGUID="db464270-ae7f-4682-8106-6cd66c037eab" CreationDate="2016-04-14T10:15:00.100" UserId="137" Text="The near clipping plane in rasterizing setups with perspective projection is there to avoid a divide by 0 and bound the possible depths for orthogonal projection.&#xD;&#xA;&#xD;&#xA;With a bit of extra math you can make the depth stored in the depth buffer linear again. However you still need the guard against the divide by 0.&#xD;&#xA;&#xD;&#xA;In raytracing the near plane can be at 0 no problem. There is nothing technical stopping you from putting it at -10 however (besides that it would be very odd).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5408" PostHistoryTypeId="5" PostId="2304" RevisionGUID="0132daa1-e36a-4ee2-99ce-e9ce7a6df880" CreationDate="2016-04-14T17:27:49.293" UserId="457" Comment="deleted 1 character in body" Text="&gt; Could someone ELI5 to me, what is an index buffer and how is it&#xD;&#xA;&gt; related to vertex buffers&#xD;&#xA;&#xD;&#xA;Your vertex buffer contains the X and Y coordinates of 5 vertices. They are:&#xD;&#xA;&#xD;&#xA;    index |  X  |  Y&#xD;&#xA;      0   | 0.0 | 0.0 &#xD;&#xA;      1   | 1.0 | 0.0&#xD;&#xA;      2   | 0.0 | 0.6&#xD;&#xA;      3   | 1.0 | 0.6&#xD;&#xA;      4   | 0.5 | 1.0&#xD;&#xA;&#xD;&#xA;Your index buffer contains information about which lines to draw between these vertices. It uses the index of each vertex in the vertex buffer as a value.&#xD;&#xA;&#xD;&#xA;Since you are drawing lines, each pair of consecutive values in your index buffer indicate a line segment. For example, if the index buffer starts with `0, 2`, it means draw a line between the 0th and 2nd vertices in the vertex array, which in this case would draw a line going from `[0.0, 0.0]` to `[0.0, 0.6]`.&#xD;&#xA;&#xD;&#xA;In the following graphic each pair of indices is color coordinated with the line it indicates:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Similarly, if you were drawing triangles instead of lines, you would need to supply an index buffer where each 3 consecutive values indicate the indices of three vertices in the vertex buffer, e.g. &#xD;&#xA;    &#xD;&#xA;    0, 1, 2,&#xD;&#xA;    2, 1, 3,&#xD;&#xA;    2, 3, 4,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0H9FS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5420" PostHistoryTypeId="2" PostId="2314" RevisionGUID="8d363b8d-3c72-4fc7-8000-14179a20f313" CreationDate="2016-04-15T14:29:35.037" UserId="2372" Text="This might be a general question but I have some difficulties about understanding baked bent normal maps and how to use it inside a shader in Unity.&#xD;&#xA;&#xD;&#xA;From what I understand, bent normals are especially used with occlusion but I don't really get what they contain and how to use them.&#xD;&#xA;The other strange thing is that when baking them with different tools, it gives me different output, so it's hard for me to interpret them.&#xD;&#xA;&#xD;&#xA;Here are some examples:&#xD;&#xA;&#xD;&#xA;[![][1]][1]&lt;br&gt;&#xD;&#xA;This is made from Substance Designer in World Space. Seems really close to a simple normal map in World Space.&#xD;&#xA;&#xD;&#xA;[![][2]][2]&#xD;&#xA;This is made from Substance Designer in Tangent Space. It doesn't seem to contain really relevant informations as the one above.&#xD;&#xA;&#xD;&#xA;[![][3]][3]&#xD;&#xA;This is made from Maya Turtle. It seems to contain interesting information but... what space is that ?!&#xD;&#xA;&#xD;&#xA;[![][4]][4]&#xD;&#xA;This is the same as the one above but converted to Unity using Handplane. What can I do with this...&#xD;&#xA;&#xD;&#xA;It seems that Unity is using tangent space normal maps but I don't have any control on the import process and I don't know what they are doing. Regular normals are then unpacked in converted into world space normals using TBN matrix.&#xD;&#xA;&#xD;&#xA;The fact is that at this point, any clue or advice should be really useful.&#xD;&#xA;I don't know if my baked maps are right or usable and I don't know how to use them inside my shader.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tHXeT.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1AAcV.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Zenrb.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/BCZmP.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5421" PostHistoryTypeId="1" PostId="2314" RevisionGUID="8d363b8d-3c72-4fc7-8000-14179a20f313" CreationDate="2016-04-15T14:29:35.037" UserId="2372" Text="How could I use bent normal map" ContentLicense="CC BY-SA 3.0" />
  <row Id="5422" PostHistoryTypeId="3" PostId="2314" RevisionGUID="8d363b8d-3c72-4fc7-8000-14179a20f313" CreationDate="2016-04-15T14:29:35.037" UserId="2372" Text="|rendering|shader|texture|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5423" PostHistoryTypeId="6" PostId="2314" RevisionGUID="b186d6c1-6daa-40c3-9cfa-4b3371661156" CreationDate="2016-04-15T14:50:10.927" UserId="2372" Comment="edited tags" Text="|opengl|rendering|shader|texture|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5424" PostHistoryTypeId="5" PostId="2314" RevisionGUID="70c32545-007e-4492-a9b1-f7dda607e272" CreationDate="2016-04-15T15:16:12.770" UserId="2372" Comment="added 12 characters in body" Text="This might be a general question but I have some difficulties about understanding baked bent normal maps and how to use it inside a shader in Unity.&#xD;&#xA;&#xD;&#xA;From what I understand, bent normals are especially used with occlusion but I don't really get what they contain and how to use them.&#xD;&#xA;The other strange thing is that when baking them with different tools, it gives me different output, so it's hard for me to interpret them.&#xD;&#xA;&#xD;&#xA;Here are some examples:&#xD;&#xA;&#xD;&#xA;[![][1]][1]&lt;br&gt;&#xD;&#xA;This is made from Substance Designer in World Space. Seems really close to a simple normal map in World Space.&#xD;&#xA;&#xD;&#xA;[![][2]][2]&lt;br&gt;&#xD;&#xA;This is made from Substance Designer in Tangent Space. It doesn't seem to contain really relevant informations as the one above.&#xD;&#xA;&#xD;&#xA;[![][3]][3]&lt;br&gt;&#xD;&#xA;This is made from Maya Turtle. It seems to contain interesting information but... what space is that ?!&#xD;&#xA;&#xD;&#xA;[![][4]][4]&lt;br&gt;&#xD;&#xA;This is the same as the one above but converted to Unity using Handplane. What can I do with this...&#xD;&#xA;&#xD;&#xA;It seems that Unity is using tangent space normal maps but I don't have any control on the import process and I don't know what they are doing. Regular normals are then unpacked in converted into world space normals using TBN matrix.&#xD;&#xA;&#xD;&#xA;The fact is that at this point, any clue or advice should be really useful.&#xD;&#xA;I don't know if my baked maps are right or usable and I don't know how to use them inside my shader.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tHXeT.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1AAcV.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Zenrb.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/BCZmP.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5425" PostHistoryTypeId="10" PostId="2301" RevisionGUID="5cf7d6bd-83e2-4af1-a02b-b87a4f62ddf3" CreationDate="2016-04-16T06:49:49.237" UserId="127" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:528,&quot;DisplayName&quot;:&quot;Wumpf&quot;},{&quot;Id&quot;:127,&quot;DisplayName&quot;:&quot;Nero&quot;}]}" />
  <row Id="5426" PostHistoryTypeId="2" PostId="2315" RevisionGUID="1d4584c3-7472-4707-a2a3-6c9212093a3a" CreationDate="2016-04-16T11:26:50.253" UserId="3141" Text="I need to load a model &quot;somemodel.json&quot; into my &quot;movie.js&quot;.Can someone tell me where i am going wrong.I followed the steps given [here](http://threejs.org/docs/#Reference/Loaders/JSONLoader).&#xD;&#xA;&#xD;&#xA;**index.html**&#xD;&#xA;&#xD;&#xA;.. code:: html&#xD;&#xA;&#xD;&#xA;    &lt;!DOCTYPE html&gt;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;	    &lt;head&gt;&#xD;&#xA;		     &lt;meta charset=utf-8&gt;&#xD;&#xA;		     &lt;title&gt;Test&lt;/title&gt;&#xD;&#xA;		     &lt;style&gt;&#xD;&#xA;			    body { margin: 0; }&#xD;&#xA;			    canvas { width: 100%; height: 100% }&#xD;&#xA;		     &lt;/style&gt;&#xD;&#xA;	    &lt;/head&gt;&#xD;&#xA;	    &lt;body&gt;&#xD;&#xA;		    &lt;script src=&quot;three.min.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;            &lt;script src=&quot;JSONLoader.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;		    &lt;script src=&quot;movie.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;	    &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;**movie.js**&#xD;&#xA;&#xD;&#xA;.. code:: javascipt&#xD;&#xA;&#xD;&#xA;    var camera;&#xD;&#xA;    var scene;&#xD;&#xA;    var renderer;&#xD;&#xA;    var loader;&#xD;&#xA;&#xD;&#xA;    frame();&#xD;&#xA;    animate();&#xD;&#xA;  &#xD;&#xA;    function frame() {&#xD;&#xA;  &#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    camera = new THREE.PerspectiveCamera( 45, window.innerWidth /     window.innerHeight, 0.1, 1000);&#xD;&#xA;    camera.position.y = 0;&#xD;&#xA;    camera.position.z = 10;&#xD;&#xA;    camera.rotation.x = 0;&#xD;&#xA;&#xD;&#xA;    var loader = new THREE.JSONLoader();&#xD;&#xA;    loader.load(&#xD;&#xA;	'somemodel.json',&#xD;&#xA;	function () {&#xD;&#xA;        var geometry = new THREE.SphereGeometry(3,32,32);&#xD;&#xA;		var material = new THREE.MeshBasicMaterial();&#xD;&#xA;		var object = new THREE.Mesh( geometry, material );&#xD;&#xA;	    scene.add( object );&#xD;&#xA;	}&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize( window.innerWidth, window.innerHeight );&#xD;&#xA;    document.body.appendChild( renderer.domElement );&#xD;&#xA;    render();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function animate() {&#xD;&#xA;    render();&#xD;&#xA;    requestAnimationFrame( animate );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function render() {&#xD;&#xA;    renderer.render( scene, camera );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Or can your give an example with a sample model ?&#xD;&#xA;&#xD;&#xA;Thanks in advance !!!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5427" PostHistoryTypeId="1" PostId="2315" RevisionGUID="1d4584c3-7472-4707-a2a3-6c9212093a3a" CreationDate="2016-04-16T11:26:50.253" UserId="3141" Text="How to load a model in .json in three.js" ContentLicense="CC BY-SA 3.0" />
  <row Id="5428" PostHistoryTypeId="3" PostId="2315" RevisionGUID="1d4584c3-7472-4707-a2a3-6c9212093a3a" CreationDate="2016-04-16T11:26:50.253" UserId="3141" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5429" PostHistoryTypeId="5" PostId="2315" RevisionGUID="d8737756-f905-42c4-ab4d-c46ec8c0dc3d" CreationDate="2016-04-16T11:39:32.350" UserId="3141" Comment="added 6 characters in body" Text="I need to load a model &quot;somemodel.json&quot; into my &quot;movie.js&quot;.Can someone tell me where i am going wrong.I followed the steps given [here](http://threejs.org/docs/#Reference/Loaders/ObjectLoader).&#xD;&#xA;&#xD;&#xA;**index.html**&#xD;&#xA;&#xD;&#xA;.. code:: html&#xD;&#xA;&#xD;&#xA;    &lt;!DOCTYPE html&gt;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;	    &lt;head&gt;&#xD;&#xA;		     &lt;meta charset=utf-8&gt;&#xD;&#xA;		     &lt;title&gt;Test&lt;/title&gt;&#xD;&#xA;		     &lt;style&gt;&#xD;&#xA;			    body { margin: 0; }&#xD;&#xA;			    canvas { width: 100%; height: 100% }&#xD;&#xA;		     &lt;/style&gt;&#xD;&#xA;	    &lt;/head&gt;&#xD;&#xA;	    &lt;body&gt;&#xD;&#xA;		    &lt;script src=&quot;three.min.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;            &lt;script src=&quot;ObjectLoader.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;		    &lt;script src=&quot;movie.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;	    &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;**movie.js**&#xD;&#xA;&#xD;&#xA;.. code:: javascipt&#xD;&#xA;&#xD;&#xA;    var camera;&#xD;&#xA;    var scene;&#xD;&#xA;    var renderer;&#xD;&#xA;    var loader;&#xD;&#xA;&#xD;&#xA;    frame();&#xD;&#xA;    animate();&#xD;&#xA;  &#xD;&#xA;    function frame() {&#xD;&#xA;  &#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    camera = new THREE.PerspectiveCamera( 45, window.innerWidth /     window.innerHeight, 0.1, 1000);&#xD;&#xA;    camera.position.y = 0;&#xD;&#xA;    camera.position.z = 10;&#xD;&#xA;    camera.rotation.x = 0;&#xD;&#xA;&#xD;&#xA;    var loader = new THREE.ObjectLoader();&#xD;&#xA;    loader.load(&#xD;&#xA;	'somemodel.json',&#xD;&#xA;	function () {&#xD;&#xA;        var geometry = new THREE.SphereGeometry(3,32,32);&#xD;&#xA;		var material = new THREE.MeshBasicMaterial();&#xD;&#xA;		var object = new THREE.Mesh( geometry, material );&#xD;&#xA;	    scene.add( object );&#xD;&#xA;	}&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize( window.innerWidth, window.innerHeight );&#xD;&#xA;    document.body.appendChild( renderer.domElement );&#xD;&#xA;    render();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function animate() {&#xD;&#xA;    render();&#xD;&#xA;    requestAnimationFrame( animate );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function render() {&#xD;&#xA;    renderer.render( scene, camera );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Or can your give an example with a sample model ?&#xD;&#xA;&#xD;&#xA;Thanks in advance !!!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5430" PostHistoryTypeId="5" PostId="2315" RevisionGUID="c8887bdd-fb82-44a9-8054-bc574568c57a" CreationDate="2016-04-16T11:50:49.683" UserId="231" Comment="Correct syntax highlighting" Text="I need to load a model &quot;somemodel.json&quot; into my &quot;movie.js&quot;.Can someone tell me where i am going wrong.I followed the steps given [here](http://threejs.org/docs/#Reference/Loaders/ObjectLoader).&#xD;&#xA;&#xD;&#xA;**index.html**&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;!DOCTYPE html&gt;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;	    &lt;head&gt;&#xD;&#xA;		     &lt;meta charset=utf-8&gt;&#xD;&#xA;		     &lt;title&gt;Test&lt;/title&gt;&#xD;&#xA;		     &lt;style&gt;&#xD;&#xA;			    body { margin: 0; }&#xD;&#xA;			    canvas { width: 100%; height: 100% }&#xD;&#xA;		     &lt;/style&gt;&#xD;&#xA;	    &lt;/head&gt;&#xD;&#xA;	    &lt;body&gt;&#xD;&#xA;		    &lt;script src=&quot;three.min.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;            &lt;script src=&quot;ObjectLoader.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;		    &lt;script src=&quot;movie.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;	    &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;**movie.js**&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;    var camera;&#xD;&#xA;    var scene;&#xD;&#xA;    var renderer;&#xD;&#xA;    var loader;&#xD;&#xA;&#xD;&#xA;    frame();&#xD;&#xA;    animate();&#xD;&#xA;  &#xD;&#xA;    function frame() {&#xD;&#xA;  &#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    camera = new THREE.PerspectiveCamera( 45, window.innerWidth /     window.innerHeight, 0.1, 1000);&#xD;&#xA;    camera.position.y = 0;&#xD;&#xA;    camera.position.z = 10;&#xD;&#xA;    camera.rotation.x = 0;&#xD;&#xA;&#xD;&#xA;    var loader = new THREE.ObjectLoader();&#xD;&#xA;    loader.load(&#xD;&#xA;	'somemodel.json',&#xD;&#xA;	function () {&#xD;&#xA;        var geometry = new THREE.SphereGeometry(3,32,32);&#xD;&#xA;		var material = new THREE.MeshBasicMaterial();&#xD;&#xA;		var object = new THREE.Mesh( geometry, material );&#xD;&#xA;	    scene.add( object );&#xD;&#xA;	}&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize( window.innerWidth, window.innerHeight );&#xD;&#xA;    document.body.appendChild( renderer.domElement );&#xD;&#xA;    render();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function animate() {&#xD;&#xA;    render();&#xD;&#xA;    requestAnimationFrame( animate );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function render() {&#xD;&#xA;    renderer.render( scene, camera );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Or can your give an example with a sample model ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5431" PostHistoryTypeId="5" PostId="2315" RevisionGUID="5b0b5cdd-e20a-4e16-8aad-ff739183ef19" CreationDate="2016-04-16T12:10:44.253" UserId="3141" Comment="added 100 characters in body" Text="I need to load a model &quot;somemodel.json&quot; into my &quot;movie.js&quot;.Can someone tell me where i am going wrong.I followed the steps given [here](http://threejs.org/docs/#Reference/Loaders/ObjectLoader).&#xD;&#xA;&#xD;&#xA;**index.html**&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;!DOCTYPE html&gt;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;	    &lt;head&gt;&#xD;&#xA;		     &lt;meta charset=utf-8&gt;&#xD;&#xA;		     &lt;title&gt;Test&lt;/title&gt;&#xD;&#xA;		     &lt;style&gt;&#xD;&#xA;			    body { margin: 0; }&#xD;&#xA;			    canvas { width: 100%; height: 100% }&#xD;&#xA;		     &lt;/style&gt;&#xD;&#xA;	    &lt;/head&gt;&#xD;&#xA;	    &lt;body&gt;&#xD;&#xA;		    &lt;script src=&quot;three.min.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;            &lt;script src=&quot;ObjectLoader.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;		    &lt;script src=&quot;movie.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;	    &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;**movie.js**&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;    var camera;&#xD;&#xA;    var scene;&#xD;&#xA;    var renderer;&#xD;&#xA;    var loader;&#xD;&#xA;&#xD;&#xA;    frame();&#xD;&#xA;    animate();&#xD;&#xA;  &#xD;&#xA;    function frame() {&#xD;&#xA;  &#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    camera = new THREE.PerspectiveCamera( 45, window.innerWidth /     window.innerHeight, 0.1, 1000);&#xD;&#xA;    camera.position.y = 0;&#xD;&#xA;    camera.position.z = 10;&#xD;&#xA;    camera.rotation.x = 0;&#xD;&#xA;&#xD;&#xA;    var loader = new THREE.ObjectLoader();&#xD;&#xA;    loader.load(&#xD;&#xA;	'somemodel.json',&#xD;&#xA;	function () {&#xD;&#xA;        var geometry = new THREE.SphereGeometry(3,32,32);&#xD;&#xA;		var material = new THREE.MeshBasicMaterial();&#xD;&#xA;		var object = new THREE.Mesh( geometry, material );&#xD;&#xA;	    scene.add( object );&#xD;&#xA;	}&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize( window.innerWidth, window.innerHeight );&#xD;&#xA;    document.body.appendChild( renderer.domElement );&#xD;&#xA;    render();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function animate() {&#xD;&#xA;    render();&#xD;&#xA;    requestAnimationFrame( animate );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function render() {&#xD;&#xA;    renderer.render( scene, camera );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Or can your give an example with a sample model ?&#xD;&#xA;&#xD;&#xA;When i run my file it raises an error in the console saying ``not well-formed        male.json``" ContentLicense="CC BY-SA 3.0" />
  <row Id="5432" PostHistoryTypeId="2" PostId="2316" RevisionGUID="74eef146-f88a-4ddd-b704-edfed24f682a" CreationDate="2016-04-16T21:40:19.773" UserId="231" Text="I have seen that in some implementations of Path Tracing, an approach called Russian Roulette is used to cull some of the paths and share their contribution among the other paths.&#xD;&#xA;&#xD;&#xA;I understand that rather than following a path until it drops below a certain threshold value of contribution, and then abandoning it, a different threshold is used and paths whose contribution is below that threshold are only terminated with some small probability. The other paths have their contribution increased by an amount corresponding to sharing the lost energy from the terminated path. It isn't clear to me whether this is to correct a bias introduced by the technique, or whether the whole technique is itself necessary to avoid bias.&#xD;&#xA;&#xD;&#xA;- Does Russian Roulette give an unbiased result?&#xD;&#xA;- Is Russian Roulette *necessary* for an unbiased result?&#xD;&#xA;&#xD;&#xA;That is, would using a tiny threshold and just terminating a path the moment it drops below that threshold give a more or less biased result?&#xD;&#xA;&#xD;&#xA;Given an arbitrarily large number of samples, would both approaches converge on an unbiased resulting image?&#xD;&#xA;&#xD;&#xA;I'm looking to understand the underlying reason for using the Russian Roulette approach. Is there a significant difference in speed or quality?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I understand that the energy is redistributed among other rays in order to preserve total energy. However, could this redistribution not still be done if the ray were terminated on dropping below a fixed threshold, rather than having a randomly determined life span after reaching that threshold?&#xD;&#xA;&#xD;&#xA;Conversely, if energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays it is redistributed to are also eventually terminated), how does this improve the situation?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5433" PostHistoryTypeId="1" PostId="2316" RevisionGUID="74eef146-f88a-4ddd-b704-edfed24f682a" CreationDate="2016-04-16T21:40:19.773" UserId="231" Text="Is Russian Roulette really the answer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5434" PostHistoryTypeId="3" PostId="2316" RevisionGUID="74eef146-f88a-4ddd-b704-edfed24f682a" CreationDate="2016-04-16T21:40:19.773" UserId="231" Text="|monte-carlo|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5435" PostHistoryTypeId="2" PostId="2317" RevisionGUID="f28f196f-6b90-4700-ad0e-b7d52f649735" CreationDate="2016-04-16T23:14:54.010" UserId="3143" Text="The error ```not well-formed        male.json``` doesn't appear to have anything to do with the code you've posted. I don't see any references to a JSON file called ```male.json```.&#xD;&#xA;&#xD;&#xA;If this file is in your code somewhere, the error is telling you the problem. It is malformed. Paste the contents of the file into an online validation tool such as [JSONLint][1]. It will tell you what is making it malformed.&#xD;&#xA;&#xD;&#xA;Also, you're passing JSON into ```ObjectLoader.load``` but you don't do anything with the results. Instead try this:&#xD;&#xA;&#xD;&#xA;    var loader = new THREE.ObjectLoader();&#xD;&#xA;    loader.load('somemodel.json', function (object) {&#xD;&#xA;        scene.add(object);&#xD;&#xA;    });&#xD;&#xA;&#xD;&#xA;Check out [the documentation][2] for more information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]: http://jsonlint.com/&#xD;&#xA;[2]: http://threejs.org/docs/#Reference/Loaders/ObjectLoader&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5436" PostHistoryTypeId="2" PostId="2318" RevisionGUID="8f427943-ef66-406e-b1fa-663c2839aefa" CreationDate="2016-04-16T23:42:21.557" UserId="3144" Text="I found many sites, books and articles, all about especifics algorithms, I listed some of them (like *bounding boxes*, *bounding spheres*, *octrees* and *KD-tree*), but any of these founds lists every algorithm for collision detection, and thats what I need.&#xD;&#xA;&#xD;&#xA;Someone knows the name of all algorithms (or at least some of them, any other algorithm would help) for collision detection, or knows where I can find it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5437" PostHistoryTypeId="1" PostId="2318" RevisionGUID="8f427943-ef66-406e-b1fa-663c2839aefa" CreationDate="2016-04-16T23:42:21.557" UserId="3144" Text="Collision detection methods for 2D and 3D environments" ContentLicense="CC BY-SA 3.0" />
  <row Id="5438" PostHistoryTypeId="3" PostId="2318" RevisionGUID="8f427943-ef66-406e-b1fa-663c2839aefa" CreationDate="2016-04-16T23:42:21.557" UserId="3144" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5439" PostHistoryTypeId="2" PostId="2319" RevisionGUID="4f8373da-186e-4cde-8134-c6bab17c95d5" CreationDate="2016-04-16T23:53:54.400" UserId="3145" Text="There is a book about real-time collision detection that contains a variety of algorithms for all sorts of intersection tests and lists a large number of collision detection algorithms. It's a decent overview if that's what you are looking for:&#xD;&#xA;&#xD;&#xA;http://realtimecollisiondetection.net&#xD;&#xA;&#xD;&#xA;https://books.google.com/books?isbn=0080474144" ContentLicense="CC BY-SA 3.0" />
  <row Id="5440" PostHistoryTypeId="10" PostId="2318" RevisionGUID="f2372f7f-f9b7-4784-bfe1-8523d2ba400d" CreationDate="2016-04-17T08:43:38.453" UserId="231" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="5441" PostHistoryTypeId="2" PostId="2320" RevisionGUID="1ef79553-709c-41ad-89c9-7c5c9156a2c8" CreationDate="2016-04-17T11:42:57.663" UserId="3069" Text="I am trying to implement for research purposes a path tracer, but so far but results are not so good and I will explain you why. The general idea before getting to the code:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid, which means that I can calculate its contribution for the pixel (x,y) which otherwise will be black.&#xD;&#xA;&#xD;&#xA;But first, my aim is to reach an &quot;acceptable&quot; image with a few number of SPP (around 16-32 spp). This is because I am following the code of a target framework, easy implemented, that manages to reach such good results in few steps (explained later). The following is the  target image that I want to reach, produced by the target framework:&#xD;&#xA;&#xD;&#xA;[![Target image][1]][1]&#xD;&#xA;&#xD;&#xA;It's rendered with 16SPP. The core code behind it is quite straightforward. It just implements the rendering equation and it is shown and commented below:&#xD;&#xA;&#xD;&#xA;    Vec Sample(vec3 O, vec3 D, int depth)//oriding, direction, depth of the recursive step&#xD;&#xA;    {&#xD;&#xA;	  vec3 color(0, 0, 0);&#xD;&#xA;      float t;&#xD;&#xA;	  if (checkIfIntersectSomething(D, t))&#xD;&#xA;	  {&#xD;&#xA;				&#xD;&#xA;		vec3 I = O + t * D; //get to the intersection point on the object&#xD;&#xA;		vec3 diffuse = getMaterial(I);&#xD;&#xA;&#xD;&#xA;		vec3 L = vec3(-1 + Rand(2.0f), 20, 9 + Rand(2.0f)) - I; //(-1,20,9) is Hard-code of the light position, and I add Rand(2.0f) on X and Z axis&#xD;&#xA;		//so that I have an area light instead of a point light&#xD;&#xA;		L = normalize(L);&#xD;&#xA;		float ndotl = dot(I.getNormal(), L); //the closer the dotProdutc is to 1.0, the more the light and surface face each other&#xD;&#xA;		if (ndotl &gt; 0)&#xD;&#xA;		{&#xD;&#xA;			if (!checkRayLightIntersection(L)) {&#xD;&#xA;				float dist = distFromLight(I);&#xD;&#xA;				color += diffuse * ndotl * vec3(1000.0f, 1000.0f, 850.0f) * (1.0f / (dist * dist));&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		// russian roulette&#xD;&#xA;		float Psurvival = CLAMP((diffuse.r + diffuse.g + diffuse.b) * 0.33333f, 0.2f, 0.8f);&#xD;&#xA;&#xD;&#xA;		// continue random walk &#xD;&#xA;		float rand = Rand(1.0f);&#xD;&#xA;		if (depth &lt; 10 &amp;&amp; rand &lt; Psurvival)&#xD;&#xA;		{&#xD;&#xA;			//Besides russian roulette, I also do another weight, because rays that go towards the horizon will bring back very little energy&#xD;&#xA;			//so I make a random distribution that favours those rays who are close to the normal of the hit point, this is DiffuseReflectionCosineWeighted(). It creates a Random bounce but proportional to N dot R&#xD;&#xA;			vec3 R = DiffuseReflectionCosineWeighted(I.getNormal());//there is a weight&#xD;&#xA;&#xD;&#xA;			float prob = 1.0;&#xD;&#xA;			float cosTheta = fabs(dot(I.getNormal(), R));&#xD;&#xA;			if (cosTheta &gt; 1e-6) prob = cosTheta / M_PI;&#xD;&#xA;&#xD;&#xA;			color += diffuse * Sample(I + R * EPSILON, R, depth + 1) * (1.0f / Psurvival); //the cosTheta() of the attenuation of the rendering equation gets simplified with the cosTheta of the &quot;prob&quot;&#xD;&#xA;			//the PI of the prob gets simplified with the BRDF where we are using the ideal BRDF = diffuse/PI&#xD;&#xA;		}&#xD;&#xA;	  }&#xD;&#xA;	return color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **DiffuseReflectionCosineWeighted** implies that we have to apply a PDF to our recursive step. This PDF is **cosTheta/PI** and we have to divide for it in:&#xD;&#xA;&#xD;&#xA;    color += diffuse * Sample(I + R * EPSILON, R, depth + 1) * (1.0f / Psurvival);&#xD;&#xA;&#xD;&#xA;You can't see it in the code because it gets simplified witht the **cosTheta** attenuation term of the rendering equation and **PI** of the diffuse BRDF where my BRDF is indeed **diffuse/PI** because we want to consider only DIFFUSE objects.&#xD;&#xA;(For any question about the code do not hesitate to ask.)&#xD;&#xA;&#xD;&#xA;I tried to emulate this code with the difference that I don't calculate the path at the moment I want to calculate the color of a pixel (like the target framework does above), but I calculate a path beforehand:&#xD;&#xA;My **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface of area 2x2 placed at the same position (-1,20,9), as the target framework does.&#xD;&#xA;&#xD;&#xA;First the definition of a couple of struct to store some info:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; And now the main code:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p - O);&#xD;&#xA;			float distFromLight = length(hitLightPoint - O);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **BSDFDiffuseReflectionCosineWeighted()** just calculates the new direction like in the target framework, tested and working. What remains last is the Sample method which calculates the final color of the pixel using the path calculated right above:&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is that the image is really dark, you can see how small the light is, but somehow in the target framework it works correctly while in mine:&#xD;&#xA;&#xD;&#xA;[![Dark render][2]][2]&#xD;&#xA;&#xD;&#xA;This is because not many rays reach the light, so many paths are not considered valid. If instead I make my light broad (20x20) results are better but I lose the shadows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am sure that less rays reach the light cause I have been calculating them in both cases: small area light and big area light. I also tried to compensate the dark image by increasing the light contribution when reached by the path, but it brings to white pixels (for paths that reach the light) and the black ones (cause of invalid path) keep remaining black, so not a good approach. It seems that (as far as my understanding arrives) the target framework applies direct lighting, that's why such a good image BUT according to theory direct lighting only decrease variance, reducing the noise.. which means that using or not direct lighting shouldn't change the resulting image so much. Is there a way according to you to fix this problem? Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QHG2z.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/8aYPH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JvGhf.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5442" PostHistoryTypeId="1" PostId="2320" RevisionGUID="1ef79553-709c-41ad-89c9-7c5c9156a2c8" CreationDate="2016-04-17T11:42:57.663" UserId="3069" Text="How to compensate low amount of rays reaching the light in a Path Tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="5443" PostHistoryTypeId="3" PostId="2320" RevisionGUID="1ef79553-709c-41ad-89c9-7c5c9156a2c8" CreationDate="2016-04-17T11:42:57.663" UserId="3069" Text="|c++|lighting|shadow|pathtracing|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5445" PostHistoryTypeId="5" PostId="2316" RevisionGUID="2693fee6-1360-41ad-b6c6-da333724c6ef" CreationDate="2016-04-17T13:07:37.037" UserId="231" Comment="Minor wording improvement" Text="I have seen that in some implementations of Path Tracing, an approach called Russian Roulette is used to cull some of the paths and share their contribution among the other paths.&#xD;&#xA;&#xD;&#xA;I understand that rather than following a path until it drops below a certain threshold value of contribution, and then abandoning it, a different threshold is used and paths whose contribution is below that threshold are only terminated with some small probability. The other paths have their contribution increased by an amount corresponding to sharing the lost energy from the terminated path. It isn't clear to me whether this is to correct a bias introduced by the technique, or whether the whole technique is itself necessary to avoid bias.&#xD;&#xA;&#xD;&#xA;- Does Russian Roulette give an unbiased result?&#xD;&#xA;- Is Russian Roulette *necessary* for an unbiased result?&#xD;&#xA;&#xD;&#xA;That is, would using a tiny threshold and just terminating a path the moment it drops below that threshold give a more biased or less biased result?&#xD;&#xA;&#xD;&#xA;Given an arbitrarily large number of samples, would both approaches converge on an unbiased resulting image?&#xD;&#xA;&#xD;&#xA;I'm looking to understand the underlying reason for using the Russian Roulette approach. Is there a significant difference in speed or quality?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I understand that the energy is redistributed among other rays in order to preserve total energy. However, could this redistribution not still be done if the ray were terminated on dropping below a fixed threshold, rather than having a randomly determined life span after reaching that threshold?&#xD;&#xA;&#xD;&#xA;Conversely, if the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5447" PostHistoryTypeId="5" PostId="2279" RevisionGUID="502d06be-c95d-4568-b9cf-84ed01a99db1" CreationDate="2016-04-17T15:19:19.143" UserId="3069" Comment="added 665 characters in body" Text="I am trying to implement for research purposes a gradient-domain path tracer. In order to achieve this step I first need a working Path tracer. I have been creating one so far but results are wrong and I will explain you why. Some concepts:&#xD;&#xA;&#xD;&#xA;I am working on paths that are generated before sampling them. I mean that the first step of my algorithm consists in calculating a path for a certain pixel (x,y). This path will perform some bounces within the scene and, if terminates on the light, will be considered valid.&#xD;&#xA;&#xD;&#xA;First of all: the following is the definition of a struct (will be declared and initialized later), containing some scene info needed to cast ray from the camera into the scene.&#xD;&#xA;&#xD;&#xA;    struct RenderData&#xD;&#xA;	{&#xD;&#xA;		vec3 E;&#xD;&#xA;        vec3 p1;&#xD;&#xA;        vec3 dx;&#xD;&#xA;        vec3 dy;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;It is initialized in the InitializeScene method:&#xD;&#xA;&#xD;&#xA;    void InitializeScene(){ // setup virtual screen plane&#xD;&#xA;      vec3 E( 2, 8, -26 ); //Eye position&#xD;&#xA;      vec3 V( 0, 0, 1 ); //LookAt vector&#xD;&#xA;	  float d = 0.5f, ratio = SCRWIDTH / SCRHEIGHT, focal = 18.0f;&#xD;&#xA;	  vec3 p1(E + V * focal + vec3(-d * ratio * focal, d * focal, 0)); // top-left screen corner in SCREEN SPACE&#xD;&#xA;	  vec3 p2(E + V * focal + vec3(d * ratio * focal, d * focal, 0)); // top-right screen corner&#xD;&#xA;	  vec3 p3(E + V * focal + vec3(-d * ratio * focal, -d * focal, 0)); // bottom-left screen corner&#xD;&#xA;      mat4 M = rotate( mat4( 1 ), r, vec3( 0, 1, 0 ) );&#xD;&#xA;	  p1 = vec3(M * vec4(p1, 1.0f)); //rotating the above points&#xD;&#xA;	  p2 = vec3(M * vec4(p2, 1.0f));&#xD;&#xA;	  p3 = vec3(M * vec4(p3, 1.0f));&#xD;&#xA;	  renderData.dx = (p2 - p1) / (float)SCRWIDTH;&#xD;&#xA;	  renderData.dy = (p3 - p1) / (float)SCRHEIGHT;&#xD;&#xA;	  renderData.E = vec3(M * vec4(E, 1.0f));&#xD;&#xA;	  renderData.p1 = p1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above is to make you understand how I initialized the scene.&#xD;&#xA;I also have structs to store informations about my paths:&#xD;&#xA;&#xD;&#xA;    struct PathVert {&#xD;&#xA;       vec3 p; vec3 n; //hit point and normal of the surface hit &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    struct Path {&#xD;&#xA;       PathVert verts[MAX_DEPTH]; //maxDepth is 15 for now&#xD;&#xA;       int vertCount;&#xD;&#xA;       int x, y; //which pixel this path is referring to&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; therefore I start consider pixel after pixel.&#xD;&#xA;&#xD;&#xA;    for (int y = 0; y &lt; SCRHEIGHT; y++) for (int x = 0; x &lt; SCRWIDTH; x++)&#xD;&#xA;	{	  &#xD;&#xA;       Path path;&#xD;&#xA;       if(generatePath(x,y, path)){&#xD;&#xA;          Sample(path);&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The **generatePath()** method indeed tracks the path into the scene and checks all the vertices it hits. The **checkIfRayIntersectSomething(t)** method you will see used, it's just a pseudo method implemented in my framework and that I omit posting cause of its length. I use it to check if my ray hits something in the scene, if it does, it update the &quot;t&quot; with the distance to that object. NOTE: the light is not considered an object itself. Hence, I also have a **checkRayLightIntersection(hitLightPoint)** which checks the intersection with the light, if there is any, the hitLightPoint is updated with the point on the light I have been hitting.&#xD;&#xA;The light is a 2D surface.&#xD;&#xA;&#xD;&#xA;    Vec lightPos = Vec(5, 15, 2); //hard coded position of the light&#xD;&#xA;&#xD;&#xA;And the light, as said, is a surface, but exactly a square surface, whose 4 angles are:&#xD;&#xA;&#xD;&#xA;    Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 20);&#xD;&#xA;	Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;	Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 20);&#xD;&#xA;&#xD;&#xA;Quite big, I know, so the first question relies on this aspect, is it correct having such a big light?&#xD;&#xA;&#xD;&#xA;But let's go to the main methods. Hereby you can see the GeneratePath method:&#xD;&#xA;&#xD;&#xA;    bool GeneratePath(int x, int y, Path &amp;path){&#xD;&#xA;       path.x = x;&#xD;&#xA;	   path.y = y;&#xD;&#xA;	   path.vertCount = 0;&#xD;&#xA;&#xD;&#xA;       vec3 P = renderData.p1 + renderData.dx * ((float)(x) + Rand(1)) +  renderData.dy * ((float)(y) + Rand(1));&#xD;&#xA;	   vec3 O = renderData.E + vec3(Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f, Rand(0.4f) - 0.2f);&#xD;&#xA;	   vec3 D = normalize(P - O); //direction of the first ray, the one from the camera towards the pixel we are considering&#xD;&#xA;&#xD;&#xA;	   for (int depth = 1; depth &lt;= MAXDEPTH; depth++){&#xD;&#xA;		float t;&#xD;&#xA;		Vec hitLightPoint;&#xD;&#xA;		PathVert vert;&#xD;&#xA;		if (!checkIfRayIntersectSomething(t)){&#xD;&#xA;			//we didn't find any object.. but we still may have found the light which is an object non represented in the scene&#xD;&#xA;			//the depth check avoids me rendering the light as a white plane&#xD;&#xA;			if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);//cause the light is pointing down&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				path.vertCount++;&#xD;&#xA;				return true; //light hit, path completed	&#xD;&#xA;			}&#xD;&#xA;			return false; //nothing hit, path non valid&#xD;&#xA;		}&#xD;&#xA;        //otherwise I got a hit into the scene&#xD;&#xA;		vert.p = O + D * t; //reach the hitPoint&#xD;&#xA;		vert.n = methodToFindTheNormal();&#xD;&#xA;		vert.color = CalculateColor(vert.p); //according to the material properties (only diffuse objects so far)&#xD;&#xA;		path.verts[depth - 1] = vert;&#xD;&#xA;		path.vertCount++;&#xD;&#xA;&#xD;&#xA;		//since I have the light, and a path terminates when it hits the light, I have to check out also if my ray hits this light,&#xD;&#xA;		//and if does, I have to check whether it first hits the light or the object just calculated above&#xD;&#xA;		//moreover with the &quot;depth &gt; 1&quot; check, I avoid again rendering the light which otherwise would be visible as a white plane&#xD;&#xA;&#xD;&#xA;		if (depth &gt; 1 &amp;&amp; checkRayLightIntersection(O, D, hitLightPoint)){&#xD;&#xA;			float distFromObj = length(vert.p);&#xD;&#xA;			float distFromLight = length(hitLightPoint);&#xD;&#xA;			if (distFromLight &lt; distFromObj){&#xD;&#xA;				//update the vertex since we realized it's the light&#xD;&#xA;				vert.p = hitLightPoint;&#xD;&#xA;				vert.n = Vec(0, -1, 0);&#xD;&#xA;				vert.color = Vec(1, 1, 1);// TODO light color? or light emission?&#xD;&#xA;				&#xD;&#xA;				path.verts[depth - 1] = vert;&#xD;&#xA;				return true; //light hit, path completed&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (depth == MAXDEPTH) return false;&#xD;&#xA;		   Vec newDir = BSDFDiffuseReflectionCosineWeighted(vert.n, D);//explained later&#xD;&#xA;		   D = newDir;&#xD;&#xA;		   O = vert.p;&#xD;&#xA;	   }&#xD;&#xA;	   return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The BSDFDiffuseReflectionCosineWeighted() just calculate the new directions, tested and working. What remains last is the Sample method which calculates the final color of the pixel.&#xD;&#xA;&#xD;&#xA;    Vec Sampling(Path &amp;path){&#xD;&#xA;&#xD;&#xA;       Vec color(1, 1, 1);&#xD;&#xA;&#xD;&#xA;       for (int vert = 0; vert &lt; path.vertCount - 1; vert++) { //considers the last vertex as the light&#xD;&#xA;          const PathVert &amp;currVert = path.verts[vert];&#xD;&#xA;          const PathVert &amp;nextVert = path.verts[vert + 1];&#xD;&#xA;          Vec wo = (nextVert.p - currVert.p).norm();&#xD;&#xA;          double cosTheta = fabs(wo.dot(currVert.n));&#xD;&#xA;          float PDF = cosTheta/PI;&#xD;&#xA;          if (cosTheta &lt;= 1e-6) return Vec();&#xD;&#xA;          //considering only DIFFUSE objects&#xD;&#xA;          color = color.mult(currVert.color * (cosTheta / M_PI) / PDF);&#xD;&#xA;       }&#xD;&#xA;       return color.mult(Vec(10.0f, 10.0f, 10.0f)); //multiplication for the light emission?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result with 16SPP is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the results are not that bad but there is one main problem: shadows are missing.. tried many combinations but no improvements. There is some error in the algorithm itself. Can you help me understanding why? Thanks in advance.&#xD;&#xA;&#xD;&#xA;EDIT: this is my target reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT 2: this is what happens in case the **depth &gt; 1** check is omitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;EDIT 3: after fixing the **distFromLight** and **distFromObj** I got the following results:&#xD;&#xA;&#xD;&#xA;[![some clue of shadows][4]][4]&#xD;&#xA;&#xD;&#xA;One of the 2 problems as suggested by @trichoplax could be too soft shadows. So I tried to lower the size of the light, increasing his power to compensate. Results are not good and shown here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Moreover as requested I can post some more code:&#xD;&#xA;&#xD;&#xA;    bool checkRayLightIntersection(Vec O, Vec D, Vec &amp; hitLightPoint){&#xD;&#xA;      //getting the 4 corners of my light&#xD;&#xA;	  Vec P1 = Vec(lightPos.x - 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P2 = Vec(lightPos.x + 20, lightPos.y, lightPos.z + 10);&#xD;&#xA;	  Vec P3 = Vec(lightPos.x + 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;	  Vec P4 = Vec(lightPos.x - 20, lightPos.y, lightPos.z - 10);&#xD;&#xA;&#xD;&#xA;	  //the majority of the methods first find out where the ray intersects the plane that the rectangle lies on Ax + By + Cz + D = 0&#xD;&#xA;	  //in our case the equation of that plane is easy -&gt; D = 20&#xD;&#xA;	  // answers.google.com/answers/threadview?id=18979&#xD;&#xA;&#xD;&#xA;	  float t = -(-O.y + lightPos.y) / (-D.y);&#xD;&#xA;	  if (t &gt; 0){&#xD;&#xA;		Vec hitPoint = O + D * t;&#xD;&#xA;		Vec V1 = (P2 - P1).norm();&#xD;&#xA;		Vec V2 = (P3 - P2).norm();&#xD;&#xA;		Vec V3 = (P4 - P3).norm();&#xD;&#xA;		Vec V4 = (P1 - P4).norm();&#xD;&#xA;		Vec V5 = (hitPoint - P1).norm();&#xD;&#xA;		Vec V6 = (hitPoint - P2).norm();&#xD;&#xA;		Vec V7 = (hitPoint - P3).norm();&#xD;&#xA;		Vec V8 = (hitPoint - P4).norm();&#xD;&#xA;&#xD;&#xA;		if (V1.dot(V5) &gt; 0.0 &amp;&amp; V2.dot(V6) &gt; 0.0 &amp;&amp; V3.dot(V7) &gt; 0.0 &amp;&amp; V4.dot(V8) &gt; 0.0){&#xD;&#xA;			hitLightPoint = hitPoint;&#xD;&#xA;			return true;&#xD;&#xA;		}&#xD;&#xA;      }&#xD;&#xA;      return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Instead, the **checkIfRayIntersectSomething** method is part of the framework itself (it has just another name), it's not done by me but it's tested and working.&#xD;&#xA;&#xD;&#xA;EDIT 4: tried to render a small part of the scene with high number of spp. Tried 512 spp for the bottom right corner where should appear shadows according to the target image. Results show that shadows are not there:&#xD;&#xA;&#xD;&#xA;[![Bottom right corner at 512spp][6]][6]&#xD;&#xA;&#xD;&#xA;EDIT 5:&#xD;&#xA;&#xD;&#xA;I hereby post the code used to render the target image, it does at the same time my **Sampling()** and **GeneratePath()** methods using a recursive structure.&#xD;&#xA;&#xD;&#xA;    Vec Sample(vec3 O, vec3 D, int depth)&#xD;&#xA;    {&#xD;&#xA;	  vec3 color(0, 0, 0);&#xD;&#xA;      float t;&#xD;&#xA;	  if (checkIfIntersectSomething(D, t))&#xD;&#xA;	  {&#xD;&#xA;				&#xD;&#xA;		vec3 I = O + t * D; //get to the intersection point on the object&#xD;&#xA;		vec3 diffuse = getMaterial(I);&#xD;&#xA;&#xD;&#xA;		vec3 L = vec3(-1 + Rand(2.0f), 20, 9 + Rand(2.0f)) - I; //(-1,20,9) is Hard-code of the light position, and I add Rand(2.0f) on X and Z axis&#xD;&#xA;		//so that I have an area light instead of a point light&#xD;&#xA;		L = normalize(L);&#xD;&#xA;		float ndotl = dot(I.getNormal(), L); //the closer the dotProdutc is to 1.0, the more the light and surface face each other&#xD;&#xA;		if (ndotl &gt; 0)&#xD;&#xA;		{&#xD;&#xA;			if (!checkRayLightIntersection(L)) {&#xD;&#xA;				float dist = distFromLight(I);&#xD;&#xA;				color += diffuse * ndotl * vec3(1000.0f, 1000.0f, 850.0f) * (1.0f / (dist * dist));&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		// russian roulette&#xD;&#xA;		float Psurvival = CLAMP((diffuse.r + diffuse.g + diffuse.b) * 0.33333f, 0.2f, 0.8f);&#xD;&#xA;&#xD;&#xA;		// continue random walk &#xD;&#xA;		float rand = Rand(1.0f);&#xD;&#xA;		if (depth &lt; 10 &amp;&amp; rand &lt; Psurvival)&#xD;&#xA;		{&#xD;&#xA;			//Besides russian roulette, I also do another weight, because rays that go towards the horizon will bring back very little energy&#xD;&#xA;			//so I make a random distribution that favours those rays who are close to the normal of the hit point, this is DiffuseReflectionCosineWeighted(). It creates a Random bounce but proportional to N dot R&#xD;&#xA;			vec3 R = DiffuseReflectionCosineWeighted(I.getNormal());//there is a weight&#xD;&#xA;&#xD;&#xA;			float prob = 1.0;&#xD;&#xA;			float cosTheta = fabs(dot(I.getNormal(), R));&#xD;&#xA;			if (cosTheta &gt; 1e-6) prob = cosTheta / M_PI;&#xD;&#xA;&#xD;&#xA;			color += diffuse * Sample(I + R * EPSILON, R, depth + 1) * (1.0f / Psurvival); //the cosTheta() of the attenuation of the rendering equation gets simplified with the cosTheta of the &quot;prob&quot;&#xD;&#xA;			//the PI of the prob gets simplified with the BRDF where we are using the ideal BRDF = diffuse/PI&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;	return color;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;EDIT 6: Trichoplax was right, I had a problem calculating the **distanceFromObject** and **distanceFromLight**. After solving this, we realized that some sort of shadows appeared (shown in one of the images above). He then suggested that such a broad light might have been washing out the shadows, and so it was. By reducing the light size and by using a high amount of SPP we realized that shadows are there and visibile: https://i.stack.imgur.com/Eez7y.jpg . As a drawback tho, way less rays reach the light, giving back an image with high noise, but this is another kind of problem and I created another question for it. Thanks to @trichoplax and @julien for their help&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HNOah.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/QHG2z.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hiqEY.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/JvGhf.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/8aYPH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/ohZJu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5448" PostHistoryTypeId="2" PostId="2322" RevisionGUID="f5775cc1-48f3-4346-a866-41d2e42621c4" CreationDate="2016-04-17T17:40:13.913" UserId="196" Text="The Russian roulette technique itself is a way of terminating paths without introducing systemic bias. The principle is fairly straightforward: if at a particular vertex you have a 10% chance of arbitrarily replacing the energy with 0, and if you do that an infinite number of times, you will see 10% less energy. The energy boost just compensates for that. If you did not compensate for the energy lost due to path termination, then Russian roulette would be biased, but the whole technique is a useful method of avoiding bias.&#xD;&#xA;&#xD;&#xA;If I was an adversary looking to prove that the &quot;terminate paths whose contribution is less than some small fixed value&quot; technique is biased, I would construct a scene with lights so dim that the contributing paths are _always_ less than that value. Perhaps I'm simulating a low-light camera.&#xD;&#xA;&#xD;&#xA;But of course you could always expose the fixed value as a tweakable parameter to the user, so they can drop it even further if their scene happens to be low-light. So let's disregard that example for a minute.&#xD;&#xA;&#xD;&#xA;What happens if I consider an object that is illuminated by a lot of very low-energy paths that are collected by a [parabolic reflector][1]? Low energy paths don't _necessarily_ bounce around indiscriminately in a manner that you can completely neglect. Similarly reasoning applies for, e.g., cutting off paths after a fixed number of bounces: you can construct a scene with a path that bounces off a series of 20 mirrors before hitting an object.&#xD;&#xA;&#xD;&#xA;Another way of looking at it: if you set the contribution of a path to 0 after it falls below some fixed epsilon, how do you correct for that energy loss? You aren't simply reducing the total energy by some fraction. You don't know anything about how much energy you are neglecting, because you are cutting off at some _contribution_ threshold before you know the other factor: the incident energy.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Parabolic_reflector" ContentLicense="CC BY-SA 3.0" />
  <row Id="5449" PostHistoryTypeId="2" PostId="2323" RevisionGUID="a88b83c3-7428-46ca-89e9-167d47ada36c" CreationDate="2016-04-17T18:17:05.423" UserId="196" Text="The near clipping plane is a fundamental feature of projective rasterization. To borrow a diagram from Eric Lengyel's [Projection Matrix Tricks][2] presentation:&#xD;&#xA;&#xD;&#xA;[![Diagram of camera space to NDC transform][1]][1]&#xD;&#xA;&#xD;&#xA;The displayed region of clip space (that you can think of rasterization as happening in) is a box which has a &quot;near&quot; face. This is associated with the near clip plane. But we can push the far clip plane out to infinity, so can we pull the near clip plane in to zero?&#xD;&#xA;&#xD;&#xA;Mathematically, you absolutely can! The only point that presents a problem is the eye itself: you can get infinitely close to the eye and still resolve to a single point in clip space. However, if you have a triangle that passes through the eye, you still need to clip it, and to clip it you need an actual plane, not a concept like &quot;infinitely close to the eye.&quot;&#xD;&#xA;&#xD;&#xA;More critically for the current rasterization pipeline, the perspective divide does fun things with numerical precision. See the line at 0 in the diagram above? It's halfway through the viewing volume in clip space, but not at all near halfway through the view frustum in camera space. In fact, its position depends on the near clip plane's distance to the eye! This means that over half of the depth range in clip space is in that region near the eye. As you get the near clip plane closer and closer to the eye, that plane pulls in even closer and you waste more and more depth range. This isn't necessarily fundamental—you don't have to store z/w in the depth buffer—but it is convenient. Here's an [article from Nathan Reed][3] about depth precision, and a few notes about [why the projected z/w depth is useful][4] from Emil Persson.&#xD;&#xA;&#xD;&#xA;Finally, I'll plug [a post in the excellent &quot;A trip through the Graphics Pipeline&quot;][5] series, which is very interesting and references homogeneous rasterization algorithms which, in theory, could avoid the need to do clipping in projected clip space, which would totally avoid some of these traps.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wd9gx.png&#xD;&#xA;  [2]: http://www.terathon.com/gdc07_lengyel.pdf&#xD;&#xA;  [3]: https://developer.nvidia.com/content/depth-precision-visualized&#xD;&#xA;  [4]: http://www.humus.name/index.php?ID=255&#xD;&#xA;  [5]: https://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5450" PostHistoryTypeId="2" PostId="2324" RevisionGUID="31910663-daaf-4ffd-a4ee-3d4d7f8c8b11" CreationDate="2016-04-17T18:31:13.193" UserId="3153" Text="So I have a vector of glm::vec3 containing the triangles for the classic Cornell Box called triangles. The Draw method casts a ray for each pixel on the screen and calls ClosestIntersection which returns true or false and updates a struct containing things like colour and the point of that intersection. Then I simply draw the pixels based on the colours (black for no intersection). &#xD;&#xA;&#xD;&#xA;The result is very inconsistent and I can't find the error:&#xD;&#xA;http://imgur.com/nQlyeC4&#xD;&#xA;&#xD;&#xA;    void Draw()&#xD;&#xA;    {&#xD;&#xA;	    if (SDL_MUSTLOCK(screen))&#xD;&#xA;		    SDL_LockSurface(screen);&#xD;&#xA;&#xD;&#xA;	    // Loop through each pixel and cast ray&#xD;&#xA;	    for (int y = 0; y&lt;SCREEN_HEIGHT; ++y)&#xD;&#xA;	    {&#xD;&#xA;		    for (int x = 0; x&lt;SCREEN_WIDTH; ++x)&#xD;&#xA;		    {&#xD;&#xA;		    	vec3 dir(x - SCREEN_WIDTH / 2, y - SCREEN_HEIGHT / 2, focalLength);&#xD;&#xA;		    	Intersection isect;&#xD;&#xA;		    	if (ClosestIntersection(cameraPos, dir, triangles, isect))&#xD;&#xA;			    {&#xD;&#xA;			    	vec3 color = triangles[isect.triangleIndex].color;&#xD;&#xA;			    	PutPixelSDL(screen, x, y, color);&#xD;&#xA;			    }&#xD;&#xA;			    else&#xD;&#xA;			    {&#xD;&#xA;				    PutPixelSDL(screen, x, y, vec3(1, 1, 1));&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;	    }&#xD;&#xA;&#xD;&#xA;	    if (SDL_MUSTLOCK(screen))&#xD;&#xA;		    SDL_UnlockSurface(screen);&#xD;&#xA;&#xD;&#xA;	    SDL_UpdateRect(screen, 0, 0, 0, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is the function called from Draw:&#xD;&#xA;&#xD;&#xA;    bool ClosestIntersection(vec3 start,&#xD;&#xA;        vec3 dir,&#xD;&#xA;        const vector&lt;Triangle&gt;&amp; triangles,&#xD;&#xA;        Intersection&amp; closestIntersection)&#xD;&#xA;    {&#xD;&#xA;	    bool foundIntersection = false;&#xD;&#xA;&#xD;&#xA;	    // Loop through all the triangles and check for intersection with ray&#xD;&#xA;	    for (size_t i = 0; i &lt; triangles.size(); i++)&#xD;&#xA;	    {&#xD;&#xA;		    vec3 v0 = triangles[i].v0;&#xD;&#xA;		    vec3 v1 = triangles[i].v1;&#xD;&#xA;		    vec3 v2 = triangles[i].v2;&#xD;&#xA;		    vec3 e1 = v1 - v0;&#xD;&#xA;		    vec3 e2 = v2 - v0;&#xD;&#xA;		    vec3 b = start - v0;&#xD;&#xA;		    mat3 A(-dir, e1, e2);&#xD;&#xA;		    vec3 x = glm::inverse(A) * b;&#xD;&#xA;&#xD;&#xA;		    // Check that found scalars are within bounds&#xD;&#xA;		    if ((x.x &gt;= 0) &amp;&amp; (x.y &gt; 0) &amp;&amp; (x.z &gt; 0) &amp;&amp; (x.y + x.z &lt; 1))&#xD;&#xA;		    {&#xD;&#xA;			    if (foundIntersection)	// If there's a previvous intersection for this ray check that new one is closer to camera&#xD;&#xA;			    {&#xD;&#xA;				    if (glm::distance(start, x) &lt; closestIntersection.distance)&#xD;&#xA;				    {&#xD;&#xA;					    closestIntersection.distance = glm::distance(start, x);&#xD;&#xA;					    closestIntersection.triangleIndex = i;&#xD;&#xA;					    closestIntersection.position = x;&#xD;&#xA;				    }&#xD;&#xA;			    }&#xD;&#xA;			    else&#xD;&#xA;			    {&#xD;&#xA;				    foundIntersection = true;&#xD;&#xA;				    closestIntersection.distance = glm::distance(start, x);&#xD;&#xA;				    closestIntersection.triangleIndex = i;&#xD;&#xA;				    closestIntersection.position = x;&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;	    }&#xD;&#xA;	    return foundIntersection;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="5451" PostHistoryTypeId="1" PostId="2324" RevisionGUID="31910663-daaf-4ffd-a4ee-3d4d7f8c8b11" CreationDate="2016-04-17T18:31:13.193" UserId="3153" Text="Ray-tracing the Cornell Box results in really inconsistent image" ContentLicense="CC BY-SA 3.0" />
  <row Id="5452" PostHistoryTypeId="3" PostId="2324" RevisionGUID="31910663-daaf-4ffd-a4ee-3d4d7f8c8b11" CreationDate="2016-04-17T18:31:13.193" UserId="3153" Text="|raytracing|c++|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5453" PostHistoryTypeId="2" PostId="2325" RevisionGUID="5f6cfffd-9077-4456-a77f-86198f75189b" CreationDate="2016-04-17T18:59:48.360" UserId="310" Text="In order to understand Russian Roulette, let's look at a very basic forward path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely unbiased, bounces *should* go to infinity. But this is unrealistic, and as you noted, not necessary. For most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.&#xD;&#xA;&#xD;&#xA;So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.&#xD;&#xA;&#xD;&#xA;That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20. &#xD;&#xA;[![2 Bounces from Disney's Big Hero 6][1]][1]&#xD;&#xA;[![9 Bounces from Disney's Big Hero 6][2]][2]&#xD;&#xA;&#xD;&#xA;If we choose too low, the image will be visibly biased. But if we choose to high, we're wasting computation energy and time.&#xD;&#xA;&#xD;&#xA;One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias. &#xD;&#xA;&#xD;&#xA;Clamping after a threshold, will *work*, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.&#xD;&#xA;&#xD;&#xA;Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            // Randomly terminate a path with a probability inversely equal to the throughput&#xD;&#xA;            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;            if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // Add the energy we 'lose' by randomly terminating paths&#xD;&#xA;            throughput *= 1 / p;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So path with low throughput that won't contribute much to the scene are more likely to be terminated. &#xD;&#xA;&#xD;&#xA;If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last questions:&#xD;&#xA;&#xD;&#xA; 1. Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?&#xD;&#xA;   - If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still biased. To be completely unbiased, it must be random.&#xD;&#xA; 2. If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;   - Russian Roulette only stops the bouncing. It doesn't remove the negate the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason *not* to use it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ikXSo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BPiZ7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5454" PostHistoryTypeId="5" PostId="2325" RevisionGUID="5dc2cc07-24e1-46b5-8a8e-45858758bc2b" CreationDate="2016-04-17T19:10:53.160" UserId="310" Comment="Clarify it as &quot;visually&quot; necessary" Text="In order to understand Russian Roulette, let's look at a very basic forward path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely mathematically unbiased, bounces *should* go to infinity. But this is unrealistic, and as you noted, not visually necessary; for most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.&#xD;&#xA;&#xD;&#xA;So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.&#xD;&#xA;&#xD;&#xA;That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20. &#xD;&#xA;[![2 Bounces from Disney's Big Hero 6][1]][1]&#xD;&#xA;[![9 Bounces from Disney's Big Hero 6][2]][2]&#xD;&#xA;&#xD;&#xA;If we choose too low, the image will be visibly biased. But if we choose to high, we're wasting computation energy and time.&#xD;&#xA;&#xD;&#xA;One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias. &#xD;&#xA;&#xD;&#xA;Clamping after a threshold, will *work*, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.&#xD;&#xA;&#xD;&#xA;Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            // Randomly terminate a path with a probability inversely equal to the throughput&#xD;&#xA;            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;            if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // Add the energy we 'lose' by randomly terminating paths&#xD;&#xA;            throughput *= 1 / p;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So path with low throughput that won't contribute much to the scene are more likely to be terminated. &#xD;&#xA;&#xD;&#xA;If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last questions:&#xD;&#xA;&#xD;&#xA; 1. Does Russian Roulette give an unbiased result?&#xD;&#xA;   - Yes&#xD;&#xA; 2. Is Russian Roulette necessary for an unbiased result?&#xD;&#xA;   - Depends on what you mean by unbiased. If you mean mathematically, then yes. However, if you mean visually, then no. You just have to choose you max path depth and cutoff threshold very very carefully. This can be very tedious since it can change from scene to scene.&#xD;&#xA; 3. Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?&#xD;&#xA;   - If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still mathematically biased. To be completely unbiased, it must be random.&#xD;&#xA; 4. If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;   - Russian Roulette only stops the bouncing. It doesn't remove the negate the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason *not* to use it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ikXSo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BPiZ7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5455" PostHistoryTypeId="5" PostId="2323" RevisionGUID="e31878f0-9dbe-4093-858a-63e72956fab5" CreationDate="2016-04-17T19:31:05.250" UserId="196" Comment="clarification" Text="The near clipping plane is a fundamental feature of projective rasterization. To borrow a diagram from Eric Lengyel's [Projection Matrix Tricks][2] presentation:&#xD;&#xA;&#xD;&#xA;[![Diagram of camera space to NDC transform][1]][1]&#xD;&#xA;&#xD;&#xA;The displayed region of clip space (that you can think of rasterization as happening in) is a box which has a &quot;near&quot; face. This is associated with the near clip plane. But we can push the far clip plane out to infinity, so can we pull the near clip plane in to zero?&#xD;&#xA;&#xD;&#xA;Mathematically, you absolutely can! The only point that presents a problem is the eye itself: you can get infinitely close to the eye and still resolve to a single point in clip space. However, if you have a triangle that passes through the eye, you still need to clip it, and to clip it you need an actual plane, not a concept like &quot;infinitely close to the eye.&quot;&#xD;&#xA;&#xD;&#xA;More critically for the current rasterization pipeline, the perspective divide does fun things with numerical precision. See the line at NDC 0 in the diagram above? It's halfway through the viewing volume in clip space, but not at all near halfway through the view frustum in camera space. In fact, its position depends on the near clip plane's distance to the eye! This means that over half of the depth range in clip space is in that region near the eye. As you get the near clip plane closer and closer to the eye, that plane pulls in even closer and you waste more and more depth range. This isn't necessarily fundamental—you don't have to store z/w in the depth buffer—but it is convenient. Here's an [article from Nathan Reed][3] about depth precision, and a few notes about [why the projected z/w depth is useful][4] from Emil Persson.&#xD;&#xA;&#xD;&#xA;Finally, I'll plug [a post in the excellent &quot;A trip through the Graphics Pipeline&quot;][5] series, which is very interesting and references homogeneous rasterization algorithms which, in theory, could avoid the need to do clipping in projected clip space, which would totally avoid some of these traps.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wd9gx.png&#xD;&#xA;  [2]: http://www.terathon.com/gdc07_lengyel.pdf&#xD;&#xA;  [3]: https://developer.nvidia.com/content/depth-precision-visualized&#xD;&#xA;  [4]: http://www.humus.name/index.php?ID=255&#xD;&#xA;  [5]: https://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5456" PostHistoryTypeId="2" PostId="2326" RevisionGUID="0e6671a8-bc07-4907-80c0-e4a4e280a55d" CreationDate="2016-04-17T23:05:46.197" UserId="3156" Text="I'm interested in virtual reality, but according to some sources, less than 1% of computers in use today have the necessary performance to run modern VR games, granted many of them are not intended for gaming, that's still a huge barrier for the widespread adoption of VR headsets into the market. So I was wondering what could be done to reduce the performance requirements of a VR game that hasn't been implemented with such optimizations in mind.&#xD;&#xA;&#xD;&#xA;I'm talking about technologies like foveated rendering, which (ab)uses the fact that we only ever perceive a few degrees in the center of our field of vision as sharp while everything else is blurry. This can be combined with eye tracking so that only the areas where the player is looking are rendered in full quality, while we can reduce the render quality and therefore the performance requirements everywhere else.&#xD;&#xA;This seems like a great advantage and I honestly wonder why none of the major VR companies have implemented eye tracking into their headsets and foveated rendering into their SDKs into their headsets. The technology exists and I can't imagine that it would add much to the price tag.&#xD;&#xA;[Paper about foveated rendering](http://research.microsoft.com/pubs/176610/foveated_final15.pdf)&#xD;&#xA;	&#xD;&#xA;There's also instanced stereo rendering which basically renders things to both eyes at the same time rather than rendering it for each eye individually.&#xD;&#xA;(I lack the reputation to link images -.-)&#xD;&#xA;[Example gif for Instanced Stero Rendering - Epic Games, Unreal Engine 4.11 release notes](https://docs.unrealengine.com/latest/images/Support/Builds/ReleaseNotes/2016/4_11/image_16.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It's also possible to use just one frustum for both eyes rather than two as discussed here.&#xD;&#xA;[VR and frustum culling](http://computergraphics.stackexchange.com/questions/1736/vr-and-frustum-culling)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But are there other approaches to the performane problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5457" PostHistoryTypeId="1" PostId="2326" RevisionGUID="0e6671a8-bc07-4907-80c0-e4a4e280a55d" CreationDate="2016-04-17T23:05:46.197" UserId="3156" Text="What methods/technologies to reduce required performance for virtual reality are there?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5458" PostHistoryTypeId="3" PostId="2326" RevisionGUID="0e6671a8-bc07-4907-80c0-e4a4e280a55d" CreationDate="2016-04-17T23:05:46.197" UserId="3156" Text="|rendering|performance|optimisation|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5459" PostHistoryTypeId="2" PostId="2327" RevisionGUID="abd544c6-8853-438d-8e1d-8a016aa717c9" CreationDate="2016-04-17T23:24:54.573" UserId="231" Text="# Two symptoms&#xD;&#xA;&#xD;&#xA;There appear to be two problems with the image.&#xD;&#xA;&#xD;&#xA;1. The background is showing through along the line between adjacent triangles.&#xD;&#xA;1. The colour displayed is not always from the closest intersection.&#xD;&#xA;&#xD;&#xA;Note that the background colour is white, rather than black, due to the line:&#xD;&#xA;&#xD;&#xA;                    PutPixelSDL(screen, x, y, vec3(1, 1, 1));&#xD;&#xA;&#xD;&#xA;Why this background shows through at the triangle edges I do not know. However, the second problem is identified below, so I recommend you fix that first and then the first problem can be analysed in isolation without the additional distractions.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Cause of the problem with `ClosestIntersection`&#xD;&#xA;&#xD;&#xA;The `ClosestIntesection` function returns `true` when an intersection is found, and updates an `Intersection` object called `closestIntersection`. However, the intersection stored here is not always the closest to the camera.&#xD;&#xA;&#xD;&#xA;The reason for this is here:&#xD;&#xA;&#xD;&#xA;                    closestIntersection.distance = glm::distance(start, x);&#xD;&#xA;&#xD;&#xA;This appears in two places so it will need to be fixed in both.&#xD;&#xA;&#xD;&#xA;`start` is `cameraPos`, presumably in world coordinates. `x` appears to be in the local coordinates of the triangle being intersected (one of the triangle vertices being the origin). The distance between two points in different coordinate systems is meaningless, so that in different regions of a triangle it will appear to be behind or in front of another triangle for no immediately apparent reason.&#xD;&#xA;&#xD;&#xA;If `x` is first converted to world coordinates then the distance will be correct and the intersection chosen will be the closest to the camera.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5461" PostHistoryTypeId="2" PostId="2328" RevisionGUID="a20a1394-4126-4cf1-b145-45efa29874f5" CreationDate="2016-04-18T04:49:34.327" UserId="182" Text="###A note first&#xD;&#xA;From the look of your screen capture, I suspect there might still be a bug in your code. Noise is to be expected with only 16 spp, but your picture still looks surprisingly dark to me. For comparison, here is what my implementation of SmallPT looks like with 16 spp, 15 bounces, and no next event prediction:&#xD;&#xA;&#xD;&#xA;[![SmallPT, 16 spp, 15 bounces, no next event predicition][1]][1]&#xD;&#xA;([here it is on ShaderToy][2])&#xD;&#xA;&#xD;&#xA;Noisy, but not nearly as dark as your picture. It is very different scene, but considering the that the shape is similar (a box with one side open and only one light source), I would expect to get a similar luminosity/noise appearance.&#xD;&#xA;&#xD;&#xA;_The rest of this answer assumes your code to be correct._&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;##Path tracing and reducing noise&#xD;&#xA;&#xD;&#xA;The balance between light source size, noise and SPP is a classic problem, to which there is no magical solution. From easiest to hardest, you could:&#xD;&#xA;&#xD;&#xA;* Use a scene that is more suitable to your algorithm:&#xD;&#xA;&#xD;&#xA;  Rendering algorithms have limitations, may shine in certain cases and poorly handle other cases. Knowing the limitations of yours, you can choose to restrict its use to a case that works best for it: a large light source, a sky dome, many light sources, a scene with less occlusion, etc.&#xD;&#xA;&#xD;&#xA;* Implement next event prediction:&#xD;&#xA;&#xD;&#xA;  When you know where your light sources are, at each bounce you can try and shoot rays directly toward them. If the ray doesn't hit other geometry first, you get a path that contributes. Since doing so biases the randomness, you will need to use proper factors to take it into account.&#xD;&#xA;&#xD;&#xA;* Implement [Bi-Directional Path Tracing][3]:&#xD;&#xA;&#xD;&#xA;  When tracing rays from the camera, if the light source is small, a large number of paths will never reach it. This is the problem you are having. On the opposite, when tracing rays from the light, many of them will never reach the camera. BDPT consists in first shooting rays both from the camera and from the light source, then trying to connect them. Each pair that can be connected is a contributing path. BDPT will significantly reduce noise.&#xD;&#xA;&#xD;&#xA;* Implement [Metropolis Light Transport][4]:&#xD;&#xA;&#xD;&#xA;  If there is a path between the camera and a light source, it is likely there will be a similar path between them. MLT consists in searching for those contributing paths in the neighborhood of paths that are already known to contribute by mutating them (adding, removing or changing one or more bounces). This is a lot less trivial already, as the math to keep it unbiased gets a bit hairy.&#xD;&#xA;&#xD;&#xA;The problem of reducing noise is still under active research though, and there is no silver bullet. At this point you will need to read what are the latest developments.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zFFjC.png&#xD;&#xA;  [2]: https://www.shadertoy.com/view/4sfGDB&#xD;&#xA;  [3]: http://www.graphics.cornell.edu/~eric/Portugal.html&#xD;&#xA;  [4]: http://graphics.stanford.edu/papers/metro/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5462" PostHistoryTypeId="2" PostId="2329" RevisionGUID="caa00890-9f26-43aa-a112-0945bde3b193" CreationDate="2016-04-18T05:05:56.010" UserId="182" Text="There was some research published recently measuring when users can or cannot tell whether the specular contribution, which is view point dependent, is different between eyes.&#xD;&#xA;&#xD;&#xA;[Perception of Highlight Disparity at a Distance in Consumer Head-Mounted Displays][1]&#xD;&#xA;&#xD;&#xA;In the future, this could be use to share some computation between the two eye renders. Unfortunately this sounds hard to take advantage of in a typical rasterization pipeline.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://software.intel.com/en-us/articles/perception-of-highlight-disparity-at-a-distance-in-consumer-head-mounted-displays" ContentLicense="CC BY-SA 3.0" />
  <row Id="5463" PostHistoryTypeId="5" PostId="2324" RevisionGUID="67c10639-e49e-4a5b-bdae-dbeb16d6e46e" CreationDate="2016-04-18T05:40:09.957" UserId="182" Comment="Embedded the screen capture in the question." Text="So I have a vector of `glm::vec3` containing the triangles for the classic Cornell Box called triangles. The Draw method casts a ray for each pixel on the screen and calls `ClosestIntersection` which returns true or false and updates a struct containing things like colour and the point of that intersection. Then I simply draw the pixels based on the colours (black for no intersection). &#xD;&#xA;&#xD;&#xA;The result is very inconsistent and I can't find the error:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void Draw()&#xD;&#xA;    {&#xD;&#xA;	    if (SDL_MUSTLOCK(screen))&#xD;&#xA;		    SDL_LockSurface(screen);&#xD;&#xA;&#xD;&#xA;	    // Loop through each pixel and cast ray&#xD;&#xA;	    for (int y = 0; y&lt;SCREEN_HEIGHT; ++y)&#xD;&#xA;	    {&#xD;&#xA;		    for (int x = 0; x&lt;SCREEN_WIDTH; ++x)&#xD;&#xA;		    {&#xD;&#xA;		    	vec3 dir(x - SCREEN_WIDTH / 2, y - SCREEN_HEIGHT / 2, focalLength);&#xD;&#xA;		    	Intersection isect;&#xD;&#xA;		    	if (ClosestIntersection(cameraPos, dir, triangles, isect))&#xD;&#xA;			    {&#xD;&#xA;			    	vec3 color = triangles[isect.triangleIndex].color;&#xD;&#xA;			    	PutPixelSDL(screen, x, y, color);&#xD;&#xA;			    }&#xD;&#xA;			    else&#xD;&#xA;			    {&#xD;&#xA;				    PutPixelSDL(screen, x, y, vec3(1, 1, 1));&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;	    }&#xD;&#xA;&#xD;&#xA;	    if (SDL_MUSTLOCK(screen))&#xD;&#xA;		    SDL_UnlockSurface(screen);&#xD;&#xA;&#xD;&#xA;	    SDL_UpdateRect(screen, 0, 0, 0, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is the function called from Draw:&#xD;&#xA;&#xD;&#xA;    bool ClosestIntersection(vec3 start,&#xD;&#xA;        vec3 dir,&#xD;&#xA;        const vector&lt;Triangle&gt;&amp; triangles,&#xD;&#xA;        Intersection&amp; closestIntersection)&#xD;&#xA;    {&#xD;&#xA;	    bool foundIntersection = false;&#xD;&#xA;&#xD;&#xA;	    // Loop through all the triangles and check for intersection with ray&#xD;&#xA;	    for (size_t i = 0; i &lt; triangles.size(); i++)&#xD;&#xA;	    {&#xD;&#xA;		    vec3 v0 = triangles[i].v0;&#xD;&#xA;		    vec3 v1 = triangles[i].v1;&#xD;&#xA;		    vec3 v2 = triangles[i].v2;&#xD;&#xA;		    vec3 e1 = v1 - v0;&#xD;&#xA;		    vec3 e2 = v2 - v0;&#xD;&#xA;		    vec3 b = start - v0;&#xD;&#xA;		    mat3 A(-dir, e1, e2);&#xD;&#xA;		    vec3 x = glm::inverse(A) * b;&#xD;&#xA;&#xD;&#xA;		    // Check that found scalars are within bounds&#xD;&#xA;		    if ((x.x &gt;= 0) &amp;&amp; (x.y &gt; 0) &amp;&amp; (x.z &gt; 0) &amp;&amp; (x.y + x.z &lt; 1))&#xD;&#xA;		    {&#xD;&#xA;			    if (foundIntersection)	// If there's a previvous intersection for this ray check that new one is closer to camera&#xD;&#xA;			    {&#xD;&#xA;				    if (glm::distance(start, x) &lt; closestIntersection.distance)&#xD;&#xA;				    {&#xD;&#xA;					    closestIntersection.distance = glm::distance(start, x);&#xD;&#xA;					    closestIntersection.triangleIndex = i;&#xD;&#xA;					    closestIntersection.position = x;&#xD;&#xA;				    }&#xD;&#xA;			    }&#xD;&#xA;			    else&#xD;&#xA;			    {&#xD;&#xA;				    foundIntersection = true;&#xD;&#xA;				    closestIntersection.distance = glm::distance(start, x);&#xD;&#xA;				    closestIntersection.triangleIndex = i;&#xD;&#xA;				    closestIntersection.position = x;&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;	    }&#xD;&#xA;	    return foundIntersection;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/L1UbK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5464" PostHistoryTypeId="2" PostId="2330" RevisionGUID="6409cfd4-df1b-476d-966f-d29003ada97e" CreationDate="2016-04-18T07:56:36.613" UserId="2817" Text="Alex Vlachos from Valve has had two great GDC talks about this:&#xD;&#xA;&#xD;&#xA; - [the one from 2015][1]&#xD;&#xA; - [the one from 2016][2]&#xD;&#xA;&#xD;&#xA;Other than that (and what you have linked yourself), there isn't much left to do than to simply optimize your app until you spend at most 10 ms per frame (100 Hz, targeting a 90 Hz display + margin). Standard rendering optimizations apply. Apply a technique, profile, determine its impact on performance, rinse, repeat.&#xD;&#xA;&#xD;&#xA;You may also exercise caution with that UE4 stereo instancing from Epic. In my experience, its performance boost depends heavily on the game's rendering workload. I had a statically lit game with lots of instanced foliage and this feature has actually been a net loss, probably due to the overhead of left/right eye dynamic branching in the shaders; while a fully dynamically-lit scene may benefit from it all right. As I said before: profile to ensure that a technique actually helps performance.&#xD;&#xA;&#xD;&#xA;  [1]: http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf&#xD;&#xA;  [2]: http://www.gdcvault.com/play/1021771/Advanced-VR" ContentLicense="CC BY-SA 3.0" />
  <row Id="5465" PostHistoryTypeId="2" PostId="2331" RevisionGUID="c2055ee6-318d-4605-b02e-d83052fa3047" CreationDate="2016-04-18T07:59:10.987" UserId="110" Text="In [Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs](https://hal.inria.fr/hal-01024289/document), Eric Heitz derives the Separable Masking and Shadowing function as (P.83-84):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the mentioned [Microfacet Models for Refraction through Rough Surfaces](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf) by Walter et al., Smith term is computed as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I don't see a parameterisation of Λ that could make appear the generic form (Heitz version) from the specific form derived by Walter. What am I missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1F17w.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Sxwgo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5466" PostHistoryTypeId="1" PostId="2331" RevisionGUID="c2055ee6-318d-4605-b02e-d83052fa3047" CreationDate="2016-04-18T07:59:10.987" UserId="110" Text="Why G1 term has 2 in numerator in Walter's formula, but not in Heitz's generalized formula?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5467" PostHistoryTypeId="3" PostId="2331" RevisionGUID="c2055ee6-318d-4605-b02e-d83052fa3047" CreationDate="2016-04-18T07:59:10.987" UserId="110" Text="|function|masking|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5468" PostHistoryTypeId="2" PostId="2332" RevisionGUID="c44b540b-0b3f-423c-a069-f797e2045476" CreationDate="2016-04-18T08:53:27.960" UserId="2383" Text="Suppose i have a image and I want to convert the portion of image that is red to blue(or any other color). One way to do this is extract red part of image using HSV or other color values and convert red hsv value to corresponding blue. Is there any other methods(better) for this. What sort of algorithms do Photoshop color replacement tool use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5469" PostHistoryTypeId="1" PostId="2332" RevisionGUID="c44b540b-0b3f-423c-a069-f797e2045476" CreationDate="2016-04-18T08:53:27.960" UserId="2383" Text="Change particular color in an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="5470" PostHistoryTypeId="3" PostId="2332" RevisionGUID="c44b540b-0b3f-423c-a069-f797e2045476" CreationDate="2016-04-18T08:53:27.960" UserId="2383" Text="|color|color-science|color-management|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5471" PostHistoryTypeId="2" PostId="2333" RevisionGUID="58861089-af77-48e8-abe1-c4d232eda334" CreationDate="2016-04-18T08:58:40.510" UserId="110" Text="Actually I just had to solve the following equation to find a solution, not inconsistent with the presence of the &quot;2&quot; in the numerator:&#xD;&#xA;&#xD;&#xA;$\frac{1}{1+\Lambda (m)}=\frac{2}{1+\sqrt{1+\alpha ^{2}tan_{2}\theta_{m} }}$&#xD;&#xA;&#xD;&#xA;$1+\Lambda (m)=\frac{1+\sqrt{1+\alpha ^{2}tan_{2}\theta_{m} }}{2}$&#xD;&#xA;&#xD;&#xA;$\Lambda (m)=\frac{-1+\sqrt{1+\alpha ^{2}tan_{2}\theta_{m} }}{2}$" ContentLicense="CC BY-SA 3.0" />
  <row Id="5472" PostHistoryTypeId="5" PostId="2333" RevisionGUID="47bd9b31-e6ce-45a2-aa6b-a1a429d2cbad" CreationDate="2016-04-18T10:21:12.167" UserId="110" Comment="deleted 6 characters in body" Text="Actually I just had to solve the following equation to find a solution, consistent with the presence of the &quot;2&quot; in the numerator:&#xD;&#xA;&#xD;&#xA;$\frac{1}{1+\Lambda (m)}=\frac{2}{1+\sqrt{1+\alpha ^{2}tan_{2}\theta_{m} }}$&#xD;&#xA;&#xD;&#xA;$1+\Lambda (m)=\frac{1+\sqrt{1+\alpha ^{2}tan_{2}\theta_{m} }}{2}$&#xD;&#xA;&#xD;&#xA;$\Lambda (m)=\frac{-1+\sqrt{1+\alpha ^{2}tan_{2}\theta_{m} }}{2}$" ContentLicense="CC BY-SA 3.0" />
  <row Id="5473" PostHistoryTypeId="4" PostId="2331" RevisionGUID="3f5f6e73-a890-4f45-8463-6ed9e39e8e52" CreationDate="2016-04-18T13:51:41.537" UserId="231" Comment="Clarify title" Text="Why does the G1 term have a 2 in the numerator in Walter's formula, but not in Heitz's generalized formula?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5474" PostHistoryTypeId="2" PostId="2334" RevisionGUID="86b40119-199f-48bd-b6c8-5764a144f1c7" CreationDate="2016-04-18T14:39:31.007" UserId="3128" Text="Assuming you are looking to transform a particular component (r, g or b) of any color, this can be easily done by simple vector/matrix multiplication.&#xD;&#xA;&#xD;&#xA;The introduction on this page (Chapter 6.1) - from the most excellent immersivemath.com site - illustrates this perfectly:&#xD;&#xA;http://immersivemath.com/ila/ch06_matrices/ch06.html&#xD;&#xA;&#xD;&#xA;Think of it as the &quot;Channel Mixer&quot; command in PhotoShop." ContentLicense="CC BY-SA 3.0" />
  <row Id="5476" PostHistoryTypeId="5" PostId="2326" RevisionGUID="e4aff83b-db8c-470c-b540-91066f149b3f" CreationDate="2016-04-18T20:32:32.223" UserId="3156" Comment="deleted 43 characters in body" Text="I'm interested in virtual reality, but according to some sources, less than 1% of computers in use today have the necessary performance to run modern VR games, granted many of them are not intended for gaming, that's still a huge barrier for the widespread adoption of VR headsets into the market. So I was wondering what could be done to reduce the performance requirements of a VR game that hasn't been implemented with such optimizations in mind.&#xD;&#xA;&#xD;&#xA;I'm talking about technologies like foveated rendering, which (ab)uses the fact that we only ever perceive a few degrees in the center of our field of vision as sharp while everything else is blurry. This can be combined with eye tracking so that only the areas where the player is looking are rendered in full quality, while we can reduce the render quality and therefore the performance requirements everywhere else.&#xD;&#xA;This seems like a great advantage and I honestly wonder why none of the major VR companies have implemented eye tracking into their headsets and foveated rendering into their SDKs into their headsets. The technology exists and I can't imagine that it would add much to the price tag.&#xD;&#xA;[Paper about foveated rendering](http://research.microsoft.com/pubs/176610/foveated_final15.pdf)&#xD;&#xA;	&#xD;&#xA;There's also instanced stereo rendering which basically renders things to both eyes at the same time rather than rendering it for each eye individually.&#xD;&#xA;![Example gif for Instanced Stero Rendering - Epic Games, Unreal Engine 4.11 release notes](https://docs.unrealengine.com/latest/images/Support/Builds/ReleaseNotes/2016/4_11/image_16.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It's also possible to use just one frustum for both eyes rather than two as discussed here.&#xD;&#xA;[VR and frustum culling](http://computergraphics.stackexchange.com/questions/1736/vr-and-frustum-culling)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But are there other approaches to the performane problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5481" PostHistoryTypeId="2" PostId="2336" RevisionGUID="3a2cbe0c-49bd-45e7-9570-5afbf930312e" CreationDate="2016-04-19T08:12:14.370" UserId="182" Text="When I saw an implementation of normal mapping that computed the *TBN matrix* in the vertex shader and converted everything (in particular the view vector and light vector) to tangent space at that stage, it seemed like the proper way to do. This way there is no matrix-vector multiplication left to do in the fragment shader.&#xD;&#xA;&#xD;&#xA;Enters image based lighting: for each fragment we want to fetch from an image, typically one or more cube map textures, the light intensity coming from certain directions. I assume this data is in world space.&#xD;&#xA;&#xD;&#xA;My question is: is it possible to use IBL while retaining the vertex shader transform optimization mentioned above?&#xD;&#xA;&#xD;&#xA; - It seems to me we still need to transform our fetch direction from tangent space to world space (or whichever space the cube map is in).&#xD;&#xA; - Conversely, if we want to work in world space, like with deferred shading, we need to transform the normal for each fragment.&#xD;&#xA;&#xD;&#xA;Does IBL necessarily imply at least one matrix vector multiplication per fragment and the optimization I mentioned is an uncommon case, or am I missing something?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5482" PostHistoryTypeId="1" PostId="2336" RevisionGUID="3a2cbe0c-49bd-45e7-9570-5afbf930312e" CreationDate="2016-04-19T08:12:14.370" UserId="182" Text="Image based lighting, tangent space coordinates, and optimization" ContentLicense="CC BY-SA 3.0" />
  <row Id="5483" PostHistoryTypeId="3" PostId="2336" RevisionGUID="3a2cbe0c-49bd-45e7-9570-5afbf930312e" CreationDate="2016-04-19T08:12:14.370" UserId="182" Text="|optimisation|matrix|ibl|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5484" PostHistoryTypeId="5" PostId="2334" RevisionGUID="a40242ec-6552-4db5-bd83-1253bf1246ee" CreationDate="2016-04-19T08:18:04.490" UserId="3128" Comment="added 394 characters in body" Text="Assuming you are looking to transform a particular component (r, g or b) of any color, this can be easily done by simple vector/matrix multiplication.&#xD;&#xA;&#xD;&#xA;The introduction on this page (Chapter 6.1) - from the most excellent immersivemath.com site - illustrates this perfectly:&#xD;&#xA;http://immersivemath.com/ila/ch06_matrices/ch06.html&#xD;&#xA;&#xD;&#xA;Think of it as the &quot;Channel Mixer&quot; command in PhotoShop.&#xD;&#xA;&#xD;&#xA;**edit**&#xD;&#xA;&#xD;&#xA;What I described above is one of many ways of changing a given color. The PS Color Replacement Tool simply applies that to any pixel that matches certain conditions defined by the user (source color, destination color, tolerance, etc...). The nifty thing they did is put it in the form of a brush tool, allowing the user artistic control over where to apply the color transform." ContentLicense="CC BY-SA 3.0" />
  <row Id="5485" PostHistoryTypeId="5" PostId="2334" RevisionGUID="1c941d15-9bc7-4f8d-90e9-598979969d0d" CreationDate="2016-04-19T08:30:39.597" UserId="3128" Comment="added 394 characters in body" Text="Assuming you are looking to transform a particular component (r, g or b) of any color, this can be easily done by simple vector/matrix multiplication.&#xD;&#xA;&#xD;&#xA;The introduction on this page (Chapter 6.1) - from the most excellent immersivemath.com site - illustrates this perfectly:&#xD;&#xA;http://immersivemath.com/ila/ch06_matrices/ch06.html&#xD;&#xA;&#xD;&#xA;Think of it as the &quot;Channel Mixer&quot; command in PhotoShop.&#xD;&#xA;&#xD;&#xA;**edit**&#xD;&#xA;&#xD;&#xA;What I described above is one of many ways of changing a given color. The PS Color Replacement Tool simply applies that to any pixel that matches certain conditions defined by the user (source color, destination color, tolerance, etc...). The nifty thing they did is put it in the form of a brush tool, allowing the user artistic control over where to apply the color transform.&#xD;&#xA;&#xD;&#xA;Basically it boils down to this: if a pixel under the brush matches the conditions set by the user the color transform is applied. If not, leave the pixel as is." ContentLicense="CC BY-SA 3.0" />
  <row Id="5486" PostHistoryTypeId="2" PostId="2337" RevisionGUID="b55ae8a5-f2aa-4e05-bdff-9007a3fe99e1" CreationDate="2016-04-19T09:07:32.807" UserId="361" Text="The GL Transmission Format comes along with a JSON styled main file which basicly describes the scene and binary files which contain the buffers.&#xD;&#xA;&#xD;&#xA;[![gltf basic structure][1]][1]&#xD;&#xA;&#xD;&#xA;I'm currently writing a WebGL library and I need to work alot with the vertex and index buffers. So, my question now is:&#xD;&#xA;&#xD;&#xA;Would it be possible to store plain text array buffers in the gltf (e.g., as JSON) instead of generating binary blobs always when the buffers are adjusted?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RtFrg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5487" PostHistoryTypeId="1" PostId="2337" RevisionGUID="b55ae8a5-f2aa-4e05-bdff-9007a3fe99e1" CreationDate="2016-04-19T09:07:32.807" UserId="361" Text="Is it possible to store the plain buffer data in gltf files?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5488" PostHistoryTypeId="3" PostId="2337" RevisionGUID="b55ae8a5-f2aa-4e05-bdff-9007a3fe99e1" CreationDate="2016-04-19T09:07:32.807" UserId="361" Text="|webgl|data-structure|vertex-buffer-object|gltf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5489" PostHistoryTypeId="6" PostId="1934" RevisionGUID="0169206e-6164-4802-a150-ec73f8b255dc" CreationDate="2016-04-19T09:08:55.813" UserId="361" Comment="edited tags" Text="|webgl|vertex-buffer-object|gltf|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5490" PostHistoryTypeId="6" PostId="416" RevisionGUID="6439578c-998b-4491-ad73-16259d3ecae7" CreationDate="2016-04-19T09:09:34.377" UserId="361" Comment="edited tags" Text="|webgl|vertex-buffer-object|data-structure|gltf|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5491" PostHistoryTypeId="2" PostId="2338" RevisionGUID="fd1674a8-dbcd-4264-8f1c-3c4f320233ab" CreationDate="2016-04-19T09:18:40.673" UserId="361" Text="I'm looking for any low level tools (e.g., C, C++, Rust) which enable me to quickly generate gltf files including the conversion of plain array buffers (vertex, index, color, etc.) into binary (bgltf, glb, bin) files.&#xD;&#xA;&#xD;&#xA;I'm asking because it currently looks like there are only high level applications like Maya, Blender available which can do that or converters to indirectly write glTF from COLLADA.&#xD;&#xA;&#xD;&#xA;Are there any low level tools to generate binary gltf array buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5492" PostHistoryTypeId="1" PostId="2338" RevisionGUID="fd1674a8-dbcd-4264-8f1c-3c4f320233ab" CreationDate="2016-04-19T09:18:40.673" UserId="361" Text="Are there any low level tools to generate binary gltf array buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5493" PostHistoryTypeId="3" PostId="2338" RevisionGUID="fd1674a8-dbcd-4264-8f1c-3c4f320233ab" CreationDate="2016-04-19T09:18:40.673" UserId="361" Text="|data-structure|gltf|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5494" PostHistoryTypeId="2" PostId="2339" RevisionGUID="2cd059bf-a676-4aa8-acd8-858a55745f61" CreationDate="2016-04-19T09:40:01.340" UserId="137" Text="Embedding human readable data is not supported. However you can put the data into a [data uri][1] to store the data inline in base64 format.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &quot;buffers&quot;: {&#xD;&#xA;        &quot;a-buffer-id&quot;: {&#xD;&#xA;            &quot;byteLength&quot;: 1024,&#xD;&#xA;            &quot;type&quot;: &quot;arraybuffer&quot;,&#xD;&#xA;            &quot;uri&quot;=&quot;data:application/octet-stream;base64,...&quot;&#xD;&#xA;        }&#xD;&#xA;    },&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://tools.ietf.org/html/rfc2397&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5495" PostHistoryTypeId="2" PostId="2340" RevisionGUID="cc39de33-a698-4c03-af76-23280844263a" CreationDate="2016-04-19T09:53:41.033" UserId="137" Text="Technically any file format where you can dump the entire file into a VBO and then render from that will work for the .bin files. Unfortunately those formats are less well known than they should be.&#xD;&#xA;&#xD;&#xA;Then you only need to adjust the bufferview elements to reference the proper subset of the file" ContentLicense="CC BY-SA 3.0" />
  <row Id="5496" PostHistoryTypeId="2" PostId="2341" RevisionGUID="6a57c3ca-0ded-403b-adff-ce3a1991a7f3" CreationDate="2016-04-19T12:00:41.240" UserId="2372" Text="Here is an interesting answer from Styves on gamedev.net : **[How could I use bent normal map][1]**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.gamedev.net/topic/678008-how-could-i-use-bent-normal-map/?view=findpost&amp;p=5287363" ContentLicense="CC BY-SA 3.0" />
  <row Id="5497" PostHistoryTypeId="2" PostId="2342" RevisionGUID="565a675a-3298-4d91-b016-4743d5a449eb" CreationDate="2016-04-19T12:20:54.443" UserId="2372" Text="I am trying to blend two world space normals inside a shader. One comes from a tangent space normal map converted into world space using a classic TBN matrix and the other one is a mesh normal map in world space.&#xD;&#xA;&#xD;&#xA;I found some interesting resources here :&#xD;&#xA;&#xD;&#xA; - [Blending in Detail][1]&#xD;&#xA; - [Shadertoy - Normal Map Blending][2]&#xD;&#xA;&#xD;&#xA;But those blending technics seem to be only available for tangent space normals, especially the Reoriented Normal Mapping (RNM).&#xD;&#xA;I tried to apply the RNM technic with unpack already done.&#xD;&#xA;&#xD;&#xA;    n1 += vec3(0, 0, 1);&#xD;&#xA;	n2 *= vec3(-1, -1, 1);&#xD;&#xA;	&#xD;&#xA;    return n1*dot(n1, n2)/n1.z - n2;&#xD;&#xA;&#xD;&#xA;But this doesn't give expected results and I don't get why. Is there a way to apply the RNM blending on world space normals ?&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/blending-in-detail/&#xD;&#xA;  [2]: https://www.shadertoy.com/view/4t2SzR#" ContentLicense="CC BY-SA 3.0" />
  <row Id="5498" PostHistoryTypeId="1" PostId="2342" RevisionGUID="565a675a-3298-4d91-b016-4743d5a449eb" CreationDate="2016-04-19T12:20:54.443" UserId="2372" Text="How to blend World Space Normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="5499" PostHistoryTypeId="3" PostId="2342" RevisionGUID="565a675a-3298-4d91-b016-4743d5a449eb" CreationDate="2016-04-19T12:20:54.443" UserId="2372" Text="|opengl|rendering|shader|texture|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5500" PostHistoryTypeId="5" PostId="2342" RevisionGUID="9516f6da-415f-405b-8668-c6b8324fbe53" CreationDate="2016-04-19T12:42:58.227" UserId="2372" Comment="added 4 characters in body" Text="I am trying to blend two world space normals inside a shader. One comes from a tangent space normal map converted into world space using a classic TBN matrix and the other one is a mesh normal map in world space.&#xD;&#xA;&#xD;&#xA;I found some interesting resources here :&#xD;&#xA;&#xD;&#xA; - [Blending in Detail][1]&#xD;&#xA; - [Shadertoy - Normal Map Blending][2]&#xD;&#xA;&#xD;&#xA;But those blending technics seem to be only available for tangent space normals, especially the Reoriented Normal Mapping (RNM).&#xD;&#xA;I tried to apply the RNM technic with unpack already done.&#xD;&#xA;&#xD;&#xA;    n1 += vec3(0, 0, 1);&#xD;&#xA;	n2 *= vec3(-1, -1, 1);&#xD;&#xA;	&#xD;&#xA;    return n1 * dot(n1, n2) / n1.z - n2;&#xD;&#xA;&#xD;&#xA;But this doesn't give expected results and I don't get why. Is there a way to apply the RNM blending on world space normals ?&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/blending-in-detail/&#xD;&#xA;  [2]: https://www.shadertoy.com/view/4t2SzR#" ContentLicense="CC BY-SA 3.0" />
  <row Id="5501" PostHistoryTypeId="2" PostId="2343" RevisionGUID="0f012cb1-9f5f-4b3d-9c41-56333ef949b4" CreationDate="2016-04-19T13:48:31.713" UserId="2644" Text="Let's assume that we have some set of points in 3d space sampled from some arbitrary surface, without self intersections and mostly flat. Is it possible to get any parametrization over this set of points?  And if it is - how?&#xD;&#xA;&#xD;&#xA;My first idea was to find a plane (Maybe through PCA), or more sophisticated smooth surface to this set of points, project each of these points on this fitted plane/surface and get corresponding parameters. But maybe there is better solutions for this problem.&#xD;&#xA;&#xD;&#xA;Thanks for any help." ContentLicense="CC BY-SA 3.0" />
  <row Id="5502" PostHistoryTypeId="1" PostId="2343" RevisionGUID="0f012cb1-9f5f-4b3d-9c41-56333ef949b4" CreationDate="2016-04-19T13:48:31.713" UserId="2644" Text="Parametrize set of unordered points in 3d space" ContentLicense="CC BY-SA 3.0" />
  <row Id="5503" PostHistoryTypeId="3" PostId="2343" RevisionGUID="0f012cb1-9f5f-4b3d-9c41-56333ef949b4" CreationDate="2016-04-19T13:48:31.713" UserId="2644" Text="|algorithm|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5504" PostHistoryTypeId="5" PostId="2343" RevisionGUID="f03a6738-5c09-459e-9394-38b0f6045b73" CreationDate="2016-04-19T14:10:26.560" UserId="2644" Comment="added 15 characters in body" Text="Let's assume that we have some set of points in 3d space sampled from some arbitrary surface, without self intersections and mostly flat. Is it possible to get any parametrization over this set of points?  And if it is - how?&#xD;&#xA;&#xD;&#xA;My first idea was to find a plane (Maybe through PCA), or more sophisticated smooth surface which approximate this set of points, project each of these points on this fitted plane/surface and get corresponding parameters. But maybe there is better solutions for this problem.&#xD;&#xA;&#xD;&#xA;Thanks for any help." ContentLicense="CC BY-SA 3.0" />
  <row Id="5505" PostHistoryTypeId="2" PostId="2344" RevisionGUID="5af05a87-1514-4e17-935c-c6a23db63e4c" CreationDate="2016-04-19T14:32:18.870" UserId="196" Text="Yes, you do need to transform the fetch direction into the space of the cubemap. If you could somehow figure out the fetch direction in the vertex shader, then you could do the transformation there instead, but that would produce worse lighting.&#xD;&#xA;&#xD;&#xA;It also may be worth optimizing for a smaller number of interpolants between the vertex and pixel shaders (rather than a smaller number of matrix-vector multiplications in the pixel shader). As soon as you have one transformed view vector and two transformed light vectors that must be interpolated (which would otherwise be constant), you've matched the size of the tangent/bitangent/normal matrix that you would otherwise be interpolating. That has the potential to have more performance impact than doing extra matrix multiplications in the shader." ContentLicense="CC BY-SA 3.0" />
  <row Id="5506" PostHistoryTypeId="2" PostId="2345" RevisionGUID="e9140dca-ac55-4615-815d-c9b4f70d6538" CreationDate="2016-04-19T14:59:49.760" UserId="137" Text="You can put the data into a data uri to store the data inline in base64 format.&#xD;&#xA;&#xD;&#xA;    &quot;buffers&quot;: {&#xD;&#xA;        &quot;a-buffer-id&quot;: {&#xD;&#xA;            &quot;byteLength&quot;: 1024,&#xD;&#xA;            &quot;type&quot;: &quot;arraybuffer&quot;,&#xD;&#xA;            &quot;uri&quot;=&quot;data:application/octet-stream;base64,...&quot;&#xD;&#xA;        }&#xD;&#xA;    },&#xD;&#xA;&#xD;&#xA;It's still a bit bloated compared to storing the data in a binary file though." ContentLicense="CC BY-SA 3.0" />
  <row Id="5507" PostHistoryTypeId="2" PostId="2346" RevisionGUID="004d6906-fb8d-4c54-925a-5c338624b6d3" CreationDate="2016-04-19T18:18:33.913" UserId="3173" Text="I'm a newbie to OpenGL and I was following a series by &quot;thebennybox&quot; on Youtube. Specifically his series on modern opengl programming. I thought I would try to implement his Mesh wrapper using the vector in C++ rather than using arrays of data and passing that to OpenGL. It works, but I cant' seem to render multiple meshes?&#xD;&#xA;&#xD;&#xA;Am I making an obvious mistake somewhere?&#xD;&#xA;&#xD;&#xA;This is I do to setup my mesh:&#xD;&#xA;&#xD;&#xA;	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;	glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(BUFFER_COUNT, vbo);&#xD;&#xA;&#xD;&#xA;	// vertices buffer&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, vbo[BUFFER_POSITION]);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(positions.front()), &amp;positions.front(), GL_STATIC_DRAW);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;&#xD;&#xA;	// texture buffer&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, vbo[BUFFER_TEXCOORD]);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(texes.front()), &amp;texes.front(), GL_STATIC_DRAW);&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;&#xD;&#xA;	// index buffer&#xD;&#xA;	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[BUFFER_INDEX]);&#xD;&#xA;	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices.front()), &amp;indices.front(), GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;Then to render it I bind the VAO and draw the elements:&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(vao);&#xD;&#xA;	glDrawElementsBaseVertex(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0, 0);&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally I can send it some data:&#xD;&#xA;&#xD;&#xA;    std::vector&lt;Vertex&gt; vertices = {&#xD;&#xA;		Vertex(glm::vec3(0, 0, 0), glm::vec2(0, 0)),&#xD;&#xA;		Vertex(glm::vec3(0, 1, 0), glm::vec2(1, 0)),&#xD;&#xA;		Vertex(glm::vec3(0, 1, 1), glm::vec2(1, 1)),&#xD;&#xA;		Vertex(glm::vec3(0, 0, 1), glm::vec2(0, 1)),&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	std::vector&lt;unsigned int&gt; indices = {&#xD;&#xA;		0, 1, 2, 2, 3, 0&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	shape = new Mesh(vertices, indices);&#xD;&#xA;&#xD;&#xA;The weird thing is that this works perfectly, but as soon as I try render another mesh it wont render the previous mesh. The weird thing is that say I had mesh A and mesh B. I can render mesh A, then I _setup_ mesh B, and even if I don't render it, nothing renders at all. Not even mesh A. I assume this is due to the state-based-ness of OpenGL." ContentLicense="CC BY-SA 3.0" />
  <row Id="5508" PostHistoryTypeId="1" PostId="2346" RevisionGUID="004d6906-fb8d-4c54-925a-5c338624b6d3" CreationDate="2016-04-19T18:18:33.913" UserId="3173" Text="Can't render multiple VAO's?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5509" PostHistoryTypeId="3" PostId="2346" RevisionGUID="004d6906-fb8d-4c54-925a-5c338624b6d3" CreationDate="2016-04-19T18:18:33.913" UserId="3173" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5510" PostHistoryTypeId="5" PostId="2342" RevisionGUID="ffc772c0-2a29-41e0-83cf-54372c426bf6" CreationDate="2016-04-19T20:02:38.247" UserId="2372" Comment="added 191 characters in body" Text="I am trying to blend two world space normals inside a shader. One comes from a tangent space normal map converted into world space using a classic TBN matrix and the other one is a mesh normal map in world space.&#xD;&#xA;&#xD;&#xA;I found some interesting resources here :&#xD;&#xA;&#xD;&#xA; - [Blending in Detail][1]&#xD;&#xA; - [Shadertoy - Normal Map Blending][2]&#xD;&#xA;&#xD;&#xA;But those blending technics seem to be only available for tangent space normals, especially the Reoriented Normal Mapping (RNM).&#xD;&#xA;I tried to apply the RNM technic with unpack already done.&#xD;&#xA;&#xD;&#xA;    n1 += vec3(0, 0, 1);&#xD;&#xA;	n2 *= vec3(-1, -1, 1);&#xD;&#xA;	&#xD;&#xA;    return n1 * dot(n1, n2) / n1.z - n2;&#xD;&#xA;&#xD;&#xA;But this doesn't give expected results and I don't get why. Is there a way to apply the RNM blending on world space normals ?&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;&#xD;&#xA;**Edit:** Here are some output and the result I am having with RNM. The A normal is not disturbed by the B normal, it gives some strange massively reoriented results.&#xD;&#xA;&#xD;&#xA;    float3 nv = dot(normal, viewDir);&#xD;&#xA;    color.rgb = nv;&#xD;&#xA;&#xD;&#xA;[![][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/blending-in-detail/&#xD;&#xA;  [2]: https://www.shadertoy.com/view/4t2SzR#&#xD;&#xA;  [3]: https://i.stack.imgur.com/RYopV.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/iFPZp.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5511" PostHistoryTypeId="2" PostId="2347" RevisionGUID="44cafd70-ac55-450e-a546-fcdae7ad7c01" CreationDate="2016-04-19T20:58:44.273" UserId="3098" Text="Another code review question.&#xD;&#xA;&#xD;&#xA;I am trying to draw an arrow to represent a vector. I have started with an unit arrow with vertices defined as follows:&#xD;&#xA;&#xD;&#xA;    //vertex data for vector with arrow    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;		//line&#xD;&#xA;		0.0f, 0.0f, 0.0f,&#xD;&#xA;		1.0f, 0.0f, 0.0f,&#xD;&#xA;&#xD;&#xA;		//arrow bases&#xD;&#xA;		0.95f, 0.01f, 0.0f,&#xD;&#xA;		0.95f,-0.01f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    GLuint indices[] = {&#xD;&#xA;		0, 1,		// Line&#xD;&#xA;		1, 2, 3    // Arrow Triangle&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I have another array that contains the actual vector start and end positions:&#xD;&#xA;&#xD;&#xA;    GLfloat lineVertices[] = {&#xD;&#xA;						&#xD;&#xA;		1.0f, 2.0f, 3.0f, //v1 start&#xD;&#xA;		3.0f, 5.0f,-5.0f, //v1 end&#xD;&#xA;&#xD;&#xA;	   -1.0f,-1.0f,-1.0f, //v2 start&#xD;&#xA;	   -3.0f, 5.0f,-10.0f //v2 end&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am trying to construct the `model` matrix to apply the transformation from `lineVertices` for each vectors on the unit arrow.&#xD;&#xA;&#xD;&#xA;    //'view', and 'projection' matrix is set out side of the loop&#xD;&#xA;	for (GLint i = 0; i &lt; sizeof(lineVertices) / sizeof(GLfloat); i += 6)&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 model;&#xD;&#xA;&#xD;&#xA;		//apply transformation&#xD;&#xA;		glm::vec3 start(lineVertices[i], lineVertices[i + 1], lineVertices[i + 2]);&#xD;&#xA;		glm::vec3 end(lineVertices[i + 3], lineVertices[i + 4], lineVertices[i + 5]);&#xD;&#xA;		glm::vec3 startToEnd = end - start;&#xD;&#xA;		GLfloat length = glm::length(startToEnd);&#xD;&#xA;&#xD;&#xA;		//scale&#xD;&#xA;		model = glm::scale(model, glm::vec3(length));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		GLfloat xyAngle = glm::atan(startToEnd.z, length);&#xD;&#xA;		GLfloat xzAngle = glm::atan(startToEnd.y, length);&#xD;&#xA;		GLfloat yzAngle = glm::atan(startToEnd.x, length);&#xD;&#xA;&#xD;&#xA;		model = glm::rotate(model, xyAngle, glm::vec3(1.0f, 1.0f, 0.0f));&#xD;&#xA;		model = glm::rotate(model, xzAngle, glm::vec3(1.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, yzAngle, glm::vec3(0.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;		//translate&#xD;&#xA;		model = glm::translate(model, start);&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			&#xD;&#xA;		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Though this seems to work, as I can see all those arrows. However, I am not sure whether this is the right implementation or not. Please let me know, if this is correct and/or there is room for improvement, or there are easier ways to achieve this, and so on.&#xD;&#xA;&#xD;&#xA;P.S.: this implementation is based on following stack exchange discussions: [1][1], [2][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/a/96960/82355&#xD;&#xA;  [2]: http://math.stackexchange.com/a/799812/298948" ContentLicense="CC BY-SA 3.0" />
  <row Id="5512" PostHistoryTypeId="1" PostId="2347" RevisionGUID="44cafd70-ac55-450e-a546-fcdae7ad7c01" CreationDate="2016-04-19T20:58:44.273" UserId="3098" Text="Represent vector with arrow" ContentLicense="CC BY-SA 3.0" />
  <row Id="5513" PostHistoryTypeId="3" PostId="2347" RevisionGUID="44cafd70-ac55-450e-a546-fcdae7ad7c01" CreationDate="2016-04-19T20:58:44.273" UserId="3098" Text="|opengl|c++|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5514" PostHistoryTypeId="10" PostId="2338" RevisionGUID="0a58d719-5e51-4427-bae9-a6be033dfa07" CreationDate="2016-04-19T22:22:26.563" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="5517" PostHistoryTypeId="5" PostId="2347" RevisionGUID="748af5bb-1c08-4d4b-b372-4d4428b0286b" CreationDate="2016-04-20T05:38:00.030" UserId="3098" Comment="typo correction" Text="Another code review question.&#xD;&#xA;&#xD;&#xA;I am trying to draw an arrow to represent a vector. I have started with an unit arrow with vertices defined as follows:&#xD;&#xA;&#xD;&#xA;    //vertex data for vector with arrow    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;		//line&#xD;&#xA;		0.0f, 0.0f, 0.0f,&#xD;&#xA;		1.0f, 0.0f, 0.0f,&#xD;&#xA;&#xD;&#xA;		//arrow bases&#xD;&#xA;		0.95f, 0.01f, 0.0f,&#xD;&#xA;		0.95f,-0.01f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    GLuint indices[] = {&#xD;&#xA;		0, 1,		// Line&#xD;&#xA;		1, 2, 3    // Arrow Triangle&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I have another array that contains the actual vector start and end positions:&#xD;&#xA;&#xD;&#xA;    GLfloat lineVertices[] = {&#xD;&#xA;						&#xD;&#xA;		1.0f, 2.0f, 3.0f, //v1 start&#xD;&#xA;		3.0f, 5.0f,-5.0f, //v1 end&#xD;&#xA;&#xD;&#xA;	   -1.0f,-1.0f,-1.0f, //v2 start&#xD;&#xA;	   -3.0f, 5.0f,-10.0f //v2 end&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am trying to construct the `model` matrix to apply the transformation from `lineVertices` for each vectors on the unit arrow.&#xD;&#xA;&#xD;&#xA;    //'view', and 'projection' matrix is set out side of the loop&#xD;&#xA;	for (GLint i = 0; i &lt; sizeof(lineVertices) / sizeof(GLfloat); i += 6)&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 model;&#xD;&#xA;&#xD;&#xA;		//apply transformation&#xD;&#xA;		glm::vec3 start(lineVertices[i], lineVertices[i + 1], lineVertices[i + 2]);&#xD;&#xA;		glm::vec3 end(lineVertices[i + 3], lineVertices[i + 4], lineVertices[i + 5]);&#xD;&#xA;		glm::vec3 startToEnd = end - start;&#xD;&#xA;		GLfloat length = glm::length(startToEnd);&#xD;&#xA;&#xD;&#xA;		//scale&#xD;&#xA;		model = glm::scale(model, glm::vec3(length));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		GLfloat xyAngle = glm::atan(startToEnd.z, length);&#xD;&#xA;		GLfloat xzAngle = glm::atan(startToEnd.y, length);&#xD;&#xA;		GLfloat yzAngle = glm::atan(startToEnd.x, length);&#xD;&#xA;&#xD;&#xA;		model = glm::rotate(model, xyAngle, glm::vec3(1.0f, 1.0f, 0.0f));&#xD;&#xA;		model = glm::rotate(model, xzAngle, glm::vec3(1.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, yzAngle, glm::vec3(0.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;		//translate&#xD;&#xA;		model = glm::translate(model, start);&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			&#xD;&#xA;		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Though this seems to work, as I can see all those arrows, however, I am not sure whether this is the right implementation or not. Please let me know, if this is correct and/or there is room for improvement, or there are easier ways to achieve this, and so on.&#xD;&#xA;&#xD;&#xA;P.S.: this implementation is based on following stack exchange discussions: [1][1], [2][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/a/96960/82355&#xD;&#xA;  [2]: http://math.stackexchange.com/a/799812/298948" ContentLicense="CC BY-SA 3.0" />
  <row Id="5518" PostHistoryTypeId="5" PostId="2341" RevisionGUID="57ade945-0e89-48de-82d7-4e3d4f7cfdba" CreationDate="2016-04-20T05:44:23.073" UserId="2372" Comment="added 1042 characters in body" Text="Here is an interesting answer from Styves on gamedev.net.&#xD;&#xA;&#xD;&#xA;&gt; Calculating bent normals is just an extension of AO calculation where&#xD;&#xA;&gt; the direction of each sample is also averaged along with the occlusion&#xD;&#xA;&gt; amount.&#xD;&#xA;&gt; &#xD;&#xA;&gt; [![][2]][2]&#xD;&#xA;&gt; &#xD;&#xA;&gt; The bent normals from substance painter seem correct. In any region&#xD;&#xA;&gt; that there is no AO, your normal won't be bent in any direction,&#xD;&#xA;&gt; therefore in tangent space it's pointing straight up along the surface&#xD;&#xA;&gt; normal. This is why you only see details in the ears.&#xD;&#xA;&gt; &#xD;&#xA;&gt;  &#xD;&#xA;&gt; &#xD;&#xA;&gt; I have no idea how Unity handles the bent normals but the usual way is&#xD;&#xA;&gt; to, instead of applying AO as a standard multiplier onto the lighting&#xD;&#xA;&gt; result (which gives this weird muddy look), use the dot product of the&#xD;&#xA;&gt; bent normal and the light instead. This is how we handle SSDO in&#xD;&#xA;&gt; CryENGINE for example.&#xD;&#xA;&gt; &#xD;&#xA;&gt; I've only ever used a texture-based version of this technique once,&#xD;&#xA;&gt; however in this version the bent normals also contained information&#xD;&#xA;&gt; from the original tangent space normal map, and was used directly&#xD;&#xA;&gt; during lighting in place of the original.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.gamedev.net/topic/678008-how-could-i-use-bent-normal-map/?view=findpost&amp;p=5287363&#xD;&#xA;  [2]: https://i.stack.imgur.com/HH0zw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5519" PostHistoryTypeId="2" PostId="2348" RevisionGUID="b7c58769-ecb8-4291-9076-fd87933514b4" CreationDate="2016-04-20T06:59:31.810" UserId="110" Text="There are many references related to the physically-based rendering of several natural features of the numan body, such as skin, hair, eyes.  &#xD;&#xA;However, I could not find specific information about the simulation of visually realistic nails. For example, I did not find specificities of the characteristics of the reaction of human nails to light.&#xD;&#xA;&#xD;&#xA;![Image from the Wikipedia article](https://upload.wikimedia.org/wikipedia/commons/a/aa/Daumennagel_mit_Nagelhaut_und_Niednagel.jpg)&#xD;&#xA;&#xD;&#xA;A few ideas I had:  &#xD;&#xA;&#xD;&#xA;- According to the [Wikipedia article](https://en.wikipedia.org/wiki/Nail_(anatomy)), nails are &quot;made of a tough protective protein called keratin. (...) It is made up of dead skin cells&quot;.  &#xD;&#xA;Hair is also [composed of keratin](https://en.wikipedia.org/wiki/Hair), so nail rendering might have a few similarities with hair rendering? However I think the main feature of hair rendering is the coloring of specular highlights due to internal reflections inside the hair fiber. Is that phenomenon significant or does it even happen for nails?&#xD;&#xA;&#xD;&#xA;- Examination indicates that nails are transparent and that they host sub-surface scattering effects. Are there models combining these phenomenons?&#xD;&#xA;&#xD;&#xA;- The proximity to skin also seems to suggest that the skin under nails has singular appearance properties. Should this layer require some specific techniques to be simulated too?&#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;What kind of technology would be involved to simulate accurately the rendering of human nails?  &#xD;&#xA;What kind of tricks digital artists use to simulate the appearance of human nails?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5520" PostHistoryTypeId="1" PostId="2348" RevisionGUID="b7c58769-ecb8-4291-9076-fd87933514b4" CreationDate="2016-04-20T06:59:31.810" UserId="110" Text="What kind of technology would be involved in the rendering of human nails?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5521" PostHistoryTypeId="3" PostId="2348" RevisionGUID="b7c58769-ecb8-4291-9076-fd87933514b4" CreationDate="2016-04-20T06:59:31.810" UserId="110" Text="|rendering|realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5522" PostHistoryTypeId="2" PostId="2349" RevisionGUID="91757a7d-2cae-4251-b35a-d823e9a35fc7" CreationDate="2016-04-20T07:22:17.570" UserId="48" Text="I'm not aware of any rendering technology designed specially for fingernails. Just eyeballing it, I would suggest that a combination of subsurface scattering with a relatively smooth glossy specular surface would get you most of the way there. In other words, you could use the same shader as you do for skin, but with different textures and different specular parameters.&#xD;&#xA;&#xD;&#xA;I wouldn't guess that a hair shader would be too useful. Nails are not in the shape of fibers, nor do they have the kind of complex occlusion and shadowing that hair does.&#xD;&#xA;&#xD;&#xA;That being said, if the scattering properties of the nails are different enough from that of skin, it might make sense to use a different shader (for instance, doing some sort of volumetric scattering instead of a dipole approximation). I don't know of any references on skin scattering that have investigated nails specifically, though." ContentLicense="CC BY-SA 3.0" />
  <row Id="5523" PostHistoryTypeId="2" PostId="2350" RevisionGUID="3f68cd34-b3e5-44f2-b29d-d39c8f647e4a" CreationDate="2016-04-20T07:48:13.090" UserId="3178" Text="I don't know of any specific technology for rendering fingernails, but I agree that using subsurface scattering with some specular would be a good starting point. &#xD;&#xA;&#xD;&#xA;A couple of things I'd take into account are that most natural nails without any coatings or nail polish aren't that shiny and have some ridges, so there should be some anisotropy to the highlights. I think a hair shader might be overkill for that though. &#xD;&#xA;&#xD;&#xA;A few things I think would be interesting to look at would be things like inclusions from injury/disease/etc., discoloration, and varying thickness; there's probably some work to be done on how light scatters between the soft tissue of the nailbed and the nail itself. Another interesting thing to look at would be nails with nail polish on them; I bet you could do some cool stuff with car paint effects and long distance scattering (like with a backlit manicured nail)." ContentLicense="CC BY-SA 3.0" />
  <row Id="5524" PostHistoryTypeId="5" PostId="2338" RevisionGUID="875bbd84-81bc-4455-a0e4-295d4b55d0e3" CreationDate="2016-04-20T08:15:42.833" UserId="361" Comment="deleted 3 characters in body; edited title" Text="I'm looking for any way which enables me to quickly generate gltf files including the conversion of plain array buffers (vertex, index, color, etc.) into binary (bgltf, glb, bin) files.&#xD;&#xA;&#xD;&#xA;I'm asking because it currently looks like there are only high level applications like Maya, Blender available which can do that or converters to indirectly write glTF from COLLADA.&#xD;&#xA;&#xD;&#xA;Are there any way to generate binary gltf array buffers using low level / command line utilities?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5525" PostHistoryTypeId="4" PostId="2338" RevisionGUID="875bbd84-81bc-4455-a0e4-295d4b55d0e3" CreationDate="2016-04-20T08:15:42.833" UserId="361" Comment="deleted 3 characters in body; edited title" Text="How to generate binary gltf array buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5526" PostHistoryTypeId="11" PostId="2338" RevisionGUID="2937b4ca-5106-4318-80fa-410bc1d3b4b6" CreationDate="2016-04-20T08:34:13.520" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="5536" PostHistoryTypeId="5" PostId="2208" RevisionGUID="8272a296-1308-4b26-80f5-948fcf056a1e" CreationDate="2016-04-21T11:19:54.067" UserId="231" Comment="Remove request for external resources" Text="I have an .STL file (ascii and binary format) that contains several different CAD models. How can I read the file and create separate .stl files for each of the single different models. Even some hints/reference would be helpful.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5537" PostHistoryTypeId="2" PostId="2353" RevisionGUID="eebcf478-0e47-436d-9010-1cf9f6e2f601" CreationDate="2016-04-21T18:09:25.737" UserId="2372" Text="Huge thanks to @MJP who answered this.&lt;br&gt;&#xD;&#xA;The aim is to avoid the simplification made when using tangent space normals.&#xD;&#xA;Here is the paper : [Blending in detail][1]&#xD;&#xA;&#xD;&#xA;But only implement equation ([4][2]) which gives you this.&#xD;&#xA;&#xD;&#xA;    float3 ReorientNormal(in float3 u, in float3 t, in float3 s)&#xD;&#xA;    {&#xD;&#xA;        // Build the shortest-arc quaternion&#xD;&#xA;        float4 q = float4(cross(s, t), dot(s, t) + 1) / sqrt(2 * (dot(s, t) + 1));&#xD;&#xA;        // Rotate the normal&#xD;&#xA;        return u * (q.w * q.w - dot(q.xyz, q.xyz)) + 2 * q.xyz * dot(q.xyz, u) + 2 * q.w * cross(q.xyz, u);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Original answer is [here][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/blending-in-detail/&#xD;&#xA;  [2]: http://blog.selfshadow.com/publications/blending-in-detail/#mjx-eqn-eqrotation&#xD;&#xA;  [3]: http://www.gamedev.net/topic/678043-how-to-blend-world-space-normals/?view=findpost&amp;p=5287707" ContentLicense="CC BY-SA 3.0" />
  <row Id="5538" PostHistoryTypeId="2" PostId="2354" RevisionGUID="dda8e40b-7d96-4802-b41a-4380d6411458" CreationDate="2016-04-22T05:32:42.897" UserId="3003" Text="In order to replace a color with another color, you need some sort of [distance metric](https://en.wikipedia.org/wiki/Metric_(mathematics)) between the colors and a function for calculating the [blending](https://en.wikipedia.org/wiki/Blend_modes) based on that distance. &#xD;&#xA;&#xD;&#xA;Finding a distance between 2 colors can be tricky. RGB is a bad color space to measure the distance between colors for perceptual uses. HSV or YCbCr are better. &#xD;&#xA;&#xD;&#xA;Once you have the colors in a color space you like, you need to decide how to calculate the distance. I generally calculate the hue distance for starters. If the hue of the color I'm considering replacing is within +/- some threshold (possibly set by the user), then I check to see if the saturation and value are within a certain range, too. &#xD;&#xA;&#xD;&#xA;Once I've found a color that's within the ranges specified, I calculate a blending amount. Usually this will be 100% if the color in the image exactly matches the color I want to replace, and will fall off to 0 at the thresholds of hue, saturation and brightness. &#xD;&#xA;&#xD;&#xA;You then need to calculate the color you're going to use as a replacement color. It's useful to offset the hue, saturation and value (or Y, Cb, and Cr components) by the same amount as the color in the image differs from the replacement color.&#xD;&#xA;&#xD;&#xA;So now you have the original color in the image, the color to replace it with, and a blending amount. You still need to figure out which blend mode you want to use. I would start with what Photoshop calls &quot;Normal&quot; or &quot;Over&quot;. That would be a linear mix of the two. If you have colors A and B with a mix amount of 25%, it would be calculated like this:&#xD;&#xA;&#xD;&#xA;newColor = A * .25 + B * (1.0 - .25);&#xD;&#xA;&#xD;&#xA;Here are some relevant answers I gave to similar questions on Stack Overflow:&#xD;&#xA;&#xD;&#xA;[How to Change the Hue of a Texture with GLSL](http://stackoverflow.com/questions/9234724/how-to-change-hue-of-a-texture-with-glsl/9234854#9234854)&#xD;&#xA;&#xD;&#xA;[Better Image Coloring Logic/Algorithm](http://stackoverflow.com/questions/9064556/better-image-coloring-logic-algorithm/9075340#9075340)" ContentLicense="CC BY-SA 3.0" />
  <row Id="5539" PostHistoryTypeId="5" PostId="2329" RevisionGUID="5fd8fdb9-b8cd-4895-b6e1-a53e2c83f078" CreationDate="2016-04-22T07:13:59.907" UserId="182" Comment="Extended answer" Text="##Avoid stereo when possible&#xD;&#xA;&#xD;&#xA;There was some research published recently measuring when users can or cannot tell whether the specular contribution, which is view point dependent, is different between eyes.&#xD;&#xA;&#xD;&#xA;[Perception of Highlight Disparity at a Distance in Consumer Head-Mounted Displays][1]&#xD;&#xA;&#xD;&#xA;In the future, this could be use to share some computation between the two eye renders. Unfortunately this sounds hard to take advantage of in a typical rasterization pipeline.&#xD;&#xA;&#xD;&#xA;Some games already avoid stereo when rendering far objects and background.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;##Reduce shading when possible&#xD;&#xA;&#xD;&#xA;###Lens distortion&#xD;&#xA;&#xD;&#xA;Part of the NVidia VRWorks SDK is a feature, [Multi-Res Shading][2], that allow to reduce the amount of shading, to take into account the fact that some pixels contribute less to the final image due to lens distortion.&#xD;&#xA;&#xD;&#xA;In [Alex Vlachos' GDC 2015 presentation][3], he also mentions the idea of rendering the image in two parts of different resolution, to achieve the same goal.&#xD;&#xA;&#xD;&#xA;###Foveated rendering&#xD;&#xA;&#xD;&#xA;Finally, like your question mentions, foveated rendering aims at scaling the resolution to take into account the fact that eyes have more precision in the fovea and less in the periphery. There is some [research on the topic][4], but this requires eye tracking like in the [Fove][5] HMD.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://software.intel.com/en-us/articles/perception-of-highlight-disparity-at-a-distance-in-consumer-head-mounted-displays&#xD;&#xA;  [2]: https://blogs.nvidia.com/blog/2016/04/20/ue-4/&#xD;&#xA;  [3]: http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf&#xD;&#xA;  [4]: http://research.lighttransport.com/foveated-real-time-ray-tracing-for-virtual-reality-headset/&#xD;&#xA;  [5]: http://www.getfove.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5540" PostHistoryTypeId="2" PostId="2355" RevisionGUID="d430056a-8b55-4990-bc91-2db64c65e04d" CreationDate="2016-04-22T09:39:17.053" UserId="3204" Text="My shape is a slightly concave polygon, and I'd like to know the maximal 'radius'. I imagine a straight line between two points on the surface of the polygon, such that the line does not pass outside the polygon.&#xD;&#xA;&#xD;&#xA;Is there a general algorithm for this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="5541" PostHistoryTypeId="1" PostId="2355" RevisionGUID="d430056a-8b55-4990-bc91-2db64c65e04d" CreationDate="2016-04-22T09:39:17.053" UserId="3204" Text="Find the longest straight line between two points on surface of polygon" ContentLicense="CC BY-SA 3.0" />
  <row Id="5542" PostHistoryTypeId="3" PostId="2355" RevisionGUID="d430056a-8b55-4990-bc91-2db64c65e04d" CreationDate="2016-04-22T09:39:17.053" UserId="3204" Text="|mathematics|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5543" PostHistoryTypeId="5" PostId="2355" RevisionGUID="fd1ef773-fb1f-486c-8ab0-1c6a31709bd7" CreationDate="2016-04-22T17:05:40.357" UserId="48" Comment="added computational-geometry tag, changed radius to diameter" Text="My shape is a slightly concave polygon, and I'd like to know the maximal diameter. I imagine a straight line between two points on the surface of the polygon, such that the line does not pass outside the polygon.&#xD;&#xA;&#xD;&#xA;Is there a general algorithm for this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="5544" PostHistoryTypeId="6" PostId="2355" RevisionGUID="fd1ef773-fb1f-486c-8ab0-1c6a31709bd7" CreationDate="2016-04-22T17:05:40.357" UserId="48" Comment="added computational-geometry tag, changed radius to diameter" Text="|mathematics|computational-geometry|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5545" PostHistoryTypeId="5" PostId="1864" RevisionGUID="96824bc9-8239-4c7d-9bc3-97730a331ded" CreationDate="2016-04-23T05:26:56.453" UserId="127" Comment="Moderator edits article" Text="**Computer Graphics Stack Exchange** is for computer graphics researchers and programmers.&#xA;&#xA;Topics that are usually a good fit for this site include:&#xA;&#xA;* Questions about math related to computer graphics,&#xA;* Questions about a specific graphics [programming](http://meta.computergraphics.stackexchange.com/questions/67/are-questions-about-api-specific-stuff-on-topic) or [debugging](http://meta.computergraphics.stackexchange.com/questions/1/are-questions-about-debugging-opengl-shaders-on-topic) problem,&#xA;* Questions about a specific [graphics API](http://meta.computergraphics.stackexchange.com/questions/67/are-questions-about-api-specific-stuff-on-topic),&#xA;* Questions about a specific graphics algorithm or concept.&#xA;&#xA;If your question generally covers (one of) these topics, then you’re in the right place to ask your question!&#xA;&#xA;---&#xA;&#xA;However, some questions are still off-topic, although they might fit into the above criteria.&#xA;&#xA;* Questions asking for [off-site resources](http://meta.computergraphics.stackexchange.com/questions/146/are-questions-asking-for-off-site-resources-on-topic) including books, tools and tutorials are off-topic as they tend to attract opinionated answers and spam. Also, the other sites may remove their content, which makes the question here useless for future visitors. Instead, ask about the specific problem you have.&#xA;* The same applies to questions asking for [software recommendations](http://meta.computergraphics.stackexchange.com/questions/141/are-questions-about-software-recommendation-in-scope). You may ask such questions on [Software Recommendations Stack Exchange](http://softwarerecs.stackexchange.com/), but please first read over their [Help Center](https://softwarerecs.stackexchange.com/help/on-topic) and [quality guidelines](http://meta.softwarerecs.stackexchange.com/questions/336/what-is-required-for-a-question-to-contain-enough-information).&#xA;* Questions about [how to use (a feature of) modeling software](http://meta.computergraphics.stackexchange.com/questions/13/is-asking-about-maya-or-3ds-max-blender-api-on-topic) are off-topic here, but may be suitable to [Super User](http://superuser.com). Questions specific to Blender may even be asked on [Blender Stack Exchange](http://blender.stackexchange.com). Again, please have a look into their Help Centers before asking.&#xA;* Questions about [Computer Vision](http://meta.computergraphics.stackexchange.com/questions/176/is-computer-vision-in-scope) are off-topic, except where it overlaps with computer graphics. As there is a significant part of overlap between these two topics, the line is blurry. Computer Vision questions unrelated to computer graphics may be suitable to [Signal Processing Stack Exchange](http://dsp.stackexchange.com).&#xA;&#xA;---&#xA;&#xA;&lt;p&gt;Please &lt;a href=&quot;/search&quot;&gt;look around&lt;/a&gt; to see if your question has been asked before. It’s also OK to &lt;a href=&quot;/helpcenter/self-answer&quot;&gt;ask and answer your own question&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your question is not specifically on-topic for $SiteName, it may be on topic for another Stack Exchange site. If no site currently exists that will accept your question, you may &lt;a href=&quot;http://area51.stackexchange.com/faq&quot;&gt;commit to&lt;/a&gt; or &lt;a href=&quot;http://meta.stackexchange.com/questions/76974/how-can-i-propose-a-new-site&quot;&gt;propose&lt;/a&gt; a new site at &lt;a href=&quot;http://area51.stackexchange.com/&quot;&gt;Area51&lt;/a&gt;, the place where new Stack Exchange communities are democratically created.&lt;/p&gt;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5546" PostHistoryTypeId="4" PostId="1864" RevisionGUID="96824bc9-8239-4c7d-9bc3-97730a331ded" CreationDate="2016-04-23T05:26:56.453" UserId="127" Comment="Moderator edits article" Text="What topics can I ask about here?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5547" PostHistoryTypeId="5" PostId="2355" RevisionGUID="cd6c41c9-5d2a-4d9d-b60b-ff415e6af4f0" CreationDate="2016-04-23T05:39:47.663" UserId="3204" Comment="added 228 characters in body" Text="My shape is a slightly concave polygon, and I'd like to know the maximal diameter. I imagine a straight line between two points on the surface of the polygon, such that the line does not pass outside the polygon.&#xD;&#xA;&#xD;&#xA;Is there a general algorithm for this? &#xA;&#xA;In my case I am interested in 2D. My shapes are tumors in medical images. So we can also assume:&#xA;1 the centroid is always inside the polygon. &#xA;2 a high vertex density, i.e. the next vertex is always close to the previous one. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5548" PostHistoryTypeId="2" PostId="2356" RevisionGUID="75be32dc-3cdc-4956-b0f9-52f2964d93a9" CreationDate="2016-04-24T14:21:39.993" UserId="2646" Text="I'm attempting to test out the maths behind bounding volume algorithms (prior to ray tracing) using MATLAB.&#xD;&#xA;&#xD;&#xA;So far, I have successfully created the relatively trivial axis aligned bounding volume, and I believe I have successfully created a bounding sphere.&#xD;&#xA;&#xD;&#xA;I've attempted to then create an object aligned bounding volume - but although I believe I have got the principle axes correct because the box appears to be a suitable shape - I have been unable to translate it correctly &quot;onto&quot; the shape.&#xD;&#xA;&#xD;&#xA;Essentially my question is - what am I doing wrong in my algorithm &amp; how do I translate my bounding volume onto the shape.&#xD;&#xA;&#xD;&#xA;The two sources I have been using are [Maths for 3D Games][1], as well as a [blog][2] which gives some indication on to do the translation - but doesn't seem to have worked very well.&#xD;&#xA;&#xD;&#xA;I have put my source code below - thanks very much!&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %===================Declare vertices and faces===================&#xD;&#xA;    vp_vtx = [379.379,684.302,319.752,711.497,215.956,439.237,600,600,732.938,418.084,600,600,747.081;&#xD;&#xA;        225.836,158.305,394.208,337.480,84.834,245.958,212.858,342.251,322.344,330.576,300,416.190,398.885;&#xD;&#xA;        0.933,0.917,0.904,0.878,0.854,0.923,0.914,0.949,0.943,0.908,0.896,0.940,0.933;&#xD;&#xA;        1,1,1,1,1,1,1,1,1,1,1,1,1];&#xD;&#xA;    ws_fcs = [2,4,3,6,6,7,7,10,10; %Faces forming shape&#xD;&#xA;        4,3,1,7,11,9,13,11,13;&#xD;&#xA;        5,5,5,11,10,13,11,13,12];&#xD;&#xA;    %===================Create an AA bounding box===================&#xD;&#xA;    x = vp_vtx(1,:);y = vp_vtx(2,:);z = vp_vtx(3,:); %Seperate vertex coordinates&#xD;&#xA;    bb_vtx = [min(x),max(x),min(x),max(x),min(x),max(x),min(x),max(x); %Take min/max from each&#xD;&#xA;        min(y),min(y),max(y),max(y),min(y),min(y),max(y),max(y); %To form enclosing box&#xD;&#xA;        min(z),min(z),min(z),min(z),max(z),max(z),max(z),max(z)];&#xD;&#xA;    &#xD;&#xA;    bb_fcs = [1,2,6,1,1,3; 2,4,5,5,2,4;4,8,7,7,6,8; 3,6,8,3,5,7]; %Allocate faces of box&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z'); &#xD;&#xA;    scatter3(vp_vtx(1,:),vp_vtx(2,:),vp_vtx(3,:),'r'); %Plot shape&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',vp_vtx(1:3,:)', 'Facecolor', 'r','FaceAlpha', 0.1)&#xD;&#xA;    %Plot enclosing box&#xD;&#xA;    patch('Faces',bb_fcs', 'Vertices',bb_vtx','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;    &#xD;&#xA;    %vp_vtx = [-1,1,2,2;-2,0,-1,-1;1,2,3,2;0,0,0,0] %Test values from book&#xD;&#xA;    mean_point = sum(vp_vtx,2)/length(vp_vtx);&#xD;&#xA;    C = zeros(4,4); %Create 4x4 empty matrix&#xD;&#xA;    for i = 1:length(vp_vtx)&#xD;&#xA;        C = C+(vp_vtx(:,i)-mean_point)*(vp_vtx(:,i)-mean_point)'; %Sum to get covarience matrix&#xD;&#xA;    end;&#xD;&#xA;    C = C/length(vp_vtx); %Scale by the number of samples&#xD;&#xA;    &#xD;&#xA;    [y,v] = eig(C(1:3,1:3)) ;%Get eigenvalues &amp; eigen vectors&#xD;&#xA;    &#xD;&#xA;    R = y(:,1); %Eigen vectors &amp; values form object aligned axes&#xD;&#xA;    S = y(:,2);&#xD;&#xA;    T = y(:,3);&#xD;&#xA;    %Plot the object aligned axes&#xD;&#xA;    plot3([mean_point(1),mean_point(1)+T(1)*400],[mean_point(2),mean_point(2)+T(2)*400],[mean_point(3),mean_point(3)+T(3)*400])&#xD;&#xA;    plot3([mean_point(1),mean_point(1)+R(1)],[mean_point(2),mean_point(2)+R(2)],[mean_point(3),mean_point(3)+R(3)/10])&#xD;&#xA;    plot3([mean_point(1),mean_point(1)+S(1)*400],[mean_point(2),mean_point(2)+S(2)*400],[mean_point(3),mean_point(3)+S(3)*400])&#xD;&#xA;    %T is principle axis as derived from largest eigenvalue&#xD;&#xA;    &#xD;&#xA;    %==============Create a bounding Sphere=====================&#xD;&#xA;    %Get points deviating the most from principle axis&#xD;&#xA;    for i = 1:length(vp_vtx)&#xD;&#xA;        dt = dot(vp_vtx(1:3,i),T);&#xD;&#xA;        if(i == 1), min_t = dt; max_t = dt; end;&#xD;&#xA;        if dt &lt; min_t&#xD;&#xA;            min_t = dt;&#xD;&#xA;            min_i = i;&#xD;&#xA;        end&#xD;&#xA;        if dt &gt; max_t&#xD;&#xA;            max_t = dt;&#xD;&#xA;            max_i = i;&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    %Centre is middle between these seperated points&#xD;&#xA;    Q = 0.5*(vp_vtx(1:3,min_i)+vp_vtx(1:3,max_i)); &#xD;&#xA;    r = norm(vp_vtx(1:3,max_i)-Q); %Radius is distance between these 2 points&#xD;&#xA;    [x,y,z] = sphere(20); %Create matlab sphere &amp; plot to illustrate&#xD;&#xA;    surf((x*r)+Q(1),(y*r)+Q(2),(z*r)+Q(3), 'FaceColor', 'b', 'FaceAlpha',0.1, 'EdgeColor', 'none')&#xD;&#xA;    &#xD;&#xA;    %========Create an Object Orientated Bounding Box=========&#xD;&#xA;    dot_arr = zeros(size(vp_vtx));&#xD;&#xA;    for i = 1:length(vp_vtx)  %Create array of dot products with each OO axis&#xD;&#xA;        dot_arr(1,i) = dot(vp_vtx(1:3,i),T);&#xD;&#xA;        dot_arr(2,i) = dot(vp_vtx(1:3,i),R);&#xD;&#xA;        dot_arr(3,i) = dot(vp_vtx(1:3,i),S);&#xD;&#xA;    end&#xD;&#xA;    %Get min/max variation in each OO axis&#xD;&#xA;    a = 0.5*(min(dot_arr(1,:)) + max(dot_arr(1,:)));&#xD;&#xA;    b = 0.5*(min(dot_arr(2,:)) + max(dot_arr(2,:)));&#xD;&#xA;    c = 0.5*(min(dot_arr(3,:)) + max(dot_arr(3,:)));&#xD;&#xA;    %Centre is point where the 3 planes of the box intersect? (from book)&#xD;&#xA;    q = a*T + b*R + c*S;&#xD;&#xA;    &#xD;&#xA;    Tr = vertcat(horzcat(T,S,R,q),[0,0,0,1]); %Transform &amp; translate original AA box&#xD;&#xA;    bb_vtx = Tr*vertcat(bb_vtx, ones(1,length(bb_vtx)));&#xD;&#xA;    patch('Faces',bb_fcs', 'Vertices',bb_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/tl3shi/books/blob/master/GameDev/Math/Mathematics.for.3D.Game.Programming.and.Computer.Graphics,.Lengyel,.3rd,.2011.pdf&#xD;&#xA;  [2]: http://jamesgregson.blogspot.co.uk/2011/03/latex-test.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5549" PostHistoryTypeId="1" PostId="2356" RevisionGUID="75be32dc-3cdc-4956-b0f9-52f2964d93a9" CreationDate="2016-04-24T14:21:39.993" UserId="2646" Text="Creating an Object Orientated Bounding Volume" ContentLicense="CC BY-SA 3.0" />
  <row Id="5550" PostHistoryTypeId="3" PostId="2356" RevisionGUID="75be32dc-3cdc-4956-b0f9-52f2964d93a9" CreationDate="2016-04-24T14:21:39.993" UserId="2646" Text="|raytracing|transformations|bounding-volume-hierarchy|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5554" PostHistoryTypeId="2" PostId="2357" RevisionGUID="4603bf31-93d3-4e47-be22-9268588c2d68" CreationDate="2016-04-25T07:39:59.417" UserId="3220" Text="Whenever I try to adjust gamma settings in a game, I am shown three different icons and usually asked to make sure the left-most one is barely visible.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;[![Image][1]][1]&#xD;&#xA;&#xD;&#xA;What are the other two icons for?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tetOP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5555" PostHistoryTypeId="1" PostId="2357" RevisionGUID="4603bf31-93d3-4e47-be22-9268588c2d68" CreationDate="2016-04-25T07:39:59.417" UserId="3220" Text="Gamma setting in games - Why 3 icons?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5556" PostHistoryTypeId="3" PostId="2357" RevisionGUID="4603bf31-93d3-4e47-be22-9268588c2d68" CreationDate="2016-04-25T07:39:59.417" UserId="3220" Text="|gamma|brightness|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5557" PostHistoryTypeId="2" PostId="2358" RevisionGUID="67c137e5-634b-4627-88bb-d216a5c4acae" CreationDate="2016-04-25T07:55:10.327" UserId="2811" Text="Sorry about the long wait, but it has become obvious that although the article I have promised is basically complete, the publishing process will take some time. Therefore, I have instead prepared an open source program with my new multi-channel distance field construction algorithm, **msdfgen**, which you can try out right now.&#xD;&#xA;&#xD;&#xA;It is available on GitHub: https://github.com/Chlumsky/msdfgen&#xD;&#xA;&#xD;&#xA;(I am new to this, so please let me know if there is anything wrong with the repository.)&#xD;&#xA;&#xD;&#xA;Someone also asked about how it compares to a larger monochrome distance field, so here is a teaser of the quality difference. However, it really depends on the particular font, and I would not say it is always worth the extra data.&#xD;&#xA;&#xD;&#xA;[![Multi-channel distance field 16x16][1]][1]&#xD;&#xA;[![Monochrome distance field 32x32][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dhhiy.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/w0Ehl.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ExmTZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5558" PostHistoryTypeId="5" PostId="2151" RevisionGUID="b01a1c56-c8a5-4e2b-b46a-d4f43de7c293" CreationDate="2016-04-25T07:59:45.870" UserId="2811" Comment="added 65 characters in body" Text="**EDIT: Please see my other answer with a concrete solution.**&#xD;&#xA;&#xD;&#xA;I have actually solved this exact problem over a year ago for my master's thesis. In the Valve paper, they show that you can AND two distance fields to achieve this, which works as long as you only have one convex corner. For concave corners, you also need the OR operation. [This guy][1] actually developed some obscure system to switch between the two operations using four texture channels.&#xD;&#xA;&#xD;&#xA;However, there is a much simpler operation that can facilitate both AND and OR depending on the situation, and this is the principal idea of my thesis: **the median of three**. So basically, you use exactly three channels (ideal for RGB), which are completely interchangeable, and combine them using the median operation (choose the middle value out of the three).&#xD;&#xA;&#xD;&#xA;To accomodate anti-aliasing, we don't work with just booleans, but floating point values, and the AND operation becomes the minimum, and the OR becomes the maximum of two values. The median of three can indeed do both: if *a* &lt; *b*, for (*a*, *a*, *b*), the median is the minimum, and for (*a*, *b*, *b*), it is the maximum.&#xD;&#xA;&#xD;&#xA;The rendering process is still extremely simple. The entire fragment shader including anti-aliasing can look something like this:&#xD;&#xA;&#xD;&#xA;    int main() {&#xD;&#xA;        // Bilinear sampling of the distance field&#xD;&#xA;        vec3 s = texture2D(sdf, p).rgb;&#xD;&#xA;        // Acquire the signed distance&#xD;&#xA;        float d = median(s.r, s.g, s.b) - 0.5;&#xD;&#xA;        // Weight between inside and outside (anti-aliasing)&#xD;&#xA;        float w = clamp(d/fwidth(d) + 0.5, 0.0, 1.0);&#xD;&#xA;        // Combining the background and foreground color&#xD;&#xA;        gl_FragColor = mix(outsideColor, insideColor, w);&#xD;&#xA;    }&#xD;&#xA;So the only difference from the original method is computing the median right after sampling the texture. You will have to implement the median function though, [which can be done with just 4 min/max operations][2].&#xD;&#xA;&#xD;&#xA;Now of course, the question is, **how do I build such a three-channel distance field?** And this is the tricky part. The most obvious approach that I took in the beginning was to perform a decomposition of the input shape/glyph into three components, and then generate a conventional distance field out of each. The rules for this decomposition aren't that complicated. Firstly , the area with at least 2 out of 3 channels on is the inside. Then, if you imagine this as the RGB color channels, convex corners must be made of a secondary color, and its two primary components continue outward. Concave corners are the inverse: Two secondary colors enclose their common primary color, and the wedge between where both edges continue inward is white. I also found that some padding is necessary where two primary or two secondary colors would otherwise touch to avoid artifacts (for example, in the middle stroke of the &quot;N&quot; in the picture).&#xD;&#xA;&#xD;&#xA;The following image is an example decomposition generated by the program from my thesis:&#xD;&#xA;&#xD;&#xA;[![Multi-channel decomposition of glyphs][3]][3]&#xD;&#xA;&#xD;&#xA;This approach however has some drawbacks. One of them is that the special effects, such as outlines and shadows will no longer work correctly. Fortunatelly, I also came up with a second, much more elegant method, which generates the distance fields directly, and even supports all of the graphical effects. It is also included in my thesis and so is also over a year old. I am not going to give any more details right now, because I am currently writing a paper that describes this second technique in detail, but I will post it here as soon as it's finished.&#xD;&#xA;&#xD;&#xA;Anyway, here is an example of the difference in quality. The texture resolution is the same in each image, but the left one uses a regular texture, the middle one uses an ordinary distance field, and the right one uses my three-channel distance field. The performance overhead is only the difference between sampling an RGB texture versus a monochrome one.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lambdacube3d.wordpress.com/2014/11/12/playing-around-with-font-rendering/&#xD;&#xA;  [2]: http://stackoverflow.com/a/19045659/1189488&#xD;&#xA;  [3]: https://i.stack.imgur.com/2fVah.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/aG1NR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5559" PostHistoryTypeId="5" PostId="2356" RevisionGUID="26ea758c-6f1d-4414-9891-4bed0ce560e0" CreationDate="2016-04-25T13:47:39.697" UserId="2646" Comment="Simplified the code" Text="I'm attempting to test out the maths behind bounding volume algorithms (prior to ray tracing) using MATLAB.&#xD;&#xA;&#xD;&#xA;So far, I have successfully created the relatively trivial axis aligned bounding volume, and I believe I have successfully created a bounding sphere.&#xD;&#xA;&#xD;&#xA;I've attempted to then create an object aligned bounding volume - but although I believe I have got the principle axes correct because the box appears to be a suitable shape - I have been unable to translate it correctly &quot;onto&quot; the shape.&#xD;&#xA;&#xD;&#xA;Essentially my question is - what am I doing wrong in my algorithm &amp; how do I translate my bounding volume onto the shape.&#xD;&#xA;&#xD;&#xA;The two sources I have been using are [Maths for 3D Games][1], as well as a [blog][2] which gives some indication on to do the translation - but doesn't seem to have worked very well.&#xD;&#xA;&#xD;&#xA;I have put my source code below - thanks very much!&#xD;&#xA;&#xD;&#xA;    %//===================Declare vertices and faces===================&#xD;&#xA;    vp_vtx = [379.379,684.302,319.752,711.497,215.956,439.237,600,600,732.938,418.084,600,600,747.081;&#xD;&#xA;        225.836,158.305,394.208,337.480,84.834,245.958,212.858,342.251,322.344,330.576,300,416.190,398.885;&#xD;&#xA;        0.933,0.917,0.904,0.878,0.854,0.923,0.914,0.949,0.943,0.908,0.896,0.940,0.933;&#xD;&#xA;        1,1,1,1,1,1,1,1,1,1,1,1,1];&#xD;&#xA;    ws_fcs = [2,4,3,6,6,7,7,10,10; %//Faces forming shape&#xD;&#xA;        4,3,1,7,11,9,13,11,13;&#xD;&#xA;        5,5,5,11,10,13,11,13,12];&#xD;&#xA;    %//===================Create an AA bounding box===================&#xD;&#xA;    x = vp_vtx(1,:);y = vp_vtx(2,:);z = vp_vtx(3,:); %//Seperate vertex coordinates&#xD;&#xA;    bb_vtx = [min(x),max(x),min(x),max(x),min(x),max(x),min(x),max(x); %//Take min/max from each&#xD;&#xA;        min(y),min(y),max(y),max(y),min(y),min(y),max(y),max(y); %//To form enclosing box&#xD;&#xA;        min(z),min(z),min(z),min(z),max(z),max(z),max(z),max(z)];&#xD;&#xA;    &#xD;&#xA;    bb_fcs = [1,2,6,1,1,3; 2,4,5,5,2,4;4,8,7,7,6,8; 3,6,8,3,5,7]; %//Allocate faces of box&#xD;&#xA;    &#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(vp_vtx(1,:),vp_vtx(2,:),vp_vtx(3,:),'r'); %//Plot shape&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',vp_vtx(1:3,:)', 'Facecolor', 'r','FaceAlpha', 0.1)&#xD;&#xA;    patch('Faces',bb_fcs', 'Vertices',bb_vtx','FaceColor','g','FaceAlpha', 0.05);%//Plot enclosing box&#xD;&#xA;    &#xD;&#xA;    mean_point = sum(vp_vtx,2)/length(vp_vtx);&#xD;&#xA;    C = zeros(4,4); %//Create 4x4 empty matrix&#xD;&#xA;    for i = 1:length(vp_vtx)&#xD;&#xA;        C = C+(vp_vtx(:,i)-mean_point)*(vp_vtx(:,i)-mean_point)'; %//Sum to get covarience matrix&#xD;&#xA;    end;&#xD;&#xA;    C = C/length(vp_vtx); %//Scale by the number of samples&#xD;&#xA;    &#xD;&#xA;    [y,v] = eig(C(1:3,1:3)) ;%//Get eigenvalues &amp; eigen vectors&#xD;&#xA;    &#xD;&#xA;    R = y(:,1); %//Eigen vectors &amp; values form object aligned axes&#xD;&#xA;    S = y(:,2);&#xD;&#xA;    T = y(:,3);%//T is principle axis as derived from largest eigenvalue&#xD;&#xA;    &#xD;&#xA;    %//========Create an Object Orientated Bounding Box=========&#xD;&#xA;    dot_arr = zeros(size(vp_vtx));&#xD;&#xA;    for i = 1:length(vp_vtx)  %//Create array of dot products with each OO axis&#xD;&#xA;        dot_arr(1,i) = dot(vp_vtx(1:3,i),T);&#xD;&#xA;        dot_arr(2,i) = dot(vp_vtx(1:3,i),R);&#xD;&#xA;        dot_arr(3,i) = dot(vp_vtx(1:3,i),S);&#xD;&#xA;    end&#xD;&#xA;    %//Get min/max variation in each OO axis&#xD;&#xA;    a = 0.5*(min(dot_arr(1,:)) + max(dot_arr(1,:)));&#xD;&#xA;    b = 0.5*(min(dot_arr(2,:)) + max(dot_arr(2,:)));&#xD;&#xA;    c = 0.5*(min(dot_arr(3,:)) + max(dot_arr(3,:)));&#xD;&#xA;    %//Centre is point where the 3 planes of the box intersect? (from book)&#xD;&#xA;    q = a*T + b*R + c*S;&#xD;&#xA;    &#xD;&#xA;    Tr = vertcat(horzcat(T,S,R,q),[0,0,0,1]); %//Transform &amp; translate original AA box&#xD;&#xA;    bb_vtx = Tr*vertcat(bb_vtx, ones(1,length(bb_vtx)));&#xD;&#xA;    patch('Faces',bb_fcs', 'Vertices',bb_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/tl3shi/books/blob/master/GameDev/Math/Mathematics.for.3D.Game.Programming.and.Computer.Graphics,.Lengyel,.3rd,.2011.pdf&#xD;&#xA;  [2]: http://jamesgregson.blogspot.co.uk/2011/03/latex-test.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5560" PostHistoryTypeId="5" PostId="3" RevisionGUID="c8596291-8582-4dc2-8c2d-97ec177f6db6" CreationDate="2016-04-25T15:46:40.090" UserId="17" Comment="deleted 32 characters in body; edited title" Text="Sometimes I use vector graphics, simply because they look just *slightly* nicer in some cases, and other times, I use bitmap/raster graphics.&#xD;&#xA;&#xD;&#xA;I was wondering, are there any significant performance differences between these two options?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5561" PostHistoryTypeId="4" PostId="3" RevisionGUID="c8596291-8582-4dc2-8c2d-97ec177f6db6" CreationDate="2016-04-25T15:46:40.090" UserId="17" Comment="deleted 32 characters in body; edited title" Text="Performance of vector graphics versus bitmap or raster graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="5563" PostHistoryTypeId="5" PostId="2347" RevisionGUID="31e56fdf-e92a-487c-92a8-e2799d150bc9" CreationDate="2016-04-26T07:27:58.553" UserId="3098" Comment="updated code sample" Text="Another code review question.&#xD;&#xA;&#xD;&#xA;I am trying to draw an arrow to represent a vector. I have started with an unit arrow with vertices defined as follows:&#xD;&#xA;&#xD;&#xA;    //vertex data for vector with arrow    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;		//line&#xD;&#xA;		0.0f, 0.0f, 0.0f,&#xD;&#xA;		1.0f, 0.0f, 0.0f,&#xD;&#xA;&#xD;&#xA;		//arrow bases&#xD;&#xA;		0.95f, 0.01f, 0.0f,&#xD;&#xA;		0.95f,-0.01f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    GLuint indices[] = {&#xD;&#xA;		0, 1,		// Line&#xD;&#xA;		1, 2, 3    // Arrow Triangle&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I have another array that contains the actual vector start and end positions:&#xD;&#xA;&#xD;&#xA;    GLfloat lineVertices[] = {&#xD;&#xA;						&#xD;&#xA;		1.0f, 2.0f, 3.0f, //v1 start&#xD;&#xA;		3.0f, 5.0f,-5.0f, //v1 end&#xD;&#xA;&#xD;&#xA;	   -1.0f,-1.0f,-1.0f, //v2 start&#xD;&#xA;	   -3.0f, 5.0f,-10.0f //v2 end&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am trying to construct the `model` matrix to apply the transformation from `lineVertices` for each vectors on the unit arrow.&#xD;&#xA;&#xD;&#xA;    //'view', and 'projection' matrix is set out side of the loop&#xD;&#xA;	for (GLint i = 0; i &lt; sizeof(lineVertices) / sizeof(GLfloat); i += 6)&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 model;&#xD;&#xA;&#xD;&#xA;		//apply transformation&#xD;&#xA;		glm::vec3 start(lineVertices[i], lineVertices[i + 1], lineVertices[i + 2]);&#xD;&#xA;		glm::vec3 end(lineVertices[i + 3], lineVertices[i + 4], lineVertices[i + 5]);&#xD;&#xA;		glm::vec3 startToEnd = end - start;&#xD;&#xA;		GLfloat length = glm::length(startToEnd);&#xD;&#xA;&#xD;&#xA;		//scale&#xD;&#xA;		model = glm::scale(model, glm::vec3(length));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		//GLfloat xyAngle = glm::atan(startToEnd.z, length);&#xD;&#xA;		//GLfloat xzAngle = glm::atan(startToEnd.y, length);&#xD;&#xA;		//GLfloat yzAngle = glm::atan(startToEnd.x, length);&#xD;&#xA;&#xD;&#xA;		//model = glm::rotate(model, xyAngle, glm::vec3(1.0f, 1.0f, 0.0f));&#xD;&#xA;		//model = glm::rotate(model, xzAngle, glm::vec3(1.0f, 0.0f, 1.0f));&#xD;&#xA;		//model = glm::rotate(model, yzAngle, glm::vec3(0.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		GLfloat angleWithZ = glm::acos(startToEnd.z/length);&#xD;&#xA;		GLfloat angleWithY = glm::acos(startToEnd.y/length);&#xD;&#xA;		GLfloat angleWithX = glm::acos(startToEnd.x/length);&#xD;&#xA;&#xD;&#xA;		model = glm::rotate(model, angleWithX, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithY, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithZ, glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;		//translate&#xD;&#xA;		model = glm::translate(model, start);&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			&#xD;&#xA;		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Though this seems to work, as I can see all those arrows, however, I am not sure whether this is the right implementation or not. Please let me know, if this is correct and/or there is room for improvement, or there are easier ways to achieve this, and so on.&#xD;&#xA;&#xD;&#xA;**Edit:** updated my code sample (only the rotation part) based on [Direction cosine (wikipedia)][1]. Old code is still kept commented. &#xD;&#xA;&#xD;&#xA;P.S.: this implementation is based on following stack exchange discussions: [1][2], [2][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Direction_cosine&#xD;&#xA;  [2]: http://gamedev.stackexchange.com/a/96960/82355&#xD;&#xA;  [3]: http://math.stackexchange.com/a/799812/298948" ContentLicense="CC BY-SA 3.0" />
  <row Id="5564" PostHistoryTypeId="2" PostId="2359" RevisionGUID="36076156-2126-4328-89f5-45302183750b" CreationDate="2016-04-26T11:54:22.140" UserId="3225" Text="I have an application in which I am using an octree to store a volume mesh of axis-aligned bounding boxes (AABBs). &#xD;&#xA;&#xD;&#xA;Given a water-tight triangle mesh, I need to:&#xD;&#xA;&#xD;&#xA;- find if an AABB is intersected by or completely inside/outside of the surface mesh,&#xD;&#xA;&#xD;&#xA;- clip the surface mesh with the intersected AABBs to generate triangles that completely lie within each AABB. &#xD;&#xA;&#xD;&#xA;The triangulation and the octree containing the AABBs are both dynamic. The number of leaf nodes in the octree is huge. The number of triangles in the surface mesh is much smaller (`O(10^9 - 10^13)` octree nodes, vs `O(10^6)` triangles).&#xD;&#xA;&#xD;&#xA;Which data-structures and algorithm are suitable for my problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5565" PostHistoryTypeId="1" PostId="2359" RevisionGUID="36076156-2126-4328-89f5-45302183750b" CreationDate="2016-04-26T11:54:22.140" UserId="3225" Text="Data structure and algorithm for clipping triangulation with leaf nodes of an octree" ContentLicense="CC BY-SA 3.0" />
  <row Id="5566" PostHistoryTypeId="3" PostId="2359" RevisionGUID="36076156-2126-4328-89f5-45302183750b" CreationDate="2016-04-26T11:54:22.140" UserId="3225" Text="|algorithm|geometry|performance|data-structure|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5568" PostHistoryTypeId="2" PostId="2360" RevisionGUID="e1145184-f0fb-4ad9-b03d-85eac2b5f89a" CreationDate="2016-04-26T17:11:05.690" UserId="1924" Text="Say I have rendered an HDR ray traced image with dimensions 1920x1080 (width x height) pixels and I want to instead represent it with dimensions 960x540. Assume as well that the image has not yet been gamma corrected (i.e. it is still in linear space). How should I go about downsampling the image such that I don't need to re-render the image in the new dimensions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5569" PostHistoryTypeId="1" PostId="2360" RevisionGUID="e1145184-f0fb-4ad9-b03d-85eac2b5f89a" CreationDate="2016-04-26T17:11:05.690" UserId="1924" Text="How can I resize a rendered ray traced image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5570" PostHistoryTypeId="3" PostId="2360" RevisionGUID="e1145184-f0fb-4ad9-b03d-85eac2b5f89a" CreationDate="2016-04-26T17:11:05.690" UserId="1924" Text="|raytracing|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5572" PostHistoryTypeId="2" PostId="2361" RevisionGUID="0e5bdb10-b5e4-4878-afa5-39bb8f0a941c" CreationDate="2016-04-26T23:27:46.947" UserId="48" Text="Since you want to downsample the image by a factor of 2 along each axis, a simple and easy thing to do is just average a 2&amp;times;2 box of source pixels to generate each destination pixel. In pseudocode this would look like:&#xD;&#xA;&#xD;&#xA;    for dest_y = 0 to 540&#xD;&#xA;        src_y = dest_y*2&#xD;&#xA;        for dest_x = 0 to 960&#xD;&#xA;            src_x = dest_x*2&#xD;&#xA;            average = 0.25 * (src[src_y][src_x] + src[src_y][src_x+1] +&#xD;&#xA;                              src[src_y+1][src_x] + src[src_y+1][src_x+1])&#xD;&#xA;            dest[dest_y][dest_x] = average&#xD;&#xA;&#xD;&#xA;This will do an okay job, but for higher-quality downsampling or resizing images to any size (not just neat integer factors), I suggest looking at the [stb_image_resize](https://github.com/nothings/stb/blob/master/stb_image_resize.h) library. It's quite easy to use, supports either 8-bit or floating-point images with any number of channels, and gives good results." ContentLicense="CC BY-SA 3.0" />
  <row Id="5573" PostHistoryTypeId="33" PostId="2356" RevisionGUID="333e4c9c-c7ad-44e1-80e3-52d455d1127a" CreationDate="2016-04-27T09:34:58.197" UserId="2646" Comment="14" />
  <row Id="5574" PostHistoryTypeId="2" PostId="2362" RevisionGUID="8691895a-e3e3-41ea-949b-81a746e9a0d0" CreationDate="2016-04-27T10:12:31.790" UserId="2712" Text="Thanks for the suggestion. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;1. First of it is identified if two line segments intersects or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). Once the boolean flag mentions that the intersection point is found, Then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;        short int getXIntersection(float x1,&#xD;&#xA;                                   float y1,&#xD;&#xA;                                   float x2,&#xD;&#xA;                                   float y2,&#xD;&#xA;                                   float yPos)&#xD;&#xA;        {&#xD;&#xA;            float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;            float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;            return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;     &#xD;&#xA;&#xD;&#xA;The above function snippet is for the case when one of the line segment is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segment is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity , the code snippet is not written here. I hope you can imagine how will it be ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole into this over-all algorithm ? In practice , I am getting some huge intersection point value that it way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection point must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5575" PostHistoryTypeId="1" PostId="2362" RevisionGUID="8691895a-e3e3-41ea-949b-81a746e9a0d0" CreationDate="2016-04-27T10:12:31.790" UserId="2712" Text="Line segment intersection test and find the point of intersection" ContentLicense="CC BY-SA 3.0" />
  <row Id="5576" PostHistoryTypeId="3" PostId="2362" RevisionGUID="8691895a-e3e3-41ea-949b-81a746e9a0d0" CreationDate="2016-04-27T10:12:31.790" UserId="2712" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5577" PostHistoryTypeId="5" PostId="2362" RevisionGUID="4467d445-95db-4af6-89ff-9c289b469720" CreationDate="2016-04-27T11:53:40.937" UserId="231" Comment="Add link to previous question and fix minor typos" Text="Thanks for the [suggestions]. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;1. First off it is identified if two line segments intersect or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). Once the boolean flag mentions that the intersection point is found, then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;        short int getXIntersection(float x1,&#xD;&#xA;                                   float y1,&#xD;&#xA;                                   float x2,&#xD;&#xA;                                   float y2,&#xD;&#xA;                                   float yPos)&#xD;&#xA;        {&#xD;&#xA;            float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;            float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;            return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;     &#xD;&#xA;The above function snippet is for the case when one of the line segments is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segments is parallel to the Y-axis and the other segment is of arbitrary orientation. For the sake of brevity, the code snippet is not written here. I hope you can imagine how it will be?&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole in this overall algorithm? In practice, I am getting some huge intersection point values that are way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection point must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [suggestions]: http://computergraphics.stackexchange.com/questions/2140/intersection-between-line-segments-narrowed-precondition" ContentLicense="CC BY-SA 3.0" />
  <row Id="5578" PostHistoryTypeId="5" PostId="2362" RevisionGUID="9430064e-a421-4cb1-b101-7d9af39c6b65" CreationDate="2016-04-27T11:56:00.160" UserId="2712" Comment="added 2811 characters in body" Text="Thanks for the suggestion. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;1. First of it is identified if two line segments intersects or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). &#xD;&#xA;&#xD;&#xA;        int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;                        glm::i16vec2 &amp;p2,&#xD;&#xA;                        glm::i16vec2 &amp;p3)&#xD;&#xA;         {&#xD;&#xA;           return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;          bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;                         const glm::i16vec2 &amp;pj,&#xD;&#xA;                         const glm::i16vec2 &amp;pk)&#xD;&#xA;          {&#xD;&#xA;             if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x))  &amp;&amp;&#xD;&#xA;             (std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;                return true;&#xD;&#xA;             else&#xD;&#xA;                return false;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          int main()&#xD;&#xA;          {&#xD;&#xA;            glm::i16vec2 hs(5,1);  // p1&#xD;&#xA;            glm::i16vec2 he(5,3); // p2&#xD;&#xA;&#xD;&#xA;            glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;            glm::i16vec2 ce(5,3); // p4&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            int d1 = orientation(cs,ce,hs);&#xD;&#xA;            int d2 = orientation(cs,ce,he);&#xD;&#xA;            int d3 = orientation(hs,he,cs);&#xD;&#xA;            int d4 = orientation(hs,he,ce);&#xD;&#xA;&#xD;&#xA;            if(((d1 &gt; 0 &amp;&amp; d2 &lt; 0) || (d1 &lt; 0 &amp;&amp; d2 &gt; 0)) &amp;&amp;&#xD;&#xA;               ((d3 &gt; 0 &amp;&amp; d4 &lt; 0) || (d3 &lt; 0 &amp;&amp; d4 &gt; 0)))&#xD;&#xA;                   std::cout &lt;&lt; &quot;Intersection between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; ## &quot; &#xD;&#xA;                             &lt;&lt; glm::to_string(he) &lt;&lt; &quot; and \n&quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(cs) &lt;&lt; &quot; ## &quot; &#xD;&#xA;                             &lt;&lt; glm::to_string(ce) &lt;&lt; std::endl;&#xD;&#xA;            else if(d1 == 0 &amp;&amp; onSegment(cs,ce,hs))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(hs)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                                                    &lt;&lt; glm::to_string(cs) &#xD;&#xA;                                                    &lt;&lt; &quot; and &quot;&#xD;&#xA;                                                    &lt;&lt; glm::to_string(ce) &#xD;&#xA;                                                    &lt;&lt; std::endl;&#xD;&#xA;            else if(d2 == 0 &amp;&amp; onSegment(cs,ce,he))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(he)  &#xD;&#xA;                             &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(cs) &lt;&lt; &quot; and &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(ce) &lt;&lt; std::endl;&#xD;&#xA;            else if(d3 == 0 &amp;&amp; onSegment(hs,he,cs))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(cs)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; and &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(he) &lt;&lt; std::endl;&#xD;&#xA;            else if(d4 == 0 &amp;&amp; onSegment(hs,he,ce))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(ce)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; and &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(he) &lt;&lt; std::endl;&#xD;&#xA;            else&#xD;&#xA;                   std::cout &lt;&lt; &quot;There is no Intersection.&quot; &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Once the boolean flag mentions that the intersection point is found, Then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;        short int getXIntersection(float x1,&#xD;&#xA;                                   float y1,&#xD;&#xA;                                   float x2,&#xD;&#xA;                                   float y2,&#xD;&#xA;                                   float yPos)&#xD;&#xA;        {&#xD;&#xA;            float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;            float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;            return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;     &#xD;&#xA;&#xD;&#xA;The above function snippet is for the case when one of the line segment is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segment is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity , the code snippet is not written here. I hope you can imagine how will it be ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole into this over-all algorithm ? In practice , I am getting some huge intersection point value that it way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection point must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5579" PostHistoryTypeId="5" PostId="2362" RevisionGUID="3f6cc6c0-24a0-436f-8bcd-4c49b84b7a49" CreationDate="2016-04-27T12:33:38.937" UserId="231" Comment="Reapply previous edit that appears to have clashed and been reversed." Text="Thanks for the [suggestions]. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;1. First off it is identified if two line segments intersect or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). &#xD;&#xA;&#xD;&#xA;        int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;                        glm::i16vec2 &amp;p2,&#xD;&#xA;                        glm::i16vec2 &amp;p3)&#xD;&#xA;         {&#xD;&#xA;           return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;          bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;                         const glm::i16vec2 &amp;pj,&#xD;&#xA;                         const glm::i16vec2 &amp;pk)&#xD;&#xA;          {&#xD;&#xA;             if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x))  &amp;&amp;&#xD;&#xA;             (std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;                return true;&#xD;&#xA;             else&#xD;&#xA;                return false;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          int main()&#xD;&#xA;          {&#xD;&#xA;            glm::i16vec2 hs(5,1);  // p1&#xD;&#xA;            glm::i16vec2 he(5,3); // p2&#xD;&#xA;&#xD;&#xA;            glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;            glm::i16vec2 ce(5,3); // p4&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            int d1 = orientation(cs,ce,hs);&#xD;&#xA;            int d2 = orientation(cs,ce,he);&#xD;&#xA;            int d3 = orientation(hs,he,cs);&#xD;&#xA;            int d4 = orientation(hs,he,ce);&#xD;&#xA;&#xD;&#xA;            if(((d1 &gt; 0 &amp;&amp; d2 &lt; 0) || (d1 &lt; 0 &amp;&amp; d2 &gt; 0)) &amp;&amp;&#xD;&#xA;               ((d3 &gt; 0 &amp;&amp; d4 &lt; 0) || (d3 &lt; 0 &amp;&amp; d4 &gt; 0)))&#xD;&#xA;                   std::cout &lt;&lt; &quot;Intersection between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; ## &quot; &#xD;&#xA;                             &lt;&lt; glm::to_string(he) &lt;&lt; &quot; and \n&quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(cs) &lt;&lt; &quot; ## &quot; &#xD;&#xA;                             &lt;&lt; glm::to_string(ce) &lt;&lt; std::endl;&#xD;&#xA;            else if(d1 == 0 &amp;&amp; onSegment(cs,ce,hs))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(hs)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                                                    &lt;&lt; glm::to_string(cs) &#xD;&#xA;                                                    &lt;&lt; &quot; and &quot;&#xD;&#xA;                                                    &lt;&lt; glm::to_string(ce) &#xD;&#xA;                                                    &lt;&lt; std::endl;&#xD;&#xA;            else if(d2 == 0 &amp;&amp; onSegment(cs,ce,he))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(he)  &#xD;&#xA;                             &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(cs) &lt;&lt; &quot; and &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(ce) &lt;&lt; std::endl;&#xD;&#xA;            else if(d3 == 0 &amp;&amp; onSegment(hs,he,cs))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(cs)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; and &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(he) &lt;&lt; std::endl;&#xD;&#xA;            else if(d4 == 0 &amp;&amp; onSegment(hs,he,ce))&#xD;&#xA;                   std::cout &lt;&lt; glm::to_string(ce)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; and &quot;&#xD;&#xA;                             &lt;&lt; glm::to_string(he) &lt;&lt; std::endl;&#xD;&#xA;            else&#xD;&#xA;                   std::cout &lt;&lt; &quot;There is no Intersection.&quot; &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Once the boolean flag mentions that the intersection point is found, then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;        short int getXIntersection(float x1,&#xD;&#xA;                                   float y1,&#xD;&#xA;                                   float x2,&#xD;&#xA;                                   float y2,&#xD;&#xA;                                   float yPos)&#xD;&#xA;        {&#xD;&#xA;            float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;            float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;            return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;     &#xD;&#xA;The above function snippet is for the case when one of the line segments is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segments is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity, the code snippet is not written here. I hope you can imagine how it will be?&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole in this overall algorithm? In practice, I am getting some huge intersection point value that is way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection points must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [suggestions]: http://computergraphics.stackexchange.com/questions/2140/intersection-between-line-segments-narrowed-precondition" ContentLicense="CC BY-SA 3.0" />
  <row Id="5580" PostHistoryTypeId="5" PostId="2362" RevisionGUID="aab56c77-fb96-4c5f-b239-5068ddc9d3d9" CreationDate="2016-04-27T12:51:49.383" UserId="231" Comment="Apply syntax highlighting and fix scrambled indentation" Text="Thanks for the [suggestions]. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;First off it is identified if two line segments intersect or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). &#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;    				glm::i16vec2 &amp;p2,&#xD;&#xA;    				glm::i16vec2 &amp;p3)&#xD;&#xA;    {&#xD;&#xA;       return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;    				 const glm::i16vec2 &amp;pj,&#xD;&#xA;    				 const glm::i16vec2 &amp;pk)&#xD;&#xA;    {&#xD;&#xA;    	if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x))  &amp;&amp;&#xD;&#xA;    	(std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;    		return true;&#xD;&#xA;    	else&#xD;&#xA;    		return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	glm::i16vec2 hs(5,1);  // p1&#xD;&#xA;    	glm::i16vec2 he(5,3); // p2&#xD;&#xA;    &#xD;&#xA;    	glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;    	glm::i16vec2 ce(5,3); // p4&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	int d1 = orientation(cs,ce,hs);&#xD;&#xA;    	int d2 = orientation(cs,ce,he);&#xD;&#xA;    	int d3 = orientation(hs,he,cs);&#xD;&#xA;    	int d4 = orientation(hs,he,ce);&#xD;&#xA;    &#xD;&#xA;    	if(((d1 &gt; 0 &amp;&amp; d2 &lt; 0) || (d1 &lt; 0 &amp;&amp; d2 &gt; 0)) &amp;&amp;&#xD;&#xA;    	   ((d3 &gt; 0 &amp;&amp; d4 &lt; 0) || (d3 &lt; 0 &amp;&amp; d4 &gt; 0)))&#xD;&#xA;    		   std::cout &lt;&lt; &quot;Intersection between &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; ## &quot; &#xD;&#xA;    					 &lt;&lt; glm::to_string(he) &lt;&lt; &quot; and \n&quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(cs) &lt;&lt; &quot; ## &quot; &#xD;&#xA;    					 &lt;&lt; glm::to_string(ce) &lt;&lt; std::endl;&#xD;&#xA;    	else if(d1 == 0 &amp;&amp; onSegment(cs,ce,hs))&#xD;&#xA;    		   std::cout &lt;&lt; glm::to_string(hs)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;    											&lt;&lt; glm::to_string(cs) &#xD;&#xA;    											&lt;&lt; &quot; and &quot;&#xD;&#xA;    											&lt;&lt; glm::to_string(ce) &#xD;&#xA;    											&lt;&lt; std::endl;&#xD;&#xA;    	else if(d2 == 0 &amp;&amp; onSegment(cs,ce,he))&#xD;&#xA;    		   std::cout &lt;&lt; glm::to_string(he)  &#xD;&#xA;    					 &lt;&lt; &quot; is in between &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(cs) &lt;&lt; &quot; and &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(ce) &lt;&lt; std::endl;&#xD;&#xA;    	else if(d3 == 0 &amp;&amp; onSegment(hs,he,cs))&#xD;&#xA;    		   std::cout &lt;&lt; glm::to_string(cs)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; and &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(he) &lt;&lt; std::endl;&#xD;&#xA;    	else if(d4 == 0 &amp;&amp; onSegment(hs,he,ce))&#xD;&#xA;    		   std::cout &lt;&lt; glm::to_string(ce)  &lt;&lt; &quot; is in between &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(hs) &lt;&lt; &quot; and &quot;&#xD;&#xA;    					 &lt;&lt; glm::to_string(he) &lt;&lt; std::endl;&#xD;&#xA;    	else&#xD;&#xA;    		   std::cout &lt;&lt; &quot;There is no Intersection.&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Once the boolean flag mentions that the intersection point is found, then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;    short int getXIntersection(float x1,&#xD;&#xA;                               float y1,&#xD;&#xA;                               float x2,&#xD;&#xA;                               float y2,&#xD;&#xA;                               float yPos)&#xD;&#xA;    {&#xD;&#xA;        float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;        float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;        return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;     &#xD;&#xA;The above function snippet is for the case when one of the line segments is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segments is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity, the code snippet is not written here. I hope you can imagine how it will be?&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole in this overall algorithm? In practice, I am getting some huge intersection point value that is way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection points must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [suggestions]: http://computergraphics.stackexchange.com/questions/2140/intersection-between-line-segments-narrowed-precondition&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5582" PostHistoryTypeId="5" PostId="2362" RevisionGUID="65ff71fe-7d79-47ba-802c-616e360b21fe" CreationDate="2016-04-27T15:41:56.563" UserId="2712" Comment="added 181 characters in body" Text="Thanks for the [suggestions]. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;First off it is identified if two line segments intersect or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). &#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;    				glm::i16vec2 &amp;p2,&#xD;&#xA;    				glm::i16vec2 &amp;p3)&#xD;&#xA;    {&#xD;&#xA;       return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;    				 const glm::i16vec2 &amp;pj,&#xD;&#xA;    				 const glm::i16vec2 &amp;pk)&#xD;&#xA;    {&#xD;&#xA;    	if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x))  &amp;&amp;&#xD;&#xA;    	(std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;    		return true;&#xD;&#xA;    	else&#xD;&#xA;    		return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool intersects(const glm::i16vec2 &amp;p1,const glm::i16vec2 &amp;p2,&#xD;&#xA;                    const glm::i16vec2 &amp;p3,const glm::i16vec2 &amp;p4)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    	int d1 = orientation(p1,p2,p3);&#xD;&#xA;    	int d2 = orientation(p1,p2,p4);&#xD;&#xA;    	int d3 = orientation(p3,p4,p1);&#xD;&#xA;    	int d4 = orientation(p3,p4,p2);&#xD;&#xA;    &#xD;&#xA;    	if(((d1 &gt; 0 &amp;&amp; d2 &lt; 0) || (d1 &lt; 0 &amp;&amp; d2 &gt; 0)) &amp;&amp;&#xD;&#xA;    	    ((d3 &gt; 0 &amp;&amp; d4 &lt; 0) || (d3 &lt; 0 &amp;&amp; d4 &gt; 0)))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d1 == 0 &amp;&amp; onSegment(p3,p4,p1))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d2 == 0 &amp;&amp; onSegment(p3,p4,p2))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d3 == 0 &amp;&amp; onSegment(p1,p2,p3))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d4 == 0 &amp;&amp; onSegment(p1,p2,p4))&#xD;&#xA;              return true;&#xD;&#xA;    	else&#xD;&#xA;    		  return false;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	glm::i16vec2 hs(5,1);  // p1&#xD;&#xA;    	glm::i16vec2 he(5,3); // p2&#xD;&#xA;    &#xD;&#xA;    	glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;    	glm::i16vec2 ce(5,3); // p4&#xD;&#xA;&#xD;&#xA;        if(intersects(hs,he,cs,ce))&#xD;&#xA;          std::cout &lt;&lt; &quot;It has intersection&quot; &lt;&lt; std::endl;&#xD;&#xA;        else&#xD;&#xA;          std::cout &lt;&lt; &quot;No intersection&quot; &lt;&lt; std::endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Once the boolean flag mentions that the intersection point is found, then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;    short int getXIntersection(float x1,&#xD;&#xA;                               float y1,&#xD;&#xA;                               float x2,&#xD;&#xA;                               float y2,&#xD;&#xA;                               float yPos)&#xD;&#xA;    {&#xD;&#xA;        float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;        float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;        return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;     &#xD;&#xA;The above function snippet is for the case when one of the line segments is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segments is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity, the code snippet is not written here. I hope you can imagine how it will be?&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole in this overall algorithm? In practice, I am getting some huge intersection point value that is way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection points must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After several comments and one answer , some adjustments is made within the code. It is found that with overlapping line segments the algorithm return true. It is not intended in my case, all overlapping line segments must not be flagged as intersection. Some hint would be nice. The issue of getting the intersection point is still in the pipeline. I believe that I missed the part that must be done after the initial true/false algorithm - that is to test if the calculated intersectin point lies within both the line segments or not. If it does, only then we eventually have the true intersection otherwise no intersection at all. &#xD;&#xA;&#xD;&#xA;Some feed-back would be great! &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [suggestions]: http://computergraphics.stackexchange.com/questions/2140/intersection-between-line-segments-narrowed-precondition&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5587" PostHistoryTypeId="2" PostId="2364" RevisionGUID="55ac9033-cf63-41c9-a5e0-a9a3acf9fa4a" CreationDate="2016-04-28T11:41:14.680" UserId="2712" Text="I have implemented line segments [intersetion test][1] and at the very same test I want to include the fact that if two line segments overlap each other partially or fully , it will be flagged as no intersection.&#xD;&#xA;&#xD;&#xA;Some hint to it would be great to have!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/2362/line-segment-intersection-test-and-find-the-point-of-intersection" ContentLicense="CC BY-SA 3.0" />
  <row Id="5588" PostHistoryTypeId="1" PostId="2364" RevisionGUID="55ac9033-cf63-41c9-a5e0-a9a3acf9fa4a" CreationDate="2016-04-28T11:41:14.680" UserId="2712" Text="Line segments overlapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="5589" PostHistoryTypeId="3" PostId="2364" RevisionGUID="55ac9033-cf63-41c9-a5e0-a9a3acf9fa4a" CreationDate="2016-04-28T11:41:14.680" UserId="2712" Text="|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5590" PostHistoryTypeId="2" PostId="2365" RevisionGUID="5926999d-1653-47f6-bcca-64951e4e742b" CreationDate="2016-04-28T16:18:55.477" UserId="197" Text="I am writing an OpenCL program for use with my AMD Radeon HD 7800 series GPU. According to AMD's [OpenCL programming guide](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/07/AMD_Accelerated_Parallel_Processing_OpenCL_Programming_Guide-rev-2.7.pdf), this generation of GPU has two hardware queues that can operate asynchronously. To do this, I've created two separate OpenCL command queues to feed data to the GPU. Roughly, [the program running on the host thread](https://github.com/Mokosha/GenTC/blob/SeparateGLSync/codec/codec.cpp#L570) looks something like this:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    static const int kNumQueues = 2;&#xD;&#xA;    cl_command_queue default_queue;&#xD;&#xA;    cl_command_queue work_queue[kNumQueues];&#xD;&#xA;&#xD;&#xA;    static const int N = 256;&#xD;&#xA;    cl_mem gl_buffers[N];&#xD;&#xA;    cl_event finish_events[N];&#xD;&#xA;    &#xD;&#xA;    clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);&#xD;&#xA;&#xD;&#xA;    int queue_idx = 0;&#xD;&#xA;    for (int i = 0; i &lt; N; ++i) {&#xD;&#xA;      cl_command_queue queue = work_queue[queue_idx];&#xD;&#xA;&#xD;&#xA;      cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);&#xD;&#xA;&#xD;&#xA;      // Enqueue a few kernels&#xD;&#xA;      cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);&#xD;&#xA;      clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);&#xD;&#xA;&#xD;&#xA;      clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);&#xD;&#xA;&#xD;&#xA;      cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);&#xD;&#xA;      clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);&#xD;&#xA;&#xD;&#xA;      clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);&#xD;&#xA;&#xD;&#xA;      queue_idx = (queue_idx + 1) % kNumQueues;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);&#xD;&#xA;    clWaitForEvents(N, finish_events);&#xD;&#xA;&#xD;&#xA;With `kNumQueues = 1`, this application pretty much works as intended: it collects all of the work into a single command queue that then runs to completion with the GPU being fairly busy the whole time. I'm able to see this by looking at the output of the CodeXL profiler:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, when I set `kNumQueues = 2`, I expect the same thing to happen but with the work evenly split across two queues. If anything, I expect each queue to have the same characteristics individually as the one queue: that it starts work sequentially until everything is done. However, when using two queues, I can see that not all of the work is split across the two hardware queues:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;At the beginning of the GPU's work, the queues do manage to run some kernels asynchronously, although it seems like neither ever fully occupies the hardware queues (unless my understanding is mistaken). Near the end of the GPU work, it seems like the queues are adding work sequentially to only one of the hardware queues, but there are even times that no kernels are running. What gives? Do I have some fundamental misunderstanding of how the runtime is supposed to behave?&#xD;&#xA;&#xD;&#xA;I have a few theories as to why this is happening:&#xD;&#xA;&#xD;&#xA;1. The interspersed `clCreateBuffer` calls are forcing the GPU to allocate device resources from a shared memory pool synchronously which stalls the execution of individual kernels.&#xD;&#xA;&#xD;&#xA;2. The underlying OpenCL implementation does not map logical queues to physical queues, and only decides where to place objects at runtime.&#xD;&#xA;&#xD;&#xA;3. Because I'm using GL objects, the GPU needs to synchronize access to specially allocated memory during writes.&#xD;&#xA;&#xD;&#xA;Are any of these assumptions true? Does anyone know what could be causing the GPU to wait in the two-queue scenario? Any and all insight would be appreciated!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IP41r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/eDhDI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5591" PostHistoryTypeId="1" PostId="2365" RevisionGUID="5926999d-1653-47f6-bcca-64951e4e742b" CreationDate="2016-04-28T16:18:55.477" UserId="197" Text="What is my GPU waiting on?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5592" PostHistoryTypeId="3" PostId="2365" RevisionGUID="5926999d-1653-47f6-bcca-64951e4e742b" CreationDate="2016-04-28T16:18:55.477" UserId="197" Text="|gpgpu|opencl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5593" PostHistoryTypeId="2" PostId="2366" RevisionGUID="1747c333-2e11-45ce-a512-e0de280198d0" CreationDate="2016-04-28T18:11:12.010" UserId="3248" Text="I'm currently trying to develop a game using Cocos2d-x using C++&#xD;&#xA;I really need to generate this burst or (donut-shaped) pulse.&#xD;&#xA;I'm having a difficult time how to generate such shape.&#xD;&#xA;At first, I was thinking of scaling the image but that didnt work out because the line or &quot;diameter&quot; of the donut shape gets bigger accordingly..&#xD;&#xA;Any experienced coders who can provide an equation of this thing? or maybe &quot;mathematics&quot; is more exact.&#xD;&#xA;If you guys can provide ANY help, suggestion, or alternative recommendation, I'll be so glad^^&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=ewnEE5mt1ZM&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5594" PostHistoryTypeId="1" PostId="2366" RevisionGUID="1747c333-2e11-45ce-a512-e0de280198d0" CreationDate="2016-04-28T18:11:12.010" UserId="3248" Text="Generate this kind of 2d burst or pulse algorithm?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5595" PostHistoryTypeId="3" PostId="2366" RevisionGUID="1747c333-2e11-45ce-a512-e0de280198d0" CreationDate="2016-04-28T18:11:12.010" UserId="3248" Text="|c++|2d|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5596" PostHistoryTypeId="2" PostId="2367" RevisionGUID="b9066d29-3bf6-4921-860f-3939def03f02" CreationDate="2016-04-28T19:49:11.807" UserId="48" Text="Rather than using an image, I would suggest doing this kind of effect using a shader. I'm not familiar with Cocos2d-x, but some quick googling suggests that it can work with shaders. You'd use a pixel shader that calculates the distance of each pixel to the center of the pulse effect, then applies a function based on that distance to define the shape and appearance of the pulse.&#xD;&#xA;&#xD;&#xA;I made a [quick shadertoy](https://www.shadertoy.com/view/MdtXWX) as a proof of concept and example.&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/49koo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5597" PostHistoryTypeId="2" PostId="2368" RevisionGUID="9f35c803-bc43-4de7-a0c9-e804b5b1d143" CreationDate="2016-04-28T20:24:24.297" UserId="3251" Text="I have a 3d scene I use to generate some images which I then process in Matlab. I noticed that when GI is not enabled, rendering always generates exactly the same pixel-for-pixel image (as far as I can tell). However, when I enable GI, the image is not exactly the same. I have been told (I originally accidentally posted [here][1]) that GI is stochastic and so this is to be somewhat expected. However, I am curious if there's any way to avoid it (while still using GI).&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicdesign.stackexchange.com/questions/70432/gi-leading-to-image-variation/70480#70480" ContentLicense="CC BY-SA 3.0" />
  <row Id="5598" PostHistoryTypeId="1" PostId="2368" RevisionGUID="9f35c803-bc43-4de7-a0c9-e804b5b1d143" CreationDate="2016-04-28T20:24:24.297" UserId="3251" Text="GI leading to image variation" ContentLicense="CC BY-SA 3.0" />
  <row Id="5599" PostHistoryTypeId="3" PostId="2368" RevisionGUID="9f35c803-bc43-4de7-a0c9-e804b5b1d143" CreationDate="2016-04-28T20:24:24.297" UserId="3251" Text="|rendering|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5600" PostHistoryTypeId="2" PostId="2369" RevisionGUID="b4a62346-c80f-4822-a3d4-b397779dbfee" CreationDate="2016-04-28T20:43:54.790" UserId="56" Text="If you can make your samples deterministic (the same from run to run - don't based random sample points on time or any other non deterministic value), it will be a stable rendering that you get every time." ContentLicense="CC BY-SA 3.0" />
  <row Id="5601" PostHistoryTypeId="2" PostId="2370" RevisionGUID="87ed4b3d-3b09-4f6e-aed2-f2e8e9d854dd" CreationDate="2016-04-28T20:50:53.533" UserId="3233" Text="What I'm trying to do is to simulate refraction through biconcave lens described by spheres `A`, `B`, `C` where `C` is a sphere in between `A` and `B`. So far I've gathered that a good approach would be to use CSG when it comes to modeling such object. I'm failing to understand how to implement this though. There are mentions of using Interval Arithmetics but I don't understand how exactly are they supposed to help me." ContentLicense="CC BY-SA 3.0" />
  <row Id="5602" PostHistoryTypeId="1" PostId="2370" RevisionGUID="87ed4b3d-3b09-4f6e-aed2-f2e8e9d854dd" CreationDate="2016-04-28T20:50:53.533" UserId="3233" Text="How to implement Constructive Solid Geometry in ray tracing with implicit surfaces (spheres)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5603" PostHistoryTypeId="3" PostId="2370" RevisionGUID="87ed4b3d-3b09-4f6e-aed2-f2e8e9d854dd" CreationDate="2016-04-28T20:50:53.533" UserId="3233" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5607" PostHistoryTypeId="5" PostId="2369" RevisionGUID="32509c0c-5b1a-4e73-9007-9bb31f549130" CreationDate="2016-04-28T22:08:45.650" UserId="56" Comment="deleted 1 character in body" Text="If you can make your samples deterministic (the same from run to run - don't base random sample points on time or any other non deterministic value), it will be a stable rendering that you get every time." ContentLicense="CC BY-SA 3.0" />
  <row Id="5608" PostHistoryTypeId="2" PostId="2372" RevisionGUID="fc38de61-3b29-4b7e-ac78-59179347c04b" CreationDate="2016-04-29T03:32:36.057" UserId="3003" Text="If you're working in 2D, it should be enough to just take the dot product of the normals of the lines and if it is -1 or 1 then the lines are parallel, and either don't overlap or fully overlap. 2 lines cannot &quot;partially overlap&quot;. They either meet at a single point, at every point, or no points." ContentLicense="CC BY-SA 3.0" />
  <row Id="5611" PostHistoryTypeId="5" PostId="2368" RevisionGUID="113fb861-f1c8-43fe-958e-3a0d79aeb856" CreationDate="2016-04-29T03:56:50.823" UserId="38" Comment="added 22 characters in body; edited title" Text="I have a 3D scene I use to generate some images which I then process in Matlab. I noticed that when global illumination (GI) is not enabled, rendering always generates exactly the same pixel-for-pixel image (as far as I can tell). However, when I enable GI, the image is not exactly the same. I have been told (I originally accidentally posted [here][1]) that GI is stochastic and so this is to be somewhat expected. However, I am curious if there's any way to avoid it (while still using GI).&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicdesign.stackexchange.com/questions/70432/gi-leading-to-image-variation/70480#70480" ContentLicense="CC BY-SA 3.0" />
  <row Id="5612" PostHistoryTypeId="4" PostId="2368" RevisionGUID="113fb861-f1c8-43fe-958e-3a0d79aeb856" CreationDate="2016-04-29T03:56:50.823" UserId="38" Comment="added 22 characters in body; edited title" Text="Global illumination leading to image variation" ContentLicense="CC BY-SA 3.0" />
  <row Id="5613" PostHistoryTypeId="2" PostId="2374" RevisionGUID="f7bc5ce0-d550-4c91-b2cb-440fae555b9a" CreationDate="2016-04-29T07:08:27.200" UserId="2479" Text="Yes, computation of global illumination is usually done in a stochastic way and as such it relies on randomly generated numbers.&#xA;&#xA;Typically pseudo random generators are employed, which generate deterministic sequences, and usually have so called &quot;seed&quot; parameter. The seed basically says where to start in the sequence, which in turn affects the noise pattern of your rendered image. If you can use the same seed for each run, there is a high chance of getting identical results. &#xA;&#xA;The question is whether the software that you use allows you to do that. In the rendering settings, I would suggest looking for for words like seed, random or deterministic. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5614" PostHistoryTypeId="5" PostId="2374" RevisionGUID="a9ea265d-2c5e-4349-b90c-58efdc4ac6b3" CreationDate="2016-04-29T07:25:08.900" UserId="2479" Comment="Added Vray engine name" Text="Yes, computation of global illumination is usually done in a stochastic way and as such it relies on randomly generated numbers.&#xD;&#xA;&#xD;&#xA;Typically pseudo random generators are employed, which generate deterministic sequences, and usually have so called &quot;seed&quot; parameter. The seed basically says where to start in the sequence, which in turn affects the noise pattern of your rendered image. If you can use the same seed for each run, there is a high chance of getting identical results. &#xD;&#xA;&#xD;&#xA;The question is whether the software that you use allows you to do that. In the rendering settings, I would suggest looking for for words like seed, random or deterministic.&#xD;&#xA;&#xD;&#xA;**Edit:** Since you said you use Vray, it seems to me that using &quot;Deterministic Monte Carlo&quot; engine should be the way to go." ContentLicense="CC BY-SA 3.0" />
  <row Id="5616" PostHistoryTypeId="2" PostId="2375" RevisionGUID="01640a4d-e482-4a29-8a1e-bab982978d37" CreationDate="2016-04-29T13:54:57.470" UserId="209" Text="I'm not sure what exactly you are asking but, IIRC, to do CSG with ray tracing, you maintain not just the closest intersection with an object, but a list of ordered pairs of [Inpoint, OutPoint] 'interval' distances. With a single sphere test (or any solid convex primitive for that matter), this list would have at most one [Inpoint, OutPoint] entry *or* is empty if there is a miss.&#xD;&#xA;&#xD;&#xA;To implement CSG you then apply the binary operator to a pair of lists, which in turn means applying them to the entries in the lists in a manner akin to merge-sorting two lists. &#xD;&#xA;&#xD;&#xA;For example, for intersection, if you had  [a,b] in one list and [c,d] in the other, compute  e=Max(a,c) f=Min(b,d).  If e &gt; f there's no intersection else return the intersection, [e,f].&#xD;&#xA;&#xD;&#xA;Does that help?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5618" PostHistoryTypeId="2" PostId="2376" RevisionGUID="18381aa1-ab7d-4d6f-ac28-5c2958620ca5" CreationDate="2016-04-30T01:06:36.060" UserId="231" Text="The first step in your existing code calculates the orientations of one line segment relative to each of the two end points of the other line segment, using the cross product. This allows testing whether the other line segment has one end point anticlockwise and the other end point clockwise from the first line segment, indicating that the line on which the first segment lies cuts the other segment.&#xD;&#xA;&#xD;&#xA;Rather than writing a new test, you can use these same orientations to test for line segments that overlap (including partial overlap). If the lines on which the segments lie are the same, then all four orientations calculated in your first step will be zero, because none of the end points are either clockwise or anticlockwise from the line, since they are on the line. Then it remains only to check whether the two segments on the same line overlap, by checking whether either of them has an end point between the end points of the other segment." ContentLicense="CC BY-SA 3.0" />
  <row Id="5619" PostHistoryTypeId="5" PostId="2376" RevisionGUID="00ebbb4b-73ee-4804-a0aa-faa0d58ba417" CreationDate="2016-04-30T01:13:58.043" UserId="231" Comment="Improve clarity" Text="The first step in your existing code calculates the orientations of one line segment relative to each of the two end points of the other line segment, using the cross product. This allows testing whether the other line segment has one end point anticlockwise and the other end point clockwise from the first line segment, indicating that the line on which the first segment lies cuts the other segment.&#xD;&#xA;&#xD;&#xA;Rather than writing a new test, you can use these same orientations to test for line segments that overlap (including partial overlap). If both segments lie on the same line, then all four orientations calculated in your first step will be zero, because none of the end points are either clockwise or anticlockwise from the line, since they are on the line. Then it remains only to check whether the two segments on the same line overlap, by checking whether either of them has an end point between the end points of the other segment." ContentLicense="CC BY-SA 3.0" />
  <row Id="5621" PostHistoryTypeId="2" PostId="2377" RevisionGUID="8cced7d3-7542-4278-85d7-3402ac0122fe" CreationDate="2016-04-30T10:43:15.217" UserId="3267" Text="Recently I'm developing a simple Monte-Carlo path tracer. To measure my tracer's performance, I decided to implement a simple mechanism to count how many rays can it trace in a second. Then here comes the problem, there are two ways to recognize a single ray:&#xD;&#xA;&#xD;&#xA;&gt; 1. A complete ray, i.e., starting from camera and bouncing around the scene until it terminates.&#xD;&#xA;&gt; &#xD;&#xA;&gt; 2. The ray originated from each intersection point.&#xD;&#xA;&#xD;&#xA;Although many people use &quot;Rays per Second&quot; to measure ray/path tracer's performance, how they recognize &quot;rays&quot; is unclear to me. Perhapes anybody knows?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5622" PostHistoryTypeId="1" PostId="2377" RevisionGUID="8cced7d3-7542-4278-85d7-3402ac0122fe" CreationDate="2016-04-30T10:43:15.217" UserId="3267" Text="How does everyone count &quot;Rays per Second&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5623" PostHistoryTypeId="3" PostId="2377" RevisionGUID="8cced7d3-7542-4278-85d7-3402ac0122fe" CreationDate="2016-04-30T10:43:15.217" UserId="3267" Text="|raytracing|performance|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5624" PostHistoryTypeId="5" PostId="2377" RevisionGUID="8a72bb33-36a5-4580-82bb-2638d535d6fe" CreationDate="2016-04-30T14:42:14.363" UserId="3267" Comment="deleted 4 characters in body" Text="Recently I'm developing a simple Monte-Carlo path tracer. To measure my tracer's performance, I decided to implement a simple mechanism to count how many rays can it trace in a second. Then here comes the problem, there are two ways to define a single ray:&#xD;&#xA;&#xD;&#xA;&gt; 1. A complete ray, i.e., starting from camera and bouncing around the scene until it terminates.&#xD;&#xA;&gt; &#xD;&#xA;&gt; 2. The ray originated from each intersection point.&#xD;&#xA;&#xD;&#xA;Although many people use &quot;Rays per Second&quot; to measure ray/path tracer's performance, how they recognize &quot;rays&quot; is unclear to me. Perhaps anybody knows?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5625" PostHistoryTypeId="5" PostId="2377" RevisionGUID="28aa32d2-67b7-4c9b-9848-4628de917cb5" CreationDate="2016-04-30T18:59:36.110" UserId="3267" Comment="deleted 7 characters in body" Text="Recently I'm developing a Monte-Carlo path tracer. To measure my tracer's performance, I decided to implement a simple mechanism to count how many rays can it trace in a second. Then here comes the problem, there are two ways to define a single ray:&#xD;&#xA;&#xD;&#xA;&gt; 1. A complete ray, i.e., starting from camera and bouncing around the scene until it terminates.&#xD;&#xA;&gt; &#xD;&#xA;&gt; 2. The ray originated from each intersection point.&#xD;&#xA;&#xD;&#xA;Although many people use &quot;Rays per Second&quot; to measure ray/path tracer's performance, how they recognize &quot;rays&quot; is unclear to me. Perhaps anybody knows?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5626" PostHistoryTypeId="2" PostId="2378" RevisionGUID="60ea9a61-c97e-4a2a-989f-b6f079b1c8f7" CreationDate="2016-04-30T19:06:49.000" UserId="3271" Text="We have a matrix      &#xD;&#xA;a11 a12 a13   &#xD;&#xA;a21 a22 a23  &#xD;&#xA;a31 a32 a33  &#xD;&#xA;     &#xD;&#xA;This matrix represents a transformation in homogeneous coordinates.&#xD;&#xA;My question is whether the above matrix is affine or not and an example too for this.                  " ContentLicense="CC BY-SA 3.0" />
  <row Id="5627" PostHistoryTypeId="1" PostId="2378" RevisionGUID="60ea9a61-c97e-4a2a-989f-b6f079b1c8f7" CreationDate="2016-04-30T19:06:49.000" UserId="3271" Text="Affine Transformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="5628" PostHistoryTypeId="3" PostId="2378" RevisionGUID="60ea9a61-c97e-4a2a-989f-b6f079b1c8f7" CreationDate="2016-04-30T19:06:49.000" UserId="3271" Text="|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5629" PostHistoryTypeId="2" PostId="2379" RevisionGUID="dc8f1a35-daeb-4647-a6ae-f74b88a1b0ed" CreationDate="2016-04-30T22:00:59.013" UserId="48" Text="It is not necessarily affine. An affine matrix in homogeneous coordinates has a form like:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} a_{11} &amp; a_{12} &amp; a_{13} \\ a_{21} &amp; a_{22} &amp; a_{23} \\ 0 &amp; 0 &amp; 1 \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;(assuming you use a column vector convention). Here, the upper-left 2&amp;times;2 submatrix is the linear part, and $(a_{13}, a_{23})$ is the translation vector of the affine transform.&#xD;&#xA;&#xD;&#xA;If the lower row of the matrix has some values other than $[0, 0, 1]$, then it is in general a projective transform, not an affine one." ContentLicense="CC BY-SA 3.0" />
  <row Id="5630" PostHistoryTypeId="5" PostId="2378" RevisionGUID="49be5da2-de50-4a52-8643-2e4c7d7c8dcb" CreationDate="2016-04-30T22:02:29.723" UserId="48" Comment="math formatting + added tags" Text="We have a matrix      &#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} a_{11} &amp; a_{12} &amp; a_{13} \\ a_{21} &amp; a_{22} &amp; a_{23} \\ a_{31} &amp; a_{32} &amp; a_{33} \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This matrix represents a transformation in homogeneous coordinates.&#xD;&#xA;My question is whether the above matrix is affine or not and an example too for this.                  " ContentLicense="CC BY-SA 3.0" />
  <row Id="5631" PostHistoryTypeId="6" PostId="2378" RevisionGUID="49be5da2-de50-4a52-8643-2e4c7d7c8dcb" CreationDate="2016-04-30T22:02:29.723" UserId="48" Comment="math formatting + added tags" Text="|transformations|affine-transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5632" PostHistoryTypeId="2" PostId="2380" RevisionGUID="b1ed86df-5d8e-4816-bb45-f04f4946e2e2" CreationDate="2016-04-30T22:55:42.313" UserId="3075" Text="I've seen both, unfortunately. I'm not fond of rays per second as meaning exclusively primary rays and I'd suggest &quot;paths per second&quot; or better yet &quot;samples per second&quot; instead. &quot;Complete ray&quot; is not a common term: a ray is a (potentially unbounded) line segment and a sequence of rays is a path.&#xD;&#xA;&#xD;&#xA;Rays per second in your second sense of total ray casts is not well-specified for a path tracer: do shadow rays count, for instance? It's a useful metric for evaluating an acceleration structure or intersection testing framework (i.e. Embree or OptiX) but I'd avoid it for a renderer.&#xD;&#xA;&#xD;&#xA;Finally, be aware that samples per second still isn't a great metric of actual performance since sample quality will vary wildly depending on implementation details. It's probably the best thing you can do starting out though, as the better solutions involve fairly complex variance estimates." ContentLicense="CC BY-SA 3.0" />
  <row Id="5634" PostHistoryTypeId="2" PostId="2381" RevisionGUID="7962d98f-cc1e-4d0e-8e85-be2407c29608" CreationDate="2016-05-01T03:48:18.253" UserId="3271" Text="In a plane, we have a **convex** polygon with n sides. what would be the maximum number of disconnected pieces / fragments if this polygon is clipped against a square?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5635" PostHistoryTypeId="1" PostId="2381" RevisionGUID="7962d98f-cc1e-4d0e-8e85-be2407c29608" CreationDate="2016-05-01T03:48:18.253" UserId="3271" Text="finding the maximum number of disconnected fragments" ContentLicense="CC BY-SA 3.0" />
  <row Id="5636" PostHistoryTypeId="3" PostId="2381" RevisionGUID="7962d98f-cc1e-4d0e-8e85-be2407c29608" CreationDate="2016-05-01T03:48:18.253" UserId="3271" Text="|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5640" PostHistoryTypeId="5" PostId="2365" RevisionGUID="f9b7c019-5d33-45d2-a6f0-0a3040fb39cf" CreationDate="2016-05-01T16:04:46.257" UserId="197" Comment="added 413 characters in body" Text="I am writing an OpenCL program for use with my AMD Radeon HD 7800 series GPU. According to AMD's [OpenCL programming guide](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/07/AMD_Accelerated_Parallel_Processing_OpenCL_Programming_Guide-rev-2.7.pdf), this generation of GPU has two hardware queues that can operate asynchronously.&#xD;&#xA;&#xD;&#xA;&gt; **5.5.6 Command Queue**&#xD;&#xA;&gt;&#xD;&#xA;&gt; For Southern Islands and later, devices support at least two hardware compute&#xD;&#xA;queues. That allows an application to increase the throughput of small dispatches&#xD;&#xA;with two command queues for asynchronous submission and possibly execution.&#xD;&#xA;The hardware compute queues are selected in the following order: first queue =&#xD;&#xA;even OCL command queues, second queue = odd OCL queues.&#xD;&#xA;&#xD;&#xA;To do this, I've created two separate OpenCL command queues to feed data to the GPU. Roughly, [the program running on the host thread](https://github.com/Mokosha/GenTC/blob/SeparateGLSync/codec/codec.cpp#L570) looks something like this:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    static const int kNumQueues = 2;&#xD;&#xA;    cl_command_queue default_queue;&#xD;&#xA;    cl_command_queue work_queue[kNumQueues];&#xD;&#xA;&#xD;&#xA;    static const int N = 256;&#xD;&#xA;    cl_mem gl_buffers[N];&#xD;&#xA;    cl_event finish_events[N];&#xD;&#xA;    &#xD;&#xA;    clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);&#xD;&#xA;&#xD;&#xA;    int queue_idx = 0;&#xD;&#xA;    for (int i = 0; i &lt; N; ++i) {&#xD;&#xA;      cl_command_queue queue = work_queue[queue_idx];&#xD;&#xA;&#xD;&#xA;      cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);&#xD;&#xA;&#xD;&#xA;      // Enqueue a few kernels&#xD;&#xA;      cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);&#xD;&#xA;      clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);&#xD;&#xA;&#xD;&#xA;      clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);&#xD;&#xA;&#xD;&#xA;      cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);&#xD;&#xA;      clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);&#xD;&#xA;&#xD;&#xA;      clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);&#xD;&#xA;&#xD;&#xA;      queue_idx = (queue_idx + 1) % kNumQueues;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);&#xD;&#xA;    clWaitForEvents(N, finish_events);&#xD;&#xA;&#xD;&#xA;With `kNumQueues = 1`, this application pretty much works as intended: it collects all of the work into a single command queue that then runs to completion with the GPU being fairly busy the whole time. I'm able to see this by looking at the output of the CodeXL profiler:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, when I set `kNumQueues = 2`, I expect the same thing to happen but with the work evenly split across two queues. If anything, I expect each queue to have the same characteristics individually as the one queue: that it starts work sequentially until everything is done. However, when using two queues, I can see that not all of the work is split across the two hardware queues:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;At the beginning of the GPU's work, the queues do manage to run some kernels asynchronously, although it seems like neither ever fully occupies the hardware queues (unless my understanding is mistaken). Near the end of the GPU work, it seems like the queues are adding work sequentially to only one of the hardware queues, but there are even times that no kernels are running. What gives? Do I have some fundamental misunderstanding of how the runtime is supposed to behave?&#xD;&#xA;&#xD;&#xA;I have a few theories as to why this is happening:&#xD;&#xA;&#xD;&#xA;1. The interspersed `clCreateBuffer` calls are forcing the GPU to allocate device resources from a shared memory pool synchronously which stalls the execution of individual kernels.&#xD;&#xA;&#xD;&#xA;2. The underlying OpenCL implementation does not map logical queues to physical queues, and only decides where to place objects at runtime.&#xD;&#xA;&#xD;&#xA;3. Because I'm using GL objects, the GPU needs to synchronize access to specially allocated memory during writes.&#xD;&#xA;&#xD;&#xA;Are any of these assumptions true? Does anyone know what could be causing the GPU to wait in the two-queue scenario? Any and all insight would be appreciated!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IP41r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/eDhDI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5641" PostHistoryTypeId="2" PostId="2383" RevisionGUID="d8be5cac-65e1-47e7-8018-05eafb9b5bc0" CreationDate="2016-05-01T22:02:24.773" UserId="3277" Text="I have been studying computer graphics, from the book [Fundamentals of Computer Graphic][1] (but the third edition), and I lastly read about projections. Though, I didn't exactly understand what's the difference between orthographic and perspective projection? Why do we need both of them, where are they used? I also would like to learn what is *perspective transform* that is applied before orthographic projection in perspective projection. Lastly, why do we need the viewport transformation? I mean we use view transformation if the camera/viewer is not looking at $-z$-direction, but what about the viewport?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.amazon.com/Fundamentals-Computer-Graphics-Fourth-Marschner/dp/1482229390/ref=sr_1_4?s=books&amp;ie=UTF8&amp;qid=1462139810&amp;sr=1-4&amp;keywords=computer%20graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="5642" PostHistoryTypeId="1" PostId="2383" RevisionGUID="d8be5cac-65e1-47e7-8018-05eafb9b5bc0" CreationDate="2016-05-01T22:02:24.773" UserId="3277" Text="What's the difference between orthographic and perspective projection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5643" PostHistoryTypeId="3" PostId="2383" RevisionGUID="d8be5cac-65e1-47e7-8018-05eafb9b5bc0" CreationDate="2016-05-01T22:02:24.773" UserId="3277" Text="|3d|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5644" PostHistoryTypeId="5" PostId="2359" RevisionGUID="960de44f-5c57-4951-8861-82b38e2d9317" CreationDate="2016-05-02T09:02:03.433" UserId="3225" Comment="be more precise" Text="I have an application in which I am using an octree to store a volume mesh of axis-aligned bounding boxes (AABBs).&#xD;&#xA;&#xD;&#xA;Given a water-tight triangle mesh, I need to:&#xD;&#xA;&#xD;&#xA;- find if an AABB is intersected by or completely inside/outside of the surface mesh,&#xD;&#xA;&#xD;&#xA;- clip the surface mesh with the intersected AABBs to generate triangles that completely lie within each AABB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The triangulation and the octree containing the AABBs are both dynamic. The number of leaf nodes in the octree is huge. The number of triangles in the surface mesh is much smaller (O(10^9 - 10^13) octree nodes, vs O(10^6) triangles).&#xD;&#xA;&#xD;&#xA;Which data-structures and algorithm are suitable for my problem?&#xD;&#xA;&#xD;&#xA;Right now I:&#xD;&#xA;&#xD;&#xA; - store the triangles in the same octree as the volume mesh,&#xD;&#xA; - store each triangle in the smallest octree node that contains it,&#xD;&#xA; - clip the triangle mesh with a single AABB by traversing from that AABB to both the root node and its leafs clipping each triangle contained in the nodes with the AABB. &#xD;&#xA;&#xD;&#xA;The triangles in the nodes until the leafs are fully contained within the AABB and don't need any clipping, while the ones contained in the nodes from the AABB to the root need clipping. However:&#xD;&#xA;&#xD;&#xA; -  due to the way I am storing the triangles I don't have an upper bound in the maximum number of triangles that can be store within each single octree node, so I don't have an upper bound in the number of triangles that have to be clip when clipping the surface mesh with a single AABB.&#xD;&#xA;&#xD;&#xA; - testing if an AABB is intersected by the triangle mesh might require &quot;clipping&quot; if there are triangles stored in the root node (as opposed to just traverse the tree up and down and doing nothing if the nodes don't contain any triangles).&#xD;&#xA;&#xD;&#xA; - have no fast way of determining if a node is inside/outside/intersected by the mesh." ContentLicense="CC BY-SA 3.0" />
  <row Id="5645" PostHistoryTypeId="5" PostId="2359" RevisionGUID="887159f9-2246-4d5b-8d52-49c198984fcd" CreationDate="2016-05-02T09:10:15.263" UserId="3225" Comment="be more precise" Text="I have an application in which I am using an octree to store a volume mesh of axis-aligned bounding boxes (AABBs).&#xD;&#xA;&#xD;&#xA;Given a water-tight triangle mesh, I need to:&#xD;&#xA;&#xD;&#xA;- find if an AABB is intersected by or completely inside/outside of the surface mesh,&#xD;&#xA;&#xD;&#xA;- clip the surface mesh with the intersected AABBs to generate triangles that completely lie within each AABB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The triangulation and the octree containing the AABBs are both dynamic. The number of leaf nodes in the octree is huge. The number of triangles in the surface mesh is much smaller (O(10^9 - 10^13) octree nodes, vs O(10^6) triangles).&#xD;&#xA;&#xD;&#xA;Which data-structures and algorithm are suitable for my problem?&#xD;&#xA;&#xD;&#xA;Right now I:&#xD;&#xA;&#xD;&#xA; - store the triangles in the same octree as the volume mesh,&#xD;&#xA; - store each triangle in the smallest octree node that contains it,&#xD;&#xA; - clip the triangle mesh with a single AABB by traversing from that AABB to both the root node and its leafs clipping each triangle contained in the nodes with the AABB. &#xD;&#xA;&#xD;&#xA;The triangles in the nodes until the leafs are fully contained within the AABB and don't need any &quot;clipping&quot; (the AABB just contains those triangles), while the ones contained in the nodes from the AABB to the root need clipping. However:&#xD;&#xA;&#xD;&#xA; -  due to the way I am storing the triangles (in the smallest octree node that fully contains them) I don't have an upper bound in the maximum number of triangles that can be stored within each single octree node, so I don't have an upper bound in the number of triangles that have to be tested against a single AABB.&#xD;&#xA;&#xD;&#xA; - if I just want to test if an AABB is intersected by the triangle mesh, I have to test all triangles between that AABB and the root node which might be expensive. Ideally I would like to have a very fast way to test, and then clip the mesh if the test is true.&#xD;&#xA;&#xD;&#xA; - have no fast way of determining if a node is inside/outside/intersected by the mesh.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- moving the triangle mesh requires manipulating the octree (I don't know if this can be avoided). Ideally I would like to generate an octree for the triangle mesh once, and then just move the mesh using a single transformation matrix. However, then I would need to have some sort of mapping between &quot;the octree containing the triangle mesh&quot; and &quot;the octree of my volume mesh&quot;. Maybe this is trivial but I haven't figured it out yet." ContentLicense="CC BY-SA 3.0" />
  <row Id="5646" PostHistoryTypeId="5" PostId="2359" RevisionGUID="954f6ceb-5af0-435b-a2bd-41f9731410ba" CreationDate="2016-05-02T09:16:48.533" UserId="3225" Comment="added 3 characters in body" Text="I have an application in which I am using an octree to store a volume mesh of axis-aligned bounding boxes (AABBs).&#xD;&#xA;&#xD;&#xA;Given a water-tight triangle mesh, I need to:&#xD;&#xA;&#xD;&#xA;- find if an AABB is intersected by or completely inside/outside of the surface mesh,&#xD;&#xA;&#xD;&#xA;- clip the surface mesh with the intersected AABBs to generate triangles that completely lie within each AABB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The triangulation and the octree containing the AABBs are both dynamic. The number of leaf nodes in the octree is huge. The number of triangles in the surface mesh is much smaller (O(10^9 - 10^13) octree nodes, vs O(10^6) triangles).&#xD;&#xA;&#xD;&#xA;Which data-structures and algorithm are suitable for my problem?&#xD;&#xA;&#xD;&#xA;Right now I:&#xD;&#xA;&#xD;&#xA; - store the triangles in the same octree as the volume mesh,&#xD;&#xA; - store each triangle in the smallest octree node that contains it,&#xD;&#xA; - clip the triangle mesh with a single AABB by traversing from that AABB to both the root node and its leafs clipping each triangle contained in the nodes with the AABB. &#xD;&#xA;&#xD;&#xA;The triangles in the nodes until the leafs are fully contained within the AABB and don't need any &quot;clipping&quot; (the AABB just contains those triangles), while the ones contained in the nodes from the AABB to the root need clipping. However:&#xD;&#xA;&#xD;&#xA; -  due to the way I am storing the triangles (in the smallest octree node that fully contains them) I don't have an upper bound in the maximum number of triangles that can be stored within each single octree node, so I don't have an upper bound in the number of triangles that have to be tested against a single AABB.&#xD;&#xA;&#xD;&#xA; - if I just want to test if an AABB is intersected by the triangle mesh, I have to test all triangles between that AABB and the root node which might be expensive. Ideally I would like to have a very fast way to test, and then clip the mesh if the test is true.&#xD;&#xA;&#xD;&#xA; - currently I have no fast way of determining if a node is inside/outside/intersected by the mesh. I could construct a signed distance field (which is expensive), or perform some ray casting (which is also expensive), maybe there is a better solution or maybe I just need to precompute something to speed this up every time I move the triangle mesh.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - moving the triangle mesh requires manipulating the octree (I don't know if this can be avoided). Ideally I would like to generate an octree for the triangle mesh once, and then just move the mesh using a single transformation matrix. However, then I would need to have some sort of mapping between &quot;the octree containing the triangle mesh&quot; and &quot;the octree of my volume mesh&quot;. Maybe this mapping is trivial but I haven't figured it out yet. This would save me from manipulating the octree when I move the mesh and maybe the coordinate transformations that would be required are negligible with the cost of clipping." ContentLicense="CC BY-SA 3.0" />
  <row Id="5650" PostHistoryTypeId="2" PostId="2385" RevisionGUID="435c8f25-c497-4d9c-aa77-ddeef6c1da8f" CreationDate="2016-05-02T10:18:12.757" UserId="38" Text="Orthographic projections are parallel projections. Each line that is originally parallel will be parallel after this transformation. The orthographic projection can be represented by a affine transformation.&#xD;&#xA;&#xD;&#xA;In contrast a perspective projection is not a parallel projection and originally parallel lines will no longer be parallel after this operation. Thus orthographic projection can not be done by a affine transform.&#xD;&#xA;&#xD;&#xA;Why would you need orthographic projections? It is useful for several artistic and technical reasons. Orthographic projections are used in CAD drawings and other technical documentations. One of the primary reasons is to verify that your part actually fits in the space that has been reserved for it on a floor plan for example. Orthographic projections are often chosen so that the dimensions are easy to measure. In many cases this is just a convenient way to represent a problem in a different basis so that coordinates are easier to figure out.&#xD;&#xA;&#xD;&#xA;[![ortho][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A number of useful orthographic projections for same object (and projection rule). The last on on the right is a special case called isometric having the property that cardinal axe directions are all in same scale.&#xD;&#xA;&#xD;&#xA;A perspective projection is needed to be able to do 2 and 3 point perspectives, which is how we experience the world. A specific perspective projection can be decomposed as being a combination of a orthographic projection and a perspective divide.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 point perspective note how the lines in prespective direction no longer are parallel&#xD;&#xA;&#xD;&#xA;View port transformation allows you to pan/rotate/scale the resulting projection. Maybe because you want a off center projection like in cameras with film offset, or you have a anisotropic medium for example. It can sloe be convenient for the end user.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5zqm3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/urTYN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5651" PostHistoryTypeId="5" PostId="2385" RevisionGUID="509d6fa0-a6e9-4dda-9d9a-15150b4ce5fb" CreationDate="2016-05-02T10:24:59.497" UserId="38" Comment="deleted 1 character in body" Text="Orthographic projections are parallel projections. Each line that is originally parallel will be parallel after this transformation. The orthographic projection can be represented by a affine transformation.&#xD;&#xA;&#xD;&#xA;In contrast a perspective projection is not a parallel projection and originally parallel lines will no longer be parallel after this operation. Thus orthographic projection can not be done by a affine transform.&#xD;&#xA;&#xD;&#xA;Why would you need orthographic projections? It is useful for several artistic and technical reasons. Orthographic projections are used in CAD drawings and other technical documentations. One of the primary reasons is to verify that your part actually fits in the space that has been reserved for it on a floor plan for example. Orthographic projections are often chosen so that the dimensions are easy to measure. In many cases this is just a convenient way to represent a problem in a different basis so that coordinates are easier to figure out.&#xD;&#xA;&#xD;&#xA;[![ortho][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A number of useful orthographic projections for same object (and projection rule). The last on on the right is a special case called isometric having the property that cardinal axe directions are all in same scale.&#xD;&#xA;&#xD;&#xA;A perspective projection is needed to be able to do 2 and 3 point perspectives, which is how we experience the world. A specific perspective projection can be decomposed as being a combination of a orthographic projection and a perspective divide.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 point perspective note how the lines in prespective direction no longer are parallel&#xD;&#xA;&#xD;&#xA;Viewport transformation allows you to pan/rotate/scale the resulting projection. Maybe because you want a off center projection like in cameras with film offset, or you have a anisotropic medium for example. It can sloe be convenient for the end user.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5zqm3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/urTYN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5652" PostHistoryTypeId="2" PostId="2386" RevisionGUID="ccc18a37-73f8-4b63-8adf-6678a3f506e0" CreationDate="2016-05-02T19:56:03.910" UserId="3277" Text="I have been studying computer graphics, from the book [Fundamentals of Computer Graphic][1] (but the third edition), and I lastly read about texture mapping and shadow maps. Though, I didn't exactly understand how they function. I know there is also another type of texture map called projective texture map which allows to cast hard shadows, but how they function? On the other hand, how are soft shadows cast? And what's exactly the difference between hard and soft shadows?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.amazon.com/Fundamentals-Computer-Graphics-Fourth-Marschner/dp/1482229390/ref=sr_1_4?s=books&amp;ie=UTF8&amp;qid=1462139810&amp;sr=1-4&amp;keywords=computer%20graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="5653" PostHistoryTypeId="1" PostId="2386" RevisionGUID="ccc18a37-73f8-4b63-8adf-6678a3f506e0" CreationDate="2016-05-02T19:56:03.910" UserId="3277" Text="How are hard and soft shadows cast?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5654" PostHistoryTypeId="3" PostId="2386" RevisionGUID="ccc18a37-73f8-4b63-8adf-6678a3f506e0" CreationDate="2016-05-02T19:56:03.910" UserId="3277" Text="|texture|3d|shadow|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5655" PostHistoryTypeId="2" PostId="2387" RevisionGUID="9d5abb63-2681-4610-82a8-3ae0ece3ae9c" CreationDate="2016-05-02T20:16:32.843" UserId="137" Text="Hard shadows are simple that only needs a point light. &#xD;&#xA;&#xD;&#xA;How it's done is by rendering the scene from the point of view of the light and only keep only the depth information. This is the shadow map.&#xD;&#xA;&#xD;&#xA;Then when doing the actual rendering you calculate the point on the triangle in world space and find where it would be on the shadow map. Then you sample the depth from the shadowmap at that point and compare it to the distance to the light.&#xD;&#xA;&#xD;&#xA;Soft shadows are harder. They require figuring out how close you are to the edge of what would be a hard shadow and adjusting the light value based on that. There are several techniques for that. One of which is simply sampling multiple times. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5656" PostHistoryTypeId="5" PostId="1444" RevisionGUID="49c98d1d-48ea-4d51-8259-21208dda6210" CreationDate="2016-05-02T22:40:12.990" UserId="48" Comment="correct the rounding; just learned that it's down, not up." Text="The rule is that to compute the next mipmap size, you divide by two and round down to the nearest integer (unless it rounds down to 0, in which case, it's 1 instead). For example, a 57x43 image would have mipmaps like:&#xD;&#xA;&#xD;&#xA;    level 0: 57x43&#xD;&#xA;    level 1: 28x21&#xD;&#xA;    level 2: 14x10&#xD;&#xA;    level 3: 7x5&#xD;&#xA;    level 4: 3x2&#xD;&#xA;    level 5: 1x1&#xD;&#xA;&#xD;&#xA;UV mapping, LOD selection, and filtering work just the same way as for power-of-two texture sizes.&#xD;&#xA;&#xD;&#xA;Generating good quality mips for a non-power-of-two texture is a little trickier, as you can't simply average a 2x2 box of pixels to downsample in all cases. However, a 2x2 box filter wasn't that great to begin with, so using a better downsampling filter such as Mitchell-Netravali is recommended regardless of the texture size." ContentLicense="CC BY-SA 3.0" />
  <row Id="5657" PostHistoryTypeId="2" PostId="2388" RevisionGUID="eef25a27-2d27-4892-9feb-4f659e2abd70" CreationDate="2016-05-03T03:27:35.803" UserId="54" Text="@ratchetfreak's answer describes shadow mapping, however, there's another not so difficult to implement way of drawing hard shadows. The [*shadow volume*](https://en.wikipedia.org/wiki/Shadow_volume) technique uses extruded geometry plus some [stencil buffer](http://computergraphics.stackexchange.com/q/12/54) tricks to simulate the area occluded by an object. The idea behind it is to generate a volume from the light source's perspective and then render it as you would render other geometry. The resulting shadow geometry will be as accurate as your graphics hardware is capable of rendering it, so the shadows will be very clear cut. There's no simple way of producing soft shadow edges with this technique though.&#xD;&#xA;&#xD;&#xA;[![shadow volume][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sRO84.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5658" PostHistoryTypeId="5" PostId="2365" RevisionGUID="13f80e02-4635-4e56-9c8b-11e91280eb44" CreationDate="2016-05-03T03:51:59.007" UserId="197" Comment="deleted 8 characters in body" Text="I am writing an OpenCL program for use with my AMD Radeon HD 7800 series GPU. According to AMD's [OpenCL programming guide](http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/07/AMD_Accelerated_Parallel_Processing_OpenCL_Programming_Guide-rev-2.7.pdf), this generation of GPU has two hardware queues that can operate asynchronously.&#xD;&#xA;&#xD;&#xA;&gt; **5.5.6 Command Queue**&#xD;&#xA;&gt;&#xD;&#xA;&gt; For Southern Islands and later, devices support at least two hardware compute&#xD;&#xA;queues. That allows an application to increase the throughput of small dispatches&#xD;&#xA;with two command queues for asynchronous submission and possibly execution.&#xD;&#xA;The hardware compute queues are selected in the following order: first queue =&#xD;&#xA;even OCL command queues, second queue = odd OCL queues.&#xD;&#xA;&#xD;&#xA;To do this, I've created two separate OpenCL command queues to feed data to the GPU. Roughly, [the program running on the host thread](https://github.com/Mokosha/GenTC/blob/master/codec/codec.cpp#L242) looks something like this:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    static const int kNumQueues = 2;&#xD;&#xA;    cl_command_queue default_queue;&#xD;&#xA;    cl_command_queue work_queue[kNumQueues];&#xD;&#xA;&#xD;&#xA;    static const int N = 256;&#xD;&#xA;    cl_mem gl_buffers[N];&#xD;&#xA;    cl_event finish_events[N];&#xD;&#xA;    &#xD;&#xA;    clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);&#xD;&#xA;&#xD;&#xA;    int queue_idx = 0;&#xD;&#xA;    for (int i = 0; i &lt; N; ++i) {&#xD;&#xA;      cl_command_queue queue = work_queue[queue_idx];&#xD;&#xA;&#xD;&#xA;      cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);&#xD;&#xA;&#xD;&#xA;      // Enqueue a few kernels&#xD;&#xA;      cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);&#xD;&#xA;      clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);&#xD;&#xA;&#xD;&#xA;      clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);&#xD;&#xA;&#xD;&#xA;      cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);&#xD;&#xA;      clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);&#xD;&#xA;&#xD;&#xA;      clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);&#xD;&#xA;&#xD;&#xA;      queue_idx = (queue_idx + 1) % kNumQueues;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);&#xD;&#xA;    clWaitForEvents(N, finish_events);&#xD;&#xA;&#xD;&#xA;With `kNumQueues = 1`, this application pretty much works as intended: it collects all of the work into a single command queue that then runs to completion with the GPU being fairly busy the whole time. I'm able to see this by looking at the output of the CodeXL profiler:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, when I set `kNumQueues = 2`, I expect the same thing to happen but with the work evenly split across two queues. If anything, I expect each queue to have the same characteristics individually as the one queue: that it starts work sequentially until everything is done. However, when using two queues, I can see that not all of the work is split across the two hardware queues:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;At the beginning of the GPU's work, the queues do manage to run some kernels asynchronously, although it seems like neither ever fully occupies the hardware queues (unless my understanding is mistaken). Near the end of the GPU work, it seems like the queues are adding work sequentially to only one of the hardware queues, but there are even times that no kernels are running. What gives? Do I have some fundamental misunderstanding of how the runtime is supposed to behave?&#xD;&#xA;&#xD;&#xA;I have a few theories as to why this is happening:&#xD;&#xA;&#xD;&#xA;1. The interspersed `clCreateBuffer` calls are forcing the GPU to allocate device resources from a shared memory pool synchronously which stalls the execution of individual kernels.&#xD;&#xA;&#xD;&#xA;2. The underlying OpenCL implementation does not map logical queues to physical queues, and only decides where to place objects at runtime.&#xD;&#xA;&#xD;&#xA;3. Because I'm using GL objects, the GPU needs to synchronize access to specially allocated memory during writes.&#xD;&#xA;&#xD;&#xA;Are any of these assumptions true? Does anyone know what could be causing the GPU to wait in the two-queue scenario? Any and all insight would be appreciated!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IP41r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/eDhDI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5659" PostHistoryTypeId="5" PostId="2385" RevisionGUID="36231bed-3f7c-44f4-bad9-7aed7912186b" CreationDate="2016-05-03T04:57:00.327" UserId="38" Comment="added 53 characters in body" Text="Orthographic projections are parallel projections. Each line that is originally parallel will be parallel after this transformation. The orthographic projection can be represented by a affine transformation.&#xD;&#xA;&#xD;&#xA;In contrast a perspective projection is not a parallel projection and originally parallel lines will no longer be parallel after this operation. Thus orthographic projection can not be done by a affine transform.&#xD;&#xA;&#xD;&#xA;Why would you need orthographic projections? It is useful for several artistic and technical reasons. Orthographic projections are used in CAD drawings and other technical documentations. One of the primary reasons is to verify that your part actually fits in the space that has been reserved for it on a floor plan for example. Orthographic projections are often chosen so that the dimensions are easy to measure. In many cases this is just a convenient way to represent a problem in a different basis so that coordinates are easier to figure out.&#xD;&#xA;&#xD;&#xA;[![ortho][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A number of useful orthographic projections for same object (and projection rule). The last on on the right is a special case called isometric having the property that cardinal axe directions are all in same scale.&#xD;&#xA;&#xD;&#xA;A perspective projection is needed to be able to do 2 and 3 point perspectives, which is how we experience the world. A specific perspective projection can be decomposed as being a combination of a orthographic projection and a perspective divide.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 point perspective note how the lines in prespective direction no longer are parallel&#xD;&#xA;&#xD;&#xA;Viewport transformation allows you to pan/rotate/scale the resulting projection. Maybe because you want a off center projection like in cameras with film offset, or you have a anisotropic medium for example. It can alse be convenient for the end user as he can zoom areas without changing the perpective.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5zqm3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/urTYN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5660" PostHistoryTypeId="5" PostId="1869" RevisionGUID="37adf1db-ba9d-4223-a457-2bdd1ebe98e0" CreationDate="2016-05-03T05:34:42.030" UserId="1683" Comment="added 4 characters in body" Text="There are numerous upscaling and downscaling algorithms available to scale images from any resolution to any other arbitrary resolution. Each algorithm typically involves a trade-off between efficiency, smoothness and sharpness, with varying degrees of each trade-off for different algorithms.&#xD;&#xA;&#xD;&#xA;Check out [this Wikipedia article][1] for such algorithms and examples of such algorithms.&#xD;&#xA;&#xD;&#xA;The most popularly known (and used) algorithm is the [Bicubic interpolation][2] algorithm. It interpolates between 2D points on a rectangular grid. Using [Cubic Splines][3] (or Cubic Interpolation), It first interpolates on one dimension (finds the interpolated row/column), then interpolates the interpolated row/column in the other dimension.&#xD;&#xA;&#xD;&#xA;Bilinear interpolation is similar to Bicubic interpolation, except the former interpolates using a linear function and can interpolate only between two values and the latter uses a cubic function and can interpolate between four values.&#xD;&#xA;&#xD;&#xA;The simple function for Bicubic interpolation is as follows:&#xD;&#xA;&#xD;&#xA;    f(f(p00, p01, p02, p03, y), f(p10, p11, p12, p13, y), f(p20, p21, p22, p23, y), f(p30, p31, p32, p33, y), x)&#xD;&#xA;&#xD;&#xA;where (x, y) is the interpolated position and p[][] is the 2d array representing the 4 * 4 grid.&#xD;&#xA;&#xD;&#xA;Check [this link][4] for more information and example code, which really helps a lot!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Image_scaling#Scaling_methods&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bicubic_interpolation&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline&#xD;&#xA;  [4]: http://www.paulinternet.nl/?page=bicubic" ContentLicense="CC BY-SA 3.0" />
  <row Id="5661" PostHistoryTypeId="5" PostId="2385" RevisionGUID="c7faaf78-0b45-44a5-b60f-ed03a4ad6b8f" CreationDate="2016-05-03T09:17:02.863" UserId="38" Comment="deleted 1 character in body" Text="Orthographic projections are parallel projections. Each line that is originally parallel will be parallel after this transformation. The orthographic projection can be represented by a affine transformation.&#xD;&#xA;&#xD;&#xA;In contrast a perspective projection is not a parallel projection and originally parallel lines will no longer be parallel after this operation. Thus perspective projection can not be done by a affine transform.&#xD;&#xA;&#xD;&#xA;Why would you need orthographic projections? It is useful for several artistic and technical reasons. Orthographic projections are used in CAD drawings and other technical documentations. One of the primary reasons is to verify that your part actually fits in the space that has been reserved for it on a floor plan for example. Orthographic projections are often chosen so that the dimensions are easy to measure. In many cases this is just a convenient way to represent a problem in a different basis so that coordinates are easier to figure out.&#xD;&#xA;&#xD;&#xA;[![ortho][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A number of useful orthographic projections for same object (and projection rule). The last on on the right is a special case called isometric having the property that cardinal axe directions are all in same scale.&#xD;&#xA;&#xD;&#xA;A perspective projection is needed to be able to do 2 and 3 point perspectives, which is how we experience the world. A specific perspective projection can be decomposed as being a combination of a orthographic projection and a perspective divide.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 point perspective note how the lines in prespective direction no longer are parallel&#xD;&#xA;&#xD;&#xA;Viewport transformation allows you to pan/rotate/scale the resulting projection. Maybe because you want a off center projection like in cameras with film offset, or you have a anisotropic medium for example. It can alse be convenient for the end user as he can zoom areas without changing the perpective.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5zqm3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/urTYN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5662" PostHistoryTypeId="2" PostId="2389" RevisionGUID="13d8ea91-8753-403c-b719-4dc889ed4920" CreationDate="2016-05-03T13:17:41.510" UserId="2838" Text="This has to do with gamma correction.&#xD;&#xA;&#xD;&#xA;If one pixel has red component with value of 1 (where 255 is max), the next pixel has value for red that is 2, there no guarantee that exactly twice as much photons are exiting from the second pixel. Displays have different curves that predict what's the expected brightness. It also has to do with how our eyes work: they're more sensitive for darker shades than brighter shades.&#xD;&#xA;&#xD;&#xA;To read more about these phenomena:&#xD;&#xA;&#xD;&#xA; - https://gamedevdaily.io/the-srgb-learning-curve-773b7f68cf7a#.di88vr58t&#xD;&#xA; - http://marcinignac.com/blog/pragmatic-pbr-setup-and-gamma/ (gamma section)&#xD;&#xA; - http://colour-science.org/posts/the-importance-of-terminology-and-srgb-uncertainty/&#xD;&#xA; - http://www.essentialmath.com/GDC2015/VanVerth_Jim_DoingMathwRGB.pdf&#xD;&#xA;&#xD;&#xA;The three images are used as low value, medium grey and bright examples. Indeed, the lowest brightness is used so you are able do see the difference between the black background and &quot;barely lit&quot; object, and the other two images are just used to display other important values for the set gamma curve." ContentLicense="CC BY-SA 3.0" />
  <row Id="5664" PostHistoryTypeId="5" PostId="2385" RevisionGUID="2d91b283-6ff3-4308-8ebb-c3096524e2c2" CreationDate="2016-05-03T15:32:59.583" UserId="38" Comment="added 14 characters in body" Text="Orthographic projections are parallel projections. Each line that is originally parallel will be parallel after this transformation. The orthographic projection can be represented by a affine transformation.&#xD;&#xA;&#xD;&#xA;In contrast a perspective projection is not a parallel projection and originally parallel lines will no longer be parallel after this operation. Thus perspective projection can not be done by a affine transform.&#xD;&#xA;&#xD;&#xA;Why would you need orthographic projections? It is useful for several artistic and technical reasons. Orthographic projections are used in CAD drawings and other technical documentations. One of the primary reasons is to verify that your part actually fits in the space that has been reserved for it on a floor plan for example. Orthographic projections are often chosen so that the dimensions are easy to measure. In many cases this is just a convenient way to represent a problem in a different basis so that coordinates are easier to figure out.&#xD;&#xA;&#xD;&#xA;[![ortho][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A number of useful orthographic projections for same object (and projection rule). The last on on the right is a special case called isometric having the property that cardinal axe directions are all in same scale.&#xD;&#xA;&#xD;&#xA;A perspective projection is needed to be able to do 2 and 3 point perspectives, which is how we experience the world. A specific perspective projection can be decomposed as being a combination of a orthographic projection and a perspective divide.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 point perspective note how the lines in prespective direction no longer are parallel&#xD;&#xA;&#xD;&#xA;Viewport transformation allows you to pan/rotate/scale the resulting projection. Maybe because you want a off center projection like in cameras with film offset, or you have a anisotropic medium for example. It can also be convenient for the end user to zoom into image without changing the perspective in the process.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5zqm3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/urTYN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5665" PostHistoryTypeId="5" PostId="1869" RevisionGUID="f70f4d68-7eb5-4696-8a5a-609c7371c00c" CreationDate="2016-05-03T16:13:54.833" UserId="174" Comment="Improve interpolation function formatting" Text="There are numerous upscaling and downscaling algorithms available to scale images from any resolution to any other arbitrary resolution. Each algorithm typically involves a trade-off between efficiency, smoothness and sharpness, with varying degrees of each trade-off for different algorithms.&#xD;&#xA;&#xD;&#xA;Check out [this Wikipedia article][1] for such algorithms and examples of such algorithms.&#xD;&#xA;&#xD;&#xA;The most popularly known (and used) algorithm is the [Bicubic interpolation][2] algorithm. It interpolates between 2D points on a rectangular grid. Using [Cubic Splines][3] (or Cubic Interpolation), It first interpolates on one dimension (finds the interpolated row/column), then interpolates the interpolated row/column in the other dimension.&#xD;&#xA;&#xD;&#xA;Bilinear interpolation is similar to Bicubic interpolation, except the former interpolates using a linear function and can interpolate only between two values and the latter uses a cubic function and can interpolate between four values.&#xD;&#xA;&#xD;&#xA;The simple function for Bicubic interpolation is as follows:&#xD;&#xA;&#xD;&#xA;    f(f(p00, p01, p02, p03, y),&#xD;&#xA;      f(p10, p11, p12, p13, y),&#xD;&#xA;      f(p20, p21, p22, p23, y),&#xD;&#xA;      f(p30, p31, p32, p33, y),&#xD;&#xA;      x)&#xD;&#xA;&#xD;&#xA;where (x, y) is the interpolated position and p[][] is the 2d array representing the 4 * 4 grid.&#xD;&#xA;&#xD;&#xA;Check [this link][4] for more information and example code, which really helps a lot!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Image_scaling#Scaling_methods&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bicubic_interpolation&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline&#xD;&#xA;  [4]: http://www.paulinternet.nl/?page=bicubic" ContentLicense="CC BY-SA 3.0" />
  <row Id="5666" PostHistoryTypeId="24" PostId="1869" RevisionGUID="f70f4d68-7eb5-4696-8a5a-609c7371c00c" CreationDate="2016-05-03T16:13:54.833" Comment="Proposed by 174 approved by 1683 edit id of 135" ContentLicense="CC BY-SA 3.0" />
  <row Id="5672" PostHistoryTypeId="5" PostId="2366" RevisionGUID="6b8e3f6b-78f2-48fd-a5c8-fd1e50f15f35" CreationDate="2016-05-04T10:29:14.240" UserId="3248" Comment="added 84 characters in body" Text="[![enter image description here][1]][1]I'm currently trying to develop a game using Cocos2d-x using C++&#xD;&#xA;I really need to generate this burst or (donut-shaped) pulse.&#xD;&#xA;I'm having a difficult time how to generate such shape.&#xD;&#xA;At first, I was thinking of scaling the image but that didnt work out because the line or &quot;diameter&quot; of the donut shape gets bigger accordingly..&#xD;&#xA;Any experienced coders who can provide an equation of this thing? or maybe &quot;mathematics&quot; is more exact.&#xD;&#xA;If you guys can provide ANY help, suggestion, or alternative recommendation, I'll be so glad^^&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=ewnEE5mt1ZM&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t5yOY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5674" PostHistoryTypeId="5" PostId="2359" RevisionGUID="1fd9d29d-4b74-4530-b412-02f66469d7a3" CreationDate="2016-05-04T14:12:42.043" UserId="3225" Comment="added 9 characters in body" Text="I have an application in which I am using an octree to store a volume mesh of axis-aligned bounding boxes (AABBs).&#xD;&#xA;&#xD;&#xA;Given a water-tight manifold triangle mesh, I need to:&#xD;&#xA;&#xD;&#xA;- find if an AABB is intersected by or completely inside/outside of the surface mesh,&#xD;&#xA;&#xD;&#xA;- clip the surface mesh with the intersected AABBs to generate triangles that completely lie within each AABB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The triangulation and the octree containing the AABBs are both dynamic. The number of leaf nodes in the octree is huge. The number of triangles in the surface mesh is much smaller (O(10^9 - 10^13) octree nodes, vs O(10^6) triangles).&#xD;&#xA;&#xD;&#xA;Which data-structures and algorithm are suitable for my problem?&#xD;&#xA;&#xD;&#xA;Right now I:&#xD;&#xA;&#xD;&#xA; - store the triangles in the same octree as the volume mesh,&#xD;&#xA; - store each triangle in the smallest octree node that contains it,&#xD;&#xA; - clip the triangle mesh with a single AABB by traversing from that AABB to both the root node and its leafs clipping each triangle contained in the nodes with the AABB. &#xD;&#xA;&#xD;&#xA;The triangles in the nodes until the leafs are fully contained within the AABB and don't need any &quot;clipping&quot; (the AABB just contains those triangles), while the ones contained in the nodes from the AABB to the root need clipping. However:&#xD;&#xA;&#xD;&#xA; -  due to the way I am storing the triangles (in the smallest octree node that fully contains them) I don't have an upper bound in the maximum number of triangles that can be stored within each single octree node, so I don't have an upper bound in the number of triangles that have to be tested against a single AABB.&#xD;&#xA;&#xD;&#xA; - if I just want to test if an AABB is intersected by the triangle mesh, I have to test all triangles between that AABB and the root node which might be expensive. Ideally I would like to have a very fast way to test, and then clip the mesh if the test is true.&#xD;&#xA;&#xD;&#xA; - currently I have no fast way of determining if a node is inside/outside/intersected by the mesh. I could construct a signed distance field (which is expensive), or perform some ray casting (which is also expensive), maybe there is a better solution or maybe I just need to precompute something to speed this up every time I move the triangle mesh.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - moving the triangle mesh requires manipulating the octree (I don't know if this can be avoided). Ideally I would like to generate an octree for the triangle mesh once, and then just move the mesh using a single transformation matrix. However, then I would need to have some sort of mapping between &quot;the octree containing the triangle mesh&quot; and &quot;the octree of my volume mesh&quot;. Maybe this mapping is trivial but I haven't figured it out yet. This would save me from manipulating the octree when I move the mesh and maybe the coordinate transformations that would be required are negligible with the cost of clipping." ContentLicense="CC BY-SA 3.0" />
  <row Id="5675" PostHistoryTypeId="2" PostId="2391" RevisionGUID="7d6a4788-1f8d-4e33-a010-6ccf3da0b3ef" CreationDate="2016-05-04T21:54:04.517" UserId="2479" Text="What is the best currently known and ideally also production-verified approach for sampling environment maps (EM) in a uni-directional path tracer and similar types of renderers? I would prefer solutions which are reasonably complicated while reasonably functional to those which provide perfect sampling at cost of super complicated and hard-to-understand implementation.&#xD;&#xA;&#xD;&#xA;What I know so far&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;There are some easy ways of sampling EMs. One can sample the needed hemisphere in a cosine-weighted manner,&#xD;&#xA;   which ignores both the BSDF and the EM function shapes. As a result,&#xD;&#xA;   it doesn't work for dynamic EMs:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To improve&#xD;&#xA;   the sampling to a usable level is to sample the luminance of the EM&#xD;&#xA;   over the whole sphere. It is relatively easily implemented and the&#xD;&#xA;   results are quite good. However, the sampling strategy is still&#xD;&#xA;   ignoring the hemispherical visibility information and the cosine&#xD;&#xA;   factor (and also the BSDF), resulting in high noise on the surfaces&#xD;&#xA;   which are not directly lit by high-intensity areas of the EM:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Papers&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;I have found a few papers on the topic, but have not read them yet. Is any of these worth reading and implementing in a forward uni-directional path tracer, or is there something even better?&#xD;&#xA;&#xD;&#xA; - [Steerable Importance Sampling][3] (2007) by&#xD;&#xA;   Kartic Subr and Jim Arvo. They claim to present “...an algorithm for&#xD;&#xA;   efficient stratified importance sampling of environment maps that&#xD;&#xA;   generates samples in the positive hemi-sphere defined by local&#xD;&#xA;   orientation of arbitrary surfaces while accounting for cosine&#xD;&#xA;   weighting. “ The paper “Importance Sampling Spherical Harmonics”&#xD;&#xA;   comments on it: ”They create a triangulated representation of the&#xD;&#xA;   environment map and store the illumination premultiplied by each of&#xD;&#xA;   the first nine spherical harmonic basis functions at every vertex.&#xD;&#xA;   This forms a steerable basis where the clamped-cosine can be&#xD;&#xA;   efficiently rotated to any orientation.”&#xD;&#xA;&#xD;&#xA; - [Practical Product Importance Sampling for Direct Illumination][4] (2008) by&#xD;&#xA;   Petrik Clarberg and Tomas Akenine-Möller. An algorithm for sampling&#xD;&#xA;   the product of environment map lighting and surface reflectance. Uses&#xD;&#xA;   wavelet-based importance sampling.&#xD;&#xA;   &#xD;&#xA; - [Importance Sampling Spherical Harmonics][5] (2009)&#xD;&#xA;   by Jarosz, Carr, and Jensenn. The abstract says: “...we present the&#xD;&#xA;   first practical method for importance sampling functions represented&#xD;&#xA;   as spherical harmonics (SH)...”&#xD;&#xA;   &#xD;&#xA; - [Tone-Mapped Mean-shift Based Environment Map Sampling][6] (2015) by Feng&#xD;&#xA;   et al. This is pretty new and I have found neither a reference to it&#xD;&#xA;   nor the paper itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TBYYn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1DOSr.png&#xD;&#xA;  [3]: http://home.eps.hw.ac.uk/~ks400/research.html#SteerableImportance&#xD;&#xA;  [4]: http://fileadmin.cs.lth.se/graphics/research/papers/2008/pps/&#xD;&#xA;  [5]: https://www.cs.dartmouth.edu/~wjarosz/publications/jarosz09importance.html&#xD;&#xA;  [6]: http://www.ncbi.nlm.nih.gov/pubmed/26584494" ContentLicense="CC BY-SA 3.0" />
  <row Id="5676" PostHistoryTypeId="1" PostId="2391" RevisionGUID="7d6a4788-1f8d-4e33-a010-6ccf3da0b3ef" CreationDate="2016-05-04T21:54:04.517" UserId="2479" Text="Importance sampling environment maps" ContentLicense="CC BY-SA 3.0" />
  <row Id="5677" PostHistoryTypeId="3" PostId="2391" RevisionGUID="7d6a4788-1f8d-4e33-a010-6ccf3da0b3ef" CreationDate="2016-05-04T21:54:04.517" UserId="2479" Text="|rendering|sampling|pathtracing|importance-sampling|ibl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5678" PostHistoryTypeId="2" PostId="2392" RevisionGUID="4923a26a-d516-48e7-8309-29394cc8174f" CreationDate="2016-05-04T22:38:30.980" UserId="3041" Text="Ship your application with a benchmarking sequence testing the actual platform. (Possible answer for many questions I guess...)&#xD;&#xA;&#xD;&#xA;I suspect the performance is highly dependent on **how** you use the hardware. Since the hardware is unlikely to somehow instrument your application backwards, telling you what to do, I´d go with whatever looks good in your design.&#xD;&#xA;&#xD;&#xA;&gt; &quot;...command queues can be executed concurrently by the device...&quot;&#xD;&#xA;&#xD;&#xA;Keyword is CAN. I see no reason why any vendor would screw this up. In the end it is the platform provider (Intel/AMD/Nvidia) who is responsible of making you a good enough driver for you not to consider switching vendor. If they do have a &quot;know issue&quot; with this functionality (which by the way has no functional meaning, only performance) then they **should** also solve it using what they know. I mean for crying out loud, the fallback is something they have already implemented; synchrounous execution. &#xD;&#xA;&#xD;&#xA;Hardware is enough voodoo as it is for us developers." ContentLicense="CC BY-SA 3.0" />
  <row Id="5679" PostHistoryTypeId="2" PostId="2393" RevisionGUID="0df50739-6e36-46e8-bc75-8a82d29d78fd" CreationDate="2016-05-05T06:44:00.977" UserId="88" Text="Tessellation has been touted as one of the major features in newer graphics APIs like DirecX 11, and it is shown as a standalone stage in a modern graphics pipeline.&#xD;&#xA;&#xD;&#xA;Compared to the amount of hardware and software attention given to this feature, it doesn't seem to be heavily used in real-time graphics. So this doesn't seem to be a feature that arose out of graphical demand.&#xD;&#xA;&#xD;&#xA;Then why did tessellation become such a prominent feature? To cater to the demands of non-realtime rendering? As a side-effect of the increasing shift in GPU architecture as generalized parallel processors in heterogeneous computing? Or is this a forward-thinking feature that will be used in graphics as tessellation-capable GPUs become increasingly common?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5680" PostHistoryTypeId="1" PostId="2393" RevisionGUID="0df50739-6e36-46e8-bc75-8a82d29d78fd" CreationDate="2016-05-05T06:44:00.977" UserId="88" Text="Why did tessellation come to be a prominent feature?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5681" PostHistoryTypeId="3" PostId="2393" RevisionGUID="0df50739-6e36-46e8-bc75-8a82d29d78fd" CreationDate="2016-05-05T06:44:00.977" UserId="88" Text="|gpu|directx11|tesselation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5682" PostHistoryTypeId="2" PostId="2394" RevisionGUID="afb02fe5-8937-49c0-a64d-dfed3b547f9e" CreationDate="2016-05-05T06:44:32.243" UserId="48" Text="Rather than making one spatial subdivision structure do double duty in representing both the voxels and the triangles, I would suggest creating a separate BVH for the mesh. You can find many articles and papers about BVH-building algorithms on the web. It's likely to be a more efficiently queryable representation of the mesh than the octree would be.&#xD;&#xA;&#xD;&#xA;Given the BVH, it's easy to determine whether a given voxel might intersect the mesh by starting at the BVH root and traversing to child nodes that intersect the voxel box. Depending on the quality of the BVH, i.e. how tightly it fits the mesh, many voxels (or even higher-level octree nodes) may be able to be eliminated with only a few checks. For voxels that do intersect the mesh surface, the BVH traversal will reach down to the leaves, where you can accumulate the triangles into a list for clipping.&#xD;&#xA;&#xD;&#xA;If the BVH is built in the mesh's local space, the mesh can easily be moved or transformed without needing to update the octree. (If translation is the only transform needed, then the BVH nodes will always be axis-aligned relative to the voxels, which simplifies the intersection test to an AABB overlap test; if more general transforms are needed, you'd have to use a more general OBB vs OBB test.)&#xD;&#xA;&#xD;&#xA;However, note that a BVH doesn't lend itself that well to determining whether a things are inside versus outside a watertight mesh. If that's important to you (it wasn't clear to me whether it is), then you might want to look into using a BSP tree instead of a BVH. A BSP tree can be used for intersection testing similarly to a BVH, but additionally can represent the exact boundary of the mesh so that it can be used to determine whether a point (or voxel) is inside or outside. This property of BSP trees is widely used for collision detection.&#xD;&#xA;&#xD;&#xA;An alternate approach to determining inside/outsideness is to use raycasting and count the number of intersections with the mesh (even = outside, odd = inside). The raycasting can be accelerated by the BVH as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="5683" PostHistoryTypeId="34" PostId="2356" RevisionGUID="12065918-3a2c-495e-98db-506c8cf231c9" CreationDate="2016-05-05T10:41:11.427" UserId="-1" Comment="14" />
  <row Id="5684" PostHistoryTypeId="2" PostId="2395" RevisionGUID="1dd61bfb-c1d2-4a8e-ba85-21501aa0b7d7" CreationDate="2016-05-05T14:49:18.677" UserId="310" Text="The main purpose of tesselation is to increase the resolution of the mesh, while only transferring a small amount of triangle data around. In addition, tessellation allows you to dynamically change the LOD of the mesh, so you can [optimize your shader calls.][1]&#xD;&#xA;&#xD;&#xA;So, we can pass the GPU, say, 3000 triangles, and have it tesselate it to 300000 triangles. We are essentially trading storage space/bandwidth for compute power. Since GPUs have lots and lots of compute, and memory is limited/slow, this is a pretty good tradeoff.&#xD;&#xA;&#xD;&#xA;As for &quot;not being heavily used in real-time graphics&quot;. I somewhat disagree. Many AAA games have been using tessellation for a long time. That said, tessellation is *hard* to get right. Done wrong, tesselation can lead to lots of problems, such as [cracking][2], or over tessellating to sub-pixel triangles, which [destroys your fill rate][1].&#xD;&#xA;&#xD;&#xA;Combined, these problems make it difficult to implement good and fast tessellation for your everyday person. Thus, most of the uses of tessellation you see nowadays are in AA or AAA games, game engines, and offline rendering tools.&#xD;&#xA;&#xD;&#xA;That said, there is active research going on that is trying to better utilize the tessellation hardware, and make it easier to use. For example: [Efficient GPU Rendering of Subdivision Surfaces using Adaptive Quadtrees][3]&#xD;&#xA;&#xD;&#xA;In the end, tessellation is a great feature, but is difficult to get right&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.g-truc.net/post-0662.html&#xD;&#xA;  [2]: https://developer.nvidia.com/content/dynamic-hardware-tessellation-basics&#xD;&#xA;  [3]: http://www.graphics.stanford.edu/~niessner/brainerd2016efficient.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5685" PostHistoryTypeId="5" PostId="1870" RevisionGUID="a28c3603-bb9a-45fb-99cd-6ac762e57a4a" CreationDate="2016-05-05T14:56:32.470" UserId="310" Comment="Some minor grammar fixes" Text="In essence a image is  a group of point samples (read [A pixel is not a little square&lt;sup&gt;3&lt;/sup&gt;](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf)). When you transform or scale the image you need to resample it. So what you do, theoretically, is take the point samples and convert them into a continuous function. Then you sample that continuous function and reconstruct a signal. So, there are two or three different phases here.&#xD;&#xA;&#xD;&#xA;1. Converting the samples to a continuous function, (function reconstruction).&#xD;&#xA;2. (Transforming)&#xD;&#xA;3. Re-sampling the signal&#xD;&#xA;&#xD;&#xA;Note that none of these steps have a fixed form. In practice, when optimized, it's impossible to tell that there are steps. The transformation does not really have to be simple it could be mapping the shape into a spiral etc. &#xD;&#xA;&#xD;&#xA;[![Reconstruction of signal][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A 1-D signal reconstructed by different filters.&#xD;&#xA;&#xD;&#xA;In practice, quite a bit of lore is known about signal reconstruction in the signal processing field. Designing these filters and choosing the right one is a art form on its own. But, in essence, the choice of filter is a tradeoff between blurring and [ringing][2]. Of course the algorithm also has other qualities such as how many instructions it takes to implement and how fast and how much memory it needs etc. Which can be very important in realtime or embedded applications.&#xD;&#xA;&#xD;&#xA;[![The process][3]][3]&#xD;&#xA;&#xD;&#xA;**Image 2**: Overview of entire process.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WWaeC.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Ringing_artifacts&#xD;&#xA;  [3]: https://i.stack.imgur.com/XNqUx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5686" PostHistoryTypeId="5" PostId="2391" RevisionGUID="c7683e5e-60db-416d-8e35-5e4ac2631bb9" CreationDate="2016-05-05T16:25:28.187" UserId="2479" Comment="minor wording changes" Text="What is the best currently known and ideally also production-verified approach for sampling environment maps (EM) in a uni-directional path tracer and similar types of renderers? I would prefer solutions which are reasonably complicated while reasonably functional to those which provide perfect sampling at cost of super complicated and hard-to-understand implementation.&#xD;&#xA;&#xD;&#xA;What I know so far&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;There are some easy ways of sampling EMs. One can sample the needed hemisphere in a cosine-weighted manner,&#xD;&#xA;   which ignores both the BSDF and the EM function shapes. As a result,&#xD;&#xA;   it doesn't work for dynamic EMs:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To improve&#xD;&#xA;   the sampling to a usable level, one can sample the luminance of the EM&#xD;&#xA;   over the whole sphere. It is relatively easily implemented and the&#xD;&#xA;   results are quite good. However, the sampling strategy is still&#xD;&#xA;   ignoring the hemispherical visibility information and the cosine&#xD;&#xA;   factor (and also the BSDF), resulting in high noise on the surfaces&#xD;&#xA;   which are not directly lit by high-intensity areas of the EM:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Papers&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;I have found a few papers on the topic, but have not read them yet. Is any of these worth reading and implementing in a forward uni-directional path tracer, or is there something even better?&#xD;&#xA;&#xD;&#xA; - [Steerable Importance Sampling][3] (2007) by&#xD;&#xA;   Kartic Subr and Jim Arvo. They claim to present “...an algorithm for&#xD;&#xA;   efficient stratified importance sampling of environment maps that&#xD;&#xA;   generates samples in the positive hemi-sphere defined by local&#xD;&#xA;   orientation of arbitrary surfaces while accounting for cosine&#xD;&#xA;   weighting. “ The paper “Importance Sampling Spherical Harmonics”&#xD;&#xA;   comments on it: ”They create a triangulated representation of the&#xD;&#xA;   environment map and store the illumination premultiplied by each of&#xD;&#xA;   the first nine spherical harmonic basis functions at every vertex.&#xD;&#xA;   This forms a steerable basis where the clamped-cosine can be&#xD;&#xA;   efficiently rotated to any orientation.”&#xD;&#xA;&#xD;&#xA; - [Practical Product Importance Sampling for Direct Illumination][4] (2008) by&#xD;&#xA;   Petrik Clarberg and Tomas Akenine-Möller. An algorithm for sampling&#xD;&#xA;   the product of environment map lighting and surface reflectance. Uses&#xD;&#xA;   wavelet-based importance sampling.&#xD;&#xA;   &#xD;&#xA; - [Importance Sampling Spherical Harmonics][5] (2009)&#xD;&#xA;   by Jarosz, Carr, and Jensenn. The abstract says: “...we present the&#xD;&#xA;   first practical method for importance sampling functions represented&#xD;&#xA;   as spherical harmonics (SH)...”&#xD;&#xA;   &#xD;&#xA; - [Tone-Mapped Mean-shift Based Environment Map Sampling][6] (2015) by Feng&#xD;&#xA;   et al. This is pretty new and I have found neither a reference to it&#xD;&#xA;   nor the paper itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TBYYn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1DOSr.png&#xD;&#xA;  [3]: http://home.eps.hw.ac.uk/~ks400/research.html#SteerableImportance&#xD;&#xA;  [4]: http://fileadmin.cs.lth.se/graphics/research/papers/2008/pps/&#xD;&#xA;  [5]: https://www.cs.dartmouth.edu/~wjarosz/publications/jarosz09importance.html&#xD;&#xA;  [6]: http://www.ncbi.nlm.nih.gov/pubmed/26584494" ContentLicense="CC BY-SA 3.0" />
  <row Id="5687" PostHistoryTypeId="4" PostId="2391" RevisionGUID="c7683e5e-60db-416d-8e35-5e4ac2631bb9" CreationDate="2016-05-05T16:25:28.187" UserId="2479" Comment="minor wording changes" Text="Importance Sampling of Environment Maps" ContentLicense="CC BY-SA 3.0" />
  <row Id="5692" PostHistoryTypeId="2" PostId="2397" RevisionGUID="b9704f9e-9b3f-4cf2-8d78-21d8ada47876" CreationDate="2016-05-06T01:23:24.967" UserId="3003" Text="While the other answers given are correct I'm not sure they entirely answer your question. In order to not get black bars you have 2 options if the destination is not the same shape (or aspect ratio) as the source:&#xD;&#xA;&#xD;&#xA; 1. **Fill the destination leaving some pixels from the source out of the destination.** In your example, the source is 1024x768 and the destination is 1920x1080. If you scale the original image up so the result is 1920x1440, you can then crop the top and/or bottom off to make it 1920x1080.&#xD;&#xA; 2. **Stretch the destination image to fit.** So you'd scale vertically by 1080/768 = 1.40625, and scale horizontally by 1920/1024 = 1.875. This is almost never what you want, and looks terrible in most cases. (This is what makes people look much wider than they should, and turns circles into ovals and rotations into shears.)&#xD;&#xA;&#xD;&#xA;There's another option, but it doesn't fit your criteria - scale uniformly, but only until 1 dimension is as big as the destination. In this case you would scale both horizontally and vertically by 1.40625 to get a result of 1440x1080. This is usually referred to as &quot;scale to fit&quot;.&#xD;&#xA;&#xD;&#xA;For any of these options you can use whichever scaling algorithm meets your needs." ContentLicense="CC BY-SA 3.0" />
  <row Id="5693" PostHistoryTypeId="5" PostId="2391" RevisionGUID="66fbd6fa-7bfd-4eae-a288-4b5c8f9e5de6" CreationDate="2016-05-06T08:20:38.070" UserId="2479" Comment="Added link to paper &quot;Structured Importance Sampling of Environment Maps&quot;" Text="What is the best currently known and ideally also production-verified approach for sampling environment maps (EM) in a uni-directional path tracer and similar types of renderers? I would prefer solutions which are reasonably complicated while reasonably functional to those which provide perfect sampling at cost of super complicated and hard-to-understand implementation.&#xD;&#xA;&#xD;&#xA;What I know so far&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;There are some easy ways of sampling EMs. One can sample the needed hemisphere in a cosine-weighted manner,&#xD;&#xA;   which ignores both the BSDF and the EM function shapes. As a result,&#xD;&#xA;   it doesn't work for dynamic EMs:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To improve&#xD;&#xA;   the sampling to a usable level, one can sample the luminance of the EM&#xD;&#xA;   over the whole sphere. It is relatively easily implemented and the&#xD;&#xA;   results are quite good. However, the sampling strategy is still&#xD;&#xA;   ignoring the hemispherical visibility information and the cosine&#xD;&#xA;   factor (and also the BSDF), resulting in high noise on the surfaces&#xD;&#xA;   which are not directly lit by high-intensity areas of the EM:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Papers&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;I have found a few papers on the topic, but have not read them yet. Is any of these worth reading and implementing in a forward uni-directional path tracer, or is there something even better?&#xD;&#xA;&#xD;&#xA; - [Structured Importance Sampling of Environment Maps][3] (2003) by&#xD;&#xA;   Agarwal et al.&#xD;&#xA;&#xD;&#xA; - [Steerable Importance Sampling][4] (2007) by&#xD;&#xA;   Kartic Subr and Jim Arvo. They claim to present “...an algorithm for&#xD;&#xA;   efficient stratified importance sampling of environment maps that&#xD;&#xA;   generates samples in the positive hemi-sphere defined by local&#xD;&#xA;   orientation of arbitrary surfaces while accounting for cosine&#xD;&#xA;   weighting. “ The paper “Importance Sampling Spherical Harmonics”&#xD;&#xA;   comments on it: ”They create a triangulated representation of the&#xD;&#xA;   environment map and store the illumination premultiplied by each of&#xD;&#xA;   the first nine spherical harmonic basis functions at every vertex.&#xD;&#xA;   This forms a steerable basis where the clamped-cosine can be&#xD;&#xA;   efficiently rotated to any orientation.”&#xD;&#xA;&#xD;&#xA; - [Practical Product Importance Sampling for Direct Illumination][5] (2008) by&#xD;&#xA;   Petrik Clarberg and Tomas Akenine-Möller. An algorithm for sampling&#xD;&#xA;   the product of environment map lighting and surface reflectance. Uses&#xD;&#xA;   wavelet-based importance sampling.&#xD;&#xA;   &#xD;&#xA; - [Importance Sampling Spherical Harmonics][6] (2009)&#xD;&#xA;   by Jarosz, Carr, and Jensenn. The abstract says: “...we present the&#xD;&#xA;   first practical method for importance sampling functions represented&#xD;&#xA;   as spherical harmonics (SH)...”&#xD;&#xA;   &#xD;&#xA; - [Tone-Mapped Mean-shift Based Environment Map Sampling][7] (2015) by Feng&#xD;&#xA;   et al. This is pretty new and I have found neither a reference to it&#xD;&#xA;   nor the paper itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TBYYn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1DOSr.png&#xD;&#xA;  [3]: https://cseweb.ucsd.edu/~ravir/papers/structured/&#xD;&#xA;  [4]: http://home.eps.hw.ac.uk/~ks400/research.html#SteerableImportance&#xD;&#xA;  [5]: http://fileadmin.cs.lth.se/graphics/research/papers/2008/pps/&#xD;&#xA;  [6]: https://www.cs.dartmouth.edu/~wjarosz/publications/jarosz09importance.html&#xD;&#xA;  [7]: http://www.ncbi.nlm.nih.gov/pubmed/26584494" ContentLicense="CC BY-SA 3.0" />
  <row Id="5694" PostHistoryTypeId="2" PostId="2398" RevisionGUID="60dd0265-213e-4283-acd4-c4551c581829" CreationDate="2016-05-06T10:21:44.147" UserId="2383" Text="I implemented the algorithm shown in given link to fit given image to specified quadrilateral but the output is blank. Here is the link to the algorithm&#xD;&#xA;http://math.ewha.ac.kr/~jylee/SciComp/dip-crane/chapter8/list8_4.c&#xD;&#xA;&#xD;&#xA;I implemented it in C# as follows&#xD;&#xA;&#xD;&#xA;        Bitmap inputImage = new Bitmap(&quot;D:\\Image\\A2.jpg&quot;);&#xD;&#xA;            Bitmap outputBitmap = new Bitmap(inputImage.Width, inputImage.Height);&#xD;&#xA;            double a11, a21, a31, a41;&#xD;&#xA;            double a12, a22, a32, a42;&#xD;&#xA;            double first, second;&#xD;&#xA;            double denom;&#xD;&#xA;            int u, v;&#xD;&#xA;            double floatu, floatv;&#xD;&#xA;            int i, j;&#xD;&#xA;            ulong sourcebase; /// this has been replaced by u,v i think its same&#xD;&#xA;            double x, y;&#xD;&#xA;            double A, B, C;&#xD;&#xA;            int x0 = 50, y0 = 100, x1 = 65, y1 = 110, x2 = 55, y2 = 120, x3 = 450, y3 = 110;// fix value quadrilaeral for checking purpose.&#xD;&#xA;            a11 = x0 - x1 - x3 + x2;&#xD;&#xA;            a21 = x1 - x0;&#xD;&#xA;            a31 = x3 - x0;&#xD;&#xA;            a41 = x0;&#xD;&#xA;            a12 = y0 - y1 - y3 + y2;&#xD;&#xA;            a22 = y1 - y0;&#xD;&#xA;            a32 = y3 - y0;&#xD;&#xA;            a42 = y0;&#xD;&#xA;            Console.WriteLine(&quot;inside of here&quot;);&#xD;&#xA;            A = a11 * a22 - a21 * a12;&#xD;&#xA;            if (A == 0)&#xD;&#xA;                A = 0.00001;&#xD;&#xA;            int rows = inputImage.Height, cols = inputImage.Width;&#xD;&#xA;            for (i = 0; i &lt; rows; i++)&#xD;&#xA;            {&#xD;&#xA;                y = Convert.ToDouble(i) / Convert.ToDouble(rows);&#xD;&#xA;                for (j = 0; j &lt; cols; j++)&#xD;&#xA;                {&#xD;&#xA;                    x = Convert.ToDouble(j) / Convert.ToDouble(cols);&#xD;&#xA;                    B = a12 * x - a11 * y + a11 * a42 - a41 * a12 + a31 * a22 - a21 * a32;&#xD;&#xA;                    C = a32 * x - a31 * y + a31 * a42 - a41 * a32;&#xD;&#xA;                    first = B * B;&#xD;&#xA;                    second = 4.0 * A * C;&#xD;&#xA;                    if (first &lt; second)&#xD;&#xA;                        floatu = B / (-2.0 * A);&#xD;&#xA;                    else&#xD;&#xA;                        floatu = (-1.0 * B + Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;                    if((floatu &lt; 0.0) | (floatu &gt; 1.0))&#xD;&#xA;                    {&#xD;&#xA;                        if (first &lt; second)&#xD;&#xA;                            floatu = B / -2.0 * A;&#xD;&#xA;                        else&#xD;&#xA;                            floatu = (1.0 * B - Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;                    }&#xD;&#xA;                    denom = (a11 * floatu + a31);&#xD;&#xA;                    if (denom == 0.0)&#xD;&#xA;                        denom = 0.000001;&#xD;&#xA;                    floatv = (x - a21 * floatu - a41) / denom;&#xD;&#xA;                    u = Convert.ToInt32(floatu * cols + 0.5);&#xD;&#xA;                    v = Convert.ToInt32(floatv * rows + 0.5);&#xD;&#xA;                    Color pixelColor;&#xD;&#xA;                    if ((u &gt;= cols) | (u &lt; 0) | (v &gt;= rows) | (v &lt; 0))&#xD;&#xA;                    {&#xD;&#xA;                        // Console.WriteLine(&quot;escapaed&quot;);&#xD;&#xA;                        pixelColor = Color.Black;&#xD;&#xA;                        continue;&#xD;&#xA;                    }&#xD;&#xA;                    else { /// program ne&#xD;&#xA;                        Console.WriteLine(&quot;here&quot;);&#xD;&#xA;                        //sourcebase = ((ulong)u * (ulong)cols + (ulong)v);&#xD;&#xA;                        pixelColor = inputImage.GetPixel((int)u, (int)v);&#xD;&#xA;                        outputBitmap.SetPixel(i, j, pixelColor);// =pixelColor;&#xD;&#xA;                                                                // pictureBox1.Image = outputBitmap;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;              //  Console.WriteLine(i);&#xD;&#xA;            }&#xD;&#xA;            pictureBox1.Image = outputBitmap;&#xD;&#xA;            outputBitmap.Save(&quot;output.jpg&quot;);&#xD;&#xA;            Console.WriteLine(&quot;Out Of here&quot;);&#xD;&#xA;            pictureBox1.Invalidate();&#xD;&#xA;&#xD;&#xA;//" ContentLicense="CC BY-SA 3.0" />
  <row Id="5695" PostHistoryTypeId="1" PostId="2398" RevisionGUID="60dd0265-213e-4283-acd4-c4551c581829" CreationDate="2016-05-06T10:21:44.147" UserId="2383" Text="Bilinear Transformation not working" ContentLicense="CC BY-SA 3.0" />
  <row Id="5696" PostHistoryTypeId="3" PostId="2398" RevisionGUID="60dd0265-213e-4283-acd4-c4551c581829" CreationDate="2016-05-06T10:21:44.147" UserId="2383" Text="|image-processing|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5699" PostHistoryTypeId="5" PostId="2398" RevisionGUID="c9841dd5-20a8-4f0d-8124-36e2f7e64add" CreationDate="2016-05-06T14:52:11.957" UserId="231" Comment="Add syntax highlighting" Text="I implemented the algorithm shown in given link to fit given image to specified quadrilateral but the output is blank. Here is the link to the algorithm&#xD;&#xA;http://math.ewha.ac.kr/~jylee/SciComp/dip-crane/chapter8/list8_4.c&#xD;&#xA;&#xD;&#xA;I implemented it in C# as follows&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-csharp --&gt;&#xD;&#xA;&#xD;&#xA;        Bitmap inputImage = new Bitmap(&quot;D:\\Image\\A2.jpg&quot;);&#xD;&#xA;            Bitmap outputBitmap = new Bitmap(inputImage.Width, inputImage.Height);&#xD;&#xA;            double a11, a21, a31, a41;&#xD;&#xA;            double a12, a22, a32, a42;&#xD;&#xA;            double first, second;&#xD;&#xA;            double denom;&#xD;&#xA;            int u, v;&#xD;&#xA;            double floatu, floatv;&#xD;&#xA;            int i, j;&#xD;&#xA;            ulong sourcebase; /// this has been replaced by u,v i think its same&#xD;&#xA;            double x, y;&#xD;&#xA;            double A, B, C;&#xD;&#xA;            int x0 = 50, y0 = 100, x1 = 65, y1 = 110, x2 = 55, y2 = 120, x3 = 450, y3 = 110;// fix value quadrilaeral for checking purpose.&#xD;&#xA;            a11 = x0 - x1 - x3 + x2;&#xD;&#xA;            a21 = x1 - x0;&#xD;&#xA;            a31 = x3 - x0;&#xD;&#xA;            a41 = x0;&#xD;&#xA;            a12 = y0 - y1 - y3 + y2;&#xD;&#xA;            a22 = y1 - y0;&#xD;&#xA;            a32 = y3 - y0;&#xD;&#xA;            a42 = y0;&#xD;&#xA;            Console.WriteLine(&quot;inside of here&quot;);&#xD;&#xA;            A = a11 * a22 - a21 * a12;&#xD;&#xA;            if (A == 0)&#xD;&#xA;                A = 0.00001;&#xD;&#xA;            int rows = inputImage.Height, cols = inputImage.Width;&#xD;&#xA;            for (i = 0; i &lt; rows; i++)&#xD;&#xA;            {&#xD;&#xA;                y = Convert.ToDouble(i) / Convert.ToDouble(rows);&#xD;&#xA;                for (j = 0; j &lt; cols; j++)&#xD;&#xA;                {&#xD;&#xA;                    x = Convert.ToDouble(j) / Convert.ToDouble(cols);&#xD;&#xA;                    B = a12 * x - a11 * y + a11 * a42 - a41 * a12 + a31 * a22 - a21 * a32;&#xD;&#xA;                    C = a32 * x - a31 * y + a31 * a42 - a41 * a32;&#xD;&#xA;                    first = B * B;&#xD;&#xA;                    second = 4.0 * A * C;&#xD;&#xA;                    if (first &lt; second)&#xD;&#xA;                        floatu = B / (-2.0 * A);&#xD;&#xA;                    else&#xD;&#xA;                        floatu = (-1.0 * B + Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;                    if((floatu &lt; 0.0) | (floatu &gt; 1.0))&#xD;&#xA;                    {&#xD;&#xA;                        if (first &lt; second)&#xD;&#xA;                            floatu = B / -2.0 * A;&#xD;&#xA;                        else&#xD;&#xA;                            floatu = (1.0 * B - Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;                    }&#xD;&#xA;                    denom = (a11 * floatu + a31);&#xD;&#xA;                    if (denom == 0.0)&#xD;&#xA;                        denom = 0.000001;&#xD;&#xA;                    floatv = (x - a21 * floatu - a41) / denom;&#xD;&#xA;                    u = Convert.ToInt32(floatu * cols + 0.5);&#xD;&#xA;                    v = Convert.ToInt32(floatv * rows + 0.5);&#xD;&#xA;                    Color pixelColor;&#xD;&#xA;                    if ((u &gt;= cols) | (u &lt; 0) | (v &gt;= rows) | (v &lt; 0))&#xD;&#xA;                    {&#xD;&#xA;                        // Console.WriteLine(&quot;escapaed&quot;);&#xD;&#xA;                        pixelColor = Color.Black;&#xD;&#xA;                        continue;&#xD;&#xA;                    }&#xD;&#xA;                    else { /// program ne&#xD;&#xA;                        Console.WriteLine(&quot;here&quot;);&#xD;&#xA;                        //sourcebase = ((ulong)u * (ulong)cols + (ulong)v);&#xD;&#xA;                        pixelColor = inputImage.GetPixel((int)u, (int)v);&#xD;&#xA;                        outputBitmap.SetPixel(i, j, pixelColor);// =pixelColor;&#xD;&#xA;                                                                // pictureBox1.Image = outputBitmap;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;              //  Console.WriteLine(i);&#xD;&#xA;            }&#xD;&#xA;            pictureBox1.Image = outputBitmap;&#xD;&#xA;            outputBitmap.Save(&quot;output.jpg&quot;);&#xD;&#xA;            Console.WriteLine(&quot;Out Of here&quot;);&#xD;&#xA;            pictureBox1.Invalidate();&#xD;&#xA;&#xD;&#xA;//" ContentLicense="CC BY-SA 3.0" />
  <row Id="5700" PostHistoryTypeId="2" PostId="2399" RevisionGUID="e9ffd378-70b9-457c-80c2-207a7d56b290" CreationDate="2016-05-06T15:05:48.190" UserId="3305" Text="I am using matrix for performing 3D rotations. I know that in 3D space the matrix product order is important - changing the order of the matrices can effect the rotate result.&#xD;&#xA;&#xD;&#xA;So I am interesting about how can I create a rotate matrix that perform rotation (clockwise) around some vector, say $(1, 0, 1)$.&#xD;&#xA;&#xD;&#xA;I thought that $R_{(1,0,1)}(\theta) = R_X(\theta) \cdot R_Z(\theta)$ but it seems wrong because if I tries to rotate the $(1, 0, 1)$ with $45^{\circ}$ it moves out from $(1, 0, 1)$ but it should stay in place.&#xD;&#xA;&#xD;&#xA;So how can I build such a rotation matrix as product of 3D trasformation matrices?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5701" PostHistoryTypeId="1" PostId="2399" RevisionGUID="e9ffd378-70b9-457c-80c2-207a7d56b290" CreationDate="2016-05-06T15:05:48.190" UserId="3305" Text="3D rotation matrix around vector" ContentLicense="CC BY-SA 3.0" />
  <row Id="5702" PostHistoryTypeId="3" PostId="2399" RevisionGUID="e9ffd378-70b9-457c-80c2-207a7d56b290" CreationDate="2016-05-06T15:05:48.190" UserId="3305" Text="|3d|transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5706" PostHistoryTypeId="2" PostId="2401" RevisionGUID="146e9496-fcb8-4dc2-8f06-515c24f5747b" CreationDate="2016-05-06T17:16:17.913" UserDisplayName="user2500" Text="History: ATI Introduced PN triangles (a basic approach to tessellation) in its first generation to include programmable HW - so it's been around about as long as programmable HW shaders. It was deprecated in ATI's next generation, but tessellation was revived in the HW that became the basis of the Xbox 360 (a few ATI demos showed it off on PCs). Microsoft then incorporated the feature into DX11 (although not compatible with ATI/AMD's existing HW), making tessellation support a de-facto requirement for all GPU makers." ContentLicense="CC BY-SA 3.0" />
  <row Id="5707" PostHistoryTypeId="2" PostId="2402" RevisionGUID="0e3712c7-697e-444d-b93a-b2dd9df4b1ef" CreationDate="2016-05-06T17:20:52.417" UserId="2712" Text="I am trying to find an algorithm as mentioned in the subject. It is as follows:&#xD;&#xA;&#xD;&#xA;     int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;                     glm::i16vec2 &amp;p2,&#xD;&#xA;                     glm::i16vec2 &amp;p3)&#xD;&#xA;     {&#xD;&#xA;       return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;                    const glm::i16vec2 &amp;pj,&#xD;&#xA;                    const glm::i16vec2 &amp;pk)&#xD;&#xA;     {&#xD;&#xA;       if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x)) &amp;&amp;&#xD;&#xA;          (std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;        return true;&#xD;&#xA;       else&#xD;&#xA;        return false;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;     int main()&#xD;&#xA;     {&#xD;&#xA;       glm::i16vec2 hs(5,2);  // p1&#xD;&#xA;       glm::i16vec2 he(5,3); // p2&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;       glm::i16vec2 ce(5,3); // p4&#xD;&#xA;&#xD;&#xA;       int d1 = orientation(cs,ce,hs);&#xD;&#xA;       int d2 = orientation(cs,ce,he);&#xD;&#xA;       int d3 = orientation(hs,he,cs);&#xD;&#xA;       int d4 = orientation(hs,he,ce);&#xD;&#xA;&#xD;&#xA;       if((d1 == 0 &amp;&amp; d2 == 0 &amp;&amp; d3 == 0 &amp;&amp; d4 == 0) &amp;&amp;&#xD;&#xA;            (onSegment(cs,ce,hs) &amp;&amp; onSegment(cs,ce,he)))&#xD;&#xA;       {&#xD;&#xA;        std::cout &lt;&lt; &quot;HPs is entirely inside CPs&quot; &lt;&lt; std::endl;&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;       return 0;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So far it working fine. Is there any leak within procedure when it may not work as intended in some situations ? Would like  to know about those scenarios ...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 3.0" />
  <row Id="5708" PostHistoryTypeId="1" PostId="2402" RevisionGUID="0e3712c7-697e-444d-b93a-b2dd9df4b1ef" CreationDate="2016-05-06T17:20:52.417" UserId="2712" Text="Check if one line segments is entirely on the other line segment" ContentLicense="CC BY-SA 3.0" />
  <row Id="5709" PostHistoryTypeId="3" PostId="2402" RevisionGUID="0e3712c7-697e-444d-b93a-b2dd9df4b1ef" CreationDate="2016-05-06T17:20:52.417" UserId="2712" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5711" PostHistoryTypeId="2" PostId="2403" RevisionGUID="c9a02c59-d076-4a49-906c-1aaad80893f0" CreationDate="2016-05-06T20:14:27.637" UserId="38" Text="Build a matrix with one of the vectors a=(1,0,1) now you need another vector to define the matrix vector say b=(1, 0, 0) take the cross product of a  and b lets call this c. Then take the cross product of a and c for a rectified b'. Normalize a, b' and c.&#xD;&#xA;&#xD;&#xA;Your matrix T is now [a b' c] plus any affine part you deem neccesery.  Then do T&lt;sup&gt;-1&lt;/sup&gt; * Rx(Angle) * T. where Rx(a) is a function that returns a rotation matrix around the x axis with a angle of a.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5712" PostHistoryTypeId="2" PostId="2404" RevisionGUID="336e7028-505e-4012-99ed-32e0d322dfad" CreationDate="2016-05-06T21:01:50.843" UserId="48" Text="There is a direct formula for the rotation matrix for an arbitrary axis and angle. Given a unit vector $a = (a_x, a_y, a_z)$ and angle $\theta$, the matrix can be constructed as follows (derivation from [Wikipedia](https://en.wikipedia.org/wiki/Rodrigues'_rotation_formula#Matrix_notation)):&#xD;&#xA;&#xD;&#xA;First build a matrix $C$ from the components of $a$ according to the following formula:&#xD;&#xA;&#xD;&#xA;$$ C =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;  0 &amp; -a_z &amp; a_y \\&#xD;&#xA;  a_z &amp; 0 &amp; -a_x \\&#xD;&#xA;  -a_y &amp; a_x &amp; 0&#xD;&#xA;\end{bmatrix} $$&#xD;&#xA;&#xD;&#xA;Then you can construct the rotation matrix from $C$ as follows:&#xD;&#xA;&#xD;&#xA;$$ R_a(\theta) = I + C \sin \theta + C^2 (1 - \cos \theta) $$&#xD;&#xA;&#xD;&#xA;where $I$ is the 3&amp;times;3 identity matrix. This assumes you're using a column-vector convention; if you're using row vectors instead, transpose $C$.&#xD;&#xA;&#xD;&#xA;By the way, this formula has a neat geometric interpretation. The matrix $C$ has the effect of calculating cross products with $a$. In other words, for any vector $v$, $Cv = a \times v$. If you imagine rotating some vector $v$ about $a$, the tip of $v$ traces out a circle perpendicular to $a$; $Cv$ is a vector tangent to that circle, and $C^2 v$ (which equals $a \times (a \times v)$) is a vector normal to the circle. So with those two vectors, you have a basis for the plane of the circle; then you can apply a variation of the usual sine/cosine formula for points on a circle.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5713" PostHistoryTypeId="5" PostId="2381" RevisionGUID="56a10dea-e7b0-40e9-a37e-19b10a03095f" CreationDate="2016-05-06T21:11:45.187" UserId="3304" Comment="Copy edited." Text="In a plane, we have a **convex** polygon with n sides. What would be the maximum number of disconnected pieces / fragments if this polygon is clipped against a square?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5714" PostHistoryTypeId="4" PostId="2381" RevisionGUID="56a10dea-e7b0-40e9-a37e-19b10a03095f" CreationDate="2016-05-06T21:11:45.187" UserId="3304" Comment="Copy edited." Text="Finding the maximum number of disconnected fragments" ContentLicense="CC BY-SA 3.0" />
  <row Id="5715" PostHistoryTypeId="24" PostId="2381" RevisionGUID="56a10dea-e7b0-40e9-a37e-19b10a03095f" CreationDate="2016-05-06T21:11:45.187" Comment="Proposed by 3304 approved by 310, 48 edit id of 136" ContentLicense="CC BY-SA 3.0" />
  <row Id="5716" PostHistoryTypeId="2" PostId="2405" RevisionGUID="f2cd043d-44d2-4591-a8d7-c155e8e43453" CreationDate="2016-05-06T21:46:39.237" UserId="2736" Text="So I been thinking about this for a while and tried to google for an answer but without any success.&#xD;&#xA;&#xD;&#xA;If all your textures are 8bit LDR images, like JPEGs, couldn't that potentially cause conflicts with exposure control/tone mapping when rendering. That is if you adjust the rendering exposure of your image that should expose detail in the textures that aren't really there, since they been clamped out by the low dynamic range. So wouldn't it make sense to also have the textures as HDR images, saved as .exr, in linear colour space with 16bit half-float to get a good colour representation (32bit &quot;full&quot; float might be overkill?). To have more detailed and correct colour values might also, I figure, have an effect on GI and how colour bleed is calculated?&#xD;&#xA;&#xD;&#xA;Or is it simply not necessary since the end result of the rendering we want is probably going to be similar to the exposure level of the texture when it was photographed any way? And since camera mostly shoot in 12-14bit you would have to take multiple exposures of the texture and do all that extra work to piece them all together to one HDRI. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5717" PostHistoryTypeId="1" PostId="2405" RevisionGUID="f2cd043d-44d2-4591-a8d7-c155e8e43453" CreationDate="2016-05-06T21:46:39.237" UserId="2736" Text="16bit half-float linear HDR images as (diffuse/albedo) textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5718" PostHistoryTypeId="3" PostId="2405" RevisionGUID="f2cd043d-44d2-4591-a8d7-c155e8e43453" CreationDate="2016-05-06T21:46:39.237" UserId="2736" Text="|texture|physically-based|pbr|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5719" PostHistoryTypeId="2" PostId="2406" RevisionGUID="97b56ff0-05e5-45e3-809b-2fdf3f059394" CreationDate="2016-05-07T06:17:59.660" UserId="48" Text="Yes, it's possible in some extreme cases for HDR lighting and tonemapping to expose banding issues in color textures. In those cases, having a higher bit depth for the textures could be useful. However, in my experience the majority of materials and ordinary lighting situations don't exhibit this problem, and most textures in a typical game are fine in 8-bit (or even less&amp;mdash;games often use BC1 compression, which reduces them to 5-6-5-bit).&#xD;&#xA;&#xD;&#xA;People use HDR render targets because a single scene can contain vastly different magnitudes of brightness, such as a dark room in which you can see through a window to a sunlit exterior 10&amp;ndash;100 times brighter than the room. However, color textures don't have such a wide range of magnitudes. They represent reflectances, which are inherently in the [0, 1] range, and in practice few everyday materials are lower than about 2&amp;ndash;5% reflectance. So an 8-bit image (with gamma encoding) can usually represent diffuse and specular colors with enough precision.&#xD;&#xA;&#xD;&#xA;It's true that the combination of a quite dark texture with very bright lighting or an extremely overexposed camera setting can show banding in the final frame, but that would be a more unusual case.&#xD;&#xA;&#xD;&#xA;A case where you probably *would* want an HDR texture is emissive materials, especially for neon signs and similar light sources. The texture would appear with its value amped up to appear as a bright light source in game, so in that case an 8-bit image could easily show banding.&#xD;&#xA;&#xD;&#xA;Finally, it can still be useful to work at higher precision (e.g. 16-bit precision) if possible when capturing and creating textures, simply because it gives you more headroom to process the image without causing precision problems. For instance, if you need to adjust levels or color balance, you lose a little precision; that can introduce banding (especially if you do it multiple times) when starting from an 8-bit source image. A 16-bit source would be more resilient to such problems. However, the final texture used in the game would still probably be compressed to 8-bit." ContentLicense="CC BY-SA 3.0" />
  <row Id="5720" PostHistoryTypeId="2" PostId="2407" RevisionGUID="441ad988-0386-4587-8e1b-b32255030d7d" CreationDate="2016-05-07T06:40:03.413" UserId="38" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole.&#xD;&#xA;2. When the lines exit 2 times you have one fragment&#xD;&#xA;3. when the lines exit 4 times you have two fragments&#xD;&#xA;4. when the exits are 6 times you have three fragments&#xD;&#xA;5. when the exits are 8 times you have four fragments&#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four**.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5721" PostHistoryTypeId="5" PostId="2407" RevisionGUID="c312c18e-d8c2-44d2-a681-0aa8d9041916" CreationDate="2016-05-07T06:51:58.887" UserId="38" Comment="added 52 characters in body" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole.&#xD;&#xA;2. When the lines exit 2 times you have one fragment&#xD;&#xA;3. when the lines exit 4 times you have two fragments&#xD;&#xA;4. when the exits are 6 times you have three fragments&#xD;&#xA;5. when the exits are 8 times you have four fragments&#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four** or five if you count the clipped part as one piece. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5723" PostHistoryTypeId="5" PostId="2407" RevisionGUID="dc34c1f0-9766-42bf-9f11-9b919e24f423" CreationDate="2016-05-07T08:41:48.643" UserId="38" Comment="added 55 characters in body" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole.&#xD;&#xA;2. When the lines exit 2 times you have one fragment&#xD;&#xA;3. when the lines exit 4 times you have two fragments&#xD;&#xA;4. when the exits are 6 times you have three fragments&#xD;&#xA;5. when the exits are 8 times you have four fragments&#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four** or five if you count the clipped part as one piece. Also worth to note that the cliped polygons are convex.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5724" PostHistoryTypeId="2" PostId="2409" RevisionGUID="bad3fe19-a76c-4fda-9c12-3a11f94aab46" CreationDate="2016-05-07T10:24:23.030" UserId="273" Text="I have a Optix Raycasting renderer which loads and renders VTK files.&#xD;&#xA;For a single static model this works fine.&#xD;&#xA;&#xD;&#xA;But now my dataset consists of multiple timesteps which I want to display in a animated fashion.&#xD;&#xA;&#xD;&#xA;Each couple of frames or seconds the displayed model has to be switched out with the next one.&#xD;&#xA;If possible I want to refrain from rebuilding the acceleration structure each time this happens.&#xD;&#xA;&#xD;&#xA;So my question: Can I just load all models at once, place them in the global acceleration structure and then just switch all off except the one currently displayed.&#xD;&#xA;My hope is that this would be more efficient." ContentLicense="CC BY-SA 3.0" />
  <row Id="5725" PostHistoryTypeId="1" PostId="2409" RevisionGUID="bad3fe19-a76c-4fda-9c12-3a11f94aab46" CreationDate="2016-05-07T10:24:23.030" UserId="273" Text="Optix: Rendering time-variant data" ContentLicense="CC BY-SA 3.0" />
  <row Id="5726" PostHistoryTypeId="3" PostId="2409" RevisionGUID="bad3fe19-a76c-4fda-9c12-3a11f94aab46" CreationDate="2016-05-07T10:24:23.030" UserId="273" Text="|vtk|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5728" PostHistoryTypeId="5" PostId="2407" RevisionGUID="ff0b25b6-7f34-4891-ac3b-cbcbade10f1b" CreationDate="2016-05-07T12:19:05.470" UserId="38" Comment="deleted 57 characters in body" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole.&#xD;&#xA;2. When the lines exit 2 times you have one fragment&#xD;&#xA;3. when the lines exit 4 times you have two fragments&#xD;&#xA;4. when the exits are 6 times you have three fragments&#xD;&#xA;5. when the exits are 8 times you have four fragments&#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four** or five if you count the clipped part as one piece. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5729" PostHistoryTypeId="2" PostId="2410" RevisionGUID="0cb64e26-b5a7-41bf-8281-fc8d68e7b7d4" CreationDate="2016-05-07T12:46:39.143" UserId="1971" Text="Specify individually the translation and scaling matrices required to transform a 2D&#xD;&#xA;window of [Xmin=-234, Ymin=156] and [Xmax=66, Ymax=456] to a display viewport&#xD;&#xA;of [Umin=45, Vmin=35] and [Umax=245, Vmax=185].&#xD;&#xA;&#xD;&#xA;**Ignore the question above since I solved the matrix, the information is just relevant for the question I'm stuck on**&#xD;&#xA;&#xD;&#xA;I was asked to compute the view-port positions (U1,V1) and (U2,V2) for two points A (-100,300)&#xD;&#xA;and B (30,-40) in a 2D window and determine if these two points are inside the view-port.&#xD;&#xA;&#xD;&#xA;Based on the transformation Matrix I found (U1,V1) to be (403/3, 407) and (U2,v2) to be (221, -103). It turns out that both these points are outside our view-port but part of the line between them is inside.&#xD;&#xA;&#xD;&#xA;Now I'm confused about this part below:&#xD;&#xA;&#xD;&#xA;Apply a 2D clipping method to the line segment between the two points A and B as&#xD;&#xA;given in above.&#xD;&#xA;&#xD;&#xA;**My Attempt**&#xD;&#xA;&#xD;&#xA;delta x = 221-(403/3) = 260/3&#xD;&#xA;&#xD;&#xA;delta y = -103 - 406 = -510&#xD;&#xA;&#xD;&#xA;m = delta y / delta x = -5.88&#xD;&#xA;&#xD;&#xA;I started with U1,V1 since it is above our viewport:&#xD;&#xA;&#xD;&#xA;Y = 185&#xD;&#xA;&#xD;&#xA;X = 403/3 + (185-407)*(delta x/ delta y)&#xD;&#xA;&#xD;&#xA;X = 279.48&#xD;&#xA;&#xD;&#xA;Point 1 - (172, 185) &#xD;&#xA;&#xD;&#xA;Is this correct? Since the point is now within the view-port. Do I then do the same for the second point?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5730" PostHistoryTypeId="1" PostId="2410" RevisionGUID="0cb64e26-b5a7-41bf-8281-fc8d68e7b7d4" CreationDate="2016-05-07T12:46:39.143" UserId="1971" Text="Cohen-Sutherland Clipping" ContentLicense="CC BY-SA 3.0" />
  <row Id="5731" PostHistoryTypeId="3" PostId="2410" RevisionGUID="0cb64e26-b5a7-41bf-8281-fc8d68e7b7d4" CreationDate="2016-05-07T12:46:39.143" UserId="1971" Text="|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5732" PostHistoryTypeId="5" PostId="2407" RevisionGUID="f11cbcf7-6f5e-4d61-ae8a-8ecd96637c66" CreationDate="2016-05-07T14:46:13.920" UserId="38" Comment="added 17 characters in body" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole.&#xD;&#xA;2. When the lines exit 2 times you have one fragment&#xD;&#xA;3. when the lines exit 4 times you have two fragments or less&#xD;&#xA;4. when the exits are 6 times you have three fragments or less&#xD;&#xA;5. when the exits are 8 times you have four fragments &#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four** or five if you count the clipped part as one piece. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5733" PostHistoryTypeId="2" PostId="2411" RevisionGUID="fa86d679-5c47-409c-932d-c0b03cb91380" CreationDate="2016-05-08T12:23:55.243" UserId="2359" Text="This is how the rendering equation is written in the textbook&#xD;&#xA;&#xD;&#xA;L(p,w)=L&lt;sub&gt;e&lt;/sub&gt;(p,w)+∫f(p,w&lt;sub&gt;i&lt;/sub&gt;,ω0)L(p*,-ω&lt;sub&gt;i&lt;/sub&gt;)cos0dω&lt;sub&gt;i&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;which component of this equation handles the shadowing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5734" PostHistoryTypeId="1" PostId="2411" RevisionGUID="fa86d679-5c47-409c-932d-c0b03cb91380" CreationDate="2016-05-08T12:23:55.243" UserId="2359" Text="How does the rendering equation incorporate shadowing" ContentLicense="CC BY-SA 3.0" />
  <row Id="5735" PostHistoryTypeId="3" PostId="2411" RevisionGUID="fa86d679-5c47-409c-932d-c0b03cb91380" CreationDate="2016-05-08T12:23:55.243" UserId="2359" Text="|rendering|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5736" PostHistoryTypeId="2" PostId="2412" RevisionGUID="a36728f9-6b83-480c-9d2d-982cea4d2dc2" CreationDate="2016-05-08T12:39:12.340" UserId="3305" Text="In perspective projection, group of parallel lines have the same vanishing point. I am interesting about the reverse calculation: Getting the group of parallel lines equations that their vanishing point specific point.&#xD;&#xA;&#xD;&#xA;Say I know that the camera is perspective camera at $(0,0,0)$ and it's direction is $(0,0,1)$, the view plane is $z = 1$ and I am interesting about the lines in plane $y= y_0$ that their vanishing point is $P = (p_x,p_y,p_z)$.&#xD;&#xA;&#xD;&#xA;I have tried to calculate the projection point of some point $(x,y_0,z)$ and get the equations:  &#xD;&#xA;(i) $p_x = x(\frac1z)$  &#xD;&#xA;(ii) $p_y = y_0(\frac1z)$  &#xD;&#xA;(iii) $p_z = 1$&#xD;&#xA;&#xD;&#xA;But it seems wrong because if the vanishing point is like $(x_0,0,*)$ then form (ii) we will get $z\rightarrow \infty$ but then (i) is wrong because $x(\frac1z)\rightarrow0$ but it need to be equals to $x_0$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So how can I get the group of parallel lines have the same vanishing point in these conditions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5737" PostHistoryTypeId="1" PostId="2412" RevisionGUID="a36728f9-6b83-480c-9d2d-982cea4d2dc2" CreationDate="2016-05-08T12:39:12.340" UserId="3305" Text="Calculate vanishing point" ContentLicense="CC BY-SA 3.0" />
  <row Id="5738" PostHistoryTypeId="3" PostId="2412" RevisionGUID="a36728f9-6b83-480c-9d2d-982cea4d2dc2" CreationDate="2016-05-08T12:39:12.340" UserId="3305" Text="|3d|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5739" PostHistoryTypeId="2" PostId="2413" RevisionGUID="f15a0213-7f32-4af1-b163-dd71fc8d0b20" CreationDate="2016-05-08T12:53:05.680" UserId="137" Text="Light that is blocked will mean that $L(p*, -w_i)$ under the integral is 0 plus how much light the blocking object reflects itself. &#xD;&#xA;&#xD;&#xA;In other words the shadowing is embedded in the incoming light function.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5740" PostHistoryTypeId="2" PostId="2414" RevisionGUID="1b46747d-e141-48bf-96fc-6be970a19cc8" CreationDate="2016-05-08T13:42:24.037" UserId="137" Text="Here's a hint to get you started: Parallel lines include the line through the camera. &#xD;&#xA;&#xD;&#xA;So really all you need is the direction from the camera to the vanishing point on the view plane. Then create lines parallel to that line." ContentLicense="CC BY-SA 3.0" />
  <row Id="5741" PostHistoryTypeId="5" PostId="2413" RevisionGUID="d9ad958a-455e-4762-8fd8-23184e04ddc6" CreationDate="2016-05-08T15:40:27.513" UserId="137" Comment="edited body" Text="Light that is blocked will mean that $L(p*, -w_i)$ under the integral is 0 plus how much light the blocking object itself reflects. &#xD;&#xA;&#xD;&#xA;In other words the shadowing is embedded in the incoming light function.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5742" PostHistoryTypeId="5" PostId="2411" RevisionGUID="75fc8030-b8d6-4282-abb9-8c30f266e39e" CreationDate="2016-05-08T15:42:01.227" UserId="3305" Comment="Improved formatting" Text="This is how the rendering equation is written in the textbook&#xD;&#xA;&#xD;&#xA;$L(p,w)=L_e(p,w)+∫f(p,w_i,ω0)L(p*,-ω_i)cos0 dω_i$&#xD;&#xA;&#xD;&#xA;which component of this equation handles the shadowing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5743" PostHistoryTypeId="24" PostId="2411" RevisionGUID="75fc8030-b8d6-4282-abb9-8c30f266e39e" CreationDate="2016-05-08T15:42:01.227" Comment="Proposed by 3305 approved by -1 edit id of 137" ContentLicense="CC BY-SA 3.0" />
  <row Id="5744" PostHistoryTypeId="5" PostId="2411" RevisionGUID="342df670-48e5-44e0-ab89-268bfb3bd4fa" CreationDate="2016-05-08T15:42:01.227" UserId="137" Comment="Improved formatting" Text="This is how the rendering equation is written in the textbook&#xD;&#xA;&#xD;&#xA;$L(p,w)=L_e(p,w)+\int f(p,w_i,ω_0)L(p*,-ω_i)\cos 0 dω_i$&#xD;&#xA;&#xD;&#xA;which component of this equation handles the shadowing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5745" PostHistoryTypeId="5" PostId="2411" RevisionGUID="ec44c454-7009-466e-bae2-0586b938a631" CreationDate="2016-05-08T18:31:34.063" UserId="48" Comment="improved math formatting" Text="This is how the rendering equation is written in the textbook&#xD;&#xA;&#xD;&#xA;$$L(p,\omega) = L_e(p,\omega) + \int f(p,\omega_i,\omega) \, L(p*,-\omega_i)\cos \theta \, d\omega_i$$&#xD;&#xA;&#xD;&#xA;which component of this equation handles the shadowing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5746" PostHistoryTypeId="5" PostId="2407" RevisionGUID="4161f185-0944-4ce8-9fbf-014c2288cb84" CreationDate="2016-05-08T20:04:54.253" UserId="38" Comment="added 67 characters in body" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole or the entire polygon is contained and theres no hole and no piece.&#xD;&#xA;2. When the lines exit 2 times you have one fragment&#xD;&#xA;3. when the lines exit 4 times you have two fragments &#xD;&#xA;4. when the exits are 6 times you have three fragments &#xD;&#xA;5. when the exits are 8 times you have four fragments &#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four** or five if you count the clipped part as one piece. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5747" PostHistoryTypeId="5" PostId="2407" RevisionGUID="7607d40b-5ff7-4103-9798-03ec4bfb101b" CreationDate="2016-05-08T20:18:18.947" UserId="38" Comment="added 214 characters in body" Text="A convex polygon has the property:&#xD;&#xA;&#xD;&#xA; * A line drawn through a convex polygon will intersect the polygon exactly twice.&#xD;&#xA;&#xD;&#xA;  From this follows that any line trough splits the convex polygon in 2 pieces.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: convex polygon split by a line.&#xD;&#xA;&#xD;&#xA;Using this, and assuming the inner piece is discarded we can craw the conclusion that there are five cases:&#xD;&#xA;&#xD;&#xA;1. When the lines of the square do not exit the polygon. You now have a piece with a hole or the entire polygon is contained and theres no hole and no piece.&#xD;&#xA;2. When the lines exit 2 times you have one fragment\*&#xD;&#xA;3. when the lines exit 4 times you have two fragments\*&#xD;&#xA;4. when the exits are 6 times you have three fragments\* &#xD;&#xA;5. when the exits are 8 times you have four fragments \*&#xD;&#xA;&#xD;&#xA;  [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  **Image 2**: the five cases, clipping rectangle and remaining shards in black. Even a squares has same cases if the polygons vary, just easier to draw this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last case is the maximum so answer is **four** or five if you count the clipped part as one piece. &#xD;&#xA;&#xD;&#xA;\* Since we haven't tackled the cases very rigorously we know that this is the highest possible answer, there could be less for each case. There shouldn't be but I so far haven't given evidence for that. But thats okay it wasn't asked.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uyM6r.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OwHAq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5752" PostHistoryTypeId="5" PostId="2409" RevisionGUID="b24efdf9-2d22-4cdb-92be-11a4154beec1" CreationDate="2016-05-09T11:45:01.930" UserId="273" Comment="Added what I have already tried." Text="I have a Optix Raycasting renderer which loads and renders VTK files.&#xD;&#xA;For a single static model this works fine.&#xD;&#xA;&#xD;&#xA;But now my dataset consists of multiple timesteps which I want to display in a animated fashion.&#xD;&#xA;&#xD;&#xA;Each couple of frames or seconds the displayed model has to be switched out with the next one.&#xD;&#xA;If possible I want to refrain from rebuilding the acceleration structure each time this happens.&#xD;&#xA;&#xD;&#xA;So my question: Can I just load all models at once, place them in the global acceleration structure and then just switch all off except the one currently displayed.&#xD;&#xA;My hope is that this would be more efficient.&#xD;&#xA;&#xD;&#xA;Edit 1:&#xD;&#xA;I have now build a variant in which I create _optix::Acceleration_ and _optix::Group_ for each of the timesteps separate and each time the active timestep changes I just &#xD;&#xA;&#xD;&#xA;    _context[&quot;top_object&quot;]-&gt;set(mesh_group[timestep]);&#xD;&#xA;&#xD;&#xA;But each this call takes nearly half a second. I think optix does quite some work in the background when I switch this object out.&#xD;&#xA;This delay is not acceptable for me as it makes the playback of my &quot;animation&quot; stutter.&#xD;&#xA;&#xD;&#xA;Has anyone a idea how to do this more efficient?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5758" PostHistoryTypeId="2" PostId="2416" RevisionGUID="e57e808e-af8a-4906-8a51-08eb2ee5ce57" CreationDate="2016-05-09T14:39:36.810" UserId="3319" Text="Here's an odd intellectual puzzle.  Something I was daydreaming about on a train - but the maths are somewhat beyond me.  How would someone go about un-winding a spiral to produce a long flat image?  Like a rope on a spool, I'd want to uncoil the rope so that it lay long and flat.  The function would have to take in the image data (imageData) and the imageHeight (the height of the output strip - and hence also the thickness of the 'rope' on the spool).  Assumptions that could be made are that the input image is square, containing a circle whose top and bottom touch the top and bottom of the square - and left and right similarly.  The hub of circle would be in the absolute centre of the image.&#xD;&#xA;&#xD;&#xA;    (char*) unwindImage (char* imageData, int imageHeight)&#xD;&#xA;&#xD;&#xA;Has anyone else puzzled over this?  And, if so, what solution did your come up with?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5759" PostHistoryTypeId="1" PostId="2416" RevisionGUID="e57e808e-af8a-4906-8a51-08eb2ee5ce57" CreationDate="2016-05-09T14:39:36.810" UserId="3319" Text="Unwinding an image on a spiral to make it long and flat" ContentLicense="CC BY-SA 3.0" />
  <row Id="5760" PostHistoryTypeId="3" PostId="2416" RevisionGUID="e57e808e-af8a-4906-8a51-08eb2ee5ce57" CreationDate="2016-05-09T14:39:36.810" UserId="3319" Text="|algorithm|transformations|mathematics|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5761" PostHistoryTypeId="2" PostId="2417" RevisionGUID="4f1b0b83-740e-4b5f-a2ad-be927bb917f2" CreationDate="2016-05-09T16:45:13.933" UserId="3323" Text="I'm searching a way to implement a linear gradient shader that behaves as the linear gradient in Photoshop (only the vertical case is necessary). It will be applied to 2D sprites.&#xD;&#xA;&#xD;&#xA;Currently I'm passing to the pixel shader these parameters:&#xD;&#xA;&#xD;&#xA; - StartColor.&#xD;&#xA; - EndColor.&#xD;&#xA; - Offset: an offset applied to the gradient starting point.&#xD;&#xA; - Length: the gradient length (the range inside where the colors will be&#xD;&#xA;   interpolated).&#xD;&#xA; - isFixed: a boolean parameter that indicates if the&#xD;&#xA;   gradient must be influenced by the camera position or not.&#xD;&#xA;&#xD;&#xA;Here a first attempt of the vertex shader and the pixel shader that I've implemented:&#xD;&#xA;&#xD;&#xA;    struct VsInput&#xD;&#xA;    {&#xD;&#xA;        float3 position : VES_POSITION;&#xD;&#xA;        float2 uv	    : VES_TEXCOORD0;&#xD;&#xA;        float4 color    : VES_COLOR;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VsOutput&#xD;&#xA;    {&#xD;&#xA;        float4 position : HPOS;&#xD;&#xA;        float2 uv	    : TEXCOORD0;&#xD;&#xA;        float4 color    : COLOR0;&#xD;&#xA;        float4 outPos   : TEXCOORD1;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    VsOutput main(VsInput input)&#xD;&#xA;    {&#xD;&#xA;        VsOutput vsOutput;&#xD;&#xA;        vsOutput.position = MUL(float4(input.position, 1.0f), WorldViewProjection);&#xD;&#xA;        vsOutput.uv = input.uv;&#xD;&#xA;        vsOutput.color = input.color;&#xD;&#xA;        vsOutput.outPos = vsOutput.position;&#xD;&#xA;    &#xD;&#xA;        return vsOutput;&#xD;&#xA;    }&#xD;&#xA;    struct PsInput&#xD;&#xA;    {&#xD;&#xA;        float4 Position : HPOS;&#xD;&#xA;        float2 UV	    : TEXCOORD0;&#xD;&#xA;        float4 Color    : COLOR0;&#xD;&#xA;        float4 outPos   : TEXCOORD1;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float4 startColor;&#xD;&#xA;    float4 endColor;&#xD;&#xA;    float offset;&#xD;&#xA;    float len;&#xD;&#xA;    bool isFixed;&#xD;&#xA;    &#xD;&#xA;    float4 main(PsInput psInput) : COLOR&#xD;&#xA;    {&#xD;&#xA;        psInput.outPos = psInput.outPos / psInput.outPos.w;&#xD;&#xA;        float yScreenSize = 900.0f;&#xD;&#xA;        float yPixelCoordinate = 0.0f;&#xD;&#xA;        if (isFixed)&#xD;&#xA;        {&#xD;&#xA;    	    yPixelCoordinate = 0.5f * (1.0f - psInput.UV.y) * yScreenSize;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            yPixelCoordinate = 0.5f * (psInput.outPos.y + 1.0f) * yScreenSize;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        float gradient = (yPixelCoordinate + offset) / len;&#xD;&#xA;        gradient = clamp(gradient, 0.0f, 1.0f);&#xD;&#xA;        return lerp(startColor, endColor, gradient);&#xD;&#xA;    }&#xD;&#xA;When **isFixed** is false I want the gradient influenced by the camera position. But my shader is wrong, since the starting point of the gradient is the bottom of the window instead of the bottom of the sprite.&#xD;&#xA;The question is: how can I modify the shader in order to have the gradient starting from the bottom of the sprite? Maybe I need the size of the sprite in pixel? Or there are other convenient ways?&#xD;&#xA; &#xD;&#xA;The other question regards the &quot;fixed gradient&quot;: if I want the gradient not influenced by the camera position, what is the convenient way? It's possible to have these two behaviors in the same shader?&#xD;&#xA;&#xD;&#xA;Maybe the sentence _gradient influenced by the camera_, it is not correct, so I'll try to be more clear with a few images (taken using the shaders above).&#xD;&#xA;&#xD;&#xA;In the first image you can see a base sprite (in black) with an orange gradient applied to it. On top of the base you can see the player sprite; the camera is attached to this one.&#xD;&#xA;&#xD;&#xA;In the second image the player has jumped and the camera follows him: the **isFixed** attribute is false and, as you can see, the gradiend moves with the player and the camera.&#xD;&#xA;&#xD;&#xA;The third image shows the same situation of the second image, but the **isFixed** attribute is true and, as you can see, the gradient don't moves with the player and the camera.&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;[![][2]][2]&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IhsGb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PptVQ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/MzWOl.png&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="5762" PostHistoryTypeId="1" PostId="2417" RevisionGUID="4f1b0b83-740e-4b5f-a2ad-be927bb917f2" CreationDate="2016-05-09T16:45:13.933" UserId="3323" Text="Linear gradient shader ( Photoshop-like)" ContentLicense="CC BY-SA 3.0" />
  <row Id="5763" PostHistoryTypeId="3" PostId="2417" RevisionGUID="4f1b0b83-740e-4b5f-a2ad-be927bb917f2" CreationDate="2016-05-09T16:45:13.933" UserId="3323" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5768" PostHistoryTypeId="2" PostId="2419" RevisionGUID="d1101895-2a22-49ea-9dee-519a12d656a9" CreationDate="2016-05-09T21:54:21.997" UserId="2712" Text="Once a 3D model is sliced against a plane and projected onto it, we get a contour curve at certain height. The contour curve I am generating in this process is made of several line segments in closed loop. Now I want to generate another contour curve with the following characteristics:&#xD;&#xA;&#xD;&#xA;1. Each of the line segment of the newly generated inner contour curve must be parallel to the corresponding line segments at the outer contour curve.&#xD;&#xA;&#xD;&#xA;2. Each of the parallel line segments on both outer and inner contour curve has an adjacent distance in between and defined by a constant value as shown in the attached picture (green mark) &#xD;&#xA;&#xD;&#xA;[Image Link][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I need some suggested algorithms to generate it . I hope that I have explained the issue properly. Please do let me know if it is not clear enough.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cptpE.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5769" PostHistoryTypeId="1" PostId="2419" RevisionGUID="d1101895-2a22-49ea-9dee-519a12d656a9" CreationDate="2016-05-09T21:54:21.997" UserId="2712" Text="generate multiple border contour" ContentLicense="CC BY-SA 3.0" />
  <row Id="5770" PostHistoryTypeId="3" PostId="2419" RevisionGUID="d1101895-2a22-49ea-9dee-519a12d656a9" CreationDate="2016-05-09T21:54:21.997" UserId="2712" Text="|computer-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5771" PostHistoryTypeId="5" PostId="2398" RevisionGUID="063f51da-0656-400b-8002-688c97f78ce5" CreationDate="2016-05-10T00:04:00.297" UserId="2383" Comment="deleted 2 characters in body" Text="I implemented the algorithm shown in given link to fit given image to specified quadrilateral but the output is blank. Here is the link to the algorithm&#xD;&#xA;http://math.ewha.ac.kr/~jylee/SciComp/dip-crane/chapter8/list8_4.c&#xD;&#xA;&#xD;&#xA;I implemented it in C# as follows&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-csharp --&gt;&#xD;&#xA;&#xD;&#xA;        Bitmap inputImage = new Bitmap(&quot;D:\\Image\\A2.jpg&quot;);&#xD;&#xA;            Bitmap outputBitmap = new Bitmap(inputImage.Width, inputImage.Height);&#xD;&#xA;            double a11, a21, a31, a41;&#xD;&#xA;            double a12, a22, a32, a42;&#xD;&#xA;            double first, second;&#xD;&#xA;            double denom;&#xD;&#xA;            int u, v;&#xD;&#xA;            double floatu, floatv;&#xD;&#xA;            int i, j;&#xD;&#xA;            ulong sourcebase; /// this has been replaced by u,v i think its same&#xD;&#xA;            double x, y;&#xD;&#xA;            double A, B, C;&#xD;&#xA;            int x0 = 50, y0 = 100, x1 = 65, y1 = 110, x2 = 55, y2 = 120, x3 = 450, y3 = 110;// fix value quadrilaeral for checking purpose.&#xD;&#xA;            a11 = x0 - x1 - x3 + x2;&#xD;&#xA;            a21 = x1 - x0;&#xD;&#xA;            a31 = x3 - x0;&#xD;&#xA;            a41 = x0;&#xD;&#xA;            a12 = y0 - y1 - y3 + y2;&#xD;&#xA;            a22 = y1 - y0;&#xD;&#xA;            a32 = y3 - y0;&#xD;&#xA;            a42 = y0;&#xD;&#xA;            Console.WriteLine(&quot;inside of here&quot;);&#xD;&#xA;            A = a11 * a22 - a21 * a12;&#xD;&#xA;            if (A == 0)&#xD;&#xA;                A = 0.00001;&#xD;&#xA;            int rows = inputImage.Height, cols = inputImage.Width;&#xD;&#xA;            for (i = 0; i &lt; rows; i++)&#xD;&#xA;            {&#xD;&#xA;                y = Convert.ToDouble(i) / Convert.ToDouble(rows);&#xD;&#xA;                for (j = 0; j &lt; cols; j++)&#xD;&#xA;                {&#xD;&#xA;                    x = Convert.ToDouble(j) / Convert.ToDouble(cols);&#xD;&#xA;                    B = a12 * x - a11 * y + a11 * a42 - a41 * a12 + a31 * a22 - a21 * a32;&#xD;&#xA;                    C = a32 * x - a31 * y + a31 * a42 - a41 * a32;&#xD;&#xA;                    first = B * B;&#xD;&#xA;                    second = 4.0 * A * C;&#xD;&#xA;                    if (first &lt; second)&#xD;&#xA;                        floatu = B / (-2.0 * A);&#xD;&#xA;                    else&#xD;&#xA;                        floatu = (-1.0 * B + Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;                    if((floatu &lt; 0.0) | (floatu &gt; 1.0))&#xD;&#xA;                    {&#xD;&#xA;                        if (first &lt; second)&#xD;&#xA;                            floatu = B / -2.0 * A;&#xD;&#xA;                        else&#xD;&#xA;                            floatu = (1.0 * B - Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;                    }&#xD;&#xA;                    denom = (a11 * floatu + a31);&#xD;&#xA;                    if (denom == 0.0)&#xD;&#xA;                        denom = 0.000001;&#xD;&#xA;                    floatv = (x - a21 * floatu - a41) / denom;&#xD;&#xA;                    u = Convert.ToInt32(floatu * cols + 0.5);&#xD;&#xA;                    v = Convert.ToInt32(floatv * rows + 0.5);&#xD;&#xA;                    Color pixelColor;&#xD;&#xA;                    if ((u &gt;= cols) | (u &lt; 0) | (v &gt;= rows) | (v &lt; 0))&#xD;&#xA;                    {&#xD;&#xA;                        // Console.WriteLine(&quot;escapaed&quot;);&#xD;&#xA;                        pixelColor = Color.Black;&#xD;&#xA;                        continue;&#xD;&#xA;                    }&#xD;&#xA;                    else { /// program ne&#xD;&#xA;                        Console.WriteLine(&quot;here&quot;);&#xD;&#xA;                        //sourcebase = ((ulong)u * (ulong)cols + (ulong)v);&#xD;&#xA;                        pixelColor = inputImage.GetPixel((int)u, (int)v);&#xD;&#xA;                        outputBitmap.SetPixel(i, j, pixelColor);// =pixelColor;&#xD;&#xA;                                                                // pictureBox1.Image = outputBitmap;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;              //  Console.WriteLine(i);&#xD;&#xA;            }&#xD;&#xA;            pictureBox1.Image = outputBitmap;&#xD;&#xA;            outputBitmap.Save(&quot;output.jpg&quot;);&#xD;&#xA;            Console.WriteLine(&quot;Out Of here&quot;);&#xD;&#xA;            pictureBox1.Invalidate();&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5772" PostHistoryTypeId="2" PostId="2420" RevisionGUID="41194128-fbd1-4a44-a5a1-56f26f361f0d" CreationDate="2016-05-10T00:42:44.313" UserId="1614" Text="I'd like to invite readers to read this article about [Quake 2 engine rasterization technology explained in details][1], if they have the time.&#xD;&#xA;&#xD;&#xA;If TLDR, please pay attention to this image:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What we see is the **Albedo** channel, that's what you want to encode in 16 bits if I understand your question correctly.  &#xD;&#xA;I'm not going to say &quot;*if it could be encoded in 256 colors for games in the past, why would we need 281474976710656 (that's 281 trillion) in new games?*&quot; even if I want to but that sounds like pixar's grumpy guy from Up. More constructively, if you noted in this image, **everything is at the same lighting level**. More particularly, the maximum intensity possible that preserves the desired saturation. (meaning in HSV space, V is maxed out)&#xD;&#xA;&#xD;&#xA;The emphasis is key, we barely need any bits because albedo has no depth to encode anyway. The dynamic comes from the shading, it makes sense to work in `f32` per components within shaders, and output to `f16` render targets. But storing albedo textures in `f16` that's not only overkill, that's a severe unjustified performance hog for our precious bandwidth.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://fabiensanglard.net/quake2/quake2_software_renderer.php&#xD;&#xA;  [2]: https://i.stack.imgur.com/j4i57.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5773" PostHistoryTypeId="5" PostId="2405" RevisionGUID="1a4e43b8-8057-47fe-b6ec-1829aa2971c7" CreationDate="2016-05-10T07:32:26.140" UserId="2736" Comment="To clearify my question's scope." Text="So I been thinking about this for a while and tried to google for an answer but without any success.&#xD;&#xA;&#xD;&#xA;If all your textures are 8bit LDR images, like JPEGs, couldn't that potentially cause conflicts with exposure control/tone mapping when rendering. That is if you adjust the rendering exposure of your image that should expose detail in the textures that aren't really there, since they been clamped out by the low dynamic range. So wouldn't it make sense to also have the textures as HDR images, saved as .exr, in linear colour space with 16bit half-float to get a good colour representation (32bit &quot;full&quot; float might be overkill?). To have more detailed and correct colour values might also, I figure, have an effect on GI and how colour bleed is calculated?&#xD;&#xA;&#xD;&#xA;Or is it simply not necessary since the end result of the rendering we want is probably going to be similar to the exposure level of the texture when it was photographed any way? And since camera mostly shoot in 12-14bit you would have to take multiple exposures of the texture and do all that extra work to piece them all together to one HDRI. &#xD;&#xA;&#xD;&#xA;**Edit:** *To clarify, I'm mostly interested in this from a photo realistic rendering point of view, with ray trace renderers (like mental ray, V-Ray, Arnold, etc.) with full light simulations and global illumination, rather then for real-time game engines.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="5774" PostHistoryTypeId="2" PostId="2421" RevisionGUID="f24597f2-af8f-4a95-aa48-f6991e1a3e8f" CreationDate="2016-05-10T10:09:35.760" UserId="3328" Text="I am reading [two shot svbrdf capture][1] . I want to understand the data fitting.&#xD;&#xA;&#xD;&#xA;For example, I have my input image 3000x2000 pixels, and I divide it to create my source tiles of 192x192 pixels. The way I understand this paper is, each pixel of each tile will be the svbrdf. Now we have to find the BRDF parameters for each position with the L-M method.&#xD;&#xA;&#xD;&#xA;Then, we get svbrdf parameters for 192x192 pixels.&#xD;&#xA;After the data fitting what did they do to obtain the normal map, specular albedo and diffuse albedo.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://reality.cs.ucl.ac.uk/projects/two-shot-svbrdf/two-shot-svbrdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="5775" PostHistoryTypeId="1" PostId="2421" RevisionGUID="f24597f2-af8f-4a95-aa48-f6991e1a3e8f" CreationDate="2016-05-10T10:09:35.760" UserId="3328" Text="Data fitting SVBRDF with L-M" ContentLicense="CC BY-SA 3.0" />
  <row Id="5776" PostHistoryTypeId="3" PostId="2421" RevisionGUID="f24597f2-af8f-4a95-aa48-f6991e1a3e8f" CreationDate="2016-05-10T10:09:35.760" UserId="3328" Text="|optimisation|brdf|specular|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5777" PostHistoryTypeId="5" PostId="2362" RevisionGUID="edcff89c-6ef8-4fb2-8eb3-10c14b8d0d28" CreationDate="2016-05-10T15:17:40.067" UserId="2712" Comment="added 1133 characters in body" Text="Thanks for the [suggestions]. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;First off it is identified if two line segments intersect or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). &#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;    				glm::i16vec2 &amp;p2,&#xD;&#xA;    				glm::i16vec2 &amp;p3)&#xD;&#xA;    {&#xD;&#xA;       return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;    				 const glm::i16vec2 &amp;pj,&#xD;&#xA;    				 const glm::i16vec2 &amp;pk)&#xD;&#xA;    {&#xD;&#xA;    	if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x))  &amp;&amp;&#xD;&#xA;    	(std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;    		return true;&#xD;&#xA;    	else&#xD;&#xA;    		return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool intersects(const glm::i16vec2 &amp;p1,const glm::i16vec2 &amp;p2,&#xD;&#xA;                    const glm::i16vec2 &amp;p3,const glm::i16vec2 &amp;p4)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    	int d1 = orientation(p1,p2,p3);&#xD;&#xA;    	int d2 = orientation(p1,p2,p4);&#xD;&#xA;    	int d3 = orientation(p3,p4,p1);&#xD;&#xA;    	int d4 = orientation(p3,p4,p2);&#xD;&#xA;    &#xD;&#xA;    	if(((d1 &gt; 0 &amp;&amp; d2 &lt; 0) || (d1 &lt; 0 &amp;&amp; d2 &gt; 0)) &amp;&amp;&#xD;&#xA;    	    ((d3 &gt; 0 &amp;&amp; d4 &lt; 0) || (d3 &lt; 0 &amp;&amp; d4 &gt; 0)))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d1 == 0 &amp;&amp; onSegment(p3,p4,p1))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d2 == 0 &amp;&amp; onSegment(p3,p4,p2))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d3 == 0 &amp;&amp; onSegment(p1,p2,p3))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d4 == 0 &amp;&amp; onSegment(p1,p2,p4))&#xD;&#xA;              return true;&#xD;&#xA;    	else&#xD;&#xA;    		  return false;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	glm::i16vec2 hs(5,1);  // p1&#xD;&#xA;    	glm::i16vec2 he(5,3); // p2&#xD;&#xA;    &#xD;&#xA;    	glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;    	glm::i16vec2 ce(5,3); // p4&#xD;&#xA;&#xD;&#xA;        if(intersects(hs,he,cs,ce))&#xD;&#xA;          std::cout &lt;&lt; &quot;It has intersection&quot; &lt;&lt; std::endl;&#xD;&#xA;        else&#xD;&#xA;          std::cout &lt;&lt; &quot;No intersection&quot; &lt;&lt; std::endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Once the boolean flag mentions that the intersection point is found, then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;    short int getXIntersection(float x1,&#xD;&#xA;                               float y1,&#xD;&#xA;                               float x2,&#xD;&#xA;                               float y2,&#xD;&#xA;                               float yPos)&#xD;&#xA;    {&#xD;&#xA;        float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;        float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;        return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;     &#xD;&#xA;The above function snippet is for the case when one of the line segments is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segments is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity, the code snippet is not written here. I hope you can imagine how it will be? Yet it is included in the following snippet as for some coordinate values I am having wrong output:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    short int getYIntersection(float x1,&#xD;&#xA;                               float y1,&#xD;&#xA;                               float x2,&#xD;&#xA;                               float y2,&#xD;&#xA;                               float xPos)&#xD;&#xA;    {&#xD;&#xA;        float t = (y2 - y1)/(x2 - x1);&#xD;&#xA;&#xD;&#xA;        float yDbl = (static_cast&lt;double&gt;(xPos) - x1) * t + y1;&#xD;&#xA;&#xD;&#xA;        return static_cast&lt;short int&gt;(std::floor(0.5+yDbl));&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;RECENT : Lets a line segment that is parallel to the Y-axis and it has the following coordinates as start and end point.&#xD;&#xA;&#xD;&#xA;hs(3124,-3168)&#xD;&#xA;he(3124,-3094)&#xD;&#xA;&#xD;&#xA;The other arbitrarily oriented line segment has the following coordinates:&#xD;&#xA;&#xD;&#xA;cs(3124,-3168)&#xD;&#xA;ce(3125,-3116)&#xD;&#xA;&#xD;&#xA;Since the line segment parallel to Y-axis has the constant X-value, should not the function getYIntersection() get the correct Y-value . But I am not getting it- instead I am getting -3213 as the Y-intersection value. Is there anything I am missing here ? The Y-value of the intersection must be within both the line segment, unfortunately it is not.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole in this overall algorithm? In practice, I am getting some huge intersection point value that is way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection points must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After several comments and one answer , some adjustments is made within the code. It is found that with overlapping line segments the algorithm return true. It is not intended in my case, all overlapping line segments must not be flagged as intersection. Some hint would be nice. The issue of getting the intersection point is still in the pipeline. I believe that I missed the part that must be done after the initial true/false algorithm - that is to test if the calculated intersectin point lies within both the line segments or not. If it does, only then we eventually have the true intersection otherwise no intersection at all. &#xD;&#xA;&#xD;&#xA;Some feed-back would be great! &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [suggestions]: http://computergraphics.stackexchange.com/questions/2140/intersection-between-line-segments-narrowed-precondition&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5778" PostHistoryTypeId="2" PostId="2422" RevisionGUID="1d3a4808-8bcc-4d5f-80ea-4c540853b0e6" CreationDate="2016-05-10T15:35:53.373" UserId="3330" Text="I am working on a small rendering engine for a personal project and I am having issues with the texture mapping part of it.&#xD;&#xA;&#xD;&#xA;It seems to work for some cases, but not for others. For example, when one of the vertices is behind the camera, the texture is stretched.&#xD;&#xA;&#xD;&#xA;*Seemingly* **Correct case**&#xD;&#xA;[![Seemingly correct case][1]][1]&#xD;&#xA;**Incorrect case**&#xD;&#xA;[![Incorrect case][2]][2]&#xD;&#xA;&#xD;&#xA;I am guessing that it has something to do with the texture mapping not being perspective-correct. I have tried various changes mainly involving the z-distance to the camera, but I could not find any quick fix to my code.&#xD;&#xA;&#xD;&#xA;Here is my code for the perspective projection:&#xD;&#xA;&#xD;&#xA;    public double[] project(double x, double y, double z) {&#xD;&#xA;        double tx = x - camera.x;&#xD;&#xA;        double ty = z - camera.z;&#xD;&#xA;        double tz = y - camera.y;&#xD;&#xA;&#xD;&#xA;        double cx = Math.cos(camera.pitch);&#xD;&#xA;        double cy = Math.cos(camera.yaw);&#xD;&#xA;        double cz = Math.cos(camera.roll);&#xD;&#xA;&#xD;&#xA;        double sx = Math.sin(camera.pitch);&#xD;&#xA;        double sy = Math.sin(camera.yaw);&#xD;&#xA;        double sz = Math.sin(camera.roll);&#xD;&#xA;&#xD;&#xA;        double dx = cy * (sz * ty + cz * tx) - sy * tz;&#xD;&#xA;        double dy = sx * (cy * tz + sy * (sz * ty + cz * tx)) + cx * (cz * ty - sz * tx);&#xD;&#xA;        double dz = cx * (cy * tz + sy * (sz * ty + cz * tx)) - sx * (cz * ty - sz * tx);&#xD;&#xA;&#xD;&#xA;        double ez = 1.0 / Math.tan(FOV / 2.0);&#xD;&#xA;        &#xD;&#xA;        double bx = ez / dz * dx;&#xD;&#xA;        double by = ez / dz * dy;&#xD;&#xA;        &#xD;&#xA;        if (dz &lt; 0.0) {&#xD;&#xA;            bx = -bx;&#xD;&#xA;            by = -by;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        int px = (int) (width + bx * height) / 2;&#xD;&#xA;        int py = (int) (height + by * height) / 2;&#xD;&#xA;&#xD;&#xA;        return new double[] { px, py, dz };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here my code for the texture mapping:&#xD;&#xA;&#xD;&#xA;    public double[] map(double x, double y, double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3) {&#xD;&#xA;        double A = (x0 - x) * (y0 - y2) - (y0 - y) * (x0 - x2);&#xD;&#xA;        double B = ((x0 - x) * (y1 - y3) - (y0 - y) * (x1 - x3) + (x1 - x) * (y0 - y2) - (y1 - y) * (x0 - x2)) / 2.0;&#xD;&#xA;        double C = (x1 - x) * (y1 - y3) - (y1 - y) * (x1 - x3);&#xD;&#xA;&#xD;&#xA;        double det = A - 2.0 * B + C;&#xD;&#xA;&#xD;&#xA;        double u;&#xD;&#xA;        if (det == 0.0) {&#xD;&#xA;            u = A / (A - C);&#xD;&#xA;            if (Double.isNaN(u) || u &lt; 0.0 || u &gt; 1.0)&#xD;&#xA;                return null;&#xD;&#xA;        } else {&#xD;&#xA;            double u1 = ((A - B) + Math.sqrt(B * B - A * C)) / det;&#xD;&#xA;            boolean u1valid = !Double.isNaN(u1) &amp;&amp; u1 &gt;= 0.0 &amp;&amp; 1.0 &gt;= u1;&#xD;&#xA;&#xD;&#xA;            double u2 = ((A - B) - Math.sqrt(B * B - A * C)) / det;&#xD;&#xA;            boolean u2valid = !Double.isNaN(u2) &amp;&amp; u2 &gt;= 0.0 &amp;&amp; 1.0 &gt;= u2;&#xD;&#xA;&#xD;&#xA;            if (u1valid &amp;&amp; u2valid)&#xD;&#xA;                u = u1 &lt; u2 ? u2 : u1;&#xD;&#xA;            else if (u1valid)&#xD;&#xA;                u = u1;&#xD;&#xA;            else if (u2valid)&#xD;&#xA;                u = u2;&#xD;&#xA;            else&#xD;&#xA;                return null;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        double v1 = ((1.0 - u) * (x0 - x) + u * (x1 - x)) / ((1.0 - u) * (x0 - x2) + u * (x1 - x3));&#xD;&#xA;        boolean v1valid = !Double.isNaN(v1) &amp;&amp; v1 &gt;= 0.0 &amp;&amp; 1.0 &gt;= v1;&#xD;&#xA;&#xD;&#xA;        double v2 = ((1.0 - u) * (y0 - y) + u * (y1 - y)) / ((1.0 - u) * (y0 - y2) + u * (y1 - y3));&#xD;&#xA;        boolean v2valid = !Double.isNaN(v2) &amp;&amp; v2 &gt;= 0.0 &amp;&amp; 1.0 &gt;= v2;&#xD;&#xA;&#xD;&#xA;        double v;&#xD;&#xA;        if (v1valid &amp;&amp; v2valid)&#xD;&#xA;            v = v1 &lt; v2 ? v2 : v1;&#xD;&#xA;        else if (v1valid)&#xD;&#xA;            v = v1;&#xD;&#xA;        else if (v2valid)&#xD;&#xA;            v = v2;&#xD;&#xA;        else&#xD;&#xA;            return null;&#xD;&#xA;&#xD;&#xA;        return new double[] { u, v };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here is my quad drawing code:&#xD;&#xA;&#xD;&#xA;    public void renderFace(Screen screen, int x0, int y0, int z0, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {&#xD;&#xA;        boolean render = true;&#xD;&#xA;&#xD;&#xA;        double[] p0 = screen.project(x0, y0, z0);&#xD;&#xA;        int px0 = (int) p0[0], py0 = (int) p0[1];&#xD;&#xA;        render |= p0[2] &gt;= ZCLIP &amp;&amp; px0 &gt;= 0 &amp;&amp; px0 &lt; screen.width &amp;&amp; py0 &gt;= 0 &amp;&amp; py0 &lt; screen.height;&#xD;&#xA;&#xD;&#xA;        double[] p1 = screen.project(x1, y1, z1);&#xD;&#xA;        int px1 = (int) p1[0], py1 = (int) p1[1];&#xD;&#xA;        render |= p1[2] &gt;= ZCLIP &amp;&amp; px1 &gt;= 0 &amp;&amp; px1 &lt; screen.width &amp;&amp; py1 &gt;= 0 &amp;&amp; py1 &lt; screen.height;&#xD;&#xA;&#xD;&#xA;        double[] p2 = screen.project(x2, y2, z2);&#xD;&#xA;        int px2 = (int) p2[0], py2 = (int) p2[1];&#xD;&#xA;        render |= p2[2] &gt;= ZCLIP &amp;&amp; px2 &gt;= 0 &amp;&amp; px2 &lt; screen.width &amp;&amp; py2 &gt;= 0 &amp;&amp; py2 &lt; screen.height;&#xD;&#xA;&#xD;&#xA;        double[] p3 = screen.project(x3, y3, z3);&#xD;&#xA;        int px3 = (int) p3[0], py3 = (int) p3[1];&#xD;&#xA;        render |= p3[2] &gt;= ZCLIP &amp;&amp; px3 &gt;= 0 &amp;&amp; px3 &lt; screen.width &amp;&amp; py3 &gt;= 0 &amp;&amp; py3 &lt; screen.height;&#xD;&#xA;&#xD;&#xA;        if (!render)&#xD;&#xA;            return;&#xD;&#xA;&#xD;&#xA;        int minX = Math.min(Math.min(px0, px1), Math.min(px2, px3));&#xD;&#xA;        if (minX &lt; 0)&#xD;&#xA;            minX = 0;&#xD;&#xA;        if (minX &gt; screen.width)&#xD;&#xA;            minX = screen.width;&#xD;&#xA;&#xD;&#xA;        int minY = Math.min(Math.min(py0, py1), Math.min(py2, py3));&#xD;&#xA;        if (minY &lt; 0)&#xD;&#xA;            minY = 0;&#xD;&#xA;        if (minY &gt; screen.height)&#xD;&#xA;            minY = screen.height;&#xD;&#xA;&#xD;&#xA;        int maxX = Math.max(Math.max(px0, px1), Math.max(px2, px3));&#xD;&#xA;        if (maxX &lt; 0)&#xD;&#xA;            maxX = 0;&#xD;&#xA;        if (maxX &gt; screen.width)&#xD;&#xA;            maxX = screen.width;&#xD;&#xA;&#xD;&#xA;        int maxY = Math.max(Math.max(py0, py1), Math.max(py2, py3));&#xD;&#xA;        if (maxY &lt; 0)&#xD;&#xA;            maxY = 0;&#xD;&#xA;        if (maxY &gt; screen.height)&#xD;&#xA;            maxY = screen.height;&#xD;&#xA;&#xD;&#xA;        if (minX == maxX || minY == maxY)&#xD;&#xA;            return;&#xD;&#xA;        &#xD;&#xA;        for (int py = minY; py &lt; maxY; ++py)&#xD;&#xA;            for (int px = minX; px &lt; maxX; ++px) {&#xD;&#xA;                double[] uv = screen.map(px + 0.5, py + 0.5, px0, py0, px1, py1, px2, py2, px3, py3);&#xD;&#xA;                if (uv == null)&#xD;&#xA;                    continue;&#xD;&#xA;                double u = uv[0], v = uv[1];&#xD;&#xA;&#xD;&#xA;                double pz = (1 - u) * ((1 - v) * p0[2] + v * p2[2]) + u * ((1 - v) * p1[2] + v * p3[2]);&#xD;&#xA;                if (pz &lt; ZCLIP)&#xD;&#xA;                    continue;&#xD;&#xA;&#xD;&#xA;                int texX = 15 - Math.min(15, (int) (16 * u));&#xD;&#xA;                int texY = 15 - Math.min(15, (int) (16 * v));&#xD;&#xA;                screen.setPixel(px, py, pz, Art.WALLS.getPixel(texX, texY) * BRICKS);&#xD;&#xA;            }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Can anyone point out what I am doing wrong? I am not very experienced as this is my first try at implementing a game engine.&#xD;&#xA;&#xD;&#xA;Thank you for any insight.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IJtuU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5M70C.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5779" PostHistoryTypeId="1" PostId="2422" RevisionGUID="1d3a4808-8bcc-4d5f-80ea-4c540853b0e6" CreationDate="2016-05-10T15:35:53.373" UserId="3330" Text="Perspective-Correct Texture Mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="5780" PostHistoryTypeId="3" PostId="2422" RevisionGUID="1d3a4808-8bcc-4d5f-80ea-4c540853b0e6" CreationDate="2016-05-10T15:35:53.373" UserId="3330" Text="|texture|perspective|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5781" PostHistoryTypeId="2" PostId="2423" RevisionGUID="83c889ba-73e1-4db0-9e07-9da94b4dcd54" CreationDate="2016-05-10T18:27:56.747" UserId="1781" Text="In film production, we almost never use 8-bit textures for color/albedo, because of banding, etc. (JPEG is especially problematic since by spec, it's sRGB rather than linear values.) We either use 'half' (16 bit float) or 16-bit unsigned integer values for color/albedo textures.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5782" PostHistoryTypeId="2" PostId="2424" RevisionGUID="67645219-2f38-4557-9395-40c699e7297f" CreationDate="2016-05-11T06:00:33.290" UserId="3339" Text="I'm currently reading some books on radiometry. They mention that radiance is constant along a ray. It doesn't change with distance.&#xD;&#xA;However, I've seen some raytracer and they put the 1/r² factor when they deal with point sources. I don't get why. I didn't find a great explanation on the Internet. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5783" PostHistoryTypeId="1" PostId="2424" RevisionGUID="67645219-2f38-4557-9395-40c699e7297f" CreationDate="2016-05-11T06:00:33.290" UserId="3339" Text="Why does the 1/r² term appear with point sources?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5784" PostHistoryTypeId="3" PostId="2424" RevisionGUID="67645219-2f38-4557-9395-40c699e7297f" CreationDate="2016-05-11T06:00:33.290" UserId="3339" Text="|raytracing|color|brdf|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5785" PostHistoryTypeId="2" PostId="2425" RevisionGUID="487616bc-5a39-4d0c-9e72-75b6cee88eb7" CreationDate="2016-05-11T09:26:05.633" UserId="3331" Text="It is the [inverse square law of light][1] for a pure point light.&#xD;&#xA;&#xD;&#xA;$E = \frac{I}{r^2}$&#xD;&#xA;&#xD;&#xA;Where E is illuminance and I is pointance or power/flux per unit solid angle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://hyperphysics.phy-astr.gsu.edu/hbase/vision/isql.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5786" PostHistoryTypeId="2" PostId="2426" RevisionGUID="0b58bdcc-3f65-4ef6-98b6-e213a61875d8" CreationDate="2016-05-11T09:29:43.657" UserId="2712" Text="The slicing algorithm is done on the STL model and it is made sure that the result must be a series of simple polygons that do not intersect each other. In other words all of those polygons generates closed loops. I need to identify which of those loops are outer and inner loops. there has been some references of tree depth that can be used to identify external and internal loops, without any outline of the algorithm. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It would be great if anyone in the forum can point to more detail references where the tree depth can be utilized to filter out inner and outer contour lines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 3.0" />
  <row Id="5787" PostHistoryTypeId="1" PostId="2426" RevisionGUID="0b58bdcc-3f65-4ef6-98b6-e213a61875d8" CreationDate="2016-05-11T09:29:43.657" UserId="2712" Text="identify different contour cycle after model sliicing" ContentLicense="CC BY-SA 3.0" />
  <row Id="5788" PostHistoryTypeId="3" PostId="2426" RevisionGUID="0b58bdcc-3f65-4ef6-98b6-e213a61875d8" CreationDate="2016-05-11T09:29:43.657" UserId="2712" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5789" PostHistoryTypeId="2" PostId="2427" RevisionGUID="c2cc242c-0ced-4e38-bc41-62a8aadfaeed" CreationDate="2016-05-11T12:14:42.920" UserId="3341" Text="Usually GearVR + SamsungPhone are used both for rendering and displaying but I would like to use it only for displaying when it is plugged to PC. The reason is to get performance similar to Oculus Rift or HTC Vive and not spend money for it. Is it possible?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5790" PostHistoryTypeId="1" PostId="2427" RevisionGUID="c2cc242c-0ced-4e38-bc41-62a8aadfaeed" CreationDate="2016-05-11T12:14:42.920" UserId="3341" Text="Using GPU in PC for GearVR" ContentLicense="CC BY-SA 3.0" />
  <row Id="5791" PostHistoryTypeId="3" PostId="2427" RevisionGUID="c2cc242c-0ced-4e38-bc41-62a8aadfaeed" CreationDate="2016-05-11T12:14:42.920" UserId="3341" Text="|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5792" PostHistoryTypeId="2" PostId="2428" RevisionGUID="5e55158f-62c5-4047-a887-616f32d512a2" CreationDate="2016-05-11T13:48:05.083" UserId="2817" Text="Since you're asking in this Stack Exchange, I assume you intend to build a VR app yourself that utilizes this scenario.&#xD;&#xA;&#xD;&#xA;While it is perfectly possible to utilize PC for rendering and stream the output to a mobile VR headset, it will come at the relatively high cost of increased latency (see e.g. [here][1] for why this is important; the tl;dr is that high latency → nausea). This is because wireless networks have intrinsically higher latency than wired ones, and you need to do the following in a loop:&#xD;&#xA;&#xD;&#xA; 1. Collect head tracking (gyroscope/accelerometer) data from the VR headset.&#xD;&#xA; 2. Send the head tracking data over the network to the PC.&#xD;&#xA; 3. Render a frame on the PC.&#xD;&#xA; 4. Stream the frame from the PC to the VR headset.&#xD;&#xA;&#xD;&#xA;As I mentioned previously, steps 2 and 4 introduce additional latency, which – depending on your specific application and the individual tolerance of the user – may or may not be a deal breaker.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://arstechnica.com/gaming/2013/01/how-fast-does-virtual-reality-have-to-be-to-look-like-actual-reality/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5793" PostHistoryTypeId="2" PostId="2429" RevisionGUID="eee0f206-b648-4cec-b5c9-573de5185a31" CreationDate="2016-05-11T17:49:05.713" UserId="48" Text="The concept of a point source is an approximation. Physically, light sources are extended objects and emit light from every point on their surface; but when you're far enough away (i.e. the distance to the source is large compared to its size) it's useful to approximate it as a point source.&#xD;&#xA;&#xD;&#xA;You can get the $1/r^2$ law out of it is as follows. Imagine a spherical area light with some radius $r_\text{light}$, and you're looking at it from a distance $r$ away. Then, we can approximate the solid angle that it subtends from your point of view as the area of a circle of radius $r_\text{light}/r$ (just using similar triangles). This area will be $\pi (r_\text{light}/r)^2$, so it's proportional to $1/r^2$.&#xD;&#xA;&#xD;&#xA;Note that this approximation becomes exact in the limit $r_\text{light}/r \to 0$, i.e. when the light source is very far away or very small. It breaks down if the source is too large or too close.&#xD;&#xA;&#xD;&#xA;If the source emits a constant radiance from every point on its surface, then when you integrate over solid angle in the rendering equation, you'll get a total irradiance proportional to $1/r^2$. In order to approximate it as a point source in a renderer, we skip the integration and just add an irradiance proportional to $1/r^2$ directly." ContentLicense="CC BY-SA 3.0" />
  <row Id="5794" PostHistoryTypeId="5" PostId="2429" RevisionGUID="f491e879-32a8-4a86-896a-7f2556e233f8" CreationDate="2016-05-11T18:04:08.223" UserId="48" Comment="typo" Text="The concept of a point source is an approximation. Physically, light sources are extended objects and emit light from every point on their surface; but when you're far enough away (i.e. the distance to the source is large compared to its size) it's useful to approximate it as a point source.&#xD;&#xA;&#xD;&#xA;You can get the $1/r^2$ law out of it as follows. Imagine a spherical area light with some radius $r_\text{light}$, and you're looking at it from a distance $r$ away. Then, we can approximate the solid angle that it subtends from your point of view as the area of a circle of radius $r_\text{light}/r$ (just using similar triangles). This area will be $\pi (r_\text{light}/r)^2$, so it's proportional to $1/r^2$.&#xD;&#xA;&#xD;&#xA;Note that this approximation becomes exact in the limit $r_\text{light}/r \to 0$, i.e. when the light source is very far away or very small. It breaks down if the source is too large or too close.&#xD;&#xA;&#xD;&#xA;If the source emits a constant radiance from every point on its surface, then when you integrate over solid angle in the rendering equation, you'll get a total irradiance proportional to $1/r^2$. In order to approximate it as a point source in a renderer, we skip the integration and just add an irradiance proportional to $1/r^2$ directly." ContentLicense="CC BY-SA 3.0" />
  <row Id="5795" PostHistoryTypeId="5" PostId="2426" RevisionGUID="14278710-f7e1-456d-af7e-7d9f25ba3823" CreationDate="2016-05-11T19:23:47.933" UserId="2712" Comment="added 209 characters in body" Text="The slicing algorithm is done on the STL model and it is made sure that the result must be a series of simple polygons that do not intersect each other. In other words all of those polygons generates closed loops. I need to identify which of those loops are outer and inner loops. there has been some references of tree depth that can be used to identify external and internal loops, without any outline of the algorithm. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It would be great if anyone in the forum can point to more detail references where the tree depth can be utilized to filter out inner and outer contour lines.&#xD;&#xA;&#xD;&#xA;The following images will provide more information for you make some suggestion:&#xD;&#xA;&#xD;&#xA;[Depth Tree Structure][1]&#xD;&#xA;&#xD;&#xA;[Partition areas][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://imgur.com/rM661UP&#xD;&#xA;  [2]: http://imgur.com/so8C2Gl" ContentLicense="CC BY-SA 3.0" />
  <row Id="5796" PostHistoryTypeId="5" PostId="2426" RevisionGUID="e683fb31-aeef-4607-9f78-392381bb50a3" CreationDate="2016-05-11T23:38:26.267" UserId="48" Comment="embed images" Text="The slicing algorithm is done on the STL model and it is made sure that the result must be a series of simple polygons that do not intersect each other. In other words all of those polygons generates closed loops. I need to identify which of those loops are outer and inner loops. there has been some references of tree depth that can be used to identify external and internal loops, without any outline of the algorithm. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It would be great if anyone in the forum can point to more detail references where the tree depth can be utilized to filter out inner and outer contour lines.&#xD;&#xA;&#xD;&#xA;The following images will provide more information for you make some suggestion:&#xD;&#xA;&#xD;&#xA;![Partition areas][2]&#xD;&#xA;![Depth Tree Structure][1]&#xD;&#xA;&#xD;&#xA;Thanks &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QTbP4.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/qOCYz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5797" PostHistoryTypeId="5" PostId="2426" RevisionGUID="b5cf4d10-dd14-4fc3-b170-a4f7898a6f4b" CreationDate="2016-05-12T01:21:15.350" UserId="231" Comment="Make images links and minor typos" Text="The slicing algorithm is done on the STL model and it is ensured that the result is a series of simple polygons that do not intersect each other. In other words all of those polygons generate closed loops. I need to identify which of those loops are outer and inner loops. There have been some references suggesting tree depth can be used to identify external and internal loops, without any outline of the algorithm. &#xD;&#xA;&#xD;&#xA;It would be great if anyone can point to more detailed references where the tree depth can be utilized to filter out inner and outer contour lines.&#xD;&#xA;&#xD;&#xA;The following images will provide more information:&#xD;&#xA;&#xD;&#xA;[![Partition areas][2]][2]&#xD;&#xA;[![Depth Tree Structure][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QTbP4.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/qOCYz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5798" PostHistoryTypeId="4" PostId="2426" RevisionGUID="b5cf4d10-dd14-4fc3-b170-a4f7898a6f4b" CreationDate="2016-05-12T01:21:15.350" UserId="231" Comment="Make images links and minor typos" Text="Identify different contour cycle after model slicing" ContentLicense="CC BY-SA 3.0" />
  <row Id="5799" PostHistoryTypeId="2" PostId="2430" RevisionGUID="640149f3-04ea-4970-9968-9371f7343f99" CreationDate="2016-05-12T07:43:31.303" UserId="38" Text="A quickly formulated method, read first one that popped in my brain (not best), could be. Find the closest points on a parametric spiral for each sample (read [A Pixel Is Not A Little Square&lt;sup&gt;3&lt;/sup&gt;](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf)). Then place the samples on a line by placing the pints in one axis by how far they are from your spiral line and the other by what the closest point is.&#xD;&#xA;&#xD;&#xA;[![spiral[1]][1]&#xD;&#xA;&#xD;&#xA;You can then use something like poisson disk sampling to reconstruct the image (maybe the didsk should be longer ovals the further away they are form the center line and less long as you progress further into the spiral).&#xD;&#xA;&#xD;&#xA;Now that i think of the problem a bit more. A simpler approach could be to map the image on mesh, using uv mapping, then unwrap the mesh. A triangular mesh might exhibit some artifacts so using a B-spline interpolation could be better. Several image mesh algorithms exist and you even have these in Photoshop.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m8TYh.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5800" PostHistoryTypeId="5" PostId="2430" RevisionGUID="c6130d9a-b565-480a-a5b6-ddd9b3caddd2" CreationDate="2016-05-12T08:19:17.530" UserId="38" Comment="added 232 characters in body" Text="A quickly formulated method, read first one that popped in my brain (not best), could be. Find the closest points on a parametric spiral for each sample (read [A Pixel Is Not A Little Square&lt;sup&gt;3&lt;/sup&gt;](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf)). Then place the samples on a line by placing the pints in one axis by how far they are from your spiral line and the other by what the closest point is.&#xD;&#xA;&#xD;&#xA;[![spiral[1][1]&#xD;&#xA;&#xD;&#xA;You can then use something like poisson disk sampling to reconstruct the image (maybe the didsk should be longer ovals the further away they are form the center line and less long as you progress further into the spiral)&#xD;&#xA;&#xD;&#xA;Now that I think of the problem a bit more. A simpler approach could be to map the image on mesh, using UV mapping, then unwrap the mesh. A triangular mesh might exhibit some artifacts so using a B-spline interpolation could be better. Several image mesh algorithms exist and you even have these in Photoshop.&#xD;&#xA;&#xD;&#xA;![unwound spiral][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: A proof of concept of unwound spiral with the mesh method. Note i scaled the unwound spirals length to make it fit the site requirements better.&#xD;&#xA;&#xD;&#xA;From initial test in my 3D app of choice seems that a dense enough triangular mesh works fine.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m8TYh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Qc5qt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5801" PostHistoryTypeId="2" PostId="2431" RevisionGUID="b538c23b-bc0c-4a4d-a403-51c5c278c798" CreationDate="2016-05-12T09:58:02.670" UserId="3069" Text="I am trying to implement my own path tracer but before arriving to the question I want to give you a short overview:   &#xD;&#xA;In the implementation of the rendering equation I use some particular technique in order to sample surfaces. For example: when one of my rays hits a diffuse surface, the next ray bouncing from that surface will be calculated using a *Cosine-weighted Random Direction*. This implies that in my rendering equation I have to take into account the PDF that this specific random distribution implies and specifically divide for this PDF in my equation. So far everything is okey.&#xD;&#xA;&#xD;&#xA;Now, my question. I want to implement a particular technique called &quot;next event estimation&quot; which simply samples the lights. In order to do so, I want to pick a **random point** on my light, which is spherical, by using the following code (C++):&#xD;&#xA;&#xD;&#xA;    Vec3&lt;float&gt; randomPoint() const&#xD;&#xA;	{&#xD;&#xA;		float x;&#xD;&#xA;		float y;&#xD;&#xA;		float z;&#xD;&#xA;&#xD;&#xA;			// random vector in unit sphere&#xD;&#xA;		do&#xD;&#xA;		{&#xD;&#xA;			x = ((float)rand() / (RAND_MAX)) * 2 - 1;			// random coordinates between -1 and 1&#xD;&#xA;			y = ((float)rand() / (RAND_MAX)) * 2 - 1;&#xD;&#xA;			z = ((float)rand() / (RAND_MAX)) * 2 - 1;&#xD;&#xA;		} while (pow(x, 2) + pow(y, 2) + pow(z, 2) &gt; 1);		// simple rejection sampling&#xD;&#xA;&#xD;&#xA;		return centerOfSphere + Vec3&lt;float&gt;(x, y, z) * radius;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;As far as I understand (please correct me if wrong), this implements a **uniformly random sampling**. Also, as far as I have read, this kind of sampling has a PDF = 1 / (b - a) . My question: do I have to use this PDF as well like I do for my *Cosine-weighted Random Distribution* or not, since it is a uniform distribution? if yes, what's the range (b - a) that PDF talks about? Thanks in advance!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5802" PostHistoryTypeId="1" PostId="2431" RevisionGUID="b538c23b-bc0c-4a4d-a403-51c5c278c798" CreationDate="2016-05-12T09:58:02.670" UserId="3069" Text="Role of PDF of Uniform Random Sampling in a path tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="5803" PostHistoryTypeId="3" PostId="2431" RevisionGUID="b538c23b-bc0c-4a4d-a403-51c5c278c798" CreationDate="2016-05-12T09:58:02.670" UserId="3069" Text="|rendering|c++|pathtracing|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5804" PostHistoryTypeId="2" PostId="2432" RevisionGUID="478b95e7-f494-4f77-a5d1-6fc24ea5ab9b" CreationDate="2016-05-12T11:33:27.583" UserId="3075" Text="Say the point light is at $P_L$, the shading is happening at $P_S$&#xD;&#xA;&#xD;&#xA;It's true that the radiance is constant along a shadow ray $P_L \rightarrow P_S$, but that's not the key property for solving the rendering equation at $P_S$. &#xD;&#xA;&#xD;&#xA;The rendering equation, somewhat simplified, is: $L_o(\omega_o) = L_e(\omega_o) + \int_{\Omega} \, f_r(\omega_i, \omega_o)\, L_i(\omega_i)\, (n \cdot \omega_i) \, d \omega_o $&#xD;&#xA;&#xD;&#xA;While $L_o$ is expressed in radiance, you are actually integrating the _irradiance_ $L_i$ of the incoming light at $P_S$, which is expressed in $W/m^2$. The incoming radiance -- call it $\hat{L}_i$ -- is in $W m^{-2} sr^{-1}$ and since area of 1 $sr$ increases quadratically with distance from $P_L$, the difference between $\hat{L}_i$ and $L_i$ is a $1/r^2$ term." ContentLicense="CC BY-SA 3.0" />
  <row Id="5805" PostHistoryTypeId="5" PostId="2430" RevisionGUID="dad0cb2b-5d80-4857-b8ae-b2c50253200d" CreationDate="2016-05-12T11:40:11.467" UserId="38" Comment="deleted 1 character in body" Text="A quickly formulated method, read first one that popped in my brain (not best), could be. Find the closest points on a parametric spiral for each sample (read [A Pixel Is Not A Little Square&lt;sup&gt;3&lt;/sup&gt;](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf)). Then place the samples on a line by placing the pints in one axis by how far they are from your spiral line and the other by what the closest point is.&#xD;&#xA;&#xD;&#xA;![spiral[1][1]&#xD;&#xA;&#xD;&#xA;You can then use something like poisson disk sampling to reconstruct the image (maybe the didsk should be longer ovals the further away they are form the center line and less long as you progress further into the spiral)&#xD;&#xA;&#xD;&#xA;Now that I think of the problem a bit more. A simpler approach could be to map the image on mesh, using UV mapping, then unwrap the mesh. A triangular mesh might exhibit some artifacts so using a B-spline interpolation could be better. Several image mesh algorithms exist and you even have these in Photoshop.&#xD;&#xA;&#xD;&#xA;![unwound spiral][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: A proof of concept of unwound spiral with the mesh method. Note i scaled the unwound spirals length to make it fit the site requirements better.&#xD;&#xA;&#xD;&#xA;From initial test in my 3D app of choice seems that a dense enough triangular mesh works fine.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m8TYh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Qc5qt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5806" PostHistoryTypeId="5" PostId="2430" RevisionGUID="4f5d3414-c67d-4d1a-904a-c96e56bcf466" CreationDate="2016-05-12T14:40:56.900" UserId="38" Comment="added 1 character in body" Text="A quickly formulated method, read first one that popped in my brain (not best), could be. Find the closest points on a parametric spiral for each sample (read [A Pixel Is Not A Little Square&lt;sup&gt;3&lt;/sup&gt;](http://alvyray.com/Memos/CG/Microsoft/6_pixel.pdf)). Then place the samples on a line by placing the pints in one axis by how far they are from your spiral line and the other by what the closest point is.&#xD;&#xA;&#xD;&#xA;![spiral[1][1]&#xD;&#xA;&#xD;&#xA;You can then use something like poisson disk sampling to reconstruct the image (maybe the didsk should be longer ovals the further away they are form the center line and less long as you progress further into the spiral).&#xD;&#xA;&#xD;&#xA;Now that I think of the problem a bit more. A simpler approach could be to map the image on mesh, using UV mapping, then unwrap the mesh. A triangular mesh might exhibit some artifacts so using a B-spline interpolation could be better. Several image mesh algorithms exist and you even have these in Photoshop.&#xD;&#xA;&#xD;&#xA;![unwound spiral][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: A proof of concept of unwound spiral with the mesh method. Note i scaled the unwound spirals length to make it fit the site requirements better.&#xD;&#xA;&#xD;&#xA;From initial test in my 3D app of choice seems that a dense enough triangular mesh works fine.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m8TYh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Qc5qt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5807" PostHistoryTypeId="2" PostId="2433" RevisionGUID="eea84bc4-4dfe-4005-a6d3-7191d7633f2d" CreationDate="2016-05-12T18:36:13.147" UserId="38" Text="Polygon offsetting is certainly possible to do yourself. It is not nearly as involved as Bezier or B-spline offsetting is. First you want to decide how to deal with:&#xD;&#xA;&#xD;&#xA;1. Areas with no info, in essence how to deal with the joins. Do you just extend the line to the common intersection (miter join) or do you just connect the endpoints (bevel). You could also use round, parabolic or other join styles if you wish. Options here are unlimited. &#xD;&#xA;&#xD;&#xA;  For purposes of this discussion I will assume you will want a miter or bevel join.&#xD;&#xA;&#xD;&#xA;2. How do you want to deal with sidedness. Is a open curves offset closed or just on the other side. Other than that the convention is usually in 2D that outside is on the clockwise side of the path&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So lets look at what happens when 2 straight lines join and they are offset.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: situation in 2D&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;For a beveled corner join vector from any point to its offset is magnitude of $a$ direction of segment rotated counterclockwise times length of offset. Or in case of the picture in mathematical notation&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA; A' = A + a\bigg(\big|B-A\big|   \begin{bmatrix}&#xD;&#xA;    0 &amp; 1\\&#xD;&#xA;    -1 &amp; 0 &#xD;&#xA;  \end{bmatrix}\bigg)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where a is the amount of offset. This assumes lines go from $A$ to $B$ to $C$. Connecting segments must be processed on both sides separately. The same formula can be used for all the points. Then just connect $B'^1$ to $B'^2$ with a line. In case your matrix illiterate the matrix says swap x and y coordinate and invert the x value.&#xD;&#xA;&#xD;&#xA;For a miter join the following applies:&#xD;&#xA;&#xD;&#xA;[![sss][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Situation of miter.&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA; B^{B-B'^{1}} = a\bigg(\big|B-A\big| \begin{bmatrix}&#xD;&#xA;    0 &amp; 1\\&#xD;&#xA;    -1 &amp; 0 &#xD;&#xA;  \end{bmatrix}\bigg)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;B' = B+\dfrac{ B^{B-B'^{1}}}{B^{B-B'^{1}}  \cdot (|B-A|-|C-B|)}&#xD;&#xA;$$&#xD;&#xA; &#xD;&#xA;The above can be heavily simplified ill leave that to the reader.&#xD;&#xA;&#xD;&#xA;Now the reason to use a library is that when the curves start to self intersect it gets a bit tedious to manage this. So just find a library that does this for you you'll save a lot of time.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jagc9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/r6eG1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5808" PostHistoryTypeId="2" PostId="2434" RevisionGUID="dfc0d7e1-d5ba-4366-8788-4fef6b39a830" CreationDate="2016-05-12T21:13:17.540" UserId="2308" Text="I am making a 2d game in opengl es 2.0&#xA;&#xA;Inside are tons of rectangles defined by 4 points and one 4 component color. &#xA;&#xA;I am using vertex buffer objects, and I have heard that it is efficent to interlace the data. &#xA;&#xA;So like traditionally you would do&#xA;&#xA;    Corner.x&#xA;    Corner.y&#xA;    Corner.z&#xA;    Corner.rgba&#xA;    (repeat for each corner) &#xA;&#xA;However in my situations two assumptions can be made that can probably make things faster&#xA;&#xA;    1. All the rectangles z values are 0&#xA;    2. All corners of the rectangle have the same color. &#xA;&#xA;Is it possible, and what would it look like to have a buffer object structured like this. &#xA;&#xA;    Corner.xy&#xA;    Corner.xy&#xA;    Corner.xy&#xA;    Corner.xy&#xA;    Color.rgba? &#xA;&#xA;Is it even possible to have opengl assume that the Z is always 0? Is it possible to reuse the color like to hat? " ContentLicense="CC BY-SA 3.0" />
  <row Id="5809" PostHistoryTypeId="1" PostId="2434" RevisionGUID="dfc0d7e1-d5ba-4366-8788-4fef6b39a830" CreationDate="2016-05-12T21:13:17.540" UserId="2308" Text="Interlacing vertex buffer data with extra efficiency" ContentLicense="CC BY-SA 3.0" />
  <row Id="5810" PostHistoryTypeId="3" PostId="2434" RevisionGUID="dfc0d7e1-d5ba-4366-8788-4fef6b39a830" CreationDate="2016-05-12T21:13:17.540" UserId="2308" Text="|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5814" PostHistoryTypeId="2" PostId="2436" RevisionGUID="646c3672-d382-4974-b327-1f2a5942851c" CreationDate="2016-05-12T21:31:21.500" UserId="310" Text="Firstly, as @trichoplax correctly pointed out, your randomPoint function calculates a point in a cube, then uses rejection sampling to return ***all points that are inside a unit sphere***. In order to return points on a sphere, you would need to change the greater than to an equals. That said, rejection sampling is very inefficient. &#xD;&#xA;&#xD;&#xA;A better way to uniformly sample a sphere, is to sample in spherical space, then transform to cartesian. ie:&#xD;&#xA;&#xD;&#xA;    float phi = PI * randf();&#xD;&#xA;    float theta = 2 * PI * randf();    &#xD;&#xA;    &#xD;&#xA;    float x = radius * std::sinf(phi) * std::sinf(theta);&#xD;&#xA;    float y = radius * std::cosf(phi);&#xD;&#xA;    float z = radius * std::sinf(phi) * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;However, in the case of next event estimation, uniform sampling the whole sphere is inefficient, because a ray can only 'see' half of the sphere at a time. So if we generate a point on the 'back' of the sphere, the sphere will occlude the point, and your calculation will be wasted.&#xD;&#xA;&#xD;&#xA;Instead, you generate samples in a cone, which covers the great circle of the sphere, as viewed from the starting point of the ray.&#xD;&#xA;&#xD;&#xA;    // Sample sphere uniformly inside subtended cone&#xD;&#xA;    float rand1 = randf();&#xD;&#xA;    float rand2 = randf();&#xD;&#xA;&#xD;&#xA;    // Compute theta and phi values for sample in cone&#xD;&#xA;    float distanceSquared = DistanceSquared(rayOrigin, sphereCenter);&#xD;&#xA;    &#xD;&#xA;    // We use geometry to calculate the angle of the cone (aka, the maximum phi can be when we sample)&#xD;&#xA;    // It's easier / cheaper to use geometry to calculate sin/cos phi directly, rather than generating phi and using sin/cos&#xD;&#xA;    float sinPhiMaxSquared = radius * radius / distanceSquared;&#xD;&#xA;    float cosPhiMax = std::sqrt(1.0f - sinPhiMaxSquared);&#xD;&#xA;    float cosPhi = (1.0f - rand1) + rand1 * cosPhiMax;&#xD;&#xA;    float sinPhi = std::sqrt(1.0f - cosPhi * cosPhi);&#xD;&#xA;&#xD;&#xA;    // Phi can be anything in 2 PI&#xD;&#xA;    float theta = 2 * PI * rand2;&#xD;&#xA;&#xD;&#xA;    float x = radius * sinPhi * std::sinf(theta);&#xD;&#xA;    float y = radius * cosPhi;&#xD;&#xA;    float z = radius * sinPhi * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE: x, y, z are in LOCAL coordinate space.**&#xD;&#xA;&#xD;&#xA;So we need to transform to world coordinates:&#xD;&#xA;&#xD;&#xA;    float3 zAxis = normalize(sphereCenter - rayOrigin);&#xD;&#xA;    float3 xAxis;&#xD;&#xA;    if (std::abs(zAxis.x) &gt; std::abs(zAxis.y))&#xD;&#xA;        xAxis = float3(-zAxis.z, 0.0f, zAxis.x) / std::sqrt(zAxis.x * zAxis.x + zAxis.z * zAxis.z);&#xD;&#xA;    else&#xD;&#xA;        xAxis = float3(0.0f, zAxis.z, -zAxis.y) / std::sqrt(zAxis.y * zAxis.y + zAxis.z * zAxis.z);&#xD;&#xA;    yAxis = cross(zAxis, xAxis);&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    float3 samplePoint = x * xAxis + y * yAxis + z * zAxis;&#xD;&#xA;&#xD;&#xA;And the pdf is calculated as follows:&#xD;&#xA;&#xD;&#xA;    float pdf = 1 / (2 * PI * (1 - cosPhiMax));&#xD;&#xA;&#xD;&#xA;The code here is heavily influenced / copied from [PBRT v3][1]. They have a series of classes and functions for sampling from shapes.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;Finally, the pdf. In monte-carlo integration, we need to combine the pdf's of each integration we do. In path tracing, we can integrate over many many things. For example, the general rendering equation integrates the incoming light over the hemisphere, depth of field can be treated as an integration over a focal distance, etc.&#xD;&#xA;&#xD;&#xA;For next event estimation, you explicitly split the rendering equation into two integrands, direct lighting, and indirect lighting.&#xD;&#xA;&#xD;&#xA;Standard rendering equation:&#xD;&#xA;$$ L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} $$&#xD;&#xA;&#xD;&#xA;Next Event Estimation:&#xD;&#xA;$$ L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ + \ \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, direct}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}\ \ + \ \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, indirect}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In simple naive forward path tracing, everything is is treated as indirect light. In next event estimation, we directly calculate the direct lighting and add it to the indirect lighting. And if we hit a light, we ignore the contribution, since we're calculating the direct lighting.&#xD;&#xA;&#xD;&#xA;Since we have two integration, each will have its own pdf. Aka:&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ \ + \ \sum_{k=0}^{\infty } \frac{f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, direct}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | }{pdf_{direct}}\ \ + \ \sum_{k=0}^{\infty } \frac{f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, indirect}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | }{pdf_{indirect}}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/shapes/sphere.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="5817" PostHistoryTypeId="5" PostId="2436" RevisionGUID="bfecf447-ca9f-4e2e-85ba-c8353a343572" CreationDate="2016-05-12T21:41:13.140" UserId="310" Comment="Minor edits" Text="Firstly, as @trichoplax correctly pointed out, your randomPoint function calculates a point in a cube, then uses rejection sampling to return ***all*** points that are ***inside*** a unit sphere. In order to return points on a sphere, you would need to change the greater than to an equals. That said, rejection sampling is very inefficient. &#xD;&#xA;&#xD;&#xA;A better way to uniformly sample a sphere, is to sample in spherical space, then transform to cartesian. ie:&#xD;&#xA;&#xD;&#xA;    float phi = PI * randf();&#xD;&#xA;    float theta = 2 * PI * randf();    &#xD;&#xA;    &#xD;&#xA;    float x = radius * std::sinf(phi) * std::sinf(theta);&#xD;&#xA;    float y = radius * std::cosf(phi);&#xD;&#xA;    float z = radius * std::sinf(phi) * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;However, in the case of next event estimation, uniform sampling the whole sphere is inefficient, because a ray can only 'see' half of the sphere at a time. So if we generate a point on the 'back' of the sphere, the sphere will occlude the point, and your calculation will be wasted.&#xD;&#xA;&#xD;&#xA;Instead, you generate samples in a cone, which covers the great circle of the sphere, as viewed from the starting point of the ray.&#xD;&#xA;&#xD;&#xA;    // Sample sphere uniformly inside subtended cone&#xD;&#xA;    float rand1 = randf();&#xD;&#xA;    float rand2 = randf();&#xD;&#xA;&#xD;&#xA;    // Compute theta and phi values for sample in cone&#xD;&#xA;    float distanceSquared = DistanceSquared(rayOrigin, sphereCenter);&#xD;&#xA;    &#xD;&#xA;    // We use geometry to calculate the angle of the cone (aka, the maximum phi can be when we sample)&#xD;&#xA;    // It's easier / cheaper to use geometry to calculate sin/cos phi directly, rather than generating phi and using sin/cos&#xD;&#xA;    float sinPhiMaxSquared = radius * radius / distanceSquared;&#xD;&#xA;    float cosPhiMax = std::sqrt(1.0f - sinPhiMaxSquared);&#xD;&#xA;    float cosPhi = (1.0f - rand1) + rand1 * cosPhiMax;&#xD;&#xA;    float sinPhi = std::sqrt(1.0f - cosPhi * cosPhi);&#xD;&#xA;&#xD;&#xA;    // Phi can be anything in 2 PI&#xD;&#xA;    float theta = 2 * PI * rand2;&#xD;&#xA;&#xD;&#xA;    float x = radius * sinPhi * std::sinf(theta);&#xD;&#xA;    float y = radius * cosPhi;&#xD;&#xA;    float z = radius * sinPhi * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE: x, y, z are in LOCAL coordinate space.**&#xD;&#xA;&#xD;&#xA;So we need to transform to world coordinates:&#xD;&#xA;&#xD;&#xA;    float3 zAxis = normalize(sphereCenter - rayOrigin);&#xD;&#xA;    float3 xAxis;&#xD;&#xA;    if (std::abs(zAxis.x) &gt; std::abs(zAxis.y))&#xD;&#xA;        xAxis = float3(-zAxis.z, 0.0f, zAxis.x) / std::sqrt(zAxis.x * zAxis.x + zAxis.z * zAxis.z);&#xD;&#xA;    else&#xD;&#xA;        xAxis = float3(0.0f, zAxis.z, -zAxis.y) / std::sqrt(zAxis.y * zAxis.y + zAxis.z * zAxis.z);&#xD;&#xA;    yAxis = cross(zAxis, xAxis);&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    float3 samplePoint = x * xAxis + y * yAxis + z * zAxis;&#xD;&#xA;&#xD;&#xA;And the pdf is calculated as follows:&#xD;&#xA;&#xD;&#xA;    float pdf = 1 / (2 * PI * (1 - cosPhiMax));&#xD;&#xA;&#xD;&#xA;The code here is heavily influenced / copied from [PBRT v3][1]. They have a series of classes and functions for sampling from shapes.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;Finally, the pdf. In monte-carlo integration, we need to combine the pdf's of each integration we do. In path tracing, we can integrate over many many things. For example, the general rendering equation integrates the incoming light over the hemisphere, depth of field can be treated as an integration over a focal distance, etc.&#xD;&#xA;&#xD;&#xA;For next event estimation, you explicitly split the rendering equation into two integrands, direct lighting, and indirect lighting.&#xD;&#xA;&#xD;&#xA;Standard rendering equation:&#xD;&#xA;$$ L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} $$&#xD;&#xA;&#xD;&#xA;Next Event Estimation:&#xD;&#xA;$$ L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ + \ \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, direct}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}\ \ + \ \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, indirect}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In simple naive forward path tracing, everything is is treated as indirect light. In next event estimation, we directly calculate the direct lighting and add it to the indirect lighting. And if we hit a light, we ignore the contribution, since we're calculating the direct lighting.&#xD;&#xA;&#xD;&#xA;Since we have two integrations, each will have its own pdf. Aka:&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ \ + \ \sum_{k=0}^{\infty } \frac{f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, direct}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | }{pdf_{direct}}\ \ + \ \sum_{k=0}^{\infty } \frac{f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, indirect}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | }{pdf_{indirect}}$$&#xD;&#xA;&#xD;&#xA;If you want to see how this is implemented, you can check out my implementation [here][2]. Note: my light sampling is a bit more complicated, since it does multiple importance sampling. But it can be as simple as:&#xD;&#xA;&#xD;&#xA;    float3 Renderer::EstimateDirect(Light *light, UniformSampler *sampler, float3a &amp;surfacePos, float3a &amp;surfaceNormal, float3a &amp;wo, Material *material) const {&#xD;&#xA;        float pdf;&#xD;&#xA;        float3 wi;&#xD;&#xA;        &#xD;&#xA;        // Sample a point on the light and get the pdf&#xD;&#xA;        float3 Li = light-&gt;SampleLi(sampler, m_scene, surfacePos, surfaceNormal, &amp;wi, &amp;pdf);&#xD;&#xA;&#xD;&#xA;        // Calculate the brdf value&#xD;&#xA;        float f = material-&gt;Eval(wi, wo, surfaceNormal);&#xD;&#xA;        return f * Li * / pdf;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/shapes/sphere.cpp&#xD;&#xA;  [2]: https://github.com/RichieSams/lantern/blob/master/source/renderer/renderer.cpp#L92" ContentLicense="CC BY-SA 3.0" />
  <row Id="5818" PostHistoryTypeId="5" PostId="2426" RevisionGUID="9210af3e-dd38-457c-bcdd-78b73618449e" CreationDate="2016-05-12T22:42:47.093" UserId="2712" Comment="added 718 characters in body" Text="The slicing algorithm is done on the STL model and it is ensured that the result is a series of simple polygons that do not intersect each other. In other words all of those polygons generate closed loops. I need to identify which of those loops are outer and inner loops. There have been some references suggesting tree depth can be used to identify external and internal loops, without any outline of the algorithm. &#xD;&#xA;&#xD;&#xA;It would be great if anyone can point to more detailed references where the tree depth can be utilized to filter out inner and outer contour lines.&#xD;&#xA;&#xD;&#xA;The following images will provide more information:&#xD;&#xA;&#xD;&#xA;[![Partition areas][2]][2]&#xD;&#xA;[![Depth Tree Structure][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QTbP4.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/qOCYz.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;According to the article that I am following - a , b , e, f, and j are outer loops, while the rest are inner loops. &#xD;&#xA;&#xD;&#xA;In the current situation , I am identifying the inner and outer loops while doing the scanline over each layer after the slicing operation. But I want to identify the inner and outer loops ahead of the scanline operation, so that I can create inner/outer offset for the identified loops and then run the scanline to generate the fill pattern.&#xD;&#xA;&#xD;&#xA;The article that I am following is titled - &quot;Equidistant path generation for improving scanning efficiency in layered manufacturing&quot;. I googled up and I am afraid that it is not public. I downloaded the particle through the university database." ContentLicense="CC BY-SA 3.0" />
  <row Id="5819" PostHistoryTypeId="5" PostId="2426" RevisionGUID="49a8beec-3917-4dd6-abb5-fc569e291ebf" CreationDate="2016-05-13T00:59:24.057" UserId="231" Comment="Minor typo" Text="The slicing algorithm is done on the STL model and it is ensured that the result is a series of simple polygons that do not intersect each other. In other words all of those polygons generate closed loops. I need to identify which of those loops are outer and inner loops. There have been some references suggesting tree depth can be used to identify external and internal loops, without any outline of the algorithm. &#xD;&#xA;&#xD;&#xA;It would be great if anyone can point to more detailed references where the tree depth can be utilized to filter out inner and outer contour lines.&#xD;&#xA;&#xD;&#xA;The following images will provide more information:&#xD;&#xA;&#xD;&#xA;[![Partition areas][2]][2]&#xD;&#xA;[![Depth Tree Structure][1]][1]&#xD;&#xA;&#xD;&#xA;According to the article that I am following - a, b, e, f, and j are outer loops, while the rest are inner loops. &#xD;&#xA;&#xD;&#xA;In the current situation, I am identifying the inner and outer loops while doing the scanline over each layer after the slicing operation. But I want to identify the inner and outer loops ahead of the scanline operation, so that I can create inner/outer offset for the identified loops and then run the scanline to generate the fill pattern.&#xD;&#xA;&#xD;&#xA;The article that I am following is titled - &quot;Equidistant path generation for improving scanning efficiency in layered manufacturing&quot;. I googled up and I am afraid that it is not public. I downloaded the article through the university database.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QTbP4.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/qOCYz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5820" PostHistoryTypeId="5" PostId="2436" RevisionGUID="e4c93bd3-a5ab-4d64-ad5e-0f0daefdfe49" CreationDate="2016-05-13T02:36:03.227" UserId="310" Comment="Corrected the calculation for uniform sampling of a sphere and added an explaination" Text="Firstly, as @trichoplax correctly pointed out, your randomPoint function calculates a point in a cube, then uses rejection sampling to return ***all*** points that are ***inside*** a unit sphere. In order to return points on a sphere, you would need to change the greater than to an equals. That said, rejection sampling is very inefficient. &#xD;&#xA;&#xD;&#xA;A better way to sample a sphere, is to sample in spherical space, then transform to cartesian. ie:&#xD;&#xA;&#xD;&#xA;    float phi = PI * randf();&#xD;&#xA;    float theta = 2 * PI * randf();    &#xD;&#xA;    &#xD;&#xA;    float x = radius * std::sinf(phi) * std::sinf(theta);&#xD;&#xA;    float y = radius * std::cosf(phi);&#xD;&#xA;    float z = radius * std::sinf(phi) * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;However, this is not uniform, and will cause samples to clump at the poles. To prevent this, we transform phi:&#xD;&#xA;&#xD;&#xA;    float phi = std::acosf(2.0f * randf() - 1.0f);&#xD;&#xA;    float theta = 2 * PI * randf();    &#xD;&#xA;    &#xD;&#xA;We can use some trig identities to make it a bit more efficient to calculate with the computer:&#xD;&#xA;$$\begin{align*}&#xD;&#xA;\sin(\cos^{-1}(x)) \equiv&amp; \ \sqrt{1 - x^2}\\&#xD;&#xA;\cos(\cos^{-1}(x)) \equiv&amp; \ x\\&#xD;&#xA;\\&#xD;&#xA;\phi =&amp; \ \cos^{-1}(2\xi - 1)\\&#xD;&#xA;\sin(\phi) =&amp; \ sin(\cos^{-1}(2 \xi - 1))\\&#xD;&#xA;=&amp; \ \sqrt{1 - (2 \xi - 1)^2}\\&#xD;&#xA;\cos(\phi) =&amp; \ 2 \xi - 1&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;So the full change is:&#xD;&#xA;&#xD;&#xA;    float cosPhi = 2.0f * randf() - 1.0f;&#xD;&#xA;    float sinPhi = std::sqrt(1.0f - cosPhi * cosPhi);&#xD;&#xA;    float theta = 2 * PI * randf();    &#xD;&#xA;    &#xD;&#xA;    float x = radius * sinPhi * std::sinf(theta);&#xD;&#xA;    float y = radius * cosPhi;&#xD;&#xA;    float z = radius * sinPhi * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;However, in the case of next event estimation, uniform sampling the whole sphere is inefficient, because a ray can only 'see' half of the sphere at a time. So if we generate a point on the 'back' of the sphere, the sphere will occlude the point, and your calculation will be wasted.&#xD;&#xA;&#xD;&#xA;Instead, you generate samples in a cone, which covers the great circle of the sphere, as viewed from the starting point of the ray.&#xD;&#xA;&#xD;&#xA;    // Sample sphere uniformly inside subtended cone&#xD;&#xA;    float rand1 = randf();&#xD;&#xA;    float rand2 = randf();&#xD;&#xA;&#xD;&#xA;    // Compute theta and phi values for sample in cone&#xD;&#xA;    float distanceSquared = DistanceSquared(rayOrigin, sphereCenter);&#xD;&#xA;    &#xD;&#xA;    // We use geometry to calculate the angle of the cone (aka, the maximum phi can be when we sample)&#xD;&#xA;    // It's easier / cheaper to use geometry to calculate sin/cos phi directly, rather than generating phi and using sin/cos&#xD;&#xA;    float sinPhiMaxSquared = radius * radius / distanceSquared;&#xD;&#xA;    float cosPhiMax = std::sqrt(1.0f - sinPhiMaxSquared);&#xD;&#xA;    float cosPhi = (1.0f - rand1) + rand1 * cosPhiMax;&#xD;&#xA;    float sinPhi = std::sqrt(1.0f - cosPhi * cosPhi);&#xD;&#xA;&#xD;&#xA;    // Phi can be anything in 2 PI&#xD;&#xA;    float theta = 2 * PI * rand2;&#xD;&#xA;&#xD;&#xA;    float x = radius * sinPhi * std::sinf(theta);&#xD;&#xA;    float y = radius * cosPhi;&#xD;&#xA;    float z = radius * sinPhi * std::cosf(theta);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE: x, y, z are in LOCAL coordinate space.**&#xD;&#xA;&#xD;&#xA;So we need to transform to world coordinates:&#xD;&#xA;&#xD;&#xA;    float3 zAxis = normalize(sphereCenter - rayOrigin);&#xD;&#xA;    float3 xAxis;&#xD;&#xA;    if (std::abs(zAxis.x) &gt; std::abs(zAxis.y))&#xD;&#xA;        xAxis = float3(-zAxis.z, 0.0f, zAxis.x) / std::sqrt(zAxis.x * zAxis.x + zAxis.z * zAxis.z);&#xD;&#xA;    else&#xD;&#xA;        xAxis = float3(0.0f, zAxis.z, -zAxis.y) / std::sqrt(zAxis.y * zAxis.y + zAxis.z * zAxis.z);&#xD;&#xA;    yAxis = cross(zAxis, xAxis);&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    float3 samplePoint = x * xAxis + y * yAxis + z * zAxis;&#xD;&#xA;&#xD;&#xA;And the pdf is calculated as follows:&#xD;&#xA;&#xD;&#xA;    float pdf = 1 / (2 * PI * (1 - cosPhiMax));&#xD;&#xA;&#xD;&#xA;The code here is heavily influenced / copied from [PBRT v3][1]. They have a series of classes and functions for sampling from shapes.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;Finally, the pdf. In monte-carlo integration, we need to combine the pdf's of each integration we do. In path tracing, we can integrate over many many things. For example, the general rendering equation integrates the incoming light over the hemisphere, depth of field can be treated as an integration over a focal distance, etc.&#xD;&#xA;&#xD;&#xA;For next event estimation, you explicitly split the rendering equation into two integrands, direct lighting, and indirect lighting.&#xD;&#xA;&#xD;&#xA;Standard rendering equation:&#xD;&#xA;$$ L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} $$&#xD;&#xA;&#xD;&#xA;Next Event Estimation:&#xD;&#xA;$$ L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ + \ \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, direct}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}\ \ + \ \int_{\Omega} f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, indirect}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In simple naive forward path tracing, everything is is treated as indirect light. In next event estimation, we directly calculate the direct lighting and add it to the indirect lighting. And if we hit a light, we ignore the contribution, since we're calculating the direct lighting.&#xD;&#xA;&#xD;&#xA;Since we have two integrations, each will have its own pdf. Aka:&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) \ \ + \ \sum_{k=0}^{\infty } \frac{f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, direct}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | }{pdf_{direct}}\ \ + \ \sum_{k=0}^{\infty } \frac{f(p, \omega_{\text{o}}, \omega_{\text{i}}) L_{\text{i, indirect}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | }{pdf_{indirect}}$$&#xD;&#xA;&#xD;&#xA;If you want to see how this is implemented, you can check out my implementation [here][2]. Note: my light sampling is a bit more complicated, since it does multiple importance sampling. But it can be as simple as:&#xD;&#xA;&#xD;&#xA;    float3 Renderer::EstimateDirect(Light *light, UniformSampler *sampler, float3a &amp;surfacePos, float3a &amp;surfaceNormal, float3a &amp;wo, Material *material) const {&#xD;&#xA;        float pdf;&#xD;&#xA;        float3 wi;&#xD;&#xA;        &#xD;&#xA;        // Sample a point on the light and get the pdf&#xD;&#xA;        float3 Li = light-&gt;SampleLi(sampler, m_scene, surfacePos, surfaceNormal, &amp;wi, &amp;pdf);&#xD;&#xA;&#xD;&#xA;        // Calculate the brdf value&#xD;&#xA;        float f = material-&gt;Eval(wi, wo, surfaceNormal);&#xD;&#xA;        return f * Li * / pdf;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/shapes/sphere.cpp&#xD;&#xA;  [2]: https://github.com/RichieSams/lantern/blob/master/source/renderer/renderer.cpp#L92" ContentLicense="CC BY-SA 3.0" />
  <row Id="5823" PostHistoryTypeId="5" PostId="2428" RevisionGUID="5b8edd76-d940-4284-8c72-775fcab7959b" CreationDate="2016-05-13T07:10:30.100" UserId="2817" Comment="reworded" Text="Since you're asking in this Stack Exchange, I assume you intend to build a VR app yourself that utilizes this scenario.&#xD;&#xA;&#xD;&#xA;While it is perfectly possible to utilize PC for rendering and stream the output to a mobile VR headset, it will come at the relatively high cost of increased latency (see e.g. [here][1] for why this is important; the tl;dr is that high latency → nausea). This is because wireless networks have intrinsically higher latency than wired ones, and you need to do the following in a loop:&#xD;&#xA;&#xD;&#xA; 1. Collect head tracking (gyroscope/accelerometer) data from the VR headset.&#xD;&#xA; 2. Send the head tracking data over the network to the PC.&#xD;&#xA; 3. Render a frame on the PC.&#xD;&#xA; 4. Stream the frame from the PC to the VR headset. This involves the following substeps:&#xD;&#xA;  1. Encode video and audio on the PC.&#xD;&#xA;  2. Transmit the encoded media frame to the VR headset over the network.&#xD;&#xA;  3. Decode video and audio on the VR headset.&#xD;&#xA;&#xD;&#xA;As I mentioned previously, steps 2 and 4 introduce additional latency (probably from several to a dozen milliseconds, from stream encoding/decoding and network transmission), which – depending on your specific application and the individual tolerance of the user – may or may not be a deal breaker.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://arstechnica.com/gaming/2013/01/how-fast-does-virtual-reality-have-to-be-to-look-like-actual-reality/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5827" PostHistoryTypeId="2" PostId="2438" RevisionGUID="21d6b9a0-e14b-4cbe-a938-fd3d5fabb4f2" CreationDate="2016-05-13T09:27:56.793" UserId="137" Text="&gt; Is it even possible to have opengl assume that the Z is always 0?&#xD;&#xA;&#xD;&#xA;Yes it is. Just set the component count to 2 in `glVertexAttribPointer` and the other 2 components (`z` and `w`) will be auto filled with 0 and 1 resp.&#xD;&#xA;&#xD;&#xA;&gt; Is it possible to reuse the color like to hat? &#xD;&#xA;&#xD;&#xA;No it is not. Opengl (and most other graphics apis) require that each vertex is referenced by only a single index." ContentLicense="CC BY-SA 3.0" />
  <row Id="5828" PostHistoryTypeId="2" PostId="2439" RevisionGUID="49d35bc4-8186-457a-9b2f-b52d14b802a5" CreationDate="2016-05-13T11:34:19.540" UserId="273" Text="With help from the Nvidia Forum and two very helpful and friendly Nvidia employees I found the perfect solution.&#xD;&#xA;&#xD;&#xA;In OptiX there is a so called selector node. This is a special scene-graph node that utilizes a user specified program to select which child a ray should traverse and which not.&#xD;&#xA;&#xD;&#xA;    #include &lt;optix.h&gt;&#xD;&#xA;&#xD;&#xA;    rtDeclareVariable(unsigned int, timestep, , );&#xD;&#xA;&#xD;&#xA;    RT_PROGRAM void animation_selector()&#xD;&#xA;    {&#xD;&#xA;	    rtIntersectChild(timestep);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is a simple version of such a selection program. From the CPP-API side the current timestep will be set and can be used to make the animation. And then when the scene graph is traversed the program just says &quot;Traverse only the child with index 'timestep'&quot;. This does not trigger a recompile or refit and therefore is nearly instant.&#xD;&#xA;&#xD;&#xA;The selector node is simply created in following way:&#xD;&#xA;&#xD;&#xA;    optix::Selector selector = context_-&gt;createSelector();&#xD;&#xA;&#xD;&#xA;	std::string path_to_ptx = VRTPtxFinder::GetPtxPath(&quot;VistaRayTracing_generated_animation_selector.cu.ptx&quot;);&#xD;&#xA;&#xD;&#xA;	optix::Program selection_program = context_-&gt;createProgramFromPTXFile(path_to_ptx, &quot;animation_selector&quot;);&#xD;&#xA;	selector[&quot;timestep&quot;]-&gt;setUint(0u);&#xD;&#xA;	selector-&gt;setVisitProgram(selection_program);&#xD;&#xA;&#xD;&#xA;    for(auto group : groups)&#xD;&#xA;    {&#xD;&#xA;      selector-&gt;addChild(group);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The only cost is one additional method call for each traversal and thereby also a slightly bigger stack which caused me some problems with a stack overflow so when using this, keep an eye on the stack size." ContentLicense="CC BY-SA 3.0" />
  <row Id="5829" PostHistoryTypeId="2" PostId="2440" RevisionGUID="062ec3bb-40c1-4ab6-8b84-9b03fb773689" CreationDate="2016-05-13T11:57:41.403" UserId="38" Text="Take a random vertex on your loop, shoot a ray trough all the other loops. For loops you crossed a odd number of times your inside for loops you crossed a even number of times your outside.&#xD;&#xA;&#xD;&#xA;The loops that are outside of all others is in the root of your tree. Then find loops that are inside that, but not inside some other. Then find next level and next level and so on. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Arranging in tree by shooting rays&#xD;&#xA;&#xD;&#xA;You can optimize this by using bounding boxes/ bsp trees for the test areas. But for a small number of areas that might be overkill. just sorting them left to right top to bottom should suffice. You can use the same algorithms as your scan line operators.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the topology is somewhat stable across levels of slices so you can use that to your benefit. Just follow the 3D surface.&#xD;&#xA;&#xD;&#xA;Or you could do the offset in 3D on the polygons so you do not need this info.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eY5kH.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="5830" PostHistoryTypeId="5" PostId="2440" RevisionGUID="aed2007e-703e-4f18-b96d-cef817a21674" CreationDate="2016-05-13T12:03:08.070" UserId="38" Comment="added 314 characters in body" Text="Take a random vertex on your loop, shoot a ray trough all the other loops. For loops you crossed a odd number of times your inside for loops you crossed a even number of times your outside.&#xD;&#xA;&#xD;&#xA;The loops that are outside of all others is in the root of your tree. Then find loops that are inside that, but not inside some other. Then find next level and next level and so on. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Animation of arranging in tree by shooting rays&#xD;&#xA;&#xD;&#xA;You can optimize this by using bounding boxes/ bsp trees for the test areas. But for a small number of areas that might be overkill. just sorting them left to right top to bottom should suffice. You can use the same algorithms as your scan line operators.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the topology is somewhat stable across levels of slices so you can use that to your benefit. Just follow the 3D surface.&#xD;&#xA;&#xD;&#xA;Or you could do the offset in 3D on the polygons so you do not need this info. Also if you just need the winding for knowing which way to offset rule you can derive it from the 3d model itself, each vertex has a normal so project the normal for one triangle in each loop with your slicing algorithm per loop. That then gives you the direction of loops outside which is inside for nearly free. You wouldn't get the tree but then again you might not need it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eY5kH.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="5831" PostHistoryTypeId="5" PostId="2440" RevisionGUID="ccb5f77b-473f-425c-94e9-d32df278af8c" CreationDate="2016-05-13T12:11:09.990" UserId="38" Comment="added 107 characters in body" Text="Take a random vertex on your loop, shoot a ray trough all the other loops. For loops you crossed a odd number of times your inside for loops you crossed a even number of times your outside.&#xD;&#xA;&#xD;&#xA;The loops that are outside of all others is in the root of your tree. Then find loops that are inside that, but not inside some other. Then find next level and next level and so on. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Animation of arranging in tree by shooting rays&#xD;&#xA;&#xD;&#xA;You can optimize this by using bounding boxes/ bsp trees for the test areas. But for a small number of areas that might be overkill. just sorting them left to right top to bottom should suffice. You can use the same algorithms as your scan line operators.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![offset][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: And now you can offset the shape. But you need to recheck that there is no intersection left after this.&#xD;&#xA;&#xD;&#xA;Now the topology is somewhat stable across levels of slices so you can use that to your benefit. Just follow the 3D surface.&#xD;&#xA;&#xD;&#xA;Or you could do the offset in 3D on the polygons so you do not need this info. Also if you just need the winding for knowing which way to offset rule you can derive it from the 3d model itself, each vertex has a normal so project the normal for one triangle in each loop with your slicing algorithm per loop. That then gives you the direction of loops outside which is inside for nearly free. You wouldn't get the tree but then again you might not need it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eY5kH.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/FGFVR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5833" PostHistoryTypeId="2" PostId="2441" RevisionGUID="5e4258d1-1278-46b0-8fb7-6ec6d789b409" CreationDate="2016-05-13T15:40:05.353" UserId="3294" Text="I have a scalar function defined over the vertices of a surface mesh. I want to compute an approximate (and generalized, I suppose) &quot;gaussian blur/convolution&quot; of this function over the surface.&#xD;&#xA;&#xD;&#xA;I can imagine for each vertex, taking an average of the function at vertices in it's (multi-hop) neighborhood weighted according to the gaussian of their Euclidean distance (in R3) from the current vertex multiplied by the local area they represent. This approximation would be good if the surface isn't too curved at the scale of the gaussian kernel. However it would still be computationally prohibitive.&#xD;&#xA;&#xD;&#xA;Is there a more efficient convolving algorithm, perhaps based on some kind of iterated &quot;flow&quot; or partial exchange through edges of the mesh?&#xD;&#xA;&#xD;&#xA;The mesh can have either triangular or quadrilateral faces - whichever is more convenient in answering this question. The mesh is not regular in the sense that edge length varies within the mesh, otherwise I could have used [MeshDOG][1], as [DoG][2] is what I am aiming to do after this convolution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;cad=rja&amp;uact=8&amp;ved=0ahUKEwjBstDNr9fMAhUMLMAKHXTfCDwQFgggMAA&amp;url=https%3A%2F%2Fhal.inria.fr%2Finria-00440407%2Fdocument&amp;usg=AFQjCNEyYd95Cd9vAccR99zGnvHzbuAVyw&amp;sig2=YL3vM1zt5DUL6odWCw5zUA&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Difference_of_Gaussians" ContentLicense="CC BY-SA 3.0" />
  <row Id="5834" PostHistoryTypeId="1" PostId="2441" RevisionGUID="5e4258d1-1278-46b0-8fb7-6ec6d789b409" CreationDate="2016-05-13T15:40:05.353" UserId="3294" Text="Gaussian blurring a function defined over a surface mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="5835" PostHistoryTypeId="3" PostId="2441" RevisionGUID="5e4258d1-1278-46b0-8fb7-6ec6d789b409" CreationDate="2016-05-13T15:40:05.353" UserId="3294" Text="|mesh|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5839" PostHistoryTypeId="2" PostId="2443" RevisionGUID="0056cc14-5797-477e-a7fb-7456878d797b" CreationDate="2016-05-13T22:34:31.890" UserId="286" Text="While the product sampling methods provides better (perfect) distribution for rays I would say that using MIS (multiple importance sampling) is a method verified in production. Since shadowing information is unknown product sampling doesn't become perfect anyway and it is quite hard to implmenet. Shooting more rays might be worth more! Depends on your situation and ray budgets of course!&#xD;&#xA;&#xD;&#xA;Short description of MIS: In essence you trace both a BSDF-ray (as you would anyway for doing indirect lighting) and an explicit ray towards the EM. MIS give you weights so that you can combine them in a way that removes a lot of the noise. MIS is especially good at choosing &quot;technique&quot; (implicit or explicit sampling) based on the situation that arises. This happens naturally without the user having to make hard choices based on roughness etc.&#xD;&#xA;&#xD;&#xA;Chapter 9 of http://graphics.stanford.edu/papers/veach_thesis/ covers this in detail. Also see https://www.shadertoy.com/view/4sSXWt for a demo of MIS in action with area lights." ContentLicense="CC BY-SA 3.0" />
  <row Id="5843" PostHistoryTypeId="5" PostId="2441" RevisionGUID="5d366cb8-d9dd-4bf2-b5d2-6a5729dc4140" CreationDate="2016-05-13T23:42:17.090" UserId="3294" Comment="Added random walk modelling idea" Text="I have a scalar function defined over the vertices of a surface mesh. I want to compute an approximate (and generalized, I suppose) &quot;Gaussian blur/convolution&quot; of this function over the surface.&#xD;&#xA;&#xD;&#xA;I can imagine for each vertex, taking an average of the function at vertices in it's (multi-hop) neighborhood weighted according to the Gaussian of their Euclidean distance (in R3) from the current vertex multiplied by the local area they represent. This approximation would be good if the surface isn't too curved at the scale of the Gaussian kernel. However it would still be computationally prohibitive.&#xD;&#xA;&#xD;&#xA;Is there a more efficient convolving algorithm, perhaps based on some kind of iterated &quot;flow&quot; or partial exchange through edges of the mesh?&#xD;&#xA;&#xD;&#xA;The mesh can have either triangular or quadrilateral faces - whichever is more convenient in answering this question. The mesh is not regular in the sense that edge length varies within the mesh, otherwise I could have used [MeshDOG][1], as [DoG][2] is what I am aiming to do after this convolution.&#xD;&#xA;&#xD;&#xA;EDIT: Just a thought:&#xD;&#xA;&#xD;&#xA;The probability distribution of the location of a particle undergoing a random walk diffuses as a Gaussian distribution, I think. So if we take the function (we want to convolve) as the initial probability density of the particle's location, and then update the distribution according to some &quot;appropriate&quot; random walk through the mesh, the result may be the convolution I am seeking. So it may come down to determining the transition probabilities for each edge, as determined by the geometry within each 1-ring neighborhood.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;cad=rja&amp;uact=8&amp;ved=0ahUKEwjBstDNr9fMAhUMLMAKHXTfCDwQFgggMAA&amp;url=https%3A%2F%2Fhal.inria.fr%2Finria-00440407%2Fdocument&amp;usg=AFQjCNEyYd95Cd9vAccR99zGnvHzbuAVyw&amp;sig2=YL3vM1zt5DUL6odWCw5zUA&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Difference_of_Gaussians" ContentLicense="CC BY-SA 3.0" />
  <row Id="5844" PostHistoryTypeId="24" PostId="2441" RevisionGUID="5d366cb8-d9dd-4bf2-b5d2-6a5729dc4140" CreationDate="2016-05-13T23:42:17.090" Comment="Proposed by 3294 approved by 231 edit id of 138" ContentLicense="CC BY-SA 3.0" />
  <row Id="5845" PostHistoryTypeId="5" PostId="2433" RevisionGUID="5d883f93-43a6-473e-9844-f0381fd99458" CreationDate="2016-05-14T07:23:47.213" UserId="38" Comment="added 29 characters in body" Text="Polygon offsetting is certainly possible to do yourself. It is not nearly as involved as Bezier or B-spline offsetting is. First you want to decide how to deal with:&#xD;&#xA;&#xD;&#xA;1. Areas with no info, in essence how to deal with the joins. Do you just extend the line to the common intersection (miter join) or do you just connect the endpoints (bevel). You could also use round, parabolic or other join styles if you wish. Options here are unlimited. &#xD;&#xA;&#xD;&#xA;  For purposes of this discussion I will assume you will want a miter or bevel join.&#xD;&#xA;&#xD;&#xA;2. How do you want to deal with sidedness. Is a open curves offset closed or just on the other side. Other than that the convention is usually in 2D that outside is on the clockwise side of the path&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So lets look at what happens when 2 straight lines join and they are offset.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: situation in 2D&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;For a beveled corner join vector from any point to its offset is magnitude of $a$ direction of segment rotated counterclockwise 90 degrees then multiply that with length of offset. Or in case of the picture in mathematical notation&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA; A' = A + a\bigg(\big|B-A\big|   \begin{bmatrix}&#xD;&#xA;    0 &amp; 1\\&#xD;&#xA;    -1 &amp; 0 &#xD;&#xA;  \end{bmatrix}\bigg)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where a is the amount of offset. This assumes lines go from $A$ to $B$ to $C$. Connecting segments must be processed on both sides separately. The same formula can be used for all the points. Then just connect $B'^1$ to $B'^2$ with a line. In case your matrix illiterate the matrix says swap x and y coordinate and invert the x value.&#xD;&#xA;&#xD;&#xA;For a miter join the following applies:&#xD;&#xA;&#xD;&#xA;[![sss][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Situation of miter.&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA; B^{B-B'^{1}} = a\bigg(\big|B-A\big| \begin{bmatrix}&#xD;&#xA;    0 &amp; 1\\&#xD;&#xA;    -1 &amp; 0 &#xD;&#xA;  \end{bmatrix}\bigg)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;B' = B+\dfrac{ B^{B-B'^{1}}}{B^{B-B'^{1}}  \cdot (|B-A|-|C-B|)}&#xD;&#xA;$$&#xD;&#xA; &#xD;&#xA;The above can be heavily simplified ill leave that to the reader.&#xD;&#xA;&#xD;&#xA;Now the reason to use a library is that when the curves start to self intersect it gets a bit tedious to manage this. So just find a library that does this for you you'll save a lot of time.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jagc9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/r6eG1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5847" PostHistoryTypeId="5" PostId="2391" RevisionGUID="89e9222c-a415-4f98-8f31-eb064f151156" CreationDate="2016-05-14T11:03:35.480" UserId="2479" Comment="Added info about MIS" Text="What is the best currently known and ideally also production-verified approach for sampling environment maps (EM) in a MIS-based uni-directional path tracer and similar types of renderers? I would prefer solutions which are reasonably complicated while reasonably functional to those which provide perfect sampling at cost of super complicated and hard-to-understand implementation.&#xD;&#xA;&#xD;&#xA;What I know so far&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;There are some easy ways of sampling EMs. One can sample the needed hemisphere in a cosine-weighted manner,&#xD;&#xA;   which ignores both the BSDF and the EM function shapes. As a result,&#xD;&#xA;   it doesn't work for dynamic EMs:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To improve&#xD;&#xA;   the sampling to a usable level, one can sample the luminance of the EM&#xD;&#xA;   over the whole sphere. It is relatively easily implemented and the&#xD;&#xA;   results are quite good. However, the sampling strategy is still&#xD;&#xA;   ignoring the hemispherical visibility information and the cosine&#xD;&#xA;   factor (and also the BSDF), resulting in high noise on the surfaces&#xD;&#xA;   which are not directly lit by high-intensity areas of the EM:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Papers&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;I have found a few papers on the topic, but have not read them yet. Is any of these worth reading and implementing in a forward uni-directional path tracer, or is there something even better?&#xD;&#xA;&#xD;&#xA; - [Structured Importance Sampling of Environment Maps][3] (2003) by&#xD;&#xA;   Agarwal et al.&#xD;&#xA;&#xD;&#xA; - [Steerable Importance Sampling][4] (2007) by&#xD;&#xA;   Kartic Subr and Jim Arvo. They claim to present “...an algorithm for&#xD;&#xA;   efficient stratified importance sampling of environment maps that&#xD;&#xA;   generates samples in the positive hemi-sphere defined by local&#xD;&#xA;   orientation of arbitrary surfaces while accounting for cosine&#xD;&#xA;   weighting. “ The paper “Importance Sampling Spherical Harmonics”&#xD;&#xA;   comments on it: ”They create a triangulated representation of the&#xD;&#xA;   environment map and store the illumination premultiplied by each of&#xD;&#xA;   the first nine spherical harmonic basis functions at every vertex.&#xD;&#xA;   This forms a steerable basis where the clamped-cosine can be&#xD;&#xA;   efficiently rotated to any orientation.”&#xD;&#xA;&#xD;&#xA; - [Practical Product Importance Sampling for Direct Illumination][5] (2008) by&#xD;&#xA;   Petrik Clarberg and Tomas Akenine-Möller. An algorithm for sampling&#xD;&#xA;   the product of environment map lighting and surface reflectance. Uses&#xD;&#xA;   wavelet-based importance sampling.&#xD;&#xA;   &#xD;&#xA; - [Importance Sampling Spherical Harmonics][6] (2009)&#xD;&#xA;   by Jarosz, Carr, and Jensenn. The abstract says: “...we present the&#xD;&#xA;   first practical method for importance sampling functions represented&#xD;&#xA;   as spherical harmonics (SH)...”&#xD;&#xA;   &#xD;&#xA; - [Tone-Mapped Mean-shift Based Environment Map Sampling][7] (2015) by Feng&#xD;&#xA;   et al. This is pretty new and I have found neither a reference to it&#xD;&#xA;   nor the paper itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TBYYn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1DOSr.png&#xD;&#xA;  [3]: https://cseweb.ucsd.edu/~ravir/papers/structured/&#xD;&#xA;  [4]: http://home.eps.hw.ac.uk/~ks400/research.html#SteerableImportance&#xD;&#xA;  [5]: http://fileadmin.cs.lth.se/graphics/research/papers/2008/pps/&#xD;&#xA;  [6]: https://www.cs.dartmouth.edu/~wjarosz/publications/jarosz09importance.html&#xD;&#xA;  [7]: http://www.ncbi.nlm.nih.gov/pubmed/26584494" ContentLicense="CC BY-SA 3.0" />
  <row Id="5848" PostHistoryTypeId="5" PostId="2433" RevisionGUID="5240d581-b99f-407c-b73c-2118aa0289bb" CreationDate="2016-05-14T11:16:23.827" UserId="231" Comment="Minor tidying. Feel free to roll back anything that changes your intent." Text="Polygon offsetting is certainly possible to do yourself. It is not nearly as involved as Bezier or B-spline offsetting is. First you want to decide how to deal with:&#xD;&#xA;&#xD;&#xA;1. Areas with no info, in essence how to deal with the joins. Do you just extend the line to the common intersection (miter join) or do you just connect the endpoints (bevel). You could also use round, parabolic or other join styles if you wish. Options here are unlimited. &#xD;&#xA;&#xD;&#xA;  For the purposes of this discussion I will assume you will want a miter or bevel join.&#xD;&#xA;&#xD;&#xA;2. How do you want to deal with sidedness. Is an open curve's offset closed or just on the other side. Other than that the convention is usually in 2D that outside is on the clockwise side of the path&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So lets look at what happens when 2 straight lines join and they are offset.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Situation in 2D.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;For a beveled corner join vector, from any point to its offset is magnitude of $a$. Take the direction of the segment rotated counterclockwise 90 degrees then multiply that with the length of offset. Or in the case of the picture in mathematical notation&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA; A' = A + a\bigg(\big|B-A\big|   \begin{bmatrix}&#xD;&#xA;    0 &amp; 1\\&#xD;&#xA;    -1 &amp; 0 &#xD;&#xA;  \end{bmatrix}\bigg)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $a$ is the amount of offset. This assumes lines go from $A$ to $B$ to $C$. Connecting segments must be processed on both sides separately. The same formula can be used for all the points. Then just connect $B'^1$ to $B'^2$ with a line. In case you are matrix illiterate, the matrix says swap x and y coordinate and invert the x value.&#xD;&#xA;&#xD;&#xA;For a miter join the following applies:&#xD;&#xA;&#xD;&#xA;[![sss][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Situation of miter.&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA; B^{B-B'^{1}} = a\bigg(\big|B-A\big| \begin{bmatrix}&#xD;&#xA;    0 &amp; 1\\&#xD;&#xA;    -1 &amp; 0 &#xD;&#xA;  \end{bmatrix}\bigg)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;B' = B+\dfrac{ B^{B-B'^{1}}}{B^{B-B'^{1}}  \cdot (|B-A|-|C-B|)}&#xD;&#xA;$$&#xD;&#xA; &#xD;&#xA;The above can be heavily simplified but I'll leave that to the reader.&#xD;&#xA;&#xD;&#xA;Now the reason to use a library is that when the curves start to self intersect it gets a bit tedious to manage this. So just find a library that does this for you and you'll save a lot of time.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jagc9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/r6eG1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5849" PostHistoryTypeId="2" PostId="2444" RevisionGUID="fa305c52-0981-4b60-8d6b-70e3f442b894" CreationDate="2016-05-14T12:59:19.210" UserId="231" Text="# A few different approaches&#xD;&#xA;&#xD;&#xA;I'll consider a few variations on your specific request, since you mention efficiency and I suspect your specific request may be the least efficient. I'll also suggest ways of improving the efficiency without varying from your intended approach, so you can weigh up the alternatives.&#xD;&#xA;&#xD;&#xA;# Blurring the volume instead of the surface&#xD;&#xA;&#xD;&#xA;If you want the distance metric to be 3D Euclidean distance instead of 2D Euclidean distance within the surface, then you could perform the blur on a regular 3D grid to which the scalar function you have in mind has been applied. Then you can use the final result of your Difference of Gaussians to calculate the scalar values at the vertices of your irregular mesh. This avoids having to take into account the mesh shape for the bulk of the calculation.&#xD;&#xA;&#xD;&#xA;The 3D grid is likely to have a much larger number of vertices than the 2D mesh, but they will all be equally spaced and the large kernel blur can be achieved by repeated application of a small kernel blur taking into account only the 6 nearest neighbours, which will always be at a constant distance away. This approach involves potentially more calculation, but the ease with which the regular grid could be GPU accelerated may appeal.&#xD;&#xA;&#xD;&#xA;This will give a different result from performing the blur on the mesh vertices using 3D Euclidean distance. For example, the 3D grid approach will be affected by distinctive regions of the 3D scalar function that are near but not on the mesh. This may be desirable or not depending on your specific purpose.&#xD;&#xA;&#xD;&#xA;# Using 2D distance instead of 3D distance&#xD;&#xA;&#xD;&#xA;If you find that you need the distance metric to be 2D Euclidean within the surface, then you can get a good approximation to a larger kernel Gaussian blur by repeatedly applying a smaller kernel Gaussian blur. If there is not too much variation in the edge lengths within your mesh you may be able to choose a kernel size which allows for only including vertices one edge away at each iteration. This allows for only using the edge length to calculate the size of the contribution of a vertex.&#xD;&#xA;&#xD;&#xA;# 3D distance using the surface without the volume&#xD;&#xA;&#xD;&#xA;If you need the calculation to be precisely as described in your question, being calculated within the mesh rather than within the surrounding volume, but also using the 3D Euclidean distance, then using nearest neighbours and several iterations will not work. Unless the mesh is near to flat, the repeated application of a nearest neighbour blur will result in an approximation to the 2D Euclidean distance case, since the values will only be able to bleed from vertex to vertex, not directly along the shortest path as they would in a single pass. This will give less spread than would be achieved by a single pass that calculates the 3D distance to a vertex 10 edges away. (I have used 10 edges since you mention a 10-hop in your comment on the question.)&#xD;&#xA;&#xD;&#xA;Implementing the blur in a single pass will mean calculating the 3D Euclidean distance between every vertex and every other vertex with a 10 edge radius. This will be expensive, but perfectly possible. Since you mention efficiency, consider that there are some redundancies you can eliminate provided you have sufficient available memory.&#xD;&#xA;&#xD;&#xA;The two blurs that you produce prior to taking the Difference of Gaussians will use the same set of 3D distances up to the edge radius of the smaller kernel blur. If you can save these then you only need to calculate them once, rather than once per blur.&#xD;&#xA;&#xD;&#xA;Also, each distance will be used twice per blur - once in each direction as the length from vertex A to vertex B is the same as the length from B to A. Caching/memoising these distances will avoid calculating them twice.&#xD;&#xA;&#xD;&#xA;# Effects from arbitrarily many edges away&#xD;&#xA;&#xD;&#xA;If the surface curves such that some vertices which are many edges away are still near enough to affect each other in 3D distance, then rather than considering vertices within a certain number of edges away, you may need to consider all vertices within a certain 3D radius, regardless of how long the path via edges. In this case you can consider fewer vertices by using space partitioning, choosing a specific method which suits the mesh.&#xD;&#xA;&#xD;&#xA;If you don't want parts of the surface which approach each other to influence each other, then you probably want a 2D distance metric rather than the 3D one.&#xD;&#xA;&#xD;&#xA;If you have a wide range of different edge lengths then you may find the same problem of not being able to define a set number of edges to traverse. Again you may need to define a 3D distance instead of a number of edges, and consider all vertices that lie within that radius.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5850" PostHistoryTypeId="5" PostId="2444" RevisionGUID="1cfb75f1-dd8e-471f-b139-5e33892b38bd" CreationDate="2016-05-14T13:09:26.750" UserId="231" Comment="added 54 characters in body" Text="# A few different approaches&#xD;&#xA;&#xD;&#xA;I'll consider a few variations on your specific request, since you mention efficiency and I suspect your specific request may be the least efficient. I'll also suggest ways of improving the efficiency without varying from your intended approach, so you can weigh up the alternatives.&#xD;&#xA;&#xD;&#xA;# Blurring the volume instead of the surface&#xD;&#xA;&#xD;&#xA;If you want the distance metric to be 3D Euclidean distance instead of 2D Euclidean distance within the surface, then you could perform the blur on a regular 3D grid to which the scalar function you have in mind has been applied. Then you can use the final result of your Difference of Gaussians to calculate the scalar values at the vertices of your irregular mesh. This avoids having to take into account the mesh shape for the bulk of the calculation.&#xD;&#xA;&#xD;&#xA;The 3D grid is likely to have a much larger number of vertices than the 2D mesh, but they will all be equally spaced and the large kernel blur can be achieved by repeated application of a small kernel blur taking into account only the 6 nearest neighbours, which will always be at a constant distance away. This approach involves potentially more calculation, but the ease with which the regular grid could be GPU accelerated may appeal.&#xD;&#xA;&#xD;&#xA;This will give a different result from performing the blur on the mesh vertices using 3D Euclidean distance. For example, the 3D grid approach will be affected by distinctive regions of the 3D scalar function that are near but not on the mesh. This may be desirable or not depending on your specific purpose.&#xD;&#xA;&#xD;&#xA;# Using 2D distance instead of 3D distance&#xD;&#xA;&#xD;&#xA;If you find that you need the distance metric to be 2D Euclidean within the surface, then you can get a good approximation to a larger kernel Gaussian blur by repeatedly applying a smaller kernel Gaussian blur. If there is not too much variation in the edge lengths within your mesh you may be able to choose a kernel size which allows for only including vertices one edge away at each iteration. This allows for only using single edge lengths to calculate the size of the contribution of a vertex, rather than calculating a 2D multi-edge distance.&#xD;&#xA;&#xD;&#xA;# 3D distance using the surface without the volume&#xD;&#xA;&#xD;&#xA;If you need the calculation to be precisely as described in your question, being calculated within the mesh rather than within the surrounding volume, but also using the 3D Euclidean distance, then using nearest neighbours and several iterations will not work. Unless the mesh is near to flat, the repeated application of a nearest neighbour blur will result in an approximation to the 2D Euclidean distance case, since the values will only be able to bleed from vertex to vertex, not directly along the shortest path as they would in a single pass. This will give less spread than would be achieved by a single pass that calculates the 3D distance to a vertex 10 edges away. (I have used 10 edges since you mention a 10-hop in your comment on the question.)&#xD;&#xA;&#xD;&#xA;Implementing the blur in a single pass will mean calculating the 3D Euclidean distance between every vertex and every other vertex within a 10 edge radius. This will be expensive, but perfectly possible. Since you mention efficiency, consider that there are some redundancies you can eliminate provided you have sufficient available memory.&#xD;&#xA;&#xD;&#xA;The two blurs that you produce prior to taking the Difference of Gaussians will use the same set of 3D distances up to the edge radius of the smaller kernel blur. If you can save these then you only need to calculate them once, rather than once per blur.&#xD;&#xA;&#xD;&#xA;Also, each distance will be used twice per blur - once in each direction as the length from vertex A to vertex B is the same as the length from B to A. Caching/memoising these distances will avoid calculating them twice.&#xD;&#xA;&#xD;&#xA;# Effects from arbitrarily many edges away&#xD;&#xA;&#xD;&#xA;If the surface curves such that some vertices which are many edges away are still near enough to affect each other in 3D distance, then rather than considering vertices within a certain number of edges away, you may need to consider all vertices within a certain 3D radius, regardless of how long the path via edges. In this case you can consider fewer vertices by using space partitioning, choosing a specific method which suits the mesh.&#xD;&#xA;&#xD;&#xA;If you don't want parts of the surface which approach each other to influence each other, then you probably want a 2D distance metric rather than the 3D one.&#xD;&#xA;&#xD;&#xA;If you have a wide range of different edge lengths then you may find the same problem of not being able to define a set number of edges to traverse, even if the mesh is fairly flat. Again you may need to define a 3D distance instead of a number of edges, and consider all vertices that lie within that radius.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5851" PostHistoryTypeId="2" PostId="2445" RevisionGUID="0c9f5b31-8a0e-4269-a002-1b27a7412ff9" CreationDate="2016-05-14T14:27:20.423" UserId="231" Text="I'll give an intuitive idea of the reason in this answer. Once this intuitive idea is grasped, it can be easier to absorb the mathematical descriptions.&#xD;&#xA;&#xD;&#xA;Other people find it easier the other way around, so look at all the answers and see which approach works for you personally.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# A spherical shell of photons&#xD;&#xA;&#xD;&#xA;Imagine a point light source. Picture an instant where it emits a million photons spread evenly in all directions. At that instant, they are all in the same position, at the central point. A moment later, they have all moved the same distance and are now arranged in a small sphere with the point at its centre. A short time later they are still arranged in a sphere, but now a much larger sphere.&#xD;&#xA;&#xD;&#xA;As the sphere expands it always has the same number of photons, but they are spread out over the increasing area. Each photon has the same amount of energy it had when it first left the point source, but the photons are more spread out so a given area of the sphere now has less energy due to having fewer photons.&#xD;&#xA;&#xD;&#xA;When a photon hits a surface, it adds the same amount of energy whether it has traveled 1 metre or 100 metres. The reason the surface looks dimmer when it is further from the light source is that the photons are more spread out across that surface.&#xD;&#xA;&#xD;&#xA;# Source to eye ray tracing&#xD;&#xA;&#xD;&#xA;If you wrote a ray tracer that started with rays being emitted from a point light source, and then followed them to see what they hit, you wouldn't need the 1/r^2 term. Objects further from the light would naturally be hit by fewer rays due to the rays spreading out.&#xD;&#xA;&#xD;&#xA;# Eye to source ray tracing&#xD;&#xA;&#xD;&#xA;Most ray tracers don't start the rays from the light source, as this results in calculating the paths of all the rays that never reach the eye, which is very inefficient. Instead the rays start at the eye and are traced backwards, to see what surface they came from. If the ray was then bounced from that surface in a random direction to see if it hits the point light source, the fact that the light source is a point would make the probability of hitting it zero. So instead 1/r^2 is used to give a measure of how many rays hit the surface.&#xD;&#xA;&#xD;&#xA;# Geometry of a point source&#xD;&#xA;&#xD;&#xA;This isn't a property of light, it is a property of a point source. Light traveling in all directions from a point forms spherical shells of photons, and the surface area of a sphere increases in proportion to the radius squared.&#xD;&#xA;&#xD;&#xA;If you had light being emitted that was not in all directions then the rule would be different. For example, imagine a line light source instead of a point, with all the light being emitted radially (only in directions perpendicular to the line). Now the light forms cylindrical shells of photons, and the surface area of a cylinder increases in proportion to the radius, not the radius squared. Now you would use a 1/r term instead of a 1/r^2 term, and an object would need to be moved significantly further from the light source before seeing a noticeable drop in brightness.&#xD;&#xA;&#xD;&#xA;In reality, nearly every light source is equivalent to a collection of point sources - every point on an area light source emits light in all directions. So the reduction in light level will nearly always be with 1/r^2." ContentLicense="CC BY-SA 3.0" />
  <row Id="5852" PostHistoryTypeId="5" PostId="2445" RevisionGUID="133567ef-07f2-4b41-9ece-9c41f31a9cea" CreationDate="2016-05-14T14:32:44.140" UserId="231" Comment="added 172 characters in body" Text="I'll give an intuitive idea of the reason in this answer. Once this intuitive idea is grasped, it can be easier to absorb the mathematical descriptions.&#xD;&#xA;&#xD;&#xA;Other people find it easier the other way around, so look at all the answers and see which approach works for you personally.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# A spherical shell of photons&#xD;&#xA;&#xD;&#xA;Imagine a point light source. Picture an instant where it emits a million photons spread evenly in all directions. At that instant, they are all in the same position, at the central point. A moment later, they have all moved the same distance and are now arranged in a small sphere with the point at its centre. A short time later they are still arranged in a sphere, but now a much larger sphere.&#xD;&#xA;&#xD;&#xA;As the sphere expands it always has the same number of photons, but they are spread out over the increasing area. Each photon has the same amount of energy it had when it first left the point source, but the photons are more spread out so a given area of the sphere now has less energy due to having fewer photons.&#xD;&#xA;&#xD;&#xA;When a photon hits a surface, it adds the same amount of energy whether it has traveled 1 metre or 100 metres. The reason the surface looks dimmer when it is further from the light source is that the photons are more spread out across that surface.&#xD;&#xA;&#xD;&#xA;# Source to eye ray tracing&#xD;&#xA;&#xD;&#xA;If you wrote a ray tracer that started with rays being emitted from a point light source, and then followed them to see what they hit, you wouldn't need the 1/r^2 term. Objects further from the light would naturally be hit by fewer rays due to the rays spreading out.&#xD;&#xA;&#xD;&#xA;# Eye to source ray tracing&#xD;&#xA;&#xD;&#xA;Most ray tracers don't start the rays from the light source, as this results in calculating the paths of all the rays that never reach the eye, which is very inefficient. Instead the rays start at the eye and are traced backwards, to see what surface they came from. If the ray was then bounced from that surface in a random direction to see if it hits the point light source, the fact that the light source is a point would make the probability of hitting it zero. So instead 1/r^2 is used to give a measure of how many rays hit the surface.&#xD;&#xA;&#xD;&#xA;# Geometry of a point source&#xD;&#xA;&#xD;&#xA;This isn't a property of light, it is a property of a point source. Light traveling in all directions from a point forms spherical shells of photons, and the surface area of a sphere increases in proportion to the radius squared.&#xD;&#xA;&#xD;&#xA;If you had light being emitted that was not in all directions then the rule would be different. For example, imagine a line light source instead of a point, with all the light being emitted radially (only in directions perpendicular to the line). Now the light forms cylindrical shells of photons, and the surface area of a cylinder increases in proportion to the radius, not the radius squared. Now you would use a 1/r term instead of a 1/r^2 term, and an object would need to be moved significantly further from the light source before seeing a noticeable drop in brightness.&#xD;&#xA;&#xD;&#xA;In reality, nearly every light source is equivalent to a collection of point sources - every point on an area light source emits light in all directions. Even cylindrical lights like flourescent strip lights and neon signs still emit light in all directions, so the photons form spherical shells rather than cylindrical ones. So the reduction in light level will nearly always be with 1/r^2." ContentLicense="CC BY-SA 3.0" />
  <row Id="5853" PostHistoryTypeId="5" PostId="2445" RevisionGUID="25957120-e216-4b7a-aaa3-07b9c5bd0ab1" CreationDate="2016-05-14T14:40:01.353" UserId="231" Comment="Add mathjax for expressions" Text="I'll give an intuitive idea of the reason in this answer. Once this intuitive idea is grasped, it can be easier to absorb the mathematical descriptions.&#xD;&#xA;&#xD;&#xA;Other people find it easier the other way around, so look at all the answers and see which approach works for you personally.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# A spherical shell of photons&#xD;&#xA;&#xD;&#xA;Imagine a point light source. Picture an instant where it emits a million photons spread evenly in all directions. At that instant, they are all in the same position, at the central point. A moment later, they have all moved the same distance and are now arranged in a small sphere with the point at its centre. A short time later they are still arranged in a sphere, but now a much larger sphere.&#xD;&#xA;&#xD;&#xA;As the sphere expands it always has the same number of photons, but they are spread out over the increasing area. Each photon has the same amount of energy it had when it first left the point source, but the photons are more spread out so a given area of the sphere now has less energy due to having fewer photons.&#xD;&#xA;&#xD;&#xA;When a photon hits a surface, it adds the same amount of energy whether it has traveled 1 metre or 100 metres. The reason the surface looks dimmer when it is further from the light source is that the photons are more spread out across that surface.&#xD;&#xA;&#xD;&#xA;# Source to eye ray tracing&#xD;&#xA;&#xD;&#xA;If you wrote a ray tracer that started with rays being emitted from a point light source, and then followed them to see what they hit, you wouldn't need the $1/r^2$ term. Objects further from the light would naturally be hit by fewer rays due to the rays spreading out.&#xD;&#xA;&#xD;&#xA;# Eye to source ray tracing&#xD;&#xA;&#xD;&#xA;Most ray tracers don't start the rays from the light source, as this results in calculating the paths of all the rays that never reach the eye, which is very inefficient. Instead the rays start at the eye and are traced backwards, to see what surface they came from. If the ray was then bounced from that surface in a random direction to see if it hits the point light source, the fact that the light source is a point would make the probability of hitting it zero. So instead $1/r^2$ is used to give a measure of how many rays hit the surface.&#xD;&#xA;&#xD;&#xA;# Geometry of a point source&#xD;&#xA;&#xD;&#xA;This isn't a property of light, it is a property of a point source. Light traveling in all directions from a point forms spherical shells of photons, and the surface area of a sphere increases in proportion to the radius squared.&#xD;&#xA;&#xD;&#xA;If you had light being emitted that was not in all directions then the rule would be different. For example, imagine a line light source instead of a point, with all the light being emitted radially (only in directions perpendicular to the line). Now the light forms cylindrical shells of photons, and the surface area of a cylinder increases in proportion to the radius, not the radius squared. Now you would use a $1/r$ term instead of a $1/r^2$ term, and an object would need to be moved significantly further from the light source before seeing a noticeable drop in brightness.&#xD;&#xA;&#xD;&#xA;In reality, nearly every light source is equivalent to a collection of point sources - every point on an area light source emits light in all directions. Even cylindrical lights like flourescent strip lights and neon signs still emit light in all directions, so the photons form spherical shells rather than cylindrical ones. So the reduction in light level will nearly always be with $1/r^2$." ContentLicense="CC BY-SA 3.0" />
  <row Id="5855" PostHistoryTypeId="2" PostId="2446" RevisionGUID="75a563da-a546-41c4-b121-d36752a6c123" CreationDate="2016-05-15T04:39:01.593" UserId="2308" Text="OK so I have a simple setup going on.  Basically I am just drawing some textures and shapes.  However sizing is going weird... let me show you how any maybe you can diagnose.&#xD;&#xA;&#xD;&#xA;Basically everything is broken into components that work fine by themselves, however when together it is disastrous.&#xD;&#xA;&#xD;&#xA;Case #1 Section of actual texture appears with a blown up resolution in the bottom left corner.&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, GLsizei(width), GLsizei(height))&#xD;&#xA;    layer_shapes.begin()&#xD;&#xA;    glViewport(0, 0, GLsizei(width), GLsizei(height))&#xD;&#xA;    checkFades()&#xD;&#xA;    drawShapes()&#xD;&#xA;    layer_shapes.end()&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Case #2 Image appears blown up and full screen&#xD;&#xA;&#xD;&#xA;    layer_shapes.begin()&#xD;&#xA;    checkFades()&#xD;&#xA;    drawShapes()&#xD;&#xA;    layer_shapes.end()&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Case #3 proving that texture drawing works by drawing to front buffer (I put a texture into a fbo and never drew to the fbo)&#xD;&#xA;&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;Case #4 Proving that shape drawing works (This is what it should look like, except with an accumulation effect)&#xD;&#xA;&#xD;&#xA;    drawShapes()&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;(Please note discoloration is due to a debugging thing in the fragment shader, not an error)&#xD;&#xA;&#xD;&#xA;And Incase you want to see it here is how I set up my texture fbo's.  They get initialized and then have .load() called on them&#xD;&#xA;&#xD;&#xA;    class TextureBuffer {&#xD;&#xA;        var framebuffer:GLuint = 0&#xD;&#xA;        var tex:GLuint = 0&#xD;&#xA;        var old_fbo:GLint = 0&#xD;&#xA;        var w:GLsizei = 0&#xD;&#xA;        var h:GLsizei = 0&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        init(widthi: GLsizei = 0, heighti: GLsizei = 0)&#xD;&#xA;        {&#xD;&#xA;            w = widthi&#xD;&#xA;            h = heighti&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func begin()&#xD;&#xA;        {&#xD;&#xA;            glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &amp;old_fbo)&#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func checkStatus()&#xD;&#xA;        {&#xD;&#xA;            let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))&#xD;&#xA;            if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))&#xD;&#xA;            {&#xD;&#xA;                print(&quot;DIDNT GO WELL WITH&quot;)&#xD;&#xA;                print(status)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func end()&#xD;&#xA;        {&#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func loadTexture(name: String, type: String) -&gt; GLuint&#xD;&#xA;        {&#xD;&#xA;            var it:GLKTextureInfo = GLKTextureInfo()&#xD;&#xA;            let pic = UIImage(named: name + &quot;.&quot; + type)!.CGImage&#xD;&#xA;            let path = NSBundle.mainBundle().pathForResource(name, ofType: type)&#xD;&#xA;            &#xD;&#xA;            do&#xD;&#xA;            {&#xD;&#xA;                try it = GLKTextureLoader.textureWithContentsOfFile(path!, options: nil)&#xD;&#xA;            }&#xD;&#xA;            catch&#xD;&#xA;            {&#xD;&#xA;                do&#xD;&#xA;                {&#xD;&#xA;                    //print(&quot;ERR Loading: &quot; + path!)&#xD;&#xA;                    try it = GLKTextureLoader.textureWithCGImage(pic!, options: nil)&#xD;&#xA;                }&#xD;&#xA;                catch&#xD;&#xA;                {&#xD;&#xA;                    print(&quot;Error loading UIImage: &quot; +  pic.debugDescription)&#xD;&#xA;                    it = GLKTextureInfo()&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return it.name&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func load(width: CGFloat?, height: CGFloat?)&#xD;&#xA;        {&#xD;&#xA;            if let lwidth = width&#xD;&#xA;            {&#xD;&#xA;                w = GLsizei(lwidth)&#xD;&#xA;            }&#xD;&#xA;            if let lheight = height&#xD;&#xA;            {&#xD;&#xA;                h = GLsizei(lheight)&#xD;&#xA;            }&#xD;&#xA;            glBindTexture(GLenum(GL_TEXTURE_2D), 0)&#xD;&#xA;            glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &amp;old_fbo)&#xD;&#xA;            &#xD;&#xA;            glGenFramebuffers(1, &amp;framebuffer)&#xD;&#xA;            tex = loadTexture(&quot;Black&quot;, type: &quot;png&quot;)&#xD;&#xA;            &#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            glBindTexture(GLenum(GL_TEXTURE_2D), tex)&#xD;&#xA;            //------&gt;&gt;&gt;&gt;glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(w), GLsizei(h), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), nil)&#xD;&#xA;            glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), tex, 0)&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))&#xD;&#xA;            if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))&#xD;&#xA;            {&#xD;&#xA;                print(&quot;DIDNT GO WELL WITH&quot;, width, &quot; &quot; , height)&#xD;&#xA;                print(status)&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A thought is there was a line near the end (I put an arrow pointing to it) that I had to remove to get the fbo to work properly.  Previously the code worked fine, however it is not working fine now.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BQqGr.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/jfR7w.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/YvdOz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/9hlqX.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5856" PostHistoryTypeId="1" PostId="2446" RevisionGUID="75a563da-a546-41c4-b121-d36752a6c123" CreationDate="2016-05-15T04:39:01.593" UserId="2308" Text="What is causing this odd scaling behavior?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5857" PostHistoryTypeId="3" PostId="2446" RevisionGUID="75a563da-a546-41c4-b121-d36752a6c123" CreationDate="2016-05-15T04:39:01.593" UserId="2308" Text="|opengl|texture|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5858" PostHistoryTypeId="5" PostId="2446" RevisionGUID="71d4eacc-8bbb-4906-8555-49a1c23dc30e" CreationDate="2016-05-15T16:17:20.827" UserId="2308" Comment="Made it more clear" Text="OK so I have a simple setup going on.  Basically I am just drawing some textures and shapes.  However sizing is going weird... let me show you how any maybe you can diagnose.&#xD;&#xA;&#xD;&#xA;Basically everything is broken into components that work fine by themselves, however when together it is disastrous.&#xD;&#xA;&#xD;&#xA;**Case #1 Section of actual texture appears with an enlarged resolution in the bottom left corner.**&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, GLsizei(width), GLsizei(height))&#xD;&#xA;    layer_shapes.begin()&#xD;&#xA;    glViewport(0, 0, GLsizei(width), GLsizei(height))&#xD;&#xA;    checkFades()&#xD;&#xA;    drawShapes()&#xD;&#xA;    layer_shapes.end()&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;**Case #2 Image appears enlarged and full screen**&#xD;&#xA;&#xD;&#xA;    layer_shapes.begin()&#xD;&#xA;    checkFades()&#xD;&#xA;    drawShapes()&#xD;&#xA;    layer_shapes.end()&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Case #3 proving that texture drawing works by drawing to front buffer (I put a texture into a fbo and never drew to the fbo)**&#xD;&#xA;&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Case #4 Proving that shape drawing works (This is what it should look like, except with an accumulation effect)**&#xD;&#xA;&#xD;&#xA;    drawShapes()&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;(Please note discoloration is due to a debugging thing in the fragment shader, not an error)&#xD;&#xA;&#xD;&#xA;**In summary** Cases 1 and 2 do not work as intended (they enlarge only part of the shape drawing and put it in the wrong proportion on the screen).  Cases 3 and 4 show the individual complnents (drawing shapes, and drawing textures) working when everything is drawn to the front buffer without any 'glViewport' calls.&#xD;&#xA;&#xD;&#xA;**The desired behavior is** that an image like case 4 would be drawn, however the image would be an accumulation of previous frames (Notice how i never clear the layer_shapes fbo) so the shapes (that are moving) would leave a trail.  The proportions are just being weird! &#xD;&#xA;&#xD;&#xA;And Incase you want to see it here is how I set up my texture fbo's.  They get initialized and then have .load() called on them&#xD;&#xA;&#xD;&#xA;    class TextureBuffer {&#xD;&#xA;        var framebuffer:GLuint = 0&#xD;&#xA;        var tex:GLuint = 0&#xD;&#xA;        var old_fbo:GLint = 0&#xD;&#xA;        var w:GLsizei = 0&#xD;&#xA;        var h:GLsizei = 0&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        init(widthi: GLsizei = 0, heighti: GLsizei = 0)&#xD;&#xA;        {&#xD;&#xA;            w = widthi&#xD;&#xA;            h = heighti&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func begin()&#xD;&#xA;        {&#xD;&#xA;            glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &amp;old_fbo)&#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func checkStatus()&#xD;&#xA;        {&#xD;&#xA;            let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))&#xD;&#xA;            if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))&#xD;&#xA;            {&#xD;&#xA;                print(&quot;DIDNT GO WELL WITH&quot;)&#xD;&#xA;                print(status)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func end()&#xD;&#xA;        {&#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func loadTexture(name: String, type: String) -&gt; GLuint&#xD;&#xA;        {&#xD;&#xA;            var it:GLKTextureInfo = GLKTextureInfo()&#xD;&#xA;            let pic = UIImage(named: name + &quot;.&quot; + type)!.CGImage&#xD;&#xA;            let path = NSBundle.mainBundle().pathForResource(name, ofType: type)&#xD;&#xA;            &#xD;&#xA;            do&#xD;&#xA;            {&#xD;&#xA;                try it = GLKTextureLoader.textureWithContentsOfFile(path!, options: nil)&#xD;&#xA;            }&#xD;&#xA;            catch&#xD;&#xA;            {&#xD;&#xA;                do&#xD;&#xA;                {&#xD;&#xA;                    //print(&quot;ERR Loading: &quot; + path!)&#xD;&#xA;                    try it = GLKTextureLoader.textureWithCGImage(pic!, options: nil)&#xD;&#xA;                }&#xD;&#xA;                catch&#xD;&#xA;                {&#xD;&#xA;                    print(&quot;Error loading UIImage: &quot; +  pic.debugDescription)&#xD;&#xA;                    it = GLKTextureInfo()&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return it.name&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func load(width: CGFloat?, height: CGFloat?)&#xD;&#xA;        {&#xD;&#xA;            if let lwidth = width&#xD;&#xA;            {&#xD;&#xA;                w = GLsizei(lwidth)&#xD;&#xA;            }&#xD;&#xA;            if let lheight = height&#xD;&#xA;            {&#xD;&#xA;                h = GLsizei(lheight)&#xD;&#xA;            }&#xD;&#xA;            glBindTexture(GLenum(GL_TEXTURE_2D), 0)&#xD;&#xA;            glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &amp;old_fbo)&#xD;&#xA;            &#xD;&#xA;            glGenFramebuffers(1, &amp;framebuffer)&#xD;&#xA;            tex = loadTexture(&quot;Black&quot;, type: &quot;png&quot;)&#xD;&#xA;            &#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            glBindTexture(GLenum(GL_TEXTURE_2D), tex)&#xD;&#xA;            //------&gt;&gt;&gt;&gt;glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(w), GLsizei(h), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), nil)&#xD;&#xA;            glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), tex, 0)&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))&#xD;&#xA;            if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))&#xD;&#xA;            {&#xD;&#xA;                print(&quot;DIDNT GO WELL WITH&quot;, width, &quot; &quot; , height)&#xD;&#xA;                print(status)&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A thought is there was a line near the end (I put an arrow pointing to it) that I had to remove to get the fbo to work properly.  Previously the code worked fine, however it is not working fine now.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BQqGr.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/jfR7w.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/YvdOz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/9hlqX.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5859" PostHistoryTypeId="5" PostId="2446" RevisionGUID="0da085c1-3300-438f-b955-f1668b43aa14" CreationDate="2016-05-15T16:33:53.343" UserId="2308" Comment="added 273 characters in body" Text="OK so I have a simple setup going on.  Basically I am just drawing some textures and shapes.  However sizing is going weird... let me show you how any maybe you can diagnose.&#xD;&#xA;&#xD;&#xA;Basically everything is broken into components that work fine by themselves, however when together it is disastrous.&#xD;&#xA;&#xD;&#xA;**Case #1 Section of actual texture appears with an enlarged resolution in the bottom left corner.**&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, GLsizei(width), GLsizei(height))&#xD;&#xA;    layer_shapes.begin()&#xD;&#xA;    glViewport(0, 0, GLsizei(width), GLsizei(height))&#xD;&#xA;    checkFades()&#xD;&#xA;    drawShapes()&#xD;&#xA;    layer_shapes.end()&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;**Case #2 Image appears enlarged and full screen**&#xD;&#xA;&#xD;&#xA;    layer_shapes.begin()&#xD;&#xA;    checkFades()&#xD;&#xA;    drawShapes()&#xD;&#xA;    layer_shapes.end()&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Case #3 proving that texture drawing works by drawing to front buffer (I put a texture into a fbo and never drew to the fbo)**&#xD;&#xA;&#xD;&#xA;    drawTexture(layer_shapes, alpha: 0.0)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Case #4 Proving that shape drawing works (This is what it should look like, except with an accumulation effect)**&#xD;&#xA;&#xD;&#xA;    drawShapes()&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;(Please note discoloration is due to a debugging thing in the fragment shader, not an error)&#xD;&#xA;&#xD;&#xA;**In summary** Cases 1 and 2 do not work as intended (they enlarge only part of the shape drawing and put it in the wrong proportion on the screen).  Cases 3 and 4 show the individual complnents (drawing shapes, and drawing textures) working when everything is drawn to the front buffer without any 'glViewport' calls.&#xD;&#xA;&#xD;&#xA;**The desired behavior is** that an image like case 4 would be drawn, however the image would be an accumulation of previous frames (Notice how i never clear the layer_shapes fbo) so the shapes (that are moving) would leave a trail.  The proportions are just being weird! &#xD;&#xA;&#xD;&#xA;And Incase you want to see it here is how I set up my texture fbo's.  They get initialized and then have .load() called on them&#xD;&#xA;&#xD;&#xA;    class TextureBuffer {&#xD;&#xA;        var framebuffer:GLuint = 0&#xD;&#xA;        var tex:GLuint = 0&#xD;&#xA;        var old_fbo:GLint = 0&#xD;&#xA;        var w:GLsizei = 0&#xD;&#xA;        var h:GLsizei = 0&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        init(widthi: GLsizei = 0, heighti: GLsizei = 0)&#xD;&#xA;        {&#xD;&#xA;            w = widthi&#xD;&#xA;            h = heighti&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func begin()&#xD;&#xA;        {&#xD;&#xA;            glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &amp;old_fbo)&#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func checkStatus()&#xD;&#xA;        {&#xD;&#xA;            let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))&#xD;&#xA;            if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))&#xD;&#xA;            {&#xD;&#xA;                print(&quot;DIDNT GO WELL WITH&quot;)&#xD;&#xA;                print(status)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func end()&#xD;&#xA;        {&#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func loadTexture(name: String, type: String) -&gt; GLuint&#xD;&#xA;        {&#xD;&#xA;            var it:GLKTextureInfo = GLKTextureInfo()&#xD;&#xA;            let pic = UIImage(named: name + &quot;.&quot; + type)!.CGImage&#xD;&#xA;            let path = NSBundle.mainBundle().pathForResource(name, ofType: type)&#xD;&#xA;            &#xD;&#xA;            do&#xD;&#xA;            {&#xD;&#xA;                try it = GLKTextureLoader.textureWithContentsOfFile(path!, options: nil)&#xD;&#xA;            }&#xD;&#xA;            catch&#xD;&#xA;            {&#xD;&#xA;                do&#xD;&#xA;                {&#xD;&#xA;                    //print(&quot;ERR Loading: &quot; + path!)&#xD;&#xA;                    try it = GLKTextureLoader.textureWithCGImage(pic!, options: nil)&#xD;&#xA;                }&#xD;&#xA;                catch&#xD;&#xA;                {&#xD;&#xA;                    print(&quot;Error loading UIImage: &quot; +  pic.debugDescription)&#xD;&#xA;                    it = GLKTextureInfo()&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return it.name&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        func load(width: CGFloat?, height: CGFloat?)&#xD;&#xA;        {&#xD;&#xA;            if let lwidth = width&#xD;&#xA;            {&#xD;&#xA;                w = GLsizei(lwidth)&#xD;&#xA;            }&#xD;&#xA;            if let lheight = height&#xD;&#xA;            {&#xD;&#xA;                h = GLsizei(lheight)&#xD;&#xA;            }&#xD;&#xA;            glBindTexture(GLenum(GL_TEXTURE_2D), 0)&#xD;&#xA;            glGetIntegerv(GLenum(GL_FRAMEBUFFER_BINDING), &amp;old_fbo)&#xD;&#xA;            &#xD;&#xA;            glGenFramebuffers(1, &amp;framebuffer)&#xD;&#xA;            tex = loadTexture(&quot;Black&quot;, type: &quot;png&quot;)&#xD;&#xA;            &#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), framebuffer)&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            glBindTexture(GLenum(GL_TEXTURE_2D), tex)&#xD;&#xA;            //------&gt;&gt;&gt;&gt;glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(w), GLsizei(h), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), nil)&#xD;&#xA;            glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), tex, 0)&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))&#xD;&#xA;            if (status != GLenum(GL_FRAMEBUFFER_COMPLETE))&#xD;&#xA;            {&#xD;&#xA;                print(&quot;DIDNT GO WELL WITH&quot;, width, &quot; &quot; , height)&#xD;&#xA;                print(status)&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), GLenum(old_fbo))&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A thought is there was a line near the end (I put an arrow pointing to it) that I had to remove to get the fbo to work properly.  Previously the code worked fine, however it is not working fine now.&#xD;&#xA;&#xD;&#xA;I do have a suspicion that since I have removed that line that caused nothing to work that the texture that is generated by it is the wrong size since the texture it is loading is of a non-device size.  However I do not know why that call causes everything not to work.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BQqGr.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/jfR7w.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/YvdOz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/9hlqX.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5860" PostHistoryTypeId="2" PostId="2447" RevisionGUID="0aac99be-898c-41f2-9d41-0beb2b543805" CreationDate="2016-05-15T17:06:14.197" UserId="3365" Text="I tried to implement Perlin Noise *by myself* using just the theory (following flafla2.github.io/2014/08/09/perlinnoise.html). Unfortunately I was unable to achieve the look of the &quot;original&quot; Perlin Noise.&#xD;&#xA;&#xD;&#xA;What's the reason the code below renders a blocky version of Perlin Noise?&#xD;&#xA;&#xD;&#xA;What should I improve/change in the code so that it renders Perlin Noise without the artifacts?&#xD;&#xA;&#xD;&#xA;I suspect there might be problem either in the way I interpolate or in the `grads` vector. The `grads` vector contains dot products of (random vector for lattice point) and (the size vector) – for all 4 nearby lattice points. (The random and size vectors are described in the very first link.)&#xD;&#xA;&#xD;&#xA;GLSL Sandbox: http://glslsandbox.com/e#32663.0&#xD;&#xA;&#xD;&#xA;[![Artifacts in the noise][1]][1]&#xD;&#xA;&#xD;&#xA;    float fade(float t) { return t * t * t * (t * (t * 6. - 15.) + 10.); }&#xD;&#xA;    vec2 smooth(vec2 x) { return vec2(fade(x.x), fade(x.y)); }&#xD;&#xA;    &#xD;&#xA;    vec2 hash(vec2 co) {&#xD;&#xA;        return fract (vec2(.5654654, -.65465) * dot (vec2(.654, 57.4), co));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float perlinNoise(vec2 uv) {&#xD;&#xA;        vec2 PT  = floor(uv);&#xD;&#xA;        vec2 pt  = fract(uv);&#xD;&#xA;        vec2 mmpt= smooth(pt);&#xD;&#xA;        &#xD;&#xA;        vec4 grads = vec4(&#xD;&#xA;        	dot(hash(PT + vec2(.0, 1.)), pt-vec2(.0, 1.)),   dot(hash(PT + vec2(1., 1.)), pt-vec2(1., 1.)),&#xD;&#xA;            dot(hash(PT + vec2(.0, .0)), pt-vec2(.0, .0)),   dot(hash(PT + vec2(1., .0)), pt-vec2(1., 0.))&#xD;&#xA;        );&#xD;&#xA;    &#xD;&#xA;        return 5.*mix (mix (grads.z, grads.w, mmpt.x), mix (grads.x, grads.y, mmpt.x), mmpt.y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float fbm(vec2 uv) {&#xD;&#xA;        float finalNoise = 0.;&#xD;&#xA;        finalNoise += .50000*perlinNoise(2.*uv);&#xD;&#xA;        finalNoise += .25000*perlinNoise(4.*uv);&#xD;&#xA;        finalNoise += .12500*perlinNoise(8.*uv);&#xD;&#xA;        finalNoise += .06250*perlinNoise(16.*uv);&#xD;&#xA;        finalNoise += .03125*perlinNoise(32.*uv);&#xD;&#xA;        &#xD;&#xA;        return finalNoise;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	vec2 position = gl_FragCoord.xy / resolution.y;&#xD;&#xA;    	gl_FragColor = vec4( vec3( fbm(3.*position) ), 1.0 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/okckE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5861" PostHistoryTypeId="1" PostId="2447" RevisionGUID="0aac99be-898c-41f2-9d41-0beb2b543805" CreationDate="2016-05-15T17:06:14.197" UserId="3365" Text="Why does my Perlin Noise look &quot;blocky&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5862" PostHistoryTypeId="3" PostId="2447" RevisionGUID="0aac99be-898c-41f2-9d41-0beb2b543805" CreationDate="2016-05-15T17:06:14.197" UserId="3365" Text="|glsl|noise|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5866" PostHistoryTypeId="5" PostId="2441" RevisionGUID="3fea77a6-4ee7-45ed-9b78-458176878c5b" CreationDate="2016-05-15T18:28:19.443" UserId="3294" Comment="deleted 86 characters in body" Text="I have a scalar function defined over the vertices of a surface mesh. I want to compute an approximate (and generalized, I suppose) &quot;Gaussian blur/convolution&quot; of this function over the surface.&#xD;&#xA;&#xD;&#xA;I can imagine for each vertex, taking an average of the function at vertices in it's (multi-hop) neighborhood weighted according to the Gaussian of their Euclidean distance (in R3) from the current vertex multiplied by the local area they represent. This approximation would be good if the surface isn't too curved at the scale of the Gaussian kernel. However it would still be computationally prohibitive.&#xD;&#xA;&#xD;&#xA;Is there a more efficient convolving algorithm, perhaps based on some kind of iterated &quot;flow&quot; or partial exchange through edges of the mesh?&#xD;&#xA;&#xD;&#xA;The mesh can have either triangular or quadrilateral faces - whichever is more convenient in answering this question. But the edge lengths are not constant, so local neighborhood geometry differs between vertices.&#xD;&#xA;&#xD;&#xA;EDIT: Just a thought:&#xD;&#xA;&#xD;&#xA;The probability distribution of the location of a particle undergoing a random walk diffuses as a Gaussian distribution, I think. So if we take the function (we want to convolve) as the initial probability density of the particle's location, and then update the distribution according to some &quot;appropriate&quot; random walk through the mesh, the result may be the convolution I am seeking. So it may come down to determining the transition probabilities for each edge, as determined by the geometry within each 1-ring neighborhood.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;cad=rja&amp;uact=8&amp;ved=0ahUKEwjBstDNr9fMAhUMLMAKHXTfCDwQFgggMAA&amp;url=https%3A%2F%2Fhal.inria.fr%2Finria-00440407%2Fdocument&amp;usg=AFQjCNEyYd95Cd9vAccR99zGnvHzbuAVyw&amp;sig2=YL3vM1zt5DUL6odWCw5zUA&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Difference_of_Gaussians" ContentLicense="CC BY-SA 3.0" />
  <row Id="5867" PostHistoryTypeId="2" PostId="2449" RevisionGUID="174c7a5f-81b9-449f-8487-eb5d2d5deed1" CreationDate="2016-05-15T18:38:14.730" UserId="48" Text="The interpolation looks fine. The main problem here is that the hash function you're using isn't very good. If I look at just one octave, and visualize the hash result by outputting `hash(PT).x`, I get something like this:&#xD;&#xA;&#xD;&#xA;[![bad hash function][1]][1]&#xD;&#xA;&#xD;&#xA;This is supposed to be completely random per grid square, but you can see that it has a lot of diagonal line patterns in it (it almost looks like a checkerboard), so it's not a very random hash, and those patterns will show up in the noise produced by it.&#xD;&#xA;&#xD;&#xA;The other problem is that your hash only returns gradient vectors in [0, 1], while they should be in [&amp;minus;1, 1] to get gradients in all directions. That part's easy to fix by remapping.&#xD;&#xA;&#xD;&#xA;To fix those problems, I switched the code to use this hash function (due to Mikkel Gjoel):&#xD;&#xA;&#xD;&#xA;    vec2 hash(vec2 co) {&#xD;&#xA;        float m = dot(co, vec2(12.9898, 78.233));&#xD;&#xA;        return fract(vec2(sin(m),cos(m))* 43758.5453) * 2. - 1.;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note that due to the trig functions it's going to be a bit more expensive than your version. However, it considerably improves the appearance of the resulting noise:&#xD;&#xA;&#xD;&#xA;[![fbm noise with better hash function][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LcFJV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ND8Es.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5871" PostHistoryTypeId="2" PostId="2450" RevisionGUID="f43fb0f2-9c73-4364-8458-ba2e2ec88c02" CreationDate="2016-05-16T17:31:04.707" UserId="3377" Text="I'd like to load arbitrary meshes and draw thick black lines along the edges to get a toon-shading like look.&#xD;&#xA;I managed to draw a black silhouette around the objects by using the stencil buffer. You can see the result here:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But what's missing are the black lines in the object itself. I thought about checking normal discontinuities: Checking if a neighbouring pixel has a different normal vector than the current one. If yes, an edge has been found. Unfortunately, I've no idea how I could implement this approach, neither in OpenGL nor in GLSL vertex/fragment shader.&#xD;&#xA;&#xD;&#xA;I'd be very happy for some help regarding this approach or any other regarding edge detection. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rPEIz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5872" PostHistoryTypeId="1" PostId="2450" RevisionGUID="f43fb0f2-9c73-4364-8458-ba2e2ec88c02" CreationDate="2016-05-16T17:31:04.707" UserId="3377" Text="OpenGL - Detection of edges" ContentLicense="CC BY-SA 3.0" />
  <row Id="5873" PostHistoryTypeId="3" PostId="2450" RevisionGUID="f43fb0f2-9c73-4364-8458-ba2e2ec88c02" CreationDate="2016-05-16T17:31:04.707" UserId="3377" Text="|opengl|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5874" PostHistoryTypeId="5" PostId="2450" RevisionGUID="4597a3e3-4b90-4ddc-8124-ff155b3af6d7" CreationDate="2016-05-16T17:38:31.117" UserId="3377" Comment="added 50 characters in body" Text="I'd like to load arbitrary meshes and draw thick black lines along the edges to get a toon-shading like look.&#xD;&#xA;I managed to draw a black silhouette around the objects by using the stencil buffer. You can see the result here:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But what's missing are the black lines in the object itself. I thought about checking normal discontinuities: Checking if a neighbouring pixel has a different normal vector than the current one. If yes, an edge has been found. Unfortunately, I've no idea how I could implement this approach, neither in OpenGL nor in GLSL vertex/fragment shader.&#xD;&#xA;&#xD;&#xA;I'd be very happy for some help regarding this approach or any other regarding edge detection. &#xD;&#xA;&#xD;&#xA;Edit: I do not use any textures for my meshes.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rPEIz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5875" PostHistoryTypeId="5" PostId="2441" RevisionGUID="80e09efb-595a-4b71-8cbf-2ee205f996d5" CreationDate="2016-05-16T18:21:30.267" UserId="3294" Comment="deleted 555 characters in body" Text="I have a scalar function defined over the vertices of a surface mesh. I want to compute an approximate (and generalized, I suppose) &quot;Gaussian blur/convolution&quot; of this function over the surface.&#xD;&#xA;&#xD;&#xA;I can imagine for each vertex, taking an average of the function at vertices in it's (multi-hop) neighborhood weighted according to the Gaussian of their Euclidean distance (in R3) from the current vertex multiplied by the local area they represent. This approximation would be good if the surface isn't too curved at the scale of the Gaussian kernel. However it would still be computationally prohibitive.&#xD;&#xA;&#xD;&#xA;Is there a more efficient convolving algorithm, perhaps based on some kind of iterated &quot;flow&quot; or partial exchange through edges of the mesh?&#xD;&#xA;&#xD;&#xA;The mesh can have either triangular or quadrilateral faces - whichever is more convenient in answering this question. But the edge lengths are not constant, so local neighborhood geometry differs between vertices.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=1&amp;cad=rja&amp;uact=8&amp;ved=0ahUKEwjBstDNr9fMAhUMLMAKHXTfCDwQFgggMAA&amp;url=https%3A%2F%2Fhal.inria.fr%2Finria-00440407%2Fdocument&amp;usg=AFQjCNEyYd95Cd9vAccR99zGnvHzbuAVyw&amp;sig2=YL3vM1zt5DUL6odWCw5zUA&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Difference_of_Gaussians" ContentLicense="CC BY-SA 3.0" />
  <row Id="5876" PostHistoryTypeId="2" PostId="2451" RevisionGUID="624d43a4-d643-4952-a24b-373b154c49bb" CreationDate="2016-05-16T20:30:13.717" UserId="1613" Text="Disclaimer: I have no idea what is the state of the art in the environmental map sampling. In fact, I have very little knowledge about this topic. So this will not be complete answer but I will formulate the problem mathematically and analyze it. I do this mainly for myself, so I make it clear for my self but I hope that OP and others will find it useful.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\newcommand{\w}{\omega}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;We want to calculate direct illumination at a point i.e. we want to know the value of [the integral][1]&#xD;&#xA;$$&#xD;&#xA;I =\int_{S^2} f(\omega_i,\omega_o,n) \, L(\omega_i) \,(\omega_i\cdot n)^+ d\omega_i&#xD;&#xA;$$&#xD;&#xA;where $f(\omega_i,\omega_o,n)$ is BSDF function(I explicitly state dependance on the normal which will be useful later), $L(\omega_i)$ is radiance of environmental map and $(\omega_i \cdot n)^+$ is the cosine term together with the visibility([that what the $+$ is for][2]) i.e. $(\omega_i \cdot n)^+=0$ if $(\omega_i \cdot n)&lt;0$&#xD;&#xA;&#xD;&#xA;We estimate this integral by generating $N$ samples  $\omega_i^1,\dots,\omega_i^N$ with the respect to the probability density function $p(\omega_i)$, the estimator is&#xD;&#xA;$$&#xD;&#xA;I \approx \frac1N \sum_{k=1}^N \frac{f(\omega_i^k,\omega_o,n) \, L(\omega_i^k) \,(\omega_i^k\cdot n)^+ }{p(\omega_i^k)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The question is: How do we choose the pdf $p$ such that we are able to generate the samples in acceptable time and the variance of the above estimator is reasonably small.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;**&lt;s&gt;Best&lt;/s&gt; method** Pick $p$ proportional to the integrand&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) \sim f(\omega_i,\omega_o,n) \, L(\omega_i) \,(\omega_i\cdot n)^+ &#xD;&#xA;$$&#xD;&#xA;But most of the times it is very expensive to generate a sample according to this pdf, so it is not useful in practice.&#xD;&#xA;&#xD;&#xA;Methods suggested by OP:&#xD;&#xA;&#xD;&#xA;**Method one**: Choose $p$ proportional to the cosine term&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) \sim (\omega_i\cdot n)^+&#xD;&#xA;$$&#xD;&#xA;**Method two**: Choose $p$ proportional to the EM&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) \sim L(\omega_i)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Based on the names of mentioned papers I can partially guess what they do(unfortunately I do not have the time and energy to read them right now). But before discussing what they most probably do, let's talk about power series a little bit :D&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If we have a function of one real variable e.g. $f(x)$. Then if it is well behaved then it can be expanded into a power series&#xD;&#xA;$$&#xD;&#xA;f(x) = \sum_{k=0}^\infty a_k x^k&#xD;&#xA;$$&#xD;&#xA;Where $a_k$ are constants. This can be used to approximate $f$ by truncating the sum at some step $n$&#xD;&#xA;$$&#xD;&#xA;f(x) \approx \sum_{k=0}^n a_k x^k&#xD;&#xA;$$&#xD;&#xA;If $n$ is sufficiently high then the error is really small.&#xD;&#xA;&#xD;&#xA;Now if we have function in two variables e.g. $f(x,y)$ we can expand it only in the first argument&#xD;&#xA;$$&#xD;&#xA;f(x,y) = \sum_{k=0}^\infty b_k(y) \, x^k&#xD;&#xA;$$&#xD;&#xA;where  $b_k(y)$ are functions only in $y$. It can be also expanded in both arguments&#xD;&#xA;$$&#xD;&#xA;f(x,y) = \sum_{k,l=0}^\infty c_{kl} x^k y^l&#xD;&#xA;$$&#xD;&#xA;where $c_{kl}$ are constants. So function with real arguments can be expanded as sum of powers of that argument. Something similar can be done for functions defined on sphere.&#xD;&#xA;&#xD;&#xA;Now, let's have a function defined on sphere e.g. $f(\omega)$. Such a function can be also expanded in similar fashion as function of one real parameter&#xD;&#xA;$$&#xD;&#xA;f(\omega) =\sum_{k=0}^\infty \alpha_k S_k(\omega)&#xD;&#xA;$$&#xD;&#xA;where $\alpha_k$ are constants and $S_k(\omega)$ are [spherical harmonics][3]. Spherical harmonics are normally indexed by two indices and are written as function in spherical coordinates but that is not important here. The important thing is that $f$ can be written as a sum of some known functions.&#xD;&#xA;&#xD;&#xA;Now function which takes two points on sphere e.g. $f(\omega,\omega')$ can be expanded only in its first arguments&#xD;&#xA;$$&#xD;&#xA;f(\omega,\omega') = \sum_{k=0}^\infty \beta_k(\omega') \, S_k(\omega)&#xD;&#xA;$$&#xD;&#xA;or in both its arguments&#xD;&#xA;$$&#xD;&#xA;f(\omega,\omega') = \sum_{k,l=0}^\infty \gamma_{kl} \, S_k(\omega)S_l(\omega')&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So how is this all useful?&#xD;&#xA;&#xD;&#xA;I propose the  **CMUNSM**(Crazy mental useless no sampling method):&#xD;&#xA;Lets assume that we have expansions for all the function i.e.&#xD;&#xA;\begin{align}&#xD;&#xA;f(\omega_i,\omega_o,n) &amp;= \sum_{k,l,m=0}^\infty \alpha_{klm} S_k(\omega_i)S_l(\omega_o) S_m(n) \\&#xD;&#xA;L(\omega_i ) &amp;= \sum_{n=0}^\infty \beta_n S_n(\omega) \\&#xD;&#xA;(\omega_i\cdot n)^+ &amp;= \sum_{p,q=0}^\infty \gamma_{pq} S_p(\omega_i)S_q(n)&#xD;&#xA;\end{align}&#xD;&#xA;If we plug this into the integral we get&#xD;&#xA;$$&#xD;&#xA;I = \sum_{k,l,m,n,p,q=0}^\infty \alpha_{klm} \beta_n  \gamma_{pq} S_l(\omega_o) S_m(n) S_q(n) \int_{S^2} S_k(\omega_i) S_n(\omega)  S_p(\omega_i) d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Actually we no longer need Monte Carlo because we can calculate values of the integrals $\int_{S^2} S_k(\omega_i) S_n(\omega)  S_p(\omega_i) d\omega_i$ beforehand and then evaluate the sum(actually approximate the sum, we would sum only first few terms) and we get desired result.&#xD;&#xA;&#xD;&#xA;This is all nice **but** we might not know the expansions of BSDF or environmental map or the expansions converge very slowly therefore we would have to take a lots of terms in the sum to get reasonably accurate answer.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So the idea is not to expand in all arguments. One method which might be worth investigating would be to ignore BSDF and expand only the environmental map i.e.&#xD;&#xA;$$&#xD;&#xA;L(\omega_i) \approx \sum_{n=0}^K \beta_n S_n(\omega_i)&#xD;&#xA;$$&#xD;&#xA;this would lead to pdf:&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) \sim \sum_{n=0}^K \beta_n S_n(\omega_i) (\omega \cdot n)^+&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;We already know how to do this for $K=0$, this is nothing but the **method one**. My guess is, it is done in one of the papers for higher $K$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Further extensions. You can expand different functions in different arguments and do similar stuff as above. Another thing is, that you can expand in different basis, i.e. do not use spherical harmonics but different functions.&#xD;&#xA;&#xD;&#xA;So this is my take on the topic, I hope you have found it at least a little bit useful and now I'm off to GoT and bed.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation#Equation_form&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Positive_and_negative_parts&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Spherical_harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="5877" PostHistoryTypeId="2" PostId="2452" RevisionGUID="08ee4a41-5121-4f3c-9c1f-acc3f12dbeba" CreationDate="2016-05-16T21:02:48.873" UserId="100" Text="Generally edge detection boils down to detect areas of the image with high gradient value. &#xD;&#xA;&#xD;&#xA;In our case we can crudely see the gradient as the derivative of the image function, therefore the magnitude of the gradient gives you an information on *how much* your image changes locally (in regards of neighbouring pixels/texels).&lt;br/&gt; Now, an edge is as you say an indication of discontinuity, so now that we defined the gradient is clear that this info is all we need. Once we find the gradient of an image, it's just a matter of applying a threshold to it to obtain a binary value edge/non-edge. &#xD;&#xA;&#xD;&#xA;How do you find this gradient is really what you are asking and I am yet to answer :) &#xD;&#xA;&#xD;&#xA;Lots of ways! Here a couple :) &#xD;&#xA;&#xD;&#xA;# Built in shader functions #&#xD;&#xA;&#xD;&#xA;Both hlsl and glsl offer derivative functions. In GLSL you have [dFdx and dFdy][1] that give you respectively gradient information in x and y direction. Typically these functions are evaluated in a block of 2x2 fragments.  &#xD;&#xA;Unless you are interested in a single direction, a good way to have a compact result that indicates how strong is the gradient in the region is [fwidth][2] that gives you nothing else but the sum of the absolute value of dFdy and dFdy. &lt;br&gt;You are likely to be interested in an edge on the overall image rather than on a specific channel, so you might want to transform your image function to luma. With this in mind,when it comes to edge detection your shader could include something to the like of:&#xD;&#xA;&#xD;&#xA;      float Luminance = dot(yourFinalColour,vec3(0.2126, 0.7152, 0.0722));&#xD;&#xA;      float Gradient = fwidth(Luminance);&#xD;&#xA;      float isEdge = Gradient &gt; threshold;&#xD;&#xA;&#xD;&#xA;With an high threshold you will find coarser edges and you might miss some, conversely, with a low threshold you might detect false edges. You have to experiment to find the threshold that better suits your needs. &#xD;&#xA;&#xD;&#xA;*The reason why these functions work is worth mentioning but I don't have time for it now, I am likely to update this answer later on :)*&#xD;&#xA;&#xD;&#xA;# Screen space post-process #&#xD;&#xA;&#xD;&#xA;You could fancier than this, now the field of Edge detection in image processing is immense. I could cite you tens of good ways to detect edge detection according to your needs, but let's keep it simple for now, if you are interested I can cite you more options!&#xD;&#xA;&#xD;&#xA;So the idea would be similar to the one above, with the difference that you could look at a wider neighbourhood. Typically, you run a convolution over your image with a kernel that gives you as a result a good gradient info. &lt;br&gt; A very common choice is the Sobel kernel&#xD;&#xA;&#xD;&#xA; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Which respectively give you gradients in x and y directions: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;You can get the single value out of the gradient as $G = \sqrt{(GradientResult_x)^2 + (GradientResult_y)^2}$ &lt;br&gt;And then threshold as shown above.&#xD;&#xA;&#xD;&#xA;This kernel as you can see give more weight to the central pixel, so effectively is computing the gradient + a bit of smoothing. &#xD;&#xA;&#xD;&#xA;The above works quite well, but if you don't like the smoothing you can use the Prewitt kernels: &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;(Note I am in a rush, will write proper formatted text instead of images soon! )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Really there are plenty more kernels and techniques to find edge detection in an image process-y way rather than real time graphics, so I have excluded more convoluted (pun not intended) methods as probably you'd be just fine with dFdx/y functions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/dFdx.xhtml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man/html/fwidth.xhtml&#xD;&#xA;  [3]: https://i.stack.imgur.com/kXrkd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gCQgw.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/tQ5WJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5878" PostHistoryTypeId="5" PostId="2452" RevisionGUID="26d818e9-7af3-4fbf-b9d2-f8981772d2ab" CreationDate="2016-05-16T21:10:12.483" UserId="100" Comment="added 842 characters in body" Text="Generally edge detection boils down to detect areas of the image with high gradient value. &#xD;&#xA;&#xD;&#xA;In our case we can crudely see the gradient as the derivative of the image function, therefore the magnitude of the gradient gives you an information on *how much* your image changes locally (in regards of neighbouring pixels/texels).&lt;br/&gt; Now, an edge is as you say an indication of discontinuity, so now that we defined the gradient is clear that this info is all we need. Once we find the gradient of an image, it's just a matter of applying a threshold to it to obtain a binary value edge/non-edge. &#xD;&#xA;&#xD;&#xA;How do you find this gradient is really what you are asking and I am yet to answer :) &#xD;&#xA;&#xD;&#xA;Lots of ways! Here a couple :) &#xD;&#xA;&#xD;&#xA;# Built in shader functions #&#xD;&#xA;&#xD;&#xA;Both hlsl and glsl offer derivative functions. In GLSL you have [dFdx and dFdy][1] that give you respectively gradient information in x and y direction. Typically these functions are evaluated in a block of 2x2 fragments.  &#xD;&#xA;Unless you are interested in a single direction, a good way to have a compact result that indicates how strong is the gradient in the region is [fwidth][2] that gives you nothing else but the sum of the absolute value of dFdy and dFdy. &lt;br&gt;You are likely to be interested in an edge on the overall image rather than on a specific channel, so you might want to transform your image function to luma. With this in mind,when it comes to edge detection your shader could include something to the like of:&#xD;&#xA;&#xD;&#xA;      float luminance = dot(yourFinalColour,vec3(0.2126, 0.7152, 0.0722));&#xD;&#xA;      float gradient = fwidth(luminance );&#xD;&#xA;      float isEdge = gradient &gt; threshold;&#xD;&#xA;&#xD;&#xA;With an high threshold you will find coarser edges and you might miss some, conversely, with a low threshold you might detect false edges. You have to experiment to find the threshold that better suits your needs. &#xD;&#xA;&#xD;&#xA;*The reason why these functions work is worth mentioning but I don't have time for it now, I am likely to update this answer later on :)*&#xD;&#xA;&#xD;&#xA;# Screen space post-process #&#xD;&#xA;&#xD;&#xA;You could fancier than this, now the field of Edge detection in image processing is immense. I could cite you tens of good ways to detect edge detection according to your needs, but let's keep it simple for now, if you are interested I can cite you more options!&#xD;&#xA;&#xD;&#xA;So the idea would be similar to the one above, with the difference that you could look at a wider neighbourhood. Typically, you run a convolution over your image with a kernel that gives you as a result a good gradient info. &lt;br&gt; A very common choice is the Sobel kernel&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Which respectively give you gradients in x and y directions: &#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![From an old pdf I wrote a long time ago.][4]][4]&#xD;&#xA;&#xD;&#xA;You can get the single value out of the gradient as $ GradientMagnitude = \sqrt{ (Gradient_x) ^ 2 + (Gradient_y) ^ 2 } $ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then you can threshold as the same way I mentioned above.&#xD;&#xA;&#xD;&#xA;This kernel as you can see give more weight to the central pixel, so effectively is computing the gradient + a bit of smoothing which traditionally helps (often the image is gaussian blurred to eliminate small edges). &#xD;&#xA;&#xD;&#xA;The above works quite well, but if you don't like the smoothing you can use the Prewitt kernels: &#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;(Note I am in a rush, will write proper formatted text instead of images soon! )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Really there are plenty more kernels and techniques to find edge detection in an image process-y way rather than real time graphics, so I have excluded more convoluted (pun not intended) methods as probably you'd be just fine with dFdx/y functions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/dFdx.xhtml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man/html/fwidth.xhtml&#xD;&#xA;  [3]: https://i.stack.imgur.com/kXrkd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gCQgw.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/tQ5WJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5879" PostHistoryTypeId="5" PostId="2432" RevisionGUID="aba60076-3de3-459e-9aaa-e0876699e3f5" CreationDate="2016-05-16T21:29:20.397" UserId="3075" Comment="added 47 characters in body" Text="Say the point light is at $P_L$, the shading is happening at $P_S$&#xD;&#xA;&#xD;&#xA;It's true that the radiance is constant along a shadow ray $P_L \rightarrow P_S$, but that's not the key property for solving the rendering equation at $P_S$. &#xD;&#xA;&#xD;&#xA;The rendering equation, somewhat simplified, is: $L_o(\omega_o) = L_e(\omega_o) + \int_{\Omega} \, f_r(\omega_i, \omega_o)\, L_i(\omega_i)\, (n \cdot \omega_i) \, d \omega_i $&#xD;&#xA;&#xD;&#xA;While $L_o$ is expressed in radiance, you are actually integrating the _irradiance_ $L_i$ of the incoming light at $P_S$, which is expressed in $Wm^{-2}$. The incoming *radiance* -- call it $\hat{L}_i$ -- is in $W m^{-2} sr^{-1}$ and, while constant along the shadow ray, it is not directly relevant. The difference between $\hat{L}_i$ and $L_i$ is a $1/r^2$ term since the area of 1 $sr$ increases quadratically with distance from $P_L$ ." ContentLicense="CC BY-SA 3.0" />
  <row Id="5880" PostHistoryTypeId="5" PostId="2452" RevisionGUID="a89a4c09-3de9-4d51-8ed6-44340cc4713b" CreationDate="2016-05-16T21:49:48.597" UserId="100" Comment="added 63 characters in body" Text="Generally edge detection boils down to detect areas of the image with high gradient value. &#xD;&#xA;&#xD;&#xA;In our case we can crudely see the gradient as the derivative of the image function, therefore the magnitude of the gradient gives you an information on *how much* your image changes locally (in regards of neighbouring pixels/texels).&lt;br/&gt; Now, an edge is as you say an indication of discontinuity, so now that we defined the gradient is clear that this info is all we need. Once we find the gradient of an image, it's just a matter of applying a threshold to it to obtain a binary value edge/non-edge. &#xD;&#xA;&#xD;&#xA;How do you find this gradient is really what you are asking and I am yet to answer :) &#xD;&#xA;&#xD;&#xA;Lots of ways! Here a couple :) &#xD;&#xA;&#xD;&#xA;# Built in shader functions #&#xD;&#xA;&#xD;&#xA;Both hlsl and glsl offer derivative functions. In GLSL you have [dFdx and dFdy][1] that give you respectively gradient information in x and y direction. Typically these functions are evaluated in a block of 2x2 fragments.  &#xD;&#xA;Unless you are interested in a single direction, a good way to have a compact result that indicates how strong is the gradient in the region is [fwidth][2] that gives you nothing else but the sum of the absolute value of dFdy and dFdy. &lt;br&gt;You are likely to be interested in an edge on the overall image rather than on a specific channel, so you might want to transform your image function to luma. With this in mind,when it comes to edge detection your shader could include something to the like of:&#xD;&#xA;&#xD;&#xA;      float luminance = dot(yourFinalColour,vec3(0.2126, 0.7152, 0.0722));&#xD;&#xA;      float gradient = fwidth(luminance );&#xD;&#xA;      float isEdge = gradient &gt; threshold;&#xD;&#xA;&#xD;&#xA;With an high threshold you will find coarser edges and you might miss some, conversely, with a low threshold you might detect false edges. You have to experiment to find the threshold that better suits your needs. &#xD;&#xA;&#xD;&#xA;*The reason why these functions work is worth mentioning but I don't have time for it now, I am likely to update this answer later on :)*&#xD;&#xA;&#xD;&#xA;# Screen space post-process #&#xD;&#xA;&#xD;&#xA;You could go fancier than this, now the field of Edge detection in image processing is immense. I could cite you tens of good ways to detect edge detection according to your needs, but let's keep it simple for now, if you are interested I can cite you more options!&#xD;&#xA;&#xD;&#xA;So the idea would be similar to the one above, with the difference that you could look at a wider neighbourhood and use a set of weights on sorrounding samples if you want. Typically, you run a convolution over your image with a kernel that gives you as a result a good gradient info. &lt;br&gt; A very common choice is the Sobel kernel&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Which respectively give you gradients in x and y directions: &#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![From an old pdf I wrote a long time ago.][4]][4]&#xD;&#xA;&#xD;&#xA;You can get the single value out of the gradient as $ GradientMagnitude = \sqrt{ (Gradient_x) ^ 2 + (Gradient_y) ^ 2 } $ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then you can threshold as the same way I mentioned above.&#xD;&#xA;&#xD;&#xA;This kernel as you can see give more weight to the central pixel, so effectively is computing the gradient + a bit of smoothing which traditionally helps (often the image is gaussian blurred to eliminate small edges). &#xD;&#xA;&#xD;&#xA;The above works quite well, but if you don't like the smoothing you can use the Prewitt kernels: &#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;(Note I am in a rush, will write proper formatted text instead of images soon! )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Really there are plenty more kernels and techniques to find edge detection in an image process-y way rather than real time graphics, so I have excluded more convoluted (pun not intended) methods as probably you'd be just fine with dFdx/y functions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man/html/dFdx.xhtml&#xD;&#xA;  [2]: https://www.opengl.org/sdk/docs/man/html/fwidth.xhtml&#xD;&#xA;  [3]: https://i.stack.imgur.com/kXrkd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gCQgw.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/tQ5WJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5881" PostHistoryTypeId="5" PostId="2449" RevisionGUID="fe6d82e8-bbab-4020-b6c8-0d18e458bf6c" CreationDate="2016-05-16T21:52:56.627" UserId="48" Comment="update citation" Text="The interpolation looks fine. The main problem here is that the hash function you're using isn't very good. If I look at just one octave, and visualize the hash result by outputting `hash(PT).x`, I get something like this:&#xD;&#xA;&#xD;&#xA;[![bad hash function][1]][1]&#xD;&#xA;&#xD;&#xA;This is supposed to be completely random per grid square, but you can see that it has a lot of diagonal line patterns in it (it almost looks like a checkerboard), so it's not a very random hash, and those patterns will show up in the noise produced by it.&#xD;&#xA;&#xD;&#xA;The other problem is that your hash only returns gradient vectors in [0, 1], while they should be in [&amp;minus;1, 1] to get gradients in all directions. That part's easy to fix by remapping.&#xD;&#xA;&#xD;&#xA;To fix those problems, I switched the code to use this hash function (which I learned from Mikkel Gjoel, and [is probably due to a paper by W.J.J. Rey](http://stackoverflow.com/questions/12964279/whats-the-origin-of-this-glsl-rand-one-liner/)):&#xD;&#xA;&#xD;&#xA;    vec2 hash(vec2 co) {&#xD;&#xA;        float m = dot(co, vec2(12.9898, 78.233));&#xD;&#xA;        return fract(vec2(sin(m),cos(m))* 43758.5453) * 2. - 1.;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note that due to the trig functions it's going to be a bit more expensive than your version. However, it considerably improves the appearance of the resulting noise:&#xD;&#xA;&#xD;&#xA;[![fbm noise with better hash function][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LcFJV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ND8Es.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5883" PostHistoryTypeId="2" PostId="2453" RevisionGUID="7243ee80-e938-40da-a397-f52c355f59ca" CreationDate="2016-05-17T08:15:04.127" UserId="386" Text="I know that fragments are rasterized in a 2x2 quad. That's why the seam between two triangles can be rasterized twice. At least [that article][1] states this. I wonder is it still true today on modern hardware?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.humus.name/index.php?page=Comments&amp;ID=228" ContentLicense="CC BY-SA 3.0" />
  <row Id="5884" PostHistoryTypeId="1" PostId="2453" RevisionGUID="7243ee80-e938-40da-a397-f52c355f59ca" CreationDate="2016-05-17T08:15:04.127" UserId="386" Text="Double rasterization work on triangles edges." ContentLicense="CC BY-SA 3.0" />
  <row Id="5885" PostHistoryTypeId="3" PostId="2453" RevisionGUID="7243ee80-e938-40da-a397-f52c355f59ca" CreationDate="2016-05-17T08:15:04.127" UserId="386" Text="|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5886" PostHistoryTypeId="6" PostId="2419" RevisionGUID="b9022ec1-2fa5-4302-b336-b6c0053d3d91" CreationDate="2016-05-17T15:35:18.937" UserId="127" Comment="edited tags" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5887" PostHistoryTypeId="2" PostId="2454" RevisionGUID="4516c60b-3712-457e-9a54-90787d731fb1" CreationDate="2016-05-17T15:45:12.903" UserId="209" Text="&gt; That's why the seam between two triangles can be rasterized twice.&#xD;&#xA;&#xD;&#xA;The seam won't be *rasterized* twice because of the OpenGL or D3D fill/rasterisation rules. &#xD;&#xA;&#xD;&#xA;What I think Humus is alluding to is that a fragment shader may be executed multiple times on pixels spanning the shared edge, which just implies wasted effort.&#xD;&#xA;&#xD;&#xA;The moral of the story is &quot;avoid small or long/thin triangles if you want efficient rendering&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="5888" PostHistoryTypeId="2" PostId="2455" RevisionGUID="450af3ab-84c5-47d7-b954-4c8b370bcf75" CreationDate="2016-05-17T15:48:32.090" UserId="2712" Text="I am going through code snippet that reads in a triangular model, calculates &amp; store the normal with each Triangle object and eventually check the consistencies of winding order. Let us define a triangle with the vertices v1, v2 and v3. The face normal of the triangle is calculated as follows:&#xD;&#xA;&#xD;&#xA;    void calculateFaceNormal()&#xD;&#xA;    {&#xD;&#xA;       //vector from v3 to v1&#xD;&#xA;       double dx13, dy13, dz13;&#xD;&#xA;&#xD;&#xA;       //vector from v3 to v2&#xD;&#xA;       double dx23, dy23, dz23;&#xD;&#xA;&#xD;&#xA;		dx13 = v1.x_ - v3.x_;&#xD;&#xA;		dy13 = v1.y_ - v3.y_;&#xD;&#xA;		dz13 = v1.z_ - v3.z_;&#xD;&#xA;&#xD;&#xA;		dx23 = v2.x_ - v3.x_;&#xD;&#xA;		dy23 = v2.y_ - v3.y_;&#xD;&#xA;		dz23 = v2.z_ - v3.z_;&#xD;&#xA;&#xD;&#xA;		// Cross product gives normal.&#xD;&#xA;		x_ = dy13*dz23 - dy23*dz13;&#xD;&#xA;		y_ = dz13*dx23 - dz23*dx13;&#xD;&#xA;		z_ = dx13*dy23 - dx23*dy13;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Each Triangle object store the references of its neighboring triangles as follows:&#xD;&#xA;&#xD;&#xA;    class Triangle()&#xD;&#xA;    {&#xD;&#xA;      public:&#xD;&#xA;        .......&#xD;&#xA;        .......&#xD;&#xA;&#xD;&#xA;        const Triangle *edge12Granne_;&#xD;&#xA;        const Triangle *edge23Granne_;&#xD;&#xA;        const Triangle *edge31Granne_;&#xD;&#xA;&#xD;&#xA;        bool isGranne12NormalConsistent() const;&#xD;&#xA;        bool isGranne23NormalConsistent() const;&#xD;&#xA;        bool isGranne31NormalConsistent() const;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I am writing down only of the function whose definition is not clear to me and I believe that if someone could explain the theories behind it,I shall be able to understand the rest.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        bool Triangle::isGranne12NormalConsistent() const&#xD;&#xA;        {&#xD;&#xA;&#xD;&#xA;		  // Find opposing vertex in neighbour.&#xD;&#xA;		  if(edge12Granne_-&gt;edge12Granne_ == this)&#xD;&#xA;		  {&#xD;&#xA;&#xD;&#xA;            /*&#xD;&#xA;             * two triangle are neighbors to each other by&#xD;&#xA;             * the adjecent edge that constitutes both the&#xD;&#xA;             * triangles.&#xD;&#xA;             * */&#xD;&#xA;&#xD;&#xA;			  // v2 | w1&#xD;&#xA;			  // v1 | w2&#xD;&#xA;			  if(v1_.id_ == edge12Granne_-&gt;v2_.id_)&#xD;&#xA;			  {&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			  }&#xD;&#xA;			  else&#xD;&#xA;			  {&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			  }&#xD;&#xA;		  }&#xD;&#xA;		  else if(edge12Granne_-&gt;edge23Granne_ == this)&#xD;&#xA;		  {&#xD;&#xA;			// v2 | w2&#xD;&#xA;			// v1 | w3&#xD;&#xA;			if(v1_.id_ == edge12Granne_-&gt;v3_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// v2 | w3&#xD;&#xA;			// v1 | w1&#xD;&#xA;			if(v1_.id_ == edge12Granne_-&gt;v1_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5889" PostHistoryTypeId="1" PostId="2455" RevisionGUID="450af3ab-84c5-47d7-b954-4c8b370bcf75" CreationDate="2016-05-17T15:48:32.090" UserId="2712" Text="face normal consistencies" ContentLicense="CC BY-SA 3.0" />
  <row Id="5890" PostHistoryTypeId="3" PostId="2455" RevisionGUID="450af3ab-84c5-47d7-b954-4c8b370bcf75" CreationDate="2016-05-17T15:48:32.090" UserId="2712" Text="|computer-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5891" PostHistoryTypeId="6" PostId="2455" RevisionGUID="4823f5e2-0023-4358-b624-60895ba84700" CreationDate="2016-05-17T15:59:39.493" UserId="127" Comment="edited tags" Text="|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5892" PostHistoryTypeId="2" PostId="2456" RevisionGUID="ecc216eb-5ccb-488a-a865-cf25218f7448" CreationDate="2016-05-17T16:33:28.920" UserId="3383" Text="I have some experience programming geometry and compute shaders - but never adventured myself in really playing with the fragment shaders. Currently, I am trying to better understand how they work and their potential. One of the things I have read in multiple places is that a fragment (i.e. a screen pixel) cannot extend beyond itself within the fragment shader. Which means, a given fragment being iterated can only affect itself.&#xD;&#xA;&#xD;&#xA;Therefore, and for the sake of learning, I would like to know if the following is possible (and if it is, how, in general lines, can it be achieved). Suppose we have, for the sake of simplicity, a point-mesh consisting of only two vertices (located in the 3D World space). Can we program a shader in a way such that each of these two vertices would be painted on screen at their exact WorldToViewport position, but also that a circle around each of them of radius=R is also painted in the surrounding pixels even if they extend beyond the original mesh to which the shader is attached? Like in the figure below (where the red square inthe center of the circles represents the vertices painted on screen):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If that is possible, can a shader also be programmed in such a way that these circles that extend beyond the vertices influence the color (RGBA) of each other? Like in the figure below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As I said, if these are possible things, I would love to hear a bit of how to achieve such a thing - either in conceptual or practical terms. Is it done in the fragment shader, or has to be calculated before at the vertex or geometry shaders? How to calculate and pass &quot;additional fragments&quot; that extend beyond those fragments occupied by the mesh body?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GV3QO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CtdIW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5893" PostHistoryTypeId="1" PostId="2456" RevisionGUID="ecc216eb-5ccb-488a-a865-cf25218f7448" CreationDate="2016-05-17T16:33:28.920" UserId="3383" Text="Can (and how so) shaders paint screen pixels beyond those that occupied by the shaded mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5894" PostHistoryTypeId="3" PostId="2456" RevisionGUID="ecc216eb-5ccb-488a-a865-cf25218f7448" CreationDate="2016-05-17T16:33:28.920" UserId="3383" Text="|rendering|shader|pixel-shader|drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5895" PostHistoryTypeId="5" PostId="2455" RevisionGUID="7cb76320-d863-4a97-9c79-e235270679fa" CreationDate="2016-05-17T18:20:38.387" UserId="2712" Comment="added 32 characters in body" Text="I am going through code snippet that reads in a triangular model, calculates &amp; store the normal with each Triangle object and eventually check the consistencies of winding order. Let us define a triangle with the vertices v1, v2 and v3. The face normal of the triangle is calculated as follows:&#xD;&#xA;&#xD;&#xA;    void calculateFaceNormal()&#xD;&#xA;    {&#xD;&#xA;       //vector from v3 to v1&#xD;&#xA;       double dx13, dy13, dz13;&#xD;&#xA;&#xD;&#xA;       //vector from v3 to v2&#xD;&#xA;       double dx23, dy23, dz23;&#xD;&#xA;&#xD;&#xA;		dx13 = v1.x_ - v3.x_;&#xD;&#xA;		dy13 = v1.y_ - v3.y_;&#xD;&#xA;		dz13 = v1.z_ - v3.z_;&#xD;&#xA;&#xD;&#xA;		dx23 = v2.x_ - v3.x_;&#xD;&#xA;		dy23 = v2.y_ - v3.y_;&#xD;&#xA;		dz23 = v2.z_ - v3.z_;&#xD;&#xA;&#xD;&#xA;		// Cross product gives normal.&#xD;&#xA;		x_ = dy13*dz23 - dy23*dz13;&#xD;&#xA;		y_ = dz13*dx23 - dz23*dx13;&#xD;&#xA;		z_ = dx13*dy23 - dx23*dy13;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Each Triangle object store the references of its neighboring triangles as follows:&#xD;&#xA;&#xD;&#xA;    class Triangle()&#xD;&#xA;    {&#xD;&#xA;      public:&#xD;&#xA;        .......&#xD;&#xA;        .......&#xD;&#xA;&#xD;&#xA;        const Triangle *edge12Granne_;&#xD;&#xA;        const Triangle *edge23Granne_;&#xD;&#xA;        const Triangle *edge31Granne_;&#xD;&#xA;&#xD;&#xA;        bool isGranne12NormalConsistent() const;&#xD;&#xA;        bool isGranne23NormalConsistent() const;&#xD;&#xA;        bool isGranne31NormalConsistent() const;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I am writing down only one of the functions whose definition is not clear to me and I believe that if someone could explain the theories behind it,I shall be able to understand the rest of the other two functions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        bool Triangle::isGranne12NormalConsistent() const&#xD;&#xA;        {&#xD;&#xA;&#xD;&#xA;		  // Find opposing vertex in neighbour.&#xD;&#xA;		  if(edge12Granne_-&gt;edge12Granne_ == this)&#xD;&#xA;		  {&#xD;&#xA;&#xD;&#xA;            /*&#xD;&#xA;             * two triangle are neighbors to each other by&#xD;&#xA;             * the adjecent edge that constitutes both the&#xD;&#xA;             * triangles.&#xD;&#xA;             * */&#xD;&#xA;&#xD;&#xA;			  // v2 | w1&#xD;&#xA;			  // v1 | w2&#xD;&#xA;			  if(v1_.id_ == edge12Granne_-&gt;v2_.id_)&#xD;&#xA;			  {&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			  }&#xD;&#xA;			  else&#xD;&#xA;			  {&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			  }&#xD;&#xA;		  }&#xD;&#xA;		  else if(edge12Granne_-&gt;edge23Granne_ == this)&#xD;&#xA;		  {&#xD;&#xA;			// v2 | w2&#xD;&#xA;			// v1 | w3&#xD;&#xA;			if(v1_.id_ == edge12Granne_-&gt;v3_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// v2 | w3&#xD;&#xA;			// v1 | w1&#xD;&#xA;			if(v1_.id_ == edge12Granne_-&gt;v1_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5896" PostHistoryTypeId="2" PostId="2457" RevisionGUID="ad671e44-097f-4320-9d06-ba8d2d0f57fa" CreationDate="2016-05-17T23:55:45.460" UserId="3385" Text="So I have been wanting to make a rendering engine as a summer project. I'd like to shoot for photo-realism of static scenes rather than real time dynamic game like graphics. So in my research I came across two major techniques for going about this. One is to attempt to directly solve the rendering equation with specialized numeric methods like bidirectional path tracing. Another is the well known ray tracing technique. Ray tracing is a) much simpler and b) more efficient. Additionally it seems as though some kind of interpolation/de-noising is needed to make the images look properly smooth when path tracing techniques are used.&#xD;&#xA;&#xD;&#xA;I understand recursive ray tracing to be an algorithm in which rays are shot out from the eye and collide with objects in the space. When they do more rays are shot from that point to calculate the lighting at that point.&#xD;&#xA;&#xD;&#xA;I understand path tracing to be trying to find paths to the viewing plane from light sources. If enough of these paths are sampled without bias then you can use these paths to perform monte carlo integration over the space using the found paths as your sample points.&#xD;&#xA;&#xD;&#xA;What effects are captured by path tracing that are not captured by ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="5897" PostHistoryTypeId="1" PostId="2457" RevisionGUID="ad671e44-097f-4320-9d06-ba8d2d0f57fa" CreationDate="2016-05-17T23:55:45.460" UserId="3385" Text="What effects does path tracing capture that recursive ray tracing does not?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5898" PostHistoryTypeId="3" PostId="2457" RevisionGUID="ad671e44-097f-4320-9d06-ba8d2d0f57fa" CreationDate="2016-05-17T23:55:45.460" UserId="3385" Text="|raytracing|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5899" PostHistoryTypeId="2" PostId="2458" RevisionGUID="eb9e60f7-01ca-41eb-b4c1-2a137fbb03ad" CreationDate="2016-05-18T03:34:20.290" UserId="3386" Text="It is true to on today's GPUs, unless one or more vendors has implemented a technique such as this:&#xD;&#xA;http://graphics.stanford.edu/papers/fragmerging/shade_sig10.pdf&#xD;&#xA;&#xD;&#xA;To clarify, rasterization is not being done multiple times, or redundantly - rather it is the shading work that is done redundantly. Each 2x2 quad will be shaded once for every triangle that covers at least one sub pixel sample in that 2x2 quad. So, for 4x MSAA, that could be as many as 16 times if every sample covers a different (very small) triangle." ContentLicense="CC BY-SA 3.0" />
  <row Id="5906" PostHistoryTypeId="2" PostId="2460" RevisionGUID="3a99192b-42e1-4d38-b7be-1fc406841758" CreationDate="2016-05-18T13:39:55.867" UserId="196" Text="Generally speaking, **path tracing** removes a number of assumptions that ray tracing makes. Ray tracing usually assumes that there is no **indirect lighting** (or that indirect lighting can be approximated by a constant function), because handling indirect lighting would require casting many additional rays whenever you shade an intersection point. Ray tracing usually assumes that there is no such thing as **non-glossy reflection**, because while it is fairly easy to handle glossy/mirror reflection (you reflect the ray and continue with the raycast), if you have non-glossy specular reflection you have a problem very much like indirect lighting: you need to trace a bunch more rays and then do lighting wherever those rays hit. Ray tracing also usually assumes that there are no **area lights**, because it is very cheap to cast a single ray towards a light to determine if an intersection point is in shadow, but if you have an area light you generally need to cast multiple rays towards different points on that light to determine the *amount* that the intersection point is shadowed.&#xD;&#xA;&#xD;&#xA;And as soon as you need to break any of those assumptions with ray tracing, you now have a **sampling problem**: you need to decide how to distribute the many additional rays you need to trace in order to get an accurate result that doesn't have noticeable aliasing." ContentLicense="CC BY-SA 3.0" />
  <row Id="5907" PostHistoryTypeId="2" PostId="2461" RevisionGUID="0ca2b4ef-a69c-46d7-9326-757620ec58f3" CreationDate="2016-05-18T14:35:29.327" UserId="3069" Text="I am trying to implement my own Gradient Domain Path Tracer by following the code of this guy who already implemented it: &#xD;&#xA;&#xD;&#xA;https://gist.github.com/BachiLi/4f5c6e5a4fef5773dab1&#xD;&#xA;&#xD;&#xA;I already managed to go through various steps but I wanted to do something more. I expanded the code of in the reference by implementing next event estimation and here are some results.&#xD;&#xA;&#xD;&#xA;Normal Path Tracer image:&#xD;&#xA;&#xD;&#xA;[![Basic Path Tracer][1]][1]&#xD;&#xA;&#xD;&#xA;Gradient Domain resulting image:&#xD;&#xA;&#xD;&#xA;[![Gradient Domain image without Next Event Estimation][2]][2]&#xD;&#xA;&#xD;&#xA;Results are already good.. but as said before, I wanted something more. So I implemented Next Event Estimation and here is the result of the basic Path Tracer:&#xD;&#xA;&#xD;&#xA;[![Path Tracer with NEE][3]][3]&#xD;&#xA;&#xD;&#xA;Here is my code:&#xD;&#xA;&#xD;&#xA;    private Vector3 SampleWithNEE( Ray ray )&#xD;&#xA;    {&#xD;&#xA;	  // prepare&#xD;&#xA;	  Vector3 T = (1,1,1), E = (0,0,0), NL = (0,-1,0);&#xD;&#xA;	  int depth = 0;&#xD;&#xA;	  // random walk&#xD;&#xA;	  while (depth++ &lt; MAXDEPTH)&#xD;&#xA;	  {&#xD;&#xA;		// find nearest ray/scene intersection&#xD;&#xA;		Scene.Intersect( ray );&#xD;&#xA;		if (ray.objIdx == -1) break; //if there is no intersection&#xD;&#xA;		Vector3 I = ray.O + ray.t * ray.D; //go to the Hit Point on the scene&#xD;&#xA;		Material material = scene.GetMaterial( ray.objIdx, I );&#xD;&#xA;		if (material.emissive) //case of a light&#xD;&#xA;		{&#xD;&#xA;			E += material.diffuse;&#xD;&#xA;			break;&#xD;&#xA;		}&#xD;&#xA;		// next event estimation&#xD;&#xA;		Vector3 BRDF = material.diffuse * 1 / PI;&#xD;&#xA;		float f = RTTools.RandomFloat();&#xD;&#xA;		Vector3 L = Scene.RandomPointOnLight() - I;&#xD;&#xA;		float dist = L.Length();&#xD;&#xA;		L = Vector3.Normalize( L );&#xD;&#xA;		float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;		float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;		if (NdotL &gt; 0)&#xD;&#xA;		{&#xD;&#xA;			Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;			Scene.Intersect( r );&#xD;&#xA;			if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;			{&#xD;&#xA;				float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;				E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		// sample random direction on hemisphere&#xD;&#xA;		Vector3 R = DiffuseReflectionCosWeighted( ray.N );&#xD;&#xA;		float hemi_PDF = Vector3.Dot( R, ray.N ) / PI;&#xD;&#xA;		T *= (Vector3.Dot( R, ray.N ) / hemiPDF) * BRDF;&#xD;&#xA;		ray = new Ray( I + R * EPSILON, R, 1e34f );&#xD;&#xA;	  }&#xD;&#xA;	  return E;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Things work really fine and the results are shown with the picture above. One more thing: I have only diffuse surfaces in my scene. &#xD;&#xA;&#xD;&#xA;Now, the problem is that in this method I use 2 kind of PDF's:&#xD;&#xA;&#xD;&#xA; - one is given by randomly sampling the light in the Direct Lighting of the Next Event Estimation, indeed that **SolidAngle** is our PDF, or better 1/PDF. &#xD;&#xA; - while the second PDF is the one led by the use of **DiffuseReflectionCosWeighted** which brings a PDF equals to **CosTheta/PI**. &#xD;&#xA;&#xD;&#xA;Everything fine so far and for any implementation detail you can just look at my code but problems come with my Gradient Domain Path Tracer. Indeed, there, as also in the reference link above implemented by Tzu-Mao Li, I need the *final probability density of a whole path* to compute the final gradient image. How did I calculate it in case without Next Event Estimation (NEE) ? In that case (since I have only Diffuse surfaces) this probability is the product of **CosTheta / PI** at each bounce in the scene. Everything is fine and the resulting gradient image is shown above.&#xD;&#xA;&#xD;&#xA;Instead, in case I use NEE things don't work anymore because the Probability Density of my whole path changes and I don't manage to understand how it is. The resulting Gradient Domain Image with Next Event Estimation is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I need to understand how to calculate the final density probability of a path. Can you help me doing it? Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qPe9r.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/UyaZB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HdUSm.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/uTMGA.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5908" PostHistoryTypeId="1" PostId="2461" RevisionGUID="0ca2b4ef-a69c-46d7-9326-757620ec58f3" CreationDate="2016-05-18T14:35:29.327" UserId="3069" Text="Resulting Probabilty Density in Path Tracer for paths using Next Event Estimation" ContentLicense="CC BY-SA 3.0" />
  <row Id="5909" PostHistoryTypeId="3" PostId="2461" RevisionGUID="0ca2b4ef-a69c-46d7-9326-757620ec58f3" CreationDate="2016-05-18T14:35:29.327" UserId="3069" Text="|rendering|c++|physically-based|physics|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5911" PostHistoryTypeId="2" PostId="2462" RevisionGUID="4afc696c-edbc-443b-b72c-89a86099aab2" CreationDate="2016-05-19T01:19:21.283" UserId="2383" Text="I have mapped four rectangular point(R1-&gt;R4) to four quadrilateral points(Q1-&gt;Q4) to generate a perspective view.&#xD;&#xA;Now I have to translate quadrilateral in x and y direction while maintaing perspective view. How can I achieve this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5912" PostHistoryTypeId="1" PostId="2462" RevisionGUID="4afc696c-edbc-443b-b72c-89a86099aab2" CreationDate="2016-05-19T01:19:21.283" UserId="2383" Text="Perspective Translation Of Quadrilateral" ContentLicense="CC BY-SA 3.0" />
  <row Id="5913" PostHistoryTypeId="3" PostId="2462" RevisionGUID="4afc696c-edbc-443b-b72c-89a86099aab2" CreationDate="2016-05-19T01:19:21.283" UserId="2383" Text="|perspective|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5915" PostHistoryTypeId="2" PostId="2463" RevisionGUID="8f261587-605b-4458-b607-e36aedbd2b5c" CreationDate="2016-05-19T12:21:51.260" UserId="1810" Text="When you use linewidth or line antialiasing or pointwidth or pointsprites, OpenGL creates for you a small rectangle instead of the line or point, with texture coordinates. Nowadays you can even program this yourself using geometry shaders ot even the tesselator.&#xD;&#xA;&#xD;&#xA;A totally different approach is to use defered shading, using one geometric pass just to store information in the RGBAZ buffer, then a second pass than you run a an the pixels of the screen to do some process. (to act on all pixels, simlpy draw on full-screen rectangle).&#xD;&#xA;Nowadays you can even do the first pass as one or several &quot;render to texture&quot;, then MIPmap these textures, so that the final pass can easily access to less local values." ContentLicense="CC BY-SA 3.0" />
  <row Id="5916" PostHistoryTypeId="5" PostId="2450" RevisionGUID="a82f1132-5f7c-4132-93e7-a70d7926e5cf" CreationDate="2016-05-19T15:10:56.093" UserId="3377" Comment="added 264 characters in body" Text="I'd like to load arbitrary meshes and draw thick black lines along the edges to get a toon-shading like look.&#xD;&#xA;I managed to draw a black silhouette around the objects by using the stencil buffer. You can see the result here:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But what's missing are the black lines in the object itself. I thought about checking normal discontinuities: Checking if a neighbouring pixel has a different normal vector than the current one. If yes, an edge has been found. Unfortunately, I've no idea how I could implement this approach, neither in OpenGL nor in GLSL vertex/fragment shader.&#xD;&#xA;&#xD;&#xA;I'd be very happy for some help regarding this approach or any other regarding edge detection. &#xD;&#xA;&#xD;&#xA;Edit: I do not use any textures for my meshes.&#xD;&#xA;&#xD;&#xA;Too be more precise, I would like to create a CAD/CAM solution that looks as much as possible like this (taken from Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rPEIz.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/uIZW7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5918" PostHistoryTypeId="2" PostId="2464" RevisionGUID="1d9179d2-e7a4-411a-a0cb-adee218f1ef0" CreationDate="2016-05-19T17:41:41.510" UserId="3332" Text="Here's how I've solved this in the past:&#xD;&#xA;&#xD;&#xA; 1. Draw the first object (the one that should appear behind the other object) by depth testing but **not** depth writing&#xD;&#xA; 2. Draw the second object by depth testing and depth writing.  This won't cause z-fighting since we didn't write any depth in step 1.&#xD;&#xA; 3. Draw the first object by only writing to the depth buffer and **not** to the color buffer. This makes sure the depth buffer is up to date for any pixels that are covered by object 1 but not by object 2.&#xD;&#xA;&#xD;&#xA;Note, the objects need to be draw consecutively for this to work.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5919" PostHistoryTypeId="2" PostId="2465" RevisionGUID="280969f6-b6e3-4314-b64e-b5c4a8b4e4c9" CreationDate="2016-05-19T22:40:47.670" UserId="3386" Text="The best place to put a look up table for a GPU compute shader depends on the size of the lookup table, and the frequency/coherency of access. In your case (you mentioned 4kb), shared local memory would likely be best (assuming you do not need this memory for other purposes in the same kernel). This memory has different names in different APIs, but is the same architectural thing and follows the same performance guidelines:&#xD;&#xA;  &#xD;&#xA; + CUDA: threadgroup shared memory&#xD;&#xA; + DirectCompute: groupshared memory&#xD;&#xA; + OpenCL: local memory&#xD;&#xA; + Metal: threadgroup memory&#xD;&#xA; + OpenGL: shared memory&#xD;&#xA;&#xD;&#xA;Storing the lookup table in global memory as a read-only buffer may perform just as well, depending on the cache size(s) of the particular GPU you're running on.&#xD;&#xA;&#xD;&#xA;Note that I'm presuming this is a read-only lookup table. A read-write lookup table is a completely different beast, and you don't have any good options there." ContentLicense="CC BY-SA 3.0" />
  <row Id="5920" PostHistoryTypeId="5" PostId="2463" RevisionGUID="05c25d9c-80d5-43ee-a12e-b0500b2d4e6e" CreationDate="2016-05-20T07:07:12.043" UserId="1810" Comment="added 3 characters in body" Text="When you use linewidth or line antialiasing or pointwidth or pointsprites, OpenGL creates for you a small rectangle instead of the line or point, with texture coordinates. Nowadays you can even program this yourself using geometry shaders ot even the tesselator.&#xD;&#xA;&#xD;&#xA;A totally different approach is to use defered shading, using one geometric pass just to store information in the RGBAZ buffer, then a second pass than you run on all the pixels of the screen to do some process. (to act on all pixels, simply draw one full-screen rectangle).&#xD;&#xA;Nowadays you can even do the first pass as one or several &quot;render to texture&quot;, then MIPmap these textures, so that the final pass can easily access to less local values." ContentLicense="CC BY-SA 3.0" />
  <row Id="5921" PostHistoryTypeId="2" PostId="2466" RevisionGUID="617eefca-63c2-4f4e-9edd-273e6c96d821" CreationDate="2016-05-20T07:51:38.263" UserId="3401" Text="Given a triangle mesh, does there exist any algorithm to compute a base mesh (smaller in size than the triangle mesh) that could be subdivided multiple times to get back the original mesh (or an approximate of the original) ?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="5922" PostHistoryTypeId="1" PostId="2466" RevisionGUID="617eefca-63c2-4f4e-9edd-273e6c96d821" CreationDate="2016-05-20T07:51:38.263" UserId="3401" Text="Constructing base mesh for required subdivision surface" ContentLicense="CC BY-SA 3.0" />
  <row Id="5923" PostHistoryTypeId="3" PostId="2466" RevisionGUID="617eefca-63c2-4f4e-9edd-273e6c96d821" CreationDate="2016-05-20T07:51:38.263" UserId="3401" Text="|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5924" PostHistoryTypeId="6" PostId="2466" RevisionGUID="bd6ef790-397b-46b8-901b-d41daf314625" CreationDate="2016-05-20T09:43:18.833" UserId="3401" Comment="edited tags" Text="|compression|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5925" PostHistoryTypeId="5" PostId="2464" RevisionGUID="1435f517-590a-4c9c-9e9b-2debabf5e921" CreationDate="2016-05-20T13:51:31.210" UserId="3332" Comment="added 3 characters in body" Text="Here's how I've solved this in the past:&#xD;&#xA;&#xD;&#xA; 1. Draw the first object (the one that should appear behind the other object) by depth testing but **not** depth writing&#xD;&#xA; 2. Draw the second object by depth testing and depth writing.  This won't cause z-fighting since we didn't write any depth in step 1.  &#xD;&#xA; 3. Draw the first object by only writing to the depth buffer and **not** to the color buffer. This makes sure the depth buffer is up to date for any pixels that are covered by object 1 but not by object 2.&#xD;&#xA;&#xD;&#xA;Note, the objects need to be drawn consecutively for this to work.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5926" PostHistoryTypeId="2" PostId="2467" RevisionGUID="b90f12c4-2c70-4d25-a0e4-6bce88abbcd0" CreationDate="2016-05-20T14:02:05.440" UserId="3404" Text="Is there a way to make a difference between a photo of an actual object and a photo of an object through a computer or smartphone screen.&#xD;&#xA;&#xD;&#xA;For example: how can I detect that the second image is taken from a screen?&#xD;&#xA;&#xD;&#xA;[![Actual dog][1]][1]&#xD;&#xA;[![Screen dog][2]][2]&#xD;&#xA;&#xD;&#xA;Thank you very much!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6aTf2.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/6nH7M.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5927" PostHistoryTypeId="1" PostId="2467" RevisionGUID="b90f12c4-2c70-4d25-a0e4-6bce88abbcd0" CreationDate="2016-05-20T14:02:05.440" UserId="3404" Text="How to detect a screen in a photo" ContentLicense="CC BY-SA 3.0" />
  <row Id="5928" PostHistoryTypeId="3" PostId="2467" RevisionGUID="b90f12c4-2c70-4d25-a0e4-6bce88abbcd0" CreationDate="2016-05-20T14:02:05.440" UserId="3404" Text="|texture|lighting|color|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5929" PostHistoryTypeId="2" PostId="2468" RevisionGUID="5f7deaa8-81b3-4a15-b380-4657a0db2c76" CreationDate="2016-05-20T14:41:18.767" UserId="2712" Text="I am going though a functional source that have the following class:&#xD;&#xA;&#xD;&#xA;     class Point3D&#xD;&#xA;     {&#xD;&#xA;           int x ,y,z;&#xD;&#xA;&#xD;&#xA;           int vSize2() const&#xD;&#xA;           {&#xD;&#xA;               return x*x +&#xD;&#xA;	                  y*y +&#xD;&#xA;	                  z*z;&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;           int vSize() const&#xD;&#xA;           {&#xD;&#xA;             return sqrt(vSize2());&#xD;&#xA;           }           &#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is hard to understand the functionalities of the above two functions (vSize2() and vSize()). It seems to me that it is calculating the length between the point and the origin. &#xD;&#xA;&#xD;&#xA;Any thoughts ?&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="5930" PostHistoryTypeId="1" PostId="2468" RevisionGUID="5f7deaa8-81b3-4a15-b380-4657a0db2c76" CreationDate="2016-05-20T14:41:18.767" UserId="2712" Text="Is there any length of the a point?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5931" PostHistoryTypeId="3" PostId="2468" RevisionGUID="5f7deaa8-81b3-4a15-b380-4657a0db2c76" CreationDate="2016-05-20T14:41:18.767" UserId="2712" Text="|computer-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5932" PostHistoryTypeId="2" PostId="2469" RevisionGUID="be603054-da2d-4fe7-9e3c-cdfb57073795" CreationDate="2016-05-20T14:55:55.117" UserId="231" Text="No, a point does not have a length. A point is only a location - it has no extent in any direction.&#xD;&#xA;&#xD;&#xA;You are correct in guessing that the function `vSize()` returns the distance from the origin to the point. The other function, `vSize2()` returns the square of that distance. This is used in calculating the distance, and in some cases it may be useful to work directly with the square of the distance instead of the distance. This avoids calculating square roots, so can lead to improvements in speed and accuracy." ContentLicense="CC BY-SA 3.0" />
  <row Id="5933" PostHistoryTypeId="6" PostId="2468" RevisionGUID="d60501c7-1871-4329-a93f-1b2b9839ec09" CreationDate="2016-05-20T14:57:09.360" UserId="231" Comment="edited tags" Text="|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5934" PostHistoryTypeId="5" PostId="2468" RevisionGUID="373f7763-186a-4f06-9346-daaf36bd9c16" CreationDate="2016-05-20T15:31:28.283" UserId="231" Comment="Add syntax highlighting and correct minor typos" Text="I am going though a functional source that has the following class:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;     class Point3D&#xD;&#xA;     {&#xD;&#xA;           int x ,y,z;&#xD;&#xA;&#xD;&#xA;           int vSize2() const&#xD;&#xA;           {&#xD;&#xA;               return x*x +&#xD;&#xA;	                  y*y +&#xD;&#xA;	                  z*z;&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;           int vSize() const&#xD;&#xA;           {&#xD;&#xA;             return sqrt(vSize2());&#xD;&#xA;           }           &#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is hard to understand the functionalities of the above two functions (`vSize2()` and `vSize()`). It seems to me that it is calculating the length between the point and the origin. &#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5935" PostHistoryTypeId="4" PostId="2468" RevisionGUID="373f7763-186a-4f06-9346-daaf36bd9c16" CreationDate="2016-05-20T15:31:28.283" UserId="231" Comment="Add syntax highlighting and correct minor typos" Text="Does a point have a length?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5936" PostHistoryTypeId="5" PostId="2469" RevisionGUID="9db3f47c-bdfa-4b0a-a995-2ee5d05b185d" CreationDate="2016-05-20T15:52:07.877" UserId="231" Comment="Include Nero's point about accuracy" Text="No, a point does not have a length. A point is only a location - it has no extent in any direction.&#xD;&#xA;&#xD;&#xA;You are correct in guessing that the function `vSize()` returns the distance from the origin to the point. The other function, `vSize2()` returns the square of that distance. This is used in calculating the distance, and in some cases it may be useful to work directly with the square of the distance instead of the distance. This avoids calculating square roots, so can lead to improvements in speed and accuracy.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that as Nero points out, the functions are using only `int`s (integer variables and return values). The distance between a point and the origin is not in general an integer value, even if the coordinates of the point are all integers. The distance squared returned by `vSize2()` will be accurate, but the distance itself returned by `vSize()` will be accurate only to the nearest integer." ContentLicense="CC BY-SA 3.0" />
  <row Id="5937" PostHistoryTypeId="5" PostId="2325" RevisionGUID="99de814d-ccbd-4472-900a-5dd39a2238df" CreationDate="2016-05-20T20:26:14.153" UserId="310" Comment="Fix small typo" Text="In order to understand Russian Roulette, let's look at a very basic forward path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely mathematically unbiased, bounces *should* go to infinity. But this is unrealistic, and as you noted, not visually necessary; for most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.&#xD;&#xA;&#xD;&#xA;So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.&#xD;&#xA;&#xD;&#xA;That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20. &#xD;&#xA;[![2 Bounces from Disney's Big Hero 6][1]][1]&#xD;&#xA;[![9 Bounces from Disney's Big Hero 6][2]][2]&#xD;&#xA;&#xD;&#xA;If we choose too low, the image will be visibly biased. But if we choose to high, we're wasting computation energy and time.&#xD;&#xA;&#xD;&#xA;One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias. &#xD;&#xA;&#xD;&#xA;Clamping after a threshold, will *work*, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.&#xD;&#xA;&#xD;&#xA;Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            // Randomly terminate a path with a probability inversely equal to the throughput&#xD;&#xA;            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;            if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // Add the energy we 'lose' by randomly terminating paths&#xD;&#xA;            throughput *= 1 / p;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So path with low throughput that won't contribute much to the scene are more likely to be terminated. &#xD;&#xA;&#xD;&#xA;If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last questions:&#xD;&#xA;&#xD;&#xA; 1. Does Russian Roulette give an unbiased result?&#xD;&#xA;   - Yes&#xD;&#xA; 2. Is Russian Roulette necessary for an unbiased result?&#xD;&#xA;   - Depends on what you mean by unbiased. If you mean mathematically, then yes. However, if you mean visually, then no. You just have to choose you max path depth and cutoff threshold very very carefully. This can be very tedious since it can change from scene to scene.&#xD;&#xA; 3. Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?&#xD;&#xA;   - If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still mathematically biased. To be completely unbiased, it must be random.&#xD;&#xA; 4. If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;   - Russian Roulette only stops the bouncing. It doesn't remove the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason *not* to use it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ikXSo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BPiZ7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5938" PostHistoryTypeId="2" PostId="2470" RevisionGUID="4ac9bf4c-1b1b-41fe-a7d9-22d75393c255" CreationDate="2016-05-21T09:26:25.177" UserId="1810" Text="The first things I would try is to see if smartphone pixels are visible (if the photo is high res) or if strange aliasing occurs (your example image shows both). &#xD;&#xA;&#xD;&#xA;Another classical test (but not adapted to any scenes) is to detect perspective bias: if the camera is not exactly parallel to the smartphone screen, then 3D objects projected on the image on screen are projected again to the camera captor through a slightly different perspective. If the scene contains spheres, discs (physical or as reflects, for instance), perpendicular angles, or any similar invariant, then you can detect this.   (this kind of trick is also used to detect images photoshoped by composition of several images)." ContentLicense="CC BY-SA 3.0" />
  <row Id="5939" PostHistoryTypeId="2" PostId="2471" RevisionGUID="4b2c39f0-b7b8-45bc-8fb7-270cce82d275" CreationDate="2016-05-21T11:04:09.310" UserId="3408" Text="I have some problem in OSG doing my model, which need an rectangular prism, that I do not know the parametric equation.&#xD;&#xA;&#xD;&#xA;I tried to search with the google, but no usable result.&#xD;&#xA;&#xD;&#xA;Also tried to draw it by using this site: http://www.math.uri.edu/~bkaskosz/flashmo/tools/parsur/&#xD;&#xA;&#xD;&#xA;Could somebody help to find the parametric equation for (x,y,z) cordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="5940" PostHistoryTypeId="1" PostId="2471" RevisionGUID="4b2c39f0-b7b8-45bc-8fb7-270cce82d275" CreationDate="2016-05-21T11:04:09.310" UserId="3408" Text="Rectangular prism parametric equation" ContentLicense="CC BY-SA 3.0" />
  <row Id="5941" PostHistoryTypeId="3" PostId="2471" RevisionGUID="4b2c39f0-b7b8-45bc-8fb7-270cce82d275" CreationDate="2016-05-21T11:04:09.310" UserId="3408" Text="|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5942" PostHistoryTypeId="33" PostId="2461" RevisionGUID="d43d15de-bdca-4231-a777-f1ee9d1470ad" CreationDate="2016-05-21T11:16:22.007" UserId="3069" Comment="15" />
  <row Id="5943" PostHistoryTypeId="2" PostId="2472" RevisionGUID="32632cb7-aa46-4bd0-84d9-6abe96e8b759" CreationDate="2016-05-21T14:03:10.723" UserId="2448" Text="I'm recently implementing Phong materials in my path tracer. My implementation of a randomly sampled Phong material works and looks fine. But it doesn't work well if the shininess(aka power) is too high. So I tried to implement an importance sampled Phong material. It also looks fine. &lt;br&gt;&#xD;&#xA;However, when I compared the random sampled Phong material to the importance sampled one. Both material looks the same if the shininess is high, but the importance sampled one looks darker if the shininess is low. Why? Where am I doing wrong?&#xD;&#xA;&#xD;&#xA;Picture 1. Random sampled Phong surface(left)/importance sampled Phong surface(right), both shininess ware set to 0 (3500 SPP, naive path tracing). The importance sampled  surface is too dark.&lt;br&gt;&#xD;&#xA;[![Random sampled vs Importance sampled, power = 0][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Picture 2. andom sampled Phong surface(left)/importance sampled Phong surface(right), both shininess ware set to 23 (6700 SPP, naive path tracing). Both surface looks identical.&lt;br&gt;&#xD;&#xA;[![Random sampled vs Importance sampled, power = 23][2]][2]&#xD;&#xA;&#xD;&#xA;The code.&lt;br&gt;&#xD;&#xA;1.The code that samples the Phong BRDF randomly&#xD;&#xA;&#xD;&#xA;    void PhongMaterial::createSample(const Ray&amp; ray, float4 normal, float4 intersection, Ray&amp; sampleRay, float4&amp; coefficient)&#xD;&#xA;	{&#xD;&#xA;		sampleRay = createRandomReflect(normal,intersection);&#xD;&#xA;		float4 reflectDirection = reflect(ray.direction,normal);&#xD;&#xA;		coefficient = reflectColor * pow(dot(sampleRay.direction,reflectDirection),power+1)&#xD;&#xA;			*(float)((power+1));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;2.The code that importance samples the Phong BRDF&#xD;&#xA;&#xD;&#xA;    void PhongMaterial::createImportanceSample(const Ray&amp; ray, float4 normal, float4 intersection, Ray&amp; sampleRay, float4&amp; coefficient)&#xD;&#xA;	{&#xD;&#xA;    	float4 reflectDirection = reflect(ray.direction,normal);&#xD;&#xA;		float2 rnd(rand1(),rand1());&#xD;&#xA;		float phi = 2.0f*M_PI*rnd.x;&#xD;&#xA;		float theta = acos(pow(rnd.y,1.0f/(power+1.f)));&#xD;&#xA;		float4 rotX,rotY;&#xD;&#xA;		ons(reflectDirection,rotX,rotY);&#xD;&#xA;		float4 result = cos(phi)*sin(theta)*rotX&#xD;&#xA;			+ sin(phi)*sin(theta)*rotY&#xD;&#xA;			+ cos(theta)*reflectDirection;&#xD;&#xA;		sampleRay.origin = intersection + result*0.00001f;&#xD;&#xA;		sampleRay.direction = result;&#xD;&#xA;    &#xD;&#xA;		coefficient = reflectColor*(float)((power+1)/(power+2));&#xD;&#xA;		}&#xD;&#xA;    }&#xD;&#xA;Where `ray` is the incoming ray, `normal` is the surface normal, `intersection` is where the ray and the surface intersects, `coefficient` is light transmit coefficient and `power` is the shininess.&lt;br&gt;&#xD;&#xA;Also, `ons` creates two vector perpendicular to the rest from a single vector(the first parameter).&#xD;&#xA;&#xD;&#xA;Where am I doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fqgRS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KW0ng.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5944" PostHistoryTypeId="1" PostId="2472" RevisionGUID="32632cb7-aa46-4bd0-84d9-6abe96e8b759" CreationDate="2016-05-21T14:03:10.723" UserId="2448" Text="How to properly implement Phong material and importance sample it in a path tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="5945" PostHistoryTypeId="3" PostId="2472" RevisionGUID="32632cb7-aa46-4bd0-84d9-6abe96e8b759" CreationDate="2016-05-21T14:03:10.723" UserId="2448" Text="|brdf|pathtracing|sampling|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5948" PostHistoryTypeId="2" PostId="2474" RevisionGUID="0c04e627-e092-4057-960c-cf5abb5f25c1" CreationDate="2016-05-21T14:34:32.753" UserId="231" Text="A [prism] is a polyhedron with a polygonal base, another parallel base of the same shape, and joining faces between corresponding edges of the two base faces.&#xD;&#xA;&#xD;&#xA;The word &quot;prism&quot; is commonly used to describe a right prism with base faces perpendicular to the joining faces. In this case the joining faces are also rectangles, and so a rectangular right prism is simply a [cuboid].&#xD;&#xA;&#xD;&#xA;A cuboid can be described directly, but a simple way to generate one is to start with a cube and use directional [scaling] to give the edges the required lengths.&#xD;&#xA;&#xD;&#xA;If the base faces are not perpendicular to the joining faces, this oblique prism can be achieved by applying a [shear] to a cuboid with the required edge lengths.&#xD;&#xA;&#xD;&#xA;So all you need is a parametric description of a cube, and you can go from there to any rectangular prism required.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [prism]: https://en.wikipedia.org/wiki/Prism_%28geometry%29&#xD;&#xA;  [cuboid]: https://en.wikipedia.org/wiki/Cuboid&#xD;&#xA;  [shear]: https://en.wikipedia.org/wiki/Shear_mapping&#xD;&#xA;  [scaling]: https://en.wikipedia.org/wiki/Scaling_%28geometry%29" ContentLicense="CC BY-SA 3.0" />
  <row Id="5949" PostHistoryTypeId="5" PostId="2474" RevisionGUID="41e03970-bfc4-4df1-a521-e01bceb596aa" CreationDate="2016-05-21T14:50:40.573" UserId="231" Comment="Add example parametrisation of one cube face" Text="A [prism] is a polyhedron with a polygonal base, another parallel base of the same shape, and joining faces between corresponding edges of the two base faces.&#xD;&#xA;&#xD;&#xA;The word &quot;prism&quot; is commonly used to describe a right prism with base faces perpendicular to the joining faces. In this case the joining faces are also rectangles, and so a rectangular right prism is simply a [cuboid].&#xD;&#xA;&#xD;&#xA;A cuboid can be described directly, but a simple way to generate one is to start with a cube and use directional [scaling] to give the edges the required lengths.&#xD;&#xA;&#xD;&#xA;If the base faces are not perpendicular to the joining faces, this oblique prism can be achieved by applying a [shear] to a cuboid with the required edge lengths.&#xD;&#xA;&#xD;&#xA;So all you need is a parametric description of a cube, and you can go from there to any rectangular prism required.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;As joojaa points out, there isn't an easy way to describe a prism (including a cube) in just a single parametrisation. You will need to describe each face with a separate set of parametric equations. For example, using parameters u and v, you could describe one of the faces as follows.&#xD;&#xA;&#xD;&#xA;$$  x=u  \\  y=v  \\  z=1  \\  0 \leq u \leq 1  \\  0 \leq v \leq 1  $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [prism]: https://en.wikipedia.org/wiki/Prism_%28geometry%29&#xD;&#xA;  [cuboid]: https://en.wikipedia.org/wiki/Cuboid&#xD;&#xA;  [shear]: https://en.wikipedia.org/wiki/Shear_mapping&#xD;&#xA;  [scaling]: https://en.wikipedia.org/wiki/Scaling_%28geometry%29" ContentLicense="CC BY-SA 3.0" />
  <row Id="5950" PostHistoryTypeId="5" PostId="2472" RevisionGUID="096bafab-977d-42a6-a6b9-a6101ac52c72" CreationDate="2016-05-21T15:46:22.470" UserId="2448" Comment="Edit: remove a extra bracket in Code 2." Text="I'm recently implementing Phong materials in my path tracer. My implementation of a randomly sampled Phong material works and looks fine. But it doesn't work well if the shininess(aka power) is too high. So I tried to implement an importance sampled Phong material. It also looks fine. &lt;br&gt;&#xD;&#xA;However, when I compared the random sampled Phong material to the importance sampled one. Both material looks the same if the shininess is high, but the importance sampled one looks darker if the shininess is low. Why? Where am I doing wrong?&#xD;&#xA;&#xD;&#xA;Picture 1. Random sampled Phong surface(left)/importance sampled Phong surface(right), both shininess ware set to 0 (3500 SPP, naive path tracing). The importance sampled  surface is too dark.&lt;br&gt;&#xD;&#xA;[![Random sampled vs Importance sampled, power = 0][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Picture 2. andom sampled Phong surface(left)/importance sampled Phong surface(right), both shininess ware set to 23 (6700 SPP, naive path tracing). Both surface looks identical.&lt;br&gt;&#xD;&#xA;[![Random sampled vs Importance sampled, power = 23][2]][2]&#xD;&#xA;&#xD;&#xA;The code.&lt;br&gt;&#xD;&#xA;1.The code that samples the Phong BRDF randomly&#xD;&#xA;&#xD;&#xA;    void PhongMaterial::createSample(const Ray&amp; ray, float4 normal, float4 intersection, Ray&amp; sampleRay, float4&amp; coefficient)&#xD;&#xA;	{&#xD;&#xA;		sampleRay = createRandomReflect(normal,intersection);&#xD;&#xA;		float4 reflectDirection = reflect(ray.direction,normal);&#xD;&#xA;		coefficient = reflectColor * pow(dot(sampleRay.direction,reflectDirection),power+1)&#xD;&#xA;			*(float)((power+1));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;2.The code that importance samples the Phong BRDF&#xD;&#xA;&#xD;&#xA;    void PhongMaterial::createImportanceSample(const Ray&amp; ray, float4 normal, float4 intersection, Ray&amp; sampleRay, float4&amp; coefficient)&#xD;&#xA;	{&#xD;&#xA;    	float4 reflectDirection = reflect(ray.direction,normal);&#xD;&#xA;		float2 rnd(rand1(),rand1());&#xD;&#xA;		float phi = 2.0f*M_PI*rnd.x;&#xD;&#xA;		float theta = acos(pow(rnd.y,1.0f/(power+1.f)));&#xD;&#xA;		float4 rotX,rotY;&#xD;&#xA;		ons(reflectDirection,rotX,rotY);&#xD;&#xA;		float4 result = cos(phi)*sin(theta)*rotX&#xD;&#xA;			+ sin(phi)*sin(theta)*rotY&#xD;&#xA;			+ cos(theta)*reflectDirection;&#xD;&#xA;		sampleRay.origin = intersection + result*0.00001f;&#xD;&#xA;		sampleRay.direction = result;&#xD;&#xA;    &#xD;&#xA;		coefficient = reflectColor*(float)((power+1)/(power+2));&#xD;&#xA;    }&#xD;&#xA;Where `ray` is the incoming ray, `normal` is the surface normal, `intersection` is where the ray and the surface intersects, `coefficient` is light transmit coefficient and `power` is the shininess.&lt;br&gt;&#xD;&#xA;Also, `ons` creates two vector perpendicular to the rest from a single vector(the first parameter).&#xD;&#xA;&#xD;&#xA;Where am I doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fqgRS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KW0ng.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5951" PostHistoryTypeId="4" PostId="2472" RevisionGUID="096bafab-977d-42a6-a6b9-a6101ac52c72" CreationDate="2016-05-21T15:46:22.470" UserId="2448" Comment="Edit: remove a extra bracket in Code 2." Text="How to properly implement Phong material and importance sample it in a path tracer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5952" PostHistoryTypeId="2" PostId="2475" RevisionGUID="68eecaa7-db07-4afb-930d-43dc60ce654f" CreationDate="2016-05-21T17:08:55.753" UserId="48" Text="The function in your third code snippet is checking for the winding order to be consistent between two neighboring triangles. It does this by looking at the order in which vertices are listed in their shared edge. If the two triangles have consistent winding (both counterclockwise for instance), they will have opposite orientations for the shared edge.&#xD;&#xA;&#xD;&#xA;A diagram may help see this:&#xD;&#xA;![diagram of two triangles with vertex winding][1]&#xD;&#xA;&#xD;&#xA;The vertex order is indicated by the blue arrows:&#xD;&#xA;&#xD;&#xA;    t0: v0, v1, v2&#xD;&#xA;    t1: v1, v3, v2&#xD;&#xA;&#xD;&#xA;If you look at the shared edge (v1&amp;ndash;v2), it appears in the first triangle with order `v1, v2`, and in the other with order `v2, v1` (cycling around the end of the vertex list back to the beginning).&#xD;&#xA;&#xD;&#xA;The function in your snippet takes a triangle and looks at one of its neighbors, checks all three possibilities for which edge in the second triangle is the shared one, and checks that the vertices in that (other triangle's) edge appear in the reverse order to the vertices in the current triangle's edge. It returns true if this is the case, and false otherwise.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JSz6H.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5953" PostHistoryTypeId="2" PostId="2476" RevisionGUID="9fbe73e8-75d0-4104-84f2-238a2ff0d142" CreationDate="2016-05-21T17:55:41.620" UserId="48" Text="One good way you can arrange for a circle (or other shape) to be drawn for each vertex in a mesh is to use [geometry instancing](https://en.wikipedia.org/wiki/Geometry_instancing). This is a GPU feature that allows multiple instances (copies) of a mesh to be drawn at once, with the vertices/indices of the mesh given by one set of buffers, and another vertex buffer that can give additional data per-instance. The vertex shader can be used to combine the data from both buffers in whatever way you choose.&#xD;&#xA;&#xD;&#xA;To be concrete, in your case you could create a mesh representing a circle of the desired radius, with its vertices specified directly in screen-space coordinates and centered at the origin. Then you'd use instancing to make the GPU render a new copy of the circle mesh for every vertex of your original point-mesh. In the vertex shader, you'd calculate the screen-space position of the point (using the world-view-projection transforms as usual), then translate the circle mesh to be centered at that position.&#xD;&#xA;&#xD;&#xA;As for the second part of your question, on how to have the circles influence each other's color: it depends on what you want to do, specifically. Hardware blending can be used to handle simple cases, such as adding or multiplying the colors, or alpha-blending. If you want something more complicated than that, then it might be possible to do it with a multi-pass algorithm, or (on the latest GPUs) programmable blending." ContentLicense="CC BY-SA 3.0" />
  <row Id="5954" PostHistoryTypeId="2" PostId="2477" RevisionGUID="13ddb16f-e450-422c-ad2d-96b61773f189" CreationDate="2016-05-21T18:24:35.543" UserId="2479" Text="This is not a full answer, I would just like to share the knowledge I obtained by studying two of the papers mentioned in the question: [Steerable Importance Sampling][1] and [Practical Product Importance Sampling for Direct Illumination][2].&#xD;&#xA;&#xD;&#xA;Steerable Importance Sampling&#xD;&#xA;-----------------------------&#xD;&#xA;&#xD;&#xA;In this paper they propose a method for sampling the product of the clamped cosine component and environment map lighting:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L\left(\omega_{i}\right)\left(\omega_{i}\cdot n\right)^+&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;They make use of the fact that a piece-wise linear approximation of the product function can be relatively well expressed and partially pre-computed using the first nine spherical harmonic bases. They build this approximation on top of an adaptively triangulated EM and use it as an importance function for sampling.&#xD;&#xA;&#xD;&#xA;They pre-compute and store coefficients of the piece-wise approximation for each triangle vertex and also coefficients for computation of its integral over the triangle &amp;ndash; they call them vertex and triangle weights. Then they make use of the fact that is it possible to easily compute coefficients for an integral over a set of triangles just by summing the individual triangle weights without incorporating additional spherical harmonic bases. This allows them to build a balanced binary tree over the triangles where each node contains coefficients for computing approximation integral over the node's sub-tree triangles.&#xD;&#xA;&#xD;&#xA;The sampling procedure consists of selecting a triangle and sampling its area:&#xD;&#xA;&#xD;&#xA; - A triangle is chosen by descending down the pre-built binary tree    with probability proportional to the sub-integral approximation. This    const $O\left(\log N_{\triangle}\right)$ on-the-fly computations of       sub-integrals, each consisting of one inner product of clamped-cosine    spherical harmonic coordinates with the pre-computed coefficients.   &#xD;&#xA; - The chosen triangle surface is then sampled in $O\left(1\right)$ in a    bi-linear fashion by a novel stratified sampling strategy proposed in    the paper.&#xD;&#xA;&#xD;&#xA;To me, this looks like a **promising technique**, but the classical question with papers is how it will behave in the real life. On one hand there may, for example, be pathological cases when the EM is hard to approximate with triangulated piece-wise linear function, which can lead either to an enormous amount of triangles and/or to poor sample quality. On the other hand it can instantly provide a relatively good approximation of the whole EM contribution, which can be useful when sampling from multiple lights.&#xD;&#xA;&#xD;&#xA;Practical Product Importance Sampling for Direct Illumination&#xD;&#xA;-----------------------------&#xD;&#xA;&#xD;&#xA;In this paper they propose a method for sampling the whole integrand &amp;ndash; the product of environment map lighting and cosine-weighted surface reflectance:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L\left(\omega_{i}\right)f_{r}\left(\omega_{i},\omega_{o},n\right)\left(\omega_{i}\cdot n\right)^+&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The only pre-processing in this method is computation of a hierarchical representation of the EM (either mipmap or wavelet based). The rest is done on the fly during the sampling.&#xD;&#xA;&#xD;&#xA;The sampling procedure:&#xD;&#xA;&#xD;&#xA; - Building an on-the-fly BRDF approximation: They first draw several BRDF importance samples and evaluate $f_{r}\cos\theta_i$. From these values they build a quadtree-based piece-wise constant approximation of the BRDF, where each leaf of the tree contains exactly one sample.&#xD;&#xA; - Computing a product of the BRDF approximation and the EM: Multiplication is done at the BRDF quadtree leaves and averaged values are propagated to parents.&#xD;&#xA; - Product sampling: uniform samples are fed through the product tree using sample warping.&#xD;&#xA;&#xD;&#xA;The procedure should generate relatively good samples at the cost of heavy pre-computation &amp;ndash; they show that roughly 100&amp;ndash;200 BRDF samples are needed for BRDF approximation to achieve the best sampling performance. This may make it suitable for purely direct illumination computations, where one generates many samples per shading point, but is most probably **too expensive for global illumination algorithms** (e.g. uni- or bi-directional path traces), where you usually generate only a few samples per shading point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://home.eps.hw.ac.uk/~ks400/research.html#SteerableImportance&#xD;&#xA;  [2]: http://fileadmin.cs.lth.se/graphics/research/papers/2008/pps/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5957" PostHistoryTypeId="5" PostId="2477" RevisionGUID="c5054837-32a0-46f5-99b4-840d46a51b8f" CreationDate="2016-05-21T19:29:57.323" UserId="2479" Comment="Minor clarifications and typo fixes" Text="This is not a full answer, I would just like to share the knowledge I obtained by studying two of the papers mentioned in the question: [Steerable Importance Sampling][1] and [Practical Product Importance Sampling for Direct Illumination][2].&#xD;&#xA;&#xD;&#xA;Steerable Importance Sampling&#xD;&#xA;-----------------------------&#xD;&#xA;&#xD;&#xA;In this paper they propose a method for sampling the product of the clamped cosine component and environment map lighting:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{EM}\left(\omega_{i}\right)\left(\omega_{i}\cdot n\right)^+&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;They make use of the fact that a piece-wise linear approximation of the product function can be relatively well expressed and partially pre-computed using the first nine spherical harmonic bases. They build this approximation on top of an adaptively triangulated EM and use it as an importance function for sampling.&#xD;&#xA;&#xD;&#xA;They pre-compute and store approximation coefficients for each triangle vertex and also coefficients for computation of approximation integral over the triangle for each triangle. These coefficients are called vertex and triangle weights. Then they make use of the fact that is it possible to easily compute coefficients for an integral over a set of triangles just by summing the individual triangle weights without incorporating additional spherical harmonic bases. This allows them to build a balanced binary tree over the triangles where each node contains coefficients for computing approximation integral over the node's sub-tree triangles.&#xD;&#xA;&#xD;&#xA;The sampling procedure consists of selecting a triangle and sampling its area:&#xD;&#xA;&#xD;&#xA; - A triangle is chosen by descending down the pre-built binary tree    with probability proportional to the sub-integral approximations. This costs $O\left(\log N_{\triangle}\right)$ on-the-fly computations of sub-integrals, each consisting of one inner product of clamped-cosine spherical harmonic coordinates with the pre-computed coefficients.   &#xD;&#xA; - The chosen triangle surface is then sampled in $O\left(1\right)$ time in a    bi-linear fashion by a novel stratified sampling strategy proposed in    the paper.&#xD;&#xA;&#xD;&#xA;To me, this looks like a **promising technique**, but the classical question with papers is how it will behave in the real life. On the one hand, there may be pathological cases when the EM is hard to approximate with triangulated piece-wise linear function, which can lead to an enormous amount of triangles and/or to poor sample quality. On the other hand, it can instantly provide a relatively good approximation of the whole EM contribution, which can be useful when sampling multiple light sources.&#xD;&#xA;&#xD;&#xA;Practical Product Importance Sampling for Direct Illumination&#xD;&#xA;-------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;In this paper they propose a method for sampling the product of environment map lighting and cosine-weighted surface reflectance:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{EM}\left(\omega_{i}\right)f_{r}\left(\omega_{i},\omega_{o},n\right)\left(\omega_{i}\cdot n\right)^+&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The only pre-processing in this method is computation of a hierarchical representation of the EM (either mipmap or wavelet based). The rest is done on the fly during the sampling.&#xD;&#xA;&#xD;&#xA;The sampling procedure:&#xD;&#xA;&#xD;&#xA; - Building an on-the-fly BRDF approximation: They first draw several BRDF importance samples and evaluate $f_{r}\left(\omega_{i},\omega_{o},n\right)\left(\omega_{i}\cdot n\right)^+$. From these values they build a quadtree-based piece-wise constant approximation of the BRDF, where each leaf of the tree contains exactly one sample.&#xD;&#xA; - Computing a product of the BRDF approximation and the EM: Multiplication is done at the BRDF quadtree leaves and averaged values are propagated to parents.&#xD;&#xA; - Product sampling: uniform samples are fed through the product tree using simple sample warping.&#xD;&#xA;&#xD;&#xA;The procedure should generate relatively good samples at the cost of heavy pre-computation &amp;ndash; they show that roughly 100&amp;ndash;200 BRDF samples are needed for BRDF approximation to achieve the best sampling performance. This may make it suitable for purely direct illumination computations, where one generates many samples per shading point, but is most probably **too expensive for global illumination algorithms** (e.g. uni- or bi-directional path tracers), where you usually generate only a few samples per shading point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://home.eps.hw.ac.uk/~ks400/research.html#SteerableImportance&#xD;&#xA;  [2]: http://fileadmin.cs.lth.se/graphics/research/papers/2008/pps/" ContentLicense="CC BY-SA 3.0" />
  <row Id="5959" PostHistoryTypeId="2" PostId="2478" RevisionGUID="2b2d3e8c-bbbf-4956-800b-58e2f12fd4e1" CreationDate="2016-05-21T21:56:59.703" UserId="3410" Text="First of all, let me explain what I am really trying to achieve. In a post-effect shader acting on a camera-renderer, I want to change the color of each fragment  depending on how many green (RGBA = 0,~1,0,1) fragments there are nearby.&#xD;&#xA;&#xD;&#xA;So, for the sake of simplicity, let's imagine my screen is all black, with some (~10k) green points spread around. In the fragment shader, for each fragment I have to find how many green fragments there are within a given distance and then change the color of the current fragment being evaluated depending on that number of surrounding green fragments.&#xD;&#xA;&#xD;&#xA;I began with the most naïve approach one could think of: for each fragment, I calculated the coordinates of the 10th neighbor fragments to each side: right, left, up and down (which gives a surrounding square, then I discarded the corners from the computation to get a surrounding circle of radius ~10pixels, centered at the current fragment). Then I tested which of the fragments within such &quot;surrounding bounding circle&quot; was green (i.e. color.g &gt; 0.9f). In affirmative case, I increased a counter variable.&#xD;&#xA;&#xD;&#xA;In my way of thinking, that would be doing a brute force and in order to visualize the result, I then painted each fragment with the RGBA color (counter*0.1f, 0, counter*0.1f, 1). Here is the code snippet:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D _MainTex;&#xD;&#xA;    static float2 _Pixels = float2(_ScreenParams.x, _ScreenParams.y); //gets the Screen width and height&#xD;&#xA;    static half sx = 1 / _ScreenParams.x; //defines the measure of a fragment at the X axis of the viewport&#xD;&#xA;    static half sy = 1 / _ScreenParams.y; //defines the measure of a fragment at the Y axis of the viewport&#xD;&#xA;&#xD;&#xA;    float4 frag(v2f_img input) : COLOR{&#xD;&#xA;    fixed2 uv = round(input.uv * _Pixels) / _Pixels;&#xD;&#xA;&#xD;&#xA;    float counter = 0.0f;&#xD;&#xA;    float i; float j;&#xD;&#xA;    float thrsh = 0.8f;&#xD;&#xA;&#xD;&#xA;    [unroll(10)]for (i = zero; i&lt;10;i++) //loop trough 10 fragments horizontally&#xD;&#xA;    {&#xD;&#xA;        [unroll(10)]for (j = zero; j &lt; 10; j++) //loop trough 10 fragments vertically&#xD;&#xA;        {&#xD;&#xA;            //the following lines cut (very roughly) the corners of the surrounding square ixj to approximate a surrounding circle of radius ~10fragments. But this is less important: if such lines are commented, the problem that I will show later will still happen, just with a surrounding square instead of a surrounding circle&#xD;&#xA;            if ((i == 4 || i == 5) &amp;&amp; j &gt; 9) j = 0; else if ((i == 6) &amp;&amp; j &gt; 8) j = 0; else if ((i == 7) &amp;&amp; j &gt; 7) j = 0;&#xD;&#xA;            else if ((i == 8) &amp;&amp; j &gt; 6) j = 0; else if ((i == 9) &amp;&amp; j &gt; 5) j = 0; else if (i == 10 &amp;&amp; j &gt; 4) j = 0;&#xD;&#xA;&#xD;&#xA;            else if (j &gt; 0) { //so, let's continue only if current iteration does not relate to the corners of the surrounding square, i.e. outside the surrounding circle with radius ~10 fragments&#xD;&#xA;&#xD;&#xA;                float tl = tex2D(_MainTex, uv + fixed2(-sx*i, +sy*j)).g; //gets the top-left neighbor times i and j&#xD;&#xA;                float cl = tex2D(_MainTex, uv + fixed2(-sx*i, 0)).g; //gets the center-left neighbor times i and j&#xD;&#xA;                float bl = tex2D(_MainTex, uv + fixed2(-sx*i, -sy*j)).g; //gets the bottom-left neighbor times i and j&#xD;&#xA;                float tc = tex2D(_MainTex, uv + fixed2(0, +sy*j)).g; //gets the top-center neighbor times i and j&#xD;&#xA;                float cc = tex2D(_MainTex, uv + fixed2(0, 0)).g;  //gets the current fragment bein evaluated (i.e. center-center)&#xD;&#xA;                float bc = tex2D(_MainTex, uv + fixed2(0, -sy*j)).g;  //gets the bottom-center neighbor times i and j&#xD;&#xA;                float tr = tex2D(_MainTex, uv + fixed2(+sx*i, +sy*j)).g; //gets the top-right neighbor times i and j&#xD;&#xA;                float cr = tex2D(_MainTex, uv + fixed2(+sx*i, 0)).g; //gets the center-right neighbor times i and j&#xD;&#xA;                float br = tex2D(_MainTex, uv + fixed2(+sx*i, -sy*j)).g;  //gets the bottom-right neighbor times i and j&#xD;&#xA;&#xD;&#xA;                //Now, for each fragment surrounding that is above the Green threshold, we increase the counter&#xD;&#xA;                    if (tl &gt; thrsh) counter++;&#xD;&#xA;                    if (cl &gt; thrsh) counter++;&#xD;&#xA;                    if (bl &gt; thrsh) counter++;&#xD;&#xA;                    if (tc &gt; thrsh) counter++;&#xD;&#xA;                    if (bc &gt; thrsh) counter++;&#xD;&#xA;                    if (tr &gt; thrsh) counter++;&#xD;&#xA;                    if (cr &gt; thrsh) counter++;&#xD;&#xA;                    if (br &gt; thrsh) counter++;&#xD;&#xA;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (counter &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        return float4(counter *0.1f, 0, counter *0.1f, 1); //in case at least one surrounding fragment was green, paint the fragments pink-ish in proportion to how many green there were in the surrounding circle&#xD;&#xA;    } else {&#xD;&#xA;        return tex2D(_MainTex, float4(0,0,0,1)); //otherwise, paint black&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, besides **very** inefficient, the solution above is also not working correctly. Obvioulsy, I was expecting to get, around each green point at the screen, something like a pink-ish circle that is of stronger intensity when close to the center and fades away at the border, i.e. away from the center. Instead, this is what I get (in actual and zoomed sizes):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now, I tried everything I could think of but I don't get:&#xD;&#xA;&#xD;&#xA;1) why it is not working properly. What am I doing wrong? Could anyone shed some light?&#xD;&#xA;&#xD;&#xA;2) also, if there is any obvious more performant way of achieving what I want, please do let me know too (the current solution is taking 12ms in a non HD resolution). Or if you prefer, I can come with a different question for that later, after the operational problem described above is solved.&#xD;&#xA;&#xD;&#xA;Thanks anyways for your time.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Tsef3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5960" PostHistoryTypeId="1" PostId="2478" RevisionGUID="2b2d3e8c-bbbf-4956-800b-58e2f12fd4e1" CreationDate="2016-05-21T21:56:59.703" UserId="3410" Text="Count number of green fragments that are within a given distance from each screen fragment" ContentLicense="CC BY-SA 3.0" />
  <row Id="5961" PostHistoryTypeId="3" PostId="2478" RevisionGUID="2b2d3e8c-bbbf-4956-800b-58e2f12fd4e1" CreationDate="2016-05-21T21:56:59.703" UserId="3410" Text="|shader|geometry|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5962" PostHistoryTypeId="2" PostId="2479" RevisionGUID="487d5e79-74fe-4acd-b9d2-a3c9273c74cf" CreationDate="2016-05-22T01:01:30.820" UserId="48" Text="You're getting a cross shape in the output because in your loop, you're counting pixels on the center row and column multiple times. For example the pixel at (0, 0) offset will be counted on every iteration of the inner loop, so 100 times. Similarly, (&amp;pm;i, 0) and (0, &amp;pm;i) will be counted on every iteration of the inner loop, so 10 times for each value of i.&#xD;&#xA;&#xD;&#xA;A better way to write the loop is like this:&#xD;&#xA;&#xD;&#xA;    [unroll] for (int i = -10; i &lt;= 10; i++)&#xD;&#xA;    {&#xD;&#xA;        [unroll] for (int j = -10; j &lt;= 10; j++)&#xD;&#xA;        {&#xD;&#xA;            float sample = tex2D(_MainTex, input.uv + float2(sx*i, sy*j)).g;&#xD;&#xA;            if (sample &gt; thrsh) counter++;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will weight all pixels equally within a box. To make a more circular shape you can change the `j` iteration bounds based on the value of `i`.&#xD;&#xA;&#xD;&#xA;Also, I doubt you need or want to round off `uv` to the nearest pixel as you're doing. The UVs coming into the fragment shader should already be correct, and moreover they are not multiples of the pixel size; they are the coordinates of pixel _centers_, so they contain a half-pixel offset (which is exactly what you want for sampling a screen-sized texture).&#xD;&#xA;&#xD;&#xA;For a more efficient algorithm, you could downsample the original image 2x, then run a 5px-radius neighbor search on that one instead of a 10px-radius search on the original. This will make the circle shape somewhat less precise but depending on what you're doing, it may not matter that much.&#xD;&#xA;&#xD;&#xA;Another approach that's less brute-force but still precise would be to build a spatial hierarchy of the green points. This could be as simple as a uniform grid where each grid square stores a list of the points inside it, or as complicated as a kd-tree. Your fragment shader could then walk this data structure to efficiently search the nodes within a radius of the fragment, and count the points it finds." ContentLicense="CC BY-SA 3.0" />
  <row Id="5963" PostHistoryTypeId="2" PostId="2480" RevisionGUID="dd88c276-3c24-4b74-b7de-7cc252364454" CreationDate="2016-05-22T15:05:30.210" UserId="2308" Text="So I have a game and I am trying to fake glow inside of it by using the hardwares capability to downsize textures causing them to blur.&#xA;&#xA;The texture I wish to do this with is in a render buffer that is the size of the screen (not power of two)&#xA;&#xA;What would be the quickest way to get these lower resolutions created?&#xA;Tricking the software to make minimaps?&#xA;Another fbo with the texture rendered on it in smaller size?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5964" PostHistoryTypeId="1" PostId="2480" RevisionGUID="dd88c276-3c24-4b74-b7de-7cc252364454" CreationDate="2016-05-22T15:05:30.210" UserId="2308" Text="Generation of lower resolution textures" ContentLicense="CC BY-SA 3.0" />
  <row Id="5965" PostHistoryTypeId="3" PostId="2480" RevisionGUID="dd88c276-3c24-4b74-b7de-7cc252364454" CreationDate="2016-05-22T15:05:30.210" UserId="2308" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5966" PostHistoryTypeId="2" PostId="2481" RevisionGUID="2be8e11d-5cf8-4597-afc3-e944b7ca4c5c" CreationDate="2016-05-22T16:37:02.623" UserDisplayName="user3412" Text="I would think rendering to a downsampled FBO would be much faster than generating mipmaps.  glGenerateMipmap will generate the complete mipmap pyramid, which seems wasteful:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenerateMipmap.xml&#xD;&#xA;&#xD;&#xA;Besides, only OpenGL ES 3.0 lets you manually select mip level when texturing:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/opengles/sdk/docs/man3/html/textureLod.xhtml&#xD;&#xA;&#xD;&#xA;Artistically, this might not give you the look you want.  In my experience, simply downsampling gives a grainy look.  I would recommend also doing a pair of one-dimensional blurs, as described in this article from GPU Gems:&#xD;&#xA;&#xD;&#xA;http://http.developer.nvidia.com/GPUGems/gpugems_ch21.html&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5967" PostHistoryTypeId="2" PostId="2482" RevisionGUID="4027685d-e93f-468e-81ec-06f9dd65fe30" CreationDate="2016-05-23T02:54:29.953" UserId="310" Text="I am trying to implement refraction and transmission in my path tracer and I'm a bit unsure on how to implement it. First, some background:&#xD;&#xA;&#xD;&#xA;When light hits a surface, a portion of it will reflect, and a portion will be refracted:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;How much light reflects vs. refracts is given by the [Fresnel Equations][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In a recursive ray tracer, the simple implementation would be to shoot a ray for reflection and a ray for refraction, then do a weighted sum using the Fresnel.&#xD;&#xA;$$\begin{align*}&#xD;&#xA;R &amp;= Fresnel()\\&#xD;&#xA;T &amp;= 1 - R\\&#xD;&#xA;L_{\text{o}} &amp;= R \cdot L_{\text{i,reflection}} + T \cdot L_{\text{i,refraction}}&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;However, in path tracing, we only choose one path. This is my question:&#xD;&#xA;&#xD;&#xA; - **How do I choose whether to reflect or refract in a non-biased way**&#xD;&#xA;&#xD;&#xA;My first guess would be to randomly choose based on the Fresnel. Aka:&#xD;&#xA;&#xD;&#xA;    float p = randf();&#xD;&#xA;    float fresnel = Fresnel();&#xD;&#xA;    if (p &lt;= fresnel) {&#xD;&#xA;        // Reflect&#xD;&#xA;    } else {&#xD;&#xA;        // Refract&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Would this be correct? Or do I need to have some kind of correction factor? Since I'm not taking both paths.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2oBo9.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [3]: https://i.stack.imgur.com/cYrKH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="5968" PostHistoryTypeId="1" PostId="2482" RevisionGUID="4027685d-e93f-468e-81ec-06f9dd65fe30" CreationDate="2016-05-23T02:54:29.953" UserId="310" Text="Choosing Reflection or Refraction in Path Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="5969" PostHistoryTypeId="3" PostId="2482" RevisionGUID="4027685d-e93f-468e-81ec-06f9dd65fe30" CreationDate="2016-05-23T02:54:29.953" UserId="310" Text="|brdf|pathtracing|reflection|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5971" PostHistoryTypeId="2" PostId="2483" RevisionGUID="418de754-4f09-407e-9a2b-2fe337d4d13b" CreationDate="2016-05-23T08:04:39.000" UserId="2479" Text="If you allow BSDFs - not just BRDFs - in your path tracer, you have to integrate over the whole sphere instead of just the positive hemisphere. Monte Carlo samples can be generated by various strategies: for the direct illumination you can use BRDF and ligth sampling, for the indirect illumination the only meaningful strategy usually is the BSDF sampling. The sampling strategies themselves usually contain the decision about what hemisphere to sample. &#xA;&#xA;For light sampling, you can use the information about the surface properties to sample the hemispheres which have non-zero contribution, but the rest of the properties is usually ignored. &#xA;&#xA;For BSDF sampling, the situation is much more interesting. The case you described deals with an ideal Fresnel surface, where there are only two contributing directions. You can easily split the integral into sum of two parts - positive hemisphere for reflection and negative hemisphere for refraction. Since, as you mentioned, we don’t want to go in both directions in a path tracer, we have to pick one. This in fact means that we want to estimate the sum of numbers by picking just one of them. And, as we like to do in computer graphics, this can be done by adding one more Monte Carlo estimation: pick one of the addends randomly and divide it by the probability of picking. In an ideal case you want to have the sampling probability proportional the the addends, but since we don't know their values (we wouldn't have to estimate the sum if we knew them), so we just estimate them by neglecting some of the factors. In this case, we ignore the incoming light amount and take just the Fresnel reflectance/ transmittance into account.&#xA;&#xA;The BSDF sampling routine for the case of smooth Fresnel surface is, therefore, to pick the direction randomly according to Fresnel reflectance and, at some point, divide the result by probability of picking the direction. &#xA;&#xA;In case of more sophisticated BSDF models like microfacet-based ones, the sampling is slightly more complex, but the idea of splitting the whole spherical integral into a finite sum and using discrete Monte Carlo can usually be applied. &#xA;&#xA;...Sorry, no formulae, I wrote this on my phone. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5972" PostHistoryTypeId="5" PostId="2483" RevisionGUID="a5ba717e-d30e-49a7-a129-7ca954d97ce3" CreationDate="2016-05-23T09:18:04.470" UserId="2479" Comment="Added tl;dr version" Text="TL;DR Answer&#xD;&#xA;------------&#xD;&#xA;&#xD;&#xA;Yes, you can do it like that, you just have to divide the result by the probability of choosing the direction.&#xD;&#xA;&#xD;&#xA;Full Answer&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;If you allow BSDFs - not just BRDFs - in your path tracer, you have to integrate over the whole sphere instead of just the positive hemisphere. Monte Carlo samples can be generated by various strategies: for the direct illumination you can use BRDF and ligth sampling, for the indirect illumination the only meaningful strategy usually is the BSDF sampling. The sampling strategies themselves usually contain the decision about what hemisphere to sample. &#xD;&#xA;&#xD;&#xA;For light sampling, you can use the information about the surface properties to sample the hemispheres which have non-zero contribution, but the rest of the properties is usually ignored. &#xD;&#xA;&#xD;&#xA;For BSDF sampling, the situation is much more interesting. The case you described deals with an ideal Fresnel surface, where there are only two contributing directions. You can easily split the integral into sum of two parts - positive hemisphere for reflection and negative hemisphere for refraction. Since, as you mentioned, we don’t want to go in both directions in a path tracer, we have to pick one. This in fact means that we want to estimate the sum of numbers by picking just one of them. And, as we like to do in computer graphics, this can be done by adding one more Monte Carlo estimation: pick one of the addends randomly and divide it by the probability of picking. In an ideal case you want to have the sampling probability proportional the the addends, but since we don't know their values (we wouldn't have to estimate the sum if we knew them), so we just estimate them by neglecting some of the factors. In this case, we ignore the incoming light amount and take just the Fresnel reflectance/ transmittance into account.&#xD;&#xA;&#xD;&#xA;The BSDF sampling routine for the case of smooth Fresnel surface is, therefore, to pick the direction randomly according to Fresnel reflectance and, at some point, divide the result by probability of picking the direction. &#xD;&#xA;&#xD;&#xA;In case of more sophisticated BSDF models like microfacet-based ones, the sampling is slightly more complex, but the idea of splitting the whole spherical integral into a finite sum and using discrete Monte Carlo can usually be applied. &#xD;&#xA;&#xD;&#xA;...Sorry, no formulae, I wrote this on my phone. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5973" PostHistoryTypeId="5" PostId="2483" RevisionGUID="9243a361-7a94-46cf-95bb-c2d5fb13f4a5" CreationDate="2016-05-23T09:48:23.157" UserId="2479" Comment="minor" Text="TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;Yes, you can do it like that, you just have to divide the result by the probability of choosing the direction.&#xD;&#xA;&#xD;&#xA;Full Answer&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;The topic of sampling in path tracers allowing materials with both reflection and refraction is actually a little bit more complex.&#xD;&#xA;&#xD;&#xA;Let's start with some background first. If you allow BSDFs - not just BRDFs - in your path tracer, you have to integrate over the whole sphere instead of just the positive hemisphere. Monte Carlo samples can be generated by various strategies: for the direct illumination you can use BSDF and light sampling, for the indirect illumination the only meaningful strategy usually is the BSDF sampling. The sampling strategies themselves usually contain the decision about which hemisphere to sample (e.g. whether reflection or refraction is computed).&#xD;&#xA;&#xD;&#xA;In the simplest version, the light sampling usually doesn't take care much about reflection or refraction. It samples the light sources or the environment map (if present) with respect to the light properties. You can improve sampling of environment maps by picking just the hemisphere in which the material has non-zero contribution, but the rest of the material properties is usually ignored. Note that for and ideally smooth Fresnel material the light sampling doesn't work.&#xD;&#xA;&#xD;&#xA;For BSDF sampling, the situation is much more interesting. The case you described deals with an ideal Fresnel surface, where there are only two contributing directions (since Fresnel BSDF is in fact just a sum of two delta functions). You can easily split the integral into a sum of two parts - one reflection and one for refraction. Since, as you mentioned, we don’t want to go in both directions in a path tracer, we have to pick one. This means that we want to estimate the sum of numbers by picking just one of them. And, as we like to do in computer graphics, this can be done by adding one more Monte Carlo estimation: pick one of the addends randomly and divide it by the probability of it being picked. In an ideal case you want to have the sampling probability proportional the the addends, but since we don't know their values (we wouldn't have to estimate the sum if we knew them), we just estimate them by neglecting some of the factors. In this case, we ignore the incoming light amount and use just the Fresnel reflectance/transmittance as our estimates.&#xD;&#xA;&#xD;&#xA;The BSDF sampling routine for the case of smooth Fresnel surface is, therefore, to pick the direction randomly according to Fresnel reflectance and, at some point, divide the result for that direction by probability of picking the direction.&#xD;&#xA;&#xD;&#xA;In case of more sophisticated BSDF models like those based on microfacet theory, the sampling is slightly more complex, but the idea of splitting the whole integral into a finite sum of sub-integrals and using discrete Monte Carlo afterwards can usually be applied too.&#xD;&#xA;&#xD;&#xA;...sorry, no formulae, I wrote this on my phone. " ContentLicense="CC BY-SA 3.0" />
  <row Id="5974" PostHistoryTypeId="2" PostId="2484" RevisionGUID="1946fdbf-ca1b-43dd-9678-cc44b1abaf8f" CreationDate="2016-05-23T11:32:16.083" UserId="3416" Text="In [this tutorial][1], &#xD;&#xA;&#xD;&#xA;&gt; It is very often the case that triangles are rendered that share&#xD;&#xA;&gt; edges. OpenGL offers a guarantee that, so long as the shared edge&#xD;&#xA;&gt; vertex positions are identical, there will be no sample gaps during&#xD;&#xA;&gt; scan conversion.&#xD;&#xA;&#xD;&#xA;1 What exactly is sample gaps during scan conversion? &#xD;&#xA;&#xD;&#xA;2 Under what circumstances, will it happen? &#xD;&#xA;&#xD;&#xA;3 Does it happen when the line cross the center of the fragment?&#xD;&#xA;  [1]: http://alfonse.bitbucket.org/oldtut/Basics/Intro%20Graphics%20and%20Rendering.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5975" PostHistoryTypeId="1" PostId="2484" RevisionGUID="1946fdbf-ca1b-43dd-9678-cc44b1abaf8f" CreationDate="2016-05-23T11:32:16.083" UserId="3416" Text="What is sample gaps during scan conversion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5976" PostHistoryTypeId="3" PostId="2484" RevisionGUID="1946fdbf-ca1b-43dd-9678-cc44b1abaf8f" CreationDate="2016-05-23T11:32:16.083" UserId="3416" Text="|opengl|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5977" PostHistoryTypeId="2" PostId="2485" RevisionGUID="ea3c0373-ac0c-4b06-b9cb-0fbac67de517" CreationDate="2016-05-23T11:55:20.703" UserId="209" Text="Assuming a consistent winding order, it means that if you have triangles  ABC and BCD, then if a sample point, that is a test during scan conversion to determine if a point (read pixel) is inside a triangle, lies *exactly* on the shared edge BC, then that sample will belong to *exactly one* of those two triangles. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This avoids both gaps and double filling. The latter would be problematic with, say, translucency or stencil operations.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5978" PostHistoryTypeId="5" PostId="2484" RevisionGUID="d21b9e7b-52ed-4023-9edf-e6053822522c" CreationDate="2016-05-23T12:15:53.193" UserId="209" Comment="s/is/are in various places" Text="In [this tutorial][1], &#xD;&#xA;&#xD;&#xA;&gt; It is very often the case that triangles are rendered that share&#xD;&#xA;&gt; edges. OpenGL offers a guarantee that, so long as the shared edge&#xD;&#xA;&gt; vertex positions are identical, there will be no sample gaps during&#xD;&#xA;&gt; scan conversion.&#xD;&#xA;&#xD;&#xA;1 What exactly are sample gaps during scan conversion? &#xD;&#xA;&#xD;&#xA;2 Under what circumstances, will it happen? &#xD;&#xA;&#xD;&#xA;3 Does it happen when the line cross the center of the fragment?&#xD;&#xA;  [1]: http://alfonse.bitbucket.org/oldtut/Basics/Intro%20Graphics%20and%20Rendering.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="5979" PostHistoryTypeId="4" PostId="2484" RevisionGUID="d21b9e7b-52ed-4023-9edf-e6053822522c" CreationDate="2016-05-23T12:15:53.193" UserId="209" Comment="s/is/are in various places" Text="What are sample gaps during scan conversion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5980" PostHistoryTypeId="5" PostId="2485" RevisionGUID="c8d78e2a-7150-4807-8f19-76df597d70e3" CreationDate="2016-05-23T13:32:52.187" UserId="209" Comment="added 2 characters in body" Text="Assuming a consistent winding order, it means that if you have triangles  ABC and BCD, then if a sample point - that is a test during scan conversion to determine if a point (read pixel) is inside a triangle - lies *exactly* on the shared edge BC, then that sample will belong to *exactly one* of those two triangles. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This avoids both gaps and double filling. The latter would be problematic with, say, translucency or stencil operations.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5983" PostHistoryTypeId="5" PostId="2485" RevisionGUID="40c30bdb-7df2-486e-865a-4ec94dd711f7" CreationDate="2016-05-23T15:47:18.867" UserId="209" Comment="Just realised my answer didn't really address the concerns of the original question" Text="Sample gaps will occur if you don't do things &quot;properly&quot;. &#xD;&#xA;&#xD;&#xA;In OpenGL or D3D, assuming a consistent winding order, if you have triangles  ABC and BCD, then when a sample point - that is a test during scan conversion to determine if a point (read pixel) is inside a triangle - lies *exactly* on the shared edge BC, then that sample will belong to *exactly one* of those two triangles. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This avoids both gaps and double filling. The latter would be problematic with, say, translucency or stencil operations.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5985" PostHistoryTypeId="2" PostId="2486" RevisionGUID="e88a2cc7-40ad-4118-a8aa-5af410f001ee" CreationDate="2016-05-24T04:25:05.057" UserDisplayName="user3412" Text="I have been studying hardware corporation GPU profilers in recent days (Qualcomm, PowerVR, Intel).  I've noticed that these tools seem to give more low-level details  than the GPU profilers I have used in the past -- XCode's OpenGL ES frame capture and apitrace -- which only listed which OpenGL calls were made and what the state of current resources are.&#xD;&#xA;&#xD;&#xA;How do I get started if I want to make a low-level tool that displays things like sampler cache misses and shader assembler code?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5986" PostHistoryTypeId="1" PostId="2486" RevisionGUID="e88a2cc7-40ad-4118-a8aa-5af410f001ee" CreationDate="2016-05-24T04:25:05.057" UserDisplayName="user3412" Text="How to get started writing a low-level GPU profiler?" ContentLicense="CC BY-SA 3.0" />
  <row Id="5987" PostHistoryTypeId="3" PostId="2486" RevisionGUID="e88a2cc7-40ad-4118-a8aa-5af410f001ee" CreationDate="2016-05-24T04:25:05.057" UserDisplayName="user3412" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5988" PostHistoryTypeId="2" PostId="2487" RevisionGUID="67f15de5-dd99-4aab-9146-95608d48e675" CreationDate="2016-05-24T05:06:18.593" UserId="48" Text="For basic GPU timing data, you can use [D3D timestamp queries](http://www.reedbeta.com/blog/2011/10/12/gpu-profiling-101/) or the equivalent [OpenGL timer queries](https://www.opengl.org/wiki/Query_Object#Timer_queries).&#xD;&#xA;&#xD;&#xA;Any low-level hardware data like cache misses is going to be extremely vendor-specific. Each GPU vendor has its own custom API or extension for giving access to low-level performance data on its hardware. The APIs vary in how they work, and they don't necessarily all expose the same details. The available data may also vary between different chip models within the same vendor, so you probably need to know a bit about how the hardware works to make sense of it.&#xD;&#xA;&#xD;&#xA;Here are links to the relevant APIs for most of the main GPU vendors.&#xD;&#xA;&#xD;&#xA;* AMD: [GPUPerfAPI](http://developer.amd.com/tools-and-sdks/graphics-development/gpuperfapi/); see also [AMD_performance_monitor](https://www.opengl.org/registry/specs/AMD/performance_monitor.txt) &#xD;&#xA;* Intel: [Performance Counter Monitor](https://software.intel.com/en-us/articles/intel-performance-counter-monitor) (note: it's not clear to me whether this includes access to GPU counters, or only CPU ones); see also  [INTEL_performance_query](https://www.opengl.org/registry/specs/INTEL/performance_query.txt)&#xD;&#xA;* NVIDIA: [PerfKit](https://developer.nvidia.com/nvidia-perfkit)&#xD;&#xA;* PowerVR: [PVRScope](https://community.imgtec.com/developers/powervr/tools/pvrscope/)&#xD;&#xA;* Qualcomm: [QCOM_performance_monitor_global_mode](https://www.khronos.org/registry/gles/extensions/QCOM/QCOM_performance_monitor_global_mode.txt)" ContentLicense="CC BY-SA 3.0" />
  <row Id="5989" PostHistoryTypeId="2" PostId="2488" RevisionGUID="a8690c0f-7827-4954-b1c1-56239f68c1c5" CreationDate="2016-05-24T08:54:32.497" UserId="2712" Text="I am going through an undocumented function that takes in three points and a Z-value that projects three points on the plane defined by Z-value. I want to understand the mathematical theory behind it and I need your help to decode the function:&#xD;&#xA;&#xD;&#xA;    SlicerSegment project2D(Point3&amp; p0, Point3&amp; p1, Point3&amp; p2, int32_t z) const&#xD;&#xA;    {&#xD;&#xA;        SlicerSegment seg;&#xD;&#xA;        seg.start.X = p0.x + int64_t(p1.x - p0.x) * int64_t(z - p0.z) / int64_t(p1.z - p0.z);&#xD;&#xA;        seg.start.Y = p0.y + int64_t(p1.y - p0.y) * int64_t(z - p0.z) / int64_t(p1.z - p0.z);&#xD;&#xA;&#xD;&#xA;	seg.end.X = p0.x + int64_t(p2.x - p0.x) * int64_t(z - p0.z) / int64_t(p2.z - p0.z);&#xD;&#xA;        seg.end.Y = p0.y + int64_t(p2.y - p0.y) * int64_t(z - p0.z) / int64_t(p2.z - p0.z);&#xD;&#xA;        return seg;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any references/article will be helpful .&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="5990" PostHistoryTypeId="1" PostId="2488" RevisionGUID="a8690c0f-7827-4954-b1c1-56239f68c1c5" CreationDate="2016-05-24T08:54:32.497" UserId="2712" Text="2D projection from some points" ContentLicense="CC BY-SA 3.0" />
  <row Id="5991" PostHistoryTypeId="3" PostId="2488" RevisionGUID="a8690c0f-7827-4954-b1c1-56239f68c1c5" CreationDate="2016-05-24T08:54:32.497" UserId="2712" Text="|graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5992" PostHistoryTypeId="2" PostId="2489" RevisionGUID="fff27286-adc4-48cd-bd18-53cb3bfb40c6" CreationDate="2016-05-24T10:32:27.893" UserId="3424" Text="I'm trying to implement a microfacet BRDF in my raytracer but I'm running into some issues. A lot of the papers and articles I've read define the partial geometry term as a function of the view and half vectors: G1(v, h). However, when implementing this I got the following result: &#xD;&#xA;&#xD;&#xA;[![GGX Geometry term using the half vector][1]][1]&#xD;&#xA;&#xD;&#xA;(Bottom row is dielectric with roughness 1.0 - 0.0, Top row is metallic with roughness 1.0 - 0.0)&#xD;&#xA;&#xD;&#xA;There's a weird highlight around the edges and a cut-off around n.l == 0. I couldn't really figure out where this comes from. I'm using Unity as a reference to check my renders so I checked their shader source to see what they use and from what I can tell their geometry term is not parametrized by the half vector at all! So I tried the same code but used to macro surface normal instead of the half vector and got the following result:&#xD;&#xA;&#xD;&#xA;[![GGX geometry term using the macro surface normal][2]][2]&#xD;&#xA;&#xD;&#xA;To my untrained eye this seems way closer to the desired result. But I have the feeling this is not correct? The majority of the articles I read use the half vector but not all of them. Is there a reason for this difference?&#xD;&#xA;&#xD;&#xA;I use the following code as my geometry term:&#xD;&#xA;&#xD;&#xA;    float RayTracer::GeometryGGX(const Vector3&amp; v, const Vector3&amp; l, const Vector3&amp; n, const Vector3&amp; h, float a)&#xD;&#xA;    {&#xD;&#xA;    	return G1GGX(v, h, a) * G1GGX(l, h, a);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float RayTracer::G1GGX(const Vector3&amp; v, const Vector3&amp; h, float a)&#xD;&#xA;    {&#xD;&#xA;    	float NoV = Util::Clamp01(cml::dot(v, h));&#xD;&#xA;    	float a2 = a * a;&#xD;&#xA;    &#xD;&#xA;    	return (2.0f * NoV) / std::max(NoV + sqrt(a2 + (1.0f - a2) * NoV * NoV), 1e-7f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And for reference, this is my normal distribution function:&#xD;&#xA;&#xD;&#xA;    float RayTracer::DistributionGGX(const Vector3&amp; n, const Vector3&amp; h, float alpha)&#xD;&#xA;    {&#xD;&#xA;    	float alpha2 = alpha * alpha;&#xD;&#xA;    	float NoH = Util::Clamp01(cml::dot(n, h));&#xD;&#xA;    	float denom = (NoH * NoH * (alpha2 - 1.0f)) + 1.0f;&#xD;&#xA;    	return alpha2 / std::max((float)PI * denom * denom, 1e-7f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VGIdx.jpg&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/bnVxb.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="5993" PostHistoryTypeId="1" PostId="2489" RevisionGUID="fff27286-adc4-48cd-bd18-53cb3bfb40c6" CreationDate="2016-05-24T10:32:27.893" UserId="3424" Text="Correct form of the GGX geometry term" ContentLicense="CC BY-SA 3.0" />
  <row Id="5994" PostHistoryTypeId="3" PostId="2489" RevisionGUID="fff27286-adc4-48cd-bd18-53cb3bfb40c6" CreationDate="2016-05-24T10:32:27.893" UserId="3424" Text="|shader|brdf|pbr|microfacet|" ContentLicense="CC BY-SA 3.0" />
  <row Id="5995" PostHistoryTypeId="5" PostId="2483" RevisionGUID="5f618418-e565-4a03-aa97-5d9e54a1d784" CreationDate="2016-05-24T11:25:59.273" UserId="2479" Comment="Added the estimator formula &amp; small minor improvements" Text="TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;Yes, you can do it like that, you just have to divide the result by the probability of choosing the direction.&#xD;&#xA;&#xD;&#xA;Full Answer&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;The topic of sampling in path tracers allowing materials with both reflection and refraction is actually a little bit more complex.&#xD;&#xA;&#xD;&#xA;Let's start with some background first. If you allow BSDFs - not just BRDFs - in your path tracer, you have to integrate over the whole sphere instead of just the positive hemisphere. Monte Carlo samples can be generated by various strategies: for the direct illumination you can use BSDF and light sampling, for the indirect illumination the only meaningful strategy usually is the BSDF sampling. The sampling strategies themselves usually contain the decision about which hemisphere to sample (e.g. whether reflection or refraction is computed).&#xD;&#xA;&#xD;&#xA;In the simplest version, the light sampling usually doesn't take care much about reflection or refraction. It samples the light sources or the environment map (if present) with respect to the light properties. You can improve sampling of environment maps by picking just the hemisphere in which the material has non-zero contribution, but the rest of the material properties is usually ignored. Note that for and ideally smooth Fresnel material the light sampling doesn't work.&#xD;&#xA;&#xD;&#xA;For BSDF sampling, the situation is much more interesting. The case you described deals with an ideal Fresnel surface, where there are only two contributing directions (since Fresnel BSDF is in fact just a sum of two delta functions). You can easily split the integral into a sum of two parts - one reflection and one for refraction. Since, as you mentioned, we don’t want to go in both directions in a path tracer, we have to pick one. This means that we want to estimate the sum of numbers by picking just one of them. This can be done by discrete Monte Carlo estimation: pick one of the addends randomly and divide it by the probability of it being picked. In an ideal case you want to have the sampling probability proportional the the addends, but since we don't know their values (we wouldn't have to estimate the sum if we knew them), we just estimate them by neglecting some of the factors. In this case, we ignore the incoming light amount and use just the Fresnel reflectance/transmittance as our estimates.&#xD;&#xA;&#xD;&#xA;The BSDF sampling routine for the case of smooth Fresnel surface is, therefore, to pick one of the directions randomly with probability proportional to the the Fresnel reflectance and, at some point, divide the result for that direction by probability of picking the direction. The estimator will look like:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac&#xD;&#xA;   {L_{i}\left(\omega_{i}\right)F\left(\theta_{i}\right)}&#xD;&#xA;   {P\left(\omega_{i}\right)} =&#xD;&#xA;\frac&#xD;&#xA;   {L_{i}\left(\omega_{i}\right)F\left(\theta_{i}\right)}&#xD;&#xA;   {F\left(\theta_{i}\right)} =&#xD;&#xA;L_{i}\left(\omega_{i}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $\omega_{i}=\left( \phi_{i}, \theta_{i} \right)$ is the chosen incident light direction, $L_{i}\left(\omega_{i}\right)$ is the amount of incident radiance, $F\left(\theta_{i}\right)$ is either the Fresnel reflectance for the reflection case or 1 - Fresnel reflectance for the refraction case, $P\left(\omega_{i}\right)$ is the discrete probability of picking the direction and is equal to $F\left(\theta_{i}\right)$.&#xD;&#xA;&#xD;&#xA;In case of more sophisticated BSDF models like those based on microfacet theory, the sampling is slightly more complex, but the idea of splitting the whole integral into a finite sum of sub-integrals and using discrete Monte Carlo afterwards can usually be applied too." ContentLicense="CC BY-SA 3.0" />
  <row Id="5996" PostHistoryTypeId="2" PostId="2490" RevisionGUID="8102e05d-2269-40fd-87c8-4a9a58e6cd4b" CreationDate="2016-05-24T12:40:05.170" UserId="2712" Text="I am going through some ideas that slice a 3D model and fill the area of the resulting polygon contour . Currently they are using the following concepts as follows:&#xD;&#xA;&#xD;&#xA;1. Every resulting line of the polygon after the slicing operation has a parent triangle, as the original model is made of triangle .&#xD;&#xA;&#xD;&#xA;2. Each of the triangle has a face normal.&#xD;&#xA;&#xD;&#xA;3. During scan conversion, when a scanline at a particular height intersect any of the polygon contour line, the normal information of the parent triangle is utilized to find out if the intersection is happening while getting into the contour or getting out of the contour. All these information are used to generate the region that are to be filled.&#xD;&#xA;&#xD;&#xA;Then there is another way called the even-odd filling rule. I do not think it is necessary for me to describe it here. I believe that all of you are very well aware of it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My question is which one of it is better option to go with in terms of correctness.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="5997" PostHistoryTypeId="1" PostId="2490" RevisionGUID="8102e05d-2269-40fd-87c8-4a9a58e6cd4b" CreationDate="2016-05-24T12:40:05.170" UserId="2712" Text="Polygon Filling rule - even odd OR orientation of the normal" ContentLicense="CC BY-SA 3.0" />
  <row Id="5998" PostHistoryTypeId="3" PostId="2490" RevisionGUID="8102e05d-2269-40fd-87c8-4a9a58e6cd4b" CreationDate="2016-05-24T12:40:05.170" UserId="2712" Text="|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6000" PostHistoryTypeId="2" PostId="2491" RevisionGUID="ebeabd1d-0062-4d83-b4be-11d788bc101f" CreationDate="2016-05-24T19:11:52.377" UserId="48" Text="The function calculates the intersection points between two edges of a triangle and a plane that is assumed to cut it. It returns a line segment running along the cut.&#xD;&#xA;&#xD;&#xA;Or more generally, the function calculates where the intersection points with the two edges would be, if the edges were extended to infinite lines. Given that it's called &quot;project&quot;, that might be the intended use-case; hard to know without seeing how this gets used in context.&#xD;&#xA;&#xD;&#xA;The first two lines of math are calculating the intersection point of the $p_0 p_1$ edge with the z-plane. It works by linearly interpolating the $x, y$ values along the edge based on the proportion between $z$ values. The second two lines do the same thing for the $p_0 p_2$ edge.&#xD;&#xA;&#xD;&#xA;One odd thing is that the function is using integers everywhere. Presumably it's because the program is using fixed-point coordinates (which makes good sense for a lot of geometry processing applications due to its uniform precision). However, the way it's done here seems oblivious to rounding: the integer divisions will truncate any fractional component instead of rounding to nearest." ContentLicense="CC BY-SA 3.0" />
  <row Id="6003" PostHistoryTypeId="2" PostId="2492" RevisionGUID="95ce0edc-035d-4dc1-89c7-a730e4828817" CreationDate="2016-05-25T08:04:54.230" UserId="38" Text="Let us look at the first line in detail:&#xD;&#xA;&#xD;&#xA;* `int64_t(p1.x - p0.x)` is the distance between p1 and p0 in the x (also y later) direction lets call this `dx` for later discussion.&#xD;&#xA;* `int64_t(z - p0.z)` is the distance from z and p0 for simplicity lets us call this `a` later.&#xD;&#xA;* `int64_t(p1.z - p0.z)` is the distance from z and p0 simplicity lets us call this `b` later.&#xD;&#xA;* lets look at `a/b` well that is simply the length of the ratio of the each point to 0. This equals to how much the vector p1-p0 must be scaled to reach the plane intersection. &#xD;&#xA;&#xD;&#xA;Finally the entire expression is can be read as follows:&#xD;&#xA;&#xD;&#xA;&gt; vector p0 + vector p0-1 * length to intesresction&#xD;&#xA;&#xD;&#xA;And visually its as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The vectors in the calculation, (blue lines sow offsets and projections for feeling of 3D)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iYnJb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6004" PostHistoryTypeId="5" PostId="2492" RevisionGUID="ec421a07-40fb-4241-9cd4-9e849668fab7" CreationDate="2016-05-25T08:18:04.070" UserId="38" Comment="added 506 characters in body" Text="Let us look at the first line in detail:&#xD;&#xA;&#xD;&#xA;* `int64_t(p1.x - p0.x)` is the distance between p1 and p0 in the x (also y later) direction lets call this `dx` for later discussion.&#xD;&#xA;* `int64_t(z - p0.z)` is the distance from z and p0 for simplicity lets us call this `a` later.&#xD;&#xA;* `int64_t(p1.z - p0.z)` is the distance from z and p0 simplicity lets us call this `b` later.&#xD;&#xA;* lets look at `a/b` well that is simply the length of the ratio of the each point to 0. This equals to how much the vector p1-p0 must be scaled to reach the plane intersection. &#xD;&#xA;&#xD;&#xA;Finally the entire expression is can be read as follows:&#xD;&#xA;&#xD;&#xA;&gt; vector p0 + vector p0-1 * length to intesresction&#xD;&#xA;&#xD;&#xA;And visually its as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The vectors in the calculation, (blue lines sow offsets and projections for feeling of 3D)&#xD;&#xA;&#xD;&#xA;And the entire function gives the same for the two edges of your triangle. Please note that it is perfectly possible that the result is degenerate as the choice of what edges to use is not checked for so one edge MIGHT be parallel to the plane. Also selection of points to send changes what is being projected.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: input blue triangle as 3 points (black), return value projected segment in orange on plane.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iYnJb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pKQi8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6005" PostHistoryTypeId="2" PostId="2493" RevisionGUID="02bc5c0e-df54-4b29-9985-c81a6af9a852" CreationDate="2016-05-25T10:19:16.237" UserId="3426" Text="I have a question about finding the symmetry plane that separate the left and the right halves of a point cloud. We scanned an object, say a human face, with a 3D scanner, such as Kinect, which gives a 3D point cloud. Now we want to find the plane that segments the face into symmetrical left and right halves. I found a paper like https://hal.inria.fr/file/index/docid/331758/filename/cvpr2008CombesFinal.pdf, but could not find any code. Though I found the C++ code &quot;CLARCS&quot; doing this work, but it is no only available. Can anyone help to find some code that does this job? Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="6006" PostHistoryTypeId="1" PostId="2493" RevisionGUID="02bc5c0e-df54-4b29-9985-c81a6af9a852" CreationDate="2016-05-25T10:19:16.237" UserId="3426" Text="Symmetry plane estimation for 3D point cloud" ContentLicense="CC BY-SA 3.0" />
  <row Id="6007" PostHistoryTypeId="3" PostId="2493" RevisionGUID="02bc5c0e-df54-4b29-9985-c81a6af9a852" CreationDate="2016-05-25T10:19:16.237" UserId="3426" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6008" PostHistoryTypeId="5" PostId="2493" RevisionGUID="46bf07d2-5312-4ea1-9a14-99af1979efeb" CreationDate="2016-05-25T10:24:07.997" UserId="231" Comment="Remove request for off site resources to prevent question being closed" Text="I have a question about finding the symmetry plane that separate the left and the right halves of a point cloud. We scanned an object, say a human face, with a 3D scanner, such as Kinect, which gives a 3D point cloud. Now we want to find the plane that segments the face into symmetrical left and right halves. I found a paper like https://hal.inria.fr/file/index/docid/331758/filename/cvpr2008CombesFinal.pdf, but could not find any code. Though I found the C++ code &quot;CLARCS&quot; doing this work, but it is no only available." ContentLicense="CC BY-SA 3.0" />
  <row Id="6009" PostHistoryTypeId="5" PostId="2493" RevisionGUID="e265ba0d-2fae-4e5f-a7a1-3ec7f85aa07b" CreationDate="2016-05-25T10:25:08.537" UserId="3426" Comment="added 2 characters in body" Text="I have a question about finding the symmetry plane that separate the left and the right halves of a point cloud. We scanned an object, say a human face, with a 3D scanner, such as Kinect, which gives a 3D point cloud. Now we want to find the plane that segments the face into symmetrical left and right halves. I found a paper like https://hal.inria.fr/file/index/docid/331758/filename/cvpr2008CombesFinal.pdf, but could not find any code. Though I found the C++ code &quot;CLARCS&quot; doing this work, but it is no longer available." ContentLicense="CC BY-SA 3.0" />
  <row Id="6010" PostHistoryTypeId="5" PostId="2493" RevisionGUID="de75c1c5-093c-4385-930f-938ba9173e4b" CreationDate="2016-05-25T10:26:46.230" UserId="3426" Comment="added 2 characters in body" Text="I have a question about finding the symmetry plane that separate the left and the right halves of a point cloud. We scanned an object, say a human face, with a 3D scanner, such as Kinect, which gives a 3D point cloud. Now we want to find the plane that segments the face into symmetrical left and right halves. I found a paper like https://hal.inria.fr/file/index/docid/331758/filename/cvpr2008CombesFinal.pdf, but could not find any code. Though I found the C++ code &quot;CLARCS&quot; doing this work, but it is no longer available. Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="6011" PostHistoryTypeId="5" PostId="2492" RevisionGUID="f8f70a73-8bfb-488f-aa6a-8c91559983ca" CreationDate="2016-05-25T10:51:25.760" UserId="38" Comment="deleted 1 character in body" Text="Let us look at the first line in detail:&#xD;&#xA;&#xD;&#xA;* `int64_t(p1.x - p0.x)` is the distance between p1 and p0 in the x (also y later) direction lets call this `dx` for later discussion.&#xD;&#xA;* `int64_t(z - p0.z)` is the distance from z and p0 for simplicity lets us call this `a` later.&#xD;&#xA;* `int64_t(p1.z - p0.z)` is the distance from z and p0 simplicity lets us call this `b` later.&#xD;&#xA;* lets look at `a/b` well that is simply the length of the ratio of the each point to 0. This equals to how much the vector p1-p0 must be scaled to reach the plane intersection. &#xD;&#xA;&#xD;&#xA;Finally the entire expression is can be read as follows:&#xD;&#xA;&#xD;&#xA;&gt; vector p0 + vector p0-1 * length to intersection&#xD;&#xA;&#xD;&#xA;And visually its as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The vectors in the calculation, (blue lines sow offsets and projections for feeling of 3D)&#xD;&#xA;&#xD;&#xA;And the entire function gives the same for the two edges of your triangle. Please note that it is perfectly possible that the result is degenerate as the choice of what edges to use is not checked for so one edge MIGHT be parallel to the plane. Also selection of points to send changes what is being projected.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: input blue triangle as 3 points (black), return value projected segment in orange on plane.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iYnJb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pKQi8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6012" PostHistoryTypeId="2" PostId="2494" RevisionGUID="17b5719b-f2a3-439a-9acf-a7c23fdde304" CreationDate="2016-05-25T13:24:03.887" UserId="182" Text="The well known [Schlick approximation][1] of the Fresnel coefficient gives the equation:&#xD;&#xA;&#xD;&#xA;$F=F_0+(1 - F_0)(1 - cos(\theta))^5$&#xD;&#xA;&#xD;&#xA;And $cos(\theta)$ is equal to the dot product of the surface normal vector and the view vector.&#xD;&#xA;&#xD;&#xA;It is still unclear to me though if we should use the actual surface normal $N$ or the half vector $H$. Which should be used in a physically based BRDF and why?&#xD;&#xA;&#xD;&#xA;Moreover, as far as I understand the Fresnel coefficient gives the probability of a given ray to either get reflected or refracted. So I have trouble seeing why we can still use that formula in a BRDF, which is supposed to approximate the integral over all the hemisphere.&#xD;&#xA;&#xD;&#xA;This observation would tend to make me think this is where $H$ would come, but it is not obvious to me that the Fresnel of a representative normal is equivalent to integrating the Fresnel of all the actual normals.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Schlick's_approximation" ContentLicense="CC BY-SA 3.0" />
  <row Id="6013" PostHistoryTypeId="1" PostId="2494" RevisionGUID="17b5719b-f2a3-439a-9acf-a7c23fdde304" CreationDate="2016-05-25T13:24:03.887" UserId="182" Text="In a physically based BRDF, what vector should be used to compute the Fresnel coefficient?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6014" PostHistoryTypeId="3" PostId="2494" RevisionGUID="17b5719b-f2a3-439a-9acf-a7c23fdde304" CreationDate="2016-05-25T13:24:03.887" UserId="182" Text="|brdf|pbr|integral|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6015" PostHistoryTypeId="2" PostId="2495" RevisionGUID="ae143517-3a99-4552-8482-cdc800400e6f" CreationDate="2016-05-25T14:42:49.120" UserId="310" Text="In Schlick's 1994 paper, [&quot;An Inexpensive Model for Physically-Based Rendering&quot;][1], where they derive the approximation, the formula is:&#xD;&#xA;$$F_{\lambda}(u) = f_{\lambda} + (1 - f_{\lambda})(1 - u)^{5}$$&#xD;&#xA;&#xD;&#xA;Where [![Description of vectors][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, to answer your first question, $\theta$ refers to the angle between the view vector and the half vector. Consider for a minute that the surface is a perfect mirror. So:&#xD;&#xA;$$V \equiv reflect(V')$$&#xD;&#xA;In this case:&#xD;&#xA;$$N \equiv H$$&#xD;&#xA;&#xD;&#xA;For microfacet-base BRDFs, the $D(h_{r})$ term refers to the statistical percentage of microfacet normals that are oriented towards $H$. So it makes sense to use $H$ for the Fresnel term as well.&#xD;&#xA;&#xD;&#xA;As for why we use Fresnel in a BRDF, it has to do with the fact that a BRDF by itself is only a portion of the full BSDF. A BRDF attenuates the reflected portion of light and a BTDF attenuates the refracted. We use the Fresnel to calculate the amount of reflected and refracted light, so we can properly attenuate it with the BRDF and BTDF.&#xD;&#xA;&#xD;&#xA;$$BSDF = BRDF + BSDF\\&#xD;&#xA;$$&#xD;&#xA;$$\begin{align*}&#xD;&#xA;L_{\text{o}}(p, \omega_{\text{o}}) &amp;=  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BSDF * L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} \\&#xD;&#xA; &amp;= L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BRDF * L_{\text{i, reflected}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}  \ + \  \int_{\Omega} BTDF * L_{\text{i, refracted}}(p, \omega_{\text{i}}) * \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/xxyc2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6016" PostHistoryTypeId="2" PostId="2496" RevisionGUID="b7b9eafc-fb55-4102-b5b8-d5f5c80d6e37" CreationDate="2016-05-25T15:27:13.490" UserId="3339" Text="I was reading a paper on BRDF. I've come across this formula :&#xD;&#xA;$$ f(\omega_i, \omega_o ) = \frac{FDG}{4(N.V)(N.L)}$$ &#xD;&#xA;&#xD;&#xA;The (N.L) term can be cancelled by the cosine term which appears in the rendering equation :&#xD;&#xA;&#xD;&#xA;$$ L_o = \int f(\omega_i, \omega_o) L_i cos(\theta) d\omega_i $$&#xD;&#xA;&#xD;&#xA;What about the (N.V) term ? What happens if (N.V) = 0 ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6017" PostHistoryTypeId="1" PostId="2496" RevisionGUID="b7b9eafc-fb55-4102-b5b8-d5f5c80d6e37" CreationDate="2016-05-25T15:27:13.490" UserId="3339" Text="What is the effect of the BRDF denominator?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6018" PostHistoryTypeId="3" PostId="2496" RevisionGUID="b7b9eafc-fb55-4102-b5b8-d5f5c80d6e37" CreationDate="2016-05-25T15:27:13.490" UserId="3339" Text="|raytracing|color|brdf|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6019" PostHistoryTypeId="2" PostId="2497" RevisionGUID="f0f6677d-5c45-4d81-b6ee-cab0d7ce8f59" CreationDate="2016-05-25T15:38:02.133" UserId="3339" Text="Thanks for your answers. That was helpfull.&#xD;&#xA;&#xD;&#xA;This is how I understand the 1/r² term for point source (tell me if I'm wrong).&#xD;&#xA;Let's take the BRDF definition :&#xD;&#xA;&#xD;&#xA;$$ L_o = \int f(\omega, \omega_o) dE$$&#xD;&#xA;&#xD;&#xA;Now, we have to answer this question : How is the Irradiance E distributed ?&#xD;&#xA;For one point source, we have : $$ dE = \delta(\omega_i-\omega)E d\omega $$&#xD;&#xA;The irradiance is only comming from one direction (the point source). Therfore, we can simplify the equation :&#xD;&#xA;&#xD;&#xA;$$ L_o = \int f(\omega, \omega_o) \delta(\omega_i-\omega)E d\omega = f(\omega_i, \omega_o) E$$ &#xD;&#xA;We can use the relation between the intensity I of the point source and E $$ E = cos(\theta_i)I/r² $$&#xD;&#xA;Finally : $$ L_o = f(\omega_i, \omega_o) cos(\theta_i)I/r² $$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6020" PostHistoryTypeId="2" PostId="2498" RevisionGUID="cebb6935-c6a6-49fa-a800-b458940f4fdc" CreationDate="2016-05-25T16:05:41.587" UserId="1810" Text="Don't forget that at the end this is to be integrated in some cone (e.g. pixel footprint).&#xD;&#xA;Then the visible cross section of differential surface dN is also be $(N\cdot V)$." ContentLicense="CC BY-SA 3.0" />
  <row Id="6021" PostHistoryTypeId="5" PostId="2495" RevisionGUID="4503ae8b-08c3-4152-984a-c6a8ff14906b" CreationDate="2016-05-25T16:21:14.240" UserId="310" Comment="Add some clarification" Text="In Schlick's 1994 paper, [&quot;An Inexpensive Model for Physically-Based Rendering&quot;][1], where they derive the approximation, the formula is:&#xD;&#xA;$$F_{\lambda}(u) = f_{\lambda} + (1 - f_{\lambda})(1 - u)^{5}$$&#xD;&#xA;&#xD;&#xA;Where [![Description of vectors][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, to answer your first question, $\theta$ refers to the angle between the view vector and the half vector. Consider for a minute that the surface is a perfect mirror. So:&#xD;&#xA;$$V \equiv reflect(V')$$&#xD;&#xA;In this case:&#xD;&#xA;$$N \equiv H$$&#xD;&#xA;&#xD;&#xA;For microfacet-base BRDFs, the $D(h_{r})$ term refers to the statistical percentage of microfacet normals that are oriented towards $H$. Aka, what percentage of the incoming light will bounce in the outgoing direction.&#xD;&#xA;&#xD;&#xA;As for why we use Fresnel in a BRDF, it has to do with the fact that a BRDF by itself is only a portion of the full BSDF. A BRDF attenuates the reflected portion of light and a BTDF attenuates the refracted. We use the Fresnel to calculate the amount of reflected vs. refracted light, so we can properly attenuate it with the BRDF and BTDF.&#xD;&#xA;&#xD;&#xA;$$BSDF = BRDF + BSDF\\&#xD;&#xA;$$&#xD;&#xA;$$\begin{align*}&#xD;&#xA;L_{\text{o}}(p, \omega_{\text{o}}) &amp;=  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BSDF * L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} \\&#xD;&#xA; &amp;= L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BRDF * L_{\text{i, reflected}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}  \ + \  \int_{\Omega} BTDF * L_{\text{i, refracted}}(p, \omega_{\text{i}}) * \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;So, in summary, we use $D$ to get the percentage of light that will bounce in the outgoing direction, and $F$, to find out what percentage of the remaining light will reflect/refract. Both these use $H$, because that is the surface orientation that allows a mirror reflection between $V$ and $V'$&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/xxyc2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6022" PostHistoryTypeId="2" PostId="2499" RevisionGUID="5f415116-5300-4c37-bc3c-55698a472af2" CreationDate="2016-05-25T17:08:37.117" UserId="310" Text="Firstly, I highly suggest reading Eric Heitz's paper &quot;[Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs][1]&quot;, which covers the full derivation of microfacet-based BRDFs. &#xD;&#xA;&#xD;&#xA;The $\frac{1}{4(N \cdot V)(N \cdot L)}$ term is a side effect of the derivation of the BRDF for specular microfacets. Specifically, it comes from the Jacobian of the reflection transformation. See the paper and/or [Walter et. al's 2007 paper][2] for more details.&#xD;&#xA;&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;As for your concern for a divide by zero, the definition of the rendering equation prevents it. Let me explain:&#xD;&#xA;&#xD;&#xA;For $(N \cdot V)$ to equal zero, they must be orthogonal. In this case, the visibility term of the rendering equation will cull the cases at / below the horizon.&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/hal-00942452v2/document&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6023" PostHistoryTypeId="5" PostId="2497" RevisionGUID="20dcdac9-fb28-4295-a21f-473a4ccefb2d" CreationDate="2016-05-25T18:45:30.017" UserId="48" Comment="improved math formatting" Text="Thanks for your answers. That was helpfull.&#xD;&#xA;&#xD;&#xA;This is how I understand the 1/r² term for point source (tell me if I'm wrong).&#xD;&#xA;Let's take the BRDF definition :&#xD;&#xA;&#xD;&#xA;$$ L_o = \int f(\omega, \omega_o) \, dE$$&#xD;&#xA;&#xD;&#xA;Now, we have to answer this question : How is the Irradiance E distributed ?&#xD;&#xA;For one point source, we have : $$ dE = \delta(\omega_i-\omega)E \, d\omega $$&#xD;&#xA;The irradiance is only comming from one direction (the point source). Therfore, we can simplify the equation :&#xD;&#xA;&#xD;&#xA;$$ L_o = \int f(\omega, \omega_o) \delta(\omega_i-\omega)E \, d\omega = f(\omega_i, \omega_o) E$$ &#xD;&#xA;We can use the relation between the intensity I of the point source and E $$ E = cos(\theta_i)I/r^2 $$&#xD;&#xA;Finally : $$ L_o = f(\omega_i, \omega_o) cos(\theta_i)I/r^2 $$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6024" PostHistoryTypeId="2" PostId="2500" RevisionGUID="59f1466a-fbbc-4503-a15b-6633b95f26a3" CreationDate="2016-05-25T18:49:13.150" UserId="2308" Text="Ok this is hard to explain but I am going to try, then I will explain it as pure mathematics.&#xD;&#xA;&#xD;&#xA;Look at this image.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;So basically this is a moving line, each frame a new segment is added and the previous frame is faded by an amount decided by fps. (their are dots to make things neat but im not showing them for simplicity).&#xD;&#xA;&#xD;&#xA;So based on the fps a number is calculated (0.05 if perfect fps) and as a result the previous frame gets a black plane drawn over it with an opacity of 0.05.&#xD;&#xA;&#xD;&#xA;As you can see this causes an issue because of the segments. My solution is to give each vertex a color, however I dont know how to calculate that color.  The line color is defined by hsv, and the fading is decided by rgb.  Furthermore I am pretty sure fading with the transparent plane creates an exponential effect, however HSV.V works linearly.&#xD;&#xA;&#xD;&#xA;My question is if I know on a given frame that the fading plane will have an opacity of 0.05 how can I calculate an equivalent HSV color to what the previous frame will be after fading? That way the bottom two vertices can be a darker color and interpolation can fix it.&#xD;&#xA;&#xD;&#xA;Thanks much!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jBASF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="6025" PostHistoryTypeId="1" PostId="2500" RevisionGUID="59f1466a-fbbc-4503-a15b-6633b95f26a3" CreationDate="2016-05-25T18:49:13.150" UserId="2308" Text="Matching a hsv color with a blended color" ContentLicense="CC BY-SA 3.0" />
  <row Id="6026" PostHistoryTypeId="3" PostId="2500" RevisionGUID="59f1466a-fbbc-4503-a15b-6633b95f26a3" CreationDate="2016-05-25T18:49:13.150" UserId="2308" Text="|opengl|color|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6027" PostHistoryTypeId="5" PostId="2500" RevisionGUID="03918de6-17a6-48c0-9486-732c04726792" CreationDate="2016-05-25T19:15:22.323" UserId="2308" Comment="added 101 characters in body" Text="Ok this is hard to explain but I am going to try, then I will explain it as pure mathematics.&#xD;&#xA;&#xD;&#xA;Look at this image.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;So basically this is a moving line, each frame a new segment is added and the previous frame is faded by an amount decided by fps. (their are dots to make things neat but im not showing them for simplicity).&#xD;&#xA;&#xD;&#xA;So based on the fps a number is calculated (0.05 if perfect fps) and as a result the previous frame gets a black plane drawn over it with an opacity of 0.05.&#xD;&#xA;&#xD;&#xA;As you can see this causes an issue because of the segments. My solution is to give each vertex a color, however I dont know how to calculate that color.  The line color is defined by hsv, and the fading is decided by rgb.  Furthermore I am pretty sure fading with the transparent plane creates an exponential effect, however HSV.V works linearly.&#xD;&#xA;&#xD;&#xA;My question is if I know on a given frame that the fading plane will have an opacity of 0.05 how can I calculate an equivalent HSV color to what the previous frame will be after fading? That way the bottom two vertices can be a darker color and interpolation can fix it.&#xD;&#xA;&#xD;&#xA;Thanks much!&#xD;&#xA;&#xD;&#xA;PS The formula that decides the opacity of the black is as follows. &#xD;&#xA;&#xD;&#xA;    (dt / (1 / 60)) * 0.5&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jBASF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="6028" PostHistoryTypeId="2" PostId="2501" RevisionGUID="56955df6-bcc6-42b5-9a6d-87cd9538ac02" CreationDate="2016-05-25T20:40:55.557" UserId="2214" Text="Let's assume I have the following cube.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zyfHW.png&#xD;&#xA;&#xD;&#xA;Let's assume the isovalue = 0. I would like to draw the resulting triangles of the isosurface.&#xD;&#xA;&#xD;&#xA;I know that first I define which values are inside or outside comparing them to the given isovalue and after that we correspond to a particular list of edges.&#xD;&#xA;&#xD;&#xA;After that, we have somehow to linearly interpolate the points.&#xD;&#xA;I have read on an article that using this formula $P = P_1 + \frac{(iso -v_1)(P_2-P_1)}{V_2-V_1}$ we can get the interpolated values. &#xD;&#xA;&#xD;&#xA;Can someone demonstrate to me how I can interpolate the points in this case ? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6029" PostHistoryTypeId="1" PostId="2501" RevisionGUID="56955df6-bcc6-42b5-9a6d-87cd9538ac02" CreationDate="2016-05-25T20:40:55.557" UserId="2214" Text="Linear interpolation on Plane (Marching Cubes)" ContentLicense="CC BY-SA 3.0" />
  <row Id="6030" PostHistoryTypeId="3" PostId="2501" RevisionGUID="56955df6-bcc6-42b5-9a6d-87cd9538ac02" CreationDate="2016-05-25T20:40:55.557" UserId="2214" Text="|algorithm|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6031" PostHistoryTypeId="2" PostId="2502" RevisionGUID="b04cc665-e5a9-44aa-a935-f013b32ea9d6" CreationDate="2016-05-25T20:55:50.740" UserId="1810" Text="The opacity acts linearly through the colors, i.e. it affects R G B similarily, so it should affects the value V the same way.&#xD;&#xA;You just want to have an intensity factor decay as $0.95^n$." ContentLicense="CC BY-SA 3.0" />
  <row Id="6032" PostHistoryTypeId="2" PostId="2503" RevisionGUID="5ab13636-87eb-4376-a220-612f27f0c3c4" CreationDate="2016-05-25T21:01:16.457" UserId="1810" Text="You can use this formula on each edge where one point is &lt; isovalue and the other is &gt; .&#xD;&#xA;Then you link together the points belonging to the same square to form the edges of your iso-mesh. &#xD;&#xA;Then you make polygons by linking edges sharing a vertex. In case of more than 3 sides (could be up to 6), it's up to you to prefer spliting the polygon into triangles.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6037" PostHistoryTypeId="6" PostId="2488" RevisionGUID="d1c9721d-a432-4394-a513-5e81df298ec1" CreationDate="2016-05-25T22:42:44.653" UserId="231" Comment="edited tags" Text="|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6038" PostHistoryTypeId="2" PostId="2505" RevisionGUID="58e36ae8-6e7c-4cc7-b99f-ef8ca6bf3d55" CreationDate="2016-05-25T22:43:42.677" UserId="48" Text="The Fresnel coefficient should be evaluated using $H$, not $N$.&#xD;&#xA;&#xD;&#xA;You wrote,&#xD;&#xA;&#xD;&#xA;&gt; I have trouble seeing why we can still use that formula in a BRDF, which is supposed to approximate the integral over all the hemisphere.&#xD;&#xA;&#xD;&#xA;It's not. The BRDF in itself does not approximate the integral over all the hemisphere. The rendering equation does that: you integrate over all incoming light directions, but each time the BRDF inside the integral is evaluated, it's for _one specific choice_ of incoming and outgoing ray directions.&#xD;&#xA;&#xD;&#xA;For microfacet BRDFs, the usual simplifying assumption is that individual microfacets are perfect specular reflectors. Then, given the $L$ and $V$ at which to evaluate, the _only_ microfacets that can contribute are those that are aligned along $H = \text{normalize}(L+V)$, because that's the only way they can reflect light from the incoming to the outgoing ray.&#xD;&#xA;&#xD;&#xA;The normal distribution function and the visibility factor in the BRDF together approximate the density of microfacets oriented along $H$ that are visible from both the $L$ and $V$ directions. The Fresnel factor is evaluated _for those microfacets_, so the correct angle to use is the one between $L$ and $H$, or equivalently $V$ and $H$.&#xD;&#xA;&#xD;&#xA;There are a couple cases where this argument gets modified. One is if the microfacet model assumes something other than perfect specularity. For instance, the [Oren-Nayar BRDF](https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model) assumes Lambertian microfacets. In this case the BRDF has to incorporate some kind of integral over all the possible microfacet orientations that can scatter light from $L$ to $V$. Then the BRDF won't have a standard Fresnel factor at all; it'll have some other formula that approximates the result of integrating the Fresnel factor over the normal hemisphere.&#xD;&#xA;&#xD;&#xA;The other case that comes up in real-time graphics is the reflection from an environment map. To be really correct, we should integrate the environment map multiplied by the BRDF over all incoming light directions, but in practice we often sample a prefiltered environment map using the dominant reflection vector $R = \text{reflect}(V, N)$ and then multiply it by some approximate Fresnel formula that depends on the angle between $R$ and $N$ (equivalently $V$ and $N$), as well as the surface roughness. This is very much an approximation, but often good enough for real-time use." ContentLicense="CC BY-SA 3.0" />
  <row Id="6039" PostHistoryTypeId="5" PostId="2492" RevisionGUID="2dc32ca0-634f-4b0e-b6a4-9f56661aaf08" CreationDate="2016-05-26T06:02:16.920" UserId="38" Comment="added 22 characters in body" Text="Let us look at the first line in detail:&#xD;&#xA;&#xD;&#xA;* `int64_t(p1.x - p0.x)` is the distance between p1 and p0 in the x (also y later) direction lets call this `dx` for later discussion.&#xD;&#xA;* `int64_t(z - p0.z)` is the distance from z and p0 for simplicity lets us call this `a` later.&#xD;&#xA;* `int64_t(p1.z - p0.z)` is the distance from p0 and p1 or vector length simplicity lets us call this `len` later.&#xD;&#xA;* lets look at `a/len` well that is simply the length of the ratio of the each point to 0. This equals to how much the vector p1-p0 must be scaled to reach the plane intersection. &#xD;&#xA;&#xD;&#xA;Finally the entire expression is can be read as follows:&#xD;&#xA;&#xD;&#xA;&gt; vector p0 + vector p0-1 * length to intersection&#xD;&#xA;&#xD;&#xA;And visually its as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The vectors in the calculation, (blue lines sow offsets and projections for feeling of 3D)&#xD;&#xA;&#xD;&#xA;And the entire function gives the same for the two edges of your triangle. Please note that it is perfectly possible that the result is degenerate as the choice of what edges to use is not checked for so one edge MIGHT be parallel to the plane. Also selection of points to send changes what is being projected.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: input blue triangle as 3 points (black), return value projected segment in orange on plane.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iYnJb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pKQi8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6041" PostHistoryTypeId="2" PostId="2506" RevisionGUID="c0f22718-0e84-4776-95ad-a52314f178e2" CreationDate="2016-05-26T08:59:25.520" UserId="2214" Text="Let's assume that in a triangle we have computed the brightness on the vertices of a triangle and we have found that it is maximum. &#xD;&#xA;&#xD;&#xA;Can any other point which lies on that triangle have more brightness than the maximum brightness on those vertices ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6042" PostHistoryTypeId="1" PostId="2506" RevisionGUID="c0f22718-0e84-4776-95ad-a52314f178e2" CreationDate="2016-05-26T08:59:25.520" UserId="2214" Text="Surface shading on an triangle" ContentLicense="CC BY-SA 3.0" />
  <row Id="6043" PostHistoryTypeId="3" PostId="2506" RevisionGUID="c0f22718-0e84-4776-95ad-a52314f178e2" CreationDate="2016-05-26T08:59:25.520" UserId="2214" Text="|shading|brightness|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6044" PostHistoryTypeId="2" PostId="2507" RevisionGUID="6d45b4cc-0d0b-4d04-9ce4-a7be6343fb8b" CreationDate="2016-05-26T09:09:22.663" UserId="209" Text="That completely depends on how you are computing the shading. If you are then just linearly interpolating the shaded colours across the triangle, i.e. [Gouraud shading](https://en.wikipedia.org/wiki/Gouraud_shading) then, clearly, the answer is &quot;no&quot;.&#xD;&#xA;&#xD;&#xA;However, if you are doing per-pixel shading by, say, interpolating normals and light directions, then you can easily get a brighter area away from the vertices." ContentLicense="CC BY-SA 3.0" />
  <row Id="6045" PostHistoryTypeId="2" PostId="2508" RevisionGUID="391d8788-0ec2-41c3-aebd-8071f52103ec" CreationDate="2016-05-26T11:39:20.120" UserId="386" Text="I'm working with `DirectCompute`, but this question can be applied to general gpu programming I suppose.&#xD;&#xA;&#xD;&#xA;As far as I know the threads in a group works in a lockstep. It means that every instruction for every thread executes at the same time, right? But what if one thread out of `1024` entered `if/else` condition? All other `1023` will just wait or lockstep condition will be violated?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6046" PostHistoryTypeId="1" PostId="2508" RevisionGUID="391d8788-0ec2-41c3-aebd-8071f52103ec" CreationDate="2016-05-26T11:39:20.120" UserId="386" Text="Threads lockstep and conditions in compute shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="6047" PostHistoryTypeId="3" PostId="2508" RevisionGUID="391d8788-0ec2-41c3-aebd-8071f52103ec" CreationDate="2016-05-26T11:39:20.120" UserId="386" Text="|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6048" PostHistoryTypeId="2" PostId="2509" RevisionGUID="2585e78f-fd82-4331-98e9-078dd89e20da" CreationDate="2016-05-26T12:02:55.647" UserId="137" Text="Not all threads will execute in lockstep but they are split into groups whose threads are locked to each other.&#xD;&#xA;&#xD;&#xA;This means that if only 1 thread out of all threads enters a branch then only 1 group will need to enter that branch while all the others will skip it.&#xD;&#xA;&#xD;&#xA;In that group that has to execute both branches it will actually execute both branches but threads will throw away the result of the branch that it didn't need to go into.&#xD;&#xA;&#xD;&#xA;For more information [see this question][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/q/280/137" ContentLicense="CC BY-SA 3.0" />
  <row Id="6049" PostHistoryTypeId="2" PostId="2510" RevisionGUID="4dd7285e-063a-499c-9459-184b96fb8e61" CreationDate="2016-05-26T13:04:36.520" UserId="2712" Text="I am going through the Vatti Arbitrary Polygon Clipping Algorithm, but got stuck at their very initial explanation . It says the following:&#xD;&#xA;&#xD;&#xA;&quot;Call an edge of a polygon a left or right edge if the interior of the polygon is to the right or left,&#xD;&#xA;respectively. Horizontal edges are considered to be both left and right edges. A key fact that is used by the&#xD;&#xA;Vatti algorithm is that polygons can be represented via a set of left and right bounds which are connected&#xD;&#xA;lists of left and right edges, respectively, that come in pairs. Each of these bounds starts at a local&#xD;&#xA;minimum of the polygon and ends at a local maximum. Consider the &quot;polygon&quot; with vertices p 0 , p 1 , ...,&#xD;&#xA;p 8 shown in Figure 1(a). The two left bounds have vertices p 0 , p 8 , p 7 , p 6 and p 4 , p 3 , p 2 , respectively. The&#xD;&#xA;two right bounds have vertices p 0 , p 1 , p 2 and p 4 , p 5 , p 6 .&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The image it refers is :&#xD;&#xA;&#xD;&#xA;[Image Link][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://imgur.com/cWpcjyX&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I do not understand the vertices of the second left bound (p4,p3,p2). How these vertices are derived ?. Some explanation is requested ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="6050" PostHistoryTypeId="1" PostId="2510" RevisionGUID="4dd7285e-063a-499c-9459-184b96fb8e61" CreationDate="2016-05-26T13:04:36.520" UserId="2712" Text="some explanation from vatti clipping algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="6051" PostHistoryTypeId="3" PostId="2510" RevisionGUID="4dd7285e-063a-499c-9459-184b96fb8e61" CreationDate="2016-05-26T13:04:36.520" UserId="2712" Text="|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6052" PostHistoryTypeId="5" PostId="2510" RevisionGUID="c40d377c-1829-441c-9709-a87a87dfea12" CreationDate="2016-05-26T13:25:53.437" UserId="137" Comment="formatting and image" Text="I am going through the Vatti Arbitrary Polygon Clipping Algorithm, but got stuck at their very initial explanation. It says the following:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Call an edge of a polygon a left or right edge if the interior of the&#xD;&#xA;&gt; polygon is to the right or left, respectively. Horizontal edges are&#xD;&#xA;&gt; considered to be both left and right edges. A key fact that is used by&#xD;&#xA;&gt; the Vatti algorithm is that polygons can be represented via a set of&#xD;&#xA;&gt; left and right bounds which are connected lists of left and right&#xD;&#xA;&gt; edges, respectively, that come in pairs. Each of these bounds starts&#xD;&#xA;&gt; at a local minimum of the polygon and ends at a local maximum.&#xD;&#xA;&gt; Consider the &quot;polygon&quot; with vertices $\{p_0, p_1, ..., p_8\}$ shown in&#xD;&#xA;&gt; Figure 1(a). The two left bounds have vertices $\{p_0, p_8, p_7, p_6\}$ and $\{p_4, p_3, p_2\}$ , respectively. The two right bounds&#xD;&#xA;&gt; have vertices $\{p_0, p_1, p_2\}$ and $\{p_4, p_5, p_6\}$ .&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The image it refers is :&#xD;&#xA;&#xD;&#xA;![Image Link][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fFx6m.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I do not understand the vertices of the second left bound $\{p_4,p_3,p_2\}$. How these vertices are derived? " ContentLicense="CC BY-SA 3.0" />
  <row Id="6053" PostHistoryTypeId="5" PostId="2510" RevisionGUID="bb228f5b-36e4-4682-9b4b-89f26a601c5f" CreationDate="2016-05-26T13:43:45.090" UserId="231" Comment="Minor tidying; edited tags" Text="I am going through the Vatti Arbitrary Polygon Clipping Algorithm, but got stuck at their very initial explanation. It says the following:&#xD;&#xA;&#xD;&#xA;&gt; Call an edge of a polygon a left or right edge if the interior of the polygon is to the right or left, respectively. Horizontal edges are considered to be both left and right edges. A key fact that is used by the Vatti algorithm is that polygons can be represented via a set of left and right bounds which are connected lists of left and right edges, respectively, that come in pairs. Each of these bounds starts at a local minimum of the polygon and ends at a local maximum. Consider the &quot;polygon&quot; with vertices $\{p_0, p_1, ..., p_8\}$ shown in Figure 1(a). The two left bounds have vertices $\{p_0, p_8, p_7, p_6\}$ and $\{p_4, p_3, p_2\}$, respectively. The two right bounds have vertices $\{p_0, p_1, p_2\}$ and $\{p_4, p_5, p_6\}$.&#xD;&#xA;&#xD;&#xA;The image it refers to is:&#xD;&#xA;&#xD;&#xA;[![Image showing polygon vertices][1]][1]&#xD;&#xA;&#xD;&#xA;I do not understand the vertices of the second left bound $\{p_4,p_3,p_2\}$. How are these vertices derived? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fFx6m.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6054" PostHistoryTypeId="4" PostId="2510" RevisionGUID="bb228f5b-36e4-4682-9b4b-89f26a601c5f" CreationDate="2016-05-26T13:43:45.090" UserId="231" Comment="Minor tidying; edited tags" Text="Explanation of the Vatti clipping algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="6055" PostHistoryTypeId="6" PostId="2510" RevisionGUID="bb228f5b-36e4-4682-9b4b-89f26a601c5f" CreationDate="2016-05-26T13:43:45.090" UserId="231" Comment="Minor tidying; edited tags" Text="|algorithm|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6057" PostHistoryTypeId="5" PostId="32" RevisionGUID="f0bf7c7d-dcfe-4ce8-90fc-7545df06b3d7" CreationDate="2016-05-26T18:05:06.767" UserId="17" Comment="Improved spelling and grammar." Text="From my basic understanding, a Vertex Buffer Object works something like this (psuedo code):&#xD;&#xA;&#xD;&#xA;&gt; Normally, if one wanted to say, draw a square, one could issue line drawing commands.&#xD;&#xA;&#xD;&#xA;&gt;     line (0, 0) -&gt; (1, 0)&#xD;&#xA;&gt;     line (1, 0) -&gt; (1, 1)&#xD;&#xA;&gt;     line (1, 1) -&gt; (0, 1)&#xD;&#xA;&gt;     line (0, 1) -&gt; (0, 0)&#xD;&#xA;&#xD;&#xA;&gt; Using a VBO, if I understand correctly, would load the vertices into a VBO.&#xD;&#xA;&#xD;&#xA;&gt;     define VBO&#xD;&#xA;&gt;     load (0,0) -&gt; VBO&#xD;&#xA;&gt;     load (1,0) -&gt; VBO&#xD;&#xA;&gt;     load (1,1) -&gt; VBO&#xD;&#xA;&gt;     load (0,1) -&gt; VBO&#xD;&#xA;&gt;     load (0,0) -&gt; VBO&#xD;&#xA;&#xD;&#xA;&gt; Then you can issue one drawing command.&#xD;&#xA;&#xD;&#xA;&gt;     draw VBO vertices&#xD;&#xA;    &#xD;&#xA;While I understand how VBOs work, I don't know why they improve performance. &#xD;&#xA;&#xD;&#xA;How do they improve performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6058" PostHistoryTypeId="5" PostId="2492" RevisionGUID="dbf1076b-4bbb-4fba-8b6b-9a3dd6d80b6c" CreationDate="2016-05-26T18:38:36.873" UserId="38" Comment="added 2 characters in body" Text="Let us look at the first line in detail:&#xD;&#xA;&#xD;&#xA;* `int64_t(p1.x - p0.x)` is the distance between p1 and p0 in the x (also y later) direction lets call this `dx` for later discussion.&#xD;&#xA;* `int64_t(z - p0.z)` is the distance from z and p0 for simplicity lets us call this `a` later.&#xD;&#xA;* `int64_t(p1.z - p0.z)` is the distance from p0 and p1 or vector length simplicity lets us call this `len` later.&#xD;&#xA;* lets look at `a/len` well that is simply the length of the ratio of the each point to 0. This equals to how much the vector p1-p0 must be scaled to reach the plane intersection. &#xD;&#xA;&#xD;&#xA;Finally the entire expression is can be read as follows:&#xD;&#xA;&#xD;&#xA;&gt; vector p0 + vector p0-1 * length to intersection&#xD;&#xA;&#xD;&#xA;And visually its as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The vectors in the calculation, (blue lines sow offsets and projections for feeling of 3D)&#xD;&#xA;&#xD;&#xA;And the entire function gives the same for the two edges of your triangle. Please note that it is perfectly possible that the result is degenerate as the choice of what edges to use is not checked for so one edge MIGHT be parallel to the plane. Also selection of points to send changes what is being projected.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: input blue triangle as 3 points (black), return value projected segment in orange on plane.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iYnJb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZqBRW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6062" PostHistoryTypeId="5" PostId="2501" RevisionGUID="abd84ba7-337d-461b-bedc-9282675ca093" CreationDate="2016-05-27T08:09:33.930" UserId="2214" Comment="changed a variable in the equation" Text="Let's assume I have the following cube.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zyfHW.png&#xD;&#xA;&#xD;&#xA;Let's assume the isovalue = 0. I would like to draw the resulting triangles of the isosurface.&#xD;&#xA;&#xD;&#xA;I know that first I define which values are inside or outside comparing them to the given isovalue and after that we correspond to a particular list of edges.&#xD;&#xA;&#xD;&#xA;After that, we have somehow to linearly interpolate the points.&#xD;&#xA;I have read on an article that using this formula $P = P_1 + \frac{(iso -V_1)(P_2-P_1)}{V_2-V_1}$ we can get the interpolated values. &#xD;&#xA;&#xD;&#xA;Can someone demonstrate to me how I can interpolate the points in this case ? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6063" PostHistoryTypeId="2" PostId="2512" RevisionGUID="c46e248f-bd7a-4870-9516-7447eb6cec8c" CreationDate="2016-05-27T08:35:44.453" UserId="1937" Text="P1 and P2 in this case represent the actual *coordinates* of the vertices of the cube in your output mesh. These might be the same as the input coordinates of the function you're using, or they might not be, it's entirely up to you how you output them. A simple way to map them would be to just use integer coords, biased by half the resolution of your sample volume - so a mesh spanning 100^3 cubes would have coordinates from -50 to 50 on each axis.&#xD;&#xA;&#xD;&#xA;So in the formula you describe, (iso - V1) / (V2 - V1) gives you the amount to interpolate by, and (P2 - P1) is a vector representing a single cube lattice edge along the axis you want.&#xD;&#xA;&#xD;&#xA;Let's assume we're using unit sized cubes, +Y is up, and +Z is 'into' the screen.&#xD;&#xA;&#xD;&#xA;In your cube above, you will have crossings on the three edges coming from the left-bottom-front corner. On the X and Z edges you will interpolate by 0.25 : (0 - (-1)) / (3 - (-1)) , and on the Y edge you will interpolate by 0.5.&#xD;&#xA;&#xD;&#xA;So if the left-bottom-front corner is at the origin, your three mesh vertices will be at &lt;0.25, 0, 0&gt; , &lt;0, 0.5, 0&gt; and &lt;0, 0, 0.25&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6064" PostHistoryTypeId="5" PostId="2512" RevisionGUID="015d5e63-feca-4007-a685-6dc255054773" CreationDate="2016-05-27T08:44:03.607" UserId="1937" Comment="added 387 characters in body" Text="P1 and P2 in this case represent the actual *coordinates* of the vertices of the cube in your output mesh. These might be the same as the input coordinates of the function you're using, or they might not be, it's entirely up to you how you output them. A simple way to map them would be to just use integer coords, biased by half the resolution of your sample volume - so a mesh spanning 100^3 cubes would have coordinates from -50 to 50 on each axis.&#xD;&#xA;&#xD;&#xA;So in the formula you describe, (iso - V1) / (V2 - V1) gives you the amount to interpolate by, and (P2 - P1) is a vector representing a single cube lattice edge along the axis you want.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Let's assume we're using unit sized cubes, +Y is up, and +Z is 'into' the screen.&#xD;&#xA;&#xD;&#xA;In your cube above, you will have crossings on the three edges coming from the left-bottom-front corner. On the X and Z edges you will interpolate by 0.25 : (0 - (-1)) / (3 - (-1)) , and on the Y edge you will interpolate by 0.5.&#xD;&#xA;&#xD;&#xA;So if the left-bottom-front corner is at the origin, your three mesh vertices will be at &#xD;&#xA;&lt;0.25, 0, 0&gt; , &#xD;&#xA;&lt;0, 0.5, 0&gt; and &#xD;&#xA;&lt;0, 0, 0.25&gt;.&#xD;&#xA;&#xD;&#xA;Apply the same formula to the right-top-back corner and you get &lt;0.5, 1, 1&gt;, &lt;1, 0.5, 1&gt; and &lt;1, 1, 0.5&gt;&#xD;&#xA;&#xD;&#xA;The only difference is the left-bottom-front corner values will be P1 and V1 in your formula as it is at the 'negative' end of the edges to be interpolated, and the right-top-back values will be P2 and V2 as it is at the 'positive' end.&#xD;&#xA;&#xD;&#xA;Hope that all makes sense.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6068" PostHistoryTypeId="2" PostId="2514" RevisionGUID="3883cd33-08cd-4e15-89dc-fe6b389003fa" CreationDate="2016-05-27T19:44:48.500" UserId="3386" Text="Assuming you have almost any lighting model at all:&#xD;&#xA;&#xD;&#xA;You cannot bound the view irradiance (light reflected from a surface location towards the eye/camera) by computing the irradiance at the vertices and bounding those, even if the surface is completely diffuse Lambertian and has no view-angle term.  &#xD;&#xA;&#xD;&#xA;Imagine a large floor triangle, and a point lighting near the center of the triangle, close to the surface.  The center of the triangle is very bright, while the vertices - which are far away from the light source - are dark.&#xD;&#xA;&#xD;&#xA;Alternatively, if you are just asking if a linearly interpolated quantity can exceed the value at any/all of the end points - then the answer is simply 'no' - your bounds are accurate. The key issue here is that irradiance is a non-linear function over the surface, but interpolation is linear" ContentLicense="CC BY-SA 3.0" />
  <row Id="6069" PostHistoryTypeId="2" PostId="2515" RevisionGUID="6f75f3ac-f75a-4205-b133-0ee2dd3c6972" CreationDate="2016-05-27T21:04:34.613" UserId="38" Text="I am supplementing the answer of others by adding a picture showing a Blinn and Lambert material applied to a triangle (the triangle has normal's in different directions at corners to sow difference in shading). There is one distant directional light in the scene.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]  &#xD;&#xA;&#xD;&#xA;**Image 1**: Image shows lightning on a triangle lit by directional light.  &#xD;&#xA;&#xD;&#xA;By comparing the samples in image 1 we can see that the highest color value can somewhere in the center of the triangle. Which shows that the question is generally invalid. &#xD;&#xA;&#xD;&#xA;So **no** you can not generally assume that the corners are the maximum of a triangle. A shader with this property can be constructed but quite a few shades have this property naturally.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Ly97.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6070" PostHistoryTypeId="5" PostId="2515" RevisionGUID="2456160e-6e41-4e5c-8378-f4354a2a0eb5" CreationDate="2016-05-27T21:09:34.797" UserId="38" Comment="added 3 characters in body" Text="I am supplementing the answer of others by adding a picture showing a Blinn and Lambert material applied to a triangle (the triangle has normal's in different directions at corners to sow difference in shading). There is one distant directional light in the scene.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]  &#xD;&#xA;&#xD;&#xA;**Image 1**: Image shows lightning on a triangle lit by directional light.  &#xD;&#xA;&#xD;&#xA;By comparing the samples in image 1 we can see that the highest color value can be somewhere in the center of the triangle. Which shows that the question is generally invalid. &#xD;&#xA;&#xD;&#xA;So **no** you can not generally assume that the corners are the maximum of a triangle. A shader with this property can be constructed but quite a few shades have this property naturally.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Ly97.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6071" PostHistoryTypeId="5" PostId="2515" RevisionGUID="203650e3-fdb3-46d9-8387-8c0d733fe414" CreationDate="2016-05-27T22:16:48.133" UserId="38" Comment="added 18 characters in body" Text="I am supplementing the answer of others by adding a picture showing a Blinn and Lambert material applied to a triangle (the triangle has normal's in different directions at corners to sow difference in shading). There is one distant directional light in the scene.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]  &#xD;&#xA;&#xD;&#xA;**Image 1**: Image shows lightning on a triangle lit by directional light.  &#xD;&#xA;&#xD;&#xA;By comparing the samples in image 1 we can see that the highest color value can be somewhere in the center of the triangle. Which shows that the assumption in yor question is generally invalid. &#xD;&#xA;&#xD;&#xA;So **no** you can not generally assume that the corners are the maximum of a triangle. A shader with this property can be constructed but quite a few shades have this property naturally.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Ly97.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6073" PostHistoryTypeId="2" PostId="2516" RevisionGUID="f326f863-b92a-4a0b-9277-7efb508ed0f8" CreationDate="2016-05-28T07:08:27.267" UserId="537" Text="I am writing a software and I need to represent a graph in a orthogonal manner from topological data (vector of edges,vertices and their connectivity data)&#xD;&#xA;&#xD;&#xA;**Graphs** consist of a set of **vertices** and a set of **edges**, each connecting two vertices.A vertex may have any number of connected edges so it makes the problem a lot more complicated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have read some articles and its looks like that the **Kandinsky model** is the post popular one. However I just don't know the algorithm, any other solution (algorithm) that solve the problem is also very welcome.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6074" PostHistoryTypeId="1" PostId="2516" RevisionGUID="f326f863-b92a-4a0b-9277-7efb508ed0f8" CreationDate="2016-05-28T07:08:27.267" UserId="537" Text="How to represent an orthogonal graph from its edges and vertices data?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6075" PostHistoryTypeId="3" PostId="2516" RevisionGUID="f326f863-b92a-4a0b-9277-7efb508ed0f8" CreationDate="2016-05-28T07:08:27.267" UserId="537" Text="|algorithm|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6077" PostHistoryTypeId="2" PostId="2518" RevisionGUID="91c41be9-697c-4654-b9ad-8e12aeef570b" CreationDate="2016-05-28T13:51:32.880" UserId="141" Text="I would like to rotate a raster image by an arbitrary angle. I don't really care for speed: the rotation should be of highest quality possible. Could someone please suggest a suitable algorithm?&#xD;&#xA;&#xD;&#xA;I'm familiar with the [rotation by three shears](http://www.leptonica.com/rotation.html#ROTATION-BY-SHEAR) but I'm not sure if the shears would not cause too much aliasing/blurring." ContentLicense="CC BY-SA 3.0" />
  <row Id="6078" PostHistoryTypeId="1" PostId="2518" RevisionGUID="91c41be9-697c-4654-b9ad-8e12aeef570b" CreationDate="2016-05-28T13:51:32.880" UserId="141" Text="Image rotation algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="6079" PostHistoryTypeId="3" PostId="2518" RevisionGUID="91c41be9-697c-4654-b9ad-8e12aeef570b" CreationDate="2016-05-28T13:51:32.880" UserId="141" Text="|algorithm|transformations|image-processing|2d|raster-image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6080" PostHistoryTypeId="2" PostId="2519" RevisionGUID="903d4251-dbab-427c-bfba-b565c72d44c9" CreationDate="2016-05-28T14:49:53.177" UserId="2479" Text="TL;DR: Your $G1$ formula is wrong. &#xD;&#xA;&#xD;&#xA;Just to avoid confusion, I am assuming the isotropic version of the BRDF, the Smith microfacet model (as opposed to the V-cavity model), and the GGX microfacet distribution.&#xD;&#xA;&#xD;&#xA;According to [Heitz 2014][1], the masking/shadowing term $G1$ is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\omega_{v}\cdot\omega_{g}\right)&#xD;&#xA;\frac{2}{1+\sqrt{1+\alpha_{o}^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and according [Walter 2007][2] the formula is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\frac{\omega_{v}\cdot\omega_{g}}{\omega_{v}\cdot\omega_{m}}\right)\frac{2}{1+\sqrt{1+\alpha^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $\omega_{m}$ is the microfacet normal direction (halfway vector), $\omega_{g}$ is the main (geometric) normal direction (normal), $\omega_{v}$ is the incoming or outgoing direction, $\alpha$ is the isotropic roughness parameter, and $\chi^{+}\left(a\right)$ is the positive characteristic function, or the Heaviside step function (equals one if a&gt;0 and zero otherwise).&#xD;&#xA;&#xD;&#xA;As you can notice, the half vector $\omega_{m}$ is either not used at all or is used only to make sure the $G1$ is zero if the geometrical configuration is forbidden. More precisely, it makes sure that the back surface of the microsurface is never visible from directions on the front side of the macrosurface and vice versa. If the calling code guarantees this, then you can obviously omit this parameter. That is probably the reason why they did so in Unity.&#xD;&#xA;&#xD;&#xA;You implementation, on the other hand, uses the half vector to compute the cosine of the direction in question with respect to the microfacet, which leads to computing of something else then the presented formulae.&#xD;&#xA;&#xD;&#xA;If I may suggest, then this is my implementation of the $G1$ factor:&#xD;&#xA;&#xD;&#xA;    float SmithMaskingFunctionGgx(&#xD;&#xA;        const Vec3f &amp;aDir,  // the direction to compute masking for (either incoming or outgoing)&#xD;&#xA;        const Vec3f &amp;aMicrofacetNormal,&#xD;&#xA;        const float  aRoughnessAlpha)&#xD;&#xA;    {&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aDir);&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);&#xD;&#xA;        PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);&#xD;&#xA;&#xD;&#xA;        if (aMicrofacetNormal.z &lt;= 0)&#xD;&#xA;            return 0.0f;&#xD;&#xA;&#xD;&#xA;        const float cosThetaVM = Dot(aDir, aMicrofacetNormal);&#xD;&#xA;        if ((aDir.z * cosThetaVM) &lt; 0.0f)&#xD;&#xA;            return 0.0f; // up direction is below microfacet or vice versa&#xD;&#xA;&#xD;&#xA;        const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;&#xD;&#xA;        const float tanThetaSqr = Geom::TanThetaSqr(aDir);&#xD;&#xA;        const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);&#xD;&#xA;&#xD;&#xA;        const float result = 2.0f / (1.0f + root);&#xD;&#xA;&#xD;&#xA;        PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/hal-00996995&#xD;&#xA;  [2]: http://dx.doi.org/10.2312/EGWR/EGSR07/195-206" ContentLicense="CC BY-SA 3.0" />
  <row Id="6081" PostHistoryTypeId="5" PostId="2515" RevisionGUID="5fab655e-dcef-49f1-b5f2-a76018925ff9" CreationDate="2016-05-28T14:58:48.403" UserId="231" Comment="Minor typos" Text="I am supplementing the answer of others by adding a picture showing a Blinn and Lambert material applied to a triangle (the triangle has normals in different directions at the corners to show the difference in shading). There is one distant directional light in the scene.&#xD;&#xA;&#xD;&#xA;[![Lighting on a triangle lit by directional light][1]][1]  &#xD;&#xA;&#xD;&#xA;**Image 1**: Image shows lighting on a triangle lit by directional light.  &#xD;&#xA;&#xD;&#xA;By comparing the samples in image 1 we can see that the highest color value can be somewhere in the center of the triangle. Which shows that the assumption in your question is generally invalid. &#xD;&#xA;&#xD;&#xA;So **no** you can not generally assume that the corners are the maximum of a triangle. A shader with this property can be constructed but quite a few shaders have this property naturally.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Ly97.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6082" PostHistoryTypeId="5" PostId="2519" RevisionGUID="920b162f-9bf1-4785-a7d4-da877121161a" CreationDate="2016-05-28T15:06:24.580" UserId="231" Comment="Minor typos" Text="TL;DR: Your $G1$ formula is wrong. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Just to avoid confusion, I am assuming the isotropic version of the BRDF, the Smith microfacet model (as opposed to the V-cavity model), and the GGX microfacet distribution.&#xD;&#xA;&#xD;&#xA;According to [Heitz 2014][1], the masking/shadowing term $G1$ is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\omega_{v}\cdot\omega_{g}\right)&#xD;&#xA;\frac{2}{1+\sqrt{1+\alpha_{o}^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and according [Walter 2007][2] the formula is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\frac{\omega_{v}\cdot\omega_{g}}{\omega_{v}\cdot\omega_{m}}\right)\frac{2}{1+\sqrt{1+\alpha^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $\omega_{m}$ is the microfacet normal direction (halfway vector), $\omega_{g}$ is the main (geometric) normal direction (normal), $\omega_{v}$ is the incoming or outgoing direction, $\alpha$ is the isotropic roughness parameter, and $\chi^{+}\left(a\right)$ is the positive characteristic function, or the Heaviside step function (equals one if a&gt;0 and zero otherwise).&#xD;&#xA;&#xD;&#xA;As you can notice, the half vector $\omega_{m}$ is either not used at all or is used only to make sure the $G1$ is zero if the geometrical configuration is forbidden. More precisely, it makes sure that the back surface of the microsurface is never visible from directions on the front side of the macrosurface and vice versa. If the calling code guarantees this, then you can obviously omit this parameter. That is probably the reason why they did so in Unity.&#xD;&#xA;&#xD;&#xA;Your implementation, on the other hand, uses the half vector to compute the cosine of the direction in question with respect to the microfacet, which leads to computing of something else than the presented formulae.&#xD;&#xA;&#xD;&#xA;If I may suggest, then this is my implementation of the $G1$ factor:&#xD;&#xA;&#xD;&#xA;    float SmithMaskingFunctionGgx(&#xD;&#xA;        const Vec3f &amp;aDir,  // the direction to compute masking for (either incoming or outgoing)&#xD;&#xA;        const Vec3f &amp;aMicrofacetNormal,&#xD;&#xA;        const float  aRoughnessAlpha)&#xD;&#xA;    {&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aDir);&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);&#xD;&#xA;        PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);&#xD;&#xA;&#xD;&#xA;        if (aMicrofacetNormal.z &lt;= 0)&#xD;&#xA;            return 0.0f;&#xD;&#xA;&#xD;&#xA;        const float cosThetaVM = Dot(aDir, aMicrofacetNormal);&#xD;&#xA;        if ((aDir.z * cosThetaVM) &lt; 0.0f)&#xD;&#xA;            return 0.0f; // up direction is below microfacet or vice versa&#xD;&#xA;&#xD;&#xA;        const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;&#xD;&#xA;        const float tanThetaSqr = Geom::TanThetaSqr(aDir);&#xD;&#xA;        const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);&#xD;&#xA;&#xD;&#xA;        const float result = 2.0f / (1.0f + root);&#xD;&#xA;&#xD;&#xA;        PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/hal-00996995&#xD;&#xA;  [2]: http://dx.doi.org/10.2312/EGWR/EGSR07/195-206" ContentLicense="CC BY-SA 3.0" />
  <row Id="6083" PostHistoryTypeId="5" PostId="2488" RevisionGUID="47d59039-6ce8-4a21-84e6-727c34099815" CreationDate="2016-05-28T15:11:04.637" UserId="231" Comment="Remove request for off site resources to prevent question being closed" Text="I am going through an undocumented function that takes in three points and a Z-value that projects three points on the plane defined by Z-value. I want to understand the mathematical theory behind it and I need your help to decode the function:&#xD;&#xA;&#xD;&#xA;    SlicerSegment project2D(Point3&amp; p0, Point3&amp; p1, Point3&amp; p2, int32_t z) const&#xD;&#xA;    {&#xD;&#xA;        SlicerSegment seg;&#xD;&#xA;        seg.start.X = p0.x + int64_t(p1.x - p0.x) * int64_t(z - p0.z) / int64_t(p1.z - p0.z);&#xD;&#xA;        seg.start.Y = p0.y + int64_t(p1.y - p0.y) * int64_t(z - p0.z) / int64_t(p1.z - p0.z);&#xD;&#xA;&#xD;&#xA;	seg.end.X = p0.x + int64_t(p2.x - p0.x) * int64_t(z - p0.z) / int64_t(p2.z - p0.z);&#xD;&#xA;        seg.end.Y = p0.y + int64_t(p2.y - p0.y) * int64_t(z - p0.z) / int64_t(p2.z - p0.z);&#xD;&#xA;        return seg;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6084" PostHistoryTypeId="5" PostId="32" RevisionGUID="8419c4dd-f28c-47ce-a7dd-a0e3b06337e7" CreationDate="2016-05-28T15:15:22.093" UserId="231" Comment="Minor typo and formatting" Text="From my basic understanding, a Vertex Buffer Object works something like this (pseudo code):&#xD;&#xA;&#xD;&#xA;Normally, if one wanted to say, draw a square, one could issue line drawing commands.&#xD;&#xA;&#xD;&#xA;    line (0, 0) -&gt; (1, 0)&#xD;&#xA;    line (1, 0) -&gt; (1, 1)&#xD;&#xA;    line (1, 1) -&gt; (0, 1)&#xD;&#xA;    line (0, 1) -&gt; (0, 0)&#xD;&#xA;&#xD;&#xA;Using a VBO, if I understand correctly, would load the vertices into a VBO.&#xD;&#xA;&#xD;&#xA;    define VBO&#xD;&#xA;    load (0,0) -&gt; VBO&#xD;&#xA;    load (1,0) -&gt; VBO&#xD;&#xA;    load (1,1) -&gt; VBO&#xD;&#xA;    load (0,1) -&gt; VBO&#xD;&#xA;    load (0,0) -&gt; VBO&#xD;&#xA;&#xD;&#xA;Then you can issue one drawing command.&#xD;&#xA;&#xD;&#xA;    draw VBO vertices&#xD;&#xA;    &#xD;&#xA;While I understand how VBOs work, I don't know why they improve performance. &#xD;&#xA;&#xD;&#xA;How do they improve performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6085" PostHistoryTypeId="5" PostId="2519" RevisionGUID="dcadd6d7-d1f3-4fa6-8678-79a0d3a44731" CreationDate="2016-05-28T17:35:52.113" UserId="2479" Comment="Clarified a few details" Text="TL;DR: Your $G1$ formula is wrong. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Just to avoid confusion, I am assuming the isotropic version of the BRDF, the Smith microfacet model (as opposed to the V-cavity model), and the GGX microfacet distribution.&#xD;&#xA;&#xD;&#xA;According to [Heitz 2014][1], the masking/shadowing term $G1$ is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\omega_{v}\cdot\omega_{g}\right)&#xD;&#xA;\frac{2}{1+\sqrt{1+\alpha_{o}^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and according [Walter 2007][2] the formula is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\frac{\omega_{v}\cdot\omega_{g}}{\omega_{v}\cdot\omega_{m}}\right)\frac{2}{1+\sqrt{1+\alpha^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $\omega_{m}$ is the microfacet normal direction (halfway vector), $\omega_{g}$ is the main (geometric) normal direction (normal), $\omega_{v}$ is the incoming or outgoing direction, $\alpha$ is the isotropic roughness parameter, and $\chi^{+}\left(a\right)$ is the positive characteristic function, or the Heaviside step function (equals one if $a&gt;0$ and zero otherwise).&#xD;&#xA;&#xD;&#xA;As you can notice, the half vector $\omega_{m}$ is either not used at all or is used only to make sure the $G1$ is zero if the geometrical configuration is forbidden. More precisely, it makes sure that the back surface of the microsurface is never visible from the $\omega_{v}$ direction on the front side of the macrosurface and vice versa (the latter case is meaningful only when also refractions are supported). If the calling code guarantees this, then you can obviously omit this parameter. That is probably the reason why they did so in Unity.&#xD;&#xA;&#xD;&#xA;Your implementation, on the other hand, uses the half vector to compute the cosine of the $\omega_{v}$ direction with respect to the microfacet, which leads to computation of something else than the presented formulae.&#xD;&#xA;&#xD;&#xA;If it is of any help, then this is my implementation of the $G1$ factor:&#xD;&#xA;&#xD;&#xA;    float SmithMaskingFunctionGgx(&#xD;&#xA;        const Vec3f &amp;aDir,  // the direction to compute masking for (either incoming or outgoing)&#xD;&#xA;        const Vec3f &amp;aMicrofacetNormal,&#xD;&#xA;        const float  aRoughnessAlpha)&#xD;&#xA;    {&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aDir);&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);&#xD;&#xA;        PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);&#xD;&#xA;&#xD;&#xA;        if (aMicrofacetNormal.z &lt;= 0)&#xD;&#xA;            return 0.0f;&#xD;&#xA;&#xD;&#xA;        const float cosThetaVM = Dot(aDir, aMicrofacetNormal);&#xD;&#xA;        if ((aDir.z * cosThetaVM) &lt; 0.0f)&#xD;&#xA;            return 0.0f; // up direction is below microfacet or vice versa&#xD;&#xA;&#xD;&#xA;        const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;&#xD;&#xA;        const float tanThetaSqr = Geom::TanThetaSqr(aDir);&#xD;&#xA;        const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);&#xD;&#xA;&#xD;&#xA;        const float result = 2.0f / (1.0f + root);&#xD;&#xA;&#xD;&#xA;        PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/hal-00996995&#xD;&#xA;  [2]: http://dx.doi.org/10.2312/EGWR/EGSR07/195-206" ContentLicense="CC BY-SA 3.0" />
  <row Id="6089" PostHistoryTypeId="2" PostId="2521" RevisionGUID="b46fef12-978d-46dd-ac8c-d058e9ac3511" CreationDate="2016-05-28T22:01:49.243" UserDisplayName="user3437" Text="I know how to draw lines with DDA but i want to learn more efficient way and google suggest Bresenham's line drawing algorithm is better than DDA&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is my implementation :- &#xD;&#xA;&#xD;&#xA;        int x0 = Math.round(m_start.getPosition().getX());&#xD;&#xA;		int y0 = Math.round(m_start.getPosition().getY());&#xD;&#xA;		int x1 = Math.round(m_end.getPosition().getX()); &#xD;&#xA;		int y1 = Math.round(m_end.getPosition().getY()); &#xD;&#xA;&#xD;&#xA;		int dx = x1 - x0;&#xD;&#xA;		int dy = y1 - y0;&#xD;&#xA;			&#xD;&#xA;		int parameter = 2 * dy -  dx;&#xD;&#xA;		&#xD;&#xA;		 Point k = new Point(new Vector2D(x0, y0), m_display, PixelData.white());&#xD;&#xA;		 k.DrawPoint();&#xD;&#xA;		&#xD;&#xA;		for(int i = x0 + 1; i &lt; x1; i++){	&#xD;&#xA;		   if(parameter &lt; 0){&#xD;&#xA;			   y0 += 1;&#xD;&#xA;			   Point p = new Point(new Vector2D(i, y0), m_display, PixelData.white());&#xD;&#xA;			   p.DrawPoint();&#xD;&#xA;			   &#xD;&#xA;			   parameter += 2 * dy;&#xD;&#xA;		   }else{&#xD;&#xA;			   y0 += 1;&#xD;&#xA;			   Point p = new Point(new Vector2D(i, y0 + 1), m_display, PixelData.white());&#xD;&#xA;			   p.DrawPoint();&#xD;&#xA;			   &#xD;&#xA;			   parameter += 2 * dy - 2 * dx;&#xD;&#xA;		   }&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;and here is the output : -&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;as you can see the line is not ending at the desired coordinate, that small dot is where it should end. &#xD;&#xA;&#xD;&#xA;I checked the slope, dx and dy.&#xD;&#xA;&#xD;&#xA;		System.out.println(dx + &quot; &quot; + dy + &quot; &quot; + (dy/(float)dx));&#xD;&#xA;&#xD;&#xA;Output : -&#xD;&#xA;&#xD;&#xA;        100 50 0.5&#xD;&#xA;&#xD;&#xA;the slope is below tan (pi/4).&#xD;&#xA;&#xD;&#xA;Please help me find the bug. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BT5tA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6090" PostHistoryTypeId="1" PostId="2521" RevisionGUID="b46fef12-978d-46dd-ac8c-d058e9ac3511" CreationDate="2016-05-28T22:01:49.243" UserDisplayName="user3437" Text="Bug with the Bresenham's line drawing algorithm?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6091" PostHistoryTypeId="3" PostId="2521" RevisionGUID="b46fef12-978d-46dd-ac8c-d058e9ac3511" CreationDate="2016-05-28T22:01:49.243" UserDisplayName="user3437" Text="|algorithm|computational-geometry|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6092" PostHistoryTypeId="2" PostId="2522" RevisionGUID="f4e332b7-6450-4fd1-abce-a1d24531505d" CreationDate="2016-05-28T22:31:51.283" UserId="2479" Text="Frankly, your implementation doesn't make much sense. It basically iterates x coordinate through `i` variable and increments `y` variable at each step. Since the `parameter` doesn't cross the 0 boundary, it generates the diagonal points you can see on your picture.&#xD;&#xA;&#xD;&#xA;You also compute and update the `parameter` variable somehow, but don't use it anywhere.&#xD;&#xA;&#xD;&#xA;Last, but not least, you use integer arithmetic for the variable which (I guess) should probably accumulate the slower coordinate error or the whole slower coordinate, which will not work properly if I am not mistaken" ContentLicense="CC BY-SA 3.0" />
  <row Id="6093" PostHistoryTypeId="5" PostId="2519" RevisionGUID="e861f275-0fa8-4c5b-8fc0-eb4272914a2e" CreationDate="2016-05-28T22:53:31.367" UserId="2479" Comment="added 4 characters in body" Text="TL;DR: Your $G1$ formula is wrong. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Just to avoid confusion, I am assuming the isotropic version of the BRDF, the Smith microfacet model (as opposed to the V-cavity model), and the GGX microfacet distribution.&#xD;&#xA;&#xD;&#xA;According to [Heitz 2014][1], the masking/shadowing term $G1$ is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\omega_{v}\cdot\omega_{g}\right)&#xD;&#xA;\frac{2}{1+\sqrt{1+\alpha_{o}^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and according to [Walter 2007][2], the formula is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\frac{\omega_{v}\cdot\omega_{g}}{\omega_{v}\cdot\omega_{m}}\right)\frac{2}{1+\sqrt{1+\alpha^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $\omega_{m}$ is the microfacet normal direction (halfway vector), $\omega_{g}$ is the main (geometric) normal direction (normal), $\omega_{v}$ is the incoming or outgoing direction, $\alpha$ is the isotropic roughness parameter, and $\chi^{+}\left(a\right)$ is the positive characteristic function, or the Heaviside step function (equals one if $a&gt;0$ and zero otherwise).&#xD;&#xA;&#xD;&#xA;As you can notice, the half vector $\omega_{m}$ is either not used at all or is used only to make sure the $G1$ is zero if the geometrical configuration is forbidden. More precisely, it makes sure that the back surface of the microsurface is never visible from the $\omega_{v}$ direction on the front side of the macrosurface and vice versa (the latter case is meaningful only when also refractions are supported). If the calling code guarantees this, then you can obviously omit this parameter. That is probably the reason why they did so in Unity.&#xD;&#xA;&#xD;&#xA;Your implementation, on the other hand, uses the half vector to compute the cosine of the $\omega_{v}$ direction with respect to the microfacet, which leads to computation of something else than the presented formulae.&#xD;&#xA;&#xD;&#xA;If it is of any help, then this is my implementation of the $G1$ factor:&#xD;&#xA;&#xD;&#xA;    float SmithMaskingFunctionGgx(&#xD;&#xA;        const Vec3f &amp;aDir,  // the direction to compute masking for (either incoming or outgoing)&#xD;&#xA;        const Vec3f &amp;aMicrofacetNormal,&#xD;&#xA;        const float  aRoughnessAlpha)&#xD;&#xA;    {&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aDir);&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);&#xD;&#xA;        PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);&#xD;&#xA;&#xD;&#xA;        if (aMicrofacetNormal.z &lt;= 0)&#xD;&#xA;            return 0.0f;&#xD;&#xA;&#xD;&#xA;        const float cosThetaVM = Dot(aDir, aMicrofacetNormal);&#xD;&#xA;        if ((aDir.z * cosThetaVM) &lt; 0.0f)&#xD;&#xA;            return 0.0f; // up direction is below microfacet or vice versa&#xD;&#xA;&#xD;&#xA;        const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;&#xD;&#xA;        const float tanThetaSqr = Geom::TanThetaSqr(aDir);&#xD;&#xA;        const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);&#xD;&#xA;&#xD;&#xA;        const float result = 2.0f / (1.0f + root);&#xD;&#xA;&#xD;&#xA;        PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/hal-00996995&#xD;&#xA;  [2]: http://dx.doi.org/10.2312/EGWR/EGSR07/195-206" ContentLicense="CC BY-SA 3.0" />
  <row Id="6094" PostHistoryTypeId="2" PostId="2523" RevisionGUID="ebbfbb74-ffb0-40df-93f7-e10ee3a9fc8b" CreationDate="2016-05-28T23:39:03.033" UserId="231" Text="I don't have any experience with Gradient Domain Path Tracing, but here are my thoughts:&#xD;&#xA;&#xD;&#xA;# There seems to be a different problem&#xD;&#xA;&#xD;&#xA;If you look carefully at the little spikes of distortion in the final image, you will see that they are all lit from the same direction - on their top left side at a consistent 45 degrees. The sphere also appears to be lit from this angle, rather than from above by the light source.&#xD;&#xA;&#xD;&#xA;This is unlikely to be explained by an incorrect probability estimation for a path. I would expect there to be a different problem with the code, that these distortions are hinting at.&#xD;&#xA;&#xD;&#xA;I will therefore address these two separate points:&#xD;&#xA;&#xD;&#xA;1. You want to know how to calculate the Probability Density of a path when using Next Event Estimation.&#xD;&#xA;1. There is evidence of some problem unrelated to this.&#xD;&#xA;&#xD;&#xA;I'll also review the code for non-essential points - but I'll leave this until after the essentials.&#xD;&#xA;&#xD;&#xA;# Probability Density of a path when using Next Event Estimation&#xD;&#xA;&#xD;&#xA;Looking at the [paper on which the code you are following was based] it seems that the novel shift mapping described in section 5.2 is defined in terms of the reflective properties of the surfaces found at the vertices of the path. I must emphasise that I don't have a full understanding of this, but it suggests that Next Event Estimation may not require a change in this approach, as the surfaces encountered will be the same. Hopefully once the other problems are cleared up it will be easier to judge whether the image looks correct.&#xD;&#xA;&#xD;&#xA;# The cause of the incorrect lighting direction&#xD;&#xA;&#xD;&#xA;In reading through the code to familiarise myself with how it works, I noticed that `NLdotL` is calculated, but then not used. A text search revealed that the only other occurrence has a different case: `nldotl`. Here are the two variables in context (first and ninth lines of this excerpt):&#xD;&#xA;&#xD;&#xA;    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;    float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;    if (NdotL &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;        Scene.Intersect( r );&#xD;&#xA;        if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;        {&#xD;&#xA;            float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;            E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since `nldotl` is not defined, the result of the code is undefined behaviour. In practice, the code is likely to act as if `nldotl` is zero, or for some compilers perhaps a constant arbitrary value. I strongly suspect this is the cause of the distinctive alignment of lighting angle on all the speckles and the sphere. If there is also another contributing problem it will be easier to analyse it in a separate question once this initial problem has been fixed.&#xD;&#xA;&#xD;&#xA;It may be worth considering using a compiler and/or flag setting that gives an error or at the very least a warning for undefined variables, as this type of mistake is both very easy to make, and very easy to overlook later.&#xD;&#xA;&#xD;&#xA;# Additional contribution of light source&#xD;&#xA;&#xD;&#xA;There appears to be another problem that will cause results to be incorrect in a more subtle way, with no obvious distortion. Due to Next Event Estimation, the light source is contributing to each step along the path. This means it should not make a contribution if the path itself hits the light source directly. Otherwise, for that path the light source will be contributing twice. You can correct this by changing:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        E += material.diffuse;&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will give a zero contribution from the intersection with the light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Doubly finite rays&#xD;&#xA;&#xD;&#xA;I'm used to defining a ray as a half infinite line segment - having a starting point but no ending point. I notice that this code gives a ray both a starting point and a length. The only place I can see a need for this is when testing a shadow ray against the light source: it checks that there are no intersections on the way to the light, and you don't want to include intersections behind the light (or the light itself). In all other places, the ray is defined with a pseudo-infinite length (`1e34f`).&#xD;&#xA;&#xD;&#xA;The following suggestion won't affect the *correctness* of your code, but it may be more readable and avoid you having to work around the need for infinity and having to account for epsilon twice.&#xD;&#xA;&#xD;&#xA;If the ray is simply a starting point and a direction, then shadow rays can simply check that the first intersection is the light, rather than checking that there is no intersection. For example, by replacing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == LIGHT) // There is no object intersected before the light&#xD;&#xA;&#xD;&#xA;Here I use `LIGHT` as a placeholder for the id of the light source, since that part of the code is not included in the question.&#xD;&#xA;&#xD;&#xA;### Lights that don't reflect&#xD;&#xA;&#xD;&#xA;Your code currently models lights and surfaces separately. This means that if an object is a light then it is only emissive, and reflects no light from other objects.&#xD;&#xA;&#xD;&#xA;This causes a negligible difference in the example scene in the question, which has a single bright light. However, if used with a number of dimmer lights, it would be more noticeable that they do not light each other. In many cases the difference will not be noticeable, so this is not a problem if it works for the scenes you wish to render.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [paper on which the code you are following was based]: https://mediatech.aalto.fi/publications/graphics/GPT/kettunen2015siggraph_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6095" PostHistoryTypeId="5" PostId="2523" RevisionGUID="01a32d7f-3974-46d7-b002-3b7775352f54" CreationDate="2016-05-28T23:44:42.593" UserId="231" Comment="Tidying" Text="I don't have any experience with Gradient Domain Path Tracing, but here are my thoughts:&#xD;&#xA;&#xD;&#xA;# There seems to be a different problem&#xD;&#xA;&#xD;&#xA;If you look carefully at the little spikes of distortion in the final image, you will see that they are all lit from the same direction - on their top left side at a consistent 45 degrees. The sphere also appears to be lit from this angle, rather than from above by the light source.&#xD;&#xA;&#xD;&#xA;This is unlikely to be explained by an incorrect probability estimation for a path. I would expect there to be a different problem with the code, that these distortions are hinting at.&#xD;&#xA;&#xD;&#xA;I will therefore address these two separate points:&#xD;&#xA;&#xD;&#xA;1. You want to know how to calculate the Probability Density of a path when using Next Event Estimation.&#xD;&#xA;1. There is evidence of some problem unrelated to this.&#xD;&#xA;&#xD;&#xA;I'll also review the code for non-essential points - but I'll leave this until after the essentials.&#xD;&#xA;&#xD;&#xA;# Probability Density of a path when using Next Event Estimation&#xD;&#xA;&#xD;&#xA;Looking at the [paper on which the code you are following was based] it seems that the novel shift mapping described in section 5.2 is defined in terms of the reflective properties of the surfaces found at the vertices of the path. I must emphasise that I don't have a full understanding of this, but it suggests that Next Event Estimation may not require a change in this approach, as the surfaces encountered will be the same. Hopefully once the other problems are cleared up it will be easier to judge whether the image looks correct.&#xD;&#xA;&#xD;&#xA;# The cause of the incorrect lighting direction&#xD;&#xA;&#xD;&#xA;In reading through the code to familiarise myself with how it works, I noticed that `NLdotL` is calculated, but then not used. A text search revealed that the only other occurrence has a different case: `nldotl`. Here are the two variables in context (first and ninth lines of this excerpt):&#xD;&#xA;&#xD;&#xA;    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;    float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;    if (NdotL &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;        Scene.Intersect( r );&#xD;&#xA;        if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;        {&#xD;&#xA;            float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;            E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since `nldotl` is not defined, the result of the code is undefined behaviour. In practice, the program is likely to act as if `nldotl` is zero, or for some compilers perhaps a constant arbitrary value, or even a different arbitrary value at each iteration. I strongly suspect this is the cause of the distinctive alignment of lighting angle on all the speckles and the sphere. If there is also another contributing problem it will be easier to analyse it in a separate question once this initial problem has been fixed.&#xD;&#xA;&#xD;&#xA;It may be worth considering using a compiler and/or flag setting that gives an error or at the very least a warning for undefined variables, as this type of mistake is both very easy to make, and very easy to overlook later.&#xD;&#xA;&#xD;&#xA;# Additional contribution of light source&#xD;&#xA;&#xD;&#xA;There appears to be another problem that will cause results to be incorrect in a more subtle way, with no obvious distortion. Due to Next Event Estimation, the light source is contributing to each step along the path. This means it should not make a contribution if the path itself hits the light source directly. Otherwise, for that path the light source will be contributing twice. You can correct this by changing:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        E += material.diffuse;&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will give a zero contribution from the intersection with the light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;### Doubly finite rays&#xD;&#xA;&#xD;&#xA;I'm used to defining a ray as a half infinite line segment - having a starting point but no ending point. I notice that this code gives a ray both a starting point and a length. The only place I can see a reason for this is when testing a shadow ray against the light source: the code checks that there are no intersections on the way to the light, so intersections behind the light (or on the light itself) must be excluded. In all other places, the ray is defined with a pseudo-infinite length (`1e34f`).&#xD;&#xA;&#xD;&#xA;The following suggestion won't affect the *correctness* of your code, but it may be more readable and avoid you having to work around the need for infinity and having to account for epsilon twice.&#xD;&#xA;&#xD;&#xA;If the ray is simply a starting point and a direction, then shadow rays can simply check that the first intersection is the light, rather than checking that there is no intersection. For example, by replacing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == LIGHT) // There is no object intersected before the light&#xD;&#xA;&#xD;&#xA;Here I use `LIGHT` as a placeholder for the id of the light source, since that part of the code is not included in the question.&#xD;&#xA;&#xD;&#xA;### Lights that don't reflect&#xD;&#xA;&#xD;&#xA;Your code currently models lights and surfaces separately. This means that if an object is a light then it is only emissive, and reflects no light from other objects.&#xD;&#xA;&#xD;&#xA;This causes a negligible difference in the example scene in the question, which has a single bright light. However, if used with a number of dimmer lights, it would be more noticeable that they do not light each other. In many cases the difference will not be noticeable, so this is not a problem if it works for the scenes you wish to render.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [paper on which the code you are following was based]: https://mediatech.aalto.fi/publications/graphics/GPT/kettunen2015siggraph_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6096" PostHistoryTypeId="5" PostId="2523" RevisionGUID="4570e789-7ae3-4cac-b72c-3d27e0a334f3" CreationDate="2016-05-28T23:55:21.757" UserId="231" Comment="added 267 characters in body" Text="I don't have any experience with Gradient Domain Path Tracing, but here are my thoughts:&#xD;&#xA;&#xD;&#xA;# There seems to be a different problem&#xD;&#xA;&#xD;&#xA;If you look carefully at the little spikes of distortion in the final image, you will see that they are all lit from the same direction - on their top left side at a consistent 45 degrees. The sphere also appears to be lit from this angle, rather than from above by the light source.&#xD;&#xA;&#xD;&#xA;This is unlikely to be explained by an incorrect probability estimation for a path. I would expect there to be a different problem with the code, that these distortions are hinting at.&#xD;&#xA;&#xD;&#xA;I will therefore address these two separate points:&#xD;&#xA;&#xD;&#xA;1. You want to know how to calculate the Probability Density of a path when using Next Event Estimation.&#xD;&#xA;1. There is evidence of some problem unrelated to this.&#xD;&#xA;&#xD;&#xA;I'll also review the code for non-essential points - but I'll leave this until after the essentials.&#xD;&#xA;&#xD;&#xA;# Probability Density of a path when using Next Event Estimation&#xD;&#xA;&#xD;&#xA;Looking at the [paper on which the code you are following was based] it seems that the novel shift mapping described in section 5.2 is defined in terms of the reflective properties of the surfaces found at the vertices of the path. I must emphasise that I don't have a full understanding of this, but it suggests that Next Event Estimation may not require a change in this approach, as the surfaces encountered will be the same. Hopefully once the other problems are cleared up it will be easier to judge whether the image looks correct.&#xD;&#xA;&#xD;&#xA;# The cause of the incorrect lighting direction&#xD;&#xA;&#xD;&#xA;In reading through the code to familiarise myself with how it works, I noticed that `NLdotL` is calculated, but then not used. A text search revealed that the only other occurrence has a different case: `nldotl`. Here are the two variables in context (first and ninth lines of this excerpt):&#xD;&#xA;&#xD;&#xA;    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;    float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;    if (NdotL &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;        Scene.Intersect( r );&#xD;&#xA;        if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;        {&#xD;&#xA;            float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;            E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since `nldotl` is not defined, the result of the code is undefined behaviour. In practice, the program is likely to act as if `nldotl` is zero, or for some compilers perhaps a constant arbitrary value, or even a different arbitrary value at each iteration. I strongly suspect this is the cause of the distinctive alignment of lighting angle on all the speckles and the sphere. If there is also another contributing problem it will be easier to analyse it in a separate question once this initial problem has been fixed.&#xD;&#xA;&#xD;&#xA;It may be worth considering using a compiler and/or flag setting that gives an error or at the very least a warning for undefined variables, as this type of mistake is both very easy to make, and very easy to overlook later.&#xD;&#xA;&#xD;&#xA;# Additional contribution of light source&#xD;&#xA;&#xD;&#xA;There appears to be another problem that will cause results to be incorrect in a more subtle way, with no obvious distortion. Due to Next Event Estimation, the light source is contributing to each step along the path. This means it should not make a contribution if the path itself hits the light source directly. Otherwise, for that path the light source will be contributing twice. You can correct this by changing:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        E += material.diffuse;&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will give a zero contribution from the intersection with the light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;### Doubly finite rays&#xD;&#xA;&#xD;&#xA;I'm used to defining a ray as a half infinite line segment - having a starting point but no ending point. I notice that this code gives a ray both a starting point and a length. The only place I can see a reason for this is when testing a shadow ray against the light source: the code checks that there are no intersections on the way to the light, so intersections behind the light (or on the light itself) must be excluded. In all other places, the ray is defined with a pseudo-infinite length (`1e34f`).&#xD;&#xA;&#xD;&#xA;The following suggestion won't affect the *correctness* of your code, but it may be more readable and avoid you having to work around the need for infinity and having to account for epsilon twice.&#xD;&#xA;&#xD;&#xA;If the ray is simply a starting point and a direction, then shadow rays can simply check that the first intersection is the light, rather than checking that there is no intersection. For example, by replacing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == LIGHT) // There is no object intersected before the light&#xD;&#xA;&#xD;&#xA;Here I use `LIGHT` as a placeholder for the id of the light source, since that part of the code is not included in the question.&#xD;&#xA;&#xD;&#xA;- This will always give false if the light is occluded by a nearer object.&#xD;&#xA;- This will always give true if the ray hits the light before any more distant objects.&#xD;&#xA;&#xD;&#xA;This is therefore equivalent to the current code, but does not require the ray to store a length.&#xD;&#xA;&#xD;&#xA;### Lights that don't reflect&#xD;&#xA;&#xD;&#xA;The code currently models lights and surfaces separately. This means that if an object is a light then it is only emissive, and reflects no light from other objects.&#xD;&#xA;&#xD;&#xA;This causes a negligible difference in the example scene in the question, which has a single bright light. However, if used with a number of dimmer lights, it would be more noticeable that they do not light each other. In many cases the difference will not be noticeable, so this is not a problem if it works for the scenes you wish to render.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [paper on which the code you are following was based]: https://mediatech.aalto.fi/publications/graphics/GPT/kettunen2015siggraph_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6097" PostHistoryTypeId="5" PostId="2523" RevisionGUID="03152598-db29-425a-9511-4479bc300cbb" CreationDate="2016-05-29T00:00:41.910" UserId="231" Comment="Clarification" Text="I don't have any experience with Gradient Domain Path Tracing, but here are my thoughts:&#xD;&#xA;&#xD;&#xA;# There seems to be a different problem&#xD;&#xA;&#xD;&#xA;If you look carefully at the little spikes of distortion in the final image, you will see that they are all lit from the same direction - on their top left side at a consistent 45 degrees. The sphere also appears to be lit from this angle, rather than from above by the light source.&#xD;&#xA;&#xD;&#xA;This is unlikely to be explained by an incorrect probability estimation for a path. I would expect there to be a different problem with the code, that these distortions are hinting at.&#xD;&#xA;&#xD;&#xA;I will therefore address these two separate points:&#xD;&#xA;&#xD;&#xA;1. You want to know how to calculate the Probability Density of a path when using Next Event Estimation.&#xD;&#xA;1. There is evidence of some problem unrelated to this.&#xD;&#xA;&#xD;&#xA;I'll also review the code for non-essential points - but I'll leave this until after the essentials.&#xD;&#xA;&#xD;&#xA;# Probability Density of a path when using Next Event Estimation&#xD;&#xA;&#xD;&#xA;Looking at the [paper on which the code you are following was based] it seems that the novel shift mapping described in section 5.2 is defined in terms of the reflective properties of the surfaces found at the vertices of the path. I must emphasise that I don't have a full understanding of this, but it suggests that Next Event Estimation may not require a change in this approach, as the surfaces encountered will be the same. Hopefully once the other problems are cleared up it will be easier to judge whether the image looks correct.&#xD;&#xA;&#xD;&#xA;# The cause of the incorrect lighting direction&#xD;&#xA;&#xD;&#xA;In reading through the code to familiarise myself with how it works, I noticed that `NLdotL` is calculated, but then not used. A text search revealed that the only other occurrence has a different case: `nldotl`. Here are the two variables in context (first and ninth lines of this excerpt):&#xD;&#xA;&#xD;&#xA;    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;    float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;    if (NdotL &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;        Scene.Intersect( r );&#xD;&#xA;        if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;        {&#xD;&#xA;            float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;            E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since `nldotl` is not defined, the result of the code is undefined behaviour. In practice, the program is likely to act as if `nldotl` is zero, or for some compilers perhaps a constant arbitrary value, or even a different arbitrary value at each iteration. For your particular compiler it appears to be a constant value, and I strongly suspect this is the cause of the distinctive alignment of lighting angle on all the speckles and the sphere. If there is also another contributing problem it will be easier to analyse it in a separate question once this initial problem has been fixed.&#xD;&#xA;&#xD;&#xA;It may be worth considering using a compiler and/or flag setting that gives an error or at the very least a warning for undefined variables, as this type of mistake is both very easy to make, and very easy to overlook later.&#xD;&#xA;&#xD;&#xA;# Additional contribution of light source&#xD;&#xA;&#xD;&#xA;There appears to be another problem that will cause results to be incorrect in a more subtle way, with no obvious distortion. Due to Next Event Estimation, the light source is contributing to each step along the path. This means it should not make a contribution if the path itself hits the light source directly. Otherwise, for that path the light source will be contributing twice. You can correct this by changing:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        E += material.diffuse;&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will give a zero contribution from the intersection with the light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;### Doubly finite rays&#xD;&#xA;&#xD;&#xA;I'm used to defining a ray as a half infinite line segment - having a starting point but no ending point. I notice that this code gives a ray both a starting point and a length. The only place I can see a reason for this is when testing a shadow ray against the light source: the code checks that there are no intersections on the way to the light, so intersections behind the light (or on the light itself) must be excluded. In all other places, the ray is defined with a pseudo-infinite length (`1e34f`).&#xD;&#xA;&#xD;&#xA;The following suggestion won't affect the *correctness* of your code, but it may be more readable and avoid you having to work around the need for infinity and having to account for epsilon twice.&#xD;&#xA;&#xD;&#xA;If the ray is simply a starting point and a direction, then shadow rays can simply check that the first intersection is the light, rather than checking that there is no intersection. For example, by replacing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == LIGHT) // There is no object intersected before the light&#xD;&#xA;&#xD;&#xA;Here I use `LIGHT` as a placeholder for the id of the light source, since that part of the code is not included in the question.&#xD;&#xA;&#xD;&#xA;- This will always give false if the light is occluded by a nearer object.&#xD;&#xA;- This will always give true if the ray hits the light before any more distant objects.&#xD;&#xA;&#xD;&#xA;This is therefore equivalent to the current code, but does not require the ray to store a length.&#xD;&#xA;&#xD;&#xA;### Lights that don't reflect&#xD;&#xA;&#xD;&#xA;The code currently models lights and surfaces separately. This means that if an object is a light then it is only emissive, and reflects no light from other objects.&#xD;&#xA;&#xD;&#xA;This causes a negligible difference in the example scene in the question, which has a single bright light. However, if used with a number of dimmer lights, it would be more noticeable that they do not light each other. In many cases the difference will not be noticeable, so this is not a problem if it works for the scenes you wish to render.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [paper on which the code you are following was based]: https://mediatech.aalto.fi/publications/graphics/GPT/kettunen2015siggraph_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6098" PostHistoryTypeId="5" PostId="2523" RevisionGUID="eb59ff06-fda9-4760-92ee-f1287b22fd65" CreationDate="2016-05-29T00:26:30.723" UserId="231" Comment="Extra thought" Text="I don't have any experience with Gradient Domain Path Tracing, but here are my thoughts:&#xD;&#xA;&#xD;&#xA;# There seems to be a different problem&#xD;&#xA;&#xD;&#xA;If you look carefully at the little spikes of distortion in the final image, you will see that they are all lit from the same direction - on their top left side at a consistent 45 degrees. The sphere also appears to be lit from this angle, rather than from above by the light source.&#xD;&#xA;&#xD;&#xA;This is unlikely to be explained by an incorrect probability estimation for a path. I would expect there to be a different problem with the code, that these distortions are hinting at.&#xD;&#xA;&#xD;&#xA;I will therefore address these two separate points:&#xD;&#xA;&#xD;&#xA;1. You want to know how to calculate the Probability Density of a path when using Next Event Estimation.&#xD;&#xA;1. There is evidence of some problem unrelated to this.&#xD;&#xA;&#xD;&#xA;I'll also review the code for non-essential points - but I'll leave this until after the essentials.&#xD;&#xA;&#xD;&#xA;# Probability Density of a path when using Next Event Estimation&#xD;&#xA;&#xD;&#xA;Looking at the [paper on which the code you are following was based] it seems that the novel shift mapping described in section 5.2 is defined in terms of the reflective properties of the surfaces found at the vertices of the path. I must emphasise that I don't have a full understanding of this, but it suggests that Next Event Estimation may not require a change in this approach, as the surfaces encountered will be the same. Hopefully once the other problems are cleared up it will be easier to judge whether the image looks correct.&#xD;&#xA;&#xD;&#xA;# The cause of the incorrect lighting direction&#xD;&#xA;&#xD;&#xA;In reading through the code to familiarise myself with how it works, I noticed that `NLdotL` is calculated, but then not used. A text search revealed that the only other occurrence has a different case: `nldotl`. Here are the two variables in context (first and ninth lines of this excerpt):&#xD;&#xA;&#xD;&#xA;    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;    float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;    if (NdotL &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;        Scene.Intersect( r );&#xD;&#xA;        if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;        {&#xD;&#xA;            float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;            E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since `nldotl` is not defined, the result of the code is undefined behaviour. In practice, the program is likely to act as if `nldotl` is zero, or for some compilers perhaps a constant arbitrary value, or even a different arbitrary value at each iteration. For your particular compiler it appears to be a constant value, and I strongly suspect this is the cause of the distinctive alignment of lighting angle on all the speckles and the sphere. If there is also another contributing problem it will be easier to analyse it in a separate question once this initial problem has been fixed.&#xD;&#xA;&#xD;&#xA;It may be worth considering using a compiler and/or flag setting that gives an error or at the very least a warning for undefined variables, as this type of mistake is both very easy to make, and very easy to overlook later.&#xD;&#xA;&#xD;&#xA;# Additional contribution of light source&#xD;&#xA;&#xD;&#xA;There appears to be another problem that will cause results to be incorrect in a more subtle way, with no obvious distortion. Due to Next Event Estimation, the light source is contributing to each step along the path. This means it should not make a contribution if the path itself hits the light source directly. Otherwise, for that path the light source will be contributing twice. You can correct this by changing:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        E += material.diffuse;&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will give a zero contribution from the intersection with the light.&#xD;&#xA;&#xD;&#xA;Note that since I can only see this one function, I can't guess whether this will also make the light appear black in the image. You may or may not need to adjust for rays that start at the camera and hit the light directly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;### Doubly finite rays&#xD;&#xA;&#xD;&#xA;I'm used to defining a ray as a half infinite line segment - having a starting point but no ending point. I notice that this code gives a ray both a starting point and a length. The only place I can see a reason for this is when testing a shadow ray against the light source: the code checks that there are no intersections on the way to the light, so intersections behind the light (or on the light itself) must be excluded. In all other places, the ray is defined with a pseudo-infinite length (`1e34f`).&#xD;&#xA;&#xD;&#xA;The following suggestion won't affect the *correctness* of your code, but it may be more readable and avoid you having to work around the need for infinity and having to account for epsilon twice.&#xD;&#xA;&#xD;&#xA;If the ray is simply a starting point and a direction, then shadow rays can simply check that the first intersection is the light, rather than checking that there is no intersection. For example, by replacing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == LIGHT) // There is no object intersected before the light&#xD;&#xA;&#xD;&#xA;Here I use `LIGHT` as a placeholder for the id of the light source, since that part of the code is not included in the question.&#xD;&#xA;&#xD;&#xA;- This will always give false if the light is occluded by a nearer object.&#xD;&#xA;- This will always give true if the ray hits the light before any more distant objects.&#xD;&#xA;&#xD;&#xA;This is therefore equivalent to the current code, but does not require the ray to store a length.&#xD;&#xA;&#xD;&#xA;### Lights that don't reflect&#xD;&#xA;&#xD;&#xA;The code currently models lights and surfaces separately. This means that if an object is a light then it is only emissive, and reflects no light from other objects.&#xD;&#xA;&#xD;&#xA;This causes a negligible difference in the example scene in the question, which has a single bright light. However, if used with a number of dimmer lights, it would be more noticeable that they do not light each other. In many cases the difference will not be noticeable, so this is not a problem if it works for the scenes you wish to render.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [paper on which the code you are following was based]: https://mediatech.aalto.fi/publications/graphics/GPT/kettunen2015siggraph_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6099" PostHistoryTypeId="5" PostId="2523" RevisionGUID="7624b3ef-cc58-4857-b5b1-deb7e6c72496" CreationDate="2016-05-29T00:53:36.330" UserId="231" Comment="Extra thoughts on area sampling" Text="I don't have any experience with Gradient Domain Path Tracing, but here are my thoughts:&#xD;&#xA;&#xD;&#xA;# There seems to be a different problem&#xD;&#xA;&#xD;&#xA;If you look carefully at the little spikes of distortion in the final image, you will see that they are all lit from the same direction - on their top left side at a consistent 45 degrees. The sphere also appears to be lit from this angle, rather than from above by the light source.&#xD;&#xA;&#xD;&#xA;This is unlikely to be explained by an incorrect probability estimation for a path. I would expect there to be a different problem with the code, that these distortions are hinting at.&#xD;&#xA;&#xD;&#xA;I will therefore address these two separate points:&#xD;&#xA;&#xD;&#xA;1. You want to know how to calculate the Probability Density of a path when using Next Event Estimation.&#xD;&#xA;1. There is evidence of some problem unrelated to this.&#xD;&#xA;&#xD;&#xA;I'll also review the code for non-essential points - but I'll leave this until after the essentials.&#xD;&#xA;&#xD;&#xA;# Probability Density of a path when using Next Event Estimation&#xD;&#xA;&#xD;&#xA;Looking at the [paper on which the code you are following was based] it seems that the novel shift mapping described in section 5.2 is defined in terms of the reflective properties of the surfaces found at the vertices of the path. I must emphasise that I don't have a full understanding of this, but it suggests that Next Event Estimation may not require a change in this approach, as the surfaces encountered will be the same. Hopefully once the other problems are cleared up it will be easier to judge whether the image looks correct.&#xD;&#xA;&#xD;&#xA;Note that section 5.2 of the paper already mentions (just below Figure 10) that they take into account sampling the emitter &quot;*either using BSDF or area sampling*&quot;.&#xD;&#xA;&#xD;&#xA;The difference with Next Event Estimation is that the area sampling happens at every vertex of the path, but it isn't obvious to me that this should cause a problem.&#xD;&#xA;&#xD;&#xA;The fact that your scene uses only diffuse surfaces means that the offset path should in most cases rejoin the base path at the second vertex, so you would only need to recalculate the area sampling for the first vertex of the offset path.&#xD;&#xA;&#xD;&#xA;# The cause of the incorrect lighting direction&#xD;&#xA;&#xD;&#xA;In reading through the code to familiarise myself with how it works, I noticed that `NLdotL` is calculated, but then not used. A text search revealed that the only other occurrence has a different case: `nldotl`. Here are the two variables in context (first and ninth lines of this excerpt):&#xD;&#xA;&#xD;&#xA;    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );&#xD;&#xA;    float NdotL = Vector3.Dot( ray.N, L );&#xD;&#xA;    if (NdotL &gt; 0)&#xD;&#xA;    {&#xD;&#xA;        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point&#xD;&#xA;        Scene.Intersect( r );&#xD;&#xA;        if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;        {&#xD;&#xA;            float solidAngle= (nldotl * light.getArea()) / (dist * dist);&#xD;&#xA;            E += T * (NdotL) * solidAngle * BRDF * light.emission;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Since `nldotl` is not defined, the result of the code is undefined behaviour. In practice, the program is likely to act as if `nldotl` is zero, or for some compilers perhaps a constant arbitrary value, or even a different arbitrary value at each iteration. For your particular compiler it appears to be a constant value, and I strongly suspect this is the cause of the distinctive alignment of lighting angle on all the speckles and the sphere. If there is also another contributing problem it will be easier to analyse it in a separate question once this initial problem has been fixed.&#xD;&#xA;&#xD;&#xA;It may be worth considering using a compiler and/or flag setting that gives an error or at the very least a warning for undefined variables, as this type of mistake is both very easy to make, and very easy to overlook later.&#xD;&#xA;&#xD;&#xA;# Additional contribution of light source&#xD;&#xA;&#xD;&#xA;There appears to be another problem that will cause results to be incorrect in a more subtle way, with no obvious distortion. Due to Next Event Estimation, the light source is contributing to each step along the path. This means it should not make a contribution if the path itself hits the light source directly. Otherwise, for that path the light source will be contributing twice. You can correct this by changing:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        E += material.diffuse;&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    if (material.emissive) //case of a light&#xD;&#xA;    {&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This will give a zero contribution from the intersection with the light.&#xD;&#xA;&#xD;&#xA;Note that since I can only see this one function, I can't guess whether this will also make the light appear black in the image. You may or may not need to adjust for rays that start at the camera and hit the light directly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;### Doubly finite rays&#xD;&#xA;&#xD;&#xA;I'm used to defining a ray as a half infinite line segment - having a starting point but no ending point. I notice that this code gives a ray both a starting point and a length. The only place I can see a reason for this is when testing a shadow ray against the light source: the code checks that there are no intersections on the way to the light, so intersections behind the light (or on the light itself) must be excluded. In all other places, the ray is defined with a pseudo-infinite length (`1e34f`).&#xD;&#xA;&#xD;&#xA;The following suggestion won't affect the *correctness* of your code, but it may be more readable and avoid you having to work around the need for infinity and having to account for epsilon twice.&#xD;&#xA;&#xD;&#xA;If the ray is simply a starting point and a direction, then shadow rays can simply check that the first intersection is the light, rather than checking that there is no intersection. For example, by replacing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == -1) //no occlusion towards the light&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    if (r.objIdx == LIGHT) // There is no object intersected before the light&#xD;&#xA;&#xD;&#xA;Here I use `LIGHT` as a placeholder for the id of the light source, since that part of the code is not included in the question.&#xD;&#xA;&#xD;&#xA;- This will always give false if the light is occluded by a nearer object.&#xD;&#xA;- This will always give true if the ray hits the light before any more distant objects.&#xD;&#xA;&#xD;&#xA;This is therefore equivalent to the current code, but does not require the ray to store a length.&#xD;&#xA;&#xD;&#xA;### Lights that don't reflect&#xD;&#xA;&#xD;&#xA;The code currently models lights and surfaces separately. This means that if an object is a light then it is only emissive, and reflects no light from other objects.&#xD;&#xA;&#xD;&#xA;This causes a negligible difference in the example scene in the question, which has a single bright light. However, if used with a number of dimmer lights, it would be more noticeable that they do not light each other. In many cases the difference will not be noticeable, so this is not a problem if it works for the scenes you wish to render.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [paper on which the code you are following was based]: https://mediatech.aalto.fi/publications/graphics/GPT/kettunen2015siggraph_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="6100" PostHistoryTypeId="2" PostId="2524" RevisionGUID="c3a111af-eb58-4a03-a8f4-6426b6c584d6" CreationDate="2016-05-29T01:45:44.823" UserId="231" Text="*Note that the approach you appear to be taking will only work for lines with a slope in a single octant. For the other seven octants the algorithm requires changing the approach, for example by changing the values of x and y. Wikipedia gives a [table of cases] that can be used for this conversion.*&#xD;&#xA;&#xD;&#xA;*For this answer I will assume you are simply trying to get the code working for the first octant.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I notice you have multiplied the calculations by 2 in order to make the entire algorithm work with only integers. This will still work fine.&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;`parameter` starts off negative only if `dx` &gt; `2 * dy`.&#xD;&#xA;&#xD;&#xA;In this case the total horizontal distance to be covered by the line is more than twice the vertical distance, which means the first step should be purely horizontal. So if `parameter` is negative then `y0` should not change.&#xD;&#xA;&#xD;&#xA;Here is the source of the problem:&#xD;&#xA;&#xD;&#xA;    if(parameter &lt; 0){&#xD;&#xA;               y0 += 1;&#xD;&#xA;&#xD;&#xA;`y0` should only be incremented if `parameter` is not negative. This `y0 += 1` is causing vertical movement even if the first step should be purely horizontal.&#xD;&#xA;&#xD;&#xA;The same problem applies on later steps too. The code causes `parameter` to switch back and for between negative and non-negative in proportion to the ratio between `dx` and `dy` (in this case `2 * dx` and `2 * dy` to keep everything integer). `y0` must only be incremented when `parameter` is non-negative. That additional occurrence of `y0 += 1` prevents `y0` from ever staying still, causing a slope of 1 regardless of the inputs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [table of cases]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases" ContentLicense="CC BY-SA 3.0" />
  <row Id="6101" PostHistoryTypeId="5" PostId="2524" RevisionGUID="585aed47-4126-4733-b34f-6db07d2f56d5" CreationDate="2016-05-29T01:50:46.630" UserId="231" Comment="deleted 64 characters in body" Text="*Note that the approach you appear to be taking will only work for lines with a slope in a single octant. For the other seven octants the algorithm requires changing the approach, for example by changing the values of x and y. Wikipedia gives a [table of cases] that can be used for this conversion.*&#xD;&#xA;&#xD;&#xA;*For this answer I will assume you are simply trying to get the code working for the first octant.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I notice you have multiplied the calculations by 2 in order to make the entire algorithm work with only integers. This will still work fine.&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;`parameter` starts off negative only if `dx` &gt; `2 * dy`.&#xD;&#xA;&#xD;&#xA;In this case the total horizontal distance to be covered by the line is more than twice the vertical distance, which means the first step should be purely horizontal. So if `parameter` is negative then `y0` should not change.&#xD;&#xA;&#xD;&#xA;Here is the source of the problem:&#xD;&#xA;&#xD;&#xA;    if(parameter &lt; 0){&#xD;&#xA;               y0 += 1;&#xD;&#xA;&#xD;&#xA;`y0` should only be incremented if `parameter` is not negative. This `y0 += 1` is causing vertical movement even if the first step should be purely horizontal.&#xD;&#xA;&#xD;&#xA;The same problem applies on later steps too. The code causes `parameter` to switch back and for between negative and non-negative in proportion to the ratio between `dx` and `dy`. `y0` must only be incremented when `parameter` is non-negative. That additional occurrence of `y0 += 1` prevents `y0` from ever staying still, causing a slope of 1 regardless of the inputs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [table of cases]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases" ContentLicense="CC BY-SA 3.0" />
  <row Id="6102" PostHistoryTypeId="5" PostId="2524" RevisionGUID="2341c62c-d13a-42c8-aa61-74d5c9919021" CreationDate="2016-05-29T01:59:09.937" UserId="231" Comment="added 4 characters in body" Text="*Note that the approach you appear to be taking will only work for lines with a slope in a single octant. For the other seven octants the algorithm requires changing the approach, for example by changing the values of x and y. Wikipedia gives a [table of cases] that can be used for this conversion.*&#xD;&#xA;&#xD;&#xA;*For this answer I will assume you are simply trying to get the code working for the first octant.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I notice you have multiplied the calculations by 2 in order to make the entire algorithm work with only integers. This will still work fine.&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;`parameter` starts off negative only if `dx` &gt; `2 * dy`.&#xD;&#xA;&#xD;&#xA;In this case the total horizontal distance to be covered by the line is more than twice the vertical distance, which means the first step should be purely horizontal. So if `parameter` is negative then `y0` should not change.&#xD;&#xA;&#xD;&#xA;Here is the source of the problem:&#xD;&#xA;&#xD;&#xA;    if(parameter &lt; 0){&#xD;&#xA;               y0 += 1;&#xD;&#xA;&#xD;&#xA;`y0` should only be incremented if `parameter` is not negative. This `y0 += 1` is causing vertical movement even if the first step should be purely horizontal.&#xD;&#xA;&#xD;&#xA;The same problem applies on later steps too. The code causes `parameter` to switch back and for between negative and non-negative in proportion to the ratio between `2 * dx` and `dy`. `y0` must only be incremented when `parameter` is non-negative. That additional occurrence of `y0 += 1` prevents `y0` from ever staying still, causing a slope of 1 regardless of the inputs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [table of cases]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases" ContentLicense="CC BY-SA 3.0" />
  <row Id="6103" PostHistoryTypeId="5" PostId="2524" RevisionGUID="63ee86bd-0b6a-41e0-99da-6aab49a749e1" CreationDate="2016-05-29T02:07:58.887" UserId="231" Comment="deleted 144 characters in body" Text="*Note that the approach you appear to be taking will only work for lines with a slope in a single octant. For the other seven octants the algorithm requires changing the approach, for example by changing the values of x and y. Wikipedia gives a [table of cases] that can be used for this conversion.*&#xD;&#xA;&#xD;&#xA;*For this answer I will assume you are simply trying to get the code working for the first octant.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;`parameter` starts off negative only if `dx` &gt; `2 * dy`.&#xD;&#xA;&#xD;&#xA;In this case the total horizontal distance to be covered by the line is more than twice the vertical distance, which means the first step should be purely horizontal. So if `parameter` is negative then `y0` should not change.&#xD;&#xA;&#xD;&#xA;Here is the source of the problem:&#xD;&#xA;&#xD;&#xA;    if(parameter &lt; 0){&#xD;&#xA;               y0 += 1;&#xD;&#xA;&#xD;&#xA;`y0` should only be incremented if `parameter` is not negative. This `y0 += 1` is causing vertical movement even if the first step should be purely horizontal.&#xD;&#xA;&#xD;&#xA;The same problem applies on later steps too. The code causes `parameter` to switch back and for between negative and non-negative in proportion to the ratio between `2 * dx` and `dy`. `y0` must only be incremented when `parameter` is non-negative. That additional occurrence of `y0 += 1` prevents `y0` from ever staying still, causing a slope of 1 regardless of the inputs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [table of cases]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases" ContentLicense="CC BY-SA 3.0" />
  <row Id="6104" PostHistoryTypeId="5" PostId="2524" RevisionGUID="ccefd515-9e9c-4c90-b2c6-afdd8628d3c3" CreationDate="2016-05-29T02:23:33.710" UserId="231" Comment="Explain strict inequality" Text="*Note that the approach you appear to be taking will only work for lines with a slope in a single octant. For the other seven octants the algorithm requires changing the approach, for example by changing the roles of x and y. Wikipedia gives a [table of cases] that can be used for this conversion.*&#xD;&#xA;&#xD;&#xA;*For this answer I will assume you are simply trying to get the code working for the first octant.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;`parameter` starts off negative only if `dx` &gt; `2 * dy`.&#xD;&#xA;&#xD;&#xA;In this case the total horizontal distance to be covered by the line is more* than twice the vertical distance, which means the first step should be purely horizontal. So if `parameter` is negative then `y0` should not change.&#xD;&#xA;&#xD;&#xA;Here is the source of the problem:&#xD;&#xA;&#xD;&#xA;    if(parameter &lt; 0){&#xD;&#xA;               y0 += 1;&#xD;&#xA;&#xD;&#xA;`y0` should only be incremented if `parameter` is *not* negative. This `y0 += 1` is causing vertical movement even if the first step should be purely horizontal.&#xD;&#xA;&#xD;&#xA;The same problem applies on later steps too. The code causes `parameter` to switch back and for between negative and non-negative in proportion to the ratio between `2 * dx` and `dy`. `y0` must only be incremented when `parameter` is non-negative. That additional occurrence of `y0 += 1` prevents `y0` from ever staying still, causing a slope of 1 regardless of the inputs. Simply remove that line and it should work correctly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*If you are wondering why the algorithm only steps purely horizontally when the parameter is less than zero, rather than less than or equal to zero, bear in mind that the horizontal distance to be covered is one less than the number of pixel columns displayed. If x0 is 0 and x1 is 3, then dx is 3, but 4 columns of pixels will be displayed. So a line 4 pixels across and 2 pixels down actually has xd as 3 and yd as 1. In this case the number of pixels across is exactly twice the number of pixels down, but xd is *more* than twice yd, so this still results in the parameter being negative.&#xD;&#xA;  [table of cases]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases" ContentLicense="CC BY-SA 3.0" />
  <row Id="6105" PostHistoryTypeId="5" PostId="2524" RevisionGUID="9af1e10e-3ce1-4d12-ab91-7529f97516df" CreationDate="2016-05-29T02:29:31.397" UserId="231" Comment="added 62 characters in body" Text="*Note that the approach you appear to be taking will only work for lines with a slope in a single octant. For the other seven octants the algorithm requires changing the approach, for example by changing the roles of x and y. Wikipedia gives a [table of cases] that can be used for this conversion.*&#xD;&#xA;&#xD;&#xA;*For this answer I will assume you are simply trying to get the code working for the first octant.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;`parameter` starts off negative only if `dx` &gt; `2 * dy`.&#xD;&#xA;&#xD;&#xA;In this case the total horizontal distance to be covered by the line is more* than twice the vertical distance, which means the first step should be purely horizontal. So if `parameter` is negative then `y0` should not change.&#xD;&#xA;&#xD;&#xA;Here is the source of the problem:&#xD;&#xA;&#xD;&#xA;    if(parameter &lt; 0){&#xD;&#xA;               y0 += 1;&#xD;&#xA;&#xD;&#xA;`y0` should only be incremented if `parameter` is *not* negative. This `y0 += 1` is causing vertical movement even if the first step should be purely horizontal.&#xD;&#xA;&#xD;&#xA;The same problem applies on later steps too. The code causes `parameter` to switch back and for between negative and non-negative in proportion to the ratio between `2 * dx` and `dy`. `y0` must only be incremented when `parameter` is non-negative. That additional occurrence of `y0 += 1` prevents `y0` from ever staying still, causing a slope of 1 regardless of the inputs. Simply remove that line and it should work correctly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*If you are wondering why the algorithm only steps purely horizontally when the parameter is less than zero, rather than less than or equal to zero, bear in mind that the horizontal distance to be covered is one less than the number of pixel columns displayed. If x0 is 0 and x1 is 3, then dx is 3, but 4 columns of pixels will be displayed. So a line 4 pixels across and 2 pixels down actually has xd as 3 and yd as 1. In this case the number of pixels across is exactly twice the number of pixels down, but xd is *more* than twice yd, so this still results in the parameter being negative and the line moving purely horizontally on the first step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [table of cases]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases" ContentLicense="CC BY-SA 3.0" />
  <row Id="6112" PostHistoryTypeId="5" PostId="2522" RevisionGUID="d4708ced-913a-46aa-81af-1a66f277d2db" CreationDate="2016-05-29T07:12:32.357" UserId="2479" Comment="deleted 221 characters in body" Text="Frankly, your implementation doesn't make much sense. It basically iterates x coordinate through `i` variable and increments `y` variable at each step. Since the `parameter` doesn't cross the 0 boundary, it generates the diagonal points you can see on your picture.&#xD;&#xA;&#xD;&#xA;You also compute and update the `parameter` variable somehow, but don't use it anywhere." ContentLicense="CC BY-SA 3.0" />
  <row Id="6115" PostHistoryTypeId="34" PostId="2461" RevisionGUID="73f7e171-d356-404a-8ab9-97b758e4a344" CreationDate="2016-05-29T12:40:17.747" UserId="-1" Comment="15" />
  <row Id="6116" PostHistoryTypeId="2" PostId="2526" RevisionGUID="5af3e7ed-fda4-42eb-bf03-90d69f974442" CreationDate="2016-05-29T14:05:33.413" UserId="3452" Text="After updating my graphics driver and trying to run [this][1] example from John Chapman's blog I got this error&#xD;&#xA;&#xD;&#xA;    Vertex shader failed to compile with the following errors:&#xD;&#xA;    ERROR: 0:8: error(#105) #version must occur before any other program statement&#xD;&#xA;&#xD;&#xA;I remember this working perfectly a few months ago. So what exactly has changed and the `#include` command is no longer valid?&#xD;&#xA;&#xD;&#xA;  [1]: http://john-chapman-graphics.blogspot.al/2013/02/pseudo-lens-flare.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="6117" PostHistoryTypeId="1" PostId="2526" RevisionGUID="5af3e7ed-fda4-42eb-bf03-90d69f974442" CreationDate="2016-05-29T14:05:33.413" UserId="3452" Text="Why cant I use `#include` after upgrading my driver" ContentLicense="CC BY-SA 3.0" />
  <row Id="6118" PostHistoryTypeId="3" PostId="2526" RevisionGUID="5af3e7ed-fda4-42eb-bf03-90d69f974442" CreationDate="2016-05-29T14:05:33.413" UserId="3452" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6119" PostHistoryTypeId="5" PostId="2526" RevisionGUID="22daa9e0-75d1-4388-ac06-7b27ecb4b6b0" CreationDate="2016-05-29T14:53:12.817" UserId="3452" Comment="added 295 characters in body" Text="After updating my graphics driver and trying to run [this][1] example from John Chapman's blog I got this error&#xD;&#xA;&#xD;&#xA;    Vertex shader failed to compile with the following errors:&#xD;&#xA;    ERROR: 0:8: error(#105) #version must occur before any other program statement&#xD;&#xA;&#xD;&#xA;The way that the version is defined is by including a file containing this code&#xD;&#xA;&#xD;&#xA;    #ifndef DEF_GLSL_&#xD;&#xA;    #define DEF_GLSL_&#xD;&#xA;    &#xD;&#xA;    #version 420&#xD;&#xA;    &#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;So inside all other shader files one can see that the first line is as follows&#xD;&#xA;&#xD;&#xA;    #include &quot;common/def.glsl&quot;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;I remember this working perfectly a few months ago. So what exactly has changed and the `#include` command is no longer valid?&#xD;&#xA;&#xD;&#xA;  [1]: http://john-chapman-graphics.blogspot.al/2013/02/pseudo-lens-flare.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="6120" PostHistoryTypeId="2" PostId="2527" RevisionGUID="cdb26f11-5f1b-48e2-a5e7-ec4658dca16e" CreationDate="2016-05-29T16:33:58.057" UserId="231" Text="The error message gives a clue in the wording:&#xD;&#xA;&#xD;&#xA;    #version must occur before any other program statement&#xD;&#xA;&#xD;&#xA;Is there a reason that the previous 2 lines need to appear before the `#version` line? If not, you can avoid the error by moving this line to the beginning, since the actions of the lines are independent of their order in this instance.&#xD;&#xA;&#xD;&#xA;The `#version` needing to be at the beginning of the file is not a new requirement. I don't know why you were able to run this code previously." ContentLicense="CC BY-SA 3.0" />
  <row Id="6123" PostHistoryTypeId="2" PostId="2528" RevisionGUID="b3aa76df-ad01-45ca-9b39-7f76965ee3c4" CreationDate="2016-05-30T08:37:34.313" UserId="3073" Text="Are you calling glViewport when switching drawing to FBO ? This should be called when switching into a different resolution render target. I say this because case #1 is a symptom of incorrect glViewport." ContentLicense="CC BY-SA 3.0" />
  <row Id="6124" PostHistoryTypeId="2" PostId="2529" RevisionGUID="b97cb267-4505-4216-b988-b0e8395ebb8d" CreationDate="2016-05-30T12:43:29.830" UserId="67" Text="I'm using a Sobel filter to draw an outline in a shader. How do I control its thickness? Here's my outlining code:&#xD;&#xA;&#xD;&#xA;    float3x3 Kx = {&#xD;&#xA;    -1, 0, 1,&#xD;&#xA;    -2, 0, 2,&#xD;&#xA;    -1, 0, 1};&#xD;&#xA;    &#xD;&#xA;    float3x3 Ky = {&#xD;&#xA;    1, 2, 1,&#xD;&#xA;    0, 0, 0,&#xD;&#xA;    -1,-2,-1};&#xD;&#xA;    &#xD;&#xA;    float Lx = 0;&#xD;&#xA;    float Ly = 0;    &#xD;&#xA;    &#xD;&#xA;    for (int y = -1; y &lt;= 1; ++y) {&#xD;&#xA;        for (int x = -1; x&lt;= 1; ++x) {&#xD;&#xA;            float2 offset = float2( x, y );&#xD;&#xA;            float3 tex = tex2D(sampler, uv + offset).rgb;&#xD;&#xA;            float luminance = dot(tex, float3(0.3, 0.59, 0.11));&#xD;&#xA;         &#xD;&#xA;            Lx += luminance * Kx[y+1][x+1];&#xD;&#xA;            Ly += luminance * Ky[y+1][x+1];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    float color = sqrt(Lx*Lx + Ly*Ly);&#xD;&#xA;    return float4( color, color, color, color );" ContentLicense="CC BY-SA 3.0" />
  <row Id="6125" PostHistoryTypeId="1" PostId="2529" RevisionGUID="b97cb267-4505-4216-b988-b0e8395ebb8d" CreationDate="2016-05-30T12:43:29.830" UserId="67" Text="Controlling Sobel edge thickness" ContentLicense="CC BY-SA 3.0" />
  <row Id="6126" PostHistoryTypeId="3" PostId="2529" RevisionGUID="b97cb267-4505-4216-b988-b0e8395ebb8d" CreationDate="2016-05-30T12:43:29.830" UserId="67" Text="|shader|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6129" PostHistoryTypeId="2" PostId="2530" RevisionGUID="de2311a1-8d49-419f-893e-dce3c55f964f" CreationDate="2016-05-30T16:47:25.703" UserId="3041" Text="First off you want the start of each line to have the color of an already faded line, ie rgb_color*0.95. You already figured out how to do this so I stop there.&#xA;&#xA;For the HSV you are interested in the Value component only when fading towards black. Basically you should do hsv_color.value*0.95.&#xA;&#xA;I typed this on phone. Please edit if you get it and may explain better." ContentLicense="CC BY-SA 3.0" />
  <row Id="6130" PostHistoryTypeId="2" PostId="2531" RevisionGUID="30b038d5-8a58-405a-a6f5-1fbf09c76b4a" CreationDate="2016-05-30T17:38:15.047" UserId="3459" Text="I am a some-what experienced programer, and I have been working on creating a 3D graphics engine utilizing the OpenGL system, primarily focused on use in games. However, I also want to do some work with functional programming, and wanted to create a clean UI for more functional programs, like a task manager. An example of the kind of effect that I want to create could be somewhat like the Visual Studio Code UI. My question is: is there a specific library that I should use for creating desktop programs, or should I continue to use OpenGL's 3D aspects, but keep everything in a single Z axis plane, effectively creating a 2D program? Or is there a better way to create normal program visuals, that wont be cheating out of a 3D graphical space?&#xD;&#xA;&#xD;&#xA;Thanks for your help." ContentLicense="CC BY-SA 3.0" />
  <row Id="6131" PostHistoryTypeId="1" PostId="2531" RevisionGUID="30b038d5-8a58-405a-a6f5-1fbf09c76b4a" CreationDate="2016-05-30T17:38:15.047" UserId="3459" Text="Optimal 2D graphics resource" ContentLicense="CC BY-SA 3.0" />
  <row Id="6132" PostHistoryTypeId="3" PostId="2531" RevisionGUID="30b038d5-8a58-405a-a6f5-1fbf09c76b4a" CreationDate="2016-05-30T17:38:15.047" UserId="3459" Text="|opengl|3d|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6133" PostHistoryTypeId="2" PostId="2532" RevisionGUID="e7be3883-4de3-48e1-ba90-a607cf7d7fca" CreationDate="2016-05-30T17:48:43.137" UserId="3041" Text="I'll say a few words about rendering without graphics cards.&#xA;&#xA;Niether OpenGL nor DirectX really need a graphics card. An implementation may be fully software accelerated.&#xA;&#xA;For OpenGL in Linux there is Mesa software rasterizer. In my experience it works ok as long as you don't push it too hard combining weird features (display list + indexed vertex arrays). I imagine their list of actual bugs is mile high. Make sure to do continous testing!&#xA;&#xA;I have less experience using OpenGL in Windows. Edit answer if you know anything!&#xA;&#xA;DirectX SDK is delivered with a software rasterizer called &quot;reference rasterizer&quot;. It is mostly for debugging in my opinion but I know of at least one friend using the reference rasterizer when developing DX11 on a DX10 only capable laptop. As mentioned in other answers DirectX is Microsoft only." ContentLicense="CC BY-SA 3.0" />
  <row Id="6134" PostHistoryTypeId="5" PostId="2531" RevisionGUID="0e76fac5-6c0d-4652-afb7-aeb2ca8cd14f" CreationDate="2016-05-30T18:58:14.850" UserId="3459" Comment="added 112 characters in body" Text="I am a some-what experienced programer, and I have been working on creating a 3D graphics engine utilizing the OpenGL system, primarily focused on use in games. However, I also want to do some work with functional programming, and wanted to create a clean UI for more functional programs, like a task manager. An example of the kind of effect that I want to create could be somewhat like the Visual Studio Code UI. My question is: is there a specific library that I should use for creating desktop programs, or should I continue to use OpenGL's 3D aspects, but keep everything in a single Z axis plane, effectively creating a 2D program? Or is there a better way to create normal program visuals, that wont be cheating out of a 3D graphical space?&#xD;&#xA;&#xD;&#xA;Thanks for your help.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I am currently using C++/C, but I am also happy to expand my knowledge base to include new languages." ContentLicense="CC BY-SA 3.0" />
  <row Id="6135" PostHistoryTypeId="2" PostId="2533" RevisionGUID="71c9e85d-04f9-4d34-8997-fccd0c4e157f" CreationDate="2016-05-30T19:55:19.277" UserDisplayName="user3437" Text="As you said you want to create something like this [![][1]][1]&#xD;&#xA;&#xD;&#xA;As you know these are not graphic intense rendering.&#xD;&#xA;Thus, (i guess but not 100%) Windows do these rendering on CPU not on GPU.&#xD;&#xA;GPU is for intense rendering with lighting, textures, 3D models, etc. Where you can take the benefit of algorithm built in GPU circuit, Which is what OpenGL does.&#xD;&#xA;&#xD;&#xA;So i would recommend to use built-in libraries that don't use GPU and use CPU for rendering, Although you can use OpenGL or Direct3D as well.     &#xD;&#xA;&#xD;&#xA;Some libraries that are built in different programming languages are :-&#xD;&#xA;&#xD;&#xA;&gt;Java - Jframe, Graphics, Buffered image,  Canvas. (Note : all these libraries have different functionality and you have to use them together for software rendering [See this for more detail][2]) &#xD;&#xA;&#xD;&#xA;&gt;C# - System.drawing,  (i don't have much experience of C#, So i can't name any more libraries), also C# form application.&#xD;&#xA;&#xD;&#xA;&gt;JavaScript - Canvas [check this out][3]&#xD;&#xA;&#xD;&#xA;&gt;C++ - you need third party libraries like QT, GTX etc. [Qt learning resource][4], [related resource][5]&#xD;&#xA;&#xD;&#xA;&gt;Python - Pygame (No personnal eperience) [See this for detail][6]&#xD;&#xA; &#xD;&#xA;  [1]: https://i.stack.imgur.com/WOk2z.png&#xD;&#xA;  [2]: https://www.youtube.com/playlist?list=PLEETnX-uPtBUbVOok816vTl1K9vV1GgH5&#xD;&#xA;  [3]: https://www.youtube.com/playlist?list=PLh-MBXZEiyMhulEqYE3gn63idSAKG6Sx1&#xD;&#xA;  [4]: https://www.youtube.com/watch?v=6KtOzh0StTc&amp;list=PL2D1942A4688E9D63&#xD;&#xA;  [5]: https://www.youtube.com/watch?v=FxCC9Ces1Yg&amp;list=PLSPw4ASQYyymu3PfG9gxywSPghnSMiOAW&#xD;&#xA;  [6]: https://www.youtube.com/playlist?list=PLQVvvaa0QuDdLkP8MrOXLe_rKuf6r80KO" ContentLicense="CC BY-SA 3.0" />
  <row Id="6136" PostHistoryTypeId="5" PostId="2519" RevisionGUID="a30d51cb-35ae-4dfc-892f-3c1467e6bc20" CreationDate="2016-05-30T21:35:41.830" UserId="2479" Comment="Fixed error in the first formula ($\omega_g$ replaced with $\omega_m$)" Text="TL;DR: Your $G1$ formula is wrong. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Just to avoid confusion, I am assuming the isotropic version of the BRDF, the Smith microfacet model (as opposed to the V-cavity model), and the GGX microfacet distribution.&#xD;&#xA;&#xD;&#xA;According to [Heitz 2014][1], the masking/shadowing term $G1$ is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\omega_{v}\cdot\omega_{m}\right)&#xD;&#xA;\frac{2}{1+\sqrt{1+\alpha_{o}^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and according to [Walter 2007][2], the formula is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\chi^{+}\left(\frac{\omega_{v}\cdot\omega_{g}}{\omega_{v}\cdot\omega_{m}}\right)\frac{2}{1+\sqrt{1+\alpha^{2}\tan^{2}\theta_{v}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $\omega_{m}$ is the microfacet normal direction (halfway vector), $\omega_{g}$ is the main (geometric) normal direction (normal), $\omega_{v}$ is the incoming or outgoing direction, $\alpha$ is the isotropic roughness parameter, and $\chi^{+}\left(a\right)$ is the positive characteristic function, or the Heaviside step function (equals one if $a&gt;0$ and zero otherwise).&#xD;&#xA;&#xD;&#xA;As you can notice, the half vector $\omega_{m}$ is used only to make sure the $G1$ is zero if the geometrical configuration is forbidden. More precisely, it makes sure that the back surface of the microsurface is never visible from the $\omega_{v}$ direction on the front side of the macrosurface and vice versa (the latter case is meaningful only when also refractions are supported). If the calling code guarantees this, then you can obviously omit this parameter. That is probably the reason why they did so in Unity.&#xD;&#xA;&#xD;&#xA;Your implementation, on the other hand, uses the half vector to compute the cosine of the $\omega_{v}$ direction with respect to the microfacet, which leads to computation of something else than the presented formulae.&#xD;&#xA;&#xD;&#xA;If it is of any help, then this is my implementation of the $G1$ factor:&#xD;&#xA;&#xD;&#xA;    float SmithMaskingFunctionGgx(&#xD;&#xA;        const Vec3f &amp;aDir,  // the direction to compute masking for (either incoming or outgoing)&#xD;&#xA;        const Vec3f &amp;aMicrofacetNormal,&#xD;&#xA;        const float  aRoughnessAlpha)&#xD;&#xA;    {&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aDir);&#xD;&#xA;        PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);&#xD;&#xA;        PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);&#xD;&#xA;&#xD;&#xA;        if (aMicrofacetNormal.z &lt;= 0)&#xD;&#xA;            return 0.0f;&#xD;&#xA;&#xD;&#xA;        const float cosThetaVM = Dot(aDir, aMicrofacetNormal);&#xD;&#xA;        if ((aDir.z * cosThetaVM) &lt; 0.0f)&#xD;&#xA;            return 0.0f; // up direction is below microfacet or vice versa&#xD;&#xA;&#xD;&#xA;        const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;&#xD;&#xA;        const float tanThetaSqr = Geom::TanThetaSqr(aDir);&#xD;&#xA;        const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);&#xD;&#xA;&#xD;&#xA;        const float result = 2.0f / (1.0f + root);&#xD;&#xA;&#xD;&#xA;        PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://hal.inria.fr/hal-00996995&#xD;&#xA;  [2]: http://dx.doi.org/10.2312/EGWR/EGSR07/195-206" ContentLicense="CC BY-SA 3.0" />
  <row Id="6137" PostHistoryTypeId="2" PostId="2534" RevisionGUID="0eeab134-d71e-4ef0-afc0-f62ec5024d0c" CreationDate="2016-05-30T21:39:46.060" UserId="2712" Text="I am going through one of the most basic line drawing algorithms and stuck with the following mathematical explanations. The implicit function of line equation is:&#xD;&#xA;&#xD;&#xA;    f(x,y) = ax + by + c&#xD;&#xA;&#xD;&#xA;The Book(Computer Graphics , Principles  and practice) mentions that&#xD;&#xA;&#xD;&#xA;    f(x,y) = 0 , when any point m is on line&#xD;&#xA;    f(x,y) &lt; 0, when any point m is above the line, and &#xD;&#xA;    f(x,y) &gt; 0, when any point m is below the line.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It would be great to have some explanation of the claim above. I tried to figure out the first one with the following example:&#xD;&#xA;&#xD;&#xA;    3x + 2y = 1&#xD;&#xA;    =&gt; 3x + 2y -1 = 0, where a = 3, b = 2 and c = -1&#xD;&#xA;&#xD;&#xA;All I figure out that I need to plug in a (x,y) coordinate so that 3x + 2y - 1 = 0. I am not sure how to choose this coordinate value .&#xD;&#xA;&#xD;&#xA;And I am clueless about the next two cases. An example demonstrating all the three cases would be fantastic !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 3.0" />
  <row Id="6138" PostHistoryTypeId="1" PostId="2534" RevisionGUID="0eeab134-d71e-4ef0-afc0-f62ec5024d0c" CreationDate="2016-05-30T21:39:46.060" UserId="2712" Text="Midpoint algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="6139" PostHistoryTypeId="3" PostId="2534" RevisionGUID="0eeab134-d71e-4ef0-afc0-f62ec5024d0c" CreationDate="2016-05-30T21:39:46.060" UserId="2712" Text="|midpoint|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6140" PostHistoryTypeId="2" PostId="2535" RevisionGUID="5306d7ce-e93b-41fa-85ee-80251f1aa887" CreationDate="2016-05-31T04:50:19.163" UserDisplayName="user3437" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TizJk.png&#xD;&#xA;&#xD;&#xA;Let $ax + by + c$ be any line such that $b &gt; 0$. &#xD;&#xA;&#xD;&#xA;Now pick point $(\alpha,\beta)$ on the line.&#xD;&#xA;&#xD;&#xA;Thus $\alpha *a + \beta*b + c = 0$&#xD;&#xA;&#xD;&#xA;Now pick a point $(\alpha, \gamma)$ such that $\gamma$ &gt; $\beta$ &#xD;&#xA;&#xD;&#xA;Thus $\alpha * a + \gamma * b + c$  &gt; 0&#xD;&#xA;&#xD;&#xA;Thus any point satisfying $ax+by +c$ &gt; 0 line above the line. &#xD;&#xA;&#xD;&#xA;your results can be deduced from the converse of the proof. " ContentLicense="CC BY-SA 3.0" />
  <row Id="6141" PostHistoryTypeId="2" PostId="2536" RevisionGUID="807d53c0-cab6-4295-9b0d-1bdbcdfb0829" CreationDate="2016-05-31T04:50:41.500" UserId="3003" Text="I've done this 2 different ways in the past:&#xD;&#xA;&#xD;&#xA; 1. Apply a pre-blur to the image before running the Sobel operator on it. This will have the side effect of getting rid of any noise that's smaller than the blur kernel, but it will also thicken the lines you end up drawing, too.&#xD;&#xA; 2. Apply a post-process where you thicken the lines by either stamping a shape at every point that's an edge, or using some sort of [dilate process](https://en.wikipedia.org/wiki/Mathematical_morphology).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6142" PostHistoryTypeId="5" PostId="2535" RevisionGUID="24f8bc1d-c2a5-4906-9bfc-e938de4eabfb" CreationDate="2016-05-31T04:55:52.333" UserDisplayName="user3437" Comment="added 63 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TizJk.png&#xD;&#xA;&#xD;&#xA;(I know i marked the coordinates of the second point wrong)&#xD;&#xA;&#xD;&#xA;Let $ax + by + c$ be any line such that $b &gt; 0$. &#xD;&#xA;&#xD;&#xA;Now pick point $(\alpha,\beta)$ on the line.&#xD;&#xA;&#xD;&#xA;Thus $\alpha *a + \beta*b + c = 0$&#xD;&#xA;&#xD;&#xA;Now pick a point $(\alpha, \gamma)$ such that $\gamma$ &gt; $\beta$ &#xD;&#xA;&#xD;&#xA;Thus $\alpha * a + \gamma * b + c$  &gt; 0&#xD;&#xA;&#xD;&#xA;Thus any point satisfying $ax+by +c$ &gt; 0 line above the line. &#xD;&#xA;&#xD;&#xA;your results can be deduced from the converse of the proof. " ContentLicense="CC BY-SA 3.0" />
  <row Id="6143" PostHistoryTypeId="2" PostId="2537" RevisionGUID="3504ee09-3dc0-4c1a-a5fe-f78b19033885" CreationDate="2016-05-31T09:12:46.230" UserId="209" Text="(Promoting &quot;comment&quot; to an answer)&#xD;&#xA;	&#xD;&#xA;It looks to me that it's just finding monotonic runs of edges. Given a defined winding order (in this case anticlockwise), then you can identify {P6, P7, P8, P0} as a decreasing run, as is {P2, P3, P4}. Since the left most vertex, P8, is on a decreasing run, the decreasing runs define left boundaries and, therefore, increasing runs are right boundaries." ContentLicense="CC BY-SA 3.0" />
  <row Id="6144" PostHistoryTypeId="2" PostId="2538" RevisionGUID="f8dd4e5b-597b-41b5-8467-7920400a592f" CreationDate="2016-05-31T10:13:37.447" UserId="2712" Text="I have a bounding area of a contour after the slicing operation. Now to generate the tool-path over the contour, I need to distribute the bounding area into grid space so that each each cell maintain a certain precomputed width.&#xD;&#xA;&#xD;&#xA;I am doing the math as follows, but I am not sure if the whole area will be covered as there is floating point values concatenated to integer coordinates.&#xD;&#xA;&#xD;&#xA;           short int xDist = std::abs(xMax - xMin);&#xD;&#xA;           short int yDist = std::abs(yMax - yMin);&#xD;&#xA;&#xD;&#xA;           short int xCells = (xDist/scanSpacingStep) + 1;&#xD;&#xA;           short int yCells = (yDist/scanSpacingStep) + 1;&#xD;&#xA;&#xD;&#xA;The indexing starts from (0,0). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="6145" PostHistoryTypeId="1" PostId="2538" RevisionGUID="f8dd4e5b-597b-41b5-8467-7920400a592f" CreationDate="2016-05-31T10:13:37.447" UserId="2712" Text="distribute the bounding area into grid space" ContentLicense="CC BY-SA 3.0" />
  <row Id="6146" PostHistoryTypeId="3" PostId="2538" RevisionGUID="f8dd4e5b-597b-41b5-8467-7920400a592f" CreationDate="2016-05-31T10:13:37.447" UserId="2712" Text="|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6154" PostHistoryTypeId="2" PostId="2540" RevisionGUID="22983c72-07ca-4f4f-888f-7ba80335d09a" CreationDate="2016-05-31T19:43:47.037" UserId="3123" Text="Is there any difference between registers types in hlsl?&#xD;&#xA;&#xD;&#xA;For example when using register t0 for UAV will it be somehow precache like textures?&#xD;&#xA;&#xD;&#xA;According to microsoft's presentation about resource in DX12 and hlsl 5.1 this registers mean nothing, but maybe they only mean that there isn't any real registers like on CPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6155" PostHistoryTypeId="1" PostId="2540" RevisionGUID="22983c72-07ca-4f4f-888f-7ba80335d09a" CreationDate="2016-05-31T19:43:47.037" UserId="3123" Text="Hlsl - registers type" ContentLicense="CC BY-SA 3.0" />
  <row Id="6156" PostHistoryTypeId="3" PostId="2540" RevisionGUID="22983c72-07ca-4f4f-888f-7ba80335d09a" CreationDate="2016-05-31T19:43:47.037" UserId="3123" Text="|gpu|hlsl|directx12|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6157" PostHistoryTypeId="2" PostId="2541" RevisionGUID="aef2444b-e92d-43b0-ae36-14a43a28023d" CreationDate="2016-05-31T19:58:37.443" UserDisplayName="user3437" Text="Here is my function that does interpolation&#xD;&#xA;&#xD;&#xA;	static public PixelData InterpolateColour(Point start, Point end ,float curLength, float totalLength){&#xD;&#xA;		&#xD;&#xA;		float endPercent = curLength / totalLength;				// Calculates the percent of colour at the ending point of the line to be used in current pixel &#xD;&#xA;		float startPercent = 1 - (curLength / totalLength);		// Calculates the percent of colour at the starting point of the line to be used in current pixel &#xD;&#xA;		&#xD;&#xA;		float startHueInRadians[] = PixelData.PixelDataToHsbInRadians(start.getColour()); 	// Converting the ending point colour into a hsb colour model &#xD;&#xA;		float endHueInRadians[] = PixelData.PixelDataToHsbInRadians(end.getColour());		// Converting the starting point colour into a hsb colour model&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;		startHueInRadians[0] = (startHueInRadians[0] == 0) ? 											// if the start colour is red then then choosing the value to be zero or 2*pi&#xD;&#xA;							   ((endHueInRadians[0] &gt;= (Math.PI * 4)/3) ?  (float)(Math.PI * 2) : 0)	// if the end colour is red then then choosing the value to be zero or 2*pi&#xD;&#xA;							   : startHueInRadians[0];&#xD;&#xA;							   &#xD;&#xA;		endHueInRadians[0] = (endHueInRadians[0] == 0) ? &#xD;&#xA;						     ((startHueInRadians[0] &gt;= (Math.PI * 4)/3) ?  (float)(Math.PI * 2) : 0)&#xD;&#xA;						     : endHueInRadians[0];&#xD;&#xA;			&#xD;&#xA;&#xD;&#xA;						     &#xD;&#xA;		float a = start.getColour().getAInInt() * endPercent + end.getColour().getAInInt() * startPercent;	//Interpolating alpha, which is not working :(				     &#xD;&#xA;		float h = endHueInRadians[0] * endPercent + startHueInRadians[0] * startPercent;					//Interpolating hue.&#xD;&#xA;		float s = endHueInRadians[1] * endPercent + startHueInRadians[1] * startPercent;					//Interpolating staturation, which is useless currently. :(&#xD;&#xA;		float b = endHueInRadians[2] * endPercent + startHueInRadians[2] * startPercent;					//Interpolating value, which is useless currently. :(&#xD;&#xA;			&#xD;&#xA;		float f[] = {h,s,b};&#xD;&#xA;		&#xD;&#xA;		PixelData p = PixelData.HsbinRadiansToPixelData(f); 	// Converting interpolated hsb back to rgb&#xD;&#xA;		&#xD;&#xA;		p.setAInInt((int)a);	//setting the alpha value &#xD;&#xA;			&#xD;&#xA;		return p;				// returing the intepolated value &#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;It is working properly but it is giant bulky code that runs very slowly because it has all kind of Ternary operator, floating point arithmetic and also it runs once per pixel.   &#xD;&#xA;&#xD;&#xA;I am currently refactoring my code to be small and less hacky. &#xD;&#xA;&#xD;&#xA;What are some interpolation algorithm that are used in computer graphics ? because i came up with this code and it is just bad.  " ContentLicense="CC BY-SA 3.0" />
  <row Id="6158" PostHistoryTypeId="1" PostId="2541" RevisionGUID="aef2444b-e92d-43b0-ae36-14a43a28023d" CreationDate="2016-05-31T19:58:37.443" UserDisplayName="user3437" Text="Is there a way to interpolate color across the line with only integer calculation ?`" ContentLicense="CC BY-SA 3.0" />
  <row Id="6159" PostHistoryTypeId="3" PostId="2541" RevisionGUID="aef2444b-e92d-43b0-ae36-14a43a28023d" CreationDate="2016-05-31T19:58:37.443" UserDisplayName="user3437" Text="|algorithm|color|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6160" PostHistoryTypeId="2" PostId="2542" RevisionGUID="4183858a-dc2b-4ef3-8d56-a657fc1fa8fc" CreationDate="2016-05-31T21:45:28.007" UserId="3410" Text="I have a post-effect camera-shader in which I want to implement a simple spatial partitioning of the screen between two passes of the fragment shader.&#xD;&#xA;&#xD;&#xA;The first pass should divide the screen into cells of size = 30x30 pixels, and then for each green fragment, store **somehow** which of those screen cells the coordinate of such green fragment  is located. That information should then be available for the second pass to work with.&#xD;&#xA;&#xD;&#xA;Well, merely dividing the screen into cells is trivial, considering that it's easy to calculate the row and column indexes of such screen-grid:&#xD;&#xA;&#xD;&#xA;	static float2 _Pixels = float2(_ScreenParams.x, _ScreenParams.y);&#xD;&#xA;    float2 griduv = round(input.uv * _Pixels) * _invPixels; //pixel-screen space coordinate of the current fragment being evaluated&#xD;&#xA;    half cellsize = 30.0f;&#xD;&#xA;&#xD;&#xA;    float gridX = griduv .x/cellsize;&#xD;&#xA;    float gridY = griduv .y/cellsize;&#xD;&#xA;&#xD;&#xA;    int gridrow = gridX  - frac(gridX);&#xD;&#xA;    int gridcol = gridY  - frac(gridY);&#xD;&#xA;&#xD;&#xA;If that was not a shader task but rather a standard CPU code, it would be just a matter of saving the `i`th `griduv` into an array-of-arrays (e.g. `float2[][] grid = new float2[gridrow*gridcol][maxNfloat2]`) at position `grid[gridrow*gridcol+gridrow][i]`.&#xD;&#xA;&#xD;&#xA;However, in a shader, for most hardwares and most DirectX and OpenGL versions, we can't have multi-dimensional arrays and we also can't pass variables and containers from one pass to the next. As one can easily see, this situation is also not well suited for using a simple texture to store values from one pass to the next, since I would need multiple `float2` into each grid cell.&#xD;&#xA;&#xD;&#xA;So, how could I proceed in such a situation? In other words, how could I store the pixel-screen coordinates of given fragments in a spatial-partitioning of the screen (in this case a simple fixed size grid of the screen), to be passed from one shader pass to the next?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6161" PostHistoryTypeId="1" PostId="2542" RevisionGUID="4183858a-dc2b-4ef3-8d56-a657fc1fa8fc" CreationDate="2016-05-31T21:45:28.007" UserId="3410" Text="In a shader, how to store fragment coordinates in a spatial partitioning from one pass to the next?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6162" PostHistoryTypeId="3" PostId="2542" RevisionGUID="4183858a-dc2b-4ef3-8d56-a657fc1fa8fc" CreationDate="2016-05-31T21:45:28.007" UserId="3410" Text="|shader|gpu|fragment-shader|grid|space-partitioning|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6163" PostHistoryTypeId="2" PostId="2543" RevisionGUID="121a2323-84ef-4f9d-8805-9a34209fd986" CreationDate="2016-05-31T22:55:46.933" UserId="231" Text="*Yes, it is possible to use only integer calculations. I will describe how, but bear in mind that the difference in speed between integer arithmetic and floating point arithmetic is not as great as it was historically. If you want your code to run faster, it is best to profile and identify which parts of the code are taking up most time, before considering whether to convert a particular aspect to use integers.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# A straight line through colour space&#xD;&#xA;&#xD;&#xA;Looking at the code, it appears you first convert from RGB to [HSB] then create a linear gradient, and convert it back to RGB.&#xD;&#xA;&#xD;&#xA;A linear gradient is a straight line through the colour space, so you can use an integer based straight line algorithm to generate it without the need for floating point arithmetic. For example, the [integer based version of Bresenham's algorithm].&#xD;&#xA;&#xD;&#xA;H, S, and B are being treated independently, so you can calculate each one separately. For example, the H component can be calculated by treating the line as a straight line from (x0, H0) to (x1, H1), instead of the usual (x0, y0) to (x1, y1).&#xD;&#xA;&#xD;&#xA;If the range of y values along the line is greater than the range of x values along the line then Bresenham's algorithm will step along integer y values instead of x values. The algorithm can still be applied in exactly the same way, just using (y0, H0) to (y1, H1).&#xD;&#xA;&#xD;&#xA;You can also combine all 4 calculations into a single loop, keeping track of a parameter each for determining y value, H value, S value and B value.&#xD;&#xA;&#xD;&#xA;The only difference from plotting a line on the screen (using x and y) is that not every value of H, S, and B needs to be taken. If the x range is greater than the y range, the algorithm steps through each of the x values checking whether to increment y. If the y range is greater then it instead steps through the values of y checking whether to increment x. However, if the range of H is greater than the range of x, it makes no sense to step through H values, as many of them will correspond to the same x value, wasting calculations. If the range of H is smaller than the range of x then the algorithm can proceed as usual. If the range of H is often going to be larger than the range of x then it is worth considering a different approach. Similarly for S and B.&#xD;&#xA;&#xD;&#xA;# Fitting the colour space to your line&#xD;&#xA;&#xD;&#xA;One way to eliminate this problem is to tailor your colour space to the x (or y if greater) range required for this specific line. Since your input colours and final output colours are in RGB, you are not constrained to a particular range for the HSB colours. You are free to convert from 256 levels of R, G, and B to 1000 levels of H, S, and B (or 1000000, or whatever you choose). If you choose to use a colour space where the range of H values used is the same integer as the range of x values used, then you won't even need to use a line drawing algorithm for the colours. Simply store the required values for converting back to RGB, and each of the H, S, and B values will be x plus a constant.&#xD;&#xA;&#xD;&#xA;This will require modifying your conversion function, but this will probably be necessary anyway, as it currently uses radians, which are not going to help with keeping things integer.&#xD;&#xA;&#xD;&#xA;# More accurate colour spaces&#xD;&#xA;&#xD;&#xA;Note that using a colour space like HSB will not give gradients which look as even as if using a more perceptually uniform color space such as [Lab]. However, since such spaces require calculating roots and you are looking to keep to integer arithmetic as much as possible, I'm assuming you are happy with HSB. If you did want to use something like Lab, you could still potentially keep to integers by using look up tables.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [HSB]: https://en.wikipedia.org/wiki/HSL_and_HSV &quot;Hue and saturation based colour spaces&quot;&#xD;&#xA;&#xD;&#xA;  [integer based version of Bresenham's algorithm]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm &quot;Description of the algorithm, including an integer based version&quot;&#xD;&#xA;&#xD;&#xA;  [Lab]: https://en.wikipedia.org/wiki/Lab_color_space &quot;CIELAB colour space&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6164" PostHistoryTypeId="5" PostId="2543" RevisionGUID="8533bda1-74d2-4bd2-829b-94cd813e22ae" CreationDate="2016-06-01T00:07:41.430" UserId="231" Comment="Extra thoughts" Text="*Yes, it is possible to use only integer calculations. I will describe how, but bear in mind that the difference in speed between integer arithmetic and floating point arithmetic is not as great as it was historically. If you want your code to run faster, it is best to profile and identify which parts of the code are taking up most time, before considering whether to convert a particular aspect to use integers.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# A straight line through colour space&#xD;&#xA;&#xD;&#xA;Looking at the code, it appears you first convert from RGB to [HSB] then create a linear gradient, and convert it back to RGB.&#xD;&#xA;&#xD;&#xA;A linear gradient is a straight line through the colour space, so you can use an integer based straight line algorithm to generate it without the need for floating point arithmetic. For example, the [integer based version of Bresenham's algorithm].&#xD;&#xA;&#xD;&#xA;H, S, and B are being treated independently, so you can calculate each one separately. For example, the H component can be calculated by treating the line as a straight line from (x0, H0) to (x1, H1), instead of the usual (x0, y0) to (x1, y1).&#xD;&#xA;&#xD;&#xA;If the range of y values along the line is greater than the range of x values along the line then Bresenham's algorithm will step along integer y values instead of x values. The algorithm can still be applied in exactly the same way, just using (y0, H0) to (y1, H1).&#xD;&#xA;&#xD;&#xA;You can also combine all 4 calculations into a single loop, keeping track of a parameter each for determining y value, H value, S value and B value.&#xD;&#xA;&#xD;&#xA;The only difference from plotting a line on the screen (using x and y) is that not every value of H, S, and B needs to be taken. If the x range is greater than the y range, the algorithm steps through each of the x values checking whether to increment y. If the y range is greater then it instead steps through the values of y checking whether to increment x. However, if the range of H is greater than the range of x, it makes no sense to step through H values, as many of them will correspond to the same x value, wasting calculations. If the range of H is smaller than the range of x then the algorithm can proceed as usual. If the range of H is often going to be larger than the range of x then it is worth considering a different approach. Similarly for S and B.&#xD;&#xA;&#xD;&#xA;# Fitting the colour space to your line&#xD;&#xA;&#xD;&#xA;One way to eliminate this problem is to tailor your colour space to the x (or y if greater) range required for this specific line. Since your input colours and final output colours are in RGB, you are not constrained to a particular range for the HSB colours. You are free to convert from 256 levels of R, G, and B to 1000 levels of H, S, and B (or 1000000, or whatever you choose). If you choose to use a colour space where the range of H values used is the same integer as the range of x values used, then you won't even need to use a line drawing algorithm for the colours. Simply store the required values for converting back to RGB, and each of the H, S, and B values will be x plus a constant.&#xD;&#xA;&#xD;&#xA;This will require modifying your conversion function, but this will probably be necessary anyway, as it currently uses radians, which are not going to help with keeping things integer.&#xD;&#xA;&#xD;&#xA;# More accurate colour spaces&#xD;&#xA;&#xD;&#xA;Note that using a colour space like HSB will not give gradients which look as even as if using a more perceptually uniform color space such as [Lab]. However, since such spaces require calculating roots and you are looking to keep to integer arithmetic as much as possible, I'm assuming you are happy with HSB. If you did want to use something like Lab, you could still potentially keep to integers by using look up tables.&#xD;&#xA;&#xD;&#xA;# What inputs does this need to work for?&#xD;&#xA;&#xD;&#xA;You also mention having to make decisions in the code which also takes up time. I would question how much difference this makes since the decisions are outside the loops and therefore only performed once. If you really want to eliminate them, ask yourself which inputs the code needs to work for.&#xD;&#xA;&#xD;&#xA;Currently the code checks the start and end values of the hue and decides whether to change the hue clockwise or anticlockwise. If you eliminate this check the code will still work, but it may not always give the colour direction the user intended. Deciding this automatically also may not give the direction the user intended (since different users have different expectations, and the requirement may change from one use to the next). You could simply take the direction as an additional parameter, which would avoid having to make the decision.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Code review&#xD;&#xA;&#xD;&#xA;### Meaningful variable names&#xD;&#xA;&#xD;&#xA;The use of &quot;hue&quot; in the naming of variables that store all three of hue, saturation and brightness makes the code less intuitive to read, potentially causing the reader to wonder whether saturation and brightness have been overlooked. It also makes the code difficult to reason about, since `startHueInRadians[0]` is a hue, while `startHueInRadians[1]` is a saturation, which is not only not a hue, but also presumably not in radians.&#xD;&#xA;&#xD;&#xA;In addition to making the code more accessible to others, you may also find it easier to work with it yourself if the naming is consistent, especially if you look back at the code after a few months.&#xD;&#xA;&#xD;&#xA;### A potential bug&#xD;&#xA;&#xD;&#xA;If one end of the colour gradient is at hue zero (red), the code checks whether the other end is greater than or equal to two thirds of the way around the hue circle. This corresponds to blue. If it is less than blue, then the gradient proceeds from zero upwards (anticlockwise), otherwise it proceeds from 2 pi downwards (clockwise). This means that a gradient from red to a colour with hue just above blue will go from red to magenta to blue. A gradient from red to a colour with hue just below blue will go from red to yellow to green to cyan to blue, which may not be what is expected. Intuitively, I would expect the cut off to be half way around the circle rather than two thirds, so that the gradient always includes the fewest colours (taking the shorter, more direct route).&#xD;&#xA;&#xD;&#xA;If you did intend to have this asymmetry, note that choosing a similar red with hue just above or just below zero will override this behaviour, forcing the long route or the short route respectively.&#xD;&#xA;&#xD;&#xA;If you want the gradient to consistently take the shorter route, then the code will need to check which route to take for all values, not just zero. For example, currently choosing the start hue just above zero and the finish hue just below zero will give start and finish colours that both look red, but the gradient will pass through red, yellow, green, cyan, blue, magenta and back to red, rather than just fading subtly from one hue of red to another.&#xD;&#xA;&#xD;&#xA;  [HSB]: https://en.wikipedia.org/wiki/HSL_and_HSV &quot;Hue and saturation based colour spaces&quot;&#xD;&#xA;&#xD;&#xA;  [integer based version of Bresenham's algorithm]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm &quot;Description of the algorithm, including an integer based version&quot;&#xD;&#xA;&#xD;&#xA;  [Lab]: https://en.wikipedia.org/wiki/Lab_color_space &quot;CIELAB colour space&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6166" PostHistoryTypeId="33" PostId="2516" RevisionGUID="9fd0bdf7-4b6a-4553-8b4c-6b28ed61b11b" CreationDate="2016-06-01T06:40:39.753" UserId="537" Comment="16" />
  <row Id="6167" PostHistoryTypeId="5" PostId="2540" RevisionGUID="9a4338ee-0eb7-4e30-a2bd-e112bd770e19" CreationDate="2016-06-01T06:51:53.277" UserId="3123" Comment="added 4 characters in body" Text="Is there any difference between registers types in hlsl?&#xD;&#xA;&#xD;&#xA;For example when using register `t0` for `UAV` will it be somehow precache like textures?&#xD;&#xA;&#xD;&#xA;According to microsoft's presentation about resource in DX12 and hlsl 5.1 this registers mean nothing, but maybe they only mean that there isn't any real registers like on CPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6168" PostHistoryTypeId="10" PostId="2531" RevisionGUID="07b66661-c9c2-4361-a901-40eafb03a7ac" CreationDate="2016-06-01T09:28:43.650" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="6169" PostHistoryTypeId="5" PostId="2537" RevisionGUID="94d71901-2aed-45c4-b043-2aeffc85b53e" CreationDate="2016-06-01T09:34:21.397" UserId="209" Comment="Added an additional case." Text="(Promoting &quot;comment&quot; to an answer)&#xD;&#xA;	&#xD;&#xA;It looks to me that it's just finding monotonic runs of edges. Given a defined winding order (in this case anticlockwise), then you can identify {P6, P7, P8, P0} as a decreasing run, as is {P2, P3, P4}. Since the left most vertex, P8, is in (**the middle of) a decreasing run, the decreasing runs define left boundaries and, therefore, increasing runs are right boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**it just occurred to me that if the left most point is at the beginning/end of a monotonic run then a slightly more involved rule will need to be applied involving the edges entering/leaving that point." ContentLicense="CC BY-SA 3.0" />
  <row Id="6171" PostHistoryTypeId="2" PostId="2544" RevisionGUID="d92fd5f8-1a2b-4f25-ace6-214f2b603699" CreationDate="2016-06-01T17:18:50.150" UserId="2308" Text="I have a scene rendered entirely with objects with additive blend mode.  I have a value that is oscillating from 0, to 1.  When it is 1 the object is supposed to be invisible, 0 should be entirely visible.&#xD;&#xA;&#xD;&#xA;However I have noticed that something seems off about it, specifically it stays dark for too long.  It is not my oscillating function, I suspect it having something to do with light using a logarithmic scale.&#xD;&#xA;&#xD;&#xA;How would I convert my linear 0-&gt;1 value into a properly scaled value between 0-&gt;1" ContentLicense="CC BY-SA 3.0" />
  <row Id="6172" PostHistoryTypeId="1" PostId="2544" RevisionGUID="d92fd5f8-1a2b-4f25-ace6-214f2b603699" CreationDate="2016-06-01T17:18:50.150" UserId="2308" Text="Fading an object in add mode with correct color math" ContentLicense="CC BY-SA 3.0" />
  <row Id="6173" PostHistoryTypeId="3" PostId="2544" RevisionGUID="d92fd5f8-1a2b-4f25-ace6-214f2b603699" CreationDate="2016-06-01T17:18:50.150" UserId="2308" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6174" PostHistoryTypeId="5" PostId="2544" RevisionGUID="b0543a08-17ac-4e9a-a5d4-4177b0f52ca8" CreationDate="2016-06-01T17:24:43.120" UserId="2308" Comment="added 2089 characters in body" Text="I have a scene rendered entirely with objects with additive blend mode.  I have a value that is oscillating from 0, to 1.  When it is 1 the object is supposed to be invisible, 0 should be entirely visible.&#xD;&#xA;&#xD;&#xA;However I have noticed that something seems off about it, specifically it stays dark for too long.  It is not my oscillating function, I suspect it having something to do with light using a logarithmic scale.&#xD;&#xA;&#xD;&#xA;How would I convert my linear 0-&gt;1 value into a properly scaled value between 0-&gt;1&#xD;&#xA;&#xD;&#xA;Fragment:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D s_texture;&#xD;&#xA;    &#xD;&#xA;    varying vec2 v_texcoord;&#xD;&#xA;    varying float alpha;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 col = texture2D(s_texture, v_texcoord);&#xD;&#xA;        gl_FragColor = vec4( col.rgba  - alpha);&#xD;&#xA;        &#xD;&#xA;        if (col.a &lt; 0.001)&#xD;&#xA;        {&#xD;&#xA;            discard; //11.7-&gt;12.2&#xD;&#xA;        }&#xD;&#xA;        //gl_FragColor = vec4(0.4);&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Vertex:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec2 pos;&#xD;&#xA;    attribute vec2 tc;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 matrix;&#xD;&#xA;    uniform float time;&#xD;&#xA;    uniform float maxLeafs;&#xD;&#xA;    uniform vec2 position;&#xD;&#xA;    uniform float instance;&#xD;&#xA;    uniform vec2 anchorPoint;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    varying vec2 v_texcoord;&#xD;&#xA;    varying float alpha;&#xD;&#xA;    &#xD;&#xA;    vec4 finalTranslate(vec3 pos)&#xD;&#xA;    {&#xD;&#xA;        return vec4(pos + vec3(position, 0.0), 1.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 rotate(vec3 pos, float angle)&#xD;&#xA;    {&#xD;&#xA;        float s = sin(-angle);&#xD;&#xA;        float c = cos(-angle);&#xD;&#xA;        return vec3(c * pos.x - s * pos.y, s * pos.x + c * pos.y, 0.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 translate(vec2 pos)&#xD;&#xA;    {&#xD;&#xA;        return vec3(pos - anchorPoint, 0.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 scale(vec3 pos, float amm)&#xD;&#xA;    {&#xD;&#xA;        return pos * amm;&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        &#xD;&#xA;        float v = log((time * 0.9) + 0.1);&#xD;&#xA;        alpha = 0.0;&#xD;&#xA;        &#xD;&#xA;        float leafCoverage = (3.14149 * 2.0);&#xD;&#xA;        float goal = ((instance) / (maxLeafs + 1.0)) * leafCoverage;&#xD;&#xA;        float timeFactor = smoothstep(0.0, 1.0, time);&#xD;&#xA;        float calculation1 = goal * timeFactor;&#xD;&#xA;        float calculation2 = clamp(timeFactor * leafCoverage, 0.0, goal);&#xD;&#xA;        &#xD;&#xA;        float scaleFactor = clamp(smoothstep(0.0, 1.0, time * 1.2), 0.0, 1.0);&#xD;&#xA;        &#xD;&#xA;        gl_Position = matrix * finalTranslate(rotate( scale(translate(pos) ,scaleFactor) ,  calculation1));&#xD;&#xA;        v_texcoord = tc;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Right now I am just taking the oscillating float time and passing it in directly, but eventually I will put it on a function so it fades in, temporarily is extra bright, then goes to the source texture." ContentLicense="CC BY-SA 3.0" />
  <row Id="6175" PostHistoryTypeId="2" PostId="2545" RevisionGUID="6cef660a-ba29-4057-8fe2-c6f58a9435fe" CreationDate="2016-06-01T18:01:26.300" UserId="48" Text="You have to use the appropriate register type for the resource: `b` registers for constant buffers, `t` for textures, and `u` for UAVs. AFAIK, it is not possible to bind a UAV to a texture slot, or otherwise mismatch registers and resources.&#xD;&#xA;&#xD;&#xA;However, a resource can have multiple views, so it is possible to have a resource bound as a UAV in one shader and as a regular texture (SRV) in another, which enables all the usual GPU texture sampling features to be used in the latter case.&#xD;&#xA;&#xD;&#xA;The details of how the DirectX API concepts of slots, registers, and resources map to the actual hardware are vendor-specific. On one GPU they may literally represent registers of some kind, while on another they may represent a small chunk of metadata in memory somewhere, which describes the resource to the hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="6176" PostHistoryTypeId="5" PostId="2544" RevisionGUID="82dca98a-9c64-4307-a2ea-e37971b4c923" CreationDate="2016-06-01T18:55:46.843" UserId="2308" Comment="added 96 characters in body" Text="I have a scene rendered entirely with objects with additive blend mode.  I have a value that is oscillating from 0, to 1.  When it is 1 the object is supposed to be invisible, 0 should be entirely visible.&#xD;&#xA;&#xD;&#xA;However I have noticed that something seems off about it, specifically it stays dark for too long.  It is not my oscillating function, I suspect it having something to do with light using a logarithmic scale.&#xD;&#xA;&#xD;&#xA;How would I convert my linear 0-&gt;1 value into a properly scaled value between 0-&gt;1&#xD;&#xA;&#xD;&#xA;Fragment:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D s_texture;&#xD;&#xA;    &#xD;&#xA;    varying vec2 v_texcoord;&#xD;&#xA;    varying float alpha;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 col = texture2D(s_texture, v_texcoord);&#xD;&#xA;        gl_FragColor = vec4( col.rgba  - alpha);&#xD;&#xA;        &#xD;&#xA;        if (col.a &lt; 0.001)&#xD;&#xA;        {&#xD;&#xA;            discard; //11.7-&gt;12.2&#xD;&#xA;        }&#xD;&#xA;        //gl_FragColor = vec4(0.4);&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Vertex:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    attribute vec2 pos;&#xD;&#xA;    attribute vec2 tc;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 matrix;&#xD;&#xA;    uniform float time;&#xD;&#xA;    uniform float maxLeafs;&#xD;&#xA;    uniform vec2 position;&#xD;&#xA;    uniform float instance;&#xD;&#xA;    uniform vec2 anchorPoint;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    varying vec2 v_texcoord;&#xD;&#xA;    varying float alpha;&#xD;&#xA;    &#xD;&#xA;    vec4 finalTranslate(vec3 pos)&#xD;&#xA;    {&#xD;&#xA;        return vec4(pos + vec3(position, 0.0), 1.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 rotate(vec3 pos, float angle)&#xD;&#xA;    {&#xD;&#xA;        float s = sin(-angle);&#xD;&#xA;        float c = cos(-angle);&#xD;&#xA;        return vec3(c * pos.x - s * pos.y, s * pos.x + c * pos.y, 0.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 translate(vec2 pos)&#xD;&#xA;    {&#xD;&#xA;        return vec3(pos - anchorPoint, 0.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 scale(vec3 pos, float amm)&#xD;&#xA;    {&#xD;&#xA;        return pos * amm;&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        &#xD;&#xA;        float v = log((time * 0.9) + 0.1);&#xD;&#xA;        alpha = 0.0;&#xD;&#xA;        &#xD;&#xA;        float leafCoverage = (3.14149 * 2.0);&#xD;&#xA;        float goal = ((instance) / (maxLeafs + 1.0)) * leafCoverage;&#xD;&#xA;        float timeFactor = smoothstep(0.0, 1.0, time);&#xD;&#xA;        float calculation1 = goal * timeFactor;&#xD;&#xA;        float calculation2 = clamp(timeFactor * leafCoverage, 0.0, goal);&#xD;&#xA;        &#xD;&#xA;        float scaleFactor = clamp(smoothstep(0.0, 1.0, time * 1.2), 0.0, 1.0);&#xD;&#xA;        &#xD;&#xA;        gl_Position = matrix * finalTranslate(rotate( scale(translate(pos) ,scaleFactor) ,  calculation1));&#xD;&#xA;        v_texcoord = tc;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Right now I am just taking the oscillating float time and passing it in directly, but eventually I will put it on a function so it fades in, temporarily is extra bright, then goes to the source texture.&#xD;&#xA;&#xD;&#xA;Edit: I solved my problem, to my surprise the GLSL log function is in base e rather then 10." ContentLicense="CC BY-SA 3.0" />
  <row Id="6177" PostHistoryTypeId="2" PostId="2546" RevisionGUID="d8fcb41f-ecc8-4d1f-b2a0-39da5bbd010b" CreationDate="2016-06-02T01:03:53.487" UserId="2308" Text="Turns this was not an issue with the scale of the values passed in, just that the log function in glsl is base e.  The solution was merely to do log(stuff)/log(10) and that got the result of a base 10 log." ContentLicense="CC BY-SA 3.0" />
  <row Id="6178" PostHistoryTypeId="2" PostId="2547" RevisionGUID="ddf03e03-b7d1-467d-ab15-4a8c46d007d7" CreationDate="2016-06-02T01:07:38.570" UserId="2308" Text="So I am trying to make my shader efficient by lowing the amount of texture lookups. If I had a line of code with something like.&#xD;&#xA;&#xD;&#xA;    step(1.0, x) * texture2D(pic1, uv);&#xD;&#xA;&#xD;&#xA;Where x is a value that ranges from 0 to 2 based on the fragment position.  Would the GPU see when step evaluates to 0 and thus not ever calculate texture2D? Or would it still lookup the texture because the 0 is not constant?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6179" PostHistoryTypeId="1" PostId="2547" RevisionGUID="ddf03e03-b7d1-467d-ab15-4a8c46d007d7" CreationDate="2016-06-02T01:07:38.570" UserId="2308" Text="Short circuit when multiply by 0?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6180" PostHistoryTypeId="3" PostId="2547" RevisionGUID="ddf03e03-b7d1-467d-ab15-4a8c46d007d7" CreationDate="2016-06-02T01:07:38.570" UserId="2308" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6181" PostHistoryTypeId="4" PostId="2547" RevisionGUID="b08578e7-7b54-4605-b314-0b62e6d1e2f4" CreationDate="2016-06-02T01:29:54.797" UserId="2308" Comment="edited title" Text="GPU short circuit when multiply by 0?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6182" PostHistoryTypeId="5" PostId="2547" RevisionGUID="b08578e7-7b54-4605-b314-0b62e6d1e2f4" CreationDate="2016-06-02T01:29:54.797" UserId="2308" Comment="edited title" Text="So I am trying to make my shader efficient by lowing the amount of texture lookups. If I had a line of code with something like.&#xD;&#xA;&#xD;&#xA;    step(1.0, x) * texture2D(pic1, uv);&#xD;&#xA;&#xD;&#xA;Where x is a value that ranges from 0 to 2 based on the fragment position.  Would the GPU see when step evaluates to 0 and thus not ever calculate texture2D? Or would it still lookup the texture because the 0 is not constant?&#xD;&#xA;&#xD;&#xA;BTW I use the term &quot;short circuit&quot; because I have been told that is what happens when you have `false &amp;&amp; (bla)` the computer sees the false and ignores the right." ContentLicense="CC BY-SA 3.0" />
  <row Id="6183" PostHistoryTypeId="2" PostId="2548" RevisionGUID="1e150ba7-70ce-44e3-bf49-e80db569f955" CreationDate="2016-06-02T05:13:34.250" UserId="116" Text="I've been reading several sources in the web about transforming world-space points into camera-space ones.&#xD;&#xA;I am building my view-matrix from the following parameters&#xD;&#xA;    &#xD;&#xA;    1. Camera position&#xD;&#xA;    2. Point the camera is looking at&#xD;&#xA;    3. Up vector&#xD;&#xA;&#xD;&#xA;I perfectly understand the meaning of each of the parameters, however, there are still some doubts.&#xD;&#xA;&#xD;&#xA;1. How is the direction vector built? We have camera position and lookat position, is it camPos-lookatPos or lookatPos-camPos? In other words, does the direction vector aligns with (goes in the same direction of) the world +z-axis or is opposite to it? *Direction* is a bit confusing since it makes me think it goes the direction the camera lens is pointing to.&#xD;&#xA;2. What's the reasoning behind translating the camera to the origin? How does this simplifies math?&#xD;&#xA;&#xD;&#xA;My view matrix looks like follows&#xD;&#xA;&#xD;&#xA;$$V = \begin{matrix}&#xD;&#xA;  Rx &amp; Ry &amp; Rz &amp; 0 \\&#xD;&#xA;  Ux &amp; Uy &amp; Uz &amp; 0 \\&#xD;&#xA;  Fx &amp; Fy &amp; Fz &amp; 0 \\&#xD;&#xA;  -CamPosx &amp; -CamPosy &amp; -CamPosz &amp; 1&#xD;&#xA; \end{matrix}$$&#xD;&#xA;&#xD;&#xA;3. Will this V matrix convert from camera to world or from world to camera coordinates? How can I understand which direction it is going?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6184" PostHistoryTypeId="1" PostId="2548" RevisionGUID="1e150ba7-70ce-44e3-bf49-e80db569f955" CreationDate="2016-06-02T05:13:34.250" UserId="116" Text="Understanding view matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="6185" PostHistoryTypeId="3" PostId="2548" RevisionGUID="1e150ba7-70ce-44e3-bf49-e80db569f955" CreationDate="2016-06-02T05:13:34.250" UserId="116" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6186" PostHistoryTypeId="2" PostId="2549" RevisionGUID="47da7f3d-500e-4547-87a3-b876fe947fc2" CreationDate="2016-06-02T05:43:25.093" UserId="1614" Text="There is no relation between `direction`'s direction and the world axis. And that's fortunate otherwise it would mean your camera is not a free view, it's some kind of a axis bound camera, which has its usages but most likely nothing in your mind right now.&#xD;&#xA;&#xD;&#xA;The default camera matrix is looking at +z when everything is Identity, that's most surely where you got confused. Know that this is purely a convention, but sticking to a widely adopted convention allows for easy compatibility with libraries like glm.&#xD;&#xA;&#xD;&#xA;the direction vector goes outward, so its `normalize(lookat - campos)`. &#xD;&#xA;&#xD;&#xA;The view matrix can be constructed directly with TBN vectors in rows 0 1 2 :)  &#xD;&#xA;(that's your RUF)&#xD;&#xA;&#xD;&#xA;Point 2. There is no translating of the camera to the origin, that's just how you chose to view (pun) it. There is translation of world objects toward the origin. Because the rasterizer will work in device coordinates (NDC) which is not configurable, so having a roaming camera (that travels) makes it necessary to indicate its translation in world as part of the last row (row 3), and in reverse since it's not a world matrix representing the camera position, it's the matrix that will bring back points into the view space. (by the way, incidentally meaning the actual camera world matrix is the inverse of the view matrix).&#xD;&#xA;&#xD;&#xA;3. oh, that was the last phrase of pt 2." ContentLicense="CC BY-SA 3.0" />
  <row Id="6187" PostHistoryTypeId="2" PostId="2550" RevisionGUID="75787785-11c0-49e0-9bc6-cb3b42abb44f" CreationDate="2016-06-02T05:54:21.460" UserId="1614" Text="There is a difference between being able to determine value at compilation time and at runtime.&#xD;&#xA;&#xD;&#xA;`false &amp;&amp; bla`  &#xD;&#xA;Gets eliminated because of C/C++ lazy operand evaluation rule which is standardized with left to right order.  &#xD;&#xA;The compiler generates no code so the machine has no overhead.&#xD;&#xA;&#xD;&#xA;`step(1.0, x) * texture2D(pic1, uv);`&#xD;&#xA;&#xD;&#xA;That will depend if x is coming from a uniform value, in which case the drivers will compile an adjustment of the shader (and put it in a combinator cache). At some point before starting to render.  &#xD;&#xA;(this can cause hiccups in framerate when new uniform values are encountered that cause massive shader rebuild)&#xD;&#xA;&#xD;&#xA;Now, if `x` is **dependant**, which means it comes from a previous calculation that comes from varying values or system values, the compiler will cut your expression in 2 parts, the `lerp` calculus and the `sample` call.  &#xD;&#xA;It will move the sampling of the texture in the first instructions of the shader. (provided it's unconditional in the shader flow).  &#xD;&#xA;So you're basically screwed when it's 0, you'll pay the sampling anyway.&#xD;&#xA;&#xD;&#xA;In your case (0-2 wrt frag pos), I would recommend using `if (inrect(0,0,1,1))` because this is a low frequency &quot;step&quot; function, which means very good branch elimination in 3 quarters of the screen.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="6188" PostHistoryTypeId="2" PostId="2551" RevisionGUID="2d73d49f-4af4-49dc-b278-f976aac539c5" CreationDate="2016-06-02T08:25:26.957" UserId="361" Text="I am loading a texture in a WebGL fragment shader (GLSL version 1.00).&#xD;&#xA;&#xD;&#xA;This is my working code:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    uniform sampler2D u_texture;&#xD;&#xA;    varying float v_coord;&#xD;&#xA;&#xD;&#xA;    void main(void) {&#xD;&#xA;      float inv_coord;&#xD;&#xA;      gl_FragColor = texture2D(u_texture, vec2(v_coord, 0.5));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;`v_coord` holds the texture coordinates for each vertex. What I'm trying now, is to invert the texture coordinates. I thought about something like `abs(v_coord - 1)`. However, whenever I try to substract `- 1` from `v_coord`, my shader fails to compile.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    uniform sampler2D u_texture;&#xD;&#xA;    varying float v_coord;&#xD;&#xA;&#xD;&#xA;    void main(void) {&#xD;&#xA;      float inv_coord = v_coord - 1; // fails here&#xD;&#xA;      inv_coord = abs(inv_coord);&#xD;&#xA;      gl_FragColor = texture2D(u_texture, vec2(inv_coord, 0.5));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Why does substracting minus one in fragment shader fail for a float data type? How to invert the texture coordinate value correctly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6189" PostHistoryTypeId="1" PostId="2551" RevisionGUID="2d73d49f-4af4-49dc-b278-f976aac539c5" CreationDate="2016-06-02T08:25:26.957" UserId="361" Text="Why does substracting -1 in shader fail for a float data type?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6190" PostHistoryTypeId="3" PostId="2551" RevisionGUID="2d73d49f-4af4-49dc-b278-f976aac539c5" CreationDate="2016-06-02T08:25:26.957" UserId="361" Text="|texture|glsl|mathematics|webgl|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6191" PostHistoryTypeId="2" PostId="2552" RevisionGUID="b43f518b-b439-4075-ab18-db17b39ad9b8" CreationDate="2016-06-02T08:43:46.127" UserId="137" Text="Without seeing the error message I can't be sure but I think it's failing on the 1 being int instead of a float. &#xD;&#xA;&#xD;&#xA;    float inv_coord = v_coord - 1.0;&#xD;&#xA;&#xD;&#xA;There is a simpler method, you can do `1.0 - v_coord` and do away with the abs." ContentLicense="CC BY-SA 3.0" />
  <row Id="6195" PostHistoryTypeId="2" PostId="2554" RevisionGUID="19dfff28-3841-40de-adda-83500d9fd85a" CreationDate="2016-06-02T13:29:26.403" UserId="2237" Text="I'm developing a simple educational project to study OpenGL ES.&#xD;&#xA;I'm try to render some simple OBJ models using Blinn-Phong.&#xD;&#xA;The first version of the of my implementation calculate all the lighting equation in this way:&#xD;&#xA;&#xD;&#xA;        #version 300 es&#xD;&#xA;    &#xD;&#xA;    struct material {&#xD;&#xA;        vec4 ka;&#xD;&#xA;        vec4 kd;&#xD;&#xA;        vec4 ks;&#xD;&#xA;        float sh;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct pointLight {&#xD;&#xA;        vec3 position;&#xD;&#xA;        vec4 color;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    uniform mat4 mvMatrix;&#xD;&#xA;    uniform mat4 mvpMatrix;&#xD;&#xA;    uniform mat4 normalMatrix;&#xD;&#xA;    uniform pointLight light;&#xD;&#xA;    uniform material surfaceMaterial;&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 inputPosition;&#xD;&#xA;    layout(location = 1) in vec3 inputNormal;&#xD;&#xA;    &#xD;&#xA;    out vec4 v_color;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        &#xD;&#xA;        //Convert vertex and normal to camera space.&#xD;&#xA;        vec3 normal = vec3(normalize(normalMatrix * vec4(inputNormal, 0.0)));&#xD;&#xA;        vec4 vertexPositionHomogeneous = mvMatrix * vec4(inputPosition, 1.0);&#xD;&#xA;        vec3 vertexPosition = vec3(vertexPositionHomogeneous) / vertexPositionHomogeneous.w;&#xD;&#xA;        &#xD;&#xA;        //Calculate light direction and view direction.&#xD;&#xA;        vec3 lightDirection = normalize(light.position - vertexPosition);&#xD;&#xA;        vec3 viewPosition = vec3(0.0, 0.0, 1.0);&#xD;&#xA;        vec3 viewDirection = normalize(-1.0 *  vertexPosition);&#xD;&#xA;        &#xD;&#xA;        //Cosine theta diffuse lambertian component.&#xD;&#xA;        float cosTheta = max(0.0, dot(normal, normalize(lightDirection)));&#xD;&#xA;        &#xD;&#xA;        //H vector for specular component.&#xD;&#xA;        vec3 h = normalize(lightDirection + viewDirection);&#xD;&#xA;        &#xD;&#xA;        vec4 ambient = surfaceMaterial.ka * light.color;&#xD;&#xA;        vec4 diffuse = surfaceMaterial.kd * light.color * cosTheta;&#xD;&#xA;        vec4 specular = surfaceMaterial.ks * light.color * pow(max(0.0, dot(h, normal)), surfaceMaterial.sh);&#xD;&#xA;        &#xD;&#xA;        //Output position and color for fragment shader.&#xD;&#xA;        v_color = specular;&#xD;&#xA;        gl_Position = mvpMatrix * vec4(inputPosition, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This version doesn't work. This is what I obtain:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I move the calculation to the fragment shader it works. The is the result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fMfeG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZiDxG.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This image is obtained using a fragment shader that contains the same lighting calculation that I used in the vertex shader above. So my question is: why the vertex shader only version is not working? Am I missing something about how vertex and fragment shaders works? " ContentLicense="CC BY-SA 3.0" />
  <row Id="6196" PostHistoryTypeId="1" PostId="2554" RevisionGUID="19dfff28-3841-40de-adda-83500d9fd85a" CreationDate="2016-06-02T13:29:26.403" UserId="2237" Text="OpenGL ES vertex/fragment shaders - Blinn phong" ContentLicense="CC BY-SA 3.0" />
  <row Id="6197" PostHistoryTypeId="3" PostId="2554" RevisionGUID="19dfff28-3841-40de-adda-83500d9fd85a" CreationDate="2016-06-02T13:29:26.403" UserId="2237" Text="|opengl|lighting|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6198" PostHistoryTypeId="2" PostId="2555" RevisionGUID="682d8463-5c6c-42d4-ae33-6a4026c947a6" CreationDate="2016-06-02T14:07:28.077" UserId="3472" Text="As a CG assignment with OpenGL and SDL, I want to create a clone of the videogame WipeOut instead of the classical car racing game. Examples of motion in 2D have been given and are rather simple to understand; the complexity in 3D is that the road is not planar - when the vehicle approaches a cliff or a vertical loop, it should be translated on the y-axis and rotated to be mantained parallel to the road. I have no idea on how to get and update such informations (translation and rotation for the road). I thought about creating a bezier curve with informations about its derivative (overlapping the road) and keeping track of the movements of the vehicle with respect to the curve, but I don't know if it's the right (simplest) way of doing this. By the way, being able to track the position of the vehicle relative to the curve would also solve some collision problems by limiting its distance.&#xD;&#xA;&#xD;&#xA;Of course, this feature is not mandatory - I could just keep a planar road - but I'd like to understand how to do it. Suggestions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6199" PostHistoryTypeId="1" PostId="2555" RevisionGUID="682d8463-5c6c-42d4-ae33-6a4026c947a6" CreationDate="2016-06-02T14:07:28.077" UserId="3472" Text="&quot;Anchor&quot; vehicle to 3D path with OpenGL / SDL" ContentLicense="CC BY-SA 3.0" />
  <row Id="6200" PostHistoryTypeId="3" PostId="2555" RevisionGUID="682d8463-5c6c-42d4-ae33-6a4026c947a6" CreationDate="2016-06-02T14:07:28.077" UserId="3472" Text="|opengl|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6201" PostHistoryTypeId="5" PostId="2542" RevisionGUID="9ded15e5-cea1-494a-b416-312097ec81c4" CreationDate="2016-06-03T00:20:14.557" UserId="3410" Comment="Addressed one of the comments that asked for further detailing" Text="I have a post-effect camera-shader in which I want to implement a simple spatial partitioning of the screen between two passes of the fragment shader.&#xD;&#xA;&#xD;&#xA;The first pass should divide the screen into cells of size = 30x30 pixels, and then for each green fragment, store **somehow** which of those screen cells the coordinate of such green fragment  is located. That information should then be available for the second pass to work with.&#xD;&#xA;&#xD;&#xA;Well, merely dividing the screen into cells is trivial, considering that it's easy to calculate the row and column indexes of such screen-grid:&#xD;&#xA;&#xD;&#xA;	static float2 _Pixels = float2(_ScreenParams.x, _ScreenParams.y);&#xD;&#xA;    float2 griduv = round(input.uv * _Pixels) * _invPixels; //pixel-screen space coordinate of the current fragment being evaluated&#xD;&#xA;    half cellsize = 30.0f;&#xD;&#xA;&#xD;&#xA;    float gridX = griduv .x/cellsize;&#xD;&#xA;    float gridY = griduv .y/cellsize;&#xD;&#xA;&#xD;&#xA;    int gridrow = gridX  - frac(gridX);&#xD;&#xA;    int gridcol = gridY  - frac(gridY);&#xD;&#xA;&#xD;&#xA;If that was not a shader task but rather a standard CPU code, it would be just a matter of saving the `i`th `griduv` into an array-of-list or array-of-array (e.g. `float2[][] grid = new float2[gridrow*gridcol][maxNfloat2]`) at position `grid[gridrow*gridcol+gridrow][i]`.&#xD;&#xA;&#xD;&#xA;However, in a shader, for most hardwares and most DirectX and OpenGL versions, it seems to me that 1) we can't have multi-dimensional arrays, 2) we can't have resizable containers like lists and 3) we also can't pass variables and containers from one pass to the next.&#xD;&#xA;&#xD;&#xA;As one can easily see, this situation is also **not** well suited for using a simple texture to store values from one pass to the next, since I would need multiple `float2` into each grid cell and I can have quite many floats to store.&#xD;&#xA;&#xD;&#xA;So, how could I proceed in such a situation? In other words, how could I store the pixel-screen coordinates of given fragments in a spatial-partitioning of the screen (in this case a simple fixed size grid of the screen), to be passed from one shader pass to the next?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6202" PostHistoryTypeId="6" PostId="2555" RevisionGUID="1d931a87-6909-4d86-9ac2-ed238cc56505" CreationDate="2016-06-03T04:07:00.677" UserId="38" Comment="edited tags" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6203" PostHistoryTypeId="2" PostId="2556" RevisionGUID="e1706b9a-8c66-4600-ba4e-f9de076310c1" CreationDate="2016-06-03T06:48:37.310" UserId="3477" Text="So I know that I'm basically asking to identify the main problem to be solved in creating realistic 3d Graphics, but as someone without much technical experience in the field, I'm curious that if these problems can be identified, what the issue is with implementing them programmatically.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The picture below from Hitman is what I would call &quot;ultra-realistic&quot;. But, it still definitely looks like a 3d model. If you were to put a photograph of the same scene with a real actor and background, there would probably be some differences obvious enough to be able to point out which is which.&#xD;&#xA;&#xD;&#xA;Why is that? &lt; 100% accurate subsurface scattering? Is the lighting ever-so-slightly off? etc.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;PS, sorry for tag choices. I am not familiar enough with this SE to know what to choose. Please edit better ones in, if you know any.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UH2r1.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="6204" PostHistoryTypeId="1" PostId="2556" RevisionGUID="e1706b9a-8c66-4600-ba4e-f9de076310c1" CreationDate="2016-06-03T06:48:37.310" UserId="3477" Text="What physical properties are “lacking” to keep this 3D scene from looking like a real photograph?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6205" PostHistoryTypeId="3" PostId="2556" RevisionGUID="e1706b9a-8c66-4600-ba4e-f9de076310c1" CreationDate="2016-06-03T06:48:37.310" UserId="3477" Text="|raytracing|rendering|physics|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6206" PostHistoryTypeId="2" PostId="2557" RevisionGUID="4892e042-290a-415a-93f5-8ae0319a1fdb" CreationDate="2016-06-03T10:02:48.540" UserId="38" Text="Hard to say because we can not see the code. Subsurface scattering might be part of that equation. &#xD;&#xA;&#xD;&#xA;I would just point out that human brains are extremely specialized in facial recognition. It has been postulated that the brain has a inbuilt defence mechanism to detect alien impostors. You are right in middle of what is known as [uncanny valley](https://en.m.wikipedia.org/wiki/Uncanny_valley) nothing sort of near perfect seems to get it right, it seems&#xD;&#xA;&#xD;&#xA;It is also worth noting that we do not really know what it is that is lacking that puts you in uncanny valley. So it seems to me we do not conclusively know what, if anything, is missing. So the entire thing might be because we are neglecting something important but as of yet unknown." ContentLicense="CC BY-SA 3.0" />
  <row Id="6207" PostHistoryTypeId="5" PostId="2557" RevisionGUID="9135c536-b8d8-485b-92b9-9559d32871c0" CreationDate="2016-06-03T11:43:21.333" UserId="38" Comment="added 17 characters in body" Text="Hard to say because we can not see the code. Subsurface scattering might be part of that equation. &#xD;&#xA;&#xD;&#xA;I would just point out that human brains are extremely specialized in facial recognition. It has been postulated that the brain has a inbuilt defence mechanism to detect alien impostors/anomalous people. You are right in middle of what is known as [uncanny valley](https://en.m.wikipedia.org/wiki/Uncanny_valley) nothing sort of near perfect seems to get it right, it seems&#xD;&#xA;&#xD;&#xA;It is also worth noting that we do not really know what it is that is lacking that puts you in uncanny valley. So it seems to me we do not conclusively know what, if anything, is missing. So the entire thing might be because we are neglecting something important but as of yet unknown." ContentLicense="CC BY-SA 3.0" />
  <row Id="6208" PostHistoryTypeId="6" PostId="2556" RevisionGUID="3f66846a-3a29-4ab8-9c28-d6923715aede" CreationDate="2016-06-03T16:08:51.047" UserId="2479" Comment="Improved tags: raytracing removed, uncanny-valley added" Text="|rendering|physics|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6209" PostHistoryTypeId="24" PostId="2556" RevisionGUID="3f66846a-3a29-4ab8-9c28-d6923715aede" CreationDate="2016-06-03T16:08:51.047" Comment="Proposed by 2479 approved by 310, 209 edit id of 140" ContentLicense="CC BY-SA 3.0" />
  <row Id="6210" PostHistoryTypeId="2" PostId="2558" RevisionGUID="c3b563b0-eec3-4d39-87bb-dc3ea4565502" CreationDate="2016-06-03T17:30:58.390" UserId="273" Text="I think the most common way to have a the &quot;up and down&quot; movement of a vehicle is to actually build a physics simulation.&#xD;&#xA;It does not have to be a very sophisticated one and how much realism you want is up to you.&#xD;&#xA;&#xD;&#xA;But just in each frame update the velocity of the car in downward direction (gravity) until it hits the road. Then if the road has an upward slope it will also push the car up (by colliding with the car).&#xD;&#xA;&#xD;&#xA;Now you have a new problem and that is the problem that the car remains parallel to the ground-plane. And the physical calculation behind this is a bit more complex.&#xD;&#xA;&#xD;&#xA;When detecting if your car hit the ground you would have to detect the exact position of the hit (which part of the car hit the floor?). Then using the gravity, mass and some material properties (all of which you could just set globally and assume as easy values for simplicity) you can calculate how the reaction force to the collision will be. And you know that the force will be exerted on the collision point.&#xD;&#xA;Now when you have the center of mass of the car, and the collision point, and the force created by the ground-collision, you can calculate how to rotate the car.&#xD;&#xA;&#xD;&#xA;This is only a very rough sketch of how I learned to handle such things in a &quot;real&quot; way. I hope this was not too confusing, if you have additional questions I can rework the answer later." ContentLicense="CC BY-SA 3.0" />
  <row Id="6211" PostHistoryTypeId="2" PostId="2559" RevisionGUID="0b1822d8-7fa2-4d86-978b-9c01a8b29024" CreationDate="2016-06-03T17:38:05.737" UserId="273" Text="Though I have never used them myself OpenGL in modern versions gives you something called &quot;Shader Storage Buffer Object&quot; These are buffers that you can fill with your data. They are guaranteed to be able to hold up to 16 MB of data and most implementations seem to have no problem with them taking up the whole GRAM.&#xD;&#xA;&#xD;&#xA;This feature is core since OpenGL version 4.3.&#xD;&#xA;The SSBOs are basically just a buffer that you can put any datatype in (a struct for example) and a huge amount of them.&#xD;&#xA;&#xD;&#xA;I cannot really tell you how to use them, but I think with the name you will find some resource in the web." ContentLicense="CC BY-SA 3.0" />
  <row Id="6212" PostHistoryTypeId="2" PostId="2560" RevisionGUID="65c8e550-d5aa-4f25-807c-331f8724c272" CreationDate="2016-06-03T18:01:14.717" UserId="231" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="6213" PostHistoryTypeId="2" PostId="2561" RevisionGUID="22140563-ba1d-4293-a067-987a7dfd8acf" CreationDate="2016-06-03T18:01:14.717" UserId="231" Text="For questions about the path tracing Monte Carlo algorithm for physically accurate global illumination, or its variants." ContentLicense="CC BY-SA 3.0" />
  <row Id="6214" PostHistoryTypeId="2" PostId="2562" RevisionGUID="6fd84871-74c9-4829-9e97-f3b71c06cb6b" CreationDate="2016-06-03T21:32:35.773" UserId="2828" Text="I think you identified the problem yourself in your question :&#xD;&#xA;&#xD;&#xA;&gt;  it still definitely looks like a 3d model&#xD;&#xA;&#xD;&#xA;It's obviously hard to tell and subjective, but while many things are off in this picture, the expression and the proportions of the character model are what I find most unrealistic. It is to the appreciation of the art director, but most of the time, realism is not the main drive in shaping and animating character models. Here we have all the clichés of bland character design, and a significant lack of effort put in the expressiveness of the character. It feels 100% designed as a game persona. As such, no matter how close to reality all visual phenomenons are transcribed, my brain just won't accept it, as no-one looks like that in real life." ContentLicense="CC BY-SA 3.0" />
  <row Id="6216" PostHistoryTypeId="2" PostId="2563" RevisionGUID="d9705061-e01a-4686-aded-22f1e062071b" CreationDate="2016-06-04T00:56:18.453" UserId="310" Text="I would like to add full monte-carlo volumetric scattering to my path tracer, but I'm having a hard time researching how to do it. Let me explain what I would like to do:&#xD;&#xA;[![Monte Carlo Volumetric Scattering][1]][1]&#xD;&#xA;A ray enters a material, and we apply the BTDF, then after some distance, a volumetric scattering event happens, after which (in the isotropic case), the ray scatters in any direction in the sphere. This repeats until the ray exits the material with another BTDF. &#xD;&#xA;&#xD;&#xA;My questions are as follows:&#xD;&#xA;&#xD;&#xA; 1. How do I choose the distance between scatter events? Intuition tells me there should be some kind of scatter pdf, which gives the probability to scatter after a certain distance? &#xD;&#xA;  - Would this be correct?&#xD;&#xA;  - Would the pdf be a linear function for isotropic materials?&#xD;&#xA;  - Does this function have a name or something I can Google?&#xD;&#xA; 2. Would Beer-Lambert still apply between scatter events?&#xD;&#xA;  - I would think not. Since Beer-Lambert is a simplification of actual scattering calculations.&#xD;&#xA;  - Then again, perhaps Beer-Lambert is a calculation at the micro scale, and path tracing is on a macro scale.&#xD;&#xA; 3. What is the volumetric equivalent to a BSDF? It looks like I can use a phase function such as Henyey-Greenstein to determine the new direction, but what do I use for attenuation?&#xD;&#xA; 4. Lastly, what are some better Google phrases for Monte-Carlo volumetric scattering? &#xD;&#xA;  - Searching volumetric scattering, or SSS, ends up giving papers, methods, and blog posts about the simplfications of full Monte-Carlo simulation (Dipole, in-scattering, out-scattering, diffusion, etc.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tOp55.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="6217" PostHistoryTypeId="1" PostId="2563" RevisionGUID="d9705061-e01a-4686-aded-22f1e062071b" CreationDate="2016-06-04T00:56:18.453" UserId="310" Text="Help / Resources for Full Monte-Carlo Volumetric Scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="6218" PostHistoryTypeId="3" PostId="2563" RevisionGUID="d9705061-e01a-4686-aded-22f1e062071b" CreationDate="2016-06-04T00:56:18.453" UserId="310" Text="|pathtracing|monte-carlo|volumetric-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6219" PostHistoryTypeId="2" PostId="2564" RevisionGUID="82d5225b-4720-4c79-8d41-e72c6ff28576" CreationDate="2016-06-04T01:00:33.120" UserId="3003" Text="I see several things that are off in addition to what others have said. He doesn't appear to be breathing. He's in a very cold place (it appears to be snowing), yet there's no breath in front of his nose or mouth. It's snowing, but none of the snow is in front of him. It's all behind him, or on his clothes, but not falling around him.&#xD;&#xA;&#xD;&#xA;I feel like our brains pick up on the subtler things, too. Like the fact that his eyebrows are just a flat texture mapped onto the geometry of his face. They're not separate hairs. Even though you couldn't resolve them very well at this distance, I think we still notice it a little. There are no specular highlights on them, either.&#xD;&#xA;&#xD;&#xA;And to me his skin looks rubbery, not alive. I know that in the cold my skin gets a little blotchy - some parts get more pinkish than others. His coloring is very even." ContentLicense="CC BY-SA 3.0" />
  <row Id="6223" PostHistoryTypeId="2" PostId="2566" RevisionGUID="8ba5dea6-f20d-41dc-b15b-66833ba32096" CreationDate="2016-06-04T11:55:24.110" UserId="1810" Text="It speed does not matter, I suggest to use a truncated sinc or a Lanczos isotropic kernel: to compute a target pixel, you back-rotate the filter and  convolve it with the image. Since it is isotropic, it is separable and you can even use a square filter parallel to the axis of the source image." ContentLicense="CC BY-SA 3.0" />
  <row Id="6225" PostHistoryTypeId="2" PostId="2567" RevisionGUID="6daa6cff-3901-4ef3-af78-42c57186a451" CreationDate="2016-06-04T17:54:49.740" UserId="3484" Text="I know that OpenGL uses a projection matrix to project the view frustum directly into the canoical volume [-1, 1]^3. But how would I project the frustum into an orthographic cuboid, which would then get projected by an orthographic matrix into the canonical volume? This is purely about the theory behind the workings, I don't intend to implement it. I hope somebody can help." ContentLicense="CC BY-SA 3.0" />
  <row Id="6226" PostHistoryTypeId="1" PostId="2567" RevisionGUID="6daa6cff-3901-4ef3-af78-42c57186a451" CreationDate="2016-06-04T17:54:49.740" UserId="3484" Text="How to project a view frustum in an orthographic cuboid?" ContentLicense="CC BY-SA 3.0" />
  <row Id="6227" PostHistoryTypeId="3" PostId="2567" RevisionGUID="6daa6cff-3901-4ef3-af78-42c57186a451" CreationDate="2016-06-04T17:54:49.740" UserId="3484" Text="|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="6229" PostHistoryTypeId="5" PostId="2516" RevisionGUID="80862f14-375e-4174-84cd-c40f1beb3ad7" CreationDate="2016-06-04T21:39:13.460" UserId="537" Comment="added 1398 characters in body" Text="I am writing a software and I need to represent a graph in a orthogonal manner from topological data (vector of edges,vertices and their connectivity data)&#xD;&#xA;&#xD;&#xA;**Graphs** consist of a set of **vertices** and a set of **edges**, each connecting two vertices.A vertex may have any number of connected edges so it makes the problem a lot more complicated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have read some articles and its looks like that the **Kandinsky model** is the post popular one. However I just don't know the algorithm, any other solution (algorithm) that solve the problem is also very welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Added after edit**&#xD;&#xA;&#xD;&#xA;The following picture shows a real world example for an electricity network which should be considered as raw data, in order to create a graph from this network, some preliminary tasks must be done. &#xD;&#xA;&#xD;&#xA;Input Data:&#xD;&#xA;&#xD;&#xA;[![Input Data][1]][1]&#xD;&#xA;&#xD;&#xA;The result I am looking for is something like below, &#xD;&#xA;there are some characteristics if you take a look much closer : &#xD;&#xA;&#xD;&#xA;The Red Polygon in the middle of the above picture(input data) represents an electricity substation which is a node itself and can be connected to more than 4 edges.&#xD;&#xA;There are more red polygons but only one can be fit into the above picture however as you may see, the following picture could cover much more than a red polygon that means it can map a bigger area, so the following picture is much more denser.&#xD;&#xA;&#xD;&#xA;In Schematics diagrams, red polygons (Substations) usually maintain their position against each other relatively so if we manage to see beyond the extents of the above map by zooming out for example, we should almost see a triangle that is obviously can be seen at the below while having the left one at the left, the down one at the down ..... (this is not a rule, but I thought it could be a head start for desired algorithm)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Orthogonal Diagram:&#xD;&#xA;&#xD;&#xA;[![Orthogonal Schematic][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pJofq.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5gffC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="6231" PostHistoryTypeId="2" PostId="2568" RevisionGUID="dc2b57d8-b7b9-41e0-9d51-324f77b87734" CreationDate="2016-06-05T00:44:00.993" UserId="3487" Text="Few things, but usually this is what it takes to make the difference:&#xA;&#xA;1- the material reflection at his head, he is bald, yet the diffuse texture shows color difference where the hair is, this means he has a shaved heaf, not a naturl bald, this should translate in reflection, take a look at his head, top right, the reflection is very smooth, no bumps at all.&#xA;&#xA;2- the wrinkles in his face need to be emphasized, he looks like some kind of a warrier, yet he has very smooth skin like a 15 year old has, I'm not talking about deep scars, I am talking about skin texture and bumpiness due to rough way of life, skin bumps, moles, a minor infection that will affect both coloration and bumpiness.&#xA;&#xA;3- his mouth is off, the size and positionning, I know that many people has small mouths, and a relatively large distance between the nose and the mouth, but that drives the attention of the viewers, it feels wrong, even if it was a photo of a real person, you can spare this kind of dragging attention to extreme shapes if reality is what you're after.&#xA;&#xA;4- This is a minor thing, but it had a role to play, the background and outfit, they look fake, this drives the viewrs automatically and subconsciously to feel that this is not real, try to put more effort in these, making the outfit less uniform, and the background to have more realistic pattern, with more hue variation.&#xA;&#xA;5- And last, the eyes, there's no reflection, yet the lighting is low and the image is small, so I am not sure if this is due to lighting or to the material itself.&#xA;&#xA;That all been said, all these remarks are minor, the artwork looks awesome, I don't think a CG artwork should look like a photo, a perfectly realistic CG artwork that looks ecactly like a photo, will become just another photo to the viewer." ContentLicense="CC BY-SA 3.0" />
  <row Id="7234" PostHistoryTypeId="5" PostId="2568" RevisionGUID="3f24ea0a-5346-4b16-a946-92c4ed77d6b9" CreationDate="2016-06-05T17:05:28.107" UserId="3487" Comment="typo, and refined explanation" Text="Few things, but usually this is what it takes to make the difference:&#xD;&#xA;&#xD;&#xA;1- the material reflection at his head, he is bald, yet the diffuse texture shows color difference where the hair is, this means he has a shaved head, not a natural bald, this should translate in reflection, take a look at his head, top right (top left for the image), the reflection is very smooth, no bumps at all, there should be some indication in reflection to the tiny hairs that you can see in the texture map.&#xD;&#xA;&#xD;&#xA;2- the wrinkles in his face need to be emphasized, he looks like some kind of a worrier, yet he has very smooth skin like a 15 year old has, I'm not talking about deep scars, I am talking about skin texture and bumpiness due to rough way of life, skin bumps, moles, a minor infection that will affect both coloration and bumpiness.&#xD;&#xA;&#xD;&#xA;3- his mouth is off, the size and positioning, I know that many people has small mouths, and a relatively large distance between the nose and the mouth, but that drives the attention of the viewers, it feels wrong, even if it was a photo of a real person, you can spare this kind of dragging attention to extreme shapes if reality is what you're after.&#xD;&#xA;&#xD;&#xA;4- This is a minor thing, but it had a role to play, the background and outfit, they look fake, this drives the viewers automatically and subconsciously to feel that this is not real, try to put more effort in these, making the outfit less uniform, and the background to have more realistic pattern, with more hue variation.&#xD;&#xA;&#xD;&#xA;5- And last, the eyes, there's no reflection, yet the lighting is low and the image is small, so I am not sure if this is due to lighting or to the material itself.&#xD;&#xA;&#xD;&#xA;That all been said, all these remarks are minor, the artwork looks awesome, I don't think a CG artwork should look like a photo, a perfectly realistic CG artwork that looks exactly like a photo, will become just another photo to the viewer." ContentLicense="CC BY-SA 3.0" />
  <row Id="7235" PostHistoryTypeId="33" PostId="2563" RevisionGUID="f6aa6abf-bb39-4ff8-8c5e-5c2d843f73ed" CreationDate="2016-06-06T05:26:38.877" UserId="310" Comment="17" />
  <row Id="7237" PostHistoryTypeId="2" PostId="3569" RevisionGUID="1fb58004-80cc-4f35-b9f3-0e9f783a00d0" CreationDate="2016-06-06T18:10:06.110" UserId="1971" Text="For a 3D scene in the World Coordinates, its View Reference Point is at c=(0,3,4), and&#xD;&#xA;a viewer is looking towards its origin O (0,0,0). Construct a transform matrix which will&#xD;&#xA;map World Coordinate points to a right-handed (UVN) viewing space, so that c is the&#xD;&#xA;origin, the line joining c to O is the positive N axis, and the View-Up Vector is (0,0,1).&#xD;&#xA;&#xD;&#xA;**My Attempt**&#xD;&#xA;&#xD;&#xA;VRP = (0,3,4)&#xD;&#xA;&#xD;&#xA;VUP = (0,0,1)&#xD;&#xA;&#xD;&#xA;VPN = (0,0,0,) - c = (0,-3,-4)&#xD;&#xA;&#xD;&#xA;n = VPN / |VPN| = (0,-0.6,-0.8)&#xD;&#xA;&#xD;&#xA;**Stuck Here**&#xD;&#xA;&#xD;&#xA;u = (n x VUP) / |(n x VUP)| = &#xD;&#xA;&#xD;&#xA;I'm confused how we would solve u now?&#xD;&#xA;&#xD;&#xA;After we have found u, I can just find v easy and then sub those values into the relevant matrices" ContentLicense="CC BY-SA 3.0" />
  <row Id="7238" PostHistoryTypeId="1" PostId="3569" RevisionGUID="1fb58004-80cc-4f35-b9f3-0e9f783a00d0" CreationDate="2016-06-06T18:10:06.110" UserId="1971" Text="View Reference Coordinate System" ContentLicense="CC BY-SA 3.0" />
  <row Id="7239" PostHistoryTypeId="3" PostId="3569" RevisionGUID="1fb58004-80cc-4f35-b9f3-0e9f783a00d0" CreationDate="2016-06-06T18:10:06.110" UserId="1971" Text="|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7240" PostHistoryTypeId="4" PostId="2563" RevisionGUID="462fca52-0f32-4ab4-b1d7-7d6851b62e37" CreationDate="2016-06-06T22:50:02.707" UserId="310" Comment="edited title" Text="Full Monte-Carlo Volumetric Scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="7241" PostHistoryTypeId="2" PostId="3570" RevisionGUID="83d83014-8798-4602-bfe5-3013ec9f1b9b" CreationDate="2016-06-07T03:47:47.680" UserId="48" Text="First of all, a good reference for Monte Carlo path tracing in participating media is [these course notes](http://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf) from Steve Marschner.&#xD;&#xA;&#xD;&#xA;The way I like to think about volume scattering is that a photon traveling through a medium has a certain probability per unit length of interacting (getting scattered or absorbed). As long as it doesn't interact, it just goes in a straight line unimpeded and without losing energy. The greater the distance, the greater the probability that it interacts somewhere in that distance. The interaction probability per unit length is the coefficient $\sigma$ that you see in the equations. We usually have separate coefficients for scattering and absorption probabilities, so $\sigma = \sigma_s + \sigma_a$.&#xD;&#xA;&#xD;&#xA;This probability per unit length is exactly the origin of the Beer-Lambert law. Slice a ray segment into infinitesimal intervals, treat each interval as an independent possible place to interact, then integrate along the ray; you get an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution) (with rate parameter $\sigma$) for the probability of interaction as a function of distance.&#xD;&#xA;&#xD;&#xA;So, to answer your questions directly:&#xD;&#xA;&#xD;&#xA;1. You _can_ technically choose the distance between events however you want, as long as you correctly weight the path for the probability that a photon can make it between two adjacent events without interacting with the medium. In other words, each path segment within the medium contributes a weight factor of $e^{-\sigma x}$, where $x$ is the length of the segment. (This is assuming a homogeneous medium, but see section 4.2 in the Marschner notes linked above for what to do if it's inhomogeneous.)&#xD;&#xA;&#xD;&#xA; Given this, a usually good choice for the distance is to importance-sample it from the exponential distribution. In other words, you set $x = -(\ln \xi)/\sigma$ and then leave out the $e^{-\sigma x}$ factor from the path weight.&#xD;&#xA;&#xD;&#xA; Then, to account for absorption, you can use Russian roulette to kill off a fraction $\sigma_a/\sigma$ of the paths at each event. This is particularly necessary for very large or infinite media (think atmospheric scattering) where the path could bounce around for an arbitrarily long time. If you're only dealing with small and not-too-dense media, then it might be better to just factor in a weight of $1 - \sigma_a/\sigma$ per event, rather than using Russian roulette.&#xD;&#xA;&#xD;&#xA;2. No, if you follow the importance-sampling procedure just described, Beer-Lambert is already incorporated implicitly in the sampling, so you don't want to apply it to the path weights.&#xD;&#xA;&#xD;&#xA;3. The volumetric equivalent to a BSDF is the combination of the scattering and absorption coefficients $\sigma_s, \sigma_a$ and the phase function. By convention, the coefficients control the overall balance of transmission, scattering, and absorption, while the phase function is always normalized.&#xD;&#xA;&#xD;&#xA; You could do something like this for BSDFs too; you could factor out the overall albedo, and have the directional dependence always be normalized. It's mostly a matter of convention AFAICT.&#xD;&#xA;&#xD;&#xA;4. Try &quot;participating media&quot; (that is, a volumetric &quot;medium&quot;&amp;mdash;plural &quot;media&quot;&amp;mdash;which &quot;participates&quot; in light transport), and &quot;volumetric path tracing&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="7242" PostHistoryTypeId="5" PostId="3570" RevisionGUID="c25ad464-3310-459a-a0ae-da2e3bfef83d" CreationDate="2016-06-07T03:54:51.840" UserId="48" Comment="added 19 characters in body" Text="First of all, a good reference for Monte Carlo path tracing in participating media is [these course notes](http://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf) from Steve Marschner.&#xD;&#xA;&#xD;&#xA;The way I like to think about volume scattering is that a photon traveling through a medium has a certain probability per unit length of interacting (getting scattered or absorbed). As long as it doesn't interact, it just goes in a straight line unimpeded and without losing energy. The greater the distance, the greater the probability that it interacts somewhere in that distance. The interaction probability per unit length is the coefficient $\sigma$ that you see in the equations. We usually have separate coefficients for scattering and absorption probabilities, so $\sigma = \sigma_s + \sigma_a$.&#xD;&#xA;&#xD;&#xA;This probability per unit length is exactly the origin of the Beer-Lambert law. Slice a ray segment into infinitesimal intervals, treat each interval as an independent possible place to interact, then integrate along the ray; you get an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution) (with rate parameter $\sigma$) for the probability of interaction as a function of distance.&#xD;&#xA;&#xD;&#xA;So, to answer your questions directly:&#xD;&#xA;&#xD;&#xA;1. You _can_ technically choose the distance between events however you want, as long as you correctly weight the path for the probability that a photon can make it between two adjacent events without interacting with the medium. In other words, each path segment within the medium contributes a weight factor of $e^{-\sigma x}$, where $x$ is the length of the segment. (This is assuming a homogeneous medium, but see section 4.2 in the Marschner notes linked above for what to do if it's inhomogeneous.)&#xD;&#xA;&#xD;&#xA; Given this, a usually good choice for the distance is to importance-sample it from the exponential distribution. In other words, you set $x = -(\ln \xi)/\sigma$ and then leave out the $e^{-\sigma x}$ factor from the path weight.&#xD;&#xA;&#xD;&#xA; Then, to account for absorption, you can use Russian roulette to kill off a fraction $\sigma_a/\sigma$ of the paths at each event. This is particularly necessary for very large or infinite media (think atmospheric scattering) where the path could bounce around for an arbitrarily long time if it's not killed. If you're only dealing with small and not-too-dense media, then it might be better to just factor in a weight of $1 - \sigma_a/\sigma$ per event, rather than using Russian roulette.&#xD;&#xA;&#xD;&#xA;2. No, if you follow the importance-sampling procedure just described, Beer-Lambert is already incorporated implicitly in the sampling, so you don't want to apply it to the path weights.&#xD;&#xA;&#xD;&#xA;3. The volumetric equivalent to a BSDF is the combination of the scattering and absorption coefficients $\sigma_s, \sigma_a$ and the phase function. By convention, the coefficients control the overall balance of transmission, scattering, and absorption, while the phase function is always normalized.&#xD;&#xA;&#xD;&#xA; You could do something like this for BSDFs too; you could factor out the overall albedo, and have the directional dependence always be normalized. It's mostly a matter of convention AFAICT.&#xD;&#xA;&#xD;&#xA;4. Try &quot;participating media&quot; (that is, a volumetric &quot;medium&quot;&amp;mdash;plural &quot;media&quot;&amp;mdash;which &quot;participates&quot; in light transport), and &quot;volumetric path tracing&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="7243" PostHistoryTypeId="2" PostId="3571" RevisionGUID="c57793cf-936a-41b6-8d4b-6d8ea0388e01" CreationDate="2016-06-07T04:35:00.773" UserDisplayName="user3437" Text="I am implementing simple rotation but the object is not rotating around the local center instead it is rotating around world origin.&#xD;&#xA;&#xD;&#xA;This is the code :-  &#xD;&#xA;&#xD;&#xA;		Matrix2D m = Matrix2D.Rotate((float) (Math.PI));&#xD;&#xA;		&#xD;&#xA;		Point p =  new Point(new Vector2D(-0.1f,0.7f),this, new PixelData(255, 255, 0, 0));&#xD;&#xA;		Point p2 = new Point(new Vector2D(0,0.8f),this, new PixelData(255, 255, 0, 0));&#xD;&#xA;		Point p3 = new Point(new Vector2D(0.1f,0.7f),this, new PixelData(255, 255, 0, 0));&#xD;&#xA;	&#xD;&#xA;		Vector2D v = Matrix2D.MatrixTimesVector2D(m, p.getPosition());&#xD;&#xA;		Vector2D v2 = Matrix2D.MatrixTimesVector2D(m, p2.getPosition());&#xD;&#xA;		Vector2D v3 = Matrix2D.MatrixTimesVector2D(m, p3.getPosition());&#xD;&#xA;		&#xD;&#xA;		Point z = new Point(v, this, p.getColour());&#xD;&#xA;		Point z2 = new Point(v2, this, p.getColour());&#xD;&#xA;		Point z3 = new Point(v3, this, p.getColour());&#xD;&#xA;		&#xD;&#xA;		new Triangle(z2.Transform(), z.Transform(), z3.Transform(),this).DrawTriangle();&#xD;&#xA;&#xD;&#xA;I checked my matrices and matrix multiplication is correct.&#xD;&#xA; &#xD;&#xA;Result without rotation :-&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And after rotation :-&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Why i am getting this weird rotation ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CcoSg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3eTRX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7244" PostHistoryTypeId="1" PostId="3571" RevisionGUID="c57793cf-936a-41b6-8d4b-6d8ea0388e01" CreationDate="2016-06-07T04:35:00.773" UserDisplayName="user3437" Text="Object rotating around origin instead of object center?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7245" PostHistoryTypeId="3" PostId="3571" RevisionGUID="c57793cf-936a-41b6-8d4b-6d8ea0388e01" CreationDate="2016-06-07T04:35:00.773" UserDisplayName="user3437" Text="|transformations|mathematics|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7246" PostHistoryTypeId="2" PostId="3572" RevisionGUID="bee276d1-154e-48f9-a1c2-68fe98077486" CreationDate="2016-06-07T06:23:58.637" UserId="3434" Text="Your triangle's coordinates: &#xD;&#xA;(-0.1f,0.7f)&#xD;&#xA;(0.0f,0.8f)&#xD;&#xA;(0.1f,0.7f)&#xD;&#xA;are defined with the origin at the center of the screen.&#xD;&#xA;&#xD;&#xA;Multiplying a rotation matrix by a vertex position will rotate around the point (0,0,0). In your case, that is the center of the screen.&#xD;&#xA;&#xD;&#xA;**Possible solution:**&#xD;&#xA;&#xD;&#xA;- Define the vertices as: (-0.1f,-0.5f) (0.0f,0.5f,) and (0.1f,-0.5f)&#xD;&#xA;- Rotate the vertices with your rotation matrix (Like you did):&#xD;&#xA;&#xD;&#xA;    Vector2D v = Matrix2D.MatrixTimesVector2D(m, p.getPosition());&#xD;&#xA;&#xD;&#xA;    Vector2D v2 = Matrix2D.MatrixTimesVector2D(m, p2.getPosition());&#xD;&#xA;&#xD;&#xA;    Vector2D v3 = Matrix2D.MatrixTimesVector2D(m, p3.getPosition());&#xD;&#xA;&#xD;&#xA;- If you want your triangle at the top of you screen, use a translation matrix:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XYXUs.png&#xD;&#xA;&#xD;&#xA;I'm not sure what language/library you are using, but create a translation matrix by yourself or using a built in fuction. Above dx, dy and dz are the translations in x,y and z.&#xD;&#xA;&#xD;&#xA;Multiply your positions v, v2 and v3 by the translation matrix.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Google tranlsation and rotation matrix and you will understand better! Good luck!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7248" PostHistoryTypeId="2" PostId="3573" RevisionGUID="c6528ca8-b775-4b55-97d9-c63e2d55cf82" CreationDate="2016-06-07T13:37:24.170" UserId="4497" Text="I have a program I wrote that allows chromakey (green screen) using a web cam. I wrote it using DirectShow - I created a custom filter to blend the web cam video with a graphic. It works fine but requires huge amounts of CPU. Also, from what I understand, DS is deprecated - or at least on its way out.&#xD;&#xA;&#xD;&#xA;So, I'm thinking about re-doing it with OpenGL and using OpenCV to grab the web cam video. I don't have a lot of experience with OpenGL, so my question is: If I create a chromakey shader will it be executed on the GPU and therefore be faster? Or is this something for which OpenGL is not useful?&#xD;&#xA;&#xD;&#xA;I would like the input of someone with experience before I attempt this." ContentLicense="CC BY-SA 3.0" />
  <row Id="7249" PostHistoryTypeId="1" PostId="3573" RevisionGUID="c6528ca8-b775-4b55-97d9-c63e2d55cf82" CreationDate="2016-06-07T13:37:24.170" UserId="4497" Text="Chromakey Conversion" ContentLicense="CC BY-SA 3.0" />
  <row Id="7250" PostHistoryTypeId="3" PostId="3573" RevisionGUID="c6528ca8-b775-4b55-97d9-c63e2d55cf82" CreationDate="2016-06-07T13:37:24.170" UserId="4497" Text="|opengl|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7251" PostHistoryTypeId="34" PostId="2563" RevisionGUID="afeb733b-d053-446e-a11f-c8da7c595a37" CreationDate="2016-06-07T14:21:27.697" UserId="310" Comment="17" />
  <row Id="7252" PostHistoryTypeId="2" PostId="3574" RevisionGUID="7533a6d6-b123-4b2f-b880-962a8d2b7e66" CreationDate="2016-06-07T14:35:14.047" UserId="38" Text="It almost certainly depends on implementation. I have used CPU only keyers that had no problems keying full hd in real time. &#xD;&#xA;&#xD;&#xA;But back to the question would a shader be faster? Most likely, especially if your chroma key is a classic color transform. Then the GPU would shine as it would get to use it massive multicore architecture to full potential." ContentLicense="CC BY-SA 3.0" />
  <row Id="7253" PostHistoryTypeId="2" PostId="3575" RevisionGUID="2f8b3ba0-7b8a-4ad5-8702-8d9013c88d2a" CreationDate="2016-06-07T21:13:56.997" UserId="3477" Text="[From the wiki][1]: &quot;the Vulkan API was initially referred to as the 'next generation OpenGL initiative' by Khrono&quot;, [and that it is][2] &quot;a grounds-up redesign effort to unify OpenGL and OpenGL ES into one common API that will not be backwards compatible with existing OpenGL versions&quot;.&#xD;&#xA;&#xD;&#xA;So should those now getting into graphics programming be better served to learn Vulkan instead of OpenGL? It seem they will serve the same purpose.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Vulkan_(API)&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/OpenGL#Vulkan" ContentLicense="CC BY-SA 3.0" />
  <row Id="7254" PostHistoryTypeId="1" PostId="3575" RevisionGUID="2f8b3ba0-7b8a-4ad5-8702-8d9013c88d2a" CreationDate="2016-06-07T21:13:56.997" UserId="3477" Text="Should new graphics programmers be learning Vulkan instead of OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7255" PostHistoryTypeId="3" PostId="3575" RevisionGUID="2f8b3ba0-7b8a-4ad5-8702-8d9013c88d2a" CreationDate="2016-06-07T21:13:56.997" UserId="3477" Text="|opengl|api|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7256" PostHistoryTypeId="2" PostId="3576" RevisionGUID="b50a6d55-6de2-49fd-a26c-a402ed18575b" CreationDate="2016-06-07T21:20:37.550" UserId="4494" Text="Hardly!&#xD;&#xA;&#xD;&#xA;This seems a lot like asking &quot;Should new programmers learn C++ instead of C,&quot; or &quot;Should new artists be learning digital painting instead of physical painting.&quot;&#xD;&#xA;&#xD;&#xA;Especially because it's NOT backward compatible, graphics programmers would be foolish to exclude the most common graphics API in the industry, simply because there's a new one. Additionally, OpenGL does different things differently. It's entirely possible that a company would choose OpenGL over Vulkan, especially this early in the game, and that company would not be interested in someone who doesn't know OpenGL, regardless of whether they know Vulkan or not.&#xD;&#xA;&#xD;&#xA;Specialization is rarely a marketable skill." ContentLicense="CC BY-SA 3.0" />
  <row Id="7257" PostHistoryTypeId="5" PostId="3576" RevisionGUID="0e590f04-bb22-4ca9-94fc-05cbe762b57b" CreationDate="2016-06-07T21:25:46.773" UserId="4494" Comment="added 362 characters in body" Text="Hardly!&#xD;&#xA;&#xD;&#xA;This seems a lot like asking &quot;Should new programmers learn C++ instead of C,&quot; or &quot;Should new artists be learning digital painting instead of physical painting.&quot;&#xD;&#xA;&#xD;&#xA;Especially because it's NOT backward compatible, graphics programmers would be foolish to exclude the most common graphics API in the industry, simply because there's a new one. Additionally, OpenGL does different things differently. It's entirely possible that a company would choose OpenGL over Vulkan, especially this early in the game, and that company would not be interested in someone who doesn't know OpenGL, regardless of whether they know Vulkan or not.&#xD;&#xA;&#xD;&#xA;Specialization is rarely a marketable skill.&#xD;&#xA;&#xD;&#xA;For those who don't need to market their skills as such, like indie developers, it'd be even MORE foolish to remove a tool from their toolbox. An indie dev is even more dependent on flexibility and being able to choose what works, over what's getting funded. Specializing in Vulkan only limits your options.&#xD;&#xA;&#xD;&#xA;Specialization is rarely an efficient paradigm." ContentLicense="CC BY-SA 3.0" />
  <row Id="7258" PostHistoryTypeId="2" PostId="3577" RevisionGUID="3d6d42cb-9f34-48d5-8602-a439583af82b" CreationDate="2016-06-08T01:02:11.473" UserId="4499" Text="The primary appeal of OpenGL (at least to me) is that it works on many platforms. Currently, Vulkan does not work on OSX, and Apple has a competing API called Metal. It's very possible that it will be some time before Apple supports Vulkan, and when they do, Vulkan support may only come to their latest hardware. OpenGL already supports most hardware, and will continue to do so." ContentLicense="CC BY-SA 3.0" />
  <row Id="7259" PostHistoryTypeId="2" PostId="3578" RevisionGUID="e0b29af1-044c-42c8-962c-c2157c089b2e" CreationDate="2016-06-08T07:27:09.513" UserId="3123" Text="It depends on what you want to do. If you want to learn graphics programming only for yourself it really doesn't matter what you will choose.&#xD;&#xA;&#xD;&#xA;If you thinking about professional work I recommend Vulkan. It is closer to hardware and I think knowledge about what hardware do is important for graphics programmers." ContentLicense="CC BY-SA 3.0" />
  <row Id="7261" PostHistoryTypeId="2" PostId="3579" RevisionGUID="292eec60-f9fc-4523-a634-bb8c608d2241" CreationDate="2016-06-08T10:29:07.650" UserId="2041" Text="If you're getting started now, and you want to do GPU work (as opposed to always using a game engine such as Unity), you should definitely start by learning Vulkan. Maybe you should learn GL later too, but there are a couple of reasons to think Vulkan-first.&#xD;&#xA;&#xD;&#xA;1. GL and GLES were designed many years ago, when GPUs worked quite differently. (The most obvious difference being immediate-mode draw calls vs tiling and command queues.) GL encourages you to think in an immediate-mode style, and has a lot of legacy cruft. Vulkan offers programming models that are much closer to how contemporary GPUs work, so if you learn Vulkan, you'll have a better understanding of how the technology really works, and of what is efficient and what is inefficient. I see lots of people who've started with GL or GLES and immediately get into bad habits like issuing separate draw calls per-object instead of using VBOs, or even worse, using display lists. It's hard for GL programmers to find out what is no longer encouraged.&#xD;&#xA;&#xD;&#xA;2. It's much easier to move from Vulkan to GL or GLES than vice-versa. Vulkan makes explicit a lot of things that were hidden or unpredictable in GL, such as concurrency control, sharing, and rendering state. It pushes a lot of complexity up from the driver to the application: but by doing so, it gives control to the application, and makes it simpler to get predictable performance and compatibility between different GPU vendors. If you have some code that works in Vulkan, it's quite easy to port that to GL or GLES instead, and you end up with something that uses good GL/GLES habits. If you have code that works in GL or GLES, you almost have to start again to make it work efficiently in Vulkan: especially if it was written in a legacy style (see point 1).&#xD;&#xA;&#xD;&#xA;As others have said: GL is available on many platforms, WebGL is a nice delivery mechanism, there's a lot of existing software that uses GL, and there are many employers hiring for that skill. It's going to be around for the next few years while Vulkan ramps up and develops an ecosystem. For these reasons, you'd be foolish to rule out learning GL entirely. Even so, you'll have a much easier time with it, and become a better GL programmer (and a better GPU programmer in general), if you start off with something that helps you to understand the GPU, instead of understanding how they worked 20 years ago.&#xD;&#xA;&#xD;&#xA;Of course, there's one option more. I don't know whether this is relevant to you in particular, but I feel I should say it for the other visitors anyway.&#xD;&#xA;&#xD;&#xA;To be an indie games developer, or a game designer, or to make VR experiences, you don't need to learn Vulkan or GL. Many people get started with a games engine (Unity or UE4 are popular at the moment). Using an engine like that will let you focus on the experience you want to create, instead of the technology behind it. It will hide the differences between GL and Vulkan from you, and you don't need to worry about which is supported on your platform. It'll let you learn about 3D co-ordinates, transforms, lighting, and animation without having to deal with all the gritty details at once. Some game or VR studios only work in an engine, and they don't have a full-time GL expert at all. Even in larger studios which write their own engines, the people who do the graphics programming are a minority, and most of the developers work on higher-level code.&#xD;&#xA;&#xD;&#xA;Learning about the details of how to interact with a GPU is certainly a useful skill, and one that many employers will value, but you shouldn't feel like you have to learn that to get into 3D programming; and even if you know it, it won't necessarily be something you use every day." ContentLicense="CC BY-SA 3.0" />
  <row Id="7262" PostHistoryTypeId="2" PostId="3580" RevisionGUID="bc7f1c8a-dd6a-4098-8c9d-c077b992ae97" CreationDate="2016-06-08T13:28:33.330" UserId="4490" Text="This question was originally asked on Physics, then moved to [Cognitive Sciences][1].&#xD;&#xA;&#xD;&#xA;Consider the following image:&#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;You might want to display the image in a new page, in case it gets resized for mobile displays.&#xD;&#xA;&#xD;&#xA;On the top half, there is a pixel-sized checkerboard pattern with alternating black and white pixels; on the bottom half, there's a black to white gradient. Now, I don't know if you see the same, but for me, when viewing from distance or defocusing my eyes and the top half blending into one color, I can't find any color in the gradient below which would match it.&#xD;&#xA;&#xD;&#xA;With simple arithmetics, I would guess at first guess the resulting color be either RGB $(0.5, 0.5, 0.5)$ or, with gamma, $(\sqrt{0.5}, \sqrt{0.5}, \sqrt{0.5})$. I cannot help myself, but the resulting color appears a lot warmer than the metallic gray which would appear if you for example zoomed this page or used a blur filter. I tried to add some yellow to the gradient, and the result looks more similar to the perceived color.&#xD;&#xA;&#xD;&#xA;Now, based on the comments, it appears some people perceive yellowish tint and some don't. And I do on my LCD computer screen but not on my mobile display. Thus I guess it's based on some property of the display.&#xD;&#xA;&#xD;&#xA;Why don't we perceive the resulting color like real gray? Where does the yellow color come from?&#xD;&#xA;&#xD;&#xA;I have a theory: Based on the [color arrangement in a typical LCD pixel][3], one white pixel would contain the red and green color together and blue on the right side. Blue color appears darker to human eye than colors with the same physical intensity, so a white pixel is more green than red than blue. Green and red have roughy the same perceptional insensity, and mixing red and green color addivitely gives yellow, thus the yellow tint? Well, shouldn't then all white pixels on the display appear a bit yellow?&#xD;&#xA;&#xD;&#xA;Is this possible? Are there any other explanations?&#xD;&#xA;&#xD;&#xA;A side question: Do you know any computer image scaling algorithm or blur filter that tries to mimic this, simulating a blurry vision of a human eye correctly?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/IxOzp.png&#xD;&#xA;  [3]: https://upload.wikimedia.org/wikipedia/commons/4/4d/Pixel_geometry_01_Pengo.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://cogsci.stackexchange.com/questions/15186/why-does-checkerboard-pattern-on-a-computer-screen-appear-with-a-yellowish-tint" ContentLicense="CC BY-SA 3.0" />
  <row Id="7263" PostHistoryTypeId="1" PostId="3580" RevisionGUID="bc7f1c8a-dd6a-4098-8c9d-c077b992ae97" CreationDate="2016-06-08T13:28:33.330" UserId="4490" Text="Why does checkerboard pattern on a computer screen appear with a yellowish tint?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7264" PostHistoryTypeId="3" PostId="3580" RevisionGUID="bc7f1c8a-dd6a-4098-8c9d-c077b992ae97" CreationDate="2016-06-08T13:28:33.330" UserId="4490" Text="|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7265" PostHistoryTypeId="2" PostId="3581" RevisionGUID="4ad3edb3-6cd3-4aa9-b47d-cb8f3037187a" CreationDate="2016-06-08T16:04:31.510" UserId="3420" Text="You should be learning OpenGL first, as that is the standard for Graphics, across so many platforms.&#xD;&#xA;&#xD;&#xA;Even if there is a newer library, understanding the basics, and working with a language that is used all over the industry, is very important.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, I've heard that OpenGL, and Vulkan, aren't exactly the same.  I hear Vulkan is a lower level API, and closer to machine code, than OpenGL.&#xD;&#xA;&#xD;&#xA;This answer I just found seems to have a lot of great info&#xD;&#xA;&#xD;&#xA;http://gamedev.stackexchange.com/questions/96014/what-is-vulkan-and-how-does-it-differ-from-opengl&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another thing that is something to consider is the issue that happened back with OpenGL 1.&#xD;&#xA;&#xD;&#xA;OpenGL 1 to OpenGL 2 had MAJOR changes, and since many people were using OpenGL1, and hardware supported it, there is heavy backwards compatibility needed to be implemented in some applications/engines, and that sometimes is really painful for the devs to keep supporting it.&#xD;&#xA;&#xD;&#xA;Besides the support, the language shifted so much, that you had to learn new stuff.&#xD;&#xA;&#xD;&#xA;This has happened with frameworks such as JavaFX (from 1.x to 2.x) and Play! Framework (Also 1.x to 2.x).  Complete changes to the framework, meaning we have to relearn... everything...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;--------------------------------------&#xD;&#xA;&#xD;&#xA;So essentially what you should do is wait until Vulkan is STABLE.  That means wait until Probably the 2.0 patch.  IT doesn't mean you cannot learn about the basics of Vulkan, but just know this might change.  I would assume that a group like Kronos would provide a very stable API from the start, especially since there are multiple Nvidia and AMD engineers working on Vulkan, including a high up Nvidia person overseeing the project apparently, as well as The base of Mantle; however, like any software, we the coders will see how well it works from the start, but many are wary and waiting to see what happens.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7269" PostHistoryTypeId="5" PostId="3578" RevisionGUID="8662db2f-b523-4199-aeff-c707029a35a1" CreationDate="2016-06-08T18:04:37.543" UserId="3123" Comment="added 1169 characters in body" Text="It depends on what you want to do. If you want to learn graphics programming only for yourself it really doesn't matter what you will choose.&#xD;&#xA;&#xD;&#xA;If you thinking about professional work I recommend Vulkan. It is closer to hardware and I think knowledge about what hardware do is important for graphics programmers.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;Little comment to what i meant:&#xD;&#xA;&#xD;&#xA;Vulkan is closer to hardware because OpenGL does a lot of stuff under the hood which in Vulkan you do manually, like execute command queue.&#xD;&#xA;Also memory management is up to application not driver. You need to worry about allocate memory for `uniforms`(variable that you pass from CPU to GPU), about tracking them. You have more things to worry about but also it gives more freedom on usage of memory.&#xD;&#xA;It can sound scary and overwhelming but it really isn't. It's only next API that you need to learn.&#xD;&#xA;&#xD;&#xA;Understanding this things also will help in understanding how GPU work. What will allow you to do some optimization both on Vulkan and OpenGL. &#xD;&#xA;&#xD;&#xA;And one more thing that come to my mind, If you are starting to learn graphics programming probably when you will searching a job as one Vulkan will be more popular (maybe more popular than OpenGL) also as far as I know most of companies that are using some graphics API write own functions around it so there is probability that in job you will not writing in OpenGL neither in Vulkan but knowledge about GPU will be always useful.&#xD;&#xA;&#xD;&#xA;Sorry for my really bad english." ContentLicense="CC BY-SA 3.0" />
  <row Id="7272" PostHistoryTypeId="2" PostId="3583" RevisionGUID="1acf7d64-4fcf-457d-83da-23a553690e6d" CreationDate="2016-06-09T04:38:43.670" UserId="4522" Text="I've been &quot;getting in to&quot; graphics programming for a few months now.&#xD;&#xA;&#xD;&#xA;Right now I'm still in High School, and I can tell you I am almost always looking to develop cross platform applications. This is in fact my number one problem with Vulkan - It isn't developed to work on all platforms. I work with OpenGL in Java and have for over 6 months.&#xD;&#xA;&#xD;&#xA;Another problem I have is with Vulkan's claims is how it claims to be better. While OpenGL certainly isn't updating their website very often. They continue to constantly release updates and I always look forward to new updates that run faster or work better with new hardware.&#xD;&#xA;&#xD;&#xA;That being said, while I mostly work with OpenGL I understand basic principles of DirectX and Vulkan. While I don't work with them extensively, especially Vulkan as it's very hard to learn and not as well structured for programming as OpenGl and DirectX.&#xD;&#xA;&#xD;&#xA;Lastly, I'd like to add that specializing in a single field like I mostly use Java and OpenGL isn't amazingly marketable standalone. If I wanted to get a job at a company that made games, for the most part OpenGL would only be used to make games for Linux and Android development and possibly OSX. DirectX for Windows and Consoles &lt; Which Vulkan can replace in some cases. &#xD;&#xA;&#xD;&#xA;I can't hold out for OpenGL updates forever, and I wont. But it's my preference for developing." ContentLicense="CC BY-SA 3.0" />
  <row Id="7273" PostHistoryTypeId="2" PostId="3584" RevisionGUID="5c5878e8-aa6d-4f3e-9131-4501c17779dd" CreationDate="2016-06-09T06:35:26.767" UserDisplayName="user3437" Text="This is my code of the algorithm for making triangles :-&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    private void sort(){&#xD;&#xA;		int temp = Math.round(m_Vertex1.getPosition().getX());&#xD;&#xA;		int temp2 = Math.round(m_Vertex2.getPosition().getX());&#xD;&#xA;		int temp3 = Math.round(m_Vertex3.getPosition().getX());&#xD;&#xA;		&#xD;&#xA;		m_minX = Math.min(temp3, Math.min(temp, temp2));	//Sorting the X values&#xD;&#xA;		m_maxX = Math.max(temp3, Math.max(temp, temp2));&#xD;&#xA;		&#xD;&#xA;		temp = Math.round(m_Vertex1.getPosition().getY()); &#xD;&#xA;		temp2 = Math.round(m_Vertex2.getPosition().getY());&#xD;&#xA;		temp3 = Math.round(m_Vertex3.getPosition().getY());&#xD;&#xA;		&#xD;&#xA;		m_minY = Math.min(temp3, Math.min(temp, temp2));	// Sorting the Y values&#xD;&#xA;		m_maxY = Math.max(temp3, Math.max(temp, temp2));&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	public void DrawTriangle(){	&#xD;&#xA;		new Line(m_Vertex1, m_Vertex2, m_display).DrawLine(Optional.of(EdgeOnePoints));		//Getting all the points on the boundary of the triangle&#xD;&#xA;		new Line(m_Vertex2, m_Vertex3, m_display).DrawLine(Optional.of(EdgeTwoPoints));&#xD;&#xA;		new Line(m_Vertex1, m_Vertex3, m_display).DrawLine(Optional.of(EdgeThreePoints));&#xD;&#xA;	&#xD;&#xA;		Vector2D start = Vector2D.zero();&#xD;&#xA;		Vector2D end = Vector2D.zero();&#xD;&#xA;		&#xD;&#xA;		for(float i = m_minY; i &lt;= m_maxY ;i++){		//Iterating from top to bottom of the triangle&#xD;&#xA;			&#xD;&#xA;			for(float j = m_minX; j &lt;= m_maxX; j++){	//Iterating left to right of the triangle&#xD;&#xA;				Vector2D temp = new Vector2D(j,i);&#xD;&#xA;				&#xD;&#xA;				if(EdgeOnePoints.contains(temp)	|| EdgeTwoPoints.contains(temp) || EdgeThreePoints.contains(temp)){  &#xD;&#xA;					if(start.equals(Vector2D.zero())){		// Getting the first point of intersection between the triangle and the scanline &#xD;&#xA;						start = temp;&#xD;&#xA;					}else{&#xD;&#xA;						if(EdgeOnePoints.contains(start) &amp;&amp; !EdgeOnePoints.contains(temp)){		// Checking if start point and end point are on the same edge or not, if not then it is a valid point else not.&#xD;&#xA;							end = temp;&#xD;&#xA;							break;&#xD;&#xA;						}else if(EdgeTwoPoints.contains(start) &amp;&amp; !EdgeTwoPoints.contains(temp)){&#xD;&#xA;							end = temp;&#xD;&#xA;							break;&#xD;&#xA;						}else if(EdgeThreePoints.contains(start) &amp;&amp; !EdgeThreePoints.contains(temp)){&#xD;&#xA;							end = temp;&#xD;&#xA;							break;&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			&#xD;&#xA;			if(!start.equals(Vector2D.zero()) &amp;&amp; !end.equals(Vector2D.zero())){	//if both start and end points are available then draw then fill all the points in between them.&#xD;&#xA;				for(float j = start.getX(); j &lt;= end.getX(); j++){&#xD;&#xA;					new Point(new Vector2D(j, i), PixelData.white(), m_display).DrawPoint();&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			&#xD;&#xA;			start = Vector2D.zero(); &#xD;&#xA;			end = Vector2D.zero();   &#xD;&#xA;		}&#xD;&#xA;	} &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now i have couple of problems with it :- &#xD;&#xA;&#xD;&#xA;1. It is a tortoise, i have tested it on a old machine and just with 2 rotating triangles, the frame rate is below 30.&#xD;&#xA;&#xD;&#xA;2. i get this weird line in between the triangle at some specific position when rotating the triangle.&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6KsEH.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I don't care much about the second problem but can anyone help me making this algorithm fast. should i use something like flood fill or boundary fill algorithm ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7274" PostHistoryTypeId="1" PostId="3584" RevisionGUID="5c5878e8-aa6d-4f3e-9131-4501c17779dd" CreationDate="2016-06-09T06:35:26.767" UserDisplayName="user3437" Text="scan line algorithm is too slow?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7275" PostHistoryTypeId="3" PostId="3584" RevisionGUID="5c5878e8-aa6d-4f3e-9131-4501c17779dd" CreationDate="2016-06-09T06:35:26.767" UserDisplayName="user3437" Text="|algorithm|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7276" PostHistoryTypeId="2" PostId="3585" RevisionGUID="a4377a97-23ed-4bcb-94f7-1276cfbe7d7f" CreationDate="2016-06-09T07:15:28.370" UserId="48" Text="One red flag is the use of `new` several times within the loop. Memory allocation doesn't belong in a rasterizer! :) Certainly you should not need to allocate a `Point` object (which is used once and then immediately discarded) and do a method call on it, just in order to fill a single pixel! The pixels are hopefully stored as a flat array of bytes, so just write directly to the appropriate address in it. Similarly, don't allocate a `Vector2D` every time through, just create one (ideally on the stack, if the language you're using allows for it), and re-use it.&#xD;&#xA;&#xD;&#xA;Secondly, the algorithm you're using doesn't seem to be a true scanline rasterizer. It iterates over the pixels in each line from left to right, performing edge tests on every single pixel to determine whether it's inside or outside, and recording when that state changes in the `start` and `end` variables.&#xD;&#xA;&#xD;&#xA;The way a scanline rasterizer is supposed to work (which is much faster) is to *calculate* the intersection points of each edge with the scanline (using good old school algebra line-line intersection math). Ideally you would have already categorized and sorted the three edges as left, right, or horizontal and therefore once you have the intersection points, it's easy to figure out the interval that the triangle covers on the scanline. Then you can iterate over that and shade or fill each pixel.&#xD;&#xA;&#xD;&#xA;Finally, I'm not sure if this is a real issue or not, but there are a lot of method calls for relatively trivial things like checking whether vectors are equal, or doing an edge-vs-point test. Hopefully the compiler is inlining all those, but you might want to check the generated code to see. If it's not, you could see a fair speedup by manually inlining that stuff, and possibly manually &quot;destructuring&quot; the vectors (i.e. replace a Vector2D variable by two explicit x and y variables)." ContentLicense="CC BY-SA 3.0" />
  <row Id="7277" PostHistoryTypeId="2" PostId="3586" RevisionGUID="b993e5e9-61f9-4a76-b717-4556e73e6894" CreationDate="2016-06-09T07:40:03.600" UserId="2061" Text="I have been reading a lot of debate on a new feature that will be available in the new version of the game engine Unity 5.4 - called GPU instancing. I understand the importance of instancing in general, both in terms of saving memory and draw calls.&#xD;&#xA;&#xD;&#xA;However, even after doing some reading, I still couldn't understand what exactly are the differences between GPU instancing and non-GPU instancing - and, more importantly, where the alleged GPU advantages in terms of performance come from in comparison to standard instancing.&#xD;&#xA;&#xD;&#xA;Thanks for your knowledge and for any references." ContentLicense="CC BY-SA 3.0" />
  <row Id="7278" PostHistoryTypeId="1" PostId="3586" RevisionGUID="b993e5e9-61f9-4a76-b717-4556e73e6894" CreationDate="2016-06-09T07:40:03.600" UserId="2061" Text="What are the differences between GPU instancing and standard instancing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7279" PostHistoryTypeId="3" PostId="3586" RevisionGUID="b993e5e9-61f9-4a76-b717-4556e73e6894" CreationDate="2016-06-09T07:40:03.600" UserId="2061" Text="|gpu|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7280" PostHistoryTypeId="34" PostId="2516" RevisionGUID="23636924-f570-489a-bf1a-ba4809abd93d" CreationDate="2016-06-09T08:27:12.940" UserId="-1" Comment="16" />
  <row Id="7281" PostHistoryTypeId="2" PostId="3587" RevisionGUID="b9be35ce-0a08-4563-959f-f1bfa2b2f3d6" CreationDate="2016-06-09T12:46:18.310" UserId="4528" Text="I am trying to devise a GUI system that functions as a virtual patchbay, as seen in something like Logic Studio's environment editor, or seen in virtual synthesizers that use virtual patchcables.&#xD;&#xA;&#xD;&#xA;I'm not much of a coder, so I've been experimenting with LiveCode.&#xD;&#xA;&#xD;&#xA;The challenge seems to be part code, part graphical. I can't even fathom how a system like that works. What bitmaps should I produce (if any) and how should they be manipulated in code? &#xD;&#xA;&#xD;&#xA;Any assistance would be greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="7282" PostHistoryTypeId="1" PostId="3587" RevisionGUID="b9be35ce-0a08-4563-959f-f1bfa2b2f3d6" CreationDate="2016-06-09T12:46:18.310" UserId="4528" Text="How would I create a virtual cabling system?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7283" PostHistoryTypeId="3" PostId="3587" RevisionGUID="b9be35ce-0a08-4563-959f-f1bfa2b2f3d6" CreationDate="2016-06-09T12:46:18.310" UserId="4528" Text="|line-drawing|physics|simulation|edge-detection|realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7284" PostHistoryTypeId="2" PostId="3588" RevisionGUID="a3563157-ea2f-4d01-91b4-4286e5e2a620" CreationDate="2016-06-09T12:53:14.763" UserId="4513" Text="I have made an 3d solar exposure analysis for a 3d city model that determines how long a surface receive direct sunlight throughout the year. Results are coloured surfaces and legend of coloures that explain how long the colour means. You can see the results in the attaching file. How can I report the results. How can I convert visualization into data? Because I want to query the results of analysis&#xD;&#xA;&#xD;&#xA;[![analysisi results][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uwKxk.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7285" PostHistoryTypeId="1" PostId="3588" RevisionGUID="a3563157-ea2f-4d01-91b4-4286e5e2a620" CreationDate="2016-06-09T12:53:14.763" UserId="4513" Text="How to convert image results into data?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7286" PostHistoryTypeId="3" PostId="3588" RevisionGUID="a3563157-ea2f-4d01-91b4-4286e5e2a620" CreationDate="2016-06-09T12:53:14.763" UserId="4513" Text="|raytracing|3d|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7287" PostHistoryTypeId="2" PostId="3589" RevisionGUID="857e2444-b76f-4699-a66a-38acd42e6bac" CreationDate="2016-06-09T15:43:51.957" UserId="2654" Text="Learning graphics programming is about more than just learning APIs. It's about learning how graphics works. Vertex transformations, lighting models, shadow techniques, texture mapping, deferred rendering, and so forth. These have absolutely nothing to do with the API you use to implement them.&#xD;&#xA;&#xD;&#xA;So the question is this: do you want to learn how to use an API? Or do you want to learn *graphics*?&#xD;&#xA;&#xD;&#xA;In order to do stuff with hardware-accelerated graphics, you have to learn how to use an API to access that hardware. But once you have the ability to interface with the system, your graphics learning stops focusing on what the API does for you and instead focuses on graphics concepts. Lighting, shadows, bump-mapping, etc.&#xD;&#xA;&#xD;&#xA;If your goal is to learn graphics concepts, the time you're spending with the API is time you're not spending *learning graphics concepts*. How to compile shaders has nothing to do with graphics. Nor does how to send them uniforms, how to upload vertex data into buffers, etc. These are tools, and important tools for doing graphics work.&#xD;&#xA;&#xD;&#xA;But they aren't actually graphics concepts. They are a means to an end.&#xD;&#xA;&#xD;&#xA;It takes a *lot* of work and learning with Vulkan before you can reach the point where you're ready to start learning graphics concepts. Passing data to shaders requires explicit memory management and explicit synchronization of access. And so forth.&#xD;&#xA;&#xD;&#xA;By contrast, getting to that point with OpenGL requires less work. And yes, I'm talking about modern, shader-based core-profile OpenGL.&#xD;&#xA;&#xD;&#xA;Just compare what it takes to do something as simple as clearing the screen. In Vulkan, this requires at least some understanding of a large number of concepts: command buffers, device queues, memory objects, images, and the various WSI constructs.&#xD;&#xA;&#xD;&#xA;In OpenGL... it's three functions: `glClearColor`, `glClear`, and the platform-specific swap buffers call. If you're using more modern OpenGL, you can get it down to two: `glClearBufferuiv` and swap buffers. You don't need to know what a framebuffer is or where its image comes from. You clear it and swap buffers.&#xD;&#xA;&#xD;&#xA;Because OpenGL hides a lot from you, it takes a lot less effort to get to the point where you're actually learning graphics as opposed to learning the interface to graphics hardware.&#xD;&#xA;&#xD;&#xA;Furthermore, OpenGL is a (relatively) safe API. It will issue errors when you do something wrong, usually. Vulkan is not. While there are debugging layers that you can use to help, the core Vulkan API will tell you almost nothing unless there is a hardware fault. If you do something wrong, you can get garbage rendering or crash the GPU.&#xD;&#xA;&#xD;&#xA;Coupled with Vulkan's complexity, it becomes very easy to accidentally do the wrong thing. Forgetting to set a texture to the right layout may work under one implementation, but not another. Forgetting a sychronization point may work sometimes, but then suddenly fail for seemingly no reason. And so forth.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;All that being said, there is more to learning graphics than learning graphical techniques. There's one area in particular where Vulkan wins.&#xD;&#xA;&#xD;&#xA;Graphical *performance*.&#xD;&#xA;&#xD;&#xA;Being a 3D graphics programmer usually requires some idea of how to optimize your code. And it is here where OpenGL's hiding of information and doing things behind your back becomes a problem.&#xD;&#xA;&#xD;&#xA;The OpenGL memory model is synchronous. The implementation is allowed to issue commands asynchronously so long as the user cannot tell the difference. So if you render to some image, then try to read from it, the implementation must issue an explicit synchronization event between these two tasks.&#xD;&#xA;&#xD;&#xA;But in order to achieve performance in OpenGL, you have to know that implementations do this, so that you can *avoid it*. You have to realize where the implementation is secretly issuing synchronization events, and then rewrite your code to avoid them as much as possible. But the API itself doesn't make this obvious; you have to have gained this knowledge from somewhere.&#xD;&#xA;&#xD;&#xA;With Vulkan... *you* are the one who has to issue those synchronization events. Therefore, you *must* be aware of the fact that the hardware does not execute commands synchronously. You must know when you need to issue those events, and therefore you must be aware that they will probably slow your program down. So you do everything you can to avoid them.&#xD;&#xA;&#xD;&#xA;An explicit API like Vulkan forces you to make these kinds of performance decisions. And therefore, if you learn the Vulkan API, you already have a good idea about what things are going to be slow and what things are going to be fast.&#xD;&#xA;&#xD;&#xA;If you have to do some framebuffer work that forces you to create a new renderpass... odds are good that this will be slower than if you could fit it into a separate subpass of a renderpass. That doesn't mean you can't do that, but the API tells you up front that it could cause a performance problem.&#xD;&#xA;&#xD;&#xA;In OpenGL, the API basically invites you to change your framebuffer attachments willy-nilly. There's no guidance on which changes will be fast or slow.&#xD;&#xA;&#xD;&#xA;So in that case, learning Vulkan can help you better learn about how to make graphics faster. And it will certainly help you reduce CPU overhead.&#xD;&#xA;&#xD;&#xA;It'll still take much longer before you can get to the point where you can learn graphical rendering techniques." ContentLicense="CC BY-SA 3.0" />
  <row Id="7288" PostHistoryTypeId="6" PostId="3580" RevisionGUID="d96f96b7-3edc-45eb-acb4-cdae0cdeaa23" CreationDate="2016-06-09T15:53:08.310" UserId="2479" Comment="Added tags" Text="|color|pixel-graphics|color-management|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7289" PostHistoryTypeId="24" PostId="3580" RevisionGUID="d96f96b7-3edc-45eb-acb4-cdae0cdeaa23" CreationDate="2016-06-09T15:53:08.310" Comment="Proposed by 2479 approved by 310, 209 edit id of 142" ContentLicense="CC BY-SA 3.0" />
  <row Id="7290" PostHistoryTypeId="5" PostId="3581" RevisionGUID="0dad377a-7232-4766-9016-955f4bfb4b78" CreationDate="2016-06-09T16:13:28.647" UserId="3420" Comment="added 353 characters in body" Text="You should be learning OpenGL first, as that is the standard for Graphics, across so many platforms.&#xD;&#xA;&#xD;&#xA;Even if there is a newer library, understanding the basics, and working with a language that is used all over the industry, is very important... Especially since Vulkan wont be used in Big Companies for awhile, since.&#xD;&#xA;&#xD;&#xA;1.  No one wants to adapt right away and end up screwing themselves over with a non-stable Framework/Library.&#xD;&#xA;&#xD;&#xA;2.  They would need to hire / re-train their current Open-GL programmers, and there is no need to.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;------------------------------&#xD;&#xA;&#xD;&#xA;Also, I've heard that OpenGL, and Vulkan, aren't exactly the same.  I hear Vulkan is a lower level API, and closer to machine code, than OpenGL.&#xD;&#xA;&#xD;&#xA;This answer I just found seems to have a lot of great info&#xD;&#xA;&#xD;&#xA;http://gamedev.stackexchange.com/questions/96014/what-is-vulkan-and-how-does-it-differ-from-opengl&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------------------&#xD;&#xA;&#xD;&#xA;Another thing that is something to consider is the issue that happened back with OpenGL 1.&#xD;&#xA;&#xD;&#xA;OpenGL 1 to OpenGL 2 had MAJOR changes, and since many people were using OpenGL1, and hardware supported it, there is heavy backwards compatibility needed to be implemented in some applications/engines, and that sometimes is really painful for the devs to keep supporting it.&#xD;&#xA;&#xD;&#xA;Besides the support, the language shifted so much, that you had to learn new stuff.&#xD;&#xA;&#xD;&#xA;This has happened with frameworks such as JavaFX (from 1.x to 2.x) and Play! Framework (Also 1.x to 2.x).  Complete changes to the framework, meaning we have to relearn... everything...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;--------------------------------------&#xD;&#xA;&#xD;&#xA;So essentially what you should do is wait until Vulkan is STABLE.  That means wait until Probably the 2.0 patch.  IT doesn't mean you cannot learn about the basics of Vulkan, but just know this might change.  I would assume that a group like Kronos would provide a very stable API from the start, especially since there are multiple Nvidia and AMD engineers working on Vulkan, including a high up Nvidia person overseeing the project apparently, as well as The base of Mantle; however, like any software, we the coders will see how well it works from the start, but many are wary and waiting to see what happens.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7291" PostHistoryTypeId="2" PostId="3590" RevisionGUID="6508103e-1ac0-4f81-8966-8fcc56732fef" CreationDate="2016-06-09T16:20:01.487" UserId="182" Text="Because your monitor is not properly calibrated.&#xD;&#xA;&#xD;&#xA;On my screen at home the top and bottom parts have the same hue. At my office though, the top part tends to looks a bit yellow compared to the bottom part that looks more red.&#xD;&#xA;&#xD;&#xA;The difference: my screen at home was from a series that was decently calibrated out of the factory, and on top of that I did calibrate it properly with a color calibration tool. That was quite some years ago and its colors have probably degraded since, but it still makes a difference.&#xD;&#xA;&#xD;&#xA;A poorly calibrated monitor will not display exactly the color intensity requested for R, G and B, resulting in differences between the color that should be displayed and the one actually displayed. It can even vary depending the area of the screen (many consumer level LCD screens tend to have more light leaking near the edges for example).&#xD;&#xA;&#xD;&#xA;The image you included is a good example to highlight a calibration issue, because it allows to compare directly the average color at 50% intensity (combining two halves at 0% and 100% intensity) with the color displayed when requesting 50% intensity. Moreover, the gradient allows to see if the hue is constant from 0% to 100% intensity." ContentLicense="CC BY-SA 3.0" />
  <row Id="7292" PostHistoryTypeId="2" PostId="3591" RevisionGUID="e0567920-2319-44b0-bdeb-4d162e6f5acf" CreationDate="2016-06-09T16:33:53.057" UserId="273" Text="I think getting the real data with high precision is not easy without some API.&#xD;&#xA;The first idea would be just to manually use some color based selection tool that you can tell to select all areas in the screenshots according to the lookup table.&#xD;&#xA;But that would not result in some 3D data, but only segmented images where you can annotate the values.&#xD;&#xA;&#xD;&#xA;Another method would be to make a UV-map of the mesh, and then by making screenshots from various regions try to extract the color-coded texture.&#xD;&#xA;Then you could read the interpolated color-values of the texture and map them back to the actual values.&#xD;&#xA;&#xD;&#xA;The last but maybe strangest idea would be to make a huge number of screenshots and then use some multiview object reconstruction algorithm (I don't know if there is software or if you have to write it yourself.). There are algorithms that not only reconstruct the geometry, but also the texture.&#xD;&#xA;This would then give you a model with the color-texture that again you could map back to the values.&#xD;&#xA;&#xD;&#xA;But ideally there would be some export function in the software you used. Maybe this is a question you should ask the developer of the software. Maybe they have this function somehow but it is a bit hidden." ContentLicense="CC BY-SA 3.0" />
  <row Id="7297" PostHistoryTypeId="2" PostId="3593" RevisionGUID="9136c6ad-8896-4e14-967f-ab4963ff28ad" CreationDate="2016-06-10T13:59:01.767" UserId="3472" Text="I know there are tons of questions about it, but I found nothing useful so far so, here I am.&#xD;&#xA;&#xD;&#xA;I'm trying to render a texture which is attached to a wavefront .obj mesh. I continued to fail (somehow, it was like textures were not correctly loaded), so I wrote a simple example code to see where I was wrong. The sample code follows, and the texture is &quot;correctly&quot; loaded and rendered. However, there are some problems in the render itself: the image is incomplete / blurry / repeated / distorted. I will also post the expected result and the actual result.&#xD;&#xA;&#xD;&#xA;Working on Linux Ubuntu 14.04, OpenGL 3.0 Mesa 10.5.9.&#xD;&#xA;Any idea of what is happening?&#xD;&#xA;&#xD;&#xA;Texture (copyright Angryfly @ Turbosquid) and result on the right:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Sample code:&#xD;&#xA;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    #include &lt;GL/glu.h&gt;&#xD;&#xA;    #include &lt;SDL2/SDL.h&gt;&#xD;&#xA;    #include &lt;SDL2/SDL_image.h&gt;&#xD;&#xA;    #include&lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char* argv[]) {&#xD;&#xA;    	SDL_Init( SDL_INIT_VIDEO );&#xD;&#xA;    	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );&#xD;&#xA;    	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );&#xD;&#xA;        // prepare the window&#xD;&#xA;    	SDL_Window *window = SDL_CreateWindow(argv[0], 0, 0,&#xD;&#xA;    			800, 600,&#xD;&#xA;    			SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);&#xD;&#xA;    	SDL_GLContext context = SDL_GL_CreateContext(window);&#xD;&#xA;        // enable textures and bind a name (say 50)&#xD;&#xA;    	glEnable(GL_TEXTURE_2D);&#xD;&#xA;    	glBindTexture(GL_TEXTURE_2D, 50);&#xD;&#xA;    &#xD;&#xA;    	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,&#xD;&#xA;    	                 GL_LINEAR_MIPMAP_NEAREST );&#xD;&#xA;    	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;    	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );&#xD;&#xA;    	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );&#xD;&#xA;        // load image with SDL&#xD;&#xA;    	SDL_Surface *s = IMG_Load(&quot;texture.png&quot;);&#xD;&#xA;    	// the following doesn't work (white space)&#xD;&#xA;        //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, s-&gt;w, s-&gt;h, 0, GL_RGB, GL_UNSIGNED_BYTE, s-&gt;pixels);&#xD;&#xA;    	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, s-&gt;w, s-&gt;h, GL_RGB, GL_UNSIGNED_BYTE, s-&gt;pixels);&#xD;&#xA;    &#xD;&#xA;    	glViewport(0, 0, 800, 600);&#xD;&#xA;    	glClearColor(1,1,1,1);&#xD;&#xA;    	glMatrixMode(GL_PROJECTION);&#xD;&#xA;    	glLoadIdentity();&#xD;&#xA;    	gluPerspective(70, 0.75, 0.2, 1000);&#xD;&#xA;    &#xD;&#xA;    	glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    	glLoadIdentity();&#xD;&#xA;    	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );&#xD;&#xA;    	gluLookAt(0, 10, 0, 0, 0, 0, 1, 0, 0);&#xD;&#xA;    &#xD;&#xA;    	glActiveTexture(50);&#xD;&#xA;        // display texture as 2 triangles.&#xD;&#xA;    	glBegin(GL_TRIANGLES);&#xD;&#xA;    	glTexCoord2d(0,0); glVertex3d(-5, 0, -5);&#xD;&#xA;    	glTexCoord2d(0,1); glVertex3d(-5, 0, 5);&#xD;&#xA;    	glTexCoord2d(1,0); glVertex3d(5, 0, -5);&#xD;&#xA;    &#xD;&#xA;    	glTexCoord2d(0,1); glVertex3d(-5, 0, 5);&#xD;&#xA;    	glTexCoord2d(1,0); glVertex3d(5, 0, -5);&#xD;&#xA;    	glTexCoord2d(1,1); glVertex3d(5, 0, 5);&#xD;&#xA;    &#xD;&#xA;    	glEnd();&#xD;&#xA;    	glFinish();&#xD;&#xA;    	SDL_GL_SwapWindow(window);&#xD;&#xA;        // wait for quit procedure&#xD;&#xA;    	SDL_Quit();&#xD;&#xA;    	return 0;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9VeLs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7298" PostHistoryTypeId="1" PostId="3593" RevisionGUID="9136c6ad-8896-4e14-967f-ab4963ff28ad" CreationDate="2016-06-10T13:59:01.767" UserId="3472" Text="Texture rendering in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="7299" PostHistoryTypeId="3" PostId="3593" RevisionGUID="9136c6ad-8896-4e14-967f-ab4963ff28ad" CreationDate="2016-06-10T13:59:01.767" UserId="3472" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7300" PostHistoryTypeId="2" PostId="3594" RevisionGUID="6d5ac9ed-537f-400b-828e-cb2742e552d5" CreationDate="2016-06-10T14:16:48.143" UserId="4544" Text="Cone Step Mapping and Relaxed Cone Step Mapping appear to be very decent algorithms. These rely on a bit of preprocessing of the height field to create a 2D map used for more efficient lookups.&#xD;&#xA;&#xD;&#xA;http://www.lonesock.net/files/ConeStepMapping.pdf&#xD;&#xA;http://http.developer.nvidia.com/GPUGems3/gpugems3_ch18.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7301" PostHistoryTypeId="2" PostId="3595" RevisionGUID="0391f6f4-cdbd-421c-a5f6-034c27a4350a" CreationDate="2016-06-10T14:19:06.340" UserId="4543" Text="I'm trying to write a mesh deformer that bends a Cube around an axis like this:&#xD;&#xA;&#xD;&#xA;![3D Bend](https://i.stack.imgur.com/5pDaI.png)&#xD;&#xA;&#xD;&#xA;The bend degree in figure A is 90 and something like 35 in B. So if I know my desired bend degree how can I get alpha?&#xD;&#xA;&#xD;&#xA;I know that the distance between the vertices v1 and v2 stays the same and that i basically just have to rotate the edge alpha degrees. I can't figure out where the center of the Circle has to be, so that the bend looks organic." ContentLicense="CC BY-SA 3.0" />
  <row Id="7302" PostHistoryTypeId="1" PostId="3595" RevisionGUID="0391f6f4-cdbd-421c-a5f6-034c27a4350a" CreationDate="2016-06-10T14:19:06.340" UserId="4543" Text="Implement own Bend function" ContentLicense="CC BY-SA 3.0" />
  <row Id="7303" PostHistoryTypeId="3" PostId="3595" RevisionGUID="0391f6f4-cdbd-421c-a5f6-034c27a4350a" CreationDate="2016-06-10T14:19:06.340" UserId="4543" Text="|3d|mesh|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7307" PostHistoryTypeId="5" PostId="3579" RevisionGUID="f00d4298-1bba-41f6-8011-49b8fbfe754f" CreationDate="2016-06-10T16:00:06.960" UserId="2041" Comment="Add a paragraph addressing concerns that Vulkan is too hard for beginners." Text="If you're getting started now, and you want to do GPU work (as opposed to always using a game engine such as Unity), you should definitely start by learning Vulkan. Maybe you should learn GL later too, but there are a couple of reasons to think Vulkan-first.&#xD;&#xA;&#xD;&#xA;1. GL and GLES were designed many years ago, when GPUs worked quite differently. (The most obvious difference being immediate-mode draw calls vs tiling and command queues.) GL encourages you to think in an immediate-mode style, and has a lot of legacy cruft. Vulkan offers programming models that are much closer to how contemporary GPUs work, so if you learn Vulkan, you'll have a better understanding of how the technology really works, and of what is efficient and what is inefficient. I see lots of people who've started with GL or GLES and immediately get into bad habits like issuing separate draw calls per-object instead of using VBOs, or even worse, using display lists. It's hard for GL programmers to find out what is no longer encouraged.&#xD;&#xA;&#xD;&#xA;2. It's much easier to move from Vulkan to GL or GLES than vice-versa. Vulkan makes explicit a lot of things that were hidden or unpredictable in GL, such as concurrency control, sharing, and rendering state. It pushes a lot of complexity up from the driver to the application: but by doing so, it gives control to the application, and makes it simpler to get predictable performance and compatibility between different GPU vendors. If you have some code that works in Vulkan, it's quite easy to port that to GL or GLES instead, and you end up with something that uses good GL/GLES habits. If you have code that works in GL or GLES, you almost have to start again to make it work efficiently in Vulkan: especially if it was written in a legacy style (see point 1).&#xD;&#xA;&#xD;&#xA;I was concerned at first that Vulkan is much harder to program against, and that while it would be OK for the experienced developers at larger companies, it would be a huge barrier to indies and hobbyists. I posed this question to some members of the Working Group, and they said they have some data points from people they've spoken to who've already moved to Vulkan. These people range from developers at Epic working on UE4 integration to hobbyist game developers. Their experience was that getting started (i.e. getting to having one triangle on the screen) involved learning more concepts and having longer boilerplate code, but it wasn't too complex, even for the indies. But after getting to that stage, they found it much easier to build up to a real, shippable application, because (a) the behaviour is a lot more predictable between different vendors' implementations, and (b) getting to something that performed well with all the effects turned on didn't involve as much trial-and-error. With these experiences from real developers, they convinced me that programming against Vulkan is viable even for a beginner in graphics, and that the overall complexity is less once you get past the tutorial and starting building demos or applications you can give to other people.&#xD;&#xA;&#xD;&#xA;As others have said: GL is available on many platforms, WebGL is a nice delivery mechanism, there's a lot of existing software that uses GL, and there are many employers hiring for that skill. It's going to be around for the next few years while Vulkan ramps up and develops an ecosystem. For these reasons, you'd be foolish to rule out learning GL entirely. Even so, you'll have a much easier time with it, and become a better GL programmer (and a better GPU programmer in general), if you start off with something that helps you to understand the GPU, instead of understanding how they worked 20 years ago.&#xD;&#xA;&#xD;&#xA;Of course, there's one option more. I don't know whether this is relevant to you in particular, but I feel I should say it for the other visitors anyway.&#xD;&#xA;&#xD;&#xA;To be an indie games developer, or a game designer, or to make VR experiences, you don't need to learn Vulkan or GL. Many people get started with a games engine (Unity or UE4 are popular at the moment). Using an engine like that will let you focus on the experience you want to create, instead of the technology behind it. It will hide the differences between GL and Vulkan from you, and you don't need to worry about which is supported on your platform. It'll let you learn about 3D co-ordinates, transforms, lighting, and animation without having to deal with all the gritty details at once. Some game or VR studios only work in an engine, and they don't have a full-time GL expert at all. Even in larger studios which write their own engines, the people who do the graphics programming are a minority, and most of the developers work on higher-level code.&#xD;&#xA;&#xD;&#xA;Learning about the details of how to interact with a GPU is certainly a useful skill, and one that many employers will value, but you shouldn't feel like you have to learn that to get into 3D programming; and even if you know it, it won't necessarily be something you use every day." ContentLicense="CC BY-SA 3.0" />
  <row Id="7308" PostHistoryTypeId="2" PostId="3596" RevisionGUID="6296acbf-97a2-4c68-a05d-f01fda0ed0bd" CreationDate="2016-06-10T16:17:59.203" UserId="4513" Text="I want to develop a componet for 3d shadow analysis of 3d citymodel. I decided to using ray tracing for this purpose. For everytime step (for sun's dinamic position during the year) rays will be sent from sun (point light source) and with ray intersection tests surfaces which are and how long are in shadow will be determined. Ara there any components for this purpose such as sun's position, ray tracing etc. or Do I have to code everything from begining till to the end? Any answer would be very helpful " ContentLicense="CC BY-SA 3.0" />
  <row Id="7309" PostHistoryTypeId="1" PostId="3596" RevisionGUID="6296acbf-97a2-4c68-a05d-f01fda0ed0bd" CreationDate="2016-06-10T16:17:59.203" UserId="4513" Text="Components that can be used for 3d shadow analysis, sunhours of surfaces throughout the year in a 3d model?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7310" PostHistoryTypeId="3" PostId="3596" RevisionGUID="6296acbf-97a2-4c68-a05d-f01fda0ed0bd" CreationDate="2016-06-10T16:17:59.203" UserId="4513" Text="|raytracing|shadow|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7311" PostHistoryTypeId="2" PostId="3597" RevisionGUID="e69b81eb-39a1-47a5-9343-ae91d3f1c368" CreationDate="2016-06-10T16:52:28.663" UserId="273" Text="I use Nvidia OptiX for Ray casting and tracing purposes. It is based on CUDA and gives you a library that runs on GPU and is capable of building and traversing efficient acceleration structures. You just supply a few programs such as intersection tests and shading and OptiX does the rest.&#xA;I personally think it is really easy to work with it but your milage may vary.&#xA;With this it should be very doable to make your project and even with decent running speed." ContentLicense="CC BY-SA 3.0" />
  <row Id="7312" PostHistoryTypeId="2" PostId="3598" RevisionGUID="57db1946-2840-418f-9f0e-782f33dd03f6" CreationDate="2016-06-10T19:52:16.557" UserId="506" Text="The shape you’re trying to draw is called a [catenary](https://en.wikipedia.org/wiki/Catenary)—it’s the shape that a cable/cord of constant density takes when supported at each end. You’ll have to do some research to find a parametric equation for its shape—[this page](http://mathworld.wolfram.com/Catenary.html) has a start, though it doesn’t let you substitute in the endpoints so you’ll need some additional work there.&#xD;&#xA;&#xD;&#xA;Once you have an equation that gives you a point along the curve as a function `f(t) = (x,y)`, where `t` is in the range 0–1, you can draw it the same way you would any other parametric curve: step along the function from 0 to 1 in small increments, drawing individual line segments from the value of `f` at the previous increment.&#xD;&#xA;&#xD;&#xA;For nicer-looking cables, you can follow that process with a wide line in a dark color followed by a narrow line in a lighter one, draw a shadow with the same curve offset vertically in partially-transparent black, etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="7313" PostHistoryTypeId="5" PostId="3598" RevisionGUID="9d6454fc-db15-40ac-9dc9-987d3cec1306" CreationDate="2016-06-10T19:57:34.127" UserId="506" Comment="added 616 characters in body" Text="The shape you’re trying to draw is called a [catenary](https://en.wikipedia.org/wiki/Catenary): it’s the shape that a cable/cord of constant density takes when supported at each end. You’ll have to do some research to find a parametric equation for its shape—[this page](http://mathworld.wolfram.com/Catenary.html) has a start, though it doesn’t let you substitute in the endpoints so you’ll need some additional work there.&#xD;&#xA;&#xD;&#xA;Once you have an equation that gives you a point along the curve as a function `f(t) = (x,y)`, where `t` is in the range [0,1], you can draw it the same way you would any other parametric curve: step along the function from 0 to 1 in small increments, drawing individual line segments from the value of `f` at the previous increment.&#xD;&#xA;&#xD;&#xA;For nicer-looking cables, you can follow that process with a wide line in a dark color followed by a narrow line in a lighter one to give the appearance of shading, draw a shadow with the same curve offset vertically in partially-transparent black, etc.&#xD;&#xA;&#xD;&#xA;As to the patch ports themselves… you can make grids pretty easily by using an image for a single port and drawing it at regular intervals across the space you want to cover. To figure out which port a given screen position corresponds to (e.g. if the user clicks on a particular one), get that position, divide it by the size of the interval you drew the ports at, and take the ceiling of that value. In other words, if you’re drawing a port every 20 pixels and the user clicks on (42, 27), dividing each coordinate value by 20 gives you (2.1, 1.35), which ceils to (3, 2)—i.e. the third column and second row." ContentLicense="CC BY-SA 3.0" />
  <row Id="7314" PostHistoryTypeId="2" PostId="3599" RevisionGUID="94bfb299-1c6b-4c41-b939-b8a0e0f2b5bc" CreationDate="2016-06-10T19:58:16.703" UserId="2817" Text="This type of artifact is a tell-tale sign that you've messed up your texture image format at the byte level. It's hard to tell what exactly is wrong, but it's something along the lines of bad pitch or a component layout mismatch.&#xD;&#xA;&#xD;&#xA;Have a read of [this wiki page][1] and try again. `glTexImage2D` should work, keep trying until it does.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Image_Format" ContentLicense="CC BY-SA 3.0" />
  <row Id="7316" PostHistoryTypeId="6" PostId="3575" RevisionGUID="ce283790-b36b-4b82-bcd3-a8153a04488e" CreationDate="2016-06-11T01:01:18.187" UserId="2041" Comment="create Vulkan tag" Text="|opengl|api|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7317" PostHistoryTypeId="24" PostId="3575" RevisionGUID="ce283790-b36b-4b82-bcd3-a8153a04488e" CreationDate="2016-06-11T01:01:18.187" Comment="Proposed by 2041 approved by 3477 edit id of 143" ContentLicense="CC BY-SA 3.0" />
  <row Id="7319" PostHistoryTypeId="2" PostId="3600" RevisionGUID="4c0377b3-da9e-4feb-bc68-ecbfe498bb6f" CreationDate="2016-06-11T04:39:32.547" UserId="4545" Text="I have a simple question: when using a Compute Shader, is it possible to keep a buffer in the GPU memory during the whole run-time duration of the application, so whenever the Compute Shader is executed again it can use data from such buffer and/or update them?&#xD;&#xA;&#xD;&#xA;If so, what is the correct way of declaring buffers when one wants them to be permanent in GPU versus one-time-use only? If that helps, I am using CG in Unity, but an engine/language agnostic answer is fine." ContentLicense="CC BY-SA 3.0" />
  <row Id="7320" PostHistoryTypeId="1" PostId="3600" RevisionGUID="4c0377b3-da9e-4feb-bc68-ecbfe498bb6f" CreationDate="2016-06-11T04:39:32.547" UserId="4545" Text="Compute shaders: one-time-only versus persistent buffers" ContentLicense="CC BY-SA 3.0" />
  <row Id="7321" PostHistoryTypeId="3" PostId="3600" RevisionGUID="4c0377b3-da9e-4feb-bc68-ecbfe498bb6f" CreationDate="2016-06-11T04:39:32.547" UserId="4545" Text="|gpu|compute-shader|memory|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7322" PostHistoryTypeId="5" PostId="3600" RevisionGUID="e8f58492-0aa3-482e-b15a-761dc6725420" CreationDate="2016-06-11T04:47:32.840" UserId="4545" Comment="added 26 characters in body" Text="When using a Compute Shader, is it possible to keep a buffer in the GPU memory during the whole run-time duration of the application, so whenever the original Compute Shader or other Compute Shaders are executed later they can access data from such buffer and/or update them?&#xD;&#xA;&#xD;&#xA;If so, what is the correct way of declaring/referencing buffers when one wants them to be permanent in GPU versus one-time-use only? If that helps, I am using CG in Unity, but an engine/language agnostic answer is fine." ContentLicense="CC BY-SA 3.0" />
  <row Id="7323" PostHistoryTypeId="5" PostId="2347" RevisionGUID="4b516c1e-f67d-42fc-b950-b8f7bb156ef6" CreationDate="2016-06-11T08:24:30.833" UserId="3098" Comment="added 6 characters in body" Text="Another code review question.&#xD;&#xA;&#xD;&#xA;I am trying to draw an arrow to represent a vector. I have started with an unit arrow with vertices defined as follows:&#xD;&#xA;&#xD;&#xA;    //vertex data for vector with arrow    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;		//line&#xD;&#xA;		0.0f, 0.0f, 0.0f,&#xD;&#xA;		1.0f, 0.0f, 0.0f,&#xD;&#xA;&#xD;&#xA;		//arrow bases&#xD;&#xA;		0.95f, 0.01f, 0.0f,&#xD;&#xA;		0.95f,-0.01f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    GLuint indices[] = {&#xD;&#xA;		0, 1,		// Line&#xD;&#xA;		1, 2, 3    // Arrow Triangle&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I have another array that contains the actual vector start and end positions:&#xD;&#xA;&#xD;&#xA;    GLfloat lineVertices[] = {&#xD;&#xA;						&#xD;&#xA;		1.0f, 2.0f, 3.0f, //v1 start&#xD;&#xA;		3.0f, 5.0f,-5.0f, //v1 end&#xD;&#xA;&#xD;&#xA;	   -1.0f,-1.0f,-1.0f, //v2 start&#xD;&#xA;	   -3.0f, 5.0f,-10.0f //v2 end&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am trying to construct the `model` matrix to apply the transformation from `lineVertices` for each vectors on the unit arrow.&#xD;&#xA;&#xD;&#xA;    //'view', and 'projection' matrix is set out side of the loop&#xD;&#xA;	for (GLint i = 0; i &lt; sizeof(lineVertices) / sizeof(GLfloat); i += 6)&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 model;&#xD;&#xA;&#xD;&#xA;		//apply transformation&#xD;&#xA;		glm::vec3 start(lineVertices[i], lineVertices[i + 1], lineVertices[i + 2]);&#xD;&#xA;		glm::vec3 end(lineVertices[i + 3], lineVertices[i + 4], lineVertices[i + 5]);&#xD;&#xA;		glm::vec3 startToEnd = end - start;&#xD;&#xA;		GLfloat length = glm::length(startToEnd);&#xD;&#xA;&#xD;&#xA;        //translate&#xD;&#xA;		model = glm::translate(model, start);&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		//GLfloat xyAngle = glm::atan(startToEnd.z, length);&#xD;&#xA;		//GLfloat xzAngle = glm::atan(startToEnd.y, length);&#xD;&#xA;		//GLfloat yzAngle = glm::atan(startToEnd.x, length);&#xD;&#xA;&#xD;&#xA;		//model = glm::rotate(model, xyAngle, glm::vec3(1.0f, 1.0f, 0.0f));&#xD;&#xA;		//model = glm::rotate(model, xzAngle, glm::vec3(1.0f, 0.0f, 1.0f));&#xD;&#xA;		//model = glm::rotate(model, yzAngle, glm::vec3(0.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		GLfloat angleWithZ = glm::acos(startToEnd.z/length);&#xD;&#xA;		GLfloat angleWithY = glm::acos(startToEnd.y/length);&#xD;&#xA;		GLfloat angleWithX = glm::acos(startToEnd.x/length);&#xD;&#xA;&#xD;&#xA;		model = glm::rotate(model, angleWithX, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithY, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithZ, glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;		//scale&#xD;&#xA;		model = glm::scale(model, glm::vec3(length));&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			&#xD;&#xA;		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Though this seems to work, as I can see all those arrows, however, I am not sure whether this is the right implementation or not. Please let me know, if this is correct and/or there is room for improvement, or there are easier ways to achieve this, and so on.&#xD;&#xA;&#xD;&#xA;**Edit:** updated my code sample (only the rotation part) based on [Direction cosine (wikipedia)][1]. Old code is still kept commented. &#xD;&#xA;&#xD;&#xA;P.S.: this implementation is based on following stack exchange discussions: [1][2], [2][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Direction_cosine&#xD;&#xA;  [2]: http://gamedev.stackexchange.com/a/96960/82355&#xD;&#xA;  [3]: http://math.stackexchange.com/a/799812/298948" ContentLicense="CC BY-SA 3.0" />
  <row Id="7327" PostHistoryTypeId="2" PostId="3602" RevisionGUID="e12f837c-aba0-41c9-8506-250b077d7db7" CreationDate="2016-06-11T15:13:56.427" UserId="67" Text="My understanding is that in 5.4, instancing will use API calls like glDrawElementsInstanced and shaders need to be modified for instance buffers like in this document: https://docs.google.com/document/d/1RS6cVjE8mBVOKqQUuXbaZcPW3kmw3ZWySJwr-5rDwSs/edit&#xD;&#xA;&#xD;&#xA;&gt; UNITY_INSTANCING_CBUFFER_START (MyProperties)&#xD;&#xA;&#xD;&#xA;&gt; UNITY_DEFINE_INSTANCED_PROP (float4, _Color)&#xD;&#xA;&#xD;&#xA;&gt; UNITY_INSTANCING_CBUFFER_END&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7330" PostHistoryTypeId="2" PostId="3603" RevisionGUID="7c385712-d13e-4a79-8800-ebad65c320ea" CreationDate="2016-06-12T08:01:32.257" UserId="1937" Text="Yes, it's totally possible, and in fact it's preferable to keep buffers in memory if you will be accessing them over the life of your program, rather than deallocating and reallocating them again.&#xD;&#xA;&#xD;&#xA;I can't speak for Unity's way of allocating persistent buffers - I work with Unity and do a lot of shader writing in Cg, but most of our stuff is on mobile so compute shaders aren't an option. However, from a recent project I did using OpenGL, a buffer will generally hang around until you tell it not to, and even then, it is not in any way guaranteed to release the memory in a timely manner.&#xD;&#xA;&#xD;&#xA;Allocating a buffer in modern OpenGL is done by calling glCreateBuffers and passing it a pointer to a GLuint array which will store your buffer 'names', then calling glBufferData or glBufferStorage to actually allocate and populate the VRAM for that buffer. Calling glBufferData a second time on the same buffer name will allocate new storage for that buffer, and the original storage will be 'orphaned'. It's kind of like reallocating an object in Java, the variable name will no longer point to that object, but other parts of the system may still have references to it (e.g. if it's still being used for a texture read somewhere), so it will not be eligible for cleanup until all references to it are gone.&#xD;&#xA;&#xD;&#xA;Calling glDeleteBuffers with the buffer name has a similar effect but without allocating new storage. In both cases, the storage will *not* be deleted until absolutely all references to it within the system are gone. Even then, it is more like Java's garbage collection than C++'s delete, the system may well hold on to the memory for quite some time in order to reuse it for any future allocations you may make.&#xD;&#xA;&#xD;&#xA;The upshot of all this is it's often better to allocate buffers once when you launch your app and cycle different data through them as needed. In OpenGL, a buffer will persist for the lifetime of the application unless you explicitly delete or reallocate it. Unity's rendering system has its own quirks as I'm sure you're aware, but in principle it should behave similarly." ContentLicense="CC BY-SA 3.0" />
  <row Id="7333" PostHistoryTypeId="5" PostId="3584" RevisionGUID="5efc3c8d-cdf0-4b08-885e-2e209c32a51a" CreationDate="2016-06-13T08:18:36.273" UserId="182" Comment="Added pretty print." Text="This is my code of the algorithm for making triangles :-&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-java --&gt;&#xD;&#xA;&#xD;&#xA;    private void sort(){&#xD;&#xA;		int temp = Math.round(m_Vertex1.getPosition().getX());&#xD;&#xA;		int temp2 = Math.round(m_Vertex2.getPosition().getX());&#xD;&#xA;		int temp3 = Math.round(m_Vertex3.getPosition().getX());&#xD;&#xA;		&#xD;&#xA;		m_minX = Math.min(temp3, Math.min(temp, temp2));	//Sorting the X values&#xD;&#xA;		m_maxX = Math.max(temp3, Math.max(temp, temp2));&#xD;&#xA;		&#xD;&#xA;		temp = Math.round(m_Vertex1.getPosition().getY()); &#xD;&#xA;		temp2 = Math.round(m_Vertex2.getPosition().getY());&#xD;&#xA;		temp3 = Math.round(m_Vertex3.getPosition().getY());&#xD;&#xA;		&#xD;&#xA;		m_minY = Math.min(temp3, Math.min(temp, temp2));	// Sorting the Y values&#xD;&#xA;		m_maxY = Math.max(temp3, Math.max(temp, temp2));&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	public void DrawTriangle(){	&#xD;&#xA;		new Line(m_Vertex1, m_Vertex2, m_display).DrawLine(Optional.of(EdgeOnePoints));		//Getting all the points on the boundary of the triangle&#xD;&#xA;		new Line(m_Vertex2, m_Vertex3, m_display).DrawLine(Optional.of(EdgeTwoPoints));&#xD;&#xA;		new Line(m_Vertex1, m_Vertex3, m_display).DrawLine(Optional.of(EdgeThreePoints));&#xD;&#xA;	&#xD;&#xA;		Vector2D start = Vector2D.zero();&#xD;&#xA;		Vector2D end = Vector2D.zero();&#xD;&#xA;		&#xD;&#xA;		for(float i = m_minY; i &lt;= m_maxY ;i++){		//Iterating from top to bottom of the triangle&#xD;&#xA;			&#xD;&#xA;			for(float j = m_minX; j &lt;= m_maxX; j++){	//Iterating left to right of the triangle&#xD;&#xA;				Vector2D temp = new Vector2D(j,i);&#xD;&#xA;				&#xD;&#xA;				if(EdgeOnePoints.contains(temp)	|| EdgeTwoPoints.contains(temp) || EdgeThreePoints.contains(temp)){  &#xD;&#xA;					if(start.equals(Vector2D.zero())){		// Getting the first point of intersection between the triangle and the scanline &#xD;&#xA;						start = temp;&#xD;&#xA;					}else{&#xD;&#xA;						if(EdgeOnePoints.contains(start) &amp;&amp; !EdgeOnePoints.contains(temp)){		// Checking if start point and end point are on the same edge or not, if not then it is a valid point else not.&#xD;&#xA;							end = temp;&#xD;&#xA;							break;&#xD;&#xA;						}else if(EdgeTwoPoints.contains(start) &amp;&amp; !EdgeTwoPoints.contains(temp)){&#xD;&#xA;							end = temp;&#xD;&#xA;							break;&#xD;&#xA;						}else if(EdgeThreePoints.contains(start) &amp;&amp; !EdgeThreePoints.contains(temp)){&#xD;&#xA;							end = temp;&#xD;&#xA;							break;&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			&#xD;&#xA;			if(!start.equals(Vector2D.zero()) &amp;&amp; !end.equals(Vector2D.zero())){	//if both start and end points are available then draw then fill all the points in between them.&#xD;&#xA;				for(float j = start.getX(); j &lt;= end.getX(); j++){&#xD;&#xA;					new Point(new Vector2D(j, i), PixelData.white(), m_display).DrawPoint();&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			&#xD;&#xA;			start = Vector2D.zero(); &#xD;&#xA;			end = Vector2D.zero();   &#xD;&#xA;		}&#xD;&#xA;	} &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now i have couple of problems with it :- &#xD;&#xA;&#xD;&#xA;1. It is a tortoise, i have tested it on a old machine and just with 2 rotating triangles, the frame rate is below 30.&#xD;&#xA;&#xD;&#xA;2. i get this weird line in between the triangle at some specific position when rotating the triangle.&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6KsEH.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I don't care much about the second problem but can anyone help me making this algorithm fast. should i use something like flood fill or boundary fill algorithm ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7334" PostHistoryTypeId="2" PostId="3604" RevisionGUID="9a3757d1-b5c6-45fa-a0ff-068d094e2a65" CreationDate="2016-06-13T08:21:17.957" UserId="2041" Text="It's easy to work out if you consider not that case but the angle at v3 (if the &quot;cube&quot; were continued past v3). By the time you get to v3, the angle is simply the desired bend angle. (That's not quite right, though: because you've got alpha on the decreasing side, it's 90 degrees minus the desired angle.) You have to split that angle equally among all the segments going along the bend direction, so the angle alpha is simply 90 degrees minus (the desired angle divided by the number of vertices). So for A, where the requested angle is 90 degrees, each vertex gets a third of that angle: alpha is (90 - 30) degrees.&#xD;&#xA;&#xD;&#xA;For cube B, if the total bend is 35 degrees, each vertex gets just over 11 degrees, so alpha is just under 79 degrees.&#xD;&#xA;&#xD;&#xA;This **doesn't** generalise to an arbitrary axis, though. It only works for bends like those in your diagram. For a more general (and more useful!) tool, it makes more sense to simply apply a 2D rotation (about the axis) to each vertex independently. Exactly what rotation to apply depends on some design decisions about how the bend should behave when the axis goes through the mesh, and how strong a bend you want to allow. The crucial point is that it's not the same rotation for every vertex: the rotation is proportional to the perpendicular distance from the vertex to the neutral line of the transformation. In your example, the neutral line is the bottom edge of each cube." ContentLicense="CC BY-SA 3.0" />
  <row Id="7335" PostHistoryTypeId="2" PostId="3605" RevisionGUID="8100b030-68a4-445d-8efd-1488a7cc5ffc" CreationDate="2016-06-13T09:06:23.813" UserId="4556" Text="At first: I already posted this on the stackoverflow community. I'm new and didn't know about this community here. I apologize.&#xD;&#xA;&#xD;&#xA;I basically got the same question as the guy who asked here: http://stackoverflow.com/questions/36457138/dynamically-sized-arrays-in-opengl-es-vertex-shader-used-for-blend-shapes-morph.&#xD;&#xA;Especially his last unanswered question bothers me too.&#xD;&#xA;&#xD;&#xA;So I also want to use an arbitrary number of blendshapes for each mesh I'm processing. At the moment I'm using a fixed number and treat the shapes as vertex attribute. The advantage here is that I always have the relevant data for the current vertex availiable. Now, if I want to use an arbitrary number of shapes, I figured I'd use SSBOs since their clue is exactly what I want: Dynamically sized data. However SSBOs are, as far as I understand it, static and for each processed vertex in the shader I have the blendshape data for the whole mesh availiable. That means I would have to introduce some kind of counter and try to pick the correct data piece out of my SSBO for each vertex.&#xD;&#xA;&#xD;&#xA;Is this understanding correct? I'm really not sure whether this is the optimal solution, maybe you can give me some hints.&#xD;&#xA;&#xD;&#xA;Thank you for your answers!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7336" PostHistoryTypeId="1" PostId="3605" RevisionGUID="8100b030-68a4-445d-8efd-1488a7cc5ffc" CreationDate="2016-06-13T09:06:23.813" UserId="4556" Text="Open GL Shader Storage Buffer Objects to replace Vertex Attributes" ContentLicense="CC BY-SA 3.0" />
  <row Id="7337" PostHistoryTypeId="3" PostId="3605" RevisionGUID="8100b030-68a4-445d-8efd-1488a7cc5ffc" CreationDate="2016-06-13T09:06:23.813" UserId="4556" Text="|opengl|shader|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7338" PostHistoryTypeId="2" PostId="3606" RevisionGUID="15edafc9-55dd-431e-9aa4-27ead1e18609" CreationDate="2016-06-13T09:44:32.683" UserId="137" Text="The counter you want is built in the shader as `gl_vertexID`. &#xD;&#xA;&#xD;&#xA;However you have 16 attributes of 4 components each to work with. Take 2 components for the texture coordinates and you have 62 float values to play with. If you need 6 components per blend shape (3 pos + 3 normal) you get 10 blend shapes to work with per object per frame. If you leave off the normal as static then you get up to 19 shapes.&#xD;&#xA;&#xD;&#xA;Times when you want to blend between more than 10 shapes should be very rare. And even then you can probably get away with making another shape to get the resulting shape you want." ContentLicense="CC BY-SA 3.0" />
  <row Id="7339" PostHistoryTypeId="2" PostId="3607" RevisionGUID="efa5c8fa-6640-4bac-ac5d-b60b08736a2a" CreationDate="2016-06-13T10:28:12.603" UserId="1981" Text="##α = 90° - β/4&#xD;&#xA;&#xD;&#xA;Lets call the bend angle `β`.&#xD;&#xA;The math is quite easy after following observation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;We can draw a perpendicular bisector `middle-&gt;w` of the isoscles triangle `v1-&gt;middle-&gt;v2`. Then the anlge at `v1` is the desired `α`, the angle at `w` is `90°` and the angle at `middle` is just `β/4`. &#xD;&#xA;&#xD;&#xA;By the [triangle postulate](https://en.wikipedia.org/wiki/Sum_of_angles_of_a_triangle) the sum of the interior angles of a triangle is `180°`. By applying this to our new triangle we get&#xD;&#xA; `180° = α + 90° + β/4`, so we get &#xD;&#xA;&#xD;&#xA;##α = 90° - β/4&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xv0WO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7340" PostHistoryTypeId="2" PostId="3608" RevisionGUID="60b824ac-b68c-4179-b37a-b7aca8bd49ad" CreationDate="2016-06-13T16:31:08.373" UserId="4558" Text="While investigating the inner workings of perlin noise, I wondered why one would use perlin noise instead of simple value noise. As far as I understand it right, the following applies:&#xD;&#xA;&#xD;&#xA;Perlin noise is a lattice based noise function, which assigns a n-dimensional gradient (random for the original implementation, fixed for the improved one) for every point in the underlying noise space. Now you can query a value for every point in space by calculating the dot product between the distance vector and the gradient vector. After that you average all values calculated and get the queried value.&#xD;&#xA;&#xD;&#xA;But isn't value noise kind of the same without using gradient vectors but random values? Since I also interpolate between values in value noise I cannot see any benefits by using an additional calculation step (the dot product) in perlin noise.&#xD;&#xA;&#xD;&#xA;So why would I use perlin noise instead of value noise? Why is perlin noise so popular?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7341" PostHistoryTypeId="1" PostId="3608" RevisionGUID="60b824ac-b68c-4179-b37a-b7aca8bd49ad" CreationDate="2016-06-13T16:31:08.373" UserId="4558" Text="benefit of perlin noise over value noise" ContentLicense="CC BY-SA 3.0" />
  <row Id="7342" PostHistoryTypeId="3" PostId="3608" RevisionGUID="60b824ac-b68c-4179-b37a-b7aca8bd49ad" CreationDate="2016-06-13T16:31:08.373" UserId="4558" Text="|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7344" PostHistoryTypeId="2" PostId="3609" RevisionGUID="af509aa9-543f-43a7-94bb-ada9c0181eda" CreationDate="2016-06-14T10:03:24.597" UserId="4558" Text="The benefit of perlin noise is the overall distribution of frequencies. Since value noise uses simple values that are interpolated, there is a higher chance, that a row of several values only differs a little. The consequence is, that some regions of your picture may contain little changes and some regions a lot of changes. &#xD;&#xA;&#xD;&#xA;By using gradients you are reducing this effect because the interpolation is not done by value but instead calculated between tangents. Now it's more difficult to have a flat curve (both tangents must be collinear).&#xD;&#xA;&#xD;&#xA;[![perlin noise vs value noise][1]][1]&#xD;&#xA;&#xD;&#xA;Source: As noted by Martin Ender the question was already posted on a different StackExchange community: see [this Math.SE post][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7kSzR.png&#xD;&#xA;  [2]: http://math.stackexchange.com/q/184121/50421" ContentLicense="CC BY-SA 3.0" />
  <row Id="7349" PostHistoryTypeId="2" PostId="3611" RevisionGUID="fe6fd10d-6fe6-4f9a-83b6-c206eb941bd3" CreationDate="2016-06-14T17:14:01.773" UserDisplayName="user4570" Text="Sorry if this is on the wrong community, wasn't sure which one would be appropriate.&#xD;&#xA;&#xD;&#xA;I have this issue I have come across in programming (don't worry - the graphical part comes in a second).&#xD;&#xA;&#xD;&#xA;I am decrementing/incrementing position x until it reaches y. However, this creates a rectangular-like path. I want position x to smoothly curve towards y (diagonally) on a 2D plane.&#xD;&#xA;&#xD;&#xA;What kind of maths would I need to achieve this? Thanks.&#xD;&#xA;Example image attached.&#xD;&#xA;&#xD;&#xA;[![Algorithm][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MMbkN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7350" PostHistoryTypeId="1" PostId="3611" RevisionGUID="fe6fd10d-6fe6-4f9a-83b6-c206eb941bd3" CreationDate="2016-06-14T17:14:01.773" UserDisplayName="user4570" Text="Move position in smooth gradient" ContentLicense="CC BY-SA 3.0" />
  <row Id="7351" PostHistoryTypeId="3" PostId="3611" RevisionGUID="fe6fd10d-6fe6-4f9a-83b6-c206eb941bd3" CreationDate="2016-06-14T17:14:01.773" UserDisplayName="user4570" Text="|algorithm|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7352" PostHistoryTypeId="2" PostId="3612" RevisionGUID="aff5ffc2-36e7-43f4-a82a-425059dc26d4" CreationDate="2016-06-14T17:33:49.510" UserId="4571" Text="I'm currently writing a software rasterizer and I'm at the point where I can draw arbitrary triangles with vertex colors and perspective correct texture mapping. I do point and directional lighting by linearly interpolating the vertex normals and it works fine, only on big triangles you can notice that the lighting is somehow distorted when viewed from a very flat angle. However, this is only visible when you're particularly looking for it but I was wondering if there is a way to have perspective correction on the normals too.&#xD;&#xA;&#xD;&#xA;For the texture coordinates and other stuff this is being done by dividing the value by W or Z. But if you divide a vector by a single number you only change its magnitude, which is useless, as I'm normalizing the vector in the end for the lighting computation. So, is there a way to do it perspective correct?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7353" PostHistoryTypeId="1" PostId="3612" RevisionGUID="aff5ffc2-36e7-43f4-a82a-425059dc26d4" CreationDate="2016-06-14T17:33:49.510" UserId="4571" Text="Perspective correct interpolation of normal values" ContentLicense="CC BY-SA 3.0" />
  <row Id="7354" PostHistoryTypeId="3" PostId="3612" RevisionGUID="aff5ffc2-36e7-43f4-a82a-425059dc26d4" CreationDate="2016-06-14T17:33:49.510" UserId="4571" Text="|3d|c++|perspective|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7355" PostHistoryTypeId="2" PostId="3613" RevisionGUID="332168a6-e2cf-4893-9c36-c0795c0fa116" CreationDate="2016-06-14T18:18:23.387" UserId="4558" Text="The math you need is linear interpolation. I think of a player sprite which moves from position X to position Y. Pseudocode:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = Y.x + t * (X.x - Y.x)&#xD;&#xA;    playerSprite.y = Y.y + t * (X.y - Y.y)&#xD;&#xA;&#xD;&#xA;where t is a value between 0.0 and 1.0 (floating point). Instead of incrementing the position components of Y you increment t till it reaches 1. When it reaches 1 the playerSprite reached point X. If t is 0, then the playerSprite is at position Y." ContentLicense="CC BY-SA 3.0" />
  <row Id="7356" PostHistoryTypeId="2" PostId="3614" RevisionGUID="97bc66f3-1685-40bc-b40b-393492954ba9" CreationDate="2016-06-14T19:37:32.353" UserId="38" Text="What you want is linear interpolation like @Tim points out. However he uses a formula that is not so easily understandable form. Basically linear interpolation is a weighted average where the weight of the first term is in range of *1-0* and the weight of the other value is *1-weight*. Literature usually uses t for the weight. A more understandable version of the formula in scientific form is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;y = t \cdot y_0 + (1-t) \cdot y_1     \quad \quad t \in [-1,1]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As code it looks like:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = t * X.x + (1-t) * Y.x &#xD;&#xA;    playerSprite.y = t * X.y + (1-t) * Y.y &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7357" PostHistoryTypeId="5" PostId="3614" RevisionGUID="4507d706-56d2-4df8-80f2-c36f34a48886" CreationDate="2016-06-14T19:57:41.907" UserId="38" Comment="edited body" Text="What you want is linear interpolation like @Tim points out. However he uses a formula that is not so easily understandable form. Basically linear interpolation is a weighted average where the weight of the first term is in range of *1-0* and the weight of the other value is *1-weight*. Literature usually uses t for the weight. A more understandable version of the formula in scientific form is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;y = t \cdot y_0 + (1-t) \cdot y_1     \quad \quad t \in [-1,1]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As code it looks like:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = t * Y.x + (1-t) * X.x &#xD;&#xA;    playerSprite.y = t * Y.y + (1-t) * X.y &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7358" PostHistoryTypeId="5" PostId="3614" RevisionGUID="8df9cab3-f405-441f-969a-49ff4ac6884a" CreationDate="2016-06-14T20:14:25.583" UserId="38" Comment="added 247 characters in body" Text="What you want is linear interpolation like @Tim points out. However he uses a formula that is not so easily understandable form. Basically linear interpolation is a weighted average where the weight of the first term is in range of *1-0* and the weight of the other value is *1-weight*. Literature usually uses t for the weight. A more understandable version of the formula in scientific form is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;y = t \cdot y_0 + (1-t) \cdot y_1     \quad \quad t \in [-1,1]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As code it looks like:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = t * Y.x + (1-t) * X.x &#xD;&#xA;    playerSprite.y = t * Y.y + (1-t) * X.y &#xD;&#xA;&#xD;&#xA;There is a simple visual interpretation of this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Visual interpretation of weights (below) and the sum of vectors and position on line (above)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Vkqaf.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="7359" PostHistoryTypeId="5" PostId="3614" RevisionGUID="bc3b2486-ccf6-4119-9ab1-58ee34da3d73" CreationDate="2016-06-14T20:21:32.030" UserId="38" Comment="deleted 1 character in body" Text="What you want is linear interpolation like @Tim points out. However he uses a formula that is not so easily understandable form. Basically linear interpolation is a weighted average where the weight of the first term is in range of *1-0* and the weight of the other value is *1-weight*. Literature usually uses t for the weight. A more understandable version of the formula in scientific form is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;y = t \cdot y_1 + (1-t) \cdot y_0     \quad \quad t \in [0,1]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As code it looks like:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = t * Y.x + (1-t) * X.x &#xD;&#xA;    playerSprite.y = t * Y.y + (1-t) * X.y &#xD;&#xA;&#xD;&#xA;There is a simple visual interpretation of this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Visual interpretation of weights (below) and the sum of vectors and position on line (above)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Vkqaf.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="7360" PostHistoryTypeId="5" PostId="3614" RevisionGUID="546e538b-ce41-4b2e-91ec-3ea397488c91" CreationDate="2016-06-15T06:52:27.357" UserId="38" Comment="edited body" Text="What you want is linear interpolation like @Tim points out. However he uses a formula that is not so easily understandable form. Basically linear interpolation is a weighted average where the weight of the first term is in range of *0-1* and the weight of the other value is *1-weight*. Literature usually uses t for the weight. A more understandable version of the formula in scientific form is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;y = t \cdot y_1 + (1-t) \cdot y_0     \quad \quad t \in [0,1]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As code it looks like:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = t * Y.x + (1-t) * X.x &#xD;&#xA;    playerSprite.y = t * Y.y + (1-t) * X.y &#xD;&#xA;&#xD;&#xA;There is a simple visual interpretation of this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Visual interpretation of weights (below) and the sum of vectors and position on line (above)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Vkqaf.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="7361" PostHistoryTypeId="5" PostId="3614" RevisionGUID="1a3d439e-01ba-4e1a-b00b-574309fc1480" CreationDate="2016-06-15T07:01:26.843" UserId="38" Comment="edited body" Text="What you want is linear interpolation like @Tim points out. However he uses a formula that is not so easily understandable form, we can refactor it differently. Basically linear interpolation is a weighted average where the weight of the first term is in range of *0-1* and the weight of the other value is *1-weight*. Literature usually uses t for the weight and y for input (y can be a scalar, vector, matrix or mostly any construct). A more understandable version of the formula in scientific form is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;y = t \cdot y_1 + (1-t) \cdot y_0     \quad \quad t \in [0,1]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As code it looks like:&#xD;&#xA;&#xD;&#xA;    playerSprite.x = t * Y.x + (1-t) * X.x &#xD;&#xA;    playerSprite.y = t * Y.y + (1-t) * X.y &#xD;&#xA;&#xD;&#xA;There is a simple visual interpretation of this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Visual interpretation of weights (below) and the sum of vectors and position on line (above)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Vkqaf.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="7363" PostHistoryTypeId="2" PostId="3615" RevisionGUID="fc4cae75-8e0a-49f9-a0e7-0ee4497ac243" CreationDate="2016-06-15T08:32:02.530" UserId="4574" Text="I have a base 3D mesh of an object that I want to texturize. I also have a 360 degrees video of the real-world object.&#xD;&#xA;&#xD;&#xA;What are good ways to use the video to texturize the mesh? Are there existing tools to do that? (paid or free)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7364" PostHistoryTypeId="1" PostId="3615" RevisionGUID="fc4cae75-8e0a-49f9-a0e7-0ee4497ac243" CreationDate="2016-06-15T08:32:02.530" UserId="4574" Text="How to texturize a 3D model from video?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7365" PostHistoryTypeId="3" PostId="3615" RevisionGUID="fc4cae75-8e0a-49f9-a0e7-0ee4497ac243" CreationDate="2016-06-15T08:32:02.530" UserId="4574" Text="|algorithm|3d|3dtexture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7366" PostHistoryTypeId="2" PostId="3616" RevisionGUID="faf4a513-3341-44a2-a3b0-b5e6f29b6cbe" CreationDate="2016-06-15T09:15:41.350" UserId="361" Text="I'm playing around with base64 embedded data URI's and tried to analyze the buffer data of the gltf box sample model, as defined in [this example here][1] (line 76).&#xD;&#xA;&#xD;&#xA;     &quot;uri&quot;: &quot;data:application/octet-stream;base64,AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUAAAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/&quot;&#xD;&#xA;&#xD;&#xA;This is the buffer data for a simple cube, here's screenshot:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But it's giving me a hard time to understand what's exactly in this buffer. As far as I know, it should contain the vertices, and maybe indices.&#xD;&#xA;&#xD;&#xA;I tried to decode the base64 and the output is *binary*. I'm lost since I have no clue how this binary is encoded or decoded. Can anyone point me how to write such buffers or at least how to read them?&#xD;&#xA;&#xD;&#xA;How do I generate my own buffers?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/master/sampleModels/Box/glTF-Embedded/Box.gltf#L76&#xD;&#xA;  [2]: https://i.stack.imgur.com/zZmqD.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7367" PostHistoryTypeId="1" PostId="3616" RevisionGUID="faf4a513-3341-44a2-a3b0-b5e6f29b6cbe" CreationDate="2016-06-15T09:15:41.350" UserId="361" Text="How to encode/decode buffer data in glTF?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7368" PostHistoryTypeId="3" PostId="3616" RevisionGUID="faf4a513-3341-44a2-a3b0-b5e6f29b6cbe" CreationDate="2016-06-15T09:15:41.350" UserId="361" Text="|vertex-buffer-object|gltf|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7369" PostHistoryTypeId="5" PostId="3615" RevisionGUID="88cb0ce7-d333-491d-9bb5-142a7c9f5aa3" CreationDate="2016-06-15T09:18:37.760" UserId="4574" Comment="added 160 characters in body" Text="I have a base 3D mesh of an object that I want to texturize. I also have a 360 degrees video of the real-world object.&#xD;&#xA;&#xD;&#xA;What are good ways to use the video to texturize the mesh? Are there existing tools to do that? (paid or free)&#xD;&#xA;&#xD;&#xA;**Edit**: I have complete control over the camera and object positions, I can measure the distances and whatever needed. I can also put markers on the object." ContentLicense="CC BY-SA 3.0" />
  <row Id="7370" PostHistoryTypeId="2" PostId="3617" RevisionGUID="ddea3940-92cd-42e6-b050-b3b0e37f3329" CreationDate="2016-06-15T10:11:34.690" UserId="1937" Text="The information you're looking for is defined in the 'accessors' and 'bufferViews' near the top of the source file you linked. &#xD;&#xA;&#xD;&#xA;Bufferviews simply divide the buffer up into sub ranges and define broadly what kind of data lives there using some obscure shortcodes. In this case, target 34963 means index data and 34962 means vertex data. So from the other parameters in the bufferviews you can see that the first 72 bytes are indices and the remaining 576 bytes are vertex data.&#xD;&#xA;&#xD;&#xA;The accessors are what actually define the format of the data and again use weird codes for &quot;componentType&quot; - 5123 is an unsigned short (2 bytes) and 5126 is single precision float (4 bytes). They also define whether they should be read singly (&quot;SCALAR&quot;) or in vector groups (e.g. &quot;VEC3&quot;), and also a starting offset into the bufferview and &quot;stride&quot; between the start of data points like regular OpenGL vertex buffer bindings.&#xD;&#xA;&#xD;&#xA;Putting it all together, the first 72 bytes are 36 shorts representing the indices (3 * 12 triangles). The next 576 bytes are two consecutive sets of 24 vec3 (4 per square face, 12 bytes per vec3) representing vertex data. Since the first set are clamped to + or - 1/2 and the second set to + or - 1, I'm guessing first set are positions, second set are normals.&#xD;&#xA;&#xD;&#xA;The base 64 encoding just takes the raw bit stream, splits it into groups of 6 rather than 8, and maps each unique 6-bit combination onto a character. You can see this is quite wasteful as each character takes at least 8 bits to store, quite possibly 16 or more depending on the encoding used. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7374" PostHistoryTypeId="2" PostId="3619" RevisionGUID="1031709c-acc2-4c91-a5c5-182f1055309b" CreationDate="2016-06-15T10:40:23.027" UserId="4577" Text="Apologies for the following noob question, it's just I can't find a satisfactory answer anywhere...&#xD;&#xA;&#xD;&#xA;When I render a simple axis-aligned quad made up of two triangles, I don't understand why there's never any visible artefacts on the diagonal edge where those triangles meet. Some of those pixels must be in both triangles, right? So if my fragshader always emits a partially-transparent color - 50% black say - then shouldn't there be a visible dark diagonal line in the resulting quad?&#xD;&#xA;&#xD;&#xA;Obviously it's great that this isn't a real problem that has to be coded around, I just don't understand why it isn't. What GPU magic is it that makes this always work out?&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="7375" PostHistoryTypeId="1" PostId="3619" RevisionGUID="1031709c-acc2-4c91-a5c5-182f1055309b" CreationDate="2016-06-15T10:40:23.027" UserId="4577" Text="Why do adjacent triangles never overlap when rasterized?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7376" PostHistoryTypeId="3" PostId="3619" RevisionGUID="1031709c-acc2-4c91-a5c5-182f1055309b" CreationDate="2016-06-15T10:40:23.027" UserId="4577" Text="|opengl|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7378" PostHistoryTypeId="2" PostId="3620" RevisionGUID="486a1884-6aba-496d-8c9e-e3472d15ece9" CreationDate="2016-06-15T10:58:46.450" UserId="209" Text="This is the same problem as discussed in [What are sample gaps during scan conversion?](https://computergraphics.stackexchange.com/questions/2484/what-are-sample-gaps-during-scan-conversion)&#xD;&#xA;&#xD;&#xA;Briefly, rasterisation - at least with the majority of hardware systems - test at a single 'infinitesimal' point for each pixel to determine if that pixel is inside a given triangle. &#xD;&#xA;&#xD;&#xA;If the sample point lies exactly on an edge, then additional tie-breaking rules, often referred to as &quot;fill rules, come in to play. Typically these will be something equivalent to, say, only consider the edge points on the top/left** edges of a triangle to be &quot;inside&quot;.&#xD;&#xA;&#xD;&#xA;**Other rules are available ;-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7379" PostHistoryTypeId="5" PostId="3620" RevisionGUID="db916870-bd8b-4799-9586-7b2b59955dff" CreationDate="2016-06-15T11:08:23.103" UserId="209" Comment="added 1 character in body" Text="This is the same problem as discussed in [What are sample gaps during scan conversion?](https://computergraphics.stackexchange.com/questions/2484/what-are-sample-gaps-during-scan-conversion)&#xD;&#xA;&#xD;&#xA;Briefly, rasterisation - at least with the majority of hardware systems - tests at a single 'infinitesimal' point for each pixel to determine if that pixel is inside a given triangle. &#xD;&#xA;&#xD;&#xA;If the sample point lies exactly on an edge, then additional tie-breaking rules, often referred to as &quot;fill rules, come in to play. Typically these will be something equivalent to, say, only consider the edge points on the top/left** edges of a triangle to be &quot;inside&quot;.&#xD;&#xA;&#xD;&#xA;**Other rules are available ;-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7380" PostHistoryTypeId="6" PostId="3619" RevisionGUID="37357f3c-ff62-4584-97d8-195306bec6e8" CreationDate="2016-06-15T11:28:14.057" UserId="209" Comment="edited tags" Text="|opengl|gpu|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7381" PostHistoryTypeId="2" PostId="3621" RevisionGUID="41953523-0c62-44cc-ab21-486609d199f7" CreationDate="2016-06-15T11:44:32.040" UserId="4578" Text="I am reading the book Physically Based Rendering (Pharr, Humphreys). In the chapter on lights, they talk about approximating the total emitted power of different kinds of lights. For example, a point light's total power is `intensity * 4 * pi`. Here 4pi represents a solid angle over the entire sphere.&#xD;&#xA;This makes sense to me because intensity * solid angle = power (or radiant flux if you will). You can see this by the units as well. Intensity is W/sr and solid angle is sr, so `W/sr * sr = W` and power is measured in watts. It checks out.&#xD;&#xA;&#xD;&#xA;However, I don't understand the corresponding calculation for the `DiffuseAreaLight`. From my understanding of the book they calculate the total power emitted from a diffuse area light as `emitted radiance * area * pi`.&#xD;&#xA;Since the unit of radiance is W/(sr*m^2) multiplying area gives W/sr. This makes me think the pi factor represents solid angle - but why only 1pi? I would have guessed 2pi since each point on the area light would radiate in a complete hemisphere (corresponding to 2pi steradians).&#xD;&#xA;&#xD;&#xA;You can find the actual code mentioned in the book [here][1].&#xD;&#xA;&#xD;&#xA;What am I misunderstanding? Why does `total emitted power = emitted radiance * area * pi` for diffuse area lights make sense?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v2/blob/master/src/lights/diffuse.cpp#L55" ContentLicense="CC BY-SA 3.0" />
  <row Id="7382" PostHistoryTypeId="1" PostId="3621" RevisionGUID="41953523-0c62-44cc-ab21-486609d199f7" CreationDate="2016-06-15T11:44:32.040" UserId="4578" Text="Total emitted power of diffuse area light" ContentLicense="CC BY-SA 3.0" />
  <row Id="7383" PostHistoryTypeId="3" PostId="3621" RevisionGUID="41953523-0c62-44cc-ab21-486609d199f7" CreationDate="2016-06-15T11:44:32.040" UserId="4578" Text="|raytracing|pathtracing|physically-based|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7384" PostHistoryTypeId="5" PostId="3620" RevisionGUID="96f3ff38-4219-4c20-ab1c-62c01116adb4" CreationDate="2016-06-15T14:44:42.670" UserId="231" Comment="Close quotes to avoid confusion" Text="This is the same problem as discussed in [What are sample gaps during scan conversion?](https://computergraphics.stackexchange.com/questions/2484/what-are-sample-gaps-during-scan-conversion)&#xD;&#xA;&#xD;&#xA;Briefly, rasterisation - at least with the majority of hardware systems - tests at a single 'infinitesimal' point for each pixel to determine if that pixel is inside a given triangle. &#xD;&#xA;&#xD;&#xA;If the sample point lies exactly on an edge, then additional tie-breaking rules, often referred to as &quot;fill rules&quot;, come in to play. Typically these will be something equivalent to, say, only consider the edge points on the top/left** edges of a triangle to be &quot;inside&quot;.&#xD;&#xA;&#xD;&#xA;**Other rules are available ;-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7385" PostHistoryTypeId="2" PostId="3622" RevisionGUID="e4d2473b-30ee-4757-9a36-6cf3593e7f65" CreationDate="2016-06-15T15:47:01.427" UserId="4581" Text="Which among Intel's integrated GPUs depart from their predecessors in a major way? Which are merely incremental improvements?&#xD;&#xA;&#xD;&#xA;**BACKGROUND**&#xD;&#xA;&#xD;&#xA;Intel integrates GPUs with many of the processors they sell. With each generation of processors (Ivy Bridge, Haswell, Broadwell, Skylake, Kaby Lake, etc.), Intel updates the graphics architecture. Much is written in the popular press regarding each of these: does your favorite video game make only 98 frames per second on the latest, or does it achieve a previously unheard-of 99? Bar charts are published, and so on.&#xD;&#xA;&#xD;&#xA;None of the articles, or practically none, seems to grasp the underlying technology. I would be interested to learn whether Ivy Bridge, Haswell, Broadwell, Sklyake, Kaby Lake, and so on, are each merely incremental improvements in the same, basic graphics architecture, or whether, say, Broadwell (or Kaby Lake, or whatever) was an entirely new design.&#xD;&#xA;&#xD;&#xA;I would likewise be interested to learn if one generation had been upgraded over the previous in a way which made OpenCL-type usage much more practical or capable.&#xD;&#xA;&#xD;&#xA;Apparently, Broadwell was the first capable of Vulkan, but I do not know whether this capability represents a fundamental architectural change or if it's just a driver issue.&#xD;&#xA;&#xD;&#xA;Most of the popular press seems pretty clueless at this technical level. Can you shed any light?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7386" PostHistoryTypeId="1" PostId="3622" RevisionGUID="e4d2473b-30ee-4757-9a36-6cf3593e7f65" CreationDate="2016-06-15T15:47:01.427" UserId="4581" Text="The generations of Intel's integrated graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="7387" PostHistoryTypeId="3" PostId="3622" RevisionGUID="e4d2473b-30ee-4757-9a36-6cf3593e7f65" CreationDate="2016-06-15T15:47:01.427" UserId="4581" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7388" PostHistoryTypeId="2" PostId="3623" RevisionGUID="88f0ce30-6dc5-4345-b7b5-9c930f992c36" CreationDate="2016-06-15T18:51:57.920" UserId="361" Text="In addition to @russ' answer, I was able to decode the buffer with the [gltf Utilities][1].&#xD;&#xA;&#xD;&#xA;    let uri = &quot;data:application/octet-stream;base64,AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUAAAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/&quot;;&#xD;&#xA;&#xD;&#xA;    gltfUtilities.loadArrayBuffer(uri,&#xD;&#xA;      function(buf) {&#xD;&#xA;        let idx = new DataView(buf, 0, 72);&#xD;&#xA;        for (var i = 0; i &lt; 72; i += 2) {&#xD;&#xA;          window.console.log(idx.getUint16(i, true));&#xD;&#xA;        }&#xD;&#xA;        let vtx = new DataView(buf, 72, 288);&#xD;&#xA;        for (var v = 0; v &lt; 288; v += 4) {&#xD;&#xA;          window.console.log(vtx.getFloat32(v, true));&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      function(xhr) {&#xD;&#xA;        window.console.log(&quot;The ArrayBuffer failed to load&quot;);&#xD;&#xA;      }&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;Here is a [JSfiddle][2] to test. `loadArrayBuffer()` creates a JavaScript `ArrayBuffer` from the base64 encoded String.&#xD;&#xA;&#xD;&#xA;Opening the ArrayBuffer with a JavaScript DataView allows to read the buffer data. Note the first 72 bytes are 36 unsigned short indeces (Uint16) and the following 288 bytes are the 72 float vertices (Float32).&#xD;&#xA;&#xD;&#xA;I didn't read the normals (last 288 bytes), but that would work similar to the vertices.&#xD;&#xA;&#xD;&#xA;And to encode a base64 string with my custom buffers, I'll just do it vice versa. Here is a [JSfiddle][3] for encoding.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/AnalyticalGraphicsInc/gltf-utilities&#xD;&#xA;  [2]: https://jsfiddle.net/s1bzc0zc/6/&#xD;&#xA;  [3]: https://jsfiddle.net/6cevt681/1/" ContentLicense="CC BY-SA 3.0" />
  <row Id="7389" PostHistoryTypeId="2" PostId="3624" RevisionGUID="8d9de81d-e027-4b6b-90a5-ce8e54b1ebdf" CreationDate="2016-06-15T18:57:12.357" UserId="361" Text="It's not possible to store the plain text array buffers in gltf, however, here is the code I use to generate buffers in JavaScript:&#xD;&#xA;&#xD;&#xA;    let vtx = [&#xD;&#xA;      0.0857, 0.0759,&#xD;&#xA;      0.0367, 0.9726,&#xD;&#xA;      0.9678, 0.0318,&#xD;&#xA;      0.9754, 0.9327&#xD;&#xA;    ];&#xD;&#xA;&#xD;&#xA;    let idx = [&#xD;&#xA;      0, 2,&#xD;&#xA;      2, 4,&#xD;&#xA;      4, 0,&#xD;&#xA;      0, 1,&#xD;&#xA;      1, 4&#xD;&#xA;    ];&#xD;&#xA;&#xD;&#xA;    let buf = new ArrayBuffer(52);&#xD;&#xA;    let dat = new DataView(buf, 0, 52);&#xD;&#xA;&#xD;&#xA;    for (var i = 0; i &lt; 20; i += 2) {&#xD;&#xA;      dat.setUint16(i, idx[i / 2], true);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    for (var v = 20; v &lt; 52; v += 4) {&#xD;&#xA;      dat.setFloat32(v, vtx[(v - 20) / 4], true);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    let b64 = btoa(String.fromCharCode(...new Uint8Array(buf)));&#xD;&#xA;&#xD;&#xA;    window.console.log(&quot;data:application/octet-stream;base64,&quot; + b64);&#xD;&#xA;&#xD;&#xA;Where `buf` contains the binary data in a JavaScript ArrayBuffer object and `b64` finally a base64 encoded string:&#xD;&#xA;&#xD;&#xA;    data:application/octet-stream;base64,AAACAAIABAAEAAAAAAABAAEABAB7g689dnGbPb1SFj1Q/Hg/vsF3P7hAAj3Qs3k/bcVuPw==" ContentLicense="CC BY-SA 3.0" />
  <row Id="7390" PostHistoryTypeId="2" PostId="3625" RevisionGUID="e4cb0240-70fc-4475-ae05-2d9a192256ab" CreationDate="2016-06-15T19:03:36.683" UserId="361" Text="I've finally managed to write the buffers myself using [JavaScript][1].&#xD;&#xA;&#xD;&#xA;The result is a base64 encoded String, like:&#xD;&#xA;&#xD;&#xA;    data:application/octet-stream;base64,AAACAAIABAAEAAAAAAABAAEABAB7g689dnGbPb1SFj1Q/Hg/vsF3P7hAAj3Qs3k/bcVuPw==&#xD;&#xA;&#xD;&#xA;If you paste this Data URI into the browser, you can download a binary blob which is exactly what the glTF files can use.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The 52 bytes in this case contain 10 indices of 2 bytes size (`U_SHORT`) and 8 vertices of 4 bytes size (`FLOAT`), so `10 * 2 B + 8 * 4 B = 52 B`.&#xD;&#xA;&#xD;&#xA;See [this post][3] to find out how I generated the buffer and see [this answer][4] on how to read the data again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jsfiddle.net/6cevt681/1/&#xD;&#xA;  [2]: https://i.stack.imgur.com/x2dxF.png&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/a/3624/361&#xD;&#xA;  [4]: http://computergraphics.stackexchange.com/a/3623/361" ContentLicense="CC BY-SA 3.0" />
  <row Id="7391" PostHistoryTypeId="5" PostId="417" RevisionGUID="0e2b9b71-7a17-437b-b35b-e2e50bac8b53" CreationDate="2016-06-15T19:04:57.963" UserId="361" Comment="fixed broken link" Text="Ok sometimes you have to ask a question to figure out the answer already.&#xD;&#xA;&#xD;&#xA;Example datasets are available in the same repository as linked in the question already. &#xD;&#xA;&#xD;&#xA;Here are some:&#xD;&#xA;&#xD;&#xA; - [supermurdoc.gltf][1]&#xD;&#xA; - [duck.gltf][2]&#xD;&#xA; - [etc. pp.][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/e9cf7b0de2d1daed58317f5e6c8b9a2b7d543375/model/SuperMurdoch/SuperMurdoch.gltf&#xD;&#xA;  [2]: https://github.com/KhronosGroup/glTF/blob/e9cf7b0de2d1daed58317f5e6c8b9a2b7d543375/model/duck/duck.gltf&#xD;&#xA;  [3]: https://github.com/KhronosGroup/glTF/tree/master/sampleModels" ContentLicense="CC BY-SA 3.0" />
  <row Id="7395" PostHistoryTypeId="2" PostId="3627" RevisionGUID="e2abea9b-41bc-47c5-a87e-25a2b0a6c817" CreationDate="2016-06-15T20:33:39.417" UserId="4583" Text="I know the philosophy of how a gpu works { many weak men doing a a tasks(gpu) compared to one strong man doning the same task(cpu)}. How does the gpu manage all the ALUs and schedule the the necessary calculation to an alu.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7396" PostHistoryTypeId="1" PostId="3627" RevisionGUID="e2abea9b-41bc-47c5-a87e-25a2b0a6c817" CreationDate="2016-06-15T20:33:39.417" UserId="4583" Text="how does a gpu process a task by using multiple ALUs" ContentLicense="CC BY-SA 3.0" />
  <row Id="7397" PostHistoryTypeId="3" PostId="3627" RevisionGUID="e2abea9b-41bc-47c5-a87e-25a2b0a6c817" CreationDate="2016-06-15T20:33:39.417" UserId="4583" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7398" PostHistoryTypeId="2" PostId="3628" RevisionGUID="fed60206-33cd-49d9-8342-b0ce1d95ec8d" CreationDate="2016-06-15T20:50:54.617" UserId="361" Text="After spending a hard time to understand the way [how the binary buffers work in the gltf files][1] I finally managed to generate a truely _minimal_ gltf file. It's a single yellow triangle ([demo][2]). &#xD;&#xA;&#xD;&#xA;[![minimal triangle][3]][3]&#xD;&#xA;&#xD;&#xA;I tried to remove everything which is not needed from the gltf. This is what is required it seems ([github][4]):&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;        &quot;accessors&quot;: {&#xD;&#xA;            &quot;accessor0&quot;: {&#xD;&#xA;                &quot;bufferView&quot;: &quot;bufferView0&quot;,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;componentType&quot;: 5123,&#xD;&#xA;                &quot;count&quot;: 3,&#xD;&#xA;                &quot;type&quot;: &quot;SCALAR&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;accessor1&quot;: {&#xD;&#xA;                &quot;bufferView&quot;: &quot;bufferView1&quot;,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;byteStride&quot;: 12,&#xD;&#xA;                &quot;componentType&quot;: 5126,&#xD;&#xA;                &quot;count&quot;: 3,&#xD;&#xA;                &quot;max&quot;: [&#xD;&#xA;                    0.5,&#xD;&#xA;                    0.5,&#xD;&#xA;                    0.5&#xD;&#xA;                ],&#xD;&#xA;                &quot;min&quot;: [&#xD;&#xA;                    0.0,&#xD;&#xA;                    0.0,&#xD;&#xA;                    0.0&#xD;&#xA;                ],&#xD;&#xA;                &quot;type&quot;: &quot;VEC3&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;asset&quot;: {&#xD;&#xA;            &quot;generator&quot;: &quot;5chdn&quot;,&#xD;&#xA;            &quot;profile&quot;: {&#xD;&#xA;                &quot;api&quot;: &quot;WebGL&quot;,&#xD;&#xA;                &quot;version&quot;: &quot;1.0.3&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;version&quot;: &quot;1.0&quot;,&#xD;&#xA;            &quot;extras&quot;: {&#xD;&#xA;                &quot;description&quot;: &quot;minimal gltf, single triangle&quot;,&#xD;&#xA;                &quot;base64encoder&quot;: &quot;https://jsfiddle.net/opkxy0xb/&quot;,&#xD;&#xA;                &quot;stackexchange&quot;: &quot;http://computergraphics.stackexchange.com/q/1934/361&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;bufferViews&quot;: {&#xD;&#xA;            &quot;bufferView0&quot;: {&#xD;&#xA;                &quot;buffer&quot;: &quot;Min&quot;,&#xD;&#xA;                &quot;byteLength&quot;: 6,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;target&quot;: 34963&#xD;&#xA;            },&#xD;&#xA;            &quot;bufferView1&quot;: {&#xD;&#xA;                &quot;buffer&quot;: &quot;Min&quot;,&#xD;&#xA;                &quot;byteLength&quot;: 36,&#xD;&#xA;                &quot;byteOffset&quot;: 6,&#xD;&#xA;                &quot;target&quot;: 34962&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;buffers&quot;: {&#xD;&#xA;            &quot;Min&quot;: {&#xD;&#xA;                &quot;bytelength&quot;: 42,&#xD;&#xA;                &quot;type&quot;: &quot;arraybuffer&quot;,&#xD;&#xA;                &quot;uri&quot;: &quot;data:application/octet-stream;base64,AAABAAIArK34PnZxmz29UhY9T6+UPXuD7z64QAI9UWuaPW/wBT3ysPA+&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;materials&quot;: {&#xD;&#xA;            &quot;effect0&quot;: {&#xD;&#xA;                &quot;values&quot;: {&#xD;&#xA;                    &quot;emission&quot;: [&#xD;&#xA;                        0.8,&#xD;&#xA;                        0.8,&#xD;&#xA;                        0.0,&#xD;&#xA;                        1.0&#xD;&#xA;                    ]&#xD;&#xA;                },&#xD;&#xA;                &quot;technique&quot;: &quot;technique0&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;meshes&quot;: {&#xD;&#xA;            &quot;mesh0&quot;: {&#xD;&#xA;                &quot;name&quot;: &quot;Triangle&quot;,&#xD;&#xA;                &quot;primitives&quot;: [&#xD;&#xA;                    {&#xD;&#xA;                        &quot;attributes&quot;: {&#xD;&#xA;                            &quot;POSITION&quot;: &quot;accessor1&quot;&#xD;&#xA;                        },&#xD;&#xA;                        &quot;indices&quot;: &quot;accessor0&quot;,&#xD;&#xA;                        &quot;material&quot;: &quot;effect0&quot;,&#xD;&#xA;                        &quot;mode&quot;: 4&#xD;&#xA;                    }&#xD;&#xA;                ]&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;nodes&quot;: {&#xD;&#xA;            &quot;node0&quot;: {&#xD;&#xA;                &quot;matrix&quot;: [&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1&#xD;&#xA;                ],&#xD;&#xA;                &quot;meshes&quot;: [&#xD;&#xA;                    &quot;mesh0&quot;&#xD;&#xA;                ],&#xD;&#xA;                &quot;name&quot;: &quot;TriangleMesh&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;programs&quot;: {&#xD;&#xA;            &quot;program0&quot;: {&#xD;&#xA;                &quot;attributes&quot;: [&#xD;&#xA;                    &quot;a_position&quot;&#xD;&#xA;                ],&#xD;&#xA;                &quot;fragmentShader&quot;: &quot;fragmentShader0&quot;,&#xD;&#xA;                &quot;vertexShader&quot;: &quot;vertexShader0&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;scenes&quot;: {&#xD;&#xA;            &quot;scene0&quot;: {&#xD;&#xA;                &quot;nodes&quot;: [&#xD;&#xA;                    &quot;node0&quot;&#xD;&#xA;                ]&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;shaders&quot;: {&#xD;&#xA;            &quot;vertexShader0&quot;: {&#xD;&#xA;                &quot;type&quot;: 35633,&#xD;&#xA;                &quot;uri&quot;: &quot;data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMzIGFfcG9zaXRpb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX1Bvc2l0aW9uID0gdV9wcm9qZWN0aW9uTWF0cml4ICogdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCn0=&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;fragmentShader0&quot;: {&#xD;&#xA;                &quot;type&quot;: 35632,&#xD;&#xA;                &quot;uri&quot;: &quot;data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX0ZyYWdDb2xvciA9IHVfZW1pc3Npb247DQp9&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;techniques&quot;: {&#xD;&#xA;            &quot;technique0&quot;: {&#xD;&#xA;                &quot;attributes&quot;: {&#xD;&#xA;                    &quot;a_position&quot;: &quot;position&quot;&#xD;&#xA;                },&#xD;&#xA;                &quot;parameters&quot;: {&#xD;&#xA;                    &quot;modelViewMatrix&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;MODELVIEW&quot;,&#xD;&#xA;                        &quot;type&quot;: 35676&#xD;&#xA;                    },&#xD;&#xA;                    &quot;projectionMatrix&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;PROJECTION&quot;,&#xD;&#xA;                        &quot;type&quot;: 35676&#xD;&#xA;                    },&#xD;&#xA;                    &quot;emission&quot;: {&#xD;&#xA;                        &quot;type&quot;: 35666&#xD;&#xA;                    },&#xD;&#xA;                    &quot;position&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;POSITION&quot;,&#xD;&#xA;                        &quot;type&quot;: 35665&#xD;&#xA;                    }&#xD;&#xA;                },&#xD;&#xA;                &quot;program&quot;: &quot;program0&quot;,&#xD;&#xA;                &quot;states&quot;: {&#xD;&#xA;                    &quot;enable&quot;: [&#xD;&#xA;                        2884,&#xD;&#xA;                        2929&#xD;&#xA;                    ]&#xD;&#xA;                },&#xD;&#xA;                &quot;uniforms&quot;: {&#xD;&#xA;                    &quot;u_modelViewMatrix&quot;: &quot;modelViewMatrix&quot;,&#xD;&#xA;                    &quot;u_projectionMatrix&quot;: &quot;projectionMatrix&quot;,&#xD;&#xA;                    &quot;u_emission&quot;: &quot;emission&quot;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A good starting point was the [Appendix A of the gltf Specification][5] which defines a default material and shaders. All I had to do was adding the scene description and the buffers.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/a/3624/361&#xD;&#xA;  [2]: http://5chdn.github.io/gltf-tiles-loader-poc/&#xD;&#xA;  [3]: https://i.stack.imgur.com/kMZO0.png&#xD;&#xA;  [4]: https://github.com/5chdn/gltf-tiles-loader-poc/blob/8f25b30fed2324820e0a4a8958715fa2a424305d/data/Min/glTF-Embedded/Min.gltf&#xD;&#xA;  [5]: https://github.com/KhronosGroup/glTF/blob/master/specification/README.md#appendix-a-default-material" ContentLicense="CC BY-SA 3.0" />
  <row Id="7399" PostHistoryTypeId="5" PostId="3627" RevisionGUID="6dd94b89-509d-4a85-b611-efb713dd8077" CreationDate="2016-06-15T21:24:17.410" UserDisplayName="user3437" Comment="grammar, formatting" Text="I know the philosophy of how a GPU works { many weak men doing a task (GPU) compared to one strong man doing the same task (CPU)}. &#xD;&#xA;&#xD;&#xA;&gt;How does the GPU manage all the ALUs and schedule the the necessary calculation to an ALU ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7400" PostHistoryTypeId="24" PostId="3627" RevisionGUID="6dd94b89-509d-4a85-b611-efb713dd8077" CreationDate="2016-06-15T21:24:17.410" Comment="Proposed by 3437 approved by -1 edit id of 145" ContentLicense="CC BY-SA 3.0" />
  <row Id="7401" PostHistoryTypeId="5" PostId="3627" RevisionGUID="bf8b0162-e94d-4bf2-9353-43d7dfab28df" CreationDate="2016-06-15T21:24:17.410" UserId="231" Comment="grammar, formatting" Text="I know the philosophy of how a GPU works {many weak men doing a task (GPU) compared to one strong man doing the same task (CPU)}. &#xD;&#xA;&#xD;&#xA;How does the GPU manage all the ALUs and schedule the necessary calculation to an ALU?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7402" PostHistoryTypeId="4" PostId="3627" RevisionGUID="bf8b0162-e94d-4bf2-9353-43d7dfab28df" CreationDate="2016-06-15T21:24:17.410" UserId="231" Comment="grammar, formatting" Text="How does a GPU process a task by using multiple ALUs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7403" PostHistoryTypeId="10" PostId="416" RevisionGUID="8e736464-07cc-46ab-888e-9b5398e4678c" CreationDate="2016-06-15T21:51:05.390" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="7407" PostHistoryTypeId="2" PostId="3629" RevisionGUID="d9096bfb-1286-4c0b-a400-8eb4cbe074e6" CreationDate="2016-06-16T01:47:03.613" UserId="2707" Text="Architecture Background&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;GPU don't schedule to individual ALUs, but rather groups of them. Terminology will vary based on GPU company (NVidia, ATI, and Intel), but I will stick with NVidia terminology since they all work somewhat similarly at the high level.&#xD;&#xA;&#xD;&#xA;NVidia has a concept of CUDA cores, each of which contains an ALU and/or FPU, which make up collections called Streaming Multiprocessors (SM). [The Fermi architecture][1] has 32 CUDA cores per SM, for example.&#xD;&#xA;&#xD;&#xA;GPUs operate in a SIMD-like manner. This means that unlike a CPU, which traditionally has had one execution unit per instruction, GPUs have many execution units per instruction (CUDA core). These groups of execution are called warps.&#xD;&#xA;&#xD;&#xA;Answer&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;GPUs contain scheduling units that attempt to reach maximal utilization. Warps are scheduled in a way to utilize as much of the GPU as possible. One way to do this is to use a [round-robin approach][2]. Latency is something that a GPU struggles with compared to a CPU, so scheduling a process as soon as possible is often desirable. Like an OS (which controls CPU scheduling), however, simplicity and hiding latency are still desirable traits to an extent, although other tradeoffs may be deemed more important.&#xD;&#xA;&#xD;&#xA;Your workload will determine how scheduling is done. If you run a CUDA kernel or shader on 320 pieces of data (threads), you will need at least 10 warps to be scheduled (this depends on the type of data as well). If you have 1 thread that needs to be calculated, oh well, you still need to schedule one warp to do the calculation.&#xD;&#xA;&#xD;&#xA;Of course, what ratchet freak said is true about GPU architectures and algorithms being proprietary, especially when compared to CPUs.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Fermi_(microarchitecture)&#xD;&#xA;  [2]: https://users.ece.cmu.edu/~omutlu/pub/large-gpu-warps_micro11.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="7408" PostHistoryTypeId="2" PostId="3630" RevisionGUID="5fb0688b-ddd7-48d4-8548-dc2832984286" CreationDate="2016-06-16T02:15:29.827" UserId="2707" Text="Unity provides a pretty clear description of [GPU instancing][1]. It is exactly the same as instancing. Employees of Unity even spell this out by initially [arguing][2] against it years ago before finally implementing it.&#xD;&#xA;&#xD;&#xA;Before this, Unity solely relied on [batching][3], which was a technique that combined meshes together into one to reduce draw calls.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unity3d.com/540/Documentation/Manual/GPUInstancing.html&#xD;&#xA;  [2]: http://forum.unity3d.com/threads/gpu-mesh-instancing.19670/&#xD;&#xA;  [3]: http://docs.unity3d.com/Manual/DrawCallBatching.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="7409" PostHistoryTypeId="2" PostId="3631" RevisionGUID="c0f3648a-64a2-491e-95a3-492ab05aefa6" CreationDate="2016-06-16T04:04:10.187" UserId="3003" Text="One method is to do [projection mapping](https://en.wikipedia.org/wiki/Projection_mapping). I understand that most 3D rendering applications can do that. I don't have much experience with them, but I have done it using AfterEffects using the Camera Mapper in [Buena Depth Cue](http://aescripts.com/buena-depth-cue/).&#xD;&#xA;&#xD;&#xA;Algorithmically, it's achieved by projecting the geometry back onto the image to generate texture coordinates. So one way to do that is as follows:&#xD;&#xA;&#xD;&#xA; 1. Line up the image of the scene in front of the corresponding geometry&#xD;&#xA; 2. For each triangle in your geometry, project the 3 corners onto the image&#xD;&#xA; 3. The coordinates where the projection hits your image are the texture coordinates you need for that triangle" ContentLicense="CC BY-SA 3.0" />
  <row Id="7410" PostHistoryTypeId="6" PostId="1755" RevisionGUID="2d621d09-1c6c-428d-b1c6-e30681ed2bdf" CreationDate="2016-06-16T11:03:27.667" UserId="4558" Comment="added tag l-system" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7411" PostHistoryTypeId="24" PostId="1755" RevisionGUID="2d621d09-1c6c-428d-b1c6-e30681ed2bdf" CreationDate="2016-06-16T11:03:27.667" Comment="Proposed by 4558 approved by 209, 273 edit id of 146" ContentLicense="CC BY-SA 3.0" />
  <row Id="7412" PostHistoryTypeId="6" PostId="405" RevisionGUID="febf3989-8ce4-4d64-9ca7-5e5acf13a3e6" CreationDate="2016-06-16T11:21:44.067" UserId="231" Comment="edited tags" Text="|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7413" PostHistoryTypeId="6" PostId="1535" RevisionGUID="c93da47c-910e-4cac-9240-1e8a8fac4e17" CreationDate="2016-06-16T11:23:43.593" UserId="231" Comment="edited tags" Text="|hemisphere|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7415" PostHistoryTypeId="2" PostId="3633" RevisionGUID="201eb2a3-f728-435a-b2b9-0d20688af951" CreationDate="2016-06-16T13:43:20.917" UserId="4589" Text="Firstly, English is not my native language hence sorry for my grammar mistakes in advance. I am trying to implement the SIFT feature extraction algorithm. I have couple of question which are not very clear at paper:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;1. When interpolating the extremas with 2nd order func., do we upscale the downscaled images directly from DoG or interpolate at original downsampled image than upscale for the subpixel accuracy pixel positions?&#xD;&#xA;&#xD;&#xA;2. At description step, it is stated that &quot; In order to achieve orientation&#xD;&#xA;invariance, the coordinates of the descriptor and the gradient orientations are rotated relative to the keypoint orientation.&quot;. I think the rotated thing is not the keypoint locations and it should be the window of descriptor and gradient orientations are rotated after rotating the window. Do you think it is true? &#xD;&#xA;&#xD;&#xA;3. Should image size stay same after convolving with the Gaussian? This will effect the keypoint locations.&#xD;&#xA;&#xD;&#xA;Vevaldi provided great implementation http://vision.ucla.edu/~vedaldi/code/sift.html . Because it is at .mex format i can't reach what is going on inside. Other open source codes' solutions haven't satisfy me also. Hence i am asking for your help.&#xD;&#xA;&#xD;&#xA;Thank you so much for your valuable answers." ContentLicense="CC BY-SA 3.0" />
  <row Id="7416" PostHistoryTypeId="1" PostId="3633" RevisionGUID="201eb2a3-f728-435a-b2b9-0d20688af951" CreationDate="2016-06-16T13:43:20.917" UserId="4589" Text="SIFT Feature Extraction" ContentLicense="CC BY-SA 3.0" />
  <row Id="7417" PostHistoryTypeId="3" PostId="3633" RevisionGUID="201eb2a3-f728-435a-b2b9-0d20688af951" CreationDate="2016-06-16T13:43:20.917" UserId="4589" Text="|scene-description|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7418" PostHistoryTypeId="2" PostId="3634" RevisionGUID="4b8f5369-af3c-4885-b9e6-79c4fb1f657f" CreationDate="2016-06-16T22:11:13.730" UserId="56" Text="To compile shaders, I currently spin up a thread per core where each thread pulls a shader from a list and calls D3DX11CompileFromFile for dx11 and D3DXCompileShaderFromFile for dx9.&#xD;&#xA;&#xD;&#xA;I've heard it mentioned that spinning up multiple processes instead of multiple threads can be faster, since there is some sort of per process driver contention.&#xD;&#xA;&#xD;&#xA;Has anyone tried this, or does anyone have any tips on how to speed up shader compilation?&#xD;&#xA;&#xD;&#xA;I have a modern machine w/ SSD drives." ContentLicense="CC BY-SA 3.0" />
  <row Id="7419" PostHistoryTypeId="1" PostId="3634" RevisionGUID="4b8f5369-af3c-4885-b9e6-79c4fb1f657f" CreationDate="2016-06-16T22:11:13.730" UserId="56" Text="Fastest shader compilation strategy on windows dx9 and dx11?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7420" PostHistoryTypeId="3" PostId="3634" RevisionGUID="4b8f5369-af3c-4885-b9e6-79c4fb1f657f" CreationDate="2016-06-16T22:11:13.730" UserId="56" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7421" PostHistoryTypeId="5" PostId="2346" RevisionGUID="5790569d-7bd9-47db-a920-8b0078401199" CreationDate="2016-06-17T00:55:55.473" UserDisplayName="user3437" Comment="formatting, " Text="I'm a newbie to OpenGL and I was following a series by &quot;thebennybox&quot; on Youtube. Specifically his series on modern opengl programming. I thought I would try to implement his Mesh wrapper using the vector in C++ rather than using arrays of data and passing that to OpenGL. It works, but I cant' seem to render multiple meshes?&#xD;&#xA;&#xD;&#xA;Am I making an obvious mistake somewhere?&#xD;&#xA;&#xD;&#xA;This is I do to setup my mesh:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp--&gt;&#xD;&#xA;&#xD;&#xA;	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;	glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(BUFFER_COUNT, vbo);&#xD;&#xA;&#xD;&#xA;	// vertices buffer&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, vbo[BUFFER_POSITION]);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(positions.front()), &amp;positions.front(), GL_STATIC_DRAW);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;&#xD;&#xA;	// texture buffer&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, vbo[BUFFER_TEXCOORD]);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(texes.front()), &amp;texes.front(), GL_STATIC_DRAW);&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;&#xD;&#xA;	// index buffer&#xD;&#xA;	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[BUFFER_INDEX]);&#xD;&#xA;	glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices.front()), &amp;indices.front(), GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;Then to render it I bind the VAO and draw the elements:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp--&gt;&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(vao);&#xD;&#xA;	glDrawElementsBaseVertex(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0, 0);&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally I can send it some data:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    std::vector&lt;Vertex&gt; vertices = {&#xD;&#xA;		Vertex(glm::vec3(0, 0, 0), glm::vec2(0, 0)),&#xD;&#xA;		Vertex(glm::vec3(0, 1, 0), glm::vec2(1, 0)),&#xD;&#xA;		Vertex(glm::vec3(0, 1, 1), glm::vec2(1, 1)),&#xD;&#xA;		Vertex(glm::vec3(0, 0, 1), glm::vec2(0, 1)),&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	std::vector&lt;unsigned int&gt; indices = {&#xD;&#xA;		0, 1, 2, 2, 3, 0&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	shape = new Mesh(vertices, indices);&#xD;&#xA;&#xD;&#xA;The weird thing is that this works perfectly, but as soon as I try render another mesh it wont render the previous mesh. The weird thing is that say I had mesh A and mesh B. I can render mesh A, then I _setup_ mesh B, and even if I don't render it, nothing renders at all. Not even mesh A. I assume this is due to the state-based-ness of OpenGL." ContentLicense="CC BY-SA 3.0" />
  <row Id="7422" PostHistoryTypeId="24" PostId="2346" RevisionGUID="5790569d-7bd9-47db-a920-8b0078401199" CreationDate="2016-06-17T00:55:55.473" Comment="Proposed by 3437 approved by 273, 310 edit id of 147" ContentLicense="CC BY-SA 3.0" />
  <row Id="7427" PostHistoryTypeId="2" PostId="3636" RevisionGUID="e162bcd8-6d23-4ebf-89de-bdf037754b49" CreationDate="2016-06-17T04:11:11.553" UserId="48" Text="From what I can find out (not having tried it myself), using a thread per core to do D3D compiles is [reported](https://twitter.com/solid_angle/status/327572869699731457) to be safe and gives a good perf speedup, and there [doesn't seem to be any contention](https://twitter.com/repi/status/327580478062333952) between threads in the compiler itself.&#xD;&#xA;&#xD;&#xA;However, [Fabian Giesen notes](https://twitter.com/rygorous/status/327582029296324608) that you might see lower perf when running under a debugger, due to contention in the Windows debug heap allocator, [which can (and probably should) be disabled](http://preshing.com/20110717/the-windows-heap-is-slow-when-launched-from-the-debugger/).&#xD;&#xA;&#xD;&#xA;BTW, the functions you mentioned are both wrappers around [`D3DCompile`](https://msdn.microsoft.com/en-us/library/windows/desktop/dd607324.aspx), and don't involve the driver per se at all; they only do the GPU-independent &quot;HLSL source to bytecode&quot; step, and not the GPU-specific &quot;bytecode to machine code&quot; step. So they're entirely Microsoft code, not GPU IHV code." ContentLicense="CC BY-SA 3.0" />
  <row Id="7429" PostHistoryTypeId="2" PostId="3637" RevisionGUID="7344ee37-bb1c-4ea8-8d41-91e50a0248a2" CreationDate="2016-06-17T11:42:59.457" UserId="361" Text="WebGL 1.0 specification does not allow [to create 32-bit index buffers][1]. Now I'm in trouble, I'm trying to render huge objects with 100 thousends to 1 million indices. In OpenGL this is no issue at all, and I think it will be no issue in WebGL too, in most cases.&#xD;&#xA;&#xD;&#xA;I am not able [to split my data into smaller subsets][2] as I'm already working with split data sets and cant divide it further without breaking up my full program logic.&#xD;&#xA;&#xD;&#xA;Now I came across a new extension for WebGL from 2012, [OES_element_index_uint][3], which looks like it enables unsigned integers (32 bit) for `drawElements` calls. &#xD;&#xA;&#xD;&#xA;    /* draw geometry lines by indices */&#xD;&#xA;    gl.drawElements(gl.LINES, getIndexBuffer().length, gl.UNSIGNED_INT, idxBuffer);&#xD;&#xA;&#xD;&#xA;But when I try to use the `gl.UNSIGNED_INT` I run into the following error:&#xD;&#xA;&#xD;&#xA;    uncaught exception: gl.INVALID_ENUM was caused by call to drawElements&#xD;&#xA;&#xD;&#xA;How to use 32 bit Integers for Element Indices in WebGL 1.0? How to enable this extension in Chrome or Firefox?&#xD;&#xA;&#xD;&#xA;Does this mean in general such a call wont be compatible with most devices running WebGL 1.0?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/webgl/public-mailing-list/archives/1102/msg00093.php&#xD;&#xA;  [2]: http://stackoverflow.com/a/5189502/1260906&#xD;&#xA;  [3]: https://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/" ContentLicense="CC BY-SA 3.0" />
  <row Id="7430" PostHistoryTypeId="1" PostId="3637" RevisionGUID="7344ee37-bb1c-4ea8-8d41-91e50a0248a2" CreationDate="2016-06-17T11:42:59.457" UserId="361" Text="How to use 32 bit Integers for Element Indices in WebGL 1.0?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7431" PostHistoryTypeId="3" PostId="3637" RevisionGUID="7344ee37-bb1c-4ea8-8d41-91e50a0248a2" CreationDate="2016-06-17T11:42:59.457" UserId="361" Text="|webgl|drawing|types|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7432" PostHistoryTypeId="5" PostId="3637" RevisionGUID="fc31585a-4132-482c-847f-c4f0290f475d" CreationDate="2016-06-17T11:51:48.263" UserId="361" Comment="added 56 characters in body" Text="WebGL 1.0 specification does not allow [to create 32-bit index buffers][1]. Now I'm in trouble, I'm trying to render huge objects with 100 thousends to 1 million indices. In OpenGL this is no issue at all, and I think it will be no issue in WebGL too, in most cases.&#xD;&#xA;&#xD;&#xA;I am not able [to split my data into smaller subsets][2] as I'm already working with split data sets and cant divide it further without breaking up my full program logic.&#xD;&#xA;&#xD;&#xA;Now I came across a new extension for WebGL from 2012, [OES_element_index_uint][3], which looks like it enables unsigned integers (32 bit) for `drawElements` calls. &#xD;&#xA;&#xD;&#xA;    /* draw geometry lines by indices */&#xD;&#xA;    gl.drawElements(gl.LINES, getIndexBuffer().length, gl.UNSIGNED_INT, idxBuffer);&#xD;&#xA;&#xD;&#xA;But when I try to use the `gl.UNSIGNED_INT` I run into the following error:&#xD;&#xA;&#xD;&#xA;    Error: WebGL: drawElements: Invalid `type`: 0x1405&#xD;&#xA;    uncaught exception: gl.INVALID_ENUM was caused by call to drawElements&#xD;&#xA;&#xD;&#xA;How to use 32 bit Integers for Element Indices in WebGL 1.0? How to enable this extension in Chrome or Firefox?&#xD;&#xA;&#xD;&#xA;Does this mean in general such a call wont be compatible with most devices running WebGL 1.0?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/webgl/public-mailing-list/archives/1102/msg00093.php&#xD;&#xA;  [2]: http://stackoverflow.com/a/5189502/1260906&#xD;&#xA;  [3]: https://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/" ContentLicense="CC BY-SA 3.0" />
  <row Id="7433" PostHistoryTypeId="2" PostId="3638" RevisionGUID="5452fc9d-9f75-4d80-838e-2c72cbccceda" CreationDate="2016-06-17T12:00:41.297" UserId="137" Text="Enabling the extension is as simple as:&#xD;&#xA;&#xD;&#xA;    var uints_for_indices = gl.getExtension(&quot;OES_element_index_uint&quot;);&#xD;&#xA;&#xD;&#xA;if `uints_for_indices` is null then the extension is not available and you'll have to split your data anyway.&#xD;&#xA;&#xD;&#xA;If it's not null then you can now pass `gl.UNSIGNED_INT` for the index type into `gl.drawElements`." ContentLicense="CC BY-SA 3.0" />
  <row Id="7434" PostHistoryTypeId="2" PostId="3639" RevisionGUID="0d32a8ce-9ee3-4179-a1cb-dfaae8cbcec7" CreationDate="2016-06-17T12:28:27.927" UserId="3472" Text="I have a mesh loaded by an obj file (wavefront), complete with normals and texture coordinates per face, and its relative texture available. In my C++ / OpenGL code (assignment for a computer graphics class) I bind correctly the texture, but fail at correctly mapping texture coordinates with face vertexes. Below I show the code for texture binding and the chain of calls to rasterize the object. I also show images for the expected result and the actual results (2 of them, one for each render setting). To be accurate, it seems that the first render &quot;tassellates&quot; the plain image on the rasterized shape of the whole object, while the second maps the image once on the shape of the object.&#xD;&#xA;&#xD;&#xA;What is going on here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Expected result][1]][1]&#xD;&#xA;[![Result #1][2]][2]&#xD;&#xA;[![Result #2 (don't mind the background)][3]][3]&#xD;&#xA;&#xD;&#xA;Bind procedure:&#xD;&#xA;&#xD;&#xA;    SDL_Surface *s = IMG_Load(filename.c_str());&#xD;&#xA;&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, textureIndex);&#xD;&#xA;	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB,&#xD;&#xA;			s-&gt;w, s-&gt;h, GL_RGB, GL_UNSIGNED_BYTE, s-&gt;pixels);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D,&#xD;&#xA;			GL_TEXTURE_MAG_FILTER,&#xD;&#xA;			GL_LINEAR );&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D,&#xD;&#xA;			GL_TEXTURE_MIN_FILTER,&#xD;&#xA;			GL_LINEAR_MIPMAP_LINEAR );&#xD;&#xA;&#xD;&#xA;Raster procedure (pseudo code intended):&#xD;&#xA;&#xD;&#xA;    // gl pushMatrix, Traslation and rotations;&#xD;&#xA;    glPushMatrix();&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureIndex);&#xD;&#xA;    glColor3f(1,1,1);&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_S);&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_T);&#xD;&#xA;    glDisable(GL_LIGHTING);&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    for (face f in faces) {&#xD;&#xA;      glNormal3d(faceNormal.x, faceNormal.y, faceNormal.z);&#xD;&#xA;      for (i = 0, i &lt; 3, ++i)&#xD;&#xA;		glTexCoord3d(texturePoint[i].x, texturePoint[i].y, 0);&#xD;&#xA;		glVertex3d(v[i]-&gt;x(), v[i]-&gt;y(), v[i]-&gt;z());&#xD;&#xA;    glEnd();&#xD;&#xA;    glPopMatrix();&#xD;&#xA;    // gl PopMatrix to exit from traslation / rotation context.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nQ2Ez.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LEOSJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/q7TXB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7435" PostHistoryTypeId="1" PostId="3639" RevisionGUID="0d32a8ce-9ee3-4179-a1cb-dfaae8cbcec7" CreationDate="2016-06-17T12:28:27.927" UserId="3472" Text="OpenGL Vertex - Texture Mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="7436" PostHistoryTypeId="3" PostId="3639" RevisionGUID="0d32a8ce-9ee3-4179-a1cb-dfaae8cbcec7" CreationDate="2016-06-17T12:28:27.927" UserId="3472" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7437" PostHistoryTypeId="2" PostId="3640" RevisionGUID="c661981f-a01d-40c9-a760-fbe0d8a4ae93" CreationDate="2016-06-17T12:38:47.507" UserId="2041" Text="    for (i = 0, i &lt; 3, ++i)&#xD;&#xA;        glTexCoord3d(texturePoint[i].x, texturePoint[i].y, 0);&#xD;&#xA;        glVertex3d(v[i]-&gt;x(), v[i]-&gt;y(), v[i]-&gt;z());&#xD;&#xA;&#xD;&#xA;This code calls `glTexCoord3d` three times and `glVertex3d` only once. You need more braces around your `for` loop." ContentLicense="CC BY-SA 3.0" />
  <row Id="7439" PostHistoryTypeId="5" PostId="3639" RevisionGUID="7f70387e-7b69-42c4-94cb-454b0cb9311f" CreationDate="2016-06-17T13:30:02.483" UserId="3472" Comment="fixed typos" Text="I have a mesh loaded by an obj file (wavefront), complete with normals and texture coordinates per face, and its relative texture available. In my C++ / OpenGL code (assignment for a computer graphics class) I bind correctly the texture, but fail at correctly mapping texture coordinates with face vertexes. Below I show the code for texture binding and the chain of calls to rasterize the object. I also show images for the expected result and the actual results (2 of them, one for each render setting). To be accurate, it seems that the first render &quot;tassellates&quot; the plain image on the rasterized shape of the whole object, while the second maps the image once on the shape of the object.&#xD;&#xA;&#xD;&#xA;What is going on here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Expected result][1]][1]&#xD;&#xA;[![Result #1][2]][2]&#xD;&#xA;[![Result #2 (don't mind the background)][3]][3]&#xD;&#xA;&#xD;&#xA;Bind procedure:&#xD;&#xA;&#xD;&#xA;    SDL_Surface *s = IMG_Load(filename.c_str());&#xD;&#xA;&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, textureIndex);&#xD;&#xA;	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB,&#xD;&#xA;			s-&gt;w, s-&gt;h, GL_RGB, GL_UNSIGNED_BYTE, s-&gt;pixels);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D,&#xD;&#xA;			GL_TEXTURE_MAG_FILTER,&#xD;&#xA;			GL_LINEAR );&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D,&#xD;&#xA;			GL_TEXTURE_MIN_FILTER,&#xD;&#xA;			GL_LINEAR_MIPMAP_LINEAR );&#xD;&#xA;&#xD;&#xA;Raster procedure (pseudo code intended):&#xD;&#xA;&#xD;&#xA;    // gl pushMatrix, Traslation and rotations;&#xD;&#xA;    glPushMatrix();&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureIndex);&#xD;&#xA;    glColor3f(1,1,1);&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_S);&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_T);&#xD;&#xA;    glDisable(GL_LIGHTING);&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    for (face f in faces) {&#xD;&#xA;      glNormal3d(faceNormal.x, faceNormal.y, faceNormal.z);&#xD;&#xA;      for (i = 0, i &lt; 3, ++i) {&#xD;&#xA;		glTexCoord3d(texturePoint[i].x, texturePoint[i].y, 0);&#xD;&#xA;		glVertex3d(vertex[i].x, vertex[i].y, vertex[i].z);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    glEnd();&#xD;&#xA;    glPopMatrix();&#xD;&#xA;    // gl PopMatrix to exit from traslation / rotation context.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nQ2Ez.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LEOSJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/q7TXB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7441" PostHistoryTypeId="2" PostId="3641" RevisionGUID="0807e8c6-d43c-430a-9612-825080cfe5f8" CreationDate="2016-06-17T18:41:05.410" UserId="4603" Text="I'm building an engine, which has Vulkan for its primary rendering engine. But to have at least some backwards compatibility with devices that don't get drivers for (Mainly mobile) it I want to implement an OpenGL fallback. Now, how do I check what API's are available in the current system?&#xD;&#xA;&#xD;&#xA;I want to check if Vulkan support exists, if not then if GL support exists and if not that then crash." ContentLicense="CC BY-SA 3.0" />
  <row Id="7442" PostHistoryTypeId="1" PostId="3641" RevisionGUID="0807e8c6-d43c-430a-9612-825080cfe5f8" CreationDate="2016-06-17T18:41:05.410" UserId="4603" Text="How to check available API's?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7443" PostHistoryTypeId="3" PostId="3641" RevisionGUID="0807e8c6-d43c-430a-9612-825080cfe5f8" CreationDate="2016-06-17T18:41:05.410" UserId="4603" Text="|opengl|c++|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7444" PostHistoryTypeId="4" PostId="3641" RevisionGUID="5266bcaa-b257-4e62-b6f5-d90064289edd" CreationDate="2016-06-17T19:19:00.037" UserId="4494" Comment="Clarified the question" Text="How to check which API's are available on a given machine?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7445" PostHistoryTypeId="24" PostId="3641" RevisionGUID="5266bcaa-b257-4e62-b6f5-d90064289edd" CreationDate="2016-06-17T19:19:00.037" Comment="Proposed by 4494 approved by 4603 edit id of 148" ContentLicense="CC BY-SA 3.0" />
  <row Id="7446" PostHistoryTypeId="2" PostId="3642" RevisionGUID="c2385b58-568b-4307-a07e-c346ebc82db5" CreationDate="2016-06-17T19:46:24.013" UserId="137" Text="Basic Vulkan availability can be checked by the presence of the loader dynamic library. This will reside in a standard place where you can load it with `dlopen` or `LoadLibrary`. &#xD;&#xA;&#xD;&#xA;If it fails to load then vulkan is not installed. If it does load then you can get the vkGetInstanceProcAddr function pointer from it with `dlsym `or `GetProcAddress`. After that you can query the devices as normal and decide whether or not it's sufficient to support your app." ContentLicense="CC BY-SA 3.0" />
  <row Id="7447" PostHistoryTypeId="2" PostId="3643" RevisionGUID="a98b1c77-96d4-4af6-a333-440eec701370" CreationDate="2016-06-17T19:49:16.273" UserDisplayName="user3437" Text="If i remember correctly i have read somewhere that all the graphic cards that supports OpenGL version 3.0 and on, will support Vulkan, just new drivers are required. You can get the OpenGL version with `glGetString(GL_VERSION)`, read [here][1] and [here][2].&#xD;&#xA;&#xD;&#xA;Anyway i don't think comparing strings is a good way, i am sure there would be a better way of doing this and somebody will  point it out nor i know if this will work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Get_Context_Info#OpenGL_version_number&#xD;&#xA;  [2]: https://www.khronos.org/opengles/sdk/1.1/docs/man/glGetString.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="7451" PostHistoryTypeId="5" PostId="3641" RevisionGUID="6ffcc8b3-9ced-4648-90fc-9d60fe67f2c6" CreationDate="2016-06-18T09:14:51.010" UserId="231" Comment="Improve clarity" Text="I'm building an engine, which has Vulkan for its primary rendering engine. But to have at least some backwards compatibility with devices that don't have drivers for it (mainly mobile) I want to implement an OpenGL fallback. Now, how do I check what API's are available in the current system?&#xD;&#xA;&#xD;&#xA;I want to check if Vulkan support exists, if not then if OpenGL support exists and if not that then crash." ContentLicense="CC BY-SA 3.0" />
  <row Id="7452" PostHistoryTypeId="5" PostId="3639" RevisionGUID="bb919836-11be-421d-aac5-3a0b0429ee9c" CreationDate="2016-06-18T10:19:20.357" UserId="231" Comment="Minor typos" Text="I have a mesh loaded by an obj file (wavefront), complete with normals and texture coordinates per face, and its relative texture available. In my C++ / OpenGL code (assignment for a computer graphics class) I bind correctly the texture, but fail at correctly mapping texture coordinates with face vertexes. Below I show the code for texture binding and the chain of calls to rasterize the object. I also show images for the expected result and the actual results (2 of them, one for each render setting). To be specific, it seems that the first render &quot;tessellates&quot; the plain image on the rasterized shape of the whole object, while the second maps the image once on the shape of the object.&#xD;&#xA;&#xD;&#xA;What is going on here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Expected result][1]][1]&#xD;&#xA;[![Result #1][2]][2]&#xD;&#xA;[![Result #2 (don't mind the background)][3]][3]&#xD;&#xA;&#xD;&#xA;Bind procedure:&#xD;&#xA;&#xD;&#xA;    SDL_Surface *s = IMG_Load(filename.c_str());&#xD;&#xA;&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, textureIndex);&#xD;&#xA;	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB,&#xD;&#xA;			s-&gt;w, s-&gt;h, GL_RGB, GL_UNSIGNED_BYTE, s-&gt;pixels);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D,&#xD;&#xA;			GL_TEXTURE_MAG_FILTER,&#xD;&#xA;			GL_LINEAR );&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D,&#xD;&#xA;			GL_TEXTURE_MIN_FILTER,&#xD;&#xA;			GL_LINEAR_MIPMAP_LINEAR );&#xD;&#xA;&#xD;&#xA;Raster procedure (pseudo code intended):&#xD;&#xA;&#xD;&#xA;    // gl pushMatrix, Traslation and rotations;&#xD;&#xA;    glPushMatrix();&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureIndex);&#xD;&#xA;    glColor3f(1,1,1);&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_S);&#xD;&#xA;    glEnable(GL_TEXTURE_GEN_T);&#xD;&#xA;    glDisable(GL_LIGHTING);&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    for (face f in faces) {&#xD;&#xA;      glNormal3d(faceNormal.x, faceNormal.y, faceNormal.z);&#xD;&#xA;      for (i = 0, i &lt; 3, ++i) {&#xD;&#xA;		glTexCoord3d(texturePoint[i].x, texturePoint[i].y, 0);&#xD;&#xA;		glVertex3d(vertex[i].x, vertex[i].y, vertex[i].z);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    glEnd();&#xD;&#xA;    glPopMatrix();&#xD;&#xA;    // gl PopMatrix to exit from traslation / rotation context.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nQ2Ez.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LEOSJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/q7TXB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7453" PostHistoryTypeId="5" PostId="3637" RevisionGUID="ba61c60a-3682-4087-8bf2-d360f1ec093e" CreationDate="2016-06-18T10:23:14.050" UserId="231" Comment="Minor typos" Text="WebGL 1.0 specification does not allow [to create 32-bit index buffers][1]. Now I'm in trouble, I'm trying to render huge objects with 100 thousands to 1 million indices. In OpenGL this is no issue at all, and I think it will be no issue in WebGL too, in most cases.&#xD;&#xA;&#xD;&#xA;I am not able [to split my data into smaller subsets][2] as I'm already working with split data sets and can't divide it further without breaking up my full program logic.&#xD;&#xA;&#xD;&#xA;Now I came across a new extension for WebGL from 2012, [OES_element_index_uint][3], which looks like it enables unsigned integers (32 bit) for `drawElements` calls. &#xD;&#xA;&#xD;&#xA;    /* draw geometry lines by indices */&#xD;&#xA;    gl.drawElements(gl.LINES, getIndexBuffer().length, gl.UNSIGNED_INT, idxBuffer);&#xD;&#xA;&#xD;&#xA;But when I try to use the `gl.UNSIGNED_INT` I run into the following error:&#xD;&#xA;&#xD;&#xA;    Error: WebGL: drawElements: Invalid `type`: 0x1405&#xD;&#xA;    uncaught exception: gl.INVALID_ENUM was caused by call to drawElements&#xD;&#xA;&#xD;&#xA;How to use 32 bit Integers for Element Indices in WebGL 1.0? How to enable this extension in Chrome or Firefox?&#xD;&#xA;&#xD;&#xA;Does this mean in general such a call won't be compatible with most devices running WebGL 1.0?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/webgl/public-mailing-list/archives/1102/msg00093.php&#xD;&#xA;  [2]: http://stackoverflow.com/a/5189502/1260906&#xD;&#xA;  [3]: https://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/" ContentLicense="CC BY-SA 3.0" />
  <row Id="7455" PostHistoryTypeId="5" PostId="3633" RevisionGUID="666e6281-6a10-4acd-aa53-16d2a2c49493" CreationDate="2016-06-18T10:49:44.040" UserId="231" Comment="Edited for clarity. Please feel free to reverse anything which changes your intended meaning." Text="I am trying to implement the [SIFT feature extraction algorithm]. I have a few questions which are not very clear from the paper:&#xD;&#xA;&#xD;&#xA;1. When interpolating the extrema with 2nd order functions, do we upscale the downscaled images directly from [DoG] or interpolate in the original downsampled image then upscale for the subpixel accuracy pixel positions?&#xD;&#xA;&#xD;&#xA;1. At the description step, it is stated that&#xD;&#xA;&quot;In order to achieve orientation invariance, the coordinates of the descriptor and the gradient orientations are rotated relative to the keypoint orientation&quot;.&#xD;&#xA;I think the rotated thing is not the keypoint locations and it should be the window of descriptor and gradient orientations that are rotated after rotating the window. Do you think this is true? &#xD;&#xA;&#xD;&#xA;1. Should the image size stay the same after convolving with the Gaussian? This will affect the keypoint locations.&#xD;&#xA;&#xD;&#xA;Vevaldi provided a [great implementation]. Because it is in .mex format i can't see what is going on inside. Other open source codes' solutions also haven't satisfied me. Hence I am asking for your help.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [SIFT feature extraction algorithm]: https://en.wikipedia.org/wiki/Scale-invariant_feature_transform &quot;Scale Invariant Feature Transform&quot;&#xD;&#xA;&#xD;&#xA;  [DoG]: https://en.wikipedia.org/wiki/Difference_of_Gaussians &quot;Difference of Gaussians&quot;&#xD;&#xA;&#xD;&#xA;  [great implementation]: http://vision.ucla.edu/~vedaldi/code/sift.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="7458" PostHistoryTypeId="6" PostId="3633" RevisionGUID="910e9fbf-b042-4fcb-82dc-d722a0becfb1" CreationDate="2016-06-18T10:57:17.673" UserId="231" Comment="[Edit removed during grace period]; edited tags" Text="|image-processing|scene-description|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7459" PostHistoryTypeId="5" PostId="1934" RevisionGUID="62839467-bd06-4cb5-895c-aa9d34c20ea8" CreationDate="2016-06-18T11:19:39.657" UserId="231" Comment="Minor typo" Text="I am currently looking into [glTF][1] to use as a transfer format for my WebGL project. I already have the geometries I wish to render on my WebGL client available as preprocessed vertex and index buffers (and color buffers, but let's ignore them for now).&#xD;&#xA;&#xD;&#xA;For example:&#xD;&#xA;&#xD;&#xA;    [       // vertex buffer&#xD;&#xA;      0,0,0,&#xD;&#xA;      0,1,0,&#xD;&#xA;      1,0,0,&#xD;&#xA;      1,1,0,&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;And to draw simple `LINES`:&#xD;&#xA;&#xD;&#xA;    [       // index buffer&#xD;&#xA;      0,2,&#xD;&#xA;      2,4,&#xD;&#xA;      4,0,&#xD;&#xA;      0,1,&#xD;&#xA;      1,4,&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;I wonder how to create glTF files containing these buffers? Is this possible?&#xD;&#xA;&#xD;&#xA;I want to avoid using COLLADA and [COLLADA2GLTF][2] as this would only add an additional step and might just bloat the resulting glTF files.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/master/specification/README.md&#xD;&#xA;  [2]: https://github.com/KhronosGroup/glTF/wiki/converter" ContentLicense="CC BY-SA 3.0" />
  <row Id="7462" PostHistoryTypeId="2" PostId="3645" RevisionGUID="12f93293-2890-4286-b9c5-790ee6a5f7f2" CreationDate="2016-06-19T06:55:39.910" UserId="4611" Text="Using VTK 7.0 I have found that rendering a 20k triangle STL model takes approximately 17ms on my Nvidia GTX970. However, I am only interested in the silhouette of this model (like the image below) and was wondering if: a) such speeds are reasonable for this model size, and b) since I am not really interested in a full render, is there a much faster way to compute just that silhouette? I considered a ray tracing approach where I just compute whether or not each pixel hits the model, but since I am only interested in speed I do not know if this is a good route to pursue. As a side note, these questions need not be specific to VTK - I am really just conerned with the fastest way to utilize a GPU to compute a silhouette (suggestions algorithms, theory, or libraries are all all welcome!) and what reasonable times I can expect for such model sizes.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CBp4P.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7463" PostHistoryTypeId="1" PostId="3645" RevisionGUID="12f93293-2890-4286-b9c5-790ee6a5f7f2" CreationDate="2016-06-19T06:55:39.910" UserId="4611" Text="How fast should I expect to render the silhouette of a 20k triangle model?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7464" PostHistoryTypeId="3" PostId="3645" RevisionGUID="12f93293-2890-4286-b9c5-790ee6a5f7f2" CreationDate="2016-06-19T06:55:39.910" UserId="4611" Text="|rendering|silhouette|vtk|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7466" PostHistoryTypeId="2" PostId="3646" RevisionGUID="ea98ceb5-a2ae-4732-9922-7b5f48a28e8a" CreationDate="2016-06-19T11:03:51.923" UserId="3377" Text="With respect to [this topic ][1] I've successfully implemented the [Sobel Edge Detection][2] filter in GLSL. Here is the fragment shader code of the filter:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D screenTexture;&#xD;&#xA;&#xD;&#xA;    mat3 sx = mat3( &#xD;&#xA;	    1.0, 2.0, 1.0, &#xD;&#xA;	    0.0, 0.0, 0.0, &#xD;&#xA;	   -1.0, -2.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;    mat3 sy = mat3( &#xD;&#xA;	    1.0, 0.0, -1.0, &#xD;&#xA;	    2.0, 0.0, -2.0, &#xD;&#xA;	    1.0, 0.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec3 diffuse = texture(screenTexture, TexCoords.st).rgb;&#xD;&#xA;        mat3 I;&#xD;&#xA;	    for (int i=0; i&lt;3; i++) {&#xD;&#xA;		    for (int j=0; j&lt;3; j++) {&#xD;&#xA;			    vec3 sample  = texelFetch(screenTexture, ivec2(gl_FragCoord) + ivec2(i-1,j-1), 0 ).rgb;&#xD;&#xA;			    I[i][j] = length(sample); &#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float gx = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]); &#xD;&#xA;	float gy = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);&#xD;&#xA;&#xD;&#xA;	float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;	color = vec4(diffuse - vec3(g), 1.0);&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And here is the result of a cube with Sobel edge detection:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cube with Sobel edge detection filter][3]][3]&#xD;&#xA;&#xD;&#xA;If you enlarge the picture, you will see that there is a lot of &quot;noise&quot; produced by Sobel: &#xD;&#xA;There are gray horizontal stripes all over the scene due to the blue/white gradient. Futhermore, the light cones produce an unwanted pattern on the cube. The black edges on the left of the cube also seem to fade because of the light cone on the left half of the cube.&#xD;&#xA;&#xD;&#xA;So I read [this article][4] which stated that one should grayscale the image first and use a Gaussian blur filter to make the edges more apparent. On the bottom of the article, there is also the canny edge detection filter which seem to produce better results.&#xD;&#xA;&#xD;&#xA;Now I have two questions:&#xD;&#xA;&#xD;&#xA; 1. Are the following steps correct to produce the best possible edge detection results:&#xD;&#xA;  - Grayscale&#xD;&#xA;  - Gaussian Blur&#xD;&#xA;  - Sobel/Canny edge detection&#xD;&#xA;&#xD;&#xA; 2. If yes, how would I merge the original image with the processed image? I mean, after processing the steps stated above, I get an image that is either completely black with white edges or vice verca. How would I put the edges on my original image/texture?&#xD;&#xA;&#xD;&#xA;Thanks for your help!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/2450/opengl-detection-of-edges&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Sobel_operator&#xD;&#xA;  [3]: https://i.stack.imgur.com/PawMD.png&#xD;&#xA;  [4]: https://www.objc.io/issues/21-camera-and-photos/gpu-accelerated-machine-vision/" ContentLicense="CC BY-SA 3.0" />
  <row Id="7467" PostHistoryTypeId="1" PostId="3646" RevisionGUID="ea98ceb5-a2ae-4732-9922-7b5f48a28e8a" CreationDate="2016-06-19T11:03:51.923" UserId="3377" Text="OpenGL GLSL - Sobel Edge Detection Filter" ContentLicense="CC BY-SA 3.0" />
  <row Id="7468" PostHistoryTypeId="3" PostId="3646" RevisionGUID="ea98ceb5-a2ae-4732-9922-7b5f48a28e8a" CreationDate="2016-06-19T11:03:51.923" UserId="3377" Text="|opengl|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7469" PostHistoryTypeId="2" PostId="3647" RevisionGUID="275b340d-621f-475d-966a-1b86fc665a91" CreationDate="2016-06-19T13:10:38.510" UserId="182" Text="1. _The best results_ strongly depend on your use case. They also depend on what effect you want to achieve. Sobel is just an edge detection filter: the edges will depend on the input signal, choosing that input signal is up to you.&#xD;&#xA;&#xD;&#xA;  Here you are using the color image as an input, and the filter rightfully detects faint edges in the blue gradient, while the edges of the cube get interrupted where its color is too close from the background color.&#xD;&#xA;&#xD;&#xA;  Since I assume your program is also responsible for drawing the cube, you have access to other information that you can feed to your Sobel filter. For example depth and normals are good candidates for edge detection. The albedo before lighting could be used to. Test with different inputs and decide which ones to use depending on the results you get.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. Regarding your question about how to combine the edge information, I suggest you filter `g` a little before using it. Then you can use it to interpolate between the original color and the wanted edge color.&#xD;&#xA;&#xD;&#xA;  For example you could try something like this:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;        float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;&#xD;&#xA;        // Try different values and see what happens&#xD;&#xA;        g = smoothstep(0.4, 0.6, g);&#xD;&#xA;&#xD;&#xA;        vec3 edgeColor = vec3(1., 0., 0.2);&#xD;&#xA;        color = vec4(mix(diffuse, edgeColor, g), 1.);" ContentLicense="CC BY-SA 3.0" />
  <row Id="7470" PostHistoryTypeId="2" PostId="3648" RevisionGUID="fe934772-29da-4e8d-aca7-53e1ef75cdd5" CreationDate="2016-06-19T22:19:58.373" UserId="1636" Text="I'm very confused about sampling and reconstruction of images.&#xD;&#xA;I read that in the framebuffer there is a sampled representation of an image, for visualization the sampled representation is converted into a continuous one by the video hardware.&#xD;&#xA;Which filter is used by an LCD display ?&#xD;&#xA;&#xD;&#xA;But isn't an LCD display already digital ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7471" PostHistoryTypeId="1" PostId="3648" RevisionGUID="fe934772-29da-4e8d-aca7-53e1ef75cdd5" CreationDate="2016-06-19T22:19:58.373" UserId="1636" Text="Reconstruction filter of LCD monitor" ContentLicense="CC BY-SA 3.0" />
  <row Id="7472" PostHistoryTypeId="3" PostId="3648" RevisionGUID="fe934772-29da-4e8d-aca7-53e1ef75cdd5" CreationDate="2016-06-19T22:19:58.373" UserId="1636" Text="|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7473" PostHistoryTypeId="2" PostId="3649" RevisionGUID="c6e004a0-bb45-4f3d-ab89-b1f9bedd7944" CreationDate="2016-06-20T05:03:17.427" UserId="48" Text="The output of an LCD or other display is continuous by virtue of its being a physical device, with pixels that have some size and shape, and emit some physical spectrum of light.&#xD;&#xA;&#xD;&#xA;![close up of an iPhone 4 display][1]&lt;br/&gt;from [Apple Retina Display by Bryan Jones](http://prometheus.med.utah.edu/~bwjones/2010/06/apple-retina-display/) &#xD;&#xA;&#xD;&#xA;My guess as to what's meant by the comment that &quot;the sampled representation is converted into a continuous one by the video hardware&quot; is just that the input to the hardware is a sampled digital signal that drives the physical pixels, while the output is a continuous light field such as the above. So the &quot;reconstruction filter&quot;, so to speak, is the physical pattern of light emitted when the display is turned on.&#xD;&#xA;&#xD;&#xA;(Also note that displays often do additional digital processing of the input image before displaying it, e.g. to adjust brightness, contrast, color temperature, sharpness, and so forth. But those things wouldn't be called a reconstruction filter.)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E8hHG.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7474" PostHistoryTypeId="2" PostId="3650" RevisionGUID="d36d9003-0f5e-4899-ad3c-de5c3f69e395" CreationDate="2016-06-20T07:43:31.553" UserId="2817" Text="Your geometry may be prepared for Direct3D, which has texture space origin placed differently (top-left vs bottom-left corner). Try flipping either the texture's Y coordinates (i.e. load it from the bottom to the top), or the V texture coordinate (`glTexCoord3d(texturePoint[i].x, 1.0f - texturePoint[i].y, 0);`)." ContentLicense="CC BY-SA 3.0" />
  <row Id="7475" PostHistoryTypeId="2" PostId="3651" RevisionGUID="64447736-9b8f-4950-b24f-6c8741182845" CreationDate="2016-06-20T16:46:02.933" UserId="4620" Text="I am looking for the correct term for a type of problem solver. Since its hard to google for something without knowing its name, I hope that the good people of this stackexchange may be able to help me.&#xD;&#xA;&#xD;&#xA;When defining shapes in CAD systems based on constructive solid geometry, you start out with a (usually 2D) sketch, from which you extrude, rotate, or otherwise generate a 3D shape. You make this sketch by defining a set of curves (lines, arcs, bezier, etc.) and then defining a set of constraints. This is co-linear to that, this line is parallel to that line, the distance here is so and so.&#xD;&#xA;&#xD;&#xA;If you define a valid combination of constraints, the CAD system can almost always find a configuration of the curves matching those constraints. What is the part of the CAD system called, that finds those solutions? Is there a good open-source implementation that I could use?&#xD;&#xA;&#xD;&#xA;I tried search terms like &quot;geometry solver&quot; or &quot;geometric solver&quot;, but I couldn't find anything relevant." ContentLicense="CC BY-SA 3.0" />
  <row Id="7476" PostHistoryTypeId="1" PostId="3651" RevisionGUID="64447736-9b8f-4950-b24f-6c8741182845" CreationDate="2016-06-20T16:46:02.933" UserId="4620" Text="Solving a set of Geometry Constraints - What's that Methode called?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7477" PostHistoryTypeId="3" PostId="3651" RevisionGUID="64447736-9b8f-4950-b24f-6c8741182845" CreationDate="2016-06-20T16:46:02.933" UserId="4620" Text="|computational-geometry|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7478" PostHistoryTypeId="2" PostId="3652" RevisionGUID="3457a93b-038c-48a2-94eb-1d02dfb44f23" CreationDate="2016-06-20T17:29:05.517" UserId="56" Text="I've worked with various interpolation algorithms including linear, cubic (and bilinear and bicubic), other bezier (and nurbs, etc) based interpolations, lagrange interpolation and some others, but I haven't been able to find any basic info that explains what bilateral upsampling is.&#xD;&#xA;&#xD;&#xA;I have been able to find information on [Joint Bilateral Upsampling][1] which as best as I can tell interpolates multiple pieces of data in parallel, using hints from each to help the other interpolate better, but am having trouble separating the info of BU and JBU.&#xD;&#xA;&#xD;&#xA;Is anyone able to explain the basic ideas of what bilateral upsampling is about?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://johanneskopf.de/publications/jbu/" ContentLicense="CC BY-SA 3.0" />
  <row Id="7479" PostHistoryTypeId="1" PostId="3652" RevisionGUID="3457a93b-038c-48a2-94eb-1d02dfb44f23" CreationDate="2016-06-20T17:29:05.517" UserId="56" Text="What is bilateral upsampling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7480" PostHistoryTypeId="3" PostId="3652" RevisionGUID="3457a93b-038c-48a2-94eb-1d02dfb44f23" CreationDate="2016-06-20T17:29:05.517" UserId="56" Text="|image-processing|interpolation|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7481" PostHistoryTypeId="2" PostId="3653" RevisionGUID="f5bd3a9b-02ed-4c21-8211-5844a00f0688" CreationDate="2016-06-20T19:31:53.083" UserId="38" Text="Its called a [geometric constraints solver](https://www.cs.purdue.edu/homes/cmh/distribution/papers/Constraints/CAD95.pdf) (good primer on subject). You can find a open source solver as part of [Open Cascade](http://www.opencascade.com/) but its a bit convoluted to get going. A simpler solution for just solving, but also 3D solver capable, is [geosolver](http://geosolver.sourceforge.net/).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7482" PostHistoryTypeId="2" PostId="3654" RevisionGUID="d81c806d-b348-4190-bb4a-f2af3654308f" CreationDate="2016-06-20T19:47:03.700" UserId="3184" Text="If I understand you correctly, you have a 3D model, and a video of the real world object? This sounds like a job for photogrammetry. Using a photogrammetry plugin, you can derive a model of what is seen in the video, and a texture map of it. The derived model probably won't be exactly like your 3D model, but you may be able to remap the texture map back onto your 3D model. Doing a search on photogrammetry and blender should give you some good links." ContentLicense="CC BY-SA 3.0" />
  <row Id="7483" PostHistoryTypeId="5" PostId="3653" RevisionGUID="6929101b-16d6-429f-8076-6873881facca" CreationDate="2016-06-20T20:51:25.727" UserId="38" Comment="added 686 characters in body" Text="Its called a [geometric constraints solver](https://www.cs.purdue.edu/homes/cmh/distribution/papers/Constraints/CAD95.pdf) (good primer on subject). You can find a open source solver as part of [Open Cascade](http://www.opencascade.com/) but its a bit convoluted to get going. A simpler solution for just solving, but also 3D solver capable, is [geosolver](http://geosolver.sourceforge.net/).&#xD;&#xA;&#xD;&#xA;Making your own (algebraic solution being easiest to write) is also not that hard, just a bit of work to make it automatically write the equations. Take the following drawing as a example (made and solved with mathematica):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can simply conclude that its a sum of vectors that has to loop back at the origin thus:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;7\begin{pmatrix}\sin(15^\circ)\\ \cos(15^\circ)\end{pmatrix}+5\begin{pmatrix}\sin(120^\circ)\\ \cos(120^\circ)\end{pmatrix}+2\begin{pmatrix}\sin(195^\circ)\\ \cos(195^\circ)\end{pmatrix}+4\begin{pmatrix}\sin(\delta)\\ \cos(\delta)\end{pmatrix}+x\begin{pmatrix}\sin(-90^\circ)\\ \cos(-90^\circ)\end{pmatrix}=0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And solve the 2 unknowns from 2 equations.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hoDbc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7484" PostHistoryTypeId="2" PostId="3655" RevisionGUID="d679a99d-2390-4015-8298-9b89be50cd1b" CreationDate="2016-06-20T20:56:30.480" UserId="523" Text="It seems like you're asking two things.  I can't really speak technically about JBU, but I can give an overview of the necessary concepts and bilateral filtering generally.  You'll probably need to find more details yourself, but this should give a coherent structure to start from.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;##Fixing &quot;Image&quot;s&#xD;&#xA;&#xD;&#xA;Many image-processing people view filtering as either something to be done as a post-process, or as a way to scale images.  The mathematician's perspective is more accurate, descriptive, and complex.&#xD;&#xA;&#xD;&#xA;When you have an image file, you don't have a real image.  You have pixel &quot;values&quot;, which are strictly valid _only_ at the center of pixels.  Roughly speaking, each pixel has an _area_ that takes on that color.  Mathematically, what you're doing is using a _nearest-neighbor reconstruction filter_ to reconstruct the true image from pixel values.  So **an &quot;image&quot; is really a set of samples and a reconstruction filter, typically nearest-neighbor**.&#xD;&#xA;&#xD;&#xA;##Resampling&#xD;&#xA;&#xD;&#xA;When you upscale an image, what you're really doing is _resampling_.  How do you do this?  You take your signal, and generate a new set of samples from it.  But for an image, I just said we don't _have_ the real image; we have to reconstruct it first.  So a typical resampling procedure looks like this:&#xD;&#xA;&#xD;&#xA;1. Take your pixel values.&#xD;&#xA;2. Reconstruct an image between the values, which live at pixel centers, by using reconstruction filtering.&#xD;&#xA;3. Measure a new set of samples from the reconstructed image, possibly spaced differently.&#xD;&#xA;4. Throw away the old samples and use the new ones.&#xD;&#xA;&#xD;&#xA;**The key point is that the reconstruction filter used is the &quot;filter&quot; used for resampling.**  For example, a &quot;bicubic upsample&quot; would use a bicubic reconstruction filter.&#xD;&#xA;&#xD;&#xA;It turns out that if you use a sinc function for the reconstruction filter, and you don't shrink the image, you get (theoretically) the same image back.  In fact, if you upscale the image and then downscale it again, you'll get the same answer.  This isn't generally true for any other filter.&#xD;&#xA;&#xD;&#xA;Most filters approximate a sinc filter to more or lesser degrees.  Deviations result in image loss.&#xD;&#xA;&#xD;&#xA;##Filtering&#xD;&#xA;&#xD;&#xA;If you use the same before/after sampling rate, you do something called &quot;filtering&quot;.  Formally, **filtering is resampling without a change in sample rate.  Filtering is a special case of resampling.**&#xD;&#xA;&#xD;&#xA;The only possible purpose to filtering it to throw away information (e.g. a Gaussian) or possibly also to distort or add spurious information (e.g. a Sobel).&#xD;&#xA;&#xD;&#xA;#Bilateral Filtering&#xD;&#xA;&#xD;&#xA;You can use many different filters for filtering.  Bilateral filtering is one of them.  It don't believe it's considered state-of-the-art for any purpose now (though I don't know what is; probably some newfangled machine-learning thing I expect).&#xD;&#xA;&#xD;&#xA;A bilateral filter is a non-linear filter, meaning it doesn't have a nice Fourier representation.  Conceptually, it is like a Gaussian, but the source colors themselves also factor into a pixel's &quot;distance&quot; from others.  This tends to smooth flat areas while preserving edges.&#xD;&#xA;&#xD;&#xA;#Bilateral Upscaling&#xD;&#xA;&#xD;&#xA;By now, I hope you see where I'm going with this: any filter you can use for filtering, you can use for upscaling or downscaling, which are really the same thing (because all of it is resampling).&#xD;&#xA;&#xD;&#xA;If you've implemented a bilateral filter, you should be able to rather simply implement a bilateral filter resampler--just as, if you've implemented a Gaussian filter, you should be able to implement a Gaussian filter resampler.&#xD;&#xA;&#xD;&#xA;The only difficulty may be the definitions.  Unfortunately, the distinction between filtering and resampling is systemically muddied to occasional non-existence in the image-processing literature.  For implementing a bilateral-type filter, I would rely heavily on its similarities to Gaussian resampling.  IIRC (I haven't read the paper in years) bilateral filtering is posed in terms of pixels, not samples." ContentLicense="CC BY-SA 3.0" />
  <row Id="7485" PostHistoryTypeId="5" PostId="3653" RevisionGUID="03035329-9083-4f43-8c9f-f676ce26c7e7" CreationDate="2016-06-20T20:58:07.190" UserId="38" Comment="added 30 characters in body" Text="Its called a [geometric constraints solver](https://www.cs.purdue.edu/homes/cmh/distribution/papers/Constraints/CAD95.pdf) (good primer on subject). You can find a open source solver as part of [Open Cascade](http://www.opencascade.com/) but its a bit convoluted to get going. A simpler solution for just solving, but also 3D solver capable, is [geosolver](http://geosolver.sourceforge.net/).&#xD;&#xA;&#xD;&#xA;Making your own (algebraic solution being easiest to write) is also not that hard, just a bit of work to make it automatically write the equations (and be efficient at solving). Take the following drawing as a example (made and solved with Mathematica):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can simply conclude that its a sum of vectors that has to loop back at the origin thus:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;7\begin{pmatrix}\sin(15^\circ)\\ \cos(15^\circ)\end{pmatrix}+5\begin{pmatrix}\sin(120^\circ)\\ \cos(120^\circ)\end{pmatrix}+2\begin{pmatrix}\sin(195^\circ)\\ \cos(195^\circ)\end{pmatrix}+4\begin{pmatrix}\sin(\delta)\\ \cos(\delta)\end{pmatrix}+x\begin{pmatrix}\sin(-90^\circ)\\ \cos(-90^\circ)\end{pmatrix}=0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And solve the 2 unknowns from 2 equations, either algebraically or by using a gradient descent solver of some kind.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hoDbc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7487" PostHistoryTypeId="2" PostId="3656" RevisionGUID="25d329be-64ca-4165-9604-a074dbfc2cf9" CreationDate="2016-06-21T01:25:58.780" UserId="1614" Text="Maybe you need to write down the spec of what you want to do first, usually when you know the problem you know the solution. So mostly, life is a matter of finding the problems.&#xD;&#xA;&#xD;&#xA;I believe in your case, what you want to do is replicate what GPUs were in 1996, that is, a brute force texture filler specialized hardware.&#xD;&#xA;&#xD;&#xA;GPUs did nothing back then, no vertex transform, no 3d, they just took regions in 2d (triangles after projection) and filled them. The only 3d-like operation that the hardware could do, was the division by w during rasterization. pretty handy to have dedicated hardware to do that, since CPUs suck at this.&#xD;&#xA;&#xD;&#xA;So, if you want to do wireframe, basically your hardware will be a [bresenham][1] implementation but in FPGA. Are you sure this makes any sense ?  &#xD;&#xA;Bresenham parallelization will be an interesting job though, you can split your space in screen tiles and do grid-scheduling (eg `ALU[i], i = pixelX / 32 % numalu` for 32 pixel wide tiles). You'll need to clip your lines to the tiles borders.&#xD;&#xA;&#xD;&#xA;Thouh it seems to me that your biggest challenge will be to convert your frontbuffer to display port protocol. Or VGA if you still have that. maybe some ready to use chips exist for that. (or fpga schemas that you can load and append to your design?)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="7489" PostHistoryTypeId="5" PostId="3653" RevisionGUID="98e4e404-a746-4e8f-9521-4a3c71670504" CreationDate="2016-06-21T06:38:59.667" UserId="38" Comment="added 6 characters in body" Text="Its called a **geometric constraints solver** (a [good primer](https://www.cs.purdue.edu/homes/cmh/distribution/papers/Constraints/CAD95.pdf) on subject). You can find a open source solver as part of [Open Cascade](http://www.opencascade.com/) but its a bit convoluted to get going. A simpler solution for just solving, but also 3D solver capable, is [geosolver](http://geosolver.sourceforge.net/).&#xD;&#xA;&#xD;&#xA;Making your own (algebraic solution being easiest to write) is also not that hard, just a bit of work to make it automatically write the equations (and be efficient at solving). Take the following drawing as a example (made and solved with Mathematica):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can simply conclude that its a sum of vectors that has to loop back at the origin thus:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;7\begin{pmatrix}\sin(15^\circ)\\ \cos(15^\circ)\end{pmatrix}+5\begin{pmatrix}\sin(120^\circ)\\ \cos(120^\circ)\end{pmatrix}+2\begin{pmatrix}\sin(195^\circ)\\ \cos(195^\circ)\end{pmatrix}+4\begin{pmatrix}\sin(\delta)\\ \cos(\delta)\end{pmatrix}+x\begin{pmatrix}\sin(-90^\circ)\\ \cos(-90^\circ)\end{pmatrix}=0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And solve the 2 unknowns from 2 equations, either algebraically or by using a gradient descent solver of some kind.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hoDbc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7490" PostHistoryTypeId="4" PostId="3651" RevisionGUID="26b3a439-a646-4bb4-b603-5a1d96e1f0a8" CreationDate="2016-06-21T08:12:11.553" UserId="231" Comment="Minor typo" Text="Solving a set of Geometry Constraints - What's that Method called?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7491" PostHistoryTypeId="5" PostId="3656" RevisionGUID="e5731e27-ca95-4bc7-a59c-53a653f9cf51" CreationDate="2016-06-21T08:19:30.473" UserId="231" Comment="Minor typos. Please feel free to revert anything that changes your intended meaning." Text="Maybe you need to write down the spec of what you want to do first, usually when you know the problem you know the solution. So mostly, life is a matter of finding the problems.&#xD;&#xA;&#xD;&#xA;I believe in your case, what you want to do is replicate what GPUs were in 1996, that is, a brute force texture filler specialized hardware.&#xD;&#xA;&#xD;&#xA;GPUs did nothing back then, no vertex transform, no 3d, they just took regions in 2d (triangles after projection) and filled them. The only 3d-like operation that the hardware could do, was the division by w during rasterization. Pretty handy to have dedicated hardware to do that, since CPUs suck at this.&#xD;&#xA;&#xD;&#xA;So, if you want to do wireframe, basically your hardware will be a [bresenham][1] implementation but in FPGA. Are you sure this makes any sense?  &#xD;&#xA;Bresenham parallelization will be an interesting job though, you can split your space into screen tiles and do grid-scheduling (eg `ALU[i], i = pixelX / 32 % numalu` for 32 pixel wide tiles). You'll need to clip your lines to the tiles borders.&#xD;&#xA;&#xD;&#xA;Though it seems to me that your biggest challenge will be to convert your frontbuffer to display port protocol. Or VGA if you still have that. maybe some ready to use chips exist for that (or FPGA schemas that you can load and append to your design?).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="7492" PostHistoryTypeId="5" PostId="3655" RevisionGUID="7ea3ad54-5263-4230-bd9f-20e6468ee768" CreationDate="2016-06-21T08:35:13.940" UserId="231" Comment="Minor typo" Text="It seems like you're asking two things.  I can't really speak technically about JBU, but I can give an overview of the necessary concepts and bilateral filtering generally.  You'll probably need to find more details yourself, but this should give a coherent structure to start from.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;##Fixing &quot;Image&quot;s&#xD;&#xA;&#xD;&#xA;Many image-processing people view filtering as either something to be done as a post-process, or as a way to scale images.  The mathematician's perspective is more accurate, descriptive, and complex.&#xD;&#xA;&#xD;&#xA;When you have an image file, you don't have a real image.  You have pixel &quot;values&quot;, which are strictly valid _only_ at the center of pixels.  Roughly speaking, each pixel has an _area_ that takes on that color.  Mathematically, what you're doing is using a _nearest-neighbor reconstruction filter_ to reconstruct the true image from pixel values.  So **an &quot;image&quot; is really a set of samples and a reconstruction filter, typically nearest-neighbor**.&#xD;&#xA;&#xD;&#xA;##Resampling&#xD;&#xA;&#xD;&#xA;When you upscale an image, what you're really doing is _resampling_.  How do you do this?  You take your signal, and generate a new set of samples from it.  But for an image, I just said we don't _have_ the real image; we have to reconstruct it first.  So a typical resampling procedure looks like this:&#xD;&#xA;&#xD;&#xA;1. Take your pixel values.&#xD;&#xA;2. Reconstruct an image between the values, which live at pixel centers, by using reconstruction filtering.&#xD;&#xA;3. Measure a new set of samples from the reconstructed image, possibly spaced differently.&#xD;&#xA;4. Throw away the old samples and use the new ones.&#xD;&#xA;&#xD;&#xA;**The key point is that the reconstruction filter used is the &quot;filter&quot; used for resampling.**  For example, a &quot;bicubic upsample&quot; would use a bicubic reconstruction filter.&#xD;&#xA;&#xD;&#xA;It turns out that if you use a sinc function for the reconstruction filter, and you don't shrink the image, you get (theoretically) the same image back.  In fact, if you upscale the image and then downscale it again, you'll get the same answer.  This isn't generally true for any other filter.&#xD;&#xA;&#xD;&#xA;Most filters approximate a sinc filter to more or lesser degrees.  Deviations result in image loss.&#xD;&#xA;&#xD;&#xA;##Filtering&#xD;&#xA;&#xD;&#xA;If you use the same before/after sampling rate, you do something called &quot;filtering&quot;.  Formally, **filtering is resampling without a change in sample rate.  Filtering is a special case of resampling.**&#xD;&#xA;&#xD;&#xA;The only possible purpose to filtering it to throw away information (e.g. a Gaussian) or possibly also to distort or add spurious information (e.g. a Sobel).&#xD;&#xA;&#xD;&#xA;#Bilateral Filtering&#xD;&#xA;&#xD;&#xA;You can use many different filters for filtering.  Bilateral filtering is one of them.  I don't believe it's considered state-of-the-art for any purpose now (though I don't know what is; probably some newfangled machine-learning thing I expect).&#xD;&#xA;&#xD;&#xA;A bilateral filter is a non-linear filter, meaning it doesn't have a nice Fourier representation.  Conceptually, it is like a Gaussian, but the source colors themselves also factor into a pixel's &quot;distance&quot; from others.  This tends to smooth flat areas while preserving edges.&#xD;&#xA;&#xD;&#xA;#Bilateral Upscaling&#xD;&#xA;&#xD;&#xA;By now, I hope you see where I'm going with this: any filter you can use for filtering, you can use for upscaling or downscaling, which are really the same thing (because all of it is resampling).&#xD;&#xA;&#xD;&#xA;If you've implemented a bilateral filter, you should be able to rather simply implement a bilateral filter resampler - just as, if you've implemented a Gaussian filter, you should be able to implement a Gaussian filter resampler.&#xD;&#xA;&#xD;&#xA;The only difficulty may be the definitions.  Unfortunately, the distinction between filtering and resampling is systemically muddied to occasional non-existence in the image-processing literature.  For implementing a bilateral-type filter, I would rely heavily on its similarities to Gaussian resampling.  IIRC (I haven't read the paper in years) bilateral filtering is posed in terms of pixels, not samples." ContentLicense="CC BY-SA 3.0" />
  <row Id="7493" PostHistoryTypeId="2" PostId="3657" RevisionGUID="1e7721a6-4c0e-43b7-a5a7-3e1c03f7ddae" CreationDate="2016-06-21T08:50:29.780" UserId="2817" Text="This probably does not explore the full depth of the term, but the first thing that comes to my mind when I hear &quot;bilateral upsampling&quot; is depth-aware blending of low-resolution images onto high-resolution ones; for instance, when you render alpha-blended geometry to a half-resolution buffer (for performance savings) and then composite it back onto the main render target. Angelo Pesce [wrote a post][1] that explains it well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://c0de517e.blogspot.com/2016/02/downsampled-effects-with-depth-aware.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="7497" PostHistoryTypeId="2" PostId="3659" RevisionGUID="b1397a27-128e-4733-942f-83d6092933ac" CreationDate="2016-06-21T22:25:47.030" UserId="3098" Text="I am trying to pick objects on mouse click. For this I have followed [this tutorial][1], and tried to use the stencil buffer for this purpose.&#xD;&#xA;&#xD;&#xA;Inside &quot;game&quot; loop I am trying to draw 10 (5 pairs) 'pick'able triangles as follows:&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    glClearColor(red, green, blue, 1.0f);&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;	glClearStencil(0); // this is the default value&#xD;&#xA;&#xD;&#xA;    /* Enable stencil operations */&#xD;&#xA;	glEnable(GL_STENCIL_TEST);&#xD;&#xA;	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);&#xD;&#xA;    &#xD;&#xA;    /*Some other drawing not involving stencil buffer*/&#xD;&#xA;&#xD;&#xA;    int index = 0;&#xD;&#xA;	for (GLshort i = 0; i &lt; 5; i++)&#xD;&#xA;	{&#xD;&#xA;        //this returns 2 model matrices&#xD;&#xA;		auto modelMatrices = trianglePairs[i].getModelMatrices(); &#xD;&#xA;&#xD;&#xA;		for (GLshort j = 0; j &lt; 2; j++)&#xD;&#xA;		{&#xD;&#xA;			glStencilFunc(GL_ALWAYS, index, -1);&#xD;&#xA;			glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(modelMatrices[j]));&#xD;&#xA;			glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;			index++;&#xD;&#xA;		}&#xD;&#xA;        /*Some other drawing not involving stencil buffer*/&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;However, when I am trying to read back the stencil values, I am getting wrong values. I am reading back the values as (this is also a [part of the above-mentioned tutorial][2]):&#xD;&#xA;&#xD;&#xA;    GLuint index;&#xD;&#xA;    glReadPixels(xpos, Height - ypos - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &amp;index);&#xD;&#xA;&#xD;&#xA;Whenever, I click the first triangle of the pair I am getting values as `i+1`, whereas the correct value should have been `i`, and for the second triangle of the pair, I am getting `0` as `index`. &#xD;&#xA;&#xD;&#xA;Please let me know what am I missing here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection#Using_the_stencil_buffer_to_identify_objects&#xD;&#xA;  [2]: https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection#Reading_back_information_from_the_framebuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="7498" PostHistoryTypeId="1" PostId="3659" RevisionGUID="b1397a27-128e-4733-942f-83d6092933ac" CreationDate="2016-06-21T22:25:47.030" UserId="3098" Text="Incorrect values written in stencil buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="7499" PostHistoryTypeId="3" PostId="3659" RevisionGUID="b1397a27-128e-4733-942f-83d6092933ac" CreationDate="2016-06-21T22:25:47.030" UserId="3098" Text="|opengl|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7500" PostHistoryTypeId="2" PostId="3660" RevisionGUID="3e88771e-8194-418e-8684-690b1b14036c" CreationDate="2016-06-22T00:47:44.900" UserId="4625" Text="(I previously posted this in [Mathematics][1], but realize this is also a CG question.  It will be interesting to see if the two posts get the same answer!)&#xD;&#xA;&#xD;&#xA;Is there a reasonable way to compute the area of the intersection of a square and a toroidal slice, as shown in the orange section below?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The motivation: I have a raster of square pixels, and I'm converting it to &quot;polar pixels&quot; -- I want to find out the contribution of each cartesian pixel to each polar pixel.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/questions/1835146/area-of-the-intersection-of-a-square-and-a-toroidal-slice&#xD;&#xA;  [2]: https://i.stack.imgur.com/Tz312.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7501" PostHistoryTypeId="1" PostId="3660" RevisionGUID="3e88771e-8194-418e-8684-690b1b14036c" CreationDate="2016-06-22T00:47:44.900" UserId="4625" Text="Computing the area intersection of a square and a toroidal slice" ContentLicense="CC BY-SA 3.0" />
  <row Id="7502" PostHistoryTypeId="3" PostId="3660" RevisionGUID="3e88771e-8194-418e-8684-690b1b14036c" CreationDate="2016-06-22T00:47:44.900" UserId="4625" Text="|polygon|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7503" PostHistoryTypeId="2" PostId="3661" RevisionGUID="284b172b-7b1c-46f0-9893-74c6d8067873" CreationDate="2016-06-22T04:38:08.857" UserId="116" Text="I am basically following [this tutorial](http://ogldev.atspace.co.uk/www/tutorial18/tutorial18.html) about diffuse lighting in OpenGL.&#xD;&#xA;I did some modifications but the idea is the same, at least that's what I think. However, my fragment shader is not showing any colors. I checked and rechecked my uniform variables and light properties and data is ok on CPU side (don't know how to check on GPU side, though).&#xD;&#xA;Here are my shaders where I cannot spot any errors, maybe someone can help me out&#xD;&#xA;&#xD;&#xA;**VERTEX SHADER**&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;&#xD;&#xA;    in vec4 vposition;&#xD;&#xA;    in vec3 vnormal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 M;&#xD;&#xA;    uniform mat4 VP;&#xD;&#xA;    &#xD;&#xA;    out vec4 fcolor;&#xD;&#xA;    out vec3 fnormal;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vposition * M * VP;&#xD;&#xA;        fcolor = vposition + vec4(0.5);&#xD;&#xA;        fnormal = (M * vec4(vnormal, 0.0)).xyz;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**FRAGMENT SHADER**&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    &#xD;&#xA;    in vec4 fcolor;&#xD;&#xA;    in vec3 fnormal;&#xD;&#xA;    &#xD;&#xA;    out vec4 color;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 lightColor;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform float lightIntensity;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec3 N = normalize(fnormal);&#xD;&#xA;        vec3 L = normalize(lightDirection);&#xD;&#xA;        float visibility = clamp(dot(N, L), 0.0, 1.0);&#xD;&#xA;        color = fcolor * vec4(lightColor, 1.0) * lightIntensity * visibility;&#xD;&#xA;        //color = vec4(1.0); Not even this shows model in complete white&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;The buffer for my mesh are created like follows, maybe it helps out detecting the problem&#xD;&#xA;&#xD;&#xA;    void Mesh::initBuffers()&#xD;&#xA;    {&#xD;&#xA;        glGenVertexArrays(1, &amp;m_verticesVao);&#xD;&#xA;    	glBindVertexArray(m_verticesVao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;m_positionsVbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_positionsVbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &amp;m_positions[0], GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;m_normalsVbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_normalsVbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &amp;m_normals[0], GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;    	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;m_positionsEbo);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_positionsEbo);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_numIndices * 3 * sizeof(unsigned int), &amp;m_indices[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	glBindVertexArray(0);&#xD;&#xA;        &#xD;&#xA;        m_initBuffers = true;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="7504" PostHistoryTypeId="1" PostId="3661" RevisionGUID="284b172b-7b1c-46f0-9893-74c6d8067873" CreationDate="2016-06-22T04:38:08.857" UserId="116" Text="Why is my fragment shader not showing any colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7505" PostHistoryTypeId="3" PostId="3661" RevisionGUID="284b172b-7b1c-46f0-9893-74c6d8067873" CreationDate="2016-06-22T04:38:08.857" UserId="116" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7506" PostHistoryTypeId="5" PostId="3659" RevisionGUID="f557abaf-2482-4be0-abd9-f7989235b68c" CreationDate="2016-06-22T07:21:26.687" UserId="3098" Comment="added 318 characters in body" Text="I am trying to pick objects on mouse click. For this I have followed [this tutorial][1], and tried to use the stencil buffer for this purpose.&#xD;&#xA;&#xD;&#xA;Inside &quot;game&quot; loop I am trying to draw 10 (5 pairs) 'pick'able triangles as follows:&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    glClearColor(red, green, blue, 1.0f);&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;	glClearStencil(0); // this is the default value&#xD;&#xA;&#xD;&#xA;    /* Enable stencil operations */&#xD;&#xA;	glEnable(GL_STENCIL_TEST);&#xD;&#xA;	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);&#xD;&#xA;    &#xD;&#xA;    /*Some other drawing not involving stencil buffer*/&#xD;&#xA;&#xD;&#xA;    GLuint index = 1;&#xD;&#xA;	for (GLshort i = 0; i &lt; 5; i++)&#xD;&#xA;	{&#xD;&#xA;        //this returns 2 model matrices&#xD;&#xA;		auto modelMatrices = trianglePairs[i].getModelMatrices(); &#xD;&#xA;&#xD;&#xA;		for (GLshort j = 0; j &lt; 2; j++)&#xD;&#xA;		{&#xD;&#xA;			glStencilFunc(GL_ALWAYS, index, -1);&#xD;&#xA;			glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(modelMatrices[j]));&#xD;&#xA;			glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;			index++;&#xD;&#xA;		}&#xD;&#xA;        /*Some other drawing not involving stencil buffer*/&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    /*Some other drawing not involving stencil buffer*/&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;However, when I am trying to read back the stencil values, I am getting wrong values. I am reading back the values as (this is also a [part of the above-mentioned tutorial][2]):&#xD;&#xA;&#xD;&#xA;    GLuint index;&#xD;&#xA;    glReadPixels(xpos, Height - ypos - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &amp;index);&#xD;&#xA;&#xD;&#xA;Whenever, I click the first triangle of the pair I am getting values as `i+1`, whereas the correct value should have been `i`, and for the second triangle of the pair, I am getting `0` as `index`. &#xD;&#xA;&#xD;&#xA;Please let me know what am I missing here?&#xD;&#xA;&#xD;&#xA;**Update**&#xD;&#xA;I have found that stencil values can be applied on quads. When I tried to apply the stencil value on unit square (instead of triangles) it worked correctly. However, when the quad is not unit square, it returns `0`. What is the reason for this?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection#Using_the_stencil_buffer_to_identify_objects&#xD;&#xA;  [2]: https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection#Reading_back_information_from_the_framebuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="7507" PostHistoryTypeId="5" PostId="3647" RevisionGUID="3ba235a9-1df8-467e-a091-a60ed1230534" CreationDate="2016-06-22T12:27:08.380" UserId="182" Comment="Added basic information about MRT." Text="1. _The best results_ strongly depend on your use case. They also depend on what effect you want to achieve. Sobel is just an edge detection filter: the edges will depend on the input signal, choosing that input signal is up to you.&#xD;&#xA;&#xD;&#xA;  Here you are using the color image as an input, and the filter rightfully detects faint edges in the blue gradient, while the edges of the cube get interrupted where its color is too close from the background color.&#xD;&#xA;&#xD;&#xA;  Since I assume your program is also responsible for drawing the cube, you have access to other information that you can feed to your Sobel filter. For example depth and normals are good candidates for edge detection. The albedo before lighting could be used to. Test with different inputs and decide which ones to use depending on the results you get.&#xD;&#xA;&#xD;&#xA;2. Regarding your question about how to combine the edge information, I suggest you filter `g` a little before using it. Then you can use it to interpolate between the original color and the wanted edge color.&#xD;&#xA;&#xD;&#xA;  For example you could try something like this:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;        float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;&#xD;&#xA;        // Try different values and see what happens&#xD;&#xA;        g = smoothstep(0.4, 0.6, g);&#xD;&#xA;&#xD;&#xA;        vec3 edgeColor = vec3(1., 0., 0.2);&#xD;&#xA;        color = vec4(mix(diffuse, edgeColor, g), 1.);&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;###Addendum&#xD;&#xA;To use depth or normals, you would need to save them in a texture if that's not done already. When you create the frame buffer for your regular rendering pass, you can attach various textures to it (see [`glFramebufferTexture2D`](https://www.opengl.org/sdk/docs/man/html/glFramebufferTexture.xhtml)) and write other information to them than just the color of the scene.&#xD;&#xA;&#xD;&#xA;If you attach a depth texture (with `GL_DEPTH_ATTACHMENT`), it will be used automatically for depth. If you attach one or several color textures (with `GL_COLOR_ATTACHMENTi`), you can write to them by declaring several outputs to your fragment shaders (this used to be done with `gl_FragData`; either way, see [`glDrawBuffers`](https://www.opengl.org/sdk/docs/man/html/glDrawBuffers.xhtml)).&#xD;&#xA;&#xD;&#xA;For more information on the topic, look up _&quot;Multi Render Target&quot;_ (MRT).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7508" PostHistoryTypeId="5" PostId="3661" RevisionGUID="a3b4dd11-0eaa-4e84-8ea8-f10015852c9b" CreationDate="2016-06-22T13:11:09.380" UserId="116" Comment="added 118 characters in body" Text="I am basically following [this tutorial](http://ogldev.atspace.co.uk/www/tutorial18/tutorial18.html) about diffuse lighting in OpenGL.&#xD;&#xA;I did some modifications but the idea is the same, at least that's what I think. However, my fragment shader is not showing any colors. I checked and rechecked my uniform variables and light properties and data is ok on CPU side (don't know how to check on GPU side, though).&#xD;&#xA;Here are my shaders where I cannot spot any errors, maybe someone can help me out&#xD;&#xA;&#xD;&#xA;**VERTEX SHADER**&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;&#xD;&#xA;    in vec4 vposition;&#xD;&#xA;    in vec3 vnormal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 M;&#xD;&#xA;    uniform mat4 VP;&#xD;&#xA;    &#xD;&#xA;    out vec4 fcolor;&#xD;&#xA;    out vec3 fnormal;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vposition * M * VP;&#xD;&#xA;        fcolor = vposition + vec4(0.5);&#xD;&#xA;        fnormal = (M * vec4(vnormal, 0.0)).xyz;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**FRAGMENT SHADER**&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    &#xD;&#xA;    in vec4 fcolor;&#xD;&#xA;    in vec3 fnormal;&#xD;&#xA;    &#xD;&#xA;    out vec4 color;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 lightColor;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform float lightIntensity;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec3 N = normalize(fnormal);&#xD;&#xA;        vec3 L = normalize(lightDirection);&#xD;&#xA;        float visibility = clamp(dot(N, L), 0.0, 1.0);&#xD;&#xA;        color = fcolor * vec4(lightColor, 1.0) * lightIntensity * visibility;&#xD;&#xA;        //color = vec4(1.0); Not even this shows model in complete white&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;The buffer for my mesh are created like follows, maybe it helps out detecting the problem&#xD;&#xA;&#xD;&#xA;    void Mesh::initBuffers()&#xD;&#xA;    {&#xD;&#xA;        glGenVertexArrays(1, &amp;m_verticesVao);&#xD;&#xA;    	glBindVertexArray(m_verticesVao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;m_positionsVbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_positionsVbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &amp;m_positions[0], GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;m_normalsVbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_normalsVbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &amp;m_normals[0], GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;    	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;m_positionsEbo);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_positionsEbo);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_numIndices * 3 * sizeof(unsigned int), &amp;m_indices[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	glBindVertexArray(0);&#xD;&#xA;        &#xD;&#xA;        m_initBuffers = true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Commenting all the code related to the normal in shaders results in a correct rendered mesh with colors (or white)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7509" PostHistoryTypeId="5" PostId="3660" RevisionGUID="c47ad471-587a-4235-83b3-9debc5a846d1" CreationDate="2016-06-22T14:58:13.197" UserId="4625" Comment="toroidal slice =&gt; annular section (thank you @trichoplax), and deleting identical post in Maths.SE" Text="(I previously posted this in [Mathematics][1] (now deleted), but realize this is more of a CG question.)&#xD;&#xA;&#xD;&#xA;Is there a reasonable way to compute the area of the intersection of a square and an annular section, as shown in the orange section below?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The motivation: I have a raster of square pixels, and I'm converting it to &quot;polar pixels&quot; -- I want to find out the contribution of each cartesian pixel to each polar pixel.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://math.stackexchange.com/questions/1835146/area-of-the-intersection-of-a-square-and-a-toroidal-slice&#xD;&#xA;  [2]: https://i.stack.imgur.com/Tz312.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7510" PostHistoryTypeId="4" PostId="3660" RevisionGUID="c47ad471-587a-4235-83b3-9debc5a846d1" CreationDate="2016-06-22T14:58:13.197" UserId="4625" Comment="toroidal slice =&gt; annular section (thank you @trichoplax), and deleting identical post in Maths.SE" Text="Computing the area intersection of a square and an annular section" ContentLicense="CC BY-SA 3.0" />
  <row Id="7511" PostHistoryTypeId="5" PostId="3660" RevisionGUID="7206eff5-6875-4e56-b7a7-8ba5e595e1fa" CreationDate="2016-06-22T15:21:21.537" UserId="4625" Comment="reworked question to make it clear I'm converting cartesian to polar" Text="(I've largely revamped this entire question, though the motivation remains the same.)&#xD;&#xA;&#xD;&#xA;### revised question&#xD;&#xA;&#xD;&#xA;I want to convert a raster of cartesian pixels into polar pixels.  Is there a sensible algorithm for doing this?  For example, how do I compute the value of the shaded (polar) pixel in the image below, given the value of the three (cartesian) pixels that it overlaps?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### original question&#xD;&#xA;&#xD;&#xA;Is there a reasonable way to compute the area of the intersection of a square and an annular section, as shown in the orange section below?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The motivation: I have a raster of square pixels, and I'm converting it to &quot;polar pixels&quot; -- I want to find out the contribution of each cartesian pixel to each polar pixel.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c2Lh0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Tz312.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7512" PostHistoryTypeId="4" PostId="3660" RevisionGUID="7206eff5-6875-4e56-b7a7-8ba5e595e1fa" CreationDate="2016-06-22T15:21:21.537" UserId="4625" Comment="reworked question to make it clear I'm converting cartesian to polar" Text="Converting cartesian pixels to polar pixels" ContentLicense="CC BY-SA 3.0" />
  <row Id="7518" PostHistoryTypeId="2" PostId="3663" RevisionGUID="91ed7d47-6911-4d7a-915d-ed6bd2b81170" CreationDate="2016-06-23T17:00:01.107" UserId="4624" Text="I was under the impression that the frame buffer resolution always has to be the same as the physical screen resolution, so changing the software resolution settings would not affect rasterization. But after I made a demo and ran a profiler against it, the profiler told me that the frame buffer resolution changed according to my settings and fewer pixels were rasterized.&#xD;&#xA;&#xD;&#xA;This brings up other questions I am unable to figure out. Which part of the rendering pipeline does re-sample the frame buffer to match the screen resolution? And the re-sampling stage does not show up in the profiler (Intel GPA for Android), is it so fast that I can safely ignore it or I am missing something that would cost me here?&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="7519" PostHistoryTypeId="1" PostId="3663" RevisionGUID="91ed7d47-6911-4d7a-915d-ed6bd2b81170" CreationDate="2016-06-23T17:00:01.107" UserId="4624" Text="Is there a performance implication if the frame buffer resolution and the physical screen resolution are different?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7520" PostHistoryTypeId="3" PostId="3663" RevisionGUID="91ed7d47-6911-4d7a-915d-ed6bd2b81170" CreationDate="2016-06-23T17:00:01.107" UserId="4624" Text="|rasterizer|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7521" PostHistoryTypeId="2" PostId="3664" RevisionGUID="f4d77e6f-5297-4a5a-9c53-055f4c699049" CreationDate="2016-06-23T19:38:58.193" UserId="310" Text="This is the screen's [video scaler module][1]. &#xD;&#xA;Essentially, it is a dedicated piece of silicon that allows the user to use non-native screen resolutions. &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Video_scaler" ContentLicense="CC BY-SA 3.0" />
  <row Id="7522" PostHistoryTypeId="2" PostId="3665" RevisionGUID="4badba2d-b360-4cc6-8ae6-523982b00d7a" CreationDate="2016-06-24T01:28:27.813" UserId="48" Text="For PCs with discrete displays, the resampling to the screen resolution may happen either on the computer prior to the signal being sent to the display, as part of [window compositing](https://en.wikipedia.org/wiki/Compositing_window_manager), or on the display side. I don't think it's anything to worry about in terms of FPS, in either case, but it possibly could affect latency.&#xD;&#xA;&#xD;&#xA;It depends whether you're in &quot;true&quot; fullscreen (exclusive) mode or not. If the app renders to a window, including a borderless fullscreen window, then the window compositor (part of the OS) will be running each frame, and any upsampling needed can happen &quot;for free&quot; as part of that operation. In other words, I wouldn't expect an upsample during compositing to cost noticeably more than it does to do compositing in general (which is very cheap).&#xD;&#xA;&#xD;&#xA;On the other hand, if you're in true fullscreen and your app has exclusive control of the display, it's possible to set the video mode to something non-native and send your rendered image directly to the display, in which case the display's scaler chip will handle it, again without performance cost to you, since it's happening in parallel to anything going on with the GPU.&#xD;&#xA;&#xD;&#xA;You mentioned Android, so I assume you're working on a mobile device. In that case, I'm not sure if there is a scaler chip, or if the mobile GPU is just expected to always output at native resolution, in which case scaling would always be done on the GPU by the compositor software. (By the way, the reason the scaling doesn't show up in profiling is likely because it's being done by the OS rather than by your app.)&#xD;&#xA;&#xD;&#xA;That being said, though upscaling is very cheap, it does imply an extra pass that could increase input latency. With a borderless fullscreen window, if no other windows are visible on top of your app, and no scaling is required, the compositor could be short-circuited so that your app writes directly to the display output rather than passing through the compositor. (This is an optimization that the OS would have to perform when it detects that all the conditions are right.) Similarly, on the display, if no extra image processing is required including scaling, color correction, etc. then some stages of the display hardware might be bypassed. In either case, you could see lower latency when you render directly to native resolution than when you require scaling. This is a matter of concern for VR in particular." ContentLicense="CC BY-SA 3.0" />
  <row Id="7523" PostHistoryTypeId="2" PostId="3666" RevisionGUID="42328c74-53c0-4e6b-9d44-bb63cc5d63cf" CreationDate="2016-06-24T06:02:30.477" UserId="4625" Text="I called up an old officemate and CG expert, and after asking me a few questions he offered a simple solution.  I may have mangled a few details, but the basic idea follows:&#xD;&#xA;&#xD;&#xA;Subsample the polar coordinates to whatever degree of accuracy needed, treating each subsample as a point.  It's then trivial to find the cartesian pixel that contains each point.  Sum up the sub-sampled points for each polar pixel to get its final value.&#xD;&#xA;&#xD;&#xA;There's some subtlety in getting the weights right -- the guiding insight is that if the entire cartesian raster is flat gray, then each polar pixel should each have the same grayscale value.  And you could add on lots of other nuances, but the basic technique is intuitively and computationally straightforward.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7524" PostHistoryTypeId="5" PostId="3659" RevisionGUID="ce027c60-2d86-4d93-ba66-33296597f925" CreationDate="2016-06-24T07:40:36.590" UserId="3098" Comment="added 37 characters in body" Text="I am trying to pick objects on mouse click. For this I have followed [this tutorial][1], and tried to use the stencil buffer for this purpose.&#xD;&#xA;&#xD;&#xA;Inside &quot;game&quot; loop I am trying to draw 10 (5 pairs) 'pick'able triangles as follows:&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    glClearColor(red, green, blue, 1.0f);&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;	glClearStencil(0); // this is the default value&#xD;&#xA;&#xD;&#xA;    /* Enable stencil operations */&#xD;&#xA;	glEnable(GL_STENCIL_TEST);&#xD;&#xA;	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);&#xD;&#xA;    &#xD;&#xA;    /*Some other drawing not involving stencil buffer*/&#xD;&#xA;&#xD;&#xA;    GLuint index = 1;&#xD;&#xA;	for (GLshort i = 0; i &lt; 5; i++)&#xD;&#xA;	{&#xD;&#xA;        //this returns 2 model matrices&#xD;&#xA;		auto modelMatrices = trianglePairs[i].getModelMatrices(); &#xD;&#xA;&#xD;&#xA;		for (GLshort j = 0; j &lt; 2; j++)&#xD;&#xA;		{&#xD;&#xA;			glStencilFunc(GL_ALWAYS, index, -1);&#xD;&#xA;			glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(modelMatrices[j]));&#xD;&#xA;			glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;			index++;&#xD;&#xA;		}&#xD;&#xA;        /*Some other drawing not involving stencil buffer*/&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    /*Some other drawing not involving stencil buffer*/&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;However, when I am trying to read back the stencil values, I am getting wrong values. I am reading back the values as (this is also a [part of the above-mentioned tutorial][2]):&#xD;&#xA;&#xD;&#xA;    GLuint index;&#xD;&#xA;    glReadPixels(xpos, Height - ypos - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &amp;index);&#xD;&#xA;&#xD;&#xA;Whenever, I click the first triangle of the pair I am getting values as `i+1`, whereas the correct value should have been `i`, and for the second triangle of the pair, I am getting `0` as `index`. &#xD;&#xA;&#xD;&#xA;Please let me know what am I missing here?&#xD;&#xA;&#xD;&#xA;**Update**&#xD;&#xA;I have found that stencil values can be applied on quads. When I tried to apply the stencil value on rectangle it worked correctly. Though it is not the solution I was looking at, still, I can live with that. However, I would still like to know what was the problem with triangles.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection#Using_the_stencil_buffer_to_identify_objects&#xD;&#xA;  [2]: https://en.wikibooks.org/wiki/OpenGL_Programming/Object_selection#Reading_back_information_from_the_framebuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="7526" PostHistoryTypeId="5" PostId="3661" RevisionGUID="cdb29a1a-0d26-47ac-9b57-be0caba1d9ee" CreationDate="2016-06-24T16:34:55.077" UserId="116" Comment="added 91 characters in body" Text="I am basically following [this tutorial](http://ogldev.atspace.co.uk/www/tutorial18/tutorial18.html) about diffuse lighting in OpenGL.&#xD;&#xA;I did some modifications but the idea is the same, at least that's what I think. However, my fragment shader is not showing any colors. I checked and rechecked my uniform variables and light properties and data is ok on CPU side (don't know how to check on GPU side, though).&#xD;&#xA;Here are my shaders where I cannot spot any errors, maybe someone can help me out&#xD;&#xA;&#xD;&#xA;**VERTEX SHADER**&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;&#xD;&#xA;    in vec4 vposition;&#xD;&#xA;    in vec3 vnormal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 M;&#xD;&#xA;    uniform mat4 VP;&#xD;&#xA;    &#xD;&#xA;    out vec4 fcolor;&#xD;&#xA;    out vec3 fnormal;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vposition * M * VP;&#xD;&#xA;        fcolor = vposition + vec4(0.5);&#xD;&#xA;        fnormal = (M * vec4(vnormal, 0.0)).xyz;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**FRAGMENT SHADER**&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    &#xD;&#xA;    in vec4 fcolor;&#xD;&#xA;    in vec3 fnormal;&#xD;&#xA;    &#xD;&#xA;    out vec4 color;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 lightColor;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform float lightIntensity;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec3 N = normalize(fnormal);&#xD;&#xA;        vec3 L = normalize(lightDirection);&#xD;&#xA;        float visibility = clamp(dot(N, L), 0.0, 1.0);&#xD;&#xA;        color = fcolor * vec4(lightColor, 1.0) * lightIntensity * visibility;&#xD;&#xA;        //color = vec4(1.0); Not even this shows model in complete white&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;The buffer for my mesh are created like follows, maybe it helps out detecting the problem&#xD;&#xA;&#xD;&#xA;    void Mesh::initBuffers()&#xD;&#xA;    {&#xD;&#xA;        glGenVertexArrays(1, &amp;m_verticesVao);&#xD;&#xA;    	glBindVertexArray(m_verticesVao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;m_positionsVbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_positionsVbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &amp;m_positions[0], GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;m_normalsVbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_normalsVbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, m_numVertices * 3 * sizeof(float), &amp;m_normals[0], GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;    	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;m_positionsEbo);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_positionsEbo);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_numIndices * 3 * sizeof(unsigned int), &amp;m_indices[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	glBindVertexArray(0);&#xD;&#xA;        &#xD;&#xA;        m_initBuffers = true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Commenting all the code related to the normal in shaders results in a correct rendered mesh with colors (or white)&#xD;&#xA;&#xD;&#xA;If it helps, you can checkout [my code](https://github.com/BRabbit27/OGLPlayground.git)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7527" PostHistoryTypeId="2" PostId="3667" RevisionGUID="85883e25-5d7b-4ef5-8118-dd55e5aaca13" CreationDate="2016-06-24T18:10:04.783" UserId="3098" Text="OK, so this not really an answer, rather just sharing what I have learned. &#xD;&#xA;&#xD;&#xA;To clarify, shape of the object has nothing to do with this problem at all. Be it a triangle or rectangle, and wherever you click on that object, this method should work (the 'But' for this part is explained below).&#xD;&#xA;&#xD;&#xA;I think stencil buffer values are associated with each pixel *on screen*, and it does not directly maps to the OpenGL window space. Initially I was using a window size that is smaller than my screen size and on top of that it was not full screen. Each time I started (debugging from VS 2015), the window appeared not exactly at `(0, 0)` on the screen. Some of the screen space is also consumed by the window bar at the top. I think this is the reason for getting erratic values when reading back the data from stencil buffer.&#xD;&#xA;&#xD;&#xA;So as a simple solution to this problem what I did is to make the window full screen, and everything worked like charm. As I use `GLFW`, here is how I have done it:&#xD;&#xA;&#xD;&#xA;    glfwCreateWindow(Width, Height, &quot;Title&quot;, glfwGetPrimaryMonitor(), nullptr);&#xD;&#xA;&#xD;&#xA;Just used `glfwGetPrimaryMonitor()`, while creating the window. And that's it.&#xD;&#xA;&#xD;&#xA;And yes, it works for triangles too." ContentLicense="CC BY-SA 3.0" />
  <row Id="7528" PostHistoryTypeId="2" PostId="3668" RevisionGUID="44f8e559-2797-40c8-8bcb-6ae2d15bc87a" CreationDate="2016-06-24T18:42:43.210" UserId="2308" Text="So I have a batch draw call I am doing with various squares. I have a 4x4 tile map with the numbers 1-16 going in right/down order.&#xD;&#xA;&#xD;&#xA;When it gets to the fragment shader their is a varying float &quot;id&quot; that holds the number. In a perfect world if the id was 0, it would sample the top left and display &quot;0&quot;, if the id was 4 it would sample the top right and display &quot;4&quot;.&#xD;&#xA;&#xD;&#xA;Thankfully this is mostly working! However the numbers 5, 9, and 13 (which happen to be on the left of the tile map flicker! The values on these squares just change frequently. &#xD;&#xA;&#xD;&#xA;I have traced it down to being the fault of the sample location. And probably this function here: The goal is to take the id and return the proper row and column to texture map.&#xD;&#xA;&#xD;&#xA;    vec2 getGrid()&#xD;&#xA;    {&#xD;&#xA;        return vec2(float(int(mod(id, 4.0))), float(floor(id / 4.0)));&#xD;&#xA;    }&#xD;&#xA;It appears that the flickering ones have a constantly changing x result from &quot;getGrid()&quot; and most of the squares have an occasionally changing y result from the &quot;getGrid()&quot; call. I really have no clue why this is happening!&#xD;&#xA;&#xD;&#xA;It probably has something to do with the way glsl does math because id and everything else (I have checked) and they are constant.&#xD;&#xA;&#xD;&#xA;Incase it helps here is the tile map. The texture is actually 2000 x 2000 due to the size these need to be. It will be hard to see because the numbers are white and the background is grey.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RHOzG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7529" PostHistoryTypeId="1" PostId="3668" RevisionGUID="44f8e559-2797-40c8-8bcb-6ae2d15bc87a" CreationDate="2016-06-24T18:42:43.210" UserId="2308" Text="Flickering tile map" ContentLicense="CC BY-SA 3.0" />
  <row Id="7530" PostHistoryTypeId="3" PostId="3668" RevisionGUID="44f8e559-2797-40c8-8bcb-6ae2d15bc87a" CreationDate="2016-06-24T18:42:43.210" UserId="2308" Text="|texture|tile-based-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7531" PostHistoryTypeId="2" PostId="3669" RevisionGUID="19600557-c4a2-4fc7-b2a9-c4dba493a802" CreationDate="2016-06-24T19:14:01.930" UserId="2308" Text="I realized that the problem was that I was sending the instance id to the fragment shader via a varying, somehow that was causing issues even though each vertex should have had the same id." ContentLicense="CC BY-SA 3.0" />
  <row Id="7535" PostHistoryTypeId="2" PostId="3671" RevisionGUID="3f7d942f-84c7-46f1-8be5-95964d4bca4c" CreationDate="2016-06-25T06:18:30.003" UserId="4638" Text="Inspired by Minecraft and LEGOs, we created an app to promote creativity on smartphones. Many people like being creative but find a blank canvas daunting. &quot;Recipes&quot; inside the app let users create like the most talented individuals -- similar to how a cooking recipe lets anyone cook like Thomas Keller.&#xD;&#xA;&#xD;&#xA;The problem so far is users say the app doesn't look &quot;3D&quot; enough (not linking to our app or screenshots to avoid the appearance of spam). What they mean is they expect the app to look more like apps like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;We're using SceneKit on iOS, but are having trouble identifying what is needed to make the app look more like the images above. We played with lighting and textures, but are new to 3D graphics as well as SceneKit and are unsure what to do.&#xD;&#xA;&#xD;&#xA;We have tried to find consultants on StackOverflow, LinkedIn, Github, but this expertise appears not so common.&#xD;&#xA;&#xD;&#xA;A few questions:&#xD;&#xA;&#xD;&#xA;1) For iOS, is SceneKit capable of producing the images above, or do we need to use something like Metal?&#xD;&#xA;&#xD;&#xA;2) If SceneKit is capable, what are the key concepts to learn?&#xD;&#xA;&#xD;&#xA;3) (Happy to strike this question if it's considered off-topic) Which websites/forums could we find people to help provide advice if we get stuck?&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4Kh0S.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LMePj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/mGfva.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7536" PostHistoryTypeId="1" PostId="3671" RevisionGUID="3f7d942f-84c7-46f1-8be5-95964d4bca4c" CreationDate="2016-06-25T06:18:30.003" UserId="4638" Text="How to determine if SceneKit can produce sufficiently 3D graphics like Minecraft?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7537" PostHistoryTypeId="3" PostId="3671" RevisionGUID="3f7d942f-84c7-46f1-8be5-95964d4bca4c" CreationDate="2016-06-25T06:18:30.003" UserId="4638" Text="|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7539" PostHistoryTypeId="2" PostId="3672" RevisionGUID="673916ef-6d45-48bf-9acb-da2ac691b48b" CreationDate="2016-06-25T06:53:20.210" UserId="4639" Text="I'm struggling with this idea of creating two particles in 3d and draw a tube between them. I can't figure out how to properly set the angle of the tube. I've used two approaches:&#xD;&#xA;&#xD;&#xA;1. calculating the angle with the square root dot product divided by the length of the vectors.&#xD;&#xA;2. cartesian to polar function which calculates the y and z rotation values&#xD;&#xA;&#xD;&#xA;I'm obviously missing something (and I'm not that good in math). So what's my approach?&#xD;&#xA;&#xD;&#xA;Thanks in advance! See below what I have so far.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YOwcg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7540" PostHistoryTypeId="1" PostId="3672" RevisionGUID="673916ef-6d45-48bf-9acb-da2ac691b48b" CreationDate="2016-06-25T06:53:20.210" UserId="4639" Text="How can I draw a tube on basis of position and angle between two 3d points?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7541" PostHistoryTypeId="3" PostId="3672" RevisionGUID="673916ef-6d45-48bf-9acb-da2ac691b48b" CreationDate="2016-06-25T06:53:20.210" UserId="4639" Text="|3d|vectors|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7542" PostHistoryTypeId="2" PostId="3673" RevisionGUID="01370d45-a77f-4a69-acf6-ae841c1695f3" CreationDate="2016-06-25T18:34:59.263" UserId="4495" Text="1) Drawing a bunch of 3d cubes with simple textures? Yes, SceneKit can do that.  &#xD;&#xA;&#xD;&#xA;2) Way to broad a question... try [reading the docs.](https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/)&#xD;&#xA;&#xD;&#xA;3) Since this is a platform specific question try the scenekit tag on stackOverflow, but see answer 2 first.&#xD;&#xA;&#xD;&#xA;good luck!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7543" PostHistoryTypeId="5" PostId="3673" RevisionGUID="97d72ee3-d38d-428e-b833-966f90184d0e" CreationDate="2016-06-25T18:40:17.857" UserId="4495" Comment="a little more info and a typo" Text="1) Drawing a bunch of 3d cubes with simple textures? Yes, SceneKit can do that.  &#xD;&#xA;&#xD;&#xA;2) Way too broad a question... try [reading the docs.](https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/)&#xD;&#xA;&#xD;&#xA;3) Since this is a platform specific question try the **scenekit** and **scene-kit** tags on [stackOverflow](http://stackoverflow.com/) and [Game Development](http://gamedev.stackexchange.com/), but see answer 2 first.&#xD;&#xA;&#xD;&#xA;good luck!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7544" PostHistoryTypeId="5" PostId="3671" RevisionGUID="9abc23b1-2560-47df-b5f6-1cea1b72d410" CreationDate="2016-06-25T22:37:28.127" UserId="4638" Comment="added 262 characters in body" Text="Inspired by Minecraft and LEGOs, we created an app to promote creativity on smartphones. Many people like being creative but find a blank canvas daunting. &quot;Recipes&quot; inside the app let users create like the most talented individuals -- similar to how a cooking recipe lets anyone cook like Thomas Keller.&#xD;&#xA;&#xD;&#xA;The problem so far is users say the app doesn't look &quot;3D&quot; enough. What they mean is they expect the app to look more like apps like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;With encouragement from one of the admins, these screenshots from our app illustrate the disparity in &quot;3Dness&quot;:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;We're using SceneKit on iOS, but are having trouble identifying what is needed to make the app look more like the images above. We played with lighting and textures, but are new to 3D graphics as well as SceneKit and are unsure what to do.&#xD;&#xA;&#xD;&#xA;We have tried to find consultants on StackOverflow, LinkedIn, Github, but this expertise appears not so common.&#xD;&#xA;&#xD;&#xA;A few questions:&#xD;&#xA;&#xD;&#xA;1) For iOS, is SceneKit capable of producing the images above, or do we need to use something like Metal?&#xD;&#xA;&#xD;&#xA;2) If SceneKit is capable, what are the key concepts to learn?&#xD;&#xA;&#xD;&#xA;3) (Happy to strike this question if it's considered off-topic) Which websites/forums could we find people to help provide advice if we get stuck?&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4Kh0S.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LMePj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/mGfva.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/ntHkQ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/dodAZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7545" PostHistoryTypeId="2" PostId="3674" RevisionGUID="2fa486cb-1901-46cc-a224-df360c0f8b8e" CreationDate="2016-06-25T23:33:50.490" UserId="137" Text="The simplest solution is to use a lookat matrix. This is a matrix calculated from a &quot;eye&quot; point, a &quot;target&quot; point and an up vector.&#xD;&#xA;&#xD;&#xA;The resulting matrix will then make the Z axis point from the eye to the target and the y axis in the general direction of up." ContentLicense="CC BY-SA 3.0" />
  <row Id="7546" PostHistoryTypeId="2" PostId="3675" RevisionGUID="c9e61fa3-9473-4e64-8205-e9cb5cbe01d6" CreationDate="2016-06-25T23:36:23.003" UserId="231" Text="# What is missing?&#xD;&#xA;&#xD;&#xA;Now that we can see images from your app, the difference that stands out most to me is the lack of shadows and [ambient occlusion]. This gives a very flat look as the colour of a surface does not vary according to its surroundings. This makes a big difference to how much an image appears to have depth.&#xD;&#xA;&#xD;&#xA;Another effect which may be less important is that the surfaces are crystal clear all the way up to the horizon. Adding a mist/fog effect so that objects become gradually more obscured the further they are from the camera helps to give the impression of distance.&#xD;&#xA;&#xD;&#xA;Both these effects can be seen most obviously in the first example image in the question. The nearest building shows ambient occlusion on top of the stepped red roof, and also the grass is in partial shade near to the buildings and animals. The trees in the distance look more obviously far away due to the distance fog making them only partially visible.&#xD;&#xA;&#xD;&#xA;# Can scenekit provide these?&#xD;&#xA;&#xD;&#xA;I haven't used scenekit myself, but a search online reveals that both ambient occlusion and distance fog effects are both possible using scenekit.&#xD;&#xA;&#xD;&#xA;Another effect not used in the example images, but that you might like to look into, is depth of field. The example images all have everything in focus at the same time, whereas photographs often have a focal distance at which everything is in clear focus, with anything nearer or farther being out of focus. It seems scenekit can also handle this. Since your competitors don't appear to be using this, you could either view this as unimportant, or as a feature that could give you an advantage.&#xD;&#xA;&#xD;&#xA;I'd expect narrow depth of field to make a building app awkward, as parts of the object you are building would be out of focus. You may be interested in a wide depth of field that only creates a subtle blur for objects too distant to be part of what is currently being built, if that suits your purposes.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;As you guessed, asking for off site resources is off topic. However, you can ask further questions about computer graphics programming here on this site, if you run into any problems implementing these effects.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [ambient occlusion]: https://en.wikipedia.org/wiki/Ambient_occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="7547" PostHistoryTypeId="5" PostId="3675" RevisionGUID="5c643a7d-7822-4519-a15c-517aac4d6793" CreationDate="2016-06-25T23:41:30.230" UserId="231" Comment="edited body" Text="# What is missing?&#xD;&#xA;&#xD;&#xA;Now that we can see images from your app, the difference that stands out most to me is the lack of shadows and [ambient occlusion]. This gives a very flat look as the colour of a surface does not vary according to its surroundings. This makes a big difference to how much an image appears to have depth.&#xD;&#xA;&#xD;&#xA;Another effect which may be less important is that the surfaces are crystal clear all the way up to the horizon. Adding a mist/fog effect so that objects become gradually more obscured the further they are from the camera helps to give the impression of distance.&#xD;&#xA;&#xD;&#xA;Both these effects can be seen most obviously in the first example image in the question. The nearest building shows ambient occlusion on top of the stepped red roof, and also the grass is in partial shade near to the buildings and animals. The trees in the distance look more obviously far away due to the distance fog making them only partially visible.&#xD;&#xA;&#xD;&#xA;# Can SceneKit provide these?&#xD;&#xA;&#xD;&#xA;I haven't used SceneKit myself, but a search online reveals that both ambient occlusion and distance fog effects are both possible using SceneKit.&#xD;&#xA;&#xD;&#xA;Another effect not used in the example images, but that you might like to look into, is depth of field. The example images all have everything in focus at the same time, whereas photographs often have a focal distance at which everything is in clear focus, with anything nearer or farther being out of focus. It seems SceneKit can also handle this. Since your competitors don't appear to be using this, you could either view this as unimportant, or as a feature that could give you an advantage.&#xD;&#xA;&#xD;&#xA;I'd expect narrow depth of field to make a building app awkward, as parts of the object you are building would be out of focus. You may be interested in a wide depth of field that only creates a subtle blur for objects too distant to be part of what is currently being built, if that suits your purposes.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;As you guessed, asking for off site resources is off topic. However, you can ask further questions about computer graphics programming here on this site, if you run into any problems implementing these effects.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [ambient occlusion]: https://en.wikipedia.org/wiki/Ambient_occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="7552" PostHistoryTypeId="2" PostId="3677" RevisionGUID="76088fa9-c17b-437b-a40c-59dce50f18cb" CreationDate="2016-06-26T08:13:51.857" UserId="4608" Text="My previous question got closed, because of a delay in response from my &#xD;&#xA;side so I'm posting here with a lot more details.&#xD;&#xA;&#xD;&#xA;I want to do keyframe interpolation in matlab.&#xD;&#xA;&#xD;&#xA;If I understand correctly, it uses splines to approximate the the motion of specific pixel points within the frames(through transforms). Correct me if I'm wrong.&#xD;&#xA;&#xD;&#xA;I tried looking but there are no toolboxes or any code for it. Where can I start?&#xD;&#xA;&#xD;&#xA;I will be working with video frames. At specific points (say after N frames, N~~100) the first frame encountered is labeled the keyframe.&#xD;&#xA;&#xD;&#xA;These frames are the equivalent to what animator artists draw and then animate by getting the computer to approximate frames in between.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm interpolating image frames. Literal image frame pixel values.&#xD;&#xA;&#xD;&#xA;Imagine this, there are some pixel values I select, then I call those pixel values features and decide to track those pixel values against the frames. Those pixel values must have some sort of trajectory. I want to interpolate pixel values at various points of a trajectory such that the trajectory approximates a smooth motion between the pixel values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can anyone help me?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7553" PostHistoryTypeId="1" PostId="3677" RevisionGUID="76088fa9-c17b-437b-a40c-59dce50f18cb" CreationDate="2016-06-26T08:13:51.857" UserId="4608" Text="How to do keyframe interpolation on matlab? Please mention any toolboxes" ContentLicense="CC BY-SA 3.0" />
  <row Id="7554" PostHistoryTypeId="3" PostId="3677" RevisionGUID="76088fa9-c17b-437b-a40c-59dce50f18cb" CreationDate="2016-06-26T08:13:51.857" UserId="4608" Text="|transformations|interpolation|animation|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7558" PostHistoryTypeId="2" PostId="3678" RevisionGUID="a8e116c2-e508-43ba-b394-327b9d4095f3" CreationDate="2016-06-26T11:12:24.697" UserId="4646" Text="I'm trying to figure this out for my Computer Graphics course, but I find it very hard to understand. &#xD;&#xA;&#xD;&#xA;I believe the minimum number of angles obtained from clipping a convex polygon with n angles is 0, for example if the polygon is outside of the clipping rectangle, but I'm not sure if this makes sense.&#xD;&#xA;&#xD;&#xA;As for the maximum number of angles, I believe it is 2n, as in if every angle tip gets outside of the rectangle. However, I'm not sure about this either.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7559" PostHistoryTypeId="1" PostId="3678" RevisionGUID="a8e116c2-e508-43ba-b394-327b9d4095f3" CreationDate="2016-06-26T11:12:24.697" UserId="4646" Text="Maximal and minimal no. of angles obtained from clipping a convex polygon with n angles" ContentLicense="CC BY-SA 3.0" />
  <row Id="7560" PostHistoryTypeId="3" PostId="3678" RevisionGUID="a8e116c2-e508-43ba-b394-327b9d4095f3" CreationDate="2016-06-26T11:12:24.697" UserId="4646" Text="|polygon|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7561" PostHistoryTypeId="2" PostId="3679" RevisionGUID="e41d144b-1a5f-4b62-abc4-8e34a083a5c5" CreationDate="2016-06-26T14:42:49.290" UserId="231" Text="*Since this is a homework question, I'll give hints rather than a numerical answer.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# Clipping a convex polygon&#xD;&#xA;&#xD;&#xA;Think about how many times the polygon can cross each edge of the rectangle. In general, a polygon can cross one of the edges of the rectangle an arbitrarily large number of times. How is this number reduced if the polygon is convex?&#xD;&#xA;&#xD;&#xA;This will give you the maximal number of new angles that can be added per rectangle edge, which should lead you to the answer.&#xD;&#xA;&#xD;&#xA;# Clipping a non-convex polygon&#xD;&#xA;&#xD;&#xA;As for your guess of 2n, even for a non-convex polygon it may not be able to reach this high. If one vertex is outside the rectangle, then in order to create 2 new vertices both of its neighbouring vertices must be inside the rectangle. This means you cannot create 2n new vertices this way.&#xD;&#xA;&#xD;&#xA;The exception is when an edge of the polygon crosses 2 edges of the rectangle, for example at a corner of the rectangle. This allows creating two new vertices from a single edge. So for small enough n, it is possible to clip to a polygon with 2n vertices, but for larger n this is not possible.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7562" PostHistoryTypeId="2" PostId="3680" RevisionGUID="6951abae-2fdf-465e-85fc-9691dec19f75" CreationDate="2016-06-26T15:07:15.097" UserId="4647" Text="_This is a copy-paste of [my answer](http://stackoverflow.com/a/38039733/673852) to the same [question at StackOverflow](http://stackoverflow.com/q/2508818/673852)_.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;At the bottom of this answer is an example of GLSL code which allows to output the full `float` value as color, encoding IEEE 754 `binary32`. I use it like follows (this snippet gives out `yy` component of modelview matrix):&#xD;&#xA;&#xD;&#xA;    vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);&#xD;&#xA;    if(bool(1)) // put 0 here to get lowest byte instead of three highest&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.rgb,1);&#xD;&#xA;    else&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.a,0,0,1);&#xD;&#xA;&#xD;&#xA;After you get this on screen, you can just take any color picker, format the color as HTML (appending `00` to the `rgb` value if you don't need higher precision, and doing a second pass to get the lower byte if you do), and you get the hexadecimal representation of the `float` as IEEE 754 `binary32`.&#xD;&#xA;&#xD;&#xA;Here's the actual implementation of `toColor()`:&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;    &#xD;&#xA;    const int emax=127;&#xD;&#xA;    // Input: x&gt;=0&#xD;&#xA;    // Output: base 2 exponent of x if (x!=0 &amp;&amp; !isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    //         -emax if x==0&#xD;&#xA;    //         emax+1 otherwise&#xD;&#xA;    int floorLog2(float x)&#xD;&#xA;    {&#xD;&#xA;        if(x==0) return -emax;&#xD;&#xA;        // NOTE: there exist values of x, for which floor(log2(x)) will give wrong&#xD;&#xA;        // (off by one) result as compared to the one calculated with infinite precision.&#xD;&#xA;        // Thus we do it in a brute-force way.&#xD;&#xA;        for(int e=emax;e&gt;=1-emax;--e)&#xD;&#xA;            if(x&gt;=exp2(float(e))) return e;&#xD;&#xA;        // If we are here, x must be infinity or NaN&#xD;&#xA;        return emax+1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x&#xD;&#xA;    // Output: IEEE 754 biased exponent with bias=emax&#xD;&#xA;    int biasedExp(float x) { return emax+floorLog2(abs(x)); }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that (!isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    // Output: significand AKA mantissa of x if !isnan(x) &amp;&amp; !isinf(x)&#xD;&#xA;    //         undefined otherwise&#xD;&#xA;    float significand(float x)&#xD;&#xA;    {&#xD;&#xA;        // converting int to float so that exp2(genType) gets correctly-typed value&#xD;&#xA;        float expo=floorLog2(abs(x));&#xD;&#xA;        return abs(x)/exp2(expo);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: x\in[0,1)&#xD;&#xA;    //        N&gt;=0&#xD;&#xA;    // Output: Nth byte as counted from the highest byte in the fraction&#xD;&#xA;    int part(float x,int N)&#xD;&#xA;    {&#xD;&#xA;        // All comments about exactness here assume that underflow and overflow don't occur&#xD;&#xA;        const int byteShift=256;&#xD;&#xA;        // Multiplication is exact since it's just an increase of exponent by 8&#xD;&#xA;        for(int n=0;n&lt;N;++n)&#xD;&#xA;            x*=byteShift;&#xD;&#xA;    &#xD;&#xA;        // Cut higher bits away.&#xD;&#xA;        // $q \in [0,1) \cap \mathbb Q'.$&#xD;&#xA;        float q=fract(x);&#xD;&#xA;    &#xD;&#xA;        // Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected&#xD;&#xA;        // results of rounding by the GPU later in the pipeline when transforming to TrueColor&#xD;&#xA;        // the resulting subpixel value.&#xD;&#xA;        // $c \in [0,255] \cap \mathbb Z.$&#xD;&#xA;        // Multiplication is exact since it's just and increase of exponent by 8&#xD;&#xA;        float c=floor(byteShift*q);&#xD;&#xA;        return int(c);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x acceptable to significand()&#xD;&#xA;    // Output: significand of x split to (8,8,8)-bit data vector&#xD;&#xA;    ivec3 significandAsIVec3(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec3 result;&#xD;&#xA;        float sig=significand(x)/2; // shift all bits to fractional part&#xD;&#xA;        result.x=part(sig,0);&#xD;&#xA;        result.y=part(sig,1);&#xD;&#xA;        result.z=part(sig,2);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that !isnan(x)&#xD;&#xA;    // Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)&#xD;&#xA;    ivec4 packIEEE754binary32(float x)&#xD;&#xA;    {&#xD;&#xA;        int e = biasedExp(x);&#xD;&#xA;        // sign to bit 7&#xD;&#xA;        int s = x&lt;0 ? 128 : 0;&#xD;&#xA;    &#xD;&#xA;        ivec4 binary32;&#xD;&#xA;        binary32.yzw=significandAsIVec3(x);&#xD;&#xA;        // clear the implicit integer bit of significand&#xD;&#xA;        if(binary32.y&gt;=128) binary32.y-=128;&#xD;&#xA;        // put lowest bit of exponent into its position, replacing just cleared integer bit&#xD;&#xA;        binary32.y+=128*int(mod(e,2));&#xD;&#xA;        // prepare high bits of exponent for fitting into their positions&#xD;&#xA;        e/=2;&#xD;&#xA;        // pack highest byte&#xD;&#xA;        binary32.x=e+s;&#xD;&#xA;    &#xD;&#xA;        return binary32;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec4 toColor(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec4 binary32=packIEEE754binary32(x);&#xD;&#xA;        // Transform color components to [0,1] range.&#xD;&#xA;        // Division is inexact, but works reliably for all integers from 0 to 255 if&#xD;&#xA;        // the transformation to TrueColor by GPU uses rounding to nearest or upwards.&#xD;&#xA;        // The result will be multiplied by 255 back when transformed&#xD;&#xA;        // to TrueColor subpixel value by OpenGL.&#xD;&#xA;        return binary32/255.;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="7563" PostHistoryTypeId="5" PostId="2521" RevisionGUID="5ed492c5-5328-4228-bdc7-f151648e6660" CreationDate="2016-06-26T17:04:50.810" UserId="3304" Comment="Copy edited (e.g. ref. &lt;http://english.stackexchange.com/questions/4645/is-it-ever-correct-to-have-a-space-before-a-question-or-exclamation-mark#comment206109_4645&gt;). In English, the subjective form of the singular first-person pronoun, &quot;I&quot;, is capitalized." Text="I know how to draw lines with DDA, but I want to learn a more efficient way and Google suggests Bresenham's line drawing algorithm is better than DDA.&#xD;&#xA;&#xD;&#xA;Here is my implementation:&#xD;&#xA;&#xD;&#xA;    int x0 = Math.round(m_start.getPosition().getX());&#xD;&#xA;    int y0 = Math.round(m_start.getPosition().getY());&#xD;&#xA;    int x1 = Math.round(m_end.getPosition().getX());&#xD;&#xA;    int y1 = Math.round(m_end.getPosition().getY());&#xD;&#xA;&#xD;&#xA;    int dx = x1 - x0;&#xD;&#xA;    int dy = y1 - y0;&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;    Point k = new Point(new Vector2D(x0, y0), m_display, PixelData.white());&#xD;&#xA;    k.DrawPoint();&#xD;&#xA;&#xD;&#xA;    for(int i = x0 + 1; i &lt; x1; i++){&#xD;&#xA;       if(parameter &lt; 0){&#xD;&#xA;           y0 += 1;&#xD;&#xA;           Point p = new Point(new Vector2D(i, y0), m_display, PixelData.white());&#xD;&#xA;           p.DrawPoint();&#xD;&#xA;&#xD;&#xA;           parameter += 2 * dy;&#xD;&#xA;       }&#xD;&#xA;       else{&#xD;&#xA;           y0 += 1;&#xD;&#xA;           Point p = new Point(new Vector2D(i, y0 + 1), m_display, PixelData.white());&#xD;&#xA;           p.DrawPoint();&#xD;&#xA;&#xD;&#xA;           parameter += 2 * dy - 2 * dx;&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here is the output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can seel, the line is not ending at the desired coordinate. That small dot is where it should end.&#xD;&#xA;&#xD;&#xA;I checked the slope, dx and dy.&#xD;&#xA;&#xD;&#xA;    System.out.println(dx + &quot; &quot; + dy + &quot; &quot; + (dy/(float)dx));&#xD;&#xA;&#xD;&#xA;Output:&#xD;&#xA;&#xD;&#xA;    100 50 0.5&#xD;&#xA;&#xD;&#xA;The slope is below tan (pi/4).&#xD;&#xA;&#xD;&#xA;How do I find the bug?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BT5tA.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7564" PostHistoryTypeId="24" PostId="2521" RevisionGUID="5ed492c5-5328-4228-bdc7-f151648e6660" CreationDate="2016-06-26T17:04:50.810" Comment="Proposed by 3304 approved by 273, -1 edit id of 149" ContentLicense="CC BY-SA 3.0" />
  <row Id="7565" PostHistoryTypeId="5" PostId="2521" RevisionGUID="c321b944-2d82-49ac-bbce-b82b0fefce90" CreationDate="2016-06-26T17:04:50.810" UserId="231" Comment="Copy edited (e.g. ref. &lt;http://english.stackexchange.com/questions/4645/is-it-ever-correct-to-have-a-space-before-a-question-or-exclamation-mark#comment206109_4645&gt;). In English, the subjective form of the singular first-person pronoun, &quot;I&quot;, is capitalized." Text="I know how to draw lines with DDA, but I want to learn a more efficient way and Google suggests Bresenham's line drawing algorithm is better than DDA.&#xD;&#xA;&#xD;&#xA;Here is my implementation:&#xD;&#xA;&#xD;&#xA;    int x0 = Math.round(m_start.getPosition().getX());&#xD;&#xA;    int y0 = Math.round(m_start.getPosition().getY());&#xD;&#xA;    int x1 = Math.round(m_end.getPosition().getX());&#xD;&#xA;    int y1 = Math.round(m_end.getPosition().getY());&#xD;&#xA;&#xD;&#xA;    int dx = x1 - x0;&#xD;&#xA;    int dy = y1 - y0;&#xD;&#xA;&#xD;&#xA;    int parameter = 2 * dy -  dx;&#xD;&#xA;&#xD;&#xA;    Point k = new Point(new Vector2D(x0, y0), m_display, PixelData.white());&#xD;&#xA;    k.DrawPoint();&#xD;&#xA;&#xD;&#xA;    for(int i = x0 + 1; i &lt; x1; i++){&#xD;&#xA;       if(parameter &lt; 0){&#xD;&#xA;           y0 += 1;&#xD;&#xA;           Point p = new Point(new Vector2D(i, y0), m_display, PixelData.white());&#xD;&#xA;           p.DrawPoint();&#xD;&#xA;&#xD;&#xA;           parameter += 2 * dy;&#xD;&#xA;       }&#xD;&#xA;       else{&#xD;&#xA;           y0 += 1;&#xD;&#xA;           Point p = new Point(new Vector2D(i, y0 + 1), m_display, PixelData.white());&#xD;&#xA;           p.DrawPoint();&#xD;&#xA;&#xD;&#xA;           parameter += 2 * dy - 2 * dx;&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here is the output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the line is not ending at the desired coordinate. That small dot is where it should end.&#xD;&#xA;&#xD;&#xA;I checked the slope, dx and dy.&#xD;&#xA;&#xD;&#xA;    System.out.println(dx + &quot; &quot; + dy + &quot; &quot; + (dy/(float)dx));&#xD;&#xA;&#xD;&#xA;Output:&#xD;&#xA;&#xD;&#xA;    100 50 0.5&#xD;&#xA;&#xD;&#xA;The slope is below tan (pi/4).&#xD;&#xA;&#xD;&#xA;How do I find the bug?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BT5tA.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7566" PostHistoryTypeId="2" PostId="3681" RevisionGUID="443bbd4d-7e3f-4703-b947-9a61d007b6e8" CreationDate="2016-06-26T18:53:56.907" UserId="2308" Text="My goal is to take a point that is inside of a circle with a given radius and put it on the circumference.&#xA;&#xA;Recently I have been normalizing the vector between the point and the center of the circle then multiplying that by the radius.  However I need (if possible) a less computationally expensive method because the distance formula is expensive.&#xA;&#xA;Another thought I had was to use &quot;atan2&quot; to get the angle between the two points and then use sine and cosine multiplied by the radius to get the point on the circumference.&#xA;&#xA;Which method do you think would be faster for the computer to process? Can you think of a faster method." ContentLicense="CC BY-SA 3.0" />
  <row Id="7567" PostHistoryTypeId="1" PostId="3681" RevisionGUID="443bbd4d-7e3f-4703-b947-9a61d007b6e8" CreationDate="2016-06-26T18:53:56.907" UserId="2308" Text="Fastest way to put a point on the circumference of a circle" ContentLicense="CC BY-SA 3.0" />
  <row Id="7568" PostHistoryTypeId="3" PostId="3681" RevisionGUID="443bbd4d-7e3f-4703-b947-9a61d007b6e8" CreationDate="2016-06-26T18:53:56.907" UserId="2308" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7570" PostHistoryTypeId="5" PostId="3681" RevisionGUID="5e058282-db91-4fda-9c18-174ede130918" CreationDate="2016-06-26T20:19:01.097" UserId="2308" Comment="added 428 characters in body" Text="My goal is to take a point that is inside of a circle with a given radius and put it on the circumference.&#xA;&#xA;Recently I have been normalizing the vector between the point and the center of the circle then multiplying that by the radius.  However I need (if possible) a less computationally expensive method because the distance formula is expensive.&#xA;&#xA;Another thought I had was to use &quot;atan2&quot; to get the angle between the two points and then use sine and cosine multiplied by the radius to get the point on the circumference.&#xA;&#xA;Which method do you think would be faster for the computer to process? Can you think of a faster method.&#xA;&#xA;&#xA;**Details about the simulation yhid is in**&#xA;This is an ios application written in swift.&#xA;&#xA;Basically there are a bunch of particles moving around randomly. And the user is putting down fingers. Each finger is a circle with a radius that grows as time goes on. The part that is inneficent is that if the dot is ever inside of any of the circles (attached to touchscreen touches) that it goes on the circumference of the circle." ContentLicense="CC BY-SA 3.0" />
  <row Id="7571" PostHistoryTypeId="5" PostId="3681" RevisionGUID="100e24cd-3d77-46f6-837d-94f52aa07294" CreationDate="2016-06-26T21:09:47.170" UserId="2308" Comment="added 1 character in body" Text="My goal is to take a point that is inside of a circle with a given radius and put it on the circumference.&#xD;&#xA;&#xD;&#xA;Recently I have been normalizing the vector between the point and the center of the circle then multiplying that by the radius.  However I need (if possible) a less computationally expensive method because the distance formula is expensive.&#xD;&#xA;&#xD;&#xA;Another thought I had was to use &quot;atan2&quot; to get the angle between the two points and then use sine and cosine multiplied by the radius to get the point on the circumference.&#xD;&#xA;&#xD;&#xA;Which method do you think would be faster for the computer to process? Can you think of a faster method.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Details about the simulation**&#xD;&#xA;This is an ios application written in swift.&#xD;&#xA;&#xD;&#xA;Basically there are a bunch of particles moving around randomly. And the user is putting down fingers. Each finger is a circle with a radius that grows as time goes on. The part that is inneficent is that if the dot is ever inside of any of the circles (attached to touchscreen touches) that it goes on the circumference of the circle." ContentLicense="CC BY-SA 3.0" />
  <row Id="7572" PostHistoryTypeId="2" PostId="3682" RevisionGUID="24db60e8-a7af-463d-b3b0-e14bced0dabe" CreationDate="2016-06-26T22:53:24.400" UserId="231" Text="Before focusing on optimising the individual process of moving a point, consider how many points are being processed this way. This is likely to give a much more significant speed up if it hasn't yet been addressed.&#xD;&#xA;&#xD;&#xA;For example, if every point on the screen is being tested against every circle, then most of the points are being checked needlessly.&#xD;&#xA;&#xD;&#xA;If instead you divide the screen into a grid, with each grid cell keeping a list of all points currently within it, then each circle only needs to be checked against the points that appear in the grid cells which that circle overlaps. This allows checking a few tens of points, instead of hundreds or thousands.&#xD;&#xA;&#xD;&#xA;This is a much bigger speed up than you can hope to achieve by optimising the circumference calculation, and after this you may find that further optimisation is not needed.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7573" PostHistoryTypeId="2" PostId="3683" RevisionGUID="b3478538-7f40-46a3-9fc5-38dea18a49d6" CreationDate="2016-06-27T00:22:45.793" UserId="2308" Text="I am trying to programmatically figure out how many &quot;texture2d &quot; calls the gpu can make before the fps drops below 60fps.&#xA;&#xA;My current way of doing this is to have a fragment shader with a for loop that will run a specified number of times based on a passed in uniform. So each frame the for loop will run more times, each time sampling the texture more times.&#xA;&#xA;Then on the cpu I can monitor the fps and see when it drops.&#xA;&#xA;My problem is if this shader runs on more then one pixel then the test is worth nothing.&#xA;&#xA;How can I ensure from the cpu code and vertex shader that the fragment program only runs once?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7574" PostHistoryTypeId="1" PostId="3683" RevisionGUID="b3478538-7f40-46a3-9fc5-38dea18a49d6" CreationDate="2016-06-27T00:22:45.793" UserId="2308" Text="How to ensure a fragment shader only runs once" ContentLicense="CC BY-SA 3.0" />
  <row Id="7575" PostHistoryTypeId="3" PostId="3683" RevisionGUID="b3478538-7f40-46a3-9fc5-38dea18a49d6" CreationDate="2016-06-27T00:22:45.793" UserId="2308" Text="|gpu|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7578" PostHistoryTypeId="5" PostId="3680" RevisionGUID="62db190d-93e1-45e6-96ee-0a602ca3f600" CreationDate="2016-06-27T06:09:23.410" UserId="4647" Comment="Add syntax highlighting" Text="_This is a copy-paste of [my answer](http://stackoverflow.com/a/38039733/673852) to the same [question at StackOverflow](http://stackoverflow.com/q/2508818/673852)_.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;At the bottom of this answer is an example of GLSL code which allows to output the full `float` value as color, encoding IEEE 754 `binary32`. I use it like follows (this snippet gives out `yy` component of modelview matrix):&#xD;&#xA;&#xD;&#xA;&lt;!-- NOTE: setting highlighting language to C since it has similar syntax while GLSL highlighting isn't supported on stackexchange --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);&#xD;&#xA;    if(bool(1)) // put 0 here to get lowest byte instead of three highest&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.rgb,1);&#xD;&#xA;    else&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.a,0,0,1);&#xD;&#xA;&#xD;&#xA;After you get this on screen, you can just take any color picker, format the color as HTML (appending `00` to the `rgb` value if you don't need higher precision, and doing a second pass to get the lower byte if you do), and you get the hexadecimal representation of the `float` as IEEE 754 `binary32`.&#xD;&#xA;&#xD;&#xA;Here's the actual implementation of `toColor()`:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;    &#xD;&#xA;    const int emax=127;&#xD;&#xA;    // Input: x&gt;=0&#xD;&#xA;    // Output: base 2 exponent of x if (x!=0 &amp;&amp; !isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    //         -emax if x==0&#xD;&#xA;    //         emax+1 otherwise&#xD;&#xA;    int floorLog2(float x)&#xD;&#xA;    {&#xD;&#xA;        if(x==0) return -emax;&#xD;&#xA;        // NOTE: there exist values of x, for which floor(log2(x)) will give wrong&#xD;&#xA;        // (off by one) result as compared to the one calculated with infinite precision.&#xD;&#xA;        // Thus we do it in a brute-force way.&#xD;&#xA;        for(int e=emax;e&gt;=1-emax;--e)&#xD;&#xA;            if(x&gt;=exp2(float(e))) return e;&#xD;&#xA;        // If we are here, x must be infinity or NaN&#xD;&#xA;        return emax+1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x&#xD;&#xA;    // Output: IEEE 754 biased exponent with bias=emax&#xD;&#xA;    int biasedExp(float x) { return emax+floorLog2(abs(x)); }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that (!isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    // Output: significand AKA mantissa of x if !isnan(x) &amp;&amp; !isinf(x)&#xD;&#xA;    //         undefined otherwise&#xD;&#xA;    float significand(float x)&#xD;&#xA;    {&#xD;&#xA;        // converting int to float so that exp2(genType) gets correctly-typed value&#xD;&#xA;        float expo=floorLog2(abs(x));&#xD;&#xA;        return abs(x)/exp2(expo);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: x\in[0,1)&#xD;&#xA;    //        N&gt;=0&#xD;&#xA;    // Output: Nth byte as counted from the highest byte in the fraction&#xD;&#xA;    int part(float x,int N)&#xD;&#xA;    {&#xD;&#xA;        // All comments about exactness here assume that underflow and overflow don't occur&#xD;&#xA;        const int byteShift=256;&#xD;&#xA;        // Multiplication is exact since it's just an increase of exponent by 8&#xD;&#xA;        for(int n=0;n&lt;N;++n)&#xD;&#xA;            x*=byteShift;&#xD;&#xA;    &#xD;&#xA;        // Cut higher bits away.&#xD;&#xA;        // $q \in [0,1) \cap \mathbb Q'.$&#xD;&#xA;        float q=fract(x);&#xD;&#xA;    &#xD;&#xA;        // Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected&#xD;&#xA;        // results of rounding by the GPU later in the pipeline when transforming to TrueColor&#xD;&#xA;        // the resulting subpixel value.&#xD;&#xA;        // $c \in [0,255] \cap \mathbb Z.$&#xD;&#xA;        // Multiplication is exact since it's just and increase of exponent by 8&#xD;&#xA;        float c=floor(byteShift*q);&#xD;&#xA;        return int(c);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x acceptable to significand()&#xD;&#xA;    // Output: significand of x split to (8,8,8)-bit data vector&#xD;&#xA;    ivec3 significandAsIVec3(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec3 result;&#xD;&#xA;        float sig=significand(x)/2; // shift all bits to fractional part&#xD;&#xA;        result.x=part(sig,0);&#xD;&#xA;        result.y=part(sig,1);&#xD;&#xA;        result.z=part(sig,2);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that !isnan(x)&#xD;&#xA;    // Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)&#xD;&#xA;    ivec4 packIEEE754binary32(float x)&#xD;&#xA;    {&#xD;&#xA;        int e = biasedExp(x);&#xD;&#xA;        // sign to bit 7&#xD;&#xA;        int s = x&lt;0 ? 128 : 0;&#xD;&#xA;    &#xD;&#xA;        ivec4 binary32;&#xD;&#xA;        binary32.yzw=significandAsIVec3(x);&#xD;&#xA;        // clear the implicit integer bit of significand&#xD;&#xA;        if(binary32.y&gt;=128) binary32.y-=128;&#xD;&#xA;        // put lowest bit of exponent into its position, replacing just cleared integer bit&#xD;&#xA;        binary32.y+=128*int(mod(e,2));&#xD;&#xA;        // prepare high bits of exponent for fitting into their positions&#xD;&#xA;        e/=2;&#xD;&#xA;        // pack highest byte&#xD;&#xA;        binary32.x=e+s;&#xD;&#xA;    &#xD;&#xA;        return binary32;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec4 toColor(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec4 binary32=packIEEE754binary32(x);&#xD;&#xA;        // Transform color components to [0,1] range.&#xD;&#xA;        // Division is inexact, but works reliably for all integers from 0 to 255 if&#xD;&#xA;        // the transformation to TrueColor by GPU uses rounding to nearest or upwards.&#xD;&#xA;        // The result will be multiplied by 255 back when transformed&#xD;&#xA;        // to TrueColor subpixel value by OpenGL.&#xD;&#xA;        return binary32/255.;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="7579" PostHistoryTypeId="2" PostId="3684" RevisionGUID="f6bcb06f-32ca-44de-83e2-0412516d1ec3" CreationDate="2016-06-27T12:43:05.767" UserId="4650" Text="I'm implementing a simple Lamberitan BRDF in GLSL, using a point light source. My fragment shader simply returns `light_colour * 1.0/PI * cosine`, which should model a fully diffuse white material. &#xD;&#xA;&#xD;&#xA;However, it looks rather dark... If I have a point light with colour (1,1,1), and no attenuation with distance, the maximum brightness of the material (at normal incidence) will be 1/3 (dark grey). &#xD;&#xA;&#xD;&#xA;Is this just because I am using a physically incorrect point light with zero size? Is there any &quot;correct&quot; value for the light colour in this case, if I want the surface to be white at its brightest parts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7580" PostHistoryTypeId="1" PostId="3684" RevisionGUID="f6bcb06f-32ca-44de-83e2-0412516d1ec3" CreationDate="2016-06-27T12:43:05.767" UserId="4650" Text="How to correctly implement Lambertian BRDF with point light" ContentLicense="CC BY-SA 3.0" />
  <row Id="7581" PostHistoryTypeId="3" PostId="3684" RevisionGUID="f6bcb06f-32ca-44de-83e2-0412516d1ec3" CreationDate="2016-06-27T12:43:05.767" UserId="4650" Text="|brdf|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7582" PostHistoryTypeId="2" PostId="3685" RevisionGUID="0bae78b9-d1c4-4e65-97d8-bb94a6f9c9ea" CreationDate="2016-06-27T14:06:45.213" UserId="137" Text="I don't think your approach is viable for a variety of reasons.&#xD;&#xA;&#xD;&#xA;1. a GPU is heavily cache-dependent for performance. Pulling the same pixels over and over will just measure how fast a cache hit is. Sampling random pixels will only measure a cache miss. Neither are useful statistics. &#xD;&#xA;&#xD;&#xA;2. each texture2d call will pull in multiple pixels to leverage that, in a fragment shader, neighbouring fragments will want neighbouring pixels.&#xD;&#xA;&#xD;&#xA;3. The driver could optimize your shader to pull out the loop if it sees that each iteration does the exact same computation or if the computed result is not used.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7583" PostHistoryTypeId="2" PostId="3686" RevisionGUID="58a987f7-e794-4c49-8543-3441921c7592" CreationDate="2016-06-27T14:23:47.803" UserId="4653" Text="I´m new to Processing Language. Trying to do my first skecth I´m having trouble with the dimension of the display window width and height because even though I´ve tried putting a variety of values in the size() function, the size of the window doesn´t change at any time, it always has the same size (100 px x 100 px). The function fullScreen() have the same results. ¿How could I resolve this problem?&#xD;&#xA;&#xD;&#xA;It´s a simple visualization of a &quot;star field&quot;. First block, class Star, simply create a star and fill it with a color. Second block is where I´m trying to adjust the size of the display window but it doesn´t work.&#xD;&#xA;&#xD;&#xA;    class Star {&#xD;&#xA;      float x;&#xD;&#xA;      float y;&#xD;&#xA;      float z;&#xD;&#xA; &#xD;&#xA;      Star(){&#xD;&#xA;        // Places the star in random X and Y coordinates&#xD;&#xA;        x = random(0, width);&#xD;&#xA;        y = random(0, height);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      /* Colors the star */&#xD;&#xA;      void update(){&#xD;&#xA;        fill(255);&#xD;&#xA;        noStroke();&#xD;&#xA;        ellipse(x, y, 8, 8);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      void show(){}&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // Array that contains all the amount of stars created (100 in this case)&#xD;&#xA;    Star[] stars = new Star[100];&#xD;&#xA;&#xD;&#xA;    void Setup(){&#xD;&#xA;      size(800, 800); // TROUBLE HERE. DOESN´T WORK&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i] = new Star();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Draw(){&#xD;&#xA;      background(0); // Colors the background&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i].update();&#xD;&#xA;        stars[i].show();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Thank you in advance." ContentLicense="CC BY-SA 3.0" />
  <row Id="7584" PostHistoryTypeId="1" PostId="3686" RevisionGUID="58a987f7-e794-4c49-8543-3441921c7592" CreationDate="2016-06-27T14:23:47.803" UserId="4653" Text="Issue with size() function in Processing Language?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7585" PostHistoryTypeId="3" PostId="3686" RevisionGUID="58a987f7-e794-4c49-8543-3441921c7592" CreationDate="2016-06-27T14:23:47.803" UserId="4653" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7586" PostHistoryTypeId="5" PostId="3686" RevisionGUID="c92fd1b5-acbf-4fe7-b17f-42cccdb67a3a" CreationDate="2016-06-27T14:31:50.967" UserId="4653" Comment="edited body" Text="I´m new to Processing Language. Trying to do my first sketch I´m having trouble with the dimension of the display window width and height because even though I´ve tried putting a variety of values in the size() function, the size of the window doesn´t change at any time, it always has the same size (100 px x 100 px). The function fullScreen() have the same results. ¿How could I resolve this problem?&#xD;&#xA;&#xD;&#xA;It´s a simple visualization of a &quot;star field&quot;. First block, class Star, simply create a star and fill it with a color. Second block is where I´m trying to adjust the size of the display window but it doesn´t work.&#xD;&#xA;&#xD;&#xA;    class Star {&#xD;&#xA;      float x;&#xD;&#xA;      float y;&#xD;&#xA;      float z;&#xD;&#xA; &#xD;&#xA;      Star(){&#xD;&#xA;        // Places the star in random X and Y coordinates&#xD;&#xA;        x = random(0, width);&#xD;&#xA;        y = random(0, height);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      /* Colors the star */&#xD;&#xA;      void update(){&#xD;&#xA;        fill(255);&#xD;&#xA;        noStroke();&#xD;&#xA;        ellipse(x, y, 8, 8);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      void show(){}&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // Array that contains all the amount of stars created (100 in this case)&#xD;&#xA;    Star[] stars = new Star[100];&#xD;&#xA;&#xD;&#xA;    void Setup(){&#xD;&#xA;      size(800, 800); // TROUBLE HERE. DOESN´T WORK&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i] = new Star();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Draw(){&#xD;&#xA;      background(0); // Colors the background&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i].update();&#xD;&#xA;        stars[i].show();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Thank you in advance." ContentLicense="CC BY-SA 3.0" />
  <row Id="7587" PostHistoryTypeId="2" PostId="3687" RevisionGUID="f517a979-a290-42f1-b082-1946676d0922" CreationDate="2016-06-27T14:43:51.540" UserId="4652" Text="What you probably need is this 4 x 4 matrix:&#xD;&#xA;&#xD;&#xA;$$\mathtt{T} = \begin{bmatrix}1 &amp; 0 &amp; 0 &amp; 0\\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1 \\  \end{bmatrix}$$&#xD;&#xA;which is flipping the z-axis. The inverse of this particular matrix is the matrix itself:&#xD;&#xA;$\mathtt{T}^{-1} = \mathtt{T}$&#xD;&#xA;&#xD;&#xA;For 3D points $\mathbf{x}$ multiply it from the left:&#xD;&#xA;$$\mathbf{x}' = \mathtt{T}\,\, \mathbf{x}$$&#xD;&#xA;and for 3D transformations multiply it from the right:&#xD;&#xA;$$\mathtt{P}' = \mathtt{P} \,\,\mathtt{T}$$&#xD;&#xA;&#xD;&#xA;Thus, you have not changed anything in the projection because:&#xD;&#xA;$$\mathtt{P}'\,\,\mathbf{x}' = \mathtt{P} \,\,\mathtt{T} \, \,\mathtt{T}\,\,  \mathbf{x} =  \mathtt{P} \,\,(\mathtt{T}^{-1} \, \,\mathtt{T})\,\,  \mathbf{x} = \mathtt{P}\,\,\mathbf{x}$$&#xD;&#xA;&#xD;&#xA;Quaternions $q=(s,x,y,z)^\top$ could be convert into &#xD;&#xA;a 3D transformation matrix with:&#xD;&#xA;&#xD;&#xA;$$\mathtt{P} = \begin{bmatrix} 1-2y^2-2z^2 &amp; 2xy-2sz&amp; 2xz+2ys &amp; 0\\ &#xD;&#xA;              2xy+2sz &amp; 1-2x^2-2z^2&amp; 2yz-2sx &amp; 0\\ &#xD;&#xA;              2xz-2sy &amp; 2yz+2sx&amp; 1-2x^2-2y^2 &amp; 0\\  0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}$$&#xD;&#xA;and could then be treated like other 3D transformations.&#xD;&#xA;&#xD;&#xA;However, 3D engines typically apply transformation in a transformation hierarchy. If this is the case, make sure you are only modifying the 3D transformation &quot;closest&quot; to the 3D point in the hierarchy.&#xD;&#xA;&#xD;&#xA;Sources:&#xD;&#xA;http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/graphics_5_2_eng_web.html&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7588" PostHistoryTypeId="2" PostId="3688" RevisionGUID="b31628a1-6e37-4eae-b0f0-d4ccbe731303" CreationDate="2016-06-27T15:05:43.860" UserId="4654" Text="**Problem:**&#xD;&#xA;I'm trying to draw a scene with a lot (about 10000) of similar objects (in my case bushes, but could be anything). For each bush I have three meshes with a different number of triangles and I want to use one of these meshes depending on the distance to the camera.&#xD;&#xA;&#xD;&#xA;**First approach:**&#xD;&#xA;I can select the correct mesh on the CPU, update the model matrix after every bush and then draw the VBO with the correct mesh. The problem is that I need to update the model matrix 10000 times per frame ... you can guess what this means performance wise.&#xD;&#xA;&#xD;&#xA;**Second Approach:**&#xD;&#xA;Again select the correct mesh on the CPU, but this time use instanced rendering to draw all bushes with lowest lod in one draw call, then the bushes with middle lod and then the bushes with high lod. I have stored the bush positions already on the GPU. But my problem here is that I still need to send an array as uniform variable which contains the information which mesh has to be drawn at which position. With this approach i run into the limit of uniform variables.&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;What I would like to do is to calculate the distance from the bush to the camera on the GPU (no problem for example in the vertex shader). And then draw only the VBO with the correct level of detail depending on the outcome. Therefore my question is if there is any possibility to select which VBO to draw on the GPU (I don't see any possibility to do this, since in the Vertex and Fragment shader I am a already to far down the pipeline)? Or do you have another idea that I could try?&#xD;&#xA;&#xD;&#xA;Best, Albert" ContentLicense="CC BY-SA 3.0" />
  <row Id="7589" PostHistoryTypeId="1" PostId="3688" RevisionGUID="b31628a1-6e37-4eae-b0f0-d4ccbe731303" CreationDate="2016-06-27T15:05:43.860" UserId="4654" Text="OpenGL Instanced Rendering with Level of Detail" ContentLicense="CC BY-SA 3.0" />
  <row Id="7590" PostHistoryTypeId="3" PostId="3688" RevisionGUID="b31628a1-6e37-4eae-b0f0-d4ccbe731303" CreationDate="2016-06-27T15:05:43.860" UserId="4654" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7591" PostHistoryTypeId="2" PostId="3689" RevisionGUID="68f252ad-d1f2-44ec-ae35-02912c6cf4cd" CreationDate="2016-06-27T17:27:03.067" UserId="3386" Text="I think the assumption (perhaps stated perhaps not, I dont' have the text handy) is that the radiance is emitted in a cosine-lobe distribution. This means that there's falloff in proportion to the cosine of the angle between the emitter's normal, and the direction of emission.&#xD;&#xA;&#xD;&#xA;If you look in the global illumination compendium [https://people.cs.kuleuven.be/~philip.dutre/GI/TotalCompendium.pdf], under Hemispherical Geometry, equation set (30), you'll see that the integral over the hemisphere, modulated by a cosine lobe, is exactly pi. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7592" PostHistoryTypeId="6" PostId="3686" RevisionGUID="261be015-0203-4282-8fe9-35a1eaa81690" CreationDate="2016-06-27T18:28:50.007" UserId="231" Comment="edited tags" Text="|processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7593" PostHistoryTypeId="2" PostId="3690" RevisionGUID="25ee2aac-08f4-4cff-b3f9-8d240620f07d" CreationDate="2016-06-27T18:30:48.547" UserId="231" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="7594" PostHistoryTypeId="2" PostId="3691" RevisionGUID="2bcb8c4f-3f73-48c2-8051-85a5d049cb01" CreationDate="2016-06-27T18:30:48.547" UserId="231" Text="Processing is an open source programming language and integrated development environment (IDE) built with the purpose of teaching the fundamentals of computer programming in a visual context." ContentLicense="CC BY-SA 3.0" />
  <row Id="7595" PostHistoryTypeId="2" PostId="3692" RevisionGUID="d671ac24-7b6c-47e8-bf7b-25728f85569d" CreationDate="2016-06-27T19:13:31.157" UserId="4655" Text="Radiance (in terms of flux) has the following definition:&#xD;&#xA;&#xD;&#xA;$L_o = \frac{\mathrm{d}\Phi}{\mathrm{d}\omega^\perp\mathrm{d}A}&#xD;&#xA;= \frac{\mathrm{d}\Phi}{\cos{\theta} \mathrm{d}\omega \mathrm{d}A}$.&#xD;&#xA;&#xD;&#xA;Thus in order to get the total emitted power we need to integrate over the area of the light and we need to integrate over the projected solid angle of the hemisphere (in the direction of the surface normal). The radiance for the area lights in pbrt is constant. This gives us:&#xD;&#xA;&#xD;&#xA;$\Phi = \int_A \int_{H^2(\mathbf{n})} L_o\mathrm{d}\omega^\perp \mathrm{d}A =&#xD;&#xA;\int_A \int_{H^2(\mathbf{n})} L_o \cos\theta \mathrm{d}\omega \mathrm{d}A =&#xD;&#xA;\int_A L_o \int_0^{2\pi} \int_0^{\pi/2} \sin\theta \cos\theta \mathrm{d}\theta \mathrm{d}\phi \mathrm{d}A =&#xD;&#xA;\int_A L_o \pi \mathrm{d}A =&#xD;&#xA;A \cdot L_o \cdot \pi$" ContentLicense="CC BY-SA 3.0" />
  <row Id="7596" PostHistoryTypeId="2" PostId="3693" RevisionGUID="1b0d3247-674e-49ad-97e1-a6b129f8351b" CreationDate="2016-06-27T19:20:33.517" UserDisplayName="user3437" Text="the window is `100px, 100px` because it is the default size and you are not changing it, as your&#xD;&#xA;`size()` is never been called because `Setup()` is not a predefined function. &#xD;&#xA;`setup()` is the function, lower case `s` not upper case `S`. Same with `draw()`.&#xD;&#xA;&#xD;&#xA;Below is the working code.&#xD;&#xA;&#xD;&#xA;    class Star {&#xD;&#xA;      float x;&#xD;&#xA;      float y;&#xD;&#xA;      float z;&#xD;&#xA; &#xD;&#xA;      Star(){&#xD;&#xA;        // Places the star in random X and Y coordinates&#xD;&#xA;        x = random(0, width);&#xD;&#xA;        y = random(0, height);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      /* Colors the star */&#xD;&#xA;      void update(){&#xD;&#xA;        fill(255);&#xD;&#xA;        noStroke();&#xD;&#xA;        ellipse(x, y, 8, 8);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      void show(){}&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // Array that contains all the amount of stars created (100 in this case)&#xD;&#xA;    Star[] stars = new Star[100];&#xD;&#xA;&#xD;&#xA;    void setup(){&#xD;&#xA;      size(800, 800); // TROUBLE HERE. DOESN´T WORK&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i] = new Star();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void draw(){&#xD;&#xA;      background(0); // Colors the background&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i].update();&#xD;&#xA;        stars[i].show();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7597" PostHistoryTypeId="2" PostId="3694" RevisionGUID="71fe6947-ac86-4c52-afd9-f13178af9cd9" CreationDate="2016-06-27T19:28:07.637" UserId="310" Text="IMO, a variation of your second approach is going to be the simplest, and could be quite fast.&#xD;&#xA;&#xD;&#xA;Have you profiled anything yet? A CPU should chew through 10000 matrix multiplications extremely quickly. If you wanted to get even more performance, you could SIMD / thread the update. That said, the slowest part is probably going to be the bandwidth of sending 10000 matrices over the PCIE bus. &#xD;&#xA;&#xD;&#xA;But, again, this is all supposition. Try it out, and profile.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;I was thinking something like this:&#xD;&#xA;&#xD;&#xA;(I apologize for the DX functions. I'm not super familiar with the corresponding OpenGL functions. That said, OpenGL *should* be quite similar)&#xD;&#xA;&#xD;&#xA;    // Variable definitions&#xD;&#xA;&#xD;&#xA;    vector&lt;matrix&gt; lod0;&#xD;&#xA;    vector&lt;matrix&gt; lod1;&#xD;&#xA;    vector&lt;matrix&gt; lod2;&#xD;&#xA;&#xD;&#xA;    ID3D11Buffer lod0VertexBuffer;&#xD;&#xA;    uint lod0VertexCount;&#xD;&#xA;&#xD;&#xA;    ID3D11Buffer lod1VertexBuffer;&#xD;&#xA;    uint lod1VertexCount;&#xD;&#xA;&#xD;&#xA;    ID3D11Buffer lod2VertexBuffer;&#xD;&#xA;    uint lod2VertexCount;&#xD;&#xA;&#xD;&#xA;    ID3D11Buffer instanceBuffer;&#xD;&#xA;&#xD;&#xA;    /// ..................&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    /// Per frame...&#xD;&#xA;    lod0.clear();&#xD;&#xA;    lod1.clear();&#xD;&#xA;    lod2.clear();&#xD;&#xA;&#xD;&#xA;    for (uint i = 0; i &lt; bushes.size(); ++i) {&#xD;&#xA;        float distance = distance(bushes[i].pos, camera.origin);&#xD;&#xA;        if (distance &lt; 50.0f) {&#xD;&#xA;            lod0.push_back(bushes[i].matrix);&#xD;&#xA;        } else if (distance &lt; 100.0f) {&#xD;&#xA;            lod1.push_back(bushes[i].matrix);&#xD;&#xA;        } else {&#xD;&#xA;            lod2.push_back(bushes[i].matrix);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    D3D11_MAPPED_SUBRESOURCE mappedResource;&#xD;&#xA;    ID3D11Buffer vertexBuffers[] = {&#xD;&#xA;        lod0VertexBuffer,&#xD;&#xA;        instanceBuffer&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    // Update lod0 matrices&#xD;&#xA;    context-&gt;Map(instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &amp;mappedResource);&#xD;&#xA;    memcpy(mappedResource.pData, &amp;lod0[0], sizeof(matrix) * lod0.size());&#xD;&#xA;    context-&gt;Unmap(instanceBuffer, 0);&#xD;&#xA;&#xD;&#xA;    // Draw lod0&#xD;&#xA;    context-&gt;IASetVertexBuffers(0, 2, vertexBuffers, nullptr, nullptr);&#xD;&#xA;    context-&gt;DrawInstanced(lod0VertexCount, lod0.size(), 0, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Update lod1 matrices&#xD;&#xA;    context-&gt;Map(instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &amp;mappedResource);&#xD;&#xA;    memcpy(mappedResource.pData, &amp;lod1[0], sizeof(matrix) * lod1.size());&#xD;&#xA;    context-&gt;Unmap(instanceBuffer, 0);&#xD;&#xA;&#xD;&#xA;    // Draw lod1&#xD;&#xA;    vertexBuffers[0] = lod1VertexBuffer;&#xD;&#xA;    context-&gt;IASetVertexBuffers(0, 2, vertexBuffers, nullptr, nullptr);&#xD;&#xA;    context-&gt;DrawInstanced(lod1VertexCount, lod1.size(), 0, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Update lod2 matrices&#xD;&#xA;    context-&gt;Map(instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &amp;mappedResource);&#xD;&#xA;    memcpy(mappedResource.pData, &amp;lod2[0], sizeof(matrix) * lod1.size());&#xD;&#xA;    context-&gt;Unmap(instanceBuffer, 0);&#xD;&#xA;&#xD;&#xA;    // Draw lod2&#xD;&#xA;    vertexBuffers[0] = lod2VertexBuffer;&#xD;&#xA;    context-&gt;IASetVertexBuffers(0, 2, vertexBuffers, nullptr, nullptr);&#xD;&#xA;    context-&gt;DrawInstanced(lod1VertexCount, lod2.size(), 0, 0);&#xD;&#xA;&#xD;&#xA;If this ends up being too slow, you could try to do this calculation in a compute shader, then draw the result using an indirect draw call. See [AZDO][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.gdcvault.com/play/1020791/Approaching-Zero-Driver-Overhead-in" ContentLicense="CC BY-SA 3.0" />
  <row Id="7598" PostHistoryTypeId="5" PostId="3686" RevisionGUID="79585460-fb1a-4c29-ab7d-508bb09c5e4a" CreationDate="2016-06-27T19:59:29.390" UserId="231" Comment="Add syntax highlighting and correct minor typos" Text="I´m new to the Processing language. Trying to do my first sketch I´m having trouble with the dimension of the display window width and height because even though I´ve tried putting a variety of values in the size() function, the size of the window doesn´t change at any time, it always has the same size (100px x 100px). The function fullScreen() has the same results. How could I resolve this problem?&#xD;&#xA;&#xD;&#xA;It´s a simple visualization of a &quot;star field&quot;. First block, class Star, simply create a star and fill it with a color. Second block is where I´m trying to adjust the size of the display window but it doesn´t work.&#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-processing --&gt;&#xD;&#xA;&#xD;&#xA;    class Star {&#xD;&#xA;      float x;&#xD;&#xA;      float y;&#xD;&#xA;      float z;&#xD;&#xA; &#xD;&#xA;      Star(){&#xD;&#xA;        // Places the star in random X and Y coordinates&#xD;&#xA;        x = random(0, width);&#xD;&#xA;        y = random(0, height);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      /* Colors the star */&#xD;&#xA;      void update(){&#xD;&#xA;        fill(255);&#xD;&#xA;        noStroke();&#xD;&#xA;        ellipse(x, y, 8, 8);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      void show(){}&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // Array that contains all the amount of stars created (100 in this case)&#xD;&#xA;    Star[] stars = new Star[100];&#xD;&#xA;&#xD;&#xA;    void Setup(){&#xD;&#xA;      size(800, 800); // TROUBLE HERE. DOESN´T WORK&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i] = new Star();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Draw(){&#xD;&#xA;      background(0); // Colors the background&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i].update();&#xD;&#xA;        stars[i].show();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7599" PostHistoryTypeId="4" PostId="3686" RevisionGUID="79585460-fb1a-4c29-ab7d-508bb09c5e4a" CreationDate="2016-06-27T19:59:29.390" UserId="231" Comment="Add syntax highlighting and correct minor typos" Text="Issue with size() function in Processing language?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7602" PostHistoryTypeId="5" PostId="3693" RevisionGUID="9b505447-a90d-43e3-b5b9-c4d35d907f74" CreationDate="2016-06-27T20:37:51.540" UserDisplayName="user3437" Comment="added 40 characters in body" Text="the window is `100px, 100px` because it is the default size and you are not changing it, as your&#xD;&#xA;`size()` is never been called because `Setup()` is not a predefined function. &#xD;&#xA;`setup()` is the function, lower case `s` not upper case `S`. Same with `draw()`.&#xD;&#xA;&#xD;&#xA;Below is the working code.&#xD;&#xA;&lt;!-- language-all: lang-processing --&gt;&#xD;&#xA;&#xD;&#xA;    class Star {&#xD;&#xA;      float x;&#xD;&#xA;      float y;&#xD;&#xA;      float z;&#xD;&#xA; &#xD;&#xA;      Star(){&#xD;&#xA;        // Places the star in random X and Y coordinates&#xD;&#xA;        x = random(0, width);&#xD;&#xA;        y = random(0, height);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      /* Colors the star */&#xD;&#xA;      void update(){&#xD;&#xA;        fill(255);&#xD;&#xA;        noStroke();&#xD;&#xA;        ellipse(x, y, 8, 8);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      void show(){}&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // Array that contains all the amount of stars created (100 in this case)&#xD;&#xA;    Star[] stars = new Star[100];&#xD;&#xA;&#xD;&#xA;    void setup(){&#xD;&#xA;      size(800, 800); // TROUBLE HERE. DOESN´T WORK&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i] = new Star();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void draw(){&#xD;&#xA;      background(0); // Colors the background&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i].update();&#xD;&#xA;        stars[i].show();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7603" PostHistoryTypeId="5" PostId="3693" RevisionGUID="99dfc196-4bbb-45c0-abfa-4950b8420755" CreationDate="2016-06-27T20:59:48.117" UserId="231" Comment="Minor typos" Text="The window is `100px, 100px` because it is the default size and you are not changing it, as your&#xD;&#xA;`size()` is never being called because `Setup()` is not a predefined function. &#xD;&#xA;`setup()` is the function, lower case `s` not upper case `S`. Same with `draw()`.&#xD;&#xA;&#xD;&#xA;Below is the working code.&#xD;&#xA;&lt;!-- language-all: lang-processing --&gt;&#xD;&#xA;&#xD;&#xA;    class Star {&#xD;&#xA;      float x;&#xD;&#xA;      float y;&#xD;&#xA;      float z;&#xD;&#xA; &#xD;&#xA;      Star(){&#xD;&#xA;        // Places the star in random X and Y coordinates&#xD;&#xA;        x = random(0, width);&#xD;&#xA;        y = random(0, height);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      /* Colors the star */&#xD;&#xA;      void update(){&#xD;&#xA;        fill(255);&#xD;&#xA;        noStroke();&#xD;&#xA;        ellipse(x, y, 8, 8);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      void show(){}&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // Array that contains all the amount of stars created (100 in this case)&#xD;&#xA;    Star[] stars = new Star[100];&#xD;&#xA;&#xD;&#xA;    void setup(){&#xD;&#xA;      size(800, 800); // TROUBLE HERE. DOESN´T WORK&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i] = new Star();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void draw(){&#xD;&#xA;      background(0); // Colors the background&#xD;&#xA;      for(int i = 0; i &lt; stars.length; i++){&#xD;&#xA;        stars[i].update();&#xD;&#xA;        stars[i].show();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7604" PostHistoryTypeId="2" PostId="3696" RevisionGUID="ec95f7aa-726e-48a0-9eec-e730d91b7b34" CreationDate="2016-06-27T21:20:34.373" UserId="506" Text="It doesn’t matter that it’s a point light; the 1/π normalization factor is what’s causing your surface to be 1/π as bright as you’d like it to be. You can either up your light intensity so the maximum brightness is π or just get rid of the normalization factor. There’s a good article with some notes about this and how it interacts with more complex lighting techniques [here](https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/)." ContentLicense="CC BY-SA 3.0" />
  <row Id="7606" PostHistoryTypeId="2" PostId="3697" RevisionGUID="3e749814-a516-4788-97bd-0aa75679fa11" CreationDate="2016-06-27T21:34:46.570" UserId="4656" Text="I need to find the center of a Bezier curve to rotate it. I have a list of all points (control points, beginning and end, all points on the curve itself). How would I go about finding it's center?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7607" PostHistoryTypeId="1" PostId="3697" RevisionGUID="3e749814-a516-4788-97bd-0aa75679fa11" CreationDate="2016-06-27T21:34:46.570" UserId="4656" Text="Algorithm to find the center of a Bezier curve" ContentLicense="CC BY-SA 3.0" />
  <row Id="7608" PostHistoryTypeId="3" PostId="3697" RevisionGUID="3e749814-a516-4788-97bd-0aa75679fa11" CreationDate="2016-06-27T21:34:46.570" UserId="4656" Text="|algorithm|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7609" PostHistoryTypeId="2" PostId="3698" RevisionGUID="9ca1b801-9540-49be-93cd-d59883c9d34e" CreationDate="2016-06-28T03:39:55.790" UserDisplayName="user3412" Text="You want to look up &quot;Intel Graphics Developer Guides&quot;, they are quite thorough.  Here's a link to the latest:&#xD;&#xA;&#xD;&#xA;https://software.intel.com/sites/default/files/managed/c5/9a/The-Compute-Architecture-of-Intel-Processor-Graphics-Gen9-v1d0.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="7610" PostHistoryTypeId="5" PostId="3698" RevisionGUID="d38a340c-0b73-45aa-a01a-2c3d16b71be0" CreationDate="2016-06-28T05:50:20.483" UserDisplayName="user3412" Comment="deleted 23 characters in body" Text="You want to look up &quot;Intel Graphics Developer Guides&quot;, they are quite thorough.  Here's a link to the latest:&#xD;&#xA;&#xD;&#xA;https://software.intel.com/sites/default/files/managed/22/6d/6th_gen_graphics_api_dev_guide_dec_2015.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="7611" PostHistoryTypeId="2" PostId="3699" RevisionGUID="b167a239-4436-4edb-9186-2d9b30d9b59c" CreationDate="2016-06-28T12:27:57.410" UserId="38" Text="This is more of a long comment than answer to a under defined question.&#xD;&#xA;&#xD;&#xA;Bézier Curves are mathematical entities and have no clearly defined center. One can in fact define many different things as the center of the Bézier curve. I have tried to depict some of the possible centers in image 1. More than this do exist.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Some of the possible centers of a single span Bézier curve&#xD;&#xA;&#xD;&#xA;In practice nearly all graphics applications geared for drawing use the center of the local bounding box (BB) as their center. Animation software usually have a additional concept of pivot so they use the ask user approach, if no input is made they often revert to BB center or simply local coordinate center. This probably because the BB needs to be calculated anyway and getting its center is pretty easy to do (see [A Primer on Bézier Curves](http://pomax.github.io/bezierinfo/#boundingbox)).&#xD;&#xA;&#xD;&#xA;The Center of gravity metrics are also somewhat natural especially in a animation context, tough nastier to compute. Easiest being to discretitze the data and do the computation on the discrete input. This said some closed form solutions are possible for the curve center of gravity, but it's not a very nice equation to formulate and simplify.&#xD;&#xA;&#xD;&#xA;Then we have the on the curve points the midpoint by arc length and the point where the $t$ parameter is 0.5. In my mind the $t$ param is often problematic though easy to compute, and it loses meaning when you chain multiple Béziers after each other for a polybézier. The center of length of course is only natural as long as the curve is not closed.&#xD;&#xA;&#xD;&#xA;We also define other possible centers, the center could be at the curve center of gravity of the hull. the average of the control points or the control cage BB center. Although in practice these do not seem to work out very well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N7tQj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7612" PostHistoryTypeId="5" PostId="3699" RevisionGUID="e6588ee5-dac2-4e00-bf04-b8d5312b7e3d" CreationDate="2016-06-28T12:33:55.097" UserId="38" Comment="added 183 characters in body" Text="This is more of a long comment than answer to a underdefined question. &#xD;&#xA;&#xD;&#xA;Bézier Curves are mathematical entities and have no clearly defined center. One can in fact define many different things as the center of the Bézier curve. I have tried to depict some of the possible centers in image 1. More than this do exist.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Some of the possible centers of a single span Bézier curve&#xD;&#xA;&#xD;&#xA;In practice nearly all graphics applications geared for drawing use the center of the local bounding box (BB) as their center. Animation software usually have a additional concept of pivot so they use the ask user approach, if no input is made they often revert to BB center or simply local coordinate center. This probably because the BB needs to be calculated anyway and getting its center is pretty easy to do (see [A Primer on Bézier Curves](http://pomax.github.io/bezierinfo/#boundingbox)). &#xD;&#xA;&#xD;&#xA;The Center of gravity metrics are also somewhat natural especially in a animation context, tough nastier to compute. Easiest being to discretitze the data and do the computation on the discrete input. This said some closed form solutions are possible for the curve center of gravity, but it's not a very nice equation to formulate and simplify.&#xD;&#xA;&#xD;&#xA;Then we have the on the curve points the midpoint by arc length and the point where the $t$ parameter is 0.5. In my mind the $t$ param is often problematic though easy to compute, and it loses meaning when you chain multiple Béziers after each other for a polybézier. The center of length of course is only natural as long as the curve is not closed.&#xD;&#xA;&#xD;&#xA;We also define other possible centers, the center could be at the curve center of gravity of the hull. the average of the control points or the control cage BB center. Although in practice these do not seem to work out very well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Please note**: Altough the curve in picture 1 shows the BB center quite near to some natural centers this this is not always the case formore complex curves and especially polybéziers.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N7tQj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7613" PostHistoryTypeId="5" PostId="3699" RevisionGUID="ca3bca28-248f-409c-bc05-8afc701056fa" CreationDate="2016-06-28T14:04:20.230" UserId="38" Comment="deleted 75 characters in body" Text="Bézier Curves are mathematical entities and have no clearly defined center. One can in fact define many different things as the center of the Bézier curve. I have tried to depict some of the possible centers in image 1. More than this do exist.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Some of the possible centers of a single span Bézier curve&#xD;&#xA;&#xD;&#xA;In practice nearly all graphics applications geared for drawing use the center of the local bounding box (BB) as their center. Animation software usually have a additional concept of pivot so they use the ask user approach, if no input is made they often revert to BB center or simply local coordinate center. This probably because the BB needs to be calculated anyway and getting its center is pretty easy to do (see [A Primer on Bézier Curves](http://pomax.github.io/bezierinfo/#boundingbox)). &#xD;&#xA;&#xD;&#xA;The Center of gravity metrics are also somewhat natural especially in a animation context, tough nastier to compute. Easiest being to discretitze the data and do the computation on the discrete input. This said some closed form solutions are possible for the curve center of gravity, but it's not a very nice equation to formulate and simplify.&#xD;&#xA;&#xD;&#xA;Then we have the on the curve points the midpoint by arc length and the point where the $t$ parameter is 0.5. In my mind the $t$ param is often problematic though easy to compute, and it loses meaning when you chain multiple Béziers after each other for a polybézier. The center of length of course is only natural as long as the curve is not closed.&#xD;&#xA;&#xD;&#xA;We also define other possible centers, the center could be at the curve center of gravity of the hull. the average of the control points or the control cage BB center. Although in practice these do not seem to work out very well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Please note**: Altough the curve in picture 1 shows the BB center quite near to some natural centers this this is not always the case formore complex curves and especially polybéziers.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N7tQj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7614" PostHistoryTypeId="5" PostId="3699" RevisionGUID="d8b2e893-7e39-436f-a1f2-049816d65f52" CreationDate="2016-06-28T14:15:23.593" UserId="231" Comment="Minor typos - please revert anything I misjudged" Text="Bézier curves are mathematical entities and have no clearly defined center. One can in fact define many different things as the center of the Bézier curve. I have tried to depict some of the possible centers in image 1. More than this do exist.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Some of the possible centers of a single span Bézier curve&#xD;&#xA;&#xD;&#xA;In practice nearly all graphics applications geared for drawing use the center of the local bounding box (BB) as their center. Animation software usually have an additional concept of pivot so they use the ask user approach, if no input is made they often revert to BB center or simply local coordinate center. This is probably because the BB needs to be calculated anyway and getting its center is pretty easy to do (see [A Primer on Bézier Curves](http://pomax.github.io/bezierinfo/#boundingbox)). &#xD;&#xA;&#xD;&#xA;The center of gravity metrics are also somewhat natural especially in an animation context, though nastier to compute. Easiest being to discretize the data and do the computation on the discrete input. This said some closed form solutions are possible for the curve center of gravity, but it's not a very nice equation to formulate and simplify.&#xD;&#xA;&#xD;&#xA;Then we have the on the curve points: the midpoint by arc length and the point where the $t$ parameter is 0.5. In my mind the $t$ param is often problematic though easy to compute, and it loses meaning when you chain multiple Béziers after each other for a polybézier. The center of length of course is only natural as long as the curve is not closed.&#xD;&#xA;&#xD;&#xA;We also define other possible centers, the center could be at the curve center of gravity of the hull, the average of the control points or the control cage BB center. Although in practice these do not seem to work out very well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Please note**: Although the curve in picture 1 shows the BB center quite near to some natural centers this this is not always the case for more complex curves and especially polybéziers.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N7tQj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7615" PostHistoryTypeId="2" PostId="3700" RevisionGUID="94ea21ae-7304-4b68-b627-9daec9392587" CreationDate="2016-06-28T19:09:42.353" UserDisplayName="user3437" Text="So i was reading [this][1], so i sort of got the reason why there are a lot more games on Microsoft windows than on any other OS. The main issue presented was that Direct3D is preferred over OpenGL. &#xD;&#xA;&#xD;&#xA;What i don't understand why would any developer sacrifice compatibility ? , that is simply a financial loss to the company. I understand that OpenGL is kind of mess, but that should hardly be a issue for experts. Even if it is, i think that people would go a extra mile than to incur a financial loss. &#xD;&#xA;&#xD;&#xA;Also if i not wrong then many cross platform applications use both Direct3D and OpenGL. I think they switch between the APIs.     &#xD;&#xA;&#xD;&#xA;This is weird as they can just use OpenGL, why even care about Direct3D ? &#xD;&#xA;&#xD;&#xA;So the question is , are there any technical issues with OpenGL ? or is there any support that that Direct3D provide that OpenGL lacks ?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;i am aware that this question might be closed as being off-topic or too broad, i tried my best to narrow it down.    &#xD;&#xA;&#xD;&#xA;  [1]: http://programmers.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7616" PostHistoryTypeId="1" PostId="3700" RevisionGUID="94ea21ae-7304-4b68-b627-9daec9392587" CreationDate="2016-06-28T19:09:42.353" UserDisplayName="user3437" Text="Is there any reason to prefer Direct3D over OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7617" PostHistoryTypeId="3" PostId="3700" RevisionGUID="94ea21ae-7304-4b68-b627-9daec9392587" CreationDate="2016-06-28T19:09:42.353" UserDisplayName="user3437" Text="|opengl|direct3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7618" PostHistoryTypeId="5" PostId="3698" RevisionGUID="c0087b44-92df-45a7-a0f1-d06f066decba" CreationDate="2016-06-29T05:56:39.997" UserDisplayName="user3412" Comment="Added snippets of the manuals to give an overview of architectural evolution..." Text="You want to look up &quot;Intel Graphics Developer Guides&quot;, they are quite thorough.  Here's a link to the latest:&#xD;&#xA;&#xD;&#xA;https://software.intel.com/sites/default/files/managed/22/6d/6th_gen_graphics_api_dev_guide_dec_2015.pdf&#xD;&#xA;&#xD;&#xA;And here's the architectural Cliff Notes for the past five generations of Intel GPUs:&#xD;&#xA;&#xD;&#xA;&quot;In several important respects, the 6th gen Intel Core processors' graphics hardware architecture is similar to that of 5th generation Intel® CoreTM processors&quot;&#xD;&#xA;&#xD;&#xA;&quot;The graphics hardware architecture of the 5th gen Intel Core processors is similar to that of the 4th gen processors.&quot;&#xD;&#xA;&#xD;&#xA;&quot;The graphics hardware architecture in the 4th gen Intel Core processor is similar to that in the 3rd gen processor.&quot;&#xD;&#xA;&#xD;&#xA;&quot;The new generation of microarchitecture, codenamed Ivy Bridge, provides another jump in functionality and performance over Sandy Bridge microarchitecture.&quot;&#xD;&#xA;&#xD;&#xA;&quot;With the introduction of the Intel microarchitecture codenamed Sandy Bridge, the graphics processor has moved onto the same die as the CPU, and is now referred to as “processor graphics”. In addition, processor graphics has enjoyed numerous architectural improvements that yield significant performance improvements over previous generations of Intel® integrated graphics parts.&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7619" PostHistoryTypeId="2" PostId="3701" RevisionGUID="8148f193-8fae-48b5-93ee-44d70b09ea71" CreationDate="2016-06-29T11:01:51.503" UserId="67" Text="A couple of possible reasons:&#xD;&#xA;&#xD;&#xA;* Historically, OpenGL driver quality has varied a lot, but I'm not sure that's the case any more.&#xD;&#xA;* Xbox supports D3D so porting a game between it and PC is easier.&#xD;&#xA;* Debugging tools for D3D have been better than for OpenGL. Luckily we now have [RenderDoc][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://renderdoc.org" ContentLicense="CC BY-SA 3.0" />
  <row Id="7620" PostHistoryTypeId="2" PostId="3702" RevisionGUID="54fc19d0-9d9c-4db5-8bf9-d70904acabde" CreationDate="2016-06-29T15:17:03.670" UserId="4665" Text="About the fact that there are more games for Windows, some reasons are&#xD;&#xA;&#xD;&#xA; 1. Windows has the majority of the market and in the past to develop cross platform games was more complicated than it is today.&#xD;&#xA; 2. DirectX comes with way better tools for developing (e.g. debugging)&#xD;&#xA; 3. Big innovations are generally first created/implemented in DirectX, and then ported to/implemented in OpenGL. &#xD;&#xA; 4. As for Windows vs Linux, you have to consider that when there is an actual standard due to marketing and historical reasons (for that see http://programmers.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows, as I said in the comments), it has its inertia.&#xD;&#xA;&#xD;&#xA;The inertia thing is very important. If your team develop for DirectX, targeting 90% of the market (well... if you play games on pc you probaly have windows, so... 99% of the market?), why would you want to invest in OpenGL? If you already develop in OpenGL, again targeting 99% of the market, you will stick to it as long as you can. For exampe Id Tech by Id Software is an excellent game engine (powering the DOOM series) that uses OpenGL.&#xD;&#xA;&#xD;&#xA;**About the topic of your discussion, a comment.**&#xD;&#xA;&#xD;&#xA;As of today, there are many many APIs, and a common practice is to use a Game Engine that abstracts over them. For example, consider that&#xD;&#xA; &#xD;&#xA; - On most mobile platform you have to use OpenGl ES.&#xD;&#xA; - On PC you can use both DirectX and OpenGL&#xD;&#xA; - I think on XBOX you have to use DirectX.&#xD;&#xA; - I think that on PS you use their own API. &#xD;&#xA; - With old hardware you use DirectX9 or OpenGL 3, or OpenGL ES 2.&#xD;&#xA; - With more recent hardware you can (and want to) use DirectX 11, OpenGL 4, OpenGL ES 3.&#xD;&#xA;  &#xD;&#xA;Recently, with the advent of the new low overhead APIs - whch is a major turning point for graphical programming - there are DirectX 12 for Windows and XBOX, Metal for iOS and Vulkan (the new OpenGL) for Windows and Linux (including Android and Tizen).&#xD;&#xA;&#xD;&#xA;There still are games that only target Windows and XBOX, but IMHO today that can only be marketing choice.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7624" PostHistoryTypeId="2" PostId="3704" RevisionGUID="c15010ae-b786-4c0d-b726-a475e8cdfe70" CreationDate="2016-06-29T23:38:17.307" UserId="4638" Text="New to computer graphics, so please be gentle. Shading and shadowing are often mentioned in how to create realistic 3D graphics, but the distinction is not clear. Are both responsible for the generation of shadows, or do they refer to the same concept?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7625" PostHistoryTypeId="1" PostId="3704" RevisionGUID="c15010ae-b786-4c0d-b726-a475e8cdfe70" CreationDate="2016-06-29T23:38:17.307" UserId="4638" Text="What is the difference between shading and shadowing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7626" PostHistoryTypeId="3" PostId="3704" RevisionGUID="c15010ae-b786-4c0d-b726-a475e8cdfe70" CreationDate="2016-06-29T23:38:17.307" UserId="4638" Text="|lighting|shadow|shading|ambient-occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7628" PostHistoryTypeId="2" PostId="3705" RevisionGUID="fd594e36-e2f5-49d4-8ef0-1152d7fefec7" CreationDate="2016-06-30T06:16:23.510" UserId="67" Text="In simplified terms, shading controls how object's surface's brightness changes when the angle between its normal and light vector changes. Shadows are areas where the light cannot reach because it's occluded by other objects. So no, they both are not responsible for creating shadows." ContentLicense="CC BY-SA 3.0" />
  <row Id="7629" PostHistoryTypeId="2" PostId="3706" RevisionGUID="64c27313-ec6f-4d7a-8fd3-62a588886bfe" CreationDate="2016-06-30T07:13:18.660" UserId="2308" Text="I have a simple game and and subjects of it are these little lines. It is targeted for iOS and android so it has a HUGE range of processors that it could run on, right now.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am trying to add realtime glow to them for two reasons&#xD;&#xA;1. I am trying to hide the fact that I don't have the rendering time to process anti-aliasing on most devices.&#xD;&#xA;2. The subject of the game is supposed to be pure light, ergo that picture should look like those things are pure light.&#xD;&#xA;&#xD;&#xA;I have been tweaking a separable gaussian blur shader for quite awhile and I have came up to a point of frustration, I just can't get it to look right, perhaps the issue is I am trying to futilely hide the jagged edges of the light meanwhile not making the light look blurry.&#xD;&#xA;&#xD;&#xA;Anyway I had questions in two areas:&#xD;&#xA; - So many variables:&#xD;&#xA;I am very new to graphics/rendering and I am in no way an artist. Perhaps the most frustrating thing about rending to me is all the variables that seem to be involved. With glow I have seen so many possible changes.&#xD;&#xA;&#xD;&#xA; -  A. Add blend mode, screen blend mode, or some other concoction  &#xD;&#xA; - B.Weighting the blur, and normal differently before combination &#xD;&#xA; - C. The&#xD;&#xA;   Sigma of the gaussian bell function (I have been using [this][2]&#xD;&#xA;   confusing calculator but it doesn't seem to give the same values I&#xD;&#xA;   see other people have in) &#xD;&#xA; - D. Scalars on the &quot;x&quot; values sent to the&#xD;&#xA;   sigma function &#xD;&#xA; - E. Sample scale (making the blur radius smaller or&#xD;&#xA;   larger) &#xD;&#xA; - F. Changing the resolution of the glow buffer&#xD;&#xA;&#xD;&#xA;How does one find the &quot;best looking&quot; constants when working with so many variables like this?&#xD;&#xA;&#xD;&#xA;I am also having issues because the time between me making a tweak and seeing it is a long that its hard to see changes, I would do it in shader toy however I can't load up this image or procedurally generate one like it.&#xD;&#xA;&#xD;&#xA;Right now I am really stuck on the sigma of the gaussian bell curve kernel, especially because I am coding in the numbers rather then the formula because I need the processor speed. [Can you suggest a good sigma to use][2]?&#xD;&#xA;&#xD;&#xA;2. Physics of light:&#xD;&#xA;I have recently been inspired by the short youtube video [&quot;computer color is broken&quot;][3] and I have [messed with it with color interpolation][4] and boy is it beautiful!&#xD;&#xA;&#xD;&#xA;A big thing the video talks about is that this principal should be applied to blurring, however I am pretty confused.  I don't really know what to square when and what to sqrt when when values are being added. My current theory is each texture sample for the gaussian blur gets raised by the power of two weighted with a bell curve and added to a sum like usual. At the end the sum is square rooted, but i'm not sure if that is correct. Could someone please confirm? Would this make an appreciable difference that made things worth it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6CojT.jpg&#xD;&#xA;  [2]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=LKnqECcg6Gw&#xD;&#xA;  [4]: https://www.shadertoy.com/view/MsGSR3" ContentLicense="CC BY-SA 3.0" />
  <row Id="7630" PostHistoryTypeId="1" PostId="3706" RevisionGUID="64c27313-ec6f-4d7a-8fd3-62a588886bfe" CreationDate="2016-06-30T07:13:18.660" UserId="2308" Text="I am trying to make my glow shader look better" ContentLicense="CC BY-SA 3.0" />
  <row Id="7631" PostHistoryTypeId="3" PostId="3706" RevisionGUID="64c27313-ec6f-4d7a-8fd3-62a588886bfe" CreationDate="2016-06-30T07:13:18.660" UserId="2308" Text="|lighting|pixel-shader|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7632" PostHistoryTypeId="5" PostId="3706" RevisionGUID="5898739b-399e-428d-bed4-66bd7e73592d" CreationDate="2016-06-30T07:21:15.090" UserId="16" Comment="I think this was the intended formatting?" Text="I have a simple game and and subjects of it are these little lines. It is targeted for iOS and android so it has a HUGE range of processors that it could run on, right now.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am trying to add realtime glow to them for two reasons&#xD;&#xA;&#xD;&#xA;1. I am trying to hide the fact that I don't have the rendering time to process anti-aliasing on most devices.&#xD;&#xA;2. The subject of the game is supposed to be pure light, ergo that picture should look like those things are pure light.&#xD;&#xA;&#xD;&#xA;I have been tweaking a separable gaussian blur shader for quite awhile and I have came up to a point of frustration, I just can't get it to look right, perhaps the issue is I am trying to futilely hide the jagged edges of the light meanwhile not making the light look blurry.&#xD;&#xA;&#xD;&#xA;Anyway I had questions in two areas:&#xD;&#xA;&#xD;&#xA;1. So many variables:&#xD;&#xA;&#xD;&#xA;  I am very new to graphics/rendering and I am in no way an artist. Perhaps the most frustrating thing about rending to me is all the variables that seem to be involved. With glow I have seen so many possible changes.&#xD;&#xA;&#xD;&#xA; -  A. Add blend mode, screen blend mode, or some other concoction  &#xD;&#xA; - B.Weighting the blur, and normal differently before combination &#xD;&#xA; - C. The&#xD;&#xA;   Sigma of the gaussian bell function (I have been using [this][2]&#xD;&#xA;   confusing calculator but it doesn't seem to give the same values I&#xD;&#xA;   see other people have in) &#xD;&#xA; - D. Scalars on the &quot;x&quot; values sent to the&#xD;&#xA;   sigma function &#xD;&#xA; - E. Sample scale (making the blur radius smaller or&#xD;&#xA;   larger) &#xD;&#xA; - F. Changing the resolution of the glow buffer&#xD;&#xA;&#xD;&#xA;  &lt;br&gt;&#xD;&#xA;  How does one find the &quot;best looking&quot; constants when working with so many variables like this?&#xD;&#xA;&#xD;&#xA;  I am also having issues because the time between me making a tweak and seeing it is a long that its hard to see changes, I would do it in shader toy however I can't load up this image or procedurally generate one like it.&#xD;&#xA;&#xD;&#xA;  Right now I am really stuck on the sigma of the gaussian bell curve kernel, especially because I am coding in the numbers rather then the formula because I need the processor speed. [Can you suggest a good sigma to use][2]?&#xD;&#xA;&#xD;&#xA;2. Physics of light:&#xD;&#xA;I have recently been inspired by the short youtube video [&quot;computer color is broken&quot;][3] and I have [messed with it with color interpolation][4] and boy is it beautiful!&#xD;&#xA;&#xD;&#xA;  A big thing the video talks about is that this principal should be applied to blurring, however I am pretty confused.  I don't really know what to square when and what to sqrt when when values are being added. My current theory is each texture sample for the gaussian blur gets raised by the power of two weighted with a bell curve and added to a sum like usual. At the end the sum is square rooted, but i'm not sure if that is correct. Could someone please confirm? Would this make an appreciable difference that made things worth it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6CojT.jpg&#xD;&#xA;  [2]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=LKnqECcg6Gw&#xD;&#xA;  [4]: https://www.shadertoy.com/view/MsGSR3" ContentLicense="CC BY-SA 3.0" />
  <row Id="7633" PostHistoryTypeId="2" PostId="3707" RevisionGUID="0c9e2e31-c765-416d-b9b4-addd8193c59a" CreationDate="2016-06-30T07:28:55.903" UserId="2308" Text="I am trying to make a glow shader using separable gaussian blurring.&#xD;&#xA;&#xD;&#xA;I have recently been inspired by the short youtube video [&quot;computer color is broken&quot;][3] and I have [messed with it with color interpolation][4] and boy his suggestion is beautiful!&#xD;&#xA;&#xD;&#xA;  A big thing the video talks about is that this principal should be applied to blurring, however I am pretty confused.  I don't really know what to square when and what to sqrt when when values are being added. My current theory is each texture sample for the gaussian blur gets raised by the power of two weighted with a bell curve and added to a sum like usual. At the end the sum is square rooted, but i'm not sure if that is correct. Could someone please confirm? Would this make an appreciable difference that made things worth it?&#xD;&#xA;&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=LKnqECcg6Gw&#xD;&#xA;  [4]: https://www.shadertoy.com/view/MsGSR3" ContentLicense="CC BY-SA 3.0" />
  <row Id="7634" PostHistoryTypeId="1" PostId="3707" RevisionGUID="0c9e2e31-c765-416d-b9b4-addd8193c59a" CreationDate="2016-06-30T07:28:55.903" UserId="2308" Text="Applying correct light physics to gaussian blur formulas for glow" ContentLicense="CC BY-SA 3.0" />
  <row Id="7635" PostHistoryTypeId="3" PostId="3707" RevisionGUID="0c9e2e31-c765-416d-b9b4-addd8193c59a" CreationDate="2016-06-30T07:28:55.903" UserId="2308" Text="|physics|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7636" PostHistoryTypeId="5" PostId="3706" RevisionGUID="9d109211-15c7-4d39-a4d3-7ff6b4ee8f9c" CreationDate="2016-06-30T07:29:22.590" UserId="2308" Comment="Removed the physics part and moved it to http://computergraphics.stackexchange.com/questions/3707/applying-correct-light-physics-to-gaussian-blur-formulas-for-glow" Text="I have a simple game and and subjects of it are these little lines. It is targeted for iOS and android so it has a HUGE range of processors that it could run on, right now.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am trying to add realtime glow to them for two reasons&#xD;&#xA;&#xD;&#xA;1. I am trying to hide the fact that I don't have the rendering time to process anti-aliasing on most devices.&#xD;&#xA;2. The subject of the game is supposed to be pure light, ergo that picture should look like those things are pure light.&#xD;&#xA;&#xD;&#xA;I have been tweaking a separable gaussian blur shader for quite awhile and I have came up to a point of frustration, I just can't get it to look right, perhaps the issue is I am trying to futilely hide the jagged edges of the light meanwhile not making the light look blurry.&#xD;&#xA;&#xD;&#xA;My biggest problem is all the variables involved in making it look its best.&#xD;&#xA;&#xD;&#xA;  I am very new to graphics/rendering and I am in no way an artist. Perhaps the most frustrating thing about rending to me is all the variables that seem to be involved. With glow I have seen so many possible changes.&#xD;&#xA;&#xD;&#xA; -  A. Add blend mode, screen blend mode, or some other concoction  &#xD;&#xA; - B.Weighting the blur, and normal differently before combination &#xD;&#xA; - C. The&#xD;&#xA;   Sigma of the gaussian bell function (I have been using [this][2]&#xD;&#xA;   confusing calculator but it doesn't seem to give the same values I&#xD;&#xA;   see other people have in) &#xD;&#xA; - D. Scalars on the &quot;x&quot; values sent to the&#xD;&#xA;   sigma function &#xD;&#xA; - E. Sample scale (making the blur radius smaller or&#xD;&#xA;   larger) &#xD;&#xA; - F. Changing the resolution of the glow buffer&#xD;&#xA;&#xD;&#xA;  &lt;br&gt;&#xD;&#xA;  How does one find the &quot;best looking&quot; constants when working with so many variables like this?&#xD;&#xA;&#xD;&#xA;  I am also having issues because the time between me making a tweak and seeing it is a long that its hard to see changes, I would do it in shader toy however I can't load up this image or procedurally generate one like it.&#xD;&#xA;&#xD;&#xA;  Right now I am really stuck on the sigma of the gaussian bell curve kernel, especially because I am coding in the numbers rather then the formula because I need the processor speed. [Can you suggest a good sigma to use][2]?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6CojT.jpg&#xD;&#xA;  [2]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7637" PostHistoryTypeId="4" PostId="3706" RevisionGUID="9d109211-15c7-4d39-a4d3-7ff6b4ee8f9c" CreationDate="2016-06-30T07:29:22.590" UserId="2308" Comment="Removed the physics part and moved it to http://computergraphics.stackexchange.com/questions/3707/applying-correct-light-physics-to-gaussian-blur-formulas-for-glow" Text="Tweaking a glow shader to make it look better" ContentLicense="CC BY-SA 3.0" />
  <row Id="7638" PostHistoryTypeId="5" PostId="3706" RevisionGUID="f4772f88-5001-4f45-9432-2dce432cdce1" CreationDate="2016-06-30T07:31:06.367" UserId="16" Comment="deleted 14 characters in body" Text="I have a simple game and and subjects of it are these little lines. It is targeted for iOS and android so it has a HUGE range of processors that it could run on, right now.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am trying to add realtime glow to them for two reasons&#xD;&#xA;&#xD;&#xA;1. I am trying to hide the fact that I don't have the rendering time to process anti-aliasing on most devices.&#xD;&#xA;2. The subject of the game is supposed to be pure light, ergo that picture should look like those things are pure light.&#xD;&#xA;&#xD;&#xA;I have been tweaking a separable gaussian blur shader for quite awhile and I have came up to a point of frustration, I just can't get it to look right, perhaps the issue is I am trying to futilely hide the jagged edges of the light meanwhile not making the light look blurry.&#xD;&#xA;&#xD;&#xA;My biggest problem is all the variables involved in making it look its best.&#xD;&#xA;&#xD;&#xA;  I am very new to graphics/rendering and I am in no way an artist. Perhaps the most frustrating thing about rending to me is all the variables that seem to be involved. With glow I have seen so many possible changes.&#xD;&#xA;&#xD;&#xA; -  A. Add blend mode, screen blend mode, or some other concoction  &#xD;&#xA; - B.Weighting the blur, and normal differently before combination &#xD;&#xA; - C. The&#xD;&#xA;   Sigma of the gaussian bell function (I have been using [this][2]&#xD;&#xA;   confusing calculator but it doesn't seem to give the same values I&#xD;&#xA;   see other people have in) &#xD;&#xA; - D. Scalars on the &quot;x&quot; values sent to the&#xD;&#xA;   sigma function &#xD;&#xA; - E. Sample scale (making the blur radius smaller or&#xD;&#xA;   larger) &#xD;&#xA; - F. Changing the resolution of the glow buffer&#xD;&#xA;&#xD;&#xA;How does one find the &quot;best looking&quot; constants when working with so many variables like this?&#xD;&#xA;&#xD;&#xA;I am also having issues because the time between me making a tweak and seeing it is a long that its hard to see changes, I would do it in shader toy however I can't load up this image or procedurally generate one like it.&#xD;&#xA;&#xD;&#xA;Right now I am really stuck on the sigma of the gaussian bell curve kernel, especially because I am coding in the numbers rather then the formula because I need the processor speed. [Can you suggest a good sigma to use][2]?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6CojT.jpg&#xD;&#xA;  [2]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7650" PostHistoryTypeId="5" PostId="3704" RevisionGUID="9d877d01-0c8c-47b3-b991-c2a3df1f0f0a" CreationDate="2016-07-01T14:54:45.730" UserDisplayName="user3437" Comment="removed useless stuff" Text="Shading and shadowing are often mentioned in how to create realistic 3D graphics, but the distinction is not clear. Are both responsible for the generation of shadows, or do they refer to the same concept?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7651" PostHistoryTypeId="24" PostId="3704" RevisionGUID="9d877d01-0c8c-47b3-b991-c2a3df1f0f0a" CreationDate="2016-07-01T14:54:45.730" Comment="Proposed by 3437 approved by 209, 310 edit id of 150" ContentLicense="CC BY-SA 3.0" />
  <row Id="7652" PostHistoryTypeId="2" PostId="3709" RevisionGUID="6da803eb-f2bb-4240-b2d7-8909cfa27b73" CreationDate="2016-07-01T15:29:33.447" UserId="4620" Text="I would be open to moving this to math, but since it is a geometric problem that I need for computer graphics, I went with this SE.&#xD;&#xA;&#xD;&#xA;I have two circles, that I know are both tangential to a third (unknown) circle. I also know what quadrants of the circles the tangential points are in. It is as pictured below. I also know the arc angle that the third circle spans between the two tangential points (beta).&#xD;&#xA;&#xD;&#xA;Would like to know the location of the two tangential points, as well one of the tangential directions, so I can draw the unknown (red) circle.&#xD;&#xA;&#xD;&#xA;I currently have a working solution for this involving a nonlinear equation solver. If at all possible I would like to have a solution that involves no non-linear equation solving, because I need to run very many of these problems and I need precise results.&#xD;&#xA;&#xD;&#xA;Thanks for reading!&#xD;&#xA;&#xD;&#xA;[![Arrangement of the circles][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/anI6om.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7653" PostHistoryTypeId="1" PostId="3709" RevisionGUID="6da803eb-f2bb-4240-b2d7-8909cfa27b73" CreationDate="2016-07-01T15:29:33.447" UserId="4620" Text="Closed form solution to a problem of tangent circles" ContentLicense="CC BY-SA 3.0" />
  <row Id="7654" PostHistoryTypeId="3" PostId="3709" RevisionGUID="6da803eb-f2bb-4240-b2d7-8909cfa27b73" CreationDate="2016-07-01T15:29:33.447" UserId="4620" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7655" PostHistoryTypeId="2" PostId="3710" RevisionGUID="8b832d3c-7d39-4fd7-b28c-ab790ac97b73" CreationDate="2016-07-01T21:08:00.613" UserId="4652" Text="I have implemented the cartesian-to-polar-conversion and have used different interpolation methods:&#xD;&#xA;&#xD;&#xA;1) nearest neighbor&#xD;&#xA;&#xD;&#xA;2) a subsampling approach, which averages 81 subpixel locations&#xD;&#xA;&#xD;&#xA;3) bilinear interpolation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The 2nd row in the image below shows detail magnifications of the output for the three approaches:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the GLSL shader code for approach 1 and 3:&#xD;&#xA;&lt;code&gt;&#xD;&#xA;precision mediump float;&#xD;&#xA;varying vec2 tc; // texture coordinate of current output pixel&#xD;&#xA;uniform sampler2D inputImg; // input image&#xD;&#xA;const float PI = 3.141592653589793238462643383;&#xD;&#xA;void main() {&#xD;&#xA;  float phi = tc.x; // phi is x-direction in output&#xD;&#xA;  float r = tc.y;   // radius is y-direction in output&#xD;&#xA;  float xx = r * cos(2.0 * PI * phi);  // unit circle in range [-1.0, 1.0]&#xD;&#xA;  float yy = r * sin(2.0 * PI * phi);&#xD;&#xA;  float x = xx * 0.5 + 0.5; // input texture coordinate in range [0.0, 1.0];&#xD;&#xA;  float y = yy * 0.5 + 0.5;&#xD;&#xA;  gl_FragColor = texture2D(inputImg, vec2(x,y));&#xD;&#xA;}&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;This is the GLSL shader code for approach 2:&#xD;&#xA;&lt;code&gt;&#xD;&#xA;precision mediump float;&#xD;&#xA;varying vec2 tc; // texture coordinate of current output pixel&#xD;&#xA;uniform sampler2D inputImg; // input image&#xD;&#xA;uniform int outputWidth; // width of output image&#xD;&#xA;uniform int outputHeight; // height of output image&#xD;&#xA;const float PI = 3.141592653589793238462643383;&#xD;&#xA;const int samplesPerSide = 4;&#xD;&#xA;void main() {&#xD;&#xA;  int samplesPerDirection = samplesPerSide * 2 + 1;&#xD;&#xA;  // compute size of subsample step in texture coordinates&#xD;&#xA;  float sampleStepX = 1.0 / float(outputWidth * samplesPerDirection); &#xD;&#xA;  float sampleStepY = 1.0 / float(outputHeight * samplesPerDirection);&#xD;&#xA;  vec4 sampleSum = vec4(0); // init sum to zero&#xD;&#xA;  for(int i = -samplesPerSide; i &lt;= samplesPerSide; i++) {&#xD;&#xA;    for(int j = -samplesPerSide; j &lt;= samplesPerSide; j++) {&#xD;&#xA;      float phi = tc.x + float(i) * sampleStepX; // phi is x-direction in output&#xD;&#xA;      float r = tc.y + float(j) * sampleStepY;   // radius is y-direction in output&#xD;&#xA;      float xx = r * cos(2.0 * PI * phi);  // unit circle in range [-1.0, 1.0]&#xD;&#xA;      float yy = r * sin(2.0 * PI * phi);&#xD;&#xA;      float x = xx * 0.5 + 0.5; // input texture coordinate in range [0.0, 1.0];&#xD;&#xA;      float y = yy * 0.5 + 0.5;&#xD;&#xA;      sampleSum += texture2D(inputImg, vec2(x,y));&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;  gl_FragColor += sampleSum / float(samplesPerDirection * samplesPerDirection);&#xD;&#xA;}&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;Approach 2, which is approx. factor 81 slower than 1 and 3, is probably the one you are looking for but I also like the bilinear interpolation result.&#xD;&#xA;&#xD;&#xA;With a WebGL capable browser you can try out these implementations here:&#xD;&#xA;&#xD;&#xA;https://www.gsn-lib.org/index.html#projectName=CartesianToPolar&amp;graphName=CartesianToPolar&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3o1vV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7656" PostHistoryTypeId="5" PostId="3710" RevisionGUID="a544234e-ff6a-4423-a64e-8b82d38322fe" CreationDate="2016-07-02T07:02:48.307" UserId="38" Comment="added 132 characters in body" Text="I have implemented the cartesian-to-polar-conversion and have used different interpolation methods:&#xD;&#xA;&#xD;&#xA;1) nearest neighbor&#xD;&#xA;&#xD;&#xA;2) a subsampling approach, which averages 81 subpixel locations&#xD;&#xA;&#xD;&#xA;3) bilinear interpolation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The 2nd row in the image below shows detail magnifications of the output for the three approaches:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the GLSL shader code for approach 1 and 3:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    varying vec2 tc; // texture coordinate of current output pixel&#xD;&#xA;    uniform sampler2D inputImg; // input image&#xD;&#xA;    const float PI = 3.141592653589793238462643383;&#xD;&#xA;    void main() {&#xD;&#xA;      float phi = tc.x; // phi is x-direction in output&#xD;&#xA;      float r = tc.y;   // radius is y-direction in output&#xD;&#xA;      float xx = r * cos(2.0 * PI * phi);  // unit circle in range [-1.0, 1.0]&#xD;&#xA;      float yy = r * sin(2.0 * PI * phi);&#xD;&#xA;      float x = xx * 0.5 + 0.5; // input texture coordinate in range [0.0, 1.0];&#xD;&#xA;      float y = yy * 0.5 + 0.5;&#xD;&#xA;      gl_FragColor = texture2D(inputImg, vec2(x,y));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is the GLSL shader code for approach 2:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    varying vec2 tc; // texture coordinate of current output pixel&#xD;&#xA;    uniform sampler2D inputImg; // input image&#xD;&#xA;    uniform int outputWidth; // width of output image&#xD;&#xA;    uniform int outputHeight; // height of output image&#xD;&#xA;    const float PI = 3.141592653589793238462643383;&#xD;&#xA;    const int samplesPerSide = 4;&#xD;&#xA;    void main() {&#xD;&#xA;      int samplesPerDirection = samplesPerSide * 2 + 1;&#xD;&#xA;      // compute size of subsample step in texture coordinates&#xD;&#xA;      float sampleStepX = 1.0 / float(outputWidth * samplesPerDirection); &#xD;&#xA;      float sampleStepY = 1.0 / float(outputHeight * samplesPerDirection);&#xD;&#xA;      vec4 sampleSum = vec4(0); // init sum to zero&#xD;&#xA;      for(int i = -samplesPerSide; i &lt;= samplesPerSide; i++) {&#xD;&#xA;        for(int j = -samplesPerSide; j &lt;= samplesPerSide; j++) {&#xD;&#xA;          float phi = tc.x + float(i) * sampleStepX; // phi is x-direction in output&#xD;&#xA;          float r = tc.y + float(j) * sampleStepY;   // radius is y-direction in output&#xD;&#xA;          float xx = r * cos(2.0 * PI * phi);  // unit circle in range [-1.0, 1.0]&#xD;&#xA;          float yy = r * sin(2.0 * PI * phi);&#xD;&#xA;          float x = xx * 0.5 + 0.5; // input texture coordinate in range [0.0, 1.0];&#xD;&#xA;          float y = yy * 0.5 + 0.5;&#xD;&#xA;          sampleSum += texture2D(inputImg, vec2(x,y));&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;      gl_FragColor += sampleSum / float(samplesPerDirection * samplesPerDirection);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Approach 2, which is approx. factor 81 slower than 1 and 3, is probably the one you are looking for but I also like the bilinear interpolation result.&#xD;&#xA;&#xD;&#xA;With a WebGL capable browser you can try out these implementations here:&#xD;&#xA;&#xD;&#xA;https://www.gsn-lib.org/index.html#projectName=CartesianToPolar&amp;graphName=CartesianToPolar&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3o1vV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7657" PostHistoryTypeId="2" PostId="3711" RevisionGUID="615217dd-8206-4165-ba69-34098e7de017" CreationDate="2016-07-02T08:25:52.297" UserId="38" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles. The other solutions are permutations of inside tangency and outside tangency.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x-r_2)^2-2(x-r_1)(x-r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{2} \left(\pm\sqrt{\frac{\cos (b) (\text{r1}-\text{r2})^2-2 d^2+(\text{r1}-\text{r2})^2}{\cos (b)-1}}-\text{r1}-\text{r2}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7658" PostHistoryTypeId="5" PostId="3711" RevisionGUID="552c3b1e-e029-4757-9cd4-642952b22f17" CreationDate="2016-07-02T08:31:08.127" UserId="38" Comment="deleted 28 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles. The other solutions are permutations of inside tangency and outside tangency.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x-r_2)^2-2(x-r_1)(x-r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7659" PostHistoryTypeId="5" PostId="3711" RevisionGUID="256dc511-35c9-4304-a876-2af23226f232" CreationDate="2016-07-02T08:43:29.920" UserId="38" Comment="added 110 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles. The other solutions are permutations of inside tangency and outside tangency.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x-r_2)^2-2(x-r_1)(x-r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7660" PostHistoryTypeId="5" PostId="3711" RevisionGUID="bda56084-0674-40eb-9bac-d55b885c6422" CreationDate="2016-07-02T09:15:04.860" UserId="38" Comment="added 69 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles. The other solutions are permutations of inside tangency and outside tangency.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So for exmple let the cicle be on the inner outside of both circles. Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7661" PostHistoryTypeId="5" PostId="3711" RevisionGUID="4d292b45-0ed1-443d-ba17-c6fa8368a8f2" CreationDate="2016-07-02T09:30:40.617" UserId="38" Comment="added 43 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles. The other solutions are permutations of inside tangency and outside tangency.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So for exmple let the cicle be on the inner outside of both circles (the sign changes for the other solutions). Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7662" PostHistoryTypeId="5" PostId="3711" RevisionGUID="b8e868de-008f-40b6-bfe3-232dfee2b57f" CreationDate="2016-07-02T10:43:17.647" UserId="38" Comment="added 93 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles.  The other solutions are permutations of inside tangency and outside tangency. In addition there is 4 other possible solutions with center on the line connecting centers.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: All possible soliutions&#xD;&#xA;&#xD;&#xA;Solving the triangles&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So for exmple let the cicle be on the inner outside of both circles (the sign changes for the other solutions). Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j3QJo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7663" PostHistoryTypeId="5" PostId="3711" RevisionGUID="609d5001-f4d8-4779-a3d9-89a41e61dda2" CreationDate="2016-07-02T10:54:10.593" UserId="38" Comment="added 147 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles.  The other solutions are permutations of inside tangency and outside tangency. In addition there is 4 other possible solutions with center on the line connecting centers.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: All possible solutions&#xD;&#xA;&#xD;&#xA;From the sheer number of solutions available we can conclude that knowing which quadrant the solution is in is not enough for a good formulation&#xD;&#xA;&#xD;&#xA;Solving the triangles&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So for exmple let the cicle be on the inner outside of both circles (the sign changes for the other solutions). Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IDU3w.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7664" PostHistoryTypeId="2" PostId="3712" RevisionGUID="3fc7b3f0-7447-4052-96d4-9433eccd0d19" CreationDate="2016-07-02T10:59:43.413" UserId="1636" Text="Curves fairness is a strange problem in Computer Aided Geometric Design and every author gives his personal definition.&#xD;&#xA;One of the simplest is the following:&#xD;&#xA;&#xD;&#xA;A curve is said to be fair if&#xD;&#xA;(1) it is G2 continuous,&#xD;&#xA;(2) it has no undesirable inflection points, and&#xD;&#xA;(3) its curvature varies in an even way.&#xD;&#xA;&#xD;&#xA;Yes, but why is a curve with these properties fair ? It is only a definition and I can define what I want. I need a theorem to state something in mathematics.&#xD;&#xA;Where are theorems about fairness ?&#xD;&#xA;The problem is that in mathematics I can speak about sets,functions and other mathematical objects, but not about fairness.&#xD;&#xA;&#xD;&#xA;How can you solve this problem ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7665" PostHistoryTypeId="1" PostId="3712" RevisionGUID="3fc7b3f0-7447-4052-96d4-9433eccd0d19" CreationDate="2016-07-02T10:59:43.413" UserId="1636" Text="Curves fairness" ContentLicense="CC BY-SA 3.0" />
  <row Id="7666" PostHistoryTypeId="3" PostId="3712" RevisionGUID="3fc7b3f0-7447-4052-96d4-9433eccd0d19" CreationDate="2016-07-02T10:59:43.413" UserId="1636" Text="|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7667" PostHistoryTypeId="8" PostId="3711" RevisionGUID="28c32b71-f006-4bfa-b30d-f95685590148" CreationDate="2016-07-02T16:28:25.360" UserId="38" Comment="Rollback to [b8e868de-008f-40b6-bfe3-232dfee2b57f]" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connect s the centers of your original circles.  The other solutions are permutations of inside tangency and outside tangency. In addition there is 4 other possible solutions with center on the line connecting centers.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: All possible soliutions&#xD;&#xA;&#xD;&#xA;Solving the triangles&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So for exmple let the cicle be on the inner outside of both circles (the sign changes for the other solutions). Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j3QJo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7668" PostHistoryTypeId="5" PostId="3711" RevisionGUID="fed28b2e-2f60-45b9-9245-85459b80a78b" CreationDate="2016-07-02T16:37:48.653" UserId="38" Comment="deleted 10 characters in body" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirrors solutions across the line that connects the centers of your original circles.  The other solutions are permutations of inside tangent and outside tangent connections. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: All possible solutions&#xD;&#xA;&#xD;&#xA;So knowing the quadrant is hardly enough for the choice of solution.&#xD;&#xA;&#xD;&#xA;Solving the triangles&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So for exmple let the cicle be on the inner outside of both circles (the sign changes for the other solutions). Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra systems and gives 2 solutions with numerous corner constraints (do it yourself its important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. Thin can be done in many ways but i would proceef by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use a an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6XSpu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7669" PostHistoryTypeId="5" PostId="3711" RevisionGUID="c0f9c96f-d86c-46b3-963d-bafef5c2d8c1" CreationDate="2016-07-02T17:46:29.030" UserId="231" Comment="Minor typos" Text="First let us solve the radius of your circle. You can see that the centers of the circles form a triangle. There are 8 possible triangles, of which 4 are mirror solutions across the line that connects the centers of your original circles.  The other solutions are permutations of inside tangent and outside tangent connections. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: All possible solutions&#xD;&#xA;&#xD;&#xA;So knowing the quadrant is hardly enough for the choice of solution.&#xD;&#xA;&#xD;&#xA;Solving the triangles&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So for eaxmple let the circle be on the inner outside of both circles (the sign changes for the other solutions). Now you need to solve the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA; D^2=(x+r_1)^2+(x+r_2)^2-2(x+r_1)(x+r_2)\cos(\beta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now this can be solved in a computer algebra system and gives 2 solutions with numerous corner constraints (do it yourself it's important for robust code and obviously you need 4 solutions to check.)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x=\frac{1}{2} \left(\pm\sqrt{\frac{\cos (\beta) (r_1-r_2)^2-2 D^2+(r_1-r_2)^2}{\cos (\beta)-1}}-r_1-r_2\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Once you have x solved you can solve the center. This can be done in many ways but I would proceed by solving angle $\alpha$ and some vector rotation, normalization and scalar multiplication. Same calculation can be used to find the intersection point and the tangent is just this vector rotated by 90 degrees.&#xD;&#xA;&#xD;&#xA;You could also use an alternate formulation with 2 angles and a vector sum of $a+b-c=0$, with 2 unknowns and 2 equations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6XSpu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/S8qfp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7670" PostHistoryTypeId="2" PostId="3713" RevisionGUID="4ada3263-4bd7-4dea-8d7f-32f9fd58c296" CreationDate="2016-07-02T17:48:29.317" UserId="2308" Text="I am trying to get [this shader][1] to run on a really old iDevice, as well as eventually androids.&#xD;&#xA;&#xD;&#xA;Even when I reduce the code down to 2 sine functions per fragment the shader runs at about 20fps.&#xD;&#xA;&#xD;&#xA;I have considered taking a leaf out of the book of old shading techniques and creating an array that holds a bunch of predefined trig values and somehow using those to approximate the shader.&#xD;&#xA;&#xD;&#xA;In the shader I linked above I am already simulating that by rounding the values sent to the trig funcion the further left the mouse (while down) goes the less quality of the shader. Its actually pretty cool because really close to the left side it looks like a completly differnt and pretty cool shader.&#xD;&#xA;&#xD;&#xA;Anyway I have two delimas:&#xD;&#xA;&#xD;&#xA;1. I dont know what the most efficent way to have an array of like 360 values in it in a glsl shader, constant or uniform?&#xD;&#xA;2. I cant figure out how to put a number in a range like usually if I wanted an angle between 0 and 360 (yes I know gpu's use radians) I would do it like so.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        func range(float angle)&#xD;&#xA;        {&#xD;&#xA;           float temp = angle&#xD;&#xA;           while (temp &gt; 360) {temp -= 360;}&#xD;&#xA;           while (temp &lt; 0)   {temp += 360;}&#xD;&#xA;           return temp;&#xD;&#xA;        }&#xD;&#xA;However glsl does not allow while loops or recursive functions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/lsKSDt" ContentLicense="CC BY-SA 3.0" />
  <row Id="7671" PostHistoryTypeId="1" PostId="3713" RevisionGUID="4ada3263-4bd7-4dea-8d7f-32f9fd58c296" CreationDate="2016-07-02T17:48:29.317" UserId="2308" Text="Using a LUT to speed up a trig heavy shader for mobile devices" ContentLicense="CC BY-SA 3.0" />
  <row Id="7672" PostHistoryTypeId="3" PostId="3713" RevisionGUID="4ada3263-4bd7-4dea-8d7f-32f9fd58c296" CreationDate="2016-07-02T17:48:29.317" UserId="2308" Text="|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7673" PostHistoryTypeId="5" PostId="3709" RevisionGUID="8b5bc324-33fd-4139-b6f4-cdcf219bc84b" CreationDate="2016-07-02T17:48:44.337" UserId="231" Comment="Remove intro now that this question is clearly welcome here" Text="I have two circles, that I know are both tangential to a third (unknown) circle. I also know what quadrants of the circles the tangential points are in. It is as pictured below. I also know the arc angle that the third circle spans between the two tangential points (beta).&#xD;&#xA;&#xD;&#xA;Would like to know the location of the two tangential points, as well as one of the tangential directions, so I can draw the unknown (red) circle.&#xD;&#xA;&#xD;&#xA;I currently have a working solution for this involving a nonlinear equation solver. If at all possible I would like to have a solution that involves no non-linear equation solving, because I need to run very many of these problems and I need precise results.&#xD;&#xA;&#xD;&#xA;[![Arrangement of the circles][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/anI6om.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7674" PostHistoryTypeId="5" PostId="1674" RevisionGUID="9a352519-ff96-499d-bf59-458c0b86858a" CreationDate="2016-07-02T17:58:08.067" UserId="38" Comment="added 1 character in body" Text="* G0 Continuity means that the separate surfaces meet,&#xD;&#xA;* G1 Continuity that the surfaces meet at same angle,&#xD;&#xA;* G2 Continuity means that the change in angle matches in point of contact.&#xD;&#xA;&#xD;&#xA;The G2 requirement does not mean that the surface is good quality. Just means that without this the surface is not going to have a continuous reflection flow so humans can see the difference. That may or may not be a good thing depends on what you want.&#xD;&#xA;&#xD;&#xA;Mathematically the surface normal is:&#xD;&#xA;&#xD;&#xA;$f(u,v) \frac{\partial}{\partial u} \times f(u,v) \frac{\partial}{\partial v}$&#xD;&#xA;&#xD;&#xA;Since both sides are derived that means that the function field of the surface normal has one degree less than the original surface. So for the reflection to be first degree continuous it has to have a second degree continuity.&#xD;&#xA;&#xD;&#xA;So far we have established the relationship between the continuity of the surface and the continuity of the reflection. Nothing thus far proves that the surface reflection needs to be first degree continuous. To understand why we must exit the realm of mathematics and enter the realm of biology.&#xD;&#xA;&#xD;&#xA;They eye is equipped with a edge detection algorithm on a structural level right on the retina. This edge detection algorithm in essence works as a discrete derivative of the input signal. So, if your surface is not G2 continuous then the human edge detection kicks in and shows itself up. For references read on [Mach Bands](https://en.wikipedia.org/wiki/Mach_bands) and so forth.&#xD;&#xA;&#xD;&#xA;Since the edge detection is discrete G2 continuity is not enough. The change has to not only be locally satisfied but also satisfied on the retina. So the change should still be shallow enough not to cause problems." ContentLicense="CC BY-SA 3.0" />
  <row Id="7675" PostHistoryTypeId="2" PostId="3714" RevisionGUID="7cb6b375-1ee1-4aae-bdc6-db9233f9c361" CreationDate="2016-07-02T21:12:19.577" UserId="116" Text="After checking and rechecking my code over and over again. I finally made it work.&#xD;&#xA;The problem was that I was creating the buffers and assigning locations to the position and the normals buffers&#xD;&#xA;&#xD;&#xA;    // Positions&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;    // Normals&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;&#xD;&#xA;However in the vertex shader I was not setting the locations&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    &#xD;&#xA;    in vec4 vposition;&#xD;&#xA;    in vec3 vnormal;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;So changing the previous code to&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec4 vposition;&#xD;&#xA;    layout(location = 1) in vec3 vnormal;&#xD;&#xA;&#xD;&#xA;fixed the application.&#xD;&#xA;Now, I am not really sure why this works, but I remember reading somewhere that OpenGL assigns locations as it sees best, so maybe in my code the location for the normal was not the same as the enabled vertex attrib array. I let someone more experienced clarify this." ContentLicense="CC BY-SA 3.0" />
  <row Id="7676" PostHistoryTypeId="5" PostId="1674" RevisionGUID="4715b852-2e74-4374-98ed-ada6385c5e2c" CreationDate="2016-07-03T00:12:28.800" UserId="231" Comment="Minor typos" Text="* G0 Continuity means that the separate surfaces meet,&#xD;&#xA;* G1 Continuity that the surfaces meet at same angle,&#xD;&#xA;* G2 Continuity means that the change in angle matches in point of contact.&#xD;&#xA;&#xD;&#xA;The G2 requirement does not mean that the surface is good quality. Just means that without this the surface is not going to have a continuous reflection flow so humans can see the difference. That may or may not be a good thing depends on what you want.&#xD;&#xA;&#xD;&#xA;Mathematically the surface normal is:&#xD;&#xA;&#xD;&#xA;$f(u,v) \frac{\partial}{\partial u} \times f(u,v) \frac{\partial}{\partial v}$&#xD;&#xA;&#xD;&#xA;Since both sides are derived that means that the function field of the surface normal has one degree less than the original surface. So for the reflection to be first degree continuous it has to have a second degree continuity.&#xD;&#xA;&#xD;&#xA;So far we have established the relationship between the continuity of the surface and the continuity of the reflection. Nothing thus far proves that the surface reflection needs to be first degree continuous. To understand why we must exit the realm of mathematics and enter the realm of biology.&#xD;&#xA;&#xD;&#xA;The eye is equipped with an edge detection algorithm on a structural level right on the retina. This edge detection algorithm in essence works as a discrete derivative of the input signal. So, if your surface is not G2 continuous then the human edge detection kicks in and shows itself up. For references read on [Mach Bands](https://en.wikipedia.org/wiki/Mach_bands) and so forth.&#xD;&#xA;&#xD;&#xA;Since the edge detection is discrete G2 continuity is not enough. The change has to not only be locally satisfied but also satisfied on the retina. So the change should still be shallow enough not to cause problems." ContentLicense="CC BY-SA 3.0" />
  <row Id="7678" PostHistoryTypeId="2" PostId="3715" RevisionGUID="02c33cd1-181e-4045-83a0-935a50825133" CreationDate="2016-07-03T01:28:41.097" UserId="48" Text="Yes, your theory is correct. A gamma-correct blur entails converting the input pixels to linear color space, performing the blur weighting and accumulation in that space, and then converting back to gamma space at the end.&#xD;&#xA;&#xD;&#xA;As noted in the comments, the actual transform is not literally squaring and square-rooting, that's just an approximation (and not that good of one). For the true sRGB gamma transform, see the equations in [this Wikipedia article](https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation) (look down the page for the equations involving $C_\text{srgb}$ and $C_\text{linear}$).&#xD;&#xA;&#xD;&#xA;By the way, some visual comparisons of gamma-correct and gamma-incorrect blurs can be found on [this page by Elle Stone](http://ninedegreesbelow.com/photography/linear-gamma-blur-normal-blend.html#100), which shows why this whole thing matters." ContentLicense="CC BY-SA 3.0" />
  <row Id="7679" PostHistoryTypeId="2" PostId="3716" RevisionGUID="3e478609-3e23-498d-a7d9-74a69e553a77" CreationDate="2016-07-03T02:55:52.373" UserId="4685" Text="SceneKit, as of iOS 9/OS X El Capitan, can handle all of the suggested lighting changes from @trichoplax. The newly announced (June 2016) Physically Based Rendering (PBR), and support for Pixar's Universal Scene Description, make some stunningly beautiful images, if you can required iOS 10 (hint: you should). &#xD;&#xA;&#xD;&#xA;SceneKit is using Metal or OpenGL (your choice) as the renderer. What SceneKit gets you is a higher level of abstraction. I think that's a good approach for the problem you're trying to solve.&#xD;&#xA;&#xD;&#xA;I particularly recommend the videos of the SceneKit presentations at WWDC 2014, 2015, and 2016. The What's New presentation for 2014 was written in SceneKit, and is available as sample code. I haven't seen 2016's code yet but it's been promised. Also take a look at the ModelIO framework, which is designed for loading various standard 3d, texture, and lighting formats and making them available for SceneKit, Metal, and OpenGL.&#xD;&#xA;&#xD;&#xA;David Rönnqvist's SceneKit book (on iBook Store) steps through the different texture, material, and lighting controls. It's a bit outdated now because of the PBR and ModelIO enhancements, but it's valuable in learning how to manipulate the scene.&#xD;&#xA;&#xD;&#xA;I think ultimately you're going to need to develop some intermediate level skill with a 3D modeling tool like Maya, Blender, or Cheetah3D, if only to understand the common challenges and paradigms for 3D rendering." ContentLicense="CC BY-SA 3.0" />
  <row Id="7681" PostHistoryTypeId="2" PostId="3717" RevisionGUID="b2a10e23-2354-48d8-b574-8febf658b8c6" CreationDate="2016-07-03T12:34:20.267" UserId="4687" Text="Orthogonal Layout Algorithm&#xD;&#xA;&#xD;&#xA;**HOLA**&#xD;&#xA;&#xD;&#xA;Human-like Orthogonal Layout Algorithm&#xD;&#xA;&#xD;&#xA;[https://vimeo.com/150509722][1]&#xD;&#xA;&#xD;&#xA;Kieffer, Steve, Tim Dwyer, Kim Marriott, and Michael Wybrow. &quot;Hola: Human-like orthogonal network layout.&quot; Visualization and Computer Graphics, IEEE Transactions on 22, no. 1 (2016): 349-358.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vimeo.com/150509722" ContentLicense="CC BY-SA 3.0" />
  <row Id="7682" PostHistoryTypeId="6" PostId="3709" RevisionGUID="0f4843bb-ec7d-42e6-b738-872452a46d9e" CreationDate="2016-07-03T13:54:49.483" UserId="38" Comment="edited tags" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7683" PostHistoryTypeId="5" PostId="3709" RevisionGUID="ddc71b24-d5a4-47f5-9edc-f218c577367b" CreationDate="2016-07-03T18:02:00.380" UserId="4620" Comment="added 2 characters in body" Text="I have two circles, that I know are both tangential to a third (unknown) circle. I also know what quadrants of the circles the tangential points are in. It is as pictured below. I also know the arc angle that the third circle spans between the two tangential points (beta).&#xD;&#xA;&#xD;&#xA;I would like to know the location of the two tangential points, as well as one of the tangential directions, so I can draw the unknown (red) circle.&#xD;&#xA;&#xD;&#xA;I currently have a working solution for this involving a nonlinear equation solver. If at all possible I would like to have a solution that involves no non-linear equation solving, because I need to run very many of these problems and I need precise results.&#xD;&#xA;&#xD;&#xA;[![Arrangement of the circles][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/anI6om.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7685" PostHistoryTypeId="2" PostId="3718" RevisionGUID="6da914d8-85fd-4d9f-81d8-21340d0db022" CreationDate="2016-07-03T23:42:12.383" UserId="48" Text="## Sigma and kernel size of Gaussian filter ##&#xD;&#xA;&#xD;&#xA;Regarding how to choose the sigma and the kernel size (pixels) of the Gaussian: you set the sigma based on how wide of a blur you want (judging it visually) and then choose the kernel size based on the sigma. It's a game of finding a kernel size that captures enough of the (mathematically infinite) bell curve to look good, while not being too expensive.&#xD;&#xA;&#xD;&#xA;As a rule of thumb, the kernel size should be at least 6 times the sigma. Then the kernel extends out to 3 sigmas in each direction, which is enough to [cover almost all the weight](https://en.wikipedia.org/wiki/Normal_distribution#/media/File:Empirical_Rule.PNG) of the mathematical bell curve. It's also nice to round up the pixel size to the next odd number so the filter will be symmetrical. So for example, with sigma = 1.5 px, you'd use a 9-pixel filter; with sigma = 2.0 px, use a 13-pixel filter, etc.&#xD;&#xA;&#xD;&#xA;Alternatively, if you have performance limitations that control how big a kernel size you can use, then divide by 6 to get the maximum sigma you can get away with. (Note that sigma can be fractional, as it's just an input to the bell curve equation.)&#xD;&#xA;&#xD;&#xA;By the way, a trick to get better performance on large Gaussian blurs is to downsample the image, perform a smaller blur, then upsample. For instance, to get an effective 13-pixel blur, you could downsample the image by 2x (using bilinear filtering), then perform a 7-pixel blur, and then upsample (using bilinear filtering). It will look almost as good as the 13-pixel blur, but will be considerably faster.&#xD;&#xA;&#xD;&#xA;## Creating a good-looking glow filter ##&#xD;&#xA;&#xD;&#xA;A common trick with these is to use multiple Gaussians of different radius, added together. It makes a better glow effect than any single Gaussian by itself. For example, here's a mockup in Photoshop created with three layers additively blended together. The three Gaussians are of size 3px, 5px and 11px (corresponding to sigma = 0.5px, 2.5px, 5.5px respectively).&#xD;&#xA;&#xD;&#xA;[![mocked-up bloom filter][1]][1]&#xD;&#xA;&#xD;&#xA;You can also add even larger Gaussians to further increase the apparent radius of the glow. This is how the standard &quot;bloom&quot; effect is implemented in 3D game engines.&#xD;&#xA;&#xD;&#xA;If performance is a concern, the smallest Gaussian can be replaced by a copy of the unblurred original image; the resulting effect will look sharper, not so soft, but will still have a glow surrounding it. As mentioned previously, larger Gaussians can be done by downsampling, blurring, and upsampling; and the upsampling can be done using hardware bilinear filtering, folded into the pass that blends the layers together.&#xD;&#xA;&#xD;&#xA;## Jaggies ##&#xD;&#xA;&#xD;&#xA;You'll notice that jaggies are still visible in some areas of the above image. Unfortunately, blurring is not very effective at hiding jaggies unless the blur radius is quite large. There's no easy way to use a post-process get rid of jaggies: the best way to avoid them is not to render them in the first place. :)&#xD;&#xA;&#xD;&#xA;I hear you that you can't use MSAA for performance reasons, but may be another option.  Depending on how you render the glow trails, you might be able to slightly increase their size, and write a shader that applies a gradient to fade out the color within a couple pixels of the edge. That should help them look smoother. [Here's a shadertoy](https://www.shadertoy.com/view/MdtXWX) that demonstrates a 1px-wide edge falloff used for antialiasing a procedural shape.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9QCiw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7686" PostHistoryTypeId="5" PostId="3718" RevisionGUID="0de0c100-a685-42d0-a4c6-1246026b1798" CreationDate="2016-07-04T00:34:46.920" UserId="48" Comment="added 2 characters in body" Text="## Sigma and kernel size of Gaussian filter ##&#xD;&#xA;&#xD;&#xA;Regarding how to choose the sigma and the kernel size (pixels) of the Gaussian: you set the sigma based on how wide of a blur you want (judging it visually) and then choose the kernel size based on the sigma. It's a game of finding a kernel size that captures enough of the (mathematically infinite) bell curve to look good, while not being too expensive.&#xD;&#xA;&#xD;&#xA;As a rule of thumb, the kernel size should be at least 6 times the sigma. Then the kernel extends out to 3 sigmas in each direction, which is enough to [cover almost all the weight](https://en.wikipedia.org/wiki/Normal_distribution#/media/File:Empirical_Rule.PNG) of the mathematical bell curve. It's also nice to round up the pixel size to the next odd number so the filter will be symmetrical. So for example, with sigma = 1.5 px, you'd use a 9-pixel filter; with sigma = 2.0 px, use a 13-pixel filter, etc.&#xD;&#xA;&#xD;&#xA;Alternatively, if you have performance limitations that control how big a kernel size you can use, then divide by 6 to get the maximum sigma you can get away with. (Note that sigma can be fractional, as it's just an input to the bell curve equation.)&#xD;&#xA;&#xD;&#xA;By the way, a trick to get better performance on large Gaussian blurs is to downsample the image, perform a smaller blur, then upsample. For instance, to get an effective 13-pixel blur, you could downsample the image by 2x (using bilinear filtering), then perform a 7-pixel blur, and then upsample (using bilinear filtering). It will look almost as good as the 13-pixel blur, but will be considerably faster.&#xD;&#xA;&#xD;&#xA;## Creating a good-looking glow filter ##&#xD;&#xA;&#xD;&#xA;A common trick with these is to use multiple Gaussians of different radius, added together. It makes a better glow effect than any single Gaussian by itself. For example, here's a mockup in Photoshop created with three layers additively blended together. The three Gaussians are of size 3px, 5px and 11px (corresponding to sigma = 0.5px, 0.83px, 1.83px respectively).&#xD;&#xA;&#xD;&#xA;[![mocked-up bloom filter][1]][1]&#xD;&#xA;&#xD;&#xA;You can also add even larger Gaussians to further increase the apparent radius of the glow. This is how the standard &quot;bloom&quot; effect is implemented in 3D game engines.&#xD;&#xA;&#xD;&#xA;If performance is a concern, the smallest Gaussian can be replaced by a copy of the unblurred original image; the resulting effect will look sharper, not so soft, but will still have a glow surrounding it. As mentioned previously, larger Gaussians can be done by downsampling, blurring, and upsampling; and the upsampling can be done using hardware bilinear filtering, folded into the pass that blends the layers together.&#xD;&#xA;&#xD;&#xA;## Jaggies ##&#xD;&#xA;&#xD;&#xA;You'll notice that jaggies are still visible in some areas of the above image. Unfortunately, blurring is not very effective at hiding jaggies unless the blur radius is quite large. There's no easy way to use a post-process get rid of jaggies: the best way to avoid them is not to render them in the first place. :)&#xD;&#xA;&#xD;&#xA;I hear you that you can't use MSAA for performance reasons, but may be another option.  Depending on how you render the glow trails, you might be able to slightly increase their size, and write a shader that applies a gradient to fade out the color within a couple pixels of the edge. That should help them look smoother. [Here's a shadertoy](https://www.shadertoy.com/view/MdtXWX) that demonstrates a 1px-wide edge falloff used for antialiasing a procedural shape.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9QCiw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7687" PostHistoryTypeId="5" PostId="3716" RevisionGUID="ae47bc9d-b3fa-4dda-8109-270e780455f2" CreationDate="2016-07-04T02:25:54.090" UserId="4685" Comment="Cite another book" Text="SceneKit, as of iOS 9/OS X El Capitan, can handle all of the suggested lighting changes from @trichoplax. The newly announced (June 2016) Physically Based Rendering (PBR), and support for Pixar's Universal Scene Description, make some stunningly beautiful images, if you can required iOS 10 (hint: you should). &#xD;&#xA;&#xD;&#xA;SceneKit is using Metal or OpenGL (your choice) as the renderer. What SceneKit gets you is a higher level of abstraction. I think that's a good approach for the problem you're trying to solve.&#xD;&#xA;&#xD;&#xA;I particularly recommend the videos of the SceneKit presentations at WWDC 2014, 2015, and 2016. The What's New presentation for 2014 was written in SceneKit, and is available as sample code. I haven't seen 2016's code yet but it's been promised. Also take a look at the ModelIO framework, which is designed for loading various standard 3d, texture, and lighting formats and making them available for SceneKit, Metal, and OpenGL.&#xD;&#xA;&#xD;&#xA;David Rönnqvist's SceneKit book (on iBook Store) steps through the different texture, material, and lighting controls. It's a bit outdated now because of the PBR and ModelIO enhancements, but it's valuable in learning how to manipulate the scene.&#xD;&#xA;&#xD;&#xA;Chris Language's book &quot;3D iOS Games by Tutorials&quot; has two sections worth looking at. Section II is, as far as I know, the only written documentation on using the Xcode Scene Editor. In the process, he covers the fundamentals of lighting and materials. Section III goes into more details on lighting and shadows. The book is pretty good at making render-related terminology and concepts accessible. I'm not a fan of its jumbling of view controllers and game logic, though.&#xD;&#xA;&#xD;&#xA;I think ultimately you're going to need to develop some intermediate level skill with a 3D modeling tool like Maya, Blender, or Cheetah3D, if only to understand the common challenges and paradigms for 3D rendering." ContentLicense="CC BY-SA 3.0" />
  <row Id="7688" PostHistoryTypeId="5" PostId="3716" RevisionGUID="6da22c89-0039-4b63-8e20-268ab17261ca" CreationDate="2016-07-04T02:31:44.013" UserId="4685" Comment="add links" Text="SceneKit, as of iOS 9/OS X El Capitan, can handle all of the suggested lighting changes from @trichoplax. The newly announced (June 2016) Physically Based Rendering (PBR), and support for Pixar's Universal Scene Description, make some stunningly beautiful images, if you can required iOS 10 (hint: you should). &#xD;&#xA;&#xD;&#xA;SceneKit is using Metal or OpenGL (your choice) as the renderer. What SceneKit gets you is a higher level of abstraction. I think that's a good approach for the problem you're trying to solve.&#xD;&#xA;&#xD;&#xA;I particularly recommend the videos of the SceneKit presentations at WWDC 2014, 2015, and 2016. The What's New presentation for 2014 was written in SceneKit, and is available as sample code. I haven't seen 2016's code yet but it's been promised. Also take a look at the ModelIO framework, which is designed for loading various standard 3d, texture, and lighting formats and making them available for SceneKit, Metal, and OpenGL.&#xD;&#xA;&#xD;&#xA;David Rönnqvist's SceneKit book ([on iBook Store][1]) steps through the different texture, material, and lighting controls. It's a bit outdated now because of the PBR and ModelIO enhancements, but it's valuable in learning how to manipulate the scene.&#xD;&#xA;&#xD;&#xA;Chris Language's book [3D iOS Games by Tutorials][2] has two sections you should work through. Section II is, as far as I know, the only written documentation on using the Xcode Scene Editor. In the process, he covers the fundamentals of lighting and materials. Section III goes into more details on lighting and shadows. The book is pretty good at making render-related terminology and concepts accessible. I'm not a fan of its jumbling of view controllers and game logic, though.&#xD;&#xA;&#xD;&#xA;I think ultimately you're going to need to develop some intermediate level skill with a 3D modeling tool like Maya, Blender, or Cheetah3D, if only to understand the common challenges and paradigms for 3D rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://itunes.apple.com/us/book/3d-graphics-with-scene-kit/&#xD;&#xA;  [2]: https://www.raywenderlich.com/store/3d-ios-games-by-tutorials" ContentLicense="CC BY-SA 3.0" />
  <row Id="7690" PostHistoryTypeId="5" PostId="3671" RevisionGUID="c7b0613a-dcf8-413c-bb55-09f24e492337" CreationDate="2016-07-04T07:37:50.087" UserId="4638" Comment="added 140 characters in body" Text="Inspired by Minecraft and LEGOs, we created an app to promote creativity on smartphones. Many people like being creative but find a blank canvas daunting. &quot;Recipes&quot; inside the app let users create like the most talented individuals -- similar to how a cooking recipe lets anyone cook like Thomas Keller.&#xD;&#xA;&#xD;&#xA;The problem so far is users say the app doesn't look &quot;3D&quot; enough.&#xD;&#xA;&#xD;&#xA;Here's the relevant code that creates the scene and creates blocks: https://gist.github.com/panabee/dca88a591f94a3904023dacabd020ad9.&#xD;&#xA;&#xD;&#xA;What they mean is they expect the app to look more like apps like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;With encouragement from one of the admins, these screenshots from our app illustrate the disparity in &quot;3Dness&quot;:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;We're using SceneKit on iOS, but are having trouble identifying what is needed to make the app look more like the images above. We played with lighting and textures, but are new to 3D graphics as well as SceneKit and are unsure what to do.&#xD;&#xA;&#xD;&#xA;We have tried to find consultants on StackOverflow, LinkedIn, Github, but this expertise appears not so common.&#xD;&#xA;&#xD;&#xA;A few questions:&#xD;&#xA;&#xD;&#xA;1) For iOS, is SceneKit capable of producing the images above, or do we need to use something like Metal?&#xD;&#xA;&#xD;&#xA;2) If SceneKit is capable, what are the key concepts to learn?&#xD;&#xA;&#xD;&#xA;3) (Happy to strike this question if it's considered off-topic) Which websites/forums could we find people to help provide advice if we get stuck?&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4Kh0S.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LMePj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/mGfva.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/ntHkQ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/dodAZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7696" PostHistoryTypeId="5" PostId="3717" RevisionGUID="bf54ea4e-d341-41a6-9407-9a5c9e7af1c6" CreationDate="2016-07-04T17:26:56.427" UserId="4687" Comment="merged answeres" Text="**libCola**&#xD;&#xA;&#xD;&#xA;cola.js (a.k.a. WebCola) is a JavaScript based rewrite of libcola which works well with D3.js&#xD;&#xA;&#xD;&#xA;http://marvl.infotech.monash.edu/webcola/&#xD;&#xA;&#xD;&#xA;Gridified Layout example:&#xD;&#xA; &#xD;&#xA;http://marvl.infotech.monash.edu/webcola/examples/dotpowergraph.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**OGDF**&#xD;&#xA;&#xD;&#xA;Open Graph Drawing Framework&#xD;&#xA;&#xD;&#xA;Have an orthogonal layout&#xD;&#xA;&#xD;&#xA;&gt; Orthogonal: Ortholayout with modules for the steps of shape and&#xD;&#xA;&gt; compaction, ClusterOrthoLayout&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;http://www.ogdf.net/doku.php/ogdf:features&#xD;&#xA;&#xD;&#xA;Check projects that uses OGDF&#xD;&#xA;&#xD;&#xA;http://www.ogdf.net/doku.php/project:external&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**HOLA**&#xD;&#xA;&#xD;&#xA;Human-like Orthogonal Layout Algorithm&#xD;&#xA;&#xD;&#xA;[https://vimeo.com/150509722][1]&#xD;&#xA;&#xD;&#xA;Kieffer, Steve, Tim Dwyer, Kim Marriott, and Michael Wybrow. &quot;Hola: Human-like orthogonal network layout.&quot; Visualization and Computer Graphics, IEEE Transactions on 22, no. 1 (2016): 349-358.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vimeo.com/150509722" ContentLicense="CC BY-SA 3.0" />
  <row Id="7698" PostHistoryTypeId="2" PostId="3721" RevisionGUID="2e903257-2392-43a0-9216-30069df8301e" CreationDate="2016-07-04T18:23:56.550" UserId="273" Text="I try to write a simple triangle mesh renderer with OpenGL.&#xD;&#xA;&#xD;&#xA;    void ShaderProgram::SetUniformMatrix4(std::string name, glm::mat4 matrix)&#xD;&#xA;    {&#xD;&#xA;      GLint location = glGetUniformLocation(program_, name.c_str());&#xD;&#xA;&#xD;&#xA;      if (location != -1)&#xD;&#xA;      {&#xD;&#xA;         glUniformMatrix4fv(location, 1, GL_FALSE, &amp;matrix[0][0]);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is my uniform related code. I made sure that _glUseProgram(program\_)_ is called before this method is executed.&#xD;&#xA;Also the _glm::mat4_ does indeed contain the correct values and _program\__ has a value of 3 so it seems vaid.&#xD;&#xA;The location comes out as a 0 &#xD;&#xA;&#xD;&#xA;here how I call that method:&#xD;&#xA;&#xD;&#xA;    shader_-&gt;BindProgram();&#xD;&#xA;    shader_-&gt;SetUniformMatrix4(&quot;matModel&quot;, transformation);&#xD;&#xA;  &#xD;&#xA;    texture_-&gt;BindTexture();&#xD;&#xA;    mesh_-&gt;Draw();&#xD;&#xA;    texture_-&gt;FreeTexture();&#xD;&#xA;&#xD;&#xA;    shader_-&gt;FreeProgram();&#xD;&#xA;&#xD;&#xA;Now I have following simple Vertex Shader &#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertexPosition_modelspace;&#xD;&#xA;    layout (location = 1) in vec3 vertexNormal_modelspace;&#xD;&#xA;    layout (location = 2) in vec2 textureCoords_modelspace;&#xD;&#xA;&#xD;&#xA;    uniform mat4 matModel;&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform Camera{&#xD;&#xA;      mat4 matView;&#xD;&#xA;      mat4 matProjection;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    out vec2 textureCoords;&#xD;&#xA;&#xD;&#xA;    void main(){    &#xD;&#xA;      textureCoords = textureCoords_modelspace;&#xD;&#xA;      gl_Position =  matProjection * matView * matModel * vec4(vertexPosition_modelspace, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I see nothing on the screen which is the main error.&#xD;&#xA;When Debugging with Nvidia-NSight I find that all values except the _matModel_ are correctly set. The _matModel_ contains all zero which seems to be why the model isn't drawn.&#xD;&#xA;&#xD;&#xA;Why is the _matModel_ always zero, even when I try to set the uniform?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7699" PostHistoryTypeId="1" PostId="3721" RevisionGUID="2e903257-2392-43a0-9216-30069df8301e" CreationDate="2016-07-04T18:23:56.550" UserId="273" Text="Uniform not set, despite valid location" ContentLicense="CC BY-SA 3.0" />
  <row Id="7700" PostHistoryTypeId="3" PostId="3721" RevisionGUID="2e903257-2392-43a0-9216-30069df8301e" CreationDate="2016-07-04T18:23:56.550" UserId="273" Text="|opengl|shader|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7701" PostHistoryTypeId="2" PostId="3722" RevisionGUID="dae91913-9398-4023-881d-d59022c5f112" CreationDate="2016-07-04T22:32:49.957" UserId="273" Text="It seems that nothing was wrong with the code I posted.&#xD;&#xA;I deleted my complete build and rebuild it, and now it seems to work.&#xD;&#xA;I don't see anything on screen but i think that error is unrelated.&#xD;&#xA;&#xD;&#xA;I can see the matrix in the nsight debugger." ContentLicense="CC BY-SA 3.0" />
  <row Id="7703" PostHistoryTypeId="2" PostId="3723" RevisionGUID="d8106879-b77c-4154-8a81-e64659567be4" CreationDate="2016-07-05T07:00:13.630" UserId="4694" Text="I have a human body 'surface' mesh data.: triangular mesh (vertices, face)&#xD;&#xA;&#xD;&#xA;What I want to get from this is 'exact-down-sampled' version of the current mesh.&#xD;&#xA;&#xD;&#xA;Which means.. the processed output mesh should have the vertices that all belong to the input mesh and the mesh data should be in the triangular mesh form..&#xD;&#xA;&#xD;&#xA;I know there are some surface mesh simplification algorithms, such as poisson surface reconstruction algorithm. But as far as I know, they don't preserve the positions of the input mesh.&#xD;&#xA; What I simply want is to down-sample the points and triangulate them.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7704" PostHistoryTypeId="1" PostId="3723" RevisionGUID="d8106879-b77c-4154-8a81-e64659567be4" CreationDate="2016-07-05T07:00:13.630" UserId="4694" Text="exact down sampling and re-triangulation of mesh data(non-convex)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7705" PostHistoryTypeId="3" PostId="3723" RevisionGUID="d8106879-b77c-4154-8a81-e64659567be4" CreationDate="2016-07-05T07:00:13.630" UserId="4694" Text="|algorithm|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7706" PostHistoryTypeId="5" PostId="3721" RevisionGUID="5b407557-235c-47db-a035-9b85f8e17ce9" CreationDate="2016-07-05T09:38:05.610" UserId="231" Comment="Minor typos and apply assumed intended formating (please revert anything that isn't your intention)" Text="I try to write a simple triangle mesh renderer with OpenGL.&#xD;&#xA;&#xD;&#xA;    void ShaderProgram::SetUniformMatrix4(std::string name, glm::mat4 matrix)&#xD;&#xA;    {&#xD;&#xA;      GLint location = glGetUniformLocation(program_, name.c_str());&#xD;&#xA;&#xD;&#xA;      if (location != -1)&#xD;&#xA;      {&#xD;&#xA;         glUniformMatrix4fv(location, 1, GL_FALSE, &amp;matrix[0][0]);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is my uniform related code. I made sure that _glUseProgram(program\_)_ is called before this method is executed.  &#xD;&#xA;Also the _glm::mat4_ does indeed contain the correct values and _program\__ has a value of 3 so it seems valid.  &#xD;&#xA;The location comes out as a 0 &#xD;&#xA;&#xD;&#xA;Here how I call that method:&#xD;&#xA;&#xD;&#xA;    shader_-&gt;BindProgram();&#xD;&#xA;    shader_-&gt;SetUniformMatrix4(&quot;matModel&quot;, transformation);&#xD;&#xA;  &#xD;&#xA;    texture_-&gt;BindTexture();&#xD;&#xA;    mesh_-&gt;Draw();&#xD;&#xA;    texture_-&gt;FreeTexture();&#xD;&#xA;&#xD;&#xA;    shader_-&gt;FreeProgram();&#xD;&#xA;&#xD;&#xA;Now I have following simple Vertex Shader &#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertexPosition_modelspace;&#xD;&#xA;    layout (location = 1) in vec3 vertexNormal_modelspace;&#xD;&#xA;    layout (location = 2) in vec2 textureCoords_modelspace;&#xD;&#xA;&#xD;&#xA;    uniform mat4 matModel;&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform Camera{&#xD;&#xA;      mat4 matView;&#xD;&#xA;      mat4 matProjection;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    out vec2 textureCoords;&#xD;&#xA;&#xD;&#xA;    void main(){    &#xD;&#xA;      textureCoords = textureCoords_modelspace;&#xD;&#xA;      gl_Position =  matProjection * matView * matModel * vec4(vertexPosition_modelspace, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I see nothing on the screen which is the main error.  &#xD;&#xA;When Debugging with Nvidia-NSight I find that all values except the _matModel_ are correctly set. The _matModel_ contains all zero which seems to be why the model isn't drawn.&#xD;&#xA;&#xD;&#xA;Why is the _matModel_ always zero, even when I try to set the uniform?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7708" PostHistoryTypeId="2" PostId="3724" RevisionGUID="ff9467a5-1dac-484d-a4fa-f50ee27605ea" CreationDate="2016-07-06T06:42:32.643" UserId="4702" Text="Given a set of vertices, transforming them to fit onto some spline curve.&#xD;&#xA;For example 3D modelling software has extrude along curve and Unreal Engine has a spline mesh component that takes some mesh and stretches it along a defined curve.&#xD;&#xA;&#xD;&#xA;Is there some branch of mathematics or theory that looks into this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7709" PostHistoryTypeId="1" PostId="3724" RevisionGUID="ff9467a5-1dac-484d-a4fa-f50ee27605ea" CreationDate="2016-07-06T06:42:32.643" UserId="4702" Text="How to deform some mesh so that it fits along a spline curve?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7710" PostHistoryTypeId="3" PostId="3724" RevisionGUID="ff9467a5-1dac-484d-a4fa-f50ee27605ea" CreationDate="2016-07-06T06:42:32.643" UserId="4702" Text="|transformations|computational-geometry|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7712" PostHistoryTypeId="2" PostId="3725" RevisionGUID="98ce8b89-4d29-47e0-82fd-4bd3335fcdf9" CreationDate="2016-07-06T11:25:47.647" UserId="4700" Text="For a project dealing with deep semantic labeling of images I need a format that supports arrays of arbitrary length for each pixel of the image.&#xD;&#xA;&#xD;&#xA;The array is an array of integers. &#xD;&#xA;&#xD;&#xA;Which image formats support this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7713" PostHistoryTypeId="1" PostId="3725" RevisionGUID="98ce8b89-4d29-47e0-82fd-4bd3335fcdf9" CreationDate="2016-07-06T11:25:47.647" UserId="4700" Text="Is there a image-format that support an array per pixel?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7714" PostHistoryTypeId="3" PostId="3725" RevisionGUID="98ce8b89-4d29-47e0-82fd-4bd3335fcdf9" CreationDate="2016-07-06T11:25:47.647" UserId="4700" Text="|raster-image|image|pixels|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7715" PostHistoryTypeId="2" PostId="3726" RevisionGUID="1a3b7101-f300-4754-9769-eae34989cedb" CreationDate="2016-07-06T12:27:06.610" UserId="3123" Text="Probably `.dds`. You can store there textures array or 3d texture both can be use as array per pixel.&#xD;&#xA;You can try creating this textures with `DxTex` from `DirecX SDK`.&#xD;&#xA;Also you can look in `Legacy Texture Tools` from Nvidia&#xD;&#xA;https://developer.nvidia.com/legacy-texture-tools" ContentLicense="CC BY-SA 3.0" />
  <row Id="7716" PostHistoryTypeId="2" PostId="3727" RevisionGUID="aff22182-9aa6-4035-9dfc-00de5824d344" CreationDate="2016-07-06T14:36:15.557" UserId="273" Text="**1. Method: Vertex Clustering**&#xD;&#xA;&#xD;&#xA;This is more or less a low-quality method, but depending on your Mesh it could work well.&#xD;&#xA;The basic idea is to partition the space into a regular grid, and then chose one representative for each cell that holds at least one vertex.&#xD;&#xA;Then calculate the connectivity based on the connectivity of the original vertices.&#xD;&#xA;[![2D Vertex Clustering][1]][1]&#xD;&#xA;&#xD;&#xA;In the image you see a basic 2D clustering. The unreduced mesh left, and the reduced right with the chosen representatives.&#xD;&#xA;As you can see, just chosing an exsting vertex as representative (by closest to mean, or closest to center, or any other idea you can think of) you get a subset of vertices.&#xD;&#xA;&#xD;&#xA;But you also see the problem, thin parts will degenerate and parts that are close to forming a loop will probably get connected. But as already said, it depends on your mesh if this works.&#xD;&#xA;&#xD;&#xA;**2. Method: Incremental Mesh Decimation with with Halfedge Collapse**&#xD;&#xA;&#xD;&#xA;&lt;a href=&quot;https://www.researchgate.net/figure/221129055_fig1_Fig-1-Half-edge-collapse-decimation-operation&quot;&gt;&lt;img src=&quot;https://www.researchgate.net/profile/Khaled_Mamou/publication/221129055/figure/fig1/AS:305611066626062@1449874764141/Fig-1-Half-edge-collapse-decimation-operation.png&quot; alt=&quot;Fig. 1 . Half-edge collapse decimation operation.&amp;nbsp;&quot;&gt;&lt;/a&gt;&#xD;&#xA;&#xD;&#xA;One vertex gets collapsed into his neigbour. Thereby you get again a subsampling.&#xD;&#xA;This is a progressive method. You evaluate which collaps will decrease the quality (for example total distance to the original surface, but many more possible) and collapse it. Then you check if your quality has dropped too much for another collapse, and if so you stop. Otherwise you do it again. Until either the quality drops too much or the target size is reached.&#xD;&#xA;&#xD;&#xA;**Method 3: Progressive Mesh Decimation with Vertex Decimation.**&#xD;&#xA;&#xD;&#xA;The same progressive idea as in method 2, but this time instead of a callapse you just delete a vertex and calculate e new triangulation for the hole that this created.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ijNC6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7721" PostHistoryTypeId="2" PostId="3729" RevisionGUID="720f422a-5bac-45f2-bf48-ebe629845db0" CreationDate="2016-07-06T18:52:44.217" UserId="4708" Text="I have dealt with glsl before, but I still have problems with my understanding of how to achieve certain kinds of effects with per-pixel processing. What I am looking to do is use a fragment shader to emulate ink spreading across paper. There is a random initial &quot;mass&quot; applied to each pixel, and one method I'm considering is having the texture scale outwards with the value of the initial &quot;mass&quot; decreasing until 0.&#xD;&#xA;&#xD;&#xA;What might I be missing in trying to implement this? Does anyone know of a similar shader effect that I could consult while building this?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7722" PostHistoryTypeId="1" PostId="3729" RevisionGUID="720f422a-5bac-45f2-bf48-ebe629845db0" CreationDate="2016-07-06T18:52:44.217" UserId="4708" Text="Creating an &quot;ink spread&quot; effect with a glsl fragment shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="7723" PostHistoryTypeId="3" PostId="3729" RevisionGUID="720f422a-5bac-45f2-bf48-ebe629845db0" CreationDate="2016-07-06T18:52:44.217" UserId="4708" Text="|opengl|glsl|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7724" PostHistoryTypeId="5" PostId="3727" RevisionGUID="b8a05f27-1bff-465c-b492-4d5f8b8393fc" CreationDate="2016-07-06T19:10:00.253" UserId="231" Comment="Typos and apply assumed intended formating. Please revert anything which is not your intention." Text="**1. Method: Vertex Clustering**&#xD;&#xA;&#xD;&#xA;This is more or less a low-quality method, but depending on your mesh it could work well.  &#xD;&#xA;The basic idea is to partition the space into a regular grid, and then choose one representative for each cell that holds at least one vertex.  &#xD;&#xA;Then calculate the connectivity based on the connectivity of the original vertices.&#xD;&#xA;&#xD;&#xA;[![2D Vertex Clustering][Figure 1]][Figure 1]&#xD;&#xA;&#xD;&#xA;In the image you see a basic 2D clustering. The unreduced mesh on the left, and the reduced on the right with the chosen representatives.  &#xD;&#xA;As you can see, just choosing an existing vertex as representative (by closest to mean, or closest to center, or any other idea you can think of) you get a subset of vertices.&#xD;&#xA;&#xD;&#xA;But you also see the problem, thin parts will degenerate and parts that are close to forming a loop will probably get connected. But as already said, it depends on your mesh if this works.&#xD;&#xA;&#xD;&#xA;**2. Method: Incremental Mesh Decimation with with Half-edge Collapse**&#xD;&#xA;&#xD;&#xA;[![Figure 2][Figure 2 image]][Figure 2 link]&#xD;&#xA;&#xD;&#xA;One vertex gets collapsed into its neighbour. Thereby you get again a subsampling.  &#xD;&#xA;This is a progressive method. You evaluate which collapse will decrease the quality (for example total distance to the original surface, but many more possible) and collapse it. Then you check if your quality has dropped too much for another collapse, and if so you stop. Otherwise you do it again. Until either the quality drops too much or the target size is reached.&#xD;&#xA;&#xD;&#xA;**Method 3: Progressive Mesh Decimation with Vertex Decimation.**&#xD;&#xA;&#xD;&#xA;The same progressive idea as in method 2, but this time instead of a collapse you just delete a vertex and calculate a new triangulation for the hole that this created.&#xD;&#xA;&#xD;&#xA;  [Figure 1]: https://i.stack.imgur.com/ijNC6.png&#xD;&#xA;&#xD;&#xA;  [Figure 2 link]: https://www.researchgate.net/figure/221129055_fig1_Fig-1-Half-edge-collapse-decimation-operation&#xD;&#xA;&#xD;&#xA;  [Figure 2 image]: https://www.researchgate.net/profile/Khaled_Mamou/publication/221129055/figure/fig1/AS:305611066626062@1449874764141/Fig-1-Half-edge-collapse-decimation-operation.png &quot;Fig. 1 . Half-edge collapse decimation operation.&amp;nbsp;&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7725" PostHistoryTypeId="2" PostId="3730" RevisionGUID="31edfa9f-76f2-47f1-a7f3-4b44a3766cca" CreationDate="2016-07-06T19:30:02.953" UserId="4705" Text="I have been trying to understand &quot;Fast Simulation of Mass-Spring Systems&quot; by Liu et al., which can be found [here](http://graphics.berkeley.edu/papers/Liu-FSM-2013-11/Liu-FSM-2013-11.pdf). There is one part in the methods section that is confusing me. Just after equation 12, it states:&#xD;&#xA;&#xD;&#xA;Similarly, **S**&lt;sub&gt;*i*&lt;/sub&gt; ∈ R&lt;sup&gt;*s*&lt;/sup&gt; is the *i*-th spring indicator, i.e., **S**&lt;sub&gt;*i,j*&lt;/sub&gt; = *δ*&lt;sub&gt;*i,j*&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;The subscript *i* is for each spring in the system. But I am not sure what δ is supposed to be - it isn't mentioned anywhere else in the paper. I also don't know what the subscript *j* is for, or what a spring indicator is. My guess was that **S** is a diagonal matrix, with the deflection of each spring along the diagonal. But this doesn't work in my code. Having **S** as just the identity matrix works better.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7726" PostHistoryTypeId="1" PostId="3730" RevisionGUID="31edfa9f-76f2-47f1-a7f3-4b44a3766cca" CreationDate="2016-07-06T19:30:02.953" UserId="4705" Text="Confusion about notation in a paper" ContentLicense="CC BY-SA 3.0" />
  <row Id="7727" PostHistoryTypeId="3" PostId="3730" RevisionGUID="31edfa9f-76f2-47f1-a7f3-4b44a3766cca" CreationDate="2016-07-06T19:30:02.953" UserId="4705" Text="|simulation|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7728" PostHistoryTypeId="5" PostId="3730" RevisionGUID="5e6a2b0c-7c0d-436a-a625-61489b5379ca" CreationDate="2016-07-06T19:39:37.123" UserId="4705" Comment="added 79 characters in body" Text="I have been trying to understand &quot;Fast Simulation of Mass-Spring Systems&quot; by Liu et al., which can be found [here](http://graphics.berkeley.edu/papers/Liu-FSM-2013-11/Liu-FSM-2013-11.pdf). There is one part in the methods section that is confusing me. Just after equation 12, it states:&#xD;&#xA;&#xD;&#xA;Similarly, **S**&lt;sub&gt;*i*&lt;/sub&gt; ∈ R&lt;sup&gt;*s*&lt;/sup&gt; is the *i*-th spring indicator, i.e., **S**&lt;sub&gt;*i,j*&lt;/sub&gt; = *δ*&lt;sub&gt;*i,j*&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;The subscript *i* is for each spring in the system. But I am not sure what δ is supposed to be - it isn't mentioned anywhere else in the paper. I also don't know what the subscript *j* is for, or what a spring indicator is. My guess was that **S** is a diagonal matrix, with the deflection of each spring along the diagonal. But this doesn't work in my code. Having **S** as just the identity matrix works better. Does anyone know &#xD;&#xA;&#xD;&#xA;Does anyone know what the **S** matrix is supposed to be?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7729" PostHistoryTypeId="5" PostId="3730" RevisionGUID="587858ae-0c6e-4c17-a79e-28e5ac1ed20a" CreationDate="2016-07-06T19:49:16.340" UserId="4705" Comment="deleted 18 characters in body" Text="I have been trying to understand &quot;Fast Simulation of Mass-Spring Systems&quot; by Liu et al., which can be found [here](http://graphics.berkeley.edu/papers/Liu-FSM-2013-11/Liu-FSM-2013-11.pdf). There is one part in the methods section that is confusing me. Just after equation 12, it states:&#xD;&#xA;&#xD;&#xA;Similarly, **S**&lt;sub&gt;*i*&lt;/sub&gt; ∈ R&lt;sup&gt;*s*&lt;/sup&gt; is the *i*-th spring indicator, i.e., **S**&lt;sub&gt;*i,j*&lt;/sub&gt; = *δ*&lt;sub&gt;*i,j*&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;The subscript *i* is for each spring in the system. But I am not sure what δ is supposed to be - it isn't mentioned anywhere else in the paper. I also don't know what the subscript *j* is for, or what a spring indicator is. My guess was that **S** is a diagonal matrix, with the deflection of each spring along the diagonal. But this doesn't work in my code. Having **S** as just the identity matrix works better.&#xD;&#xA;&#xD;&#xA;Does anyone know what the **S** matrix is supposed to be?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7730" PostHistoryTypeId="2" PostId="3731" RevisionGUID="b9e11f1c-493e-4194-95b3-dbf82506c8be" CreationDate="2016-07-06T19:52:08.680" UserId="48" Text="The notation $\delta_{i,j}$ is the [Kronecker delta](https://en.wikipedia.org/wiki/Kronecker_delta), a notation commonly used in physics. It's defined as:&#xD;&#xA;$$\delta_{i,j} \equiv \begin{cases}1,&amp;i=j\\0,&amp;i\neq j\end{cases}$$&#xD;&#xA;So, as you suspected, it's essentially a shorthand for the identity matrix.&#xD;&#xA;&#xD;&#xA;The notation $\mathbf{S}_i \in \mathrm{R}^s$ means that each $\mathbf{S}_i$ is an $s$-dimensional vector, so the index $j$ labels the components of this vector." ContentLicense="CC BY-SA 3.0" />
  <row Id="7731" PostHistoryTypeId="5" PostId="3731" RevisionGUID="771959bc-b61a-4d05-940e-9ae6f47c5a54" CreationDate="2016-07-06T20:01:29.647" UserId="48" Comment="elaborated on how the vector is used in the paper" Text="The notation $\delta_{i,j}$ is the [Kronecker delta](https://en.wikipedia.org/wiki/Kronecker_delta), a notation commonly used in physics. It's defined as:&#xD;&#xA;$$\delta_{i,j} \equiv \begin{cases}1,&amp;i=j\\0,&amp;i\neq j\end{cases}$$&#xD;&#xA;So, as you suspected, it's essentially a shorthand for the identity matrix.&#xD;&#xA;&#xD;&#xA;The notation $\mathbf{S}_i \in \mathrm{R}^s$ means that each $\mathbf{S}_i$ is an $s$-dimensional vector, so the index $j$ labels the components of this vector. The term &quot;indicator&quot; probably refers to the concept of an [indicator function](https://en.wikipedia.org/wiki/Indicator_function), which is a function that labels some set or point with the value 1 while mapping everything else to 0. So, the &quot;$i$-th spring indicator&quot;, in this context, is a vector that has a 1 in the $i$-th component and 0 everywhere else. That's exactly the Kronecker delta, i.e. the identity matrix.&#xD;&#xA;&#xD;&#xA;The way this &quot;indicator vector&quot; gets used in equation 12 in the paper is in the form of an outer product with another vector, $\mathbf{A}_i \in \mathrm{R}^m$. The two vectors are multiplied together in the form $\mathbf{A}_i \mathbf{S}_i^{\mathrm{T}}$, which is an outer product. The result is an $m \times s$ matrix with the contents of $\mathbf{A}_i$ in the $i$-th column, and zeroes everywhere else." ContentLicense="CC BY-SA 3.0" />
  <row Id="7732" PostHistoryTypeId="2" PostId="3732" RevisionGUID="9edf942f-1779-4aaa-8405-fccd0fb7f861" CreationDate="2016-07-06T20:22:23.883" UserId="4709" Text="Is it topological correct to combine triangles with quads to form a mesh. If not, why?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7733" PostHistoryTypeId="1" PostId="3732" RevisionGUID="9edf942f-1779-4aaa-8405-fccd0fb7f861" CreationDate="2016-07-06T20:22:23.883" UserId="4709" Text="Combination of Triangles and Quads in a mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="7734" PostHistoryTypeId="3" PostId="3732" RevisionGUID="9edf942f-1779-4aaa-8405-fccd0fb7f861" CreationDate="2016-07-06T20:22:23.883" UserId="4709" Text="|mesh|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7735" PostHistoryTypeId="2" PostId="3733" RevisionGUID="bf11459e-a397-4c95-a409-c3ff973dd786" CreationDate="2016-07-06T22:00:21.027" UserId="4710" Text="OpenEXR might be a good fit. You can have an arbitrary number of channels per pixel and the data types for each channel can be integers.&#xD;&#xA;&#xD;&#xA;http://www.openexr.com/&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7736" PostHistoryTypeId="5" PostId="3729" RevisionGUID="38858d97-9f46-4c59-9eef-c15f30683935" CreationDate="2016-07-06T23:22:01.557" UserId="4708" Comment="added 264 characters in body" Text="I have dealt with glsl before, but I still have problems with my understanding of how to achieve certain kinds of effects with per-pixel processing. What I am looking to do is use a fragment shader to emulate ink spreading across paper. Simply put, I want to emulate a large drop of ink being dropped on paper, with the ink spreading out from the source, perhaps with some capillary effect. Instead of one drop, this will apply to an entire image.&#xA;&#xA;Ive done some brainstorming for the implementation. There is a random initial &quot;mass&quot; applied to each pixel, and one method I'm considering is having the texture scale outwards with the value of the initial &quot;mass&quot; decreasing until 0.&#xD;&#xA;&#xD;&#xA;What might I be missing in trying to implement this? Does anyone know of a similar shader effect that I could consult while building this?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7737" PostHistoryTypeId="2" PostId="3734" RevisionGUID="77a63193-b13c-4b67-bb6e-6c3b755178f9" CreationDate="2016-07-07T03:39:29.670" UserId="3073" Text="I see you use glEnable(GL_TEXTURE_GEN_S); but also use glTexCoord(...) to load coordinates. These are mutually exclusive features IIRC. If you are supplying your own texture coordinates you should not need to use glEnable(GL_TEXTURE_GEN_n).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7738" PostHistoryTypeId="2" PostId="3735" RevisionGUID="432e1885-2e72-4663-a319-d0c2aa3fc604" CreationDate="2016-07-07T07:35:05.870" UserId="182" Text="I have no knowledge of the literature on the topic, but I did something very similar to what you're asking some time ago: I wanted to generate lathe meshes and bend them according to a spline. I think the same technique could be adapted to your case quite easily.&#xD;&#xA;&#xD;&#xA;First you would need to define what your default axis is: if the input mesh corresponds to the case when the spline curve is a straight line, where is that line in 3D? It could be defined arbitrarily as the Y axis, the PCA of the mesh, or some manually defined axis.&#xD;&#xA;&#xD;&#xA;The algorithm is then:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    for each vertex v&#xD;&#xA;    {&#xD;&#xA;        float h = GetPositionOnAxis(v);&#xD;&#xA;        matrix4 M = ComputeTransformFromAxisToSpline(h);&#xD;&#xA;        v = ApplyTransform(v, M);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The tricky part is to define a transform $M$. You can do something like:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    matrix4 ComputeTransformFromAxisToSpline(float h)&#xD;&#xA;    {&#xD;&#xA;        vector3 p1 = GetPointOnSpline(h);&#xD;&#xA;        vector3 p2 = GetPointOnSpline(h + dh); // dh is a small delta&#xD;&#xA;        vector3 u = normalize(p2 - p1);&#xD;&#xA;&#xD;&#xA;        // Define an orthogonal basis&#xD;&#xA;        vector3 v = v0;&#xD;&#xA;        vector3 w = normalize(cross(u, v));&#xD;&#xA;        vector3 v = normalize(cross(w, u));&#xD;&#xA;&#xD;&#xA;        return MakeTransform(u, v, w, p1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;$v_0$ is going to be the problem. I have tried two approaches:&#xD;&#xA;&#xD;&#xA; - Use an absolute value, like an axis orthogonal to the default axis. This will work only if the spline never gets parallel to that axis. It may also lead to undesired shapes.&#xD;&#xA; - Start with an absolute value for the points at $h=0$, then reuse the previous $v$ for bigger $h$ values. This means you have to treat vertices ordered by $h$. In my case this was trivial because I was generating the vertices, but in your case that would probably mean to sort them. The result is a mesh that will tend to twist in curves, which may or may not be desirable.&#xD;&#xA;&#xD;&#xA;Another possibility would be to define the orientation by having more information in the curve, but I haven't tried that approach as I was already satisfied with the result." ContentLicense="CC BY-SA 3.0" />
  <row Id="7739" PostHistoryTypeId="5" PostId="3735" RevisionGUID="50455689-1637-4272-8d47-70bf19806da3" CreationDate="2016-07-07T07:42:51.123" UserId="182" Comment="Back transform" Text="I have no knowledge of the literature on the topic, but I did something very similar to what you're asking some time ago: I wanted to generate lathe meshes and bend them according to a spline. I think the same technique could be adapted to your case quite easily.&#xD;&#xA;&#xD;&#xA;First you would need to define what your default axis is: if the input mesh corresponds to the case when the spline curve is a straight line, where is that line in 3D? It could be defined arbitrarily as the Y axis, the PCA of the mesh, or some manually defined axis.&#xD;&#xA;&#xD;&#xA;The algorithm is then:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    for each vertex v&#xD;&#xA;    {&#xD;&#xA;        matrix4 M = ComputeTransformFromAxisToSpline(v);&#xD;&#xA;        v = ApplyTransform(v, M);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The tricky part is obviously to define a transform $M$. You could do something like:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    matrix4 ComputeTransformFromAxisToSpline(vector3 v)&#xD;&#xA;    {&#xD;&#xA;        float h = GetPositionOnAxis(v, originalAxis);&#xD;&#xA;        vector3 p1 = GetPointOnSpline(h);&#xD;&#xA;        vector3 p2 = GetPointOnSpline(h + dh); // dh is a small delta&#xD;&#xA;        vector3 u = normalize(p2 - p1);&#xD;&#xA;&#xD;&#xA;        // Define an orthogonal basis&#xD;&#xA;        vector3 v = v0;&#xD;&#xA;        vector3 w = normalize(cross(u, v));&#xD;&#xA;        vector3 v = normalize(cross(w, u));&#xD;&#xA;&#xD;&#xA;        return MakeTransform(u, v, w, p1) * MakeTranslation(originalAxis, -h);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;$v_0$ is going to be the problem. I have tried two approaches:&#xD;&#xA;&#xD;&#xA; - Use an absolute value, like an axis orthogonal to the default axis. This will work only if the spline never gets parallel to that axis. It may also lead to undesired shapes.&#xD;&#xA; - Start with an absolute value for the points at $h=0$, then reuse the previous $v$ for bigger $h$ values. This means you have to treat vertices ordered by $h$. In my case this was trivial because I was generating the vertices, but in your case that would probably mean to sort them. The result is a mesh that will tend to twist in curves, which may or may not be desirable.&#xD;&#xA;&#xD;&#xA;Another possibility would be to define the orientation by having more information in the curve, but I haven't tried that approach as I was already satisfied with the result." ContentLicense="CC BY-SA 3.0" />
  <row Id="7740" PostHistoryTypeId="2" PostId="3736" RevisionGUID="17d7bdf2-b41c-4118-8d11-a28b4f66374b" CreationDate="2016-07-07T10:32:52.690" UserId="137" Text="None of today's graphics interfaces support quads by default in the first place.&#xD;&#xA;&#xD;&#xA;This means that quads, when actually set up for rendering, are just pairs of triangles." ContentLicense="CC BY-SA 3.0" />
  <row Id="7741" PostHistoryTypeId="2" PostId="3737" RevisionGUID="a640604b-53b0-4854-9309-393be0e023dd" CreationDate="2016-07-07T12:50:17.560" UserId="273" Text="Topologically correct is a very vague.&#xD;&#xA;&#xD;&#xA;I believe you think of Polygon-Meshes when you say meshes, which is to represent the surface of the object by a patch of polygons, in most cases triangles or quads. There are other options to model meshes, one idea would be to use signed distance functions as for example in constructive solid geometry.&#xD;&#xA;&#xD;&#xA;So back to the question. Is it correct to mix the type of polygon? Yes. There is, mathematically and theoretically nothing stopping you from doing it.&#xD;&#xA;&#xD;&#xA;The only real 'correctness' criteria that comes to my mind is the one of the mesh being a manifold. This is in (overly) simplficated the property that the mesh has a defined outside and inside and no strange places where you can't decide. (This happens for example if the mesh intersects with itself, but it get's freaky).&#xD;&#xA;&#xD;&#xA;But most algorithms can actually deal with non-manifolds. There is no problem in rasterizing or raycasting a non-manifold as these algorithms process each primitive separately.&#xD;&#xA;&#xD;&#xA;The more interesting question here is: Why DONT we mix the type of primitive?&#xD;&#xA;&#xD;&#xA;And here the answer is very simple: Efficiency. You want to design an algorithm that handles your mesh as efficient as possible, and so you assume it's only one type of primitive. And at some point in time, because triangle-meshes are really handy, hardware and hardware-api began to adpot mainly to processing triangles. And now they are good at that and even other primitive types get split into triangles since splitting and rendering triangles is still faster than rendering the polygons directly.&#xD;&#xA;&#xD;&#xA;So in short: You can mix polygon types, but if you want to be fast, use only triangles since they are simple and widely used." ContentLicense="CC BY-SA 3.0" />
  <row Id="7742" PostHistoryTypeId="5" PostId="3677" RevisionGUID="c1aef87f-46cf-4b7e-a4f1-ff0281248053" CreationDate="2016-07-07T13:59:01.953" UserId="4608" Comment="added even more info at request of user joojaa" Text="My previous question got closed, because of a delay in response from my &#xD;&#xA;side so I'm posting here with a lot more details.&#xD;&#xA;&#xD;&#xA;I want to do keyframe interpolation in matlab.&#xD;&#xA;&#xD;&#xA;If I understand correctly, it uses splines to approximate the the motion of specific pixel points within the frames(through transforms). Correct me if I'm wrong.&#xD;&#xA;&#xD;&#xA;I tried looking but there are no toolboxes or any code for it. Where can I start?&#xD;&#xA;&#xD;&#xA;I will be working with video frames. At specific points (say after N frames, N~~100) the first frame encountered is labeled the keyframe.&#xD;&#xA;&#xD;&#xA;These frames are the equivalent to what animator artists draw and then animate by getting the computer to approximate frames in between.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm interpolating image frames. Literal image frame pixel values.&#xD;&#xA;&#xD;&#xA;Imagine this, there are some pixel values I select, then I call those pixel values features and decide to track those pixel values against the frames. Those pixel values must have some sort of trajectory. I want to interpolate pixel values at various points of a trajectory such that the trajectory approximates a smooth motion between the pixel values.&#xD;&#xA;&#xD;&#xA;Can anyone help me?&#xD;&#xA;&#xD;&#xA;EDIT::&#xD;&#xA;&#xD;&#xA;I know the per pixel affine transform matrices between frames, the warps they perform on any single pixel in the image give rise to displacement in the pixel in a frame-time plot and end up being a trajectory. I smooth this thing somehow and have another set of matrices now describing the same thing but smoother" ContentLicense="CC BY-SA 3.0" />
  <row Id="7743" PostHistoryTypeId="5" PostId="3737" RevisionGUID="dd01a736-334c-4794-8721-56f96d677fb3" CreationDate="2016-07-07T14:44:39.093" UserId="273" Comment="Made it clearer why manifoldness no problem." Text="Topologically correct is a very vague.&#xD;&#xA;&#xD;&#xA;I believe you think of Polygon-Meshes when you say meshes, which is to represent the surface of the object by a patch of polygons, in most cases triangles or quads. There are other options to model meshes, one idea would be to use signed distance functions as for example in constructive solid geometry.&#xD;&#xA;&#xD;&#xA;So back to the question. Is it correct to mix the type of polygon? Yes. There is, mathematically and theoretically nothing stopping you from doing it.&#xD;&#xA;&#xD;&#xA;The only real 'correctness' criteria that comes to my mind is the one of the mesh being a manifold. This is in (overly) simplficated the property that the mesh has a defined outside and inside and no strange places where you can't decide. (This happens for example if the mesh intersects with itself, but it get's freaky). And having different types of primitive does not violate the manifoldness of the mesh.&#xD;&#xA;&#xD;&#xA;But most algorithms can actually deal with non-manifolds. There is no problem in rasterizing or raycasting a non-manifold as these algorithms process each primitive separately.&#xD;&#xA;&#xD;&#xA;The more interesting question here is: Why DONT we mix the type of primitive?&#xD;&#xA;&#xD;&#xA;And here the answer is very simple: Efficiency. You want to design an algorithm that handles your mesh as efficient as possible, and so you assume it's only one type of primitive. And at some point in time, because triangle-meshes are really handy, hardware and hardware-api began to adpot mainly to processing triangles. And now they are good at that and even other primitive types get split into triangles since splitting and rendering triangles is still faster than rendering the polygons directly.&#xD;&#xA;&#xD;&#xA;So in short: You can mix polygon types, but if you want to be fast, use only triangles since they are simple and widely used." ContentLicense="CC BY-SA 3.0" />
  <row Id="7745" PostHistoryTypeId="2" PostId="3738" RevisionGUID="b675fba4-e937-4a15-b2b3-660fea811e3f" CreationDate="2016-07-07T18:25:37.150" UserId="4712" Text="why the rendering equation, introduced by Kajiya in 1986, is not solvable directly/analytically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7746" PostHistoryTypeId="1" PostId="3738" RevisionGUID="b675fba4-e937-4a15-b2b3-660fea811e3f" CreationDate="2016-07-07T18:25:37.150" UserId="4712" Text="Rendering equation - why unsolvable directly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7747" PostHistoryTypeId="3" PostId="3738" RevisionGUID="b675fba4-e937-4a15-b2b3-660fea811e3f" CreationDate="2016-07-07T18:25:37.150" UserId="4712" Text="|raytracing|rendering|lighting|brdf|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7748" PostHistoryTypeId="2" PostId="3739" RevisionGUID="62d718cc-33fd-4fdb-b967-2c76015fe86e" CreationDate="2016-07-07T18:36:55.133" UserId="2308" Text="Ok, I have a simulation I am trying to make. The entire simulation is drawn by circles (with gl_Point) and rectangles (gl_triangles with indices).&#xD;&#xA;&#xD;&#xA;It would be great to add some anti aliasing especially as there scale is usually rather small.&#xD;&#xA;&#xD;&#xA;My problem is I have seen some formulas that smooth step the edges of a shape, however I do not know how to properly consider scale.&#xD;&#xA;&#xD;&#xA;Each sprite will have different scale to it, each rectangle will have a different width / height ratio, not to mention I am not yet passing in texture coords because they have been so far un-necesary. And this will run on multiple screen resolutions.&#xD;&#xA;&#xD;&#xA;I guess I have two questions:&#xD;&#xA;&#xD;&#xA; 1. Is it possible to anti-alias a rectangle in a fragment shader without knowing the UV of each fragment since I am not yet passing them in? Even if it was possible how would I account for different ratios of rectangles?&#xD;&#xA; 2. What math can I use to ensure that no matter the device resolution, or shape size that the anti aliasing effects a maximum of 2 pixels (or whatever) from the edge of the shape?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7749" PostHistoryTypeId="1" PostId="3739" RevisionGUID="62d718cc-33fd-4fdb-b967-2c76015fe86e" CreationDate="2016-07-07T18:36:55.133" UserId="2308" Text="How to never draw &quot;Jaggies&quot; in the first place considering resolution and scale" ContentLicense="CC BY-SA 3.0" />
  <row Id="7750" PostHistoryTypeId="3" PostId="3739" RevisionGUID="62d718cc-33fd-4fdb-b967-2c76015fe86e" CreationDate="2016-07-07T18:36:55.133" UserId="2308" Text="|line-drawing|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7751" PostHistoryTypeId="2" PostId="3740" RevisionGUID="04101f97-e0be-4cce-b920-daf6f28737de" CreationDate="2016-07-07T20:01:22.897" UserId="273" Text="The rendering equation is as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now, the integral is over the sphere around the point x.&#xD;&#xA;You integrate over some attenuated light, incoming from every direction.&#xD;&#xA;&#xD;&#xA;But how much light comes in? Thit is the light L(x',w_i) that some other point x' reflect in the direction w_i of point x.&#xD;&#xA;&#xD;&#xA;Now you have to calculate how much that new point x' reflects, which is to solve rendering equation for that point. And the solution for that point depends on a huge number of other points, including x.&#xD;&#xA;&#xD;&#xA;Short: The rendering equation is infinitely recursive.&#xD;&#xA;&#xD;&#xA;You cannot solve it exactly and analytically because it has infinive integrals over infinite integration domains.&#xD;&#xA;&#xD;&#xA;But since light gets weaker each time it is reflected, at some point a human simply cannot notice the difference any more. And so you do not actually solve the rendering equation, but you limit the number of recursions (say reflections) to something that is 'close enough'.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d9L29.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7752" PostHistoryTypeId="2" PostId="3741" RevisionGUID="b6e37a49-9ec4-411b-a667-439723d286b0" CreationDate="2016-07-07T20:16:03.360" UserId="38" Text="Well you can render at higher resolution and sample down thhis is called FSAA and should just work without much change to render code. FSAA has the benefit of not having a conflation problem whereas smoothing does.&#xD;&#xA;&#xD;&#xA;1. No, something has to emit this info.&#xD;&#xA;&#xD;&#xA;2. You take the derivate (the gfx card does this for you) of the surface varying to determine how far the step would take you in your pixel. if its over the edge then you antialias." ContentLicense="CC BY-SA 3.0" />
  <row Id="7753" PostHistoryTypeId="2" PostId="3742" RevisionGUID="06df3a27-048a-4488-823b-ed33b5bf4377" CreationDate="2016-07-08T05:14:00.333" UserId="4714" Text="tl;dr: Math problem in projective geometry: **How does one find some 4x4 camera matrix that gives a projection as illustrated below, such that points A,B,C,D are somewhere on the edges of the unit box (e.g. OpenGL normalized device coordinates), and the corners of the unit box fall somewhere reasonable along the rays EA, EB, EC, ED?**&#xD;&#xA;&#xD;&#xA;( extra tags: dlt direct-linear-transform projections opengl homography projective-space perspectivity collineation ndc normalized-device-coordinates matrix svd singular-value-decomposition least-squares camera camera-matrix projective-geometry projective-space homogeneous-coordinates )&#xD;&#xA;&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;elaboration:&#xD;&#xA;&#xD;&#xA;Given a quadrilateral ABCD within the the viewport, I think there exists a unique(?) transformation that maps it back to a rectangle. As seen in the image below: the quadrilateral ABCD in the viewport acts as a physical 'window', and if we map it back to a rectangle it will appear distorted.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/k5XLm.png&#xD;&#xA;&#xD;&#xA;(the box on the right represents NDC, which I talk about later)&#xD;&#xA;&#xD;&#xA;The goal is to quickly obtain the image on the right. We could raytrace every point to obtain the image (which I've done), but I would prefer to use OpenGL or other projective techniques because I wanted to take advantage of things like blending, primitives, etc.&#xD;&#xA;&#xD;&#xA;first attempt (hover to show):&#xD;&#xA;&#xD;&#xA;&gt;! I believe I can solve the problem of finding the 3x4 [camera matrix](https://en.wikipedia.org/wiki/Camera_matrix) that makes the 3+1-dimensional [homogeneous coordinate](https://en.wikipedia.org/wiki/Homogeneous_coordinates) in 3-space (on the left) and projects it down to the 2+1 dimensional homogeneous coordinates in 2-space (on the right). One can solve this using the [direct linear transformation](https://en.wikipedia.org/wiki/Direct_linear_transformation) to get a system of equations `Ba=0` for the unknown entries `a` of the camera matrix, and solving the system using [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) (SVD). I would take the vectors EA, EB, EC, ED (where E is your physical eye or the camera in world-space) as points in the pre-image, and (0,0), (1,0), (1,1), (0,1) or something as the points in the post-image, and each pair of points would give a few linear equations to plug into the SVD. The resulting matrix would map EA-&gt;(0,0) etc. (assuming there are enough degrees of freedom i.e. if the solution is unique, which I'm not sure about, see note[a].)&#xD;&#xA;&#xD;&#xA;But to my chagrin this is not how OpenGL works. OpenGL does not directly project 3d to 2d with a 3x4 matrix. OpenGL requires &quot;normalized device coordinates&quot; (NDC), which are three-dimensional points. After projecting into NDC, everything in the 'unit' box from (-1,-1,-1,1) to (1,1,1,1) is drawn; everything outside is clipped (since we're dealing with homogenerous coordinates: any point (x,y,z,w) will appear only on-screen only if the first three coordinates of (x/w,y/w,z/w,1) are within the unit box from -1 to 1).&#xD;&#xA;&#xD;&#xA;So the question becomes: does there exist some reasonable transformation that maps some weird-looking cuboid in homogeneous coordinates (specifically the cuboid drawn on the left, with ABCD (front points) and A'B'C'D' (back points, hidden behind front points)) to the unit cube, e.g. using a 4x4 matrix? How does one do it?&#xD;&#xA;&#xD;&#xA;what I've tried: &#xD;&#xA;&gt;! I've tried something stronger: I made ABCD and A'B'C'D' look like a regular pyramidal frustrum (e.g. gl frustrum) (i.e. in this hypothetical setup, the image on the left would just have a black rectangle superposed on it, not a quadrilateral), and then used the DLT/direct linear transformation to solve for the alleged 4x4 matrix. However when I tried it, there did not seem to be enough degrees of freedom... the resulting 4x4 matrix did not map every input vector to every output vector. While using A,B,C,D,A' (5 pairs of pre-transform and post-transform vectors), I /almost/ get the result I want... the vectors are mapped correctly, but for example B',C',D' are mapping to (3,3,1,1) instead of (-1,-1,1,1) and are clipped away by OpenGL. If I try adding a sixth point (6 pairs of points for the 4x4 matrix to project), my solution seems degenerate (zeroes, infinites). How many degrees of freedom am I dealing with here, and is this possible with a 4x4 matrix mapping the usual 4vectors (3+1-dimensional homogeneous-coordinate vectors) that we know and love?&#xD;&#xA;&#xD;&#xA;random minor thoughts:&#xD;&#xA;&gt;! (I'm guessing that it's not possible to map any arbitrary cuboid to any arbitrary cuboid with a 4x4 matrix, though I'm confused because I thought it was possible to map any convex quadrilateral to any other convex quadrilateral in 2d with some matrix like in, say, Photoshop?... can/can't this not be done with a projective transform? And how does it generalize to 3d? ...... Also given the failed attempt to find a 4x4 matrix, linear algebra says we should not expect an NxN matrix to map more than N linearly independent points to N target points in the best case, but I feel that somehow homogeneous coordinates cheat this because there is some hidden colinearity going on? I guess not?)&#xD;&#xA;&#xD;&#xA;another solution?:&#xD;&#xA;&gt;! I guess one could also maybe do the following ugly thing, where you use a typical frustrum camera projection matrix, find the 2d points corresponding to the corners, then perform a 2d perspective distort homography, but if that were to happen after the pixels were rendered (e.g. photoshop) then there would be problems with resolution... maybe hypothetically one could figure out a matrix to perform this transformation on the XY-plane within NDC-space, then compose it with the normal frustrum-based matrix?&#xD;&#xA;&#xD;&#xA;(note [a]: Degree of freedom: ABCD can be further constrained to be the post-image of a projective transformation acting on a rectangle, if that is necessary... that is the black rectangle on the left could be said to be the result of projecting a picture frame clipart model)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7754" PostHistoryTypeId="1" PostId="3742" RevisionGUID="06df3a27-048a-4488-823b-ed33b5bf4377" CreationDate="2016-07-08T05:14:00.333" UserId="4714" Text="How to unproject quadrilateral into rectangle?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7755" PostHistoryTypeId="3" PostId="3742" RevisionGUID="06df3a27-048a-4488-823b-ed33b5bf4377" CreationDate="2016-07-08T05:14:00.333" UserId="4714" Text="|opengl|projections|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7757" PostHistoryTypeId="2" PostId="3743" RevisionGUID="3fac37af-a9a7-4de5-95c6-2c47820baaf2" CreationDate="2016-07-09T05:52:30.027" UserId="3386" Text="The distinction is not clear mainly because the term &quot;shading&quot; is an extremely broad term. One of the first uses for programmable &quot;shaders&quot; in real-time graphics pipeline was computing illumination on vertices or pixels - close analogs to what an artist does when shading an object in a drawing for example. &#xD;&#xA;&#xD;&#xA;Today it has come to encompass all calculations that figure into determining the final color of a fragment (&quot;fragment/pixel shader&quot;), or the final attribute values of a vertex (&quot;vertex shader&quot;) or primitive (&quot;geometry shader&quot;), etc. Generally all programmable stages in the real-time graphics pipeline have come be called &quot;shaders&quot; whether they compute colors/illumination or not.&#xD;&#xA;&#xD;&#xA;*Shadowing* likely just refers to shading work that determines the portion of direct light that is occluded with respect to a location on a surface. It can also reasonably refer to *indirect* illumination/occlusion." ContentLicense="CC BY-SA 3.0" />
  <row Id="7758" PostHistoryTypeId="5" PostId="3677" RevisionGUID="180615d4-cd7b-4a4a-a15f-d4de35d1d961" CreationDate="2016-07-09T08:07:29.120" UserId="4608" Comment="Added images for even more clarity" Text="My previous question got closed, because of a delay in response from my &#xD;&#xA;side so I'm posting here with a lot more details.&#xD;&#xA;&#xD;&#xA;I want to do keyframe interpolation in matlab.&#xD;&#xA;&#xD;&#xA;If I understand correctly, it uses splines to approximate the the motion of specific pixel points within the frames(through transforms). Correct me if I'm wrong.&#xD;&#xA;&#xD;&#xA;I tried looking but there are no toolboxes or any code for it. Where can I start?&#xD;&#xA;&#xD;&#xA;I will be working with video frames. At specific points (say after N frames, N~~100) the first frame encountered is labeled the keyframe.&#xD;&#xA;&#xD;&#xA;These frames are the equivalent to what animator artists draw and then animate by getting the computer to approximate frames in between.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm interpolating image frames. Literal image frame pixel values.&#xD;&#xA;&#xD;&#xA;Imagine this, there are some pixel values I select, then I call those pixel values features and decide to track those pixel values against the frames. Those pixel values must have some sort of trajectory. I want to interpolate pixel values at various points of a trajectory such that the trajectory approximates a smooth motion between the pixel values.&#xD;&#xA;&#xD;&#xA;Can anyone help me?&#xD;&#xA;&#xD;&#xA;EDIT::&#xD;&#xA;&#xD;&#xA;I know the per pixel affine transform matrices between frames, the warps they perform on any single pixel in the image give rise to displacement in the pixel in a frame-time plot and end up being a trajectory. I smooth this thing somehow and have another set of matrices now describing the same thing but smoother&#xD;&#xA;&#xD;&#xA;EDIT::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::&#xD;&#xA;&#xD;&#xA;ADDED IMAGES&#xD;&#xA;&#xD;&#xA;[![Image 1][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Image 2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;i.stack.imgur.com/g4E46.png [THIRD IMAGE]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shqub.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/noKVs.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;CAN NOW SOMEONE PLEASE HELP ME?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7760" PostHistoryTypeId="5" PostId="3677" RevisionGUID="d3199d11-1ea9-4acb-99df-bb0a4c634e67" CreationDate="2016-07-09T13:25:03.277" UserId="231" Comment="Fix broken image. Remove ALL UPPER CASE shouting, redundant EDIT labels and redundant &quot;Can anyone help?&quot;" Text="I want to do keyframe interpolation in matlab.&#xD;&#xA;&#xD;&#xA;If I understand correctly, it uses splines to approximate the the motion of specific pixel points within the frames(through transforms). Correct me if I'm wrong.&#xD;&#xA;&#xD;&#xA;I tried looking but there are no toolboxes or any code for it. Where can I start?&#xD;&#xA;&#xD;&#xA;I will be working with video frames. At specific points (say after N frames, N~~100) the first frame encountered is labeled the keyframe.&#xD;&#xA;&#xD;&#xA;These frames are the equivalent to what animator artists draw and then animate by getting the computer to approximate frames in between.&#xD;&#xA;&#xD;&#xA;I'm interpolating image frames. Literal image frame pixel values.&#xD;&#xA;&#xD;&#xA;Imagine this, there are some pixel values I select, then I call those pixel values features and decide to track those pixel values against the frames. Those pixel values must have some sort of trajectory. I want to interpolate pixel values at various points of a trajectory such that the trajectory approximates a smooth motion between the pixel values.&#xD;&#xA;&#xD;&#xA;I know the per pixel affine transform matrices between frames, the warps they perform on any single pixel in the image give rise to displacement in the pixel in a frame-time plot and end up being a trajectory. I smooth this thing somehow and have another set of matrices now describing the same thing but smoother.&#xD;&#xA;&#xD;&#xA;[![Image 1][1]][1]&#xD;&#xA;&#xD;&#xA;[![Image 2][2]][2]&#xD;&#xA;&#xD;&#xA;[![Image 3][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shqub.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/noKVs.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/g4E46.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7761" PostHistoryTypeId="4" PostId="3677" RevisionGUID="d3199d11-1ea9-4acb-99df-bb0a4c634e67" CreationDate="2016-07-09T13:25:03.277" UserId="231" Comment="Fix broken image. Remove ALL UPPER CASE shouting, redundant EDIT labels and redundant &quot;Can anyone help?&quot;" Text="How to do keyframe interpolation on matlab?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7764" PostHistoryTypeId="2" PostId="3744" RevisionGUID="1152582f-f404-4a83-b157-fe9bd210de7e" CreationDate="2016-07-09T21:49:04.233" UserId="4655" Text="I'm sadly not able to add a comment to the answer above (not enough reputation), so I will do it like this.&#xD;&#xA;&#xD;&#xA;I'd like to point out that what Dragonsteel describes is simply an integral equation (specifically a Fredholm equation of the second kind). There are many such equations which do have an analytic solution, even some forms of the rendering equation have one (e.g. the solution of a white furnace can be given using a simple convergent geometric series, even though the rendering equation is infinitely recursive).&#xD;&#xA;&#xD;&#xA;It is also not necessary to bias the estimated solution by bounding the number of recursions, Russian Roulette provides an useful tool for giving us an unbiased solution for an infinitely recursive rendering equation.&#xD;&#xA;&#xD;&#xA;The main difficulty lies in the fact that the functions for reflectance (BRDF), emitted radiance and visibility are highly complex and often contain many discontinuities. In these cases there often is no analytic solution, or it is simply unfeasible to find such a solution. This is also true in the one dimensional case, most integrals lack an analytic solution.&#xD;&#xA;&#xD;&#xA;Finally I'd like to note that even though most cases of the rendering equation do not have an analytic solution, there is a lot of research in forms of the rendering equation which do have an analytic solution. Using such solution (as n approximation) when possible can significantly reduce noise and can speed up rendering times." ContentLicense="CC BY-SA 3.0" />
  <row Id="7768" PostHistoryTypeId="50" PostId="3596" RevisionGUID="c16b70bc-7e4c-4542-98cd-c286f528e8ed" CreationDate="2016-07-10T17:32:01.237" UserId="-1" />
  <row Id="7773" PostHistoryTypeId="5" PostId="3740" RevisionGUID="3e53b3d8-9b8f-4f77-a747-c6840b768045" CreationDate="2016-07-11T10:07:06.030" UserId="273" Comment="Use mathjax to make it prettier" Text="The rendering equation is as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now, the integral is over the sphere around the point $x$.&#xD;&#xA;You integrate over some attenuated light, incoming from every direction.&#xD;&#xA;&#xD;&#xA;But how much light comes in? Thit is the light $L(x',w_i)$ that some other point $x'$ reflect in the direction $w_i$ of point $x$.&#xD;&#xA;&#xD;&#xA;Now you have to calculate how much that new point $x'$ reflects, which is to solve rendering equation for that point. And the solution for that point depends on a huge number of other points, including $x$.&#xD;&#xA;&#xD;&#xA;Short: The rendering equation is infinitely recursive.&#xD;&#xA;&#xD;&#xA;You cannot solve it exactly and analytically because it has infinive integrals over infinite integration domains.&#xD;&#xA;&#xD;&#xA;But since light gets weaker each time it is reflected, at some point a human simply cannot notice the difference any more. And so you do not actually solve the rendering equation, but you limit the number of recursions (say reflections) to something that is 'close enough'.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d9L29.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7774" PostHistoryTypeId="5" PostId="3596" RevisionGUID="0ae0cf7d-9e22-48b9-afa7-f6f53d11968c" CreationDate="2016-07-11T12:34:56.330" UserId="67" Comment="Fixed spelling" Text="I want to develop a component for 3d shadow analysis of 3d citymodel. I decided to use ray tracing for this purpose. For every time step (for sun's dynamic position during the year) rays will be sent from sun (point light source) and with ray intersection tests surfaces which are and how long are in shadow will be determined. Are there any components for this purpose such as sun's position, ray tracing etc. or do I have to code everything from beginning till to the end? Any answer would be very helpful." ContentLicense="CC BY-SA 3.0" />
  <row Id="7775" PostHistoryTypeId="24" PostId="3596" RevisionGUID="0ae0cf7d-9e22-48b9-afa7-f6f53d11968c" CreationDate="2016-07-11T12:34:56.330" Comment="Proposed by 67 approved by 273, -1 edit id of 151" ContentLicense="CC BY-SA 3.0" />
  <row Id="7776" PostHistoryTypeId="5" PostId="3596" RevisionGUID="1bb6dbfd-cc0e-4517-816b-10959cb161a5" CreationDate="2016-07-11T12:34:56.330" UserId="209" Comment="Fixed spelling" Text="I want to develop a component for 3d shadow analysis of 3d city model. I decided to use ray tracing for this purpose. For every time step (for sun's dynamic position during the year) rays will be sent from sun (point light source) and with ray intersection tests surfaces which are and how long are in shadow will be determined. Are there any components for this purpose such as sun's position, ray tracing etc. or do I have to code everything from beginning to the end? Any answer would be very helpful." ContentLicense="CC BY-SA 3.0" />
  <row Id="7777" PostHistoryTypeId="5" PostId="3744" RevisionGUID="e5dff057-3998-4127-b2b0-27766262b94b" CreationDate="2016-07-11T13:17:56.473" UserId="4655" Comment="deleted 1 character in body" Text="I'm sadly not able to add a comment to the answer above (not enough reputation), so I will do it like this.&#xD;&#xA;&#xD;&#xA;I'd like to point out that what Dragonseel describes is simply an integral equation (specifically a Fredholm equation of the second kind). There are many such equations which do have an analytic solution, even some forms of the rendering equation have one (e.g. the solution of a white furnace can be given using a simple convergent geometric series, even though the rendering equation is infinitely recursive).&#xD;&#xA;&#xD;&#xA;It is also not necessary to bias the estimated solution by bounding the number of recursions, Russian Roulette provides an useful tool for giving us an unbiased solution for an infinitely recursive rendering equation.&#xD;&#xA;&#xD;&#xA;The main difficulty lies in the fact that the functions for reflectance (BRDF), emitted radiance and visibility are highly complex and often contain many discontinuities. In these cases there often is no analytic solution, or it is simply unfeasible to find such a solution. This is also true in the one dimensional case, most integrals lack an analytic solution.&#xD;&#xA;&#xD;&#xA;Finally I'd like to note that even though most cases of the rendering equation do not have an analytic solution, there is a lot of research in forms of the rendering equation which do have an analytic solution. Using such solution (as n approximation) when possible can significantly reduce noise and can speed up rendering times." ContentLicense="CC BY-SA 3.0" />
  <row Id="7778" PostHistoryTypeId="2" PostId="3746" RevisionGUID="c9ebbd9c-7056-4934-b19e-8594f180bc09" CreationDate="2016-07-11T14:54:35.777" UserId="2485" Text="here is my vertex array I am using:&#xD;&#xA;&#xD;&#xA;        vertices = [&#xD;&#xA;             -1.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            -0.5, 1.0, 0.0,&#xD;&#xA;             0.5, 1.0, 0.0,&#xD;&#xA;            1.0, 1.0, 0.0,&#xD;&#xA;            1.0, 0.5, 0.0,&#xD;&#xA;            0.0, 0.5, 0.0,&#xD;&#xA;            0.5, 0.5, 0.0,&#xD;&#xA;            -0.5, 0.5, 0.0,&#xD;&#xA;            -1.0, 0.5, 0.0,&#xD;&#xA;&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -0.5, 0.0, 0.0,&#xD;&#xA;            0.0, 0.0, 0.0,&#xD;&#xA;            0.5, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;            -1.0, -0.5, 0.0,&#xD;&#xA;            0.0, -0.5, 0.0,&#xD;&#xA;            -0.5, -0.5, 0.0,&#xD;&#xA;             0.5, -0.5, 0.0,&#xD;&#xA;            1.0, -0.5, 0.0,&#xD;&#xA;            1.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.5, -1.0, 0.0,&#xD;&#xA;            -0.5, -1.0, 0.0,&#xD;&#xA;            -1.0, -1.0, 0.0,&#xD;&#xA;        ];&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In a html-select I want to select a rendering mode and use it inmy `drawScene`-method:&#xD;&#xA;&#xD;&#xA;        var renderModeSelector = document.getElementById(&quot;renderModeDropDown&quot;);&#xD;&#xA;        var selectedRenderModeValue = renderModeSelector.options[renderModeSelector.selectedIndex].value;&#xD;&#xA;&#xD;&#xA;        switch (selectedRenderModeValue) {&#xD;&#xA;            case &quot;0&quot;:&#xD;&#xA;                gl.drawArrays(gl.POINTS, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            case &quot;1&quot;:&#xD;&#xA;                gl.drawArrays(gl.TRIANGLE_FAN, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            case &quot;2&quot;:&#xD;&#xA;                gl.drawArrays(gl.LINE_LOOP, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            default:&#xD;&#xA;                console.log(&quot;No rendering mode selected.&quot;);&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; 1. Case '0' is supposed to draw the points which works fine&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; 2. Case '1' should draw a filled rectangle, with the shader below. Unfortunately it is messed up, see also in the picture below.&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;        precision mediump float;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_FragColor = vColor;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex-shader:&#xD;&#xA;&#xD;&#xA;        attribute vec3 aVertexPosition;&#xD;&#xA;        attribute vec4 aVertexColor;&#xD;&#xA;&#xD;&#xA;        uniform mat4 uMVMatrix;&#xD;&#xA;        uniform mat4 uPMatrix;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);&#xD;&#xA;        vColor = aVertexColor;&#xD;&#xA;        gl_PointSize = 5.0;&#xD;&#xA;        }&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA; 3. And finally in case '2' it is supposed to draw only the outlines, which also does not work as expected, see below.&#xD;&#xA;&#xD;&#xA; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So I wonder if it is possible to meet my requirements while using one vertexPositionBuffer. Also if it is not what would be another appropriate solution? Should I create another vertexPositionBuffer or can I just change mine &quot;on the fly&quot;, before rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZiyIL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vahR1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/23zah.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7779" PostHistoryTypeId="1" PostId="3746" RevisionGUID="c9ebbd9c-7056-4934-b19e-8594f180bc09" CreationDate="2016-07-11T14:54:35.777" UserId="2485" Text="Rendering same vertex-array in different modes" ContentLicense="CC BY-SA 3.0" />
  <row Id="7780" PostHistoryTypeId="3" PostId="3746" RevisionGUID="c9ebbd9c-7056-4934-b19e-8594f180bc09" CreationDate="2016-07-11T14:54:35.777" UserId="2485" Text="|rendering|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7781" PostHistoryTypeId="5" PostId="3746" RevisionGUID="6ec11529-b829-4239-8de3-3d9a9f3c2dd0" CreationDate="2016-07-11T15:31:47.283" UserId="2485" Comment="corrected formatting" Text="here is my vertex array I am using:&#xD;&#xA;&#xD;&#xA;        vertices = [&#xD;&#xA;             -1.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            -0.5, 1.0, 0.0,&#xD;&#xA;             0.5, 1.0, 0.0,&#xD;&#xA;            1.0, 1.0, 0.0,&#xD;&#xA;            1.0, 0.5, 0.0,&#xD;&#xA;            0.0, 0.5, 0.0,&#xD;&#xA;            0.5, 0.5, 0.0,&#xD;&#xA;            -0.5, 0.5, 0.0,&#xD;&#xA;            -1.0, 0.5, 0.0,&#xD;&#xA;&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -0.5, 0.0, 0.0,&#xD;&#xA;            0.0, 0.0, 0.0,&#xD;&#xA;            0.5, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;            -1.0, -0.5, 0.0,&#xD;&#xA;            0.0, -0.5, 0.0,&#xD;&#xA;            -0.5, -0.5, 0.0,&#xD;&#xA;             0.5, -0.5, 0.0,&#xD;&#xA;            1.0, -0.5, 0.0,&#xD;&#xA;            1.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.5, -1.0, 0.0,&#xD;&#xA;            -0.5, -1.0, 0.0,&#xD;&#xA;            -1.0, -1.0, 0.0,&#xD;&#xA;        ];&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In a html-select I want to select a rendering mode and use it inmy `drawScene`-method:&#xD;&#xA;&#xD;&#xA;        var renderModeSelector = document.getElementById(&quot;renderModeDropDown&quot;);&#xD;&#xA;        var selectedRenderModeValue = renderModeSelector.options[renderModeSelector.selectedIndex].value;&#xD;&#xA;&#xD;&#xA;        switch (selectedRenderModeValue) {&#xD;&#xA;            case &quot;0&quot;:&#xD;&#xA;                gl.drawArrays(gl.POINTS, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            case &quot;1&quot;:&#xD;&#xA;                gl.drawArrays(gl.TRIANGLE_FAN, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            case &quot;2&quot;:&#xD;&#xA;                gl.drawArrays(gl.LINE_LOOP, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            default:&#xD;&#xA;                console.log(&quot;No rendering mode selected.&quot;);&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; 1. Case '0' is supposed to draw the points which works fine&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; 2. Case '1' should draw a filled rectangle, with the shader below. Unfortunately it is messed up, see also in the picture below.&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;        precision mediump float;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_FragColor = vColor;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex-shader:&#xD;&#xA;&#xD;&#xA;        attribute vec3 aVertexPosition;&#xD;&#xA;        attribute vec4 aVertexColor;&#xD;&#xA;&#xD;&#xA;        uniform mat4 uMVMatrix;&#xD;&#xA;        uniform mat4 uPMatrix;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);&#xD;&#xA;        vColor = aVertexColor;&#xD;&#xA;        gl_PointSize = 5.0;&#xD;&#xA;        }&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA; 3. And finally in case '2' it is supposed to draw only the outlines, which also does not work as expected, see below.&#xD;&#xA;&#xD;&#xA; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So I wonder if it is possible to meet my requirements while using one vertexPositionBuffer. Should I maybe create another vertexPositionBuffer or can I just change mine &quot;on the fly&quot;, before rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZiyIL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vahR1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/23zah.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7782" PostHistoryTypeId="5" PostId="3746" RevisionGUID="e15c269c-198d-4d29-b2d4-7414f9dd4fda" CreationDate="2016-07-11T18:36:53.230" UserId="2485" Comment="code formatting" Text="here is my vertex array I am using:&#xD;&#xA;&#xD;&#xA;        vertices = [&#xD;&#xA;             -1.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            -0.5, 1.0, 0.0,&#xD;&#xA;             0.5, 1.0, 0.0,&#xD;&#xA;            1.0, 1.0, 0.0,&#xD;&#xA;            1.0, 0.5, 0.0,&#xD;&#xA;            0.0, 0.5, 0.0,&#xD;&#xA;            0.5, 0.5, 0.0,&#xD;&#xA;            -0.5, 0.5, 0.0,&#xD;&#xA;            -1.0, 0.5, 0.0,&#xD;&#xA;&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -0.5, 0.0, 0.0,&#xD;&#xA;            0.0, 0.0, 0.0,&#xD;&#xA;            0.5, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;            -1.0, -0.5, 0.0,&#xD;&#xA;            0.0, -0.5, 0.0,&#xD;&#xA;            -0.5, -0.5, 0.0,&#xD;&#xA;             0.5, -0.5, 0.0,&#xD;&#xA;            1.0, -0.5, 0.0,&#xD;&#xA;            1.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.5, -1.0, 0.0,&#xD;&#xA;            -0.5, -1.0, 0.0,&#xD;&#xA;            -1.0, -1.0, 0.0,&#xD;&#xA;        ];&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In a html-select I want to select a rendering mode and use it inmy `drawScene`-method:&#xD;&#xA;&#xD;&#xA;        var renderModeSelector = document.getElementById(&quot;renderModeDropDown&quot;);&#xD;&#xA;        var selectedRenderModeValue = renderModeSelector.options[renderModeSelector.selectedIndex].value;&#xD;&#xA;&#xD;&#xA;        switch (selectedRenderModeValue) {&#xD;&#xA;            case &quot;0&quot;:&#xD;&#xA;                gl.drawArrays(gl.POINTS, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            case &quot;1&quot;:&#xD;&#xA;                gl.drawArrays(gl.TRIANGLE_FAN, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            case &quot;2&quot;:&#xD;&#xA;                gl.drawArrays(gl.LINE_LOOP, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;                break;&#xD;&#xA;            default:&#xD;&#xA;                console.log(&quot;No rendering mode selected.&quot;);&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; 1. Case '0' is supposed to draw the points which works fine&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; 2. Case '1' should draw a filled rectangle, with the shader below. Unfortunately it is messed up, see also in the picture below.&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;        precision mediump float;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_FragColor = vColor;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex-shader:&#xD;&#xA;&#xD;&#xA;        attribute vec3 aVertexPosition;&#xD;&#xA;        attribute vec4 aVertexColor;&#xD;&#xA;&#xD;&#xA;        uniform mat4 uMVMatrix;&#xD;&#xA;        uniform mat4 uPMatrix;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);&#xD;&#xA;        vColor = aVertexColor;&#xD;&#xA;        gl_PointSize = 5.0;&#xD;&#xA;        }&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA; 3. And finally in case '2' it is supposed to draw only the outlines, which also does not work as expected, see below.&#xD;&#xA;&#xD;&#xA; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So I wonder if it is possible to meet my requirements while using one vertexPositionBuffer. Should I maybe create another vertexPositionBuffer or can I just change mine &quot;on the fly&quot;, before rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZiyIL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vahR1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/23zah.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7789" PostHistoryTypeId="2" PostId="3748" RevisionGUID="2469b8d1-8e60-4be9-b9ea-5ab8a1965263" CreationDate="2016-07-12T19:23:13.317" UserId="2308" Text="Ok, so I have a pretty good glow shader going now thanks to some tips from people here.&#xD;&#xA;&#xD;&#xA;However there are a few things that bother me that could mabye be better.&#xD;&#xA;&#xD;&#xA;**#1 Definition of the particles:** A lot of times if the particles are moving a lot it just looks like a single sheet of color. The image below is zoomed in so you can see a bit more definition, but zoomed out and real time it just looks like a sheet of sorts&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**#2 The particles dont look like they are neon:**I mean I dont want the effect to be huge but when they are grouped together I would hope for them to have some white highlighting in the glow.&#xD;&#xA;It looks like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;When it should look more like this (this was just a mockup by blending in an additive copy of it with more contrast) when particles are grouped toghether [However singular particles shouldnt have white highlights]:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is my current rendering process:&#xD;&#xA;&#xD;&#xA;I have acouple FBO's with texture attachments:&#xD;&#xA;&#xD;&#xA; - Drawing Frame: Never cleared, up-scaled for the purposes of anti-alising&#xD;&#xA; - Smaller Frame: Cleared each frame, exact resolution of screen, Draws the drawing frame on it with the darkest parts cut out&#xD;&#xA; - Horizontal Blur: Cleared each frame, does a horizontal blur (lower resolutino then screen)&#xD;&#xA; - Vertical Blur: Cleared each frame, blurs the horizontal blur vertically (lower resolution then screen)&#xD;&#xA; - Front buffer: Draws the Smaller frame, and Vertical Buffers ontop of each-other to the screen.&#xD;&#xA;&#xD;&#xA;So A typical render might look like this (I apologize for the misalignment and cropping, the xcode frame debugger allows you to peek at fbo's but not export the texture inside of them I had to use screenshots)&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;To combine the two textures I am using this &#xD;&#xA;&#xD;&#xA;    gl_FragColor = vec4(clamp(texture2D(s_texture, v_texcoord).xyz, 0.,&#xD;&#xA;    1.) + (clamp(texture2D(s_texture2, v_texcoord).xyz, 0., 1.) * 1.5),&#xD;&#xA;    1.0);&#xD;&#xA;&#xD;&#xA;And for the two blurs I am using code like this, a lot of this is pre-computed but to make it easier to read I put how I computed it.&#xD;&#xA;&#xD;&#xA;    float Gaussian(float x, float deviation)&#xD;&#xA;    {&#xD;&#xA;        return (1.0 / sqrt(2.0 * 3.141592 * deviation)) * exp(-((x * x) / (2.0 * deviation)));&#xD;&#xA;    }&#xD;&#xA;    vec3 blurS15()&#xD;&#xA;    &#xD;&#xA;    {&#xD;&#xA;        vec3 blr = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;        float scalart =  (1 / screenResolution.x) * (1.0 / 7.0) * 14.0;&#xD;&#xA;        float deviationScale = 1.2;&#xD;&#xA;        float finalScalar = 1.1;&#xD;&#xA;    &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(7.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(7.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(6.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(6.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(5.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(5.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(4.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(4.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(3.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(3.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(2.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(1.0, 7.0 * deviationScale) ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(0.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(0.0, 7.0 * deviationScale) ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-1.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-2.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-3.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-3.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-4.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-4.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-5.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-5.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-6.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-6.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-7.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-7.0, 7.0 * deviationScale) ;&#xD;&#xA;    &#xD;&#xA;        return blr; //This gets put into gl_FragColor&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now while the issue could be in how I calculate the blur, and combine it I think it is more likely that the issue is in the way I render the particles. Basically each particle is rendered with a circle and a rectangle each frame. The dot marks where it is, and the rectangle connects it the the previous frame. Each new frame the previous frame is faded and then drawn over.&#xD;&#xA;&#xD;&#xA;Here is a diagram of the process, each new hue group represents a new frame, sorry for the childish look of the colors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I do this using two draw calls, one that draws the rectangles (GL_TRIANGLES with indices), and one that draws the circles (GL_POINTS with outsides alpha set to 0).&#xD;&#xA;&#xD;&#xA;While this allows me to quickly simulate an accumulation buffer it comes with some drawbacks, if these can be dealt with without compromising speed then it would be nice to change them.&#xD;&#xA;&#xD;&#xA; 1. No actual depth sorting, although the particles could easily have z values it is futile because opengles 2.0 will go black if you dont clear the depth buffer each frame, so it cant really work with an accumulation buffer.&#xD;&#xA; 2. No additive drawing&#xD;&#xA;     - Because there are two seperate draw calls, even with that setting on nothing seems to draw additivly inside of the same draw call &#xD;&#xA;     - Even if I did the area where the circle and rectangle meet would be extra bright which is undesiarable&#xD;&#xA;&#xD;&#xA;The additive mode I tried was&#xD;&#xA;&#xD;&#xA;    glBlendFunc(GLenum(GL_ONE), GLenum(GL_ONE))&#xD;&#xA;    glEnable(GLenum(GL_BLEND));&#xD;&#xA;    //To be specific when I said it didnt work I tried disabling it before fade, and then enabling it afterwards&#xD;&#xA;    //It caused everything to look wierd almost as if there were no trails&#xD;&#xA;    //And there didnt seem to be highlights where particles intersect&#xD;&#xA;    //However if I had it enabled the whole time then it did look like additive blending&#xD;&#xA;    //Only the previous frame never faded because you cant draw black in add blend mode&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Sorry for writing so much! If you can think of any way I can get more highlighting especially when particles collide, or otherwize make the glow effect look better please let me know.&#xD;&#xA;&#xD;&#xA;I am very curious if there is a way to still do depth sorting with an accumulation buffer/a way to not have to clear the depth buffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AO0kc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/UTIo5.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/9NWsT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/4RzP5.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/tVyCW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7790" PostHistoryTypeId="1" PostId="3748" RevisionGUID="2469b8d1-8e60-4be9-b9ea-5ab8a1965263" CreationDate="2016-07-12T19:23:13.317" UserId="2308" Text="Where are the highlight definitions inside of my shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7791" PostHistoryTypeId="3" PostId="3748" RevisionGUID="2469b8d1-8e60-4be9-b9ea-5ab8a1965263" CreationDate="2016-07-12T19:23:13.317" UserId="2308" Text="|lighting|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7792" PostHistoryTypeId="2" PostId="3749" RevisionGUID="9edd1f16-cdb2-45c2-8692-0f39219f61d1" CreationDate="2016-07-12T20:56:38.973" UserId="3098" Text="I have a 3 dimensional dataset where each value of the dataset is normalized to `[0, 1]`. I want to visualize this dataset by using texture, and blending.&#xD;&#xA;However, it seems that I can't make it work.&#xD;&#xA;&#xD;&#xA;Here is what I have done so far:&#xD;&#xA;&#xD;&#xA;    int main(){&#xD;&#xA;        ...&#xD;&#xA;        //building an image for each rectangular slice of data&#xD;&#xA;        vector&lt;Texture&gt; myTextures;&#xD;&#xA;        for (GLint rowIndex = 0; rowIndex &lt; ROW_NUM; rowIndex++)&#xD;&#xA;	    {&#xD;&#xA;		    auto pathToImage = &quot;images/row&quot; + to_string(rowIndex) + FILE_EXT;&#xD;&#xA;		    FIBITMAP *img = FreeImage_Allocate(SLICE_DIMENSION, SLICE_NUM, 32); //32 = RGBA&#xD;&#xA;&#xD;&#xA;		    for (GLint depthIndex = 0; depthIndex &lt; DEPTH_NUM; depthIndex++)&#xD;&#xA;		    {&#xD;&#xA;			    for (GLint colIndex = 0; colIndex &lt; COL_NUM; colIndex++)&#xD;&#xA;    			{&#xD;&#xA;				    auto value = my3DData[depthIndex][rowIndex][colIndex];&#xD;&#xA;&#xD;&#xA;				    //transform tValue to a source color&#xD;&#xA;				    glm::vec4 source = transformValueToColor(value);&#xD;&#xA;&#xD;&#xA;                    //note that here I am also setting the opacity. &#xD;&#xA;				    RGBQUAD linRgb = { source.b, source.g, source.r, source.a }; &#xD;&#xA;				    FreeImage_SetPixelColor(img, colIndex, depthIndex, &amp;linRgb);&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;&#xD;&#xA;            //Saving images. Saved images shows transparency. &#xD;&#xA;		    FreeImage_Save(FIF_PNG, img, pathToImage.c_str());&#xD;&#xA;		    myTextures.push_back(Texture(pathToImage.c_str(), GL_TEXTURE0));&#xD;&#xA;	    }&#xD;&#xA;        //create VAO, VBO, EBO for a unit quad.&#xD;&#xA;        &#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;	    glEnable(GL_BLEND);&#xD;&#xA;	    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;&#xD;&#xA;        //game loop&#xD;&#xA;	    while (!glfwWindowShouldClose(window))&#xD;&#xA;     	{&#xD;&#xA;		    ...&#xD;&#xA;		    for (int i = 0; i &lt; myTextures.size(); i++)&#xD;&#xA;		    {&#xD;&#xA;			    GLint index = myTextures.size() - i - 1;&#xD;&#xA;			    myTextures[index].bind(); //does glActiveTexture(...), and glBindTexture(...);&#xD;&#xA;&#xD;&#xA;			    glm::mat4 model;&#xD;&#xA;&#xD;&#xA;			    //translate&#xD;&#xA;			    model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));&#xD;&#xA;&#xD;&#xA;			    //scale&#xD;&#xA;			    model = glm::scale(model, glm::vec3(1.2f));&#xD;&#xA;&#xD;&#xA;			    glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;&#xD;&#xA;			    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;		    }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;`transformValueToColor`for transforming data value in `[0,1]` to color value:&#xD;&#xA;&#xD;&#xA;    //All inputs &gt;=0.6 is transformed to highly transparent white color.&#xD;&#xA;    glm::vec4 transformValueToColor(GLclampf tValue)&#xD;&#xA;    {&#xD;&#xA;	    if (tValue &gt;= 0.6f) {&#xD;&#xA;		    return glm::vec4(255, 255, 255, 10);&#xD;&#xA;	    }&#xD;&#xA;	    else {&#xD;&#xA;		    auto val = round(255 * tValue);&#xD;&#xA;            auto valOp = round(255 * (1 - tValue));&#xD;&#xA;		    return glm::vec4(val, val, val, valOp);&#xD;&#xA;    	}    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 position;&#xD;&#xA;    layout(location = 1) in vec2 texCoord;&#xD;&#xA;&#xD;&#xA;    out vec2 TexCoord;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection * view * model * vec4(position, 1.0f);&#xD;&#xA;    	TexCoord = vec2(texCoord.s, 1-texCoord.t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;&#xD;&#xA;    out vec4 color; &#xD;&#xA;&#xD;&#xA;    uniform sampler2D sliceTexture;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec4 texColor = texture(sliceTexture, TexCoord); &#xD;&#xA;	    color = texColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I think this is the code needed for the blending to work. The images are generated correctly, and also applied as texture on the quads correctly. However, the quads on the front appears as completely opaque, though the generated images (even the one appearing at front) shows transparent area.&#xD;&#xA;&#xD;&#xA;I am not sure where I am going wrong. Requesting your suggestions. &#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="7793" PostHistoryTypeId="1" PostId="3749" RevisionGUID="9edd1f16-cdb2-45c2-8692-0f39219f61d1" CreationDate="2016-07-12T20:56:38.973" UserId="3098" Text="Can't make blending work" ContentLicense="CC BY-SA 3.0" />
  <row Id="7794" PostHistoryTypeId="3" PostId="3749" RevisionGUID="9edd1f16-cdb2-45c2-8692-0f39219f61d1" CreationDate="2016-07-12T20:56:38.973" UserId="3098" Text="|opengl|c++|blending|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7795" PostHistoryTypeId="2" PostId="3750" RevisionGUID="4cfba7f7-ef16-4cb9-a8ea-069bf140ac32" CreationDate="2016-07-13T03:59:42.333" UserId="3003" Text="I notice that you've enabled blending and depth testing and are drawing with a non-opaque alpha channel. What's going to happen is that if you don't draw from back to front (relative to the camera), then any objects you draw that are farther away won't get drawn, so you won't see them through the nearer objects. If you turn off depth testing does it look correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7796" PostHistoryTypeId="5" PostId="3750" RevisionGUID="7b91587a-da9a-47c5-bf56-ab13c839a343" CreationDate="2016-07-13T04:20:08.833" UserId="3003" Comment="Added Depth Peeling link." Text="I notice that you've enabled blending and depth testing and are drawing with a non-opaque alpha channel. What's going to happen is that if you don't draw from back to front (relative to the camera), then any objects you draw that are farther away won't get drawn, so you won't see them through the nearer objects. If you turn off depth testing does it look correct?&#xD;&#xA;&#xD;&#xA;To handle this correctly, you can also use a technique known as [depth peeling](https://en.wikipedia.org/wiki/Depth_peeling)." ContentLicense="CC BY-SA 3.0" />
  <row Id="7797" PostHistoryTypeId="2" PostId="3751" RevisionGUID="b772b76d-6c5e-47df-80f5-7f71a0fe1083" CreationDate="2016-07-13T07:54:40.517" UserId="2817" Text="In order to achieve the &quot;white&quot; glow effect for amassed particles, you should probably switch to HDR rendering and have your tone mapping operator desaturate the &quot;overbright&quot; pixels. So you'll need a higher-precision, floating point render target (e.g. RGBA1010102, or RGBA16F) and a post-process step to bring  that down to the LDR system back-buffer. Then just make sure that your colliding particles add up to a sufficiently high colour value (i.e. over 1.0) and the tone mapper should do the trick.&#xD;&#xA;&#xD;&#xA;You may easily simulate an accumulation buffer by using the ping-pong pattern for your render targets:&#xD;&#xA;&#xD;&#xA;1. Render frame #0 to FBO A.&#xD;&#xA;2. Render frame #1 to FBO B, taking FBO A as history (i.e. hitherto accumulation) input.&#xD;&#xA;3. Render frame #2 to FBO A, taking FBO B as history input.&#xD;&#xA;4. Repeat from point 2.&#xD;&#xA;&#xD;&#xA;In particular, you could have a moving average in order for the particles to leave nice trails like that. Check out Brian Karis's [presentation on Unreal Engine 4's temporal supersampling](https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf) - slides 15-17 describe the moving average-based blend weighting." ContentLicense="CC BY-SA 3.0" />
  <row Id="7798" PostHistoryTypeId="6" PostId="3749" RevisionGUID="ebd91e7b-e827-4aa3-a83c-6f0e9d6bd792" CreationDate="2016-07-13T09:10:03.600" UserId="3098" Comment="edited tags" Text="|opengl|c++|blending|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7799" PostHistoryTypeId="5" PostId="421" RevisionGUID="b580f6c7-c11b-4b37-91ff-f0c7f48586f9" CreationDate="2016-07-13T11:31:33.590" UserId="385" Comment="Fixed some typos" Text="In his classic paper [Ray Tracing with Cones][1], John Amanatides describes a variation on classical ray tracing. By extending the concept of a *ray* by an *aperture angle*, making it a cone, aliasing effects (including those originating from too few Monte Carlo samples) can be reduced.&#xD;&#xA;&#xD;&#xA;During cone-triangle intersection, a scalar coverage value is calculated. This value represents the fraction of the cone that is covered by the triangle. If it is less than $1$, it means that the triangle doesn't fully cover the cone. Further tests are required. Without the usage of more advanced techniques however, we only know how much of the cone is covered, but not which parts.&#xD;&#xA;&#xD;&#xA;Amanatides states:&#xD;&#xA;&gt; Since at present only the fractional coverage value is used in mixing&#xD;&#xA;&gt; the contributions from the various objects, overlapping surfaces will&#xD;&#xA;&gt; be calculated correctly but abutting surfaces will not.&#xD;&#xA;&#xD;&#xA;This does not make sense to me. From my point of view it is the other way around. Let's take an example: We have two *abutting* triangles, a green and a blue one, each of which covers exactly 50% of our cone. They are at the same distance from the viewer.&#xD;&#xA;&#xD;&#xA;[![Green and blue triangle][2]][2]&#xD;&#xA;&#xD;&#xA;The green triangle is tested first. It has a coverage value of 0.5, so the blue triangle is tested next. With the blue one's coverage value of 0.5 our cone is fully covered, so we're done and end up with a 50:50 green-blue mixture. Great!&#xD;&#xA;&#xD;&#xA;Now imagine that we kill the blue triangle and add a red one some distance behind the green one - *overlapping*. Greeny gives us a coverage value of 0.5 again. Since we don't have the blue one to test anymore we look further down the cone and soon find the red one. This too returns some coverage value greater than 0, which it shouldn't because it is *behind* the green one.&#xD;&#xA;&#xD;&#xA;So, from this I conclude that abutting triangles work fine, while overlapping triangles would need some more magic like coverage masks to be correct. This is the opposite of what Amanatides says. Did I misunderstand something or is this a slip in the paper?&#xD;&#xA;&#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.32.6170&#xD;&#xA;  [2]: https://i.stack.imgur.com/n5JTo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7800" PostHistoryTypeId="5" PostId="3749" RevisionGUID="4d9a314e-deba-4a0d-8a36-74b0ae00f325" CreationDate="2016-07-13T16:30:33.297" UserId="3098" Comment="Added details of view and projection matrix" Text="I have a 3 dimensional dataset where each value of the dataset is normalized to `[0, 1]`. I want to visualize this dataset by using texture, and blending.&#xD;&#xA;However, it seems that I can't make it work.&#xD;&#xA;&#xD;&#xA;Here is what I have done so far:&#xD;&#xA;&#xD;&#xA;    int main(){&#xD;&#xA;        ...&#xD;&#xA;        //building an image for each rectangular slice of data&#xD;&#xA;        vector&lt;Texture&gt; myTextures;&#xD;&#xA;        for (GLint rowIndex = 0; rowIndex &lt; ROW_NUM; rowIndex++)&#xD;&#xA;	    {&#xD;&#xA;		    auto pathToImage = &quot;images/row&quot; + to_string(rowIndex) + FILE_EXT;&#xD;&#xA;		    FIBITMAP *img = FreeImage_Allocate(SLICE_DIMENSION, SLICE_NUM, 32); //32 = RGBA&#xD;&#xA;&#xD;&#xA;		    for (GLint depthIndex = 0; depthIndex &lt; DEPTH_NUM; depthIndex++)&#xD;&#xA;		    {&#xD;&#xA;			    for (GLint colIndex = 0; colIndex &lt; COL_NUM; colIndex++)&#xD;&#xA;    			{&#xD;&#xA;				    auto value = my3DData[depthIndex][rowIndex][colIndex];&#xD;&#xA;&#xD;&#xA;				    //transform tValue to a source color&#xD;&#xA;				    glm::vec4 source = transformValueToColor(value);&#xD;&#xA;&#xD;&#xA;                    //note that here I am also setting the opacity. &#xD;&#xA;				    RGBQUAD linRgb = { source.b, source.g, source.r, source.a }; &#xD;&#xA;				    FreeImage_SetPixelColor(img, colIndex, depthIndex, &amp;linRgb);&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;&#xD;&#xA;            //Saving images. Saved images shows transparency. &#xD;&#xA;		    FreeImage_Save(FIF_PNG, img, pathToImage.c_str());&#xD;&#xA;		    myTextures.push_back(Texture(pathToImage.c_str(), GL_TEXTURE0));&#xD;&#xA;	    }&#xD;&#xA;        //create VAO, VBO, EBO for a unit quad.&#xD;&#xA;        &#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;	    glEnable(GL_BLEND);&#xD;&#xA;	    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;&#xD;&#xA;        //game loop&#xD;&#xA;	    while (!glfwWindowShouldClose(window))&#xD;&#xA;     	{&#xD;&#xA;		    ...&#xD;&#xA;		    for (int i = 0; i &lt; myTextures.size(); i++)&#xD;&#xA;		    {&#xD;&#xA;			    GLint index = myTextures.size() - i - 1;&#xD;&#xA;			    myTextures[index].bind(); //does glActiveTexture(...), and glBindTexture(...);&#xD;&#xA;&#xD;&#xA;			    glm::mat4 model;&#xD;&#xA;&#xD;&#xA;			    //translate&#xD;&#xA;			    model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));&#xD;&#xA;&#xD;&#xA;			    //scale&#xD;&#xA;			    model = glm::scale(model, glm::vec3(1.2f));&#xD;&#xA;&#xD;&#xA;			    glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;&#xD;&#xA;			    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;		    }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;`transformValueToColor`for transforming data value in `[0,1]` to color value:&#xD;&#xA;&#xD;&#xA;    //All inputs &gt;=0.6 is transformed to highly transparent white color.&#xD;&#xA;    glm::vec4 transformValueToColor(GLclampf tValue)&#xD;&#xA;    {&#xD;&#xA;	    if (tValue &gt;= 0.6f) {&#xD;&#xA;		    return glm::vec4(255, 255, 255, 10);&#xD;&#xA;	    }&#xD;&#xA;	    else {&#xD;&#xA;		    auto val = round(255 * tValue);&#xD;&#xA;            auto valOp = round(255 * (1 - tValue));&#xD;&#xA;		    return glm::vec4(val, val, val, valOp);&#xD;&#xA;    	}    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 position;&#xD;&#xA;    layout(location = 1) in vec2 texCoord;&#xD;&#xA;&#xD;&#xA;    out vec2 TexCoord;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection * view * model * vec4(position, 1.0f);&#xD;&#xA;    	TexCoord = vec2(texCoord.s, 1-texCoord.t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;&#xD;&#xA;    out vec4 color; &#xD;&#xA;&#xD;&#xA;    uniform sampler2D sliceTexture;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec4 texColor = texture(sliceTexture, TexCoord); &#xD;&#xA;	    color = texColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I think this is the code needed for the blending to work. The images are generated correctly, and also applied as texture on the quads correctly. However, the quads on the front appears as completely opaque, though the generated images (even the one appearing at front) shows transparent area.&#xD;&#xA;&#xD;&#xA;I am not sure where I am going wrong. Requesting your suggestions. &#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;**Edit** &#xD;&#xA;&#xD;&#xA;Details of camera class. `Camera::getViewMatrix()` provides `view` matrix.&#xD;&#xA;&#xD;&#xA;    Camera::Camera(GLFWwindow* window, glm::vec3 position, glm::vec3 worldUpDirection, GLfloat yaw, GLfloat pitch)&#xD;&#xA;		:mouseSensitivity(0.25f), fov(45.0f), cameraSpeed(1.0f)&#xD;&#xA;	{&#xD;&#xA;		this-&gt;position = this-&gt;originalPosition = position;&#xD;&#xA;		this-&gt;worldUpDirection = worldUpDirection;&#xD;&#xA;		this-&gt;yaw = this-&gt;originalYaw = yaw;&#xD;&#xA;		this-&gt;pitch = this-&gt;originalPitch = pitch;&#xD;&#xA;&#xD;&#xA;		updateCameraVectors();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void Camera::updateCameraVectors()&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 yawPitchRotMat;&#xD;&#xA;&#xD;&#xA;		yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(yaw), glm::vec3(0.0f, 1.0f, 0.0f));		//y-ais as yaw axis&#xD;&#xA;		yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(pitch), glm::vec3(1.0f, 0.0f, 0.0f));		//x-axis as pitch axis&#xD;&#xA;&#xD;&#xA;		frontDirection = glm::normalize(-glm::vec3(yawPitchRotMat[2].x, yawPitchRotMat[2].y, yawPitchRotMat[2].z));&#xD;&#xA;&#xD;&#xA;		rightDirection = glm::normalize(glm::cross(frontDirection, worldUpDirection));&#xD;&#xA;		upDirection = glm::normalize(glm::cross(rightDirection, frontDirection));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	glm::mat4 Camera::getViewMatrix()&#xD;&#xA;	{&#xD;&#xA;		return glm::lookAt(position, position + frontDirection, upDirection);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;And the `projection` matrix is given by: `glm::perspective(glm::radians(camera.fov), Width / Height, 0.1f, 100.0f);`" ContentLicense="CC BY-SA 3.0" />
  <row Id="7801" PostHistoryTypeId="2" PostId="3752" RevisionGUID="59959cbc-04e3-4f71-a4a6-03c8d994f0c4" CreationDate="2016-07-13T16:50:17.123" UserId="4735" Text="I'm not really sure if this is possible but it should be.&#xD;&#xA;&#xD;&#xA;I currently have a photo of a sphere, whose radius I've measures physically. Knowing the apparent size of the sphere from the photo and all internal camera parameters is it possible to estimate the distance from the camera to the sphere?&#xD;&#xA;&#xD;&#xA;There is an equation, more used in lens imaging that is useful:&#xD;&#xA;&#xD;&#xA;object_image_size = (real_object_size * lens_focal_length)/object distance&#xD;&#xA;&#xD;&#xA;Problem is my object_image_size is in pixels and I need to convert it to a real world measure, preferable the size that actually showed up on the sensor. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7802" PostHistoryTypeId="1" PostId="3752" RevisionGUID="59959cbc-04e3-4f71-a4a6-03c8d994f0c4" CreationDate="2016-07-13T16:50:17.123" UserId="4735" Text="Estimating real world object distance from photo" ContentLicense="CC BY-SA 3.0" />
  <row Id="7803" PostHistoryTypeId="3" PostId="3752" RevisionGUID="59959cbc-04e3-4f71-a4a6-03c8d994f0c4" CreationDate="2016-07-13T16:50:17.123" UserId="4735" Text="|mathematics|pixels|conversion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7804" PostHistoryTypeId="2" PostId="3753" RevisionGUID="8a033bed-5cde-4ee7-abc3-c7fb7ca47c2e" CreationDate="2016-07-13T17:40:43.970" UserId="38" Text="Yes for the sphere no for other things in image, but if it is possible to augment the situation then it is possible to measure anything you can track. First, knowing the scale of a object that you can successfully track is a requirement to getting a scale for the image as cameras lose all scaling info. But this requirement alone is not enough.&#xD;&#xA;&#xD;&#xA;One way is to have two photos from different angles in a scene with enough depth variation. You can then use stereo geometry to solve the depth many such tracker apps exist as part special effects packages and making your own is not entirely out of the question (fun link, [fundamental matrix song](https://www.youtube.com/watch?v=DgGV3l82NTk)). The second way is to have a known plane, the plane can be solved by knowing 4 points and their relative locations. A third way is to use structured light (a cloud of laser light points, or a line for example) to triangulate the point distances. Or you could use a light field camera." ContentLicense="CC BY-SA 3.0" />
  <row Id="7805" PostHistoryTypeId="5" PostId="3753" RevisionGUID="ad7ae163-549f-4e87-8745-fca6afe7ba6b" CreationDate="2016-07-13T17:50:09.873" UserId="38" Comment="added 428 characters in body" Text="Yes, theoretically, for the sphere no for other things in image. If it is possible to augment the situation then it is possible to measure anything you can track much more reliably. First, knowing the scale of a object that you can successfully track is a requirement to getting a scale for the image as the cameras lost all scaling info. But this requirement alone is not enough.&#xD;&#xA;&#xD;&#xA;In practice you do not know the other settings of a camera (unless calibrated with stereo geometry first), all kinds of problems arise when you do real camera tracking. Such as real cameras not being ideal. By tracking more than 2 features on the scene you can automatically estimate the actual focal distances and camera distortions. More importantly you can get an error estimate on your data.&#xD;&#xA;&#xD;&#xA;One way is to have two photos from different angles in a scene with enough depth variation (for a stationary object this is quite easy). You can then use stereo geometry to solve the depth many such tracker apps exist as part special effects packages and making your own is not entirely out of the question (fun link, [fundamental matrix song](https://www.youtube.com/watch?v=DgGV3l82NTk)). The second way is to have a known plane, the plane can be solved by knowing 4 points and their relative locations. In reality it is better use more points for error and lens correction estimates. A third way is to use structured light (a cloud of laser light points, or a line for example) to triangulate the point distances. Or you could use a light field camera." ContentLicense="CC BY-SA 3.0" />
  <row Id="7809" PostHistoryTypeId="5" PostId="3750" RevisionGUID="0d9712f8-547e-4ded-8ea6-36756adc4098" CreationDate="2016-07-14T04:35:28.220" UserId="3003" Comment="Added edit about view matrix and z-fighting" Text="I notice that you've enabled blending and depth testing and are drawing with a non-opaque alpha channel. What's going to happen is that if you don't draw from back to front (relative to the camera), then any objects you draw that are farther away won't get drawn, so you won't see them through the nearer objects. If you turn off depth testing does it look correct?&#xD;&#xA;&#xD;&#xA;To handle this correctly, you can also use a technique known as [depth peeling](https://en.wikipedia.org/wiki/Depth_peeling).&#xD;&#xA;&#xD;&#xA;**EDIT** I see how you calculate your view matrix, but I don't see any code calling it, so it's hard to say whether your camera is pointing in the right direction or not for this to work as expected.&#xD;&#xA;&#xD;&#xA;One other thing I notice is that your projection matrix sets the near plane to 0.1, but you're translating your geometry in increments of -0.003. If your camera is at the origin (i.e. your view matrix has a translation of &lt;0,0,0&gt;), then you won't see any layers until you get to the 34th layer. Also, with such small increments between the layers, you may end up with [Z-fighting](https://en.wikipedia.org/wiki/Z-fighting), as well.&#xD;&#xA;&#xD;&#xA;You might try hard-coding your loop to display just a single layer and make sure each layer is drawn correctly when drawn alone. Once you've verified that, you can figure out why drawing more than 1 layer doesn't work as expected." ContentLicense="CC BY-SA 3.0" />
  <row Id="7810" PostHistoryTypeId="2" PostId="3755" RevisionGUID="d670d181-e05b-4d69-a9ae-f94fdbab8be9" CreationDate="2016-07-14T05:02:41.603" UserId="3003" Text="I may be misunderstanding what you're asking, but if you know the sensor size and the number of pixels in the object, then you can calculate the object size. For example, a [Canon 7D](http://www.dpreview.com/products/canon/slrs/canon_eos7d/specifications) has an APS-C sensor that's 22.3 x 14.9mm and 5184 x 3456 pixels. That works out to ~0.0043mm/pixel. So if you have an object that's 250 pixels wide, then the projection of the object onto the sensor would have been 250 pixels * 0.0043mm/pixel = 1.075mm wide." ContentLicense="CC BY-SA 3.0" />
  <row Id="7811" PostHistoryTypeId="5" PostId="3753" RevisionGUID="014dc803-2163-47db-8679-1d920ca87573" CreationDate="2016-07-14T19:15:13.060" UserId="38" Comment="added 5 characters in body" Text="Yes, theoretically, for the sphere no for other things in image. If it is possible to augment the situation then it is possible to measure anything you can track much more reliably. First, knowing the scale of a object that you can successfully track is a requirement to getting a scale for the image as the cameras lost all scaling info. But this requirement alone is not enough.&#xD;&#xA;&#xD;&#xA;In practice you do not know the other settings of a camera (unless calibrated with stereo geometry first), all kinds of problems arise when you do real camera tracking. Such as real cameras lens not being ideal. By tracking more than 2 features on the scene you can automatically estimate the actual focal distances and camera distortions. More importantly you can get an error estimate on your data.&#xD;&#xA;&#xD;&#xA;One way is to have two photos from different angles in a scene with enough depth variation (for a stationary object this is quite easy). You can then use stereo geometry to solve the depth many such tracker apps exist as part special effects packages and making your own is not entirely out of the question (fun link, [fundamental matrix song](https://www.youtube.com/watch?v=DgGV3l82NTk)). The second way is to have a known plane, the plane can be solved by knowing 4 points and their relative locations. In reality it is better use more points for error and lens correction estimates. A third way is to use structured light (a cloud of laser light points, or a line for example) to triangulate the point distances. Or you could use a light field camera." ContentLicense="CC BY-SA 3.0" />
  <row Id="7813" PostHistoryTypeId="5" PostId="3755" RevisionGUID="a2052772-747d-4f08-9b0f-dde2d27d5cee" CreationDate="2016-07-15T02:32:58.797" UserId="3003" Comment="Added the results of my experiment." Text="I may be misunderstanding what you're asking, but if you know the sensor size and the number of pixels in the object, then you can calculate the object size. For example, a [Canon 7D](http://www.dpreview.com/products/canon/slrs/canon_eos7d/specifications) has an APS-C sensor that's 22.3 x 14.9mm and 5184 x 3456 pixels. That works out to ~0.0043mm/pixel. So if you have an object that's 250 pixels wide, then the projection of the object onto the sensor would have been 250 pixels * 0.0043mm/pixel = 1.075mm wide.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;So just for fun, I gave this a try. I took a 300mm ruler, put it at 1 meter from the camera and shot it with a 50mm lens on a Canon 7D. According to the ruler tool in Photoshop, it was 3734 pixels wide. That gives me the following equation:&#xD;&#xA;&#xD;&#xA;3734 * 0.0043 = (300 * 50) / 1000&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;16.0562 = 15.0&#xD;&#xA;&#xD;&#xA;Well, it's close, but not exact. (Over by 7%.) My guess is that the sensor site size is actually slightly smaller than 0.0043mm or the sensor size is slightly bigger than the reported size. In fact, the specs for the camera say 18MP effective size, but 19MP actual sensor size. So I'm not sure what that means, but I'm guessing it explains the difference between my actual result and the calculated result. (Either that or I'm misreading the length in Photoshop and it should actually be 3488 pixels instead of 3734.) But it was fun to try!" ContentLicense="CC BY-SA 3.0" />
  <row Id="7814" PostHistoryTypeId="5" PostId="3755" RevisionGUID="a0a3d16e-51b4-4976-832b-93aef2904bcd" CreationDate="2016-07-15T02:50:37.330" UserId="3003" Comment="Added link to Photo Stack Exchange explaining the difference" Text="I may be misunderstanding what you're asking, but if you know the sensor size and the number of pixels in the object, then you can calculate the object size. For example, a [Canon 7D](http://www.dpreview.com/products/canon/slrs/canon_eos7d/specifications) has an APS-C sensor that's 22.3 x 14.9mm and 5184 x 3456 pixels. That works out to ~0.0043mm/pixel. So if you have an object that's 250 pixels wide, then the projection of the object onto the sensor would have been 250 pixels * 0.0043mm/pixel = 1.075mm wide.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;So just for fun, I gave this a try. I took a 300mm ruler, put it at 1 meter from the camera and shot it with a 50mm lens on a Canon 7D. According to the ruler tool in Photoshop, it was 3734 pixels wide. That gives me the following equation:&#xD;&#xA;&#xD;&#xA;3734 * 0.0043 = (300 * 50) / 1000&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;16.0562 = 15.0&#xD;&#xA;&#xD;&#xA;Well, it's close, but not exact. (Over by 7%.) My guess is that the sensor site size is actually slightly smaller than 0.0043mm or the sensor size is slightly bigger than the reported size. In fact, the specs for the camera say 18MP effective size, but 19MP actual sensor size. So I'm not sure what that means, but I'm guessing it explains the difference between my actual result and the calculated result. (Either that or I'm misreading the length in Photoshop and it should actually be 3488 pixels instead of 3734.) But it was fun to try!&#xD;&#xA;&#xD;&#xA;**2nd EDIT:** [This question on the Photo Stack Exchange](http://photo.stackexchange.com/questions/69582/why-isnt-my-computation-of-the-actual-size-of-an-object-in-a-photograph-matchin) explains it. Camera lenses are often slightly longer or shorter than claimed, but rounded to the nearest nice focal length. So (assuming my calculations and measurements were correct) my lens is actually a ~53.5mm lens." ContentLicense="CC BY-SA 3.0" />
  <row Id="7815" PostHistoryTypeId="2" PostId="3756" RevisionGUID="9b1cb0a9-47df-414d-9151-9ade881f248b" CreationDate="2016-07-15T05:27:57.677" UserId="3386" Text="Perspective correct interpolation of normals works just as it does any color or coordinate or other linearly varying attribute. Each component of each varying vector is interpolated independently as if they were scalars, using exactly the same equation. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7816" PostHistoryTypeId="2" PostId="3757" RevisionGUID="d9f25cb7-c8cd-4a46-b492-53e6080e13b5" CreationDate="2016-07-15T09:00:02.467" UserId="2941" Text="I'm Learning about BRDFs and wondering why the BRDF is defined as the ratio of outgoing radiance to a given direction and incoming irradiance from another direction. Why isn't the BRDF defined as ratio of radiances?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7817" PostHistoryTypeId="1" PostId="3757" RevisionGUID="d9f25cb7-c8cd-4a46-b492-53e6080e13b5" CreationDate="2016-07-15T09:00:02.467" UserId="2941" Text="Why isn't a BRDF a ratio of radiances?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7818" PostHistoryTypeId="3" PostId="3757" RevisionGUID="d9f25cb7-c8cd-4a46-b492-53e6080e13b5" CreationDate="2016-07-15T09:00:02.467" UserId="2941" Text="|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7819" PostHistoryTypeId="2" PostId="3758" RevisionGUID="ec5ca046-b2f8-44ab-aeb6-22bc2232c5ba" CreationDate="2016-07-15T10:00:11.443" UserId="385" Text="I am trying to implement [Ray Tracing with Cones (Amanatides 1984)][1]. Instead of rays, cones are shot into the scene and intersected with geometry. Since multiple triangles can occupy the cone's aperture, we need to calculate (or rather quickly estimate, since cone tracing makes a lot of approximations anyway) the relative area of the circle that is covered by the triangle. Afterwards, the individual contributions are weighted and summed up.&#xD;&#xA;&#xD;&#xA;The author, unfortunately, does not give a lot of detail about his solution. Here is what he writes on cone-plane intersections:&#xD;&#xA;&#xD;&#xA;&gt; The spread angle and the angle between the ray and plane computed&#xD;&#xA;&gt; above together indicate how the distance between the center of the&#xD;&#xA;&gt; circle and the edge of the half plane [sic]. Given this distance, the area&#xD;&#xA;&gt; of intersection is computed using a polynomial approximation. This&#xD;&#xA;&gt; completes the intersection calculation for planes.&#xD;&#xA;&#xD;&#xA;And then, after projecting a polygon to the plane perpendicular to the&#xD;&#xA;direction vector of the cone:&#xD;&#xA;&#xD;&#xA;&gt; We then must calculate the intersection between the projected polygon&#xD;&#xA;&gt; and a circle. This can be accomplished by calculating the distance&#xD;&#xA;&gt; from the center of the circle to each of the edges and then using the&#xD;&#xA;&gt; circle - half plane intersection estimation mentioned earlier.&#xD;&#xA;&#xD;&#xA;I found [a solution to the problem][2] over at StackExchange. I have ported the code from [NowIGetToLearnWhatAHeadIs' answer][3], and it works fine, but seems pretty complicated to me. I am working with Compute Shaders, so branching is a bad thing, and the solutions rely heavily on it.&#xD;&#xA;&#xD;&#xA; 1. What is this *polynomial approximation* that Amanatides talks about, and how is it to be applied to polygons (espc. triangles)?&#xD;&#xA; 2. Is there any approximation to the problem that will give resonably accurate results (say ±10%) at considerable performance / code simplicity gains?&#xD;&#xA; 3. Working with GPUs, I am interested in an optimized solution that uses min/max over branching, for example. Maybe something like this already exists. Any luck?&#xD;&#xA;&#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.32.6170&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [2]: http://Compute%20the%20area%20of%20intersection%20between%20a%20circle%20and%20a%20triangle?&#xD;&#xA;  [3]: http://stackoverflow.com/a/22420313/776142" ContentLicense="CC BY-SA 3.0" />
  <row Id="7820" PostHistoryTypeId="1" PostId="3758" RevisionGUID="ec5ca046-b2f8-44ab-aeb6-22bc2232c5ba" CreationDate="2016-07-15T10:00:11.443" UserId="385" Text="Estimating the area of a triangle-circle intersection" ContentLicense="CC BY-SA 3.0" />
  <row Id="7821" PostHistoryTypeId="3" PostId="3758" RevisionGUID="ec5ca046-b2f8-44ab-aeb6-22bc2232c5ba" CreationDate="2016-07-15T10:00:11.443" UserId="385" Text="|raytracing|performance|computational-geometry|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7822" PostHistoryTypeId="2" PostId="3759" RevisionGUID="5482d13b-78da-4870-ba47-4a19489a6c22" CreationDate="2016-07-15T12:57:23.850" UserId="38" Text="Working Towards an Exact solution&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;Just some quick thought before I must run!&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Ok,  let us turn the problem on its head what if one does not calculate the area of the triangle cut by circle. Instead lets calculate the inverse of this. The area of three segments cut out of the circle. The beauty of this approach is that if we can make single piece of code that we can repeat three times. Off course some of the time the answer will be 0 but that is OK.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Lets calculate this problem instead&#xD;&#xA;&#xD;&#xA;Now it urns out we know how to calculate the inverse, it is the segment of of a circle.  So we can just say that $A_{int}=A_{circle}-A_1-A_2-A_3$. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: We know this solution.&#xD;&#xA;&#xD;&#xA;The formula for the area of a segment is simply $A_{sector}-A_{triange}$ And that has a well known solution in literature. &#xD;&#xA;&#xD;&#xA;So now all you need to do is find the intersections between edges and circle in a space centered on circle calculate the angle between those and then calculate each segment. And the only special case is if no intersection exists. I dont know is this is fast but at least code should be somewhat easy to implement.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ou8QT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/kE7Wa.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7823" PostHistoryTypeId="5" PostId="3749" RevisionGUID="f5994ed2-82a7-443a-b65a-ea8f8b2b9d81" CreationDate="2016-07-15T19:46:08.067" UserId="3098" Comment="added 420 characters in body" Text="I have a 3 dimensional dataset where each value of the dataset is normalized to `[0, 1]`. I want to visualize this dataset by using texture, and blending.&#xD;&#xA;However, it seems that I can't make it work.&#xD;&#xA;&#xD;&#xA;Here is what I have done so far:&#xD;&#xA;&#xD;&#xA;    int main(){&#xD;&#xA;        ...&#xD;&#xA;        //building an image for each rectangular slice of data&#xD;&#xA;        vector&lt;Texture&gt; myTextures;&#xD;&#xA;        for (GLint rowIndex = 0; rowIndex &lt; ROW_NUM; rowIndex++)&#xD;&#xA;	    {&#xD;&#xA;		    auto pathToImage = &quot;images/row&quot; + to_string(rowIndex) + FILE_EXT;&#xD;&#xA;		    FIBITMAP *img = FreeImage_Allocate(SLICE_DIMENSION, SLICE_NUM, 32); //32 = RGBA&#xD;&#xA;&#xD;&#xA;		    for (GLint depthIndex = 0; depthIndex &lt; DEPTH_NUM; depthIndex++)&#xD;&#xA;		    {&#xD;&#xA;			    for (GLint colIndex = 0; colIndex &lt; COL_NUM; colIndex++)&#xD;&#xA;    			{&#xD;&#xA;				    auto value = my3DData[depthIndex][rowIndex][colIndex];&#xD;&#xA;&#xD;&#xA;				    //transform tValue to a source color&#xD;&#xA;				    glm::vec4 source = transformValueToColor(value);&#xD;&#xA;&#xD;&#xA;                    //note that here I am also setting the opacity. &#xD;&#xA;				    RGBQUAD linRgb = { source.b, source.g, source.r, source.a }; &#xD;&#xA;				    FreeImage_SetPixelColor(img, colIndex, depthIndex, &amp;linRgb);&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;&#xD;&#xA;            //Saving images. Saved images shows transparency. &#xD;&#xA;		    FreeImage_Save(FIF_PNG, img, pathToImage.c_str());&#xD;&#xA;		    myTextures.push_back(Texture(pathToImage.c_str(), GL_TEXTURE0));&#xD;&#xA;	    }&#xD;&#xA;        //create VAO, VBO, EBO for a unit quad.&#xD;&#xA;        &#xD;&#xA;        glEnable(GL_DEPTH_TEST);&#xD;&#xA;	    glEnable(GL_BLEND);&#xD;&#xA;	    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;&#xD;&#xA;        //game loop&#xD;&#xA;	    while (!glfwWindowShouldClose(window))&#xD;&#xA;     	{&#xD;&#xA;		    ...&#xD;&#xA;		    for (int i = 0; i &lt; myTextures.size(); i++)&#xD;&#xA;		    {&#xD;&#xA;			    GLint index = myTextures.size() - i - 1;&#xD;&#xA;			    myTextures[index].bind(); //does glActiveTexture(...), and glBindTexture(...);&#xD;&#xA;&#xD;&#xA;			    glm::mat4 model;&#xD;&#xA;&#xD;&#xA;			    //translate&#xD;&#xA;			    model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));&#xD;&#xA;&#xD;&#xA;			    //scale&#xD;&#xA;			    model = glm::scale(model, glm::vec3(1.2f));&#xD;&#xA;&#xD;&#xA;			    glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;&#xD;&#xA;			    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;		    }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;`transformValueToColor`for transforming data value in `[0,1]` to color value:&#xD;&#xA;&#xD;&#xA;    //All inputs &gt;=0.6 is transformed to highly transparent white color.&#xD;&#xA;    glm::vec4 transformValueToColor(GLclampf tValue)&#xD;&#xA;    {&#xD;&#xA;	    if (tValue &gt;= 0.6f) {&#xD;&#xA;		    return glm::vec4(255, 255, 255, 10);&#xD;&#xA;	    }&#xD;&#xA;	    else {&#xD;&#xA;		    auto val = round(255 * tValue);&#xD;&#xA;            auto valOp = round(255 * (1 - tValue));&#xD;&#xA;		    return glm::vec4(val, val, val, valOp);&#xD;&#xA;    	}    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 position;&#xD;&#xA;    layout(location = 1) in vec2 texCoord;&#xD;&#xA;&#xD;&#xA;    out vec2 TexCoord;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position = projection * view * model * vec4(position, 1.0f);&#xD;&#xA;    	TexCoord = vec2(texCoord.s, 1-texCoord.t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;&#xD;&#xA;    out vec4 color; &#xD;&#xA;&#xD;&#xA;    uniform sampler2D sliceTexture;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec4 texColor = texture(sliceTexture, TexCoord); &#xD;&#xA;	    color = texColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I think this is the code needed for the blending to work. The images are generated correctly, and also applied as texture on the quads correctly. However, the quads on the front appears as completely opaque, though the generated images (even the one appearing at front) shows transparent area.&#xD;&#xA;&#xD;&#xA;I am not sure where I am going wrong. Requesting your suggestions. &#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;**Edit** &#xD;&#xA;&#xD;&#xA;Details of camera class. `Camera::getViewMatrix()` provides `view` matrix.&#xD;&#xA;&#xD;&#xA;    Camera::Camera(GLFWwindow* window, glm::vec3 position, glm::vec3 worldUpDirection, GLfloat yaw, GLfloat pitch)&#xD;&#xA;		:mouseSensitivity(0.25f), fov(45.0f), cameraSpeed(1.0f)&#xD;&#xA;	{&#xD;&#xA;		this-&gt;position = this-&gt;originalPosition = position;&#xD;&#xA;		this-&gt;worldUpDirection = worldUpDirection;&#xD;&#xA;		this-&gt;yaw = this-&gt;originalYaw = yaw;&#xD;&#xA;		this-&gt;pitch = this-&gt;originalPitch = pitch;&#xD;&#xA;&#xD;&#xA;		updateCameraVectors();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void Camera::updateCameraVectors()&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 yawPitchRotMat;&#xD;&#xA;&#xD;&#xA;		yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(yaw), glm::vec3(0.0f, 1.0f, 0.0f));		//y-ais as yaw axis&#xD;&#xA;		yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(pitch), glm::vec3(1.0f, 0.0f, 0.0f));		//x-axis as pitch axis&#xD;&#xA;&#xD;&#xA;		frontDirection = glm::normalize(-glm::vec3(yawPitchRotMat[2].x, yawPitchRotMat[2].y, yawPitchRotMat[2].z));&#xD;&#xA;&#xD;&#xA;		rightDirection = glm::normalize(glm::cross(frontDirection, worldUpDirection));&#xD;&#xA;		upDirection = glm::normalize(glm::cross(rightDirection, frontDirection));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	glm::mat4 Camera::getViewMatrix()&#xD;&#xA;	{&#xD;&#xA;		return glm::lookAt(position, position + frontDirection, upDirection);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;And the `projection` matrix is given by: `glm::perspective(glm::radians(camera.fov), Width / Height, 0.1f, 100.0f);`&#xD;&#xA;&#xD;&#xA;**Update:** In short, blending was working all along. I followed the advice of user1118321, tested with only 2 textures, and found that it is working. Then I understood that a good part of images appearing on front was opaque. After that it was easy. I just manipulated with the transformation function `transformValueToColor`, added additional threshold to make additional part of the image opaque. And that was it." ContentLicense="CC BY-SA 3.0" />
  <row Id="7824" PostHistoryTypeId="2" PostId="3760" RevisionGUID="0c22d205-be99-48c3-92eb-4620b128193d" CreationDate="2016-07-15T23:49:56.603" UserId="4747" Text="this seemed like an appropriate place to ask my question, so here it goes. I'm trying to triangulate complex 3D objects, that may have holes in them. Now I tried going over the problem myself, after a few hours I didn't get anything that would work all of the time, so I've been searching around and without much luck. Does anyone know of any algorithms, or free libraries, that would suit my needs. Links to any relevant documentation would be appreciated as well. Thanks!&#xD;&#xA;&#xD;&#xA;Also as a note, I'm a self taught programmer/cs-tist. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7825" PostHistoryTypeId="1" PostId="3760" RevisionGUID="0c22d205-be99-48c3-92eb-4620b128193d" CreationDate="2016-07-15T23:49:56.603" UserId="4747" Text="Computational Geometry - Triangulation" ContentLicense="CC BY-SA 3.0" />
  <row Id="7826" PostHistoryTypeId="3" PostId="3760" RevisionGUID="0c22d205-be99-48c3-92eb-4620b128193d" CreationDate="2016-07-15T23:49:56.603" UserId="4747" Text="|computational-geometry|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7827" PostHistoryTypeId="2" PostId="3761" RevisionGUID="218ff35c-8ad9-44f6-80f0-1c8292449b3a" CreationDate="2016-07-16T01:18:44.440" UserId="4748" Text="What it means to &quot;triangulate complex 3D objects&quot; is not unambiguous.&#xD;&#xA;Just one possible interpretation: You have a 3D polygon in space, and you&#xD;&#xA;want to triangulate that. This is NP-hard:&#xD;&#xA;&#xD;&#xA;&gt; Barequet, Gill, Matthew Dickerson, and David Eppstein. &quot;On triangulating three-dimensional polygons.&quot; *Proceedings of the 12th Symposium on Computational Geometry*. ACM, 1996. ([ACM link](http://dl.acm.org/citation.cfm?id=237234&amp;dl=ACM&amp;coll=DL&amp;CFID=644220912&amp;CFTOKEN=23394613).)&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/PeHXb.png&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PeHXb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7830" PostHistoryTypeId="5" PostId="3759" RevisionGUID="42ad3e48-92c6-4692-aefc-659f9e2a6e5d" CreationDate="2016-07-16T12:18:25.760" UserId="231" Comment="Minor typos - please revert anything that changes your intention " Text="Working Towards an Exact solution&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;Just some quick thought before I must run!&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Ok, let us turn the problem on its head. What if one does not calculate the area of the triangle cut by the circle. Instead let's calculate the inverse of this. The area of three segments cut out of the circle. The beauty of this approach is that we can make a single piece of code that we can repeat three times. Of course some of the time the answer will be 0 but that is OK.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Let's calculate this problem instead.&#xD;&#xA;&#xD;&#xA;Now it turns out we know how to calculate the inverse, it is the segment of a circle.  So we can just say that $A_{int}=A_{circle}-A_1-A_2-A_3$. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: We know this solution.&#xD;&#xA;&#xD;&#xA;The formula for the area of a segment is simply $A_{sector}-A_{triangle}$ and that has a well known solution in literature. &#xD;&#xA;&#xD;&#xA;So now all you need to do is find the intersections between the edges and the circle in a space centered on the circle, calculate the angle between those and then calculate each segment. And the only special case is if no intersection exists. I dont know if this is fast but at least code should be somewhat easy to implement.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ou8QT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/kE7Wa.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7832" PostHistoryTypeId="5" PostId="3760" RevisionGUID="05c27f0a-5bbd-4abb-a160-bbe9dd890b29" CreationDate="2016-07-17T07:50:05.510" UserId="4749" Comment="Extra information" Text="this seemed like an appropriate place to ask my question, so here it goes. I'm trying to triangulate complex 3D objects, that may have holes in them. Now I tried going over the problem myself, after a few hours I didn't get anything that would work all of the time, so I've been searching around and without much luck. Does anyone know of any algorithms, or free libraries, that would suit my needs. Links to any relevant documentation would be appreciated as well. Thanks!&#xD;&#xA;&#xD;&#xA;Also as a note, I'm a self taught programmer/cs-tist. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;edit: I have a set of points and I need to provide a game engine the shape in triangles. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7833" PostHistoryTypeId="24" PostId="3760" RevisionGUID="05c27f0a-5bbd-4abb-a160-bbe9dd890b29" CreationDate="2016-07-17T07:50:05.510" Comment="Proposed by 4749 approved by 273, -1 edit id of 152" ContentLicense="CC BY-SA 3.0" />
  <row Id="7834" PostHistoryTypeId="5" PostId="3760" RevisionGUID="6c0780d7-614c-4a17-a8cb-8b510664b1eb" CreationDate="2016-07-17T07:50:05.510" UserId="231" Comment="Remove &quot;edit&quot; label as history is available. " Text="I'm trying to triangulate complex 3D objects, that may have holes in them. Now I tried going over the problem myself, after a few hours I didn't get anything that would work all of the time, so I've been searching around and without much luck. Does anyone know of any algorithms, or free libraries, that would suit my needs. Links to any relevant documentation would be appreciated as well.&#xD;&#xA;&#xD;&#xA;Also as a note, I'm a self taught programmer/cs-tist. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a set of points and I need to provide a game engine the shape in triangles. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7841" PostHistoryTypeId="5" PostId="3760" RevisionGUID="234be34e-edea-4130-bba3-9a342ad73514" CreationDate="2016-07-17T19:26:44.807" UserId="4749" Comment="More information" Text="I'm trying to triangulate complex 3D objects, that may have holes in them. Now I tried going over the problem myself, after a few hours I didn't get anything that would work all of the time, so I've been searching around and without much luck. Does anyone know of any algorithms, or free libraries, that would suit my needs. Links to any relevant documentation would be appreciated as well.&#xD;&#xA;&#xD;&#xA;Also as a note, I'm a self taught programmer/cs-tist. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a set of points and I need to provide a game engine the shape in triangles. I get these points from a shape, I then add points to add area, subtract area, or split the shape. After modifying/adding points I need to give the game engine the shape in triangles as well as other information. Holes could be anywhere in any shape.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7842" PostHistoryTypeId="24" PostId="3760" RevisionGUID="234be34e-edea-4130-bba3-9a342ad73514" CreationDate="2016-07-17T19:26:44.807" Comment="Proposed by 4749 approved by 385, 273 edit id of 153" ContentLicense="CC BY-SA 3.0" />
  <row Id="7843" PostHistoryTypeId="5" PostId="1864" RevisionGUID="9e51dfc2-603f-4cc0-89bc-fdf63bbcc30a" CreationDate="2016-07-18T12:39:44.610" UserId="222" Comment="Moderator edits article" Text="**Computer Graphics Stack Exchange** is for computer graphics researchers and programmers.&#xA;&#xA;Topics that are usually a good fit for this site include:&#xA;&#xA;* Questions about math related to computer graphics,&#xA;* Questions about a specific graphics [programming](http://meta.computergraphics.stackexchange.com/questions/67/are-questions-about-api-specific-stuff-on-topic) or [debugging](http://meta.computergraphics.stackexchange.com/questions/1/are-questions-about-debugging-opengl-shaders-on-topic) problem,&#xA;* Questions about a specific [graphics API](http://meta.computergraphics.stackexchange.com/questions/67/are-questions-about-api-specific-stuff-on-topic),&#xA;* Questions about a specific graphics algorithm or concept.&#xA;&#xA;If your question generally covers (one of) these topics, then you’re in the right place to ask your question!&#xA;&#xA;---&#xA;&#xA;However, some questions are still off-topic, although they might fit into the above criteria.&#xA;&#xA;* Questions asking for [off-site resources](http://meta.computergraphics.stackexchange.com/questions/146/are-questions-asking-for-off-site-resources-on-topic) including books, tools and tutorials are off-topic as they tend to attract opinionated answers and spam. Also, the other sites may remove their content, which makes the question here useless for future visitors. Instead, ask about the specific problem you have.&#xA;* The same applies to questions asking for [software recommendations](http://meta.computergraphics.stackexchange.com/questions/141/are-questions-about-software-recommendation-in-scope). You may ask such questions on [Software Recommendations Stack Exchange](http://softwarerecs.stackexchange.com/), but please first read over their [Help Center](https://softwarerecs.stackexchange.com/help/on-topic) and [quality guidelines](http://meta.softwarerecs.stackexchange.com/questions/336/what-is-required-for-a-question-to-contain-enough-information).&#xA;* Questions about [how to use (a feature of) modeling software](http://meta.computergraphics.stackexchange.com/questions/13/is-asking-about-maya-or-3ds-max-blender-api-on-topic) are off-topic here, but may be suitable to [Super User](http://superuser.com). Questions specific to Blender may even be asked on [Blender Stack Exchange](http://blender.stackexchange.com). Again, please have a look into their Help Centers before asking.&#xA;* Questions about [Computer Vision](http://meta.computergraphics.stackexchange.com/questions/176/is-computer-vision-in-scope) are off-topic, except where it overlaps with computer graphics. As there is a significant part of overlap between these two topics, the line is blurry. Computer Vision questions unrelated to computer graphics may be suitable to [Signal Processing Stack Exchange](http://dsp.stackexchange.com).&#xA;&#xA;---&#xA;&#xA;&lt;p&gt;Please &lt;a href=&quot;/search&quot;&gt;look around&lt;/a&gt; to see if your question has been asked before. It’s also OK to &lt;a href=&quot;/helpcenter/self-answer&quot;&gt;ask and answer your own question&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your question is not specifically on-topic for $SiteName, it may be on topic for another Stack Exchange site. If no site currently exists that will accept your question, you may &lt;a href=&quot;http://area51.stackexchange.com/faq&quot;&gt;commit to&lt;/a&gt; or &lt;a href=&quot;http://meta.stackexchange.com/questions/76974/how-can-i-propose-a-new-site&quot;&gt;propose&lt;/a&gt; a new site at &lt;a href=&quot;http://area51.stackexchange.com/&quot;&gt;Area 51&lt;/a&gt;, the place where new Stack Exchange communities are democratically created.&lt;/p&gt;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7844" PostHistoryTypeId="5" PostId="3758" RevisionGUID="f8930ed5-a26e-4716-bfa2-48f2919bc202" CreationDate="2016-07-18T15:09:59.560" UserId="385" Comment="Fixed link" Text="I am trying to implement [Ray Tracing with Cones (Amanatides 1984)][1]. Instead of rays, cones are shot into the scene and intersected with geometry. Since multiple triangles can occupy the cone's aperture, we need to calculate (or rather quickly estimate, since cone tracing makes a lot of approximations anyway) the relative area of the circle that is covered by the triangle. Afterwards, the individual contributions are weighted and summed up.&#xD;&#xA;&#xD;&#xA;The author, unfortunately, does not give a lot of detail about his solution. Here is what he writes on cone-plane intersections:&#xD;&#xA;&#xD;&#xA;&gt; The spread angle and the angle between the ray and plane computed&#xD;&#xA;&gt; above together indicate how the distance between the center of the&#xD;&#xA;&gt; circle and the edge of the half plane [sic]. Given this distance, the area&#xD;&#xA;&gt; of intersection is computed using a polynomial approximation. This&#xD;&#xA;&gt; completes the intersection calculation for planes.&#xD;&#xA;&#xD;&#xA;And then, after projecting a polygon to the plane perpendicular to the&#xD;&#xA;direction vector of the cone:&#xD;&#xA;&#xD;&#xA;&gt; We then must calculate the intersection between the projected polygon&#xD;&#xA;&gt; and a circle. This can be accomplished by calculating the distance&#xD;&#xA;&gt; from the center of the circle to each of the edges and then using the&#xD;&#xA;&gt; circle - half plane intersection estimation mentioned earlier.&#xD;&#xA;&#xD;&#xA;I found [a solution to the problem][2] over at StackExchange. I have ported the code from [NowIGetToLearnWhatAHeadIs' answer][3], and it works fine, but seems pretty complicated to me. I am working with Compute Shaders, so branching is a bad thing, and the solutions rely heavily on it.&#xD;&#xA;&#xD;&#xA; 1. What is this *polynomial approximation* that Amanatides talks about, and how is it to be applied to polygons (espc. triangles)?&#xD;&#xA; 2. Is there any approximation to the problem that will give resonably accurate results (say ±10%) at considerable performance / code simplicity gains?&#xD;&#xA; 3. Working with GPUs, I am interested in an optimized solution that uses min/max over branching, for example. Maybe something like this already exists. Any luck?&#xD;&#xA;&#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.32.6170&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [2]: http://stackoverflow.com/questions/540014/compute-the-area-of-intersection-between-a-circle-and-a-triangle&#xD;&#xA;  [3]: http://stackoverflow.com/a/22420313/776142" ContentLicense="CC BY-SA 3.0" />
  <row Id="7845" PostHistoryTypeId="2" PostId="3764" RevisionGUID="0c73a465-87e3-47b8-9c62-6cfbcd3d16be" CreationDate="2016-07-18T18:39:53.650" UserId="4761" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ch0vp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7846" PostHistoryTypeId="1" PostId="3764" RevisionGUID="0c73a465-87e3-47b8-9c62-6cfbcd3d16be" CreationDate="2016-07-18T18:39:53.650" UserId="4761" Text="Apply distortion to Bézier surface" ContentLicense="CC BY-SA 3.0" />
  <row Id="7847" PostHistoryTypeId="3" PostId="3764" RevisionGUID="0c73a465-87e3-47b8-9c62-6cfbcd3d16be" CreationDate="2016-07-18T18:39:53.650" UserId="4761" Text="|transformations|geometry|computational-geometry|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7848" PostHistoryTypeId="2" PostId="3765" RevisionGUID="da2c301c-cae8-4c4c-9a16-9eb3f21738fd" CreationDate="2016-07-19T12:31:24.113" UserId="4765" Text="# OVERVIEW #&#xD;&#xA;My program receives some data points (0-400 per sec). &#xD;&#xA;&#xD;&#xA;    // simplified example of point's data structure&#xD;&#xA;    struct Point {&#xD;&#xA;        QPoint p;&#xD;&#xA;        QTime t;&#xD;&#xA;        quint32 value;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* I need to render some filtered points (eg. that `point.time &gt; currentTime-5` and `point.value&gt;5`).&#xD;&#xA;* I need to store data history (up to ~50'000 points).&#xD;&#xA;* The data can be used also on the CPU. &#xD;&#xA;* I will use object-picking. &#xD;&#xA;* Points are rendered in 3d&#xD;&#xA;* camera position can change, but points data is constant&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# QUESTION #&#xD;&#xA;What is the best architecture to implement this kind of problem? What what are best practices with this kind of data and what are practices to avoid?&#xD;&#xA;&#xD;&#xA;# POSSIBLE SOLUTIONS #&#xD;&#xA;* storing and filtering data&#xD;&#xA;  1. Store the data on the CPU (word coordinates), filtering data on a CPU and sending filtered data to VBO, calculating screen-space coordinates with shaders&#xD;&#xA;  2. Store the data on a CPU and a GPU (update a VBO when some new point arrives).&#xD;&#xA;  Filter points on CPU and calculate offsets and use `glMultiDrawArrays`&#xD;&#xA;  3. Store the data only on a GPU (update VBO when point arrives). Filter it with shaders, get data from VBO to CPU when needed.&#xD;&#xA;&#xD;&#xA;Solution 1. is fairly easy, but I think it is a bad practice.&#xD;&#xA;Solution 2. has data duplication, but it is easy to filter the data. &#xD;&#xA;Solution 3. has data reading GPU-&gt;CPU&#xD;&#xA;&#xD;&#xA;I tried those solutions, and Solution 2. occurs to me as the best, there are some issues with it:&#xD;&#xA;* multiplication of data has to be handled gently&#xD;&#xA;* it is not the easiest-to-read-and-modify solution&#xD;&#xA;* when there are changes in data there is a lot of thigs to change&#xD;&#xA;I used something like circular buffer on VBO and send offsets to render on it.&#xD;&#xA;&#xD;&#xA;# ENVIRONMENT #&#xD;&#xA;* OpenGL 3.3&#xD;&#xA;* Qt 5+ bindings&#xD;&#xA;* Linux" ContentLicense="CC BY-SA 3.0" />
  <row Id="7849" PostHistoryTypeId="1" PostId="3765" RevisionGUID="da2c301c-cae8-4c4c-9a16-9eb3f21738fd" CreationDate="2016-07-19T12:31:24.113" UserId="4765" Text="proper architecture for rendering history of stramed data (points)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7850" PostHistoryTypeId="3" PostId="3765" RevisionGUID="da2c301c-cae8-4c4c-9a16-9eb3f21738fd" CreationDate="2016-07-19T12:31:24.113" UserId="4765" Text="|opengl|rendering|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7851" PostHistoryTypeId="5" PostId="3765" RevisionGUID="6d1b3fd4-d74d-4777-8b3c-360d3335e45d" CreationDate="2016-07-19T12:39:53.123" UserId="4765" Comment="PS" Text="# OVERVIEW #&#xD;&#xA;My program receives some data points (0-400 per sec). &#xD;&#xA;&#xD;&#xA;    // simplified example of point's data structure&#xD;&#xA;    struct Point {&#xD;&#xA;        QPoint p;&#xD;&#xA;        QTime t;&#xD;&#xA;        quint32 value;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* I need to render some filtered points (eg. that `point.time &gt; currentTime-5` and `point.value&gt;5`).&#xD;&#xA;* I need to store data history (up to ~50'000 points).&#xD;&#xA;* The data can be used also on the CPU. &#xD;&#xA;* I will use object-picking. &#xD;&#xA;* Points are rendered in 3d&#xD;&#xA;* camera position can change, but points data is constant&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# QUESTION #&#xD;&#xA;What is the best architecture to implement this kind of problem? What what are best practices with this kind of data and what are practices to avoid?&#xD;&#xA;&#xD;&#xA;# POSSIBLE SOLUTIONS #&#xD;&#xA;* storing and filtering data&#xD;&#xA;  1. Store the data on the CPU (word coordinates), filtering data on a CPU and sending filtered data to VBO, calculating screen-space coordinates with shaders&#xD;&#xA;  2. Store the data on a CPU and a GPU (update a VBO when some new point arrives).&#xD;&#xA;  Filter points on CPU and calculate offsets and use `glMultiDrawArrays`&#xD;&#xA;  3. Store the data only on a GPU (update VBO when point arrives). Filter it with shaders, get data from VBO to CPU when needed.&#xD;&#xA;&#xD;&#xA;Solution 1. is fairly easy, but I think it is a bad practice.&#xD;&#xA;Solution 2. has data duplication, but it is easy to filter the data. &#xD;&#xA;Solution 3. has data reading GPU-&gt;CPU&#xD;&#xA;&#xD;&#xA;I tried those solutions, and Solution 2. occurs to me as the best, there are some issues with it:&#xD;&#xA;* multiplication of data has to be handled gently&#xD;&#xA;* it is not the easiest-to-read-and-modify solution&#xD;&#xA;* when there are changes in data there is a lot of thigs to change&#xD;&#xA;I used something like circular buffer on VBO and send offsets to render on it.&#xD;&#xA;&#xD;&#xA;# ENVIRONMENT #&#xD;&#xA;* OpenGL 3.3&#xD;&#xA;* Qt 5+ bindings&#xD;&#xA;* Linux&#xD;&#xA;&#xD;&#xA;PS&#xD;&#xA;I am fairly new to computer graphics and openGL, so maybe this kind of problem even has its name. I changed my implementations few times, it took me a lot of time and I am not happy with it due to its complexity. Any materials, guides and thoughts are welcome. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7852" PostHistoryTypeId="5" PostId="3764" RevisionGUID="c3a68936-315b-449d-bdb7-fa5f28830c53" CreationDate="2016-07-19T13:56:55.047" UserId="4761" Comment="added 295 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;* When moving d from 0 to 1, two top corners move horizontally to 0, two bottom corners move horizontally to 2X.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ch0vp.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7853" PostHistoryTypeId="5" PostId="3764" RevisionGUID="ef347e56-a342-4dd1-ba5b-64b49a8fd447" CreationDate="2016-07-19T14:29:00.797" UserId="4761" Comment="deleted 114 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ch0vp.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7854" PostHistoryTypeId="2" PostId="3766" RevisionGUID="e3d2d20b-d957-4892-bd7b-f1a2e7e9493c" CreationDate="2016-07-19T14:42:16.460" UserId="4524" Text="You can find the formula of a Bezier curve from given points. As far as I can tell, Photoshop is keeping vertical lines straight. It picks four equidistant points on top and bottom curves, and cut these lines from 1/3 and 2/3. With this you will have two sets of 4 points on the new Bezier curves running along the image. You can find their formula. These lines are the ones that are visible over the image. Finally, you can apply this every line to reach to the final image." ContentLicense="CC BY-SA 3.0" />
  <row Id="7855" PostHistoryTypeId="5" PostId="3766" RevisionGUID="064d2a48-3ab4-40ce-b129-5065622ad8c5" CreationDate="2016-07-19T15:27:19.703" UserId="4524" Comment="deleted 122 characters in body" Text="Edit: changed the answer according to clarification.&#xD;&#xA;&#xD;&#xA;The effect applied to the Bezier surface is the following, assuming center is 0, 0 and corners are (-1, -1), (1, -1), (-1, 1), (1, 1).&#xD;&#xA;&#xD;&#xA;    for every control point p&#xD;&#xA;       p.x = p.x + p.x * p.y&#xD;&#xA;&#xD;&#xA;Apply this formula to all control points, your surface will be deformed as the reference images." ContentLicense="CC BY-SA 3.0" />
  <row Id="7856" PostHistoryTypeId="5" PostId="3764" RevisionGUID="69f3407c-96dd-4027-be92-2a0133e6f468" CreationDate="2016-07-19T15:44:54.593" UserId="4761" Comment="added 141 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;&#xD;&#xA;Here I drew the lines: corners move along red lines, other control points move along blue lines.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7IGo8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7857" PostHistoryTypeId="5" PostId="3764" RevisionGUID="c2358e6b-ce47-4d54-b352-7f9d1e39e5c0" CreationDate="2016-07-19T15:54:18.687" UserId="4761" Comment="added 84 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;&#xD;&#xA;Here I drew the lines: corners move along red lines, other control points move along blue lines.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xuTih.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7858" PostHistoryTypeId="5" PostId="3764" RevisionGUID="9d74efdc-7e42-4434-b5b0-7cca96da5ebd" CreationDate="2016-07-19T16:14:19.910" UserId="4761" Comment="added 84 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;&#xD;&#xA;Here I drew the lines: corners move along red lines, other control points move along blue lines.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xuTih.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bq7Vd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7859" PostHistoryTypeId="5" PostId="3764" RevisionGUID="197d37da-e0bb-4306-91e5-2f66e200f58a" CreationDate="2016-07-19T17:30:07.133" UserId="4761" Comment="added 76 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;&#xD;&#xA;Here I drew the lines: corners move along red lines, other control points move along blue lines.&#xD;&#xA;&#xD;&#xA;*  https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;*  https://i.stack.imgur.com/xuTih.png&#xD;&#xA;*  https://i.stack.imgur.com/bq7Vd.png&#xD;&#xA;*  https://i.stack.imgur.com/iHYiE.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xuTih.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bq7Vd.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/iHYiE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7860" PostHistoryTypeId="2" PostId="3767" RevisionGUID="cfc7d4e0-3483-4558-adbf-17f61f51ccba" CreationDate="2016-07-19T18:20:16.133" UserId="4766" Text="I'm probably going to screw this up but.... In all the graphics libraries I've seen various matrices are often called something along the lines of&#xD;&#xA;&#xD;&#xA;    viewProjection&#xD;&#xA;    modelViewProjection&#xD;&#xA;    worldViewProjection&#xD;&#xA;    mvp&#xD;&#xA;    wvp&#xD;&#xA;&#xD;&#xA;etc.&#xD;&#xA;&#xD;&#xA;But, that seems unintuitive given that GLSL, HLSL, and most math libraries seem to multiply in the opposite direction.&#xD;&#xA;&#xD;&#xA;In other words&#xD;&#xA;&#xD;&#xA;    viewProjection = projection * view;  // correct but unintuitive&#xD;&#xA;&#xD;&#xA;vs&#xD;&#xA;&#xD;&#xA;    viewProjection = view * projection;  // incorrect but naming matches order&#xD;&#xA;&#xD;&#xA;It gets worse if you add in transpose or inverse since now the order of operations vs the order of parts of the name of the matrix make zero sense whatsoever. a `worldViewProjectionInverseTranspose` would be&#xD;&#xA;&#xD;&#xA;    transpose(inverse(projection * view * world))&#xD;&#xA;&#xD;&#xA;Well you can read it backward but as far as order of operations and position in the expression its &#xD;&#xA;&#xD;&#xA;    5 ( 4 ( 1 * 2 * 3 ) )&#xD;&#xA;&#xD;&#xA;Is there any objective reason for the names to be backward from the operations that construct them or is it just some naming convention that stuck from some example lost in obscurity?&#xD;&#xA;&#xD;&#xA;I'm asking this question because being that it's unintuitive I find it's always hard to remember the order. If `worldViewProjection` equaled `world * view * projection` it would be easy since the name matches the order. I'm hoping there's some other objective reason that might help remember vs just remembering always multiply backward from the order of the parts of the commonly used names.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7861" PostHistoryTypeId="1" PostId="3767" RevisionGUID="cfc7d4e0-3483-4558-adbf-17f61f51ccba" CreationDate="2016-07-19T18:20:16.133" UserId="4766" Text="Is there a objective reason for matrix naming conventions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7862" PostHistoryTypeId="3" PostId="3767" RevisionGUID="cfc7d4e0-3483-4558-adbf-17f61f51ccba" CreationDate="2016-07-19T18:20:16.133" UserId="4766" Text="|transformations|glsl|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7863" PostHistoryTypeId="2" PostId="3768" RevisionGUID="356332f3-a32a-45f2-b930-479e97f586c9" CreationDate="2016-07-19T22:00:48.733" UserId="3328" Text="I am trying to render Blin Phong as a brdf model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use 3d programing api such as opengl or webgl and so on..&#xD;&#xA;my purpose is to render the surface plane without those apis.Every steps that i did are, I create 3 spaces:&#xD;&#xA;&#xD;&#xA; 1.  image space: (0,0) is at the top left of the image&#xD;&#xA; 3. camera space: (0,0) is at the middle of the image&#xD;&#xA; 4. world space: (0,0) is outside of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, i convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;The 2 images belows show my results: the first one is obtained when the camera space is at the middle and left of the image. The second one is obtained when the camera space is at the middle of the image. With the last image result, we can see exactly the ambiant color (at the most left) and the diffuse + specular is at the right.&#xD;&#xA;&#xD;&#xA;Of course the lobe specular should be a circle (in my opinion) but not like this. That's why I am asking.&#xD;&#xA;&#xD;&#xA;Any help please!! Regards&#xD;&#xA;[![Image space at the middle and left of the image][1]][1]&#xD;&#xA;[![Image space at the middle of the image][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NI2j6.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Mm4Z8.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7864" PostHistoryTypeId="1" PostId="3768" RevisionGUID="356332f3-a32a-45f2-b930-479e97f586c9" CreationDate="2016-07-19T22:00:48.733" UserId="3328" Text="Blin Phong rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="7865" PostHistoryTypeId="3" PostId="3768" RevisionGUID="356332f3-a32a-45f2-b930-479e97f586c9" CreationDate="2016-07-19T22:00:48.733" UserId="3328" Text="|rendering|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7866" PostHistoryTypeId="5" PostId="3768" RevisionGUID="3635c75b-429a-4caf-8c05-1968432a5c3e" CreationDate="2016-07-19T22:41:35.923" UserId="231" Comment="Minor typos and apply assumed intended formating (please revert anything that isn't your intention)" Text="I am trying to render Blinn Phong as a BRDF model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use a 3d programing api such as opengl or webgl and so on...  &#xD;&#xA;My purpose is to render the surface plane without those apis. The steps I take are, I create 3 spaces:&#xD;&#xA;&#xD;&#xA; 1. image space: (0,0) is at the top left of the image&#xD;&#xA; 1. camera space: (0,0) is at the middle of the image&#xD;&#xA; 1. world space: (0,0) is outside of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, I convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;The 2 images below show my results: the first one is obtained when the camera space is at the middle and left of the image. The second one is obtained when the camera space is at the middle of the image. With the last image result, we can see exactly the ambient color (at the most left) and the diffuse + specular is at the right.&#xD;&#xA;&#xD;&#xA;Of course the lobe specular should be a circle (in my opinion) but not like this. That's why I am asking.&#xD;&#xA;&#xD;&#xA;[![Image space at the middle and left of the image][1]][1]&#xD;&#xA;&#xD;&#xA;[![Image space at the middle of the image][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NI2j6.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Mm4Z8.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7867" PostHistoryTypeId="5" PostId="3768" RevisionGUID="dd633ee6-26e2-4811-994c-3647f6759dd9" CreationDate="2016-07-19T22:47:53.793" UserId="3328" Comment="added 1393 characters in body" Text="I am trying to render Blin Phong as a brdf model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use 3d programing api such as opengl or webgl and so on..&#xD;&#xA;my purpose is to render the surface plane without those apis.Every steps that i did are, I create 3 spaces:&#xD;&#xA;&#xD;&#xA; 1.  image space: (0,0) is at the top left of the image&#xD;&#xA; 3. camera space: (0,0) is at the middle of the image&#xD;&#xA; 4. world space: (0,0) is outside of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, i convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;    double[] cam=(Cam2World((new double[]{0,0,1})));&#xD;&#xA;	double[] lum=(Cam2World((new double[]{0,0,1})));&#xD;&#xA;    double[] E=new double[3];&#xD;&#xA;			double[] L=new double[3];&#xD;&#xA;			double[] H=new double[3];&#xD;&#xA;			double D2;&#xD;&#xA;			Mat image=new Mat(rows,cols,CvType.CV_8UC3);&#xD;&#xA;			System.out.println(&quot;Start!!&quot;);&#xD;&#xA;			System.out.println(&quot;ok&quot;);&#xD;&#xA;			for(int i=0;i&lt;tileHNumber;i++)&#xD;&#xA;			{&#xD;&#xA;				for(int j=0;j&lt;tileWNumber;j++)&#xD;&#xA;				{&#xD;&#xA;					for(int s=0;s&lt;192;s++)&#xD;&#xA;					{&#xD;&#xA;						for(int t=0;t&lt;192;t++)&#xD;&#xA;						{&#xD;&#xA;							originS=s+192*i;//ligne&#xD;&#xA;							originT=t+192*j;//colonne&#xD;&#xA;							double[] pos=Cam2World((Image2Cam(new double[]{originT,originS,0})));&#xD;&#xA;							E=normalize(XY(pos,cam));&#xD;&#xA;							L=calculeL(pos, lum);&#xD;&#xA;							double[] le=addXY(L,E);&#xD;&#xA;							H=normalize(le);&#xD;&#xA;							D2=dot(E,E);&#xD;&#xA;							double blue=color(blueColor,pos,E,L,H,D2);&#xD;&#xA;							double green=color(greenColor,pos,E,L,H,D2);&#xD;&#xA;							double red=color(redColor,pos,E,L,H,D2);&#xD;&#xA;							image.put(originS, originT, new byte[]{(byte)(blue),(byte)(green),(byte)(red)});&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;     public static double color(double col,double[] pos,double[] E,double[] L,double[] H,double D2)&#xD;&#xA;	 {&#xD;&#xA;		double value=0;&#xD;&#xA;		double[] N=normalize((new double[]{pos[0],pos[1],1}));&#xD;&#xA;		double diffuse=Math.max(0, dot(N,L));	&#xD;&#xA;		double specular=Math.pow(Math.max(0, dot(N,H)),60);&#xD;&#xA;		value=d*diffuse*0.5+0.2*d+specular*255*0.3;&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The 2 images belows show my results: the first one is obtained when the camera space is at the middle and left of the image. The second one is obtained when the camera space is at the middle of the image. With the last image result, we can see exactly the ambiant color (at the most left) and the diffuse + specular is at the right.&#xD;&#xA;&#xD;&#xA;Of course the lobe specular should be a circle (in my opinion) but not like this. That's why I am asking.&#xD;&#xA;&#xD;&#xA;Any help please!! Regards&#xD;&#xA;[![Image space at the middle and left of the image][1]][1]&#xD;&#xA;[![Image space at the middle of the image][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NI2j6.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Mm4Z8.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7868" PostHistoryTypeId="5" PostId="3764" RevisionGUID="4eff1456-d543-4f32-9a77-4d9032dcd689" CreationDate="2016-07-19T22:56:32.687" UserId="4761" Comment="added 83 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;What I figured out:&#xD;&#xA;&#xD;&#xA;* All control points have original position at d=0 and the new position at d=1. When moving d from 0 to 1, all control points move along the lines between original and new position, linearly.&#xD;&#xA;* 4 control points on the left and 4 on the right side move along parallel lines.&#xD;&#xA;&#xD;&#xA;Here I drew the lines: corners move along red lines, other control points move along blue lines.&#xD;&#xA;&#xD;&#xA;*  https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;*  https://i.stack.imgur.com/xuTih.png&#xD;&#xA;*  https://i.stack.imgur.com/bq7Vd.png&#xD;&#xA;*  https://i.stack.imgur.com/iHYiE.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xuTih.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bq7Vd.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/iHYiE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7869" PostHistoryTypeId="2" PostId="3769" RevisionGUID="703b697e-16d2-4eb8-b7bb-344763b1c1a1" CreationDate="2016-07-19T23:21:29.547" UserId="4768" Text="I think the naming order is intuitive because it is in reading order (left to right), e.g., worldViewProjection means that your point/direction is first multiplied by the world matrix, then the view matrix, and then the projection matrix. In this manner, you know the correct multiplication order by just reading the variable name and you do not have to think about mathematics at all. In your case, I think the problem is that your intuition seems to be focused on how you write the equations on paper or code.&#xD;&#xA;&#xD;&#xA;The idea that a point is a column vector and matrices are multiplied on the left is also just a mathematical convention that you are used. You can use a row vector and multiply on the right by the transpose matrix, and the math is exactly the same, but would imply a reverse writing order in compound transformations. Some people just prefer one notation over the other.&#xD;&#xA;&#xD;&#xA;I have read some old computer graphics books that use row vectors as points/directions, but it seems that most modern books have converged on using column vectors. IMHO, maybe this change during the years is one of the sources of confusion for so many new CG students..." ContentLicense="CC BY-SA 3.0" />
  <row Id="7870" PostHistoryTypeId="5" PostId="3769" RevisionGUID="f22a52dc-11d3-4b05-ac02-d9f286ec495c" CreationDate="2016-07-19T23:32:55.590" UserId="4768" Comment="added 642 characters in body" Text="I think the naming order is intuitive because it is in reading order (left to right), e.g., worldViewProjection means that your point/direction is first multiplied by the world matrix, then the view matrix, and then the projection matrix. In this manner, you know the correct multiplication order by just reading the variable name and you do not have to think about mathematics at all. In your case, I think the problem is that your intuition seems to be focused on how you write the equations on paper or code.&#xD;&#xA;&#xD;&#xA;The idea that a point is a column vector and matrices are multiplied on the left is also just a mathematical convention that you are used. You can use a row vector and multiply on the right by the transpose matrix, and the math is exactly the same, but would imply a reverse writing order in compound transformations. Some people just prefer one notation over the other.&#xD;&#xA;&#xD;&#xA;I have read some old computer graphics books that use row vectors as points/directions, but it seems that most modern books have converged on using column vectors. IMHO, maybe this change during the years is one of the sources of confusion for so many new CG students.&#xD;&#xA;&#xD;&#xA;For instance, if you choose to represent points as row vectors you would write something like this in your code: **new_point = point * world * view * projection**. On the other hand, if you use column vectors you would write this: **new_point = projection * view * world * point**. The important thing is that these matrices must not be the same, that is, the world matrix in the first code is the transpose of the world matrix in the second code, and the same is true for the others. As you can see, if you choose one math convention over the other, this will probably have influence on your naming conventions while writing your code." ContentLicense="CC BY-SA 3.0" />
  <row Id="7873" PostHistoryTypeId="2" PostId="3771" RevisionGUID="dc028e67-f7b6-4bd0-af54-00c600087617" CreationDate="2016-07-20T06:59:43.183" UserId="4696" Text="I have a 3d surface mesh.&#xD;&#xA;&#xD;&#xA;Say the camera is located in some points and I want to get the visible points from the 3d surface mesh from the camera view.&#xD;&#xA;&#xD;&#xA;I believe this kind of process would be done before 3d rendering in graphics. &#xD;&#xA;&#xD;&#xA;I want to know how it generally works and fast, simple algorithm for the problem. It would be better, if there is some matlab function library to do this task.&#xD;&#xA;&#xD;&#xA;Note that 3d rendering is not my purpose... I just want to get the visible point set from the 3d surface mesh." ContentLicense="CC BY-SA 3.0" />
  <row Id="7874" PostHistoryTypeId="1" PostId="3771" RevisionGUID="dc028e67-f7b6-4bd0-af54-00c600087617" CreationDate="2016-07-20T06:59:43.183" UserId="4696" Text="get partial view points from 3d surface mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="7875" PostHistoryTypeId="3" PostId="3771" RevisionGUID="dc028e67-f7b6-4bd0-af54-00c600087617" CreationDate="2016-07-20T06:59:43.183" UserId="4696" Text="|3d|computational-geometry|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7876" PostHistoryTypeId="2" PostId="3772" RevisionGUID="b0ed240b-6c67-4e4d-84ad-16f271198896" CreationDate="2016-07-20T07:32:16.313" UserId="3073" Text="In your case you would test every point to see if it lies inside your camera frustum, this is basically a set of point-vs-plane tests. This is not a fast way to do do things but the simplest to understand and implement. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7877" PostHistoryTypeId="2" PostId="3773" RevisionGUID="249065b6-7bcb-4aeb-a27d-0df2f6627103" CreationDate="2016-07-20T08:43:25.277" UserId="3073" Text="If I'm guessing right, you are drawing a plane which is facing the camera, so your normals need to be 0,0,-1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;change&#xD;&#xA;&#xD;&#xA;double[] N=normalize((new double[]{pos[0],pos[1],1}));&#xD;&#xA;&#xD;&#xA;to&#xD;&#xA;&#xD;&#xA;double[] N=normalize((new double[]{0,0,-1}));" ContentLicense="CC BY-SA 3.0" />
  <row Id="7878" PostHistoryTypeId="2" PostId="3774" RevisionGUID="a03cac14-bf97-4e80-940b-bb9159eb913c" CreationDate="2016-07-20T08:44:00.260" UserId="38" Text="The order is arbitrary. The difference is that you seem to think that its more natural to observe the systen on the outside. For a mathematician it is more natural to think from local coordinates out. There are several reasons for this but mathematicians seem to want to reduce this to functional form if you were to transform a value x trough multiple functions you would get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;h(g(f(x))) &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or sometimes&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(h \circ g \circ f)(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This quite literary means transform x to f to g to h. So it is natural for a mathematician and some programmers to read the operations inside out. This way your operqtional order matches also other branches of mathematical notation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But obviously you are free to transpose your vectors and then your order is opposite. It is up to you to define meaning to your math." ContentLicense="CC BY-SA 3.0" />
  <row Id="7879" PostHistoryTypeId="5" PostId="3774" RevisionGUID="d8c0d002-3501-4727-8eb8-b824c3dbee56" CreationDate="2016-07-20T08:54:41.263" UserId="38" Comment="added 312 characters in body" Text="The order is arbitrary. The difference is that you seem to think that its more natural to observe the systen on the outside. For a mathematician it is more natural to think from local coordinates out. There are several reasons for this but mathematicians seem to want to reduce this to functional form if you were to transform a value x trough multiple functions you would get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;h(g(f(x))) &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or sometimes&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(h \circ g \circ f)(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This quite literary means transform x to f to g to h. So it is natural for a mathematician and some programmers to read the operations inside out. This way your operational order matches also other branches of mathematical notation. Since most math and physics textbooks take this approach you probably should too.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But obviously you are free to transpose your vectors and then your order is opposite. It is up to you to define meaning to your math. This because there is  a rule that follows from how matrices are defined that states:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(A \cdot B)^T = B^T \cdot A^T&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;It is easily shown that longer chains just reverse the entire chain by recursing this forumula.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7880" PostHistoryTypeId="5" PostId="3774" RevisionGUID="95c8ef30-f059-45ef-a4b2-e17a072744cc" CreationDate="2016-07-20T09:04:11.673" UserId="38" Comment="added 312 characters in body" Text="The order is arbitrary. The difference is that you seem to think that its more natural to observe the systen on the outside (and for graphics pipe devs its often so, notvso for modeler). For a mathematician it is more natural to think from local coordinates out. There are several reasons for this but mathematicians seem to want to reduce this to functional form if you were to transform a value x trough multiple functions you would get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;h(g(f(x))) &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or sometimes&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(h \circ g \circ f)(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This quite literary means transform x to f to g to h. So it is natural for a mathematician and some programmers to read the operations inside out. This way your operational order matches also other branches of mathematical notation. Since most math and physics textbooks take this approach you probably should too. The other reason is that your modeling elements lie on the outside of your data.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But obviously you are free to transpose your vectors and then your order is opposite. It is up to you to define meaning to your math. This because there is  a rule that follows from how matrices are defined that states:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(A \cdot B)^T = B^T \cdot A^T&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;It is easily shown that longer chains just reverse the entire chain by recursing this forumula.&#xD;&#xA;&#xD;&#xA;It is good to remeber that the order inside the vectors are arbitrary as well as calculation order. There is no reason for the vector to be defined in X, Y, Z, W order we could define the matrices and vectors in any order even a slightly cryptic X, W, Z, Y order. So rember the modeling convention is not somehow set in stone. Students would often want it to be, because that would mean not needing to understand as much, but it does not have to be. Matrices just enable you to model arbitrary vectors with unified math notation. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7881" PostHistoryTypeId="5" PostId="3774" RevisionGUID="45893a9a-6b4b-4e10-bbc6-a00249177b61" CreationDate="2016-07-20T09:09:39.803" UserId="38" Comment="added 312 characters in body" Text="The order is arbitrary, but if you want to be compatible with physics textbooks then your notation is mostly set. The difference is that you seem to think that its more natural to observe the systen on the outside (and for graphics pipe devs its often so, not for modeler). For a mathematician it is more natural to think from local coordinates out. There are several reasons for this but mathematicians seem to want to reduce this to functional form if you were to transform a value x trough multiple functions you would get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;h(g(f(x))) &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or sometimes&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(h \circ g \circ f)(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This quite literary means transform x to f to g to h. So it is natural for a mathematician and some programmers to read the operations inside out. This way your operational order matches also other branches of mathematical notation. Since most math and physics textbooks take this approach you probably should too. &#xD;&#xA;&#xD;&#xA;The other reason is that your modeling elements lie on the outside of your data. But obviously you are free to transpose your vectors and then your order is opposite. It is up to you to define meaning to your math. This because there is  a rule that follows from how matrices are defined that states:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(A \cdot B)^T = B^T \cdot A^T&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;It is easily shown that longer chains just reverse the entire chain by recursing this forumula.&#xD;&#xA;&#xD;&#xA;It is good to remeber that the order inside the vectors are arbitrary as well as calculation order. There is no reason for the vector to be defined in X, Y, Z, W order we could define the matrices and vectors in any order even a slightly cryptic X, W, Z, Y order. So rember the modeling convention is not somehow set in stone. Students would often want it to be, because that would mean not needing to understand as much, but it does not have to be. Matrices just enable you to model arbitrary vectors with unified math notation. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7882" PostHistoryTypeId="5" PostId="3774" RevisionGUID="4c7c16dd-8e33-4665-8072-8aea33a751bc" CreationDate="2016-07-20T09:15:21.853" UserId="38" Comment="added 312 characters in body" Text="The order is arbitrary, but if you want to be compatible with physics textbooks then your notation is mostly set. The difference is that you seem to think that its more natural to observe the systen on the outside (and for graphics pipe devs its often so, not for modeler). For a mathematician it is more natural to think from local coordinates out. There are several reasons for this but mathematician seem to want to reduce this to functional form if you were to transform a value x through multiple functions you would get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;h(g(f(x))) &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or sometimes&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(h \circ g \circ f)(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This quite literary means transform x to f to g to h. So it is natural for a mathematician/physicist and some programmers to read the operations inside out simplybbecause this ties in better with the notation you were teached in early calculus. This way your operational order matches also other branches of mathematical notation. Since most math and physics textbooks take this approach you probably should too. &#xD;&#xA;&#xD;&#xA;The other reason is that your modeling elements lie on the outside of your data. But obviously you are free to transpose your vectors and then your order is opposite. It is up to you to define meaning to your math. This because there is  a rule that follows from how matrices are defined that states:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(A \cdot B)^T = B^T \cdot A^T&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;It is easily shown that longer chains just reverse the entire chain by recursing this forumula.&#xD;&#xA;&#xD;&#xA;It is good to remeber that the order inside the vectors are arbitrary as well as calculation order. There is no reason for the vector to be defined in X, Y, Z, W order we could define the matrices and vectors in any order even a slightly cryptic X, W, Z, Y order. So rember the modeling convention is not somehow set in stone. Students would often want it to be, because that would mean not needing to understand as much, but it does not have to be. Matrices just enable you to model arbitrary vectors with unified math notation. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7883" PostHistoryTypeId="5" PostId="3768" RevisionGUID="26132eb9-ba5e-4a17-8572-7536670b35d5" CreationDate="2016-07-20T10:44:15.410" UserId="67" Comment="Fixed a typo, spacing and caps" Text="I am trying to render Blinn Phong as a BRDF model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use 3d programing api such as OpenGL or WebGL and so on.&#xD;&#xA;My purpose is to render the surface plane without those apis. Every steps that I did are, I create 3 spaces:&#xD;&#xA;&#xD;&#xA; 1.  image space: (0,0) is at the top left of the image&#xD;&#xA; 3. camera space: (0,0) is at the middle of the image&#xD;&#xA; 4. world space: (0,0) is outside of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, I convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;    double[] cam=(Cam2World((new double[]{0,0,1})));&#xD;&#xA;	double[] lum=(Cam2World((new double[]{0,0,1})));&#xD;&#xA;    double[] E=new double[3];&#xD;&#xA;			double[] L=new double[3];&#xD;&#xA;			double[] H=new double[3];&#xD;&#xA;			double D2;&#xD;&#xA;			Mat image=new Mat(rows,cols,CvType.CV_8UC3);&#xD;&#xA;			System.out.println(&quot;Start!!&quot;);&#xD;&#xA;			System.out.println(&quot;ok&quot;);&#xD;&#xA;			for(int i=0;i&lt;tileHNumber;i++)&#xD;&#xA;			{&#xD;&#xA;				for(int j=0;j&lt;tileWNumber;j++)&#xD;&#xA;				{&#xD;&#xA;					for(int s=0;s&lt;192;s++)&#xD;&#xA;					{&#xD;&#xA;						for(int t=0;t&lt;192;t++)&#xD;&#xA;						{&#xD;&#xA;							originS=s+192*i;//ligne&#xD;&#xA;							originT=t+192*j;//colonne&#xD;&#xA;							double[] pos=Cam2World((Image2Cam(new double[]{originT,originS,0})));&#xD;&#xA;							E=normalize(XY(pos,cam));&#xD;&#xA;							L=calculeL(pos, lum);&#xD;&#xA;							double[] le=addXY(L,E);&#xD;&#xA;							H=normalize(le);&#xD;&#xA;							D2=dot(E,E);&#xD;&#xA;							double blue=color(blueColor,pos,E,L,H,D2);&#xD;&#xA;							double green=color(greenColor,pos,E,L,H,D2);&#xD;&#xA;							double red=color(redColor,pos,E,L,H,D2);&#xD;&#xA;							image.put(originS, originT, new byte[]{(byte)(blue),(byte)(green),(byte)(red)});&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;     public static double color(double col,double[] pos,double[] E,double[] L,double[] H,double D2)&#xD;&#xA;	 {&#xD;&#xA;		double value=0;&#xD;&#xA;		double[] N=normalize((new double[]{pos[0],pos[1],1}));&#xD;&#xA;		double diffuse=Math.max(0, dot(N,L));	&#xD;&#xA;		double specular=Math.pow(Math.max(0, dot(N,H)),60);&#xD;&#xA;		value=d*diffuse*0.5+0.2*d+specular*255*0.3;&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The 2 images belows show my results: the first one is obtained when the camera space is at the middle and left of the image. The second one is obtained when the camera space is at the middle of the image. With the last image result, we can see exactly the ambiant color (at the most left) and the diffuse + specular is at the right.&#xD;&#xA;&#xD;&#xA;Of course the lobe specular should be a circle (in my opinion) but not like this. That's why I am asking.&#xD;&#xA;&#xD;&#xA;Any help please!! Regards&#xD;&#xA;[![Image space at the middle and left of the image][1]][1]&#xD;&#xA;[![Image space at the middle of the image][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NI2j6.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Mm4Z8.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7884" PostHistoryTypeId="4" PostId="3768" RevisionGUID="26132eb9-ba5e-4a17-8572-7536670b35d5" CreationDate="2016-07-20T10:44:15.410" UserId="67" Comment="Fixed a typo, spacing and caps" Text="Blinn Phong rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="7885" PostHistoryTypeId="24" PostId="3768" RevisionGUID="26132eb9-ba5e-4a17-8572-7536670b35d5" CreationDate="2016-07-20T10:44:15.410" Comment="Proposed by 67 approved by -1 edit id of 154" ContentLicense="CC BY-SA 3.0" />
  <row Id="7886" PostHistoryTypeId="5" PostId="3768" RevisionGUID="90f60e02-a9fa-437f-90dd-a5adf216e72a" CreationDate="2016-07-20T10:44:15.410" UserId="231" Comment="Add syntax highlighting (assume C++). Also minor typos. Please revert anything that changes your intention." Text="I am trying to render Blinn Phong as a BRDF model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use 3d programing API such as OpenGL or WebGL and so on.  &#xD;&#xA;My purpose is to render the surface plane without those APIs. The steps that I take are, I create 3 spaces:&#xD;&#xA;&#xD;&#xA; 1. image space: (0,0) is at the top left of the image.&#xD;&#xA; 1. camera space: (0,0) is at the middle of the image.&#xD;&#xA; 1. world space: (0,0) is outside of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, I convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    double[] cam=(Cam2World((new double[]{0,0,1})));&#xD;&#xA;	double[] lum=(Cam2World((new double[]{0,0,1})));&#xD;&#xA;    double[] E=new double[3];&#xD;&#xA;			double[] L=new double[3];&#xD;&#xA;			double[] H=new double[3];&#xD;&#xA;			double D2;&#xD;&#xA;			Mat image=new Mat(rows,cols,CvType.CV_8UC3);&#xD;&#xA;			System.out.println(&quot;Start!!&quot;);&#xD;&#xA;			System.out.println(&quot;ok&quot;);&#xD;&#xA;			for(int i=0;i&lt;tileHNumber;i++)&#xD;&#xA;			{&#xD;&#xA;				for(int j=0;j&lt;tileWNumber;j++)&#xD;&#xA;				{&#xD;&#xA;					for(int s=0;s&lt;192;s++)&#xD;&#xA;					{&#xD;&#xA;						for(int t=0;t&lt;192;t++)&#xD;&#xA;						{&#xD;&#xA;							originS=s+192*i;//ligne&#xD;&#xA;							originT=t+192*j;//colonne&#xD;&#xA;							double[] pos=Cam2World((Image2Cam(new double[]{originT,originS,0})));&#xD;&#xA;							E=normalize(XY(pos,cam));&#xD;&#xA;							L=calculeL(pos, lum);&#xD;&#xA;							double[] le=addXY(L,E);&#xD;&#xA;							H=normalize(le);&#xD;&#xA;							D2=dot(E,E);&#xD;&#xA;							double blue=color(blueColor,pos,E,L,H,D2);&#xD;&#xA;							double green=color(greenColor,pos,E,L,H,D2);&#xD;&#xA;							double red=color(redColor,pos,E,L,H,D2);&#xD;&#xA;							image.put(originS, originT, new byte[]{(byte)(blue),(byte)(green),(byte)(red)});&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;     public static double color(double col,double[] pos,double[] E,double[] L,double[] H,double D2)&#xD;&#xA;	 {&#xD;&#xA;		double value=0;&#xD;&#xA;		double[] N=normalize((new double[]{pos[0],pos[1],1}));&#xD;&#xA;		double diffuse=Math.max(0, dot(N,L));	&#xD;&#xA;		double specular=Math.pow(Math.max(0, dot(N,H)),60);&#xD;&#xA;		value=d*diffuse*0.5+0.2*d+specular*255*0.3;&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The 2 images below show my results: the first one is obtained when the camera space is at the middle and left of the image. The second one is obtained when the camera space is at the middle of the image. With the last image result, we can see exactly the ambient color (at the most left) and the diffuse + specular color is at the right.&#xD;&#xA;&#xD;&#xA;Of course the lobe specular should be a circle (in my opinion) but not like this. That's why I am asking.&#xD;&#xA;&#xD;&#xA;[![Image space at the middle and left of the image][1]][1]&#xD;&#xA;[![Image space at the middle of the image][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NI2j6.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Mm4Z8.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7887" PostHistoryTypeId="2" PostId="3775" RevisionGUID="c64648a4-3ef1-4888-b6ad-16e8f483b10b" CreationDate="2016-07-20T11:03:49.183" UserId="4770" Text="&lt;br&gt;&#xD;&#xA;In a recent version of uTorrent , if you open the **About** Window, you will see an animated background , which is kind of waves that go on forever.&lt;br&gt;&#xD;&#xA;How can this be achieved? Is this kind of a well-known algorithm/class of algorithms?&lt;br&gt;&#xD;&#xA;Thanks.&lt;br&gt;&#xD;&#xA;Edit: Here is an (static) image.&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oKtmm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="7888" PostHistoryTypeId="1" PostId="3775" RevisionGUID="c64648a4-3ef1-4888-b6ad-16e8f483b10b" CreationDate="2016-07-20T11:03:49.183" UserId="4770" Text="What algorithm is used in the animation of the uTorrent 's &quot;About window&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7889" PostHistoryTypeId="3" PostId="3775" RevisionGUID="c64648a4-3ef1-4888-b6ad-16e8f483b10b" CreationDate="2016-07-20T11:03:49.183" UserId="4770" Text="|algorithm|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7890" PostHistoryTypeId="5" PostId="3775" RevisionGUID="9c6c8a8d-9ca1-4309-878d-a851469e7bd5" CreationDate="2016-07-20T11:29:55.937" UserId="4770" Comment="deleted 6 characters in body" Text="&lt;br&gt;&#xD;&#xA;In a recent version of uTorrent , if you open the **About** Window, you will see an animated background , which is kind of waves that go on forever.&lt;br&gt;&#xD;&#xA;How can this be achieved? Is this kind of a well-known algorithm/class of algorithms?&lt;br&gt;&#xD;&#xA;Thanks.&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6us3F.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="7891" PostHistoryTypeId="2" PostId="3776" RevisionGUID="260167ca-1a38-49b4-addd-789880585468" CreationDate="2016-07-20T11:53:09.083" UserId="4770" Text="After some searching, I found out it's called Plasma. &lt;br&gt;&#xD;&#xA;[Plasma Effect][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.bidouille.org/prog/plasma" ContentLicense="CC BY-SA 3.0" />
  <row Id="7892" PostHistoryTypeId="2" PostId="3777" RevisionGUID="20520344-2176-457c-9a8d-54376d3a3a91" CreationDate="2016-07-20T12:24:45.157" UserId="231" Text="As you discovered and mentioned in your self-answer, the pattern in the background appears to be a sum of sinusoidal gradients.&#xD;&#xA;&#xD;&#xA;However, the example linked to in your answer is more complicated than that used by µTorrent. The background of the About window appears to be a static pattern, rather than the animated sinusoidal pattern used in the plasma post.&#xD;&#xA;&#xD;&#xA;Several sinusoidal gradients have been summed to give a single image, and the illusion of movement is given by simply cycling the colours in that one image, rather than generating a number of different images. This is most noticeable if you focus on the centre of one of the rings of colour. In the µTorrent pattern you will notice that each ring stays in one place, and has colour flowing either into it or out of it. In contrast, the rings of colour in the fully animated pattern move around, occasionally dividing or merging.&#xD;&#xA;&#xD;&#xA;The simplified approach used by µTorrent is reminiscent of animations used in the past when recalculating the sinusoidal patterns each frame was not realistic." ContentLicense="CC BY-SA 3.0" />
  <row Id="7894" PostHistoryTypeId="2" PostId="3779" RevisionGUID="9cfd7849-573e-47c7-bc7d-f7b0b0ffedd0" CreationDate="2016-07-20T13:48:38.443" UserId="4765" Text="# Question #&#xD;&#xA;&#xD;&#xA;How to manage data (GPU,CPU) for dynamic label placement in 3dfor thousands of objects (OpenGL)?&#xD;&#xA;&#xD;&#xA;# Details #&#xD;&#xA;objects:&#xD;&#xA;&#xD;&#xA; - **count:** 2k-10k&#xD;&#xA; - **type:** points/quads&#xD;&#xA;&#xD;&#xA;labels: &#xD;&#xA;&#xD;&#xA; - **bilboarding**&#xD;&#xA; - **data**: text and colors&#xD;&#xA;&#xD;&#xA;placing:&#xD;&#xA; &#xD;&#xA; - **labels are not overlaping**&#xD;&#xA;&#xD;&#xA;more on this in my another [question][1]&#xD;&#xA;&#xD;&#xA;# Elaboration #&#xD;&#xA;To calculate label placing I need screen space coordinates. There are lots of algorithms for the purpose, but I do not even know if they are implementable (w/o some hard hacking) on shaders since Vertex Shader has access to only one vertex. But with many objects calculating matrix multiplication (MVP * vertex position) for all vertexes so as to get screen-space coordinates on CPU-side and sending them each frame seems to be fairly slow and badly designed, imo. &#xD;&#xA;&#xD;&#xA;So, should I:&#xD;&#xA;&#xD;&#xA; - compute screen-space coordinates on CPU and send them to GPU so as to draw objects, compute label placing on CPU and send data to GPU&#xD;&#xA; - send only vertice's word coordinates and calculate screen space coordinates on GPU, then somehow implement label placing on GPU&#xD;&#xA; - Read the GPU-side calculated screen-side coordinates and compute on CPU&#xD;&#xA; - something different&#xD;&#xA;&#xD;&#xA;I know that it depends on the load on CPU/GPU from other things, but what do you think?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/3765/proper-architecture-for-rendering-history-of-stramed-data-points" ContentLicense="CC BY-SA 3.0" />
  <row Id="7895" PostHistoryTypeId="1" PostId="3779" RevisionGUID="9cfd7849-573e-47c7-bc7d-f7b0b0ffedd0" CreationDate="2016-07-20T13:48:38.443" UserId="4765" Text="Label Placing for thousands of objects with OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="7896" PostHistoryTypeId="3" PostId="3779" RevisionGUID="9cfd7849-573e-47c7-bc7d-f7b0b0ffedd0" CreationDate="2016-07-20T13:48:38.443" UserId="4765" Text="|opengl|shader|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7898" PostHistoryTypeId="2" PostId="3780" RevisionGUID="efb52d4a-1906-43b6-8014-3e896d73fe1b" CreationDate="2016-07-20T19:10:42.160" UserId="4497" Text="I am grabbing video from a web cam using Microsoft Media Foundation. The image data is in YUY2 format. The pixels are packed in a 4:2:2 ratio. The color format is YCbCr. The color data gets repeated 2x. Ex the packed pixel data is:&#xD;&#xA;&#xD;&#xA;    u y1 v y0&#xD;&#xA;&#xD;&#xA;Gets unpacked to 2 pixels:&#xD;&#xA;&#xD;&#xA;    y0 u v and y1 u v&#xD;&#xA;&#xD;&#xA;I want to use this data as an OpenGL texture. The question is: is there a way to pass this type of texture to `glTexImage2D` as-is? Or do I need to unpack it first? I would like you keep the YCbCr color and convert to RGBA in a shader.&#xD;&#xA;&#xD;&#xA;(I know I can use OpenCV to get video - I've already done that. I am trying a more low level solution mostly as a learning experience)." ContentLicense="CC BY-SA 3.0" />
  <row Id="7899" PostHistoryTypeId="1" PostId="3780" RevisionGUID="efb52d4a-1906-43b6-8014-3e896d73fe1b" CreationDate="2016-07-20T19:10:42.160" UserId="4497" Text="Pixel packed texture source" ContentLicense="CC BY-SA 3.0" />
  <row Id="7900" PostHistoryTypeId="3" PostId="3780" RevisionGUID="efb52d4a-1906-43b6-8014-3e896d73fe1b" CreationDate="2016-07-20T19:10:42.160" UserId="4497" Text="|opengl|texture|pixels|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7901" PostHistoryTypeId="5" PostId="3766" RevisionGUID="743d831b-7362-4f4e-8c88-5ba732ef52cb" CreationDate="2016-07-20T21:19:56.127" UserId="4524" Comment="deleted 18 characters in body" Text="Edit: changed the answer according to new images and clarification.&#xD;&#xA;&#xD;&#xA;    for every control point p(k, n)&#xD;&#xA;       p'(k, n) = ( p(k, n) - p(k) ) * d * l(k) + p(k, n)&#xD;&#xA;&#xD;&#xA;where `k` is the row index and `n` is the column index of control point. `l` is the elevation factor and is equal to {-1, -1/3, 1/3, 1}. `p(k)` is the center of the k'th row." ContentLicense="CC BY-SA 3.0" />
  <row Id="7902" PostHistoryTypeId="5" PostId="3765" RevisionGUID="aef12785-1ac4-4654-96e6-263ae46b78ef" CreationDate="2016-07-20T21:42:33.880" UserId="231" Comment="Correct formatting to hopefully appear as originally intended. Please revert anything which changes your intention." Text="# Overview&#xD;&#xA;&#xD;&#xA;My program receives some data points (0-400 per sec). &#xD;&#xA;&#xD;&#xA;    // simplified example of point's data structure&#xD;&#xA;    struct Point {&#xD;&#xA;        QPoint p;&#xD;&#xA;        QTime t;&#xD;&#xA;        quint32 value;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* I need to render some filtered points (eg. that `point.time &gt; currentTime-5` and `point.value&gt;5`).&#xD;&#xA;* I need to store data history (up to ~50'000 points).&#xD;&#xA;* The data can be used also on the CPU. &#xD;&#xA;* I will use object-picking. &#xD;&#xA;* Points are rendered in 3d.&#xD;&#xA;* Camera position can change, but points data is constant.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;What is the best architecture to implement this kind of problem? What are best practices with this kind of data and what are practices to avoid?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Possible solutions&#xD;&#xA;&#xD;&#xA;* Storing and filtering data.&#xD;&#xA;1. Store the data on the CPU (world coordinates), filtering data on a CPU and sending filtered data to VBO, calculating screen-space coordinates with shaders.&#xD;&#xA;2. Store the data on a CPU and a GPU (update a VBO when some new point arrives).  &#xD;&#xA;Filter points on CPU and calculate offsets and use `glMultiDrawArrays`.&#xD;&#xA;3. Store the data only on a GPU (update VBO when point arrives).  &#xD;&#xA;Filter it with shaders, get data from VBO to CPU when needed.&#xD;&#xA;&#xD;&#xA;Solution 1. is fairly easy, but I think it is a bad practice.  &#xD;&#xA;Solution 2. has data duplication, but it is easy to filter the data.  &#xD;&#xA;Solution 3. has data reading GPU-&gt;CPU.&#xD;&#xA;&#xD;&#xA;I tried those solutions, and Solution 2. occurs to me as the best, but there are some issues with it:&#xD;&#xA;&#xD;&#xA;* Multiplication of data has to be handled gently.&#xD;&#xA;* It is not the easiest-to-read-and-modify solution.&#xD;&#xA;* When there are changes in data there is a lot of things to change.  &#xD;&#xA;I used something like circular buffer on VBO and send offsets to render on it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Environment&#xD;&#xA;&#xD;&#xA;* OpenGL 3.3&#xD;&#xA;* Qt 5+ bindings&#xD;&#xA;* Linux&#xD;&#xA;&#xD;&#xA;PS  &#xD;&#xA;I am fairly new to computer graphics and openGL, so maybe this kind of problem even has its name. I changed my implementations few times, it took me a lot of time and I am not happy with it due to its complexity. Any materials, guides and thoughts are welcome. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7905" PostHistoryTypeId="5" PostId="3766" RevisionGUID="459f954b-e0f2-4e3c-931d-1711f5513571" CreationDate="2016-07-21T05:57:56.017" UserId="4524" Comment="added 28 characters in body" Text="Edit: changed the answer according to new images and clarification.&#xD;&#xA;&#xD;&#xA;    for every control point p(k, n)&#xD;&#xA;       p'(k, n) = ( p(k, n) - p(k) ) * d * l(k) + p(k, n)&#xD;&#xA;&#xD;&#xA;where `k` is the row index and `n` is the column index of control point. `l` is the elevation factor and is equal to {-1, -1/3, 1/3, 1}. `p(k)` is the center of the k'th row.&#xD;&#xA;&#xD;&#xA;Rationale:&#xD;&#xA;From the new" ContentLicense="CC BY-SA 3.0" />
  <row Id="7906" PostHistoryTypeId="5" PostId="3766" RevisionGUID="188edf3c-7540-45e4-9b1f-2163ec55e972" CreationDate="2016-07-21T06:11:39.750" UserId="4524" Comment="added 28 characters in body" Text="Edit: changed the answer according to new images and clarification.&#xD;&#xA;&#xD;&#xA;    for every control point p(k, n)&#xD;&#xA;       p'(k, n) = ( p(k, n) - p(k) ) * d * l(k) + p(k, n)&#xD;&#xA;&#xD;&#xA;where `k` is the row index and `n` is the column index of control point. `l` is the elevation factor and is equal to {-1, -1/3, 1/3, 1}. `p(k)` is the center of the k'th row.&#xD;&#xA;&#xD;&#xA;**Rationale:**&#xD;&#xA;&#xD;&#xA;From the new images, red and blue lines are drawn from the center of the line (p(k) which is basically (k, 0)) to that point. On the first line, all control points, including the ones on the graph (red lines) are moved to the same point on that line. p(k, n) - p(k) gives the vector which moves a point from p(k) to p(k, n) which now should be applied to the other way, moving the point to the desired location. On your graphs, d = 1 so that all first line points would be moved to the center. You can easily solve the equation to verify this. `d * l(0)` is -1, so it would be `-p(k, n) + p(k) + p(k, n)` which would give p(k).&#xD;&#xA;&#xD;&#xA;On the second line, your blue line is again from point to the center, but this time it stopped before reaching it. I cannot tell if it really is cut from 1/3 but that would be a good starting point. So the same formula still applies. l is -1/3 d is 1, so the point would be moved in 1/3 of the way. 3rd is the same as the second but it now moves outwards, thus l is 1/3.&#xD;&#xA;&#xD;&#xA;On the final line, all control points are moved out from the center point of that line. This is quite clear since your lines meet up at that center.&#xD;&#xA;&#xD;&#xA;The only problem this formula can have is assumption of 1/3, other than that I do not see the reason why it should fail. &#xD;&#xA;&#xD;&#xA;**Note:** I used row, column while indexing, thus if you are using x, y you should switch their locations." ContentLicense="CC BY-SA 3.0" />
  <row Id="7914" PostHistoryTypeId="5" PostId="3764" RevisionGUID="4d05e952-1adc-4c23-b445-30db998d37a6" CreationDate="2016-07-21T19:25:05.490" UserId="4761" Comment="deleted 559 characters in body" Text="I am trying to simulate the image warp effect, that is used in Adobe Photoshop.&#xD;&#xA;&#xD;&#xA;The rectangular image is warped according to a cubic Bézier surface (in 2D, all Z components are 0). Having any Bézier surface, **vertical distortion** $d \in[0,1]$ can be applied to it.&#xD;&#xA;&#xD;&#xA;**Left**: input bézier surface, $d=0$, **Right**: output surface,  $d=0.8$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea, what is done to the Bézier surface (16 points), when converting from the version on the left to the output on the right?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VHlGk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WyOAa.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7IGo8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xuTih.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bq7Vd.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/iHYiE.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7920" PostHistoryTypeId="4" PostId="3765" RevisionGUID="e9f1f663-bff8-409c-8e75-3095b78b99a0" CreationDate="2016-07-22T12:36:48.907" UserId="231" Comment="Minor typo in title" Text="Proper architecture for rendering history of streamed data (points)" ContentLicense="CC BY-SA 3.0" />
  <row Id="7922" PostHistoryTypeId="2" PostId="3783" RevisionGUID="6d29ee64-fd80-4aea-b9c1-3de3d4193f3b" CreationDate="2016-07-22T16:58:36.673" UserId="48" Text="My advice would actually be to stick with solution 1 unless and until something more is needed. It's the simplest and easiest to understand, and it should be quite feasible to make it perform well.&#xD;&#xA;&#xD;&#xA;On the one hand, it may seem wasteful to re-filter the points and re-upload a bunch of data to the VBO every frame. I guess that this is why you say it is a &quot;bad practice&quot;. But consider the total amount of data involved. An order-of-magnitude estimate shows that processing this amount of data every frame is not much work for a modern computer.&#xD;&#xA;&#xD;&#xA;The `Point` struct you quote looks like it's about 20 bytes (assuming that `p` is 3 floats and `t` is one float or int). With 50,000 points, the total size of the data is about 1 MB. Even if your actual data struct is a bit larger, still the total size of the data is only a few MB&amp;mdash;a small amount by today's standards. The time needed to process this amount of data on the CPU, and transfer it to the GPU, is on the order of ~0.1 ms. (Assuming ~20 GB/sec CPU bandwidth, and ~8 GB/sec PCIe transfer bandwidth.) So, this is an entirely reasonable amount of data to re-process each frame, and in fact you could handle many times more without stressing your system at all.&#xD;&#xA;&#xD;&#xA;So, just keep things simple and efficient for memory access: store the points in a big flat array (maybe using a ring buffer to allow new incoming points to overwrite old ones, if that makes sense). Each frame, scan the points using a tight loop on the CPU, and copy the ones that pass the filter into the VBO. For best efficiency, probably you should use `GL_DYNAMIC_DRAW` usage when you create the VBO, then use [`glMapBuffer`](http://docs.gl/gl3/glMapBuffer) each frame and copy the filtered points directly into the mapped buffer. Then unmap the buffer and issue the drawing commands, using a vertex shader to transform the points to screen-space as usual." ContentLicense="CC BY-SA 3.0" />
  <row Id="7923" PostHistoryTypeId="5" PostId="3783" RevisionGUID="1776b9cb-9e13-4f58-a494-22d14409e01d" CreationDate="2016-07-22T17:08:40.300" UserId="48" Comment="added note about buffer invalidation, and formatted the long paragraph as a list" Text="My advice would actually be to stick with solution 1 unless and until something more is needed. It's the simplest and easiest to understand, and it should be quite feasible to make it perform well.&#xD;&#xA;&#xD;&#xA;On the one hand, it may seem wasteful to re-filter the points and re-upload a bunch of data to the VBO every frame. I guess that this is why you say it is a &quot;bad practice&quot;. But consider the total amount of data involved. An order-of-magnitude estimate shows that processing this amount of data every frame is not much work for a modern computer.&#xD;&#xA;&#xD;&#xA;The `Point` struct you quote looks like it's about 20 bytes (assuming that `p` is 3 floats and `t` is one float or int). With 50,000 points, the total size of the data is about 1 MB. Even if your actual data struct is a bit larger, still the total size of the data is only a few MB&amp;mdash;a small amount by today's standards. The time needed to process this amount of data on the CPU, and transfer it to the GPU, is on the order of ~0.1 ms. (Assuming ~20 GB/sec CPU bandwidth, and ~8 GB/sec PCIe transfer bandwidth.) So, this is an entirely reasonable amount of data to re-process each frame, and in fact you could handle many times more without stressing your system at all.&#xD;&#xA;&#xD;&#xA;So, just keep things simple and efficient for memory access:&#xD;&#xA;&#xD;&#xA;1. Store the points in a big flat array (maybe using a ring buffer to allow new incoming points to overwrite old ones).&#xD;&#xA;2. Each frame, scan the points using a tight loop on the CPU, and copy the ones that pass the filter into the VBO.&#xD;&#xA; * For best efficiency, probably you should use `GL_DYNAMIC_DRAW` usage when you create the VBO, then use [`glMapBufferRange`](http://docs.gl/gl3/glMapBufferRange) each frame and copy the filtered points directly into the mapped buffer.&#xD;&#xA; * Use `GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT` for the `access` parameter to `glMapBufferRange`; this will allow the GL driver to perform under-the-hood double-buffering to stream the data to the GPU efficiently. For more information on what's going on here, see [Buffer Object Streaming](https://www.opengl.org/wiki/Buffer_Object_Streaming).&#xD;&#xA;3. Then unmap the buffer and issue the drawing commands, using a vertex shader to transform the points to screen-space as usual." ContentLicense="CC BY-SA 3.0" />
  <row Id="7925" PostHistoryTypeId="2" PostId="3784" RevisionGUID="3b978e97-24a5-4a5e-b140-14ae555aa953" CreationDate="2016-07-22T19:42:31.390" UserId="48" Text="There are  a couple of ways to answer this question: an algebraic way and a geometric way.&#xD;&#xA;&#xD;&#xA;Algebraically, we can identify the units that the BRDF must have by looking at its place in the rendering equation. The classic rendering equation is:&#xD;&#xA;&#xD;&#xA;$$L_\text{outgoing}(\omega) = L_\text{emitted}(\omega) + \int_\Omega L_\text{incoming}(\omega') \, f_\text{BRDF}(\omega, \omega') \, (n \cdot \omega') \, d\omega'$$&#xD;&#xA;&#xD;&#xA;The output value on the left is a radiance, so the result of the integral must also be a radiance. The integrand contains a radiance multiplied by a solid angle $d\omega'$, so something else in the integrand has to cancel out that factor of solid angle. The $n \cdot \omega'$ factor is dimensionless, and the only other thing there is the BRDF&amp;mdash;so to make the whole thing work out, the BRDF must have units of inverse solid angle. Equivalently, the BRDF can be seen as a ratio of radiance to irradiance, since they differ by a factor of solid angle in the denominator of radiance.&#xD;&#xA;&#xD;&#xA;Another way to see it is that the BRDF plays a role similar to a probability density. If you look at how probability densities work, they have units inverse to the volume of their domain. For instance, a 1D probability density has units of inverse length (probability per unit length, but probability itself is dimensionless), a 2D one has units of inverse area, and so on. The BRDF acts much like a probability density defined on the hemisphere, giving a likelihood for a photon coming in from a given direction to be reflected into some other direction. So, like any other probability density on a spherical domain, it has units of inverse solid angle.&#xD;&#xA;&#xD;&#xA;Geometrically, we can get right down to brass tacks and take apart what's going on in the integral in the rendering equation. Recall that an integral means to subdivide the domain into tiny pieces and sum the integrand over all the pieces (in the limit as the pieces get infinitesimally small). Let's look at one such piece. The integrand should result in an infinitesimal amount of radiance $dL$, since we're going to sum over many pieces to arrive at a finite outgoing radiance. So a single infinitesimal piece of the integral looks like:&#xD;&#xA;&#xD;&#xA;$$dL = L_\text{incoming} \, f_\text{BRDF} \, (n \cdot \omega') \, d\omega'$$&#xD;&#xA;&#xD;&#xA;If we regroup the factors a bit, the combination $L_\text{incoming} \, (n \cdot \omega') \, d\omega'$ calculates the irradiance on the surface due to the light coming from the infinitesimal solid angle $d\omega'$. Since it's arriving from an infinitesimal amount of solid angle, it produces an infinitesimal irradiance $dE$.&#xD;&#xA;&#xD;&#xA;$$dL = f_\text{BRDF} \, dE$$&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;$$f_\text{BRDF} = \frac{dL}{dE}$$&#xD;&#xA;&#xD;&#xA;So the BRDF acts as a proportionality constant between the infinitesimal irradiance arriving at the surface from an infinitesimal solid angle, and the infinitesimal outgoing radiance generated thereby. It couldn't be a ratio of radiances, because we have a _finite_ incoming radiance, and we need an _infinitesimal_ outgoing radiance if we want to sum up many pieces of the integral and get a finite result. To make that happen, the BRDF would have to be infinitesimal-valued, which...isn't a thing, in standard mathematics. :)&#xD;&#xA;&#xD;&#xA;I hope some of this helps. There are a variety of equivalent ways to look at this problem, as with so many things in math and physics." ContentLicense="CC BY-SA 3.0" />
  <row Id="7926" PostHistoryTypeId="2" PostId="3785" RevisionGUID="e4069e4f-6e14-40e5-ac50-306d5fa1678a" CreationDate="2016-07-22T21:03:41.297" UserId="58" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional create a CPU thread + collect results approach.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict ahead of time which would be better.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL if since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content." ContentLicense="CC BY-SA 3.0" />
  <row Id="7927" PostHistoryTypeId="5" PostId="3785" RevisionGUID="bb4f0f6c-eabb-4c1c-8fb3-01163cb4266e" CreationDate="2016-07-22T21:09:43.097" UserId="58" Comment="mention existence of alternative algorithms" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional create a CPU thread + collect results approach.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;There are more clever overlap correction algorithms, most of which are approximate, but this one can in principle perfectly correct overlap and is simple to implement and understand.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict ahead of time which would be better.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL if since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content." ContentLicense="CC BY-SA 3.0" />
  <row Id="7928" PostHistoryTypeId="5" PostId="3785" RevisionGUID="63d610ff-1064-4d5c-9ad2-ab16d23c8308" CreationDate="2016-07-22T21:26:08.363" UserId="58" Comment="one last edit! promise!" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional 'create a CPU thread + collect results' approach, or even run in the main thread if the task is lightweight enough.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Now place the corresponding label somewhere nearby.&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;Note that the adjustment loop is only adjusting the label its compute shader was assigned. To avoid position read/write race conditions, it is best to use a temporary position and fence every time you decide whether to continue the loop. Here is an example:&#xD;&#xA;&#xD;&#xA;    bool overlap = true;&#xD;&#xA;    uint maxIters = 5;&#xD;&#xA;    vec3 tempPos = label[kernelIndex].pos;&#xD;&#xA;    for (uint numIters = 0; overlap &amp;&amp; numIters &lt; maxIters; numIters++)&#xD;&#xA;    {&#xD;&#xA;        for (each labelIndex)&#xD;&#xA;        {   &#xD;&#xA;            // Of course a label overlaps itself!&#xD;&#xA;            if (labelIndex == kernelIndex)&#xD;&#xA;                continue;&#xD;&#xA;            // ...check overlap and adjust position of tempPos...  &#xD;&#xA;        }&#xD;&#xA;        label[kernelIndex].pos = tempPos;&#xD;&#xA;        fence();&#xD;&#xA;    }   &#xD;&#xA;&#xD;&#xA;Of course avoiding fencing as much as possible and avoiding cross-kernel talk of any kind is ideal, but for this problem you can't completely avoid it. Still, I'd try turning off the fence in the loop and see what happens to perf and output. =)&#xD;&#xA;&#xD;&#xA;There are more clever overlap correction algorithms, most of which are approximate, but this one can in principle perfectly correct overlap and is simple to implement and understand.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict ahead of time which would be better.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL if since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content." ContentLicense="CC BY-SA 3.0" />
  <row Id="7929" PostHistoryTypeId="5" PostId="3785" RevisionGUID="c92ed58a-c07c-4dbe-a2d6-2b19f1f5e1ec" CreationDate="2016-07-22T21:38:00.953" UserId="58" Comment="expanded code sample" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional 'create a CPU thread + collect results' approach, or even run in the main thread if the task is lightweight enough.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice. That said, you could lead a vertex buffer with vertex positions at each object world position, then transform the vertices to screen space (see below) in the vertex shader, but considering you are dealing with OpenGL 3.3 you will probably be limited to writing the output label positions to textures via render to texture or transform feedback buffers which may be slow depending on the hardware. If you can use the shader image load store extension, it could help, but bending the graphics pipeline to GPGPU is all probably more work than it is worth.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Now place the corresponding label somewhere nearby.&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;Note that the adjustment loop is only adjusting the label its compute shader was assigned. To avoid position read/write race conditions, it is best to use a temporary position and fence every time you decide whether to continue the loop. Here is an example:&#xD;&#xA;&#xD;&#xA;    vec4 objectScreenPos = camera.projViewTrans * object[kernelIndex].worldPos;&#xD;&#xA;&#xD;&#xA;    label[kernelIndex].pos = objectScreenPos.xyz + someOffset;&#xD;&#xA;&#xD;&#xA;    fence();&#xD;&#xA;&#xD;&#xA;    bool overlap = true;&#xD;&#xA;    uint maxIters = 5;&#xD;&#xA;    vec3 tempPos = label[kernelIndex].pos;&#xD;&#xA;    for (uint numIters = 0; overlap &amp;&amp; numIters &lt; maxIters; numIters++)&#xD;&#xA;    {&#xD;&#xA;        for (each labelIndex)&#xD;&#xA;        {   &#xD;&#xA;            // Of course a label overlaps itself!&#xD;&#xA;            if (labelIndex == kernelIndex)&#xD;&#xA;                continue;&#xD;&#xA;            // ...check overlap and adjust position of tempPos...  &#xD;&#xA;        }&#xD;&#xA;        label[kernelIndex].pos = tempPos;&#xD;&#xA;        fence();&#xD;&#xA;    }   &#xD;&#xA;&#xD;&#xA;Of course avoiding fencing as much as possible and avoiding cross-kernel talk of any kind is ideal, but for this problem you can't completely avoid it. Still, I'd try turning off the fence in the loop and see what happens to perf and output. =)&#xD;&#xA;&#xD;&#xA;There are more clever overlap correction algorithms, most of which are approximate, but this one can in principle perfectly correct overlap and is simple to implement and understand.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict ahead of time which would be better.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL if since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content." ContentLicense="CC BY-SA 3.0" />
  <row Id="7930" PostHistoryTypeId="5" PostId="3785" RevisionGUID="66d13525-b65b-411e-91b8-9ce9c0bd2099" CreationDate="2016-07-22T21:46:45.090" UserId="58" Comment="mention screen space coordinate system" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional 'create a CPU thread + collect results' approach, or even run in the main thread if the task is lightweight enough.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice. That said, you could lead a vertex buffer with vertex positions at each object world position, then transform the vertices to screen space (see below) in the vertex shader, but considering you are dealing with OpenGL 3.3 you will probably be limited to writing the output label positions to textures via render to texture or transform feedback buffers which may be slow depending on the hardware. If you can use the shader image load store extension, it could help, but bending the graphics pipeline to GPGPU is all probably more work than it is worth.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Now place the corresponding label somewhere nearby.&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;Note that the adjustment loop is only adjusting the label its compute shader was assigned. To avoid position read/write race conditions, it is best to use a temporary position and fence every time you decide whether to continue the loop. Here is an example:&#xD;&#xA;&#xD;&#xA;    vec4 objectScreenPos = camera.projViewTrans * object[kernelIndex].worldPos;&#xD;&#xA;&#xD;&#xA;    //...transform objectScreenPos to desired coordinate &#xD;&#xA;    // system if needed; either [0,1] or [-1,1] or whatever &#xD;&#xA;    // depending on your projViewTrans and needs of your &#xD;&#xA;    // overlap correction algorithm...&#xD;&#xA;&#xD;&#xA;    label[kernelIndex].pos = objectScreenPos.xyz + someOffset;&#xD;&#xA;&#xD;&#xA;    fence();&#xD;&#xA;&#xD;&#xA;    bool overlap = true;&#xD;&#xA;    uint maxIters = 5;&#xD;&#xA;    vec3 tempPos = label[kernelIndex].pos;&#xD;&#xA;    for (uint numIters = 0; overlap &amp;&amp; numIters &lt; maxIters; numIters++)&#xD;&#xA;    {&#xD;&#xA;        for (each labelIndex)&#xD;&#xA;        {   &#xD;&#xA;            // Of course a label overlaps itself!&#xD;&#xA;            if (labelIndex == kernelIndex)&#xD;&#xA;                continue;&#xD;&#xA;            // ...check overlap and adjust position of tempPos...  &#xD;&#xA;        }&#xD;&#xA;        label[kernelIndex].pos = tempPos;&#xD;&#xA;        fence();&#xD;&#xA;    }   &#xD;&#xA;&#xD;&#xA;Of course avoiding fencing as much as possible and avoiding cross-kernel talk of any kind is ideal, but for this problem you can't completely avoid it. Still, I'd try turning off the fence in the loop and see what happens to perf and output. =)&#xD;&#xA;&#xD;&#xA;There are more clever overlap correction algorithms, most of which are approximate, but this one can in principle perfectly correct overlap and is simple to implement and understand.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict ahead of time which would be better.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL if since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content." ContentLicense="CC BY-SA 3.0" />
  <row Id="7931" PostHistoryTypeId="2" PostId="3786" RevisionGUID="7b106ec2-6490-4bfb-90cf-90b66e0611da" CreationDate="2016-07-22T21:46:50.497" UserId="523" Text="&gt; The question is: is there a way to pass this type of texture to glTexImage2D as-is?&#xD;&#xA;&#xD;&#xA;Yes; you can just pass it as-is, but (looking at [the docs](https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml)) it is not supported directly.  You'll need a custom shader to _interpret_ it.&#xD;&#xA;&#xD;&#xA;Depending on your needs, expanding the pixels first (or even doing the full conversion CPU-side) may be worthwhile.  At a guess, I'd say that expanding the pixels (as you copy from the camera's driver buffer into a staging buffer for upload to the GPU) is a pretty consistently good idea, unless you're extremely bandwidth-saturated.  I'd add the color-space conversion for easier debugging, or if the image doesn't update frequently." ContentLicense="CC BY-SA 3.0" />
  <row Id="7932" PostHistoryTypeId="5" PostId="3785" RevisionGUID="ac0e9e5e-e065-430f-9279-53d5f7586658" CreationDate="2016-07-22T22:07:25.237" UserId="58" Comment="minor wording corrections" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional 'create a CPU thread + collect results' approach, or even run in the main thread if the task is lightweight enough.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice. That said, you could lead a vertex buffer with vertex positions at each object world position, then transform the vertices to screen space (see below) in the vertex shader, but considering you are dealing with OpenGL 3.3 you will probably be limited to writing the output label positions to textures via render to texture or transform feedback buffers which may be slow depending on the hardware. If you can use the shader image load store extension, it could help, but bending the graphics pipeline to GPGPU is all probably more work than it is worth.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Now place the corresponding label somewhere nearby.&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;Note that the adjustment loop is only adjusting the label its compute shader was assigned. To avoid position read/write race conditions, it is best to use a temporary position and fence every time you decide whether to continue the loop. Here is an example:&#xD;&#xA;&#xD;&#xA;    vec4 objectScreenPos = camera.projViewTrans * object[kernelIndex].worldPos;&#xD;&#xA;&#xD;&#xA;    //...transform objectScreenPos to desired coordinate &#xD;&#xA;    // system if needed; either [0,1] or [-1,1] or whatever &#xD;&#xA;    // depending on your projViewTrans and needs of your &#xD;&#xA;    // overlap correction algorithm...&#xD;&#xA;&#xD;&#xA;    label[kernelIndex].pos = objectScreenPos.xyz + someOffset;&#xD;&#xA;&#xD;&#xA;    fence();&#xD;&#xA;&#xD;&#xA;    bool overlap = true;&#xD;&#xA;    uint maxIters = 5;&#xD;&#xA;    vec3 tempPos = label[kernelIndex].pos;&#xD;&#xA;    for (uint numIters = 0; overlap &amp;&amp; numIters &lt; maxIters; numIters++)&#xD;&#xA;    {&#xD;&#xA;        for (each labelIndex)&#xD;&#xA;        {   &#xD;&#xA;            // Of course a label overlaps itself!&#xD;&#xA;            if (labelIndex == kernelIndex)&#xD;&#xA;                continue;&#xD;&#xA;            // ...check overlap and adjust position of tempPos...  &#xD;&#xA;        }&#xD;&#xA;        label[kernelIndex].pos = tempPos;&#xD;&#xA;        fence();&#xD;&#xA;    }   &#xD;&#xA;&#xD;&#xA;Of course avoiding fencing as much as possible and avoiding cross-kernel talk of any kind is ideal, but for this problem you can't completely avoid it. Still, I'd try turning off the fence in the loop and see what happens to perf and output. =)&#xD;&#xA;&#xD;&#xA;There are more clever overlap correction algorithms, most of which are approximate, but this one can in principle perfectly correct overlap and is simple to implement and understand.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict the change ahead of time.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content." ContentLicense="CC BY-SA 3.0" />
  <row Id="7936" PostHistoryTypeId="2" PostId="3788" RevisionGUID="6347093a-7592-4b93-9708-48264395ab75" CreationDate="2016-07-22T22:30:30.157" UserId="3386" Text="It is pretty well known that writing depth in your fragment shader generally disables &quot;early Z&quot; test/write optimizations that modern GPUs rely on for fastness. Nonetheless, APIs still allow it and GPUs still provide support for correct visibility when shaders write arbitrary depth.&#xD;&#xA;&#xD;&#xA;The question is: are there any state of the art real-time effects in today's game engines that require writing Z in the fragment shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7937" PostHistoryTypeId="1" PostId="3788" RevisionGUID="6347093a-7592-4b93-9708-48264395ab75" CreationDate="2016-07-22T22:30:30.157" UserId="3386" Text="What modern real-time rendering applications still use fragment shader depth writes / late-Z?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7938" PostHistoryTypeId="3" PostId="3788" RevisionGUID="6347093a-7592-4b93-9708-48264395ab75" CreationDate="2016-07-22T22:30:30.157" UserId="3386" Text="|gpu|rasterizer|z-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7939" PostHistoryTypeId="2" PostId="3789" RevisionGUID="45b3ee69-1e5e-43d4-8c8f-c03720421527" CreationDate="2016-07-23T04:53:58.660" UserId="48" Text="Any techniques that involve raytracing in the fragment shader might want to write Z in order that the depth buffer contain an accurate representation of the raytraced surface. For example:&#xD;&#xA;&#xD;&#xA; * [Distance-field ray marching](http://iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm), as seen in many shadertoys and demoscene productions. Here, only a full-screen quad gets rasterized, and all the geometry is generated by the fragment shader. Writing Z would be necessary if you want to use the depth buffer for deferred lighting or post-effects, or to composite distance fields with ordinary triangle geometry and get correct occlusion.&#xD;&#xA; * Voxel ray marching, similar to the above. Even when the voxels are translucent (as in a smoke cloud or suchlike), it may be useful to write Z when the voxel density is high enough to become opaque; for instance, that can be useful for later motion blur / depth-of-field calculations.&#xD;&#xA; * [Parallax occlusion mapping](http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262) techniques, in which a flat surface is given the appearance of depth by ray-marching against a heightfield.&#xD;&#xA;&#xD;&#xA;There are probably other similar cases where the shape of a surface is defined by the fragment shader rather than by the rasterized triangles.&#xD;&#xA;&#xD;&#xA;By the way, newer APIs and GPUs include support for a [conservative depth output](https://mynameismjp.wordpress.com/2010/11/14/d3d11-features/) mode, in which the shader-written Z is only allowed to be greater-equal to the geometric Z, but not less. This allows early-Z / hierarchical-Z optimizations to still work based on the geometric Z: if the rasterized geometry gets culled for being behind something, then you know the shader-written Z would have been culled as well. This is a good fit for cases like the above, as you can rasterize some bounding geometry for the distance-field / voxel / heightfield object; then the actual depth will be greater-equal to that of the bounding geometry." ContentLicense="CC BY-SA 3.0" />
  <row Id="7945" PostHistoryTypeId="2" PostId="3791" RevisionGUID="901ee3e4-5777-4949-ae22-2c9429535642" CreationDate="2016-07-26T06:09:08.703" UserId="3073" Text="The effect can be roughly recreated by adding 2 (or more) radial sinusoids together and than animating the resulting phase through another sine function.&#xD;&#xA;&#xD;&#xA;Use www.shadertoy.com to verify.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;     void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;       {&#xD;&#xA;    	   vec2 uv = fragCoord.xy / iResolution.xy;&#xD;&#xA;           float d = sin(length(uv - vec2(0.5)) * 10.0) + sin(length(uv - vec2(0.2)) * 10.0);&#xD;&#xA;           d = sin(d * 10.0 + iGlobalTime * 4.0);&#xD;&#xA;    	   fragColor = vec4(d,d,d,1.0);&#xD;&#xA;       }" ContentLicense="CC BY-SA 3.0" />
  <row Id="7946" PostHistoryTypeId="5" PostId="3791" RevisionGUID="ca737cbf-9af7-4f5a-b384-1c54850cac85" CreationDate="2016-07-26T06:35:42.097" UserId="3073" Comment="added 25 characters in body" Text="The effect can be roughly recreated by adding 2 (or more) radial sinusoids together and than animating the resulting phase through another sine function.&#xD;&#xA;&#xD;&#xA;Use www.shadertoy.com to verify.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;       void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;       {&#xD;&#xA;           vec2 uv = fragCoord.xy / iResolution.xy;&#xD;&#xA;           float d = sin(length(uv - vec2(0.5)) * 35.0) + sin(length(uv - vec2(0.2,0.3)) * 45.0);&#xD;&#xA;           d = sin(d * 4.0 + iGlobalTime * 4.0)*0.5+1.0;&#xD;&#xA;           fragColor = vec4(d,d,d,1.0);&#xD;&#xA;       }" ContentLicense="CC BY-SA 3.0" />
  <row Id="7947" PostHistoryTypeId="5" PostId="3779" RevisionGUID="84e789fc-601b-4c42-afb6-cb6f6a358007" CreationDate="2016-07-26T08:40:43.533" UserId="4765" Comment="added 1 character in body" Text="# Question #&#xD;&#xA;&#xD;&#xA;How to manage data (GPU,CPU) for dynamic label placement in 3d for thousands of objects (OpenGL)?&#xD;&#xA;&#xD;&#xA;# Details #&#xD;&#xA;objects:&#xD;&#xA;&#xD;&#xA; - **count:** 2k-10k&#xD;&#xA; - **type:** points/quads&#xD;&#xA;&#xD;&#xA;labels: &#xD;&#xA;&#xD;&#xA; - **bilboarding**&#xD;&#xA; - **data**: text and colors&#xD;&#xA;&#xD;&#xA;placing:&#xD;&#xA; &#xD;&#xA; - **labels are not overlaping**&#xD;&#xA;&#xD;&#xA;more on this in my another [question][1]&#xD;&#xA;&#xD;&#xA;# Elaboration #&#xD;&#xA;To calculate label placing I need screen space coordinates. There are lots of algorithms for the purpose, but I do not even know if they are implementable (w/o some hard hacking) on shaders since Vertex Shader has access to only one vertex. But with many objects calculating matrix multiplication (MVP * vertex position) for all vertexes so as to get screen-space coordinates on CPU-side and sending them each frame seems to be fairly slow and badly designed, imo. &#xD;&#xA;&#xD;&#xA;So, should I:&#xD;&#xA;&#xD;&#xA; - compute screen-space coordinates on CPU and send them to GPU so as to draw objects, compute label placing on CPU and send data to GPU&#xD;&#xA; - send only vertice's word coordinates and calculate screen space coordinates on GPU, then somehow implement label placing on GPU&#xD;&#xA; - Read the GPU-side calculated screen-side coordinates and compute on CPU&#xD;&#xA; - something different&#xD;&#xA;&#xD;&#xA;I know that it depends on the load on CPU/GPU from other things, but what do you think?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/3765/proper-architecture-for-rendering-history-of-stramed-data-points" ContentLicense="CC BY-SA 3.0" />
  <row Id="7960" PostHistoryTypeId="33" PostId="3746" RevisionGUID="c8b2bdad-67a5-46fd-96fc-38a2ad888f81" CreationDate="2016-07-27T08:35:41.930" UserId="2485" Comment="19" />
  <row Id="7961" PostHistoryTypeId="2" PostId="3794" RevisionGUID="73c87d88-10aa-4404-ae93-7d4c33f59f59" CreationDate="2016-07-27T09:27:21.420" UserId="3073" Text="For case 1&amp;2: You cannot really draw a grid of points in this mode as vertice 0 (the top left one) will be used in every triangle, as well as other issues. You should be using Triangle/Line strips, although these aren't so straightforward as you some vertices are shared between each row.&#xD;&#xA;&#xD;&#xA;For example, imagine you have vertices arranged like so..&#xD;&#xA;&#xD;&#xA;0 1 2&#xD;&#xA;&#xD;&#xA;3 4 5&#xD;&#xA;&#xD;&#xA;6 7 8&#xD;&#xA;&#xD;&#xA;You would draw strips by sending the above vertices in the following order..&#xD;&#xA;&#xD;&#xA;0,3,1 (outputs triangle 0,1,3)&#xD;&#xA;&#xD;&#xA;4,    (outputs triangle 1,3,4)&#xD;&#xA;&#xD;&#xA;2,    (outputs triangle 1,2,4)&#xD;&#xA;&#xD;&#xA;etc..&#xD;&#xA;&#xD;&#xA;This you can do in code by scanning across 1 row of vertices and including the vertex on the next row for every other vertex.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    int numColumns = 5;   // As per your example..&#xD;&#xA;    int numRows = 5;&#xD;&#xA;    int verticeOffset = 0;&#xD;&#xA;    int verticeSize = 3;          // 3 floats per vertice&#xD;&#xA;    int nextRow = numColumns * verticeSize;   &#xD;&#xA;    &#xD;&#xA;    // This loop is for each row-strip, which requires 2 vertex rows..&#xD;&#xA;    for(int j = 0; j &lt; numRows - 1; j++) {&#xD;&#xA;       &#xD;&#xA;        // Inner loop sends vertices for each row-strip&#xD;&#xA;        for(int n = 0; n &lt; numColumns; n++, verticeOffset += verticeSize) {&#xD;&#xA;           glVertex3fv(vertices + verticeOffset);            // Current row&#xD;&#xA;           glVertex3fv(vertices + verticeOffset + nextRow);  // Row below&#xD;&#xA;        }&#xD;&#xA;        // This is special, we send a duplicate vertex to restart a new strip for the next row (This can be omitted if j == numRows - 1)&#xD;&#xA;        glVertex3fv(vertices + verticeOffset - 3 + nextRow);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are concerned about sending duplicate vertices you could use an additional indice buffer, as that will allow you to use the exact same vertex buffer you used for the GL_POINTS version." ContentLicense="CC BY-SA 3.0" />
  <row Id="7962" PostHistoryTypeId="5" PostId="3794" RevisionGUID="fa9d3724-cd28-401b-bd69-019f5cfc920b" CreationDate="2016-07-27T10:09:44.980" UserId="3073" Comment="added 18 characters in body" Text="Your shaders are fine, the problem is topological, that is the way the vertices are connected to create triangles..&#xD;&#xA;&#xD;&#xA;For case 1&amp;2: You cannot really draw a grid of points in this mode (GL_TRIANGLE_FAN) as vertice 0 (the top left one) will be used in every triangle, as well as other issues. You should be using Triangle/Line strips, although these aren't so straightforward as some vertices are shared between each row.&#xD;&#xA;&#xD;&#xA;For example, imagine you have vertices arranged like so..&#xD;&#xA;&#xD;&#xA;0 1 2&#xD;&#xA;&#xD;&#xA;3 4 5&#xD;&#xA;&#xD;&#xA;6 7 8&#xD;&#xA;&#xD;&#xA;You would draw strips by sending the above vertices in the following order..&#xD;&#xA;&#xD;&#xA;0,3,1 (outputs triangle 0,1,3)&#xD;&#xA;&#xD;&#xA;4,    (outputs triangle 1,3,4)&#xD;&#xA;&#xD;&#xA;2,    (outputs triangle 1,2,4)&#xD;&#xA;&#xD;&#xA;etc..&#xD;&#xA;&#xD;&#xA;This you can do in code by scanning across 1 row of vertices and including the vertex on the next row for every other vertex.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    int numColumns = 5;   // As per your example..&#xD;&#xA;    int numRows = 5;&#xD;&#xA;    int verticeOffset = 0;&#xD;&#xA;    int verticeSize = 3;          // 3 floats per vertice&#xD;&#xA;    int nextRow = numColumns * verticeSize;   &#xD;&#xA;    &#xD;&#xA;    // This loop is for each row-strip, which requires 2 vertex rows..&#xD;&#xA;    for(int j = 0; j &lt; numRows - 1; j++) {&#xD;&#xA;       &#xD;&#xA;        // Inner loop sends vertices for each row-strip&#xD;&#xA;        for(int n = 0; n &lt; numColumns; n++, verticeOffset += verticeSize) {&#xD;&#xA;           glVertex3fv(vertices + verticeOffset);            // Current row&#xD;&#xA;           glVertex3fv(vertices + verticeOffset + nextRow);  // Row below&#xD;&#xA;        }&#xD;&#xA;        // This is special, we send a duplicate vertex to restart a new strip for the next row (This can be omitted if j == numRows - 1)&#xD;&#xA;        glVertex3fv(vertices + verticeOffset - 3 + nextRow);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are concerned about sending duplicate vertices you could use an additional indice buffer, as that will allow you to use the exact same vertex buffer you used for the GL_POINTS version." ContentLicense="CC BY-SA 3.0" />
  <row Id="7963" PostHistoryTypeId="5" PostId="3780" RevisionGUID="501cbdc8-f9a1-4457-b6c3-8dff26127be2" CreationDate="2016-07-27T14:22:20.687" UserId="4497" Comment="edited body" Text="I am grabbing video from a web cam using Microsoft Media Foundation. The image data is in YUY2 format. The pixels are packed in a 4:2:2 ratio. The color format is YCbCr. The color data gets repeated 2x. Ex the packed pixel data is:&#xD;&#xA;&#xD;&#xA;    y0 u y1 v&#xD;&#xA;&#xD;&#xA;Gets unpacked to 2 pixels:&#xD;&#xA;&#xD;&#xA;    y0 u v and y1 u v&#xD;&#xA;&#xD;&#xA;I want to use this data as an OpenGL texture. The question is: is there a way to pass this type of texture to `glTexImage2D` as-is? Or do I need to unpack it first? I would like you keep the YCbCr color and convert to RGBA in a shader.&#xD;&#xA;&#xD;&#xA;(I know I can use OpenCV to get video - I've already done that. I am trying a more low level solution mostly as a learning experience)." ContentLicense="CC BY-SA 3.0" />
  <row Id="7964" PostHistoryTypeId="5" PostId="3785" RevisionGUID="cb6add84-80ea-4084-a5a6-fefb0fc81a02" CreationDate="2016-07-27T20:18:15.097" UserId="58" Comment="minor addition" Text="Since you are new to computer graphics, you may be better off avoiding the complications of SIMD and sticking with the traditional 'create a CPU thread + collect results' approach, or even run in the main thread if the task is lightweight enough.&#xD;&#xA;&#xD;&#xA;But if that approach fails to be performant and/or you are willing to dip into OpenCL / GLSL compute shaders, read on...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a per-object calculation, not a per-vertex or fragment calculation, so the traditional graphics pipeline is not the best choice. That said, you could lead a vertex buffer with vertex positions at each object world position, then transform the vertices to screen space (see below) in the vertex shader, but considering you are dealing with OpenGL 3.3 you will probably be limited to writing the output label positions to textures via render to texture or transform feedback buffers which may be slow depending on the hardware. If you can use the shader image load store extension, it could help, but bending the graphics pipeline to GPGPU is all probably more work than it is worth.&#xD;&#xA;&#xD;&#xA;You have not detailed your overlap requirements (i.e., whether it must be perfect or approximate, overlap probability, whether you can guarantee sufficient screen room to achieve perfect non-overlap, whether you need all labels to be on visible screen at all times, etc.), but generally pairwise problems which can give non-convergent iterations when multiple particles are adjusted simultaneously are best done on a single thread on the CPU. It could be a dedicated CPU thread. &#xD;&#xA;&#xD;&#xA;To understand what I mean by non-convergent iterations, imagine a grid of labels whose lower left and upper right corners touch. If they all are adjusted simultaneously in opposite directions of one neighbor, they may end up in a situation where they simply overlap their other neighbor. This cycle may repeat indefinitely since the corner overlaps are opposite. Whether this actually occurs depends on the specifics of the algorithm and the object positions / dimensions, but it is possible unless you can make some object spacing guarantees or some other assumption I am unaware of.&#xD;&#xA;&#xD;&#xA;If you have access to GLSL computer shaders or (even better) OpenCL, and you  do not demand perfect overlap, or predict that overlap will be relatively seldom, the following simple SIMD approach may outperform a single-threaded CPU approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**SIMD algorithm**: At the beginning of each frame (or whatever label update freq. makes sense), pass the object world positions, label dimensions, and camera projection + view transform to a per-object + label pair compute shader / kernel to calculate the screen space positions:&#xD;&#xA;&#xD;&#xA;vec4 objScreenSpacePosition = camera.projectionViewTransform * object.worldPosition;&#xD;&#xA;&#xD;&#xA;Now place the corresponding label somewhere nearby.&#xD;&#xA;&#xD;&#xA;Then place a sync fence in the shader / kernel to ensure all screen space positions have been calculated before proceeding. Finally, perform a pair-wise loop with all other labels and adjust the label position / depth to correct for overlap. You may need to repeat the loop multiple times until all labels have no overlap if you demand absolute assurance of zero overlap, or you could cutoff overlap adjustment after a certain number of iterations to ensure it doesn't take too long or run indefinitely (see above about non-convergence).&#xD;&#xA;&#xD;&#xA;Note that the adjustment loop is only adjusting the label its compute shader was assigned. To avoid position read/write race conditions, it is best to use a temporary position and fence every time you decide whether to continue the loop. Here is an example:&#xD;&#xA;&#xD;&#xA;    vec4 objectScreenPos = camera.projViewTrans * object[kernelIndex].worldPos;&#xD;&#xA;&#xD;&#xA;    //...transform objectScreenPos to desired coordinate &#xD;&#xA;    // system if needed; either [0,1] or [-1,1] or whatever &#xD;&#xA;    // depending on your projViewTrans and needs of your &#xD;&#xA;    // overlap correction algorithm...&#xD;&#xA;&#xD;&#xA;    label[kernelIndex].pos = objectScreenPos.xyz + someOffset;&#xD;&#xA;&#xD;&#xA;    fence();&#xD;&#xA;&#xD;&#xA;    bool overlap = true;&#xD;&#xA;    uint maxIters = 5;&#xD;&#xA;    vec3 tempPos = label[kernelIndex].pos;&#xD;&#xA;    for (uint numIters = 0; overlap &amp;&amp; numIters &lt; maxIters; numIters++)&#xD;&#xA;    {&#xD;&#xA;        for (each labelIndex)&#xD;&#xA;        {   &#xD;&#xA;            // Of course a label overlaps itself!&#xD;&#xA;            if (labelIndex == kernelIndex)&#xD;&#xA;                continue;&#xD;&#xA;            // ...check overlap and adjust position of tempPos...  &#xD;&#xA;        }&#xD;&#xA;        label[kernelIndex].pos = tempPos;&#xD;&#xA;        fence();&#xD;&#xA;    }   &#xD;&#xA;&#xD;&#xA;Of course avoiding fencing as much as possible and avoiding cross-kernel talk of any kind is ideal, but for this problem you can't completely avoid it. Still, I'd try turning off the fence in the loop and see what happens to perf and output. =)&#xD;&#xA;&#xD;&#xA;There are more clever overlap correction algorithms, most of which are approximate, but this one can in principle perfectly correct overlap and is simple to implement and understand.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;A GPGPU or even threaded CPU approach could actually be slower than performing a single-threaded calculation on the CPU, depending on the number of actual objects. This is why OpenCL is ideal for these sorts of problems: it gives you the option of running single or multi-threaded on CPU, or moving to the GPU. You could even switch between CPU and GPU on the fly if the number of objects radically changes over time and you can predict the change ahead of time.&#xD;&#xA;&#xD;&#xA;I would probably write this in OpenCL since if all else fails, I could run it in a single thread on the CPU and come as close as possible to guaranteeing perfect non-overlap. Then I could experiment with multiple threads / GPU calculations and profile, profile, profile to my heart's content.&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;**Update - OpenGL 3.3 graphics pipeline approach**: &#xD;&#xA;&#xD;&#xA;While OpenCL or the OpenGL compute pipeline would be ideal, you should be able modify the above SIMD alg to use the OpenGL 3.3 core graphics pipeline with a bit of extra effort and likely perf loss. Example: During a point draw, pass object positions and IDs as vertex data to a vertex shader that calculates the object screen position. Set glPosition to the object ID and pass the resulting screen position to the fragment shader using the `flat` modifier to prevent interpolation. Render the result to a 1D framebuffer with length equal to number of labels so that there is a 1:1 correspondence between 'pixel' (i.e. label) and vertex (i.e. object). You now have a 1D texture filled with label positions. You could then read this back to the CPU to perform overlap elimination (with possible guarantee of no overlap), then upload the updated label positions to OpenGL in a uniform buffer array, texture, or whatever works best in your situation. Alternatively you could launch a second vertex shader with label IDs as vertex attributes and perform a non-guaranteed overlap elimination which does not depend on the updated positions of the other labels, then follow a similar pattern from before to render the updated positions to a second 1D framebuffer, and finally use the related framebuffer texture as a label ID indexed lookup table during label rendering to determine the final positions of each of the four billboard corner vertices. The label ID could either be passed in using a uniform or vertex attribute.&#xD;&#xA;&#xD;&#xA;Hopefully you are beginning to see how much the GL 3.3 core graphics pipeline limits your options for GPGPU and how much more complicated it makes things. What was before a single compute shader or kernel gets broken into multiple shaders (and possibly multiple draws) where you must abuse the concepts of 'vertex' and 'pixel' to achieve your ends. Achieving good perf with this approach often requires a decent understanding of the graphics pipeline and hardware you are working with. Depending on the hardware, driver, and number of objects, the above graphics pipeline algorithm may not be able to beat simply calculating screen space coordinates and eliminating overlap on the CPU then uploading results to GPU. Hence the reason I suggest you either opt for OpenCL or OpenGL compute, or else stick with traditional CPU threading." ContentLicense="CC BY-SA 3.0" />
  <row Id="7966" PostHistoryTypeId="5" PostId="3794" RevisionGUID="6160f6b0-d5be-49f5-ad08-0ebf7504b682" CreationDate="2016-07-28T04:54:42.790" UserId="3073" Comment="Fixed constant in code example" Text="Your shaders are fine, the problem is topological, that is the way the vertices are connected to create triangles..&#xD;&#xA;&#xD;&#xA;For case 1&amp;2: You cannot really draw a grid of points in this mode (GL_TRIANGLE_FAN) as vertice 0 (the top left one) will be used in every triangle, as well as other issues. You should be using Triangle/Line strips, although these aren't so straightforward as some vertices are shared between each row.&#xD;&#xA;&#xD;&#xA;For example, imagine you have vertices arranged like so..&#xD;&#xA;&#xD;&#xA;0 1 2&#xD;&#xA;&#xD;&#xA;3 4 5&#xD;&#xA;&#xD;&#xA;6 7 8&#xD;&#xA;&#xD;&#xA;You would draw strips by sending the above vertices in the following order..&#xD;&#xA;&#xD;&#xA;0,3,1 (outputs triangle 0,1,3)&#xD;&#xA;&#xD;&#xA;4,    (outputs triangle 1,3,4)&#xD;&#xA;&#xD;&#xA;2,    (outputs triangle 1,2,4)&#xD;&#xA;&#xD;&#xA;etc..&#xD;&#xA;&#xD;&#xA;This you can do in code by scanning across 1 row of vertices and including the vertex on the next row for every other vertex.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    int numColumns = 5;   // As per your example..&#xD;&#xA;    int numRows = 5;&#xD;&#xA;    int verticeOffset = 0;&#xD;&#xA;    int verticeSize = 3;          // 3 floats per vertice&#xD;&#xA;    int nextRow = numColumns * verticeSize;   &#xD;&#xA;    &#xD;&#xA;    // This loop is for each row-strip, which requires 2 vertex rows..&#xD;&#xA;    for(int j = 0; j &lt; numRows - 1; j++) {&#xD;&#xA;       &#xD;&#xA;        // Inner loop sends vertices for each row-strip&#xD;&#xA;        for(int n = 0; n &lt; numColumns; n++, verticeOffset += verticeSize) {&#xD;&#xA;           glVertex3fv(vertices + verticeOffset);            // Current row&#xD;&#xA;           glVertex3fv(vertices + verticeOffset + nextRow);  // Row below&#xD;&#xA;        }&#xD;&#xA;        // This is special, we send a duplicate vertex to restart a new strip for the next row (This can be omitted if j == numRows - 1)&#xD;&#xA;        glVertex3fv(vertices + verticeOffset - verticeSize + nextRow);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are concerned about sending duplicate vertices you could use an additional indice buffer, as that will allow you to use the exact same vertex buffer you used for the GL_POINTS version." ContentLicense="CC BY-SA 3.0" />
  <row Id="7967" PostHistoryTypeId="2" PostId="3795" RevisionGUID="75dce3d2-0414-4f1f-a84e-c8a65eeb33e5" CreationDate="2016-07-28T05:39:38.747" UserId="4820" Text="So I just recently learned about the Compute Shader and it looks from what I have picked up the same idea as parallel programming you would do with CUDA or OpenCL, but in the shader pipeline.&#xD;&#xA;&#xD;&#xA;If I want to draw a million cubes in a scene should I be using one method over the other or both. If both how do you split that up so the GPU isn't trying to parallel compute both the shader and another process at the same time" ContentLicense="CC BY-SA 3.0" />
  <row Id="7968" PostHistoryTypeId="1" PostId="3795" RevisionGUID="75dce3d2-0414-4f1f-a84e-c8a65eeb33e5" CreationDate="2016-07-28T05:39:38.747" UserId="4820" Text="Compute Shader vs CUDA/OpenCL" ContentLicense="CC BY-SA 3.0" />
  <row Id="7969" PostHistoryTypeId="3" PostId="3795" RevisionGUID="75dce3d2-0414-4f1f-a84e-c8a65eeb33e5" CreationDate="2016-07-28T05:39:38.747" UserId="4820" Text="|compute-shader|opencl|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7970" PostHistoryTypeId="5" PostId="3768" RevisionGUID="73a0f8cf-38f5-4a7b-98a4-ec7ae4fffc20" CreationDate="2016-07-28T10:09:53.327" UserId="3328" Comment="deleted 346 characters in body" Text="I am trying to render Blinn Phong as a BRDF model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use 3d programing API such as OpenGL or WebGL and so on.  &#xD;&#xA;My purpose is to render the surface plane without those APIs. The steps that I take are, I create 2 spaces:&#xD;&#xA;&#xD;&#xA; 1. image space: (0,0) is at the top left of the image.&#xD;&#xA; 1. camera space: (0,0) is at the middle of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, I convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    double[] cam=((new double[]{0,0,1}));&#xD;&#xA;	double[] lum=((new double[]{0,0,1}));&#xD;&#xA;    double[] E=new double[3];&#xD;&#xA;			double[] L=new double[3];&#xD;&#xA;			double[] H=new double[3];&#xD;&#xA;			double D2;&#xD;&#xA;			Mat image=new Mat(rows,cols,CvType.CV_8UC3);&#xD;&#xA;			System.out.println(&quot;Start!!&quot;);&#xD;&#xA;			System.out.println(&quot;ok&quot;);&#xD;&#xA;			for(int i=0;i&lt;tileHNumber;i++)&#xD;&#xA;			{&#xD;&#xA;				for(int j=0;j&lt;tileWNumber;j++)&#xD;&#xA;				{&#xD;&#xA;					for(int s=0;s&lt;192;s++)&#xD;&#xA;					{&#xD;&#xA;						for(int t=0;t&lt;192;t++)&#xD;&#xA;						{&#xD;&#xA;							originS=s+192*i;//ligne&#xD;&#xA;							originT=t+192*j;//colonne&#xD;&#xA;							double[] pos=(Image2Cam(new double[]{originT,originS,0}));&#xD;&#xA;							E=normalize(XY(cam,pos));&#xD;&#xA;							L=normalize(XY(lum, pos);&#xD;&#xA;							double[] le=addXY(L,E);&#xD;&#xA;							H=normalize(le);&#xD;&#xA;							D2=dot(E,E);&#xD;&#xA;							double blue=color(blueColor,pos,E,L,H,D2);&#xD;&#xA;							double green=color(greenColor,pos,E,L,H,D2);&#xD;&#xA;							double red=color(redColor,pos,E,L,H,D2);&#xD;&#xA;							image.put(originS, originT, new byte[]{(byte)(blue),(byte)(green),(byte)(red)});&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;     public static double color(double col,double[] pos,double[] E,double[] L,double[] H,double D2)&#xD;&#xA;	 {&#xD;&#xA;		double value=0;&#xD;&#xA;		double[] N=normalize((new double[]{pos[0],pos[1],1}));&#xD;&#xA;		double diffuse=Math.max(0, dot(N,L));	&#xD;&#xA;		double specular=Math.pow(Math.max(0, dot(N,H)),60);&#xD;&#xA;		value=d*diffuse*0.5+0.2*d+specular*255*0.3;&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The 2 images below show my results: the first one shows diffuse image only. The second one shows specular image only represented by the white color. &#xD;&#xA;&#xD;&#xA;My question is why the lobe specular is not surrounding the center of the image.&#xD;&#xA;&#xD;&#xA;[![Diffuse image][1]][1]&#xD;&#xA;[![Specular image][2]][2]&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7yBBh.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/A1h2s.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="7971" PostHistoryTypeId="2" PostId="3796" RevisionGUID="749ba151-acd5-493b-a1ad-14e647a35f39" CreationDate="2016-07-28T14:22:01.777" UserId="3386" Text="It's not quite correct, today, to think of compute shaders as being &quot;in the shader pipeline&quot; in the same sense that your vertex and fragment shaders are literally hooked up into a pipeline. Compute shaders are not &quot;hooked up&quot; to anything currently, cannot drive rasterization, or directly consume the outputs of rasterization. &#xD;&#xA;&#xD;&#xA;What it allows you to do, though, is consume and produce memory resources also used by draw calls in a relatively efficient way. OpenCL makes this rather difficult (see for example https://software.intel.com/en-us/articles/opencl-and-opengl-interoperability-tutorial). This allows you to efficiently integrate compute *passes* within your renderer, but it is not integrated into the rendering *pipeline*" ContentLicense="CC BY-SA 3.0" />
  <row Id="7972" PostHistoryTypeId="2" PostId="3797" RevisionGUID="1353b5dc-eda0-4090-9fb0-ac350980313f" CreationDate="2016-07-28T16:02:56.850" UserId="4824" Text="AMD have recently been in the [news][1] with an interesting Radeon Pro board with a couple of M2 SSDs on it.&#xD;&#xA;&#xD;&#xA;As some of the more detailed stories ([here][2] or [here][3], for example) note, the benefits may principally accrue not from high bandwidth (the M2's are just on 4 PCIe lanes each, so the board's own 16 lane connector ought to have more) but from low latency.  [This story][4] includes the claim &quot;this results in 10x lower memory access latency&quot;.&#xD;&#xA;&#xD;&#xA;My question is basically: why should PCIe-connected SSDs on the GPU board have significantly less latency than the GPU accessing main system RAM or storage devices on the system PCIe bus?  What is it about the main system that &quot;gets in the way&quot; and means the on-board SSD's can be so much faster to access?&#xD;&#xA;&#xD;&#xA;  [1]: http://arstechnica.com/gadgets/2016/07/amd-radeon-pro-ssg-graphics-card-specs-price-release-date/&#xD;&#xA;  [2]: https://semiaccurate.com/2016/07/25/amd-puts-massive-ssds-gpus-calls-ssg/&#xD;&#xA;  [3]: http://www.extremetech.com/extreme/232416-amd-announces-new-ssg-a-gpu-with-1tb-of-ssd-storage-attached&#xD;&#xA;  [4]: http://www.tomshardware.com/news/amd-radeon-ssg-1tb-gpu-memory,32325.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="7973" PostHistoryTypeId="1" PostId="3797" RevisionGUID="1353b5dc-eda0-4090-9fb0-ac350980313f" CreationDate="2016-07-28T16:02:56.850" UserId="4824" Text="Why did AMD's putting an SSD on a GPU board reduce latency so much?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7974" PostHistoryTypeId="3" PostId="3797" RevisionGUID="1353b5dc-eda0-4090-9fb0-ac350980313f" CreationDate="2016-07-28T16:02:56.850" UserId="4824" Text="|gpu|performance|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7980" PostHistoryTypeId="2" PostId="3799" RevisionGUID="9195a0d8-912c-415e-859a-a98213261b01" CreationDate="2016-07-29T12:20:10.287" UserId="4827" Text="[![https://i.imgur.com/xpBL3Ts.png][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j9ani.png&#xD;&#xA;&#xD;&#xA;&gt;We will use EL for irradiance perpendicular to `l`&#xD;&#xA;&#xD;&#xA;Where `l` is the light vector. &#xD;&#xA;&#xD;&#xA;What does this mean? How do I calculate `EL`?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7981" PostHistoryTypeId="1" PostId="3799" RevisionGUID="9195a0d8-912c-415e-859a-a98213261b01" CreationDate="2016-07-29T12:20:10.287" UserId="4827" Text="What does `EL` mean in the context of shading equations from the book &quot;Real time rendering&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7982" PostHistoryTypeId="3" PostId="3799" RevisionGUID="9195a0d8-912c-415e-859a-a98213261b01" CreationDate="2016-07-29T12:20:10.287" UserId="4827" Text="|rendering|lighting|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7983" PostHistoryTypeId="5" PostId="3799" RevisionGUID="49c9c98a-ad8d-46b4-90c1-f1830270ae7e" CreationDate="2016-07-29T13:06:35.380" UserId="231" Comment="Tidy up formating." Text="&#xD;&#xA;[![Equation 5.10 from Real Time Rendering book][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; We will use $E_L$ for irradiance perpendicular to $l$&#xD;&#xA;&#xD;&#xA;Where $l$ is the light vector. &#xD;&#xA;&#xD;&#xA;What does this mean? How do I calculate $E_L$?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j9ani.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="7984" PostHistoryTypeId="4" PostId="3799" RevisionGUID="49c9c98a-ad8d-46b4-90c1-f1830270ae7e" CreationDate="2016-07-29T13:06:35.380" UserId="231" Comment="Tidy up formating." Text="What does $E_L$ mean in the context of shading equations from the book &quot;Real time rendering&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7986" PostHistoryTypeId="2" PostId="3800" RevisionGUID="cd6be7f7-fe02-469b-945e-799bad7e493d" CreationDate="2016-07-29T16:20:33.077" UserId="48" Text="The line you quoted says it: $E_L$ is the incoming [irradiance](https://en.wikipedia.org/wiki/Irradiance) at the surface due to the light source under consideration. Less technically, it's a vector representing the intensity and color of the incoming light at that point.&#xD;&#xA;&#xD;&#xA;The equation you mention is for a punctual light source (directional, point, or spot light), so in this case $E_L$ would simply be the user-defined RGB color of the light source, multiplied by any relevant attenuation factors—such as shadows, distance attenuation for point/spot lights, and cone angle attenuation for spot lights." ContentLicense="CC BY-SA 3.0" />
  <row Id="7987" PostHistoryTypeId="2" PostId="3801" RevisionGUID="b98b31ea-610b-4fb9-84b8-111355912228" CreationDate="2016-07-29T21:46:08.980" UserId="4830" Text="I have an array of color values. I have an interpolating parameter, `t`, which varies from `0` to `1`.&#xD;&#xA;&#xD;&#xA;I can't for the life of me figure out how to smoothly interpolate between these color values based on `t`, such that I get a smooth blended color for any `t` value.&#xD;&#xA;&#xD;&#xA;Any ideas? Its probably something simple that I am blanking out on.. " ContentLicense="CC BY-SA 3.0" />
  <row Id="7988" PostHistoryTypeId="1" PostId="3801" RevisionGUID="b98b31ea-610b-4fb9-84b8-111355912228" CreationDate="2016-07-29T21:46:08.980" UserId="4830" Text="How can you interpolate over an array of say 5 colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7989" PostHistoryTypeId="3" PostId="3801" RevisionGUID="b98b31ea-610b-4fb9-84b8-111355912228" CreationDate="2016-07-29T21:46:08.980" UserId="4830" Text="|color|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7990" PostHistoryTypeId="2" PostId="3802" RevisionGUID="edb0abde-a23b-41fa-a8e2-564435608e3a" CreationDate="2016-07-29T23:18:36.603" UserId="273" Text="Say you have colors&#xD;&#xA;&#xD;&#xA;$[c_1, c_2, c_3, c_4, c_5]$&#xD;&#xA;&#xD;&#xA;And $t$ values at which each color should be purely displayed.&#xD;&#xA;&#xD;&#xA;$[t_1, t_2, t_3, t_4, t_5]$&#xD;&#xA;&#xD;&#xA;Now your problem is given $t$ which color do I have to display?&#xD;&#xA;&#xD;&#xA;1. Find the t-values $t_i$ and $t_{(i+1)}$ between which $t$ lies.&#xD;&#xA;2. Calculate a 0 to 1 ratio where $t$ lies between them&#xD;&#xA;&#xD;&#xA;$ param = (t - t_i) / (t_{(i+1)} - t_i) $&#xD;&#xA;&#xD;&#xA;3. Interpolate the color via&#xD;&#xA;&#xD;&#xA;$ c = param * c_i + (1-param) * c_{(i+1)}$&#xD;&#xA;&#xD;&#xA;If I haven't messed up something in my mind, this should work for any piecwise linear function, and not only if your $t_i$ values lie between 0 and 1." ContentLicense="CC BY-SA 3.0" />
  <row Id="7993" PostHistoryTypeId="2" PostId="3803" RevisionGUID="41bf32f9-5dfc-4236-b1dc-34ea183d31f3" CreationDate="2016-07-30T21:10:53.690" UserId="4838" Text="I'm learning OpenGL compute shaders and following [this guy's code](https://github.com/StanEpp/OpenGL_ParticleSystem), and I have stuff drawing, but not updating.  The particles are spread out in their starting positions, but they stay there.  &#xD;&#xA;&#xD;&#xA;Particle manager initialization&#xD;&#xA;&#xD;&#xA;    void ParticleManager::Init(unsigned int programId,&#xD;&#xA;        unsigned int computeProgramId,&#xD;&#xA;        unsigned int numParticles)&#xD;&#xA;    {&#xD;&#xA;        ...reset all particles...&#xD;&#xA;&#xD;&#xA;        _unifLocDeltaTimeSec = glGetUniformLocation(_computeProgramId, &quot;uDeltaTimeSec&quot;);&#xD;&#xA;&#xD;&#xA;       _shaderBufferId = 0;&#xD;&#xA;        glGenBuffers(1, &amp;_shaderBufferId);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, _shaderBufferId);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, _allParticles.size() * sizeof(Particle), _allParticles.data(), GL_STATIC_DRAW);&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, _shaderBufferId);  &#xD;&#xA;&#xD;&#xA;        ...vertex array buffer and attribute array initialization...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Particle manager update&#xD;&#xA;&#xD;&#xA;    void ParticleManager::Update(float deltaTimeSec)&#xD;&#xA;    {&#xD;&#xA;        glUseProgram(_computeProgramId);&#xD;&#xA;        glUniform1f(_unifLocDeltaTimeSec, deltaTimeSec);&#xD;&#xA;&#xD;&#xA;        GLuint numWorkGroupsX = (_allParticles.size() / 128) + 1;&#xD;&#xA;        GLuint numWorkGroupsY = 1;&#xD;&#xA;        GLuint numWorkGroupsZ = 1;&#xD;&#xA;        glDispatchCompute(numWorkGroupsX, numWorkGroupsY, numWorkGroupsZ);&#xD;&#xA;&#xD;&#xA;        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;        glUseProgram(0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Particle manager render&#xD;&#xA;&#xD;&#xA;    void ParticleManager::Render()&#xD;&#xA;    {&#xD;&#xA;        glUseProgram(_programId);&#xD;&#xA;        glBindVertexArray(_vaoId);&#xD;&#xA;        glDrawArrays(GL_POINTS, 0, _allParticles.size());&#xD;&#xA;        glUseProgram(0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Compute shader&#xD;&#xA;&#xD;&#xA;    #version 440&#xD;&#xA;&#xD;&#xA;    struct Particle&#xD;&#xA;    {&#xD;&#xA;        vec2 _position;&#xD;&#xA;        vec2 _velocity;&#xD;&#xA;        int _isActive;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) buffer ParticleBuffer {&#xD;&#xA;        Particle AllParticles[];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    uniform float uDeltaTimeSec;     // self-explanatory&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uint index = gl_GlobalInvocationID.x;&#xD;&#xA;        Particle p = AllParticles[index];&#xD;&#xA;&#xD;&#xA;        vec2 deltaPosition = p._velocity * uDeltaTimeSec;&#xD;&#xA;        p._position = p._position + deltaPosition;&#xD;&#xA;        &#xD;&#xA;        AllParticles[index] = p;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've looked through various forum posts (stack exchange, stack overflow, OpenGL forums) and read [at least one tutorial](http://antongerdelan.net/opengl/compute.html) and followed another guy's github project (only allowed 2 links in a post), but I haven't been able to figure out why nothing moves.&#xD;&#xA;&#xD;&#xA;My top culprits are:&#xD;&#xA;&#xD;&#xA;1. Something in the compute shader's &quot;delta position&quot; is evaluating to 0.  &#xD;&#xA;2. The compute shader is not getting called.  &#xD;&#xA;3. The draw shader is not getting access to the compute shader's updated info.&#xD;&#xA;&#xD;&#xA;Doubts:&#xD;&#xA;&#xD;&#xA;1. I hard coded a change in position, so all particles should have moved some on every frame, and when that didn't work, I hard-coded a position, and that didn't work either, so the shader might not even be getting to main().&#xD;&#xA;2. `numWorkGroupsX` evaluates to 79 (non-zero), so the compute shader should at least reach main().&#xD;&#xA;3. I called `glMemoryBarrier(...)` with `GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT`, so the vertex array buffer should have access to the updated info.&#xD;&#xA;&#xD;&#xA;Also, no errors or warnings are reported during GLSL compilation or at runtime, so the computer is evidently happy with what I provided it.&#xD;&#xA;&#xD;&#xA;Help?  Why are my particles never moving beyond initialization?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7994" PostHistoryTypeId="1" PostId="3803" RevisionGUID="41bf32f9-5dfc-4236-b1dc-34ea183d31f3" CreationDate="2016-07-30T21:10:53.690" UserId="4838" Text="Compute shader not updating buffer, or vertex buffer unable to read the updates" ContentLicense="CC BY-SA 3.0" />
  <row Id="7995" PostHistoryTypeId="3" PostId="3803" RevisionGUID="41bf32f9-5dfc-4236-b1dc-34ea183d31f3" CreationDate="2016-07-30T21:10:53.690" UserId="4838" Text="|opengl|c++|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="7996" PostHistoryTypeId="2" PostId="3804" RevisionGUID="cd92e29e-6646-4901-a8c8-393453a4a24e" CreationDate="2016-07-30T21:31:45.453" UserId="2507" Text="I'm writing my own TrueType font rasterizer as an exercise to improve my knowledge in computer graphics (along with a basic vector graphics engine). At this stage, I have implemented most of the TTF file parsing, decoding glyph outlines, scaling, and scan converting the outlines into a bitmap. &#xD;&#xA;(I'm not doing any font hinting/grid fitting for the time being).&#xD;&#xA;&#xD;&#xA;When it comes to anti-aliasing the glyph bitmaps, what process or method is typically used (or best)? So far I have tried two methods. Bilinear filtering and setting the alpha value at the edges according to the pixel coverage of the outline. &#xD;&#xA;&#xD;&#xA;Bilinear sampling is too blurry to be effective in font rendering, and using pixel coverage is not continuous enough. Here are some images as reference of a lowercase Arial 'c' being rendered at 24 points: &#xD;&#xA;&#xD;&#xA;Raw bitmap with no anti-aliasing:&#xD;&#xA;&#xD;&#xA;[![Raw glyph with no anti-aliasing][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Bilinear filtering:&#xD;&#xA;&#xD;&#xA;[![Bilinear filtering][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the same character rendered at the same size with a library (stb): &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally, here it is rendered as it would appear on OS X (using CoreText I presume):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w7CQD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/T6m7H.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/1EteV.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7uACN.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/kgEYF.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/8tAM0.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/UOgSC.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/qs03k.png&#xD;&#xA;&#xD;&#xA;I'd be happy with whatever method is used by the stb library for my purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="7997" PostHistoryTypeId="1" PostId="3804" RevisionGUID="cd92e29e-6646-4901-a8c8-393453a4a24e" CreationDate="2016-07-30T21:31:45.453" UserId="2507" Text="What kind of anti-aliasing is used in font rasterization?" ContentLicense="CC BY-SA 3.0" />
  <row Id="7998" PostHistoryTypeId="3" PostId="3804" RevisionGUID="cd92e29e-6646-4901-a8c8-393453a4a24e" CreationDate="2016-07-30T21:31:45.453" UserId="2507" Text="|antialiasing|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8000" PostHistoryTypeId="2" PostId="3805" RevisionGUID="c41bf873-3d33-4af9-b0c6-3d12822405a8" CreationDate="2016-07-31T09:43:27.543" UserId="4840" Text="Billboarding/impostors mean, roughly, representing complex 3D objects in 2D or with simple quadrilaterals, for the sake of LOD systems.&#xD;&#xA;&#xD;&#xA;Consider the case of rendering a very numerous asteroid field where one base asteroid mesh is instanced X times. If none of the instances of the mesh are re-scaled, it is easy to replace them with a billboard/impostor: one should just generate a billboard or impostor for the base asteroid mesh and substitute each asteroid instance with an instance of the billboard/impostor when desired.&#xD;&#xA;&#xD;&#xA;Now, if each instance of the asteroid mesh that is present in the asteroid field is supposed to be re-scaled (e.g. to give the illusion of diversity to an asteroid field), this becomes much more complicated. Re-scaling a billboard quad of the base asteroid mesh, for instance, would not mimic the re-scaled instances of the asteroid mesh. At the same time, it is not clear whether using techniques like true-impostor would solve that any further.&#xD;&#xA;&#xD;&#xA;Thus, my question is: is there any impostoring technique that would allow that? I.e. pre-generating an impostor of the base asteroid mesh, then scaling each impostor's instance in a way that would mimic the re-scaling of the instances of the asteroid mesh?&#xD;&#xA;&#xD;&#xA;I have been reading the recent literature on advanced billboarding/impostor techniques (true impostors, 3-view impostors, volumetric impostors, etc), but I am still confused about that." ContentLicense="CC BY-SA 3.0" />
  <row Id="8001" PostHistoryTypeId="1" PostId="3805" RevisionGUID="c41bf873-3d33-4af9-b0c6-3d12822405a8" CreationDate="2016-07-31T09:43:27.543" UserId="4840" Text="Billboards or impostors when objects' instances are re-scaled" ContentLicense="CC BY-SA 3.0" />
  <row Id="8002" PostHistoryTypeId="3" PostId="3805" RevisionGUID="c41bf873-3d33-4af9-b0c6-3d12822405a8" CreationDate="2016-07-31T09:43:27.543" UserId="4840" Text="|rendering|performance|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8003" PostHistoryTypeId="2" PostId="3806" RevisionGUID="3f503874-d267-419d-9a1c-b9ab57fdee9e" CreationDate="2016-07-31T21:56:45.207" UserId="48" Text="Sean Barrett, the author of the stb libraries, [wrote an article on how stb_truetype's rasterization works](http://nothings.org/gamedev/rasterize/). It's quite readable.&#xD;&#xA;&#xD;&#xA;The article describes two methods of antialiasing, both based on scanline rasterization. In scanline rasterization, you iterate through the lines (rows) of pixels and keep track of which edges from the glyph outline are intersecting the scanline (considered as a mathematical zero-thickness line); then you can identify which pixel-centers are inside the outline by tracking enter/exit intersection points along that line.&#xD;&#xA;&#xD;&#xA;You can do horizontal antialiasing by calculating partial pixel coverage, using the position of the intersection points relative to the pixel grid. For example, if you have an entering point at $x = 4.6$ on the current scanline, then pixel index 4 would be set to 60% empty and 40% covered. This sounds somewhat like what you tried to do. However, this doesn't help with vertical antialiasing since the scanline is still considered as a mathematical line with zero thickness. So, the article recommends to just supersample along the vertical axis: that is, process multiple &quot;scanlines&quot; spaced out vertically within each pixel row, and average the results together.&#xD;&#xA;&#xD;&#xA;The second method performs both horizontal and vertical antialiasing at once, by evaluating the area of intersection of the glyph outline with each pixel square. It's still based on scanline rasterization, but now treats the scanline as a 1-pixel-tall rectangle and tracks all edges that touch the rectangle. To evaluate pixel coverage, the trapezoidal rule is used to calculate a signed area for each glyph edge—positive or negative depending on the edge's orientation—and these are summed up to give the total coverage area within the pixel square. (There are a lot more implementation details covered in the article, plus you can [read the source](https://github.com/nothings/stb/blob/master/stb_truetype.h).) This is somewhat faster and more accurate than the supersampling method, though more difficult to implement." ContentLicense="CC BY-SA 3.0" />
  <row Id="8004" PostHistoryTypeId="5" PostId="3806" RevisionGUID="1073e9b5-d38a-4620-91e6-e8fae3cbb3f4" CreationDate="2016-07-31T22:11:43.570" UserId="48" Comment="add note about gamma" Text="Sean Barrett, the author of the stb libraries, [wrote an article on how stb_truetype's rasterization works](http://nothings.org/gamedev/rasterize/). It's quite readable.&#xD;&#xA;&#xD;&#xA;The article describes two methods of antialiasing, both based on scanline rasterization. In scanline rasterization, you iterate through the lines (rows) of pixels and keep track of which edges from the glyph outline are intersecting the scanline (considered as a mathematical zero-thickness line); then you can identify which pixel-centers are inside the outline by tracking enter/exit intersection points along that line.&#xD;&#xA;&#xD;&#xA;You can do horizontal antialiasing by calculating partial pixel coverage, using the position of the intersection points relative to the pixel grid. For example, if you have an entering point at $x = 4.6$ on the current scanline, then pixel index 4 would be set to 60% empty and 40% covered. This sounds somewhat like what you tried to do. However, this doesn't help with vertical antialiasing since the scanline is still considered as a mathematical line with zero thickness. So, the article recommends to just supersample along the vertical axis: that is, process multiple &quot;scanlines&quot; spaced out vertically within each pixel row, and average the results together.&#xD;&#xA;&#xD;&#xA;The second method performs both horizontal and vertical antialiasing at once, by evaluating the area of intersection of the glyph outline with each pixel square. It's still based on scanline rasterization, but now treats the scanline as a 1-pixel-tall rectangle and tracks all edges that touch the rectangle. To evaluate pixel coverage, the trapezoidal rule is used to calculate a signed area for each glyph edge—positive or negative depending on the edge's orientation—and these are summed up to give the total coverage area within the pixel square. (There are a lot more implementation details covered in the article, plus you can [read the source](https://github.com/nothings/stb/blob/master/stb_truetype.h).) This is somewhat faster and more accurate than the supersampling method, though more difficult to implement.&#xD;&#xA;&#xD;&#xA;Finally, it's important to keep gamma correction in mind when rendering text (as with rendering anything else). The antialiased coverage values shouldn't be used directly as pixel values; they should be treated as an alpha, and used for linear-color-space blending between the background color and text color, followed by conversion to output gamma. Otherwise, you may see [artifacts such as the font appearing to get heavier or lighter](https://www.freetype.org/freetype2/docs/text-rendering-general.html#back-to-stem-darkening) depending on color and font size." ContentLicense="CC BY-SA 3.0" />
  <row Id="8005" PostHistoryTypeId="5" PostId="3806" RevisionGUID="87c4eac8-0441-4181-a6cb-a1eeae926999" CreationDate="2016-07-31T23:04:38.117" UserId="48" Comment="added 315 characters in body" Text="Sean Barrett, the author of the stb libraries, [wrote an article on how stb_truetype's rasterization works](http://nothings.org/gamedev/rasterize/). It's quite readable.&#xD;&#xA;&#xD;&#xA;The article describes two methods of antialiasing, both based on scanline rasterization. In scanline rasterization, you iterate through the lines (rows) of pixels and keep track of which edges from the glyph outline are intersecting the scanline (considered as a mathematical zero-thickness line); then you can identify which pixel-centers are inside the outline by tracking enter/exit intersection points along that line.&#xD;&#xA;&#xD;&#xA;You can do horizontal antialiasing by calculating partial pixel coverage, using the position of the intersection points relative to the pixel grid. For example, if you have an entering point at $x = 4.6$ on the current scanline, then pixel index 4 would be set to 60% empty and 40% covered. This sounds somewhat like what you tried to do. However, this doesn't help with vertical antialiasing since the scanline is still considered as a mathematical line with zero thickness. So, the article recommends to just supersample along the vertical axis: that is, process multiple &quot;scanlines&quot; spaced out vertically within each pixel row, and average the results together.&#xD;&#xA;&#xD;&#xA;The second method performs both horizontal and vertical antialiasing at once, by evaluating the area of intersection of the glyph outline with each pixel square. It's still based on scanline rasterization, but now treats the scanline as a 1-pixel-tall rectangle and tracks all edges that touch the rectangle. To evaluate pixel coverage, the trapezoidal rule is used to calculate a signed area for each glyph edge—positive or negative depending on the edge's orientation—and these are summed up to give the total coverage area within the pixel square. (There are a lot more implementation details covered in the article, plus you can [read the source](https://github.com/nothings/stb/blob/master/stb_truetype.h).) This is somewhat faster and more accurate than the supersampling method, though more difficult to implement.&#xD;&#xA;&#xD;&#xA;Finally, it's important to consider whether you want gamma correction when rendering text (as with rendering anything else). Theoretically, the antialiased coverage values shouldn't be used directly as pixel values; they should be treated as an alpha, and used for linear-color-space blending between the background color and text color, followed by conversion to output gamma. However, in practice almost no one seems to do this; we're accustomed to seeing non-gamma-correct text, and screen fonts are designed to look good rendered this way. (Print fonts are another story.) So, the choice of whether to apply gamma correction comes down to personal preference. Either way, you may see [artifacts such as the font appearing to get heavier or lighter](https://www.freetype.org/freetype2/docs/text-rendering-general.html#back-to-stem-darkening) depending on color and font size." ContentLicense="CC BY-SA 3.0" />
  <row Id="8006" PostHistoryTypeId="5" PostId="3806" RevisionGUID="d2979bcd-2e04-4b44-b0b3-61cce6c2718c" CreationDate="2016-07-31T23:13:44.507" UserId="48" Comment="more notes on gamma" Text="Sean Barrett, the author of the stb libraries, [wrote an article on how stb_truetype's rasterization works](http://nothings.org/gamedev/rasterize/). It's quite readable.&#xD;&#xA;&#xD;&#xA;The article describes two methods of antialiasing, both based on scanline rasterization. In scanline rasterization, you iterate through the lines (rows) of pixels and keep track of which edges from the glyph outline are intersecting the scanline (considered as a mathematical zero-thickness line); then you can identify which pixel-centers are inside the outline by tracking enter/exit intersection points along that line.&#xD;&#xA;&#xD;&#xA;You can do horizontal antialiasing by calculating partial pixel coverage, using the position of the intersection points relative to the pixel grid. For example, if you have an entering point at $x = 4.6$ on the current scanline, then pixel index 4 would be set to 60% empty and 40% covered. This sounds somewhat like what you tried to do. However, this doesn't help with vertical antialiasing since the scanline is still considered as a mathematical line with zero thickness. So, the article recommends to just supersample along the vertical axis: that is, process multiple &quot;scanlines&quot; spaced out vertically within each pixel row, and average the results together.&#xD;&#xA;&#xD;&#xA;The second method performs both horizontal and vertical antialiasing at once, by evaluating the area of intersection of the glyph outline with each pixel square. It's still based on scanline rasterization, but now treats the scanline as a 1-pixel-tall rectangle and tracks all edges that touch the rectangle. To evaluate pixel coverage, the trapezoidal rule is used to calculate a signed area for each glyph edge—positive or negative depending on the edge's orientation—and these are summed up to give the total coverage area within the pixel square. (There are a lot more implementation details covered in the article, plus you can [read the source](https://github.com/nothings/stb/blob/master/stb_truetype.h).) This is somewhat faster and more accurate than the supersampling method, though more difficult to implement.&#xD;&#xA;&#xD;&#xA;Finally, it's important to consider whether you want gamma correction when rendering text (as with rendering anything else). Theoretically, the antialiased coverage values shouldn't be used directly as pixel values; they should be treated as an alpha, and used for linear-color-space blending between the background color and text color, followed by conversion to output gamma. However, in practice almost no one seems to do this; we're accustomed to seeing non-gamma-correct text, and screen fonts are designed to look good rendered this way. (Print fonts are another story.) On the other hand, if the text is animated, or rotated or not aligned with the pixel grid for any reason, gamma correction will help it look more consistent regardless of its placement relative to the pixel grid.&#xA;&#xA;So, the choice of whether to apply gamma correction comes down to personal preference and the needs of the application. Either way, you may see artifacts such as the font appearing to get heavier or lighter depending on [color](https://twitter.com/rygorous/status/512371399542202368) and [font size](https://www.freetype.org/freetype2/docs/text-rendering-general.html#back-to-stem-darkening)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8007" PostHistoryTypeId="2" PostId="3807" RevisionGUID="93894657-c444-472d-970b-19d02a2a22f5" CreationDate="2016-07-31T23:18:14.897" UserId="3377" Text="My goal is to implement an edge detection algorithmus that is capable to find edges of arbitrary 3d meshes. I want to find the edges by detecting normal discontinuities. Furthermore, I want the edges to be one pixel wide.&#xD;&#xA;&#xD;&#xA;I render the color values of my scene and the corresponding normal vectors to two different render buffer targets, i.e. to two different textures (screenTexture and normalTexture).&#xD;&#xA;I use the sobel edge detection algorithmus in my fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D screenTexture;&#xD;&#xA;    uniform sampler2D normalTexture;&#xD;&#xA;    uniform sampler2D depthTexture;&#xD;&#xA;&#xD;&#xA;    mat3 sx = mat3( &#xD;&#xA;	    1.0, 2.0, 1.0, &#xD;&#xA;	    0.0, 0.0, 0.0, &#xD;&#xA;	   -1.0, -2.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;    mat3 sy = mat3( &#xD;&#xA;	   1.0, 0.0, -1.0, &#xD;&#xA;	   2.0, 0.0, -2.0, &#xD;&#xA;	   1.0, 0.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec4 diffuse = texelFetch(screenTexture, ivec2(gl_FragCoord), 0);&#xD;&#xA;	    vec3 normal = texelFetch(normalTexture, ivec2(gl_FragCoord), 0 ).xyz;&#xD;&#xA;        vec3 I[3];&#xD;&#xA;	    for (int i=0; i&lt;3; i++) {&#xD;&#xA;		    float sampleValLeft  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,-1), 0 ).rgb);&#xD;&#xA;		    float sampleValMiddle  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,0), 0 ).rgb);&#xD;&#xA;		    float sampleValRight  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,1), 0 ).rgb);&#xD;&#xA;		    I[i] = vec3(sampleValLeft, sampleValMiddle, sampleValRight);&#xD;&#xA;	    }&#xD;&#xA;&#xD;&#xA;	    float gx = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]); &#xD;&#xA;	    float gy = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);&#xD;&#xA;&#xD;&#xA;	    float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;	    g = smoothstep(0.4,0.8, g);&#xD;&#xA;&#xD;&#xA;	    if(g &gt; 0.2) {&#xD;&#xA;		    color = vec4(0., 0., 0.0, 1);&#xD;&#xA;	    } else {&#xD;&#xA;		    color = diffuse;&#xD;&#xA;	    }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;The shader produces the following result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the line thickness of the solids are not consistent: &#xD;&#xA;&#xD;&#xA; 1. Edges visible between the turquois and the solid are 1px wide like&#xD;&#xA;   intended.&#xD;&#xA; 2. Edges within the object are 2px wide which is too bride.&#xD;&#xA;&#xD;&#xA;The reason why 1. works is because I initalized the scene with vec3(0,0,0) vectors which produces a dot-product of 0.&#xD;&#xA;But edges within the object are detected two times by sobel because of a gx or gy which is one time positive and one time negative.&#xD;&#xA;&#xD;&#xA;I'm totally stuck what I can do to produce consistent wide lines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XjsGs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8008" PostHistoryTypeId="1" PostId="3807" RevisionGUID="93894657-c444-472d-970b-19d02a2a22f5" CreationDate="2016-07-31T23:18:14.897" UserId="3377" Text="Sobel edge detection line thickness" ContentLicense="CC BY-SA 3.0" />
  <row Id="8009" PostHistoryTypeId="3" PostId="3807" RevisionGUID="93894657-c444-472d-970b-19d02a2a22f5" CreationDate="2016-07-31T23:18:14.897" UserId="3377" Text="|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8010" PostHistoryTypeId="5" PostId="3807" RevisionGUID="a4ca8e43-e617-4101-941b-40d9714064f5" CreationDate="2016-07-31T23:24:50.693" UserId="3377" Comment="added 176 characters in body" Text="My goal is to implement an edge detection algorithmus that is capable to find edges of arbitrary 3d meshes. I want to find the edges by detecting normal discontinuities. Furthermore, I want the edges to be one pixel wide.&#xD;&#xA;&#xD;&#xA;I render the color values of my scene and the corresponding normal vectors to two different render buffer targets, i.e. to two different textures (screenTexture and normalTexture).&#xD;&#xA;I use the sobel edge detection algorithmus in my fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D screenTexture;&#xD;&#xA;    uniform sampler2D normalTexture;&#xD;&#xA;    uniform sampler2D depthTexture;&#xD;&#xA;&#xD;&#xA;    mat3 sx = mat3( &#xD;&#xA;	    1.0, 2.0, 1.0, &#xD;&#xA;	    0.0, 0.0, 0.0, &#xD;&#xA;	   -1.0, -2.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;    mat3 sy = mat3( &#xD;&#xA;	   1.0, 0.0, -1.0, &#xD;&#xA;	   2.0, 0.0, -2.0, &#xD;&#xA;	   1.0, 0.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec4 diffuse = texelFetch(screenTexture, ivec2(gl_FragCoord), 0);&#xD;&#xA;	    vec3 normal = texelFetch(normalTexture, ivec2(gl_FragCoord), 0 ).xyz;&#xD;&#xA;        vec3 I[3];&#xD;&#xA;	    for (int i=0; i&lt;3; i++) {&#xD;&#xA;		    float sampleValLeft  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,-1), 0 ).rgb);&#xD;&#xA;		    float sampleValMiddle  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,0), 0 ).rgb);&#xD;&#xA;		    float sampleValRight  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,1), 0 ).rgb);&#xD;&#xA;		    I[i] = vec3(sampleValLeft, sampleValMiddle, sampleValRight);&#xD;&#xA;	    }&#xD;&#xA;&#xD;&#xA;	    float gx = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]); &#xD;&#xA;	    float gy = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);&#xD;&#xA;&#xD;&#xA;	    float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;	    g = smoothstep(0.4,0.8, g);&#xD;&#xA;&#xD;&#xA;	    if(g &gt; 0.2) {&#xD;&#xA;		    color = vec4(0., 0., 0.0, 1);&#xD;&#xA;	    } else {&#xD;&#xA;		    color = diffuse;&#xD;&#xA;	    }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;The shader produces the following result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the line thickness of the solids are not consistent: &#xD;&#xA;&#xD;&#xA; 1. Edges visible between the turquois and the solid are 1px wide like&#xD;&#xA;   intended.&#xD;&#xA; 2. Edges within the object are 2px wide which is too bride.&#xD;&#xA;&#xD;&#xA;The reason why 1. works is because I initalized the whole scene with vec3(0,0,0) vectors which produces a dot-product of 0 as soon as the current pixel is a scene pixel and the adjacent right or left pixel is an edge pixel of the solid.&#xD;&#xA;&#xD;&#xA;But edges within the object are detected two times by sobel because of a gx or gy which is one time positive and one time negative. In other words, gx or gy is both times not 0 and therefore g is greater than 0.2 both of the time.&#xD;&#xA;&#xD;&#xA;I'm totally stuck what I can do to produce consistent wide lines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XjsGs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8011" PostHistoryTypeId="2" PostId="3808" RevisionGUID="16063f63-f7c6-4bea-bf02-a7126550a3ae" CreationDate="2016-08-01T09:50:37.307" UserId="3058" Text="VR rendering needs a lot of GPU power. VR SLI can help that. But, is it possible for us to use distributed parallel rendering technology to improve the performance dramatically? There is an open source software &quot;equalizer&quot; which could do that.&#xD;&#xA;&#xD;&#xA;For example, put 4 or 8 GPUs in one PC server and disable vender's SLI driver. Use equalizer to do parallel rendering. Or, run equalizer on 16 PC servers with GPU equipped. &#xD;&#xA;&#xD;&#xA;So that we can get very high performance easily? Right?&#xD;&#xA;&#xD;&#xA;Equalizer supports sort-first and sort-last. Since sort-last needs a lot of network bandwidth, we'd better use sort-first." ContentLicense="CC BY-SA 3.0" />
  <row Id="8012" PostHistoryTypeId="1" PostId="3808" RevisionGUID="16063f63-f7c6-4bea-bf02-a7126550a3ae" CreationDate="2016-08-01T09:50:37.307" UserId="3058" Text="Distributed parallel rendering in Gaming or VR rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="8013" PostHistoryTypeId="3" PostId="3808" RevisionGUID="16063f63-f7c6-4bea-bf02-a7126550a3ae" CreationDate="2016-08-01T09:50:37.307" UserId="3058" Text="|rendering|gpu|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8014" PostHistoryTypeId="5" PostId="3807" RevisionGUID="06db0c98-8d08-42a9-8a34-ab7a49510c1c" CreationDate="2016-08-01T09:57:18.353" UserId="3377" Comment="added 11 characters in body" Text="My goal is to implement an edge detection algorithmus that is capable to find edges of arbitrary 3d meshes. I want to find the edges by detecting normal discontinuities. Furthermore, I want the edges to be one pixel wide.&#xD;&#xA;&#xD;&#xA;I render the color values of my scene and the corresponding normal vectors to two different render buffer targets, i.e. to two different textures (screenTexture and normalTexture).&#xD;&#xA;I use the sobel edge detection algorithmus in my fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D screenTexture;&#xD;&#xA;    uniform sampler2D normalTexture;&#xD;&#xA;    uniform sampler2D depthTexture;&#xD;&#xA;&#xD;&#xA;    mat3 sx = mat3( &#xD;&#xA;	    1.0, 2.0, 1.0, &#xD;&#xA;	    0.0, 0.0, 0.0, &#xD;&#xA;	   -1.0, -2.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;    mat3 sy = mat3( &#xD;&#xA;	   1.0, 0.0, -1.0, &#xD;&#xA;	   2.0, 0.0, -2.0, &#xD;&#xA;	   1.0, 0.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec4 diffuse = texelFetch(screenTexture, ivec2(gl_FragCoord), 0);&#xD;&#xA;	    vec3 normal = texelFetch(normalTexture, ivec2(gl_FragCoord), 0 ).xyz;&#xD;&#xA;        vec3 I[3];&#xD;&#xA;	    for (int i=0; i&lt;3; i++) {&#xD;&#xA;		    float sampleValLeft  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,-1), 0 ).rgb);&#xD;&#xA;		    float sampleValMiddle  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,0), 0 ).rgb);&#xD;&#xA;		    float sampleValRight  = dot(normal, texelFetch(normalTexture, ivec2(gl_FragCoord) + ivec2(i-1,1), 0 ).rgb);&#xD;&#xA;		    I[i] = vec3(sampleValLeft, sampleValMiddle, sampleValRight);&#xD;&#xA;	    }&#xD;&#xA;&#xD;&#xA;	    float gx = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]); &#xD;&#xA;	    float gy = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);&#xD;&#xA;&#xD;&#xA;	    float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;	    g = smoothstep(0.4,0.8, g);&#xD;&#xA;&#xD;&#xA;	    if(g &gt; 0.2) {&#xD;&#xA;		    color = vec4(0., 0., 0.0, 1);&#xD;&#xA;	    } else {&#xD;&#xA;		    color = diffuse;&#xD;&#xA;	    }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;The shader produces the following result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the line thickness of the solids are not consistent: &#xD;&#xA;&#xD;&#xA; 1. Edges visible between the turquois background and the solid are 1px wide like&#xD;&#xA;   intended.&#xD;&#xA; 2. Edges within the object are 2px wide which is too bride.&#xD;&#xA;&#xD;&#xA;The reason why 1. works is because I initalized normalTexture with vec3(0,0,0) normal vectors which produces a dot-product of 0 as soon as the current pixel is a scene pixel and the adjacent right or left pixel is an edge pixel of the solid.&#xD;&#xA;&#xD;&#xA;But edges within the object are detected two times by sobel because of a gx or gy which is one time positive and one time negative. In other words, gx or gy is both times not 0 and therefore g is greater than 0.2 both of the time.&#xD;&#xA;&#xD;&#xA;I'm totally stuck what I can do to produce consistent wide lines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XjsGs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8015" PostHistoryTypeId="2" PostId="3809" RevisionGUID="ded970f8-88be-49e7-9434-13540181d0d3" CreationDate="2016-08-01T10:45:11.937" UserId="2644" Text="I have rectangular matrix of 3d points sampled from a parametric surface. In my program this matrix provides base points for bilinear interpolation of surface (In any (u,v) point it returns 3d point interpolated from neighboring sampled values). Now I want to find closest point on surface from any other point in 3d space, considering values &quot;between&quot; sampled points of grid.&#xD;&#xA;&#xD;&#xA;My first idea was: Find closest point in this matrix, for example with K-D tree, or simple linear search. After this get indexes of this point in my 2d matrix of samples, and search for closest point considering 8 neighboring points in matrix (Because closest point may lie between sampled points). But I think there might be better solution for this problem.&#xD;&#xA;&#xD;&#xA;I'll attach picture with example on 2d curve. Here yellow points are sampled points, red point - point to which we want to find closest, and green - point which we need to find as closest. With proposed algo we will find point 3, or 4, and then search for closest point on line from 3 to 4, or from 4 to 3. [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YKLGT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8016" PostHistoryTypeId="1" PostId="3809" RevisionGUID="ded970f8-88be-49e7-9434-13540181d0d3" CreationDate="2016-08-01T10:45:11.937" UserId="2644" Text="Find closest point on surface interpolated by 2d matrix of points" ContentLicense="CC BY-SA 3.0" />
  <row Id="8017" PostHistoryTypeId="3" PostId="3809" RevisionGUID="ded970f8-88be-49e7-9434-13540181d0d3" CreationDate="2016-08-01T10:45:11.937" UserId="2644" Text="|algorithm|computational-geometry|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8018" PostHistoryTypeId="12" PostId="3809" RevisionGUID="f6b2988a-f675-485c-8240-d86d539717c7" CreationDate="2016-08-01T10:53:43.123" UserId="2644" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2644,&quot;DisplayName&quot;:&quot;Olologin&quot;}]}" />
  <row Id="8019" PostHistoryTypeId="13" PostId="3809" RevisionGUID="8d0ad57d-b22c-4ed7-90cf-a6969558cbb3" CreationDate="2016-08-01T11:02:35.630" UserId="2644" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2644,&quot;DisplayName&quot;:&quot;Olologin&quot;}]}" />
  <row Id="8020" PostHistoryTypeId="12" PostId="3809" RevisionGUID="c47c3caf-8fc2-45bd-9cc8-1e727b96e0a8" CreationDate="2016-08-01T11:55:44.750" UserId="2644" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2644,&quot;DisplayName&quot;:&quot;Olologin&quot;}]}" />
  <row Id="8021" PostHistoryTypeId="2" PostId="3810" RevisionGUID="f83ee2ba-0c54-472b-b034-77a54a0dabdc" CreationDate="2016-08-01T11:58:01.420" UserId="182" Text="Yes, it's a limitation of the Sobel based edge detection and other 3x3 convolution filters: you can only detect edges twice as big as your pixels. The [Robert operator][1] uses a 2x2 convolution filter, so it yields thinner edges but they are still more than one pixel thick.&#xD;&#xA;&#xD;&#xA;If you absolutely want one pixel width, you could use texture filtering and sample every half pixel when applying the Sobel operator, but the result will probably be less clean.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Roberts_cross" ContentLicense="CC BY-SA 3.0" />
  <row Id="8022" PostHistoryTypeId="5" PostId="3810" RevisionGUID="2003dc07-1002-4725-8d3b-87a8fc097b93" CreationDate="2016-08-01T12:14:06.147" UserId="182" Comment="added 234 characters in body" Text="The edge between the sphere and the background is actually the one that is incorrect; you need to initialize your normal texture with a unit normal to get correct results.&#xD;&#xA;&#xD;&#xA;The two pixels thickness is a limitation of the Sobel based edge detection and other 3x3 convolution filters: you can only detect edges twice as big as your pixels. The [Robert operator][1] uses a 2x2 convolution filter with weights making a cross, so it yields thinner edges but they are still thicker than one pixel.&#xD;&#xA;&#xD;&#xA;If you absolutely want one pixel width, you could use filtered texture sampling and sample every half pixel when applying the Sobel operator, but the detection will probably miss some features.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Roberts_cross" ContentLicense="CC BY-SA 3.0" />
  <row Id="8023" PostHistoryTypeId="13" PostId="3809" RevisionGUID="52b06f48-42e8-43dd-bc5b-09aba368a707" CreationDate="2016-08-01T18:11:48.523" UserId="2644" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2644,&quot;DisplayName&quot;:&quot;Olologin&quot;}]}" />
  <row Id="8024" PostHistoryTypeId="5" PostId="3809" RevisionGUID="991f3576-9696-4f46-8b00-f2a8771acecf" CreationDate="2016-08-01T18:12:38.467" UserId="2644" Comment="deleted 465 characters in body" Text="I have rectangular matrix of 3d points sampled from a parametric surface. In my program this matrix provides base points for bilinear interpolation of surface (In any (u,v) point it returns 3d point interpolated from neighboring sampled values). Now I want to find closest point on surface from any other point in 3d space, considering values &quot;between&quot; sampled points of grid.&#xD;&#xA;&#xD;&#xA;I'll attach picture with example on 2d curve. Here yellow points are sampled points, red point - point to which we want to find closest, and green - point which we need to find as closest (witness point). [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YKLGT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8025" PostHistoryTypeId="2" PostId="3811" RevisionGUID="9fd036e9-cf1e-4b0a-b592-e6353267ba7c" CreationDate="2016-08-01T20:33:28.353" UserId="2817" Text="You are essentially correct in assuming that it is technically feasible to distribute the rendering computation workload. It is, essentially, a computation workload like any other; possibly even better-suited for parallelization due to its very nature: many similarly structured units running the same code path (i.e. vertices, pixels).&#xD;&#xA;&#xD;&#xA;What you are forgetting, however, is latency. Having all the render power in the world is useless if the image does not arrive to the HMD fast enough not to cause discomfort to the user. Here is an article that explains the importance of motion-to-photon latency:&#xD;&#xA;&#xD;&#xA;http://www.chioka.in/what-is-motion-to-photon-latency/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8026" PostHistoryTypeId="10" PostId="3724" RevisionGUID="ae12d56e-926f-47e2-92b7-90ae2ea1ec27" CreationDate="2016-08-01T22:02:19.977" UserId="-1" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:273,&quot;DisplayName&quot;:&quot;Dragonseel&quot;},{&quot;Id&quot;:385,&quot;DisplayName&quot;:&quot;David Kuri&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;}]}" />
  <row Id="8027" PostHistoryTypeId="2" PostId="3812" RevisionGUID="4b1a0467-ff92-4fde-9e03-1429be075b89" CreationDate="2016-08-01T23:49:23.110" UserId="4838" Text="Got help from someone over in the [OpenGL subreddit](https://www.reddit.com/r/opengl/comments/4vdu02/need_help_with_a_compute_shader_new_to_compute/).  Apparently, as I trimmed the code for posting here and there, I changed the operation of the code.&#xD;&#xA;&#xD;&#xA;What I trimmed to this:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uint index = gl_GlobalInvocationID.x;&#xD;&#xA;        Particle p = AllParticles[index];&#xD;&#xA;&#xD;&#xA;        vec2 deltaPosition = p._velocity * uDeltaTimeSec;&#xD;&#xA;        p._position = p._position + deltaPosition;&#xD;&#xA;&#xD;&#xA;        AllParticles[index] = p;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Was more or less this:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uint index = gl_GlobalInvocationID.x;&#xD;&#xA;        Particle p = AllParticles[index];&#xD;&#xA;&#xD;&#xA;        // update position&#xD;&#xA;        vec2 deltaPosition = p._velocity * uDeltaTimeSec;&#xD;&#xA;        deltaPosition = vec2(0.0f, 0.0f);&#xD;&#xA;        //p._position = p._position + deltaPosition;&#xD;&#xA;        p._position = deltaPosition;&#xD;&#xA;&#xD;&#xA;        AllParticles[index] = p;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Which should have been this:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uint index = gl_GlobalInvocationID.x;&#xD;&#xA;        Particle p = AllParticles[index];&#xD;&#xA;&#xD;&#xA;        // update position&#xD;&#xA;        vec2 deltaPosition = p._velocity * uDeltaTimeSec;&#xD;&#xA;        //deltaPosition = vec2(0.0f, 0.0f);&#xD;&#xA;        p._position = p._position + deltaPosition;&#xD;&#xA;        //p._position = deltaPosition;&#xD;&#xA;&#xD;&#xA;        AllParticles[index] = p;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So I really just did that.  The redditor who helped me downloaded my source code via github and found the error.  Standard case of one pair of eyes glossing over an error.&#xD;&#xA;&#xD;&#xA;All is well now." ContentLicense="CC BY-SA 3.0" />
  <row Id="8029" PostHistoryTypeId="2" PostId="3813" RevisionGUID="e86a447a-d84a-4794-a5c9-d5632099ca57" CreationDate="2016-08-02T06:06:04.130" UserId="4765" Text="# Question&#xD;&#xA;Is there a way to compute sth. in a first shader program (eg. screen-space coordinates from word-space ones) and access those results in an another shader program? &#xD;&#xA;&#xD;&#xA;#Possible solutions&#xD;&#xA;1. Give up multiple-shader-programs architecture and create one combined shader program&#xD;&#xA;2. Save somehow results to a buffer objects (I couldn't find out if this is possible except computation shaders)&#xD;&#xA;3. Render to texture and read the texture &#xD;&#xA;&#xD;&#xA;Is there a nicer solution?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8030" PostHistoryTypeId="1" PostId="3813" RevisionGUID="e86a447a-d84a-4794-a5c9-d5632099ca57" CreationDate="2016-08-02T06:06:04.130" UserId="4765" Text="Sharing calculation result between shader programs in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="8031" PostHistoryTypeId="3" PostId="3813" RevisionGUID="e86a447a-d84a-4794-a5c9-d5632099ca57" CreationDate="2016-08-02T06:06:04.130" UserId="4765" Text="|opengl|shader|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8032" PostHistoryTypeId="2" PostId="3814" RevisionGUID="37aa0d6a-3bd8-4ad6-954c-a6ca4ef026f2" CreationDate="2016-08-02T06:17:52.277" UserId="3073" Text="Yes you can, this is how deferred rendering for example would work. For that you would render to a texture in one pass, in openGL this would be via an FBO, then feed that texture as the input to the next pass/shader.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8033" PostHistoryTypeId="34" PostId="3746" RevisionGUID="9b31a047-bd60-4035-aec5-b238f1bb45df" CreationDate="2016-08-02T07:34:52.373" UserId="2485" Comment="19" />
  <row Id="8036" PostHistoryTypeId="5" PostId="3794" RevisionGUID="80d5432a-f0a6-4a28-acf1-c72a1511c90d" CreationDate="2016-08-02T07:43:42.017" UserId="2485" Comment="corrected formatting" Text="Your shaders are fine, the problem is topological, that is the way the vertices are connected to create triangles.&#xD;&#xA;&#xD;&#xA;For case 1 &amp; 2: You cannot really draw a grid of points in this mode (`GL_TRIANGLE_FAN`) as vertice 0 (the top left one) will be used in every triangle, as well as other issues. You should be using Triangle/Line strips, although these aren't so straightforward as some vertices are shared between each row.&#xD;&#xA;&#xD;&#xA;For example, imagine you have vertices arranged like so:&#xD;&#xA;&#xD;&#xA;&gt; 0 1 2&#xD;&#xA;&gt; &#xD;&#xA;&gt; 3 4 5&#xD;&#xA;&gt; &#xD;&#xA;&gt; 6 7 8&#xD;&#xA;&#xD;&#xA;You would draw strips by sending the above vertices in the following order:&#xD;&#xA;&#xD;&#xA;&gt; 0,3,1 (outputs triangle 0,1,3)&#xD;&#xA;&gt; &#xD;&#xA;&gt; 4,    (outputs triangle 1,3,4)&#xD;&#xA;&gt; &#xD;&#xA;&gt; 2,    (outputs triangle 1,2,4)&#xD;&#xA;&#xD;&#xA;etc..&#xD;&#xA;&#xD;&#xA;This you can do in code by scanning across 1 row of vertices and including the vertex on the next row for every other vertex.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    int numColumns = 5;   // As per your example..&#xD;&#xA;    int numRows = 5;&#xD;&#xA;    int verticeOffset = 0;&#xD;&#xA;    int verticeSize = 3;          // 3 floats per vertice&#xD;&#xA;    int nextRow = numColumns * verticeSize;   &#xD;&#xA;    &#xD;&#xA;    // This loop is for each row-strip, which requires 2 vertex rows..&#xD;&#xA;    for(int j = 0; j &lt; numRows - 1; j++) {&#xD;&#xA;       &#xD;&#xA;        // Inner loop sends vertices for each row-strip&#xD;&#xA;        for(int n = 0; n &lt; numColumns; n++, verticeOffset += verticeSize) {&#xD;&#xA;           glVertex3fv(vertices + verticeOffset);            // Current row&#xD;&#xA;           glVertex3fv(vertices + verticeOffset + nextRow);  // Row below&#xD;&#xA;        }&#xD;&#xA;        // This is special, we send a duplicate vertex to restart a new strip for the next row (This can be omitted if j == numRows - 1)&#xD;&#xA;        glVertex3fv(vertices + verticeOffset - verticeSize + nextRow);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are concerned about sending duplicate vertices you could use an additional indice buffer, as that will allow you to use the exact same vertex buffer you used for the `GL_POINTS` version." ContentLicense="CC BY-SA 3.0" />
  <row Id="8037" PostHistoryTypeId="24" PostId="3794" RevisionGUID="80d5432a-f0a6-4a28-acf1-c72a1511c90d" CreationDate="2016-08-02T07:43:42.017" Comment="Proposed by 2485 approved by 3073 edit id of 155" ContentLicense="CC BY-SA 3.0" />
  <row Id="8039" PostHistoryTypeId="2" PostId="3815" RevisionGUID="146e75f7-b134-48de-9ae0-ff501025c830" CreationDate="2016-08-02T12:19:18.660" UserId="273" Text="This is only a rough idea, though I hope it may inspire better answers.&#xD;&#xA;&#xD;&#xA;The closest point on a surface is as far as I know always forms together with the red point a line that is orthogonal to the surface.&#xD;&#xA;&#xD;&#xA;If you know which yellow vertices form the surface that the green point lies on, this is easy. You could just formulate the normal form of the surface (which is piecewise linear so it works out) formulate the orthogonal line to the surface that goes through the red point and solve for the intersection point. Though I don't have the exact math here, this step should be easy to look up.&#xD;&#xA;&#xD;&#xA;Now the problem is: Which linear piece of your surface is the closest one.&#xD;&#xA;Either you calculate the green-point candidates for all linear pieces and also the distance and take the closest one, or you find some other possibly faster way for this.&#xD;&#xA;For that I don't have a more clever idea.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8040" PostHistoryTypeId="5" PostId="3794" RevisionGUID="c5869774-0aa0-440d-85f4-0ba4c4c7f234" CreationDate="2016-08-02T12:40:50.633" UserId="231" Comment="Replace mixed use of vertex/vertice and index/indice with vertex and index " Text="Your shaders are fine, the problem is topological, that is the way the vertices are connected to create triangles.&#xD;&#xA;&#xD;&#xA;For cases 1 &amp; 2: You cannot really draw a grid of points in this mode (`GL_TRIANGLE_FAN`) as vertex 0 (the top left one) will be used in every triangle, as well as other issues. You should be using Triangle/Line strips, although these aren't so straightforward as some vertices are shared between each row.&#xD;&#xA;&#xD;&#xA;For example, imagine you have vertices arranged like so:&#xD;&#xA;&#xD;&#xA;&gt; 0 1 2&#xD;&#xA;&gt; &#xD;&#xA;&gt; 3 4 5&#xD;&#xA;&gt; &#xD;&#xA;&gt; 6 7 8&#xD;&#xA;&#xD;&#xA;You would draw strips by sending the above vertices in the following order:&#xD;&#xA;&#xD;&#xA;&gt; 0,3,1 (outputs triangle 0,1,3)&#xD;&#xA;&gt; &#xD;&#xA;&gt; 4,    (outputs triangle 1,3,4)&#xD;&#xA;&gt; &#xD;&#xA;&gt; 2,    (outputs triangle 1,2,4)&#xD;&#xA;&#xD;&#xA;etc...&#xD;&#xA;&#xD;&#xA;This you can do in code by scanning across 1 row of vertices and including the vertex on the next row for every other vertex.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    int numColumns = 5;   // As per your example..&#xD;&#xA;    int numRows = 5;&#xD;&#xA;    int vertexOffset = 0;&#xD;&#xA;    int vertexSize = 3;          // 3 floats per vertex&#xD;&#xA;    int nextRow = numColumns * vertexSize;   &#xD;&#xA;    &#xD;&#xA;    // This loop is for each row-strip, which requires 2 vertex rows..&#xD;&#xA;    for(int j = 0; j &lt; numRows - 1; j++) {&#xD;&#xA;       &#xD;&#xA;        // Inner loop sends vertices for each row-strip&#xD;&#xA;        for(int n = 0; n &lt; numColumns; n++, vertexOffset += vertexSize) {&#xD;&#xA;           glVertex3fv(vertices + vertexOffset);            // Current row&#xD;&#xA;           glVertex3fv(vertices + vertexOffset + nextRow);  // Row below&#xD;&#xA;        }&#xD;&#xA;        // This is special, we send a duplicate vertex to restart a new strip for the next row (This can be omitted if j == numRows - 1)&#xD;&#xA;        glVertex3fv(vertices + vertexOffset - vertexSize + nextRow);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If you are concerned about sending duplicate vertices you could use an additional index buffer, as that will allow you to use the exact same vertex buffer you used for the `GL_POINTS` version." ContentLicense="CC BY-SA 3.0" />
  <row Id="8044" PostHistoryTypeId="5" PostId="3813" RevisionGUID="b9376df4-68d1-47da-afa6-5c9d59ebce51" CreationDate="2016-08-02T20:15:25.777" UserId="231" Comment="Expand abbreviation in case anyone else, like me, needed to look up what it means..." Text="# Question&#xD;&#xA;Is there a way to compute something in a first shader program (eg. screen-space coordinates from word-space ones) and access those results in an another shader program? &#xD;&#xA;&#xD;&#xA;# Possible solutions&#xD;&#xA;1. Give up multiple-shader-programs architecture and create one combined shader program&#xD;&#xA;2. Save somehow results to a buffer objects (I couldn't find out if this is possible except computation shaders)&#xD;&#xA;3. Render to texture and read the texture &#xD;&#xA;&#xD;&#xA;Is there a nicer solution?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8045" PostHistoryTypeId="2" PostId="3817" RevisionGUID="e1cb20d7-7a5b-4ccb-a385-6a506e3e9263" CreationDate="2016-08-02T20:33:34.053" UserId="4854" Text="I always feel gaming, particularly AAA gaming (e.g., FPS), is and will be the last application for cloud rendering, regardless being VR or not. VR simply makes the problem/requirement harder. &#xD;&#xA;&#xD;&#xA;Because of the tight loop of interactivity, latency is the the blocking factor as others have pointed out -- and we know that unlike bandwidth, latency is a much harder problem to solve practically in a commercial world. Though technically solvable (say deploy a group game server in every county, which is well within the Geo-boundary range of your back-of-envolop calculation above; also your matchmaking process needs to do the right player grouping), it really needs justifiable business case.&#xD;&#xA;&#xD;&#xA;Having said that, some non-AAA titles could well fall into cloud side rendering.&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8049" PostHistoryTypeId="2" PostId="3818" RevisionGUID="f3ac03c5-365f-4499-af5e-07e5fc80a002" CreationDate="2016-08-03T05:56:53.610" UserId="1870" Text="Answering from a somewhat layperson's perspective (I'm not a hardware expert, but I have built my own computer), I'll analogize, using the situation of getting some ingredients for cooking food.&#xD;&#xA;&#xD;&#xA;Using &quot;main system&quot; RAM/storage is like you looking for an ingredient, not finding it in your cupboards, and, say, walking over to your neighbor and asking if they have any.  It turns out they do; they bring you it, you thank them and return to your house and use it.&#xD;&#xA;&#xD;&#xA;Using &quot;on board&quot; RAM/storage is like you looking for an ingredient, finding it in your cupboard, and using it.&#xD;&#xA;&#xD;&#xA;With on board RAM/storage, the GPU just has to do less work to obtain the information it needs.  The information is also simply closer, both physically and when considering the amount of hardware and software the information needs to go through.  With the on board RAM/storage, the GPU needs only look up where the information is, and then retrieve that information from RAM/storage, which then travels through maybe a couple inches of wire to the GPU's processing units.&#xD;&#xA;&#xD;&#xA;With main system RAM/storage, there is a larger distance of wire for the signal to travel through which, although it may be only a minuscule fraction of a second, can still add up over thousands of calls to retrieve information.  Also, there are more potential bottlenecks, with all the different pieces that are interconnected.&#xD;&#xA;&#xD;&#xA;Lastly, with on board RAM/storage, AMD has the opportunity to optimize the system, since they're controlling precisely hardware is being used.  This is just like how Apple tailors Mac OS to its Mac computers." ContentLicense="CC BY-SA 3.0" />
  <row Id="8050" PostHistoryTypeId="2" PostId="3819" RevisionGUID="4a8f8689-0033-48c6-9088-8d0bb8b22e19" CreationDate="2016-08-04T05:45:33.540" UserId="523" Text="There are material color and texture colors (e.g. `Kd 0.8 0.8 0.8` vs. `map_Kd diff.png`).  [The documentation](http://paulbourke.net/dataformats/mtl/) says of this:&#xD;&#xA;&#xD;&#xA;&gt; During rendering, the map_Kd value is multiplied by the Kd value.&#xD;&#xA;&#xD;&#xA;However, then there is a `decal` command, which specifies a different relation:&#xD;&#xA;&#xD;&#xA;&gt; During rendering, the Ka, Kd, and Ks values and the map_Ka, map_Kd, and map_Ks values are blended according to the following formula:&#xD;&#xA;&gt;&#xD;&#xA;&gt; result_color=tex_color(tv)\*decal(tv)+mtl_color\*(1.0-decal(tv))&#xD;&#xA;&gt;&#xD;&#xA;&gt; where tv is the texture vertex.&#xD;&#xA;&gt;&#xD;&#xA;&gt; &quot;result_color&quot; is the blended Ka, Kd, and Ks values.&#xD;&#xA;&#xD;&#xA;Essentially, this is saying that the `decal` at a particular `(u,v)` lerps between the texture at that `(u,v)` and the material color.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;How does one reconcile these two different usages in the documentation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8051" PostHistoryTypeId="1" PostId="3819" RevisionGUID="4a8f8689-0033-48c6-9088-8d0bb8b22e19" CreationDate="2016-08-04T05:45:33.540" UserId="523" Text="Alias|Wavefront .mtl File &quot;decal&quot; Command" ContentLicense="CC BY-SA 3.0" />
  <row Id="8052" PostHistoryTypeId="3" PostId="3819" RevisionGUID="4a8f8689-0033-48c6-9088-8d0bb8b22e19" CreationDate="2016-08-04T05:45:33.540" UserId="523" Text="|texture|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8073" PostHistoryTypeId="5" PostId="1432" RevisionGUID="a4c9fb4f-d83b-4e6a-af35-050bc87985dd" CreationDate="2016-08-04T14:57:25.730" UserId="110" Comment="Add image from &quot;Approximate Models For Physically Based Rendering&quot;" Text="[Anisotropic filtering](https://en.wikipedia.org/wiki/Anisotropic_filtering) &quot;retains the sharpness of a texture normally lost by MIP map texture's attempts to avoid aliasing&quot;. The Wikipedia article gives hints about how it can be implemented (&quot;probe the texture (...) for any orientation of anisotropy&quot;), but it does't read very clear to me.  &#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;There seem to be various implementations, as suggested by the tests illustrated in the [notes][1] of the presentation [Approximate Models For Physically Based Rendering][2]:&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What are the concrete computations performed by (modern) GPUs to choose the correct MIP level when using anisotropic filtering?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.dropboxusercontent.com/u/6809780/BLOG_HOSTING/sig2015_approx_models_PBR_notes_DRAFT.pdf&#xD;&#xA;  [2]: http://c0de517e.blogspot.jp/2016/07/siggraph-2015-notes-for-approximate.html&#xD;&#xA;  [3]: https://i.stack.imgur.com/9NAa0.png&#xD;&#xA;  [4]: https://dl.dropboxusercontent.com/u/6809780/BLOG_HOSTING/sig2015_approx_models_PBR_notes_DRAFT.pdf#page=37" ContentLicense="CC BY-SA 3.0" />
  <row Id="8074" PostHistoryTypeId="5" PostId="3817" RevisionGUID="5186fd26-e730-44ee-b137-dda63883b93b" CreationDate="2016-08-04T15:40:27.483" UserId="4854" Comment="added 7 characters in body" Text="I always feel gaming, particularly AAA gaming (e.g., FPS), is and will be the last application for cloud rendering, regardless being VR or not. VR simply makes the problem/requirement harder. &#xD;&#xA;&#xD;&#xA;Because of the tight loop of interactivity, latency is the the blocking factor as others have pointed out -- and we know that unlike bandwidth, latency is a much harder problem to solve practically in a commercial world. Though technically solvable (say deploying a group of game servers in every county, which is well within the Geo-boundary range of your back-of-envolop calculation above; also your matchmaking process needs to do the right player grouping), it really needs justifiable business case.&#xD;&#xA;&#xD;&#xA;Having said that, some non-AAA titles could well fall into cloud side rendering.&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8075" PostHistoryTypeId="2" PostId="3823" RevisionGUID="37c0bd33-2beb-4396-932d-29ecf0cf11ac" CreationDate="2016-08-05T16:25:40.423" UserId="4866" Text="I'm working on a document storage project and i found a problem.&#xD;&#xA;&#xD;&#xA;After converting/compressing a scanned document to black &amp; white sometimes, some areas of the document are unreadable because shadows are transformed to black chunks.&#xD;&#xA;&#xD;&#xA;Is it possible to find out when this black chunks are present on the images?&#xD;&#xA;&#xD;&#xA;the intuiton of this validation is to mark the file as unreadable to manual analisys." ContentLicense="CC BY-SA 3.0" />
  <row Id="8076" PostHistoryTypeId="1" PostId="3823" RevisionGUID="37c0bd33-2beb-4396-932d-29ecf0cf11ac" CreationDate="2016-08-05T16:25:40.423" UserId="4866" Text="detect blurred zones after conversion to black &amp; white" ContentLicense="CC BY-SA 3.0" />
  <row Id="8077" PostHistoryTypeId="3" PostId="3823" RevisionGUID="37c0bd33-2beb-4396-932d-29ecf0cf11ac" CreationDate="2016-08-05T16:25:40.423" UserId="4866" Text="|algorithm|transformations|optimisation|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8078" PostHistoryTypeId="2" PostId="3824" RevisionGUID="74cf4c2d-8051-4bd8-8632-87b3ff954cd9" CreationDate="2016-08-06T00:32:55.620" UserId="523" Text="I'm generalizing my texturing code, and have become confused by the frankly contradictory information about textures' pieces.  Specifically, **I'm looking to understand what _exactly_ the terms &quot;face&quot;, &quot;layer&quot;, &quot;layer-face&quot;, and &quot;mipmap chain&quot; refer to**.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I've put together an !ASCII-art diagram of what I think I understand for the example of a mipmapped cubemap array texture containing two cubemaps ([from my site](http://geometrian.com/programming/tutorials/gltextureterm/index.php), reproduced poorly here):&lt;pre&gt;&#xD;&#xA;																				   &quot;Mipmap&quot; /&#xD;&#xA;														 &quot;Layer-Face&quot;            &quot;Mipmap Chain&quot;&#xD;&#xA;														 (or &quot;Image&quot;)              ┌────┴────┐&#xD;&#xA;┌─ &quot;Texture&quot; (2D Cubemap Array) ──────────────────────────────┼────────────────────┼─────────┼──────────────────────────────────────────────┐&#xD;&#xA;│ ┌─ &quot;Image Array&quot; / &quot;Layered Image&quot; / &quot;Mipmap Level&quot; ────────┼────────────────────┼─────────┼────────────────────────────────────────────┐ │&#xD;&#xA;│ │ ┌─ &quot;Layer&quot; of Array ──────────────────────────────────────┼───────┐            │         │                                            │ │&#xD;&#xA;│ │ │                                                    ┌────┴────┐  │            │         │                                            │ │&#xD;&#xA;│ │ │   ╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗│╔═╦═╦═╦═╗│  │   ╔═╦═╦═╦═╗│╔═╦═╦═╦═╗│╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗ ╔═╦═╦═╦═╗     │ │&#xD;&#xA;│ │ │   ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣│╠═╬═╬═╬═╣│  │   ╠═╬═╬═╬═╣│╠═╬═╬═╬═╣│╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣     │ │&#xD;&#xA;│ │ │   ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣│╠═╬═╬═╬═╣│  │   ╠═╬═╬═╬═╣│╠═╬═╬═╬═╣│╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣     │ │&#xD;&#xA;│ │ │   ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣│╠═╬═╬═╬═╣│  │   ╠═╬═╬═╬═╣│╠═╬═╬═╬═╣│╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣ ╠═╬═╬═╬═╣     │ │&#xD;&#xA;│ │ │   ╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝│╚═╩═╩═╩═╝│  │   ╚═╩═╩═╩═╝│╚═╩═╩═╩═╝│╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝ ╚═╩═╩═╩═╝     │ │&#xD;&#xA;│ │ │                                                    └─────────┘  │            │         │                                            │ │&#xD;&#xA;│ │ └─────────────────────────────────────────────────────────────────┘            │         │                                            │ │&#xD;&#xA;│ └────────────────────────────────────────────────────────────────────────────────┼─────────┼────────────────────────────────────────────┘ │&#xD;&#xA;│         ╔═╦═╗     ╔═╦═╗     ╔═╦═╗     ╔═╦═╗     ╔═╦═╗     ╔═╦═╗           ╔═╦═╗  │  ╔═╦═╗  │  ╔═╦═╗     ╔═╦═╗     ╔═╦═╗     ╔═╦═╗         │&#xD;&#xA;│         ╠═╬═╣     ╠═╬═╣     ╠═╬═╣     ╠═╬═╣     ╠═╬═╣     ╠═╬═╣           ╠═╬═╣  │  ╠═╬═╣  │  ╠═╬═╣     ╠═╬═╣     ╠═╬═╣     ╠═╬═╣         │&#xD;&#xA;│         ╚═╩═╝     ╚═╩═╝     ╚═╩═╝     ╚═╩═╝     ╚═╩═╝     ╚═╩═╝           ╚═╩═╝  │  ╚═╩═╝  │  ╚═╩═╝     ╚═╩═╝     ╚═╩═╝     ╚═╩═╝         │&#xD;&#xA;│                                                                                  │         │                                              │&#xD;&#xA;│                                                                                  │         │                                              │&#xD;&#xA;│                                                                                  │         │                                              │&#xD;&#xA;│          ╔═╗       ╔═╗       ╔═╗       ╔═╗       ╔═╗       ╔═╗             ╔═╗   │   ╔═╗   │   ╔═╗       ╔═╗       ╔═╗       ╔═╗          │&#xD;&#xA;│          ╚═╝       ╚═╝       ╚═╝       ╚═╝       ╚═╝       ╚═╝             ╚═╝   │   ╚═╝   │   ╚═╝       ╚═╝       ╚═╝       ╚═╝          │&#xD;&#xA;│                                                                                  └─────────┘                                              │&#xD;&#xA;└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;&#xD;&#xA;Basically, I'd like corrections and additions to the above diagram, but if phrased as my key questions:&#xD;&#xA;&#xD;&#xA;1. Where does &quot;face&quot; fit in?&#xD;&#xA;2. Is my &quot;layer-face&quot; description correct?  Or maybe it refers to all mip levels instead?&#xD;&#xA;3. Is my description of a &quot;layer&quot; correct?&#xD;&#xA;1. Similarly, does a &quot;mipmap chain&quot; refer to all mip levels of a single face, or to all mip levels of the layer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8079" PostHistoryTypeId="1" PostId="3824" RevisionGUID="74cf4c2d-8051-4bd8-8632-87b3ff954cd9" CreationDate="2016-08-06T00:32:55.620" UserId="523" Text="Texture Parts Terminology" ContentLicense="CC BY-SA 3.0" />
  <row Id="8080" PostHistoryTypeId="3" PostId="3824" RevisionGUID="74cf4c2d-8051-4bd8-8632-87b3ff954cd9" CreationDate="2016-08-06T00:32:55.620" UserId="523" Text="|opengl|texture|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8081" PostHistoryTypeId="2" PostId="3825" RevisionGUID="ab73d612-512e-4cad-926b-a5836fbb4487" CreationDate="2016-08-06T09:09:51.730" UserId="1796" Text="Given that I have implemented a function called `calc_bspline_surf()` in C, and that function has the following declaration:&#xD;&#xA;&#xD;&#xA;    calc_bspline_surf(ctrlnet, p, q, U, V, u, v)&#xD;&#xA;    /*&#xD;&#xA;      ctrlnet --&gt; control net of B-spline surface&#xD;&#xA;      p, q --&gt; degree of B-spline surface&#xD;&#xA;      U, V --&gt; the knots vector in two directions&#xD;&#xA;      u, v --&gt; parameter pair&#xD;&#xA;    */&#xD;&#xA;&#xD;&#xA;So for a pair of parameters `{u, v}`, corresponding B-spline surface coordinate could be generated via calling function `calc_bspline_surf(u, v)`.&#xD;&#xA;&#xD;&#xA;However, how many 3D-points I need to sample? Is there classical sample strategy?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8082" PostHistoryTypeId="1" PostId="3825" RevisionGUID="ab73d612-512e-4cad-926b-a5836fbb4487" CreationDate="2016-08-06T09:09:51.730" UserId="1796" Text="How to sample 3D points to visualize a B-spline surface?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8083" PostHistoryTypeId="3" PostId="3825" RevisionGUID="ab73d612-512e-4cad-926b-a5836fbb4487" CreationDate="2016-08-06T09:09:51.730" UserId="1796" Text="|sampling|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8084" PostHistoryTypeId="2" PostId="3826" RevisionGUID="381fb118-d7ec-40c4-a5f3-03049aaf6fbc" CreationDate="2016-08-06T19:01:49.183" UserId="2308" Text="I am running this fragment shader on every pixel on screen. I am trying to make it as efficient as possible. BTW I am running open gl es 2.0.&#xD;&#xA;&#xD;&#xA;The code segment below is only a sample from the code, there are about 56 different calls to Gaussian() spread across different functions. I am wondering wether it would be valuable to replace the calls to Gaussian() with there appropriate resulting float value.&#xD;&#xA;&#xD;&#xA;I know a lot of times stuff like this is pre-calculated on compilation of the shader, or calculated only once because the gpu realizes it is the same calculation for all fragments.&#xD;&#xA;&#xD;&#xA;So would it be worthwhile for me to manually calculate each of these and replace them with their values?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    uniform float scalar;&#xD;&#xA;    varying float scalart;&#xD;&#xA;    float deviationScale = 1.2;&#xD;&#xA;    float finalScalar = 1.1;&#xD;&#xA;    float Gaussian(float x, float deviation)&#xD;&#xA;    {&#xD;&#xA;        return (1.0 / sqrt(2.0 * 3.141592 * deviation)) * exp(-((x * x) / (2.0 * deviation)));&#xD;&#xA;    }&#xD;&#xA;    vec3 blurS5()&#xD;&#xA;    {&#xD;&#xA;        vec3 blr = vec3(0.0);&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(2.0, 2.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(1.0, 2.0 * deviationScale) ;&#xD;&#xA;        &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(0.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(0.0, 2.0 * deviationScale) ;&#xD;&#xA;        &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-1.0, 2.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-2.0, 2.0 * deviationScale) ;&#xD;&#xA;        return blr;&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    		if (scalar == 2.)&#xD;&#xA;            {&#xD;&#xA;                gl_FragColor = vec4(blurS5(), 1.0);&#xD;&#xA;            }&#xD;&#xA;            else if (scalar == 3.)&#xD;&#xA;            {&#xD;&#xA;                gl_FragColor = vec4(blurS9(), 1.0);&#xD;&#xA;            }&#xD;&#xA;            //There are waaayyy more of these&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8085" PostHistoryTypeId="1" PostId="3826" RevisionGUID="381fb118-d7ec-40c4-a5f3-03049aaf6fbc" CreationDate="2016-08-06T19:01:49.183" UserId="2308" Text="Will the gaussian kernels in this fragment shader be computed for every fragment?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8086" PostHistoryTypeId="3" PostId="3826" RevisionGUID="381fb118-d7ec-40c4-a5f3-03049aaf6fbc" CreationDate="2016-08-06T19:01:49.183" UserId="2308" Text="|shader|fragment-shader|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8087" PostHistoryTypeId="2" PostId="3827" RevisionGUID="df5fd7bf-af27-4d8d-8e69-2d20aa27a747" CreationDate="2016-08-06T21:36:21.350" UserId="174" Text="In order to naïvely render sprites, you can send single rectangles with their position, rotation, size, and texture. This is very easy, but given that reducing state changes, draw calls, and data uploads are good ways to improve rendering performance, it's clearly not an efficient solution.&#xD;&#xA;Some techniques like passing each sprite as a single primitive and assembling a rectangle in the geometry shader are very appealing but aren't available if targeting a platform like WebGL or even just older hardware.&#xD;&#xA;&#xD;&#xA;On top of issues like batching and texture aliases, how do you efficiently submit geometry to render sprites?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8088" PostHistoryTypeId="1" PostId="3827" RevisionGUID="df5fd7bf-af27-4d8d-8e69-2d20aa27a747" CreationDate="2016-08-06T21:36:21.350" UserId="174" Text="Efficiently rendering sprites" ContentLicense="CC BY-SA 3.0" />
  <row Id="8089" PostHistoryTypeId="3" PostId="3827" RevisionGUID="df5fd7bf-af27-4d8d-8e69-2d20aa27a747" CreationDate="2016-08-06T21:36:21.350" UserId="174" Text="|rendering|efficiency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8090" PostHistoryTypeId="5" PostId="3825" RevisionGUID="fe0fe52e-a339-4e20-8bc3-19da1a5c406c" CreationDate="2016-08-07T05:14:02.940" UserId="1796" Comment="added 261 characters in body" Text="Given that I have implemented a function called `calc_bspline_surf()` in C, and that function has the following declaration:&#xD;&#xA;&#xD;&#xA;    calc_bspline_surf(ctrlnet, p, q, U, V, u, v)&#xD;&#xA;    /*&#xD;&#xA;      ctrlnet --&gt; control net of B-spline surface&#xD;&#xA;      p, q --&gt; degree of B-spline surface&#xD;&#xA;      U, V --&gt; the knots vector in two directions&#xD;&#xA;      u, v --&gt; parameter pair&#xD;&#xA;    */&#xD;&#xA;&#xD;&#xA;So for a pair of parameters `{u, v}`, corresponding B-spline surface coordinate could be generated via calling function `calc_bspline_surf(u, v)`.&#xD;&#xA;&#xD;&#xA;Here is a solution that sampling the 3D points uniformly in two direction&#xD;&#xA;&#xD;&#xA;    for u = {0, 0.05, ..., 1}&#xD;&#xA;        for v= {0, 0.05, ..., 1}&#xD;&#xA;           calc_bspline_surf(u, v)&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;However, how many 3D-points I need to sample? Is there classical sample strategy?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6J4Vr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8091" PostHistoryTypeId="2" PostId="3828" RevisionGUID="848a79d2-fc2d-4c25-9c96-6e865690145e" CreationDate="2016-08-07T12:03:08.463" UserId="182" Text="It depends. On a desktop, if the `Gaussian` function is always called with the same arguments, the shader compiler will probably optimize it so it's evaluated only once. On a mobile platform though, the compiler has less time to do optimizations and might miss it. Either way, you can confirm by looking at the generated assembly.&#xD;&#xA;&#xD;&#xA;Note that Aras Pranckevičius of Unity wrote a GLSL optimizer to address the problem of sub-optimal compilers on mobile: https://github.com/aras-p/glsl-optimizer&#xD;&#xA;&#xD;&#xA;That being said, regarding your sample code, I would definitely at least expose `(1.0 / sqrt(2.0 * 3.141592 * deviation))` as a uniform." ContentLicense="CC BY-SA 3.0" />
  <row Id="8092" PostHistoryTypeId="5" PostId="3827" RevisionGUID="986ff754-260f-4295-bed3-ab291e226955" CreationDate="2016-08-07T14:29:07.630" UserId="174" Comment="added 146 characters in body" Text="In order to naïvely render sprites, you can send single rectangles with their position, rotation, size, and texture. This is very easy, but given that reducing state changes, draw calls, and data uploads are good ways to improve rendering performance, it's clearly not an efficient solution.&#xD;&#xA;Some techniques like passing each sprite as a single primitive and assembling a rectangle in the geometry shader are very appealing but aren't available if targeting a platform like WebGL or even just older hardware.&#xD;&#xA;&#xD;&#xA;On top of issues like batching and texture aliases, how do you efficiently submit geometry to render sprites?&#xD;&#xA;&#xD;&#xA;I'm interested in answers that are rendering API-agnostic, but using a specific API like OpenGL or Direct X is fine for illustration purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="8093" PostHistoryTypeId="5" PostId="3827" RevisionGUID="cff085b8-cd6b-4bae-92cf-a4b8854feaf8" CreationDate="2016-08-07T18:13:29.600" UserId="174" Comment="edited body" Text="In order to naïvely render sprites, you can send single rectangles with their position, rotation, size, and texture. This is very easy, but given that reducing state changes, draw calls, and data uploads are good ways to improve rendering performance, it's clearly not an efficient solution.&#xD;&#xA;Some techniques like passing each sprite as a single primitive and assembling a rectangle in the geometry shader are very appealing but aren't available if targeting a platform like WebGL or even just older hardware.&#xD;&#xA;&#xD;&#xA;On top of issues like batching and texture aliases, how do you efficiently submit geometry to render sprites?&#xD;&#xA;&#xD;&#xA;I'm interested in answers that are rendering API agnostic, but using a specific API like OpenGL or Direct X is fine for illustration purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="8094" PostHistoryTypeId="2" PostId="3829" RevisionGUID="ac2e83c7-e86c-4c15-ace5-2372d13a7413" CreationDate="2016-08-07T22:06:03.660" UserId="48" Text="A good way to improve sprite rendering efficiency is [geometry instancing](https://en.wikipedia.org/wiki/Geometry_instancing). This lets you define a mesh using one vertex/index buffer pair, then render many instances of that mesh in a single draw call using a second vertex buffer whose elements define the instances. This is more widely supported than geometry shaders; in particular, it's is supported in WebGL via the [ANGLE_instanced_arrays extension](https://developer.mozilla.org/en-US/docs/Web/API/ANGLE_instanced_arrays).&#xD;&#xA;&#xD;&#xA;To apply this to sprites, one vertex buffer could define the shape of a sprite (i.e. a quad made of two triangles), then another vertex buffer could contain per-sprite information such as position, rotation, size, and so on.&#xD;&#xA;&#xD;&#xA;If there are 4 vertices per sprite and N sprites, the vertex shader will be called a total of 4N times, onces for each vertex in each sprite. You'd use the vertex shader to put the information from the two buffers together, transforming each vertex appropriately to the sprite's properties. This allows the GPU to do the work of generating all the vertices for the sprites, and saves on data uploaded from the CPU.&#xD;&#xA;&#xD;&#xA;Coincidentally, I published a small [OpenGL instancing demo](https://github.com/Reedbeta/gfx-workshops/) recently.&#xD;&#xA;&#xD;&#xA;Using instancing this way does require that all the sprites are drawn with the same state, i.e. the same shader, textures, blending mode and so on. If different states are needed for some sprites, a separate batch of instances will be needed for each state combination." ContentLicense="CC BY-SA 3.0" />
  <row Id="8095" PostHistoryTypeId="2" PostId="3830" RevisionGUID="7443c393-0a41-46c5-9608-673be9c5a5d8" CreationDate="2016-08-07T23:28:05.313" UserId="4874" Text="I been looking for a way to do anti-aliasing with deferred rendering with WebGL as my target platform. WebGL does not support multisampled FBOs. I found FXAA implmentations such as this https://github.com/mattdesl/glsl-fxaa/blob/master/fxaa.glsl and it has the following:&#xD;&#xA;&#xD;&#xA;    #ifndef FXAA_REDUCE_MIN&#xD;&#xA;        #define FXAA_REDUCE_MIN   (1.0/ 128.0)&#xD;&#xA;    #endif&#xD;&#xA;    #ifndef FXAA_REDUCE_MUL&#xD;&#xA;        #define FXAA_REDUCE_MUL   (1.0 / 8.0)&#xD;&#xA;    #endif&#xD;&#xA;    #ifndef FXAA_SPAN_MAX&#xD;&#xA;        #define FXAA_SPAN_MAX     8.0&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;Im wondering what does these settings do and if I could tweak those settings to produce better results. &#xD;&#xA;&#xD;&#xA;I have implemented FXAA with the default settings and I found the image quality to be unsatisfactory. Is there other anti aliasing techniques I could try given the limitations of webgl platform? " ContentLicense="CC BY-SA 3.0" />
  <row Id="8096" PostHistoryTypeId="1" PostId="3830" RevisionGUID="7443c393-0a41-46c5-9608-673be9c5a5d8" CreationDate="2016-08-07T23:28:05.313" UserId="4874" Text="What does these FXAA settings do?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8097" PostHistoryTypeId="3" PostId="3830" RevisionGUID="7443c393-0a41-46c5-9608-673be9c5a5d8" CreationDate="2016-08-07T23:28:05.313" UserId="4874" Text="|webgl|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8098" PostHistoryTypeId="2" PostId="3831" RevisionGUID="498c182c-4f74-45ba-ab59-684c879b7371" CreationDate="2016-08-08T00:03:31.260" UserId="48" Text="Based on your linked question, the problem appears to be that you don't get enough samples in highly curved areas of the surface. You could increase the sample density everywhere, but then you oversample the flatter areas and it becomes too slow.&#xD;&#xA;&#xD;&#xA;So, you need to increase the sample density locally in areas where it's needed. A conceptually simple algorithm for this is adaptive refinement. You would start out with a uniform sample grid in UV space. Then, detect grid squares in which the curvature is too high for the grid spacing (above some threshold), and subdivide them, adding additional samples in between the existing ones. This process can be repeated recursively on the new, smaller grid squares, subdividing as finely as the surface requires. You can tune the curvature threshold to balance fidelity versus performance.&#xD;&#xA;&#xD;&#xA;Since B-splines (NURBS) are based on rational functions, I would guess that the maximum curvature in a region can be found (or at least bounded) analytically. This would be ideal, if possible, since it would avoid the problem of missing a small high-curvature area if none of the initial grid points happen to land in it. However, in a pinch the curvature can be estimated by looking at the sample points you've evaluated. For instance, if $p_1, p_2, p_3$ are three sample points collinear in UV space, they should be close to collinear as well, if the surface is adequately sampled. So, you could for instance evaluate&#xD;&#xA;$$\frac{\|p_2 - p_1\| + \|p_3 - p_2\|}{\|p_3 - p_1\|}$$&#xD;&#xA;(the double bars mean vector length). If this is greater than some threshold value such as 0.1 or 0.5, then you would subdivide the area between these points." ContentLicense="CC BY-SA 3.0" />
  <row Id="8099" PostHistoryTypeId="5" PostId="3831" RevisionGUID="940a1599-f14f-4b41-84b3-091140bd6fdf" CreationDate="2016-08-08T04:15:03.340" UserId="48" Comment="correct example threshold values" Text="Based on your linked question, the problem appears to be that you don't get enough samples in highly curved areas of the surface. You could increase the sample density everywhere, but then you oversample the flatter areas and it becomes too slow.&#xD;&#xA;&#xD;&#xA;So, you need to increase the sample density locally in areas where it's needed. A conceptually simple algorithm for this is adaptive refinement. You would start out with a uniform sample grid in UV space. Then, detect grid squares in which the curvature is too high for the grid spacing (above some threshold), and subdivide them, adding additional samples in between the existing ones. This process can be repeated recursively on the new, smaller grid squares, subdividing as finely as the surface requires. You can tune the curvature threshold to balance fidelity versus performance.&#xD;&#xA;&#xD;&#xA;Since B-splines (NURBS) are based on rational functions, I would guess that the maximum curvature in a region can be found (or at least bounded) analytically. This would be ideal, if possible, since it would avoid the problem of missing a small high-curvature area if none of the initial grid points happen to land in it. However, in a pinch the curvature can be estimated by looking at the sample points you've evaluated. For instance, if $p_1, p_2, p_3$ are three sample points collinear in UV space, they should be close to collinear as well, if the surface is adequately sampled. So, you could for instance evaluate&#xD;&#xA;$$\frac{\|p_2 - p_1\| + \|p_3 - p_2\|}{\|p_3 - p_1\|}$$&#xD;&#xA;where the double bars mean vector length. If this is greater than some threshold value such as 1.1 or 1.5 (note that 1.0 would be perfectly flat), then you would subdivide the area between these points." ContentLicense="CC BY-SA 3.0" />
  <row Id="8100" PostHistoryTypeId="2" PostId="3832" RevisionGUID="ee6664fa-555e-40ae-8286-ea193c6df386" CreationDate="2016-08-08T04:23:40.170" UserId="3386" Text="1. A &quot;face&quot; simply specifies one of the six images at a level in a cubemap (and its optional mip pyramid). &#xD;&#xA;&#xD;&#xA;  It is helpful to think of level L of your mipmapped cube array texture as consisting of a 2D array of images, with exactly six columns comprising the six faces of the logical cube, and the N rows corresponding to the N layers of the array (some APIs call these &quot;slices&quot;). This is because non-array Cube textures are already structured like 2D arrays with exactly 6 layers. &#xD;&#xA;&#xD;&#xA;2. This is correct with the exception that it would refer to the entire mip pyramid for that layer-face. Regarding the 2D array of faces and layers i just mentioned, OpenGL uses a single index for this 2d array, &quot;unrolls&quot; it, and calls this 1D index a &quot;layer-face&quot;.  &#xD;&#xA;&#xD;&#xA;3. Yes, but again, encompasses the mip pyramids for each layer-face image in that layer&#xD;&#xA;&#xD;&#xA;4. Depends on the context, could be either.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8101" PostHistoryTypeId="2" PostId="3833" RevisionGUID="f5ce13b5-22aa-42d5-a27f-59b68dbf9e7a" CreationDate="2016-08-08T06:28:44.883" UserId="3058" Text="The rough definition of &quot;MTP&quot; is clear. But the exact one is not. You can refer http://www.chioka.in/what-is-motion-to-photon-latency or http://xinreality.com/wiki/Motion-to-photon_latency.&#xD;&#xA;But from different online articles, we get different explains on that:&#xD;&#xA;1) From Atman Binstock (Oculus) blog: https://developer.oculus.com/blog/optimizing-vr-graphics-with-late-latching. We can see MTP = T2(time to flip) - T1(Time of PO). But, T2 is just begining to display the image, not finish displaying.&#xD;&#xA;2) From John Carmack (Oculus) blog: http://www.chioka.in/what-is-motion-to-photon-latency/, MTP = T2(finish displaying) - T1(Time of PO).&#xD;&#xA;3) From Alex Vlachos (Valve) slides: Advanced VR Rendering, GDC 2015. MTP = T2(finish displaying) - T1(Time of PO)&#xD;&#xA;4) From Qualcomm blog: http://www.qualcomm.cn/news/blog-2016-07-20, (Sorry it is in Chinese), MTP = T2(half of finish displaying) - T1(Time of PO)&#xD;&#xA;&#xD;&#xA;I think Qualcomm's explain is the best. If it is correct, we can relax the rendering time budget. What's your opinions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8102" PostHistoryTypeId="1" PostId="3833" RevisionGUID="f5ce13b5-22aa-42d5-a27f-59b68dbf9e7a" CreationDate="2016-08-08T06:28:44.883" UserId="3058" Text="how to define &quot;motion to photon&quot; in VR?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8103" PostHistoryTypeId="3" PostId="3833" RevisionGUID="f5ce13b5-22aa-42d5-a27f-59b68dbf9e7a" CreationDate="2016-08-08T06:28:44.883" UserId="3058" Text="|rendering|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8104" PostHistoryTypeId="2" PostId="3834" RevisionGUID="045a1a83-53a9-47d3-bb6d-5d23fa92e06a" CreationDate="2016-08-08T17:27:27.653" UserId="3069" Text="I start saying that I am a newbie in computer graphics and I am trying to develop a special case of path tracing really slowly! But first: I came up studying the Mitsuba renderer and one of its uses in the so-called GDPT (Gradient Domain Path Tracer). I am trying to build a Cornell Box in this framework and my silly problem arises in realising which kind of material is a &quot;mirror&quot;. In simpler words: I want a mirroring sphere in my scene but I don't manage to create it. According to the documentation that you can find here (http://www.mitsuba-renderer.org/releases/current/documentation.pdf) we can have all the different surfaces explained in section 8.2, which are:&#xD;&#xA;&#xD;&#xA; - Smooth Diffuse material (diffuse)&#xD;&#xA; - Rough diffuse material(roughdiffuse) &#xD;&#xA; - Smooth dielectric material (dielectric)&#xD;&#xA; - Thin dielectric material (thindielectric)&#xD;&#xA; - Rough dielectric material  (roughdielectric)&#xD;&#xA; - Smooth conductor (conductor)&#xD;&#xA; - Rough conductor material (roughconductor)&#xD;&#xA; - Smooth plastic material (plastic)&#xD;&#xA; - Rough   plastic material (roughplastic)&#xD;&#xA; - Smooth dielectric coating (coating)&#xD;&#xA; - Rough dielectric coating (roughcoating)&#xD;&#xA;&#xD;&#xA;Can you please help me realising which one gives me a mirroring surface and the exact values I have to use to have such material? Usually for each kind of material there is an XML code of reference (which is what I am using to build the scene). Therefore, the main question remains understanding how to build a mirror, but please take those examples in considerations because the parameters in those are the only things I can tune. Thanks in advance!" ContentLicense="CC BY-SA 3.0" />
  <row Id="8105" PostHistoryTypeId="1" PostId="3834" RevisionGUID="045a1a83-53a9-47d3-bb6d-5d23fa92e06a" CreationDate="2016-08-08T17:27:27.653" UserId="3069" Text="How to create specular surface in Mitsurba Renderer" ContentLicense="CC BY-SA 3.0" />
  <row Id="8106" PostHistoryTypeId="3" PostId="3834" RevisionGUID="045a1a83-53a9-47d3-bb6d-5d23fa92e06a" CreationDate="2016-08-08T17:27:27.653" UserId="3069" Text="|rendering|specular|subsurface-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8108" PostHistoryTypeId="2" PostId="3835" RevisionGUID="76cff5fd-09a3-4bbf-9fd4-7d088210ab9f" CreationDate="2016-08-08T20:45:30.130" UserId="1930" Text="You want to use the &quot;conductor&quot; plugin to create a smooth conductor / metal type BRDF. See section 8.2.6 in the documentation.&#xD;&#xA;&#xD;&#xA;As far as Mitsuba is concerned, a mirror is a special instance of a metal, where the material is specified as &quot;none&quot; (which corresponds to using complex IOR of $ \eta = 0 $ and $ k = 1 $).&#xD;&#xA;&#xD;&#xA;Here is an example in xml:&#xD;&#xA;&#xD;&#xA;    &lt;shape type=&quot;...&quot;&gt;&#xD;&#xA;        &lt;bsdf type=&quot;conductor&quot;&gt;&#xD;&#xA;            &lt;string name=&quot;material&quot; value=&quot;none&quot;/&gt;&#xD;&#xA;        &lt;/bsdf&gt;&#xD;&#xA;    &lt;shape&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8109" PostHistoryTypeId="2" PostId="3836" RevisionGUID="fe196a65-0be0-40af-813b-51dd301b94ca" CreationDate="2016-08-08T21:12:17.303" UserId="3377" Text="Just in case anyone elso also needs to detect edges: &#xD;&#xA;[Here][1] is a nice article how to display a wireframe and [this][2] article explains how to show only the edges.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://strattonbrazil.blogspot.de/2011/09/single-pass-wireframe-rendering_10.html&#xD;&#xA;  [2]: http://strattonbrazil.blogspot.de/2011/09/single-pass-wireframe-rendering_11.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8110" PostHistoryTypeId="2" PostId="3837" RevisionGUID="e5dc6b1b-4b79-4262-b1fb-33eae50c8530" CreationDate="2016-08-09T17:58:59.387" UserId="4735" Text="I'm doing a direct implementation of DLT algorithm but I can't figure out why, at the end the matrix H I get doesn't (even remotely) produce x2 = H*x1&#xD;&#xA;&#xD;&#xA;The algorithm is not that complicated so I can't see what I'm missing at this stage.&#xD;&#xA;&#xD;&#xA;    %%point matching section (manual for now)&#xD;&#xA;    &#xD;&#xA;    % point selection &#xD;&#xA;    &#xD;&#xA;    [originalpoints1, normpoints1, translation1, scaling1 ]= pointprocessing(rootimage, false);&#xD;&#xA;    [originalpoints2, normpoints2, translation2, scaling2 ]= pointprocessing(sideimage, true);&#xD;&#xA;    &#xD;&#xA;    if(length (originalpoints1) ~= length (originalpoints2))&#xD;&#xA;        error('points must be referenced in both images');&#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    %% DLT transform application&#xD;&#xA;    &#xD;&#xA;    % getting A&#xD;&#xA;    i = 1;&#xD;&#xA;    A = zeros(2*length(originalpoints1), 9);&#xD;&#xA;    while(i &lt;= length(normpoints1))&#xD;&#xA;        x1 = normpoints1(1,i);&#xD;&#xA;        y1 = normpoints1(2,i);&#xD;&#xA;        w1 = normpoints1(3,i);&#xD;&#xA;        &#xD;&#xA;        x2 = normpoints2(1,i);&#xD;&#xA;        y2 = normpoints2(2,i);&#xD;&#xA;        w2 = normpoints2(3,i);&#xD;&#xA;        &#xD;&#xA;        a1 = - w2 * (normpoints1(:,i)');  &#xD;&#xA;        a2 =   y2 * (normpoints1(:,i)');&#xD;&#xA;        a3 =   w2 * (normpoints1(:,i)');&#xD;&#xA;        a4 = - x2 * (normpoints1(:,i)');&#xD;&#xA;        z = zeros(1,3);&#xD;&#xA;        &#xD;&#xA;       	a = [z a1 a2; a3 z a4];&#xD;&#xA;        &#xD;&#xA;        A(2*i-1, :) = a(1, :);&#xD;&#xA;        &#xD;&#xA;        A(2*i, :) = a(2, :);&#xD;&#xA;        &#xD;&#xA;        i = i + 1;&#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    % getting H&#xD;&#xA;    &#xD;&#xA;    [U D V] = svd(A);&#xD;&#xA;    &#xD;&#xA;    h = V(:, end);&#xD;&#xA;    &#xD;&#xA;    normH = reshape(h, 3, 3)';&#xD;&#xA;    &#xD;&#xA;    % denormalization&#xD;&#xA;    &#xD;&#xA;    T1 = scaling1 * translation1;&#xD;&#xA;    &#xD;&#xA;    T2 = scaling2 * translation2;&#xD;&#xA;    &#xD;&#xA;    H = inv(T2) * normH * T1;&#xD;&#xA;&#xD;&#xA;The normalizing process works as intended - I've double checked, performs the translation and scaling (none on Z) as intended. But for clarity sake here that one also:&#xD;&#xA;&#xD;&#xA;    function [ originalpoints, normpoints, translation, scaling ] = pointprocessing( image, flag )&#xD;&#xA;    &#xD;&#xA;    % point selection &#xD;&#xA;    &#xD;&#xA;    figure(1);&#xD;&#xA;    imshow(image);&#xD;&#xA;    axis on;&#xD;&#xA;    if (~flag)&#xD;&#xA;        title('select n &gt;= 4 reference points, double click last');&#xD;&#xA;    else&#xD;&#xA;        title('mark the same reference points (same order), double click last');&#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    [x, y] = getpts();&#xD;&#xA;    &#xD;&#xA;    close(1);&#xD;&#xA;    &#xD;&#xA;    if(length (x) &lt; 4 || length (y) &lt; 4)&#xD;&#xA;        error('selected too few points');&#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    % coordinate conversion  - centroid calculation&#xD;&#xA;    &#xD;&#xA;    center_x = mean(x);&#xD;&#xA;    &#xD;&#xA;    center_y = mean(y);&#xD;&#xA;    &#xD;&#xA;    originalpoints  = [x'; y'; ones(1, length (x))];&#xD;&#xA;    &#xD;&#xA;    % coordinate conversion - apply the translation&#xD;&#xA;    &#xD;&#xA;    translation = [1 0 -center_x; 0 1 -center_y; 0 0 1];&#xD;&#xA;    &#xD;&#xA;    translatedpoints = translation * originalpoints;&#xD;&#xA;    &#xD;&#xA;    % coordinate conversion - apply isotropic scaling&#xD;&#xA;    &#xD;&#xA;    goal = sqrt(2);&#xD;&#xA;    &#xD;&#xA;    heuristic = meandistance(translatedpoints);&#xD;&#xA;    &#xD;&#xA;    if(heuristic &lt; goal)&#xD;&#xA;        error('average distance between points too (1 pixel) small? double check')&#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    scaling_factor = (length(translatedpoints) * goal) / adaptedmeandistance(translatedpoints); &#xD;&#xA;    &#xD;&#xA;    scaling = [scaling_factor 0 0; 0 scaling_factor 0; 0 0 1];&#xD;&#xA;    &#xD;&#xA;    normpoints = scaling * translatedpoints;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    function [sum] = adaptedmeandistance(point_matrix)&#xD;&#xA;    &#xD;&#xA;    %assumes &gt; 3 points &#xD;&#xA;    i = 1;&#xD;&#xA;    sum = 0;&#xD;&#xA;    while (i &lt;= length(point_matrix))&#xD;&#xA;        sum = sum + abs(realsqrt( point_matrix(1,i)^2 + point_matrix(2,i)^2));&#xD;&#xA;        i = i + 1;&#xD;&#xA;    end&#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    function [distance] = meandistance(point_matrix)&#xD;&#xA;    &#xD;&#xA;    %assumes &gt; 3 points &#xD;&#xA;    i = 1;&#xD;&#xA;    sum = 0;&#xD;&#xA;    while (i &lt;= length(point_matrix))&#xD;&#xA;        sum = sum + euclidian(point_matrix(1,i), point_matrix(2,i), 0, 0);&#xD;&#xA;        i = i + 1;&#xD;&#xA;    end&#xD;&#xA;    distance = sum / length(point_matrix);&#xD;&#xA;    &#xD;&#xA;    end&#xD;&#xA;    &#xD;&#xA;    function [distance] = euclidian(point1_x, point1_y, point2_x, point2_y)&#xD;&#xA;        &#xD;&#xA;        distance = abs(realsqrt( (point1_x - point2_x)^2 + (point1_y - point2_y)^2));&#xD;&#xA;    &#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;The issue is that I get, for instance, an H of &#xD;&#xA;&#xD;&#xA;    0.4787    0.0051  186.8102&#xD;&#xA;    0.0702    0.4762  144.1276&#xD;&#xA;    0.0000    0.0000    0.4514&#xD;&#xA;&#xD;&#xA;Transforming originalpoints1&#xD;&#xA;&#xD;&#xA;       1.0e+03 *&#xD;&#xA;    &#xD;&#xA;        0.1465    2.3465    2.3465    0.1985&#xD;&#xA;        0.1545    0.1345    3.0545    3.0945&#xD;&#xA;        0.0010    0.0010    0.0010    0.0010&#xD;&#xA;&#xD;&#xA;into something,&#xD;&#xA;&#xD;&#xA;       1.0e+03 *&#xD;&#xA;    &#xD;&#xA;        0.2577    1.3108    1.3257    0.2976&#xD;&#xA;        0.2280    0.3729    1.7634    1.6316&#xD;&#xA;        0.0005    0.0006    0.0007    0.0006&#xD;&#xA;&#xD;&#xA;that's not originalpoints2&#xD;&#xA;&#xD;&#xA;       1.0e+03 *&#xD;&#xA;    &#xD;&#xA;        0.5545    2.2865    1.9265    0.5105&#xD;&#xA;        0.4905    0.6505    2.5625    2.7985&#xD;&#xA;        0.0010    0.0010    0.0010    0.0010&#xD;&#xA;&#xD;&#xA;The problem might be on the scale, should I manually enforce the scale of each point to 1? Doesn't that mean there's something wrong with H?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8111" PostHistoryTypeId="1" PostId="3837" RevisionGUID="e5dc6b1b-4b79-4262-b1fb-33eae50c8530" CreationDate="2016-08-09T17:58:59.387" UserId="4735" Text="DLT algorithm (4+ points) not working, what's missing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8112" PostHistoryTypeId="3" PostId="3837" RevisionGUID="e5dc6b1b-4b79-4262-b1fb-33eae50c8530" CreationDate="2016-08-09T17:58:59.387" UserId="4735" Text="|image-processing|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8113" PostHistoryTypeId="2" PostId="3838" RevisionGUID="97ff335a-3fce-4577-87b0-b2f59cb74288" CreationDate="2016-08-09T18:08:38.317" UserId="4735" Text="Just realized that this is an equation involving homogeneous vectors; thus the 3-vectors should not equal, they have the same direction but may differ in magnitude by a nonzero scale factor. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8114" PostHistoryTypeId="2" PostId="3839" RevisionGUID="8c656a4d-730b-4a96-a2f9-ec43f1e37132" CreationDate="2016-08-09T23:14:06.840" UserId="3386" Text="The shader compiler will very likely perform common-subexpression consolidation, and compute that function once, and reuse it each time it appears in the shader. &#xD;&#xA;&#xD;&#xA;You might think that, since `deviationScale` and all the other args are constants, it is possible it gets constant-folded entirely and never executes at runtime at all. But this is incorrect, as sqrt() and exp() are not compile-time constexpr functions.  The compiler cannot assume any specific implementation (and associated numerical properties) of these math functions, and so the entire function will not get optimized out, and it will not get re-used across threads either, as this is precluded by the shading language's programming model.&#xD;&#xA;&#xD;&#xA;Your best move is to pre-calculate the entire expression and stash it in a uniform, if it is important that this be optimal.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8115" PostHistoryTypeId="2" PostId="3840" RevisionGUID="efa3824b-50f5-45ee-9151-6ff8aa98c55c" CreationDate="2016-08-10T01:56:35.487" UserId="4886" Text="I'm attempting to perform an intersection test using ray casting (not sure if correct term so please forgive me if not) and am outputting the intersections as a point cloud, and the point cloud shows curvature (on the Z-axis only, the point cloud is completely flat on the Y axis, and the horizontal axis in this image is the X axis) (which I do not want):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I borrowed concepts from the Scratchapixel site, specifically http://scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection.&#xD;&#xA;&#xD;&#xA;Essentially, I am generating 16 rays, all with the same origin vector.  The direction vectors start at +15 degrees on the YZ plane, and continue in increments of -2 degrees down to -15.  I have an axis aligned bounding box that I am testing intersection with.  I use a rotation transform to rotate the 16 rays CCW around the Z axis.  I am performing the intersection test for all 16 rays each 0.1 degrees, and if it returns true, I add the point to the point cloud.&#xD;&#xA;&#xD;&#xA;Here's my intersection code:&#xD;&#xA;&#xD;&#xA;    bool test_intersect(Box b, Ray r, Vec3f&amp; intersect_point)&#xD;&#xA;    {&#xD;&#xA;    	float txmin = 0.0f, txmax = 0.0f, tymin = 0.0f, tymax = 0.0f, tzmin = 0.0f, tzmax = 0.0f;&#xD;&#xA;    	float t_min = 0.0f, t_max = 0.0f, t = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	// Determine inverse direction of ray to alleviate 0 = -0 issues&#xD;&#xA;    	Vec3f inverse_direction(1 / r.direction.x, 1 / r.direction.y, 1 / r.direction.z);&#xD;&#xA;    &#xD;&#xA;    	// Solving box_min/box_max0 = O + Dt &#xD;&#xA;    	txmin = (b.box_min.x - r.origin.x) * inverse_direction.x;&#xD;&#xA;    	txmax = (b.box_max.x - r.origin.x) * inverse_direction.x;&#xD;&#xA;    	tymin = (b.box_min.y - r.origin.y) * inverse_direction.y;&#xD;&#xA;    	tymax = (b.box_max.y - r.origin.y) * inverse_direction.y;&#xD;&#xA;    	tzmin = (b.box_min.z - r.origin.z) * inverse_direction.z;&#xD;&#xA;    	tzmax = (b.box_max.z - r.origin.z) * inverse_direction.z;&#xD;&#xA;    	&#xD;&#xA;    	// Depending on direction of ray tmin may &gt; tmax, so we may need to swap&#xD;&#xA;    	if (txmin &gt; txmax) std::swap(txmin, txmax);&#xD;&#xA;    	if (tymin &gt; tymax) std::swap(tymin, tymax);&#xD;&#xA;    	if (tzmin &gt; tzmax) std::swap(tzmin, tzmax);&#xD;&#xA;    &#xD;&#xA;    	t_min = txmin;&#xD;&#xA;    	t_max = txmax;&#xD;&#xA;    &#xD;&#xA;    	// If t-value of a min is greater than t-value of max,&#xD;&#xA;    	// we missed the object in that plane.&#xD;&#xA;    	if ((t_min &gt; tymax) || (tymin &gt; t_max))&#xD;&#xA;    		return false;&#xD;&#xA;    &#xD;&#xA;    	if (tymin &gt; t_min)&#xD;&#xA;    		t_min = tymin;&#xD;&#xA;    	if (tymax &lt; t_max)&#xD;&#xA;    		t_max = tymax;&#xD;&#xA;    &#xD;&#xA;    	if ((t_min &gt; tzmax) || (tzmin &gt; t_max))&#xD;&#xA;    		return false;&#xD;&#xA;    		&#xD;&#xA;    	if (tzmin &gt; t_min)&#xD;&#xA;    		t_min = tzmin;&#xD;&#xA;    	if (tzmax &lt; t_max)&#xD;&#xA;    		t_max = tzmax;&#xD;&#xA;    &#xD;&#xA;    	if (t_min &gt; 0)&#xD;&#xA;    		t = t_min;&#xD;&#xA;    	else&#xD;&#xA;    		if (t_max &gt; 0)&#xD;&#xA;    			t = t_max;&#xD;&#xA;    		else&#xD;&#xA;    			return false;&#xD;&#xA;    &#xD;&#xA;    	intersect_point.x = r.origin.x + r.direction.x * t;&#xD;&#xA;    	intersect_point.y = r.origin.y + r.direction.y * t;&#xD;&#xA;    	intersect_point.z = r.origin.z + r.direction.z * t;&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And my rotation:&#xD;&#xA;&#xD;&#xA;    // Rotation around z axis, for rotating array and checking beam intersections&#xD;&#xA;    void transform_rotate_z(Vec3f&amp; in_vector, float angle)&#xD;&#xA;    {&#xD;&#xA;    	float radians = angle * (M_PI / 180);&#xD;&#xA;    	&#xD;&#xA;    	float result_x = cos(radians) * in_vector.x + -sin(radians) * in_vector.y;&#xD;&#xA;    	float result_y = sin(radians) * in_vector.x + cos(radians) * in_vector.y;&#xD;&#xA;        float result_z = &#xD;&#xA;    	in_vector.x = result_x;&#xD;&#xA;    	in_vector.y = result_y;&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have racked my brain for quite a while but I can't seem to determine how I can prevent this curvature, I'm sure I'm overlooking something simple.  I'd be grateful for any help you can provide.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wd9OX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8116" PostHistoryTypeId="1" PostId="3840" RevisionGUID="efa3824b-50f5-45ee-9151-6ff8aa98c55c" CreationDate="2016-08-10T01:56:35.487" UserId="4886" Text="Ray casting in fan configuration produces point cloud with curvature, how to eliminate curvature?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8117" PostHistoryTypeId="3" PostId="3840" RevisionGUID="efa3824b-50f5-45ee-9151-6ff8aa98c55c" CreationDate="2016-08-10T01:56:35.487" UserId="4886" Text="|raytracing|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8118" PostHistoryTypeId="5" PostId="3840" RevisionGUID="c2e8a99b-e6a0-45f1-bf56-4c9638fff525" CreationDate="2016-08-10T02:02:38.127" UserId="4886" Comment="deleted 27 characters in body" Text="I'm attempting to perform an intersection test using ray casting (not sure if correct term so please forgive me if not) and am outputting the intersections as a point cloud, and the point cloud shows curvature (on the Z-axis only, the point cloud is completely flat on the Y axis, and the horizontal axis in this image is the X axis):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I borrowed concepts from the Scratchapixel site, specifically http://scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection.&#xD;&#xA;&#xD;&#xA;Essentially, I am generating 16 rays, all with the same origin vector.  The direction vectors start at +15 degrees on the YZ plane, and continue in increments of -2 degrees down to -15.  I have an axis aligned bounding box that I am testing intersection with.  I use a rotation transform to rotate the 16 rays CCW around the Z axis.  I am performing the intersection test for all 16 rays each 0.1 degrees, and if it returns true, I add the point to the point cloud.&#xD;&#xA;&#xD;&#xA;Here's my intersection code:&#xD;&#xA;&#xD;&#xA;    bool test_intersect(Box b, Ray r, Vec3f&amp; intersect_point)&#xD;&#xA;    {&#xD;&#xA;    	float txmin = 0.0f, txmax = 0.0f, tymin = 0.0f, tymax = 0.0f, tzmin = 0.0f, tzmax = 0.0f;&#xD;&#xA;    	float t_min = 0.0f, t_max = 0.0f, t = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	// Determine inverse direction of ray to alleviate 0 = -0 issues&#xD;&#xA;    	Vec3f inverse_direction(1 / r.direction.x, 1 / r.direction.y, 1 / r.direction.z);&#xD;&#xA;    &#xD;&#xA;    	// Solving box_min/box_max0 = O + Dt &#xD;&#xA;    	txmin = (b.box_min.x - r.origin.x) * inverse_direction.x;&#xD;&#xA;    	txmax = (b.box_max.x - r.origin.x) * inverse_direction.x;&#xD;&#xA;    	tymin = (b.box_min.y - r.origin.y) * inverse_direction.y;&#xD;&#xA;    	tymax = (b.box_max.y - r.origin.y) * inverse_direction.y;&#xD;&#xA;    	tzmin = (b.box_min.z - r.origin.z) * inverse_direction.z;&#xD;&#xA;    	tzmax = (b.box_max.z - r.origin.z) * inverse_direction.z;&#xD;&#xA;    	&#xD;&#xA;    	// Depending on direction of ray tmin may &gt; tmax, so we may need to swap&#xD;&#xA;    	if (txmin &gt; txmax) std::swap(txmin, txmax);&#xD;&#xA;    	if (tymin &gt; tymax) std::swap(tymin, tymax);&#xD;&#xA;    	if (tzmin &gt; tzmax) std::swap(tzmin, tzmax);&#xD;&#xA;    &#xD;&#xA;    	t_min = txmin;&#xD;&#xA;    	t_max = txmax;&#xD;&#xA;    &#xD;&#xA;    	// If t-value of a min is greater than t-value of max,&#xD;&#xA;    	// we missed the object in that plane.&#xD;&#xA;    	if ((t_min &gt; tymax) || (tymin &gt; t_max))&#xD;&#xA;    		return false;&#xD;&#xA;    &#xD;&#xA;    	if (tymin &gt; t_min)&#xD;&#xA;    		t_min = tymin;&#xD;&#xA;    	if (tymax &lt; t_max)&#xD;&#xA;    		t_max = tymax;&#xD;&#xA;    &#xD;&#xA;    	if ((t_min &gt; tzmax) || (tzmin &gt; t_max))&#xD;&#xA;    		return false;&#xD;&#xA;    		&#xD;&#xA;    	if (tzmin &gt; t_min)&#xD;&#xA;    		t_min = tzmin;&#xD;&#xA;    	if (tzmax &lt; t_max)&#xD;&#xA;    		t_max = tzmax;&#xD;&#xA;    &#xD;&#xA;    	if (t_min &gt; 0)&#xD;&#xA;    		t = t_min;&#xD;&#xA;    	else&#xD;&#xA;    		if (t_max &gt; 0)&#xD;&#xA;    			t = t_max;&#xD;&#xA;    		else&#xD;&#xA;    			return false;&#xD;&#xA;    &#xD;&#xA;    	intersect_point.x = r.origin.x + r.direction.x * t;&#xD;&#xA;    	intersect_point.y = r.origin.y + r.direction.y * t;&#xD;&#xA;    	intersect_point.z = r.origin.z + r.direction.z * t;&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And my rotation:&#xD;&#xA;&#xD;&#xA;    // Rotation around z axis, for rotating array and checking beam intersections&#xD;&#xA;    void transform_rotate_z(Vec3f&amp; in_vector, float angle)&#xD;&#xA;    {&#xD;&#xA;    	float radians = angle * (M_PI / 180);&#xD;&#xA;    	&#xD;&#xA;    	float result_x = cos(radians) * in_vector.x + -sin(radians) * in_vector.y;&#xD;&#xA;    	float result_y = sin(radians) * in_vector.x + cos(radians) * in_vector.y;&#xD;&#xA;    	in_vector.x = result_x;&#xD;&#xA;    	in_vector.y = result_y;&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have racked my brain for quite a while but I can't seem to determine how I can prevent this curvature, I'm sure I'm overlooking something simple.  I'd be grateful for any help you can provide.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wd9OX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8119" PostHistoryTypeId="2" PostId="3841" RevisionGUID="9b955a8c-6b1b-4064-a89c-491182430bba" CreationDate="2016-08-10T04:18:41.373" UserId="48" Text="&gt; The direction vectors start at +15 degrees on the YZ plane, and continue in increments of -2 degrees down to -15.&#xD;&#xA;&#xD;&#xA;There's your problem—by generating the rays that way, you're doing something more like a spherical projection or fisheye projection, not a linear perspective projection. The nonlinear projection is the origin of the curvature you see.&#xD;&#xA;&#xD;&#xA;To get a perspective projection instead, conceptually the way to think about it is that there's an image rectangle floating in front of the camera, divided into grid squares (pixels), and you fire a ray from the camera position toward the center of each pixel. In code, this looks something like:&#xD;&#xA;&#xD;&#xA;    p = tan(horizontalFOV / 2)&#xD;&#xA;    q = tan(verticalFOV / 2)&#xD;&#xA;    for y = 0 to imageHeight - 1&#xD;&#xA;        for x = 0 to imageWidth - 1&#xD;&#xA;            rayDirection = Vec3f(1.0,&#xD;&#xA;                                 p * ((x + 0.5) / imageWidth * 2.0 - 1.0)&#xD;&#xA;                                 q * ((y + 0.5) / imageHeight * 2.0 - 1.0)).normalize()&#xD;&#xA;&#xD;&#xA;Note that the directions generated this way are not equally spaced in angle (they're closer together in angle toward the edges of the image than at the center), but they _are_ equally spaced in distance on the image rectangle." ContentLicense="CC BY-SA 3.0" />
  <row Id="8120" PostHistoryTypeId="2" PostId="3842" RevisionGUID="fd08fc24-b208-4703-ba7a-c05d0f328a28" CreationDate="2016-08-10T11:05:45.350" UserId="2736" Text="So I'm trying to wrap my head around this from a fairly technical point of view.&#xD;&#xA;&#xD;&#xA;When you add a Bump or Normal or Displacement map in your shader they should not be gamma corrected. But diffuse textures should be. But why?&#xD;&#xA;&#xD;&#xA;When you save a file in 8bit (or 16bit Integer) with a format like JPEG, PNG or TIFF they get the gamma of 0.4545 (1/2.2) burnt in. So a camera captures the light from the real world (that is linear) and when saving the photo as a JPEG a gamma value of 1/2.2 is added, as a way to compress the information into 8bit, and then when you view the image on a monitor that adds a gamma of 2.2 making the luminance linear again.&#xD;&#xA;&#xD;&#xA;So when using a diffuse textures (like a photo) you need to a &quot;remove&quot; that 1/2.2 gamma to make it linear (called linearizing) so now the texture looks darker but these values are correct from a mathematical standpoint so the renderer will make the correct calculations. Side note: the software used a display gamma of 2.2 to make sure the textures looks correct it's just for the internal calculation that they are linearized. But when I create a Bump map in Photoshop and save that as a JPG or PNG then that 1/2.2 gamma is burnt into that image as well, so why doesn't this Bump map need to be linearized as well?&#xD;&#xA;&#xD;&#xA;If I load a Bump map in 3ds Max with a input gamma of 2.2 just like a would do with a Diffuse texture, the diffuse looks right but the bump looks wrong, so I have to set the input gamma to 1.0 for the bump in order to make it look right, but as I said: why, both image files have the 1/2.2 gamma burnt in, right?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8121" PostHistoryTypeId="1" PostId="3842" RevisionGUID="fd08fc24-b208-4703-ba7a-c05d0f328a28" CreationDate="2016-08-10T11:05:45.350" UserId="2736" Text="Why shouldn't Bump, Normal and Displacement maps be gamma corrected?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8122" PostHistoryTypeId="3" PostId="3842" RevisionGUID="fd08fc24-b208-4703-ba7a-c05d0f328a28" CreationDate="2016-08-10T11:05:45.350" UserId="2736" Text="|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8126" PostHistoryTypeId="50" PostId="3596" RevisionGUID="44c7bd3f-740d-4c54-aeeb-9de8212f7944" CreationDate="2016-08-10T12:37:40.973" UserId="-1" />
  <row Id="8128" PostHistoryTypeId="2" PostId="3844" RevisionGUID="a87f366e-85c2-4dc8-9d54-9644563c3a99" CreationDate="2016-08-10T14:46:23.977" UserId="2817" Text="Actually, if your bump or displacement map is saved with that 0.45 gamma correction, it's wrong. These maps contain geometrical information rather than light, and as such, should be simply encoded linearly.&#xD;&#xA;&#xD;&#xA;For a related issue and a fix for Adobe Photoshop, see this slide deck: https://docs.google.com/presentation/d/1vS5nAAnXbZ8Pt6-dXxy-xEXDkjfjXTmNnthNGccorl0/edit#slide=id.g14b3e28660_0_8" ContentLicense="CC BY-SA 3.0" />
  <row Id="8130" PostHistoryTypeId="2" PostId="3845" RevisionGUID="5c304a77-70c2-43f0-8430-26a3a4c0aae8" CreationDate="2016-08-10T15:14:13.783" UserId="3470" Text="JPG, PNG or any other 8 bit image formats do not intrinsically have 1/2.2 gamma associated with it. They just store values from 0-255. How that data is interpreted depends on the software that reads and writes those files. The interesting fact is that most image editing software uses gamma color space by default. All the brushes, effects, filters and even the color picker all operate in gamma space. Just look at the shades of gray on the color picker in Photoshop. They do not follow a linear distribution.&#xD;&#xA;&#xD;&#xA;The consequence is that Photoshop does no conversions between gamma and linear color space when opening or saving an image (by default), only when displaying it. That means that you can just as easily use it to create or edit linear data such as a heightmap as you can edit photos. The bump map does not look correctly when loaded with gamma correction, because it wasn't saved with it." ContentLicense="CC BY-SA 3.0" />
  <row Id="8131" PostHistoryTypeId="2" PostId="3846" RevisionGUID="b6279d0f-cc75-48c3-98d4-b2e41ee023ce" CreationDate="2016-08-10T15:40:22.977" UserId="182" Text="The fact that a photo is stored in gamma space doesn't have to do with PNG or JPEG, it has to do with the fact that it's a photo.&#xD;&#xA;&#xD;&#xA;The camera detects a 50% intensity but is going to save it as a 187 instead of 127, because that is more efficient to keep the color information that matters when you have only 255 different possible values. And so does Photoshop if you tell it so. For normals or displacement maps, you don't have this need so there is no reason to use gamma space for them (it would actually be a mistake to use it). Thus when you decode a normal texture or a displacement texture, you don't need to apply gamma.&#xD;&#xA;&#xD;&#xA;If the normal map is encoded in a different space though, [as can be the case for a G-Buffer for example][1], then you have to apply the corresponding correction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://aras-p.info/texts/CompactNormalStorage.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8136" PostHistoryTypeId="2" PostId="3848" RevisionGUID="b90396c6-58c0-4193-b918-1246b04a241b" CreationDate="2016-08-11T20:50:28.990" UserId="38" Text="### Introduction&#xD;&#xA;&#xD;&#xA;It depends on how you do the map! Consider the following and let it sink in for a while before you go forward:&#xD;&#xA;&#xD;&#xA;1. The image is displayed with a gamma correction for the benefit of your eyes&#xD;&#xA;2. The data is still just data. The gamma correction is for the display part not the data part.&#xD;&#xA;&#xD;&#xA;Now a bump map is pretty hard to draw with a paint application. Because its hard to see even if you were correctly linear. So you end up using such things as looking at values. Now here is the catch:&#xD;&#xA;&#xD;&#xA;* If you decide that 128 is halfway in your intensity then that is reality. Since that is what your encoding into the data stream. The data is what you interpret it to be since its not meant for human eyes and the monitor. Who cares what the monitor shows the values as its all on how you interpret the data editing it in.&#xD;&#xA;&#xD;&#xA;### Making the bump map&#xD;&#xA;&#xD;&#xA;Ok, so now I have described that the data is up to interpretation. But why would you interpret the data as linear? Because then you can design your side profile better. See what you can do is think of 100% opacity of your brush as the target height you want to carve or layer to. You can then use the curves tool to design the shape of your stamps brush (since you think the data is linear). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A suction cup stamp. &#xD;&#xA;&#xD;&#xA;Now if you do something like this then your image is linear despite what everybody tells you. You have decided to discard the image rules that says otherwise. **And that is why the image is linear**, the author chooses for it to be linear so its easier to work with.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 2**: Same image bumped and interpreted linear (note I scaled the height a bit to fit to my default bb size), working as intended.&#xD;&#xA;&#xD;&#xA;### Technically linear is better.&#xD;&#xA;&#xD;&#xA;A synthetic map has no benefit of compressing certain values on the expense of others. Linear is inherently better because the spread of your bump is better that way. Which is why you'd be wasting resources encoding it in a gamma corrected manner.&#xD;&#xA;&#xD;&#xA;Secondly a image does not need to specify what color space it is in. Its just that image editors will assume it is sRGB encoded. You have no reason to do same interpretation, no info means just: &quot;Nobody bothered to write down what they were thinking&quot;. So maybe the point should be made you should tag it linear. But here is the rub... your computer does not come with a easily accessible linear profile.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### What about Photoshop and blur?&#xD;&#xA;&#xD;&#xA;This is where it gets tricky. Photoshop tries to do quite much work to ensure that you do not need to know anything about this stuff. And this is where you shoot yourself in the foot. Se Photoshop is not meant for texture making, its meant to edit images not random data. So since blur on a image is different linear and nonlinear it wont work its geared to wrong data.&#xD;&#xA;&#xD;&#xA;But you can do one of 2 things to fix this:&#xD;&#xA;&#xD;&#xA;1. Disable the gamma correction of blur&#xD;&#xA;2. set your working space to a linear profile&#xD;&#xA;&#xD;&#xA;### Conclusion&#xD;&#xA;&#xD;&#xA;The reason you have a hard time with this is &#xD;&#xA;&#xD;&#xA;1. You do not know what other people think, you simply do not know if they should be gamma corrected or not.&#xD;&#xA;2. that your using a application that treats images as images&#xD;&#xA;&#xD;&#xA;Point one is especially confusing. I just know that ALL my bump and displacement maps are in fact linear. But I can not know what your maps are.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mz2yX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/txFW0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8137" PostHistoryTypeId="5" PostId="3848" RevisionGUID="aba3ac8b-6712-46fb-ad16-cdd3d304645a" CreationDate="2016-08-11T20:58:01.497" UserId="38" Comment="added 287 characters in body" Text="### Introduction&#xD;&#xA;&#xD;&#xA;It depends on how you create the map! Consider the following and let it sink in for a while before you go forward:&#xD;&#xA;&#xD;&#xA;1. The image is displayed with a gamma correction for the benefit of your eyes&#xD;&#xA;2. The data is still just data. The gamma correction is for the display part not the data part.&#xD;&#xA;&#xD;&#xA;Now a bump map is pretty hard to draw with a paint application. Because its hard to see even if you were correctly linear. So you end up using such things as looking at values. Now here is the catch:&#xD;&#xA;&#xD;&#xA;* If you decide that 128 is halfway in your intensity then that is reality. Since that is what your encoding into the data stream. The data is what you interpret it to be since its not meant for human eyes and the monitor. Who cares what the monitor shows the values as its all on how you interpret the data editing it in.&#xD;&#xA;&#xD;&#xA;### Making the bump map&#xD;&#xA;&#xD;&#xA;Ok, so now I have described that the data is up to interpretation. But why would you interpret the data as linear? Because then you can design your side profile better. See what you can do is think of 100% opacity of your brush as the target height you want to carve or layer to. You can then use the curves tool to design the shape of your stamps brush (since you think the data is linear). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A suction cup stamp. &#xD;&#xA;&#xD;&#xA;Now if you do something like this then your image is linear despite what everybody tells you. You have decided to discard the image rules that says otherwise. **And that is why the image is linear**, the author chooses for it to be linear so its easier to work with.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 2**: Same image bumped and interpreted linear (note I scaled the height a bit to fit to my default bb size), working as intended.&#xD;&#xA;&#xD;&#xA;### Technically linear is better.&#xD;&#xA;&#xD;&#xA;A synthetic map has no benefit of compressing certain values on the expense of others. Linear is inherently better because the spread of your bump is better that way. Which is why you'd be wasting resources encoding it in a gamma corrected manner.&#xD;&#xA;&#xD;&#xA;Secondly a image does not need to specify what color space it is in. Its just that image editors will assume it is sRGB encoded. You have no reason to do same interpretation, no info means just: &quot;Nobody bothered to write down what they were thinking&quot;. So maybe the point should be made you should tag it linear. But here is the rub... your computer does not come with a easily accessible linear profile.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### What about Photoshop and blur?&#xD;&#xA;&#xD;&#xA;This is where it gets tricky. Photoshop tries to do quite much work to ensure that you do not need to know anything about this stuff. And this is where you shoot yourself in the foot. Se Photoshop is not meant for texture making, its meant to edit images not random data. So since blur on a image is different linear and nonlinear it wont work its geared to wrong data.&#xD;&#xA;&#xD;&#xA;But you can do one of 2 things to fix this:&#xD;&#xA;&#xD;&#xA;1. Disable the gamma correction of blur&#xD;&#xA;2. set your working space to a linear profile&#xD;&#xA;&#xD;&#xA;### Conclusion&#xD;&#xA;&#xD;&#xA;The reason you have a hard time with this is &#xD;&#xA;&#xD;&#xA;1. You do not know what other people think, you simply do not know if they should be gamma corrected or not.&#xD;&#xA;2. that your using a application that treats images as images&#xD;&#xA;&#xD;&#xA;Point one is especially confusing. I just know that ALL my bump and displacement maps are in fact linear. But I can not know what your maps are. Odds are they are linear because its nearly universally understood that the data is linear. Even people who do not know about gamma tend to do it linear for bump/displacement for some reason (because its easy and that's what you think images are until somebody tells you otherwise).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mz2yX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/txFW0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8138" PostHistoryTypeId="5" PostId="3848" RevisionGUID="75fe4482-3df8-4cfe-b731-e14ea9eb5ee0" CreationDate="2016-08-12T05:49:14.120" UserId="38" Comment="added 16 characters in body" Text="### Introduction&#xD;&#xA;&#xD;&#xA;It depends on how you create the map! Consider the following and let it sink in for a while before you go forward:&#xD;&#xA;&#xD;&#xA;1. The image is displayed with a gamma correction for the benefit of your eyes&#xD;&#xA;2. The data is still just data. The gamma correction is for the display part not the data part.&#xD;&#xA;&#xD;&#xA;Now a bump map is pretty hard to draw with a paint application. Because its hard to see even if you were correctly linear. So you end up using such things as looking at values. Now here is the catch:&#xD;&#xA;&#xD;&#xA;* If you decide that 128 is halfway in your intensity then that is reality. Since that is what your encoding into the data stream. The data is what you interpret it to be since its not meant for human eyes and the monitor. Who cares what the monitor shows the values as its all on how you interpret the data editing it in.&#xD;&#xA;&#xD;&#xA;### Making the bump/displacement map&#xD;&#xA;&#xD;&#xA;Ok, so now I have described that the data is up to interpretation. But why would you interpret the data as linear? Because then you can design your side profile better. See what you can do is think of 100% opacity of your brush as the target height you want to carve or layer to. You can then use the curves tool to design the shape of your stamps brush (since you think the data is linear). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: A suction cup stamp. &#xD;&#xA;&#xD;&#xA;Now if you do something like this then your image is linear despite what everybody tells you. You have decided to discard the image rules that says otherwise. **And that is why the image is linear**, the author chooses for it to be linear so its easier to work with.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 2**: Same image displaced and interpreted linear (note I scaled the height a bit to fit to my default bb size), working as intended.&#xD;&#xA;&#xD;&#xA;### Technically linear is better.&#xD;&#xA;&#xD;&#xA;A synthetic map has no benefit of compressing certain values on the expense of others. Linear is inherently better because the spread of your bump is better that way. Which is why you'd be wasting resources encoding it in a gamma corrected manner.&#xD;&#xA;&#xD;&#xA;Secondly a image does not need to specify what color space it is in. Its just that image editors will assume it is sRGB encoded. You have no reason to do same interpretation, no info means just: &quot;Nobody bothered to write down what they were thinking&quot;. So maybe the point should be made you should tag it linear. But here is the rub... your computer does not come with a easily accessible linear profile.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### What about Photoshop and blur?&#xD;&#xA;&#xD;&#xA;This is where it gets tricky. Photoshop tries to do quite much work to ensure that you do not need to know anything about this stuff. And this is where you shoot yourself in the foot. Se Photoshop is not meant for texture making, its meant to edit images not random data. So since blur on a image is different linear and nonlinear it wont work its geared to wrong data.&#xD;&#xA;&#xD;&#xA;But you can do one of 2 things to fix this:&#xD;&#xA;&#xD;&#xA;1. Disable the gamma correction of blur&#xD;&#xA;2. set your working space to a linear profile&#xD;&#xA;&#xD;&#xA;### Conclusion&#xD;&#xA;&#xD;&#xA;The reason you have a hard time with this is &#xD;&#xA;&#xD;&#xA;1. You do not know what other people think, you simply do not know if they should be gamma corrected or not.&#xD;&#xA;2. that your using a application that treats images as images&#xD;&#xA;&#xD;&#xA;Point one is especially confusing. I just know that ALL my bump and displacement maps are in fact linear. But I can not know what your maps are. Odds are they are linear because its nearly universally understood that the data is linear. Even people who do not know about gamma tend to do it linear for bump/displacement for some reason (because its easy and that's what you think images are until somebody tells you otherwise).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mz2yX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/txFW0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8139" PostHistoryTypeId="2" PostId="3849" RevisionGUID="7e7cd119-9377-4bfb-84c3-c6ae015c78fe" CreationDate="2016-08-12T22:14:28.347" UserId="4843" Text="I am implementing Bezier curve offset.&#xD;&#xA;&#xD;&#xA;My approach is simple:&#xD;&#xA;&#xD;&#xA; 1. Given the handles, calculate the vectors normal to them&#xD;&#xA; 2. Move the handle along the normal vector.&#xD;&#xA; 3. If the new curve intersects the old one, reverse the offset direction.&#xD;&#xA; 4. etc.&#xD;&#xA;&#xD;&#xA;I would like to find an alternative to step 3. I believe the problem comes from my careless handling of vector maths (mainly calculations involving the cross product). Are there other ways to check the offset direction other than the one I just described?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8140" PostHistoryTypeId="1" PostId="3849" RevisionGUID="7e7cd119-9377-4bfb-84c3-c6ae015c78fe" CreationDate="2016-08-12T22:14:28.347" UserId="4843" Text="Checking the correct offset direction for Bezier curve offset" ContentLicense="CC BY-SA 3.0" />
  <row Id="8141" PostHistoryTypeId="3" PostId="3849" RevisionGUID="7e7cd119-9377-4bfb-84c3-c6ae015c78fe" CreationDate="2016-08-12T22:14:28.347" UserId="4843" Text="|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8142" PostHistoryTypeId="2" PostId="3850" RevisionGUID="32e1bea6-677d-4034-8456-f94c7efb41df" CreationDate="2016-08-12T23:48:03.667" UserId="2437" Text="I am making an engine with 2D volumetric transparent objects and need advice how to store transparency data. There are 3 requirements:   &#xD;&#xA;- The transparency textures need to be easily editable with common tools (e.g paint.NET, so .png preferred)       &#xD;&#xA;- Since a pixel value will determine the light transmittance 8 bits are not enough - in this case lights could travel maximum 256 pixels in non-transparent textures.   &#xD;&#xA;- It should be clear what each pixel means.    &#xD;&#xA;&#xD;&#xA;I've tried using the HEX values from RGB pixels. For example heres a strip with HEX values from 0 to 0xFFFFFF:&#xD;&#xA;&#xD;&#xA;[![RGB strip][1]][1]&#xD;&#xA;&#xD;&#xA;While this gives enough values (256*256*256), looking at the image its not clear what each pixel means (=if I'd pick a random pixel from this image you could not tell approximately the alpha value).&#xD;&#xA;&#xD;&#xA;Does anyone know a good method how to represent &gt;256 values in an RGB texture, where its clear what each pixel means?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aXgNJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8143" PostHistoryTypeId="1" PostId="3850" RevisionGUID="32e1bea6-677d-4034-8456-f94c7efb41df" CreationDate="2016-08-12T23:48:03.667" UserId="2437" Text="How to store &gt; 256 transparency values in textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8144" PostHistoryTypeId="3" PostId="3850" RevisionGUID="32e1bea6-677d-4034-8456-f94c7efb41df" CreationDate="2016-08-12T23:48:03.667" UserId="2437" Text="|texture|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8145" PostHistoryTypeId="5" PostId="3850" RevisionGUID="8216289f-876e-4265-b602-6bff9c6ac096" CreationDate="2016-08-13T00:23:30.097" UserId="2437" Comment="added 34 characters in body" Text="I am making an engine with 2D volumetric transparent objects and need advice how to store transparency data. There are 3 requirements:   &#xD;&#xA;- The transparency textures need to be easily editable with common tools (e.g paint.NET, so .png preferred)       &#xD;&#xA;- Since a pixel value will determine the light transmittance 8 bits are not enough - in this case lights could travel maximum 256 pixels in non fully transparent textures.   &#xD;&#xA;- It should be clear what each pixel means when looking at the texture.    &#xD;&#xA;&#xD;&#xA;I've tried using the HEX values from RGB pixels. For example heres a strip with HEX values from 0 to 0xFFFFFF:&#xD;&#xA;&#xD;&#xA;[![RGB strip][1]][1]&#xD;&#xA;&#xD;&#xA;While this gives enough values (256*256*256), looking at the image its not clear what each pixel means (=if I'd pick a random pixel from this image you could not tell approximately the alpha value).&#xD;&#xA;&#xD;&#xA;Does anyone know a good method how to represent &gt;256 values in an RGB texture, where its clear what each pixel means?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aXgNJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8148" PostHistoryTypeId="2" PostId="3851" RevisionGUID="43d82aaa-80ef-45be-9353-e7d479a9b670" CreationDate="2016-08-13T14:26:14.233" UserId="4908" Text="A normal argb image has 8 bits per channel and therefor 32 bits per pixel, the size of an integer. That's why it's stored in an integer a lot of the times.&#xD;&#xA;&#xD;&#xA;Floats are also 32 bits.&#xD;&#xA;&#xD;&#xA;Something that you can do, is to have a separate image that has only 1 channel, for the transparency. If you make that a float type (or for 16 bit, another type that uses 16 bits instead of 32 bits), then it will take about the same room as an extra normal image.&#xD;&#xA;&#xD;&#xA;After a quick google, I found out that most programs are limited to 8 bit per channel, but there should be programs that have 16 bit per channel.&#xD;&#xA;This gives you at least more precision.&#xD;&#xA;&#xD;&#xA;When loading in the normal 16 bit image (your texture, if you use 16 bits per channel), you could convert the normal rgb part to 8 bits, and load that in and then create a new image that has 1 channel that is 16 or 32 bits, and then store the alpha value in there.&#xD;&#xA;&#xD;&#xA;This way it should be similar to having an extra image, and you do, but instead of 2 textures, you have the transparency in another image.&#xD;&#xA;&#xD;&#xA;What would then also be possible to do, is to store the transparency in a normal rgba image (inside your program as a texture), as you were talking about, and then in the shader, you manipulate the rgba values to restore the transparency value. This way you wouldn't need a floating point image.&#xD;&#xA;&#xD;&#xA;This is just a quick idea. As far as I know, this should work. (This is my first answer here! whoop! whoop!)&#xD;&#xA;&#xD;&#xA;Hope it helps and good luck!&#xD;&#xA;&#xD;&#xA;https://developer.mbed.org/handbook/C-Data-Types&#xD;&#xA;&#xD;&#xA;(^for the data sizes)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8167" PostHistoryTypeId="2" PostId="3856" RevisionGUID="9a929005-93e0-483c-80c0-af749960e2d0" CreationDate="2016-08-14T16:23:25.170" UserId="4843" Text="Using the dot product on the offset vectors provides the answer. There are three distinct cases (when I mention handles, I am refering to Bezier handles such as the ones used in Blender):&#xD;&#xA;&#xD;&#xA; - the angle between the Bezier handles is greater than 90º. The dot product has to be positive&#xD;&#xA; - the angle between the Bezier handles is less than 90º. The dot product has to be negative&#xD;&#xA; - the angle is 90º.&#xD;&#xA;&#xD;&#xA;This last case is trickier. You have to sum the offset vectors, and them sum the handle vectors (which are defined as the vector from the control point to the relevant left or right handle). The dot product of these two vectors has to be positive." ContentLicense="CC BY-SA 3.0" />
  <row Id="8170" PostHistoryTypeId="5" PostId="3846" RevisionGUID="8117af8b-03d9-4473-a070-272b1fe89379" CreationDate="2016-08-15T07:41:09.803" UserId="182" Comment="Emphasis." Text="The fact that a photo is stored in gamma space doesn't have to do with PNG or JPEG, it has to do with the fact that it's a photo.&#xD;&#xA;&#xD;&#xA;The camera detects a 50% intensity but is going to save it as a 187 instead of 127, because that is more efficient to keep the color information that matters to the human eye when you have only 256 different possible values. And so does Photoshop if you tell it so.&#xD;&#xA;&#xD;&#xA;**For normals or displacement maps, you don't have this need so there is no reason to use gamma space for them** (using gamma for them would actually be a mistake, since it would affect how precision is distributed). Thus when you decode a normal texture or a displacement texture, you don't need to apply gamma.&#xD;&#xA;&#xD;&#xA;If the normal map is encoded in a different space though, [as can be the case for a G-Buffer for example][1], then you have to apply the corresponding correction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://aras-p.info/texts/CompactNormalStorage.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8171" PostHistoryTypeId="2" PostId="3857" RevisionGUID="72413a1b-1834-419f-88a1-21841779b858" CreationDate="2016-08-15T17:41:23.913" UserId="38" Text="For a two dimensional spline it is possible to define a left and a right side, or let us call the directions counterclockwise and clockwise side (or maybe port and starboard would be appropriate). The side is easily identified as the cross product of the tangent in direction of point order crossed by the paper plane.&#xD;&#xA;&#xD;&#xA;[![offset side][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Offset side in 2D.&#xD;&#xA;&#xD;&#xA;The higher dimensional cases are more problematic, I will be examining the 3D space only. A free space curve has no inherent good second direction. Mathematicians have defined, what is essentially a hack, that the second direction is in the direction of curvature which has a mathematical definition. The only problem is that curvature is subject to change and can flip direction along the curve. This is not good. &#xD;&#xA;&#xD;&#xA;So how to counter this? Well simplest is if a curve on a surface of a 2D plane or surface. In this case you can simply use the underlying primitives directions as reference and do a 2D case. This has the added benefit of not doing a somewhat random offset direction.&#xD;&#xA;&#xD;&#xA;For the free curve case there are several approaches you can use, they all have the downside of needing to keep some extra data with you. &#xD;&#xA;&#xD;&#xA;One is to calculate the location where the curvature is 0 and &quot;cut&quot; the curve at that point and continue with a flipped curvature direction. In case of a straight line just continue with last good direction. A variation of this is not to use curvature but a user defined vector and use that instead. &#xD;&#xA;&#xD;&#xA;This can also be done numerically by sampling multiple points along and detect the flip by comparing nearby result and not letting it turn more than a certain degree untill you declare a flip (what your doing sound like a variation of this). One other is to propagate a vector along the curve. One way to do this is to specify a vector at each point and let the user flip them if he feels the need. Or interpolate vectors only at certain points on the curve.&#xD;&#xA;&#xD;&#xA;Most applications simply just use the will not do it or bug out option. This has the benefit of being rather sane, as the curvature based bi-normal is a bit erratic to say the least. This way the user has to come up with a way to make the directional control with for example a ruled surface.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\*  Bézier, NURBS or something other like a [Catmul-Rom](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline) spline doesn't matter&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TtQpx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8172" PostHistoryTypeId="2" PostId="3858" RevisionGUID="fd814c77-fbf4-4a55-aa2b-dd6fde518292" CreationDate="2016-08-16T07:16:39.057" UserId="1937" Text="I've been digging a bit into what actually happens at a hardware level on the GPU, and found NVidia's [Life of a triangle][1] which explains the pipeline pretty well, at least for green boxes. One thing I wasn't clear on is what happens with indexed meshes, when the same vertex is used for a bunch of different triangles. Since data is generally not persisted for any longer than necessary in a stream processor, I'm guessing the vertex is simply destroyed after being rasterized, then fetched and run through the vertex shader again whenever it appears in a new triangle. Can anyone confirm this? Also, what happens in line-strip or triangle-strip modes? Does the GPU persist the transformed vertex data somewhere until the 2 or 3 relevant primitives have been rasterized in these cases?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/content/life-triangle-nvidias-logical-pipeline " ContentLicense="CC BY-SA 3.0" />
  <row Id="8173" PostHistoryTypeId="1" PostId="3858" RevisionGUID="fd814c77-fbf4-4a55-aa2b-dd6fde518292" CreationDate="2016-08-16T07:16:39.057" UserId="1937" Text="Are vertices reprocessed per-poly for indexed meshes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8174" PostHistoryTypeId="3" PostId="3858" RevisionGUID="fd814c77-fbf4-4a55-aa2b-dd6fde518292" CreationDate="2016-08-16T07:16:39.057" UserId="1937" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8175" PostHistoryTypeId="2" PostId="3859" RevisionGUID="03b511aa-06f5-48d4-9eec-0a74a09cf01f" CreationDate="2016-08-16T08:20:34.033" UserId="209" Text="The key expression you may be looking for is [&quot;Post Transform Cache&quot;](https://www.opengl.org/wiki/Post_Transform_Cache).&#xD;&#xA;&#xD;&#xA;This is usually effective because of the natural vertex reuse, but reordering your mesh, e.g. with [Hoppe's method](http://hhoppe.com/proj/tvc/) or [Fortsyth's](https://tomforsyth1000.github.io/papers/fast_vert_cache_opt.html) can improve things further." ContentLicense="CC BY-SA 3.0" />
  <row Id="8176" PostHistoryTypeId="2" PostId="3860" RevisionGUID="4b871ca2-7f18-4ee6-b586-0416cfebc2d8" CreationDate="2016-08-16T08:32:50.617" UserId="137" Text="That depends on how far apart the vertexes are reused.&#xD;&#xA;&#xD;&#xA;For example the square `0, 1, 2, 2, 1, 3` will have a short enough interval that the `1` and `2` vertices will be reused. But if there are a hundred vertices between reuses then it's more likely that there will be no reuse.&#xD;&#xA;&#xD;&#xA;But when they are much further apart then the vertex will fall out of the cache and have to be reprocessed by the vertex shader.&#xD;&#xA;&#xD;&#xA;This is why some 3D software have a way to improve vertex locality for indexed meshes by reordering the vertices." ContentLicense="CC BY-SA 3.0" />
  <row Id="8177" PostHistoryTypeId="5" PostId="3859" RevisionGUID="2ba36b7b-bcc8-44a5-8adb-001490d4c8d5" CreationDate="2016-08-16T08:50:36.270" UserId="209" Comment="added 50 characters in body" Text="The key expression you may be looking for is [&quot;Post Transform Cache&quot;](https://www.opengl.org/wiki/Post_Transform_Cache).&#xD;&#xA;&#xD;&#xA;This is usually effective because of the natural vertex reuse, but reordering your mesh, e.g. with [Hoppe's method](http://hhoppe.com/proj/tvc/) (note: the page also lists some more recent work) or [Fortsyth's](https://tomforsyth1000.github.io/papers/fast_vert_cache_opt.html) can improve things further." ContentLicense="CC BY-SA 3.0" />
  <row Id="8178" PostHistoryTypeId="2" PostId="3861" RevisionGUID="93a665fa-c7e7-41d9-879b-45f99cbf1984" CreationDate="2016-08-16T09:30:19.817" UserId="4924" Text="I am trying to write a spaceship simulator. One problem I've hit into is how to best simulate the background of space with its stars. I don't need it to be faithful to the real thing with constellations and everything, but my attempt of uniformly distributing random points on the celestial sphere produced... unnatural-looking starry backgrounds, for reasons I can't put a finger on.&#xD;&#xA;&#xD;&#xA;**Is there a way to &quot;realistically&quot; distribute random &quot;stars&quot; in space?** I'm language agnostic, so feel free to code in the language you're most comfortable with; I'll adjust. :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8179" PostHistoryTypeId="1" PostId="3861" RevisionGUID="93a665fa-c7e7-41d9-879b-45f99cbf1984" CreationDate="2016-08-16T09:30:19.817" UserId="4924" Text="How do I simulate a starfield?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8180" PostHistoryTypeId="3" PostId="3861" RevisionGUID="93a665fa-c7e7-41d9-879b-45f99cbf1984" CreationDate="2016-08-16T09:30:19.817" UserId="4924" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8181" PostHistoryTypeId="5" PostId="3844" RevisionGUID="a9150849-0126-45b0-8b85-c82035ebdf20" CreationDate="2016-08-16T10:36:08.683" UserId="2817" Comment="replaced &quot;light&quot; with &quot;colour&quot;" Text="Actually, if your bump or displacement map is saved with that 0.45 gamma correction, it's wrong. These maps contain geometrical information rather than colour, and as such, should be simply encoded linearly.&#xD;&#xA;&#xD;&#xA;For a related issue and a fix for Adobe Photoshop, see this slide deck: https://docs.google.com/presentation/d/1vS5nAAnXbZ8Pt6-dXxy-xEXDkjfjXTmNnthNGccorl0/edit#slide=id.g14b3e28660_0_8" ContentLicense="CC BY-SA 3.0" />
  <row Id="8182" PostHistoryTypeId="2" PostId="3862" RevisionGUID="771a557d-5fbd-4fff-8209-658078fc237c" CreationDate="2016-08-16T14:07:04.037" UserId="4543" Text="I'm trying to render a randomly generated terrain with vertex buffers and OpenGL. I want to use a shader to color the terrain, but it seemms like my shader isn't used. I have used shaders before when drawing triangles manually on the CPU and didn't have any problems there.&#xD;&#xA;&#xD;&#xA;activate and deactivate is just glUseProgram(m_ShaderProgram) and glUseProgram(0);&#xD;&#xA;&#xD;&#xA;This is my draw method: &#xD;&#xA;&#xD;&#xA;    void Terrain::drawTest() {&#xD;&#xA;	&#xD;&#xA;	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);&#xD;&#xA;&#xD;&#xA;	glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;	glEnableClientState(GL_NORMAL_ARRAY);&#xD;&#xA;&#xD;&#xA;	// setup position &amp; normal pointers&#xD;&#xA;	glVertexPointer(3, GL_FLOAT, sizeof(TerrainVertex), BUFFER_OFFSET(0));&#xD;&#xA;	glNormalPointer(GL_FLOAT, sizeof(TerrainVertex), BUFFER_OFFSET(12));&#xD;&#xA;&#xD;&#xA;	m_ShaderProgram.activate();&#xD;&#xA;	glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));&#xD;&#xA;	m_ShaderProgram.deactivate();&#xD;&#xA;&#xD;&#xA;	glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;	glDisableClientState(GL_NORMAL_ARRAY);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And my shaders look like this:&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    varying vec3 Normal;&#xD;&#xA;    varying vec3 Position;&#xD;&#xA;    varying vec2 Texcoord;&#xD;&#xA;&#xD;&#xA;    void main(void) {&#xD;&#xA;	    Position = (gl_ModelViewMatrix * gl_Vertex).xyz;&#xD;&#xA;	    Normal = gl_NormalMatrix * gl_Normal;&#xD;&#xA;	    Texcoord = gl_MultiTexCoord0.xy;&#xD;&#xA;	    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    varying vec3 Normal;&#xD;&#xA;    varying vec3 Position;&#xD;&#xA;    varying vec2 Texcoord;&#xD;&#xA;   &#xD;&#xA;    void main(void) {&#xD;&#xA;	   gl_FragColor = vec4(1.0,1.0,0,0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result:&#xD;&#xA;[![Terrain][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the fragment shader doesn't seem to do anything and I can't figure out what the problem is.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VzISb.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8183" PostHistoryTypeId="1" PostId="3862" RevisionGUID="771a557d-5fbd-4fff-8209-658078fc237c" CreationDate="2016-08-16T14:07:04.037" UserId="4543" Text="How to use Shaders with vertex &amp; index buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8184" PostHistoryTypeId="3" PostId="3862" RevisionGUID="771a557d-5fbd-4fff-8209-658078fc237c" CreationDate="2016-08-16T14:07:04.037" UserId="4543" Text="|opengl|c++|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8185" PostHistoryTypeId="5" PostId="3859" RevisionGUID="3ebbfef4-bb72-4c3c-9731-11d9d837e032" CreationDate="2016-08-16T15:05:49.967" UserId="209" Comment="oops. Corrected spelling of Tom F's surname" Text="The key expression you may be looking for is [&quot;Post Transform Cache&quot;](https://www.opengl.org/wiki/Post_Transform_Cache).&#xD;&#xA;&#xD;&#xA;This is usually effective because of the natural vertex reuse, but reordering your mesh, e.g. with [Hoppe's method](http://hhoppe.com/proj/tvc/) (note: the page also lists some more recent work) or [Forsyth's](https://tomforsyth1000.github.io/papers/fast_vert_cache_opt.html) can improve things further." ContentLicense="CC BY-SA 3.0" />
  <row Id="8186" PostHistoryTypeId="2" PostId="3863" RevisionGUID="18200ddb-39f6-47da-b4a1-5030050d2ced" CreationDate="2016-08-16T15:14:01.173" UserId="4543" Text="Apparently there was just a problem with the loading of the shader. A bug that crept into the code from an old project..." ContentLicense="CC BY-SA 3.0" />
  <row Id="8187" PostHistoryTypeId="2" PostId="3864" RevisionGUID="d09b5a10-aa73-4b3c-af57-83275b91ae08" CreationDate="2016-08-17T04:24:02.497" UserId="4933" Text="**Intro**&#xD;&#xA;&#xD;&#xA;Maxwell Render has a feature called _multilight_, where one can ray-trace a scene with multiple light sources, and **change the brightness** of the individual light sources _afterwards_.&#xD;&#xA;Luxrender has a similar feature called _light groups_.&#xD;&#xA;&#xD;&#xA;I image that behind the scenes, these renderers keep track of the contributions of the different light sources separately, and then composing a final image (given brightnesses of light sources) just amounts to mixing these per-light contributions with appropriate coefficients. Effectively, instead of keeping track of the color of a ray as a tuple (R,G,B), one keeps track of more numbers (R1, G1, B1, R2, G2, B2, ..., Rk, Gk, Bk) if there are k light sources (let's assume no spectral rendering, just for ease of notation -- it's conceptually identical).&#xD;&#xA;&#xD;&#xA;From a mathematical point of view, the final image is a **linear combination** of the images resulting from the individual light sources.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;Now it seems interesting to have a similar feature that allows **changing the colors of objects** in the scene _after rendering_.&#xD;&#xA;This can be done with an entirely similar technique: suppose that we have two objects whose color we want to be able to change after rendering. The final image is a **polynomial** in the color of these objects, with two variables (one for each object) and of degree n, where n is the maximum number of bounces for a ray.&#xD;&#xA;&#xD;&#xA;Specifically, instead of keeping track of tuples (R,G,B), the integrator would keep track of&#xD;&#xA;expressions of the form (R00,G00,B00) + (R10,G10,B10)x + (R01,G01,B01)y + (R11,G11,B11)xy + (R21,G21,B21)x²y + ..., for a total of k^n terms, where k is the number of colors you want to be able to change, and n the maximum number of bounces.&#xD;&#xA;For modest k and n, this certainly seems tractable. Color calculations become more expensive, as does storing the resulting &quot;polynomial-image&quot;, but all the geometric calculations are identical.&#xD;&#xA;&#xD;&#xA;&gt; Is this feature implemented in any widely available renderers?&#xD;&#xA;&#xD;&#xA;&gt; - If so, which ones?&#xD;&#xA;&#xD;&#xA;&gt; - If not, why not? Is this not something that's useful in practice? Is it not computationally feasible?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Remark**&#xD;&#xA;&#xD;&#xA;I hope I've made myself clear in my explanation. I don't know much about computer graphics (mathematician by training), so my notation may be unusual. More general that just changing the colors of objects, one could change more properties of materials after rendering. For example, the transparency of objects could be changed afterwards (though assuming importance sampling is used by the integrator, this comes at the cost of noise, I guess).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8188" PostHistoryTypeId="1" PostId="3864" RevisionGUID="d09b5a10-aa73-4b3c-af57-83275b91ae08" CreationDate="2016-08-17T04:24:02.497" UserId="4933" Text="Changing colors after raytracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="8189" PostHistoryTypeId="3" PostId="3864" RevisionGUID="d09b5a10-aa73-4b3c-af57-83275b91ae08" CreationDate="2016-08-17T04:24:02.497" UserId="4933" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8190" PostHistoryTypeId="2" PostId="3865" RevisionGUID="c6a02092-4452-4d58-9bbd-c129061e0bcd" CreationDate="2016-08-17T09:54:42.610" UserId="38" Text="What you describe is essentially a deep raster. Most modern renderers implement this in fact it is implemented in several ways. There are even sopecific technical positions that rely on this technology in form of lighting, color grading and compositioning artists&#xD;&#xA;&#xD;&#xA;The first technique is multipass rendering which is basically just this dumping of render data out of the renderer for fast defered rendering.  All rendering engines on the planet can do this, though all do not implement dumping it out of one render, most do however). What you then do is you integrate these dumped buffers in a compositioning app (Nuke, Fusion, maybe even after effects, you can even do this in photoshop) where you can do final tweaks and changes. This is a very old idea and has been used for more than 30 years. It has certain drawbacks bit overall this means you night be able to pull off even calculation changes that would be too costly to do with a re-render. So color of objects&#xD;&#xA;&#xD;&#xA;Many systems also support interactive sessions that cache the computations, in what is essentially a deep raster. This way its possible to recalculate not only color but even the position, decay of individual lights at interactive speeds. The most modern ones of these are frankly quite sophisticated and can also issue the renderer to rerender in background. Animation studios have lots of people working on these to make them better.&#xD;&#xA;&#xD;&#xA;You can even use this trick to change camera position for the second stereo camera without recomputing your scene." ContentLicense="CC BY-SA 3.0" />
  <row Id="8194" PostHistoryTypeId="2" PostId="3867" RevisionGUID="93af117e-11f6-4e4c-85b4-9462a5c52237" CreationDate="2016-08-18T16:46:04.390" UserId="56" Text="Why is it that it's so common to use monte carlo randomized sample locations, instead of uniform sampling?&#xD;&#xA;&#xD;&#xA;I'm assuming that taking randomized samples gives some benefit but I don't know what they could be.&#xD;&#xA;&#xD;&#xA;Is anyone able to explain the advantage of randomized sample locations over uniform sample locations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8195" PostHistoryTypeId="1" PostId="3867" RevisionGUID="93af117e-11f6-4e4c-85b4-9462a5c52237" CreationDate="2016-08-18T16:46:04.390" UserId="56" Text="Why random monte carlo sampling instead of uniform sampling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8196" PostHistoryTypeId="3" PostId="3867" RevisionGUID="93af117e-11f6-4e4c-85b4-9462a5c52237" CreationDate="2016-08-18T16:46:04.390" UserId="56" Text="|sampling|monte-carlo|integral|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8197" PostHistoryTypeId="2" PostId="3868" RevisionGUID="86989858-aa0b-47f4-8dd4-8cd4530fe9e8" CreationDate="2016-08-18T16:50:12.220" UserId="56" Text="The 99 lines of C path tracer [Smallpt][1] renders a 2x2 subpixel grid for each pixel it intends to render and then does a tent filter to combine them.&#xD;&#xA;&#xD;&#xA;There is an interesting presentation explaining the code [here][2], and it mentions the tent filter but doesn't explain why it's there.&#xD;&#xA;&#xD;&#xA;Can anyone explain why a tent filter would be preferable in this case over a box blur (just averaging the samples)?&#xD;&#xA;&#xD;&#xA;Would it be higher quality to go with something better than a tent filter, such as bicubic hermite interpolation?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;  [2]: https://drive.google.com/file/d/0B8g97JkuSSBwUENiWTJXeGtTOHFmSm51UC01YWtCZw/view" ContentLicense="CC BY-SA 3.0" />
  <row Id="8198" PostHistoryTypeId="1" PostId="3868" RevisionGUID="86989858-aa0b-47f4-8dd4-8cd4530fe9e8" CreationDate="2016-08-18T16:50:12.220" UserId="56" Text="Why use a tent filter in path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8199" PostHistoryTypeId="3" PostId="3868" RevisionGUID="86989858-aa0b-47f4-8dd4-8cd4530fe9e8" CreationDate="2016-08-18T16:50:12.220" UserId="56" Text="|pathtracing|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8200" PostHistoryTypeId="2" PostId="3869" RevisionGUID="bb35e743-56dc-478e-9185-fc0cdde62ca4" CreationDate="2016-08-18T22:49:47.863" UserId="4908" Text="I just looked at Wikipedia articles about Bilinear interpolation.&#xD;&#xA;A tent filter is a kind of Bilinear interpolation.&#xD;&#xA;A Bilinear interpolation interpolates on 2 dimensions.&#xD;&#xA;It first linearly interpolates on one dimension and then the other.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When you look at this picture, it first does it on the column and then the row for example.&#xD;&#xA;&#xD;&#xA;The reason why this could be better than averaging colors, is that when one of the points gets closer to the center than another one, it contributes more to the final color.&#xD;&#xA;With averaging the colors, all the points contributes equally, even when one point is closer to the center than another point.&#xD;&#xA;&#xD;&#xA;If all the 4 points are on fixed positions on a equal distance from the center, then you get exactly 25% contribution on all points, that's the same as averaging.&#xD;&#xA;&#xD;&#xA;This means that when you implement anti aliasing by just rendering at 4 times higher resolution, and then down sampling it. The output between the 2 ways should be the same, as far as I understand it.&#xD;&#xA;&#xD;&#xA;So, which filter should you use? Well, it depends on what you want and your situation. If you pick random sub pixel locations for your samples, then it might be better to use a Bilinear interpolation.&#xD;&#xA;If all the points are fixed and you just render out at a higher resolution, then averaging could be useful.&#xD;&#xA;In the end this is all just some sub pixel things that normally you don't or barely notice, so if there is some kind if AA, then it's good enough. But that's just my opinion and probably that of the average viewer of 3D animation or something like that.&#xD;&#xA;&#xD;&#xA;A Bicubic interpolation gives you a smoother look.&#xD;&#xA;Bicubic:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Bilinear:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8I67g.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/iIlKX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HQDup.png&#xD;&#xA;&#xD;&#xA;Which is better? Well, it depends on what you like, and I don't think that there will be a huge difference.&#xD;&#xA;&#xD;&#xA;My sources:&#xD;&#xA;https://en.wikipedia.org/wiki/Reconstruction_filter#Image_processing&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Bilinear_interpolation&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Bicubic_interpolation&#xD;&#xA;&#xD;&#xA;(Images are from Wikipedia and are public domain)&#xD;&#xA;&#xD;&#xA;I hope this helps, I just want to say that I am not a professional on this, I'm just somebody that just likes computer graphics stuff. It could be that I made some mistakes. If so, just say it and I change it!" ContentLicense="CC BY-SA 3.0" />
  <row Id="8204" PostHistoryTypeId="2" PostId="3871" RevisionGUID="aeacfbb3-aa87-4dc3-af83-81d7ebb95d61" CreationDate="2016-08-19T04:33:52.853" UserId="4946" Text="Briefly: &#xD;&#xA;&#xD;&#xA;- Low **albedo** --&gt; darker object&#xD;&#xA;- High **albedo** --&gt; brighter object&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- Low **diffuse** reflection --&gt; mirror-like reflection (aka Specular)&#xD;&#xA;- high **diffuse** reflection --&gt; cotton-like reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="8205" PostHistoryTypeId="2" PostId="3872" RevisionGUID="4a9cbf03-9597-4dc7-a141-d985539c5bbc" CreationDate="2016-08-19T11:33:54.710" UserId="182" Text="Monte Carlo methods rely on the **[law of large numbers][1]**, which states that the average of a random event repeated a large number of times converges toward the expected value. **[Monte Carlo integration][2]** uses that law to evaluate an integral by averaging a large number of random samples.&#xD;&#xA;&#xD;&#xA;Using a uniform distribution would break the algorithm because the law it is based upon wouldn't apply anymore.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Law_of_large_numbers&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Monte_Carlo_integration" ContentLicense="CC BY-SA 3.0" />
  <row Id="8206" PostHistoryTypeId="5" PostId="3872" RevisionGUID="7352851a-b3ef-4103-b479-9d4459d0c469" CreationDate="2016-08-19T11:40:21.620" UserId="182" Comment="added 91 characters in body" Text="Monte Carlo methods rely on the **[law of large numbers][1]**, which states that the average of a random event repeated a large number of times converges toward the expected value (if you flip a coin a gazillion times, on average you will obtain each side half the time). **[Monte Carlo integration][2]** uses that law to evaluate an integral by averaging a large number of random samples.&#xD;&#xA;&#xD;&#xA;Using a uniform distribution would break the algorithm because the law it is based upon wouldn't apply anymore.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Law_of_large_numbers&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Monte_Carlo_integration" ContentLicense="CC BY-SA 3.0" />
  <row Id="8207" PostHistoryTypeId="5" PostId="3863" RevisionGUID="6cc975c8-2762-4dea-a4ef-a552e03340f0" CreationDate="2016-08-19T14:07:21.030" UserId="4543" Comment="added 137 characters in body" Text="Apparently there was just a problem with the loading of the shader. A bug that crept into the code from an old project...&#xD;&#xA;&#xD;&#xA;EDIT: The GLuint of the compiled shader was never saved in the class and only local to the load function. Just a stupid mistake really." ContentLicense="CC BY-SA 3.0" />
  <row Id="8208" PostHistoryTypeId="2" PostId="3873" RevisionGUID="f7a94b32-3d07-4a01-af44-159ac0049f0e" CreationDate="2016-08-19T17:53:15.607" UserId="4948" Text="I am working in 3DS Max with V-Ray 3.4. I have recently been encountering strange artifacts on baked textures.  Surfaces that should be flat smooth objects render with dark stripes or other unusual patterns, usually geometric.  The objects affected appear to be random.  One will bake just fine and another that is an instance of the first has these stripes.  And once an object starts baking like this there is no going back.  The only solution appears to be to remodel it from scratch (and that is not guaranteed to work either).  And this behavior only occurs when baking.  Normal rendering works just fine.&#xD;&#xA;&#xD;&#xA;Things I have tested for and ruled out:&#xD;&#xA;&#xD;&#xA; - Co-Planar surfaces&#xD;&#xA; - bad UVW mapping (Tried automatic and manually unwrapping - no effect)&#xD;&#xA; - bad material&#xD;&#xA; - lighting problems&#xD;&#xA; - bad normals&#xD;&#xA; - and I've tested on multiple machines with the same results&#xD;&#xA;&#xD;&#xA;Attached is an image of what I'm talking about.  The large square surface should be more or less smooth and evenly lit, but instead, there is a strange dark rectangle.  &#xD;&#xA;&#xD;&#xA;Thanks![![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oSFad.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8209" PostHistoryTypeId="1" PostId="3873" RevisionGUID="f7a94b32-3d07-4a01-af44-159ac0049f0e" CreationDate="2016-08-19T17:53:15.607" UserId="4948" Text="Dark stripes on surfaces in vray when rendering to texture (baking)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8210" PostHistoryTypeId="3" PostId="3873" RevisionGUID="f7a94b32-3d07-4a01-af44-159ac0049f0e" CreationDate="2016-08-19T17:53:15.607" UserId="4948" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8211" PostHistoryTypeId="2" PostId="3874" RevisionGUID="e5fc3b76-b375-4913-bd01-0419744d6529" CreationDate="2016-08-19T18:22:55.483" UserId="4829" Text="I would like to limit the amount draw calls to approximate performance. Is there a nominal amount to aim for when working with high performance gaming? &#xD;&#xA;&#xD;&#xA;From my understanding to render an object that contains exceptional amount of vertices, this would require a lot of draw calls. Though, without doing dynamic draw calls, is there another way to limit the amount of draw calls? &#xD;&#xA;&#xD;&#xA;Per example, if the number draw calls is to be 60 for 60 frames per second; this rate is completely arbitrary, am just looking for a basic explanation on how to control this." ContentLicense="CC BY-SA 3.0" />
  <row Id="8212" PostHistoryTypeId="1" PostId="3874" RevisionGUID="e5fc3b76-b375-4913-bd01-0419744d6529" CreationDate="2016-08-19T18:22:55.483" UserId="4829" Text="What is required to limit the amount of draw calls in Unity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8213" PostHistoryTypeId="3" PostId="3874" RevisionGUID="e5fc3b76-b375-4913-bd01-0419744d6529" CreationDate="2016-08-19T18:22:55.483" UserId="4829" Text="|drawing|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8215" PostHistoryTypeId="2" PostId="3875" RevisionGUID="3f8be720-2e97-4501-acc2-ecce4c71cade" CreationDate="2016-08-20T02:08:19.910" UserId="48" Text="The theoretical ideal antialiasing filter for discretely sampled data is a [sinc filter](https://en.wikipedia.org/wiki/Sinc_filter), because it perfectly removes all frequencies higher than the Nyquist frequency, while leaving alone all the lower ones. So, to some extent, we can expect antialiasing filters that more closely resemble the sinc filter to produce better-quality images.&#xD;&#xA;&#xD;&#xA;The tent filter (triangle filter) certainly resembles the central peak of the sinc filter more closely than does the box filter:&#xD;&#xA;&#xD;&#xA;![sinc, triangle, and box filters][1]&#xD;&#xA;&#xD;&#xA;A bicubic filter (e.g. Mitchell-Netravali) could capture the shape of the sinc even more precisely, including its first two negative lobes.&#xD;&#xA;&#xD;&#xA;The reality of filter selection is a bit more subtle than &quot;approximate sinc as well as possible&quot;, since there are different kinds of artifacts that can be generated by &quot;non-ideal&quot; antialiasing filters, such as aliasing, overblurring, and ringing. Also, different filters may be more or less computationally expensive. So it's a game of trying to trade off the different artifacts against each other and against performance. Different scenes/images may favor one choice or another, and it's also partly an aesthetic judgement.&#xD;&#xA;&#xD;&#xA;As for why smallpt uses a tent filter in particular, I would guess for a combination of performance (it's a quick filter to evaluate) and brevity—it can be done in a couple lines of code, while a bicubic filter would take a bunch more code.&#xD;&#xA;&#xD;&#xA;Incidentally, smallpt actually uses a 2x2 subpixel grid and places a tent filter _at each subpixel_, then averages together the results of the four subpixels. So the overall effect is, curiously, that of the sum of four tents, which ends up looking like a pyramid with a flat top:&#xD;&#xA;&#xD;&#xA;![subpixel tent filters][2]&#xD;&#xA;&#xD;&#xA;I'm not sure if this was intentional, or just happened to be the way it worked out. My guess is this results in a somewhat sharper image than if a single tent filter per pixel were used (because of the narrower support), but probably also more visible aliasing.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PVdbP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sU59F.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8217" PostHistoryTypeId="2" PostId="3876" RevisionGUID="e677dd6e-7593-4631-a547-07aa4fe61041" CreationDate="2016-08-20T04:49:46.763" UserId="2707" Text="There's quite a bit of [information][1] about this:&#xD;&#xA;&#xD;&#xA; - Static/dynamic batching: basically combining objects into one super-object&#xD;&#xA; - Atlas textures: combining textures into one large texture than only uses one material&#xD;&#xA; - Switch to a deferred renderer if you are using many lights&#xD;&#xA;&#xD;&#xA;&gt; From my understanding to render an object that contains exceptional amount of vertices, this would require a lot of draw calls.&#xD;&#xA;&#xD;&#xA;The vertex amount doesn't directly determine the number of draw calls. There also isn't really a guide on how many draw calls is too much. The best thing to do is to profile your application and see where your performance problems come from.&#xD;&#xA;&#xD;&#xA;  [1]: http://answers.unity3d.com/questions/14578/whats-the-best-way-to-reduce-draw-calls.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8218" PostHistoryTypeId="2" PostId="3877" RevisionGUID="891b9d23-fdb6-414e-b92b-8ce17043461d" CreationDate="2016-08-20T06:48:31.657" UserId="48" Text="Sample locations with a uniform pattern will create aliasing in the output, whenever there are geometric features of size comparable to or smaller than the sampling grid. That's the reason why &quot;jaggies&quot; exist: because images are made of a uniform square pixel grid, and when you render (for example) an angled line without antialiasing, it crosses rows/columns of pixels at regular intervals, creating a regular pattern of stairstep artifacts in the resulting image.&#xD;&#xA;&#xD;&#xA;Supersampling at a finer uniform grid will improve things, but the image will still have similar artifacts—just less badly. You can see this with MSAA, as in this comparison image from an NVIDIA presentation on temporal antialiasing:&#xD;&#xA;&#xD;&#xA;[![comparison of no AA, uniform-grid MSAA, and temporal AA][1]][1]&#xD;&#xA;&#xD;&#xA;The 8x MSAA image (which is [not quite a grid](https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx#D3D11_MSAAPatterns_8_16) but still has a repeating pattern) still plainly has jaggies in it, although they're antialiased jaggies. Compare to the TXAA result, which both has a higher effective sample count (due to temporal reuse) and uses a Gaussian rather than box filter for accumulating the samples.&#xD;&#xA;&#xD;&#xA;On the other hand, random sampling produces noise instead of aliasing. There is no pattern to the sample locations, so no pattern to the resulting errors. Both aliasing and noise are errors due to not having enough samples to form a clean image, but arguably noise is the less visually-objectionable artifact.&#xD;&#xA;&#xD;&#xA;On the _other_ other hand, perfectly random sampling (in the sense of [i.i.d. random variables](https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables)) tends to exhibit a certain level of clumping. Purely by chance, some areas in the domain will have denser-than-average clumps of samples, and other areas will be lacking in samples; those areas will be, respectively, over-represented and under-represented in the resulting estimate.&#xD;&#xA;&#xD;&#xA;The convergence rate of the Monte Carlo process can often by improved by using things like [stratified sampling](http://cg.informatik.uni-freiburg.de/course_notes/graphics2_04_sampling.pdf#9), [low-discrepancy sequences](https://en.wikipedia.org/wiki/Low-discrepancy_sequence), or [blue noise](http://www.joesfer.com/?p=108). These are all strategies to generate &quot;de-clumped&quot; samples that are spaced out a bit more evenly than i.i.d. samples, but without creating any regular patterns that might lead to aliasing.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nYrym.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8220" PostHistoryTypeId="5" PostId="3873" RevisionGUID="e4641b77-ccd2-48f1-903c-2ae9da84fe86" CreationDate="2016-08-20T12:33:30.577" UserId="231" Comment="Remove &quot;Thanks!&quot; as usual (which was also preventing the image link from working due to the exclamation mark being adjacent)" Text="I am working in 3DS Max with V-Ray 3.4. I have recently been encountering strange artifacts on baked textures.  Surfaces that should be flat smooth objects render with dark stripes or other unusual patterns, usually geometric.  The objects affected appear to be random.  One will bake just fine and another that is an instance of the first has these stripes.  And once an object starts baking like this there is no going back.  The only solution appears to be to remodel it from scratch (and that is not guaranteed to work either).  And this behavior only occurs when baking.  Normal rendering works just fine.&#xD;&#xA;&#xD;&#xA;Things I have tested for and ruled out:&#xD;&#xA;&#xD;&#xA; - Co-Planar surfaces&#xD;&#xA; - bad UVW mapping (Tried automatic and manually unwrapping - no effect)&#xD;&#xA; - bad material&#xD;&#xA; - lighting problems&#xD;&#xA; - bad normals&#xD;&#xA; - and I've tested on multiple machines with the same results&#xD;&#xA;&#xD;&#xA;Below is an image of what I'm talking about.  The large square surface should be more or less smooth and evenly lit, but instead, there is a strange dark rectangle.  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oSFad.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8221" PostHistoryTypeId="4" PostId="3873" RevisionGUID="e4641b77-ccd2-48f1-903c-2ae9da84fe86" CreationDate="2016-08-20T12:33:30.577" UserId="231" Comment="Remove &quot;Thanks!&quot; as usual (which was also preventing the image link from working due to the exclamation mark being adjacent)" Text="Dark stripes on surfaces in V-Ray when rendering to texture (baking)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8224" PostHistoryTypeId="10" PostId="3805" RevisionGUID="6a0ed5a0-3c80-43a6-affd-485655bd3eab" CreationDate="2016-08-20T12:50:53.267" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8226" PostHistoryTypeId="2" PostId="3878" RevisionGUID="6a1b8fb2-f803-4aa6-91ca-01b2d748726c" CreationDate="2016-08-20T14:02:08.247" UserId="4954" Text="Alright so I'm a complete n00b at image processing so forgive me if my question sounds vague. I'll try to supplement it with what I have learnt until now and also a couple of images.&#xD;&#xA;&#xD;&#xA;See the caption in the image below?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WC1qE.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What I'm essentially trying to do, it to remove it and restore the original image in (Python using OpenCV).**&#xD;&#xA;&#xD;&#xA;Now I have a couple of approaches in mind. First one I read about is a technique called *Inpainting*. Now I saw a tutorial on inpaiting [here](http://docs.opencv.org/trunk/df/d3d/tutorial_py_inpainting.html) but this required me to create a separate mask where the non-zero pixels denote the stuff I want gone.&#xD;&#xA;&#xD;&#xA;Now what I noticed is that the caption is not fully opaque. So i was wondering if there is any possible way to restore the original image by first removing the darkened part of the strip. (essentially something very the original image with only the whitened text on it) and then create a mask of the text and then use inpaiting.&#xD;&#xA;&#xD;&#xA;Now I have a couple of questions. &#xD;&#xA;&#xD;&#xA; 1. What technique do I use to remove the darkened part (let the text be now, we can remove it in the second step using inpaiting)&#xD;&#xA; 2. Does this algorithm even make sense. Is there a better approach I should be looking at?&#xD;&#xA;&#xD;&#xA;NOTE: In no way am I looking for any sort of code or specific implementation. I'm just looking for what *techniques* and *procedures* I can study up on so as to get the job done. The rest is on me" ContentLicense="CC BY-SA 3.0" />
  <row Id="8227" PostHistoryTypeId="1" PostId="3878" RevisionGUID="6a1b8fb2-f803-4aa6-91ca-01b2d748726c" CreationDate="2016-08-20T14:02:08.247" UserId="4954" Text="Removing a darkened caption with text on it in an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="8228" PostHistoryTypeId="3" PostId="3878" RevisionGUID="6a1b8fb2-f803-4aa6-91ca-01b2d748726c" CreationDate="2016-08-20T14:02:08.247" UserId="4954" Text="|image-processing|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8229" PostHistoryTypeId="5" PostId="3833" RevisionGUID="5b7183a0-f14b-4e67-92e6-8a7a5eca8a60" CreationDate="2016-08-20T15:10:06.153" UserId="182" Comment="Reworked style and wording for clarity." Text="The rough definition of _&quot;MTP&quot;_ is clear. But the exact one is not. You can refer to http://www.chioka.in/what-is-motion-to-photon-latency or http://xinreality.com/wiki/Motion-to-photon_latency.&#xD;&#xA;&#xD;&#xA;But from different online articles, we get different definitions regarding how the value is measured:&#xD;&#xA;&#xD;&#xA;1. From [Atman Binstock (Oculus) blog][1], we can see:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(time to flip) - T1(Time of PO)`.&lt;br/&gt;&#xD;&#xA;   But, `T2` is just beginning to display the image, not finish displaying.&#xD;&#xA;&#xD;&#xA;2. From [John Carmack (Oculus) blog][2]:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(finish displaying) - T1(Time of PO)`.&#xD;&#xA;&#xD;&#xA;3. From Alex Vlachos (Valve) slides: _Advanced VR Rendering_, GDC 2015:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(finish displaying) - T1(Time of PO)`&#xD;&#xA;&#xD;&#xA;4. From [Qualcomm blog][3] (sorry it is in Chinese):&lt;br/&gt;&#xD;&#xA;  `MTP = T2(half of finish displaying) - T1(Time of PO)`&#xD;&#xA;&#xD;&#xA;I think Qualcomm's explanation is the best. If it is correct, we can relax the rendering time budget. What is your opinion?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.oculus.com/blog/optimizing-vr-graphics-with-late-latching&#xD;&#xA;  [2]: http://www.chioka.in/what-is-motion-to-photon-latency/&#xD;&#xA;  [3]: http://www.qualcomm.cn/news/blog-2016-07-20" ContentLicense="CC BY-SA 3.0" />
  <row Id="8230" PostHistoryTypeId="4" PostId="3833" RevisionGUID="5b7183a0-f14b-4e67-92e6-8a7a5eca8a60" CreationDate="2016-08-20T15:10:06.153" UserId="182" Comment="Reworked style and wording for clarity." Text="What is the definition of &quot;motion to photon&quot; in VR?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8231" PostHistoryTypeId="2" PostId="3879" RevisionGUID="81d402a5-39c5-4728-adde-83ef9fefbeaa" CreationDate="2016-08-20T15:38:39.947" UserId="4956" Text="I'm starting to learn three.js and want to create a chord diagram as possible in d3.js, but from ground up. I've created a scene and have circle segments on xz axes. But I got stuck on the chords. I looked up d3.js code (path+quadratic curve) but need some good example or explanation how to do it in three.js.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What I'd like to do is to have chords with stroke and fill joining my circle segments with different widths at both ends, nicely curved and thinner in the middle (same as d3.js) with a way to set z-index and opacity in the future.&#xD;&#xA;&#xD;&#xA;Some example could be really helpfull, thanks.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7y0zT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8232" PostHistoryTypeId="1" PostId="3879" RevisionGUID="81d402a5-39c5-4728-adde-83ef9fefbeaa" CreationDate="2016-08-20T15:38:39.947" UserId="4956" Text="draw a chord in three.js as in d3.js" ContentLicense="CC BY-SA 3.0" />
  <row Id="8233" PostHistoryTypeId="3" PostId="3879" RevisionGUID="81d402a5-39c5-4728-adde-83ef9fefbeaa" CreationDate="2016-08-20T15:38:39.947" UserId="4956" Text="|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8234" PostHistoryTypeId="2" PostId="3880" RevisionGUID="2b0ce511-39d9-49e6-907b-f9e0ef3c22e9" CreationDate="2016-08-20T16:02:31.440" UserId="4958" Text="I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. &#xD;&#xA;Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume):&#xD;&#xA;[![3d texture aligned with frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3S8F1.jpg&#xD;&#xA;&#xD;&#xA;So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.&#xD;&#xA;&#xD;&#xA;Tried some magic like:&#xD;&#xA;&#xD;&#xA;    vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space&#xD;&#xA;    texcoords.xyz /= texcoords.w; //to NDC&#xD;&#xA;    texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]&#xD;&#xA;&#xD;&#xA;Eventually:&#xD;&#xA;&#xD;&#xA;    vec3 texcoords;&#xD;&#xA;    texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad&#xD;&#xA;    texcoords.y = texcoord0.y;&#xD;&#xA;    texcoords.z = texture(depthTex, texcoord0).r; //depth tex of screen quad scene&#xD;&#xA;&#xD;&#xA;But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8235" PostHistoryTypeId="1" PostId="3880" RevisionGUID="2b0ce511-39d9-49e6-907b-f9e0ef3c22e9" CreationDate="2016-08-20T16:02:31.440" UserId="4958" Text="mapping 3d texture on view frustum (or part of it)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8236" PostHistoryTypeId="3" PostId="3880" RevisionGUID="2b0ce511-39d9-49e6-907b-f9e0ef3c22e9" CreationDate="2016-08-20T16:02:31.440" UserId="4958" Text="|opengl|texture|glsl|volumetric|raymarching|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8237" PostHistoryTypeId="5" PostId="3880" RevisionGUID="ef514c86-4a1a-44bc-9a72-dc3bab24fcb5" CreationDate="2016-08-20T16:11:57.513" UserId="4958" Comment="added 141 characters in body" Text="I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. &#xD;&#xA;Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume):&#xD;&#xA;[![3d texture aligned with frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3S8F1.jpg&#xD;&#xA;&#xD;&#xA;So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.&#xD;&#xA;&#xD;&#xA;Tried some magic like:&#xD;&#xA;&#xD;&#xA;    vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space&#xD;&#xA;    texcoords.xyz /= texcoords.w; //to NDC&#xD;&#xA;    texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]&#xD;&#xA;&#xD;&#xA;Eventually:&#xD;&#xA;&#xD;&#xA;    vec3 texcoords;&#xD;&#xA;    texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad&#xD;&#xA;    texcoords.y = texcoord0.y;&#xD;&#xA;    texcoords.z = texture(depthTex, texcoord0).r; //depth tex of screen quad scene&#xD;&#xA;&#xD;&#xA;But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.&#xD;&#xA;&#xD;&#xA;To check if this works for now its implemented like this: camera aligned in center of volume so rotating it not really matters some much.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8238" PostHistoryTypeId="5" PostId="3880" RevisionGUID="098ad445-6d21-4c61-86cb-b855537344ab" CreationDate="2016-08-20T16:24:14.697" UserId="4958" Comment="added 84 characters in body" Text="I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. &#xD;&#xA;Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume):&#xD;&#xA;[![3d texture aligned with frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3S8F1.jpg&#xD;&#xA;&#xD;&#xA;So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.&#xD;&#xA;&#xD;&#xA;Tried some magic like:&#xD;&#xA;&#xD;&#xA;    vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space&#xD;&#xA;    texcoords.xyz /= texcoords.w; //to NDC&#xD;&#xA;    texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]&#xD;&#xA;&#xD;&#xA;Eventually:&#xD;&#xA;&#xD;&#xA;    vec3 texcoords;&#xD;&#xA;    texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad&#xD;&#xA;    texcoords.y = texcoord0.y;&#xD;&#xA;    texcoords.z = texture(depthTex, texcoord0).r; //depth tex of screen quad scene&#xD;&#xA;&#xD;&#xA;But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.&#xD;&#xA;&#xD;&#xA;To check if this works for now its implemented like this: camera aligned in center of volume so rotating it not really matters some much. So i probably will need to modify injections stage too to get correct cell indexes.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8239" PostHistoryTypeId="5" PostId="3880" RevisionGUID="a6315962-51ba-4b3d-954c-03641afbf382" CreationDate="2016-08-20T16:30:00.803" UserId="4958" Comment="added 84 characters in body" Text="I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. &#xD;&#xA;Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume):&#xD;&#xA;[![3d texture aligned with frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3S8F1.jpg&#xD;&#xA;&#xD;&#xA;So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.&#xD;&#xA;&#xD;&#xA;Tried some magic like:&#xD;&#xA;&#xD;&#xA;    vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space&#xD;&#xA;    texcoords.xyz /= texcoords.w; //to NDC&#xD;&#xA;    texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]&#xD;&#xA;&#xD;&#xA;Eventually:&#xD;&#xA;&#xD;&#xA;    vec3 texcoords;&#xD;&#xA;    texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad&#xD;&#xA;    texcoords.y = texcoord0.y;&#xD;&#xA;    texcoords.z = texture(depthTex, texcoord0).r; //depth tex of screen quad scene&#xD;&#xA;&#xD;&#xA;But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.&#xD;&#xA;&#xD;&#xA;To check if this works for now its implemented like this: camera aligned in center of volume so rotating it not really matters some much. So i probably will need to modify injections stage too to get correct cell indexes which are statically computed like: &#xD;&#xA;&#xD;&#xA;    vec3 index = vec3(gl_GlobalInvocationID); //cell number of texture;&#xD;&#xA;    vec3 pos = camerapos+index*cellSize*textureDimensions;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8240" PostHistoryTypeId="5" PostId="3880" RevisionGUID="87fa7ae5-99e0-4a97-a8f3-1d2683d680e7" CreationDate="2016-08-20T17:00:46.847" UserId="4958" Comment="deleted 18 characters in body" Text="I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. &#xD;&#xA;Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume):&#xD;&#xA;[![3d texture aligned with frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3S8F1.jpg&#xD;&#xA;&#xD;&#xA;So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.&#xD;&#xA;&#xD;&#xA;Tried some magic like:&#xD;&#xA;&#xD;&#xA;    vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space&#xD;&#xA;    texcoords.xyz /= texcoords.w; //to NDC&#xD;&#xA;    texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]&#xD;&#xA;&#xD;&#xA;Eventually:&#xD;&#xA;&#xD;&#xA;    vec3 texcoords;&#xD;&#xA;    texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad&#xD;&#xA;    texcoords.y = texcoord0.y;&#xD;&#xA;    texcoords.z = texture(depthTex, texcoord0).r; //depth tex of screen quad scene&#xD;&#xA;&#xD;&#xA;But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.&#xD;&#xA;&#xD;&#xA;To check if this works for now its implemented like this: camera aligned in center of volume so rotating it not really matters some much. So i probably will need to modify injections stage too to get correct cell indexes which are statically computed like: &#xD;&#xA;&#xD;&#xA;    vec3 index = vec3(gl_GlobalInvocationID); //cell number of texture;&#xD;&#xA;    vec3 pos = camerapos+index*cellSize;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8241" PostHistoryTypeId="5" PostId="3878" RevisionGUID="7d7b4f63-5ad8-49a6-91ac-02c24b3d3979" CreationDate="2016-08-20T17:24:09.783" UserId="4954" Comment="added 1 character in body" Text="Alright so I'm a complete n00b at image processing so forgive me if my question sounds vague. I'll try to supplement it with what I have learnt until now and also a couple of images.&#xD;&#xA;&#xD;&#xA;See the caption in the image below?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WC1qE.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What I'm essentially trying to do, it to remove it and restore the original image in (Python using OpenCV).**&#xD;&#xA;&#xD;&#xA;Now I have a couple of approaches in mind. First one I read about is a technique called *Inpainting*. Now I saw a tutorial on inpaiting [here](http://docs.opencv.org/trunk/df/d3d/tutorial_py_inpainting.html) but this required me to create a separate mask where the non-zero pixels denote the stuff I want gone.&#xD;&#xA;&#xD;&#xA;Now what I noticed is that the caption is not fully opaque. So i was wondering if there is any possible way to restore the original image by first removing the darkened part of the strip. (essentially something very the original image with only the whitened text on it) and then create a mask of the text and then use inpaiting.&#xD;&#xA;&#xD;&#xA;Now I have a couple of questions. &#xD;&#xA;&#xD;&#xA; 1. What technique do I use to remove the darkened part (let the text be now, we can remove it in the second step using inpainting)&#xD;&#xA; 2. Does this algorithm even make sense. Is there a better approach I should be looking at?&#xD;&#xA;&#xD;&#xA;NOTE: In no way am I looking for any sort of code or specific implementation. I'm just looking for what *techniques* and *procedures* I can study up on so as to get the job done. The rest is on me" ContentLicense="CC BY-SA 3.0" />
  <row Id="8242" PostHistoryTypeId="5" PostId="3880" RevisionGUID="82d22c49-27eb-4af3-a50a-5c350f98d97a" CreationDate="2016-08-20T17:31:49.147" UserId="4958" Comment="deleted 18 characters in body" Text="I'm implementing volumetric fog in my OpenGL renderer. First I inject color into 3D texture using compute shader, atomic operations and shadow map visibility check. The information I use to compute cell index and position in world space are uniforms: camera pos, cellsize and texture dimensions. &#xD;&#xA;Next, when volume filled with data is ready, I need to align it with view frustum to raymarch through texture and apply effect as postprocess (deffered stage) and I'm quite stuck with it. I think there are two options (red is texture volume):&#xD;&#xA;[![3d texture aligned with frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3S8F1.jpg&#xD;&#xA;&#xD;&#xA;So, while applying effect I raymarch from camera pos to frag pos (from G-Buffer texture). I dont know if it is correct, but I think I need to somewhat transform frag pos to NDC, scale it to [0,1] and then using this sample from volume.&#xD;&#xA;&#xD;&#xA;Tried some magic like:&#xD;&#xA;&#xD;&#xA;    vec4 texcoords = vpMatrix * vec4(fragPos, 1.0); //to clip space&#xD;&#xA;    texcoords.xyz /= texcoords.w; //to NDC&#xD;&#xA;    texcoords.xyz = texcoords.xyz *0.5 +0.5; //[-1,1] to [0,1]&#xD;&#xA;&#xD;&#xA;Eventually:&#xD;&#xA;&#xD;&#xA;    vec3 texcoords;&#xD;&#xA;    texcoords.x = texcoord0.x; //texcoord0 - texcoords of screen quad&#xD;&#xA;    texcoords.y = texcoord0.y;&#xD;&#xA;    texcoords.z = depth; //depth from vector: worldpos-camerapos&#xD;&#xA;&#xD;&#xA;But its just guessing. In addition I dont know which option from picture is used in such cases (pro game engines) and how to apply only on some length of frustum because its quite big. Will be really grateful for any hint for this.&#xD;&#xA;&#xD;&#xA;To check if this works for now its implemented like this: camera aligned in center of volume so rotating it not really matters some much. So i probably will need to modify injections stage too to get correct cell indexes which are statically computed like: &#xD;&#xA;&#xD;&#xA;    vec3 index = vec3(gl_GlobalInvocationID); //cell number of texture;&#xD;&#xA;    vec3 pos = camerapos+index*cellSize;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8243" PostHistoryTypeId="2" PostId="3881" RevisionGUID="a2a88fa7-95d2-4fdb-bce9-2f4b2e54a967" CreationDate="2016-08-20T17:35:12.873" UserId="4959" Text="I really cannot get my head around on this issue - how does an analogue image is sampled and then stored in a ture-colour frame buffer (e.g. in a camera) and how do you prevent noise when you do so? Read multiple articles on it but I cannot really get it. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8244" PostHistoryTypeId="1" PostId="3881" RevisionGUID="a2a88fa7-95d2-4fdb-bce9-2f4b2e54a967" CreationDate="2016-08-20T17:35:12.873" UserId="4959" Text="How do you sample an analogue image and store it in a true-colour frame buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8245" PostHistoryTypeId="3" PostId="3881" RevisionGUID="a2a88fa7-95d2-4fdb-bce9-2f4b2e54a967" CreationDate="2016-08-20T17:35:12.873" UserId="4959" Text="|image-processing|noise|image|buffers|photometric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8246" PostHistoryTypeId="5" PostId="3879" RevisionGUID="fdbf812f-768b-4e89-b27c-57e2c44cc962" CreationDate="2016-08-20T18:18:12.597" UserId="4956" Comment="added 177 characters in body" Text="I'm starting to learn three.js and want to create a chord diagram as possible in d3.js, but from ground up. I've created a scene and have circle segments on xz axes. But I got stuck on the chords. I looked up d3.js code (path+quadratic curve) but need some good example or explanation how to do it in three.js.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What I'd like to do is to have chords with stroke and fill joining my circle segments with different widths at both ends, nicely curved and thinner in the middle (same as d3.js) with a way to set z-index and opacity in the future.&#xD;&#xA;&#xD;&#xA;Some example could be really helpfull, thanks.&#xD;&#xA;&#xD;&#xA;I want to achieve something like this (only chord could have different width at both ends):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7y0zT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/lDgsf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8247" PostHistoryTypeId="5" PostId="3879" RevisionGUID="71d2ddba-1141-4416-ad1a-5a00c3796690" CreationDate="2016-08-20T19:14:11.827" UserId="4956" Comment="deleted 2 characters in body" Text="I'm starting to learn three.js and want to create a chord diagram as possible in d3.js, but from ground up. I've created a scene and have circle segments on xz axes. But I got stuck on the chords. I looked up d3.js code (path+quadratic curve) but need some good example or explanation how to do it in three.js.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What I'd like to do is to have chords with stroke and fill joining my circle segments with different widths at both ends, nicely curved and thinner in the middle (same as d3.js) with a way to set z-index and opacity in the future.&#xD;&#xA;&#xD;&#xA;Some example could be really helpfull, thanks.&#xD;&#xA;&#xD;&#xA;I want to achieve something like this (only chord could have different width at both ends):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7y0zT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7kxbA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8248" PostHistoryTypeId="2" PostId="3882" RevisionGUID="f0fd9e55-c276-4dfe-81e0-871825c1e05f" CreationDate="2016-08-20T23:23:03.777" UserId="48" Text="Ideally, motion-to-photon latency is exactly what it says. It measures time from when the user physically makes a _motion_ (say, begins to turn their head) to when the _photons_ physically coming out of the display change to reflect that motion.&#xD;&#xA;&#xD;&#xA;With a bit of apparatus, this can be measured directly—for instance by using a high-speed camera aimed at the headset. You give the headset a light bump with your finger (or use some automated device to bump it), and you can see in the high-speed video when the motion occurred and when the image visible on the screen updated to reflect the motion.&#xD;&#xA;&#xD;&#xA;The complication leading to different definitions occurs because many VR headsets have _rolling displays_, where the physical pixels on the display light up progressively, one row at a time, as the image is scanned out from the host PC. So, when you define motion-to-photon latency, you have to say _which_ photons you're talking about. The very first ones to scan out? The very last ones? Somewhere in the middle?&#xD;&#xA;&#xD;&#xA;You can pretty much make whichever definition you want here about what point in the scanout process to use as your reference. There may be an argument for one definition or another based on psychovisual effects (i.e. how much of your visual field must be updated in order for your brain to perceive motion?) but this is beyond my knowledge.&#xD;&#xA;&#xD;&#xA;On the other hand, if a headset has a global display instead of a rolling one, then the pixels are kept dark while being updated and then the whole display is flashed on and off at the end of scanout. In this case it's clear that the appropriate reference point to measure is the beginning of the flash, since all the photons come out at the same time.&#xD;&#xA;&#xD;&#xA;Finally, it's worth noting that latency measurements incorporated into an app or API are approximations. The software can't observe the motion nor the photons directly, so instead we must use software-visible proxy events.&#xD;&#xA;&#xD;&#xA;* The app querying for the latest head pose is a proxy for user motion, but note that this discards any latency in the sensors, USB driver, sensor fusion processing, and time the data spent sitting around in a buffer waiting for the app to query it.&#xD;&#xA;* The GPU flipping its display buffers is a proxy for photons beginning to come out, but this discards any latency added in the scanout and display process.&#xD;&#xA;&#xD;&#xA;So, ideally an app-measured latency figure should include some corrections to at least estimate the above factors. Or accept that you're not really measuring the full motion-to-photon latency, but just the app-query-to-flip latency or some such." ContentLicense="CC BY-SA 3.0" />
  <row Id="8249" PostHistoryTypeId="2" PostId="3883" RevisionGUID="e7de14c5-b176-494f-9896-4a38d4fdff33" CreationDate="2016-08-21T04:51:59.777" UserId="48" Text="In techniques I've seen that use a frustum-aligned voxel grid (so-called &quot;froxels&quot;), it looks like option 2 in your diagram. The voxels are cuboids in post-projective screen space, so when transformed back to world space they look like mini-frusta, automatically expanding as they get farther from the camera.&#xD;&#xA;&#xD;&#xA;Marching along eye rays is then very easy: you just step along the grid's Z axis. Summing optical density or in-scattered light along an eye ray is just a matter of iterating over the Z dimension of the texture. (Or you could try to apply methods like [parallel prefix sum](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html) as well, but it may not be worthwhile, depending on the texture size.)&#xD;&#xA;&#xD;&#xA;If you're rendering some geometry and you want to know which voxel it's in, you don't have to do any matrix transformations. Just use [`gl_FragCoord​`](http://docs.gl/sl4/gl_FragCoord), which represents the screen-space position (including depth) of the current fragment. It comes in window units (i.e. pixels) so you'll have to remap it to [0,1] for texture sampling, or to voxel units if you're doing an image store.&#xD;&#xA;&#xD;&#xA;Otherwise, for mapping world-space positions into the voxel grid, use the usual sequence of transformations. It looks to me like you got it right in your code snippet, assuming `fragPos` is in world space. For getting from the voxel grid back to world space, you'll need to invert that sequence of transformations." ContentLicense="CC BY-SA 3.0" />
  <row Id="8250" PostHistoryTypeId="2" PostId="3884" RevisionGUID="44de8f27-1f11-42b5-9fb8-b9161d47730b" CreationDate="2016-08-21T07:47:22.740" UserId="4962" Text="As tutor’s for this years programming languages course during our Computer Science studies we’re preparing for the students final project which is the implementation of a ray tracer. We’re implementing one on our own.&#xD;&#xA;&#xD;&#xA;I’m having trouble understanding how the [phong reflection model](https://en.m.wikipedia.org/wiki/Phong_reflection_model) and reflection/refraction ([Reflections and Refractions in Ray Tracing](http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf), Bram de Greve, 2006) can be used in conjunction.&#xD;&#xA;&#xD;&#xA;Our materials currently have these properties:&#xD;&#xA;&#xD;&#xA;- ka, kd, ks – ambient, diffuse and specular terms defined as RGB colors&#xD;&#xA;- shininess – Controlling specular highlights (0 ≤ shininess)&#xD;&#xA;- reflectivity – Controls degree of reflectivity (0 ≤ shininess ≤ 1, 0 means not reflective)&#xD;&#xA;- refractive index – Defines the refractive index of the material (0 ≤ refractive index)&#xD;&#xA;&#xD;&#xA;How I understand it, ray tracing as per phong reflection model with reflection and refraction works roughly like this:&#xD;&#xA;&#xD;&#xA;1. The material is (semi)reflective and (semi)transparent (is this a word). In this case reflectivity and transmittance can be calculated with Fresnel equations. However then the reflectivity as specified in the material is ignored. The final color is `reflectivity * trace(reflected_ray, depth + 1) + transmittance * trace(refracted_ray, depth + 1)`.&#xD;&#xA;2. The material is (semi)reflective but not transparent. The reflective component is determined by further ray tracing. The other component is calculated via the equation from the Phong reflection model. Our ray tracer currently adds both components as in `(1 - reflectivity) * color + reflectivity * trace(reflected_ray, depth + 1)` where `color` is determined by the Phong equation.&#xD;&#xA;3. The material is not reflective and not transparent. The Phong equation is used solely.&#xD;&#xA;&#xD;&#xA;How do I know whether a material is (semi)transparent? Do I add a boolean property which I use to determine whether I’m in case 1 or 2?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8251" PostHistoryTypeId="1" PostId="3884" RevisionGUID="44de8f27-1f11-42b5-9fb8-b9161d47730b" CreationDate="2016-08-21T07:47:22.740" UserId="4962" Text="Controlling reflection and refraction with material properties in ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="8252" PostHistoryTypeId="3" PostId="3884" RevisionGUID="44de8f27-1f11-42b5-9fb8-b9161d47730b" CreationDate="2016-08-21T07:47:22.740" UserId="4962" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8253" PostHistoryTypeId="2" PostId="3885" RevisionGUID="c9bb260a-a776-4ff2-ba35-4548117125d1" CreationDate="2016-08-21T08:57:04.567" UserId="4963" Text="I'm passing my vertex shader a bunch of vertices and color data. I would like to first render the triangles and then render a point at each vertex. The triangles render fine, but I can't think of a way to render the triangles and the points without making and calling a whole new method for rendering points, which I guess I could do, but I'd like to know if there is some shader magic that accomplish it for me.&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;This is my vs:&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;&#xD;&#xA;    gl_Position = projection * ftransform();&#xD;&#xA;    gl_PointSize = 1.0;&#xD;&#xA;    gl_FrontColor = gl_Color;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is my fs:&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;&#xD;&#xA;    #define point_color vec3(1,1,1)&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;&#xD;&#xA;    vec4 color = gl_Color;&#xD;&#xA;    gl_FragColor = vec4(color);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is the code behind it. I'm using lwjgl.&#xD;&#xA;&#xD;&#xA;    public void render() {&#xD;&#xA;&#xD;&#xA;        glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;        glEnableClientState(GL_COLOR_ARRAY);&#xD;&#xA;        glEnable(GL_PROGRAM_POINT_SIZE);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO_id);&#xD;&#xA;        glVertexPointer(3, GL_FLOAT, 0, 0);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, c_id);&#xD;&#xA;        glColorPointer(4, GL_FLOAT, 0, 0);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_id);&#xD;&#xA;        glDrawElements(GL_TRIANGLES, draw_count, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;        glDrawArrays(GL_POINTS, 0, draw_count_v);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;        glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;        glDisableClientState(GL_COLOR_ARRAY);&#xD;&#xA;        glDisable(GL_PROGRAM_POINT_SIZE);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8254" PostHistoryTypeId="1" PostId="3885" RevisionGUID="c9bb260a-a776-4ff2-ba35-4548117125d1" CreationDate="2016-08-21T08:57:04.567" UserId="4963" Text="Can I use the same vertices to render multiple things?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8255" PostHistoryTypeId="3" PostId="3885" RevisionGUID="c9bb260a-a776-4ff2-ba35-4548117125d1" CreationDate="2016-08-21T08:57:04.567" UserId="4963" Text="|opengl|rendering|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8256" PostHistoryTypeId="5" PostId="3879" RevisionGUID="5babb306-8bca-4caa-ada0-bec0b0b427cd" CreationDate="2016-08-21T09:38:08.700" UserId="4956" Comment="deleted 53 characters in body" Text="I'm starting to learn three.js and want to create a chord diagram as possible in d3.js, but from ground up. I've created a scene and have circle segments on xz axes. But I got stuck on the chords. I looked up d3.js code (path+quadratic curve) but need some good example or explanation how to do it in three.js.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What I'd like to do is to have chords with stroke and fill joining my circle segments with different widths at both ends, nicely curved and thinner in the middle (same as d3.js) with a way to set z-index and opacity in the future.&#xD;&#xA;&#xD;&#xA;Some example could be really helpfull, thanks.&#xD;&#xA;&#xD;&#xA;I want to achieve something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7y0zT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7kxbA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8257" PostHistoryTypeId="2" PostId="3886" RevisionGUID="1d7d9ff1-ae8a-4d72-8e4f-5af9080fe03a" CreationDate="2016-08-21T09:57:34.137" UserId="4958" Text="If your intention is to render some textured or colored triangles and points colored diferently at the same time at vertex postions with one draw call:&#xD;&#xA;&#xD;&#xA;    glDrawElements(GL_TRIANGLES, draw_count, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;In order to access vertex data in vertex shader, you can create vertex array object which references to vertex buffer object with data you provided (vertices) for example at index 0.&#xD;&#xA;&#xD;&#xA;then in vertex shader you have:&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vPosition; //positions for each vertex&#xD;&#xA;&#xD;&#xA;You might then do something like that (vertex shader):&#xD;&#xA;&#xD;&#xA;    flat out vec3 fpos; //not interpolated vertices&#xD;&#xA;    out vec3 pos; //interpolated vertices (for default)&#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;      pos = vPosition;&#xD;&#xA;      fpos = vPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And then in fragment shader:&#xD;&#xA;&#xD;&#xA;    if(length(fpos-pos)&lt;threshold) //small threshold&#xD;&#xA;     fragColor = pointColor;&#xD;&#xA;    else&#xD;&#xA;     fragColor = triangleColor;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8258" PostHistoryTypeId="2" PostId="3887" RevisionGUID="2dc07b0c-4a1a-4d95-9836-4ae220836bf2" CreationDate="2016-08-21T15:22:59.740" UserId="4966" Text="I'm writing my implementation of ray tracer and I've got result which you can see at this image.&#xD;&#xA;&#xD;&#xA;![img](https://i.stack.imgur.com/tFCEf.png)&#xD;&#xA;So you can see that some dark parts are overlapping. And I have them even in the part where it should be bright in my opinion. There are two lights one from above and the second one from right-bottom corner.&#xD;&#xA;&#xD;&#xA;And I have two questions. Is it right? I really tried to google some references but failed. I'm not still sure that results in my imagination are correct ones.&#xD;&#xA;&#xD;&#xA;And the second one where does it come from?&#xD;&#xA;&#xD;&#xA;I use usual lambertian shading model and have something like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = (0, 0, 0)&#xD;&#xA;    normal = get normal of sphere in point of intersection;&#xD;&#xA;    normal = unit vector of normal;&#xD;&#xA;    for each light from light_set {&#xD;&#xA;        light = unit vector of light;&#xD;&#xA;        pixel = pixel + diffuseColor * max(0, scalar multiplication of light and normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm really struggled to find out the reason where this strange thing is coming from. But couldn't find it." ContentLicense="CC BY-SA 3.0" />
  <row Id="8259" PostHistoryTypeId="1" PostId="3887" RevisionGUID="2dc07b0c-4a1a-4d95-9836-4ae220836bf2" CreationDate="2016-08-21T15:22:59.740" UserId="4966" Text="Ray tracing scene with 2 lights and sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="8260" PostHistoryTypeId="3" PostId="3887" RevisionGUID="2dc07b0c-4a1a-4d95-9836-4ae220836bf2" CreationDate="2016-08-21T15:22:59.740" UserId="4966" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8264" PostHistoryTypeId="2" PostId="3889" RevisionGUID="764de593-7a4d-4778-92f0-34bbe26cd9d7" CreationDate="2016-08-21T17:30:08.733" UserId="4948" Text="Solved.  The issue was with V-Ray's global ambient occlusion on the GI tab.  Once that was shut off everything renders fine.  " ContentLicense="CC BY-SA 3.0" />
  <row Id="8266" PostHistoryTypeId="2" PostId="3890" RevisionGUID="d9b1b2c6-b663-4cce-899c-094ba3816c66" CreationDate="2016-08-21T22:03:49.733" UserId="3377" Text="I would like to display arbitrary 3d meshes with black edges (black outline, black ridges, etc.). Thereby I have created two different textures: One color texture and one anti-aliased edge texture.&#xD;&#xA;&#xD;&#xA;Here is an example of the color texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And the the corresponding edge texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I'd like to merge both textures. The edge texture has a white background with black/grey edges. I used fxaa, therefore some pixels are grey.&#xD;&#xA;&#xD;&#xA;My question: How can I combine (blend) both textures correctly? And do I have to use fxaa for the color texture, too?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5sY4w.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/s2d1P.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8267" PostHistoryTypeId="1" PostId="3890" RevisionGUID="d9b1b2c6-b663-4cce-899c-094ba3816c66" CreationDate="2016-08-21T22:03:49.733" UserId="3377" Text="GLSL - Merge two textures" ContentLicense="CC BY-SA 3.0" />
  <row Id="8268" PostHistoryTypeId="3" PostId="3890" RevisionGUID="d9b1b2c6-b663-4cce-899c-094ba3816c66" CreationDate="2016-08-21T22:03:49.733" UserId="3377" Text="|opengl|glsl|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8269" PostHistoryTypeId="5" PostId="3890" RevisionGUID="11cd12bb-f012-427d-93b8-ae83d5a449de" CreationDate="2016-08-21T22:17:29.687" UserId="3377" Comment="added 2 characters in body" Text="I would like to display arbitrary 3d meshes with black edges (black outline, black ridges, etc.). Thereby I have created two different textures: One color texture and one anti-aliased edge texture.&#xD;&#xA;&#xD;&#xA;Here is an example of the color texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And the the corresponding edge texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I'd like to merge both textures. The edge texture has a white background with black/grey edges. I used fxaa, therefore some pixels are grey.&#xD;&#xA;&#xD;&#xA;My question: How can I combine (blend) both textures correctly? And do I have to apply fxaa for the color texture, too?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5sY4w.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/s2d1P.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8270" PostHistoryTypeId="5" PostId="3890" RevisionGUID="29849ac5-8a5f-4515-bd8a-413cdf898683" CreationDate="2016-08-21T23:24:12.990" UserId="3377" Comment="added 3229 characters in body" Text="I would like to display arbitrary 3d meshes with black edges (black outline, black ridges, etc.). Thereby I have created two different textures: One color texture and one anti-aliased edge texture.&#xD;&#xA;&#xD;&#xA;Here is an example of the color texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And the the corresponding edge texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I'd like to merge both textures. The edge texture has a white background with black/grey edges. I used fxaa, therefore some pixels are grey.&#xD;&#xA;&#xD;&#xA;My question: How can I combine (blend) both textures correctly? And do I have to apply fxaa for the color texture, too?&#xD;&#xA;&#xD;&#xA;EDIT: For completeness, here's the fxaa-shader code:&#xD;&#xA;&#xD;&#xA;        #version 330 core&#xD;&#xA;&#xD;&#xA;    in vec2 texPos;&#xD;&#xA;    out vec4 color;&#xD;&#xA;    uniform sampler2D colorTexture;&#xD;&#xA;    uniform float rt_w;&#xD;&#xA;    uniform float rt_h;&#xD;&#xA;&#xD;&#xA;    vec4 PostFX(sampler2D tex);&#xD;&#xA;    vec3 FxaaPixelShader(sampler2D tex, vec2 rcpFrame);  &#xD;&#xA;      &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        color = PostFX(colorTexture);&#xD;&#xA;        //color = texelFetch(colorTexture, ivec2(gl_FragCoord), 0 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec4 PostFX(sampler2D tex)&#xD;&#xA;    {&#xD;&#xA;      vec4 c = vec4(0.0);&#xD;&#xA;      vec2 rcpFrame = vec2(1.0/rt_w, 1.0/rt_h);&#xD;&#xA;      c.rgb = FxaaPixelShader(tex, rcpFrame);&#xD;&#xA;      c.a = 1.0;&#xD;&#xA;      return c;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec3 FxaaPixelShader( &#xD;&#xA;      sampler2D tex, // Input texture.&#xD;&#xA;      vec2 rcpFrame) // Constant {1.0/frameWidth, 1.0/frameHeight}.&#xD;&#xA;    {   &#xD;&#xA;    /*---------------------------------------------------------*/&#xD;&#xA;        #define FXAA_REDUCE_MIN   (1.0/128.0)&#xD;&#xA;        #define FXAA_REDUCE_MUL   (1.0/8.0)&#xD;&#xA;        #define FXAA_SPAN_MAX     8.0&#xD;&#xA;    /*---------------------------------------------------------*/&#xD;&#xA;        vec3 rgbNW = texture(tex, vec2(texPos) + (vec2(-1,-1) * rcpFrame.xy)).xyz;&#xD;&#xA;        vec3 rgbNE = texture(tex, vec2(texPos) + (vec2(1,-1) * rcpFrame.xy)).xyz;&#xD;&#xA;        vec3 rgbSW = texture(tex, vec2(texPos)+ (vec2(-1,1) * rcpFrame.xy)).xyz;&#xD;&#xA;        vec3 rgbSE = texture(tex, vec2(texPos) + (vec2(1,1) * rcpFrame.xy)).xyz;&#xD;&#xA;        vec3 rgbM  = texture(tex, vec2(texPos)).xyz;&#xD;&#xA;    /*---------------------------------------------------------*/&#xD;&#xA;        vec3 luma = vec3(0.299, 0.587, 0.114);&#xD;&#xA;        float lumaNW = dot(rgbNW, luma);&#xD;&#xA;        float lumaNE = dot(rgbNE, luma);&#xD;&#xA;        float lumaSW = dot(rgbSW, luma);&#xD;&#xA;        float lumaSE = dot(rgbSE, luma);&#xD;&#xA;        float lumaM  = dot(rgbM,  luma);&#xD;&#xA;    /*---------------------------------------------------------*/&#xD;&#xA;        float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));&#xD;&#xA;        float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));&#xD;&#xA;    /*---------------------------------------------------------*/&#xD;&#xA;        vec2 dir; &#xD;&#xA;        dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));&#xD;&#xA;        dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));&#xD;&#xA;    /*---------------------------------------------------------*/&#xD;&#xA;        float dirReduce = max(&#xD;&#xA;            (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),&#xD;&#xA;            FXAA_REDUCE_MIN);&#xD;&#xA;        float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);&#xD;&#xA;        dir = min(vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX), &#xD;&#xA;              max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), &#xD;&#xA;              dir * rcpDirMin)) * rcpFrame.xy;&#xD;&#xA;    /*--------------------------------------------------------*/&#xD;&#xA;        vec3 rgbA = (1.0/2.0) * (&#xD;&#xA;            texture(tex, texPos.xy + dir * (1.0/3.0 - 0.5)).xyz +&#xD;&#xA;            texture(tex, texPos.xy + dir * (2.0/3.0 - 0.5)).xyz);&#xD;&#xA;        vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (&#xD;&#xA;            texture(tex, texPos.xy + dir * (0.0/3.0 - 0.5)).xyz +&#xD;&#xA;            texture(tex, texPos.xy + dir * (3.0/3.0 - 0.5)).xyz);&#xD;&#xA;        float lumaB = dot(rgbB, luma);&#xD;&#xA;        if((lumaB &lt; lumaMin) || (lumaB &gt; lumaMax)) return rgbA;&#xD;&#xA;        return rgbB; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5sY4w.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/s2d1P.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8271" PostHistoryTypeId="2" PostId="3891" RevisionGUID="e5892838-2fcd-4436-bad7-24cc6af4eb88" CreationDate="2016-08-22T00:47:43.987" UserId="4503" Text="Do current WebGL capabilities allow to use Clustered Lighting? If not what is it missing to allow that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8272" PostHistoryTypeId="1" PostId="3891" RevisionGUID="e5892838-2fcd-4436-bad7-24cc6af4eb88" CreationDate="2016-08-22T00:47:43.987" UserId="4503" Text="Can I Implement Clustered Lightin with WebGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8273" PostHistoryTypeId="3" PostId="3891" RevisionGUID="e5892838-2fcd-4436-bad7-24cc6af4eb88" CreationDate="2016-08-22T00:47:43.987" UserId="4503" Text="|rendering|lighting|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8274" PostHistoryTypeId="2" PostId="3892" RevisionGUID="31699060-9847-4dfb-8320-3e37774eb3e1" CreationDate="2016-08-22T02:30:35.690" UserId="3073" Text="I think what your describing is what happens when you mix colours in gamma space. You should be using linear colour space when mixing.&#xD;&#xA;&#xD;&#xA;When reading colours of lights, convert them from gamma-&gt;linear using the inverse gamma function.&#xD;&#xA;&#xD;&#xA;    colourLin = pow(colourLight, 2.2);&#xD;&#xA;    ... do lambert calculation here and accumulate in 'colour' variable ..&#xD;&#xA;&#xD;&#xA;    // On output (linear-&gt;gamma conversion)&#xD;&#xA;    gl_FragColor = pow(colour, 1.0/2.2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There is an in depth article in GPU gems on this topic (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8275" PostHistoryTypeId="5" PostId="3892" RevisionGUID="924357e2-9d30-4877-8886-51d92e45b85e" CreationDate="2016-08-22T03:02:40.890" UserId="3073" Comment="mention material colour + spelling fix" Text="I think what you're describing is what happens when you mix colours in gamma space. You should be using linear colour space when mixing.&#xD;&#xA;&#xD;&#xA;When reading colours of lights and materials, convert them from gamma-&gt;linear using the inverse gamma function.&#xD;&#xA;&#xD;&#xA;    colourLin = pow(colourLight, 2.2);&#xD;&#xA;    ... do lambert calculation here and accumulate in 'colour' variable ..&#xD;&#xA;&#xD;&#xA;    // On output (linear-&gt;gamma conversion)&#xD;&#xA;    gl_FragColor = pow(colour, 1.0/2.2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There is an in depth article in GPU gems on this topic (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8276" PostHistoryTypeId="5" PostId="3887" RevisionGUID="c88d3289-2b7c-4e06-be43-61e90ad617f3" CreationDate="2016-08-22T04:24:36.603" UserId="4966" Comment="Added some real code as requested from commentary." Text="I'm writing my implementation of ray tracer and I've got result which you can see at this image.&#xD;&#xA;&#xD;&#xA;![img](https://i.stack.imgur.com/tFCEf.png)&#xD;&#xA;So you can see that some dark parts are overlapping. And I have them even in the part where it should be bright in my opinion. There are two lights one from above and the second one from right-bottom corner.&#xD;&#xA;&#xD;&#xA;And I have two questions. Is it right? I really tried to google some references but failed. I'm not still sure that results in my imagination are correct ones.&#xD;&#xA;&#xD;&#xA;And the second one where does it come from?&#xD;&#xA;&#xD;&#xA;I use usual lambertian shading model and have something like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = (0, 0, 0)&#xD;&#xA;    normal = get normal of sphere in point of intersection;&#xD;&#xA;    normal = unit vector of normal;&#xD;&#xA;    for each light from light_set {&#xD;&#xA;        light = unit vector of light;&#xD;&#xA;        pixel = pixel + diffuseColor * max(0, scalar multiplication of light and normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm really struggled to find out the reason where this strange thing is coming from. But couldn't find it.&#xD;&#xA;&#xD;&#xA;UPD0: added some of my real code. The part which is described here is next:&#xD;&#xA;&#xD;&#xA;    Material mat = surfaces[closestSurfase]-&gt;getMaterial();&#xD;&#xA;    Color pixel = Color(0, 0, 0);&#xD;&#xA;    Vector3f normal = surfaces[closestSurfase]-&gt;getNormal(point).getUnitVector();&#xD;&#xA;    Vector3f view = -ray.getDirection().getUnitVector();&#xD;&#xA;    for (size_t i = 0; i &lt; lights.size(); ++i) {&#xD;&#xA;        Vector3f normal_light = lights[i]-&gt;getDirection().getUnitVector();&#xD;&#xA;        Vector3f specVect = (normal_light + view).getUnitVector();&#xD;&#xA;        float intenst = lights[i]-&gt;getIntensity();&#xD;&#xA;        pixel = pixel + mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;        }&#xD;&#xA;    result-&gt;setPixel(x, y, pixel);&#xD;&#xA;&#xD;&#xA;Or you can find more here: https://github.com/minebv/ray_tracer/tree/lambertian_shading_fix/src&#xD;&#xA;&#xD;&#xA;Described above is from Camera's method getRender." ContentLicense="CC BY-SA 3.0" />
  <row Id="8277" PostHistoryTypeId="5" PostId="3887" RevisionGUID="9f9ec07e-2723-45c6-afd0-080ada818a28" CreationDate="2016-08-22T04:52:40.820" UserId="4966" Comment="Added more information about question and some investigations." Text="I'm writing my implementation of ray tracer and I've got result which you can see at this image.&#xD;&#xA;&#xD;&#xA;![img](https://i.stack.imgur.com/tFCEf.png)&#xD;&#xA;So you can see that some dark parts are overlapping. And I have them even in the part where it should be bright in my opinion. There are two lights one from above and the second one from right-bottom corner.&#xD;&#xA;&#xD;&#xA;And I have two questions. Is it right? I really tried to google some references but failed. I'm not still sure that results in my imagination are correct ones.&#xD;&#xA;&#xD;&#xA;And the second one where does it come from?&#xD;&#xA;&#xD;&#xA;I use usual lambertian shading model and have something like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = (0, 0, 0)&#xD;&#xA;    normal = get normal of sphere in point of intersection;&#xD;&#xA;    normal = unit vector of normal;&#xD;&#xA;    for each light from light_set {&#xD;&#xA;        light = unit vector of light;&#xD;&#xA;        pixel = pixel + diffuseColor * max(0, scalar multiplication of light and normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm really struggled to find out the reason where this strange thing is coming from. But couldn't find it.&#xD;&#xA;&#xD;&#xA;UPD0: added some of my real code. The part which is described here is next:&#xD;&#xA;&#xD;&#xA;    Material mat = surfaces[closestSurfase]-&gt;getMaterial();&#xD;&#xA;    Color pixel = Color(0, 0, 0);&#xD;&#xA;    Vector3f normal = surfaces[closestSurfase]-&gt;getNormal(point).getUnitVector();&#xD;&#xA;    Vector3f view = -ray.getDirection().getUnitVector();&#xD;&#xA;    for (size_t i = 0; i &lt; lights.size(); ++i) {&#xD;&#xA;        Vector3f normal_light = lights[i]-&gt;getDirection().getUnitVector();&#xD;&#xA;        Vector3f specVect = (normal_light + view).getUnitVector();&#xD;&#xA;        float intenst = lights[i]-&gt;getIntensity();&#xD;&#xA;        pixel = pixel + mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;        }&#xD;&#xA;    result-&gt;setPixel(x, y, pixel);&#xD;&#xA;&#xD;&#xA;Or you can find more here: https://github.com/minebv/ray_tracer/tree/lambertian_shading_fix/src&#xD;&#xA;&#xD;&#xA;Described above is from Camera's method getRender.&#xD;&#xA;&#xD;&#xA;UPD1: It looks like the problem in the mixing colors in gamma space instead linear one, as answered @PaulHK .&#xD;&#xA;&#xD;&#xA;But I've still some kind of problem. Here you can see 2 renders.&#xD;&#xA;![img1](https://i.stack.imgur.com/HNclL.png)&#xD;&#xA;At the left one I make all work after transformation all colors into linear space, I mean it's like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = pixel + mat.getDiffuse().toLinear() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;&#xD;&#xA;At the right one I make transformation after multiplying:&#xD;&#xA;&#xD;&#xA;    pixel = pixel + (mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst).toLinear();&#xD;&#xA;&#xD;&#xA;And I didn't forget to make pixel into gamma space again after all job.&#xD;&#xA;&#xD;&#xA;As for me, the right one is more correct. But then there is a question: why should I make multiplication on angle into gamma space? Or is it my incorrect way to think about what is right?&#xD;&#xA;&#xD;&#xA;Thank you for your answers." ContentLicense="CC BY-SA 3.0" />
  <row Id="8278" PostHistoryTypeId="5" PostId="3891" RevisionGUID="87195bf1-fcaa-42be-a32d-311193fe3cf9" CreationDate="2016-08-22T09:33:33.363" UserId="4503" Comment="added 329 characters in body" Text="Do current WebGL capabilities allow to use Clustered Lighting? If not what is it missing to allow that? Basically WebGL uses GLES 2, so is that possible with GLES 2?&#xD;&#xA;&#xD;&#xA;I want to implement this one:&#xD;&#xA;&#xD;&#xA; [Clustered Shading][1]&#xD;&#xA;&#xD;&#xA;And use as fallback this one:&#xD;&#xA;&#xD;&#xA;[Alternative to Clustered shading][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cse.chalmers.se/~uffe/clustered_shading_preprint.pdf&#xD;&#xA;  [2]: https://worldoffries.wordpress.com/2015/02/19/simple-alternative-to-clustered-shading-for-thousands-of-lights/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8279" PostHistoryTypeId="5" PostId="3887" RevisionGUID="8a5c9992-3ea8-4034-89fc-a3d13257536c" CreationDate="2016-08-22T09:54:12.783" UserId="4966" Comment="Solution found." Text="I'm writing my implementation of ray tracer and I've got result which you can see at this image.&#xD;&#xA;&#xD;&#xA;![img](https://i.stack.imgur.com/tFCEf.png)&#xD;&#xA;So you can see that some dark parts are overlapping. And I have them even in the part where it should be bright in my opinion. There are two lights one from above and the second one from right-bottom corner.&#xD;&#xA;&#xD;&#xA;And I have two questions. Is it right? I really tried to google some references but failed. I'm not still sure that results in my imagination are correct ones.&#xD;&#xA;&#xD;&#xA;And the second one where does it come from?&#xD;&#xA;&#xD;&#xA;I use usual lambertian shading model and have something like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = (0, 0, 0)&#xD;&#xA;    normal = get normal of sphere in point of intersection;&#xD;&#xA;    normal = unit vector of normal;&#xD;&#xA;    for each light from light_set {&#xD;&#xA;        light = unit vector of light;&#xD;&#xA;        pixel = pixel + diffuseColor * max(0, scalar multiplication of light and normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm really struggled to find out the reason where this strange thing is coming from. But couldn't find it.&#xD;&#xA;&#xD;&#xA;UPD0: added some of my real code. The part which is described here is next:&#xD;&#xA;&#xD;&#xA;    Material mat = surfaces[closestSurfase]-&gt;getMaterial();&#xD;&#xA;    Color pixel = Color(0, 0, 0);&#xD;&#xA;    Vector3f normal = surfaces[closestSurfase]-&gt;getNormal(point).getUnitVector();&#xD;&#xA;    Vector3f view = -ray.getDirection().getUnitVector();&#xD;&#xA;    for (size_t i = 0; i &lt; lights.size(); ++i) {&#xD;&#xA;        Vector3f normal_light = lights[i]-&gt;getDirection().getUnitVector();&#xD;&#xA;        Vector3f specVect = (normal_light + view).getUnitVector();&#xD;&#xA;        float intenst = lights[i]-&gt;getIntensity();&#xD;&#xA;        pixel = pixel + mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;    }&#xD;&#xA;    result-&gt;setPixel(x, y, pixel);&#xD;&#xA;&#xD;&#xA;Or you can find more here: https://github.com/minebv/ray_tracer/tree/lambertian_shading_fix/src&#xD;&#xA;&#xD;&#xA;Described above is from Camera's method getRender.&#xD;&#xA;&#xD;&#xA;UPD1: It looks like the problem in the mixing colors in gamma space instead linear one, as answered @PaulHK .&#xD;&#xA;&#xD;&#xA;But I've still some kind of problem. Here you can see 2 renders.&#xD;&#xA;![img1](https://i.stack.imgur.com/HNclL.png)&#xD;&#xA;At the left one I make all work after transformation all colors into linear space, I mean it's like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = pixel + mat.getDiffuse().toLinear() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;&#xD;&#xA;At the right one I make transformation after multiplying:&#xD;&#xA;&#xD;&#xA;    pixel = pixel + (mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst).toLinear();&#xD;&#xA;&#xD;&#xA;And I didn't forget to make pixel into gamma space again after all job.&#xD;&#xA;&#xD;&#xA;As for me, the right one is more correct. But then there is a question: why should I make multiplication on angle into gamma space? Or is it my incorrect way to think about what is right?&#xD;&#xA;&#xD;&#xA;UPD3:it looks like the whole thing really was about mixing colors in gamma space instead of linear one. Here is result with ambient light.&#xD;&#xA;![img3](https://i.stack.imgur.com/DOjAR.png)&#xD;&#xA;&#xD;&#xA;Also about overlapping lights, it was my incorrect way of thinking. I finally found reference material where they have the same thing. Found it at blender [docs](https://www.blender.org/manual/render/blender_render/materials/properties/specular_shaders.html#cooktorr).&#xD;&#xA;&#xD;&#xA;Thank everyone for answers." ContentLicense="CC BY-SA 3.0" />
  <row Id="8280" PostHistoryTypeId="5" PostId="3889" RevisionGUID="008ff9b4-20f2-4b4d-992a-22e990c886d2" CreationDate="2016-08-22T14:05:01.930" UserId="4948" Comment="added 73 characters in body" Text="Solved.  The issue was with V-Ray's global ambient occlusion on the GI tab.  Once that was shut off everything renders fine.  Interestingly, V-RayDirt maps in materials seem to be behaving just fine." ContentLicense="CC BY-SA 3.0" />
  <row Id="8281" PostHistoryTypeId="2" PostId="3893" RevisionGUID="848de2ce-c4f8-47df-8203-a0eaa241aff3" CreationDate="2016-08-22T15:13:13.423" UserId="4513" Text="I have a 3d city model that is a collada file which consist of many triangles. When I select the model in a 3d software all buildings are selected. But I want Every building to be selectable seperately is it possible? Are there any method or algorithm that defines which triangles are belong to a building in 3 3d model that consist many buildings and triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8282" PostHistoryTypeId="1" PostId="3893" RevisionGUID="848de2ce-c4f8-47df-8203-a0eaa241aff3" CreationDate="2016-08-22T15:13:13.423" UserId="4513" Text="In a polygonal mesh 3d model which consist of triangles is it possible to seperate different objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8283" PostHistoryTypeId="3" PostId="3893" RevisionGUID="848de2ce-c4f8-47df-8203-a0eaa241aff3" CreationDate="2016-08-22T15:13:13.423" UserId="4513" Text="|3d|mesh|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8284" PostHistoryTypeId="4" PostId="3891" RevisionGUID="be25eea5-f7dd-47d2-9289-8b7dc6d53efd" CreationDate="2016-08-22T17:59:07.550" UserId="231" Comment="Minor typo in title" Text="Can I Implement Clustered Lighting with WebGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8285" PostHistoryTypeId="2" PostId="3894" RevisionGUID="5c1840f9-ac61-4846-9411-a833efe249bb" CreationDate="2016-08-23T00:39:27.270" UserId="48" Text="It sounds to me like you're slightly mixing up several concepts: how lighting due to point-light sources (Phong model) and lighting due to other objects in the scene (recursively raytraced reflection or transmission) combine with each other, as compared to how specular lighting combines with diffuse lighting and/or transmission (using the Fresnel equations).&#xD;&#xA;&#xD;&#xA;A useful way to think about specular vs diffuse is that specular happens at the _surface_ of the material while diffuse, transmissive, and refractive properties are associated with the _bulk_ (the interior) of the material. So you can think of it as two layers composited together. Specular is on top: it reflects a portion of the incoming light, defined by the Fresnel equations, and any remaining light proceeds into the material to light the bulk.&#xD;&#xA;&#xD;&#xA;The bulk will have some combination of scattering and absorption properties. Low scattering makes a transmissive material and high scattering makes a diffuse material (the diffuse color is due to scattering on a scale too small to see). Some materials have an intermediate degree of scattering too, but we can ignore that for simplicity and just treat it as a boolean: opaque (Lambert diffuse) or transmissive.&#xD;&#xA;&#xD;&#xA;Meanwhile, each of these potential material components (specular, diffuse, and transmissive) has to deal with light arriving both from point light sources and from the rest of the scene. Physically, all light sources are just emissive objects that are part of the scene (area lights) but again for simplicity we often approximate by using point lights.&#xD;&#xA;&#xD;&#xA;So, putting it all together, when lighting a surface:&#xD;&#xA;&#xD;&#xA;* For each point light&#xD;&#xA;   1. Calculate Fresnel factor based on light vector&#xD;&#xA;   2. Accumulate Phong specular weighted by Fresnel reflectance&#xD;&#xA;   3. [if opaque] Accumulate Lambert diffuse weighted by Fresnel transmittance&#xD;&#xA;   4. [if transparent] Nothing; light goes through and isn't scattered into the camera.&#xD;&#xA;* For reflecting the rest of the scene&#xD;&#xA;   1. Calculate Fresnel factor based on view vector&#xD;&#xA;   2. Cast a reflection ray and accumulate it weighted by Fresnel reflectance&#xD;&#xA;   3. [if opaque] Nothing. (Ideally, accumulate Lambert diffuse due to all objects visible in the normal hemisphere of the surface, i.e. indirect diffuse. However, for a basic recursive raytracer this isn't feasible; it requires path tracing, photon mapping, or suchlike.)&#xD;&#xA;   4. [if transparent] Cast a transmission ray and accumulate it weighted by Fresnel transmittance&#xD;&#xA;&#xD;&#xA;Also, a note about your material properties: physically, not all of those properties are actually independent of each other. Ks, reflectivity, and refractive index are all the same thing. Ks is the same thing as reflectivity because both control specular reflections; Ks is for point lights and reflectivity is for reflected environment rays, but it's the same physical mechanism for both. And Ks is determined in turn by the Fresnel equations based on refractive index (which can vary with wavelength).&#xD;&#xA;&#xD;&#xA;So, strictly speaking, you should pick one of those variables and let it determine the others. For opaque materials where you don't really care about refractive index, you might let users set Ks (at normal incidence) and backsolve the Fresnel equations to get the appropriate refractive index from that. For transparent materials like glass you can let users set the refractive index and then let the Fresnel equations do their thing.&#xD;&#xA;&#xD;&#xA;BTW, to get some physics background that will hopefully help clarify all this, I highly recommend Naty Hoffman's &quot;Physics and Math of Shading&quot; talk from the [SIGGRAPH 2015 Physically-Based Shading Course](http://blog.selfshadow.com/publications/s2015-shading-course/). It gives a quick and not-too-mathematical intro to the physical basis of things like diffuse and specular lighting, BRDFs and so on." ContentLicense="CC BY-SA 3.0" />
  <row Id="8286" PostHistoryTypeId="5" PostId="3893" RevisionGUID="2fd36b5d-b7f4-44bf-a583-b97787d52ec2" CreationDate="2016-08-23T02:30:07.680" UserId="67" Comment="Fixed spelling" Text="I have a 3d city model that is a collada file which consist of many triangles. When I select the model in a 3d software all buildings are selected. But I want every building to be selectable separately, is it possible? Are there any methods or algorithms that define which triangles belong to a building in a 3d model that consist many buildings and triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8287" PostHistoryTypeId="4" PostId="3893" RevisionGUID="2fd36b5d-b7f4-44bf-a583-b97787d52ec2" CreationDate="2016-08-23T02:30:07.680" UserId="67" Comment="Fixed spelling" Text="In a polygonal mesh 3d model which consist of triangles is it possible to separate different objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8288" PostHistoryTypeId="24" PostId="3893" RevisionGUID="2fd36b5d-b7f4-44bf-a583-b97787d52ec2" CreationDate="2016-08-23T02:30:07.680" Comment="Proposed by 67 approved by 48, 182 edit id of 157" ContentLicense="CC BY-SA 3.0" />
  <row Id="8294" PostHistoryTypeId="2" PostId="3896" RevisionGUID="b87172c9-050f-4f08-a135-5ead09338078" CreationDate="2016-08-24T13:48:40.060" UserId="4503" Text="At page (slide in reality) 12/20 of [this tutorial][1] it is shown a function used to project lights into SH coefficients, however the value of those coefficients is not given, what are their values and what they are for?&#xD;&#xA;&#xD;&#xA;Do I have to clamp colors to max value of 1 (float) / 255(uint) when adding lights to SH coefficients?&#xD;&#xA;&#xD;&#xA;  [1]: http://documents.tips/documents/spherical-harmonics-gdce.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8295" PostHistoryTypeId="1" PostId="3896" RevisionGUID="b87172c9-050f-4f08-a135-5ead09338078" CreationDate="2016-08-24T13:48:40.060" UserId="4503" Text="What are the fConstX in Spherical Harmonics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8296" PostHistoryTypeId="3" PostId="3896" RevisionGUID="b87172c9-050f-4f08-a135-5ead09338078" CreationDate="2016-08-24T13:48:40.060" UserId="4503" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8297" PostHistoryTypeId="2" PostId="3897" RevisionGUID="d14597d7-5ca1-4323-b922-90e89daa50a0" CreationDate="2016-08-24T14:25:55.273" UserId="4981" Text="Said L the incoming ray (at a point P).  R is the reflected ray. N is the normal to the surface at the point P.  alpha is the angle between N and L (and N and R also). It is assumed a smooth surface (like a plane). P_R1 is the projection of the vector R on the plane.  R2 is the vector that joins the vector R and P_R1.&#xD;&#xA;Now you have, &#xD;&#xA;&#xD;&#xA;R= P_R1 + R2  (sum of vectors)&#xD;&#xA;&#xD;&#xA;P_R1 = -L+R2&#xD;&#xA;&#xD;&#xA;Thus:&#xD;&#xA;R=2R2-L&#xD;&#xA;&#xD;&#xA;Now, exploiting the property of dot product (namely scalar product)&#xD;&#xA;&#xD;&#xA;R2 = (NL)/|N|          (bacause R2 is Lcos(alpha) bacause is the projection of L on N)&#xD;&#xA;&#xD;&#xA;where NL is the dot product and |N| is the magnitude (the module) of vector N.&#xD;&#xA; But the vector N is the normal that typically has |N|=1&#xD;&#xA;Thus:&#xD;&#xA;&#xD;&#xA;R = 2(NL)-L&#xD;&#xA;&#xD;&#xA;But my book (3D Computer Graphics, Alan Watt) tells that:&#xD;&#xA;&#xD;&#xA;R2 = (NL)N&#xD;&#xA;&#xD;&#xA;Rather for me is:&#xD;&#xA;&#xD;&#xA;R2=(NL)/|N| = NL    (bacause |N|=1)&#xD;&#xA;&#xD;&#xA;I don't understand this point.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8298" PostHistoryTypeId="1" PostId="3897" RevisionGUID="d14597d7-5ca1-4323-b922-90e89daa50a0" CreationDate="2016-08-24T14:25:55.273" UserId="4981" Text="Expressing a reflected ray at a point as a function of the incoming ray and the normal to the surface at that point" ContentLicense="CC BY-SA 3.0" />
  <row Id="8299" PostHistoryTypeId="3" PostId="3897" RevisionGUID="d14597d7-5ca1-4323-b922-90e89daa50a0" CreationDate="2016-08-24T14:25:55.273" UserId="4981" Text="|geometry|computational-geometry|mathematics|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8300" PostHistoryTypeId="5" PostId="3897" RevisionGUID="ae008bf9-99d9-4775-82eb-41372b9fa6f4" CreationDate="2016-08-24T15:13:31.520" UserId="137" Comment="mathjax it up" Text="Said L the incoming ray (at a point $P$).  $R$ is the reflected ray. $N$ is the normal to the surface at the point $P$.  $\alpha$ is the angle between $N$ and $L$ (and $N$ and $R$ also). It is assumed a smooth surface (like a plane). $P_{R1}$ is the projection of the vector $R$ on the plane.  $R_2$ is the vector that joins the vector $R$ and $P_{R1}$.&#xD;&#xA;Now you have, &#xD;&#xA;&#xD;&#xA;$R= P_{R1} + R_2$  (sum of vectors)&#xD;&#xA;&#xD;&#xA;$P_{R1} = -L+R_2$&#xD;&#xA;&#xD;&#xA;Thus:&#xD;&#xA;$R=2R_2-L$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, exploiting the property of dot product (namely scalar product)&#xD;&#xA;&#xD;&#xA;$R_2 = (N\cdot L)/|N|$          (because $R_2$ is $L\cos(\alpha)$ because is the projection of $L$ on $N$)&#xD;&#xA;&#xD;&#xA;where $N\cdot L$ is the dot product and $|N|$ is the magnitude (the module) of vector $N$.&#xD;&#xA; But the vector $N$ is the normal that typically has $|N|=1$&#xD;&#xA;Thus:&#xD;&#xA;&#xD;&#xA;$R = 2(N\cdot L)-L$&#xD;&#xA;&#xD;&#xA;But my book (3D Computer Graphics, Alan Watt) tells that:&#xD;&#xA;&#xD;&#xA;$R_2 = (N\cdot L)N$&#xD;&#xA;&#xD;&#xA;Rather for me is:&#xD;&#xA;&#xD;&#xA;$R_2=(N\cdot L)/|N| = N\cdot L$    (because $|N|=1$)&#xD;&#xA;&#xD;&#xA;I don't understand this point.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8304" PostHistoryTypeId="2" PostId="3898" RevisionGUID="ee34795f-94af-4ca2-a0ae-f09a66aec635" CreationDate="2016-08-24T19:10:07.183" UserId="67" Text="Your attribute locations could be wrong, because you're not querying them:&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, false, 7*4, 0);&#xD;&#xA;    glVertexAttribPointer(3, 4, GL_FLOAT, false, 7*4, 3*4);&#xD;&#xA;&#xD;&#xA;The first parameter should be queried using `glGetAttribLocation`:&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(glGetAttribLocation( program, &quot;position&quot; ), 3, GL_FLOAT, false, 7*4, 0);&#xD;&#xA;    glVertexAttribPointer(glGetAttribLocation( program, &quot;i_color&quot; ), 4, GL_FLOAT, false, 7*4, 3*4);&#xD;&#xA;&#xD;&#xA;If using more modern OpenGL, the locations can be set manually in the shader, eliminating the need for `glGetAttribLocation`:&#xD;&#xA;&#xD;&#xA;    layout(location=0) in vec3 position;&#xD;&#xA;    layout(location=3) in vec4 i_color;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8309" PostHistoryTypeId="2" PostId="3901" RevisionGUID="07734366-a4e3-45ee-84af-4725a47ffc0f" CreationDate="2016-08-24T23:39:21.850" UserId="4983" Text="I have code, which for the sake of argument, looks like [the code here](https://dl.dropboxusercontent.com/u/94180423/stereoDisparity.m):&#xD;&#xA;&#xD;&#xA;	bestMatchIndex = sortedIndeces(1, 1);&#xD;&#xA;		&#xD;&#xA;	% Convert the 1-based index of this block back into an offset.&#xD;&#xA;	% This is the final disparity value produced by basic block matching.&#xD;&#xA;	d = bestMatchIndex + mind - 1;&#xD;&#xA;		&#xD;&#xA;	% Calculate a sub-pixel estimate of the disparity by interpolating.&#xD;&#xA;	% Sub-pixel estimation requires a block to the left and right, so we &#xD;&#xA;	% skip it if the best matching block is at either edge of the search&#xD;&#xA;	% window.&#xD;&#xA;	if ((bestMatchIndex == 1) || (bestMatchIndex == numBlocks))&#xD;&#xA;		% Skip sub-pixel estimation and store the initial disparity value.&#xD;&#xA;		DbasicSubpixel(m, n) = d;&#xD;&#xA;	else&#xD;&#xA;		% Grab the SAD values at the closest matching block (C2) and it's &#xD;&#xA;		% immediate neighbors (C1 and C3).&#xD;&#xA;		C1 = blockDiffs(bestMatchIndex - 1);&#xD;&#xA;		C2 = blockDiffs(bestMatchIndex);&#xD;&#xA;		C3 = blockDiffs(bestMatchIndex + 1);&#xD;&#xA;		&#xD;&#xA;		% Adjust the disparity by some fraction.&#xD;&#xA;		% We're estimating the subpixel location of the true best match.&#xD;&#xA;		DbasicSubpixel(m, n) = d - (0.5 * (C3 - C1) / (C1 - (2*C2) + C3));&#xD;&#xA;	end&#xD;&#xA;&#xD;&#xA;Now, I also want to calculate an *inverse disparity*, to eliminate points at infinity, but I cannot find a suitable algorithm. Can anyone describe how it should be done?&#xD;&#xA;&#xD;&#xA;My research has suggested that instead of comparing L(x, y) with R(x..x+n, y) it should be comparing L(x, y) with R(x-n..x, y), but am I correct?&#xD;&#xA;&#xD;&#xA;(My actual situation is C++ code with a buggy inverse disparity calculation which I cannot find a reference for to discover how the code should be.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8310" PostHistoryTypeId="1" PostId="3901" RevisionGUID="07734366-a4e3-45ee-84af-4725a47ffc0f" CreationDate="2016-08-24T23:39:21.850" UserId="4983" Text="Calculating inverse disparity of a stereo image" ContentLicense="CC BY-SA 3.0" />
  <row Id="8311" PostHistoryTypeId="3" PostId="3901" RevisionGUID="07734366-a4e3-45ee-84af-4725a47ffc0f" CreationDate="2016-08-24T23:39:21.850" UserId="4983" Text="|algorithm|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8314" PostHistoryTypeId="2" PostId="3902" RevisionGUID="f688d2ee-7e69-4ac9-8ca3-f37c88cae06a" CreationDate="2016-08-25T06:15:41.637" UserId="3003" Text="While normally I'd agree with @Survival Machine's assessment, since you say that the geometry is correct, but the color is showing up as solid red, it sounds like your colors have their color channels backwards. Normally, I would expect RGBA to be correct. But if everything's red, that sounds like the alpha is where the red should be. (Your alpha is always 1, so if they're swapped, now your red is always 1.) You can test this by changing your fragment shader to try different color orderings. Just add a swizzle to the last line:&#xD;&#xA;&#xD;&#xA;    f_color = color.yzwx;&#xD;&#xA;&#xD;&#xA;That will switch it from RGBA to ARGB. You might also try going the other way:&#xD;&#xA;&#xD;&#xA;    f_color = color.wxyz;&#xD;&#xA;&#xD;&#xA;It could also be in ABGR format (unlikely). You'd fix that by doing:&#xD;&#xA;&#xD;&#xA;    f_color = color.wzyx;&#xD;&#xA;&#xD;&#xA;It seems strange that any of these would happen. If that does turn out to be the issue, it would be worth investigating why it's happening." ContentLicense="CC BY-SA 3.0" />
  <row Id="8315" PostHistoryTypeId="2" PostId="3903" RevisionGUID="a4f9e478-633d-414d-8169-c88c7e8de9ec" CreationDate="2016-08-25T08:17:44.933" UserId="48" Text="$N \cdot L$ is the scalar _length_ of the projection of $L$ on $N$ (assuming $|N|=1$).&#xD;&#xA;&#xD;&#xA;$(N \cdot L)N$ is the actual vector with the length of $N \cdot L$ in the direction of $N$.&#xD;&#xA;&#xD;&#xA;There is often a confusion when people say &quot;projection of this on that&quot; whether they mean just its length, or the actual vector resulting from the projection. In this case you want to combine it with another vector, so you need the vector version. The correct reflection formula is thus: $$R = 2(N \cdot L)N - L$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="8316" PostHistoryTypeId="2" PostId="3904" RevisionGUID="855ebc91-924e-47fd-9477-5ccb88dcbcfe" CreationDate="2016-08-25T09:22:30.033" UserId="3331" Text="In order to reduce noise from an edge detection shader is it *generally* better to blur the input (depth and normal buffer in this case) or the output before applying the edge?&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="8317" PostHistoryTypeId="1" PostId="3904" RevisionGUID="855ebc91-924e-47fd-9477-5ccb88dcbcfe" CreationDate="2016-08-25T09:22:30.033" UserId="3331" Text="Is it better to blur the input or output of an edge detection shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8318" PostHistoryTypeId="3" PostId="3904" RevisionGUID="855ebc91-924e-47fd-9477-5ccb88dcbcfe" CreationDate="2016-08-25T09:22:30.033" UserId="3331" Text="|image-processing|blur|edge-detection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8320" PostHistoryTypeId="5" PostId="3904" RevisionGUID="f40b8c33-067b-4150-815d-45d21af5a55a" CreationDate="2016-08-25T13:16:24.043" UserId="3331" Comment="added 444 characters in body" Text="In order to reduce noise from an edge detection shader is it *generally* better to blur the input (depth and normal buffer in this case) or the output before applying the edge?&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;&#xD;&#xA;EDIT: To clarify.&#xD;&#xA;&#xD;&#xA;To reduce noise of edge detection the norm seems like it is to apply a blur. However, is it generally better to apply the blur to the input of the edge detection. The input in my case being the depth and normal GBuffers in which I compare neighbouring pixels.   &#xD;&#xA;Or is it better to blur the output of the edge detection, e.g. a greyscale image of edge strength, before I use that to apply some edge to a colour buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8321" PostHistoryTypeId="5" PostId="3904" RevisionGUID="7990e947-3475-4d8f-9b85-5f80b455935c" CreationDate="2016-08-25T13:31:20.940" UserId="231" Comment="Remove previous version (it is available in the edit history and redundant in the final version)" Text="To reduce noise of edge detection the norm seems like it is to apply a blur. However, is it generally better to apply the blur to the input of the edge detection. The input in my case being the depth and normal GBuffers in which I compare neighbouring pixels.   &#xD;&#xA;Or is it better to blur the output of the edge detection, e.g. a greyscale image of edge strength, before I use that to apply some edge to a colour buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8322" PostHistoryTypeId="2" PostId="3905" RevisionGUID="9804405b-6ab2-4115-97d5-075ec4e5ff75" CreationDate="2016-08-25T15:31:00.660" UserId="4956" Text="Ok, I've found the solution myself.&#xD;&#xA;&#xD;&#xA;It goes like this:&#xD;&#xA;&#xD;&#xA;    // create shape&#xD;&#xA;    shape = new THREE.Shape();&#xD;&#xA;    &#xD;&#xA;    // move it to first point of the chord&#xD;&#xA;    shape.moveTo(0+(RADIUS-2)*Math.cos(-1.4639537206164), 0+(RADIUS-2)*Math.sin(-1.4639537206164));&#xD;&#xA;&#xD;&#xA;    // create all the parts afterward&#xD;&#xA;    shape.absarc(0, 0, (RADIUS-2), -1.4639537206164, -1.3041396376011, true);&#xD;&#xA;    shape.quadraticCurveTo(0, 0, 0+(RADIUS-2)*Math.cos(4.5262534414805), 0+(RADIUS-2)*Math.sin(4.5262534414805));&#xD;&#xA;    shape.absarc(0, 0, (RADIUS-2), 4.5262534414805, 4.6513392175639, true);&#xD;&#xA;    shape.quadraticCurveTo(0, 0, 0+(RADIUS-2)*Math.cos(-1.4639537206164), 0+(RADIUS-2)*Math.sin(-1.4639537206164));&#xD;&#xA;&#xD;&#xA;    // create geometry&#xD;&#xA;    geometry = new THREE.ShapeGeometry( shape );&#xD;&#xA;    // create mesh&#xD;&#xA;    mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x000000, side: THREE.DoubleSide } ) ) ;&#xD;&#xA;    // rotate&#xD;&#xA;    mesh.rotation.x = 90 * Math.PI/180;&#xD;&#xA;    // add to scene&#xD;&#xA;    scene.add( mesh );" ContentLicense="CC BY-SA 3.0" />
  <row Id="8323" PostHistoryTypeId="2" PostId="3906" RevisionGUID="5da65cf6-5779-4b81-afe4-5010edf6bd88" CreationDate="2016-08-25T21:21:30.143" UserId="4981" Text="The scenery is the following:&#xD;&#xA;I have a polygon in the space, defined (the polygon) from your vertices. By 3 vertices of the polygon (non-aligned) revenue equation of the plane containing the polygon.&#xD;&#xA;Later I have a ray of light, represented by the parametric equation of the line in the plane (the parameter is $\textstyle t $\).&#xD;&#xA;&#xD;&#xA;I must determine the intersection between the line and the plan and see if the point of intersection (if they line and plane are not parallel) is internal or external to the polygon. &#xD;&#xA;&#xD;&#xA;Written the equation of the plan then,&#xD;&#xA;it's simple find the point of intersection: I replace the parameter values of $\textstyle x $ $\textstyle y $ and $\textstyle z $ of the line in the equation of the plane and from here I determine the value of the parameter t. Then replace t parametric equation of the line, and I am the coordinates of the intersection point.&#xD;&#xA;&#xD;&#xA;Then replace t in the parametric equation of the line, and I am the coordinates of the intersection point.&#xD;&#xA;&#xD;&#xA;The text that I am following (3D COmputer Graphics) tells me that if I get from the calculation that $\textstyle t &lt; 0 $ the point will stay in a part of plane that does not contain the polygon.&#xD;&#xA;&#xD;&#xA;I did not understand why. Than intuitive-geometric meaning has $\textstyle t $?&#xD;&#xA;&#xD;&#xA;I point that t &lt;0 is sufficient but not necessary condition to say that the point does not belong to the polygon. If it isn't  t &lt;0 I'll have to explicitly test whether the point is inside the polygon or not but the book says that if t &lt;0 I can avoid all this job  because the point is certainly outside the polygon (in a part of the plan that the book calls half plane ). I would like to know why, what mean the parameter t." ContentLicense="CC BY-SA 3.0" />
  <row Id="8324" PostHistoryTypeId="1" PostId="3906" RevisionGUID="5da65cf6-5779-4b81-afe4-5010edf6bd88" CreationDate="2016-08-25T21:21:30.143" UserId="4981" Text="Meaning of the parameter in a line-plane intersection in the space" ContentLicense="CC BY-SA 3.0" />
  <row Id="8325" PostHistoryTypeId="3" PostId="3906" RevisionGUID="5da65cf6-5779-4b81-afe4-5010edf6bd88" CreationDate="2016-08-25T21:21:30.143" UserId="4981" Text="|geometry|computational-geometry|mathematics|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8326" PostHistoryTypeId="2" PostId="3907" RevisionGUID="0dbcdbdb-c316-4edf-ba78-387a570ae5b2" CreationDate="2016-08-25T22:46:41.427" UserId="48" Text="The $t$ parameter represents the distance from the ray's origin point to the intersection point, as a multiple of the ray's direction vector. It is positive for intersections &quot;in front&quot; of the origin, negative for those &quot;behind&quot; the origin as judged by the direction vector.&#xD;&#xA;&#xD;&#xA;In raytracing we always discard any intersections with $t &lt; 0$, because we don't want to render objects behind the camera, and so forth. A ray is only half a line, and only the points $t \geq 0$ are part of the ray.&#xD;&#xA;&#xD;&#xA;It is not correct to say &quot;if $t&lt;0$ the point will stay in a part of plane that does not contain the polygon&quot;. If the polygon is behind the ray origin, then the intersection point may well be inside the polygon. However, we can immediately discard this intersection due to its being located behind the ray origin, so we would not need to perform any further tests of whether the point on the plane is in fact inside the polygon." ContentLicense="CC BY-SA 3.0" />
  <row Id="8327" PostHistoryTypeId="2" PostId="3908" RevisionGUID="ddde93a9-9275-4e06-9f46-4283451df033" CreationDate="2016-08-26T00:31:24.117" UserId="4991" Text="I'm new to GL stuff (coming in via WebGL, with no direct OpenGL experience). Can we use PhysX with WebGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8328" PostHistoryTypeId="1" PostId="3908" RevisionGUID="ddde93a9-9275-4e06-9f46-4283451df033" CreationDate="2016-08-26T00:31:24.117" UserId="4991" Text="Can we use PhysX in WebGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8329" PostHistoryTypeId="3" PostId="3908" RevisionGUID="ddde93a9-9275-4e06-9f46-4283451df033" CreationDate="2016-08-26T00:31:24.117" UserId="4991" Text="|webgl|physics|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8330" PostHistoryTypeId="4" PostId="3904" RevisionGUID="d20db11c-3838-4e63-bf14-ebac1bb583b7" CreationDate="2016-08-26T08:07:52.887" UserId="3331" Comment="added more context to title" Text="Is it better to blur the input or output of an edge detection shader for noise reduction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8331" PostHistoryTypeId="2" PostId="3909" RevisionGUID="15ad313b-66ce-4110-bbcd-102509a663b5" CreationDate="2016-08-26T08:28:27.930" UserId="385" Text="PhysX is a C++ API and can thus not directly be integrated with the JavaScript-based WebGL.&#xD;&#xA;&#xD;&#xA;Depending on your needs, you have the following options:&#xD;&#xA;&#xD;&#xA; - Use a JavaScript-based physics engine, mostly suitable for 2D use cases.&#xD;&#xA; - Use a Game Engine that can export for the web (e.g. Unity 3D) and build your application in there, using full 3D physics capability. Keep in mind that this will probably require your users to install some additional Web Player and is not native WebGL.&#xD;&#xA;&#xD;&#xA;Keep in mind that Game Engines may be a viable way for 2D applications too and can make your life a whole lot easier." ContentLicense="CC BY-SA 3.0" />
  <row Id="8332" PostHistoryTypeId="2" PostId="3910" RevisionGUID="e893548b-6c85-47c5-b9aa-e44a0801796b" CreationDate="2016-08-26T11:06:50.213" UserId="4992" Text="I have to create a file describing a 3d surface with the following properties:&#xD;&#xA;&#xD;&#xA; - a circular arc x-section is swept along a closed 2d curve spine defined with equations&#xD;&#xA; - the normal direction of the arc is not always tangential to the spine, the direction is defined with an equation&#xD;&#xA; - the surface should be analytic (defined by equations), but a tesselated is also acceptable (with an external script I can derive the x,y,z coords of the vertexes for a tesselated surf)&#xD;&#xA; - the file should be modifed by an external script (python), so it should be editable with text editor&#xD;&#xA; - the file should be opened by Creo(Proe), Catia and NX&#xD;&#xA;&#xD;&#xA;The question:&#xD;&#xA;Which is the best file format for making this feature?&#xD;&#xA;&#xD;&#xA;What I tried:&#xD;&#xA;&#xD;&#xA; - step: buying the ISO standard is unavoidable, as I cannot figure out on my own how the definition works&#xD;&#xA; - vrml: only tesselated seems to be feasible&#xD;&#xA; - x3d: same as vrml, as it has a sweep (extrusion) feature, but the normal direction is the same as the local spine direction, and Proe does not seem to open it&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8333" PostHistoryTypeId="1" PostId="3910" RevisionGUID="e893548b-6c85-47c5-b9aa-e44a0801796b" CreationDate="2016-08-26T11:06:50.213" UserId="4992" Text="File format for swept profile with changing normal" ContentLicense="CC BY-SA 3.0" />
  <row Id="8334" PostHistoryTypeId="3" PostId="3910" RevisionGUID="e893548b-6c85-47c5-b9aa-e44a0801796b" CreationDate="2016-08-26T11:06:50.213" UserId="4992" Text="|3d|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8335" PostHistoryTypeId="2" PostId="3911" RevisionGUID="963e022f-03d4-45bd-b7d4-501ab3000ade" CreationDate="2016-08-26T11:50:32.283" UserId="4993" Text="Given 3 points in 3D: $A=(A_x,A_y,A_z);   B=(B_x,B_y,B_z)  ;    C=(C_x,C_y,C_z)$&#xD;&#xA;&#xD;&#xA;Find the transformation matrix (in homogenous coordinates) that performs a reflection around the plane spanned by the given 3 points.&#xD;&#xA;&#xD;&#xA;Answer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;1. Can anyone explain why this answer is correct?&#xD;&#xA;2. Isnt normalization should be performed by dividing $|C-A|$ and $|B-A|$ and not $|AC|$ and $|AB|$?&#xD;&#xA;3. Wouldn't we want to reflect on $uv$ plane (and then the -1 would be one row below?)&#xD;&#xA;4. I saw a similar question where you had to rotate around a vector and not a surface, and then we created $v$ with $v=u\times(0,0,1)^T$ (the vector was $P_1-P_0$ and $u=\dfrac{P_1-P_0}{|P_1-P_0|}$, whats the difference?&#xD;&#xA;5. In general, what is the rule of thumb when finding $u,v,z$ cartesian system of a given object (plane, line, point etc)?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WhjIw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8336" PostHistoryTypeId="1" PostId="3911" RevisionGUID="963e022f-03d4-45bd-b7d4-501ab3000ade" CreationDate="2016-08-26T11:50:32.283" UserId="4993" Text="Transformaion Matrices" ContentLicense="CC BY-SA 3.0" />
  <row Id="8337" PostHistoryTypeId="3" PostId="3911" RevisionGUID="963e022f-03d4-45bd-b7d4-501ab3000ade" CreationDate="2016-08-26T11:50:32.283" UserId="4993" Text="|3d|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8338" PostHistoryTypeId="5" PostId="3911" RevisionGUID="688cb621-edd5-42ca-bdef-fbdf0c145f9e" CreationDate="2016-08-26T12:10:57.340" UserId="231" Comment="Minor typos in title and body" Text="Given 3 points in 3D: $A=(A_x,A_y,A_z);   B=(B_x,B_y,B_z)  ;    C=(C_x,C_y,C_z)$&#xD;&#xA;&#xD;&#xA;Find the transformation matrix (in homogeneous coordinates) that performs a reflection around the plane spanned by the given 3 points.&#xD;&#xA;&#xD;&#xA;Answer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;1. Can anyone explain why this answer is correct?&#xD;&#xA;2. Isnt normalization should be performed by dividing $|C-A|$ and $|B-A|$ and not $|AC|$ and $|AB|$?&#xD;&#xA;3. Wouldn't we want to reflect on $uv$ plane (and then the -1 would be one row below)?&#xD;&#xA;4. I saw a similar question where you had to rotate around a vector and not a surface, and then we created $v$ with $v=u\times(0,0,1)^T$ (the vector was $P_1-P_0$ and $u=\dfrac{P_1-P_0}{|P_1-P_0|}$, whats the difference?&#xD;&#xA;5. In general, what is the rule of thumb when finding $u,v,z$ cartesian system of a given object (plane, line, point etc)?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WhjIw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8339" PostHistoryTypeId="4" PostId="3911" RevisionGUID="688cb621-edd5-42ca-bdef-fbdf0c145f9e" CreationDate="2016-08-26T12:10:57.340" UserId="231" Comment="Minor typos in title and body" Text="Transformation Matrices" ContentLicense="CC BY-SA 3.0" />
  <row Id="8340" PostHistoryTypeId="5" PostId="3910" RevisionGUID="848d8a90-1f51-4376-866e-cd1c0843d5e8" CreationDate="2016-08-26T12:30:58.797" UserId="231" Comment="Tried to remove ambiguity - please correct any wrong assumptions I've made" Text="I have to create a file describing a 3d surface with the following properties:&#xD;&#xA;&#xD;&#xA;- a circular arc cross section is swept along a closed 2d curve spine defined with equations&#xD;&#xA;- the normal direction of the arc is not always tangential to the spine, the direction is defined with an equation&#xD;&#xA;- the surface should be analytic (defined by equations), but a tesselated surface is also acceptable (with an external script I can derive the x,y,z coords of the vertexes for a tesselated surface)&#xD;&#xA;- the file will be modified by an external script (python), so it should be editable with text editor&#xD;&#xA;- the file should be opened by Creo(Proe), Catia and NX&#xD;&#xA;&#xD;&#xA;The question:  &#xD;&#xA;Which is the best file format for making this feature?&#xD;&#xA;&#xD;&#xA;What I tried:&#xD;&#xA;&#xD;&#xA;- step: buying the ISO standard is unavoidable, as I cannot figure out on my own how the definition works&#xD;&#xA;- vrml: only tesselated seems to be feasible&#xD;&#xA;- x3d: same as vrml, as it has a sweep (extrusion) feature, but the normal direction is the same as the local spine direction, and Proe does not seem to open it&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8341" PostHistoryTypeId="2" PostId="3912" RevisionGUID="d9504dd0-a2fd-4e6e-87de-a401ecb48232" CreationDate="2016-08-26T14:05:19.270" UserId="4958" Text="In order to optimize I'm trying to set up a setup which ping pong between same framebuffer two color attachments to apply some postprocess effects. It seems to work (effects are applied) but concurently I'm getting a lot of strange artifacts like:&#xD;&#xA;&#xD;&#xA; - blinking squares&#xD;&#xA; - borders on depth discontinuities&#xD;&#xA; - color spilling on screen (window resize removes it)&#xD;&#xA;&#xD;&#xA;Which change or disappear partly when I for example remove one step (one post process effect) from &quot;ping ponging&quot;.&#xD;&#xA;&#xD;&#xA;If I do this ordinary way using different framebuffers seems to remove them but I'm not 100% sure if it is not a mess in the shaders or something but they seem fine.&#xD;&#xA;&#xD;&#xA;In each frame I'm doing ping pong like that:&#xD;&#xA;&#xD;&#xA;First step - render to current color attach using other fb texture&#xD;&#xA;&#xD;&#xA;    fbDeferredLighting-&gt;bindFramebuffer(); //fb which has two color attachments&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    effect1-&gt;setConstPerFrameUniforms();&#xD;&#xA;    //get 0 attachment from fb scene prepass to apply effect and draw on fbDeferredLighting current color attach&#xD;&#xA;    effect1-&gt;setTextureUniforms(fbScene, 0); &#xD;&#xA;    quad-&gt;draw();&#xD;&#xA;&#xD;&#xA;And then repeating some number of times: swap step and drawing, using same fb swapped attachment:&#xD;&#xA;&#xD;&#xA;    fbDeferredLighting-&gt;bindFramebuffer();&#xD;&#xA;    //after swap - now current=1, other=0 or current=0, other=1&#xD;&#xA;    std::swap(colorAttachment0Current, colorAttachment0Other);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texturesDiffuse[colorAttachment0Current]-&gt;getTextureID(), 0);&#xD;&#xA;    glClear(GL_DEPTH_BUFFER_BIT); //only clear depth&#xD;&#xA;    effectX-&gt;setConstPerFrameUniforms();&#xD;&#xA;    //get other color attach and use it to apply effect on current&#xD;&#xA;    effectX-&gt;setTextureUniforms(fbDeferredLighting , colorAttachment0Other); &#xD;&#xA;    quad-&gt;draw();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is this correct?&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8342" PostHistoryTypeId="1" PostId="3912" RevisionGUID="d9504dd0-a2fd-4e6e-87de-a401ecb48232" CreationDate="2016-08-26T14:05:19.270" UserId="4958" Text="ping pong between same framebuffer two color attachments" ContentLicense="CC BY-SA 3.0" />
  <row Id="8343" PostHistoryTypeId="3" PostId="3912" RevisionGUID="d9504dd0-a2fd-4e6e-87de-a401ecb48232" CreationDate="2016-08-26T14:05:19.270" UserId="4958" Text="|opengl|rendering|texture|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8344" PostHistoryTypeId="5" PostId="3906" RevisionGUID="4926dd34-6d88-4ba5-b69c-2a7c42021541" CreationDate="2016-08-26T17:03:39.380" UserId="4981" Comment="deleted 98 characters in body" Text="The scenery is the following:&#xD;&#xA;I have a polygon in the space, defined (the polygon) from your vertices. By 3 vertices of the polygon (non-aligned) revenue equation of the plane containing the polygon.&#xD;&#xA;Later I have a ray of light, represented by the parametric equation of the line in the plane (the parameter is $\textstyle t $\).&#xD;&#xA;&#xD;&#xA;I must determine the intersection between the line and the plan and see if the point of intersection (if they line and plane are not parallel) is internal or external to the polygon. &#xD;&#xA;&#xD;&#xA;Written the equation of the plan then,&#xD;&#xA;it's simple find the point of intersection: I replace the parameter values of $\textstyle x $ $\textstyle y $ and $\textstyle z $ of the line in the equation of the plane and from here I determine the value of the parameter t.&#xD;&#xA;Then I replace t in the parametric equation of the line, and I have the coordinates of the intersection point.&#xD;&#xA;&#xD;&#xA;The text that I am following (3D COmputer Graphics) tells me that if I get from the calculation that $\textstyle t &lt; 0 $ the point will stay in a part of plane that does not contain the polygon.&#xD;&#xA;&#xD;&#xA;I did not understand why. Than intuitive-geometric meaning has $\textstyle t $?&#xD;&#xA;&#xD;&#xA;I point that t &lt;0 is sufficient but not necessary condition to say that the point does not belong to the polygon. If it isn't  t &lt;0 I'll have to explicitly test whether the point is inside the polygon or not but the book says that if t &lt;0 I can avoid all this job  because the point is certainly outside the polygon (in a part of the plan that the book calls half plane ). I would like to know why, what mean the parameter t." ContentLicense="CC BY-SA 3.0" />
  <row Id="8345" PostHistoryTypeId="5" PostId="3912" RevisionGUID="0ef693dc-3227-4378-ada1-52a3686c9466" CreationDate="2016-08-26T22:25:16.707" UserId="4958" Comment="added 81 characters in body" Text="In order to optimize I'm trying to set up a setup which ping pong between same framebuffer two color attachments to apply some postprocess effects. It seems to work (effects are applied) but concurently I'm getting a lot of strange artifacts like:&#xD;&#xA;&#xD;&#xA; - blinking squares&#xD;&#xA; - borders on depth discontinuities&#xD;&#xA; - color spilling on screen (window resize removes it)&#xD;&#xA;&#xD;&#xA;Which change or disappear partly when I for example remove one step (one post process effect) from &quot;ping ponging&quot;.&#xD;&#xA;&#xD;&#xA;If I do this ordinary way using different framebuffers seems to remove them but I'm not 100% sure if it is not a mess in the shaders or something but they seem fine.&#xD;&#xA;&#xD;&#xA;In each frame I'm doing ping pong like that:&#xD;&#xA;&#xD;&#xA;First step - render to current color attach using other fb texture&#xD;&#xA;&#xD;&#xA;    fbDeferredLighting-&gt;bindFramebuffer(); //fb which has two color attachments&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    effect1-&gt;setConstPerFrameUniforms();&#xD;&#xA;    //get 0 attachment from fb scene prepass to apply effect and draw on fbDeferredLighting current color attach&#xD;&#xA;    effect1-&gt;setTextureUniforms(fbScene, 0); &#xD;&#xA;    quad-&gt;draw();&#xD;&#xA;&#xD;&#xA;And then repeating some number of times: swap step and drawing, using same fb swapped attachment:&#xD;&#xA;&#xD;&#xA;    fbDeferredLighting-&gt;bindFramebuffer();&#xD;&#xA;    //after swap - now current=1, other=0 or current=0, other=1&#xD;&#xA;    std::swap(colorAttachment0Current, colorAttachment0Other);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texturesDiffuse[colorAttachment0Current]-&gt;getTextureID(), 0);&#xD;&#xA;    glClear(GL_DEPTH_BUFFER_BIT); //only clear depth&#xD;&#xA;    effectX-&gt;setConstPerFrameUniforms();&#xD;&#xA;    //get other color attach and use it to apply effect on current&#xD;&#xA;    effectX-&gt;setTextureUniforms(fbDeferredLighting , colorAttachment0Other); &#xD;&#xA;    quad-&gt;draw();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is this correct?&#xD;&#xA;&#xD;&#xA; EDIT:&#xD;&#xA;I wonder, maybe rewrite it to compute shaders, that would simplify things.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8350" PostHistoryTypeId="5" PostId="3905" RevisionGUID="1c55feb9-efe4-42ba-8c09-1abf6cfc2d68" CreationDate="2016-08-27T06:38:33.557" UserId="-1" Comment="brief explanation added" Text="Ok, I've found the solution myself.&#xD;&#xA;&#xD;&#xA;It goes like this:&#xD;&#xA;&#xD;&#xA;    // create shape&#xD;&#xA;    shape = new THREE.Shape();&#xD;&#xA;    &#xD;&#xA;    // move it to first point of the chord&#xD;&#xA;    shape.moveTo(0+(RADIUS-2)*Math.cos(-1.4639537206164), 0+(RADIUS-2)*Math.sin(-1.4639537206164));&#xD;&#xA;&#xD;&#xA;    // create all the parts afterward&#xD;&#xA;    shape.absarc(0, 0, (RADIUS-2), -1.4639537206164, -1.3041396376011, true);&#xD;&#xA;    shape.quadraticCurveTo(0, 0, 0+(RADIUS-2)*Math.cos(4.5262534414805), 0+(RADIUS-2)*Math.sin(4.5262534414805));&#xD;&#xA;    shape.absarc(0, 0, (RADIUS-2), 4.5262534414805, 4.6513392175639, true);&#xD;&#xA;    shape.quadraticCurveTo(0, 0, 0+(RADIUS-2)*Math.cos(-1.4639537206164), 0+(RADIUS-2)*Math.sin(-1.4639537206164));&#xD;&#xA;&#xD;&#xA;    // create geometry&#xD;&#xA;    geometry = new THREE.ShapeGeometry( shape );&#xD;&#xA;    // create mesh&#xD;&#xA;    mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x000000, side: THREE.DoubleSide } ) ) ;&#xD;&#xA;    // rotate&#xD;&#xA;    mesh.rotation.x = 90 * Math.PI/180;&#xD;&#xA;    // add to scene&#xD;&#xA;    scene.add( mesh );&#xD;&#xA;&#xD;&#xA;1) create Shape object&lt;br&gt;&#xD;&#xA;2) move offset to the first point on the arc&lt;br&gt;&#xD;&#xA;3) create arc with the same center and smaller radius as circle (start angle of the first point, end angle second)&lt;br&gt;&#xD;&#xA;4) use quadratic curve with control point (circle center) and the third point&lt;br&gt;&#xD;&#xA;5) use arc the same way as before&lt;br&gt;&#xD;&#xA;6) complete shape with quadratic curve and the last point&lt;br&gt;&#xD;&#xA;7) set geometry, material, add it to scene&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8351" PostHistoryTypeId="24" PostId="3905" RevisionGUID="1c55feb9-efe4-42ba-8c09-1abf6cfc2d68" CreationDate="2016-08-27T06:38:33.557" Comment="Proposed by anonymous approved by 4956 edit id of 158" ContentLicense="CC BY-SA 3.0" />
  <row Id="8352" PostHistoryTypeId="2" PostId="3914" RevisionGUID="709c18f0-7671-44a9-bdd1-0054eca3ba01" CreationDate="2016-08-27T07:40:09.907" UserId="48" Text="The answer in the screenshot is wrong on two counts. First, you're correct that in the middle matrix the −1 should be on the third row, not the second. The other error is that the $u, v$ basis vectors are normalized, but not orthogonalized, so $M$ is not in general a rotation matrix; therefore its inverse is not simply its transpose. (The reflection doesn't actually need an orthonormal basis, so you could fix the answer either way: by using the full inverse for $M$, or by fully orthonormalizing $u$ and $v$.)&#xD;&#xA;&#xD;&#xA;The rule of thumb for setting up a local coordinate system (I assume orthonormal) for a given object is to set some of the axes to be lined up with the object, then choose arbitrary perpendicular vectors for any remaining axes.&#xD;&#xA;&#xD;&#xA;* For a point, there's nothing to line up with, so you can use any arbitrary axes.&#xD;&#xA;* For a line, you line up the $u$ axis with the line, then there's nothing to constrain the $v$ axis, so you can choose any arbitrary vector perpendicular to $u$. That's what the $v=u\times(0,0,1)^T$ thing was getting at: it's a convenient formula to get _some_ vector perpendicular to $u$ if you don't otherwise care what direction it is. Except that this won't work if $u$ happens to be parallel to the z-axis (the cross product returns zero then), so you actually need to detect that and switch to a different formula, such as $v=u\times(1,0,0)^T$, in that case.&#xD;&#xA;* For a plane, you line up the $u$ and $v$ axes with the plane. So, you can pick any arbitrary $u$ that lies in the plane, then find a $v$ that lies in the plane and is perpendicular to $u$." ContentLicense="CC BY-SA 3.0" />
  <row Id="8353" PostHistoryTypeId="50" PostId="3768" RevisionGUID="827f34ad-40e7-4e44-b82b-040ceb5796fa" CreationDate="2016-08-27T10:19:31.807" UserId="-1" />
  <row Id="8354" PostHistoryTypeId="2" PostId="3915" RevisionGUID="99e203e6-a2ac-45e2-82dc-7169c1738aa8" CreationDate="2016-08-27T16:12:21.590" UserId="4999" Text="How CAD programs handle displaying B-Reps and NURBS/T-Splines in their viewports? Assuming viewport uses OpenGL API - are those programs transform every object into triangles and creating/deleting vertex/index buffers when needed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8355" PostHistoryTypeId="1" PostId="3915" RevisionGUID="99e203e6-a2ac-45e2-82dc-7169c1738aa8" CreationDate="2016-08-27T16:12:21.590" UserId="4999" Text="How CAD programs render 3D objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8356" PostHistoryTypeId="3" PostId="3915" RevisionGUID="99e203e6-a2ac-45e2-82dc-7169c1738aa8" CreationDate="2016-08-27T16:12:21.590" UserId="4999" Text="|opengl|rendering|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8357" PostHistoryTypeId="2" PostId="3916" RevisionGUID="0388e8cd-9ee7-4325-935d-bb7a0558b20f" CreationDate="2016-08-27T17:46:17.120" UserId="3383" Text="While doing some reading on how real-time applications handle color under OpneGL, I noticed that some examples implemented Color as a collection of 4 `floats`, while others used 4 `doubles`. I have even seen some vertex-compression examples in the game development field that advocated saving colors as 4 `short`.&#xD;&#xA;&#xD;&#xA;All this got me eager for learning more about this: what is the limit precision that OpenGl (or hardwares) handle? More importantly, though, what are the limits in precision above which color differences become impossible to notice?&#xD;&#xA;&#xD;&#xA;I have the impression that learning more carefully about that would help me better think and decide on how to implement a Color class for different applications and scenarios (e.g. making trade-off choices between memory, speed and color-variety).&#xD;&#xA;&#xD;&#xA;Thanks for your ideas on this." ContentLicense="CC BY-SA 3.0" />
  <row Id="8358" PostHistoryTypeId="1" PostId="3916" RevisionGUID="0388e8cd-9ee7-4325-935d-bb7a0558b20f" CreationDate="2016-08-27T17:46:17.120" UserId="3383" Text="How much precision (half, float, double, etc) is enough for a Color class?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8359" PostHistoryTypeId="3" PostId="3916" RevisionGUID="0388e8cd-9ee7-4325-935d-bb7a0558b20f" CreationDate="2016-08-27T17:46:17.120" UserId="3383" Text="|opengl|color|color-science|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8360" PostHistoryTypeId="5" PostId="3916" RevisionGUID="ef05a380-954a-4615-a6ed-b5f33954a796" CreationDate="2016-08-27T18:09:43.917" UserId="3383" Comment="added 11 characters in body" Text="While doing some reading on how real-time applications handle color under OpneGL, I noticed that some examples implemented Color as a collection of 4 `floats`, while others used 4 `doubles`. I have even seen some vertex-compression examples in the game development field that advocated saving colors as 4 `short`.&#xD;&#xA;&#xD;&#xA;All this got me eager for learning more about this: what is the limit precision that OpenGl (or hardwares) handle for colors? More importantly, though, what are the limits in precision above which color differences become impossible to notice?&#xD;&#xA;&#xD;&#xA;I have the impression that learning more carefully about that would help me better think and decide on how to implement a Color class for different applications and scenarios (e.g. making trade-off choices between memory, speed and color-variety).&#xD;&#xA;&#xD;&#xA;Thanks for your ideas on this." ContentLicense="CC BY-SA 3.0" />
  <row Id="8361" PostHistoryTypeId="2" PostId="3917" RevisionGUID="fb6eb4ef-8d13-4af7-8db7-5a7c8214806b" CreationDate="2016-08-27T22:56:08.433" UserId="5002" Text="I'm not an expert on Spherical Harmonic (SH), but I'll try to answer.&#xD;&#xA;&#xD;&#xA;SH functions are basis functions. That means that they encode a function $f$ this way by a given basis function $B_i$:&#xD;&#xA;&#xD;&#xA; $$\int_{}^{} f(x) B_i(x) dx=fConst_i$$&#xD;&#xA;&#xD;&#xA;So what we can do is to use the $fConst_i$ to reconstruct an approximation of the function $f$ this way:&#xD;&#xA;&#xD;&#xA;$$\sum_{n=1}^{i} fConst_iB(i)$$&#xD;&#xA;&#xD;&#xA;In your case they could look like this:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;fConst1 = 0.429043;&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;fConst2 = 0.511664;&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;fConst3 = 0.743125;&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;fConst4 = 0.886227;&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;fConst5 = 0.247708;&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;These coefficients approximate diffuse lighting." ContentLicense="CC BY-SA 3.0" />
  <row Id="8362" PostHistoryTypeId="2" PostId="3918" RevisionGUID="9898508d-279e-4eba-bc7b-02c1c0f607b8" CreationDate="2016-08-28T01:04:45.113" UserId="4991" Text="I am familiar with the basic concepts of writing vector and fragment shaders while using linear transformation matrices to describe orientations in 3D space.&#xD;&#xA;&#xD;&#xA;But, what other paradigms exist (theoretical or not)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8363" PostHistoryTypeId="1" PostId="3918" RevisionGUID="9898508d-279e-4eba-bc7b-02c1c0f607b8" CreationDate="2016-08-28T01:04:45.113" UserId="4991" Text="What other paradigms exist besides vector/fragment/transform graphics programming?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8364" PostHistoryTypeId="3" PostId="3918" RevisionGUID="9898508d-279e-4eba-bc7b-02c1c0f607b8" CreationDate="2016-08-28T01:04:45.113" UserId="4991" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8365" PostHistoryTypeId="2" PostId="3919" RevisionGUID="9bb09a23-6017-4396-a6d9-97d5b015d034" CreationDate="2016-08-28T01:11:30.527" UserId="4991" Text="It's totally possible to re-use vertices. That's why when making a flat rectangle plane with four corners that there can be two triangles rendered to construct the rectangle, and the triangles share two of the vertices." ContentLicense="CC BY-SA 3.0" />
  <row Id="8366" PostHistoryTypeId="5" PostId="3914" RevisionGUID="282fa210-ad48-42eb-a437-7add4f452d16" CreationDate="2016-08-28T01:21:12.287" UserId="48" Comment="addendum on orthonormalization" Text="The answer in the screenshot is wrong on two counts. First, you're correct that in the middle matrix the −1 should be on the third row, not the second. The other error is that the $u, v$ basis vectors are normalized, but not orthogonalized, so $M$ is not in general a rotation matrix; therefore its inverse is not simply its transpose. (The reflection doesn't actually need an orthonormal basis, so you could fix the answer either way: by using the full inverse for $M$, or by fully orthonormalizing $u$ and $v$.)&#xD;&#xA;&#xD;&#xA;The rule of thumb for setting up a local coordinate system (I assume orthonormal) for a given object is to set some of the axes to be lined up with the object, then choose arbitrary perpendicular vectors for any remaining axes.&#xD;&#xA;&#xD;&#xA;* For a point, there's nothing to line up with, so you can use any arbitrary axes.&#xD;&#xA;* For a line, you line up the $u$ axis with the line, then there's nothing to constrain the $v$ axis, so you can choose any arbitrary vector perpendicular to $u$. That's what the $v=u\times(0,0,1)^T$ thing was getting at: it's a convenient formula to get _some_ vector perpendicular to $u$ if you don't otherwise care what direction it is. Except that this won't work if $u$ happens to be parallel to the z-axis (the cross product returns zero then), so you actually need to detect that and switch to a different formula, such as $v=u\times(1,0,0)^T$, in that case.&#xD;&#xA;* For a plane, you line up the $u$ and $v$ axes with the plane. So, you can pick any arbitrary $u$ that lies in the plane, then find a $v$ that lies in the plane and is perpendicular to $u$.&#xD;&#xA;&#xD;&#xA;###Addendum on orthonormalization&#xD;&#xA;&#xD;&#xA;Suppose you have a couple of 3D vectors $u, v$ that are non-parallel (linearly independent) but otherwise arbitrary, and you want to generate a 3D orthonormal basis $u', v', w'$ from them. There are two equivalent ways to do it.&#xD;&#xA;&#xD;&#xA;1. Use the [Gram–Schmidt process](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process). This works as follows: first, normalize $u$. Then, for each additional vector, subtract off its projection onto the previous vectors, and normalize what's left over. For the 3D case this looks like:&#xD;&#xA;$$ \begin{aligned}&#xD;&#xA;u' &amp;= \text{normalize}(u) = \frac{u}{|u|} \\&#xD;&#xA;v' &amp;= \text{normalize} \bigl( v - (u' \cdot v)u' \bigr) \\&#xD;&#xA;w' &amp;= u' \times v'&#xD;&#xA;\end{aligned} $$&#xD;&#xA;Note that the notation $(u' \cdot v)u'$ means take the dot product of $u'$ with $v$ (giving a scalar), then multiply that scalar by $u'$. This gives the vector component of $v$ that is parallel to $u'$. When this is subtracted from $v$, the remaining component is perpendicular to $u'$.&#xD;&#xA;&#xD;&#xA; Finally, $w'$ is set to the cross product of $u'$ and $v'$ to ensure the basis is right-handed. Since $u', v'$ are already orthonormal, we don't need to normalize $w'$—it comes out already normalized. (This isn't strictly part of the Gram–Schmidt process.)&#xD;&#xA;&#xD;&#xA; By the way, the Gram–Schmidt process works for making an orthonormal basis in any number of dimensions, not just two or three.&#xD;&#xA;&#xD;&#xA;2. The other way, which only works in 3D, is to use cross products.&#xD;&#xA;$$ \begin{aligned}&#xD;&#xA;u' &amp;= \text{normalize}(u) \\&#xD;&#xA;w' &amp;= \text{normalize}(u' \times v) \\&#xD;&#xA;v' &amp;= w' \times u'&#xD;&#xA;\end{aligned} $$&#xD;&#xA;Here, $w'$ has to be normalized because $u'$ and $v$ are not orthonormal. But then $u'$ and $w'$ are orthonormal, so we can calculate $v'$ from them without a normalize. This gives the same results as the previous process, so it's up to you which you prefer to use." ContentLicense="CC BY-SA 3.0" />
  <row Id="8367" PostHistoryTypeId="2" PostId="3920" RevisionGUID="abafd7c0-a71c-44d6-b38d-d804de4c6915" CreationDate="2016-08-28T02:49:41.457" UserId="48" Text="Colors shown on your display or saved to standard image file formats use 8 bits per component. So to store these colors it suffices to use four bytes (`unsigned char`). These colors are usually using [sRGB](https://en.wikipedia.org/wiki/SRGB) color space, which includes a non-linear &quot;gamma&quot; transformation that redistributes precision to make it somewhat more perceptually uniform, so it's actually pretty close to the limit of how finely humans can perceive color differences already. (However, the sRGB gamut is only a subset of all the colors that are physically perceivable. Wider gamuts need more bits.)&#xD;&#xA;&#xD;&#xA;However, if you're generating or processing colors in graphics software (and not just loading/storing them), there are various reasons you might want to use more precision.&#xD;&#xA;&#xD;&#xA;* Performing operations on colors, such as adjusting brightness and contrast, alpha blending, gamma correction, etc all tend to lose precision. You might want to store colors as 16-bit or more internally to give yourself more precision headroom. Otherwise, repeated rounding off to 8 bits after each operation can cause a progressive loss of quality.&#xD;&#xA;* Similarly, when working with linear colors (not the sRGB gamma-encoded colors) for lighting math, extra precision is needed to ensure you have sufficient precision when you eventually convert back to sRGB.&#xD;&#xA;* It may be faster and more convenient to work with floating-point colors instead of integer ones. This is especially true on GPUs, where integer math instructions have only a fraction of the throughput of float instructions. But even on CPUs it's certainly easier and probably faster to convert colors to float, do a bunch of operations, and then convert back to integer, rather than trying to do everything with integer fixed-point math.&#xD;&#xA;* If you do [HDR](https://en.wikipedia.org/wiki/High-dynamic-range_rendering) rendering at all then you'll need more than 8 bits of precision to handle the larger color gamut and intensity range. The new HDR displays just starting to come out accept images with 10 or 12 bits per component.&#xD;&#xA;&#xD;&#xA;Using `double` for colors is massive overkill, but using `float` for internal representation of colors is common for all the reasons above. When working with GPUs, `half` (16-bit float) is also common, as they support that format in hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="8368" PostHistoryTypeId="2" PostId="3921" RevisionGUID="b5eef6a5-9504-4da7-a53d-53141e0dfd8f" CreationDate="2016-08-28T06:19:19.717" UserId="38" Text="Depends on the CAD program. But yes basically they do just what you describe they triangulate the model into a mesh/lines on demand and then display that. How they chose to do this depends on the CAD, most modernized codebases probably use buffers. But older cads may in fact use the old immediate mode draw calls. &#xD;&#xA;&#xD;&#xA;This said it is possible that the triangulation happens on the GPU. Though i doubt it is implemented that way in many CAD software. There are also other reasons for the CAD to triangulate the meshes, such as intersection testing, CAM path planning and export, that has nothing to do with display as such and would result in the need of implementing both a software and a gpu triangulator doubling workload or and making maintenance difficult.&#xD;&#xA;&#xD;&#xA;Most CAD systems allow you to access the triangulated representation, trough their API as well as export. But if all else fails you could just attach a debug dll to see what data the CAD dumps to the display card." ContentLicense="CC BY-SA 3.0" />
  <row Id="8369" PostHistoryTypeId="5" PostId="3921" RevisionGUID="0b678197-108d-4ee1-97a4-2cbbaf392a45" CreationDate="2016-08-28T06:24:38.150" UserId="38" Comment="added 68 characters in body" Text="Depends on the CAD program. But yes basically they do just what you describe they triangulate the model into a mesh/lines on demand and then display that. How they chose to do this depends on the CAD, most modernized codebases probably use buffers. But older cads may in fact use the old immediate mode draw calls. &#xD;&#xA;&#xD;&#xA;This said it is possible that the triangulation happens on the GPU. Though i doubt it is implemented that way in many CAD software. There are also other reasons for the CAD to triangulate the meshes, such as intersection testing, CAM path planning and export, that has nothing to do with display as such and would result in the need of implementing both a software and a gpu triangulator doubling workload or and making maintenance difficult.&#xD;&#xA;&#xD;&#xA;Most CAD systems allow you to access the triangulated representation, trough their API as well as export. But if all else fails you could just attach a debug dll to see what data the CAD dumps to the display card. So for a definitive answer ask your CAD software to tell it to you." ContentLicense="CC BY-SA 3.0" />
  <row Id="8370" PostHistoryTypeId="2" PostId="3922" RevisionGUID="eeea9bcb-ea7b-4ff5-b048-b5dd3d6da470" CreationDate="2016-08-28T06:32:28.993" UserId="48" Text="Several other rendering paradigms exist aside from conventional rasterization of triangles using vertex and fragment shaders.&#xD;&#xA;&#xD;&#xA;* [Ray tracing](https://en.wikipedia.org/wiki/Ray_tracing_(graphics)) works by intersecting light rays with surfaces (triangle meshes, or more general surfaces: anything that can be tested for intersection) and then firing additional rays to gather information about lighting, shadows, reflections, etc at the intersection point. Path tracing and photon mapping are refinements of this concept.&#xD;&#xA;* [REYES rendering](https://en.wikipedia.org/wiki/Reyes_rendering) subdivides all primitives into micropolygons the size of a single pixel or smaller, calculates lighting and shading per micropolygon vertex, then uses a specialized rasterizing algorithm to render the micropolygons in screen space with motion blur and depth of field.&#xD;&#xA;* [Distance field ray-marching](http://iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm) (also called [sphere tracing](http://computergraphics.stackexchange.com/questions/161/what-is-ray-marching-is-sphere-tracing-the-same-thing)) represents all primitives in terms of distance fields: 3D functions and/or volumetric textures that give the distance from any given point to the nearest surface in any direction. The distance field is used to step adaptively along a ray until it hits a surface, and can also be used for lighting effects such as ambient occlusion.&#xD;&#xA;&#xD;&#xA;However, all rendering algorithms use linear transformation matrices. That's not part of the &quot;paradigm&quot; so much as it's the basic machinery for manipulating objects, the camera, etc in 3D space. It would be hard to do anything interesting without it." ContentLicense="CC BY-SA 3.0" />
  <row Id="8371" PostHistoryTypeId="4" PostId="3915" RevisionGUID="73affef6-c15a-4b2a-8f4f-af12745f3554" CreationDate="2016-08-28T09:29:12.063" UserId="506" Comment="clarified title, added a relevant tag" Text="How do CAD programs render non-polygonal 3D objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8372" PostHistoryTypeId="6" PostId="3915" RevisionGUID="73affef6-c15a-4b2a-8f4f-af12745f3554" CreationDate="2016-08-28T09:29:12.063" UserId="506" Comment="clarified title, added a relevant tag" Text="|opengl|rendering|nurbs|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8373" PostHistoryTypeId="24" PostId="3915" RevisionGUID="73affef6-c15a-4b2a-8f4f-af12745f3554" CreationDate="2016-08-28T09:29:12.063" Comment="Proposed by 506 approved by 48, 273 edit id of 159" ContentLicense="CC BY-SA 3.0" />
  <row Id="8374" PostHistoryTypeId="5" PostId="3921" RevisionGUID="a500593a-26e4-49d0-a8d4-b3c0a8adf180" CreationDate="2016-08-28T11:27:09.323" UserId="231" Comment="Minor typo" Text="Depends on the CAD program. But yes basically they do just what you describe they triangulate the model into a mesh/lines on demand and then display that. How they chose to do this depends on the CAD, most modernized codebases probably use buffers. But older cads may in fact use the old immediate mode draw calls. &#xD;&#xA;&#xD;&#xA;This said it is possible that the triangulation happens on the GPU. Though i doubt it is implemented that way in many CAD software. There are also other reasons for the CAD to triangulate the meshes, such as intersection testing, CAM path planning and export, that has nothing to do with display as such and would result in the need of implementing both a software and a gpu triangulator doubling workload or and making maintenance difficult.&#xD;&#xA;&#xD;&#xA;Most CAD systems allow you to access the triangulated representation, through their API as well as export. But if all else fails you could just attach a debug dll to see what data the CAD dumps to the display card. So for a definitive answer ask your CAD software to tell it to you." ContentLicense="CC BY-SA 3.0" />
  <row Id="8375" PostHistoryTypeId="2" PostId="3923" RevisionGUID="d79e8ee9-d6b5-495d-9907-efa846fe4f96" CreationDate="2016-08-28T13:55:19.850" UserId="38" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed).&#xD;&#xA;&#xD;&#xA;I would explore an alternative option, buy a commercial or take a free CAD kernel and let the kernel (open CSCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the otherhand this is not hard to do inside your CAD application.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8376" PostHistoryTypeId="5" PostId="3923" RevisionGUID="32575fbe-d4b7-4c47-bd6a-86c47fdc0a13" CreationDate="2016-08-28T15:40:25.777" UserId="38" Comment="added 50 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed).&#xD;&#xA;&#xD;&#xA;I would explore an alternative option, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the otherhand this is not hard to do inside your CAD application. Which you will need anyway to verify the result.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8377" PostHistoryTypeId="5" PostId="3923" RevisionGUID="e0b4476c-9ff3-4bc1-95e8-3b3650fec946" CreationDate="2016-08-28T18:12:27.850" UserId="38" Comment="added 168 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed).&#xD;&#xA;&#xD;&#xA;I would explore an alternative option, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. The CAD applications have a COM API's so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and its usually less work to set up than using just the kernel).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8378" PostHistoryTypeId="2" PostId="3924" RevisionGUID="551f6d08-09a7-4e52-9894-6112aecfe306" CreationDate="2016-08-28T18:19:07.210" UserId="4705" Text="A 2D vector can be rotated by an angle $\theta$ using the rotation matrix:&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; -\sin(\theta) \\&#xD;&#xA;\sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Or, it can be rotated by multiplying the vector by the complex number $c$:&#xD;&#xA;&#xD;&#xA;$$c = \cos(\theta) + i\sin(\theta)$$&#xD;&#xA;&#xD;&#xA;Is there any meaningful difference between these two methods? I tested both in MATLAB, and they seem to run at the same speed. &#xD;&#xA;&#xD;&#xA;On a related note, is there some spatial transformation that complex numbers can do but matrices cannot?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8379" PostHistoryTypeId="1" PostId="3924" RevisionGUID="551f6d08-09a7-4e52-9894-6112aecfe306" CreationDate="2016-08-28T18:19:07.210" UserId="4705" Text="Computing a rotation: complex numbers vs rotation matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="8380" PostHistoryTypeId="3" PostId="3924" RevisionGUID="551f6d08-09a7-4e52-9894-6112aecfe306" CreationDate="2016-08-28T18:19:07.210" UserId="4705" Text="|transformations|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8381" PostHistoryTypeId="5" PostId="3923" RevisionGUID="48f8b0bd-ca76-433b-b06b-079d10fa1e58" CreationDate="2016-08-28T19:16:13.300" UserId="38" Comment="added 165 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed).&#xD;&#xA;&#xD;&#xA;I would explore an alternative option, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. Most CAD applications have a COM API's (dont know about NX most likely, but both creo and catia do have this) so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and its usually less work to set up than using just the kernel).&#xD;&#xA;&#xD;&#xA;[![sweep][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Sweept with spine angle $60 \cos(4 t)+110$ and polar trajectory with $r = \cos(4 t)$ in Creo. All input from program injection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ufq1l.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8382" PostHistoryTypeId="2" PostId="3925" RevisionGUID="a8ffc265-4d36-4a7a-934f-18f8c9b84f14" CreationDate="2016-08-28T20:28:01.203" UserId="38" Text="In a 2D case it reduces to the same calculation. Anyway for 3D we have quaternions that are multidimensional imaginary numbers with one real and 3 imaginary components. Quaternions have a property that makes rotation composing a linear interpolation operation by summing 2 weighted quaternions. This neatly solves certain problems with space rotations. But at the cost of understandability." ContentLicense="CC BY-SA 3.0" />
  <row Id="8383" PostHistoryTypeId="2" PostId="3926" RevisionGUID="a02cb85f-ca48-4a4b-80d3-58cd7acfacbf" CreationDate="2016-08-28T20:30:55.193" UserId="4993" Text="I need to find the transformation matrix&#xD;&#xA;(homogeneous coordinates) that flips an&#xD;&#xA;object about a plane whose normal is&#xD;&#xA;directed towards (-2 2 0), and intersects the&#xD;&#xA;y-axis at y=2.&#xD;&#xA;&#xD;&#xA;I know how to do that when I have 3 points on the plane (A,B,C): translate to origin, find the orthonormal basis of the plane (u,v,w axes) and then rotate the plane to match XYZ coordinate system (with the axes I found), perform the reflection, rotate back and translate back.&#xD;&#xA;&#xD;&#xA;However in this case I have a normal and another data which I don't know how to use.&#xD;&#xA;&#xD;&#xA;Any ideas?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8384" PostHistoryTypeId="1" PostId="3926" RevisionGUID="a02cb85f-ca48-4a4b-80d3-58cd7acfacbf" CreationDate="2016-08-28T20:30:55.193" UserId="4993" Text="Transformations about a Plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="8385" PostHistoryTypeId="3" PostId="3926" RevisionGUID="a02cb85f-ca48-4a4b-80d3-58cd7acfacbf" CreationDate="2016-08-28T20:30:55.193" UserId="4993" Text="|3d|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8386" PostHistoryTypeId="2" PostId="3927" RevisionGUID="ae500833-4a22-4397-a451-5d6638462500" CreationDate="2016-08-28T21:10:22.533" UserId="38" Text="This is the same problem as the rotation about an axis. What you need is a matrix (any matrix) that satisfies the following corner constraint: one axis must point toward $(-2, 2, 0)$ in the case of a rotation this matrix must be a rotation matrix, in the case of a planar mirror it just has to span the 3D space. But since we know how to make a an arbitrary rotation matrix we use same approach.&#xD;&#xA;&#xD;&#xA;1. Pick any vector(u) thats not paralell to normal (n)&#xD;&#xA;2. take cross product of u and n for b&#xD;&#xA;3. take cross product of u and b for a&#xD;&#xA;&#xD;&#xA;you now have now an arbitrary rotation matrix with one axis defined using vectors n, b and a. Otherwise same as the last question.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8387" PostHistoryTypeId="2" PostId="3928" RevisionGUID="7b8ae9a7-7cbb-4944-a5bf-c522a47fae2d" CreationDate="2016-08-28T21:28:10.987" UserId="48" Text="Both methods end up doing the same calculations when you break it down.&#xD;&#xA;&#xD;&#xA;Rotating a vector $u$ with a matrix:&#xD;&#xA;$$\begin{bmatrix}\cos\theta &amp; -\sin\theta \\ \sin\theta &amp; \cos\theta\end{bmatrix} \begin{bmatrix}u_x\\u_y\end{bmatrix} =&#xD;&#xA;\begin{bmatrix}u_x \cos\theta - u_y\sin\theta \\ u_x \sin\theta + u_y \cos\theta \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Rotating a vector $u$ using complex numbers:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;(\cos\theta + i\sin\theta)(u_x + iu_y) &amp;= u_x\cos\theta + iu_y\cos\theta + iu_x\sin\theta - u_y\sin\theta \\&#xD;&#xA;&amp;=(u_x\cos\theta - u_y\sin\theta) + i(u_x\sin\theta + u_y\cos\theta)&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;I wouldn't expect either one to be appreciably faster or slower than the other, since they all end up doing the same set of basic operations, i.e. 4 multiplies and 2 adds.&#xD;&#xA;&#xD;&#xA;Conceivably, complex numbers could be faster when you have a large number of rotations stored in an array, because they have only two components instead of four and therefore more of them fit into each cache line.&#xD;&#xA;&#xD;&#xA;&gt; On a related note, is there some spatial transformation that complex numbers can do but matrices cannot?&#xD;&#xA;&#xD;&#xA;No. Matrices are more general than complex numbers. Any complex number $z$ can be represented by a matrix as:&#xD;&#xA;$$\begin{bmatrix}\text{Re}(z) &amp; -\text{Im}(z) \\ \text{Im}(z) &amp; \text{Re}(z) \end{bmatrix}$$&#xD;&#xA;This corresponds to rotation by the phase of $z$ combined with scaling by the magnitude of $z$. Complex numbers can only represent rotation and uniform scaling. Matrices can represent those, but also nonuniform scaling and shearing. Another way to see it is that complex numbers have only two degrees of freedom, while 2×2 matrices have four degrees of freedom." ContentLicense="CC BY-SA 3.0" />
  <row Id="8388" PostHistoryTypeId="2" PostId="3929" RevisionGUID="69e9e282-be71-491d-8454-1feafb919336" CreationDate="2016-08-28T22:03:42.680" UserId="5003" Text="I am trying to figure out an algorithm for handling an otherwise simple animation. I have a progress bar that &quot;ticks down&quot; from a user specified amount of time to zero. I wanted a smooth animation, so I chose to update it in a timer class at approximately 24 frames-per-second. This works just fine.&#xD;&#xA;&#xD;&#xA;The problem I am trying to figure out is how to speed up the animation at an arbitrary point in the animation cycle (the user will initiate it by pressing an &quot;Update Now&quot; type of button. So, say the timer/progress bar is running down from a 10 minute wait and they press &quot;Update Now&quot;, I want the animation to &quot;hurry up&quot; and complete. This new rate would be as if the total wait time was 1 second. To put it another way, if the user waited half way though the normal timer even and pressed &quot;Update Now&quot;, then there would only be a half-second left to animate. If they waited 75% of the time, then there would only be 250 ms left to animate, etc.&#xD;&#xA;&#xD;&#xA;I have tried too many things to list and all have failed. Most notably, the progress bar *jumps* to a later time, and then finishes the animation--I can't get it to animate fast from the point where it has left off. I'm sure this is easy, I just can't quite grasp the correct algorithm.&#xD;&#xA;&#xD;&#xA;Givens:&#xD;&#xA;&#xD;&#xA; - My timer is running at 24 frames-per-second for a smooth animation.&#xD;&#xA; - My current algorithm works by taking the countdown timer's initial value (in ms) and subtracting how much time has passed, also in ms, then calculating what percentage of time has passed for the progress bar.&#xD;&#xA; - One thing I tried of note, that does **not** work for me was to have a counter of how many frames I had to consume, and subtract a frame count every time my timer even entered. I then *assumed* I could increase the frame rate to simulate the faster time. This all failed miserably. I'm not sure why, but increasing the frame rate did not appear to do much on my computer--the speed increased, but not to the extent I wished for. Further, my timer is not reliable enough even when **not** doing the faster animation. It would gain approximately 1 second for every 10 seconds of original wait time. So, that method is off the table. If the user wanted to wait 60 seconds and didn't press &quot;Update Now&quot;, then the timer would consistently run for approximately 70 seconds, a 120 seconds would become 140 seconds, etc. I'm doing this on an i7-6700 and the CPU is not strained (7-8% total), but something is causing the timer to be otherwise unreliable...&#xD;&#xA;&#xD;&#xA;I'm sure the answer will turn out easy, but any help would be appreciated. I'm doing this in c#, but I am sure I can figure out any algorithm presented and translate it if needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="8389" PostHistoryTypeId="1" PostId="3929" RevisionGUID="69e9e282-be71-491d-8454-1feafb919336" CreationDate="2016-08-28T22:03:42.680" UserId="5003" Text="Algorithm for adjusting the speed of a progress bar animation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8390" PostHistoryTypeId="3" PostId="3929" RevisionGUID="69e9e282-be71-491d-8454-1feafb919336" CreationDate="2016-08-28T22:03:42.680" UserId="5003" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8391" PostHistoryTypeId="5" PostId="3927" RevisionGUID="d999df66-0d29-4832-91d9-e82a40ee0798" CreationDate="2016-08-29T05:10:58.217" UserId="38" Comment="edited body" Text="This is the same problem as the rotation about an axis. What you need is a matrix (any matrix) that satisfies the following corner constraint: one axis must point toward $(-2, 2, 0)$ in the case of a rotation this matrix must be a rotation matrix, in the case of a planar mirror it just has to span the 3D space. But since we know how to make a an arbitrary rotation matrix we use same approach.&#xD;&#xA;&#xD;&#xA;1. Pick any vector(u) thats not paralell to normal (n)&#xD;&#xA;2. take cross product of u and n for b&#xD;&#xA;3. take cross product of n and b for a&#xD;&#xA;&#xD;&#xA;you now have now an arbitrary rotation matrix with one axis defined using vectors n, b and a. Otherwise same as the last question.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8392" PostHistoryTypeId="5" PostId="3923" RevisionGUID="c13a7246-675f-440d-8409-2283c3192869" CreationDate="2016-08-29T07:49:27.127" UserId="38" Comment="added 249 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed). You could also use one of the nomstandard kernel internal formats like Parasolid as its also commonly supported. Most other formats are polygon data so not suitable.&#xD;&#xA;&#xD;&#xA;I would explore an alternative option to writing your own exporter, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. Most CAD applications have a COM API's (dont know about NX most likely, but both creo and catia do have this) so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and its usually less work to set up than using just the kernel).&#xD;&#xA;&#xD;&#xA;[![sweep][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Sweept with spine angle $60 \cos(4 t)+110$ and polar trajectory with $r = \cos(4 t)$ in Creo. All input from program injection.&#xD;&#xA;&#xD;&#xA;So the approach depends on why you want to do what you do. And what your budget/time constraint is.&#xD;&#xA;&#xD;&#xA;PS: NURBS (the underlying format of CAD data) solutions are not nesseserily analytic, but parameric fits to analytical solutions. Sometimes these are exact sometimes not so exact as not all fubtions can be fitted to rational splines. (though many can)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ufq1l.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8393" PostHistoryTypeId="5" PostId="3923" RevisionGUID="c3b55e6e-1428-4fb1-bc5c-1ef347970104" CreationDate="2016-08-29T07:56:31.130" UserId="38" Comment="added 53 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed). You could also use one of the nomstandard kernel internal formats like Parasolid as its also commonly supported. Most other formats are polygon data so not suitable.&#xD;&#xA;&#xD;&#xA;I would explore an alternative option to writing your own exporter, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. Most CAD applications have a COM API's (dont know about NX most likely, but both creo and catia do have this) so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and its usually less work to set up than using just the kernel).&#xD;&#xA;&#xD;&#xA;[![sweep][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Sweept with spine angle $60 \cos(4 t)+110$ and polar trajectory with $r = \cos(4 t)$ in Creo. All input from program injection.&#xD;&#xA;&#xD;&#xA;So the approach depends on why you want to do what you do. And what your budget/time constraint is.&#xD;&#xA;&#xD;&#xA;**PS**: NURBS (the underlying format of CAD data) solutions are not nesseserily analytic, but parameric fits to analytical solutions. Sometimes these are exact sometimes not so exact as not all functions can be fitted to rational spline (though many can). Even when they can fitting is a more general solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ufq1l.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8394" PostHistoryTypeId="5" PostId="3923" RevisionGUID="932ca4d1-09e3-45a8-9dcc-12625200a242" CreationDate="2016-08-29T08:02:24.473" UserId="38" Comment="added 38 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed, and lots of money is wasted on paper). You could also use one of the nomstandard kernel internal formats like Parasolid as its also commonly supported. Most other formats are polygon data so not suitable.&#xD;&#xA;&#xD;&#xA;I would explore an alternative option to writing your own exporter, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. Most CAD applications have a COM API's (dont know about NX most likely, but both creo and catia do have this) so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and its usually less work to set up than using just the kernel).&#xD;&#xA;&#xD;&#xA;[![sweep][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Sweept with spine angle $60 \cos(4 t)+110$ and polar trajectory with $r = \cos(4 t)$ in Creo. All input from program injection.&#xD;&#xA;&#xD;&#xA;So the approach depends on why you want to do what you do. And what your budget/time constraint is.&#xD;&#xA;&#xD;&#xA;**PS**: NURBS (the underlying format of CAD data) solutions are not nesseserily analytic, but parameric fits to analytical solutions. Sometimes these are exact sometimes not so exact as not all functions can be fitted to rational spline (though many can). Even when they can fitting is a more general solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ufq1l.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8395" PostHistoryTypeId="2" PostId="3930" RevisionGUID="1cf38b73-bb1f-485c-ad0b-81feb1c801c3" CreationDate="2016-08-29T10:29:04.487" UserId="137" Text="You will need to persist the percent completed across frames and update it based on the time elapsed since last frame and the total time. &#xD;&#xA;&#xD;&#xA;    percentCompleted = 0;&#xD;&#xA;    totalTime = 10; //in seconds&#xD;&#xA;    &#xD;&#xA;    void onUpdate(float deltaTime){&#xD;&#xA;        percentCompleted += deltaTime/totalTime;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void hurryUp(){&#xD;&#xA;        totalTime = 1;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8396" PostHistoryTypeId="5" PostId="3923" RevisionGUID="7df6bb83-3651-49e8-9d1f-432bef041818" CreationDate="2016-08-29T12:32:31.617" UserId="38" Comment="added 2 characters in body" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed, and lots of money is wasted on paper). You could also use one of the nomstandard kernel internal formats like Parasolid as its also commonly supported. Most other formats are polygon data so not suitable.&#xD;&#xA;&#xD;&#xA;I would explore an alternative option to writing your own exporter, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. Most CAD applications have a COM API's (dont know about NX most likely, but both creo and catia do have this) so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and its usually less work to set up than using just the kernel).&#xD;&#xA;&#xD;&#xA;[![sweep][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Sweept with spine angle $60 \cos(4 t)+110$ and polar trajectory with $r = \cos(4 t)+3$ in Creo. All input from program injection.&#xD;&#xA;&#xD;&#xA;So the approach depends on why you want to do what you do. And what your budget/time constraint is.&#xD;&#xA;&#xD;&#xA;**PS**: NURBS (the underlying format of CAD data) solutions are not nesseserily analytic, but parameric fits to analytical solutions. Sometimes these are exact sometimes not so exact as not all functions can be fitted to rational spline (though many can). Even when they can fitting is a more general solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ufq1l.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8398" PostHistoryTypeId="5" PostId="3927" RevisionGUID="a68f4aa2-ecab-47aa-920a-cffa576b7288" CreationDate="2016-08-29T13:58:39.427" UserId="231" Comment="Link to last question for future readers - please revert if I have misunderstood" Text="This is the same problem as the rotation about an axis. What you need is a matrix (any matrix) that satisfies the following corner constraint: one axis must point toward $(-2, 2, 0)$ in the case of a rotation this matrix must be a rotation matrix, in the case of a planar mirror it just has to span the 3D space. But since we know how to make an arbitrary rotation matrix we use the same approach.&#xD;&#xA;&#xD;&#xA;1. Pick any vector (u) that's not parallel to the normal (n)&#xD;&#xA;2. Take cross product of u and n for b&#xD;&#xA;3. Take cross product of n and b for a&#xD;&#xA;&#xD;&#xA;You now have an arbitrary rotation matrix with one axis defined using vectors n, b and a. Otherwise same as [the last question].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [the last question]: http://computergraphics.stackexchange.com/questions/3911/transformation-matrices" ContentLicense="CC BY-SA 3.0" />
  <row Id="8399" PostHistoryTypeId="5" PostId="3910" RevisionGUID="6c251cbd-b5f1-4e70-bcbb-5178da365bf1" CreationDate="2016-08-29T15:02:28.923" UserId="4992" Comment="added 279 characters in body" Text="I have to create a file describing a 3d surface with the following properties:&#xD;&#xA;&#xD;&#xA;- a circular arc cross section is swept along a closed 2d curve spine defined with equations&#xD;&#xA;- the normal direction of the arc is not always tangential to the spine, the direction is defined with an equation&#xD;&#xA;- the surface should be analytic (defined by equations), but a tesselated surface is also acceptable (with an external script I can derive the x,y,z coords of the vertexes for a tesselated surface)&#xD;&#xA;- the file will be modified by an external script (python), so it should be editable with text editor&#xD;&#xA;- the file should be opened by Creo(Proe), Catia and NX&#xD;&#xA;&#xD;&#xA;The question:  &#xD;&#xA;Which is the best file format for making this feature?&#xD;&#xA;&#xD;&#xA;What I tried:&#xD;&#xA;&#xD;&#xA;- step: buying the ISO standard is unavoidable, as I cannot figure out on my own how the definition works&#xD;&#xA;- vrml: only tesselated seems to be feasible&#xD;&#xA;- x3d: same as vrml, as it has a sweep (extrusion) feature, but the normal direction is the same as the local spine direction, and Proe does not seem to open it&#xD;&#xA;&#xD;&#xA;The egg-shaped curve is the trajectory, the arc is the curve to be swept along it.&#xD;&#xA;The plane of the arc is close to parallel to the plane &quot;Top&quot;, but this angle varies between 0-30 degrees&#xD;&#xA;[![explanation for the feature][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GJuRL.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8403" PostHistoryTypeId="2" PostId="3931" RevisionGUID="ab75e25e-1c96-44ad-84ac-7e5301541785" CreationDate="2016-08-30T07:23:10.793" UserId="2308" Text="I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on is thus): I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this wierdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.&#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasnt difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS wierd is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8404" PostHistoryTypeId="1" PostId="3931" RevisionGUID="ab75e25e-1c96-44ad-84ac-7e5301541785" CreationDate="2016-08-30T07:23:10.793" UserId="2308" Text="Weird rendering in rectangle mesh shader AKA Why has my basic shader become a modern art generator?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8405" PostHistoryTypeId="3" PostId="3931" RevisionGUID="ab75e25e-1c96-44ad-84ac-7e5301541785" CreationDate="2016-08-30T07:23:10.793" UserId="2308" Text="|mesh|artifacts|tesselation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8408" PostHistoryTypeId="10" PostId="3881" RevisionGUID="8a94edc5-e7d6-4772-918e-09d8f5bf5f25" CreationDate="2016-08-30T16:52:07.133" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:273,&quot;DisplayName&quot;:&quot;Dragonseel&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8409" PostHistoryTypeId="2" PostId="3932" RevisionGUID="d4527b68-5cc3-43cb-b842-744a0029e0db" CreationDate="2016-08-30T21:33:23.940" UserId="4705" Text="After watching [this video](https://www.youtube.com/watch?v=kYB8IZa5AuE) on matrices, I tried to make a simple animation of 2D linear transformations. Starting with a set of 2D points in a grid, I applied a 2x2 matrix to each point and obtained a set of transformed points.&#xD;&#xA;&#xD;&#xA;I'm not sure how to animate the transition between the initial and final states. At first, I made each point move along the straight path between its initial and final position. This caused problems for rotation matrices. For example, a 180$^{\circ}$ rotation should show the points rotate about the origin in circular arcs, but my method made it look like the whole grid flipped around, without rotating. &#xD;&#xA;&#xD;&#xA;A better rotation animation can be made by applying a very small rotation, say 1$^{\circ}$, multiple times. The matrix for a 1$^{\circ}$ rotation is close to the identity matrix:&#xD;&#xA;$$\begin{bmatrix} 0.9998 &amp; -0.0175 \\ 0.0175  &amp;  0.9998 \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Is there some general formula that can generate a differential transformation matrix, given the full transformation matrix? I would like it to work for any 2x2 matrix, without needing to specify the type of transformation." ContentLicense="CC BY-SA 3.0" />
  <row Id="8410" PostHistoryTypeId="1" PostId="3932" RevisionGUID="d4527b68-5cc3-43cb-b842-744a0029e0db" CreationDate="2016-08-30T21:33:23.940" UserId="4705" Text="Animating a smooth linear transformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8411" PostHistoryTypeId="3" PostId="3932" RevisionGUID="d4527b68-5cc3-43cb-b842-744a0029e0db" CreationDate="2016-08-30T21:33:23.940" UserId="4705" Text="|transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8413" PostHistoryTypeId="5" PostId="3911" RevisionGUID="8e1055f2-3b0c-4841-9e84-f14221b4f51a" CreationDate="2016-08-31T07:28:05.017" UserId="182" Comment="Minor edit to fix grammar and quote the problem while at it." Text="Consider the following problem and its answer:&#xD;&#xA;&#xD;&#xA;&gt; Given 3 points in 3D: $A=(A_x,A_y,A_z);   B=(B_x,B_y,B_z)  ;    C=(C_x,C_y,C_z)$&#xD;&#xA;&gt;&#xD;&#xA;&gt; Find the transformation matrix (in homogeneous coordinates) that performs a reflection around the plane spanned by the given 3 points.&#xD;&#xA;&gt;&#xD;&#xA;&gt; Answer:&#xD;&#xA;&gt;&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;1. Can anyone explain why this answer is correct?&#xD;&#xA;2. Shouldn't normalization be performed by dividing by $|C-A|$ and $|B-A|$ instead of $|AC|$ and $|AB|$?&#xD;&#xA;3. Wouldn't we want to reflect on $uv$ plane (and then the -1 would be one row below)?&#xD;&#xA;4. I saw a similar question where you had to rotate around a vector and not a surface, and then we created $v$ with $v=u\times(0,0,1)^T$ (the vector was $P_1-P_0$ and $u=\dfrac{P_1-P_0}{|P_1-P_0|}$. What's the difference?&#xD;&#xA;5. In general, what is the rule of thumb when finding the $u,v,z$ cartesian system of a given object (plane, line, point etc)?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WhjIw.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8414" PostHistoryTypeId="33" PostId="1759" RevisionGUID="cabc0c2d-74e1-402f-ae09-bfa59515dfb5" CreationDate="2016-08-31T13:03:17.380" UserId="231" Comment="20" />
  <row Id="8415" PostHistoryTypeId="5" PostId="3931" RevisionGUID="e4eae068-4566-45d0-8996-17863ef6d5dd" CreationDate="2016-08-31T13:28:30.900" UserId="231" Comment="Apply swift syntax highlighting" Text="&lt;!-- language-all: lang-swift --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on) is thus: I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this weirdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.  &#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasn't difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS weird is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8416" PostHistoryTypeId="2" PostId="3933" RevisionGUID="9dfaa75e-413c-4493-8839-6486c0249f05" CreationDate="2016-08-31T14:45:32.937" UserId="5013" Text="This:&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, false, 7*4, 0);&#xD;&#xA;    glVertexAttribPointer(3, 4, GL_FLOAT, false, 7*4, 3*4);&#xD;&#xA;should be this:&#xD;&#xA;&#xD;&#xA;	GLint posAttrib = glGetAttribLocation(yourShader, &quot;position&quot;);&#xD;&#xA;	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    glVertexAttribPointer(posAttrib, 3, GL_FLOAT, false, sizeof(float)*7, 0);&#xD;&#xA;&#xD;&#xA;    posAttrib = glGetAttribLocation(yourShader, &quot;i_color&quot;);&#xD;&#xA;	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    glVertexAttribPointer(posAttrib, 4, GL_FLOAT, false, sizeof(float)*7, sizeof(float)*2);&#xD;&#xA;&#xD;&#xA;as both are byte offsets, not array indices. A GLfloat is currently defined as 32 bit = 4 Byte, but you should never hard code that.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8417" PostHistoryTypeId="5" PostId="3931" RevisionGUID="3c10666a-172a-4f3e-90d1-209c0bea2452" CreationDate="2016-09-01T06:47:39.737" UserId="2308" Comment="added 1066 characters in body" Text="&lt;!-- language-all: lang-swift --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on) is thus: I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this weirdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.  &#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasn't difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS weird is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Here is the matrix code&#xD;&#xA;&#xD;&#xA;    var orthographicMatrix:[GLfloat] = []&#xD;&#xA;        &#xD;&#xA;        func buildMatrix()&#xD;&#xA;        {&#xD;&#xA;            orthographicMatrix = glkitmatrixtoarray(GLKMatrix4MakeOrtho(0, GLfloat(width), 0, GLfloat(height), -100, 100))&#xD;&#xA;            //Storage.upScaleFactor&#xD;&#xA;        }&#xD;&#xA;        func glkitmatrixtoarray(mat: GLKMatrix4) -&gt; [GLfloat]&#xD;&#xA;        {&#xD;&#xA;            var buildme:[GLfloat] = []&#xD;&#xA;            buildme.append(mat.m.0)&#xD;&#xA;            buildme.append(mat.m.1)&#xD;&#xA;            buildme.append(mat.m.2)&#xD;&#xA;            buildme.append(mat.m.3)&#xD;&#xA;            buildme.append(mat.m.4)&#xD;&#xA;            buildme.append(mat.m.5)&#xD;&#xA;            buildme.append(mat.m.6)&#xD;&#xA;            buildme.append(mat.m.7)&#xD;&#xA;            buildme.append(mat.m.8)&#xD;&#xA;            buildme.append(mat.m.9)&#xD;&#xA;            buildme.append(mat.m.10)&#xD;&#xA;            buildme.append(mat.m.11)&#xD;&#xA;            buildme.append(mat.m.12)&#xD;&#xA;            buildme.append(mat.m.13)&#xD;&#xA;            buildme.append(mat.m.14)&#xD;&#xA;            buildme.append(mat.m.15)&#xD;&#xA;            return buildme&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8418" PostHistoryTypeId="5" PostId="3931" RevisionGUID="ef30c8b5-b180-47bd-8826-96552f9c8d65" CreationDate="2016-09-01T07:07:04.397" UserId="2308" Comment="added 218 characters in body" Text="&lt;!-- language-all: lang-swift --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on) is thus: I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this weirdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.  &#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasn't difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS weird is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Here is the matrix code&#xD;&#xA;&#xD;&#xA;    var orthographicMatrix:[GLfloat] = []&#xD;&#xA;        &#xD;&#xA;        func buildMatrix()&#xD;&#xA;        {&#xD;&#xA;            orthographicMatrix = glkitmatrixtoarray(GLKMatrix4MakeOrtho(0, GLfloat(width), 0, GLfloat(height), -100, 100))&#xD;&#xA;            //Storage.upScaleFactor&#xD;&#xA;        }&#xD;&#xA;        func glkitmatrixtoarray(mat: GLKMatrix4) -&gt; [GLfloat]&#xD;&#xA;        {&#xD;&#xA;            var buildme:[GLfloat] = []&#xD;&#xA;            buildme.append(mat.m.0)&#xD;&#xA;            buildme.append(mat.m.1)&#xD;&#xA;            buildme.append(mat.m.2)&#xD;&#xA;            buildme.append(mat.m.3)&#xD;&#xA;            buildme.append(mat.m.4)&#xD;&#xA;            buildme.append(mat.m.5)&#xD;&#xA;            buildme.append(mat.m.6)&#xD;&#xA;            buildme.append(mat.m.7)&#xD;&#xA;            buildme.append(mat.m.8)&#xD;&#xA;            buildme.append(mat.m.9)&#xD;&#xA;            buildme.append(mat.m.10)&#xD;&#xA;            buildme.append(mat.m.11)&#xD;&#xA;            buildme.append(mat.m.12)&#xD;&#xA;            buildme.append(mat.m.13)&#xD;&#xA;            buildme.append(mat.m.14)&#xD;&#xA;            buildme.append(mat.m.15)&#xD;&#xA;            return buildme&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Now the issue is not the abstract art but that the rectangle only goes half way nomater the scale factor. Notice the jagged edge&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jBcCz.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8419" PostHistoryTypeId="33" PostId="3931" RevisionGUID="c814e1ac-8bdf-4bb1-b4e3-eab44df4d1c9" CreationDate="2016-09-01T07:46:49.437" UserId="2308" Comment="21" />
  <row Id="8420" PostHistoryTypeId="2" PostId="3934" RevisionGUID="7038f4a3-7e09-48dd-99f4-eac6bd03b3c8" CreationDate="2016-09-01T08:27:16.253" UserId="3073" Text="I think you are not constructing the indice buffer correctly. Firstly you only need 1 degenerate vertice to terminate each triangle-strip row. &#xD;&#xA;&#xD;&#xA;You also should not need any special handling for odd/even rows. You can emit a single triangle-strip per loop.&#xD;&#xA;&#xD;&#xA;Your indice loop should look something like :&#xD;&#xA; &#xD;&#xA;    var index:Int = 0&#xD;&#xA;    for i in 0..&lt;rSimHeight - 1&#xD;&#xA;    {&#xD;&#xA;        for j in 0..&lt;rSimWidth&#xD;&#xA;        {&#xD;&#xA;        	ind[index++] = Indicie(i*rSimWidth + j);		// current row&#xD;&#xA;        	ind[index++] = Indicie((i+1)*rSimWidth + j);	// row below&#xD;&#xA;        &#xD;&#xA;        	if(j == rSimWidth - 1) {&#xD;&#xA;        		ind[index] = ind[index-1];		// degenerate vertice / row termination&#xD;&#xA;        		index++;&#xD;&#xA;        	}&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This also means you indice count is defined like :&#xD;&#xA;&#xD;&#xA;    int triStripRows = rSimHeight - 1;&#xD;&#xA;    int indicesPerRow = (rSimWidth * 2) + 1&#xD;&#xA;    int totalIndices = indicesPerRow * triStripRows;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8421" PostHistoryTypeId="5" PostId="3931" RevisionGUID="57d48b9d-70fe-4ce9-97e2-c612edb7e110" CreationDate="2016-09-01T08:38:45.323" UserId="2308" Comment="added 191 characters in body" Text="&lt;!-- language-all: lang-swift --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on) is thus: I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this weirdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.  &#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasn't difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS weird is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Here is the matrix code&#xD;&#xA;&#xD;&#xA;    var orthographicMatrix:[GLfloat] = []&#xD;&#xA;        &#xD;&#xA;        func buildMatrix()&#xD;&#xA;        {&#xD;&#xA;            orthographicMatrix = glkitmatrixtoarray(GLKMatrix4MakeOrtho(0, GLfloat(width), 0, GLfloat(height), -100, 100))&#xD;&#xA;            //Storage.upScaleFactor&#xD;&#xA;        }&#xD;&#xA;        func glkitmatrixtoarray(mat: GLKMatrix4) -&gt; [GLfloat]&#xD;&#xA;        {&#xD;&#xA;            var buildme:[GLfloat] = []&#xD;&#xA;            buildme.append(mat.m.0)&#xD;&#xA;            buildme.append(mat.m.1)&#xD;&#xA;            buildme.append(mat.m.2)&#xD;&#xA;            buildme.append(mat.m.3)&#xD;&#xA;            buildme.append(mat.m.4)&#xD;&#xA;            buildme.append(mat.m.5)&#xD;&#xA;            buildme.append(mat.m.6)&#xD;&#xA;            buildme.append(mat.m.7)&#xD;&#xA;            buildme.append(mat.m.8)&#xD;&#xA;            buildme.append(mat.m.9)&#xD;&#xA;            buildme.append(mat.m.10)&#xD;&#xA;            buildme.append(mat.m.11)&#xD;&#xA;            buildme.append(mat.m.12)&#xD;&#xA;            buildme.append(mat.m.13)&#xD;&#xA;            buildme.append(mat.m.14)&#xD;&#xA;            buildme.append(mat.m.15)&#xD;&#xA;            return buildme&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Now the issue is not the abstract art but that the rectangle only goes half way nomater the scale factor. Notice the jagged edge&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In apples frame debugger you can see the outline of all the triangles that it draws it looks like this:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jBcCz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/a5uoq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8422" PostHistoryTypeId="5" PostId="3931" RevisionGUID="e2457e80-4e58-4e75-abd7-0f965b144b24" CreationDate="2016-09-01T08:44:19.740" UserId="2308" Comment="added 191 characters in body" Text="&lt;!-- language-all: lang-swift --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on) is thus: I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this weirdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.  &#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasn't difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS weird is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Here is the matrix code&#xD;&#xA;&#xD;&#xA;    var orthographicMatrix:[GLfloat] = []&#xD;&#xA;        &#xD;&#xA;        func buildMatrix()&#xD;&#xA;        {&#xD;&#xA;            orthographicMatrix = glkitmatrixtoarray(GLKMatrix4MakeOrtho(0, GLfloat(width), 0, GLfloat(height), -100, 100))&#xD;&#xA;            //Storage.upScaleFactor&#xD;&#xA;        }&#xD;&#xA;        func glkitmatrixtoarray(mat: GLKMatrix4) -&gt; [GLfloat]&#xD;&#xA;        {&#xD;&#xA;            var buildme:[GLfloat] = []&#xD;&#xA;            buildme.append(mat.m.0)&#xD;&#xA;            buildme.append(mat.m.1)&#xD;&#xA;            buildme.append(mat.m.2)&#xD;&#xA;            buildme.append(mat.m.3)&#xD;&#xA;            buildme.append(mat.m.4)&#xD;&#xA;            buildme.append(mat.m.5)&#xD;&#xA;            buildme.append(mat.m.6)&#xD;&#xA;            buildme.append(mat.m.7)&#xD;&#xA;            buildme.append(mat.m.8)&#xD;&#xA;            buildme.append(mat.m.9)&#xD;&#xA;            buildme.append(mat.m.10)&#xD;&#xA;            buildme.append(mat.m.11)&#xD;&#xA;            buildme.append(mat.m.12)&#xD;&#xA;            buildme.append(mat.m.13)&#xD;&#xA;            buildme.append(mat.m.14)&#xD;&#xA;            buildme.append(mat.m.15)&#xD;&#xA;            return buildme&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Now the issue is not the abstract art but that the rectangle only goes half way nomater the scale factor. Notice the jagged edge&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In apples frame debugger you can see the outline of all the triangles that it draws it looks like this:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Could it be this line that is causing all the trouble `let index = (yy*rSimWidth + xx) * 2`&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jBcCz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/a5uoq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8423" PostHistoryTypeId="5" PostId="3934" RevisionGUID="24da86a7-05c5-423a-9755-c40bf37ce1a1" CreationDate="2016-09-01T08:56:56.293" UserId="3073" Comment="deleted 61 characters in body" Text="I think you are not constructing the indice buffer correctly. Firstly you only need 1 degenerate vertice to terminate each triangle-strip row. &#xD;&#xA;&#xD;&#xA;You also should not need any special handling for odd/even rows. You can emit a single triangle-strip per loop.&#xD;&#xA;&#xD;&#xA;Your indice loop should look something like :&#xD;&#xA; &#xD;&#xA;    var index:Int = 0&#xD;&#xA;    for i in 0..&lt;rSimHeight - 1&#xD;&#xA;    {&#xD;&#xA;        for j in 0..&lt;rSimWidth&#xD;&#xA;        {&#xD;&#xA;        	ind[index++] = Indicie(i*rSimWidth + j);		// current row&#xD;&#xA;        	ind[index++] = Indicie((i+1)*rSimWidth + j);	// row below&#xD;&#xA;        }&#xD;&#xA;        ind[index] = ind[index-1];		// degenerate vertice / row termination&#xD;&#xA;        index++;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This also means you indice count is defined like :&#xD;&#xA;&#xD;&#xA;    int triStripRows = rSimHeight - 1;&#xD;&#xA;    int indicesPerRow = (rSimWidth * 2) + 1&#xD;&#xA;    int totalIndices = indicesPerRow * triStripRows;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8424" PostHistoryTypeId="5" PostId="3934" RevisionGUID="f1721080-6f02-4b51-bde0-c9499c41c002" CreationDate="2016-09-01T09:00:45.490" UserId="231" Comment="Minor typos" Text="I think you are not constructing the index buffer correctly. Firstly you only need 1 degenerate vertex to terminate each triangle-strip row. &#xD;&#xA;&#xD;&#xA;You also should not need any special handling for odd/even rows. You can emit a single triangle-strip per loop.&#xD;&#xA;&#xD;&#xA;Your index loop should look something like :&#xD;&#xA; &#xD;&#xA;    var index:Int = 0&#xD;&#xA;    for i in 0..&lt;rSimHeight - 1&#xD;&#xA;    {&#xD;&#xA;        for j in 0..&lt;rSimWidth&#xD;&#xA;        {&#xD;&#xA;        	ind[index++] = Indicie(i*rSimWidth + j);		// current row&#xD;&#xA;        	ind[index++] = Indicie((i+1)*rSimWidth + j);	// row below&#xD;&#xA;        }&#xD;&#xA;        ind[index] = ind[index-1];		// degenerate vertex / row termination&#xD;&#xA;        index++;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This also means your index count is defined like:&#xD;&#xA;&#xD;&#xA;    int triStripRows = rSimHeight - 1;&#xD;&#xA;    int indicesPerRow = (rSimWidth * 2) + 1&#xD;&#xA;    int totalIndices = indicesPerRow * triStripRows;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8425" PostHistoryTypeId="5" PostId="3931" RevisionGUID="692540ad-5aeb-4d25-9f21-f94b29b1ebed" CreationDate="2016-09-01T09:40:01.463" UserId="2308" Comment="added 416 characters in body" Text="&lt;!-- language-all: lang-swift --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am trying to translate an old (2013) bit of code from Apple from objective C to Swift with some modifications I need for my simulation.&#xD;&#xA;&#xD;&#xA;The code I am translating can be found [here][1]&#xD;&#xA;&#xD;&#xA;To make translation easier I have broken the simulation into parts. The part I am working on now (and am stuck on) is thus: I simply need to draw your general full screen texture coords shader however I need it to be broken up into a grid. If I have a grid scale factor 1 then each pixel on the screen will get a triangle and that will make up the mesh. However if I put in 10 then there will be a triangle every 10 pixels. Essentially this is the resolution of my simulation.&#xD;&#xA;&#xD;&#xA;My problem is these images (the numbers indicate the scale factor of the pond):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;For some reason rather then drawing a full screen texture coord drawing it draws this weirdness (Some of these honestly belong in a modern art museum). I really have no clue where to look in my code to find this issue, my guess is it is the indices.  &#xD;&#xA;You would see the individual triangles on the top of the 1st and second image but I killed the resolution so it wasn't difficult to upload to SO.&#xD;&#xA;&#xD;&#xA;So first off here is how I define all of the arrays that make up this simulation:&#xD;&#xA;&#xD;&#xA;    var rSimWidth:Int = 0&#xD;&#xA;    var rSimHeight:Int = 0&#xD;&#xA;    var mesh:[GLfloat] = []&#xD;&#xA;    var tex:[GLfloat] = []&#xD;&#xA;    var ind:[Indicie] = []&#xD;&#xA;    &#xD;&#xA;    var realWidth:Int = 0&#xD;&#xA;    var realHeight:Int = 0&#xD;&#xA;	&#xD;&#xA;	//In this case width = 568, height = 320, mpp varies look at top of picture&#xD;&#xA;    init(width: Int, height: Int, mpp: Int)&#xD;&#xA;    {&#xD;&#xA;        rSimWidth = width / mpp&#xD;&#xA;        rSimHeight = height / mpp&#xD;&#xA;        rSimWidth += 1; rSimHeight += 1&#xD;&#xA;        realWidth = width&#xD;&#xA;        realHeight = height&#xD;&#xA;        &#xD;&#xA;        mesh = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        tex = [GLfloat](count: rSimWidth * rSimHeight * 2, repeatedValue: 0)&#xD;&#xA;        ind = [Indicie](count: (rSimHeight-1)*(rSimWidth*2+2), repeatedValue: 0)&#xD;&#xA;        &#xD;&#xA;        print(&quot;Screen is (\(width) x \(height))\tPond is (\(rSimWidth) x \(rSimHeight))\tScreenSA: \(width * height)\tPond sa: \(rSimWidth * rSimHeight)\tMP: \(mpp) \((rSimWidth * rSimHeight) * mpp)&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I fill up the indices. I had difficulties with this because of the data type. I believe for indices I am supposed to use GLushort however on my system the maximum value is 65,535 . This value was quickly overflowed by the indice generation so I had to switch it to &quot;Int&quot;. There is a typedef &quot;Indicie&quot; so I can change the type of data in the indices easily. What I find odd is when I ramped up the simulation resolution in the apple code I never had an overflow issue.&#xD;&#xA;&#xD;&#xA;        var index:Int = 0&#xD;&#xA;        for i in 0..&lt;rSimHeight - 1&#xD;&#xA;        {&#xD;&#xA;            for j in 0..&lt;rSimWidth&#xD;&#xA;            {&#xD;&#xA;                if (i%2==0)//X is even&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    //(114 + 1) * 569 + 101&#xD;&#xA;                    //&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENERATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    if (j == 0)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie((i+1)*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                    &#xD;&#xA;                    ind[index] = Indicie((i + 1) * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    ind[index] = Indicie(i * rSimWidth + j)&#xD;&#xA;                    index += 1&#xD;&#xA;                    &#xD;&#xA;                    if (j == rSimWidth - 1)&#xD;&#xA;                    {&#xD;&#xA;                        //DEGENRATE TRIANGLE&#xD;&#xA;                        ind[index] = Indicie(i*rSimWidth + j)&#xD;&#xA;                        index += 1&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In case you wish to see the position and tc code&#xD;&#xA;&#xD;&#xA;      for yy in 0..&lt;rSimHeight&#xD;&#xA;        {let y = GLfloat(yy);&#xD;&#xA;            for xx in 0..&lt;rSimWidth&#xD;&#xA;            {let x = GLfloat(xx);&#xD;&#xA;                let index = (yy*rSimWidth + xx) * 2&#xD;&#xA;                tex[index] = x / GLfloat(rSimWidth - 1)&#xD;&#xA;                tex[index + 1] = y / GLfloat(rSimHeight - 1)&#xD;&#xA;                &#xD;&#xA;                mesh[index] = tex[index] * GLfloat(realWidth)&#xD;&#xA;                mesh[index + 1] = tex[index + 1] * GLfloat(realHeight)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Here is the drawing code&#xD;&#xA;&#xD;&#xA;         glUseProgram(shade.progId)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        let posLoc = GLuint(glGetAttribLocation(shade.progId, &quot;pos&quot;))&#xD;&#xA;        let texLoc = GLuint(glGetAttribLocation(shade.progId, &quot;tc&quot;))&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);&#xD;&#xA;        glBufferData(GLenum(GL_ARRAY_BUFFER), sim.tex.count * sizeof(GLfloat), sim.tex, GLenum(GL_DYNAMIC_DRAW));&#xD;&#xA;        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(texLoc)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)&#xD;&#xA;        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 2, BUFFER_OFFSET(0))&#xD;&#xA;        glEnableVertexAttribArray(posLoc)&#xD;&#xA;        &#xD;&#xA;        let uniOrtho = glGetUniformLocation(shade.progId, &quot;matrix&quot;)&#xD;&#xA;        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &amp;orthographicMatrix)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.ind.count), GLenum(GL_UNSIGNED_SHORT), nil)&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)&#xD;&#xA;        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)&#xD;&#xA;        glDisableVertexAttribArray(posLoc)&#xD;&#xA;        glDisableVertexAttribArray(texLoc)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really have 0 clues as to why something THIS weird is drawing rather then something that makes sense. Any suggestions of what it might be or tips are appreciated!&#xD;&#xA;&#xD;&#xA;Extra note:&#xD;&#xA;I am so sorry but Swift likes to think it is special so it ditched c style for loops. Basically for all of these loops think&#xD;&#xA;&#xD;&#xA;    for (var i = &lt;value before ..&gt;; i &lt; &lt;value after dot&gt;; &lt;happens automatically&gt;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Here is the matrix code&#xD;&#xA;&#xD;&#xA;    var orthographicMatrix:[GLfloat] = []&#xD;&#xA;        &#xD;&#xA;        func buildMatrix()&#xD;&#xA;        {&#xD;&#xA;            orthographicMatrix = glkitmatrixtoarray(GLKMatrix4MakeOrtho(0, GLfloat(width), 0, GLfloat(height), -100, 100))&#xD;&#xA;            //Storage.upScaleFactor&#xD;&#xA;        }&#xD;&#xA;        func glkitmatrixtoarray(mat: GLKMatrix4) -&gt; [GLfloat]&#xD;&#xA;        {&#xD;&#xA;            var buildme:[GLfloat] = []&#xD;&#xA;            buildme.append(mat.m.0)&#xD;&#xA;            buildme.append(mat.m.1)&#xD;&#xA;            buildme.append(mat.m.2)&#xD;&#xA;            buildme.append(mat.m.3)&#xD;&#xA;            buildme.append(mat.m.4)&#xD;&#xA;            buildme.append(mat.m.5)&#xD;&#xA;            buildme.append(mat.m.6)&#xD;&#xA;            buildme.append(mat.m.7)&#xD;&#xA;            buildme.append(mat.m.8)&#xD;&#xA;            buildme.append(mat.m.9)&#xD;&#xA;            buildme.append(mat.m.10)&#xD;&#xA;            buildme.append(mat.m.11)&#xD;&#xA;            buildme.append(mat.m.12)&#xD;&#xA;            buildme.append(mat.m.13)&#xD;&#xA;            buildme.append(mat.m.14)&#xD;&#xA;            buildme.append(mat.m.15)&#xD;&#xA;            return buildme&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Now the issue is not the abstract art but that the rectangle only goes half way nomater the scale factor. Notice the jagged edge&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In apples frame debugger you can see the outline of all the triangles that it draws it looks like this:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Could it be this line that is causing all the trouble `let index = (yy*rSimWidth + xx) * 2`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A test:&#xD;&#xA;I tried the code out by passing 3, 3, and 1 into the initialize function. This should in theory make a 3x3 pixel square, however it just made a mess. Here is all the [data on the CPU][5], and here (according to frame capture take as grain of salt) is how the gpu understands it.&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Introduction/Intro.htm&#xD;&#xA;  [2]: https://i.stack.imgur.com/CLUwc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jBcCz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/a5uoq.png&#xD;&#xA;  [5]: http://pastebin.com/JEf48xYK&#xD;&#xA;  [6]: https://i.stack.imgur.com/a4lDJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8426" PostHistoryTypeId="5" PostId="3934" RevisionGUID="7194c7a0-32f0-47e4-b0fa-37d9d4d1175f" CreationDate="2016-09-01T10:02:15.737" UserId="3073" Comment="new info about vertex output solved the remaining problem" Text="I think you are not constructing the index buffer correctly. Firstly you only need 1 degenerate vertex to terminate each triangle-strip row. &#xD;&#xA;&#xD;&#xA;You also should not need any special handling for odd/even rows. You can emit a single triangle-strip per loop.&#xD;&#xA;&#xD;&#xA;Your index loop should look something like :&#xD;&#xA; &#xD;&#xA;    var index:Int = 0&#xD;&#xA;    for i in 0..&lt;rSimHeight - 1&#xD;&#xA;    {&#xD;&#xA;        for j in 0..&lt;rSimWidth&#xD;&#xA;        {&#xD;&#xA;        	ind[index++] = Indicie(i*rSimWidth + j);		// current row&#xD;&#xA;        	ind[index++] = Indicie((i+1)*rSimWidth + j);	// row below&#xD;&#xA;        }&#xD;&#xA;        ind[index] = ind[index-1];		// degenerate vertex / row termination&#xD;&#xA;        index++;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This also means your index count is defined like:&#xD;&#xA;&#xD;&#xA;    int triStripRows = rSimHeight - 1;&#xD;&#xA;    int indicesPerRow = (rSimWidth * 2) + 1&#xD;&#xA;    int totalIndices = indicesPerRow * triStripRows;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit : After seeing the vertex dump you added to your question I can see there is another problem with the index buffer format. Every odd item in the vertex list is vertice 0. This looks like index buffer is created using 32bit indexes but is being interpreted by opengl as 16bits. So it will read the lower 16bits then upper 16bits of each index. This can be fixed by either changing Indicie data type to 16bit (short) or telling opengl the index buffer is really 32 bits by using GL_UNSIGNED_INT instead of GL_UNSIGNED_SHORT in glDrawElements." ContentLicense="CC BY-SA 3.0" />
  <row Id="8427" PostHistoryTypeId="2" PostId="3935" RevisionGUID="0f15386f-b3a1-411d-b2de-923cce2e130c" CreationDate="2016-09-01T15:52:42.367" UserId="4958" Text="Actually, GL_COLOR_BUFFER_BIT also need to be cleared&#xD;&#xA;&#xD;&#xA;After creation of the framebuffer, draw buffer need to be set to:&#xD;&#xA;&#xD;&#xA;    glDrawBuffer(GL_COLOR_ATTACHMENT0);&#xD;&#xA;&#xD;&#xA;and then after each swap:&#xD;&#xA;&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;instead of only &#xD;&#xA;&#xD;&#xA;    glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;To clear current attachment 0.&#xD;&#xA;I don't really understand these clearing bits extensively but this seems to fix blinking &quot;chess board&quot; artifact.&#xD;&#xA;&#xD;&#xA;Borders seems to be connected with motion blur shader." ContentLicense="CC BY-SA 3.0" />
  <row Id="8428" PostHistoryTypeId="5" PostId="3894" RevisionGUID="57eb33a0-a43a-4a65-bc95-9d06dc644093" CreationDate="2016-09-01T21:58:19.270" UserId="4962" Comment="Add information from author's comment" Text="It sounds to me like you're slightly mixing up several concepts: how lighting due to point-light sources (Phong model) and lighting due to other objects in the scene (recursively raytraced reflection or transmission) combine with each other, as compared to how specular lighting combines with diffuse lighting and/or transmission (using the Fresnel equations).&#xD;&#xA;&#xD;&#xA;A useful way to think about specular vs diffuse is that specular happens at the _surface_ of the material while diffuse, transmissive, and refractive properties are associated with the _bulk_ (the interior) of the material. So you can think of it as two layers composited together. Specular is on top: it reflects a portion of the incoming light, defined by the Fresnel equations, and any remaining light proceeds into the material to light the bulk.&#xD;&#xA;&#xD;&#xA;The bulk will have some combination of scattering and absorption properties. Low scattering makes a transmissive material and high scattering makes a diffuse material (the diffuse color is due to scattering on a scale too small to see). Some materials have an intermediate degree of scattering too, but we can ignore that for simplicity and just treat it as a boolean: opaque (Lambert diffuse) or transmissive.&#xD;&#xA;&#xD;&#xA;Meanwhile, each of these potential material components (specular, diffuse, and transmissive) has to deal with light arriving both from point light sources and from the rest of the scene. Physically, all light sources are just emissive objects that are part of the scene (area lights) but again for simplicity we often approximate by using point lights.&#xD;&#xA;&#xD;&#xA;So, putting it all together, when lighting a surface:&#xD;&#xA;&#xD;&#xA;* For each point light&#xD;&#xA;   1. Calculate Fresnel factor based on light vector&#xD;&#xA;   2. Accumulate Phong specular weighted by Fresnel reflectance&#xD;&#xA;   3. [if opaque] Accumulate Lambert diffuse weighted by Fresnel transmittance&#xD;&#xA;   4. [if transparent] Nothing; light goes through and isn't scattered into the camera.&#xD;&#xA;* For reflecting the rest of the scene&#xD;&#xA;   1. Calculate Fresnel factor based on view vector&#xD;&#xA;   2. Cast a reflection ray and accumulate it weighted by Fresnel reflectance&#xD;&#xA;   3. [if opaque] Nothing. (Ideally, accumulate Lambert diffuse due to all objects visible in the normal hemisphere of the surface, i.e. indirect diffuse. However, for a basic recursive raytracer this isn't feasible; it requires path tracing, photon mapping, or suchlike.)&#xD;&#xA;   4. [if transparent] Cast a transmission ray and accumulate it weighted by Fresnel transmittance&#xD;&#xA;&#xD;&#xA;Also, a note about your material properties: physically, not all of those properties are actually independent of each other. Ks, reflectivity, and refractive index are all the same thing. Ks is the same thing as reflectivity (literally the same value) because both control specular reflections; Ks is for point lights and reflectivity is for reflected environment rays, but it's the same physical mechanism for both. And Ks is determined in turn by the Fresnel equations based on refractive index (which can vary with wavelength).&#xD;&#xA;&#xD;&#xA;So, strictly speaking, you should pick one of those variables and let it determine the others. For opaque materials where you don't really care about refractive index, you might let users set Ks (at normal incidence) and backsolve the Fresnel equations to get the appropriate refractive index from that. For transparent materials like glass you can let users set the refractive index and then let the Fresnel equations do their thing.&#xD;&#xA;&#xD;&#xA;BTW, to get some physics background that will hopefully help clarify all this, I highly recommend Naty Hoffman's &quot;Physics and Math of Shading&quot; talk from the [SIGGRAPH 2015 Physically-Based Shading Course](http://blog.selfshadow.com/publications/s2015-shading-course/). It gives a quick and not-too-mathematical intro to the physical basis of things like diffuse and specular lighting, BRDFs and so on." ContentLicense="CC BY-SA 3.0" />
  <row Id="8429" PostHistoryTypeId="24" PostId="3894" RevisionGUID="57eb33a0-a43a-4a65-bc95-9d06dc644093" CreationDate="2016-09-01T21:58:19.270" Comment="Proposed by 4962 approved by 273, 48 edit id of 160" ContentLicense="CC BY-SA 3.0" />
  <row Id="8430" PostHistoryTypeId="2" PostId="3936" RevisionGUID="3b4018e4-f2f8-4a75-87d5-a4e3ae72b6ea" CreationDate="2016-09-02T05:44:10.807" UserId="523" Text="[`glReadBuffer(...)`](https://www.opengl.org/sdk/docs/man/html/glReadBuffer.xhtml)/[`glDrawBuffer(...)`](https://www.opengl.org/sdk/docs/man/html/glDrawBuffer.xhtml)/[`glDrawBuffers(...)`](https://www.opengl.org/sdk/docs/man/html/glDrawBuffers.xhtml) access part of a framebuffer's state.&#xD;&#xA;&#xD;&#xA;For reading the default framebuffer, this is `GL_FRONT` or `GL_BACK`.  However, the documentation doesn't say what it is for FBOs.  The only thing I found was an offhand comment [here](http://www.lighthouse3d.com/tutorials/opengl_framebuffer_objects/) stating that the default is GL_COLOR_ATTACHMENT0 (which is what I would guess).  Can I rely on that?&#xD;&#xA;&#xD;&#xA;For writing, I didn't immediately find any claims what what color buffers are enabled." ContentLicense="CC BY-SA 3.0" />
  <row Id="8431" PostHistoryTypeId="1" PostId="3936" RevisionGUID="3b4018e4-f2f8-4a75-87d5-a4e3ae72b6ea" CreationDate="2016-09-02T05:44:10.807" UserId="523" Text="What Are The Default Values of `glReadBuffer/glDrawBuffer(s)` for an FBO?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8432" PostHistoryTypeId="3" PostId="3936" RevisionGUID="3b4018e4-f2f8-4a75-87d5-a4e3ae72b6ea" CreationDate="2016-09-02T05:44:10.807" UserId="523" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8433" PostHistoryTypeId="2" PostId="3937" RevisionGUID="710b5732-3293-4d26-9f00-6bc07494f54b" CreationDate="2016-09-02T05:44:10.807" UserId="523" Text="You can usually track down the answer for such questions in the OpenGL specification.  Assuming the value you care about is consistent across OpenGL versions (often the case for initial values, [seldom the case for minimum values](https://github.com/imallett/parse-GL-minimum-limits)).&#xD;&#xA;&#xD;&#xA;In this case, in the [GL 4.5 specification](https://www.opengl.org/registry/doc/glspec45.core.pdf), check out the following:&#xD;&#xA;&#xD;&#xA;- `glReadBuffer(...)` initial value: (default framebuffer: `GL_FRONT` iff single-buffered, `GL_BACK` iff double-buffered) (FBO: `GL_COLOR_ATTACHMENT0`) (see page 506)&#xD;&#xA;- `glDrawBuffer(...)` initial value: (see `glDrawBuffers(...)`)&#xD;&#xA;- `glDrawBuffers(...)` initial value: (default framebuffer: fragment color 0 goes to `GL_FRONT` iff single-buffered, `GL_BACK` iff double-buffered) (FBO: fragment color 0 goes to `GL_COLOR_ATTACHMENT0`) (both: fragment colors other than 0 go to `GL_NONE`) (see page 497)" ContentLicense="CC BY-SA 3.0" />
  <row Id="8434" PostHistoryTypeId="2" PostId="3938" RevisionGUID="5ded81e8-1708-4502-b0de-bec5c3749e13" CreationDate="2016-09-02T06:01:15.033" UserId="4992" Text="Here is what I finally did, maybe somebody finds it useful.&#xD;&#xA;&#xD;&#xA;I wrote a script with Excel VBA what does the following:&#xD;&#xA;&#xD;&#xA; 1. gets the coordinates of n discrete points on the trajectory&#xD;&#xA; 2. gets k points of the circular cross-section at each n, in a horizontal plane&#xD;&#xA; 3. applies a rotation on these cross-sections (moves all points)&#xD;&#xA; 4. creates (n-1)*(k-1) facets (assigns 4 corner points to each)&#xD;&#xA; 5. exports the points and the facets to a vrml file&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; - The script might have been easier in python, but I chose Excel VBA  &#xD;&#xA;   because this way I don't have to deal with the GUI.&#xD;&#xA;   &#xD;&#xA; - The format is vrml, because a) most software handles it b) the&#xD;&#xA;   definition is available (mostly) and simple&#xD;&#xA;&#xD;&#xA; - prepare the file by script instead of a CAD software: in my experience they can't build this surface reliably enough. The features will be super-sensitive to the input parameters, they will tend to crash after small changes&#xD;&#xA;&#xD;&#xA;There are a couple of issues remaining:&#xD;&#xA;&#xD;&#xA;  - Catia can't open the result, possibly because the vertex normals are not defined in the wrl file. This feature of the vrml is not really documented. Opening and saving it with Creo solves the issue, as it adds the normals automatically. Creo and NX are ok.&#xD;&#xA;  - Can't convert the result to quilt in Creo, hence sectioning, measuring, etc is problematic&#xD;&#xA;&#xD;&#xA;Any suggestions with the issues above are most welcome.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GIwAu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8435" PostHistoryTypeId="2" PostId="3939" RevisionGUID="2b7b6e12-d18b-4bdd-ae8a-0d0d687855fa" CreationDate="2016-09-02T20:39:11.707" UserId="5021" Text="There's already something called K-nearest neighbour algorithm with gives nearest neighbour to points. But what I want is unique neighbour which is not shared by any other neighbour.&#xD;&#xA;I've implemented this logic but it's very slow. You can review my code [here][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://codereview.stackexchange.com/questions/140292" ContentLicense="CC BY-SA 3.0" />
  <row Id="8436" PostHistoryTypeId="1" PostId="3939" RevisionGUID="2b7b6e12-d18b-4bdd-ae8a-0d0d687855fa" CreationDate="2016-09-02T20:39:11.707" UserId="5021" Text="How to get unique nearest neighbour?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8437" PostHistoryTypeId="3" PostId="3939" RevisionGUID="2b7b6e12-d18b-4bdd-ae8a-0d0d687855fa" CreationDate="2016-09-02T20:39:11.707" UserId="5021" Text="|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8438" PostHistoryTypeId="2" PostId="3940" RevisionGUID="79f51ed0-f3c2-4dc0-ab9c-5784cde16cca" CreationDate="2016-09-02T20:52:10.987" UserId="2308" Text="In my simulation I draw a bunch of rectangles with GL_TRIANGLE_STRIP inside of one draw call.&#xD;&#xA;&#xD;&#xA;If I turn off GL_DEPTH_SORT what will happen? If all of the rectangles were stacked ontop of themselves in a 2D screenspace sense would they always be in the same order?&#xD;&#xA;&#xD;&#xA;Im assuming its just like when you do multiple draw calls (the first one is in back, the last one is in front) how it essentially just draws over what was previously drawn.&#xD;&#xA;&#xD;&#xA;BTW I am using OpenglES 2.0" ContentLicense="CC BY-SA 3.0" />
  <row Id="8439" PostHistoryTypeId="1" PostId="3940" RevisionGUID="79f51ed0-f3c2-4dc0-ab9c-5784cde16cca" CreationDate="2016-09-02T20:52:10.987" UserId="2308" Text="What happens when GL_Depth is disabled" ContentLicense="CC BY-SA 3.0" />
  <row Id="8440" PostHistoryTypeId="3" PostId="3940" RevisionGUID="79f51ed0-f3c2-4dc0-ab9c-5784cde16cca" CreationDate="2016-09-02T20:52:10.987" UserId="2308" Text="|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8441" PostHistoryTypeId="5" PostId="3940" RevisionGUID="5fc559cf-c420-4b6d-a26c-6bf86dd2352a" CreationDate="2016-09-02T21:05:23.927" UserId="2308" Comment="added 169 characters in body" Text="In my simulation I draw a bunch of rectangles with GL_TRIANGLE_STRIP inside of one draw call.&#xD;&#xA;&#xD;&#xA;If I turn off GL_DEPTH_SORT what will happen? If all of the rectangles were stacked ontop of themselves in a 2D screenspace sense would they always be in the same order?&#xD;&#xA;&#xD;&#xA;Im assuming its just like when you do multiple draw calls (the first one is in back, the last one is in front) how it essentially just draws over what was previously drawn.&#xD;&#xA;&#xD;&#xA;BTW I am using OpenglES 2.0&#xD;&#xA;&#xD;&#xA;Also what happens with blend modes? Lets say I am doing additive blending, and then multiply the colors by 0.5 making them transparent. Would additive blending work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8442" PostHistoryTypeId="2" PostId="3941" RevisionGUID="379a9940-2a7f-4d8c-afee-bd114ab81779" CreationDate="2016-09-02T22:01:12.723" UserId="48" Text="If depth testing is disabled, the triangles get drawn in the order they're submitted, i.e. the order they appear in the index buffer or vertex buffer. Later ones will overwrite earlier ones, or blend over them if blending is enabled. This ordering is guaranteed by all GPUs and APIs as far as I know." ContentLicense="CC BY-SA 3.0" />
  <row Id="8443" PostHistoryTypeId="2" PostId="3942" RevisionGUID="83395e67-c497-487f-b54e-1ecd48dd627e" CreationDate="2016-09-03T01:47:23.163" UserId="5026" Text="I'm trying to condense my Deferred Rendering G-Buffer. So I have some questions about getting 2-component Screenspace Normals. I know Frostbite and Killzone (the only two AAA company's G-Buffers I could find) use them.&#xD;&#xA;&#xD;&#xA;How are screenspace normals created, and is this step before or after using normal maps or bump maps? If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals, and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?&#xD;&#xA;&#xD;&#xA;Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8444" PostHistoryTypeId="1" PostId="3942" RevisionGUID="83395e67-c497-487f-b54e-1ecd48dd627e" CreationDate="2016-09-03T01:47:23.163" UserId="5026" Text="Screenspace Normals - Creation, Normal Maps, and Unpacking" ContentLicense="CC BY-SA 3.0" />
  <row Id="8445" PostHistoryTypeId="3" PostId="3942" RevisionGUID="83395e67-c497-487f-b54e-1ecd48dd627e" CreationDate="2016-09-03T01:47:23.163" UserId="5026" Text="|shader|transformations|deferred-rendering|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8446" PostHistoryTypeId="2" PostId="3943" RevisionGUID="26743847-2483-455c-8f53-9e4fbdc1db64" CreationDate="2016-09-03T01:48:41.327" UserId="2308" Text="I have been working on how the GPU does parellel processing, and branching. However I am not yet to the point where I know how to make this shader more efficent. Essentially I dont know enough about how it works.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Anyway I have the following shader:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;     &#xD;&#xA;    varying vec3 o_color; //Color it should be&#xD;&#xA;    varying vec2 texture_coord; //Interpolated value 0-1&#xD;&#xA;    varying float ratio_out; //This is the height / width of the capsule on screen&#xD;&#xA;    varying float rdistOut; //This number is used to fill in all pixels when particle is slow enough for the geometry to be a square but still has some distance from last position.&#xD;&#xA;     &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;       &#xD;&#xA;       &#xD;&#xA;        vec2 yCoord = vec2(0.5);&#xD;&#xA;        float yScale = ratio_out;&#xD;&#xA;       &#xD;&#xA;        vec2 my = texture_coord * vec2(1.0, yScale);&#xD;&#xA;       &#xD;&#xA;        vec2 del = yCoord - my;&#xD;&#xA;       &#xD;&#xA;        float len = del.x * del.x + del.y * del.y;&#xD;&#xA;        if ((!(my.y &gt; 1.0) &amp;&amp; (len &lt; 0.25)) || (my.y &gt; yCoord.y &amp;&amp; my.y &lt; rdistOut))&#xD;&#xA;        {&#xD;&#xA;            gl_FragColor = vec4(o_color, 1.0);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            gl_FragColor.a = 0.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What it does is draw capsules on the screen. Basically these capsules connect where the particle was to where it is.&#xD;&#xA;&#xD;&#xA;On the cpu I compute the vertices of this with some linear algebra, but in screen space terms the rectangle we will be shading has a maximum width of `W` and a minimum height of `W`. If the capsule is moving faster then `W/2` then the capsules geometry will start to get longer to accommodate.&#xD;&#xA;&#xD;&#xA;Here are some diagrams of what is going on:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is an image of a single capsule. Because the distance between the current and last position is not large enough so the screen-space geometry is a square. You can see that to compensate that lighter area is shaded in as well to connect the two points.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here are some more examples of what could happen&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The thing is these capsules are all individual, sometimes every capsule will be elongated, sometimes it will only be a small percent. This shader needs to be as steady fps as possible.&#xD;&#xA;&#xD;&#xA;Now here are some tips that are useful and might help make things more efficent:&#xD;&#xA;&#xD;&#xA; 1. The dot product is NEVER needed past the point where the circle part is done.&#xD;&#xA; 2. If the scaleFactor is greater then 1 then the dot product is never needed past the center of the circle.&#xD;&#xA;&#xD;&#xA;This is shown in this diagram.  In this case none of the grey area needs to preform the dot product.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Explanation of variables:&#xD;&#xA;&#xD;&#xA;o_color: is the color that that particle is&#xD;&#xA;&#xD;&#xA;texture_coord: these are the exact same as if you were going to texture this, they go from 0-1&#xD;&#xA;&#xD;&#xA;ratio_out: height / width. Will never be less then 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Inside the main function to get the coordinates in screen scale we simply multiply the y texture coordinate by the scale factor. That makes the center of the circle part a 0.5, 0.5.&#xD;&#xA;&#xD;&#xA;rdistOut is the tiny area that the particle sometimes has when it is a square but still moving. Things should be shaded from 0.5-rdistOut.&#xD;&#xA;&#xD;&#xA;Could you please help me remove un-needed dot product computations and comparisons as well as get rid of branching?&#xD;&#xA;&#xD;&#xA;**Please include an explanation of how you got the GPU to skip dot product calculations or why you did what you did. Next time I hope to be able to do this myself.**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/J6619.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TEi8a.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/XWikU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8447" PostHistoryTypeId="1" PostId="3943" RevisionGUID="26743847-2483-455c-8f53-9e4fbdc1db64" CreationDate="2016-09-03T01:48:41.327" UserId="2308" Text="I dont understand how a GPU computes and branches, could you please help me fix this shader preformance" ContentLicense="CC BY-SA 3.0" />
  <row Id="8448" PostHistoryTypeId="3" PostId="3943" RevisionGUID="26743847-2483-455c-8f53-9e4fbdc1db64" CreationDate="2016-09-03T01:48:41.327" UserId="2308" Text="|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8449" PostHistoryTypeId="2" PostId="3944" RevisionGUID="04b7be19-e732-463e-9382-fcd8687b0cb6" CreationDate="2016-09-03T02:56:55.973" UserId="2707" Text="&gt; How are screenspace normals created, and is this step before or after using normal maps or bump maps?&#xD;&#xA;&#xD;&#xA;They are created after using normal maps. In deferred rendering, you write to the various buffers (diffuse, normal, depth, etc.) in fragment shaders. By this time, the normal maps would have already been read.&#xD;&#xA;&#xD;&#xA;&gt; If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals,...&#xD;&#xA;&#xD;&#xA;If you are referring to normal maps on models, normal maps can stay the same. You can compress normal maps as well if you want, but this becomes irrelevant to what you do for writing to the normal buffer.&#xD;&#xA;&#xD;&#xA;&gt; ...and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?&#xD;&#xA;&#xD;&#xA;You don't need to recreate model-view matrices. Your model's normals are computed per vertex and interpolated through rasterization to be per fragment. The normal maps are processed per fragment, but these are just texture lookups. After the fragment stage, you don't need to do anymore calculations on vertices.&#xD;&#xA;&#xD;&#xA;&gt; Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?&#xD;&#xA;&#xD;&#xA;The idea behind 2-component normals versus 3-component normals is that the vector magnitude isn't often taken into account for normals. Also, normals facing away from the camera generally aren't useful. With two components, you can use model a hemisphere facing the camera. You unpack them the same way you pack them.&#xD;&#xA;&#xD;&#xA;Think about normals as positions. When converting from world space (x, y, z) to screenspace (x, y, depth), but the depth does not effect where on the screen a mesh gets displayed. Convert the 3D vector to a vector in terms of screenspace.&#xD;&#xA;&#xD;&#xA;Then you can discard the z-component (aligned with the camera) as long as you normals are unit vectors (because you can derive z from the other two vectors)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8450" PostHistoryTypeId="5" PostId="3944" RevisionGUID="eb2867fd-1e8e-4fa3-9f50-9b03f4076ed9" CreationDate="2016-09-03T03:54:58.413" UserId="2707" Comment="deleted 10 characters in body" Text="&gt; How are screenspace normals created, and is this step before or after using normal maps or bump maps?&#xD;&#xA;&#xD;&#xA;They are created after using normal maps. In deferred rendering, you write to the various buffers (diffuse, normal, depth, etc.) in fragment shaders. By this time, the normal maps would have already been read.&#xD;&#xA;&#xD;&#xA;&gt; If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals,...&#xD;&#xA;&#xD;&#xA;If you are referring to normal maps on models, normal maps can stay the same. You can compress normal maps as well if you want, but this becomes irrelevant to what you do for writing to the normal buffer.&#xD;&#xA;&#xD;&#xA;&gt; ...and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?&#xD;&#xA;&#xD;&#xA;Your model's normals are computed per vertex and interpolated through rasterization to be per fragment. The normal maps are processed per fragment, but these are just texture lookups. After the fragment stage, you don't need to do anymore calculations on vertices.&#xD;&#xA;&#xD;&#xA;&gt; Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?&#xD;&#xA;&#xD;&#xA;The idea behind 2-component normals versus 3-component normals is that the vector magnitude isn't often taken into account for normals. Also, normals facing away from the camera generally aren't useful. With two components, you can use model a hemisphere facing the camera. You unpack them the same way you pack them.&#xD;&#xA;&#xD;&#xA;Think about normals as positions. When converting from world space (x, y, z) to screenspace (x, y, depth), but the depth does not effect where on the screen a mesh gets displayed. Convert the 3D vector to a vector in terms of screenspace (through view matrix multiplications).&#xD;&#xA;&#xD;&#xA;Then you can discard the z-component (aligned with the camera) as long as you normals are unit vectors (because you can derive z from the other two vectors)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8451" PostHistoryTypeId="5" PostId="3944" RevisionGUID="062ad0bc-fce9-4516-b874-70000fbaa7eb" CreationDate="2016-09-03T04:07:59.903" UserId="2707" Comment="added 64 characters in body" Text="&gt; How are screenspace normals created, and is this step before or after using normal maps or bump maps?&#xD;&#xA;&#xD;&#xA;They are created after using normal maps. In deferred rendering, you write to the various buffers (diffuse, normal, depth, etc.) in fragment shaders. By this time, the normal maps would have already been read.&#xD;&#xA;&#xD;&#xA;&gt; If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals,...&#xD;&#xA;&#xD;&#xA;If you are referring to normal maps on models, normal maps can stay the same. You can compress normal maps as well if you want, but this becomes irrelevant to what you do for writing to the normal buffer.&#xD;&#xA;&#xD;&#xA;&gt; ...and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?&#xD;&#xA;&#xD;&#xA;Your model's normals are computed per vertex and interpolated through rasterization to be per fragment. The normal maps are processed per fragment, but these are just texture lookups, and these can be applied to the camera-space normals produced from the previous pipeline steps. Therefore, a view matrix is no longer necessary.&#xD;&#xA;&#xD;&#xA;&gt; Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?&#xD;&#xA;&#xD;&#xA;The idea behind 2-component normals versus 3-component normals is that the vector magnitude isn't often taken into account for normals. Also, normals facing away from the camera generally aren't useful. With two components, you can use model a hemisphere facing the camera. You unpack them the same way you pack them.&#xD;&#xA;&#xD;&#xA;Think about normals as positions. When converting from world space (x, y, z) to screenspace (x, y, depth), but the depth does not effect where on the screen a mesh gets displayed. Convert the 3D vector to a vector in terms of screenspace (through view matrix multiplications).&#xD;&#xA;&#xD;&#xA;Then you can discard the z-component (aligned with the camera) as long as you normals are unit vectors (because you can derive z from the other two vectors)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8456" PostHistoryTypeId="5" PostId="3939" RevisionGUID="b968a555-3ceb-4f89-a52a-db570d24b1b4" CreationDate="2016-09-04T10:19:14.597" UserId="5021" Comment="added 1070 characters in body" Text="There's already something called K-nearest neighbour algorithm with gives nearest neighbour to points. But what I want is unique neighbour which is not shared by any other neighbour.&#xD;&#xA;I've implemented this logic but it's very slow. You can review my code [here][n].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [n]: http://codereview.stackexchange.com/questions/140292&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Let's assume there're 2 galaxies with 5 stars in each. GalaxyA neighbour list(let's call it closestNeighbourList) in GalaxyB starting from closest to fartherest...&#xD;&#xA;&#xD;&#xA;star 0: [4, 1, 0, 3, 2]&#xD;&#xA;&#xD;&#xA;star 1: [2, 0, 4, 3, 1]&#xD;&#xA;&#xD;&#xA;star 2: [2, 1, 3, 0, 4]&#xD;&#xA;&#xD;&#xA;star 3: [0, 3, 2, 4, 1]&#xD;&#xA;&#xD;&#xA;star 4: [0, 3, 1, 4, 2]&#xD;&#xA;&#xD;&#xA;from these lists default first neighbour list:&#xD;&#xA;&#xD;&#xA;star 0: [4]&#xD;&#xA;&#xD;&#xA;star 1: [2]&#xD;&#xA;&#xD;&#xA;star 2: [2]&#xD;&#xA;&#xD;&#xA;star 3: [0]&#xD;&#xA;&#xD;&#xA;star 4: [0]&#xD;&#xA;&#xD;&#xA;Since I want unique neighbour in GalaxyB, but here you see a problem, star 2 in GalaxyB is closest to two GalaxyA stars 1 &amp; 2 and same for star 0. So these are not unique neighbour as shared by two or more stars. So to overcome this problem what I'm doing first storing all neighbours in a list(closestNeighbourList) then looping over those to check if it's closer to(shared by) some other star then go to next neighbour and when it's find unique neighbour break out of the loop.&#xD;&#xA;&#xD;&#xA;after applying unique neighbour algorithm first neighbour list will be:&#xD;&#xA;&#xD;&#xA;star 0: [4]&#xD;&#xA;&#xD;&#xA;star 1: [2]&#xD;&#xA;&#xD;&#xA;star 2: [1]&#xD;&#xA;&#xD;&#xA;star 3: [3]&#xD;&#xA;&#xD;&#xA;star 4: [0]" ContentLicense="CC BY-SA 3.0" />
  <row Id="8457" PostHistoryTypeId="2" PostId="3946" RevisionGUID="ca653402-951b-457f-b86c-2de80c16f85a" CreationDate="2016-09-04T12:24:58.883" UserId="5033" Text="since a while I am doing some research on the topic of PBR and one reflection-modelis mentioned over and over is the Cook-Torrance-/ Torrance-Sparrow-model and it semes like in any mention or explanation of this model another form of the specular term is used. The versions I have found are:&#xD;&#xA;&#xD;&#xA; 1. $${\frac {FDG}{\pi ({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA; 2. $${\frac {FDG}{4 ({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA; 3. $${\frac {FDG}{({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA;&#xD;&#xA;Which one is when correct? In PBR: From Theory to Implementation the second one is conclusive derivated, but in thier orignal paper Cook Torrance use the first one without any detailed explation.&#xD;&#xA;&#xD;&#xA;I hope you can help me." ContentLicense="CC BY-SA 3.0" />
  <row Id="8458" PostHistoryTypeId="1" PostId="3946" RevisionGUID="ca653402-951b-457f-b86c-2de80c16f85a" CreationDate="2016-09-04T12:24:58.883" UserId="5033" Text="Correct Specular-Term of the Cook-Torrance- Torrance-Sparrow-Model" ContentLicense="CC BY-SA 3.0" />
  <row Id="8459" PostHistoryTypeId="3" PostId="3946" RevisionGUID="ca653402-951b-457f-b86c-2de80c16f85a" CreationDate="2016-09-04T12:24:58.883" UserId="5033" Text="|rendering|mathematics|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8460" PostHistoryTypeId="2" PostId="3947" RevisionGUID="99d3c7c0-dca0-4897-a17f-c07bb4a08ee6" CreationDate="2016-09-04T13:38:32.540" UserId="2351" Text="&gt; I'm trying to condense my Deferred Rendering G-Buffer. So I have some questions about getting 2-component Screenspace Normals. I know Frostbite and Killzone (the only two AAA company's G-Buffers I could find) use them.&#xD;&#xA;&#xD;&#xA;I'm confused when you say &quot;screenspace normals&quot;, Killzone uses view-space normals, they store the X &amp; Y coordinate of the normal in FP16 format, and reconstruct Z using $z = sqrt(1.0 - Normal.x^2 - Normal.y2)$ a problem with that is that we lack the sign of Z, even in view-space the normals can point away from the camera, i.e. Z is not always positive.&#xD;&#xA;&#xD;&#xA;&gt; How are screenspace normals created, and is this step before or after using normal maps or bump maps? If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals, and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?&#xD;&#xA;&#xD;&#xA;After loading your normal maps, you construct a TBN matrix to transform from tangent space to e.g. world space before writing to the G-Buffer. So in essence, your normals in the G-Buffer are stored in world-space, not screen-space. With that you can apply lighting in world space, as far as I'm aware, Crytek &amp; Epic do the lighting in world-space now.&#xD;&#xA;&#xD;&#xA;I'm not sure what you mean by &quot;screenspace-ness&quot;, but when writing any sort of data to the G-Buffer, you're essentially writing their current value, if the normals are in world-space, they will remain in world-space when written to the G-Buffer. When you sample the G-Buffer on the second pass, for each texel, you get an RGB color (assuming you're using RGB) that maps to your coordinate data.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8461" PostHistoryTypeId="34" PostId="3931" RevisionGUID="19714f63-a3c8-4233-b87b-47fc4749c82f" CreationDate="2016-09-04T19:22:47.797" UserId="2308" Comment="21" />
  <row Id="8462" PostHistoryTypeId="5" PostId="3946" RevisionGUID="b97b843f-e883-41e0-b135-b92353676780" CreationDate="2016-09-04T22:02:20.147" UserId="231" Comment="Clarification - please correct any changes if I have misunderstood your intention." Text="For a while I have been doing some research on the topic of PBR (Physically Based Rendering). One reflection model that is mentioned over and over is the [Cook-Torrance] / Torrance-Sparrow model. It seems like in each mention or explanation of this model a different form of the specular term is used. The versions I have found are:&#xD;&#xA;&#xD;&#xA; 1. $${\frac {FDG}{\pi ({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA; 2. $${\frac {FDG}{4 ({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA; 3. $${\frac {FDG}{({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA;&#xD;&#xA;Which one is correct, and when? In *PBR: From Theory to Implementation* the second one is conclusively derived, but in their original paper Cook and Torrance use the first one without any detailed explanation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Cook-Torrance]: https://en.wikipedia.org/wiki/Specular_highlight#Cook.E2.80.93Torrance_model" ContentLicense="CC BY-SA 3.0" />
  <row Id="8463" PostHistoryTypeId="4" PostId="3946" RevisionGUID="b97b843f-e883-41e0-b135-b92353676780" CreationDate="2016-09-04T22:02:20.147" UserId="231" Comment="Clarification - please correct any changes if I have misunderstood your intention." Text="Correct Specular Term of the Cook-Torrance / Torrance-Sparrow Model" ContentLicense="CC BY-SA 3.0" />
  <row Id="8465" PostHistoryTypeId="5" PostId="3946" RevisionGUID="9006cdf4-c26e-4c15-a88f-1163f15a5a45" CreationDate="2016-09-04T23:48:37.567" UserId="5033" Comment="added 137 characters in body" Text="For a while I have been doing some research on the topic of Physically Based Rendering. One reflection model that is mentioned over and over is the [Cook-Torrance] / Torrance-Sparrow model. It seems like in each mention or explanation of this model a different form of the specular term is used. The versions I have found are:&#xD;&#xA;&#xD;&#xA; 1. $${\frac {FDG}{\pi ({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA; 2. $${\frac {FDG}{4 ({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA; 3. $${\frac {FDG}{({\vec N}\cdot {\vec V})({\vec N}\cdot {\vec L})}}$$&#xD;&#xA;&#xD;&#xA;Which one is correct, and when? In *[Physically Based Rendering: From Theory to Implementation]* by Matt Pharr and Greg Humphreys, the second one is conclusively derived, but in their original paper Cook and Torrance use the first one without any detailed explanation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Cook-Torrance]: https://en.wikipedia.org/wiki/Specular_highlight#Cook.E2.80.93Torrance_model&#xD;&#xA;  [Physically Based Rendering: From Theory to Implementation]:http://www.pbrt.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8466" PostHistoryTypeId="2" PostId="3948" RevisionGUID="712d5296-e77c-449c-ab6d-2db70a2413dc" CreationDate="2016-09-04T23:51:57.767" UserId="5039" Text="Identifying your axes in both figures and adding the camera position to your first figure would help you understand what's going on.&#xD;&#xA;&#xD;&#xA;You could also have a single variables for all your points, generating a 2D matrix with the rows as each point and columns as the components $x$, $y$ and $z$. That way, you could handle the projection using a simple matrix multiplication instead of handling each row separately.&#xD;&#xA;&#xD;&#xA;In the problem statement, would be interesting to know the direction of your rotation, and more importantly, the original camera direction and its up vector. I guess you camera is rotated by 160° counter-clockwise, the original camera direction is $[0, 0, 1]$ and its up vector is $[0, 1, 0]$. If any of those assumptions is wrong, the rest of the answer will be wrong.&#xD;&#xA;&#xD;&#xA;There is no sign of mm to m conversion in your code. Either your focal should be $0.016$ and $S_x = S_y = 0.0001$ or your point coordinates should be multiplied by $0.00001$.&#xD;&#xA;&#xD;&#xA;Let's reason about where should the points end up in your image. For example, your camera center, without rotation, is pointing at the $[-1,1,x]$ line. Since the points are all on the $z=0.5$ plane, we can do the following analysis: if we focus on the $x$-axis, we can see that $tan(160°) \cdot (5 - 0.5) = 1.64...$, so the camera center will end up slightly to the left of the points (as the camera is at $x=-1$), so the center will end up at $\approx 0.64$, meaning that the points will appear on the right section of the image. Furthermore, the camera has the same $y$ coordinates as two point, and since the $y$ coordinates are not changed by the rotation, they should still end up on the same coordinates after the transform, meaning on the central row of the image.&#xD;&#xA;&#xD;&#xA;A good way to check your answer is by using an existing 3D modeler like Blender:&#xD;&#xA;[![3D scene in Blender][1]][1]&#xD;&#xA;Be cautious with Blender' coordinates system, for example the default camera vector is `[0, 0, -1]`.&#xD;&#xA;Here's the render:&#xD;&#xA;[![Render in Blender][2]][2]&#xD;&#xA;Focal was set to another value to make the sphere more visible. So we see that the bottom two points are on the middle row of the image and the points are slightly to the right of the image.&#xD;&#xA;&#xD;&#xA;I implemented your homework in Python:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from mpl_toolkits.mplot3d import axes3d, Axes3D&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    # Parameters&#xD;&#xA;    f_mm = 0.016&#xD;&#xA;    f_px = f_mm / 0.00001&#xD;&#xA;    t_cam = np.array([[-1., 1., 5.]]).T&#xD;&#xA;    t_cam_homogeneous = np.vstack((t_cam, np.array([[0]])))&#xD;&#xA;    theta = 160. * np.pi / 180.&#xD;&#xA;    ox = 320&#xD;&#xA;    oy = 240&#xD;&#xA;    # Rotation and points are in homogeneous coordinates&#xD;&#xA;    rot_cam = np.array([[np.cos(theta), 0, np.sin(theta)],&#xD;&#xA;                        [0, 1, 0],&#xD;&#xA;                        [-np.sin(theta), 0, np.cos(theta)]])&#xD;&#xA;    points = np.array([[1, 1, 0.5, 1],&#xD;&#xA;                       [1, 1.5, 0.5, 1],&#xD;&#xA;                       [1.5, 1.5, 0.5, 1],&#xD;&#xA;                       [1.5, 1, 0.5, 1]]).T&#xD;&#xA;&#xD;&#xA;    # Compute projection matrix using intrinsics and extrinsics&#xD;&#xA;    intrinsics = np.array([[f_px, 0, ox],&#xD;&#xA;                           [0, f_px, oy],&#xD;&#xA;                           [0, 0, 1]])&#xD;&#xA;    extrinsics = np.hstack((rot_cam, rot_cam.dot(-t_cam)))&#xD;&#xA;&#xD;&#xA;    rot_cam2 = np.identity(4); rot_cam2[:3,:3] = rot_cam&#xD;&#xA;    camera_coordinates = rot_cam2.dot(points - t_cam_homogeneous)&#xD;&#xA;    camera_coordinates = camera_coordinates[:3,:] / camera_coordinates[3,:]&#xD;&#xA;&#xD;&#xA;    # Perform the projection&#xD;&#xA;    projected_points = intrinsics.dot(camera_coordinates)&#xD;&#xA;    projected_points = projected_points[:2,:] / projected_points[2,:]&#xD;&#xA;    projected_points[0,:] = -projected_points[0,:] # Inverted x-axis because camera is pointing toward [0, 0, 1]&#xD;&#xA;&#xD;&#xA;    fig = plt.figure()&#xD;&#xA;    ax = Axes3D(fig)&#xD;&#xA;    ax.scatter(points[0,:], points[1,:], points[2,:], label=&quot;Points&quot;)&#xD;&#xA;    ax.scatter(t_cam[0], t_cam[1], t_cam[2], c=&quot;red&quot;, label=&quot;Camera&quot;)&#xD;&#xA;    ax.set_xlabel(&quot;X axis&quot;); ax.set_ylabel(&quot;Y axis&quot;); ax.set_zlabel(&quot;Z axis&quot;)&#xD;&#xA;    plt.title(&quot;World coordinates&quot;)&#xD;&#xA;    plt.legend()&#xD;&#xA;    plt.savefig('world_coordinates.png', dpi=300, bbox_inches=&quot;tight&quot;)&#xD;&#xA;&#xD;&#xA;    fig = plt.figure()&#xD;&#xA;    ax = Axes3D(fig)&#xD;&#xA;    ax.scatter(camera_coordinates[0,:], camera_coordinates[1,:], camera_coordinates[2,:], label=&quot;Points&quot;)&#xD;&#xA;    ax.scatter(0, 0, 0, c=&quot;red&quot;, label=&quot;Camera&quot;)&#xD;&#xA;    ax.set_xlabel(&quot;X axis&quot;); ax.set_ylabel(&quot;Y axis&quot;); ax.set_zlabel(&quot;Z axis&quot;)&#xD;&#xA;    plt.title(&quot;Camera coordinates&quot;)&#xD;&#xA;    plt.legend()&#xD;&#xA;    plt.savefig('camera_coordinates.png', dpi=300, bbox_inches=&quot;tight&quot;)&#xD;&#xA;&#xD;&#xA;    plt.figure()&#xD;&#xA;    plt.scatter(projected_points[0,:], projected_points[1,:])&#xD;&#xA;    plt.xlabel(&quot;X axis&quot;); plt.ylabel(&quot;Y axis&quot;)&#xD;&#xA;    plt.title(&quot;Image coordinates&quot;)&#xD;&#xA;    plt.savefig('image_coordinates.png', dpi=300, bbox_inches=&quot;tight&quot;)&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This yield me those figures:&#xD;&#xA;[![World coordinates][3]][3]&#xD;&#xA;[![Camera coordinates][4]][4]&#xD;&#xA;[![Camera coordinates rotated][5]][5]&#xD;&#xA;[![Image coordinates][6]][6]&#xD;&#xA;Respectively: World coordinates, Camera coordinates, Camera coordinates rotated to fit *slightly* the camera orientation (note that here the camera vector goes toward the figure viewpoint, it does not &quot;enter&quot; the figure) and image coordinates.&#xD;&#xA;&#xD;&#xA;So we see that the vertical coordinates for the bottom points are correctly on the middle row (240) and the points are on the right side of the image (horizontal value &gt; 320).&#xD;&#xA;&#xD;&#xA;I believe one bug you had is that you found negative X values, so you negated the focals (`-f/Sxy`) in the intrinsics matrix to compensate. The issue here is that we've assumed that the camera initially was pointing toward $[0, 0, 1]$ (otherwise the 160° rotation would not point toward the points). If you look at it that way, the $x$-axis increases when going toward the *left*, the inverse of this axis should be taken.&#xD;&#xA;&#xD;&#xA;Both our results seems similar to me, just that you supposed a $[0, -1, 0]$ up vector for the camera (in fact both axes were mirrored because you negated both focals), and did the computation in mm instead of meters.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VIypz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SLLK5.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Ky8jK.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/cjiTE.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/aybff.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ca7xs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8467" PostHistoryTypeId="2" PostId="3949" RevisionGUID="c40bd9df-7b6c-46f1-96c1-135a6b210cfc" CreationDate="2016-09-05T03:02:35.950" UserId="48" Text="After asking around a bit on Twitter, I found that what you're trying to solve seems to be an instance of the [assignment problem](https://en.wikipedia.org/wiki/Assignment_problem). In general, the assignment problem is to take two sets and assign elements of one to the other, in such a way that a cost function is minimized.&#xD;&#xA;&#xD;&#xA;In your case the two sets would be the stars in each galaxy, and the cost function would be the distances between stars. An optimal solution to the assignment problem would then minimize the total distance between corresponding stars, summed over all the stars in the galaxies.&#xD;&#xA;&#xD;&#xA;A classic algorithm for solving the assignment problem is called the [Hungarian algorithm](https://en.wikipedia.org/wiki/Hungarian_algorithm). If you google around, you'll some explanations of how it works. There's even a Python module implementing this algorithm, called [Munkres](http://software.clapper.org/munkres/).&#xD;&#xA;&#xD;&#xA;A warning: this algorithm runs in $O(n^3)$ time, so it will be rather slow for large point sets. You might want to do some further research on fast algorithms for the assignment problem. It may be that you can find a faster, approximate algorithm if you don't require a perfectly optimal solution. Or maybe there are specialized algorithms for the case of point clouds that can do better." ContentLicense="CC BY-SA 3.0" />
  <row Id="8468" PostHistoryTypeId="2" PostId="3950" RevisionGUID="a93d5888-5e47-4121-9888-4f9608ce9b44" CreationDate="2016-09-05T08:49:28.463" UserId="2351" Text="Personally I have used equation 2. Equation 3 seems incorrect to me, the Pi factor is to normalise the light response and for energy conservation. Essentially you do not want more light to be reflected from the surface than what it receives. &#xA;&#xA;Equation 2 is an improvement of equation 1 and is more correct as far as I'm aware. For more information about equation 2, see **Microfacet Models for Refraction through Rough Surfaces** by Walter et al" ContentLicense="CC BY-SA 3.0" />
  <row Id="8469" PostHistoryTypeId="2" PostId="3951" RevisionGUID="03bc1c70-7391-47d2-885e-c4a5387a3959" CreationDate="2016-09-05T09:55:45.350" UserId="5039" Text="Standard blur removes high frequency content from the signal, whereas edge detection usually look into high frequency to detect edges. Be careful on how much blurring to apply to ensure that you don't lose desirable edges. The goal of blurring is to perform **noise reduction**, so the best would be to come up with a model of the noise present in your images and what your desired edges looks like (their frequency, orientation, what caused them: shading on a smooth object, shadows, etc.) and tailor your blur filter to remove the noise but not the edges.&#xD;&#xA;&#xD;&#xA;Seems like you want to implement an edge detector into a shader. Be sure to check what are the sources of noise in your image. For example, if you are displaying pure lambertian surfaces, chances are that there is virtually no noise in your data, so you don't need to apply a smoothing filter before detecting edges.&#xD;&#xA;&#xD;&#xA;Also, instead of using a standard gaussian blur, you could look into [edge-preserving filters][1] like the bilateral filter. It is much slower, but is good to remove noise without altering too much the edges.&#xD;&#xA;&#xD;&#xA;If you are performing filtering and edge detection through convolutions (the standard way of doing it), it doesn't matter if you do one before another, as convolutions are commutative, meaning $a*b = b*a$, where $*$ is the convolution operator, $a$ being the edge detector and $b$ the smoothing kernel.&#xD;&#xA;&#xD;&#xA;On non-associative operations (like the bilateral filter), you must ask yourself the question &quot;what is the goal of this operation?&quot; Basically, blurring before the edge detection will diminish the image noise while blurring after will give you blurred edges (potentially caused by noise) instead of sharp edges. The same edges will be found, though, but the blurred one will be less precise. It depends on what you want to achieve: it could be interesting for art, but it just removes interesting information for signal analysis.&#xD;&#xA;&#xD;&#xA;Not sure what &quot;applying an edge to a color buffer&quot; means; is the goal to perform [edge enhancement][2]?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Edge-preserving_smoothing&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Edge_enhancement" ContentLicense="CC BY-SA 3.0" />
  <row Id="8470" PostHistoryTypeId="2" PostId="3952" RevisionGUID="e61bbf9f-5e2f-4743-9ce4-155bfcdcb156" CreationDate="2016-09-05T11:07:12.020" UserId="5043" Text="I am creating a simple 3D engine as a learning project to get the hang on spherical trigonometry. I am using the following approach.&#xD;&#xA;1. A model consists of a lot of triangular faces.&#xD;&#xA;2. Each triangle is rendered through finding where the vectors pointing to the corners of it intersect a plane. This creates a flat projection I draw to the screen.&#xD;&#xA;&#xD;&#xA;[![projection][1]][1]&#xD;&#xA;&#xD;&#xA;I have already implemented this, and it works great, except when some of the corners of a triangle are located behind me.&#xD;&#xA;&#xD;&#xA;[![outside the view][2]][2]&#xD;&#xA;&#xD;&#xA;It is quite obvious what the problem is: The vector pointing to the corner is never intersecting the plane. But I need a point to render the projection, as a part of the triangle is visible.&#xD;&#xA;That causes trouble. I can not place the third corner anywhere on my projection plane, as the edges of the projected triangle are diverging when they escape the field of view.&#xD;&#xA;&#xD;&#xA;Logically, the edges of the projected triangle are thus pointing towards two **different** points on the plane outside the frame (or on the frame border, depending on taste and size of data types).&#xD;&#xA;&#xD;&#xA;[![frame of view][3]][3]&#xD;&#xA;&#xD;&#xA;Suddenly having to deal with rendering a four-sided polygon instead of a triangle is no problem, my rasterization algorithms are flexible. I can however not figure out how to calculate the locations of the new &quot;off-screen&quot; points. How can I find them?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eoV3E.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/w8Sw8.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/QKBLG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8471" PostHistoryTypeId="1" PostId="3952" RevisionGUID="e61bbf9f-5e2f-4743-9ce4-155bfcdcb156" CreationDate="2016-09-05T11:07:12.020" UserId="5043" Text="Where should I project a polygon corner when it is behind me?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8472" PostHistoryTypeId="3" PostId="3952" RevisionGUID="e61bbf9f-5e2f-4743-9ce4-155bfcdcb156" CreationDate="2016-09-05T11:07:12.020" UserId="5043" Text="|3d|geometry|projections|polygon|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8473" PostHistoryTypeId="2" PostId="3953" RevisionGUID="93089ceb-bf76-4c0e-9294-cc2cc3107f83" CreationDate="2016-09-05T12:09:40.927" UserId="209" Text="Rather than trying to speed up your shader by fiddling with the code, can I suggest you make use of the GPU's inherent ability to rapidly fill polygons? This will allow it to eliminate the vast bulk of the cases where there is no need to even make a decision.&#xD;&#xA;&#xD;&#xA;What I suggest you try is _something_ like the following: Create, say, a heptagon (i.e. the blue dashed outline (*note: it shares some of the boundary with the green but I just noticed this is not particularly obvious in the diagram*)) that starts from the original location and extends to the new position but lies inside the extremes of the new location's circle. &#xD;&#xA;The shader for this is then utterly trivial.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Then there can be one or two cases depending on how much you want to optimise. If the tail extends outside of the end position circle, you draw the green-dashed nonagon with your decision-based shader. This contains vastly fewer pixels. &#xD;&#xA;If the tail doesn't extend outside, then you'll need to mirror this polygon to get the other side of the circle. Alternatively, rather than make the decision, you could always mirror it and let the Z-test eliminate unneeded fills.&#xD;&#xA;&#xD;&#xA;Your examples also have the have the capsules shown as opaque. If this is the case, you can also make gains with, say, TBDR-systems (a blatant plug) or those with early-Z, provided you supply all your opaque &quot;tail&quot; portions first and then follow with all parts requiring decisions.&#xD;&#xA;&#xD;&#xA;The shapes of course were just examples. You may find it's better to use more segments in your outlines in order to reduce the regions requiring the complex shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UXeIn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8474" PostHistoryTypeId="2" PostId="3954" RevisionGUID="3af911ba-57f1-44b0-9914-17ecacec2957" CreationDate="2016-09-05T13:32:14.480" UserId="5043" Text="Trying to explain a problem seems to help the thought process. This is what eventually worked for me:&#xD;&#xA;&#xD;&#xA;I realized that I can easily find the point (in 3D space) where a line between two of the corners brakes through one of the walls in my pyramid field of view, given the coordinates of the out-of-view corner and one of the visible ones. It is only a matter of finding the intersection between two lines. The position of the intersection point gives away the height on the frame wall.&#xD;&#xA;&#xD;&#xA;[![wall intersection][1]][1]&#xD;&#xA;&#xD;&#xA;Self answer, yes, but nothing came to mind before posting at SE.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fOz83.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8475" PostHistoryTypeId="2" PostId="3955" RevisionGUID="1a6a43ce-b9a7-4ef6-84f9-157b96059dbd" CreationDate="2016-09-05T21:20:35.890" UserId="2237" Text="I implemented a physically based path tracer after studying PBRT by M. Pharr and G. Humphreys. Now I'm trying to apply physically based rendering to real time graphics using OpenGL ES (in an iPhone application).&#xD;&#xA;&#xD;&#xA;I want to start using Oren-Nayar and Cook-Torrance as diffuse and specular BRDF but I have a problem: how do I model indirect lighting?&#xD;&#xA;&#xD;&#xA;In a path tracer (like the one contained in pbrt) the indirect/ambient light is given &quot;automatically&quot; from the path tracing algorithm, as it follows the path of light rays taking into account direct and indirect lighting.&#xD;&#xA;&#xD;&#xA;How do I model the indirect lighting in a physically based render written in OpenGL ES, so using real time computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8476" PostHistoryTypeId="1" PostId="3955" RevisionGUID="1a6a43ce-b9a7-4ef6-84f9-157b96059dbd" CreationDate="2016-09-05T21:20:35.890" UserId="2237" Text="Physically based shading - ambient/indirect lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="8477" PostHistoryTypeId="3" PostId="3955" RevisionGUID="1a6a43ce-b9a7-4ef6-84f9-157b96059dbd" CreationDate="2016-09-05T21:20:35.890" UserId="2237" Text="|real-time|physically-based|shading|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8478" PostHistoryTypeId="2" PostId="3956" RevisionGUID="b5bc6e0d-6d77-4318-854f-17e36d35ee06" CreationDate="2016-09-05T21:50:21.310" UserId="48" Text="I would trust Pharr and Humphreys on this. Equation 2 also agrees with the [SIGGRAPH Physically Based Rendering course notes](http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf#57), as well as with equation 20 in the [Walter et al paper](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf) that introduced the GGX distribution.&#xD;&#xA;&#xD;&#xA;I've read somewhere that there is an error in the original Cook-Torrance paper that led them to miss the factor of 4 in the denominator, which was corrected in subsequent papers. I couldn't find a reference to this with a quick search though (if anyone knows one, please feel free to note it in the comments).&#xD;&#xA;&#xD;&#xA;As for the factor of π, it might appear or not, depending on conventions. Sometimes it's factored into the normal distribution function D. For instance, if you look in the Walter et all GGX paper section 5.2 where they give the equations for several D functions, you can see they all have a π in the denominator. Note that this implies that the Lambertian BRDF should have a π in the denominator as well.&#xD;&#xA;&#xD;&#xA;In real-time graphics, the π is often left out, in which case we can interpret it as [having been factored into the light colors](https://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/). Either way is fine, as long as you're consistent about either putting the π in or leaving it out of _all_ the BRDFs you use." ContentLicense="CC BY-SA 3.0" />
  <row Id="8479" PostHistoryTypeId="2" PostId="3957" RevisionGUID="da471d16-c07a-457b-9595-3364a3825293" CreationDate="2016-09-05T22:34:44.773" UserId="2351" Text="Path tracing is a very computationally expensive algorithm, and not suited to real-time. PBRT's architecture is not suited to real-time either, the main goal of PBRT is to solve the rendering equation, using unbiased Monte Carlo integration. See https://en.wikipedia.org/wiki/Unbiased_rendering for more info.&#xD;&#xA;&#xD;&#xA;Without a lot of optimization and constraints, I doubt you'll be able to reach decent performance on a mobile device.&#xD;&#xA;&#xD;&#xA;In any case, path tracing can be implemented in OpenGL, I would suggest to look into **compute shaders** which are very powerful. OpenGL ES 3.1 supports compute shaders with some minor limitations, in contrast to Desktop GL.&#xD;&#xA;&#xD;&#xA;Have a read through this page to get more information: https://github.com/LWJGL/lwjgl3-wiki/wiki/2.6.1.-Ray-tracing-with-OpenGL-Compute-Shaders-(Part-I)&#xD;&#xA;&#xD;&#xA;Best of luck!" ContentLicense="CC BY-SA 3.0" />
  <row Id="8484" PostHistoryTypeId="2" PostId="3959" RevisionGUID="b96a7749-d6a0-4894-9412-0c7759fa3112" CreationDate="2016-09-06T07:34:23.493" UserId="48" Text="Real-time graphics deploys a variety of approximations to deal with the computational expense of simulating indirect lighting, trading off between runtime performance and lighting fidelity. This is an area of active research, with new techniques appearing every year.&#xD;&#xA;&#xD;&#xA;## Ambient lighting&#xD;&#xA;&#xD;&#xA;At the very simplest end of the range, you can use [**ambient lighting**](https://en.wikipedia.org/wiki/Shading#Ambient_lighting): a global, omnidirectional light source that applies to every object in the scene, without regard to actual light sources or local visibility. This is not at all accurate, but is extremely cheap, easy for an artist to tweak, and can look okay depending on the scene and the desired visual style.&#xD;&#xA;&#xD;&#xA;Common extensions to basic ambient lighting include:&#xD;&#xA;&#xD;&#xA;* Make the ambient color vary directionally, e.g. using [spherical harmonics (SH)](https://dickyjim.wordpress.com/2013/09/04/spherical-harmonics-for-beginners/) or a [small cubemap](http://www.valvesoftware.com/publications/2006/SIGGRAPH06_Course_ShadingInValvesSourceEngine.pdf#5), and looking up the color in a shader based on each vertex's or pixel's normal vector. This allows some visual differentiation between surfaces of different orientations, even where no direct light reaches them.&#xD;&#xA;* Apply [ambient occlusion (AO)](https://en.wikipedia.org/wiki/Ambient_occlusion) techniques including pre-computed vertex AO, AO texture maps, [AO fields](http://www.gdcvault.com/play/1015320/Ambient-Occlusion-Fields-and-Decals), and [screen-space AO (SSAO)](http://graphics.cs.williams.edu/papers/SAOHPG12/). These all work by attempting to detect areas such as holes and crevices where indirect light is less likely to bounce into, and darkening the ambient light there.&#xD;&#xA;* Add an [environment cubemap](http://learnopengl.com/#!Advanced-OpenGL/Cubemaps) to provide ambient specular reflection. A cubemap with a decent resolution (128² or 256² per face) can be quite convincing for specular on curved, shiny surfaces.&#xD;&#xA;&#xD;&#xA;## Baked indirect lighting&#xD;&#xA;&#xD;&#xA;The next &quot;level&quot;, so to speak, of techniques involve **baking** (pre-computing offline) some representation of the indirect lighting in a scene. The advantage of baking is you can get pretty high-quality results for little real-time computational expense, since all the hard parts are done in the bake. The trade-offs are that the time needed for the bake process harms level designers' iteration rate; more memory and disk space are required to store the precomputed data; the ability to change the lighting in real-time is very limited; and the bake process can only use information from static level geometry, so indirect lighting effects from dynamic objects such as characters will be missed. Still, baked lighting is very widely used in AAA games today.&#xD;&#xA;&#xD;&#xA;The bake step can use any desired rendering algorithm including path tracing, radiosity, or using the game engine itself to render out cubemaps (or [hemicubes](http://the-witness.net/news/2010/09/hemicube-rendering-and-integration/)).&#xD;&#xA;&#xD;&#xA;The results can be stored in textures ([lightmaps](https://en.wikipedia.org/wiki/Lightmap)) applied to static geometry in the level, and/or they can also be converted to SH and stored in volumetric data structures, such as [irradiance volumes](http://simonstechblog.blogspot.com/2014_10_01_archive.html) (volume textures where each texel stores an SH probe) or [tetrahedral meshes](http://www.gdcvault.com/play/1015312/Light-Probe-Interpolation-Using-Tetrahedral). You can then use shaders to look up and interpolate colors from that data structure and apply them to your rendered geometry. The volumetric approach allows baked lighting to be applied to dynamic objects as well as static geometry.&#xD;&#xA;&#xD;&#xA;The spatial resolution of the lightmaps etc. will be limited by memory and other practical constraints, so you might supplement the baked lighting with some AO techniques to add high-frequency detail that the baked lighting can't provide, and to respond to dynamic objects (such as darkening the indirect light under a moving character or vehicle).&#xD;&#xA;&#xD;&#xA;There's also a technique called [precomputed radiance transfer (PRT)](http://www0.cs.ucl.ac.uk/staff/j.kautz/PRTCourse/), which extends baking to handle more dynamic lighting conditions. In PRT, instead of baking the indirect lighting itself, you bake the _transfer function_ from some source of light—usually the sky—to the resultant indirect lighting in the scene. The transfer function is represented as a matrix that transforms from source to destination SH coefficients at each bake sample point. This allows the lighting environment to be changed, and the indirect lighting in the scene will respond plausibly. [Far Cry 3 and 4 used this technique](http://www.gdcvault.com/play/1015326/Deferred-Radiance-Transfer-Volumes-Global) to allow a continuous day-night cycle, with indirect lighting varying based on the sky colors at each time of day.&#xD;&#xA;&#xD;&#xA;One other point about baking: it may be useful to have separate baked data for diffuse and specular indirect lighting. Cubemaps work much better than SH for specular (since cubemaps can have a lot more angular detail), but they also take up a lot more memory, so you can't afford to place them as densely as SH samples. [Parallax correction](https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/) can be used to somewhat make up for that, by heuristically warping the cubemap to make its reflections feel more grounded to the geometry around it.&#xD;&#xA;&#xD;&#xA;## Fully real-time techniques&#xD;&#xA;&#xD;&#xA;Finally, it's possible to compute fully dynamic indirect lighting on the GPU. It can respond in real-time to arbitrary changes of lighting or geometry. However, again there is a tradeoff between runtime performance, lighting fidelity, and scene size. Some of these techniques need a beefy GPU to work at all, and may only be feasible for limited scene sizes. They also typically support only a single bounce of indirect light.&#xD;&#xA;&#xD;&#xA;* [Screen-space global illumination](http://people.mpi-inf.mpg.de/~ritschel/Papers/SSDO.pdf), an extension of SSAO that gathers bounce lighting from nearby pixels on the screen in a post-processing pass.&#xD;&#xA;* [Screen-space raytraced reflection](http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html) works by ray-marching through the depth buffer in a post-pass. It can provide quite high-quality reflections as long as the reflected objects are on-screen.&#xD;&#xA;* [Instant radiosity](https://www.cg.tuwien.ac.at/courses/RendEng/RendEng-2016-01-11-InstantRadiosity.pdf) works by tracing rays into the scene using the CPU, and placing a point light at each ray hit point, which approximately represents the outgoing reflected light in all directions from that ray. These many lights, known as virtual point lights (VPLs), are then rendered by the GPU in the usual way.&#xD;&#xA;* [Reflective shadow maps (RSMs)](http://www.klayge.org/material/3_12/GI/rsm.pdf) are similar to instant radiosity, but the VPLs are generated by rendering the scene from the light's point of view (like a shadow map) and placing a VPL at each pixel of this map.&#xD;&#xA;* [Light propagation volumes](http://www.crytek.com/download/Light_Propagation_Volumes.pdf) consist of 3D grids of SH probes placed throughout the scene. RSMs are rendered and used to &quot;inject&quot; bounce light into the SH probes nearest the reflecting surfaces. Then a flood-fill-like process propagates light from each SH probe to surrounding points in the grid, and the result of this is used to apply lighting to the scene. This technique [has been extended to volumetric light scattering](https://newq.net/archived/www.cse.chalmers.se/pub/scatter/index.html) as well.&#xD;&#xA;* [Voxel cone tracing](http://maverick.inria.fr/Publications/2011/CNSGE11b/) works by voxelizing the scene geometry (likely using varying voxel resolutions, finer near the camera and coarser far away), then injecting light from RSMs into the voxel grid. When rendering the main scene, the pixel shader performs a &quot;cone trace&quot;—a ray-march with gradually increasing radius—through the voxel grid to gather incoming light for either diffuse or specular shading.&#xD;&#xA;&#xD;&#xA;Most of these techniques are not widely used in games today due to problems scaling up to realistic scene sizes, or other limitations. The exception is screen-space reflection, which is very popular (though it's usually used with cubemaps as a fallback, for regions where the screen-space part fails).&#xD;&#xA;&#xD;&#xA;As you can see, real-time indirect lighting is a huge topic and even this (rather long!) answer can only provide a 10,000-foot overview and context for further reading. Which approach is best for you will depend greatly on the details of your particular application, what constraints you're willing to accept, and how much time you have to put into it." ContentLicense="CC BY-SA 3.0" />
  <row Id="8485" PostHistoryTypeId="2" PostId="3960" RevisionGUID="2deabebb-de78-4639-975a-3205c42f433f" CreationDate="2016-09-06T07:56:59.850" UserId="5026" Text="I'm still working on my BRDF equations. Theoretically, all equations are correct, but the hilights are super sharp. I'm not sure if this is a result of  me not using Image-Based Lighting (I currently use just an env map with a LOD function). I'm using materials from here: http://freepbr.com/c/base-materials/ - I use Specular/Gloss but the materials use the fragment shader to convert it.&#xD;&#xA;&#xD;&#xA;[![Bright Highlights][1]][1]&#xD;&#xA;&#xD;&#xA;Material Frag Shader (Excerpt) (Specifically, the Metalness-Roughness shader):&#xD;&#xA;&#xD;&#xA;    float Roughness = baseSpecular.a;&#xD;&#xA;    if (uTexRoughEnabled == 1)&#xD;&#xA;    	Roughness = texture(texRoughness, UV).r;&#xD;&#xA;    &#xD;&#xA;    float Metalness = texture(texSpecular, UV).r;&#xD;&#xA;    &#xD;&#xA;    // 1 - Roughness becomes Glossiness&#xD;&#xA;    specular = vec4(mix(vec3(0.4), albedo.rgb, Metalness), 1-Roughness);&#xD;&#xA;    albedo = vec4(mix(albedo.rgb, vec3(0), Metalness), 1-Roughness);&#xD;&#xA;&#xD;&#xA;Lighting Functions:&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH) {&#xD;&#xA;    	// Fresnel Schlick&#xD;&#xA;    	return Specular + (1-Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float Light_D(in float alpha, in float NH) {&#xD;&#xA;    	// GGX&#xD;&#xA;    	float alphaSqr = alpha*alpha;&#xD;&#xA;    	float denom = NH * NH * (alphaSqr - 1) + 1;&#xD;&#xA;    &#xD;&#xA;    	return alphaSqr / (pi * denom * denom);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float Light_V( in float NL, in float NV, in float alpha ) {&#xD;&#xA;    	// Frostbite's GGX&#xD;&#xA;    	float Lambda_GGXV = NL * sqrt (( - NV * alpha + NV ) * NV + alpha );&#xD;&#xA;    	float Lambda_GGXL = NV * sqrt (( - NL * alpha + NL ) * NL + alpha );&#xD;&#xA;    &#xD;&#xA;    	return 0.5f / ( Lambda_GGXV + Lambda_GGXL );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 Light_Diffuse(in float NV, in float NL, in vec3 Normal, in float alpha, in vec3 Albedo, in vec3 eyeDir, in vec3 lightDir) {&#xD;&#xA;            // Oren-Nayar&#xD;&#xA;            float gamma = dot( eyeDir - Normal * NV, lightDir - Normal * NL);&#xD;&#xA;            float A = 1.0f - 0.5f * (alpha / (alpha + 0.57f));&#xD;&#xA;            float B = 0.45f * (alpha / (alpha + 0.09));&#xD;&#xA;    	float diffAlpha = max( acos( NV ), acos( NL ) );&#xD;&#xA;    	float diffBeta  = min( acos( NV ), acos( NL ) );&#xD;&#xA;    	float C = sin(diffAlpha) * tan(diffBeta);&#xD;&#xA;    	return Albedo * (A + B * max( 0.0f, gamma ) * C) / pi;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Final lighting function in deferred renderer:&#xD;&#xA;&#xD;&#xA;    vec3 LightCalc(in vec3 Albedo, in vec4 WorldPos, in vec4 Specular, in vec3 Normal, in samplerCube envMap, in vec3 lightPos, in float lightAtten, in vec4 lightColor) {&#xD;&#xA;    	vec3 lightDir	= WorldPos.xyz - lightPos;&#xD;&#xA;    	vec3 eyeDir	= normalize(eyePos - WorldPos.xyz);&#xD;&#xA;    	vec3 eyeReflect = reflect(-eyeDir, Normal);&#xD;&#xA;    	&#xD;&#xA;    	float Distance	= length(lightDir);&#xD;&#xA;    	lightDir		= -normalize(lightDir);&#xD;&#xA;    	&#xD;&#xA;    	float Attenuation = clamp(1 - pow(Distance / lightAtten, 4), 0, 1);&#xD;&#xA;    	Attenuation = Attenuation*Attenuation/(Distance*Distance+1);&#xD;&#xA;    	&#xD;&#xA;    	vec3 AmbientColor = vec3(Albedo.xyz)*0.01;&#xD;&#xA;    	&#xD;&#xA;    	float Roughness = 1-Specular.a;&#xD;&#xA;    	float alpha = Roughness * Roughness;&#xD;&#xA;    	&#xD;&#xA;    	vec3 H = normalize(eyeDir + lightDir);&#xD;&#xA;    	&#xD;&#xA;    	float NL = clamp(dot(Normal, lightDir), 0, 1);&#xD;&#xA;    	float NH = clamp(dot(Normal, H), 0, 1);&#xD;&#xA;    	float NV = clamp(dot(Normal, eyeDir), 0, 1);&#xD;&#xA;    	float LH = clamp(dot(lightDir, H), 0, 1);&#xD;&#xA;    	float VH = clamp(dot(eyeDir, H), 0, 1);&#xD;&#xA;    	&#xD;&#xA;    	float lod = compute_lod(alpha, 1, NH);&#xD;&#xA;    	vec3 reflectDir = normalize(eyeReflect);&#xD;&#xA;    	vec3 reflectPix = textureLod(envMap, reflectDir, lod).rgb;&#xD;&#xA;    	&#xD;&#xA;    	float D = Light_D(alpha, NH);&#xD;&#xA;    	vec3 F = Light_F(clamp(Specular.rgb, 0.018, 0.95), LH);&#xD;&#xA;    	float Vis = Light_V(NL, NV, alpha);&#xD;&#xA;    	vec3 Spec = (D * F * Vis) * reflectPix;&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	vec3 Diffuse = Light_Diffuse(NV, NL, Normal, alpha, Albedo.rgb, eyeDir, lightDir);&#xD;&#xA;    &#xD;&#xA;    	vec3 lightModifier = lightColor.xyz*lightColor.w*Attenuation;&#xD;&#xA;    	return NL*(Spec + max(Diffuse, AmbientColor))*lightModifier;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Feel free to point out any mistakes I made, even if not related to the issue. I've tested the materials in Unreal, and they looked correct. I doubt this is solely due to the lack of Image-Based Lighting. I also doubt this is an issue with using point lighting. Additionally, if I turn down the roughness by a lot, it becomes too dark a high roughness to be the issue.&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/pjbtv.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8486" PostHistoryTypeId="1" PostId="3960" RevisionGUID="2deabebb-de78-4639-975a-3205c42f433f" CreationDate="2016-09-06T07:56:59.850" UserId="5026" Text="Bug: Overly Sharp Highlights in PBR" ContentLicense="CC BY-SA 3.0" />
  <row Id="8487" PostHistoryTypeId="3" PostId="3960" RevisionGUID="2deabebb-de78-4639-975a-3205c42f433f" CreationDate="2016-09-06T07:56:59.850" UserId="5026" Text="|glsl|brdf|specular|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8488" PostHistoryTypeId="2" PostId="3961" RevisionGUID="64d82a14-8656-47ec-800f-922b00aec8f5" CreationDate="2016-09-06T08:11:17.577" UserId="1937" Text="This is the main 'hard' problem remaining in real-time CG, and there is a lot of research ongoing into solving it. &#xD;&#xA;&#xD;&#xA;The biggest hurdle is that in raster graphics, each component of the scene is rendered 'in a vacuum' - each triangle is rendered without reference to any other triangles in the scene, and the same goes for pixels, as opposed to ray-tracing approaches where each ray has access to the entire scene in memory. So real-time programmers need to use hacky tricks to do stuff like reflections and shadows, and the same applies to global illumination.&#xD;&#xA;&#xD;&#xA;A cheap runtime method is to use baked light-maps, where you run something slow-but-awesome like radiosity or path-tracing offline first, then save the lighting information along with your regular vertex data. This is great for static geometry, but becomes problematic as soon as you add moving objects. Michal Iwanicki did a good [presentation][1] on how they solved this for 'The Last of Us'.&#xD;&#xA;&#xD;&#xA;[Spherical Harmonics][2] are used a lot in game engines to represent indirect light. They're basically a Fourier transform across the surface of a sphere, by discarding high-frequency components you can get visually pleasing, mostly accurate environment lighting in only 9 coefficients per-color. Unity, for example, uses S.H. to bake 'light probes' at various points in the scene, moving objects can then interpolate between nearby probes to get an approximation of the indirect light at their position. Robin Green's [paper][3] is basically the bible on this technique, but it's pretty heavy going.&#xD;&#xA;&#xD;&#xA;The hot technique at the moment seems to be Voxel Cone Tracing, which doesn't involve any pre-bake step. I'm not too familiar with it myself, but as I understand it, it involves voxelizing your scene into a low-res Minecraft-style world, placing the voxels into a quickly-traversable spatial structure like an octree, then casting a few wide rays (cones) from each point and checking which voxels they hit to gather bounce lighting. NVidia is pushing this pretty hard at the moment, and there are papers on it [here][4] and [here][5].&#xD;&#xA;&#xD;&#xA;Hope that helps :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://miciwan.com/SIGGRAPH2013/Lighting%20Technology%20of%20The%20Last%20Of%20Us.pdf&#xD;&#xA;  [2]: http://Spherical%20Harmonics&#xD;&#xA;  [3]: https://graphics.cg.uni-saarland.de/fileadmin/cguds/courses/ss15/ris/slides/RIS18Green.pdf&#xD;&#xA;  [4]: https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf&#xD;&#xA;  [5]: http://simonstechblog.blogspot.sg/2013/01/implementing-voxel-cone-tracing.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8495" PostHistoryTypeId="2" PostId="3963" RevisionGUID="a51aac65-3679-4573-8082-0f90058d2a97" CreationDate="2016-09-07T10:11:05.043" UserId="4958" Text="Raw volume raymarching especially aligned with frustum seem to produce a lot of aliasing/banding on edges of shadow map. Especially when fragment pos is far because step length is then getting bigger. Making some research how to correct it I found out about temporal reprojection technique.&#xD;&#xA;&#xD;&#xA;So basically I have an two 2D textures, current and previous where I store exponential moving average of raymarching result of previous frames like:&#xD;&#xA;&#xD;&#xA;$s(n) = w*f(n)+(1-w)*s(n-1)$&#xD;&#xA;&#xD;&#xA;where:&#xD;&#xA;&#xD;&#xA;$w$ - weight&#xD;&#xA;&#xD;&#xA;$f(n)$ - current frame calculation&#xD;&#xA;&#xD;&#xA;$s(n-1)$ - result of previous frames calculation&#xD;&#xA;&#xD;&#xA;This seem to be working when camera is moving because then bands are moving and blending with each other. But when camera stands still everything returns to normal. I tried to:&#xD;&#xA;&#xD;&#xA; - add some noise aligned with ray direction to starting position every other frame but banding is still at the same positions&#xD;&#xA; - add noise not aligned with ray direction but then bands are shifted ramdomly and raymarching results are wrong&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Here][1] (FrostBite engine) it is smooth constantly independent of camera movement.  &#xD;&#xA;&#xD;&#xA;So is there a way to simulate camera movements? Or any other technique to correct the issue?&#xD;&#xA;&#xD;&#xA;[Here][2] you can download some content describing subject.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=yjoD6RCuM4c&#xD;&#xA;  [2]: http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8496" PostHistoryTypeId="1" PostId="3963" RevisionGUID="a51aac65-3679-4573-8082-0f90058d2a97" CreationDate="2016-09-07T10:11:05.043" UserId="4958" Text="Frustum aligned volume integration - aliasing issue - temporal reprojection" ContentLicense="CC BY-SA 3.0" />
  <row Id="8497" PostHistoryTypeId="3" PostId="3963" RevisionGUID="a51aac65-3679-4573-8082-0f90058d2a97" CreationDate="2016-09-07T10:11:05.043" UserId="4958" Text="|texture|3d|volumetric|raymarching|3dtexture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8498" PostHistoryTypeId="34" PostId="1759" RevisionGUID="440caaf8-2823-4ba4-9a02-b22143d4494f" CreationDate="2016-09-07T16:34:33.990" UserId="231" Comment="20" />
  <row Id="8499" PostHistoryTypeId="2" PostId="3964" RevisionGUID="990b22d3-54bf-4efe-8c81-76e2cd7d6769" CreationDate="2016-09-07T19:17:05.367" UserId="3377" Text="I use Phong shading as my lightning model. Nevertheless, The specular shading produces gradients in the light cone:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Hopefully you can see the gradients starting from the lower left corner expanding along the cuboid.&#xD;&#xA;&#xD;&#xA;Here is the shader code that produces this specular light:&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = normalize(-FragPos);&#xD;&#xA;    vec3 lightDir = normalize(-light.direction);&#xD;&#xA;    vec3 reflectDir = reflect(-lightDir, normal);&#xD;&#xA;	float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);&#xD;&#xA;&#xD;&#xA;By the way, I'm doing my lighting calculations in view-space. &#xD;&#xA;&#xD;&#xA;Is there any chance to make the lighing smoother?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RknYH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8500" PostHistoryTypeId="1" PostId="3964" RevisionGUID="990b22d3-54bf-4efe-8c81-76e2cd7d6769" CreationDate="2016-09-07T19:17:05.367" UserId="3377" Text="OpenGL diffuse shading- Gradient issues" ContentLicense="CC BY-SA 3.0" />
  <row Id="8501" PostHistoryTypeId="3" PostId="3964" RevisionGUID="990b22d3-54bf-4efe-8c81-76e2cd7d6769" CreationDate="2016-09-07T19:17:05.367" UserId="3377" Text="|opengl|glsl|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8502" PostHistoryTypeId="4" PostId="3964" RevisionGUID="75c38dc1-e3ae-4fc9-b0a7-b2890297d6bc" CreationDate="2016-09-08T05:20:39.007" UserId="506" Comment="clarified title" Text="OpenGL specular shading- Gradient banding issues" ContentLicense="CC BY-SA 3.0" />
  <row Id="8503" PostHistoryTypeId="24" PostId="3964" RevisionGUID="75c38dc1-e3ae-4fc9-b0a7-b2890297d6bc" CreationDate="2016-09-08T05:20:39.007" Comment="Proposed by 506 approved by 182, 48 edit id of 161" ContentLicense="CC BY-SA 3.0" />
  <row Id="8504" PostHistoryTypeId="2" PostId="3965" RevisionGUID="5eeed15e-56bb-4cad-a444-952a1c966952" CreationDate="2016-09-08T05:45:00.897" UserId="48" Text="This is a common problem with very subtle gradients. The problem is that the image is displayed with 8 bits per component and this is not quite enough precision to make a gradient that is smooth to the eye under these conditions.&#xD;&#xA;&#xD;&#xA;However, the underlying calculations being done in the shader are at higher precision (e.g. float = 24 effective bits of mantissa), so you can apply dithering to improve the appearance of the image.&#xD;&#xA;&#xD;&#xA;You can do this by adding a slight amount of random noise to the value of each pixel in the shader. The noise can come from a texture, filled with random grayscale values in [0, 1] and mapped 1:1 to screen pixels. In the shader you remap this to the range [−0.5/255, 0.5/255] and add it to the output color.&#xD;&#xA;&#xD;&#xA;[Here's a Shadertoy demonstrating this.](https://www.shadertoy.com/view/MlV3R1) The left side has no dithering; the right side uses the procedure just described. As you can see, the banding vanishes on the right.&#xD;&#xA;&#xD;&#xA;[![banding on left; dithered on right][1]][1]&#xD;&#xA;&#xD;&#xA;Dithering effectively allows you to represent intermediate values between 8-bit integer levels. For instance, an area that the shader computes as 82.3 (out of 255) would normally be uniformly rounded down to 82, but with dithering it will come out as a random mix with 70% of the pixels set to 82, and 30% set to 83. The eye averages over this very slight, high-frequency noise and it becomes practically invisible.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/X61tI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8509" PostHistoryTypeId="2" PostId="3967" RevisionGUID="65d06a12-c834-47f9-b573-f13954e34faa" CreationDate="2016-09-08T15:52:02.190" UserId="5082" Text="I need a lot of real time rendered images and real images where it's recorded which one is which to prove either way whether existing gaming computers have the hardware to be photo-realistic to someone I know (which they will have if they're unable to tell the difference, statistically) at their best. Please can someone link me to what I'm looking for? Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="8510" PostHistoryTypeId="1" PostId="3967" RevisionGUID="65d06a12-c834-47f9-b573-f13954e34faa" CreationDate="2016-09-08T15:52:02.190" UserId="5082" Text="Photo-realism blind experiment" ContentLicense="CC BY-SA 3.0" />
  <row Id="8511" PostHistoryTypeId="3" PostId="3967" RevisionGUID="65d06a12-c834-47f9-b573-f13954e34faa" CreationDate="2016-09-08T15:52:02.190" UserId="5082" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8512" PostHistoryTypeId="2" PostId="3968" RevisionGUID="90872a96-6fcc-417b-8d4c-21d3627c97ec" CreationDate="2016-09-08T16:04:28.537" UserId="56" Text="Path tracing is a common method for making photo realistic images.  If I were you, I'd start off doing a google image search for path tracing to find some images.&#xD;&#xA;&#xD;&#xA;You may get lucky and find a site that has a lot of them.&#xD;&#xA;&#xD;&#xA;Here are a few examples I found doing that:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LEVpW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fui1d.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sFkkp.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/XXF1U.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8513" PostHistoryTypeId="50" PostId="3837" RevisionGUID="b005cb88-02d4-4855-8633-0bfda493c5c5" CreationDate="2016-09-08T18:27:29.033" UserId="-1" />
  <row Id="8514" PostHistoryTypeId="2" PostId="3969" RevisionGUID="eda2ead7-7078-46a8-8bf0-f5581bfdd70b" CreationDate="2016-09-08T20:41:57.200" UserId="4647" Text="I'm trying to get the correct representation of visible spectrum to render on the screen. My current progress is with using CIE 1931 standard observer color matching functions analytically approximated by the equations given in [this paper](http://jcgt.org/published/0002/02/01/paper.pdf). Current image is like this:&#xD;&#xA;&#xD;&#xA;[![current image I could generate][1]][1]&#xD;&#xA;&#xD;&#xA;Here the background is not ideally black to make it possible to introduce the negative contributions from the color matching functions:&#xD;&#xA;&#xD;&#xA;[![color matching functions][2]][2]&#xD;&#xA;&#xD;&#xA;But the problem with it is that the image seems to have a dip in intensity somewhere around 490 nm. I guess that this is related to the sum of the three functions having a minimum there. See the sum plotted against wavelength:&#xD;&#xA;&#xD;&#xA;[![sum of three color matching functions][3]][3]&#xD;&#xA;&#xD;&#xA;So my question is now: how do I fix the intensity of the image? Is there any standard for taking spectral sensitivity into account when converting wavelength to RGB/XYZ representation?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xzsvc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/NctGH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/sbazx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8515" PostHistoryTypeId="1" PostId="3969" RevisionGUID="eda2ead7-7078-46a8-8bf0-f5581bfdd70b" CreationDate="2016-09-08T20:41:57.200" UserId="4647" Text="How to correctly render visible spectrum of with intensity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8516" PostHistoryTypeId="3" PostId="3969" RevisionGUID="eda2ead7-7078-46a8-8bf0-f5581bfdd70b" CreationDate="2016-09-08T20:41:57.200" UserId="4647" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8518" PostHistoryTypeId="5" PostId="3969" RevisionGUID="177f58fe-e4ec-497f-a6ba-bc62814261d0" CreationDate="2016-09-08T20:47:42.597" UserId="4647" Comment="deleted 9 characters in body" Text="I'm trying to get the correct representation of visible spectrum to render on the screen. My current progress is with using CIE 1931 standard observer color matching functions analytically approximated by the equations given in [this paper](http://jcgt.org/published/0002/02/01/). Current image is like this:&#xD;&#xA;&#xD;&#xA;[![current image I could generate][1]][1]&#xD;&#xA;&#xD;&#xA;Here the background is not ideally black to make it possible to introduce the negative contributions from the color matching functions:&#xD;&#xA;&#xD;&#xA;[![color matching functions][2]][2]&#xD;&#xA;&#xD;&#xA;But the problem with it is that the image seems to have a dip in intensity somewhere around 490 nm. I guess that this is related to the sum of the three functions having a minimum there. See the sum plotted against wavelength:&#xD;&#xA;&#xD;&#xA;[![sum of three color matching functions][3]][3]&#xD;&#xA;&#xD;&#xA;So my question is now: how do I fix the intensity of the image? Is there any standard for taking spectral sensitivity into account when converting wavelength to RGB/XYZ representation?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xzsvc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/NctGH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/sbazx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8520" PostHistoryTypeId="4" PostId="3969" RevisionGUID="5e90385e-b9ac-419b-9dcd-1200fe0c9599" CreationDate="2016-09-09T05:30:35.047" UserId="4647" Comment="edited title" Text="How to correctly render visible spectrum with uniform intensity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8521" PostHistoryTypeId="2" PostId="3970" RevisionGUID="49b63c2e-e92c-4049-8fa2-c40fb9504cfc" CreationDate="2016-09-09T08:03:14.227" UserId="4647" Text="Suppose you have generated an image using linear values for RGB channels. E.g. you linearly interpolated it when doing blending, etc.. When you're going to present this on the screen, should the values be transformed as $C_{\mathrm{linear}}\to C_{\mathrm{sRGB}}$ as given [here](https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29) or backwards as described [here](https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation)?&#xD;&#xA;&#xD;&#xA;It would seem that the image should be encoded in sRGB, thus the forward transformation is necessary. But I've measured response of my monitor, and it appears that to have linearly changing brightness with input RGB, the color data have to be transformed as $C_{\mathrm{sRGB}}\to C_{\mathrm{linear}}$ as if my image were already in sRGB color space (the behavior is consistent with that described in [another question](http://computergraphics.stackexchange.com/q/1587/4647)).&#xD;&#xA;&#xD;&#xA;So is it correct that to render and present an image one has to do the following:&#xD;&#xA;&#xD;&#xA;1. Draw in linear RGB to have correct blending&#xD;&#xA;2. Treating the data _as if_ they were sRGB, convert to linear RGB&#xD;&#xA;3. Present on screen, so that monitor now converts this back&#xD;&#xA;&#xD;&#xA;Then the result will be linear as expected. Or am I missing something?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8522" PostHistoryTypeId="1" PostId="3970" RevisionGUID="49b63c2e-e92c-4049-8fa2-c40fb9504cfc" CreationDate="2016-09-09T08:03:14.227" UserId="4647" Text="Confusion between usages of linear RGB and sRGB" ContentLicense="CC BY-SA 3.0" />
  <row Id="8523" PostHistoryTypeId="3" PostId="3970" RevisionGUID="49b63c2e-e92c-4049-8fa2-c40fb9504cfc" CreationDate="2016-09-09T08:03:14.227" UserId="4647" Text="|color|brightness|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8524" PostHistoryTypeId="10" PostId="3967" RevisionGUID="c9a14481-7fe2-4e3d-bfb8-6944d2e382a6" CreationDate="2016-09-09T10:13:49.367" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8525" PostHistoryTypeId="2" PostId="3971" RevisionGUID="e0e2cc82-4a72-47eb-ad4f-626f6c34455e" CreationDate="2016-09-09T10:37:45.823" UserId="5087" Text="I'd like to take an photograph, subdivide it into a tesselation, either of squares, or (ideally), hexagons, and then find the centre of gravity (or, if you prefer, centre of mass) of each cell of the tesselation.&#xD;&#xA;&#xD;&#xA;The output, for any image, would be a matrix of points. For the attached diagram, something like this (in polar coordinates - $(r,\theta)$ ):&#xD;&#xA;&#xD;&#xA;    &lt;code&gt;&#xD;&#xA;&#xD;&#xA;(5,5pi/4) (0,0) (1,7pi/4) (1,5pi/4)&#xD;&#xA;     (5,3pi/4) (0,0) (5,pi/2) &#xD;&#xA;(0.0) (0,0) (0.0) (0,0)  [I know the bottom left dot is actually at (2,3pi/2)]&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've attached an image showing what I mean.&#xD;&#xA;&#xD;&#xA;[![Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FuwMP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8526" PostHistoryTypeId="1" PostId="3971" RevisionGUID="e0e2cc82-4a72-47eb-ad4f-626f6c34455e" CreationDate="2016-09-09T10:37:45.823" UserId="5087" Text="What is a good algorithm, and framework, to calculate centres of gravity or mass (cog)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8527" PostHistoryTypeId="3" PostId="3971" RevisionGUID="e0e2cc82-4a72-47eb-ad4f-626f6c34455e" CreationDate="2016-09-09T10:37:45.823" UserId="5087" Text="|mesh|physics|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8528" PostHistoryTypeId="5" PostId="3971" RevisionGUID="40980c36-04b0-4573-8f0e-760b384ea0fd" CreationDate="2016-09-09T10:42:47.957" UserId="5087" Comment="added 6 characters in body" Text="I'd like to take an photograph, subdivide it into a tesselation, either of squares, or (ideally), hexagons, and then find the centre of gravity (or, if you prefer, centre of mass) of each cell of the tesselation.&#xD;&#xA;&#xD;&#xA;The output, for any image, would be a matrix of points. For the attached diagram, something like this (in polar coordinates - $(r,\theta)$ ):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    $(5,5\pi/4)$ (0,0) $(1,7\pi/4)$ $(1,5\pi/4)$&#xD;&#xA;         $(5,3\pi/4)$ (0,0) $(5,\pi/2)$ &#xD;&#xA;    (0.0) (0,0) (0.0) (0,0)  [I know the bottom left dot is actually at $(2,3\pi/2)$]&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've attached an image showing what I mean.&#xD;&#xA;&#xD;&#xA;[![Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FuwMP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8529" PostHistoryTypeId="5" PostId="3971" RevisionGUID="1c345a5a-7672-4fba-8b2a-6e31d2925c75" CreationDate="2016-09-09T10:48:33.493" UserId="5087" Comment="added 9 characters in body" Text="I'd like to take an photograph, subdivide it into a tesselation, either of squares, or (ideally), hexagons, and then find the centre of gravity (or, if you prefer, centre of mass) of each cell of the tesselation.&#xD;&#xA;&#xD;&#xA;The output, for any image, would be a matrix of points. For the attached diagram, something like this (in polar coordinates - $(r,\theta)$ ):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    (5,5Π/4) (0,0) (1,7Π/4) (1,5Π/4)&#xD;&#xA;         (5,3Π/4) (0,0) (5,Π/2) &#xD;&#xA;    (0.0) (0,0) (0.0) (0,0)  [I know the bottom left dot is actually at (2,3Π/2)]&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've attached an image showing what I mean.&#xD;&#xA;&#xD;&#xA;[![Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FuwMP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8531" PostHistoryTypeId="50" PostId="3596" RevisionGUID="409c328f-7fe9-41d9-9a4b-8d57c01dfa7f" CreationDate="2016-09-09T13:38:43.737" UserId="-1" />
  <row Id="8532" PostHistoryTypeId="2" PostId="3972" RevisionGUID="cc7aeeac-a832-4f47-b9c5-d7c021367aa6" CreationDate="2016-09-09T14:12:38.487" UserId="56" Text="I have a naive diffuse/emissive material path tracer implementation (pinhole camera) and am seeing it take a very large number of samples per pixel to converge - like probably in the millions - and was wondering if that was normal for &quot;naive&quot; path tracer implementations?&#xD;&#xA;&#xD;&#xA;Here is 10,000 samples per pixel:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here's a 10,000spp image using cosine weighted hemisphere samples as comparison:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA; 1. Cast a ray out into the scene for the pixel (starting at near plane, of the direction of the camera to the pixel's location on the near plane).&#xD;&#xA; 2. When an object is hit, I calculate a uniform random direction in the hemisphere defined by the normal and continue.&#xD;&#xA; 3. At each level, i return emissive + (2*Dot(normal, bounceRayDir)*ColorFromBounceRay*DiffuseColor/pi)&#xD;&#xA; 4. If nothing is hit by a bounced ray, i return black.&#xD;&#xA; 5. I'm working with 3 floating point color channels, where the intent is that 0-1 corresponds to 0-255 in the final output uint8 per color channel.&#xD;&#xA; 5. I allow 5 bounces max.&#xD;&#xA;&#xD;&#xA;After averaging all the samples for the pixel, I do this to convert it from HDR to LDR:&#xD;&#xA;&#xD;&#xA; 1. For each color channel i do gamma correction: channel = powf(channel, 1.0f /2.2f)&#xD;&#xA; 2. I then multiply the channel value by 255, clamp it from 0-255 and cast it to uint8 for the final pixel color.&#xD;&#xA;&#xD;&#xA;The source code can be seen here in the gist below.  It includes windows.h for bitmap headers, but otherwise has no non standard headers, and no library dependencies:&#xD;&#xA;https://gist.github.com/anonymous/0dc9f7f5abf15f8fdb9aa84ecfcf67d5&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Il8Lw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bJOV7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8533" PostHistoryTypeId="1" PostId="3972" RevisionGUID="cc7aeeac-a832-4f47-b9c5-d7c021367aa6" CreationDate="2016-09-09T14:12:38.487" UserId="56" Text="Is it expected that a naive path tracer takes many, many samples to converge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8534" PostHistoryTypeId="3" PostId="3972" RevisionGUID="cc7aeeac-a832-4f47-b9c5-d7c021367aa6" CreationDate="2016-09-09T14:12:38.487" UserId="56" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8535" PostHistoryTypeId="2" PostId="3973" RevisionGUID="12ec1456-3ff0-4ef7-b71a-a7fdf3bff73b" CreationDate="2016-09-09T14:20:34.397" UserId="5088" Text="As a general rule, you cannot interpolate transformation matrices. In stead, you decompose them into their individual values, then interpolate those and recompose. &#xD;&#xA;&#xD;&#xA;The Möbius transformation as suggested in the comments sounds interesting, but tradionally I'd just extract scale and rotation and interpolate those.&#xD;&#xA;&#xD;&#xA;Assuming a transformation matrix&#xD;&#xA;&#xD;&#xA;        | a  b |&#xD;&#xA;    T = | c  d |&#xD;&#xA;&#xD;&#xA;- the *scale* is `[sqrt(a² + c²), sqrt(b² + d²)]`&#xD;&#xA;- The *rotation angle* is `atan(c/d)`&#xD;&#xA;&#xD;&#xA;You'd now interpolate this scale and rotation angle, recomposing the matrix at each frame.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8536" PostHistoryTypeId="5" PostId="3972" RevisionGUID="86d262c0-b426-4c12-bfb9-c2a8eb029955" CreationDate="2016-09-09T14:24:24.757" UserId="56" Comment="typos" Text="I have a naive diffuse/emissive material path tracer implementation (pinhole camera) and am seeing it take a very large number of samples per pixel to converge - like probably in the millions - and was wondering if that was normal for &quot;naive&quot; path tracer implementations?&#xD;&#xA;&#xD;&#xA;Here is 10,000 samples per pixel:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here's a 10,000spp image using cosine weighted hemisphere samples as comparison:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;For each pixel I do this:&#xD;&#xA;&#xD;&#xA; 1. Cast a ray out into the scene for the pixel (starting at near plane, of the direction of the camera to the pixel's location on the near plane).&#xD;&#xA; 2. When an object is hit, I calculate a uniform random direction in the hemisphere defined by the normal and continue.&#xD;&#xA; 3. At each level, i return emissive + (2 * Dot(normal, bounceRayDir) * ColorFromBounceRay * DiffuseColor/pi)&#xD;&#xA; 4. If nothing is hit by a bounced ray, i return black.&#xD;&#xA; 5. I'm working with 3 floating point color channels, where the intent is that 0-1 corresponds to 0-255 in the final output uint8 per color channel.&#xD;&#xA; 5. I allow 5 bounces max.&#xD;&#xA;&#xD;&#xA;After averaging all the samples for the pixel, I do this to convert it from HDR to LDR:&#xD;&#xA;&#xD;&#xA; 1. For each color channel i do gamma correction: channel = powf(channel, 1.0f /2.2f)&#xD;&#xA; 2. I then multiply the channel value by 255, clamp it from 0-255 and cast it to uint8 for the final pixel color.&#xD;&#xA;&#xD;&#xA;The source code can be seen here in the gist below.  It includes windows.h for bitmap headers, but otherwise has no non standard headers, and no library dependencies:&#xD;&#xA;https://gist.github.com/anonymous/0dc9f7f5abf15f8fdb9aa84ecfcf67d5&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Il8Lw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bJOV7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8537" PostHistoryTypeId="2" PostId="3974" RevisionGUID="f88667c5-ad5c-4946-90e3-949077d6d60c" CreationDate="2016-09-09T14:34:07.837" UserId="4647" Text="The monitor interprets its input data as encoded in sRGB color space. This means that to actually display them, i.e. to get brightness of the subpixels it does the transformation $C_{\mathrm{sRGB}}\to C_{\mathrm{linear}}$. This transformation is basically application of gamma of $\approx2.2$ to the value, so that output brightness will be superlinearly dependent on input data. Since non-extremal input values are $&lt;1$, they'll all be darker than with linear response.&#xD;&#xA;&#xD;&#xA;Now if you have rendered an image in linear RGB color space, you need to compensate the transformation the monitor does. Thus you convert the image to sRGB, i.e. apply the $C_{\mathrm{linear}}\to C_{\mathrm{sRGB}}$ transformation. This transformation is inverse of what the monitor does: it applies a gamma of $\approx1/2.2$ to the values, so all non-extremal values will be larger than original.&#xD;&#xA;&#xD;&#xA;In the OP I was coming to the wrong conclusion because of a mistake when trying to match the output of monitor with my input. To match it correctly one needs to either apply $C_{\mathrm{sRGB}}\to C_{\mathrm{linear}}$ transformation to input data to simulate what the monitor does with them, or apply backward transformation to the measured output — to undo monitor's processing." ContentLicense="CC BY-SA 3.0" />
  <row Id="8541" PostHistoryTypeId="2" PostId="3976" RevisionGUID="94ddb386-987b-4055-8f8a-b0b22163318a" CreationDate="2016-09-09T17:23:15.240" UserId="48" Text="Without explicit light sampling, I'd expect very slow convergence.&#xD;&#xA;&#xD;&#xA;Any path that doesn't happen to hit the light source before being terminated will be useless (contributes zero). Since you have a small light source, the vast majority of paths will not hit it. It would be interesting to add some statistics to your tracer to see how many paths return zero vs nonzero. I'd guess you'll find something like 99–99.9% of them are zero, so you're only getting one useful sample out of every 100–1000 or so paths traced.&#xD;&#xA;&#xD;&#xA;Naive path tracing is more reasonable with e.g. a sky light, which almost every path can be expected to hit." ContentLicense="CC BY-SA 3.0" />
  <row Id="8542" PostHistoryTypeId="2" PostId="3977" RevisionGUID="b029d65f-d640-4336-8e19-1bad54e13b3e" CreationDate="2016-09-09T19:53:46.417" UserId="5093" Text="I would like to make certain objects in my scene transparent, but only the parts visible to the camera when opaque. &#xD;&#xA;&#xD;&#xA;Currently, when I make objects transparent, I can see other transparent objects behind them, which I don't want. I only want to be able to see opaque objects behind transparent objects.&#xD;&#xA;&#xD;&#xA;This is what happens now:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is what I want:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gRP4b.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WctUW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8543" PostHistoryTypeId="1" PostId="3977" RevisionGUID="b029d65f-d640-4336-8e19-1bad54e13b3e" CreationDate="2016-09-09T19:53:46.417" UserId="5093" Text="Only show opaque objects behind transparent objects" ContentLicense="CC BY-SA 3.0" />
  <row Id="8544" PostHistoryTypeId="3" PostId="3977" RevisionGUID="b029d65f-d640-4336-8e19-1bad54e13b3e" CreationDate="2016-09-09T19:53:46.417" UserId="5093" Text="|rendering|webgl|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8545" PostHistoryTypeId="2" PostId="3978" RevisionGUID="e4528c9a-a398-4104-93f1-bd5f5c846e75" CreationDate="2016-09-09T20:39:49.030" UserId="231" Text="Yes, this is to be expected. The difference between your two images is the difference between using and not using importance sampling.&#xD;&#xA;&#xD;&#xA;The first image shows noticeably more noise than the second. This is because instead of biasing the hemisphere samples towards the normal by using cosine weighting, the code instead samples uniformly over the hemisphere and then gives less reflected light to rays nearer to perpendicular to the normal. Note that since this uses the dot product, this is also cosine weighting, just weighting the contribution of each ray, rather than weighting the number of rays in each direction.&#xD;&#xA;&#xD;&#xA;The second image is less noisy because it doesn't waste many samples on near-perpendicular rays which contribute very little to the image. The image will still converge to the same result given enough samples - the approach taken in the second image will just get there much sooner.&#xD;&#xA;&#xD;&#xA;The effect in both cases is the same:&#xD;&#xA;&#xD;&#xA;1. The weighting is applied to the amount of light reflected per ray, resulting in many of the rays carrying very little contribution.&#xD;&#xA;2. Every ray is given the same weight, but fewer of them are used in the directions associated with little contribution.&#xD;&#xA;&#xD;&#xA;The long term sum is the same either way, but approach (1) involves many rays with negligible contribution, that still require just as much calculation as any other ray.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that even with this speed up, the convergence will still be *very* slow for scenes with small, bright lights, or if there are parts of the scene accessible only by narrow paths. Generally, any scene where there are regions for which only a narrow range of angles contribute most of the light.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8546" PostHistoryTypeId="5" PostId="3977" RevisionGUID="b6d06c1d-e148-4390-a185-a36dd8abe517" CreationDate="2016-09-09T20:42:42.007" UserId="5093" Comment="Fixed image" Text="I would like to make certain objects in my scene transparent, but only the parts visible to the camera when opaque. &#xD;&#xA;&#xD;&#xA;Currently, when I make objects transparent, I can see other transparent objects behind them, which I don't want. I only want to be able to see opaque objects behind transparent objects.&#xD;&#xA;&#xD;&#xA;This is what happens now:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is what I want:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gRP4b.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vIumn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8547" PostHistoryTypeId="5" PostId="3978" RevisionGUID="b59bafe0-314e-448e-ba1c-28b6e0543cb9" CreationDate="2016-09-09T20:56:45.103" UserId="231" Comment="Explain dot product is also cosine weighting" Text="Yes, this is to be expected. The difference between your two images is the difference between using and not using importance sampling.&#xD;&#xA;&#xD;&#xA;The first image shows noticeably more noise than the second. This is because instead of biasing the hemisphere samples towards the normal by using cosine weighting, the code instead samples uniformly over the hemisphere and then gives less reflected light to rays nearer to perpendicular to the normal. Note that since this uses the dot product, this is also cosine weighting:&#xD;&#xA;&#xD;&#xA;$$A\cdot B=\|A\|\|B\|\cos{\theta}$$&#xD;&#xA;&#xD;&#xA;It's just weighting the contribution of each ray, rather than weighting the number of rays in each direction.&#xD;&#xA;&#xD;&#xA;The second image is less noisy because it doesn't waste many samples on near-perpendicular rays which contribute very little to the image. The image will still converge to the same result given enough samples - the approach taken in the second image will just get there much sooner.&#xD;&#xA;&#xD;&#xA;The effect in both cases is the same:&#xD;&#xA;&#xD;&#xA;1. The weighting is applied to the amount of light reflected per ray, resulting in many of the rays carrying very little contribution.&#xD;&#xA;2. Every ray is given the same weight, but fewer of them are used in the directions associated with little contribution.&#xD;&#xA;&#xD;&#xA;The long term sum is the same either way, but approach (1) involves many rays with negligible contribution, that still require just as much calculation as any other ray.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that even with this speed up, the convergence will still be *very* slow for scenes with small, bright lights, or if there are parts of the scene accessible only by narrow paths. Generally, any scene where there are regions for which only a narrow range of angles contribute most of the light.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8548" PostHistoryTypeId="2" PostId="3979" RevisionGUID="e8f98e5d-2cbb-44ca-88f3-0bdbbf9aff03" CreationDate="2016-09-10T08:40:26.277" UserId="5097" Text="Just like the question says. Is it possible to selectively set the value of the stencil buffer based on a property of a vertex, like the value of its normal, during its vertex processing phase? Instead of setting for all fragments of the model. Basically I want to detect the edges of my model by using variation in vertex normals and use them to set the stencil values in the corresponding fragments for some special effects " ContentLicense="CC BY-SA 3.0" />
  <row Id="8549" PostHistoryTypeId="1" PostId="3979" RevisionGUID="e8f98e5d-2cbb-44ca-88f3-0bdbbf9aff03" CreationDate="2016-09-10T08:40:26.277" UserId="5097" Text="selectively setting stencil value based on vertex property in vertex shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="8550" PostHistoryTypeId="3" PostId="3979" RevisionGUID="e8f98e5d-2cbb-44ca-88f3-0bdbbf9aff03" CreationDate="2016-09-10T08:40:26.277" UserId="5097" Text="|opengl|shader|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8551" PostHistoryTypeId="6" PostId="3971" RevisionGUID="ef87fa51-d7f2-45b2-b393-f239527845d1" CreationDate="2016-09-10T10:22:28.533" UserId="5087" Comment="I've not had many responding, so I'm trying better tagging to see if it helps." Text="|opengl|gpu|mathematics|physics|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8552" PostHistoryTypeId="2" PostId="3980" RevisionGUID="85b778c0-a6b5-4fc9-a771-4deacec51ea0" CreationDate="2016-09-10T11:42:23.603" UserId="5087" Text="I'd like an automatic method to clean images. I've been looking at the GIMP, and its command line (cli) interface, in scheme / lisp. It looks very promising, but I'm a complete novice, so I'd be grateful for advice.&#xD;&#xA;&#xD;&#xA;I'm, essentially, wanting to remove all man-made artefacts from a large number of photos - which is why I need to automate it, it's easy enough with just the one.&#xD;&#xA;&#xD;&#xA;I'd like to remove anything with a hard-edge (square, rectangle, or part of one), or with a smooth curve (circle, ellipse, or part of one), but not remove naturally curved things, like leaves, or fronds.&#xD;&#xA;&#xD;&#xA;I've attached a before and after photo. In a perfect world, I'd like a script that takes the image on the left, and leaves the image on the right.&#xD;&#xA;&#xD;&#xA;Any suggestions of the best way to go?&#xD;&#xA;&#xD;&#xA;It'd be nice if the method could be one that can use a GPU.&#xD;&#xA;&#xD;&#xA;/Users/peterbrooks/Pictures/Image Cleaning - before and after.tiff" ContentLicense="CC BY-SA 3.0" />
  <row Id="8553" PostHistoryTypeId="1" PostId="3980" RevisionGUID="85b778c0-a6b5-4fc9-a771-4deacec51ea0" CreationDate="2016-09-10T11:42:23.603" UserId="5087" Text="Image cleaning - removing all regular shapes ( circles, squares, text, icons etc. )" ContentLicense="CC BY-SA 3.0" />
  <row Id="8554" PostHistoryTypeId="3" PostId="3980" RevisionGUID="85b778c0-a6b5-4fc9-a771-4deacec51ea0" CreationDate="2016-09-10T11:42:23.603" UserId="5087" Text="|opengl|gpu|computational-geometry|image-processing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8555" PostHistoryTypeId="5" PostId="3971" RevisionGUID="7b385238-4b13-48b5-b085-0e3ac01d092a" CreationDate="2016-09-10T13:39:16.867" UserId="231" Comment="Include image description in a visible form as it contributes to the explanation." Text="I'd like to take an photograph, subdivide it into a tesselation, either of squares, or (ideally), hexagons, and then find the centre of gravity (or, if you prefer, centre of mass) of each cell of the tesselation.&#xD;&#xA;&#xD;&#xA;The output, for any image, would be a matrix of points. For the attached diagram, something like this (in polar coordinates - $(r,\theta)$ ):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    (5,5Π/4) (0,0) (1,7Π/4) (1,5Π/4)&#xD;&#xA;         (5,3Π/4) (0,0) (5,Π/2) &#xD;&#xA;    (0.0) (0,0) (0.0) (0,0)  [I know the bottom left dot is actually at (2,3Π/2)]&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've attached an image showing what I mean.&#xD;&#xA;&#xD;&#xA;[![Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge][1]][1]&#xD;&#xA;&#xD;&#xA;Figure 1. Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FuwMP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8556" PostHistoryTypeId="5" PostId="3980" RevisionGUID="08618720-b025-4000-a9e1-2a1067f9882e" CreationDate="2016-09-10T16:46:58.757" UserId="5087" Comment="Foolishly, I'd left out the image" Text="I'd like an automatic method to clean images. I've been looking at the GIMP, and its command line (cli) interface, in scheme / lisp. It looks very promising, but I'm a complete novice, so I'd be grateful for advice.&#xD;&#xA;&#xD;&#xA;I'm, essentially, wanting to remove all man-made artefacts from a large number of photos - which is why I need to automate it, it's easy enough with just the one.&#xD;&#xA;&#xD;&#xA;I'd like to remove anything with a hard-edge (square, rectangle, or part of one), or with a smooth curve (circle, ellipse, or part of one), but not remove naturally curved things, like leaves, or fronds.&#xD;&#xA;&#xD;&#xA;I've attached a before and after photo. In a perfect world, I'd like a script that takes the image on the left, and leaves the image on the right.&#xD;&#xA;&#xD;&#xA;Any suggestions of the best way to go?&#xD;&#xA;&#xD;&#xA;It'd be nice if the method could be one that can use a GPU.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mUC7H.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8557" PostHistoryTypeId="5" PostId="3971" RevisionGUID="c973ee45-9a90-4065-a80a-420e3a966408" CreationDate="2016-09-10T16:53:47.140" UserId="5087" Comment="I've neatened up the picture, emphasising the gravity effect more, hoping this is clearer." Text="I'd like to take an photograph, subdivide it into a tesselation, either of squares, or (ideally), hexagons, and then find the centre of gravity (or, if you prefer, centre of mass) of each cell of the tesselation.&#xD;&#xA;&#xD;&#xA;The output, for any image, would be a matrix of points. For the attached diagram, something like this (in polar coordinates - $(r,\theta)$ ):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    (5,5Π/4) (0,0) (1,7Π/4) (1,5Π/4)&#xD;&#xA;         (5,3Π/4) (0,0) (5,Π/2) &#xD;&#xA;    (0.0) (0,0) (0.0) (0,0)  &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've attached an image showing what I mean.&#xD;&#xA;&#xD;&#xA;[![Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zQng6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8558" PostHistoryTypeId="5" PostId="3971" RevisionGUID="4d575424-6779-4607-b140-2030ad2c8806" CreationDate="2016-09-10T17:56:28.453" UserId="5087" Comment="I've added a specific question to clarify what I'm looking for - and to give an idea of my thinking towards a solution so far." Text="I'd like to take an photograph, subdivide it into a tesselation, either of squares, or (ideally), hexagons, and then find the centre of gravity (or, if you prefer, centre of mass) of each cell of the tesselation.&#xD;&#xA;&#xD;&#xA;The output, for any image, would be a matrix of points. For the attached diagram, something like this (in polar coordinates - $(r,\theta)$ ):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    (5,5Π/4) (0,0) (1,7Π/4) (1,5Π/4)&#xD;&#xA;         (5,3Π/4) (0,0) (5,Π/2) &#xD;&#xA;    (0.0) (0,0) (0.0) (0,0)  &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've attached an image showing what I mean.&#xD;&#xA;&#xD;&#xA;[![Hexagonal tesselation. The black circles are the centres of gravity of each cell - in clear, or monochrome, cells it is in the centre of the cell. In those with a green splodge, the cog is pulled towards the splodge][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zQng6.png&#xD;&#xA;&#xD;&#xA;My question, to put it simply, is the best method to use to calculate the cog, in this tessellation... For squares, it'd be easy to calculate the weighted mean for each row, but that would be too rough an approximation. What's a good way to iterate either a general tessellation (ideal), or an hexagonal one?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8559" PostHistoryTypeId="5" PostId="3973" RevisionGUID="77851ed2-bfa9-41dc-8687-eb49c63c74b6" CreationDate="2016-09-10T18:11:02.893" UserId="5088" Comment="added 65 characters in body" Text="As a general rule, you cannot interpolate transformation matrices. In stead, you decompose them into their individual values, then interpolate those and recompose. &#xD;&#xA;&#xD;&#xA;The Möbius transformation as suggested in the comments sounds interesting, but tradionally I'd just extract scale and rotation and interpolate those.&#xD;&#xA;&#xD;&#xA;Assuming a transformation matrix&#xD;&#xA;&#xD;&#xA;        | a  b |&#xD;&#xA;    T = | c  d |&#xD;&#xA;&#xD;&#xA;- the *scale* is `[sqrt(a² + c²), sqrt(b² + d²)]`&#xD;&#xA;- The *rotation angle* is `atan(c/a)`&#xD;&#xA;&#xD;&#xA;You'd now interpolate this scale and rotation angle, recomposing the matrix at each frame.&#xD;&#xA;&#xD;&#xA;*[Edit] Corrected the angle (as spotted by Nathan Reed [/Edit]*" ContentLicense="CC BY-SA 3.0" />
  <row Id="8560" PostHistoryTypeId="5" PostId="3973" RevisionGUID="0359d149-e5c6-4fea-8816-0378071f421d" CreationDate="2016-09-10T18:18:39.683" UserId="5088" Comment="added 1 character in body" Text="As a general rule, you cannot interpolate transformation matrices. In stead, you decompose them into their individual values, then interpolate those and recompose. &#xD;&#xA;&#xD;&#xA;The Möbius transformation as suggested in the comments sounds interesting, but tradionally I'd just extract scale and rotation and interpolate those.&#xD;&#xA;&#xD;&#xA;Assuming a transformation matrix&#xD;&#xA;&#xD;&#xA;        | a  b |&#xD;&#xA;    T = | c  d |&#xD;&#xA;&#xD;&#xA;- the *scale* is `[sqrt(a² + c²), sqrt(b² + d²)]`&#xD;&#xA;- The *rotation angle* is `atan(c/a)`&#xD;&#xA;&#xD;&#xA;You'd now interpolate this scale and rotation angle, recomposing the matrix at each frame.&#xD;&#xA;&#xD;&#xA;*[Edit] Corrected the angle (as spotted by Nathan Reed) [/Edit]*" ContentLicense="CC BY-SA 3.0" />
  <row Id="8561" PostHistoryTypeId="2" PostId="3981" RevisionGUID="10c6c77d-89b2-4178-a8f4-db383698fc04" CreationDate="2016-09-10T18:57:16.533" UserId="4958" Text="Well actually I think I was doing it wrong. I stored raymarching effects in 2D texture. This is not correct because it suffers from issues.&#xD;&#xA;&#xD;&#xA;Correct way is store raymarching effect in 3D texture, to get linear interpolation and no banding. And then perform sampling from it.&#xD;&#xA;&#xD;&#xA;Now I need to implement this to check if it is true." ContentLicense="CC BY-SA 3.0" />
  <row Id="8562" PostHistoryTypeId="5" PostId="3980" RevisionGUID="d735970a-05d7-4621-bb3a-1c6560c9c61b" CreationDate="2016-09-11T02:08:05.137" UserId="5087" Comment="Added a representative photo of the sort of things I'm wanting to exclude, and not wanting to exclude" Text="I'd like an automatic method to clean images. I've been looking at the GIMP, and its command line (cli) interface, in scheme / lisp. It looks very promising, but I'm a complete novice, so I'd be grateful for advice.&#xD;&#xA;&#xD;&#xA;I'm, essentially, wanting to remove all man-made artefacts from a large number of photos - which is why I need to automate it, it's easy enough with just the one.&#xD;&#xA;&#xD;&#xA;I'd like to remove anything with a hard-edge (square, rectangle, or part of one), or with a smooth curve (circle, ellipse, or part of one), but not remove naturally curved things, like leaves, or fronds.&#xD;&#xA;&#xD;&#xA;I've attached a before and after photo. In a perfect world, I'd like a script that takes the image on the left, and leaves the image on the right.&#xD;&#xA;&#xD;&#xA;Any suggestions of the best way to go?&#xD;&#xA;&#xD;&#xA;It'd be nice if the method could be one that can use a GPU.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's a representative image. In this, I'd be wanting to exclude the straight-edged areas on the top right, and the straight-edged white blocks on the top left. What I'd be not wanting to exclude, but would actually be looking for (a separate problem) would be the white mass that's just to the bottom-right of the centre of the image. As you can see, it has nothing like a straight-edge or arc about it.&#xD;&#xA;&#xD;&#xA;[![Sample photo - it's a mammogram, showing a tumour][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mUC7H.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/hFsnV.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8563" PostHistoryTypeId="2" PostId="3982" RevisionGUID="5fc680a1-aaf6-45ca-8b89-85334d8f3a66" CreationDate="2016-09-11T09:08:43.267" UserId="5102" Text="I new to this area and have less knowledge , i want to create some graphics&lt;br&gt; like  `Sparks and lighting` by writing some code , using my own physics and i don't want to use some engine , However i can use external Libraries. &#xD;&#xA;&#xD;&#xA;Can anyone tell me how to set started , where should i proceeded.&#xD;&#xA;Like should i go with `OpenGl` for writing my own code or something else. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8564" PostHistoryTypeId="1" PostId="3982" RevisionGUID="5fc680a1-aaf6-45ca-8b89-85334d8f3a66" CreationDate="2016-09-11T09:08:43.267" UserId="5102" Text="Creating Sparks using Code" ContentLicense="CC BY-SA 3.0" />
  <row Id="8565" PostHistoryTypeId="3" PostId="3982" RevisionGUID="5fc680a1-aaf6-45ca-8b89-85334d8f3a66" CreationDate="2016-09-11T09:08:43.267" UserId="5102" Text="|3d|physics|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8567" PostHistoryTypeId="2" PostId="3984" RevisionGUID="158e903d-4d84-4765-b362-a481e617e91a" CreationDate="2016-09-11T16:24:42.170" UserId="5104" Text="I am writing a texture splatting pixel shader for meshes (not terrain) whereby I find a UV position from a raycast, which I convert to a local position, and then calculate a bounding box around that position.&#xD;&#xA;&#xD;&#xA;Then when cycling through the UVs in the shader I am able to check if each position is within the bounding box, and hence set a colour.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The bit I am struggling with is how to take each local position and map it to the bounding box so I can then map that result to the splat texture using UVs or percentages.&#xD;&#xA;&#xD;&#xA;In the image above I have 6 splat points. As you can see the one is crossing an edge so I need to be able to transform the 3D position along all axes.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P28sG.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8568" PostHistoryTypeId="1" PostId="3984" RevisionGUID="158e903d-4d84-4765-b362-a481e617e91a" CreationDate="2016-09-11T16:24:42.170" UserId="5104" Text="Converting or unwrapping a 3D point to a UV position" ContentLicense="CC BY-SA 3.0" />
  <row Id="8569" PostHistoryTypeId="3" PostId="3984" RevisionGUID="158e903d-4d84-4765-b362-a481e617e91a" CreationDate="2016-09-11T16:24:42.170" UserId="5104" Text="|pixel-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8570" PostHistoryTypeId="5" PostId="3982" RevisionGUID="558a89c7-1aee-4b9a-b417-7d0e24343ccd" CreationDate="2016-09-11T16:36:45.070" UserId="67" Comment="Fixed spelling and spacing" Text="I'm new to this area and have less knowledge. I want to create some graphics like  **Sparks and lighting** by writing some code, using my own physics. I don't want to use some engine, However I can use external libraries. &#xD;&#xA;&#xD;&#xA;Can anyone tell me how to set started, where should I proceed?&#xD;&#xA;Like should I go with `OpenGL` for writing my own code or something else. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8571" PostHistoryTypeId="24" PostId="3982" RevisionGUID="558a89c7-1aee-4b9a-b417-7d0e24343ccd" CreationDate="2016-09-11T16:36:45.070" Comment="Proposed by 67 approved by -1 edit id of 162" ContentLicense="CC BY-SA 3.0" />
  <row Id="8572" PostHistoryTypeId="5" PostId="3982" RevisionGUID="4bcc5d32-3ee5-47f9-8a42-ae354de87e28" CreationDate="2016-09-11T16:36:45.070" UserId="231" Comment="Assumed &quot;lightning&quot; was intended from the context. Please revert if this was not your intention." Text="I'm new to this area and have less knowledge. I want to create some graphics like  **sparks and lightning** by writing some code, using my own physics. I don't want to use some engine, However I can use external libraries. &#xD;&#xA;&#xD;&#xA;Can anyone tell me how to set started, where should I proceed?&#xD;&#xA;Like should I go with `OpenGL` for writing my own code or something else. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8573" PostHistoryTypeId="5" PostId="3978" RevisionGUID="5262968b-9bda-44f5-a942-ea636665c594" CreationDate="2016-09-11T16:47:02.643" UserId="231" Comment="Change to bullets as numbered list gave the impression of component parts rather than mutually exclusive approaches." Text="Yes, this is to be expected. The difference between your two images is the difference between using and not using importance sampling.&#xD;&#xA;&#xD;&#xA;The first image shows noticeably more noise than the second. This is because instead of biasing the hemisphere samples towards the normal by using cosine weighting, the code instead samples uniformly over the hemisphere and then gives less reflected light to rays nearer to perpendicular to the normal. Note that since this uses the dot product, this is also cosine weighting:&#xD;&#xA;&#xD;&#xA;$$A\cdot B=\|A\|\|B\|\cos{\theta}$$&#xD;&#xA;&#xD;&#xA;It's just weighting the contribution of each ray, rather than weighting the number of rays in each direction.&#xD;&#xA;&#xD;&#xA;The second image is less noisy because it doesn't waste many samples on near-perpendicular rays which contribute very little to the image. The image will still converge to the same result given enough samples - the approach taken in the second image will just get there much sooner.&#xD;&#xA;&#xD;&#xA;The effect in both cases is the same:&#xD;&#xA;&#xD;&#xA;- **Approach 1**: The weighting is applied to the amount of light reflected per ray, resulting in many of the rays carrying very little contribution.&#xD;&#xA;- **Approach 2**: Every ray is given the same weight, but fewer of them are used in the directions associated with little contribution.&#xD;&#xA;&#xD;&#xA;The long term sum is the same either way, but approach 1 involves many rays with negligible contribution, that still require just as much calculation as any other ray, thus wasting most of the calculation time.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that even with this speed up, the convergence will still be *very* slow for scenes with small, bright lights, or if there are parts of the scene accessible only by narrow paths. Generally, any scene where there are regions for which only a narrow range of angles contribute most of the light.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8574" PostHistoryTypeId="5" PostId="3984" RevisionGUID="8ec08f95-dd8a-4b0e-ac3d-7b714b506d85" CreationDate="2016-09-11T17:40:56.947" UserId="5104" Comment="deleted 12 characters in body" Text="I am writing a texture splatting pixel shader for meshes (not terrain) whereby I find a UV position from a raycast, which I convert to a local position, and then calculate a bounding box around that position.&#xD;&#xA;&#xD;&#xA;Then when cycling through the UVs in the shader I am able to check if each position is within the bounding box, and hence set a colour.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The bit I am struggling with is how to map each local position to the bounding box so I can then map that result to the splat texture using UVs or percentages.&#xD;&#xA;&#xD;&#xA;In the image above I have 6 splat points. As you can see the one is crossing an edge so I need to be able to transform the 3D position along all axes.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P28sG.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8575" PostHistoryTypeId="2" PostId="3985" RevisionGUID="7bd88d9c-74f1-4372-a968-323f548dda55" CreationDate="2016-09-11T18:11:19.783" UserId="5105" Text="I am really new in computer graphic area.&#xD;&#xA;Suppose I have 1024*1024 frame buffer, and I want to use it to control a 512*512 display. What shall I do?&#xD;&#xA;In my opinion, I will only read the information in 512*512, such as from (0,0) to (0,511) then go to next line, (1,0) to (1,511)...&#xD;&#xA;Is this an usual way to solve the problem?  " ContentLicense="CC BY-SA 3.0" />
  <row Id="8576" PostHistoryTypeId="1" PostId="3985" RevisionGUID="7bd88d9c-74f1-4372-a968-323f548dda55" CreationDate="2016-09-11T18:11:19.783" UserId="5105" Text="Use big frame buffer to control a small display" ContentLicense="CC BY-SA 3.0" />
  <row Id="8577" PostHistoryTypeId="3" PostId="3985" RevisionGUID="7bd88d9c-74f1-4372-a968-323f548dda55" CreationDate="2016-09-11T18:11:19.783" UserId="5105" Text="|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8578" PostHistoryTypeId="4" PostId="3984" RevisionGUID="ff59c6c8-0474-45b0-9664-7fa5ccff6314" CreationDate="2016-09-11T18:11:39.157" UserId="5104" Comment="edited title" Text="Flattening/unfolding a 3D point to a Cartesian plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="8579" PostHistoryTypeId="5" PostId="3984" RevisionGUID="7b0b0d8f-cd25-4b7d-93c2-fb84e2024ca0" CreationDate="2016-09-11T18:23:00.677" UserId="5104" Comment="added 102 characters in body; edited title" Text="I am writing a texture splatting pixel shader for meshes (not terrain) whereby I find a UV position from a raycast, which I convert to a local position, and then calculate a bounding box around that position.&#xD;&#xA;&#xD;&#xA;Then when cycling through the UVs in the shader I am able to check if each position is within the bounding box, and hence set a colour.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The bit I am struggling with is how to map each local position to the bounding box so I can then map that result to the splat texture using UVs or percentages.&#xD;&#xA;&#xD;&#xA;In the image above I have 6 splat points. As you can see the one is crossing an edge so I need to be able to transform the 3D position along all axes.&#xD;&#xA;&#xD;&#xA;I was thinking I could flatten/unfold the 3D point, but I'm not sure how to do this with all axes.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P28sG.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8580" PostHistoryTypeId="4" PostId="3984" RevisionGUID="7b0b0d8f-cd25-4b7d-93c2-fb84e2024ca0" CreationDate="2016-09-11T18:23:00.677" UserId="5104" Comment="added 102 characters in body; edited title" Text="Converting a 3D point to a Cartesian plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="8581" PostHistoryTypeId="5" PostId="3984" RevisionGUID="0cc7f7e0-b07a-483e-acf7-d699942e78ad" CreationDate="2016-09-11T18:33:16.837" UserId="5104" Comment="deleted 22 characters in body" Text="I am writing a texture splatting pixel shader for meshes (not terrain) whereby I find a UV position from a raycast, which I convert to a local position, and then calculate a bounding box around that position.&#xD;&#xA;&#xD;&#xA;Then when cycling through the UVs in the shader I am able to check if each position is within the bounding box, and hence set a colour.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The bit I am struggling with is how to map each local position to the bounding box so I can then map that result to the splat texture using UVs or percentages.&#xD;&#xA;&#xD;&#xA;In the image above I have 6 splat points. As you can see the one is crossing an edge so I need to be able to transform the 3D position along all axes.&#xD;&#xA;&#xD;&#xA;I was thinking I could flatten/unfold the 3D point, but I'm not sure how to do this with all axes.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P28sG.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8582" PostHistoryTypeId="4" PostId="3984" RevisionGUID="0cc7f7e0-b07a-483e-acf7-d699942e78ad" CreationDate="2016-09-11T18:33:16.837" UserId="5104" Comment="deleted 22 characters in body" Text="Unfolding a 3D point to a Cartesian plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="8583" PostHistoryTypeId="2" PostId="3986" RevisionGUID="96dadb4e-b0d7-4c21-aaab-3ee5bd09ce5e" CreationDate="2016-09-11T18:41:04.720" UserId="5088" Text="As stated, the question is a bit generic. It all depends on what part you *want* to display in the 512x512 display. If you have a 1024x1024 frame buffer from some source and only want to display 1/4 of the information, by all means copy the first 512 elements from the first 512 lines. If you want to support *panning*, you'll start at a different index in a different line. If you want to support *scaling* (with or without filter), you'll use a bigger or smaller set of source pixels.&#xD;&#xA;&#xD;&#xA;It also depends on the type of the buffer. If it's just raw bytes, your suggested approach is basically the only way to go, but if it's a DirectX/OpenGL texture, or part of some other graphics API (Windows Bitmap, graphics engine, etc), there are usually specialized approaches to get a rectangular subset of a buffer. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8584" PostHistoryTypeId="2" PostId="3987" RevisionGUID="1e801fa6-ecba-49c0-8084-2e4d48085d03" CreationDate="2016-09-11T18:45:40.160" UserId="5106" Text="I'm trying to understand OpenGL by using Processing OpenGL ES.&#xD;&#xA;&#xD;&#xA;If I have an example Cube to render.&#xD;&#xA;&#xD;&#xA;I've read that a vertex shader will be run once for each Vertex. The fragment shader will be run (at least) once for each pixel. &#xD;&#xA;&#xD;&#xA;In a vertex shader I have:&#xD;&#xA;&#xD;&#xA;    #define PROCESSING_COLOR_SHADER&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;&#xD;&#xA;    attribute vec4 vertex;&#xD;&#xA;    attribute vec4 color;&#xD;&#xA;&#xD;&#xA;    varying vec4 col;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;        gl_Position = vertex;&#xD;&#xA;	&#xD;&#xA;        col = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In a fragment shader I have:&#xD;&#xA;&#xD;&#xA;    gl_FragColor = col;&#xD;&#xA;&#xD;&#xA;When ran, it creates a simple painted cube of the colour defined in the Processing sketch. However, if I change the vertex shader to...&#xD;&#xA; &#xD;&#xA;    gl_Position = vertex&#xD;&#xA;&#xD;&#xA;(instead of transform*vertex) it draws a wireframe cube in exactly the same place. What exactly does the transform matrix do? " ContentLicense="CC BY-SA 3.0" />
  <row Id="8585" PostHistoryTypeId="1" PostId="3987" RevisionGUID="1e801fa6-ecba-49c0-8084-2e4d48085d03" CreationDate="2016-09-11T18:45:40.160" UserId="5106" Text="OpenGL: Purpose of transform matrix in Vertex shader where transform*vertex" ContentLicense="CC BY-SA 3.0" />
  <row Id="8586" PostHistoryTypeId="3" PostId="3987" RevisionGUID="1e801fa6-ecba-49c0-8084-2e4d48085d03" CreationDate="2016-09-11T18:45:40.160" UserId="5106" Text="|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8587" PostHistoryTypeId="2" PostId="3988" RevisionGUID="40f2f763-1948-4005-8308-e58b4aa2b00f" CreationDate="2016-09-11T19:12:39.433" UserId="137" Text="The transform matrix will be a uniform which is easier to update and upload to the gpu (just a single glUniform call) than applying the transform to all vertices on the cpu and uploading the new vertices. Especially with large models." ContentLicense="CC BY-SA 3.0" />
  <row Id="8591" PostHistoryTypeId="2" PostId="3990" RevisionGUID="a8907d30-5682-45f8-ad6a-0f95e64317e9" CreationDate="2016-09-12T07:00:21.483" UserId="5089" Text="I have two methods of calculating tangent and cotengent (needed for normalMap lighting calculation).&#xD;&#xA;&#xD;&#xA; - The one is doing it from CPP code (with assimp library for example)&#xD;&#xA; - The second is doing it directly in shader (in Vertex shader/in fragment shader)&#xD;&#xA;&#xD;&#xA;What is the best optimized method?&#xD;&#xA;&#xD;&#xA;I use Opengl 3.3+" ContentLicense="CC BY-SA 3.0" />
  <row Id="8592" PostHistoryTypeId="1" PostId="3990" RevisionGUID="a8907d30-5682-45f8-ad6a-0f95e64317e9" CreationDate="2016-09-12T07:00:21.483" UserId="5089" Text="Where is the best place for Tangent-cotangent calculation, in shader or in C/CPP code?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8593" PostHistoryTypeId="3" PostId="3990" RevisionGUID="a8907d30-5682-45f8-ad6a-0f95e64317e9" CreationDate="2016-09-12T07:00:21.483" UserId="5089" Text="|opengl|shader|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8594" PostHistoryTypeId="5" PostId="3990" RevisionGUID="290fdb5f-b1b6-4395-baa1-197739a38c6d" CreationDate="2016-09-12T07:41:59.087" UserId="5089" Comment="added 22 characters in body" Text="I have two methods of calculating tangent and cotengent (needed for normalMap lighting calculation).&#xD;&#xA;&#xD;&#xA; - The one is doing it from CPP code (with assimp library for example)&#xD;&#xA; - The second is doing it directly in shader (in Vertex shader/in fragment shader)&#xD;&#xA;&#xD;&#xA;What is the best optimized method? (optimized for speed, with vsync activated)&#xD;&#xA;&#xD;&#xA;I use Opengl 3.3+" ContentLicense="CC BY-SA 3.0" />
  <row Id="8596" PostHistoryTypeId="2" PostId="3992" RevisionGUID="799c9527-42f1-49f0-8e09-4c464dc71268" CreationDate="2016-09-12T07:59:16.487" UserId="5055" Text="The transform matrix allows you to translate, rotate or resize your model. From the model's point of view, its vertices always are at the same position. But if you multiply the vertices with, let us say a translation matrix, they all get moved. Seen from the model's origin, they are still at the same position. But in world space, your whole model has moved.&#xD;&#xA;The reason that changing the code did nothing to how the cube was presented to you lies in your transformation matrix not applying any changes to the cube's model data.&#xD;&#xA;If you choose a different transformation matrix, things will look differently.&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="8598" PostHistoryTypeId="2" PostId="3993" RevisionGUID="043728b9-9507-4575-9124-05ea8bff09b1" CreationDate="2016-09-12T10:01:31.040" UserId="209" Text="Disclaimer: I haven't actually tested this but it seems feasible.&#xD;&#xA;&#xD;&#xA;I agree with @trichoplax that what you want could possibly be expressed more clearly but, assuming I've understood correctly, would the following do the job?&#xD;&#xA;&#xD;&#xA;First I assume you can supply the opaque and translucent geometry separately, and that the opaque is sent first. I'm also going to assume there *may* be translucent geometry with exactly the same pixel Z values.(If this isn't the case, the stencil requirements could probably be dropped.)&#xD;&#xA;&#xD;&#xA;To handle the &quot;single translucent layer&quot;, clear the stencil buffer and send the translucent polygons to update the Z-buffer and set the stencil buffer on each pixel, but don't touch the frame buffer. &#xD;&#xA;&#xD;&#xA;Do a second pass through the translucent data which actually updates the framebuffer,  but change the Z test to 'equal' and only allow drawing on the pixels that are currently set in the the stencil buffer. Also clear the stencil for any pixels that pass the tests.&#xD;&#xA;&#xD;&#xA;This. I think, should result in only the closest translucency layer being applied.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8599" PostHistoryTypeId="5" PostId="3993" RevisionGUID="1b145626-71e7-4d31-a222-a2cc5b5e638e" CreationDate="2016-09-12T10:33:56.353" UserId="209" Comment="edited body" Text="Disclaimer: I haven't actually tested this but it seems feasible.&#xD;&#xA;&#xD;&#xA;I agree with @trichoplax that what you want could possibly be expressed more clearly but, assuming I've understood correctly, would the following do the job?&#xD;&#xA;&#xD;&#xA;First I assume you can supply the opaque and translucent geometry separately, and that the opaque is sent first. I'm also going to assume there *may* be translucent geometry with exactly the same pixel Z values.(If this isn't the case, the stencil requirements could probably be dropped.)&#xD;&#xA;&#xD;&#xA;To handle the &quot;single translucent layer&quot;, clear the stencil buffer and send the translucent polygons to update the Z-buffer and set the stencil buffer on each pixel, but don't touch the frame buffer. &#xD;&#xA;&#xD;&#xA;Do a second pass through the translucent data which actually updates the framebuffer,  but change the Z test to 'equal' and only allow drawing on the pixels that are currently set in the the stencil buffer. Also clear the stencil for any pixels that pass the tests.&#xD;&#xA;&#xD;&#xA;This, I think, should result in only the closest translucency layer being applied.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8600" PostHistoryTypeId="2" PostId="3994" RevisionGUID="5b75ce47-0889-48e9-9205-831f81223652" CreationDate="2016-09-12T11:58:46.960" UserId="3377" Text="I use C# and OpenTK as my OpenGL implementation.&#xD;&#xA;My Vertex layout consists of 6 Doubles and one Float:&#xD;&#xA;&#xD;&#xA;    public struct Vertex&#xD;&#xA;    {&#xD;&#xA;        //Positions&#xD;&#xA;        public double X;&#xD;&#xA;        public double Y;&#xD;&#xA;        public double Z;&#xD;&#xA;        //ContourEdge&#xD;&#xA;        public float IsContourEdge;&#xD;&#xA;        //Normals&#xD;&#xA;        public double NX;&#xD;&#xA;        public double NY;&#xD;&#xA;        public double NZ;&#xD;&#xA;        public Vertex(float x, float y, float z) : this()&#xD;&#xA;        {&#xD;&#xA;            X = x;&#xD;&#xA;            Y = y;&#xD;&#xA;            Z = z;&#xD;&#xA;            IsContourEdge = 0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        public Vertex(float x, float y, float z, float nX, float nY, float nZ) : this()&#xD;&#xA;        {&#xD;&#xA;            X = x;&#xD;&#xA;            Y = y;&#xD;&#xA;            Z = z;&#xD;&#xA;            NX = nX;&#xD;&#xA;            NY = nY;&#xD;&#xA;            NZ = nZ;&#xD;&#xA;            IsContourEdge = 0f;&#xD;&#xA;        }&#xD;&#xA;        public static int IsContourEdgeOffset()&#xD;&#xA;        {&#xD;&#xA;            return sizeof (double) * 3;&#xD;&#xA;        }&#xD;&#xA;        public static int NormalOffset()&#xD;&#xA;        {&#xD;&#xA;            return sizeof(double) * 4;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And I render my vertices like this:&#xD;&#xA;&#xD;&#xA;    //Bind vao, vbo and ebo&#xD;&#xA;    GL.BindVertexArray(bufferObject.Vao);&#xD;&#xA;&#xD;&#xA;    GL.BindBuffer(BufferTarget.ArrayBuffer, bufferObject.Vbo);&#xD;&#xA;    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * Marshal.SizeOf(typeof(Vertex))), vertices, BufferUsage);&#xD;&#xA;&#xD;&#xA;    // Vertex Positions&#xD;&#xA;    GL.EnableVertexAttribArray(0);&#xD;&#xA;    GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Double, false, Marshal.SizeOf(typeof(Vertex)), IntPtr.Zero);&#xD;&#xA;    // Is Contour Edge&#xD;&#xA;    GL.EnableVertexAttribArray(1);&#xD;&#xA;    GL.VertexAttribPointer(1, 1, VertexAttribPointerType.Float, false, Marshal.SizeOf(typeof(Vertex)), Vertex.IsContourEdgeOffset());&#xD;&#xA;    // Vertex Normals&#xD;&#xA;    if (hasNormals)&#xD;&#xA;    {&#xD;&#xA;        GL.EnableVertexAttribArray(2);&#xD;&#xA;        GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Double, false, Marshal.SizeOf(typeof(Vertex)), Vertex.NormalOffset());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Unlink buffers&#xD;&#xA;    GL.BindBuffer(BufferTarget.ArrayBuffer, 0);&#xD;&#xA;    GL.BindVertexArray(0);&#xD;&#xA;    GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);&#xD;&#xA;&#xD;&#xA;Everything works fine here. &#xD;&#xA;But the offset of the normals doesn't make sense for me. In my Vertex struct I said:&#xD;&#xA;&#xD;&#xA;    public static int NormalOffset()&#xD;&#xA;    {&#xD;&#xA;        return sizeof(double) * 4;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But shouldn't it be&#xD;&#xA;&#xD;&#xA;    public static int NormalOffset()&#xD;&#xA;    {&#xD;&#xA;        return 3* sizeof(double) * sizeof(float);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;since IsContourEdge is a float and a I also pass it as a float (VertexAttribPointerType.Float) to my vertex shader? &#xD;&#xA;&#xD;&#xA;Anyway, if I use this NormalOffset instead of the previous one, the normals don't work anymore.&#xD;&#xA;The only explanation I have is that OpenGL expands the size of a Float to the size of a Double. Is that right?&#xD;&#xA;&#xD;&#xA;Just for completeness, here is the vertex shader code:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout (location = 0) in vec3 position; //Vertices and normals are in world coordinate space&#xD;&#xA;    layout (location = 1) in float isContourEdge;&#xD;&#xA;    layout (location = 2) in vec3 normal;&#xD;&#xA;&#xD;&#xA;    out VS_OUT {&#xD;&#xA;        vec3 Normal;&#xD;&#xA;        vec3 FragPos;&#xD;&#xA;        vec3 VertWorldNormal;&#xD;&#xA;        vec3 VertWorldPos;&#xD;&#xA;        float ExcludeEdge;&#xD;&#xA;    } vs_out;&#xD;&#xA;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 proj;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = proj * view *  vec4(position, 1.0f);&#xD;&#xA;        vs_out.FragPos = vec3(view * vec4(position, 1.0f));&#xD;&#xA;        vs_out.Normal = vec3(view * vec4(normal, 0));&#xD;&#xA;        vs_out.ExcludeEdge = isContourEdge;&#xD;&#xA;&#xD;&#xA;        vs_out.VertWorldNormal = normal;&#xD;&#xA;        vs_out.VertWorldPos = position;&#xD;&#xA;    } " ContentLicense="CC BY-SA 3.0" />
  <row Id="8601" PostHistoryTypeId="1" PostId="3994" RevisionGUID="5b75ce47-0889-48e9-9205-831f81223652" CreationDate="2016-09-12T11:58:46.960" UserId="3377" Text="OpenTK - Vertex attribute layout issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="8602" PostHistoryTypeId="3" PostId="3994" RevisionGUID="5b75ce47-0889-48e9-9205-831f81223652" CreationDate="2016-09-12T11:58:46.960" UserId="3377" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8603" PostHistoryTypeId="5" PostId="3993" RevisionGUID="6d74e184-ce42-499d-930c-0a205d37272c" CreationDate="2016-09-12T13:41:53.500" UserId="209" Comment="added 66 characters in body" Text="Disclaimer: I haven't actually tested this but it seems feasible.&#xD;&#xA;&#xD;&#xA;I agree with [trichoplax](https://computergraphics.stackexchange.com/users/231/trichoplax) that what you want could possibly be expressed more clearly but, assuming I've understood correctly, would the following do the job?&#xD;&#xA;&#xD;&#xA;First I assume you can supply the opaque and translucent geometry separately, and that the opaque is sent first. I'm also going to assume there *may* be translucent geometry with exactly the same pixel Z values.(If this isn't the case, the stencil requirements could probably be dropped.)&#xD;&#xA;&#xD;&#xA;To handle the &quot;single translucent layer&quot;, clear the stencil buffer and send the translucent polygons to update the Z-buffer and set the stencil buffer on each pixel, but don't touch the frame buffer. &#xD;&#xA;&#xD;&#xA;Do a second pass through the translucent data which actually updates the framebuffer,  but change the Z test to 'equal' and only allow drawing on the pixels that are currently set in the the stencil buffer. Also clear the stencil for any pixels that pass the tests.&#xD;&#xA;&#xD;&#xA;This, I think, should result in only the closest translucency layer being applied.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8604" PostHistoryTypeId="2" PostId="3995" RevisionGUID="47a75258-56b0-43f9-87b0-021a36d24d9b" CreationDate="2016-09-12T13:42:34.243" UserId="5114" Text="So, I started writing my second raytracer - this time focusing on photometric rendering that uses IES lights and standard photometric units.  I've got the basic raytracing up and running (using pure geometry), I've read any article I could found on radio- and photometry (I think I developed an intuition for it) but the issues started when I tried to validate/play with the underlying math.&#xD;&#xA;&#xD;&#xA;I use IES lights as a function of spherical coordinates that gives me the intensity of light in that direction in candelas (lumens per unit solid angle). Also in the equation for Luminance/Radiance there are differential solid angle and differential surface area. On the paper everything looks good, however:&#xD;&#xA;&#xD;&#xA;**My question is**: how should I deal with those parameters in my raytracer? I assume (but I'm not sure) that my (differential) solid angle is just a (unit) vector in descrete world and the surface area is simply a point - but what values should I plug in to those equations? I saw that on some websites that people just ignored those terms and replaced the integral with sum - but no explanation was given...&#xD;&#xA;&#xD;&#xA;And my second question is related to those IES lights - how can I simply convert intensity to radiance? The intensity already has the solid angle, but for radiance I need the surface area... Or should I somehow integrate the luminious intensity to get luminious flux and then somehow calculate the radiance from that.&#xD;&#xA;&#xD;&#xA;Thanks in advance" ContentLicense="CC BY-SA 3.0" />
  <row Id="8605" PostHistoryTypeId="1" PostId="3995" RevisionGUID="47a75258-56b0-43f9-87b0-021a36d24d9b" CreationDate="2016-09-12T13:42:34.243" UserId="5114" Text="Solid angle and surface area values in (photometric) raytracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="8606" PostHistoryTypeId="3" PostId="3995" RevisionGUID="47a75258-56b0-43f9-87b0-021a36d24d9b" CreationDate="2016-09-12T13:42:34.243" UserId="5114" Text="|raytracing|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8607" PostHistoryTypeId="2" PostId="3996" RevisionGUID="7270dff0-6e35-4640-b9fd-617ade501d44" CreationDate="2016-09-12T13:46:16.877" UserId="3331" Text=" The simplest solution is to do three passes:&#xD;&#xA;&#xD;&#xA; - Render opaque meshes to a buffer (depth read/write on)&#xD;&#xA; - Render translucent meshes to another buffer (depth read/write on)&#xD;&#xA; - Alpha blend translucent mesh on top of opaque buffer using opaque depth buffer. (depth read on)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8608" PostHistoryTypeId="2" PostId="3997" RevisionGUID="05f41228-40f7-4666-a432-b1209d273640" CreationDate="2016-09-12T14:00:21.257" UserId="137" Text="welcome to the world of padding. Doubles are 8 byte aligned so when a 4 byte float gets inserted between 2 doubles some padding gets inserted to keep the next double aligned to a 8 byte boundary.&#xD;&#xA;&#xD;&#xA;You can make sure the offset is always correct (even when alignment changes in future versions) by using the [`Marshal.OffsetOf(Type, String)`][1] method.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.offsetof(v=vs.110).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="8610" PostHistoryTypeId="5" PostId="3993" RevisionGUID="aeeccf43-8813-4ab5-bf6f-f2ad0223896b" CreationDate="2016-09-12T15:36:30.583" UserId="209" Comment="deleted 6 characters in body" Text="Disclaimer: I haven't actually tested this but it seems feasible.&#xD;&#xA;&#xD;&#xA;I agree with [trichoplax](https://computergraphics.stackexchange.com/users/231/trichoplax) that what you want could possibly be expressed more clearly but, assuming I've understood correctly, would the following do the job?&#xD;&#xA;&#xD;&#xA;First I assume you can supply the opaque and translucent geometry separately, and that the opaque is sent first. I'm also going to assume there *may* be translucent geometry with exactly the same pixel Z values.(If this isn't the case, the stencil requirements could probably be dropped.)&#xD;&#xA;&#xD;&#xA;To handle the &quot;single translucent layer&quot;, clear the stencil buffer and send the translucent polygons to update the Z-buffer and set the stencil buffer on each pixel, but don't touch the frame buffer. &#xD;&#xA;&#xD;&#xA;Submit the translucent data a second time (to actually update the framebuffer),  but change the Z test to 'equal' and only allow drawing on the pixels that are currently set in the the stencil buffer. Also clear the stencil for any pixels that pass the tests.&#xD;&#xA;&#xD;&#xA;This, I think, should result in only the closest translucency layer being applied.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8611" PostHistoryTypeId="5" PostId="3996" RevisionGUID="20285260-43d1-4b93-99b1-a2782e150dfa" CreationDate="2016-09-12T15:36:49.107" UserId="3331" Comment="Reasoning" Text=" The simplest solution is to do three passes:&#xD;&#xA;&#xD;&#xA; - Render opaque meshes to a buffer (depth read/write on)&#xD;&#xA; - Render translucent meshes to another buffer (depth read/write on)  &#xD;&#xA;   This makes sure that only the closest translucent mesh is rendered.&#xD;&#xA; - Alpha blend translucent mesh on top of opaque buffer using opaque depth buffer. (depth read on)  &#xD;&#xA;This will take care of opaque meshes blocking translucent meshes and preserving translucent opacity levels. Depth test for values less or equal for small early z test (potential) optimisation.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8612" PostHistoryTypeId="5" PostId="3984" RevisionGUID="ec54a8f7-e93b-423f-8229-cdb7160f429e" CreationDate="2016-09-12T16:44:02.507" UserId="5104" Comment="added 37 characters in body" Text="I am writing a texture splatting pixel shader for meshes (not terrain) whereby I find a UV position from a raycast, which I convert to a local position, and then calculate a bounding box around that position.&#xD;&#xA;&#xD;&#xA;Then when cycling through the UVs (also converted to local positions) in the shader I am able to check if each UV is within the bounding box, and hence set a colour.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The bit I am struggling with is how to map each local position to the bounding box so I can then map that result to the splat texture using UVs or percentages.&#xD;&#xA;&#xD;&#xA;In the image above I have 6 splat points. As you can see the one is crossing an edge so I need to be able to transform the 3D position along all axes.&#xD;&#xA;&#xD;&#xA;I was thinking I could flatten/unfold the 3D point, but I'm not sure how to do this with all axes.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P28sG.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8613" PostHistoryTypeId="5" PostId="3996" RevisionGUID="ed494952-b2d7-4e80-a90c-10bdaa4e67ac" CreationDate="2016-09-12T17:31:40.257" UserId="3331" Comment="edits" Text=" The simplest solution is to do three passes:&#xD;&#xA;&#xD;&#xA; - Render opaque meshes to a buffer (front-to-back, depth read/write on)&#xD;&#xA; - Render translucent meshes to another buffer (front-to-back, depth read/write on)  &#xD;&#xA;   This makes sure that only the closest translucent mesh is rendered.&#xD;&#xA; - Alpha blend translucent mesh on top of opaque buffer using opaque depth buffer. (depth read on)  &#xD;&#xA;This will take care of opaque meshes blocking translucent meshes and preserving translucent opacity levels. Depth test for values less or equal for small early z test (potential) optimisation.&#xD;&#xA;&#xD;&#xA;EDIT: As mentioned below you could use the same depth buffer for the translucent pass and do the alpha blend then, the key is rendering the translucent pass front-to-back and depth write/testing.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8614" PostHistoryTypeId="2" PostId="3998" RevisionGUID="599a72f9-4942-4ad5-84e3-7ef9ef7a0fa8" CreationDate="2016-09-12T17:41:49.053" UserId="116" Text="Reading through some code about voxelization I found the following line in the fragment shader&#xD;&#xA;&#xD;&#xA;`layout (binding = 0, r32f ) coherent uniform writeonly image3D volumeTexture;`&#xD;&#xA;&#xD;&#xA;I have only used `samplers` in the past and have never seen `image3D` before. &#xD;&#xA;&#xD;&#xA;I have read the entries about [Sampler Varibles](https://www.opengl.org/wiki/Sampler_(GLSL)) and [Image Variables](https://www.opengl.org/wiki/Image_Load_Store#Image_variables) but I really don't grasp the differences, advantages/disadvantages between Sampler and Image.&#xD;&#xA;&#xD;&#xA;Can someone help me pointing out what are the difference between these two types of variables and when should I used one over the other?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8615" PostHistoryTypeId="1" PostId="3998" RevisionGUID="599a72f9-4942-4ad5-84e3-7ef9ef7a0fa8" CreationDate="2016-09-12T17:41:49.053" UserId="116" Text="What is the difference between a Sampler2D and an Image2D in GLSL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8616" PostHistoryTypeId="3" PostId="3998" RevisionGUID="599a72f9-4942-4ad5-84e3-7ef9ef7a0fa8" CreationDate="2016-09-12T17:41:49.053" UserId="116" Text="|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8617" PostHistoryTypeId="2" PostId="3999" RevisionGUID="87ceae49-72e7-41bb-831b-50aeb0a24f0b" CreationDate="2016-09-12T17:48:52.590" UserId="3331" Text="Unlike samplers imageLoad (Load in HLSL) requires an texel coordinate (integer). This will load the value at that location only. The range of the coordinate can be (0,0) to (image width, image height). Because only an integer can be supplied no sampling is applied to blend between multiple texels (e.g. bilinear in 2D). I'd therefore **assume** it is a cheaper operation.&#xD;&#xA;&#xD;&#xA;Image processing algorithms such as blurs often use image load so that discrete texel values can be processed." ContentLicense="CC BY-SA 3.0" />
  <row Id="8618" PostHistoryTypeId="5" PostId="3999" RevisionGUID="3684c228-c4b6-4c09-a5ab-412a433f72ad" CreationDate="2016-09-12T18:22:19.587" UserId="3331" Comment="grammar" Text="Unlike samplers imageLoad (Load in HLSL) requires a texel coordinate (integer). This will load the value at that location only. The range of the coordinate can be (0,0) to (image width, image height). Because only an integer can be supplied no sampling is applied to blend between multiple texels (e.g. bilinear in 2D). I'd therefore **assume** it is a cheaper operation.&#xD;&#xA;&#xD;&#xA;Image processing algorithms such as blurs often use image load so that discrete texel values can be processed." ContentLicense="CC BY-SA 3.0" />
  <row Id="8619" PostHistoryTypeId="2" PostId="4000" RevisionGUID="f5e3cc4b-3132-4b63-bed0-b5cca6c85978" CreationDate="2016-09-12T18:24:17.537" UserId="4958" Text=" - Images creation is the same as texture, but it must be binded as&#xD;&#xA;   image to image units. These are equivalent of &quot;texture units&quot;.&#xD;&#xA; - With them you can arbitrarily perform read/write/modify operations&#xD;&#xA;   using `imageStore/imageLoad` or atomic operations at some coordinates. Unlike samplers these&#xD;&#xA;   coordinates are in unsigned integer range.&#xD;&#xA; - They do need to be part of framebuffer color attachments to write&#xD;&#xA;   into them. This is useful and simplify some techniques like injecting&#xD;&#xA;   data into volume textures and is used in compute shaders. No need to use draw calls with buffer data upload.&#xD;&#xA; - There is no mipmapping or texture filtering available when doing&#xD;&#xA;   operation on texture binded as image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8620" PostHistoryTypeId="2" PostId="4001" RevisionGUID="113f29d6-ac77-46a3-ad55-56c7bab4eabe" CreationDate="2016-09-12T18:28:23.067" UserId="2351" Text="Image and Samplers differ in many ways. Unlike Samplers, images can only be addressed with an integer coordinate that ranges from  (0,0) to (x,y), where x and y are the width and height of the image. They support random access reads like texelFetch, and support no filtering as you're accessing raw texels. The most interesting thing with images is that they support read and write access, in Open GLES there are limitations, wherein an image may only be specified as readonly or writeonly, not both, in desktop GL though you may specify an image as read/write so that you can both read and write to that image in a single pass. &#xA;&#xA;Using a sampler, if you wanted to write a color into it you'd have to use an FBO, then a second pass to consume that. With images, you can do this all in one pass by writing to the image and reading from it, you'd have to handle the synchronisation yourself of course.&#xA;Images are very useful for image processing etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="8621" PostHistoryTypeId="4" PostId="3998" RevisionGUID="b4ff3c9d-362c-451b-83a5-97cf378b0a17" CreationDate="2016-09-12T19:03:29.133" UserId="116" Comment="Corrected title" Text="What is the difference between a Sampler and an Image variables in GLSL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8622" PostHistoryTypeId="2" PostId="4002" RevisionGUID="3c8a3feb-bfd5-414f-bbe6-319903cca74f" CreationDate="2016-09-12T19:03:31.397" UserId="2941" Text="I'm using www.scratchapixel.com among other resources to help me learn how to implement a renderer. I am looking at the following code from [this page][1] where a packet of photons moving through a material is being considered. For each photon packet, the weight $w$ is initialised to $1$. $dw$ is the probability of absorption.&#xD;&#xA;&#xD;&#xA;The confusing part to me is when $dw$ is subtracted from $w$. I can see this would make sense when the packet has full-weight of $1$ because $1 - dw$ is the unabsorbed proportion of photons. E.g. if probability of absorption is $33\%$ then $w = 1 - 0.33 = 0.67$ and $67\%$ of the photons remain. I can't see how this makes sense on subsequent iterations, can you?&#xD;&#xA;&#xD;&#xA;    int photons = 10000; &#xD;&#xA;    ... &#xD;&#xA;    int m = 5; // there's 1 over 6 chances for the packet to be absorbed &#xD;&#xA;    for (int i = 0; i &lt; nphotons; ++i) { &#xD;&#xA;        float w = 1; // set the weight to 1 &#xD;&#xA;        Vec3f P(0, 0, 0); &#xD;&#xA;        Vec3f V(0, 0, 1); &#xD;&#xA;        while (1) { &#xD;&#xA;            ... &#xD;&#xA;            float dw = sigma_a / sigma_t; &#xD;&#xA;            absorption += dw; &#xD;&#xA;            w -= dw; &#xD;&#xA;            if (w &lt; 0.001) { // perform russian roulette if weight is small &#xD;&#xA;                if (drand48() &lt; 1.0 / m) { &#xD;&#xA;                    break; // we kill the packet &#xD;&#xA;                } &#xD;&#xA;                else &#xD;&#xA;                    w *= m; // adjust weight &#xD;&#xA;            } &#xD;&#xA;        } &#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/monte-carlo-methods-in-practice/monte-carlo-simulation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8623" PostHistoryTypeId="1" PostId="4002" RevisionGUID="3c8a3feb-bfd5-414f-bbe6-319903cca74f" CreationDate="2016-09-12T19:03:31.397" UserId="2941" Text="Is this Russian roulette code correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8624" PostHistoryTypeId="3" PostId="4002" RevisionGUID="3c8a3feb-bfd5-414f-bbe6-319903cca74f" CreationDate="2016-09-12T19:03:31.397" UserId="2941" Text="|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8625" PostHistoryTypeId="5" PostId="3995" RevisionGUID="9abf7e16-29c2-4a26-9656-c82513468dfa" CreationDate="2016-09-12T19:07:26.130" UserId="5114" Comment="Added more elaborative description including an example of my thought process" Text="So, I started writing my second raytracer - this time focusing on photometric rendering that uses IES lights and standard photometric units.  I've got the basic raytracing up and running (using pure geometry), I've read any article I could found on radio- and photometry (I think I developed an intuition for it) but the issues started when I tried to validate/play with the underlying math.&#xD;&#xA;&#xD;&#xA;I use IES lights as a function of spherical coordinates that gives me the intensity of light in that direction in candelas (lumens per unit solid angle). Also in the equation for Luminance/Radiance there are differential solid angle and differential surface area. On the paper everything looks good, however:&#xD;&#xA;&#xD;&#xA;**My question is**: how should I deal with those parameters in my raytracer? I assume (but I'm not sure) that my (differential) solid angle is just a (unit) vector in descrete world and the surface area is simply a point - but what values should I plug in to those equations? I saw that on some websites that people just ignored those terms and replaced the integral with sum - but no explanation was given...&#xD;&#xA;&#xD;&#xA;And my second question is related to those IES lights - how can I simply convert intensity to radiance? The intensity already has the solid angle, but for radiance I need the surface area... Or should I somehow integrate the luminious intensity to get luminious flux and then somehow calculate the radiance from that.&#xD;&#xA;&#xD;&#xA;Thanks in advance&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:** I decided to try to grab a sheet of paper, try again and share with you my thought process. In order to simplify a lot of things:&#xD;&#xA;&#xD;&#xA;- each plane has a single scalar value as material (let's name it *reflectivity* between 0 and 1)&#xD;&#xA;  - $p1$ has $reflectivity = 0.5$&#xD;&#xA;  - $p2$ has $reflectivity = 1$&#xD;&#xA;&#xD;&#xA;- all materials are lambertian (no specular reflections nor emission)&#xD;&#xA;&#xD;&#xA;So with those in mind let's imagine that we have following scene:&#xD;&#xA;[![Example scene with 2 planes][1]][1]&#xD;&#xA;&#xD;&#xA;**Step 1 - Illuminance at $p1$**&#xD;&#xA;&#xD;&#xA;The light luminious intensity at vertical angle $V=0$ is $I = 6619 [cd]$. In order to compute the illuminance at point $p1$ we can create a sphere with radius equal to the distance between the light and intersection point $p1$ which is $r = 2$ meters. That virtual sphere intersects with the first plane creating a small differential area $dA$. Knowing that $d\omega = \frac {dA}{r^2}$ we get $E_L(r) = \frac {I}{r^2} [ \frac {W}{m^2}]$ which is equal to illuminance measured at a plane perpendicular to light. We have to project it to know how many light hits the $p1$, so $E = E_L \times cos \theta$. I **assume** that $L_i = E$, but that is just a guess. I hope that at this point I got it right...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Step 2 - Outgoing luminance**&#xD;&#xA;&#xD;&#xA;In order to calculate the outgoing radiance I think that is the place for the rendering equation to kick in:&#xD;&#xA;$$&#xD;&#xA;L_o = L_e + \int_{\Omega} f_r(\omega_i, \omega_o) L_i(p, \omega_i) cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;since I ignore the emission and my BRDF is $f_r(\omega_i, \omega_o) = \frac {reflectivity}{\pi}$ which is constant across the integral giving me:&#xD;&#xA;$$&#xD;&#xA;L_o = \frac {reflectivity}{\pi} \int_{\Omega} L_i(p, \omega_i) cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;Now I have to discretize it, which I don't fully understand. Based on my notes that I've made based on many pages I've got:&#xD;&#xA;$L_o = \frac {reflectivity}{\pi} \sum L_i(p, \omega_i) cos \theta \Rightarrow L_o = \frac {0.5}{\pi} L_i cos \theta$, where $L_i$ was calculated in step 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Step 3 - Luminance at $p2$**&#xD;&#xA;&#xD;&#xA;Can I assume that $L_{i_{p2}} = L(p_1 \rightarrow p_2) \times cos \theta = L_{o_{p1}} \times cos \theta$ ? I'm not sure if I have to apply the $cos \theta$ twice (for outgoing and incoming $dA$s).&#xD;&#xA;&#xD;&#xA;_I also would like to apologize for making this question sooo long - but I had never taken any course that would introduce radiometry and I was forced to (try to) learn it by myself._&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BRL0Y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8626" PostHistoryTypeId="5" PostId="4002" RevisionGUID="4a7c3124-5408-46d8-9041-d308e696aa3e" CreationDate="2016-09-12T19:29:11.853" UserId="2941" Comment="added 115 characters in body" Text="I'm using www.scratchapixel.com among other resources to help me learn how to implement a renderer. I am looking at the following code from [this page][1] where a packet of photons moving through a material is being considered. For each photon packet, the weight $w$ is initialised to $1$. $dw$ is the probability of absorption.&#xD;&#xA;&#xD;&#xA;The confusing part to me is when $dw$ is subtracted from $w$. I can see this would make sense when the packet has full-weight of $1$ because $1 - dw$ is the unabsorbed proportion of photons. E.g. if probability of absorption is $33\%$ then $w = 1 - 0.33 = 0.67$ and $67\%$ of the photons remain. I can't see how this makes sense on subsequent iterations. For example, on iteration two, $w = 0.67 - 0.33 = 0.34$ so half the photons are absorbed on this iteration, not a third.&#xD;&#xA;&#xD;&#xA;    int photons = 10000; &#xD;&#xA;    ... &#xD;&#xA;    int m = 5; // there's 1 over 6 chances for the packet to be absorbed &#xD;&#xA;    for (int i = 0; i &lt; nphotons; ++i) { &#xD;&#xA;        float w = 1; // set the weight to 1 &#xD;&#xA;        Vec3f P(0, 0, 0); &#xD;&#xA;        Vec3f V(0, 0, 1); &#xD;&#xA;        while (1) { &#xD;&#xA;            ... &#xD;&#xA;            float dw = sigma_a / sigma_t; &#xD;&#xA;            absorption += dw; &#xD;&#xA;            w -= dw; &#xD;&#xA;            if (w &lt; 0.001) { // perform russian roulette if weight is small &#xD;&#xA;                if (drand48() &lt; 1.0 / m) { &#xD;&#xA;                    break; // we kill the packet &#xD;&#xA;                } &#xD;&#xA;                else &#xD;&#xA;                    w *= m; // adjust weight &#xD;&#xA;            } &#xD;&#xA;        } &#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/monte-carlo-methods-in-practice/monte-carlo-simulation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8627" PostHistoryTypeId="2" PostId="4003" RevisionGUID="c1a93911-09fb-4ba5-9ee6-b16c05333070" CreationDate="2016-09-12T23:08:32.867" UserId="2351" Text="Doing it in the CPU side during initialization is what I'd go for, this is assuming you are initialising that data once and passing it to the GPU.&#xA;&#xA;On the GPU side, doing the calculations per fragment would be too costly and should be out of the question, unless it's really needed for a special effect then you shouldn't add unneeded ALU work to the fragment shader, this will only cause your application to slow down. On the vertex shader is more acceptable but again if you have highly tessellated geometry, it'll be expensive. &#xA;&#xA;Whenever there is data that you can compute just once, then go for that instead of doing it every frame. Even if you were planning on doing it just once on the GPU and using transform feedback or an FBO to store the data, I think this approach would be more costly. As always though, profile your application, careful tradeoffs are specific to architectures." ContentLicense="CC BY-SA 3.0" />
  <row Id="8628" PostHistoryTypeId="2" PostId="4004" RevisionGUID="d9d1abc2-b056-4b23-b78e-cc967807d01c" CreationDate="2016-09-13T11:52:00.110" UserId="5117" Text="I used visual studio c++ and opengl.I tried to put jpg image like background to my application. First time I tried with FreeImage library, but the image didn't show. Second time i tried with Gdiplus, i opened the image but when i opened and the object the background disappeared. I will send link to my project, If someone have any ideas i will be so happy, because I haven't yet.&#xD;&#xA;&#xD;&#xA;https://www.dropbox.com/sh/k6drd7de4...eK8aVjRTa?dl=0" ContentLicense="CC BY-SA 3.0" />
  <row Id="8629" PostHistoryTypeId="1" PostId="4004" RevisionGUID="d9d1abc2-b056-4b23-b78e-cc967807d01c" CreationDate="2016-09-13T11:52:00.110" UserId="5117" Text="Background behind 3D model" ContentLicense="CC BY-SA 3.0" />
  <row Id="8630" PostHistoryTypeId="3" PostId="4004" RevisionGUID="d9d1abc2-b056-4b23-b78e-cc967807d01c" CreationDate="2016-09-13T11:52:00.110" UserId="5117" Text="|opengl|texture|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8631" PostHistoryTypeId="2" PostId="4005" RevisionGUID="59f52cde-0d0e-4569-9541-a691c211c3d2" CreationDate="2016-09-13T19:06:08.477" UserId="56" Text="Let's say we are path tracing and that there is an object which has some amount of diffuse reflection, and some amount of specular reflection.&#xD;&#xA;&#xD;&#xA;What is the best or correct way to handle that in the path tracer?&#xD;&#xA;&#xD;&#xA;Looking at smallpt (http://www.kevinbeason.com/smallpt/), it doesn't allow for objects to have both, but instead forces materials to be either diffuse or specular.&#xD;&#xA;&#xD;&#xA;I've seen other path tracing code which rolls a random number to choose which way to go, using the luminance of the diffuse and specular reflectance as weightings in the random roll.&#xD;&#xA;&#xD;&#xA;I've also seen code which follows both paths and diverges when this happens and sums the results, where each recursive ray was multiplied by it's corresponding reflectance.&#xD;&#xA;&#xD;&#xA;I've seen refraction dealt with similarly to all the above.&#xD;&#xA;&#xD;&#xA;Is there a physically correct way to handle these situations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8632" PostHistoryTypeId="1" PostId="4005" RevisionGUID="59f52cde-0d0e-4569-9541-a691c211c3d2" CreationDate="2016-09-13T19:06:08.477" UserId="56" Text="Proper way to handle diffuse + refraction + reflection rays in path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8633" PostHistoryTypeId="3" PostId="4005" RevisionGUID="59f52cde-0d0e-4569-9541-a691c211c3d2" CreationDate="2016-09-13T19:06:08.477" UserId="56" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8634" PostHistoryTypeId="2" PostId="4006" RevisionGUID="7a1c28d0-c47b-49eb-9ca6-e00fc985a449" CreationDate="2016-09-14T00:03:18.343" UserId="273" Text="Let us take one step back.&#xD;&#xA;When you do path tracing, you are doing a Monte Carlo integration.&#xD;&#xA;What does this mean? You try to solve $\int f(x)\mathrm{d}x$ by sampling.&#xD;&#xA;The Monte Carlo integration says for a sufficiently big $n$: $\frac{1}{n}\sum_{i=0}^n f(x_i) \rightarrow \int f(x)p(x) \mathrm{d}x$&#xD;&#xA;&#xD;&#xA;If we instead sum $\frac{f(x_i)}{p(x_i)}$ we get $\frac{1}{n}\sum_{i=0}^n \frac{f(x_i)}{p(x_i)} \rightarrow \int f(x) \mathrm{d}x$.&#xD;&#xA;Now your $f(x)$ is the rendering equation and you got yourself a way to approximate the rendering equation.&#xD;&#xA;&#xD;&#xA;Now that we are on the same page about the basics, let's consider what you do.&#xD;&#xA;You generate a path of light, that will become one of the samples $\frac{f(x_i)}{p(x_i)}$. In order to do this you model the interaction of the light with the surface at each step along the path. And you always update your current path probability $p(x_i)$.&#xD;&#xA;&#xD;&#xA;What is now the correct way to handle a material that has multiple different ways that a ray could travel? There is no one correct way. The only important part is, that your values $n$, $f(x_i)$ and $p(x_i)$ stay correct.&#xD;&#xA;&#xD;&#xA;When you diverge the path and spawn two rays, you have to increase the number $n$ of total samples accordingly because now you have done two samples. Then handle both pathes as if they were separate from the beginning.&#xD;&#xA;&#xD;&#xA;If you want to only continue one path, you can do it with the russian roulette way.&#xD;&#xA;Define three intervals (one common way is to chose the intervals to be a partition of the numbers between 0 and 1). The relative sizes of these intervals have to be proportional to the material. The tricky part is how do you design this. In my class we defined a number reflectivity $\rho$.&#xD;&#xA;We draw a random number between 0 and 1, if it is lower than $\rho$ the path ends. Else we reflect. The BRDF will take care to weight the specular vs diffuse part if you do enough samples.&#xD;&#xA;&#xD;&#xA;Of course you can improve this via importance sampling, and that is probably where you have problems. For a very specular surface design a random distribution that just draws more directions from the specular reflection direction. Rest will be diffuse. I don't have enough experience with actually bulding path tracers to help you how to design one, but your sources will probably have something here.&#xD;&#xA;&#xD;&#xA;Important here is again: Design it so that you know how probable a specific direction is, and then keep your $p(x_i)$ up to it, so you can in the end divide by this and get a correct Monte Carlo estimate.&#xD;&#xA;&#xD;&#xA;TL;DR There is no correct way. It is ONLY important to keep the probabilities of samples in mind.&#xD;&#xA;&#xD;&#xA;I hope I haven't missed the point of your question entirely.&#xD;&#xA;&#xD;&#xA;Addition:&#xD;&#xA;Monte Carlo samling, as long as you correct weighting by probability, will always with infinite samples converge against the correct value. This means even if you use a complete stupid way to generate samples, if you do it long enough, that will work. Maybe not in your lifetime or that of your great grandchildren, but it will." ContentLicense="CC BY-SA 3.0" />
  <row Id="8636" PostHistoryTypeId="2" PostId="4007" RevisionGUID="2a9b3bc7-77c5-44f8-81ca-d37c5f848cc3" CreationDate="2016-09-14T07:49:05.447" UserId="137" Text="Normally if you paint a background image you simply draw a textured full-screen square while depth testing and writing is disabled before drawing the actual scene (where you re-enable depth)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8637" PostHistoryTypeId="5" PostId="4000" RevisionGUID="3c8ef8b2-60bd-45d5-bf18-f77f2ee5dbd9" CreationDate="2016-09-14T09:05:31.750" UserId="4958" Comment="added 4 characters in body" Text=" - Images creation is the same as texture, but it must be binded as&#xD;&#xA;   image to image units. These are equivalent of &quot;texture units&quot;.&#xD;&#xA; - With them you can arbitrarily perform read/write/modify operations&#xD;&#xA;   using `imageStore/imageLoad` or atomic operations at some coordinates. Unlike samplers these&#xD;&#xA;   coordinates are in unsigned integer range.&#xD;&#xA; - They do not need to be part of framebuffer color attachments to write&#xD;&#xA;   into them. This is useful and simplify some techniques like injecting&#xD;&#xA;   data into volume textures and is used in compute shaders. No need to use draw calls with buffer data upload.&#xD;&#xA; - There is no mipmapping or texture filtering available when doing&#xD;&#xA;   operation on texture binded as image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8638" PostHistoryTypeId="2" PostId="4008" RevisionGUID="8068f711-eee8-4b86-81bb-4bc1bbcc420c" CreationDate="2016-09-14T11:53:11.273" UserId="5121" Text="I am given geometry of a cylinder which lies on the XY plane with 1 unit radius. And given coordinates of 2 points in 3D I need to move the cylinder so that it connects the two points.&#xD;&#xA;&#xD;&#xA;What I tried so far after searching online:&#xD;&#xA;&#xD;&#xA;1. Calculated the vector between the two points p = p1 - p2;&#xD;&#xA;2. Took the normal vector to the plane(0,0,1) v&#xD;&#xA;3. Axis of rotation = v x p (cross)&#xD;&#xA;4. angle of rotation = acos(|v|.|p|) (unit vectors)&#xD;&#xA;5. I applied this rotation.&#xD;&#xA;6. Translated one of the end point of cylinder to one of the points.&#xD;&#xA;&#xD;&#xA;but it moves the object to a wrong location. Any help what I'm doing wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8639" PostHistoryTypeId="1" PostId="4008" RevisionGUID="8068f711-eee8-4b86-81bb-4bc1bbcc420c" CreationDate="2016-09-14T11:53:11.273" UserId="5121" Text="Rotate a cylinder from XY plane to given points" ContentLicense="CC BY-SA 3.0" />
  <row Id="8640" PostHistoryTypeId="3" PostId="4008" RevisionGUID="8068f711-eee8-4b86-81bb-4bc1bbcc420c" CreationDate="2016-09-14T11:53:11.273" UserId="5121" Text="|opengl|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8641" PostHistoryTypeId="2" PostId="4009" RevisionGUID="0c10b7e5-7ac3-4505-b1f1-1bceba635b80" CreationDate="2016-09-14T15:46:57.783" UserId="48" Text="I think you're right and the subtraction is a mistake. The code should rather be multiplying the fraction of photons not absorbed into the weight. Something like:&#xD;&#xA;&#xD;&#xA;    float fraction_absorbed = sigma_a / sigma_t;&#xD;&#xA;    absorption += w * fraction_absorbed;&#xD;&#xA;    w *= (1.0f - fraction_absorbed);&#xD;&#xA;&#xD;&#xA;This makes `absorption` the total fraction of photons absorbed so far, and `w` the fraction of photons remaining." ContentLicense="CC BY-SA 3.0" />
  <row Id="8644" PostHistoryTypeId="5" PostId="2130" RevisionGUID="fac6056a-e908-4575-9000-8eb464c1d82d" CreationDate="2016-09-14T19:37:35.923" UserId="310" Comment="Fix typo" Text="In ray tracing / path tracing, one of the simplest way to anti-alias the image is to supersample the pixel values and average the results. IE. instead of shooting every sample through the center of the pixel, you offset the samples by some amount.&#xD;&#xA;&#xD;&#xA;In searching around the internet, I've found two somewhat different methods to do this:&#xD;&#xA;&#xD;&#xA;1. Generate samples however you want and weigh the result with a filter&#xD;&#xA;  - One example is [PBRT][1]&#xD;&#xA;2. Generate the samples with a distribution equal to the shape of a filter&#xD;&#xA;  - Two examples are [smallpt][2] and [Benedikt Bitterli][3]'s [Tungsten Renderer][4] &#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate and Weigh**&#xD;&#xA;&#xD;&#xA;The basic process is:&#xD;&#xA;&#xD;&#xA;  1. Create samples however you want (randomly, stratified, low-discrepancy sequences, etc.) &#xD;&#xA;  2. Offset the camera ray using two samples (x and y)&#xD;&#xA;  3. Render the scene with the ray&#xD;&#xA;  4. Calculate a weight using a filter function and the distance of the sample in reference to the pixel center. For example, Box Filter, Tent Filter, Gaussian Filter, etc.)&#xD;&#xA;[![Filter Shapes][5]][5]&#xD;&#xA;  5. Apply the weight to the color from the render&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate in the shape of a filter**&#xD;&#xA;&#xD;&#xA;The basic premise is to use [Inverse Transform Sampling][6] to create samples that are distributed according to the shape of a filter. For example a histogram of a samples distributed in the shape of a Gaussian would be:&lt;br/&gt;&#xD;&#xA;[![Gaussian Histogram][7]][7]&#xD;&#xA;&#xD;&#xA;This can either be done exactly, or by binning the function into a discrete pdf/cdf. [smallpt][2] uses the exact inverse cdf of a tent filter. Examples of binning method can be found [here][8]&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;What are the pros and cons of each method? And why would you use one over the other? I can think of a few things:&#xD;&#xA;&#xD;&#xA;Generate and Weigh seems to be the most robust, allowing any combination of any sampling method with any filter. However, it requires you to track the weights in the ImageBuffer and then do a final resolve.&#xD;&#xA;&#xD;&#xA;Generate in the Shape of a Filter can only support positive filter shapes (ie. no Mitchell, Catmull Rom, or Lanczos), since you can not have a negative pdf. But, as mentioned above, it's easier to implement, since you don't need to track any weights.&#xD;&#xA;&#xD;&#xA;Though, in the end, I guess you can think of method 2 as a simplification of method 1, since it's essentially using an implicit Box Filter weight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/core/film.h#L114&#xD;&#xA;  [2]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;  [3]: http://computergraphics.stackexchange.com/users/79/benedikt-bitterli&#xD;&#xA;  [4]: https://github.com/tunabrain/tungsten/blob/master/src/core/cameras/ReconstructionFilter.hpp&#xD;&#xA;  [5]: https://i.stack.imgur.com/gz7Bg.png&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Inverse_transform_sampling&#xD;&#xA;  [7]: https://i.stack.imgur.com/7pGFS.png&#xD;&#xA;  [8]: https://gist.github.com/RichieSams/ce2ca2a201227c1de543&#xD;&#xA;  " ContentLicense="CC BY-SA 3.0" />
  <row Id="8645" PostHistoryTypeId="2" PostId="4010" RevisionGUID="d4972cd7-64fc-4af3-b60a-a0dee9f5c13f" CreationDate="2016-09-15T03:25:15.923" UserId="3003" Text="For the lightning, I recommend using a midpoint displacement algorithm. You start with a line segment between any 2 points A and B (this works in either 2D or 3D). Calculate the midpoint of the segment AB. Now move that point a random amount in the direction perpendicular to the line segment AB and call it point C. Replace the original segment AB with 2 line segments AC and CB. Repeat with the new line segments until you are satisfied with how it looks. In my experience you'll need somewhere between 5 and 10 iterations depending on the resolution you're working at. You can add a glow to the resulting geometry to make it look more realistic.&#xD;&#xA;&#xD;&#xA;For sparks you need to make a particle system. These are pretty fun. You generally have a point (or other shape) that generates particles every few milliseconds. That is, particles are spontaneously formed on the point or boundary of the shape periodically. Each particle has various properties such as location, velocity, color, size, lifetime, etc. When animating, you can update the velocity and position based on various forces such as gravity, wind, or some sort of convection current or flow field. After a particle has reached its &quot;lifetime&quot; it can disappear, or fade out, and a new particle will be generated in its place at the point or on the boundary of the shape. The particles themselves can be drawn as single pixels, small shapes, or images. There's an [interesting wikipedia article on particle systems](https://en.wikipedia.org/wiki/Particle_system)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8646" PostHistoryTypeId="10" PostId="4004" RevisionGUID="5a97cc61-625e-484d-b969-a04de8c7c24b" CreationDate="2016-09-15T08:59:52.773" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8647" PostHistoryTypeId="5" PostId="4004" RevisionGUID="081650c7-99ce-478d-9596-4a7ae8fc4768" CreationDate="2016-09-15T14:10:21.663" UserId="5117" Comment="added 32 characters in body" Text="I used visual studio c++ and opengl.I tried to put jpg image like background to my application. First time I tried with FreeImage library, but the image didn't show. Second time i tried with Gdiplus, i opened the image but when i opened and the object the background disappeared. I will send link to my project, If someone have any ideas i will be so happy, because I haven't yet.&#xD;&#xA;&#xD;&#xA;https://github.com/Nushiii/viewer/blob/master/ViewerPicture%20FreeImege/ViewerPicture/main.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="8648" PostHistoryTypeId="2" PostId="4011" RevisionGUID="b690b7ff-18c3-47e5-8088-346f7800bb73" CreationDate="2016-09-15T17:02:16.237" UserId="5129" Text="I've been doing some side-research on computer graphics as a hobby and came across this article on quaternions:&#xD;&#xA;http://www.opengl-tutorial.org/assets/faq_quaternions/index.html#Q2&#xD;&#xA;&#xD;&#xA;In the first section on matrices, it describes 2x2, 3x3, and 4x4 matrices and their functions.  Here is the entry on 3x3 matrices:&#xD;&#xA;&#xD;&#xA;&gt;   3x3 matrices are used to perform low-budget 3D animation. Operations&#xD;&#xA;&gt; such as rotation and multiplication can be performed using matrix  &#xD;&#xA;&gt; operations, but perspective depth projection is performed using  &#xD;&#xA;&gt; standard optimised into pure divide operations.&#xD;&#xA;&#xD;&#xA;I'm not sure if this blurb means that 3x3 matrices aren't used anymore or if we are still using them for simpler calculations on certain animations.  I understand what perspective depth projection is, but what does it mean it is performed using pure divide operations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8649" PostHistoryTypeId="1" PostId="4011" RevisionGUID="b690b7ff-18c3-47e5-8088-346f7800bb73" CreationDate="2016-09-15T17:02:16.237" UserId="5129" Text="Do we use 3x3 matrices in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8650" PostHistoryTypeId="3" PostId="4011" RevisionGUID="b690b7ff-18c3-47e5-8088-346f7800bb73" CreationDate="2016-09-15T17:02:16.237" UserId="5129" Text="|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8651" PostHistoryTypeId="5" PostId="4004" RevisionGUID="f81706e2-d761-46db-806d-ad7dde080b70" CreationDate="2016-09-15T18:22:59.757" UserId="5117" Comment="added 31 characters in body" Text="I have object loader, which i want to have background. I tried to put jpg image like texture to my application. I tried to make that with FreeImage library, but the image didn't show. Also i tried with Gdiplus, i opened the image but when i opened and the object the background disappeared.&#xA;I send link with the code (with FreeImage library), If someone have any ideas i will be so happy, because I haven't yet.&#xD;&#xA;&#xD;&#xA;https://github.com/Nushiii/viewer/blob/master/ViewerPicture%20FreeImege/ViewerPicture/main.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="8652" PostHistoryTypeId="5" PostId="4004" RevisionGUID="9af1254a-59c8-486a-8074-343e8d0c2ee4" CreationDate="2016-09-15T18:50:28.067" UserId="5117" Comment="added 31 characters in body" Text="I have object loader, which i want to have background. I tried to put jpg image like texture to my application. I tried to make that with FreeImage library, but the image didn't show. Also i tried with Gdiplus, i opened the image but when i opened and the object the background disappeared.&#xD;&#xA;I send link with the code (with FreeImage library), If someone have any ideas i will be so happy, because I haven't yet.&#xD;&#xA;&#xD;&#xA;https://github.com/Nushiii/viewer/blob/master/ViewerPicture%20FreeImege/ViewerPicture/main.cpp&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;           int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;        MSG msg = {0};&#xD;&#xA;        WNDCLASSEX wcl = {0};&#xD;&#xA;    &#xD;&#xA;    	GLuint texture;&#xD;&#xA;    	float theta = 0.0f;&#xD;&#xA;    &#xD;&#xA;        wcl.cbSize = sizeof(wcl);&#xD;&#xA;        wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;&#xD;&#xA;        wcl.lpfnWndProc = WindowProc;&#xD;&#xA;        wcl.cbClsExtra = 0;&#xD;&#xA;        wcl.cbWndExtra = 0;&#xD;&#xA;        wcl.hInstance = g_hInstance = hInstance;&#xD;&#xA;        wcl.hIcon = static_cast&lt;HICON&gt;(LoadImage(hInstance,&#xD;&#xA;        MAKEINTRESOURCE (IDI_ICON1),&#xD;&#xA;        IMAGE_ICON,&#xD;&#xA;        48, 48,    // or whatever size icon you want to load&#xD;&#xA;        LR_DEFAULTCOLOR));&#xD;&#xA;        wcl.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;        wcl.hbrBackground = 0;&#xD;&#xA;        wcl.lpszMenuName = MAKEINTRESOURCE(MENU_FIXED_FUNC);&#xD;&#xA;        wcl.lpszClassName = &quot;GLWindowClass&quot;;&#xD;&#xA;        wcl.hIconSm = 0;&#xD;&#xA;    &#xD;&#xA;        if (!RegisterClassEx(&amp;wcl))&#xD;&#xA;            return 0;&#xD;&#xA;    &#xD;&#xA;        g_hWnd = CreateAppWindow(wcl, APP_TITLE);&#xD;&#xA;    &#xD;&#xA;        	  // load our texture&#xD;&#xA;          FIBITMAP  *dib1 = loadImage(&quot;angel.jpg&quot;);&#xD;&#xA;          texture = LoadTexturee( dib1, TRUE );&#xD;&#xA;    &#xD;&#xA;        if (g_hWnd)&#xD;&#xA;        {&#xD;&#xA;            SetProcessorAffinity();&#xD;&#xA;    &#xD;&#xA;            if (Init())&#xD;&#xA;            {&#xD;&#xA;                ShowWindow(g_hWnd, nShowCmd);&#xD;&#xA;                UpdateWindow(g_hWnd);&#xD;&#xA;    &#xD;&#xA;                while (true)&#xD;&#xA;                {&#xD;&#xA;                    if (PeekMessage(&amp;msg, 0, 0, 0, PM_REMOVE))&#xD;&#xA;                    {&#xD;&#xA;                        if (msg.message == WM_QUIT)&#xD;&#xA;                            break;&#xD;&#xA;    &#xD;&#xA;                        TranslateMessage(&amp;msg);&#xD;&#xA;                        DispatchMessage(&amp;msg);&#xD;&#xA;                    } else {&#xD;&#xA;&#xD;&#xA;I think that i make mistike here and with DrawFrame function, maybe both functions overlap.I need DrawFrame() for the object. &#xD;&#xA;    &#xD;&#xA;    					// OpenGL animation code goes here&#xD;&#xA;    					glClearColor( 0.4f, 0.0f, 0.0f, 0.0f );&#xD;&#xA;    					//glClear( GL_COLOR_BUFFER_BIT );&#xD;&#xA;    &#xD;&#xA;    					// setup texture mapping&#xD;&#xA;    					glEnable( GL_TEXTURE_2D );&#xD;&#xA;    					glBindTexture( GL_TEXTURE_2D, texture );&#xD;&#xA;    &#xD;&#xA;    					glPushMatrix();&#xD;&#xA;    					//glRotatef( theta, 0.0f, 0.0f, 1.0f );&#xD;&#xA;    					glBegin( GL_QUADS );&#xD;&#xA;    					glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);&#xD;&#xA;    					glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);&#xD;&#xA;    					glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);&#xD;&#xA;    					glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);&#xD;&#xA;    					glEnd();&#xD;&#xA;    					glPopMatrix();&#xD;&#xA;          &#xD;&#xA;    					//SwapBuffers( g_hDC );&#xD;&#xA;          &#xD;&#xA;    					//theta += 1.0f;&#xD;&#xA;    &#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;                    if (msg.message == WM_QUIT)&#xD;&#xA;                        break;&#xD;&#xA;    &#xD;&#xA;                    if (g_hasFocus)&#xD;&#xA;                    {&#xD;&#xA;                        UpdateFrame(GetElapsedTimeInSeconds());&#xD;&#xA;                        DrawFrame();&#xD;&#xA;                        SwapBuffers(g_hDC);&#xD;&#xA;                    }&#xD;&#xA;                    else&#xD;&#xA;                    {&#xD;&#xA;                        WaitMessage();&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            Cleanup();&#xD;&#xA;            UnregisterClass(wcl.lpszClassName, hInstance);&#xD;&#xA;        }&#xD;&#xA;    	FreeTexture( texture );&#xD;&#xA;        return static_cast&lt;int&gt;(msg.wParam);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    FIBITMAP  *loadImage(const char *filename)&#xD;&#xA;    {&#xD;&#xA;    	FIBITMAP *dib1 = NULL;&#xD;&#xA;    	FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(filename);&#xD;&#xA;    &#xD;&#xA;    	dib1 = FreeImage_Load(fif, filename, JPEG_DEFAULT);&#xD;&#xA;    	if (!dib1)&#xD;&#xA;        {&#xD;&#xA;           //std::cerr &lt;&lt; &quot;Erreur ouverture d\'image&quot; &lt;&lt; std::endl;&#xD;&#xA;           exit (0);&#xD;&#xA;    &#xD;&#xA;        } &#xD;&#xA;    	return dib1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void DrawFrame()&#xD;&#xA;    {&#xD;&#xA;        glViewport(0, 0, g_windowWidth, g_windowHeight);&#xD;&#xA;        //glClearColor(0.0f, 0.6f, 0.9f, 0.0f);&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        glMatrixMode(GL_PROJECTION);&#xD;&#xA;        glLoadIdentity();&#xD;&#xA;        gluPerspective(CAMERA_FOVY,&#xD;&#xA;            static_cast&lt;float&gt;(g_windowWidth) / static_cast&lt;float&gt;(g_windowHeight),&#xD;&#xA;            CAMERA_ZNEAR, CAMERA_ZFAR);&#xD;&#xA;    &#xD;&#xA;        glMatrixMode(GL_MODELVIEW);&#xD;&#xA;        glLoadIdentity();&#xD;&#xA;        gluLookAt(g_cameraPos[0], g_cameraPos[1], g_cameraPos[2],&#xD;&#xA;            g_targetPos[0], g_targetPos[1], g_targetPos[2],&#xD;&#xA;            0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;        glRotatef(g_pitch, 1.0f, 0.0f, 0.0f);&#xD;&#xA;        glRotatef(g_heading, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;        if (g_supportsProgrammablePipeline)&#xD;&#xA;            DrawModelUsingProgrammablePipeline();&#xD;&#xA;        else&#xD;&#xA;            DrawModelUsingFixedFuncPipeline();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    GLuint LoadTexturee( FIBITMAP  * dib1, int wrap )&#xD;&#xA;    {&#xD;&#xA;     GLuint texture = 0;&#xD;&#xA;    	int x, y;&#xD;&#xA;    	int height, width;&#xD;&#xA;    	//BYTE * data;&#xD;&#xA;    	RGBQUAD rgbquad;&#xD;&#xA;    	FREE_IMAGE_TYPE type;&#xD;&#xA;    	BITMAPINFOHEADER *header;&#xD;&#xA;      &#xD;&#xA;    	type = FreeImage_GetImageType(dib1);&#xD;&#xA;    	height = FreeImage_GetHeight(dib1);&#xD;&#xA;    	width = FreeImage_GetWidth(dib1);&#xD;&#xA;    	//data = ( unsigned char * )malloc( width * height * 3 );&#xD;&#xA;    &#xD;&#xA;      &#xD;&#xA;    	header = FreeImage_GetInfoHeader(dib1);&#xD;&#xA;    	int scanLineWidh = ((3*width)%4 == 0) ? 3*width : ((3*width)/4)*4+4;&#xD;&#xA;    	unsigned char * texels= (GLubyte*)calloc(height*scanLineWidh, sizeof(GLubyte));&#xD;&#xA;    	for (x=0 ; x&lt;width ; x++)&#xD;&#xA;    		for (y=0 ; y&lt;height; y++)&#xD;&#xA;    		{  &#xD;&#xA;    		  FreeImage_GetPixelColor(dib1,x,y,&amp;rgbquad);&#xD;&#xA;    &#xD;&#xA;    		  texels[(y*scanLineWidh+3*x)]=((GLubyte*)&amp;rgbquad)[2];&#xD;&#xA;    		  texels[(y*scanLineWidh+3*x)+1]=((GLubyte*)&amp;rgbquad)[1];&#xD;&#xA;    		  texels[(y*scanLineWidh+3*x)+2]=((GLubyte*)&amp;rgbquad)[0];&#xD;&#xA;    		 }&#xD;&#xA;    &#xD;&#xA;      // allocate a texture name&#xD;&#xA;      glGenTextures( 1, &amp;texture );&#xD;&#xA;    &#xD;&#xA;      // select our current texture&#xD;&#xA;      glBindTexture( GL_TEXTURE_2D, texture );&#xD;&#xA;    &#xD;&#xA;      // select modulate to mix texture with color for shading&#xD;&#xA;      glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&#xD;&#xA;    &#xD;&#xA;      // when texture area is small, bilinear filter the closest MIP map&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,&#xD;&#xA;                       GL_LINEAR_MIPMAP_NEAREST );&#xD;&#xA;      // when texture area is large, bilinear filter the first MIP map&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );&#xD;&#xA;    &#xD;&#xA;      // if wrap is true, the texture wraps over at the edges (repeat)&#xD;&#xA;      //       ... false, the texture ends at the edges (clamp)&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&#xD;&#xA;                       wrap ? GL_REPEAT : GL_CLAMP );&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&#xD;&#xA;                       wrap ? GL_REPEAT : GL_CLAMP );&#xD;&#xA;    &#xD;&#xA;      // build our texture MIP maps&#xD;&#xA;      gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width,&#xD;&#xA;        height, GL_RGB, GL_UNSIGNED_BYTE, texels );&#xD;&#xA;    &#xD;&#xA;      // free buffer&#xD;&#xA;      free( texels );&#xD;&#xA;    &#xD;&#xA;      return texture;&#xD;&#xA;    &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8653" PostHistoryTypeId="2" PostId="4012" RevisionGUID="38a8eaec-2da5-4149-ba43-b6e72dacf0f0" CreationDate="2016-09-16T03:47:27.583" UserId="3003" Text="That quote is a very strange way to phrase things. We definitely use 3x3 matrices in computer graphics. They tend to be most useful for doing affine transformations of 2D objects. It allows you to have scale, rotation, shearing, and translation, but not perspective transformations. I believe that's what the quote is trying to say.&#xD;&#xA;&#xD;&#xA;To get a perspective projection of a 3D scene onto a 2D plane (such as your computer screen), at some point you will need to divide the x and y components of each point in your geometry by some factor that foreshortens lines in the z dimension. That's the divide that they are referring to. See [this article](https://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection) for more details. In it, they describe:&#xD;&#xA;&#xD;&#xA;&gt; The simplest perspective projection uses the origin as the center of projection, and z = 1 as the image plane. The functional form of this transformation is then *x' = x / z*; *y' = y / z*." ContentLicense="CC BY-SA 3.0" />
  <row Id="8654" PostHistoryTypeId="11" PostId="4004" RevisionGUID="229ecf66-2f3c-41c4-8958-d663574858f4" CreationDate="2016-09-16T07:58:18.970" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8656" PostHistoryTypeId="4" PostId="3990" RevisionGUID="7d8fd3fb-2c89-4fc5-8efd-95afc51d9911" CreationDate="2016-09-16T08:47:28.577" UserId="5089" Comment="edited title" Text="Where is the best place for Tangent-bitangent calculation, in shader or in C/CPP code?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8657" PostHistoryTypeId="2" PostId="4013" RevisionGUID="7994f933-8e5b-409b-a1d6-d9c70a5ebfd7" CreationDate="2016-09-16T16:25:18.357" UserId="56" Text="In graphics, it's common to take multiple samples within the bounds of a pixel and combine them together (most commonly just doing an average) for a final sample pixel color.  This has the effect of anti aliasing an image.&#xD;&#xA;&#xD;&#xA;On one hand this makes sense to me because what you are effectively doing is integrating the color of the pixel over the area that the pixel represents.  In this line of thinking, averaging &quot;random&quot; samples seems to be the ideal setup, for doing monte carlo integration.  (&quot;random&quot; could be stratified, blue noise based, low discrepency sequences etc)&#xD;&#xA;&#xD;&#xA;On the other hand, this feels wrong (or at least not as correct as it could be) from a digital signal processing point of view.  From that point of view, it feels like we are taking a lot of samples and then downsampling using a box filter (box blur) to get the final pixel value.  In that light, it seems like the ideal thing to do would be to use sinc filtering instead of averaging the samples.  I could see that the box filter is a cheaper aproximation to sinc thinking along these lines.&#xD;&#xA;&#xD;&#xA;This leaves me a bit confused.  Is the core idea that we are integrating the pixel area and averaging is correct?  Or is it that we are downsampling and should be using sinc, but are using a box filter because it's fast?&#xD;&#xA;&#xD;&#xA;Or is it something else entirely?&#xD;&#xA;&#xD;&#xA;A little bit related: http://computergraphics.stackexchange.com/questions/2130/anti-aliasing-filtering-in-ray-tracing&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8658" PostHistoryTypeId="1" PostId="4013" RevisionGUID="7994f933-8e5b-409b-a1d6-d9c70a5ebfd7" CreationDate="2016-09-16T16:25:18.357" UserId="56" Text="What is the fundamental reasoning for anti aliasing using multiple random samples within a pixel?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8659" PostHistoryTypeId="3" PostId="4013" RevisionGUID="7994f933-8e5b-409b-a1d6-d9c70a5ebfd7" CreationDate="2016-09-16T16:25:18.357" UserId="56" Text="|sampling|antialiasing|supersampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8663" PostHistoryTypeId="2" PostId="4015" RevisionGUID="0601459c-e736-4a08-903c-b30004b6523c" CreationDate="2016-09-16T18:32:05.067" UserId="38" Text="You are in fact doing both things. You are integrating the area and because your result is still discrete samples you are reconstructing the signal to make it continious function. Therefore the higher order filtering. (Also human eye is a discrete sampler so it also reconstructs the signal)&#xD;&#xA;&#xD;&#xA;It took me a considerable amount of time to come into terms with this explanation. The thing that helped me was a paper by Tony Apodaca titled [The Lore of TDs](https://renderman.pixar.com/view/the-lore-of-the-tds)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8664" PostHistoryTypeId="5" PostId="4012" RevisionGUID="ca5275f1-2333-413b-be91-b6fba6d202e9" CreationDate="2016-09-16T20:50:12.490" UserId="3003" Comment="clarified translation is only in 2D" Text="That quote is a very strange way to phrase things. We definitely use 3x3 matrices in computer graphics. They tend to be most useful for doing affine transformations of 2D objects. It allows you to have scale, rotation, shearing, and translation (in 2D), but not perspective transformations. I believe that's what the quote is trying to say.&#xD;&#xA;&#xD;&#xA;To get a perspective projection of a 3D scene onto a 2D plane (such as your computer screen), at some point you will need to divide the x and y components of each point in your geometry by some factor that foreshortens lines in the z dimension. That's the divide that they are referring to. See [this article](https://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection) for more details. In it, they describe:&#xD;&#xA;&#xD;&#xA;&gt; The simplest perspective projection uses the origin as the center of projection, and z = 1 as the image plane. The functional form of this transformation is then *x' = x / z*; *y' = y / z*." ContentLicense="CC BY-SA 3.0" />
  <row Id="8665" PostHistoryTypeId="2" PostId="4016" RevisionGUID="6233c9e3-873b-47bb-8937-8972f2ecf36f" CreationDate="2016-09-16T22:43:27.390" UserId="5136" Text="I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube light where the lights look the same as sphere lights despite the length value being changed.&#xD;&#xA;&#xD;&#xA;I am working from epics paper on PBR [found here][1], I have tried looking at other sources to see if i could find anything that but none of the results fixed the issue i was having.&#xD;&#xA;&#xD;&#xA;The method i am using for tube lighting is as follows:&#xD;&#xA;&#xD;&#xA;    float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)&#xD;&#xA;    {&#xD;&#xA;        float3 pos   = (cLightPosPS.xyz - worldPos);&#xD;&#xA;        float3 reflectVec  = reflect(-toCamera, normal);&#xD;&#xA;        &#xD;&#xA;        float3 L01 = lightVec * LightLengh;&#xD;&#xA;        float3 L0 = pos - 0.5 * L01;&#xD;&#xA;        float3 L1 = pos + 0.5 * L01;&#xD;&#xA;        float3 ld = L1 - L0;&#xD;&#xA;&#xD;&#xA;        float distL0    = length( L0 );&#xD;&#xA;        float distL1    = length( L1 );&#xD;&#xA;&#xD;&#xA;        float NoL0      = dot( L0, normal ) / ( 2.0 * distL0 );&#xD;&#xA;        float NoL1      = dot( L1, normal ) / ( 2.0 * distL1 );&#xD;&#xA;        ndl             = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) &#xD;&#xA;                        / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );&#xD;&#xA;    &#xD;&#xA;        float RoL0      = dot( reflectVec, L0 );&#xD;&#xA;        float RoLd      = dot( reflectVec, ld );&#xD;&#xA;        float L0oLd     = dot( L0, ld );&#xD;&#xA;        float distLd    = length( ld );&#xD;&#xA;        float t         = ( RoL0 * RoLd - L0oLd ) &#xD;&#xA;                    / ( distLd * distLd - RoLd * RoLd );&#xD;&#xA;        &#xD;&#xA;        float3 closestPoint   = L0 + ld * saturate( t);&#xD;&#xA;        float3 centreToRay    = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;&#xD;&#xA;        closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));&#xD;&#xA;&#xD;&#xA;        float3 l = normalize(closestPoint);&#xD;&#xA;        float3 h = normalize(toCamera + l);&#xD;&#xA;&#xD;&#xA;        ndl       = saturate(dot(normal, l));&#xD;&#xA;        float hdn = saturate(dot(h, normal));&#xD;&#xA;        float hdv = dot(h, toCamera);&#xD;&#xA;        float ndv = saturate(dot(normal, toCamera));&#xD;&#xA;&#xD;&#xA;        float distL      = length(closestPoint);&#xD;&#xA;        float alpha      = roughness * roughness;&#xD;&#xA;        float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);&#xD;&#xA;&#xD;&#xA;        const float3 fresnelTerm = Fresnel(specColor, hdv) ;&#xD;&#xA;        const float distTerm     = Distribution(hdn, alphaPrime);&#xD;&#xA;        const float visTerm      = Visibility(ndl, ndv, roughness);&#xD;&#xA;&#xD;&#xA;        return distTerm * visTerm * fresnelTerm ;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the code snippet is not enough to help solve this issue you can download the full area lighting branch from github, [found here][2]. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shaders source files can be found under &#xD;&#xA;[build location]/bin/CoreData/Shaders/HLSL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: https://github.com/dragonCASTjosh/Urho3D" ContentLicense="CC BY-SA 3.0" />
  <row Id="8666" PostHistoryTypeId="1" PostId="4016" RevisionGUID="6233c9e3-873b-47bb-8937-8972f2ecf36f" CreationDate="2016-09-16T22:43:27.390" UserId="5136" Text="Error with tube lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="8667" PostHistoryTypeId="3" PostId="4016" RevisionGUID="6233c9e3-873b-47bb-8937-8972f2ecf36f" CreationDate="2016-09-16T22:43:27.390" UserId="5136" Text="|lighting|physically-based|directx11|hlsl|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8668" PostHistoryTypeId="5" PostId="4016" RevisionGUID="36d40264-3f06-4e3d-ad4d-f6386eefbe4a" CreationDate="2016-09-17T00:11:29.113" UserId="5136" Comment="added 43 characters in body" Text="I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube light where the lights look the same as sphere lights despite the length value being changed.&#xD;&#xA;&#xD;&#xA;I am working from epics paper on PBR [found here][1], I have tried looking at other sources to see if i could find anything that but none of the results fixed the issue i was having.&#xD;&#xA;&#xD;&#xA;The method i am using for tube lighting is as follows:&#xD;&#xA;&#xD;&#xA;    float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)&#xD;&#xA;    {&#xD;&#xA;        float3 pos   = (cLightPosPS.xyz - worldPos);&#xD;&#xA;        float3 reflectVec  = reflect(-toCamera, normal);&#xD;&#xA;        &#xD;&#xA;        float3 L01 = lightVec * LightLengh;&#xD;&#xA;        float3 L0 = pos - 0.5 * L01;&#xD;&#xA;        float3 L1 = pos + 0.5 * L01;&#xD;&#xA;        float3 ld = L1 - L0;&#xD;&#xA;&#xD;&#xA;        float distL0    = length( L0 );&#xD;&#xA;        float distL1    = length( L1 );&#xD;&#xA;&#xD;&#xA;        float NoL0      = dot( L0, normal ) / ( 2.0 * distL0 );&#xD;&#xA;        float NoL1      = dot( L1, normal ) / ( 2.0 * distL1 );&#xD;&#xA;        ndl             = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) &#xD;&#xA;                        / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );&#xD;&#xA;    &#xD;&#xA;        float RoL0      = dot( reflectVec, L0 );&#xD;&#xA;        float RoLd      = dot( reflectVec, ld );&#xD;&#xA;        float L0oLd     = dot( L0, ld );&#xD;&#xA;        float distLd    = length( ld );&#xD;&#xA;        float t         = ( RoL0 * RoLd - L0oLd ) &#xD;&#xA;                    / ( distLd * distLd - RoLd * RoLd );&#xD;&#xA;        &#xD;&#xA;        float3 closestPoint   = L0 + ld * saturate( t);&#xD;&#xA;        float3 centreToRay    = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;&#xD;&#xA;        closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));&#xD;&#xA;&#xD;&#xA;        float3 l = normalize(closestPoint);&#xD;&#xA;        float3 h = normalize(toCamera + l);&#xD;&#xA;&#xD;&#xA;        ndl       = saturate(dot(normal, l));&#xD;&#xA;        float hdn = saturate(dot(h, normal));&#xD;&#xA;        float hdv = dot(h, toCamera);&#xD;&#xA;        float ndv = saturate(dot(normal, toCamera));&#xD;&#xA;&#xD;&#xA;        float distL      = length(closestPoint);&#xD;&#xA;        float alpha      = roughness * roughness;&#xD;&#xA;        float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);&#xD;&#xA;&#xD;&#xA;        const float3 fresnelTerm = Fresnel(specColor, hdv) ;&#xD;&#xA;        const float distTerm     = Distribution(hdn, alphaPrime);&#xD;&#xA;        const float visTerm      = Visibility(ndl, ndv, roughness);&#xD;&#xA;&#xD;&#xA;        return distTerm * visTerm * fresnelTerm ;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the code snippet is not enough to help solve this issue you can download the full area lighting branch from github, [found here][2]. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shaders source files can be found under &#xD;&#xA;[build location]/bin/CoreData/Shaders/HLSL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: https://github.com/dragonCASTjosh/Urho3D&#xD;&#xA;  [3]: https://i.stack.imgur.com/3rDUJ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8669" PostHistoryTypeId="5" PostId="4016" RevisionGUID="8b4f609a-d2dc-4dba-9b01-0483e3addc36" CreationDate="2016-09-17T00:22:35.190" UserId="56" Comment="added 58 characters in body" Text="I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube light where the lights look the same as sphere lights despite the length value being changed.&#xD;&#xA;&#xD;&#xA;I am working from epics paper on PBR [found here][1], I have tried looking at other sources to see if i could find anything that but none of the results fixed the issue i was having.&#xD;&#xA;&#xD;&#xA;The method i am using for tube lighting is as follows:&#xD;&#xA;&#xD;&#xA;    float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)&#xD;&#xA;    {&#xD;&#xA;        float3 pos   = (cLightPosPS.xyz - worldPos);&#xD;&#xA;        float3 reflectVec  = reflect(-toCamera, normal);&#xD;&#xA;        &#xD;&#xA;        float3 L01 = lightVec * LightLengh;&#xD;&#xA;        float3 L0 = pos - 0.5 * L01;&#xD;&#xA;        float3 L1 = pos + 0.5 * L01;&#xD;&#xA;        float3 ld = L1 - L0;&#xD;&#xA;&#xD;&#xA;        float distL0    = length( L0 );&#xD;&#xA;        float distL1    = length( L1 );&#xD;&#xA;&#xD;&#xA;        float NoL0      = dot( L0, normal ) / ( 2.0 * distL0 );&#xD;&#xA;        float NoL1      = dot( L1, normal ) / ( 2.0 * distL1 );&#xD;&#xA;        ndl             = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) &#xD;&#xA;                        / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );&#xD;&#xA;    &#xD;&#xA;        float RoL0      = dot( reflectVec, L0 );&#xD;&#xA;        float RoLd      = dot( reflectVec, ld );&#xD;&#xA;        float L0oLd     = dot( L0, ld );&#xD;&#xA;        float distLd    = length( ld );&#xD;&#xA;        float t         = ( RoL0 * RoLd - L0oLd ) &#xD;&#xA;                    / ( distLd * distLd - RoLd * RoLd );&#xD;&#xA;        &#xD;&#xA;        float3 closestPoint   = L0 + ld * saturate( t);&#xD;&#xA;        float3 centreToRay    = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;&#xD;&#xA;        closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));&#xD;&#xA;&#xD;&#xA;        float3 l = normalize(closestPoint);&#xD;&#xA;        float3 h = normalize(toCamera + l);&#xD;&#xA;&#xD;&#xA;        ndl       = saturate(dot(normal, l));&#xD;&#xA;        float hdn = saturate(dot(h, normal));&#xD;&#xA;        float hdv = dot(h, toCamera);&#xD;&#xA;        float ndv = saturate(dot(normal, toCamera));&#xD;&#xA;&#xD;&#xA;        float distL      = length(closestPoint);&#xD;&#xA;        float alpha      = roughness * roughness;&#xD;&#xA;        float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);&#xD;&#xA;&#xD;&#xA;        const float3 fresnelTerm = Fresnel(specColor, hdv) ;&#xD;&#xA;        const float distTerm     = Distribution(hdn, alphaPrime);&#xD;&#xA;        const float visTerm      = Visibility(ndl, ndv, roughness);&#xD;&#xA;&#xD;&#xA;        return distTerm * visTerm * fresnelTerm ;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the code snippet is not enough to help solve this issue you can download the full area lighting branch from github, [found here][2]. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shaders source files can be found under &#xD;&#xA;[build location]/bin/CoreData/Shaders/HLSL&#xD;&#xA;&#xD;&#xA;You can see the images here:&#xD;&#xA;https://i.stack.imgur.com/uAZTJ.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: https://github.com/dragonCASTjosh/Urho3D&#xD;&#xA;  [3]: https://i.stack.imgur.com/3rDUJ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8675" PostHistoryTypeId="2" PostId="4018" RevisionGUID="0bdd9c22-814e-44ca-9e5d-0ad00b0fb5de" CreationDate="2016-09-17T04:17:53.697" UserId="48" Text="From a signal processing point of view, you're sampling a continuous-domain signal, and you need to filter it to get rid of frequencies beyond the Nyquist limit. It's that filtering that leads to integrating over the pixel area—or more generally, integrating over the support of your antialiasing kernel (which need not be a box).&#xD;&#xA;&#xD;&#xA;Consider your rendering function that takes a sample point $x, y$ in screen space and returns back the color found at that point. (Let's ignore any issues of random sampling for the moment, and assume it returns a &quot;perfect&quot; rendered color for that specific point.) This function effectively defines a 2D continuous-domain signal. Or to put it another way, it defines an _infinite-resolution_ image, since nothing prevents this function from having features at arbitrarily small scales. In terms of frequency domain: the function is not band-limited; it can include components of arbitrarily high spatial frequencies.&#xD;&#xA;&#xD;&#xA;Now you want to convert it down to a finite number of pixels. Much like digitizing an audio signal, when you sample it, you'll get aliasing unless you first eliminate frequencies beyond the Nyquist limit imposed by the sampling rate. In other words, you have to get rid of features smaller than the pixel grid. To do this, you apply a low-pass filter. The _ideal_ low-pass filter is the sinc function, but for various reasons of practicality we use other filters (that don't perfectly eliminate frequencies beyond the Nyquist limit, but they at least attenuate them).&#xD;&#xA;&#xD;&#xA;Low-pass filtering is done by convolution. If $f(x, y)$ is the rendering function and $k(x, y)$ is a filter kernel, then we can define the low-pass filtered image as:&#xD;&#xA;&#xD;&#xA;$$f_\text{filtered}(x, y) = \iint f(x', y') \, k(x' - x, y'- y) \, dx' \, dy'$$&#xD;&#xA;&#xD;&#xA;Then the image is safe to sample, so the final pixel values are gotten by just evaluating $f_\text{filtered}$ at the pixel coordinates.&#xD;&#xA;&#xD;&#xA;If $k$ is a box filter, which looks like $k = 1$ within the pixel box and $k = 0$ elsewhere, then this simplifies to just integrating $f$ over the pixel box. But as noted, the box filter isn't so great and there are better choices such as tent, bicubic, and Gaussian filters.&#xD;&#xA;&#xD;&#xA;Anyway, now that we have an integral, we can use Monte Carlo for it and combine it with any other integrals we might like to do—for lighting, motion blur, and so on. We can even apply importance sampling to the $k$ factor in the integral, by generating samples for each pixel that are distributed around the pixel center according to $k$." ContentLicense="CC BY-SA 3.0" />
  <row Id="8676" PostHistoryTypeId="5" PostId="4016" RevisionGUID="a981efbd-5b47-41a9-a66d-01191b08313c" CreationDate="2016-09-17T08:28:40.183" UserId="231" Comment="Add image" Text="I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube lights where the lights look the same as sphere lights despite the length value being changed.&#xD;&#xA;&#xD;&#xA;I am working from [Epic's paper on PBR][1] by Brian Karis. I have tried looking at other sources to see if I could find anything but none of the results fixed the issue I was having.&#xD;&#xA;&#xD;&#xA;The method I am using for tube lighting is as follows:&#xD;&#xA;&#xD;&#xA;    float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)&#xD;&#xA;    {&#xD;&#xA;        float3 pos   = (cLightPosPS.xyz - worldPos);&#xD;&#xA;        float3 reflectVec  = reflect(-toCamera, normal);&#xD;&#xA;        &#xD;&#xA;        float3 L01 = lightVec * LightLengh;&#xD;&#xA;        float3 L0 = pos - 0.5 * L01;&#xD;&#xA;        float3 L1 = pos + 0.5 * L01;&#xD;&#xA;        float3 ld = L1 - L0;&#xD;&#xA;&#xD;&#xA;        float distL0    = length( L0 );&#xD;&#xA;        float distL1    = length( L1 );&#xD;&#xA;&#xD;&#xA;        float NoL0      = dot( L0, normal ) / ( 2.0 * distL0 );&#xD;&#xA;        float NoL1      = dot( L1, normal ) / ( 2.0 * distL1 );&#xD;&#xA;        ndl             = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) &#xD;&#xA;                        / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );&#xD;&#xA;    &#xD;&#xA;        float RoL0      = dot( reflectVec, L0 );&#xD;&#xA;        float RoLd      = dot( reflectVec, ld );&#xD;&#xA;        float L0oLd     = dot( L0, ld );&#xD;&#xA;        float distLd    = length( ld );&#xD;&#xA;        float t         = ( RoL0 * RoLd - L0oLd ) &#xD;&#xA;                    / ( distLd * distLd - RoLd * RoLd );&#xD;&#xA;        &#xD;&#xA;        float3 closestPoint   = L0 + ld * saturate( t);&#xD;&#xA;        float3 centreToRay    = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;&#xD;&#xA;        closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));&#xD;&#xA;&#xD;&#xA;        float3 l = normalize(closestPoint);&#xD;&#xA;        float3 h = normalize(toCamera + l);&#xD;&#xA;&#xD;&#xA;        ndl       = saturate(dot(normal, l));&#xD;&#xA;        float hdn = saturate(dot(h, normal));&#xD;&#xA;        float hdv = dot(h, toCamera);&#xD;&#xA;        float ndv = saturate(dot(normal, toCamera));&#xD;&#xA;&#xD;&#xA;        float distL      = length(closestPoint);&#xD;&#xA;        float alpha      = roughness * roughness;&#xD;&#xA;        float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);&#xD;&#xA;&#xD;&#xA;        const float3 fresnelTerm = Fresnel(specColor, hdv) ;&#xD;&#xA;        const float distTerm     = Distribution(hdn, alphaPrime);&#xD;&#xA;        const float visTerm      = Visibility(ndl, ndv, roughness);&#xD;&#xA;&#xD;&#xA;        return distTerm * visTerm * fresnelTerm ;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the code snippet is not enough to help solve this issue you can download the [full area lighting branch][2] from GitHub. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shader source files can be found under &#xD;&#xA;&#xD;&#xA;    [build location]/bin/CoreData/Shaders/HLSL&#xD;&#xA;&#xD;&#xA;[![tube light image][tube image]][tube image]&#xD;&#xA;&#xD;&#xA;You can see that both images look identical [here](https://i.stack.imgur.com/uAZTJ.jpg).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: https://github.com/dragonCASTjosh/Urho3D&#xD;&#xA;&#xD;&#xA;  [tube image]: https://i.stack.imgur.com/3rDUJ.jpg&#xD;&#xA;  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8677" PostHistoryTypeId="5" PostId="4016" RevisionGUID="31932e66-b545-4beb-8287-6f11eb5c16c6" CreationDate="2016-09-17T08:47:17.620" UserId="5136" Comment="deleted 4 characters in body" Text="I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube lights where the lights look the same as sphere lights despite the length value being changed.&#xD;&#xA;&#xD;&#xA;I am working from [Epic's paper on PBR][1] by Brian Karis. I have tried looking at other sources to see if I could find anything but none of the results fixed the issue I was having.&#xD;&#xA;&#xD;&#xA;The method I am using for tube lighting is as follows:&#xD;&#xA;&#xD;&#xA;    float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)&#xD;&#xA;    {&#xD;&#xA;        float3 pos   = (cLightPosPS.xyz - worldPos);&#xD;&#xA;        float3 reflectVec  = reflect(-toCamera, normal);&#xD;&#xA;        &#xD;&#xA;        float3 L01 = lightVec * LightLengh;&#xD;&#xA;        float3 L0 = pos - 0.5 * L01;&#xD;&#xA;        float3 L1 = pos + 0.5 * L01;&#xD;&#xA;        float3 ld = L1 - L0;&#xD;&#xA;&#xD;&#xA;        float distL0    = length( L0 );&#xD;&#xA;        float distL1    = length( L1 );&#xD;&#xA;&#xD;&#xA;        float NoL0      = dot( L0, normal ) / ( 2.0 * distL0 );&#xD;&#xA;        float NoL1      = dot( L1, normal ) / ( 2.0 * distL1 );&#xD;&#xA;        ndl             = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) &#xD;&#xA;                        / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );&#xD;&#xA;    &#xD;&#xA;        float RoL0      = dot( reflectVec, L0 );&#xD;&#xA;        float RoLd      = dot( reflectVec, ld );&#xD;&#xA;        float L0oLd     = dot( L0, ld );&#xD;&#xA;        float distLd    = length( ld );&#xD;&#xA;        float t         = ( RoL0 * RoLd - L0oLd ) &#xD;&#xA;                    / ( distLd * distLd - RoLd * RoLd );&#xD;&#xA;        &#xD;&#xA;        float3 closestPoint   = L0 + ld * saturate( t);&#xD;&#xA;        float3 centreToRay    = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;&#xD;&#xA;        closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));&#xD;&#xA;&#xD;&#xA;        float3 l = normalize(closestPoint);&#xD;&#xA;        float3 h = normalize(toCamera + l);&#xD;&#xA;&#xD;&#xA;        ndl       = saturate(dot(normal, l));&#xD;&#xA;        float hdn = saturate(dot(h, normal));&#xD;&#xA;        float hdv = dot(h, toCamera);&#xD;&#xA;        float ndv = saturate(dot(normal, toCamera));&#xD;&#xA;&#xD;&#xA;        float distL      = length(closestPoint);&#xD;&#xA;        float alpha      = roughness * roughness;&#xD;&#xA;        float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);&#xD;&#xA;&#xD;&#xA;        const float3 fresnelTerm = Fresnel(specColor, hdv) ;&#xD;&#xA;        const float distTerm     = Distribution(hdn, alphaPrime);&#xD;&#xA;        const float visTerm      = Visibility(ndl, ndv, roughness);&#xD;&#xA;&#xD;&#xA;        return distTerm * visTerm * fresnelTerm ;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the code snippet is not enough to help solve this issue you can download the [full area lighting branch][2] from GitHub. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shader source files can be found under &#xD;&#xA;&#xD;&#xA;    [build location]/bin/CoreData/Shaders/HLSL&#xD;&#xA;&#xD;&#xA;[![tube light image][tube image]][tube image]&#xD;&#xA;&#xD;&#xA;You can see that both images look identical [here](https://i.stack.imgur.com/uAZTJ.jpg).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: https://github.com/dragonCASTjosh/Urho3D&#xD;&#xA;&#xD;&#xA;  [tube image]: https://i.stack.imgur.com/BinG1.jpg&#xD;&#xA;  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8681" PostHistoryTypeId="5" PostId="4004" RevisionGUID="f0e87041-0065-42d9-8427-fe225734229d" CreationDate="2016-09-17T10:16:50.430" UserId="5117" Comment="added 12 characters in body" Text="I have object loader, which i want to have background. I tried to put jpg image like texture to my application. I tried to make that with FreeImage library, but the image didn't show. Also i tried with Gdiplus, i opened the image but when i opened and the object the background disappeared.&#xD;&#xA;I send link with the code (with FreeImage library), If someone have any ideas i will be so happy, because I haven't yet.&#xD;&#xA;&#xD;&#xA;https://github.com/Nushiii/viewer/blob/master/ViewerPicture%20FreeImege/ViewerPicture/main.cpp&#xD;&#xA;&#xD;&#xA; **EDIT:**&#xD;&#xA;&#xD;&#xA;           int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;        MSG msg = {0};&#xD;&#xA;        WNDCLASSEX wcl = {0};&#xD;&#xA;    &#xD;&#xA;    	GLuint texture;&#xD;&#xA;    	float theta = 0.0f;&#xD;&#xA;    &#xD;&#xA;        wcl.cbSize = sizeof(wcl);&#xD;&#xA;        wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;&#xD;&#xA;        wcl.lpfnWndProc = WindowProc;&#xD;&#xA;        wcl.cbClsExtra = 0;&#xD;&#xA;        wcl.cbWndExtra = 0;&#xD;&#xA;        wcl.hInstance = g_hInstance = hInstance;&#xD;&#xA;        wcl.hIcon = static_cast&lt;HICON&gt;(LoadImage(hInstance,&#xD;&#xA;        MAKEINTRESOURCE (IDI_ICON1),&#xD;&#xA;        IMAGE_ICON,&#xD;&#xA;        48, 48,    // or whatever size icon you want to load&#xD;&#xA;        LR_DEFAULTCOLOR));&#xD;&#xA;        wcl.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;        wcl.hbrBackground = 0;&#xD;&#xA;        wcl.lpszMenuName = MAKEINTRESOURCE(MENU_FIXED_FUNC);&#xD;&#xA;        wcl.lpszClassName = &quot;GLWindowClass&quot;;&#xD;&#xA;        wcl.hIconSm = 0;&#xD;&#xA;    &#xD;&#xA;        if (!RegisterClassEx(&amp;wcl))&#xD;&#xA;            return 0;&#xD;&#xA;    &#xD;&#xA;        g_hWnd = CreateAppWindow(wcl, APP_TITLE);&#xD;&#xA;    &#xD;&#xA;        	  // load our texture&#xD;&#xA;          FIBITMAP  *dib1 = loadImage(&quot;angel.jpg&quot;);&#xD;&#xA;          texture = LoadTexturee( dib1, TRUE );&#xD;&#xA;    &#xD;&#xA;        if (g_hWnd)&#xD;&#xA;        {&#xD;&#xA;            SetProcessorAffinity();&#xD;&#xA;    &#xD;&#xA;            if (Init())&#xD;&#xA;            {&#xD;&#xA;                ShowWindow(g_hWnd, nShowCmd);&#xD;&#xA;                UpdateWindow(g_hWnd);&#xD;&#xA;    &#xD;&#xA;                while (true)&#xD;&#xA;                {&#xD;&#xA;                    if (PeekMessage(&amp;msg, 0, 0, 0, PM_REMOVE))&#xD;&#xA;                    {&#xD;&#xA;                        if (msg.message == WM_QUIT)&#xD;&#xA;                            break;&#xD;&#xA;    &#xD;&#xA;                        TranslateMessage(&amp;msg);&#xD;&#xA;                        DispatchMessage(&amp;msg);&#xD;&#xA;                    } else {&#xD;&#xA;&#xD;&#xA;I think that i make mistike here and with DrawFrame function, maybe both functions overlap.I need DrawFrame() for the object. &#xD;&#xA;    &#xD;&#xA;    					// OpenGL animation code goes here&#xD;&#xA;    					glClearColor( 0.4f, 0.0f, 0.0f, 0.0f );&#xD;&#xA;    					//glClear( GL_COLOR_BUFFER_BIT );&#xD;&#xA;    &#xD;&#xA;    					// setup texture mapping&#xD;&#xA;    					glEnable( GL_TEXTURE_2D );&#xD;&#xA;    					glBindTexture( GL_TEXTURE_2D, texture );&#xD;&#xA;    &#xD;&#xA;    					glPushMatrix();&#xD;&#xA;    					//glRotatef( theta, 0.0f, 0.0f, 1.0f );&#xD;&#xA;    					glBegin( GL_QUADS );&#xD;&#xA;    					glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);&#xD;&#xA;    					glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);&#xD;&#xA;    					glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);&#xD;&#xA;    					glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);&#xD;&#xA;    					glEnd();&#xD;&#xA;    					glPopMatrix();&#xD;&#xA;          &#xD;&#xA;    					//SwapBuffers( g_hDC );&#xD;&#xA;          &#xD;&#xA;    					//theta += 1.0f;&#xD;&#xA;    &#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;                    if (msg.message == WM_QUIT)&#xD;&#xA;                        break;&#xD;&#xA;    &#xD;&#xA;                    if (g_hasFocus)&#xD;&#xA;                    {&#xD;&#xA;                        UpdateFrame(GetElapsedTimeInSeconds());&#xD;&#xA;                        DrawFrame();&#xD;&#xA;                        SwapBuffers(g_hDC);&#xD;&#xA;                    }&#xD;&#xA;                    else&#xD;&#xA;                    {&#xD;&#xA;                        WaitMessage();&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            Cleanup();&#xD;&#xA;            UnregisterClass(wcl.lpszClassName, hInstance);&#xD;&#xA;        }&#xD;&#xA;    	FreeTexture( texture );&#xD;&#xA;        return static_cast&lt;int&gt;(msg.wParam);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    FIBITMAP  *loadImage(const char *filename)&#xD;&#xA;    {&#xD;&#xA;    	FIBITMAP *dib1 = NULL;&#xD;&#xA;    	FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(filename);&#xD;&#xA;    &#xD;&#xA;    	dib1 = FreeImage_Load(fif, filename, JPEG_DEFAULT);&#xD;&#xA;    	if (!dib1)&#xD;&#xA;        {&#xD;&#xA;           //std::cerr &lt;&lt; &quot;Erreur ouverture d\'image&quot; &lt;&lt; std::endl;&#xD;&#xA;           exit (0);&#xD;&#xA;    &#xD;&#xA;        } &#xD;&#xA;    	return dib1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void DrawFrame()&#xD;&#xA;    {&#xD;&#xA;        glViewport(0, 0, g_windowWidth, g_windowHeight);&#xD;&#xA;        //glClearColor(0.0f, 0.6f, 0.9f, 0.0f);&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        glMatrixMode(GL_PROJECTION);&#xD;&#xA;        glLoadIdentity();&#xD;&#xA;        gluPerspective(CAMERA_FOVY,&#xD;&#xA;            static_cast&lt;float&gt;(g_windowWidth) / static_cast&lt;float&gt;(g_windowHeight),&#xD;&#xA;            CAMERA_ZNEAR, CAMERA_ZFAR);&#xD;&#xA;    &#xD;&#xA;        glMatrixMode(GL_MODELVIEW);&#xD;&#xA;        glLoadIdentity();&#xD;&#xA;        gluLookAt(g_cameraPos[0], g_cameraPos[1], g_cameraPos[2],&#xD;&#xA;            g_targetPos[0], g_targetPos[1], g_targetPos[2],&#xD;&#xA;            0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;        glRotatef(g_pitch, 1.0f, 0.0f, 0.0f);&#xD;&#xA;        glRotatef(g_heading, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;        if (g_supportsProgrammablePipeline)&#xD;&#xA;            DrawModelUsingProgrammablePipeline();&#xD;&#xA;        else&#xD;&#xA;            DrawModelUsingFixedFuncPipeline();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    GLuint LoadTexturee( FIBITMAP  * dib1, int wrap )&#xD;&#xA;    {&#xD;&#xA;     GLuint texture = 0;&#xD;&#xA;    	int x, y;&#xD;&#xA;    	int height, width;&#xD;&#xA;    	//BYTE * data;&#xD;&#xA;    	RGBQUAD rgbquad;&#xD;&#xA;    	FREE_IMAGE_TYPE type;&#xD;&#xA;    	BITMAPINFOHEADER *header;&#xD;&#xA;      &#xD;&#xA;    	type = FreeImage_GetImageType(dib1);&#xD;&#xA;    	height = FreeImage_GetHeight(dib1);&#xD;&#xA;    	width = FreeImage_GetWidth(dib1);&#xD;&#xA;    	//data = ( unsigned char * )malloc( width * height * 3 );&#xD;&#xA;    &#xD;&#xA;      &#xD;&#xA;    	header = FreeImage_GetInfoHeader(dib1);&#xD;&#xA;    	int scanLineWidh = ((3*width)%4 == 0) ? 3*width : ((3*width)/4)*4+4;&#xD;&#xA;    	unsigned char * texels= (GLubyte*)calloc(height*scanLineWidh, sizeof(GLubyte));&#xD;&#xA;    	for (x=0 ; x&lt;width ; x++)&#xD;&#xA;    		for (y=0 ; y&lt;height; y++)&#xD;&#xA;    		{  &#xD;&#xA;    		  FreeImage_GetPixelColor(dib1,x,y,&amp;rgbquad);&#xD;&#xA;    &#xD;&#xA;    		  texels[(y*scanLineWidh+3*x)]=((GLubyte*)&amp;rgbquad)[2];&#xD;&#xA;    		  texels[(y*scanLineWidh+3*x)+1]=((GLubyte*)&amp;rgbquad)[1];&#xD;&#xA;    		  texels[(y*scanLineWidh+3*x)+2]=((GLubyte*)&amp;rgbquad)[0];&#xD;&#xA;    		 }&#xD;&#xA;    &#xD;&#xA;      // allocate a texture name&#xD;&#xA;      glGenTextures( 1, &amp;texture );&#xD;&#xA;    &#xD;&#xA;      // select our current texture&#xD;&#xA;      glBindTexture( GL_TEXTURE_2D, texture );&#xD;&#xA;    &#xD;&#xA;      // select modulate to mix texture with color for shading&#xD;&#xA;      glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&#xD;&#xA;    &#xD;&#xA;      // when texture area is small, bilinear filter the closest MIP map&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,&#xD;&#xA;                       GL_LINEAR_MIPMAP_NEAREST );&#xD;&#xA;      // when texture area is large, bilinear filter the first MIP map&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );&#xD;&#xA;    &#xD;&#xA;      // if wrap is true, the texture wraps over at the edges (repeat)&#xD;&#xA;      //       ... false, the texture ends at the edges (clamp)&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&#xD;&#xA;                       wrap ? GL_REPEAT : GL_CLAMP );&#xD;&#xA;      glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&#xD;&#xA;                       wrap ? GL_REPEAT : GL_CLAMP );&#xD;&#xA;    &#xD;&#xA;      // build our texture MIP maps&#xD;&#xA;      gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width,&#xD;&#xA;        height, GL_RGB, GL_UNSIGNED_BYTE, texels );&#xD;&#xA;    &#xD;&#xA;      // free buffer&#xD;&#xA;      free( texels );&#xD;&#xA;    &#xD;&#xA;      return texture;&#xD;&#xA;    &#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8682" PostHistoryTypeId="5" PostId="4007" RevisionGUID="00a3419c-d06a-4e27-b561-28f0118f1fa0" CreationDate="2016-09-17T12:30:43.597" UserId="137" Comment="added 164 characters in body" Text="Normally if you paint a background image you simply draw a textured full-screen square while depth testing and writing is disabled before drawing the actual scene (where you re-enable depth)&#xD;&#xA;&#xD;&#xA;In the code you posted you draw the quad but then clear the screen again. Don't do that. Move the drawing of the quad from main to right after the `glClear` call." ContentLicense="CC BY-SA 3.0" />
  <row Id="8683" PostHistoryTypeId="2" PostId="4019" RevisionGUID="5cad8f6d-4ed1-4fb5-a34d-81f071835219" CreationDate="2016-09-17T16:06:39.290" UserDisplayName="user464" Text="The following is the 2d complex sinusoidal function,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;$u_0$ and $v_0$ represent Fundamental Frequencies in $X$ and $Y$ directions respectively.&#xD;&#xA;&#xD;&#xA;I need to implement that sinusoidal function in this present form so that, I can plot it and save it in a Bitmap image file. &#xD;&#xA;&#xD;&#xA;How can I represent $j$ (imaginary number)?&#xD;&#xA;&#xD;&#xA;What values should I assign to $u_0$ and $v_0$ respectively to plot that Sinusoidal Function?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SPyuQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8684" PostHistoryTypeId="1" PostId="4019" RevisionGUID="5cad8f6d-4ed1-4fb5-a34d-81f071835219" CreationDate="2016-09-17T16:06:39.290" UserDisplayName="user464" Text="How can I implement a complex sinusoidal function?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8685" PostHistoryTypeId="3" PostId="4019" RevisionGUID="5cad8f6d-4ed1-4fb5-a34d-81f071835219" CreationDate="2016-09-17T16:06:39.290" UserDisplayName="user464" Text="|image-processing|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8686" PostHistoryTypeId="5" PostId="4019" RevisionGUID="bfcd93ce-f0d1-416e-9769-302edd49e299" CreationDate="2016-09-17T16:36:54.133" UserDisplayName="user464" Comment="deleted 93 characters in body" Text="The following is the 2d complex sinusoidal function,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;$u_0$ and $v_0$ represent Fundamental Frequencies in $X$ and $Y$ directions respectively.&#xD;&#xA;&#xD;&#xA;I need to implement that sinusoidal function in this present form so that, I can plot it and save it in a Bitmap image file. &#xD;&#xA;&#xD;&#xA;How can I represent $j$ (imaginary number)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SPyuQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8687" PostHistoryTypeId="5" PostId="4019" RevisionGUID="691e0bc7-49c4-4b26-b700-18b835a06e67" CreationDate="2016-09-17T16:45:53.467" UserDisplayName="user464" Comment="added 380 characters in body" Text="The following is the 2d complex sinusoidal function,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;$u_0$ and $v_0$ represent Fundamental Frequencies in $X$ and $Y$ directions respectively.&#xD;&#xA;&#xD;&#xA;I need to implement that sinusoidal function in this present form so that, I can plot it and save it in a Bitmap image file. &#xD;&#xA;&#xD;&#xA;How can I represent $j$ (imaginary number)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit:** &#xD;&#xA;&#xD;&#xA;here is my use-case:  ...  ...  I need to implement Gabor Filter using both spatial and frequency domain equations. In the link ...  http://www.cs.utah.edu/~arul/report/node13.html  ..., you can see that there are several equations. (14) is the equation of Gabor Filter in spatial domain. (15) is the equation of Gabor Filter in frequency domain. Hence, my question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SPyuQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8688" PostHistoryTypeId="2" PostId="4020" RevisionGUID="f2f1f2c8-1428-4b03-be11-01eb2b8aade1" CreationDate="2016-09-17T17:14:01.057" UserId="48" Text="One way to represent a complex-valued function in a bitmap is to use one color channel for the real component and one for the imaginary component. For example, rendering a complex plane wave (your equation) with R = real, G = imaginary looks like this (click for shadertoy):&#xD;&#xA;&#xD;&#xA;[![complex plane wave][1]](https://www.shadertoy.com/view/MtG3Dz)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/F5gb7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8689" PostHistoryTypeId="5" PostId="4019" RevisionGUID="99b8cfa7-9e88-4925-bddc-16b5d104fbde" CreationDate="2016-09-17T17:25:52.043" UserDisplayName="user464" Comment="deleted 129 characters in body" Text="The following is the 2d complex sinusoidal function,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;$u_0$ and $v_0$ represent Fundamental Frequencies in $X$ and $Y$ directions respectively.&#xD;&#xA;&#xD;&#xA;How can I represent $j$ (imaginary number)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit:** &#xD;&#xA;&#xD;&#xA;here is my use-case:  ...  ...  I need to implement Gabor Filter using both spatial and frequency domain equations. In the link ...  http://www.cs.utah.edu/~arul/report/node13.html  ..., you can see that there are several equations. (14) is the equation of Gabor Filter in spatial domain. (15) is the equation of Gabor Filter in frequency domain. Hence, my question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SPyuQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8690" PostHistoryTypeId="5" PostId="4004" RevisionGUID="6a599481-262b-496b-a4bd-172685158df3" CreationDate="2016-09-17T19:28:46.980" UserId="5117" Comment="deleted 3357 characters in body" Text="I have object loader, which i want to have background. I tried to put jpg image like texture to my application. I tried to make that with FreeImage library, but the image didn't show. Also i tried with Gdiplus, i opened the image but when i opened and the object the background disappeared.&#xD;&#xA;I send link with the code (with FreeImage library), If someone have any ideas i will be so happy, because I haven't yet.&#xD;&#xA;&#xD;&#xA;https://github.com/Nushiii/viewer/blob/master/ViewerPicture%20FreeImege/ViewerPicture/main.cpp&#xD;&#xA;&#xD;&#xA; **EDIT:**&#xD;&#xA;&#xD;&#xA;           int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;        MSG msg = {0};&#xD;&#xA;        WNDCLASSEX wcl = {0};&#xD;&#xA;    &#xD;&#xA;    	GLuint texture;&#xD;&#xA;    	float theta = 0.0f;&#xD;&#xA;    &#xD;&#xA;        wcl.cbSize = sizeof(wcl);&#xD;&#xA;        wcl.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;&#xD;&#xA;        wcl.lpfnWndProc = WindowProc;&#xD;&#xA;        wcl.cbClsExtra = 0;&#xD;&#xA;        wcl.cbWndExtra = 0;&#xD;&#xA;        wcl.hInstance = g_hInstance = hInstance;&#xD;&#xA;        wcl.hIcon = static_cast&lt;HICON&gt;(LoadImage(hInstance,&#xD;&#xA;        MAKEINTRESOURCE (IDI_ICON1),&#xD;&#xA;        IMAGE_ICON,&#xD;&#xA;        48, 48,    // or whatever size icon you want to load&#xD;&#xA;        LR_DEFAULTCOLOR));&#xD;&#xA;        wcl.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;        wcl.hbrBackground = 0;&#xD;&#xA;        wcl.lpszMenuName = MAKEINTRESOURCE(MENU_FIXED_FUNC);&#xD;&#xA;        wcl.lpszClassName = &quot;GLWindowClass&quot;;&#xD;&#xA;        wcl.hIconSm = 0;&#xD;&#xA;    &#xD;&#xA;        if (!RegisterClassEx(&amp;wcl))&#xD;&#xA;            return 0;&#xD;&#xA;    &#xD;&#xA;        g_hWnd = CreateAppWindow(wcl, APP_TITLE);&#xD;&#xA;    &#xD;&#xA;        	  // load our texture&#xD;&#xA;          FIBITMAP  *dib1 = loadImage(&quot;angel.jpg&quot;);&#xD;&#xA;          texture = LoadTexturee( dib1, TRUE );&#xD;&#xA;    &#xD;&#xA;        if (g_hWnd)&#xD;&#xA;        {&#xD;&#xA;            SetProcessorAffinity();&#xD;&#xA;    &#xD;&#xA;            if (Init())&#xD;&#xA;            {&#xD;&#xA;                ShowWindow(g_hWnd, nShowCmd);&#xD;&#xA;                UpdateWindow(g_hWnd);&#xD;&#xA;    &#xD;&#xA;                while (true)&#xD;&#xA;                {&#xD;&#xA;                    if (PeekMessage(&amp;msg, 0, 0, 0, PM_REMOVE))&#xD;&#xA;                    {&#xD;&#xA;                        if (msg.message == WM_QUIT)&#xD;&#xA;                            break;&#xD;&#xA;    &#xD;&#xA;                        TranslateMessage(&amp;msg);&#xD;&#xA;                        DispatchMessage(&amp;msg);&#xD;&#xA;                    } else {&#xD;&#xA;&#xD;&#xA;**EDIT**           	  &#xD;&#xA;&#xD;&#xA;                      UpdateFrame(GetElapsedTimeInSeconds());&#xD;&#xA;		              DrawFrame(texture, g_hDC);&#xD;&#xA;                      SwapBuffers(g_hDC);&#xD;&#xA;&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;                    if (msg.message == WM_QUIT)&#xD;&#xA;                        break;&#xD;&#xA;    &#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            Cleanup();&#xD;&#xA;            UnregisterClass(wcl.lpszClassName, hInstance);&#xD;&#xA;        }&#xD;&#xA;    	FreeTexture( texture );&#xD;&#xA;        return static_cast&lt;int&gt;(msg.wParam);&#xD;&#xA;    }&#xD;&#xA;**EDIT:** **Now i load the picture, but the object doesn'n load.**&#xD;&#xA;&#xD;&#xA;    VOID DrawFrame(GLuint texture,HDC hDC)&#xD;&#xA;    { &#xD;&#xA;    	&#xD;&#xA;	glMatrixMode(GL_PROJECTION);&#xD;&#xA;	glPushMatrix();&#xD;&#xA;	glLoadIdentity();&#xD;&#xA;&#xD;&#xA;	glMatrixMode(GL_MODELVIEW);&#xD;&#xA;	glPushMatrix();&#xD;&#xA;	glLoadIdentity();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      // setup texture mapping&#xD;&#xA;     glEnable( GL_TEXTURE_2D );&#xD;&#xA;     glBindTexture( GL_TEXTURE_2D, texture );&#xD;&#xA;&#xD;&#xA;     glPushMatrix();&#xD;&#xA;     glBegin( GL_QUADS );&#xD;&#xA;     glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);&#xD;&#xA;     glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);&#xD;&#xA;     glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);&#xD;&#xA;     glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);&#xD;&#xA;     glEnd();&#xD;&#xA;     glPopMatrix();&#xD;&#xA;&#xD;&#xA;	glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;	glMatrixMode(GL_PROJECTION);&#xD;&#xA;	glPopMatrix(); // Pops our orthographic projection matrix&#xD;&#xA;	glMatrixMode(GL_MODELVIEW);&#xD;&#xA;	glMatrixMode(GL_PROJECTION); &#xD;&#xA;	glLoadIdentity();&#xD;&#xA;    gluPerspective(CAMERA_FOVY,&#xD;&#xA;       static_cast&lt;float&gt;(g_windowWidth) / static_cast&lt;float&gt; (g_windowHeight),&#xD;&#xA;       CAMERA_ZNEAR, CAMERA_ZFAR);&#xD;&#xA;	    glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;    gluLookAt(g_cameraPos[0], g_cameraPos[1], g_cameraPos[2],&#xD;&#xA;      g_targetPos[0], g_targetPos[1], g_targetPos[2],&#xD;&#xA;      0.0f, 1.0f, 0.0f);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8691" PostHistoryTypeId="5" PostId="4016" RevisionGUID="cfa10bb7-49b7-4bff-906e-7dfbc50ff283" CreationDate="2016-09-17T21:45:10.847" UserId="5136" Comment="added 163 characters in body" Text="I have recently been working on area lights for a small open source game engine called Urho3D but have run into an issues when rendering tube lights where the lights look the same as sphere lights despite the length value being changed.&#xD;&#xA;&#xD;&#xA;I am working from [Epic's paper on PBR][1] by Brian Karis. I have tried looking at other sources to see if I could find anything but none of the results fixed the issue I was having.&#xD;&#xA;&#xD;&#xA;The method I am using for tube lighting is as follows:&#xD;&#xA;&#xD;&#xA;    float3 TubeLight(float3 worldPos, float3 lightVec, float3 normal, float3 toCamera, float roughness, float3 specColor, out float ndl)&#xD;&#xA;    {&#xD;&#xA;        float3 pos   = (cLightPosPS.xyz - worldPos);&#xD;&#xA;        float3 reflectVec  = reflect(-toCamera, normal);&#xD;&#xA;        &#xD;&#xA;        float3 L01 = lightVec * LightLengh;&#xD;&#xA;        float3 L0 = pos - 0.5 * L01;&#xD;&#xA;        float3 L1 = pos + 0.5 * L01;&#xD;&#xA;        float3 ld = L1 - L0;&#xD;&#xA;&#xD;&#xA;        float distL0    = length( L0 );&#xD;&#xA;        float distL1    = length( L1 );&#xD;&#xA;&#xD;&#xA;        float NoL0      = dot( L0, normal ) / ( 2.0 * distL0 );&#xD;&#xA;        float NoL1      = dot( L1, normal ) / ( 2.0 * distL1 );&#xD;&#xA;        ndl             = ( 2.0 * clamp( NoL0 + NoL1, 0.0, 1.0 ) ) &#xD;&#xA;                        / ( distL0 * distL1 + dot( L0, L1 ) + 2.0 );&#xD;&#xA;    &#xD;&#xA;        float RoL0      = dot( reflectVec, L0 );&#xD;&#xA;        float RoLd      = dot( reflectVec, ld );&#xD;&#xA;        float L0oLd     = dot( L0, ld );&#xD;&#xA;        float distLd    = length( ld );&#xD;&#xA;        float t         = ( RoL0 * RoLd - L0oLd ) &#xD;&#xA;                    / ( distLd * distLd - RoLd * RoLd );&#xD;&#xA;        &#xD;&#xA;        float3 closestPoint   = L0 + ld * saturate( t);&#xD;&#xA;        float3 centreToRay    = dot( closestPoint, reflectVec ) * reflectVec - closestPoint;&#xD;&#xA;        closestPoint = closestPoint + centreToRay * saturate(LightRad / length(centreToRay));&#xD;&#xA;&#xD;&#xA;        float3 l = normalize(closestPoint);&#xD;&#xA;        float3 h = normalize(toCamera + l);&#xD;&#xA;&#xD;&#xA;        ndl       = saturate(dot(normal, l));&#xD;&#xA;        float hdn = saturate(dot(h, normal));&#xD;&#xA;        float hdv = dot(h, toCamera);&#xD;&#xA;        float ndv = saturate(dot(normal, toCamera));&#xD;&#xA;&#xD;&#xA;        float distL      = length(closestPoint);&#xD;&#xA;        float alpha      = roughness * roughness;&#xD;&#xA;        float alphaPrime = saturate(LightRad / (distL * 2.0) + alpha);&#xD;&#xA;&#xD;&#xA;        const float3 fresnelTerm = Fresnel(specColor, hdv) ;&#xD;&#xA;        const float distTerm     = Distribution(hdn, alphaPrime);&#xD;&#xA;        const float visTerm      = Visibility(ndl, ndv, roughness);&#xD;&#xA;&#xD;&#xA;        return distTerm * visTerm * fresnelTerm ;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If the code snippet is not enough to help solve this issue you can download the [full area lighting branch][2] from GitHub. Build instructions can be found on the Urho3D website (cant link due to reputation), note currently area lighting is only tested in DX11. Shader source files can be found under &#xD;&#xA;&#xD;&#xA;    [build location]/bin/CoreData/Shaders/HLSL&#xD;&#xA;&#xD;&#xA;[![tube light image][tube image]][tube image]&#xD;&#xA;&#xD;&#xA;You can see that both images look identical [here](https://i.stack.imgur.com/uAZTJ.jpg).&#xD;&#xA;&#xD;&#xA;If pos in multiplied into line 40 then it creates more of a tube effect but is still far from correct results, [As you can see here](https://i.stack.imgur.com/BlYLP.jpg).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: https://github.com/dragonCASTjosh/Urho3D&#xD;&#xA;&#xD;&#xA;  [tube image]: https://i.stack.imgur.com/BinG1.jpg&#xD;&#xA;  &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8692" PostHistoryTypeId="2" PostId="4021" RevisionGUID="a25ed8f7-6f68-4fa5-a671-f63052d5692d" CreationDate="2016-09-18T10:26:35.697" UserId="2069" Text="We are trying to optimize Lighting in fillrate. Integrated graphics chips are very slow in memory access.&#xD;&#xA;&#xD;&#xA;There are two Light Buffers: one for Diffuse and one for Specular. Both use format R11G11B10F. Is there any way to pack two buffers into one? For instance, using color model Y'CbCr:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kUIZU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8693" PostHistoryTypeId="1" PostId="4021" RevisionGUID="a25ed8f7-6f68-4fa5-a671-f63052d5692d" CreationDate="2016-09-18T10:26:35.697" UserId="2069" Text="Encode two R11G11B10F buffers into one using Y'CbCr?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8694" PostHistoryTypeId="3" PostId="4021" RevisionGUID="a25ed8f7-6f68-4fa5-a671-f63052d5692d" CreationDate="2016-09-18T10:26:35.697" UserId="2069" Text="|shader|color|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8695" PostHistoryTypeId="50" PostId="3862" RevisionGUID="6170dce7-d442-48a1-8198-9a32b09e4b79" CreationDate="2016-09-18T14:11:50.170" UserId="-1" />
  <row Id="8696" PostHistoryTypeId="2" PostId="4022" RevisionGUID="eeb22c2f-1a6b-4ea1-9355-d9a952284277" CreationDate="2016-09-18T18:55:50.977" UserId="48" Text="You might want to look at [The Compact YCoCg Framebuffer](http://www.pmavridis.com/research/fbcompression/). It uses a 2-channel buffer to store luminance for every pixel and the two chroma components in half the pixels each, forming a checkerboard. It also uses an edge-aware upsampling filter at the end of the frame to reconstruct the missing chroma components and convert back to RGB.&#xD;&#xA;&#xD;&#xA;You could extend this to a single 3-channel buffer to store the diffuse luminance, specular luminance, and checkerboarded chroma (assuming based on the diagram in your question that it suffices to store just one pair of chroma values).&#xD;&#xA;&#xD;&#xA;You might also consider using R10G10B10A2 format instead, unless you _really_ need the range of the floating-point format. It's the same amount of bandwidth but will give you a good deal more precision (R11G11B10F only gives you 5–6 bits of mantissa per component). Plus, you can use the 2 bits of alpha to store a couple of flags, such as your diffuse/specular flag." ContentLicense="CC BY-SA 3.0" />
  <row Id="8697" PostHistoryTypeId="2" PostId="4023" RevisionGUID="977b2369-a3cd-4be7-b1ff-0246c82d336e" CreationDate="2016-09-18T20:42:55.240" UserId="5148" Text="Suppose I have to use bilinear interpolation to rescale image. I more or less understand how enlargement works in case of integer scale factor. &#xA;&#xA;But what to do with non-integer scale and especially when you need to downsample an image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8698" PostHistoryTypeId="1" PostId="4023" RevisionGUID="977b2369-a3cd-4be7-b1ff-0246c82d336e" CreationDate="2016-09-18T20:42:55.240" UserId="5148" Text="Image rescaling algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="8699" PostHistoryTypeId="3" PostId="4023" RevisionGUID="977b2369-a3cd-4be7-b1ff-0246c82d336e" CreationDate="2016-09-18T20:42:55.240" UserId="5148" Text="|algorithm|image-processing|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8700" PostHistoryTypeId="5" PostId="3840" RevisionGUID="7eacd421-4fc8-40c9-8839-a86734c2ca90" CreationDate="2016-09-19T01:53:01.020" UserId="4886" Comment="Clarified that initial beliefs were incorrect." Text="I'm attempting to perform an intersection test using ray casting (not sure if correct term so please forgive me if not) and am outputting the intersections as a point cloud, and the point cloud shows curvature (on the Z-axis only, the point cloud is completely flat on the Y axis, and the horizontal axis in this image is the X axis):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I borrowed concepts from the Scratchapixel site, specifically http://scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection.&#xD;&#xA;&#xD;&#xA;Essentially, I am generating 16 rays, all with the same origin vector.  The direction vectors start at +15 degrees on the YZ plane, and continue in increments of -2 degrees down to -15.  I have an axis aligned bounding box that I am testing intersection with.  I use a rotation transform to rotate the 16 rays CCW around the Z axis.  I am performing the intersection test for all 16 rays each 0.1 degrees, and if it returns true, I add the point to the point cloud.&#xD;&#xA;&#xD;&#xA;Here's my intersection code:&#xD;&#xA;&#xD;&#xA;    bool test_intersect(Box b, Ray r, Vec3f&amp; intersect_point)&#xD;&#xA;    {&#xD;&#xA;    	float txmin = 0.0f, txmax = 0.0f, tymin = 0.0f, tymax = 0.0f, tzmin = 0.0f, tzmax = 0.0f;&#xD;&#xA;    	float t_min = 0.0f, t_max = 0.0f, t = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	// Determine inverse direction of ray to alleviate 0 = -0 issues&#xD;&#xA;    	Vec3f inverse_direction(1 / r.direction.x, 1 / r.direction.y, 1 / r.direction.z);&#xD;&#xA;    &#xD;&#xA;    	// Solving box_min/box_max0 = O + Dt &#xD;&#xA;    	txmin = (b.box_min.x - r.origin.x) * inverse_direction.x;&#xD;&#xA;    	txmax = (b.box_max.x - r.origin.x) * inverse_direction.x;&#xD;&#xA;    	tymin = (b.box_min.y - r.origin.y) * inverse_direction.y;&#xD;&#xA;    	tymax = (b.box_max.y - r.origin.y) * inverse_direction.y;&#xD;&#xA;    	tzmin = (b.box_min.z - r.origin.z) * inverse_direction.z;&#xD;&#xA;    	tzmax = (b.box_max.z - r.origin.z) * inverse_direction.z;&#xD;&#xA;    	&#xD;&#xA;    	// Depending on direction of ray tmin may &gt; tmax, so we may need to swap&#xD;&#xA;    	if (txmin &gt; txmax) std::swap(txmin, txmax);&#xD;&#xA;    	if (tymin &gt; tymax) std::swap(tymin, tymax);&#xD;&#xA;    	if (tzmin &gt; tzmax) std::swap(tzmin, tzmax);&#xD;&#xA;    &#xD;&#xA;    	t_min = txmin;&#xD;&#xA;    	t_max = txmax;&#xD;&#xA;    &#xD;&#xA;    	// If t-value of a min is greater than t-value of max,&#xD;&#xA;    	// we missed the object in that plane.&#xD;&#xA;    	if ((t_min &gt; tymax) || (tymin &gt; t_max))&#xD;&#xA;    		return false;&#xD;&#xA;    &#xD;&#xA;    	if (tymin &gt; t_min)&#xD;&#xA;    		t_min = tymin;&#xD;&#xA;    	if (tymax &lt; t_max)&#xD;&#xA;    		t_max = tymax;&#xD;&#xA;    &#xD;&#xA;    	if ((t_min &gt; tzmax) || (tzmin &gt; t_max))&#xD;&#xA;    		return false;&#xD;&#xA;    		&#xD;&#xA;    	if (tzmin &gt; t_min)&#xD;&#xA;    		t_min = tzmin;&#xD;&#xA;    	if (tzmax &lt; t_max)&#xD;&#xA;    		t_max = tzmax;&#xD;&#xA;    &#xD;&#xA;    	if (t_min &gt; 0)&#xD;&#xA;    		t = t_min;&#xD;&#xA;    	else&#xD;&#xA;    		if (t_max &gt; 0)&#xD;&#xA;    			t = t_max;&#xD;&#xA;    		else&#xD;&#xA;    			return false;&#xD;&#xA;    &#xD;&#xA;    	intersect_point.x = r.origin.x + r.direction.x * t;&#xD;&#xA;    	intersect_point.y = r.origin.y + r.direction.y * t;&#xD;&#xA;    	intersect_point.z = r.origin.z + r.direction.z * t;&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And my rotation:&#xD;&#xA;&#xD;&#xA;    // Rotation around z axis, for rotating array and checking beam intersections&#xD;&#xA;    void transform_rotate_z(Vec3f&amp; in_vector, float angle)&#xD;&#xA;    {&#xD;&#xA;    	float radians = angle * (M_PI / 180);&#xD;&#xA;    	&#xD;&#xA;    	float result_x = cos(radians) * in_vector.x + -sin(radians) * in_vector.y;&#xD;&#xA;    	float result_y = sin(radians) * in_vector.x + cos(radians) * in_vector.y;&#xD;&#xA;    	in_vector.x = result_x;&#xD;&#xA;    	in_vector.y = result_y;&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have racked my brain for quite a while but I can't seem to determine how I can prevent this curvature, I'm sure I'm overlooking something simple.  I'd be grateful for any help you can provide.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wd9OX.png&#xD;&#xA;&#xD;&#xA;EDIT 9/18/16:  It turned out that I had incorrectly believed that physical LIDAR units had some algorithmic way of &quot;straightening&quot; out the curves, which is not the case!  The output is supposed to look like the picture above." ContentLicense="CC BY-SA 3.0" />
  <row Id="8701" PostHistoryTypeId="2" PostId="4024" RevisionGUID="af502445-22f0-419d-9cc0-8aae5f4a6eec" CreationDate="2016-09-19T02:53:45.657" UserId="2707" Text="With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xD;&#xA;&#xD;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels). The red dot (0, 0) in the top left is closer to the black dot in the top left (0, 0) than the four other surrounding dots, so the downsampled pixel will have a heavier weight for determining the color of the downsampled pixel.&#xD;&#xA;&#xD;&#xA;[![Different scale factors overlapped][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c5apF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8702" PostHistoryTypeId="5" PostId="4024" RevisionGUID="5c6d5aa5-90ab-4ab9-b9bb-e0d23394aeda" CreationDate="2016-09-19T03:13:29.150" UserId="2707" Comment="Added a more comprehensive description and example. Formatted everything." Text="#Theory&#xD;&#xA;&#xD;&#xA;With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xD;&#xA;&#xD;&#xA;#Example&#xD;&#xA;&#xD;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels). The red dot (0, 0) in the top left is closer to the black dot in the top left (0, 0) than the four other surrounding dots, so the downsampled pixel will have a heavier weight for determining the color of the downsampled pixel.&#xD;&#xA;&#xD;&#xA;[![Different scale factors overlapped][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c5apF.png&#xD;&#xA;&#xD;&#xA;#With numbers:&#xD;&#xA;&#xD;&#xA;Horizontal distance from:&#xD;&#xA;-Right 2 original (green) pixels = 0.1 pixels&#xD;&#xA;-Left 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Vertical distance from:&#xD;&#xA;-Top 2 original (green) pixels = 0.1 pixels&#xD;&#xA;-Bottom 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Weight for final pixel:&#xD;&#xA;$$weight(0, 0) = \frac{(1.0 - 0.1) + (1.0 - 0.1)}{4} = \frac{1.8}{4} = 0.45$$&#xD;&#xA;$$weight(0, 1) = \frac{(1.0 - 0.1) + (1.0 - 0.9)}{4} = \frac{0.9}{4} = 0.225$$&#xD;&#xA;$$weight(1, 0) = \frac{(1.0 - 0.9) + (1.0 - 0.1)}{4} = \frac{0.9}{4} = 0.225$$&#xD;&#xA;$$weight(1, 1) = \frac{(1.0 - 0.9) + (1.0 - 0.9)}{4} = \frac{0.2}{4} = 0.1$$&#xD;&#xA;&#xD;&#xA;Subtract from 1 both the horizontal and vertical distance (because closer pixels should carry more weight). You can divide by 4 to normalize the each weight (since there are 4 pixels you are sampling from). The scale factor in this example is 0.75." ContentLicense="CC BY-SA 3.0" />
  <row Id="8703" PostHistoryTypeId="5" PostId="4024" RevisionGUID="eb77f0e7-0a54-45c3-8f77-1c3c4c6b7d53" CreationDate="2016-09-19T06:04:18.397" UserId="2707" Comment="Corrected error with equations" Text="#Explanation&#xD;&#xA;&#xD;&#xA;With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xD;&#xA;&#xD;&#xA;#Example&#xD;&#xA;&#xD;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels). The red dot (0, 0) in the top left is closer to the black dot in the top left (0, 0) than the four other surrounding dots, so the downsampled pixel will have a heavier weight for determining the color of the downsampled pixel.&#xD;&#xA;&#xD;&#xA;[![Different scale factors overlapped][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c5apF.png&#xD;&#xA;&#xD;&#xA;#With numbers:&#xD;&#xA;&#xD;&#xA;Horizontal distance from:&#xD;&#xA;&#xD;&#xA; - Right 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Left 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Vertical distance from:&#xD;&#xA;&#xD;&#xA; - Top 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Bottom 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Weight for final pixel:&#xD;&#xA;$$weight(0, 0) = \frac{(1.0 - 0.1)(1.0 - 0.1)}{4} = \frac{1.8}{4} = 0.81$$&#xD;&#xA;$$weight(0, 1) = \frac{(1.0 - 0.1)(1.0 - 0.9)}{4} = \frac{0.9}{4} = 0.09$$&#xD;&#xA;$$weight(1, 0) = \frac{(1.0 - 0.9)(1.0 - 0.1)}{4} = \frac{0.9}{4} = 0.09$$&#xD;&#xA;$$weight(1, 1) = \frac{(1.0 - 0.9)(1.0 - 0.9)}{4} = \frac{0.2}{4} = 0.01$$&#xD;&#xA;&#xD;&#xA;Subtract from 1 both the horizontal and vertical distance (because closer pixels should carry more weight). You can divide by 4 to normalize the each weight (since there are 4 pixels you are sampling from). The scale factor in this example is 0.75." ContentLicense="CC BY-SA 3.0" />
  <row Id="8704" PostHistoryTypeId="5" PostId="4024" RevisionGUID="e3721fe4-4f14-48bf-849b-f39b56cac371" CreationDate="2016-09-19T06:19:37.157" UserId="2707" Comment="deleted 203 characters in body" Text="#Explanation&#xD;&#xA;&#xD;&#xA;With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xD;&#xA;&#xD;&#xA;#Example&#xD;&#xA;&#xD;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels). The red dot (0, 0) in the top left is closer to the black dot in the top left (0, 0) than the four other surrounding dots, so the downsampled pixel will have a heavier weight for determining the color of the downsampled pixel.&#xD;&#xA;&#xD;&#xA;[![Different scale factors overlapped][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c5apF.png&#xD;&#xA;&#xD;&#xA;#With numbers:&#xD;&#xA;&#xD;&#xA;Horizontal distance from:&#xD;&#xA;&#xD;&#xA; - Right 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Left 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Vertical distance from:&#xD;&#xA;&#xD;&#xA; - Top 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Bottom 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Weight for final pixel:&#xD;&#xA;$$weight(0, 0) = (1.0 - 0.1)(1.0 - 0.1) = 0.81$$&#xD;&#xA;$$weight(0, 1) = (1.0 - 0.1)(1.0 - 0.9) = 0.09$$&#xD;&#xA;$$weight(1, 0) = (1.0 - 0.9)(1.0 - 0.1) = 0.09$$&#xD;&#xA;$$weight(1, 1) = (1.0 - 0.9)(1.0 - 0.9) = 0.01$$&#xD;&#xA;&#xD;&#xA;Subtract from 1 both the horizontal and vertical distance (because closer pixels should carry more weight). The scale factor in this example is 0.75." ContentLicense="CC BY-SA 3.0" />
  <row Id="8705" PostHistoryTypeId="2" PostId="4025" RevisionGUID="54d0370f-ff2f-4999-ae74-21a5089d5b89" CreationDate="2016-09-19T10:19:05.920" UserId="5136" Text="Found the solution, it turns out the lightVec is not the vector of light from the tube but rather the direction the tube will point. Therefore i will need to pass it a light rotation value to be used there.&#xD;&#xA;&#xD;&#xA;Results:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tpgrW.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8706" PostHistoryTypeId="2" PostId="4026" RevisionGUID="465e5eb2-914a-4f1e-b2ce-75f5192651cb" CreationDate="2016-09-19T11:19:36.437" UserId="4958" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;//transform from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8707" PostHistoryTypeId="1" PostId="4026" RevisionGUID="465e5eb2-914a-4f1e-b2ce-75f5192651cb" CreationDate="2016-09-19T11:19:36.437" UserId="4958" Text="Transforming fragment-to-camera to tangent space for parallax occlusion mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="8708" PostHistoryTypeId="3" PostId="4026" RevisionGUID="465e5eb2-914a-4f1e-b2ce-75f5192651cb" CreationDate="2016-09-19T11:19:36.437" UserId="4958" Text="|shader|texture|transformations|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8709" PostHistoryTypeId="5" PostId="4026" RevisionGUID="7c931984-0d3f-458c-a130-32ae6dd376f9" CreationDate="2016-09-19T11:33:38.470" UserId="4958" Comment="added 57 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8710" PostHistoryTypeId="5" PostId="4026" RevisionGUID="d59a48a9-a5a8-468f-ba21-a34e1406e972" CreationDate="2016-09-19T12:21:17.833" UserId="4958" Comment="added 8 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8711" PostHistoryTypeId="5" PostId="1551" RevisionGUID="637187b6-6568-4727-b914-52ddd90e38a6" CreationDate="2016-09-19T12:46:31.650" UserId="209" Comment="Minor improvements to descriptions" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  A problem with palette textures are that the compression rates for the achieved quality are generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2BPP ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4BPP, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This paper also included a compression algorithm but, for our purposes, we are mainly interested in the resulting compressed data and of the decompression process.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, what is in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4BPP RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4BPP. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts can often go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4BPP RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 BPP RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4BPP produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2BPP variant has, naturally, higher error than the 4BPP (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4BPP ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of BPP. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="8712" PostHistoryTypeId="5" PostId="4024" RevisionGUID="533d39a4-9676-4821-8d44-3650c27b695f" CreationDate="2016-09-20T01:09:04.533" UserId="2707" Comment="Added better diagrams, addressed concern raised from one of the comments, fixed mistakes in writing" Text="#Explanation&#xD;&#xA;&#xD;&#xA;With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xD;&#xA;&#xD;&#xA;#Example&#xD;&#xA;&#xD;&#xA;##Normalization&#xD;&#xA;&#xD;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels).&#xD;&#xA;&#xD;&#xA;You can align the two images by treating each pixel coordinate as a set of two values (x and y) between 0 and 1 (inclusive). Pixels should not be treated as square, so you should treat each pixel as a point rather than a square (when aligning the two images).&#xD;&#xA;&#xD;&#xA;[![Larger and downsampled image][1]][1]&#xD;&#xA;&#xD;&#xA;In the above image, the four corners would all carry the weight of the original image's four corners, for example. The points in the middle would carry different weights depending on the difference between the four neighboring points.&#xD;&#xA;&#xD;&#xA;##With numbers:&#xD;&#xA;&#xD;&#xA;This is a hypothetical area to sample in larger images (not related to the image above). The distances are between original pixels are normalized from 0 to 1 to simplify the math. &#xD;&#xA;&#xD;&#xA;The black dots represent the sample points (pixels) of the original image. The larger red dots represent the sample points of the downsampled image. The red dot in the top left is closer to the black dot in the top left than the other three surrounding dots, so that pixel will have a heavier weight for determining the color of the downsampled pixel.&#xD;&#xA;&#xD;&#xA;[![Closeup of sampling region][2]][2]&#xD;&#xA;&#xD;&#xA;Horizontal distance from:&#xD;&#xA;&#xD;&#xA; - Right 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Left 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Vertical distance from:&#xD;&#xA;&#xD;&#xA; - Top 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Bottom 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Weight for final pixel:&#xD;&#xA;$$weight(0, 0) = (1.0 - 0.1)(1.0 - 0.1) = 0.81$$&#xD;&#xA;$$weight(0, 1) = (1.0 - 0.1)(1.0 - 0.9) = 0.09$$&#xD;&#xA;$$weight(1, 0) = (1.0 - 0.9)(1.0 - 0.1) = 0.09$$&#xD;&#xA;$$weight(1, 1) = (1.0 - 0.9)(1.0 - 0.9) = 0.01$$&#xD;&#xA;&#xD;&#xA;Subtract from 1 both the horizontal and vertical distance (because closer pixels should carry more weight). The scale factor in this example is 0.75 in each direction.&#xD;&#xA;&#xD;&#xA;#Scaling Up vs. Scaling Down&#xD;&#xA;&#xD;&#xA;Scaling up in the same  process as scaling down. By normalizing both the original image and the new image to between (0, 0) and (1, 1), you can do either with the same process. As an exercise, in the first figure, if the red points were from the original image and the black points were from the enlarged image, you should be able to see that the process is the same.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IyFNP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/B2wip.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8713" PostHistoryTypeId="5" PostId="4024" RevisionGUID="fcb402b7-043a-4f7a-8e84-4948ab269d79" CreationDate="2016-09-20T05:30:08.800" UserId="2707" Comment="Fixed the first picture" Text="#Explanation&#xD;&#xA;&#xD;&#xA;With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xD;&#xA;&#xD;&#xA;#Example&#xD;&#xA;&#xD;&#xA;##Normalization&#xD;&#xA;&#xD;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels).&#xD;&#xA;&#xD;&#xA;You can align the two images by treating each pixel coordinate as a set of two values (x and y) between 0 and 1 (inclusive). Pixels should not be treated as square, so you should treat each pixel as a point rather than a square (when aligning the two images).&#xD;&#xA;&#xD;&#xA;[![Larger and downsampled image][1]][1]&#xD;&#xA;&#xD;&#xA;In the above image, the four corners would all carry the weight of the original image's four corners, for example. The points in the middle would carry different weights depending on the difference between the four neighboring points.&#xD;&#xA;&#xD;&#xA;##With numbers:&#xD;&#xA;&#xD;&#xA;This is a hypothetical area to sample in larger images (not related to the image above). The distances are between original pixels are normalized from 0 to 1 to simplify the math. &#xD;&#xA;&#xD;&#xA;The black dots represent the sample points (pixels) of the original image. The larger red dots represent the sample points of the downsampled image. The red dot in the top left is closer to the black dot in the top left than the other three surrounding dots, so that pixel will have a heavier weight for determining the color of the downsampled pixel.&#xD;&#xA;&#xD;&#xA;[![Closeup of sampling region][2]][2]&#xD;&#xA;&#xD;&#xA;Horizontal distance from:&#xD;&#xA;&#xD;&#xA; - Right 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Left 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Vertical distance from:&#xD;&#xA;&#xD;&#xA; - Top 2 original (green) pixels = 0.1 pixels&#xD;&#xA; - Bottom 2 original (green) pixels = 0.9 pixels&#xD;&#xA;&#xD;&#xA;Weight for final pixel:&#xD;&#xA;$$weight(0, 0) = (1.0 - 0.1)(1.0 - 0.1) = 0.81$$&#xD;&#xA;$$weight(0, 1) = (1.0 - 0.1)(1.0 - 0.9) = 0.09$$&#xD;&#xA;$$weight(1, 0) = (1.0 - 0.9)(1.0 - 0.1) = 0.09$$&#xD;&#xA;$$weight(1, 1) = (1.0 - 0.9)(1.0 - 0.9) = 0.01$$&#xD;&#xA;&#xD;&#xA;Subtract from 1 both the horizontal and vertical distance (because closer pixels should carry more weight). The scale factor in this example is 0.75 in each direction.&#xD;&#xA;&#xD;&#xA;#Scaling Up vs. Scaling Down&#xD;&#xA;&#xD;&#xA;Scaling up in the same  process as scaling down. By normalizing both the original image and the new image to between (0, 0) and (1, 1), you can do either with the same process. As an exercise, in the first figure, if the red points were from the original image and the black points were from the enlarged image, you should be able to see that the process is the same.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dPoxG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/B2wip.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8714" PostHistoryTypeId="5" PostId="1551" RevisionGUID="1cd1a505-60b8-42d9-ba21-64de85b8bc90" CreationDate="2016-09-20T07:53:52.987" UserId="209" Comment="Made BPP vs bpp consistent." Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  A problem with palette textures is that the compression rates for the achieved quality is generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2bpp ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4bpp, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This paper also included a compression algorithm but, for our purposes, we are mainly interested in the resulting compressed data and of the decompression process.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4bpp RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses either RGB RGB+1bit Alpha to 4bpp. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts may go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4bpp RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 bpp RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4bpp produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2bpp variant has, naturally, higher error than the 4bpp (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4bpp ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of bpp. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="8719" PostHistoryTypeId="2" PostId="4028" RevisionGUID="7e04a352-7f39-4691-a6bb-466c51d79b19" CreationDate="2016-09-20T16:42:47.833" UserId="56" Text="If you are ok with specular being only white, you could put diffuse and specular into RGBA.&#xD;&#xA;&#xD;&#xA;It looks like that is what unity does for it's deferred rendering.&#xD;&#xA;&#xD;&#xA;Someone discovering this issue:&#xD;&#xA;http://forum.unity3d.com/threads/specular-color-based-on-light-color.134412/&#xD;&#xA;&#xD;&#xA;The docs mentioning it:&#xD;&#xA;https://docs.unity3d.com/Manual/RenderTech-DeferredLighting.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8720" PostHistoryTypeId="2" PostId="4029" RevisionGUID="bb849b64-173d-4523-8c48-3165b794a80a" CreationDate="2016-09-20T21:55:43.057" UserId="5105" Text="I know in computer graphic, we can set a world window in world coordinate system, and then mapping it to viewport which is the display window. Things that are not in the world window should not be displayed and we can do this through Clipping (like in OpenGL). I have a question that do we have alternative methods?  " ContentLicense="CC BY-SA 3.0" />
  <row Id="8721" PostHistoryTypeId="1" PostId="4029" RevisionGUID="bb849b64-173d-4523-8c48-3165b794a80a" CreationDate="2016-09-20T21:55:43.057" UserId="5105" Text="Alternatives to Clipping in avoiding display problem" ContentLicense="CC BY-SA 3.0" />
  <row Id="8722" PostHistoryTypeId="3" PostId="4029" RevisionGUID="bb849b64-173d-4523-8c48-3165b794a80a" CreationDate="2016-09-20T21:55:43.057" UserId="5105" Text="|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8723" PostHistoryTypeId="10" PostId="4029" RevisionGUID="e6fd305c-006c-4544-9786-7e674f337b7c" CreationDate="2016-09-21T09:47:18.237" UserId="231" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[2310],&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8727" PostHistoryTypeId="11" PostId="4029" RevisionGUID="6a815857-00b0-43cc-b556-3fc55ea1342b" CreationDate="2016-09-22T11:58:43.127" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8728" PostHistoryTypeId="2" PostId="4030" RevisionGUID="62c02160-df1a-4841-9aa7-d2fa8abe811c" CreationDate="2016-09-22T12:56:43.040" UserId="209" Text="*&quot;Go not to the CG Elves for counsel for they will say both no and yes&quot;.* &#xD;&#xA;&#xD;&#xA; Yes and No. As noted in another post, these issues don't exist with ray tracing but I'll assume you are interested in standard rasterisation.&#xD;&#xA;&#xD;&#xA; - It's possible to dispose of near clipping by using homogeneous rendering but that can introduce additional cost. (e.g more expensive triangle set up, more difficulty in identifying which screen regions are covered in tile-based renderers) &#xD;&#xA;&#xD;&#xA; - You could eliminate XY clipping by using float representations for the X and Y coordinates in the rasteriser *but* that can lead to catastrophic cancellation when computing triangle determinants which, AFAICS, is a necessary step. In my experience, hardware rasterisers* usually work in fixed-point so that everything is 'exact'.&#xD;&#xA;&#xD;&#xA; - As a compromise to XY clipping, guard-band clipping was introduced so that clipping only needs to be done on triangles that extend a 'long'** way off screen. Culling, however, is still be done with the standard frustum planes to eliminate those that are trivially off-screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Dreamcast being a notable exception.&#xD;&#xA;&#xD;&#xA;**for certain definitions of 'long', e.g. a small integer multiple of the screen width/height." ContentLicense="CC BY-SA 3.0" />
  <row Id="8729" PostHistoryTypeId="2" PostId="4031" RevisionGUID="09a6f9c9-2134-4fc7-b4ae-1d495dcdf35a" CreationDate="2016-09-23T12:20:26.900" UserId="5171" Text="I'm working with Kinect face api, it provides an array of vertices and indices for triangles which is to be rendered to make the face image.&#xD;&#xA;&#xD;&#xA;The no of vertices and their order in array as well as the indices given by kinect is always constant.&#xD;&#xA;&#xD;&#xA;However the api gives no information on UV data and vertex normals.&#xD;&#xA;&#xD;&#xA;The application requires me to keep the vertex order as given out by the kinect as their positions in 3d space change as per facial movement so generating uv and normals in a 3d editing software is out of question.&#xD;&#xA;&#xD;&#xA;I managed to generate UV by projecting the vertex positions onto a 2D plane  since there were very few vertices on same plane.&#xD;&#xA;&#xD;&#xA;However, I don't know how to generate vertex normals for the mesh, without vertex normal the face mesh draws with no depth of its features from prespective, although silhouette is visible as vertex positions are correct.&#xD;&#xA;&#xD;&#xA;I understand that due to absence of vertex normals the lighting wont work correctly on it and hence the pale featureless mesh it looks right now.&#xD;&#xA;&#xD;&#xA;so how do I generate vertex normals when all I have is just vertex position and the index of vertices to make triangles out of it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8730" PostHistoryTypeId="1" PostId="4031" RevisionGUID="09a6f9c9-2134-4fc7-b4ae-1d495dcdf35a" CreationDate="2016-09-23T12:20:26.900" UserId="5171" Text="Programmatically generating vertex normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="8731" PostHistoryTypeId="3" PostId="4031" RevisionGUID="09a6f9c9-2134-4fc7-b4ae-1d495dcdf35a" CreationDate="2016-09-23T12:20:26.900" UserId="5171" Text="|mesh|shading|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8732" PostHistoryTypeId="2" PostId="4032" RevisionGUID="8c15e5b3-54da-4621-9139-2b272bd92bd1" CreationDate="2016-09-23T17:59:18.003" UserId="182" Text="Computing the normal from vertex positions is quite simple using the vector cross product.&#xD;&#xA;&#xD;&#xA;#Flat shading normals&#xD;&#xA;&#xD;&#xA;If you have a triangle $ABC$, the normal is the unit vector perpendicular to the triangle's plane. Since [cross product][1] of two vectors (noted $u \times v$, or sometimes $u \wedge v$) is a vector perpendicular to them, $AB \times AC$ is a vector perpendicular to $ABC$. The direction of the vector will depend on the order of the multiplication: $u \times v$ is the opposite of $v \times u$ (the two directions perpendicular to the plane). The length will be proportional to the triangle's area, so to get a unit vector you could do:&#xD;&#xA;&#xD;&#xA; $N = \dfrac{AB \times AC}{|AB \times AC|}$.&#xD;&#xA;&#xD;&#xA;In code, this would look like `n = normalize(cross(b-a, c-a))` for example. Just apply this over all your faces and you will have your normals per face.&#xD;&#xA;&#xD;&#xA;    For each triangle ABC&#xD;&#xA;        n := normalize(cross(B-A, C-A))&#xD;&#xA;        A.n := n&#xD;&#xA;        B.n := n&#xD;&#xA;        C.n := n&#xD;&#xA;&#xD;&#xA;Note that this assumes vertices are not shared between triangles. I am not familiar with the Kinect API; it's quite possible that they are shared, in which case you would have to duplicate them, or move on to the next solution:&#xD;&#xA;&#xD;&#xA;#Smooth shading normals&#xD;&#xA;&#xD;&#xA;After lighting with normals computed as above, you will notice that triangle edges are apparent. If this in not desirable, you can compute smooth normals instead, by taking into account all the faces that share a same vertex.&#xD;&#xA;&#xD;&#xA;The idea is that if a same vertex is shared by three triangles $T1$, $T2$ and $T3$ for example, the normal $N$ will be the average of $N1$, $N2$ and $N3$. Moreover, if $T1$ is a big triangle and $T2$ is a tiny one, you probably want $N$ to be more influenced by $N1$ than by $N2$.&#xD;&#xA;&#xD;&#xA;Remember how the cross product is proportional to the area? If you add up the cross products then normalize the sum, it will do exactly the weighted sum we want. So the algorithm becomes:&#xD;&#xA;&#xD;&#xA;    For each vertex&#xD;&#xA;        vertex.n := (0, 0, 0)&#xD;&#xA;&#xD;&#xA;    For each triangle ABC&#xD;&#xA;        // compute the cross product and add it to each vertex&#xD;&#xA;        p := cross(B-A, C-A)&#xD;&#xA;        A.n += p&#xD;&#xA;        B.n += p&#xD;&#xA;        C.n += p&#xD;&#xA;&#xD;&#xA;    For each vertex&#xD;&#xA;        vertex.n := normalize(vertex.n)&#xD;&#xA;&#xD;&#xA;This technique is explained in longer detail this article by Iñigo Quilez: [clever normalization of a mesh][2].&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For more on normals, see also:&#xD;&#xA;&#xD;&#xA; * http://computergraphics.stackexchange.com/questions/1562/how-to-calculate-surface-normals-for-generated-geomtery/1576#1576&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cross_product&#xD;&#xA;  [2]: http://www.iquilezles.org/www/articles/normals/normals.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="8733" PostHistoryTypeId="5" PostId="4032" RevisionGUID="ffd8c4a5-4993-4844-a221-b79ced5416ec" CreationDate="2016-09-23T18:17:51.310" UserId="182" Comment="added 257 characters in body" Text="Computing the normal from vertex positions is quite simple using the vector cross product.&#xD;&#xA;&#xD;&#xA;The [cross product][1] of two vectors $u$ and $v$ (noted $u \times v$, or sometimes $u \wedge v$) is a vector perpendicular to $u$ and $v$, of length $||u \times v|| = ||u|| \cdot ||v|| sin(\theta)$, with $\theta$ the angle between $u$ and $v$. The direction of the vector will depend on the order of the multiplication: $u \times v$ is the opposite of $v \times u$ (the two directions perpendicular to the plane).&#xD;&#xA;&#xD;&#xA;If you are not familiar with the cross product, I invite you to read about it and get comfortable with it. Normals will then seem simple.&#xD;&#xA;&#xD;&#xA;#Flat shading normals&#xD;&#xA;&#xD;&#xA;If you have a triangle $ABC$, $AB \times AC$ is a vector perpendicular to the triangle and with a length proportional to its area. Since the normal is the unit vector perpendicular to the triangle's plane, you can get the normal with:&#xD;&#xA;&#xD;&#xA;$N = \dfrac{AB \times AC}{||AB \times AC||}$&#xD;&#xA;&#xD;&#xA;In code, this would look like `n = normalize(cross(b-a, c-a))` for example. Just apply this over all your faces and you will have your normals per face.&#xD;&#xA;&#xD;&#xA;    For each triangle ABC&#xD;&#xA;        n := normalize(cross(B-A, C-A))&#xD;&#xA;        A.n := n&#xD;&#xA;        B.n := n&#xD;&#xA;        C.n := n&#xD;&#xA;&#xD;&#xA;Note that this assumes vertices are not shared between triangles. I am not familiar with the Kinect API; it's quite possible that they are shared, in which case you would have to duplicate them, or move on to the next solution:&#xD;&#xA;&#xD;&#xA;#Smooth shading normals&#xD;&#xA;&#xD;&#xA;After lighting with normals computed as above, you will notice that triangle edges are apparent. If this in not desirable, you can compute smooth normals instead, by taking into account all the faces that share a same vertex.&#xD;&#xA;&#xD;&#xA;The idea is that if a same vertex is shared by three triangles $T1$, $T2$ and $T3$ for example, the normal $N$ will be the average of $N1$, $N2$ and $N3$. Moreover, if $T1$ is a big triangle and $T2$ is a tiny one, you probably want $N$ to be more influenced by $N1$ than by $N2$.&#xD;&#xA;&#xD;&#xA;Remember how the cross product is proportional to the area? If you add up the cross products then normalize the sum, it will do exactly the weighted sum we want. So the algorithm becomes:&#xD;&#xA;&#xD;&#xA;    For each vertex&#xD;&#xA;        vertex.n := (0, 0, 0)&#xD;&#xA;&#xD;&#xA;    For each triangle ABC&#xD;&#xA;        // compute the cross product and add it to each vertex&#xD;&#xA;        p := cross(B-A, C-A)&#xD;&#xA;        A.n += p&#xD;&#xA;        B.n += p&#xD;&#xA;        C.n += p&#xD;&#xA;&#xD;&#xA;    For each vertex&#xD;&#xA;        vertex.n := normalize(vertex.n)&#xD;&#xA;&#xD;&#xA;This technique is explained in longer detail this article by Iñigo Quilez: [clever normalization of a mesh][2].&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For more on normals, see also:&#xD;&#xA;&#xD;&#xA; * http://computergraphics.stackexchange.com/questions/1562/how-to-calculate-surface-normals-for-generated-geomtery/1576#1576&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cross_product&#xD;&#xA;  [2]: http://www.iquilezles.org/www/articles/normals/normals.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="8734" PostHistoryTypeId="2" PostId="4033" RevisionGUID="00af88dd-1a2c-4d22-8e04-356588a94b58" CreationDate="2016-09-23T23:10:56.370" UserId="5173" Text="Working on optimizing a fragment shader which is slowing down my OpenGL ES 2.0 shader based game. This is used with a shadow buffer to determine if the fragment/pixel is inside a shadow volume.&#xD;&#xA;&#xD;&#xA;The problem/slowdown is the fact I need a branch if or function to determine a 1.0 (no shadow) or 0.0 (shadowed) based on comparison of the frag's shadow Z and shadow buffer Z.&#xD;&#xA;&#xD;&#xA;        // SLOWEST&#xD;&#xA;        if ( shadowValue &gt; shadowTexZ ) return 1.0; else return 0.0;&#xD;&#xA;        &#xD;&#xA;        // ALSO SLOW&#xD;&#xA;        return clamp( 1.0 + (shadowValue - shadowTexZ) * 1000.0, 0.0, 1.0 );&#xD;&#xA;&#xD;&#xA;        // SLIGHT LESS SLOW&#xD;&#xA;        return max(sign(shadowValue - shadowTexZ), 0.0);&#xD;&#xA;&#xD;&#xA;        // ALSO SLOW&#xD;&#xA;        return sign( shadowValue - shadowTexZ ) * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;If I disable the shadow test all together, GPU time in Xcode is 12ms and solid 60fps.  With the test on it jumps to 26ms and drops the framerate unacceptably to 40fps.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="8735" PostHistoryTypeId="1" PostId="4033" RevisionGUID="00af88dd-1a2c-4d22-8e04-356588a94b58" CreationDate="2016-09-23T23:10:56.370" UserId="5173" Text="OpenGL ES Frag Shader - Branching" ContentLicense="CC BY-SA 3.0" />
  <row Id="8736" PostHistoryTypeId="3" PostId="4033" RevisionGUID="00af88dd-1a2c-4d22-8e04-356588a94b58" CreationDate="2016-09-23T23:10:56.370" UserId="5173" Text="|opengl|shader|optimisation|fragment-shader|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8737" PostHistoryTypeId="2" PostId="4034" RevisionGUID="9503aaf6-a3bf-4d88-87ac-b1d9be594f0a" CreationDate="2016-09-24T19:55:23.803" UserId="2811" Text="I think the most efficient way might be either&#xD;&#xA;&#xD;&#xA;    return float(shadowValue &gt; shadowTexZ);&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;    return step(shadowTexZ, shadowValue);" ContentLicense="CC BY-SA 3.0" />
  <row Id="8739" PostHistoryTypeId="2" PostId="4035" RevisionGUID="984aa657-02b7-495b-b55a-464458100dfe" CreationDate="2016-09-25T18:03:12.037" UserId="5181" Text="I was trying to understand how real-time illumination happens with image-based lighting. &#xD;&#xA;&#xD;&#xA;I understood that importance of representing the Environment Map and BRDF in spherical harmonics. Because both of them orthonormal basis function so that the illumination integral becomes a matter of dot product of coefficients.&#xD;&#xA;&#xD;&#xA;But before that,&#xD;&#xA;&#xD;&#xA;Why is environment map in the global frame and BRDF in  the local frame? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8740" PostHistoryTypeId="1" PostId="4035" RevisionGUID="984aa657-02b7-495b-b55a-464458100dfe" CreationDate="2016-09-25T18:03:12.037" UserId="5181" Text="Real time image based lighting for arbitrary BRDFs coordinate alignment" ContentLicense="CC BY-SA 3.0" />
  <row Id="8741" PostHistoryTypeId="3" PostId="4035" RevisionGUID="984aa657-02b7-495b-b55a-464458100dfe" CreationDate="2016-09-25T18:03:12.037" UserId="5181" Text="|real-time|brdf|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8742" PostHistoryTypeId="2" PostId="4036" RevisionGUID="5dc353d9-86f8-4f3a-bf64-e4ae47f50409" CreationDate="2016-09-25T23:23:39.913" UserId="5182" Text="I have read about spherical harmonics from [Here][1] about the usage of SH for generating Irradiance Environment Maps and how it can make the process of generating EM faster than the regular operations. what they say is : &#xD;&#xA;&#xD;&#xA;&quot;*if we want to generate a diffuse cube map with an edge length of just 32 texels, from an input cube map with an edge length of 64 texels, the cost is 32x32x6x64x64x6 around 151 million operations. real-time generation of irradiance environment maps cannot be achieved using such a brute-force algorithm. &#xD;&#xA;the runtime complexity for Spherical harmonics method in the example is just 9 x 64 x 64 x 6 around thousand operations per function*&quot;&#xD;&#xA;&#xD;&#xA;my questions are :&#xD;&#xA;&#xD;&#xA;1. how the cost of generating cube map with the edge length of 32 texels from a 64 one has been calculated as 32x32x6x64x64x6 and why not 32x32x6+64*64*6? and why for SH, the cost of generating is 9x64x64x6 ?&#xD;&#xA;&#xD;&#xA;2. brute-force algorithm finds the shortest path from one node to another. how this algorithm used for that cubemap generation ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter10.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8743" PostHistoryTypeId="1" PostId="4036" RevisionGUID="5dc353d9-86f8-4f3a-bf64-e4ae47f50409" CreationDate="2016-09-25T23:23:39.913" UserId="5182" Text="The Process of Spherical Harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="8744" PostHistoryTypeId="3" PostId="4036" RevisionGUID="5dc353d9-86f8-4f3a-bf64-e4ae47f50409" CreationDate="2016-09-25T23:23:39.913" UserId="5182" Text="|uv-mapping|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8745" PostHistoryTypeId="5" PostId="4035" RevisionGUID="6d381e57-0860-462b-910e-5f3933b2dd72" CreationDate="2016-09-26T00:15:20.853" UserId="5181" Comment="source added" Text="I was trying to understand how real-time illumination happens with image-based lighting. &#xD;&#xA;&#xD;&#xA;I understood that importance of representing the Environment Map and BRDF in spherical harmonics. Because both of them orthonormal basis function so that the illumination integral becomes a matter of dot product of coefficients.&#xD;&#xA;&#xD;&#xA;But before that,&#xD;&#xA;&#xD;&#xA;Why is environment map in the global frame and BRDF in  the local frame? &#xD;&#xA;&#xD;&#xA;Edit 1: To help more this is the paper [Fast, Arbitrary BRDF Shading][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.msr-waypoint.net/en-us/um/people/johnsny/papers/shbrdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="8746" PostHistoryTypeId="2" PostId="4037" RevisionGUID="64ba8027-3a12-424e-9b56-9fe754b42e2e" CreationDate="2016-09-26T04:28:05.190" UserId="182" Text="###1&#xD;&#xA;&#xD;&#xA;For each texel of the generated diffuse cube map (which has $6$ faces times $32 \times 32$ texels), the diffuse equation combines all texels of the environment map (which has $6$ faces times $64 \times 64$ texels). Thus $32 \times 32 \times 6 \times 64 \times 64 \times 6$ as stated.&#xD;&#xA;&#xD;&#xA;Since they compute SH with $9$ coefficients, and each coefficient needs to combine all texels of the environment map, that's $9 \times 64 \times 64 \times 6$.&#xD;&#xA;&#xD;&#xA;###2&#xD;&#xA;&#xD;&#xA;_&quot;Bruteforce&quot;_ doesn't necessarily refer to graph theory. In this article it refers to the naive approach of going through every single texel of the diffuse map and each time combine every single texel of the environment map." ContentLicense="CC BY-SA 3.0" />
  <row Id="8748" PostHistoryTypeId="50" PostId="3768" RevisionGUID="3afb8f34-b0ff-444f-9896-4c65bcaa4a43" CreationDate="2016-09-26T10:55:04.093" UserId="-1" />
  <row Id="8750" PostHistoryTypeId="5" PostId="4037" RevisionGUID="b74b6dea-95f6-424d-bb26-3e99ededb7b3" CreationDate="2016-09-26T12:58:48.857" UserId="182" Comment="Large addendum to address Joe's questions in comments." Text="##1&#xD;&#xA;&#xD;&#xA;For each texel of the generated diffuse cube map (which has $6$ faces times $32 \times 32$ texels), the diffuse equation combines all texels of the environment map (which has $6$ faces times $64 \times 64$ texels). Thus $32 \times 32 \times 6 \times 64 \times 64 \times 6$ as stated.&#xD;&#xA;&#xD;&#xA;Since the article considers SH with $9$ coefficients, and each coefficient needs to combine all texels of the environment map, that's $9 \times 64 \times 64 \times 6$.&#xD;&#xA;&#xD;&#xA;##2&#xD;&#xA;&#xD;&#xA;_&quot;Bruteforce&quot;_ doesn't necessarily refer to graph theory. In this article it refers to the naive approach of going through every single texel of the diffuse map and each time combine every single texel of the environment map.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;###Appendix&#xD;&#xA;&#xD;&#xA;Let's describe the problem at hand.&#xD;&#xA;&#xD;&#xA;**As an input**, we have an environment map: it's a set of six textures forming a cube, that represents the light coming from all directions. The light is assumed to be coming from sources far enough that, at our scale, it's as if they were infinitely far. An environment map typically looks like the left figure of this illustration from the GPU Gems article:&#xD;&#xA;&#xD;&#xA;[![Environment map and diffuse irradiance][1]][1]&#xD;&#xA;&#xD;&#xA;**As an output**, for a any point of a given object that we're rendering, we want to know the diffuse irradiance affecting it. _What does that mean?_&#xD;&#xA;&#xD;&#xA;###A parenthesis&#xD;&#xA;&#xD;&#xA;Models describing how the perceived color of a surface varies depending the light reaching it, typically consist in [integrating all incoming light over an hemisphere][2], with a weight that depends both on the direction of the light and of the observer.&#xD;&#xA;&#xD;&#xA;For opaque materials, it is common to consider two components contributing to that color: the diffuse and the specular. The diffuse is due to light slightly penetrating the surface, getting partly absorbed, then getting out in random directions. The specular is due to light bouncing off the surface without entering it.&#xD;&#xA;&#xD;&#xA;[![Diffuse and specular reflections][3]][3]&#xD;&#xA;&#xD;&#xA;###Back to the problem&#xD;&#xA;&#xD;&#xA;So we want to know the color of the points of an object, we know that to compute it we need to integrate light in all directions, and we have a cube map that represents light coming from all directions. So far so good.&#xD;&#xA;&#xD;&#xA;A problem though is _integrating_ basically means we need to go over every single texel of the hemisphere (so half the environment map: $(64 \times 64 \times 6) / 2$ texels), do some math, and add that to the result. That's a lot of computation for each point, which we'd like to avoid if possible.&#xD;&#xA;&#xD;&#xA;We know that the contribution of one light depends on the light direction. If we consider the environment to be static (the lighting doesn't change), then we can isolate the part of the computation that only depends on the light and surface normal (and not on the material or the observer), pre-compute it and store it to use later. For the diffuse term, that's the _diffuse irradiance_ mentioned earlier, and it typically looks like the center figure of the illustration. Each pixel represents the irradiance term for a given surface normal. The right figure is the specular environment map, computed in a similar way but with a different integral.&#xD;&#xA;&#xD;&#xA;[![Environment map and diffuse irradiance][1]][1]&#xD;&#xA;&#xD;&#xA;With that texture, instead of painfully integrating, we just fetch the precomputed result, combine it with the rest of the equation (the material diffuse color, etc.) and voilà.&#xD;&#xA;&#xD;&#xA;###Finding the 32x32x6x64x64x6&#xD;&#xA;&#xD;&#xA;Since the result looks very blurry, it probably doesn't need to be $64 \times 64$ for storing, and the article assumes $32 \times 32$. But still, each of those $32 \times 32 \times 6$ texels' color is computed separately, by integrating over the entire corresponding hemisphere. That part never disappeared: we just moved it from the rendering stage to a pre-computation stage.&#xD;&#xA;&#xD;&#xA;So that's still $(32 \times 32 \times 6) \times (64 \times 64 \times 6) / 2$. That's half the figure stated in the article. I suppose the author was either assuming a model that integrates of the entire sphere, or just dropped the $0.5$ factor for the sake of clarity.&#xD;&#xA;&#xD;&#xA;###Finding the 9x64x64x6&#xD;&#xA;&#xD;&#xA;We can't help but notice this irradiance diffuse environment map is really blurry: surely there must be a way to store its information using a lot less than $32 \times 32 \times 6$ terms, and hopefully reduce the amount of work as well. That's what [spherical harmonics][4] do, by compressing the irradiance in just a few coefficients.&#xD;&#xA;&#xD;&#xA;I am not familiar enough with the math to engage in an explanation, but suffice to say it is generally considered that for diffuse, order three SH are sufficient. Order three SH involve nine coefficient, and again, for each of these we need to integrate over the entire hemisphere.&#xD;&#xA;&#xD;&#xA;So that's $(9 \times 64 \times 64 \times 6) / 2$ texels to fetch and process. Here too a $2$ factor is missing from the article.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZFIHb.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [3]: https://i.stack.imgur.com/85Pmg.png&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Spherical_harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="8751" PostHistoryTypeId="2" PostId="4038" RevisionGUID="0753c913-ab81-40a9-ab5a-7d0f1108ba88" CreationDate="2016-09-26T13:53:08.227" UserId="1952" Text="The surface reflectance of a BRDF function doesn't depend on orientation or position of the surface in the world space but is defined relatively to the surface normal (or tangent space in case of anisotropic BRDF) so it should be defined in local space. Think of it as a spherical 2D function fixed to a point on the surface of an object that moves and rotates with the object.&#xD;&#xA;&#xD;&#xA;Environment map on the other hand defines luminous intensity from given direction in the world space so it is defined in that space.&#xD;&#xA;&#xD;&#xA;To perform the convolution of these two functions you then have to either transform BRDF to world space or environment map to local space.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8753" PostHistoryTypeId="5" PostId="4038" RevisionGUID="229bec53-34e6-4501-8835-345a058b95a6" CreationDate="2016-09-26T14:56:29.777" UserId="1952" Comment="deleted 9 characters in body" Text="The surface reflectance of a BRDF function doesn't depend on orientation or position of the surface in the world space but is defined relatively to the surface normal (or tangent space in case of anisotropic BRDF) so it should be defined in local space. Think of it as a spherical 2D function fixed to a point on the surface of an object that moves and rotates with the object.&#xD;&#xA;&#xD;&#xA;Environment map on the other hand defines luminance from given direction in the world space so it is defined in that space.&#xD;&#xA;&#xD;&#xA;To perform the convolution of these two functions you then have to either transform BRDF to world space or environment map to local space.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8754" PostHistoryTypeId="5" PostId="4038" RevisionGUID="0e11c36d-28bc-4f67-ae04-77443b18ea60" CreationDate="2016-09-26T15:02:37.423" UserId="1952" Comment="added 4 characters in body" Text="The surface reflectance of a BRDF function doesn't depend on orientation or position of the surface in the world space but is defined relatively to the surface normal (or tangent space in case of anisotropic BRDF) so it should be defined in local space. Think of it as a hemispherical 2D function fixed to a point on the surface of an object that moves and rotates with the object.&#xD;&#xA;&#xD;&#xA;Environment map on the other hand defines luminance from given direction in the world space so it is defined in that space.&#xD;&#xA;&#xD;&#xA;To perform the convolution of these two functions you then have to either transform BRDF to world space or environment map to local space.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8758" PostHistoryTypeId="5" PostId="4038" RevisionGUID="3902b282-b6c6-4bf1-adb2-9665a2306c28" CreationDate="2016-09-26T17:49:36.257" UserId="1952" Comment="added 525 characters in body" Text="The surface reflectance of a BRDF function doesn't depend on orientation or position of the surface in the world space (except for the view vector) but is defined relatively to the surface normal (or tangent space in case of anisotropic BRDF) so it should be defined in local space. Think of it as a hemispherical 2D function fixed to a point on the surface of an object that moves and rotates with the object.&#xD;&#xA;&#xD;&#xA;Environment map on the other hand defines luminance from given direction in the world space so it is defined in that space.&#xD;&#xA;&#xD;&#xA;To perform the convolution of these two functions you then have to either transform BRDF to world space or environment map to local space.&#xD;&#xA;&#xD;&#xA;It's common to transform surface normal/tangent space to the world space and perform lighting calculations in that space. However, if you plan to do define BRDF with spherical harmonics, you might want to consider hemispherical harmonics for better frequency response and transform lighting from world space to the local space. Overall with SH/HSH you can only reproduce fairly low-frequency lighting (i.e. rough surfaces), so they may not be able to render as versatile surfaces as you wish.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8759" PostHistoryTypeId="2" PostId="4040" RevisionGUID="2c282aa1-9908-4458-8472-90c55fa01390" CreationDate="2016-09-27T01:28:53.190" UserId="2707" Text="# Context&#xD;&#xA;&#xD;&#xA;As I was trying to learn more about Vulkan, I learned that certain fixed-function steps could be implemented with shader code from this video (at around the spot where he talks about the following problem):&#xD;&#xA;&#xD;&#xA;https://youtu.be/X8Ob_b3ANzs?t=24m&#xD;&#xA;&#xD;&#xA;In this video, the presenter says &quot;hitching&quot; can occur in OpenGL because for some GPUs the colorblend stage apparently needs to be recompiled at certain times. He gives an example of when a player takes out a torch and causes hitching due to bloom.&#xD;&#xA;&#xD;&#xA;#Questions&#xD;&#xA;&#xD;&#xA;Why would this shader need to be recompiled in this scenario? In what scenarios would this shader need to be recompiled? Is this common practice/an issue across vendors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8760" PostHistoryTypeId="1" PostId="4040" RevisionGUID="2c282aa1-9908-4458-8472-90c55fa01390" CreationDate="2016-09-27T01:28:53.190" UserId="2707" Text="Colorblending shader recompilation scenarios" ContentLicense="CC BY-SA 3.0" />
  <row Id="8761" PostHistoryTypeId="3" PostId="4040" RevisionGUID="2c282aa1-9908-4458-8472-90c55fa01390" CreationDate="2016-09-27T01:28:53.190" UserId="2707" Text="|opengl|shader|vulkan|driver|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8762" PostHistoryTypeId="2" PostId="4041" RevisionGUID="449a05c9-2837-474c-a76c-094d197a7d8a" CreationDate="2016-09-27T02:53:24.330" UserId="1952" Text="You have a lot of questions so let me take a shortcut and just try to explain how this is properly done (:&#xD;&#xA;&#xD;&#xA;What you are interested in calculating is luminance (cd/m^2) for a pixel. A simple way you can do this is by using brute-force Monte Carlo integration over the hemisphere defined by the normal of a pixel, i.e. cast few thousand randomly distributed rays over the hemisphere. For each of those sample rays you evaluate the BRDF (1/sr) and multiply it with the luminance of the area light source the ray hits, or 0 if it doesn't hit anything. Sum up all these results and multiply by 2*pi/num_samples in the end, i.e. by the solid angle of each sample.&#xD;&#xA;&#xD;&#xA;This operation gives you the the luminance for the pixel, which you then multiply by camera exposure factor to map to a proper range which you can tone map, i.e. calculate EV100 from camera aperture, shutter time and ISO-settings as follows:&#xD;&#xA;&#xD;&#xA;    float ev100=log2((aperture*aperture/shutter_time)*100.0f/iso);&#xD;&#xA;&#xD;&#xA;And then calculate exposure factor:&#xD;&#xA;&#xD;&#xA;    float exposure_factor=1.2f*pow(2.0f, ev100);&#xD;&#xA;&#xD;&#xA;For IES light profiles you can normalize the profile and modulate light luminance with the IES factor for the given direction the ray hits the light.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8764" PostHistoryTypeId="2" PostId="4042" RevisionGUID="6677e15c-d845-42ca-bb93-a35fb448e089" CreationDate="2016-09-27T19:46:26.580" UserId="5193" Text="So I've been learning opengl for some weeks now and managed to understand all the viewing pipelines. As far my understanding goes we need to bring the object to world space and then the world space to view space. After that the clipping is done by any of the two projections as we want. The clipping volume is then sent to the viewport which is mapped to the screen coordinates.&#xD;&#xA;&#xD;&#xA;Now when I write this simple basic code below I don't use any of the matrixmode&#xD;&#xA;(GL_MODElVIEW or  GL_PROJECTION) but still the primitive is displayed on the screen. So what am I missing here? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and also an extension to this question I would also like to know what exactly means to bring the object to world coordinates in theory. Does it means overlapping the axes of the object coordinates with the world coordinates.  &#xD;&#xA;&#xD;&#xA;With lot of opengl discussions out there I don't know where to look. Would be extra nice if someone refer me to some good articles. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void Di()&#xD;&#xA;&#xD;&#xA;{&#xD;&#xA;   &#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;	glBegin(GL_QUADS) ;           &#xD;&#xA;       glColor3f ( 1.0, 0.3, 0.2);     &#xD;&#xA;      	glVertex2f( -0.1, -0.1 );       &#xD;&#xA;      	glVertex2f(  0.1, -0.1 );       &#xD;&#xA;      	glVertex2f(  0.1,  0.1 ); &#xD;&#xA;	    glVertex2f( -0.1,  0.1 ); &#xD;&#xA;       glEnd();&#xD;&#xA;  	glFlush();&#xD;&#xA;}&#xD;&#xA;	&#xD;&#xA;int main( int argc, char** argv)&#xD;&#xA;&#xD;&#xA;{&#xD;&#xA;	&#xD;&#xA;    glutInit( &amp;argc, argv);&#xD;&#xA;&#xD;&#xA;	glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);&#xD;&#xA;&#xD;&#xA;	glutInitWindowSize(500,500);&#xD;&#xA;&#xD;&#xA;	glutInitWindowPosition(0,0);&#xD;&#xA;&#xD;&#xA;	glutCreateWindow(&quot;First Program&quot;);&#xD;&#xA;&#xD;&#xA;	glutDisplayFunc(Di);&#xD;&#xA;	glutMainLoop();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8765" PostHistoryTypeId="1" PostId="4042" RevisionGUID="6677e15c-d845-42ca-bb93-a35fb448e089" CreationDate="2016-09-27T19:46:26.580" UserId="5193" Text="What if we don't mention Modelview and projection matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8766" PostHistoryTypeId="3" PostId="4042" RevisionGUID="6677e15c-d845-42ca-bb93-a35fb448e089" CreationDate="2016-09-27T19:46:26.580" UserId="5193" Text="|opengl|3d|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8767" PostHistoryTypeId="2" PostId="4043" RevisionGUID="6ae7926d-cf9b-40e9-a5dd-2628815f4b19" CreationDate="2016-09-27T20:11:13.680" UserId="5183" Text="I am writing an application with multiple colored surfaces. I would like to preserve luminance, i.e. a blue surface would appear as bright as a green one, are there tools to help for this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8768" PostHistoryTypeId="1" PostId="4043" RevisionGUID="6ae7926d-cf9b-40e9-a5dd-2628815f4b19" CreationDate="2016-09-27T20:11:13.680" UserId="5183" Text="Preserving luminance" ContentLicense="CC BY-SA 3.0" />
  <row Id="8769" PostHistoryTypeId="3" PostId="4043" RevisionGUID="6ae7926d-cf9b-40e9-a5dd-2628815f4b19" CreationDate="2016-09-27T20:11:13.680" UserId="5183" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8770" PostHistoryTypeId="5" PostId="4042" RevisionGUID="fd4cf1d8-ac15-410a-8405-dff011c882ad" CreationDate="2016-09-28T00:16:35.757" UserId="48" Comment="fix code formatting" Text="So I've been learning opengl for some weeks now and managed to understand all the viewing pipelines. As far my understanding goes we need to bring the object to world space and then the world space to view space. After that the clipping is done by any of the two projections as we want. The clipping volume is then sent to the viewport which is mapped to the screen coordinates.&#xD;&#xA;&#xD;&#xA;Now when I write this simple basic code below I don't use any of the matrixmode&#xD;&#xA;(GL_MODElVIEW or  GL_PROJECTION) but still the primitive is displayed on the screen. So what am I missing here? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and also an extension to this question I would also like to know what exactly means to bring the object to world coordinates in theory. Does it means overlapping the axes of the object coordinates with the world coordinates.  &#xD;&#xA;&#xD;&#xA;With lot of opengl discussions out there I don't know where to look. Would be extra nice if someone refer me to some good articles. &#xD;&#xA;&#xD;&#xA;	void Di()&#xD;&#xA;	{&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;		glBegin(GL_QUADS) ;           &#xD;&#xA;		   glColor3f ( 1.0, 0.3, 0.2);     &#xD;&#xA;			glVertex2f( -0.1, -0.1 );       &#xD;&#xA;			glVertex2f(  0.1, -0.1 );       &#xD;&#xA;			glVertex2f(  0.1,  0.1 ); &#xD;&#xA;			glVertex2f( -0.1,  0.1 ); &#xD;&#xA;		   glEnd();&#xD;&#xA;		glFlush();&#xD;&#xA;	}&#xD;&#xA;		&#xD;&#xA;	int main( int argc, char** argv)&#xD;&#xA;	{&#xD;&#xA;		glutInit( &amp;argc, argv);&#xD;&#xA;&#xD;&#xA;		glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);&#xD;&#xA;&#xD;&#xA;		glutInitWindowSize(500,500);&#xD;&#xA;&#xD;&#xA;		glutInitWindowPosition(0,0);&#xD;&#xA;&#xD;&#xA;		glutCreateWindow(&quot;First Program&quot;);&#xD;&#xA;&#xD;&#xA;		glutDisplayFunc(Di);&#xD;&#xA;		glutMainLoop();&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8771" PostHistoryTypeId="2" PostId="4044" RevisionGUID="2747361c-f378-4aea-a56d-fbefea7ecaa8" CreationDate="2016-09-28T01:07:49.037" UserId="2707" Text="Your screen isn't 3D, so how do you display 3D objects on it? You need to map 3D coordinates into 2D space. This also explains why your OpenGL code is not behaving how you're expecting it to. Sorry if parts of this answer are things you already know (just trying to be comprehensive).&#xD;&#xA;&#xD;&#xA;#What do the model view and projection matrices do?&#xD;&#xA;The **model view** matrix is actually two matrices (multiplied together): the model matrix and the view matrix. This is important to understanding because these are two transformations into different spaces.&#xD;&#xA;&#xD;&#xA;The **model** matrix transforms model space into world space. This means that say you have a vertex is at an offset from the center of a model. If you want that vertex to be in world space, it must use the scale, rotation, and position of the model to determine this. The model matrix accomplishes this.&#xD;&#xA;&#xD;&#xA;The **view** matrix transforms the world space into the camera space. Does world move or does the camera move in a 3D application? Well, actually the world moves around the camera. The camera is always at the origin, so the view matrix moves the world to this point.&#xD;&#xA;&#xD;&#xA;The **projection** matrix might be the trickiest to visualize. Screens are 2D (technicalities aside), so how do we show 3D objects here? A projection matrix converts 3D coordinates into 2D coordinates (with depth, so still technically 3D). You end up with Normalized Device Coordinates (NDCs). Each vertex on screen is represented by three values:&#xD;&#xA;* x (horizontal) ranging from [-1, 1]&#xD;&#xA;* y (vertical) ranging from [-1, 1]&#xD;&#xA;* z (depth) ranging from [-1, 1]&#xD;&#xA;&#xD;&#xA;#Why don't you need model-view and projection matrices?&#xD;&#xA;It's not that you don't need them, it's just that you are using as explained in the last step above. Otherwise, you are effectively just rendering 2D graphics. Right now you are drawing a quad.&#xD;&#xA;&#xD;&#xA;Look at the coordinates that you are providing. You are basically treating the vertices as 2D vertices for 2D graphics since you are directly specifying their coordinates in NDC space. Remember, the coordinates you picked are between -1 and 1 for x and y, so you are effectively treating them as NDCs. You directly send them to the rasterizer in your example.&#xD;&#xA;&#xD;&#xA;#Further Reading&#xD;&#xA;* http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/&#xD;&#xA;* http://learnopengl.com/#!Getting-started/Coordinate-Systems&#xD;&#xA;* http://www.songho.ca/opengl/gl_projectionmatrix.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8772" PostHistoryTypeId="2" PostId="4045" RevisionGUID="f6645604-fb39-4d54-a9ce-7af3188ffba9" CreationDate="2016-09-28T01:23:32.313" UserId="3003" Text="The usual way of doing this is to work in a color space that has luminance as one of the color components. For example the [Y'CbCr color space](https://en.wikipedia.org/wiki/YCbCr) has a luminance channel (you can think of this as similar to brightness which is a poorly defined term) and 2 chrominance or color channels. There are other color spaces that separate colors in this way, too, such as HSV, HLS, La*b*, etc.&#xD;&#xA;&#xD;&#xA;There are conversions to go between RGB and these various color spaces. The article linked above shows some of the conversions for going between Y'CbCr and sRGB, for example.&#xD;&#xA;&#xD;&#xA;You don't say what type of graphics library you'll be using, so it's hard to give any more detail than what I've given you here. But I've done this in OpenGL, Core Graphics, and others. It shouldn't be too difficult." ContentLicense="CC BY-SA 3.0" />
  <row Id="8773" PostHistoryTypeId="5" PostId="4045" RevisionGUID="52c18a80-5a72-497a-bf0e-0e6b092e8b4f" CreationDate="2016-09-28T02:49:00.587" UserId="3003" Comment="Added last paragraph" Text="The usual way of doing this is to work in a color space that has luminance as one of the color components. For example the [Y'CbCr color space](https://en.wikipedia.org/wiki/YCbCr) has a luminance channel (you can think of this as similar to brightness which is a poorly defined term) and 2 chrominance or color channels. There are other color spaces that separate colors in this way, too, such as HSV, HLS, La*b*, etc.&#xD;&#xA;&#xD;&#xA;There are conversions to go between RGB and these various color spaces. The article linked above shows some of the conversions for going between Y'CbCr and sRGB, for example.&#xD;&#xA;&#xD;&#xA;You don't say what type of graphics library you'll be using, so it's hard to give any more detail than what I've given you here. But I've done this in OpenGL, Core Graphics, and others. It shouldn't be too difficult.&#xD;&#xA;&#xD;&#xA;Edited to add: I should point out that HSV defines value or &quot;brightness&quot; not as luminance but as the average of red, green, and blue, and as such does not track very will with our intuitive sense of brightness. HLS also suffers from some issues (discontinuities, bad but popular reference implementations) and is generally not recommended by the color scientists that I know." ContentLicense="CC BY-SA 3.0" />
  <row Id="8775" PostHistoryTypeId="2" PostId="4047" RevisionGUID="d1cdef7d-e0ec-4b0e-af56-e1e895646e49" CreationDate="2016-09-28T22:25:13.647" UserId="5096" Text="&lt;http://www.cs.sandia.gov/~samitch/papers/vor_final.pdf&gt; There isn't the computer algorithm in any programming languague, but u should be able to replicate it easily with some Plane Reflections and the algorithms from the above link." ContentLicense="CC BY-SA 3.0" />
  <row Id="8776" PostHistoryTypeId="2" PostId="4048" RevisionGUID="0f1a2c4e-ec16-450a-af05-4e3a8efe8084" CreationDate="2016-09-28T22:28:46.937" UserId="4708" Text="I am trying to create a fog-like effect, similar to that found using perlin noise. I know where I can find information about that effect, but it's harder for me to tell if it's an efficient route for what I want to achieve. A similar effect can be seen here, although I'd imagine what I want is much lower in detail: https://www.youtube.com/watch?v=csYzDia5Ckw&#xD;&#xA;&#xD;&#xA;I am currently using openFrameworks (but would also be willing to do this in glsl if that's more appropriate). oF has a method for generating perlin noise, ofNoise(x,y). With this I have created a grid of noise values, and within that, I believe what I need to do next is interpolate between them. This has taken me to pages about bilinear interpolation, but I've learned that the further these effects take me, the more I need to be aware of simpler methods.&#xD;&#xA;&#xD;&#xA;Below is a snippet of my code, and the &quot;fog&quot; object is an instance of ofPixels. With this, I am getting a grid of evenly spaced points of noise. Any advice would be appreciated!&#xD;&#xA;&#xD;&#xA;    for(int x = 0; x &lt; fog.getWidth(); x++){&#xD;&#xA;        for(int y = 0; y &lt; fog.getHeight(); y++){&#xD;&#xA;            ofFloatColor t_col = ofFloatColor(0);&#xD;&#xA;            &#xD;&#xA;            if(x % g_size == 0 &amp;&amp; y % g_size == 0){&#xD;&#xA;                noise = ofNoise(x,y);&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            fog.setColor(x,y,t_col);&#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8777" PostHistoryTypeId="1" PostId="4048" RevisionGUID="0f1a2c4e-ec16-450a-af05-4e3a8efe8084" CreationDate="2016-09-28T22:28:46.937" UserId="4708" Text="Creating a gently moving 2D fog effect" ContentLicense="CC BY-SA 3.0" />
  <row Id="8778" PostHistoryTypeId="3" PostId="4048" RevisionGUID="0f1a2c4e-ec16-450a-af05-4e3a8efe8084" CreationDate="2016-09-28T22:28:46.937" UserId="4708" Text="|c++|interpolation|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8779" PostHistoryTypeId="2" PostId="4049" RevisionGUID="7ed26347-786e-49c7-8a68-ecd38b4366e1" CreationDate="2016-09-28T22:47:17.170" UserId="2308" Text="I have the following object in the game&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;It is a dial with the little triangle showing what part of the disk is being valued.&#xD;&#xA;&#xD;&#xA;The dial serves as a controller that sets a variable from 0-1. If the disk has 0 degrees facing left then it is 0, if the disk has 180 degrees facing left then it is 0.5. Somehow I will eventually find a way to express that so the disk will not be uniform.&#xD;&#xA;&#xD;&#xA;Anyway so the inner disk you see will spin meanwhile the outer disk with the triangle thing will stay in place.&#xD;&#xA;&#xD;&#xA;Something that would be nice is if the area of the spinning disk that is inside of the triangle would disappear.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is I have no clue how to do this.&#xD;&#xA;&#xD;&#xA;Currently the rotation of the disk is done by a matrix that rotates the quad that is rendering this.&#xD;&#xA;&#xD;&#xA;I have two ideas&#xD;&#xA;1. Edit the quad into a mesh cutting out the triangle, however this would not work as the mesh is translated in my current model.&#xD;&#xA;2. Run costly trigonometric calculations to figure out where each fragment is in real space then figure out its angle and distance from the center of the circle.&#xD;&#xA;&#xD;&#xA;I know doing a little trig on each fragment might not sound like much, however just rendering the disk adds 1ms of rendering time when rendering on the lowest possible hardware this could run on.&#xD;&#xA;&#xD;&#xA;How do people achieve real-time masking in opengl?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FozUp.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Nhq1p.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8780" PostHistoryTypeId="1" PostId="4049" RevisionGUID="7ed26347-786e-49c7-8a68-ecd38b4366e1" CreationDate="2016-09-28T22:47:17.170" UserId="2308" Text="Mask out parts of an image in OpenGL ES" ContentLicense="CC BY-SA 3.0" />
  <row Id="8781" PostHistoryTypeId="3" PostId="4049" RevisionGUID="7ed26347-786e-49c7-8a68-ecd38b4366e1" CreationDate="2016-09-28T22:47:17.170" UserId="2308" Text="|masking|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8782" PostHistoryTypeId="2" PostId="4050" RevisionGUID="76406ba7-7dcc-4ed3-8904-771cbc57c4b9" CreationDate="2016-09-29T04:29:48.253" UserId="5205" Text="Look at the photo, modelling for new products. &#xD;&#xA;&#xD;&#xA;Regards&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VSL2w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8783" PostHistoryTypeId="1" PostId="4050" RevisionGUID="76406ba7-7dcc-4ed3-8904-771cbc57c4b9" CreationDate="2016-09-29T04:29:48.253" UserId="5205" Text="What is the name of these software on 2 screen?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8784" PostHistoryTypeId="3" PostId="4050" RevisionGUID="76406ba7-7dcc-4ed3-8904-771cbc57c4b9" CreationDate="2016-09-29T04:29:48.253" UserId="5205" Text="|3d|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8785" PostHistoryTypeId="2" PostId="4051" RevisionGUID="400ecde3-e99e-42d6-9fd0-988431b8b19a" CreationDate="2016-09-29T05:20:27.477" UserId="48" Text="Animated noise can be created by using time as an extra dimension. So instead of 2D noise, you'd use 3D noise with time as the z-axis position, like `ofNoise(x, y, time)`." ContentLicense="CC BY-SA 3.0" />
  <row Id="8786" PostHistoryTypeId="2" PostId="4052" RevisionGUID="0662e28c-9d7b-4347-b91e-360f1838717e" CreationDate="2016-09-29T07:05:13.690" UserId="3128" Text="Judging by the interface that would be blender:&#xD;&#xA;&#xD;&#xA;https://www.blender.org/&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Please note that here is a bender-specific stackexchange site as well:&#xD;&#xA;&#xD;&#xA;http://blender.stackexchange.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8787" PostHistoryTypeId="6" PostId="4042" RevisionGUID="4b1a4b4b-c86a-4cda-8b6b-cbcb641ea0d2" CreationDate="2016-09-29T08:28:31.303" UserId="38" Comment="edited tags" Text="|opengl|3d|2d-graphics|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8788" PostHistoryTypeId="6" PostId="3639" RevisionGUID="6646dfce-1edc-4c9e-9419-107fdc35cfa3" CreationDate="2016-09-29T08:32:33.657" UserId="38" Comment="edited tags" Text="|opengl|texture|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8789" PostHistoryTypeId="6" PostId="1776" RevisionGUID="14fbca32-01ad-412a-8513-31bf2c46127a" CreationDate="2016-09-29T08:33:07.017" UserId="38" Comment="edited tags" Text="|opengl|line-drawing|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8790" PostHistoryTypeId="6" PostId="3593" RevisionGUID="61ae7473-ab45-44f9-b249-457cc49459a5" CreationDate="2016-09-29T08:35:14.597" UserId="38" Comment="edited tags" Text="|opengl|texture|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8791" PostHistoryTypeId="6" PostId="4004" RevisionGUID="1934f788-43e1-4103-9fd4-1dd3c78fca9d" CreationDate="2016-09-29T08:36:14.217" UserId="38" Comment="edited tags" Text="|opengl|3d|texture|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8793" PostHistoryTypeId="2" PostId="4053" RevisionGUID="0644337f-0dd5-47cb-8451-fb1bacb47880" CreationDate="2016-09-29T14:21:12.513" UserId="182" Text="Without looking at the code, from the look of the pictures, my intuition would be that somewhere the code is using the inverse of the matrix it should.&#xD;&#xA;&#xD;&#xA;Looking at the code seems to confirm so, but there are some other problems too.&#xD;&#xA;&#xD;&#xA;&gt;     mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;&#xD;&#xA;`mat3(t,b,n)` is a transform from world space to tangent space. The inverse of such a matrix is indeed its transpose, so `mTBN` transforms from tangent space to world space, which is not what you want.&#xD;&#xA;&#xD;&#xA;&gt;     tanViewPos = mTBN * cameraPos;&#xD;&#xA;&gt;     tanFragPos = mTBN * worldPos.xyz;&#xD;&#xA;&#xD;&#xA;You cannot do something like that. `mTBN` is a 3x3 matrix: without a 4th column and a non-zero homogeneous coordinate, you can only transform directions, not positions. You need to first get the camera direction relative to the vertex, then transform that direction.&#xD;&#xA;&#xD;&#xA;    vec3 worldCameraDir = normalize(vPosition - cameraPos);&#xD;&#xA;    tanViewDir = mTBN * worldCameraDir;&#xD;&#xA;&#xD;&#xA;Let us know in comments if that helps solving your issue." ContentLicense="CC BY-SA 3.0" />
  <row Id="8794" PostHistoryTypeId="5" PostId="4053" RevisionGUID="a9c81895-1d96-4f15-a150-a187edc9aa27" CreationDate="2016-09-29T14:27:04.720" UserId="182" Comment="added 3 characters in body" Text="Without looking at the code, from the look of the pictures, my intuition would be that somewhere the code is using the inverse of the matrix it should.&#xD;&#xA;&#xD;&#xA;Looking at the code seems to confirm so, but there are some other problems too.&#xD;&#xA;&#xD;&#xA;&gt;     mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;&#xD;&#xA;`mat3(t,b,n)` is a transform from world space to tangent space. The inverse of such a matrix is indeed its transpose, so `mTBN` transforms from tangent space to world space, which is not what you want.&#xD;&#xA;&#xD;&#xA;&gt;     tanViewPos = mTBN * cameraPos;&#xD;&#xA;&gt;     tanFragPos = mTBN * worldPos.xyz;&#xD;&#xA;&#xD;&#xA;You cannot do something like that. `mTBN` is a 3x3 matrix: without a 4th column and a non-zero homogeneous coordinate, you can only transform directions, not positions. You need to first get the camera direction relative to the vertex, then transform that direction.&#xD;&#xA;&#xD;&#xA;    // Beware of the vector direction.&#xD;&#xA;    // Here viewDir points from the object toward the viewer.&#xD;&#xA;    vec3 worldViewDir = normalize(cameraPos - worldPos.xyz);&#xD;&#xA;    tanViewDir = mTBN * worldViewDir;&#xD;&#xA;&#xD;&#xA;Let us know in comments if that helps solving your issue." ContentLicense="CC BY-SA 3.0" />
  <row Id="8796" PostHistoryTypeId="10" PostId="4050" RevisionGUID="1f762262-81c4-4585-a16d-b996fdcc78be" CreationDate="2016-09-29T15:27:43.050" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="8797" PostHistoryTypeId="5" PostId="4048" RevisionGUID="18c89cad-9046-4cc9-9295-265f3c377e89" CreationDate="2016-09-29T21:21:29.490" UserId="4708" Comment="Updated code, made progress since I first posted this." Text="I am trying to create a fog-like effect, similar to that found using perlin noise. I know where I can find information about that effect, but it's harder for me to tell if it's an efficient route for what I want to achieve. A similar effect can be seen here, although I'd imagine what I want is much lower in detail: https://www.youtube.com/watch?v=csYzDia5Ckw&#xD;&#xA;&#xD;&#xA;I am currently working in openframeworks. What I have done so far is build a grid of noise values, and have worked towards linearly interpolating in-between those. I feel like I am on the right track, but it very blocky, which makes me wonder if my approach is totally off-mark. This page on Perlin noise has been helpful: http://flafla2.github.io/2014/08/09/perlinnoise.html&#xD;&#xA;&#xD;&#xA;    for(int x = 0; x &lt; grid.getWidth(); x++){&#xD;&#xA;        if(x % g_size == 0){&#xD;&#xA;            for(int y = 0; y &lt; grid.getHeight(); y++){&#xD;&#xA;                if(y % g_size == 0){&#xD;&#xA;                    noise = ofNoise(x,y,ofGetElapsedTimef());&#xD;&#xA;                    grid.setColor(x,y,ofFloatColor(noise));&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    ofVec2f g1, g2, g3, g4;&#xD;&#xA;    float f1, f2, f3, f4, u, v, t_1, t_2;&#xD;&#xA;    &#xD;&#xA;    for(int x = 0; x &lt; grid.getWidth(); x++){&#xD;&#xA;        for(int y = 0; y &lt; grid.getHeight(); y++){&#xD;&#xA;            //find neigboring grid points&#xD;&#xA;            g1 = ofVec2f(x-(x % g_size),y-(y % g_size));&#xD;&#xA;            g2 = ofVec2f(g1.x + g_size,g1.y);&#xD;&#xA;            g3 = ofVec2f(g1.x,g1.y + g_size);&#xD;&#xA;            g4 = g1 + g_size;&#xD;&#xA;&#xD;&#xA;            //get noise values from the grid neighbors&#xD;&#xA;            f1 = grid.getColor(g1.x,g1.y).r;&#xD;&#xA;            f2 = grid.getColor(g2.x,g2.y).r;&#xD;&#xA;            f3 = grid.getColor(g3.x,g3.y).r;&#xD;&#xA;            f4 = grid.getColor(g4.x,g4.y).r;&#xD;&#xA;  &#xD;&#xA;            u = (float)(x % g_size)/g_size;&#xD;&#xA;            v = (float)(y % g_size)/g_size;&#xD;&#xA; &#xD;&#xA;            t_1 = ofLerp(f1,f2,u);&#xD;&#xA;            t_2 = ofLerp(f3,f4,u);&#xD;&#xA;            &#xD;&#xA;            ofColor average = ofLerp(t_1,t_2,v);&#xD;&#xA;            &#xD;&#xA;            fog.setColor(x,y,average);&#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8798" PostHistoryTypeId="5" PostId="4051" RevisionGUID="c8350bee-a318-4a7b-ac32-87a6ab631043" CreationDate="2016-09-30T01:42:46.207" UserId="48" Comment="added note about using octaves" Text="Animated noise can be created by using time as an extra dimension. So instead of 2D noise, you'd use 3D noise with time as the z-axis position, like `ofNoise(x, y, time)`.&#xD;&#xA;&#xD;&#xA;To control the level of detail, you'd use octaves of noise: multiple noise layers with different scales and amplitudes, mixed together. The basic Perlin routines just generate a single octave, so you can re-invoke it with scaled coordinates to add more detail, something like:&#xD;&#xA;&#xD;&#xA;    float noise = ofNoise(x, y, time);          // first octave&#xD;&#xA;    noise += 0.5 * ofNoise(2*x, 2*y, 2*time);   // second octave&#xD;&#xA;    noise += 0.25 * ofNoise(4*x, 4*y, 4*time);  // third octave&#xD;&#xA;&#xD;&#xA;and so on. The more octaves you put in, the more detailed the noise will be. The article you linked describes this in more detail if you scroll down to [Working with Octaves](http://flafla2.github.io/2014/08/09/perlinnoise.html#working-with-octaves)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8799" PostHistoryTypeId="2" PostId="4054" RevisionGUID="710c7b41-2c5e-4433-940b-b5944da2a602" CreationDate="2016-09-30T10:53:22.343" UserId="4981" Text="I must convert a isosceles trapezoid to a rectangle in 2-D with a shearing transformation (or with 2 shearing transformations).  The isosceles trapezoid is centered in the origin of axes.&#xD;&#xA;It is right write:&#xD;&#xA;&#xD;&#xA;     x' = x + αy&#xD;&#xA;     y'=y&#xD;&#xA; &#xD;&#xA;with α&gt;0  per y&gt;0 ,  and α&lt;0  per y&lt;0 (then 2 transformations)?&#xD;&#xA;And if it's right how can I calculate the parameter α?&#xD;&#xA;Otherwise if it is all wrong as I do?     &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8800" PostHistoryTypeId="1" PostId="4054" RevisionGUID="710c7b41-2c5e-4433-940b-b5944da2a602" CreationDate="2016-09-30T10:53:22.343" UserId="4981" Text="Transform a centered isosceles trapezoid in a rectangle in 2-D" ContentLicense="CC BY-SA 3.0" />
  <row Id="8801" PostHistoryTypeId="3" PostId="4054" RevisionGUID="710c7b41-2c5e-4433-940b-b5944da2a602" CreationDate="2016-09-30T10:53:22.343" UserId="4981" Text="|transformations|computational-geometry|geometry|mathematics|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8802" PostHistoryTypeId="5" PostId="4026" RevisionGUID="c573b1d3-e4e9-4998-998a-98713a6378b0" CreationDate="2016-09-30T14:10:40.243" UserId="4958" Comment="added 2093 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I've found function which calculates tbn in fragment:&#xD;&#xA;&#xD;&#xA;    mat3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)&#xD;&#xA;    {&#xD;&#xA;        // get edge vectors of the pixel triangle&#xD;&#xA;        vec3 dp1 = dFdx( P );&#xD;&#xA;        vec3 dp2 = dFdy( P );&#xD;&#xA;        vec2 duv1 = dFdx( UV );&#xD;&#xA;        vec2 duv2 = dFdy( UV );&#xD;&#xA;    &#xD;&#xA;        // solve the linear system&#xD;&#xA;        vec3 dp2perp = cross( dp2, N );&#xD;&#xA;        vec3 dp1perp = cross( N, dp1 );&#xD;&#xA;        vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;&#xD;&#xA;        vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;&#xD;&#xA;    &#xD;&#xA;        // construct a scale-invariant frame&#xD;&#xA;        float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );&#xD;&#xA;        return mat3( T * invmax, B * invmax, N );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**First Case:** So if I use that function like that:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    vFar = cameraPos - worldPos.xyz; &#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = (compute_tangent_frame(vNormal0, normalize(vFar), vTexCoord0));&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax and normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][10]&#xD;&#xA;&#xD;&#xA;**Second Case:** But if I use my TBN from CPU:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    mat4 model = ((matrices.modelMatrix));&#xD;&#xA;    vec3 t = normalize(mat3(model) * (vTangent));&#xD;&#xA;    vec3 b = normalize(mat3(model) * (vBitangent));&#xD;&#xA;    vec3 n = normalize(mat3(model) * (vNormal));&#xD;&#xA;    mTBN = ((mat3(t,b,n)));&#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = mTBN;&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax is still twisted but normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][12]&#xD;&#xA;&#xD;&#xA;If I dont transpose tbn (viewDir) in second case (mTBN)&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = ((TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;&#xD;&#xA;then some walls seem to be correct, others not...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/1YKhym.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/1YKhy.jpg&#xD;&#xA;&#xD;&#xA;  [11]: https://i.stack.imgur.com/KQFIrm.jpg&#xD;&#xA;[12]: https://i.stack.imgur.com/KQFIr.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8803" PostHistoryTypeId="5" PostId="4026" RevisionGUID="7790c238-dece-4d09-bfd1-81abf1dc9cd3" CreationDate="2016-09-30T14:24:46.020" UserId="4958" Comment="added 27 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I've found function which calculates tbn in fragment:&#xD;&#xA;&#xD;&#xA;    mat3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)&#xD;&#xA;    {&#xD;&#xA;        // get edge vectors of the pixel triangle&#xD;&#xA;        vec3 dp1 = dFdx( P );&#xD;&#xA;        vec3 dp2 = dFdy( P );&#xD;&#xA;        vec2 duv1 = dFdx( UV );&#xD;&#xA;        vec2 duv2 = dFdy( UV );&#xD;&#xA;    &#xD;&#xA;        // solve the linear system&#xD;&#xA;        vec3 dp2perp = cross( dp2, N );&#xD;&#xA;        vec3 dp1perp = cross( N, dp1 );&#xD;&#xA;        vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;&#xD;&#xA;        vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;&#xD;&#xA;    &#xD;&#xA;        // construct a scale-invariant frame&#xD;&#xA;        float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );&#xD;&#xA;        return mat3( T * invmax, B * invmax, N );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**First Case:** So if I use that function like that:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    vFar = cameraPos - worldPos.xyz; &#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = (compute_tangent_frame(vNormal0, normalize(vFar), vTexCoord0));&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax and normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][10]&#xD;&#xA;&#xD;&#xA;**Second Case:** But if I use my TBN from CPU:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    mat4 model = ((matrices.modelMatrix));&#xD;&#xA;    vec3 t = normalize(mat3(model) * (vTangent));&#xD;&#xA;    vec3 b = normalize(mat3(model) * (vBitangent));&#xD;&#xA;    vec3 n = normalize(mat3(model) * (vNormal));&#xD;&#xA;    mTBN = ((mat3(t,b,n)));&#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = mTBN;&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax is still twisted but normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][12]&#xD;&#xA;&#xD;&#xA;If I dont transpose tbn (viewDir) (the correct way You said) in second case (mTBN)&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = ((TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;&#xD;&#xA;then some walls seem to be correct, others not...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/1YKhym.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/1YKhy.jpg&#xD;&#xA;&#xD;&#xA;  [11]: https://i.stack.imgur.com/KQFIrm.jpg&#xD;&#xA;[12]: https://i.stack.imgur.com/KQFIr.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8804" PostHistoryTypeId="5" PostId="4026" RevisionGUID="70e92ab9-c44d-43c6-9c4b-9f8456bae157" CreationDate="2016-09-30T14:34:10.027" UserId="4958" Comment="added 25 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I've found function which calculates tbn in fragment:&#xD;&#xA;&#xD;&#xA;    mat3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)&#xD;&#xA;    {&#xD;&#xA;        // get edge vectors of the pixel triangle&#xD;&#xA;        vec3 dp1 = dFdx( P );&#xD;&#xA;        vec3 dp2 = dFdy( P );&#xD;&#xA;        vec2 duv1 = dFdx( UV );&#xD;&#xA;        vec2 duv2 = dFdy( UV );&#xD;&#xA;    &#xD;&#xA;        // solve the linear system&#xD;&#xA;        vec3 dp2perp = cross( dp2, N );&#xD;&#xA;        vec3 dp1perp = cross( N, dp1 );&#xD;&#xA;        vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;&#xD;&#xA;        vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;&#xD;&#xA;    &#xD;&#xA;        // construct a scale-invariant frame&#xD;&#xA;        float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );&#xD;&#xA;        return mat3( T * invmax, B * invmax, N );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**First Case:** So if I use that function like that:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    vFar = cameraPos - worldPos.xyz; &#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = (compute_tangent_frame(vNormal0, normalize(vFar), vTexCoord0));&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax (all walls) and normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][10]&#xD;&#xA;&#xD;&#xA;**Second Case:** But if I use my TBN from CPU:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    mat4 model = ((matrices.modelMatrix));&#xD;&#xA;    vec3 t = normalize(mat3(model) * (vTangent));&#xD;&#xA;    vec3 b = normalize(mat3(model) * (vBitangent));&#xD;&#xA;    vec3 n = normalize(mat3(model) * (vNormal));&#xD;&#xA;    mTBN = ((mat3(t,b,n)));&#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = mTBN;&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax is still twisted on all walls but normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][12]&#xD;&#xA;&#xD;&#xA;If I dont transpose tbn (viewDir) (the correct way You said) in second case (mTBN)&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = ((TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;&#xD;&#xA;then some walls seem to be correct, others not...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/1YKhym.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/1YKhy.jpg&#xD;&#xA;&#xD;&#xA;  [11]: https://i.stack.imgur.com/KQFIrm.jpg&#xD;&#xA;[12]: https://i.stack.imgur.com/KQFIr.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8805" PostHistoryTypeId="2" PostId="4055" RevisionGUID="39cf178b-1ff8-4c90-b4ea-c7c1c0dfbbc3" CreationDate="2016-09-30T20:18:21.453" UserId="5211" Text="I have a skeleton (in asf/amc format http://research.cs.wisc.edu/graphics/Courses/cs-838-1999/Jeff/ASF-AMC.html), from CMU's mocap database. &#xD;&#xA;I'm using python, no libraries yet. (blender in python mode doesn't work properly for this, AFAIK).&#xD;&#xA;&#xD;&#xA;I want to mirror the movement, swapping sides, assigning the right arm movement to the left arm and so in. &#xD;&#xA;&#xD;&#xA;The number of DOF for each joint is between 1 and 3, angles are stored in euler format, XYZ. All angles are local, relative to the parent bone.&#xD;&#xA;&#xD;&#xA;Quite obviously, just renaming the objects (rhand&lt;-&gt;lhand) doesn't work. Where do I start?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8806" PostHistoryTypeId="1" PostId="4055" RevisionGUID="39cf178b-1ff8-4c90-b4ea-c7c1c0dfbbc3" CreationDate="2016-09-30T20:18:21.453" UserId="5211" Text="Mirroring avatar" ContentLicense="CC BY-SA 3.0" />
  <row Id="8807" PostHistoryTypeId="3" PostId="4055" RevisionGUID="39cf178b-1ff8-4c90-b4ea-c7c1c0dfbbc3" CreationDate="2016-09-30T20:18:21.453" UserId="5211" Text="|geometry|motion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8808" PostHistoryTypeId="2" PostId="4056" RevisionGUID="efecf6a3-edfa-42a7-9277-0561e6f3c98c" CreationDate="2016-09-30T21:04:24.477" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="8809" PostHistoryTypeId="2" PostId="4057" RevisionGUID="57dcb332-8265-4d99-9bfb-f03b596887d3" CreationDate="2016-09-30T21:04:24.477" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="8810" PostHistoryTypeId="5" PostId="4055" RevisionGUID="54afe1b5-36d2-4fc9-869c-1ab0c2d25262" CreationDate="2016-09-30T22:59:16.027" UserId="231" Comment="Minor tidying" Text="I have a skeleton (in [asf/amc format]), from [CMU's mocap database]. &#xD;&#xA;I'm using python, no libraries yet. (Blender in python mode doesn't work properly for this, as far as I know.)&#xD;&#xA;&#xD;&#xA;I want to mirror the movement, swapping sides, assigning the right arm movement to the left arm and so on. &#xD;&#xA;&#xD;&#xA;The number of degrees of freedom for each joint is between 1 and 3. Angles are stored in euler format, XYZ. All angles are local, relative to the parent bone.&#xD;&#xA;&#xD;&#xA;Quite obviously, just renaming the objects (rhand&lt;-&gt;lhand) doesn't work. Where do I start?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [asf/amc format]: http://research.cs.wisc.edu/graphics/Courses/cs-838-1999/Jeff/ASF-AMC.html&#xD;&#xA;&#xD;&#xA;  [CMU's mocap database]: http://mocap.cs.cmu.edu/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8811" PostHistoryTypeId="5" PostId="4056" RevisionGUID="cc7d0887-da80-493b-a858-be6fd5b6120e" CreationDate="2016-10-01T00:04:17.403" UserId="1908" Comment="This is a verbatim copy of StackOverflow's glTF tag." Text="The GL Transmission Format ([glTF](https://github.com/KhronosGroup/glTF)) is a runtime asset delivery format for GL APIs: [tag:webgl], [tag:opengl-es], and [tag:opengl].  glTF bridges the gap between 3D content creation tools and modern GL applications by providing an efficient, extensible, interoperable format for the transmission and loading of 3D content.&#xD;&#xA;&#xD;&#xA;The need for a network-enabled 3D content delivery format such as glTF has been [compared to the need for JPEG for images, and MP3 for audio](https://www.khronos.org/gltf/).&#xD;&#xA;&#xD;&#xA;## Specification&#xD;&#xA;&#xD;&#xA;The glTF specification is maintained by [the Khronos Group](https://www.khronos.org/).  This standards organization is also responsible for OpenGL, WebGL, COLLADA, and others.&#xD;&#xA;&#xD;&#xA;* [glTF Specification](https://github.com/KhronosGroup/glTF/specification/README.md)&#xD;&#xA;* [glTF Extension Registry](https://github.com/KhronosGroup/glTF/extensions/README.md)&#xD;&#xA;&#xD;&#xA;## Sample Models&#xD;&#xA;&#xD;&#xA;A collection of [Sample models](https://github.com/KhronosGroup/glTF/blob/master/sampleModels/README.md) are available for learning glTF, and testing runtime engines and content pipeline tools.&#xD;&#xA;&#xD;&#xA;## Converters and Exporters&#xD;&#xA;&#xD;&#xA;glTF files can be created by converting from other popular formats such as [tag:collada], [tag:wavefront] OBJ, [tag:fbx], and others.  View the [list of converters](https://github.com/KhronosGroup/glTF#converters).&#xD;&#xA;&#xD;&#xA;As support for glTF grows, 3D authoring packages may gain the ability to export to glTF directly.  For example, a [tag:blender] [exporter](https://github.com/Kupoman/blendergltf) is in early stages of development.&#xD;&#xA;&#xD;&#xA;## Loaders and Viewers&#xD;&#xA;&#xD;&#xA;Support for glTF is available for [tag:three.js], [tag:babylonjs], [tag:cesium], [tag:xml3d], and others.  Khronos maintains a [list of glTF loaders and viewers](https://github.com/KhronosGroup/glTF#loaders-and-viewers).&#xD;&#xA;&#xD;&#xA;## File Structure&#xD;&#xA;&#xD;&#xA;A [structural overview diagram](https://raw.githubusercontent.com/KhronosGroup/glTF/master/specification/figures/gltfOverview-0.2.0.png) (by [Marco Hutter](https://github.com/javagl/gltfOverview)) shows an at-a-glance view of the structure of a glTF file and its contents.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8812" PostHistoryTypeId="24" PostId="4056" RevisionGUID="cc7d0887-da80-493b-a858-be6fd5b6120e" CreationDate="2016-10-01T00:04:17.403" Comment="Proposed by 1908 approved by 231 edit id of 163" ContentLicense="CC BY-SA 3.0" />
  <row Id="8813" PostHistoryTypeId="5" PostId="4057" RevisionGUID="bb6e5768-a4dc-4023-a000-e08f3e590ce3" CreationDate="2016-10-01T00:04:27.633" UserId="1908" Comment="This is a verbatim copy of StackOverflow's glTF tag." Text="The GL Transmission Format (glTF) is a runtime asset delivery format for GL APIs: WebGL, OpenGL ES, and OpenGL. glTF bridges the gap between 3D content creation tools and modern GL applications by providing an efficient, extensible, interoperable format for the transmission and loading of 3D content." ContentLicense="CC BY-SA 3.0" />
  <row Id="8814" PostHistoryTypeId="24" PostId="4057" RevisionGUID="bb6e5768-a4dc-4023-a000-e08f3e590ce3" CreationDate="2016-10-01T00:04:27.633" Comment="Proposed by 1908 approved by 231 edit id of 164" ContentLicense="CC BY-SA 3.0" />
  <row Id="8815" PostHistoryTypeId="5" PostId="4026" RevisionGUID="91ffff72-d5d7-46fc-afcf-7809b9d44be7" CreationDate="2016-10-01T10:53:20.733" UserId="4958" Comment="added 193 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I've found function which calculates tbn in fragment:&#xD;&#xA;&#xD;&#xA;    mat3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)&#xD;&#xA;    {&#xD;&#xA;        // get edge vectors of the pixel triangle&#xD;&#xA;        vec3 dp1 = dFdx( P );&#xD;&#xA;        vec3 dp2 = dFdy( P );&#xD;&#xA;        vec2 duv1 = dFdx( UV );&#xD;&#xA;        vec2 duv2 = dFdy( UV );&#xD;&#xA;    &#xD;&#xA;        // solve the linear system&#xD;&#xA;        vec3 dp2perp = cross( dp2, N );&#xD;&#xA;        vec3 dp1perp = cross( N, dp1 );&#xD;&#xA;        vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;&#xD;&#xA;        vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;&#xD;&#xA;    &#xD;&#xA;        // construct a scale-invariant frame&#xD;&#xA;        float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );&#xD;&#xA;        return mat3( T * invmax, B * invmax, N );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**First Case:** So if I use that function like that:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    vFar = cameraPos - worldPos.xyz; &#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = (compute_tangent_frame(vNormal0, normalize(vFar), vTexCoord0));&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax (all walls) and normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][10]&#xD;&#xA;&#xD;&#xA;**Second Case:** But if I use my TBN from CPU:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    mat4 model = ((matrices.modelMatrix));&#xD;&#xA;    vec3 t = normalize(mat3(model) * (vTangent));&#xD;&#xA;    vec3 b = normalize(mat3(model) * (vBitangent));&#xD;&#xA;    vec3 n = normalize(mat3(model) * (vNormal));&#xD;&#xA;    mTBN = ((mat3(t,b,n)));&#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = mTBN;&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax is still twisted on all walls but normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][12]&#xD;&#xA;&#xD;&#xA;If I dont transpose tbn (viewDir) (the correct way You said) in second case (mTBN)&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = ((TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;&#xD;&#xA;then some walls seem to be correct, others not...&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/1YKhym.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/1YKhy.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/KQFIrm.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/KQFIr.jpg&#xD;&#xA;  [13]: https://i.stack.imgur.com/2vdi7.jpg&#xD;&#xA;  [14]: https://i.stack.imgur.com/vA5lc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8816" PostHistoryTypeId="5" PostId="4026" RevisionGUID="c525ed41-9bc0-4ea6-81d5-35e7955c7b6f" CreationDate="2016-10-01T11:01:33.223" UserId="4958" Comment="added 34 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I've found function which calculates tbn in fragment:&#xD;&#xA;&#xD;&#xA;    mat3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)&#xD;&#xA;    {&#xD;&#xA;        // get edge vectors of the pixel triangle&#xD;&#xA;        vec3 dp1 = dFdx( P );&#xD;&#xA;        vec3 dp2 = dFdy( P );&#xD;&#xA;        vec2 duv1 = dFdx( UV );&#xD;&#xA;        vec2 duv2 = dFdy( UV );&#xD;&#xA;    &#xD;&#xA;        // solve the linear system&#xD;&#xA;        vec3 dp2perp = cross( dp2, N );&#xD;&#xA;        vec3 dp1perp = cross( N, dp1 );&#xD;&#xA;        vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;&#xD;&#xA;        vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;&#xD;&#xA;    &#xD;&#xA;        // construct a scale-invariant frame&#xD;&#xA;        float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );&#xD;&#xA;        return mat3( T * invmax, B * invmax, N );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**First Case:** So if I use that function like that:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    vFar = cameraPos - worldPos.xyz; &#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = (compute_tangent_frame(vNormal0, normalize(vFar), vTexCoord0));&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax (all walls) and normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][10]&#xD;&#xA;&#xD;&#xA;**Second Case:** But if I use my TBN from CPU:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    mat4 model = ((matrices.modelMatrix));&#xD;&#xA;    vec3 t = normalize(mat3(model) * (vTangent));&#xD;&#xA;    vec3 b = normalize(mat3(model) * (vBitangent));&#xD;&#xA;    vec3 n = normalize(mat3(model) * (vNormal));&#xD;&#xA;    mTBN = ((mat3(t,b,n)));&#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = mTBN;&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax is still twisted on all walls but normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][12]&#xD;&#xA;&#xD;&#xA;If I dont transpose tbn (viewDir) (the correct way You said) in second case (mTBN)&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = ((TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;&#xD;&#xA;then some walls seem to be correct, others not...&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;Adventures in tangent space...&#xD;&#xA;&#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/1YKhym.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/1YKhy.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/KQFIrm.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/KQFIr.jpg&#xD;&#xA;  [13]: https://i.stack.imgur.com/2vdi7.jpg&#xD;&#xA;  [14]: https://i.stack.imgur.com/vA5lc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8817" PostHistoryTypeId="5" PostId="4026" RevisionGUID="eaef5d3d-3880-44ed-985c-cc53d98e0370" CreationDate="2016-10-01T11:09:43.383" UserId="4958" Comment="added 74 characters in body" Text="I'm trying to implement POM using [this tutorial][1]. As stated, I need to transform fragment-to-camera to tangent space and then pass it to a function.&#xD;&#xA;&#xD;&#xA; - tangent space is computed using [Assimp][2]. Well I trusted it. For example tangent vectors look like that (Sponza model):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][4]&#xD;&#xA;&#xD;&#xA; - then in vertex I make transformation as in tutorial:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;layout (location = 0) in vec3 vPosition;&#xD;&#xA;layout (location = 1) in vec2 vTexCoord;&#xD;&#xA;layout (location = 2) in vec3 vNormal;&#xD;&#xA;layout (location = 3) in vec3 vTangent;&#xD;&#xA;layout (location = 4) in vec3 vBitangent;&#xD;&#xA;...&#xD;&#xA;worldPos = matrices.modelMatrix * vec4(vPosition, 1.0);&#xD;&#xA;//transform t, b, n from object to world (also called model) space?&#xD;&#xA;vec3 t = normalize(mat3(matrices.modelMatrix) * vTangent);&#xD;&#xA;vec3 b = normalize(mat3(matrices.modelMatrix) * vBitangent);&#xD;&#xA; vec3 n = normalize(mat3(matrices.modelMatrix) * vNormal);&#xD;&#xA;mTBN = transpose(mat3(t,b,n)); //transpose makes it from model to to tangent space?&#xD;&#xA;tanViewPos = mTBN * cameraPos;&#xD;&#xA;tanFragPos = mTBN * worldPos.xyz;&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA; - then in fragment I pass parameters to function:&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec3 viewDir = normalize(tanViewPos - tanFragPos);&#xD;&#xA;        texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;    &lt;pre&gt;&lt;code&gt;vec2 steepParallaxMapping(vec2 texCoords, vec3 viewDir, sampler2D textureHeight)&#xD;&#xA;{&#xD;&#xA;    float height_scale = 0.09;&#xD;&#xA;    // number of depth layers&#xD;&#xA;    const float numLayers = 30.0;&#xD;&#xA;    // calculate the size of each layer&#xD;&#xA;    float layerDepth = 1.0 / numLayers;&#xD;&#xA;    // depth of current layer&#xD;&#xA;    float currentLayerDepth = 0.0;&#xD;&#xA;    // the amount to shift the texture coordinates per layer (from vector P)&#xD;&#xA;    vec2 P = viewDir.xy * height_scale;&#xD;&#xA;    vec2 deltaTexCoords = P / numLayers;&#xD;&#xA;    // get initial values&#xD;&#xA;    vec2  currentTexCoords     = texCoords;&#xD;&#xA;    float currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;&#xD;&#xA;    while(currentLayerDepth &lt; currentDepthMapValue)&#xD;&#xA;    {&#xD;&#xA;        // shift texture coordinates along direction of P&#xD;&#xA;        currentTexCoords -= deltaTexCoords;&#xD;&#xA;        // get depthmap value at current texture coordinates&#xD;&#xA;        currentDepthMapValue = texture2D(textureHeight, currentTexCoords).r;&#xD;&#xA;        // get depth of next layer&#xD;&#xA;        currentLayerDepth += layerDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // get texture coordinates before collision (reverse operations)&#xD;&#xA;    vec2 prevTexCoords = currentTexCoords + deltaTexCoords;&#xD;&#xA;&#xD;&#xA;    // get depth after and before collision for linear interpolation&#xD;&#xA;    float afterDepth  = currentDepthMapValue - currentLayerDepth;&#xD;&#xA;    float beforeDepth = texture2D(textureHeight, prevTexCoords).r - currentLayerDepth + layerDepth;&#xD;&#xA;&#xD;&#xA;    // interpolation of texture coordinates&#xD;&#xA;    float weight = afterDepth / (afterDepth - beforeDepth);&#xD;&#xA;    return prevTexCoords * weight + currentTexCoords * (1.0 - weight);&#xD;&#xA;}&lt;/pre&gt;&lt;/code&gt;&#xD;&#xA;&#xD;&#xA;   Thats the result (simple displacement):&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][6]&#xD;&#xA;&#xD;&#xA;Or other texture (complex):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][8]&#xD;&#xA;&#xD;&#xA;I'm doing something wrong. And I wonder why we multiply by 3x3 part of the model matrix?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I've found function which calculates tbn in fragment:&#xD;&#xA;&#xD;&#xA;    mat3 compute_tangent_frame(vec3 N, vec3 P, vec2 UV)&#xD;&#xA;    {&#xD;&#xA;        // get edge vectors of the pixel triangle&#xD;&#xA;        vec3 dp1 = dFdx( P );&#xD;&#xA;        vec3 dp2 = dFdy( P );&#xD;&#xA;        vec2 duv1 = dFdx( UV );&#xD;&#xA;        vec2 duv2 = dFdy( UV );&#xD;&#xA;    &#xD;&#xA;        // solve the linear system&#xD;&#xA;        vec3 dp2perp = cross( dp2, N );&#xD;&#xA;        vec3 dp1perp = cross( N, dp1 );&#xD;&#xA;        vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;&#xD;&#xA;        vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;&#xD;&#xA;    &#xD;&#xA;        // construct a scale-invariant frame&#xD;&#xA;        float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );&#xD;&#xA;        return mat3( T * invmax, B * invmax, N );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**First Case:** So if I use that function like that:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    vFar = cameraPos - worldPos.xyz; &#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = (compute_tangent_frame(vNormal0, normalize(vFar), vTexCoord0));&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax (all walls) and normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][10]&#xD;&#xA;&#xD;&#xA;**Second Case:** But if I use my TBN from CPU:&#xD;&#xA;&#xD;&#xA;    //in vertex&#xD;&#xA;    mat4 model = ((matrices.modelMatrix));&#xD;&#xA;    vec3 t = normalize(mat3(model) * (vTangent));&#xD;&#xA;    vec3 b = normalize(mat3(model) * (vBitangent));&#xD;&#xA;    vec3 n = normalize(mat3(model) * (vNormal));&#xD;&#xA;    mTBN = ((mat3(t,b,n)));&#xD;&#xA;    //in fragment&#xD;&#xA;    mat3 TBN = mTBN;&#xD;&#xA;    vec3 viewDir = (transpose(TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;    vec2 texCoord = steepParallaxMapping(vTexCoord0, viewDir, textureHeight);&#xD;&#xA;    vNormalExtr = normalize(texture2D(textureNormal, texCoord).rgb*2.0 - 1.0);&#xD;&#xA;    normalMapColor = vec4(normalize((TBN) * vNormalExtr), 1.0);&#xD;&#xA;&#xD;&#xA;parallax is still twisted on all walls but normal light seem to be ok:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][12]&#xD;&#xA;&#xD;&#xA;If I dont transpose tbn (viewDir) (the correct way You said) in second case (mTBN)&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = ((TBN)*normalize(cameraPos - worldPos.xyz));&#xD;&#xA;&#xD;&#xA;then some walls seem to be correct, others not...&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;Adventures in tangent space...&#xD;&#xA;Is there a badge of longest question ever or biggest number of pictures?&#xD;&#xA;&#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!Advanced-Lighting/Parallax-Mapping&#xD;&#xA;  [2]: http://www.assimp.org&#xD;&#xA;  [3]: https://i.stack.imgur.com/OdSJsm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OdSJs.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/XuvYLm.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XuvYL.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/bI99Om.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/bI99O.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/1YKhym.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/1YKhy.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/KQFIrm.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/KQFIr.jpg&#xD;&#xA;  [13]: https://i.stack.imgur.com/2vdi7.jpg&#xD;&#xA;  [14]: https://i.stack.imgur.com/vA5lc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8818" PostHistoryTypeId="5" PostId="392" RevisionGUID="49790137-aec2-4253-84f4-63372e105121" CreationDate="2016-10-01T23:16:46.500" UserId="482" Comment="fix skew matrix" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b \\ c&amp;d\end{bmatrix}&#xD;&#xA;+&#xD;&#xA;\begin{bmatrix}e&amp; f\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair $(x', y')$ from the original pair $(x, y)$ and a list of constants $(a, b, c, d, e, f)$.&#xD;&#xA;$$&#xD;&#xA;    x' =  a\cdot x + c\cdot y + e \\&#xD;&#xA;    y' =  b\cdot x + d\cdot y + f&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'&amp;1\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}x''&amp; y''&amp;1\end{bmatrix}&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}\right)&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}a \cdot x + c \cdot y+e &amp; b \cdot x + d \cdot y+f &amp;1 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}g(a \cdot x + c \cdot y+e) + i( b \cdot x + d \cdot y+f) + k &#xD;&#xA;\\&#xD;&#xA;h(a \cdot x + c \cdot y+e) + j( b \cdot x + d \cdot y+f) + m&#xD;&#xA;\\1 \end{bmatrix}^T&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\right)&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\begin{bmatrix}ag+bi&amp; ah+bj &amp;0\\ cg+di&amp;ch+dj&amp;0 \\ eg+fi+k&amp;eh+fj+m&amp;1\end{bmatrix}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    S_x &amp; 0 &amp; 0 \\&#xD;&#xA;    0  &amp; S_y &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    T_x &amp; T_y &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; 0 &amp; 0 \\&#xD;&#xA;    Q_y &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    \cos\theta &amp; -sin\theta &amp; 0\\&#xD;&#xA;    \sin\theta &amp; \cos\theta &amp; 0\\&#xD;&#xA;    0  &amp;  0 &amp;  1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;A matrix composed purely from scaling, rotation, and translation can be [decomposed back into these three components](http://stackoverflow.com/a/11942636/733077).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8819" PostHistoryTypeId="2" PostId="4058" RevisionGUID="eddce090-514a-402e-b735-f2ae8287935a" CreationDate="2016-10-02T00:31:37.540" UserId="5215" Text="So I have very recently started looking into real-time fluid simulation. Idea is to make a game that would use fluid simulation as a core gameplay mechanic.&#xD;&#xA;&#xD;&#xA;Looking around the web, among other things, I found **[this][1]** article that compares the performance of fluid simulations on CPU and GPU. While the article itself is a bit dated, I assume that while CPUs and GPUs today are faster, the performance ration between the two has stayed similar enough to keep the article relevant. Actually, comparing their hardware (Core 2 Quad Q6600 and GeForce 8800 GT) to today's hardware (eg. i5 6600K and GTX 1070), CPU has [230% performance gain][2], while GPU has staggering [1670% performance gain][3]. This would make the article more relevant today than it was before (more than six times).&#xD;&#xA;&#xD;&#xA;Now, with bigger grids they did testing on (GS, 128^3, page 7, table 2), GPU simulation was over 3000 times faster than the CPU simulation. Even if utilizing 4 cores (they were using only a single thread), it's still over 700-fold performance gain (back in the day, today that would go up to 5000-fold). Given the data, that difference would only increase with bigger grids.&#xD;&#xA;&#xD;&#xA;The question is, along with all the normal rendering the GPU is tasked with doing, is it viable to burden it with the task of computing the simulation too, **in any case at all**?&#xD;&#xA;&#xD;&#xA;What's the use of rendering the graphics at 60FPS if fluid simulation runs at 10 steps per second, effectively making the game look like it's running at 10FPS? Wouldn't it be better if I rendered graphics at 30FPS, but could do the simulation at 30 steps per second as well?&#xD;&#xA;&#xD;&#xA;Basically, the question is, what would take longer:&#xD;&#xA;&#xD;&#xA; - For the GPU to render a frame AND compute the simulation step&#xD;&#xA;&#xD;&#xA;OR&#xD;&#xA;&#xD;&#xA; - For the CPU to compute rest of the game logic AND compute the simulation step.&#xD;&#xA;&#xD;&#xA;I know that this heavily depends on the GPU involved and the remainder of the GPU and CPU load, but look at the whole thing this way:&#xD;&#xA;&#xD;&#xA;Even if I used just 1% of the power of GPU, the speed would still be 7(50!) times greater than using the CPU.&#xD;&#xA;&#xD;&#xA;I'm a big novice in when it comes to computer graphics, so I may have gotten it all wrong. Does anything I wrote make any sense, or is it just gibberish?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.it.ubi.pt/17epcg/Actas/artigos/17epcg_submission_39.pdf&#xD;&#xA;  [2]: http://cpu.userbenchmark.com/Compare/Intel-Core2-Quad-Q6600-vs-Intel-Core-i5-6600K/1980vs3503&#xD;&#xA;  [3]: http://gpu.userbenchmark.com/Compare/Nvidia-GeForce-8800-GT-vs-Nvidia-GTX-1070/m7722vs3609" ContentLicense="CC BY-SA 3.0" />
  <row Id="8820" PostHistoryTypeId="1" PostId="4058" RevisionGUID="eddce090-514a-402e-b735-f2ae8287935a" CreationDate="2016-10-02T00:31:37.540" UserId="5215" Text="Fluid sim: CPU vs. GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="8821" PostHistoryTypeId="3" PostId="4058" RevisionGUID="eddce090-514a-402e-b735-f2ae8287935a" CreationDate="2016-10-02T00:31:37.540" UserId="5215" Text="|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8822" PostHistoryTypeId="5" PostId="4058" RevisionGUID="b63e37f8-f0d6-4add-977c-9eba7207e01a" CreationDate="2016-10-02T00:54:43.130" UserId="5215" Comment="Clarification" Text="I have very recently started looking into real-time fluid simulation. Idea is to make a game that would use 3D fluid simulation as a core gameplay mechanic.&#xD;&#xA;&#xD;&#xA;Looking around the web, I found **[this][1]** article that compares the performance of fluid simulations on CPU and GPU. While the article itself is a bit dated, I assume that while CPUs and GPUs today are faster, the performance ration between the two has stayed similar enough to keep the article relevant. Actually, comparing their hardware (Core 2 Quad Q6600 and GeForce 8800 GT) to today's hardware (eg. i5 6600K and GTX 1070), CPU has [230% performance gain][2], while GPU has staggering [1670% performance gain][3]. This would make the article more relevant today than it was before (more than six times).&#xD;&#xA;&#xD;&#xA;Now, using the biggest grid they tested with (GS, 128^3, page 7, table 2), GPU simulation was over 3000 times faster than the CPU simulation. Even if utilizing 4 cores (they were using only a single thread), it's still over 700-fold performance gain (back in the day, today that would go up to 5000-fold). Given the results for smaller grids, that difference would only increase with bigger grids than 128^3.&#xD;&#xA;&#xD;&#xA;The question is, along with all the normal rendering the GPU is tasked with doing, is it viable to burden it with the task of computing the simulation too, **in any case at all**?&#xD;&#xA;&#xD;&#xA;What's the use of rendering the graphics at 60FPS if fluid simulation runs at 10 steps per second, effectively making the game look like it's running at 10FPS? Wouldn't it be better if I rendered graphics at 30FPS, but could do the simulation at 30 steps per second as well?&#xD;&#xA;&#xD;&#xA;Basically, the question is, what would take longer:&#xD;&#xA;&#xD;&#xA; - For the GPU to render a frame AND compute the simulation step&#xD;&#xA;&#xD;&#xA;OR&#xD;&#xA;&#xD;&#xA; - For the CPU to compute rest of the game logic AND compute the simulation step.&#xD;&#xA;&#xD;&#xA;I know that this heavily depends on the GPU involved and the remainder of the GPU and CPU load, but look at the whole thing this way:&#xD;&#xA;&#xD;&#xA;Even if I used just 1% of the power of GPU, the speed would still be 7(50!) times greater than using the CPU.&#xD;&#xA;&#xD;&#xA;I'm a big novice in when it comes to computer graphics, so I may have gotten it all wrong. Does anything I wrote make any sense, or is it just gibberish?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.it.ubi.pt/17epcg/Actas/artigos/17epcg_submission_39.pdf&#xD;&#xA;  [2]: http://cpu.userbenchmark.com/Compare/Intel-Core2-Quad-Q6600-vs-Intel-Core-i5-6600K/1980vs3503&#xD;&#xA;  [3]: http://gpu.userbenchmark.com/Compare/Nvidia-GeForce-8800-GT-vs-Nvidia-GTX-1070/m7722vs3609" ContentLicense="CC BY-SA 3.0" />
  <row Id="8823" PostHistoryTypeId="2" PostId="4059" RevisionGUID="2904026b-db0a-4e75-aa07-0ee9f37978be" CreationDate="2016-10-02T08:41:23.423" UserId="5219" Text="I have a circular shape object, which I want to rotate like a fan along it's own axis.&#xD;&#xA;&#xD;&#xA;I can change the rotation in any direction i.e. dx, dy, dz using my transformation matrix.&#xD;&#xA;&#xD;&#xA;The following it's the code:&#xD;&#xA;&#xD;&#xA;     Matrix4f matrix = new Matrix4f();&#xD;&#xA;     matrix.setIdentity();&#xD;&#xA;     Matrix4f.translate(translation, matrix, matrix);&#xD;&#xA;     Matrix4f.rotate((float) Math.toRadians(rx), new Vector3f(1,0,0), matrix, matrix);&#xD;&#xA;     Matrix4f.rotate((float) Math.toRadians(ry), new Vector3f(0,1,0), matrix, matrix);&#xD;&#xA;     Matrix4f.rotate((float) Math.toRadians(rz), new Vector3f(0,0,1), matrix, matrix);&#xD;&#xA;     Matrix4f.scale(new Vector3f(scale,scale,scale), matrix, matrix);&#xD;&#xA;&#xD;&#xA;My vertex code:&#xD;&#xA;&#xD;&#xA;     vec4 worldPosition = transformationMatrix * vec4(position,1.0);&#xD;&#xA;     vec4 positionRelativeToCam = viewMatrix*worldPosition;&#xD;&#xA;     gl_Position = projectionMatrix *positionRelativeToCam;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Main Game Loop:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;     Object.increaseRotation(dxf,dyf,dzf);&#xD;&#xA;&#xD;&#xA;But, it's not rotating along it's own axis. What am I missing here? I want something like this. Please Help&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Like This][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/knBlT.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="8824" PostHistoryTypeId="1" PostId="4059" RevisionGUID="2904026b-db0a-4e75-aa07-0ee9f37978be" CreationDate="2016-10-02T08:41:23.423" UserId="5219" Text="Rotating an Object Around an Axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="8825" PostHistoryTypeId="3" PostId="4059" RevisionGUID="2904026b-db0a-4e75-aa07-0ee9f37978be" CreationDate="2016-10-02T08:41:23.423" UserId="5219" Text="|opengl|shader|transformations|mathematics|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8826" PostHistoryTypeId="2" PostId="4060" RevisionGUID="baf4e096-8ee0-4e2d-b6a6-6a0108ecf393" CreationDate="2016-10-02T11:27:23.680" UserId="3041" Text="Dithering increases percieved color depth by adding a &quot;noise&quot; to an image on transform from high color depth (e.g. 32-bit floating point) to lower color depth (e.g. 8-bit integer). A prerequisite is pixel density being high enough for the brain to &quot;blend&quot; multiple pixels together. It is also dependent on viewing distance. I´m most interested in phone or desktop workstation distance.&#xD;&#xA;&#xD;&#xA;As far as I know RGB8 (TrueColor, 16 million colors) is more than enough even without dithering for smooth gradients. RGB5 (HighColor, ~32k colors) requires dithering for gradients to look reasonably smooth, but I think pixel density start to really matter at this point. I´m not sure if RGB4 (~4k colors) or R3G3B2 (256 colors) can ever have smooth gradients but given high enough pixel density it should be possible.&#xD;&#xA;&#xD;&#xA;Is there any rule of thumb when it comes to pixel density / color channel depth ratio for a dithered image to appear having smooth gradients as percieved by the brain?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8827" PostHistoryTypeId="1" PostId="4060" RevisionGUID="baf4e096-8ee0-4e2d-b6a6-6a0108ecf393" CreationDate="2016-10-02T11:27:23.680" UserId="3041" Text="Pixel density / color channel depth ratio for dithered gradients" ContentLicense="CC BY-SA 3.0" />
  <row Id="8828" PostHistoryTypeId="3" PostId="4060" RevisionGUID="baf4e096-8ee0-4e2d-b6a6-6a0108ecf393" CreationDate="2016-10-02T11:27:23.680" UserId="3041" Text="|opengl-es|color-science|color-management|human-vision|theory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8829" PostHistoryTypeId="2" PostId="4061" RevisionGUID="c20c6fe3-79f7-4903-86dc-33359f5a4441" CreationDate="2016-10-02T13:18:46.230" UserId="4958" Text="Instead of &quot;stacking&quot; or overwriting these transformations on one matrix You might try do that using matrix multiplication:&#xD;&#xA;&#xD;&#xA;    Matrix4f translate = translate(translation,  new Matrix4F() /*identity*/);&#xD;&#xA;    Matrix4f rotateX = rotate((float) Math.toRadians(rx), new Vector3f(1,0,0), new Matrix4F());&#xD;&#xA;    Matrix4f scale = scale(new Vector3f(scale,scale,scale), new Matrix4F());&#xD;&#xA;    &#xD;&#xA;    Matrix4f transformation = translate*rotateX*scale;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8830" PostHistoryTypeId="5" PostId="4061" RevisionGUID="767ad5ef-5572-4e07-97e9-e15bdeb379d2" CreationDate="2016-10-02T13:29:50.337" UserId="4958" Comment="added 1 character in body" Text="Instead of &quot;stacking&quot; or overwriting these transformations on one matrix You may try doing that using matrix multiplication:&#xD;&#xA;&#xD;&#xA;    Matrix4f translate = translate(translation,  new Matrix4F() /*identity*/);&#xD;&#xA;    Matrix4f rotateX = rotate((float) Math.toRadians(rx), new Vector3f(1,0,0), new Matrix4F());&#xD;&#xA;    Matrix4f scale = scale(new Vector3f(scale,scale,scale), new Matrix4F());&#xD;&#xA;    &#xD;&#xA;    Matrix4f transformation = translate*rotateX*scale;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8831" PostHistoryTypeId="2" PostId="4062" RevisionGUID="a6c72a13-43f1-4104-aa13-7e6fcc1dc9c7" CreationDate="2016-10-02T13:40:34.237" UserId="1764" Text="Despite advancements modern GPUs still have fixed rasterizers. Highly customizable, with programmable shaders but nevertheless not fully programmable.&#xD;&#xA;&#xD;&#xA;Why is that?&#xD;&#xA;&#xD;&#xA;Why can't GPUs be simply massively parallel devices with universal computing units where rasterizer is just a software for that device provided by the user?&#xD;&#xA;&#xD;&#xA;Is having fixed function hardware so beneficial performance-wise that such approach is unfeasible?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8832" PostHistoryTypeId="1" PostId="4062" RevisionGUID="a6c72a13-43f1-4104-aa13-7e6fcc1dc9c7" CreationDate="2016-10-02T13:40:34.237" UserId="1764" Text="Why do GPUs still have rasterizers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8833" PostHistoryTypeId="3" PostId="4062" RevisionGUID="a6c72a13-43f1-4104-aa13-7e6fcc1dc9c7" CreationDate="2016-10-02T13:40:34.237" UserId="1764" Text="|gpu|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8834" PostHistoryTypeId="2" PostId="4063" RevisionGUID="4183b6e8-80de-41b4-bfd2-776d28c70bca" CreationDate="2016-10-02T17:46:42.837" UserId="2707" Text="In short, performance reasons are why they aren't programmable.&#xD;&#xA;&#xD;&#xA;# History and Market&#xD;&#xA;In the past, there used to be separate cores for vertex and fragment processors to avoid bloated FPU designs. There were some mathematical operations you could only do in fragment shader code for instance (because they were mostly only relevant for fragment shaders). This would produce severe hardware bottlenecks for applications that didn't max out the potential of each type of core.&#xD;&#xA;&#xD;&#xA;As programmable shaders became more popular, universal units were introduced. More and more stages of the graphics pipeline were implemented in hardware to help with scaling. During this time, GPGPU also became more popular, so vendors had to incorporate some of this functionality. It's still important to note though that the majority of the income from GPUs were still video games, so this couldn't interfere with performance.&#xD;&#xA;&#xD;&#xA;Eventually a big player, Intel, decided to invest in programmable rasterizers with their [Larrabee architecture][1]. This project was supposed to be groundbreaking, but the [performance was apparently less than desired][2]. It was shut down, and parts of it were salvaged for Xeon Phi processors. It's worth noting though that the other vendors haven't implemented this.&#xD;&#xA;&#xD;&#xA;# Attempts at Software Rasterizers&#xD;&#xA;There have been some attempts at rasterization through software, but they all seem to have issues with performance.&#xD;&#xA;&#xD;&#xA;One notable effort was an [attempt by Nvidia][3] in 2011 in this [paper][4]. This was released close to when Larrabee was terminated, so it's very possible that this was a response to that. Regardless, there are some performance figures in this, and most of them show performance multiple times slower than hardware rasterizers.&#xD;&#xA;&#xD;&#xA;# Technical Issues with Software Rasterization&#xD;&#xA;There are many issues that were faced in the Nvidia paper, but here are some that should apply to every GPU-accelerated software renderer:&#xD;&#xA;&#xD;&#xA;## Interpolation&#xD;&#xA;The hardware implementation generates interpolation equations in specialized hardware. This is slow for the software renderer since it had to be done in the fragment shader.&#xD;&#xA;&#xD;&#xA;## Anti-aliasing&#xD;&#xA;There were also performance issues with anti-aliasing (specifically with memory). Information regarding the sub-pixel samples must be stored on-chip memory, which isn't enough to hold this.&#xD;&#xA;&#xD;&#xA;# Summary&#xD;&#xA;TL;DR: there are too many inefficiencies that software rendering can't past, and these things add up. There are also many larger limitations, especially when you are dealing with VRAM bandwidth, synchronization problems, and extra computations.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Larrabee_(microarchitecture)&#xD;&#xA;  [2]: https://www.cnet.com/news/intel-initial-larrabee-graphics-chip-canceled/&#xD;&#xA;  [3]: http://highperformancegraphics.net/previous/www_2011/media/Papers/HPG2011_Papers_Laine.pdf&#xD;&#xA;  [4]: http://dl.acm.org/citation.cfm?id=2018337" ContentLicense="CC BY-SA 3.0" />
  <row Id="8835" PostHistoryTypeId="2" PostId="4064" RevisionGUID="fc0f6162-1d57-4bd7-8ee5-9936c63b04da" CreationDate="2016-10-02T18:04:59.303" UserId="2707" Text="# Mapping the Left and Right Sides&#xD;&#xA;This step should be trivial. If I remember correctly, the CMU database animation skeletons have easily identifiable bone names. If not then it's slightly less trivial. What you would have to do then would be to start at the root and go down each side. The bone structure should be the same for each animation though.&#xD;&#xA;&#xD;&#xA;# Create the Rotation Matrix&#xD;&#xA;You should have three Euler angles: X, Y, and Z. You first need to create a [rotation matrix][1] for each bone.&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;&#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Euler_angles_.28_z-y.E2.80.99-x.E2.80.B3_intrinsic.29_.E2.86.92_Rotation_matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="8836" PostHistoryTypeId="12" PostId="4064" RevisionGUID="84a81287-7e15-44bd-b30c-804d2fb69849" CreationDate="2016-10-02T18:05:04.717" UserId="2707" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2707,&quot;DisplayName&quot;:&quot;aces&quot;}]}" />
  <row Id="8837" PostHistoryTypeId="5" PostId="4064" RevisionGUID="e8762097-ba16-40e4-b25f-34d98158b1ac" CreationDate="2016-10-02T18:43:50.327" UserId="2707" Comment="Completed the answer this time" Text="# Mapping the Left and Right Sides&#xD;&#xA;This step should be trivial. If I remember correctly, the CMU database animation skeletons have easily identifiable bone names. If not, then it's slightly less trivial. What you would have to do then would be to start at the root and go down each side. The bone structure should be the same for each animation though.&#xD;&#xA;&#xD;&#xA;# Create the Rotation Matrix&#xD;&#xA;You should have three Euler angles: $X$, $Y$, and $Z$. You first need to create a [rotation matrix][1] for each bone. I use $\phi$ for $X$, $\theta$ for $Y$, and $\psi$ for $Z$ since this is a more common notation for matrix $R$. This is a right-handed matrix.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta)\cos(\psi) &amp;&#xD;&#xA;\cos(\phi)\sin(\psi) + \sin(\phi)\sin(\theta)\cos(\psi) &amp;&#xD;&#xA;\sin(\phi)\sin(\psi) - \cos(\phi)\sin(\theta)\cos(\psi) \\&#xD;&#xA;- \cos(\theta)\sin(\psi) &amp;&#xD;&#xA;\cos(\phi)\cos(\psi) - \sin(\phi)\sin(\theta)\sin(\psi) &amp;&#xD;&#xA;\sin(\phi)\cos(\psi) + \cos(\phi)\sin(\theta)\sin(\psi) \\&#xD;&#xA;\sin(\theta) &amp;&#xD;&#xA;- \sin(\phi)\cos(\theta) &amp;&#xD;&#xA;\cos(\phi)\cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Flip the Sides&#xD;&#xA;To flip the rotation matrix, you will need to multiply the axis you want to flip by $-1$. This is equivalent to [scaling in across that axis][2]. I will assume you want to scale across the x-axis for matrix $S$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;-1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Combine the Two Transforms&#xD;&#xA;Now just multiply these two matrices, and you get the opposite rotation:&#xD;&#xA;$$T = S \cdot R$$&#xD;&#xA;&#xD;&#xA;# Chain Together the Local Transforms&#xD;&#xA;Now you just need to apply forward kinematics, so you need to multiply each parent matrix by the local matrix to get an absolute transformation matrix.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Euler_angles_.28_z-y.E2.80.99-x.E2.80.B3_intrinsic.29_.E2.86.92_Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Scaling_(geometry)#Matrix_representation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8838" PostHistoryTypeId="13" PostId="4064" RevisionGUID="272816b5-db26-4298-a060-9c3f60dda9df" CreationDate="2016-10-02T19:08:16.350" UserId="2707" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2707,&quot;DisplayName&quot;:&quot;aces&quot;}]}" />
  <row Id="8839" PostHistoryTypeId="12" PostId="4064" RevisionGUID="3e5f39d2-459b-4f63-89a7-8bf64aedbf2e" CreationDate="2016-10-02T19:08:20.767" UserId="2707" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2707,&quot;DisplayName&quot;:&quot;aces&quot;}]}" />
  <row Id="8840" PostHistoryTypeId="13" PostId="4064" RevisionGUID="21dea045-4f5e-4df5-ab26-6334d629115d" CreationDate="2016-10-02T19:08:30.823" UserId="2707" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2707,&quot;DisplayName&quot;:&quot;aces&quot;}]}" />
  <row Id="8841" PostHistoryTypeId="5" PostId="4064" RevisionGUID="57828cff-b7d4-47fb-9de5-262e521682ac" CreationDate="2016-10-02T21:21:19.877" UserId="2707" Comment="edited body" Text="# Mapping the Left and Right Sides&#xD;&#xA;This step should be trivial. If I remember correctly, the CMU database animation skeletons have easily identifiable bone names. If not, then it's slightly less trivial. What you would have to do then would be to start at the root and go down each side. The bone structure should be the same for each animation though.&#xD;&#xA;&#xD;&#xA;# Create the Rotation Matrix&#xD;&#xA;You should have three Euler angles: $X$, $Y$, and $Z$. You first need to create a [rotation matrix][1] for each bone. I use $\phi$ for $X$, $\theta$ for $Y$, and $\psi$ for $Z$ since this is a more common notation for matrix $R$. This is a right-handed matrix.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta)\cos(\psi) &amp;&#xD;&#xA;\cos(\phi)\sin(\psi) + \sin(\phi)\sin(\theta)\cos(\psi) &amp;&#xD;&#xA;\sin(\phi)\sin(\psi) - \cos(\phi)\sin(\theta)\cos(\psi) \\&#xD;&#xA;- \cos(\theta)\sin(\psi) &amp;&#xD;&#xA;\cos(\phi)\cos(\psi) - \sin(\phi)\sin(\theta)\sin(\psi) &amp;&#xD;&#xA;\sin(\phi)\cos(\psi) + \cos(\phi)\sin(\theta)\sin(\psi) \\&#xD;&#xA;\sin(\theta) &amp;&#xD;&#xA;- \sin(\phi)\cos(\theta) &amp;&#xD;&#xA;\cos(\phi)\cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Flip the Sides&#xD;&#xA;To flip the rotation matrix, you will need to multiply the axis you want to flip by $-1$. This is equivalent to [scaling in across that axis][2]. I will assume you want to scale across the x-axis for matrix $S$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;-1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Combine the Two Transforms&#xD;&#xA;Now just multiply these two matrices, and you get the opposite rotation:&#xD;&#xA;$$T = R \cdot S$$&#xD;&#xA;&#xD;&#xA;# Chain Together the Local Transforms&#xD;&#xA;Now you just need to apply forward kinematics, so you need to multiply each parent matrix by the local matrix to get an absolute transformation matrix.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Euler_angles_.28_z-y.E2.80.99-x.E2.80.B3_intrinsic.29_.E2.86.92_Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Scaling_(geometry)#Matrix_representation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8842" PostHistoryTypeId="2" PostId="4065" RevisionGUID="1a083830-cc3a-471e-8898-dcf4989d046b" CreationDate="2016-10-03T00:10:43.707" UserId="5220" Text="I'm working on a webgl [audio visualizer][1] that uses particles, and I want to optimize rendering based on the user's hardware. I'd like to offer a &quot;low quality&quot; and &quot;high quality&quot; setting so that it works well on a wide-range of devices.&#xD;&#xA;&#xD;&#xA;Is there a way to automatically detect in the browser if the user has hardware acceleration available and generically whether their graphics card is good or not?&#xD;&#xA;&#xD;&#xA;What techniques are there for rendering low vs high quality? &#xD;&#xA;My initial ideas for low quality were:&#xD;&#xA;&#xD;&#xA; - render less geometry (less particles, and nearer &quot;far&quot; clipping distance)&#xD;&#xA; - use a smaller framebuffer and scale it up to the size of the canvas&#xD;&#xA; - smaller texture sizes&#xD;&#xA;&#xD;&#xA;**Edit**:&#xD;&#xA;Additionally, any resources on performance optimization would be appreciated. It seems that searches mostly result in helping users configure their graphic card settings&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://nickstanish.com/visual-audio-js/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8843" PostHistoryTypeId="1" PostId="4065" RevisionGUID="1a083830-cc3a-471e-8898-dcf4989d046b" CreationDate="2016-10-03T00:10:43.707" UserId="5220" Text="Optimizing performance on hardware" ContentLicense="CC BY-SA 3.0" />
  <row Id="8844" PostHistoryTypeId="3" PostId="4065" RevisionGUID="1a083830-cc3a-471e-8898-dcf4989d046b" CreationDate="2016-10-03T00:10:43.707" UserId="5220" Text="|performance|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8845" PostHistoryTypeId="5" PostId="4064" RevisionGUID="37223b32-4b78-418a-ac4d-f10574eb2fef" CreationDate="2016-10-03T03:04:06.853" UserId="2707" Comment="deleted 7 characters in body" Text="# Mapping the Left and Right Sides&#xD;&#xA;This step should be trivial. If I remember correctly, the CMU database animation skeletons have easily identifiable bone names. If not, then it's slightly less trivial. What you would have to do then would be to start at the root and go down each side. The bone structure should be the same for each animation though.&#xD;&#xA;&#xD;&#xA;# Create the Rotation Matrix&#xD;&#xA;You should have three Euler angles: $X$, $Y$, and $Z$. You first need to create a [rotation matrix][1] for each bone. I use $\phi$ for $X$, $\theta$ for $Y$, and $\psi$ for $Z$ since this is a more common notation for matrix $R$. This is a right-handed matrix.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta)\cos(\psi) &amp;&#xD;&#xA;\cos(\phi)\sin(\psi) + \sin(\phi)\sin(\theta)\cos(\psi) &amp;&#xD;&#xA;\sin(\phi)\sin(\psi) - \cos(\phi)\sin(\theta)\cos(\psi) \\&#xD;&#xA;- \cos(\theta)\sin(\psi) &amp;&#xD;&#xA;\cos(\phi)\cos(\psi) - \sin(\phi)\sin(\theta)\sin(\psi) &amp;&#xD;&#xA;\sin(\phi)\cos(\psi) + \cos(\phi)\sin(\theta)\sin(\psi) \\&#xD;&#xA;\sin(\theta) &amp;&#xD;&#xA;- \sin(\phi)\cos(\theta) &amp;&#xD;&#xA;\cos(\phi)\cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Flip the Sides&#xD;&#xA;To flip the rotation matrix, you will need to multiply the axis you want to flip by $-1$. This is equivalent to [scaling in across that axis][2]. I will assume you want to scale across the x-axis for matrix $S$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;-1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Combine the Two Transforms&#xD;&#xA;Now just multiply these two matrices, and you get the opposite rotation:&#xD;&#xA;$$T = RS$$&#xD;&#xA;&#xD;&#xA;# Chain Together the Local Transforms&#xD;&#xA;Now you just need to apply forward kinematics, so you need to multiply each parent matrix by the local matrix to get an absolute transformation matrix.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Euler_angles_.28_z-y.E2.80.99-x.E2.80.B3_intrinsic.29_.E2.86.92_Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Scaling_(geometry)#Matrix_representation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8846" PostHistoryTypeId="5" PostId="4064" RevisionGUID="e6311da3-5f3f-4c3a-ac36-5d88f2b00d23" CreationDate="2016-10-03T03:16:27.113" UserId="2707" Comment="Made the multiplication clearer" Text="# Mapping the Left and Right Sides&#xD;&#xA;This step should be trivial. If I remember correctly, the CMU database animation skeletons have easily identifiable bone names. If not, then it's slightly less trivial. What you would have to do then would be to start at the root and go down each side. The bone structure should be the same for each animation though.&#xD;&#xA;&#xD;&#xA;# Create the Rotation Matrix&#xD;&#xA;You should have three Euler angles: $X$, $Y$, and $Z$. You first need to create a [rotation matrix][1] for each bone. I use $\phi$ for $X$, $\theta$ for $Y$, and $\psi$ for $Z$ since this is a more common notation for matrix $R$. This is a right-handed matrix.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta)\cos(\psi) &amp;&#xD;&#xA;\cos(\phi)\sin(\psi) + \sin(\phi)\sin(\theta)\cos(\psi) &amp;&#xD;&#xA;\sin(\phi)\sin(\psi) - \cos(\phi)\sin(\theta)\cos(\psi) \\&#xD;&#xA;- \cos(\theta)\sin(\psi) &amp;&#xD;&#xA;\cos(\phi)\cos(\psi) - \sin(\phi)\sin(\theta)\sin(\psi) &amp;&#xD;&#xA;\sin(\phi)\cos(\psi) + \cos(\phi)\sin(\theta)\sin(\psi) \\&#xD;&#xA;\sin(\theta) &amp;&#xD;&#xA;- \sin(\phi)\cos(\theta) &amp;&#xD;&#xA;\cos(\phi)\cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Flip the Sides&#xD;&#xA;To flip the rotation matrix, you will need to multiply the axis you want to flip by $-1$. This is equivalent to [scaling in across that axis][2]. I will assume you want to scale across the x-axis for matrix $S$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;-1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;# Combine the Two Transforms&#xD;&#xA;Now just multiply these two matrices, and you get the opposite rotation:&#xD;&#xA;$$T = R \times S$$&#xD;&#xA;&#xD;&#xA;# Chain Together the Local Transforms&#xD;&#xA;Now you just need to apply forward kinematics, so you need to multiply each parent matrix by the local matrix to get an absolute transformation matrix.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions#Euler_angles_.28_z-y.E2.80.99-x.E2.80.B3_intrinsic.29_.E2.86.92_Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Scaling_(geometry)#Matrix_representation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8848" PostHistoryTypeId="2" PostId="4066" RevisionGUID="59e2c545-4c1e-4a9e-ae86-5e8213ef86f1" CreationDate="2016-10-03T09:03:18.540" UserId="5222" Text="DX12 introduces a new feature of pipeline named 'Bundle'. It seems that can optimize the command list, and send it to final pipeline. Vulkan invent some different pipeline: The graphic pipeline and the compute pipeline. The graphic pipeline seems just the same with the original, the compute pipeline is used as an accessor of image memory.&#xD;&#xA;&#xD;&#xA;My CG knowledge is pretty basic, and can not confirm that cognition is correct. Would someone kindly provide some explanations for it - The main difference of pipelines between them ?&#xD;&#xA;&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA; - https://msdn.microsoft.com/zh-cn/library/mt617309&#xD;&#xA; - https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#pipelines" ContentLicense="CC BY-SA 3.0" />
  <row Id="8849" PostHistoryTypeId="1" PostId="4066" RevisionGUID="59e2c545-4c1e-4a9e-ae86-5e8213ef86f1" CreationDate="2016-10-03T09:03:18.540" UserId="5222" Text="What's the main difference of pipeline process between Vulkan and DX12?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8850" PostHistoryTypeId="3" PostId="4066" RevisionGUID="59e2c545-4c1e-4a9e-ae86-5e8213ef86f1" CreationDate="2016-10-03T09:03:18.540" UserId="5222" Text="|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8852" PostHistoryTypeId="2" PostId="4067" RevisionGUID="c6b82ea5-e9ae-4d2c-a0d9-54ef58747d52" CreationDate="2016-10-03T12:31:13.210" UserId="2372" Text="I am currently trying to implement a specific directional light type.&#xD;&#xA;&#xD;&#xA;This light type has been used in the game INSIDE and is called orthogonal spotlight (aka local directional light). I assume that this is a directional light which behaves like a spot light and have a squared or rectangular attenuation but I have some difficulties to integrate it in my deferred pipeline and get the general concept of this light type.&#xD;&#xA;&#xD;&#xA;I hope that you'll be able to give me some clues.&#xD;&#xA;Thanks a lot !" ContentLicense="CC BY-SA 3.0" />
  <row Id="8853" PostHistoryTypeId="1" PostId="4067" RevisionGUID="c6b82ea5-e9ae-4d2c-a0d9-54ef58747d52" CreationDate="2016-10-03T12:31:13.210" UserId="2372" Text="Special directional light type" ContentLicense="CC BY-SA 3.0" />
  <row Id="8854" PostHistoryTypeId="3" PostId="4067" RevisionGUID="c6b82ea5-e9ae-4d2c-a0d9-54ef58747d52" CreationDate="2016-10-03T12:31:13.210" UserId="2372" Text="|shader|glsl|lighting|hlsl|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8856" PostHistoryTypeId="6" PostId="4066" RevisionGUID="e7953cb8-4cb3-4353-a85e-a05df61c8277" CreationDate="2016-10-03T13:08:03.037" UserId="16" Comment="edited tags" Text="|directx12|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8857" PostHistoryTypeId="5" PostId="4067" RevisionGUID="939951b6-a69d-4620-832f-ac305a17db59" CreationDate="2016-10-03T14:26:30.907" UserId="2372" Comment="added 90 characters in body" Text="I am currently trying to implement a specific directional light type.&#xD;&#xA;&#xD;&#xA;This light type has been used in the game INSIDE and is called orthogonal spotlight (aka local directional light). I assume that this is a directional light which behaves like a spot light and have a squared or rectangular attenuation but I have some difficulties to integrate it in my deferred pipeline and get the general concept of this light type.&#xD;&#xA;&#xD;&#xA;Classical directional light : `dot(worldNormal, lightDir)`&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I hope that you'll be able to give me some clues.&#xD;&#xA;Thanks a lot !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Vbbur.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8858" PostHistoryTypeId="2" PostId="4068" RevisionGUID="ff71b70e-74d5-49f8-a1a6-3078f28ed899" CreationDate="2016-10-03T14:54:41.397" UserId="5225" Text="From Gortler's *Foundations of Computer Graphics* (i.e., self-study):&#xD;&#xA;&#xD;&#xA;&gt; Let $\mathbf{\vec{e}}^t = \mathbf{\vec{w}}^t E$ and let $P$ be a camera matrix that is just some arbitrary $4$ by $4$ matrix with &quot;dashes&quot; in its 3rd row. Given the world coordinates of 6 points in space as well as their normalized device coordinates, how would one compute the 12 unknown entries in the matrix $PE^{-1}$? (Note: this can only be solved up to an unknown scale factor) (Hint: set up an appropriate homogeneous linear system with a right hand side of zero).&#xD;&#xA;&#xD;&#xA;Here the &quot;dashes&quot; matrix the author refers to takes form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;n_1 &amp; 0 &amp; a &amp; 0 \\&#xD;&#xA;0 &amp; n_2 &amp; b &amp; 0 \\&#xD;&#xA;- &amp; - &amp; - &amp; - \\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where we do not care what the values with dashes are. How does one use the hint to solve this problem? I think we can infer that $a$ and $b$ (the scale factors) are undetermined, but that we can infer what the $n_1$ and $n_2$ are." ContentLicense="CC BY-SA 3.0" />
  <row Id="8859" PostHistoryTypeId="1" PostId="4068" RevisionGUID="ff71b70e-74d5-49f8-a1a6-3078f28ed899" CreationDate="2016-10-03T14:54:41.397" UserId="5225" Text="Solving a problem from *Foundations of Computer Graphics*:" ContentLicense="CC BY-SA 3.0" />
  <row Id="8860" PostHistoryTypeId="3" PostId="4068" RevisionGUID="ff71b70e-74d5-49f8-a1a6-3078f28ed899" CreationDate="2016-10-03T14:54:41.397" UserId="5225" Text="|projections|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8861" PostHistoryTypeId="5" PostId="4060" RevisionGUID="95eb07d4-3b67-4d94-ba39-a42535d3657f" CreationDate="2016-10-03T16:27:42.773" UserId="3041" Comment="Rewrote RGB8 to require dither for smooth gradient" Text="Dithering increases percieved color depth by adding a &quot;noise&quot; to an image on transform from high color depth (e.g. 32-bit floating point) to lower color depth (e.g. 8-bit integer). A prerequisite is pixel density being high enough for the brain to &quot;blend&quot; multiple pixels together. It is also dependent on viewing distance. I´m most interested in phone or desktop workstation distance. Dithering algorithm also matters but for the sake of the question lets assume it is &quot;perfect&quot;.&#xD;&#xA;&#xD;&#xA;RGB8 (TrueColor, 16 million colors) requires dithering for nice smooth gradients and tend to get really nice for your average monitor. RGB5 (HighColor, ~32k colors) requires dithering for gradients to look nearly smooth, but I think pixel density start to really matter at this point. I´m not sure if RGB4 (~4k colors) or R3G3B2 (256 colors) can ever have smooth gradients but given high enough pixel density it should be possible.&#xD;&#xA;&#xD;&#xA;Is there any rule of thumb when it comes to pixel density / color channel depth ratio for a dithered image to appear having smooth gradients as percieved by the brain?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8862" PostHistoryTypeId="5" PostId="392" RevisionGUID="1a102362-097a-4e14-b054-ee39abd06085" CreationDate="2016-10-03T18:00:25.803" UserId="482" Comment="add note for reflection under scaling" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b \\ c&amp;d\end{bmatrix}&#xD;&#xA;+&#xD;&#xA;\begin{bmatrix}e&amp; f\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair $(x', y')$ from the original pair $(x, y)$ and a list of constants $(a, b, c, d, e, f)$.&#xD;&#xA;$$&#xD;&#xA;    x' =  a\cdot x + c\cdot y + e \\&#xD;&#xA;    y' =  b\cdot x + d\cdot y + f&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'&amp;1\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}x''&amp; y''&amp;1\end{bmatrix}&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}\right)&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}a \cdot x + c \cdot y+e &amp; b \cdot x + d \cdot y+f &amp;1 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}g(a \cdot x + c \cdot y+e) + i( b \cdot x + d \cdot y+f) + k &#xD;&#xA;\\&#xD;&#xA;h(a \cdot x + c \cdot y+e) + j( b \cdot x + d \cdot y+f) + m&#xD;&#xA;\\1 \end{bmatrix}^T&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\right)&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\begin{bmatrix}ag+bi&amp; ah+bj &amp;0\\ cg+di&amp;ch+dj&amp;0 \\ eg+fi+k&amp;eh+fj+m&amp;1\end{bmatrix}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    S_x &amp; 0 &amp; 0 \\&#xD;&#xA;    0  &amp; S_y &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;*Note: a reflection can be performed with scaling parameters $(S_x, S_y) = (-1,1)$ or $(1,-1)$.&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    T_x &amp; T_y &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; 0 &amp; 0 \\&#xD;&#xA;    Q_y &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    \cos\theta &amp; -sin\theta &amp; 0\\&#xD;&#xA;    \sin\theta &amp; \cos\theta &amp; 0\\&#xD;&#xA;    0  &amp;  0 &amp;  1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;A matrix composed purely from scaling, rotation, and translation can be [decomposed back into these three components](http://stackoverflow.com/a/11942636/733077).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8863" PostHistoryTypeId="2" PostId="4069" RevisionGUID="736aa665-a552-46d9-bc3b-33e4db769ee7" CreationDate="2016-10-03T22:06:50.603" UserId="116" Text="I was reading [this article](http://www.3dgep.com/understanding-the-view-matrix/) and found something that caught my attention.&#xD;&#xA;They say they are using column-major for their matrices so, in the code they have under the section **Look At Camera** they construct the orientation and translation.&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;R=\begin{bmatrix}r_x &amp; u_x &amp; f_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; f_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; f_z &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;T=\begin{bmatrix}0 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0&amp; 0&amp; 0&amp; 0 \\&#xD;&#xA;0&amp; 0&amp; 0&amp; 0 \\&#xD;&#xA;-e_x&amp; -e_y &amp; -e_z &amp; 1\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;RT_1 = \begin{bmatrix}r_x &amp; u_x &amp; f_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; f_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; f_z &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}\begin{bmatrix}0 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0&amp; 0&amp; 0&amp; 0 \\&#xD;&#xA;0&amp; 0&amp; 0&amp; 0 \\&#xD;&#xA;-e_x&amp; -e_y &amp; -e_z &amp; 1\end{bmatrix}=\begin{bmatrix}r_x &amp; u_x &amp; f_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; f_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; f_z &amp; 0 \\&#xD;&#xA;-e_x&amp; -e_y &amp; -e_z &amp; 1\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;They say this could be optimized if instead of doing the matrix multiplication we set the last row to be the dot product between camera position and the $\vec{r}, \vec{u} $ and $\vec{f}$ vectors.&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;RT_2 = \begin{bmatrix}r_x &amp; u_x &amp; f_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; f_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; f_z &amp; 0 \\&#xD;&#xA;-&lt;\vec{r}, \vec{e}&gt;&amp; -&lt;\vec{u}, \vec{e}&gt; &amp; -&lt;\vec{f}, \vec{e}&gt; &amp; 1\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;How is this possible? I don't see how $RT_1 = RT_2$ could give the same matrix. What am I missing? The only way I can see this is true is inverting the order of multiplication, i.e. $TR$" ContentLicense="CC BY-SA 3.0" />
  <row Id="8864" PostHistoryTypeId="1" PostId="4069" RevisionGUID="736aa665-a552-46d9-bc3b-33e4db769ee7" CreationDate="2016-10-03T22:06:50.603" UserId="116" Text="Building a lookat camera matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="8865" PostHistoryTypeId="3" PostId="4069" RevisionGUID="736aa665-a552-46d9-bc3b-33e4db769ee7" CreationDate="2016-10-03T22:06:50.603" UserId="116" Text="|affine-transformations|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8869" PostHistoryTypeId="2" PostId="4071" RevisionGUID="0b33e6b1-5835-4a7c-845c-77a3efc2bf5c" CreationDate="2016-10-03T23:50:00.410" UserId="231" Text="Although you may be able to detect what hardware is available as a first approximation of a computer's capability, depending on this might not be useful since the same hardware may behave differently depending on the machine it is hosted in, and any other tasks that may be competing for it.&#xD;&#xA;&#xD;&#xA;# Use the frame rate&#xD;&#xA;&#xD;&#xA;It looks like you are already measuring the frame rate, so you could simply use this value to decide which features to include. If you settle on a target frame rate, then you can order your features from most essential to most optional, and gradually add in less essential features for as long as the target frame rate is exceeded.&#xD;&#xA;&#xD;&#xA;You could also remove features in reverse order if the frame rate drops (in order to avoid poor frame rate if the available resources change). If you decide to do this, I recommend setting the target frame rate to a slightly different value for adding and removing features. Otherwise some machines near the border between two feature levels may end up skipping back and for between the two levels, adding and removing that feature endlessly. So set the trigger for removing a feature at a  slightly lower frame rate than the trigger for adding it.&#xD;&#xA;&#xD;&#xA;You'll need to find a compromise between adding new features too quickly so that the frame rate suddenly drops further than you intended, and adding features too slowly so that there are several seconds of low quality animation before it settles on the appropriate level of features. You may be able to estimate that some features can be added 2 or 3 at a time if the frame rate is already very far above target. This will depend on the specific features involved and may take some trial and error on a variety of machines with different resources.&#xD;&#xA;&#xD;&#xA;If you prefer, you can show a blank background until the frame rate has settled, so the user does not see the feature level being adjusted. Alternatively you may be able to adjust the features sufficiently gradually that there will be no perceptible change in any given moment.&#xD;&#xA;&#xD;&#xA;# Consider the window size&#xD;&#xA;&#xD;&#xA;On my laptop I get 4 frames per second consistently regardless of the window size - whether full screen or a thumbnail sized browser window. Since it appears that the particles move only away from the centre, and do not contribute later to the area they have left, it might be worth considering abandoning particles sooner when the window size is reduced. If this allows a higher frame rate when the window size is reduced, then the extra features will be automatically activated even if they were not possible at full screen." ContentLicense="CC BY-SA 3.0" />
  <row Id="8870" PostHistoryTypeId="5" PostId="4063" RevisionGUID="4f5e916e-42d8-4c5c-9ba4-3f9b1da0e5f1" CreationDate="2016-10-04T03:42:57.833" UserId="2707" Comment="Incorporated suggestions and clarified technical aspects" Text="In short, performance reasons are why they aren't programmable.&#xD;&#xA;&#xD;&#xA;# History and Market&#xD;&#xA;In the past, there used to be separate cores for vertex and fragment processors to avoid bloated FPU designs. There were some mathematical operations you could only do in fragment shader code for instance (because they were mostly only relevant for fragment shaders). This would produce severe hardware bottlenecks for applications that didn't max out the potential of each type of core.&#xD;&#xA;&#xD;&#xA;As programmable shaders became more popular, universal units were introduced. More and more stages of the graphics pipeline were implemented in hardware to help with scaling. During this time, GPGPU also became more popular, so vendors had to incorporate some of this functionality. It's still important to note though that the majority of the income from GPUs were still video games, so this couldn't interfere with performance.&#xD;&#xA;&#xD;&#xA;Eventually a big player, Intel, decided to invest in programmable rasterizers with their [Larrabee architecture][1]. This project was supposed to be groundbreaking, but the [performance was apparently less than desired][2]. It was shut down, and parts of it were salvaged for Xeon Phi processors. It's worth noting though that the other vendors haven't implemented this.&#xD;&#xA;&#xD;&#xA;# Attempts at Software Rasterizers&#xD;&#xA;There have been some attempts at rasterization through software, but they all seem to have issues with performance.&#xD;&#xA;&#xD;&#xA;One notable effort was an [attempt by Nvidia][3] in 2011 in this [paper][4]. This was released close to when Larrabee was terminated, so it's very possible that this was a response to that. Regardless, there are some performance figures in this, and most of them show performance multiple times slower than hardware rasterizers.&#xD;&#xA;&#xD;&#xA;# Technical Issues with Software Rasterization&#xD;&#xA;There are many issues that were faced in the Nvidia paper, but here are what seemed to be the most important that should apply to every GPU-accelerated software renderer:&#xD;&#xA;&#xD;&#xA;## Major Issues&#xD;&#xA;&#xD;&#xA;* **Interpolation:**&#xD;&#xA;The hardware implementation generates interpolation equations in specialized hardware. This is slow for the software renderer since it had to be done in the fragment shader.&#xD;&#xA;&#xD;&#xA;* **Anti-aliasing:**&#xD;&#xA;There were also performance issues with anti-aliasing (specifically with memory). Information regarding the sub-pixel samples must be stored on-chip memory, which isn't enough to hold this. Julien Guertault pointed out that the texture cache/cache is slower with software. MSAA certainly has issues here because it overflows the cache (the non-texture caches) and goes into memory off of the chip. Rasterizers compress data that is stored in that memory, which also helps with performance here.&#xD;&#xA;&#xD;&#xA;* **Power Consumption:**&#xD;&#xA;Simon F pointed out that power consumption would be lower. The paper did mention that custom ALUs are in rasterizers (which would reduce power consumption), and this would make sense since fragment and vertex processing units in the past used to have custom instruction sets (so likely custom ALUs as well). It certainly would be a bottleneck in many systems (e.g., mobile), although this has implications beyond performance.&#xD;&#xA;&#xD;&#xA;# Summary&#xD;&#xA;TL;DR: there are too many inefficiencies that software rendering can't past, and these things add up. There are also many larger limitations, especially when you are dealing with VRAM bandwidth, synchronization problems, and extra computations.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Larrabee_(microarchitecture)&#xD;&#xA;  [2]: https://www.cnet.com/news/intel-initial-larrabee-graphics-chip-canceled/&#xD;&#xA;  [3]: http://highperformancegraphics.net/previous/www_2011/media/Papers/HPG2011_Papers_Laine.pdf&#xD;&#xA;  [4]: http://dl.acm.org/citation.cfm?id=2018337" ContentLicense="CC BY-SA 3.0" />
  <row Id="8871" PostHistoryTypeId="5" PostId="4063" RevisionGUID="3e0f05ed-706b-4fbd-bb1c-a9cde81119f5" CreationDate="2016-10-04T03:48:23.173" UserId="2707" Comment="added 4 characters in body" Text="In short, performance reasons are why they aren't programmable.&#xD;&#xA;&#xD;&#xA;# History and Market&#xD;&#xA;In the past, there used to be separate cores for vertex and fragment processors to avoid bloated FPU designs. There were some mathematical operations you could only do in fragment shader code for instance (because they were mostly only relevant for fragment shaders). This would produce severe hardware bottlenecks for applications that didn't max out the potential of each type of core.&#xD;&#xA;&#xD;&#xA;As programmable shaders became more popular, universal units were introduced. More and more stages of the graphics pipeline were implemented in hardware to help with scaling. During this time, GPGPU also became more popular, so vendors had to incorporate some of this functionality. It's still important to note though that the majority of the income from GPUs were still video games, so this couldn't interfere with performance.&#xD;&#xA;&#xD;&#xA;Eventually a big player, Intel, decided to invest in programmable rasterizers with their [Larrabee architecture][1]. This project was supposed to be groundbreaking, but the [performance was apparently less than desired][2]. It was shut down, and parts of it were salvaged for Xeon Phi processors. It's worth noting though that the other vendors haven't implemented this.&#xD;&#xA;&#xD;&#xA;# Attempts at Software Rasterizers&#xD;&#xA;There have been some attempts at rasterization through software, but they all seem to have issues with performance.&#xD;&#xA;&#xD;&#xA;One notable effort was an [attempt by Nvidia][3] in 2011 in this [paper][4]. This was released close to when Larrabee was terminated, so it's very possible that this was a response to that. Regardless, there are some performance figures in this, and most of them show performance multiple times slower than hardware rasterizers.&#xD;&#xA;&#xD;&#xA;# Technical Issues with Software Rasterization&#xD;&#xA;There are many issues that were faced in the Nvidia paper, but here are what seemed to be the most important that should apply to every GPU-accelerated software renderer:&#xD;&#xA;&#xD;&#xA;## Major Issues&#xD;&#xA;&#xD;&#xA;* **Interpolation:**&#xD;&#xA;The hardware implementation generates interpolation equations in specialized hardware. This is slow for the software renderer since it had to be done in the fragment shader.&#xD;&#xA;&#xD;&#xA;* **Anti-aliasing:**&#xD;&#xA;There were also performance issues with anti-aliasing (specifically with memory). Information regarding the sub-pixel samples must be stored on-chip memory, which isn't enough to hold this. Julien Guertault pointed out that the texture cache/cache may be slower with software. MSAA certainly has issues here because it overflows the cache (the non-texture caches) and goes into memory off of the chip. Rasterizers compress data that is stored in that memory, which also helps with performance here.&#xD;&#xA;&#xD;&#xA;* **Power Consumption:**&#xD;&#xA;Simon F pointed out that power consumption would be lower. The paper did mention that custom ALUs are in rasterizers (which would reduce power consumption), and this would make sense since fragment and vertex processing units in the past used to have custom instruction sets (so likely custom ALUs as well). It certainly would be a bottleneck in many systems (e.g., mobile), although this has implications beyond performance.&#xD;&#xA;&#xD;&#xA;# Summary&#xD;&#xA;TL;DR: there are too many inefficiencies that software rendering can't past, and these things add up. There are also many larger limitations, especially when you are dealing with VRAM bandwidth, synchronization problems, and extra computations.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Larrabee_(microarchitecture)&#xD;&#xA;  [2]: https://www.cnet.com/news/intel-initial-larrabee-graphics-chip-canceled/&#xD;&#xA;  [3]: http://highperformancegraphics.net/previous/www_2011/media/Papers/HPG2011_Papers_Laine.pdf&#xD;&#xA;  [4]: http://dl.acm.org/citation.cfm?id=2018337" ContentLicense="CC BY-SA 3.0" />
  <row Id="8872" PostHistoryTypeId="2" PostId="4072" RevisionGUID="6ecc75ce-b5da-4d69-82aa-63da370085bb" CreationDate="2016-10-04T03:51:52.100" UserId="120" Text="Let me try to make my comment into a complete answer.&#xD;&#xA;&#xD;&#xA;The general idea is to build a linear system using those 6 point pairs and solve for the desired 12 unknowns.&#xD;&#xA;You may find this paper[1] useful if you want to learn the theoretical background,&#xD;&#xA;and you can find some more details in my blog post[2].&#xD;&#xA;&#xD;&#xA;Here is my solution using Mathematica.&#xD;&#xA;&#xD;&#xA;In the first step I will build a symbolic array which contains all variables.&#xD;&#xA;&#xD;&#xA;    v = Table[Symbol[&quot;m&quot; &lt;&gt; ToString[i]], {i, 0, 15}];&#xD;&#xA;    M = ArrayReshape[v, {4, 4}]&#xD;&#xA;&#xD;&#xA;Next we write down the coordinates for all vertices.&#xD;&#xA;&#xD;&#xA;    k = f/ n;&#xD;&#xA;&#xD;&#xA;    X = {&#xD;&#xA;        {l, t, -n, 1},&#xD;&#xA;        {l, b, -n, 1},&#xD;&#xA;        {r, b, -n, 1},&#xD;&#xA;        {r, t, -n, 1},&#xD;&#xA;        {k l, k t, -f, 1},&#xD;&#xA;        {k l, k b, -f, 1},&#xD;&#xA;        {k r, k b, -f, 1},&#xD;&#xA;        {k r, k t, -f, 1}};&#xD;&#xA;&#xD;&#xA;    U = {&#xD;&#xA;        {-1, 1, -1},&#xD;&#xA;        {-1, -1, -1},&#xD;&#xA;        {1, -1, -1},&#xD;&#xA;        {1, 1, -1},&#xD;&#xA;        {-1, 1, 1},&#xD;&#xA;        {-1, -1, 1},&#xD;&#xA;        {1, -1, 1},&#xD;&#xA;        {1, 1, 1}};&#xD;&#xA;&#xD;&#xA;where `l`,`r`,`b`,`t`,`n`,and `f` denote left, right, bottom, top, near, and far planes respectively,&#xD;&#xA;and 'X' is the coordinates in world space, `U` is the coordinates in NDC.&#xD;&#xA;&#xD;&#xA;Then next we implement a function `Generate` to generate an equation for each pair of coordinates:&#xD;&#xA;&#xD;&#xA;    Generate[{i_, j_}] := M[[j]].X[[i]] - U[[i, j]] M[[4]].X[[i]] == 0;&#xD;&#xA;&#xD;&#xA;Because we do not care about the third row,&#xD;&#xA;we only solve for the unknowns in `partialv`:&#xD;&#xA;&#xD;&#xA;    partialv = {m0, m1, m2, m3, m4, m5, m6, m7, m12, m13, m14, m15};&#xD;&#xA;&#xD;&#xA;Now we can build our linear system and solve it:&#xD;&#xA;&#xD;&#xA;    solve[subset_] := Solve[&#xD;&#xA;        Map[Generate, Table[{i, j}, {i, subset}, {j, 1, 2}], {2}] // Flatten,&#xD;&#xA;        partialv] // Simplify&#xD;&#xA;&#xD;&#xA;Let me explain it a little bit.&#xD;&#xA;&#xD;&#xA;Because only 6 pairs of points are given, we select a `subset` of 6 elements from the 8 pairs of points.&#xD;&#xA;Then we call `Generate` function on this `subset`&#xD;&#xA;and the first two rows of matrix(we do not care about the third row. And the fourth row is the &quot;homogeneous&quot; part, which is also ignored).&#xD;&#xA;&#xD;&#xA;Finally we enumerate all subsets from these 8 pairs of points, and try to find a solution:&#xD;&#xA;&#xD;&#xA;    solutions = Map[solve, Subsets[{1, 2, 3, 4, 5, 6, 7, 8}, {6}]];&#xD;&#xA;&#xD;&#xA;We can view one solution by:&#xD;&#xA;&#xD;&#xA;    MatrixForm[ArrayReshape[v /. solutions[[1]], {4, 4}]]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA; \text{m0} &amp; 0 &amp; \frac{\text{m0} (l+r)}{2 n} &amp; 0 \\&#xD;&#xA; 0 &amp; \frac{\text{m0} (l-r)}{b-t} &amp; \frac{\text{m0} (l-r) (b+t)}{2 n (b-t)} &amp; 0 \\&#xD;&#xA; \text{m8} &amp; \text{m9} &amp; \text{m10} &amp; \text{m11} \\&#xD;&#xA; 0 &amp; 0 &amp; \frac{\text{m0} (l-r)}{2 n} &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The `m0` is the &quot;unknown scalar factor&quot; which is mentioned in problem statement.&#xD;&#xA;&#xD;&#xA;In fact if we let `m0` equals `2 n/(r - l)`,&#xD;&#xA;we would get the conventional projection matrix used in OpenGL:&#xD;&#xA;&#xD;&#xA;    % /. m0 -&gt; 2 n/(r - l)&#xD;&#xA;    % // Simplify // MatrixForm&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA; \frac{2 n}{r-l} &amp; 0 &amp; \frac{l+r}{r-l} &amp; 0 \\&#xD;&#xA; 0 &amp; -\frac{2 n}{b-t} &amp; -\frac{b+t}{b-t} &amp; 0 \\&#xD;&#xA; \text{m8} &amp; \text{m9} &amp; \text{m10} &amp; \text{m11} \\&#xD;&#xA; 0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;[1] Heckbert, Paul S. Fundamentals of texture mapping and image warping. MS thesis. University of California, Berkeley, 1989.&#xD;&#xA;&#xD;&#xA;[2] Inferring projective mappings http://blog.linearconstraints.net/2016/02/03/inferring-projective-mappings.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="8876" PostHistoryTypeId="2" PostId="4074" RevisionGUID="4bb1e3c6-4df5-4afd-a96e-12ec58b93934" CreationDate="2016-10-04T11:34:32.513" UserId="120" Text="Because all matrices are column-major,&#xD;&#xA;the translation matrix $\mathbf{T}$ should be&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{T}=\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_x \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_y \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_z \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I thought you mistakenly treat the `eye` as a row vector just because they were written as a single line in the source code&#xD;&#xA;&#xD;&#xA;    mat4 translation = {&#xD;&#xA;        vec4(   1,      0,      0,   0 ),&#xD;&#xA;        vec4(   0,      1,      0,   0 ), &#xD;&#xA;        vec4(   0,      0,      1,   0 ),&#xD;&#xA;        vec4(-eye.x, -eye.y, -eye.z, 1 )&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Another issue in that the names of variables are misleading:&#xD;&#xA;the `orientation` denotes $\mathbf{R}^{-1}$, and the `translation` denotes $\mathbf{T}^{-1}$." ContentLicense="CC BY-SA 3.0" />
  <row Id="8877" PostHistoryTypeId="5" PostId="4074" RevisionGUID="2232d9ea-7b05-4d96-8340-97185bb75b23" CreationDate="2016-10-04T11:45:04.640" UserId="120" Comment="added 382 characters in body" Text="Because all matrices are column-major,&#xD;&#xA;the translation matrix $\mathbf{T}$ should be&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{T}=\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_x \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_y \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_z \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I thought you mistakenly treat the `eye` as a row vector just because they were written as a single line in the source code&#xD;&#xA;&#xD;&#xA;    mat4 translation = {&#xD;&#xA;        vec4(   1,      0,      0,   0 ),&#xD;&#xA;        vec4(   0,      1,      0,   0 ), &#xD;&#xA;        vec4(   0,      0,      1,   0 ),&#xD;&#xA;        vec4(-eye.x, -eye.y, -eye.z, 1 )&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Another issue in that article is that the variable names are misleading:&#xD;&#xA;the `orientation` denotes $\mathbf{R}^{-1}$, and the `translation` denotes $\mathbf{T}^{-1}$.&#xD;&#xA;&#xD;&#xA;The final view matrix is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;\mathbf{M} &amp; = &amp; (\mathbf{T}\mathbf{R})^{-1}\\&#xD;&#xA;&amp; = &amp; \mathbf{R}^{-1}\mathbf{T}^{-1}\\&#xD;&#xA;&amp; = &amp; \mathbf{R}^{T}\mathbf{T}^{-1}\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;r_x &amp; r_y &amp; r_z &amp; -&lt;\vec{r}, \vec{e}&gt; \\&#xD;&#xA;u_x &amp; u_y &amp; u_z &amp; -&lt;\vec{u}, \vec{e}&gt; \\&#xD;&#xA;f_x &amp; f_y &amp; f_z &amp; -&lt;\vec{f}, \vec{e}&gt; \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="8878" PostHistoryTypeId="5" PostId="4074" RevisionGUID="3b102663-7967-40f9-90b3-8ef49f459dfa" CreationDate="2016-10-04T11:51:27.363" UserId="120" Comment="added 382 characters in body" Text="Because all matrices are column-major,&#xD;&#xA;the translation matrix $\mathbf{T}$ should be&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{T}=\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_x \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_y \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_z \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I thought you mistakenly treat the `eye` as a row vector just because they were written as a single line in the source code&#xD;&#xA;&#xD;&#xA;    mat4 translation = {&#xD;&#xA;        vec4(   1,      0,      0,   0 ),&#xD;&#xA;        vec4(   0,      1,      0,   0 ), &#xD;&#xA;        vec4(   0,      0,      1,   0 ),&#xD;&#xA;        vec4(-eye.x, -eye.y, -eye.z, 1 )&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Another issue in that article is that the variable names are misleading:&#xD;&#xA;the `orientation` denotes $\mathbf{R}^{-1}$, and the `translation` denotes $\mathbf{T}^{-1}$(I think it is not a good practice even they commented on these variables).&#xD;&#xA;&#xD;&#xA;The final view matrix is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;\mathbf{M} &amp; = &amp; (\mathbf{T}\mathbf{R})^{-1}\\&#xD;&#xA;&amp; = &amp; \mathbf{R}^{-1}\mathbf{T}^{-1}\\&#xD;&#xA;&amp; = &amp; \mathbf{R}^{T}\mathbf{T}^{-1}\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;r_x &amp; r_y &amp; r_z &amp; -&lt;\vec{r}, \vec{e}&gt; \\&#xD;&#xA;u_x &amp; u_y &amp; u_z &amp; -&lt;\vec{u}, \vec{e}&gt; \\&#xD;&#xA;f_x &amp; f_y &amp; f_z &amp; -&lt;\vec{f}, \vec{e}&gt; \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and the implementation in that article is correct.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8879" PostHistoryTypeId="5" PostId="4063" RevisionGUID="803651a4-663b-40a9-98f6-4d2c9fc1dc46" CreationDate="2016-10-04T12:55:04.813" UserId="2707" Comment="Clarified aspects certain parts" Text="In short, performance reasons are why they aren't programmable.&#xD;&#xA;&#xD;&#xA;# History and Market&#xD;&#xA;In the past, there used to be separate cores for vertex and fragment processors to avoid bloated FPU designs. There were some mathematical operations you could only do in fragment shader code for instance (because they were mostly only relevant for fragment shaders). This would produce severe hardware bottlenecks for applications that didn't max out the potential of each type of core.&#xD;&#xA;&#xD;&#xA;As programmable shaders became more popular, universal units were introduced. More and more stages of the graphics pipeline were implemented in hardware to help with scaling. During this time, GPGPU also became more popular, so vendors had to incorporate some of this functionality. It's still important to note though that the majority of the income from GPUs were still video games, so this couldn't interfere with performance.&#xD;&#xA;&#xD;&#xA;Eventually a big player, Intel, decided to invest in programmable rasterizers with their [Larrabee architecture][1]. This project was supposed to be groundbreaking, but the [performance was apparently less than desired][2]. It was shut down, and parts of it were salvaged for Xeon Phi processors. It's worth noting though that the other vendors haven't implemented this.&#xD;&#xA;&#xD;&#xA;# Attempts at Software Rasterizers&#xD;&#xA;There have been some attempts at rasterization through software, but they all seem to have issues with performance.&#xD;&#xA;&#xD;&#xA;One notable effort was an [attempt by Nvidia][3] in 2011 in this [paper][4]. This was released close to when Larrabee was terminated, so it's very possible that this was a response to that. Regardless, there are some performance figures in this, and most of them show performance multiple times slower than hardware rasterizers.&#xD;&#xA;&#xD;&#xA;# Technical Issues with Software Rasterization&#xD;&#xA;There are many issues that were faced in the Nvidia paper. Here are some of the most important issues with software rasterizers though:&#xD;&#xA;&#xD;&#xA;## Major Issues&#xD;&#xA;&#xD;&#xA;* **Interpolation:**&#xD;&#xA;The hardware implementation generates interpolation equations in specialized hardware. This is slow for the software renderer since it had to be done in the fragment shader.&#xD;&#xA;&#xD;&#xA;* **Anti-aliasing:**&#xD;&#xA;There were also performance issues with anti-aliasing (specifically with memory). Information regarding the sub-pixel samples must be stored on-chip memory, which isn't enough to hold this. Julien Guertault pointed out that the texture cache/cache may be slower with software. MSAA certainly has issues here because it overflows the cache (the non-texture caches) and goes into memory off of the chip. Rasterizers compress data that is stored in that memory, which also helps with performance here.&#xD;&#xA;&#xD;&#xA;* **Power Consumption:**&#xD;&#xA;Simon F pointed out that power consumption would be lower. The paper did mention that custom ALUs are in rasterizers (which would reduce power consumption), and this would make sense since fragment and vertex processing units in the past used to have custom instruction sets (so likely custom ALUs as well). It certainly would be a bottleneck in many systems (e.g., mobile), although this has implications beyond performance.&#xD;&#xA;&#xD;&#xA;# Summary&#xD;&#xA;TL;DR: there are too many inefficiencies that software rendering can't past, and these things add up. There are also many larger limitations, especially when you are dealing with VRAM bandwidth, synchronization problems, and extra computations.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Larrabee_(microarchitecture)&#xD;&#xA;  [2]: https://www.cnet.com/news/intel-initial-larrabee-graphics-chip-canceled/&#xD;&#xA;  [3]: http://highperformancegraphics.net/previous/www_2011/media/Papers/HPG2011_Papers_Laine.pdf&#xD;&#xA;  [4]: http://dl.acm.org/citation.cfm?id=2018337" ContentLicense="CC BY-SA 3.0" />
  <row Id="8880" PostHistoryTypeId="2" PostId="4075" RevisionGUID="8aca62c3-b543-4e2c-8adb-8f729df15b84" CreationDate="2016-10-04T13:25:00.963" UserId="2041" Text="In GL's model of the GPU, the colour blending step is performed by special-purpose hardware. This idea dates back to the fixed-function origins of GL, before programmable shaders were even a thing.&#xD;&#xA;&#xD;&#xA;But not all GPUs today implement all colour blend options with special-purpose hardware. The hardware vendor can reduce gate count and power use by getting rid of some of the less-used blend modes (or even by getting rid of the blender hardware completely and doing everything in shaders). Instead, the GL driver has to add some code to the shader to do the blending. This code is added transparently to the driver, and isn't visible to the application, because GL doesn't have a way to make this visible or to control it from the application.&#xD;&#xA;&#xD;&#xA;Now, the shader object (the compiled shader) doesn't just depend on the shader source code, but also on the blend mode in effect when it was compiled. If the application subsequently changes the blend mode, the driver needs to work out which shader objects are affected, retrieve the stored source of those shader objects, add the code for the new blend mode, and recompile the shader. Again, it has to do this behind the application's back, because GL doesn't have a way to control it: GL assumes the shader object is independent of the blend mode.&#xD;&#xA;&#xD;&#xA;Normally, the application would compile shaders during a loading screen, or in a thread, but because the shader compilation isn't triggered by the application, it can't control when it happens. It just happens by magic when the application changed something that should be unrelated (the blend mode), which might be in the middle of a frame, so it causes hitching. And of course because it's hidden, the app can't simply ask to go back to the old state: changing the blend mode again might trigger another shader compilation (though it might come from a cache in the shader compiler).&#xD;&#xA;&#xD;&#xA;Blend mode isn't the only parameter that causes this. Some unusual texture modes are also supported by adding code to the shader. (YUV textures commonly work this way, on implementations that support them.) Exactly which parameters cause a problem depends on the implementation: it's different for different hardware architectures. I think it's typically a bigger problem on mobile, because the GPU vendors are more sensitive to gate count and power use and more keen to replace special-purpose hardware with shader code.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The reason Vulkan makes this less of a problem is that it creates a new kind of state, which depends on the blend mode, the shaders, and other parameters. Changing any of these requires the app to perform an explicit &quot;prepare&quot; operation, which might recompile shaders. This gives the app control over when it happens, including the ability to prepare all the combinations of parameters up-front in a loading screen or in a background thread. It means that shader compilation never happens without the app asking for it explicitly. And it means the app can just go back to the old state by switching to it, instead of changing the blend mode and waiting for another shader recompilation." ContentLicense="CC BY-SA 3.0" />
  <row Id="8882" PostHistoryTypeId="2" PostId="4076" RevisionGUID="2001e0ba-e8db-41b1-98f2-3f2d0e2e3760" CreationDate="2016-10-04T17:42:29.650" UserId="4829" Text="The main difference with the pipelines is that DirectX12 is focus is on multi-threading or using the multiple cores most efficiently as possible according to the rendering state of an object.&#xD;&#xA;&#xD;&#xA;As for Vulkan, they are separating the management of the threads into different types of pipelines, compute and graphical. &#xD;&#xA;&#xD;&#xA;As stated in the reference from MSDN, DirectX12 is utilizing PSO (Pipeline State Object). The optimization occurs in this way by preparing the commands to the pipeline before. Seemingly, DirectX12 uses PSO to create a object of the state of rendering to better manage changes in state to the hardware more efficiently.&#xD;&#xA;&#xD;&#xA;Hope that helps!" ContentLicense="CC BY-SA 3.0" />
  <row Id="8883" PostHistoryTypeId="2" PostId="4077" RevisionGUID="fa41ebe9-aafd-4250-be67-64ec119be1d0" CreationDate="2016-10-04T17:49:05.087" UserId="120" Text="Let's go through the paper you mentioned and try to list the factors which will affect your decision on whether to use GPU or CPU for simulation.&#xD;&#xA;I will also add some comments about my opinion for each factor.&#xD;&#xA;&#xD;&#xA;## Computation bound&#xD;&#xA;GPU program runs in SIMT(Single instruction, multiple threads) model,&#xD;&#xA;which emits many computation threads to hide the memory latency and the overhead of memory transfer between GPU and CPU.&#xD;&#xA;&#xD;&#xA;If one implementation is memory bound, we hardly benefit from the SIMT programming model.&#xD;&#xA;&#xD;&#xA;Fortunately, fluid simulation is a computation bound task for most of the cases.&#xD;&#xA;&#xD;&#xA;## Locality&#xD;&#xA;In the paper you mentioned we can observe perfect locality:&#xD;&#xA;for each grid point we only have to examine its neighbors.&#xD;&#xA;&#xD;&#xA;The actual memory access pattern depends on the finite difference scheme you use.&#xD;&#xA;But for all grid based simulation methods(Eulerian or Lattice-Boltzmann method) , I think the locality always presents.&#xD;&#xA;&#xD;&#xA;## Divergence&#xD;&#xA;A warp(a group of 32 threads) in GPU program can executed in parallel if they follow the same code path. Otherwise the program diverges and the execution of each branch will be serialized. Divergence will hurt the performance.&#xD;&#xA;&#xD;&#xA;In particle based simulations(such as SPH method) we usually have to query the nearest N particles. A tree-like data structure will be used.&#xD;&#xA;&#xD;&#xA;In GPU a tree data structure may introduce divergence because particles may fall into different branches.&#xD;&#xA;&#xD;&#xA;The paper you mentioned uses grid based methods, where all threads execute along the same code path(Jacobi or Gauss-Seidel iteration), so divergence is not a problem here.&#xD;&#xA;&#xD;&#xA;## Interactivity&#xD;&#xA;In the paper it uses static boundary conditions.&#xD;&#xA;For this case you just need to upload the boundary conditions to GPU memory for only once.&#xD;&#xA;&#xD;&#xA;If you have dynamic boundary conditions, for example, which are specified by user at each frame, the overhead of memory transfer between GPU and CPU should be taken into consideration.&#xD;&#xA;&#xD;&#xA;## Spatial complexity&#xD;&#xA;Uniform grid based simulation cannot handle very large computation area, because the spatial complexity is cubic.&#xD;&#xA;&#xD;&#xA;There are adaptive grid methods, which uses relative higher resolution for the computation area we are most interested in. But that would also bring in divergence.&#xD;&#xA;&#xD;&#xA;## Numerical issues&#xD;&#xA;For fluid simulation you cannot decide the number of steps solely based on the performance/frame rates.&#xD;&#xA;&#xD;&#xA;In grid based methods, the Courant–Friedrichs–Lewy(CFL) condition puts a constraint on how large simulation step you can have.&#xD;&#xA;Given a fixed time step, too large or too small steps would cause instability and blow up the simulation.&#xD;&#xA;&#xD;&#xA;In particle based methods and some stable grid based methods(such as the semi-Lagrangian method used in the paper), we can use relative larger simulation steps.&#xD;&#xA;&#xD;&#xA;But we still cannot increase the step size with no bound because of the accuracy.&#xD;&#xA;For example in grid based methods a large step size would introduce too much numerical viscosity.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Summary&#xD;&#xA;As a summary, if your simulation have strong convergence and locality, prefer a GPU implementation; otherwise, prefer a CPU one.&#xD;&#xA;&#xD;&#xA;In practice, I will always go to implement a CPU version because it is easier to debug and it will be useful as a baseline.&#xD;&#xA;Then I will profile it to locate the bottleneck and decide whether to have a GPU version." ContentLicense="CC BY-SA 3.0" />
  <row Id="8884" PostHistoryTypeId="2" PostId="4078" RevisionGUID="86ba445b-d32e-4a37-9286-52276545f46d" CreationDate="2016-10-04T19:55:26.123" UserId="5093" Text="I have a bunch of planes each with their own texture in a grid. Currently I am rendering these as separate planes, each with their own texture, although I could use a single plane with multiple faces.&#xD;&#xA;&#xD;&#xA;[![textures][1]][1]&#xD;&#xA;&#xD;&#xA;Each color is a texture.&#xD;&#xA;&#xD;&#xA;I have a polygon mesh with arbitrary shape that is parallel to these planes:&#xD;&#xA;&#xD;&#xA;[![polygon][2]][2]&#xD;&#xA;&#xD;&#xA;This shape could be completely contained within one of the planes, or larger.&#xD;&#xA;&#xD;&#xA;I would like to texture the polygon with the overlapping textures of the planes:&#xD;&#xA;&#xD;&#xA;[![overlap][3]][3]&#xD;&#xA;&#xD;&#xA;How do I accomplish this clipping of the textures in three js / WebGl?&#xD;&#xA;&#xD;&#xA;I am also open to any other WebGL solutions.&#xD;&#xA;&#xD;&#xA;A few ideas I had:&#xD;&#xA;&#xD;&#xA; 1. Subdivide the polygon into faces that correspond with the overlapping planes. Then texture these faces using UV coords. I know I can get this to work, but it seems like too complicated of a solution.&#xD;&#xA; 2. Apply multiple textures to the polygon and use UV coordinates to distribute them. -- Im not sure this is possible without subdividing?&#xD;&#xA;&#xD;&#xA;Any other ideas? Can this be accomplished with blending modes?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sgSuH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FdGTj.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/gsaSF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8885" PostHistoryTypeId="1" PostId="4078" RevisionGUID="86ba445b-d32e-4a37-9286-52276545f46d" CreationDate="2016-10-04T19:55:26.123" UserId="5093" Text="How to clip multiple tiled textures to polygon in Webgl / opengl" ContentLicense="CC BY-SA 3.0" />
  <row Id="8886" PostHistoryTypeId="3" PostId="4078" RevisionGUID="86ba445b-d32e-4a37-9286-52276545f46d" CreationDate="2016-10-04T19:55:26.123" UserId="5093" Text="|rendering|webgl|clipping|masking|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8887" PostHistoryTypeId="5" PostId="4077" RevisionGUID="fc9c3144-f69d-4e5d-a624-c33dfe7740a5" CreationDate="2016-10-04T23:49:08.357" UserId="231" Comment="Some tidying - please revert anything that changes your intended meaning." Text="Let's go through the paper you mentioned and try to list the factors which will affect your decision on whether to use GPU or CPU for simulation.&#xD;&#xA;I will also add some comments about my opinion for each factor.&#xD;&#xA;&#xD;&#xA;## Computation bound&#xD;&#xA;A GPU program runs in a SIMT(Single instruction, multiple threads) model,&#xD;&#xA;which emits many computation threads to hide the memory latency and the overhead of memory transfer between GPU and CPU.&#xD;&#xA;&#xD;&#xA;If one implementation is memory bound, we hardly benefit from the SIMT programming model.&#xD;&#xA;&#xD;&#xA;Fortunately, fluid simulation is a computation bound task for most of the cases.&#xD;&#xA;&#xD;&#xA;## Locality&#xD;&#xA;In the paper you mentioned we can observe perfect locality:  &#xD;&#xA;for each grid point we only have to examine its neighbors.&#xD;&#xA;&#xD;&#xA;The actual memory access pattern depends on the finite difference scheme you use.&#xD;&#xA;But for all grid based simulation methods(Eulerian or Lattice-Boltzmann method), I think the locality always presents.&#xD;&#xA;&#xD;&#xA;## Divergence&#xD;&#xA;A warp (a group of 32 threads) in a GPU program can be executed in parallel if they follow the same code path. Otherwise the program diverges and the execution of each branch will be serialized. Divergence will hurt the performance.&#xD;&#xA;&#xD;&#xA;In particle based simulations (such as SPH method) we usually have to query the nearest N particles. A tree-like data structure will be used.&#xD;&#xA;&#xD;&#xA;In GPU a tree data structure may introduce divergence because particles may fall into different branches.&#xD;&#xA;&#xD;&#xA;The paper you mentioned uses grid based methods, where all threads execute along the same code path (Jacobi or Gauss-Seidel iteration), so divergence is not a problem here.&#xD;&#xA;&#xD;&#xA;## Interactivity&#xD;&#xA;In the paper it uses static boundary conditions.  &#xD;&#xA;For this case you just need to upload the boundary conditions to GPU memory only once.&#xD;&#xA;&#xD;&#xA;If you have dynamic boundary conditions, for example, which are specified by the user at each frame, the overhead of memory transfer between GPU and CPU should be taken into consideration.&#xD;&#xA;&#xD;&#xA;## Spatial complexity&#xD;&#xA;Uniform grid based simulations cannot handle very large computation volume, because the spatial complexity is cubic.&#xD;&#xA;&#xD;&#xA;There are adaptive grid methods, which use relatively higher resolution for the computation region we are most interested in. But that would also bring in divergence.&#xD;&#xA;&#xD;&#xA;## Numerical issues&#xD;&#xA;For fluid simulation you cannot decide the number of steps solely based on the performance/frame rate.&#xD;&#xA;&#xD;&#xA;In grid based methods, the Courant–Friedrichs–Lewy (CFL) condition puts a constraint on how large simulation step you can have.&#xD;&#xA;Given a fixed time step, too large or too small steps would cause instability and blow up the simulation.&#xD;&#xA;&#xD;&#xA;In particle based methods and some stable grid based methods (such as the semi-Lagrangian method used in the paper), we can use relatively larger simulation steps.&#xD;&#xA;&#xD;&#xA;But we still cannot increase the step size with no bound because of the accuracy.&#xD;&#xA;For example in grid based methods a large step size would introduce too much numerical viscosity.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Summary&#xD;&#xA;As a summary, if your simulation has strong convergence and locality, prefer a GPU implementation; otherwise, prefer a CPU one.&#xD;&#xA;&#xD;&#xA;In practice, I will always implement a CPU version because it is easier to debug and it will be useful as a baseline.&#xD;&#xA;Then I will profile it to locate the bottleneck and decide whether to have a GPU version." ContentLicense="CC BY-SA 3.0" />
  <row Id="8888" PostHistoryTypeId="2" PostId="4079" RevisionGUID="08cfc798-7e16-49cf-80f1-60a18a834de7" CreationDate="2016-10-05T08:07:33.903" UserId="113" Text="So I'm trying to correctly map my textures using the u, v coordinates but I can't seem to get it working. I read that I needed to divide the u, v coordinates by the w component (perspective divide). But I tried that and it didn't work. So I looked a little bit more into the problem. First, here's what is happening to one vertex of my triangles.&#xD;&#xA;&#xD;&#xA;    float4 pt1 = worldViewProj * mesh-&gt;vertices[mesh-&gt;indices[i]];&#xD;&#xA;    float2 uv1 = mesh-&gt;texCoords[mesh-&gt;indices[i]];&#xD;&#xA;	triangle.p1 = float3((pt1.x / pt1.w + 0.5f) * screen-&gt;GetScreenWidth(), (pt1.y / pt1.w + 0.5f) * screen-&gt;GetScreenHeight(), pt1.w);&#xD;&#xA;&#xD;&#xA;I multiply it with the wVP and then do my perspective divide with x and y. The + 0.5f is to center it in screen space and then multiply with the screen dimensions to get it in screen space. I then stuff the w component as the z value so it will be sent to the triangle drawing function and can be used for things like the depth buffer. &#xD;&#xA;&#xD;&#xA;To my understanding the z value from the vertex gets put into w after multiplying with the projection matrix. This makes sense since m32 (counting from 0) is 1 in my projection matrix. I first tried dividing the texture coordinates per vertex by w and then interpolating them when drawing the triangle. Like so:&#xD;&#xA;&#xD;&#xA;     float2 uv1 = mesh-&gt;texCoords[mesh-&gt;indices[i]] / w;&#xD;&#xA;&#xD;&#xA;But I also tried this instead in my triangle drawing function:&#xD;&#xA;&#xD;&#xA;    float2 texCoord = (texCoord1 * u + texCoord2 * v + texCoord3 * w) / z;&#xD;&#xA;&#xD;&#xA;(Here u, v, and w are the bary centric coordinates. Each texCoord is the texCoordinate at that vertex) The difference here is that the interpolated z value is being divided at every pixel instead of it being divided at every vertex. Either way I can't seem to get it too work. My z value is very large as I have pushed the model pretty far back in the scene. uv seems to always come out to (0, 0). &#xD;&#xA;&#xD;&#xA;Here's my current thoughts on the problem I'm having. I read somewhere that I need to put the z value in homogeneous coordinates [-1, 1]. This is what the projection matrix is supposed to do but it only does it with x / w and y / w. After applying the projection matrix ny z = w and so z / w = 1 always. Is my projection matrix messed up? There seems to be many forms of the perspective projection matrix. I'm guessing I need an alteration on m32. I'd guess it would be farZ. So I could get z / farZ but this just seem to screw it a lot.&#xD;&#xA;&#xD;&#xA;Here it is:&#xD;&#xA;&#xD;&#xA;	float tanHalfFov = tanf(fov * 0.5f * 3.14f / 180.0f);&#xD;&#xA;	float s = 1.0f / (tanHalfFov * aspectRatio);&#xD;&#xA;	float zRange = farZ - nearZ;&#xD;&#xA;&#xD;&#xA;	// Set the projection matrix&#xD;&#xA;	proj.m00 = s;    proj.m01 = 0.0f;            proj.m02 = 0.0f;          proj.m03 = 0.0f;&#xD;&#xA;&#xD;&#xA;	proj.m10 = 0.0f; proj.m11 = aspectRatio * s; proj.m12 = 0.0f;          proj.m13 = 0.0f;&#xD;&#xA;&#xD;&#xA;	proj.m20 = 0.0f; proj.m21 = 0.0f;            proj.m22 = farZ / zRange; proj.m23 = farZ * nearZ / zRange;&#xD;&#xA;&#xD;&#xA;	proj.m30 = 0.0f; proj.m31 = 0.0f;            proj.m32 = 1.0f;          proj.m33 = 0.0f;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8889" PostHistoryTypeId="1" PostId="4079" RevisionGUID="08cfc798-7e16-49cf-80f1-60a18a834de7" CreationDate="2016-10-05T08:07:33.903" UserId="113" Text="Perspective Correct Texture Mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="8890" PostHistoryTypeId="3" PostId="4079" RevisionGUID="08cfc798-7e16-49cf-80f1-60a18a834de7" CreationDate="2016-10-05T08:07:33.903" UserId="113" Text="|rendering|texture|perspective|uv-mapping|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8891" PostHistoryTypeId="2" PostId="4080" RevisionGUID="c60b6229-52b3-461d-9cbc-d493a07de3ef" CreationDate="2016-10-05T11:14:03.440" UserId="2463" Text="Alan Wolfe is pretty spot on, but I will sum up any way :)&#xD;&#xA;&#xD;&#xA;- render the back-faces of your &quot;unit&quot;-sized-box, [-1;1]&#xD;&#xA;- sample the zbuffer and transform into light-local coordinates (see [our slides][1] for a fast way to do that).&#xD;&#xA;- early-out of the pixelshader if outside of the box, i.e. if any coordinate in the local-position is outside of -1;1.&#xD;&#xA;- then do the dot-product between the normal and the lightdir, in whatever space is convenient (you can extract the worldspace-lightdir from the object-to-world matrix).&#xD;&#xA;- projecting a texture is easy, the UV-coordinates are simply the localspace xy (moved to [0;1])&#xD;&#xA;- using a falloff texture is eays, the coordinate is simply the localspace z (moved to [0;1])&#xD;&#xA;&#xD;&#xA;In an actual game, you of course want to use some sort of acceleration to discard early; we used old-school stencil culling (and should have used depthbounds), but likely tiled culling, clustered culling or similar is better.&#xD;&#xA;&#xD;&#xA;You could use zgreater testing to discard pixels where background is entirely behind the light, but iirc on most modern GPUs this will not actually be an advantage, as there will be no early-discard due to the hierarchical zbuffer being primed in the direction of zless.&#xD;&#xA;&#xD;&#xA;  [1]: http://f0716f2bff707a1b9e85-36c178e006d3d30c5b9c8dd905f8236a.r70.cf2.rackcdn.com/rendering_inside.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="8892" PostHistoryTypeId="2" PostId="4081" RevisionGUID="ca93b0aa-7ca9-4cd8-928c-1afdf4daab45" CreationDate="2016-10-05T13:32:22.793" UserId="5235" Text="I have been trying to figure out why does rotation about an arbitrary axis have degree of freedom 6. I know that it takes two points, each take 3 values to determine in a 3-D space. But what about the rotation angle? Wouldn't that make the degree of freedom increase by 1 to get 7?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8893" PostHistoryTypeId="1" PostId="4081" RevisionGUID="ca93b0aa-7ca9-4cd8-928c-1afdf4daab45" CreationDate="2016-10-05T13:32:22.793" UserId="5235" Text="Why does rotation about an arbitrary axis have degree of freedom 6" ContentLicense="CC BY-SA 3.0" />
  <row Id="8894" PostHistoryTypeId="3" PostId="4081" RevisionGUID="ca93b0aa-7ca9-4cd8-928c-1afdf4daab45" CreationDate="2016-10-05T13:32:22.793" UserId="5235" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8895" PostHistoryTypeId="2" PostId="4082" RevisionGUID="2a28218f-999f-4f50-8b5f-5d61f9bc7519" CreationDate="2016-10-05T14:25:28.713" UserId="209" Text="The length of the axis is irrelevant and so you can remove one degree of freedom." ContentLicense="CC BY-SA 3.0" />
  <row Id="8901" PostHistoryTypeId="2" PostId="4084" RevisionGUID="c12a0305-ef72-482f-bf96-e1053bb743e0" CreationDate="2016-10-05T15:12:35.930" UserId="5236" Text="I would start by looking into deferred decals (you can start [here][1] for example, this blogpost has a lot of useful links)&#xD;&#xA;&#xD;&#xA;If you understand how the positions are calculated and compared with the volume then you should be able to apply the same logic in the lighting phase.&#xD;&#xA;&#xD;&#xA;  [1]: https://bartwronski.com/2015/03/12/fixing-screen-space-deferred-decals/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8902" PostHistoryTypeId="2" PostId="4085" RevisionGUID="47119091-3578-4fac-82fc-4e957dfcde4e" CreationDate="2016-10-05T15:33:28.897" UserId="2041" Text="You also need to scale the cylinder. Take the magnitude (length) of $p_1 - p_2$, and divide it by the length of the cylinder (or don't divide, if your cylinder is already unit length). This gives you the scale factor. You can apply this as a non-uniform scale along the axis that the cylinder points in. (Since you were able to work out how to apply a rotation, I assume you can make the appropriate scaling matrix given just the scale factor and direction.)&#xD;&#xA;&#xD;&#xA;Make sure to scale it before rotating or translating the cylinder! If you translate before you scale, you'll translate the start point of the cylinder as well as its length, so the start won't be attached to $p_1$ any more. If you rotate before you scale, you won't be scaling the length of the cylinder, you'll be stretching it in the wrong direction, so it won't be a cylinder any more." ContentLicense="CC BY-SA 3.0" />
  <row Id="8903" PostHistoryTypeId="5" PostId="4008" RevisionGUID="7cea9c65-cb7e-4b7c-a4c8-33a7011e4ece" CreationDate="2016-10-05T15:46:49.993" UserId="5121" Comment="added 411 characters in body" Text="I am given geometry of a cylinder which lies on the XY plane with 1 unit radius. And given coordinates of 2 points in 3D I need to move the cylinder so that it connects the two points.&#xD;&#xA;&#xD;&#xA;What I tried so far after searching online:&#xD;&#xA;&#xD;&#xA;1. Calculated the vector between the two points p = p1 - p2;&#xD;&#xA;2. Took the normal vector to the plane(0,0,1) v&#xD;&#xA;3. Axis of rotation = v x p (cross)&#xD;&#xA;4. angle of rotation = acos(|v|.|p|) (unit vectors)&#xD;&#xA;5. I applied this rotation.&#xD;&#xA;6. Translated one of the end point of cylinder to one of the points.&#xD;&#xA;&#xD;&#xA;but it moves the object to a wrong location. Any help what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;EDIT: My apologies for not being able to respond.&#xD;&#xA;The main issue was with this line.&#xD;&#xA;&#xD;&#xA;* angle of rotation = acos(|v|.|p|) (unit vectors)&#xD;&#xA;I normalized the vectors then used this wrong formula. Which will always return 90 degrees.&#xD;&#xA;&#xD;&#xA;I am still not getting exactly the correct output. Here is the screenshot.&#xD;&#xA;&#xD;&#xA;[![Atom bond representation of ligands][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GwXFS.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8904" PostHistoryTypeId="2" PostId="4086" RevisionGUID="0ffeb4d5-81ff-419d-a52d-cfcf0c3a80a9" CreationDate="2016-10-05T16:02:44.307" UserId="137" Text="It is only 3 degrees of freedom.&#xD;&#xA;&#xD;&#xA;An arbitrary axis can be specified by 1 3D vector however the length doesn't matter so it only takes 2 degrees of freedom. Then you add the rotation angle to it and you have 3 degrees of freedom.&#xD;&#xA;&#xD;&#xA;If you mean a rotation around a arbitrary point then that point takes up 3 additional degrees of freedom for a total of 6." ContentLicense="CC BY-SA 3.0" />
  <row Id="8905" PostHistoryTypeId="2" PostId="4087" RevisionGUID="47481ecd-5009-46b4-802f-6548b345e7e8" CreationDate="2016-10-05T16:23:03.047" UserId="5105" Text="I know when we use Z-buffer to eliminate the hidden faces, the polygons can be in any order. But my teacher said that this does not mean that two images generated by sending polygons in different orders will have identical values in their z-buffers and in their frame buffers. How does this happen? &#xD;&#xA;And if this is the case, When or how will the z-buffers and the frame buffers have the same values even if polygons are sent in different order?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8906" PostHistoryTypeId="1" PostId="4087" RevisionGUID="47481ecd-5009-46b4-802f-6548b345e7e8" CreationDate="2016-10-05T16:23:03.047" UserId="5105" Text="How will the z-buffers have the same values even if polygons are sent in different order?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8907" PostHistoryTypeId="3" PostId="4087" RevisionGUID="47481ecd-5009-46b4-802f-6548b345e7e8" CreationDate="2016-10-05T16:23:03.047" UserId="5105" Text="|z-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8908" PostHistoryTypeId="2" PostId="4088" RevisionGUID="60ff8bd9-a00b-42a9-9a82-72f14de3d6fc" CreationDate="2016-10-05T17:03:36.627" UserId="48" Text="What your teacher means is that at the _end_ of the frame, once all polygons in the scene have been drawn, the z-buffer will have the same values. This is because the z-buffer keeps the minimum Z within each pixel, over all the polygons drawn to that pixel, and the minimum doesn't depend on the order.&#xD;&#xA;&#xD;&#xA;If you look at the z-buffer in the _middle_ of the frame, when _some_ polygons, but not all, have been drawn, then naturally the contents of the z-buffer will depend on what's been drawn so far, which would depend on the order in general.&#xD;&#xA;&#xD;&#xA;With regard to the color buffer, the same things are true if all the Z values within each pixel are distinct. However there's one case where the results do depend on the order: when multiple polygons have the same Z value at a given pixel. This could happen if the same polygons are rendered twice with different colors, or some such. Then, the behavior depends on the setting of the depth test (i.e. [`glDepthFunc`](http://docs.gl/gl4/glDepthFunc) in OpenGL). If it's strictly &quot;less&quot;, then the first polygon drawn that has the minimum Z will &quot;win&quot; and its color will end up in the color buffer at the end. But if the depth test is set to &quot;less-equal&quot;, then each polygon that has the minimum Z will overwrite the one before it, and the last one drawn will end up in the color buffer at the end. So in that case, the order of drawing polygons, and the state of the depth test, do make a difference." ContentLicense="CC BY-SA 3.0" />
  <row Id="8909" PostHistoryTypeId="2" PostId="4089" RevisionGUID="3d46e0cd-9438-48b0-a8dc-77c90bd3bab2" CreationDate="2016-10-05T17:42:53.303" UserId="1952" Text="If you use alpha blending, then the order of rendered polygons matter even if you use depth writes &amp; tests. E.g. imagine you render two triangles A (red) and B (blue) with 50% opacity where smaller triangle B is in front of A. If you render A before B then the B will appear purple, but if you render B before A then B will appear dark blue (pixels for A are not rendered where the triangles overlap).&#xD;&#xA;&#xD;&#xA;However, if you use opaque rendering, then the frame buffer values will be the same regardless of the rendering order, except in the special case Nathan mentioned where the depth values are equal for the two triangles.&#xD;&#xA;&#xD;&#xA;Only thing where the rendering order matters for z-buffer result that comes to mind is if you use specific stencil test &amp; ops. E.g. when rendering A the stencil test passes and writes a value to stencil buffer which makes B to fail which results only the triangle A to be visible. But if you render B before A, then you see B in front of A. This will naturally influence also frame buffer values." ContentLicense="CC BY-SA 3.0" />
  <row Id="8910" PostHistoryTypeId="5" PostId="4086" RevisionGUID="eca17bda-2931-421f-b936-594e460275e0" CreationDate="2016-10-05T17:59:23.537" UserId="137" Comment="added 22 characters in body" Text="It is only 3 degrees of freedom.&#xD;&#xA;&#xD;&#xA;An arbitrary axis can be specified by 1 3D vector however the length doesn't matter so it only takes 2 degrees of freedom. Then you add the rotation angle to it and you have 3 degrees of freedom.&#xD;&#xA;&#xD;&#xA;If you mean a rotation around a arbitrary point other than the origin then that point takes up 3 additional degrees of freedom for a total of 6." ContentLicense="CC BY-SA 3.0" />
  <row Id="8911" PostHistoryTypeId="5" PostId="4079" RevisionGUID="34b7ba60-76a0-4408-9bc6-d8ccd08d29ee" CreationDate="2016-10-05T22:52:44.273" UserId="113" Comment="added 476 characters in body" Text="So I'm trying to correctly map my textures in my software renderer using the u, v coordinates but I can't seem to get it working. I got affine texture mapping working. But this perspective divide thing is confusing me. I read that I needed to divide the u, v coordinates by the w component (perspective divide). I'm guessing that this is the w component from the vertex after multiplying with the projection matrix. But I couldn't get that too work. So I looked a little bit more into the problem. First, here's what is happening to one vertex of my triangles.&#xD;&#xA;&#xD;&#xA;    float4 pt1 = worldViewProj * mesh-&gt;vertices[mesh-&gt;indices[i]];&#xD;&#xA;    float2 uv1 = mesh-&gt;texCoords[mesh-&gt;indices[i]];&#xD;&#xA;	triangle.p1 = float3((pt1.x / pt1.w + 0.5f) * screen-&gt;GetScreenWidth(), (pt1.y / pt1.w + 0.5f) * screen-&gt;GetScreenHeight(), pt1.w);&#xD;&#xA;&#xD;&#xA;I multiply it with the wVP and then do my perspective divide with x and y. The + 0.5f is to center it in homogeneous space and then multiply with the screen dimensions to get it in screen space. I then stuff the w component of the vertex as the z value so it will be sent to the triangle drawing function and can be used for things like the depth buffer.&#xD;&#xA;&#xD;&#xA;To my understanding the z value from the vertex gets put into w after multiplying with the projection matrix. This makes sense since m32 = 1 in my projection matrix. So after multiplication with the projection matrix w = z. I first tried dividing the texture coordinates per vertex by w. Like so:&#xD;&#xA;&#xD;&#xA;     float2 uv1 = mesh-&gt;texCoords[mesh-&gt;indices[i]] / w;&#xD;&#xA;&#xD;&#xA;Then in the triangle drawing function I used the bary centric coordinates to interpolate across these the uv coordinates. This did not work. Since w = z. When the texture is far from the camera (ie z is a large value. With my world translations applied z = ~700) then the texture coordinates shrink a lot and in every render I just get the (0, 0) value of my texture.&#xD;&#xA;&#xD;&#xA;But I also tried this instead in my triangle drawing function:&#xD;&#xA;&#xD;&#xA;    float2 texCoord = (texCoord1 * u + texCoord2 * v + texCoord3 * w) / z;&#xD;&#xA;&#xD;&#xA;(Here u, v, and w are the bary centric coordinates. Each texCoord is the texture Coordinate at that vertex) The difference here is that the interpolated z value is being divided at every pixel instead of it being divided at the vertices. Either way I can't seem to get it too work. Again the z value is too large and I end up getting (0, 0).&#xD;&#xA;&#xD;&#xA;So I'm investigating what I need to divide u and v by. Obviously I'm doing something wrong. Is it really the w component of the vertex after multiplying with the projection matrix? Is my w value wrong? Could the projection matrix be causing this? I've been googling around for awhile now... x / w and y / w are [-1, 1] (homogeneous) but z isn't [-1, 1]. Is it supposed to be? My perspective divide for x and y obviously works.&#xD;&#xA;&#xD;&#xA;Here's how I built my projection matrix just in case it's wrong?:&#xD;&#xA;&#xD;&#xA;	float tanHalfFov = tanf(fov * 0.5f * 3.14f / 180.0f);&#xD;&#xA;	float s = 1.0f / (tanHalfFov * aspectRatio);&#xD;&#xA;	float zRange = farZ - nearZ;&#xD;&#xA;&#xD;&#xA;	// Set the projection matrix&#xD;&#xA;	proj.m00 = s;    proj.m01 = 0.0f;            proj.m02 = 0.0f;          proj.m03 = 0.0f;&#xD;&#xA;&#xD;&#xA;	proj.m10 = 0.0f; proj.m11 = aspectRatio * s; proj.m12 = 0.0f;          proj.m13 = 0.0f;&#xD;&#xA;&#xD;&#xA;	proj.m20 = 0.0f; proj.m21 = 0.0f;            proj.m22 = farZ / zRange; proj.m23 = farZ * nearZ / zRange;&#xD;&#xA;&#xD;&#xA;	proj.m30 = 0.0f; proj.m31 = 0.0f;            proj.m32 = 1.0f;          proj.m33 = 0.0f;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8912" PostHistoryTypeId="5" PostId="4079" RevisionGUID="56231a92-5c2a-4b0a-9822-a59b617abd11" CreationDate="2016-10-05T23:44:50.150" UserId="113" Comment="added 194 characters in body" Text="So I'm trying to correctly map my textures in my software renderer using the u, v coordinates but I can't seem to get it working. I got affine texture mapping working. This is what I can produce using it:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can see from the &quot;tilt&quot; in the texture that it's not quite right. If I add more triangles to the mesh it becomes more correct. From my understanding these are not perspective correct textures. But this perspective divide thing is confusing me. I read that I needed to divide the u, v coordinates by the w component (perspective divide). I'm guessing that this is the w component from the vertex after multiplying with the projection matrix. But I couldn't get that too work. So I looked a little bit more into the problem. First, here's what is happening to one vertex of my triangles.&#xD;&#xA;&#xD;&#xA;    float4 pt1 = worldViewProj * mesh-&gt;vertices[mesh-&gt;indices[i]];&#xD;&#xA;    float2 uv1 = mesh-&gt;texCoords[mesh-&gt;indices[i]];&#xD;&#xA;	triangle.p1 = float3((pt1.x / pt1.w + 0.5f) * screen-&gt;GetScreenWidth(), (pt1.y / pt1.w + 0.5f) * screen-&gt;GetScreenHeight(), pt1.w);&#xD;&#xA;&#xD;&#xA;I multiply it with the wVP and then do my perspective divide with x and y. The + 0.5f is to center it in homogeneous space and then multiply with the screen dimensions to get it in screen space. I then stuff the w component of the vertex as the z value so it will be sent to the triangle drawing function and can be used for things like the depth buffer.&#xD;&#xA;&#xD;&#xA;To my understanding the z value from the vertex gets put into w after multiplying with the projection matrix. This makes sense since m32 = 1 in my projection matrix. So after multiplication with the projection matrix w = z. I first tried dividing the texture coordinates per vertex by w. Like so:&#xD;&#xA;&#xD;&#xA;     float2 uv1 = mesh-&gt;texCoords[mesh-&gt;indices[i]] / w;&#xD;&#xA;&#xD;&#xA;Then in the triangle drawing function I used the bary centric coordinates to interpolate across these the uv coordinates. This did not work. Since w = z. When the texture is far from the camera (ie z is a large value. With my world translations applied z = ~700) then the texture coordinates shrink a lot and in every render I just get the (0, 0) value of my texture.&#xD;&#xA;&#xD;&#xA;But I also tried this instead in my triangle drawing function:&#xD;&#xA;&#xD;&#xA;    float2 texCoord = (texCoord1 * u + texCoord2 * v + texCoord3 * w) / z;&#xD;&#xA;&#xD;&#xA;(Here u, v, and w are the bary centric coordinates. Each texCoord is the texture Coordinate at that vertex) The difference here is that the interpolated z value is being divided at every pixel instead of it being divided at the vertices. Either way I can't seem to get it too work. Again the z value is too large and I end up getting (0, 0).&#xD;&#xA;&#xD;&#xA;So I'm investigating what I need to divide u and v by. Obviously I'm doing something wrong. Is it really the w component of the vertex after multiplying with the projection matrix? Is my w value wrong? Could the projection matrix be causing this? I've been googling around for awhile now... x / w and y / w are [-1, 1] (homogeneous) but z isn't [-1, 1]. Is it supposed to be? My perspective divide for x and y obviously works.&#xD;&#xA;&#xD;&#xA;Here's how I built my projection matrix just in case it's wrong?:&#xD;&#xA;&#xD;&#xA;	float tanHalfFov = tanf(fov * 0.5f * 3.14f / 180.0f);&#xD;&#xA;	float s = 1.0f / (tanHalfFov * aspectRatio);&#xD;&#xA;	float zRange = farZ - nearZ;&#xD;&#xA;&#xD;&#xA;	// Set the projection matrix&#xD;&#xA;	proj.m00 = s;    proj.m01 = 0.0f;            proj.m02 = 0.0f;          proj.m03 = 0.0f;&#xD;&#xA;&#xD;&#xA;	proj.m10 = 0.0f; proj.m11 = aspectRatio * s; proj.m12 = 0.0f;          proj.m13 = 0.0f;&#xD;&#xA;&#xD;&#xA;	proj.m20 = 0.0f; proj.m21 = 0.0f;            proj.m22 = farZ / zRange; proj.m23 = farZ * nearZ / zRange;&#xD;&#xA;&#xD;&#xA;	proj.m30 = 0.0f; proj.m31 = 0.0f;            proj.m32 = 1.0f;          proj.m33 = 0.0f;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EuhmH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8913" PostHistoryTypeId="5" PostId="4077" RevisionGUID="bd173855-8a97-4560-accc-d3586f9f7b0a" CreationDate="2016-10-05T23:50:44.620" UserId="120" Comment="Update the SIMT part." Text="Let's go through the paper you mentioned and try to list the factors which will affect your decision on whether to use GPU or CPU for simulation.&#xD;&#xA;I will also add some comments about my opinion for each factor.&#xD;&#xA;&#xD;&#xA;## Computation bound&#xD;&#xA;A GPU program runs in a SIMT(Single instruction, multiple threads) model.&#xD;&#xA;In this model, if some threads stall due to memory access or divergence,&#xD;&#xA;thread scheduler will schedule another set of threads to run&#xD;&#xA;to hide the memory latency.&#xD;&#xA;&#xD;&#xA;As we can see it requires adequate computation load to make this mechanism work.&#xD;&#xA;If one implementation is memory bound, we hardly benefit from the SIMT programming model.&#xD;&#xA;&#xD;&#xA;Fortunately, fluid simulation is a computation bound task for most of the cases.&#xD;&#xA;&#xD;&#xA;## Locality&#xD;&#xA;In the paper you mentioned we can observe perfect locality:  &#xD;&#xA;for each grid point we only have to examine its neighbors.&#xD;&#xA;&#xD;&#xA;The actual memory access pattern depends on the finite difference scheme you use.&#xD;&#xA;But for all grid based simulation methods(Eulerian or Lattice-Boltzmann method), I think the locality always presents.&#xD;&#xA;&#xD;&#xA;## Divergence&#xD;&#xA;A warp (a group of 32 threads) in a GPU program can be executed in parallel if they follow the same code path. Otherwise the program diverges and the execution of each branch will be serialized. Divergence will hurt the performance.&#xD;&#xA;&#xD;&#xA;In particle based simulations (such as SPH method) we usually have to query the nearest N particles. A tree-like data structure will be used.&#xD;&#xA;&#xD;&#xA;In GPU a tree data structure may introduce divergence because particles may fall into different branches.&#xD;&#xA;&#xD;&#xA;The paper you mentioned uses grid based methods, where all threads execute along the same code path (Jacobi or Gauss-Seidel iteration), so divergence is not a problem here.&#xD;&#xA;&#xD;&#xA;## Interactivity&#xD;&#xA;In the paper it uses static boundary conditions.  &#xD;&#xA;For this case you just need to upload the boundary conditions to GPU memory only once.&#xD;&#xA;&#xD;&#xA;If you have dynamic boundary conditions, for example, which are specified by the user at each frame, the overhead of memory transfer between GPU and CPU should be taken into consideration.&#xD;&#xA;&#xD;&#xA;## Spatial complexity&#xD;&#xA;Uniform grid based simulations cannot handle very large computation volume, because the spatial complexity is cubic.&#xD;&#xA;&#xD;&#xA;There are adaptive grid methods, which use relatively higher resolution for the computation region we are most interested in. But that would also bring in divergence.&#xD;&#xA;&#xD;&#xA;## Numerical issues&#xD;&#xA;For fluid simulation you cannot decide the number of steps solely based on the performance/frame rate.&#xD;&#xA;&#xD;&#xA;In grid based methods, the Courant–Friedrichs–Lewy (CFL) condition puts a constraint on how large simulation step you can have.&#xD;&#xA;Given a fixed time step, too large or too small steps would cause instability and blow up the simulation.&#xD;&#xA;&#xD;&#xA;In particle based methods and some stable grid based methods (such as the semi-Lagrangian method used in the paper), we can use relatively larger simulation steps.&#xD;&#xA;&#xD;&#xA;But we still cannot increase the step size with no bound because of the accuracy.&#xD;&#xA;For example in grid based methods a large step size would introduce too much numerical viscosity.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Summary&#xD;&#xA;As a summary, if your simulation has strong convergence and locality, prefer a GPU implementation; otherwise, prefer a CPU one.&#xD;&#xA;&#xD;&#xA;In practice, I will always implement a CPU version because it is easier to debug and it will be useful as a baseline.&#xD;&#xA;Then I will profile it to locate the bottleneck and decide whether to have a GPU version." ContentLicense="CC BY-SA 3.0" />
  <row Id="8918" PostHistoryTypeId="5" PostId="4086" RevisionGUID="8e8a1d44-7ce5-47a9-afcc-d4fa0daf878e" CreationDate="2016-10-06T11:50:11.057" UserId="137" Comment="added 50 characters in body" Text="It is only 3 degrees of freedom (when talking about a rotation around the origin).&#xD;&#xA;&#xD;&#xA;An arbitrary axis can be specified by 1 3D vector however the length doesn't matter so it only takes 2 degrees of freedom. Then you add the rotation angle to it and you have 3 degrees of freedom.&#xD;&#xA;&#xD;&#xA;If you mean a rotation around a arbitrary point other than the origin then that point takes up 3 additional degrees of freedom for a total of 6." ContentLicense="CC BY-SA 3.0" />
  <row Id="8919" PostHistoryTypeId="2" PostId="4091" RevisionGUID="33cbdab4-3615-42ad-9dda-1770719bef73" CreationDate="2016-10-06T12:11:11.807" UserId="1952" Text="You are on the right track but what you need to do is to calculate u/w and v/w, and also 1/w for each vertex, which you interpolate linearly in screen space in your rasterizer. Then for every pixel you divide the interpolated u/w and v/w coordinates with the interpolated 1/w to get perspective correct uv-coordinates for the pixel.&#xD;&#xA;&#xD;&#xA;The same applies to all the vertex properties, e.g. if you need to get perspective correct color or position of vertices per pixel, then you interpolate c/w and p/w and divide those values by 1/w per pixel. Even if you don't implement software rasterizer this can be quite useful for example in ray marching of screen-space reflection implementation. I have seen people doing the ray marching for SSR in world space because they don't know how to properly interpolate position in screen space.&#xD;&#xA;&#xD;&#xA;What old software rasterizers used to do is to perform this 1/(1/w) division only every X pixels and linearly interpolate values in-between because the division was relatively expensive operation to perform every pixel.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8921" PostHistoryTypeId="5" PostId="4091" RevisionGUID="d6010c67-e6bb-413a-9c67-9cd2cdaffe01" CreationDate="2016-10-06T13:01:13.223" UserId="1952" Comment="edited body" Text="You are on the right track but what you need to do is to calculate u/w and v/w, and also 1/w for each vertex, which you interpolate linearly in screen space in your rasterizer. Then for every pixel you divide the interpolated u/w and v/w coordinates with the interpolated 1/w to get perspective correct uv-coordinates for the pixel.&#xD;&#xA;&#xD;&#xA;The same applies to all the vertex attributes, e.g. if you need to get perspective correct color or position of vertices per pixel, then you interpolate c/w and p/w and divide those values by 1/w per pixel. Even if you don't implement software rasterizer this can be quite useful for example in ray marching of screen-space reflection implementation. I have seen people doing the ray marching for SSR in world space because they don't know how to properly interpolate position in screen space.&#xD;&#xA;&#xD;&#xA;What old software rasterizers used to do is to perform this 1/(1/w) division only every X pixels and linearly interpolate values in-between because the division was relatively expensive operation to perform every pixel.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8922" PostHistoryTypeId="2" PostId="4092" RevisionGUID="02714e72-189d-4e93-9f1e-1c96330bb6d7" CreationDate="2016-10-06T14:23:27.260" UserId="5246" Text="When I was doing some graphic designing with JavaScript, I saw this strange behaviour.&lt;br&gt;&#xD;&#xA;When I ran the following code (with proper HTML and JavaScript of course),                                                                                                                                          &lt;pre&gt;&#xD;&#xA;&lt;code&gt;&#xD;&#xA;context.lineTo(100, 100);&#xD;&#xA;context.lineTo(200, 200);&#xD;&#xA;context.stroke();&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;the result was a straight line from (100, 100) to (200, 200), which I wasn't expecting. I expected that nothing would be drawn. I think this would only happen with the following code:&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;&#xD;&#xA;context.beginPath();&#xD;&#xA;context.moveTo(100, 100);&#xD;&#xA;context.lineTo(200, 200);&#xD;&#xA;context.stroke();&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt; &#xD;&#xA;Is my thinking wrong? Why is it happening so? Can anyone explain? Thank You.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8923" PostHistoryTypeId="1" PostId="4092" RevisionGUID="02714e72-189d-4e93-9f1e-1c96330bb6d7" CreationDate="2016-10-06T14:23:27.260" UserId="5246" Text="Successive lineTo(x, y) in JavaScript" ContentLicense="CC BY-SA 3.0" />
  <row Id="8924" PostHistoryTypeId="3" PostId="4092" RevisionGUID="02714e72-189d-4e93-9f1e-1c96330bb6d7" CreationDate="2016-10-06T14:23:27.260" UserId="5246" Text="|javascript|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8925" PostHistoryTypeId="2" PostId="4093" RevisionGUID="1900112a-19fd-44d0-bbc2-f53df751958b" CreationDate="2016-10-06T14:35:54.007" UserId="16" Text="Straight from the [specification](https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-lineto) of `lineTo`:&#xD;&#xA;&#xD;&#xA;&gt; If the object's path has no subpaths, then ensure there is a subpath for (x, y).&#xD;&#xA;&#xD;&#xA;And &quot;ensure that there is a subpath links to [this bit](https://html.spec.whatwg.org/multipage/scripting.html#ensure-there-is-a-subpath):&#xD;&#xA;&#xD;&#xA;&gt; When the user agent is to ensure there is a subpath for a coordinate (x, y) on a path, the user agent must check to see if the path has its need new subpath flag set. If it does, then the user agent must create a new subpath with the point (x, y) as its first (and only) point, as if the `moveTo()` method had been called, and must then unset the path's need new subpath flag.&#xD;&#xA;&#xD;&#xA;In short, if you call `lineTo` without an explicit `beginPath`, then a new path is created implicitly, with the given point as its starting point." ContentLicense="CC BY-SA 3.0" />
  <row Id="8926" PostHistoryTypeId="5" PostId="4092" RevisionGUID="4580ca2c-45aa-4b6e-a481-f0250c12a674" CreationDate="2016-10-06T14:37:01.397" UserId="16" Comment="less HTML, more markdown" Text="When I was doing some graphic designing with JavaScript, I saw this strange behaviour.  &#xD;&#xA;When I ran the following code (with proper HTML and JavaScript of course),&#xD;&#xA;&#xD;&#xA;    context.lineTo(100, 100);&#xD;&#xA;    context.lineTo(200, 200);&#xD;&#xA;    context.stroke();&#xD;&#xA;&#xD;&#xA;The result was a straight line from (100, 100) to (200, 200), which I wasn't expecting. I expected that nothing would be drawn. I think this would only happen with the following code:&#xD;&#xA;&#xD;&#xA;    context.beginPath();&#xD;&#xA;    context.moveTo(100, 100);&#xD;&#xA;    context.lineTo(200, 200);&#xD;&#xA;    context.stroke();&#xD;&#xA;&#xD;&#xA;Is my thinking wrong? Why is it happening so? Can anyone explain?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8927" PostHistoryTypeId="5" PostId="4093" RevisionGUID="ebda4783-3956-42be-ace0-397e7d3b5e14" CreationDate="2016-10-06T14:53:55.370" UserId="16" Comment="added 1 character in body" Text="Straight from the [specification](https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-lineto) of `lineTo`:&#xD;&#xA;&#xD;&#xA;&gt; If the object's path has no subpaths, then ensure there is a subpath for (x, y).&#xD;&#xA;&#xD;&#xA;And &quot;ensure that there is a subpath&quot; links to [this bit](https://html.spec.whatwg.org/multipage/scripting.html#ensure-there-is-a-subpath):&#xD;&#xA;&#xD;&#xA;&gt; When the user agent is to ensure there is a subpath for a coordinate (x, y) on a path, the user agent must check to see if the path has its *need new subpath flag* set. If it does, then the user agent must create a new subpath with the point (x, y) as its first (and only) point, as if the `moveTo()` method had been called, and must then unset the path's *need new subpath flag*.&#xD;&#xA;&#xD;&#xA;In short, if you call `lineTo` without an explicit `beginPath`, then a new path is created implicitly, with the given point as its starting point." ContentLicense="CC BY-SA 3.0" />
  <row Id="8928" PostHistoryTypeId="2" PostId="4094" RevisionGUID="a4238f9c-e260-4b7f-90a4-54eb5b612c23" CreationDate="2016-10-06T16:20:18.093" UserId="56" Text="One of the features of ray marching is that you can use modulus to repeat shapes infinitely, like in the image below, which is from https://www.shadertoy.com/view/MsBGW1&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I was curious if there exists any technique which allows you to do the same thing with ray tracing instead of ray marching?&#xD;&#xA;&#xD;&#xA;One method I do know of is to ray trace a plane from above, and then where you hit the plane, calculate your location on a grid on that plane, and use the relative position in that grid cell as an absolute position to raytrace a scene.  That will repeat the scene across the grid.&#xD;&#xA;&#xD;&#xA;However, a problem with that is if your ray doesn't hit anything in the grid cell, and it would then enter another grid cell, this technique won't catch those other shapes without walking the grid cells down the path of the ray until it exits the back side of the grid, which is very ray-marching-esque and iterative.&#xD;&#xA;&#xD;&#xA;Does anyone know of a technique that allows you to have ray marching type repetition in ray tracing?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SKXUF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8929" PostHistoryTypeId="1" PostId="4094" RevisionGUID="a4238f9c-e260-4b7f-90a4-54eb5b612c23" CreationDate="2016-10-06T16:20:18.093" UserId="56" Text="Is there a method to do ray marching style modulus repeat with raytracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8930" PostHistoryTypeId="3" PostId="4094" RevisionGUID="a4238f9c-e260-4b7f-90a4-54eb5b612c23" CreationDate="2016-10-06T16:20:18.093" UserId="56" Text="|raytracing|raymarching|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8931" PostHistoryTypeId="2" PostId="4095" RevisionGUID="17f164d7-666a-4adb-91ad-8cd461eefe0c" CreationDate="2016-10-06T17:04:22.083" UserId="56" Text="Even though I didn't know about monte carlo path tracing when I wrote this, I accidentally described it.  Ironically, monte carlo path tracing is the answer I was looking for at the time.&#xD;&#xA;&#xD;&#xA;Naive monte carlo path tracing works by evaluating something called the rendering equation to numerically solve the color value of a pixel.  It takes random samples by randomly jittering within a pixel (there are better sampling strategies, and filtering: http://computergraphics.stackexchange.com/questions/4013/what-is-the-fundamental-reasoning-for-anti-aliasing-using-multiple-random-sample) and also by bouncing in random directions when a ray hits a surface.&#xD;&#xA;&#xD;&#xA;It can take a lot of samples to give you good results, and with not enough samples, your image will look noisy.  It takes 4 times as many samples to cut the noise in half.  Render times can be on the order of an hour using 8 modern CPU cores for a simple scene.&#xD;&#xA;&#xD;&#xA;There are more advanced monte carlo path tracing techniques that let you get better images more quickly, such as importance sampling, or denoising the image after it's rendered.&#xD;&#xA;&#xD;&#xA;Monte carlo path tracing can make photorealistic images and gives you many advanced rendering features just because it follows physical laws so gives realistic results.&#xD;&#xA;&#xD;&#xA;You can read more about it here:&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/&#xD;&#xA;&#xD;&#xA;Here is an example image, which took about an hour to render using all 8 of my cpu cores:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EacNQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8933" PostHistoryTypeId="2" PostId="4096" RevisionGUID="1fc157a1-bbc9-4054-a410-e1267d1b5da6" CreationDate="2016-10-06T19:02:30.053" UserId="1952" Text="Path tracing is the standard technique in non-realtime photorealistic rendering, and you should look specifically into [bidirectional path tracing][1] to get effects like caustics, which you can't really get with basic path tracing. Also [Metropolis light transport][2] (MLT) is a more advanced path tracing technique that converges faster to the ground truth by mutating existing &quot;good&quot; paths.&#xD;&#xA;&#xD;&#xA;You can also use importance sampling for faster convergence by focusing more rays to the directions that matter more. I.e. by focusing rays based on BRDF (more towards the BRDF spike using probability density function) or to the light source, or get best of the two worlds and using multiple importance sampling. &#xD;&#xA;&#xD;&#xA;This is all about reducing noise in unbiased manner. There are also [denoising techniques][3] to further reduce noise in the rendered images.&#xD;&#xA;&#xD;&#xA;I think it's best to first implement basic brute force Monte Carlo path tracer to serve as unbiased reference before looking into the more advanced techniques. It's quite easy to do mistakes and introduce biasing that goes unnoticed, so having simple implementation is good to have around for reference.&#xD;&#xA;&#xD;&#xA;You can also get some really nice results by applying path tracing to participating media but that gets slow really fast :D&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Path_tracing#Bidirectional_path_tracing&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Metropolis_light_transport&#xD;&#xA;  [3]: https://benedikt-bitterli.me/nfor/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8934" PostHistoryTypeId="5" PostId="4096" RevisionGUID="4cca9471-cb0a-4c25-9be9-d0bfcab4b145" CreationDate="2016-10-06T19:37:04.423" UserId="1952" Comment="added 524 characters in body" Text="Path tracing is the standard technique in non-realtime photorealistic rendering, and you should look specifically into [bidirectional path tracing][1] to get effects like caustics, which you can't really get with basic path tracing. Bidirectional path tracing also converges faster to the ground truth as shown in the below image:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Also [Metropolis light transport][3] (MLT) is a more advanced path tracing technique that converges even faster to the ground truth by mutating existing &quot;good&quot; paths:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;You can also use importance sampling for faster convergence by focusing more rays to the directions that matter more. I.e. by focusing rays based on BRDF (more towards the BRDF spike using probability density function) or to the light source, or get best of the two worlds and using multiple importance sampling. &#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;This is all about reducing noise in unbiased manner. There are also [denoising techniques][6] to further reduce noise in the rendered images.&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;I think it's best to first implement basic brute force Monte Carlo path tracer to serve as unbiased reference before looking into the more advanced techniques. It's quite easy to do mistakes and introduce biasing that goes unnoticed, so having simple implementation is good to have around for reference.&#xD;&#xA;&#xD;&#xA;You can also get some really nice results by applying path tracing to participating media but that gets slow really fast :D&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Path_tracing#Bidirectional_path_tracing&#xD;&#xA;  [2]: https://i.stack.imgur.com/3fg6U.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Metropolis_light_transport&#xD;&#xA;  [4]: https://i.stack.imgur.com/KoMaU.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/TiwGE.png&#xD;&#xA;  [6]: https://benedikt-bitterli.me/nfor/&#xD;&#xA;  [7]: https://i.stack.imgur.com/YFQ8H.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/3Cmp6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8935" PostHistoryTypeId="2" PostId="4097" RevisionGUID="f7f28392-ac8a-40ea-8be1-33e84b6e53ec" CreationDate="2016-10-06T19:47:20.410" UserId="5249" Text="I'm implementing bidirectional path tracing. I want to simulate perfect refraction. I read in the Veach thesis that a perfect refraction BSDF is non-symmetric. Does it mean that I need to use different computations for refraction BSDF (BTDF) for eye subpaths and light subpaths? It seems strange for me, as BPT differs from PT only in the way I generate the path and throughput computations should be the same, as in PT all BSDFs are computed in the same way. Is that non symmetry relevant only for particle based techniques like Photon Mapping?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8936" PostHistoryTypeId="1" PostId="4097" RevisionGUID="f7f28392-ac8a-40ea-8be1-33e84b6e53ec" CreationDate="2016-10-06T19:47:20.410" UserId="5249" Text="Should I use nonsymmetric BSDF for refraction in BPT?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8937" PostHistoryTypeId="3" PostId="4097" RevisionGUID="f7f28392-ac8a-40ea-8be1-33e84b6e53ec" CreationDate="2016-10-06T19:47:20.410" UserId="5249" Text="|raytracing|brdf|pathtracing|global-illumination|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8939" PostHistoryTypeId="2" PostId="4098" RevisionGUID="38652f98-9506-441b-ae81-d52a9a36a38c" CreationDate="2016-10-06T22:13:29.590" UserId="4958" Text="Recently in searching of solving the shadow acne problem of traditional shadow mapping I implemented exponential shadow maps. It did the trick (no acne at all) but at the same time introduced other unacceptable errors.&#xD;&#xA;&#xD;&#xA;For depth map blur I use gaussian blur with smallest sigma=1.&#xD;&#xA;&#xD;&#xA;Test for shadow map:&#xD;&#xA;&#xD;&#xA;    float occluder = texture(shadowMap lightCoords.xy).r;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords[index].z;&#xD;&#xA;    float shadow = exp(c*(occluder-receiver));&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;with small c factor `c=100.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;Unacceptable light bleeding&#xD;&#xA;&#xD;&#xA;with high c factor `c=5000.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][3]&#xD;&#xA;&#xD;&#xA;No light bleeding but high frequency detail appear &quot;swollen&quot;.&#xD;&#xA;&#xD;&#xA;Cant find optimal c - light bleeding appear even at `c=3000.0` and high frequency shadow error is already there. Not bluring depth map helps but then aliasing occurs.&#xD;&#xA;&#xD;&#xA;And my question is - how can I improve this technique (ESM) or should I look for another? I think good quality shadows with nice performance are definitely possible - as seen in modern games like Witcher 3 or Fallout 4.&#xD;&#xA;  [1]: https://i.stack.imgur.com/2EHPH.jpg&#xD;&#xA;[2]: https://i.stack.imgur.com/2EHPHm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/BBYtJ.jpg&#xD;&#xA;[4]: https://i.stack.imgur.com/BBYtJm.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8940" PostHistoryTypeId="1" PostId="4098" RevisionGUID="38652f98-9506-441b-ae81-d52a9a36a38c" CreationDate="2016-10-06T22:13:29.590" UserId="4958" Text="searching for acceptable quality shadow mapping techniques" ContentLicense="CC BY-SA 3.0" />
  <row Id="8941" PostHistoryTypeId="3" PostId="4098" RevisionGUID="38652f98-9506-441b-ae81-d52a9a36a38c" CreationDate="2016-10-06T22:13:29.590" UserId="4958" Text="|rendering|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8942" PostHistoryTypeId="5" PostId="4098" RevisionGUID="7d860ca4-e377-473a-8e26-67ad46fcb743" CreationDate="2016-10-06T22:32:50.570" UserId="4958" Comment="added 3 characters in body" Text="Recently while searching of solving the shadow acne problem of traditional shadow mapping I implemented exponential shadow maps. It did the trick (no acne at all) but at the same time introduced other unacceptable errors.&#xD;&#xA;&#xD;&#xA;For depth map blur I use gaussian blur with smallest sigma=1.&#xD;&#xA;&#xD;&#xA;Test for shadow map:&#xD;&#xA;&#xD;&#xA;    float occluder = texture(shadowMap lightCoords.xy).r;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords[index].z;&#xD;&#xA;    float shadow = exp(c*(occluder-receiver));&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;with small c factor `c=100.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;Unacceptable light bleeding&#xD;&#xA;&#xD;&#xA;with high c factor `c=5000.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][3]&#xD;&#xA;&#xD;&#xA;No light bleeding but high frequency detail appear &quot;swollen&quot;.&#xD;&#xA;&#xD;&#xA;Cant find optimal c - light bleeding appear even at `c=3000.0` and high frequency shadow error is already there. Not bluring depth map helps but then aliasing occurs.&#xD;&#xA;&#xD;&#xA;And my question is - how can I improve this technique (ESM) or should I look for another? I think good quality shadows with nice performance are definitely possible - as seen in modern games like Witcher 3 or Fallout 4.&#xD;&#xA;  [1]: https://i.stack.imgur.com/2EHPH.jpg&#xD;&#xA;[2]: https://i.stack.imgur.com/2EHPHm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/BBYtJ.jpg&#xD;&#xA;[4]: https://i.stack.imgur.com/BBYtJm.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8943" PostHistoryTypeId="5" PostId="4098" RevisionGUID="85470a50-4a2c-4c31-a4f9-d38952d91220" CreationDate="2016-10-06T22:40:48.550" UserId="4958" Comment="added 5 characters in body" Text="Recently while searching of solving the shadow acne problem of traditional shadow mapping I implemented exponential shadow maps. It did the trick (no acne at all) but at the same time introduced other unacceptable errors.&#xD;&#xA;&#xD;&#xA;For depth map blur I use gaussian blur with smallest sigma=1.&#xD;&#xA;&#xD;&#xA;Test for shadow map:&#xD;&#xA;&#xD;&#xA;    float occluder = texture(shadowMap lightCoords.xy).r;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords[index].z;&#xD;&#xA;    float shadow = exp(c*(occluder-receiver));&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;with small c factor `c=100.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;Unacceptable light bleeding&#xD;&#xA;&#xD;&#xA;with high c factor `c=5000.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][3]&#xD;&#xA;&#xD;&#xA;No light bleeding but high frequency detail appear &quot;swollen&quot;.&#xD;&#xA;&#xD;&#xA;Cant find optimal c - light bleeding appear even at `c=3000.0` and high frequency shadow error is already there. Not blurring the depth map helps but then aliasing occurs.&#xD;&#xA;&#xD;&#xA;And my question is - how can I improve this technique (ESM) or should I look for another? I think good quality shadows with nice performance are definitely possible - as seen in modern games like Witcher 3 or Fallout 4.&#xD;&#xA;  [1]: https://i.stack.imgur.com/2EHPH.jpg&#xD;&#xA;[2]: https://i.stack.imgur.com/2EHPHm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/BBYtJ.jpg&#xD;&#xA;[4]: https://i.stack.imgur.com/BBYtJm.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8945" PostHistoryTypeId="5" PostId="4098" RevisionGUID="76673e25-fe3c-4ea1-b8fd-55a6f5758e4d" CreationDate="2016-10-07T08:39:52.923" UserId="4958" Comment="deleted 7 characters in body" Text="Recently while searching of solving the shadow acne problem of traditional shadow mapping I implemented exponential shadow maps. It did the trick (no acne at all) but at the same time introduced other unacceptable errors.&#xD;&#xA;&#xD;&#xA;For depth map blur I use gaussian blur with smallest sigma=1.&#xD;&#xA;&#xD;&#xA;Test for shadow map:&#xD;&#xA;&#xD;&#xA;    float occluder = texture(shadowMap lightCoords.xy).r;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = exp(c*(occluder-receiver));&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;with small c factor `c=100.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;Unacceptable light bleeding&#xD;&#xA;&#xD;&#xA;with high c factor `c=5000.0`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][3]&#xD;&#xA;&#xD;&#xA;No light bleeding but high frequency detail appear &quot;swollen&quot;.&#xD;&#xA;&#xD;&#xA;Cant find optimal c - light bleeding appear even at `c=3000.0` and high frequency shadow error is already there. Not blurring the depth map helps but then aliasing occurs.&#xD;&#xA;&#xD;&#xA;And my question is - how can I improve this technique (ESM) or should I look for another? I think good quality shadows with nice performance are definitely possible - as seen in modern games like Witcher 3 or Fallout 4.&#xD;&#xA;  [1]: https://i.stack.imgur.com/2EHPH.jpg&#xD;&#xA;[2]: https://i.stack.imgur.com/2EHPHm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/BBYtJ.jpg&#xD;&#xA;[4]: https://i.stack.imgur.com/BBYtJm.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8947" PostHistoryTypeId="2" PostId="4099" RevisionGUID="534aa2b7-c84b-4308-b5d4-b75ee105006c" CreationDate="2016-10-07T13:46:06.943" UserId="5253" Text="I am a student of computer science and this semester is my first semester of MSc !next semester I must choose advisor and subject of my dissertation,I somehow know what geometric modeling is and I want to research in this area! but I don't know where should I start! Can anyone who is a professional researcher in geometric modeling help me where I should start? what are best books or journal in this field! what are essential software/libraries/programming languages I must be familiar?&#xD;&#xA;Does this field have problems to work on?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8948" PostHistoryTypeId="1" PostId="4099" RevisionGUID="534aa2b7-c84b-4308-b5d4-b75ee105006c" CreationDate="2016-10-07T13:46:06.943" UserId="5253" Text="I need advice and good reference in geometric modeling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8949" PostHistoryTypeId="3" PostId="4099" RevisionGUID="534aa2b7-c84b-4308-b5d4-b75ee105006c" CreationDate="2016-10-07T13:46:06.943" UserId="5253" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8950" PostHistoryTypeId="2" PostId="4100" RevisionGUID="55422071-74c9-4a5a-8df8-8004dbfccd94" CreationDate="2016-10-07T14:15:31.037" UserId="56" Text="As a graphics professional, not a researcher, it's a bit hard to know what exactly is or is not part of geometric modeling, but looking at this page (http://graphics.cs.ucdavis.edu/~joy/GeometricModelingLectures/) it looks like it's just all about different ways to model surfaces, whether that's with triangles, mathematical descriptions, or other things.&#xD;&#xA;&#xD;&#xA;If that is the case, yeah, there are still open problems.&#xD;&#xA;&#xD;&#xA;Here is a journal with some papers on the topic:&#xD;&#xA;http://jcgt.org/&#xD;&#xA;&#xD;&#xA;I would also look at the SIGGRAPH conference topics over the years, there is a lot of that sort of thing there.&#xD;&#xA;&#xD;&#xA;IMO you are going to find that the problems are broken up into two main groups:&#xD;&#xA;&#xD;&#xA; - Real Time Graphics&#xD;&#xA; - Non Real Time Graphics&#xD;&#xA;&#xD;&#xA;Video games and real time simulation software has the primary need of needing representations that can be rendered in real time, and are also fairly efficient as far as size, so that they don't take up too much memory.&#xD;&#xA;&#xD;&#xA;Modern day movies, and also &quot;offline processes&quot; (such as baking out lighting into textures to use in real time applications) use non real time rendering techniques to get high quality results.  Speed and memory still matter to them of course, but the restrictions are much more relaxed as it isn't uncommon for a single frame of a movie to take a day to render, using a cluster of machines in a rendering farm.&#xD;&#xA;&#xD;&#xA;Both real time and non real time graphics also have needs beyond rigid body geometry though, and also are interested in finding good ways to model liquids, gasses like smoke, and other things.&#xD;&#xA;&#xD;&#xA;Besides the obvious representations of geometry like triangle and quad meshes, or bezier and other analytical shapes, there is also a lesser known concept of the signed distance field which can be used for both 3d modeling as well as 2d vector graphics.  In both cases, when you zoom into these shapes they have inifinite detail - such as being completely smooth, or having a perfectly sharp corner or whatever else.&#xD;&#xA;&#xD;&#xA;Here's a video about one way subdivision surfaces can be achieved in real time graphics, shown at SIGGRAPH 2016, regarding the call of duty game:&#xD;&#xA;https://www.youtube.com/watch?v=PTGTviYwolE&#xD;&#xA;&#xD;&#xA;If I were in your shoes, part of what I would research would be what the &quot;demo scene&quot; is up to.  By demo scene I mean the people who make 64KB executables that when you run them, display photo realistic movies and have music and audio as well.  Those folks have some very creative ways of doing things that often ties into cutting edge research topics.&#xD;&#xA;&#xD;&#xA;Shadertoy.com is a place where you can write webgl pixel shaders and share them with others.  There is a lot of really interesting and exotic graphics stuff there, including signed distance field rendering, ray marching, ray tracing, path tracing, and more.&#xD;&#xA;https://www.shadertoy.com/&#xD;&#xA;&#xD;&#xA;Here's a demoscene website:&#xD;&#xA;http://www.pouet.net/&#xD;&#xA;&#xD;&#xA;Lastly, if I may humbly point you towards a paper I wrote, I came up with a technique for getting the GPU texture sampler to calculate Bezier curve points of arbitrary dimension for you as part of a texture lookup, using the non programmable N-dimensional texture sample linear interpolator.&#xD;&#xA;&#xD;&#xA;I believe it can be expanded to support Bezier surfaces as well, but haven't yet looked into the details of that.&#xD;&#xA;&#xD;&#xA;http://blog.demofox.org/2016/02/22/gpu-texture-sampler-bezier-curve-evaluation/" ContentLicense="CC BY-SA 3.0" />
  <row Id="8951" PostHistoryTypeId="2" PostId="4101" RevisionGUID="dfd1d0bd-9f3b-4c25-bc4b-b4122a3eb92d" CreationDate="2016-10-07T14:25:22.823" UserId="2941" Text="I need to write a photo-realistic renderer. I have been looking at ScratchAPixel site, asking a couple of questions here on CG, and going through the Advanced Global Illumination 2nd ed book. I've read about radiometry, probability, Monte Carlo, and a bit on Russian roulette. I'm aware of the rendering equation in its hemispherical and area formulations. I've written a SAH based kd-tree, so am ok for efficient ray casting.&#xD;&#xA;&#xD;&#xA;I'm poised to start writing some code alongside reading chapter 5 of my book which is about path tracing algorithms. However, the last half of chapter 4 is taken up with talking about the following concepts:&#xD;&#xA;&#xD;&#xA; - The Importance Function&#xD;&#xA; - The Measurement Equation&#xD;&#xA; - Adjoint equations and linear transport operators&#xD;&#xA; - GRDF (Global Reflectance Distribution Function)&#xD;&#xA;&#xD;&#xA;These concepts I've not seen appearing elsewhere in my research (if you can call reading a few web pages about GI rendering proper research?). My question is, **do I really need to know this stuff to progress to writing my path tracer?** I suspect the answer might depend on which type of path tracer I'm going to developer. To start, based upon what little I know, I think it'll be unidirectional." ContentLicense="CC BY-SA 3.0" />
  <row Id="8952" PostHistoryTypeId="1" PostId="4101" RevisionGUID="dfd1d0bd-9f3b-4c25-bc4b-b4122a3eb92d" CreationDate="2016-10-07T14:25:22.823" UserId="2941" Text="Can I ignore importance, adjoint equations, GRDFs for my path tracer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8953" PostHistoryTypeId="3" PostId="4101" RevisionGUID="dfd1d0bd-9f3b-4c25-bc4b-b4122a3eb92d" CreationDate="2016-10-07T14:25:22.823" UserId="2941" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8954" PostHistoryTypeId="2" PostId="4102" RevisionGUID="3c503485-0ad6-4674-a276-e6a7e88d52a5" CreationDate="2016-10-07T18:25:47.573" UserId="1952" Text="No, you don't need to know this stuff to implement basic path tracer.&#xD;&#xA;&#xD;&#xA;Basic unidirectional path tracer is quite simple to implement. Just trace bunch of paths of length X for each pixel with uniform distribution over the normal oriented hemisphere at the path's intersection points. Then weight the remaining path with the BRDF at each intersection point and multiply with luminance of light once the path hits a light.&#xD;&#xA;&#xD;&#xA;You'll get quite a noisy (but unbiased!) image even for large number of rays and then you can start to look into methods to reduce noise, e.g. importance sampling &amp; bidirectional path tracing. Just validate the more optimized path tracers towards earlier validated path tracers to avoid introducing accidental bias.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8955" PostHistoryTypeId="5" PostId="4102" RevisionGUID="d42e2448-f552-47f5-97cb-c6ffb7e543dd" CreationDate="2016-10-07T18:37:58.797" UserId="1952" Comment="added 1 character in body" Text="No, you don't need to know this stuff to implement basic path tracer.&#xD;&#xA;&#xD;&#xA;Basic unidirectional path tracer is quite simple to implement. Just trace bunch of paths of length X for each pixel with uniform distribution over the normal oriented hemisphere at the path's intersection points. Then weight the remaining path with the BRDF at each intersection point and multiply with luminance of light once the path hits a light.&#xD;&#xA;&#xD;&#xA;You'll get quite a noisy (but unbiased!) image even for large number of paths and then you can start to look into methods to reduce noise, e.g. importance sampling &amp; bidirectional path tracing. Just validate the more optimized path tracers towards earlier validated path tracers to avoid introducing accidental bias.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8956" PostHistoryTypeId="5" PostId="4099" RevisionGUID="5c779f8f-cdae-4e8a-a7a4-5ad285a866e7" CreationDate="2016-10-08T07:55:02.843" UserId="231" Comment="Remove request for external resources so the question can avoid being closed" Text="I am a student of computer science and this semester is my first semester of MSc. Next semester I must choose an advisor and the subject of my dissertation. I somewhat know what geometric modeling is and I want to research in this area, but I don't know where should I start. Can anyone who is a professional researcher in geometric modeling help me with where I should start?&#xD;&#xA;&#xD;&#xA;Does this field have problems to work on?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8958" PostHistoryTypeId="2" PostId="4103" RevisionGUID="f17f5515-b005-4e48-b8af-005ecc44e9d0" CreationDate="2016-10-08T12:49:53.820" UserId="4958" Text="Well nevermind. I made some research and actually gonna:&#xD;&#xA;&#xD;&#xA; - sample ESM using Poisson sampling in PCF fashion (thanks Bart Wronski for great Poisson Sample generator app) and extend this to PCSS technique (variable penumbra). Render to texture.&#xD;&#xA; - optionally depth aware blur" ContentLicense="CC BY-SA 3.0" />
  <row Id="8959" PostHistoryTypeId="2" PostId="4104" RevisionGUID="82e64df0-7f30-455f-b77b-e4a289cfb78b" CreationDate="2016-10-08T19:33:22.113" UserId="5256" Text="So recently I have been learning how to implement Diffuse Lighting in DirectX and I have done so with the following code:&#xD;&#xA;&#xD;&#xA;    float4 PS(VS_OUTPUT input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        input.normal = normalize(input.normal);&#xD;&#xA;    &#xD;&#xA;        float4 diffuse = ObjTexture.Sample(ObjSamplerState, input.TexCoord);&#xD;&#xA;    &#xD;&#xA;        float3 finalColor;&#xD;&#xA;    &#xD;&#xA;        finalColor = diffuse * light.ambient;&#xD;&#xA;        finalColor += saturate(dot(light.dir, input.normal) * light.diffuse * diffuse);&#xD;&#xA;    &#xD;&#xA;        return float4(finalColor, diffuse.a);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;which has produced the following results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Before I progress any further with specular lighting I wanted to clean up my code a little so I re-implemented this with a function and few changes. &#xD;&#xA;&#xD;&#xA;    float3 DirectDiffuseBRDF(float3 diffuseAlbedo, float nDotL)&#xD;&#xA;    {&#xD;&#xA;    	return (diffuseAlbedo * nDotL);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float4 PS(VS_OUTPUT input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;    	input.normal = normalize(input.normal);&#xD;&#xA;    &#xD;&#xA;        float4 diffuseAlbedo = ObjTexture.Sample(ObjSamplerState, input.TexCoord);&#xD;&#xA;    &#xD;&#xA;    	float nDotL = saturate(dot(input.normal, light.dir));&#xD;&#xA;    &#xD;&#xA;    	float3 diffuseLighting = DirectDiffuseBRDF(diffuseAlbedo, nDotL);&#xD;&#xA;    &#xD;&#xA;        return float4(diffuseLighting, diffuseAlbedo.a);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;Which produces:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7wBHM.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/gaRXr.png&#xD;&#xA;&#xD;&#xA;As you can see the modified code has it's diffuse lighting a little different compared to the original. What am I missing from the original code to get it back to normal?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8960" PostHistoryTypeId="1" PostId="4104" RevisionGUID="82e64df0-7f30-455f-b77b-e4a289cfb78b" CreationDate="2016-10-08T19:33:22.113" UserId="5256" Text="Problem with Basic Diffuse Lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="8961" PostHistoryTypeId="3" PostId="4104" RevisionGUID="82e64df0-7f30-455f-b77b-e4a289cfb78b" CreationDate="2016-10-08T19:33:22.113" UserId="5256" Text="|texture|c++|brdf|directx11|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8962" PostHistoryTypeId="5" PostId="4103" RevisionGUID="04e881bf-69a2-48aa-9c1f-0274b0e1ae72" CreationDate="2016-10-08T20:28:35.083" UserId="4958" Comment="added 106 characters in body" Text="Well nevermind. I made some research and actually gonna:&#xD;&#xA;&#xD;&#xA; - sample ESM using Poisson sampling in PCF fashion (thanks Bart Wronski for great Poisson Sample generator app) and extend this to PCSS technique (variable penumbra). Render to texture.&#xD;&#xA; - optionally depth aware blur - EDIT not so fast this option doesnt work as expected, too bad. Maybe temporal reprojection? But this is pain... &#xD;&#xA;&#xD;&#xA;And too bad not much of discussion here." ContentLicense="CC BY-SA 3.0" />
  <row Id="8963" PostHistoryTypeId="5" PostId="4103" RevisionGUID="41b92fe0-c080-4108-929b-796e2e353a14" CreationDate="2016-10-08T20:41:40.623" UserId="4958" Comment="added 10 characters in body" Text="Well nevermind. I made some research and actually gonna:&#xD;&#xA;&#xD;&#xA; - sample ESM using Poisson sampling in PCF fashion (thanks Bart Wronski for great Poisson Sample generator app) and extend this to PCSS technique (variable penumbra). Render to texture.&#xD;&#xA; - optionally depth aware blur to soften - EDIT not so fast this option doesnt work as expected, too bad. Maybe temporal reprojection? But this is pain... &#xD;&#xA;&#xD;&#xA;And too bad not much of discussion here." ContentLicense="CC BY-SA 3.0" />
  <row Id="8964" PostHistoryTypeId="5" PostId="3748" RevisionGUID="c16b18b3-46fb-4c3c-bf96-79fbc20e5c22" CreationDate="2016-10-08T20:42:22.267" UserDisplayName="user246" Comment="spelling corrections, moved extended comments from code into their own paragrah" Text="I have a pretty good glow shader going now thanks to some tips from people here.&#xD;&#xA;&#xD;&#xA;However there are a few things that bother me that could maybe be better.&#xD;&#xA;&#xD;&#xA;### #1 Definition of the particles &#xD;&#xA;A lot of times if the particles are moving a lot it just looks like a single sheet of color. The image below is zoomed in so you can see a bit more definition, but zoomed out and real time it just looks like a sheet of sorts&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### #2 The particles don't look like they are neon&#xD;&#xA;I mean I don't want the effect to be huge but when they are grouped together I would hope for them to have some white highlighting in the glow.&#xD;&#xA;It looks like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;When it should look more like this (this was just a mockup by blending in an additive copy of it with more contrast) when particles are grouped together [However singular particles shouldn't have white highlights]:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is my current rendering process:&#xD;&#xA;&#xD;&#xA;I have a couple FBO's with texture attachments:&#xD;&#xA;&#xD;&#xA; - Drawing Frame: Never cleared, up-scaled for the purposes of anti-aliasing&#xD;&#xA; - Smaller Frame: Cleared each frame, exact resolution of screen, Draws the drawing frame on it with the darkest parts cut out&#xD;&#xA; - Horizontal Blur: Cleared each frame, does a horizontal blur (lower resolution than screen)&#xD;&#xA; - Vertical Blur: Cleared each frame, blurs the horizontal blur vertically (lower resolution then screen)&#xD;&#xA; - Front buffer: Draws the Smaller frame, and Vertical Buffers on top of each-other to the screen.&#xD;&#xA;&#xD;&#xA;So A typical render might look like this (I apologize for the misalignment and cropping, the Xcode frame debugger allows you to peek at FBO's but not export the texture inside of them I had to use screenshots)&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;To combine the two textures I am using this &#xD;&#xA;&#xD;&#xA;    gl_FragColor = vec4(clamp(texture2D(s_texture, v_texcoord).xyz, 0.,&#xD;&#xA;    1.) + (clamp(texture2D(s_texture2, v_texcoord).xyz, 0., 1.) * 1.5),&#xD;&#xA;    1.0);&#xD;&#xA;&#xD;&#xA;And for the two blurs I am using code like this, a lot of this is pre-computed but to make it easier to read I put how I computed it.&#xD;&#xA;&#xD;&#xA;    float Gaussian(float x, float deviation)&#xD;&#xA;    {&#xD;&#xA;        return (1.0 / sqrt(2.0 * 3.141592 * deviation)) * exp(-((x * x) / (2.0 * deviation)));&#xD;&#xA;    }&#xD;&#xA;    vec3 blurS15()&#xD;&#xA;    &#xD;&#xA;    {&#xD;&#xA;        vec3 blr = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;        float scalart =  (1 / screenResolution.x) * (1.0 / 7.0) * 14.0;&#xD;&#xA;        float deviationScale = 1.2;&#xD;&#xA;        float finalScalar = 1.1;&#xD;&#xA;    &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(7.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(7.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(6.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(6.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(5.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(5.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(4.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(4.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(3.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(3.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(2.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(1.0, 7.0 * deviationScale) ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(0.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(0.0, 7.0 * deviationScale) ;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-1.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-1.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-2.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-2.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-3.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-3.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-4.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-4.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-5.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-5.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-6.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-6.0, 7.0 * deviationScale) ;&#xD;&#xA;        blr += texture2D(s_texture, (v_texcoord + vec2(-7.0 * scalart, 0.0))).xyz *  finalScalar * Gaussian(-7.0, 7.0 * deviationScale) ;&#xD;&#xA;    &#xD;&#xA;        return blr; //This gets put into gl_FragColor&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now while the issue could be in how I calculate the blur, and combine it I think it is more likely that the issue is in the way I render the particles. Basically each particle is rendered with a circle and a rectangle each frame. The dot marks where it is, and the rectangle connects it the the previous frame. Each new frame the previous frame is faded and then drawn over.&#xD;&#xA;&#xD;&#xA;Here is a diagram of the process, each new hue group represents a new frame, sorry for the childish look of the colors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I do this using two draw calls, one that draws the rectangles (GL_TRIANGLES with indices), and one that draws the circles (GL_POINTS with outsides alpha set to 0).&#xD;&#xA;&#xD;&#xA;While this allows me to quickly simulate an accumulation buffer it comes with some drawbacks, if these can be dealt with without compromising speed then it would be nice to change them.&#xD;&#xA;&#xD;&#xA; 1. No actual depth sorting, although the particles could easily have z values it is futile because opengles 2.0 will go black if you don't clear the depth buffer each frame, so it cant really work with an accumulation buffer.&#xD;&#xA; 2. No additive drawing&#xD;&#xA;     - Because there are two separate draw calls, even with that setting on nothing seems to draw additively inside of the same draw call &#xD;&#xA;     - Even if I did the area where the circle and rectangle meet would be extra bright which is undesirable&#xD;&#xA;&#xD;&#xA;The additive mode I tried was&#xD;&#xA;&#xD;&#xA;    glBlendFunc(GLenum(GL_ONE), GLenum(GL_ONE))&#xD;&#xA;    glEnable(GLenum(GL_BLEND));&#xD;&#xA;&#xD;&#xA;To be specific when I said it didn't work I tried disabling it before fade, and then enabling it afterwards. It caused everything to look weird almost as if there were no trails. And there didn't seem to be highlights where particles intersect. However if I had it enabled the whole time then it did look like additive blending. Only the previous frame never faded because you can't draw black in add blend mode.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you can think of any way I can get more highlighting especially when particles collide, or otherwise make the glow effect look better please let me know.&#xD;&#xA;&#xD;&#xA;I am very curious if there is a way to still do depth sorting with an accumulation buffer/a way to not have to clear the depth buffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AO0kc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/UTIo5.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/9NWsT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/4RzP5.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/tVyCW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8965" PostHistoryTypeId="24" PostId="3748" RevisionGUID="c16b18b3-46fb-4c3c-bf96-79fbc20e5c22" CreationDate="2016-10-08T20:42:22.267" Comment="Proposed by 246 approved by 16 edit id of 165" ContentLicense="CC BY-SA 3.0" />
  <row Id="8966" PostHistoryTypeId="5" PostId="2500" RevisionGUID="94e75310-1870-45e0-8d7d-58dda64f0d80" CreationDate="2016-10-08T20:42:42.353" UserDisplayName="user246" Comment="corrected spelling" Text="This is hard to explain but I am going to try, then I will explain it as pure mathematics.&#xD;&#xA;&#xD;&#xA;Look at this image.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;So basically this is a moving line, each frame a new segment is added and the previous frame is faded by an amount decided by fps. (There are dots to make things neat but I'm not showing them for simplicity).&#xD;&#xA;&#xD;&#xA;So based on the FPS a number is calculated (0.05 if perfect FPS ) and as a result the previous frame gets a black plane drawn over it with an opacity of 0.05.&#xD;&#xA;&#xD;&#xA;As you can see this causes an issue because of the segments. My solution is to give each vertex a color, however I don't know how to calculate that color.  The line color is defined by HSV, and the fading is decided by RGB.  Furthermore I am pretty sure fading with the transparent plane creates an exponential effect, however HSV.V works linearly.&#xD;&#xA;&#xD;&#xA;My question is if I know on a given frame that the fading plane will have an opacity of 0.05 how can I calculate an equivalent HSV color to what the previous frame will be after fading? That way the bottom two vertices can be a darker color and interpolation can fix it.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;The formula that decides the opacity of the black is as follows. &#xD;&#xA;&#xD;&#xA;    (dt / (1 / 60)) * 0.5&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jBASF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="8967" PostHistoryTypeId="4" PostId="2500" RevisionGUID="94e75310-1870-45e0-8d7d-58dda64f0d80" CreationDate="2016-10-08T20:42:42.353" UserDisplayName="user246" Comment="corrected spelling" Text="Matching an HSV color with a blended color" ContentLicense="CC BY-SA 3.0" />
  <row Id="8968" PostHistoryTypeId="24" PostId="2500" RevisionGUID="94e75310-1870-45e0-8d7d-58dda64f0d80" CreationDate="2016-10-08T20:42:42.353" Comment="Proposed by 246 approved by 16 edit id of 166" ContentLicense="CC BY-SA 3.0" />
  <row Id="8969" PostHistoryTypeId="5" PostId="4103" RevisionGUID="def11b5a-1ed4-4507-9e5c-58c5a2287548" CreationDate="2016-10-08T21:47:30.660" UserId="4958" Comment="deleted 2 characters in body" Text="Well nevermind. I made some research and actually gonna:&#xD;&#xA;&#xD;&#xA; - sample ESM using Poisson sampling in PCF fashion (thanks Bart Wronski for great Poisson Sample generator app) and extend this to PCSS technique (variable penumbra). Render to texture.&#xD;&#xA; - optionally depth aware blur to soften - EDIT not so fast this option doesnt work as expected, too bad. Instead rotating PCF kernel seem to work fine. &#xD;&#xA;&#xD;&#xA;And too bad not much of discussion here." ContentLicense="CC BY-SA 3.0" />
  <row Id="8970" PostHistoryTypeId="2" PostId="4105" RevisionGUID="1d98208e-7fdd-4458-97d9-78d390ad6d4e" CreationDate="2016-10-08T21:58:21.903" UserId="5257" Text="I'm trying to do object recognition in an embedded environment, and for this I'm using Raspberry Pi (Specifically version 2).&#xD;&#xA;&#xD;&#xA;I'm using OpenCV Library and as of now I'm using feature detection algorithms contained in OpenCV.&#xD;&#xA;&#xD;&#xA;So far I've tried different approaches:&#xD;&#xA;&#xD;&#xA;I tried different keypoint extraction and description algorithms: SIFT, SURF, ORB. SIFT and SURF are too heavy and ORB is not so good.&#xD;&#xA;Then I tried using different algorithms for keypoint extraction and then description. The first approach was to use FAST algorithm to extract key points and then ORB or SURF for description, the results were not good and not rotation invariant, then i tried mixing the others.&#xD;&#xA;I now am to the point where I get the best results time permitting using ORB for keypoint extraction and SURF for description. But it is still really slow.&#xD;&#xA;&#xD;&#xA;Right now it is being used to match the object image (400x200) with frames captured from webcam. My definition of too slow is 2fps with 640x400 frame resolution. I wanted to take it to at least 5-6 fps per second, to obtain a more fluent video stream&#xD;&#xA;&#xD;&#xA;So do you have any suggestions or new ideas to obtain better results? Am I missing something?&#xD;&#xA;&#xD;&#xA;As additional information, I'm using Python 3.5 with OpenCV 3.1" ContentLicense="CC BY-SA 3.0" />
  <row Id="8971" PostHistoryTypeId="1" PostId="4105" RevisionGUID="1d98208e-7fdd-4458-97d9-78d390ad6d4e" CreationDate="2016-10-08T21:58:21.903" UserId="5257" Text="Feature detection for embedded platform OpenCV" ContentLicense="CC BY-SA 3.0" />
  <row Id="8972" PostHistoryTypeId="3" PostId="4105" RevisionGUID="1d98208e-7fdd-4458-97d9-78d390ad6d4e" CreationDate="2016-10-08T21:58:21.903" UserId="5257" Text="|algorithm|image-processing|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8973" PostHistoryTypeId="2" PostId="4106" RevisionGUID="ca26a3ba-e44d-4e24-9db9-b9b077f5b163" CreationDate="2016-10-08T23:18:34.233" UserId="56" Text="Your ambient lighting contribution is missing from the second one (:" ContentLicense="CC BY-SA 3.0" />
  <row Id="8974" PostHistoryTypeId="2" PostId="4107" RevisionGUID="46cf7d94-ddd2-4a41-8186-f3ee76bf1611" CreationDate="2016-10-09T05:50:01.477" UserId="5256" Text="    float3 DirectDiffuseBRDF(float3 diffuseAlbedo, float nDotL)&#xD;&#xA;    {&#xD;&#xA;        return (diffuseAlbedo * nDotL);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float4 PS(VS_OUTPUT input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        input.normal = normalize(input.normal);&#xD;&#xA;    &#xD;&#xA;        float4 diffuseAlbedo = ObjTexture.Sample(ObjSamplerState, input.TexCoord);&#xD;&#xA;    &#xD;&#xA;        float nDotL = dot(input.normal, light.dir);&#xD;&#xA;    &#xD;&#xA;        float3 diffuseLighting = diffuseAlbedo * light.ambient;&#xD;&#xA;    &#xD;&#xA;        diffuseLighting += saturate(DirectDiffuseBRDF(diffuseAlbedo, nDotL);&#xD;&#xA;    &#xD;&#xA;        return float4(diffuseLighting, diffuseAlbedo.a);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This seemed to have fixed it. I was forgetting to multiply my Ambient light. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8975" PostHistoryTypeId="5" PostId="4107" RevisionGUID="42aa1895-fcb2-48d5-9f2d-5335df21e9f2" CreationDate="2016-10-09T10:05:42.927" UserId="5256" Comment="added 16 characters in body" Text="    float3 DirectDiffuseBRDF(float3 diffuseAlbedo, float nDotL)&#xD;&#xA;    {&#xD;&#xA;        return (diffuseAlbedo * nDotL);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float4 PS(VS_OUTPUT input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        input.normal = normalize(input.normal);&#xD;&#xA;    &#xD;&#xA;        float4 diffuseAlbedo = ObjTexture.Sample(ObjSamplerState, input.TexCoord);&#xD;&#xA;    &#xD;&#xA;        float nDotL = dot(input.normal, light.dir);&#xD;&#xA;    &#xD;&#xA;        float3 diffuseLighting = diffuseAlbedo * light.ambient * light.diffuse;&#xD;&#xA;    &#xD;&#xA;        diffuseLighting += saturate(DirectDiffuseBRDF(diffuseAlbedo, nDotL);&#xD;&#xA;    &#xD;&#xA;        return float4(diffuseLighting, diffuseAlbedo.a);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This seemed to have fixed it. I was forgetting to multiply my Ambient light. " ContentLicense="CC BY-SA 3.0" />
  <row Id="8976" PostHistoryTypeId="2" PostId="4108" RevisionGUID="6676a9af-7476-421d-ab1b-7d31476560e9" CreationDate="2016-10-09T10:48:16.933" UserId="4958" Text="Quick idea:&#xD;&#xA;&#xD;&#xA; - render platforms color to screen quad&#xD;&#xA; - render mesh and platforms to screen quad, but as a mask. For example mesh is white, rest is black. &#xD;&#xA; - in another pass sample these textures and if mask is white, color it with sample from first texture. Render to screen." ContentLicense="CC BY-SA 3.0" />
  <row Id="8977" PostHistoryTypeId="50" PostId="3596" RevisionGUID="87f4c53d-a59f-4239-850a-57f1f7e35cf0" CreationDate="2016-10-09T13:58:13.297" UserId="-1" />
  <row Id="8978" PostHistoryTypeId="2" PostId="4109" RevisionGUID="8a15add3-3bdd-40ab-93b2-0bd27b21e664" CreationDate="2016-10-09T15:27:33.083" UserId="4571" Text="I'm currently writing a software renderer. I managed to implement texture mapping and it works fine. Only issue is, that the edges between the pixels are sometimes jagged in x direction as you can see here:&#xD;&#xA;&#xD;&#xA;[![example][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v9Mf6.png&#xD;&#xA;Could this be caused by a lack of precision? If so, how can I improve it?&#xD;&#xA;What I'm doing is simply stepping along the edges of a triangle and interpolating the UVs for each scanline." ContentLicense="CC BY-SA 3.0" />
  <row Id="8979" PostHistoryTypeId="1" PostId="4109" RevisionGUID="8a15add3-3bdd-40ab-93b2-0bd27b21e664" CreationDate="2016-10-09T15:27:33.083" UserId="4571" Text="Texture Mapping jagged pixel edges" ContentLicense="CC BY-SA 3.0" />
  <row Id="8980" PostHistoryTypeId="3" PostId="4109" RevisionGUID="8a15add3-3bdd-40ab-93b2-0bd27b21e664" CreationDate="2016-10-09T15:27:33.083" UserId="4571" Text="|rendering|texture|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8981" PostHistoryTypeId="2" PostId="4110" RevisionGUID="817bb755-ce21-4313-8b34-345bbcda5ab8" CreationDate="2016-10-10T09:42:13.847" UserId="2941" Text="Ideal specular reflection is like a perfect mirror. I'm looking at the code to [SmallPt][1] and see that one of the spheres has an ideal specular material:&#xD;&#xA;&#xD;&#xA;    Sphere spheres[] = {//Scene: radius, position, emission, color, material &#xD;&#xA;       / ...&#xD;&#xA;       Sphere(16.5,Vec(27,16.5,47),       Vec(),Vec(1,1,1)*.999, SPEC),//Mirr&#xD;&#xA;       / ...&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;In the radiance calculation, this happens:&#xD;&#xA;&#xD;&#xA;      } else if (obj.refl == SPEC)            // Ideal SPECULAR reflection &#xD;&#xA;         return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi)); &#xD;&#xA;&#xD;&#xA;where `f` is the object colour of `Vec(.999,.999,.999)`.&#xD;&#xA;&#xD;&#xA;I was surprised to see colour multiplication here. Doesn't an ideal mirror have no colour? I guess as `f` is `Vec(.999,.999,.999)`, effectively it's passing through the colour almost unchanged? Any thoughts on why .999 was used and not 1? I'm guessing this is something to do modelling a miniscule energy loss?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8982" PostHistoryTypeId="1" PostId="4110" RevisionGUID="817bb755-ce21-4313-8b34-345bbcda5ab8" CreationDate="2016-10-10T09:42:13.847" UserId="2941" Text="Should ideal specular multiply light colour with material colour?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8983" PostHistoryTypeId="3" PostId="4110" RevisionGUID="817bb755-ce21-4313-8b34-345bbcda5ab8" CreationDate="2016-10-10T09:42:13.847" UserId="2941" Text="|raytracing|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8984" PostHistoryTypeId="2" PostId="4111" RevisionGUID="b44e3724-c683-4c5e-ad91-701157274da3" CreationDate="2016-10-10T13:10:59.947" UserId="3470" Text="The specular of metals is a product of the light color and the albedo of the material. Only for non-metals is the color of the specular independent of the albedo, but it's also rather dim. A perfect mirror would therefore be a perfectly smooth metallic surface with an albedo of 1. So, you could say such a mirror would be white, rather than having no color.&#xD;&#xA;&#xD;&#xA;A more realistic mirror would use something like silver for coating, with an albedo of (0.972, 0.960, 0.915). This color represents the percentage of the light of each frequency that is reflected by silver, so it needs to be multiplied with the color of the reflected light." ContentLicense="CC BY-SA 3.0" />
  <row Id="8985" PostHistoryTypeId="2" PostId="4112" RevisionGUID="2a2ae82a-c2e9-414e-8d0d-428dd83d8336" CreationDate="2016-10-10T13:13:55.717" UserId="38" Text="Ideal mirrors are just that, ideal. The question if or not it has color never comes to play, its ideal it reflects everything. Like division by zero it is undefined. However, that does not mean you could not multiply your result by one its still the same result.&#xD;&#xA;&#xD;&#xA;The problem is that we have succesfully mixed the concepts of intensity and color together. We simply assume in RGB that color is 3 independent intensities. Which is not at all true, its quite an simplification of how reality works. There really is such thing as a highly intense dark orange that RGB can not account for. So as such its hard to tell since we are conflating two independent things as one. But yes probably some energy being removed for reason unknown in that code." ContentLicense="CC BY-SA 3.0" />
  <row Id="8986" PostHistoryTypeId="2" PostId="4113" RevisionGUID="c7514499-76ae-4875-bdea-48d6fbec9204" CreationDate="2016-10-10T14:20:03.860" UserId="1952" Text="What &quot;ideal&quot; means in this context is that there is no divergence in the direction of light reflection vectors (i.e. no roughness) but that they are all considered to be perfect reflections from an [optical flat][1] surface. However, even for optical flat surfaces [Fresnel equation][2] is still applied in BRDF evaluation that changes specular reflection and is potentially wavelength dependent, which is a common characteristic with metals.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;However, in smallPt there's no Fresnel approximation (e.g. [Schlick's approximation][4]) but the surface reflectance is simply multiplied with constant term which is wrong. Also 0.999 specular albedo is very high for any real material. Below is a table of specular reflectange of various metals &amp; dielectrics at normal incidence for reference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Optical_flat&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [3]: https://i.stack.imgur.com/RkpTZ.jpg&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Schlick%27s_approximation&#xD;&#xA;  [5]: https://i.stack.imgur.com/Q73nz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="8987" PostHistoryTypeId="2" PostId="4114" RevisionGUID="06db22c1-62c3-4f00-9f08-3c3ece38affe" CreationDate="2016-10-10T14:47:30.623" UserId="182" Text="In this context, &quot;perfect mirror&quot; refers to a perfectly flat surface with a 0% (pure black) diffuse color. It is still possible though to have a specular color: for example a Christmas tree ball behaves like a perfect mirror, but still tints the reflection. If you replace the 99% white color with a red tint, you will get the red Christmas ball look.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In _SmallPT_, spheres have two colors: `e` the emissive color and `c`. The trick is that `c` has two different meanings which depend on the material type `refl`:&#xD;&#xA;&#xD;&#xA; 1. When `refl` is `DIFF`, `c` is interpreted as the diffuse color.&#xD;&#xA; 2. When `refl` is `SPEC`, `c` is interpreted as the specular color.&#xD;&#xA;&#xD;&#xA;So in the case #2, the diffuse is left out, which is equivalent to a 0%, pure black, diffuse color.&#xD;&#xA;&#xD;&#xA;In case you haven't checked it already, this presentation is an excellent code explanation of _SmallPT_, dense but thorough: [_smallpt: Global Illumination in 99 lines of C++_](https://drive.google.com/file/d/0B8g97JkuSSBwUENiWTJXeGtTOHFmSm51UC01YWtCZw/view)." ContentLicense="CC BY-SA 3.0" />
  <row Id="8989" PostHistoryTypeId="2" PostId="4115" RevisionGUID="2986e7a5-bfd5-4a86-8048-4184b8d4d94b" CreationDate="2016-10-10T19:05:58.850" UserId="56" Text="It's common knowledge that branching in a GPU program is costly because it may have to run both the if and else logic for every pixel being evaluated in the same wave, but only applying each result to the appropriate pixels.&#xD;&#xA;&#xD;&#xA;I was curious if branching was still a performance issue if there is only an if statement and no else statement?&#xD;&#xA;&#xD;&#xA;In this case, it seems like it has the ability to be faster compared to branchless logic, for the case when no pixels need to do the work inside the if statement, and can instead skip past it as a group.&#xD;&#xA;&#xD;&#xA;Is this true?  Are there any other downsides? like perhaps older video cards still doing the if logic anyways, even though no pixels evaluate to true?" ContentLicense="CC BY-SA 3.0" />
  <row Id="8990" PostHistoryTypeId="1" PostId="4115" RevisionGUID="2986e7a5-bfd5-4a86-8048-4184b8d4d94b" CreationDate="2016-10-10T19:05:58.850" UserId="56" Text="GPU branching if without else" ContentLicense="CC BY-SA 3.0" />
  <row Id="8991" PostHistoryTypeId="3" PostId="4115" RevisionGUID="2986e7a5-bfd5-4a86-8048-4184b8d4d94b" CreationDate="2016-10-10T19:05:58.850" UserId="56" Text="|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8992" PostHistoryTypeId="50" PostId="3963" RevisionGUID="57ce8b8f-ba1f-4aa3-ba88-ccb434db3c35" CreationDate="2016-10-10T19:07:52.870" UserId="-1" />
  <row Id="8994" PostHistoryTypeId="5" PostId="4109" RevisionGUID="16c959e1-109b-4031-83d5-3b7ee19cf20c" CreationDate="2016-10-10T20:52:11.337" UserId="4571" Comment="added 1998 characters in body" Text="I'm currently writing a software renderer. I managed to implement texture mapping and it works fine. Only issue is, that the edges between the pixels are sometimes jagged in x direction as you can see here:&#xD;&#xA;&#xD;&#xA;[![example][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v9Mf6.png&#xD;&#xA;Could this be caused by a lack of precision? If so, how can I improve it?&#xD;&#xA;What I'm doing is simply stepping along the edges of a triangle and interpolating the UVs for each scanline.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Here's my code for edge stepping and drawing of scanlines. The Edge class has a method step which increments the interpolants for each scanline.&#xD;&#xA;&#xD;&#xA;**edge.h**&#xD;&#xA;  &#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    Edge(const Vertex&amp; minY, const Vertex&amp; maxY){&#xD;&#xA;		float dy = maxY.position.y - minY.position.y;&#xD;&#xA;&#xD;&#xA;		yStart = static_cast&lt;int&gt;(ceil(minY.position.y));&#xD;&#xA;		yEnd = static_cast&lt;int&gt;(ceil(maxY.position.y));&#xD;&#xA;&#xD;&#xA;		float prestep = yStart - minY.position.y;&#xD;&#xA;&#xD;&#xA;		xStep = (maxY.position.x - minY.position.x) / dy;&#xD;&#xA;		x = minY.position.x + xStep * prestep;&#xD;&#xA;&#xD;&#xA;		wStep = (1.0f / maxY.position.w - 1.0f / minY.position.w) / dy;&#xD;&#xA;		w = 1.0f / minY.position.w + wStep * prestep;&#xD;&#xA;&#xD;&#xA;		texCoordsStep = (maxY.textureCoordinates / maxY.position.w - minY.textureCoordinates / minY.position.w) / dy;&#xD;&#xA;		texCoords = minY.textureCoordinates / minY.position.w + texCoordsStep * prestep;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;**renderTarget.cpp**&#xD;&#xA;  &#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    void RenderTarget::DrawScanLine(const Edge&amp; left, const Edge&amp; right, int y){&#xD;&#xA;	    int xStart = static_cast&lt;int&gt;(ceil(left.GetCurX()));&#xD;&#xA;	    int xEnd = static_cast&lt;int&gt;(ceil(right.GetCurX()));&#xD;&#xA;	    float dx = static_cast&lt;float&gt;(xEnd - xStart);&#xD;&#xA;	    float prestep = xStart - left.GetCurX();&#xD;&#xA;&#xD;&#xA;	    float w = left.GetCurW();&#xD;&#xA;	    float wStep = (right.GetCurW() - w) / dx;&#xD;&#xA;&#xD;&#xA;	    glm::vec2 texCoordsStep = (right.GetCurTexCoords() - left.GetCurTexCoords()) / dx;&#xD;&#xA;	    glm::vec2 texCoords = left.GetCurTexCoords() + texCoordsStep * prestep;&#xD;&#xA;&#xD;&#xA;	    Uint32* p = pixels + xStart + y * surface-&gt;w;&#xD;&#xA;&#xD;&#xA;	    for(int x = xStart; x &lt; xEnd; x++){&#xD;&#xA;		    float z = 1.0f / w;  //value for perspective correction&#xD;&#xA;		    int s = static_cast&lt;int&gt;(texCoords.s * z * texture-&gt;surface-&gt;w) &amp; texture-&gt;surface-&gt;w - 1;&#xD;&#xA;		    int t = static_cast&lt;int&gt;(texCoords.t * z * texture-&gt;surface-&gt;h) &amp; texture-&gt;surface-&gt;h - 1;&#xD;&#xA;&#xD;&#xA;		    *p = texture-&gt;pixels[s + t * texture-&gt;surface-&gt;w];  //copying the texture's pixel to the framebuffer&#xD;&#xA;		    p++;&#xD;&#xA;		    w += wStep;&#xD;&#xA;		    texCoords += texCoordsStep;&#xD;&#xA;		    color += colorStep;&#xD;&#xA;	    }&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="8995" PostHistoryTypeId="2" PostId="4116" RevisionGUID="d373c838-81b1-4cf9-b89d-d124df4adddf" CreationDate="2016-10-10T22:36:53.850" UserId="4981" Text="I would understand in depth the creation of viewing transformation matrix and I have a doubt. Let's say that  world coordinates (that I call A)  have center in (1,1,1) and the view reference point (VRP) ((that I call B) namely the origin of view coordinate is (3,3,2). (It's an example)&#xD;&#xA;Each vertex of the world must be &quot;translated&quot; in B.   The axes of A and B aren't aligned namely isn't enough a translation but are necessary two rotations (around x and y of two certain angles).&#xD;&#xA;I would know if I proceed in a right way:&#xD;&#xA;For overlap the axes from A to B the first step is translate (transformation T) with translation parameters (2,2,1) namely (3-1,3-1,2-1),later Rx(rotation around x) and Ry(rotation around y).&#xD;&#xA;Thus the transformation is:&#xD;&#xA;RyRxT          when T is the first matrix which must be applied&#xD;&#xA;Thus the transformation for &quot;map&quot; a point of A into the the corresponding point in B coordinates is the inverse namely:&#xD;&#xA;(T^-1)(Rx^-1)(Ry^-1)&#xD;&#xA;My main doubt is if it's right , for overlap A and B, makes first translation.&#xD;&#xA;&#xD;&#xA;In general is it right the process?   &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="8996" PostHistoryTypeId="1" PostId="4116" RevisionGUID="d373c838-81b1-4cf9-b89d-d124df4adddf" CreationDate="2016-10-10T22:36:53.850" UserId="4981" Text="Correcteness of logical steps for create the matrix of viewing transformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="8997" PostHistoryTypeId="3" PostId="4116" RevisionGUID="d373c838-81b1-4cf9-b89d-d124df4adddf" CreationDate="2016-10-10T22:36:53.850" UserId="4981" Text="|rendering|transformations|mathematics|matrix|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="8998" PostHistoryTypeId="5" PostId="4116" RevisionGUID="cc6ff1e1-42df-4861-b366-515d1b99b48c" CreationDate="2016-10-10T22:55:47.067" UserId="4981" Comment="edited body" Text="I would understand in depth the creation of viewing transformation matrix and I have a doubt. Let's say that  world coordinates (that I call A)  have center in (1,1,1) and the view reference point (VRP) ((that I call B) namely the origin of view coordinate is (3,3,2) (It's an example).&#xD;&#xA;Each vertex of the world must be &quot;mapped&quot; in B.   The axes of A and B aren't aligned namely isn't enough a translation but are necessary two rotations (around x and y of two certain angles).&#xD;&#xA;I would know if I proceed in a right way:&#xD;&#xA;For overlap the axes from A to B the first step is translate (transformation T) with translation parameters (2,2,1) namely (3-1,3-1,2-1),later Rx(rotation around x) and Ry(rotation around y).&#xD;&#xA;Thus the transformation is:&#xD;&#xA;RyRxT          when T is the first matrix which must be applied&#xD;&#xA;Thus the transformation for &quot;map&quot; a point of A into the the corresponding point in B coordinates is the inverse namely:&#xD;&#xA;(T^-1)(Rx^-1)(Ry^-1)&#xD;&#xA;My main doubt is if it's right , for overlap A and B, makes first translation.&#xD;&#xA;&#xD;&#xA;In general is it right the process?   &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9002" PostHistoryTypeId="2" PostId="4117" RevisionGUID="75e1f1f4-7e2a-4665-986d-f6c416d7c05d" CreationDate="2016-10-11T02:36:57.870" UserId="2707" Text="#Old Hardware&#xD;&#xA;&#xD;&#xA;Some older cards didn't used to jump instructions in warps, so this was indeed an issue. If you have a conditional with these cards, the inside logic of the conditional would still be evaluated even if the block wasn't entered by any of the pixels, vertices, etc. There's little you can do in this case because every instruction will be executed.&#xD;&#xA;&#xD;&#xA;#Modern Hardware&#xD;&#xA;&#xD;&#xA;However, if you are working with relatively modern hardware though, this isn't an issue and &quot;if/else&quot; blocks should be skipped when necessary. There really shouldn't be a downside to using &quot;if/else&quot; blocks compared to not using these blocks because even if you didn't explicitly use an &quot;else&quot; statement, all the instructions would execute that part anyway. In fact, some post-processing effects specifically benefit from this.&#xD;&#xA;&#xD;&#xA;On the contrary, if your &quot;if&quot; blocks are executed, then you end up doing double the logic on the newer cards if you don't use an else statement. In conclusion, there isn't a downside to using conditionals as they are needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="9003" PostHistoryTypeId="5" PostId="4117" RevisionGUID="9a1362ef-70de-4d91-9c24-8689f45891fc" CreationDate="2016-10-11T02:54:55.717" UserId="2707" Comment="Made small meaning correction" Text="#Old Hardware&#xD;&#xA;&#xD;&#xA;Some older cards didn't used to jump instructions in warps, so this was indeed an issue. If you have a conditional with these cards, the inside logic of the conditional would still be evaluated even if the block wasn't entered by any of the pixels, vertices, etc. There's little you can do in this case because every instruction will be executed.&#xD;&#xA;&#xD;&#xA;#Modern Hardware&#xD;&#xA;&#xD;&#xA;However, if you are working with relatively modern hardware though, this isn't an issue and &quot;if/else&quot; blocks will be skipped when necessary. There really shouldn't be a downside to using &quot;if/else&quot; blocks compared to not using these blocks because even if you didn't explicitly use an &quot;else&quot; statement, all the instructions would execute that part anyway. In fact, some post-processing effects specifically benefit from this.&#xD;&#xA;&#xD;&#xA;On the contrary, if your &quot;if&quot; blocks are executed, then you end up doing double the logic on the newer cards if you don't use an else statement. In conclusion, there isn't a downside to using conditionals as they are needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="9004" PostHistoryTypeId="5" PostId="4116" RevisionGUID="d20d889b-5dbd-461c-8888-9bcdbaa2f69d" CreationDate="2016-10-11T06:45:15.747" UserId="2707" Comment="Formatted everything, corrected grammar mistakes, organized content. I think I understand what this question is asking, but please correct me if I'm wrong!" Text="In general, I understand the creation of viewing transformation matrix, but I have my doubts.&#xD;&#xA;&#xD;&#xA;For example, let's say that a world coordinate (called $A$) has a center at $(1,1,1)$, and the view reference point (VRP) (called $B$) has a center at $(3,3,2)$.&#xD;&#xA;&#xD;&#xA;Each vertex of the world must be &quot;mapped&quot; to $B$. The axes of $A$ and $B$ aren't aligned so a translation isn't enough, but there are two necessary rotations (around $x$ and $y$ of two certain angles).&#xD;&#xA;&#xD;&#xA;I want to know if I am proceeding in a correct way. For overlapping the axes from $A$ to $B$ these are the following steps:&#xD;&#xA;&#xD;&#xA;1. translate (transformation $T$) with translation parameters $(2,2,1)$, namely $(3-1,3-1,2-1)$&#xD;&#xA;2. rotation around $x$ (transformation $R_x$)&#xD;&#xA;3. rotation around $y$ (transformation $R_y$)&#xD;&#xA;&#xD;&#xA;Thus, the transformation is:&#xD;&#xA;$R_yR_xT$ when $T$ is the first matrix which must be applied. Thus, the transformation to &quot;map&quot; a point of $A$ into the the corresponding point in $B$ coordinates is the inverse namely:&#xD;&#xA;$(T^{-1})(Rx^{-1})(Ry^{-1})$&#xD;&#xA;&#xD;&#xA;My main doubt is if it's correct, for converting $A$ and $B$, to do a translation first.&#xD;&#xA;&#xD;&#xA;In general, is this process correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9005" PostHistoryTypeId="4" PostId="4116" RevisionGUID="d20d889b-5dbd-461c-8888-9bcdbaa2f69d" CreationDate="2016-10-11T06:45:15.747" UserId="2707" Comment="Formatted everything, corrected grammar mistakes, organized content. I think I understand what this question is asking, but please correct me if I'm wrong!" Text="Correctness of logical steps for create the matrix of viewing transformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="9006" PostHistoryTypeId="24" PostId="4116" RevisionGUID="d20d889b-5dbd-461c-8888-9bcdbaa2f69d" CreationDate="2016-10-11T06:45:15.747" Comment="Proposed by 2707 approved by 182, -1 edit id of 167" ContentLicense="CC BY-SA 3.0" />
  <row Id="9008" PostHistoryTypeId="2" PostId="4118" RevisionGUID="c4d093e9-5b33-4fc1-9aec-04d32f709bb2" CreationDate="2016-10-11T11:52:18.917" UserId="209" Text="I strongly suspect that you are simply running out of floating point precision (at least in &quot;U&quot; dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing comparisons against known constants.&#xD;&#xA;&#xD;&#xA;May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also look better than having little squares." ContentLicense="CC BY-SA 3.0" />
  <row Id="9009" PostHistoryTypeId="2" PostId="4119" RevisionGUID="51facdff-da0b-4aca-a685-c70434ff07e2" CreationDate="2016-10-11T13:30:40.063" UserId="1952" Text="I'm assuming you mean $A$ is object$\rightarrow$world matrix and $B$ is your camera$\rightarrow$world matrix? If that's the case, to calculate object object$\rightarrow$camera matrix you calculate:&#xD;&#xA;&#xD;&#xA;$$C=B^{-1}*A$$&#xD;&#xA;&#xD;&#xA;In general your math is correct, i.e. the order of matrix multiplication is reversed for the inverse calculation. It's just that normally these transformations are combined to a single 4x4 transformation matrix which does rotation, scaling and translation, and then you just work with that single matrix instead of it being decomposed to separate rotation &amp; translation matrices. Anyway, if you want to decompose the matrix multiplication, based on the above you would do:&#xD;&#xA;&#xD;&#xA;$$A=T_A*R_{Ay}*R_{Ax}$$&#xD;&#xA;$$B=T_B*R_{By}*R_{Bx}$$&#xD;&#xA;$$C=R_{Bx}^{-1}*R_{By}^{-1}*T_B^{-1}*T_A*R_{Ay}*R_{Ax}$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9010" PostHistoryTypeId="5" PostId="4119" RevisionGUID="d14d851c-b307-4863-99ab-5ed0cd6e4176" CreationDate="2016-10-11T13:35:54.813" UserId="1952" Comment="deleted 16 characters in body" Text="I'm assuming you mean $A$ is object$\rightarrow$world matrix and $B$ is your camera$\rightarrow$world matrix? If that's the case, to calculate object object$\rightarrow$camera matrix you calculate:&#xD;&#xA;&#xD;&#xA;$$C=B^{-1}*A$$&#xD;&#xA;&#xD;&#xA;In general your math is correct, i.e. the order of matrix multiplication is reversed for the inverse calculation. It's just that normally these transformations are combined to a single 4x4 transformation matrix which does rotation, scaling and translation, and then you just work with that single matrix instead of it being decomposed to separate rotation &amp; translation matrices. Anyway, if you want to decompose the matrix multiplication, based on the above you would do:&#xD;&#xA;&#xD;&#xA;$$A=T_A*Ry_A*Rx_A$$&#xD;&#xA;$$B=T_B*Ry_B*Rx_B$$&#xD;&#xA;$$C=Rx_B^{-1}*Ry_B^{-1}*T_B^{-1}*T_A*Ry_A*Rx_A$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9011" PostHistoryTypeId="5" PostId="4118" RevisionGUID="dbe17605-ba98-4021-a97f-9e6dd52b6235" CreationDate="2016-10-11T14:35:54.467" UserId="209" Comment="added 12 characters in body" Text="I strongly suspect that you are simply running out of floating point precision (at least in &quot;U&quot; dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.&#xD;&#xA;&#xD;&#xA;May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares." ContentLicense="CC BY-SA 3.0" />
  <row Id="9012" PostHistoryTypeId="2" PostId="4120" RevisionGUID="18a72801-5f0c-4562-94db-82d741e7b7ce" CreationDate="2016-10-11T18:23:32.030" UserId="1952" Text="If there is no divergence (i.e. all threads in a wave take the same branch) newer GPU's can skip all the work within the if-branch. If there's divergence, then code in both branches is executed, but thread execution mask basically defines which threads execute code in which branch (code in non-executed branches for threads are effectively NOPed out). This is basically the same as predicated branching but happens dynamically based on divergence.&#xD;&#xA;&#xD;&#xA;On GCN architecture at least the branching itself is basically free or at least very cheap (handled by a separate unit running parallel to ALU for example), but something to keep in mind is that branching also tends to increase GPR pressure, which in turn lowers the occupancy. Low occupancy means there can be less threads in flight at once which influences GPU's ability to hide memory latencies. This may or may not be an issue in your shaders depending on how they access memory, i.e. you should see performance increase along with increased occupancy in shaders with heavy memory access.&#xD;&#xA;&#xD;&#xA;So it's still good to optimize out branching where reasonable, but I think it's one of the things good left to the optimization stage where you need to squeeze max performance out of your shaders." ContentLicense="CC BY-SA 3.0" />
  <row Id="9013" PostHistoryTypeId="5" PostId="4117" RevisionGUID="dcfbce9a-11ef-484f-bb2b-a689c188a498" CreationDate="2016-10-12T04:32:58.580" UserId="2707" Comment="Clarifies some of the logic" Text="#Old Hardware&#xD;&#xA;&#xD;&#xA;Some older cards didn't used to jump instructions in warps, so this was indeed an issue. If you have a conditional with these cards, the inside logic of the conditional would still be evaluated even if the block wasn't entered by any of the pixels, vertices, etc. There's little you can do in this case because every instruction will be executed. The worst case is also the best case here.&#xD;&#xA;&#xD;&#xA;#Modern Hardware&#xD;&#xA;&#xD;&#xA;However, if you are working with relatively modern hardware though, this isn't an issue and &quot;if/else&quot; blocks will be skipped when necessary. There really shouldn't be a downside to using &quot;if/else&quot; blocks compared to not using them. You are still branching with an &quot;else&quot;-less statement. In fact, some post-processing effects/deferred rendering specifically benefit from this.&#xD;&#xA;&#xD;&#xA;The worst case scenario is that some threads go through the &quot;if&quot; block and the rest go through the &quot;else&quot; block. The best case scenario is that all go through the &quot;if&quot; block or the &quot;else&quot; block. There isn't a downside to using &quot;if/else&quot; conditionals as they are needed (either on old hardware or newer hardware), but there's a possible upside with newer hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="9014" PostHistoryTypeId="5" PostId="3959" RevisionGUID="a5e601b0-028d-4596-9f24-bc678b0ec36b" CreationDate="2016-10-12T04:53:32.390" UserId="48" Comment="add note about dynamic environment cubemaps" Text="Real-time graphics deploys a variety of approximations to deal with the computational expense of simulating indirect lighting, trading off between runtime performance and lighting fidelity. This is an area of active research, with new techniques appearing every year.&#xD;&#xA;&#xD;&#xA;## Ambient lighting&#xD;&#xA;&#xD;&#xA;At the very simplest end of the range, you can use [**ambient lighting**](https://en.wikipedia.org/wiki/Shading#Ambient_lighting): a global, omnidirectional light source that applies to every object in the scene, without regard to actual light sources or local visibility. This is not at all accurate, but is extremely cheap, easy for an artist to tweak, and can look okay depending on the scene and the desired visual style.&#xD;&#xA;&#xD;&#xA;Common extensions to basic ambient lighting include:&#xD;&#xA;&#xD;&#xA;* Make the ambient color vary directionally, e.g. using [spherical harmonics (SH)](https://dickyjim.wordpress.com/2013/09/04/spherical-harmonics-for-beginners/) or a [small cubemap](http://www.valvesoftware.com/publications/2006/SIGGRAPH06_Course_ShadingInValvesSourceEngine.pdf#5), and looking up the color in a shader based on each vertex's or pixel's normal vector. This allows some visual differentiation between surfaces of different orientations, even where no direct light reaches them.&#xD;&#xA;* Apply [ambient occlusion (AO)](https://en.wikipedia.org/wiki/Ambient_occlusion) techniques including pre-computed vertex AO, AO texture maps, [AO fields](http://www.gdcvault.com/play/1015320/Ambient-Occlusion-Fields-and-Decals), and [screen-space AO (SSAO)](http://graphics.cs.williams.edu/papers/SAOHPG12/). These all work by attempting to detect areas such as holes and crevices where indirect light is less likely to bounce into, and darkening the ambient light there.&#xD;&#xA;* Add an [environment cubemap](http://learnopengl.com/#!Advanced-OpenGL/Cubemaps) to provide ambient specular reflection. A cubemap with a decent resolution (128² or 256² per face) can be quite convincing for specular on curved, shiny surfaces.&#xD;&#xA;&#xD;&#xA;## Baked indirect lighting&#xD;&#xA;&#xD;&#xA;The next &quot;level&quot;, so to speak, of techniques involve **baking** (pre-computing offline) some representation of the indirect lighting in a scene. The advantage of baking is you can get pretty high-quality results for little real-time computational expense, since all the hard parts are done in the bake. The trade-offs are that the time needed for the bake process harms level designers' iteration rate; more memory and disk space are required to store the precomputed data; the ability to change the lighting in real-time is very limited; and the bake process can only use information from static level geometry, so indirect lighting effects from dynamic objects such as characters will be missed. Still, baked lighting is very widely used in AAA games today.&#xD;&#xA;&#xD;&#xA;The bake step can use any desired rendering algorithm including path tracing, radiosity, or using the game engine itself to render out cubemaps (or [hemicubes](http://the-witness.net/news/2010/09/hemicube-rendering-and-integration/)).&#xD;&#xA;&#xD;&#xA;The results can be stored in textures ([lightmaps](https://en.wikipedia.org/wiki/Lightmap)) applied to static geometry in the level, and/or they can also be converted to SH and stored in volumetric data structures, such as [irradiance volumes](http://simonstechblog.blogspot.com/2014_10_01_archive.html) (volume textures where each texel stores an SH probe) or [tetrahedral meshes](http://www.gdcvault.com/play/1015312/Light-Probe-Interpolation-Using-Tetrahedral). You can then use shaders to look up and interpolate colors from that data structure and apply them to your rendered geometry. The volumetric approach allows baked lighting to be applied to dynamic objects as well as static geometry.&#xD;&#xA;&#xD;&#xA;The spatial resolution of the lightmaps etc. will be limited by memory and other practical constraints, so you might supplement the baked lighting with some AO techniques to add high-frequency detail that the baked lighting can't provide, and to respond to dynamic objects (such as darkening the indirect light under a moving character or vehicle).&#xD;&#xA;&#xD;&#xA;There's also a technique called [precomputed radiance transfer (PRT)](http://www0.cs.ucl.ac.uk/staff/j.kautz/PRTCourse/), which extends baking to handle more dynamic lighting conditions. In PRT, instead of baking the indirect lighting itself, you bake the _transfer function_ from some source of light—usually the sky—to the resultant indirect lighting in the scene. The transfer function is represented as a matrix that transforms from source to destination SH coefficients at each bake sample point. This allows the lighting environment to be changed, and the indirect lighting in the scene will respond plausibly. [Far Cry 3 and 4 used this technique](http://www.gdcvault.com/play/1015326/Deferred-Radiance-Transfer-Volumes-Global) to allow a continuous day-night cycle, with indirect lighting varying based on the sky colors at each time of day.&#xD;&#xA;&#xD;&#xA;One other point about baking: it may be useful to have separate baked data for diffuse and specular indirect lighting. Cubemaps work much better than SH for specular (since cubemaps can have a lot more angular detail), but they also take up a lot more memory, so you can't afford to place them as densely as SH samples. [Parallax correction](https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/) can be used to somewhat make up for that, by heuristically warping the cubemap to make its reflections feel more grounded to the geometry around it.&#xD;&#xA;&#xD;&#xA;## Fully real-time techniques&#xD;&#xA;&#xD;&#xA;Finally, it's possible to compute fully dynamic indirect lighting on the GPU. It can respond in real-time to arbitrary changes of lighting or geometry. However, again there is a tradeoff between runtime performance, lighting fidelity, and scene size. Some of these techniques need a beefy GPU to work at all, and may only be feasible for limited scene sizes. They also typically support only a single bounce of indirect light.&#xD;&#xA;&#xD;&#xA;* A dynamic environment cubemap, where the faces of the cubemap are re-rendered each frame using six cameras clustered around a chosen point, can provide decently good ambient reflections for a single object. This is often used for the player car in racing games, for instance.&#xD;&#xA;* [Screen-space global illumination](http://people.mpi-inf.mpg.de/~ritschel/Papers/SSDO.pdf), an extension of SSAO that gathers bounce lighting from nearby pixels on the screen in a post-processing pass.&#xD;&#xA;* [Screen-space raytraced reflection](http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html) works by ray-marching through the depth buffer in a post-pass. It can provide quite high-quality reflections as long as the reflected objects are on-screen.&#xD;&#xA;* [Instant radiosity](https://www.cg.tuwien.ac.at/courses/RendEng/RendEng-2016-01-11-InstantRadiosity.pdf) works by tracing rays into the scene using the CPU, and placing a point light at each ray hit point, which approximately represents the outgoing reflected light in all directions from that ray. These many lights, known as virtual point lights (VPLs), are then rendered by the GPU in the usual way.&#xD;&#xA;* [Reflective shadow maps (RSMs)](http://www.klayge.org/material/3_12/GI/rsm.pdf) are similar to instant radiosity, but the VPLs are generated by rendering the scene from the light's point of view (like a shadow map) and placing a VPL at each pixel of this map.&#xD;&#xA;* [Light propagation volumes](http://www.crytek.com/download/Light_Propagation_Volumes.pdf) consist of 3D grids of SH probes placed throughout the scene. RSMs are rendered and used to &quot;inject&quot; bounce light into the SH probes nearest the reflecting surfaces. Then a flood-fill-like process propagates light from each SH probe to surrounding points in the grid, and the result of this is used to apply lighting to the scene. This technique [has been extended to volumetric light scattering](https://newq.net/archived/www.cse.chalmers.se/pub/scatter/index.html) as well.&#xD;&#xA;* [Voxel cone tracing](http://maverick.inria.fr/Publications/2011/CNSGE11b/) works by voxelizing the scene geometry (likely using varying voxel resolutions, finer near the camera and coarser far away), then injecting light from RSMs into the voxel grid. When rendering the main scene, the pixel shader performs a &quot;cone trace&quot;—a ray-march with gradually increasing radius—through the voxel grid to gather incoming light for either diffuse or specular shading.&#xD;&#xA;&#xD;&#xA;Most of these techniques are not widely used in games today due to problems scaling up to realistic scene sizes, or other limitations. The exception is screen-space reflection, which is very popular (though it's usually used with cubemaps as a fallback, for regions where the screen-space part fails).&#xD;&#xA;&#xD;&#xA;As you can see, real-time indirect lighting is a huge topic and even this (rather long!) answer can only provide a 10,000-foot overview and context for further reading. Which approach is best for you will depend greatly on the details of your particular application, what constraints you're willing to accept, and how much time you have to put into it." ContentLicense="CC BY-SA 3.0" />
  <row Id="9015" PostHistoryTypeId="5" PostId="4118" RevisionGUID="3a63b5a5-8807-45f1-a19f-543ca7a6263d" CreationDate="2016-10-12T08:14:37.170" UserId="209" Comment="added 309 characters in body" Text="I strongly suspect that you are simply running out of floating point precision (at least in &quot;U&quot; dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.&#xD;&#xA;&#xD;&#xA;May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[UPDATE] Just occurred to me that one the causes of inaccuracy is that you are doing increments for each pixel X step, eg these two&#xD;&#xA;&#xD;&#xA;    w  += wStep;&#xD;&#xA;    texCoords += texCoordsStep;&#xD;&#xA;&#xD;&#xA;These will soon cause errors to accumulate. Remove them and replace with multiplies by the X value and I expect things should improve." ContentLicense="CC BY-SA 3.0" />
  <row Id="9016" PostHistoryTypeId="2" PostId="4121" RevisionGUID="0a9fdca0-02df-47dd-9cac-a67e9e815c97" CreationDate="2016-10-12T10:05:55.373" UserId="5285" Text="How to create PNG files optimized for being compression-friendly? I.e. would it help if image is created (mostly) from 8x8 unicolor blocks?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9017" PostHistoryTypeId="1" PostId="4121" RevisionGUID="0a9fdca0-02df-47dd-9cac-a67e9e815c97" CreationDate="2016-10-12T10:05:55.373" UserId="5285" Text="Compresson-friendly PNG files" ContentLicense="CC BY-SA 3.0" />
  <row Id="9018" PostHistoryTypeId="3" PostId="4121" RevisionGUID="0a9fdca0-02df-47dd-9cac-a67e9e815c97" CreationDate="2016-10-12T10:05:55.373" UserId="5285" Text="|image-processing|image|compression|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9019" PostHistoryTypeId="4" PostId="4121" RevisionGUID="1d1a4a5c-bb21-4c75-8dbb-187e74e49574" CreationDate="2016-10-12T10:55:45.823" UserId="5285" Comment="edited title" Text="Compression-friendly PNG files" ContentLicense="CC BY-SA 3.0" />
  <row Id="9020" PostHistoryTypeId="2" PostId="4122" RevisionGUID="c5054ff6-a6de-4927-9756-f16f2b95a8eb" CreationDate="2016-10-12T12:13:24.057" UserId="38" Text="I would like to address a issue in your naming. This issue makes the question a bit odd, but not impossible, like i will try to show.&#xD;&#xA;&#xD;&#xA;There is a, often unspoken, implied relationship with the matrices. For a matrix to be meaningful there has to be a common ancestor of the matrix that all matrices relate to. See a transformation chain works like a disk system or the root node of a xml document. There is always a base node, in computer graphics texts we choose to call this node **World**\*. Calling something else world is just defining your own definition of things.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The implied hierarchy of matrices, we have agreed to name the root **World**.&#xD;&#xA;&#xD;&#xA;Now there is assumed to be nothing outside the world. Although just like zeroes before numbers there is a possibility to infinite worlds within world, but those extra worlds do not participate in our model so they hardly matter.&#xD;&#xA;&#xD;&#xA;The hierarchy determines how the matrices interact with each other. All matrices are identity matrices ($I$) when viewed from inside the object. Therefore we have the following property for world:&#xD;&#xA;&#xD;&#xA;$$T_{world} = I.$$&#xD;&#xA;&#xD;&#xA;Anything else would imply that World is not World but rather a object as [@JarkkoL's answer](http://computergraphics.stackexchange.com/a/4119/38) implies, so there is yet another World outside what you call World. Also because world is identity it can be omitted from your calculations, which is why it's sometimes left unnamed.&#xD;&#xA;&#xD;&#xA;Now it is obviously possible to name objects. This is smart as it makes talking about things easier. So you could call a bicycle object object &quot;bicycle&quot;, makes sense. In fact we do this by calling the Camera, &quot;Camera&quot;. These names are arbitrary, so it is possible to call an object space World. But then the discussion just drops into confusion.&#xD;&#xA;&#xD;&#xA;Now we can address the confusion as your description is ambiguous. This is also is why you have mental problems. So either what you describe is like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Since you have renamed World we do not know what your relationship is. &#xD;&#xA;&#xD;&#xA;So by reinventing naming convention you have made the question confused. If you had not then there would be a really easy rule you would append the multiplication as normal as long as you move towards the world and inverted if you move away from the world.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* There are traditions where this is called the *Inertial frame*, *Reference Frame* and even sometimes rarely *Base*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lF8WK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysBhE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9021" PostHistoryTypeId="2" PostId="4123" RevisionGUID="2f4b74df-3682-4c0d-b047-15f6df9e0cc9" CreationDate="2016-10-12T12:58:21.843" UserId="1952" Text="PNG format is lossless format where for compression the image is first &quot;filtered&quot; and this filtered image is then passed to [DEFLATE][1] lossless compression algorithm. The purpose of filtering stage is to make the image more compressible by DEFLATE and current method uses delta-compression from previously decoded pixels.&#xD;&#xA;&#xD;&#xA;So if your plan is to pre-process the image in some lossy way, then if you can reduce the deltas so that the following entropy encoding can benefit from it, then you get better compression ratio. For example &quot;blockifying&quot; the image as you suggested would only require more storage for the top-left pixel in the block while the deltas for the remaining pixels would be zero, which DEFLATE can compress very efficiently. This same would apply to any continuous constant color regions.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/DEFLATE" ContentLicense="CC BY-SA 3.0" />
  <row Id="9022" PostHistoryTypeId="5" PostId="4118" RevisionGUID="a37a5211-8cf4-460b-854e-417e21e8f959" CreationDate="2016-10-12T13:19:04.997" UserId="209" Comment="added 6 characters in body" Text="I strongly suspect that you are simply running out of floating point precision (at least in &quot;U&quot; dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.&#xD;&#xA;&#xD;&#xA;May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE** It just occurred to me that one the causes of inaccuracy is that you are doing increments for each pixel X step, e.g. these two&#xD;&#xA;&#xD;&#xA;    w  += wStep;&#xD;&#xA;    texCoords += texCoordsStep;&#xD;&#xA;&#xD;&#xA;These will soon cause errors to accumulate. Remove them and replace with multiplies by the X value and I expect things should improve." ContentLicense="CC BY-SA 3.0" />
  <row Id="9023" PostHistoryTypeId="5" PostId="4118" RevisionGUID="c705e6aa-b007-4bc2-8f7b-53d0321700ad" CreationDate="2016-10-12T13:25:50.573" UserId="209" Comment="added 6 characters in body" Text="I strongly suspect that you are simply running out of floating point precision (at least in &quot;U&quot; dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.&#xD;&#xA;&#xD;&#xA;May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE** It just occurred to me that one the causes of inaccuracy is that you are doing increments for each pixel X step, e.g. these two&#xD;&#xA;&#xD;&#xA;    w  += wStep;&#xD;&#xA;    texCoords += texCoordsStep;&#xD;&#xA;&#xD;&#xA;These will soon cause errors to accumulate. Remove them and replace with multiplies by the X value and I expect things should improve.&#xD;&#xA;&#xD;&#xA;**UPDATE2** It will also be affected by how far away from the origin of the texture you are when you sample it. If, for example, your source texture is defined over [0..1]x[0..1] and then repeats outside of that range, you might expect sampling  at uv = (1000000.125, 100000.125) to be the same as (0.125,0.125) but, because the precision of FP decreases with increasing magnitude (i.e. the steps between floats also increases), you might end up with something quite different." ContentLicense="CC BY-SA 3.0" />
  <row Id="9024" PostHistoryTypeId="2" PostId="4124" RevisionGUID="95fe7b69-d989-4650-abd7-b3481641d17d" CreationDate="2016-10-12T13:29:42.360" UserId="1952" Text="You can look into [alias-free volumetric sampling algorithm][1] by Huw Bowles for potential solution to the ray marching aliasing issues. The basic idea is to snap your samples to planes based on the ray direction that's best explained with [this Shadertoy demo][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/huwb/volsample&#xD;&#xA;  [2]: https://www.shadertoy.com/view/ll3GWs" ContentLicense="CC BY-SA 3.0" />
  <row Id="9025" PostHistoryTypeId="5" PostId="4118" RevisionGUID="932c70ec-5391-40a1-806e-ed915c4804b4" CreationDate="2016-10-12T14:52:27.147" UserId="209" Comment="missed &quot;of&quot;" Text="I strongly suspect that you are simply running out of floating point precision (at least in &quot;U&quot; dimension). With this sort of mathematics, the LSBs will soon become noisy resulting in the jagged appearance when you are (effectively) doing yes/no comparisons against known constants.&#xD;&#xA;&#xD;&#xA;May I suggest instead that, rather than doing point sampling of your texture, try doing (at the very least) bilinear filtering which will hide the precision artefacts and also IMHO look better than having little squares.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE** It just occurred to me that one of the possible causes of inaccuracy is that you are doing increments for each pixel X step, e.g. these two&#xD;&#xA;&#xD;&#xA;    w  += wStep;&#xD;&#xA;    texCoords += texCoordsStep;&#xD;&#xA;&#xD;&#xA;These will soon cause errors to accumulate. Remove them and replace with multiplies by the X value and I expect things should improve.&#xD;&#xA;&#xD;&#xA;**UPDATE2** It will also be affected by how far away from the origin of the texture you are when you sample it. If, for example, your source texture is defined over [0..1]x[0..1] and then repeats outside of that range, you might expect sampling  at uv = (1000000.125, 100000.125) to be the same as (0.125,0.125) but, because the precision of FP decreases with increasing magnitude (i.e. the steps between floats also increases), you might end up with something quite different." ContentLicense="CC BY-SA 3.0" />
  <row Id="9026" PostHistoryTypeId="5" PostId="4122" RevisionGUID="1bc49880-1bf9-451a-b2fb-a652fba9c112" CreationDate="2016-10-12T16:15:54.320" UserId="231" Comment="Minor tidying" Text="I would like to address an issue in your naming. This issue makes the question a bit odd, but not impossible, as I will try to show.&#xD;&#xA;&#xD;&#xA;There is an, often unspoken, implied relationship between the matrices. For a matrix to be meaningful there has to be a common ancestor of the matrix that all matrices relate to. See a transformation chain works like a disk system or the root node of a XML document. There is always a base node, in computer graphics texts we choose to call this node **World**\*. Calling something else world is just defining your own definition of things.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The implied hierarchy of matrices, we have agreed to name the root **World**.&#xD;&#xA;&#xD;&#xA;Now there is assumed to be nothing outside the world. Although just like zeroes before numbers there is a possibility of infinite worlds within worlds, but those extra worlds do not participate in our model so they hardly matter.&#xD;&#xA;&#xD;&#xA;The hierarchy determines how the matrices interact with each other. All matrices are identity matrices ($I$) when viewed from inside the object. Therefore we have the following property for world:&#xD;&#xA;&#xD;&#xA;$$T_{world} = I.$$&#xD;&#xA;&#xD;&#xA;Anything else would imply that World is not World but rather an object as [@JarkkoL's answer](http://computergraphics.stackexchange.com/a/4119/38) implies, so there is yet another World outside what you call World. Also because world is the identity it can be omitted from your calculations, which is why it's sometimes left unnamed.&#xD;&#xA;&#xD;&#xA;Now it is obviously possible to name objects. This is smart as it makes talking about things easier. So you could call a bicycle object object &quot;bicycle&quot;, makes sense. In fact we do this by calling the camera, &quot;Camera&quot;. These names are arbitrary, so it is possible to call an object space World. But then the discussion just drops into confusion.&#xD;&#xA;&#xD;&#xA;Now we can address the confusion as your description is ambiguous. This is also is why you have problems reasoning about this. So either what you describe is like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Since you have renamed World we do not know what your relationship is. &#xD;&#xA;&#xD;&#xA;So by reinventing naming convention you have made the question confused. If you had not then there would be a really easy rule you would append the multiplication as normal as long as you move towards the world and inverted if you move away from the world.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* There are traditions where this is called the *Inertial frame*, *Reference Frame* and even sometimes rarely *Base*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lF8WK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysBhE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9027" PostHistoryTypeId="5" PostId="3981" RevisionGUID="8fbb72d5-f5b4-4ac8-a11c-c0f995b6bbc6" CreationDate="2016-10-12T16:30:55.603" UserId="4958" Comment="added 177 characters in body" Text="Well actually I think I was doing it wrong. I stored raymarching effects in 2D texture. This is not correct because it suffers from issues.&#xD;&#xA;&#xD;&#xA;Correct way is store raymarching effect in 3D texture, to get linear interpolation and no banding. And then perform sampling from it.&#xD;&#xA;&#xD;&#xA;It seems to improve the result because it fixes some discontinuities. However it still probabl yneeds temporal blending to get it smooth during camera movement.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;Indeed the way to smooth temporal blending independent of camera movement is to add some jitter which is shifted each frame, but it is hard to get it working right." ContentLicense="CC BY-SA 3.0" />
  <row Id="9028" PostHistoryTypeId="5" PostId="3981" RevisionGUID="25e3b256-a3b5-40ea-9c88-4a249205030e" CreationDate="2016-10-12T16:36:27.663" UserId="4958" Comment="deleted 5 characters in body" Text="Well actually I think I was doing it wrong. I stored raymarching effects in 2D texture. This is not correct because it suffers from issues.&#xD;&#xA;&#xD;&#xA;Correct way is store raymarching effect in 3D texture, to get linear interpolation and no banding. And then perform sampling from it.&#xD;&#xA;&#xD;&#xA;It seems to improve the result because it fixes some discontinuities. However it still probably needs temporal blending to get it smooth during camera movement.&#xD;&#xA;&#xD;&#xA;Indeed the way to get smooth temporal blending independent of camera movement is to add some jitter which is shifted each frame, but it is hard to get it working right." ContentLicense="CC BY-SA 3.0" />
  <row Id="9029" PostHistoryTypeId="5" PostId="3981" RevisionGUID="f78688fa-a799-4a0c-bf58-207c15581f86" CreationDate="2016-10-12T16:54:59.383" UserId="4958" Comment="deleted 9 characters in body" Text="Well actually I think I was doing it wrong. I stored raymarching effects in 2D texture. This is not correct because it suffers from issues.&#xD;&#xA;&#xD;&#xA;Correct way is store raymarching effect in 3D texture, to get linear interpolation and no banding. And then perform sampling from it.&#xD;&#xA;&#xD;&#xA;It seems to improve the result because it fixes some discontinuities. However it still needs temporal blending to get it smooth during camera movement.&#xD;&#xA;&#xD;&#xA;Indeed the way to get smooth temporal blending independent of camera movement is to add some jitter which is shifted each frame, but it is hard to get it working right." ContentLicense="CC BY-SA 3.0" />
  <row Id="9030" PostHistoryTypeId="2" PostId="4125" RevisionGUID="1d716c36-5e58-4629-84ed-4c345e37788a" CreationDate="2016-10-12T20:35:09.033" UserId="116" Text="I have read through [this article](http://www.songho.ca/opengl/gl_projectionmatrix.html) about perspective and orthographic projection matrices.&#xD;&#xA;&#xD;&#xA;I started playing with the perspective matrix and as expected if I either increase/decrease the field of view i have a zoom out/in effect. Similarly, if I move the camera position forward/backwards I see the object being close or further away.&#xD;&#xA;&#xD;&#xA;However, when I tried the orthographic matrix, since there is no field of view parameter, I tried only moving the camera forward/backwards but my model always looked the same size.&#xD;&#xA;&#xD;&#xA;Can anybody explain to me why this is happening?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9031" PostHistoryTypeId="1" PostId="4125" RevisionGUID="1d716c36-5e58-4629-84ed-4c345e37788a" CreationDate="2016-10-12T20:35:09.033" UserId="116" Text="Zoom in orthographic vs perspective projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="9032" PostHistoryTypeId="3" PostId="4125" RevisionGUID="1d716c36-5e58-4629-84ed-4c345e37788a" CreationDate="2016-10-12T20:35:09.033" UserId="116" Text="|opengl|transformations|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9033" PostHistoryTypeId="2" PostId="4126" RevisionGUID="2f94432d-c22b-488f-8442-9ab78caac680" CreationDate="2016-10-12T22:39:57.350" UserId="56" Text="Perspective projection changes the size of an object as it's distance changes, while orthographic projection does not.  That is part of the definition of those projection types.&#xD;&#xA;&#xD;&#xA;To simplify things a bit, a simple perspective projection of a 3d point to a 2d point can be calculated like this:&#xD;&#xA;&#xD;&#xA;$x_{2d} = x/z\\&#xD;&#xA;y_{2d} = y/z$&#xD;&#xA;&#xD;&#xA;As you can see, the 2d version of the x and y change depending on the value of z.&#xD;&#xA;&#xD;&#xA;Orthographic projection on the other hand can be calculated like this:&#xD;&#xA;&#xD;&#xA;$x_{2d} = x\\&#xD;&#xA;y_{2d} = y$&#xD;&#xA;&#xD;&#xA;In that example, you can see that the x and y values do not depend at all on z, so you can move closer to or farther away from an object in orthographic projection and it's size will not change.&#xD;&#xA;&#xD;&#xA;As a fun bit of related trivia, the sun is so far away that when the light gets here, it's all basically going in the same direction.&#xD;&#xA;&#xD;&#xA;This is a reason why we have directional lighting, where light beams are always moving in the same way, because that is how sun light works.&#xD;&#xA;&#xD;&#xA;Anyways, since the light beams are parallel it means that your shadows in sun light are orthographic projections of your silhouette.  In other words, as you move your hand closer to or farther from the sun here on earth, the shadow of your hand doesn't change size.&#xD;&#xA;&#xD;&#xA;However, if you have a more local light source - light a lamp - it casts a perspective projection type of shadow, where the closer to the light source your hand is, the larger the shadow it casts.&#xD;&#xA;&#xD;&#xA;This is tied to the definition of an orthographic projection, which is that the focal length is infinitely long.  The sun is far enough away that we can consider it infinity in lighting, for as much accuracy as we care about :P" ContentLicense="CC BY-SA 3.0" />
  <row Id="9038" PostHistoryTypeId="2" PostId="4128" RevisionGUID="fe44556f-ac95-4779-a857-23b27d608a63" CreationDate="2016-10-13T07:26:20.423" UserDisplayName="user5291" Text="I've been playing around with more advanced graphics these days (beyond the basic 2D UI and image effects that the iOS platform offers), and I'm wanting to implement a visual effect similar to how iOS's Siri uses what appears to be a &quot;color nebula&quot; in the background.&#xD;&#xA;&#xD;&#xA;![Siri's color nebula](https://i.stack.imgur.com/0SjS6.jpg)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Here's a video of it in action.](https://d3vv6lp55qjaqc.cloudfront.net/items/3K2V3b1I1p1V2d231J0r/video.mov?X-CloudApp-Visitor-Id=216938) Seeing it animated is pretty important given that it's a dynamic effect.&#xD;&#xA;&#xD;&#xA;Over time, the colors and intensity change, and various areas bloom and fade colors in. It's very subtle and has this ambient feel to it.&#xD;&#xA;&#xD;&#xA;Anyway, I'm working in SceneKit, Apple's 3D scene composition API, and it has access to anything from Core Image to OpenGL to Metal as far as shaders and filtering geometries. So I'm curious if there is a general purpose algorithm for this kind of a) color effect (changing hue and other properties) and b) the slow, nebulous way colors come in and out and move around.&#xD;&#xA;&#xD;&#xA;What techniques can one employ to pull of this animated visual effect?&#xD;&#xA;&#xD;&#xA;I'd also love to read any additional resources about various ways to use colors and blending in graphics to achieve interesting effects." ContentLicense="CC BY-SA 3.0" />
  <row Id="9039" PostHistoryTypeId="1" PostId="4128" RevisionGUID="fe44556f-ac95-4779-a857-23b27d608a63" CreationDate="2016-10-13T07:26:20.423" UserDisplayName="user5291" Text="What graphics techniques can be used to simulate a color nebula effect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9040" PostHistoryTypeId="3" PostId="4128" RevisionGUID="fe44556f-ac95-4779-a857-23b27d608a63" CreationDate="2016-10-13T07:26:20.423" UserDisplayName="user5291" Text="|shader|color|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9041" PostHistoryTypeId="2" PostId="4129" RevisionGUID="815f0fa8-eecc-41c4-8146-e4d4b4bec253" CreationDate="2016-10-13T09:09:29.750" UserId="2817" Text="I have no knowledge of SceneKit whatsoever, but the effect appears to be a simple post-process Gaussian blur of the app icon grid, with the blur radius increasing over time (i.e. increasing the blur amount) during the transition, with a touch of colour correction tacked on (which causes the darkening). It should be easy enough to implement in any graphics API that allows rendering to textures and performing image filtering on them (for instance, in OpenGL you could use framebuffer objects to achieve this).&#xD;&#xA;&#xD;&#xA;You can have a look at an example WebGL implementation [here][1]. It's worth noting that it is a separable filter; meaning, it's a box filter, but you can avoid sampling the same pixels (overlapping neighbouring samples) multiple times by splitting it into two passes – a horizontal and a vertical one – to the same effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/Jam3/glsl-fast-gaussian-blur/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9042" PostHistoryTypeId="2" PostId="4130" RevisionGUID="7a7abe7a-142a-43d9-85b5-0eca22f848df" CreationDate="2016-10-13T18:00:21.427" UserId="5293" Text="I'm brand new to OpenGL and graphics programming in general, and I'm trying to figure out what software I need to program a GPU.  I saw an [NVidia OpenGL driver](https://developer.nvidia.com/opengl-driver), and I've also seen reference to the OpenGL SDK.  My understanding (sort of) is that the OpenGL driver is essentially an API that hides the differences between different GPUs and the OpenGL API works on top of that.  I really have no idea though." ContentLicense="CC BY-SA 3.0" />
  <row Id="9043" PostHistoryTypeId="1" PostId="4130" RevisionGUID="7a7abe7a-142a-43d9-85b5-0eca22f848df" CreationDate="2016-10-13T18:00:21.427" UserId="5293" Text="What is the difference and/or relationship between the OpenGL SDK and the OpenGL GPU driver?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9044" PostHistoryTypeId="3" PostId="4130" RevisionGUID="7a7abe7a-142a-43d9-85b5-0eca22f848df" CreationDate="2016-10-13T18:00:21.427" UserId="5293" Text="|opengl|gpu|driver|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9045" PostHistoryTypeId="2" PostId="4131" RevisionGUID="328587de-c38c-4c78-8ff1-d952305700b0" CreationDate="2016-10-13T21:18:39.047" UserId="1952" Text="I wouldn't really call it OpenGL SDK but OpenGL API. There's a common OpenGL API which is basically a set of functions you can call to control the GPU. This API is hardware agnostic (barring extensions), so you can use it on NVIDIA, ATI, etc. GPU's.&#xD;&#xA;&#xD;&#xA;What the OpenGL driver does is to turn these platform agnostic function calls to hardware specific commands that the driver then sends to the GPU. For example when you tell GPU to draw a triangle via OpenGL API, then the driver converts these calls under the hood to specific commands for the specific GPU you are using. This abstraction is important so that you don't have to write different code for every GPU.&#xD;&#xA;&#xD;&#xA;To explain things a bit in lower level, the graphics API implementation operates in user mode, while the graphics driver operates in kernel mode. User mode is &quot;protected&quot; mode your program runs in, in the sense that you can't mess up your entire device but only your own app and it's also relatively fast to perform the API function calls in this mode. Kernel mode on the other hand is &quot;unprotected&quot; and performing kernel mode calls requires an expensive mode switch. For OpenGL the IHV's provide both the OpenGL API and driver implementations and thus IHV's can provide optimal switching between the modes. This is in contrast to DirectX where API implementation is provided by Microsoft and the driver by IHV's.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9047" PostHistoryTypeId="2" PostId="4132" RevisionGUID="dcad8e6b-8885-49db-aa36-009a7352145e" CreationDate="2016-10-14T06:29:06.383" UserId="5256" Text="So I have recently learned about Bezier Curves (quadratic &amp; cubic) and have a thorough knowledge of how they work. In my graphics engine in DirectX I wanted to implement a Bezier Curve Tool exactly like the Pen Tool in Adobe Illustrator. I understand the basic computation of the curve but I am puzzled as to how I can get mouse interaction involved.&#xD;&#xA;&#xD;&#xA;**Basically I'd like to draw Bezier Curves with a Mouse.**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/96HLA.gif&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9048" PostHistoryTypeId="1" PostId="4132" RevisionGUID="dcad8e6b-8885-49db-aa36-009a7352145e" CreationDate="2016-10-14T06:29:06.383" UserId="5256" Text="Bezier Curve Tool Controlled by Mouse" ContentLicense="CC BY-SA 3.0" />
  <row Id="9049" PostHistoryTypeId="3" PostId="4132" RevisionGUID="dcad8e6b-8885-49db-aa36-009a7352145e" CreationDate="2016-10-14T06:29:06.383" UserId="5256" Text="|opengl|glsl|line-drawing|vector-graphics|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9050" PostHistoryTypeId="5" PostId="4129" RevisionGUID="3536b13f-e443-4808-842c-5eb3d144d1a3" CreationDate="2016-10-14T06:52:51.240" UserId="2817" Comment="reworded not to use the term &quot;box filter&quot; in a misleading way" Text="I have no knowledge of SceneKit whatsoever, but the effect appears to be a simple post-process Gaussian blur of the app icon grid, with the blur radius increasing over time (i.e. increasing the blur amount) during the transition, with a touch of colour correction tacked on (which causes the darkening). It should be easy enough to implement in any graphics API that allows rendering to textures and performing image filtering on them (for instance, in OpenGL you could use framebuffer objects to achieve this).&#xD;&#xA;&#xD;&#xA;You can have a look at an example WebGL implementation [here][1]. It's worth noting that it is a separable filter; meaning, it's a rectangle-shaped filter, but you can avoid sampling the same pixels (overlapping neighbouring samples) multiple times by splitting it into two passes – a horizontal and a vertical one – to the same effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/Jam3/glsl-fast-gaussian-blur/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9051" PostHistoryTypeId="2" PostId="4133" RevisionGUID="0a701efc-c2a9-4f07-8374-e9eed10b7fe2" CreationDate="2016-10-14T12:03:01.897" UserId="2372" Text="I am trying to implement the Parallax Refraction effect explained by **Jorge Jimenez** on this presentation:  http://www.iryoku.com/downloads/Next-Generation-Character-Rendering-v6.pptx and I am facing some difficulties. Here is a screenshot of the interesting part.&#xD;&#xA;&#xD;&#xA;[![screen][1]][1]&#xD;&#xA;&#xD;&#xA;But this document lacks a bit of explanations especially the second part with the **Physically based Refraction**.&#xD;&#xA;&#xD;&#xA;Here is what I've achieved for the moment.&lt;br&gt;&#xD;&#xA;This is the simple **Parallax Refraction** effect and, as you might notice in the screenshot, there is small glitch at grazing angles in the iris when the Parallax Scale value is too high.&#xD;&#xA;&#xD;&#xA;This is caused by the parallax calculation but are there some tricks to avoid or minimize such issue ?&#xD;&#xA;&#xD;&#xA;I don't want to go deeper with parallax mapping for the moment, so I don't want to use Steep Parallax Mapping or Parallax Occlusion Mapping.&#xD;&#xA;&#xD;&#xA;[![eye][2]][2]&#xD;&#xA;&#xD;&#xA;Here is the code. Nothing really special.&#xD;&#xA;&#xD;&#xA;    // height value comes from a texture&#xD;&#xA;    float2 offset = height * viewDir;&#xD;&#xA;    offset.y = -offset.y;&#xD;&#xA;    texcoord -= ParallaxScale * offset;&#xD;&#xA;    // Next there is the texture sampling with the texcoord value&#xD;&#xA;&#xD;&#xA;I also have another question about the **Physically based Refraction** part which is not really well explained and I am missing how some values are calculated such as `refractedW`, `frontNormalW` or `heightW`. If anyone could provide some explanations about those values.&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/a08kE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/y1sCY.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9052" PostHistoryTypeId="1" PostId="4133" RevisionGUID="0a701efc-c2a9-4f07-8374-e9eed10b7fe2" CreationDate="2016-10-14T12:03:01.897" UserId="2372" Text="Eye Parallax Refraction" ContentLicense="CC BY-SA 3.0" />
  <row Id="9053" PostHistoryTypeId="3" PostId="4133" RevisionGUID="0a701efc-c2a9-4f07-8374-e9eed10b7fe2" CreationDate="2016-10-14T12:03:01.897" UserId="2372" Text="|rendering|shader|glsl|hlsl|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9054" PostHistoryTypeId="2" PostId="4134" RevisionGUID="3aa5b4cc-c72d-46d8-b462-8ba05fcf1f9f" CreationDate="2016-10-14T13:39:08.980" UserId="1952" Text="Instead of using cubic Bezier spline, you should use [cubic Hermite spline][1]. For cubic Hermite curve you specify the segment end points and tangents, which is what you then control in the tool. Hermite spline is almost the same as Bezier spline but with different $B$ matrix, so if you already understand Bezier, then understanding Hermite is a trivial step.&#xD;&#xA;&#xD;&#xA;So in the Adobe Illustrator pen tool (which based on the video I take is the same as Adobe Photoshop pen tool that I have used) you keep adding more Hermite cubic spline segments to your spline. By default the Hermite start tangent matches (with opposite sign) the end tangent of the previous segment and in GUI they are linked together (changing one changes the other). So in that configuration the curve appears smooth. However, you can unlink the tangents to cause C1 discontinuity in the spline and control them separately. This is purely GUI work though and how you control the Hermite spline tangents &amp; positions.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline" ContentLicense="CC BY-SA 3.0" />
  <row Id="9055" PostHistoryTypeId="2" PostId="4135" RevisionGUID="7c6edad1-6085-415f-947b-cd1432cc001a" CreationDate="2016-10-14T17:57:46.247" UserId="2287" Text="How do you migrate *Flexible Vertex Format Constants* (or *[FVF](https://msdn.microsoft.com/en-us/library/windows/desktop/bb172559(v=vs.85).aspx) codes*) from *DirectX 9* to *Direct3D 11*?&#xD;&#xA;&#xD;&#xA;**Old code**:&#xD;&#xA;&#xD;&#xA;    #include &lt;d3dx9.h&gt;&#xD;&#xA;&#xD;&#xA;    struct Vertex {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    	Vertex() : p(D3DXVECTOR3(0.0f, 0.0f, 0.0f)), n(D3DXVECTOR3(0.0f, 0.0f, 0.0f)), tu(0.0f), tv(0.0f) {}&#xD;&#xA;    	Vertex(D3DXVECTOR3 p, D3DXVECTOR3 n, float tu, float tv) : p(p), n(n), tu(tu), tv(tv) {}&#xD;&#xA;    &#xD;&#xA;    	// Position of the vertex (in world space)&#xD;&#xA;    	D3DXVECTOR3 p;&#xD;&#xA;    	// Normal of this vertex&#xD;&#xA;    	D3DXVECTOR3 n;&#xD;&#xA;    	// Texture UV coordinates&#xD;&#xA;    	float tu, tv;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    // D3DFVF_XYZ: Vertex format includes the position of an untransformed vertex.&#xD;&#xA;    // D3DFVF_NORMAL: Vertex format includes a vertex normal vector.&#xD;&#xA;    // D3DFVF_TEX1: Number of texture coordinate sets for this vertex.&#xD;&#xA;    #define VERTEX_FVF ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 )&#xD;&#xA;    #define VERTEX_FVF_SIZE D3DXGetFVFVertexSize( VERTEX_FVF )&#xD;&#xA;&#xD;&#xA;**New code** without [D3DX](https://blogs.msdn.microsoft.com/chuckw/2013/08/20/living-without-d3dx/):&#xD;&#xA;&#xD;&#xA;    #include &lt;DirectXMath.h&gt;&#xD;&#xA;    using namespace DirectX;&#xD;&#xA;    &#xD;&#xA;    struct Vertex {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    	Vertex() : p(XMFLOAT3(0.0f, 0.0f, 0.0f)), n(XMFLOAT3(0.0f, 0.0f, 0.0f)), tu(0.0f), tv(0.0f) {}&#xD;&#xA;    	Vertex(XMFLOAT3 p, XMFLOAT3 n, float tu, float tv) : p(p), n(n), tu(tu), tv(tv) {}&#xD;&#xA;    &#xD;&#xA;    	// Position of the vertex (in world space)&#xD;&#xA;    	XMFLOAT3 p;&#xD;&#xA;    	// Normal of this vertex&#xD;&#xA;    	XMFLOAT3 n;&#xD;&#xA;    	// Texture UV coordinates&#xD;&#xA;    	float tu, tv;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    // ??&#xD;&#xA;&#xD;&#xA;P.S.: Can someone with enough reputation points create and add a `directx9` tag." ContentLicense="CC BY-SA 3.0" />
  <row Id="9056" PostHistoryTypeId="1" PostId="4135" RevisionGUID="7c6edad1-6085-415f-947b-cd1432cc001a" CreationDate="2016-10-14T17:57:46.247" UserId="2287" Text="Flexible Vertex Format Constants in Direct3D 11" ContentLicense="CC BY-SA 3.0" />
  <row Id="9057" PostHistoryTypeId="3" PostId="4135" RevisionGUID="7c6edad1-6085-415f-947b-cd1432cc001a" CreationDate="2016-10-14T17:57:46.247" UserId="2287" Text="|c++|direct3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9058" PostHistoryTypeId="2" PostId="4136" RevisionGUID="2df34ac4-3c10-4f06-ab28-2a82bd58278e" CreationDate="2016-10-14T21:20:46.450" UserId="48" Text="Vertex formats are specified in D3D11 using the [input layout](https://msdn.microsoft.com/en-us/library/windows/desktop/ff476512(v=vs.85).aspx). An example input layout description for your vertex might look like:&#xD;&#xA;&#xD;&#xA;	D3D11_INPUT_ELEMENT_DESC aInputDescs[] =&#xD;&#xA;	{&#xD;&#xA;		{ &quot;POSITION&quot;, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, UINT(offsetof(Vertex, p)), D3D11_INPUT_PER_VERTEX_DATA, 0 },&#xD;&#xA;		{ &quot;NORMAL&quot;, 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, UINT(offsetof(Vertex, n)), D3D11_INPUT_PER_VERTEX_DATA, 0 },&#xD;&#xA;		{ &quot;UV&quot;, 0, DXGI_FORMAT_R32G32_FLOAT, 0, UINT(offsetof(Vertex, tu)), D3D11_INPUT_PER_VERTEX_DATA, 0 },&#xD;&#xA;	};&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9060" PostHistoryTypeId="2" PostId="4137" RevisionGUID="f9ca53b5-80d4-46c3-b8cc-1bdaf972b48f" CreationDate="2016-10-15T13:13:56.173" UserId="5256" Text="So recently after implementing PBR in my engine, I was wondering what are some new &amp; old  Rendering Techniques that people are implementing and researching to get Real Time Graphics closer to what things look like in real life? A list of things that come to my mind were:&#xD;&#xA;&#xD;&#xA;**Physically Based Rendering/Lighting**&#xD;&#xA;&#xD;&#xA;**Dynamic Reflections**&#xD;&#xA;&#xD;&#xA;**Shadow Mapping (also PCSS)**&#xD;&#xA;&#xD;&#xA;**Ambient Occlusion (SSAO, HBAO)**&#xD;&#xA;&#xD;&#xA;**Bloom &amp; HDR**&#xD;&#xA;&#xD;&#xA;**Depth of Field**&#xD;&#xA;&#xD;&#xA;**Lens Flares** &#xD;&#xA;&#xD;&#xA;**Motion Blur**&#xD;&#xA;&#xD;&#xA;**Particle Effects (Fog, Fire)**&#xD;&#xA;&#xD;&#xA;What are some other techniques that are being used in very graphically demanding games like Battlefield 1, Star Wars: Battlefront, Assassins Creed Unity &amp; other such games. The past few years PBR has been the biggest thing for the gaming industry, are there any new things like that 'on the rise'?   &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9061" PostHistoryTypeId="1" PostId="4137" RevisionGUID="f9ca53b5-80d4-46c3-b8cc-1bdaf972b48f" CreationDate="2016-10-15T13:13:56.173" UserId="5256" Text="What are some new Real-Time Graphics Rendering Techniques to get closer to real life?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9062" PostHistoryTypeId="3" PostId="4137" RevisionGUID="f9ca53b5-80d4-46c3-b8cc-1bdaf972b48f" CreationDate="2016-10-15T13:13:56.173" UserId="5256" Text="|opengl|lighting|physically-based|shadow|ambient-occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9063" PostHistoryTypeId="2" PostId="4138" RevisionGUID="929e788a-0d98-43d2-88a5-1d928ccaaa99" CreationDate="2016-10-15T15:22:39.140" UserId="1952" Text="PBR isn't just a feature you &quot;add to a rendering engine&quot; but an entire philosophy how to approach solving rendering problems. This seems to be a common prevailing misconception when people talk about PBR. Quite often people assume that when they have implemented physically based BRDF (e.g. GGX) into their engines, they are &quot;done implementing PBR&quot;. They are not - they are barely getting started.&#xD;&#xA;&#xD;&#xA;Let's take some of the topics you list and how do you approach implementing them in the &quot;physically based&quot; way.&#xD;&#xA;&#xD;&#xA;Depth of Field, Lens Flares, Motion Blur and Bloom &amp; HDR for example. For years these effects have been implemented and slapped as post effect on the screen with some adhoc factors exposed to artists. However, as you know these are effects happening in the camera system and they should be exposed and implemented considering how the light interacts with this system. How camera aperture, shutter speed, ISO, camera sensor and lense system influence the effects and how they should be implemented and controlled considering these physical characteristics of the camera.&#xD;&#xA;&#xD;&#xA;This same principle applies to all the aspects of rendering when you go PBR. For example shadows you mention, how would you implement shadows in physically based way? First of all you would have to consider all lights as area light sources as opposed to infinitesimally small lights that people have been doing for ages. Recently there has been push to implement physically based area lights in real-time which is an important step towards more complete PBR, but they are completely omitting proper area shadowing. This is a difficult problem in real-time rendering and there has been only little research done in the area of area shadows. &quot;[Real Time Area Lighting - Now and Next][1]&quot; by Sam Martin is a good thing to read if you are interested in the topic.&#xD;&#xA;&#xD;&#xA;Talking about dynamic reflections or lighting in general. How should all the different lighting techniques such as SSLR, local/global environment maps, (textured) area lights, SSAO, GI, etc. be implemented and integrated together to form a cohesive lighting system? That you doesn't do double counting and that they are properly accounted in diffuse and specular lighting calculations.&#xD;&#xA;&#xD;&#xA;When implementing real-time PBR algorithms, you will eventually have to introduce some bias due to performance constraints and resort to some kind of approximations. But the important thing is that you know what the real result should be and are aware of the compromises you are making. PBR is a paradigm shift from the classic artistic observation-based real-time rendering algorithm development towards more scientific way of solving the rendering problems and this shift in mentality and the direction it pushes you helps you to get more realistic results in the end.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.geomerics.com/wp-content/uploads/2014/03/AltDevConf-SamMartin-RealTimeAreaLighting.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9064" PostHistoryTypeId="2" PostId="4139" RevisionGUID="68c64b1a-0951-4ca1-acfd-d8de2be1fea7" CreationDate="2016-10-15T16:54:38.477" UserId="5256" Text="So after reading https://www.guerrilla-games.com/read/killzone-shadow-fall-creating-art-tools-for-a-new-generation (a guerilla games presentation on PBR) I noticed the Area lights as opposed to the standard Directional, Point &amp; Spot lights in DirectX can produce very realistic shadows.&#xD;&#xA;&#xD;&#xA;Now a lot of the resources online talk about it and what it is but there's not much regarding implementation. Some websites online say that it is just an array of lights but I don't think that's what it is.&#xD;&#xA;&#xD;&#xA;Can somebody explain how I can implement this (and maybe with some code). If you could include any links to some good resources regarding implementation that would be great aswell. " ContentLicense="CC BY-SA 3.0" />
  <row Id="9065" PostHistoryTypeId="1" PostId="4139" RevisionGUID="68c64b1a-0951-4ca1-acfd-d8de2be1fea7" CreationDate="2016-10-15T16:54:38.477" UserId="5256" Text="Physically Based Area Lights" ContentLicense="CC BY-SA 3.0" />
  <row Id="9066" PostHistoryTypeId="3" PostId="4139" RevisionGUID="68c64b1a-0951-4ca1-acfd-d8de2be1fea7" CreationDate="2016-10-15T16:54:38.477" UserId="5256" Text="|opengl|lighting|physically-based|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9072" PostHistoryTypeId="2" PostId="4141" RevisionGUID="0ce05921-e6f3-4f2c-8049-81772a8809b4" CreationDate="2016-10-16T14:34:20.807" UserId="1952" Text="When I implemented real-time area lighting, there were two documents I kept referring to: &quot;[Moving Frostbite to PBR][1]&quot; by Sebastien Lagarde and &quot;[Real Shading in Unreal Engine 4][2]&quot; by Brian Karis. Also &quot;[Lighting of Killzone Shadowfall][3]&quot; by Michal Drobot is an interesting read on the topic. None of these documents deal with area shadows though but focus on energy conserving approximation of the lighting integral. While there are some code snippets, these documents lack quite a bit of details how to implement area lighting though, so you need to do fair amount of research on your own. For example I posted a question and an answer [here][4] related to implementing rectangular area lights.&#xD;&#xA;&#xD;&#xA;A very valuable tool I used was to implement Monte Carlo reference model to easily compare different approximations to the ground truth. Some people also use [Mitsuba renderer][5] to validate their implementations. I think this ground truth reference is extremely important that you know if there are mistakes in your implementation and also to see where/how these approximations fail and if you can somehow try to improve them. Implementing Monte Carlo integration is also quite a good exercise to understand the underlying problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.frostbite.com/2014/11/moving-frostbite-to-pbr/&#xD;&#xA;  [2]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [3]: https://www.guerrilla-games.com/read/killzone-shadow-fall-creating-art-tools-for-a-new-generation&#xD;&#xA;  [4]: https://math.stackexchange.com/questions/1438242/finding-ray-direction-with-smallest-angle-from-a-ray-to-a-rectangle-in-3d&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9073" PostHistoryTypeId="5" PostId="4141" RevisionGUID="fe90da3b-4e47-4969-a81d-6717c05fb7a1" CreationDate="2016-10-16T14:42:19.210" UserId="1952" Comment="added 1 character in body" Text="When I implemented real-time area lighting, there were two documents I kept referring to: &quot;[Moving Frostbite to PBR][1]&quot; by Sebastien Lagarde and &quot;[Real Shading in Unreal Engine 4][2]&quot; by Brian Karis. Also &quot;[Lighting of Killzone Shadow Fall][3]&quot; by Michal Drobot is an interesting read on the topic. None of these documents deal with area shadows though but focus on energy conserving approximation of the lighting integral. While there are some code snippets, these documents lack quite a bit of details how to implement area lighting though, so you need to do fair amount of research on your own. For example I posted a question and an answer [here][4] related to implementing rectangular area lights.&#xD;&#xA;&#xD;&#xA;A very valuable tool I used was to implement Monte Carlo reference model to easily compare different approximations to the ground truth. Some people also use [Mitsuba renderer][5] to validate their implementations. I think this ground truth reference is extremely important that you know if there are mistakes in your implementation and also to see where/how these approximations fail and if you can somehow try to improve them. Implementing Monte Carlo integration is also quite a good exercise to understand the underlying problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.frostbite.com/2014/11/moving-frostbite-to-pbr/&#xD;&#xA;  [2]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [3]: https://www.guerrilla-games.com/read/killzone-shadow-fall-creating-art-tools-for-a-new-generation&#xD;&#xA;  [4]: https://math.stackexchange.com/questions/1438242/finding-ray-direction-with-smallest-angle-from-a-ray-to-a-rectangle-in-3d&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9074" PostHistoryTypeId="2" PostId="4142" RevisionGUID="95297aa1-779b-4972-9c04-50f8c6bd0ac3" CreationDate="2016-10-16T18:58:35.857" UserId="4494" Text="I'm not sure if this question is on-topic or not, based on the tour. Feel free to point me elsewhere.&#xD;&#xA;&#xD;&#xA;The short version of the question is: what's the typical technique for generating the clean-plate for footage in which the camera moves?&#xD;&#xA;&#xD;&#xA;More detail:&#xD;&#xA;&#xD;&#xA;It's easy to understand how computer graphics are superimposed over live footage to cover existing elements (like an actor in green pajamas). For example, it seems easy for the CG version of the Hulk to completely cover Mark Ruffalo without having to replace anything real that wasn't already visible in the shot.&#xD;&#xA;&#xD;&#xA;It's also easy to understand where this comes from for footage where the camera doesn't move. With a locked-off shot it's not hard to get a shot without any of the actors/props or whatever is being replaced (a clean-plate, as it were), and match that to the real take.&#xD;&#xA;&#xD;&#xA;But I'm baffled about non-locked-off shots. A good example might be a scene from Star Trek: First Contact when the Borg Queen is introduced. The upper half of her body is lowered onto a lower-half kind of rig. Whether the actress is actually lowered or not, there is background behind either her invisible real body, as she's lowered, or behind her invisible upper body as it's being rotoscoped down into position.&#xD;&#xA;&#xD;&#xA;Either way, they had to have *something* to show behind the parts of the actress that weren't supposed to be there in the final footage.&#xD;&#xA;&#xD;&#xA;One theory I've imagined is that they run the camera through the shot first without the actors, and then repeat the shot with the actors, but this seems prohibitively prone to imprecision. &#xD;&#xA;&#xD;&#xA;Another theory is that they get the clean plate from another frame in the same footage, but this seems like it'd only work in very specific cases.&#xD;&#xA;&#xD;&#xA;I've also seen tutorials in which the trick is that the shot IS locked-off, and the camera shake is added in after the composite. But again, this only works for certain kinds of shots, and I have a hard time believing that this is the way it's done for everything.&#xD;&#xA;&#xD;&#xA;**What is/are the typical technique(s) for generating a clean plate for footage in which the camera moves?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="9075" PostHistoryTypeId="1" PostId="4142" RevisionGUID="95297aa1-779b-4972-9c04-50f8c6bd0ac3" CreationDate="2016-10-16T18:58:35.857" UserId="4494" Text="How to get clean plate from moving footage?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9076" PostHistoryTypeId="3" PostId="4142" RevisionGUID="95297aa1-779b-4972-9c04-50f8c6bd0ac3" CreationDate="2016-10-16T18:58:35.857" UserId="4494" Text="|compositing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9077" PostHistoryTypeId="5" PostId="4141" RevisionGUID="2f6c92ba-2885-4cfc-96a8-a91b5dd33db0" CreationDate="2016-10-16T22:20:00.333" UserId="231" Comment="Minor wording changes - please revert any that change your intention" Text="When I implemented real-time area lighting, there were two documents I kept referring to: &quot;[Moving Frostbite to PBR][1]&quot; by Sebastien Lagarde and &quot;[Real Shading in Unreal Engine 4][2]&quot; by Brian Karis. Also &quot;[Lighting of Killzone Shadow Fall][3]&quot; by Michal Drobot is an interesting read on the topic. None of these documents deal with area shadows though but focus on energy conserving approximation of the lighting integral. While there are some code snippets, these documents lack quite a bit of details of how to implement area lighting though, so you need to do fair amount of research on your own. For example I posted a question and an answer [here][4] related to implementing rectangular area lights.&#xD;&#xA;&#xD;&#xA;A very valuable tool I used was to implement a Monte Carlo reference model to easily compare different approximations to the ground truth. Some people also use [Mitsuba renderer][5] to validate their implementations. I think this ground truth reference is extremely important so that you know if there are mistakes in your implementation and also to see where/how these approximations fail and if you can somehow try to improve them. Implementing Monte Carlo integration is also quite a good exercise to understand the underlying problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.frostbite.com/2014/11/moving-frostbite-to-pbr/&#xD;&#xA;  [2]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [3]: https://www.guerrilla-games.com/read/killzone-shadow-fall-creating-art-tools-for-a-new-generation&#xD;&#xA;  [4]: https://math.stackexchange.com/questions/1438242/finding-ray-direction-with-smallest-angle-from-a-ray-to-a-rectangle-in-3d&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9078" PostHistoryTypeId="2" PostId="4143" RevisionGUID="502530db-3b3d-4489-a8fa-7caf5226d33e" CreationDate="2016-10-17T05:22:45.560" UserId="3003" Text="There are a couple of techniques:&#xD;&#xA;&#xD;&#xA; 1. A [motion controlled camera](https://en.wikipedia.org/wiki/Motion_control_photography) - The camera is on some sort of rig connected to a computer. The computer is programmed to move the camera in a particular way. The camera runs through the moves without the actors, generating a clean set of plates. Then it is run again with the actors.&#xD;&#xA; 2. As you surmise, sometimes a larger scene is filmed with a locked-off camera to get a clean plate, then during editing, they zoom into the scene and pan around in software to create the motion you see on screen. This doesn't work well for anything that involves the camera rotating, but can work for scenes where the camera trucks.&#xD;&#xA; 3. Parts of the scenery that the actors are in front of are blocked off with green screens and recreated in post. I've seen outtakes of a few pieces where they did this. If you have the DVD of &quot;The Others&quot; with Nicole Kidman, the &quot;DVD Extras&quot; show how fog was added to scenes that were filmed without it. It basically involved someone walking around behind her holding a large green board. Then, they recreated the scenery in the computer, added fog to it, and replaced the green screen with the foggy scene. I have a vague recollection of them doing something similar in the HBO mini-series [John Adams](http://www.hbo.com/john-adams). This would likely involve cameras that record their motion. The motion is then imported into the computer and used to move the virtual camera around the scene they've recreated." ContentLicense="CC BY-SA 3.0" />
  <row Id="9079" PostHistoryTypeId="5" PostId="4143" RevisionGUID="522698bd-b87f-46e2-973f-54f871b55d6b" CreationDate="2016-10-17T05:34:42.553" UserId="3003" Comment="Added info about Forest Gump" Text="There are a couple of techniques:&#xD;&#xA;&#xD;&#xA; 1. A [motion controlled camera](https://en.wikipedia.org/wiki/Motion_control_photography) - The camera is on some sort of rig connected to a computer. The computer is programmed to move the camera in a particular way. The camera runs through the moves without the actors, generating a clean set of plates. Then it is run again with the actors, usually wearing green or blue costumes or parts of costumes. For example, in &quot;Forest Gump,&quot; one character loses his legs in a war. The actor had working legs, as shown early in the movie, and in some later scenes wore blue stockings that were composited out. (They also used other techniques, such as simply hiding his legs under various things in some scenes. Whatever works!)&#xD;&#xA; 2. As you surmise, sometimes a larger scene is filmed with a locked-off camera to get a clean plate, then during editing, they zoom into the scene and pan around in software to create the motion you see on screen. This doesn't work well for anything that involves the camera rotating, but can work for scenes where the camera trucks.&#xD;&#xA; 3. Parts of the scenery that the actors are in front of are blocked off with green screens and recreated in post. I've seen outtakes of a few pieces where they did this. If you have the DVD of &quot;The Others&quot; with Nicole Kidman, the &quot;DVD Extras&quot; show how fog was added to scenes that were filmed without it. It basically involved someone walking around behind her holding a large green board. Then, they recreated the scenery in the computer, added fog to it, and replaced the green screen with the foggy scene. I have a vague recollection of them doing something similar in the HBO mini-series [John Adams](http://www.hbo.com/john-adams). This would likely involve cameras that record their motion. The motion is then imported into the computer and used to move the virtual camera around the scene they've recreated." ContentLicense="CC BY-SA 3.0" />
  <row Id="9083" PostHistoryTypeId="2" PostId="4145" RevisionGUID="77847dad-eae4-49f7-b170-309f8d8d4cd4" CreationDate="2016-10-17T15:49:20.797" UserId="2372" Text="Here is the way I calculate the refraction vector according to Snell's law.&#xD;&#xA;&#xD;&#xA;    float cosine = dot(viewDir, worldNormal);&#xD;&#xA;    float sine = sqrt(1 - cosine * cosine);&#xD;&#xA;    &#xD;&#xA;    float sine2 = (_IOR * sine);&#xD;&#xA;    float cosine2 = sqrt(1 - sine2 * sine2);&#xD;&#xA;    &#xD;&#xA;    float3 x = -worldNormal;&#xD;&#xA;    float3 y = normalize(cross(cross(viewDir, worldNormal), worldNormal));&#xD;&#xA;    float3 refractedW = x * cosine2 + y * sine2;&#xD;&#xA;&#xD;&#xA;This is integrated with the Physically based Refraction and it gives interesting results but I still don't know how to get rid of the high parallax scale issue which appear at grazing angles...&#xD;&#xA;&#xD;&#xA;Any idea how to get rig of that ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9086" PostHistoryTypeId="50" PostId="4019" RevisionGUID="2b634e1a-f11d-455b-a125-2bfecbc92236" CreationDate="2016-10-17T18:02:20.260" UserId="-1" />
  <row Id="9087" PostHistoryTypeId="2" PostId="4146" RevisionGUID="4d45790b-32b8-4863-a233-7772b28a932d" CreationDate="2016-10-17T19:28:15.607" UserId="5256" Text="Currently I have basic shadow mapping setup in my engine. I am currently trying to implement something more realistic like **PCSS** (percentage closer soft shadows), to get a more physically accurate result just like the image below. (See how the shadow becomes softer &amp; softer towards the end?)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GtMT9.jpg&#xD;&#xA;&#xD;&#xA;My 2 questions are:&#xD;&#xA;&#xD;&#xA;**1)** Is it worth implementing a shadow mapping technique like this? **Will people actually notice the difference?**&#xD;&#xA;&#xD;&#xA;**2)** If it is worth it, what are some resources where I can learn more about it? What are the **major techniques like PCSS?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="9088" PostHistoryTypeId="1" PostId="4146" RevisionGUID="4d45790b-32b8-4863-a233-7772b28a932d" CreationDate="2016-10-17T19:28:15.607" UserId="5256" Text="Better Shadow Mapping Techniques" ContentLicense="CC BY-SA 3.0" />
  <row Id="9089" PostHistoryTypeId="3" PostId="4146" RevisionGUID="4d45790b-32b8-4863-a233-7772b28a932d" CreationDate="2016-10-17T19:28:15.607" UserId="5256" Text="|opengl|lighting|physically-based|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9091" PostHistoryTypeId="2" PostId="4147" RevisionGUID="f10cde37-d6ed-4dcf-a427-928d7322e6f8" CreationDate="2016-10-18T00:21:11.790" UserId="5316" Text="(Apologies: I am cross-posting from SO, where there is no answer. I figured it might be more appropriate to be on this site.)&#xD;&#xA;&#xD;&#xA;I'm trying to build a compute shader in OpenGL to perform a skeletonization algorithm. I've tested the algorithm in a CPU only version, and it was correct there. However, I'm having some trouble porting it to compute shader code.&#xD;&#xA;&#xD;&#xA;The problem is that no matter how many invocations of the compute shader I run, the output never changes past the first invocation. In fact, if I take out the check at the end of the while loop, the program never terminates.&#xD;&#xA;&#xD;&#xA;I have two areas of memory that I use for input and output. I'm trying to do a trick with glBindBufferBase() in the main while loop where I swap the two of them (output of the last round becomes input for the current round). See lines 270 - 318 in main.cpp. This is so I don't copy the data back and forth between the CPU and GPU a bunch of times.&#xD;&#xA;&#xD;&#xA;I have also reworked a version of this to memcpy IMG_1 back to data and then call glBufferData with data. It works correctly, but doing all of these CPU &lt;-&gt; GPU operations seems horribly inefficient. &#xD;&#xA;&#xD;&#xA;So, my questions are:&#xD;&#xA;&#xD;&#xA;1) Can I do this trick with glBindBuffers, where I swap them around so that I can operate on the data multiple times without moving it back to the CPU? In testing on a smaller problem (just adding short arrays), it worked.&#xD;&#xA;&#xD;&#xA;2) If the trick is fine, where am I going wrong?&#xD;&#xA;&#xD;&#xA;Note: this code needs a 640 x 400 size .pgm (black and white image) called &quot;test.pgm&quot;. You can make one in GIMP, but be sure to save it as a binary one instead of an ASCII one.&#xD;&#xA;&#xD;&#xA;This code is compiled with the following flags&#xD;&#xA;&#xD;&#xA;    g++ -g pgm.cpp main.cpp -lglut -lGLU -lGL -lm -lGLEW -o test&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, forgive me for using C++ but doing C style tricks. I spend more time in C than I do C++.&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;    // Include standard headers&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA;    #include &lt;stdarg.h&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    #include &lt;errno.h&gt;&#xD;&#xA;    &#xD;&#xA;    //For stat&#xD;&#xA;    #include &lt;sys/types.h&gt;&#xD;&#xA;    #include &lt;sys/stat.h&gt;&#xD;&#xA;    #include &lt;unistd.h&gt;&#xD;&#xA;    &#xD;&#xA;    // Include GLEW&#xD;&#xA;    #include &lt;GL/glew.h&gt;&#xD;&#xA;    &#xD;&#xA;    //Glut&#xD;&#xA;    #include &lt;GL/glut.h&gt;&#xD;&#xA;    &#xD;&#xA;    //Project specific&#xD;&#xA;    #include &quot;skeletonize.hpp&quot;&#xD;&#xA;    #include &quot;PGM.hpp&quot;&#xD;&#xA;    &#xD;&#xA;    // OpenGL shader info&#xD;&#xA;    GLuint programID;&#xD;&#xA;    GLuint output_image;&#xD;&#xA;    &#xD;&#xA;    #define IMG_0               0&#xD;&#xA;    #define IMG_1               1&#xD;&#xA;    #define CMD                 2&#xD;&#xA;    #define NUM_BUFS            3&#xD;&#xA;    &#xD;&#xA;    #define CMD_BUF_WIDTH       0&#xD;&#xA;    #define CMD_BUF_HEIGHT      1&#xD;&#xA;    #define CMD_BUF_CMD         2&#xD;&#xA;    #define CMD_BUF_RESPONSE    3&#xD;&#xA;    #define CMD_BUF_LEN         4&#xD;&#xA;    &#xD;&#xA;    #define CMD_EXPAND          1&#xD;&#xA;    #define CMD_THIN_N          2&#xD;&#xA;    #define CMD_THIN_S          3&#xD;&#xA;    #define CMD_THIN_E          4&#xD;&#xA;    #define CMD_THIN_W          5&#xD;&#xA;    #define CMD_NORMALIZE       6&#xD;&#xA;    #define CMD_REGULARIZE      7&#xD;&#xA;    &#xD;&#xA;    #define INITIALIZED         0&#xD;&#xA;    #define NOT_FINISHED        1&#xD;&#xA;    &#xD;&#xA;    GLuint computeProgram;&#xD;&#xA;    GLuint buffers[NUM_BUFS];       //SSBO objects, one for IMG_0, one for IMG_1, and one for commands/response&#xD;&#xA;    static GLchar* computeSource;&#xD;&#xA;    GLuint shaderProgram;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    //TODO: don't really need 2 textures yet, but will eventually when doing overlay of original image.&#xD;&#xA;    GLuint textures[2];&#xD;&#xA;&#xD;&#xA;    GLchar* LoadSource(const char* pFile)&#xD;&#xA;    {&#xD;&#xA;        struct stat buf;&#xD;&#xA;        GLchar *source;&#xD;&#xA;        int fd;&#xD;&#xA;    &#xD;&#xA;        if (stat(pFile, &amp;buf) == -1)&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Error opening file\n&quot;);&#xD;&#xA;            printf(&quot;Error: %s\n&quot;, strerror(errno));&#xD;&#xA;            return NULL;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        fd = open(pFile, O_RDONLY);&#xD;&#xA;    &#xD;&#xA;        if (fd == -1)&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Error opening file. Error: %s\n&quot;, strerror(errno));&#xD;&#xA;            return NULL;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        source = new GLchar[buf.st_size + 1];&#xD;&#xA;    &#xD;&#xA;        if (read(fd, source, buf.st_size) == -1)&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Error reading file. Error: %s\n&quot;, strerror(errno));&#xD;&#xA;            delete[] source;&#xD;&#xA;            return NULL;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        source[buf.st_size] = '\0'; //Shader compiler needs null to know end of input&#xD;&#xA;        return source;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Shader sources&#xD;&#xA;    const GLchar* vertexSource =&#xD;&#xA;        &quot;#version 450 core\n&quot;&#xD;&#xA;        &quot;in vec2 position;&quot;&#xD;&#xA;        &quot;in vec2 texcoord;&quot;&#xD;&#xA;        &quot;out vec2 Texcoord;&quot;&#xD;&#xA;        &quot;void main()&quot;&#xD;&#xA;        &quot;{&quot;&#xD;&#xA;        &quot;    Texcoord = texcoord;&quot;&#xD;&#xA;        &quot;    gl_Position = vec4(position, 0.0, 1.0);&quot;&#xD;&#xA;        &quot;}&quot;;&#xD;&#xA;    &#xD;&#xA;    const GLchar* fragmentSource =&#xD;&#xA;        &quot;#version 450 core\n&quot;&#xD;&#xA;        &quot;in vec2 Texcoord;&quot;&#xD;&#xA;        &quot;out vec4 outColor;&quot;&#xD;&#xA;        &quot;uniform sampler2D texData;&quot;&#xD;&#xA;        &quot;void main()&quot;&#xD;&#xA;        &quot;{&quot;&#xD;&#xA;        &quot;   vec4 imColor = texture(texData, Texcoord);&quot;&#xD;&#xA;        &quot;   outColor = vec4(0.0, imColor.r, 0.0, 1.0);&quot;&#xD;&#xA;        //&quot;    outColor = texture(texData, Texcoord);&quot;&#xD;&#xA;        //&quot;    outColor = vec4(1.0, 1.0, 0.0, 1.0);&quot;&#xD;&#xA;        &quot;}&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void checkError(int line)&#xD;&#xA;    {&#xD;&#xA;        GLint err;&#xD;&#xA;    &#xD;&#xA;        do&#xD;&#xA;        {&#xD;&#xA;            err = glGetError();&#xD;&#xA;            switch (err)&#xD;&#xA;            {&#xD;&#xA;                case GL_NO_ERROR:&#xD;&#xA;                    //printf(&quot;%d: No error\n&quot;, line);&#xD;&#xA;                    break;&#xD;&#xA;                case GL_INVALID_ENUM:&#xD;&#xA;                    printf(&quot;%d: Invalid enum!\n&quot;, line);&#xD;&#xA;                    break;&#xD;&#xA;                case GL_INVALID_VALUE:&#xD;&#xA;                    printf(&quot;%d: Invalid value\n&quot;, line);&#xD;&#xA;                    break;&#xD;&#xA;                case GL_INVALID_OPERATION:&#xD;&#xA;                    printf(&quot;%d: Invalid operation\n&quot;, line);&#xD;&#xA;                    break;&#xD;&#xA;                case GL_INVALID_FRAMEBUFFER_OPERATION:&#xD;&#xA;                    printf(&quot;%d: Invalid framebuffer operation\n&quot;, line);&#xD;&#xA;                    break;&#xD;&#xA;                case GL_OUT_OF_MEMORY:&#xD;&#xA;                    printf(&quot;%d: Out of memory\n&quot;, line);&#xD;&#xA;                    break;&#xD;&#xA;                default:&#xD;&#xA;                    printf(&quot;%d: glGetError default case. Should not happen!\n&quot;, line);&#xD;&#xA;            }&#xD;&#xA;        } while (err != GL_NO_ERROR);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void display()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    	glClearColor(0.0f, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;    &#xD;&#xA;        glFlush();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void reshape(int width,int height)&#xD;&#xA;    {&#xD;&#xA;        double w2h = (height&gt;0) ? (double)width/height : 1;&#xD;&#xA;        //  Set viewport as entire window&#xD;&#xA;        glViewport(0,0, width,height);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void runComputeProgram(uint32_t *data, uint32_t *data2)&#xD;&#xA;    {&#xD;&#xA;        int width = 640;&#xD;&#xA;        int height = 400;&#xD;&#xA;    &#xD;&#xA;        uint32_t *ptr;&#xD;&#xA;        uint32_t cmd[CMD_BUF_LEN];&#xD;&#xA;    &#xD;&#xA;        computeSource = LoadSource(&quot;compute.shader&quot;);&#xD;&#xA;        if (computeSource == NULL)&#xD;&#xA;        {&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);&#xD;&#xA;        glShaderSource(computeShader, 1, &amp;computeSource, NULL);&#xD;&#xA;        glCompileShader(computeShader);&#xD;&#xA;    &#xD;&#xA;        computeProgram = glCreateProgram();&#xD;&#xA;        glAttachShader(computeProgram, computeShader);&#xD;&#xA;        glLinkProgram(computeProgram);&#xD;&#xA;        GLint status;&#xD;&#xA;        glGetProgramiv(computeProgram, GL_LINK_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;        if (status == GL_TRUE)&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;link good\n&quot;);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;link bad\n&quot;);&#xD;&#xA;            GLchar log[4096];&#xD;&#xA;            GLsizei len;&#xD;&#xA;    &#xD;&#xA;            glGetProgramInfoLog(computeProgram, 4096, &amp;len, log);&#xD;&#xA;    &#xD;&#xA;            printf(&quot;%s\n&quot;, log);&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // First action is to transform the image into binary values (0, 1)&#xD;&#xA;        &#xD;&#xA;        cmd[CMD_BUF_CMD] = CMD_NORMALIZE;&#xD;&#xA;        cmd[CMD_BUF_WIDTH] = width;&#xD;&#xA;        cmd[CMD_BUF_HEIGHT] = height;&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(NUM_BUFS, buffers);&#xD;&#xA;    &#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffers[CMD]);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cmd), cmd, GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffers[IMG_0]);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t) * width * height, data, GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, buffers[IMG_1]);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t) * width * height, data2, GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glUseProgram(computeProgram);&#xD;&#xA;    &#xD;&#xA;        glDispatchCompute(width / 16, height / 16, 1);&#xD;&#xA;        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, buffers[IMG_1]);&#xD;&#xA;        ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);&#xD;&#xA;    &#xD;&#xA;        glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);&#xD;&#xA;        &#xD;&#xA;        // Rebind ptr for our while loop&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffers[CMD]);&#xD;&#xA;        //glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cmd), cmd, GL_DYNAMIC_DRAW);&#xD;&#xA;        ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);&#xD;&#xA;        &#xD;&#xA;        int i = 0;&#xD;&#xA;        do&#xD;&#xA;        {   &#xD;&#xA;            printf(&quot;iteration: %d&quot;, i);&#xD;&#xA;            glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);&#xD;&#xA;            cmd[CMD_BUF_RESPONSE] = INITIALIZED;&#xD;&#xA;            &#xD;&#xA;            switch (i % 4)&#xD;&#xA;            {&#xD;&#xA;                case 0:&#xD;&#xA;                    cmd[CMD_BUF_CMD] = CMD_THIN_N;&#xD;&#xA;                    break;&#xD;&#xA;                case 1:&#xD;&#xA;                    cmd[CMD_BUF_CMD] = CMD_THIN_S;&#xD;&#xA;                    break;&#xD;&#xA;                case 2:&#xD;&#xA;                    cmd[CMD_BUF_CMD] = CMD_THIN_E;&#xD;&#xA;                    break;&#xD;&#xA;                case 3:&#xD;&#xA;                    cmd[CMD_BUF_CMD] = CMD_THIN_W;&#xD;&#xA;                    break;&#xD;&#xA;            }        &#xD;&#xA;            &#xD;&#xA;            glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cmd), cmd, GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glDispatchCompute(width / 16, height / 16, 1);&#xD;&#xA;            glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;           &#xD;&#xA;            if (i % 2 == 0)&#xD;&#xA;            {&#xD;&#xA;                printf(&quot;Input is now img_1. Output is img_0\n&quot;);&#xD;&#xA;                glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffers[IMG_1]);&#xD;&#xA;                glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, buffers[IMG_0]);&#xD;&#xA;                checkError(__LINE__);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                printf(&quot;Input is now img_0. Output is img_1\n&quot;);&#xD;&#xA;                glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffers[IMG_0]);&#xD;&#xA;                glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, buffers[IMG_1]);&#xD;&#xA;                checkError(__LINE__);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffers[CMD]);&#xD;&#xA;            ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);&#xD;&#xA;            printf(&quot;cmd issued at start: %d response: %d\n&quot;,  ptr[CMD_BUF_CMD], ptr[CMD_BUF_RESPONSE]);&#xD;&#xA;            i++;&#xD;&#xA;        } while(ptr[CMD_BUF_RESPONSE] != INITIALIZED &amp;&amp; i &lt; 10); //Using i &lt; 10, otherwise this never terminates&#xD;&#xA;    &#xD;&#xA;        glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); // Free ptr&#xD;&#xA;    &#xD;&#xA;        // Transform Binary image (0, 1) to (0, 0xFFFFFFFF) values for texture display&#xD;&#xA;        cmd[CMD_BUF_CMD] = CMD_REGULARIZE;        &#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffers[CMD]);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cmd), cmd, GL_DYNAMIC_DRAW);&#xD;&#xA;      &#xD;&#xA;        glDispatchCompute(width / 16, height / 16, 1);&#xD;&#xA;        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;        &#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffers[CMD]);&#xD;&#xA;        ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);&#xD;&#xA;        printf(&quot;Regularize: cmd: %d  width: %d  height: %d response: %d\n&quot;,  ptr[CMD_BUF_CMD], ptr[CMD_BUF_WIDTH], ptr[CMD_BUF_HEIGHT], ptr[CMD_BUF_RESPONSE]);&#xD;&#xA;    &#xD;&#xA;        // Create texure&#xD;&#xA;        glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);&#xD;&#xA;        &#xD;&#xA;        glGenTextures(2, textures);&#xD;&#xA;        checkError(__LINE__);&#xD;&#xA;        glActiveTexture(GL_TEXTURE0);&#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, textures[0]);&#xD;&#xA;            checkError(__LINE__);&#xD;&#xA;    &#xD;&#xA;        if (i % 2 == 0)&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;output image is img_1\n&quot;);&#xD;&#xA;            glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, buffers[IMG_1]);&#xD;&#xA;            ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {        &#xD;&#xA;            printf(&quot;output image is img_0\n&quot;);&#xD;&#xA;            glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, buffers[IMG_0]);&#xD;&#xA;            ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);&#xD;&#xA;        &#xD;&#xA;        glUseProgram(shaderProgram);&#xD;&#xA;        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,  GL_RED,  GL_UNSIGNED_INT, ptr);  //TODO: this is wrong. worry about later.&#xD;&#xA;            checkError(__LINE__);&#xD;&#xA;    &#xD;&#xA;        glUniform1i(glGetUniformLocation(shaderProgram, &quot;texData&quot;), 0);&#xD;&#xA;        checkError(__LINE__);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        checkError(__LINE__);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void initGL()&#xD;&#xA;    {&#xD;&#xA;        // Vertices &amp; texture init&#xD;&#xA;    &#xD;&#xA;        GLuint vao;&#xD;&#xA;        glGenVertexArrays(1, &amp;vao);&#xD;&#xA;        glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;        GLuint vbo;&#xD;&#xA;        glGenBuffers(1, &amp;vbo);&#xD;&#xA;    &#xD;&#xA;        GLfloat vertices[] = {&#xD;&#xA;            // X    Y      S    T&#xD;&#xA;            -1.0f,  1.0f, 0.0f, 0.0f, // Top-left&#xD;&#xA;             1.0f,  1.0f, 1.0f, 0.0f, // Top-right&#xD;&#xA;             1.0f, -1.0f, 1.0f, 1.0f, // Bottom-right&#xD;&#xA;            -1.0f, -1.0f, 0.0f, 1.0f  // Bottom-left&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        GLuint ebo;&#xD;&#xA;        glGenBuffers(1, &amp;ebo);&#xD;&#xA;    &#xD;&#xA;        GLuint elements[] = {&#xD;&#xA;            0, 1, 2,&#xD;&#xA;            2, 3, 0&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        // Create shaders&#xD;&#xA;    &#xD;&#xA;        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;        glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);&#xD;&#xA;        glCompileShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;        glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);&#xD;&#xA;        glCompileShader(fragmentShader);&#xD;&#xA;    &#xD;&#xA;        shaderProgram = glCreateProgram();&#xD;&#xA;        glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;        glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;        glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;);&#xD;&#xA;        glLinkProgram(shaderProgram);&#xD;&#xA;        glUseProgram(shaderProgram);&#xD;&#xA;    &#xD;&#xA;        // Vertex data specification&#xD;&#xA;        GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;);&#xD;&#xA;        glEnableVertexAttribArray(posAttrib);&#xD;&#xA;        glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);&#xD;&#xA;    &#xD;&#xA;        GLint texAttrib = glGetAttribLocation(shaderProgram, &quot;texcoord&quot;);&#xD;&#xA;        glEnableVertexAttribArray(texAttrib);&#xD;&#xA;        glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)));&#xD;&#xA;        checkError(__LINE__);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char** argv)&#xD;&#xA;    {&#xD;&#xA;        // Image setup&#xD;&#xA;    &#xD;&#xA;        PGM pgmImage;&#xD;&#xA;        pgmImage.ReadFile(&quot;test.pgm&quot;);&#xD;&#xA;    &#xD;&#xA;        uint32_t *data = new uint32_t[pgmImage.GetHeight() * pgmImage.GetWidth()];&#xD;&#xA;        uint32_t *data2 = new uint32_t[pgmImage.GetHeight() * pgmImage.GetWidth()];&#xD;&#xA;        unsigned int size = pgmImage.GetHeight() * pgmImage.GetWidth();&#xD;&#xA;        uint8_t *pgmData = pgmImage.GetData();&#xD;&#xA;        for (int i=0; i &lt; size; i++)&#xD;&#xA;        {&#xD;&#xA;            data[i] = pgmData[i];&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        int count = 0;&#xD;&#xA;        for (int i =0; i &lt; pgmImage.GetHeight() * pgmImage.GetWidth(); i++)&#xD;&#xA;        {&#xD;&#xA;            if (data[i] == 0xFF)&#xD;&#xA;            {&#xD;&#xA;                count++;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        printf(&quot;count: %d\n&quot;, count);&#xD;&#xA;    &#xD;&#xA;        // Window Setup&#xD;&#xA;    &#xD;&#xA;        glutInitWindowSize(640, 400);&#xD;&#xA;        glutInitWindowPosition (140, 140);&#xD;&#xA;        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);&#xD;&#xA;        glutInit(&amp;argc, argv);&#xD;&#xA;    &#xD;&#xA;        glutCreateWindow( &quot;OpenGL Application&quot; );&#xD;&#xA;        glutDisplayFunc(display);&#xD;&#xA;        glutReshapeFunc(reshape);&#xD;&#xA;    &#xD;&#xA;        glewExperimental = true;&#xD;&#xA;        if (glewInit() != GLEW_OK) {&#xD;&#xA;            fprintf(stderr, &quot;Failed to initialize GLEW\n&quot;);&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        initGL();&#xD;&#xA;        runComputeProgram(data, data2);&#xD;&#xA;        checkError(__LINE__);&#xD;&#xA;        glutMainLoop();&#xD;&#xA;        return 0;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;compute.shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    //#extension GL_NV_shader_buffer_load : enable&#xD;&#xA;    &#xD;&#xA;    #define WIDTH           0    // Width of image&#xD;&#xA;    #define HEIGHT          1    // Height of image&#xD;&#xA;    #define CMD             2    // Command to execute&#xD;&#xA;    #define RESPONSE        3    // Response to command&#xD;&#xA;    #define BUF_LEN         4&#xD;&#xA;    &#xD;&#xA;    #define CMD_UNUSED      1    // TODO: remove this. Will have to be mirroed in C code.&#xD;&#xA;    #define CMD_THIN_N      2&#xD;&#xA;    #define CMD_THIN_S      3&#xD;&#xA;    #define CMD_THIN_E      4&#xD;&#xA;    #define CMD_THIN_W      5&#xD;&#xA;    #define CMD_NORMALIZE   6&#xD;&#xA;    #define CMD_REGULARIZE  7&#xD;&#xA;    &#xD;&#xA;    #define NOT_FINISHED 1&#xD;&#xA;    &#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16) in;&#xD;&#xA;    //layout (local_size_x = 1) in; //TODO: remove&#xD;&#xA;    &#xD;&#xA;    layout (std430, binding = 0) buffer Cmd {&#xD;&#xA;       uint cmd_buf[BUF_LEN]; //Width, height, command, response&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    layout (std430, binding = 1) buffer Img1 {&#xD;&#xA;       uint image_0[];&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    layout (std430, binding = 2) buffer Img2 {&#xD;&#xA;        uint image_1[];&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int sigma(uint data[9]) {&#xD;&#xA;        int i;&#xD;&#xA;        int sigma = 0;&#xD;&#xA;    &#xD;&#xA;        // Assume 9 pixels, A0 (pixel of interest) -&gt; A8&#xD;&#xA;        // In image, A0 is center&#xD;&#xA;        // 1 2 3&#xD;&#xA;        // 8 0 4&#xD;&#xA;        // 7 6 5&#xD;&#xA;    &#xD;&#xA;        for (i=1; i &lt; 9; i++)&#xD;&#xA;        {&#xD;&#xA;            sigma += int(data[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        return sigma;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int chi(uint data[9]) {&#xD;&#xA;        int chi;&#xD;&#xA;    &#xD;&#xA;        // Assume 9 pixels, A0 (pixel of interest) -&gt; A8&#xD;&#xA;        // 1 2 3&#xD;&#xA;        // 8 0 4&#xD;&#xA;        // 7 6 5&#xD;&#xA;    &#xD;&#xA;        chi = int(data[1] != data[3]) +&#xD;&#xA;              int(data[3] != data[5]) +&#xD;&#xA;              int(data[5] != data[7]) +&#xD;&#xA;              int(data[7] != data[1]) +&#xD;&#xA;    &#xD;&#xA;              2 * ( int((data[2] &gt; data[1]) &amp;&amp; (data[2] &gt; data[3])) ) +&#xD;&#xA;              int((data[4] &gt; data[3]) &amp;&amp; (data[4] &gt; data[5])) +&#xD;&#xA;              int((data[6] &gt; data[5]) &amp;&amp; (data[6] &gt; data[7])) +&#xD;&#xA;              int((data[8] &gt; data[7]) &amp;&amp; (data[8] &gt; data[1]));&#xD;&#xA;    &#xD;&#xA;       return chi;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // 1 2 3&#xD;&#xA;    // 8 0 4&#xD;&#xA;    // 7 6 5&#xD;&#xA;    int getPos(in int x, int y) {&#xD;&#xA;       return y * int(cmd_buf[WIDTH]) + x;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    uint getVal(in int pos) {&#xD;&#xA;       return image_0[ uint(pos) ];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int removePoint(uint neighborhood[9]) {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;    &#xD;&#xA;        if (chi(neighborhood) == 2 &amp;&amp; sigma(neighborhood) != 1) {&#xD;&#xA;            image_1[getPos(x, y)] = 0;&#xD;&#xA;            cmd_buf[RESPONSE] = NOT_FINISHED;&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            //TODO: needed? Swapping back and forth between input and output should account for this&#xD;&#xA;            image_1[getPos(x,y)] = 1;&#xD;&#xA;        }   &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void getNeighborhood(inout uint neighborhood[9]) {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;        int bottom = int(cmd_buf[WIDTH] * (cmd_buf[HEIGHT] - 1));&#xD;&#xA;        int pos = getPos(x, y);&#xD;&#xA;        int width = int(cmd_buf[WIDTH]);&#xD;&#xA;        int height = int(cmd_buf[HEIGHT]);&#xD;&#xA;        uint pixel;&#xD;&#xA;        int i = 0;&#xD;&#xA;    &#xD;&#xA;        for (i=1; i &lt; 9; i++) {&#xD;&#xA;           neighborhood[i] = 2;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (pos &lt; width) {&#xD;&#xA;            // Pixel on top, fill outiside image with zero&#xD;&#xA;           neighborhood[1] = 0;&#xD;&#xA;           neighborhood[2] = 0;&#xD;&#xA;           neighborhood[3] = 0;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (pos % width == 0) {&#xD;&#xA;            // Pixel is on left edge. Fill area outside of image with zero&#xD;&#xA;            neighborhood[1] = 0;&#xD;&#xA;            neighborhood[8] = 0;&#xD;&#xA;            neighborhood[7] = 0;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if ((pos % width) == (width - 1)) {&#xD;&#xA;            // Pixel is on right edge.&#xD;&#xA;            neighborhood[3] = 0;&#xD;&#xA;            neighborhood[4] = 0;&#xD;&#xA;            neighborhood[5] = 0;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (pos &gt;= bottom) {&#xD;&#xA;            // Pixel is on bottom edge.&#xD;&#xA;            neighborhood[5] = 0;&#xD;&#xA;            neighborhood[6] = 0;&#xD;&#xA;            neighborhood[7] = 0;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Get remaining pixels&#xD;&#xA;        for (i=1; i &lt; 9; i++) {&#xD;&#xA;            if (neighborhood[i] == 2) {&#xD;&#xA;                switch (i) {&#xD;&#xA;                    case 1:&#xD;&#xA;                        // Upper left pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos - 1 - width);&#xD;&#xA;                        break;&#xD;&#xA;                    case 2:&#xD;&#xA;                        // Upper middle pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos - width);&#xD;&#xA;                        break;&#xD;&#xA;                    case 3:&#xD;&#xA;                        // Upper right pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos + 1 - width);&#xD;&#xA;                        break;&#xD;&#xA;                    case 4:&#xD;&#xA;                        // Right pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos + 1);&#xD;&#xA;                        break;&#xD;&#xA;                    case 5:&#xD;&#xA;                        // Bottom right pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos + width + 1);&#xD;&#xA;                        break;&#xD;&#xA;                    case 6:&#xD;&#xA;                        // Bottom middle pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos + width);&#xD;&#xA;                        break;&#xD;&#xA;                    case 7:&#xD;&#xA;                        // Bottom left pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos + width - 1);&#xD;&#xA;                        break;&#xD;&#xA;                    case 8:&#xD;&#xA;                        // Left pixel&#xD;&#xA;                        neighborhood[i] = getVal(pos - 1);&#xD;&#xA;                        break;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void normalize() {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;        uint val = image_0[getPos(x, y)] == 0x0 ? 0 : 1;&#xD;&#xA;    &#xD;&#xA;        image_0[getPos(x, y)] = val;&#xD;&#xA;        image_1[getPos(x, y)] = val;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void regularize() {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;        uint val = image_0[getPos(x, y)] == 0x0 ? 0 : 0xFFFFFFFF;&#xD;&#xA;        &#xD;&#xA;        if (val != 0xFFFFFFFF)&#xD;&#xA;        {&#xD;&#xA;            cmd_buf[RESPONSE] = 99; //Test Value -- TODO: remove&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        image_1[getPos(x, y)] = val;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // North-South-East-West skeletonization&#xD;&#xA;    void skeleton() {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;        uint neighborhood[9];&#xD;&#xA;        neighborhood[0] = getVal(getPos(x, y));&#xD;&#xA;       &#xD;&#xA;        // Only consider cases where the center is 1&#xD;&#xA;        if (neighborhood[0] != 1) {&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        getNeighborhood(neighborhood);&#xD;&#xA;        &#xD;&#xA;        switch (cmd_buf[CMD]) {&#xD;&#xA;            case CMD_THIN_N:&#xD;&#xA;                //north&#xD;&#xA;                if (neighborhood[2] == 0 &amp;&amp; neighborhood[6] == 1) {&#xD;&#xA;                    removePoint(neighborhood);&#xD;&#xA;                }&#xD;&#xA;                break;&#xD;&#xA;            case CMD_THIN_S:&#xD;&#xA;                //south&#xD;&#xA;                if (neighborhood[2] == 1 &amp;&amp; neighborhood[6] == 0) {&#xD;&#xA;                    removePoint(neighborhood);&#xD;&#xA;                }&#xD;&#xA;                break;&#xD;&#xA;            case CMD_THIN_E:&#xD;&#xA;                //east&#xD;&#xA;                if (neighborhood[4] == 0 &amp;&amp; neighborhood[8] == 1) {&#xD;&#xA;                    removePoint(neighborhood);&#xD;&#xA;                }&#xD;&#xA;                break;&#xD;&#xA;            case CMD_THIN_W:&#xD;&#xA;                //west&#xD;&#xA;                if (neighborhood[4] == 1 &amp;&amp; neighborhood[8] == 0) {&#xD;&#xA;                    removePoint(neighborhood);&#xD;&#xA;                }&#xD;&#xA;                break;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;        switch (cmd_buf[CMD]) {&#xD;&#xA;            case CMD_THIN_N:&#xD;&#xA;            case CMD_THIN_S:&#xD;&#xA;            case CMD_THIN_E:&#xD;&#xA;            case CMD_THIN_W:&#xD;&#xA;                skeleton();&#xD;&#xA;                break;&#xD;&#xA;            case CMD_NORMALIZE:&#xD;&#xA;                normalize();&#xD;&#xA;                break;&#xD;&#xA;            case CMD_REGULARIZE:&#xD;&#xA;                regularize();&#xD;&#xA;                break;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;pgm.cpp&#xD;&#xA;&#xD;&#xA;    #include &quot;PGM.hpp&quot;&#xD;&#xA;    &#xD;&#xA;    #define PGM_HEADER &quot;P5&quot;&#xD;&#xA;    &#xD;&#xA;    PGM::PGM()&#xD;&#xA;    {&#xD;&#xA;        mpData = NULL;&#xD;&#xA;        Clear();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    PGM::~PGM()&#xD;&#xA;    {&#xD;&#xA;        Clear();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    uint8_t* PGM::GetData()&#xD;&#xA;    {&#xD;&#xA;        return mpImgData;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    uint16_t PGM::GetWidth()&#xD;&#xA;    {&#xD;&#xA;        return mWidth;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    uint16_t PGM::GetHeight()&#xD;&#xA;    {&#xD;&#xA;        return mHeight;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    uint8_t PGM::GetMaxWhite()&#xD;&#xA;    {&#xD;&#xA;        return mMaxWhite;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void PGM::Clear()&#xD;&#xA;    {&#xD;&#xA;        if (mpData != NULL)&#xD;&#xA;        {&#xD;&#xA;            delete[] mpData;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        mpImgData = NULL;&#xD;&#xA;        mWidth = 0;&#xD;&#xA;        mHeight = 0;&#xD;&#xA;        mMaxWhite = 255;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Finds the &#xD;&#xA;    int PGM::PopulateFields(size_t size)&#xD;&#xA;    {&#xD;&#xA;        int i;&#xD;&#xA;        bool EOL = false;&#xD;&#xA;        bool haveWhite = false;&#xD;&#xA;        bool comment = false;&#xD;&#xA;        &#xD;&#xA;        if (mpData == NULL) { return -1; }&#xD;&#xA;    &#xD;&#xA;        // Check header&#xD;&#xA;        if ((mpData[0] != 0x50) || (mpData[1] != 0x35)) { return -2; }&#xD;&#xA;        &#xD;&#xA;        //Ignore the comment&#xD;&#xA;        //Start at 3rd position in file, after &quot;P5&quot; header    &#xD;&#xA;        for (i = 2; i &lt; size; i++)&#xD;&#xA;        {&#xD;&#xA;            if (mpData[i] == '#') &#xD;&#xA;            { &#xD;&#xA;                comment = true;&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            if (mpData[i] == 0x0A &amp;&amp; comment == true)&#xD;&#xA;            {&#xD;&#xA;                comment = false;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            if (comment == true) &#xD;&#xA;            { &#xD;&#xA;                continue; &#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        // Get width and height&#xD;&#xA;        i++;&#xD;&#xA;        sscanf((char *)&amp;mpData[i], &quot;%4&quot; SCNu16 &quot; %4&quot; SCNu16, &amp;mWidth, &amp;mHeight);&#xD;&#xA;        &#xD;&#xA;        for (i; i &lt; size; i++)&#xD;&#xA;        {&#xD;&#xA;            //Move past the width and height we just found&#xD;&#xA;            if (mpData[i] == 0x0A &amp;&amp; EOL == false)&#xD;&#xA;            {&#xD;&#xA;                EOL = true;&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // If past the width and height, now at the range. Save it.&#xD;&#xA;            if (EOL == true &amp;&amp; haveWhite == false)&#xD;&#xA;            {&#xD;&#xA;                sscanf((char *)&amp;mpData[i], &quot;%3&quot; SCNu8, &amp;mMaxWhite);&#xD;&#xA;                haveWhite = true;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            if (haveWhite == true &amp;&amp; mpData[i] == 0x0A)&#xD;&#xA;            {&#xD;&#xA;                i++; //Move to next element - start of the actual data&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        if (i == size)&#xD;&#xA;        {&#xD;&#xA;            return -3; //Did not find the start of data.&#xD;&#xA;        }&#xD;&#xA;         &#xD;&#xA;        mpImgData = &amp;mpData[i];&#xD;&#xA;        &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Reads a PGM file. Returns 0 on success, other values on failure&#xD;&#xA;    int PGM::ReadFile(const char *pPath)&#xD;&#xA;    {&#xD;&#xA;        struct stat st;&#xD;&#xA;        int fd;&#xD;&#xA;     &#xD;&#xA;        if (this-&gt;mpData != NULL)&#xD;&#xA;        {&#xD;&#xA;            Clear();&#xD;&#xA;        }&#xD;&#xA;           &#xD;&#xA;        if (stat(pPath, &amp;st) != 0)&#xD;&#xA;        {&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        fd = open(pPath, O_RDONLY);&#xD;&#xA;        &#xD;&#xA;        if (fd == -1)&#xD;&#xA;        {&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        //this-&gt;mpData = (uint8_t *) malloc(st.st_size);&#xD;&#xA;        mpData = new uint8_t[st.st_size];&#xD;&#xA;        &#xD;&#xA;        if (this-&gt;mpData == NULL)&#xD;&#xA;        {&#xD;&#xA;            return 2;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        if (read(fd, this-&gt;mpData, st.st_size) == -1)&#xD;&#xA;        {&#xD;&#xA;            Clear();&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        close(fd);&#xD;&#xA;            &#xD;&#xA;        PopulateFields(st.st_size);&#xD;&#xA;        &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;pgm.hpp&#xD;&#xA;&#xD;&#xA;    #ifndef __PGM_H__&#xD;&#xA;    #define __PGM_H__&#xD;&#xA;    &#xD;&#xA;    #include &lt;stdint.h&gt;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA;    #include &lt;string.h&gt;&#xD;&#xA;    #include &lt;sys/types.h&gt;&#xD;&#xA;    #include &lt;sys/stat.h&gt;&#xD;&#xA;    #include &lt;fcntl.h&gt;&#xD;&#xA;    #include &lt;unistd.h&gt;&#xD;&#xA;    #include &lt;errno.h&gt;&#xD;&#xA;    #include &lt;inttypes.h&gt;&#xD;&#xA;    &#xD;&#xA;    class PGM&#xD;&#xA;    {&#xD;&#xA;      public:&#xD;&#xA;        int         ReadFile(const char *pPath);&#xD;&#xA;        uint8_t*    GetData();&#xD;&#xA;        uint16_t    GetWidth();&#xD;&#xA;        uint16_t    GetHeight();&#xD;&#xA;        uint8_t     GetMaxWhite();&#xD;&#xA;        &#xD;&#xA;        PGM();&#xD;&#xA;        ~PGM();&#xD;&#xA;    &#xD;&#xA;      private:&#xD;&#xA;        &#xD;&#xA;        void        Clear();&#xD;&#xA;        int         PopulateFields(size_t size);&#xD;&#xA;            &#xD;&#xA;        uint8_t     *mpData;&#xD;&#xA;        uint8_t     *mpImgData;&#xD;&#xA;        uint16_t    mWidth;&#xD;&#xA;        uint16_t    mHeight;&#xD;&#xA;        uint8_t     mMaxWhite;&#xD;&#xA;        &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    #endif // __PGM_H__&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9092" PostHistoryTypeId="1" PostId="4147" RevisionGUID="f10cde37-d6ed-4dcf-a427-928d7322e6f8" CreationDate="2016-10-18T00:21:11.790" UserId="5316" Text="Can I reuse glBindBufferBase in compute shaders to keep data on GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9093" PostHistoryTypeId="3" PostId="4147" RevisionGUID="f10cde37-d6ed-4dcf-a427-928d7322e6f8" CreationDate="2016-10-18T00:21:11.790" UserId="5316" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9094" PostHistoryTypeId="5" PostId="1806" RevisionGUID="101e3584-22e3-45d7-90b9-8653372861c3" CreationDate="2016-10-18T13:38:34.603" UserId="5314" Comment="added vulkan" Text="I think it is commonly accepted that real time is everything that is above interactive. And interactive is defined as &quot;responds to input but is not smooth in the fact that the animation seems jaggy&quot;.  &#xD;&#xA;So real time will depend on the speed of the movements one needs to represent. Cinema projects at 24 FPS and is sufficiently real time for many cases.&#xD;&#xA;&#xD;&#xA;Then how many polygons a machine can deal with is easily verifiable by checking for yourself. Just create a little VBO patch as a simple test and a FPS counter, many DirectX or OpenGL samples will give you the perfect test bed for this benchmark.&#xD;&#xA;&#xD;&#xA;You'll find if you have a high end graphics card that you can display about 1 million polygons in real time. However, as you said, engines will not claim support so easily because real world scene data will cause a number of performance hogs that are unrelated to polygon count.&#xD;&#xA;&#xD;&#xA;You have:&#xD;&#xA;&#xD;&#xA;- fill rate&#xD;&#xA; - texture sampling&#xD;&#xA; - ROP output&#xD;&#xA;- draw calls&#xD;&#xA;- render target switches&#xD;&#xA;- buffer updates (uniform or other)&#xD;&#xA;- overdraw&#xD;&#xA;- shader complexity&#xD;&#xA;- pipeline complexity (any feedback used? iterative geometry shading? occlusion?)&#xD;&#xA;- synch points with CPU (pixel readback?)&#xD;&#xA;- polygon richness&#xD;&#xA;&#xD;&#xA;Depending on the weak and strong points of a particular graphic card, one or another of these points is going to be the bottleneck. It's not like you can say for sure &quot;there, that's the one&quot;.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I wanted to add that, one cannot use the GFlops spec figure of one specific card and map it linearly to polygon pushing capacity. Because of the fact that polygon treatment has to go through a sequential bottleneck in the graphics pipeline as explained in great detail here:  [https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/][1]  &#xD;&#xA;TLDR: the vertices have to fit into a small cache before primitive assembly which is natively a sequential thing (the vertex buffer order matters).  &#xD;&#xA;&#xD;&#xA;If you compare the GeForce 7800 (9yr old?) to this year's 980, it seems the number of operations per second it is capable of has increased one thousand fold. But you can bet that it's not going to push polygons a thousand times faster (which would be around 200 billion a second by this simple metric).&#xD;&#xA;&#xD;&#xA;EDIT2:&#xD;&#xA;&#xD;&#xA;To answer the question &quot;what can one do to optimize an engine&quot;, as in &quot;not to lose too much efficiency in state switches and other overheads&quot;.  &#xD;&#xA;That is a question as old as engines themselves. And is becoming more complex as history progress.  &#xD;&#xA;&#xD;&#xA;Indeed in real world situation, typical scene data will contain many materials, many textures, many different shaders, many render targets and passes, and many vertex buffers and so on. One engine I worked with worked with the notion of packets:&#xD;&#xA;&#xD;&#xA;One packet is what can be rendered with one draw call.  &#xD;&#xA;It contains identifiers to:&#xD;&#xA;&#xD;&#xA;- vertex buffer&#xD;&#xA;- index buffer&#xD;&#xA;- camera (gives the pass and render target)&#xD;&#xA;- material id (gives shader, textures and UBO)&#xD;&#xA;- distance to eye&#xD;&#xA;- is visible&#xD;&#xA;&#xD;&#xA;So the first step of each frame is to run a quick sort on the packet list using a sort function with an operator that gives priority to visibility, then pass, then material, then geometry and finally distance.&#xD;&#xA;&#xD;&#xA;Drawing close objects gets prirority to maximize early Z culling.  &#xD;&#xA;Passes are fixed steps, so we have no choice but to respect them.  &#xD;&#xA;Material is the most expensive thing to state-switch after render targets.  &#xD;&#xA;&#xD;&#xA;Even in-between different materials IDs, a sub-ordering can been made using a heuristical criterion to diminish the number of shader changes (most expensive within material state-switch operations), and secondly texture binding changes.  &#xD;&#xA;&#xD;&#xA;After all this ordering, one can apply mega texturing, virtual texturing, and attribute-less rendering ([link][2]) if deemed necessary.  &#xD;&#xA;&#xD;&#xA;About engine API also one common thing is to defer the issuing of the state-setting commands required by the client. If a client requests &quot;set camera 0&quot;, it is best to just store this request and if later the client calls &quot;set camera 1&quot; but with no other commands in between, the engine can detect the uselessness of the first command and drop it. This is redundancy elimination, which is possible by using a &quot;fully retained&quot; paradigm. By opposition to &quot;immediate&quot; paradigm, which would be just a wrapper above the native API and issue the commands right as ordered by client code. ([example: virtrev][3])&#xD;&#xA;&#xD;&#xA;And finally, with modern hardware, a very expensive (to develop), but potentially highly rewarding step to take is to switch API to metal/mantle/vulkan/DX12-style and preparing the rendering commands by hand.  &#xD;&#xA;&#xD;&#xA;An engine that prepares rendering commands creates a buffer that holds a &quot;command list&quot; that is overwritten at each frame.&#xD;&#xA;&#xD;&#xA;Usually there is a notion of frame &quot;budget&quot;, a game can afford. You need to do everything in 16 milliseconds, so you clearly partition GPU time &quot;2 ms for lightpre pass&quot;, &quot;4 ms for materials pass&quot;, &quot;6 ms for indirect lighting&quot;, &quot;4 ms for postprocesses&quot;...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/&#xD;&#xA;  [2]: http://renderingpipeline.com/2012/03/are-vertex-shaders-obsolete/&#xD;&#xA;  [3]: http://virtrev.git.sourceforge.net/git/gitweb.cgi?p=virtrev/virtrev;a=tree;f=coding/opencl_opengl_sharing/src;hb=HEAD" ContentLicense="CC BY-SA 3.0" />
  <row Id="9095" PostHistoryTypeId="24" PostId="1806" RevisionGUID="101e3584-22e3-45d7-90b9-8653372861c3" CreationDate="2016-10-18T13:38:34.603" Comment="Proposed by 5314 approved by 1614 edit id of 168" ContentLicense="CC BY-SA 3.0" />
  <row Id="9096" PostHistoryTypeId="2" PostId="4148" RevisionGUID="e6f96c89-4042-4954-957e-03e51c66a1f9" CreationDate="2016-10-19T04:27:20.920" UserId="5316" Text="I found it! The issue stems from a problem in the swap. When we swap buffers, the output buffer becomes the input and the input buffer becomes the output. However, the buffer that is now the output was not updated to match!&#xD;&#xA;&#xD;&#xA;    To illustrate:&#xD;&#xA;    &#xD;&#xA;    Init:&#xD;&#xA;     In      Out&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    &#xD;&#xA;    First Iteration (remove north corners):&#xD;&#xA;     In      Out&#xD;&#xA;    1 1 1   0 1 0&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    &#xD;&#xA;    Swap &#xD;&#xA;     In      Out&#xD;&#xA;    0 1 0   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    &#xD;&#xA;    Second iteration (remove east corners):&#xD;&#xA;     In      Out&#xD;&#xA;    0 1 0   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 0   1 1 0&#xD;&#xA;&#xD;&#xA;    ... (and so on)&#xD;&#xA;&#xD;&#xA;By modifying skeleton() in the compute shader to copy image_0 to image_1, prior to anything else, the algorithm works correctly. &#xD;&#xA;&#xD;&#xA;    void skeleton() {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;        uint neighborhood[9];&#xD;&#xA;        neighborhood[0] = getVal(getPos(x, y));&#xD;&#xA;       &#xD;&#xA;        image_1[getPos(x, y)] = image_0[getPos(x, y)];&#xD;&#xA;        &#xD;&#xA;        // Only consider cases where the center is 1&#xD;&#xA;        if (neighborhood[0] != 1) {&#xD;&#xA;            image_1[0] = 0;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        ...&#xD;&#xA;&#xD;&#xA;Additionally, I cleaned up the code quite a bit. For example, you can set the in and out buffers via glBindBufferBase() prior to the dispatch call." ContentLicense="CC BY-SA 3.0" />
  <row Id="9097" PostHistoryTypeId="5" PostId="4148" RevisionGUID="fe6237f5-a1ae-439d-8295-3d2258dffb93" CreationDate="2016-10-19T04:37:00.823" UserId="5316" Comment="edited body" Text="I found it! The issue stems from a problem in the swap. When we swap buffers, the output buffer becomes the input and the input buffer becomes the output. However, the buffer that is now the output was not updated to match!&#xD;&#xA;&#xD;&#xA;    To illustrate:&#xD;&#xA;    &#xD;&#xA;    Init:&#xD;&#xA;     In      Out&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    &#xD;&#xA;    First Iteration (remove north corners):&#xD;&#xA;     In      Out&#xD;&#xA;    1 1 1   0 1 0&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    &#xD;&#xA;    Swap &#xD;&#xA;     In      Out&#xD;&#xA;    0 1 0   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    &#xD;&#xA;    Second iteration (remove east corners):&#xD;&#xA;     In      Out&#xD;&#xA;    0 1 0   1 1 1&#xD;&#xA;    1 1 1   1 1 1&#xD;&#xA;    1 1 1   1 1 0&#xD;&#xA;&#xD;&#xA;    ... (and so on)&#xD;&#xA;&#xD;&#xA;By modifying skeleton() in the compute shader to copy image_0 to image_1, prior to anything else, the algorithm works correctly. &#xD;&#xA;&#xD;&#xA;    void skeleton() {&#xD;&#xA;        int x = int(gl_GlobalInvocationID.x);&#xD;&#xA;        int y = int(gl_GlobalInvocationID.y);&#xD;&#xA;        uint neighborhood[9];&#xD;&#xA;        neighborhood[0] = getVal(getPos(x, y));&#xD;&#xA;       &#xD;&#xA;        image_1[getPos(x, y)] = image_0[getPos(x, y)];&#xD;&#xA;        &#xD;&#xA;        // Only consider cases where the center is 1&#xD;&#xA;        if (neighborhood[0] != 1) {&#xD;&#xA;            image_1[0] = 0;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;        ...&#xD;&#xA;&#xD;&#xA;Additionally, I cleaned up the code quite a bit. For example, you can set the in and out buffers via glBindBufferBase() prior to the dispatch call." ContentLicense="CC BY-SA 3.0" />
  <row Id="9104" PostHistoryTypeId="2" PostId="4150" RevisionGUID="1ad81c73-07ef-4cd2-9d51-d0095835eea0" CreationDate="2016-10-19T13:36:21.613" UserId="5105" Text="Given a point light source, a eye position, we can find the silhouette (outline) of the given model. We can first find the silhouette edge, project the model into a 2-D plane,  then traverse all silhouette edges. But when it comes to concave model, some part of the silhouette edges should not be included in the model outline. How to find those parts? Also, can we do this without projecting the model into a 2-D plane? " ContentLicense="CC BY-SA 3.0" />
  <row Id="9105" PostHistoryTypeId="1" PostId="4150" RevisionGUID="1ad81c73-07ef-4cd2-9d51-d0095835eea0" CreationDate="2016-10-19T13:36:21.613" UserId="5105" Text="How to find silhouette for concaver" ContentLicense="CC BY-SA 3.0" />
  <row Id="9106" PostHistoryTypeId="3" PostId="4150" RevisionGUID="1ad81c73-07ef-4cd2-9d51-d0095835eea0" CreationDate="2016-10-19T13:36:21.613" UserId="5105" Text="|silhouette|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9107" PostHistoryTypeId="2" PostId="4151" RevisionGUID="b1320b88-8f88-40e5-93a2-8be44f3411ee" CreationDate="2016-10-20T05:09:59.867" UserId="5328" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;&#xD;&#xA;        // In case of downward error in log2:&#xD;&#xA;        exponent += float(exp2(exponent + 1.0) &lt;= mag);&#xD;&#xA;&#xD;&#xA;        float mantissa = mag / exp2(exponent) - 1.0;&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On my intel laptop, this works perfectly. I can't find any non-denormalized non-NaN non-Infinity 32-bit float that won't round trip. But, on my Nexus tablet, that's not the case. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]` but when I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`).&#xD;&#xA;&#xD;&#xA;I've found various strange effects, like replacing a multiplication by `exp2(-v)` with a division by `exp2(v)` will move the errors around. But mostly I'm at a loss trying to figure out where the precision is being destroyed.&#xD;&#xA;&#xD;&#xA;Is there any *exact* way to pack floats into bytes, without losing precision?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9108" PostHistoryTypeId="1" PostId="4151" RevisionGUID="b1320b88-8f88-40e5-93a2-8be44f3411ee" CreationDate="2016-10-20T05:09:59.867" UserId="5328" Text="WebGL packing/unpacking functions that can roundtrip all typical 32-bit floats" ContentLicense="CC BY-SA 3.0" />
  <row Id="9109" PostHistoryTypeId="3" PostId="4151" RevisionGUID="b1320b88-8f88-40e5-93a2-8be44f3411ee" CreationDate="2016-10-20T05:09:59.867" UserId="5328" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9110" PostHistoryTypeId="5" PostId="4151" RevisionGUID="fcf8f214-0fee-435f-86a5-fae75369cf76" CreationDate="2016-10-20T06:11:20.337" UserId="5328" Comment="added 24 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;&#xD;&#xA;        // In case of downward error in log2:&#xD;&#xA;        exponent += float(exp2(exponent + 1.0) &lt;= mag);&#xD;&#xA;&#xD;&#xA;        float mantissa = mag / exp2(exponent) - 1.0;&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On my intel laptop, this works decently. There's some really big floats that don't work, but that's not an issue for my usage. But, on my Nexus tablet, there's precision loss in the domain I care about. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]` but when I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`).&#xD;&#xA;&#xD;&#xA;I've found various strange effects, like replacing a multiplication by `exp2(-v)` with a division by `exp2(v)` will move the errors around. But mostly I'm at a loss trying to figure out where the precision is being destroyed.&#xD;&#xA;&#xD;&#xA;Is there any *exact* way to pack floats into bytes, without losing precision?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9111" PostHistoryTypeId="5" PostId="4151" RevisionGUID="773d87a4-08ea-47b8-8ab9-9eb4b852ea64" CreationDate="2016-10-20T06:32:58.047" UserId="5328" Comment="added 478 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;&#xD;&#xA;        // In case of downward error in log2:&#xD;&#xA;        exponent += float(exp2(exponent + 1.0) &lt;= mag);&#xD;&#xA;&#xD;&#xA;        float mantissa = mag / exp2(exponent) - 1.0;&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On my intel laptop, this works decently. There's some really big floats that don't work, but that's not an issue for my usage. But, on my Nexus tablet, there's precision loss in the domain I care about. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]` but when I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`).&#xD;&#xA;&#xD;&#xA;I've found various strange effects, like replacing a multiplication by `exp2(-v)` with a division by `exp2(v)` will move the errors around. But mostly I'm at a loss trying to figure out where the precision is being destroyed.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9112" PostHistoryTypeId="5" PostId="4151" RevisionGUID="c971c77d-0f25-4ff9-9f48-fa0662f4be6b" CreationDate="2016-10-20T06:45:34.480" UserId="5328" Comment="added 676 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;&#xD;&#xA;        // In case of downward error in log2:&#xD;&#xA;        exponent += float(exp2(exponent + 1.0) &lt;= mag);&#xD;&#xA;&#xD;&#xA;        float mantissa = mag / exp2(exponent) - 1.0;&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This method is close. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]`. When I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`). Close, but I want perfect.&#xD;&#xA;&#xD;&#xA;Mostly I'm at a loss trying to figure out where the precision is being destroyed in this method. Changes almost seem to have random effects, like replacing `x * exp2(n)` with `x / exp2(-n)` might fix an error in one place but introduce an error in another place.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;&#xD;&#xA;And here's what round-tripping through the above pack/unpack methods on an Intel HD 5500 does:&#xD;&#xA;&#xD;&#xA;	Error: Got &lt;&#xD;&#xA;		Float32Array[0, 0.5, 1, 2, -1, 1.100000023841858, 42, 16842750, 16777216, 16777218, 0.9999999403953552, 1.0000001192092896, 1.1754943508222875e-38, Infinity, 3.1415927410125732, 2.7182817459106445]&#xD;&#xA;	&gt; but expected it to equal &lt;&#xD;&#xA;		Float32Array[0, 0.5, 1, 2, -1, 1.100000023841858, 42, 16777215, 16777216, 16777218, 0.9999999403953552, 1.0000001192092896, 1.1754943508222875e-38, 3.4028234663852886e+38, 3.1415927410125732, 2.7182817459106445]&#xD;&#xA;	&gt;. (assertThat #1)&#xD;&#xA;&#xD;&#xA;(It turned `3.4028234663852886e+38` into `Infinity` and `16777215` into `16842750` (!!!).)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9113" PostHistoryTypeId="5" PostId="4151" RevisionGUID="963ff4e2-53ef-45e4-9b3b-23ed728e9f27" CreationDate="2016-10-20T07:58:49.763" UserId="5328" Comment="added 43 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;&#xD;&#xA;        // Fix rounding error in log2's output.&#xD;&#xA;        exponent += float(exp2(exponent + 1.0) &lt;= mag);&#xD;&#xA;        exponent -= float(exp2(exponent) &gt; mag);&#xD;&#xA;&#xD;&#xA;        float mantissa = mag / exp2(exponent) - 1.0;&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This method is close. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]`. When I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`). Close, but I want perfect.&#xD;&#xA;&#xD;&#xA;Mostly I'm at a loss trying to figure out where the precision is being destroyed in this method. Changes almost seem to have random effects, like replacing `x * exp2(n)` with `x / exp2(-n)` might fix an error in one place but introduce an error in another place.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;&#xD;&#xA;And here's what round-tripping through the above pack/unpack methods on an Intel HD 5500 does:&#xD;&#xA;&#xD;&#xA;	Error: Got &lt;&#xD;&#xA;		Float32Array[0, 0.5, 1, 2, -1, 1.100000023841858, 42, 16777215, 16777216, 16777218, 0.9999999403953552, 1.0000001192092896, 1.1754943508222875e-38, 1.7014118346046923e+38, 3.1415927410125732, 2.7182817459106445]&#xD;&#xA;	&gt; but expected it to equal &lt;&#xD;&#xA;		Float32Array[0, 0.5, 1, 2, -1, 1.100000023841858, 42, 16777215, 16777216, 16777218, 0.9999999403953552, 1.0000001192092896, 1.1754943508222875e-38, 3.4028234663852886e+38, 3.1415927410125732, 2.7182817459106445]&#xD;&#xA;	&gt;. (assertThat #1)&#xD;&#xA;&#xD;&#xA;(It turned `3.4028234663852886e+38` into `1.7014118346046923e+38`.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9114" PostHistoryTypeId="5" PostId="4151" RevisionGUID="77ae3d73-cb9f-466b-89f9-8bda82962689" CreationDate="2016-10-20T08:31:41.137" UserId="5328" Comment="deleted 270 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;        // Correct log2 approximation errors.&#xD;&#xA;        exponent += float(exp2(exponent) &lt;= mag / 2.0);&#xD;&#xA;        exponent -= float(exp2(exponent) &gt; mag);&#xD;&#xA;&#xD;&#xA;        float mantissa;&#xD;&#xA;        if (exponent &gt; 100.0) {&#xD;&#xA;            // Not sure why this needs to be done in two steps for the largest float to work.&#xD;&#xA;            // Best guess is the optimizer rewriting '/ exp2(e)' into '* exp2(-e)',&#xD;&#xA;            // but exp2(-128.0) is too small to represent.&#xD;&#xA;            mantissa = mag / 1024.0 / exp2(exponent - 10.0) - 1.0;&#xD;&#xA;        } else {&#xD;&#xA;            mantissa = mag / float(exp2(exponent)) - 1.0;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This method is close. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]`. When I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`). Close, but I want perfect.&#xD;&#xA;&#xD;&#xA;Mostly I'm at a loss trying to figure out where the precision is being destroyed in this method. Changes almost seem to have random effects, like replacing `x * exp2(n)` with `x / exp2(-n)` might fix an error in one place but introduce an error in another place.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9115" PostHistoryTypeId="2" PostId="4152" RevisionGUID="15f72443-7e1f-403c-bd87-0b26b9a914a1" CreationDate="2016-10-20T13:57:30.407" UserId="1952" Text="I'll explain the &quot;geometric way&quot; of solving the problem since that's the solution you seem to be after, instead of using rasterization that Dan suggested in the comments.&#xD;&#xA;&#xD;&#xA;You can get the list of potential silhouette edges without 2D projection by first iterating through all edges and taking dot product of the normal of the attached two triangles against the eye-&gt;edge vector (any point on the edge will do, e.g. one of the end-points). If the dot products for the two triangles on the edge have different signs, then it's a potential silhouette edge. If the object is convex, then you are done and got the list of silhouette edges.&#xD;&#xA;&#xD;&#xA;For concave objects it gets more complicated. For concave objects it could be that an edge is only partially a silhouette edge and can be potentially split to N fragments that all belong to the silhouette. So you need to process the list of potential edges and clip them with the geometry. The way you can do the clipping is to extrude every triangle in the geometry away from eye and use this volume to clip the list of potential silhouette edges. The remaining edge fragments that are not clipped away are your silhouette." ContentLicense="CC BY-SA 3.0" />
  <row Id="9116" PostHistoryTypeId="5" PostId="4151" RevisionGUID="ede024be-1225-4c0b-b26d-63b708ec0350" CreationDate="2016-10-20T18:08:44.427" UserId="5328" Comment="added 85 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;        // Correct log2 approximation errors.&#xD;&#xA;        exponent += float(exp2(exponent) &lt;= mag / 2.0);&#xD;&#xA;        exponent -= float(exp2(exponent) &gt; mag);&#xD;&#xA;&#xD;&#xA;        float mantissa;&#xD;&#xA;        if (exponent &gt; 100.0) {&#xD;&#xA;            // Not sure why this needs to be done in two steps for the largest float to work.&#xD;&#xA;            // Best guess is the optimizer rewriting '/ exp2(e)' into '* exp2(-e)',&#xD;&#xA;            // but exp2(-128.0) is too small to represent.&#xD;&#xA;            mantissa = mag / 1024.0 / exp2(exponent - 10.0) - 1.0;&#xD;&#xA;        } else {&#xD;&#xA;            mantissa = mag / float(exp2(exponent)) - 1.0;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This method is close. It works on my laptop, as far as I can tell. But it doesn't work on my Nexus tablet. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]`. When I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`). Close, but I want perfect.&#xD;&#xA;&#xD;&#xA;Mostly I'm at a loss trying to figure out where the precision is being destroyed in this method. Changes almost seem to have random effects, like replacing `x * exp2(n)` with `x / exp2(-n)` might fix an error in one place but introduce an error in another place.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9117" PostHistoryTypeId="5" PostId="4151" RevisionGUID="e7111396-b760-4e38-875a-42f79d408675" CreationDate="2016-10-20T18:15:12.000" UserId="5328" Comment="added 85 characters in body" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;I have found various blog posts and answers related to this task out on the internet ([example 1](http://www.ozone3d.net/blogs/lab/20080604/glsl-float-to-rgba8-encoder/), [example 2](http://stackoverflow.com/questions/28159591/how-to-pack4bytes-and-unpackvec4-between-c-and-glsl), [example 3](https://gist.github.com/Flexi23/1713774)), but I haven't found any that work properly on all finite non-denormalized floats.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;        // Correct log2 approximation errors.&#xD;&#xA;        exponent += float(exp2(exponent) &lt;= mag / 2.0);&#xD;&#xA;        exponent -= float(exp2(exponent) &gt; mag);&#xD;&#xA;&#xD;&#xA;        float mantissa;&#xD;&#xA;        if (exponent &gt; 100.0) {&#xD;&#xA;            // Not sure why this needs to be done in two steps for the largest float to work.&#xD;&#xA;            // Best guess is the optimizer rewriting '/ exp2(e)' into '* exp2(-e)',&#xD;&#xA;            // but exp2(-128.0) is too small to represent.&#xD;&#xA;            mantissa = mag / 1024.0 / exp2(exponent - 10.0) - 1.0;&#xD;&#xA;        } else {&#xD;&#xA;            mantissa = mag / float(exp2(exponent)) - 1.0;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This method is close. It works on my laptop, as far as I can tell. But it doesn't work on my Nexus tablet. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]`. When I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`). Close, but I want perfect.&#xD;&#xA;&#xD;&#xA;Mostly I'm at a loss trying to figure out where the precision is being destroyed in this method. Changes almost seem to have random effects, like replacing `x * exp2(n)` with `x / exp2(-n)` might fix an error in one place but introduce an error in another place.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9118" PostHistoryTypeId="2" PostId="4153" RevisionGUID="34364d76-bf02-4d17-a8dd-18bb7df86a99" CreationDate="2016-10-20T19:46:13.413" UserId="1636" Text="In theory I can't use a lambertian shader on a cube, because there aren't surface normals on the edges.&#xD;&#xA;&#xD;&#xA;Is this correct ?&#xD;&#xA;&#xD;&#xA;Why is this always possible in software applications ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9119" PostHistoryTypeId="1" PostId="4153" RevisionGUID="34364d76-bf02-4d17-a8dd-18bb7df86a99" CreationDate="2016-10-20T19:46:13.413" UserId="1636" Text="Lambertian Shading of a cube" ContentLicense="CC BY-SA 3.0" />
  <row Id="9120" PostHistoryTypeId="3" PostId="4153" RevisionGUID="34364d76-bf02-4d17-a8dd-18bb7df86a99" CreationDate="2016-10-20T19:46:13.413" UserId="1636" Text="|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9121" PostHistoryTypeId="2" PostId="4154" RevisionGUID="58caa3f4-81f9-406a-b80c-2cc22f857e8d" CreationDate="2016-10-20T22:31:50.500" UserId="56" Text="Each cube face is made up of a quad, or two triangles.  Let's take 3 points from either the quad, or one of the triangles, and call them $A,B,C$.&#xD;&#xA;&#xD;&#xA;You can get the normal to this surface by normalizing the cross product of $\overline{AB}$ and $\overline{BC}$.  You can then use that surface normal to calculate lighting.&#xD;&#xA;&#xD;&#xA;You can do similar calculations to get the tangent and bitangent to then calculate $u,v$ values for texture mapping.&#xD;&#xA;&#xD;&#xA;I'm not sure why the edges not having normals makes you think you can't calculate lighting for the cube faces, but you totally can.&#xD;&#xA;&#xD;&#xA;You could even use the vertices to calculate a normal for the edges if you wanted, but I'm not sure why you would want to do that :P" ContentLicense="CC BY-SA 3.0" />
  <row Id="9122" PostHistoryTypeId="2" PostId="4155" RevisionGUID="ce8422f5-0f98-4842-a754-2acbd7e2fd24" CreationDate="2016-10-20T22:55:23.177" UserId="5334" Text="I have got a weird bug that I cannot figure out. The apple forums were not too helpful.&#xD;&#xA;I updated my MacBookPro (Retina, early 2015) to the newest OS X sierra. My code ran fine before, now when I call `glfwCreateWindow(mWidth, mHeight, mTitle, nullptr, nullptr);`, I get following error:&#xD;&#xA;&#xD;&#xA;    &gt; ERROR: Setting &lt;private&gt; as the first responder for window&lt;private&gt;,but it is in a different window ((null))! This would&#xD;&#xA;    &gt; eventually crash when the view is freed. The first responder will be&#xD;&#xA;    &gt; set to nil.&#xD;&#xA;&#xD;&#xA;I have got no idea, why my program does not work and yes, I have set the glfw to be forward compatible.&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;Raphael&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;P.S. comupter info:&#xD;&#xA;MacBook Pro (Retina 13 inch, early 2015)&#xD;&#xA;CPU: 2.7 GHz Intel core i5&#xD;&#xA;GPU: Intel Iris Graphics 6100 1536 MB&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9123" PostHistoryTypeId="1" PostId="4155" RevisionGUID="ce8422f5-0f98-4842-a754-2acbd7e2fd24" CreationDate="2016-10-20T22:55:23.177" UserId="5334" Text="Error when calling glfwCreateWindow() on OS X after updating to sierra" ContentLicense="CC BY-SA 3.0" />
  <row Id="9124" PostHistoryTypeId="3" PostId="4155" RevisionGUID="ce8422f5-0f98-4842-a754-2acbd7e2fd24" CreationDate="2016-10-20T22:55:23.177" UserId="5334" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9125" PostHistoryTypeId="5" PostId="4155" RevisionGUID="27b8575b-3869-406c-a76f-7bad57187578" CreationDate="2016-10-21T07:43:34.997" UserId="67" Comment="Formatting, capitalization, fixed typos" Text="I have got a weird bug that I cannot figure out. The Apple forums were not too helpful.&#xD;&#xA;I updated my MacBookPro (Retina, early 2015) to the newest OS X Sierra. My code ran fine before, now when I call `glfwCreateWindow(mWidth, mHeight, mTitle, nullptr, nullptr);`, I get following error:&#xD;&#xA;&#xD;&#xA;    &gt; ERROR: Setting &lt;private&gt; as the first responder for window&lt;private&gt;,but it is in a different window ((null))! This would&#xD;&#xA;    &gt; eventually crash when the view is freed. The first responder will be&#xD;&#xA;    &gt; set to nil.&#xD;&#xA;&#xD;&#xA;I have got no idea, why my program does not work and yes, I have set the glfw to be forward compatible.&#xD;&#xA;&#xD;&#xA;P.S. computer info:&#xD;&#xA;&#xD;&#xA;- MacBook Pro (Retina 13 inch, early 2015)&#xD;&#xA;- CPU: 2.7 GHz Intel core i5&#xD;&#xA;- GPU: Intel Iris Graphics 6100 1536 MB&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9126" PostHistoryTypeId="4" PostId="4155" RevisionGUID="27b8575b-3869-406c-a76f-7bad57187578" CreationDate="2016-10-21T07:43:34.997" UserId="67" Comment="Formatting, capitalization, fixed typos" Text="Error when calling glfwCreateWindow() on OS X after updating to Sierra" ContentLicense="CC BY-SA 3.0" />
  <row Id="9127" PostHistoryTypeId="24" PostId="4155" RevisionGUID="27b8575b-3869-406c-a76f-7bad57187578" CreationDate="2016-10-21T07:43:34.997" Comment="Proposed by 67 approved by 182, 209 edit id of 169" ContentLicense="CC BY-SA 3.0" />
  <row Id="9128" PostHistoryTypeId="2" PostId="4156" RevisionGUID="f165a95d-693f-43da-ae77-23e861920994" CreationDate="2016-10-21T11:27:35.610" UserId="2041" Text="In a polygon mesh, all the faces that meet at a point don't have to share the same vertex. They can each have their own vertex, and those vertices can all have the same position but different normals.&#xD;&#xA;&#xD;&#xA;In meshes with smooth edges (such as on a sphere, where you want to hide the edges), you want all the vertices at the same point to have the same normal. Generally this will be close to the average of the normals of the faces that share the vertex. That way, Lambertian shading computes the same colour for each, and you don't get a discontinuity on the edge.&#xD;&#xA;&#xD;&#xA;In meshes where you want a deliberate sharp edge (such as your cube example), you want the vertices to have their own normals. In the cube case, each face has its own four vertices, and those vertices all have the same normal (the face normal). Each corner of the cube has three (or six, depending on the triangulation) vertices, with three normals perpendicular to each other. This way, Lambertian shading gives each face the same colour (because all the normals for one face point in the same direction), and adjacent faces don't affect each other.&#xD;&#xA;&#xD;&#xA;A mesh with some rounded parts and some sharp edges can have both. Some vertices can be merged (i.e. each triangle meeting at the same point has the same vertex normal) and others can be split (i.e. each triangle meeting at the same point has its own normal for that vertex). One triangle can have some smooth vertices (shared with its neighbours) and some sharp vertices (with the face normal, not an averaged normal). It's best if the vertices on one edge are all the same, otherwise the results look unphysical.&#xD;&#xA;&#xD;&#xA;Generally, the 3D modelling tool you use to create the mesh will give you the choice: you can make the whole mesh smooth or sharp, or you can select some edges and make them individually smooth or sharp." ContentLicense="CC BY-SA 3.0" />
  <row Id="9129" PostHistoryTypeId="2" PostId="4157" RevisionGUID="ae94350c-a23d-4f42-920f-b86657e2cb8f" CreationDate="2016-10-21T14:40:51.237" UserId="5256" Text="So after reading this Unreal Engine 4 Documentation page: https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/LayeredMaterials/ &#xD;&#xA;(Which describes how to use material layering in UE4)&#xD;&#xA;&#xD;&#xA;I wanted to know how material layering is implemented. (Notice how parts of the 'rocket' are scrached and aren't shiny?) Is it done by adding together the 2 final variables that contain the color's for each respective materialafter being processed by a BRDF?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VEjgH.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9130" PostHistoryTypeId="1" PostId="4157" RevisionGUID="ae94350c-a23d-4f42-920f-b86657e2cb8f" CreationDate="2016-10-21T14:40:51.237" UserId="5256" Text="Material Layering" ContentLicense="CC BY-SA 3.0" />
  <row Id="9131" PostHistoryTypeId="3" PostId="4157" RevisionGUID="ae94350c-a23d-4f42-920f-b86657e2cb8f" CreationDate="2016-10-21T14:40:51.237" UserId="5256" Text="|opengl|c++|physically-based|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9132" PostHistoryTypeId="2" PostId="4158" RevisionGUID="5c55efdd-5d72-4f6a-a6dd-661d02ea2594" CreationDate="2016-10-21T15:48:17.663" UserId="5256" Text="Recently I wanted to improve the lighting in my game engine, naturally I looked towards Ambient Occlusion. I was considering SSAO but are there any better techniques? Maybe some that are Physically Based? Are there any other techniques that replace SSAO or HBAO+ entirely? &#xD;&#xA;&#xD;&#xA;I am aware of [VXAO][1] but is that basically it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/vxao-voxel-ambient-occlusion&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9133" PostHistoryTypeId="1" PostId="4158" RevisionGUID="5c55efdd-5d72-4f6a-a6dd-661d02ea2594" CreationDate="2016-10-21T15:48:17.663" UserId="5256" Text="Alternatives to Ambient Occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="9134" PostHistoryTypeId="3" PostId="4158" RevisionGUID="5c55efdd-5d72-4f6a-a6dd-661d02ea2594" CreationDate="2016-10-21T15:48:17.663" UserId="5256" Text="|opengl|lighting|physically-based|ambient-occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9135" PostHistoryTypeId="5" PostId="4157" RevisionGUID="9ec7f54b-a74d-4842-88ea-5a2a67f0d955" CreationDate="2016-10-21T20:04:05.633" UserId="5256" Comment="added 1 character in body" Text="So after reading this Unreal Engine 4 Documentation page: https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/LayeredMaterials/ &#xD;&#xA;(Which describes how to use material layering in UE4)&#xD;&#xA;&#xD;&#xA;I wanted to know how material layering is implemented. (Notice how the 'unreal engine' part of the rocket has different material and aswell as the scratches on the rocket?) Is it done by adding together the 2 final variables that contain the color's for each respective material after being processed by a BRDF?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VEjgH.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9136" PostHistoryTypeId="2" PostId="4159" RevisionGUID="8099207c-380b-4578-9af1-3b26b0c16892" CreationDate="2016-10-21T23:26:09.900" UserId="3470" Text="Ambient occlusion cannot be physically based no matter what algorithm you use to calculate it. It's a simplification of global illumination that assumes all occluders only block light and are themselves completely black, which isn't true and generally makes corners darker than they should be.&#xD;&#xA;&#xD;&#xA;Ideally, you would be using some kind of global illumination method, but they generally don't have enough resolution to capture the effect ambient occlusion simulates and screen space global illumination tends to be too expensive.&#xD;&#xA;&#xD;&#xA;That means ambient occlusion is still a reasonable choice, even if it's not entirely physically correct. Screen space ambient occlusion methods are the fastest, but suffer from the limited information they have access to, which can lead to artifacts like halos around objects in the foreground and the edges of the screen. Having more information about the scene to calculate the AO from, like VXAO does, eliminates those artifacts, but it again comes at a performance cost.&#xD;&#xA;&#xD;&#xA;In the end, it depends on your perf budget. The more time you can spend calculating global illumination and ambient occlusion, the better the results are going to look. [This seems to be a solid resource][1] about screen space ambient occlusion algorithms in particular. I've personally had good results with Alchemy AO accelerated for large radii with a depth mip-chain similar to the [Scalable Ambient Obscurance paper][2].&#xD;&#xA;&#xD;&#xA;For an alternative to traditional AO, there's [Bent Normals and Cones in Screen-Space][3] that I've heard a lot about. As far as I understand it, the key difference is that instead of just calculating *how much* a point in space is occluded, it also captures information about what directions in particular are occluded. This information is then later used for lighting, where only light coming from the unoccluded directions is considered. It's still not what you'd call physically based, but in my opinion it comes closer than the usual ambient occlusion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://frederikaalund.com/a-comparative-study-of-screen-space-ambient-occlusion-methods/&#xD;&#xA;  [2]: https://research.nvidia.com/sites/default/files/publications/McGuire12SAO.pdf&#xD;&#xA;  [3]: https://people.mpi-inf.mpg.de/~ritschel/Papers/ScreenSpaceBentCones.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9137" PostHistoryTypeId="2" PostId="4160" RevisionGUID="ec8bf7ed-bd0e-4f4e-88ff-9bf283fa2c6c" CreationDate="2016-10-22T03:52:07.037" UserId="1952" Text="For light sources with larger solid angle and where the shadow caster is relatively closer to the light than the receiver, you get notable soft shadowing effect. So if you render larger light sources closer to the shadow receiver it's important to handle soft shadows properly for realistic lighting. Even with the Sun which has quite small solid angle, you can still see fairly large penumbras from tall buildings.&#xD;&#xA;&#xD;&#xA;PCSS is fairly simple algorithm for implementing contact hardening shadows, but it has some notable issues. PCSS fails when you have soft and hard shadows intersecting (blocker search fails), so it's not a good algorithm to use when large penumbras are needed. See in the below image where shadows from the box &amp; triangle intersect. This artifact is particularly disturbing when animated.&#xD;&#xA;&#xD;&#xA;[![PCSS artifact][1]][1]&#xD;&#xA;&#xD;&#xA;There's a family of [&quot;back-projection&quot; shadow techniques][2] though, which is able to handle larger penumbras. However, there's a little research done how to implement this efficiently for real-time applications that I'm aware of.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In back-projection the principle idea is to project shadow map texels to the light source for every pixel to calculate light occlusion, which when implemented naively is obviously extremely slow and furthermore introduces shadow gaps &amp; overlaps. However, there are some techniques to try to avoid the artifacts, such as adjusting the microquad extents as shown below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Another improvement to handle the gaps and overlaps is to use [bitmask soft shadowing][5] algorithm, where occlusion bitmask determines the occluded areas of the light source.&#xD;&#xA;&#xD;&#xA;The most recent paper I have seen on the topic is &quot;[Real Time Area Lighting. Now and Next][6]&quot; by Sam Martin from 2012, where the cost was several milliseconds for a single light, but it's definitely worth the read if you are interested of the topic, to get general idea about the state-of-the-art real-time shadow techniques.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VQ4ln.png&#xD;&#xA;  [2]: http://www.labri.fr/perso/guenneba/docs/SoftShadowMapping-egsr06.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/bMrtV.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZVfaN.png&#xD;&#xA;  [5]: http://research.michael-schwarz.com/publ/files/bmss-eg07.pdf&#xD;&#xA;  [6]: http://www.geomerics.com/wp-content/uploads/2014/03/AltDevConf-SamMartin-RealTimeAreaLighting.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9138" PostHistoryTypeId="2" PostId="4161" RevisionGUID="b4e111aa-6a9b-4568-b7ba-de6713fe94c1" CreationDate="2016-10-22T04:24:38.820" UserId="1952" Text="It would be too expensive (both performance and memory wise) to evaluate BRDF first for each material layer and then blend the layers. Thus the material layer parameters &amp; textures are rather first blended together and then written to the G-buffer for a single BRDF evaluation. This is feasible as long as all the layers use the same BRDF. This doesn't generate identical results to evaluating BRDF before blending, but the results are quite often acceptable.&#xD;&#xA;&#xD;&#xA;The BRDF parameter blending can be done as an offline process that generates unique textures based on blending maps. This is efficient at run-time but of course consumes more memory since for every blend map you need to generate all the source textures. You can also blend the materials at run-time with the expense of performance, but with smaller memory budget in general.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9146" PostHistoryTypeId="2" PostId="4164" RevisionGUID="0b8cf598-3333-4ce8-aea2-2a64cc393572" CreationDate="2016-10-23T08:15:51.637" UserId="5256" Text="What are **Spherical Harmonics** &amp; **Light Probes**? How useful are they in computer graphics? What exactly do they do? I've heard the word spherical harmonics &amp; Light Probes everywhere, from siggraph presentations to blog posts.&#xD;&#xA;&#xD;&#xA;Recently Matt Pettineo posted a [6 part blog series][1] on them but I still don't understand what they are.&#xD;&#xA;&#xD;&#xA;Is it another way to improve ambient lighting? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://mynameismjp.wordpress.com/2016/10/09/sg-series-part-1-a-brief-and-incomplete-history-of-baked-lighting-representations/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9147" PostHistoryTypeId="1" PostId="4164" RevisionGUID="0b8cf598-3333-4ce8-aea2-2a64cc393572" CreationDate="2016-10-23T08:15:51.637" UserId="5256" Text="What are Spherical Harmonics &amp; Light Probes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9148" PostHistoryTypeId="3" PostId="4164" RevisionGUID="0b8cf598-3333-4ce8-aea2-2a64cc393572" CreationDate="2016-10-23T08:15:51.637" UserId="5256" Text="|opengl|lighting|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9153" PostHistoryTypeId="2" PostId="4165" RevisionGUID="9b80f847-6e80-4db4-8da8-155bb1e9a4f3" CreationDate="2016-10-23T14:53:12.117" UserId="56" Text="**Spherical harmonics**&#xA;&#xA;Let's say you have some data in an array but you want to represent that data with a fewer number of bytes.&#xA;&#xA;One way to do that could be to express the data as a function instead of the raw values.&#xA;&#xA;You could represent it as a linear function:&#xA;y=ax+b&#xA;&#xA;Then instead of storing your array of values you could store just a and b.&#xA;&#xA;Problem is, a linear equation probably doesnt fit your data that well.&#xA;&#xA;You could try a quadratic instead:&#xA;y=ax^2+bx+c&#xA;&#xA;Now instead of storing a and b, you store a,b and c.&#xA;&#xA;We've increased the memory storage and also the computational complexity of storing and retrieving your data, compared to the linear equation, but it is a better fit for your array of data.  We could also take it up to a cubic function or higher.  Increasing the order increases the storage, computation and accuracy.&#xA;&#xA;Spherical harmonics is a way of making a function that is defined on a sphere instead of an f(x) like I was talking about above.&#xA;&#xA;Just like in the examples above, you can use a lower order spherical harmonics function to make something with lower storage, and lower computation to calculate data, but also lower accuracy.&#xA;&#xA;On the other hand, you can increase the order and get higher accuracy, but at the cost of more storage space required, and more computation needed to calculate a point of data.&#xA;&#xA;Because of this, in practice, spherical harmonics functions are not good at representing fine details - like a sharp reflection on a sphere - but they can be good for data that doesn't have fine details (data that doesn't have much high frequency content).&#xA;&#xA;One such data they are good at storing is &quot;irradiance&quot; which is the amount of light hitting a point from other directions. It tends to look a bit blurry, which means it has only low frequency content, and is a good candidate for being stored in a spherical harmonics function.&#xA;&#xA;I'll leave the light probes explanation to another person :p&#xA;&#xA;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9154" PostHistoryTypeId="2" PostId="4166" RevisionGUID="e81e7b94-8518-4694-921f-f8e84729fd81" CreationDate="2016-10-23T16:06:48.397" UserId="2041" Text="# Spherical harmonics&#xD;&#xA;&#xD;&#xA;If you know what a Fourier transform is, you already almost know what spherical harmonics are: they're just a Fourier transform but on a spherical instead of a linear basis. That is, while a Fourier transform is a different way of representing a function $f(x)$, spherical harmonics are the analogous thing for polar functions $f(\theta, \phi)$.&#xD;&#xA;&#xD;&#xA;If you don't know what a Fourier transform is, you kinda need to know before you can understand spherical harmonics. The Fourier transform lets you represent a signal as a series of sine and cosine waves, each with twice the frequency of the last. That is, you can represent the signal as its average, plus a sine wave whose wavelength is the same as the length of the signal, plus a sine wave twice that wavelength, and so on. Because the Fourier transform fixes you to these particular wavelengths, you only need to record the amplitude of each one.&#xD;&#xA;&#xD;&#xA;We commonly use Fourier transforms to represent images, which are just 2D digital signals. It's useful because you can throw away some of the sine waves (or reduce the precision with which you store their amplitude) without significantly changing what the image looks like to human eyes. OTOH, throwing away pixels changes the look of the image a lot.&#xD;&#xA;&#xD;&#xA;In a sampled signal like an image, if you use the same number of sine waves as there were samples (pixels) in the original image, you can reconstruct the image exactly, so once you start throwing away any frequencies, you're making the image take less storage.&#xD;&#xA;&#xD;&#xA;Spherical harmonics are just like Fourier transforms, but instead of sine waves, they use a spherical function, so instead of linear functions (such as images), they can represent functions defined on the sphere (such as environment maps).&#xD;&#xA;&#xD;&#xA;# Light probes&#xD;&#xA;&#xD;&#xA;Just like how a standard image records all the light reaching a certain point through the image plane, a light probe records all the light reaching a certain point from all directions. They first came out of movie effects. If you want to add a computer-generated object to a real-world scene, you need to be able to light the synthetic object with the real-world lighting. To do that, you need to know what light reaches the point in the scene where the synthetic object will be. (N.B. Although I say &quot;lighting&quot;, you're recording an image of *all* the light, so it can be used for reflections as well.)&#xD;&#xA;&#xD;&#xA;Because you can't have a camera with a spherical lens that records all the light reaching a single point from all directions, you record this by taking normal photographs of a spherical mirror, and then reprojecting the images onto a sphere.&#xD;&#xA;&#xD;&#xA;Outside of movie effects, it's more common to use light probes generated from an artificial scene. Imagine you have some expensive algorithm to compute global illumination (GI) in a scene, and you also have some smaller objects moving around in this scene (such as a game level with players in it). You can't run the whole GI algorithm every time any object moves, so you run it once with the static scene, and save light probes taken at various points in the level. Then you can get a good approximation to the GI by lighting the player with whichever light probe they're closest to.&#xD;&#xA;&#xD;&#xA;# Using them together &#xD;&#xA;&#xD;&#xA;Generally you want to filter out sharp edges in your global illumination anyway, so you want a way to represent them that's compact and easily lets you throw away high frequencies. That's what spherical harmonics are really good at! That's why you'll hear these two terms used together a lot.&#xD;&#xA;&#xD;&#xA;You compute light probes with your expensive GI algorithm - typically in the level-design tool, or maybe once per second (instead of once per frame) if you want to include your dynamic objects to. You store those cheaply with spherical harmonics - 16 floats is enough for pretty high quality lighting, but not reflections. Then for each dynamic object you want to light, you pick the nearest light probe (or linearly interpolate several together) and use it as a uniform or constant input to your shader. It's also commonplace to use spherical harmonics to represent ambient occlusion data, and it's very cheap to convolve that with the light probe, though there's some complexity around rotating spherical harmonic functions." ContentLicense="CC BY-SA 3.0" />
  <row Id="9155" PostHistoryTypeId="5" PostId="4165" RevisionGUID="c315e556-7337-40b2-8f17-90dda9690a5e" CreationDate="2016-10-23T16:55:54.930" UserId="2041" Comment="A couple of things were a bit misleading (see discussion in comments)" Text="**Spherical harmonics**&#xD;&#xA;&#xD;&#xA;Let's say you have some data in an array but you want to represent that data with a fewer number of bytes.&#xD;&#xA;&#xD;&#xA;One way to do that could be to express the data as a function instead of the raw values.&#xD;&#xA;&#xD;&#xA;You could represent it as a linear function:&#xD;&#xA;$y=ax+b$&#xD;&#xA;&#xD;&#xA;Then instead of storing your array of values you could store just $a$ and $b$.&#xD;&#xA;&#xD;&#xA;Problem is, a linear equation is probably a poor approximation to your data.&#xD;&#xA;&#xD;&#xA;You could try a quadratic instead:&#xD;&#xA;$y=ax^2+bx+c$&#xD;&#xA;&#xD;&#xA;Now instead of storing a and b, you store $a$, $b$ and $c$.&#xD;&#xA;&#xD;&#xA;We've increased the memory storage and also the computational complexity of storing and retrieving your data, compared to the linear equation, but it is a better approximation to your array of data.  We could also take it up to a cubic function or higher.  Increasing the order increases the storage, computation and accuracy.&#xD;&#xA;&#xD;&#xA;Spherical harmonics is a way of making a function that is defined on a sphere instead of an $f(x)$ like I was talking about above.&#xD;&#xA;&#xD;&#xA;Just like in the examples above, you can use a lower order spherical harmonics function to make something with lower storage, and lower computation to calculate data, but also lower accuracy.&#xD;&#xA;&#xD;&#xA;On the other hand, you can increase the order and get a better approximation to your original data, but at the cost of more storage space required, and more computation needed to calculate a point of data.&#xD;&#xA;&#xD;&#xA;In the extreme, you can use as many spherical harmonic terms as you had samples in your array, and then you can reconstruct your original array exactly, but you spend a lot of computation doing that, and you're using just as much storage space as you started with.&#xD;&#xA;&#xD;&#xA;Because of this, in practice, spherical harmonics functions don't offer much benefit if you need to represent fine details - like a sharp reflection on a sphere - but they can be cheap for data that doesn't have fine details (data that doesn't have much high frequency content). They're also useful for doing frequency-domain calculations like spectral analysis or convolution.&#xD;&#xA;&#xD;&#xA;One such data they are good at storing is &quot;irradiance&quot; which is the amount of light hitting a point from other directions. It tends to look a bit blurry, which means it has only low frequency content, and is a good candidate for being stored in a spherical harmonics function.&#xD;&#xA;&#xD;&#xA;I'll leave the light probes explanation to another person :p&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9156" PostHistoryTypeId="24" PostId="4165" RevisionGUID="c315e556-7337-40b2-8f17-90dda9690a5e" CreationDate="2016-10-23T16:55:54.930" Comment="Proposed by 2041 approved by -1 edit id of 170" ContentLicense="CC BY-SA 3.0" />
  <row Id="9157" PostHistoryTypeId="5" PostId="4165" RevisionGUID="5558634e-e2bd-44be-a23e-a4d7370de5ce" CreationDate="2016-10-23T16:55:54.930" UserId="231" Comment="A couple of things were a bit misleading (see discussion in comments)" Text="**Spherical harmonics**&#xD;&#xA;&#xD;&#xA;Let's say you have some data in an array but you want to represent that data with a fewer number of bytes.&#xD;&#xA;&#xD;&#xA;One way to do that could be to express the data as a function instead of the raw values.&#xD;&#xA;&#xD;&#xA;You could represent it as a linear function:&#xD;&#xA;$y=ax+b$&#xD;&#xA;&#xD;&#xA;Then instead of storing your array of values you could store just $a$ and $b$.&#xD;&#xA;&#xD;&#xA;Problem is, a linear equation is probably a poor approximation to your data.&#xD;&#xA;&#xD;&#xA;You could try a quadratic instead:&#xD;&#xA;$y=ax^2+bx+c$&#xD;&#xA;&#xD;&#xA;Now instead of storing $a$ and $b$, you store $a$, $b$ and $c$.&#xD;&#xA;&#xD;&#xA;We've increased the memory storage and also the computational complexity of storing and retrieving your data, compared to the linear equation, but it is a better approximation to your array of data.  We could also take it up to a cubic function or higher.  Increasing the order increases the storage, computation and accuracy.&#xD;&#xA;&#xD;&#xA;Spherical harmonics is a way of making a function that is defined on a sphere instead of an $f(x)$ like I was talking about above.&#xD;&#xA;&#xD;&#xA;Just like in the examples above, you can use a lower order spherical harmonics function to make something with lower storage, and lower computation to calculate data, but also lower accuracy.&#xD;&#xA;&#xD;&#xA;On the other hand, you can increase the order and get a better approximation to your original data, but at the cost of more storage space required, and more computation needed to calculate a point of data.&#xD;&#xA;&#xD;&#xA;In the extreme, you can use as many spherical harmonic terms as you had samples in your array, and then you can reconstruct your original array exactly, but you spend a lot of computation doing that, and you're using just as much storage space as you started with.&#xD;&#xA;&#xD;&#xA;Because of this, in practice, spherical harmonics functions don't offer much benefit if you need to represent fine details - like a sharp reflection on a sphere - but they can be cheap for data that doesn't have fine details (data that doesn't have much high frequency content). They're also useful for doing frequency-domain calculations like spectral analysis or convolution.&#xD;&#xA;&#xD;&#xA;One such data they are good at storing is &quot;irradiance&quot; which is the amount of light hitting a point from other directions. It tends to look a bit blurry, which means it has only low frequency content, and is a good candidate for being stored in a spherical harmonics function.&#xD;&#xA;&#xD;&#xA;I'll leave the light probes explanation to another person :p&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9158" PostHistoryTypeId="2" PostId="4167" RevisionGUID="69d84391-e95a-495c-9320-30166f9d2705" CreationDate="2016-10-23T17:17:54.173" UserId="5345" Text="[![memory consumption][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dNSdW.png&#xD;&#xA;how to calculate it?( Since it is said that I have grammar error and I cannot submit question , I translate it into image then)&#xD;&#xA;This is not from assignment or competition." ContentLicense="CC BY-SA 3.0" />
  <row Id="9159" PostHistoryTypeId="1" PostId="4167" RevisionGUID="69d84391-e95a-495c-9320-30166f9d2705" CreationDate="2016-10-23T17:17:54.173" UserId="5345" Text="memory consumption for a true color frame buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="9160" PostHistoryTypeId="3" PostId="4167" RevisionGUID="69d84391-e95a-495c-9320-30166f9d2705" CreationDate="2016-10-23T17:17:54.173" UserId="5345" Text="|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9162" PostHistoryTypeId="2" PostId="4168" RevisionGUID="44856088-233a-40e7-9063-70e7263ef5fc" CreationDate="2016-10-24T03:42:10.667" UserId="56" Text="True color is 8 bits per color channel, so 3 bytes per pixel.  1024x768 is 785,408 pixels.  At 3 bytes per pixel that is 2,356,224 bytes.  Since it's double buffered we double that number to 4,712,448 bytes which is about 4.5MB." ContentLicense="CC BY-SA 3.0" />
  <row Id="9166" PostHistoryTypeId="5" PostId="4167" RevisionGUID="ed2ab783-be41-42ce-8d62-8af40b8e40be" CreationDate="2016-10-24T12:17:05.520" UserId="3003" Comment="Changed image into searchable text." Text="What is the memory consumption for a true color frame buffer (with double buffering) on an XGA display? (&quot;XGA&quot; = 1024 x 768 pixels) How can I calculate this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9167" PostHistoryTypeId="24" PostId="4167" RevisionGUID="ed2ab783-be41-42ce-8d62-8af40b8e40be" CreationDate="2016-10-24T12:17:05.520" Comment="Proposed by 3003 approved by 209, 385 edit id of 171" ContentLicense="CC BY-SA 3.0" />
  <row Id="9177" PostHistoryTypeId="2" PostId="4172" RevisionGUID="aa953238-aa75-4a25-8448-d902797a9891" CreationDate="2016-10-25T08:57:13.603" UserId="2041" Text="On a PenTile display, the mapping from pixels in the framebuffer to individual subpixels is not trivial. Each pixel in the framebuffer may only have RG and BG subpixels, in some interesting geometric arrangement.&#xD;&#xA;&#xD;&#xA;I'm trying to do some subpixel antialiasing of content that will be displayed on a PenTile display, so to get best results I'd like to understand how I can set the values of each pixel in the framebuffer to control the subpixels individually. (N.B. I know the subpixel layout of the display I'm targeting.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9178" PostHistoryTypeId="1" PostId="4172" RevisionGUID="aa953238-aa75-4a25-8448-d902797a9891" CreationDate="2016-10-25T08:57:13.603" UserId="2041" Text="How does a PenTile display controller interpret its RGB framebuffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9179" PostHistoryTypeId="3" PostId="4172" RevisionGUID="aa953238-aa75-4a25-8448-d902797a9891" CreationDate="2016-10-25T08:57:13.603" UserId="2041" Text="|subpixel-rendering|pentile|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9181" PostHistoryTypeId="2" PostId="4173" RevisionGUID="9f4a6313-9183-477d-a293-b50537fd600d" CreationDate="2016-10-25T09:20:47.160" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="9182" PostHistoryTypeId="1" PostId="4173" RevisionGUID="9f4a6313-9183-477d-a293-b50537fd600d" CreationDate="2016-10-25T09:20:47.160" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="9183" PostHistoryTypeId="2" PostId="4174" RevisionGUID="39387bc7-8e14-4943-b314-1f6042834613" CreationDate="2016-10-25T09:20:47.160" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="9184" PostHistoryTypeId="1" PostId="4174" RevisionGUID="39387bc7-8e14-4943-b314-1f6042834613" CreationDate="2016-10-25T09:20:47.160" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="9196" PostHistoryTypeId="5" PostId="4174" RevisionGUID="2493b1f2-98a9-4540-b502-ae544713dd02" CreationDate="2016-10-25T17:11:44.810" UserId="2041" Comment="added 69 characters in body" Text="Use for questions specific to Samsung's PenTile RGBG or RGBW displays" ContentLicense="CC BY-SA 3.0" />
  <row Id="9197" PostHistoryTypeId="24" PostId="4174" RevisionGUID="2493b1f2-98a9-4540-b502-ae544713dd02" CreationDate="2016-10-25T17:11:44.810" Comment="Proposed by 2041 approved by 100, 231 edit id of 173" ContentLicense="CC BY-SA 3.0" />
  <row Id="9198" PostHistoryTypeId="5" PostId="4173" RevisionGUID="d731048a-b002-4be9-b25a-952eb757effd" CreationDate="2016-10-25T17:12:14.717" UserId="2041" Comment="added 523 characters in body" Text="PenTile is a Samsung trademark, and refers to the technology of using an RGBG or RGBW subpixel layout in an LCD, LED, or plasma display. This layout allows the display to achieve higher luminance resolution, which works well because the human eye has much higher luminance than chrominance resolution. It also allows higher resolutions to be quoted in marketing material.&#xD;&#xA;&#xD;&#xA;For more information see [PenTile on Wikipedia](https://en.wikipedia.org/wiki/PenTile_matrix_family)&#xD;&#xA;&#xD;&#xA;Related tags:-&#xD;&#xA;&#xD;&#xA;* [tag:subpixel-rendering]" ContentLicense="CC BY-SA 3.0" />
  <row Id="9199" PostHistoryTypeId="24" PostId="4173" RevisionGUID="d731048a-b002-4be9-b25a-952eb757effd" CreationDate="2016-10-25T17:12:14.717" Comment="Proposed by 2041 approved by 231 edit id of 172" ContentLicense="CC BY-SA 3.0" />
  <row Id="9201" PostHistoryTypeId="2" PostId="4177" RevisionGUID="7d54ad65-5cdb-4d62-bc88-db9dd94f668d" CreationDate="2016-10-25T17:40:27.673" UserId="1952" Text="**Basics of Spherical Harmonics**&#xD;&#xA;&#xD;&#xA;Spherical Harmonics is a way to represent a 2D function on a surface of a sphere. Instead of time domain (like cubemap), SH is defined in frequency domain with some interesting properties and operations relevant to lighting that can be performed efficiently. With increasing &quot;order&quot; of SH you can represent higher frequencies (details) of functions as illustrated in the image below ($l$ is the SH order). By scaling and summing the below &quot;basis functions&quot; you can represent any kind of 2D function on the sphere up to the frequency defined by the functions. The basis functions are defined with &quot;[associated Legendre polynomials][1]&quot;, but usually you don't need to derive these yourself but can use existing derivations for [real spherical harmonics][2].&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;One such operation that can be performed efficiently in SH is called &quot;[convolution][4]&quot;, which means integrating the product of two spherical 2D functions over a sphere. This is a common operation in lighting calculations, e.g. one of the function could be your incident lighting and one function the BRDF. When represented as SH, this operation is simply the dot product of two SH coefficient vectors.&#xD;&#xA;&#xD;&#xA;Another interesting operation is the ability to do efficient low-pass filtering. Because SH is represented in frequency domain, this is simply the matter of scaling or zeroing out some of the SH coefficients. Some other operations on the other hand can be difficult to perform in SH compared to time domain, e.g. if you want to rotate function represented as SH, it can get quite expensive for higher order SH. So it really depends on the problem if it's suitable to be performed in SH or not.&#xD;&#xA;&#xD;&#xA;SH is generally used to represent only low-frequency functions (i.e. smoothly changing functions) because higher frequencies requires increasing the amount of storage (SH coefficients) and processing. This is why you don't see SH being used for example to replace specular reflections on shiny surfaces. There are also [Zonal Spherical Harmonics][5], which is can be used to reduce storage &amp; computation for 2D functions that are rotationally symmetric about z-axis, by just storing diagonal elements of the SH coefficient matrix. Also [Hemispherical Harmonics][6] can be used if you need to only deal with hemispherical functions (also common in lighting) with the advantage of being able to represent similar frequencies as SH with less coefficients.&#xD;&#xA;&#xD;&#xA;One operation you also need to perform is &quot;SH projection&quot; to transform time domain data to SH. You can do this operation by performing convolution of time domain data with SH basis functions. An interesting property of SH is that unlike time domain representations SH doesn't suffer from aliasing, so you don't have aliasing artifacts even when projecting to very low-order SH.&#xD;&#xA;&#xD;&#xA;**Light Probes**&#xD;&#xA;&#xD;&#xA;Now that you understand the basic operations and properties of SH, we can think how to apply them to GI. A light probe records how much light is coming from every direction to the point where the probe is located. This is a 2D function on a sphere and can be represented as SH (or 3 SH function for red, green and blue). Depending on the amount of lighting details we want to encode into the probes we can choose the SH order.&#xD;&#xA;&#xD;&#xA;For light probes that are used only for Lambertian diffuse lighting, quite low-order SH is sufficient since the convolution is performed with cosine-lobe, which can be represented with order-2 SH (9 coefficients). The SH coefficients for light probes can be generated simply by rendering a cubemap at the point of the probe and then projecting it to SH.&#xD;&#xA;&#xD;&#xA;When rendering geometry, few nearest light probes are taken and their results are interpolated to get the incident lighting function in a point in space. This can be done for example by interpolating the SH coefficients of nearby probes directly and then performing the convolution with pixel normal oriented cosine lobe in SH domain.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Associated_Legendre_polynomials&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics&#xD;&#xA;  [3]: https://i.stack.imgur.com/QPNGz.png&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Convolution&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Zonal_spherical_harmonics&#xD;&#xA;  [6]: http://www.cs.ucf.edu/~ceh/Publications/Papers/Rendering/EGSR04GautronEtAl.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9202" PostHistoryTypeId="2" PostId="4178" RevisionGUID="c2ae8ac0-b0c6-40cf-96fc-d3d1a73d870e" CreationDate="2016-10-25T18:00:00.047" UserId="5357" Text="How to turn a normal photo like this one : &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;into a photo that I can use in my game development platform (Unity3D). I just wrap a 3d sphere model with the photo and then it can be all around me when I use it in a VR headset.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I know it's impossible for a car photo, but i just need to convert the space photo into the something like the car photo then retouch the stitching.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LhZwE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/G3acL.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9203" PostHistoryTypeId="1" PostId="4178" RevisionGUID="c2ae8ac0-b0c6-40cf-96fc-d3d1a73d870e" CreationDate="2016-10-25T18:00:00.047" UserId="5357" Text="Normal 2D photo to VR-compatible spherical photo" ContentLicense="CC BY-SA 3.0" />
  <row Id="9204" PostHistoryTypeId="3" PostId="4178" RevisionGUID="c2ae8ac0-b0c6-40cf-96fc-d3d1a73d870e" CreationDate="2016-10-25T18:00:00.047" UserId="5357" Text="|3d|transformations|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9205" PostHistoryTypeId="2" PostId="4179" RevisionGUID="9684b52f-8a81-4c2b-b177-f3b779af34d4" CreationDate="2016-10-25T21:13:37.410" UserDisplayName="user4718" Text="I've been introduced to local coordinates in contrast to the global ones which I was used to work on, where we have basically the camera at the origin.&#xD;&#xA;&#xD;&#xA;For example, I've the following picture of a cube:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;According to a slides that I've:&#xD;&#xA;&#xD;&#xA;&gt; the object is rotated about the x-axis by $R$ and then translated by $T$&#xD;&#xA;&#xD;&#xA;&gt; from the object's perspective, the world is first translated by $–T$ and then rotated about the (object's local) x-axis by $–R$&#xD;&#xA;&#xD;&#xA;Not just the sign but also the order of the transformations changes. Why is that? &#xD;&#xA;&#xD;&#xA;_Note: I've some ideas, clearly, but I would like to hear a good answer with a mathematical explanation_.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MXVuX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9206" PostHistoryTypeId="1" PostId="4179" RevisionGUID="9684b52f-8a81-4c2b-b177-f3b779af34d4" CreationDate="2016-10-25T21:13:37.410" UserDisplayName="user4718" Text="Why if we rotate an object by R and then translate it with T, from the object perspective, we're actually applying $-T$ and then $-R$" ContentLicense="CC BY-SA 3.0" />
  <row Id="9207" PostHistoryTypeId="3" PostId="4179" RevisionGUID="9684b52f-8a81-4c2b-b177-f3b779af34d4" CreationDate="2016-10-25T21:13:37.410" UserDisplayName="user4718" Text="|raytracing|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9208" PostHistoryTypeId="2" PostId="4180" RevisionGUID="652f698a-a321-438a-9e48-9f8ebdc83df2" CreationDate="2016-10-26T02:44:43.387" UserId="3003" Text="There are a few ways you can do it. Basically, you need to get your photo into a format that's suitable for using as an environment map. There are a number of such projections available. The most common ones I've run into for 360° video are:&#xD;&#xA;&#xD;&#xA; 1. [Cube maps](https://en.wikipedia.org/wiki/Cube_mapping) - 6 images that show what the camera would see if it were looking forward, backward, left, right, up and down from the same position.&#xD;&#xA; 2. [Equirectangular](https://en.wikipedia.org/wiki/Equirectangular_projection) - the 2nd image you show above is this type of photo. It must be exactly twice as wide as it is tall. The rows and columns of pixels then correspond to the latitude and longitude of the sphere you map it onto.&#xD;&#xA; 3. Dual hemispherical - this is when you take a camera (real or virtual) and make an image with a 180° field of view. There are 2 - one for the front and one for the back.&#xD;&#xA;&#xD;&#xA;Given the image you have, there are a few ways you could create something useful from it. You could crop it or extend it so that it has a 2x1 aspect ratio and use it as-is. You'll get a weird seam where the left and right meet, but if you are handy with photo editing tools, you can probably modify it to look reasonable. Note that this will give you the correct image for an equirect projection, but it may or may not look how you want. That purple band would never be visible all at once. It would wrap around the entire field of view, for example.&#xD;&#xA;&#xD;&#xA;Another option is to make a cube map out of it. You could crop what you have into 3 equal squares for, say, front, left, and right. Then you'd need to generate the other 3 yourself. Generating a star field isn't too difficult either in code or using a photo-editing/compositing tool. Or if you know any artists, perhaps they could help you." ContentLicense="CC BY-SA 3.0" />
  <row Id="9209" PostHistoryTypeId="2" PostId="4181" RevisionGUID="13136701-3ce9-4ee4-aea0-1304ff96ec96" CreationDate="2016-10-26T04:00:02.440" UserId="1952" Text="If you have object$\rightarrow$world space transformation matrix:&#xD;&#xA;$$M=T*R$$&#xD;&#xA;then inverse (i.e. world$\rightarrow$object) of this transformation matrix is:&#xD;&#xA;$$M^{-1}=(T*R)^{-1}=R^{-1}*T^{-1}$$&#xD;&#xA;So the order of multiplication of matrix inverses is reversed per [matrix inversion rules][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://mathworld.wolfram.com/MatrixInverse.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9211" PostHistoryTypeId="2" PostId="4182" RevisionGUID="350046c9-b5cb-4448-92d5-3d8f15993211" CreationDate="2016-10-26T09:30:02.913" UserId="38" Text="The matrix contains a description to move form one space to another. The implied assumption is that there is some parent space which the matrix is defined in. There can be arbitrary chains of these parent child relationships. So you need to know the parent of the matrix.&#xD;&#xA;&#xD;&#xA;The matrix multiplications $M \cdot \vec{v}$ describes the vector $\vec{v}$ in child space $M$ as seen by the parent space. The inverse $M^{-1} \cdot \vec{v}$  does the reverse of this it describes the vector in parent space in terms of child space coordinates. &#xD;&#xA;&#xD;&#xA;So simply if you make a tree out of your parent child relationships when you move towards the root of your tree (World) you use non-inverted matrices, and when you move in the opposite direction (towards a leaf/child node) you take the inverse.&#xD;&#xA;&#xD;&#xA;Why would you need the inverse? Well because you want to move two things independently of each other but still use the results in one space. For example imagine a world with one object and a camera. Its efficient to be able to model the camera separately. But then the vectors need to move form object space  to camera space. So you take the object space move to world (moving towards root non inverted multiplication) and then you move that to camera space (move towards a child of world use inverse) so you get&#xD;&#xA;&#xD;&#xA;$$T_{camera}^{-1} \cdot (T_{object} \cdot \vec{v}) = T_{camera}^{-1} \cdot T_{object} \cdot \vec{v}$$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9212" PostHistoryTypeId="5" PostId="4182" RevisionGUID="9bae8955-a072-45a8-9091-5d9366282ff9" CreationDate="2016-10-26T09:38:04.843" UserId="38" Comment="added 220 characters in body" Text="The matrix contains a description to move form one space to another. The implied assumption is that there is some parent space which the matrix is defined in. There can be arbitrary chains of these parent child relationships. So you need to know the parent of the matrix.&#xD;&#xA;&#xD;&#xA;The matrix multiplications $M \cdot \vec{v}$ describes the vector $\vec{v}$ in child space $M$ as seen by the parent space. The inverse $M^{-1} \cdot \vec{v}$  does the reverse of this it describes the vector in parent space in terms of child space coordinates. &#xD;&#xA;&#xD;&#xA;So simply if you make a tree out of your parent child relationships when you move towards the root of your tree (World) you use non-inverted matrices, and when you move in the opposite direction (towards a leaf/child node) you take the inverse.&#xD;&#xA;&#xD;&#xA;Why would you need the inverse? Well because you want to move two things independently of each other but still use the results in one space. For example imagine a world with one object and a camera. Its efficient to be able to model the camera separately. But then the vectors need to move form object space  to camera space. So you take the object space move to world (moving towards root non inverted multiplication) and then you move that to camera space (move towards a child of world use inverse) so you get:&#xD;&#xA;&#xD;&#xA;$$T_{camera}^{-1} \cdot (T_{object} \cdot \vec{v}) = T_{camera}^{-1} \cdot T_{object} \cdot \vec{v}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;(Please note that matrix multiplication order depends on whether you define vector as row or column matrices. Both are fine mathematically as is storing the sub vectors in arbitrary order inside the matrix)&lt;/sub&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9213" PostHistoryTypeId="5" PostId="4177" RevisionGUID="5c77072e-9c3c-4a09-b4ec-d09eb734ab66" CreationDate="2016-10-26T14:07:09.543" UserId="1952" Comment="added 15 characters in body" Text="**Basics of Spherical Harmonics**&#xD;&#xA;&#xD;&#xA;Spherical Harmonics is a way to represent a 2D function on a surface of a sphere. Instead of spatial domain (like cubemap), SH is defined in frequency domain with some interesting properties and operations relevant to lighting that can be performed efficiently. With increasing &quot;order&quot; of SH you can represent higher frequencies (details) of functions as illustrated in the image below ($l$ is the SH order). By scaling and summing the below &quot;basis functions&quot; you can represent any kind of 2D function on the sphere up to the frequency defined by the functions. The basis functions are defined with &quot;[associated Legendre polynomials][1]&quot;, but usually you don't need to derive these yourself but can use existing derivations for [real spherical harmonics][2].&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;One such operation that can be performed efficiently in SH is called &quot;[convolution][4]&quot;, which means integrating the product of two spherical 2D functions over a sphere. This is a common operation in lighting calculations, e.g. one of the function could be your incident lighting and one function the BRDF. When represented as SH, this operation is simply the dot product of two SH coefficient vectors.&#xD;&#xA;&#xD;&#xA;Another interesting operation is the ability to do efficient low-pass filtering. Because SH is represented in frequency domain, this is simply the matter of scaling or zeroing out some of the SH coefficients. Some other operations on the other hand can be difficult to perform in SH compared to spatial domain, e.g. if you want to rotate function represented as SH, it can get quite expensive for higher order SH. So it really depends on the problem if it's suitable to be performed in SH or not.&#xD;&#xA;&#xD;&#xA;SH is generally used to represent only low-frequency functions (i.e. smoothly changing functions) because higher frequencies requires increasing the amount of storage (SH coefficients) and processing. This is why you don't see SH being used for example to replace specular reflections on shiny surfaces. There are also [Zonal Spherical Harmonics][5], which is can be used to reduce storage &amp; computation for 2D functions that are rotationally symmetric about z-axis, by just storing diagonal elements of the SH coefficient matrix. Also [Hemispherical Harmonics][6] can be used if you need to only deal with hemispherical functions (also common in lighting) with the advantage of being able to represent similar frequencies as SH with less coefficients.&#xD;&#xA;&#xD;&#xA;One operation you also need to perform is &quot;SH projection&quot; to transform spatial domain data to SH. You can do this operation by performing convolution of spatial domain data with SH basis functions. An interesting property of SH is that unlike spatial domain representations SH doesn't suffer from aliasing, so you don't have aliasing artifacts even when projecting to very low-order SH.&#xD;&#xA;&#xD;&#xA;**Light Probes**&#xD;&#xA;&#xD;&#xA;Now that you understand the basic operations and properties of SH, we can think how to apply them to GI. A light probe records how much light is coming from every direction to the point where the probe is located. This is a 2D function on a sphere and can be represented as SH (or 3 SH function for red, green and blue). Depending on the amount of lighting details we want to encode into the probes we can choose the SH order.&#xD;&#xA;&#xD;&#xA;For light probes that are used only for Lambertian diffuse lighting, quite low-order SH is sufficient since the convolution is performed with cosine-lobe, which can be represented with order-2 SH (9 coefficients). The SH coefficients for light probes can be generated simply by rendering a cubemap at the point of the probe and then projecting it to SH.&#xD;&#xA;&#xD;&#xA;When rendering geometry, few nearest light probes are taken and their results are interpolated to get the incident lighting function in a point in space. This can be done for example by interpolating the SH coefficients of nearby probes directly and then performing the convolution with pixel normal oriented cosine lobe in SH domain.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Associated_Legendre_polynomials&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics&#xD;&#xA;  [3]: https://i.stack.imgur.com/QPNGz.png&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Convolution&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Zonal_spherical_harmonics&#xD;&#xA;  [6]: http://www.cs.ucf.edu/~ceh/Publications/Papers/Rendering/EGSR04GautronEtAl.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9214" PostHistoryTypeId="2" PostId="4183" RevisionGUID="1abc01aa-3865-4f0f-bf22-91a921a28e5c" CreationDate="2016-10-26T15:57:53.633" UserId="5362" Text="I've tried to figure this out as well, but I don't think there is a solution that is just as performant as tracing one sphere.  Basically you would want to cast one ray to hit a infinite set of repeating spheres with no marching iteration.  That would be awesome but is not possible:  Let me explain.&#xD;&#xA;# &#xD;&#xA;&#xD;&#xA;**Ray-tracing** is basically finding the analytical solution to this equation:&#xD;&#xA;$$&#xD;&#xA;f(\vec{r(t)}) = 0 \ for \ t&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $f(\vec{p})$ is the implicit surface function (which gives the distance the given point $\vec{p}$ is from the surface) and $\vec{r(t)}$ is the parametric ray equation ($\vec{r(t)} = \vec{origin} + \vec{direction}*t$).  $t$ would represent the distance along the ray the intersection happens.&#xD;&#xA;&#xD;&#xA;In order to ray-trace domain manipulations (like repeating space), these domain manipulations need to be present in the implicit surface function $f(\vec{p})$ while finding an analytical solution.  Let's take a 3D repeating sphere for instance.&#xD;&#xA;$$&#xD;&#xA;f'(\vec{p}) = \|\vec{p}\bmod \vec{d}\| - r&#xD;&#xA;$$&#xD;&#xA;(where $\vec{d}$ is a constant representing the grid size and $r$ is the radius)&#xD;&#xA;&#xD;&#xA;In order to solve $f'(\vec{r(t)}) = 0$ for $t$ we would need the inverse of the modulo operator which doesn't really exist : http://mathforum.org/library/drmath/view/51619.html.  That means there is no analytical solution to this equation, but there is a numerical one. Hence **Ray-marching**.&#xD;&#xA;# &#xD;&#xA;&#xD;&#xA;This is true for a lot of cool distance functions you see on shadertoy.com, the analytical solution does not exist for these surfaces so you cannot ray-trace.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9215" PostHistoryTypeId="2" PostId="4184" RevisionGUID="da4ea9c6-50e0-4d36-9a4d-db1e8edb65a3" CreationDate="2016-10-26T18:12:36.027" UserId="5363" Text="This is related to [question on SO](http://stackoverflow.com/questions/40268554/texture-coordinates-for-part-of-model) *(but the purpose of this question is different)*.&#xD;&#xA;&#xD;&#xA;I have model with *UWVs* (3DS max)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have grouped some unused parts of *UWVs* on the top right corner. *Bump map* is 512x512 (large enough), so Id like to decrease its dimensions if possible (e.g. tile a texture of smaller size). Currently I am using only *bump map* for the top part of the object and this solution is enough for now, but I want to improve it.&#xD;&#xA;&#xD;&#xA;I am asking for advice: &#xD;&#xA;&#xD;&#xA;how to optimize this *UWVs* mapping to be more universal and applicable for future usage (best practice/article/advice/example/other, leading to right direction)?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zOJrI.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9216" PostHistoryTypeId="1" PostId="4184" RevisionGUID="da4ea9c6-50e0-4d36-9a4d-db1e8edb65a3" CreationDate="2016-10-26T18:12:36.027" UserId="5363" Text="Model UWVs optimization" ContentLicense="CC BY-SA 3.0" />
  <row Id="9217" PostHistoryTypeId="3" PostId="4184" RevisionGUID="da4ea9c6-50e0-4d36-9a4d-db1e8edb65a3" CreationDate="2016-10-26T18:12:36.027" UserId="5363" Text="|texture|optimisation|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9218" PostHistoryTypeId="5" PostId="4184" RevisionGUID="96ebfbf9-a993-4751-a6c0-102cd308f5cd" CreationDate="2016-10-26T20:57:54.760" UserId="5363" Comment="Changed UVWs to UVs to avoid misunderstanding" Text="This is related to [question on SO](http://stackoverflow.com/questions/40268554/texture-coordinates-for-part-of-model) *(but the purpose of this question is different)*.&#xD;&#xA;&#xD;&#xA;I have model with *UVs* (3DS max UVW editor screenshot)&#xD;&#xA;&#xD;&#xA;[![3dsmax uvws editor screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;I have grouped some unused parts of *UVs* on the top right corner. *Bump map* is 512x512 (large enough), so Id like to decrease its dimensions if possible (e.g. tile a texture of smaller size). Currently I am using only *bump map* for the top part of the object and this solution is enough for now, but I want to improve it.&#xD;&#xA;&#xD;&#xA;I am asking for advice:&#xD;&#xA;&#xD;&#xA; - How to optimize this *UVs* mapping to be more universal and applicable for future usage (best practice/article/advice/example/other, leading to right direction)?&#xD;&#xA; - What steps and techniques I will need to do to use multiple *UVs* for single object (I would like make each texture obtain all avalable space)?&#xD;&#xA;&#xD;&#xA;P.S. for the second question - optimize like so:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zOJrI.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/iOkhI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9219" PostHistoryTypeId="4" PostId="4184" RevisionGUID="96ebfbf9-a993-4751-a6c0-102cd308f5cd" CreationDate="2016-10-26T20:57:54.760" UserId="5363" Comment="Changed UVWs to UVs to avoid misunderstanding" Text="Model UVs optimization" ContentLicense="CC BY-SA 3.0" />
  <row Id="9220" PostHistoryTypeId="2" PostId="4185" RevisionGUID="2ed001d4-00ac-491f-943a-f63aede691b8" CreationDate="2016-10-27T03:30:38.907" UserId="56" Text="I'm curious why spherical harmonics are commonly used in real time graphics instead of a spherical Fourier transform.&#xA;&#xA;I get that spherical harmonics are in a sort of frequency space (like FT is) so you can do convolution very efficiently.&#xA;&#xA;I also get that SH is an approximation of a function on a sphere, using up to an infinite series to perfectly reconstruct the original data, but often using only the first few items in the series.&#xA;&#xA;This sounds a lot like a spherical Fourier transform, but the math uses different functions entirely.&#xA;&#xA;What is the benefit of the SH representation over spherical FT?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9221" PostHistoryTypeId="1" PostId="4185" RevisionGUID="2ed001d4-00ac-491f-943a-f63aede691b8" CreationDate="2016-10-27T03:30:38.907" UserId="56" Text="Why is spherical harmonics used in low frequency graphics data instead of spherical Fourier transform?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9222" PostHistoryTypeId="3" PostId="4185" RevisionGUID="2ed001d4-00ac-491f-943a-f63aede691b8" CreationDate="2016-10-27T03:30:38.907" UserId="56" Text="|lighting|fourier-transform|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9223" PostHistoryTypeId="4" PostId="4185" RevisionGUID="992e97a2-11ed-4b86-808e-81a195a0238e" CreationDate="2016-10-27T04:36:42.530" UserId="56" Comment="edited title" Text="Why is spherical harmonics used in low frequency graphics data instead of a spherical Fourier transform?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9224" PostHistoryTypeId="5" PostId="4184" RevisionGUID="2871ad80-c129-46ac-818e-f5fe74f3cd57" CreationDate="2016-10-27T07:29:28.080" UserId="5363" Comment="Added more detailed description" Text="This is related to [question on SO](http://stackoverflow.com/questions/40268554/texture-coordinates-for-part-of-model) *(but the purpose of this question is different)*.&#xD;&#xA;&#xD;&#xA;I have model with *UVs* (3DS max UVW editor screenshot)&#xD;&#xA;&#xD;&#xA;[![3dsmax uvws editor screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;I have grouped some unused parts of *UVs* on the top right corner. *Bump map* is 512x512 (large enough), so Id like to decrease its dimensions if possible (e.g. tile a texture of smaller size). Currently I am using only *bump map* for the top part of the object and this solution is enough for now, but I want to improve it.&#xD;&#xA;&#xD;&#xA;I am asking for advice:&#xD;&#xA;&#xD;&#xA; - How to optimize this *UVs* mapping to be more universal and applicable for future usage (best practice/article/advice/example/other, leading to right direction)?&#xD;&#xA; - What steps and techniques I will need to do to use multiple *UVs* for single object (I would like make each texture obtain all avalable space)?&#xD;&#xA;&#xD;&#xA;P.S. For the second question:&#xD;&#xA;&#xD;&#xA;Imagine a cube with image of &quot;sun&quot; on left side, bump map on right side and another combinations of textures on rest sides. Then (in case of single UV) UVs would be divided into 9 parts (6 for each side and 3 unused free space) and each texture (for example image of &quot;sun&quot;) can obtain only a part of texture space and the rest space - empty. Greater dimensions of each texture is needed to get better result. &#xD;&#xA;&#xD;&#xA;So, I am looking for a way to do like so (make each texture use max avalable space):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zOJrI.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/iOkhI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9225" PostHistoryTypeId="2" PostId="4186" RevisionGUID="2db05e14-f826-415b-ac98-44c12af88381" CreationDate="2016-10-27T08:20:01.903" UserId="2041" Text="Spherical harmonics really are the &quot;spherical Fourier transform&quot; you're looking for. The kind of hack you mention in comments, of doing a 2D Fourier transform on a lat-long projection, suffers from all the problems you usually have when you try to project a sphere onto a plane: not all spatial relations in the sphere are well-represented in the plane. If you take stretching at the poles as an example, that clearly results in a frequency shift. High-frequency components in the sphere get shifted down to low frequencies in the plane, and when you do the inverse transform, any inaccuracy shows up as high-frequency components at the pole.&#xD;&#xA;&#xD;&#xA;Such a transform is useless for analysing the spectrum of the original signal, because it distorts the frequencies (and distorts them differently in different parts of the sphere). It's also poor for representation, because of the introduction of these high-frequency artefacts.&#xD;&#xA;&#xD;&#xA;Spherical harmonics use different basis functions so they can work directly on the lat-long without treating it like a plane. If you plot the response of the spherical harmonics on a plane projection of the sphere, they look kooky (like a map of the earth does), but they look much more natural on a sphere. They don't suffer from artefacts at the poles, and they don't frequency-shift signals." ContentLicense="CC BY-SA 3.0" />
  <row Id="9230" PostHistoryTypeId="2" PostId="4188" RevisionGUID="fa3cf8ac-fa83-4c4e-873f-659a05be42c2" CreationDate="2016-10-27T14:39:12.590" UserId="4981" Text="my doubt is on uniform (periodic) cubic B-splines (approximation, no interpolation).&#xD;&#xA;&#xD;&#xA;$$B=1/6\begin{bmatrix}-1&amp;3&amp;-3&amp;1\\3&amp;-6&amp;3&amp;0\\-3&amp;0&amp;3&amp;0\\1&amp;4&amp;1&amp;0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;B is the matrix of coefficients that allows calculate a single curve segment with the formula:&#xD;&#xA;&#xD;&#xA;$$ Q_i(u)=[u^3 u^2 u^1 1]M $$ \begin{bmatrix}P_{i-3}\\P_{i-2}\\P_{i-1}\\P_{i}\end{bmatrix}&#xD;&#xA;&#xD;&#xA;When i=3 I calculate  the first segment of curve. My question is when i=4 and I want calculate the second segment of curve you must change the 4 control points sequence but does B changes or not? " ContentLicense="CC BY-SA 3.0" />
  <row Id="9231" PostHistoryTypeId="1" PostId="4188" RevisionGUID="fa3cf8ac-fa83-4c4e-873f-659a05be42c2" CreationDate="2016-10-27T14:39:12.590" UserId="4981" Text="Does blending matrix change for to calculate various segments curve in uniform cubic B-splines approximation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9232" PostHistoryTypeId="3" PostId="4188" RevisionGUID="fa3cf8ac-fa83-4c4e-873f-659a05be42c2" CreationDate="2016-10-27T14:39:12.590" UserId="4981" Text="|maths|interpolation|curve|model|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9234" PostHistoryTypeId="5" PostId="4188" RevisionGUID="4edf8108-98e4-4f1f-9bc5-75b8801fd56a" CreationDate="2016-10-27T15:23:07.867" UserId="38" Comment="added 11 characters in body; edited tags" Text="I would like to ask about uniform (periodic) cubic B-splines (approximation, no interpolation).&#xD;&#xA;&#xD;&#xA;$$B=1/6\begin{bmatrix}-1&amp;3&amp;-3&amp;1\\3&amp;-6&amp;3&amp;0\\-3&amp;0&amp;3&amp;0\\1&amp;4&amp;1&amp;0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;B is the matrix of coefficients that allows calculate a single curve segment with the formula:&#xD;&#xA;&#xD;&#xA;$$ Q_i(u)=[u^3 u^2 u^1 1]M $$ \begin{bmatrix}P_{i-3}\\P_{i-2}\\P_{i-1}\\P_{i}\end{bmatrix}&#xD;&#xA;&#xD;&#xA;When i=3 I calculate  the first segment of curve. My question is when i=4 and I want calculate the second segment of curve you must change the 4 control points sequence but does B changes or not? " ContentLicense="CC BY-SA 3.0" />
  <row Id="9235" PostHistoryTypeId="6" PostId="4188" RevisionGUID="4edf8108-98e4-4f1f-9bc5-75b8801fd56a" CreationDate="2016-10-27T15:23:07.867" UserId="38" Comment="added 11 characters in body; edited tags" Text="|interpolation|curve|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9236" PostHistoryTypeId="5" PostId="4188" RevisionGUID="86ec65cb-d6b3-4975-bf01-9baf60fb0bce" CreationDate="2016-10-27T15:28:01.333" UserId="231" Comment="Improve clarity. Please reverse anything that changes your intention." Text="I would like to ask about uniform (periodic) cubic B-splines (approximation, no interpolation).&#xD;&#xA;&#xD;&#xA;$$B=1/6\begin{bmatrix}-1&amp;3&amp;-3&amp;1\\3&amp;-6&amp;3&amp;0\\-3&amp;0&amp;3&amp;0\\1&amp;4&amp;1&amp;0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;$B$ is the matrix of coefficients that allows calculating a single curve segment with the formula:&#xD;&#xA;&#xD;&#xA;$$ Q_i(u)=[u^3 u^2 u^1 1]B \begin{bmatrix}P_{i-3}\\P_{i-2}\\P_{i-1}\\P_{i}\end{bmatrix} $$&#xD;&#xA;&#xD;&#xA;When $i=3$ I calculate the first segment of the curve. My question is when $i=4$ and I want to calculate the second segment of the curve I must change the $4$ control points but does $B$ change or not? " ContentLicense="CC BY-SA 3.0" />
  <row Id="9237" PostHistoryTypeId="4" PostId="4188" RevisionGUID="86ec65cb-d6b3-4975-bf01-9baf60fb0bce" CreationDate="2016-10-27T15:28:01.333" UserId="231" Comment="Improve clarity. Please reverse anything that changes your intention." Text="Does the blending matrix change between calculating various curve segments in a uniform cubic B-splines approximation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9238" PostHistoryTypeId="2" PostId="4189" RevisionGUID="a506d0ce-9ec8-4e45-bcfc-4f14f2e597be" CreationDate="2016-10-27T17:42:26.637" UserId="48" Text="No, the $B$ matrix (basis coefficient matrix) does not change from one segment to the next. It is a property of the type of spline you're using, in this case cubic B-splines. If you used Bézier splines or Hermite splines instead, you'd have a different $B$ matrix." ContentLicense="CC BY-SA 3.0" />
  <row Id="9239" PostHistoryTypeId="2" PostId="4190" RevisionGUID="b8523710-212f-44d1-a1b8-cb2beb5e8c47" CreationDate="2016-10-27T17:42:52.457" UserId="1952" Text="No, $B$ is constant for given type of cubic spline, e.g. B-spline, Bezier, Hermite or Catmull-Rom cubic splines have different $B$ matrix. To make B-spline continuous, you need to copy 3 control points from the previous spline segment $a$ to the control points of spline segment $b$ and add a new point as the last control point of $b$ such that:&#xD;&#xA;&#xD;&#xA;$Pb_{i-3}=Pa_{i-2}$, $Pb_{i-2}=Pa_{i-1}$, $Pb_{i-1}=Pa_i$ and $Pb_i$=new control point." ContentLicense="CC BY-SA 3.0" />
  <row Id="9240" PostHistoryTypeId="2" PostId="4191" RevisionGUID="b3876607-f653-4298-8c33-f87bcdf31518" CreationDate="2016-10-27T19:56:33.657" UserId="5367" Text="So in the class I've learned that Aliasing refers to the jagged edges resultant from the discrete nature of computer graphics way of representation.&#xD;&#xA;&#xD;&#xA;Also, I know that Anti-aliasing refers to a technic (mainly of blurring) to remove (our camouiflage) aliasing.&#xD;&#xA;&#xD;&#xA;But I was presented a question about &quot;A picture flickering in a game room when the user moves&quot; and the answer was given as being an aliasing problem.&#xD;&#xA;&#xD;&#xA;I did not get the relation between flickering and aliasing. Can someone clarify it to me?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9241" PostHistoryTypeId="1" PostId="4191" RevisionGUID="b3876607-f653-4298-8c33-f87bcdf31518" CreationDate="2016-10-27T19:56:33.657" UserId="5367" Text="What is the relation between Aliasing and Flickering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9242" PostHistoryTypeId="3" PostId="4191" RevisionGUID="b3876607-f653-4298-8c33-f87bcdf31518" CreationDate="2016-10-27T19:56:33.657" UserId="5367" Text="|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9243" PostHistoryTypeId="2" PostId="4192" RevisionGUID="1e6fb47b-ef48-480d-9831-7dd166a90063" CreationDate="2016-10-27T20:06:16.797" UserId="48" Text="Flickering can be a form of *temporal* aliasing. It's a similar phenomenon to spatial aliasing such as jaggies, but it occurs in time instead of space.&#xD;&#xA;&#xD;&#xA;For instance, a common cause of image flickering in graphics is when the camera or geometry is in motion, and geometric features fluctuate in pixel size as they move. For example, imagine a railing with thin vertical bars. Depending where a bar appears relative to the pixel grid, it might get rendered as 2 pixels wide, only 1 pixel wide, or it might not appear at all. And in motion, it may rapidly fluctuate between these states, creating a visually objectionable flicker.&#xD;&#xA;&#xD;&#xA;Another common cause of image flickering is specular surfaces with a bumpy normal map and a high specular power. The specular highlights can flicker in motion, due to their alignment with pixels changing from frame to frame.&#xD;&#xA;&#xD;&#xA;Antialiasing strategies that address only spatial aliasing will often produce an image that looks good in a static screenshot, but turns into a flickery mess as soon as things start moving. This is one reason why [temporal antialiasing](https://en.wikipedia.org/wiki/Temporal_anti-aliasing) has become popular in games in recent years." ContentLicense="CC BY-SA 3.0" />
  <row Id="9244" PostHistoryTypeId="5" PostId="4186" RevisionGUID="b26bbcaf-aa37-4211-ba62-8b08490676af" CreationDate="2016-10-27T22:49:43.190" UserId="2041" Comment="Incorporate info from Nathan Read's comment, and answer the OP's question." Text="Spherical harmonics really are the &quot;spherical Fourier transform&quot; you're looking for. The kind of hack you mention in comments, of doing a 2D Fourier transform on a lat-long projection, suffers from all the problems you usually have when you try to project a sphere onto a plane: not all spatial relations in the sphere are well-represented in the plane. If you take stretching at the poles as an example, that clearly results in a frequency shift. High-frequency components in the sphere get shifted down to low frequencies in the plane, and when you do the inverse transform, any inaccuracy shows up as high-frequency components at the pole.&#xD;&#xA;&#xD;&#xA;Such a transform is useless for analysing the spectrum of the original signal, because it distorts the frequencies (and distorts them differently in different parts of the sphere). It's also poor for representation, because of the introduction of these high-frequency artefacts.&#xD;&#xA;&#xD;&#xA;Spherical harmonics use different basis functions so they can work directly on the lat-long without treating it like a plane. If you plot the response of the spherical harmonics on a plane projection of the sphere, they look kooky (like a map of the earth does), but they look much more natural on a sphere. They don't suffer from artefacts at the poles, and they don't frequency-shift signals. They're also rotation-invariant, so it doesn't even matter where you put the poles. They don't even have poles, in the sense of discontinuities, which is a property you can't achieve from a plane projection however many *ad hoc* co-ordinate transforms you do. Rotation-invariance is useful for applications like environment maps, where you'd like to rotate the spherical-harmonic transform of the environment (light probe, or whatever) into the local co-ordinate system before feeding it to the shader. There isn't a projection onto the plane that has this property." ContentLicense="CC BY-SA 3.0" />
  <row Id="9245" PostHistoryTypeId="2" PostId="4193" RevisionGUID="335737b3-23c9-43b0-9820-77b171cd26e3" CreationDate="2016-10-28T00:52:00.050" UserId="5371" Text="This is a rather primitive question coming from an electronic engineer. When applying rotate (about origin), scale (in which we shall translate towards origin and then back) and translate, does it matter in what order we do it? Why?&#xD;&#xA;&#xD;&#xA;Basically in my case I have an image in coordinate space that goes from -2 to +2 in x and -1.5 to +1.5 in y to get ration of 4:3. This range comes from how the original mandelbrot set is plotted. I need to scale and translate this to fit into an axes (of pixels) in bitmap that goes from 0 to 800 in x axis and 0 to 600 in y axis. I am trying to understand what matrix to use to scale and translate the points from my mandelbrot set into the bitmap image." ContentLicense="CC BY-SA 3.0" />
  <row Id="9246" PostHistoryTypeId="1" PostId="4193" RevisionGUID="335737b3-23c9-43b0-9820-77b171cd26e3" CreationDate="2016-10-28T00:52:00.050" UserId="5371" Text="What is the correct order of transformations scale, rotate and translate and why?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9247" PostHistoryTypeId="3" PostId="4193" RevisionGUID="335737b3-23c9-43b0-9820-77b171cd26e3" CreationDate="2016-10-28T00:52:00.050" UserId="5371" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9248" PostHistoryTypeId="2" PostId="4194" RevisionGUID="667fc771-ed2e-40b5-9dde-4a18fb20981e" CreationDate="2016-10-28T02:43:22.807" UserId="1952" Text="Usually you scale first, then rotate and finally translate. The reason is because usually want to scaling to happen along the axis of the object and rotation about the center of the object.&#xD;&#xA;&#xD;&#xA;In your case you don't really need to worry about this generic solution though, but you only need to map range [0, 800] $\rightarrow$ [-2, 2] for x-coordinate and [0, 600] $\rightarrow$ [-1.5, 1.5] for y-coordinate, in order to map screen coordinates to real/imaginary components for Mandelbrot calculation. So this is simply done by:&#xD;&#xA;$$real=4*(x+0.5)/800-2$$&#xD;&#xA;$$imag=3*(y+0.5)/600-1.5$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9249" PostHistoryTypeId="2" PostId="4195" RevisionGUID="74fab36f-6f9d-4c81-97c5-fe37812b6eeb" CreationDate="2016-10-28T07:59:48.507" UserId="2372" Text="As I am working with Unity, I found an interesting way of calculating the parallax offset inside the engine. It's not physically based but it gives better results than the classic parallax refraction.&#xD;&#xA;&#xD;&#xA;    float2 ParallaxOffset(half h, half height, half3 viewDir)&#xD;&#xA;    {&#xD;&#xA;    	h = h * height - height / 2.0;&#xD;&#xA;    	float3 v = normalize(viewDir);&#xD;&#xA;    	v.z += 0.42;&#xD;&#xA;    	return h * (v.xy / v.z);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="9250" PostHistoryTypeId="5" PostId="4194" RevisionGUID="c31e28c8-8ef6-4bcd-9670-0d9772f723fb" CreationDate="2016-10-28T08:43:40.507" UserId="1952" Comment="added 273 characters in body; added 4 characters in body; added 1 character in body" Text="Usually you scale first, then rotate and finally translate. The reason is because usually you want the scaling to happen along the axis of the object and rotation about the center of the object.&#xD;&#xA;&#xD;&#xA;In your case you don't really need to worry about this generic solution though, but you only need to map range [0, 800] $\rightarrow$ [-2, 2] for x-coordinate and [0, 600] $\rightarrow$ [-1.5, 1.5] for y-coordinate, in order to map screen coordinates to real/imaginary components for Mandelbrot calculation. So this is simply done by:&#xD;&#xA;$$real=4*(x+0.5)/800-2$$&#xD;&#xA;$$imag=3*(y+0.5)/600-1.5$$&#xD;&#xA;&#xA;Note that you need to calculate Mandelbrot coordinates from screen coordinates and not the other way aroumd. This is to ensure that you evaluate the Manderbrot equation for each pixel exactly once and are not left with holes in the image or do double evaluation per pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="9251" PostHistoryTypeId="5" PostId="4194" RevisionGUID="c7041401-1d0e-49a7-97b1-2a67ee89c2f5" CreationDate="2016-10-28T13:25:27.570" UserId="1952" Comment="added 1 character in body" Text="Usually you scale first, then rotate and finally translate. The reason is because usually you want the scaling to happen along the axis of the object and rotation about the center of the object.&#xD;&#xA;&#xD;&#xA;In your case you don't really need to worry about this generic solution though, but you only need to map range [0, 800] $\rightarrow$ [-2, 2] for x-coordinate and [0, 600] $\rightarrow$ [-1.5, 1.5] for y-coordinate, in order to map screen coordinates to real/imaginary components for Mandelbrot calculation. So this is simply done by:&#xD;&#xA;$$real=4*(x+0.5)/800-2$$&#xD;&#xA;$$imag=3*(y+0.5)/600-1.5$$&#xD;&#xA;&#xD;&#xA;Note that you need to calculate Mandelbrot coordinates from screen coordinates and not the other way around. This is to ensure that you evaluate the Manderbrot equation for each pixel exactly once and are not left with holes in the image or do double evaluation per pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="9253" PostHistoryTypeId="2" PostId="4196" RevisionGUID="40fd0e7c-bcef-4e11-9ee1-d8c858209596" CreationDate="2016-10-29T10:17:19.677" UserId="5256" Text="After reading a wikipedia article about **[Global Illumination][1]** It mentions a variety of techniques like Ray Tracing, Path Tracing and Ambient Occlusion. One technique it mentions is **Radiosity** which I don't know much about.&#xD;&#xA;&#xD;&#xA;After a quick google search I found this [**blog post**][2] which discusses what it is, a basic overview &amp; implementation details. However I'm still a little confused. So from what I gather it is a way to precompute diffuse lighting on to a lightmap **to give the illusion of light bounces?** Could someone explain it to me over here without all the jargon? Is this technique used alongside techniques like **Image Based Lighting &amp; Ambient Occlusion** or is it intended to be an entire Global Illumination technique by itself? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Global_illumination&#xD;&#xA;  [2]: https://mynameismjp.wordpress.com/2011/01/31/radiosity-dx11-style/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9254" PostHistoryTypeId="1" PostId="4196" RevisionGUID="40fd0e7c-bcef-4e11-9ee1-d8c858209596" CreationDate="2016-10-29T10:17:19.677" UserId="5256" Text="What is Radiosity?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9255" PostHistoryTypeId="3" PostId="4196" RevisionGUID="40fd0e7c-bcef-4e11-9ee1-d8c858209596" CreationDate="2016-10-29T10:17:19.677" UserId="5256" Text="|lighting|physically-based|global-illumination|ambient-occlusion|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9256" PostHistoryTypeId="2" PostId="4197" RevisionGUID="f9837fd6-9a65-4810-916a-8847c3b8adf0" CreationDate="2016-10-29T11:35:43.407" UserId="4958" Text="**When I set up texture as float it works (color is written -  BTW I'm doing voxelization):**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA,GL_FLOAT,NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32f ,binding = 0) uniform image3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0)); //ivec4 or vec4, it works&#xD;&#xA;&#xD;&#xA;reading:&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But I want to use integer texture (for binary voxelization and bitwise opartions - each bit = slice in z direction). I set it up like that:**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width, height, depth, 0, GL_RGBA, GL_INT, NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32I);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32i ,binding = 0) uniform iimage3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0));&#xD;&#xA;&#xD;&#xA;reading (same as float):&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;Then it's black. Whats wrong with that? There is sparse documentation about it. BTW The info that iimage is for integer texture, uimage is for unsigned int is actually nowhere to be found.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9257" PostHistoryTypeId="1" PostId="4197" RevisionGUID="f9837fd6-9a65-4810-916a-8847c3b8adf0" CreationDate="2016-10-29T11:35:43.407" UserId="4958" Text="setting up integer texture and binding as image" ContentLicense="CC BY-SA 3.0" />
  <row Id="9258" PostHistoryTypeId="3" PostId="4197" RevisionGUID="f9837fd6-9a65-4810-916a-8847c3b8adf0" CreationDate="2016-10-29T11:35:43.407" UserId="4958" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9259" PostHistoryTypeId="5" PostId="4197" RevisionGUID="be56a212-1512-4269-95fb-9e0c355676a5" CreationDate="2016-10-29T11:47:14.600" UserId="4958" Comment="added 1 character in body" Text="**When I set up texture as float it works (color is written -  BTW I'm doing voxelization):**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA,GL_FLOAT,NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32f ,binding = 0) uniform image3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0)); //ivec4 or vec4, it works&#xD;&#xA;&#xD;&#xA;reading:&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But I want to use integer texture (for binary voxelization and bitwise operations - each bit = slice in z direction). I set it up like that:**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width, height, depth, 0, GL_RGBA, GL_INT, NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32I);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32i ,binding = 0) uniform iimage3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0));&#xD;&#xA;&#xD;&#xA;reading (same as float):&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;Then it's black. Whats wrong with that? There is sparse documentation about it. BTW The info that iimage is for integer texture, uimage is for unsigned int is actually nowhere to be found.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9260" PostHistoryTypeId="5" PostId="4197" RevisionGUID="b9ef970a-a956-4068-81ab-cea46e9320a2" CreationDate="2016-10-29T12:00:13.027" UserId="4958" Comment="added 16 characters in body" Text="**When I set up texture as float it works (color is written -  BTW I'm doing voxelization):**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA,GL_FLOAT,NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32f ,binding = 0) uniform image3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0)); //ivec4 or vec4, it works&#xD;&#xA;&#xD;&#xA;reading:&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But I want to use integer texture (for future doing of binary voxelization and bitwise operations - each bit = slice in z direction). I set it up like that:**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width, height, depth, 0, GL_RGBA, GL_INT, NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32I);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32i ,binding = 0) uniform iimage3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0));&#xD;&#xA;&#xD;&#xA;reading (same as float):&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;Then it's black. Whats wrong with that? There is sparse documentation about it. BTW The info that iimage is for integer texture, uimage is for unsigned int is actually nowhere to be found.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9261" PostHistoryTypeId="2" PostId="4198" RevisionGUID="982e1a81-47cb-48c8-83f1-9683d634c882" CreationDate="2016-10-29T17:43:48.003" UserId="1952" Text="Radiosity is a way to calculate diffuse GI, i.e. every surface is assumed to be Lambertian surface without specular component. In the radiosity algorithm you split surfaces into small patches and calculate &quot;form factor&quot; between two patches, which defines how much energy is transferred from one patch to the other.&#xD;&#xA;&#xD;&#xA;The form factor between patches is calculated using the distance between patches (for patches further apart means less energy transferred between them), their respective orientation (two patches facing each other transfer more energy than when they face away from each other), the visibility (if patch is occluded, it doesn't transfer energy to the patch) and their size (larger surfaces emit more energy). The form factor obeys reciprocity which means that the factor for patches A and B can be used for energy transmission calculation from A to B and from B to A.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To calculate radiosity for a patch, you iterate through all patches and accumulate the energy from other patches using their respective form factors and the luminance of each patch. This is a single iteration of the radiosity algorithm, and for multiple light bounces you can run multiple iterations of this same algorithm.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yh4v5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9262" PostHistoryTypeId="5" PostId="4198" RevisionGUID="0f52c8db-6253-41b5-a4fd-18a1c39491ab" CreationDate="2016-10-29T17:49:51.393" UserId="1952" Comment="added 140 characters in body" Text="Radiosity is a way to calculate diffuse GI, i.e. every surface is assumed to be Lambertian surface without specular component. In the radiosity algorithm you split surfaces into small patches and calculate &quot;form factor&quot; between two patches, which defines how much energy is transferred from one patch to the other.&#xD;&#xA;&#xD;&#xA;The form factor between patches is calculated using the distance between patches (patches further apart means less energy transferred between them), their respective orientation (two patches facing each other transfer more energy than when they face away from each other), the visibility (if patch is occluded, it doesn't transfer energy to the patch) and their size (larger surfaces emit more energy). The form factor obeys reciprocity which means that the factor for patches A and B can be used for energy transmission calculation from A to B and from B to A.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To calculate radiosity for a patch, you iterate through all patches and accumulate the energy from other patches using their respective form factors and the luminance of each patch. This is a single iteration of the radiosity algorithm, and for multiple light bounces you can run multiple iterations of this same algorithm. This can be implemented for example by rendering scene to a hemicube around each patch and accumulating the result from the cube for the patch.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yh4v5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9263" PostHistoryTypeId="5" PostId="4197" RevisionGUID="69f2ed93-9b5f-4619-9ce7-5da2c88e6ae2" CreationDate="2016-10-29T23:29:51.577" UserId="231" Comment="Minor tidying" Text="**When I set up a texture as float it works (color is written -  BTW I'm doing voxelization):**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA,GL_FLOAT,NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32f ,binding = 0) uniform image3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0)); //ivec4 or vec4, it works&#xD;&#xA;&#xD;&#xA;reading:&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But I want to use an integer texture (so in future I can do binary voxelization and bitwise operations - each bit = slice in z direction). I set it up like that:**&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width, height, depth, 0, GL_RGBA, GL_INT, NULL);&#xD;&#xA;&#xD;&#xA;then setting filtering...&#xD;&#xA;&#xD;&#xA;then binding:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32I);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;writing:&#xD;&#xA;&#xD;&#xA;    layout(rgba32i ,binding = 0) uniform iimage3D geometryGrid;&#xD;&#xA;    ...&#xD;&#xA;    imageStore(geometryGrid, index, ivec4(1.0));&#xD;&#xA;&#xD;&#xA;reading (same as float):&#xD;&#xA;&#xD;&#xA;    uniform sampler3D geometryTexture;&#xD;&#xA;    ...&#xD;&#xA;    vec4 g = texture(geometryTexture, geomCoords);&#xD;&#xA;&#xD;&#xA;Then it's black. Whats wrong with that? There is sparse documentation about it. BTW The info that `iimage` is for integer texture, `uimage` is for unsigned int is actually nowhere to be found.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9264" PostHistoryTypeId="4" PostId="4197" RevisionGUID="69f2ed93-9b5f-4619-9ce7-5da2c88e6ae2" CreationDate="2016-10-29T23:29:51.577" UserId="231" Comment="Minor tidying" Text="Setting up integer texture and binding as image" ContentLicense="CC BY-SA 3.0" />
  <row Id="9266" PostHistoryTypeId="5" PostId="4198" RevisionGUID="13b64240-cec1-4756-a5b6-7ae3f9d148cc" CreationDate="2016-10-30T02:07:33.300" UserId="1952" Comment="added 390 characters in body" Text="Radiosity is a way to calculate diffuse GI, i.e. every surface is assumed to be Lambertian surface without specular component. In the radiosity algorithm you split surfaces into small patches and calculate &quot;form factor&quot; between two patches, which defines how much energy is transferred from one patch to the other.&#xD;&#xA;&#xD;&#xA;The form factor between patches is calculated using the distance between patches (patches further apart means less energy transferred between them), their respective orientation (two patches facing each other transfer more energy than when they face away from each other), the visibility (if patch is occluded, it doesn't transfer energy to the patch) and their size (larger surfaces emit more energy). The form factor obeys reciprocity which means that the factor for patches A and B can be used for energy transmission calculation from A to B and from B to A.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To calculate radiosity for a patch, you iterate through all patches and accumulate the energy from other patches using their respective form factors and the luminance of each patch. This is a single iteration of the radiosity algorithm, and for multiple light bounces you can run multiple iterations of this same algorithm. This can be implemented for example by rendering scene to a hemicube around each patch and accumulating the result from the cube for the patch.&#xD;&#xA;&#xD;&#xA;To answer your question if radiosity is a full GI solution - no it's not. Since all surfaces are Lambertian, there's no specular component to it, so you would need to use other techniques in addition for the full lighting solution. The result of radiosity is usually also cached into lightmaps with limited resolution so you may need use AO to provide higher frequency lighting details.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yh4v5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9267" PostHistoryTypeId="2" PostId="4199" RevisionGUID="7d2d50a6-7583-46ce-a828-527f749fac12" CreationDate="2016-10-30T04:01:22.353" UserId="1952" Text="Instead of sampler3D, you should use isampler3D to sample integer formats as described in the [GLSL documentation][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Sampler_(GLSL)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9268" PostHistoryTypeId="2" PostId="4200" RevisionGUID="6f47ccb9-3da3-4da1-a7c1-d54bb066702c" CreationDate="2016-10-30T17:37:47.637" UserId="2372" Text="I have some classic texture coordinates and as a normal behaviour they follow the mesh's transformations.&#xD;&#xA;&#xD;&#xA;I am trying to use the same texture coordinates behaviour but without being affected by the mesh rotation transformation. The results would be a sort of texture coordinates projection.&#xD;&#xA;&#xD;&#xA;I don't know if my explanations are well explained but how could I achieve such effect.&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9269" PostHistoryTypeId="1" PostId="4200" RevisionGUID="6f47ccb9-3da3-4da1-a7c1-d54bb066702c" CreationDate="2016-10-30T17:37:47.637" UserId="2372" Text="Texture coordinates projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="9270" PostHistoryTypeId="3" PostId="4200" RevisionGUID="6f47ccb9-3da3-4da1-a7c1-d54bb066702c" CreationDate="2016-10-30T17:37:47.637" UserId="2372" Text="|shader|glsl|real-time|hlsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9271" PostHistoryTypeId="2" PostId="4201" RevisionGUID="3508ea52-079a-4fcd-a21f-6c68248e7f1e" CreationDate="2016-10-30T20:24:28.240" UserId="2707" Text="GLSL has built-in [fragment shader inputs][1], and one of them is gl_FragCoord. You can get the $x$ and $y$ value from this and use that as the lookup coordinate of the texture map. This would effectively be rotation-invariant (although UV coordinates shouldn't change with rotation).&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Built-in_Variable_(GLSL)#Fragment_shader_inputs" ContentLicense="CC BY-SA 3.0" />
  <row Id="9272" PostHistoryTypeId="5" PostId="4201" RevisionGUID="1f78ee4c-a271-48d9-a772-53ff1b4e6329" CreationDate="2016-10-30T20:37:35.077" UserId="2707" Comment="added 127 characters in body" Text="GLSL has built-in [fragment shader inputs][1], and one of them is gl_FragCoord. You can get the $x$ and $y$ value from this and use that as the lookup coordinate of the texture map. This would effectively be rotation-invariant (although UV coordinates shouldn't change with rotation).&#xD;&#xA;&#xD;&#xA;Untested sample code:&#xD;&#xA;&#xD;&#xA;    vec2 texCoords = gl_FragCoord.xy; // do some sort of scaling&#xD;&#xA;    texture(sampler, texCoords);&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Built-in_Variable_(GLSL)#Fragment_shader_inputs" ContentLicense="CC BY-SA 3.0" />
  <row Id="9273" PostHistoryTypeId="5" PostId="4200" RevisionGUID="c5b98c21-396a-4e9e-a9db-570ee064682e" CreationDate="2016-10-31T10:48:04.810" UserId="2372" Comment="added 89 characters in body" Text="I have some classic texture coordinates and as a normal behaviour they follow the mesh's transformations.&#xD;&#xA;&#xD;&#xA;I am trying to use the same texture coordinates behaviour but without being affected by the mesh rotation transformation. The results would be a sort of texture coordinates projection.&#xD;&#xA;&#xD;&#xA;I don't know if my explanations are well explained but how could I achieve such effect.&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bTlg5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9277" PostHistoryTypeId="2" PostId="4203" RevisionGUID="dd100e5b-dfc9-4b05-86a3-e470533dc6b0" CreationDate="2016-10-31T14:47:48.667" UserId="2654" Text="D3D12 has 4 separate kinds of command lists: direct, bundle, compute, and copy.&#xD;&#xA;&#xD;&#xA;Vulkan has similar concepts, but they happen in a different way. Command buffers are allocated from command pools. And command pools are directly associated with a queue family. And command buffers allocated from a pool can only be submitted to the queue family for which the pool was built.&#xD;&#xA;&#xD;&#xA;Queue family specify the kinds of operations that the queue can take: graphics, compute, or memory copying operations. D3D12's command queues have a similar concept, but D3D12's command list API has you to specify the list type. Vulkan's gets this information from the queue family the pool is meant for.&#xD;&#xA;&#xD;&#xA;The D3D12 &quot;bundle&quot; command list type seems similar on the surface to Vulkan secondary command buffers. However, they are quite different.&#xD;&#xA;&#xD;&#xA;The principle difference is this: bundles inherit *all state* from their executing direct command list, except for the bound PSO itself. This includes resource descriptor bindings.&#xD;&#xA;&#xD;&#xA;Vulkan secondary command buffers inherit *no state* from their primary command buffer execution environment, except for secondary CBs that execute in a subpass of a renderpass instance (and queries). And those *only* inherit the current subpass state (and queries).&#xD;&#xA;&#xD;&#xA;This means you do different things with them, compared to D3D bundles.&#xD;&#xA;&#xD;&#xA;Bundles are sometimes used to modify descriptor tables and render stuff, on the assumption that the direct command list they're executed within will have set those tables up. So bundles are kind of like light-weight OpenGL display lists, only without all of the bad things those do. So the intent with bundles is that you build them once and keep them around. They're supposed to be small things.&#xD;&#xA;&#xD;&#xA;Vulkan secondary CBs are essential for threaded building of commands intended for a single render pass instance. This is because a render pass instance can only be created within a primary CB, so for optimal use of threads, there needs to be a way to create commands meant to execute in the same subpass in different threads. That's one of the main use-cases of secondary CBs. So the intent is that you'll probably build secondary CBs each frame (though you can reuse them if you want).&#xD;&#xA;&#xD;&#xA;So in the end, bundles and secondary CBs are intended to solve separate problems. Bundles are generally dependent on the executing environment, while secondary CBs are more stand-alone.&#xD;&#xA;&#xD;&#xA;At the same time, Vulkan secondary CBs can do something bundles cannot: they can execute on compute/copy-only queues. Since Vulkan makes a distinction between the primary/secondary level of the command buffer and the queues where that CB can be sent, it is possible in Vulkan to have secondary command buffers that execute on compute or copy-only queues.&#xD;&#xA;&#xD;&#xA;Direct3D 12 can't do that with bundles. The [`ExecuteBundle` function][1] can only be called on a direct command list. So a copy-only command list cannot execute bundles.&#xD;&#xA;&#xD;&#xA;Granted, because Vulkan doesn't inherit anything between secondary CBs except for subpass state, and compute/copy operations don't use render passes, there isn't much to be gained from putting such commands in a secondary CB rather than a primary one.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;D3D12 has the same separation between [compute pipelines][2] and [graphics pipelines][3] that Vulkan does. However, when issuing commands, D3D12 has only one pipeline binding point, to which you can bind any kind of pipeline. By contrast, Vulkan has separate binding points for compute and graphics pipelines. Of course, Vulkan doesn't have different descriptor binding points for them, so the two pipelines can interfere with one another. But if you design their resource usage carefully, it is possible to invoke a dispatch operation without disturbing the needs of the graphics pipeline.&#xD;&#xA;&#xD;&#xA;So overall, there's no real difference in pipeline architecture here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn903882(v=vs.85).aspx&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn788663(v=vs.85).aspx&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn770348(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="9280" PostHistoryTypeId="2" PostId="4204" RevisionGUID="884f01a3-25ca-4c89-a00e-0530f3352ebf" CreationDate="2016-10-31T15:32:06.603" UserId="31" Text="A static occlusion map won't generally work accurately with a dynamic mesh, as you can see. In your case you can separate the occlusion map and instead put it on a static object that wraps around the eye. You can render that object with multiplicative blending and get the effect you want." ContentLicense="CC BY-SA 3.0" />
  <row Id="9281" PostHistoryTypeId="2" PostId="4205" RevisionGUID="ed54fa7e-4046-417a-b6d0-9b5c29adafc0" CreationDate="2016-10-31T17:36:31.287" UserId="5390" Text="I'm studying Illumination subject these days and I was given a problem which asks to calculate the intensity using phong illumination model. I'm little bit confused whether I should calculate normal vector using after normalize it or as it is. Normal is given below. So if you can please tell me what type of vector I have to use there and if I have to use normalized vectors then their values. &#xD;&#xA;&#xD;&#xA;$N=(0,0,-12)$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9282" PostHistoryTypeId="1" PostId="4205" RevisionGUID="ed54fa7e-4046-417a-b6d0-9b5c29adafc0" CreationDate="2016-10-31T17:36:31.287" UserId="5390" Text="Are all those vectors in Phong Illumination Model normalized?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9283" PostHistoryTypeId="3" PostId="4205" RevisionGUID="ed54fa7e-4046-417a-b6d0-9b5c29adafc0" CreationDate="2016-10-31T17:36:31.287" UserId="5390" Text="|vectors|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9284" PostHistoryTypeId="4" PostId="4205" RevisionGUID="9c119789-3716-4ccd-b373-b9c22f5b9276" CreationDate="2016-10-31T17:41:49.880" UserId="5390" Comment="Changed content" Text="Normal vector in Phong Illumination Model should be normalized?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9285" PostHistoryTypeId="5" PostId="4205" RevisionGUID="9c119789-3716-4ccd-b373-b9c22f5b9276" CreationDate="2016-10-31T17:41:49.880" UserId="5390" Comment="Changed content" Text="I'm studying Illumination subject these days and I was given a problem which asks to calculate the intensity using phong illumination model. I'm little bit confused whether I should calculate normal vector using after normalize it or as it is. Normal is given below. So if you can please tell me what type of vector I have to use there and if I have to use normalized vectors then it's value. &#xD;&#xA;&#xD;&#xA;$N=(0,0,-12)$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9287" PostHistoryTypeId="2" PostId="4206" RevisionGUID="a4225dfe-c2b7-4775-b746-ef35c0152f6c" CreationDate="2016-10-31T17:44:19.880" UserId="506" Text="Short answer: yes.&#xD;&#xA;&#xD;&#xA;Longer answer: yes, because the vectors you’re using are meant to represent directions, not directions-and-distances. Think of it in terms of light: it doesn’t matter how far a photon’s traveled, whether it’s from the sun or from a lamp on your desk—once it arrives at a surface, it’s going to get reflected in exactly the same way." ContentLicense="CC BY-SA 3.0" />
  <row Id="9288" PostHistoryTypeId="5" PostId="4206" RevisionGUID="c09fd734-60b6-4546-ba7d-82a454cf0b9f" CreationDate="2016-10-31T17:50:37.073" UserId="506" Comment="added 496 characters in body" Text="Short answer: yes.&#xD;&#xA;&#xD;&#xA;Longer answer: yes, because the vectors you’re using are meant to represent directions, not directions-and-distances. Think of it in terms of light: it doesn’t matter how far a photon’s traveled, whether it’s from the sun or from a lamp on your desk—once it arrives at a surface, it’s going to get reflected in exactly the same way.&#xD;&#xA;&#xD;&#xA;From a mathematical standpoint, you’re making lighting calculations based on the angles between the incoming light, the view point, and the surface normal. The dot product [is defined](https://en.wikipedia.org/wiki/Dot_product#Geometric_definition) as the length of the two input vectors multiplied by each other and by the cosine of the angle between them. To get just the angle—which you need for the lighting model—you need to factor out the length of the two vectors, i.e. normalize them." ContentLicense="CC BY-SA 3.0" />
  <row Id="9289" PostHistoryTypeId="2" PostId="4207" RevisionGUID="f03ad1fa-3899-4feb-8d2f-c6f8336b7c7b" CreationDate="2016-10-31T18:03:40.033" UserId="2654" Text="&gt;     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width, height, depth, 0, GL_RGBA, GL_INT, NULL);&#xD;&#xA;&#xD;&#xA;This is not an [integer image format][1]. It's an unsigned, normalized, fixed-point image format. For those, you use floating-point image/sampler variables. So for a 3D texture, you would use `image3D`, not `iimage3D`.&#xD;&#xA;&#xD;&#xA;If you want a *true* signed integer format, you would do this:&#xD;&#xA;&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32I, width, height, depth, 0, GL_RGBA_INTEGER, GL_INT, NULL);&#xD;&#xA;&#xD;&#xA;Note two changes. First, the internal format is `GL_RGBA32I`, which specifies a 32-bit-per-channel signed integer format. The second is the use of `GL_RGBA_INTEGER` for the [pixel transfer format][2]. Even though you're not actually performing a pixel transfer (since you're passing NULL), you still must use an appropriate format and type. And the `_INTEGER` formats must be used if you're transferring to/from a texture with an integer format.&#xD;&#xA;&#xD;&#xA;When you do this, you must of course use the `iimage3D` and `isampler3D` types in your shaders.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Image_Format#Color_formats&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Pixel_Transfer#Pixel_format" ContentLicense="CC BY-SA 3.0" />
  <row Id="9290" PostHistoryTypeId="5" PostId="4201" RevisionGUID="036f1d70-2c96-4241-8999-393db1f78470" CreationDate="2016-11-01T03:08:38.110" UserId="2707" Comment="Adapted the answer to the question and clarified/expanded the process, adding additional details" Text="GLSL has built-in [fragment shader inputs][1], and one of them is gl_FragCoord. You can get the $x$ and $y$ value from this and use that as the lookup coordinate of the texture map in a sequence of two passes, but that could be a good or bad thing depending on the application (such as caching the result). This would both be rotation invariant while allowing you to scale and move the mesh.&#xD;&#xA;&#xD;&#xA;# First Pass&#xD;&#xA;Transform the mesh without rotation. Bind a texture to the fragment shader and write the interpolated UV coordinates to it.&#xD;&#xA;&#xD;&#xA;# Second Pass&#xD;&#xA;Transform the mesh correctly this time. Bind the texture from the last pass and read from it this time. You preserved the old UV coordinates, and now you can use these to look up whatever texture you have before. Obviously, this works best with a mesh that's a sphere (such as an eye).&#xD;&#xA;&#xD;&#xA;    vec2 texCoords = gl_FragCoord.xy; // do some sort of scaling&#xD;&#xA;    vec2 oldTexCoords = texture(samplerOfUVTexture, texCoords); // sample UV&#xD;&#xA;&#xD;&#xA;Now you have both the old UV coordinates and the new UV coordinates. You can use the new UV coordinates for you diffuse map and the old UV coordinates for the occlusion map.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Built-in_Variable_(GLSL)#Fragment_shader_inputs" ContentLicense="CC BY-SA 3.0" />
  <row Id="9291" PostHistoryTypeId="2" PostId="4208" RevisionGUID="16a239b7-a5b2-4f70-9fc0-c8aa5d56e660" CreationDate="2016-11-01T10:57:16.097" UserId="5399" Text="**Hi there,**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Situation:**&#xD;&#xA;&#xD;&#xA;I'm trying to switch between the rendering of two different scenes as fast as possible using OpenGL.&#xD;&#xA;&#xD;&#xA;For all my OpenGL related stuff I wrote a wrapper-class which provides a quite easy way of adding and updating data. An based on the added data it automatically creates the variable naming for the shader. In the past i always used just one instance of this OpenGL class but now I'm trying to use two of them. (Each instance has its own shader program.)&#xD;&#xA;&#xD;&#xA;When i do something like &#xD;&#xA;&#xD;&#xA;    OpenGLInstance1.AssignModel(*MyModel1);&#xD;&#xA;&#xD;&#xA;it automatically adds data and writes into the shader code:&#xD;&#xA;&#xD;&#xA;        // per vertex attributes &#xD;&#xA;    layout (location = 0) in vec3	position;&#xD;&#xA;    layout (location = 1) in vec3	normals;&#xD;&#xA;    layout (location = 2) in uvec4	BoneIDs;&#xD;&#xA;    layout (location = 3) in vec4	Weights;&#xD;&#xA;    &#xD;&#xA;    // per instance attributes&#xD;&#xA;    layout (location = 4) in mat4	CameraMatrix;			//dynamic&#xD;&#xA;    layout (location = 8) in mat4	ProjectionMatrix;		//dynamic&#xD;&#xA;&#xD;&#xA;when I'm now want to do this a second time with an other OpenGL-Class instance and Model:&#xD;&#xA;&#xD;&#xA;    OpenGLInstance2.AssignModel(*MyModel2);&#xD;&#xA;&#xD;&#xA;I get:&#xD;&#xA;&#xD;&#xA;    // per vertex attributes &#xD;&#xA;        layout (location = 12) in vec3	position;&#xD;&#xA;        layout (location = 13) in vec3	normals;&#xD;&#xA;        layout (location = 14) in uvec4	BoneIDs;&#xD;&#xA;        layout (location = 15) in vec4	Weights;&#xD;&#xA;        &#xD;&#xA;        // per instance attributes&#xD;&#xA;        layout (location = 16) in mat4	CameraMatrix;			//dynamic&#xD;&#xA;        layout (location = 20) in mat4	ProjectionMatrix;		//dynamic&#xD;&#xA;&#xD;&#xA;But since the GL_MAX_VERTEX_ATTRIBS gives a maximum number of attributes of 16, this is not possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Question 1:**&#xD;&#xA;Each VAO (vertex array object) has some VBO (vertex buffer object) assigned. Is the location indexing of the VBO just in the scope of each VAO (starting again from zero for each VAO) or is it independent of the VAO?&#xD;&#xA;&#xD;&#xA;**Question 2:**&#xD;&#xA;Do you have a suggestion how to work around this problem while keeping the implementation as generic, reusable and salable as possible? (just some general hints, i don't want to bother you with details)&#xD;&#xA;&#xD;&#xA;Thanks in advance!" ContentLicense="CC BY-SA 3.0" />
  <row Id="9292" PostHistoryTypeId="1" PostId="4208" RevisionGUID="16a239b7-a5b2-4f70-9fc0-c8aa5d56e660" CreationDate="2016-11-01T10:57:16.097" UserId="5399" Text="Attribute Location in Multiple Shader Programs" ContentLicense="CC BY-SA 3.0" />
  <row Id="9293" PostHistoryTypeId="3" PostId="4208" RevisionGUID="16a239b7-a5b2-4f70-9fc0-c8aa5d56e660" CreationDate="2016-11-01T10:57:16.097" UserId="5399" Text="|opengl|shader|glsl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9302" PostHistoryTypeId="2" PostId="4211" RevisionGUID="d20f0965-d4ec-4a91-bdbe-2b3ff7cb7f8f" CreationDate="2016-11-01T19:08:07.303" UserId="5351" Text="I'm trying to get a **grey** linear-RGB-triple that is equally bright as another (colorful) RGB-triple.&#xD;&#xA;&#xD;&#xA;I have to admit, that there is great confusion for me with all the color stuff, even though I read a lot of wikipedia articles, but I don't really get the big picture. I'm kind of lost and need help.&#xD;&#xA;&#xD;&#xA;Wikipedia seems to mention a formula to receive the perceived brightness of a linear RGB color [1]. &#xD;&#xA;So I can measure the brightness of my color and do something like this I suppose:&#xD;&#xA;&#xD;&#xA;	public Vector3d get_equally_bright_grey(Vector3d color) {&#xD;&#xA;		for (double c = 0.0; c &lt;= 1.0; c += 0.001) {&#xD;&#xA;			Vector3d grey = new Vector3d(c, c, c);&#xD;&#xA;			if (brightness(color) == brightness(grey)){&#xD;&#xA;				return grey;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;But there has to be something other :)&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;Some context:&#xD;&#xA;&#xD;&#xA;My input colors were spectral distributions that I converted to XYZ values (after Bruce Lindbloom [2]).&#xD;&#xA;Then I have converted those XYZ values to linear RGB (again with Bruce [3]). And here comes my question.&#xD;&#xA;&#xD;&#xA;I know that the `Y` component of my `XYZ` triples is also something like the luminance, but I don't know how I generate a grey color XYZ color from this either..&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;[1] https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;&#xD;&#xA;[2] http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html&#xD;&#xA;&#xD;&#xA;[3] www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9303" PostHistoryTypeId="1" PostId="4211" RevisionGUID="d20f0965-d4ec-4a91-bdbe-2b3ff7cb7f8f" CreationDate="2016-11-01T19:08:07.303" UserId="5351" Text="Calculate an equally bright grey to a linear RGB colour" ContentLicense="CC BY-SA 3.0" />
  <row Id="9304" PostHistoryTypeId="3" PostId="4211" RevisionGUID="d20f0965-d4ec-4a91-bdbe-2b3ff7cb7f8f" CreationDate="2016-11-01T19:08:07.303" UserId="5351" Text="|color|color-science|brightness|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9306" PostHistoryTypeId="36" PostId="4212" RevisionGUID="355e7f3d-3a90-4b01-849f-33d205e86d2b" CreationDate="2016-11-01T20:29:17.490" UserId="-1" Comment="from http://stackoverflow.com/questions/40197987/why-does-increasing-simplex-noise-dimension-wash-it-out" />
  <row Id="9307" PostHistoryTypeId="2" PostId="4212" RevisionGUID="cde4a173-4eca-4f9b-9e3a-9bff7b56a58c" CreationDate="2016-10-22T23:19:15.147" UserId="5349" Text="I just tried using [this approach][1] to create a tiling 2d simplex noise function with [Gustavson's java implementation][2]. The result tiled, but the texture seemed muddy / washed out. &#xD;&#xA;&#xD;&#xA;I decided to compare the result of using the 2d, 3d &amp; 4d versions to make a 2d texture by holding any 'extra' dimension parameters at zero. The 4d output looked the same as my tiled 2d output. Furthermore, I noticed a trend: as the dimensions increase, the noise starts to drift away from the min &amp; max toward the average. Here are the results along with their histograms:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] [![enter image description here][4]][4] [![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I ran across [this post][6] discussing some artifacts in Gustavson's implementation &amp; wondered if that might be contributing to the problem, so I tried using [OpenSimplex noise][7] instead &amp; got very similar results.&#xD;&#xA;&#xD;&#xA;What's going on here? I'd like to use the 4d simplex noise to make a tiling 2d texture that looks more like the &#xD;&#xA;regular 2d simplex noise. If necessary I can try to massage the output, but that seems like hack &amp; I'd rather &#xD;&#xA;treat the problem rather than the symptoms if possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/questions/23625/how-do-you-generate-tileable-perlin-noise/23639#23639&#xD;&#xA;  [2]: http://staffwww.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java&#xD;&#xA;  [3]: https://i.stack.imgur.com/qOF9n.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/D2JD7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/St0Ha.png&#xD;&#xA;  [6]: https://stackoverflow.com/questions/18885440/why-does-simplex-noise-seem-to-have-more-artifacts-than-classic-perlin-noise&#xD;&#xA;  [7]: https://gist.github.com/KdotJPG/b1270127455a94ac5d19" ContentLicense="CC BY-SA 3.0" />
  <row Id="9308" PostHistoryTypeId="1" PostId="4212" RevisionGUID="cde4a173-4eca-4f9b-9e3a-9bff7b56a58c" CreationDate="2016-10-22T23:19:15.147" UserId="5349" Text="Why does increasing simplex noise dimension wash it out?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9309" PostHistoryTypeId="3" PostId="4212" RevisionGUID="cde4a173-4eca-4f9b-9e3a-9bff7b56a58c" CreationDate="2016-10-22T23:19:15.147" UserId="5349" Text="|image-processing|noise|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9310" PostHistoryTypeId="2" PostId="4213" RevisionGUID="8981b4df-e4c1-48f6-8200-fdab8393ecac" CreationDate="2016-11-01T20:44:49.747" UserId="3470" Text="The easiest way to get the perceived brightness of a color is to calculate the [Luma][1]. Finding the grey color with the same luma is easy - just set all of the RGB components to the desired luma value. That works because the coefficients for calculating the luma sum up to 1.&#xD;&#xA;&#xD;&#xA;    public Vector3d get_equally_bright_grey(Vector3d color) {&#xD;&#xA;        double luma = color.x * 0.299 + color.y * 0.587 + color.z * 0.114;&#xD;&#xA;        return new Vector3d(luma, luma, luma);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Luma_(video)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9311" PostHistoryTypeId="5" PostId="4212" RevisionGUID="20888fa9-63ac-4219-a30e-11895eac49fa" CreationDate="2016-11-01T21:20:35.123" UserId="5349" Comment="clarifying the nature of the question" Text="I just tried using [this approach][1] to create a tiling 2d simplex noise function with [Gustavson's java implementation][2]. The result tiled, but the texture seemed muddy / washed out. &#xD;&#xA;&#xD;&#xA;I decided to compare the result of using the 2d, 3d &amp; 4d versions to make a 2d texture by holding any 'extra' dimension parameters at zero. The 4d output looked the same as my tiled 2d output. Furthermore, I noticed a trend: as the dimensions increase, the noise starts to drift away from the min &amp; max toward the average. Here are the results along with their histograms:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] [![enter image description here][4]][4] [![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I ran across [this post][6] discussing some artifacts in Gustavson's implementation &amp; wondered if that might be contributing to the problem, so I tried using [OpenSimplex noise][7] instead &amp; got very similar results.&#xD;&#xA;&#xD;&#xA;What's going on here? I'd like to use the 4d simplex noise to make a tiling 2d texture that looks more like the &#xD;&#xA;regular 2d simplex noise. If necessary I can try to massage the output, but that seems like hack &amp; I'd rather &#xD;&#xA;treat the problem rather than the symptoms if possible.&#xD;&#xA;&#xD;&#xA;Again, just to clarify, I'm asking: why does the dimensionality seem to affect the final 2D as illustrated?&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/questions/23625/how-do-you-generate-tileable-perlin-noise/23639#23639&#xD;&#xA;  [2]: http://staffwww.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java&#xD;&#xA;  [3]: https://i.stack.imgur.com/qOF9n.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/D2JD7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/St0Ha.png&#xD;&#xA;  [6]: https://stackoverflow.com/questions/18885440/why-does-simplex-noise-seem-to-have-more-artifacts-than-classic-perlin-noise&#xD;&#xA;  [7]: https://gist.github.com/KdotJPG/b1270127455a94ac5d19" ContentLicense="CC BY-SA 3.0" />
  <row Id="9312" PostHistoryTypeId="2" PostId="4214" RevisionGUID="b848d530-c0e0-4e94-96bc-992b55ab108b" CreationDate="2016-11-01T22:00:30.633" UserId="5401" Text="Given an image - such as a simple JPEG of a person or a landscape - is it possible to produce an algorithm that extracts certain visual features from the input image to produce a unique fingerprints of the image.&#xD;&#xA;&#xD;&#xA;Think of this as a hash function (such as MD5) that receives an image as input and produces a digest. However in our scenario the digest/hashing result is not from the byte content but rather form the visual representation of the image. &#xD;&#xA;&#xD;&#xA;An important feature of the visual fingerprint generation is its consistency for different variation of the image. For example the input image could be resized or saved in a different format (e.g., BMP) or with a different compression rate (in the case of JPEG), or with a reduce set of colours (in the case of GIF).&#xD;&#xA;&#xD;&#xA;Is such an algorithm possible to develop?&#xD;&#xA;If so what variations can it cover? &#xD;&#xA;and how accurate such algorithm can become?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9313" PostHistoryTypeId="1" PostId="4214" RevisionGUID="b848d530-c0e0-4e94-96bc-992b55ab108b" CreationDate="2016-11-01T22:00:30.633" UserId="5401" Text="Feature extractions from an image to produce a fingerprint" ContentLicense="CC BY-SA 3.0" />
  <row Id="9314" PostHistoryTypeId="3" PostId="4214" RevisionGUID="b848d530-c0e0-4e94-96bc-992b55ab108b" CreationDate="2016-11-01T22:00:30.633" UserId="5401" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9315" PostHistoryTypeId="2" PostId="4215" RevisionGUID="be00eec8-62dd-46ad-9b38-0ed8c7519407" CreationDate="2016-11-02T01:04:49.687" UserId="5403" Text="I am doing renders of the inside of a room. I would like to show a &quot;bird's eye&quot; view of the room, from above the ceiling (outside the room), but still see the interior of the room.&#xD;&#xA;&#xD;&#xA;[![birds eye view][1]][1]&#xD;&#xA;&#xD;&#xA;An easy way of doing this is to simply hide or remove the ceiling surfaces. However, this has the side effect of reducing the amount of lighting in the scene, because the ceiling no longer reflects light into the room. The top corners and edges of the walls also are no longer lit accurately.&#xD;&#xA;&#xD;&#xA;I would like to render the scene **as if** the ceiling was there, but without the ceiling actually being (directly) visible.&#xD;&#xA;&#xD;&#xA;Is there a name for this problem, a technique, or material?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/F240t.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9316" PostHistoryTypeId="1" PostId="4215" RevisionGUID="be00eec8-62dd-46ad-9b38-0ed8c7519407" CreationDate="2016-11-02T01:04:49.687" UserId="5403" Text="Is there a material that contributes to GI, but isn't directly visible?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9317" PostHistoryTypeId="3" PostId="4215" RevisionGUID="be00eec8-62dd-46ad-9b38-0ed8c7519407" CreationDate="2016-11-02T01:04:49.687" UserId="5403" Text="|lighting|global-illumination|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9318" PostHistoryTypeId="2" PostId="4216" RevisionGUID="440e5d56-1f10-44d1-82cb-911b0c9907ba" CreationDate="2016-11-02T01:31:01.763" UserId="1952" Text="You can use single sided triangles for the ceiling so that they are pointing towards the room. This way the ceiling influences the GI in the room but you can see through it when observing from outside" ContentLicense="CC BY-SA 3.0" />
  <row Id="9320" PostHistoryTypeId="10" PostId="4214" RevisionGUID="a7660502-f930-4515-b15d-8d6be2192e9d" CreationDate="2016-11-02T01:56:41.020" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9321" PostHistoryTypeId="33" PostId="4212" RevisionGUID="5e0a7fd9-99b5-4944-b0a9-566e5a10a222" CreationDate="2016-11-02T02:14:42.327" UserId="231" Comment="22" />
  <row Id="9322" PostHistoryTypeId="5" PostId="4211" RevisionGUID="9cf62947-7564-4bbf-99ba-67dd4e1bc242" CreationDate="2016-11-02T02:20:40.430" UserId="231" Comment="Convert footnotes to links for convenience and to save vertical space" Text="I'm trying to get a **grey** linear-RGB-triple that is equally bright as another (colorful) RGB-triple.&#xD;&#xA;&#xD;&#xA;I have to admit, that there is great confusion for me with all the color stuff, even though I read a lot of wikipedia articles, but I don't really get the big picture. I'm kind of lost and need help.&#xD;&#xA;&#xD;&#xA;Wikipedia seems to mention a formula to receive the [perceived brightness of a linear RGB color][1].  &#xD;&#xA;So I can measure the brightness of my color and do something like this I suppose:&#xD;&#xA;&#xD;&#xA;	public Vector3d get_equally_bright_grey(Vector3d color) {&#xD;&#xA;		for (double c = 0.0; c &lt;= 1.0; c += 0.001) {&#xD;&#xA;			Vector3d grey = new Vector3d(c, c, c);&#xD;&#xA;			if (brightness(color) == brightness(grey)){&#xD;&#xA;				return grey;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;But there has to be something other :)&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;Some context:&#xD;&#xA;&#xD;&#xA;My input colors were spectral distributions that I converted to XYZ values (after [Bruce Lindbloom][2]).&#xD;&#xA;Then I have converted those XYZ values to linear RGB (again with [Bruce][3]). And here comes my question.&#xD;&#xA;&#xD;&#xA;I know that the `Y` component of my `XYZ` triples is also something like the luminance, but I don't know how I generate a grey color XYZ color from this either..&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;[1]: https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;&#xD;&#xA;[2]: http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html&#xD;&#xA;&#xD;&#xA;[3]: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9323" PostHistoryTypeId="5" PostId="4208" RevisionGUID="454d5cb9-c652-4dfe-8650-fe6d9caaf9f6" CreationDate="2016-11-02T02:28:58.640" UserId="231" Comment="Tidying" Text="I'm trying to switch between the rendering of two different scenes as fast as possible using OpenGL.&#xD;&#xA;&#xD;&#xA;For all my OpenGL related stuff I wrote a wrapper-class which provides a quite easy way of adding and updating data. Based on the added data it automatically creates the variable naming for the shader. In the past I always used just one instance of this OpenGL class but now I'm trying to use two of them. (Each instance has its own shader program.)&#xD;&#xA;&#xD;&#xA;When I do something like:&#xD;&#xA;&#xD;&#xA;    OpenGLInstance1.AssignModel(*MyModel1);&#xD;&#xA;&#xD;&#xA;it automatically adds data and writes into the shader code:&#xD;&#xA;&#xD;&#xA;    // per vertex attributes &#xD;&#xA;    layout (location = 0) in vec3	position;&#xD;&#xA;    layout (location = 1) in vec3	normals;&#xD;&#xA;    layout (location = 2) in uvec4	BoneIDs;&#xD;&#xA;    layout (location = 3) in vec4	Weights;&#xD;&#xA;    &#xD;&#xA;    // per instance attributes&#xD;&#xA;    layout (location = 4) in mat4	CameraMatrix;			//dynamic&#xD;&#xA;    layout (location = 8) in mat4	ProjectionMatrix;		//dynamic&#xD;&#xA;&#xD;&#xA;When I try to do this a second time with an other OpenGL-Class instance and Model:&#xD;&#xA;&#xD;&#xA;    OpenGLInstance2.AssignModel(*MyModel2);&#xD;&#xA;&#xD;&#xA;I get:&#xD;&#xA;&#xD;&#xA;    // per vertex attributes &#xD;&#xA;    layout (location = 12) in vec3	position;&#xD;&#xA;    layout (location = 13) in vec3	normals;&#xD;&#xA;    layout (location = 14) in uvec4	BoneIDs;&#xD;&#xA;    layout (location = 15) in vec4	Weights;&#xD;&#xA;    &#xD;&#xA;    // per instance attributes&#xD;&#xA;    layout (location = 16) in mat4	CameraMatrix;			//dynamic&#xD;&#xA;    layout (location = 20) in mat4	ProjectionMatrix;		//dynamic&#xD;&#xA;&#xD;&#xA;But since the GL_MAX_VERTEX_ATTRIBS gives a maximum number of attributes of 16, this is not possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Question 1&#xD;&#xA;Each VAO (vertex array object) has some VBO (vertex buffer object) assigned. Is the location indexing of the VBO just in the scope of each VAO (starting again from zero for each VAO) or is it independent of the VAO?&#xD;&#xA;&#xD;&#xA;### Question 2&#xD;&#xA;Do you have a suggestion how to work around this problem while keeping the implementation as generic, reusable and salable as possible? (Just some general hints, I don't want to bother you with details.)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9324" PostHistoryTypeId="10" PostId="4137" RevisionGUID="7f19c081-4cfc-4216-9c7e-2228e29962c3" CreationDate="2016-11-02T02:45:50.787" UserId="231" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2707,&quot;DisplayName&quot;:&quot;aces&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9325" PostHistoryTypeId="2" PostId="4217" RevisionGUID="b197c302-ca05-48b8-b0d7-2d85712b8fe9" CreationDate="2016-11-02T03:35:03.927" UserId="2654" Text="Each VAO, and shader for that matter, has a separate space of attribute locations. It's perfectly fine to have multiple shaders use the same attribute locations. Indeed, it's a good idea to do so if those attributes conceptually mean the same thing to both shaders.&#xD;&#xA;&#xD;&#xA;A VAO can be used with a shader if that VAO's attribute locations match those the program expects. Well, technically they don't have to match. It's OK if the VAO provides an attribute that a shader doesn't use. [It's more complicated][1] if a VAO doesn't provide an attribute for a location that the shader expects.&#xD;&#xA;&#xD;&#xA;So whatever it is that generates your shader prefix strings and VAOs should not be based on what has been generated for other shaders/VAOs. So if you're going to have attributes increase numerically starting from 0, then this should be the case for each independent shader. It should not be based on some constantly increasing global.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Vertex_Specification#Non-array_attribute_values" ContentLicense="CC BY-SA 3.0" />
  <row Id="9327" PostHistoryTypeId="5" PostId="4208" RevisionGUID="09c88603-545b-431b-a01f-15e6c0dd9c29" CreationDate="2016-11-02T09:33:33.487" UserId="5399" Comment="added 1 character in body" Text="I'm trying to switch between the rendering of two different scenes as fast as possible using OpenGL.&#xD;&#xA;&#xD;&#xA;For all my OpenGL related stuff I wrote a wrapper-class which provides a quite easy way of adding and updating data. Based on the added data it automatically creates the variable naming for the shader. In the past I always used just one instance of this OpenGL class but now I'm trying to use two of them. (Each instance has its own shader program.)&#xD;&#xA;&#xD;&#xA;When I do something like:&#xD;&#xA;&#xD;&#xA;    OpenGLInstance1.AssignModel(*MyModel1);&#xD;&#xA;&#xD;&#xA;it automatically adds data and writes into the shader code:&#xD;&#xA;&#xD;&#xA;    // per vertex attributes &#xD;&#xA;    layout (location = 0) in vec3	position;&#xD;&#xA;    layout (location = 1) in vec3	normals;&#xD;&#xA;    layout (location = 2) in uvec4	BoneIDs;&#xD;&#xA;    layout (location = 3) in vec4	Weights;&#xD;&#xA;    &#xD;&#xA;    // per instance attributes&#xD;&#xA;    layout (location = 4) in mat4	CameraMatrix;			//dynamic&#xD;&#xA;    layout (location = 8) in mat4	ProjectionMatrix;		//dynamic&#xD;&#xA;&#xD;&#xA;When I try to do this a second time with an other OpenGL-Class instance and Model:&#xD;&#xA;&#xD;&#xA;    OpenGLInstance2.AssignModel(*MyModel2);&#xD;&#xA;&#xD;&#xA;I get:&#xD;&#xA;&#xD;&#xA;    // per vertex attributes &#xD;&#xA;    layout (location = 12) in vec3	position;&#xD;&#xA;    layout (location = 13) in vec3	normals;&#xD;&#xA;    layout (location = 14) in uvec4	BoneIDs;&#xD;&#xA;    layout (location = 15) in vec4	Weights;&#xD;&#xA;    &#xD;&#xA;    // per instance attributes&#xD;&#xA;    layout (location = 16) in mat4	CameraMatrix;			//dynamic&#xD;&#xA;    layout (location = 20) in mat4	ProjectionMatrix;		//dynamic&#xD;&#xA;&#xD;&#xA;But since the GL_MAX_VERTEX_ATTRIBS gives a maximum number of attributes of 16, this is not possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Question 1&#xD;&#xA;Each VAO (vertex array object) has some VBO (vertex buffer object) assigned. Is the location indexing of the VBO just in the scope of each VAO (starting again from zero for each VAO) or is it independent of the VAO?&#xD;&#xA;&#xD;&#xA;### Question 2&#xD;&#xA;Do you have a suggestion how to work around this problem while keeping the implementation as generic, reusable and scalable as possible? (Just some general hints, I don't want to bother you with details.)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9328" PostHistoryTypeId="2" PostId="4218" RevisionGUID="59ed4e6e-5518-4f59-a1fe-b3504d286a26" CreationDate="2016-11-02T15:10:39.593" UserId="2372" Text="I think that I got a solution but I would gladly know if there are some optimizations possible.&#xD;&#xA;&#xD;&#xA;My UVs and local coordinates values are corresponding. I mean that they are in the same range value. That said, I can use my XY vertices values for sampling the occlusion texture. The main problem is that the local coordinates are dependent to the rotation of my object which doesn't solve anything...&#xD;&#xA;&#xD;&#xA;To solve that I am converting my local coordinates into world space using a objectToWorld matrix (inverse of current world matrix).&lt;br&gt;&#xD;&#xA;Then I am converting it back into object space using the inverse TRS matrix but without taking into account the rotation of the object.&#xD;&#xA;&#xD;&#xA;It's a bit hacky and I think that I could avoid some steps but this is working.&lt;br&gt;&#xD;&#xA;Any advice is welcome :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9331" PostHistoryTypeId="2" PostId="4219" RevisionGUID="5e318c43-42fd-4cf9-b99d-290174c2814b" CreationDate="2016-11-03T05:38:14.550" UserId="5256" Text="Recently a question that came to my mind was that **How are Physically Based Rendering Techniques researched and developed**? Do people just use current equations by physicists or do they create their own? Hopefully I've explained my question correctly." ContentLicense="CC BY-SA 3.0" />
  <row Id="9332" PostHistoryTypeId="1" PostId="4219" RevisionGUID="5e318c43-42fd-4cf9-b99d-290174c2814b" CreationDate="2016-11-03T05:38:14.550" UserId="5256" Text="How are Physically Based Rendering Methods Researched?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9333" PostHistoryTypeId="3" PostId="4219" RevisionGUID="5e318c43-42fd-4cf9-b99d-290174c2814b" CreationDate="2016-11-03T05:38:14.550" UserId="5256" Text="|rendering|physically-based|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9334" PostHistoryTypeId="2" PostId="4220" RevisionGUID="eabdbf3f-79af-4334-a387-0c783befac76" CreationDate="2016-11-03T06:58:06.073" UserId="5412" Text="Suppose I take multiple 360 photos of a room from various locations but from the same height, is there any image library which can place them relative to each other?&#xD;&#xA;&#xD;&#xA;Ex.&#xD;&#xA;1 - x - 2&#xD;&#xA;x - 3 - x&#xD;&#xA;4 - 5 - x&#xD;&#xA;&#xD;&#xA;If I shot the photos at 1, 2, 3, 4 and 5 is there any algorithm which can correctly place the images relative to each other by just analyzing them?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="9335" PostHistoryTypeId="1" PostId="4220" RevisionGUID="eabdbf3f-79af-4334-a387-0c783befac76" CreationDate="2016-11-03T06:58:06.073" UserId="5412" Text="Place images relative to each other based on where they were shot" ContentLicense="CC BY-SA 3.0" />
  <row Id="9336" PostHistoryTypeId="3" PostId="4220" RevisionGUID="eabdbf3f-79af-4334-a387-0c783befac76" CreationDate="2016-11-03T06:58:06.073" UserId="5412" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9337" PostHistoryTypeId="2" PostId="4221" RevisionGUID="ddbf01ec-ee72-4efd-90b4-b1bfb5320a4c" CreationDate="2016-11-03T08:22:40.817" UserId="5256" Text="How can I make an object give the effect that it is giving out light when it isn't? **I basically want to make an object glow**, for example Neon Lights. Also Area Lights in my engine work properly but to increase how realistic it looks I wanted to give the effect of a haze or glow rather than a flat white rectangle/disk.&#xD;&#xA;&#xD;&#xA;This photo basically shows what I want to do perfectly.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/09CkX.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9338" PostHistoryTypeId="1" PostId="4221" RevisionGUID="ddbf01ec-ee72-4efd-90b4-b1bfb5320a4c" CreationDate="2016-11-03T08:22:40.817" UserId="5256" Text="Emissive Mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="9339" PostHistoryTypeId="3" PostId="4221" RevisionGUID="ddbf01ec-ee72-4efd-90b4-b1bfb5320a4c" CreationDate="2016-11-03T08:22:40.817" UserId="5256" Text="|opengl|lighting|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9340" PostHistoryTypeId="2" PostId="4222" RevisionGUID="5afe1082-fa94-4945-9093-721d121ecd1f" CreationDate="2016-11-03T09:10:03.203" UserId="2817" Text="This effect is called [light bloom][1]. Its algorithm is usually a variation of the following:&#xD;&#xA;&#xD;&#xA; 1. Render your scene (preferably in high dynamic range) to texture.&#xD;&#xA; 2. Make a thresholding pass to another texture. I.e. pixels whose brightness is below a certain (configurable) threshold are are turned down to black.&#xD;&#xA; 3. Downsample and blur the thresholded pixels. Usually, this is done in several &quot;octaves&quot;, i.e. rendering a Gaussian blur with a small kernel to progressively smaller render targets: from full resolution to half resolution, from half to quarter etc.&#xD;&#xA; 4. Composite the downsampled octaves back onto the scene image.&#xD;&#xA;&#xD;&#xA;Both the number of octaves used and the Gaussian blur kernel size affect the end result in terms of visual quality and performance, so you may need to do trade-offs.&#xD;&#xA;&#xD;&#xA;In other words, the glow effect that you seek is usually simply the original scene image, but thresholded and blurred, superimposed back onto the scene image.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bloom_(shader_effect)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9341" PostHistoryTypeId="2" PostId="4223" RevisionGUID="683d25a8-4bfe-41fa-be5a-5824a9df3b60" CreationDate="2016-11-03T10:01:47.817" UserId="137" Text="The most straightforward method of researching physically based lighting is to grab a light and a camera and start taking pictures of an object from all angles when lit from all angles at varying intensities.&#xD;&#xA;&#xD;&#xA;Then plot out the color values and start fitting a function to that 4+ dimensional data." ContentLicense="CC BY-SA 3.0" />
  <row Id="9342" PostHistoryTypeId="2" PostId="4224" RevisionGUID="37329ca9-991b-411c-a323-f8a2c045867e" CreationDate="2016-11-03T10:16:39.090" UserId="5055" Text="I guess physicists, and before that term was used philosophers, have always been thinking about the nature of light, color and shadow. Knowledge about those matters is not purely rooted in people trying to create the ultimate rendering technique for CGI. In [Wikipedia][1] there are whole [categories][2] that show formulas and models that were invented to describe attributes of lighting. What programmers do is to try to combine and fit those models into a probably more simple model that can be implemented in some way. &#xD;&#xA;With the increase in computing power, those models align more and more with the models that were created by physicists to describe lighting in the real world. &#xD;&#xA;If you look into recent (by that i mean 5 years back) papers that describe physically based rendering techniques, you will see that almost all of them base their algorithms on formulas and units of measure that are somehow used to describe real lighting.&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Category:Photometry&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Category:Radiometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="9346" PostHistoryTypeId="2" PostId="4226" RevisionGUID="0e7eba0e-5209-4fad-91d6-06d84cab0736" CreationDate="2016-11-03T19:04:16.233" UserId="3041" Text="I´m looking into uses of high amount of samples in multisampling. If I have an RGBA8 framebuffer and render to it using multisample with many samples, say 32, dithering on per-sample level should yield a reasonably accurate 8-bit color from the 32 samples in 4-bit color when resolved. The spec (4.5) seems a bit scary though (glBlitFrameBuffer): &#xD;&#xA;&#xD;&#xA;&gt; If the read framebuffer is multisampled (its effective value of&#xD;&#xA;&gt; SAMPLE_BUFFERS is one) and the draw framebuffer is not (its value of SAMPLE_BUFFERS is &#xD;&#xA;&gt; zero), **the samples corresponding to each pixel location in the source are converted&#xD;&#xA;&gt; to a single sample before being written to the destination.** filter is&#xD;&#xA;&gt; ignored. If the source formats are integer types or stencil values, a&#xD;&#xA;&gt; single sample’s value is selected for each pixel. If the source&#xD;&#xA;&gt; formats are ﬂoating-point or normalized types, the sample values for&#xD;&#xA;&gt; each pixel are resolved in an implementation-dependent manner. If the&#xD;&#xA;&gt; source formats are depth values, sample values are resolved in an&#xD;&#xA;&gt; implementation-dependent manner where the result will be between the&#xD;&#xA;&gt; minimum and maximum depth values in the pixel.&#xD;&#xA;&#xD;&#xA;What does that even mean? &#xD;&#xA;&#xD;&#xA;Is there a way to do it in a cross implementation defined manner?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9347" PostHistoryTypeId="1" PostId="4226" RevisionGUID="0e7eba0e-5209-4fad-91d6-06d84cab0736" CreationDate="2016-11-03T19:04:16.233" UserId="3041" Text="Can I have lower color bit depth in sample buffer than target framebuffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9348" PostHistoryTypeId="3" PostId="4226" RevisionGUID="0e7eba0e-5209-4fad-91d6-06d84cab0736" CreationDate="2016-11-03T19:04:16.233" UserId="3041" Text="|opengl|rendering|texture|color|subpixel-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9349" PostHistoryTypeId="2" PostId="4227" RevisionGUID="be18d05c-b2a4-47e7-bb6c-2f934adf2d70" CreationDate="2016-11-03T20:05:44.903" UserId="2654" Text="&gt; What does that even mean? &#xD;&#xA;&#xD;&#xA;It means that multisampling is resolved.&#xD;&#xA;&#xD;&#xA;A multisample framebuffer contains multiple samples for each pixel. The combination of samples represents the color of that pixel. The process of converting from multiple samples to a single color is multisample resolving.&#xD;&#xA;&#xD;&#xA;By blitting from a multisampled buffer to a non-multisampled buffer, you are telling OpenGL to resolve each pixel's worth of samples into a single sample. Typically, this is done by adding all the sample values up and dividing by the number of samples, but implementations can take weighted averages or something else, depending on the precise nature of each sample.&#xD;&#xA;&#xD;&#xA;Generally speaking, it's best that you let the implementation do its job.&#xD;&#xA;&#xD;&#xA;&gt; Is there a way to do it in a cross implementation defined manner?&#xD;&#xA;&#xD;&#xA;You can program your own resolution by rendering with a multisample texture to a non-multisampled texture. In the FS, you read each fragment's worth of pixels, doing whatever operation you would like to combine them.&#xD;&#xA;&#xD;&#xA;But that's probably not going to be as fast as letting the hardware do the multisample resolve itself." ContentLicense="CC BY-SA 3.0" />
  <row Id="9354" PostHistoryTypeId="4" PostId="4221" RevisionGUID="bd59c846-81f6-4143-bdd6-64335b2cf17b" CreationDate="2016-11-04T05:55:54.047" UserId="5256" Comment="edited title" Text="Bloom in DirectX" ContentLicense="CC BY-SA 3.0" />
  <row Id="9355" PostHistoryTypeId="2" PostId="4228" RevisionGUID="d1a829e4-3d1a-48e9-a654-307cf648bace" CreationDate="2016-11-04T13:08:01.800" UserId="5256" Text="So currently I want to implement Radiosity in my engine. After figuring out the amount of light that bounces between elements/disks/patches *(I've been told disks are the best correct me if I'm wonrg.*) **how do you bake it into a texture?** Do I set the render target as the size of my texture and modify my  shader to workwith UV coordinates? This is really confusing me so **is there another way?** **Do I even need to bake the light into the textures**, is hardware good enough these days?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9356" PostHistoryTypeId="1" PostId="4228" RevisionGUID="d1a829e4-3d1a-48e9-a654-307cf648bace" CreationDate="2016-11-04T13:08:01.800" UserId="5256" Text="How to bake textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9357" PostHistoryTypeId="3" PostId="4228" RevisionGUID="d1a829e4-3d1a-48e9-a654-307cf648bace" CreationDate="2016-11-04T13:08:01.800" UserId="5256" Text="|texture|physically-based|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9362" PostHistoryTypeId="5" PostId="4228" RevisionGUID="d79e4fdb-c6e0-43f3-b7ff-08cc3bba6376" CreationDate="2016-11-04T15:51:55.893" UserId="231" Comment="mi" Text="So currently I want to implement radiosity in my engine. After figuring out the amount of light that bounces between elements/disks/patches *(I've been told disks are the best - correct me if I'm wrong)* **how do you bake it into a texture?**&#xD;&#xA;&#xD;&#xA;Do I set the render target as the size of my texture and modify my  shader to work with UV coordinates? This is really confusing me so **is there another way?** **Do I even need to bake the light into the textures**, is hardware good enough these days?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9363" PostHistoryTypeId="6" PostId="4228" RevisionGUID="d79e4fdb-c6e0-43f3-b7ff-08cc3bba6376" CreationDate="2016-11-04T15:51:55.893" UserId="231" Comment="mi" Text="|texture|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9366" PostHistoryTypeId="50" PostId="4008" RevisionGUID="48c03e33-d32f-417f-848f-9254d870c27b" CreationDate="2016-11-04T16:07:16.580" UserId="-1" />
  <row Id="9367" PostHistoryTypeId="5" PostId="4220" RevisionGUID="9a0a7995-251f-4d4c-833c-6da47d09ac97" CreationDate="2016-11-04T16:15:16.370" UserId="231" Comment="Correct formatting - multiple lines were displayed as one" Text="Suppose I take multiple 360 photos of a room from various locations but from the same height, is there any image library which can place them relative to each other?&#xD;&#xA;&#xD;&#xA;Ex.  &#xD;&#xA;1 - x - 2  &#xD;&#xA;x - 3 - x  &#xD;&#xA;4 - 5 - x  &#xD;&#xA;&#xD;&#xA;If I shot the photos at 1, 2, 3, 4 and 5 is there any algorithm which can correctly place the images relative to each other by just analyzing them?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9368" PostHistoryTypeId="5" PostId="4220" RevisionGUID="63935034-1f1d-46db-a216-b7f19c3434f9" CreationDate="2016-11-04T16:25:08.310" UserId="231" Comment="Remove request for external resources so the question can avoid being off topic" Text="Suppose I take multiple 360 photos of a room from various locations but from the same height, how can I place them relative to each other?&#xD;&#xA;&#xD;&#xA;Ex.  &#xD;&#xA;1 - x - 2  &#xD;&#xA;x - 3 - x  &#xD;&#xA;4 - 5 - x  &#xD;&#xA;&#xD;&#xA;If I shot the photos at 1, 2, 3, 4 and 5 is there any algorithm which can correctly place the images relative to each other by just analyzing them?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9369" PostHistoryTypeId="10" PostId="4220" RevisionGUID="a74265fc-88f4-4cd6-ad03-5b3750a98381" CreationDate="2016-11-04T16:26:52.713" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9372" PostHistoryTypeId="4" PostId="4228" RevisionGUID="f2d00c7e-ff76-43ac-8836-e33cc2a5641c" CreationDate="2016-11-05T10:05:42.447" UserId="5256" Comment="edited title" Text="How to implement Texture Baking?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9373" PostHistoryTypeId="2" PostId="4230" RevisionGUID="f4712017-db52-4e00-bced-11c03674e00a" CreationDate="2016-11-05T11:59:54.150" UserId="3041" Text="I have thought of a triangle sub-division for the purpose of smooth triangulation (no popping) over time on the fly. I think it is very likely the scheme is already invented and has a name but I can´t seem to find it. Maybe you can help?&#xD;&#xA;&#xD;&#xA;Sub-division is made on triangle edge basis. For each edge longer than a certain threshold, say 1cm on display (i.e. projected space), the edge get two new points a threshold distance (1cm) away from eachother. The edge in between the new points are then complete and need no further sub-division. Up to six new points are thus created from the sub-division, but it could be just one edge making two new points. From the points triangles are formed and the sub-division is performed recursively until all edges are shorter than the threshold.&#xD;&#xA;&#xD;&#xA;Creating two points along the edge a threshold apart is significant for the subdivision to be smooth over time. I don´t see Loop or Catmull Clark doing this.&#xD;&#xA;&#xD;&#xA;I should probably mention I use this succesfully for cartesian meshes in polar projections. Strictly speaking the two points created along an edge may or may not be on the originally projected line.&#xD;&#xA;&#xD;&#xA;So what is it called?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9374" PostHistoryTypeId="1" PostId="4230" RevisionGUID="f4712017-db52-4e00-bced-11c03674e00a" CreationDate="2016-11-05T11:59:54.150" UserId="3041" Text="What is this triangle sub-division scheme called?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9375" PostHistoryTypeId="3" PostId="4230" RevisionGUID="f4712017-db52-4e00-bced-11c03674e00a" CreationDate="2016-11-05T11:59:54.150" UserId="3041" Text="|perspective|triangulation|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9376" PostHistoryTypeId="2" PostId="4231" RevisionGUID="95adc662-5f00-4c69-a4ef-ac6dd8cc0171" CreationDate="2016-11-05T15:17:28.937" UserId="5424" Text="Is it just so you avoid unnecessary divisions or are there other advantages as well?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9377" PostHistoryTypeId="1" PostId="4231" RevisionGUID="95adc662-5f00-4c69-a4ef-ac6dd8cc0171" CreationDate="2016-11-05T15:17:28.937" UserId="5424" Text="Why should you do homogenization after clipping?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9378" PostHistoryTypeId="3" PostId="4231" RevisionGUID="95adc662-5f00-4c69-a4ef-ac6dd8cc0171" CreationDate="2016-11-05T15:17:28.937" UserId="5424" Text="|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9379" PostHistoryTypeId="5" PostId="4231" RevisionGUID="a8143d90-836d-47d5-8ad0-c1c95cb6533c" CreationDate="2016-11-05T16:13:50.733" UserId="5424" Comment="Add further explanation" Text="Is it just so you avoid unnecessary divisions or are there other advantages as well?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;I've just implemented the Sutherland–Hodgman clipping algorithm and read online that you should do homogenization after clipping to avoid divisions and to&#xD;&#xA;&quot;avoid messy special cases&quot;. Now I wanted to ask if someone knows what they mean by &quot;messy special cases&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="9380" PostHistoryTypeId="5" PostId="4231" RevisionGUID="8ad06972-5009-4be1-8561-56bcf1cd577a" CreationDate="2016-11-05T16:38:19.297" UserId="231" Comment="Remove &quot;edit&quot; label as the edit history is available beneath the question" Text="Is it just so you avoid unnecessary divisions or are there other advantages as well?&#xD;&#xA;&#xD;&#xA;I've just implemented the Sutherland–Hodgman clipping algorithm and read online that you should do homogenization after clipping to avoid divisions and to &quot;avoid messy special cases&quot;. Now I wanted to ask if someone knows what they mean by &quot;messy special cases&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="9381" PostHistoryTypeId="2" PostId="4232" RevisionGUID="30028490-2913-4aef-921b-8522605caa26" CreationDate="2016-11-05T17:34:26.580" UserId="48" Text="One good reason to do clipping in homogeneous space is that the perspective division loses the distinction between regions behind the camera and in front of the camera. Points in front of the camera have $w &gt; 0$, and behind the camera $w &lt; 0$. After dividing by $w$, points behind the camera get mapped (with a sign flip) to the same $x, y, z$ NDC space as those in front of the camera. So it is no longer possible to tell the difference; the original sign of $w$ is lost.&#xD;&#xA;&#xD;&#xA;This implies that at least the $w$ clipping must be done in homogeneous space. For instance, triangles that have one vertex behind the camera must get clipped by the $w = 0$ plane to form a quad. Otherwise, you end up with a bizarre object called an &quot;external triangle&quot;—a triangle that appears in two pieces, both extending to infinity, originating from the in-front-of-camera and behind-camera regions of the original homogeneous triangle. &#xD;&#xA;&#xD;&#xA;And I suppose that once you have to apply *one* of the clipping planes in homogeneous space, you might as well apply *all* of them there.&#xD;&#xA;&#xD;&#xA;For further reading on this, here are a couple of good articles:&#xD;&#xA;&#xD;&#xA;1. [In-depth: Software rasterizer and triangle clipping](http://www.gamasutra.com/view/news/168577/Indepth_Software_rasterizer_and_triangle_clipping.php) by Simon Yeung&#xD;&#xA;2. [A trip through the Graphics Pipeline 2011, part 5](https://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/) by Fabian Giesen" ContentLicense="CC BY-SA 3.0" />
  <row Id="9383" PostHistoryTypeId="2" PostId="4233" RevisionGUID="ab75bf6a-bd83-4235-9d7b-2c7db8642563" CreationDate="2016-11-06T04:54:23.463" UserId="1952" Text="Instead of subdividing until reaching certain edge length on screen, you should look into GPU Gems 2 article &quot;[Adaptive Tessellation of Subdivision Surfaces with Displacement Mapping][1]&quot; by Michael Bunnell. It uses edge flatness test to adaptively tessellate the geometry which results in better quality with the same number of triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter07.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9384" PostHistoryTypeId="2" PostId="4234" RevisionGUID="4a5fe5db-dc15-4b75-9b3d-13f03f4ef409" CreationDate="2016-11-06T05:37:19.627" UserId="1952" Text="Yes, you should set the lightmap texture as the render target and use UV-coordinates as vertex position coordinates in your shader to bake lighting into lightmaps. This way you'll write the baked lighting data of triangles into the correct lightmap texels that are used for rendering the triangles on the screen. The UV-map should be unique and no triangles should overlap in the UV-space. The lightmap data needs to be also expanded so that when you later use bilinear filtering to fetch the data from the texture that you don't end up having dark borders following triangle edges at UV seams.&#xD;&#xA;&#xD;&#xA;Instead of baking indirect illumination into surface lightmaps, you could also use volume textures. Nice thing is that the with volume textures you'll have the indirect illumination data available everywhere in the scene and you don't need unique UV-mapping, but you'll also have less resolution due to the added memory usage.&#xD;&#xA;&#xD;&#xA;If you need to bake indirect illumination into textures depends on the complexity of the scene, quality of the lighting and performance/mem usage you want to achieve, so there's no easy answer." ContentLicense="CC BY-SA 3.0" />
  <row Id="9385" PostHistoryTypeId="2" PostId="4235" RevisionGUID="d37a2522-46e2-4be3-92b0-31a9f8ee22d5" CreationDate="2016-11-06T06:32:19.487" UserId="1952" Text="I think you need to split your question into real-time and offline PBR research.&#xD;&#xA;&#xD;&#xA;For real-time PBR it's mostly about finding fast approximations for path traced equivalent. For example we know how to implement area lighting with contact hardening shadows with a simple MC integrator, but finding fast approximation for this is a complex task requiring strong background in mathematics and rendering algorithms/data structures.&#xD;&#xA;&#xD;&#xA;For offline PBR research I think it's partly about understanding optics and limitations of current PBR algorithms and where the two diverges in a significant &amp; meaningful way in the worlds we try to simulate. For example we know that the microfacet model is an approximations of the more complex way light interacts with surfaces, but are there important situations where this approximation fails in a significant way that we would need a better model?&#xD;&#xA;&#xD;&#xA;Also even in offline rendering the performance is an issue, and all kinds of clever mathematical techniques needs to be developed and employed to speed up computations. For example calculating multiple scattering in participating media with brute force path tracing is extremely time consuming and clever techniques are needed to make this computation feasible for movies for example. Or techniques such as importance sampling is developed to reduce the computation in an unbiased way.&#xD;&#xA;&#xD;&#xA;For both real-time and offline PBR research you need sufficient background information in the domain of research and good mathematical/algorithmic toolbox to be able to make any meaningful contribution to the research.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9386" PostHistoryTypeId="2" PostId="4236" RevisionGUID="f1567e51-4139-458c-b55d-7aa62e024897" CreationDate="2016-11-06T08:49:45.003" UserId="5430" Text="I am in the middle of a process of implementation of Fortune's algorithm for a Voronoi diagram generating on a plane. [Here](https://github.com/tomilov/sweepline/blob/develop/sweepline.hpp) the last C++ debug version. Very rarely I catch (visually) such a bugs:&#xD;&#xA;&#xD;&#xA;[![bug][1]][1]&#xD;&#xA;&#xD;&#xA;Debugging process of a geometrical algorithms considered very complex by me. I even don't know which runtime checks (`assert`-ions) should I add to catch this bugs on the fly.&#xD;&#xA;&#xD;&#xA;The question is addressed to those who have tried to implement Fortune's algorithm. I sure, if one faced similar bugs in his implementation somewhere in the middle of a way, then one may remember how to avoid it.&#xD;&#xA;&#xD;&#xA;What is the source of the bug? What is the main corner cases (except rectangle mesh, concentric points, etc) can I face?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q3f2j.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9387" PostHistoryTypeId="1" PostId="4236" RevisionGUID="f1567e51-4139-458c-b55d-7aa62e024897" CreationDate="2016-11-06T08:49:45.003" UserId="5430" Text="Subtle bugs in Fortune's algorithm implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="9388" PostHistoryTypeId="3" PostId="4236" RevisionGUID="f1567e51-4139-458c-b55d-7aa62e024897" CreationDate="2016-11-06T08:49:45.003" UserId="5430" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9389" PostHistoryTypeId="2" PostId="4237" RevisionGUID="782969e9-f84d-4493-b9f9-43c669bbfb6f" CreationDate="2016-11-06T16:58:35.740" UserDisplayName="user2500" Text="GPUs compress multisample data (for bandwidth) and dithering would defeat this - so this is not supported. GPUs also have techniques to sample at higher frequencies than they store values (see QUINCUNX anti aliasing for an example that's been around a while), saving overall memory." ContentLicense="CC BY-SA 3.0" />
  <row Id="9390" PostHistoryTypeId="5" PostId="4233" RevisionGUID="063f8f5c-54cc-4c4e-9dee-35eb5dd34ff2" CreationDate="2016-11-07T04:38:35.347" UserId="1952" Comment="added 394 characters in body; added 6 characters in body" Text="Instead of subdividing until reaching certain edge length on screen, you should look into GPU Gems 2 article &quot;[Adaptive Tessellation of Subdivision Surfaces with Displacement Mapping][1]&quot; by Michael Bunnell. It uses edge flatness test to adaptively tessellate the geometry which results in better quality with the same number of triangles.&#xA;&#xA;With your current adaptive tessellation strategy you'll end up splitting flat surfaces, which unnecessarily increases your triangle count. This is particularly bad on GPU's as it increases quad overdraw for the resulting microtriangles.&#xA;&#xA;About your question for the name of your subdivision scheme, I don't think there is specific name for it but it just falls under more generic &quot;adaptive tessellation&quot;.&#xA;&#xA;[1]: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter07.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9391" PostHistoryTypeId="6" PostId="4236" RevisionGUID="9fbd5910-ad9a-42a7-832c-35d0b842bab4" CreationDate="2016-11-07T06:47:17.437" UserId="5349" Comment="added debugging tag" Text="|computational-geometry|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9392" PostHistoryTypeId="24" PostId="4236" RevisionGUID="9fbd5910-ad9a-42a7-832c-35d0b842bab4" CreationDate="2016-11-07T06:47:17.437" Comment="Proposed by 5349 approved by 5430 edit id of 174" ContentLicense="CC BY-SA 3.0" />
  <row Id="9393" PostHistoryTypeId="5" PostId="1573" RevisionGUID="c75e44ea-da0b-4db0-8ed3-64859f185640" CreationDate="2016-11-07T09:59:51.000" UserId="137" Comment="added 93 characters in body" Text="Nvidia has an [extension for creating command buffers in modern GL][1].&#xD;&#xA;&#xD;&#xA;The reason for the lack of similar functionality is that there is a lot of state involved regarding how to render and the display list be affected by a lot of different state. For example changing the blend state requires patching the fragment shader on some hardware.&#xD;&#xA;&#xD;&#xA;NVidia solved it by capturing *all* state and reseting to the state after a dispatch:&#xD;&#xA;&#xD;&#xA;&gt; 1) What motivates the design?&#xD;&#xA;&gt; &#xD;&#xA;&gt; The primary goal is to be able to reuse pre-validated command buffers.&#xD;&#xA;&gt; Other APIs and proposals have addressed this with various incarnations&#xD;&#xA;&gt; of command  lists or state objects, but a recurring problem is that&#xD;&#xA;&gt; interactions between various stages of the pipeline prevent this&#xD;&#xA;&gt; prevalidation and reuse. These  interactions are often&#xD;&#xA;&gt; hardware-specific (and differ from vendor to vendor  or even&#xD;&#xA;&gt; generation to generation) and new interactions are introduced by  new&#xD;&#xA;&gt; features that were not imagined when the prevalidation scheme was &#xD;&#xA;&gt; proposed.&#xD;&#xA;&gt; &#xD;&#xA;&gt; We attempt to address this by having a monolithic state object that &#xD;&#xA;&gt; encompasses (almost) the entire state of the pipeline. This should&#xD;&#xA;&gt; provide enough information for all implementations to do any needed&#xD;&#xA;&gt; cross- validation. We try to create these in a way that minimizes the&#xD;&#xA;&gt; new API  footprint - since we want ALL state (including any added in&#xD;&#xA;&gt; the future), we just capture it from the current state of the context.&#xD;&#xA;&gt; &#xD;&#xA;&gt; [...]&#xD;&#xA;&gt;&#xD;&#xA;&gt; 23) In what condition is the state left, that is modified by tokens,&#xD;&#xA;&gt; after the dispatch call?&#xD;&#xA;&gt; &#xD;&#xA;&gt; RESOLVED: state is reset.  &#xD;&#xA;&#xD;&#xA;(from the extension text linked above)&#xD;&#xA;&#xD;&#xA;However the true successor is the command buffer functionality in DX12 and vulkan. Those will also capture all render state into a single object to use when creating and filling the command buffer. The NVidia extension is based on that architecture as a result of NVidia's involvement in the Vulkan design.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/opengl/specs/GL_NV_command_list.txt&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9394" PostHistoryTypeId="2" PostId="4238" RevisionGUID="0938c1cf-ac12-430a-9246-61ec42d09d9c" CreationDate="2016-11-07T15:44:53.687" UserId="5430" Text="[This commit](https://github.com/tomilov/sweepline/commit/ed730b9b34a9c8dfabbb89bf33ecd554ed78aa98#diff-5fd4f98b93359557447770c52fd3d651) contains a fix of the bug.&#xD;&#xA;&#xD;&#xA;In short, it is wrong to disable event for second edge, during event checking, when first edge may be truncated sooner then stated by its current associated event." ContentLicense="CC BY-SA 3.0" />
  <row Id="9395" PostHistoryTypeId="5" PostId="4238" RevisionGUID="48da96dd-bbe4-4097-8205-091ce48ef8ed" CreationDate="2016-11-07T15:54:20.837" UserId="5430" Comment="added 2 characters in body" Text="[This commit](https://github.com/tomilov/sweepline/commit/ed730b9b34a9c8dfabbb89bf33ecd554ed78aa98#diff-5fd4f98b93359557447770c52fd3d651) contains the fix of the bug.&#xD;&#xA;&#xD;&#xA;In short, it is wrong to disable event for second edge, during event checking, when first edge may be truncated sooner then stated by its current associated event." ContentLicense="CC BY-SA 3.0" />
  <row Id="9396" PostHistoryTypeId="2" PostId="4239" RevisionGUID="1b932f52-ed00-4c94-94e2-d24086bc3f2f" CreationDate="2016-11-08T00:32:18.173" UserId="5371" Text="I am not sure if this is the right platform to ask this question. Basically, I am an electronic engineer. I am trying to design (personal project) a 3D grphics hardware renderer. It shall only render wireframes at this stage, no filling and no shading, not even backface culling and whatever else we take for granted.&#xD;&#xA;&#xD;&#xA;I understand that the most efficient method to draw line on screen is via Bresenham's integer line drawing algorithm. Provided that I have implemented the algorithm in VHDL and am able to calculate all pixel values for the line one by one, how do I store them into the frame buffer?&#xD;&#xA;&#xD;&#xA;e.g I have 100 lines, I can take say 10 lines and calculate their pixel values in parallel, longer lines will take longer to calculate. Every clock cycle I am able to get the next pixel value for the line, now if I just read 1 byte from memory, overwrite it with the line pixel data and write that byte back and do it for ever pixel for every line, that 1 byte read-write method appears to be rather cumbersome and inefficient. So, do you know how it is worked out how to store data into frame buffer efficiently or do people just use a very fast memory but the actual method is cumbersome and inefficient?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9397" PostHistoryTypeId="1" PostId="4239" RevisionGUID="1b932f52-ed00-4c94-94e2-d24086bc3f2f" CreationDate="2016-11-08T00:32:18.173" UserId="5371" Text="How is data stored into a frame buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9398" PostHistoryTypeId="3" PostId="4239" RevisionGUID="1b932f52-ed00-4c94-94e2-d24086bc3f2f" CreationDate="2016-11-08T00:32:18.173" UserId="5371" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9399" PostHistoryTypeId="2" PostId="4240" RevisionGUID="0d5565c7-ff09-48c4-80c3-8573337fe608" CreationDate="2016-11-08T04:25:58.237" UserId="48" Text="Real GPUs, like CPUs, have a cache hierarchy. So the rasterizer doesn't directly store to memory, but stores into a cache that eventually gets flushed to memory. &#xD;&#xA;&#xD;&#xA;Rasterization will usually have some spatial locality (it will generate writes to nearby pixels close together in time), so if those pixels are in the same cache line it will reduce the overall number of memory transactions. This is more effective for filled polygon rasterization than for lines, but even lines have some locality (especially if multiple nearby lines are being rasterized at once).&#xD;&#xA;&#xD;&#xA;Another trick is to store the framebuffer in a tiled format instead of linearly left-to-right  and top-to-bottom. You'd pick a tile size such as 4×4 or 8×8 and store the pixels in each tile in a contiguous memory block, then make the whole framebuffer out of an array of tiles. This gives you locality in both dimensions, not just one, which improves cache performance. And tiling is easy to do in hardware, as it comes down to just swizzling the order of some X and Y address bits." ContentLicense="CC BY-SA 3.0" />
  <row Id="9400" PostHistoryTypeId="5" PostId="4239" RevisionGUID="cf05933c-0c2f-49da-b40c-4a37979728a2" CreationDate="2016-11-08T11:25:15.453" UserId="231" Comment="Minor typos plus remove redundant intro" Text="I am an electronic engineer. I am trying to design (personal project) a 3D graphics hardware renderer. It shall only render wireframes at this stage, no filling and no shading, not even backface culling and whatever else we take for granted.&#xD;&#xA;&#xD;&#xA;I understand that the most efficient method to draw a line on screen is via Bresenham's integer line drawing algorithm. Provided that I have implemented the algorithm in VHDL and am able to calculate all pixel values for the line one by one, how do I store them into the frame buffer?&#xD;&#xA;&#xD;&#xA;E.g I have 100 lines, I can take say 10 lines and calculate their pixel values in parallel, longer lines will take longer to calculate. Every clock cycle I am able to get the next pixel value for the line, now if I just read 1 byte from memory, overwrite it with the line pixel data and write that byte back and do it for every pixel for every line, that 1 byte read-write method appears to be rather cumbersome and inefficient. So, do you know how it is worked out how to store data into the frame buffer efficiently or do people just use a very fast memory but the actual method is cumbersome and inefficient?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9402" PostHistoryTypeId="2" PostId="4241" RevisionGUID="773e50ca-2ce0-44f4-a79b-2f69dbde7f0c" CreationDate="2016-11-09T01:04:07.590" UserId="2707" Text="In this [webpage][1] from Nvidia, the author(s) seems to imply that you could create a command buffer for each eye on separate threads. However, I don't see the benefit to this over instanced stereo rendering since you must also handle synchronization with multiple command buffers.&#xD;&#xA;&#xD;&#xA;Is there any advantage to using multiple command buffers for stereo rendering compared to instanced stereo rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/engaging-voyage-vulkan" ContentLicense="CC BY-SA 3.0" />
  <row Id="9403" PostHistoryTypeId="1" PostId="4241" RevisionGUID="773e50ca-2ce0-44f4-a79b-2f69dbde7f0c" CreationDate="2016-11-09T01:04:07.590" UserId="2707" Text="Instanced Stereo Rendering vs. Multiple Command Buffers" ContentLicense="CC BY-SA 3.0" />
  <row Id="9404" PostHistoryTypeId="3" PostId="4241" RevisionGUID="773e50ca-2ce0-44f4-a79b-2f69dbde7f0c" CreationDate="2016-11-09T01:04:07.590" UserId="2707" Text="|virtual-reality|vulkan|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9405" PostHistoryTypeId="2" PostId="4242" RevisionGUID="1e9ea136-54d0-4e75-9bcb-4bed9eed6ecf" CreationDate="2016-11-09T01:23:02.577" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="9406" PostHistoryTypeId="1" PostId="4242" RevisionGUID="1e9ea136-54d0-4e75-9bcb-4bed9eed6ecf" CreationDate="2016-11-09T01:23:02.577" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="9407" PostHistoryTypeId="2" PostId="4243" RevisionGUID="7af1d89b-638e-4777-831e-d76d3f6c3352" CreationDate="2016-11-09T01:23:02.577" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="9408" PostHistoryTypeId="1" PostId="4243" RevisionGUID="7af1d89b-638e-4777-831e-d76d3f6c3352" CreationDate="2016-11-09T01:23:02.577" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="9409" PostHistoryTypeId="2" PostId="4244" RevisionGUID="c09f9974-5a9c-472c-b39f-cc3ee3c37f76" CreationDate="2016-11-09T01:32:22.783" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="9410" PostHistoryTypeId="1" PostId="4244" RevisionGUID="c09f9974-5a9c-472c-b39f-cc3ee3c37f76" CreationDate="2016-11-09T01:32:22.783" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="9411" PostHistoryTypeId="2" PostId="4245" RevisionGUID="cd5842a1-333a-4651-975a-56ae7a2ca8ca" CreationDate="2016-11-09T01:32:22.783" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="9412" PostHistoryTypeId="1" PostId="4245" RevisionGUID="cd5842a1-333a-4651-975a-56ae7a2ca8ca" CreationDate="2016-11-09T01:32:22.783" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="9419" PostHistoryTypeId="5" PostId="4242" RevisionGUID="72aacf5d-a1e7-4f6d-92d0-da13dc030a09" CreationDate="2016-11-09T23:18:29.457" UserId="2707" Comment="added 367 characters in body" Text="Common APIs for [GPGPU][1] include [CUDA][2], [OpenCL][3], and [compute shaders][4] (e.g., via DirectX, OpenGL, and Vulkan).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/General-purpose_computing_on_graphics_processing_units&#xD;&#xA;  [2]: https://developer.nvidia.com/cuda-zone&#xD;&#xA;  [3]: https://www.khronos.org/opencl/&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Shader#Compute_shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="9420" PostHistoryTypeId="24" PostId="4242" RevisionGUID="72aacf5d-a1e7-4f6d-92d0-da13dc030a09" CreationDate="2016-11-09T23:18:29.457" Comment="Proposed by 2707 approved by 48, 56 edit id of 175" ContentLicense="CC BY-SA 3.0" />
  <row Id="9421" PostHistoryTypeId="5" PostId="4245" RevisionGUID="79a93881-affb-452b-9b83-aa428969829f" CreationDate="2016-11-09T23:18:41.527" UserId="2707" Comment="added 122 characters in body" Text="For questions related to the rasterization process, both in terms of GPU hardware and algorithms related to rasterization." ContentLicense="CC BY-SA 3.0" />
  <row Id="9422" PostHistoryTypeId="24" PostId="4245" RevisionGUID="79a93881-affb-452b-9b83-aa428969829f" CreationDate="2016-11-09T23:18:41.527" Comment="Proposed by 2707 approved by 48, 56 edit id of 178" ContentLicense="CC BY-SA 3.0" />
  <row Id="9423" PostHistoryTypeId="5" PostId="4243" RevisionGUID="f860d7a5-79eb-449a-b532-9e0d778a5470" CreationDate="2016-11-09T23:18:59.153" UserId="2707" Comment="added 173 characters in body" Text="For questions related to the usage of graphics processing units for computation outside of the traditional graphics pipeline but still somewhat related to computer graphics." ContentLicense="CC BY-SA 3.0" />
  <row Id="9424" PostHistoryTypeId="24" PostId="4243" RevisionGUID="f860d7a5-79eb-449a-b532-9e0d778a5470" CreationDate="2016-11-09T23:18:59.153" Comment="Proposed by 2707 approved by 48, 56 edit id of 176" ContentLicense="CC BY-SA 3.0" />
  <row Id="9425" PostHistoryTypeId="5" PostId="4244" RevisionGUID="ee13c3c8-67e0-48e3-a792-1904b7fdae78" CreationDate="2016-11-09T23:19:08.257" UserId="2707" Comment="added 283 characters in body" Text="[Rasterization][1] is the process of turning shapes into fragments. This is commonly done through [ROPs][2] (hardware), but it can be accomplished through software as well.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rasterisation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Render_output_unit" ContentLicense="CC BY-SA 3.0" />
  <row Id="9426" PostHistoryTypeId="24" PostId="4244" RevisionGUID="ee13c3c8-67e0-48e3-a792-1904b7fdae78" CreationDate="2016-11-09T23:19:08.257" Comment="Proposed by 2707 approved by 48, 56 edit id of 177" ContentLicense="CC BY-SA 3.0" />
  <row Id="9427" PostHistoryTypeId="34" PostId="4212" RevisionGUID="48a13bf8-1ea4-41c0-a0c9-f330510ed53a" CreationDate="2016-11-10T03:41:09.360" UserId="-1" Comment="22" />
  <row Id="9428" PostHistoryTypeId="2" PostId="4247" RevisionGUID="5710dd8b-63fb-483c-b488-600a9df2c3ba" CreationDate="2016-11-10T07:33:13.057" UserId="5256" Text="I have begun learning how to create a Ray Tracer and 1 thing I am confused about is **how the pixel color from a Ray Tracer is stored into an image**. Do we use `SetPixel` for a Bitmap? Do we use a third party library like [libpng?][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.libpng.org/pub/png/libpng.html&#xD;&#xA;&#xD;&#xA;Most tutorials don't really explain this well online, so if anyone can explain what the most common method for this is that would be great." ContentLicense="CC BY-SA 3.0" />
  <row Id="9429" PostHistoryTypeId="1" PostId="4247" RevisionGUID="5710dd8b-63fb-483c-b488-600a9df2c3ba" CreationDate="2016-11-10T07:33:13.057" UserId="5256" Text="How are the colors for each pixel from a Ray Tracer stored in an Image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9430" PostHistoryTypeId="3" PostId="4247" RevisionGUID="5710dd8b-63fb-483c-b488-600a9df2c3ba" CreationDate="2016-11-10T07:33:13.057" UserId="5256" Text="|raytracing|c++|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9431" PostHistoryTypeId="2" PostId="4248" RevisionGUID="764b3648-a8ec-468f-b42b-01a629dd7593" CreationDate="2016-11-10T07:44:03.043" UserId="5256" Text="After reading a few articles online I am can confidently say I am clueless on **how Anti Aliasing works when Ray Tracing**.&#xD;&#xA;&#xD;&#xA;All I understand is that **A Single Pixel/Ray is split into 4 sub pixels and 4 rays rather than 1**.&#xD;&#xA;&#xD;&#xA;Could somebody please explain how this is done (preferably with code)? " ContentLicense="CC BY-SA 3.0" />
  <row Id="9432" PostHistoryTypeId="1" PostId="4248" RevisionGUID="764b3648-a8ec-468f-b42b-01a629dd7593" CreationDate="2016-11-10T07:44:03.043" UserId="5256" Text="How is Anti Aliasing Implemented in Ray Tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9433" PostHistoryTypeId="3" PostId="4248" RevisionGUID="764b3648-a8ec-468f-b42b-01a629dd7593" CreationDate="2016-11-10T07:44:03.043" UserId="5256" Text="|raytracing|antialiasing|pixels|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9434" PostHistoryTypeId="2" PostId="4249" RevisionGUID="26223420-0eb0-4700-a827-4b03fd6960c7" CreationDate="2016-11-10T09:40:12.813" UserId="137" Text="It doesn't matter. All that matters is that you can store information per pixel. &#xD;&#xA;&#xD;&#xA;In most cases this means allocating a `x*y` array of `int`s (for 3 byte-sized channels of RGB) to store the pixel values and then feed it into your image compression library of choice to save it out to disk." ContentLicense="CC BY-SA 3.0" />
  <row Id="9435" PostHistoryTypeId="2" PostId="4250" RevisionGUID="4645058b-e1b5-4da8-9dc9-2eb681863a18" CreationDate="2016-11-10T11:28:06.017" UserId="2941" Text="Do you use MFC? If so, here's a code snippet to write a red gradient image using MFC's CImage. The top of the image is redder. Because [height is positive][1], it's a [bottom-up DIB][2] and higher values of y (in GetPixelAddress()) point to earlier scanlines (i.e. lower in the image):&#xD;&#xA;&#xD;&#xA;		const unsigned int imageWidth = 100;&#xD;&#xA;		const unsigned int imageHeight = 255;&#xD;&#xA;		CImage img;&#xD;&#xA;		img.Create(imageWidth,imageHeight,24,0);&#xD;&#xA;		for(unsigned int x = 0; x &lt; imageWidth; ++x)&#xD;&#xA;		{&#xD;&#xA;			for(unsigned int y = 0; y &lt; imageHeight; ++y)&#xD;&#xA;			{&#xD;&#xA;				unsigned char* pixelP = static_cast&lt;unsigned char*&gt;(img.GetPixelAddress(x,imageHeight - 1 - y));&#xD;&#xA;				pixelP[0] = 0;&#xD;&#xA;				pixelP[1] = 0;&#xD;&#xA;				pixelP[2] = y;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		HRESULT hr = img.Save(&quot;c:\\red.bmp&quot;,Gdiplus::ImageFormatBMP);&#xD;&#xA;&#xD;&#xA;There's many image formats, and many different ways to do this. I'll probably migrate away from CImage at some future point...&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/library/52861e3d-bf7e-481f-a240-90e88f76c490.aspx#cimage__create&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd407212(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="9436" PostHistoryTypeId="5" PostId="4250" RevisionGUID="9e65f845-7b04-4c1e-bb10-726d1883f973" CreationDate="2016-11-10T11:39:00.527" UserId="2941" Comment="Note about BGR, not RGB" Text="Do you use MFC? If so, here's a code snippet to write a red gradient image using MFC's CImage. The top of the image is redder. Because [height is positive][1], it's a [bottom-up DIB][2] and higher values of y (in GetPixelAddress()) point to earlier scanlines (i.e. lower in the image):&#xD;&#xA;&#xD;&#xA;		const unsigned int imageWidth = 100;&#xD;&#xA;		const unsigned int imageHeight = 255;&#xD;&#xA;		CImage img;&#xD;&#xA;		img.Create(imageWidth,imageHeight,24,0);&#xD;&#xA;		for(unsigned int x = 0; x &lt; imageWidth; ++x)&#xD;&#xA;		{&#xD;&#xA;			for(unsigned int y = 0; y &lt; imageHeight; ++y)&#xD;&#xA;			{&#xD;&#xA;				// Note BGR, not RGB!&#xD;&#xA;				unsigned char* pixelP = static_cast&lt;unsigned char*&gt;(img.GetPixelAddress(x,imageHeight - 1 - y));&#xD;&#xA;				pixelP[0] = 0;&#xD;&#xA;				pixelP[1] = 0;&#xD;&#xA;				pixelP[2] = y;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		HRESULT hr = img.Save(&quot;c:\\red.bmp&quot;,Gdiplus::ImageFormatBMP);&#xD;&#xA;&#xD;&#xA;There's many image formats, and many different ways to do this. I'll probably migrate away from CImage at some future point...&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/library/52861e3d-bf7e-481f-a240-90e88f76c490.aspx#cimage__create&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd407212(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="9437" PostHistoryTypeId="2" PostId="4251" RevisionGUID="6ebbba1e-d389-40d7-8d0e-94d95299ce1b" CreationDate="2016-11-10T12:11:49.883" UserId="5364" Text="I think it's safe to say that there are two different ways of doing AA in raytracing:&#xD;&#xA;&#xD;&#xA;1: if you have the final image and the depth image it is possible to apply almost all existing techniques that are used in games (FXAA, etc) Those work directly on the final image and are not related to raytracing&#xD;&#xA;&#xD;&#xA;2: the second method is to take into account multiple rays for each pixel and then averaging the result. For a very simple version think of it like this:&#xD;&#xA;&#xD;&#xA;- you render first an image of size 1024x1024, one ray for each pixel (for example)&#xD;&#xA;- after rendering, you scale the image to 512x512 (each 4 pixels are avereged into one) and you can notice that the edges are smoother. This way you have effectively used 4 rays for each pixel in the final image of 512x512 size.&#xD;&#xA;&#xD;&#xA;There are other variations on this method. For example you can adapt the number of samples for pixels that are right at the edge of the geometry meaning that for some pixels you will have only 4 samples , and for others 16. &#xD;&#xA;&#xD;&#xA;Check the links in the comments above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9438" PostHistoryTypeId="2" PostId="4252" RevisionGUID="6d7b21cd-521b-4f85-b8a3-99c27c8bc443" CreationDate="2016-11-10T14:31:59.117" UserId="1952" Text="Depends if you are talking about CPU or GPU ray tracer. For CPU you generally simply allocate an array of width * height float4's (i.e. for RGB &amp; alpha) and for GPU you allocate a texture (e.g. R16G16B16A16F or R32G32B32A32F format). It depends on your case if you really need the alpha though. The target on CPU is then simply accessed by image[(x+y*width)*4] (image=float array), and on GPU image[uint2(x, y)] (image=UAV).&#xD;&#xA;&#xD;&#xA;You generally want this target to be a float format (16-bit or 32-bit) to be able to handle high dynamic range (HDR) of luminance in the scene (think of a scene illuminated by Sun = ~100,000 Lux vs Moon = ~1 Lux), that gets then [exposed][1] using camera settings, [tone mapped][2] and converted to [sRGB space][3] to be viewable on regular 8bpc devices.&#xD;&#xA;&#xD;&#xA;If you are with a very strict with memory budget, you may allocate LDR target (e.g. R8G8B8A8_UNORM) and perform camera exposure, tone mapping &amp; sRGB conversion before writing the result to the render target. This has bunch of issues though, e.g. you would need the camera exposure value prior to rendering, which can be a challenge for camera auto-exposure, so it's generally adviced to use HDR target instead.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Exposure_value&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Tone_mapping&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/SRGB" ContentLicense="CC BY-SA 3.0" />
  <row Id="9439" PostHistoryTypeId="2" PostId="4253" RevisionGUID="fa92abf5-8dee-4266-a711-9c4d77f15a75" CreationDate="2016-11-10T15:24:37.807" UserId="182" Text="Let's suppose a fairly typical raytracing main loop:&#xD;&#xA;&#xD;&#xA;    struct Ray&#xD;&#xA;    {&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    RGBColor* image = CreateImageBuffer(width, height);&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            float x = (float)i / (float)max(width, height);&#xD;&#xA;            float y = (float)j / (float)max(width, height);&#xD;&#xA;&#xD;&#xA;            vec3 dir = normalize(vec3(x, y, -tanHalfFov));&#xD;&#xA;            Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;            image[width * j + i] = ComputeColor(r);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;One possible modification of it to do 4 samples MSAA would be:&#xD;&#xA;&#xD;&#xA;    float jitterMatrix[4 * 2] = {&#xD;&#xA;        -1.0/4.0,  3.0/4.0,&#xD;&#xA;         3.0/4.0,  1.0/3.0,&#xD;&#xA;        -3.0/4.0, -1.0/4.0,&#xD;&#xA;         1.0/4.0, -3.0/4.0,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            // Init the pixel to 100% black (no light).&#xD;&#xA;            image[width * j + i] = RGBColor(0.0);&#xD;&#xA;&#xD;&#xA;            // Accumulate light for N samples.&#xD;&#xA;            for (int sample = 0; sample &lt; 4; ++sample)&#xD;&#xA;            {&#xD;&#xA;                float x = (i + jitterMatrix[2*sample]) / (float)max(width, height);&#xD;&#xA;                float y = (i + jitterMatrix[2*sample+1]) / (float)max(width, height);&#xD;&#xA;&#xD;&#xA;                vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);&#xD;&#xA;                Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;                image[width * j + i] += ComputeColor(r);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Get the average.&#xD;&#xA;            image[width * j + i] /= 4.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Another possibility is to do a random jitter (instead of the matrix based one above), but you then soon enter the realm of signal processing and it takes a lot of reading to know how to choose a good noise function.&#xD;&#xA;&#xD;&#xA;P.S.: I wrote the code above on the fly, so I'd expect a few errors in it. It's only meant to show the basic idea." ContentLicense="CC BY-SA 3.0" />
  <row Id="9440" PostHistoryTypeId="5" PostId="4253" RevisionGUID="6b05eae8-597b-484d-a9aa-911fc03dd8ba" CreationDate="2016-11-10T15:30:29.193" UserId="182" Comment="Added explanation of why MSAA." Text="Let's suppose a fairly typical raytracing main loop:&#xD;&#xA;&#xD;&#xA;    struct Ray&#xD;&#xA;    {&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    RGBColor* image = CreateImageBuffer(width, height);&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            float x = (float)i / (float)max(width, height);&#xD;&#xA;            float y = (float)j / (float)max(width, height);&#xD;&#xA;&#xD;&#xA;            vec3 dir = normalize(vec3(x, y, -tanHalfFov));&#xD;&#xA;            Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;            image[width * j + i] = ComputeColor(r);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;One possible modification of it to do 4 samples MSAA would be:&#xD;&#xA;&#xD;&#xA;    float jitterMatrix[4 * 2] = {&#xD;&#xA;        -1.0/4.0,  3.0/4.0,&#xD;&#xA;         3.0/4.0,  1.0/3.0,&#xD;&#xA;        -3.0/4.0, -1.0/4.0,&#xD;&#xA;         1.0/4.0, -3.0/4.0,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            // Init the pixel to 100% black (no light).&#xD;&#xA;            image[width * j + i] = RGBColor(0.0);&#xD;&#xA;&#xD;&#xA;            // Accumulate light for N samples.&#xD;&#xA;            for (int sample = 0; sample &lt; 4; ++sample)&#xD;&#xA;            {&#xD;&#xA;                float x = (i + jitterMatrix[2*sample]) / (float)max(width, height);&#xD;&#xA;                float y = (i + jitterMatrix[2*sample+1]) / (float)max(width, height);&#xD;&#xA;&#xD;&#xA;                vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);&#xD;&#xA;                Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;                image[width * j + i] += ComputeColor(r);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Get the average.&#xD;&#xA;            image[width * j + i] /= 4.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Another possibility is to do a random jitter (instead of the matrix based one above), but you then soon enter the realm of signal processing and it takes a lot of reading to know how to choose a good noise function.&#xD;&#xA;&#xD;&#xA;The idea remains the same though: consider the pixel to represent a tiny square area, and instead of shooting only one ray that passes through the center of the pixel, shoot many rays covering the entire pixel area. The more dense the ray distribution is, the better signal you get.&#xD;&#xA;&#xD;&#xA;P.S.: I wrote the code above on the fly, so I'd expect a few errors in it. It's only meant to show the basic idea." ContentLicense="CC BY-SA 3.0" />
  <row Id="9441" PostHistoryTypeId="2" PostId="4254" RevisionGUID="46f7ee52-5752-4df1-8426-d3244ea7ef29" CreationDate="2016-11-10T17:15:01.400" UserId="56" Text="Raxvan is completely right that &quot;traditional&quot; anti aliasing techniques will work in raytracing, including those that use information such as depth to do antialiasing.  You could even do temporal anti aliasing in ray tracing for instance.&#xD;&#xA;&#xD;&#xA;Julien expanded on Raxvan's 2nd item which was an explanation of super sampling, and showed how you'd actually do that, also mentioning that you can randomize the location of the pixels but then you are entering signal processing country which is a lot deeper, and it definitely is!&#xD;&#xA;&#xD;&#xA;As Julien said, if you want to do $N$ samples per pixel, you can break the pixel up into $N$ evenly distributed sample points (on a grid basically) and average those samples.&#xD;&#xA;&#xD;&#xA;If you do that, you can still get aliasing though.  It is better than NOT doing it, because you are increasing your sampling rate, so will be able to handle higher frequency data (aka smaller details), but it can still cause aliasing.&#xD;&#xA;&#xD;&#xA;If you instead take $N$ random samples within a pixel, you are effectively trading aliasing for noise.  Noise is easier on the eyes and looks more natural than aliasing, so is the preferred result usually.  I believe it's even provably the ideal situation with higher sample counts but don't have more info on that ):&#xD;&#xA;&#xD;&#xA;When you use just &quot;regular&quot; random numbers like you'd get from rand() or std::uniform_int_distribution, that is called &quot;white noise&quot; because it contains all frequencies, like how white light is made up of all other colors (frequencies) of light.&#xD;&#xA;&#xD;&#xA;Using white noise to randomize the samples within a pixel has the problem that sometimes your samples will clump together.  For instance, if you average 100 samples in a pixel, but they ALL end up being in the upper left corner of the pixel, you aren't going to get ANY information about the other parts of the pixel, so your final resulting pixel color will be missing information about what color it should be.&#xD;&#xA;&#xD;&#xA;A better approach is to use something called blue noise which only contains high frequency components (like how blue light is high frequency light).&#xD;&#xA;&#xD;&#xA;The benefit of blue noise is that you get even coverage over the pixel, like you get with a uniform sampling grid, but, you still get some randomness, which turns aliasing into noise and gives you a better looking image.&#xD;&#xA;&#xD;&#xA;Unfortunately, blue noise can be very costly to compute, and the best methods all seem to be patented (what the heck?!), but one way to do this, invented by pixar (and patented too i think but not 100% sure) is to make an even grid of sample points, then randomly offset each sample point a small amount - like a random amount between plus or minus half the width and height of the sampling grid.  This way you get a sort of blue noise sampling for pretty cheap.&#xD;&#xA;&#xD;&#xA;Note that this is also called stratified sampling, and poisson disk sampling is a form of this, which is also a way of generating blue noise:&#xD;&#xA;https://www.jasondavies.com/poisson-disc/&#xD;&#xA;&#xD;&#xA;If you are interested in going deeper you probably will also want to check out this question and answer!&#xD;&#xA;&#xD;&#xA;http://computergraphics.stackexchange.com/questions/4013/what-is-the-fundamental-reasoning-for-anti-aliasing-using-multiple-random-sample&#xD;&#xA;&#xD;&#xA;Lastly, this stuff is starting to stray into the realm of monte carlo path tracing which is the common method for doing photorealistic raytracing.  if you are interested in learning more about that, give this a read!&#xD;&#xA;&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9442" PostHistoryTypeId="5" PostId="4253" RevisionGUID="e28806a6-dec9-418b-8207-301ebf995779" CreationDate="2016-11-10T17:38:30.687" UserId="182" Comment="Changed x and y from [0..1] to [-1..1]; added syntax highlighting." Text="Let's suppose a fairly typical raytracing main loop:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    struct Ray&#xD;&#xA;    {&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    RGBColor* image = CreateImageBuffer(width, height);&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            float x = 2.0 * (float)i / (float)max(width, height) - 1.0;&#xD;&#xA;            float y = 2.0 * (float)j / (float)max(width, height) - 1.0;&#xD;&#xA;&#xD;&#xA;            vec3 dir = normalize(vec3(x, y, -tanHalfFov));&#xD;&#xA;            Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;            image[width * j + i] = ComputeColor(r);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;One possible modification of it to do 4 samples MSAA would be:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    float jitterMatrix[4 * 2] = {&#xD;&#xA;        -1.0/4.0,  3.0/4.0,&#xD;&#xA;         3.0/4.0,  1.0/3.0,&#xD;&#xA;        -3.0/4.0, -1.0/4.0,&#xD;&#xA;         1.0/4.0, -3.0/4.0,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            // Init the pixel to 100% black (no light).&#xD;&#xA;            image[width * j + i] = RGBColor(0.0);&#xD;&#xA;&#xD;&#xA;            // Accumulate light for N samples.&#xD;&#xA;            for (int sample = 0; sample &lt; 4; ++sample)&#xD;&#xA;            {&#xD;&#xA;                float x = 2.0 * (i + jitterMatrix[2*sample]) / (float)max(width, height) - 1.0;&#xD;&#xA;                float y = 2.0 * (i + jitterMatrix[2*sample+1]) / (float)max(width, height) - 1.0;&#xD;&#xA;&#xD;&#xA;                vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);&#xD;&#xA;                Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;                image[width * j + i] += ComputeColor(r);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Get the average.&#xD;&#xA;            image[width * j + i] /= 4.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Another possibility is to do a random jitter (instead of the matrix based one above), but you then soon enter the realm of signal processing and it takes a lot of reading to know how to choose a good noise function.&#xD;&#xA;&#xD;&#xA;The idea remains the same though: consider the pixel to represent a tiny square area, and instead of shooting only one ray that passes through the center of the pixel, shoot many rays covering the entire pixel area. The more dense the ray distribution is, the better signal you get.&#xD;&#xA;&#xD;&#xA;P.S.: I wrote the code above on the fly, so I'd expect a few errors in it. It's only meant to show the basic idea." ContentLicense="CC BY-SA 3.0" />
  <row Id="9443" PostHistoryTypeId="5" PostId="4254" RevisionGUID="64f9e126-2b00-4c1f-8a44-b48aa2391239" CreationDate="2016-11-10T17:46:43.577" UserId="56" Comment="added 18 characters in body" Text="Raxvan is completely right that &quot;traditional&quot; anti aliasing techniques will work in raytracing, including those that use information such as depth to do antialiasing.  You could even do temporal anti aliasing in ray tracing for instance.&#xD;&#xA;&#xD;&#xA;Julien expanded on Raxvan's 2nd item which was an explanation of super sampling, and showed how you'd actually do that, also mentioning that you can randomize the location of the samples within the pixel but then you are entering signal processing country which is a lot deeper, and it definitely is!&#xD;&#xA;&#xD;&#xA;As Julien said, if you want to do $N$ samples per pixel, you can break the pixel up into $N$ evenly distributed sample points (on a grid basically) and average those samples.&#xD;&#xA;&#xD;&#xA;If you do that, you can still get aliasing though.  It is better than NOT doing it, because you are increasing your sampling rate, so will be able to handle higher frequency data (aka smaller details), but it can still cause aliasing.&#xD;&#xA;&#xD;&#xA;If you instead take $N$ random samples within a pixel, you are effectively trading aliasing for noise.  Noise is easier on the eyes and looks more natural than aliasing, so is the preferred result usually.  I believe it's even provably the ideal situation with higher sample counts but don't have more info on that ):&#xD;&#xA;&#xD;&#xA;When you use just &quot;regular&quot; random numbers like you'd get from rand() or std::uniform_int_distribution, that is called &quot;white noise&quot; because it contains all frequencies, like how white light is made up of all other colors (frequencies) of light.&#xD;&#xA;&#xD;&#xA;Using white noise to randomize the samples within a pixel has the problem that sometimes your samples will clump together.  For instance, if you average 100 samples in a pixel, but they ALL end up being in the upper left corner of the pixel, you aren't going to get ANY information about the other parts of the pixel, so your final resulting pixel color will be missing information about what color it should be.&#xD;&#xA;&#xD;&#xA;A better approach is to use something called blue noise which only contains high frequency components (like how blue light is high frequency light).&#xD;&#xA;&#xD;&#xA;The benefit of blue noise is that you get even coverage over the pixel, like you get with a uniform sampling grid, but, you still get some randomness, which turns aliasing into noise and gives you a better looking image.&#xD;&#xA;&#xD;&#xA;Unfortunately, blue noise can be very costly to compute, and the best methods all seem to be patented (what the heck?!), but one way to do this, invented by pixar (and patented too i think but not 100% sure) is to make an even grid of sample points, then randomly offset each sample point a small amount - like a random amount between plus or minus half the width and height of the sampling grid.  This way you get a sort of blue noise sampling for pretty cheap.&#xD;&#xA;&#xD;&#xA;Note that this is a form of stratified sampling, and poisson disk sampling is a form of that too, which is also a way of generating blue noise:&#xD;&#xA;https://www.jasondavies.com/poisson-disc/&#xD;&#xA;&#xD;&#xA;If you are interested in going deeper you probably will also want to check out this question and answer!&#xD;&#xA;&#xD;&#xA;http://computergraphics.stackexchange.com/questions/4013/what-is-the-fundamental-reasoning-for-anti-aliasing-using-multiple-random-sample&#xD;&#xA;&#xD;&#xA;Lastly, this stuff is starting to stray into the realm of monte carlo path tracing which is the common method for doing photorealistic raytracing.  if you are interested in learning more about that, give this a read!&#xD;&#xA;&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9444" PostHistoryTypeId="2" PostId="4255" RevisionGUID="23292f24-a244-4461-8769-5b2f5df02852" CreationDate="2016-11-10T20:08:26.250" UserId="5458" Text="I'm a software engineer and although I currently don't work on anything related to computer graphics, I understand I understand how downscaling works, what I don't understand is why most modern games default to over 100% on my computer (GTX 1080, 1080p@144Hz monitor). For instance, Overwatch defaults to 140% render scale, which translates into a huge performance hit (stable 144 vs 60~80 fps). Why is the game doing this? I understand that downscaling makes the quality of the image a bit better, but this doesn't justify that performance hit. I read in some places that downscaling also helps to reduce some graphics artifacts, can someone please elaborate on this? I would like to know what are the benefits of downscaling and why modern games are defaulting to settings above 100%." ContentLicense="CC BY-SA 3.0" />
  <row Id="9445" PostHistoryTypeId="1" PostId="4255" RevisionGUID="23292f24-a244-4461-8769-5b2f5df02852" CreationDate="2016-11-10T20:08:26.250" UserId="5458" Text="What are the benefits of downscaling on modern games?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9446" PostHistoryTypeId="3" PostId="4255" RevisionGUID="23292f24-a244-4461-8769-5b2f5df02852" CreationDate="2016-11-10T20:08:26.250" UserId="5458" Text="|rendering|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9447" PostHistoryTypeId="2" PostId="4256" RevisionGUID="d6ddb400-5be9-4240-8681-ca15d5e753ea" CreationDate="2016-11-10T20:25:14.683" UserId="2654" Text="Yes, there are advantages. You can render different command buffers to *different queues.*&#xD;&#xA;&#xD;&#xA;Modern NVIDIA hardware, in particular, offers a full *sixteen* separate queues that are capable of rendering independent graphics operations. By putting each eye in a separate queue, you may be able to use the available hardware resources more efficiently.&#xD;&#xA;&#xD;&#xA;Then again, it may not. It all really depends on how things work out down in the lowest levels of hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="9448" PostHistoryTypeId="2" PostId="4257" RevisionGUID="88efc0ab-2206-4a80-ac5c-937bf283b617" CreationDate="2016-11-10T21:39:05.430" UserId="2817" Text="What you are describing is [supersampling][1], a technique for combating aliasing (a.k.a. jaggies), which is [a term from signal theory][2] that also applies to graphics. It's a spatial domain approach. Basically it means that the sampling resolution (render target pixels in this case) makes signals with different frequencies be reconstructed as the same frequency. Or, in other words, the scene is sampled too infrequently for sub-pixel detail to be properly represented.&#xD;&#xA;&#xD;&#xA;It is especially prevalent in modern games since the recent advances in GPU computing power have made that quality/performance tradeoff (that you deem unjustified, but unless we're talking VR, everything above 60 FPS is just buttery-smooth and undistinguishable) even possible, and because the (fairly) recently introduced physically-based shading models are much more susceptible to aliasing from sources other than just undersampled geometry: a group of artifacts collectively called **shading aliasing**, with specular aliasing (a.k.a. fireflies) being especially visible. Epic Games' Brian Karis explains some of that in the opening of [his presentation on temporal AA in UE4][3] (temporal AA is just another approach to anti-aliasing, one that distributes samples in time instead of space).&#xD;&#xA;&#xD;&#xA;**To sum up:** it's the **brute force approach to fixing aliasing**. An anti-aliasing technique that simply captures more samples of the scene, and thus captures more sub-pixel detail that would otherwise be lost.&#xD;&#xA;&#xD;&#xA;It is also worth mentioning that while it appears superficially similar to [Multi-Sampled Anti-Aliasing][4], it differs in the sampling pattern (SSAA simply increases the pixel grid density, whereas MSAA has a sort of sheared grid pattern) and the sampled signal resolution (SSAA is a full colour capture, MSAA cheats slightly by sampling triangle coverage more finely than colour).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Supersampling&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Aliasing&#xD;&#xA;  [3]: https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Multisample_anti-aliasing" ContentLicense="CC BY-SA 3.0" />
  <row Id="9449" PostHistoryTypeId="5" PostId="4241" RevisionGUID="6a60f070-1eab-4bcd-b4b9-09065368a7c4" CreationDate="2016-11-11T02:48:55.613" UserId="2707" Comment="Clarified my line of thinking and edited according to a comment." Text="#Source&#xD;&#xA;&#xD;&#xA;In this [webpage][1] from Nvidia, the author(s) seems to imply that you could create a command buffer for each eye on separate threads. However, I don't see the benefit to this over instanced stereo rendering since you must also handle synchronization with multiple command buffers.&#xD;&#xA;&#xD;&#xA;#Possible Synchronization Issues&#xD;&#xA;&#xD;&#xA;For synchronization (feel free to correct me if I'm wrong), I was thinking about when using a framebuffer for each eye, kind of the &quot;naive&quot; way of rendering for VR. I suppose though you could just render to one framebuffer like with stereo instanced rendering. Regardless, the issue with synchronization that I'm concerned about would be if one eye finishes considerably faster than the other eye. It seems that with stereo instanced rendering, this would be less likely to happen since the workload is more divisible. The other issue I see where synchronization could cause a performance hit is that you must wait for both threads to complete sending their respective command buffer before sending it again. Arguably, this might not be a huge concern, but it seems unnecessary nonetheless.&#xD;&#xA;&#xD;&#xA;#Spatial Locality Issues&#xD;&#xA;&#xD;&#xA;It also seems that since there isn't a way to guarantee when an object is going through the pipeline that you may get additional cache misses on the GPU compared to instancing here.&#xD;&#xA;&#xD;&#xA;#Question&#xD;&#xA;&#xD;&#xA;Is there any advantage to using multiple command buffers for stereo rendering compared to instanced stereo rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/engaging-voyage-vulkan" ContentLicense="CC BY-SA 3.0" />
  <row Id="9452" PostHistoryTypeId="2" PostId="4259" RevisionGUID="befb1bb7-c609-4b40-954e-8955d5d4e78b" CreationDate="2016-11-11T07:44:05.897" UserId="5256" Text="Recently I have developed and interest in Ray Tracing and like most computer graphics tutorials online there is nothing regarding implementation for a beginner like myself. &#xD;&#xA;&#xD;&#xA;So far I have only done real time rendering (DirectX), however I understand the basics of Ray Tracing but I want to buy a book before proceeding any further. I've taken a look at [Physically Based Rendering: From Theory to Implementation][1] (I want to learn Ray Tracing with a Physically Based Approach so I thought this would be great) but I don't think it's good for a beginner since there's not much emphasis on the code. &#xD;&#xA;&#xD;&#xA;When I was learning DirectX 11 everyone recommended Frank Luna's **[Introduction to 3D Game Programming][2]**, which was great since it covered all the basics and also a few advanced topics like SSAO with an approach a beginner could understand. Is there something like this for Ray Tracing? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org/&#xD;&#xA;  [2]: http://www.d3dcoder.net/d3d11.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="9453" PostHistoryTypeId="1" PostId="4259" RevisionGUID="befb1bb7-c609-4b40-954e-8955d5d4e78b" CreationDate="2016-11-11T07:44:05.897" UserId="5256" Text="Books to learn Ray Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="9454" PostHistoryTypeId="3" PostId="4259" RevisionGUID="befb1bb7-c609-4b40-954e-8955d5d4e78b" CreationDate="2016-11-11T07:44:05.897" UserId="5256" Text="|raytracing|physically-based|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9455" PostHistoryTypeId="2" PostId="4260" RevisionGUID="f8ee8826-aef9-4e62-be65-8d0070a3349f" CreationDate="2016-11-11T08:28:54.327" UserId="110" Text="For an introduction, you can give a look at: [Ray Tracing from the Ground Up](http://www.raytracegroundup.com/) (Amazon link [here](https://www.amazon.com/dp/1568812728)).&#xD;&#xA;  &#xD;&#xA;[![Cover](https://i.stack.imgur.com/BmIYm.jpg)](http://vk.com/doc-38203920_232998004)&#xD;&#xA;&#xD;&#xA;It starts really from the basics, and provides simple implementations for the concepts that are gradually introduced.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9457" PostHistoryTypeId="2" PostId="4261" RevisionGUID="c711e0db-df55-4e41-bf15-39bc8d610e3c" CreationDate="2016-11-11T13:29:43.467" UserId="56" Text="Not a book, but here's an online write-up about the basics of Monte Carlo path tracing:&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/&#xA;&#xA;I've also heard good things a out Peter Shirley's books. In particular &quot;Ray Tracing in one Weekend&quot;&#xA;https://www.amazon.com/Ray-Tracing-Weekend-Minibooks-Book-ebook/dp/B01B5AODD8" ContentLicense="CC BY-SA 3.0" />
  <row Id="9458" PostHistoryTypeId="5" PostId="4255" RevisionGUID="d50ed034-2d3c-45ca-ba0f-7f39ac9934a0" CreationDate="2016-11-11T14:09:28.523" UserId="2941" Comment="Removed duplicate words" Text="I'm a software engineer and although I currently don't work on anything related to computer graphics, I understand how downscaling works, what I don't understand is why most modern games default to over 100% on my computer (GTX 1080, 1080p@144Hz monitor). For instance, Overwatch defaults to 140% render scale, which translates into a huge performance hit (stable 144 vs 60~80 fps). Why is the game doing this? I understand that downscaling makes the quality of the image a bit better, but this doesn't justify that performance hit. I read in some places that downscaling also helps to reduce some graphics artifacts, can someone please elaborate on this? I would like to know what are the benefits of downscaling and why modern games are defaulting to settings above 100%." ContentLicense="CC BY-SA 3.0" />
  <row Id="9459" PostHistoryTypeId="24" PostId="4255" RevisionGUID="d50ed034-2d3c-45ca-ba0f-7f39ac9934a0" CreationDate="2016-11-11T14:09:28.523" Comment="Proposed by 2941 approved by 209, 231 edit id of 179" ContentLicense="CC BY-SA 3.0" />
  <row Id="9460" PostHistoryTypeId="10" PostId="4259" RevisionGUID="0fa7819e-c4fa-4583-9878-69d602f7c885" CreationDate="2016-11-11T14:10:46.957" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9461" PostHistoryTypeId="5" PostId="4256" RevisionGUID="6d806234-893e-46b2-a564-fe46e6d636a5" CreationDate="2016-11-11T14:32:03.523" UserId="2654" Comment="added 1737 characters in body" Text="Yes, there are advantages. You can render different command buffers to *different queues.*&#xD;&#xA;&#xD;&#xA;Modern NVIDIA hardware, in particular, offers a full *sixteen* separate queues that are capable of rendering independent graphics operations. By putting each eye in a separate queue, you may be able to use the available hardware resources more efficiently.&#xD;&#xA;&#xD;&#xA;Then again, it may not. It all really depends on how things work out down in the lowest levels of hardware.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;&gt; Regardless, the issue with synchronization that I'm concerned about would be if one eye finishes considerably faster than the other eye. It seems that with stereo instanced rendering, this would be less likely to happen since the workload is more divisible.&#xD;&#xA;&#xD;&#xA;It would basically never happen with instanced rendering. But you say that like it's a *good* thing.&#xD;&#xA;&#xD;&#xA;If one eye happens to have more scene complexity than the other eye, then that means instanced stereo rendering will be wasting a lot of vertex processing on vertices for the &quot;weak&quot; eye that will never be seen. Whereas if you built the command buffers separately, you would only submit the stuff that matters for both scenes.&#xD;&#xA;&#xD;&#xA;If you submit both CBs to the same queue, the total time spent processing those CBs can be less than the time spent processing the larger CB, since it isn't computing a bunch of triangles that won't be culled. If you submit the two CBs to different queues, how that balances out depends entirely on how well the hardware can adapt to the workload it is given. If it can adapt well, then, then you'll be fine.&#xD;&#xA;&#xD;&#xA;So for this particular case, the multiple CB setup may represent a more efficient use of hardware resources. Granted, this particular case is rather rare.&#xD;&#xA;&#xD;&#xA;Synchronization for this case is really not a problem. If one eye is so complicated relative to the other that you drop a frame, then it doesn't matter which form you're using to render. You're going to drop a frame.&#xD;&#xA;&#xD;&#xA;With Vulkan, rendering entirely separate stuff to multiple queues isn't difficult. Indeed, the only real synchronization you might need would be to synchronize the presentation of the swapchain images, which is easily done with semaphores." ContentLicense="CC BY-SA 3.0" />
  <row Id="9462" PostHistoryTypeId="5" PostId="4256" RevisionGUID="f8077471-9262-4ca2-bca1-80fba2d6492e" CreationDate="2016-11-11T14:39:02.050" UserId="2654" Comment="added 1737 characters in body" Text="Yes, there are advantages. You can render different command buffers to *different queues.*&#xD;&#xA;&#xD;&#xA;Modern NVIDIA hardware, in particular, offers a full *sixteen* separate queues that are capable of rendering independent graphics operations. By putting each eye in a separate queue, you may be able to use the available hardware resources more efficiently.&#xD;&#xA;&#xD;&#xA;Then again, it may not. It all really depends on how things work out down in the lowest levels of hardware.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;&gt; Regardless, the issue with synchronization that I'm concerned about would be if one eye finishes considerably faster than the other eye. It seems that with stereo instanced rendering, this would be less likely to happen since the workload is more divisible.&#xD;&#xA;&#xD;&#xA;It would basically never happen with instanced rendering. But you say that like it's a *good* thing.&#xD;&#xA;&#xD;&#xA;If one eye happens to have more scene complexity than the other eye, then that means instanced stereo rendering will be wasting a lot of vertex processing on vertices for the &quot;weak&quot; eye that will never be seen. Whereas if you built the command buffers separately, you would only submit the stuff that matters for both scenes.&#xD;&#xA;&#xD;&#xA;If you submit both CBs to the same queue, the total time spent processing those CBs can be less than the time spent processing the larger CB, since it isn't computing a bunch of triangles that won't be culled. If you submit the two CBs to different queues, how that balances out depends entirely on how well the hardware can adapt to the workload it is given. If it can adapt well, then, then you'll be fine.&#xD;&#xA;&#xD;&#xA;So for this particular case, the multiple CB setup may represent a more efficient use of hardware resources. Granted, this particular case is rather rare.&#xD;&#xA;&#xD;&#xA;Synchronization for this case is really not a problem. If one eye is so complicated relative to the other that you drop a frame, then it doesn't matter which form you're using to render. You're going to drop a frame.&#xD;&#xA;&#xD;&#xA;With Vulkan, rendering entirely separate stuff to multiple queues isn't difficult. Indeed, the only real synchronization you might need would be to synchronize the presentation of the swapchain images, which is easily done with semaphores.&#xD;&#xA;&#xD;&#xA;&gt; The other issue I see where synchronization could cause a performance hit is that you must wait for both threads to complete sending their respective command buffer before sending it again.&#xD;&#xA;&#xD;&#xA;No, you don't. If you're reusing CBs, you can always use the `VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT`, which allows you to submit a CB that's already in use. And if you're not reusing CBs (that is, your CBs aren't static), you don't care; just double-buffer your command pools so that you aren't trying to reset a CB that's being consumed.&#xD;&#xA;&#xD;&#xA;The latter is the general standard method for rendering dynamic scenes with Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="9468" PostHistoryTypeId="5" PostId="4256" RevisionGUID="1b526fef-586e-4afc-b65e-3022e8abb34c" CreationDate="2016-11-12T09:33:34.987" UserId="231" Comment="Remove repeated word" Text="Yes, there are advantages. You can render different command buffers to *different queues.*&#xD;&#xA;&#xD;&#xA;Modern NVIDIA hardware, in particular, offers a full *sixteen* separate queues that are capable of rendering independent graphics operations. By putting each eye in a separate queue, you may be able to use the available hardware resources more efficiently.&#xD;&#xA;&#xD;&#xA;Then again, it may not. It all really depends on how things work out down in the lowest levels of hardware.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;&gt; Regardless, the issue with synchronization that I'm concerned about would be if one eye finishes considerably faster than the other eye. It seems that with stereo instanced rendering, this would be less likely to happen since the workload is more divisible.&#xD;&#xA;&#xD;&#xA;It would basically never happen with instanced rendering. But you say that like it's a *good* thing.&#xD;&#xA;&#xD;&#xA;If one eye happens to have more scene complexity than the other eye, then that means instanced stereo rendering will be wasting a lot of vertex processing on vertices for the &quot;weak&quot; eye that will never be seen. Whereas if you built the command buffers separately, you would only submit the stuff that matters for both scenes.&#xD;&#xA;&#xD;&#xA;If you submit both CBs to the same queue, the total time spent processing those CBs can be less than the time spent processing the larger CB, since it isn't computing a bunch of triangles that won't be culled. If you submit the two CBs to different queues, how that balances out depends entirely on how well the hardware can adapt to the workload it is given. If it can adapt well, then you'll be fine.&#xD;&#xA;&#xD;&#xA;So for this particular case, the multiple CB setup may represent a more efficient use of hardware resources. Granted, this particular case is rather rare.&#xD;&#xA;&#xD;&#xA;Synchronization for this case is really not a problem. If one eye is so complicated relative to the other that you drop a frame, then it doesn't matter which form you're using to render. You're going to drop a frame.&#xD;&#xA;&#xD;&#xA;With Vulkan, rendering entirely separate stuff to multiple queues isn't difficult. Indeed, the only real synchronization you might need would be to synchronize the presentation of the swapchain images, which is easily done with semaphores.&#xD;&#xA;&#xD;&#xA;&gt; The other issue I see where synchronization could cause a performance hit is that you must wait for both threads to complete sending their respective command buffer before sending it again.&#xD;&#xA;&#xD;&#xA;No, you don't. If you're reusing CBs, you can always use the `VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT`, which allows you to submit a CB that's already in use. And if you're not reusing CBs (that is, your CBs aren't static), you don't care; just double-buffer your command pools so that you aren't trying to reset a CB that's being consumed.&#xD;&#xA;&#xD;&#xA;The latter is the general standard method for rendering dynamic scenes with Vulkan." ContentLicense="CC BY-SA 3.0" />
  <row Id="9469" PostHistoryTypeId="5" PostId="4230" RevisionGUID="ca76bbfc-b7ca-40a0-b750-f152b385e96c" CreationDate="2016-11-12T10:54:25.890" UserId="3041" Comment="Added pictures and explanation of &quot;polar&quot; projections" Text="(edited 2016-11-12)&#xD;&#xA;&#xD;&#xA;I have thought of a triangle sub-division for the purpose of smooth triangulation (no popping) over time on the fly. I think it is very likely the scheme is already invented and has a name but I can´t seem to find it. Maybe you can help?&#xD;&#xA;&#xD;&#xA;Sub-division is made on triangle edge basis. For each edge longer than a certain threshold, say 1cm on display (i.e. projected space), the edge get two new points a threshold distance (1cm) away from eachother. The edge in between the new points are then complete and need no further sub-division. Up to six new points are thus created from the sub-division, but it could be just one edge making two new points. From the points triangles are formed and the sub-division is performed recursively until all edges are shorter than the threshold.&#xD;&#xA;&#xD;&#xA;Creating two points along the edge a threshold apart is significant for the subdivision to be smooth over time. I don´t see Loop or Catmull Clark doing this.&#xD;&#xA;&#xD;&#xA;I should probably mention I use this succesfully for cartesian meshes in polar projections. Strictly speaking the two points created along an edge may or may not be on the originally projected line.&#xD;&#xA;&#xD;&#xA;So what is it called?&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;So I guess I have to explain a few things about cartesian coordinate systems in polar projections.&#xD;&#xA;&#xD;&#xA;A good example of a polar coordinate system is a flat earth. Earth may look like this in a cartesian system with a huge table on top of it:&#xD;&#xA;[![earth cartesian][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A polar coordinate system could have the x-axis defined as the angle from earth center to a cartesian coordinate given a plane used to project the earth. The y-axis is then the altitude, either from earth surface or bluntely the distance from earth center. A polar projected version of above image given my description would look like this (with the assumption the earth is spherical, which it is not...):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![polar earth][2]][2]&#xD;&#xA;&#xD;&#xA;(please have patience with me not being a great artist.)&#xD;&#xA;&#xD;&#xA;As you can see the table is now bent because in the middle it is closer to the earth center than in the edges (exagerated, I know).&#xD;&#xA;&#xD;&#xA;Without sub-division the table would still be flat in the polar view its altitude would be misleading. A point object on top of the table in cartesian coordinates may be below it in the polar view. The triangle sub-division aim to lessens the error until it is &quot;small enough&quot;. I measure this by projected length on display because it is cheap and has good corresponadence to my quality requirements but other schemes would do just as fine or better depending on the polar properties, e.g. likeliness you are interested in accurate altitude far below the earth surface.&#xD;&#xA;&#xD;&#xA;As you may realize the error becomes greater the bigger the object and the closer it is to the polar origin.&#xD;&#xA;&#xD;&#xA;Know to some details of the algorithm.&#xD;&#xA;&#xD;&#xA;This is a triangle (in cartesian coordinates) with red and green edge being to long **in the polar view**, i.e. the red is very close the polar origin, the green not so close and the black quite far away:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;(Again, I´m sorry for not being a great artist.)&#xD;&#xA;&#xD;&#xA;And this is how triangles would be formed:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Once new points are created their cartesian coordinate is a coordinate along the original edge. The new triangles are fed to the algorithm once more and repeated until the error is small enough. In above image one might suspect the red edge should be partitioned at least one more time.&#xD;&#xA;&#xD;&#xA;The point in making two control points is to get edge matching behavior without extra edge information. Splitting two adjecent triangles (or lines for that matter) is guaranteed to have the new points on the exact same location with the exact same information.&#xD;&#xA;&#xD;&#xA;Key feature here is that new triangles does not cross the middle of the original triangle as this would otherwise cause **too much error correction from one frame to another** as the greatest error is in the middle between control points. Points close to the control point will be least corrected and thus give the least amount of correction to make the error small enough. This is crucial for smooth zooming in any of the axes or even movement of the projected objects.&#xD;&#xA;&#xD;&#xA;Triangulation layout is stable no matter what edges are too long.&#xD;&#xA;&#xD;&#xA;Broad-first recursion is the better way to go if the sub-division is limited by time or memory as edge matching is guaranteed even for interrupted/partial sub-division.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SD0qD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IZjK8.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vshLw.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/XkScF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9470" PostHistoryTypeId="5" PostId="4230" RevisionGUID="df47b55c-0556-4412-a145-63eef3d82a3e" CreationDate="2016-11-12T12:20:07.510" UserId="231" Comment="Tidying, plus edits do not need to be announced as the date of last edit is already displayed and the edit history is available there" Text="I have thought of a triangle sub-division for the purpose of smooth triangulation (no popping) over time on the fly. I think it is very likely the scheme is already invented and has a name but I can´t seem to find it. &#xD;&#xA;&#xD;&#xA;Sub-division is made on triangle edge basis. For each edge longer than a certain threshold, say 1cm on display (i.e. projected space), the edge get two new points a threshold distance (1cm) away from each other. The edge in between the new points are then complete and need no further sub-division. Up to six new points are thus created from the sub-division, but it could be just one edge making two new points. From the points triangles are formed and the sub-division is performed recursively until all edges are shorter than the threshold.&#xD;&#xA;&#xD;&#xA;Creating two points along the edge a threshold apart is significant for the subdivision to be smooth over time. I don´t see Loop or Catmull Clark doing this.&#xD;&#xA;&#xD;&#xA;I should probably mention I use this successfully for cartesian meshes in polar projections. Strictly speaking the two points created along an edge may or may not be on the originally projected line.&#xD;&#xA;&#xD;&#xA;So what is it called?&#xD;&#xA;&#xD;&#xA;## Explanation&#xD;&#xA;&#xD;&#xA;So I guess I have to explain a few things about cartesian coordinate systems in polar projections.&#xD;&#xA;&#xD;&#xA;A good example of a polar coordinate system is a flat earth. Earth may look like this in a cartesian system with a huge table on top of it:&#xD;&#xA;[![earth cartesian][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A polar coordinate system could have the x-axis defined as the angle from earth center to a cartesian coordinate given a plane used to project the earth. The y-axis is then the altitude, either from earth surface or bluntly the distance from earth center. A polar projected version of above image given my description would look like this (with the assumption the earth is spherical, which it is not...):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![polar earth][2]][2]&#xD;&#xA;&#xD;&#xA;(please have patience with me not being a great artist.)&#xD;&#xA;&#xD;&#xA;As you can see the table is now bent because in the middle it is closer to the earth center than in the edges (exaggerated, I know).&#xD;&#xA;&#xD;&#xA;Without sub-division the table would still be flat in the polar view its altitude would be misleading. A point object on top of the table in cartesian coordinates may be below it in the polar view. The triangle sub-division aim to lessens the error until it is &quot;small enough&quot;. I measure this by projected length on display because it is cheap and has good correspondence to my quality requirements but other schemes would do just as fine or better depending on the polar properties, e.g. likeliness you are interested in accurate altitude far below the earth surface.&#xD;&#xA;&#xD;&#xA;As you may realize the error becomes greater the bigger the object and the closer it is to the polar origin.&#xD;&#xA;&#xD;&#xA;Know to some details of the algorithm.&#xD;&#xA;&#xD;&#xA;This is a triangle (in cartesian coordinates) with red and green edge being to long **in the polar view**, i.e. the red is very close the polar origin, the green not so close and the black quite far away:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And this is how triangles would be formed:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Once new points are created their cartesian coordinate is a coordinate along the original edge. The new triangles are fed to the algorithm once more and repeated until the error is small enough. In above image one might suspect the red edge should be partitioned at least one more time.&#xD;&#xA;&#xD;&#xA;The point in making two control points is to get edge matching behavior without extra edge information. Splitting two adjacent triangles (or lines for that matter) is guaranteed to have the new points on the exact same location with the exact same information.&#xD;&#xA;&#xD;&#xA;Key feature here is that new triangles does not cross the middle of the original triangle as this would otherwise cause **too much error correction from one frame to another** as the greatest error is in the middle between control points. Points close to the control point will be least corrected and thus give the least amount of correction to make the error small enough. This is crucial for smooth zooming in any of the axes or even movement of the projected objects.&#xD;&#xA;&#xD;&#xA;Triangulation layout is stable no matter what edges are too long.&#xD;&#xA;&#xD;&#xA;Breadth-first recursion is the better way to go if the sub-division is limited by time or memory as edge matching is guaranteed even for interrupted/partial sub-division.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SD0qD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IZjK8.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vshLw.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/XkScF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9471" PostHistoryTypeId="2" PostId="4263" RevisionGUID="f13633db-1fe5-4555-9423-3c1d52319373" CreationDate="2016-11-12T19:47:45.837" UserDisplayName="user4718" Text="I've to rasterize a line taking into account not only the background color of the screen, which is white, but also the color of other objects in the scene. In my case, I've just another object, a sphere, which is actually visualized using a ray tracing technique. &#xD;&#xA;&#xD;&#xA;So far the code that I have seems only to consider the white background color of the screen and not also the color of the sphere.&#xD;&#xA;&#xD;&#xA;So here's the code:&#xD;&#xA;&#xD;&#xA;      // ray tracing of the sphere&#xD;&#xA;      // here we initialize the z-buffer's elements to -1.0 zBuffer that you find below&#xD;&#xA;      ...&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // rasterize a line&#xD;&#xA;      //&#xD;&#xA;    &#xD;&#xA;      // line from p1 to p2 in LOCAL coordinates&#xD;&#xA;      Point3d p1 (-1.0, 0.0, 0.0);&#xD;&#xA;      Point3d p2 ( 1.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // transformations...&#xD;&#xA;    	Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);&#xD;&#xA;    	Matrix4d R1 = Matrix4d::rotation (0.5,'z');&#xD;&#xA;    	Matrix4d R2 = Matrix4d::rotation (tau,'x');&#xD;&#xA;    	Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);	&#xD;&#xA;    &#xD;&#xA;      Matrix4d M  = T*R2*R1*S;&#xD;&#xA;    &#xD;&#xA;      p1 = M*p1;&#xD;&#xA;      p2 = M*p2;&#xD;&#xA;    &#xD;&#xA;      // screen coordinates&#xD;&#xA;      double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;&#xD;&#xA;      double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;&#xD;&#xA;      double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;&#xD;&#xA;      double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // line rasterization algorithm with anti-aliasing and z-test&#xD;&#xA;      // (for lines with slope between -1 and 1)&#xD;&#xA;      //&#xD;&#xA;      int x  = round(x1);&#xD;&#xA;      int y  = round(y1);&#xD;&#xA;    &#xD;&#xA;      double I0 = 1.0;&#xD;&#xA;      double m = (y2-y1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;      bool up = true;&#xD;&#xA;      if (y2 &lt; y1) {&#xD;&#xA;        m = -m;&#xD;&#xA;        I0 = 0.0;&#xD;&#xA;        up = false;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      int nextY;&#xD;&#xA;      double z;&#xD;&#xA;      for ( ; x&lt;=x2; x++) {&#xD;&#xA;        if (up)&#xD;&#xA;          nextY = y+1;&#xD;&#xA;        else&#xD;&#xA;          nextY = y-1;&#xD;&#xA;    &#xD;&#xA;        // barycentric coordinates of the current point: (1-lambda, lambda),&#xD;&#xA;        // i.e.: x = (1-lambda) x1 + lambda x2&#xD;&#xA;        double lambda = (x-x1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;        // perspectively correct linear interpolation of z-values&#xD;&#xA;        z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );&#xD;&#xA;    &#xD;&#xA;        if ( (zBuffer[x+y*w] &lt; 0) || z &lt; zBuffer[x+y*w] ) {&#xD;&#xA;          int I = (int) 255*I0;&#xD;&#xA;     	    image-&gt;setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );&#xD;&#xA;     	    image-&gt;setPixel( x, nextY, qRgb(     I, 255,     I ) );&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (m &gt; I0) {&#xD;&#xA;          y  = nextY;&#xD;&#xA;          I0 += 1.0;&#xD;&#xA;        }&#xD;&#xA;        I0 -= m;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // repaint canvas&#xD;&#xA;      repaint();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the output is not as expected, because one of the pixels of the lines on the sphere is coloured white. Of course we notice this immediately! The idea is to make a smoother line that considers not only the colour of the background but also the colour of the sphere.&#xD;&#xA;&#xD;&#xA;I thought I need to interpolate colours, but I'm not sure which ones and how to do it. I know that the basic idea of interpolation is to find an intermediate colour between two (or more) colours ($C_1, C_2$) using a formula as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(1 - \alpha) C_1 + \alpha * C_2$$&#xD;&#xA;&#xD;&#xA;Now the problem is that I don't know what's exactly alpha and which colours would be $C_1$ and $C_2$. Any help is appreciated.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9472" PostHistoryTypeId="1" PostId="4263" RevisionGUID="f13633db-1fe5-4555-9423-3c1d52319373" CreationDate="2016-11-12T19:47:45.837" UserDisplayName="user4718" Text="How to rasterize a line when the background color is not always white?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9473" PostHistoryTypeId="3" PostId="4263" RevisionGUID="f13633db-1fe5-4555-9423-3c1d52319373" CreationDate="2016-11-12T19:47:45.837" UserDisplayName="user4718" Text="|raytracing|c++|line-drawing|interpolation|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9474" PostHistoryTypeId="5" PostId="4263" RevisionGUID="cf32c77f-d6af-4cac-8ac6-96d0bb33e7aa" CreationDate="2016-11-12T20:07:11.763" UserDisplayName="user4718" Comment="added 449 characters in body" Text="I've to rasterize a line taking into account not only the background color of the screen, which is white, but also the color of other objects in the scene. In my case, I've just another object, a sphere, which is actually visualized using a ray tracing technique. &#xD;&#xA;&#xD;&#xA;So far the code that I have seems only to consider the white background color of the screen and not also the color of the sphere.&#xD;&#xA;&#xD;&#xA;So here's the code:&#xD;&#xA;&#xD;&#xA;      // ray tracing of the sphere&#xD;&#xA;      // here we initialize the z-buffer's elements to -1.0 zBuffer that you find below&#xD;&#xA;      ...&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // rasterize a line&#xD;&#xA;      //&#xD;&#xA;    &#xD;&#xA;      // line from p1 to p2 in LOCAL coordinates&#xD;&#xA;      Point3d p1 (-1.0, 0.0, 0.0);&#xD;&#xA;      Point3d p2 ( 1.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // transformations...&#xD;&#xA;    	Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);&#xD;&#xA;    	Matrix4d R1 = Matrix4d::rotation (0.5,'z');&#xD;&#xA;    	Matrix4d R2 = Matrix4d::rotation (tau,'x');&#xD;&#xA;    	Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);	&#xD;&#xA;    &#xD;&#xA;      Matrix4d M  = T*R2*R1*S;&#xD;&#xA;    &#xD;&#xA;      p1 = M*p1;&#xD;&#xA;      p2 = M*p2;&#xD;&#xA;    &#xD;&#xA;      // screen coordinates&#xD;&#xA;      double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;&#xD;&#xA;      double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;&#xD;&#xA;      double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;&#xD;&#xA;      double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // line rasterization algorithm with anti-aliasing and z-test&#xD;&#xA;      // (for lines with slope between -1 and 1)&#xD;&#xA;      //&#xD;&#xA;      int x  = round(x1);&#xD;&#xA;      int y  = round(y1);&#xD;&#xA;    &#xD;&#xA;      double I0 = 1.0;&#xD;&#xA;      double m = (y2-y1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;      bool up = true;&#xD;&#xA;      if (y2 &lt; y1) {&#xD;&#xA;        m = -m;&#xD;&#xA;        I0 = 0.0;&#xD;&#xA;        up = false;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      int nextY;&#xD;&#xA;      double z;&#xD;&#xA;      for ( ; x&lt;=x2; x++) {&#xD;&#xA;        if (up)&#xD;&#xA;          nextY = y+1;&#xD;&#xA;        else&#xD;&#xA;          nextY = y-1;&#xD;&#xA;    &#xD;&#xA;        // barycentric coordinates of the current point: (1-lambda, lambda),&#xD;&#xA;        // i.e.: x = (1-lambda) x1 + lambda x2&#xD;&#xA;        double lambda = (x-x1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;        // perspectively correct linear interpolation of z-values&#xD;&#xA;        z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );&#xD;&#xA;    &#xD;&#xA;        if ( (zBuffer[x+y*w] &lt; 0) || z &lt; zBuffer[x+y*w] ) {&#xD;&#xA;          int I = (int) 255*I0;&#xD;&#xA;     	    image-&gt;setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );&#xD;&#xA;     	    image-&gt;setPixel( x, nextY, qRgb(     I, 255,     I ) );&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (m &gt; I0) {&#xD;&#xA;          y  = nextY;&#xD;&#xA;          I0 += 1.0;&#xD;&#xA;        }&#xD;&#xA;        I0 -= m;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // repaint canvas&#xD;&#xA;      repaint();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the output is not as expected, because one of the pixels of the lines on the sphere is coloured white. Of course we notice this immediately! The idea is to make a smoother line that considers not only the colour of the background but also the colour of the sphere.&#xD;&#xA;&#xD;&#xA;I thought I need to interpolate colours, but I'm not sure which ones and how to do it. I know that the basic idea of interpolation is to find an intermediate colour between two (or more) colours ($C_1, C_2$) using a formula as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(1 - \alpha) C_1 + \alpha * C_2$$&#xD;&#xA;&#xD;&#xA;Now the problem is that I don't know what's exactly $\alpha$ and which colours would be $C_1$ and $C_2$.  I thought $\alpha$ could be the `lambda` variable in the code above, but this is more than a guess than a conclusion after a logical reasoning. &#xD;&#xA;&#xD;&#xA;Moreover, I guessed that the colours $C_1$ and $C_2$ are respectively the color of the pixel before the rasterization of the line (i.e. in the ray tracing part), which can also be the color of the sphere, if that pixel is covered by the sphere, or the background color, i.e. white in my case. &#xD;&#xA;&#xD;&#xA;Any help is appreciated.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9475" PostHistoryTypeId="5" PostId="4263" RevisionGUID="36a04320-947d-4711-81c5-55ed676aa2cd" CreationDate="2016-11-12T20:37:32.513" UserDisplayName="user4718" Comment="added 422 characters in body" Text="I've to rasterize a line taking into account not only the background color of the screen, which is white, but also the color of other objects in the scene. In my case, I've just another object, a sphere, which is actually visualized using a ray tracing technique. &#xD;&#xA;&#xD;&#xA;So far the code that I have seems only to consider the white background color of the screen and not also the color of the sphere.&#xD;&#xA;&#xD;&#xA;So here's the code:&#xD;&#xA;&#xD;&#xA;      // ray tracing of the sphere&#xD;&#xA;      // here we initialize the z-buffer's elements to -1.0 zBuffer that you find below&#xD;&#xA;      ...&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // rasterize a line&#xD;&#xA;      //&#xD;&#xA;    &#xD;&#xA;      // line from p1 to p2 in LOCAL coordinates&#xD;&#xA;      Point3d p1 (-1.0, 0.0, 0.0);&#xD;&#xA;      Point3d p2 ( 1.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // transformations...&#xD;&#xA;    	Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);&#xD;&#xA;    	Matrix4d R1 = Matrix4d::rotation (0.5,'z');&#xD;&#xA;    	Matrix4d R2 = Matrix4d::rotation (tau,'x');&#xD;&#xA;    	Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);	&#xD;&#xA;    &#xD;&#xA;      Matrix4d M  = T*R2*R1*S;&#xD;&#xA;    &#xD;&#xA;      p1 = M*p1;&#xD;&#xA;      p2 = M*p2;&#xD;&#xA;    &#xD;&#xA;      // screen coordinates&#xD;&#xA;      double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;&#xD;&#xA;      double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;&#xD;&#xA;      double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;&#xD;&#xA;      double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // line rasterization algorithm with anti-aliasing and z-test&#xD;&#xA;      // (for lines with slope between -1 and 1)&#xD;&#xA;      //&#xD;&#xA;      int x  = round(x1);&#xD;&#xA;      int y  = round(y1);&#xD;&#xA;    &#xD;&#xA;      double I0 = 1.0;&#xD;&#xA;      double m = (y2-y1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;      bool up = true;&#xD;&#xA;      if (y2 &lt; y1) {&#xD;&#xA;        m = -m;&#xD;&#xA;        I0 = 0.0;&#xD;&#xA;        up = false;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      int nextY;&#xD;&#xA;      double z;&#xD;&#xA;      for ( ; x&lt;=x2; x++) {&#xD;&#xA;        if (up)&#xD;&#xA;          nextY = y+1;&#xD;&#xA;        else&#xD;&#xA;          nextY = y-1;&#xD;&#xA;    &#xD;&#xA;        // barycentric coordinates of the current point: (1-lambda, lambda),&#xD;&#xA;        // i.e.: x = (1-lambda) x1 + lambda x2&#xD;&#xA;        double lambda = (x-x1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;        // perspectively correct linear interpolation of z-values&#xD;&#xA;        z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );&#xD;&#xA;    &#xD;&#xA;        if ( (zBuffer[x+y*w] &lt; 0) || z &lt; zBuffer[x+y*w] ) {&#xD;&#xA;          int I = (int) 255*I0;&#xD;&#xA;     	    image-&gt;setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );&#xD;&#xA;     	    image-&gt;setPixel( x, nextY, qRgb(     I, 255,     I ) );&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (m &gt; I0) {&#xD;&#xA;          y  = nextY;&#xD;&#xA;          I0 += 1.0;&#xD;&#xA;        }&#xD;&#xA;        I0 -= m;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // repaint canvas&#xD;&#xA;      repaint();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the output is not as expected, because one of the pixels of the lines on the sphere is coloured white. Of course we notice this immediately! The idea is to make a smoother line that considers not only the colour of the background but also the colour of the sphere.&#xD;&#xA;&#xD;&#xA;I thought I need to interpolate colours, but I'm not sure which ones and how to do it. I know that the basic idea of interpolation is to find an intermediate colour between two (or more) colours ($C_1, C_2$) using a formula as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(1 - \alpha) C_1 + \alpha * C_2$$&#xD;&#xA;&#xD;&#xA;Now the problem is that I don't know what's exactly $\alpha$ and which colours would be $C_1$ and $C_2$.  I thought $\alpha$ could be the `lambda` variable in the code above, but this is more than a guess than a conclusion after a logical reasoning. &#xD;&#xA;&#xD;&#xA;Moreover, I guessed that the colours $C_1$ and $C_2$ are respectively the color of the pixel before the rasterization of the line (i.e. in the ray tracing part), which can also be the color of the sphere, if that pixel is covered by the sphere, or the background color, i.e. white in my case. &#xD;&#xA;&#xD;&#xA;Any help is appreciated.&#xD;&#xA;&#xD;&#xA;To give you an idea, this is the wrong output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;and this should be the correct one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note (if you zoom in) that the line in the first picture is not that smooth over the sphere, because one of the pixels (at least) is colored for the background color white.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q0tnC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TIUz7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9476" PostHistoryTypeId="6" PostId="3707" RevisionGUID="2fab5117-a71f-491f-99bc-f5e4fec538f6" CreationDate="2016-11-12T22:44:53.377" UserId="48" Comment="tweaked tags" Text="|color-science|blur|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9477" PostHistoryTypeId="6" PostId="2264" RevisionGUID="e46495d4-d65a-4332-b91f-8f2898de91d5" CreationDate="2016-11-12T22:44:59.610" UserId="48" Comment="tweaked tags" Text="|color-science|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9478" PostHistoryTypeId="2" PostId="4264" RevisionGUID="066234ee-55b7-49c1-b9cb-b8406f2c44f1" CreationDate="2016-11-12T22:46:14.397" UserId="48" Text="You're actually already doing color interpolation in the code you posted, in these expressions:&#xD;&#xA;&#xD;&#xA;    qRgb( 255-I, 255, 255-I )&#xD;&#xA;    qRgb(     I, 255,     I )&#xD;&#xA;&#xD;&#xA;The first one is interpolating from white to green by `I`, and the second one from green to white by `I`. In both cases `I` is acting as an integer form of the variable $\alpha$ from the equation. I note that you have already a fractional variable `I0` there, which is exactly what's needed for interpolation.&#xD;&#xA;&#xD;&#xA;So, if I rewrite your `qRgb` expressions a little bit, I can make them look closer to the form of the interpolation equation:&#xD;&#xA;&#xD;&#xA;    (1.0 - I0) * qRgb(255, 255, 255) + I0 * qRgb(0, 255, 0)&#xD;&#xA;    I0 * qRgb(255, 255, 255) + (1.0 - I0) * qRgb(0, 255, 0)&#xD;&#xA;&#xD;&#xA;This hopefully makes it clearer that $C_1$ is the color we're interpolating from, white, and $C_2$ is the color we're interpolating to, green. In the first line $\alpha$ is `I0` and in the second, $\alpha$ is `1.0 - I0`. Note that interpolating from white to green by `1.0 - I0` is equivalent to interpolating from green to white by `I0`.&#xD;&#xA;&#xD;&#xA;So, to make this work against an arbitrary colored background, you just have to change white to the actual background color of the pixel you're rasterizing to.&#xD;&#xA;&#xD;&#xA;Technically, [gamma correction](http://computergraphics.stackexchange.com/questions/2264/how-are-we-supposed-to-fix-brightness-with-square-roots) should also be applied when interpolating, but that's a relatively minor visual change that you can safely ignore for awhile." ContentLicense="CC BY-SA 3.0" />
  <row Id="9479" PostHistoryTypeId="5" PostId="4263" RevisionGUID="23e2824d-a061-4ee4-ab49-62c3ac69e69c" CreationDate="2016-11-12T23:52:33.577" UserDisplayName="user4718" Comment="added 414 characters in body" Text="I've to rasterize a line taking into account not only the background color of the screen, which is white, but also the color of other objects in the scene. In my case, I've just another object, a sphere, which is actually visualized using a ray tracing technique. &#xD;&#xA;&#xD;&#xA;So far the code that I have seems only to consider the white background color of the screen and not also the color of the sphere.&#xD;&#xA;&#xD;&#xA;So here's the code:&#xD;&#xA;&#xD;&#xA;      // ray tracing of the sphere&#xD;&#xA;      // here we initialize the z-buffer's elements to -1.0 zBuffer that you find below&#xD;&#xA;      ...&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // rasterize a line&#xD;&#xA;      //&#xD;&#xA;    &#xD;&#xA;      // line from p1 to p2 in LOCAL coordinates&#xD;&#xA;      Point3d p1 (-1.0, 0.0, 0.0);&#xD;&#xA;      Point3d p2 ( 1.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // transformations...&#xD;&#xA;    	Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);&#xD;&#xA;    	Matrix4d R1 = Matrix4d::rotation (0.5,'z');&#xD;&#xA;    	Matrix4d R2 = Matrix4d::rotation (tau,'x');&#xD;&#xA;    	Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);	&#xD;&#xA;    &#xD;&#xA;      Matrix4d M  = T*R2*R1*S;&#xD;&#xA;    &#xD;&#xA;      p1 = M*p1;&#xD;&#xA;      p2 = M*p2;&#xD;&#xA;    &#xD;&#xA;      // screen coordinates&#xD;&#xA;      double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;&#xD;&#xA;      double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;&#xD;&#xA;      double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;&#xD;&#xA;      double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // line rasterization algorithm with anti-aliasing and z-test&#xD;&#xA;      // (for lines with slope between -1 and 1)&#xD;&#xA;      //&#xD;&#xA;      int x  = round(x1);&#xD;&#xA;      int y  = round(y1);&#xD;&#xA;    &#xD;&#xA;      double I0 = 1.0;&#xD;&#xA;      double m = (y2-y1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;      bool up = true;&#xD;&#xA;      if (y2 &lt; y1) {&#xD;&#xA;        m = -m;&#xD;&#xA;        I0 = 0.0;&#xD;&#xA;        up = false;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      int nextY;&#xD;&#xA;      double z;&#xD;&#xA;      for ( ; x&lt;=x2; x++) {&#xD;&#xA;        if (up)&#xD;&#xA;          nextY = y+1;&#xD;&#xA;        else&#xD;&#xA;          nextY = y-1;&#xD;&#xA;    &#xD;&#xA;        // barycentric coordinates of the current point: (1-lambda, lambda),&#xD;&#xA;        // i.e.: x = (1-lambda) x1 + lambda x2&#xD;&#xA;        double lambda = (x-x1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;        // perspectively correct linear interpolation of z-values&#xD;&#xA;        z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );&#xD;&#xA;    &#xD;&#xA;        if ( (zBuffer[x+y*w] &lt; 0) || z &lt; zBuffer[x+y*w] ) {&#xD;&#xA;          int I = (int) 255*I0;&#xD;&#xA;     	    image-&gt;setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );&#xD;&#xA;     	    image-&gt;setPixel( x, nextY, qRgb(     I, 255,     I ) );&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (m &gt; I0) {&#xD;&#xA;          y  = nextY;&#xD;&#xA;          I0 += 1.0;&#xD;&#xA;        }&#xD;&#xA;        I0 -= m;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // repaint canvas&#xD;&#xA;      repaint();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the output is not as expected, because one of the pixels of the lines on the sphere is coloured white. Of course we notice this immediately! The idea is to make a smoother line that considers not only the colour of the background but also the colour of the sphere.&#xD;&#xA;&#xD;&#xA;I thought I need to interpolate colours, but I'm not sure which ones and how to do it. I know that the basic idea of interpolation is to find an intermediate colour between two (or more) colours ($C_1, C_2$) using a formula as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(1 - \alpha) C_1 + \alpha * C_2$$&#xD;&#xA;&#xD;&#xA;Now the problem is that I don't know what's exactly $\alpha$ and which colours would be $C_1$ and $C_2$.  I thought $\alpha$ could be the `lambda` variable in the code above, but this is more than a guess than a conclusion after a logical reasoning. &#xD;&#xA;&#xD;&#xA;Moreover, I guessed that the colours $C_1$ and $C_2$ are respectively the color of the pixel before the rasterization of the line (i.e. in the ray tracing part), which can also be the color of the sphere, if that pixel is covered by the sphere, or the background color, i.e. white in my case. &#xD;&#xA;&#xD;&#xA;Any help is appreciated.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To give you an idea, this is the wrong output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;and this should be the correct one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note (if you zoom in) that the line in the first picture is not that smooth over the sphere, because one of the pixels (at least) is colored for the background color white.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;After trying to interpolate green and the current background color (as also Nathan Reed suggested), I obtained:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;which is correct in the sense that I think that the interpolation is being done correctly, but at this point I think interpolation is not what we need to do to obtain a smooth line.&#xD;&#xA;&#xD;&#xA;To obtain this I just added a few lines when setting the pixels of the line:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int I = (int)255 * I0;&#xD;&#xA;&#xD;&#xA;    Color3d c = pixels_colors[x + y * w]; &#xD;&#xA;    // pixels_buffer contains the color at pixel x + y * w&#xD;&#xA;    // this color was saved while ray tracing the sphere&#xD;&#xA;&#xD;&#xA;    c.clamped();&#xD;&#xA;&#xD;&#xA;    int red = c.r() * 255;&#xD;&#xA;    int green = c.g() * 255;&#xD;&#xA;    int blue = c.b() * 255;&#xD;&#xA;&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(red - I, green, blue - I));&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(I, green, I));&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q0tnC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TIUz7.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rm0BZ.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9480" PostHistoryTypeId="5" PostId="4263" RevisionGUID="7efcf8c7-2df1-4b81-81df-b04395d1f56e" CreationDate="2016-11-13T00:37:03.173" UserDisplayName="user4718" Comment="added 928 characters in body" Text="I've to rasterize a line taking into account not only the background color of the screen, which is white, but also the color of other objects in the scene. In my case, I've just another object, a sphere, which is actually visualized using a ray tracing technique. &#xD;&#xA;&#xD;&#xA;So far the code that I have seems only to consider the white background color of the screen and not also the color of the sphere.&#xD;&#xA;&#xD;&#xA;So here's the code:&#xD;&#xA;&#xD;&#xA;      // ray tracing of the sphere&#xD;&#xA;      // here we initialize the z-buffer's elements to -1.0 zBuffer that you find below&#xD;&#xA;      ...&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // rasterize a line&#xD;&#xA;      //&#xD;&#xA;    &#xD;&#xA;      // line from p1 to p2 in LOCAL coordinates&#xD;&#xA;      Point3d p1 (-1.0, 0.0, 0.0);&#xD;&#xA;      Point3d p2 ( 1.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // transformations...&#xD;&#xA;    	Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);&#xD;&#xA;    	Matrix4d R1 = Matrix4d::rotation (0.5,'z');&#xD;&#xA;    	Matrix4d R2 = Matrix4d::rotation (tau,'x');&#xD;&#xA;    	Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);	&#xD;&#xA;    &#xD;&#xA;      Matrix4d M  = T*R2*R1*S;&#xD;&#xA;    &#xD;&#xA;      p1 = M*p1;&#xD;&#xA;      p2 = M*p2;&#xD;&#xA;    &#xD;&#xA;      // screen coordinates&#xD;&#xA;      double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;&#xD;&#xA;      double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;&#xD;&#xA;      double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;&#xD;&#xA;      double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;&#xD;&#xA;    &#xD;&#xA;      //&#xD;&#xA;      // line rasterization algorithm with anti-aliasing and z-test&#xD;&#xA;      // (for lines with slope between -1 and 1)&#xD;&#xA;      //&#xD;&#xA;      int x  = round(x1);&#xD;&#xA;      int y  = round(y1);&#xD;&#xA;    &#xD;&#xA;      double I0 = 1.0;&#xD;&#xA;      double m = (y2-y1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;      bool up = true;&#xD;&#xA;      if (y2 &lt; y1) {&#xD;&#xA;        m = -m;&#xD;&#xA;        I0 = 0.0;&#xD;&#xA;        up = false;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      int nextY;&#xD;&#xA;      double z;&#xD;&#xA;      for ( ; x&lt;=x2; x++) {&#xD;&#xA;        if (up)&#xD;&#xA;          nextY = y+1;&#xD;&#xA;        else&#xD;&#xA;          nextY = y-1;&#xD;&#xA;    &#xD;&#xA;        // barycentric coordinates of the current point: (1-lambda, lambda),&#xD;&#xA;        // i.e.: x = (1-lambda) x1 + lambda x2&#xD;&#xA;        double lambda = (x-x1) / (x2-x1);&#xD;&#xA;    &#xD;&#xA;        // perspectively correct linear interpolation of z-values&#xD;&#xA;        z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );&#xD;&#xA;    &#xD;&#xA;        if ( (zBuffer[x+y*w] &lt; 0) || z &lt; zBuffer[x+y*w] ) {&#xD;&#xA;          int I = (int) 255*I0;&#xD;&#xA;     	    image-&gt;setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );&#xD;&#xA;     	    image-&gt;setPixel( x, nextY, qRgb(     I, 255,     I ) );&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (m &gt; I0) {&#xD;&#xA;          y  = nextY;&#xD;&#xA;          I0 += 1.0;&#xD;&#xA;        }&#xD;&#xA;        I0 -= m;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // repaint canvas&#xD;&#xA;      repaint();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now the output is not as expected, because one of the pixels of the lines on the sphere is coloured white. Of course we notice this immediately! The idea is to make a smoother line that considers not only the colour of the background but also the colour of the sphere.&#xD;&#xA;&#xD;&#xA;I thought I need to interpolate colours, but I'm not sure which ones and how to do it. I know that the basic idea of interpolation is to find an intermediate colour between two (or more) colours ($C_1, C_2$) using a formula as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(1 - \alpha) C_1 + \alpha * C_2$$&#xD;&#xA;&#xD;&#xA;Now the problem is that I don't know what's exactly $\alpha$ and which colours would be $C_1$ and $C_2$.  I thought $\alpha$ could be the `lambda` variable in the code above, but this is more than a guess than a conclusion after a logical reasoning. &#xD;&#xA;&#xD;&#xA;Moreover, I guessed that the colours $C_1$ and $C_2$ are respectively the color of the pixel before the rasterization of the line (i.e. in the ray tracing part), which can also be the color of the sphere, if that pixel is covered by the sphere, or the background color, i.e. white in my case. &#xD;&#xA;&#xD;&#xA;Any help is appreciated.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To give you an idea, this is the wrong output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;and this should be the correct one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note (if you zoom in) that the line in the first picture is not that smooth over the sphere, because one of the pixels (at least) is colored for the background color white.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;After trying to interpolate green and the current background color (as also Nathan Reed suggested), I obtained:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;which is correct in the sense that I think that the interpolation is being done correctly, but at this point I think interpolation is not what we need to do to obtain a smooth line.&#xD;&#xA;&#xD;&#xA;To obtain this I just added a few lines when setting the pixels of the line:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int I = (int)255 * I0;&#xD;&#xA;&#xD;&#xA;    Color3d c = pixels_colors[x + y * w]; &#xD;&#xA;    // pixels_buffer contains the color at pixel x + y * w&#xD;&#xA;    // this color was saved while ray tracing the sphere&#xD;&#xA;&#xD;&#xA;    c.clamped();&#xD;&#xA;&#xD;&#xA;    int red = c.r() * 255;&#xD;&#xA;    int green = c.g() * 255;&#xD;&#xA;    int blue = c.b() * 255;&#xD;&#xA;&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(red - I, green, blue - I));&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(I, green, I));&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Edit 2**&#xD;&#xA;&#xD;&#xA;After the corrections suggested by Nathan Reed, I obtained:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The colors of the pixels of the line over the sphere now really seem to be the product of the interpolation between the color green and the color of the sphere. Here's the code:&#xD;&#xA;&#xD;&#xA;    int I = (int)255 * I0;&#xD;&#xA;&#xD;&#xA;    Color3d background_color = pixels_colors[x + y * w];&#xD;&#xA;    Color3d green(0, 1.0, 0);&#xD;&#xA;&#xD;&#xA;    Color3d color_y = (1 - I0) * background_color + I0 * green;&#xD;&#xA;    Color3d color_next_y = I0 * background_color + (1 - I0) * green;&#xD;&#xA;&#xD;&#xA;    image-&gt;setPixel(x, nextY, qRgb(color_y.r() * 255, color_y.g() * 255, color_y.b() * 255));&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(color_next_y.r() * 255, color_next_y.g() * 255, color_next_y.b() * 255));&#xD;&#xA;&#xD;&#xA;If this is now correct, the picture still doesn't look as it should. I think we may need to color more pixels?!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q0tnC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TIUz7.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rm0BZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3NSRw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9481" PostHistoryTypeId="2" PostId="4265" RevisionGUID="475dc416-5027-41ca-9cda-90c07e887ad9" CreationDate="2016-11-13T12:04:04.140" UserId="5476" Text="Given a cube defined as:&#xD;&#xA;&#xD;&#xA;    struct Cube&#xD;&#xA;    {&#xD;&#xA;        float min[3];&#xD;&#xA;        float size;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;What would be the fastest rasterization method? On the internet I only found methods that used polygons, but I think for only drawing a cube thats extremely ineffective. I don't need any depth information, I want the result to be a shadeless silhouette. " ContentLicense="CC BY-SA 3.0" />
  <row Id="9482" PostHistoryTypeId="1" PostId="4265" RevisionGUID="475dc416-5027-41ca-9cda-90c07e887ad9" CreationDate="2016-11-13T12:04:04.140" UserId="5476" Text="Non-Polygonal 3D cube rasterization" ContentLicense="CC BY-SA 3.0" />
  <row Id="9483" PostHistoryTypeId="3" PostId="4265" RevisionGUID="475dc416-5027-41ca-9cda-90c07e887ad9" CreationDate="2016-11-13T12:04:04.140" UserId="5476" Text="|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9485" PostHistoryTypeId="2" PostId="4267" RevisionGUID="c735dacb-7429-4814-a40f-7832bc43257a" CreationDate="2016-11-13T16:58:26.610" UserId="1952" Text="Since the cube is a convex object, you could first find the silhouette edges of the cube, by using dot product between cube face normals &amp; view vectors. Then you can sort the edges by the smallest y-coordinate for each edge and rasterize the cube a scanline at the time by filling the span between two active edges for each scanline. For each scanline you progress the two edges by adding the edge slopes (x1-x0)/(y1-y0) to the current x-coordinate of the edges.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9486" PostHistoryTypeId="5" PostId="4267" RevisionGUID="b5bbf48b-daa6-4af6-9dd5-4a1ebe73e883" CreationDate="2016-11-13T17:03:28.437" UserId="1952" Comment="added 7 characters in body" Text="Since the cube is a convex object, you could first find the silhouette edges of the cube, by using dot product between cube face normals &amp; view vectors. Then you can sort the edges by the smallest screen y-coordinate for each edge and rasterize the cube a scanline at the time by filling the span between two active edges for each scanline. For each scanline you progress the two edges by adding the edge slopes (x1-x0)/(y1-y0) to the current x-coordinate of the edges.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9487" PostHistoryTypeId="2" PostId="4268" RevisionGUID="22dff537-13d8-4131-b089-d12531919fce" CreationDate="2016-11-13T19:50:31.847" UserId="5478" Text="I am trying to figure out how to apply the proper sequence of translate and scale commands (or a single .transform command) so that the default pixel grid (0,0,1920,1080) for instance is setup so that the coordinate system  (minx,miny,maxx,maxy) can be used where for instance &#xD;&#xA;minx=100 maxx=200 miny=-5 maxy=5&#xD;&#xA;&#xD;&#xA;I am trying to render mathematical functions and map the results to pixels and use the mouse to select certain regions to zoom in on.. my current code is at &#xD;&#xA;&#xD;&#xA;https://bitbucket.org/stephenc214/fastmath/src/default/src/fastmath/fx/HardyZMap.java&#xD;&#xA;&#xD;&#xA;I would really appreciate any help... I know this is simple but I just can't seem to get it to work properly&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9488" PostHistoryTypeId="1" PostId="4268" RevisionGUID="22dff537-13d8-4131-b089-d12531919fce" CreationDate="2016-11-13T19:50:31.847" UserId="5478" Text="how to map rectangular coordinate system onto JavaFX GraphicsContext canvas" ContentLicense="CC BY-SA 3.0" />
  <row Id="9489" PostHistoryTypeId="3" PostId="4268" RevisionGUID="22dff537-13d8-4131-b089-d12531919fce" CreationDate="2016-11-13T19:50:31.847" UserId="5478" Text="|transformations|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9490" PostHistoryTypeId="2" PostId="4269" RevisionGUID="d65e0b73-ce04-4285-8162-841b445496d0" CreationDate="2016-11-13T20:07:07.500" UserId="4958" Text="Made a new question as suggested, follow up to that [one][1].&#xD;&#xA;&#xD;&#xA;I was experimenting with texture declaration to find solution and thats how I done that before (`unsigned int`):&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_3D, m_texture);&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER, &#xD;&#xA;    GL_UNSIGNED_INT, NULL);&#xD;&#xA;    glGenerateMipap(GL_TEXTURE_3D);&#xD;&#xA;    &#xD;&#xA;    glGenSamplers(1, &amp;m_sampler);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And for that using `imagestore` for `int`/`unsigned int` didnt work despite correct binding for writing as `uimage` , `rgba32ui`, `uvec4` format and for reading as `usampler`, `uvec4` format. Of course also binding `sampler` object for reading.&#xD;&#xA;&#xD;&#xA;But I added two lines:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_3D, m_texture);&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER, &#xD;&#xA;    GL_UNSIGNED_INT, NULL);&#xD;&#xA;    &#xD;&#xA;    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); //&#xD;&#xA;    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); //&#xD;&#xA;    &#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_3D);&#xD;&#xA;    &#xD;&#xA;    glGenSamplers(1, &amp;m_sampler);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And now it seems to work. But I fail to see any logic in this. I use `sampler` objects to set texture filtering not `glTexParameteri` functions. &#xD;&#xA;&#xD;&#xA;`Float` textures work with `sampler` objects only. Anyone can explain?&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/4197/setting-up-integer-texture-and-binding-as-image" ContentLicense="CC BY-SA 3.0" />
  <row Id="9491" PostHistoryTypeId="1" PostId="4269" RevisionGUID="d65e0b73-ce04-4285-8162-841b445496d0" CreationDate="2016-11-13T20:07:07.500" UserId="4958" Text="setting up integer texture and binding as image pt. 2" ContentLicense="CC BY-SA 3.0" />
  <row Id="9492" PostHistoryTypeId="3" PostId="4269" RevisionGUID="d65e0b73-ce04-4285-8162-841b445496d0" CreationDate="2016-11-13T20:07:07.500" UserId="4958" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9493" PostHistoryTypeId="2" PostId="4270" RevisionGUID="cc505ab4-644a-49a7-bb46-a3be010dd116" CreationDate="2016-11-13T20:13:16.387" UserId="1952" Text="You can map [x, y] pixel coordinates in an image of size [width, height] to your given range as follows:&#xD;&#xA;&#xD;&#xA;    x'=minx+(maxx-minx)*(x+0.5)/width;&#xD;&#xA;    y'=miny+(maxy-miny)*(y+0.5)/height;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9494" PostHistoryTypeId="5" PostId="4269" RevisionGUID="172e1098-94c2-495d-ba4b-08e956caf4c3" CreationDate="2016-11-13T20:30:40.423" UserId="4958" Comment="added 21 characters in body" Text="Made a new question as suggested, follow up to that [one][1].&#xD;&#xA;&#xD;&#xA;I was experimenting with texture declaration to find solution and thats how I done that before (`unsigned int`):&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_3D, m_texture);&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER, &#xD;&#xA;    GL_UNSIGNED_INT, NULL);&#xD;&#xA;    glGenerateMipap(GL_TEXTURE_3D);&#xD;&#xA;    &#xD;&#xA;    glGenSamplers(1, &amp;m_sampler);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And for that using `imagestore` for `int`/`unsigned int` didnt work despite correct binding for writing as `uimage` , `rgba32ui`, `uvec4` format and for reading as `usampler`, `uvec4` format. Of course also binding `sampler` object for reading.&#xD;&#xA;&#xD;&#xA;But I added two lines:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_3D, m_texture);&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER, &#xD;&#xA;    GL_UNSIGNED_INT, NULL);&#xD;&#xA;    &#xD;&#xA;    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); //&#xD;&#xA;    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); //&#xD;&#xA;    &#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_3D);&#xD;&#xA;    &#xD;&#xA;    glGenSamplers(1, &amp;m_sampler);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And now it seems to work. Still need to bind `sampler` thought. But I fail to see any logic in this. I use [sampler][2] objects to set texture filtering not `glTexParameteri` functions. &#xD;&#xA;&#xD;&#xA;`Float` textures work with `sampler` objects as in first block of code. Anyone can explain?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/4197/setting-up-integer-texture-and-binding-as-image&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Sampler_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="9498" PostHistoryTypeId="2" PostId="4271" RevisionGUID="15089622-c3cc-44b5-924a-318f7aad89f8" CreationDate="2016-11-14T16:01:54.830" UserId="2654" Text="&gt; I use sampler objects to set texture filtering not `glTexParameteri` functions. &#xD;&#xA;&#xD;&#xA;No, you do not. [Image Load/Store][1] doesn't use samplers.&#xD;&#xA;&#xD;&#xA;Sure, it doesn't use the [built-in sampler data stored in a texture object][2] *either*. However, those parameters *do* have an effect. They can determine if a texture is *complete*.&#xD;&#xA;&#xD;&#xA;And *whether you're using those parameters or not*, if a texture is not complete, you can't access the texture from the GPU. Among the texture completeness rules is that the texture's sampling parameters must be valid, with respect to the texture's image format.&#xD;&#xA;&#xD;&#xA;The default filtering parameters for textures are some form of LINEAR filtering; OpenGL does not change these defaults based on the image format. Therefore, a fresh texture with an integer image format will be incomplete *unless* you explicitly set the mag/min filters to `GL_NEAREST` (or `NEAREST_MIPMAP_NEARSEST` for min).&#xD;&#xA;&#xD;&#xA;You can get away with what you've when using the texture with [sampler objects][3] because their parameters override the completeness check. But as previously mentioned, Image Load/Store doesn't care about the bound sampler objects. Therefore, the completeness check must look at the texture's sampling parameters.&#xD;&#xA;&#xD;&#xA;This is regardless of the fact that Image Load/Store itself doesn't actually *use* those parameters. So it's pointless, but you've gotta do it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Image_Load_Store&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Texture#Texture_Objects&#xD;&#xA;  [3]: https://www.opengl.org/wiki/Sampler_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="9499" PostHistoryTypeId="5" PostId="4271" RevisionGUID="db1a0b1c-5811-40bd-b34d-3167d16ef295" CreationDate="2016-11-14T16:10:41.983" UserId="2654" Comment="added 138 characters in body" Text="&gt; I use sampler objects to set texture filtering not `glTexParameteri` functions. &#xD;&#xA;&#xD;&#xA;No, you do not. [Image Load/Store][1] doesn't use samplers, so you cannot be using sampler objects to set the texture's filtering, when you're using the texture with Image Load/Store.&#xD;&#xA;&#xD;&#xA;Sure, Image Load/Store doesn't use the [built-in sampler data stored in a texture object][2] *either*. However, those parameters *do* have an effect. They can determine if a texture is *complete*.&#xD;&#xA;&#xD;&#xA;And *whether you're using those parameters or not*, if a texture is not complete, you can't access the texture from the GPU. Among the texture completeness rules is that the texture's sampling parameters must be valid, with respect to the texture's image format.&#xD;&#xA;&#xD;&#xA;The default filtering parameters for textures are some form of LINEAR filtering; OpenGL does not change these defaults based on the image format. Therefore, a fresh texture with an integer image format will be incomplete *unless* you explicitly set the mag/min filters to `GL_NEAREST` (or `NEAREST_MIPMAP_NEARSEST` for min).&#xD;&#xA;&#xD;&#xA;You can get away with what you've when using the texture with [sampler objects][3] because their parameters override the completeness check. But as previously mentioned, Image Load/Store doesn't care about the bound sampler objects. Therefore, the completeness check must look at the texture's sampling parameters.&#xD;&#xA;&#xD;&#xA;This is regardless of the fact that Image Load/Store itself doesn't actually *use* those parameters. So it's pointless, but you've gotta do it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Image_Load_Store&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Texture#Texture_Objects&#xD;&#xA;  [3]: https://www.opengl.org/wiki/Sampler_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="9500" PostHistoryTypeId="5" PostId="4271" RevisionGUID="97b81917-8887-4ec5-a19b-9941b92aa668" CreationDate="2016-11-14T18:06:49.460" UserId="231" Comment="Minor typo" Text="&gt; I use sampler objects to set texture filtering not `glTexParameteri` functions. &#xD;&#xA;&#xD;&#xA;No, you do not. [Image Load/Store][1] doesn't use samplers, so you cannot be using sampler objects to set the texture's filtering, when you're using the texture with Image Load/Store.&#xD;&#xA;&#xD;&#xA;Sure, Image Load/Store doesn't use the [built-in sampler data stored in a texture object][2] *either*. However, those parameters *do* have an effect. They can determine if a texture is *complete*.&#xD;&#xA;&#xD;&#xA;And *whether you're using those parameters or not*, if a texture is not complete, you can't access the texture from the GPU. Among the texture completeness rules is that the texture's sampling parameters must be valid, with respect to the texture's image format.&#xD;&#xA;&#xD;&#xA;The default filtering parameters for textures are some form of LINEAR filtering; OpenGL does not change these defaults based on the image format. Therefore, a fresh texture with an integer image format will be incomplete *unless* you explicitly set the mag/min filters to `GL_NEAREST` (or `NEAREST_MIPMAP_NEAREST` for min).&#xD;&#xA;&#xD;&#xA;You can get away with what you have when using the texture with [sampler objects][3] because their parameters override the completeness check. But as previously mentioned, Image Load/Store doesn't care about the bound sampler objects. Therefore, the completeness check must look at the texture's sampling parameters.&#xD;&#xA;&#xD;&#xA;This is regardless of the fact that Image Load/Store itself doesn't actually *use* those parameters. So it's pointless, but you've gotta do it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Image_Load_Store&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Texture#Texture_Objects&#xD;&#xA;  [3]: https://www.opengl.org/wiki/Sampler_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="9501" PostHistoryTypeId="2" PostId="4272" RevisionGUID="3047a7d6-7ce3-48a8-a74f-e45793ed48ab" CreationDate="2016-11-14T19:00:57.030" UserId="5482" Text="I have a cylinder  that has rectangular box  regions to mark the leakage problem. The location of the rectangular box is determined by its initial position in the longitudinal axis and its initial position in the circumferential axis in degree. The length  and width (in degrees, from 0° to 360°) of the boxes are also available.&#xD;&#xA;&#xD;&#xA;How to convert this cylinder to plane surface so that I could locate the location of rectangular boxes in 2D plane?&#xD;&#xA;Here I have  three rectangles on the surface.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qMBWR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9502" PostHistoryTypeId="1" PostId="4272" RevisionGUID="3047a7d6-7ce3-48a8-a74f-e45793ed48ab" CreationDate="2016-11-14T19:00:57.030" UserId="5482" Text="Mapping of cyllender to 2D plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="9503" PostHistoryTypeId="3" PostId="4272" RevisionGUID="3047a7d6-7ce3-48a8-a74f-e45793ed48ab" CreationDate="2016-11-14T19:00:57.030" UserId="5482" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9505" PostHistoryTypeId="5" PostId="4272" RevisionGUID="f07cfc69-c625-4f47-b6c9-e6ca2e0aa757" CreationDate="2016-11-14T22:35:06.023" UserId="231" Comment="Tidying" Text="I have a cylinder that has rectangular box regions to mark leakage problems. The location of a rectangular box is determined by its initial position in the longitudinal axis and its initial position in the circumferential axis in degree. The length  and width (in degrees, from 0° to 360°) of the boxes are also available.&#xD;&#xA;&#xD;&#xA;How can I convert this cylinder to a plane surface so that I can find the location of the rectangular boxes in the 2D plane?  &#xD;&#xA;Here I have  three rectangles on the surface.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qMBWR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9506" PostHistoryTypeId="4" PostId="4272" RevisionGUID="f07cfc69-c625-4f47-b6c9-e6ca2e0aa757" CreationDate="2016-11-14T22:35:06.023" UserId="231" Comment="Tidying" Text="Mapping of cylinder to 2D plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="9508" PostHistoryTypeId="2" PostId="4274" RevisionGUID="b4557090-27d9-46f0-9700-7146c22c20b6" CreationDate="2016-11-15T07:32:44.550" UserId="5488" Text="I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical `LookAt` view matrix.&#xD;&#xA;&#xD;&#xA;The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;(\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &amp;= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\&#xD;&#xA;&amp;= \begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; \sin{y} &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;-\sin{y} &amp; 0 &amp; \cos{y} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos{p} &amp; -\sin{p} &amp; 0 \\&#xD;&#xA;0 &amp; \sin{p} &amp; \cos{p} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; -\sin{y} &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;\sin{y} &amp; 0 &amp; \cos{y} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; 0\\&#xD;&#xA;0 &amp; -\sin{p} &amp; \cos{p} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -e_0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; -e_1\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -e_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; \sin{p}\sin{y} &amp; -\cos{p}\sin{y} &amp; -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\&#xD;&#xA;\sin{y} &amp; -\cos{y}\sin{p} &amp; \cos{p}\cos{y} &amp; -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Every step is double checked using WolframAlpha.&#xD;&#xA;&#xD;&#xA;The implementation:&#xD;&#xA;&#xD;&#xA;    inline Matrix4&#xD;&#xA;    FPSView(const Vector3&amp; eyePosition, float yaw, float pitch) noexcept&#xD;&#xA;    {&#xD;&#xA;      yaw = Utils::Radians(yaw);&#xD;&#xA;      pitch = Utils::Radians(pitch);&#xD;&#xA;&#xD;&#xA;      float sinYaw = std::sin(yaw);&#xD;&#xA;      float cosYaw = std::cos(yaw);&#xD;&#xA;&#xD;&#xA;      float sinPitch = std::sin(pitch);&#xD;&#xA;      float cosPitch = std::cos(pitch);&#xD;&#xA;&#xD;&#xA;      const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};&#xD;&#xA;      const Vector3 j{0, cosPitch, sinPitch};&#xD;&#xA;      const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};&#xD;&#xA;&#xD;&#xA;      return {&#xD;&#xA;        {i[0], i[1], i[2], -i.Dot(eyePosition)},&#xD;&#xA;        {j[0], j[1], j[2], -j.Dot(eyePosition)},&#xD;&#xA;        {k[0], k[1], k[2], -k.Dot(eyePosition)},&#xD;&#xA;        {0,    0,    0,    1},&#xD;&#xA;      };&#xD;&#xA;    }&#xD;&#xA;   &#xD;&#xA;   It works fine except that _the yaw is inverted_, i.e. increasing the angle causes the object to go right while it should go left.&#xD;&#xA;&#xD;&#xA;I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand _why this is happening_?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9509" PostHistoryTypeId="1" PostId="4274" RevisionGUID="b4557090-27d9-46f0-9700-7146c22c20b6" CreationDate="2016-11-15T07:32:44.550" UserId="5488" Text="Inverted yaw angle in the view matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="9510" PostHistoryTypeId="3" PostId="4274" RevisionGUID="b4557090-27d9-46f0-9700-7146c22c20b6" CreationDate="2016-11-15T07:32:44.550" UserId="5488" Text="|transformations|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9511" PostHistoryTypeId="5" PostId="4274" RevisionGUID="ec0b7829-42c7-4c74-bf2c-f3a315362889" CreationDate="2016-11-15T09:53:04.573" UserId="5488" Comment="added 22 characters in body" Text="I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical `LookAt` view matrix.&#xD;&#xA;&#xD;&#xA;The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;(\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &amp;= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\&#xD;&#xA;&amp;= \begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; \sin{y} &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;-\sin{y} &amp; 0 &amp; \cos{y} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos{p} &amp; -\sin{p} &amp; 0 \\&#xD;&#xA;0 &amp; \sin{p} &amp; \cos{p} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; -\sin{y} &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;\sin{y} &amp; 0 &amp; \cos{y} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; 0\\&#xD;&#xA;0 &amp; -\sin{p} &amp; \cos{p} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -e_0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; -e_1\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -e_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; \sin{p}\sin{y} &amp; -\cos{p}\sin{y} &amp; -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\&#xD;&#xA;\sin{y} &amp; -\cos{y}\sin{p} &amp; \cos{p}\cos{y} &amp; -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Every step is double checked using WolframAlpha.&#xD;&#xA;&#xD;&#xA;The implementation:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    inline Matrix4&#xD;&#xA;    FPSViewRH(const Vector3&amp; eyePosition, float yaw, float pitch) noexcept&#xD;&#xA;    {&#xD;&#xA;      yaw = Utils::Radians(yaw);&#xD;&#xA;      pitch = Utils::Radians(pitch);&#xD;&#xA;&#xD;&#xA;      const auto sinYaw = std::sin(yaw);&#xD;&#xA;      const auto cosYaw = std::cos(yaw);&#xD;&#xA;&#xD;&#xA;      const auto sinPitch = std::sin(pitch);&#xD;&#xA;      const auto cosPitch = std::cos(pitch);&#xD;&#xA;&#xD;&#xA;      const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};&#xD;&#xA;      const Vector3 j{0, cosPitch, sinPitch};&#xD;&#xA;      const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};&#xD;&#xA;&#xD;&#xA;      return {&#xD;&#xA;        {i[0], i[1], i[2], -i.Dot(eyePosition)},&#xD;&#xA;        {j[0], j[1], j[2], -j.Dot(eyePosition)},&#xD;&#xA;        {k[0], k[1], k[2], -k.Dot(eyePosition)},&#xD;&#xA;        {0,    0,    0,    1},&#xD;&#xA;      };&#xD;&#xA;    }&#xD;&#xA;   &#xD;&#xA;   It works fine except that _the yaw is inverted_, i.e. increasing the angle causes the object to go right while it should go left.&#xD;&#xA;&#xD;&#xA;I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand _why this is happening_?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9519" PostHistoryTypeId="2" PostId="4276" RevisionGUID="636e178f-d6a8-4dbb-85d1-8bbe45fdbb4e" CreationDate="2016-11-15T13:48:27.740" UserDisplayName="user4718" Text="I've the following problem:&#xD;&#xA;&#xD;&#xA;&gt; Let the camera opening angle be $\frac{3}{4}\pi$ and the window be $15 \times 15$ pixels large. &#xD;&#xA;&#xD;&#xA;&gt; Which pixels does the midpoint algorithm (_without_ anti-aliasing) set for the line from $p_1 = (1, 1, 4)$ to $p_2 = (2, 1, 1)$, given in **global coordinates**?&#xD;&#xA;&#xD;&#xA;My question are:&#xD;&#xA;&#xD;&#xA;1. Why is the detail that the points are given in global coordinates important? &#xD;&#xA;&#xD;&#xA;2. Could the points be given in local coordinates? If yes, how would they would look like? How would that affect the answer?&#xD;&#xA;&#xD;&#xA;3. What would that mean local coordinates in this case?&#xD;&#xA;&#xD;&#xA;I think I understood what are local coordinates, i.e. coordinates of an object given with respect to a local system to the object. I think that global coordinates at the end are just local coordinates with respect to the camera or the viewer. Am I right?&#xD;&#xA;&#xD;&#xA;_Note: I'm not asking you to solve the problem, i.e. telling me which pixels are set, maybe I'm going to ask another question regarding that._" ContentLicense="CC BY-SA 3.0" />
  <row Id="9520" PostHistoryTypeId="1" PostId="4276" RevisionGUID="636e178f-d6a8-4dbb-85d1-8bbe45fdbb4e" CreationDate="2016-11-15T13:48:27.740" UserDisplayName="user4718" Text="Points of a line given in global coordinates to calculate the pixels that are set using the midpoint algorithm without anti-aliasing" ContentLicense="CC BY-SA 3.0" />
  <row Id="9521" PostHistoryTypeId="3" PostId="4276" RevisionGUID="636e178f-d6a8-4dbb-85d1-8bbe45fdbb4e" CreationDate="2016-11-15T13:48:27.740" UserDisplayName="user4718" Text="|antialiasing|rasterizer|midpoint|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9523" PostHistoryTypeId="5" PostId="3689" RevisionGUID="d181b5fd-bbb2-4414-a6c6-158b51176f5f" CreationDate="2016-11-15T21:39:12.463" UserId="2941" Comment="Fixed broken link to GI compendium. Attempt #2. No 404s now!" Text="I think the assumption (perhaps stated perhaps not, I dont' have the text handy) is that the radiance is emitted in a cosine-lobe distribution. This means that there's falloff in proportion to the cosine of the angle between the emitter's normal, and the direction of emission.&#xD;&#xA;&#xD;&#xA;If you look in the [global illumination compendium][1], under Hemispherical Geometry, equation set (30), you'll see that the integral over the hemisphere, modulated by a cosine lobe, is exactly pi. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://people.cs.kuleuven.be/~philip.dutre/GI/TotalCompendium.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9524" PostHistoryTypeId="24" PostId="3689" RevisionGUID="d181b5fd-bbb2-4414-a6c6-158b51176f5f" CreationDate="2016-11-15T21:39:12.463" Comment="Proposed by 2941 approved by 209, 56 edit id of 180" ContentLicense="CC BY-SA 3.0" />
  <row Id="9525" PostHistoryTypeId="2" PostId="4277" RevisionGUID="10818e76-2569-41e6-a408-884a9b5fe1d5" CreationDate="2016-11-15T21:53:23.963" UserId="2941" Text="[Wikipedia's path tracing algorithm][1] has the following line for the diffuse BRDF:&#xD;&#xA;&#xD;&#xA;    Color BRDF = 2 * m.reflectance * cos_theta;&#xD;&#xA;&#xD;&#xA;I'm a little confused as I've been reading that Lambertian surface BRDF is $\frac{\rho}{\pi}$ where $\rho$ is the reflectivity (albedo?) of the surface. Where does the $2$ come from?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Path_tracing#Algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="9526" PostHistoryTypeId="1" PostId="4277" RevisionGUID="10818e76-2569-41e6-a408-884a9b5fe1d5" CreationDate="2016-11-15T21:53:23.963" UserId="2941" Text="Derivation of Wikipedia's path tracing diffuse BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="9527" PostHistoryTypeId="3" PostId="4277" RevisionGUID="10818e76-2569-41e6-a408-884a9b5fe1d5" CreationDate="2016-11-15T21:53:23.963" UserId="2941" Text="|brdf|pathtracing|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9528" PostHistoryTypeId="2" PostId="4278" RevisionGUID="022911b6-edaf-4372-8de3-5521e2475b57" CreationDate="2016-11-16T00:00:33.477" UserId="3003" Text="When drawing objects that exist in 3D space to a 2D plane (like your monitor or an image), there are a number of spaces that are useful to work in:&#xD;&#xA;&#xD;&#xA; - Global Coordinates - Somewhere in your 3D world there is an origin, and objects will be placed relative to that origin. The camera will also be placed somewhere relative to that origin and will point in some direction in the world.&#xD;&#xA; - Object Coordinates - If you have 3D objects in your scene, they are generally created outside of the world and then transformed in some way to be placed in the world. You might create, say, a chair, with the origin of the chair where the front right leg touches the ground. In Object space, that's (0,0,0). But you'll transform that chair to where it needs to go in the scene and put it at some location in world (global) coordinates.&#xD;&#xA; - View Coordinates - Your virtual camera, as mentioned above, is placed somewhere and is pointing at something. Whatever your camera is pointing at will generate a space relative to the camera. You can think of the camera as always being at the origin of camera space.&#xD;&#xA; - Clip Space - eventually during rendering, you will use a projection matrix of some sort (perspective, orthographic, etc.) to render the final image. When running your geometry through this matrix, any coordinates that end up outside of [-1..1] will be clipped out. (In some cases [0..1] is used instead, but this detail doesn't change the point.)&#xD;&#xA;&#xD;&#xA; - Screen Space - finally, after you've clipped everything and gotten it into normalized coordinates, you then have to flatten it to 2D and display it to the user. This is screen space, and is often the same as the pixels (or some portion of them) on the user's physical display (or in an image if your rendering to an image)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9529" PostHistoryTypeId="2" PostId="4279" RevisionGUID="2384b3cf-bc5a-49d1-b687-2873d9383822" CreationDate="2016-11-16T00:25:28.440" UserId="5491" Text="I have written a standalone java program (ObjectVolume) which reads an object file (.obj) and calculates the surface area, centroid and volume of any closed triangular mesh. The program also displays the number of faces, the number of 3D coordinates and program run times. The program is in the public domain and is located at:&#xD;&#xA;&#xD;&#xA;https://sourceforge.net/projects/objectvolume/files/?source=navbar&#xD;&#xA;&#xD;&#xA;Included in a detail description of the process and the code.  The source code is included so you can add whatever you like.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9530" PostHistoryTypeId="5" PostId="4279" RevisionGUID="8ae6e055-4ae2-4bb0-a828-ba2adb4c9c7e" CreationDate="2016-11-16T00:30:34.487" UserId="5491" Comment="spelling and changed web address to summary page" Text="I have written a standalone java program (ObjectVolume) which reads an object file (.obj) and calculates the surface area, centroid and volume of any closed triangular mesh. The program also displays the number of faces, the number of 3D coordinates and program run times. The program is in the public domain and is located at:&#xD;&#xA;&#xD;&#xA;https://sourceforge.net/projects/objectvolume/?source=navbar&#xD;&#xA;&#xD;&#xA;Included is a detail description of the process and the code.  The source code is included so you can add whatever you like.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9531" PostHistoryTypeId="5" PostId="4278" RevisionGUID="fee16188-3e0d-4045-9938-1482aaf837e0" CreationDate="2016-11-16T00:54:54.297" UserId="3003" Comment="Added more explanation related to the problem at hand." Text="When drawing objects that exist in 3D space to a 2D plane (like your monitor or an image), there are a number of spaces that are useful to work in:&#xD;&#xA;&#xD;&#xA; - Global Coordinates - Somewhere in your 3D world there is an origin, and objects will be placed relative to that origin. The camera will also be placed somewhere relative to that origin and will point in some direction in the world.&#xD;&#xA; - Object Coordinates - If you have 3D objects in your scene, they are generally created outside of the world and then transformed in some way to be placed in the world. You might create, say, a chair, with the origin of the chair where the front right leg touches the ground. In Object space, that's (0,0,0). But you'll transform that chair to where it needs to go in the scene and put it at some location in world (global) coordinates.&#xD;&#xA; - View Coordinates - Your virtual camera, as mentioned above, is placed somewhere and is pointing at something. Whatever your camera is pointing at will generate a space relative to the camera. You can think of the camera as always being at the origin of camera space.&#xD;&#xA; - Clip Space - eventually during rendering, you will use a projection matrix of some sort (perspective, orthographic, etc.) to render the final image. When running your geometry through this matrix, any coordinates that end up outside of [-1..1] will be clipped out. (In some cases [0..1] is used instead, but this detail doesn't change the point.)&#xD;&#xA;&#xD;&#xA; - Screen Space - finally, after you've clipped everything and gotten it into normalized coordinates, you then have to flatten it to 2D and display it to the user. This is screen space, and is often the same as the pixels (or some portion of them) on the user's physical display (or in an image if your rendering to an image).&#xD;&#xA;&#xD;&#xA;So in the original problem, you've been given the requirement of having a field of view for your camera of 135° (3/4π radians), and a window that's 15x15 pixels large. So you need to construct a projection matrix with a 135° field of view and an aspect ratio of 1:1. &#xD;&#xA;&#xD;&#xA;The view parameters aren't specified in your problem, so I guess the camera is at the world's origin, so camera/view space and world space are the same for now. &#xD;&#xA;&#xD;&#xA;Normally, you'd take the world coordinates, (`p1` and `p2`) and multiply them by the view matrix (identity here, so no work to do), then multiply that result by the projection matrix to get to clip space. Once you have coordinates in the normalized range, you can multiply them by the window's size (15x15 in this case) to get them into screen space and determine which pixels to set." ContentLicense="CC BY-SA 3.0" />
  <row Id="9532" PostHistoryTypeId="2" PostId="4280" RevisionGUID="3e81d6ce-3922-4a4a-82d0-da02fb60f102" CreationDate="2016-11-16T01:56:08.467" UserId="1952" Text="When you perform regular Monte Carlo integration over a hemisphere using $N$ samples, each sample represents $\frac{2\pi}{N}$ steradians. So the Monte Carlo integration for Lambertian BRDF is:&#xD;&#xA;&#xD;&#xA;$$\frac{2\pi}{N}\sum_{i=1}^N\frac{\rho}{\pi}L_i*Cos\theta_i$$&#xD;&#xA;&#xD;&#xA;For path tracing, you only take one sample per path segment, so because $N$=1, the above sum becomes:&#xD;&#xA;&#xD;&#xA;$$2\pi\frac{\rho}{\pi}L*Cos\theta = 2\rho L*Cos\theta$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="9533" PostHistoryTypeId="2" PostId="4281" RevisionGUID="0ee68cbc-b280-45e4-9f16-a14e69164071" CreationDate="2016-11-16T14:25:25.323" UserId="5493" Text="To be more concrete, I'm working on an iOS app, and have a `CATransform3D` struct (basically a 4x4 transform array).&#xD;&#xA;&#xD;&#xA;Is it possible to deduce all the different &quot;operations&quot; this matrix implies? Things like how much rotation, scale, etc. it implies?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9534" PostHistoryTypeId="1" PostId="4281" RevisionGUID="0ee68cbc-b280-45e4-9f16-a14e69164071" CreationDate="2016-11-16T14:25:25.323" UserId="5493" Text="Is it possible to turn a 3d rotation matrix (4x4) into its component parts (rotation, scale, etc.)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9535" PostHistoryTypeId="3" PostId="4281" RevisionGUID="0ee68cbc-b280-45e4-9f16-a14e69164071" CreationDate="2016-11-16T14:25:25.323" UserId="5493" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9536" PostHistoryTypeId="10" PostId="1687" RevisionGUID="68da86da-c060-4e39-9bc1-fb0c3c3b7692" CreationDate="2016-11-16T14:37:43.380" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9537" PostHistoryTypeId="2" PostId="4282" RevisionGUID="adcd4779-512b-49f7-8544-afc2069c96f1" CreationDate="2016-11-16T16:02:41.793" UserId="5488" Text="You can decompose the matrix $\mathbf{M} = \mathbf{TRS}$ into basic transformations: translation, scaling, and rotation. Given this matrix:&#xD;&#xA;&#xD;&#xA;$$\mathbf{M} = \begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02} &amp; a_{03}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12} &amp; a_{13}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22} &amp; a_{23}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can decompose the translation by inspection using the last column $\mathbf{t} = (a_{03}, a_{13}, a_{23})$.&#xD;&#xA;&#xD;&#xA;For scaling, we know that the first three columns of the matrix corresponds to the bases (axes). We can get the scale by the length/norm of these vectors, i.e. how much the bases were scaled. So the scale is $\mathbf{s} = (s_0, s_1, s_2)$ where:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;s_0 = \left \|(a_{00}, a_{10}, a_{20}) \right \|\\ &#xD;&#xA;s_1 = \left \|(a_{01}, a_{11}, a_{21}) \right \|\\ &#xD;&#xA;s_2 = \left \|(a_{02}, a_{12}, a_{22}) \right \|\\ &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Now you have the scale, you can get rid of it using the $3\times 3$ sub-matrix that corresponds to $\mathbf{RS}$ by multiplying the matrix with the inverse of the scale $\mathbf{S}^{-1}$ to get $\mathbf{R}$&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;\mathbf{(RS)S}^{-1} &amp;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; s_2&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1/s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; 1/s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; 1/s_2&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Thus ($\mathbf{(RS)S}^{-1} = \mathbf{RI} = \mathbf{R}$):&#xD;&#xA;&#xD;&#xA;$$\mathbf{R} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00}/s_0 &amp; a_{01}/s_1 &amp; a_{02}/s_2\\&#xD;&#xA;a_{10}/s_0 &amp; a_{11}/s_1 &amp; a_{12}/s_2\\&#xD;&#xA;a_{20}/s_0 &amp; a_{21}/s_1 &amp; a_{22}/s_2\\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This is the final rotation matrix. You can further decompose it using many ways. It is quit lengthy but you can search for _decomposing a rotation matrix_.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;This is an ugly way and it has problems with floating point precision, you should not use it unless you did not construct the matrix yourself. &#xD;&#xA;&#xD;&#xA;If you are the one who constructed the matrix and wanted the decomposition in order to be able to edit and display the translation, scale and rotation individually, you should store the components of $\mathbf{t}$, $\mathbf{s}$ and $\mathbf{r}$ in a transform class individually as vectors (maybe quaternion for the rotation). Only when you need the transform matrix, construct a $\mathbf{TRS}$ matrix from these components (You can cache the matrix until some component is changed)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9538" PostHistoryTypeId="5" PostId="4282" RevisionGUID="1b8465a5-566c-4d3d-a95b-6ebbf39c7554" CreationDate="2016-11-16T16:11:29.623" UserId="5488" Comment="added 57 characters in body" Text="You can decompose the matrix $\mathbf{M} = \mathbf{TRS}$ into basic transformations: translation, scaling, and rotation. Given this matrix:&#xD;&#xA;&#xD;&#xA;$$\mathbf{M} = \begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02} &amp; a_{03}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12} &amp; a_{13}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22} &amp; a_{23}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can decompose the translation by inspection using the last column $\mathbf{t} = (a_{03}, a_{13}, a_{23})$.&#xD;&#xA;&#xD;&#xA;For scaling, we know that the first three columns of the matrix corresponds to the bases (axes). We can get the scale by the length/norm of these vectors, i.e. how much the bases were scaled. So the scale is $\mathbf{s} = (s_0, s_1, s_2)$ where:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;s_0 = \left \|(a_{00}, a_{10}, a_{20}) \right \|\\ &#xD;&#xA;s_1 = \left \|(a_{01}, a_{11}, a_{21}) \right \|\\ &#xD;&#xA;s_2 = \left \|(a_{02}, a_{12}, a_{22}) \right \|\\ &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Now you have the scale, you can get rid of it using the $3\times 3$ sub-matrix that corresponds to $\mathbf{RS}$ by multiplying the matrix with the inverse of the scale $\mathbf{S}^{-1}$ to get $\mathbf{R}$&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;\mathbf{(RS)S}^{-1} &amp;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; s_2&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1/s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; 1/s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; 1/s_2&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Thus ($\mathbf{(RS)S}^{-1} = \mathbf{RI} = \mathbf{R}$):&#xD;&#xA;&#xD;&#xA;$$\mathbf{R} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00}/s_0 &amp; a_{01}/s_1 &amp; a_{02}/s_2\\&#xD;&#xA;a_{10}/s_0 &amp; a_{11}/s_1 &amp; a_{12}/s_2\\&#xD;&#xA;a_{20}/s_0 &amp; a_{21}/s_1 &amp; a_{22}/s_2\\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This is the final rotation matrix. You can further decompose it using many ways. It is quit lengthy but you can search for _decomposing a rotation matrix_.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;This is an ugly way, it only gives an equivalent values, and it has problems with floating point precision, you should not use it unless you did not construct the matrix yourself. &#xD;&#xA;&#xD;&#xA;If you are the one who constructed the matrix and wanted the decomposition in order to be able to edit and display the translation, scale and rotation individually and _independently_, you should store the components of $\mathbf{t}$, $\mathbf{s}$ and $\mathbf{r}$ in a transform class individually as vectors (maybe quaternion for the rotation). Only when you need the transform matrix, construct a $\mathbf{TRS}$ matrix from these components (You can cache the matrix until some component is changed)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9539" PostHistoryTypeId="5" PostId="4282" RevisionGUID="83ed688f-87ed-49f5-bf70-c6d804c7d77c" CreationDate="2016-11-16T16:25:29.657" UserId="5488" Comment="added 177 characters in body" Text="You can decompose the matrix $\mathbf{M} = \mathbf{TRS}$ into basic transformations: translation, scaling, and rotation. Given this matrix:&#xD;&#xA;&#xD;&#xA;$$\mathbf{M} = \begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02} &amp; a_{03}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12} &amp; a_{13}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22} &amp; a_{23}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can decompose the translation by inspection using the last column $\mathbf{t} = (a_{03}, a_{13}, a_{23})$.&#xD;&#xA;&#xD;&#xA;For scaling, we know that the first three columns of the matrix corresponds to the bases (axes). We can get the scale by the length/norm of these vectors, i.e. how much the bases were scaled. So the scale is $\mathbf{s} = (s_0, s_1, s_2)$ where:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;s_0 = \left \|(a_{00}, a_{10}, a_{20}) \right \|\\ &#xD;&#xA;s_1 = \left \|(a_{01}, a_{11}, a_{21}) \right \|\\ &#xD;&#xA;s_2 = \left \|(a_{02}, a_{12}, a_{22}) \right \|\\ &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Now you have the scale, you can get rid of it using the $3\times 3$ sub-matrix that corresponds to $\mathbf{RS}$ by multiplying the matrix with the inverse of the scale $\mathbf{S}^{-1}$ to get $\mathbf{R}$&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;\mathbf{(RS)S}^{-1} &amp;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; s_2&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1/s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; 1/s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; 1/s_2&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Thus ($\mathbf{(RS)S}^{-1} = \mathbf{RI} = \mathbf{R}$):&#xD;&#xA;&#xD;&#xA;$$\mathbf{R} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00}/s_0 &amp; a_{01}/s_1 &amp; a_{02}/s_2\\&#xD;&#xA;a_{10}/s_0 &amp; a_{11}/s_1 &amp; a_{12}/s_2\\&#xD;&#xA;a_{20}/s_0 &amp; a_{21}/s_1 &amp; a_{22}/s_2\\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This is the final rotation matrix. You can further decompose it using many ways. It is quit lengthy but you can search for _decomposing a rotation matrix_.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;This method only gives an equivalent values in the form of translation, scaling and rotation (the original matrix maybe the result of other types of transformations). It may has problems with floating point precision with the rotation angles if you further used the decomposed angles. You should not use it unless you did not construct the matrix yourself. &#xD;&#xA;&#xD;&#xA;If you are the one who constructed the matrix and wanted the decomposition in order to be able to edit and display the translation, scale and rotation individually and _independently_, you should store the components of $\mathbf{t}$, $\mathbf{s}$ and $\mathbf{r}$ in a transform class individually as vectors (maybe quaternion for the rotation). Only when you need the transform matrix, construct a $\mathbf{TRS}$ matrix from these components (You can cache the matrix until some component is changed)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9540" PostHistoryTypeId="5" PostId="4282" RevisionGUID="bc8c1149-217e-4e43-9d2e-80f94a522e7d" CreationDate="2016-11-16T16:30:53.197" UserId="5488" Comment="added 177 characters in body" Text="You can decompose the matrix $\mathbf{M} = \mathbf{TRS}$ into basic transformations: translation, scaling, and rotation. Given this matrix:&#xD;&#xA;&#xD;&#xA;$$\mathbf{M} = \begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02} &amp; a_{03}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12} &amp; a_{13}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22} &amp; a_{23}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can decompose the translation by inspection using the last column $\mathbf{t} = (a_{03}, a_{13}, a_{23})$.&#xD;&#xA;&#xD;&#xA;For scaling, we know that the first three columns of the matrix corresponds to the bases (axes). We can get the scale by the length/norm of these vectors, i.e. how much the bases were scaled. So the scale is $\mathbf{s} = (s_0, s_1, s_2)$ where:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;s_0 = \left \|(a_{00}, a_{10}, a_{20}) \right \|\\ &#xD;&#xA;s_1 = \left \|(a_{01}, a_{11}, a_{21}) \right \|\\ &#xD;&#xA;s_2 = \left \|(a_{02}, a_{12}, a_{22}) \right \|\\ &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Now you have the scale, you can get rid of it using the $3\times 3$ sub-matrix that corresponds to $\mathbf{RS}$ by multiplying the matrix with the inverse of the scale $\mathbf{S}^{-1}$ to get $\mathbf{R}$&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;\mathbf{(RS)S}^{-1} &amp;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; s_2&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00} &amp; a_{01} &amp; a_{02}\\&#xD;&#xA;a_{10} &amp; a_{11} &amp; a_{12}\\&#xD;&#xA;a_{20} &amp; a_{21} &amp; a_{22}\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1/s_0 &amp; 0 &amp; 0\\ &#xD;&#xA;0 &amp; 1/s_1 &amp; 0\\ &#xD;&#xA;0 &amp; 0 &amp; 1/s_2&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Thus ($\mathbf{(RS)S}^{-1} = \mathbf{RI} = \mathbf{R}$):&#xD;&#xA;&#xD;&#xA;$$\mathbf{R} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{00}/s_0 &amp; a_{01}/s_1 &amp; a_{02}/s_2\\&#xD;&#xA;a_{10}/s_0 &amp; a_{11}/s_1 &amp; a_{12}/s_2\\&#xD;&#xA;a_{20}/s_0 &amp; a_{21}/s_1 &amp; a_{22}/s_2\\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This is the final rotation matrix. You can further decompose it using many ways. It is quit lengthy but you can search for _decomposing a rotation matrix_.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;This method only gives an equivalent values in the form of translation, scaling and rotation (the original matrix maybe the result of other types of transformations). It may has problems with floating point precision with the rotation angles if you further used the decomposed angles, rounding errors may accumulate in the computations. You should not use it unless you did not construct the matrix yourself. &#xD;&#xA;&#xD;&#xA;If you are the one who constructed the matrix and wanted the decomposition in order to be able to edit and display the translation, scale and rotation individually and _independently_, probabbly the cleanest why is to store the components of $\mathbf{t}$, $\mathbf{s}$ and $\mathbf{r}$ in a transform class individually as vectors (maybe quaternion for the rotation). Only when you need the transform matrix, construct a $\mathbf{TRS}$ matrix from these components (You can cache the matrix until some component is changed)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9541" PostHistoryTypeId="5" PostId="4274" RevisionGUID="07f6daab-b5f0-421b-b8de-c4dce7f50a89" CreationDate="2016-11-16T18:23:35.190" UserId="5488" Comment="added 53 characters in body" Text="I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical `LookAt` view matrix.&#xD;&#xA;&#xD;&#xA;The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:&#xD;&#xA;&#xD;&#xA;$$\begin{align}&#xD;&#xA;(\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &amp;= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\&#xD;&#xA;&amp;= \begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; \sin{y} &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;-\sin{y} &amp; 0 &amp; \cos{y} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos{p} &amp; -\sin{p} &amp; 0 \\&#xD;&#xA;0 &amp; \sin{p} &amp; \cos{p} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; -\sin{y} &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;\sin{y} &amp; 0 &amp; \cos{y} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; 0\\&#xD;&#xA;0 &amp; -\sin{p} &amp; \cos{p} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -e_0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; -e_1\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -e_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; \sin{p}\sin{y} &amp; -\cos{p}\sin{y} &amp; -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\&#xD;&#xA;\sin{y} &amp; -\cos{y}\sin{p} &amp; \cos{p}\cos{y} &amp; -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Every step is double checked using WolframAlpha.&#xD;&#xA;&#xD;&#xA;The implementation:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    inline Matrix4&#xD;&#xA;    FPSViewRH(const Vector3&amp; eyePosition, float yaw, float pitch) noexcept&#xD;&#xA;    {&#xD;&#xA;      yaw = Utils::Radians(yaw);&#xD;&#xA;      pitch = Utils::Radians(pitch);&#xD;&#xA;&#xD;&#xA;      const auto sinYaw = std::sin(yaw);&#xD;&#xA;      const auto cosYaw = std::cos(yaw);&#xD;&#xA;&#xD;&#xA;      const auto sinPitch = std::sin(pitch);&#xD;&#xA;      const auto cosPitch = std::cos(pitch);&#xD;&#xA;&#xD;&#xA;      const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};&#xD;&#xA;      const Vector3 j{0, cosPitch, sinPitch};&#xD;&#xA;      const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};&#xD;&#xA;&#xD;&#xA;      return {&#xD;&#xA;        {i[0], i[1], i[2], -i.Dot(eyePosition)},&#xD;&#xA;        {j[0], j[1], j[2], -j.Dot(eyePosition)},&#xD;&#xA;        {k[0], k[1], k[2], -k.Dot(eyePosition)},&#xD;&#xA;        {0,    0,    0,    1},&#xD;&#xA;      };&#xD;&#xA;    }&#xD;&#xA;   &#xD;&#xA;   It works fine except that _the yaw is inverted_, i.e. increasing the angle causes the object to go right while it should go left.&#xD;&#xA;&#xD;&#xA;I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand _why this is happening_? or if there is an interpretation for this phenomena?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9542" PostHistoryTypeId="2" PostId="4283" RevisionGUID="fd53ca97-a8dc-4936-a33d-1769bd22a124" CreationDate="2016-11-16T18:55:06.673" UserId="1952" Text="It's happening because they just happened to define the rotation matrix with counterclockwise rotation direction, which is the common convention for polar$\rightarrow$cartesian coordinate system transformation. If you [google for the transformation][1], you'll see that the angle is universally shown to rotate to the counterclockwise direction like below&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.google.ca/search?q=polar%20to%20cartesian%20coordinates&amp;espv=2&amp;biw=1920&amp;bih=911&amp;source=lnms&amp;tbm=isch&amp;sa=X&amp;ved=0ahUKEwj_6qCA-K3QAhXi7YMKHcmQCwUQ_AUIBigB&amp;dpr=1#imgrc=_&#xD;&#xA;  [2]: https://i.stack.imgur.com/DU3pS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9544" PostHistoryTypeId="5" PostId="4274" RevisionGUID="108bcc2f-ab80-45da-a234-a8d7b4d7ea4a" CreationDate="2016-11-17T15:13:16.063" UserId="231" Comment="Make maths render small so that the right hand edge is not cut off" Text="I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical `LookAt` view matrix.&#xD;&#xA;&#xD;&#xA;The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:&#xD;&#xA;&#xD;&#xA;$$\small\begin{align}&#xD;&#xA;(\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &amp;= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\&#xD;&#xA;&amp;= \begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; \sin{y} &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;-\sin{y} &amp; 0 &amp; \cos{y} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos{p} &amp; -\sin{p} &amp; 0 \\&#xD;&#xA;0 &amp; \sin{p} &amp; \cos{p} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; -\sin{y} &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;\sin{y} &amp; 0 &amp; \cos{y} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; 0\\&#xD;&#xA;0 &amp; -\sin{p} &amp; \cos{p} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -e_0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; -e_1\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -e_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; \sin{p}\sin{y} &amp; -\cos{p}\sin{y} &amp; -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\&#xD;&#xA;\sin{y} &amp; -\cos{y}\sin{p} &amp; \cos{p}\cos{y} &amp; -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Every step is double checked using WolframAlpha.&#xD;&#xA;&#xD;&#xA;The implementation:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    inline Matrix4&#xD;&#xA;    FPSViewRH(const Vector3&amp; eyePosition, float yaw, float pitch) noexcept&#xD;&#xA;    {&#xD;&#xA;      yaw = Utils::Radians(yaw);&#xD;&#xA;      pitch = Utils::Radians(pitch);&#xD;&#xA;&#xD;&#xA;      const auto sinYaw = std::sin(yaw);&#xD;&#xA;      const auto cosYaw = std::cos(yaw);&#xD;&#xA;&#xD;&#xA;      const auto sinPitch = std::sin(pitch);&#xD;&#xA;      const auto cosPitch = std::cos(pitch);&#xD;&#xA;&#xD;&#xA;      const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};&#xD;&#xA;      const Vector3 j{0, cosPitch, sinPitch};&#xD;&#xA;      const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};&#xD;&#xA;&#xD;&#xA;      return {&#xD;&#xA;        {i[0], i[1], i[2], -i.Dot(eyePosition)},&#xD;&#xA;        {j[0], j[1], j[2], -j.Dot(eyePosition)},&#xD;&#xA;        {k[0], k[1], k[2], -k.Dot(eyePosition)},&#xD;&#xA;        {0,    0,    0,    1},&#xD;&#xA;      };&#xD;&#xA;    }&#xD;&#xA;   &#xD;&#xA;   It works fine except that _the yaw is inverted_, i.e. increasing the angle causes the object to go right while it should go left.&#xD;&#xA;&#xD;&#xA;I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand _why this is happening_? or if there is an interpretation for this phenomena?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9545" PostHistoryTypeId="5" PostId="4279" RevisionGUID="52570d41-c6be-4837-9570-49ccf0a07fe5" CreationDate="2016-11-17T21:17:42.587" UserId="5491" Comment="added 11 characters in body" Text="I have written a standalone java program (ObjectVolume) which reads an object file (.obj) and calculates the surface area, centroid and volume of any closed triangular mesh. The program also displays the file name, number of faces, the number of 3D coordinates and program run times. The program is in the public domain and is located at:&#xD;&#xA;&#xD;&#xA;https://sourceforge.net/projects/objectvolume/?source=navbar&#xD;&#xA;&#xD;&#xA;Included is a detail description of the process and the code.  The source code is included so you can add whatever you like.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9546" PostHistoryTypeId="2" PostId="4284" RevisionGUID="17d2cf75-b881-4f02-8b53-b0adf0d7797e" CreationDate="2016-11-18T03:29:04.560" UserId="1952" Text="I think the mention of &quot;global coordinates&quot; is a lead to the next lecture of learning different coordinate systems (object, camera, etc.), so you are kind of jumping a head I suppose (:&#xD;&#xA;&#xD;&#xA;The points could indeed be given in local coordinates, which would then require definition of transformation from local to global coordinate system, and understanding how this transformation is performed. This transformation is usually defined as a 4x4 matrix, and the 3D points are defined as homogeneous coordinates [x, y, z, 1], which are multiplied with the matrix to bring them into global coordinate system.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9547" PostHistoryTypeId="2" PostId="4285" RevisionGUID="5a9728c2-0083-44ae-bd0d-ea5a2f865392" CreationDate="2016-11-18T05:43:25.880" UserId="5495" Text="In my last Graphic mid-term, the exam contained a Transformation Matrices problem, its statement was:&#xD;&#xA;&#xD;&#xA;**Question**: Rotate the following ladder to form a DNA-shaped ladder using  a transformation matrix.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Notes**:&#xD;&#xA;&#xD;&#xA;* The ladder base must be kept as it's without any rotating.&#xD;&#xA;* The ladder lies in the  x-y plane&#xD;&#xA;* The total rotating angle should equal 540 degrees&#xD;&#xA;* The ladder step width = 2 * ladder step height (This image isn't drawn to scale)&#xD;&#xA;* Assume that the curves are straight lines&#xD;&#xA;&#xD;&#xA;**First Idea**: When I first read the problem statement, I thought of this basic trivial solution:&#xD;&#xA;&#xD;&#xA;1. Translate the ladder such that the ladder's base is on the origin and the y-axis halves the ladder.&#xD;&#xA;2. Rotate all points by the required angle which depends on the current point y value&#xD;&#xA;3. Translate the ladder back to it rotation&#xD;&#xA;&#xD;&#xA;So, in order to write this transformation matrix (assuming that **T(x,y)** is the transformation matrix that will take care of translation to the origin and its inverse will return the ladder back to its original location). And **Ry(theta)** is the rotation matrix around y-axis to perform the rotation to achieve the DNA-shaped ladder.&#xD;&#xA;&#xD;&#xA;If we calculate theta = 540/12 = 45 degrees, then we need to rotate as following:&#xD;&#xA;&#xD;&#xA;* 1st step by 0 degrees (to maintain the fixed-base condition).&#xD;&#xA;* 2nd step by 45 degrees&#xD;&#xA;* 3rd step by 90 == (2*45) degrees &#xD;&#xA;&#xD;&#xA;**The problem**: I couldn't apply this solution and put it into valid transformation matrix because referring to my previous knowledge (and the logic behind transformation matrix too), I recalled that we cannot put variables inside the cos, sin functions inside the rotation matrix (e.g. y). Then I thought of another solution if I used power to the rotation matrix by the value of y this will give me the same effect but I also couldn't put this idea into a transformation matrix.&#xD;&#xA;&#xD;&#xA;So, to conclude the problem we have 2 ways for achieving this (which I think aren't valid):&#xD;&#xA;&#xD;&#xA;1. \begin{bmatrix}cos(yӨ)&amp;0&amp;sin(yӨ)&amp;0\\0&amp;1&amp;0&amp;0\\-sin(yӨ)&amp;0&amp;cos(yӨ)&amp;0\\0&amp;0&amp;0&amp;1\end{bmatrix}&#xD;&#xA;&#xD;&#xA;And the final answer would be: P' =  $(T(x,y))^{-1}$ R(45) T(x,y) P&#xD;&#xA;&#xD;&#xA;2.  \begin{bmatrix}cos(Ө)&amp;0&amp;sin(Ө)&amp;0\\0&amp;1&amp;0&amp;0\\-sin(Ө)&amp;0&amp;cos(Ө)&amp;0\\0&amp;0&amp;0&amp;1\end{bmatrix}&#xD;&#xA;&#xD;&#xA;And the final answer would be: P' =  $(T(x,y))^{-1}$ $(T(x,y))^{y}$ T(x,y) P&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Doctor's solution**:&#xD;&#xA;My doctor was a big supporter of the first solution and he said this is the correct transformation matrix to solve such problems.&#xD;&#xA;&#xD;&#xA;**The real question**: &#xD;&#xA;&#xD;&#xA;* Do any of these solutions achieve the required result while maintaining the transformation matrix concepts (i.e. avoid equations and direct substitutions and instead use matrices operations)&#xD;&#xA;&#xD;&#xA;* If both solutions are wrong, can you kindly guide me to the valid solution :D  &#xD;&#xA;&#xD;&#xA;* If one of the solutions above is correct, can you please explain why?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;  [1]: https://i.stack.imgur.com/U2aS1.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9548" PostHistoryTypeId="1" PostId="4285" RevisionGUID="5a9728c2-0083-44ae-bd0d-ea5a2f865392" CreationDate="2016-11-18T05:43:25.880" UserId="5495" Text="Ladder to DNA using Transformation Matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="9549" PostHistoryTypeId="3" PostId="4285" RevisionGUID="5a9728c2-0083-44ae-bd0d-ea5a2f865392" CreationDate="2016-11-18T05:43:25.880" UserId="5495" Text="|transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9550" PostHistoryTypeId="5" PostId="4285" RevisionGUID="50c24eb4-50fd-42b2-a3ee-29301fac3260" CreationDate="2016-11-18T09:47:17.560" UserId="231" Comment="Tidying up formating. Please revert anything which changes your intention." Text="In my last Graphic mid-term, the exam contained a Transformation Matrices problem, its statement was:&#xD;&#xA;&#xD;&#xA;# Question &#xD;&#xA;&#xD;&#xA;&gt; Rotate the following ladder to form a DNA-shaped ladder using a transformation matrix.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][2]&#xD;&#xA;&#xD;&#xA;# Notes&#xD;&#xA;&#xD;&#xA;* The ladder base must be kept as it is without any rotating.&#xD;&#xA;* The ladder lies in the  x-y plane.&#xD;&#xA;* The total rotating angle should equal 540 degrees.&#xD;&#xA;* The ladder step width = 2 * ladder step height (This image isn't drawn to scale).&#xD;&#xA;* Assume that the curves are straight lines.&#xD;&#xA;&#xD;&#xA;# First Idea&#xD;&#xA;&#xD;&#xA;When I first read the problem statement, I thought of this basic trivial solution:&#xD;&#xA;&#xD;&#xA;1. Translate the ladder such that the ladder's base is on the origin and the y-axis halves the ladder.&#xD;&#xA;2. Rotate all points by the required angle which depends on the current point y value.&#xD;&#xA;3. Translate the ladder back to it rotation.&#xD;&#xA;&#xD;&#xA;Assume that $T(x,y)$ is the transformation matrix that will take care of translation to the origin and its inverse will return the ladder back to its original location, and $R_y(\theta)$ is the rotation matrix around y-axis to perform the rotation to achieve the DNA-shaped ladder.&#xD;&#xA;&#xD;&#xA;If we calculate $\theta = 540/12 = 45$ degrees, then we need to rotate as following:&#xD;&#xA;&#xD;&#xA;* 1st step by $0$ degrees (to maintain the fixed-base condition).&#xD;&#xA;* 2nd step by $45$ degrees.&#xD;&#xA;* 3rd step by $90 = (2*45)$ degrees.&#xD;&#xA;&#xD;&#xA;# The problem&#xD;&#xA;&#xD;&#xA;I couldn't apply this solution and put it into valid transformation matrix because referring to my previous knowledge (and the logic behind transformation matrices too), I recalled that we cannot put variables (e.g. y) inside the cos, sin functions inside the rotation matrix. Then I thought of another solution if I used power to the rotation matrix by the value of y this will give me the same effect but I also couldn't put this idea into a transformation matrix.&#xD;&#xA;&#xD;&#xA;So, to conclude the problem we have 2 ways for achieving this (which I think aren't valid):&#xD;&#xA;&#xD;&#xA;1. $\begin{bmatrix}\cos(y\theta)&amp;0&amp;\sin(y\theta)&amp;0\\0&amp;1&amp;0&amp;0\\-\sin(y\theta)&amp;0&amp;\cos(y\theta)&amp;0\\0&amp;0&amp;0&amp;1\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;And the final answer would be: $P' =  (T(x,y))^{-1} R(45) T(x,y) P$&#xD;&#xA;&#xD;&#xA;2. $\begin{bmatrix}\cos(\theta)&amp;0&amp;\sin(\theta)&amp;0\\0&amp;1&amp;0&amp;0\\-\sin(\theta)&amp;0&amp;\cos(\theta)&amp;0\\0&amp;0&amp;0&amp;1\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;And the final answer would be: $P' =  (T(x,y))^{-1} (T(x,y))^{y} T(x,y) P$&#xD;&#xA;&#xD;&#xA;# Doctor's solution&#xD;&#xA;&#xD;&#xA;My doctor was a big supporter of the first solution and he said this is the correct transformation matrix to solve such problems.&#xD;&#xA;&#xD;&#xA;# The real question&#xD;&#xA;&#xD;&#xA;* Do any of these solutions achieve the required result while maintaining the transformation matrix concepts (i.e. avoid equations and direct substitutions and instead use matrices operations)?&#xD;&#xA;&#xD;&#xA;* If both solutions are wrong, can you kindly guide me to the valid solution? &#xD;&#xA;&#xD;&#xA;* If one of the solutions above is correct, can you please explain why?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U2aS1l.jpg &quot;click for full sized image&quot;&#xD;&#xA;  [2]: https://i.stack.imgur.com/U2aS1.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9551" PostHistoryTypeId="2" PostId="4286" RevisionGUID="b898cb46-7197-4488-ab39-b85e2c152b52" CreationDate="2016-11-18T13:56:53.940" UserId="5506" Text="I want to experiment some new stuff about modern rendering techniques and in that way I'm trying to implement a custom GI (somewhere between pathtracing and instant radiosity).&#xD;&#xA;My scene is a bit less than 1 000 000 tris and my algorithm require to render the same scene _a lot_ of times into different tiny textures (let's call them &quot;bounces&quot;).&#xD;&#xA;&#xD;&#xA;I've began my implementation in a naive way so I rapidly ran into some performance problem:&#xD;&#xA;with my 1TFlops laptop GPU I can render my 1M poly scene I can have 35 &quot;bounces&quot; before dropping bellow 30FPS which is far from enough.&#xD;&#xA;&#xD;&#xA;My &quot;naive&quot; algorythm look like this in pseudo code:&#xD;&#xA;&#xD;&#xA;    for (unsigned int i = 0; i &lt; res ; ++i) {&#xD;&#xA;      UpdateCameraUniform(i);&#xD;&#xA;      glBindFramebuffer(GL_FRAMEBUFFER, BounceFbo[i]);&#xD;&#xA;      glDrawBuffers(1, renderBuffer[i]);&#xD;&#xA;      for (Mesh&amp; m : Scene) {&#xD;&#xA;        m.render();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    Mesh::render() {&#xD;&#xA;    UpdateTransformUniform();&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, _vbo);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);&#xD;&#xA;    glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;the full code is here: https://github.com/newincpp/GLnewin/tree/master/GLnewin (the depot is really messy for now...)&#xD;&#xA;&#xD;&#xA;I need to find a new strategy to render my scene so I searched what I could do.&#xD;&#xA;I think I have 2 strategies:&#xD;&#xA;&#xD;&#xA;1) trying to reduce the number (or the performance) of my drawcalls. It seems that there is some magic function like glMultiDraw* (I've found it here: in the post on &quot;OpenGL superbible&quot; called &quot;the-road-to-one-million-draws&quot;). But I don't really understand what is does:&#xD;&#xA;Does this render a multiple time the same mesh ? different mesh but with one shader ? different mesh with different shader but just with low CPU overhead ?)&#xD;&#xA;&#xD;&#xA;2) trying to reduce the render time while rendering multiple time the same mesh in &quot;Bounces&quot; using the same technique than this: https://www.youtube.com/watch?v=nmajnglJeyE but I have absolutely no idea how it work and even if it can apply to me...&#xD;&#xA;&#xD;&#xA;Obviously I am open to any other suggestion&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9552" PostHistoryTypeId="1" PostId="4286" RevisionGUID="b898cb46-7197-4488-ab39-b85e2c152b52" CreationDate="2016-11-18T13:56:53.940" UserId="5506" Text="Seeking for advises about performance" ContentLicense="CC BY-SA 3.0" />
  <row Id="9553" PostHistoryTypeId="3" PostId="4286" RevisionGUID="b898cb46-7197-4488-ab39-b85e2c152b52" CreationDate="2016-11-18T13:56:53.940" UserId="5506" Text="|opengl|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9554" PostHistoryTypeId="5" PostId="4274" RevisionGUID="0e9a190e-dd21-4ba8-af5c-4cb565201b6b" CreationDate="2016-11-18T15:59:39.800" UserId="5488" Comment="added 174 characters in body" Text="I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical `LookAt` view matrix.&#xD;&#xA;&#xD;&#xA;The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:&#xD;&#xA;&#xD;&#xA;$$\small\begin{align}&#xD;&#xA;(\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &amp;= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\&#xD;&#xA;&amp;= \begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; \sin{y} &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;-\sin{y} &amp; 0 &amp; \cos{y} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos{p} &amp; -\sin{p} &amp; 0 \\&#xD;&#xA;0 &amp; \sin{p} &amp; \cos{p} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; -\sin{y} &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;\sin{y} &amp; 0 &amp; \cos{y} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; 0\\&#xD;&#xA;0 &amp; -\sin{p} &amp; \cos{p} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -e_0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; -e_1\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -e_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; \sin{p}\sin{y} &amp; -\cos{p}\sin{y} &amp; -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\&#xD;&#xA;\sin{y} &amp; -\cos{y}\sin{p} &amp; \cos{p}\cos{y} &amp; -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Every step is double checked using WolframAlpha.&#xD;&#xA;&#xD;&#xA;The implementation:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    inline Matrix4&#xD;&#xA;    FPSViewRH(const Vector3&amp; eyePosition, float yaw, float pitch) noexcept&#xD;&#xA;    {&#xD;&#xA;      yaw = Utils::Radians(yaw);&#xD;&#xA;      pitch = Utils::Radians(pitch);&#xD;&#xA;&#xD;&#xA;      const auto sinYaw = std::sin(yaw);&#xD;&#xA;      const auto cosYaw = std::cos(yaw);&#xD;&#xA;&#xD;&#xA;      const auto sinPitch = std::sin(pitch);&#xD;&#xA;      const auto cosPitch = std::cos(pitch);&#xD;&#xA;&#xD;&#xA;      const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};&#xD;&#xA;      const Vector3 j{0, cosPitch, sinPitch};&#xD;&#xA;      const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};&#xD;&#xA;&#xD;&#xA;      return {&#xD;&#xA;        {i[0], i[1], i[2], -i.Dot(eyePosition)},&#xD;&#xA;        {j[0], j[1], j[2], -j.Dot(eyePosition)},&#xD;&#xA;        {k[0], k[1], k[2], -k.Dot(eyePosition)},&#xD;&#xA;        {0,    0,    0,    1},&#xD;&#xA;      };&#xD;&#xA;    }&#xD;&#xA;   &#xD;&#xA;   It works fine except that _the yaw is inverted_, i.e. increasing the angle causes the object to go right while it should go left.&#xD;&#xA;&#xD;&#xA;I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand _why this is happening_? This would contradict with the definition of the view matrix as the transformation would be come $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} \overset{?}{=} \mathbf{R}_y\mathbf{R}_p^{T}\mathbf{T}^{-1}$" ContentLicense="CC BY-SA 3.0" />
  <row Id="9555" PostHistoryTypeId="5" PostId="4274" RevisionGUID="5ee01f7e-d109-45da-a083-73ee061c8dc8" CreationDate="2016-11-18T16:31:57.767" UserId="5488" Comment="deleted 55 characters in body" Text="I'm trying to construct a FPS view matrix for my OpenGL renderer using yaw and pitch angles instead of the typical `LookAt` view matrix.&#xD;&#xA;&#xD;&#xA;The view matrix is the inverse of the camera world transform $\mathbf{M}_{\textrm{view}} = (\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1}$, hence:&#xD;&#xA;&#xD;&#xA;$$\small\begin{align}&#xD;&#xA;(\mathbf{T}\mathbf{R}_p\mathbf{R}_y)^{-1} &amp;= \mathbf{R}_y^{T}\mathbf{R}_p^{T}\mathbf{T}^{-1} \\&#xD;&#xA;&amp;= \begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; \sin{y} &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;-\sin{y} &amp; 0 &amp; \cos{y} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos{p} &amp; -\sin{p} &amp; 0 \\&#xD;&#xA;0 &amp; \sin{p} &amp; \cos{p} &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^T&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; e_0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; e_1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; e_2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}^{-1} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; 0 &amp; -\sin{y} &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;\sin{y} &amp; 0 &amp; \cos{y} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; 0\\&#xD;&#xA;0 &amp; -\sin{p} &amp; \cos{p} &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -e_0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; -e_1\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -e_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix} \\&#xD;&#xA;&amp;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos{y} &amp; \sin{p}\sin{y} &amp; -\cos{p}\sin{y} &amp; -e_0\cos{y} - e_1\sin{p}\sin{y} + e_2\cos{p}\sin{y}\\&#xD;&#xA;0 &amp; \cos{p} &amp; \sin{p} &amp; -e_0 \cdot 0 - e_1 \cos{p} - e_2 \sin{p}\\&#xD;&#xA;\sin{y} &amp; -\cos{y}\sin{p} &amp; \cos{p}\cos{y} &amp; -e_0\sin{y} + e_1\cos{y}\sin{p} - e_2\cos{p}\cos{y}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Every step is double checked using WolframAlpha.&#xD;&#xA;&#xD;&#xA;The implementation:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    inline Matrix4&#xD;&#xA;    FPSViewRH(const Vector3&amp; eyePosition, float yaw, float pitch) noexcept&#xD;&#xA;    {&#xD;&#xA;      yaw = Utils::Radians(yaw);&#xD;&#xA;      pitch = Utils::Radians(pitch);&#xD;&#xA;&#xD;&#xA;      const auto sinYaw = std::sin(yaw);&#xD;&#xA;      const auto cosYaw = std::cos(yaw);&#xD;&#xA;&#xD;&#xA;      const auto sinPitch = std::sin(pitch);&#xD;&#xA;      const auto cosPitch = std::cos(pitch);&#xD;&#xA;&#xD;&#xA;      const Vector3 i{cosYaw, sinPitch * sinYaw, -cosPitch * sinYaw};&#xD;&#xA;      const Vector3 j{0, cosPitch, sinPitch};&#xD;&#xA;      const Vector3 k{sinYaw, -cosYaw * sinPitch, cosPitch * cosYaw};&#xD;&#xA;&#xD;&#xA;      return {&#xD;&#xA;        {i[0], i[1], i[2], -i.Dot(eyePosition)},&#xD;&#xA;        {j[0], j[1], j[2], -j.Dot(eyePosition)},&#xD;&#xA;        {k[0], k[1], k[2], -k.Dot(eyePosition)},&#xD;&#xA;        {0,    0,    0,    1},&#xD;&#xA;      };&#xD;&#xA;    }&#xD;&#xA;   &#xD;&#xA;   It works fine except that _the yaw is inverted_, i.e. increasing the angle causes the object to go right while it should go left.&#xD;&#xA;&#xD;&#xA;I can negate the yaw angle or change every $\sin{y}$ to $-\sin{y}$, but I don't really understand _why this is happening_?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9556" PostHistoryTypeId="2" PostId="4287" RevisionGUID="3b0cb839-ffc1-419c-add9-1379fae28dfb" CreationDate="2016-11-18T16:52:42.817" UserId="1952" Text="You can't perform this transformation by applying constant transformation matrix to the ladder model since it's not linear transformation like joojaa said in the comments. What you would have to do instead is to define the transformation as a function of height as you have done in both of your proposals.&#xD;&#xA;&#xD;&#xA;So both of your proposals are kind of correct, except for the typo in second one where you should use $R$ instead of $T$ that you raise to power of y. However, you might have difficulties raising a matrix to non-integer power (requires expansion of Taylor series, AFAIK), so your first proposal is much more practical." ContentLicense="CC BY-SA 3.0" />
  <row Id="9557" PostHistoryTypeId="5" PostId="4285" RevisionGUID="81739e68-8382-4362-a142-a7a36288c616" CreationDate="2016-11-18T17:40:16.753" UserId="5495" Comment="deleted 1 character in body" Text="In my last Graphic mid-term, the exam contained a Transformation Matrices problem, its statement was:&#xD;&#xA;&#xD;&#xA;# Question &#xD;&#xA;&#xD;&#xA;&gt; Rotate the following ladder to form a DNA-shaped ladder using a transformation matrix.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][2]&#xD;&#xA;&#xD;&#xA;# Notes&#xD;&#xA;&#xD;&#xA;* The ladder base must be kept as it is without any rotating.&#xD;&#xA;* The ladder lies in the  x-y plane.&#xD;&#xA;* The total rotating angle should equal 540 degrees.&#xD;&#xA;* The ladder step width = 2 * ladder step height (This image isn't drawn to scale).&#xD;&#xA;* Assume that the curves are straight lines.&#xD;&#xA;&#xD;&#xA;# First Idea&#xD;&#xA;&#xD;&#xA;When I first read the problem statement, I thought of this basic trivial solution:&#xD;&#xA;&#xD;&#xA;1. Translate the ladder such that the ladder's base is on the origin and the y-axis halves the ladder.&#xD;&#xA;2. Rotate all points by the required angle which depends on the current point y value.&#xD;&#xA;3. Translate the ladder back to it rotation.&#xD;&#xA;&#xD;&#xA;Assume that $T(x,y)$ is the transformation matrix that will take care of translation to the origin and its inverse will return the ladder back to its original location, and $R_y(\theta)$ is the rotation matrix around y-axis to perform the rotation to achieve the DNA-shaped ladder.&#xD;&#xA;&#xD;&#xA;If we calculate $\theta = 540/12 = 45$ degrees, then we need to rotate as following:&#xD;&#xA;&#xD;&#xA;* 1st step by $0$ degrees (to maintain the fixed-base condition).&#xD;&#xA;* 2nd step by $45$ degrees.&#xD;&#xA;* 3rd step by $90 = (2*45)$ degrees.&#xD;&#xA;&#xD;&#xA;# The problem&#xD;&#xA;&#xD;&#xA;I couldn't apply this solution and put it into valid transformation matrix because referring to my previous knowledge (and the logic behind transformation matrices too), I recalled that we cannot put variables (e.g. y) inside the cos, sin functions inside the rotation matrix. Then I thought of another solution if I used power to the rotation matrix by the value of y this will give me the same effect but I also couldn't put this idea into a transformation matrix.&#xD;&#xA;&#xD;&#xA;So, to conclude the problem we have 2 ways for achieving this (which I think aren't valid):&#xD;&#xA;&#xD;&#xA;1. $\begin{bmatrix}\cos(y\theta)&amp;0&amp;\sin(y\theta)&amp;0\\0&amp;1&amp;0&amp;0\\-\sin(y\theta)&amp;0&amp;\cos(y\theta)&amp;0\\0&amp;0&amp;0&amp;1\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;And the final answer would be: $P' =  (T(x,y))^{-1} R(45) T(x,y) P$&#xD;&#xA;&#xD;&#xA;2. $\begin{bmatrix}\cos(\theta)&amp;0&amp;\sin(\theta)&amp;0\\0&amp;1&amp;0&amp;0\\-\sin(\theta)&amp;0&amp;\cos(\theta)&amp;0\\0&amp;0&amp;0&amp;1\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;And the final answer would be: $P' =  (T(x,y))^{-1} (R(45))^{y} T(x,y) P$&#xD;&#xA;&#xD;&#xA;# Doctor's solution&#xD;&#xA;&#xD;&#xA;My doctor was a big supporter of the first solution and he said this is the correct transformation matrix to solve such problems.&#xD;&#xA;&#xD;&#xA;# The real question&#xD;&#xA;&#xD;&#xA;* Do any of these solutions achieve the required result while maintaining the transformation matrix concepts (i.e. avoid equations and direct substitutions and instead use matrices operations)?&#xD;&#xA;&#xD;&#xA;* If both solutions are wrong, can you kindly guide me to the valid solution? &#xD;&#xA;&#xD;&#xA;* If one of the solutions above is correct, can you please explain why?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U2aS1l.jpg &quot;click for full sized image&quot;&#xD;&#xA;  [2]: https://i.stack.imgur.com/U2aS1.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9559" PostHistoryTypeId="2" PostId="4288" RevisionGUID="b80e1cbe-5270-4d97-a9fc-c33ec866a55c" CreationDate="2016-11-19T07:05:58.323" UserId="5510" Text="I originally wrote a pathtracer that just bounces by the BRDF and each sample is added to a buffer that divides by the current number of frames.&#xD;&#xA;&#xD;&#xA;Now I'd like to do next event estimation at each bounce, directly sampling the light along the path. How do I &quot;weight&quot; the samples taken with regular pathtracing along with the direct light samples? Even if I weight the direct light by the solid angle of the light, if I have more than 1 sample taken I can no longer just divide by the frame count right?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9560" PostHistoryTypeId="1" PostId="4288" RevisionGUID="b80e1cbe-5270-4d97-a9fc-c33ec866a55c" CreationDate="2016-11-19T07:05:58.323" UserId="5510" Text="Path weight for direct light sampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="9561" PostHistoryTypeId="3" PostId="4288" RevisionGUID="b80e1cbe-5270-4d97-a9fc-c33ec866a55c" CreationDate="2016-11-19T07:05:58.323" UserId="5510" Text="|raytracing|pathtracing|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9562" PostHistoryTypeId="2" PostId="4289" RevisionGUID="3cc2825f-9fae-43d9-a10a-3a9548c97c18" CreationDate="2016-11-19T07:06:00.010" UserId="2707" Text="You should always profile to determine where your slowdown occurs. From your question, it's unclear whether your work is CPU bound or GPU bound.&#xD;&#xA;&#xD;&#xA;&gt; But I don't really understand what is does: Does this render a multiple time the same mesh ? different mesh but with one shader ? different mesh with different shader but just with low CPU overhead ?&#xD;&#xA;&#xD;&#xA;The `glMultiDraw*` draw commands are for allowing you to render multiple objects in one draw call. In terms of OpenGL 3.0 and later, this means that you could specify a VBO holding a bunch of objects and use `glMultiDraw*` to render them. You would use this with the same shader. If you want to render the same object multiple times, then using something such as [instancing][1] would be a good solution.&#xD;&#xA;&#xD;&#xA;This all concerns draw calls though. If you have one million triangles for only a few meshes, you won't see a massive speedup with rendering. You didn't specify your framebuffer size, but if it's small enough, you can cause severe overdraw from many small triangles. If the images are really that small, maybe you should think about adding an LOD system or use lower polygon meshes and tessellate.&#xD;&#xA;&#xD;&#xA;&gt; trying to reduce the render time while rendering multiple time the same mesh in &quot;Bounces&quot; using the same technique than this&#xD;&#xA;&#xD;&#xA;[Stereo instanced rendering][2] is specifically a technique for VR. It relies on the assumption that the scene is pretty much identical in each eye, and so it uses instancing to render to two sides of the screen at once. However, if your bounces render similar geometry, then you may be able to render multiple bounces onto a larger framebuffer provided that the bounces are independent. There is potential for speedup from avoiding framebuffer switching (which is a rather expensive process).&#xD;&#xA;&#xD;&#xA;In newer OpenGL versions (4.0 and above), there is added support for [indirect rendering][3], which allows you to determine parameters through GPU computing, but it's unclear if that will help you in this case.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/Vertex_Rendering#Instancing&#xD;&#xA;  [2]: https://docs.google.com/presentation/d/19x9XDjUvkW_9gsfsMQzt3hZbRNziVsoCEHOn4AercAc/edit#slide=id.p&#xD;&#xA;  [3]: https://www.opengl.org/wiki/Vertex_Rendering#Indirect_rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="9563" PostHistoryTypeId="2" PostId="4290" RevisionGUID="337428d3-97c4-4795-a0bb-61f3f93a9066" CreationDate="2016-11-19T10:59:49.137" UserId="5513" Text="This is what my lecturer told me in the coursework:&#xD;&#xA;&#xD;&#xA;We only consider 4*4 matrices. These are used to rotate, scale or translate objects (or any combination of these operations). Matrices are also used later in the implementation of the virtual camera model. If you do not know the difference between a vector transformation and point transformation, look it up. &#xD;&#xA;&#xD;&#xA;I can't seem to find an answer and made an account for this website just for this question." ContentLicense="CC BY-SA 3.0" />
  <row Id="9564" PostHistoryTypeId="1" PostId="4290" RevisionGUID="337428d3-97c4-4795-a0bb-61f3f93a9066" CreationDate="2016-11-19T10:59:49.137" UserId="5513" Text="What is the difference between a point transformation and a vector transformation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9565" PostHistoryTypeId="3" PostId="4290" RevisionGUID="337428d3-97c4-4795-a0bb-61f3f93a9066" CreationDate="2016-11-19T10:59:49.137" UserId="5513" Text="|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9566" PostHistoryTypeId="2" PostId="4291" RevisionGUID="0e1dc759-66c7-43c3-833d-db7b7b2db92f" CreationDate="2016-11-19T12:22:50.717" UserId="4908" Text="If you would look up the definition of a vector and a point, then a vector is:&#xD;&#xA;&#xD;&#xA;&gt; A quantity, such as velocity, completely specified by a magnitude and a direction.&#xD;&#xA;[http://www.thefreedictionary.com/vector][1]&#xD;&#xA;&#xD;&#xA;And a point is:&#xD;&#xA;&#xD;&#xA;&gt; A dimensionless geometric object having no properties except location.&#xD;&#xA;[http://www.thefreedictionary.com/point][2]&#xD;&#xA;&#xD;&#xA;So you could say that a vector is a direction with scale, and a point is a location.&#xD;&#xA;&#xD;&#xA;So, if you transform a vector you just rotate and scale it. With a point you also translate it (the rotation and scaling of a point is around the origin, since it iss just a location the point itself cannot be rotated).&#xD;&#xA;&#xD;&#xA;Most of the times a vector and a point are put into the same container, a vector with 4 components. The only difference is the w component. If the w component is 0, then it is a direction. If it is 1 then the vector is a point.&#xD;&#xA;&#xD;&#xA;The reason for this can be found in the matrix itself.&#xD;&#xA;It makes use of the way you multiply a vector with 4 components with a 4x4 matrix. If you do not know how that works, I would suggest a quick google.&#xD;&#xA;&#xD;&#xA;Most of the times you use a 4x4 matrix. A normal transformation matrix could look like this:&#xD;&#xA;\begin{bmatrix}rot+scale&amp;rot+scale&amp;rot+scale&amp;translation\\rot+scale&amp;rot+scale&amp;rot+scale&amp;translation\\rot+scale&amp;rot+scale&amp;rot+scale&amp;translation\\0&amp;0&amp;0&amp;1\end{bmatrix}&#xD;&#xA;(The rotation and scale are put in the 3x3 area you could say, so for just rotation and scale a 3x3 matrix could also be used, but when translation comes in, we need that 4th column.)&#xD;&#xA;&#xD;&#xA;As you can see, if the last component is 0, then you have a multiplication with 0 and therefore the result is 0 and there is no translation.&#xD;&#xA;&#xD;&#xA;This makes it easy in computer graphics with polygonal objects. You have the same transformation matrix to transform the positions but also the normals. Because the normals have their w component set to 0 and the positions' w component is 1, the normals are just rotated (and also scaled which can lead to some weird stuff, so most of the times the normal is normalized after) and the positions are translated (and rotated and scaled around the origin).&#xD;&#xA;&#xD;&#xA;Hope I did not make a mistake :P, and this helped you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.thefreedictionary.com/vector&#xD;&#xA;  [2]: http://www.thefreedictionary.com/point" ContentLicense="CC BY-SA 3.0" />
  <row Id="9567" PostHistoryTypeId="2" PostId="4292" RevisionGUID="8fa3e55b-6b03-4c66-afb6-133c8b8f8bdc" CreationDate="2016-11-19T12:26:51.290" UserDisplayName="user4718" Text="From what I've learnt, since I'm also a student, is that you want to work with $4 \times 4$ matrices in order to treat rotations, scaling and translations in the same way, that is, _multiplying by a matrix_ (i.e., a $4 \times 4$ matrix).&#xD;&#xA;&#xD;&#xA;Remember that without these $4 \times 4$ matrices, translations would be represented by summing with a vector, whereas rotations and scaling are represented using multiplications with respectively a vector and a scalar factor.&#xD;&#xA;&#xD;&#xA;Now the question is: _how do we pass from a 3D coordinate systems to a 4D one_? The answer is &quot;**homogenous coordinates**&quot;. &#xD;&#xA;&#xD;&#xA;So, what does it mean? We construct $4 \times 4$ matrices to represent rotations, scaling and translation, so that we only use matrix multiplications to represent transformations (e.g., rotations, scaling, etc). How we construct them individually, it's more specific, but you can have a look it on the web. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At this point, we have $4 \times 4$ matrices and 3D vectors, not useful yet, because you can't multiply $4 \times 4$ matrices and $3D$ vectors, since the dimensions do not match. That's why, when we work with homegeneous coordinates, we also need to convert our given 3D points into corresponding 4D ones. &#xD;&#xA;&#xD;&#xA;How do we do it? We distinguish between _direction_ and _position_ vectors (_what's the difference?_). We transform 3D direction vectors by adding a $0$ as the $4$th coordinate of the corresponding homegeneous vector. We do a similar thing with position vector, but instead of a $0$ we add a $1$.&#xD;&#xA;&#xD;&#xA;For example, if we have a $3D$ direction vector $v = \begin{pmatrix} v_1 \\ v_2 \\ v_3\end{pmatrix}$, we transform it by doing $v' = \begin{pmatrix} v_1 \\ v_2 \\ v_3 \\ 0\end{pmatrix}$. Similarly, if we had a point vector $u = \begin{pmatrix} u_1 \\ u_2 \\ u_3\end{pmatrix}$ we would transform it to $u = \begin{pmatrix} u_1 \\ u_2 \\ u_3 \\ 1\end{pmatrix}$&#xD;&#xA;&#xD;&#xA;Note: to convert from homogeneous coordinates back to corresponding $3D$ ones, you can't simply remove the $4th$ coordinate!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9568" PostHistoryTypeId="5" PostId="4292" RevisionGUID="9debedab-d2ee-4c37-a857-0c4ffe861a76" CreationDate="2016-11-19T12:31:59.850" UserDisplayName="user4718" Comment="added 1 character in body" Text="From what I've learnt, since I'm also a student, is that you want to work with $4 \times 4$ matrices in order to treat rotations, scaling and translations in the same way, that is, _multiplying by a matrix_ (i.e., a $4 \times 4$ matrix).&#xD;&#xA;&#xD;&#xA;Remember that without these $4 \times 4$ matrices, translations would be represented by summing with a vector, whereas rotations and scaling are represented using multiplications with respectively a vector and a scalar factor.&#xD;&#xA;&#xD;&#xA;Now the question is: _how do we pass from a 3D coordinate systems to a 4D one_? The answer is &quot;**homogenous coordinates**&quot;. &#xD;&#xA;&#xD;&#xA;So, what does it mean? We construct $4 \times 4$ matrices to represent rotations, scaling and translation, so that we only use matrix multiplications to represent transformations (e.g., rotations, scaling, etc). How we construct them individually, it's more specific, but you can have a look it on the web. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At this point, we have $4 \times 4$ matrices and 3D vectors, not useful yet, because you can't multiply $4 \times 4$ matrices and $3D$ vectors, since the dimensions do not match. That's why, when we work with homegeneous coordinates, we also need to convert our given 3D points into corresponding 4D ones. &#xD;&#xA;&#xD;&#xA;How do we do it? We distinguish between _direction_ and _position_ vectors (_what's the difference?_). We transform 3D direction vectors by adding a $0$ as the $4$th coordinate of the corresponding homegeneous vector. We do a similar thing with position vector, but instead of a $0$ we add a $1$.&#xD;&#xA;&#xD;&#xA;For example, if we have a $3D$ direction vector $v = \begin{pmatrix} v_1 \\ v_2 \\ v_3\end{pmatrix}$, we transform it by doing $v' = \begin{pmatrix} v_1 \\ v_2 \\ v_3 \\ 0\end{pmatrix}$. Similarly, if we had a point vector $u = \begin{pmatrix} u_1 \\ u_2 \\ u_3\end{pmatrix}$ we would transform it to $u' = \begin{pmatrix} u_1 \\ u_2 \\ u_3 \\ 1\end{pmatrix}$&#xD;&#xA;&#xD;&#xA;Note: to convert from homogeneous coordinates back to corresponding $3D$ ones, you can't simply remove the $4th$ coordinate!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9570" PostHistoryTypeId="2" PostId="4293" RevisionGUID="fea193dd-f551-4bf3-b4b6-7e968bbf4ea4" CreationDate="2016-11-19T13:27:36.380" UserDisplayName="user4718" Text="I'm trying to understand part of the contents of a slide, but I'm not really understanding. So, here's the interested part.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I've a few questions.&#xD;&#xA;&#xD;&#xA;1. Are the projected points $q_1$ and $q_2$ the points with respectively the screen coordinates $(x_1, y_1)$ and $(x_2, y_2)$, i.e., $q_1 = \begin{pmatrix} x_1 \\ y_1\end{pmatrix}$ and $q_2 = \begin{pmatrix} x_2 \\ y_2\end{pmatrix}$?&#xD;&#xA;&#xD;&#xA;2. Regarding how to obtain the projected points. What I understand from the slide is that the projected $3D$ points are obtained by dividing all coordinates of $p_1$ (e.g.) by its $z$ coordinate, i.e., $p_1^z$, so that we obtain $q_1 = \begin{pmatrix} \frac{p_1^x}{p_1^z} \\ \frac{p_1^y}{p_1^z} \\ \frac{p_1^z}{p_1^z}  \end{pmatrix} = \begin{pmatrix} \frac{p_1^x}{p_1^z} \\ \frac{p_1^y}{p_1^z} \\ 1 \end{pmatrix}$. So, I guess, that at this point, we obtain the sccreen coordinates by ignoring the $1$ as the 3rd coordinate. Is that right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4TwPA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9571" PostHistoryTypeId="1" PostId="4293" RevisionGUID="fea193dd-f551-4bf3-b4b6-7e968bbf4ea4" CreationDate="2016-11-19T13:27:36.380" UserDisplayName="user4718" Text="Projected points and screen coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="9572" PostHistoryTypeId="3" PostId="4293" RevisionGUID="fea193dd-f551-4bf3-b4b6-7e968bbf4ea4" CreationDate="2016-11-19T13:27:36.380" UserDisplayName="user4718" Text="|projections|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9573" PostHistoryTypeId="2" PostId="4294" RevisionGUID="b6c4debe-a965-43cb-b471-abba8cc5d06c" CreationDate="2016-11-19T14:04:43.393" UserDisplayName="user4718" Text="To continue with [this](http://computergraphics.stackexchange.com/questions/4293/projected-points-and-screen-coordinates) my other question, here's the problem. So, I've a slide, which I'm trying to understand. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here are my questions.&#xD;&#xA;&#xD;&#xA;1. What are the barycentric coordinates of? From my previous question, $(x_1, y_1)$ and $(x_2, y_2)$ are also screen coordinates. So, we're interpolating between screen coordinates. Why would we do that?&#xD;&#xA;&#xD;&#xA;2. Why is $\lambda = \frac{x - x_1}{x_2 - x_1}$?&#xD;&#xA;&#xD;&#xA;3. Are $p_1$ and $p_2$ points given in global coordinates? That is, are they $3D$ points or screen points? &#xD;&#xA;&#xD;&#xA;4. Why is $\mu$ defined as it is?&#xD;&#xA;&#xD;&#xA;5. Why do we want to know $p^z$? By the way, what is it? A vector, right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UK1Ia.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9574" PostHistoryTypeId="1" PostId="4294" RevisionGUID="b6c4debe-a965-43cb-b471-abba8cc5d06c" CreationDate="2016-11-19T14:04:43.393" UserDisplayName="user4718" Text="Screen coordinates, barycentric coordinates and global coordinateas" ContentLicense="CC BY-SA 3.0" />
  <row Id="9575" PostHistoryTypeId="3" PostId="4294" RevisionGUID="b6c4debe-a965-43cb-b471-abba8cc5d06c" CreationDate="2016-11-19T14:04:43.393" UserDisplayName="user4718" Text="|interpolation|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9576" PostHistoryTypeId="2" PostId="4295" RevisionGUID="dbcb8947-cf55-4889-b759-81c804b8f6a9" CreationDate="2016-11-19T15:58:57.973" UserId="56" Text="Here's the simple answer.&#xA;&#xA;In 4d, to be able to multiply them by a 4x4 matrix, vectors are represented as (x,y,z,0) and points are represented as (x,y,z,1).&#xA;&#xA;Since the 4th row of a 4x4 matrix represents the translation of the matrix, the above representations make it so points are affected by translation, but vectors are not.&#xA;&#xA;Both vectors and points are affected by the rotation, scaling, etc though." ContentLicense="CC BY-SA 3.0" />
  <row Id="9577" PostHistoryTypeId="5" PostId="4286" RevisionGUID="13ce53d7-b581-43f8-aab3-55020f8602dc" CreationDate="2016-11-19T18:32:24.140" UserId="231" Comment="Some tidying - please revert anything that changes your intended meaning." Text="I want to experiment with some new stuff about modern rendering techniques and in that way I'm trying to implement a custom GI (somewhere between pathtracing and instant radiosity).&#xD;&#xA;My scene is a bit less than 1,000,000 tris and my algorithm requires to render the same scene _a lot_ of times into different tiny textures (let's call them &quot;bounces&quot;).&#xD;&#xA;&#xD;&#xA;I've began my implementation in a naive way so I rapidly ran into some performance problems:  &#xD;&#xA;With my 1TFlops laptop GPU I can render my 1M poly scene I can have 35 &quot;bounces&quot; before dropping bellow 30FPS which is far from enough.&#xD;&#xA;&#xD;&#xA;My &quot;naive&quot; algorithm looks like this in pseudo code:&#xD;&#xA;&#xD;&#xA;    for (unsigned int i = 0; i &lt; res ; ++i) {&#xD;&#xA;      UpdateCameraUniform(i);&#xD;&#xA;      glBindFramebuffer(GL_FRAMEBUFFER, BounceFbo[i]);&#xD;&#xA;      glDrawBuffers(1, renderBuffer[i]);&#xD;&#xA;      for (Mesh&amp; m : Scene) {&#xD;&#xA;        m.render();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    Mesh::render() {&#xD;&#xA;    UpdateTransformUniform();&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, _vbo);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);&#xD;&#xA;    glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The full code is [here](https://github.com/newincpp/GLnewin/tree/master/GLnewin) (the depot is really messy for now...).&#xD;&#xA;&#xD;&#xA;I need to find a new strategy to render my scene so I searched what I could do.  &#xD;&#xA;I think I have 2 strategies:&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the number (or the performance) of my drawcalls. It seems that there is some magic function like glMultiDraw* (I've found it here: in the post on &quot;OpenGL superbible&quot; called &quot;the-road-to-one-million-draws&quot;). But I don't really understand what this does:&#xD;&#xA;- Does this render multiple times the same mesh?&#xD;&#xA;- Different mesh but with one shader?&#xD;&#xA;- Different mesh with different shader but just with low CPU overhead?&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the render time while rendering multiple times the same mesh in &quot;Bounces&quot; using the same technique as [this](https://www.youtube.com/watch?v=nmajnglJeyE) but I have absolutely no idea how it works or even if it can apply to me...&#xD;&#xA;&#xD;&#xA;Obviously I am open to any other suggestions.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9578" PostHistoryTypeId="4" PostId="4286" RevisionGUID="13ce53d7-b581-43f8-aab3-55020f8602dc" CreationDate="2016-11-19T18:32:24.140" UserId="231" Comment="Some tidying - please revert anything that changes your intended meaning." Text="How can I improve the performance of my custom Global Illumination approach?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9579" PostHistoryTypeId="5" PostId="4291" RevisionGUID="82ad7184-0999-4ca3-b01c-56661d6d41a5" CreationDate="2016-11-19T21:56:17.950" UserId="4908" Comment="added 139 characters in body" Text="If you would look up the definition of a vector and a point, then a vector is:&#xD;&#xA;&#xD;&#xA;&gt; A quantity, such as velocity, completely specified by a magnitude and a direction.&#xD;&#xA;[http://www.thefreedictionary.com/vector][1]&#xD;&#xA;&#xD;&#xA;And a point is:&#xD;&#xA;&#xD;&#xA;&gt; A dimensionless geometric object having no properties except location.&#xD;&#xA;[http://www.thefreedictionary.com/point][2]&#xD;&#xA;&#xD;&#xA;So you could say that a vector is a direction with scale, and a point is a location.&#xD;&#xA;&#xD;&#xA;So, if you transform a vector you just rotate and scale it. With a point you also translate it (the rotation and scaling of a point is around the origin, since it iss just a location the point itself cannot be rotated).&#xD;&#xA;&#xD;&#xA;Most of the times a vector and a point are put into the same container, a vector with 4 components. The only difference is the w component. If the w component is 0, then it is a direction. If it is 1 then the vector is a point.&#xD;&#xA;&#xD;&#xA;The reason for this can be found in the matrix itself.&#xD;&#xA;It makes use of the way you multiply a vector with 4 components with a 4x4 matrix. If you do not know how that works, I would suggest a quick google.&#xD;&#xA;&#xD;&#xA;Most of the times you use a 4x4 matrix. A normal transformation matrix could look like this:&#xD;&#xA;\begin{bmatrix}rot+scale&amp;rot+scale&amp;rot+scale&amp;translation\\rot+scale&amp;rot+scale&amp;rot+scale&amp;translation\\rot+scale&amp;rot+scale&amp;rot+scale&amp;translation\\0&amp;0&amp;0&amp;1\end{bmatrix}&#xD;&#xA;(The rotation and scale are put in the 3x3 area you could say, so for just rotation and scale a 3x3 matrix could also be used, but when translation comes in, we need that 4th column.)&#xD;&#xA;&#xD;&#xA;As you can see, if the last component is 0, then you have a multiplication with 0 and therefore the result is 0 and there is no translation.&#xD;&#xA;&#xD;&#xA;This makes it easy in computer graphics with polygonal objects. You have the same transformation matrix to transform the positions but also the normals. Because the normals have their w component set to 0 and the positions' w component is 1, the normals are just rotated (and also scaled which can lead to some weird stuff, so most of the times the normal is normalized after. It isn't actually recommended to use the same matrix for positions and rotations because of the weird stuff! Look at @JarkkoL 's comment.) and the positions are translated (and rotated and scaled around the origin).&#xD;&#xA;&#xD;&#xA;Hope I did not make a mistake :P, and this helped you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.thefreedictionary.com/vector&#xD;&#xA;  [2]: http://www.thefreedictionary.com/point" ContentLicense="CC BY-SA 3.0" />
  <row Id="9580" PostHistoryTypeId="2" PostId="4296" RevisionGUID="b26597d4-cad5-420e-b532-4948cb2c09a4" CreationDate="2016-11-20T02:14:01.213" UserId="1952" Text="A common approach for real-time radiosity in games is to assume static geometry, which can be used to pre-calculate visible surfels (position, albedo, normal) for a point in space (light probe). This approach avoids the need for run-time rasterization of the geometry for different viewpoints. The surfels can be then dynamically re-lit in run-time and used to gather illuminance for the probe, which is used to approximate the indirect illumination." ContentLicense="CC BY-SA 3.0" />
  <row Id="9581" PostHistoryTypeId="5" PostId="4296" RevisionGUID="834824dd-ae95-4622-a9eb-5ac6ec4a95b9" CreationDate="2016-11-20T02:19:53.937" UserId="1952" Comment="deleted 2 characters in body" Text="A common approach for real-time radiosity in games is to assume static geometry, which can be used to pre-calculate visible surfels (position, albedo, normal) for a point in space (light probe). This approach avoids the need for run-time rasterization of the geometry for different viewpoints. The surfels can be then dynamically re-lit in run-time and used to gather luminance for the probe, which is used to approximate the indirect illumination." ContentLicense="CC BY-SA 3.0" />
  <row Id="9586" PostHistoryTypeId="2" PostId="4298" RevisionGUID="a67a6c96-78ca-462d-baae-4c5794feb838" CreationDate="2016-11-20T05:45:23.957" UserId="48" Text="It's not 100% clear what the author means here, but I'll choose to interpret &quot;screen coordinates&quot; as &quot;pixel coordinates&quot;. These would be related to the projected points by a 2D coordinate transformation.&#xD;&#xA;&#xD;&#xA;You're correct that projection is done by dividing each component of a point by its $z$ component. (That's not _quite_ true—actually, we usually use homogeneous coordinates, which have four components $xyzw$, and divide by the $w$ component, which has previously been set to eye-space $z$ by the projection matrix. This frees up the $z$ component of the vectors to be used for the z-buffer.) The projected points $q_i$ are then in &quot;normalized device coordinates&quot; or NDC space, which has a range of [−1, 1] on each axis.&#xD;&#xA;&#xD;&#xA;To calculate the resulting pixel coordinates on the screen, we then need to perform a 2D scale-and-translate operation, to map the [−1, 1] range to the desired range of pixels. For example, if we want a 640×480 viewport, we could calculate&#xD;&#xA;$$x_i = 640 \cdot \frac{q^x_i + 1}{2} \\ y_i = 480 \cdot \frac{q^y_i + 1}{2}$$&#xD;&#xA;You might also need to flip the $y$ axis in this transformation, for instance if the NDC space is Y-up but the pixel coordinates are Y-down." ContentLicense="CC BY-SA 3.0" />
  <row Id="9587" PostHistoryTypeId="2" PostId="4299" RevisionGUID="f6787aa7-1e47-4e70-b4a3-6023a848309a" CreationDate="2016-11-20T06:22:37.617" UserId="48" Text="1. It sounds like you're rasterizing a line segment between two endpoints. The points on the line are obtained by linearly interpolating between the endpoints (whether in world space, screen space, or any other coordinate system). The barycentric coordinates identify points on the line segment.&#xD;&#xA;&#xD;&#xA;2. It's defined this way to make range of $\lambda$ be [0, 1]. (When $\lambda = 0$ you obtain $(x_1, y_1)$ and when $\lambda = 1$ you get $(x_2, y_2)$.) This is typical for barycentric coordinates for either lines or for triangles—they always range from 0 to 1, and sum to 1. These coordinates therefore also act as weights for interpolating other quantities, such as color or z-value, across the line or triangle.&#xD;&#xA;&#xD;&#xA;3. Probably the $p_i$ are the original 3D points before projection.&#xD;&#xA;&#xD;&#xA;4. This is about perspective-correct interpolation. It's stating the transformation between $\lambda$ (interpolation in screen space) and $\mu$ (interpolation in world space). The two parameters are not the same, due to perspective foreshortening—in screen space, perspective will compress parts of the line that are farther away from the camera. So, for example, the midpoint of the line in world space ($\mu = \tfrac{1}{2}$) will generally project to some place that is _not_ at the midpoint in screen space ($\lambda \neq \tfrac{1}{2}$). The equation given shows how to convert between $\lambda$ and $\mu$ for a given point on the line. Note that if $p_1^z = p_2^z$, the equation reduces to $\mu = \lambda$, showing that both kinds of interpolation match if and only if the line is parallel to the screen, so the perspective effect is uniform along the whole line.&#xD;&#xA;&#xD;&#xA;5. $p_z$ is going to be the depth of the interpolated point. It's the $z$-component of the vector $p$, so $p_z$ itself is a single value, not a vector. Presumably the reason you want to know this is so you can store it in the z-buffer during rasterization. In other words, while rasterizing a line, you can easily calculate $\lambda$ for each pixel based on how far you are between the endpoints in screen space; then this equation tells you the $z$ for each pixel to put into the z-buffer." ContentLicense="CC BY-SA 3.0" />
  <row Id="9589" PostHistoryTypeId="5" PostId="4286" RevisionGUID="19eedd6f-b58c-46d5-a166-29ea41f7c9f6" CreationDate="2016-11-20T17:51:31.873" UserId="5506" Comment="deleted 8 characters in body" Text="I want to experiment with some new stuff about modern rendering techniques and in that way I'm trying to implement a custom GI (somewhere between pathtracing and instant radiosity).&#xD;&#xA;My scene is a bit less than 1,000,000 tris and my algorithm requires to render the same scene _a lot_ of times into different tiny textures (let's call them &quot;bounces&quot;).&#xD;&#xA;&#xD;&#xA;I've began my implementation in a naive way so I rapidly ran into some performance problems:  &#xD;&#xA;With my 1TFlops laptop GPU I can render my 1M poly scene I can have 35 &quot;bounces&quot; before dropping bellow 30FPS which is far from enough.&#xD;&#xA;&#xD;&#xA;My &quot;naive&quot; algorithm looks like this in pseudo code:&#xD;&#xA;&#xD;&#xA;    for (unsigned int i = 0; i &lt; res ; ++i) {&#xD;&#xA;      UpdateCameraUniform(i);&#xD;&#xA;      glBindFramebuffer(GL_FRAMEBUFFER, BounceFbo[i]);&#xD;&#xA;      glDrawBuffers(1, renderBuffer[i]);&#xD;&#xA;      for (Mesh&amp; m : Scene) {&#xD;&#xA;        m.render();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    Mesh::render() {&#xD;&#xA;    UpdateTransformUniform();&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, _vbo);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);&#xD;&#xA;    glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The full code is [here](https://github.com/newincpp/GLnewin/tree/master/GLnewin) (the depot is really messy for now...).&#xD;&#xA;&#xD;&#xA;I need to find a new strategy to render my scene so I searched what I could do.  &#xD;&#xA;I think I have 2 strategies:&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the number (or the performance) of my drawcalls. It seems that there is some magic function like glMultiDraw* (I've found it in a post on &quot;OpenGL superbible&quot; called &quot;the-road-to-one-million-draws&quot;). But I don't really understand what this does:&#xD;&#xA;- Does this render multiple times the same mesh?&#xD;&#xA;- Different mesh but with one shader?&#xD;&#xA;- Different mesh with different shader but just with low CPU overhead?&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the render time while rendering multiple times the same mesh in &quot;Bounces&quot; using the same technique as [this](https://www.youtube.com/watch?v=nmajnglJeyE) but I have absolutely no idea how it works or even if it can apply to me...&#xD;&#xA;&#xD;&#xA;Obviously I am open to any other suggestions.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9597" PostHistoryTypeId="2" PostId="4302" RevisionGUID="49e5fae0-6a01-46af-b42d-d054bab1d4b6" CreationDate="2016-11-22T07:36:35.707" UserId="48" Text="By &quot;bounces by the BRDF&quot;, I assume you mean picking random directions in the hemisphere and weighting by the BRDF, then averaging over those samples. I guess you're accumulating one sample per frame, so then you divide by the current number of frames.&#xD;&#xA;&#xD;&#xA;To be theoretically &quot;correct&quot;, you should also be weighting those samples by $2\pi$, as that's the solid angle of the hemisphere you're integrating over. That's not too important when you just have a single sampling method, but when you're going to combine multiple ones it's easier to be sure everything's consistent if you have these factors right.&#xD;&#xA;&#xD;&#xA;Then, to incorporate explicit direct light sampling, you have to convert from the light-sampling probability density to the solid angle probability density at the receiver point. If the light samples are uniform over the light source's area, then in place of the simple $2\pi$ weight, you'd use this weight factor instead:&#xD;&#xA;$$\frac{A}{r^2} (N_\text{light} \cdot -L)$$&#xD;&#xA;where $A$ is the area of the light source, $r$ is the distance between the receiver point (current path point) and the chosen light source point, $N_\text{light}$ is the normal of the light point, and $L$ is the unit vector from the path point, toward the light point.&#xD;&#xA;&#xD;&#xA;This factor accounts for how dense the sampled light source points will be in solid angle of the receiver point, varying both with distance and with the angle on the light source's surface (the points will bunch up in areas where the source surface slopes away from the receiver, such as around the edges of a spherical area light).&#xD;&#xA;&#xD;&#xA;After weighting by this factor, the direct light samples are in the same solid angle domain as the BRDF samples, so you can just add them together and divide by the total number of samples—which would now be twice the number of frames, if you're doing one BRDF sample and one light sample per frame.&#xD;&#xA;&#xD;&#xA;Also, an important thing to get right is not double-counting the light's illumination. Since you're explicitly sampling the lights now, you have to make sure _not_ to include the emissive color if you do happen to randomly hit a light while doing the BRDF samples! Otherwise you'd end up with the lights appearing twice as bright as they should.&#xD;&#xA;&#xD;&#xA;A refinement of this is that you may wish to apply explicit light sampling only to the diffuse part of the BRDF, and not the specular part. A narrow specular highlight is better handled through importance-sampling the BRDF instead. This implies that when doing explicit light samples, you would only evaluate the diffuse component of the BRDF, and then if you hit a light source through a specular reflection ray, you _would_ include its emissive color there." ContentLicense="CC BY-SA 3.0" />
  <row Id="9600" PostHistoryTypeId="5" PostId="4286" RevisionGUID="4ffa75d5-c94a-428b-a2dc-95cdd0d8b2d6" CreationDate="2016-11-22T17:46:15.767" UserId="5506" Comment="added 55 characters in body" Text="I want to experiment with some new stuff about modern rendering techniques and in that way I'm trying to implement a custom GI (somewhere between pathtracing and instant radiosity).&#xD;&#xA;My scene is a bit less than 1,000,000 tris and my algorithm requires to render the same scene _a lot_ of times into different tiny textures (let's call them &quot;bounces&quot;).&#xD;&#xA;&#xD;&#xA;I've began my implementation in a naive way so I rapidly ran into some performance problems:  &#xD;&#xA;With my 1TFlops laptop GPU I can render my 1M poly scene I can have 35 &quot;bounces&quot; before dropping bellow 30FPS which is far from enough.&#xD;&#xA;&#xD;&#xA;My &quot;naive&quot; algorithm looks like this in pseudo code:&#xD;&#xA;&#xD;&#xA;    for (unsigned int i = 0; i &lt; res ; ++i) {&#xD;&#xA;      UpdateCameraUniform(i);&#xD;&#xA;      glBindFramebuffer(GL_FRAMEBUFFER, BounceFbo[i]);&#xD;&#xA;      glDrawBuffers(1, renderBuffer[i]);&#xD;&#xA;      for (Mesh&amp; m : Scene) {&#xD;&#xA;        m.render();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    Mesh::render() {&#xD;&#xA;    UpdateTransformUniform();&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, _vbo);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);&#xD;&#xA;    glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The full code is [here](https://github.com/newincpp/GLnewin/tree/master/GLnewin) (the depot is really messy for now...).&#xD;&#xA;&#xD;&#xA;I need to find a new strategy to render my scene so I searched what I could do.  &#xD;&#xA;I think I have 2 strategies:&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the number (or the performance) of my drawcalls. It seems that there is some magic function like glMultiDraw* (I've found it in a post on &quot;OpenGL superbible&quot; [here][1]). But I don't really understand what this does:&#xD;&#xA;- Does this render multiple times the same mesh?&#xD;&#xA;- Different mesh but with one shader?&#xD;&#xA;- Different mesh with different shader but just with low CPU overhead?&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the render time while rendering multiple times the same mesh in &quot;Bounces&quot; using the same technique as [this](https://www.youtube.com/watch?v=nmajnglJeyE) but I have absolutely no idea how it works or even if it can apply to me...&#xD;&#xA;&#xD;&#xA;Obviously I am open to any other suggestions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.openglsuperbible.com/2013/10/16/the-road-to-one-million-draws/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9601" PostHistoryTypeId="5" PostId="4286" RevisionGUID="9a5a2bbe-175a-40a6-9cc4-9078dd1991f7" CreationDate="2016-11-22T17:52:07.010" UserId="5506" Comment="added 55 characters in body" Text="I want to experiment with some new stuff about modern rendering techniques and in that way I'm trying to implement a custom GI (somewhere between pathtracing and instant radiosity).&#xD;&#xA;My scene is a bit less than 1,000,000 tris and my algorithm requires to render the same scene _a lot_ of times into different tiny textures (let's call them &quot;bounces&quot;).&#xD;&#xA;&#xD;&#xA;I've began my implementation in a naive way so I rapidly ran into some performance problems:  &#xD;&#xA;With my 1TFlops laptop GPU I can render my 1M poly scene I can have 200 &quot;bounces&quot; before dropping bellow 30FPS which is far from enough.&#xD;&#xA;&#xD;&#xA;My &quot;naive&quot; algorithm looks like this in pseudo code:&#xD;&#xA;&#xD;&#xA;    for (unsigned int i = 0; i &lt; res ; ++i) {&#xD;&#xA;      UpdateCameraUniform(i);&#xD;&#xA;      glBindFramebuffer(GL_FRAMEBUFFER, BounceFbo[i]);&#xD;&#xA;      glDrawBuffers(1, renderBuffer[i]);&#xD;&#xA;      for (Mesh&amp; m : Scene) {&#xD;&#xA;        m.render();&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    Mesh::render() {&#xD;&#xA;    UpdateTransformUniform();&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, _vbo);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);&#xD;&#xA;    glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The full code is [here](https://github.com/newincpp/GLnewin/tree/master/GLnewin) (the depot is really messy for now...).&#xD;&#xA;&#xD;&#xA;I need to find a new strategy to render my scene so I searched what I could do.  &#xD;&#xA;I think I have 2 strategies:&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the number (or the performance) of my drawcalls. It seems that there is some magic function like glMultiDraw* (I've found it in a post on &quot;OpenGL superbible&quot; [here][1]). But I don't really understand what this does:&#xD;&#xA;- Does this render multiple times the same mesh?&#xD;&#xA;- Different mesh but with one shader?&#xD;&#xA;- Different mesh with different shader but just with low CPU overhead?&#xD;&#xA;&#xD;&#xA;1. Trying to reduce the render time while rendering multiple times the same mesh in &quot;Bounces&quot; using the same technique as [this](https://www.youtube.com/watch?v=nmajnglJeyE) but I have absolutely no idea how it works or even if it can apply to me...&#xD;&#xA;&#xD;&#xA;Obviously I am open to any other suggestions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit: I can reach 200 &quot;bounces&quot; not 35&#xD;&#xA;&#xD;&#xA;  [1]: http://www.openglsuperbible.com/2013/10/16/the-road-to-one-million-draws/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9602" PostHistoryTypeId="5" PostId="4295" RevisionGUID="0db2f05e-99d7-44fa-9e23-5ec107ff550d" CreationDate="2016-11-22T17:52:28.583" UserId="56" Comment="added 406 characters in body" Text="Here's the simple answer.&#xD;&#xA;&#xD;&#xA;In 4d, to be able to multiply them by a 4x4 matrix, vectors are represented as (x,y,z,0) and points are represented as (x,y,z,1).&#xD;&#xA;&#xD;&#xA;Since the 4th row of a 4x4 matrix represents the translation of the matrix, the above representations make it so points are affected by translation, but vectors are not.&#xD;&#xA;&#xD;&#xA;Both vectors and points are affected by the rotation, scaling, etc though.&#xD;&#xA;&#xD;&#xA;**Caveat:**&#xD;&#xA;&#xD;&#xA;There is deeper discussion to be had if you expect the vectors to have certain properties.  For instance, if you transform a triangle's normal by the same matrix you transform the triangle's vertices, it likely won't actually be the normal vector of that triangle anymore.  This is because normals have a sort of inverse relation ship to the vertices that they are calculated from." ContentLicense="CC BY-SA 3.0" />
  <row Id="9607" PostHistoryTypeId="2" PostId="4305" RevisionGUID="dcc4ac4b-4960-45f3-a859-3092c9664432" CreationDate="2016-11-23T02:28:56.030" UserId="5486" Text="Would eye tracking allow for the alignment of a dual layered image (a google glass like device and a screen or projection) to provide a way to force the focus of the eyes into to a real life equivalent of the perceived distance in a similar, but healthier, way in which Anaglyph 3D and other stereoscopic or perspective tricks on a single 2d image confuse the brain into thinking you are?&#xD;&#xA;&#xD;&#xA;[Resolving the Vergence-Accommodation Conﬂict in Head Mounted Displays][1] talks about using eye tracking for &quot;Foveated rendering&quot; and &quot;gaze dependent rendered depth-of-ﬁeld&quot;. There are &quot;Deformable Mirrors in Virtual Retinal Displays&quot; and &quot;Liquid and Electroactive Lens Displays&quot;&#xD;&#xA;&#xD;&#xA;&quot;EVALUATION METHODS We establish four general evaluation strategies to evaluate VAC solutions: (1) subjective user studies, (2) direct measurement of occulomotor responses (3) measurements of physiological fatigue indicators and (4) assessment of brain activity via such tools as EEG or fMRI.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There are [software approaches][2] to minimise this effect;&#xD;&#xA;&#xD;&#xA;&quot;Use long viewing distances when possible — focus cues have less influence as the distance to the display increases. Beyond 1 meter should suffice.&#xD;&#xA;Match the simulated distance in the display and focal distance as well as possible.&#xD;&#xA;Move objects in and out of depth at a pace that gives the user’s eyes more time to adjust.&#xD;&#xA;Maximize the reliability of other depth cues. Accurate perspective, shading realism, and other visual cues that convey realistic depth...&#xD;&#xA;Minimize the consequences of VAC by making existing conflicts less salient.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.umd.edu/sites/default/files/scholarly_papers/Kramidarev.pdf&#xD;&#xA;  [2]: https://medium.com/vrinflux-dot-com/vergence-accommodation-conflict-is-a-bitch-here-s-how-to-design-around-it-87dab1a7d9ba#.n80klmszc" ContentLicense="CC BY-SA 3.0" />
  <row Id="9608" PostHistoryTypeId="1" PostId="4305" RevisionGUID="dcc4ac4b-4960-45f3-a859-3092c9664432" CreationDate="2016-11-23T02:28:56.030" UserId="5486" Text="Is it possible to create a forced focus with a dual layer of images in order to Avoid eye strain with Virtual and Augmented Reality?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9609" PostHistoryTypeId="3" PostId="4305" RevisionGUID="dcc4ac4b-4960-45f3-a859-3092c9664432" CreationDate="2016-11-23T02:28:56.030" UserId="5486" Text="|real-time|virtual-reality|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9619" PostHistoryTypeId="2" PostId="4307" RevisionGUID="ec2a4364-43f1-40e9-bac2-5daa08caae9e" CreationDate="2016-11-24T12:06:18.010" UserId="385" Text="I'm in the process of writing a Ray Tracer using DirectCompute / HLSL. First, eye rays are generated (one per pixel). Then, rays are traced, shaded and reflected in a loop. Also, shadow rays for each light source are generated and tested for occlusion. As a scene structure, I'm using a KD Tree with Ropes$^1$.&#xD;&#xA;&#xD;&#xA;I have analyzed the shader with Joshua Barczak's [Pyramid][1] and it seems that I have a major problem with register pressure, mainly vectors. On A Fiji GCN architecture, the shader uses 85 SGPRs and 81 VGPRs, limiting the number of simultaneous wavefronts per SIMD to 3 (VPGR).&#xD;&#xA;&#xD;&#xA;Furthermore, I have implemented a simple counter in my shader, that atomically increases a value when a thread starts, decreases it when a thread ends and keeps track of the maximum number of shaders that were concurrently running. I've managed to get rid of some data and bring it up from 8192 to 9216, resulting in a correlated speedup of ~%13. When I use an empty dummy shader, I get 16384 concurrent threads.&#xD;&#xA;&#xD;&#xA;I've tried to get rid of excessive variables, especially vectors, by keeping their lifetime as short as possible, and also tried storing some variables in groupshared memory and reading / writing directly from there, all without any change in register count whatsoever.&#xD;&#xA;&#xD;&#xA;Are there any practical tips on how to take pressure of the registers? Is this even as much of a problem as I think it is?&#xD;&#xA;&#xD;&#xA;I have also thought about splitting my Ray Tracer into various kernels. This should, the way I understand it, take pressure of the registers significantly, but also takes quite some coding effort on my part. Does this sound like an idea worth trying?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$^1$ [Popov et al.: Stackless KD-Tree Traversal for High Performance GPU Ray Tracing (2007).][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/jbarczak/Pyramid&#xD;&#xA;  [2]: https://graphics.cg.uni-saarland.de/fileadmin/cguds/papers/2007/popov_07_GPURT/Popov_et_al._-_Stackless_KD-Tree_Traversal_for_High_Performance_GPU_Ray_Tracing.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9620" PostHistoryTypeId="1" PostId="4307" RevisionGUID="ec2a4364-43f1-40e9-bac2-5daa08caae9e" CreationDate="2016-11-24T12:06:18.010" UserId="385" Text="Register pressure in Compute Shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="9621" PostHistoryTypeId="3" PostId="4307" RevisionGUID="ec2a4364-43f1-40e9-bac2-5daa08caae9e" CreationDate="2016-11-24T12:06:18.010" UserId="385" Text="|raytracing|performance|compute-shader|hlsl|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9622" PostHistoryTypeId="2" PostId="4308" RevisionGUID="946d3e08-d1fc-4f81-94c2-456528ae418e" CreationDate="2016-11-24T14:01:42.027" UserId="2041" Text="I'm trying to investigate the effect of certain image operations on how VR scenes are perceived. To do this, I'd like to run an off-the-shelf SteamVR application, capture the frames as they come out of the compositor, run a shader or compute kernel on them, and have them displayed as normal on the HMD. I'm aware of the latency penalty for doing this; I have some ways to minimise it, and in this case I can tolerate extra latency, so don't worry about that for now.&#xD;&#xA;&#xD;&#xA;I can see three strategies which might let me achieve this, but I don't know enough about the display subsystem to know which will work and how to start.&#xD;&#xA;&#xD;&#xA;1. Make a 'fake' display driver. My display driver would take the place of the HMD's driver, and it would act like a proxy. When the SteamVR compositor tries to swap buffers, my driver would do the processing on the backbuffer before poking the real HMD driver. It seems like the main difficulties in this would be (a) getting Windows to accept my fake driver, (b) getting SteamVR to accept my fake driver, and (c) letting my driver use the real HMD driver.&#xD;&#xA;&#xD;&#xA;2. Use normal video capture software (such as OBS) in display capture mode to capture the frames before they get to the display driver, and then use an overlay technique (like the Steam overlay) to draw over the frame completely with my processed frame. This sounds simple, but I know there's a lot of work in making either of the two halves of the system.&#xD;&#xA;&#xD;&#xA;3. Hook into the SteamVR compositor itself. It supports third-party HMD integrations, and I'd hoped I'd be able to trick it into using my shader as a chromatic aberration correction shader, but it turns out that it doesn't let the HMD integration run a shader directly, it just sets the parameters for the built-in shader. This seems like it should be the easiest way, if I can just find a way to make the compositor run my shader. (I'm not averse to hacking the compositor if there's a way.)&#xD;&#xA;&#xD;&#xA;I know some people on the site are also active researchers in this area, so I'm hoping someone has practical experience of what worked and what didn't. Since this is for an experiment, not production software, I'm more interested in an answer I can hack up in a few days to work on one particular PC, than in something that's reliable but takes months to get right." ContentLicense="CC BY-SA 3.0" />
  <row Id="9623" PostHistoryTypeId="1" PostId="4308" RevisionGUID="946d3e08-d1fc-4f81-94c2-456528ae418e" CreationDate="2016-11-24T14:01:42.027" UserId="2041" Text="How can I intercept and filter all frames coming out of SteamVR?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9624" PostHistoryTypeId="3" PostId="4308" RevisionGUID="946d3e08-d1fc-4f81-94c2-456528ae418e" CreationDate="2016-11-24T14:01:42.027" UserId="2041" Text="|virtual-reality|capture|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9625" PostHistoryTypeId="2" PostId="4309" RevisionGUID="978602b7-1c1e-40e5-9cac-a006e6e5d0cf" CreationDate="2016-11-24T14:39:09.100" UserId="1952" Text="Lowering register pressure doesn't necessarily give you any performance boost though. I recently went through this exercise myself on GCN architectures (for a simple ray tracer) and reduced register pressure so that it increased occupancy from 2 to 4, which had no impact on performance. It's generally a good idea to reduce the pressure if you need to hide memory latencies, but it really depends on what the real bottlenecks in your shaders are.&#xD;&#xA;&#xD;&#xA;Since you are working on a GPU ray tracer, you might get better improvement in performance by paying attention to the divergence of threads and try to improve this instead. For example by trying to group rays based on location and direction to reduce divergence in KD-tree traversal per wave. I'm not familiar with the paper you are referring to, and you may already have considered this though." ContentLicense="CC BY-SA 3.0" />
  <row Id="9626" PostHistoryTypeId="5" PostId="4295" RevisionGUID="f4b7a757-55a3-498b-b8c0-e38bf28c4af2" CreationDate="2016-11-24T15:14:13.447" UserId="5353" Comment="typo fixed" Text="Here's the simple answer.&#xD;&#xA;&#xD;&#xA;In 4D, to be able to multiply them by a 4x4 matrix, vectors are represented as (x,y,z,0) and points are represented as (x,y,z,1).&#xD;&#xA;&#xD;&#xA;Since the 4th row of a 4x4 matrix represents the translation of the matrix, the above representations make it so points are affected by translation, but vectors are not.&#xD;&#xA;&#xD;&#xA;Both vectors and points are affected by the rotation, scaling, etc though.&#xD;&#xA;&#xD;&#xA;**Caveat:**&#xD;&#xA;&#xD;&#xA;There is deeper discussion to be had if you expect the vectors to have certain properties.  For instance, if you transform a triangle's normal by the same matrix you transform the triangle's vertices, it likely won't actually be the normal vector of that triangle anymore. This is because normal vectors have a sort of inverse relationship to the vertices that they are calculated from." ContentLicense="CC BY-SA 3.0" />
  <row Id="9627" PostHistoryTypeId="24" PostId="4295" RevisionGUID="f4b7a757-55a3-498b-b8c0-e38bf28c4af2" CreationDate="2016-11-24T15:14:13.447" Comment="Proposed by 5353 approved by 1952, 209 edit id of 181" ContentLicense="CC BY-SA 3.0" />
  <row Id="9628" PostHistoryTypeId="5" PostId="4307" RevisionGUID="7bcedb75-bacd-44d2-8214-9c5b2016b78d" CreationDate="2016-11-24T16:07:07.607" UserId="385" Comment="typo" Text="I'm in the process of writing a Ray Tracer using DirectCompute / HLSL. First, eye rays are generated (one per pixel). Then, rays are traced, shaded and reflected in a loop. Also, shadow rays for each light source are generated and tested for occlusion. As a scene structure, I'm using a KD Tree with Ropes$^1$.&#xD;&#xA;&#xD;&#xA;I have analyzed the shader with Joshua Barczak's [Pyramid][1] and it seems that I have a major problem with register pressure, mainly vectors. On a Fiji GCN architecture, the shader uses 85 SGPRs and 81 VGPRs, limiting the number of simultaneous wavefronts per SIMD to 3 (VPGR).&#xD;&#xA;&#xD;&#xA;Furthermore, I have implemented a simple counter in my shader, that atomically increases a value when a thread starts, decreases it when a thread ends and keeps track of the maximum number of shaders that were concurrently running. I've managed to get rid of some data and bring it up from 8192 to 9216, resulting in a correlated speedup of ~%13. When I use an empty dummy shader, I get 16384 concurrent threads.&#xD;&#xA;&#xD;&#xA;I've tried to get rid of excessive variables, especially vectors, by keeping their lifetime as short as possible, and also tried storing some variables in groupshared memory and reading / writing directly from there, all without any change in register count whatsoever.&#xD;&#xA;&#xD;&#xA;Are there any practical tips on how to take pressure of the registers? Is this even as much of a problem as I think it is?&#xD;&#xA;&#xD;&#xA;I have also thought about splitting my Ray Tracer into various kernels. This should, the way I understand it, take pressure of the registers significantly, but also takes quite some coding effort on my part. Does this sound like an idea worth trying?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$^1$ [Popov et al.: Stackless KD-Tree Traversal for High Performance GPU Ray Tracing (2007).][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/jbarczak/Pyramid&#xD;&#xA;  [2]: https://graphics.cg.uni-saarland.de/fileadmin/cguds/papers/2007/popov_07_GPURT/Popov_et_al._-_Stackless_KD-Tree_Traversal_for_High_Performance_GPU_Ray_Tracing.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9630" PostHistoryTypeId="50" PostId="4178" RevisionGUID="e42dda35-6f8d-469a-afd9-4c06f197306e" CreationDate="2016-11-25T03:44:07.283" UserId="-1" />
  <row Id="9631" PostHistoryTypeId="2" PostId="4310" RevisionGUID="7b41ec37-aa1f-472a-8c47-b6715182a338" CreationDate="2016-11-25T10:49:08.287" UserId="5513" Text="I want to rotate a 3D object. On this website http://paulbourke.net/geometry/rotate/&#xD;&#xA;&#xD;&#xA;the first step says:&#xD;&#xA;&#xD;&#xA;(1) translate space so that the rotation axis passes through the origin&#xD;&#xA;&#xD;&#xA;What is meant by &quot;space&quot;? Is it every point on my object? If so, the matrix he provides would just mean that all the points would end up being 0,0,0 when I multiply it by that matrix. That would mean the rotation matrices would have no effect." ContentLicense="CC BY-SA 3.0" />
  <row Id="9632" PostHistoryTypeId="1" PostId="4310" RevisionGUID="7b41ec37-aa1f-472a-8c47-b6715182a338" CreationDate="2016-11-25T10:49:08.287" UserId="5513" Text="How to translate object to origin?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9633" PostHistoryTypeId="3" PostId="4310" RevisionGUID="7b41ec37-aa1f-472a-8c47-b6715182a338" CreationDate="2016-11-25T10:49:08.287" UserId="5513" Text="|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9634" PostHistoryTypeId="2" PostId="4311" RevisionGUID="c83bc7ef-e0fd-44c5-8080-efe7a8db61fc" CreationDate="2016-11-25T11:11:16.303" UserId="4908" Text="Normally woth rotating objects in 3d you have a pivot. With rotation matrices it is assumed that the pivot is at (0;0;0), the origin. This means that if the pivot is not at (0;0;0), you have to move all the points on that object around so it is.&#xD;&#xA;This can easily be done by subtracting the location of the pivot and after the transformation adding it back in.&#xD;&#xA;So with translating space they mean that you move all the points so that the pivot point is at the origin.&#xD;&#xA;All the points then would not be (0;0;0), just moved.&#xD;&#xA;Hope that helped you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="9635" PostHistoryTypeId="2" PostId="4312" RevisionGUID="1cd8c9c1-74f5-4e58-816c-d380325c1303" CreationDate="2016-11-25T15:45:42.133" UserId="5556" Text="The XYZ and xyY models are extremely useful for certain operations such as manipulating RGB colour spaces to another RGB encoded colour space.&#xD;&#xA;&#xD;&#xA;However, XYZ and xyY fail quite quickly in other contexts. For example, consider MacAdams ellipses that describe noticeable differences on the linear xyY scale.&#xD;&#xA;&#xD;&#xA;All of this sums up to the need for models that extend xyY / XYZ. This enters into the domain of *Colour Appearance Models*, which accurately predict some of the elements such as &quot;colourfulness&quot;. To achieve what you are seeking, you would need to transform your data into one of the many existing colour appearance models that suits your needs.&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Color_appearance_model&#xD;&#xA;http://rit-mcsl.org/fairchild/CAM.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9636" PostHistoryTypeId="2" PostId="4313" RevisionGUID="773f5754-5de9-4240-90ed-30e482684d7c" CreationDate="2016-11-25T16:48:31.527" UserId="56" Text="No, he's talking about subtracting the position of the cube from the vertex positions, so that your cube is positioned at the origin.&#xA;&#xA;Next, you rotate the vertices.&#xA;&#xA;Lastly, you add the position to the vertices again so the box goes back to where it was, but the vertices have been rotated around the location of the box.&#xA;&#xA;Doing rotation like this makes an object spin in place.&#xA;&#xA;If you didn't subtract the position before rotating, the object would orbit the origin, instead of spinning in place." ContentLicense="CC BY-SA 3.0" />
  <row Id="9637" PostHistoryTypeId="5" PostId="4313" RevisionGUID="fddbdd0a-3382-4aa1-a786-228fee88a818" CreationDate="2016-11-25T16:55:47.577" UserId="56" Comment="added 88 characters in body" Text="No, he's talking about subtracting the position of the cube from the vertex positions, so that your cube is positioned at the origin.&#xA;&#xA;If you positioned the cube at (10, 30, 15), you subtract that value from every vertex.&#xA;&#xA;Next, you rotate the vertices.&#xA;&#xA;Lastly, you add the position to the vertices again so the box goes back to where it was, but the vertices have been rotated around the location of the box.&#xA;&#xA;Doing rotation like this makes an object spin in place.&#xA;&#xA;If you didn't subtract the position before rotating, the object would orbit the origin, instead of spinning in place." ContentLicense="CC BY-SA 3.0" />
  <row Id="9642" PostHistoryTypeId="5" PostId="4312" RevisionGUID="9d3df439-cd17-4e16-9e07-08c440101e6a" CreationDate="2016-11-25T22:40:13.527" UserId="5556" Comment="added 200 characters in body" Text="The XYZ and xyY models are extremely useful for certain operations such as manipulating RGB colour spaces to another RGB encoded colour space.&#xD;&#xA;&#xD;&#xA;However, XYZ and xyY fail quite quickly in other contexts. For example, consider MacAdams ellipses that describe noticeable differences on the linear xyY scale.&#xD;&#xA;&#xD;&#xA;All of this sums up to the need for models that extend xyY / XYZ. This enters into the domain of *Colour Appearance Models*, which accurately predict some of the elements such as &quot;colourfulness&quot;. To achieve what you are seeking, you would need to transform your data into one of the many existing colour appearance models that suits your needs.&#xD;&#xA;&#xD;&#xA;All of the problems outlined in the other solution are in fact solved by colour appearance models such as the CIECAM02 model, including psychophysical effects that manifest as optical illusions.&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Color_appearance_model&#xD;&#xA;&#xD;&#xA;http://rit-mcsl.org/fairchild/CAM.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9643" PostHistoryTypeId="5" PostId="4312" RevisionGUID="11173dc7-2d70-4334-b3bc-975c68627aea" CreationDate="2016-11-25T22:45:34.440" UserId="5556" Comment="added 200 characters in body" Text="The XYZ and xyY models are extremely useful for certain operations such as manipulating RGB colour spaces to another RGB encoded colour space.&#xD;&#xA;&#xD;&#xA;However, XYZ and xyY fail quite quickly in other contexts. For example, consider MacAdams ellipses that describe noticeable differences on the linear xyY scale. You could in fact apply a nonlinear, perceptually uniform transform to the xyY values and you'd likely end up closer to what you are hoping for in your circular interface element.&#xD;&#xA;&#xD;&#xA;With that being said, there are needs for models that extend and build upon xyY / XYZ to tackle the psychophysical aspect of colour for evaluating such things as &quot;colourfulness&quot;. This enters into the domain of *Colour Appearance Models*, which are capable of accurately modelling and predicting various issues surrounding brightness (luminance), lightness, colorfulness, chroma, saturation, and hue. To achieve what you are seeking, you would need to transform your data into a colour appearance model such as CIECAM02.&#xD;&#xA;&#xD;&#xA;The problems cited in the other solution are in fact solved by colour appearance models such as the CIECAM02 model, including psychophysical effects that manifest as optical illusions.&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Color_appearance_model&#xD;&#xA;&#xD;&#xA;http://rit-mcsl.org/fairchild/CAM.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9644" PostHistoryTypeId="2" PostId="4315" RevisionGUID="768731cb-130c-492f-9581-d8f0813ce7c6" CreationDate="2016-11-26T21:58:19.217" UserId="2308" Text="I was messing with glowing lighting when I noticed an odd artifact in my first try.&#xD;&#xA;&#xD;&#xA;For some reason I can see three defined edges inside of the glowing pattern. I downloaded the image and marked where I see the edges.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am just curious why they appear to be there as I can see no mathematical reason why they should be there. Is it just the way I am displaying it, or is there some sort of computational precision issue? &#xD;&#xA;&#xD;&#xA;For reference here is the ShaderToy code that created this:&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;    	vec2 uv = fragCoord.xy / iResolution.xy;&#xD;&#xA;    	float disty = abs(uv.y - 0.5);&#xD;&#xA;        float distx = abs(uv.x - 0.5);&#xD;&#xA;        distx *= 100.0;&#xD;&#xA;        disty *= 100.0;&#xD;&#xA;        fragColor = vec4(0.0, pow((1.0 - distx) + (1.0 - disty), -0.5), 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Although I am not sure it is physically accurate to have those spikes on the edges of the diamond I sure do like the effect that creates.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HRuu4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9645" PostHistoryTypeId="1" PostId="4315" RevisionGUID="768731cb-130c-492f-9581-d8f0813ce7c6" CreationDate="2016-11-26T21:58:19.217" UserId="2308" Text="Are these edges a result of display color accuracy, computational accuracy, or something else?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9646" PostHistoryTypeId="3" PostId="4315" RevisionGUID="768731cb-130c-492f-9581-d8f0813ce7c6" CreationDate="2016-11-26T21:58:19.217" UserId="2308" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9647" PostHistoryTypeId="2" PostId="4316" RevisionGUID="9062678f-53f5-4fc2-afb0-eb010206bf0e" CreationDate="2016-11-26T22:34:48.407" UserId="56" Text="The issue is that you are passing a negative value to pow for the first argument, which has undefined behavior.&#xD;&#xA;&#xD;&#xA;What shows up on my screen is completely different than what shows up on yours.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You shouldn't rely on the behavior of anything in the red pixel areas in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;More info:&#xD;&#xA;&#xD;&#xA;https://www.opengl.org/sdk/docs/man4/html/pow.xhtml&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/swsUt.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cVHfO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9648" PostHistoryTypeId="5" PostId="4315" RevisionGUID="b43992d0-4c82-469e-94d9-00882bf5016f" CreationDate="2016-11-27T03:04:18.803" UserId="2308" Comment="added 18 characters in body" Text="I was messing with glowing lighting when I noticed an odd artifact in my first try.&#xD;&#xA;&#xD;&#xA;For some reason I can see three defined edges inside of the glowing pattern. I downloaded the image and marked where I see the edges.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am just curious why they appear to be there as I can see no mathematical reason why they should be there. Is it just the way I am displaying it, or is there some sort of computational precision issue? &#xD;&#xA;&#xD;&#xA;For reference here is the ShaderToy code that created this:&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;        vec2 uv = fragCoord.xy / iResolution.xy;&#xD;&#xA;        float disty = abs(uv.y - 0.5);&#xD;&#xA;        float distx = abs(uv.x - 0.5);&#xD;&#xA;        distx *= 100.0;&#xD;&#xA;        disty *= 100.0;&#xD;&#xA;        fragColor = vec4(0.0, 1.0 / pow(abs((1.0 - distx) + (1.0 - disty)), 0.5), 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Although I am not sure it is physically accurate to have those spikes on the edges of the diamond I sure do like the effect that creates.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HRuu4.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9649" PostHistoryTypeId="5" PostId="4316" RevisionGUID="0eafb7b1-684e-4d0d-a402-6ff4abe0720a" CreationDate="2016-11-27T05:26:41.540" UserId="56" Comment="added 1391 characters in body" Text="**Updated answer, now that pow is getting valid arguments:**&#xD;&#xA;&#xD;&#xA;What you are seeing is called &quot;banding&quot; and it comes from the fact that the color channels are quantized into 8 bits - in other words, it comes from the fact that there are only 256 different shades of green, even though the math generating the colors is capable of much larger resolution.&#xD;&#xA;&#xD;&#xA;The banding on my system isn't as bad as what you are describing but it's still present.  The reason it isn't as bad on my system is because you and I have different displays.&#xD;&#xA;&#xD;&#xA;Some computer displays don't actually even have a full 256 different shades of green.  For instance, instead of having 8 bit color, they may only have 6 bit color, and they either dither it, temporally dither it, or neither and just let it look worse.&#xD;&#xA;&#xD;&#xA;One way to get around this problem is by dithering.  There are various algorithms for dithering, with different computation and quality trade offs.&#xD;&#xA;&#xD;&#xA;A good modern dithering algorithm is called &quot;interleaved gradient noise&quot; which is fairly close to blue noise - which is the ideal - and is pretty cheap to calculate.&#xD;&#xA;&#xD;&#xA;Check out this link for more detailed information on different types of dithering, and how they compare:&#xD;&#xA;&#xD;&#xA;https://bartwronski.com/2016/10/30/dithering-part-three-real-world-2d-quantization-dithering/&#xD;&#xA;&#xD;&#xA;**First answer, from when pow was getting a negative value parameter:**&#xD;&#xA;&#xD;&#xA;The issue is that you are passing a negative value to pow for the first argument, which has undefined behavior.&#xD;&#xA;&#xD;&#xA;What shows up on my screen is completely different than what shows up on yours.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You shouldn't rely on the behavior of anything in the red pixel areas in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;More info:&#xD;&#xA;&#xD;&#xA;https://www.opengl.org/sdk/docs/man4/html/pow.xhtml&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/swsUt.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cVHfO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9656" PostHistoryTypeId="2" PostId="4319" RevisionGUID="c3316add-467b-4467-9d58-28f2aa39b0a0" CreationDate="2016-11-27T14:16:49.077" UserId="1649" Text="While creating a set of glTF models for a tutorial, I also intended to create **THE** minimal glTF file. &#xD;&#xA;&#xD;&#xA;As already mentioned in the [answer by 5chdn](http://computergraphics.stackexchange.com/a/3628/1649), one issue may be the *material*. According to the [Appendix A: Default Material](https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a) of the specification, an asset that does not contain a material should be rendered with a *default* material that simply shows the object in a uniform, 50% gray color. &#xD;&#xA;&#xD;&#xA;Some viewers might not support this, and even if they do, there have been some minor subtleties in the spec regarding this point: In glTF 1.0, it was still necessary to define an &quot;empty&quot; material, because the `mesh.primitive.material` property was not yet optional. But this should be fixed in glTF 1.1. &#xD;&#xA;&#xD;&#xA;So the following should indeed be **THE** minimal possible glTF asset (version 1.1) :&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;      &quot;scenes&quot; : {&#xD;&#xA;        &quot;scene0&quot; : {&#xD;&#xA;          &quot;nodes&quot; : [ &quot;node0&quot; ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;nodes&quot; : {&#xD;&#xA;        &quot;node0&quot; : {&#xD;&#xA;          &quot;meshes&quot; : [ &quot;mesh0&quot; ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;    &#xD;&#xA;      &quot;meshes&quot; : {&#xD;&#xA;        &quot;mesh0&quot; : {&#xD;&#xA;          &quot;primitives&quot; : [ {&#xD;&#xA;            &quot;attributes&quot; : {&#xD;&#xA;              &quot;POSITION&quot; : &quot;positionsAccessor&quot;&#xD;&#xA;            }&#xD;&#xA;          } ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;    &#xD;&#xA;      &quot;buffers&quot; : {&#xD;&#xA;        &quot;buffer0&quot; : {&#xD;&#xA;          &quot;uri&quot; : &quot;data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA&quot;,&#xD;&#xA;          &quot;byteLength&quot; : 36&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;bufferViews&quot; : {&#xD;&#xA;        &quot;positionsBufferView&quot; : {&#xD;&#xA;          &quot;buffer&quot; : &quot;buffer0&quot;,&#xD;&#xA;          &quot;byteOffset&quot; : 0,&#xD;&#xA;          &quot;byteLength&quot; : 36,&#xD;&#xA;          &quot;target&quot; : 34962&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;accessors&quot; : {&#xD;&#xA;        &quot;positionsAccessor&quot; : {&#xD;&#xA;          &quot;bufferView&quot; : &quot;positionsBufferView&quot;,&#xD;&#xA;          &quot;byteOffset&quot; : 0,&#xD;&#xA;          &quot;componentType&quot; : 5126,&#xD;&#xA;          &quot;count&quot; : 3,&#xD;&#xA;          &quot;type&quot; : &quot;VEC3&quot;,&#xD;&#xA;          &quot;max&quot; : [ 1.0, 1.0, 0.0 ],&#xD;&#xA;          &quot;min&quot; : [ 0.0, 0.0, 0.0 ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &#xD;&#xA;      &quot;asset&quot; : {&#xD;&#xA;        &quot;version&quot; : &quot;1.1&quot;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It also shows a single triangle:&#xD;&#xA;&#xD;&#xA;[![TriangleWithoutIndices][1]][1]&#xD;&#xA;&#xD;&#xA;The version without embedded buffers is available at https://github.com/javagl/gltfTutorialModels , as well as a triangle with indices, at https://github.com/javagl/gltfTutorialModels/tree/master/Triangle &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ElVqk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9657" PostHistoryTypeId="2" PostId="4320" RevisionGUID="46b3d816-35f6-4e7e-8297-ed0caadf1590" CreationDate="2016-11-27T15:42:29.077" UserId="5256" Text="How is **glint rendering** done with ray tracing in the photo below? **Is it just a simple normal map?** &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dybNF.png&#xD;&#xA;&#xD;&#xA;I found a paper online that describes the exact same method used in the photo above but I have no idea what's going on, especially with all the jargon being thrown around. Here's the link:&#xD;&#xA;**https://people.eecs.berkeley.edu/~lingqi/publications/paper_glints.pdf**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9658" PostHistoryTypeId="1" PostId="4320" RevisionGUID="46b3d816-35f6-4e7e-8297-ed0caadf1590" CreationDate="2016-11-27T15:42:29.077" UserId="5256" Text="How is glint rendering done in Ray Tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9659" PostHistoryTypeId="3" PostId="4320" RevisionGUID="46b3d816-35f6-4e7e-8297-ed0caadf1590" CreationDate="2016-11-27T15:42:29.077" UserId="5256" Text="|rendering|raytracing|physically-based|normal-mapping|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9662" PostHistoryTypeId="2" PostId="4321" RevisionGUID="824e7482-4cad-442f-979c-584c30e89343" CreationDate="2016-11-27T23:59:40.663" UserId="56" Text="I have some colors in RGB in [0,1] and want to find a way to rate their similarity, as percieved by a human.&#xA;&#xA;I have two ideas in mind, but I am sure there are other options as well, but am unsure which is best, or if perhaps there is no best, but only trade offs.&#xA;&#xA;My first idea is to treat the RGB colors as XYZ points and calculate their distance.&#xA;&#xA;Another idea I have is to treat the RGB values as a histogram and use dot product to get a similarity value between them, where a larger value is better.&#xA;&#xA;I know however, that not all of the color channels have the same percieved brightness so maybe i ought to weight the color channels differently for both cases?&#xA;&#xA;Im also thinking I perhaps would need to do sRGB correction on the color values (such as, sqrt each color channel).&#xA;&#xA;I also know other color spaces exist, so maybe one of those would be better at giving a similarity value.&#xA;&#xA;Anyone able to provide some help/direction?&#xA;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9663" PostHistoryTypeId="1" PostId="4321" RevisionGUID="824e7482-4cad-442f-979c-584c30e89343" CreationDate="2016-11-27T23:59:40.663" UserId="56" Text="What is a good color similarity metric?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9664" PostHistoryTypeId="3" PostId="4321" RevisionGUID="824e7482-4cad-442f-979c-584c30e89343" CreationDate="2016-11-27T23:59:40.663" UserId="56" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9665" PostHistoryTypeId="5" PostId="4321" RevisionGUID="4f945afc-e090-4299-ab4d-8a975b187094" CreationDate="2016-11-28T00:45:21.387" UserId="56" Comment="added 149 characters in body" Text="I have some colors in RGB in [0,1] and want to find a way to rate their similarity, as percieved by a human.&#xA;&#xA;I have two ideas in mind, but I am sure there are other options as well, but am unsure which is best, or if perhaps there is no best, but only trade offs.&#xA;&#xA;My first idea is to treat the RGB colors as XYZ points and calculate their distance.&#xA;&#xA;Another idea I have is to treat the RGB values as a histogram and use dot product to get a similarity value between them, where a larger value is better.&#xA;&#xA;I know however, that not all of the color channels have the same percieved brightness so maybe i ought to weight the color channels differently for both cases?&#xA;&#xA;Im also thinking I perhaps would need to do sRGB correction on the color values (such as, sqrt each color channel).&#xA;&#xA;I also know other color spaces exist, so maybe one of those would be better at giving a similarity value.&#xA;&#xA;Another challenge to this may be that different displays will display the same color values differently.  Not sure if that's relevant in this case.&#xA;&#xA;Anyone able to provide some help/direction?&#xA;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9666" PostHistoryTypeId="2" PostId="4322" RevisionGUID="df64cfeb-e456-48e5-845e-7521cc53435b" CreationDate="2016-11-28T04:43:33.893" UserId="4650" Text="Why is a Lambertian BRDF normalised by dividing by pi? Since the area of a unit sphere is 4 pi, and the area of the half sphere above the surface is 2 pi, shouldn't it rather be 1/(2*pi)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9667" PostHistoryTypeId="1" PostId="4322" RevisionGUID="df64cfeb-e456-48e5-845e-7521cc53435b" CreationDate="2016-11-28T04:43:33.893" UserId="4650" Text="Why normalise Lambertian BRDF by 1/pi?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9668" PostHistoryTypeId="3" PostId="4322" RevisionGUID="df64cfeb-e456-48e5-845e-7521cc53435b" CreationDate="2016-11-28T04:43:33.893" UserId="4650" Text="|brdf|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9671" PostHistoryTypeId="2" PostId="4323" RevisionGUID="9ba47d01-58a5-4c12-ad87-22967d52bdca" CreationDate="2016-11-28T06:13:26.820" UserId="4650" Text="I think I got it! &#xD;&#xA;&#xD;&#xA;Because $cos(\theta)$ integrates to $\pi$ over the hemisphere (and not $2\pi$). And the incoming light is multiplied by $cos(\theta)$ (and the BRDF)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9672" PostHistoryTypeId="5" PostId="4322" RevisionGUID="3df572f8-d71a-4373-8e6c-711bb0e5523f" CreationDate="2016-11-28T06:13:52.323" UserId="4650" Comment="added 11 characters in body" Text="Why is a Lambertian BRDF normalised by dividing by $\pi$? Since the area of a unit sphere is $4 \pi$, and the area of the half sphere above the surface is $2 \pi$, shouldn't it rather be $1/(2\pi)$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9673" PostHistoryTypeId="2" PostId="4324" RevisionGUID="caeec091-9403-4b83-8568-79dfc3bf76b8" CreationDate="2016-11-28T07:20:35.980" UserId="5502" Text="I'm working on an SSAO implementation. I've had an idea to speed it up by having AO fragment shader finish faster for fragments that are not occluded (depending on the scene, this can be a significant portion of the screen in my case).&#xD;&#xA;&#xD;&#xA;I tried a naive approach first: if, after the initial four samples the occlusion is still zero, we exit. This results in a significant speedup, but the quality deteriorates badly: the occluded portions become very noisy.&#xD;&#xA;&#xD;&#xA;I was wondering if anyone else has attempted a similar optimization. Is there a better way to approach it?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="9674" PostHistoryTypeId="1" PostId="4324" RevisionGUID="caeec091-9403-4b83-8568-79dfc3bf76b8" CreationDate="2016-11-28T07:20:35.980" UserId="5502" Text="Early exit strategy for SSAO" ContentLicense="CC BY-SA 3.0" />
  <row Id="9675" PostHistoryTypeId="3" PostId="4324" RevisionGUID="caeec091-9403-4b83-8568-79dfc3bf76b8" CreationDate="2016-11-28T07:20:35.980" UserId="5502" Text="|ambient-occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9676" PostHistoryTypeId="33" PostId="4272" RevisionGUID="9c771c9c-1958-4a29-ba35-5176de1aff81" CreationDate="2016-11-28T08:34:36.323" UserId="5482" Comment="23" />
  <row Id="9677" PostHistoryTypeId="2" PostId="4325" RevisionGUID="a87c149f-90eb-49ea-a7d4-0f82331e2327" CreationDate="2016-11-28T08:59:44.537" UserId="5513" Text="If I have a point in world space: (wx, wy, wz)&#xD;&#xA;&#xD;&#xA;and I have a centre of projection: (cx, cy, cz)&#xD;&#xA;&#xD;&#xA;and I wanted to project that point using perspective projection&#xD;&#xA;&#xD;&#xA;would my point on the screen be calculated by: &#xD;&#xA;&#xD;&#xA;x = (cz * wx) / wz&#xD;&#xA;y = (cz * wy) / wz&#xD;&#xA;&#xD;&#xA;I got this from this lecturer https://www.youtube.com/watch?v=VpNJbvZhNCQ&#xD;&#xA;I don't understand what he means by the variable 'd'. What would the variable 'd' be?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9678" PostHistoryTypeId="1" PostId="4325" RevisionGUID="a87c149f-90eb-49ea-a7d4-0f82331e2327" CreationDate="2016-11-28T08:59:44.537" UserId="5513" Text="Am I calculating perspective projection correctly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9679" PostHistoryTypeId="3" PostId="4325" RevisionGUID="a87c149f-90eb-49ea-a7d4-0f82331e2327" CreationDate="2016-11-28T08:59:44.537" UserId="5513" Text="|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9680" PostHistoryTypeId="5" PostId="3628" RevisionGUID="09ae45a6-f0d1-44fe-b13f-319b397810da" CreationDate="2016-11-28T09:01:59.490" UserId="1649" Comment="Updated link to Appendix A" Text="After spending a hard time to understand the way [how the binary buffers work in the gltf files][1] I finally managed to generate a truely _minimal_ gltf file. It's a single yellow triangle ([demo][2]). &#xD;&#xA;&#xD;&#xA;[![minimal triangle][3]][3]&#xD;&#xA;&#xD;&#xA;I tried to remove everything which is not needed from the gltf. This is what is required it seems ([github][4]):&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;        &quot;accessors&quot;: {&#xD;&#xA;            &quot;accessor0&quot;: {&#xD;&#xA;                &quot;bufferView&quot;: &quot;bufferView0&quot;,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;componentType&quot;: 5123,&#xD;&#xA;                &quot;count&quot;: 3,&#xD;&#xA;                &quot;type&quot;: &quot;SCALAR&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;accessor1&quot;: {&#xD;&#xA;                &quot;bufferView&quot;: &quot;bufferView1&quot;,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;byteStride&quot;: 12,&#xD;&#xA;                &quot;componentType&quot;: 5126,&#xD;&#xA;                &quot;count&quot;: 3,&#xD;&#xA;                &quot;max&quot;: [&#xD;&#xA;                    0.5,&#xD;&#xA;                    0.5,&#xD;&#xA;                    0.5&#xD;&#xA;                ],&#xD;&#xA;                &quot;min&quot;: [&#xD;&#xA;                    0.0,&#xD;&#xA;                    0.0,&#xD;&#xA;                    0.0&#xD;&#xA;                ],&#xD;&#xA;                &quot;type&quot;: &quot;VEC3&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;asset&quot;: {&#xD;&#xA;            &quot;generator&quot;: &quot;5chdn&quot;,&#xD;&#xA;            &quot;profile&quot;: {&#xD;&#xA;                &quot;api&quot;: &quot;WebGL&quot;,&#xD;&#xA;                &quot;version&quot;: &quot;1.0.3&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;version&quot;: &quot;1.0&quot;,&#xD;&#xA;            &quot;extras&quot;: {&#xD;&#xA;                &quot;description&quot;: &quot;minimal gltf, single triangle&quot;,&#xD;&#xA;                &quot;base64encoder&quot;: &quot;https://jsfiddle.net/opkxy0xb/&quot;,&#xD;&#xA;                &quot;stackexchange&quot;: &quot;http://computergraphics.stackexchange.com/q/1934/361&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;bufferViews&quot;: {&#xD;&#xA;            &quot;bufferView0&quot;: {&#xD;&#xA;                &quot;buffer&quot;: &quot;Min&quot;,&#xD;&#xA;                &quot;byteLength&quot;: 6,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;target&quot;: 34963&#xD;&#xA;            },&#xD;&#xA;            &quot;bufferView1&quot;: {&#xD;&#xA;                &quot;buffer&quot;: &quot;Min&quot;,&#xD;&#xA;                &quot;byteLength&quot;: 36,&#xD;&#xA;                &quot;byteOffset&quot;: 6,&#xD;&#xA;                &quot;target&quot;: 34962&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;buffers&quot;: {&#xD;&#xA;            &quot;Min&quot;: {&#xD;&#xA;                &quot;bytelength&quot;: 42,&#xD;&#xA;                &quot;type&quot;: &quot;arraybuffer&quot;,&#xD;&#xA;                &quot;uri&quot;: &quot;data:application/octet-stream;base64,AAABAAIArK34PnZxmz29UhY9T6+UPXuD7z64QAI9UWuaPW/wBT3ysPA+&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;materials&quot;: {&#xD;&#xA;            &quot;effect0&quot;: {&#xD;&#xA;                &quot;values&quot;: {&#xD;&#xA;                    &quot;emission&quot;: [&#xD;&#xA;                        0.8,&#xD;&#xA;                        0.8,&#xD;&#xA;                        0.0,&#xD;&#xA;                        1.0&#xD;&#xA;                    ]&#xD;&#xA;                },&#xD;&#xA;                &quot;technique&quot;: &quot;technique0&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;meshes&quot;: {&#xD;&#xA;            &quot;mesh0&quot;: {&#xD;&#xA;                &quot;name&quot;: &quot;Triangle&quot;,&#xD;&#xA;                &quot;primitives&quot;: [&#xD;&#xA;                    {&#xD;&#xA;                        &quot;attributes&quot;: {&#xD;&#xA;                            &quot;POSITION&quot;: &quot;accessor1&quot;&#xD;&#xA;                        },&#xD;&#xA;                        &quot;indices&quot;: &quot;accessor0&quot;,&#xD;&#xA;                        &quot;material&quot;: &quot;effect0&quot;,&#xD;&#xA;                        &quot;mode&quot;: 4&#xD;&#xA;                    }&#xD;&#xA;                ]&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;nodes&quot;: {&#xD;&#xA;            &quot;node0&quot;: {&#xD;&#xA;                &quot;matrix&quot;: [&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1&#xD;&#xA;                ],&#xD;&#xA;                &quot;meshes&quot;: [&#xD;&#xA;                    &quot;mesh0&quot;&#xD;&#xA;                ],&#xD;&#xA;                &quot;name&quot;: &quot;TriangleMesh&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;programs&quot;: {&#xD;&#xA;            &quot;program0&quot;: {&#xD;&#xA;                &quot;attributes&quot;: [&#xD;&#xA;                    &quot;a_position&quot;&#xD;&#xA;                ],&#xD;&#xA;                &quot;fragmentShader&quot;: &quot;fragmentShader0&quot;,&#xD;&#xA;                &quot;vertexShader&quot;: &quot;vertexShader0&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;scenes&quot;: {&#xD;&#xA;            &quot;scene0&quot;: {&#xD;&#xA;                &quot;nodes&quot;: [&#xD;&#xA;                    &quot;node0&quot;&#xD;&#xA;                ]&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;shaders&quot;: {&#xD;&#xA;            &quot;vertexShader0&quot;: {&#xD;&#xA;                &quot;type&quot;: 35633,&#xD;&#xA;                &quot;uri&quot;: &quot;data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMzIGFfcG9zaXRpb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX1Bvc2l0aW9uID0gdV9wcm9qZWN0aW9uTWF0cml4ICogdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCn0=&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;fragmentShader0&quot;: {&#xD;&#xA;                &quot;type&quot;: 35632,&#xD;&#xA;                &quot;uri&quot;: &quot;data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX0ZyYWdDb2xvciA9IHVfZW1pc3Npb247DQp9&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;techniques&quot;: {&#xD;&#xA;            &quot;technique0&quot;: {&#xD;&#xA;                &quot;attributes&quot;: {&#xD;&#xA;                    &quot;a_position&quot;: &quot;position&quot;&#xD;&#xA;                },&#xD;&#xA;                &quot;parameters&quot;: {&#xD;&#xA;                    &quot;modelViewMatrix&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;MODELVIEW&quot;,&#xD;&#xA;                        &quot;type&quot;: 35676&#xD;&#xA;                    },&#xD;&#xA;                    &quot;projectionMatrix&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;PROJECTION&quot;,&#xD;&#xA;                        &quot;type&quot;: 35676&#xD;&#xA;                    },&#xD;&#xA;                    &quot;emission&quot;: {&#xD;&#xA;                        &quot;type&quot;: 35666&#xD;&#xA;                    },&#xD;&#xA;                    &quot;position&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;POSITION&quot;,&#xD;&#xA;                        &quot;type&quot;: 35665&#xD;&#xA;                    }&#xD;&#xA;                },&#xD;&#xA;                &quot;program&quot;: &quot;program0&quot;,&#xD;&#xA;                &quot;states&quot;: {&#xD;&#xA;                    &quot;enable&quot;: [&#xD;&#xA;                        2884,&#xD;&#xA;                        2929&#xD;&#xA;                    ]&#xD;&#xA;                },&#xD;&#xA;                &quot;uniforms&quot;: {&#xD;&#xA;                    &quot;u_modelViewMatrix&quot;: &quot;modelViewMatrix&quot;,&#xD;&#xA;                    &quot;u_projectionMatrix&quot;: &quot;projectionMatrix&quot;,&#xD;&#xA;                    &quot;u_emission&quot;: &quot;emission&quot;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A good starting point was the [Appendix A of the gltf Specification][5] which defines a default material and shaders. All I had to do was adding the scene description and the buffers.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/a/3624/361&#xD;&#xA;  [2]: http://5chdn.github.io/gltf-tiles-loader-poc/&#xD;&#xA;  [3]: https://i.stack.imgur.com/kMZO0.png&#xD;&#xA;  [4]: https://github.com/5chdn/gltf-tiles-loader-poc/blob/8f25b30fed2324820e0a4a8958715fa2a424305d/data/Min/glTF-Embedded/Min.gltf&#xD;&#xA;  [5]: https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a" ContentLicense="CC BY-SA 3.0" />
  <row Id="9681" PostHistoryTypeId="24" PostId="3628" RevisionGUID="09ae45a6-f0d1-44fe-b13f-319b397810da" CreationDate="2016-11-28T09:01:59.490" Comment="Proposed by 1649 approved by 361 edit id of 182" ContentLicense="CC BY-SA 3.0" />
  <row Id="9682" PostHistoryTypeId="2" PostId="4326" RevisionGUID="fded7b6f-f66f-4994-99ac-3fbdcf2473b6" CreationDate="2016-11-28T12:52:08.143" UserId="5567" Text="If complex metric is acceptable I would suggest to look at perceptual based approach described [here][1]. A list of papers related to that metric can be found [here][2].&#xD;&#xA;&#xD;&#xA;  [1]: http://pdiff.sourceforge.net/&#xD;&#xA;  [2]: https://gist.github.com/reinsteam/9e6b3c05109b8bf121ec0f47252a2e1a&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9683" PostHistoryTypeId="5" PostId="4326" RevisionGUID="65628b17-3cfd-47d4-aea7-a1da87e8236d" CreationDate="2016-11-28T16:00:25.253" UserId="5567" Comment="added 520 characters in body" Text="If complex metric is acceptable I would suggest to look at perceptual based approach described [here][1]. The metric is designed to pick perceptual difference of two images. There are two main tests for that : luminance based and color based. First one allows to answer the question how important luminance change is by estimating a non uniform threshold factor based on sensitivity to contrast changes depending on spatial frequencies of the image. The second one is based on euclidean distance in CIE LAB color space, but slightly modified to make color difference less important when luminance is in mesopic and scotopic ranges. A list of papers related to that metric can be found [here][2].&#xD;&#xA;&#xD;&#xA;[1]: http://pdiff.sourceforge.net/&#xD;&#xA;[2]: https://gist.github.com/reinsteam/9e6b3c05109b8bf121ec0f47252a2e1a" ContentLicense="CC BY-SA 3.0" />
  <row Id="9684" PostHistoryTypeId="2" PostId="4327" RevisionGUID="9fa6674e-cc9a-4230-af4f-a3bd6f3288c3" CreationDate="2016-11-28T23:06:04.277" UserId="56" Text="In the video you linked to, $d$ is just the distance from the eye to the image plane.  To simplify things though, you can just set $d$ to 1, which is the usual case and causes it to disappear from the formulas.&#xD;&#xA;&#xD;&#xA;Your formula for projection is a bit wrong but don't worry, projection is actually pretty simple.&#xD;&#xA;&#xD;&#xA;$x_{Screen} = x_{World} / z_{World}\\&#xD;&#xA;y_{Screen} = y_{World} / z_{World}$&#xD;&#xA;&#xD;&#xA;If you want to move the center of projection, you can do so with a screen space coordinate, by modifying the formula to be this:&#xD;&#xA;&#xD;&#xA;$x_{Screen} = x_{World} / z_{World} - x_{ScreenCenter}\\&#xD;&#xA;y_{Screen} = y_{World} / z_{World} - y_{ScreenCenter}$&#xD;&#xA;&#xD;&#xA;If you want to re-introduce the $d$ value to control the distance from the eye to the projection plane, you can use the formula below.  Adjusting $d$ will make the camera look like it is zooming in or out.  Again, you can just set $d$ to 1 though and not deal with it.&#xD;&#xA;&#xD;&#xA;$x_{Screen} = d*x_{World} / z_{World} - x_{ScreenCenter}\\&#xD;&#xA;y_{Screen} = d*y_{World} / z_{World} - y_{ScreenCenter}$" ContentLicense="CC BY-SA 3.0" />
  <row Id="9688" PostHistoryTypeId="2" PostId="4329" RevisionGUID="97537ef2-c184-40c8-a001-5dcc409554a7" CreationDate="2016-11-29T11:50:16.860" UserId="5571" Text="I feel a bit confused about the use of $F_{ij}$ and $F_{ji}$ in Radiosity papers. $F_{ij}$ should be the fraction of energy leaving patch $i$ that arrives at patch $j$.&#xD;&#xA;&#xD;&#xA;If you take the original radiosity paper *(&quot;Modeling the Interaction of Light Between Diffuse Surfaces&quot;, by Goral, Torrance, Greenberg, and Battaile, at SIGGRAPH 84)*, the radiosity equation is expressed as:&#xD;&#xA;$$&#xD;&#xA;B_{j} = E_{j} + \rho_{j} \sum\limits_{i=1}^n B_{i} F_{ij}&#xD;&#xA;$$&#xD;&#xA;and they explicitly mention that all radiosities are measured in $W/m^2$ and that $F_{ij}$ is the *&quot;form factor and represents the fraction of radiant energy leaving surface i and impinging on surface j&quot;* (sic).&#xD;&#xA;&#xD;&#xA;Now if you take another famous paper *(&quot;The Hemi-Cube. A Radiosity solution for complex environments&quot;, by Cohen and Greenberg, at SIGGRAPH 85)* you see that their equation 1 is:&#xD;&#xA;$$&#xD;&#xA;B_{i} = E_{i} + \rho_{i} \sum\limits_{j=1}^n B_{j} F_{ij}&#xD;&#xA;$$&#xD;&#xA;and they also explicitly say that radiosities are expressed in $W/m^2$ and that $F_{ij}$ is the *&quot;the fraction of the energy leaving one surface which lands on another surface&quot;* (sic).&#xD;&#xA;&#xD;&#xA;Yes, I didn't make a mistake, both papers use $F_{ij}$ even if they switched the $i$ and $j$ indices and even if they're formulating the classical gathering radiosity (the shooting-based progressive refinement approach came later, in SIGGRAPH 88).&#xD;&#xA;&#xD;&#xA;Moreover, to add more into the confusion, some books follow the SIGGRAPH 84 paper equation (*Foley, van Dam, Feiner, Hugues*, for example), while others use the SIGGRAPH 85 paper equation (*Sillion &amp; Puech*, for example).&#xD;&#xA;&#xD;&#xA;I know $F_{ij}$ and $F_{ji}$ get reversed if you express the equation in radiant energy $(W)$ instead of radiosities $(W/m^2)$ because of the reciprocity relationship $F_{ij}A_{i}=F_{ji}A_{j}$, but however, both equations above are explicitly radiosity-based, in $W/m^2$.&#xD;&#xA;&#xD;&#xA;Is there any mistake in radiosity papers? In that case, what equation is right? Or maybe I'm missing some piece in this puzzle?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9689" PostHistoryTypeId="1" PostId="4329" RevisionGUID="97537ef2-c184-40c8-a001-5dcc409554a7" CreationDate="2016-11-29T11:50:16.860" UserId="5571" Text="Form Factors confusion in Radiosity papers" ContentLicense="CC BY-SA 3.0" />
  <row Id="9690" PostHistoryTypeId="3" PostId="4329" RevisionGUID="97537ef2-c184-40c8-a001-5dcc409554a7" CreationDate="2016-11-29T11:50:16.860" UserId="5571" Text="|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9696" PostHistoryTypeId="2" PostId="4331" RevisionGUID="e18a7e80-2641-4e0e-84ba-e2c829faf7a2" CreationDate="2016-11-29T21:16:41.657" UserId="5478" Text="    import javafx.scene.canvas.GraphicsContext;&#xD;&#xA;    import javafx.scene.transform.Affine;&#xD;&#xA;    import javafx.scene.transform.NonInvertibleTransformException;&#xD;&#xA;    double xrange = maxx - minx;&#xD;&#xA;    double yrange = maxy - miny;&#xD;&#xA;    // width and height are in units of pixels&#xD;&#xA;    // gc is the GraphicsContext object from javafx&#xD;&#xA;    Affine t = new Affine();&#xD;&#xA;    double xratio = xrange / width;&#xD;&#xA;    double yratio = yrange / height;&#xD;&#xA;    t.appendTranslation( minx, miny );&#xD;&#xA;    t.appendScale( xratio, yratio );&#xD;&#xA;    try&#xD;&#xA;    {&#xD;&#xA;      t.invert();&#xD;&#xA;    }&#xD;&#xA;    catch( NonInvertibleTransformException e )&#xD;&#xA;    {&#xD;&#xA;      throw new RuntimeException( e.getMessage(), e );&#xD;&#xA;    }&#xD;&#xA;    gc.setTransform( t );" ContentLicense="CC BY-SA 3.0" />
  <row Id="9705" PostHistoryTypeId="5" PostId="1816" RevisionGUID="7c5c48db-7b4b-41f3-8a55-be620141391b" CreationDate="2016-11-30T16:02:01.873" UserId="16" Comment="deleted 3 characters in body" Text="The centre point in your diagram is a degenerate edge of the Voronoi diagram. If you generate a Voronoi diagram for an irregular point cloud, every vertex will have degree 3. A vertex with degree 4 (or more) can only happen when two (or more) vertices coincide. That means there is a zero-length edge between them. But that edge should still have a corresponding edge in the Delaunay triangulation. The issue is that it's arbitrary which of the two possible edges you pick, because the zero-length edge has no associated direction.&#xD;&#xA;&#xD;&#xA;To visualise what I'm talking about, consider starting with four less regularly spaced points (such that we start off with only degree-3 vertices) and gradually translating them into their regular positions.&#xD;&#xA;&#xD;&#xA;We can do this in two different ways, which both lead to the degenerate case in your diagram. You will see that you end up with two different Delaunay triangulations, which are both valid limits for the degenerate case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I assume that your code is missing this degenerate case for one reason or another, but without actually seeing how you compute the Delaunay triangulation from the Voronoi diagram it's impossible to point you any further than this.&#xD;&#xA;&#xD;&#xA;Also note that having even higher degeneracies (by more than four points distributed at equal angles around a circle) would probably require additional attention:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These animations also show that (even in a non-degenerate case), the corresponding Voronoi and Delaunay edges do not necessarily actually cross within their finite extent. That might make it harder to see that the 2 (or 3) edges that triangulate the regular polygon at the end actually correspond to several degenerate edges which are all at the centre. Also note that in total there are 5 different triangulations of the pentagon and 14 triangulations of the hexagon (although I don't know whether all 14 can be obtained by deforming a non-degenerate triangulation).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit** (by OP)&#xD;&#xA;&#xD;&#xA;Voronoi diagrams computed with [Boost.polygon](http://www.boost.org/doc/libs/1_60_0/libs/polygon/doc/index.htm) enable to walk through each Voronoi vertex, and each edge linked to those vertices (clockwise or counter-clockwise). In this way, it is possible to create one triangle for each pair of edges (two connected edges will link to 3 cells).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eu33Z.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/6S6oX.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/5DgNy.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/AddyS.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="9706" PostHistoryTypeId="2" PostId="4333" RevisionGUID="83c700f5-0e33-4c44-88d5-cfb3961ca4b7" CreationDate="2016-11-30T17:22:36.337" UserId="5583" Text="So, I go to install GMIC for Gimp via the package manager and landed myself upon the demo program. I have discovered things such as Hough transform and  color quantization. So, I get the number of colors on the bottom bar, I understand what it is doing, but I do not get the cube in the middle, mainly why it's 3D or that it has other shapes inside of it (other than the dots for the colors chosen). Basically, I want to know the purpose of this cube, such as why is it a cube, or why is it 3D.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/O6REm.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9707" PostHistoryTypeId="1" PostId="4333" RevisionGUID="83c700f5-0e33-4c44-88d5-cfb3961ca4b7" CreationDate="2016-11-30T17:22:36.337" UserId="5583" Text="What is the purpose of this cube in color quantization?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9708" PostHistoryTypeId="3" PostId="4333" RevisionGUID="83c700f5-0e33-4c44-88d5-cfb3961ca4b7" CreationDate="2016-11-30T17:22:36.337" UserId="5583" Text="|color|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9709" PostHistoryTypeId="2" PostId="4334" RevisionGUID="5b0c7aa3-71c9-42d9-bb01-ce071b20e869" CreationDate="2016-11-30T17:55:14.373" UserId="5584" Text="I have NURBS surface data. I have a list of control points, knot vectors in U and V params and the degree. The U knot vector lies in range -3.14 to 3.14 and the knot V vector lies in range -100 to 100. How can I normalize this data so that both knot U and V lies in range 0 to 1?&#xD;&#xA;&#xD;&#xA;Thanks for your help!" ContentLicense="CC BY-SA 3.0" />
  <row Id="9710" PostHistoryTypeId="1" PostId="4334" RevisionGUID="5b0c7aa3-71c9-42d9-bb01-ce071b20e869" CreationDate="2016-11-30T17:55:14.373" UserId="5584" Text="Normalize NURBS knot vector" ContentLicense="CC BY-SA 3.0" />
  <row Id="9711" PostHistoryTypeId="3" PostId="4334" RevisionGUID="5b0c7aa3-71c9-42d9-bb01-ce071b20e869" CreationDate="2016-11-30T17:55:14.373" UserId="5584" Text="|nurbs|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9712" PostHistoryTypeId="2" PostId="4335" RevisionGUID="5d100394-3b32-492a-928e-6fe277ab330a" CreationDate="2016-11-30T19:59:39.063" UserId="48" Text="The cube looks like just an RGB cube, i.e. X,Y,Z map to R,G,B. Since there are 3 color channels, the 3D cube is a convenient way to visualize the space of all possible RGB colors. However, I don't know what the pie-wedge-looking shape outlined inside the cube is." ContentLicense="CC BY-SA 3.0" />
  <row Id="9713" PostHistoryTypeId="2" PostId="4336" RevisionGUID="e59794bf-fb62-44a3-b372-e6ae8e33f21a" CreationDate="2016-11-30T21:48:51.070" UserId="5586" Text="After looking at a lot of existing implementations, I am currently implementing a path tracer in OpenCL. However there seems to be divergence to what parts of the pipeline can actually benefit from OpenCL acceleration.&#xD;&#xA;&#xD;&#xA;So is it possible to construct a complete path tracer in OpenCL? What parts of the pipeline will benefit the most? Which will benefit the least? Are there any parts that is recommended to keep out of OpenCL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9714" PostHistoryTypeId="1" PostId="4336" RevisionGUID="e59794bf-fb62-44a3-b372-e6ae8e33f21a" CreationDate="2016-11-30T21:48:51.070" UserId="5586" Text="What parts of unbiased path tracing pipeline can benefit from OpenCL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9715" PostHistoryTypeId="3" PostId="4336" RevisionGUID="e59794bf-fb62-44a3-b372-e6ae8e33f21a" CreationDate="2016-11-30T21:48:51.070" UserId="5586" Text="|pathtracing|opencl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9716" PostHistoryTypeId="2" PostId="4337" RevisionGUID="01bd3afc-a558-441f-8ecb-1544df78014c" CreationDate="2016-11-30T22:40:36.490" UserId="5587" Text="I am trying to get the screen space position of each pixel in a texture on a mesh and write it into a texture. I was hoping to use a compute shader to do this:&#xD;&#xA;&#xD;&#xA;    #pragma kernel CSMain&#xD;&#xA;    &#xD;&#xA;    struct VertexData&#xD;&#xA;    {&#xD;&#xA;    	float4 v_point;&#xD;&#xA;    	float2 uv;&#xD;&#xA;    	float4x4 MVP; &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    RWTexture2D&lt;float4&gt; Result;&#xD;&#xA;    RWStructuredBuffer&lt;VertexData&gt; vBuf;&#xD;&#xA;&#xD;&#xA;    [numthreads(16,1,1)]&#xD;&#xA;    void CSMain (uint3 id : SV_DispatchThreadID)&#xD;&#xA;    {&#xD;&#xA;    	// one thread per pixel in texture&#xD;&#xA;    &#xD;&#xA;    	//Get pixels position in relation to vertices in UV space, using models UV layout&#xD;&#xA;    &#xD;&#xA;    	//multiply pixels object space position against MVP matrix to bring it into clip space and do some stuff to it&#xD;&#xA;    &#xD;&#xA;    	//finally, output this pixels colour back into the texture, storing screen space related data.&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In the above code (lump of comments) I can tell that I am going to run into some problems. The VertexData struct contains mesh data per vertex, but I want to run a thread for each pixel in a texture and then figure out what my pixels position is on a triangle. In a regular shader, this would be interpolated from the vertex shader when using data in the fragment shader, but from my little knowledge of compute shaders, this would require something extra. In the back of my mind I feel like its going to end up being something to do with Barycentric coords, but I just can't put my finger on it!&#xD;&#xA;&#xD;&#xA;A picture is worth a thousand words:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The desired end result is a texture mapped to the UV coords of a mesh, storing the screen space positions of each pixel on the mesh. If there is a better way of tackling this, please let me know!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Rv4UL.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9717" PostHistoryTypeId="1" PostId="4337" RevisionGUID="01bd3afc-a558-441f-8ecb-1544df78014c" CreationDate="2016-11-30T22:40:36.490" UserId="5587" Text="UV Coordinate Interpolation in Compute Shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="9718" PostHistoryTypeId="3" PostId="4337" RevisionGUID="01bd3afc-a558-441f-8ecb-1544df78014c" CreationDate="2016-11-30T22:40:36.490" UserId="5587" Text="|shader|compute-shader|hlsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9719" PostHistoryTypeId="2" PostId="4338" RevisionGUID="fe87fd40-9c58-443b-a290-1bb0206bd8ee" CreationDate="2016-11-30T23:14:44.050" UserId="56" Text="In short: All of it can benefit from OpenCL.&#xD;&#xA;&#xD;&#xA;Path tracing is done by taking many individual ray samples from a scene and combining them into a final image.  As the number of samples increase, so does the quality of the resulting image.&#xD;&#xA;&#xD;&#xA;If you are doing regular path tracing (not photon mapping or bidirectional path tracing or anything like that), each sample needs just READ ONLY access to the scene so can work completely independently of the other samples.&#xD;&#xA;&#xD;&#xA;That fact makes path tracing astonishing parallelizable.  If you had an output image resolution of 1000x1000, for a total of 1,000,000 pixels, and took 10,000 samples that would mean you needed to take 10,000,000,000 (10 billion) samples.&#xD;&#xA;&#xD;&#xA;Each one of those samples is parallelizable, so if you had 10 billion cores, you could make use of all of them.&#xD;&#xA;&#xD;&#xA;There are pragmatic concerns when doing this including cache coherency, but the costs of getting that wrong with the naive implementation are much smaller than the benefits of going massively threaded in the first place.&#xD;&#xA;&#xD;&#xA;Here is some more information about the details of naive path tracing if you are interested:&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/" ContentLicense="CC BY-SA 3.0" />
  <row Id="9720" PostHistoryTypeId="5" PostId="4333" RevisionGUID="d0edc2ad-acaf-4182-94ce-72fed2a7dd17" CreationDate="2016-12-01T02:49:53.607" UserId="5583" Comment="added 213 characters in body" Text="So, I go to install GMIC for Gimp via the package manager and landed myself upon the demo program. I have discovered things such as Hough transform and  color quantization. So, I get the number of colors on the bottom bar, I understand what it is doing, but I do not get the cube in the middle, mainly why it's 3D or that it has other shapes inside of it (other than the dots for the colors chosen). Basically, I want to know the purpose of this cube, such as why is it a cube, or why is it 3D.&#xD;&#xA;&#xD;&#xA;[![Original RGB Quantization Picture!][1]][1]&#xD;&#xA;&#xD;&#xA;Edit: [![I hope this is a better picture. Turns out the image is different too!][2]][2]&#xD;&#xA;&#xD;&#xA;I hope this is a better picture. Turns out the image is different too!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/O6REm.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/GUzy0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9721" PostHistoryTypeId="2" PostId="4339" RevisionGUID="2a788893-c828-4047-8b4b-b9e7be1685b2" CreationDate="2016-12-01T09:00:20.597" UserId="38" Text="The relative size of the spacing of knots is irrelevant for the NURBS curve. The only thing that matters is that they keep the relation. Note this may not be wise as parametrization may have other uses behind the scenes.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: 3 differently parametrized knots result in same curve if knot values are relatively the same.&#xD;&#xA;&#xD;&#xA;So you can scale and offset knot points as you wish. However you can not make the relative distances between entries different or your curve will change.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: On the other hand if you change the relative spacing your in trouble. So beware of floating point errors if you need to be really accurate.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cZzWl.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ICsHG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9723" PostHistoryTypeId="2" PostId="4340" RevisionGUID="09108e7e-99e2-4961-9101-56a72d721e1f" CreationDate="2016-12-02T08:26:54.907" UserId="5597" Text="my code :&#xD;&#xA;    &#xD;&#xA;    A.layout('neato', args='-Gsep=+250 -Gsplines=ortho -Goverlap=false')&#xD;&#xA;    A.draw('1.svg')&#xD;&#xA;    &#xD;&#xA;    #do something, add new nodes with pos to A,&#xD;&#xA;    add_some_nodes_to_A()&#xD;&#xA;&#xD;&#xA;    for node in A.nodes():&#xD;&#xA;        node.attr['pos'] += '!'&#xD;&#xA;        node.attr['pin'] = 'true'&#xD;&#xA;    A.layout('neato', args='-Gsep=+250 -Gsplines=ortho -Goverlap=false - Gnotranslate=true')&#xD;&#xA;    A.draw('2.svg')&#xD;&#xA;&#xD;&#xA;1.svg :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2.svg : &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;before the second layout, all A's nodes have pined, why the nodes move in 2.svg? &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UfzR0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/isZkZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9724" PostHistoryTypeId="1" PostId="4340" RevisionGUID="09108e7e-99e2-4961-9101-56a72d721e1f" CreationDate="2016-12-02T08:26:54.907" UserId="5597" Text="why pygraphviz layout() move the nodes which has 'pin = true'?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9725" PostHistoryTypeId="3" PostId="4340" RevisionGUID="09108e7e-99e2-4961-9101-56a72d721e1f" CreationDate="2016-12-02T08:26:54.907" UserId="5597" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9726" PostHistoryTypeId="2" PostId="4341" RevisionGUID="52b9cfd6-7152-40d4-a941-bf86a2f2b8c2" CreationDate="2016-12-02T12:22:41.513" UserId="5256" Text="I have been following the [**scratchapixel**][1] ray tracing tutorials online which have been great at explaining the theory behind everything &amp; how to implement it. However I reached the point where I want to implement Area Lights but I am clueless on how to do it. The tutorial on the website hasn't been uploaded yet (all though there is a placeholder link with a bunch of others).&#xD;&#xA;&#xD;&#xA;There's not much online regarding implementation so this has lead me here. **Could someone please explain how I can implement Area Lights with Ray Tracing** as opposed to Point Lights?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/KKjbF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9727" PostHistoryTypeId="1" PostId="4341" RevisionGUID="52b9cfd6-7152-40d4-a941-bf86a2f2b8c2" CreationDate="2016-12-02T12:22:41.513" UserId="5256" Text="Area Lights in Ray Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="9728" PostHistoryTypeId="3" PostId="4341" RevisionGUID="52b9cfd6-7152-40d4-a941-bf86a2f2b8c2" CreationDate="2016-12-02T12:22:41.513" UserId="5256" Text="|rendering|raytracing|physically-based|area|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9731" PostHistoryTypeId="4" PostId="4341" RevisionGUID="56054061-b591-4794-b915-3f746f42f579" CreationDate="2016-12-02T18:18:02.887" UserId="5256" Comment="edited title" Text="Area Lights in Path Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="9732" PostHistoryTypeId="2" PostId="4342" RevisionGUID="d942c62e-0c72-4a59-a96e-5d8286086283" CreationDate="2016-12-02T18:33:39.380" UserId="56" Text="I'm going to provide the simple/naive/brute force answer to this question, which does work, and gives accurate results.&#xD;&#xA;&#xD;&#xA;There are better answers however, which make the rendering converge faster with fewer samples, but uses more advanced math.  I'm hoping someone else will provide an answer along those lines.&#xD;&#xA;&#xD;&#xA;The simple answer is this:&#xD;&#xA;Area lights are just geometry which have an emissive value.&#xD;&#xA;&#xD;&#xA;To add support for emissive values to path tracing is pretty easy luckily.&#xD;&#xA;&#xD;&#xA;As you know, the amount of light heading towards a pixel is the amount of light leaving the surface that a ray down that pixel would intersect.&#xD;&#xA;&#xD;&#xA;That is calculated recursively by seeing how much light is hitting that point, integrating the BRDF, multiplying by the cosine and all that jazz.&#xD;&#xA;&#xD;&#xA;Emissive lighting is just added to that result.  So, whatever you have now as &quot;outgoing light&quot; from a surface, just add to it the emissive color of that surface.  (You could also optionally do something similar to texture mapping and have emissive values vary over the object, possibly based on a texture).&#xD;&#xA;&#xD;&#xA;That's all there is to it, it's very simple and easy.&#xD;&#xA;&#xD;&#xA;You can read more about a simple path tracer with area lights at this link, which also has commented C++ source code.&#xD;&#xA;&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8miKf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9733" PostHistoryTypeId="5" PostId="4342" RevisionGUID="b05c6b40-0db3-47b6-9c90-355f42f81810" CreationDate="2016-12-02T18:41:30.103" UserId="56" Comment="added 475 characters in body" Text="I'm going to provide the simple/naive/brute force answer to this question, which does work, and gives accurate results.&#xD;&#xA;&#xD;&#xA;There are better answers however, which make the rendering converge faster with fewer samples, but uses more advanced math.  I'm hoping someone else will provide an answer along those lines.&#xD;&#xA;&#xD;&#xA;The simple answer is this:&#xD;&#xA;Area lights are just geometry which have an emissive value.&#xD;&#xA;&#xD;&#xA;To add support for emissive values to path tracing is pretty easy luckily.&#xD;&#xA;&#xD;&#xA;As you know, the amount of light heading towards a pixel is the amount of light leaving the surface that a ray down that pixel would intersect.&#xD;&#xA;&#xD;&#xA;That is calculated recursively by seeing how much light is hitting that point, integrating the BRDF, multiplying by the cosine and all that jazz.&#xD;&#xA;&#xD;&#xA;Emissive lighting is just added to that result.  So, whatever you have now as &quot;outgoing light&quot; from a surface, just add to it the emissive color of that surface.  (You could also optionally do something similar to texture mapping and have emissive values vary over the object, possibly based on a texture).&#xD;&#xA;&#xD;&#xA;That's all there is to it, it's very simple and easy.&#xD;&#xA;&#xD;&#xA;In the rendering equation below, $L_e(\omega_o)$ represents the emissive term (that's what the e stands for, emissive), and the rest of the equation is the light integrated over the hemisphere.  You can see that you just add the emissive to the result you return as your outgoing light from a point ($L_o( \omega_o)$) to apply that emissive lighting.&#xD;&#xA;&#xD;&#xA;$L_o( \omega_o)= L_e(\omega_o)+\int_{\Omega}{f(\omega_i, \omega_o)L_i(\omega_i)(\omega_i \cdot n)\mathrm{d}\omega_i}$&#xD;&#xA;&#xD;&#xA;You can read more about a simple path tracer with area lights at this link, which also has commented C++ source code.&#xD;&#xA;&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8miKf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9739" PostHistoryTypeId="2" PostId="4344" RevisionGUID="60fe502f-8264-4b6f-8fba-08ede2f38516" CreationDate="2016-12-03T06:51:09.220" UserId="5256" Text="**How can I implement Depth of Field in my Path Tracer?** I have read this [**article**][1] which explains the theory behind everything &amp; I already have a good understanding of what this effect needs to achieve based on previous experience with a DSLR but **I am a little confused on how to code everything although I understand a most of the calculations involved** *(after reading the article linked above)*. &#xD;&#xA;&#xD;&#xA;Could someone show me their implementation? &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://courses.cs.washington.edu/courses/csep557/99au/projects/trace/depthoffield.doc&#xD;&#xA;  [2]: https://i.stack.imgur.com/nVWIf.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9740" PostHistoryTypeId="1" PostId="4344" RevisionGUID="60fe502f-8264-4b6f-8fba-08ede2f38516" CreationDate="2016-12-03T06:51:09.220" UserId="5256" Text="Depth of Field in Path Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="9741" PostHistoryTypeId="3" PostId="4344" RevisionGUID="60fe502f-8264-4b6f-8fba-08ede2f38516" CreationDate="2016-12-03T06:51:09.220" UserId="5256" Text="|rendering|physically-based|image|depth-of-field|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9742" PostHistoryTypeId="2" PostId="4345" RevisionGUID="f026e563-ee36-440c-819c-fb99d4a988c1" CreationDate="2016-12-03T11:57:00.930" UserId="5603" Text="When I have a plaster cast of a mandibula and rest it upside down on a table, in most cases it will be in a stable position.&#xD;&#xA;&#xD;&#xA;In real life, I do not have a plaster cast, but a 3D scan, i.e. a surface mesh. I want to find the transformation of &quot;table system&quot; to the scan coordinate system.&#xD;&#xA;&#xD;&#xA;Can someone point me to an algorithm? Any keyword I can use to google?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9743" PostHistoryTypeId="1" PostId="4345" RevisionGUID="f026e563-ee36-440c-819c-fb99d4a988c1" CreationDate="2016-12-03T11:57:00.930" UserId="5603" Text="The plane over the top of a surface" ContentLicense="CC BY-SA 3.0" />
  <row Id="9744" PostHistoryTypeId="3" PostId="4345" RevisionGUID="f026e563-ee36-440c-819c-fb99d4a988c1" CreationDate="2016-12-03T11:57:00.930" UserId="5603" Text="|3d|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9745" PostHistoryTypeId="10" PostId="4345" RevisionGUID="6dcbd810-84c1-4d30-9660-4c131a48e09c" CreationDate="2016-12-03T14:18:14.817" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9746" PostHistoryTypeId="2" PostId="4346" RevisionGUID="7f688201-d77d-4d4d-844d-13cbd0954e7e" CreationDate="2016-12-03T15:23:44.857" UserId="231" Text="# The missing step&#xD;&#xA;&#xD;&#xA;If you already understand how to generate a secondary ray, then you have already grasped the difficult part. All you need to do now is find the colour that this secondary ray results in. This is exactly the same process as using the primary ray to find a colour, in basic ray tracing.&#xD;&#xA;&#xD;&#xA;After repeating this for a large number of secondary rays, the average of all those colours is the colour you assign to the pixel in question (you don't use the primary ray - its only purpose is generating the secondary rays). This is the only difference from basic ray tracing.&#xD;&#xA;&#xD;&#xA;# Why it works&#xD;&#xA;&#xD;&#xA;The lens is being approximated by a disc.&#xD;&#xA;&#xD;&#xA;All these different secondary rays show you what you would see from different points on the disc, if you looked directly towards a certain point (the focal point).&#xD;&#xA;&#xD;&#xA;- For an object at the focal point, all these different viewpoints will see the same point on the object, and the object will look sharply defined.&#xD;&#xA;- For an object behind the focal point, all these different viewpoints will see slightly different positions on the object, and some of them will miss the object and see what is to the side of it. The edges of the object will be blended with the colour of whatever is to the side of it.&#xD;&#xA;- For an object in front of the focal point, again the different viewpoints will see slightly different positions on the object, giving blurred edges.&#xD;&#xA;&#xD;&#xA;If a primary ray hits an object at the focal distance, but there is a closer object which is not quite in the way, but almost, then some of the secondary rays will hit the closer object before they reach the focal point. This will give a blurred edge to the closer object, partially obscuring the object at the focal point, even though that object itself is in sharp focus.&#xD;&#xA;&#xD;&#xA;All of this is as desired. To this level of explanation, this mimics the effect of a real lens." ContentLicense="CC BY-SA 3.0" />
  <row Id="9747" PostHistoryTypeId="5" PostId="4344" RevisionGUID="edf77ece-c02e-45c6-b19d-bf31c1721db3" CreationDate="2016-12-03T15:25:41.000" UserId="231" Comment="Add wording of author's comment as this narrows the question." Text="**How can I implement Depth of Field in my Path Tracer?** I have read this [**article**][1] which explains the theory behind everything &amp; I already have a good understanding of what this effect needs to achieve based on previous experience with a DSLR but **I am a little confused on how to code everything although I understand a most of the calculations involved** *(after reading the article linked above)*. &#xD;&#xA;&#xD;&#xA;I understand how to calculate the focal point, focal distance and the secondary ray. But I'm confused on how to put this all together to create the 'blur' that is needed. I haven't found much online so I was hoping that someone here could explain that with some code.&#xD;&#xA;&#xD;&#xA;Could someone show me their implementation? &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://courses.cs.washington.edu/courses/csep557/99au/projects/trace/depthoffield.doc&#xD;&#xA;  [2]: https://i.stack.imgur.com/nVWIf.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9748" PostHistoryTypeId="5" PostId="4346" RevisionGUID="65275cdb-73c1-4fdc-b233-9d44e319a2e3" CreationDate="2016-12-03T15:36:38.837" UserId="231" Comment="Extra explanation" Text="# The missing step&#xD;&#xA;&#xD;&#xA;If you already understand how to generate a secondary ray, then you have already grasped the difficult part. All you need to do now is find the colour that this secondary ray results in. This is exactly the same process as using the primary ray to find a colour, in basic ray tracing.&#xD;&#xA;&#xD;&#xA;After repeating this for a large number of secondary rays, the average of all those colours is the colour you assign to the pixel in question (you don't use the primary ray - its only purpose is generating the secondary rays). This is the only difference from basic ray tracing.&#xD;&#xA;&#xD;&#xA;# Why it works&#xD;&#xA;&#xD;&#xA;My personal difficulty when trying to understand this was that I was trying to understand how the light gets from the different points on the lens back to the eye/camera. The thing to understand is that this is only an approximation of a lens, and the rays don't need to consider the eye/camera at all.&#xD;&#xA;&#xD;&#xA;The lens is being approximated by a disc.&#xD;&#xA;&#xD;&#xA;All these different secondary rays show you what you would see from different points on that disc, if you looked directly towards a certain point (the focal point).&#xD;&#xA;&#xD;&#xA;- For an object at the focal point, all these different viewpoints will see the same point on the object, and the object will look sharply defined.&#xD;&#xA;- For an object behind the focal point, all these different viewpoints will see slightly different positions on the object, and some of them will miss the object and see what is to the side of it. The edges of the object will be blended with the colour of whatever is to the side of it.&#xD;&#xA;- For an object in front of the focal point, again the different viewpoints will see slightly different positions on the object, giving blurred edges.&#xD;&#xA;&#xD;&#xA;If a primary ray hits an object at the focal distance, but there is a closer object which is not quite in the way, but almost, then some of the secondary rays will hit the closer object before they reach the focal point. This will give a blurred edge to the closer object, partially obscuring the object at the focal point, even though that object itself is in sharp focus.&#xD;&#xA;&#xD;&#xA;All of this is as desired. To this level of explanation, this mimics the effect of a real lens, without having to consider refraction at all." ContentLicense="CC BY-SA 3.0" />
  <row Id="9749" PostHistoryTypeId="5" PostId="4248" RevisionGUID="83d52979-23ec-4784-beb9-8b8defce3c70" CreationDate="2016-12-03T16:04:20.510" UserId="5256" Comment="edited body" Text="After reading a few articles online I am can confidently say I am clueless on **how Anti-Aliasing works when Ray Tracing**.&#xD;&#xA;&#xD;&#xA;All I understand is that **A Single Pixel/Ray is split into 4 sub-pixels and 4 rays rather than 1**.&#xD;&#xA;&#xD;&#xA;Could somebody please explain how this is done (preferably with code)? " ContentLicense="CC BY-SA 3.0" />
  <row Id="9750" PostHistoryTypeId="5" PostId="4341" RevisionGUID="22dd317f-ac5d-4fcc-85b5-8b3b57a2627b" CreationDate="2016-12-03T16:05:50.283" UserId="5256" Comment="added 1 character in body" Text="I have been following the [**scratchapixel**][1] ray tracing tutorials online which have been great at explaining the theory behind everything &amp; how to implement it. However, I reached the point where I want to implement Area Lights but I am clueless on how to do it. The tutorial on the website hasn't been uploaded yet (all though there is a placeholder link with a bunch of others).&#xD;&#xA;&#xD;&#xA;There's not much online regarding implementation so this has lead me here. **Could someone please explain how I can implement Area Lights with Ray Tracing** as opposed to Point Lights?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/KKjbF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9751" PostHistoryTypeId="5" PostId="4345" RevisionGUID="87c2a09d-6dcd-467a-b4d6-8074dff8d9da" CreationDate="2016-12-03T16:16:49.867" UserId="5603" Comment="Added explanation" Text="When I have a plaster cast of a mandibula and rest it upside down on a table, in most cases it will be in a stable position.&#xD;&#xA;&#xD;&#xA;In real life, I do not have a plaster cast, but a 3D scan, i.e. a surface mesh. I want to find the transformation of &quot;table system&quot; to the scan coordinate system.&#xD;&#xA;&#xD;&#xA;Why: we have 3D scans of mandibulae, but some of the are sligthly misaligned against the axis because the patient did not sit straight. For easier comparison, we would like make them look more similar. And in case someone suggests &quot;registration&quot;: we do that anyway.&#xD;&#xA;&#xD;&#xA;Can someone point me to an algorithm? Any keyword I can use to google?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9753" PostHistoryTypeId="2" PostId="4347" RevisionGUID="027d46c7-66c4-4e33-872b-59d9c9c601d4" CreationDate="2016-12-03T21:09:53.060" UserId="5586" Text="I am looking for theoretical and implemented models to represent color in software that strives for physical accuracy.&#xD;&#xA;&#xD;&#xA;I know that &quot;color only exists in the mind&quot; and that it sort of does not make sense to look for &quot;physical accuracy&quot;, but still, how much better is spectrum sampling or other more elaborate representations of color to simple RGB, and what benefits will it bring? What drawback beside performance will it incur (or is performance a drawback)?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9754" PostHistoryTypeId="1" PostId="4347" RevisionGUID="027d46c7-66c4-4e33-872b-59d9c9c601d4" CreationDate="2016-12-03T21:09:53.060" UserId="5586" Text="What is the most physically accurate representation of color possible in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9755" PostHistoryTypeId="3" PostId="4347" RevisionGUID="027d46c7-66c4-4e33-872b-59d9c9c601d4" CreationDate="2016-12-03T21:09:53.060" UserId="5586" Text="|color|color-science|implementation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9760" PostHistoryTypeId="5" PostId="4345" RevisionGUID="586918f8-0c19-4914-9d69-77ff4cd3c361" CreationDate="2016-12-04T00:01:33.897" UserId="231" Comment="Clarification of title and body. Please revert anything that changes your intention." Text="When I have a plaster cast of a [mandibula] and rest it upside down on a table, in most cases it will be in a stable position.&#xD;&#xA;&#xD;&#xA;In real life, I do not have a plaster cast, but a 3D scan, i.e. a surface mesh. I want to transform the meshes to the position they would be in if they were resting on a table.&#xD;&#xA;&#xD;&#xA;Why: we have 3D scans of mandibulae, but some of them are slightly misaligned against the axis because the patient did not sit straight. For easier comparison, we would like to make them look more similar. And in case someone suggests &quot;registration&quot;: we do that anyway.&#xD;&#xA;&#xD;&#xA;Can someone point me to an algorithm? Any keyword I can use to google?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [mandibula]: https://en.wikipedia.org/wiki/Mandible &quot;Lower jaw bone&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9761" PostHistoryTypeId="4" PostId="4345" RevisionGUID="586918f8-0c19-4914-9d69-77ff4cd3c361" CreationDate="2016-12-04T00:01:33.897" UserId="231" Comment="Clarification of title and body. Please revert anything that changes your intention." Text="Aligning similar surface meshes consistently" ContentLicense="CC BY-SA 3.0" />
  <row Id="9762" PostHistoryTypeId="11" PostId="4345" RevisionGUID="42cc139e-45a1-4692-8a0d-b351102d7e0a" CreationDate="2016-12-04T00:02:46.437" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9763" PostHistoryTypeId="2" PostId="4349" RevisionGUID="519d8388-a15b-46ae-9b1e-560b62480744" CreationDate="2016-12-04T00:26:34.960" UserId="5586" Text="I  am looking for theoretical and implemented models to represent surface materials in software that strives for physical accuracy.&#xD;&#xA;&#xD;&#xA;Is BRDF really the best model? What alternatives are better? Why? What drawbacks beside performance do these models have?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9764" PostHistoryTypeId="1" PostId="4349" RevisionGUID="519d8388-a15b-46ae-9b1e-560b62480744" CreationDate="2016-12-04T00:26:34.960" UserId="5586" Text="What is the most physically accurate model of surface materials possible in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9765" PostHistoryTypeId="3" PostId="4349" RevisionGUID="519d8388-a15b-46ae-9b1e-560b62480744" CreationDate="2016-12-04T00:26:34.960" UserId="5586" Text="|physically-based|brdf|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9767" PostHistoryTypeId="4" PostId="4344" RevisionGUID="2ef6a4f0-a6e1-4281-9192-c4f1cd9e2bee" CreationDate="2016-12-04T00:57:35.017" UserId="231" Comment="Make title less broad to avoid confusion with other similar questions" Text="Depth of Field in Path Tracing: What do I do with the secondary ray?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9770" PostHistoryTypeId="2" PostId="4350" RevisionGUID="a1f078e1-36e6-47f0-838a-b372990de488" CreationDate="2016-12-04T11:34:43.663" UserId="5605" Text="I am looking for a method of rendering a heightmap from a 3D scene. The scene may consist of a terrain which is in turn generated from another heightmap, but will also have regular 3D objects.&#xD;&#xA;&#xD;&#xA;The generated heightmap should, so to speak, indicate the highest point in the &quot;column&quot; of the 3D scene represented by each pixel in the heightmap.&#xD;&#xA;&#xD;&#xA;This does not need to be a fast/realtime operation, and it does not really matter what language or library is used, although I'd prefer using Python (perhaps with Panda3D?). Also, I would prefer being able to run it headlessly, from a command-line tool without the need for an actual on-screen rendering.&#xD;&#xA;&#xD;&#xA;Is this a common operation for which there are established/canonical methods, either through a library such as Panda3D or through more direct/low-level use of data structures representing the 3D scene?&#xD;&#xA;&#xD;&#xA;I should add that I am quite new to the computer graphics field of programming." ContentLicense="CC BY-SA 3.0" />
  <row Id="9771" PostHistoryTypeId="1" PostId="4350" RevisionGUID="a1f078e1-36e6-47f0-838a-b372990de488" CreationDate="2016-12-04T11:34:43.663" UserId="5605" Text="Method for rendering heightmap from a 3D scene" ContentLicense="CC BY-SA 3.0" />
  <row Id="9772" PostHistoryTypeId="3" PostId="4350" RevisionGUID="a1f078e1-36e6-47f0-838a-b372990de488" CreationDate="2016-12-04T11:34:43.663" UserId="5605" Text="|scene-graph|height-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9774" PostHistoryTypeId="50" PostId="4008" RevisionGUID="8f0c0ff4-50c0-4441-8831-eb71187fcc0a" CreationDate="2016-12-04T16:30:46.640" UserId="-1" />
  <row Id="9776" PostHistoryTypeId="2" PostId="4352" RevisionGUID="60d72390-b76c-476f-977b-8ed75db0c565" CreationDate="2016-12-05T10:13:18.270" UserId="137" Text="The most physically accurate way would be to have a $l(\theta)$ which for each possible color frequency has a certain value.&#xD;&#xA;&#xD;&#xA;Converting to RGB would then need a frequency responce function for each channel and the result is then $\int_{infrared}^{ultraviolet} l(\theta)F_{red}(\theta)d\theta$.&#xD;&#xA;&#xD;&#xA;Reflected light then has a 2 dimensional response function: $L_{reflected}(\theta) = \int l_{incoming}(\phi)R(\phi,\theta)d\phi$. (ignoring the [BRDF][1] here for simplicity)&#xD;&#xA;&#xD;&#xA;Drawbacks are that instead of just 3 color channels you now have **infinite** channels to worry about.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="9777" PostHistoryTypeId="2" PostId="4353" RevisionGUID="be3b5695-1f73-4312-845c-4b50dbcca69b" CreationDate="2016-12-05T15:35:43.780" UserId="4650" Text="You already have a 2D parametrisation, don't you? One of the dimensions is the longitudal axis (in mm?) and the other is the circumferential axis (in degrees). The only problem I see is when you have rectangles wrapping around the 0/360-degree boundary. One workaround for that would be to duplicate each rectangle (or just the ones on the boundary) so that you get one copy on each side of the boundary. Does that help? And if you need to have a distance, and not an angle, for the circular dimension, that is readily available as $l = r a \pi/180$, where $r$ is the radius and $a$ is the angle in degrees." ContentLicense="CC BY-SA 3.0" />
  <row Id="9778" PostHistoryTypeId="34" PostId="4272" RevisionGUID="1b44697c-3869-44b7-8b29-3d88c7e6f094" CreationDate="2016-12-05T16:40:22.730" UserId="5482" Comment="23" />
  <row Id="9779" PostHistoryTypeId="2" PostId="4354" RevisionGUID="70fa188c-14eb-4b5b-89fc-0c1c363a70e4" CreationDate="2016-12-05T19:59:12.123" UserId="4958" Text="I am trying to make use of free hardware PCF sampling with `sampler2DShadow` and extend it to more samples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So far I am sampling shadow map (`sampler2D`) in ESM way and extending this to PCF and it works.&#xD;&#xA;So I have no acne (thanks to ESM) and soft result, but I need a lot of PCF samples:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, lightCoords.xy+off).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But I wanted to use `sampler2DShadow` and get 4 PCF tabs for free and extend this to 16 taps for almost free with only 4 poisson samples like that:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, vec3(lightCoords.xy+off, receiver)).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But unfortunately it doesnt work as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there a way to make it work or due to `shadowSampler2D` specification it is rather impossible?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qjV7F.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9780" PostHistoryTypeId="1" PostId="4354" RevisionGUID="70fa188c-14eb-4b5b-89fc-0c1c363a70e4" CreationDate="2016-12-05T19:59:12.123" UserId="4958" Text="Exponential shadow maps sampling with PCF for sampler2DShadow instead of sampler2D" ContentLicense="CC BY-SA 3.0" />
  <row Id="9781" PostHistoryTypeId="3" PostId="4354" RevisionGUID="70fa188c-14eb-4b5b-89fc-0c1c363a70e4" CreationDate="2016-12-05T19:59:12.123" UserId="4958" Text="|opengl|lighting|glsl|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9782" PostHistoryTypeId="5" PostId="4354" RevisionGUID="b41a4c74-bb83-4708-b1a9-30b79902d3b1" CreationDate="2016-12-05T20:05:52.930" UserId="4958" Comment="added 42 characters in body" Text="I am trying to make use of free hardware PCF sampling with `sampler2DShadow` and extend it to more samples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So far I am sampling shadow map (`sampler2D`) in ESM way and extending this to PCF and it works.&#xD;&#xA;So I have no acne (thanks to ESM) and soft result, but I need a lot of PCF samples:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, lightCoords.xy+off).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But I wanted to use `sampler2DShadow` and get 4 PCF tabs for free and extend this to 16 taps for almost free with only 4 poisson samples like that:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, vec3(lightCoords.xy+off, receiver)).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But unfortunately it doesnt work as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there a way to make it work (in ESM way, not traditional due to acne) or due to `shadowSampler2D` specification it is rather impossible?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qjV7F.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9783" PostHistoryTypeId="5" PostId="4354" RevisionGUID="f327e078-58b5-44da-bff1-9cb4a09ebae5" CreationDate="2016-12-05T20:50:22.013" UserId="4958" Comment="edited body" Text="I am trying to make use of free hardware PCF sampling with `sampler2DShadow` and extend it to more samples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So far I am sampling shadow map (`sampler2D`) in ESM way and extending this to PCF and it works.&#xD;&#xA;So I have no acne (thanks to ESM) and soft result, but I need a lot of PCF samples:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, lightCoords.xy+off).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But I wanted to use `sampler2DShadow` and get 4 PCF tabs for free and extend this to 16 taps for almost free with only 4 poisson samples like that:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, vec3(lightCoords.xy+off, receiver)).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But unfortunately it doesnt work as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there a way to make it work (in ESM way, not traditional due to acne) or due to `sampler2DShadow` specification it is rather impossible?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qjV7F.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9784" PostHistoryTypeId="5" PostId="4354" RevisionGUID="c685fec7-feea-4696-a84b-4ef50aa7c072" CreationDate="2016-12-05T20:58:40.107" UserId="4958" Comment="added 35 characters in body" Text="I am trying to make use of free hardware PCF sampling with `sampler2DShadow` and extend it to more samples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So far I am sampling shadow map (`sampler2D`) in ESM way and extending this to PCF and it works.&#xD;&#xA;So I have no acne (thanks to ESM) and soft result, but I need a lot of PCF samples:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, lightCoords.xy+off).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But I wanted to use `sampler2DShadow` and get 4 PCF tabs for free and extend this to 16 taps for almost free with only 4 poisson samples like that:&#xD;&#xA;&#xD;&#xA;    float shadowMapSize = 512.0;&#xD;&#xA;    float c = 5000.0;&#xD;&#xA;    float receiver = lightCoords.z;&#xD;&#xA;    float shadow = 0.0;&#xD;&#xA;    for(int i = 0; i &lt; SAMPLE_NUM; ++i)&#xD;&#xA;    {&#xD;&#xA;        vec2 off = (POISSON_SAMPLES[i])/shadowMapSize;&#xD;&#xA;        float occluder = texture(shadowmap, vec3(lightCoords.xy+off, receiver)).r;&#xD;&#xA;        shadow += exp(c*(occluder-receiver));&#xD;&#xA;    }&#xD;&#xA;    shadow /= SAMPLE_NUM;&#xD;&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;But unfortunately it doesnt work as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there a way to make it work (in ESM way, not traditional due to acne) or due to `sampler2DShadow` specification it is rather impossible? In traditional way it is possible.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qjV7F.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9785" PostHistoryTypeId="2" PostId="4355" RevisionGUID="dafb201b-6fa6-4f88-8ea9-fa2ac5d792e9" CreationDate="2016-12-05T22:04:07.790" UserId="5002" Text="Using OpenGL, or any such library, you could transform your scene with an orthogonal matrix and move your camera view point to be looking above (and parallel to) the scene (in a vertex shader) and then use an empty fragment shader which is going to write to the depth buffer of the current attached framebuffer. Finally retrieving this depth buffer gives you the heightmap of the current view.&#xD;&#xA;&#xD;&#xA;If your scene is too big, you could move the camera higher and also move it around taking &quot;chunks&quot; of the map at a time and assembling your heightmap manually by &quot;stitching&quot; these &quot;chunk&quot; heightmaps together.&#xD;&#xA;&#xD;&#xA;Hope this helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="9787" PostHistoryTypeId="2" PostId="4356" RevisionGUID="dc7221a0-e236-42a6-85ef-6f16e9910021" CreationDate="2016-12-06T09:20:26.703" UserId="2041" Text="The easiest way to do this is by rendering the 3D scene the way you usually would through OpenGL, using whatever 3D Python library you already have loading the scene. Instead of the perspective camera you would usually use, render through an orthographic camera looking down on the scene from above (making sure the camera plane is above any part of the scene). Make sure the renderer uses a z (depth) buffer, and if you don't want anything on screen, render it to an off-screen buffer (you don't actually need the colour buffer at all, only the z buffer). Just `glReadPixels` the z buffer (i.e. read back the pixels from the buffer) after rendering, and save it to a file. Your 3D library will probably have a way to save the buffer to a file directly." ContentLicense="CC BY-SA 3.0" />
  <row Id="9790" PostHistoryTypeId="2" PostId="4357" RevisionGUID="efd3058d-ec86-4f36-8de3-2c834c83a154" CreationDate="2016-12-06T17:04:28.847" UserId="1952" Text="PFC does N shadow tests where each test returns 1 (in light) or 0 (in shadow), and returns the average of the results. sampler2DShadow is special sampler where this test is performed internally between the texture sample and texture depth coordinate, so you can't use it with ESM." ContentLicense="CC BY-SA 3.0" />
  <row Id="9791" PostHistoryTypeId="2" PostId="4358" RevisionGUID="59b40923-af46-405a-a63f-068f052483c5" CreationDate="2016-12-06T17:49:11.040" UserId="56" Text="You can perform color conversion as a post process step to convert a rendered frame's colors to a different set of colors.&#xD;&#xA;&#xD;&#xA;You might make darker colors more blue for instance, to give it a night time feel, or just modify colors to give it a different mood.&#xD;&#xA;&#xD;&#xA;One way of doing this is using a volume texture.  You use the RGB value of a pixel as texture coordinates into a volume texture, where you read out the RGB value that you should replace that pixel with.&#xD;&#xA;&#xD;&#xA;[This][1] page on the 4d texture GL extension says this though:&#xD;&#xA;&#xD;&#xA;&gt; Four-dimensional textures are used primarily as color lookup tables&#xD;&#xA;&gt; for color conversion.&#xD;&#xA;&#xD;&#xA;Can anyone explain why you would use a 4d texture lookup for color grading?&#xD;&#xA;&#xD;&#xA;Alpha (transparency) lookup doesn't seem like a plausible explanation, but perhaps something like normalizing an HDR color and using the intensity as the fourth component could be?  Or perhaps time, to be able to interpolate between two different color gradings, when moving from inside to outside and exposure is changing or something?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/registry/specs/SGIS/texture4D.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="9792" PostHistoryTypeId="1" PostId="4358" RevisionGUID="59b40923-af46-405a-a63f-068f052483c5" CreationDate="2016-12-06T17:49:11.040" UserId="56" Text="Why would a 4d texture be used for color conversion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9793" PostHistoryTypeId="3" PostId="4358" RevisionGUID="59b40923-af46-405a-a63f-068f052483c5" CreationDate="2016-12-06T17:49:11.040" UserId="56" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9794" PostHistoryTypeId="5" PostId="4358" RevisionGUID="95b72003-42ec-49fe-a0f9-b58db1b9bbd6" CreationDate="2016-12-06T17:54:58.873" UserId="56" Comment="added 7 characters in body" Text="You can perform color conversion as a post process step to convert a rendered frame's colors to a different set of colors.&#xD;&#xA;&#xD;&#xA;You might make darker colors more blue for instance, to give it a night time feel, or just modify colors to give it a different mood.&#xD;&#xA;&#xD;&#xA;One way of doing this is using a volume texture.  You use the RGB value of a source pixel as texture coordinates into a volume texture, where you read out the RGB value that you should replace that pixel with.&#xD;&#xA;&#xD;&#xA;[This][1] page on the 4d texture GL extension says this though:&#xD;&#xA;&#xD;&#xA;&gt; Four-dimensional textures are used primarily as color lookup tables&#xD;&#xA;&gt; for color conversion.&#xD;&#xA;&#xD;&#xA;Can anyone explain why you would use a 4d texture lookup for color grading?&#xD;&#xA;&#xD;&#xA;Alpha (transparency) lookup doesn't seem like a plausible explanation, but perhaps something like normalizing an HDR color and using the intensity as the fourth component could be?  Or perhaps time, to be able to interpolate between two different color gradings, when moving from inside to outside and exposure is changing or something?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/registry/specs/SGIS/texture4D.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="9795" PostHistoryTypeId="2" PostId="4359" RevisionGUID="ee989d5c-2d53-4f90-9f86-baee95d84433" CreationDate="2016-12-06T19:46:50.763" UserId="5632" Text="I think your quote refers to conversion between color spaces, rather than color grading. 4d textures could be used as lookup tables to convert color spaces like CMYK to some other space. Since CMYK has 4 components, a 3d texture wouldn't be enough." ContentLicense="CC BY-SA 3.0" />
  <row Id="9796" PostHistoryTypeId="2" PostId="4360" RevisionGUID="26de56a3-1eb5-44c8-8973-32b46f4b6ace" CreationDate="2016-12-06T21:59:51.237" UserId="3233" Text="I have a point **P** = (0, y, z). I need to determine the x coordinate of its projection **P'** onto a plane **T** along the x axis unit vector **X** = (1, 0, 0). The plane **T** is defined by a point **V** that lies on **T** and its normal **N** (see the attached picture).&#xD;&#xA;&#xD;&#xA;I know how to do this when using **N** (orthogonal projection onto plane). However, I'm not sure if (for this case) the following solution would suffice:&#xD;&#xA;&lt;**X**, **V** - **P**&gt; to get the x coordinate of **P'** = (x, y, z).&#xD;&#xA;&#xD;&#xA;Note: &lt;•,•&gt; means dot product.&#xD;&#xA;&#xD;&#xA;[![Projection onto plane along a vector.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NIbgq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9797" PostHistoryTypeId="1" PostId="4360" RevisionGUID="26de56a3-1eb5-44c8-8973-32b46f4b6ace" CreationDate="2016-12-06T21:59:51.237" UserId="3233" Text="How to project a 3D point onto a plane along another (axis) vector?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9798" PostHistoryTypeId="3" PostId="4360" RevisionGUID="26de56a3-1eb5-44c8-8973-32b46f4b6ace" CreationDate="2016-12-06T21:59:51.237" UserId="3233" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9799" PostHistoryTypeId="2" PostId="4361" RevisionGUID="a452e32e-02de-43a6-9911-4bbe574fee6f" CreationDate="2016-12-06T22:35:52.973" UserId="5633" Text="I am struggling trying to implement vertex selection by mouse clicking. I load in some set of vertices and display them onto the screen. Then I do the following to try and retrieve a line that passes through the selected point in world coordinates and through the eye position.&#xD;&#xA;&#xD;&#xA;      setFocus();&#xD;&#xA;      float xRatio, yRatio, xScene, yScene;&#xD;&#xA;      xRatio = (float)event-&gt;x() / width();&#xD;&#xA;      yRatio = (float)event-&gt;y() / height();&#xD;&#xA;    &#xD;&#xA;      xScene = (1-xRatio)*-1 + xRatio*1;&#xD;&#xA;      yScene = yRatio*-1 + (1-yRatio)*1;&#xD;&#xA;      // mouse click now transformed to [-1,1]^2&#xD;&#xA;    &#xD;&#xA;      // Import the viewPort&#xD;&#xA;          GLint *params = new GLint(4);&#xD;&#xA;          glGetIntegerv(GL_VIEWPORT, params);&#xD;&#xA;          QRect vp = QRect(*params, *(params + 1), *(params + 2), *(params + 3));     &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;          QVector3D dir = QVector3D(xScene, yScene, 0.2); // distance to near pane = 0.2&#xD;&#xA;          QVector3D origin = QVector3D(0.0, 0.0, 0.0);&#xD;&#xA;     &#xD;&#xA;      // Now I have the origin and point in near clipping pane of the line (I think)&#xD;&#xA;      // Unproject them to world coordinates.&#xD;&#xA;          dir = dir.unproject(modelViewMatrix, projectionMatrix, vp);&#xD;&#xA;          origin = origin.unproject(modelViewMatrix, projectionMatrix, vp);&#xD;&#xA;&#xD;&#xA;      float minDist = 1000.0;&#xD;&#xA;      int minIndex = 0;&#xD;&#xA;      float dist;&#xD;&#xA;&#xD;&#xA;      for (int i = 0; i &lt; vertexCoords.size(); ++i){&#xD;&#xA;          dist = vertexCoords[i].distanceToLine(origin, dir);&#xD;&#xA;          if (dist &lt; minDist){&#xD;&#xA;              minDist = dist;&#xD;&#xA;              minIndex = i;&#xD;&#xA;          }&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;I keep getting wrong result with this method. It will almost always select the same point and report a large distance of about 20 to that point. So something is going terribly wrong. Can anyone spot what is going wrong or what I am missing?&#xD;&#xA;&#xD;&#xA;Additionally, here is how the view and projection matrices look:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      modelViewMatrix.setToIdentity();&#xD;&#xA;      modelViewMatrix.translate(QVector3D(0.0, 0.0, -3.0));&#xD;&#xA;      modelViewMatrix.scale(QVector3D(1.0, 1.0, 1.0));&#xD;&#xA;      modelViewMatrix.rotate(rotX, 0.0, 1.0, 0.0);&#xD;&#xA;      modelViewMatrix.rotate(rotY, 1.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      projectionMatrix.setToIdentity();&#xD;&#xA;      projectionMatrix.perspective(FoV, dispRatio, 0.2, 8.0);&#xD;&#xA;&#xD;&#xA;Sorry for the long question, I have found quite some resources online but none of them help me figure out what is going wrong. Also, if there is a better method I would gladly hear it! Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="9800" PostHistoryTypeId="1" PostId="4361" RevisionGUID="a452e32e-02de-43a6-9911-4bbe574fee6f" CreationDate="2016-12-06T22:35:52.973" UserId="5633" Text="How to perform vertex selection using unproject (Qt/openGL)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9801" PostHistoryTypeId="3" PostId="4361" RevisionGUID="a452e32e-02de-43a6-9911-4bbe574fee6f" CreationDate="2016-12-06T22:35:52.973" UserId="5633" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9802" PostHistoryTypeId="5" PostId="4357" RevisionGUID="c473ddcd-0fa0-4996-bd0e-4c72568bdff6" CreationDate="2016-12-06T22:41:32.507" UserId="2654" Comment="Formatting and terminology. It's Percentage Closest Filtering." Text="PCF does N shadow tests, where each test returns 1 (in light) or 0 (in shadow), and returns the average of the results. `sampler2DShadow` is special sampler where PCF is applied to the nearest texels to a sample, based on the depth coordinate provided. So you can't use it with ESM." ContentLicense="CC BY-SA 3.0" />
  <row Id="9803" PostHistoryTypeId="24" PostId="4357" RevisionGUID="c473ddcd-0fa0-4996-bd0e-4c72568bdff6" CreationDate="2016-12-06T22:41:32.507" Comment="Proposed by 2654 approved by 56, 1952 edit id of 184" ContentLicense="CC BY-SA 3.0" />
  <row Id="9804" PostHistoryTypeId="5" PostId="4357" RevisionGUID="404dd084-e568-4eb1-b02e-f2a37da3b39b" CreationDate="2016-12-06T22:51:40.787" UserId="231" Comment="Add the word &quot;a&quot;" Text="PCF does N shadow tests, where each test returns 1 (in light) or 0 (in shadow), and returns the average of the results. `sampler2DShadow` is a special sampler where PCF is applied to the nearest texels to a sample, based on the depth coordinate provided. So you can't use it with ESM." ContentLicense="CC BY-SA 3.0" />
  <row Id="9807" PostHistoryTypeId="2" PostId="4363" RevisionGUID="0e690247-a8e0-4a39-997b-76af712302c9" CreationDate="2016-12-07T10:13:04.487" UserId="2485" Text="I am trying to implement [Blades of Waving Grass][1] and I am still stuck at the point where I need to achieve texture arrangements like in the figure below (the first one).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So my plan is to draw the first texture, then draw the second and rotate it by 30°, then another and rotate it by 60° etc. Drawing the first texture is not a problem but I have some issues rotating the second one. I would expect it to look something like this (view from above):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Instead the actual result looks something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I suspect that this deviation occurs due to the object being rotated around the world-space axes and not around its own.&#xD;&#xA;&#xD;&#xA;Vertex and position data:&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    	-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;    	0.5f, -0.5f, -0.5f, 1.0f, 0.0f,&#xD;&#xA;    	0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;    	0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;    	-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,&#xD;&#xA;    	-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    glm::vec3 texturePositions[] = {&#xD;&#xA;    	glm::vec3(0.0f, 0.0f, 0.0f),&#xD;&#xA;        glm::vec3(0.0f, 0.0f, 0.0f)&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Camera/View transformations:&#xD;&#xA;&#xD;&#xA;		// Camera/View transformation&#xD;&#xA;		glm::mat4 view;&#xD;&#xA;		view = camera.GetViewMatrix();&#xD;&#xA;		// Projection&#xD;&#xA;		glm::mat4 projection;&#xD;&#xA;		projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 1000.0f);&#xD;&#xA;		// Get the uniform locations&#xD;&#xA;		GLint modelLoc = glGetUniformLocation(ourShader.Program, &quot;model&quot;);&#xD;&#xA;		GLint viewLoc = glGetUniformLocation(ourShader.Program, &quot;view&quot;);&#xD;&#xA;		GLint projectionLoc = glGetUniformLocation(ourShader.Program, &quot;projection&quot;);&#xD;&#xA;		// Pass the matrices to the shader&#xD;&#xA;		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));&#xD;&#xA;		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;&#xD;&#xA;Drawing the first two textures:&#xD;&#xA;&#xD;&#xA;			//Texture 1&#xD;&#xA;			glm::mat4 model;&#xD;&#xA;			model = glm::translate(model, texturePositions[0]);			&#xD;&#xA;			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;			//Texture 2&#xD;&#xA;			GLfloat angle = glm::radians(30.0f);&#xD;&#xA;			model = glm::translate(model, texturePositions[1]);&#xD;&#xA;			model = glm::rotate(model, angle, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;Online search showed that this might have several reasons:&#xD;&#xA;&#xD;&#xA; 1. Order of the applied transformations are crucial&#xD;&#xA; 2. One solution might be to first move the &quot;object&quot; until its center&#xD;&#xA;    matches the world-space origin, apply the rotation and then move it&#xD;&#xA;    to the desired position.&#xD;&#xA;&#xD;&#xA;As I am still in the very early learning process so I am kind of clueless here.&#xD;&#xA;&#xD;&#xA; 1. I think that the order of transformations for the second texture is fine in my code, isn't it?&#xD;&#xA; 2. Also how would I determine the right position for the object where&#xD;&#xA;    the rotation would be applied correctly? (see above point 2)&#xD;&#xA; 3. Might it be more efficient to apply the rotation in the objects&#xD;&#xA;    local space? Is that possible in my case?&#xD;&#xA;&#xD;&#xA;I do not expect anybody to write code for me (though some snippet would be nice) but I would appreciate some hints or somebody pointing me in the right direction. I think that I have a basic fallacy here.&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems/gpugems_ch07.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/QVbKy.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/7xhvk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7qQrc.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9808" PostHistoryTypeId="1" PostId="4363" RevisionGUID="0e690247-a8e0-4a39-997b-76af712302c9" CreationDate="2016-12-07T10:13:04.487" UserId="2485" Text="Rotating object around its own center" ContentLicense="CC BY-SA 3.0" />
  <row Id="9809" PostHistoryTypeId="3" PostId="4363" RevisionGUID="0e690247-a8e0-4a39-997b-76af712302c9" CreationDate="2016-12-07T10:13:04.487" UserId="2485" Text="|opengl|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9810" PostHistoryTypeId="2" PostId="4364" RevisionGUID="6d6e75ff-38aa-43bb-bc23-7822e1b4f536" CreationDate="2016-12-07T14:03:26.197" UserId="4958" Text="I see you are rendering one quad of grass at the time. Many draw calls each for small number of vertices aren't very efficient and would make massive CPU bottlenecks especially if you want to render thousand of grass blades. I implemented this grass technique.&#xD;&#xA;&#xD;&#xA;I stored each grass instance (3 quads with 60° degrees between each as in picture) in single VAO which contains buffers for vertices, texcoords, indices:&#xD;&#xA;&#xD;&#xA;    //first quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.5, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.0, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.0, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    //second quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    &#xD;&#xA;    //third quad&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;&#xD;&#xA;*sin* and *cos* are from [circle equation][1].&#xD;&#xA;&#xD;&#xA;    //texcoords&#xD;&#xA;    for (int i = 0; i &lt; 3; ++i)&#xD;&#xA;    {&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 0.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 0.0));&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 1.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //indices&#xD;&#xA;        for(int i = 0; i &lt; 3; ++i)&#xD;&#xA;        {&#xD;&#xA;            for(int j = 0; j &lt; 4; ++j)&#xD;&#xA;            {&#xD;&#xA;                indices.push_back(4*i + j);&#xD;&#xA;                if(j == 3 &amp;&amp; i != 2)&#xD;&#xA;                {&#xD;&#xA;                    indices.push_back(4*i+j);&#xD;&#xA;                    indices.push_back(4*i+j+1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;then draw call for single instance with triangle strip:&#xD;&#xA;&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;But the power lies in drawing many instances with single draw call as you can do it easily with so filled buffer. &#xD;&#xA;&#xD;&#xA;Each instance will have its position somewhere on the terrain which is `glm::vec3` type. This is the additional buffer you need to bind with VAO to do instancing. Then you only need model matrix you use for terrain, for example which scales your terrain, or just identity matrix which you multiply by the position of each instance in vertex shader. thats all.&#xD;&#xA;&#xD;&#xA;In case you need some random scale or rotation matrix for each instance to look more realistic you can generate on the fly based on some random values in vertex shader.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathopenref.com/coordparamcircle.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9811" PostHistoryTypeId="5" PostId="4364" RevisionGUID="e52da728-21b2-4196-99b8-166d032281e7" CreationDate="2016-12-07T14:09:17.237" UserId="4958" Comment="added 65 characters in body" Text="I see you are rendering one quad of grass at the time. Many draw calls each for small number of vertices aren't very efficient and would make massive CPU bottlenecks especially if you want to render thousand of grass blades. I implemented this grass technique.&#xD;&#xA;&#xD;&#xA;I stored each grass instance (3 quads with 60° degrees between each as in picture) in single VAO which contains buffers for vertices, texcoords, indices:&#xD;&#xA;&#xD;&#xA;    //first quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.5, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.0, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.0, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    //second quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    &#xD;&#xA;    //third quad&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;&#xD;&#xA;*sin* and *cos* are from [circle equation][1]. You might need to change these angles to radians if you use glm.&#xD;&#xA;&#xD;&#xA;    //texcoords&#xD;&#xA;    for (int i = 0; i &lt; 3; ++i)&#xD;&#xA;    {&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 0.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 0.0));&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 1.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //indices&#xD;&#xA;        for(int i = 0; i &lt; 3; ++i)&#xD;&#xA;        {&#xD;&#xA;            for(int j = 0; j &lt; 4; ++j)&#xD;&#xA;            {&#xD;&#xA;                indices.push_back(4*i + j);&#xD;&#xA;                if(j == 3 &amp;&amp; i != 2)&#xD;&#xA;                {&#xD;&#xA;                    indices.push_back(4*i+j);&#xD;&#xA;                    indices.push_back(4*i+j+1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;then draw call for single instance with triangle strip:&#xD;&#xA;&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;But the power lies in drawing many instances with single draw call as you can do it easily with so filled buffer. &#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0, totalGrassInstances);&#xD;&#xA;&#xD;&#xA;Each instance will have its position somewhere on the terrain which is `glm::vec3` type. This is the additional buffer you need to bind with VAO to do instancing. Then you only need model matrix you use for terrain, for example which scales your terrain, or just identity matrix which you multiply by the position of each instance in vertex shader. thats all.&#xD;&#xA;&#xD;&#xA;In case you need some random scale or rotation matrix for each instance to look more realistic you can generate on the fly based on some random values in vertex shader.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathopenref.com/coordparamcircle.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9812" PostHistoryTypeId="5" PostId="4364" RevisionGUID="0ffe164d-138a-4aee-81c6-64154542c341" CreationDate="2016-12-07T14:15:39.207" UserId="4958" Comment="added 23 characters in body" Text="I see you are rendering one quad of grass at the time. Many draw calls each for small number of vertices aren't very efficient and would make massive CPU bottlenecks especially if you want to render thousand of grass blades. This isn't an answer to your question about order of transformation but you might consider how I implemented this grass technique.&#xD;&#xA;&#xD;&#xA;I stored each grass instance (3 quads with 60° degrees between each as in picture) in single VAO which contains buffers for vertices, texcoords, indices:&#xD;&#xA;&#xD;&#xA;    //first quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.5, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.5, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.0, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    //second quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    &#xD;&#xA;    //third quad&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;&#xD;&#xA;*sin* and *cos* are from [circle equation][1]. You might need to change these angles to radians if you use glm.&#xD;&#xA;&#xD;&#xA;    //texcoords&#xD;&#xA;    for (int i = 0; i &lt; 3; ++i)&#xD;&#xA;    {&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 0.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 0.0));&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 1.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //indices&#xD;&#xA;        for(int i = 0; i &lt; 3; ++i)&#xD;&#xA;        {&#xD;&#xA;            for(int j = 0; j &lt; 4; ++j)&#xD;&#xA;            {&#xD;&#xA;                indices.push_back(4*i + j);&#xD;&#xA;                if(j == 3 &amp;&amp; i != 2)&#xD;&#xA;                {&#xD;&#xA;                    indices.push_back(4*i+j);&#xD;&#xA;                    indices.push_back(4*i+j+1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;then draw call for single instance with triangle strip:&#xD;&#xA;&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;But the power lies in drawing many instances with single draw call as you can do it easily with so filled buffer. &#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0, totalGrassInstances);&#xD;&#xA;&#xD;&#xA;Each instance will have its position somewhere on the terrain which is `glm::vec3` type. This is the additional buffer you need to bind with VAO to do instancing. Then you only need model matrix you use for terrain, for example which scales your terrain, or just identity matrix which you multiply by the position of each instance in vertex shader. thats all.&#xD;&#xA;&#xD;&#xA;In case you need some random scale or rotation matrix for each instance to look more realistic you can generate on the fly based on some random values in vertex shader.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathopenref.com/coordparamcircle.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9813" PostHistoryTypeId="5" PostId="4364" RevisionGUID="496b90f3-fc3a-440c-9715-88bf74b470a3" CreationDate="2016-12-07T14:40:03.687" UserId="4958" Comment="added 96 characters in body" Text="I see you are rendering one quad of grass at the time. Many draw calls each for small number of vertices aren't very efficient and would make massive CPU bottlenecks especially if you want to render thousand of grass blades. This isn't an answer to your question about order of transformation but you might consider how I implemented this grass technique.&#xD;&#xA;&#xD;&#xA;I stored each grass instance (3 quads with 60° degrees between each as in picture) in single VAO which contains buffers for vertices, texcoords, indices:&#xD;&#xA;&#xD;&#xA;    //first quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.5, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.5, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25, 0.0, 0.0));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    //second quad&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    &#xD;&#xA;    //third quad&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.5, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.5, 0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(0.25 * glm::cos(60.0f), 0.0, -0.25 * glm::sin(60.0f)));&#xD;&#xA;    vertices.push_back(glm::vec3(-0.25 * glm::cos(60.0f), 0.0, 0.25 * glm::sin(60.0f)));&#xD;&#xA;&#xD;&#xA;*sin* and *cos* are from [circle equation][1]. You might need to change these angles to radians if you use glm.&#xD;&#xA;&#xD;&#xA;    //texcoords&#xD;&#xA;    for (int i = 0; i &lt; 3; ++i)&#xD;&#xA;    {&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 0.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 0.0));&#xD;&#xA;        texCoords.push_back(glm::vec2(1.0, 1.0)); &#xD;&#xA;        texCoords.push_back(glm::vec2(0.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //indices&#xD;&#xA;        for(int i = 0; i &lt; 3; ++i)&#xD;&#xA;        {&#xD;&#xA;            for(int j = 0; j &lt; 4; ++j)&#xD;&#xA;            {&#xD;&#xA;                indices.push_back(4*i + j);&#xD;&#xA;                if(j == 3 &amp;&amp; i != 2)&#xD;&#xA;                {&#xD;&#xA;                    indices.push_back(4*i+j);&#xD;&#xA;                    indices.push_back(4*i+j+1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;then draw call for single instance with triangle strip:&#xD;&#xA;&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;But the power lies in drawing many instances with single draw call as you can do it easily with so filled buffer. &#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0, totalGrassInstances);&#xD;&#xA;&#xD;&#xA;Each instance will have its position somewhere on the terrain which is `glm::vec3` type. This is the additional buffer you need to bind with VAO to do instancing. Then you only need `model` matrix you use for terrain, for example which scales your terrain multiplied by `viewProjection`, or just `viewProjection` matrix if your positions generated by CPU are in world space, which you multiply by the position of each instance in vertex shader. thats all.&#xD;&#xA;&#xD;&#xA;In case you need some random scale or rotation matrix for each instance to look more realistic you can generate on the fly based on some random values in vertex shader.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathopenref.com/coordparamcircle.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9814" PostHistoryTypeId="2" PostId="4365" RevisionGUID="1a325e68-b27a-45d2-9eaf-066a3cd417dd" CreationDate="2016-12-07T16:38:40.270" UserId="1952" Text="You can determine `x` by calculating line-plane intersection. Your line starts at `P` and has direction `D=[1, 0, 0]`, and plane `T=[V, N]`. This can be done as follows:&#xD;&#xA;$$x=\frac{(V-P)\cdot N}{N\cdot D}$$&#xD;&#xA;`x` is the distance from `P` along `D` to the intersection point with `T` (assuming both `D` and `N` are unit vectors)" ContentLicense="CC BY-SA 3.0" />
  <row Id="9815" PostHistoryTypeId="2" PostId="4366" RevisionGUID="d187d15d-e1cc-44d9-9032-3c6a69517706" CreationDate="2016-12-07T19:08:26.103" UserId="5640" Text="I tried passing a variable from the vertex shader to tell the fragment shader whether or not I wanted part of an object textured. That way I could write another shader for the other parts of the object. Unfortunately, what I have creates the undesirable effect seen here.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;vertex shader for house&#xD;&#xA;&#xD;&#xA;    &lt;script id=&quot;long_house-vs&quot; type=&quot;x-shader/x-vertex&quot;&gt;&#xD;&#xA;        precision highp float;&#xD;&#xA;    &#xD;&#xA;        attribute vec3 vpos;&#xD;&#xA;        attribute vec3 vnormal;&#xD;&#xA;        attribute vec2 vtexCoords;&#xD;&#xA;    &#xD;&#xA;        varying vec3 outNormal;&#xD;&#xA;        varying vec3 outPos;&#xD;&#xA;        varying vec2 outTexCoords;&#xD;&#xA;        // 1 if part of roof&#xD;&#xA;        varying float roof;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        uniform mat4 view;&#xD;&#xA;        uniform mat4 proj;&#xD;&#xA;        uniform mat4 model;&#xD;&#xA;        uniform vec3 lightdir;&#xD;&#xA;        uniform vec3 long_housecolor;&#xD;&#xA;    &#xD;&#xA;        void main(void) {&#xD;&#xA;            if(vpos.y &gt; 1.2) {&#xD;&#xA;                roof = 1.0;&#xD;&#xA;            } else {&#xD;&#xA;                roof = 0.0;&#xD;&#xA;            }&#xD;&#xA;            gl_Position = proj * view * model * vec4(vpos, 1.0);&#xD;&#xA;            outTexCoords = vtexCoords;&#xD;&#xA;            outPos =  (view * model * vec4(vpos, 1.0)).xyz;&#xD;&#xA;            outNormal = normalize(view * model * vec4(vnormal,0.0)).xyz;&#xD;&#xA;        }&#xD;&#xA;    &lt;/script&gt;&#xD;&#xA;&#xD;&#xA;fragment shader&#xD;&#xA;&#xD;&#xA;    &lt;script id=&quot;long_house-fs&quot; type=&quot;x-shader/x-fragment&quot;&gt;&#xD;&#xA;        precision highp float;&#xD;&#xA;        varying vec3 outNormal;&#xD;&#xA;        varying vec3 outPos;&#xD;&#xA;        varying vec2 outTexCoords;&#xD;&#xA;        varying float roof;&#xD;&#xA;    &#xD;&#xA;        uniform vec3 lightdir;&#xD;&#xA;        uniform vec3 long_housecolor;&#xD;&#xA;        uniform sampler2D usampler;&#xD;&#xA;        uniform sampler2D urooftext;&#xD;&#xA;    &#xD;&#xA;        void main(void) {&#xD;&#xA;            float diffuse = .5 + .5*abs(dot(outNormal, lightdir));&#xD;&#xA;            vec3 outColor = long_housecolor * diffuse;&#xD;&#xA;            vec4 textureColor;&#xD;&#xA;            if(roof == 1.0) {&#xD;&#xA;                textureColor = texture2D(urooftext, outTexCoords);&#xD;&#xA;            } else {&#xD;&#xA;                discard;&#xD;&#xA;            }&#xD;&#xA;            gl_FragColor = vec4(textureColor.rgb * diffuse, textureColor.a);&#xD;&#xA;        }&#xD;&#xA;    &lt;/script&gt;&#xD;&#xA;&#xD;&#xA;When I rearrange the code a bit so that the bottom half of the house is textured instead of the top I get this&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So what would be the correct way to write a shader that only affects part of an object?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rQKtO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vkq46.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9816" PostHistoryTypeId="1" PostId="4366" RevisionGUID="d187d15d-e1cc-44d9-9032-3c6a69517706" CreationDate="2016-12-07T19:08:26.103" UserId="5640" Text="What is the correct way to put different textures on different parts of an object?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9817" PostHistoryTypeId="3" PostId="4366" RevisionGUID="d187d15d-e1cc-44d9-9032-3c6a69517706" CreationDate="2016-12-07T19:08:26.103" UserId="5640" Text="|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9819" PostHistoryTypeId="2" PostId="4367" RevisionGUID="ec1d7b1e-9264-4b88-8439-ebb51d5ce6fb" CreationDate="2016-12-07T19:59:31.397" UserId="4958" Text="In vertex, put  `vPos` as `varying`. Then instead of doing the height check in vertex, do it in fragment.&#xD;&#xA;&#xD;&#xA;    if(outVPos.y &gt; 1.2) &#xD;&#xA;    {&#xD;&#xA;       textureColor = texture2D(urooftext, outTexCoords);&#xD;&#xA;    } &#xD;&#xA;    else &#xD;&#xA;    {&#xD;&#xA;       discard;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;By the way, `varying` qualifier is deprecated and replaced with `out` in vertex and `in` in fragment." ContentLicense="CC BY-SA 3.0" />
  <row Id="9820" PostHistoryTypeId="5" PostId="4360" RevisionGUID="89d3bde8-f3c8-41a8-8b0b-d17954ce9634" CreationDate="2016-12-08T00:41:08.517" UserId="5636" Comment="Inserted LaTeX formatting." Text="I have a point $P = (0, y, z)$. I need to determine the $x$ coordinate of its projection $P'$ onto a plane $T$ along the $x$ axis unit vector $\vec{X} = (1, 0, 0)$. The plane $T$ is defined by a point $V$ that lies on $T$ and its normal $\vec{N}$ (see the attached picture).&#xD;&#xA;&#xD;&#xA;I know how to do this when using $\vec{N}$ (orthogonal projection onto plane). However, I'm not sure if (for this case) the following solution would suffice:&#xD;&#xA;$\vec{X}•(V-P)$ to get the $x$ coordinate of $P' = (x, y, z)$.&#xD;&#xA;&#xD;&#xA;[![Projection onto plane along a vector.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NIbgq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9821" PostHistoryTypeId="24" PostId="4360" RevisionGUID="89d3bde8-f3c8-41a8-8b0b-d17954ce9634" CreationDate="2016-12-08T00:41:08.517" Comment="Proposed by 5636 approved by 231 edit id of 185" ContentLicense="CC BY-SA 3.0" />
  <row Id="9822" PostHistoryTypeId="2" PostId="4368" RevisionGUID="ba919df5-6b73-46b9-9719-59879c14f824" CreationDate="2016-12-08T04:41:03.083" UserId="1952" Text="There is [spectral rendering][1], where you can quantize the visible wavelengths from ~390nm to ~700nm to N discrete wavelengths instead of the standard 3 for RGB. Then if you had to model say a prism, you would get more realistic distribution of the spectrum.&#xA;&#xA;Light has also property of polarization that you would need to model for increased realism. I don't know if this is being modeled in any existing publicly available rendering engines and how would you represent it exactly. This would would be a relevant propery for example to model multiple specular reflections from dielectric surfaces.&#xA;&#xA;Both spectral rendering and accounting light polarization would come with the cost of performance and higher memory usage.&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Spectral_rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="9823" PostHistoryTypeId="5" PostId="4368" RevisionGUID="a34cf6a6-cd3a-4ee8-9af4-6dc41b92bbf9" CreationDate="2016-12-08T05:02:32.973" UserId="1952" Comment="added 266 characters in body" Text="There is [spectral rendering][1], where you can quantize the visible wavelengths from ~390nm to ~700nm to N discrete wavelengths instead of the standard 3 for RGB. Then if you had to model say a prism, you would get more realistic distribution of the spectrum.&#xA;&#xA;Light has also property of polarization that you would need to model for increased realism. I don't know if this is being modeled in any existing publicly available rendering engines and how would you represent it exactly. Light is electromagnetic wave with two orthogonal electric and magnetic components, which may have different amplitudes and be also out of phase potentially resulting in elliptical polarization. The polarization would be a relevant propery for example to model multiple specular reflections from dielectric surfaces, or modeling polarizing filters used by photographers on cameras.&#xA;&#xA;Both spectral rendering and accounting light polarization would come with the cost of performance and higher memory usage.&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Spectral_rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="9824" PostHistoryTypeId="2" PostId="4369" RevisionGUID="5828a4e0-4821-47b5-b5cb-90ff666fda59" CreationDate="2016-12-08T12:25:51.290" UserId="5256" Text="**How could I generate the waves for a water body with whitecaps &amp; foam and variable intensity of the waves?** Is the surface a mesh with a normal map? Is there a formula for generating that? Is there something similar to determine where and how the whitecaps are rendered?  I came across this [**paper**][1] but it's not very clear.&#xD;&#xA;&#xD;&#xA;In the paper, I understand the part where it talks about wave generation. There is a section dedicated to whitecaps and foam and it does present a formula to generate them but how do you only apply it to the parts of the water that need it? Based on what I observed it just represents F as the area that will need whitecaps, could someone clarify how that works aswell?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.utah.edu/~michael/water/waterPGColor.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="9825" PostHistoryTypeId="1" PostId="4369" RevisionGUID="5828a4e0-4821-47b5-b5cb-90ff666fda59" CreationDate="2016-12-08T12:25:51.290" UserId="5256" Text="Ocean Wave Generation" ContentLicense="CC BY-SA 3.0" />
  <row Id="9826" PostHistoryTypeId="3" PostId="4369" RevisionGUID="5828a4e0-4821-47b5-b5cb-90ff666fda59" CreationDate="2016-12-08T12:25:51.290" UserId="5256" Text="|rendering|raytracing|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9827" PostHistoryTypeId="4" PostId="4369" RevisionGUID="834c4e54-5b76-4279-97ed-0111f82d3771" CreationDate="2016-12-08T13:04:06.707" UserId="5256" Comment="edited title" Text="Ocean Wave Rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="9828" PostHistoryTypeId="2" PostId="4370" RevisionGUID="832438d2-ae97-432b-9482-e2369a3c1741" CreationDate="2016-12-08T18:49:30.387" UserId="18" Text="*I'd like to create a mesh from a point cloud generated by video tracking, ideally using python for some kind of prototype at least.*&#xD;&#xA;&#xD;&#xA;Initially I thought this is a fairly easy task, connecting the vertices, creating the faces, done ;) Then I've read that [Screened Poisson Surface Reconstruction][1] is currently the best approach. Although there is a nice [github repository][2] and code to play with, it's hard to understand the papers.&#xD;&#xA;&#xD;&#xA;**Q:** Is there another clever implementation/approach you would recommend or is *Screened Poisson Surface Reconstruction* the way to go? Any suggestion how to implement that as simple as possible will be greatly appreciated.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.jhu.edu/~misha/Code/PoissonRecon/Version9.01/&#xD;&#xA;  [2]: https://github.com/mkazhdan/PoissonRecon" ContentLicense="CC BY-SA 3.0" />
  <row Id="9829" PostHistoryTypeId="1" PostId="4370" RevisionGUID="832438d2-ae97-432b-9482-e2369a3c1741" CreationDate="2016-12-08T18:49:30.387" UserId="18" Text="Creating a mesh from a point cloud?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9830" PostHistoryTypeId="3" PostId="4370" RevisionGUID="832438d2-ae97-432b-9482-e2369a3c1741" CreationDate="2016-12-08T18:49:30.387" UserId="18" Text="|computational-geometry|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9838" PostHistoryTypeId="2" PostId="4371" RevisionGUID="04f252a3-33f7-4ad8-978b-0963817e029e" CreationDate="2016-12-09T03:15:10.777" UserId="1952" Text="There are couple of ways this is usually done:&#xA;&#xA;1) put the textures for the house to a single texture are just UV-map the object accordingly. If you would need to use different BRDF etc. for different parts of the object, you can use uber shader and switch in shader and use another texture to control which BRDF to use in which parts. The benefit is that you can render the entire object with a single draw call reducing CPU overhead with the expense of some GPU overhead due to the uber shader.&#xA;&#xA;2) split the object to different sub-objects (at triangle level) based on the material and issue separate draw call for each. This keeps the shader simpler, but has higher CPU overhead due to more draw calls." ContentLicense="CC BY-SA 3.0" />
  <row Id="9855" PostHistoryTypeId="2" PostId="4374" RevisionGUID="deb72bc6-1901-419f-ba1f-3343e806988e" CreationDate="2016-12-10T17:52:17.820" UserId="5653" Text="I am writing a basic raytracer and have implemented normal maps. However, when using normal maps, sometimes the rays generated are opposite to the surface's geometry normal, so that the rays are reaching light sources behind the object. If I kill the ray, the shading results looked faceted and the surface normals are apparent. If I don't kill the ray, the ray reaches light sources on the opposite side of the geometry.&#xD;&#xA;&#xD;&#xA;How is this handled normally?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9856" PostHistoryTypeId="1" PostId="4374" RevisionGUID="deb72bc6-1901-419f-ba1f-3343e806988e" CreationDate="2016-12-10T17:52:17.820" UserId="5653" Text="Sampling against geometry normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="9857" PostHistoryTypeId="3" PostId="4374" RevisionGUID="deb72bc6-1901-419f-ba1f-3343e806988e" CreationDate="2016-12-10T17:52:17.820" UserId="5653" Text="|raytracing|geometry|shading|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9858" PostHistoryTypeId="2" PostId="4375" RevisionGUID="a4660b52-2f13-46b5-8e34-d4e0afc1725b" CreationDate="2016-12-10T18:01:57.447" UserId="4908" Text="One thing that I see being done, is that when the ray is generated, the location is shifted on the normal. Basically the normal multiplied by a small amount is added to it.&#xD;&#xA;If you are shading the backside of the face, then the normal needs to be inverted.&#xD;&#xA;&#xD;&#xA;The reason why, is, for example, when a light is behind a face, and you cast the light ray. Without the offset the origin is exactly on the face, so t is 0. Algorithms see this as not a hit, so the offset along the normal, makes it so that t isn't 0 anymore.&#xD;&#xA;&#xD;&#xA;I hope this answers it." ContentLicense="CC BY-SA 3.0" />
  <row Id="9869" PostHistoryTypeId="2" PostId="4377" RevisionGUID="490022e0-b359-431a-91ae-a41b86f1e101" CreationDate="2016-12-12T14:51:30.703" UserId="2372" Text="I am trying to implement the [Percentage-closer Soft Shadows][1] (PCSS) from NVidia inside Unity but I am facing some issue and I don't know where they come from and then, I do not know how to solve them...&#xD;&#xA;&#xD;&#xA;Here is my current setup.&#xD;&#xA;&#xD;&#xA;I using an orthographic camera to calculate my shadowmap here are the different steps and some pseudo-code.&#xD;&#xA;&#xD;&#xA;    // Setup camera&#xD;&#xA;    _shadowCamera.clearFlags = CameraClearFlags.Depth;&#xD;&#xA;    _shadowCamera.orthographic= true;&#xD;&#xA;    &#xD;&#xA;    // Setup a render texture to output the shadowmap from the camera&#xD;&#xA;    RenderTexture _shadowTexture = new RenderTexture((int)_shadowMapSize, _shadowMapSize, 16, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);&#xD;&#xA;    &#xD;&#xA;    // Render scene using a replacement shader. This is only used to output &#xD;&#xA;    _shadowCamera.SetReplacementShader(_shadowMapShader, &quot;RenderType&quot;);&#xD;&#xA;    _shadowCamera.Render();&#xD;&#xA;    &#xD;&#xA;    // Set the camera positions and matrix&#xD;&#xA;    _radius = _bounds;&#xD;&#xA;    Vector3 targetPos = _target.transform.position;&#xD;&#xA;    Vector3 lightDir = _light.transform.forward;&#xD;&#xA;    Quaternion lightRot = _light.transform.rotation;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.transform.position = targetPos - lightDir * _radius;&#xD;&#xA;    _shadowCamera.transform.rotation = lightRot;&#xD;&#xA;    _shadowCamera.orthographicSize = _radius;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.farClipPlane = _radius * 2.0f;&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowViewMatrix = _shadowCamera.worldToCameraMatrix;&#xD;&#xA;    Matrix4x4 shadowProjectionMatrix = GL.GetGPUProjectionMatrix(_shadowCamera.projectionMatrix, false);&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowBiasMatrix = Matrix4x4.identity;&#xD;&#xA;    shadowBiasMatrix.SetRow(0, new Vector4(0.5f, 0.0f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(1, new Vector4(0.0f, 0.5f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f));&#xD;&#xA;    shadowBiasMatrix.SetRow(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));&#xD;&#xA;    &#xD;&#xA;    _shadowMatrix = shadowBiasMatrix * shadowProjectionMatrix * shadowViewMatrix;&#xD;&#xA;&#xD;&#xA;    // Transfering data to shader&#xD;&#xA;    _material.SetMatrix(&quot;_ShadowMatrix&quot;, _shadowMatrix);&#xD;&#xA;    _material.SetTexture(&quot;_ShadowTexture&quot;, _shadowTexture);&#xD;&#xA;    _material.SetTexture(&quot;u_PointSampler&quot;, _pointSampler);&#xD;&#xA;    _material.SetFloat(&quot;u_NearPlane&quot;, _shadowCamera.nearClipPlane);&#xD;&#xA;    _material.SetFloat(&quot;u_LightWorldSize&quot;, _lightWorldSize);&#xD;&#xA;    _material.SetFloat(&quot;u_LightFrustrumWidth&quot;, _lightFrustrumWidth);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In my shader, I am simply doing the blocker search part and here is also some pseudo-code.&#xD;&#xA;&#xD;&#xA;    #define BLOCKER_SEARCH_NUM_SAMPLES 16&#xD;&#xA;    #define NEAR_PLANE u_NearPlane&#xD;&#xA;    #define LIGHT_WORLD_SIZE u_LightWorldSize&#xD;&#xA;    #define LIGHT_FRUSTUM_WIDTH u_LightFrustrumWidth&#xD;&#xA;    #define LIGHT_SIZE_UV (LIGHT_WORLD_SIZE / LIGHT_FRUSTUM_WIDTH) &#xD;&#xA;    &#xD;&#xA;    uniform Texture2D				_ShadowTexture;&#xD;&#xA;    uniform SamplerComparisonState	sampler_ShadowTexture;&#xD;&#xA;    uniform Texture2D				u_PointSampler;&#xD;&#xA;    uniform SamplerState			sampleru_PointSampler;&#xD;&#xA;    &#xD;&#xA;    half4 coords = mul(_ShadowMatrix, float4(worldPos.xyz, 1.f));&#xD;&#xA;    float2 uv = coords.xy;&#xD;&#xA;    float zReceiver = coords.z;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;    float blockerSum = u_PointSampler.Sample(sampleru_PointSampler, float2(0, 0)).a;&#xD;&#xA;    float numBlockers = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; BLOCKER_SEARCH_NUM_SAMPLES; ++i)&#xD;&#xA;    {&#xD;&#xA;    	float shadowMapDepth = _ShadowTexture.Sample(sampleru_PointSampler, uv.xy + poissonDisk[i] * searchWidth).r;&#xD;&#xA;    	if (shadowMapDepth &lt; zReceiver)&#xD;&#xA;    	{&#xD;&#xA;    		blockerSum += shadowMapDepth;&#xD;&#xA;    		numBlockers++;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    float avgBlockerDepth = blockerSum / numBlockers;&#xD;&#xA;    return avgBlockerDepth;&#xD;&#xA;&#xD;&#xA;Here is an example of my issue. As you can see on the right the shadowing seems correct but if you move the cylinder, you can see on the left, the penumbra is not computed correctly.&#xD;&#xA;&#xD;&#xA;[![pcss][2]][2]&#xD;&#xA;&#xD;&#xA;As I said I don't know what I am doing wrong, I suppose that this comes from the matrix or maybe the depth but there might be some other problems.&#xD;&#xA;&#xD;&#xA;Any help is welcome, Thanks !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/uBosM.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9870" PostHistoryTypeId="1" PostId="4377" RevisionGUID="490022e0-b359-431a-91ae-a41b86f1e101" CreationDate="2016-12-12T14:51:30.703" UserId="2372" Text="Percentage-closer Soft Shadows implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="9871" PostHistoryTypeId="3" PostId="4377" RevisionGUID="490022e0-b359-431a-91ae-a41b86f1e101" CreationDate="2016-12-12T14:51:30.703" UserId="2372" Text="|rendering|shader|lighting|shadow|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9872" PostHistoryTypeId="2" PostId="4378" RevisionGUID="879f5a77-8f92-436d-8591-6adf6442b282" CreationDate="2016-12-13T01:16:36.967" UserId="5661" Text="I attempted to implement font rendering using signed distance fields.&#xD;&#xA;&#xD;&#xA;My program first generates a mono bitmap at font size 64 (using FreeType), then generates an SDF from the bitmap. This is then uploaded into a texture atlas.&#xD;&#xA;&#xD;&#xA;The results are not very nice and look nothing like the various papers show:&#xD;&#xA;&#xD;&#xA;[![Generated letter capital X][1]][1]&#xD;&#xA;&#xD;&#xA;My guess is that the bitmap does not have a high enough resolution, but&#xD;&#xA;I do not necessarily want to generate SDF's larger than 64px (they have to fit in the atlas). Besides, at 256px, the generated sdf still has artifacts, albeit less noticable unless blown up.&#xD;&#xA;&#xD;&#xA;So how can I get better results / how am I applying the algorithm wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WGKeI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9873" PostHistoryTypeId="1" PostId="4378" RevisionGUID="879f5a77-8f92-436d-8591-6adf6442b282" CreationDate="2016-12-13T01:16:36.967" UserId="5661" Text="Signed distance field font looks odd" ContentLicense="CC BY-SA 3.0" />
  <row Id="9874" PostHistoryTypeId="3" PostId="4378" RevisionGUID="879f5a77-8f92-436d-8591-6adf6442b282" CreationDate="2016-12-13T01:16:36.967" UserId="5661" Text="|opengl|signed-distance-field|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9876" PostHistoryTypeId="2" PostId="4379" RevisionGUID="9d1cd9a1-01b7-46b9-a880-65434e81cfaa" CreationDate="2016-12-13T04:35:14.420" UserId="5664" Text="I would just like to know why are there so many things defined as macros that point to memory addresses in OpenGL? &#xD;&#xA;&#xD;&#xA;I see them all over the place. For example when I go to choose parameters for a function such as glDrawArrays(), I have to choose a mode like GL_TRIANGLES as the first parameter which is a macro like all the others. " ContentLicense="CC BY-SA 3.0" />
  <row Id="9877" PostHistoryTypeId="1" PostId="4379" RevisionGUID="9d1cd9a1-01b7-46b9-a880-65434e81cfaa" CreationDate="2016-12-13T04:35:14.420" UserId="5664" Text="Why is there so many macros in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9878" PostHistoryTypeId="3" PostId="4379" RevisionGUID="9d1cd9a1-01b7-46b9-a880-65434e81cfaa" CreationDate="2016-12-13T04:35:14.420" UserId="5664" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9879" PostHistoryTypeId="2" PostId="4380" RevisionGUID="f111816c-197f-4639-af1e-28775777ea62" CreationDate="2016-12-13T08:28:47.280" UserId="2041" Text="These aren't macros pointing to memory addresses. They're just integer preprocessor constants. Back in the days when OpenGL originated, using preprocessor constants for your numeric constants was common practice in C.&#xD;&#xA;&#xD;&#xA;Nowadays it's considered better practice to define new types (single-element structs) for your constants, but it's too late to change OpenGL." ContentLicense="CC BY-SA 3.0" />
  <row Id="9880" PostHistoryTypeId="5" PostId="4363" RevisionGUID="61c7558e-670f-400a-8782-a4a56291b850" CreationDate="2016-12-13T09:11:34.577" UserId="2485" Comment="Tried new things and added results to question." Text="I am trying to implement [Blades of Waving Grass][1] and I am still stuck at the point where I need to achieve texture arrangements like in the figure below (the first one).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So my plan is to draw the first texture, then draw the second and rotate it by 30°, then another and rotate it by 60° etc. Drawing the first texture is not a problem but I have some issues rotating the second one. I would expect it to look something like this (view from above):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Instead the actual result looks something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I suspect that this deviation occurs due to the object being rotated around the world-space axes and not around its own.&#xD;&#xA;&#xD;&#xA;Vertex and position data:&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    	-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;    	0.5f, -0.5f, -0.5f, 1.0f, 0.0f,&#xD;&#xA;    	0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;    	0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;    	-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,&#xD;&#xA;    	-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    glm::vec3 texturePositions[] = {&#xD;&#xA;    	glm::vec3(0.0f, 0.0f, 0.0f),&#xD;&#xA;        glm::vec3(0.0f, 0.0f, 0.0f)&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Camera/View transformations:&#xD;&#xA;&#xD;&#xA;		// Camera/View transformation&#xD;&#xA;		glm::mat4 view;&#xD;&#xA;		view = camera.GetViewMatrix();&#xD;&#xA;		// Projection&#xD;&#xA;		glm::mat4 projection;&#xD;&#xA;		projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 1000.0f);&#xD;&#xA;		// Get the uniform locations&#xD;&#xA;		GLint modelLoc = glGetUniformLocation(ourShader.Program, &quot;model&quot;);&#xD;&#xA;		GLint viewLoc = glGetUniformLocation(ourShader.Program, &quot;view&quot;);&#xD;&#xA;		GLint projectionLoc = glGetUniformLocation(ourShader.Program, &quot;projection&quot;);&#xD;&#xA;		// Pass the matrices to the shader&#xD;&#xA;		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));&#xD;&#xA;		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;&#xD;&#xA;Drawing the first two textures:&#xD;&#xA;&#xD;&#xA;			//Texture 1&#xD;&#xA;			glm::mat4 model;&#xD;&#xA;			model = glm::translate(model, texturePositions[0]);			&#xD;&#xA;			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;			//Texture 2&#xD;&#xA;			GLfloat angle = glm::radians(30.0f);&#xD;&#xA;			model = glm::translate(model, texturePositions[1]);&#xD;&#xA;			model = glm::rotate(model, angle, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;Online search showed that this might have several reasons:&#xD;&#xA;&#xD;&#xA; 1. Order of the applied transformations are crucial&#xD;&#xA; 2. One solution might be to first move the &quot;object&quot; until its center&#xD;&#xA;    matches the world-space origin, apply the rotation and then move it&#xD;&#xA;    to the desired position.&#xD;&#xA;&#xD;&#xA;As I am still in the very early learning process so I am kind of clueless here.&#xD;&#xA;&#xD;&#xA; 1. I think that the order of transformations for the second texture is fine in my code, isn't it?&#xD;&#xA; 2. Also how would I determine the right position for the object where&#xD;&#xA;    the rotation would be applied correctly? (see above point 2)&#xD;&#xA; 3. Might it be more efficient to apply the rotation in the objects&#xD;&#xA;    local space? Is that possible in my case?&#xD;&#xA;&#xD;&#xA;I do not expect anybody to write code for me (though some snippet would be nice) but I would appreciate some hints or somebody pointing me in the right direction. I think that I have a basic fallacy here.&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA; 1. If I change the rotation axis from `y` to `z` the object rotates&#xD;&#xA;    around its own center just like expected.&#xD;&#xA; 2. I also tried to apply the following solutions (taken from [here][5]&#xD;&#xA;    and [here][6]) where I moved the object to `glm::vec3(-x,-y,-z)`&#xD;&#xA;    rotate it and then moving it back to `glm::vec3(x,y,z)`,&#xD;&#xA;    unfortunately with no success. Which makes sence as the position&#xD;&#xA;    vector is set to (0,0,0) anyway. I also tried to change thisposition&#xD;&#xA;    to something else than the origin also with no success.&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems/gpugems_ch07.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/QVbKy.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/7xhvk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7qQrc.png&#xD;&#xA;  [5]: http://gamedev.stackexchange.com/questions/18854/rotating-an-object-in-opengl-about-its-centre&#xD;&#xA;  [6]: https://www.opengl.org/discussion_boards/showthread.php/169200-Rotating-an-Object-around-its-center" ContentLicense="CC BY-SA 3.0" />
  <row Id="9881" PostHistoryTypeId="2" PostId="4381" RevisionGUID="862b889d-d2b1-4c43-ae0a-afdb6de2a340" CreationDate="2016-12-13T14:55:05.223" UserId="5633" Text="I have a polygonal mesh with ngons in it. I want to make a tessellation shader to which I send only the regular quads in such a way that it can construct a B-Spline surfaces across it. I came across the useful [tutorial](http://prideout.net/blog/?tag=tessellation-shaders), but I do not completely understand it, and my problem is slightly more general in that it contains irregular polygons and vertices. In the mesh I am looking for regular quads, i.e., quads for which all vertices have valency 4. They look like this&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;         |    |&#xD;&#xA;      ___|____|___&#xD;&#xA;         |    |&#xD;&#xA;      ___|____|___&#xD;&#xA;         |    |&#xD;&#xA;         |    |&#xD;&#xA;It is the inner face that I want the tessellation shader to divide up and then smooth using B-spline method. However, for the B-spline method I need  16 points, So I must subdivide the inner face like this&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     ______         .  .  .  .&#xD;&#xA;    |      |        .  .  .  .&#xD;&#xA;    |      |   --&gt;  .  .  .  .&#xD;&#xA;    |______|        .  .  .  .&#xD;&#xA;&#xD;&#xA;I am lost on how to find these points, I can of course just use averaging to get these points but then there will be no smoothing happening. The subdivision rules I normally use are all binary, that is, they split edges into two edges, but this can not produce such a set of control points. &#xD;&#xA;&#xD;&#xA;How do I proceed from here? Should I just resort to using quadratic B-splines, and use the top diagram to find approximations of the half way points and send those to the shader? Another issue is that adjacent faces of regular quads may very well be triangles or pentagons etc. So it is difficult to find the points I need for the tessellation shader to perform B-spline smoothing.&#xD;&#xA;&#xD;&#xA;Thanks for any tips,&#xD;&#xA;if anyone would like some more clarification about the problem please ask, I realize that the question might be vague.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9882" PostHistoryTypeId="1" PostId="4381" RevisionGUID="862b889d-d2b1-4c43-ae0a-afdb6de2a340" CreationDate="2016-12-13T14:55:05.223" UserId="5633" Text="B-Spline patches on the tessellation shader. How to get the control points" ContentLicense="CC BY-SA 3.0" />
  <row Id="9883" PostHistoryTypeId="3" PostId="4381" RevisionGUID="862b889d-d2b1-4c43-ae0a-afdb6de2a340" CreationDate="2016-12-13T14:55:05.223" UserId="5633" Text="|shader|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9884" PostHistoryTypeId="2" PostId="4382" RevisionGUID="7bae47b1-4734-40ab-8f5d-9c508d9df9a6" CreationDate="2016-12-13T15:37:01.320" UserId="5055" Text="Am I right if I understand&#xD;&#xA;&#xD;&#xA;&gt;     GLfloat vertices[] = {&#xD;&#xA;&gt;         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;&gt;         0.5f, -0.5f, -0.5f, 1.0f, 0.0f,&#xD;&#xA;&gt;         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;&gt;         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;&gt;         -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,&#xD;&#xA;&gt;         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;&gt;     };&#xD;&#xA;&#xD;&#xA;as being: &#xD;&#xA;&#xD;&#xA;&gt; x, y, z, texX, texY&#xD;&#xA;&#xD;&#xA; for 6 vertices in total?&#xD;&#xA;&#xD;&#xA;If so, then it seems like you do not use indexing yet (vertices 3 and 4 are the same), but nevermind.&#xD;&#xA;&#xD;&#xA;Not being sure what order your coordinate system is in, the plane you are constructing here is perpendicular to an axis, but does not go through your origin. &#xD;&#xA;&#xD;&#xA;An object that gets rotated my a rotation-matrix rotates around its origin. The origin of your model matrix is (0,0,0), but this is **not** the center of your object. &#xD;&#xA;&#xD;&#xA;In a right hand coordinate system, the following vertices give you a plane that is standing on the x-z-plane (perpendicular to it) and goes through your origin. Rotating that around y should rotate it like you wish to do:&#xD;&#xA;&#xD;&#xA;     GLfloat vertices[] = {&#xD;&#xA;         -0.5f, 0.0f, 0.0f, 0.0f, 0.0f,&#xD;&#xA;         0.5f, 0.0f, 0.0f, 1.0f, 0.0f,&#xD;&#xA;         0.5f, 1.0f, 0.0f, 1.0f, 1.0f,&#xD;&#xA;         0.5f, 1.0f, 0.0f, 1.0f, 1.0f,&#xD;&#xA;         -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,&#xD;&#xA;         -0.5f, 0.0f, 0.0f, 0.0f, 0.0f,&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;Notice the third value for each vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="9885" PostHistoryTypeId="5" PostId="4382" RevisionGUID="825e83f1-dc87-4473-9628-1a81fe2f336e" CreationDate="2016-12-13T17:26:43.167" UserId="231" Comment="Minor tidying" Text="Am I right if I understand&#xD;&#xA;&#xD;&#xA;&gt;     GLfloat vertices[] = {&#xD;&#xA;&gt;         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;&gt;         0.5f, -0.5f, -0.5f, 1.0f, 0.0f,&#xD;&#xA;&gt;         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;&gt;         0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;&gt;         -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,&#xD;&#xA;&gt;         -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;&gt;     };&#xD;&#xA;&#xD;&#xA;as being: &#xD;&#xA;&#xD;&#xA;&gt; x, y, z, texX, texY&#xD;&#xA;&#xD;&#xA;for 6 vertices in total?&#xD;&#xA;&#xD;&#xA;If so, then it seems like you do not use indexing yet (vertices 3 and 4 are the same), but nevermind.&#xD;&#xA;&#xD;&#xA;Not being sure what order your coordinate system is in, the plane you are constructing here is perpendicular to an axis, but does not go through your origin. &#xD;&#xA;&#xD;&#xA;An object that gets rotated by a rotation matrix rotates around its origin. The origin of your model matrix is (0, 0, 0), but this is **not** the center of your object. &#xD;&#xA;&#xD;&#xA;In a right handed coordinate system, the following vertices give you a plane that is standing on the x-z-plane (perpendicular to it) and goes through your origin. Rotating that around y should rotate it like you wish to do:&#xD;&#xA;&#xD;&#xA;     GLfloat vertices[] = {&#xD;&#xA;         -0.5f, 0.0f, 0.0f, 0.0f, 0.0f,&#xD;&#xA;         0.5f, 0.0f, 0.0f, 1.0f, 0.0f,&#xD;&#xA;         0.5f, 1.0f, 0.0f, 1.0f, 1.0f,&#xD;&#xA;         0.5f, 1.0f, 0.0f, 1.0f, 1.0f,&#xD;&#xA;         -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,&#xD;&#xA;         -0.5f, 0.0f, 0.0f, 0.0f, 0.0f,&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;Notice the third value for each vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="9886" PostHistoryTypeId="2" PostId="4383" RevisionGUID="52e08995-b00a-4ea1-8e03-b6c239157986" CreationDate="2016-12-13T18:10:32.850" UserId="48" Text="Hmm, that SDF doesn't look right. It should be much smoother, like this image for instance:&#xD;&#xA;&#xD;&#xA;![SDF example](https://farm3.staticflickr.com/2899/14414646376_03162c9141_o.png)&#xD;&#xA;&#xD;&#xA;(image from [this blog](https://www.mapbox.com/blog/text-signed-distance-fields/)).&#xD;&#xA;&#xD;&#xA;One possible issue I noticed in your description:&#xD;&#xA;&#xD;&#xA;&gt; My program first generates a mono bitmap at font size 64 (using FreeType), then generates an SDF from the bitmap.&#xD;&#xA;&#xD;&#xA;The initial text needs to be rendered at a _much higher_ resolution than the resulting SDF, so you can get subpixel precision in the distances stored in the SDF. For example, in the [original Valve paper](http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf), they render the initial mono bitmap at 4096×4096 in order to generate a 64×64 SDF from it." ContentLicense="CC BY-SA 3.0" />
  <row Id="9887" PostHistoryTypeId="2" PostId="4384" RevisionGUID="49e0fb3b-d2b6-4ec5-9235-130e3958f2e6" CreationDate="2016-12-13T18:29:07.240" UserId="48" Text="For regular quad faces, what you want to do is send the vertices for the quad you're evaluating _and_ the nine neighboring quads around it: a total of 16×16 vertices. The B-spline needs to know where the neighboring vertices are in order to generate a surface patch that connects smoothly to the neighboring patches.&#xD;&#xA;&#xD;&#xA;In the case that the adjacent faces aren't quads, I don't think you can use the straightforward B-spline evaluation. In Catmull-Clark subdivision, everything is quads after the first level of subdivision, though you'll still have extraordinary vertices to deal with." ContentLicense="CC BY-SA 3.0" />
  <row Id="9888" PostHistoryTypeId="2" PostId="4385" RevisionGUID="f795a227-1f54-4d70-8242-0760f9723a52" CreationDate="2016-12-13T22:03:06.060" UserId="5670" Text="I am looking for people who are versed with Laplacian Smoothing of meshes and in particular have worked with the paper &quot;Improved Laplacian smoothing of noisy surface meshes&quot; by J. Vollmer in the early 2000's. If you are the right person please do get in touch with me and help me with my project [I will provide further details in due course].&#xD;&#xA;&#xD;&#xA;Many thanks, &#xD;&#xA;&#xD;&#xA;Jay" ContentLicense="CC BY-SA 3.0" />
  <row Id="9889" PostHistoryTypeId="1" PostId="4385" RevisionGUID="f795a227-1f54-4d70-8242-0760f9723a52" CreationDate="2016-12-13T22:03:06.060" UserId="5670" Text="Improved Laplacian smoothing of noisy surface meshes" ContentLicense="CC BY-SA 3.0" />
  <row Id="9890" PostHistoryTypeId="3" PostId="4385" RevisionGUID="f795a227-1f54-4d70-8242-0760f9723a52" CreationDate="2016-12-13T22:03:06.060" UserId="5670" Text="|3d|algorithm|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9891" PostHistoryTypeId="5" PostId="4384" RevisionGUID="ce8fd46b-7cfa-4e7c-a650-1f95358efd62" CreationDate="2016-12-13T22:57:55.797" UserId="48" Comment="fix a mistake" Text="For regular quad faces, what you want to do is send the vertices for the quad you're evaluating _and_ the eight neighboring quads around it: a total of 16×16 vertices. The B-spline needs to know where the neighboring vertices are in order to generate a surface patch that connects smoothly to the neighboring patches.&#xD;&#xA;&#xD;&#xA;In the case that the adjacent faces aren't quads, I don't think you can use the straightforward B-spline evaluation. In Catmull-Clark subdivision, everything is quads after the first level of subdivision, though you'll still have extraordinary vertices to deal with." ContentLicense="CC BY-SA 3.0" />
  <row Id="9892" PostHistoryTypeId="10" PostId="4385" RevisionGUID="797c1105-cc83-4f9a-98a5-8448450df6e6" CreationDate="2016-12-14T01:14:51.490" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="9893" PostHistoryTypeId="5" PostId="4384" RevisionGUID="1a35d0ab-1f08-4bdd-aa07-59f35ea9c103" CreationDate="2016-12-14T04:28:37.033" UserId="1952" Comment="deleted 2 characters in body" Text="For regular quad faces, what you want to do is send the vertices for the quad you're evaluating _and_ the eight neighboring quads around it: a total of 4x4 vertices. The B-spline needs to know where the neighboring vertices are in order to generate a surface patch that connects smoothly to the neighboring patches.&#xD;&#xA;&#xD;&#xA;In the case that the adjacent faces aren't quads, I don't think you can use the straightforward B-spline evaluation. In Catmull-Clark subdivision, everything is quads after the first level of subdivision, though you'll still have extraordinary vertices to deal with." ContentLicense="CC BY-SA 3.0" />
  <row Id="9895" PostHistoryTypeId="5" PostId="4377" RevisionGUID="77067e77-ed09-4215-ad5d-c66541b11797" CreationDate="2016-12-14T14:43:03.460" UserId="2372" Comment="added 1854 characters in body" Text="I am trying to implement the [Percentage-closer Soft Shadows][1] (PCSS) from NVidia inside Unity but I am facing some issue and I don't know where they come from and then, I do not know how to solve them...&#xD;&#xA;&#xD;&#xA;Here is my current setup.&#xD;&#xA;&#xD;&#xA;I using an orthographic camera to calculate my shadowmap here are the different steps and some pseudo-code.&#xD;&#xA;&#xD;&#xA;    // Setup camera&#xD;&#xA;    _shadowCamera.clearFlags = CameraClearFlags.Depth;&#xD;&#xA;    _shadowCamera.orthographic= true;&#xD;&#xA;    &#xD;&#xA;    // Setup a render texture to output the shadowmap from the camera&#xD;&#xA;    RenderTexture _shadowTexture = new RenderTexture((int)_shadowMapSize, _shadowMapSize, 16, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);&#xD;&#xA;    &#xD;&#xA;    // Render scene using a replacement shader. This is only used to output &#xD;&#xA;    _shadowCamera.SetReplacementShader(_shadowMapShader, &quot;RenderType&quot;);&#xD;&#xA;    _shadowCamera.Render();&#xD;&#xA;    &#xD;&#xA;    // Set the camera positions and matrix&#xD;&#xA;    _radius = _bounds;&#xD;&#xA;    Vector3 targetPos = _target.transform.position;&#xD;&#xA;    Vector3 lightDir = _light.transform.forward;&#xD;&#xA;    Quaternion lightRot = _light.transform.rotation;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.transform.position = targetPos - lightDir * _radius;&#xD;&#xA;    _shadowCamera.transform.rotation = lightRot;&#xD;&#xA;    _shadowCamera.orthographicSize = _radius;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.farClipPlane = _radius * 2.0f;&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowViewMatrix = _shadowCamera.worldToCameraMatrix;&#xD;&#xA;    Matrix4x4 shadowProjectionMatrix = GL.GetGPUProjectionMatrix(_shadowCamera.projectionMatrix, false);&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowBiasMatrix = Matrix4x4.identity;&#xD;&#xA;    shadowBiasMatrix.SetRow(0, new Vector4(0.5f, 0.0f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(1, new Vector4(0.0f, 0.5f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f));&#xD;&#xA;    shadowBiasMatrix.SetRow(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));&#xD;&#xA;    &#xD;&#xA;    _shadowMatrix = shadowBiasMatrix * shadowProjectionMatrix * shadowViewMatrix;&#xD;&#xA;&#xD;&#xA;    // Transfering data to shader&#xD;&#xA;    _material.SetMatrix(&quot;_ShadowMatrix&quot;, _shadowMatrix);&#xD;&#xA;    _material.SetTexture(&quot;_ShadowTexture&quot;, _shadowTexture);&#xD;&#xA;    _material.SetTexture(&quot;u_PointSampler&quot;, _pointSampler);&#xD;&#xA;    _material.SetFloat(&quot;u_NearPlane&quot;, _shadowCamera.nearClipPlane);&#xD;&#xA;    _material.SetFloat(&quot;u_LightWorldSize&quot;, _lightWorldSize);&#xD;&#xA;    _material.SetFloat(&quot;u_LightFrustrumWidth&quot;, _lightFrustrumWidth);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In my shader, I am simply doing the blocker search part and here is also some pseudo-code.&#xD;&#xA;&#xD;&#xA;    #define BLOCKER_SEARCH_NUM_SAMPLES 16&#xD;&#xA;    #define NEAR_PLANE u_NearPlane&#xD;&#xA;    #define LIGHT_WORLD_SIZE u_LightWorldSize&#xD;&#xA;    #define LIGHT_FRUSTUM_WIDTH u_LightFrustrumWidth&#xD;&#xA;    #define LIGHT_SIZE_UV (LIGHT_WORLD_SIZE / LIGHT_FRUSTUM_WIDTH) &#xD;&#xA;    &#xD;&#xA;    uniform Texture2D				_ShadowTexture;&#xD;&#xA;    uniform SamplerComparisonState	sampler_ShadowTexture;&#xD;&#xA;    uniform Texture2D				u_PointSampler;&#xD;&#xA;    uniform SamplerState			sampleru_PointSampler;&#xD;&#xA;    &#xD;&#xA;    half4 coords = mul(_ShadowMatrix, float4(worldPos.xyz, 1.f));&#xD;&#xA;    float2 uv = coords.xy;&#xD;&#xA;    float zReceiver = coords.z;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;    float blockerSum = u_PointSampler.Sample(sampleru_PointSampler, float2(0, 0)).a;&#xD;&#xA;    float numBlockers = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; BLOCKER_SEARCH_NUM_SAMPLES; ++i)&#xD;&#xA;    {&#xD;&#xA;    	float shadowMapDepth = _ShadowTexture.Sample(sampleru_PointSampler, uv.xy + poissonDisk[i] * searchWidth).r;&#xD;&#xA;    	if (shadowMapDepth &lt; zReceiver)&#xD;&#xA;    	{&#xD;&#xA;    		blockerSum += shadowMapDepth;&#xD;&#xA;    		numBlockers++;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    float avgBlockerDepth = blockerSum / numBlockers;&#xD;&#xA;    return avgBlockerDepth;&#xD;&#xA;&#xD;&#xA;Here is an example of my issue. As you can see on the right the shadowing seems correct but if you move the cylinder, you can see on the left, the penumbra is not computed correctly.&#xD;&#xA;&#xD;&#xA;[![pcss][2]][2]&#xD;&#xA;&#xD;&#xA;As I said I don't know what I am doing wrong, I suppose that this comes from the matrix or maybe the depth but there might be some other problems.&#xD;&#xA;&#xD;&#xA;Any help is welcome, Thanks !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**====== ADDITIONAL INFORMATIONS ======**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've rebuilt my system and I better understand the whole thing and I also think that I know where the issue comes from.&#xD;&#xA;&#xD;&#xA;Let's focus on the near plane value, the shadow map and the zReceiver which is the z projection coordinate.&#xD;&#xA;&#xD;&#xA;The shadow map and the zReceiver are calculated within the light view space as you can see in the following screenshot.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now let's see how the searchWidth is calculated and some screenshots with different NEAR_PLANE values.&#xD;&#xA;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;&#xD;&#xA;In those examples only the NEAR_PLANE value is change and the camera near place remains to 0.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As you can see with a NEAR_PLANE value of zero the searchWidth doesn't varies compared to other values. But I think that other value are wrong and doesn't behave right as I am using a directional light. To try fixing this I only used the zReceiver without taking in account the NEAR_PLANE value and the results are not good.&#xD;&#xA;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * zReceiver;&#xD;&#xA;&#xD;&#xA;As you can see in the following screenshots, in the red circles as you move the object far according to the shadow map the width gets bigger and it shouldn't.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The correct behaviour is that the searchWidth shouldn't be affected by the object position in the shadow map but more of its height. Hope it makes sens.&#xD;&#xA;&#xD;&#xA;I would like know how could I calculate the seachWidth as it seems that my problem comes from its calculation. Maybe the issue comes from the shadowmap of the zReceiver but I have some doubts about it.&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/uBosM.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/8KSCZ.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/pC0lH.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/HniVt.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9897" PostHistoryTypeId="5" PostId="4377" RevisionGUID="e0d6eec5-4fc5-44ac-bba5-178dce630b71" CreationDate="2016-12-14T15:06:13.113" UserId="2372" Comment="added 117 characters in body" Text="I am trying to implement the [Percentage-closer Soft Shadows][1] (PCSS) from NVidia inside Unity but I am facing some issue and I don't know where they come from and then, I do not know how to solve them...&#xD;&#xA;&#xD;&#xA;Here is my current setup.&#xD;&#xA;&#xD;&#xA;I using an orthographic camera to calculate my shadowmap here are the different steps and some pseudo-code.&#xD;&#xA;&#xD;&#xA;    // Setup camera&#xD;&#xA;    _shadowCamera.clearFlags = CameraClearFlags.Depth;&#xD;&#xA;    _shadowCamera.orthographic= true;&#xD;&#xA;    &#xD;&#xA;    // Setup a render texture to output the shadowmap from the camera&#xD;&#xA;    RenderTexture _shadowTexture = new RenderTexture((int)_shadowMapSize, _shadowMapSize, 16, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);&#xD;&#xA;    &#xD;&#xA;    // Render scene using a replacement shader. This is only used to output &#xD;&#xA;    _shadowCamera.SetReplacementShader(_shadowMapShader, &quot;RenderType&quot;);&#xD;&#xA;    _shadowCamera.Render();&#xD;&#xA;    &#xD;&#xA;    // Set the camera positions and matrix&#xD;&#xA;    _radius = _bounds;&#xD;&#xA;    Vector3 targetPos = _target.transform.position;&#xD;&#xA;    Vector3 lightDir = _light.transform.forward;&#xD;&#xA;    Quaternion lightRot = _light.transform.rotation;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.transform.position = targetPos - lightDir * _radius;&#xD;&#xA;    _shadowCamera.transform.rotation = lightRot;&#xD;&#xA;    _shadowCamera.orthographicSize = _radius;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.farClipPlane = _radius * 2.0f;&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowViewMatrix = _shadowCamera.worldToCameraMatrix;&#xD;&#xA;    Matrix4x4 shadowProjectionMatrix = GL.GetGPUProjectionMatrix(_shadowCamera.projectionMatrix, false);&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowBiasMatrix = Matrix4x4.identity;&#xD;&#xA;    shadowBiasMatrix.SetRow(0, new Vector4(0.5f, 0.0f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(1, new Vector4(0.0f, 0.5f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f));&#xD;&#xA;    shadowBiasMatrix.SetRow(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));&#xD;&#xA;    &#xD;&#xA;    _shadowMatrix = shadowBiasMatrix * shadowProjectionMatrix * shadowViewMatrix;&#xD;&#xA;&#xD;&#xA;    // Transfering data to shader&#xD;&#xA;    _material.SetMatrix(&quot;_ShadowMatrix&quot;, _shadowMatrix);&#xD;&#xA;    _material.SetTexture(&quot;_ShadowTexture&quot;, _shadowTexture);&#xD;&#xA;    _material.SetTexture(&quot;u_PointSampler&quot;, _pointSampler);&#xD;&#xA;    _material.SetFloat(&quot;u_NearPlane&quot;, _shadowCamera.nearClipPlane);&#xD;&#xA;    _material.SetFloat(&quot;u_LightWorldSize&quot;, _lightWorldSize);&#xD;&#xA;    _material.SetFloat(&quot;u_LightFrustrumWidth&quot;, _lightFrustrumWidth);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In my shader, I am simply doing the blocker search part and here is also some pseudo-code.&#xD;&#xA;&#xD;&#xA;    #define BLOCKER_SEARCH_NUM_SAMPLES 16&#xD;&#xA;    #define NEAR_PLANE u_NearPlane&#xD;&#xA;    #define LIGHT_WORLD_SIZE u_LightWorldSize&#xD;&#xA;    #define LIGHT_FRUSTUM_WIDTH u_LightFrustrumWidth&#xD;&#xA;    #define LIGHT_SIZE_UV (LIGHT_WORLD_SIZE / LIGHT_FRUSTUM_WIDTH) &#xD;&#xA;    &#xD;&#xA;    uniform Texture2D				_ShadowTexture;&#xD;&#xA;    uniform SamplerComparisonState	sampler_ShadowTexture;&#xD;&#xA;    uniform Texture2D				u_PointSampler;&#xD;&#xA;    uniform SamplerState			sampleru_PointSampler;&#xD;&#xA;    &#xD;&#xA;    half4 coords = mul(_ShadowMatrix, float4(worldPos.xyz, 1.f));&#xD;&#xA;    float2 uv = coords.xy;&#xD;&#xA;    float zReceiver = coords.z;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;    float blockerSum = u_PointSampler.Sample(sampleru_PointSampler, float2(0, 0)).a;&#xD;&#xA;    float numBlockers = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; BLOCKER_SEARCH_NUM_SAMPLES; ++i)&#xD;&#xA;    {&#xD;&#xA;    	float shadowMapDepth = _ShadowTexture.Sample(sampleru_PointSampler, uv.xy + poissonDisk[i] * searchWidth).r;&#xD;&#xA;    	if (shadowMapDepth &lt; zReceiver)&#xD;&#xA;    	{&#xD;&#xA;    		blockerSum += shadowMapDepth;&#xD;&#xA;    		numBlockers++;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    float avgBlockerDepth = blockerSum / numBlockers;&#xD;&#xA;    return avgBlockerDepth;&#xD;&#xA;&#xD;&#xA;Here is an example of my issue. As you can see on the right the shadowing seems correct but if you move the cylinder, you can see on the left, the penumbra is not computed correctly.&#xD;&#xA;&#xD;&#xA;[![pcss][2]][2]&#xD;&#xA;&#xD;&#xA;As I said I don't know what I am doing wrong, I suppose that this comes from the matrix or maybe the depth but there might be some other problems.&#xD;&#xA;&#xD;&#xA;Any help is welcome, Thanks !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**====== ADDITIONAL INFORMATIONS ======**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've rebuilt my system and I better understand the whole thing and I also think that I know where the issue comes from.&#xD;&#xA;&#xD;&#xA;Let's focus on the near plane value, the shadow map and the zReceiver which is the z projection coordinate.&#xD;&#xA;&#xD;&#xA;The shadow map and the zReceiver are calculated within the light view space as you can see in the following screenshot.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now let's see how the searchWidth is calculated and some screenshots with different NEAR_PLANE values.&#xD;&#xA;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;&#xD;&#xA;In those examples only the NEAR_PLANE value is changed and the camera near plane remains to 0.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As you can see with a NEAR_PLANE value of zero the searchWidth doesn't varies compared to other values. But I think that other values are wrong and doesn't behave right as I am using a directional light. Indeed, the penumbra should not be affected by the distance from the object to the light. To try fixing this, I only used the zReceiver without taking in account the NEAR_PLANE value and the results are not good.&#xD;&#xA;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * zReceiver;&#xD;&#xA;&#xD;&#xA;As you can see in the following screenshots, in the red circles as you move the object far according to the shadow map, the width gets bigger and it shouldn't.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The correct behaviour is that the searchWidth shouldn't be affected by the object position in the shadow map but more by its height. I think that this should makes sense.&#xD;&#xA;&#xD;&#xA;I would like know how could I calculate the seachWidth as it seems that my problem comes from its calculation. Maybe the issue also comes from the shadowmap or the zReceiver but I have some doubts about it.&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/uBosM.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/8KSCZ.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/pC0lH.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/HniVt.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9898" PostHistoryTypeId="5" PostId="4377" RevisionGUID="28380e1d-4b04-44da-921e-61939931e42a" CreationDate="2016-12-14T15:21:51.963" UserId="231" Comment="Point to correct image (one was duplicated resulting in one being missing)" Text="I am trying to implement the [Percentage-closer Soft Shadows][1] (PCSS) from NVidia inside Unity but I am facing some issue and I don't know where they come from and then, I do not know how to solve them...&#xD;&#xA;&#xD;&#xA;Here is my current setup.&#xD;&#xA;&#xD;&#xA;I am using an orthographic camera to calculate my shadowmap. Here are the different steps and some pseudo-code.&#xD;&#xA;&#xD;&#xA;    // Setup camera&#xD;&#xA;    _shadowCamera.clearFlags = CameraClearFlags.Depth;&#xD;&#xA;    _shadowCamera.orthographic= true;&#xD;&#xA;    &#xD;&#xA;    // Setup a render texture to output the shadowmap from the camera&#xD;&#xA;    RenderTexture _shadowTexture = new RenderTexture((int)_shadowMapSize, _shadowMapSize, 16, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);&#xD;&#xA;    &#xD;&#xA;    // Render scene using a replacement shader. This is only used to output &#xD;&#xA;    _shadowCamera.SetReplacementShader(_shadowMapShader, &quot;RenderType&quot;);&#xD;&#xA;    _shadowCamera.Render();&#xD;&#xA;    &#xD;&#xA;    // Set the camera positions and matrix&#xD;&#xA;    _radius = _bounds;&#xD;&#xA;    Vector3 targetPos = _target.transform.position;&#xD;&#xA;    Vector3 lightDir = _light.transform.forward;&#xD;&#xA;    Quaternion lightRot = _light.transform.rotation;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.transform.position = targetPos - lightDir * _radius;&#xD;&#xA;    _shadowCamera.transform.rotation = lightRot;&#xD;&#xA;    _shadowCamera.orthographicSize = _radius;&#xD;&#xA;    &#xD;&#xA;    _shadowCamera.farClipPlane = _radius * 2.0f;&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowViewMatrix = _shadowCamera.worldToCameraMatrix;&#xD;&#xA;    Matrix4x4 shadowProjectionMatrix = GL.GetGPUProjectionMatrix(_shadowCamera.projectionMatrix, false);&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 shadowBiasMatrix = Matrix4x4.identity;&#xD;&#xA;    shadowBiasMatrix.SetRow(0, new Vector4(0.5f, 0.0f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(1, new Vector4(0.0f, 0.5f, 0.0f, 0.5f));&#xD;&#xA;    shadowBiasMatrix.SetRow(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f));&#xD;&#xA;    shadowBiasMatrix.SetRow(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));&#xD;&#xA;    &#xD;&#xA;    _shadowMatrix = shadowBiasMatrix * shadowProjectionMatrix * shadowViewMatrix;&#xD;&#xA;&#xD;&#xA;    // Transfering data to shader&#xD;&#xA;    _material.SetMatrix(&quot;_ShadowMatrix&quot;, _shadowMatrix);&#xD;&#xA;    _material.SetTexture(&quot;_ShadowTexture&quot;, _shadowTexture);&#xD;&#xA;    _material.SetTexture(&quot;u_PointSampler&quot;, _pointSampler);&#xD;&#xA;    _material.SetFloat(&quot;u_NearPlane&quot;, _shadowCamera.nearClipPlane);&#xD;&#xA;    _material.SetFloat(&quot;u_LightWorldSize&quot;, _lightWorldSize);&#xD;&#xA;    _material.SetFloat(&quot;u_LightFrustrumWidth&quot;, _lightFrustrumWidth);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In my shader, I am simply doing the blocker search part and here is also some pseudo-code.&#xD;&#xA;&#xD;&#xA;    #define BLOCKER_SEARCH_NUM_SAMPLES 16&#xD;&#xA;    #define NEAR_PLANE u_NearPlane&#xD;&#xA;    #define LIGHT_WORLD_SIZE u_LightWorldSize&#xD;&#xA;    #define LIGHT_FRUSTUM_WIDTH u_LightFrustrumWidth&#xD;&#xA;    #define LIGHT_SIZE_UV (LIGHT_WORLD_SIZE / LIGHT_FRUSTUM_WIDTH) &#xD;&#xA;    &#xD;&#xA;    uniform Texture2D				_ShadowTexture;&#xD;&#xA;    uniform SamplerComparisonState	sampler_ShadowTexture;&#xD;&#xA;    uniform Texture2D				u_PointSampler;&#xD;&#xA;    uniform SamplerState			sampleru_PointSampler;&#xD;&#xA;    &#xD;&#xA;    half4 coords = mul(_ShadowMatrix, float4(worldPos.xyz, 1.f));&#xD;&#xA;    float2 uv = coords.xy;&#xD;&#xA;    float zReceiver = coords.z;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;    float blockerSum = u_PointSampler.Sample(sampleru_PointSampler, float2(0, 0)).a;&#xD;&#xA;    float numBlockers = 0;&#xD;&#xA;    &#xD;&#xA;    for (int i = 0; i &lt; BLOCKER_SEARCH_NUM_SAMPLES; ++i)&#xD;&#xA;    {&#xD;&#xA;    	float shadowMapDepth = _ShadowTexture.Sample(sampleru_PointSampler, uv.xy + poissonDisk[i] * searchWidth).r;&#xD;&#xA;    	if (shadowMapDepth &lt; zReceiver)&#xD;&#xA;    	{&#xD;&#xA;    		blockerSum += shadowMapDepth;&#xD;&#xA;    		numBlockers++;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    float avgBlockerDepth = blockerSum / numBlockers;&#xD;&#xA;    return avgBlockerDepth;&#xD;&#xA;&#xD;&#xA;Here is an example of my issue. As you can see on the right the shadowing seems correct but if you move the cylinder, you can see on the left, the penumbra is not computed correctly.&#xD;&#xA;&#xD;&#xA;[![pcss][2]][2]&#xD;&#xA;&#xD;&#xA;As I said I don't know what I am doing wrong, I suppose that this comes from the matrix or maybe the depth but there might be some other problems.&#xD;&#xA;&#xD;&#xA;# Additional information&#xD;&#xA;&#xD;&#xA;I've rebuilt my system and I better understand the whole thing and I also think that I know where the issue comes from.&#xD;&#xA;&#xD;&#xA;Let's focus on the near plane value, the shadow map and the zReceiver which is the z projection coordinate.&#xD;&#xA;&#xD;&#xA;The shadow map and the zReceiver are calculated within the light view space as you can see in the following screenshot.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now let's see how the searchWidth is calculated and some screenshots with different NEAR_PLANE values.&#xD;&#xA;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;&#xD;&#xA;&#xD;&#xA;In those examples only the NEAR_PLANE value is changed and the camera near plane remains to 0.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As you can see with a NEAR_PLANE value of zero the searchWidth doesn't vary compared to other values. But I think that other values are wrong and don't behave right as I am using a directional light. Indeed, the penumbra should not be affected by the distance from the object to the light. To try fixing this, I only used the zReceiver without taking in account the NEAR_PLANE value and the results are not good.&#xD;&#xA;&#xD;&#xA;    float searchWidth = LIGHT_SIZE_UV * zReceiver;&#xD;&#xA;&#xD;&#xA;As you can see in the following screenshots, in the red circles as you move the object far according to the shadow map, the width gets bigger and it shouldn't.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The correct behaviour is that the searchWidth shouldn't be affected by the object position in the shadow map but more by its height. I think that this should makes sense.&#xD;&#xA;&#xD;&#xA;I would like know how could I calculate the searchWidth as it seems that my problem comes from its calculation. Maybe the issue also comes from the shadowmap or the zReceiver but I have some doubts about it.&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/uBosM.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/8KSCZ.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/pC0lH.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/HniVt.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9903" PostHistoryTypeId="5" PostId="4385" RevisionGUID="e1c9bdd8-4e4b-47c7-92d4-166618dd284e" CreationDate="2016-12-14T18:40:09.160" UserId="56" Comment="deleted 82 characters in body" Text="I have a question regarding Laplacian Smoothing of meshes and in particular the paper &quot;Improved Laplacian smoothing of noisy surface meshes&quot; by J. Vollmer in the early 2000's.&#xD;&#xA;&#xD;&#xA;What is the reason of SHRINKAGE after Laplacian Smoothing on noisy surface meshes?&#xD;&#xA;&#xD;&#xA;Many thanks, &#xD;&#xA;&#xD;&#xA;Jay" ContentLicense="CC BY-SA 3.0" />
  <row Id="9905" PostHistoryTypeId="5" PostId="4385" RevisionGUID="eb198409-51ee-47c4-9035-12854e88e22c" CreationDate="2016-12-14T21:43:12.663" UserId="231" Comment="Tidying" Text="I have a question regarding Laplacian Smoothing of meshes and in particular the paper &quot;Improved Laplacian smoothing of noisy surface meshes&quot; by J. Vollmer in the early 2000's.&#xD;&#xA;&#xD;&#xA;What is the reason for *shrinkage* after Laplacian Smoothing on noisy surface meshes?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="9907" PostHistoryTypeId="2" PostId="4388" RevisionGUID="9af32ca2-b153-4a1c-8730-6e3d0fae5423" CreationDate="2016-12-14T23:58:54.283" UserId="4958" Text="This problem has been haunting me for some time but I was busy with other things. I can't finish my GI technique - specifically occlusion step without solving it.&#xD;&#xA;&#xD;&#xA;I made a binary scene voxelization in single pass. Result is stored in `RGBA32UI` 3D texture. It is three way so I set three ortho matrices each for X, Y, Z direction. These matrices are centered in camera position and form frustum in cube shape. And in geometry shader choose axis based on triangle normal.&#xD;&#xA;&#xD;&#xA;**First, what works - not binary voxelization** (but it's waste of VRAM).&#xD;&#xA;Here is fragment shader code of vexelization pass:&#xD;&#xA;&#xD;&#xA;    //gridDim - gridDimensions in voxels&#xD;&#xA;    ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    ivec3 texcoord[3];&#xD;&#xA;&#xD;&#xA;    //correction of texture coord based on chosen axis and ortho matrix &#xD;&#xA;    //(f_axis - 0, 1 or 2 from geometry shader)&#xD;&#xA;    texcoord[0] = temp;&#xD;&#xA;&#xD;&#xA;    texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;    texcoord[1].y = temp.z;&#xD;&#xA;    texcoord[1].z = temp.y;&#xD;&#xA;&#xD;&#xA;    texcoord[2].x = temp.z;&#xD;&#xA;    texcoord[2].y = temp.y;&#xD;&#xA;    texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;&#xD;&#xA;    imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Drawing pass is done using instancing with cubes. The voxels are quite big because more of them results in big framerate drop:&#xD;&#xA;&#xD;&#xA;    //vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel2 = texelFetch(geometryTexture, index, 0);&#xD;&#xA;    if(voxel2.r == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And it works:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But if I change it to binary version:**&#xD;&#xA;&#xD;&#xA;    //input - position 1-128, output: coded binary position as 1 in uvec4 format&#xD;&#xA;        uvec4 encodeBinaryVoxel(int position)&#xD;&#xA;        {&#xD;&#xA;            // check for positioning to R channel&#xD;&#xA;            position = max(position, 0);&#xD;&#xA;            uint voxelId1 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to G channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId2 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to B channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId3 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to A channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId4 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            return uvec4(voxelId1, voxelId2, voxelId3, voxelId4);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;        ivec3 texcoord[3];&#xD;&#xA;    &#xD;&#xA;        texcoord[0] = temp;&#xD;&#xA;    &#xD;&#xA;        texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;        texcoord[1].y = temp.z;&#xD;&#xA;        texcoord[1].z = temp.y;&#xD;&#xA;    &#xD;&#xA;        texcoord[2].x = temp.z;&#xD;&#xA;        texcoord[2].y = temp.y;&#xD;&#xA;        texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;    &#xD;&#xA;        //get z index of texture, each z slice has room for 128 bits (32*4)&#xD;&#xA;        int indexZ = texcoord[f_axis].z / 128; &#xD;&#xA;        //get position in slice&#xD;&#xA;        int bitZ = texcoord[f_axis].z % 128 + 1; &#xD;&#xA;        ivec3 index = ivec3(texcoord[f_axis].xy, indexZ);&#xD;&#xA;        uvec4 current = imageLoad(geometryGrid, index);&#xD;&#xA;        //encode position as binary uvec4&#xD;&#xA;        uvec4 bit = encodeBinaryVoxel(bitZ); &#xD;&#xA;        //or operation with stored value&#xD;&#xA;        imageStore(geometryGrid, index, bit | current); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And read:&#xD;&#xA;&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;    int indexZ = index.z / 128;&#xD;&#xA;    int bitZ = index.z % 128 + 1;&#xD;&#xA;    uvec4 binZ = encodeBinaryVoxel(bitZ);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel = texelFetch(geometryTexture, ivec3(index.xy, indexZ), 0);&#xD;&#xA;    uvec4 occupy = binZ &amp; voxel;&#xD;&#xA;    if((occupy.r | occupy.g | occupy.b | occupy.a) == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you see in binary version it flickers and I have failed to find out logic behind this (yet). However voxel position seem to be fine. I can render these voxels also by raymarching through texture but this flickers too.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bQmhv.png&#xD;&#xA;[2]: https://i.stack.imgur.com/bQmhvm.png&#xD;&#xA;[3]:http://i65.tinypic.com/2e6g12b.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9908" PostHistoryTypeId="1" PostId="4388" RevisionGUID="9af32ca2-b153-4a1c-8730-6e3d0fae5423" CreationDate="2016-12-14T23:58:54.283" UserId="4958" Text="Binary scene voxelization using imageStore - problem" ContentLicense="CC BY-SA 3.0" />
  <row Id="9909" PostHistoryTypeId="3" PostId="4388" RevisionGUID="9af32ca2-b153-4a1c-8730-6e3d0fae5423" CreationDate="2016-12-14T23:58:54.283" UserId="4958" Text="|opengl|rendering|glsl|3dtexture|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9910" PostHistoryTypeId="5" PostId="4388" RevisionGUID="2988c2db-ec3d-421b-8393-186922ebbf36" CreationDate="2016-12-15T00:04:35.597" UserId="4958" Comment="added 1 character in body" Text="This problem has been haunting me for some time but I was busy with other things. I can't finish my GI technique - specifically occlusion step without solving it.&#xD;&#xA;&#xD;&#xA;I made a binary scene voxelization in single pass. Result is stored in `RGBA32UI` 3D texture. It is three way so I set three ortho matrices each for X, Y, Z direction. These matrices are centered in camera position and form frustum in cube shape. And in geometry shader choose axis based on triangle normal.&#xD;&#xA;&#xD;&#xA;**First, what works - not binary voxelization** (but it's waste of VRAM).&#xD;&#xA;Here is fragment shader code of vexelization pass:&#xD;&#xA;&#xD;&#xA;    //gridDim - gridDimensions in voxels&#xD;&#xA;    ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    ivec3 texcoord[3];&#xD;&#xA;&#xD;&#xA;    //correction of texture coord based on chosen axis and ortho matrix &#xD;&#xA;    //(f_axis - 0, 1 or 2 from geometry shader)&#xD;&#xA;    texcoord[0] = temp;&#xD;&#xA;&#xD;&#xA;    texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;    texcoord[1].y = temp.z;&#xD;&#xA;    texcoord[1].z = temp.y;&#xD;&#xA;&#xD;&#xA;    texcoord[2].x = temp.z;&#xD;&#xA;    texcoord[2].y = temp.y;&#xD;&#xA;    texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;&#xD;&#xA;    imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Drawing pass is done using instancing with cubes. The voxels are quite big because more of them results in big framerate drop:&#xD;&#xA;&#xD;&#xA;    //vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel2 = texelFetch(geometryTexture, index, 0);&#xD;&#xA;    if(voxel2.r == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And it works:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But if I change it to binary version:**&#xD;&#xA;&#xD;&#xA;    //input - position 1-128, output: coded binary position as 1 in uvec4 format&#xD;&#xA;        uvec4 encodeBinaryVoxel(int position)&#xD;&#xA;        {&#xD;&#xA;            // check for positioning to R channel&#xD;&#xA;            position = max(position, 0);&#xD;&#xA;            uint voxelId1 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to G channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId2 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to B channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId3 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to A channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId4 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            return uvec4(voxelId1, voxelId2, voxelId3, voxelId4);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;        ivec3 texcoord[3];&#xD;&#xA;    &#xD;&#xA;        texcoord[0] = temp;&#xD;&#xA;    &#xD;&#xA;        texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;        texcoord[1].y = temp.z;&#xD;&#xA;        texcoord[1].z = temp.y;&#xD;&#xA;    &#xD;&#xA;        texcoord[2].x = temp.z;&#xD;&#xA;        texcoord[2].y = temp.y;&#xD;&#xA;        texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;    &#xD;&#xA;        //get z index of texture, each z slice has room for 128 bits (32*4)&#xD;&#xA;        int indexZ = texcoord[f_axis].z / 128; &#xD;&#xA;        //get position in slice&#xD;&#xA;        int bitZ = texcoord[f_axis].z % 128 + 1; &#xD;&#xA;        ivec3 index = ivec3(texcoord[f_axis].xy, indexZ);&#xD;&#xA;        uvec4 current = imageLoad(geometryGrid, index);&#xD;&#xA;        //encode position as binary uvec4&#xD;&#xA;        uvec4 bit = encodeBinaryVoxel(bitZ); &#xD;&#xA;        //or operation with stored value&#xD;&#xA;        imageStore(geometryGrid, index, bit | current); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And read:&#xD;&#xA;&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;    int indexZ = index.z / 128;&#xD;&#xA;    int bitZ = index.z % 128 + 1;&#xD;&#xA;    uvec4 binZ = encodeBinaryVoxel(bitZ);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel = texelFetch(geometryTexture, ivec3(index.xy, indexZ), 0);&#xD;&#xA;    uvec4 occupy = binZ &amp; voxel;&#xD;&#xA;    if((occupy.r | occupy.g | occupy.b | occupy.a) == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you see in binary version it flickers and I have failed to find out logic behind this (yet). However voxel positions seem to be fine. I can render these voxels also by raymarching through texture and this flickers too.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bQmhv.png&#xD;&#xA;[2]: https://i.stack.imgur.com/bQmhvm.png&#xD;&#xA;[3]:http://i65.tinypic.com/2e6g12b.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9912" PostHistoryTypeId="5" PostId="4388" RevisionGUID="9a029d97-531c-4701-a6be-483f4d4af1ff" CreationDate="2016-12-15T01:10:37.487" UserId="231" Comment="Some tidying - please revert anything that changes your intended meaning." Text="This problem has been haunting me for some time but I was busy with other things. I can't finish my GI technique (specifically occlusion step) without solving it.&#xD;&#xA;&#xD;&#xA;I made a binary scene voxelization in a single pass. The result is stored in a `RGBA32UI` 3D texture. It is three way so I set three ortho matrices each for X, Y, Z direction. These matrices are centered in camera position and form frustum in cube shape. And in geometry shader choose axis based on triangle normal.&#xD;&#xA;&#xD;&#xA;**First, what works - without binary voxelization** (but it's a waste of VRAM).&#xD;&#xA;Here is fragment shader code of voxelization pass:&#xD;&#xA;&#xD;&#xA;    //gridDim - gridDimensions in voxels&#xD;&#xA;    ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    ivec3 texcoord[3];&#xD;&#xA;&#xD;&#xA;    //correction of texture coord based on chosen axis and ortho matrix &#xD;&#xA;    //(f_axis - 0, 1 or 2 from geometry shader)&#xD;&#xA;    texcoord[0] = temp;&#xD;&#xA;&#xD;&#xA;    texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;    texcoord[1].y = temp.z;&#xD;&#xA;    texcoord[1].z = temp.y;&#xD;&#xA;&#xD;&#xA;    texcoord[2].x = temp.z;&#xD;&#xA;    texcoord[2].y = temp.y;&#xD;&#xA;    texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;&#xD;&#xA;    imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Drawing pass is done using instancing with cubes. The voxels are quite big because more of them results in a big framerate drop:&#xD;&#xA;&#xD;&#xA;    //vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel2 = texelFetch(geometryTexture, index, 0);&#xD;&#xA;    if(voxel2.r == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And it works:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But if I change it to the binary version:**&#xD;&#xA;&#xD;&#xA;    //input - position 1-128, output: coded binary position as 1 in uvec4 format&#xD;&#xA;        uvec4 encodeBinaryVoxel(int position)&#xD;&#xA;        {&#xD;&#xA;            // check for positioning to R channel&#xD;&#xA;            position = max(position, 0);&#xD;&#xA;            uint voxelId1 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to G channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId2 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to B channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId3 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to A channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId4 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            return uvec4(voxelId1, voxelId2, voxelId3, voxelId4);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;        ivec3 texcoord[3];&#xD;&#xA;    &#xD;&#xA;        texcoord[0] = temp;&#xD;&#xA;    &#xD;&#xA;        texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;        texcoord[1].y = temp.z;&#xD;&#xA;        texcoord[1].z = temp.y;&#xD;&#xA;    &#xD;&#xA;        texcoord[2].x = temp.z;&#xD;&#xA;        texcoord[2].y = temp.y;&#xD;&#xA;        texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;    &#xD;&#xA;        //get z index of texture, each z slice has room for 128 bits (32*4)&#xD;&#xA;        int indexZ = texcoord[f_axis].z / 128; &#xD;&#xA;        //get position in slice&#xD;&#xA;        int bitZ = texcoord[f_axis].z % 128 + 1; &#xD;&#xA;        ivec3 index = ivec3(texcoord[f_axis].xy, indexZ);&#xD;&#xA;        uvec4 current = imageLoad(geometryGrid, index);&#xD;&#xA;        //encode position as binary uvec4&#xD;&#xA;        uvec4 bit = encodeBinaryVoxel(bitZ); &#xD;&#xA;        //or operation with stored value&#xD;&#xA;        imageStore(geometryGrid, index, bit | current); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And read:&#xD;&#xA;&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;    int indexZ = index.z / 128;&#xD;&#xA;    int bitZ = index.z % 128 + 1;&#xD;&#xA;    uvec4 binZ = encodeBinaryVoxel(bitZ);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel = texelFetch(geometryTexture, ivec3(index.xy, indexZ), 0);&#xD;&#xA;    uvec4 occupy = binZ &amp; voxel;&#xD;&#xA;    if((occupy.r | occupy.g | occupy.b | occupy.a) == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you see in the binary version it flickers and I have failed to find out the logic behind this (yet). However, voxel positions seem to be fine. I can render these voxels also by raymarching through the texture and this flickers too.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bQmhv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bQmhvm.png&#xD;&#xA;  [3]: http://i65.tinypic.com/2e6g12b.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9914" PostHistoryTypeId="2" PostId="4389" RevisionGUID="f668df35-0cc7-407d-8982-e1d8f573b347" CreationDate="2016-12-15T09:16:53.853" UserId="2623" Text="After calling &lt;code&gt;glVertexAttribPointer&lt;/code&gt; to associate data of the currently bound vertex array with data from the currently bound &lt;code&gt;GL_ARRAY_BUFFER&lt;/code&gt;, I mentioned that I can simply delete the used buffer without it affecting the rendering.&#xD;&#xA;&#xD;&#xA;What actually happens with the data within the buffer when calling &lt;code&gt;glVertexAttribPointer&lt;/code&gt;? It seems like the data from the buffer actually get's copied into another memory location that the vertex array uses." ContentLicense="CC BY-SA 3.0" />
  <row Id="9915" PostHistoryTypeId="1" PostId="4389" RevisionGUID="f668df35-0cc7-407d-8982-e1d8f573b347" CreationDate="2016-12-15T09:16:53.853" UserId="2623" Text="OpenGL VertexArray Data &quot;Retention&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="9916" PostHistoryTypeId="3" PostId="4389" RevisionGUID="f668df35-0cc7-407d-8982-e1d8f573b347" CreationDate="2016-12-15T09:16:53.853" UserId="2623" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9917" PostHistoryTypeId="2" PostId="4390" RevisionGUID="df6acabb-5f12-458e-86e0-3430a6657300" CreationDate="2016-12-15T10:48:24.800" UserId="2041" Text="So far, I've been able to attach to `vrcompositor.exe` with RenderDoc and intercept the D3D calls that do the composition. According to Baldur Karlsson (the author of RenderDoc), it's not that hard to hack RenderDoc to use its hooks to run arbitrary code on each `Present` call of the chain I'm interested in.&#xD;&#xA;&#xD;&#xA;I've not had a chance to try that out yet, so this isn't a final answer! I'll update this post with any further progress." ContentLicense="CC BY-SA 3.0" />
  <row Id="9922" PostHistoryTypeId="5" PostId="4388" RevisionGUID="340ab3d9-bf94-442f-ba82-0ad210bf4c9b" CreationDate="2016-12-15T21:54:11.480" UserId="4958" Comment="added 529 characters in body" Text="This problem has been haunting me for some time but I was busy with other things. I can't finish my GI technique (specifically occlusion step) without solving it.&#xD;&#xA;&#xD;&#xA;I made a binary scene voxelization in a single pass. The result is stored in a `RGBA32UI` 3D texture. It is three way so I set three ortho matrices each for X, Y, Z direction. These matrices are centered in camera position and form frustum in cube shape. And in geometry shader choose axis based on triangle normal.&#xD;&#xA;&#xD;&#xA;**First, what works - without binary voxelization** (but it's a waste of VRAM).&#xD;&#xA;Here is fragment shader code of voxelization pass:&#xD;&#xA;&#xD;&#xA;    //gridDim - gridDimensions in voxels&#xD;&#xA;    ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    ivec3 texcoord[3];&#xD;&#xA;&#xD;&#xA;    //correction of texture coord based on chosen axis and ortho matrix &#xD;&#xA;    //(f_axis - 0, 1 or 2 from geometry shader)&#xD;&#xA;    texcoord[0] = temp;&#xD;&#xA;&#xD;&#xA;    texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;    texcoord[1].y = temp.z;&#xD;&#xA;    texcoord[1].z = temp.y;&#xD;&#xA;&#xD;&#xA;    texcoord[2].x = temp.z;&#xD;&#xA;    texcoord[2].y = temp.y;&#xD;&#xA;    texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;&#xD;&#xA;    imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Drawing pass is done using instancing with cubes. The voxels are quite big because more of them results in a big framerate drop:&#xD;&#xA;&#xD;&#xA;    //vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel2 = texelFetch(geometryTexture, index, 0);&#xD;&#xA;    if(voxel2.r == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And it works:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But if I change it to the binary version:**&#xD;&#xA;&#xD;&#xA;    //input - position 1-128, output: coded binary position as 1 in uvec4 format&#xD;&#xA;        uvec4 encodeBinaryVoxel(int position)&#xD;&#xA;        {&#xD;&#xA;            // check for positioning to R channel&#xD;&#xA;            position = max(position, 0);&#xD;&#xA;            uint voxelId1 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to G channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId2 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to B channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId3 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to A channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId4 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            return uvec4(voxelId1, voxelId2, voxelId3, voxelId4);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;        ivec3 texcoord[3];&#xD;&#xA;    &#xD;&#xA;        texcoord[0] = temp;&#xD;&#xA;    &#xD;&#xA;        texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;        texcoord[1].y = temp.z;&#xD;&#xA;        texcoord[1].z = temp.y;&#xD;&#xA;    &#xD;&#xA;        texcoord[2].x = temp.z;&#xD;&#xA;        texcoord[2].y = temp.y;&#xD;&#xA;        texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;    &#xD;&#xA;        //get z index of texture, each z slice has room for 128 bits (32*4)&#xD;&#xA;        int indexZ = texcoord[f_axis].z / 128; &#xD;&#xA;        //get position in slice&#xD;&#xA;        int bitZ = texcoord[f_axis].z % 128 + 1; &#xD;&#xA;        ivec3 index = ivec3(texcoord[f_axis].xy, indexZ);&#xD;&#xA;        uvec4 current = imageLoad(geometryGrid, index);&#xD;&#xA;        //encode position as binary uvec4&#xD;&#xA;        uvec4 bit = encodeBinaryVoxel(bitZ); &#xD;&#xA;        //or operation with stored value&#xD;&#xA;        imageStore(geometryGrid, index, bit | current); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And read:&#xD;&#xA;&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;    int indexZ = index.z / 128;&#xD;&#xA;    int bitZ = index.z % 128 + 1;&#xD;&#xA;    uvec4 binZ = encodeBinaryVoxel(bitZ);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel = texelFetch(geometryTexture, ivec3(index.xy, indexZ), 0);&#xD;&#xA;    uvec4 occupy = binZ &amp; voxel;&#xD;&#xA;    if((occupy.r | occupy.g | occupy.b | occupy.a) == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you see in the binary version it flickers and I have failed to find out the logic behind this (yet). However, voxel positions seem to be fine. I can render these voxels also by raymarching through the texture and this flickers too.&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've made a simplest voxelization using only vertex + fragment and one ortho matrix in X direction (then it is incorrect but whatever), and store value only in first slice (my `gridDim` is less than 128 so it fits) and it still flickers:&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    &#xD;&#xA;    uvec4 bit = encodeBinaryVoxel(index.z + 1);&#xD;&#xA;    &#xD;&#xA;    uvec4 current = imageLoad(geometryGrid, ivec3(index.xy, 0));&#xD;&#xA;    &#xD;&#xA;    imageStore(geometryGrid, ivec3(index.xy, 0), bit | current);&#xD;&#xA;&#xD;&#xA;I don't know, I think  I'll join sceptics (of programming) stack exchange or something.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bQmhv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bQmhvm.png&#xD;&#xA;  [3]: http://i65.tinypic.com/2e6g12b.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="9923" PostHistoryTypeId="2" PostId="4392" RevisionGUID="be1cfa43-20e3-4786-b807-14e53aa833c5" CreationDate="2016-12-15T23:07:07.783" UserId="48" Text="In the binary version you're doing an `imageLoad` and an `imageStore` on the same texture to modify it. This is a classic race condition: the GPU executes multiple threads of the shader in parallel, and there's no guarantee for those load-modify-store sequences to happen atomically. The operations from different threads can be interleaved, resulting in wrong data stored.&#xD;&#xA;&#xD;&#xA;To fix it, you should use [`imageAtomicOr`](https://www.opengl.org/sdk/docs/man/html/imageAtomicOr.xhtml) to combine the bits you want to write with the bits already in the buffer without a race condition. For more information, see [this OpenGL wiki page](https://www.opengl.org/wiki/Image_Load_Store#Atomic_operations)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9924" PostHistoryTypeId="2" PostId="4393" RevisionGUID="85154bc7-f41f-453f-949c-019c4656eb63" CreationDate="2016-12-16T00:09:40.350" UserDisplayName="user2500" Text="I'm fiddling with simple procedural 3D modeling to make teeny buildings for 3D printing. An Example:&#xD;&#xA;![The Building][1]&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;To make the models more readable onscreen, I've implemented basic shadow mapping for a single directional light. Since my scene isn't changing, I just render the shadow map once using an axis aligned box of the scene to figure out what the bounds of the shadow map should be. The shadows and bounds look like I've got all the matrices right, but coming in a bit closer looks terrible:&#xD;&#xA;&#xD;&#xA;![Closeup of Tower][2]&#xD;&#xA;&#xD;&#xA;From the reading I've done, I understand the peter panning and what I might do about it, but the ragged edges, which I believe is a form of projective aliasing, look so bad that I think something is wrong.&#xD;&#xA;&#xD;&#xA;I hacked the pixel shader to show the shadow texel boundaries:&#xD;&#xA;&#xD;&#xA;![Showing Texel Boundaries][3]&#xD;&#xA;&#xD;&#xA;I've got bilinear filtering on in the texture (without it, I get serious shadow acne). Sadly, my attempt at PCF failed too - it looks just as ragged:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;Does this look like &quot;typical&quot; projective aliasing? Could dynamic rendering of the shadow map, using the view frustum clipped to the scene, possibly with cascading, address the issue?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CrYde.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QdBmM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KPygS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/V4vqA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9925" PostHistoryTypeId="1" PostId="4393" RevisionGUID="85154bc7-f41f-453f-949c-019c4656eb63" CreationDate="2016-12-16T00:09:40.350" UserDisplayName="user2500" Text="Handling Projective Aliasing In Shadow Mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="9926" PostHistoryTypeId="3" PostId="4393" RevisionGUID="85154bc7-f41f-453f-949c-019c4656eb63" CreationDate="2016-12-16T00:09:40.350" UserDisplayName="user2500" Text="|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9927" PostHistoryTypeId="2" PostId="4394" RevisionGUID="44961125-2fef-473d-9024-4ebad458a2a4" CreationDate="2016-12-16T03:00:25.953" UserDisplayName="user5681" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, spectral.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][3]][3]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations were extracted from the original paper, including $F$, which is presented as a more efficient, and less accurate, approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/BU0s0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9928" PostHistoryTypeId="1" PostId="4394" RevisionGUID="44961125-2fef-473d-9024-4ebad458a2a4" CreationDate="2016-12-16T03:00:25.953" UserDisplayName="user5681" Text="Path tracing the Cook-Torrance BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="9929" PostHistoryTypeId="3" PostId="4394" RevisionGUID="44961125-2fef-473d-9024-4ebad458a2a4" CreationDate="2016-12-16T03:00:25.953" UserDisplayName="user5681" Text="|raytracing|brdf|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9930" PostHistoryTypeId="2" PostId="4395" RevisionGUID="8057fa10-9bac-43c9-8997-54d41c386ed9" CreationDate="2016-12-16T10:44:48.997" UserId="5632" Text="According to [this paper][1], the $\frac{1}{\pi}$ in your $f_r$ should be $\frac{1}{4}$:&#xD;&#xA;$$&#xD;&#xA;f_r = \frac{DFG}{4(n\cdot w_i)(n \cdot w_o)},&#xD;&#xA;$$&#xD;&#xA;so you would end up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2}L_i(p,w_k)\left(\frac{DFG}{n\cdot w_o}\right).&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9931" PostHistoryTypeId="5" PostId="4393" RevisionGUID="0b7a3fd8-c6dd-4912-8b5d-554b51854f40" CreationDate="2016-12-16T12:18:25.697" UserDisplayName="user2500" Comment="Fixed formatting around image, fixed grammar." Text="I'm fiddling with simple procedural 3D modeling to make teeny buildings for 3D printing. An Example:&#xD;&#xA;&#xD;&#xA;![The Building][1]&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;To make the models more readable onscreen, I've implemented basic shadow mapping for a single directional light. Since my scene isn't changing, I just render the shadow map once using an axis aligned box of the scene to figure out what the bounds of the shadow map should be. The shadows and bounds look like I've got all the matrices right, but coming in a bit closer looks terrible:&#xD;&#xA;&#xD;&#xA;![Closeup of Tower][2]&#xD;&#xA;&#xD;&#xA;From the reading I've done, I understand the peter panning and what I might do about it, but the ragged edges, which I believe is a form of projective aliasing, look so bad that I think something is wrong in my basic implementation.&#xD;&#xA;&#xD;&#xA;I hacked the pixel shader to show the shadow texel boundaries:&#xD;&#xA;&#xD;&#xA;![Showing Texel Boundaries][3]&#xD;&#xA;&#xD;&#xA;I've got bilinear filtering on in the texture (without it, I get serious shadow acne). Sadly, my attempt at PCF failed too - it looks just as ragged:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;Does this look like &quot;typical&quot; projective aliasing? Could dynamic rendering of the shadow map, using the view frustum clipped to the scene, possibly with cascading, address the issue?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CrYde.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QdBmM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KPygS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/V4vqA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9935" PostHistoryTypeId="2" PostId="4396" RevisionGUID="0bd963f9-b606-4b06-a6d9-214b715f1d6b" CreationDate="2016-12-16T14:33:27.163" UserId="2372" Text="I am mainly using Unity and I am wondering what's the difference between using [tex2D][1] and [Sample][2] for sampling a texture.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/Cg/tex2D.html&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509695(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="9936" PostHistoryTypeId="1" PostId="4396" RevisionGUID="0bd963f9-b606-4b06-a6d9-214b715f1d6b" CreationDate="2016-12-16T14:33:27.163" UserId="2372" Text="What's the difference between Sample and tex2D" ContentLicense="CC BY-SA 3.0" />
  <row Id="9937" PostHistoryTypeId="3" PostId="4396" RevisionGUID="0bd963f9-b606-4b06-a6d9-214b715f1d6b" CreationDate="2016-12-16T14:33:27.163" UserId="2372" Text="|opengl|shader|texture|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9938" PostHistoryTypeId="5" PostId="4393" RevisionGUID="28338432-d1fe-45ec-b8e5-05684ec97c89" CreationDate="2016-12-16T15:23:39.557" UserDisplayName="user2500" Comment="Added picture with bilnear filtering off." Text="I'm fiddling with simple procedural 3D modeling to make teeny buildings for 3D printing. An Example:&#xD;&#xA;&#xD;&#xA;![The Building][1]&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;To make the models more readable onscreen, I've implemented basic shadow mapping for a single directional light. Since my scene isn't changing, I just render the shadow map once using an axis aligned box of the scene to figure out what the bounds of the shadow map should be. The shadows and bounds look like I've got all the matrices right, but coming in a bit closer looks terrible:&#xD;&#xA;&#xD;&#xA;![Closeup of Tower][2]&#xD;&#xA;&#xD;&#xA;From the reading I've done, I understand the peter panning and what I might do about it, but the ragged edges, which I believe is a form of projective aliasing, look so bad that I think something is wrong in my basic implementation.&#xD;&#xA;&#xD;&#xA;I hacked the pixel shader to show the shadow texel boundaries:&#xD;&#xA;&#xD;&#xA;![Showing Texel Boundaries][3]&#xD;&#xA;&#xD;&#xA;I've got bilinear filtering on in the texture (without it, I get serious shadow acne). Sadly, my attempt at PCF failed too - it looks just as ragged:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;Here's the single sample case with bilinear filtering disabled:&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;Does this look like &quot;typical&quot; projective aliasing? Could dynamic rendering of the shadow map, using the view frustum clipped to the scene, possibly with cascading, address the issue?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CrYde.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QdBmM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KPygS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/V4vqA.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/Tkef4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="9939" PostHistoryTypeId="5" PostId="4396" RevisionGUID="232a9879-83f0-4326-b55c-74949db3ab2f" CreationDate="2016-12-16T16:19:13.510" UserId="2654" Comment="This is not an OpenGL question." Text="I am mainly using Unity, and I am wondering what's the difference between using [`tex2D`][1] and [`Sample`][2] for sampling a texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/Cg/tex2D.html&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509695(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="9940" PostHistoryTypeId="6" PostId="4396" RevisionGUID="232a9879-83f0-4326-b55c-74949db3ab2f" CreationDate="2016-12-16T16:19:13.510" UserId="2654" Comment="This is not an OpenGL question." Text="|shader|texture|directx11|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="9941" PostHistoryTypeId="24" PostId="4396" RevisionGUID="232a9879-83f0-4326-b55c-74949db3ab2f" CreationDate="2016-12-16T16:19:13.510" Comment="Proposed by 2654 approved by -1 edit id of 187" ContentLicense="CC BY-SA 3.0" />
  <row Id="9942" PostHistoryTypeId="5" PostId="4396" RevisionGUID="c8ef48f8-bd7c-49ce-899e-a45b7ddc5c61" CreationDate="2016-12-16T16:19:13.510" UserId="2372" Comment="This is not an OpenGL question." Text="I am mainly using Unity but I think that it's not related to this engine, and I am wondering what's the difference between using [`tex2D`][1] and [`Sample`][2] for sampling a texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/Cg/tex2D.html&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509695(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="9943" PostHistoryTypeId="2" PostId="4397" RevisionGUID="92ec8c70-b64a-42d5-8554-527ad73380f9" CreationDate="2016-12-16T16:20:27.710" UserId="2654" Text="You must fully create a renderbuffer *before* you can attach it to an FBO.&#xD;&#xA;&#xD;&#xA;The [pre-DSA OpenGL Object creation functions][1] do not create objects; they create object *names*. It's like creating an uninitialized pointer variable; it doesn't point to anything yet.&#xD;&#xA;&#xD;&#xA;The actual creation of the object happens the first time the name is bound to the context. At that moment, the name is given a real object.&#xD;&#xA;&#xD;&#xA;Under normal circumstances, it was pretty much impossible to use an object *without* binding it to the context, so this distinction couldn't be noticed. However, once the ability to attach objects to one another came to be, this distinction became noticeable.&#xD;&#xA;&#xD;&#xA;Pre-DSA, the only way to fully create a renderbuffer object was to bind it to the context.&#xD;&#xA;&#xD;&#xA;However, with [ARB_DSA/GL 4.5][2], the `glCreate*` functions actually *create objects* (imagine that!). So if you use `glCreateRenderbuffers`, you can attach the renderbuffer to an FBO without binding it first.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/OpenGL_Object#Object_Creation_and_Destruction&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Direct_State_Access" ContentLicense="CC BY-SA 3.0" />
  <row Id="9944" PostHistoryTypeId="2" PostId="4398" RevisionGUID="937990a3-3685-420c-84ab-0d99564bcdcc" CreationDate="2016-12-16T16:23:32.423" UserId="2654" Text="[Deleting an OpenGL object][1] is merely a suggestion. Deleting an object will unbind the object from any binding point it is currently bound to. However, buffer objects are not &quot;bound&quot; to VAOs. They are *attached* to VAOs.&#xD;&#xA;&#xD;&#xA;When you call `glVertexAttrib*Pointer`, you attach a buffer object to the VAO. The buffer object to be attached is the one bound to `GL_ARRAY_BUFFER`. Unbinding that buffer, or even flat-out deleting it, will *not* undo the attachment.&#xD;&#xA;&#xD;&#xA;And an OpenGL object [will continue to exist so long as it is *attached* to a container object][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/wiki/OpenGL_Object#Object_Creation_and_Destruction&#xD;&#xA;  [2]: https://www.opengl.org/wiki/OpenGL_Object#Deletion_orphaning" ContentLicense="CC BY-SA 3.0" />
  <row Id="9945" PostHistoryTypeId="2" PostId="4399" RevisionGUID="82dbbbb5-abb4-41d5-a21e-13e23f3d2d34" CreationDate="2016-12-16T17:26:17.327" UserDisplayName="user5681" Text="You said that &quot;...bilinear filtering on in the texture..&quot;. It seems that you are interpolating the depth values in the shadow map. The correct way of using interpolation with shadow mapping is to apply interpolation over the outcomes of the shadow tests (as far as I remember, OpenGL supports that). You might even combine the interpolation of the outcomes of the shadow tests with PCF, wich will deliver better results. However, as you might have noticed, aliasing is a plague that always pursue the shadow mapping :)&#xD;&#xA;Although I understand that you are looking for solutions regarding shadow mapping (even because it is quite simple to implement), since it seems that you are using only polyhedra, did you consider the use of shadow volumes? It is much more intricate to implement, but does not suffer from aliasing at all, and I think would fit for your purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="9946" PostHistoryTypeId="5" PostId="4399" RevisionGUID="79d97208-39b4-446a-a4a4-2f0e79e0a061" CreationDate="2016-12-16T17:34:19.103" UserDisplayName="user5681" Comment="added 83 characters in body" Text="You've said that &quot;... bilinear filtering on in the texture ...&quot;. It seems that you are interpolating the depth values of the shadow map. The correct way of using interpolation with the shadow map is to apply it over the outcomes of the shadow tests (as far as I remember, OpenGL supports that). You might even combine the interpolation of the outcomes of the shadow tests with PCF, which will deliver much better results. However, as you might have noticed, aliasing is a plague that always pursue the shadow mapping :)&#xD;&#xA;&#xD;&#xA;Although I understand that you are looking for solutions regarding shadow mapping (even because it is quite simple to implement), have you ever considered the use of shadow volumes? It is much more intricate to implement, but does not suffer from aliasing at all, and I think would fit nicely your purposes (but only if you do not plan to render scenes containing higher order surfaces such as those generated with implicits)." ContentLicense="CC BY-SA 3.0" />
  <row Id="9947" PostHistoryTypeId="5" PostId="4399" RevisionGUID="d8367cfd-e2b2-44cd-a158-566ec2401608" CreationDate="2016-12-16T17:44:27.493" UserDisplayName="user5681" Comment="deleted 119 characters in body" Text="You've said that &quot;... bilinear filtering on in the texture ...&quot;. It seems that you are interpolating the depth values of the shadow map. The correct way of using interpolation with the shadow map is to apply it over the outcomes of the shadow tests (as far as I remember, OpenGL supports that). You might even combine the interpolation of the outcomes of the shadow tests with PCF, which will deliver much better results. However, as you might have noticed, aliasing is a plague that always pursue the shadow mapping :)&#xD;&#xA;&#xD;&#xA;Although I understand that you are looking for solutions regarding shadow mapping (even because it is quite simple to implement), have you ever considered the use of shadow volumes? It is much more intricate to implement, but does not suffer from aliasing at all, and I think would fit nicely your purposes." ContentLicense="CC BY-SA 3.0" />
  <row Id="9948" PostHistoryTypeId="2" PostId="4400" RevisionGUID="064f03b8-8d3f-4cfc-a6dd-8395292123b5" CreationDate="2016-12-16T18:34:32.290" UserId="48" Text="They represent the same operation, but `Sample` is what it's called in D3D10 and newer versions of HLSL, while `tex2D` is what it's called in D3D9 HLSL, and NVIDIA's (defunct) Cg language. By the way, the operation is also called [`texture`](http://docs.gl/sl4/texture) in GLSL." ContentLicense="CC BY-SA 3.0" />
  <row Id="9949" PostHistoryTypeId="2" PostId="4401" RevisionGUID="1343c0fc-061f-44a5-8c2f-3fe8363bb349" CreationDate="2016-12-16T18:50:35.457" UserId="4958" Text="Shadow mapping with acceptable quality is quite a journey. So you implemented first step - basic shadow map that encompass whole scene statically. This means that shadow map texel size in light view space to texel size of rendered scene in camera view space ratio is quite big, resulting in aliasing. To reduce this ratio closer to 1:1 there are techniques you mentioned like:&#xD;&#xA;&#xD;&#xA; - the easiest way is increasing size of your shadow map, to find the value with still optimal performance.&#xD;&#xA; - align shadow map with camera view frustum. Then shadow map encompass smaller part of the scene, so it reduces aliasing.&#xD;&#xA; - this can be improved to CSM, which does the same but you need to render scene for each of cascade with different center position of light view matrix based on center point of each slice of frustum.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some of the basic techniques of smoothing the edge of shadow:&#xD;&#xA;&#xD;&#xA; - obviously PCF, but is it recommended to combine your PCF implementiation with built in hardware PCF (in Opengl - using `sampler2DShadow`). This would result in less loop iterations from your side and cheaper PCF.&#xD;&#xA; - blockiness of edges can be exchanged for noise using rotated Poisson Disk. Samples used to sample from shadow map are rotated randomly with each iteration of PCF loop.&#xD;&#xA;&#xD;&#xA;You can also research the edge smoothing techniques like:&#xD;&#xA;&#xD;&#xA; - rendering shadow map to MSAA applied framebuffer&#xD;&#xA; - further enhancing PCF by [interpolation][1]&#xD;&#xA;&#xD;&#xA;There are also Exponential Shadow Maps - which I use because these are great for removing shadow acne in my experience. I combine them with PCF techniques. &#xD;&#xA;&#xD;&#xA;I didn't implemented the Volume Shadows myself but it seems to be interesting area to investigate.&#xD;&#xA;&#xD;&#xA;You didn't fail with PCF, it looks like that:)&#xD;&#xA;&#xD;&#xA;  [1]: http://codeflow.org/entries/2013/feb/15/soft-shadow-mapping/#pcf-and-interpolation" ContentLicense="CC BY-SA 3.0" />
  <row Id="9950" PostHistoryTypeId="5" PostId="4401" RevisionGUID="6fec4e31-d8bd-4053-b4ad-4020d10e8b8d" CreationDate="2016-12-16T19:01:38.600" UserId="4958" Comment="added 58 characters in body" Text="Shadow mapping with acceptable quality is quite a journey. So you implemented first step - basic shadow map that encompass whole scene statically. This means that shadow map texel size in light view space to texel size of rendered scene in camera view space ratio is quite big, resulting in aliasing. To reduce this ratio closer to 1:1 there are techniques you mentioned like:&#xD;&#xA;&#xD;&#xA; - the easiest way is increasing size of your shadow map, to find the value with still optimal performance.&#xD;&#xA; - align shadow map with camera view frustum. Then shadow map encompass smaller part of the scene, so it reduces aliasing.&#xD;&#xA; - this can be improved to CSM, which does the same but you need to render scene for each of cascade with different center position of light view matrix based on center point of each slice of frustum.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some of the basic techniques of smoothing the edge of shadow:&#xD;&#xA;&#xD;&#xA; - obviously PCF, but is it recommended to combine your PCF implementiation with built in hardware PCF (in Opengl - using `sampler2DShadow`). This would result in less loop iterations from your side and cheaper PCF.&#xD;&#xA; - blockiness of edges can be exchanged for noise using rotated Poisson Disk. Samples used to sample from shadow map are rotated randomly with each iteration of PCF loop.&#xD;&#xA;&#xD;&#xA;You can also research the edge smoothing techniques like:&#xD;&#xA;&#xD;&#xA; - rendering shadow map to MSAA applied framebuffer&#xD;&#xA; - further enhancing PCF by [interpolation][1]&#xD;&#xA;&#xD;&#xA;There are also Exponential Shadow Maps - which I use because these are great for removing shadow acne in my experience, so you don't need to add bias resulting in peter panning. I combine them with PCF techniques. Unfortunately I can't combine ESM with hardware PCF.&#xD;&#xA;&#xD;&#xA;I didn't implemented the Volume Shadows myself but it seems to be interesting area to investigate.&#xD;&#xA;&#xD;&#xA;You didn't fail with PCF, it looks like that:)&#xD;&#xA;&#xD;&#xA;I wish there was a way to apply gaussian blur on shadow map in camera view space, but it doesn't work as expected.&#xD;&#xA;&#xD;&#xA;  [1]: http://codeflow.org/entries/2013/feb/15/soft-shadow-mapping/#pcf-and-interpolation" ContentLicense="CC BY-SA 3.0" />
  <row Id="9954" PostHistoryTypeId="5" PostId="4394" RevisionGUID="d8681062-23ce-40e4-b323-ee416d1ab273" CreationDate="2016-12-17T00:32:47.683" UserDisplayName="user5681" Comment="added 995 characters in body" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, spectral.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations were extracted from the original paper, including $F$, which is presented as a more efficient, and less accurate, approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][3] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9955" PostHistoryTypeId="5" PostId="4394" RevisionGUID="03d28816-269e-452b-a74b-179fbc29e472" CreationDate="2016-12-17T00:37:57.173" UserDisplayName="user5681" Comment="added 995 characters in body" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, spectral.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations were extracted from the original paper, including $F$, which is presented as a more efficient, and less accurate, approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][3] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D_{new} = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr_{new}(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{D_{new}FG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="9971" PostHistoryTypeId="50" PostId="4274" RevisionGUID="fd34d366-2f5c-4be0-84a1-b881decc7bd5" CreationDate="2016-12-18T17:29:50.217" UserId="-1" />
  <row Id="9991" PostHistoryTypeId="5" PostId="4393" RevisionGUID="1a0b6016-08b3-4d4d-80f2-6f829840fc1a" CreationDate="2016-12-20T12:01:53.907" UserDisplayName="user2500" Comment="Grammar" Text="I'm fiddling with simple procedural 3D modeling to make teeny buildings for 3D printing. An Example:&#xD;&#xA;&#xD;&#xA;![The Building][1]&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;To make the models more readable onscreen, I've implemented basic shadow mapping for a single directional light. Since my scene isn't changing, I just render the shadow map once using an axis aligned box of the scene to figure out what the bounds of the shadow map should be. The shadows and bounds look like I've got all the matrices right, but coming in a bit closer looks terrible:&#xD;&#xA;&#xD;&#xA;![Closeup of Tower][2]&#xD;&#xA;&#xD;&#xA;From the reading I've done, I understand the peter panning and what I might do about it, but the ragged edges, which I believe is a form of projective aliasing, look so bad that I think something is wrong in my basic implementation.&#xD;&#xA;&#xD;&#xA;I hacked the pixel shader to show the shadow texel boundaries:&#xD;&#xA;&#xD;&#xA;![Showing Texel Boundaries][3]&#xD;&#xA;&#xD;&#xA;I've got bilinear filtering on in the texture (without it, I get serious shadow acne). Sadly, my attempt at PCF failed too - it looks just as ragged:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;Here's the single sample case with bilinear filtering disabled:&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;Does this look like &quot;typical&quot; projective aliasing? Could dynamic rendering of the shadow map, using the view frustum clipped to the scene, possibly with cascading, address the issue?&#xD;&#xA;&#xD;&#xA;Edit: Adding a closeup of bilinear filtering, post shadow comparison, just to show what I get. Bad shadow acne shows up because of interior edges; I'm modeling with stacked virtual blocks and not doing a proper union operation. From my reading, implementing boolean operations on polyhedra is not trivial, but will also allow me to implement static shadow volumes as well as clean up for some 3D printing software.&#xD;&#xA;&#xD;&#xA;![Bilinear Filtering][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CrYde.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QdBmM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KPygS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/V4vqA.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/Tkef4.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/t28ZW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10012" PostHistoryTypeId="11" PostId="4385" RevisionGUID="07c6506f-e072-4e75-9375-c5e467b58196" CreationDate="2016-12-21T18:31:53.290" UserId="127" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;},{&quot;Id&quot;:127,&quot;DisplayName&quot;:&quot;Nero&quot;}]}" />
  <row Id="10013" PostHistoryTypeId="2" PostId="4407" RevisionGUID="8c99579d-0112-491f-bfaa-249384e2bcb2" CreationDate="2016-12-21T21:37:50.127" UserId="5708" Text="This might be an odd question, but I was wondering if you could improve GPU performance with games, comparatively, when using doubles/halves of the native resolution, instead of an odd ratio of that.&#xD;&#xA;&#xD;&#xA;Lets compare the situation with a metaphor first. If I'd give you a standard A4 sheet of paper, I bet you can more easily fold it in half than 1/3rd. Same goes when I'd give you two sheets of A4 and ask you to create a A3-size rectangle, instead of a not-A3-but-larger-than-A4-shape.&#xD;&#xA;&#xD;&#xA;To go back to the actual situation: My Macbook has a native resolution of 2880x1800. But the game offers a variety of resolutions, such as 1440x900, 1680x1050, 2048x1280, 2560x1600 and for some reason also 3360x2100, which is above the native resolution..&#xD;&#xA;&#xD;&#xA;If we'd include the sheet of paper thought in resolution scaling with games, compared to the native resolution, I'd say 1440x900 could run even better than 1280x800, because the GPU could simply say: reduce all pixels by 50%. Not only is that an easier calculation, but it's also much easier to interpolate, *if that's the correct word for it* to calculate how the pixel should look like.&#xD;&#xA;&#xD;&#xA;Sudden thought: This does assume the game environment is rendered at the native resolution and thereafter downscaled to the set resolution, which is probably wrong. That said, I do think it'd be easier to render at half the resolution than something like 40%.&#xD;&#xA;&#xD;&#xA;This idea **does** apply to Photoshop with increasing and decreasing the resolution: Always increase with halves and doubles. So why not games?&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;I'm not only very interested in the actual answer, but perhaps makes it easier to set a resolution for a battery vs performance question :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10014" PostHistoryTypeId="1" PostId="4407" RevisionGUID="8c99579d-0112-491f-bfaa-249384e2bcb2" CreationDate="2016-12-21T21:37:50.127" UserId="5708" Text="Do GPU performance improve when rendering at native or half resolution, compared to fixed scaling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10015" PostHistoryTypeId="3" PostId="4407" RevisionGUID="8c99579d-0112-491f-bfaa-249384e2bcb2" CreationDate="2016-12-21T21:37:50.127" UserId="5708" Text="|rendering|gpu|pixel-graphics|subpixel-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10016" PostHistoryTypeId="2" PostId="4408" RevisionGUID="36475a6f-291f-48ba-994d-0bf3cfb153f1" CreationDate="2016-12-21T23:49:17.320" UserDisplayName="user2500" Text="GPUs can efficiently scale an image by an arbitrary amount (within limits - display options fall within those limits by design) either using a 3D rendering operation or as the signal is sent from GPU to the display. Both of these paths have fully dedicated hardware for the arbitrary resizing and are not likely to be optimized for doubling or halving. Both support a technique called &quot;bilinear filtering&quot; though advances in display hardware may provide higher quality.&#xD;&#xA;&#xD;&#xA;If a game is run at non native resolution on a laptop (TVs and desktop displays have their own scalers, but laptop displays generally rely on the GPU), one of these two methods will be used. Display scaling is essentially &quot;free&quot;, so it is preferred and the lower the resolution the game is originally rendered the faster the frame rate (or the lower power consumption) - with no special performance benefit for, say, doubling. If a 3D operation is required (say, due to a limitation or issue in the display scaler), the scale operation is not free, but is going to go up with the source and destination sizes smoothly, with no special casing at doubling/halving.&#xD;&#xA;&#xD;&#xA;The game may look far better at certain scaling factors, but that's up to the user to decide." ContentLicense="CC BY-SA 3.0" />
  <row Id="10017" PostHistoryTypeId="2" PostId="4409" RevisionGUID="82a7e371-7172-41fd-8098-e2619239a426" CreationDate="2016-12-22T00:15:05.157" UserId="5709" Text="I have been following a tutorial, shadow mapping works more or less as expected except sometimes the shadow projects completely weirdly on nearby walls. This isn't sampling outside the lightmap because I use CLAMP_TO_EDGE and if(min(ShadowCoord.x, ShadowCoord.y) &gt; 0.0 &amp;&amp; max(ShadowCoord.x, ShadowCoord.y) &lt; 1.0) in the fragment shader. Does anyone know what the official term for this problem is so I can go research it some more? Thanks.&#xD;&#xA;&#xD;&#xA;![Shadowmapping error](https://i.stack.imgur.com/rISb0.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10018" PostHistoryTypeId="1" PostId="4409" RevisionGUID="82a7e371-7172-41fd-8098-e2619239a426" CreationDate="2016-12-22T00:15:05.157" UserId="5709" Text="What is this shadow mapping error called?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10019" PostHistoryTypeId="3" PostId="4409" RevisionGUID="82a7e371-7172-41fd-8098-e2619239a426" CreationDate="2016-12-22T00:15:05.157" UserId="5709" Text="|shadow|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10020" PostHistoryTypeId="2" PostId="4410" RevisionGUID="9791940c-bb86-4a8b-9d41-4a59c1bd2f8f" CreationDate="2016-12-22T06:11:47.190" UserId="3003" Text="It's not entirely clear what the scene in your picture is supposed to look like, so I'm not sure I'm interpreting it correctly. But if I am, it seems like the problem is that you're projecting the shadow properly, but onto the wrong face of the gray wall. If you want to research it, you might have luck looking up [winding order](https://en.wikipedia.org/wiki/Winding_number) (sometimes called winding number), or [back-face culling](https://en.wikipedia.org/wiki/Back-face_culling). &#xD;&#xA;&#xD;&#xA;If I'm correct in what's shown above, I think you could solve it in your shader by only applying the shadows to the current fragment if the vector from the light source to the surface points away from the surface normal. In other words, take the dot product of those 2 vectors, and if it's negative apply shadows, otherwise, don't." ContentLicense="CC BY-SA 3.0" />
  <row Id="10021" PostHistoryTypeId="2" PostId="4411" RevisionGUID="df83652d-f88b-4ead-b5c0-c2e865593e7e" CreationDate="2016-12-22T12:20:10.197" UserId="38" Text="This is a quite common property of smoothing in 3D. When you have some data and you smooth it out you get some kind of average of the local variation. And this works fine, and stably, in one dimensional graphs. &#xD;&#xA;&#xD;&#xA;But when your entire data set is being smoothed over its coordinates the neighboring coordinates drag your data with them. Those again are dragged by their neighbors. The net effect is that the local variation of the surface as a whole is dragging itself towards a average that is stable in the smoothing operation itself. This will cause shrinkage because a closed object as a whole has a local average that is towards the common center of all the points in operation. &#xD;&#xA;&#xD;&#xA;In other words there is no structure to keep the surface locked to its place." ContentLicense="CC BY-SA 3.0" />
  <row Id="10022" PostHistoryTypeId="5" PostId="4411" RevisionGUID="2da0ca27-2e44-4072-9cd8-da1f19f28ef5" CreationDate="2016-12-22T12:25:28.993" UserId="38" Comment="added 110 characters in body" Text="This is a quite common property of smoothing in 3D. When you have some data and you smooth it out you get some kind of average of the local variation. And this works fine, and stably, in one dimensional graphs. &#xD;&#xA;&#xD;&#xA;But when your entire data set is being smoothed over its coordinates the neighboring coordinates drag your data with them. Those again are dragged by their neighbors. The net effect is that the local variation of the surface as a whole is dragging itself towards a average that is stable in the smoothing operation itself. This will cause shrinkage because a closed object as a whole has a local average that is towards the common center of all the points in operation. Even in cases where you go locally outwards you are eventually caught up with the eges that drag you inwards. &#xD;&#xA;&#xD;&#xA;In other words there is no structure to keep the surface locked to its place. The etendency to drag twaards the center eventually wins because there is nothing to counteract this." ContentLicense="CC BY-SA 3.0" />
  <row Id="10023" PostHistoryTypeId="5" PostId="4411" RevisionGUID="b01d11d7-debe-499d-8b2f-19f0fa655430" CreationDate="2016-12-22T12:32:16.823" UserId="38" Comment="edited body" Text="This is a quite common property of smoothing in 3D. When you have some data and you smooth it out you get some kind of average of the local variation. And this works fine, and stably, in one dimensional graphs. &#xD;&#xA;&#xD;&#xA;But when your entire data set is being smoothed over its coordinates the neighboring coordinates drag your data with them. Those again are dragged by their neighbors. The net effect is that the local variation of the surface as a whole is dragging itself towards a average that is stable in the smoothing operation itself. This will cause shrinkage because a closed object as a whole has a local average that is towards the common center of all the points in operation. Even in cases where you go locally outwards you are eventually caught up with the edges that drag you inwards. &#xD;&#xA;&#xD;&#xA;In other words there is no structure to keep the surface locked to its place. The tendency to drag towards the center eventually wins because there is nothing to counteract this. There just simply is more opportunities to go inward than outword." ContentLicense="CC BY-SA 3.0" />
  <row Id="10024" PostHistoryTypeId="5" PostId="4411" RevisionGUID="2507b8f7-92c4-49a5-a632-4364a473b72c" CreationDate="2016-12-22T13:44:08.963" UserId="231" Comment="Minor tidying" Text="This is a quite common property of smoothing in 3D. When you have some data and you smooth it out you get some kind of average of the local variation. And this works fine, and stably, in one dimensional graphs. &#xD;&#xA;&#xD;&#xA;But when your entire data set is being smoothed over its coordinates the neighboring coordinates drag your data with them. Those again are dragged by their neighbors. The net effect is that the local variation of the surface as a whole is dragging itself towards an average that is stable in the smoothing operation itself. This will cause shrinkage because a closed object as a whole has a local average that is towards the common center of all the points in operation. Even in cases where you go locally outwards you are eventually caught up with the edges that drag you inwards. &#xD;&#xA;&#xD;&#xA;In other words there is no structure to keep the surface locked to its place. The tendency to drag towards the center eventually wins because there is nothing to counteract this. There just simply are more opportunities to go inward than outward." ContentLicense="CC BY-SA 3.0" />
  <row Id="10028" PostHistoryTypeId="2" PostId="4412" RevisionGUID="f24a226f-6679-4825-8d7f-a900accde4af" CreationDate="2016-12-25T11:37:25.197" UserId="5256" Text="I have a few doubts and questions regarding **volume rendering**, I was hoping someone here could help me understand.&#xD;&#xA;&#xD;&#xA; 1. I commonly hear the terms **'Ray-Marching'** &amp; **'Volume Rendering'** being used together when it comes to **rendering fog or any other volumetric object.**&#xD;&#xA;&#xD;&#xA;**Is Ray Marching the method used to render these volumes such as Fog, Smoke &amp; Fire** *(this is regarding path tracing)*? Since we can use signed distance fields to **easily manipulate the shape of the volume?** At the **approximated intersection point is a BSDF evaluated** (BRDF + BTDF) or is it **just a BRDF?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA; 2.  At the approximated intersection point for the volume **what BRDF/BSDF do we use (if we do use one, I might have a wrong understanding of the topic)? Are there measured BRDFs &amp; BTDFs that is the common standard?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="10029" PostHistoryTypeId="1" PostId="4412" RevisionGUID="f24a226f-6679-4825-8d7f-a900accde4af" CreationDate="2016-12-25T11:37:25.197" UserId="5256" Text="Volume Rendering (Path Tracing &amp; Real-Time)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10030" PostHistoryTypeId="3" PostId="4412" RevisionGUID="f24a226f-6679-4825-8d7f-a900accde4af" CreationDate="2016-12-25T11:37:25.197" UserId="5256" Text="|brdf|pathtracing|volumetric|raymarching|volumetric-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10031" PostHistoryTypeId="2" PostId="4413" RevisionGUID="37903d5b-1abf-4b32-8622-2aadd6e4185c" CreationDate="2016-12-25T17:37:20.547" UserId="2096" Text="I want to draw a string of text with a single draw call(Instancing). I am reading a bitmap for each character texture. I want to pass the texture coordinates for each vertex of a quad(a single character). Now this texture coordinates supposed to be updated for each vertex processed by vertex shader because i set the glVertexAttribDivisor() to 0 which means it should be. But its not happening.&#xD;&#xA;&#xD;&#xA;Here's the source code where i am sending the data to the GPU...&#xD;&#xA;&#xD;&#xA;    //TEXTURE COORDS&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER, mVBOTexCoords);&#xD;&#xA;		glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*mTexCoords.size(), mTexCoords.data(), GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;		glEnableVertexAttribArray(3);&#xD;&#xA;		glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;        &#xD;&#xA;        glVertexAttribDivisor(3,0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and the vertex shader...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;       #version 400 &#xD;&#xA;&#xD;&#xA;       out vec2 tex_coords;&#xD;&#xA;&#xD;&#xA;       layout(location = 0) in vec2 pos;&#xD;&#xA;       layout(location = 1) in vec2 offset;&#xD;&#xA;       layout(location = 2) in vec2 scale;&#xD;&#xA;       layout(location = 3) in vec2 tex;&#xD;&#xA;&#xD;&#xA;       uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       void main()&#xD;&#xA;       {&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	tex_coords = tex;&#xD;&#xA;&#xD;&#xA;	vec4 position = vec4(pos,0.0f,1.0f);&#xD;&#xA;	position.xy*=scale;&#xD;&#xA;	position.xy+=offset;&#xD;&#xA;&#xD;&#xA;	gl_Position = projection*position;&#xD;&#xA;	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Sorry for the mess. I hope you get it. I am not getting why its not updating the texture coordninates for each vertex. Please help.&#xD;&#xA;Thanks.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10032" PostHistoryTypeId="1" PostId="4413" RevisionGUID="37903d5b-1abf-4b32-8622-2aadd6e4185c" CreationDate="2016-12-25T17:37:20.547" UserId="2096" Text="Texture coordinates are not updating according to the vertex divisor specified" ContentLicense="CC BY-SA 3.0" />
  <row Id="10033" PostHistoryTypeId="3" PostId="4413" RevisionGUID="37903d5b-1abf-4b32-8622-2aadd6e4185c" CreationDate="2016-12-25T17:37:20.547" UserId="2096" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10034" PostHistoryTypeId="2" PostId="4414" RevisionGUID="cd6a70bb-cc15-4542-9b34-b7a872ddd65a" CreationDate="2016-12-25T20:09:34.663" UserId="1952" Text="Ray marching is a ray tracing method where you take multiple steps along a ray to find intersection with geometry or to perform integration of in-scattered light from participating media (fog, clouds, water, etc.) along the ray. Signed distance fields doesn't really help you with participating media rendering since it's a method of finding the ray intersection instead of helping with volume integration.&#xD;&#xA;&#xD;&#xA;So when you perform ray marching along the ray for volume integration, for each step you need to calculate incoming light to that point and evaluate the &quot;phase function&quot; to calculate how much of that light scatters towards the eye. This phase function can be simple isotropic function (i.e. constant $\frac{\rho}{4\pi}$) or more complex anisotropic function such as Mie phase function shown below, depending on the modeled participating media.&#xD;&#xA;&#xD;&#xA;[![Mie Phase Function][1]][1]&#xD;&#xA;&#xD;&#xA;Additionally you need to take the extinction coefficient of the media into account, which is spatially varying for heterogeneous media, for calculating transmittance and to properly &quot;attenuate&quot; the in-scattered light as it's being blocked by media between eye and the point ([Beer-Lambert law][2]). This approach assumes homogeneous media between steps and for proper physically based integration you could take a look at SIGGRAPH 2015 presentation &quot;[Physically-based &amp; Unified Volumetric Rendering in Frostbite][3]&quot; by Sebastien Hillaire.&#xD;&#xA;&#xD;&#xA;To know how much light reaches a point in space for each of those ray steps, you can use path tracing. This can get quite expensive though since light can take random paths in the media until it reaches the point. This is known as &quot;multiple scattering&quot;, which is analogous to indirect illumination. When performing the integration over the sphere for each step along the ray, you can use [Woodcock tracking][4] to get unbiased results for heterogeneous media. Also if you use Mie phase function you should use importance sampling as the phase function has very strong forward peak.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WR0ZN.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law&#xD;&#xA;  [3]: http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/&#xD;&#xA;  [4]: http://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10035" PostHistoryTypeId="2" PostId="4415" RevisionGUID="d8ad027f-5931-4468-9778-7e3622e49df9" CreationDate="2016-12-25T20:37:04.397" UserId="2654" Text="&gt; Now this texture coordinates supposed to be updated for each vertex processed by vertex shader because i set the glVertexAttribDivisor() to 0 which means it should be.&#xD;&#xA;&#xD;&#xA;No, it doesn't.&#xD;&#xA;&#xD;&#xA;A divisor of 0 means that the texture coordinate work *exactly* as if you hadn't called `glVertexAttribDivisor` for that attribute at all. 0 is not a special case; it's the *default*.&#xD;&#xA;&#xD;&#xA;That means that the texture coordinate will be updated at the same rate as the position. So it will get the same value *for each instance*, exactly like it does for the positions.&#xD;&#xA;&#xD;&#xA;There is no way to use instancing to get an attribute to always increase. It either is a per-instance attribute (changing more-or-less based on `gl_InstanceID`) or it is a per-vertex attribute (changing based on `gl_VertexID`). To get the per-instance behavior, you use a divisor 1 or greater. To get the per-vertex behavior, you use a divisor of 0." ContentLicense="CC BY-SA 3.0" />
  <row Id="10040" PostHistoryTypeId="2" PostId="4417" RevisionGUID="6f2c84da-41fd-4029-b854-05bfbf7e9242" CreationDate="2016-12-26T03:43:09.017" UserId="2096" Text="Is there any tool available for debugging GLSL shaders? &#xA;&#xA;I have nvidia geForce 940m GPU which doesn't support Nvidia NSight and RenderDoc is great but it doesn't support GLSL shader debugging. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10041" PostHistoryTypeId="1" PostId="4417" RevisionGUID="6f2c84da-41fd-4029-b854-05bfbf7e9242" CreationDate="2016-12-26T03:43:09.017" UserId="2096" Text="GLSL shader debugging" ContentLicense="CC BY-SA 3.0" />
  <row Id="10042" PostHistoryTypeId="3" PostId="4417" RevisionGUID="6f2c84da-41fd-4029-b854-05bfbf7e9242" CreationDate="2016-12-26T03:43:09.017" UserId="2096" Text="|opengl|glsl|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10045" PostHistoryTypeId="5" PostId="4417" RevisionGUID="c5bf70b0-4ed7-4703-ab29-fce7ccefe4ff" CreationDate="2016-12-26T07:52:07.330" UserId="2096" Comment="added 22 characters in body" Text="Is there any tool available for debugging GLSL shaders? &#xA;&#xA;I have nvidia geForce 940m GPU which doesn't support Nvidia NSight and RenderDoc is great but it doesn't support GLSL shader debugging. I am using windows 10." ContentLicense="CC BY-SA 3.0" />
  <row Id="10046" PostHistoryTypeId="10" PostId="4417" RevisionGUID="e869fdc9-dfbe-4118-a67e-eb836a4c3ddb" CreationDate="2016-12-26T11:36:55.020" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="10047" PostHistoryTypeId="2" PostId="4418" RevisionGUID="dfa1fa94-f8c4-4d62-b276-fe44f43e47ee" CreationDate="2016-12-26T17:42:10.087" UserId="5724" Text="Right now, all current monitors use three (or four*) primary colors to create their color, which could never allow them to produce all colors that can be seen by the human eye; in fact, their colors will always be inside a triangle on the xyY diagram of all possible colors**.&#xD;&#xA;&#xD;&#xA;But we could decide to replace these color filters with something such as Lyot filters***, which can be tuned, similarly to LCDs, to allow only light whose wavelength is higher/lower than a certain value to pass through. &#xD;&#xA;&#xD;&#xA;This would mean that we could basically create color filters that can be adjusted to produce any color, by replacing each pixel with two stacked filters, which allow a range $[a, b]$ to pass, and a third filter next to it which allows the range $[c,\infty)$ to pass through.&#xD;&#xA;&#xD;&#xA;Using Mathematica, I [have tested][4] that a mapping between these three values is enough to create any possible $x$, $y$ and $Y$ in the CIE xyY color space:&#xD;&#xA;&#xD;&#xA;[![Plot of mapping][5]][5]&#xD;&#xA;&#xD;&#xA;So, in other words, the range of &#xD;&#xA;$$\text{XYZ}(a,b,c)=\int_{[a,b]\cup[c,\infty)}\text{I}(\lambda)\cdot(\overline{x}(\lambda),\overline{y}(\lambda),\overline{z}(\lambda))$$&#xD;&#xA;&#xD;&#xA;, where $\text{I}$ is the illuminant, is enough to produce the color of any object that can be illuminated by that illuminant.&#xD;&#xA;&#xD;&#xA;So, my questions are: &#xD;&#xA;&#xD;&#xA; * Are there already any such displays that can produce any visible color, and if not, then why not?&#xD;&#xA; * Could this actually be done in practice?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*https ://en.wikipedia.org/wiki/Quattron    &#xD;&#xA;**https ://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/CIE1931xy_gamut_comparison.svg/512px-CIE1931xy_gamut_comparison.svg.png    &#xD;&#xA;***https ://en.wikipedia.org/wiki/Lyot_filter    &#xD;&#xA;^ Sorry, I had to do this because I need 10 reputation to post more than 2 links.&#xD;&#xA;&#xD;&#xA;  [4]: http://pastebin.com/eQkpqHZV&#xD;&#xA;  [5]: https://i.stack.imgur.com/66aT9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10048" PostHistoryTypeId="1" PostId="4418" RevisionGUID="dfa1fa94-f8c4-4d62-b276-fe44f43e47ee" CreationDate="2016-12-26T17:42:10.087" UserId="5724" Text="Display that supports full CIE xyY color space" ContentLicense="CC BY-SA 3.0" />
  <row Id="10049" PostHistoryTypeId="3" PostId="4418" RevisionGUID="dfa1fa94-f8c4-4d62-b276-fe44f43e47ee" CreationDate="2016-12-26T17:42:10.087" UserId="5724" Text="|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10050" PostHistoryTypeId="5" PostId="4418" RevisionGUID="21647a31-73ad-459c-b5f6-ebc55289a17d" CreationDate="2016-12-26T18:03:56.657" UserId="5724" Comment="deleted 92 characters in body" Text="Right now, all current monitors use three (or [four][1]) primary colors to create their color, which could never allow them to produce all colors that can be seen by the human eye; [in fact, their colors will always be inside a triangle on the xyY diagram of all possible colors][2].&#xD;&#xA;&#xD;&#xA;But we could decide to replace these color filters with something such as [Lyot filters][3], which can be tuned, similarly to LCDs, to allow only light whose wavelength is higher/lower than a certain value to pass through. &#xD;&#xA;&#xD;&#xA;This would mean that we could basically create color filters that can be adjusted to produce any color, by replacing each pixel with two stacked filters, which allow a range $[a, b]$ to pass, and a third filter next to it which allows the range $[c,\infty)$ to pass through.&#xD;&#xA;&#xD;&#xA;Using Mathematica, I [have tested][4] that a mapping between these three values is enough to create any possible $x$, $y$ and $Y$ in the CIE xyY color space:&#xD;&#xA;&#xD;&#xA;[![Plot of mapping][5]][5]&#xD;&#xA;&#xD;&#xA;So, in other words, the range of &#xD;&#xA;$$\text{XYZ}(a,b,c)=\int_{[a,b]\cup[c,\infty)}\text{I}(\lambda)\cdot(\overline{x}(\lambda),\overline{y}(\lambda),\overline{z}(\lambda))$$&#xD;&#xA;&#xD;&#xA;, where $\text{I}$ is the illuminant, is enough to produce the color of any object that can be illuminated by that illuminant.&#xD;&#xA;&#xD;&#xA;So, my questions are: &#xD;&#xA;&#xD;&#xA; * Are there already any such displays that can produce any visible color, and if not, then why not?&#xD;&#xA; * Could this actually be done in practice?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Quattron&#xD;&#xA;  [2]: https://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/CIE1931xy_gamut_comparison.svg/512px-CIE1931xy_gamut_comparison.svg.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Lyot_filter&#xD;&#xA;  [4]: http://pastebin.com/eQkpqHZV&#xD;&#xA;  [5]: https://i.stack.imgur.com/66aT9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10057" PostHistoryTypeId="2" PostId="4420" RevisionGUID="ba6ae651-3000-4936-9c4b-39f1d767619d" CreationDate="2016-12-27T07:02:41.813" UserId="38" Text="No, most likely these kinds of displays do not exist. Altough the negative is hard to prove. And in this case i dont have deep enough understanding of the lore.&#xD;&#xA;&#xD;&#xA;Reason for me saying this is that usable displays need some serious minituarisation. The minituarisation process is quite expensive and requires some serious investment. There should be quite massive patent trail if this was indeed true. So we should look in patent databases for this trail.&#xD;&#xA;&#xD;&#xA;Second, having such tech probably will not yield full colorspace, atleast initially. Because the filter can only filter out colors that the back light can generate. Most probably therefore this is somekind of projector technology at first. Also filters probably have a practical limit to how much they can be tuned.&#xD;&#xA;&#xD;&#xA;Third, if/when such tech is available it must recuperate the development cost by selling enough units to overcome the capital investment. There is a likelyhood that this is one of those thigs that can not be produced without the minituarisation step like digital cameras. So keep a lookout for a killer application for this tech." ContentLicense="CC BY-SA 3.0" />
  <row Id="10058" PostHistoryTypeId="5" PostId="4420" RevisionGUID="779dfb04-820b-4871-a86a-378e8bb1aa29" CreationDate="2016-12-27T07:40:45.680" UserId="38" Comment="added 298 characters in body" Text="No, most likely these kinds of displays do not exist. Although the negative is hard to prove. And in this case i don't have deep enough understanding of the lore.&#xD;&#xA;&#xD;&#xA;Reason for me saying this is that usable displays need some serious miniaturization. The miniaturization process is quite expensive and requires some serious investment. There should be quite massive patent trail if this was indeed true. So we should look in patent databases for this trail.&#xD;&#xA;&#xD;&#xA;Second, having such tech probably will not yield full color space, at least initially. Because the filter can only filter out colors that the back light can generate. Most probably therefore this is some kind of projector technology at first. Also filters probably have a practical limit to how much they can be tuned.&#xD;&#xA;&#xD;&#xA;Third, if/when such tech is available it must recuperate the development cost by selling enough units to overcome the capital investment. There is a likelihood that this is one of those things that can not be produced without the miniaturization step like digital cameras. So keep a lookout for a killer application for this tech.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some major downsides of this kind of tech is the fact that you filter out light. This means it eats up part of the energy input. This leads to a heat dissipation problem, which for perfect narrow band filters is actually pretty huge part of the emitted light. Lot of energy goes wasted, and needs to be engineered around." ContentLicense="CC BY-SA 3.0" />
  <row Id="10062" PostHistoryTypeId="2" PostId="4422" RevisionGUID="08260813-ca96-4463-926d-abd787a2e907" CreationDate="2016-12-27T08:51:10.870" UserId="110" Text="Often a similar hardware feature is exposed via DirectX and OpenGL using different terminology. &#xD;&#xA;   &#xD;&#xA;For example:  &#xD;&#xA;[Constant Buffer][1] / [Uniform Buffer Object][2]  &#xD;&#xA;[RWBuffer][3] / [SSBO][4] (I think)&#xD;&#xA; &#xD;&#xA;I am looking for an exhaustive chart that describes DirectX terminology is used in OpenGL, and vice-versa.  &#xD;&#xA;Where can I find such a resource?  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476898(v=vs.85).aspx#Shader_Constant_Buffer&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471472(v=vs.85).aspx&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="10063" PostHistoryTypeId="1" PostId="4422" RevisionGUID="08260813-ca96-4463-926d-abd787a2e907" CreationDate="2016-12-27T08:51:10.870" UserId="110" Text="DirectX / OpenGL(Vulkan) concepts mapping chart" ContentLicense="CC BY-SA 3.0" />
  <row Id="10064" PostHistoryTypeId="3" PostId="4422" RevisionGUID="08260813-ca96-4463-926d-abd787a2e907" CreationDate="2016-12-27T08:51:10.870" UserId="110" Text="|api|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10065" PostHistoryTypeId="5" PostId="4422" RevisionGUID="4d0526e1-f024-4aac-8871-076260ff5c89" CreationDate="2016-12-27T15:19:58.300" UserId="110" Comment="added 29 characters in body" Text="Often a similar hardware feature is exposed via DirectX and OpenGL using different terminology. &#xD;&#xA;   &#xD;&#xA;For example:  &#xD;&#xA;[Constant Buffer][1] / [Uniform Buffer Object][2]  &#xD;&#xA;[RWBuffer][3] / [SSBO][4] (I think)&#xD;&#xA; &#xD;&#xA;I am looking for an exhaustive chart that describes which DirectX terminology is used to refer to which OpenGL concept, and vice-versa.  &#xD;&#xA;Where can I find such a resource?  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476898(v=vs.85).aspx#Shader_Constant_Buffer&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471472(v=vs.85).aspx&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="10066" PostHistoryTypeId="2" PostId="4423" RevisionGUID="b739f2c9-8386-487c-adab-76e707d9ea14" CreationDate="2016-12-27T16:08:51.790" UserId="5556" Text="The answer should be a theoretical no for any tri-light system, or even four light.&#xA;&#xA;The reason is, if you examine the original CIE RGB primaries, you will see that the positions of the three CIE 1931 lights correspond to the tips of the triangle in the spectral locus image here:&#xA;&#xA;[CIE 1931 test][1]&#xA;&#xA;If you look closely, you will see that along the edges of the green red axis, and the red blue, that there is some &quot;escape&quot; of the values where the primaries mixed cannot replicate the range of visible lights that the experimental observers were attempting to replicate.&#xA;&#xA;What we learn from this is that any combination of tristimulus physical lamps *can never* encompass the entire spectral locus shape.&#xA;&#xA;In order to fully enclose the unique shape of the spectral locus, it would require using primaries that consist of imaginary visual lamps that would form a triangle well beyond the spectral locus tips. Examples include the imaginary XYZ lamps, or the ACES lamps. Those lamps of course do not exist in the physical sense.&#xA;&#xA;So with all of that said, is it plausible that such a display could exist in the future? Absolutely. If we switch to a 40 lamp display, or something close to that, we could replicate the various wavelengths that enclose the entire shape of the spectral locus and fully encapsulate the CIE standard observer response.&#xA;&#xA;  [1]: https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/CIE1931xy_CIERGB.svg/990px-CIE1931xy_CIERGB.svg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10067" PostHistoryTypeId="2" PostId="4424" RevisionGUID="a82019ef-83a6-4955-8e0f-df17f837810c" CreationDate="2016-12-27T16:29:44.280" UserId="5556" Text="There has been quite some research into this using Barten contrast sensitivity function. It is the current formula behind the Dolby Perceptual Quantizer as featured in SMPTE 2084 and HDR10.&#xD;&#xA;&#xD;&#xA;This, coupled with a colour appearance model such as the work behind Dr. Mark Fairchild's CIECAM02, can result in very accurate predictions of quantization depth." ContentLicense="CC BY-SA 3.0" />
  <row Id="10068" PostHistoryTypeId="5" PostId="4420" RevisionGUID="a4209faa-cc65-42ce-a461-65de1eacf248" CreationDate="2016-12-27T16:30:16.040" UserId="38" Comment="added 34 characters in body" Text="No, most likely these kinds of displays do not exist, at the time of writing this post. Although the negative is hard to prove. And in this case i don't have deep enough understanding of the lore.&#xD;&#xA;&#xD;&#xA;Reason for me saying this is that usable displays need some serious miniaturization. The miniaturization process is quite expensive and requires some serious investment. There should be quite massive patent trail if this was indeed true. So we should look in patent databases for this trail.&#xD;&#xA;&#xD;&#xA;Second, having such tech probably will not yield full color space, at least initially. Because the filter can only filter out colors that the back light can generate. Most probably therefore this is some kind of projector technology at first. Also filters probably have a practical limit to how much they can be tuned.&#xD;&#xA;&#xD;&#xA;Third, if/when such tech is available it must recuperate the development cost by selling enough units to overcome the capital investment. There is a likelihood that this is one of those things that can not be produced without the miniaturization step like digital cameras. So keep a lookout for a killer application for this tech.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some major downsides of this kind of tech is the fact that you filter out light. This means it eats up part of the energy input. This leads to a heat dissipation problem, which for perfect narrow band filters is actually pretty huge part of the emitted light. Lot of energy goes wasted, and needs to be engineered around." ContentLicense="CC BY-SA 3.0" />
  <row Id="10069" PostHistoryTypeId="5" PostId="4408" RevisionGUID="54029d5e-2915-46b2-945a-80ed49ebdb26" CreationDate="2016-12-27T16:30:53.710" UserDisplayName="user2500" Comment="added 372 characters in body" Text="GPUs can efficiently scale an image by an arbitrary amount (within limits - display options fall within those limits by design) either using a 3D rendering operation or as the signal is sent from GPU to the display. Both of these paths have fully dedicated hardware for the arbitrary resizing and are not likely to be optimized for doubling or halving. Both support a technique called &quot;bilinear filtering&quot; though advances in display hardware may provide higher quality.&#xD;&#xA;&#xD;&#xA;If a game is run at non native resolution on a laptop (TVs and desktop displays have their own scalers, but laptop displays generally rely on the GPU), one of these two methods will be used. Display scaling is essentially &quot;free&quot;, so it is preferred and the lower the resolution the game is originally rendered the faster the frame rate (or the lower power consumption) - with no special performance benefit for, say, doubling. If a 3D operation is required (say, due to a limitation or issue in the display scaler), the scale operation is not free, but is going to go up with the source and destination sizes smoothly, with no special casing at doubling/halving.&#xD;&#xA;&#xD;&#xA;The game may look far better at certain scaling factors, but that's up to the user to decide.&#xD;&#xA;&#xD;&#xA;Edit: The intuition behind the question is correct: if GPUs didn't have dedicated scaling hardware, doubling/halving could implemented more efficiently than arbitrary scaling, either in shader code or via a slightly simpler hardware design - though the 3D rendering operation is a requirement of graphics APIs and display scaling is a requirement from systems vendors." ContentLicense="CC BY-SA 3.0" />
  <row Id="10071" PostHistoryTypeId="2" PostId="4425" RevisionGUID="b63d88f0-5dda-4748-af4b-68630c8367e4" CreationDate="2016-12-27T17:04:22.813" UserId="5556" Text="Offset.&#xA;&#xA;While any transform between two RGB colour spaces can be accomplished with a pure 3x3 matrix, some alternate transforms such as to YCbCr with given weights requires an offset." ContentLicense="CC BY-SA 3.0" />
  <row Id="10072" PostHistoryTypeId="5" PostId="4425" RevisionGUID="504373b3-918d-4ca8-ad7e-fc2840482f70" CreationDate="2016-12-27T17:54:32.507" UserId="5556" Comment="added 4 characters in body" Text="Offset.&#xD;&#xA;&#xD;&#xA;While any transform between two RGB colour spaces can be accomplished with a pure 3x3 matrix, some alternate transforms, such as to YCbCr with given weights, requires an offset." ContentLicense="CC BY-SA 3.0" />
  <row Id="10073" PostHistoryTypeId="5" PostId="4423" RevisionGUID="219c1ed6-b970-4174-81fe-b9bf5f4ed95e" CreationDate="2016-12-27T19:08:28.790" UserId="5556" Comment="deleted 37 characters in body" Text="The answer should be a theoretical no for any tri-light system, or even four light.&#xD;&#xA;&#xD;&#xA;The reason is, if you examine the original CIE RGB primaries, you will see that the positions of the three CIE 1931 lights correspond to the tips of the triangle in the spectral locus image here:&#xD;&#xA;&#xD;&#xA;[![CIE versus Imaginary Colours][1]][1]&#xD;&#xA;&#xD;&#xA;If you look closely, you will see that along the edges of the green red axis, and the red blue, that there is some &quot;escape&quot; of the values where the primaries mixed cannot replicate the range of visible lights that the experimental observers were attempting to replicate.&#xD;&#xA;&#xD;&#xA;What we learn from this is that any combination of tristimulus physical lamps *can never* encompass the entire spectral locus shape.&#xD;&#xA;&#xD;&#xA;In order to fully enclose the unique shape of the spectral locus, it would require using primaries that consist of imaginary visual lamps that would form a triangle well beyond the spectral locus tips. Examples include the imaginary XYZ lamps, or the ACES lamps. Those lamps of course do not exist in the physical sense.&#xD;&#xA;&#xD;&#xA;So with all of that said, is it plausible that such a display could exist in the future? Absolutely. If we switch to a 40 lamp display, or something close to that, we could replicate the various wavelengths that enclose the entire shape of the spectral locus and fully encapsulate the CIE standard observer response.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0aRqO.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10074" PostHistoryTypeId="2" PostId="4426" RevisionGUID="0d444a80-dd4a-4ed1-b082-e7de361fbb9d" CreationDate="2016-12-28T00:26:17.833" UserId="3003" Text="In addition to what the others have said, there are some practical issues with making such a display. It was mentioned in the comments that all current content is made for current display technologies, so having extra display capabilities wouldn't get you anything useful. Of course, if such displays were common, content would eventually come, right? Well, not necessarily. Where would it come from? Photos and video are produced either with film cameras or digital cameras. These have wider gamuts and higher dynamic range than current monitors, but I don't believe any of them cover the entire color space you're describing.&#xD;&#xA;&#xD;&#xA;Even if you did have ways of capturing the whole range or generating it you'd run into the problem that you'd need more bits per channel, and you'd need data structures and applications to interpret that data appropriately. Photoshop, for example, has supported working in 32-bit per channel float for a while, but many of its functions are unavailable in that mode. Next would be the playback apps. Then all the services that stream stuff to our devices would need to be updated, too. That would mean new codecs, too.&#xD;&#xA;&#xD;&#xA;The fact is, this *is* happening. Apple and other manufacturers are starting to use wider gamut displays on their consumer devices (the iMac and iPhone, for example). UHD content is being made for both televisions and consoles, and the display hardware is now available for them. As display gamuts get wider color gamuts (currently most wide displays are DCI-P3 or a variation thereof) and higher dynamic range the software will get written to display properly on them, then codecs will get written store and stream such data. I predict that after P3 displays are the norm, we'll make the next step to something wider like Rec. 2020, and then onto something even wider like ACES-CG. Will it ever cover the whole gamut, and the dynamic range of the eye? Probably someday. Someday soon? Probably not. But in 20-50 years, I could see it being the norm. In the meantime there's a lot of infrastructure that needs to be updated to support it, and it's going to be slow to get it all working properly." ContentLicense="CC BY-SA 3.0" />
  <row Id="10075" PostHistoryTypeId="5" PostId="4422" RevisionGUID="37b647e0-f0e9-4944-9b9d-718661e4e1dd" CreationDate="2016-12-28T02:37:01.263" UserId="110" Comment="added 44 characters in body" Text="Often a similar hardware feature is exposed via DirectX and OpenGL using different terminology. &#xD;&#xA;   &#xD;&#xA;For example:  &#xD;&#xA;[Constant Buffer][1] / [Uniform Buffer Object][2]  &#xD;&#xA;&lt;strike&gt;[RWBuffer][3] / [SSBO][4]&lt;/strike&gt; (They are actually not that similar)&#xD;&#xA; &#xD;&#xA;I am looking for an exhaustive chart that describes which DirectX terminology is used to refer to which OpenGL concept, and vice-versa.  &#xD;&#xA;Where can I find such a resource?  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476898(v=vs.85).aspx#Shader_Constant_Buffer&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471472(v=vs.85).aspx&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="10076" PostHistoryTypeId="2" PostId="4427" RevisionGUID="ad319f0f-accf-4c7c-bc09-9a271d9eaf0b" CreationDate="2016-12-28T03:56:07.543" UserId="5519" Text="I am posting this for anyone wondering about the confusion between the terms $\frac{1}{\pi}$ and $\frac{1}{4}$.&#xD;&#xA;&#xD;&#xA;The term $\frac{1}{\pi}$ is an error from the original Cook-Torrance reference. &#xD;&#xA;&#xD;&#xA;In fact, the whole term $\frac{1}{4(n \cdot \omega_i)}$ comes from the Jacobian of the transformation from reflected solid angle to normal solid angle.&#xD;&#xA;&#xD;&#xA;According to most papers, the $\frac{1}{4}$ term first appeared in [[Torrance, 67]](http://www.graphics.cornell.edu/~westin/pubs/TorranceSparrowJOSA1967.pdf).&#xD;&#xA;&#xD;&#xA;For a nice explanation of the term, you should check [[Nayar, 91]](http://www1.cs.columbia.edu/CAVE/publications/pdfs/Nayar_PAMI91.pdf), appendix D. Here is an image from the same paper:&#xD;&#xA;&#xD;&#xA;![](https://i.gyazo.com/07d01de3a8ad87c74b1c506a36df1460.png)&#xD;&#xA;$$&#xD;&#xA;   d\omega' = \frac{d\omega_r}{4\cos{\theta_i'}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Also, Joe Stam agrees with Nayar's $\frac{1}{4}$ term in [Stam 01, An Illumination Model for a Skin Layer Bounded by Rough Surfaces] , appendix B.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10077" PostHistoryTypeId="5" PostId="4422" RevisionGUID="a546b1be-537b-46ef-8c25-31c6083d68d3" CreationDate="2016-12-28T06:08:53.740" UserId="110" Comment="revert changes" Text="Often a similar hardware feature is exposed via DirectX and OpenGL using different terminology. &#xD;&#xA;   &#xD;&#xA;For example:  &#xD;&#xA;[Constant Buffer][1] / [Uniform Buffer Object][2]  &#xD;&#xA;[RWBuffer][3] / [SSBO][4]&#xD;&#xA; &#xD;&#xA;I am looking for an exhaustive chart that describes which DirectX terminology is used to refer to which OpenGL concept, and vice-versa.  &#xD;&#xA;Where can I find such a resource?  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476898(v=vs.85).aspx#Shader_Constant_Buffer&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff471472(v=vs.85).aspx&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="10089" PostHistoryTypeId="2" PostId="4429" RevisionGUID="91f958f5-c39e-4511-9b44-d4e63bc06fdd" CreationDate="2016-12-28T17:08:35.083" UserId="5740" Text="I searched for Z Buffer on Google and I discovered that's a 2 dimensional array used by the graphical card and whose aim is to enable the handling of two pixels' depth in order to display one of these pixels in front of the other.&#xD;&#xA;&#xD;&#xA;Don't panic ! **To illustrate my words**, let an image which has only 1 pixel.&#xD;&#xA;&#xD;&#xA;# What is a Z-Buffer ? What is its utility ?&#xD;&#xA;&#xD;&#xA;## Introduction&#xD;&#xA;Let P_1 the pixel we want to draw in front of P_2 (thus, P_1 will hide P_2 at drawing). So P_1 and P_2 have the same X and Y coordinates.&#xD;&#xA;&#xD;&#xA;We decide that the Z coordinate of P_1 (ie. : its depth) is lesser than P_2's one (it means P_1 is closer from the computer's user than P_2) : Z(P_1) = 1, and Z(P_2) = 2.&#xD;&#xA;&#xD;&#xA;Our Z-Buffer has, by definition, the same size than our image : 1 case. Each case of the Z-Buffer contains one pixel's depth and each case is associated with each image's pixel.&#xD;&#xA;&#xD;&#xA;First, we initialize the (only one) case of our Z Buffer at the maximum value we can store in its cases (depending on the Z Buffer's type, on the OS, etc. : double ? float ? integer ?).&#xD;&#xA;&#xD;&#xA;## P_1&#xD;&#xA;Now, we want to first draw P_1. The Z Buffer is used : the depth of his (X(P_1) ; Y(P_1)) case's value is compared to the P_1's depth. Of course, Z(P_1) is lesser than Z( (X(P_1) ; Y(P_1)) ). The results of this comparison are : first, we replace the old case value with the new Z value (which is : Z(P_1) ) ; then, P_1 is drawn.&#xD;&#xA;&#xD;&#xA;# P_2&#xD;&#xA;Finally, we want to draw P_2. Again the Z Buffer is used. (X(P_2) ; Y(P_2)) case's value is compared to Z(P_2) (note that : X(P_2) = X(P_1) and Y(P_2) = Y(P_1) - cf. &quot;So P_1 and P_2 have the same X and Y coordinates.&quot;).&#xD;&#xA;The results of this comparision are : (Z(P_2) = 2) is superior to ( Z( (X(P_2) ; Y(P_2)) ) = 1) ; first, we don't replace any case ; then, P_2 is not drawn.&#xD;&#xA;&#xD;&#xA;That's how a Z Buffer is used to display a pixel in front of another.&#xD;&#xA;&#xD;&#xA;## Example of application&#xD;&#xA;http://raphaello.univ-fcomte.fr/IG/ZBuffer/Images/ZBuffer-03.gif**&#xD;&#xA;&#xD;&#xA;# Z-Fighting&#xD;&#xA;&#xD;&#xA;## What is Z-Fighting ?&#xD;&#xA;If two polygons are very closed AND (note the &quot;AND&quot;) if the camera is moving, Z-Fighting phenomenon appears : https://icculus.org/neverball/mapping/zfighting.png&#xD;&#xA;&#xD;&#xA;## How to reproduce Z-Fighting (ie. : how does it works ? why does it appear ?)&#xD;&#xA;&#xD;&#xA;I know Z Fighting is caused by the resolution in depth of the Z Buffer, due to some conversion/casts mathematical and precision errors. But I don't understand it...&#xD;&#xA;&#xD;&#xA;In particular, I don't understand why the camera must moves.&#xD;&#xA;&#xD;&#xA;My question is : could you explain me please ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10090" PostHistoryTypeId="1" PostId="4429" RevisionGUID="91f958f5-c39e-4511-9b44-d4e63bc06fdd" CreationDate="2016-12-28T17:08:35.083" UserId="5740" Text="How to understand Z-Fighting?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10091" PostHistoryTypeId="3" PostId="4429" RevisionGUID="91f958f5-c39e-4511-9b44-d4e63bc06fdd" CreationDate="2016-12-28T17:08:35.083" UserId="5740" Text="|polygon|z-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10092" PostHistoryTypeId="5" PostId="4413" RevisionGUID="c3bca904-f339-4eb2-a090-acf3de9ab9a0" CreationDate="2016-12-28T18:17:37.793" UserId="6" Comment="Improved formatting and spelling. Removed idle chatter." Text="I want to draw a string of text with a single draw call (Instancing). I am reading a bitmap for each character texture. I want to pass the texture coordinates for each vertex of a quad (a single character). Now these texture coordinates are supposed to be updated for each vertex processed by the vertex shader because I set the `glVertexAttribDivisor()` to 0 which means it should be. But it's not happening.&#xD;&#xA;&#xD;&#xA;Here's the source code where I am sending the data to the GPU...&#xD;&#xA;&#xD;&#xA;    //TEXTURE COORDS&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, mVBOTexCoords);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*mTexCoords.size(), mTexCoords.data(), GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(3);&#xD;&#xA;    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;        &#xD;&#xA;    glVertexAttribDivisor(3,0);&#xD;&#xA;&#xD;&#xA;and the vertex shader...&#xD;&#xA;&#xD;&#xA;    #version 400 &#xD;&#xA;&#xD;&#xA;    out vec2 tex_coords;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec2 pos;&#xD;&#xA;    layout(location = 1) in vec2 offset;&#xD;&#xA;    layout(location = 2) in vec2 scale;&#xD;&#xA;    layout(location = 3) in vec2 tex;&#xD;&#xA;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        tex_coords = tex;&#xD;&#xA;&#xD;&#xA;	 vec4 position = vec4(pos,0.0f,1.0f);&#xD;&#xA;         position.xy*=scale;&#xD;&#xA;         position.xy+=offset;&#xD;&#xA;&#xD;&#xA;         gl_Position = projection*position;&#xD;&#xA;	&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Sorry for the mess. I hope you get it. I am not getting why its not updating the texture coordninates for each vertex.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10093" PostHistoryTypeId="24" PostId="4413" RevisionGUID="c3bca904-f339-4eb2-a090-acf3de9ab9a0" CreationDate="2016-12-28T18:17:37.793" Comment="Proposed by 6 approved by 2096 edit id of 188" ContentLicense="CC BY-SA 3.0" />
  <row Id="10094" PostHistoryTypeId="2" PostId="4430" RevisionGUID="598b26f2-103f-41f9-82c1-fdc731d5c0af" CreationDate="2016-12-28T18:21:08.453" UserId="5717" Text="The camera does not need to move for this problem to exist. You can see the mixed polygons as in your linked image even with a static camera.&#xD;&#xA;&#xD;&#xA;Things are worse with a moving camera because it makes the position of the polygons change, which can lead to different rounding. This means it may not be the same polygon which comes up in front at a given location for every frame. Even a very small change in the camera could swap which polygon is visible. So you get flickering which is visually a lot worse because it draws attention.&#xD;&#xA;&#xD;&#xA;One possible solution is to progressively blend surfaces together when their Z values become too similar. However, I'm not certain how easily that can be implemented in traditional Z-buffer rendering." ContentLicense="CC BY-SA 3.0" />
  <row Id="10095" PostHistoryTypeId="2" PostId="4431" RevisionGUID="88469ca8-0559-4020-9aef-fba34904d76b" CreationDate="2016-12-28T18:53:04.913" UserId="2096" Text="It's the stage in the graphics pipeline which is used to determine whether one pixel is in front or back of the other pixel. It is done by having a buffer known as z-buffer which stores z values (distance from the viewer) for each fragment. Z-fighting can happen for couple of reasons. One of the reason can be floating point precision of the depth buffer. This tutorial explains everything in a simple way about Depth testing and Z-fighting and also discusses about the solutions to avoid them..&#xD;&#xA;https://learnopengl.com/#!Advanced-OpenGL/Depth-testing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10096" PostHistoryTypeId="5" PostId="4431" RevisionGUID="4a223c98-54d0-4b9e-9df1-d4766ac1e0e6" CreationDate="2016-12-28T18:58:12.637" UserId="2096" Comment="added 98 characters in body" Text="It's the stage in the graphics pipeline which is used to determine whether one pixel is in front or back of the other pixel. It is done by having a buffer known as z-buffer which stores z values (distance from the viewer) for each fragment. Z-fighting happens when depth buffer doesn't have enough enough floating point precision to compare two very close z values. Sometimes two z values are so close to each other that they need higher precision to be compared. This tutorial explains everything in a simple way about Depth testing and Z-fighting and also discusses about the solutions to avoid them..&#xD;&#xA;https://learnopengl.com/#!Advanced-OpenGL/Depth-testing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10097" PostHistoryTypeId="5" PostId="4431" RevisionGUID="2e54d6ce-2c06-4054-afa8-f6b8250187f6" CreationDate="2016-12-28T19:19:30.913" UserId="2096" Comment="added 70 characters in body; added 110 characters in body" Text="Z-fighting is not related with camera movement. But this issue can be avoided by moving near plane of the view frustum a little further away from the viewer. As you know, depth testing the stage in the graphics pipeline which is used to determine whether one pixel is in front or back of the other pixel. It is done by having a buffer known as z-buffer which stores z values (distance from the viewer) for each fragment. Z-fighting happens when depth buffer doesn't have enough enough floating point precision to compare two very close z values. Sometimes two z values are so close to each other that they need higher precision to be compared. This tutorial explains everything in a simple way about Depth testing and Z-fighting and also discusses about the solutions to avoid them..&#xD;&#xA;https://learnopengl.com/#!Advanced-OpenGL/Depth-testing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10098" PostHistoryTypeId="2" PostId="4432" RevisionGUID="1310e24e-3d1f-49d9-bfac-0d492eedefe3" CreationDate="2016-12-28T20:29:30.783" UserId="48" Text="I haven't been able to find such a chart on the web, so I made one here. (Everyone, feel free to add, elaborate, or correct any mistakes. Some of these are just best guesses based on a partial understanding of the API and hardware internals.)&#xD;&#xA;&#xD;&#xA;## API Basics&#xD;&#xA;&#xD;&#xA;    D3D11                          OpenGL 4.x&#xD;&#xA;    -----                          ----------&#xD;&#xA;    device                         context&#xD;&#xA;    immediate context              (implicit; no specific name)&#xD;&#xA;    deferred context               (no cross-vendor equivalent, but see GL_NV_command_list)&#xD;&#xA;    swap chain                     (implicit; no specific name)&#xD;&#xA;    (no cross-vendor equivalent)   extensions&#xD;&#xA;    debug layer; info queue        GL_KHR_debug extension&#xD;&#xA;&#xD;&#xA;## Shaders&#xD;&#xA;&#xD;&#xA;    D3D11              OpenGL 4.x&#xD;&#xA;    -----              ----------&#xD;&#xA;    pixel shader       fragment shader&#xD;&#xA;    hull shader        tessellation control shader&#xD;&#xA;    domain shader      tessellation evaluation shader&#xD;&#xA;    (vertex shader, geometry shader, and compute shader are called the same in both)&#xD;&#xA;&#xD;&#xA;    registers          binding points&#xD;&#xA;    semantics          interface layouts&#xD;&#xA;    SV_Foo semantics   gl_Foo builtin variables&#xD;&#xA;&#xD;&#xA;    class linkage      subroutines&#xD;&#xA;&#xD;&#xA;    (no equivalent)    program objects; program linking&#xD;&#xA;&#xD;&#xA;    (D3D11's normal&#xD;&#xA;     behavior; no      separate shader objects&#xD;&#xA;     specific name)&#xD;&#xA;&#xD;&#xA;## Geometry and Drawing&#xD;&#xA;&#xD;&#xA;    D3D11              OpenGL 4.x&#xD;&#xA;    -----              ----------&#xD;&#xA;    vertex buffer      vertex attribute array buffer; vertex buffer object&#xD;&#xA;    index buffer       element array buffer&#xD;&#xA;    input layout       vertex array object (sort of)&#xD;&#xA;&#xD;&#xA;    Draw               glDrawArrays&#xD;&#xA;    DrawIndexed        glDrawElements&#xD;&#xA;    (instancing and indirect draw are called similarly in both)&#xD;&#xA;    (no equivalent)    multi-draw, e.g. glMultiDrawElements​&#xD;&#xA;&#xD;&#xA;    stream-out         transform feedback&#xD;&#xA;    DrawAuto           glDrawTransformFeedback​&#xD;&#xA;&#xD;&#xA;    predication        conditional rendering&#xD;&#xA;    (no equivalent)    sync objects&#xD;&#xA;&#xD;&#xA;## Buffers and Textures&#xD;&#xA;&#xD;&#xA;    D3D11                    OpenGL 4.x&#xD;&#xA;    -----                    ----------&#xD;&#xA;    constant buffer          uniform buffer object&#xD;&#xA;    typed buffer             texture buffer&#xD;&#xA;    structured buffer        (no specific name; subset of SSBO features)&#xD;&#xA;    UAV buffer               SSBO (shader storage buffer object)&#xD;&#xA;    UAV texture              image load/store&#xD;&#xA;    shader resource view     texture view&#xD;&#xA;&#xD;&#xA;    interlocked operations   atomic operations&#xD;&#xA;    append/consume buffer    SSBO + atomic counter&#xD;&#xA;&#xD;&#xA;    discard                  invalidate&#xD;&#xA;    (no equivalent)          persistent mapping&#xD;&#xA;    (D3D11's normal&#xD;&#xA;     behavior; no            immutable storage&#xD;&#xA;     specific name)&#xD;&#xA;    (implicitly inserted     glMemoryBarrier; glTextureBarrier&#xD;&#xA;     by the API)&#xD;&#xA;&#xD;&#xA;## Render Targets&#xD;&#xA;&#xD;&#xA;    D3D11                  OpenGL 4.x&#xD;&#xA;    -----                  ----------&#xD;&#xA;    (no equivalent)        framebuffer object&#xD;&#xA;    render target view     framebuffer color attachment&#xD;&#xA;    depth-stencil view     framebuffer depth-stencil attachment&#xD;&#xA;    resolve                blit multisampled buffer to non-multisampled one&#xD;&#xA;&#xD;&#xA;    texture array          layered image&#xD;&#xA;    (no equivalent)        renderbuffer&#xD;&#xA;&#xD;&#xA;## Queries&#xD;&#xA;&#xD;&#xA;    D3D11                       OpenGL 4.x&#xD;&#xA;    -----                       ----------&#xD;&#xA;    timestamp query             timer query&#xD;&#xA;    timestamp-disjoint query    (no equivalent)&#xD;&#xA;    (no equivalent)             time-elapsed query&#xD;&#xA;    occlusion query             samples-passed query&#xD;&#xA;    occlusion predicate query   any-samples-passed query&#xD;&#xA;    pipeline statistics query   (no equivalent in core, but see&#xD;&#xA;                                 GL_ARB_pipeline_statistics_query)&#xD;&#xA;    SO statistics query         primitives-generated/-written queries &#xD;&#xA;    (no equivalent)             query buffer object&#xD;&#xA;&#xD;&#xA;## Compute Shaders&#xD;&#xA;&#xD;&#xA;    D3D11                     OpenGL 4.x&#xD;&#xA;    -----                     ----------&#xD;&#xA;    thread                    invocation&#xD;&#xA;    thread group              work group&#xD;&#xA;    thread group size         local size&#xD;&#xA;    threadgroup variable      shared variable&#xD;&#xA;&#xD;&#xA;    group sync                &quot;plain&quot; barrier&#xD;&#xA;    group memory barrier      shared memory barrier&#xD;&#xA;    device memory barrier     atomic+buffer+image memory barriers&#xD;&#xA;    all memory barrier        group memory barrier&#xD;&#xA;&#xD;&#xA;## Other Resources&#xD;&#xA;&#xD;&#xA;* [Porting from DirectX11 to OpenGL 4.2](https://anteru.net/blog/2013/10/13/2188/) – not exhaustive, but a quick discussion of common porting issues&#xD;&#xA;* [MSDN: GLSL-to-HLSL porting guide](https://msdn.microsoft.com/en-us/windows/uwp/gaming/glsl-to-hlsl-reference) – lists correspondences and differences between GLSL and HLSL shading languages" ContentLicense="CC BY-SA 3.0" />
  <row Id="10101" PostHistoryTypeId="5" PostId="4432" RevisionGUID="d4e22ddf-9949-4f41-b7e7-2447966c92ca" CreationDate="2016-12-29T04:11:37.157" UserId="48" Comment="some additions and corrections; remove syntax highlighting" Text="I haven't been able to find such a chart on the web, so I made one here. (Everyone, feel free to add, elaborate, or correct any mistakes. Some of these are just best guesses based on a partial understanding of the API and hardware internals.)&#xD;&#xA;&#xD;&#xA;## API Basics&#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-none --&gt;&#xD;&#xA;&#xD;&#xA;    D3D11                          OpenGL 4.x&#xD;&#xA;    -----                          ----------&#xD;&#xA;    device                         context&#xD;&#xA;    immediate context              (implicit; no specific name)&#xD;&#xA;    deferred context               (no cross-vendor equivalent, but see&#xD;&#xA;                                    GL_NV_command_list)&#xD;&#xA;    swap chain                     (implicit; no specific name)&#xD;&#xA;    (no cross-vendor equivalent)   extensions&#xD;&#xA;    debug layer; info queue        GL_KHR_debug extension&#xD;&#xA;&#xD;&#xA;## Shaders&#xD;&#xA;&#xD;&#xA;    D3D11              OpenGL 4.x&#xD;&#xA;    -----              ----------&#xD;&#xA;    pixel shader       fragment shader&#xD;&#xA;    hull shader        tessellation control shader&#xD;&#xA;    domain shader      tessellation evaluation shader&#xD;&#xA;    (vertex shader, geometry shader, and compute shader&#xD;&#xA;     are called the same in both)&#xD;&#xA;&#xD;&#xA;    registers          binding points&#xD;&#xA;    semantics          interface layouts&#xD;&#xA;    SV_Foo semantics   gl_Foo builtin variables&#xD;&#xA;&#xD;&#xA;    class linkage      subroutines&#xD;&#xA;&#xD;&#xA;    (no equivalent)    program objects; program linking&#xD;&#xA;&#xD;&#xA;    (D3D11's normal&#xD;&#xA;     behavior; no      separate shader objects&#xD;&#xA;     specific name)&#xD;&#xA;&#xD;&#xA;## Geometry and Drawing&#xD;&#xA;&#xD;&#xA;    D3D11              OpenGL 4.x&#xD;&#xA;    -----              ----------&#xD;&#xA;    vertex buffer      vertex attribute array buffer; vertex buffer object&#xD;&#xA;    index buffer       element array buffer&#xD;&#xA;    input layout       vertex array object (sort of)&#xD;&#xA;&#xD;&#xA;    Draw               glDrawArrays&#xD;&#xA;    DrawIndexed        glDrawElements&#xD;&#xA;    (instancing and indirect draw are called similarly in both)&#xD;&#xA;    (no equivalent)    multi-draw, e.g. glMultiDrawElements​&#xD;&#xA;&#xD;&#xA;    stream-out         transform feedback&#xD;&#xA;    DrawAuto           glDrawTransformFeedback​&#xD;&#xA;&#xD;&#xA;    predication        conditional rendering&#xD;&#xA;    (no equivalent)    sync objects&#xD;&#xA;&#xD;&#xA;## Buffers and Textures&#xD;&#xA;&#xD;&#xA;    D3D11                    OpenGL 4.x&#xD;&#xA;    -----                    ----------&#xD;&#xA;    constant buffer          uniform buffer object&#xD;&#xA;    typed buffer             texture buffer&#xD;&#xA;    structured buffer        (no specific name; subset of SSBO features)&#xD;&#xA;    UAV buffer; RWBuffer     SSBO (shader storage buffer object)&#xD;&#xA;    UAV texture; RWTexture   image load/store&#xD;&#xA;&#xD;&#xA;    shader resource view     texture view&#xD;&#xA;    sampler state            sampler object&#xD;&#xA;&#xD;&#xA;    interlocked operations   atomic operations&#xD;&#xA;    append/consume buffer    SSBO + atomic counter&#xD;&#xA;&#xD;&#xA;    discard buffer/texture   invalidate buffer/texture&#xD;&#xA;    (no equivalent)          persistent mapping&#xD;&#xA;    (D3D11's normal&#xD;&#xA;     behavior; no            immutable storage&#xD;&#xA;     specific name)&#xD;&#xA;    (implicitly inserted     glMemoryBarrier; glTextureBarrier&#xD;&#xA;     by the API)&#xD;&#xA;&#xD;&#xA;## Render Targets&#xD;&#xA;&#xD;&#xA;    D3D11                     OpenGL 4.x&#xD;&#xA;    -----                     ----------&#xD;&#xA;    (no equivalent)           framebuffer object&#xD;&#xA;    render target view        framebuffer color attachment&#xD;&#xA;    depth-stencil view        framebuffer depth-stencil attachment&#xD;&#xA;    multisample resolve       blit multisampled buffer to non-multisampled one&#xD;&#xA;&#xD;&#xA;    multiple render targets   multiple color attachments&#xD;&#xA;    render target array       layered image&#xD;&#xA;&#xD;&#xA;    (no equivalent)           renderbuffer&#xD;&#xA;&#xD;&#xA;## Queries&#xD;&#xA;&#xD;&#xA;    D3D11                       OpenGL 4.x&#xD;&#xA;    -----                       ----------&#xD;&#xA;    timestamp query             timer query&#xD;&#xA;    timestamp-disjoint query    (no equivalent)&#xD;&#xA;    (no equivalent)             time-elapsed query&#xD;&#xA;    occlusion query             samples-passed query&#xD;&#xA;    occlusion predicate query   any-samples-passed query&#xD;&#xA;    pipeline statistics query   (no equivalent in core, but see&#xD;&#xA;                                 GL_ARB_pipeline_statistics_query)&#xD;&#xA;    SO statistics query         primitives-generated/-written queries &#xD;&#xA;    (no equivalent)             query buffer object&#xD;&#xA;&#xD;&#xA;## Compute Shaders&#xD;&#xA;&#xD;&#xA;    D3D11                     OpenGL 4.x&#xD;&#xA;    -----                     ----------&#xD;&#xA;    thread                    invocation&#xD;&#xA;    thread group              work group&#xD;&#xA;    thread group size         local size&#xD;&#xA;    threadgroup variable      shared variable&#xD;&#xA;&#xD;&#xA;    group sync                &quot;plain&quot; barrier&#xD;&#xA;    group memory barrier      shared memory barrier&#xD;&#xA;    device memory barrier     atomic+buffer+image memory barriers&#xD;&#xA;    all memory barrier        group memory barrier&#xD;&#xA;&#xD;&#xA;## Other Resources&#xD;&#xA;&#xD;&#xA;* [Porting from DirectX11 to OpenGL 4.2](https://anteru.net/blog/2013/10/13/2188/) – not exhaustive, but a quick discussion of common porting issues&#xD;&#xA;* [MSDN: GLSL-to-HLSL porting guide](https://msdn.microsoft.com/en-us/windows/uwp/gaming/glsl-to-hlsl-reference) – lists correspondences and differences between GLSL and HLSL shading languages" ContentLicense="CC BY-SA 3.0" />
  <row Id="10102" PostHistoryTypeId="2" PostId="4433" RevisionGUID="a3b76226-5c35-49ec-a667-93fd1efe2b9b" CreationDate="2016-12-29T07:36:18.203" UserId="2448" Text="I'm implementing my path tracer using C++ and OpenMP partially based on the design of [Small Paint][1] (using a globally available RND function to generate random floats) and [PBRTv2][2] (uses a single RNG across all threads). I notice that due to the fact there can can be multiple threads accessing the same RNG. Race condition and CPU cache invalidation will occur caused by the RNG writing to memory to store/update it's current state. Thus dragging the performance down and mess up the RNG(makes it unpredictable).&#xD;&#xA;&#xD;&#xA;How come this is in one of the top grade educational renderer? Or it's just a minor issue that isn't important?&lt;br&gt;&#xD;&#xA;If it's important, is there a known good way to fix this without breaking PBRT's rendering/threading archicture?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://users.cg.tuwien.ac.at/zsolnai/gfx/smallpaint/&#xD;&#xA;  [2]: https://github.com/mmp/pbrt-v2" ContentLicense="CC BY-SA 3.0" />
  <row Id="10103" PostHistoryTypeId="1" PostId="4433" RevisionGUID="a3b76226-5c35-49ec-a667-93fd1efe2b9b" CreationDate="2016-12-29T07:36:18.203" UserId="2448" Text="Avoilding CPU race condition/cache invalidation of RNG on multi thread path tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10104" PostHistoryTypeId="3" PostId="4433" RevisionGUID="a3b76226-5c35-49ec-a667-93fd1efe2b9b" CreationDate="2016-12-29T07:36:18.203" UserId="2448" Text="|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10105" PostHistoryTypeId="2" PostId="4434" RevisionGUID="be8d9d96-a6d9-4a08-9787-707052210486" CreationDate="2016-12-29T10:12:42.363" UserId="5745" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary great between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         &#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - the behavior is similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools.&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, have the same sort of behavior.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        n/a&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10106" PostHistoryTypeId="5" PostId="4434" RevisionGUID="2ead59eb-5b6d-4b2f-b794-cdba045a9855" CreationDate="2016-12-29T10:21:47.723" UserId="5745" Comment="added 514 characters in body" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Overall both APIs are surprisingly similar. Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary greatly between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         &#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;&#xD;&#xA;General queue behavior is pretty similar between both. There's a bit of idiosyncrasy when submitting from multiple threads. &#xD;&#xA;&#xD;&#xA;Will try to update as I remember more stuff...&#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - but the actual behavior is pretty similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools. You can also begin recording immediately after submitting the command buffer/list on both.&#xD;&#xA;&#xD;&#xA;DX12 command list are created in an open state. I find this a bit annoying since I'm used to Vulkan. DX12 also requires and explicit reset of the command allocator and command list. This is an optional behavior in Vulkan.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, have the same sort of behavior.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        n/a&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10109" PostHistoryTypeId="6" PostId="4394" RevisionGUID="55f00a91-f8de-4987-ae0b-ca48c456e5bc" CreationDate="2016-12-29T12:22:48.937" UserDisplayName="user5681" Comment="added pathtracing flag." Text="|raytracing|brdf|pathtracing|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10110" PostHistoryTypeId="5" PostId="4431" RevisionGUID="b6248f74-8e0e-4274-ab54-96f22e50567d" CreationDate="2016-12-29T12:52:53.623" UserId="231" Comment="Tidying" Text="Z-fighting is not related with camera movement. But this issue can be avoided by moving the near plane of the view frustum a little further away from the viewer. As you know, depth testing is the stage in the graphics pipeline which is used to determine whether one pixel is in front or back of the other pixel. It is done by having a buffer known as the z-buffer which stores z values (distance from the viewer) for each fragment. Z-fighting happens when the depth buffer doesn't have enough enough floating point precision to compare two very close z values. Sometimes two z values are so close to each other that they need higher precision to be compared. [This tutorial] explains everything in a simple way about Depth testing and Z-fighting and also discusses about the solutions to avoid them.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [This tutorial]: https://learnopengl.com/#!Advanced-OpenGL/Depth-testing&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10111" PostHistoryTypeId="5" PostId="4429" RevisionGUID="98f0d69b-b3db-4bee-b35f-d220a5aed820" CreationDate="2016-12-29T13:12:33.833" UserId="231" Comment="Tidying and converting P_1 to subscripts" Text="I searched for Z Buffer on Google and I discovered that's a 2 dimensional array used by the graphical card and whose aim is to enable the handling of two pixels' depth in order to display one of these pixels in front of the other.&#xD;&#xA;&#xD;&#xA;**To illustrate my words**, let an image which has only 1 pixel.&#xD;&#xA;&#xD;&#xA;# What is a Z-Buffer? What is its utility?&#xD;&#xA;&#xD;&#xA;## Introduction&#xD;&#xA;Let $P_1$ be the pixel we want to draw in front of $P_2$ (thus, $P_1$ will hide $P_2$ at drawing). So $P_1$ and $P_2$ have the same $X$ and $Y$ coordinates.&#xD;&#xA;&#xD;&#xA;We decide that the $Z$ coordinate of $P_1$ (ie. its depth) is less than $P_2$'s one (it means $P_1$ is closer to the computer's user than $P_2$): $Z(P_1) = 1$, and $Z(P_2) = 2$.&#xD;&#xA;&#xD;&#xA;Our Z-Buffer has, by definition, the same size as our image: 1 case. Each case of the Z-Buffer contains one pixel's depth and each case is associated with one image's pixel.&#xD;&#xA;&#xD;&#xA;First, we initialize the (only one) case of our Z Buffer at the maximum value we can store in its cases (depending on the Z Buffer's type, on the OS, etc.: double/float/integer).&#xD;&#xA;&#xD;&#xA;## $P_1$&#xD;&#xA;Now, we want to first draw $P_1$. The Z Buffer is used: the depth of the $(X(P_1); Y(P_1))$ case's value is compared to the $P_1$'s depth. Of course, $Z(P_1)$ is lesser than $Z( (X(P_1) ; Y(P_1)) )$. The results of this comparison are: first, we replace the old case value with the new $Z$ value (which is: $Z(P_1)$ ); then, $P_1$ is drawn.&#xD;&#xA;&#xD;&#xA;# $P_2$&#xD;&#xA;Finally, we want to draw $P_2$. Again the Z Buffer is used. $(X(P_2); Y(P_2))$ case's value is compared to $Z(P_2)$ (note that: $X(P_2) = X(P_1)$ and $Y(P_2) = Y(P_1)$ - cf. &quot;So $P_1$ and $P_2$ have the same $X$ and $Y$ coordinates.&quot;).&#xD;&#xA;The results of this comparison are: $(Z(P_2) = 2)$ is superior to $( Z( (X(P_2); Y(P_2)) ) = 1)$; first, we don't replace any case; then, $P_2$ is not drawn.&#xD;&#xA;&#xD;&#xA;That's how a Z Buffer is used to display a pixel in front of another.&#xD;&#xA;&#xD;&#xA;## Example of application&#xD;&#xA;http://raphaello.univ-fcomte.fr/IG/ZBuffer/Images/ZBuffer-03.gif&#xD;&#xA;&#xD;&#xA;# Z-Fighting&#xD;&#xA;&#xD;&#xA;## What is Z-Fighting?&#xD;&#xA;If two polygons are very closed AND (note the &quot;AND&quot;) if the camera is moving, Z-Fighting phenomenon appears: https://icculus.org/neverball/mapping/zfighting.png&#xD;&#xA;&#xD;&#xA;## How to reproduce Z-Fighting (ie. how does it work? why does it appear?)&#xD;&#xA;&#xD;&#xA;I know Z Fighting is caused by the resolution in depth of the Z Buffer, due to some conversion/casts mathematical and precision errors. But I don't understand it...&#xD;&#xA;&#xD;&#xA;In particular, I don't understand why the camera must move.&#xD;&#xA;&#xD;&#xA;My question is: could you explain this please?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10114" PostHistoryTypeId="2" PostId="4435" RevisionGUID="ac43f1a5-63a9-4ce9-b334-db9d0772125d" CreationDate="2016-12-29T14:46:19.280" UserId="1952" Text="You need to implement your own thread-safe RNG and not use the clib implementation. What I'm using is a simple &amp; efficient [multiply-with-carry][1] RNG by George Marsaglia, that I initialize with a seed based on pixel coordinates (e.g. simple x+y*width) that I'm calculating. &#xA;&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Multiply-with-carry &quot;multiply-with-carry&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10117" PostHistoryTypeId="5" PostId="4435" RevisionGUID="42c91d8a-15bd-4dc9-9354-62b574bdbba3" CreationDate="2016-12-29T15:54:11.297" UserId="1952" Comment="added 35 characters in body; added 40 characters in body" Text="You need to implement your own RNG class and not use the clib RNG implementation that shares the state across threads. What I'm using is a simple &amp; efficient [multiply-with-carry][1] RNG by George Marsaglia, that I initialize with a seed based on pixel coordinates (e.g. simple x+y*width) that I'm calculating (state per pixel instead of global state)&#xA;&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Multiply-with-carry &quot;multiply-with-carry&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10118" PostHistoryTypeId="5" PostId="4434" RevisionGUID="f343bffa-211c-49d2-a445-98c942702f4f" CreationDate="2016-12-29T16:46:46.250" UserId="5745" Comment="added 1048 characters in body" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Overall both APIs are surprisingly similar. Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary greatly between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         &#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;&#xD;&#xA;General queue behavior is pretty similar between both. There's a bit of idiosyncrasy when submitting from multiple threads. &#xD;&#xA;&#xD;&#xA;Will try to update as I remember more stuff...&#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - but the actual behavior is pretty similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools. You can also begin recording immediately after submitting the command buffer/list on both.&#xD;&#xA;&#xD;&#xA;DX12 command list are created in an open state. I find this a bit annoying since I'm used to Vulkan. DX12 also requires and explicit reset of the command allocator and command list. This is an optional behavior in Vulkan.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;VkDescriptorPool and ID3D12DescriptorHeaps are sort of similar (thanks Nicolas) in that they both manage allocation of the descriptors themselves. &#xD;&#xA;&#xD;&#xA;It should be noted that DX12 only supports at most two descriptor heaps bound to a command list at any given time. One CBVSRVUAV and one sampler. You can have as many descriptor tables as you want referencing these heaps. &#xD;&#xA;&#xD;&#xA;On the Vulkan side, there is a hard limit to the max number of descriptor sets that you tell the descriptor pool. On both you have to do a bit of manual accounting on the number of descriptors per type the pool/heap can have. Vulkan is also more explicit with the type of descriptors. Where as on DX12 descriptors are either CBVSRVUAV or sampler. &#xD;&#xA;&#xD;&#xA;DX12 also has a feature where you can sort of bind a CBV on the fly using SetGraphicsRootConstantBufferView. However, the SRV version of this, SetGraphicsRootShaderResourceView, does not work on textures. It's in the docs - but may also take you a couple of hours to figure this out if you're not a careful reader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, have the same sort of behavior.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        n/a&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10119" PostHistoryTypeId="2" PostId="4436" RevisionGUID="f45e9244-c0a7-4404-9e08-42225cf28592" CreationDate="2016-12-29T18:35:58.620" UserId="2096" Text="I was studying about euler angles and i came across the problem gimbal lock which can occur by using euler angles. In gimbal lock we lose one axis of rotation. &#xA;&#xA;But how??? And when it happens?? On what conditions??? &#xA;&#xA;As far as i know about euler angles is that rotation always occurs about the object axes not upright axes (axes whose orientation is always same as the world axes). And the object axes will remain perpendicular to each other in each rotation. &#xA;&#xA;Just someone use euler angles and show me how to get to that point of gimbal lock.&#xA;&#xA;&#xA;How it can affect animations?&#xA;&#xA;Thank you.&#xA;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10120" PostHistoryTypeId="1" PostId="4436" RevisionGUID="f45e9244-c0a7-4404-9e08-42225cf28592" CreationDate="2016-12-29T18:35:58.620" UserId="2096" Text="How to achieve gimbal lock with euler angles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10121" PostHistoryTypeId="3" PostId="4436" RevisionGUID="f45e9244-c0a7-4404-9e08-42225cf28592" CreationDate="2016-12-29T18:35:58.620" UserId="2096" Text="|rendering|3d|animation|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10122" PostHistoryTypeId="5" PostId="4436" RevisionGUID="5409c917-5949-445e-9376-367bf41740ad" CreationDate="2016-12-29T18:59:55.123" UserId="231" Comment="Tidying." Text="I was studying about Euler angles and I came across the problem gimbal lock which can occur by using Euler angles. In gimbal lock we lose one axis of rotation. &#xD;&#xA;&#xD;&#xA;But how? And when does it happen? On what conditions? &#xD;&#xA;&#xD;&#xA;All I know about Euler angles is that rotation always occurs about the object axes not upright axes (axes whose orientation is always the same as the world axes). And the object axes will remain perpendicular to each other in each rotation. &#xD;&#xA;&#xD;&#xA;Could someone use Euler angles and show me how to get to that point of gimbal lock?&#xD;&#xA;&#xD;&#xA;How can it affect animations?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10127" PostHistoryTypeId="5" PostId="4434" RevisionGUID="efcc7562-dde9-4b6f-9d17-125058aba7c7" CreationDate="2016-12-30T08:48:21.810" UserId="5745" Comment="added 1089 characters in body" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Overall both APIs are surprisingly similar. Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary greatly between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         &#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;&#xD;&#xA;General queue behavior is pretty similar between both. There's a bit of idiosyncrasy when submitting from multiple threads. &#xD;&#xA;&#xD;&#xA;Will try to update as I remember more stuff...&#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - but the actual behavior is pretty similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools. You can also begin recording immediately after submitting the command buffer/list on both.&#xD;&#xA;&#xD;&#xA;DX12 command list are created in an open state. I find this a bit annoying since I'm used to Vulkan. DX12 also requires and explicit reset of the command allocator and command list. This is an optional behavior in Vulkan.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;VkDescriptorPool and ID3D12DescriptorHeaps are sort of similar (thanks Nicolas) in that they both manage allocation of the descriptors themselves. &#xD;&#xA;&#xD;&#xA;It should be noted that DX12 only supports at most two descriptor heaps bound to a command list at any given time. One CBVSRVUAV and one sampler. You can have as many descriptor tables as you want referencing these heaps. &#xD;&#xA;&#xD;&#xA;On the Vulkan side, there is a hard limit to the max number of descriptor sets that you tell the descriptor pool. On both you have to do a bit of manual accounting on the number of descriptors per type the pool/heap can have. Vulkan is also more explicit with the type of descriptors. Whereas on DX12 descriptors are either CBVSRVUAV or sampler. &#xD;&#xA;&#xD;&#xA;DX12 also has a feature where you can sort of bind a CBV on the fly using SetGraphicsRootConstantBufferView. However, the SRV version of this, SetGraphicsRootShaderResourceView, does not work on textures. It's in the docs - but may also take you a couple of hours to figure this out if you're not a careful reader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, have the same sort of behavior.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        n/a&#xD;&#xA;    VkFramebuffer                       collection of ID3D12Resource&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. &#xD;&#xA;&#xD;&#xA;There's not a direct equivalence between VkFramebuffer in DX12. A collection of ID3D12Resource that map to RTVs is similar I suppose. &#xD;&#xA;&#xD;&#xA;VkFramebuffer acts more or less like an attachment pool that VkRenderPass references using an index. Subpasses within a VkRenderPass can reference any of the attachments in a VkFramebuffer assuming the same attachment isn't referenced more than once. Max number of color attachments used at once is limited to VkPhysicalDeviceLimits.maxColorAttachments.&#xD;&#xA;&#xD;&#xA;DX12's render targets are just RTVs that are backed by an ID3D12Resource objects. Max number of color attachments used at once is limited to D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT (8).&#xD;&#xA;&#xD;&#xA;Both APIs require you to specify the render targets/passes at the creation of the pipeline objects. However, Vulkan allows you to use compatible render passes, so you're not locked into the ones you specify during the pipline creation. I haven't tested it on DX12, but I would guess since it's just an RTV, this is also true on DX12." ContentLicense="CC BY-SA 3.0" />
  <row Id="10129" PostHistoryTypeId="5" PostId="4434" RevisionGUID="497b2a32-d04e-4c72-a311-37d071042111" CreationDate="2016-12-30T09:41:11.533" UserId="5745" Comment="added 16 characters in body" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Overall both APIs are surprisingly similar. Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary greatly between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         &#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;&#xD;&#xA;General queue behavior is pretty similar between both. There's a bit of idiosyncrasy when submitting from multiple threads. &#xD;&#xA;&#xD;&#xA;Will try to update as I remember more stuff...&#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - but the actual behavior is pretty similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools. You can also begin recording immediately after submitting the command buffer/list on both.&#xD;&#xA;&#xD;&#xA;DX12 command list are created in an open state. I find this a bit annoying since I'm used to Vulkan. DX12 also requires and explicit reset of the command allocator and command list. This is an optional behavior in Vulkan.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;VkDescriptorPool and ID3D12DescriptorHeaps are sort of similar (thanks Nicolas) in that they both manage allocation of the descriptors themselves. &#xD;&#xA;&#xD;&#xA;It should be noted that DX12 only supports at most two descriptor heaps bound to a command list at any given time. One CBVSRVUAV and one sampler. You can have as many descriptor tables as you want referencing these heaps. &#xD;&#xA;&#xD;&#xA;On the Vulkan side, there is a hard limit to the max number of descriptor sets that you tell the descriptor pool. On both you have to do a bit of manual accounting on the number of descriptors per type the pool/heap can have. Vulkan is also more explicit with the type of descriptors. Whereas on DX12 descriptors are either CBVSRVUAV or sampler. &#xD;&#xA;&#xD;&#xA;DX12 also has a feature where you can sort of bind a CBV on the fly using SetGraphicsRootConstantBufferView. However, the SRV version of this, SetGraphicsRootShaderResourceView, does not work on textures. It's in the docs - but may also take you a couple of hours to figure this out if you're not a careful reader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;*** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, but have similar net result.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        n/a&#xD;&#xA;    VkFramebuffer                       collection of ID3D12Resource&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. &#xD;&#xA;&#xD;&#xA;There's not a direct equivalence between VkFramebuffer and any objects in DX12. A collection of ID3D12Resource that map to RTVs is a loose similarity.&#xD;&#xA;&#xD;&#xA;VkFramebuffer acts more or less like an attachment pool that VkRenderPass references using an index. Subpasses within a VkRenderPass can reference any of the attachments in a VkFramebuffer assuming the same attachment isn't referenced more than once per subpass. Max number of color attachments used at once is limited to VkPhysicalDeviceLimits.maxColorAttachments.&#xD;&#xA;&#xD;&#xA;DX12's render targets are just RTVs that are backed by an ID3D12Resource objects. Max number of color attachments used at once is limited to D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT (8).&#xD;&#xA;&#xD;&#xA;Both APIs require you to specify the render targets/passes at the creation of the pipeline objects. However, Vulkan allows you to use compatible render passes, so you're not locked into the ones you specify during the pipline creation. I haven't tested it on DX12, but I would guess since it's just an RTV, this is also true on DX12." ContentLicense="CC BY-SA 3.0" />
  <row Id="10130" PostHistoryTypeId="2" PostId="4437" RevisionGUID="c9333b85-3674-4a5d-99f2-1b4f791af31a" CreationDate="2016-12-30T10:46:21.203" UserId="4908" Text="Rotations in 3D are normally done with matrices. The xyz Euler angles can be converted to matrices so that it can be used in the rotation.&#xD;&#xA;That is where something called rotation order comes in.&#xD;&#xA;Basically it says in what order you rotate the object.&#xD;&#xA;First you rotate the object around the x axis, then the y axis and lastly the z axis for example.&#xD;&#xA;&#xD;&#xA;This means that when you rotate the object around the x axis first, you change the way the y axis and z axis rotate.&#xD;&#xA;Of course this changes depending on the rotation order.&#xD;&#xA;&#xD;&#xA;This GIF shows how changing one axis value can change the others, but it doesn't work that way for everything.&#xD;&#xA;&#xD;&#xA;![gimbal lock](http://i.giphy.com/3oz8xXJ5NB2owg5V16.gif)&#xD;&#xA;&#xD;&#xA;Here you can also see at the end that I add in that gimbal lock.&#xD;&#xA;This is where I lose one axis of rotation.&#xD;&#xA;&#xD;&#xA;This could be fixed by changing the rotation order to an order, where it doesn't break the way it should work.&#xD;&#xA;It could also be fixed by not using Euler angles but Euler angles are handy and simple in 3D animation.&#xD;&#xA;&#xD;&#xA;In 3D animation it could lead to weird rotations since the values of the rotations have to be changed a lot to get a certain rotation that you want.&#xD;&#xA;If you would look at the xyz Euler angle values in a graph, you would see spikes because of that.&#xD;&#xA;This could lead to weird interpolation of the keyframes and a weird end result.&#xD;&#xA;&#xD;&#xA;If you would like to read more about the math behind it, I would recommend reading about rotation matrices in 3D.&#xD;&#xA;https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations&#xD;&#xA;&#xD;&#xA;I hope this helps!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10131" PostHistoryTypeId="5" PostId="4433" RevisionGUID="c8cc3231-0be2-4658-b4ce-4845cd58b733" CreationDate="2016-12-30T12:15:06.260" UserId="231" Comment="Minor typos" Text="I'm implementing my path tracer using C++ and OpenMP partially based on the design of [Small Paint][1] (using a globally available RND function to generate random floats) and [PBRTv2][2] (uses a single RNG across all threads). I notice that due to the fact there can can be multiple threads accessing the same RNG. Race condition and CPU cache invalidation will occur caused by the RNG writing to memory to store/update it's current state. Thus dragging the performance down and mess up the RNG(makes it unpredictable).&#xD;&#xA;&#xD;&#xA;How come this is in one of the top grade educational renderer? Or it's just a minor issue that isn't important?&lt;br&gt;&#xD;&#xA;If it's important, is there a known good way to fix this without breaking PBRT's rendering/threading architecture?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://users.cg.tuwien.ac.at/zsolnai/gfx/smallpaint/&#xD;&#xA;  [2]: https://github.com/mmp/pbrt-v2" ContentLicense="CC BY-SA 3.0" />
  <row Id="10132" PostHistoryTypeId="4" PostId="4433" RevisionGUID="c8cc3231-0be2-4658-b4ce-4845cd58b733" CreationDate="2016-12-30T12:15:06.260" UserId="231" Comment="Minor typos" Text="Avoiding CPU race condition/cache invalidation of RNG on multi thread path tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10133" PostHistoryTypeId="5" PostId="4437" RevisionGUID="d6b8c1df-e083-4af5-a595-8708c4862ead" CreationDate="2016-12-30T16:06:55.983" UserId="4908" Comment="Added an extra explanation for the animated GIF" Text="Rotations in 3D are normally done with matrices. The xyz Euler angles can be converted to matrices so that it can be used in the rotation.&#xD;&#xA;That is where something called rotation order comes in.&#xD;&#xA;Basically it says in what order you rotate the object.&#xD;&#xA;First you rotate the object around the x axis, then the y axis and lastly the z axis for example.&#xD;&#xA;&#xD;&#xA;This means that when you rotate the object around the x axis first, you change the way the y axis and z axis rotate.&#xD;&#xA;Of course this changes depending on the rotation order.&#xD;&#xA;&#xD;&#xA;This GIF shows how changing one axis value can change the others, but it doesn't work that way for everything.&#xD;&#xA;&#xD;&#xA;![gimbal lock](http://i.giphy.com/3oz8xXJ5NB2owg5V16.gif)&#xD;&#xA;&#xD;&#xA;Here you can also see at the end that I add in that gimbal lock.&#xD;&#xA;This is where I lose one axis of rotation.&#xD;&#xA;&#xD;&#xA;This could be fixed by changing the rotation order to an order, where it doesn't break the way it should work.&#xD;&#xA;It could also be fixed by not using Euler angles but Euler angles are handy and simple in 3D animation.&#xD;&#xA;&#xD;&#xA;In 3D animation it could lead to weird rotations since the values of the rotations have to be changed a lot to get a certain rotation that you want.&#xD;&#xA;If you would look at the xyz Euler angle values in a graph, you would see spikes because of that.&#xD;&#xA;This could lead to weird interpolation of the keyframes and a weird end result.&#xD;&#xA;&#xD;&#xA;If you would like to read more about the math behind it, I would recommend reading about rotation matrices in 3D.&#xD;&#xA;https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A little extra explanation for the animation:&#xD;&#xA;Rotation in this case is around axis (shown as circles) and by rotating on one axis, you rotate the other axis. The consequence is that with a normal rotation sphere (the sphere in the animation, but then without the axis being rotated) in the animation, you don't see these axis being rotated. If you get a gimbal lock, one axis is the same as another one, but with a normal rotation sphere it still tries to rotate as if that axis wasn't the same as another one, this means that it uses weird values to get to that rotation and this can make an animation look weird.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope this helps!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10136" PostHistoryTypeId="2" PostId="4438" RevisionGUID="43adde8e-0dc8-49bd-86d4-338cc7d762d9" CreationDate="2016-12-30T22:12:50.373" UserId="38" Text="A `gimbal` is a pivoted support that allows you to rotate around one axis. Now it so happens that Euler rotations\* work like a set of 3 gimbals attached to each other, one rotation builds upon the next (or previous/whole stack if your inclined to model it that way). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Rotation is like a gimbal. [Model](http://tf3dm.com/3d-model/fa-22-raptor-86148.html) using *yxz* rotation (z=blue, x= red and y=green) in a physical 3 axis gimbal structure. &#xD;&#xA;&#xD;&#xA;A `gimbal lock` happens when you turn 2 or 3 of the successive gimbals they align on to a plane. You succeed in erasing one direction since the angles both operate same same direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Rotation direction lost because 2 of the rotations overlap.&#xD;&#xA;&#xD;&#xA;The ouny way out is to unwind the stricture. Although this is the lock, problems due to diminishing possibilities to turn start earlier than the lock itself.&#xD;&#xA;&#xD;&#xA;### A more in depth look at things&#xD;&#xA;&#xD;&#xA;Now this is where most people stop thinking about the issue and move on with their life. They just conclude that Euler angles are somehow broken. This is also where a lot of misunderstandings happen so its worth investigating the matter slightly further than what causes gimbal lock.&#xD;&#xA;&#xD;&#xA;It is important to understand that this is *only* problematic if you `interpolate` in Euler angles\*\*! In a real physical gimbal this is given you have no other choice. In computer graphics you have many other choices, from normalized matrix, axis angle or quaternion interpolation. Gimbal lock has a much more dramatic implication to designing control systems than it has to 3d graphics. Which is why a mechanical engineer for example have a very different take on gimbal locking. &#xD;&#xA;&#xD;&#xA;You dont have to give up using Euler angles to get rid of gimbal locking just stop interpolating values in Euler angles. Off course this means that you can now no longer drive a rotation by doing direct manipulation of one of the channels. But as long as you key the 3 angles simultaneously you have no problems you can internally convert your interpolation target to something that has less problems.&#xD;&#xA;&#xD;&#xA;Using Euler angles is just simply more intuitive to think in most cases. And indeed Euler never claimed it was good for interpolating but just that it can model all possible space orientations. So Euler angles are just fine for setting orientations like they were meant to do. Also incidentally Euler angles have the benefit of being able to model multi turn rotations which will not happen sanely for the other representations.&#xD;&#xA;&#xD;&#xA;### Problems and how to circumvent them&#xD;&#xA;&#xD;&#xA;The matter of fact is that interpolating in Euler angle space is a bad idea, in general and affects you way before you come close to a true gimbal lock. For this reason NASA lunar orbiter would warn of gimbal lock when you come close to a 70-80 angles on a single gimbals turn. So be aware that people do not necessarily talk of just the actual locking condition when they talk of a gimbal lock. Even worse some people blame all their rotation problems on gimbal locking.&#xD;&#xA;&#xD;&#xA;Euler rotation is only safe if you rotate primarily one angle and shallow amounts on the other 2 rotations, which is quite common admittedly. This works fine for describing movement of a commercial airliner, a car etc. But not so well for a jet fighter or a acrobatics plane doing complex air maneuvers. What happens is the rotations start to interfere with each other and you get a weir wobble instead of moving straight form one position to the next.&#xD;&#xA;&#xD;&#xA;To fix the wobble problem in shallow cases just swap the rotation order so that the big rotation gets applied on the other rotations. If you need to use more complex rotations then either switch over to other interpolation methods or add even more rotation links to your gimbal (which is a good stopgap measure for cases where you can not do the switch in a timely manner).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* To be exact most of the time people do not actually use Euler angles but Tait–Bryan angles. Which are nearly the same thing only Euler insisted on repeating the same axis, not very important distinction but good to know if you ever speak to an academic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\*\* Oh well, if you use Euler-Lagrange it matters not.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9Bkct.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/1pCtJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10137" PostHistoryTypeId="5" PostId="4438" RevisionGUID="72481c61-8e1f-46c2-9411-37c28c97adc9" CreationDate="2016-12-30T22:18:46.200" UserId="38" Comment="added 10 characters in body" Text="A `gimbal` is a pivoted support that allows you to rotate around one axis. Now it so happens that Euler rotations\* work like a set of 3 gimbals attached to each other, one rotation builds upon the next (or previous/whole stack if your inclined to model it that way). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Rotation is like a gimbal. [Model](http://tf3dm.com/3d-model/fa-22-raptor-86148.html) using *yxz* rotation (z=blue, x= red and y=green) in a physical 3 axis gimbal structure. &#xD;&#xA;&#xD;&#xA;A `gimbal lock` happens when you turn 2 or 3 of the successive gimbals they align on to a plane. You succeed in erasing one direction since the angles both operate same same direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Rotation direction lost because 2 of the rotations overlap.&#xD;&#xA;&#xD;&#xA;The only way out is to unwind the stricture. Although this is the lock, problems due to diminishing possibilities to turn start earlier than the lock itself.&#xD;&#xA;&#xD;&#xA;### A more in depth look at things&#xD;&#xA;&#xD;&#xA;Now this is where most people stop thinking about the issue and move on with their life. They just conclude that Euler angles are somehow broken. This is also where a lot of misunderstandings happen so its worth investigating the matter slightly further than what causes gimbal lock.&#xD;&#xA;&#xD;&#xA;It is important to understand that this is *only* problematic if you `interpolate` in Euler angles\*\*! In a real physical gimbal this is given you have no other choice. In computer graphics you have many other choices, from normalized matrix, axis angle or quaternion interpolation. Gimbal lock has a much more dramatic implication to designing control systems than it has to 3d graphics. Which is why a mechanical engineer for example have a very different take on gimbal locking. &#xD;&#xA;&#xD;&#xA;You dont have to give up using Euler angles to get rid of gimbal locking just stop interpolating values in Euler angles. Off course this means that you can now no longer drive a rotation by doing direct manipulation of one of the channels. But as long as you key the 3 angles simultaneously you have no problems you can internally convert your interpolation target to something that has less problems.&#xD;&#xA;&#xD;&#xA;Using Euler angles is just simply more intuitive to think in most cases. And indeed Euler never claimed it was good for interpolating but just that it can model all possible space orientations. So Euler angles are just fine for setting orientations like they were meant to do. Also incidentally Euler angles have the benefit of being able to model multi turn rotations which will not happen sanely for the other representations.&#xD;&#xA;&#xD;&#xA;### Problems and how to circumvent them&#xD;&#xA;&#xD;&#xA;The matter of fact is that interpolating in Euler angle space is a bad idea, in general and affects you way before you come close to a true gimbal lock. For this reason NASA lunar orbiter would warn of gimbal lock when you come close to a 70-80 angles on a single gimbals turn. So be aware that people do not necessarily talk of just the actual locking condition when they talk of a gimbal lock. Even worse some people blame all their rotation problems on gimbal locking.&#xD;&#xA;&#xD;&#xA;Euler rotation is only safe if you rotate primarily one angle and shallow amounts on the other 2 rotations, which is quite common admittedly. This works fine for describing movement of a commercial airliner, a car etc. But not so well for a jet fighter or a acrobatics plane doing complex air maneuvers. What happens is the rotations start to interfere with each other and you get a weir wobble instead of moving straight form one position to the next.&#xD;&#xA;&#xD;&#xA;To fix the wobble problem in shallow cases just swap the rotation order so that the big rotation gets applied on the other rotations. If you need to use more complex rotations then either switch over to other interpolation methods or add even more rotation links to your gimbal (which is a good stopgap measure for cases where you can not do the switch in a timely manner).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* To be exact most of the time people do not actually use Euler angles but Tait–Bryan angles. Which are nearly the same thing only Euler insisted on repeating the same axis, not very important distinction but good to know if you ever speak to an academic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\*\* Oh well, if you use Euler–Lagrange equation it won't matter.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9Bkct.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/1pCtJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10140" PostHistoryTypeId="2" PostId="4439" RevisionGUID="7e5a4cae-e058-4da0-b3da-446b332d318e" CreationDate="2016-12-31T15:19:00.490" UserId="5763" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 330 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed because it works on Nvidia cards. It's a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box but that's it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZsCX4.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10141" PostHistoryTypeId="1" PostId="4439" RevisionGUID="7e5a4cae-e058-4da0-b3da-446b332d318e" CreationDate="2016-12-31T15:19:00.490" UserId="5763" Text="Are ATI cards lacking some feature that would allow them to draw triangle strips connected by degenerates with a single draw call using a vao?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10142" PostHistoryTypeId="3" PostId="4439" RevisionGUID="7e5a4cae-e058-4da0-b3da-446b332d318e" CreationDate="2016-12-31T15:19:00.490" UserId="5763" Text="|opengl|glsl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10144" PostHistoryTypeId="5" PostId="4439" RevisionGUID="e4822c47-e770-4013-a71f-542509409c40" CreationDate="2016-12-31T17:34:02.420" UserId="5763" Comment="Updated the sample output image. I overlooked the fact that the original had an additionial piece of geometry (the water plane) covering some of the output." Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 330 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed because it works on Nvidia cards. It's a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box but that's it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10145" PostHistoryTypeId="4" PostId="4439" RevisionGUID="4ff9ee89-5b9a-4a95-b6c3-8d207b7ba9f8" CreationDate="2016-12-31T18:01:02.793" UserId="5763" Comment="edited title" Text="Are ATI cards lacking some feature that would allow them to draw geometry with vertex array objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10146" PostHistoryTypeId="5" PostId="4439" RevisionGUID="04d00521-363a-4ecb-ad62-45d8262225e1" CreationDate="2016-12-31T18:10:12.060" UserId="5763" Comment="added summary at the end" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 330 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed because it works on Nvidia cards. It's a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box but that's it.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10147" PostHistoryTypeId="6" PostId="4439" RevisionGUID="568f3ae6-fdc8-4730-b082-5925a390a914" CreationDate="2016-12-31T18:15:28.227" UserId="5763" Comment="edited title to make the question more complete" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10148" PostHistoryTypeId="4" PostId="4439" RevisionGUID="568f3ae6-fdc8-4730-b082-5925a390a914" CreationDate="2016-12-31T18:15:28.227" UserId="5763" Comment="edited title to make the question more complete" Text="Are ATI cards lacking some feature that would allow them to draw geometry with vertex array objects, and what is the workaround if they are?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10150" PostHistoryTypeId="5" PostId="4439" RevisionGUID="5d7995f3-7eb9-4ad6-997e-bc4195c1664f" CreationDate="2016-12-31T19:42:46.293" UserId="5763" Comment="fixing typo" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 130 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed in `heightMapTexture` to the best of my knowledge because I've inspected it piece by piece in a debugger and because the strips come out correctly on Nvidia cards. I am assuming there are no fundamental differences in how `GL_TRIANGLE_STRIP` works between Nvidia and ATI. If there is a difference then that's exactly the type of thing this question is trying to figure out. The description of triangle strips in the OpenGL spec doesn't seem to leave much room for differences here if any, so it seems likely that if the strips themselves are formed correctly according to the spec they should work everywhere or nowhere.&#xD;&#xA;&#xD;&#xA;The geometry is a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box but that's it.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10151" PostHistoryTypeId="2" PostId="4440" RevisionGUID="5b8e5e46-ee70-434f-90dd-6d376538bc6c" CreationDate="2016-12-31T19:56:52.237" UserId="2318" Text="As others mentioned, [z-fighting/stiching][1] occurs even if the camera is not moving.  However, when the camera is moving and you're getting z-fighting, it will appear as though the polygons are flickering.&#xD;&#xA;&#xD;&#xA;[This link][2] helped me to understand the depth buffer much better.  Here he generates depth values and simulates the different kinds of precision errors you would get depending on your depth buffer format (graphics APIs usually let you request a depth buffer format).  &quot;indist&quot; and &quot;swaps&quot; are both precision errors, and can cause the z-fighting to appear.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Z-fighting&#xD;&#xA;  [2]: http://reedbeta.com/blog/depth-precision-visualized/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10152" PostHistoryTypeId="5" PostId="4438" RevisionGUID="ce9366b4-b59c-4720-a1ad-750f3890602e" CreationDate="2016-12-31T20:55:39.923" UserId="231" Comment="Minor tidying" Text="A `gimbal` is a pivoted support that allows you to rotate around one axis. Now it so happens that Euler rotations\* work like a set of 3 gimbals attached to each other, one rotation builds upon the next (or previous/whole stack if your inclined to model it that way). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Rotation is like a gimbal. [Model](http://tf3dm.com/3d-model/fa-22-raptor-86148.html) using *yxz* rotation (z=blue, x= red and y=green) in a physical 3 axis gimbal structure. &#xD;&#xA;&#xD;&#xA;A `gimbal lock` happens when you turn 2 or 3 of the successive gimbals and they align onto a plane. You succeed in erasing one direction since the angles both operate same same direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Rotation direction lost because 2 of the rotations overlap.&#xD;&#xA;&#xD;&#xA;The only way out is to unwind the stricture. Although this is the lock, problems due to diminishing possibilities to turn start earlier than the lock itself.&#xD;&#xA;&#xD;&#xA;### A more in depth look at things&#xD;&#xA;&#xD;&#xA;Now this is where most people stop thinking about the issue and move on with their life. They just conclude that Euler angles are somehow broken. This is also where a lot of misunderstandings happen so it's worth investigating the matter slightly further than what causes gimbal lock.&#xD;&#xA;&#xD;&#xA;It is important to understand that this is *only* problematic if you `interpolate` in Euler angles\*\*! In a real physical gimbal this is given - you have no other choice. In computer graphics you have many other choices, from normalized matrix, axis angle or quaternion interpolation. Gimbal lock has a much more dramatic implication to designing control systems than it has to 3d graphics. Which is why a mechanical engineer for example will have a very different take on gimbal locking. &#xD;&#xA;&#xD;&#xA;You don't have to give up using Euler angles to get rid of gimbal locking, just stop interpolating values in Euler angles. Of course, this means that you can now no longer drive a rotation by doing direct manipulation of one of the channels. But as long as you key the 3 angles simultaneously you have no problems and you can internally convert your interpolation target to something that has less problems.&#xD;&#xA;&#xD;&#xA;Using Euler angles is just simply more intuitive to think in most cases. And indeed Euler never claimed it was good for interpolating but just that it can model all possible space orientations. So Euler angles are just fine for setting orientations like they were meant to do. Also incidentally Euler angles have the benefit of being able to model multi turn rotations which will not happen sanely for the other representations.&#xD;&#xA;&#xD;&#xA;### Problems and how to circumvent them&#xD;&#xA;&#xD;&#xA;The fact of the matter is that interpolating in Euler angle space is a bad idea, in general and affects you way before you come close to a true gimbal lock. For this reason NASA lunar orbiter would warn of gimbal lock when you come close to a 70-80 degree angle on a single gimbal's turn. So be aware that people do not necessarily talk of just the actual locking condition when they talk of a gimbal lock. Even worse some people blame all their rotation problems on gimbal locking.&#xD;&#xA;&#xD;&#xA;Euler rotation is only safe if you rotate primarily one angle and shallow amounts on the other 2 rotations, which is quite common admittedly. This works fine for describing movement of a commercial airliner, a car etc. But not so well for a jet fighter or an acrobatics plane doing complex air maneuvers. What happens is the rotations start to interfere with each other and you get a weird wobble instead of moving straight from one position to the next.&#xD;&#xA;&#xD;&#xA;To fix the wobble problem in shallow cases just swap the rotation order so that the big rotation gets applied on the other rotations. If you need to use more complex rotations then either switch over to other interpolation methods or add even more rotation links to your gimbal (which is a good stopgap measure for cases where you cannot do the switch in a timely manner).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* To be exact most of the time people do not actually use Euler angles but Tait–Bryan angles. Which are nearly the same thing only Euler insisted on repeating the same axis, not very important distinction but good to know if you ever speak to an academic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\*\* Oh well, if you use Euler–Lagrange equation it won't matter.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9Bkct.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/1pCtJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10153" PostHistoryTypeId="4" PostId="4436" RevisionGUID="f8aef595-d6a1-4eff-a421-6a2e30424893" CreationDate="2016-12-31T21:08:19.070" UserId="231" Comment="Minor typo in title" Text="How to achieve gimbal lock with Euler angles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10154" PostHistoryTypeId="5" PostId="4439" RevisionGUID="01a5f3e1-7ce4-488c-b1c2-b7f6f15a17bf" CreationDate="2016-12-31T21:35:11.210" UserId="5763" Comment="adding a description of &quot;gray scissor clear box&quot; as per suggestion in the comments. Adding reasoning behind why I'm not debugging this on the affected hardware myself right now." Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 130 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed in `heightMapTexture` to the best of my knowledge because I've inspected it piece by piece in a debugger and because the strips come out correctly on Nvidia cards. I am assuming there are no fundamental differences in how `GL_TRIANGLE_STRIP` works between Nvidia and ATI. If there is a difference then that's exactly the type of thing this question is trying to figure out. The description of triangle strips in the OpenGL spec doesn't seem to leave much room for differences here if any, so it seems likely that if the strips themselves are formed correctly according to the spec they should work everywhere or nowhere.&#xD;&#xA;&#xD;&#xA;The geometry is a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box that is drawn by the snippet:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;&#xD;&#xA;Nothing else besides the gray box is displayed.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw. I'm looking for possible differences between how ATI and Nvidia would handle this geometry.&#xD;&#xA;&#xD;&#xA;P.S. Adding this note to answer some of the comments that suggest I should go back to a single tri and debug from scratch by myself. The reason I'm asking this question is that I don't currently have access to ATI hardware. I'm in South America until May and availability is basically nil. I have several workstations that I brought with me for work, but all have Nvidia hardware. I have to do a full build and ship of the product to someone in a different time zone for each attempt to correct the issue. I need to be a bit more purposeful in my fixes than just going back to drawing a triangle and working up from scratch. It's not that I wouldn't love to debug it myself on the affected hardware step by step. It's that I just can't right now. I need to get get the code closer to a likely solution before sending another build, so I'm looking for some educated guesses from people with direct experience with this type of geometry on ATI hardware. I would greatly appreciate more understanding than &quot;That's what debug is for. Go back to a triangle.&quot; This also seems like something that someone must have encountered before as this seems like a pretty standard way to draw a heightmap or any similar geometry really. I also think that this question will help anyone else who has this problem in the future. I've lost days to this, and there is absolutely no published answer to anything remotely similar that I could find. If this remains unanswered until May when I return home I will write the answer myself, but I hope it doesn't come to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10155" PostHistoryTypeId="5" PostId="4439" RevisionGUID="ddc618ef-aa55-4acb-8007-51cce91b2ea8" CreationDate="2016-12-31T21:46:29.327" UserId="5763" Comment="fixing typo" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 130 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed in `heightMapTexture` to the best of my knowledge because I've inspected it piece by piece in a debugger and because the strips come out correctly on Nvidia cards. I am assuming there are no fundamental differences in how `GL_TRIANGLE_STRIP` works between Nvidia and ATI. If there is a difference then that's exactly the type of thing this question is trying to figure out. The description of triangle strips in the OpenGL spec doesn't seem to leave much room for differences here if any, so it seems likely that if the strips themselves are formed correctly according to the spec they should work everywhere or nowhere.&#xD;&#xA;&#xD;&#xA;The geometry is a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box that is drawn by the snippet:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;&#xD;&#xA;Nothing else besides the gray box is displayed.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw. I'm looking for possible differences between how ATI and Nvidia would handle this geometry.&#xD;&#xA;&#xD;&#xA;P.S. Adding this note to answer some of the comments that suggest I should go back to a single tri and debug from scratch by myself. The reason I'm asking this question is that I don't currently have access to ATI hardware. I'm in South America until May and availability is basically nil. I have several workstations that I brought with me for work, but all have Nvidia hardware. I have to do a full build and ship of the product to someone in a different time zone for each attempt to correct the issue. I need to be a bit more purposeful in my fixes than just going back to drawing a triangle and working up from scratch. It's not that I wouldn't love to debug it myself on the affected hardware step by step. It's that I just can't right now. I need to get the code closer to a likely solution before sending another build, so I'm looking for some educated guesses from people with direct experience with this type of geometry on ATI hardware. I would greatly appreciate more understanding than &quot;That's what debug is for. Go back to a triangle.&quot; This also seems like something that someone must have encountered before as this seems like a pretty standard way to draw a heightmap or any similar geometry really. I also think that this question will help anyone else who has this problem in the future. I've lost days to this, and there is absolutely no published answer to anything remotely similar that I could find. If this remains unanswered until May when I return home I will write the answer myself, but I hope it doesn't come to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10156" PostHistoryTypeId="5" PostId="4439" RevisionGUID="4c36a9ad-820d-4596-a7e0-5c1ba6917533" CreationDate="2016-12-31T22:11:35.213" UserId="5763" Comment="fixing for clarity" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 130 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed in `heightMapTexture` to the best of my knowledge because I've inspected it piece by piece in a debugger and because the strips come out correctly on Nvidia cards. I am assuming there are no fundamental differences in how `GL_TRIANGLE_STRIP` works between Nvidia and ATI. If there is a difference then that's exactly the type of thing this question is trying to figure out. The description of triangle strips in the OpenGL spec doesn't seem to leave much room for differences here if any, so it seems likely that if the strips themselves are formed correctly according to the spec they should work everywhere or nowhere.&#xD;&#xA;&#xD;&#xA;The geometry is a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear box that is drawn by the snippet:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;&#xD;&#xA;Nothing else besides the gray box is displayed.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw. I'm looking for possible differences between how ATI and Nvidia would handle this geometry.&#xD;&#xA;&#xD;&#xA;P.S. I added this note to answer some of the comments that suggest I should go back to a single triangle and debug from scratch on my own. The reason I'm asking this question is that I don't currently have access to ATI hardware. I'm in South America until May and hardware availability is basically nil where I am. I have several workstations that I brought with me for work, but they all have Nvidia hardware. I have to do a full build and then ship the product to someone in a different time zone each time I attempt to correct the issue. I need to be more purposeful in my fixes than going back to drawing a triangle and working up from scratch. I would love to debug it myself on the affected hardware step by step. I just can't right now. I need to get the code closer to a likely solution before sending another build, so I'm looking for some educated guesses from people with direct experience with this type of geometry on ATI hardware. I would greatly appreciate more understanding than &quot;That's what debug is for. Go back to a triangle.&quot;, because those comments really don't help me or anyone else reading this later. This problem seems like something that someone must have encountered before because it seems like a pretty standard way to draw a heightmap. I think that this question will help anyone else who has this problem in the future. I've lost several days to this, and there is no published answer to anything similar that I could find. If this remains unanswered until May, when I return home, I will write the answer myself and remove this note, but I hope it doesn't come to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10157" PostHistoryTypeId="5" PostId="4439" RevisionGUID="e4c42dd0-33c8-4a51-8dd3-0f0314232c3c" CreationDate="2016-12-31T22:19:46.727" UserId="5763" Comment="changing the word &quot;box&quot; to &quot;rectangle&quot; since it's 2D not 3D and removing a superfluous line of code from the snippet clarifying the gray rectangle" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 130 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed in `heightMapTexture` to the best of my knowledge because I've inspected it piece by piece in a debugger and because the strips come out correctly on Nvidia cards. I am assuming there are no fundamental differences in how `GL_TRIANGLE_STRIP` works between Nvidia and ATI. If there is a difference then that's exactly the type of thing this question is trying to figure out. The description of triangle strips in the OpenGL spec doesn't seem to leave much room for differences here if any, so it seems likely that if the strips themselves are formed correctly according to the spec they should work everywhere or nowhere.&#xD;&#xA;&#xD;&#xA;The geometry is a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear rectangle that is drawn by the snippet:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;&#xD;&#xA;Nothing else besides the gray rectangle is displayed.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw. I'm looking for possible differences between how ATI and Nvidia would handle this geometry.&#xD;&#xA;&#xD;&#xA;P.S. I added this note to answer some of the comments that suggest I should go back to a single triangle and debug from scratch on my own. The reason I'm asking this question is that I don't currently have access to ATI hardware. I'm in South America until May and hardware availability is basically nil where I am. I have several workstations that I brought with me for work, but they all have Nvidia hardware. I have to do a full build and then ship the product to someone in a different time zone each time I attempt to correct the issue. I need to be more purposeful in my fixes than going back to drawing a triangle and working up from scratch. I would love to debug it myself on the affected hardware step by step. I just can't right now. I need to get the code closer to a likely solution before sending another build, so I'm looking for some educated guesses from people with direct experience with this type of geometry on ATI hardware. I would greatly appreciate more understanding than &quot;That's what debug is for. Go back to a triangle.&quot;, because those comments really don't help me or anyone else reading this later. This problem seems like something that someone must have encountered before because it seems like a pretty standard way to draw a heightmap. I think that this question will help anyone else who has this problem in the future. I've lost several days to this, and there is no published answer to anything similar that I could find. If this remains unanswered until May, when I return home, I will write the answer myself and remove this note, but I hope it doesn't come to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10158" PostHistoryTypeId="4" PostId="4439" RevisionGUID="67ed9a6b-a4e3-42d1-ab6d-6ba7ca03cc8c" CreationDate="2016-12-31T22:28:56.113" UserId="5763" Comment="Updating title to be closer to the question" Text="Is there a difference in how ATI cards draw triangle strips vs Nvidia cards that would cause ATI cards to output nothing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10159" PostHistoryTypeId="2" PostId="4441" RevisionGUID="3bc796b5-fb66-4a69-91da-b4c3973d8aea" CreationDate="2017-01-01T04:46:15.877" UserId="5764" Text="I've just finished writing a path tracer that takes OBJ files and renders it. This is convenient for still images, but my end goal was to export a sequence from a 3D application (Blender was what I had in mind), and then render an image sequence from that. Originally I figured an OBJ sequence would do, but that would take a massive amount of space for complex scenes. &#xD;&#xA;&#xD;&#xA;I began looking into parsing .fbx, .3ds and other popular file formats, but there's so little out there that I could find. I still don't really understand how those files store animations. I can imagine the mesh is stored and then keyframes indicate which vertices translate...? Maybe? Or whole objects? What happens when you have complex deformation like an ocean wave, fluid, or character where many, many vertices are translating? At that point would it be easier to do some sort of OBJ like sequence? I want to stay away from that if I can since it takes lots of memory/time to export.&#xD;&#xA;&#xD;&#xA;Hopefully someone can point me in the right direction or explain how other standalone renderers keep their animation data. Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10160" PostHistoryTypeId="1" PostId="4441" RevisionGUID="3bc796b5-fb66-4a69-91da-b4c3973d8aea" CreationDate="2017-01-01T04:46:15.877" UserId="5764" Text="Storing 3D animations for ray tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10161" PostHistoryTypeId="3" PostId="4441" RevisionGUID="3bc796b5-fb66-4a69-91da-b4c3973d8aea" CreationDate="2017-01-01T04:46:15.877" UserId="5764" Text="|raytracing|pathtracing|animation|scene-description|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10162" PostHistoryTypeId="2" PostId="4442" RevisionGUID="5dc6b308-1156-4ff7-86d0-463091b316e3" CreationDate="2017-01-01T06:52:09.213" UserId="5256" Text="I have implemented a sky rendering model in my ray tracer which saves the color of the sky to an image. I was wondering I can render the sky dome and texture map the image on to it.&#xD;&#xA;&#xD;&#xA;Do I render the sphere at the center of the environment and add the image to the inside of the sphere? How would I add a texture to the inside of a sphere as opposed to the outside in code? Do I just reverse the normals?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10163" PostHistoryTypeId="1" PostId="4442" RevisionGUID="5dc6b308-1156-4ff7-86d0-463091b316e3" CreationDate="2017-01-01T06:52:09.213" UserId="5256" Text="Texture Mapping inside a Sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="10164" PostHistoryTypeId="3" PostId="4442" RevisionGUID="5dc6b308-1156-4ff7-86d0-463091b316e3" CreationDate="2017-01-01T06:52:09.213" UserId="5256" Text="|raytracing|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10165" PostHistoryTypeId="2" PostId="4443" RevisionGUID="02b65668-a97f-4861-8ac6-51a2ab868214" CreationDate="2017-01-01T10:37:24.880" UserId="38" Text="Pixar spent quite much time, money and other capital to archive all their renders. What they did is was just to store the raw render description files their render engine used. The reason for this is that its the only way to ensure that the features stay intact. Offcourse they had a very well documented standardized format to work with. &#xD;&#xA;&#xD;&#xA;The benefit of this method is that it stores things relevantly. In other words static objects can be stored static and only animation objects need to be stored frame by frame wich is the only way to ensure compatibility for animation without relying on host apps to do this for you.&#xD;&#xA;&#xD;&#xA;Alembic works on a similar principle. The downside is big formats offcourse. But note that formats such as FBX and Collada are not much better. While its true that they can contain some of the animation data they can not allways do everything that you want them to do. Which means that in the end it might not do what you want.&#xD;&#xA;&#xD;&#xA;Personally i would implement something like the RI spec for my own renderer. If not RI spec itself which would allow you to swap renderer  if need be (also the other way around a user couod swap to your renderer without many changes)." ContentLicense="CC BY-SA 3.0" />
  <row Id="10166" PostHistoryTypeId="5" PostId="4443" RevisionGUID="8c3978f4-1351-4fa5-95c2-0e33f2a3ca8b" CreationDate="2017-01-01T10:46:11.767" UserId="38" Comment="added 653 characters in body" Text="Pixar spent quite much time, money and other capital to archive all their renders. What they did is was just to store the raw render description files their render engine used. The reason for this is that its the only way to ensure that the features stay intact. Offcourse they had a very well documented standardized format to work with. &#xD;&#xA;&#xD;&#xA;The benefit of this method is that it stores things relevantly. In other words static objects can be stored static and only animation objects need to be stored frame by frame wich is the only way to ensure compatibility for animation without relying on host apps to do this for you.&#xD;&#xA;&#xD;&#xA;Alembic works on a similar principle. The downside is big formats. But note that formats such as FBX and Collada are not much better. While its true that they can contain some of the animation data they can not always do everything that you want them to do. Which means that in the end it might not do what you want.&#xD;&#xA;&#xD;&#xA;The animation exhange formats (FBX, Collada etc...) do not usually store vertex postions, if they did then theu qould just have same problem as your obj storage. Instead the modification history so that they can redo the animation. So for example the bones are stored as tranforms and the vertex weights are used to compute their position. The downside is that your reader needs to implement substantial amounts of the animation core. And anything the format does not know how to do is stored either as point caches, or not at all. Realistically speaking for fbx you would use the API to do this. Implementing it yourself is a quite big undertaking, it may be cheaper to just buy more storage space.&#xD;&#xA;&#xD;&#xA;Personally i would implement something like the RI spec for my own renderer. If not RI spec itself which would allow you to swap renderer  if need be (also the other way around a user couod swap to your renderer without many changes)." ContentLicense="CC BY-SA 3.0" />
  <row Id="10167" PostHistoryTypeId="5" PostId="4443" RevisionGUID="7976e7b6-c49f-4709-9cff-42e06f68ba90" CreationDate="2017-01-01T12:26:46.467" UserId="38" Comment="added 11 characters in body" Text="Pixar spent quite much time, money and other capital to archive all their renders. What they did is was just to store the raw render description files their render engine used. The reason for this is that its the only way to ensure that the features stay intact. Of course they had a very well documented standardized format to work with. &#xD;&#xA;&#xD;&#xA;The benefit of this method is that it stores things relevantly. In other words static objects can be stored static and only animation objects need to be stored frame by frame wich is the only way to ensure compatibility for animation without relying on host apps to do this for you.&#xD;&#xA;&#xD;&#xA;Alembic works on a similar principle. The downside is big formats. But note that formats such as FBX and Collada (*.dae) are not much better. While its true that they can contain some of the animation data they can not always do everything that you want them to do. Which means that in the end it might not do what you want.&#xD;&#xA;&#xD;&#xA;The animation exchange formats (FBX, Collada etc...) do not usually store vertex positions, if they did then they would just have same problem as your obj storage. Instead the modification history so that they can redo the animation. So for example the bones are stored as transforms and the vertex weights are used to compute their position. The downside is that your reader needs to implement substantial amounts of the animation core. And anything the format does not know how to do is stored either as point caches, or not at all. Realistically speaking for fbx you would use the API to do this. Implementing it yourself is a quite big undertaking, it may be cheaper to just buy more storage space.&#xD;&#xA;&#xD;&#xA;Personally i would implement something like the RI spec for my own renderer. If not RI spec itself which would allow you to swap renderer  if need be (also the other way around a user could swap to your renderer without many changes)." ContentLicense="CC BY-SA 3.0" />
  <row Id="10168" PostHistoryTypeId="5" PostId="4439" RevisionGUID="4fa6ea12-9000-4f70-b3dd-c2fb1c012f40" CreationDate="2017-01-01T12:43:39.040" UserId="5763" Comment="note about language in code snippets" Text="I have a rendering system that I use for drawing height maps. The system uses triangle strips of indexed verts in a vao. The system has worked fine on the 3 Nvidia cards I have tried it on across several versions of windows and OSX. I don't own any Systems with an ATI card but I sent the application to a colleague to look at for me, and on his machine no output is produced in the 3d viewport. He has a Radeon HD 7800 and is using windows 10 which is one of the operating systems I have tried it on with an Nvidia card. Running OpenGL extensions viewer indicates that his card supports a modern range of capabilities up to GL 4.5.&#xD;&#xA;&#xD;&#xA;I attached an opengl debug callback. The shader program compiles fine and the vao is created without errors. There are no errors on draw either. The shaders use #version 330 core but I tried dropping down to #version 130 and simplifying the shaders to basically output the vertex position and a flat color, and it still works fine on nvidia but outputs nothing on ATI, so I doubt the shaders are the issue.&#xD;&#xA;&#xD;&#xA;I suspect it has something to do with the way the vao is set up or possibly some feature that is missing in ATI drivers or hardware.&#xD;&#xA;&#xD;&#xA;The following two blocks of code are in Kotlin using LWJGL3. The relevant GL calls are all the same as from Java though. They are a very tiny wrapper to the `C` calls.&#xD;&#xA;&#xD;&#xA;The vao gets set up like this: &#xD;&#xA;&#xD;&#xA;    vao = glGenVertexArrays()&#xD;&#xA;&#xD;&#xA;    if (vao &gt; 0) {&#xD;&#xA;&#xD;&#xA;        val stride = floatsPerVertex * 4&#xD;&#xA;        glBindVertexArray(vao)&#xD;&#xA;&#xD;&#xA;        val vbo = glGenBuffers()&#xD;&#xA;        val ibo = glGenBuffers()&#xD;&#xA;&#xD;&#xA;        if (vbo &gt; 0 &amp;&amp; ibo &gt; 0) {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vbo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, heightMapVertexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            if (positionAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(positionAttribute.location)&#xD;&#xA;                glVertexAttribPointer(positionAttribute.location, 2, GL_FLOAT, false, stride, 0)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (uvAttribute.location &gt;= 0) {&#xD;&#xA;                glEnableVertexAttribArray(uvAttribute.location)&#xD;&#xA;                glVertexAttribPointer(uvAttribute.location, 2, GL_FLOAT, false, stride, 8)&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)&#xD;&#xA;&#xD;&#xA;            glBufferData(GL_ELEMENT_ARRAY_BUFFER, heightMapIndexData, GL_STATIC_DRAW)&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;            throw RuntimeException(&quot;error setting up buffers&quot;)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glBindVertexArray(0)&#xD;&#xA;    } else {&#xD;&#xA;        throw RuntimeException(&quot;error generating vao&quot;)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A draw call does this:&#xD;&#xA;&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;    glDisable(GL_CULL_FACE)&#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glEnable(GL_MULTISAMPLE)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    glViewport(xPosition, flippedY, width, height)&#xD;&#xA;    glUseProgram(heightMapProgram)&#xD;&#xA;    glUniformMatrix4fv(mvMatrixUniform.location, false, mvMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix3fv(nMatrixUniform.location, false, normalMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniformMatrix4fv(mvpMatrixUniform.location, false, mvpMatrix.get(0, floatBuffer))&#xD;&#xA;    glUniform3f(lightDirectionUniform.location, lightDirection.x, lightDirection.y, lightDirection.z)&#xD;&#xA;    glUniform4f(color1Uniform.location, 0.157f, 0.165f, 0.424f, 1.0f)&#xD;&#xA;    glUniform4f(color2Uniform.location, 0.459f, 0.761f, 0.859f, 1.0f)&#xD;&#xA;    glUniform4f(color3Uniform.location, 0.353f, 0.706f, 0.275f, 1.0f)&#xD;&#xA;    glUniform4f(color4Uniform.location, 0.922f, 0.922f, 0.157f, 1.0f)&#xD;&#xA;    glUniform4f(color5Uniform.location, 0.835f, 0.176f, 0.165f, 1.0f)&#xD;&#xA;    glUniform4f(color6Uniform.location, 0.955f, 0.955f, 0.955f, 1.0f)&#xD;&#xA;    glUniform4f(ambientUniform.location, 0.1f, 0.1f, 0.1f, 1.0f)&#xD;&#xA;    glUniform4f(diffuseUniform.location, 0.6f, 0.6f, 0.6f, 1.0f)&#xD;&#xA;    glUniform4f(specularUniform.location, 0.85f, 0.85f, 0.85f, 1.0f)&#xD;&#xA;    glUniform1f(shininessUniform.location, 1.7f)&#xD;&#xA;    glUniform1f(heightScaleUniform.location, heightMapScaleFactor.value)&#xD;&#xA;    glUniform1f(uvScaleUniform.location, heightMap.width / textureResolution)&#xD;&#xA;    glUniform1i(heightMapTextureUniform.location, 0)&#xD;&#xA;    glActiveTexture(GL_TEXTURE0)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId)&#xD;&#xA;    glBindVertexArray(vao)&#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0)&#xD;&#xA;    glBindVertexArray(0)&#xD;&#xA;    glDisable(GL_SCISSOR_TEST)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are the shaders for what they're worth even though reducing these to #version 130 doesn't help and it doesn't work with or without the commented code on ATI. Nvidia runs all variations. The shaders themselves don't appear to have any impact on the issue.&#xD;&#xA;&#xD;&#xA;vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    in vec2 position;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    &#xD;&#xA;    out VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexOut;&#xD;&#xA;    &#xD;&#xA;    void main () {&#xD;&#xA;        VertexOut.uv = uv;&#xD;&#xA;        VertexOut.position = position;&#xD;&#xA;        float height = texture(heightMapTexture, uv).r * heightScale;&#xD;&#xA;        gl_Position = modelViewProjectionMatrix * vec4(position, height, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform mat4 modelViewProjectionMatrix;&#xD;&#xA;    uniform mat4 modelViewMatrix;&#xD;&#xA;    uniform mat3 normalMatrix;&#xD;&#xA;    uniform vec3 lightDirection;&#xD;&#xA;    uniform vec4 color1;&#xD;&#xA;    uniform vec4 color2;&#xD;&#xA;    uniform vec4 color3;&#xD;&#xA;    uniform vec4 color4;&#xD;&#xA;    uniform vec4 color5;&#xD;&#xA;    uniform vec4 color6;&#xD;&#xA;    uniform vec4 ambientColor;&#xD;&#xA;    uniform vec4 diffuseColor;&#xD;&#xA;    uniform vec4 specularColor;&#xD;&#xA;    uniform float shininess;&#xD;&#xA;    uniform float heightScale;&#xD;&#xA;    uniform float uvScale;&#xD;&#xA;    uniform sampler2D heightMapTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in VertexData {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec2 uv;&#xD;&#xA;    } VertexIn;&#xD;&#xA;    &#xD;&#xA;    out vec4 colorOut;&#xD;&#xA;    &#xD;&#xA;    //const ivec3 off = ivec3(-1, 0, 1);&#xD;&#xA;    //&#xD;&#xA;    //const float gamma = 2.2;&#xD;&#xA;    &#xD;&#xA;    //vec3 toLinear(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toLinear(vec4 v) {&#xD;&#xA;    //  return vec4(toLinear(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec3 toGamma(vec3 v) {&#xD;&#xA;    //  return pow(v, vec3(1.0 / gamma));&#xD;&#xA;    //}&#xD;&#xA;    //&#xD;&#xA;    //vec4 toGamma(vec4 v) {&#xD;&#xA;    //  return vec4(toGamma(v.rgb), v.a);&#xD;&#xA;    //}&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    //    if (!gl_FrontFacing) {&#xD;&#xA;    //        colorOut = vec4(0.076f, 0.082f, 0.212f, 1.0f);&#xD;&#xA;    //        return;&#xD;&#xA;    //    }&#xD;&#xA;        colorOut = color1;&#xD;&#xA;    //    vec2 size = vec2(uvScale * 2, 0.0);&#xD;&#xA;    //    float unscaledHeight = texture(heightMapTexture, VertexIn.uv).r;&#xD;&#xA;    //    float height = unscaledHeight * heightScale;&#xD;&#xA;    //    float westPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xy).r * heightScale;&#xD;&#xA;    //    float eastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zy).r * heightScale;&#xD;&#xA;    //    float northPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yx).r * heightScale;&#xD;&#xA;    //    float southPixel = textureOffset(heightMapTexture, VertexIn.uv, off.yz).r * heightScale;&#xD;&#xA;    //    float northWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xx).r * heightScale;&#xD;&#xA;    //    float southEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zz).r * heightScale;&#xD;&#xA;    //    float northEastPixel = textureOffset(heightMapTexture, VertexIn.uv, off.zx).r * heightScale;&#xD;&#xA;    //    float southWestPixel = textureOffset(heightMapTexture, VertexIn.uv, off.xz).r * heightScale;&#xD;&#xA;    //    vec3 va = normalize(vec3(size.xy, eastPixel - westPixel));&#xD;&#xA;    //    vec3 vb = normalize(vec3(size.yx, southPixel - northPixel));&#xD;&#xA;    //    vec3 vc = normalize(vec3(size.xx, southEastPixel - northWestPixel));&#xD;&#xA;    //    vec3 vd = normalize(vec3(size.x, -size.x, southWestPixel - northEastPixel));&#xD;&#xA;    //    vec3 crossNormal = cross(va, vb);&#xD;&#xA;    //    crossNormal = normalize(vec3(crossNormal.x, -crossNormal.y, crossNormal.z));&#xD;&#xA;    //    vec3 xNormal = cross(vd, vc);&#xD;&#xA;    //    xNormal = normalize(vec3(xNormal.y, -xNormal.x, xNormal.z));&#xD;&#xA;    //    vec3 modelNormal = normalize(xNormal + crossNormal);&#xD;&#xA;    //    vec3 normal = normalize(normalMatrix * modelNormal);&#xD;&#xA;    //    float diffuse = max(dot(normal, lightDirection), 0.0) + 0.06;&#xD;&#xA;    //    vec4 lowColor;&#xD;&#xA;    //    vec4 highColor;&#xD;&#xA;    //    float interpolation;&#xD;&#xA;    //    if (unscaledHeight &lt;= 0.05) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color1;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.19) {&#xD;&#xA;    //        lowColor = color1;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.05) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.24) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color2;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.38) {&#xD;&#xA;    //        lowColor = color2;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.24) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.43) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color3;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.57) {&#xD;&#xA;    //        lowColor = color3;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.43) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.62) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color4;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.76) {&#xD;&#xA;    //        lowColor = color4;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.62) * 7.1426;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.81) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color5;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    } else if (unscaledHeight &lt;= 0.95) {&#xD;&#xA;    //        lowColor = color5;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = (unscaledHeight - 0.81) * 7.1426;&#xD;&#xA;    //    } else {&#xD;&#xA;    //        lowColor = color6;&#xD;&#xA;    //        highColor = color6;&#xD;&#xA;    //        interpolation = 0.5;&#xD;&#xA;    //    }&#xD;&#xA;    //    vec4 baseColor = mix(toLinear(lowColor), toLinear(highColor), interpolation);&#xD;&#xA;    //    vec4 lightColor = toLinear(vec4(1.0));&#xD;&#xA;    //    vec4 diffuseColor = vec4(baseColor.rgb * lightColor.rgb * diffuse, 1.0);&#xD;&#xA;    //    vec4 spec = vec4(0.0);&#xD;&#xA;    //    vec3 eye = -normalize(vec3(modelViewMatrix * vec4(VertexIn.position.xy, height, 1.0)));&#xD;&#xA;    //    float intensity = max(dot(normal, lightDirection), 0.0);&#xD;&#xA;    //    if (intensity &gt; 0.0) {&#xD;&#xA;    //        vec3 halfVector = normalize(lightDirection + eye);&#xD;&#xA;    //        spec = toLinear(specularColor) * pow(max(dot(halfVector, normal), 0.0), shininess);&#xD;&#xA;    //    }&#xD;&#xA;    //    colorOut = toGamma(diffuseColor * max(intensity * toLinear(diffuseColor) + spec, toLinear(ambientColor)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The geometry itself is correctly formed in `heightMapTexture` to the best of my knowledge because I've inspected it piece by piece in a debugger and because the strips come out correctly on Nvidia cards. I am assuming there are no fundamental differences in how `GL_TRIANGLE_STRIP` works between Nvidia and ATI. If there is a difference then that's exactly the type of thing this question is trying to figure out. The description of triangle strips in the OpenGL spec doesn't seem to leave much room for differences here if any, so it seems likely that if the strips themselves are formed correctly according to the spec they should work everywhere or nowhere.&#xD;&#xA;&#xD;&#xA;The geometry is a basic hexagonally arranged triangle grid with degenerates in between the strips. I'd like to figure out what features are causing this to output nothing except the `glClear()` on ATI cards so I can get people with different machines looking at the application.&#xD;&#xA;&#xD;&#xA;Here is an example of what it outputs on all the Nvidia machines across various windows and OSX flavors, in case that helps&#xD;&#xA;&#xD;&#xA;[![sample output][1]][1]&#xD;&#xA;&#xD;&#xA;On ATI it displays the gray scissor clear rectangle that is drawn by the snippet:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_SCISSOR_TEST)&#xD;&#xA;    glClearColor(background.r, background.g, background.b, background.a)&#xD;&#xA;    glScissor(xPosition, flippedY, width, height)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)&#xD;&#xA;&#xD;&#xA;Nothing else besides the gray rectangle is displayed.&#xD;&#xA;&#xD;&#xA;In summary, for someone who has something like this working on an ATI card, are these the OpenGL calls that you would use to get it drawing on an ATI card or is there some obvious feature I'm using that's not supported by ATI that's causing the whole thing to not draw. I'm looking for possible differences between how ATI and Nvidia would handle this geometry.&#xD;&#xA;&#xD;&#xA;P.S. I added this note to answer some of the comments that suggest I should go back to a single triangle and debug from scratch on my own. The reason I'm asking this question is that I don't currently have access to ATI hardware. I'm in South America until May and hardware availability is basically nil where I am. I have several workstations that I brought with me for work, but they all have Nvidia hardware. I have to do a full build and then ship the product to someone in a different time zone each time I attempt to correct the issue. I need to be more purposeful in my fixes than going back to drawing a triangle and working up from scratch. I would love to debug it myself on the affected hardware step by step. I just can't right now. I need to get the code closer to a likely solution before sending another build, so I'm looking for some educated guesses from people with direct experience with this type of geometry on ATI hardware. I would greatly appreciate more understanding than &quot;That's what debug is for. Go back to a triangle.&quot;, because those comments really don't help me or anyone else reading this later. This problem seems like something that someone must have encountered before because it seems like a pretty standard way to draw a heightmap. I think that this question will help anyone else who has this problem in the future. I've lost several days to this, and there is no published answer to anything similar that I could find. If this remains unanswered until May, when I return home, I will write the answer myself and remove this note, but I hope it doesn't come to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NTg6O.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10169" PostHistoryTypeId="4" PostId="4442" RevisionGUID="372c8908-8215-44a8-b9b7-17b58d143de6" CreationDate="2017-01-01T13:06:11.197" UserId="5256" Comment="Improved the title" Text="Cubic Environment Mapping in a Ray Tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="10170" PostHistoryTypeId="5" PostId="4442" RevisionGUID="372c8908-8215-44a8-b9b7-17b58d143de6" CreationDate="2017-01-01T13:06:11.197" UserId="5256" Comment="Improved the title" Text="I have implemented a sky rendering model in my ray tracer which saves the color of the sky to an image. I was wondering how I can render the sky dome and texture map the image on to it.&#xD;&#xA;&#xD;&#xA;Do I render the sphere at the center of the environment and add the image to the inside of the sphere? How would I add a texture to the inside of a sphere as opposed to the outside in code? Do I just reverse the normals?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10171" PostHistoryTypeId="4" PostId="4442" RevisionGUID="806e4c0a-c649-48f7-b247-85f220862df4" CreationDate="2017-01-01T13:32:25.380" UserId="5256" Comment="edited title" Text="Skybox in a Ray Tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="10174" PostHistoryTypeId="2" PostId="4444" RevisionGUID="d14ca64b-e527-42ba-a579-53802d5d17d2" CreationDate="2017-01-01T17:14:19.177" UserId="5519" Text="I'm not entirely sure if I understood the question, but it seems like you want to implement environment map illumination in your ray tracer (you seem to be thinking in real-time, though). I will approach the general solution for offline renderers without assuming anything about the scene except the environment sphere.&#xD;&#xA;&#xD;&#xA;This is generally done by considering your environment as a light source. Let's say that you use a sphere with a radius big enough to contain your scene. Then, you sample it as you would sample an area light source. You can think of this sphere as a **textured light source**.&#xD;&#xA;&#xD;&#xA;The contribution of the direct lighting on the radiance leaving a point $x$ on the direction $\Theta$ would be:&#xD;&#xA;$$&#xD;&#xA;L_{\text{direct}}(x \rightarrow \Theta) = L_{\text{lights}}(x \rightarrow \Theta) + L_{\text{env}}(x \rightarrow \Theta)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where the environment map contribution is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{\text{env}}(x \rightarrow \Theta) = {\int_{\Omega_x} L_{\text{tex}}}(x \leftarrow \Psi)f_r(x, \Theta \leftrightarrow \Psi)V(x, \Psi) \cos(\Psi, N_x)\, d\omega_{\Psi} \qquad (1)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Note that, here, $\Psi$ are directions to the sphere, $V(x, \Psi) = 1$ if and only if the sphere is visible from that direction and $V(x, \Psi) = 0$ otherwise, $f_r$ is the BRDF and $L_{\text{tex}}$ is the color on the texture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Directions $\Psi$ can be generated with a parameterization of the sphere. If you want something simple, then this is enough, **just treat it as a textured area light and emit whatever color is on the texture on the sampled point**. If you want something more elaborate, consider the rest of the text.&#xD;&#xA;&#xD;&#xA;With this said, environment mapping can be inefficient if not implemented with care. &#xD;&#xA;&#xD;&#xA;Also, I am assuming you only implemented area lights that emit uniformly, so it was okay to sample its area uniformly. However, it is clear that the sphere is a light source where some parts contribute more than others since the colors vary on the texture. This, combined with the fact that the sphere occupies the entire solid angle around a point (instead of the hemisphere that you usually sample), skyrockets the variance of the estimator of $(1)$. The visibility term $V(x, \Psi)$ further complicates things regarding variance, depending on your scene (if it very exposed or not).&#xD;&#xA;&#xD;&#xA;In order to sample and estimate $(1)$, you have to consider:&#xD;&#xA;&#xD;&#xA;**Parameterization of the sphere**: You need to decide how to parameterize your sphere. You need to have a space where you can generate random points and map to a point on the sphere to get a direction $\Psi$ and the color from the texture. You can just use typical the latitude-longitude parameterization. &#xD;&#xA;&#xD;&#xA;For more elaborate, better distributed parameterizations: [paraboloid parameterization][1] [page 4]; [concentric-map parameterization][2].&#xD;&#xA;&#xD;&#xA;**PDF $p(\Psi)$ used for sampling the sphere**: It is possible to reduce the variance that I mentioned earlier. You can importance sample only using the term $\cos(\Psi, N_x)$ (i.e. cosine lobe sampling), but even so it is possible to do better than that. If the BRDF $f_r$ is simple, you can sample the product of the BRDF with $\cos(\Psi, N_x)$.&#xD;&#xA;&#xD;&#xA;There are other methods. In [[Kollig, Keller; 03]][3] a PDF is built from the 2D array of the texture itself. This way, it is possible to get more samples from directions from where the map contributes more. A PDF from the product of this with the BRDF would yield the best results considering a compromise between the sampling cost and actual variance reduction.&#xD;&#xA;&#xD;&#xA;For a more elaborate and adaptive solution, check [[Agarwal et. al, 03]][4].&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedevs.org/uploads/realistic-hardware-accelerated-shading-and-lighting.pdf&#xD;&#xA;  [2]: https://pdfs.semanticscholar.org/4322/6a3916a85025acbb3a58c17f6dc0756b35ac.pdf&#xD;&#xA;  [3]: https://www.uni-kl.de/AG-Heinrich/EIbHDRI.pdf&#xD;&#xA;  [4]: http://graphics.ucsd.edu/~sagarwal/structured.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10175" PostHistoryTypeId="2" PostId="4445" RevisionGUID="5411b33f-907f-48e6-9adf-f1d907fd452a" CreationDate="2017-01-01T17:37:32.553" UserId="1649" Text="I think that it is important to *classify* between different types of animations here. One rough classification could be&#xD;&#xA;&#xD;&#xA;1. Rigid body animations&#xD;&#xA;2. Vertex skinning animations&#xD;&#xA;3. Others...&#xD;&#xA;&#xD;&#xA;# Rigid body animations&#xD;&#xA;&#xD;&#xA;This refers to animations where the actual geometry data does not change. For example, you could have a geometric object, like a unit cube, and apply (usually affine) transformations to it: You can rotate, translate or scale this object. This is usually accomplished by some sort of scene graph: Each *node* of this scene graph can have information about the rotation, translation and scaling that should be applied to the objects. In general, this is something that can be expressed with a 4x4 transformation matrix.&#xD;&#xA;&#xD;&#xA;The key point is that you don't have to store &quot;animated geometry data&quot;. You only have to store the geometry data *once*, in its original state. In addition to that, you store the key frames of the transformation. &#xD;&#xA;&#xD;&#xA;In your case, if you wanted to do a rigid body animation, you could store the geometry in an OBJ file, and additionally store the key frame information in an arbitrary form, for example&#xD;&#xA;&#xD;&#xA;    TIME  TRANSLATION&#xD;&#xA;    0.0   ( 0, 0, 0)&#xD;&#xA;    0.1   (10, 0, 0)&#xD;&#xA;    0.2   (10,10, 0)&#xD;&#xA;    0.3   ( 0,10, 0)&#xD;&#xA;    0.4   ( 0, 0, 0)&#xD;&#xA;&#xD;&#xA;This could describe a movement of the object along a rectangular path, taking 0.4 seconds. Fortunately, you don't have to create your own file format for that. There already are solutions for storing this sort of animation data. For example, the COLLADA format already supports animations like this. A more compact representation of such an animation can be stored in a [glTF asset](https://github.com/KhronosGroup/glTF/). For example, it can represent animations like this one, from the glTF sample models repository:&#xD;&#xA;&#xD;&#xA;[![animation][1]][1]&#xD;&#xA;&#xD;&#xA;# Vertex skinning animations&#xD;&#xA;&#xD;&#xA;This technique refers, roughly speaking, to cases where you have an &quot;initial&quot; geometry, and you can define &quot;rules&quot; of how this geometry should be deformed based on the pose of a skeleton. As the name suggests, this is mainly intended for character animations, where you define a skeleton consisting of the &quot;bones&quot; of the character, and the geometry defines the &quot;skin&quot; of the character. Vertex skinning is also supported by different file formats like COLLADA or glTF. The effect is shown in this image, again, from the glTF sample models:&#xD;&#xA;&#xD;&#xA;[![skinning][2]][2]&#xD;&#xA;&#xD;&#xA;As already mentioned by [joojaa in his answer](http://computergraphics.stackexchange.com/a/4443/1649), implementing vertex skinning according to the specifications of these file formats may be a bit tricky. Additionally, a considerable amount of the skinning computations is usually done by the *vertex shader*. So for a ray-tracer, you would have to move these computations into your application code. &#xD;&#xA;&#xD;&#xA;# Others...&#xD;&#xA;&#xD;&#xA;This refers to what you already alluded to in the question: There may be cases where the animation is *not* a simple transformation of rigid objects, and where you cannot define any &quot;rules&quot; of how the vertices should be transformed. For example, when the vertex positions are computed by a simulator, like a fluid simulator or a *soft* body simulator. &#xD;&#xA;&#xD;&#xA;In doubt, it may simply be necessary to actually store the positions of all vertices, frame for frame. You could achieve this as a sequence of OBJ files. But note that OBJ files contain ASCII data, and thus, are usually *large* and the geometry data has to be parsed before it can be used. Storing the data in a binary form that can be used by the application directly may be beneficial here. &#xD;&#xA;&#xD;&#xA;There are some possible approaches for reducing the amount of data that has to be stored. For example, one could extend the concept of &quot;key frames&quot; here. For example, one could store the initial configuration of al vertices, and then only store the *movement* of vertices that acutally have *changed* between two frames. But of course, if (nearly) *all* vertices changed, the savings may be diminishing. &#xD;&#xA;&#xD;&#xA;I'm not aware of any universally applicable, &quot;standardized&quot; solutions for this. Maybe some of the solutions that [joojaa referred to in his answer](http://computergraphics.stackexchange.com/a/4443/1649) could be helpful here. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mm5ek.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/C85k5.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="10179" PostHistoryTypeId="2" PostId="4447" RevisionGUID="9c5a3beb-8c2e-4fd6-bfcd-d92c03239c14" CreationDate="2017-01-02T08:32:05.583" UserId="5609" Text="In older versions of OpenGL there were things like:&#xD;&#xA;&#xD;&#xA; - glLight(...)&#xD;&#xA;&#xD;&#xA; - gl_LightSourceParameters&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The modern way of doing lighting is passing light source parameters manually to the shader in vao-s? Or uniforms?&#xD;&#xA;&#xD;&#xA;Why are these things decrepated? &#xD;&#xA;&#xD;&#xA;And if I have 100 light sources in the scene, I obviously can't compute lighting with all of them. So somehow in a specific object's shading I have to only care about the light sources which are important for it.&#xD;&#xA;&#xD;&#xA;I think that I should move for example only 8 light sources to the shaders, based on their &quot;strength&quot;.&#xD;&#xA;&#xD;&#xA;But isn't this too complicated to call every frame? &#xD;&#xA;&#xD;&#xA;How should I handle lots of light sources (in the scene)?&#xD;&#xA;&#xD;&#xA;*/I read about deferred lighting, but is that the only way?/*" ContentLicense="CC BY-SA 3.0" />
  <row Id="10180" PostHistoryTypeId="1" PostId="4447" RevisionGUID="9c5a3beb-8c2e-4fd6-bfcd-d92c03239c14" CreationDate="2017-01-02T08:32:05.583" UserId="5609" Text="Modern way of light sources in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10181" PostHistoryTypeId="3" PostId="4447" RevisionGUID="9c5a3beb-8c2e-4fd6-bfcd-d92c03239c14" CreationDate="2017-01-02T08:32:05.583" UserId="5609" Text="|opengl|shader|lighting|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10182" PostHistoryTypeId="2" PostId="4448" RevisionGUID="c2e9c0f7-9dba-4917-a794-7396bc6e6e54" CreationDate="2017-01-02T09:48:30.780" UserId="5519" Text="**Why are they deprecated?**&#xD;&#xA;&#xD;&#xA;Those functions are deprecated because the OpenGL API moved in favor of a programmable pipeline in contrast with the old fixed pipeline. The programmable pipeline allows the flexibility necessary to enable a wide variety of effects and solutions that before were difficult or not possible at all to implement. You can [still access those functions][1], as they are necessary to support older systems, but besides that I don't see any reason not to use the programmable pipeline.&#xD;&#xA;&#xD;&#xA;**How to pass parameters**&#xD;&#xA;&#xD;&#xA;If we are talking about parameters of lights (such as their position or intensity), you can pass those using uniforms. Particularly, you should look at [Uniform Buffer Objects][2].&#xD;&#xA;&#xD;&#xA;It would look like this in a shader:&#xD;&#xA;&#xD;&#xA;    struct Light {&#xD;&#xA;       int type;&#xD;&#xA;       vec3 diffuse;&#xD;&#xA;       vec3 position;&#xD;&#xA;	   bool on;&#xD;&#xA;       ...&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    #define MAX_NUM_LIGHTS 8&#xD;&#xA;&#xD;&#xA;    uniform lightBlock {&#xD;&#xA;	    Light lights[MAX_NUM_LIGHTS];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Note that this already gives you a way of passing the lights that you want. Make your shaders expect an uniform buffer with 8 lights, copy those into an array in your client code and send them using the API. For more info on how to do this using the API functions, check the link above about UBOs and [this][4].&#xD;&#xA;&#xD;&#xA;**Is it too complicated to call every frame?**&#xD;&#xA;&#xD;&#xA;Depends on your scene and the criteria for how to choose the lights that you want to pass to the shader. If you are worried about sending the data of 8 lights through uniforms each frame, then don't, that is the least of your worries. The problem lies in the selection process of the lights and the complexity of your scene/shading model, as the cost increases with the number of lights.&#xD;&#xA;&#xD;&#xA; - **Forward Renderer**: If your scene and shading models are simple, maybe 8 lights are okay. If you implement modern shading models, 8 lights might be a bit too much. The point is that you will have to test it with the scene and shading models and find a compromise between all of that. Maybe pass 4 instead of 8 lights, maybe you should simplify shading models, etc.&#xD;&#xA; - **Deferred Renderer**: A deferred renderer does help with multiple light rendering due to the way it is designed. However, deferred rendering may introduce other difficulties as it is, in my opinion, a more complex system. Also, transparency and other aspects may be a pain to deal with. &#xD;&#xA;&#xD;&#xA; - **Other considerations**: Keep in mind that there are possible optimizations. It may be possible to optimize specific lights. Maybe not all of them need to be dynamic: think of [light maps][3] and other [image based lighting][5]. You should consider if your scene can apply any of this.&#xD;&#xA;&#xD;&#xA;**In summary**, choosing between deferred or forward is a big decision. Carefully think about your scene requirements first and devise a strategy for light selection. Take into account the complexity of your shading models. For optimization, you can combine several techniques, such as simplifying some lights that are far away from the camera and only pass the relevant ones. When you have a framework for testing, find a compromise between all of this.&#xD;&#xA;&#xD;&#xA;[1]: https://www.khronos.org/opengl/wiki/Legacy_OpenGL&#xD;&#xA;[2]: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object&#xD;&#xA;[3]: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-15-lightmaps/&#xD;&#xA;[4]: https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)&#xD;&#xA;[5]: https://en.wikipedia.org/wiki/Image-based_lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="10183" PostHistoryTypeId="5" PostId="4443" RevisionGUID="1085c402-f592-41d6-9b05-576b76411ec8" CreationDate="2017-01-02T10:43:30.797" UserId="231" Comment="Minor tidying" Text="Pixar spent quite much time, money and other capital to archive all their renders. What they did was just to store the raw render description files their render engine used. The reason for this is that it's the only way to ensure that the features stay intact. Of course they had a very well documented standardized format to work with. &#xD;&#xA;&#xD;&#xA;The benefit of this method is that it stores things relevantly. In other words static objects can be stored static and only animation objects need to be stored frame by frame which is the only way to ensure compatibility for animation without relying on host apps to do this for you.&#xD;&#xA;&#xD;&#xA;Alembic works on a similar principle. The downside is big formats. But note that formats such as FBX and Collada (*.dae) are not much better. While it's true that they can contain some of the animation data they cannot always do everything that you want them to do. Which means that in the end it might not do what you want.&#xD;&#xA;&#xD;&#xA;The animation exchange formats (FBX, Collada etc...) do not usually store vertex positions, if they did then they would just have same problem as your obj storage. Instead they store the modification history so that they can redo the animation. So for example the bones are stored as transforms and the vertex weights are used to compute their position. The downside is that your reader needs to implement substantial amounts of the animation core. And anything the format does not know how to do is stored either as point caches, or not at all. Realistically speaking for FBX you would use the API to do this. Implementing it yourself is a quite big undertaking, it may be cheaper to just buy more storage space.&#xD;&#xA;&#xD;&#xA;Personally I would implement something like the RI spec for my own renderer. If not RI spec itself which would allow you to swap renderer if need be (also the other way around a user could swap to your renderer without many changes)." ContentLicense="CC BY-SA 3.0" />
  <row Id="10192" PostHistoryTypeId="2" PostId="4450" RevisionGUID="5ea8291b-c7f1-4002-b94b-6115d4ca20b2" CreationDate="2017-01-02T16:33:10.507" UserId="2096" Text="Can i pass the data to the GPU through multiple cores with OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10193" PostHistoryTypeId="1" PostId="4450" RevisionGUID="5ea8291b-c7f1-4002-b94b-6115d4ca20b2" CreationDate="2017-01-02T16:33:10.507" UserId="2096" Text="Why can't i utilize multiple cores with OpenGL like vulkan?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10194" PostHistoryTypeId="3" PostId="4450" RevisionGUID="5ea8291b-c7f1-4002-b94b-6115d4ca20b2" CreationDate="2017-01-02T16:33:10.507" UserId="2096" Text="|opengl|opengl-es|vulkan|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10195" PostHistoryTypeId="4" PostId="4450" RevisionGUID="0d8d98b2-7fec-4f04-b51a-6e8635448b94" CreationDate="2017-01-02T18:27:29.227" UserId="2096" Comment="edited title" Text="Why can't i utilize multiple CPU cores with OpenGL like vulkan?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10196" PostHistoryTypeId="2" PostId="4451" RevisionGUID="304f5889-a0c3-4376-af69-7b825a6ea933" CreationDate="2017-01-02T18:47:54.863" UserId="2654" Text="Because the fundamental foundation of OpenGL makes multi-CPU-core submission impossible.&#xD;&#xA;&#xD;&#xA;[OpenGL, at its core, is a *synchronous API*][1]. Every OpenGL command behaves &quot;as if&quot; it were executed and completed immediately. Sure, `glFlush` and `glFinish` are provided, so that implementations can have some asynchronous execution of commands. But these are essentially fig leaves over the definition of OpenGL as synchronous.&#xD;&#xA;&#xD;&#xA;You can attach a texture to an FBO, bind that FBO, render to it, unbind that FBO, bind the texture as a source, and read from it. You can do all of this without *any thought* as to the fact that you've issues two sets of commands that write to then read from the same image. OpenGL implementations are required to issue whatever synchronization mechanisms are needed to make this work. You as the user can be completely oblivious to this.&lt;sup&gt;1&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Because of that, consider what would happen if you could issue that render-to-texture in one thread and the read-from-texture in another. How exactly would that even work? You would need some way to say &quot;don't execute the read until the write is done&quot;. But since the two sets of commands are on different threads, how do you say that?&#xD;&#xA;&#xD;&#xA;OpenGL has no mechanism for doing so; the closest it gets would be some form of fence sync. And even that would require that the render-to-texture thread has already finished sending those commands, since `glFenceSync` issues the fence actual fence (you cannot create a fence that has not yet been submitted). Which means that the render-to-texture thread may as well send the read-from-texture commands too.&#xD;&#xA;&#xD;&#xA;To make OpenGL work asynchronously means making lots of adjustments to its memory model. You'll have to add lots of commands for making things visible to other threads. For allowing thread A to not have its commands execute until thread B is finished. You'd need to make command buffers and queues first-class constructs of the API. And so forth.&#xD;&#xA;&#xD;&#xA;And you have to do it in a way that's backwards compatible with the existing memory model. Unless you want to go through another core/compatibility split *again*.&#xD;&#xA;&#xD;&#xA;NV_command_list shows the challenges of trying to build this sort of thing into OpenGL. They force you to use ARB_bindless_texture. They had to invent bindless buffers, so that you can provide vertex arrays, UBOs, and SSBOs.&#xD;&#xA;&#xD;&#xA;And even then, it's not something that AMD could even implement. Why? Because of image layouts. NVIDIA's hardware has fewer layouts and handles transitions automatically. AMD's hardware requires explicit control of layouts. Once you break the synchronous memory model, that implementation detail of what layout a texture is in becomes really important. You *have to* have control over it. You have to explicitly state it in various API, and you have to know to change it when you use a texture in a different way.&#xD;&#xA;&#xD;&#xA;This is also almost certainly why AMD doesn't implement D3D11 deferred contexts.&#xD;&#xA;&#xD;&#xA;Or you can do what Khronos did: make an API that naturally handles all of this stuff. A clean break is ultimately best for everyone. It allows us to jettison other garbage that OpenGL had, so that we can have a nice, clean, lower-level API.&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;1&lt;/sup&gt;: While you can be oblivious, obviously you *shouldn't* be oblivious if you care about things like performance. You should put some work between the render-to-texture and the read from that texture, if at all possible. That's one of the biggest problems with OpenGL's synchronous-by-default API: it makes it easy to do things the wrong way, since the API itself doesn't force you to issue that synchronization. In Vulkan, you *cannot* be ignorant of that synchronization.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Memory_Model" ContentLicense="CC BY-SA 3.0" />
  <row Id="10197" PostHistoryTypeId="2" PostId="4452" RevisionGUID="fa4f9dde-293b-4d85-8d90-cbd3d69c2c9f" CreationDate="2017-01-02T18:59:49.803" UserId="5770" Text="Using my raytracing engine, I'd like to generate a 360 degree video which could then be uploaded on Youtube.&#xD;&#xA;By looking on the internet, I couldn't find any specific details about how to do so. I am using FFMPEG to generate short movies.&#xD;&#xA;I saw something about stitching but that didn't really help me that much.&#xD;&#xA;&#xD;&#xA;Could you provide me some hints, please ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10198" PostHistoryTypeId="1" PostId="4452" RevisionGUID="fa4f9dde-293b-4d85-8d90-cbd3d69c2c9f" CreationDate="2017-01-02T18:59:49.803" UserId="5770" Text="How to generate a 360 degre video" ContentLicense="CC BY-SA 3.0" />
  <row Id="10199" PostHistoryTypeId="3" PostId="4452" RevisionGUID="fa4f9dde-293b-4d85-8d90-cbd3d69c2c9f" CreationDate="2017-01-02T18:59:49.803" UserId="5770" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10200" PostHistoryTypeId="2" PostId="4453" RevisionGUID="bc12b88f-a6dd-470f-b730-f3189d4a64dd" CreationDate="2017-01-02T21:06:23.077" UserId="3470" Text="[YouTube Help: Upload 360-degree videos][1]&#xD;&#xA;&gt;  We recommend uploading  360 videos (equirectangular format with a 2:1 aspect ratio) at a resolution of 7168x3584 or higher, up to 8192x4096.&#xD;&#xA;&#xD;&#xA;That means the format uses [Equirectangular projection][2] for capturing the view from all directions to a normal video format with a 2:1 aspect ratio. The projection should translate nicely to a raytracing engine with a simple mapping from pixel coordinates to the ray direction using the formula in the wiki article.&#xD;&#xA;&#xD;&#xA;  [1]: https://support.google.com/youtube/answer/6178631?hl=en&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Equirectangular_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="10201" PostHistoryTypeId="5" PostId="4451" RevisionGUID="6c77af79-436d-4b6f-a22c-d51343a5ab71" CreationDate="2017-01-02T21:57:19.360" UserId="2654" Comment="added 64 characters in body" Text="Because the fundamental foundation of OpenGL makes multi-CPU-core submission impossible.&#xD;&#xA;&#xD;&#xA;[OpenGL, at its core, is a *synchronous API*][1]. Every OpenGL command behaves &quot;as if&quot; it were executed and completed immediately. Sure, `glFlush` and `glFinish` are provided, so that implementations can have some asynchronous execution of commands. But these are essentially fig leaves over the definition of OpenGL as synchronous.&#xD;&#xA;&#xD;&#xA;You can attach a texture to an FBO, bind that FBO, render to it, unbind that FBO, bind the texture as a source, and read from it. You can do all of this without *any thought* as to the fact that you've issued two sets of commands where there can be zero overlap between them. This is because OpenGL implementations are required to issue whatever synchronization mechanisms are needed to make this work. You as the user can be completely oblivious to this.&lt;sup&gt;1&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;Because of that, consider what would happen if you could issue that render-to-texture in one thread and the read-from-texture in another. How exactly would that even work? You would need some way to say &quot;don't execute the read until the write is done&quot;. But since the two sets of commands are on different threads, how do you say that?&#xD;&#xA;&#xD;&#xA;OpenGL has no mechanism for doing so; the closest it gets would be some form of fence sync. And even that would require that the render-to-texture thread has already finished sending those commands, since `glFenceSync` issues the fence actual fence (you cannot create a fence that has not yet been submitted). Which means that the render-to-texture thread may as well send the read-from-texture commands too.&#xD;&#xA;&#xD;&#xA;To make OpenGL work asynchronously means making lots of adjustments to its memory model. You'll have to add lots of commands for making things visible to other threads. For allowing thread A to not have its commands execute until thread B is finished. You'd need to make command buffers and queues first-class constructs of the API. And so forth.&#xD;&#xA;&#xD;&#xA;And you have to do it in a way that's backwards compatible with the existing memory model. Unless you want to go through another core/compatibility split *again*.&#xD;&#xA;&#xD;&#xA;NV_command_list shows the challenges of trying to build this sort of thing into OpenGL. They force you to use ARB_bindless_texture. They had to invent bindless buffers, so that you can provide vertex arrays, UBOs, and SSBOs.&#xD;&#xA;&#xD;&#xA;And even then, it's not something that AMD could even implement. Why? Because of image layouts. NVIDIA's hardware has fewer layouts and handles transitions automatically. AMD's hardware requires explicit control of layouts. Once you break the synchronous memory model, that implementation detail of what layout a texture is in becomes really important. You *have to* have control over it. You have to explicitly state it in various API, and you have to know to change it when you use a texture in a different way.&#xD;&#xA;&#xD;&#xA;This is also almost certainly why AMD doesn't implement D3D11 deferred contexts.&#xD;&#xA;&#xD;&#xA;Or you can do what Khronos did: make an API that naturally handles all of this stuff. A clean break is ultimately best for everyone. It allows us to jettison other garbage that OpenGL had, so that we can have a nice, clean, lower-level API.&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;1&lt;/sup&gt;: While you can be oblivious, obviously you *shouldn't* be oblivious if you care about things like performance. You should put some work between the render-to-texture and the read from that texture, if at all possible. That's one of the biggest problems with OpenGL's synchronous-by-default API: it makes it easy to do things the slow way, since the API itself doesn't force you to issue that synchronization. In Vulkan, you *cannot* be ignorant of that synchronization. Or at least, not without your code invoking UB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Memory_Model" ContentLicense="CC BY-SA 3.0" />
  <row Id="10202" PostHistoryTypeId="2" PostId="4454" RevisionGUID="65c740fa-ff79-4f2c-bc0b-ba3a833e0bdd" CreationDate="2017-01-02T22:12:26.490" UserId="2237" Text="I'm trying to load an array of float to a fragment shader using a uniform buffer object, but it doesn't work.&#xD;&#xA;In the fragment shader I declared the following uniform block:&#xD;&#xA;&#xD;&#xA;    /// Spectrum samples.&#xD;&#xA;    const int samples = 31;&#xD;&#xA;    &#xD;&#xA;    layout(std140) uniform SpectralDataBlock {&#xD;&#xA;        &#xD;&#xA;        float illuminant[samples];&#xD;&#xA;        float object[samples];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Then on client side in my C++ code:&#xD;&#xA;&#xD;&#xA;    float illuminant[31] = {&#xD;&#xA;        82.754900,91.486000,93.431800,86.682300,104.865000,117.008000,117.812000,114.861000,115.923000,108.811000,109.354000,&#xD;&#xA;        107.802000,104.790000,107.689000,104.405000,104.046000,100.000000,96.334200,95.788000,88.685600,90.006200,89.599100,&#xD;&#xA;        87.698700,83.288600,83.699200,80.026800,80.214600,82.277800,78.284200,69.721300,71.609100&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float object[31] = {&#xD;&#xA;        0.051, 0.05, 0.049, 0.049, 0.049, 0.049, 0.048, 0.047, 0.045, 0.044,&#xD;&#xA;        0.044, 0.044, 0.044, 0.044, 0.045, 0.047, 0.05, 0.057, 0.072, 0.109,&#xD;&#xA;        0.192, 0.332, 0.486, 0.598, 0.654, 0.686, 0.7, 0.707, 0.718, 0.724,&#xD;&#xA;        0.729&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    std::copy(illuminant, illuminant + 31, spectralData);&#xD;&#xA;    std::copy(object, object + 31, spectralData + 31);&#xD;&#xA;    &#xD;&#xA;    blockId = glGetUniformBlockIndex(program, &quot;SpectralDataBlock&quot;);&#xD;&#xA;    glUniformBlockBinding(program, blockId, bindingPoint);&#xD;&#xA;    glGetActiveUniformBlockiv(program, blockId, GL_UNIFORM_BLOCK_DATA_SIZE, &amp;blockSize);&#xD;&#xA;    &#xD;&#xA;    glGenBuffers(1, &amp;bufferId);&#xD;&#xA;    glBindBuffer(GL_UNIFORM_BUFFER, bufferId);&#xD;&#xA;    glBufferData(GL_UNIFORM_BUFFER, blockSize, spectralData, GL_DYNAMIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, bufferId);&#xD;&#xA;&#xD;&#xA;Unfortunately, the data doesn't get correctly loaded. &#xD;&#xA;&#xD;&#xA;Are there any limitation in OpenGL ES the prevent to use float[] in an uniform buffer object? Are there any error in my code above?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10203" PostHistoryTypeId="1" PostId="4454" RevisionGUID="65c740fa-ff79-4f2c-bc0b-ba3a833e0bdd" CreationDate="2017-01-02T22:12:26.490" UserId="2237" Text="OpenGL ES 3 - Uniform buffer object with float array" ContentLicense="CC BY-SA 3.0" />
  <row Id="10204" PostHistoryTypeId="3" PostId="4454" RevisionGUID="65c740fa-ff79-4f2c-bc0b-ba3a833e0bdd" CreationDate="2017-01-02T22:12:26.490" UserId="2237" Text="|opengl-es|uniform-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10205" PostHistoryTypeId="2" PostId="4455" RevisionGUID="b15871e6-ffd9-41a2-8653-c2d251846a64" CreationDate="2017-01-02T22:23:54.210" UserId="5772" Text="It seems that in all existing graphics libraries, 3D objects are always described in terms of triangles. Drawing triangles can be implemented very efficiently on video hardware and since any 3D object can be approximated with trinagles, triangles are the only basic element needed. Triangles can be represented by 3-tuples and are simple to work with.&#xD;&#xA;&#xD;&#xA;I have always wondered whether other approaches have been tried. There are certain complications when approximating spherical objects with triangles. Have there been any alternative approaches to drawing spherical objects (for example, without using polygons for approximations)? What are the problems with such approaches that make using triangles the best option?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10206" PostHistoryTypeId="1" PostId="4455" RevisionGUID="b15871e6-ffd9-41a2-8653-c2d251846a64" CreationDate="2017-01-02T22:23:54.210" UserId="5772" Text="Is there a way to draw spherical objects without trinagles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10207" PostHistoryTypeId="3" PostId="4455" RevisionGUID="b15871e6-ffd9-41a2-8653-c2d251846a64" CreationDate="2017-01-02T22:23:54.210" UserId="5772" Text="|shader|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10208" PostHistoryTypeId="5" PostId="4455" RevisionGUID="40dc36ce-8a42-4408-ada2-0ae73891ec1e" CreationDate="2017-01-02T23:28:55.927" UserId="231" Comment="Minor typos" Text="It seems that in all existing graphics libraries, 3D objects are always described in terms of triangles. Drawing triangles can be implemented very efficiently on video hardware and since any 3D object can be approximated with triangles, triangles are the only basic element needed. Triangles can be represented by 3-tuples and are simple to work with.&#xD;&#xA;&#xD;&#xA;I have always wondered whether other approaches have been tried. There are certain complications when approximating spherical objects with triangles. Have there been any alternative approaches to drawing spherical objects (for example, without using polygons for approximations)? What are the problems with such approaches that make using triangles the best option?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10209" PostHistoryTypeId="4" PostId="4455" RevisionGUID="40dc36ce-8a42-4408-ada2-0ae73891ec1e" CreationDate="2017-01-02T23:28:55.927" UserId="231" Comment="Minor typos" Text="Is there a way to draw spherical objects without triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10210" PostHistoryTypeId="2" PostId="4456" RevisionGUID="19a5cd67-ab8c-4aad-9612-c1f0b6bd9be4" CreationDate="2017-01-02T23:50:23.747" UserId="2654" Text="Let's review what the specification says about `std140` layout of arrays:&#xD;&#xA;&#xD;&#xA;&gt; If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and **rounded up to the base alignment of a `vec4`**. The array may have padding at the end; the base offset of the member following the array is **rounded up to the next multiple of the base alignment**.&#xD;&#xA;&#xD;&#xA;Emphasis added.&#xD;&#xA;&#xD;&#xA;So, if you have an array of `float`, the array stride shall be the same as the base alignment of a `vec4`. Also, each array will be padded at the end to the base alignment of a `vec4`. Yes, a `float[]` takes up the same room as a `vec4[]` of the same size.&#xD;&#xA;&#xD;&#xA;Welcome to the wonderful world of `std140` layout.&#xD;&#xA;&#xD;&#xA;If you want to have a real array of floats in a UBO... well, it's best to *avoid* wanting that. But if you have absolutely no other choice, then I suggest making it an array of `vec4`. To fetch a single float from this array, use math:&#xD;&#xA;&#xD;&#xA;    arrayOfVec4[index / 4][index % 4]&#xD;&#xA;&#xD;&#xA;Note that OpenGL ES 3.0 does allow non-constant array indexing of `vec` and `mat` types. It also allows the integer operations needed to pull this off." ContentLicense="CC BY-SA 3.0" />
  <row Id="10211" PostHistoryTypeId="5" PostId="4456" RevisionGUID="72fe3f4a-71c7-4199-8107-b57d8e415365" CreationDate="2017-01-02T23:59:41.573" UserId="2654" Comment="added 183 characters in body" Text="Let's review what the specification says about `std140` layout of arrays:&#xD;&#xA;&#xD;&#xA;&gt; If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and **rounded up to the base alignment of a `vec4`**. The array may have padding at the end; the base offset of the member following the array is **rounded up to the next multiple of the base alignment**.&#xD;&#xA;&#xD;&#xA;Emphasis added.&#xD;&#xA;&#xD;&#xA;So, if you have an array of `float`, the array stride shall be the same as the base alignment of a `vec4`. Also, each array will be padded at the end to the base alignment of a `vec4`. Yes, a `float[]` takes up the same room as a `vec4[]` of the same size.&#xD;&#xA;&#xD;&#xA;Welcome to the wonderful world of `std140` layout.&#xD;&#xA;&#xD;&#xA;If you want to have a real array of floats in a UBO... well, it's best to *avoid* wanting that. But if you have absolutely no other choice, then I suggest making it an array of `vec4`. Obviously, the size of this array will be the size you actually want, divided by 4 and rounded up:&#xD;&#xA;&#xD;&#xA;    const int samples = 31;&#xD;&#xA;    const int arraySize = ((samples + 3) / 4);&#xD;&#xA;&#xD;&#xA;To fetch a single float from this array, use math:&#xD;&#xA;&#xD;&#xA;    arrayOfVec4[index / 4][index % 4]&#xD;&#xA;&#xD;&#xA;Note that OpenGL ES 3.0 does allow non-constant array indexing of `vec` and `mat` types. It also allows the integer operations needed to pull this off.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10212" PostHistoryTypeId="5" PostId="4450" RevisionGUID="9e3dbc89-a90d-43d7-bc8d-bb0bc384ede2" CreationDate="2017-01-03T00:01:10.000" UserId="231" Comment="Minor typos" Text="Can I pass the data to the GPU through multiple cores with OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10213" PostHistoryTypeId="4" PostId="4450" RevisionGUID="9e3dbc89-a90d-43d7-bc8d-bb0bc384ede2" CreationDate="2017-01-03T00:01:10.000" UserId="231" Comment="Minor typos" Text="Why can't I utilize multiple CPU cores with OpenGL like Vulkan?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10214" PostHistoryTypeId="5" PostId="3923" RevisionGUID="91098915-c1b4-4b17-a62e-b878e4bcff50" CreationDate="2017-01-03T00:14:56.387" UserDisplayName="user246" Comment="corrected spelling" Text="Well realistically your choices are either IGES or STEP. IGES is slightly simpler but you will not successfully write either format without buying the standard (which in case of step is actually so many pages that by the time you have read them a year has passed, and lots of money is wasted on paper). You could also use one of the nonstandard kernel internal formats like Parasolid as its also commonly supported. Most other formats are polygon data so not suitable.&#xD;&#xA;&#xD;&#xA;I would explore an alternative option to writing your own exporter, buy a commercial or take a free CAD kernel and let the kernel (open CASCADE) do the exporting for you.&#xD;&#xA;&#xD;&#xA;On the other hand this is not hard to do inside your CAD application. Which you will need anyway to verify the result. Most CAD applications have a COM API's (don't know about NX most likely, but both creo and catia do have this) so you can edit, even do the generation from a text editor via python if you so wish. This is by far the least amount of effort (and it's usually less work to set up than using just the kernel).&#xD;&#xA;&#xD;&#xA;[![sweep][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Swept with spine angle $60 \cos(4 t)+110$ and polar trajectory with $r = \cos(4 t)+3$ in Creo. All input from program injection.&#xD;&#xA;&#xD;&#xA;So the approach depends on why you want to do what you do. And what your budget/time constraint is.&#xD;&#xA;&#xD;&#xA;**PS**: NURBS (the underlying format of CAD data) solutions are not necessarily analytic, but parametric fits to analytical solutions. Sometimes these are exact sometimes not so exact as not all functions can be fitted to rational spline (though many can). Even when they can fitting is a more general solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ufq1l.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10215" PostHistoryTypeId="24" PostId="3923" RevisionGUID="91098915-c1b4-4b17-a62e-b878e4bcff50" CreationDate="2017-01-03T00:14:56.387" Comment="Proposed by 246 approved by 231 edit id of 189" ContentLicense="CC BY-SA 3.0" />
  <row Id="10216" PostHistoryTypeId="5" PostId="3713" RevisionGUID="4dcef0e3-d802-4e27-8733-1a4eb7e453d0" CreationDate="2017-01-03T00:15:42.073" UserDisplayName="user246" Comment="corrected spelling" Text="I am trying to get [this shader][1] to run on a really old iDevice, as well as eventually Androids.&#xD;&#xA;&#xD;&#xA;Even when I reduce the code down to 2 sine functions per fragment the shader runs at about 20fps.&#xD;&#xA;&#xD;&#xA;I have considered taking a leaf out of the book of old shading techniques and creating an array that holds a bunch of predefined trig values and somehow using those to approximate the shader.&#xD;&#xA;&#xD;&#xA;In the shader I linked above I am already simulating that by rounding the values sent to the trig function the further left the mouse (while down) goes the less quality of the shader. It's actually pretty cool because really close to the left side it looks like a completely different and pretty cool shader.&#xD;&#xA;&#xD;&#xA;Anyway I have two dilemmas:&#xD;&#xA;&#xD;&#xA;1. I don't know what the most efficient way to have an array of like 360 values in it in a GLSL shader, constant or uniform?&#xD;&#xA;2. I can't figure out how to put a number in a range like usually if I wanted an angle between 0 and 360 (yes I know GPUs use radians) I would do it like so.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        func range(float angle)&#xD;&#xA;        {&#xD;&#xA;           float temp = angle&#xD;&#xA;           while (temp &gt; 360) {temp -= 360;}&#xD;&#xA;           while (temp &lt; 0)   {temp += 360;}&#xD;&#xA;           return temp;&#xD;&#xA;        }&#xD;&#xA;However GLSL does not allow while loops or recursive functions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/lsKSDt" ContentLicense="CC BY-SA 3.0" />
  <row Id="10217" PostHistoryTypeId="24" PostId="3713" RevisionGUID="4dcef0e3-d802-4e27-8733-1a4eb7e453d0" CreationDate="2017-01-03T00:15:42.073" Comment="Proposed by 246 approved by 231 edit id of 190" ContentLicense="CC BY-SA 3.0" />
  <row Id="10219" PostHistoryTypeId="2" PostId="4457" RevisionGUID="df76bf99-5293-4d73-9217-f778b300c845" CreationDate="2017-01-03T01:12:39.917" UserDisplayName="user2500" Text="A standard technique is to use a ray/sphere intersection test inside a pixel shader. One draws a billboard large enough cover the area the sphere could appear on the screen (or drawing a bounding cube) to reduce the number of wasted intersection tests (other geometric shapes could be used). The fragment is killed if the intersection test fails; if an intersection occurs, the appropriate depth value is calculated in the pixel shader and output for further visibility tests." ContentLicense="CC BY-SA 3.0" />
  <row Id="10220" PostHistoryTypeId="2" PostId="4458" RevisionGUID="aeac2350-43fa-4ef7-9797-1ce10eb5de3a" CreationDate="2017-01-03T01:38:46.377" UserId="5774" Text="How can I benchmark a fragment shader? &#xD;&#xA;What my shader does is basically lots of floating point operations, since it's doing some procedural stuff.&#xD;&#xA;So, is there any software/website where I can benchmark my shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10221" PostHistoryTypeId="1" PostId="4458" RevisionGUID="aeac2350-43fa-4ef7-9797-1ce10eb5de3a" CreationDate="2017-01-03T01:38:46.377" UserId="5774" Text="Benchmark GLSL fragment shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="10222" PostHistoryTypeId="3" PostId="4458" RevisionGUID="aeac2350-43fa-4ef7-9797-1ce10eb5de3a" CreationDate="2017-01-03T01:38:46.377" UserId="5774" Text="|opengl|shader|glsl|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10223" PostHistoryTypeId="2" PostId="4459" RevisionGUID="721c4e12-ac6f-4810-8ac8-5d57ac4e7cef" CreationDate="2017-01-03T08:04:00.200" UserId="5776" Text="I have an [image](https://i.stack.imgur.com/oJxCJ.png) that I'm trying to recreate programatically using Pyx in Python. It seems that there's an overlaid circle covering the color wheel. I'm trying to see if there's a way to, given the starting and composited RGB values for each of the 8 colors shown in the image, as well as the assumption that the overlaid shape has uniform RGB color and opacity, to find said shape's color and opacity.&#xD;&#xA;&#xD;&#xA;However, seeing that I'm not familiar with alpha blending formulae, I'm at a loss as to how to find this out. How could I go about this? I've done some research using the info [here](https://en.wikipedia.org/wiki/Alpha_compositing), but I can't seem to find a converging answer using the system of equations." ContentLicense="CC BY-SA 3.0" />
  <row Id="10224" PostHistoryTypeId="1" PostId="4459" RevisionGUID="721c4e12-ac6f-4810-8ac8-5d57ac4e7cef" CreationDate="2017-01-03T08:04:00.200" UserId="5776" Text="Given a composited image, is it possible to find the color and opacity of an overlaid shape?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10225" PostHistoryTypeId="3" PostId="4459" RevisionGUID="721c4e12-ac6f-4810-8ac8-5d57ac4e7cef" CreationDate="2017-01-03T08:04:00.200" UserId="5776" Text="|2d|blending|compositing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10226" PostHistoryTypeId="2" PostId="4460" RevisionGUID="fc12f833-85ed-4804-8ac6-1ffc41859b7a" CreationDate="2017-01-03T08:05:59.750" UserId="5777" Text="Is it possible to directly bypass the CPU while transferring data to the GPU? could there be hardware which gives the GPU direct memory access to a data stream for real-time GPU processing and rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10227" PostHistoryTypeId="1" PostId="4460" RevisionGUID="fc12f833-85ed-4804-8ac6-1ffc41859b7a" CreationDate="2017-01-03T08:05:59.750" UserId="5777" Text="Is it Possible to send data directly to the GPU via a custom hardware interface?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10228" PostHistoryTypeId="3" PostId="4460" RevisionGUID="fc12f833-85ed-4804-8ac6-1ffc41859b7a" CreationDate="2017-01-03T08:05:59.750" UserId="5777" Text="|gpu|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10231" PostHistoryTypeId="2" PostId="4461" RevisionGUID="18faa04e-4c9f-408a-a848-071a1a528cb7" CreationDate="2017-01-03T12:36:13.830" UserId="137" Text="On a desktop (or laptop) the GPU is connected to the PCIe bus. This gives it direct access to the physical RAM. &#xD;&#xA;&#xD;&#xA;If you map the buffer you want to fill and then read a file into that mapped memory. The OS will tell the disk drive to dump the file into the physical ram (the disk also has direct memory access), then when you go to use the mapped buffer the driver will tell the gpu to copy it into the vram. All the while the CPU never touched that bit of ram." ContentLicense="CC BY-SA 3.0" />
  <row Id="10232" PostHistoryTypeId="2" PostId="4462" RevisionGUID="676238e8-15d2-43ec-958e-b3aaf60698d7" CreationDate="2017-01-03T14:00:44.447" UserId="2687" Text="I have two high-resolution 3D objects with arbitrary smooth surface and I want to find the contact point/area between those two objects. Accuracy is more important than computation time in this case, though it would be great if the algorithm has relatively low computation time. Also, it would be great if the contact between two objects can be represented with surface/point penetration distance, e.g. if distance between two points/areas &lt; `x` distance, then there is collision, while `x` can be non-zero. Is there any collision algorithm that satisfy above requirement?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10233" PostHistoryTypeId="1" PostId="4462" RevisionGUID="676238e8-15d2-43ec-958e-b3aaf60698d7" CreationDate="2017-01-03T14:00:44.447" UserId="2687" Text="Given two arbitrary surfaces, what is the accurate and quite fast to find collision within X distance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10234" PostHistoryTypeId="3" PostId="4462" RevisionGUID="676238e8-15d2-43ec-958e-b3aaf60698d7" CreationDate="2017-01-03T14:00:44.447" UserId="2687" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10237" PostHistoryTypeId="2" PostId="4463" RevisionGUID="62cac8fd-4425-406b-8396-3241199ff751" CreationDate="2017-01-03T14:27:45.830" UserId="5780" Text="I'm a programmer working in Java and I'm not sure if this is the right place to ask this kind of question, here it goes:&#xD;&#xA;&#xD;&#xA;In my program, I need to show an image (.jpeg .png etc.) based on the screen size, this image is used to compare to real size (physical) of an actual label which is later printed on a specific machine.&#xD;&#xA;&#xD;&#xA;The issue is, for example on my machine I have the laptop screen and a '27 monitor they are both using the same resolution 1920x1080 but as you imagine if you resize any window/program/image it looks smaller on the laptop as the physical screen size is different although it has the same resolution (I imagine is because the physical size of the pixel is smaller than the ones on my monitor)&#xD;&#xA;&#xD;&#xA;Now what I would need to do is somehow always show the image on it's corect physical size (as it were printed), on any type of screen.&#xD;&#xA;&#xD;&#xA;Regarding to programming I could easily get the screens size and resize the image but, this is because the OS gives the size (it's set up size) back to the program, yet even if I have the correct size the physical screen could display the image smaller for example, as the screen's pixels are smaller.&#xD;&#xA;&#xD;&#xA;Any ideas where to start with this?&#xD;&#xA;How can I know the real physical screen size?&#xD;&#xA;This seems to be more a hardware issue than graphics.." ContentLicense="CC BY-SA 3.0" />
  <row Id="10238" PostHistoryTypeId="1" PostId="4463" RevisionGUID="62cac8fd-4425-406b-8396-3241199ff751" CreationDate="2017-01-03T14:27:45.830" UserId="5780" Text="Get screen size and then resize image accordingly" ContentLicense="CC BY-SA 3.0" />
  <row Id="10239" PostHistoryTypeId="3" PostId="4463" RevisionGUID="62cac8fd-4425-406b-8396-3241199ff751" CreationDate="2017-01-03T14:27:45.830" UserId="5780" Text="|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10240" PostHistoryTypeId="5" PostId="4462" RevisionGUID="646c7b23-1c4f-48af-a24c-fe55d70c9d76" CreationDate="2017-01-03T14:30:40.487" UserId="2687" Comment="added 108 characters in body" Text="I have two high-resolution 3D objects(femur and patella) with arbitrary smooth surface and I want to find the contact point/area between those two objects. Accuracy is more important than computation time in this case, though it would be great if the algorithm has relatively low computation time. Also, it would be great if the contact between two objects can be represented with surface/point penetration distance, e.g. if distance between two points/areas &lt; `x` distance, then there is collision, while `x` can be non-zero. Is there any collision algorithm that satisfy above requirement?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mbgwe.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10241" PostHistoryTypeId="2" PostId="4464" RevisionGUID="b3c5d114-3066-454f-af36-acb574720957" CreationDate="2017-01-03T14:40:39.543" UserId="4958" Text="I know I can use `QueryPerformanceCounter` for measure time for whole single frame. But can I when it comes to OpenGL draw or compute call?&#xD;&#xA;&#xD;&#xA;I always assumed that, as on the diagram, CPU waits for GPU to finish so timer would measure aproximate time or am I wrong?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As seen in code:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vertexArrayObject);&#xD;&#xA;    timer-&gt;startCounter();      &#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;    estimatedRenderTime = timer-&gt;getCounter();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;    timer-&gt;startCounter();&#xD;&#xA;    glDispatchCompute(width, height, 1);&#xD;&#xA;    estimatedRenderTime = timer-&gt;getCounter();&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2nb3d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10242" PostHistoryTypeId="1" PostId="4464" RevisionGUID="b3c5d114-3066-454f-af36-acb574720957" CreationDate="2017-01-03T14:40:39.543" UserId="4958" Text="Can I use QueryPerformanceCounter to measure single draw or compute call performance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10243" PostHistoryTypeId="3" PostId="4464" RevisionGUID="b3c5d114-3066-454f-af36-acb574720957" CreationDate="2017-01-03T14:40:39.543" UserId="4958" Text="|opengl|gpu|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10244" PostHistoryTypeId="5" PostId="4464" RevisionGUID="278cbef7-ce2a-4214-a448-cea1507c86e4" CreationDate="2017-01-03T14:50:59.330" UserId="4958" Comment="added 1 character in body" Text="I know I can use `QueryPerformanceCounter` for measure time for whole single frame. But can I when it comes to OpenGL draw or compute call?&#xD;&#xA;&#xD;&#xA;I always assumed that, as on the diagram, CPU waits for GPU to finish so timer would measure approximate time or am I wrong?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As seen in code:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vertexArrayObject);&#xD;&#xA;    timer-&gt;startCounter();      &#xD;&#xA;    glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;    estimatedRenderTime = timer-&gt;getCounter();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;    timer-&gt;startCounter();&#xD;&#xA;    glDispatchCompute(width, height, 1);&#xD;&#xA;    estimatedRenderTime = timer-&gt;getCounter();&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2nb3d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10246" PostHistoryTypeId="2" PostId="4465" RevisionGUID="66d77496-a445-476c-9289-1f63548aa852" CreationDate="2017-01-03T15:04:56.997" UserId="2654" Text="That diagram includes a CPU block titled &quot;wait for GPU&quot;. I do not see the part of your code that includes an equivalent command.&#xD;&#xA;&#xD;&#xA;Furthermore, even if it did include `glFinish`/`glClientWaitSync`/etc, there is no guarantee that the CPU time in any way relates to how much time the GPU spent processing it. `glFinish` might block on a mutex, thus ending the thread's timeslice. Which means that the thread will start up sometime after that mutex is released. How long after? Who knows, but your `QueryPerformanceCounter` call will include that time.&#xD;&#xA;&#xD;&#xA;If you want to measure GPU time, you should use tools that actually *measure GPU time*. For example, [timer queries][1]. You bracket some commands with `glBeginQuery(GL_TIME_ELAPSED, queryObject)` and `glEndQuery(GL_TIME_ELAPSED)`. Then you can [read the result after some time has elapsed][2]. Like maybe next frame.&#xD;&#xA;&#xD;&#xA;And unlike `glFinish`, this will not absolutely murder your performance ;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Query_Object#Timer_queries&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Query_Object#Query_retrieval" ContentLicense="CC BY-SA 3.0" />
  <row Id="10247" PostHistoryTypeId="2" PostId="4466" RevisionGUID="3d7f95ab-3a13-48c0-9c15-cf50a190d24c" CreationDate="2017-01-03T15:40:21.740" UserId="4748" Text="A key search phrase is &quot;collision detection.&quot; You may find some references at this MO posting, &quot;[Intersection of Polyhedra](http://mathoverflow.net/a/141730/6094).&quot;&#xD;&#xA;And here is a more recent reference:&#xD;&#xA;&#xD;&#xA;&gt; Jiménez, Juan J., and Rafael J. Segura. &quot;Collision detection between complex polyhedra.&quot; *Computers &amp; Graphics* 32.4 (2008): 402-411. ([Journal link](http://www.sciencedirect.com/science/article/pii/S0097849308000526).)&#xD;&#xA;&#xD;&#xA;Google Scholar shows this has been cited by 33 papers since." ContentLicense="CC BY-SA 3.0" />
  <row Id="10249" PostHistoryTypeId="50" PostId="4008" RevisionGUID="30f03179-f8b5-4ae1-94be-175214e7a90d" CreationDate="2017-01-03T16:43:20.083" UserId="-1" />
  <row Id="10250" PostHistoryTypeId="5" PostId="4458" RevisionGUID="338dc830-42ec-4d62-b097-a286abfcd807" CreationDate="2017-01-03T21:09:41.580" UserId="231" Comment="Remove request for off site resources (software/website) to avoid question being closed as off topic" Text="How can I benchmark a fragment shader? &#xD;&#xA;What my shader does is basically lots of floating point operations, since it's doing some procedural stuff." ContentLicense="CC BY-SA 3.0" />
  <row Id="10251" PostHistoryTypeId="2" PostId="4467" RevisionGUID="6041630f-638e-4760-8fb4-41d588f647a5" CreationDate="2017-01-03T23:09:53.143" UserId="1952" Text="You can solve the colors by solving a system of linear equations if you make few assumptions:&#xD;&#xA;&#xD;&#xA; 1. The alpha of the color wheel is constant (i.e. same for all colors in the wheel)&#xD;&#xA; 2. The beige background extends half way through the color wheel, and is constant for top and bottom halves of the image&#xD;&#xA; 3. The background in the center is constant for all colors&#xD;&#xA; 4. The alpha blending equation is the standard $f=c*\alpha+b*(1-\alpha)$, where $f$ = final color, $c$ = color on the wheel, $b$ = background color, $\alpha$ = alpha of the color wheel&#xD;&#xA;&#xD;&#xA;If you now pick two colors with the same beige background (e.g. green and yellow), and feed them into the above alpha blending equation you get 4 equations with 4 unknowns, which you can then solve. I.e.&#xD;&#xA;&#xD;&#xA;$$f_1=c_1*\alpha+b_1*(1-\alpha)$$&#xD;&#xA;$$f_2=c_1*\alpha+b_2*(1-\alpha)$$&#xD;&#xA;$$f_3=c_2*\alpha+b_1*(1-\alpha)$$&#xD;&#xA;$$f_3=c_2*\alpha+b_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;where $f_1$ &amp; $f_2$ = brighter &amp; darker green colors respectively, $f_3$ &amp; $f_4$ = brighter &amp; darker yellow colors respectively, $c_1$ &amp; $c_2$ = the unknown green &amp; yellow colors respectively you try to solve, $\alpha$ = alpha you try to solve, $b_1$ = beige background color, $b_2$ = unknown background color in the center.&#xD;&#xA;&#xD;&#xA;Then you can repeat this process for all the colors, or because you solved $\alpha$ you can use this information to solve the rest of the colors simply by:&#xD;&#xA;$$c=\frac{f-(b_1*(1-\alpha))}{\alpha}$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="10252" PostHistoryTypeId="2" PostId="4468" RevisionGUID="efe5bd65-2916-4a06-b73e-9644a193e5ab" CreationDate="2017-01-03T23:35:58.547" UserId="5715" Text="A lot goes in to benching performance. I think most would agree that measuring the frame time of your application is the best metric you can gather about how well you're doing at run-time. An easy way to &quot;bench&quot; your shaders in your engine/environment is to simply record frame times for a fixed duration with a fixed view and fixed scene. Then save those frame times out to a CSV and plot them in something like Excel. This should give you a good idea of how much your frame time is fluctuating and if you're actually hitting your frame time targets most of the time. &#xD;&#xA;&#xD;&#xA;However if you want to see if your shaders are properly utilizing the GPU you may want to dig into your application with something like [AMD's GPU Perf Studio][1] or [Nvidia's NSight][2] tool. I'm more familiar with Perf Studio but it can give you a static shader analysis to see if you're actually taking full advantage of the GPU or if you're overloading certain registers. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.amd.com/tools-and-sdks/graphics-development/gpu-perfstudio/&#xD;&#xA;  [2]: https://developer.nvidia.com/nvidia-nsight-visual-studio-edition" ContentLicense="CC BY-SA 3.0" />
  <row Id="10253" PostHistoryTypeId="4" PostId="4462" RevisionGUID="440324eb-278a-4f8f-b15d-96175f8c9a29" CreationDate="2017-01-04T01:09:01.103" UserId="2687" Comment="edited title" Text="Given two arbitrary surfaces, what is the accurate and quite fast algo to find collision within X distance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10255" PostHistoryTypeId="2" PostId="4469" RevisionGUID="3c32250f-2640-4f80-8ae1-d574f357e422" CreationDate="2017-01-04T06:55:00.287" UserId="2308" Text="Does any of their rendering techniques involve rendering an area at a higher resolution just to scale it down in order to mitigate artifacts? I know they use ray methods rather than rasterization however ray methods still have artifacts even when done with a ton of rays.. right?&#xD;&#xA;&#xD;&#xA;I noticed a few moments in the film Moana that seemed to be poorly rendered because small details seemed fuzzy and sorta pixelated. Especially around the edges of a figure that was in focus with a slightly blurred background. Could they have used supersampling on those scenes to decrease the issue?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10256" PostHistoryTypeId="1" PostId="4469" RevisionGUID="3c32250f-2640-4f80-8ae1-d574f357e422" CreationDate="2017-01-04T06:55:00.287" UserId="2308" Text="Do animation studios like Pixar, Dreamworks, and Disney use super-sampling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10257" PostHistoryTypeId="3" PostId="4469" RevisionGUID="3c32250f-2640-4f80-8ae1-d574f357e422" CreationDate="2017-01-04T06:55:00.287" UserId="2308" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10258" PostHistoryTypeId="2" PostId="4470" RevisionGUID="981c77ac-da66-4369-953c-4495fcbfc710" CreationDate="2017-01-04T09:17:56.527" UserId="182" Text="From my understanding, the specular color usually refers to the amount of light that is reflected when the surface is lit at normal incidence, and is noted $F_0$ or $R_0$. Moreover, for non metal materials, this value is calculated from the index of refraction of the material $n$ with the formula [deduced from the Fresnel equations][1] (in which 1 is the index of refraction of air or void):&#xD;&#xA;$$F_0 = \frac{(n - 1)^2}{(n + 1)^2} $$&#xD;&#xA;&#xD;&#xA;According to this [list of refractive indices on Wikipedia][2]:&#xD;&#xA;&#xD;&#xA; - Solid materials typically have $n$ between 1.46 ([fused quartz][3]) and 2.69 ([Moissanite][4]). That would mean an $F_0$ between 0.03 and 0.21.&#xD;&#xA; - Liquids typically have $n$ between 1.33 (water) and 1.63 ([carbon disulfide][5]). That would mean an $F_0$ between 0.02 and 0.057, if I am not mistaken.&#xD;&#xA; - Gases typically have $n \approx 1$, so I guess we can safely assume an $F_0$ of 0.&#xD;&#xA;&#xD;&#xA;All these values are very low; even crystals with high refractive indices like diamond ($F_0=0.17$) and moissanite ($F_0=0.21$) hardly exceed 20%. Yet most metals have $F_0$ values above 50%. Moreover, I have read multiple times that the formula mentioned above doesn't apply for metals (which can be easily confirmed by trying to use it and see completely wrong results), but I haven't found any further explanation.&#xD;&#xA;&#xD;&#xA;What phenomenon explains this difference? How can I calculate $F_0$ for a metal (in particular if the medium it is in contact with has an IoR different than 1, like water)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/List_of_refractive_indices#List&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Fused_quartz&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Moissanite&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Carbon_disulfide&#xD;&#xA;  [6]: https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10259" PostHistoryTypeId="1" PostId="4470" RevisionGUID="981c77ac-da66-4369-953c-4495fcbfc710" CreationDate="2017-01-04T09:17:56.527" UserId="182" Text="What explains the high specularity of metals?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10260" PostHistoryTypeId="3" PostId="4470" RevisionGUID="981c77ac-da66-4369-953c-4495fcbfc710" CreationDate="2017-01-04T09:17:56.527" UserId="182" Text="|physics|refraction|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10261" PostHistoryTypeId="2" PostId="4471" RevisionGUID="3cb8b4b8-78d9-4c31-adda-cb75fe645e8f" CreationDate="2017-01-04T09:43:03.930" UserId="2041" Text="Super-sampling for ray-tracing doesn't just mean rendering an area at higher resolution and then downscaling the finished image: in fact, this simplest super-sampling technique is really not effective enough for high-quality production rendering.&#xD;&#xA;&#xD;&#xA;In a production ray-tracer, super-sampling means sending more than one primary ray per pixel (16 primary rays per pixel is a good average) and then using signal reconstruction techniques (i.e. not just averaging) to compute a colour for each pixel of the image. Using lots of primary rays doesn't just help to avoid aliasing (jaggies) from when polygons partially cover pixels; it also helps to smooth over noise added in shading, such as when sampling global illumination or fuzzy reflections.&#xD;&#xA;&#xD;&#xA;If you can find a frame-grab of the particular details you noticed, it would be possible to go discuss those in more detail. It's entirely possible that some artefacts are caused by a particular technique, and aren't related to super-sampling at all." ContentLicense="CC BY-SA 3.0" />
  <row Id="10263" PostHistoryTypeId="2" PostId="4472" RevisionGUID="5d382db2-5990-44ee-b440-635f41676e89" CreationDate="2017-01-04T13:56:51.150" UserId="2041" Text="The refractive index is related to the speed at which light travels through the medium, and only applies to materials which are at least partially transparent. Metals are electrically conductive, so they are opaque, so light can't travel through them at any speed, so they don't have a refractive index. &#xD;&#xA;&#xD;&#xA;This is why Fresnel's law doesn't apply: it's for predicting what fraction of the incoming light is reflected *vs.* transmitted. No light is transmitted through the material: everything that isn't absorbed is reflected, either as a specular reflection (if the surface is smooth) or as diffuse scatter (if the surface is rough).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10264" PostHistoryTypeId="2" PostId="4473" RevisionGUID="0b5e3caf-f435-48e4-9f7e-bb939487ddf8" CreationDate="2017-01-04T14:12:05.507" UserId="38" Text="The OS does not know in many cases know the physical screen size! Often the only thing you can glean is the make and model, sometimes not even that. So if you have a database then the best you can do is ask your user." ContentLicense="CC BY-SA 3.0" />
  <row Id="10265" PostHistoryTypeId="2" PostId="4474" RevisionGUID="fb18164b-ac0b-463b-bd6a-0c7849746d41" CreationDate="2017-01-04T15:15:11.770" UserId="5519" Text="**Warning**: I am not a physicist.&#xD;&#xA;&#xD;&#xA;As Dan Hulme already explained, light can't travel through metals, so dealing with IOR is a lot more... *complex*. I will answer why that happens and how to calculate the reflection coefficient.&#xD;&#xA;&#xD;&#xA;**Explanation**: Metals are filled with free electrons. Those electrons react to external fields and reposition until electrostatic equilibrium is met (the electric field is zero inside a conductor in electrostatic equilibrium). When electromagnetic waves hit a metallic surface, the free electrons move until the field that they create cancels the field of the incoming wave. Those electrons grouped together radiate a wave going out nearly the same as the one that hit the surface (i.e. with very low attenuation). How much is attenuated depends on the material properties. &#xD;&#xA;&#xD;&#xA;From this explanation it is clear that conductivity is a key part of the high reflection coefficient on metals.&#xD;&#xA;&#xD;&#xA;Math-wise, what you are missing is the [complex index of refraction][2]. On good conductors, such as metals, the complex term of the IOR is relevant and key for explaining this phenomena.&#xD;&#xA;&#xD;&#xA;**Practically**, in rendering, achieving good metal parameters is more visual based. Artists adjust to their preference until it looks believable. Often you see a *metalness* parameter with specific handling for materials marked as metal.&#xD;&#xA;&#xD;&#xA;**Involved answer**:&#xD;&#xA;&#xD;&#xA;The complex index of refraction can be seen if we use Ohm's Law $J = \sigma \vec{E}$, which holds for conductors, on the [Ampère-Maxwell][3] equation using sinusoidal waves $\vec{E} = e^{i\omega t}$:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\vec{\nabla} \times \vec{H} = \sigma\vec{E} + \frac{\partial \vec{D}}{\partial t} = \sigma \vec{E} + i\omega \epsilon \vec{E}&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA; = i\omega \left( \epsilon - i \frac{\sigma}{\omega} \right)\vec{E} = i \omega \epsilon_m\vec{E} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Note how we can interpret that whole term as a complex permittitivity $\epsilon_m$ and that $\sigma$ is the conductivity of the material. &#xD;&#xA;&#xD;&#xA;This affects the IOR, as its definition is given by:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;  n' = \sqrt{\frac{\epsilon_m}{\epsilon_0}} = \sqrt{\frac{\left(\epsilon - i \sigma / \omega\right)}{\epsilon_0}} = n_{\text{real}} + in_{\text{img}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This shows how $n'$ can be complex. Also, note how very good conductors have a relevant complex term, as $\sigma \gg \epsilon_0 \omega$. Since it would take a lot, I will skip some steps with a [reference][1], page 27: it can be shown that, since $\sigma \gg \epsilon_0\omega$, (we are dealing with $\omega$ of the visible spectrum):&#xD;&#xA;$$&#xD;&#xA;  n_{\text{real}} \approx n_{\text{img}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and reflection from metals with normal incidence, from a medium with IOR $n$, given that $n' \gg n$:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;  R = \frac{(n_{\text{real}} - n)^2 + n_{\text{img}}^2}{(n_{\text{real}} + n)^2 + n_{\text{img}}^2} \approx 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Agreeing that a good conductor is, in general, a good reflector.&#xD;&#xA;&#xD;&#xA;The famous *Introduction to Electrodynamics* from Griffiths, pages 392-398, explains this and a lot more in a similar fashion.&#xD;&#xA;&#xD;&#xA;[1]: http://www.patarnott.com/atms749/pdf/FresnelEquations.pdf&#xD;&#xA;[2]: https://en.wikipedia.org/wiki/Refractive_index#Complex_refractive_index&#xD;&#xA;[3]: https://en.wikipedia.org/wiki/Maxwell's_equations#Formulation_in_SI_units_convention" ContentLicense="CC BY-SA 3.0" />
  <row Id="10266" PostHistoryTypeId="5" PostId="4473" RevisionGUID="814a3eba-f367-49f2-9012-1d413dcb1f38" CreationDate="2017-01-04T15:20:03.950" UserId="38" Comment="added 268 characters in body" Text="The OS does not know in many cases know the physical screen size! Often the only thing you can glean is the make and model, sometimes not even that. So if you have a database then the best you can do is ask your user.&#xD;&#xA;&#xD;&#xA;There are also some interesting corner cases. What do you do if the monitor is in fact a projector? What do you do in multimonitor setups? What if the image is halfway beween 2 monitors? What do you do if the operator is using pixel zoom for accessibility reasons? What do you do if the image is shown on 2monitors at the same time? What do you do if the monitor is huge, like one used in a conference room and your image turs out to be very small in comparasion (like 4 by 4 pixels)? ..." ContentLicense="CC BY-SA 3.0" />
  <row Id="10267" PostHistoryTypeId="2" PostId="4475" RevisionGUID="eeb1a797-2fb7-48fd-b973-a1e031f06948" CreationDate="2017-01-04T15:25:51.027" UserId="5717" Text="Look at the [refractive index](http://refractiveindex.info/) of several metals. They are all complex numbers and the math does work out when you put this into the fresnel equation: you get the expected high reflectivity at all angles.&#xD;&#xA;&#xD;&#xA;There are also subtle color shifts because the index depends on wavelength. This is actually used in rendering but it is not common. The function is sometimes named &quot;conductor fresnel&quot; but it's really the same fresnel equation with complex numbers." ContentLicense="CC BY-SA 3.0" />
  <row Id="10268" PostHistoryTypeId="5" PostId="4473" RevisionGUID="f3664ad6-9226-4bd6-bc21-52c9227f8f42" CreationDate="2017-01-04T15:30:14.250" UserId="38" Comment="added 15 characters in body" Text="The OS does not, in many or most cases, know the physical screen size! Often the only thing you can glean is the make and model, sometimes not even that. So if you do not want to have a database then the best you can do is ask your user.&#xD;&#xA;&#xD;&#xA;There are also some interesting corner cases. What do you do if the monitor is in fact a projector? What do you do in multimonitor setups? What if the image is halfway beween 2 monitors? What do you do if the operator is using pixel zoom for accessibility reasons? What do you do if the image is shown on 2 monitors at the same time? What do you do if the monitor is huge, like one used in a conference room and your image turns out to be very small in comparasion (like 4 by 4 pixels)? ..." ContentLicense="CC BY-SA 3.0" />
  <row Id="10270" PostHistoryTypeId="5" PostId="4473" RevisionGUID="7ba49055-bf45-46c5-933a-58dffbc4d43d" CreationDate="2017-01-04T16:32:36.503" UserId="38" Comment="added 1 character in body" Text="The OS does not, in many or most cases, know the physical screen size! Often the only thing you can glean is the make and model, sometimes not even that. So if you do not want to have a database then the best you can do is ask your user.&#xD;&#xA;&#xD;&#xA;There are also some interesting corner cases. What do you do if the monitor is in fact a projector? What do you do in multi monitor setups? What if the image is halfway between 2 monitors? What do you do if the operator is using pixel zoom for accessibility reasons? What do you do if the image is shown on 2 monitors at the same time? What do you do if the monitor is huge, like one used in a conference room and your image turns out to be very small in comparison (like 4 by 4 pixels)? ..." ContentLicense="CC BY-SA 3.0" />
  <row Id="10271" PostHistoryTypeId="2" PostId="4476" RevisionGUID="a405c79d-2186-49ea-83a8-ee47d7c8bab3" CreationDate="2017-01-04T17:44:25.723" UserId="56" Text="Raytracing is a great way to render spheres as Daniel mentioned.  Below is a screenshot of a raytraced scene I made but lost the source code to unfortunately.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you are looking to render smooth / non polygonal objects in general, it's not always easy, desired or even possible to do an analytical solve for ray vs object.&#xD;&#xA;&#xD;&#xA;For these cases, a useful technique is something called &quot;ray marching&quot; (also called sphere tracing).  In ray marching, you take steps down a ray and at each point ask if you are inside or outside of the object (alternately, above or below).  When the answer changes, you know that the intersection of the ray occurred between the current and last point you tested on the ray.&#xD;&#xA;&#xD;&#xA;Once you know the intersection occured between those two points, you can do various things to try and find the actual intersection, depending on quality needs vs computation costs.  Some common techniques:&#xD;&#xA;&#xD;&#xA; 1. Just accept either the current or last point tested as the intersection point (fastest)&#xD;&#xA; 2. Binary search the range to get a better answer&#xD;&#xA; 3. If you have a function which gives you an (estimated) signed distance from a point to the surface, instead of just an &quot;inside vs outside&quot; test, you can do a linear interpolation between the last point and the current point to find where the &quot;0&quot; is, and take that as your intersection point.  This is what I've had most success with personally.&#xD;&#xA;&#xD;&#xA;Also, if you have a &quot;signed (estimated) distance function&quot; instead of just inside vs outside function, you can find the surface normal by getting the partial derivatives of your distance function using a finite differences method (Finite differences info: http://blog.demofox.org/2015/08/02/finite-differences/), which will let you do shading.&#xD;&#xA;&#xD;&#xA;Below is a ray marched surface that is defined as a function $z=f(x,y)$, and is a screenshot of this webgl2 interactive demo: http://demofox.org/LeastSquaresSurfaceFit.html&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Alternately, here's a shadertoy which ray marches a cubic bezier rectangle - it's cubic on each axis, so is degree(3,3): https://www.shadertoy.com/view/4tfXz2&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Back to talking about rendering spheres, you can also just rasterize a sphere as a 2d circle (possibly distorted by a view / projection matrix type setup in &quot;2d&quot;), and then shade it as if it was a 3d object.  It can also work for non spheres, and you see this a lot with renderings of metaballs.&#xD;&#xA;&#xD;&#xA;Below is a screenshot of this shadertoy which renders metaballs: https://www.shadertoy.com/view/4sXXWM&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Lastly, I wanted to mention that all of these techniques are compatible with traditional renderers as well.  Like Daniel said, you can draw a screen space billboard that is larger than the shape (or draw a world space unit cube that contains it) and then you do your raytracing, raymarching, or rasterization / fake 3d lighting within the pixel shader, to mix these techniques with standard rasterization rendering methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ee8T2.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/bK8KL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/O7ORO.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/CJoC4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10275" PostHistoryTypeId="5" PostId="4476" RevisionGUID="30ea1049-cbba-4dfb-8cf9-6ed60d3761e7" CreationDate="2017-01-04T19:18:24.873" UserId="56" Comment="added 115 characters in body" Text="Raytracing is a great way to render spheres as Daniel mentioned.  Below is a screenshot of a raytraced scene I made but lost the source code to unfortunately.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you are looking to render smooth / non polygonal objects in general, it's not always easy, desired or even possible to do an analytical solve for ray vs object.&#xD;&#xA;&#xD;&#xA;For these cases, a useful technique is something called &quot;ray marching&quot; (also called sphere tracing).  In ray marching, you take steps down a ray and at each point ask if you are inside or outside of the object (alternately, above or below).  When the answer changes, you know that the intersection of the ray occurred between the current and last point you tested on the ray.&#xD;&#xA;&#xD;&#xA;Once you know the intersection occured between those two points, you can do various things to try and find the actual intersection, depending on quality needs vs computation costs.  Some common techniques:&#xD;&#xA;&#xD;&#xA; 1. Just accept either the current or last point tested as the intersection point (fastest)&#xD;&#xA; 2. Binary search the range to get a better answer&#xD;&#xA; 3. If you have a function which gives you an (estimated) signed distance from a point to the surface, instead of just an &quot;inside vs outside&quot; test, you can do a linear interpolation between the last point and the current point to find where the &quot;0&quot; is, and take that as your intersection point.  This is what I've had most success with personally.&#xD;&#xA;&#xD;&#xA;Note that you can get an estimated signed distance numerically using finite differences and using the gradient. Check this link for more info on that: http://www.iquilezles.org/www/articles/distance/distance.htm&#xD;&#xA;&#xD;&#xA;You can find more info about finite difference methods here:&#xD;&#xA;http://blog.demofox.org/2015/08/02/finite-differences/&#xD;&#xA;&#xD;&#xA;With a signed distance estimating function, you can also use the gradient to get the normal, which is required for shading.&#xD;&#xA;&#xD;&#xA;Below is a ray marched surface that is defined as a function $z=f(x,y)$, and is a screenshot of this webgl2 interactive demo: http://demofox.org/LeastSquaresSurfaceFit.html&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Alternately, here's a shadertoy which ray marches a cubic bezier rectangle - it's cubic on each axis, so is degree(3,3): https://www.shadertoy.com/view/4tfXz2&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Back to talking about rendering spheres, you can also just rasterize a sphere as a 2d circle (possibly distorted by a view / projection matrix type setup in &quot;2d&quot;), and then shade it as if it was a 3d object.  It can also work for non spheres, and you see this a lot with renderings of metaballs.&#xD;&#xA;&#xD;&#xA;Below is a screenshot of this shadertoy which renders metaballs: https://www.shadertoy.com/view/4sXXWM&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Lastly, I wanted to mention that all of these techniques are compatible with traditional renderers as well.  Like Daniel said, you can draw a screen space billboard that is larger than the shape (or draw a world space scaled and oriented unit cube that contains it) and then you do your raytracing, raymarching, or rasterization / fake 3d lighting within the pixel shader, to mix these techniques with standard rasterization rendering methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ee8T2.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/bK8KL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/O7ORO.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/CJoC4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10277" PostHistoryTypeId="2" PostId="4477" RevisionGUID="8bdf8c1a-e631-40be-bdf3-00a6e4925f57" CreationDate="2017-01-04T22:39:42.020" UserId="5787" Text="Is there currently anyone working on a link between these two fields? I have a hunch that, due to the repetitive nature of sampling, there could be a good bit to gain in the area of ray tracing using Machine Learning techniques, but I'm interested in finding out more and getting involved if there's a group out there doing this." ContentLicense="CC BY-SA 3.0" />
  <row Id="10278" PostHistoryTypeId="1" PostId="4477" RevisionGUID="8bdf8c1a-e631-40be-bdf3-00a6e4925f57" CreationDate="2017-01-04T22:39:42.020" UserId="5787" Text="Machine Learning and Computer Graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="10279" PostHistoryTypeId="3" PostId="4477" RevisionGUID="8bdf8c1a-e631-40be-bdf3-00a6e4925f57" CreationDate="2017-01-04T22:39:42.020" UserId="5787" Text="|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10280" PostHistoryTypeId="5" PostId="4467" RevisionGUID="b53b047a-c4e5-49f1-8bd6-69df13f24464" CreationDate="2017-01-04T23:11:45.333" UserId="1952" Comment="edited body" Text="You can solve the colors by solving a system of linear equations if you make few assumptions:&#xD;&#xA;&#xD;&#xA; 1. The alpha of the color wheel is constant (i.e. same for all colors in the wheel)&#xD;&#xA; 2. The beige background extends half way through the color wheel, and is constant for top and bottom halves of the image&#xD;&#xA; 3. The background in the center is constant for all colors&#xD;&#xA; 4. The alpha blending equation is the standard $f=c*\alpha+b*(1-\alpha)$, where $f$ = final color, $c$ = color on the wheel, $b$ = background color, $\alpha$ = alpha of the color wheel&#xD;&#xA;&#xD;&#xA;If you now pick two colors with the same beige background (e.g. green and yellow), and feed them into the above alpha blending equation you get 4 equations with 4 unknowns, which you can then solve. I.e.&#xD;&#xA;&#xD;&#xA;$$f_1=c_1*\alpha+b_1*(1-\alpha)$$&#xD;&#xA;$$f_2=c_1*\alpha+b_2*(1-\alpha)$$&#xD;&#xA;$$f_3=c_2*\alpha+b_1*(1-\alpha)$$&#xD;&#xA;$$f_4=c_2*\alpha+b_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;where $f_1$ &amp; $f_2$ = brighter &amp; darker green colors respectively, $f_3$ &amp; $f_4$ = brighter &amp; darker yellow colors respectively, $c_1$ &amp; $c_2$ = the unknown green &amp; yellow colors respectively you try to solve, $\alpha$ = alpha you try to solve, $b_1$ = beige background color, $b_2$ = unknown background color in the center.&#xD;&#xA;&#xD;&#xA;Then you can repeat this process for all the colors, or because you solved $\alpha$ you can use this information to solve the rest of the colors simply by:&#xD;&#xA;$$c=\frac{f-(b_1*(1-\alpha))}{\alpha}$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="10281" PostHistoryTypeId="5" PostId="4462" RevisionGUID="c5c35182-71cf-4f99-a220-55f33a48702f" CreationDate="2017-01-05T01:51:50.260" UserId="2687" Comment="deleted 3 characters in body" Text="I have two high-resolution 3D objects(femur and patella) with arbitrary smooth surface and I want to find the contact point/area between those two objects. Accuracy is more important than computation time in this case, though it would be great if the algorithm has relatively low computation time. Also, it would be great if the contact between two objects can be represented with surface/point penetration distance, e.g. if distance between two points/triangles/areas &lt;= `x` distance, then there is collision, while `x` can be non-zero. Is there any collision algorithm that satisfy above requirement?&#xD;&#xA;&#xD;&#xA;[![objects' shape][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mbgwe.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10286" PostHistoryTypeId="2" PostId="4478" RevisionGUID="7dff832d-faef-42fd-be56-7f1fa85ba5cd" CreationDate="2017-01-05T03:36:09.997" UserDisplayName="user2500" Text="A group from UC Santa Barbara published the Siggraph 2015 paper [A Machine Learning Approach for Filtering Monte Carlo Noise][1] describing a technique which trains a neural network to select filtering parameters for path tracing. The paper details the structure of the neural network and the filter parameters used and how several secondary features are pre-computed to feed the neural network.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://cvc.ucsb.edu/graphics/Papers/SIGGRAPH2015_LBF/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10287" PostHistoryTypeId="5" PostId="4478" RevisionGUID="056f713b-9bcf-424b-be08-c47129da7656" CreationDate="2017-01-05T03:41:43.930" UserDisplayName="user2500" Comment="deleted 3 characters in body" Text="A group from UC Santa Barbara published the Siggraph 2015 paper [A Machine Learning Approach for Filtering Monte Carlo Noise][1] describing a technique which trains a neural network to select filtering parameters for path tracing. The paper details the structure of the neural network, the filter parameters used and how several secondary features are pre-computed to feed the neural network.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://cvc.ucsb.edu/graphics/Papers/SIGGRAPH2015_LBF/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10289" PostHistoryTypeId="5" PostId="4471" RevisionGUID="c0116b16-c858-4ee5-b694-69ca248f43d2" CreationDate="2017-01-05T10:25:39.180" UserId="2041" Comment="incorporate information from comments" Text="Super-sampling for ray-tracing doesn't just mean rendering an area at higher resolution and then downscaling the finished image: in fact, this simplest super-sampling technique is really not effective enough for high-quality production rendering.&#xD;&#xA;&#xD;&#xA;In a production ray-tracer, super-sampling means sending more than one primary ray per pixel (16 primary rays per pixel is a good average) and then using signal reconstruction techniques (i.e. not just averaging) to compute a colour for each pixel of the image. Using lots of primary rays doesn't just help to avoid aliasing (jaggies) from when polygons partially cover pixels; it also helps to smooth over noise added in shading, such as when sampling global illumination or fuzzy reflections.&#xD;&#xA;&#xD;&#xA;In addition, super-sampling by sending more rays lets you jitter the sample positions to avoid the artefacts you get from regular sampling. It also lets you use the results of previously traced primary rays to decide where to put more samples.&#xD;&#xA;&#xD;&#xA;For example, the simplest *adaptive sampling* algorithm is contrast based: within each pixel, you measure the contrast among all of the primary rays. Pick the pixel(s) with the highest contrast, and shoot more primary rays in those pixels. You can also use the contrast between samples to choose where in the pixel to shoot new primary rays, but then you have to use a more complex reconstruction algorithm to avoid bias in your result.&#xD;&#xA;&#xD;&#xA;If you can find a frame-grab of the particular details you noticed, it would be possible to go discuss those in more detail. It's entirely possible that some artefacts are caused by a particular technique, and aren't related to super-sampling at all." ContentLicense="CC BY-SA 3.0" />
  <row Id="10290" PostHistoryTypeId="6" PostId="4469" RevisionGUID="cfa0ef82-2fcb-41a9-a1b3-468fcd9190a0" CreationDate="2017-01-05T10:38:53.840" UserId="2041" Comment="add relevant tags" Text="|rendering|raytracing|supersampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10292" PostHistoryTypeId="5" PostId="4185" RevisionGUID="20289418-a08f-4290-b38c-7a6db306aecd" CreationDate="2017-01-05T10:39:23.930" UserId="2041" Comment="add new tag" Text="I'm curious why spherical harmonics are commonly used in real time graphics instead of a spherical Fourier transform.&#xD;&#xA;&#xD;&#xA;I get that spherical harmonics are in a sort of frequency space (like FT is) so you can do convolution very efficiently.&#xD;&#xA;&#xD;&#xA;I also get that SH is an approximation of a function on a sphere, using up to an infinite series to perfectly reconstruct the original data, but often using only the first few items in the series.&#xD;&#xA;&#xD;&#xA;This sounds a lot like a spherical Fourier transform, but the math uses different functions entirely.&#xD;&#xA;&#xD;&#xA;What is the benefit of the SH representation over spherical FT?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10293" PostHistoryTypeId="6" PostId="4185" RevisionGUID="20289418-a08f-4290-b38c-7a6db306aecd" CreationDate="2017-01-05T10:39:23.930" UserId="2041" Comment="add new tag" Text="|lighting|fourier-transform|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10294" PostHistoryTypeId="6" PostId="4164" RevisionGUID="cc02b772-a2b6-426a-ba41-f3fb69c04828" CreationDate="2017-01-05T10:39:47.540" UserId="2041" Comment="add new tag" Text="|lighting|physically-based|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10295" PostHistoryTypeId="6" PostId="1445" RevisionGUID="b3bab67e-19a0-44cf-b9e6-1b964536836d" CreationDate="2017-01-05T10:40:21.753" UserId="2041" Comment="add new tag" Text="|lighting|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10297" PostHistoryTypeId="6" PostId="1703" RevisionGUID="201f8cb5-f2ff-4df8-8dd5-b6977dd6b552" CreationDate="2017-01-05T10:45:29.997" UserId="2041" Comment="add new tag" Text="|texture|algorithm|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10299" PostHistoryTypeId="2" PostId="4479" RevisionGUID="3bc0375b-ba9a-47c9-a618-71910241611f" CreationDate="2017-01-05T17:06:19.973" UserId="5802" Text="How do you use textures with direct state access in OpenGL?&#xD;&#xA;&#xD;&#xA;I have the following in my code, which seems to work:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glGenTextures(1, &amp;textureHandle);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureHandle);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;However, when I replace it with the following everything just becomes black:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;textureHandle);&#xD;&#xA;    glTextureImage2DEXT(textureHandle, GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTextureParameteri(textureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);" ContentLicense="CC BY-SA 3.0" />
  <row Id="10300" PostHistoryTypeId="1" PostId="4479" RevisionGUID="3bc0375b-ba9a-47c9-a618-71910241611f" CreationDate="2017-01-05T17:06:19.973" UserId="5802" Text="How to do texturing with OpenGL direct state access?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10301" PostHistoryTypeId="3" PostId="4479" RevisionGUID="3bc0375b-ba9a-47c9-a618-71910241611f" CreationDate="2017-01-05T17:06:19.973" UserId="5802" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10302" PostHistoryTypeId="2" PostId="4480" RevisionGUID="dd7031c4-8138-455d-b010-507c1bf6b677" CreationDate="2017-01-05T19:49:27.193" UserId="5750" Text="What black magic is behind [this][1]?&#xD;&#xA;&#xD;&#xA;[![rigged finger][2]][2]&#xD;&#xA;&#xD;&#xA;Starting from a pile of polygons, a skeleton, and an initial conformation, how is a new conformation turned into a new pile of polygons?&#xD;&#xA;&#xD;&#xA;  [1]: http://blender.stackexchange.com/a/46319/13953&#xD;&#xA;  [2]: https://i.stack.imgur.com/1frCY.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="10303" PostHistoryTypeId="1" PostId="4480" RevisionGUID="dd7031c4-8138-455d-b010-507c1bf6b677" CreationDate="2017-01-05T19:49:27.193" UserId="5750" Text="How does a rigged model work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10304" PostHistoryTypeId="3" PostId="4480" RevisionGUID="dd7031c4-8138-455d-b010-507c1bf6b677" CreationDate="2017-01-05T19:49:27.193" UserId="5750" Text="|3d|mathematics|animation|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10305" PostHistoryTypeId="2" PostId="4481" RevisionGUID="a58bb123-966a-4d45-993e-05fd861e42c9" CreationDate="2017-01-05T22:03:06.623" UserId="56" Text="The magic is that the mesh is attached to the skeleton.  In it's simplest form, this is done by assigning each vertex to a bone.&#xD;&#xA;&#xD;&#xA;When a vertex is assigned to a bone, that means that it will always keep the same position relative to that bone's position, and orientation (normal, tangent, bitangent aka the bone's local X,Y,Z axis) as the bone moves as directed by the animation data, physics impulses, or whatever else driving it.&#xD;&#xA;&#xD;&#xA;As you might expect, some triangles will have vertices that belong to different bones.  When this happens, since the triangle is made up of those vertices, the triangle will stretch or squish as the bones move.&#xD;&#xA;&#xD;&#xA;The link you mention explains a way to set up the vertices for this specific type of movement such that the vertices stretch and squish in realistic and well behaved ways.&#xD;&#xA;&#xD;&#xA;In modern games, vertices are usually attached to multiple bones with a weight per bone so that each vertex is actually affected by the movement of multiple bones.  This gives a more natural and organic look to the mesh.&#xD;&#xA;&#xD;&#xA;This answer only scratches the surface though, and this is a very deep topic which has many sub topics that are active areas of research!&#xD;&#xA;&#xD;&#xA;If you want to read more about skeletal animation, this link is a good starting point:&#xD;&#xA;http://blog.demofox.org/2012/09/21/anatomy-of-a-skeletal-animation-system-part-1/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10306" PostHistoryTypeId="2" PostId="4482" RevisionGUID="c30d0756-b9c4-45b4-a08b-471cd68d04d5" CreationDate="2017-01-05T22:42:40.700" UserId="48" Text="You still have to use either `glActiveTexture`+`glBindTexture` or `glBindMultiTextureEXT` to select which texture is to be bound to texture unit 0 for rendering. Otherwise, the GL driver doesn't know which texture you want to use, so it defaults to &quot;no texture&quot;.&#xD;&#xA;&#xD;&#xA;The direct state access &quot;way&quot; of binding a texture is like:&#xD;&#xA;&#xD;&#xA;    glBindMultiTextureEXT(0, GL_TEXTURE_2D, textureHandle);&#xD;&#xA;&#xD;&#xA;The first parameter indicates which texture unit to bind to." ContentLicense="CC BY-SA 3.0" />
  <row Id="10307" PostHistoryTypeId="5" PostId="4482" RevisionGUID="df941d6f-f761-4ddf-9e21-d515b349c2b0" CreationDate="2017-01-06T00:36:34.693" UserId="48" Comment="added notes about glBindTextures and ARB_DSA, h/t Nicol Bolas" Text="You still have to bind the desired texture to the texture unit to use it for rendering. In your current code, you're not specifying which texture to use for rendering, so the GL driver doesn't know which one you want to use and is defaulting to &quot;no texture&quot;.&#xD;&#xA;&#xD;&#xA;There are a few ways to bind a texture. You can keep using `glActiveTexture`+`glBindTexture` as in your non-DSA code; you can use [`glBindTextures`](http://docs.gl/gl4/glBindTextures) with a GL 4.4+ context, or you can use `glBindMultiTextureEXT` from EXT_direct_state_access.&#xD;&#xA;&#xD;&#xA;For example, with `glBindTextures`, do this:&#xD;&#xA;&#xD;&#xA;    glBindTextures(0, 1, &amp;textureHandle);&#xD;&#xA;&#xD;&#xA;By the way, in case you're not aware, there's a newer version of DSA under the extension name [ARB_direct_state_access](https://www.opengl.org/registry/specs/ARB/direct_state_access.txt). You might want to convert your code to use that if possible, as it's considered to be superior to the EXT version ([here's an article on the differences between them](https://www.khronos.org/opengl/wiki/Direct_State_Access#Changes_from_EXT)). However, the ARB version is currently not available on Intel GPUs (as of this writing), while the EXT version is." ContentLicense="CC BY-SA 3.0" />
  <row Id="10308" PostHistoryTypeId="5" PostId="4482" RevisionGUID="def0f315-2006-4858-9023-284f40c5f50b" CreationDate="2017-01-06T00:57:00.683" UserId="48" Comment="note ARB_DSA is core in 4.5" Text="You still have to bind the desired texture to the texture unit to use it for rendering. In your current code, you're not specifying which texture to use for rendering, so the GL driver doesn't know which one you want to use and is defaulting to &quot;no texture&quot;.&#xD;&#xA;&#xD;&#xA;There are a few ways to bind a texture. You can keep using `glActiveTexture`+`glBindTexture` as in your non-DSA code; you can use [`glBindTextures`](http://docs.gl/gl4/glBindTextures) with a GL 4.4+ context, or you can use `glBindMultiTextureEXT` from EXT_direct_state_access.&#xD;&#xA;&#xD;&#xA;For example, with `glBindTextures`, do this:&#xD;&#xA;&#xD;&#xA;    glBindTextures(0, 1, &amp;textureHandle);&#xD;&#xA;&#xD;&#xA;By the way, in case you're not aware, there's a newer version of DSA under the extension name [ARB_direct_state_access](https://www.opengl.org/registry/specs/ARB/direct_state_access.txt), which is also in core in GL 4.5. You might want to convert your code to use that if possible, as it's considered to be superior to the EXT version ([here's an article on the differences between them](https://www.khronos.org/opengl/wiki/Direct_State_Access#Changes_from_EXT)). However, the ARB version is currently not available on Intel GPUs (as of this writing), while the EXT version is." ContentLicense="CC BY-SA 3.0" />
  <row Id="10309" PostHistoryTypeId="5" PostId="4482" RevisionGUID="8b6a2e0d-aac2-4363-9cb2-9a037323a843" CreationDate="2017-01-06T03:12:18.397" UserId="48" Comment="revise to assume GL 4.5 is available" Text="You still have to bind the desired texture to the texture unit to use it for rendering. In your current code, you're not specifying which texture to use for rendering, so the GL driver doesn't know which one you want to use and is defaulting to &quot;no texture&quot;.&#xD;&#xA;&#xD;&#xA;There are a few ways to bind a texture. You can keep using `glActiveTexture`+`glBindTexture` as in your non-DSA code, or you can use either [`glBindTextures`](http://docs.gl/gl4/glBindTextures) or [`glBindTextureUnit`](http://docs.gl/gl4/glBindTextureUnit).&#xD;&#xA;&#xD;&#xA;For example, with `glBindTextureUnit`, do this:&#xD;&#xA;&#xD;&#xA;    glBindTextureUnit(0, textureHandle);&#xD;&#xA;&#xD;&#xA;The first parameter is the texture unit to bind to.&#xD;&#xA;&#xD;&#xA;By the way, instead of using `glTextureImage2DEXT` (which is from the old and deprecated EXT_direct_state_access extension), it's probably better to stick with core OpenGL calls. You can initialize the texture by using [`glTextureStorage2D`](http://docs.gl/gl4/glTexStorage2D) to allocate the memory and set the format, then [`glTextureSubImage2D`](http://docs.gl/gl4/glTexSubImage2D) to upload the data.&#xD;&#xA;&#xD;&#xA;([Here's an article with more on the differences](https://www.khronos.org/opengl/wiki/Direct_State_Access#Changes_from_EXT) between EXT_direct_state_access and the newer core version of the functionality, if you're interested.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10310" PostHistoryTypeId="2" PostId="4483" RevisionGUID="d5daf797-7f96-4f53-aea6-6167d3337269" CreationDate="2017-01-06T04:23:02.390" UserId="5764" Text="I apologize if my methods seem way off because this is my first time trying to build a path tracer and I'm struggling quite a bit. Currently, I am trying to mimic the &quot;mix shader&quot; node in Blender 3D that combines two different shaders. I would like to add this functionality to my path tracer because it would allow me to make a plastic-like material. Reading through a few explanations, it seems it takes a probabilistic approach to picking one or the other when a ray hits the surface.&#xD;&#xA;&#xD;&#xA;Here is a rendering of an object with a 50/50 mix of ideal reflection and ideal diffuse at 80 samples per pixel:&#xD;&#xA;[![enter image description here][1]][1]   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yAi7i.png&#xD;&#xA;&#xD;&#xA;Something is just off about it. Especially those weird underside highlights on the leg extending farthest to the left. I have a strong feeling I'm implementing it wrong.&#xD;&#xA;&#xD;&#xA;Here is a pseudo implementation of the path tracing part. It uses explicit light sampling. Based off of smallpt path tracer.&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you to anyone who can offer me some direction! Again, sorry if this is really convoluted. I've made it so far and I'm about to give up, but I feel like I'm reaaaally close. &#xD;&#xA;&#xD;&#xA;And one more thing. What happens if I want to make the mirror glossy? Would I just jitter the reflected ray a little? It has to be more complex than that seeing as there's different types of reflections like GGX or phong. Would a BRDF have to be thrown in there somewhere? That wouldn't be too bad if I was just doing brute force path tracing, but I can't even imagine how that would work the way I have it explicitly sampling the lights because that'd cause sooo much noise." ContentLicense="CC BY-SA 3.0" />
  <row Id="10311" PostHistoryTypeId="1" PostId="4483" RevisionGUID="d5daf797-7f96-4f53-aea6-6167d3337269" CreationDate="2017-01-06T04:23:02.390" UserId="5764" Text="Mix shader looks wrong on my path tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="10312" PostHistoryTypeId="3" PostId="4483" RevisionGUID="d5daf797-7f96-4f53-aea6-6167d3337269" CreationDate="2017-01-06T04:23:02.390" UserId="5764" Text="|rendering|raytracing|shader|3d|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10313" PostHistoryTypeId="5" PostId="4483" RevisionGUID="a3c36e3b-013e-464d-a15e-6f9d7a47b1eb" CreationDate="2017-01-06T06:31:11.787" UserId="5764" Comment="added 652 characters in body" Text="I apologize if my methods seem way off because this is my first time trying to build a path tracer and I'm struggling quite a bit. Currently, I am trying to mimic the &quot;mix shader&quot; node in Blender 3D that combines two different shaders. I would like to add this functionality to my path tracer because it would allow me to make a plastic-like material. Reading through a few explanations, it seems it takes a probabilistic approach to picking one or the other when a ray hits the surface.&#xD;&#xA;&#xD;&#xA;Here is a rendering of an object with a 50/50 mix of ideal reflection and ideal diffuse at 80 samples per pixel:&#xD;&#xA;[![enter image description here][1]][1]   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Something is just off about it. Especially those weird underside highlights on the leg extending farthest to the left. I have a strong feeling I'm implementing it wrong.&#xD;&#xA;&#xD;&#xA;Here is a pseudo implementation of the path tracing part. It uses explicit light sampling. Based off of smallpt path tracer.&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you to anyone who can offer me some direction! Again, sorry if this is really convoluted. I've made it so far and I'm about to give up, but I feel like I'm reaaaally close. &#xD;&#xA;&#xD;&#xA;And one more thing. What happens if I want to make the mirror glossy? Would I just jitter the reflected ray a little? It has to be more complex than that seeing as there's different types of reflections like GGX or phong. Would a BRDF have to be thrown in there somewhere? That wouldn't be too bad if I was just doing brute force path tracing, but I can't even imagine how that would work the way I have it explicitly sampling the lights because that'd cause sooo much noise.&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;&#xD;&#xA;As suggested, I have modeled it in Blender to reference. I should've done that in the first place! I am happy to see it is nearly identical. I guess my question now is, is the method I am using above correct? If so, how do I go about making it more glossy as asked above? (see reference below)&#xD;&#xA;&#xD;&#xA;Mine:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Blender's:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The glossy (roughness) effect from Blender I wish to achieve:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yAi7i.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TKaWp.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/1JFuh.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ubOLx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10314" PostHistoryTypeId="2" PostId="4484" RevisionGUID="a280209e-5cbb-4863-856d-2150abc5801f" CreationDate="2017-01-06T13:33:35.830" UserId="5399" Text="Basically my problem deals with texture access in OpenGL's Fragment Shader. First I'll describe the background of the problem and what I want to accomplish. Afterwards I'll explain the point at which my problem arises. And finally I'll present a few lines of code followed by my actual question. If you're not interested in the details you can skip directly to the problem. But maybe the detailed explanation is useful for others.&#xD;&#xA;&#xD;&#xA;#The Background#&#xD;&#xA;&#xD;&#xA;Basically I want to compute the partial derivatives of a rendered depth image according to equation (15) in this paper [*Wei, Xiaolin, Peizhao Zhang, and Jinxiang Chai. &quot;Accurate realtime full-body motion capture using a single depth camera.&quot; ACM Transactions on Graphics (TOG) 31.6 (2012): 188.*][1]&#xD;&#xA;&#xD;&#xA;**Derivatives**&#xD;&#xA;&#xD;&#xA;In this paper there are two important derivatives which has to be computed: &#xD;&#xA;&#xD;&#xA;**1. The Parameter Gradient**&#xD;&#xA;&#xD;&#xA;The change of depth value $D$ with respect to a parameter $q_k$ which moves the skeleton:&#xD;&#xA;$$ \frac{\partial D_c}{\partial \vec{q}} = \left[\frac{\partial D_c}{\partial q_1},\; ...,\; \frac{\partial D_c}{\partial q_k},\;...\right] $$&#xD;&#xA;But since I'm using multiple cameras, I've different depth images of the same model. In the example here two cameras are used ($c=1,2$) and therefore we have $D_1$ and $D_2$.&#xD;&#xA;This gradients can be seen in the image below. I'll refer to this image as *Gradient-Texture* $G$. Here we see multiple instances of the same model. The first instance (0) in the upper left corner is in contrast to the other instances not a derivative but the raw depth value $D_1$. The second instance is the depth change with respect to a rotation of the whole model around the x-axis (which is  parameter $q_1$)($q_7$ is the angle of the upper leg). After all $\frac{\partial D_1}{\partial q_k}$ are computed we proceed with $c=2$ and see $D_2$ and so on.&#xD;&#xA;&#xD;&#xA;[![Absolute value of the depth gradient][2]][2]&#xD;&#xA;*Figure 1: The raw depth images and depth gradients with respect to parameters. (referred to as Gradient-Texture $G$ )*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2. The Image Gradient**&#xD;&#xA;&#xD;&#xA;The image gradient is well known and has to be computed by applying the convolution operator $\left[-1/2, 0, +1/2 \right]$ to $D_1$ and $D_2$. By doing this in x and y direction we get:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c = \left[ \frac{\partial D_c}{\partial x}, \frac{\partial D_c}{\partial y} \right]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Summation**&#xD;&#xA;&#xD;&#xA;In the end I have to sum up the two derivatives:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c \frac{\partial \vec{x}}{\partial \vec{q}} + \frac{\partial D_c}{\partial \vec{q}} \;. \;\; (1)$$&#xD;&#xA;&#xD;&#xA;Where $\frac{\partial \vec{x}}{\partial \vec{q}}$ is the change of the image coordinates of a projected point on the model with respect to a parameter. This becomes a constant for a orthographic projection as it is applied here.&#xD;&#xA;&#xD;&#xA;#The Problem#&#xD;&#xA;&#xD;&#xA;To compute the sum in equation (1) i need to add the gradient to each $\frac{\partial D_c}{\partial q_k}$. Therefore I need to access $D_c$ in each instance, compute the derivative and add it to the instance $\frac{\partial D_c}{\partial q_k}$. &#xD;&#xA;&#xD;&#xA;This is done in a Fragment Shader which has as input the figure 1 (as GL_TEXTURE_RECTANGLE). Since each instance $i$ does not know where to find the raw depth image ($D_c$) in the texture, an additional input with the x- and y-offset from the current pixel/texel position to the according pixel/texel position of the raw depth image is provided: Let's call it $O_x$ and $O_y$. So to get the coordinates of the raw depth image $D_c$ in the Gradient-Texture $G$, we do:&#xD;&#xA;$$&#xD;&#xA;x_D  =  x + O_x(x,y)\;\, \;\;\;\;\;\;\;\;  \\&#xD;&#xA;y_D  =  y + O_y(x,y)\;, \;\;\; (2)$$&#xD;&#xA;where $x$, $y$ are the current pixel coordinates (gl_fragCoord) in the Fragment Shader and $x_D$ is the x-coordinate of the raw depth image $D_c$ assigned to the Gradient-Texture at $(x,y)$.&#xD;&#xA;&#xD;&#xA;The Offset-Texture $O_x$ is shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Offset-Texture][3]][3]&#xD;&#xA;*Figure 2: The Offset-Texture which transforms the coordinates from a point of each instance in the Gradient-Texture to the coordinates of the raw depth image in the Gradient-Texture.*&#xD;&#xA;&#xD;&#xA;When I do the computation stated in equation (2) I obtain the Base-Coordinates $x_D$, as I called them. They are shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Position Offset][5]][5]&#xD;&#xA;*Figure 3: The Base-Position $x_D$ of the raw depth image for each instance.*&#xD;&#xA;&#xD;&#xA;And now when I access the values of the Gradient-Texture with the computed Base-Coordinates&#xD;&#xA;&#xD;&#xA;$$D_c = G(x_D,y_D)$$&#xD;&#xA;&#xD;&#xA;I get a fault. The result is shown in Figure 4 below. I would expect each instance to show it's assigned raw depth $D_c$. But as you see there are black artefacts. Afterwards I would have to compute the gradient image $\nabla D_c$ but I stopped here since there is obviously a fault.&#xD;&#xA;&#xD;&#xA;[![Raw Depth accessed using Base-Coordinates][6]][6]&#xD;&#xA;*Figure 4: Raw depth $D_c$ extracted from the Gradient-Texture $G$ using the computed Base-Coordinates*&#xD;&#xA;&#xD;&#xA;#The Code#&#xD;&#xA;&#xD;&#xA;To provide useful feedback I assume you'll need the Code. In the following you'll find the Fragment Shader code. &#xD;&#xA;&#xD;&#xA;The variable&#xD;&#xA;    GradientsTexture&#xD;&#xA;contains $G$ and&#xD;&#xA;&#xD;&#xA;    GradientsOffset&#xD;&#xA;contains $O_x$ and $O_y$.&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    // locations of the output data&#xD;&#xA;    layout(location = 5) out float	depth2;&#xD;&#xA;&#xD;&#xA;    in		vec4	gl_FragCoord;&#xD;&#xA;&#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    uniform sampler2DRect GradientsOffset;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;	    ivec2 pos		= ivec2(gl_FragCoord.x-0.5,  gl_FragCoord.y-0.5);&#xD;&#xA;	    ivec2 offset	= ivec2(texelFetch(GradientsOffset, pos).xy);&#xD;&#xA;	    ivec2 basePos	= pos+offset;&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;	    depth2 = gradient.x;&#xD;&#xA;	&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;#The Question#&#xD;&#xA;&#xD;&#xA;And finally my question: Does anyone knows where these artefacts come from? As you saw in the figures above, the steps before give corret results. Only the access to the Gradient-Texture with &#xD;&#xA;&#xD;&#xA;    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;causes unexpected results as shown in figure 4.&#xD;&#xA;&#xD;&#xA;Thanks in advance and sorry for the long explanation.&#xD;&#xA;&#xD;&#xA;Cheers,&#xD;&#xA;Christian Bloch.&#xD;&#xA; &#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.297.3923&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/UJEzd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/zFcmq.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/dLMrk.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/zSJEu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10315" PostHistoryTypeId="1" PostId="4484" RevisionGUID="a280209e-5cbb-4863-856d-2150abc5801f" CreationDate="2017-01-06T13:33:35.830" UserId="5399" Text="OpenGL texelFetch causes black stripes" ContentLicense="CC BY-SA 3.0" />
  <row Id="10316" PostHistoryTypeId="3" PostId="4484" RevisionGUID="a280209e-5cbb-4863-856d-2150abc5801f" CreationDate="2017-01-06T13:33:35.830" UserId="5399" Text="|opengl|texture|fragment-shader|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10317" PostHistoryTypeId="5" PostId="4484" RevisionGUID="6aa5651a-7e2c-4084-9840-16afa0a53ccb" CreationDate="2017-01-06T13:48:24.973" UserId="5399" Comment="added 28 characters in body" Text="Basically my problem deals with texture access in OpenGL's Fragment Shader. First I'll describe the background of the problem and what I want to accomplish. Afterwards I'll explain the point at which my problem arises. And finally I'll present a few lines of code followed by my actual question. If you're not interested in the details you can skip directly to the problem. But maybe the detailed explanation is useful for others.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Background#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Basically I want to compute the partial derivatives of a rendered depth image according to equation (15) in this paper [*Wei, Xiaolin, Peizhao Zhang, and Jinxiang Chai. &quot;Accurate realtime full-body motion capture using a single depth camera.&quot; ACM Transactions on Graphics (TOG) 31.6 (2012): 188.*][1]&#xD;&#xA;&#xD;&#xA;**Derivatives**&#xD;&#xA;&#xD;&#xA;In this paper there are two important derivatives which has to be computed: &#xD;&#xA;&#xD;&#xA;**1. The Parameter Gradient**&#xD;&#xA;&#xD;&#xA;The change of depth value $D$ with respect to a parameter $q_k$ which moves the skeleton:&#xD;&#xA;$$ \frac{\partial D_c}{\partial \vec{q}} = \left[\frac{\partial D_c}{\partial q_1},\; ...,\; \frac{\partial D_c}{\partial q_k},\;...\right] $$&#xD;&#xA;But since I'm using multiple cameras, I've different depth images of the same model. In the example here two cameras are used ($c=1,2$) and therefore we have $D_1$ and $D_2$.&#xD;&#xA;This gradients can be seen in the image below. I'll refer to this image as *Gradient-Texture* $G$. Here we see multiple instances of the same model. The first instance (0) in the upper left corner is in contrast to the other instances not a derivative but the raw depth value $D_1$. The second instance is the depth change with respect to a rotation of the whole model around the x-axis (which is  parameter $q_1$)($q_7$ is the angle of the upper leg). After all $\frac{\partial D_1}{\partial q_k}$ are computed we proceed with $c=2$ and see $D_2$ and so on.&#xD;&#xA;&#xD;&#xA;[![Absolute value of the depth gradient][2]][2]&#xD;&#xA;*Figure 1: The raw depth images and depth gradients with respect to parameters. (referred to as Gradient-Texture $G$ )*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2. The Image Gradient**&#xD;&#xA;&#xD;&#xA;The image gradient is well known and has to be computed by applying the convolution operator $\left[-1/2, 0, +1/2 \right]$ to $D_1$ and $D_2$. By doing this in x and y direction we get:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c = \left[ \frac{\partial D_c}{\partial x}, \frac{\partial D_c}{\partial y} \right]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Summation**&#xD;&#xA;&#xD;&#xA;In the end I have to sum up the two derivatives:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c \frac{\partial \vec{x}}{\partial \vec{q}} + \frac{\partial D_c}{\partial \vec{q}} \;. \;\; (1)$$&#xD;&#xA;&#xD;&#xA;Where $\frac{\partial \vec{x}}{\partial \vec{q}}$ is the change of the image coordinates of a projected point on the model with respect to a parameter. This becomes a constant for a orthographic projection as it is applied here.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Problem#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the sum in equation (1) i need to add the gradient to each $\frac{\partial D_c}{\partial q_k}$. Therefore I need to access $D_c$ in each instance, compute the derivative and add it to the instance $\frac{\partial D_c}{\partial q_k}$. &#xD;&#xA;&#xD;&#xA;This is done in a Fragment Shader which has as input the figure 1 (as GL_TEXTURE_RECTANGLE). Since each instance $i$ does not know where to find the raw depth image ($D_c$) in the texture, an additional input with the x- and y-offset from the current pixel/texel position to the according pixel/texel position of the raw depth image is provided: Let's call it $O_x$ and $O_y$. So to get the coordinates of the raw depth image $D_c$ in the Gradient-Texture $G$, we do:&#xD;&#xA;$$&#xD;&#xA;x_D  =  x + O_x(x,y)\;\, \;\;\;\;\;\;\;\;  \\&#xD;&#xA;y_D  =  y + O_y(x,y)\;, \;\;\; (2)$$&#xD;&#xA;where $x$, $y$ are the current pixel coordinates (gl_fragCoord) in the Fragment Shader and $x_D$ is the x-coordinate of the raw depth image $D_c$ assigned to the Gradient-Texture at $(x,y)$.&#xD;&#xA;&#xD;&#xA;The Offset-Texture $O_x$ is shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Offset-Texture][3]][3]&#xD;&#xA;*Figure 2: The Offset-Texture which transforms the coordinates from a point of each instance in the Gradient-Texture to the coordinates of the raw depth image in the Gradient-Texture.*&#xD;&#xA;&#xD;&#xA;When I do the computation stated in equation (2) I obtain the Base-Coordinates $x_D$, as I called them. They are shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Position Offset][5]][5]&#xD;&#xA;*Figure 3: The Base-Position $x_D$ of the raw depth image for each instance.*&#xD;&#xA;&#xD;&#xA;And now when I access the values of the Gradient-Texture with the computed Base-Coordinates&#xD;&#xA;&#xD;&#xA;$$D_c = G(x_D,y_D)$$&#xD;&#xA;&#xD;&#xA;I get a fault. The result is shown in Figure 4 below. I would expect each instance to show it's assigned raw depth $D_c$. But as you see there are black artefacts. Afterwards I would have to compute the gradient image $\nabla D_c$ but I stopped here since there is obviously a fault.&#xD;&#xA;&#xD;&#xA;[![Raw Depth accessed using Base-Coordinates][6]][6]&#xD;&#xA;*Figure 4: Raw depth $D_c$ extracted from the Gradient-Texture $G$ using the computed Base-Coordinates*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Code#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To provide useful feedback I assume you'll need the Code. In the following you'll find the Fragment Shader code. &#xD;&#xA;&#xD;&#xA;The variable&#xD;&#xA;    GradientsTexture&#xD;&#xA;contains $G$ and&#xD;&#xA;&#xD;&#xA;    GradientsOffset&#xD;&#xA;contains $O_x$ and $O_y$.&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    // locations of the output data&#xD;&#xA;    layout(location = 5) out float	depth2;&#xD;&#xA;&#xD;&#xA;    in		vec4	gl_FragCoord;&#xD;&#xA;&#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    uniform sampler2DRect GradientsOffset;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;	    ivec2 pos		= ivec2(gl_FragCoord.x-0.5,  gl_FragCoord.y-0.5);&#xD;&#xA;	    ivec2 offset	= ivec2(texelFetch(GradientsOffset, pos).xy);&#xD;&#xA;	    ivec2 basePos	= pos+offset;&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;	    depth2 = gradient.x;&#xD;&#xA;	&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Question#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally my question: Does anyone knows where these artefacts come from? As you saw in the figures above, the steps before give corret results. Only the access to the Gradient-Texture with &#xD;&#xA;&#xD;&#xA;    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;causes unexpected results as shown in figure 4.&#xD;&#xA;&#xD;&#xA;Thanks in advance and sorry for the long explanation.&#xD;&#xA;&#xD;&#xA;Cheers,&#xD;&#xA;Christian Bloch.&#xD;&#xA; &#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.297.3923&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/UJEzd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/zFcmq.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/dLMrk.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/zSJEu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10318" PostHistoryTypeId="5" PostId="4483" RevisionGUID="f47571ae-530f-460d-82c9-f9f2f580e6d1" CreationDate="2017-01-06T16:08:01.160" UserId="5764" Comment="deleted 644 characters in body" Text="I apologize if my methods seem way off because this is my first time trying to build a path tracer and I'm struggling quite a bit. Currently, I am trying to mimic the &quot;mix shader&quot; node in Blender 3D that combines two different shaders. I would like to add this functionality to my path tracer because it would allow me to make a plastic-like material. Reading through a few explanations, it seems it takes a probabilistic approach to picking one or the other when a ray hits the surface.&#xD;&#xA;&#xD;&#xA;Here is a rendering of an object with a 50/50 mix of ideal reflection and ideal diffuse at 80 samples per pixel:&#xD;&#xA;[![enter image description here][1]][1]   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Something is just off about it. Especially those weird underside highlights on the leg extending farthest to the left. I have a strong feeling I'm implementing it wrong.&#xD;&#xA;&#xD;&#xA;Here is a pseudo implementation of the path tracing part. It uses explicit light sampling. Based off of smallpt path tracer.&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you to anyone who can offer me some direction! Again, sorry if this is really convoluted. I've made it so far and I'm about to give up, but I feel like I'm reaaaally close. &#xD;&#xA;&#xD;&#xA;And one more thing. What happens if I want to make the mirror glossy? Would I just jitter the reflected ray a little? It has to be more complex than that seeing as there's different types of reflections like GGX or phong. Would a BRDF have to be thrown in there somewhere? That wouldn't be too bad if I was just doing brute force path tracing, but I can't even imagine how that would work the way I have it explicitly sampling the lights because that'd cause sooo much noise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yAi7i.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10319" PostHistoryTypeId="2" PostId="4485" RevisionGUID="5c781060-c24e-4f8c-8f3a-affaa66acde3" CreationDate="2017-01-06T16:10:43.373" UserId="5764" Text="As suggested in the comments, I created an exact scene in Blender using the same .obj. After adding a mix shader node and setting one side to diffuse and the other to a perfect mirror, you can see that the results are almost identical. This would indicate that my implementation is correct.&#xD;&#xA;&#xD;&#xA;Here is a side by side comparison. Mine is on the left, Blender's is on the right:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qWziH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10320" PostHistoryTypeId="2" PostId="4486" RevisionGUID="c0098767-1fc8-4f40-9859-5f5a3d16dade" CreationDate="2017-01-06T16:37:47.590" UserId="5764" Text="Recently I asked a question regarding how to mix a glossy and diffuse shader in my path tracer: [Mix shader looks wrong on my path tracer][1]. &#xD;&#xA;I thought it was incorrect, but a comparison between mine and Blender's seems correct. However, now I am lost in how I would approach making the surface of a mirror look rough as this example shows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have done some research, and discovered that there are different types of reflectance models such as Beckmann and GGX. I've found some explanations of how to find the BRDF such as this site: [Specular BRDF][3], but I can't find any explanation on how to do the reflection ray with explicit lighting. As shown in the pseudo code of my path tracer (below), for every object I shoot a ray towards a light and use the surface transport rendering equation to incorporate the BRDF. I am assuming this is where the GGX/Beckmann BRDF would be plugged in. (I'm guessing it's not quite that simple though and some probability must be involved). What really gets me though is that reflection ray. For diffuse it's easy because I just send off a random ray anywhere in the hemisphere of the surface normal. However, for specular, there's a more sharp bump in the BRDF. How would I translate that into a reflected ray? If I just jittered the ideal reflection ray a little, that wouldn't relate to how the microfacets are modeled in the GGX/Beckmann reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Explicit lighting equation from Peter Shirley's Realistic Ray Tracing:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Where p(x) is the density function of the light triangle 1/Area&#xD;&#xA;&#xD;&#xA;x' is a random point on the light triangle&#xD;&#xA;&#xD;&#xA;x  is the hit point on the object&#xD;&#xA;&#xD;&#xA;The cosines are the angles between the light's normal and the light ray, and the object's normal and the light ray&#xD;&#xA;&#xD;&#xA;Rho is the BRDF (1/PI for ideal diffuse)&#xD;&#xA;&#xD;&#xA;And v is either 1 or 0 depending on if it's in shadow&#xD;&#xA;&#xD;&#xA;Pseudo code:&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/4483/mix-shader-looks-wrong-on-my-path-tracer&#xD;&#xA;  [2]: https://i.stack.imgur.com/lBTPz.jpg&#xD;&#xA;  [3]: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/HnQ3j.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10321" PostHistoryTypeId="1" PostId="4486" RevisionGUID="c0098767-1fc8-4f40-9859-5f5a3d16dade" CreationDate="2017-01-06T16:37:47.590" UserId="5764" Text="Mimicking Blender's &quot;roughness&quot; in my path tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="10322" PostHistoryTypeId="3" PostId="4486" RevisionGUID="c0098767-1fc8-4f40-9859-5f5a3d16dade" CreationDate="2017-01-06T16:37:47.590" UserId="5764" Text="|raytracing|pathtracing|material|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10324" PostHistoryTypeId="2" PostId="4487" RevisionGUID="9935276d-48b7-4035-be03-ef68d4f68d70" CreationDate="2017-01-06T21:48:05.473" UserId="5807" Text="I would like to compute volumetric obscurance with line integrals like described in this paper : &#xD;&#xA;http://advances.realtimerendering.com/s2010/Ownby,Hall%20and%20Hall%20-%20Toystory3%20(SIGGRAPH%202010%20Advanced%20RealTime%20Rendering%20Course).pdf&#xD;&#xA;&#xD;&#xA;For a 2D sample, it is possible to know the &quot;depth in sphere&quot;. But I don't understand how they compute the occluded (in red on the following image) part and the unnoccluded (in yellow) part of the line in the sphere. &#xD;&#xA;&#xD;&#xA;I think that they say that given the depth read through the sample and the &quot;depth in sphere&quot;, we should be able to deduce each part of the lines.&#xD;&#xA;&#xD;&#xA;[![line sampling][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eOLwt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10325" PostHistoryTypeId="1" PostId="4487" RevisionGUID="9935276d-48b7-4035-be03-ef68d4f68d70" CreationDate="2017-01-06T21:48:05.473" UserId="5807" Text="Volumetric Obscurance : line integrals" ContentLicense="CC BY-SA 3.0" />
  <row Id="10326" PostHistoryTypeId="3" PostId="4487" RevisionGUID="9935276d-48b7-4035-be03-ef68d4f68d70" CreationDate="2017-01-06T21:48:05.473" UserId="5807" Text="|rendering|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10327" PostHistoryTypeId="5" PostId="4479" RevisionGUID="7415ca77-ed2d-4524-a591-9a6edc535836" CreationDate="2017-01-06T21:55:24.353" UserId="5802" Comment="solution" Text="How do you use textures with direct state access in OpenGL?&#xD;&#xA;&#xD;&#xA;I have the following in my code, which seems to work:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glGenTextures(1, &amp;textureHandle);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureHandle);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;However, when I replace it with the following everything just becomes black:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;textureHandle);&#xD;&#xA;    glTextureImage2DEXT(textureHandle, GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTextureParameteri(textureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;Edit: I have now replaced it with the following, which works:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;textureHandle);&#xD;&#xA;    glTextureStorage2D(textureHandle, 1, GL_RGBA8, imageW, imageH);&#xD;&#xA;    glTextureSubImage2D(textureHandle, 0, 0, 0, imageW, imageH, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTextureParameteri(textureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glBindTextureUnit(0, textureHandle);" ContentLicense="CC BY-SA 3.0" />
  <row Id="10333" PostHistoryTypeId="5" PostId="4487" RevisionGUID="37784038-f9c1-4cf6-9c04-47f86e08ad21" CreationDate="2017-01-07T12:12:11.423" UserId="231" Comment="Convert exposed URL to a hyperlink for ease of reading" Text="I would like to compute volumetric obscurance with line integrals like described in [this paper].&#xD;&#xA;&#xD;&#xA;For a 2D sample, it is possible to know the &quot;depth in sphere&quot;. But I don't understand how they compute the occluded (in red on the following image) part and the unnoccluded (in yellow) part of the line in the sphere. &#xD;&#xA;&#xD;&#xA;I think that they say that given the depth read through the sample and the &quot;depth in sphere&quot;, we should be able to deduce each part of the lines.&#xD;&#xA;&#xD;&#xA;[![line sampling][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [this paper]:http://advances.realtimerendering.com/s2010/Ownby,Hall%20and%20Hall%20-%20Toystory3%20(SIGGRAPH%202010%20Advanced%20RealTime%20Rendering%20Course).pdf&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eOLwt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10334" PostHistoryTypeId="5" PostId="4483" RevisionGUID="cfe71160-4d83-442b-b06c-48df9e6e5ddc" CreationDate="2017-01-07T12:17:46.577" UserId="231" Comment="Removing the &quot;one more thing&quot; section now that it has been posted as a separate question" Text="I apologize if my methods seem way off because this is my first time trying to build a path tracer and I'm struggling quite a bit. Currently, I am trying to mimic the &quot;mix shader&quot; node in Blender 3D that combines two different shaders. I would like to add this functionality to my path tracer because it would allow me to make a plastic-like material. Reading through a few explanations, it seems it takes a probabilistic approach to picking one or the other when a ray hits the surface.&#xD;&#xA;&#xD;&#xA;Here is a rendering of an object with a 50/50 mix of ideal reflection and ideal diffuse at 80 samples per pixel:&#xD;&#xA;[![enter image description here][1]][1]   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Something is just off about it. Especially those weird underside highlights on the leg extending farthest to the left. I have a strong feeling I'm implementing it wrong.&#xD;&#xA;&#xD;&#xA;Here is a pseudo implementation of the path tracing part. It uses explicit light sampling. Based off of smallpt path tracer.&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you to anyone who can offer me some direction! Again, sorry if this is really convoluted. I've made it so far and I'm about to give up, but I feel like I'm reaaaally close. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yAi7i.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10335" PostHistoryTypeId="5" PostId="4486" RevisionGUID="89d015e0-b138-4a14-9b23-e55dcfa6d4ea" CreationDate="2017-01-07T12:59:13.773" UserId="231" Comment="Add MathJax - feel free to roll back anything that changes your intention" Text="Recently I asked a question regarding how to mix a glossy and diffuse shader in my path tracer: [Mix shader looks wrong on my path tracer][1]. &#xD;&#xA;I thought it was incorrect, but a comparison between mine and Blender's seems correct. However, now I am lost in how I would approach making the surface of a mirror look rough as this example shows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have done some research, and discovered that there are different types of reflectance models such as Beckmann and GGX. I've found some explanations of how to find the BRDF such as this site: [Specular BRDF][3], but I can't find any explanation on how to do the reflection ray with explicit lighting. As shown in the pseudo code of my path tracer (below), for every object I shoot a ray towards a light and use the surface transport rendering equation to incorporate the BRDF. I am assuming this is where the GGX/Beckmann BRDF would be plugged in. (I'm guessing it's not quite that simple though and some probability must be involved). What really gets me though is that reflection ray. For diffuse it's easy because I just send off a random ray anywhere in the hemisphere of the surface normal. However, for specular, there's a more sharp bump in the BRDF. How would I translate that into a reflected ray? If I just jittered the ideal reflection ray a little, that wouldn't relate to how the microfacets are modeled in the GGX/Beckmann reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Explicit lighting equation from Peter Shirley's Realistic Ray Tracing:&#xD;&#xA;&#xD;&#xA;$$\large L_S(\mathbf x,\mathbf k_o)\approx\frac{\rho(\mathbf k_i,\mathbf k_o)L_e(\mathbf x',\mathbf x-\mathbf x')v(\mathbf x,\mathbf x')\cos\theta_i\cos\theta'}{p(\mathbf x')\left\lVert \mathbf x-\mathbf x'\right\rVert^2}$$&#xD;&#xA;&#xD;&#xA;Where $p(\mathbf x)$ is the density function of the light triangle $1/\text{Area}$&#xD;&#xA;&#xD;&#xA;$\mathbf x'$ is a random point on the light triangle&#xD;&#xA;&#xD;&#xA;$\mathbf x$  is the hit point on the object&#xD;&#xA;&#xD;&#xA;The cosines are the angles between the light's normal and the light ray, and the object's normal and the light ray&#xD;&#xA;&#xD;&#xA;$\rho$ is the BRDF ($1/\pi$ for ideal diffuse)&#xD;&#xA;&#xD;&#xA;And $v$ is either $1$ or $0$ depending on if it's in shadow&#xD;&#xA;&#xD;&#xA;Pseudo code:&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/4483/mix-shader-looks-wrong-on-my-path-tracer&#xD;&#xA;  [2]: https://i.stack.imgur.com/lBTPz.jpg&#xD;&#xA;  [3]: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10336" PostHistoryTypeId="2" PostId="4489" RevisionGUID="26d83d2e-3822-411c-b81d-ee888cf62eaa" CreationDate="2017-01-07T16:03:04.000" UserId="5802" Text="I have now replaced it with the following, which works:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;textureHandle);&#xD;&#xA;    glTextureStorage2D(textureHandle, 1, GL_RGBA8, imageW, imageH);&#xD;&#xA;    glTextureSubImage2D(textureHandle, 0, 0, 0, imageW, imageH, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTextureParameteri(textureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glBindTextureUnit(0, textureHandle);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10337" PostHistoryTypeId="5" PostId="4479" RevisionGUID="0473aaa2-1fcd-4fa7-b02b-5f6b703c73da" CreationDate="2017-01-07T16:03:11.527" UserId="2654" Comment="Answers do not go in questions." Text="How do you use textures with direct state access in OpenGL?&#xD;&#xA;&#xD;&#xA;I have the following in my code, which seems to work:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glGenTextures(1, &amp;textureHandle);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureHandle);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;However, when I replace it with the following everything just becomes black:&#xD;&#xA;&#xD;&#xA;    GLuint textureHandle;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;textureHandle);&#xD;&#xA;    glTextureImage2DEXT(textureHandle, GL_TEXTURE_2D, 0, GL_RGBA8, imageW, imageH, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);&#xD;&#xA;    glTextureParameteri(textureHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10338" PostHistoryTypeId="24" PostId="4479" RevisionGUID="0473aaa2-1fcd-4fa7-b02b-5f6b703c73da" CreationDate="2017-01-07T16:03:11.527" Comment="Proposed by 2654 approved by 2500, 5802 edit id of 192" ContentLicense="CC BY-SA 3.0" />
  <row Id="10340" PostHistoryTypeId="2" PostId="4490" RevisionGUID="fd955966-ec29-4f3e-b9dc-6d9a118ae6c0" CreationDate="2017-01-07T21:00:10.837" UserId="56" Text="Let's say that I have a raytracer that is rendering a scene that includes a refractive object.&#xD;&#xA;&#xD;&#xA;When a ray hits the refractive object, I know that I can use the fresnel equation (Schlick's approximation in my case) as well as the object's base reflectivity amount to figure out how much light is reflected or transmitted at that point on the surface.&#xD;&#xA;&#xD;&#xA;At this point, I can get the reflected color using a reflection ray (possibly recursively), an environment map, and also calculate a specular highlight for the light source(s) I have.  I sum whatever reflection colors I have, multiplied by the amount of reflection from the fresnel equation.&#xD;&#xA;&#xD;&#xA;Next, I calculate what amount of light comes in due to refraction by following the refracted ray (recursively) and multiplying that value by 1.0-reflectionAmount.&#xD;&#xA;&#xD;&#xA;That makes sense to me so far, but where I get a little confused is for the refraction rays.&#xD;&#xA;&#xD;&#xA;When I follow the refracted ray into the object and hit the back side of the surface the first time, i once again use the fresnel equations to calculate the reflected (internally) and refracted multipliers for the light, taking into account the possibility of total internal refraction (assuming here that the inside of the object has a higher IOR than outside of the object, an ok assumption for my case).&#xD;&#xA;&#xD;&#xA;But, at this point, do i apply a specular highlight to the surface that i hit from the inside?&#xD;&#xA;&#xD;&#xA;On one hand it's a surface so i feel like i should, but which ray should i use for the lighting - the refracted ray or the reflected ray, or both?&#xD;&#xA;&#xD;&#xA;If using the refracted ray, it feels wrong to use the direction to the light source for the specular light, and feels like i should shoot the refracted ray to the surface of the object and see what the specular highlight would look like from there and use that - but do so recursively, using the fresnel equation again at each step.&#xD;&#xA;&#xD;&#xA;Can anyone explain a decent way to handle a specular highlight in a ray tracer that supports refraction and total internal reflection?&#xD;&#xA;&#xD;&#xA;Since this is a ray tracer, not a path tracer, instead of being limited to physically accurate solutions, I'm looking for any plausible solutions, but of course, physically inspired solutions are likely to be better!&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10341" PostHistoryTypeId="1" PostId="4490" RevisionGUID="fd955966-ec29-4f3e-b9dc-6d9a118ae6c0" CreationDate="2017-01-07T21:00:10.837" UserId="56" Text="How to handle specular highlights with reflection / total internal reflection in a ray tracer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10342" PostHistoryTypeId="3" PostId="4490" RevisionGUID="fd955966-ec29-4f3e-b9dc-6d9a118ae6c0" CreationDate="2017-01-07T21:00:10.837" UserId="56" Text="|raytracing|specular|reflection|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10343" PostHistoryTypeId="2" PostId="4491" RevisionGUID="c4b8d24d-774d-4774-b32b-c2170fe1824b" CreationDate="2017-01-07T21:35:26.213" UserId="4509" Text="I am writing a plugin to export data from 3DS Max. 3DS Max's geometry pipeline is... interesting.&#xD;&#xA;&#xD;&#xA;As part of my plugin I decompose a transform matrix into a translation, (quaternion) rotation &amp; scale using an inbuilt function.&#xD;&#xA;This of course does not always work, such as when a shear is present.&#xD;&#xA;&#xD;&#xA;Max does have an affine decomposition function, but I don't want to use that because the resulting components do not all have an analogue in the destination application.&#xD;&#xA;&#xD;&#xA;What I'd like to do, is detect when the decomposition is lossy, so I can bake the geometry for the object which uses it, before transmitting it.&#xD;&#xA;&#xD;&#xA;**How can I determine, either before or after, whether a matrix TRS decomposition is exact?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="10344" PostHistoryTypeId="1" PostId="4491" RevisionGUID="c4b8d24d-774d-4774-b32b-c2170fe1824b" CreationDate="2017-01-07T21:35:26.213" UserId="4509" Text="Detect a lossy matrix decomposition?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10345" PostHistoryTypeId="3" PostId="4491" RevisionGUID="c4b8d24d-774d-4774-b32b-c2170fe1824b" CreationDate="2017-01-07T21:35:26.213" UserId="4509" Text="|transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10346" PostHistoryTypeId="2" PostId="4492" RevisionGUID="8252fe55-de97-49b3-970a-4e6cd2e9cda9" CreationDate="2017-01-07T23:34:33.220" UserId="5816" Text="Think of diffuse as the amount of light scattered by the roughness of the surface.&#xD;&#xA;&#xD;&#xA;Surfaces such as wood has a high diffuse coefficient due to it's material texture, but if it was sanded, varnished and polished, the surface would be far smoother, thus decreasing the diffuse coefficient, but increasing the &quot;mirror shine&quot;, or specularity.&#xD;&#xA;&#xD;&#xA;Albedo would be the amount of light, on average, that a surface reflects. The moon, despite being cratered and pitted, reflect a lot of light due to the distance between the observer and the moon, and so, the diffuse of the individual surface regions can be ignored, in favour of an average value. Going back to the lunar example, we know that the moon has many regions, with varying amounts of diffuse and specular values, but at a far enough distance, those values become less important, as we are too far away to make out such detail with the naked eye.&#xD;&#xA;&#xD;&#xA;At far distances, you could theoretically, in computer graphics terms, use albedo to compute the average colour of a surface (using sampling), and use the specular coefficient to compute the brightness of that colour. But in practice, LOD texture sampling does the job just fine." ContentLicense="CC BY-SA 3.0" />
  <row Id="10349" PostHistoryTypeId="2" PostId="4493" RevisionGUID="f6f4e028-8446-4e09-912d-058b49a9b3fd" CreationDate="2017-01-08T19:36:44.920" UserId="48" Text="You can detect a matrix that can't be decomposed in TRS form by taking its 3×3 upper-left submatrix, interpreting its columns as vectors, and dotting them together in all combinations (1 with 2, 2 with 3, and 1 with 3). For a TRS matrix, the three dot products should all be zero, i.e. the column vectors should be orthogonal to each other. If any of the dot products are nonzero (beyond some epsilon to account for roundoff error) then the matrix is not decomposable as TRS.&#xD;&#xA;&#xD;&#xA;This derives from the property that a rotation matrix is an [orthogonal matrix](https://en.wikipedia.org/wiki/Orthogonal_matrix), i.e. its column vectors form an orthonormal basis. When you multiply the rotation by a scaling matrix, the column vectors may no longer be unit vectors, but they should still be orthogonal. And the translation part doesn't affect the rotation-scaling part." ContentLicense="CC BY-SA 3.0" />
  <row Id="10350" PostHistoryTypeId="2" PostId="4494" RevisionGUID="0bfc5908-26c1-43dc-bf74-80b11e7adc5d" CreationDate="2017-01-08T20:07:08.267" UserId="48" Text="For explicit light sampling: yep, you just evaluate the BRDF for that incoming direction and the output direction back toward the camera. There's probability involved in the case of an area light: you have to randomly choose a point on the light source, and include a factor to convert from probability density over light source area to a density over solid angle at the receiver point. It looks like you've got that already (that's the $\cos \theta' / (p(\mathbf{x}')\|\mathbf{x}-\mathbf{x}'\|^2)$ in the formula you mentioned).&#xD;&#xA;&#xD;&#xA;For sampling the reflection ray, you _could_ just pick a random ray from the hemisphere and weight it by the BRDF, the same as you'd do for diffuse. But that won't be very efficient; it'll take a huge number of samples to converge to a low-noise result.&#xD;&#xA;&#xD;&#xA;What you really want to do is _importance-sample_ the BRDF. This means choosing a random ray not uniformly over the hemisphere, but using a probability distribution that matches the shape of the BRDF (as much as possible). Then you'll automatically get rays that are clustered around the sharp reflection peak in the BRDF when the roughness is low, and spread out more over the hemisphere when the roughness is high.&#xD;&#xA;&#xD;&#xA;So how do you do it? The paper [Microfacet Models for Refraction through Rough Surfaces](http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html) by Walter et al (which popularized the GGX distribution in graphics) handily gives importance-sampling formulas for several common BRDFs in section 5.2. Their approach is to importance-sample the normal distribution of the BRDF, then leave the Fresnel and geometry factors to be factored into the path weight.&#xD;&#xA;&#xD;&#xA;For example, their GGX importance-sampling formula is (equations 35–36):&#xD;&#xA;$$\begin{aligned}\theta_m &amp;= \arctan \left( \frac{\alpha_g\sqrt{\xi_1}}{\sqrt{1-\xi_1}} \right) \\ \phi_m &amp;= 2\pi\xi_2\end{aligned}$$&#xD;&#xA;where $\alpha_g$ is the GGX roughness parameter, and $\xi_1, \xi_2$ are a pair of uniform random numbers in [0, 1]. The outputs $\theta_m, \phi_m$ are the polar coordinates (relative to the surface normal) of the sampled microfacet normal.&#xD;&#xA;&#xD;&#xA;So to use this, you'd choose random inputs $\xi_1, \xi_2$, then evaluate the above equations, and use the resulting normal to compute the reflection ray, as well as the Fresnel and geometry factors from the BRDF." ContentLicense="CC BY-SA 3.0" />
  <row Id="10351" PostHistoryTypeId="2" PostId="4495" RevisionGUID="dc0ecf24-9f5d-49ef-a5b2-cebee4784546" CreationDate="2017-01-08T20:27:29.750" UserId="48" Text="This is based on the formula for a sphere that expresses its surface $z$ as a function of $x, y$:&#xD;&#xA;$$z(x, y) = \pm\sqrt{r^2 - x^2 - y^2}$$&#xD;&#xA;&#xD;&#xA;So, if $x, y$ is the vector from the sphere's center to your sample point, the total length of the line segment (both occluded and unoccluded parts) is the distance between the top and bottom surfaces, which is $L = 2\sqrt{r^2 - x^2 - y^2}$. (This formula appears on slide 51 of that paper, BTW, although they've apparently scaled so that the radius is 1.)&#xD;&#xA;&#xD;&#xA;Then, if you know the depth of the sample point relative to the sphere's center (call it $\Delta z$), you can calculate the fraction of the line that's occluded as&#xD;&#xA;$$\frac{\tfrac{1}{2}L - \Delta z}{L}$$&#xD;&#xA;or equivalently&#xD;&#xA;$$\frac{1}{2} - \frac{\Delta z}{L}$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="10354" PostHistoryTypeId="2" PostId="4496" RevisionGUID="cac2b6ba-73a5-4053-b3b9-21c44a67ab54" CreationDate="2017-01-09T09:41:49.727" UserId="5823" Text="In my case, i fixed the problem adding Dx' for interpolation of x-direction.&#xD;&#xA;In edge scan line of x-direction, I use integer-type for speed-up but ingnored dx' as below. I changed variable type from interger to float and adding dx'.&#xD;&#xA;(picture 1)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sqqTx.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10358" PostHistoryTypeId="5" PostId="4484" RevisionGUID="7617271e-b1ad-4620-bf42-f29305c325bd" CreationDate="2017-01-09T10:54:09.830" UserId="5399" Comment="added 1293 characters in body" Text="#THE SHORT VERSION#&#xD;&#xA;In my fragment shader I'm reading (using texelFetch) multiple times the same texel from a texture (created by another fragment shader) and write it to the output render buffer. After a few read operations on the texel a fault occurs.&#xD;&#xA;&#xD;&#xA;The texture and my rendered image have a size of (n*256) x (m*192) pixel/texel. In the first instance (texel [0,...,255]x[0,...,191]) the texture contains a human.&#xD;&#xA;&#xD;&#xA;Here is the minimal code of the fragment shader which should copy the human:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    // output render buffer&#xD;&#xA;    layout(location = 5) out float depth;&#xD;&#xA;    &#xD;&#xA;    in      vec4    gl_FragCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    &#xD;&#xA;        ivec2 pos       = ivec2(mod(gl_FragCoord.x,256),  mod(gl_FragCoord.y,192));&#xD;&#xA;        vec4  gradient  = texelFetch(GradientsTexture, pos);&#xD;&#xA;        depth           = gradient.x;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After execution the output looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, there is an Problem after the third instance. Additionally I noticed, that the position of the black boxe/stripes varies randomly.&#xD;&#xA;&#xD;&#xA;Do you have any idea how this problem could be fixed?&#xD;&#xA;&#xD;&#xA;# THE LONG VERSION #&#xD;&#xA;&#xD;&#xA;Basically my problem deals with texture access in OpenGL's Fragment Shader. First I'll describe the background of the problem and what I want to accomplish. Afterwards I'll explain the point at which my problem arises. And finally I'll present a few lines of code followed by my actual question. If you're not interested in the details you can skip directly to the problem. But maybe the detailed explanation is useful for others.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Background#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Basically I want to compute the partial derivatives of a rendered depth image according to equation (15) in this paper [*Wei, Xiaolin, Peizhao Zhang, and Jinxiang Chai. &quot;Accurate realtime full-body motion capture using a single depth camera.&quot; ACM Transactions on Graphics (TOG) 31.6 (2012): 188.*][2]&#xD;&#xA;&#xD;&#xA;**Derivatives**&#xD;&#xA;&#xD;&#xA;In this paper there are two important derivatives which has to be computed: &#xD;&#xA;&#xD;&#xA;**1. The Parameter Gradient**&#xD;&#xA;&#xD;&#xA;The change of depth value $D$ with respect to a parameter $q_k$ which moves the skeleton:&#xD;&#xA;$$ \frac{\partial D_c}{\partial \vec{q}} = \left[\frac{\partial D_c}{\partial q_1},\; ...,\; \frac{\partial D_c}{\partial q_k},\;...\right] $$&#xD;&#xA;But since I'm using multiple cameras, I've different depth images of the same model. In the example here two cameras are used ($c=1,2$) and therefore we have $D_1$ and $D_2$.&#xD;&#xA;This gradients can be seen in the image below. I'll refer to this image as *Gradient-Texture* $G$. Here we see multiple instances of the same model. The first instance (0) in the upper left corner is in contrast to the other instances not a derivative but the raw depth value $D_1$. The second instance is the depth change with respect to a rotation of the whole model around the x-axis (which is  parameter $q_1$)($q_7$ is the angle of the upper leg). After all $\frac{\partial D_1}{\partial q_k}$ are computed we proceed with $c=2$ and see $D_2$ and so on.&#xD;&#xA;&#xD;&#xA;[![Absolute value of the depth gradient][3]][3]&#xD;&#xA;*Figure 1: The raw depth images and depth gradients with respect to parameters. (referred to as Gradient-Texture $G$ )*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2. The Image Gradient**&#xD;&#xA;&#xD;&#xA;The image gradient is well known and has to be computed by applying the convolution operator $\left[-1/2, 0, +1/2 \right]$ to $D_1$ and $D_2$. By doing this in x and y direction we get:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c = \left[ \frac{\partial D_c}{\partial x}, \frac{\partial D_c}{\partial y} \right]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Summation**&#xD;&#xA;&#xD;&#xA;In the end I have to sum up the two derivatives:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c \frac{\partial \vec{x}}{\partial \vec{q}} + \frac{\partial D_c}{\partial \vec{q}} \;. \;\; (1)$$&#xD;&#xA;&#xD;&#xA;Where $\frac{\partial \vec{x}}{\partial \vec{q}}$ is the change of the image coordinates of a projected point on the model with respect to a parameter. This becomes a constant for a orthographic projection as it is applied here.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Problem#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the sum in equation (1) i need to add the gradient to each $\frac{\partial D_c}{\partial q_k}$. Therefore I need to access $D_c$ in each instance, compute the derivative and add it to the instance $\frac{\partial D_c}{\partial q_k}$. &#xD;&#xA;&#xD;&#xA;This is done in a Fragment Shader which has as input the figure 1 (as GL_TEXTURE_RECTANGLE). Since each instance $i$ does not know where to find the raw depth image ($D_c$) in the texture, an additional input with the x- and y-offset from the current pixel/texel position to the according pixel/texel position of the raw depth image is provided: Let's call it $O_x$ and $O_y$. So to get the coordinates of the raw depth image $D_c$ in the Gradient-Texture $G$, we do:&#xD;&#xA;$$&#xD;&#xA;x_D  =  x + O_x(x,y)\;\, \;\;\;\;\;\;\;\;  \\&#xD;&#xA;y_D  =  y + O_y(x,y)\;, \;\;\; (2)$$&#xD;&#xA;where $x$, $y$ are the current pixel coordinates (gl_fragCoord) in the Fragment Shader and $x_D$ is the x-coordinate of the raw depth image $D_c$ assigned to the Gradient-Texture at $(x,y)$.&#xD;&#xA;&#xD;&#xA;The Offset-Texture $O_x$ is shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Offset-Texture][4]][4]&#xD;&#xA;*Figure 2: The Offset-Texture which transforms the coordinates from a point of each instance in the Gradient-Texture to the coordinates of the raw depth image in the Gradient-Texture.*&#xD;&#xA;&#xD;&#xA;When I do the computation stated in equation (2) I obtain the Base-Coordinates $x_D$, as I called them. They are shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Position Offset][5]][5]&#xD;&#xA;*Figure 3: The Base-Position $x_D$ of the raw depth image for each instance.*&#xD;&#xA;&#xD;&#xA;And now when I access the values of the Gradient-Texture with the computed Base-Coordinates&#xD;&#xA;&#xD;&#xA;$$D_c = G(x_D,y_D)$$&#xD;&#xA;&#xD;&#xA;I get a fault. The result is shown in Figure 4 below. I would expect each instance to show it's assigned raw depth $D_c$. But as you see there are black artefacts. Afterwards I would have to compute the gradient image $\nabla D_c$ but I stopped here since there is obviously a fault.&#xD;&#xA;&#xD;&#xA;[![Raw Depth accessed using Base-Coordinates][6]][6]&#xD;&#xA;*Figure 4: Raw depth $D_c$ extracted from the Gradient-Texture $G$ using the computed Base-Coordinates*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Code#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To provide useful feedback I assume you'll need the Code. In the following you'll find the Fragment Shader code. &#xD;&#xA;&#xD;&#xA;The variable&#xD;&#xA;    GradientsTexture&#xD;&#xA;contains $G$ and&#xD;&#xA;&#xD;&#xA;    GradientsOffset&#xD;&#xA;contains $O_x$ and $O_y$.&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    // locations of the output data&#xD;&#xA;    layout(location = 5) out float	depth2;&#xD;&#xA;&#xD;&#xA;    in		vec4	gl_FragCoord;&#xD;&#xA;&#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    uniform sampler2DRect GradientsOffset;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;	    ivec2 pos		= ivec2(gl_FragCoord.x-0.5,  gl_FragCoord.y-0.5);&#xD;&#xA;	    ivec2 offset	= ivec2(texelFetch(GradientsOffset, pos).xy);&#xD;&#xA;	    ivec2 basePos	= pos+offset;&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;	    depth2 = gradient.x;&#xD;&#xA;	&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Question#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally my question: Does anyone knows where these artefacts come from? As you saw in the figures above, the steps before give corret results. Only the access to the Gradient-Texture with &#xD;&#xA;&#xD;&#xA;    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;causes unexpected results as shown in figure 4.&#xD;&#xA;&#xD;&#xA;Thanks in advance and sorry for the long explanation.&#xD;&#xA;&#xD;&#xA;Cheers,&#xD;&#xA;Christian Bloch.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iqYUW.png&#xD;&#xA;  [2]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.297.3923&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/UJEzd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zFcmq.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/dLMrk.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/zSJEu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10359" PostHistoryTypeId="5" PostId="4484" RevisionGUID="f568575e-6f7e-49fc-b777-ed8f61a624ab" CreationDate="2017-01-09T12:19:53.310" UserId="5399" Comment="Added new insight: No fault when GPU debugging is used" Text="#THE SHORT VERSION#&#xD;&#xA;In my fragment shader I'm reading (using texelFetch) multiple times the same texel from a texture (created by another fragment shader) and write it to the output render buffer. After a few read operations on the texel a fault occurs.&#xD;&#xA;&#xD;&#xA;The texture and my rendered image have a size of (n*256) x (m*192) pixel/texel. In the first instance (texel [0,...,255]x[0,...,191]) the texture contains a human.&#xD;&#xA;&#xD;&#xA;Here is the minimal code of the fragment shader which should copy the human:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    // output render buffer&#xD;&#xA;    layout(location = 5) out float depth;&#xD;&#xA;    &#xD;&#xA;    in      vec4    gl_FragCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    &#xD;&#xA;        ivec2 pos       = ivec2(mod(gl_FragCoord.x,256),  mod(gl_FragCoord.y,192));&#xD;&#xA;        vec4  gradient  = texelFetch(GradientsTexture, pos);&#xD;&#xA;        depth           = gradient.x;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After execution the output looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, there is an Problem after the third instance. Additionally I noticed, that the position of the black boxe/stripes varies randomly.&#xD;&#xA;&#xD;&#xA;Do you have any idea how this problem could be fixed?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# THE LONG VERSION #&#xD;&#xA;&#xD;&#xA;Basically my problem deals with texture access in OpenGL's Fragment Shader. First I'll describe the background of the problem and what I want to accomplish. Afterwards I'll explain the point at which my problem arises. And finally I'll present a few lines of code followed by my actual question. If you're not interested in the details you can skip directly to the problem. But maybe the detailed explanation is useful for others.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Background#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Basically I want to compute the partial derivatives of a rendered depth image according to equation (15) in this paper [*Wei, Xiaolin, Peizhao Zhang, and Jinxiang Chai. &quot;Accurate realtime full-body motion capture using a single depth camera.&quot; ACM Transactions on Graphics (TOG) 31.6 (2012): 188.*][2]&#xD;&#xA;&#xD;&#xA;**Derivatives**&#xD;&#xA;&#xD;&#xA;In this paper there are two important derivatives which has to be computed: &#xD;&#xA;&#xD;&#xA;**1. The Parameter Gradient**&#xD;&#xA;&#xD;&#xA;The change of depth value $D$ with respect to a parameter $q_k$ which moves the skeleton:&#xD;&#xA;$$ \frac{\partial D_c}{\partial \vec{q}} = \left[\frac{\partial D_c}{\partial q_1},\; ...,\; \frac{\partial D_c}{\partial q_k},\;...\right] $$&#xD;&#xA;But since I'm using multiple cameras, I've different depth images of the same model. In the example here two cameras are used ($c=1,2$) and therefore we have $D_1$ and $D_2$.&#xD;&#xA;This gradients can be seen in the image below. I'll refer to this image as *Gradient-Texture* $G$. Here we see multiple instances of the same model. The first instance (0) in the upper left corner is in contrast to the other instances not a derivative but the raw depth value $D_1$. The second instance is the depth change with respect to a rotation of the whole model around the x-axis (which is  parameter $q_1$)($q_7$ is the angle of the upper leg). After all $\frac{\partial D_1}{\partial q_k}$ are computed we proceed with $c=2$ and see $D_2$ and so on.&#xD;&#xA;&#xD;&#xA;[![Absolute value of the depth gradient][3]][3]&#xD;&#xA;*Figure 1: The raw depth images and depth gradients with respect to parameters. (referred to as Gradient-Texture $G$ )*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2. The Image Gradient**&#xD;&#xA;&#xD;&#xA;The image gradient is well known and has to be computed by applying the convolution operator $\left[-1/2, 0, +1/2 \right]$ to $D_1$ and $D_2$. By doing this in x and y direction we get:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c = \left[ \frac{\partial D_c}{\partial x}, \frac{\partial D_c}{\partial y} \right]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Summation**&#xD;&#xA;&#xD;&#xA;In the end I have to sum up the two derivatives:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c \frac{\partial \vec{x}}{\partial \vec{q}} + \frac{\partial D_c}{\partial \vec{q}} \;. \;\; (1)$$&#xD;&#xA;&#xD;&#xA;Where $\frac{\partial \vec{x}}{\partial \vec{q}}$ is the change of the image coordinates of a projected point on the model with respect to a parameter. This becomes a constant for a orthographic projection as it is applied here.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Problem#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the sum in equation (1) i need to add the gradient to each $\frac{\partial D_c}{\partial q_k}$. Therefore I need to access $D_c$ in each instance, compute the derivative and add it to the instance $\frac{\partial D_c}{\partial q_k}$. &#xD;&#xA;&#xD;&#xA;This is done in a Fragment Shader which has as input the figure 1 (as GL_TEXTURE_RECTANGLE). Since each instance $i$ does not know where to find the raw depth image ($D_c$) in the texture, an additional input with the x- and y-offset from the current pixel/texel position to the according pixel/texel position of the raw depth image is provided: Let's call it $O_x$ and $O_y$. So to get the coordinates of the raw depth image $D_c$ in the Gradient-Texture $G$, we do:&#xD;&#xA;$$&#xD;&#xA;x_D  =  x + O_x(x,y)\;\, \;\;\;\;\;\;\;\;  \\&#xD;&#xA;y_D  =  y + O_y(x,y)\;, \;\;\; (2)$$&#xD;&#xA;where $x$, $y$ are the current pixel coordinates (gl_fragCoord) in the Fragment Shader and $x_D$ is the x-coordinate of the raw depth image $D_c$ assigned to the Gradient-Texture at $(x,y)$.&#xD;&#xA;&#xD;&#xA;The Offset-Texture $O_x$ is shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Offset-Texture][4]][4]&#xD;&#xA;*Figure 2: The Offset-Texture which transforms the coordinates from a point of each instance in the Gradient-Texture to the coordinates of the raw depth image in the Gradient-Texture.*&#xD;&#xA;&#xD;&#xA;When I do the computation stated in equation (2) I obtain the Base-Coordinates $x_D$, as I called them. They are shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Position Offset][5]][5]&#xD;&#xA;*Figure 3: The Base-Position $x_D$ of the raw depth image for each instance.*&#xD;&#xA;&#xD;&#xA;And now when I access the values of the Gradient-Texture with the computed Base-Coordinates&#xD;&#xA;&#xD;&#xA;$$D_c = G(x_D,y_D)$$&#xD;&#xA;&#xD;&#xA;I get a fault. The result is shown in Figure 4 below. I would expect each instance to show it's assigned raw depth $D_c$. But as you see there are black artefacts. Afterwards I would have to compute the gradient image $\nabla D_c$ but I stopped here since there is obviously a fault.&#xD;&#xA;&#xD;&#xA;[![Raw Depth accessed using Base-Coordinates][6]][6]&#xD;&#xA;*Figure 4: Raw depth $D_c$ extracted from the Gradient-Texture $G$ using the computed Base-Coordinates*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Code#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To provide useful feedback I assume you'll need the Code. In the following you'll find the Fragment Shader code. &#xD;&#xA;&#xD;&#xA;The variable&#xD;&#xA;    GradientsTexture&#xD;&#xA;contains $G$ and&#xD;&#xA;&#xD;&#xA;    GradientsOffset&#xD;&#xA;contains $O_x$ and $O_y$.&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    // locations of the output data&#xD;&#xA;    layout(location = 5) out float	depth2;&#xD;&#xA;&#xD;&#xA;    in		vec4	gl_FragCoord;&#xD;&#xA;&#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    uniform sampler2DRect GradientsOffset;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;	    ivec2 pos		= ivec2(gl_FragCoord.x-0.5,  gl_FragCoord.y-0.5);&#xD;&#xA;	    ivec2 offset	= ivec2(texelFetch(GradientsOffset, pos).xy);&#xD;&#xA;	    ivec2 basePos	= pos+offset;&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;	    depth2 = gradient.x;&#xD;&#xA;	&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Question#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally my question: Does anyone knows where these artefacts come from? As you saw in the figures above, the steps before give corret results. Only the access to the Gradient-Texture with &#xD;&#xA;&#xD;&#xA;    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;causes unexpected results as shown in figure 4.&#xD;&#xA;&#xD;&#xA;Thanks in advance and sorry for the long explanation.&#xD;&#xA;&#xD;&#xA;Cheers,&#xD;&#xA;Christian Bloch.&#xD;&#xA;&#xD;&#xA;#Update 1#&#xD;&#xA;&#xD;&#xA;When I do the &quot;Graphics Debugging&quot; of NVidias NSight VS-Plugin it works fine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iqYUW.png&#xD;&#xA;  [2]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.297.3923&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/UJEzd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zFcmq.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/dLMrk.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/zSJEu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10361" PostHistoryTypeId="5" PostId="4484" RevisionGUID="fcdb5532-ab38-454d-b465-05339bef0163" CreationDate="2017-01-09T12:56:58.447" UserId="5399" Comment="deleted 97 characters in body" Text="#THE SHORT VERSION#&#xD;&#xA;In my fragment shader I'm reading (using texelFetch) multiple times the same texel from a texture (created by another fragment shader) and write it to the output render buffer. After a few read operations on the texel a fault occurs.&#xD;&#xA;&#xD;&#xA;The texture and my rendered image have a size of (n*256) x (m*192) pixel/texel. In the first instance (texel [0,...,255]x[0,...,191]) the texture contains a human.&#xD;&#xA;&#xD;&#xA;Here is the minimal code of the fragment shader which should copy the human:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    // output render buffer&#xD;&#xA;    layout(location = 5) out float depth;&#xD;&#xA;    &#xD;&#xA;    in      vec4    gl_FragCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    &#xD;&#xA;        ivec2 pos       = ivec2(mod(gl_FragCoord.x,256),  mod(gl_FragCoord.y,192));&#xD;&#xA;        vec4  gradient  = texelFetch(GradientsTexture, pos);&#xD;&#xA;        depth           = gradient.x;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After execution the output looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, there is an Problem after the third instance. Additionally I noticed, that the position of the black boxe/stripes varies randomly.&#xD;&#xA;&#xD;&#xA;Do you have any idea how this problem could be fixed?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;# THE LONG VERSION #&#xD;&#xA;&#xD;&#xA;Basically my problem deals with texture access in OpenGL's Fragment Shader. First I'll describe the background of the problem and what I want to accomplish. Afterwards I'll explain the point at which my problem arises. And finally I'll present a few lines of code followed by my actual question. If you're not interested in the details you can skip directly to the problem. But maybe the detailed explanation is useful for others.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Background#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Basically I want to compute the partial derivatives of a rendered depth image according to equation (15) in this paper [*Wei, Xiaolin, Peizhao Zhang, and Jinxiang Chai. &quot;Accurate realtime full-body motion capture using a single depth camera.&quot; ACM Transactions on Graphics (TOG) 31.6 (2012): 188.*][2]&#xD;&#xA;&#xD;&#xA;**Derivatives**&#xD;&#xA;&#xD;&#xA;In this paper there are two important derivatives which has to be computed: &#xD;&#xA;&#xD;&#xA;**1. The Parameter Gradient**&#xD;&#xA;&#xD;&#xA;The change of depth value $D$ with respect to a parameter $q_k$ which moves the skeleton:&#xD;&#xA;$$ \frac{\partial D_c}{\partial \vec{q}} = \left[\frac{\partial D_c}{\partial q_1},\; ...,\; \frac{\partial D_c}{\partial q_k},\;...\right] $$&#xD;&#xA;But since I'm using multiple cameras, I've different depth images of the same model. In the example here two cameras are used ($c=1,2$) and therefore we have $D_1$ and $D_2$.&#xD;&#xA;This gradients can be seen in the image below. I'll refer to this image as *Gradient-Texture* $G$. Here we see multiple instances of the same model. The first instance (0) in the upper left corner is in contrast to the other instances not a derivative but the raw depth value $D_1$. The second instance is the depth change with respect to a rotation of the whole model around the x-axis (which is  parameter $q_1$)($q_7$ is the angle of the upper leg). After all $\frac{\partial D_1}{\partial q_k}$ are computed we proceed with $c=2$ and see $D_2$ and so on.&#xD;&#xA;&#xD;&#xA;[![Absolute value of the depth gradient][3]][3]&#xD;&#xA;*Figure 1: The raw depth images and depth gradients with respect to parameters. (referred to as Gradient-Texture $G$ )*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2. The Image Gradient**&#xD;&#xA;&#xD;&#xA;The image gradient is well known and has to be computed by applying the convolution operator $\left[-1/2, 0, +1/2 \right]$ to $D_1$ and $D_2$. By doing this in x and y direction we get:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c = \left[ \frac{\partial D_c}{\partial x}, \frac{\partial D_c}{\partial y} \right]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Summation**&#xD;&#xA;&#xD;&#xA;In the end I have to sum up the two derivatives:&#xD;&#xA;&#xD;&#xA;$$ \nabla D_c \frac{\partial \vec{x}}{\partial \vec{q}} + \frac{\partial D_c}{\partial \vec{q}} \;. \;\; (1)$$&#xD;&#xA;&#xD;&#xA;Where $\frac{\partial \vec{x}}{\partial \vec{q}}$ is the change of the image coordinates of a projected point on the model with respect to a parameter. This becomes a constant for a orthographic projection as it is applied here.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Problem#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the sum in equation (1) i need to add the gradient to each $\frac{\partial D_c}{\partial q_k}$. Therefore I need to access $D_c$ in each instance, compute the derivative and add it to the instance $\frac{\partial D_c}{\partial q_k}$. &#xD;&#xA;&#xD;&#xA;This is done in a Fragment Shader which has as input the figure 1 (as GL_TEXTURE_RECTANGLE). Since each instance $i$ does not know where to find the raw depth image ($D_c$) in the texture, an additional input with the x- and y-offset from the current pixel/texel position to the according pixel/texel position of the raw depth image is provided: Let's call it $O_x$ and $O_y$. So to get the coordinates of the raw depth image $D_c$ in the Gradient-Texture $G$, we do:&#xD;&#xA;$$&#xD;&#xA;x_D  =  x + O_x(x,y)\;\, \;\;\;\;\;\;\;\;  \\&#xD;&#xA;y_D  =  y + O_y(x,y)\;, \;\;\; (2)$$&#xD;&#xA;where $x$, $y$ are the current pixel coordinates (gl_fragCoord) in the Fragment Shader and $x_D$ is the x-coordinate of the raw depth image $D_c$ assigned to the Gradient-Texture at $(x,y)$.&#xD;&#xA;&#xD;&#xA;The Offset-Texture $O_x$ is shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Offset-Texture][4]][4]&#xD;&#xA;*Figure 2: The Offset-Texture which transforms the coordinates from a point of each instance in the Gradient-Texture to the coordinates of the raw depth image in the Gradient-Texture.*&#xD;&#xA;&#xD;&#xA;When I do the computation stated in equation (2) I obtain the Base-Coordinates $x_D$, as I called them. They are shown in the image below.&#xD;&#xA;&#xD;&#xA;[![Position Offset][5]][5]&#xD;&#xA;*Figure 3: The Base-Position $x_D$ of the raw depth image for each instance.*&#xD;&#xA;&#xD;&#xA;And now when I access the values of the Gradient-Texture with the computed Base-Coordinates&#xD;&#xA;&#xD;&#xA;$$D_c = G(x_D,y_D)$$&#xD;&#xA;&#xD;&#xA;I get a fault. The result is shown in Figure 4 below. I would expect each instance to show it's assigned raw depth $D_c$. But as you see there are black artefacts. Afterwards I would have to compute the gradient image $\nabla D_c$ but I stopped here since there is obviously a fault.&#xD;&#xA;&#xD;&#xA;[![Raw Depth accessed using Base-Coordinates][6]][6]&#xD;&#xA;*Figure 4: Raw depth $D_c$ extracted from the Gradient-Texture $G$ using the computed Base-Coordinates*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Code#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To provide useful feedback I assume you'll need the Code. In the following you'll find the Fragment Shader code. &#xD;&#xA;&#xD;&#xA;The variable&#xD;&#xA;    GradientsTexture&#xD;&#xA;contains $G$ and&#xD;&#xA;&#xD;&#xA;    GradientsOffset&#xD;&#xA;contains $O_x$ and $O_y$.&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    // locations of the output data&#xD;&#xA;    layout(location = 5) out float	depth2;&#xD;&#xA;&#xD;&#xA;    in		vec4	gl_FragCoord;&#xD;&#xA;&#xD;&#xA;    uniform sampler2DRect GradientsTexture;&#xD;&#xA;    uniform sampler2DRect GradientsOffset;&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;&#xD;&#xA;	    ivec2 pos		= ivec2(gl_FragCoord.x-0.5,  gl_FragCoord.y-0.5);&#xD;&#xA;	    ivec2 offset	= ivec2(texelFetch(GradientsOffset, pos).xy);&#xD;&#xA;	    ivec2 basePos	= pos+offset;&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;	    depth2 = gradient.x;&#xD;&#xA;	&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;#The Question#&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And finally my question: Does anyone knows where these artefacts come from? As you saw in the figures above, the steps before give corret results. Only the access to the Gradient-Texture with &#xD;&#xA;&#xD;&#xA;    vec4  gradient	= texelFetch(GradientsTexture, basePos);&#xD;&#xA;&#xD;&#xA;causes unexpected results as shown in figure 4.&#xD;&#xA;&#xD;&#xA;Thanks in advance and sorry for the long explanation.&#xD;&#xA;&#xD;&#xA;Cheers,&#xD;&#xA;Christian Bloch.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iqYUW.png&#xD;&#xA;  [2]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.297.3923&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/UJEzd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zFcmq.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/dLMrk.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/zSJEu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10364" PostHistoryTypeId="2" PostId="4498" RevisionGUID="7f0e2cea-32a6-4b18-a638-fbb68da5c125" CreationDate="2017-01-09T15:25:04.057" UserId="5717" Text="&gt; But, at this point, do i apply a specular highlight to the surface that i hit from the inside?&#xD;&#xA;&#xD;&#xA;Unless you have a light source inside your object, there's no point in doing lighting on the inside surface as you'll hit the object again before you reach the light or environment.&#xD;&#xA;&#xD;&#xA;If you want to support a light in the object, then by all means do your lighting but make sure to trace rays to check that you actually reach the lights without exiting the object.&#xD;&#xA;&#xD;&#xA;Otherwise, that lighting should come from your (internal) reflected ray which will eventually hit the surface again, be refracted and get light from the outside.&#xD;&#xA;&#xD;&#xA;&gt; which ray should i use for the lighting - the refracted ray or the reflected ray, or both?&#xD;&#xA;&#xD;&#xA;I think the confusion here is that when you write of &quot;calculate a specular highlight&quot; there is an assumed BRDF which may not make much sense for refraction. At least probably not without a few tweaks. What you really need is a BTDF (bidirectional transmittance distribution function).&#xD;&#xA;&#xD;&#xA;If you want to keep it simple, I think you could adapt a Blinn-Phong model for refraction by using the half vector of equation (16) in [Microfacet Models for Refraction through Rough Surfaces][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10366" PostHistoryTypeId="50" PostId="4374" RevisionGUID="e8c0043d-2987-4c42-9bf1-4b78b16ff96a" CreationDate="2017-01-09T18:02:22.403" UserId="-1" />
  <row Id="10367" PostHistoryTypeId="2" PostId="4499" RevisionGUID="74c46c98-2366-49ab-b981-b9457fbd2d86" CreationDate="2017-01-09T18:57:31.660" UserId="5825" Text="I may do not have understand sampler or pipeline objects in vulkan correctly so I appologize for stupid questions.&#xA;&#xA;I have problems implementing a vulkan renderer alongside my OpenGL one.&#xA;&#xA;In OpenGL one can change sampler parameters easily at runtime (like anisotropy settings through glTexParameter) or blend/depth states.&#xA;&#xA;I wonder if this is also possible in vulkan.&#xA;&#xA;I usually create lets say a sampler object with all information needed and throw the creation info away after construction.&#xA;&#xA;I did not found any information on this on the net.&#xA;&#xA;So, is there any way to changes those settings at runtime or do I have to create a complete new sampler object down the road?&#xA;&#xA;The same question applys to depth/blend states in pipeline objects.&#xA;&#xA;I think the second case would not actually be particularly fast performance wise.&#xA;&#xA;Hope you guys can help me out.&#xA;&#xA;Regards,&#xA;TheMastermaind" ContentLicense="CC BY-SA 3.0" />
  <row Id="10368" PostHistoryTypeId="1" PostId="4499" RevisionGUID="74c46c98-2366-49ab-b981-b9457fbd2d86" CreationDate="2017-01-09T18:57:31.660" UserId="5825" Text="How to change sampler/pipeline states at runtime in vulkan?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10369" PostHistoryTypeId="3" PostId="4499" RevisionGUID="74c46c98-2366-49ab-b981-b9457fbd2d86" CreationDate="2017-01-09T18:57:31.660" UserId="5825" Text="|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10370" PostHistoryTypeId="2" PostId="4500" RevisionGUID="c8fe75e3-eb9b-43d7-8a0c-f3ecfa6a7f24" CreationDate="2017-01-09T19:35:15.503" UserId="4546" Text="That is, to my knowledge, a problem without a proper solution. You're seeing the discrepancy between shading normal and geometry normal and it becomes obvious, that the shading normal is just a trick. [PBRT][1] has a paragraph on this, their solution is to look at the geometric normal to determine whether to call the BRDF (reflection) or the BTDF (transmission), then to pass the shading normal to the BxDF. Still, this doesn't work robustly in all situations.&#xD;&#xA;&#xD;&#xA;This problem is also known and described for production proven render engines:&#xD;&#xA;http://blog.irayrender.com/post/29042276644/shadow-acne-and-the-shadow-terminator&#xD;&#xA;The solution suggested for iRay is to use displacement mapping instead of normal maps. This way, shading and geometry normal are in agreement again.&#xD;&#xA;&#xD;&#xA;  [1]: http://pbrt.org &quot;PBRT&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10371" PostHistoryTypeId="2" PostId="4501" RevisionGUID="0f9162ea-f613-4a08-bb91-279b3e19faa1" CreationDate="2017-01-09T19:51:20.567" UserId="4546" Text="BRDFs are not accurate for any dielectric surface, as all of them have some degree of subsurface scattering. A BSSRDF is also just an approximation based on the assumption of a semi-infinite slab. Ideally, you'd run a volumetric path trace for all surfaces, which would be much more accurate than BRDFs or BSSRDFs, but significantly more expensive. Although, Disney has already used brute force path tracing over BSSRDFs in production, see [the SIGGRAPH 2015 course notes, section 2.5][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10372" PostHistoryTypeId="2" PostId="4502" RevisionGUID="7688c5bc-4be6-443d-ab97-fa431d06a0e9" CreationDate="2017-01-09T20:11:42.203" UserId="5715" Text="You're sort of asking two different questions here but that's okay.&#xD;&#xA;&#xD;&#xA;Changing Sampler states is pretty straightforward. When you create a descriptor set, you write your `VkSampler` object that you've created into a descriptor set. If you want to update a sampler in a descriptor set, create a `VkSampler` with the sampler settings you want and then call `vkUpdateDescriptorSets` with the new `VkSampler` writes that you want to perform. When you bind that descriptor set again it should contain your new sampler. This is a bit roundabout but you have to architect for it. You probably don't want to update samplers every frame so only do this when you need to. This is not an extremely expensive operation if you do it right. Vulkan expects descriptor set data to change; so long as that data lines up with the descriptor set layout it's going to go pretty fast. &#xD;&#xA;&#xD;&#xA;Changing Pipelines is EXTREMELY expensive. Vulkan doesn't like to perform context switches like this so you can't just *update* an existing pipeline that's in use. You do have to completely rebuild your rendering path to use the new PSO. If you want to change between a few different Pipelines it's best to build them all upfront, build all the different command buffers that use the different pipelines and then execute the command buffer that has the pipeline you want to run. If you want to change your pipeline, execute the other command buffer that uses the pipeline you want. &#xD;&#xA;&#xD;&#xA;Vulkan wants you to create, cache and reuse data as much as possible. That's how you get a lot of savings. You don't need to update descriptor sets, command buffers etc. unless they actually change. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10373" PostHistoryTypeId="2" PostId="4503" RevisionGUID="5c09cb4d-d246-456d-b2ea-60ed30c5e18a" CreationDate="2017-01-09T22:38:06.093" UserId="3434" Text="I'm having some trouble trying to figure out how to go from a coordinate on the screen, to 3D world coordinates on a plane.&#xD;&#xA;&#xD;&#xA;My case is as seen on the picture further down. World origo is in the center with the grid representing the X-Y plane. &#xD;&#xA;I want to be able to click/touch on the screen, and transform the screen coordinates to the correct 3D world coordinates on the X-Y plane.&#xD;&#xA;&#xD;&#xA;I first tried to figure out the maths myself by simple geometry, but got stuck...&#xD;&#xA;I then tried the function `glm::unProject()` after checking out this post http://stackoverflow.com/questions/9901453/using-glms-unproject.&#xD;&#xA;&#xD;&#xA;The screen has dimensions `mWindowWidth` and `mWindowHeight`.&#xD;&#xA;`x`, `y` are the screen coordinates where origo is in the top left corner. Positive x to the right, positive y down.&#xD;&#xA;&#xD;&#xA;`projM` is the projection matrix&#xD;&#xA;&#xD;&#xA;Third parameter is the model matrix, which I believe in my case only needs to be an identity matrix.&#xD;&#xA;&#xD;&#xA;I get the world coordinates X and Y (Z is already known as it is on the plane) by using these parameters in `glm::unProject`:&#xD;&#xA;&#xD;&#xA;    glm::vec3 posVec = glm::unProject(&#xD;&#xA;       glm::vec3(x, float(mWindowHeight) - y, 1.0f), &#xD;&#xA;       glm::mat4(1.0f), &#xD;&#xA;       projM, &#xD;&#xA;       glm::vec4(0.0f, 0.0f, float(mWindowWidth), float(mWindowHeight))&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;What happens is that if I have screen coordinates near world origo, the world coordinates seems correct. But If I use screen coordinates near the edges and corners of the screen, I get a certain offset (see image below).&#xD;&#xA;&#xD;&#xA;Where is this offset coming from, and what am I misunderstanding?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gc5Mu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10374" PostHistoryTypeId="1" PostId="4503" RevisionGUID="5c09cb4d-d246-456d-b2ea-60ed30c5e18a" CreationDate="2017-01-09T22:38:06.093" UserId="3434" Text="Screen to World coordinates glm::unProject" ContentLicense="CC BY-SA 3.0" />
  <row Id="10375" PostHistoryTypeId="3" PostId="4503" RevisionGUID="5c09cb4d-d246-456d-b2ea-60ed30c5e18a" CreationDate="2017-01-09T22:38:06.093" UserId="3434" Text="|raytracing|projections|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10379" PostHistoryTypeId="2" PostId="4504" RevisionGUID="f01f6f60-7f88-41db-b314-f3e3172505c9" CreationDate="2017-01-10T01:45:02.033" UserId="5764" Text="I have been trying to implement the GGX shader in my path tracer based on this paper: [Microfacet Models for Refraction through Rough Surfaces][1]&#xD;&#xA;It's pretty clear how the importance sampling works, but I would also like to do next even estimation (direct lighting) for when the object is more rough and acts close to a diffuse shader. &#xD;&#xA;The part that is really confusing to me is equation [19] and [20]:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;I don't understand why in [19] they use the microsurface normal, but in [20] they use the macrosurface normal. The transmission term I don't need because I'm just working on the reflectance, but I still don't get why it's m on [19] and n on [20]. Is it possible to use any incident direction and outgoing direction and get back a proper BRDF? Or does the scatter direction &quot;o&quot; have to match where the microsurface normal makes it bounce to? In direct lighting the directions would need to be independent of each other for it to work.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/58HCg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10380" PostHistoryTypeId="1" PostId="4504" RevisionGUID="f01f6f60-7f88-41db-b314-f3e3172505c9" CreationDate="2017-01-10T01:45:02.033" UserId="5764" Text="How to properly direct light sample GGX in path tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="10381" PostHistoryTypeId="3" PostId="4504" RevisionGUID="f01f6f60-7f88-41db-b314-f3e3172505c9" CreationDate="2017-01-10T01:45:02.033" UserId="5764" Text="|raytracing|shader|3d|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10382" PostHistoryTypeId="2" PostId="4505" RevisionGUID="278fd551-d9a5-4d93-9755-553143162320" CreationDate="2017-01-10T01:49:10.983" UserId="5826" Text="Network latency will not be low enough VR in near future. Mobile VR is a key driver for Cloud Rendering. However, the mobile network latency is much higher. Split rendering with future micro-cloud based Gamelets architecture (http://ieeexplore.ieee.org/document/6799051/) is one possible solution for Cloud Rendering for VR. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10383" PostHistoryTypeId="5" PostId="4504" RevisionGUID="32c7be31-12ec-477b-a66f-0bbf7fcdc207" CreationDate="2017-01-10T01:55:08.267" UserId="5764" Comment="added 95 characters in body" Text="I have been trying to implement the GGX shader in my path tracer based on this paper: [Microfacet Models for Refraction through Rough Surfaces][1]&#xD;&#xA;It's pretty clear how the importance sampling works, but I would also like to do next even estimation (direct lighting) for when the object is more rough and acts close to a diffuse shader. &#xD;&#xA;The part that is really confusing to me is equation [19] and [20]:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;I don't understand why in [19] they use the microsurface normal, but in [20] they use the macrosurface normal. The transmission term I don't need because I'm just working on the reflectance, but I still don't get why it's m on [19] and n on [20]. Is it possible to use any incident direction and outgoing direction and get back a proper BRDF? Or does the scatter direction &quot;o&quot; have to match where the microsurface normal makes it bounce to? In direct lighting the directions would need to be independent of each other for it to work since you're grabbing a from the hit point to the light, and from the hit point to the camera. &#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/58HCg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10384" PostHistoryTypeId="2" PostId="4506" RevisionGUID="4778f6e0-c969-4b3b-8657-6173593bffb6" CreationDate="2017-01-10T02:01:08.383" UserId="48" Text="This may simply be a typo or oversight. Note that in the previous section they've been discussing the _microsurface_ BxDFs $f^m_r(\mathbf{i},\mathbf{o},\mathbf{m})$ and $f^m_t(\mathbf{i},\mathbf{o},\mathbf{m})$, which are naturally evaluated at a microsurface normal, but in this section they've moved on to talking about _macrosurface_ BxDFs, which have the microsurface integrated out.&#xD;&#xA;&#xD;&#xA;AFAICT, the intent of equation 19 is just to say that the total BSDF is a sum of reflection and transmission parts, so it doesn't really matter ($\mathbf{m}$ is a free variable there and could be named anything), but to be less confusing it should probably have been $\mathbf{n}$. Maybe they just forgot to update it during a round of edits, or something.&#xD;&#xA;&#xD;&#xA;Yes, you can evaluate a BRDF/BSDF with any combination of input and output directions and it should give the correct answer." ContentLicense="CC BY-SA 3.0" />
  <row Id="10385" PostHistoryTypeId="2" PostId="4507" RevisionGUID="ba47ea08-5548-4857-ae0c-f5d32a6d1d23" CreationDate="2017-01-10T04:40:10.430" UserId="5828" Text="I have a set of non-convex polygons and I want to merge them. I am able to find the a connection between two polygons. If there are more than two polygons, one connection can intersect another polygon within the set. I do not want to check for a possible intersection. So I have to find the nearest neighbor of a single polygon. Is there an existing algorithm? I can't find anything in my literature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0wGVT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10386" PostHistoryTypeId="1" PostId="4507" RevisionGUID="ba47ea08-5548-4857-ae0c-f5d32a6d1d23" CreationDate="2017-01-10T04:40:10.430" UserId="5828" Text="Finding the nearest neighor of polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="10387" PostHistoryTypeId="3" PostId="4507" RevisionGUID="ba47ea08-5548-4857-ae0c-f5d32a6d1d23" CreationDate="2017-01-10T04:40:10.430" UserId="5828" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10388" PostHistoryTypeId="6" PostId="4507" RevisionGUID="c7fd78cb-37bc-4f4e-b51f-a1a8eebd842e" CreationDate="2017-01-10T04:47:08.737" UserId="5828" Comment="edited tags" Text="|algorithm|computational-geometry|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10389" PostHistoryTypeId="2" PostId="4508" RevisionGUID="21114e92-0040-4c0b-b033-3d26391ef910" CreationDate="2017-01-10T08:35:47.950" UserId="4546" Text="You're looking for a nearest neighbor search: https://en.wikipedia.org/wiki/Nearest_neighbor_search&#xD;&#xA;We've solved similar problems in 3D space using spatial subdivision (kd tree). Depending on polygon count and uniformity, a linear search or hash grid would be options too. A linear search, while O(N^2) can still be faster than setting up extra data structures for small a small number of polygons/vertices. A hash grid should be faster to update than a kd tree if your scene is dynamic, and I would expect it to be more efficient when the scene is uniform in vertex density." ContentLicense="CC BY-SA 3.0" />
  <row Id="10391" PostHistoryTypeId="5" PostId="4504" RevisionGUID="b616eb2d-29c5-4391-ae35-96d0b2c8ccb1" CreationDate="2017-01-10T11:58:09.770" UserId="231" Comment="Minor typo" Text="I have been trying to implement the GGX shader in my path tracer based on this paper: [Microfacet Models for Refraction through Rough Surfaces][1]&#xD;&#xA;It's pretty clear how the importance sampling works, but I would also like to do next event estimation (direct lighting) for when the object is more rough and acts close to a diffuse shader.&#xD;&#xA;&#xD;&#xA;The part that is really confusing to me is equation [19] and [20]:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I don't understand why in [19] they use the microsurface normal, but in [20] they use the macrosurface normal. The transmission term I don't need because I'm just working on the reflectance, but I still don't get why it's **m** on [19] and **n** on [20]. Is it possible to use any incident direction and outgoing direction and get back a proper BRDF? Or does the scatter direction &quot;**o**&quot; have to match where the microsurface normal makes it bounce to? In direct lighting the directions would need to be independent of each other for it to work since you're grabbing a from the hit point to the light, and from the hit point to the camera. &#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/58HCg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10392" PostHistoryTypeId="5" PostId="4503" RevisionGUID="d174e164-44ec-4133-88ad-eda34f9512d7" CreationDate="2017-01-10T12:04:39.087" UserId="231" Comment="Minor typos" Text="I'm having some trouble trying to figure out how to go from a coordinate on the screen, to 3D world coordinates on a plane.&#xD;&#xA;&#xD;&#xA;My case is as seen on the picture further down. World origin is in the center with the grid representing the X-Y plane.  &#xD;&#xA;I want to be able to click/touch on the screen, and transform the screen coordinates to the correct 3D world coordinates on the X-Y plane.&#xD;&#xA;&#xD;&#xA;I first tried to figure out the maths myself by simple geometry, but got stuck...  &#xD;&#xA;I then tried the function `glm::unProject()` after checking out [this post].&#xD;&#xA;&#xD;&#xA;The screen has dimensions `mWindowWidth` and `mWindowHeight`.  &#xD;&#xA;`x`, `y` are the screen coordinates where origin is in the top left corner. Positive x to the right, positive y down.&#xD;&#xA;&#xD;&#xA;`projM` is the projection matrix.&#xD;&#xA;&#xD;&#xA;Third parameter is the model matrix, which I believe in my case only needs to be an identity matrix.&#xD;&#xA;&#xD;&#xA;I get the world coordinates X and Y (Z is already known as it is on the plane) by using these parameters in `glm::unProject`:&#xD;&#xA;&#xD;&#xA;    glm::vec3 posVec = glm::unProject(&#xD;&#xA;       glm::vec3(x, float(mWindowHeight) - y, 1.0f), &#xD;&#xA;       glm::mat4(1.0f), &#xD;&#xA;       projM, &#xD;&#xA;       glm::vec4(0.0f, 0.0f, float(mWindowWidth), float(mWindowHeight))&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;What happens is that if I have screen coordinates near world origin, the world coordinates seems correct. But If I use screen coordinates near the edges and corners of the screen, I get a certain offset (see image below).&#xD;&#xA;&#xD;&#xA;Where is this offset coming from, and what am I misunderstanding?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [this post]: http://stackoverflow.com/questions/9901453/using-glms-unproject&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gc5Mu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10393" PostHistoryTypeId="5" PostId="4499" RevisionGUID="9a5bf4a8-9a1a-4728-8f5b-5ec0a8fefc7b" CreationDate="2017-01-10T12:10:24.840" UserId="231" Comment="Minor typos plus remove redundant intro and sign off" Text="I have problems implementing a Vulkan renderer alongside my OpenGL one.&#xD;&#xA;&#xD;&#xA;In OpenGL one can change sampler parameters easily at runtime (like anisotropy settings through glTexParameter) or blend/depth states.&#xD;&#xA;&#xD;&#xA;I wonder if this is also possible in Vulkan.&#xD;&#xA;&#xD;&#xA;I usually create lets say a sampler object with all information needed and throw the creation info away after construction.&#xD;&#xA;&#xD;&#xA;I did not find any information on this on the net.&#xD;&#xA;&#xD;&#xA;So, is there any way to change those settings at runtime or do I have to create a complete new sampler object down the road?&#xD;&#xA;&#xD;&#xA;The same question applies to depth/blend states in pipeline objects.&#xD;&#xA;&#xD;&#xA;I think the second case would not actually be particularly fast performance wise." ContentLicense="CC BY-SA 3.0" />
  <row Id="10394" PostHistoryTypeId="4" PostId="4499" RevisionGUID="9a5bf4a8-9a1a-4728-8f5b-5ec0a8fefc7b" CreationDate="2017-01-10T12:10:24.840" UserId="231" Comment="Minor typos plus remove redundant intro and sign off" Text="How to change sampler/pipeline states at runtime in Vulkan?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10399" PostHistoryTypeId="2" PostId="4510" RevisionGUID="94a1acd2-4548-4c2a-9d62-80b52dd1368c" CreationDate="2017-01-10T18:18:07.440" UserId="4981" Text="I would understand this code that is obscure now. The code calculates ,given a mesh namely vertices (in the parameter vs like 3 floats for each vertex) and indices (in the parameter ind) , the normals for each vertex (which are differents for a vertex of the same triangle also because share differents traingles).&#xD;&#xA;For each triangle are listed 3 indices in the way &quot;TRIANGLES&quot; (It exsists TRANGLE STRIP, TRIANGLE FUN etc).&#xD;&#xA;The code is Javascript (but It does not matter. It's from WebGL)  &#xD;&#xA;The circuitry is counterclockwise.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    utilsObject.prototype.calculateNormals = function(vs, ind){&#xD;&#xA;        var x=0; &#xD;&#xA;        var y=1;&#xD;&#xA;        var z=2;&#xD;&#xA;        &#xD;&#xA;        var ns = [];&#xD;&#xA;        for(var i=0;i&lt;vs.length;i++){ //for each vertex, initialize normal x, normal y, normal z&#xD;&#xA;            ns[i]=0.0;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        for(var i=0;i&lt;ind.length;i=i+3){ //we work on triads of vertices to calculate normals so i = i+3 (i = indices index)&#xD;&#xA;            var v1 = [];&#xD;&#xA;            var v2 = [];&#xD;&#xA;            var normal = [];&#xD;&#xA;            //p1 - p0&#xD;&#xA;             v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;             v1[y] = vs[3*ind[i+1]+y] - vs[3*ind[i]+y];&#xD;&#xA;             v1[z] = vs[3*ind[i+1]+z] - vs[3*ind[i]+z];&#xD;&#xA;           // p0 - p1&#xD;&#xA;             v2[x] = vs[3*ind[i+2]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;             v2[y] = vs[3*ind[i+2]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;             v2[z] = vs[3*ind[i+2]+z] - vs[3*ind[i+1]+z];            &#xD;&#xA;            //p2 - p1&#xD;&#xA;            // v1[x] = vs[3*ind[i+2]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;            // v1[y] = vs[3*ind[i+2]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;            // v1[z] = vs[3*ind[i+2]+z] - vs[3*ind[i+1]+z];&#xD;&#xA;           // p0 - p1&#xD;&#xA;            // v2[x] = vs[3*ind[i]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;            // v2[y] = vs[3*ind[i]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;            // v2[z] = vs[3*ind[i]+z] - vs[3*ind[i+1]+z];&#xD;&#xA;            //cross product by Sarrus Rule&#xD;&#xA;            normal[x] = v1[y]*v2[z] - v1[z]*v2[y];&#xD;&#xA;            normal[y] = v1[z]*v2[x] - v1[x]*v2[z];&#xD;&#xA;            normal[z] = v1[x]*v2[y] - v1[y]*v2[x];&#xD;&#xA;            &#xD;&#xA;            // ns[3*ind[i]+x] += normal[x];&#xD;&#xA;            // ns[3*ind[i]+y] += normal[y];&#xD;&#xA;            // ns[3*ind[i]+z] += normal[z];&#xD;&#xA;             for(j=0;j&lt;3;j++){ //update the normals of that triangle: sum of vectors&#xD;&#xA;                ns[3*ind[i+j]+x] =  ns[3*ind[i+j]+x] + normal[x];&#xD;&#xA;                 ns[3*ind[i+j]+y] =  ns[3*ind[i+j]+y] + normal[y];&#xD;&#xA;                 ns[3*ind[i+j]+z] =  ns[3*ind[i+j]+z] + normal[z];&#xD;&#xA;             }&#xD;&#xA;        }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10400" PostHistoryTypeId="1" PostId="4510" RevisionGUID="94a1acd2-4548-4c2a-9d62-80b52dd1368c" CreationDate="2017-01-10T18:18:07.440" UserId="4981" Text="Explanation of the functioning of the code to calculate the normals to the vertices of a mesh of triangles" ContentLicense="CC BY-SA 3.0" />
  <row Id="10401" PostHistoryTypeId="3" PostId="4510" RevisionGUID="94a1acd2-4548-4c2a-9d62-80b52dd1368c" CreationDate="2017-01-10T18:18:07.440" UserId="4981" Text="|shader|computational-geometry|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10403" PostHistoryTypeId="5" PostId="4503" RevisionGUID="be87638c-6ae5-42da-a821-2a6eb62b0b90" CreationDate="2017-01-10T19:47:46.037" UserId="3434" Comment="added 650 characters in body" Text="I'm having some trouble trying to figure out how to go from a coordinate on the screen, to 3D world coordinates on a plane.&#xD;&#xA;&#xD;&#xA;My case is as seen on the picture further down. World origin is in the center with the grid representing the X-Y plane.  &#xD;&#xA;I want to be able to click/touch on the screen, and transform the screen coordinates to the correct 3D world coordinates on the X-Y plane.&#xD;&#xA;&#xD;&#xA;I first tried to figure out the maths myself by simple geometry, but got stuck...  &#xD;&#xA;I then tried the function `glm::unProject()` after checking out [this post].&#xD;&#xA;&#xD;&#xA;The screen has dimensions `mWindowWidth` and `mWindowHeight`.  &#xD;&#xA;`x`, `y` are the screen coordinates where origin is in the top left corner. Positive x to the right, positive y down.&#xD;&#xA;&#xD;&#xA;`projM` is the projection matrix.&#xD;&#xA;&#xD;&#xA;Third parameter is the model matrix, which I believe in my case only needs to be an identity matrix.&#xD;&#xA;&#xD;&#xA;I get the world coordinates X and Y (Z is already known as it is on the plane) by using these parameters in `glm::unProject`:&#xD;&#xA;&#xD;&#xA;    glm::vec3 posVec = glm::unProject(&#xD;&#xA;       glm::vec3(x, float(mWindowHeight) - y, 1.0f), &#xD;&#xA;       glm::mat4(1.0f), &#xD;&#xA;       projM, &#xD;&#xA;       glm::vec4(0.0f, 0.0f, float(mWindowWidth), float(mWindowHeight))&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;What happens is that if I have screen coordinates near world origin, the world coordinates seems correct. But If I use screen coordinates near the edges and corners of the screen, I get a certain offset (see image below).&#xD;&#xA;&#xD;&#xA;Where is this offset coming from, and what am I misunderstanding?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [this post]: http://stackoverflow.com/questions/9901453/using-glms-unproject&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;As mentioned in the comments, the second parameter should be the &quot;model-view&quot; matrix. I tried to switch `glm::mat4(1.0f)` with `viewM` (view matrix). The effect is still the same, if not with even more offset.&#xD;&#xA;&#xD;&#xA;I also tried to get the `z` buffer depth value by using:&#xD;&#xA;(Got it from this [tutorial][2])&#xD;&#xA;&#xD;&#xA;    float z;&#xD;&#xA;    glReadPixels(int(x), int(mWindowHeight) - int(y), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &amp;z);&#xD;&#xA;&#xD;&#xA;This results in very small values of X and Y world coordinates, and essentially where ever I touch, the resulting coordinates are near the origin.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gc5Mu.png&#xD;&#xA;  [2]: http://nehe.gamedev.net/article/using_gluunproject/16013/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10404" PostHistoryTypeId="2" PostId="4511" RevisionGUID="1730d0b6-17a5-48ff-9f7b-247b557c6e55" CreationDate="2017-01-10T21:27:37.973" UserId="5832" Text="I'm about to implement downscaling on a microcontroller. Source resolution is e.g. 720x576 (the 576i PAL resolution, other one possible: 480i, NTSC resolution), destination is 32x16. The goal is to have RGB LED matrix (of size 36x16) flowing with various colors, shapes, shadows, etc. – a half-abstract vs. half-meaningful effect, driven by a prepared PAL or NTSC video.&#xD;&#xA;&#xD;&#xA;I will only be able to select every 22th pixel (720 / 36) and every 36th line (576 / 16) – the microcontroller will not be able to compute averages of groups of pixels etc. This way I will obtain 32x16 downscaled image to output to the LED matrix.&#xD;&#xA;&#xD;&#xA;I cannot find any examples of how such downscaling will behave. Tried searching for &quot;decimation&quot; but no luck. Which program can I use to test this downscaling? Can I quickly code this somehow – if I would to code this, I would use libSDL1, generate set of files, but this is difficult (e.g. image loading). Maybe some snippet-solution is possible? Should I care about Nyquist frequency?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10405" PostHistoryTypeId="1" PostId="4511" RevisionGUID="1730d0b6-17a5-48ff-9f7b-247b557c6e55" CreationDate="2017-01-10T21:27:37.973" UserId="5832" Text="Downscaling by skipping rows and columns – any example images?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10406" PostHistoryTypeId="3" PostId="4511" RevisionGUID="1730d0b6-17a5-48ff-9f7b-247b557c6e55" CreationDate="2017-01-10T21:27:37.973" UserId="5832" Text="|image-processing|noise|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10407" PostHistoryTypeId="10" PostId="4510" RevisionGUID="d6c67c3c-a285-482a-8865-d416e6d0e247" CreationDate="2017-01-10T22:43:20.437" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="10408" PostHistoryTypeId="5" PostId="4510" RevisionGUID="dd0081d4-8d74-489f-bcd7-a8c9f785b673" CreationDate="2017-01-10T23:34:43.460" UserId="4981" Comment="added 239 characters in body" Text="I would understand this code that is obscure now. The code calculates ,given a mesh namely vertices (in the parameter vs like 3 floats for each vertex) and indices (in the parameter ind) , the normals for each vertex (which are differents for a vertex of the same triangle also because share differents traingles).&#xD;&#xA;For each triangle are listed 3 indices in the way &quot;TRIANGLES&quot; (It exsists TRANGLE STRIP, TRIANGLE FUN etc).&#xD;&#xA;The code is Javascript (but It does not matter. It's from WebGL)  &#xD;&#xA;The circuitry is counterclockwise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    utilsObject.prototype.calculateNormals = function(vs, ind){&#xD;&#xA;        var x=0; &#xD;&#xA;        var y=1;&#xD;&#xA;        var z=2;&#xD;&#xA;        &#xD;&#xA;        var ns = [];&#xD;&#xA;        for(var i=0;i&lt;vs.length;i++){ //for each vertex, initialize normal x, normal y, normal z&#xD;&#xA;            ns[i]=0.0;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        for(var i=0;i&lt;ind.length;i=i+3){ //we work on triads of vertices to calculate normals so i = i+3 (i = indices index)&#xD;&#xA;            var v1 = [];&#xD;&#xA;            var v2 = [];&#xD;&#xA;            var normal = [];&#xD;&#xA;            //p1 - p0&#xD;&#xA;             v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;             v1[y] = vs[3*ind[i+1]+y] - vs[3*ind[i]+y];&#xD;&#xA;             v1[z] = vs[3*ind[i+1]+z] - vs[3*ind[i]+z];&#xD;&#xA;           // p0 - p1&#xD;&#xA;             v2[x] = vs[3*ind[i+2]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;             v2[y] = vs[3*ind[i+2]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;             v2[z] = vs[3*ind[i+2]+z] - vs[3*ind[i+1]+z];            &#xD;&#xA;            //p2 - p1&#xD;&#xA;            // v1[x] = vs[3*ind[i+2]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;            // v1[y] = vs[3*ind[i+2]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;            // v1[z] = vs[3*ind[i+2]+z] - vs[3*ind[i+1]+z];&#xD;&#xA;           // p0 - p1&#xD;&#xA;            // v2[x] = vs[3*ind[i]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;            // v2[y] = vs[3*ind[i]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;            // v2[z] = vs[3*ind[i]+z] - vs[3*ind[i+1]+z];&#xD;&#xA;            //cross product by Sarrus Rule&#xD;&#xA;            normal[x] = v1[y]*v2[z] - v1[z]*v2[y];&#xD;&#xA;            normal[y] = v1[z]*v2[x] - v1[x]*v2[z];&#xD;&#xA;            normal[z] = v1[x]*v2[y] - v1[y]*v2[x];&#xD;&#xA;            &#xD;&#xA;            // ns[3*ind[i]+x] += normal[x];&#xD;&#xA;            // ns[3*ind[i]+y] += normal[y];&#xD;&#xA;            // ns[3*ind[i]+z] += normal[z];&#xD;&#xA;             for(j=0;j&lt;3;j++){ //update the normals of that triangle: sum of vectors&#xD;&#xA;                ns[3*ind[i+j]+x] =  ns[3*ind[i+j]+x] + normal[x];&#xD;&#xA;                 ns[3*ind[i+j]+y] =  ns[3*ind[i+j]+y] + normal[y];&#xD;&#xA;                 ns[3*ind[i+j]+z] =  ns[3*ind[i+j]+z] + normal[z];&#xD;&#xA;             }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;For example how do you explain the indexes in the instruction:&#xD;&#xA;    &#xD;&#xA;    v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;&#xD;&#xA;And above all, what is the logic in the implementation details and no high-level, behind the instructions&#xD;&#xA;&#xD;&#xA;    " ContentLicense="CC BY-SA 3.0" />
  <row Id="10409" PostHistoryTypeId="5" PostId="4510" RevisionGUID="e79b45ec-833d-4dd8-9ef7-d97ea6d036e0" CreationDate="2017-01-11T06:50:25.370" UserId="182" Comment="I have tried to clarify the question, by rewording and fixing the grammar, and removing the commented code." Text="I have trouble understanding the following Javascript code.&#xD;&#xA;&#xD;&#xA;It calculates, given a mesh described by its vertices `vs` and indices `ind`, the normals for each vertex. The mesh faces are a triangle list, and are oriented counterclockwise.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: javascript --&gt;&#xD;&#xA;&#xD;&#xA;    utilsObject.prototype.calculateNormals = function(vs, ind){&#xD;&#xA;        var x=0; &#xD;&#xA;        var y=1;&#xD;&#xA;        var z=2;&#xD;&#xA;        &#xD;&#xA;        var ns = [];&#xD;&#xA;        for(var i=0;i&lt;vs.length;i++){ //for each vertex, initialize normal x, normal y, normal z&#xD;&#xA;            ns[i]=0.0;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        for(var i=0;i&lt;ind.length;i=i+3){ //we work on triads of vertices to calculate normals so i = i+3 (i = indices index)&#xD;&#xA;            var v1 = [];&#xD;&#xA;            var v2 = [];&#xD;&#xA;            var normal = [];&#xD;&#xA;&#xD;&#xA;            //p1 - p0&#xD;&#xA;            v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;            v1[y] = vs[3*ind[i+1]+y] - vs[3*ind[i]+y];&#xD;&#xA;            v1[z] = vs[3*ind[i+1]+z] - vs[3*ind[i]+z];&#xD;&#xA;&#xD;&#xA;            // p0 - p1&#xD;&#xA;            v2[x] = vs[3*ind[i+2]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;            v2[y] = vs[3*ind[i+2]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;            v2[z] = vs[3*ind[i+2]+z] - vs[3*ind[i+1]+z];            &#xD;&#xA;&#xD;&#xA;            //cross product by Sarrus Rule&#xD;&#xA;            normal[x] = v1[y]*v2[z] - v1[z]*v2[y];&#xD;&#xA;            normal[y] = v1[z]*v2[x] - v1[x]*v2[z];&#xD;&#xA;            normal[z] = v1[x]*v2[y] - v1[y]*v2[x];&#xD;&#xA;            &#xD;&#xA;            for(j=0;j&lt;3;j++){ //update the normals of that triangle: sum of vectors&#xD;&#xA;                ns[3*ind[i+j]+x] =  ns[3*ind[i+j]+x] + normal[x];&#xD;&#xA;                ns[3*ind[i+j]+y] =  ns[3*ind[i+j]+y] + normal[y];&#xD;&#xA;                ns[3*ind[i+j]+z] =  ns[3*ind[i+j]+z] + normal[z];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;How does this function work? For example, could you explain the use of indexes in the instruction:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: javascript --&gt;&#xD;&#xA;&#xD;&#xA;    v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;&#xD;&#xA;Rather than a high-level explanation, I am interested in the logic of the implementation details." ContentLicense="CC BY-SA 3.0" />
  <row Id="10410" PostHistoryTypeId="4" PostId="4510" RevisionGUID="e79b45ec-833d-4dd8-9ef7-d97ea6d036e0" CreationDate="2017-01-11T06:50:25.370" UserId="182" Comment="I have tried to clarify the question, by rewording and fixing the grammar, and removing the commented code." Text="How does this function calculates normals of a mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10411" PostHistoryTypeId="2" PostId="4512" RevisionGUID="ac282372-50fa-4011-ae37-5966d376b0ff" CreationDate="2017-01-11T10:14:08.090" UserId="4958" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc.).&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints)&#xD;&#xA; - based on scene voxelization (Voxel Cone Tracing)&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;&#xD;&#xA;I hope this is not an opinion based question." ContentLicense="CC BY-SA 3.0" />
  <row Id="10412" PostHistoryTypeId="1" PostId="4512" RevisionGUID="ac282372-50fa-4011-ae37-5966d376b0ff" CreationDate="2017-01-11T10:14:08.090" UserId="4958" Text="Selection of GI techniques working in real time" ContentLicense="CC BY-SA 3.0" />
  <row Id="10413" PostHistoryTypeId="3" PostId="4512" RevisionGUID="ac282372-50fa-4011-ae37-5966d376b0ff" CreationDate="2017-01-11T10:14:08.090" UserId="4958" Text="|real-time|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10414" PostHistoryTypeId="5" PostId="4512" RevisionGUID="095bb0c3-a40b-4dc0-937f-1330734df061" CreationDate="2017-01-11T10:28:31.717" UserId="4958" Comment="deleted 47 characters in body" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc.).&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints)&#xD;&#xA; - based on scene voxelization (Voxel Cone Tracing)&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10415" PostHistoryTypeId="2" PostId="4513" RevisionGUID="36cfe059-9024-4fa9-93bd-c5fa8e7a05d8" CreationDate="2017-01-11T11:24:26.260" UserId="5609" Text="I use **SDL2**.&#xD;&#xA;&#xD;&#xA;Currently my only shader has a **MVP matrix**, and transforms the points with it.&#xD;&#xA;&#xD;&#xA;**I calculate my View and Projection matrix for a camera with GLM:**&#xD;&#xA;&#xD;&#xA;    glm::lookAt(pos, pos + forward, up);&#xD;&#xA;    glm::perspective(fov, aspectRatio, zNear, zFar);&#xD;&#xA;&#xD;&#xA;I searched it, but I can only find legacy implementation of multiple viewports.&#xD;&#xA;&#xD;&#xA;If I create for example **4 cameras** and let's say that they **all the same**, except every camera has a **different quarter of the screen** to render. (So I want 4 viewports with the same content)&#xD;&#xA;&#xD;&#xA;How can I do this? Sorry if I didn't give enough informations, feel free to ask.&#xD;&#xA;&#xD;&#xA;(Maybe with `glm::frustum(left, right, bottom, top	near, far)`?)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10416" PostHistoryTypeId="1" PostId="4513" RevisionGUID="36cfe059-9024-4fa9-93bd-c5fa8e7a05d8" CreationDate="2017-01-11T11:24:26.260" UserId="5609" Text="Multiple viewports with modern OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10417" PostHistoryTypeId="3" PostId="4513" RevisionGUID="36cfe059-9024-4fa9-93bd-c5fa8e7a05d8" CreationDate="2017-01-11T11:24:26.260" UserId="5609" Text="|opengl|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10418" PostHistoryTypeId="5" PostId="4513" RevisionGUID="f8140c5a-dbbf-4f9f-9e1a-5397bc79f8cb" CreationDate="2017-01-11T11:44:55.550" UserId="5609" Comment="added 104 characters in body" Text="I use **SDL2**.&#xD;&#xA;&#xD;&#xA;Currently my only shader has a **MVP matrix**, and transforms the points with it.&#xD;&#xA;&#xD;&#xA;**I calculate my View and Projection matrix for a camera with GLM:**&#xD;&#xA;&#xD;&#xA;    glm::lookAt(pos, pos + forward, up);&#xD;&#xA;    glm::perspective(fov, aspectRatio, zNear, zFar);&#xD;&#xA;&#xD;&#xA;I searched it, but I can only find legacy implementation of multiple viewports.&#xD;&#xA;&#xD;&#xA;If I create for example **4 cameras** and let's say that they **all the same**, except every camera has a **different quarter of the screen** to render. (So I want 4 viewports with the same content)&#xD;&#xA;&#xD;&#xA;How can I do this? Sorry if I didn't give enough informations, feel free to ask.&#xD;&#xA;&#xD;&#xA;(Maybe with `glm::frustum(left, right, bottom, top	near, far)`?)&#xD;&#xA;&#xD;&#xA;(Or modifying `up`'s value from `(0, 1, 0)` to `(0, 0.25, 0)` and translating the viewport somehow?)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10420" PostHistoryTypeId="2" PostId="4514" RevisionGUID="1648bfed-eced-4be9-8c44-c82d2e0fd88b" CreationDate="2017-01-11T14:45:57.720" UserId="1952" Text="You can calculate the world position of the pixel on near plane quite easily by first defining Normalized Device Coordinates (NDC) for the point and then transforming the NDC back to the world space. You can calculate NDC for your point as follows:&#xD;&#xA;$$v=[2*(x+0.5)/width-1, 1-2*(y+0.5)/height, 0, 1]$$&#xD;&#xA;I'm using 0 here for the z-component assuming near-plane in NDC is 0, but it could be something else as well, so check with your projection matrix what values comes out at the near-plane. This vector must be then transformed to clip-space by multiplying by near-plane distance:&#xD;&#xA;$$v'=np*v$$&#xD;&#xA;Now that you have clip-space coordinates, you just need to transform this back to world space with the standard clip$\rightarrow$world transformation matrix:&#xD;&#xA;$$v''=M*v'$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="10421" PostHistoryTypeId="2" PostId="4515" RevisionGUID="632226f0-70e0-49c9-b290-f2a3908637ce" CreationDate="2017-01-11T14:51:02.887" UserId="4958" Text="Rendering to different viewports (parts) of the same screen can be easily done with blending. As far as I know `glBlend` or `glBlendFunc` isn't considered legacy.&#xD;&#xA;&#xD;&#xA;For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:&#xD;&#xA;&#xD;&#xA;    bindFramebuffer();&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    scene-&gt;setConstPerFrameUniforms();&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_ONE, GL_ONE);&#xD;&#xA;&#xD;&#xA;    //left bottom&#xD;&#xA;    glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(1);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right bottom&#xD;&#xA;    glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(2);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //left top&#xD;&#xA;    glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(3);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right top&#xD;&#xA;    glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(4);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, WindowWidth, WindowHeight); //restore default&#xD;&#xA;    glDisable(GL_BLEND);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10422" PostHistoryTypeId="5" PostId="4515" RevisionGUID="03e1054c-3dd9-407a-856e-a9c5df61d307" CreationDate="2017-01-11T14:57:13.153" UserId="4958" Comment="added 230 characters in body" Text="Rendering to different viewports (parts) of the same screen can be easily done with blending. As far as I know `glBlend` or `glBlendFunc` isn't considered legacy.&#xD;&#xA;&#xD;&#xA;For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:&#xD;&#xA;&#xD;&#xA;    bindFramebuffer();&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    scene-&gt;setConstPerFrameUniforms();&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_ONE, GL_ONE);&#xD;&#xA;&#xD;&#xA;    //left bottom&#xD;&#xA;    glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(1);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right bottom&#xD;&#xA;    glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(2);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //left top&#xD;&#xA;    glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(3);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right top&#xD;&#xA;    glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(4);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, WindowWidth, WindowHeight); //restore default&#xD;&#xA;    glDisable(GL_BLEND);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This use `GL_ONE, GL_ONE` blend mode but for some effects like overlapping different modes can be used. [This][1] is nice visual representation of different modes&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.quake-1.com/docs/blending.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10423" PostHistoryTypeId="5" PostId="4515" RevisionGUID="ec72f0cf-32dd-4b4c-9809-112a6116f761" CreationDate="2017-01-11T15:08:10.067" UserId="4958" Comment="added 1 character in body" Text="Rendering to different viewports (parts) of the same screen can be easily done with blending. As far as I know `GL_BLEND` or `glBlendFunc` isn't considered legacy.&#xD;&#xA;&#xD;&#xA;For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:&#xD;&#xA;&#xD;&#xA;    bindFramebuffer();&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    scene-&gt;setConstPerFrameUniforms();&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_ONE, GL_ONE);&#xD;&#xA;&#xD;&#xA;    //left bottom&#xD;&#xA;    glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(1);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right bottom&#xD;&#xA;    glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(2);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //left top&#xD;&#xA;    glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(3);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right top&#xD;&#xA;    glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(4);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, WindowWidth, WindowHeight); //restore default&#xD;&#xA;    glDisable(GL_BLEND);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This use `GL_ONE, GL_ONE` blend mode but for some effects like overlapping different modes can be used. [This][1] is nice visual representation of different modes&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.quake-1.com/docs/blending.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10424" PostHistoryTypeId="2" PostId="4516" RevisionGUID="4756c12f-222a-433d-a64b-d5c86f7425b5" CreationDate="2017-01-11T15:09:28.307" UserId="1952" Text="Many of the real-time GI solutions have some precomputation involved, which enable real-time lighting changes but limit the geometry changes to be non-real time. E.g. in cone tracing you mentioned there's the non-real time scene voxelization process. Here are few such real-time solutions that come to mind in addition to the ones you listed.&#xD;&#xA;&#xD;&#xA; 1. Light probes&#xD;&#xA; 2. Screen-Space GI&#xD;&#xA; 3. Virtual Point Lights&#xD;&#xA; 4. Precomputed Radiance Transfer&#xD;&#xA;&#xD;&#xA;It's also the question how you define real-time: What's FPS, on what kind of hardware and for what kind of scene complexity.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10425" PostHistoryTypeId="5" PostId="4512" RevisionGUID="60369ddc-2001-4609-b912-74cb15d7c757" CreationDate="2017-01-11T15:13:10.490" UserId="4958" Comment="added 127 characters in body" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc.).&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints)&#xD;&#xA; - based on scene voxelization in real time (Voxel Cone Tracing) - voxelization of box shape (ortho projection) with center as camera position and and moving in voxel size increments&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10426" PostHistoryTypeId="5" PostId="4513" RevisionGUID="fdc1335a-42b4-4aed-af6f-d057408f0ebd" CreationDate="2017-01-11T15:24:54.707" UserId="5609" Comment="deleted 172 characters in body" Text="I use **SDL2**.&#xD;&#xA;&#xD;&#xA;Currently my only shader has a **MVP matrix**, and transforms the points with it.&#xD;&#xA;&#xD;&#xA;**I calculate my View and Projection matrix for a camera with GLM:**&#xD;&#xA;&#xD;&#xA;    glm::lookAt(pos, pos + forward, up);&#xD;&#xA;    glm::perspective(fov, aspectRatio, zNear, zFar);&#xD;&#xA;&#xD;&#xA;I searched it, but I can only find legacy implementation of multiple viewports.&#xD;&#xA;&#xD;&#xA;If I create for example **4 cameras** and let's say that they **all the same**, except every camera has a **different quarter of the screen** to render. (So I want 4 viewports with the same content)&#xD;&#xA;&#xD;&#xA;How can I do this? Sorry if I didn't give enough informations, feel free to ask." ContentLicense="CC BY-SA 3.0" />
  <row Id="10427" PostHistoryTypeId="5" PostId="4512" RevisionGUID="80ab4279-a03b-4c1b-bb76-2f3397edfa74" CreationDate="2017-01-11T16:04:05.323" UserId="4958" Comment="deleted 3 characters in body" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc.).&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints) &#xD;&#xA; - based on scene voxelization in real time (Voxel Cone Tracing) - voxelization of box shape (ortho projection) with center as camera position and moving in voxel size increments&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10428" PostHistoryTypeId="5" PostId="4512" RevisionGUID="dccfb67e-6cdd-4a2a-bee9-9c2246021102" CreationDate="2017-01-11T16:09:10.893" UserId="4958" Comment="deleted 3 characters in body" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc.).&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints) &#xD;&#xA; - based on cone tracing of scene voxelization calculated in every frame (Voxel Cone Tracing) &#xD;&#xA;&#xD;&#xA;Each technique is based on grid moving with camera in voxel size increments.&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10429" PostHistoryTypeId="5" PostId="4515" RevisionGUID="a377cc1a-b78a-4eb8-8478-e6d44913f271" CreationDate="2017-01-11T16:26:54.463" UserId="4958" Comment="added 283 characters in body" Text="Rendering to different viewports (parts) of the same screen can be easily done with blending. As far as I know `GL_BLEND` or `glBlendFunc` isn't considered legacy.&#xD;&#xA;&#xD;&#xA;For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:&#xD;&#xA;&#xD;&#xA;    bindFramebuffer();&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    scene-&gt;setConstPerFrameUniforms();&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_ONE, GL_ONE);&#xD;&#xA;&#xD;&#xA;    //left bottom&#xD;&#xA;    glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(1);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right bottom&#xD;&#xA;    glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(2);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //left top&#xD;&#xA;    glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(3);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right top&#xD;&#xA;    glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(4);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, WindowWidth, WindowHeight); //restore default&#xD;&#xA;    glDisable(GL_BLEND);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This use `GL_ONE, GL_ONE` blend mode but for some effects like overlapping different modes can be used. [This][1] is nice visual representation of different modes&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I thought about that and it can be done without blending. You just need four framebuffers or one with bunch of color attachments. To each of them you render your scene with different viewport enabled. Then in render pass to screen you bind those textures and blend them in more modern way using fragment shader. That's more complex but with more freedom of applying desired results.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.quake-1.com/docs/blending.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10433" PostHistoryTypeId="2" PostId="4518" RevisionGUID="44da0b4d-2314-4f01-8418-fda416bbe3f0" CreationDate="2017-01-11T18:19:27.617" UserId="5835" Text="I have just started learning OpenCV and I am trying to map a texture on a Quad Strip. Basically, I am trying to create a parametric surface and I don't know how to map the coordinates. What can I do? This is what I tried so far and, unfortunately, it doesn't work.&#xD;&#xA;    &#xD;&#xA;    public void draw(GL2 gl, GLU glu, GLUT glut) {&#xD;&#xA;&#xD;&#xA;        Textures.track.enable(gl);&#xD;&#xA;        Textures.track.bind(gl);&#xD;&#xA;&#xD;&#xA;        gl.glEnable(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;        gl.glBegin(GL_QUAD_STRIP);&#xD;&#xA;&#xD;&#xA;        double t = 0.0;&#xD;&#xA;        gl.glColor3f(1f, 1f, 1f);&#xD;&#xA;&#xD;&#xA;        for(int i = 0; i &lt;= 100; i++){&#xD;&#xA;            t = t + 0.01;&#xD;&#xA;            Vector tangent = getTangent(t);&#xD;&#xA;            Vector normal = tangent.cross(Vector.Z);&#xD;&#xA;            Vector centerPoint = getPoint(t);&#xD;&#xA;&#xD;&#xA;            Vector point1 = centerPoint.subtract(normal.scale(w/30));&#xD;&#xA;            Vector point2 = centerPoint.add(normal.scale(w/30));&#xD;&#xA;&#xD;&#xA;            gl.glTexCoord2f((float)t, 0f);&#xD;&#xA;            gl.glVertex3d(point1.x, point1.y, point1.z);&#xD;&#xA;            gl.glTexCoord2f(0f, (float)t);&#xD;&#xA;            gl.glVertex3d(point2.x, point2.y, point2.z);&#xD;&#xA;        }&#xD;&#xA;        gl.glEnd();&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10434" PostHistoryTypeId="1" PostId="4518" RevisionGUID="44da0b4d-2314-4f01-8418-fda416bbe3f0" CreationDate="2017-01-11T18:19:27.617" UserId="5835" Text="Texture mapping on a quad strip" ContentLicense="CC BY-SA 3.0" />
  <row Id="10435" PostHistoryTypeId="3" PostId="4518" RevisionGUID="44da0b4d-2314-4f01-8418-fda416bbe3f0" CreationDate="2017-01-11T18:19:27.617" UserId="5835" Text="|opengl|shader|texture|glsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10437" PostHistoryTypeId="5" PostId="4518" RevisionGUID="8ad44dd7-0947-4aa2-b792-5a585460c64d" CreationDate="2017-01-11T18:48:33.300" UserId="2041" Comment="I assume you mean OpenGL, not OpenCV, since there isn't any OpenCV code in your code snippet, and I've removed the shader and glsl tags since you haven't mentioned any shader." Text="I have just started learning OpenGL and I am trying to map a texture on a Quad Strip. Basically, I am trying to create a parametric surface and I don't know how to map the coordinates. What can I do? This is what I tried so far and, unfortunately, it doesn't work.&#xD;&#xA;    &#xD;&#xA;    public void draw(GL2 gl, GLU glu, GLUT glut) {&#xD;&#xA;&#xD;&#xA;        Textures.track.enable(gl);&#xD;&#xA;        Textures.track.bind(gl);&#xD;&#xA;&#xD;&#xA;        gl.glEnable(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;        gl.glBegin(GL_QUAD_STRIP);&#xD;&#xA;&#xD;&#xA;        double t = 0.0;&#xD;&#xA;        gl.glColor3f(1f, 1f, 1f);&#xD;&#xA;&#xD;&#xA;        for(int i = 0; i &lt;= 100; i++){&#xD;&#xA;            t = t + 0.01;&#xD;&#xA;            Vector tangent = getTangent(t);&#xD;&#xA;            Vector normal = tangent.cross(Vector.Z);&#xD;&#xA;            Vector centerPoint = getPoint(t);&#xD;&#xA;&#xD;&#xA;            Vector point1 = centerPoint.subtract(normal.scale(w/30));&#xD;&#xA;            Vector point2 = centerPoint.add(normal.scale(w/30));&#xD;&#xA;&#xD;&#xA;            gl.glTexCoord2f((float)t, 0f);&#xD;&#xA;            gl.glVertex3d(point1.x, point1.y, point1.z);&#xD;&#xA;            gl.glTexCoord2f(0f, (float)t);&#xD;&#xA;            gl.glVertex3d(point2.x, point2.y, point2.z);&#xD;&#xA;        }&#xD;&#xA;        gl.glEnd();&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10438" PostHistoryTypeId="6" PostId="4518" RevisionGUID="8ad44dd7-0947-4aa2-b792-5a585460c64d" CreationDate="2017-01-11T18:48:33.300" UserId="2041" Comment="I assume you mean OpenGL, not OpenCV, since there isn't any OpenCV code in your code snippet, and I've removed the shader and glsl tags since you haven't mentioned any shader." Text="|opengl|texture|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10439" PostHistoryTypeId="5" PostId="4507" RevisionGUID="3ed0cd1e-c608-4ed6-91fa-58aa312f42c1" CreationDate="2017-01-11T20:12:46.793" UserId="5828" Comment="added 83 characters in body" Text="I have a set of non-convex polygons and I want to merge them. I am able to find the a connection between two polygons. If there are more than two polygons, one connection can intersect another polygon within the set. I do not want to check for a possible intersection. So I have to find the nearest neighbor of a single polygon. Is there an existing algorithm? I can't find anything in my literature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0wGVT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/b1bca.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10440" PostHistoryTypeId="2" PostId="4519" RevisionGUID="3e356b1c-03f8-49f1-90c6-961cca4984d1" CreationDate="2017-01-11T20:33:24.870" UserId="56" Text="In this vein a bit, Killzone renders one bounce reflections, but uses temporal anti aliasing to combine the last frame with the current frame.&#xD;&#xA;&#xD;&#xA;In practice, this means you get MANY bounce reflections, since in effect each frame rendered catches the previous number of reflections as the new reflection - adding one each frame.&#xD;&#xA;&#xD;&#xA;Not quite GI, but i wouldn't be surprised if people pursue that direction more in the future, if they aren't already working on it." ContentLicense="CC BY-SA 3.0" />
  <row Id="10442" PostHistoryTypeId="5" PostId="4519" RevisionGUID="52193529-6452-4dd5-9063-2c7caf0507ac" CreationDate="2017-01-11T20:51:31.777" UserId="56" Comment="added 365 characters in body" Text="In this vein a bit, Killzone renders one bounce reflections, but uses temporal anti aliasing to combine the last frame with the current frame.&#xD;&#xA;&#xD;&#xA;In practice, this means you get MANY bounce reflections, since in effect each frame rendered catches the previous number of reflections as the new reflection - adding one each frame.&#xD;&#xA;&#xD;&#xA;Not quite GI, but i wouldn't be surprised if people pursue that direction more in the future, if they aren't already working on it.&#xD;&#xA;&#xD;&#xA;The temporal anti aliasing used normally lets you get more samples with subsequent frames, but used in this way, it also gives you higher bounce counts with subsequent frames.&#xD;&#xA;&#xD;&#xA;I could totally see doing path tracing type path following, choosing reflection or BSDF rays based on fresnel equations for instance, and having the temporal AA combine it over time." ContentLicense="CC BY-SA 3.0" />
  <row Id="10443" PostHistoryTypeId="5" PostId="4512" RevisionGUID="21c5c7db-824d-4388-abd2-3eef07182f74" CreationDate="2017-01-11T20:55:37.497" UserId="4958" Comment="added 64 characters in body" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc. and each frame everything is calculated anew) to narrow my topic.&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints) &#xD;&#xA; - based on cone tracing of scene voxelization calculated in every frame (Voxel Cone Tracing) &#xD;&#xA;&#xD;&#xA;Each technique is based on grid moving with camera in voxel size increments.&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10444" PostHistoryTypeId="5" PostId="4512" RevisionGUID="4be8d350-618c-43a4-99da-1fbc276a4e4c" CreationDate="2017-01-11T21:04:00.550" UserId="4958" Comment="added 187 characters in body" Text="I'm considering topic of my thesis connected with computer graphics - I would compare some GI techniques which work **completely in real time** (no precomputation to lightmaps etc. and each frame everything is calculated anew) to narrow my topic.&#xD;&#xA;&#xD;&#xA;I plan to compare two kind of techniques:&#xD;&#xA;&#xD;&#xA; - based on RSM sampling heuristics (Radiance Hints) &#xD;&#xA; - based on cone tracing of scene voxelization calculated in every frame (Voxel Cone Tracing) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Each technique is based on grid moving with camera in voxel size increments.&#xD;&#xA;&#xD;&#xA;The key I think is to describe pros and cons of kind of technique in more general way. For example some other techniques are based on RSM sampling. I think two kinds should suffice.&#xD;&#xA;&#xD;&#xA;Is there any other important or popular kind of technique which I should include or I am not aware of?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10446" PostHistoryTypeId="2" PostId="4521" RevisionGUID="8640d57e-805c-44f9-8af1-7510d7b9e604" CreationDate="2017-01-12T09:19:21.363" UserId="5256" Text="**What are some of the challenges of Offline Rendering?** I know one problem that is faced is performance and rendering times, are there any more issues? &#xD;&#xA;&#xD;&#xA;Path Traced photos seem to have reached the point where it is hard to distinguish a CGI image in comparison to a real photo so being able to render a photo-realistic image doesn't really seem like a challenge anymore.&#xD;&#xA;&#xD;&#xA;**Is offline rendering just about refining current techniques to find an improvement in render times now and not so much about photo realism?** &#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ko8BI.jpg&#xD;&#xA;&#xD;&#xA;*(Grand Moff Tarkin in Star Wars: Rogue One was entirely created through CGI since the actual actor had died)*" ContentLicense="CC BY-SA 3.0" />
  <row Id="10447" PostHistoryTypeId="1" PostId="4521" RevisionGUID="8640d57e-805c-44f9-8af1-7510d7b9e604" CreationDate="2017-01-12T09:19:21.363" UserId="5256" Text="Challenges of Offline Rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="10448" PostHistoryTypeId="3" PostId="4521" RevisionGUID="8640d57e-805c-44f9-8af1-7510d7b9e604" CreationDate="2017-01-12T09:19:21.363" UserId="5256" Text="|rendering|raytracing|performance|pathtracing|offline|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10453" PostHistoryTypeId="2" PostId="4523" RevisionGUID="01a22322-99d3-4dc2-b2be-60755ec55429" CreationDate="2017-01-12T12:05:10.333" UserDisplayName="user4718" Text="I've been reading around that matrices (for example, rotation matrices, but not only) can be thought somehow as coordinate systems. &#xD;&#xA;&#xD;&#xA;My question is: how is that possible? &#xD;&#xA;&#xD;&#xA;I've seen for example that if we're using row-major conventions, the rows of the matrices involved in the transformations (specifically I've seen about _rotations_) can be thought as the vectors representing some coordinate system (specifically it should be a _local_ coordinate system).&#xD;&#xA;&#xD;&#xA;Why is this the case? And why specifically a _local coordinate system_? What does it even mean _local coordinate system_ in this context? Are there any other type of matrices, apart from the rotation matrices, which can be thought as coordinate systems? If yes, which ones, and why?&#xD;&#xA;&#xD;&#xA;Matrices usually represent a transformation (linear or not, maybe also affine in computer graphics), but it's new to me to think about matrices as coordinate systems. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10454" PostHistoryTypeId="1" PostId="4523" RevisionGUID="01a22322-99d3-4dc2-b2be-60755ec55429" CreationDate="2017-01-12T12:05:10.333" UserDisplayName="user4718" Text="How is that possible that matrices can be thought as coordinate systems?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10455" PostHistoryTypeId="3" PostId="4523" RevisionGUID="01a22322-99d3-4dc2-b2be-60755ec55429" CreationDate="2017-01-12T12:05:10.333" UserDisplayName="user4718" Text="|transformations|matrix|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10456" PostHistoryTypeId="10" PostId="4518" RevisionGUID="ef6c3dac-745e-44f5-8468-c52f9edd504e" CreationDate="2017-01-12T12:58:14.103" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="10457" PostHistoryTypeId="2" PostId="4524" RevisionGUID="6e269730-d525-43a5-a672-2b859f26f8e2" CreationDate="2017-01-12T14:23:41.867" UserId="5717" Text="A matrix can be used to transform a coordinate system into a new one. More specifically, it can be used to transform the basis vectors of a coordinate system. That's how it defines a new coordinate system. It is of course always in relation to another coordinate system but that is often implicit.&#xD;&#xA;&#xD;&#xA;*local coordinate system* usually means a coordinate system which is specific to only part of your scene. For example, the coordinate system where an object's vertices are defined. Those vertices are then transformed, with a matrix, to some global coordinate system with the rest of the scene. That's why it is said that the matrix defines the local coordinate system, in relation to the global one.&#xD;&#xA;&#xD;&#xA;With that said, there can be a number of other meanings. Texture coordinates are also a form of local coordinate system: a 2D one defined on a surface. It is specific to that surface and it is usually not defined by a transformation matrix." ContentLicense="CC BY-SA 3.0" />
  <row Id="10458" PostHistoryTypeId="2" PostId="4525" RevisionGUID="db6dcd43-7af5-441c-bd59-0a642462cf44" CreationDate="2017-01-12T15:14:50.807" UserId="3332" Text="This is a copy of @narthex's answer, except with only the viewports since that is all you need.  I'm not sure why the frame buffer / blend stuff is included in his answer.&#xD;&#xA;&#xD;&#xA;    //left bottom&#xD;&#xA;    glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right bottom&#xD;&#xA;    glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //left top&#xD;&#xA;    glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right top&#xD;&#xA;    glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, WindowWidth, WindowHeight); //restore default" ContentLicense="CC BY-SA 3.0" />
  <row Id="10459" PostHistoryTypeId="5" PostId="4515" RevisionGUID="1e43e7e2-6d57-4f44-8ad9-393d5ba95dfc" CreationDate="2017-01-12T15:50:49.653" UserId="4958" Comment="deleted 779 characters in body" Text="Rendering to different viewports (parts) of the same screen can be done as follows:&#xD;&#xA;&#xD;&#xA;For example splitting screen into four parts and rendering the same scene four times to each corner with different uniforms and different viewports:&#xD;&#xA;&#xD;&#xA;    bindFramebuffer();&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    scene-&gt;setConstPerFrameUniforms();&#xD;&#xA;&#xD;&#xA;    //left bottom&#xD;&#xA;    glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(1);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right bottom&#xD;&#xA;    glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(2);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //left top&#xD;&#xA;    glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(3);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    //right top&#xD;&#xA;    glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);&#xD;&#xA;    scene-&gt;setVarPerFrameUniforms(4);&#xD;&#xA;    scene-&gt;draw();&#xD;&#xA;&#xD;&#xA;    glViewport(0, 0, WindowWidth, WindowHeight); //restore default&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10462" PostHistoryTypeId="2" PostId="4527" RevisionGUID="bdff2067-8f60-41b8-a2b0-9e1f7d03ddc5" CreationDate="2017-01-12T18:34:20.407" UserId="56" Text="If you have a 3x3 matrix representing some transformation, you will actually have the X,Y,Z vectors of that transformation in the rows or columns (depending on if it's a row major or column major matrix).&#xD;&#xA;&#xD;&#xA;In other words, if you have a 3x3, you can look at it and immediately get the up, right(*), forward vectors (asterisk due to handedness, it could be the left vector).&#xD;&#xA;&#xD;&#xA;This however is much like a vector in that it describes directions but has no position.&#xD;&#xA;&#xD;&#xA;If you have a 4x4 matrix that represents a 3d transform and uses homogeneous coordinates for a translation, you can then use that to get the X,Y,Z orientation vectors, but also can get the translation from the origin.&#xD;&#xA;&#xD;&#xA;Hopefully this is helpful, and not misleading for less common matrix types.  I saw an answer deleted which said similar, so fingers crossed :P" ContentLicense="CC BY-SA 3.0" />
  <row Id="10463" PostHistoryTypeId="5" PostId="4527" RevisionGUID="36438514-0a54-4c3f-a46c-f65ce51fb290" CreationDate="2017-01-12T19:30:49.027" UserId="56" Comment="added 1805 characters in body" Text="If you have a 3x3 matrix representing some transformation, you will actually have the X,Y,Z vectors of that transformation in the rows or columns (depending on if it's a row major or column major matrix).&#xD;&#xA;&#xD;&#xA;In other words, if you have a 3x3, you can look at it and immediately get the up, right(*), forward vectors (asterisk due to handedness, it could be the left vector).&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**3x3 Details:**&#xD;&#xA;&#xD;&#xA;let's say you have a 3x3 matrix $M$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;M_{ij} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,1} &amp; M_{1,2} &amp; M_{1,3} \\&#xD;&#xA;M_{2,1} &amp; M_{2,2} &amp; M_{2,3} \\&#xD;&#xA;M_{3,1} &amp; M_{3,2} &amp; M_{3,3} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Let's see what happens when you multiply that by a vector $\begin{bmatrix}1,0,0 \end{bmatrix}$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,1} &amp; M_{1,2} &amp; M_{1,3} \\&#xD;&#xA;M_{2,1} &amp; M_{2,2} &amp; M_{2,3} \\&#xD;&#xA;M_{3,1} &amp; M_{3,2} &amp; M_{3,3} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;*&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 \\&#xD;&#xA;0 \\&#xD;&#xA;0 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,1} \\&#xD;&#xA;M_{2,1} \\&#xD;&#xA;M_{3,1} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Now let's try vector $\begin{bmatrix}0,1,0\end{bmatrix}$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,1} &amp; M_{1,2} &amp; M_{1,3} \\&#xD;&#xA;M_{2,1} &amp; M_{2,2} &amp; M_{2,3} \\&#xD;&#xA;M_{3,1} &amp; M_{3,2} &amp; M_{3,3} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;*&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 \\&#xD;&#xA;1 \\&#xD;&#xA;0 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,2} \\&#xD;&#xA;M_{2,2} \\&#xD;&#xA;M_{3,2} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And lastly, vector $\begin{bmatrix}0,0,1\end{bmatrix}$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,1} &amp; M_{1,2} &amp; M_{1,3} \\&#xD;&#xA;M_{2,1} &amp; M_{2,2} &amp; M_{2,3} \\&#xD;&#xA;M_{3,1} &amp; M_{3,2} &amp; M_{3,3} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;*&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 \\&#xD;&#xA;0 \\&#xD;&#xA;1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;M_{1,3} \\&#xD;&#xA;M_{2,3} \\&#xD;&#xA;M_{3,3} \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;This shows that whatever matrix $M$ is, the first column is the X axis vector of the coordinate space defined by the matrix.  The second column is the Y axis vector, and the third column is the Z axis vector.&#xD;&#xA;&#xD;&#xA;These vectors are in global space.&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;M =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;X_x &amp; Y_x &amp; Z_x \\&#xD;&#xA;X_y &amp; Y_y &amp; Z_y \\&#xD;&#xA;X_z &amp; Y_z &amp; Z_z \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;You can even see that this is true in an identity matrix, where the X,Y and Z vectors are just what you'd expect them to be:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;M =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A 3x3 matrix is much like a vector in that it describes directions but has no position.&#xD;&#xA;&#xD;&#xA;If you have a 4x4 matrix that represents a 3d transform and uses homogeneous coordinates for a translation, you can then use that to get the X,Y,Z orientation vectors, but also can get the translation from the origin.&#xD;&#xA;&#xD;&#xA;Hopefully this is helpful, and not misleading for less common matrix types.  I saw an answer deleted which said similar, so fingers crossed :P" ContentLicense="CC BY-SA 3.0" />
  <row Id="10464" PostHistoryTypeId="2" PostId="4528" RevisionGUID="eef83bda-0ccd-4e33-8bc2-62e0e1b79e60" CreationDate="2017-01-12T19:51:33.987" UserId="56" Text="I have a [Shadertoy][1] which renders the image below using ray tracing.&#xD;&#xA;&#xD;&#xA;I'd like to add caustics, but am aware that in general they are a hard solution, especially without bidirectional ray tracing or photon mapping.&#xD;&#xA;&#xD;&#xA;Does anyone know if there is a way to analytically calculate caustics, or at least some of the caustics (or plausible caustic effects) in a situation like this?&#xD;&#xA;&#xD;&#xA;There is refraction going on here, not just transparency, in case that makes a difference.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/4tyXDR &quot;Shadertoy&quot;&#xD;&#xA;  [2]: https://i.stack.imgur.com/YtQBB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10465" PostHistoryTypeId="1" PostId="4528" RevisionGUID="eef83bda-0ccd-4e33-8bc2-62e0e1b79e60" CreationDate="2017-01-12T19:51:33.987" UserId="56" Text="Is there a way to do sphere caustics analytically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10466" PostHistoryTypeId="3" PostId="4528" RevisionGUID="eef83bda-0ccd-4e33-8bc2-62e0e1b79e60" CreationDate="2017-01-12T19:51:33.987" UserId="56" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10467" PostHistoryTypeId="2" PostId="4529" RevisionGUID="888e076f-e0e8-49fb-a2db-0e00f15975b2" CreationDate="2017-01-12T20:30:57.713" UserId="506" Text="You might find [this paper](http://graphics.cs.williams.edu/papers/TransparencyI3D16/) useful—its authors describe a way to make reasonably plausible caustic effects just by modulating their shadows with the surface normal and refractive index. It won’t get you the more complex/interesting hot-spot shapes that you’d get with photon mapping, but it could work well depending on your scene.&#xD;&#xA;&#xD;&#xA;![sample fake caustics](https://i.stack.imgur.com/91pVo.jpg)&#xD;&#xA;&#xD;&#xA;&gt; To extend stochastic shadow maps to mimic caustics, we decrease shadowing where light strikes a transmissive surface at normal incidence. We increase shadowing where the refractor is at a glancing angle and thus has a low Fresnel transmission factor.&#xD;&#xA;Specifically, during shadow map rendering, we increase ρ(λ) where the magnitude of the dot product of the surface normal nˆ and the vector to the light ωˆi is close to 1, and decrease ρ(λ) where the dot product is close to zero. We also increase this effect with the relative refractive index η." ContentLicense="CC BY-SA 3.0" />
  <row Id="10468" PostHistoryTypeId="5" PostId="4507" RevisionGUID="df64634f-09ba-458d-9bfd-6fafbe61f9f4" CreationDate="2017-01-13T02:59:20.857" UserId="5828" Comment="deleted 2 characters in body; edited title" Text="I have a set of non-convex polygons and I want to merge them. I am able to find the connection between two polygons. If there are more than two polygons, one connection can intersect another polygon within the set. I do not want to check for a possible intersection. So I have to find the nearest neighbor of a single polygon. Is there an existing algorithm? I can't find anything in my literature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0wGVT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/b1bca.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10469" PostHistoryTypeId="4" PostId="4507" RevisionGUID="df64634f-09ba-458d-9bfd-6fafbe61f9f4" CreationDate="2017-01-13T02:59:20.857" UserId="5828" Comment="deleted 2 characters in body; edited title" Text="Finding the nearest neighbor of polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="10471" PostHistoryTypeId="2" PostId="4530" RevisionGUID="6cbc9414-3e90-4be9-a08b-8d9a8d15c4aa" CreationDate="2017-01-13T06:18:55.530" UserId="3073" Text="A basic nearest neighbour scale function would work like so. Here I also use 24:8 fixed point arithmetic to make it more micro friendly. &#xD;&#xA;&#xD;&#xA;    const int originalWidth = 320, originalHeight = 240;&#xD;&#xA;    int targetWidth = 50, targetHeight = 50;&#xD;&#xA;&#xD;&#xA;    char *pSource = sourceBuffer; &#xD;&#xA;    char *pDest = destBuffer;    // you can use RGB instead of char&#xD;&#xA;&#xD;&#xA;    int yStep = (originalWidth &lt;&lt; 8) / targetWidth;&#xD;&#xA;    int xStep = (originalHeight &lt;&lt; 8) / targetHeight;&#xD;&#xA;&#xD;&#xA;    for(int y = 0, sampleY = 0; y &lt; targetHeight; y++, sampleY += yStep) {&#xD;&#xA;        // Point to start of scaled Y source line&#xD;&#xA;        char *pSourceLine = pSource + ((sampleY &gt;&gt; 8) * originalWidth);&#xD;&#xA;&#xD;&#xA;        // Output the line, scaling only in X (we already know scaled-Y)&#xD;&#xA;        for(int x = 0, sampleX = 0; x &lt; targetWidth; x++, sampleX += xStep)&#xD;&#xA;            *pDest++ = pSourceLine[sampleX &gt;&gt; 8];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This will also work to scale image up as well as down, it should work on any input vs output size." ContentLicense="CC BY-SA 3.0" />
  <row Id="10472" PostHistoryTypeId="2" PostId="4531" RevisionGUID="1e0ad6f4-9a1c-439f-9030-1a44a596f547" CreationDate="2017-01-13T12:37:08.923" UserId="5399" Text="If you are writing your own Vertex/Fragment Shader there is another additional possibility to do this. It is much more complicated but might be useful for you and/or others. Additionally it speeds up the whole drawing process since it uses only one call to a draw command. The maximum number of Viewports is defined by GL_MAX_VIEWPORTS and is usually 16. &#xD;&#xA;&#xD;&#xA;Since OpenGL 4.1 the method [glViewportArrayv][1] exists. It can define an array of Viewports. The Viewports which are created by this method have an index assigned. &#xD;&#xA;&#xD;&#xA;This index can be used in the Vertex Shader to set the Viewport to which the scene is rendered. &#xD;&#xA;&#xD;&#xA;In your case I would suggest to do the following:&#xD;&#xA;&#xD;&#xA;- Store the 4 camera matrices in a Shader Storage Buffer (Array of mat4) to have them in the Vertex Shader&#xD;&#xA;- Use [indexed drawing][2], for example :[glDrawElementsInstanced][3]&#xD;&#xA;- use the build in [gl_InstanceID][4] of the Vertex Shader to access the camera matrix array&#xD;&#xA;- set the build in variable output variable gl_ViewportIndex in the Fragment Shader to the gl_InstanceID. (for details see [ARB_fragment_layer_viewport][5])&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man4/html/glViewportArray.xhtml&#xD;&#xA;  [2]: https://learnopengl.com/#!Advanced-OpenGL/Instancing&#xD;&#xA;  [3]: https://www.opengl.org/sdk/docs/man/html/glDrawElementsInstanced.xhtml&#xD;&#xA;  [4]: https://www.opengl.org/sdk/docs/man/html/gl_InstanceID.xhtml&#xD;&#xA;  [5]: https://www.opengl.org/registry/specs/ARB/fragment_layer_viewport.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="10473" PostHistoryTypeId="2" PostId="4532" RevisionGUID="a651f4c7-439c-471c-a7e7-d912b4e35570" CreationDate="2017-01-13T12:41:15.877" UserDisplayName="user4718" Text="After asking [this](http://computergraphics.stackexchange.com/questions/4523/how-is-that-possible-that-matrices-can-be-thought-as-coordinate-systems) question, a few new terms that I had never heard of came up. Note, I'm quite familiar with linear algebra, but I've never heard these terms in the context of linear algebra. &#xD;&#xA;&#xD;&#xA;Comments like &#xD;&#xA;&#xD;&#xA;&gt; In my example, you can use the columns to get the basis vectors of the coordinate system it describes. _The columns are in the coordinate system of whatever the **parent coordinate system** is. If there is no parent coordinate system, they are in global space. Else, they are in the coordinate system of the parent._&#xD;&#xA;&#xD;&#xA;What's a parent coordinate system? When is this term used? Why is it called a parent coordinate system?&#xD;&#xA;&#xD;&#xA;Then the author of the comment tries to explain me the meaning as follows:&#xD;&#xA;&#xD;&#xA;&gt; Matrices can be parented off of each other, but that is probably too confusing to visualize as you are just trying to learn things. Just imagine that if there was a matrix hierarchy, that all the matrices are multiplied together into one matrix M then you can ignore hierarchies.&#xD;&#xA;&#xD;&#xA;This hasn't really cleared things up. What is it mean that _matrices can be parented off of each other_? What is it meant by _matrix hierarchy_? &#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;I know that if you have $m$ $A_1, A_2, \cdots, A_m \in \mathbb{R}^{n \times n}$ matrices which represent transformations, any combination of products of these matrices represents clearly a new transformation. For example, say that $A_1 * A_2 = B_{12}$. Suppose now that we have a vector $v \in \mathbb{R}^{n \times 1}$. Then the following two statements should clearly be equivalent&#xD;&#xA;&#xD;&#xA;$$A_1 * A_2 * v$$&#xD;&#xA;&#xD;&#xA;and &#xD;&#xA;&#xD;&#xA;$$B_{12} * v$$&#xD;&#xA;&#xD;&#xA;but the transformations used are different, i.e., in one case we use two single transformations (i.e., $A_1$ and $A_2$) and in the other case we use only one transformation, namely $B_{12}$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I don't know if this has something to do with &quot;parent coordinate systems&quot;, but I just wanted to show you a few things that I'm suspecting could be related to this terminology and concepts of computer graphics.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Final question would be: does it make sense to talk just about &quot;parent _coodinate systems_&quot; or does it also make sense to talk about &quot;parent vector spaces&quot;? Why?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10474" PostHistoryTypeId="1" PostId="4532" RevisionGUID="a651f4c7-439c-471c-a7e7-d912b4e35570" CreationDate="2017-01-13T12:41:15.877" UserDisplayName="user4718" Text="What's a parent vector space or coordinate system?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10475" PostHistoryTypeId="3" PostId="4532" RevisionGUID="a651f4c7-439c-471c-a7e7-d912b4e35570" CreationDate="2017-01-13T12:41:15.877" UserDisplayName="user4718" Text="|transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10477" PostHistoryTypeId="2" PostId="4533" RevisionGUID="0dc96ee7-de20-4e6a-b938-cdde473563d8" CreationDate="2017-01-13T14:48:55.407" UserId="209" Text="***&quot;Downscaling by skipping rows and columns – any example images?&quot;***&#xD;&#xA;&#xD;&#xA;You asked for example images: The following is a sequence of 50 frames from a well known (and hopefully freely available) sequence subsampled as you suggested.&#xD;&#xA;&#xD;&#xA;I think you might find simply subsampling to be a bit too noisy. Are you sure you can't at least do box filtering?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AZjl1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10478" PostHistoryTypeId="5" PostId="4533" RevisionGUID="ddb96394-7f3a-4809-bf6a-d01a594e1cac" CreationDate="2017-01-13T15:40:26.613" UserId="209" Comment="added 21 characters in body" Text="***&quot;Downscaling by skipping rows and columns – any example images?&quot;***&#xD;&#xA;&#xD;&#xA;You asked for example images: The following is a sequence of 50 frames from a well known (and hopefully freely available) sequence, subsampled as you suggested.&#xD;&#xA;&#xD;&#xA;I think you might find simply subsampling/decimating to be a bit too noisy. &#xD;&#xA;&#xD;&#xA;Are you sure you can't at least do some box filtering?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AZjl1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10479" PostHistoryTypeId="2" PostId="4534" RevisionGUID="269d11fb-22a8-4352-940a-79fff07bd642" CreationDate="2017-01-13T15:47:09.850" UserId="38" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathemathics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathemathics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because its easier to think in one orientation or just simply because you want to move/rotate/scale objecs out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minumum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straoght ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. Preferably automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other. &#xD;&#xA;&#xD;&#xA;Altough this could be done in any number of ways it is commonly done with a tree structure using affine matrices. Mainly because this takes care of 2 issues. A the tree structure is easy to traverse and find the path to any other part in the hierarchy and matrices being appendable to form a compound transform independent of geometry calculation for each point in a object.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to tranform the object to its parents coordinates, which in turn describes the tranform to its parent all the way to the world. Since all objects share one common ancestor we can easily traverse the tree to find a transform from any one space to another sibce te inverse transform and multiply them together. Whenever we travel in the oppsite direction away from the world we simply use the inverse transform of the stored transform. &#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why. You should understand also that we do not have any limit to complexity of the hierarchy to facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This hierarchy is called a scene graph and such things can be found in webpages, vector and cad applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because its a tree, and earliest tree graphs are genealogical stidies, or family trees. Where the previous level is simply the parents and the next ome is their children.&#xD;&#xA;&#xD;&#xA;PS: Written on my  phone at afterwork beer waiting for my coworkers to arrive so maybe i will still improve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10481" PostHistoryTypeId="5" PostId="4511" RevisionGUID="3265e926-14a8-46de-9cfd-b96634fdf215" CreationDate="2017-01-13T17:47:26.793" UserId="5832" Comment="edited body" Text="I'm about to implement downscaling on a microcontroller. Source resolution is e.g. 720x576 (the 576i PAL resolution, other one possible: 480i, NTSC resolution), destination is 32x16. The goal is to have RGB LED matrix (of size 32x16) flowing with various colors, shapes, shadows, etc. – a half-abstract vs. half-meaningful effect, driven by a prepared PAL or NTSC video.&#xD;&#xA;&#xD;&#xA;I will only be able to select every 22th pixel (720 / 36) and every 36th line (576 / 16) – the microcontroller will not be able to compute averages of groups of pixels etc. This way I will obtain 32x16 downscaled image to output to the LED matrix.&#xD;&#xA;&#xD;&#xA;I cannot find any examples of how such downscaling will behave. Tried searching for &quot;decimation&quot; but no luck. Which program can I use to test this downscaling? Can I quickly code this somehow – if I would to code this, I would use libSDL1, generate set of files, but this is difficult (e.g. image loading). Maybe some snippet-solution is possible? Should I care about Nyquist frequency?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10482" PostHistoryTypeId="2" PostId="4535" RevisionGUID="527cec00-4c11-40b3-8ade-15fe50ab60eb" CreationDate="2017-01-13T18:44:07.243" UserId="5841" Text="I need to implement translation, scaling and rotation gizmos and I'm having trouble with the rotation gizmo. Basically I don't know how to translate the mouse movement to determine in which direction to rotate the object.&#xD;&#xA; &#xD;&#xA;For the translation and scaling gizmos, which are represented as 3 axes, I do the following: I make a vector of the difference between the previous and current mouse position in screen space. Then multiply this vector by the inverse of the view and projection matrices, which gives me a vector of the mouse movement in world space. Then I take the dot product of the vector in world space with the  selected axis. This allows me determine if the mouse movement is in line with the axis or away from the axis. &#xD;&#xA; &#xD;&#xA;But I can't do the same thing for the rotation gizmo. The rotation gizmo is represented as 3 circles, each representing a rotation around an axis. Once a circle is clicked, I need to find some way to translate the mouse movement to determine which direction to rotate the object around the selected axis. I don't know how to do this. Please help.&#xD;&#xA; &#xD;&#xA;It is important to note that I am using color picking and not raycasting to determine where the gizmo was clicked. This means that I don't have the point at which the ray hits the gizmo in world space to start from. I mention this because I've looked at examples that use raycasting like libgizmo and I don't think I can do the same thing.&#xD;&#xA; &#xD;&#xA;Thanks in advance for any help." ContentLicense="CC BY-SA 3.0" />
  <row Id="10483" PostHistoryTypeId="1" PostId="4535" RevisionGUID="527cec00-4c11-40b3-8ade-15fe50ab60eb" CreationDate="2017-01-13T18:44:07.243" UserId="5841" Text="How to translate mouse movement to a rotation gizmo?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10484" PostHistoryTypeId="3" PostId="4535" RevisionGUID="527cec00-4c11-40b3-8ade-15fe50ab60eb" CreationDate="2017-01-13T18:44:07.243" UserId="5841" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10485" PostHistoryTypeId="5" PostId="4535" RevisionGUID="950c805e-70f2-43f0-9f78-ffd394041d39" CreationDate="2017-01-13T18:55:57.740" UserId="56" Comment="added 154 characters in body" Text="I need to implement translation, scaling and rotation gizmos and I'm having trouble with the rotation gizmo. Basically I don't know how to translate the mouse movement to determine in which direction to rotate the object.&#xD;&#xA;&#xD;&#xA;By rotation gizmo (widget) I mean something like the below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA;For the translation and scaling gizmos, which are represented as 3 axes, I do the following: I make a vector of the difference between the previous and current mouse position in screen space. Then multiply this vector by the inverse of the view and projection matrices, which gives me a vector of the mouse movement in world space. Then I take the dot product of the vector in world space with the  selected axis. This allows me determine if the mouse movement is in line with the axis or away from the axis. &#xD;&#xA; &#xD;&#xA;But I can't do the same thing for the rotation gizmo. The rotation gizmo is represented as 3 circles, each representing a rotation around an axis. Once a circle is clicked, I need to find some way to translate the mouse movement to determine which direction to rotate the object around the selected axis. I don't know how to do this. Please help.&#xD;&#xA; &#xD;&#xA;It is important to note that I am using color picking and not raycasting to determine where the gizmo was clicked. This means that I don't have the point at which the ray hits the gizmo in world space to start from. I mention this because I've looked at examples that use raycasting like libgizmo and I don't think I can do the same thing.&#xD;&#xA; &#xD;&#xA;Thanks in advance for any help.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LVQ2Y.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10486" PostHistoryTypeId="2" PostId="4536" RevisionGUID="86f80327-475b-4fe4-b230-ab7fe0220d33" CreationDate="2017-01-13T18:59:18.583" UserId="56" Text="From the presentations on non real time rendering I've seen at SIGGRAPH, the answer is basically yes, a lot of time is spent making render times faster.  For instance, even with huge amounts of ram, the amount of data needed to render a scene is larger than can fit in memory all at once, so strategies are developed to minimized disk access during the render process since it is so slow.&#xD;&#xA;&#xD;&#xA;However, I have also seen a lot of effort and research put into simulations - such as realistic foamy ocean tidal wave simulations.&#xD;&#xA;&#xD;&#xA;I guess once the rendering is realistic, the next things to work on is the simulation that is being rendered." ContentLicense="CC BY-SA 3.0" />
  <row Id="10487" PostHistoryTypeId="2" PostId="4537" RevisionGUID="caf6c564-15b6-46b9-9700-928e84323346" CreationDate="2017-01-13T19:16:40.717" UserId="5843" Text="I've seen the term `st` come up a few times when looking at other OpenGL fragment shaders. However, I don't know what it stands for or what it's used for. Here's an example:&#xD;&#xA;&#xD;&#xA;    uniform vec2 u_resolution;&#xD;&#xA;&#xD;&#xA;    vec2 st = gl_FragCoord.xy/u_resolution;&#xD;&#xA;&#xD;&#xA;I can understand that this is converting the pixel coordinates into normalized coordinates of 0.0 - 1.0 instead of 640 x 480 (for example).&#xD;&#xA;&#xD;&#xA;I've also seen things like `position.st`.&#xD;&#xA;&#xD;&#xA;What does it mean?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10488" PostHistoryTypeId="1" PostId="4537" RevisionGUID="caf6c564-15b6-46b9-9700-928e84323346" CreationDate="2017-01-13T19:16:40.717" UserId="5843" Text="What does &quot;st&quot; mean in the context of OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10489" PostHistoryTypeId="3" PostId="4537" RevisionGUID="caf6c564-15b6-46b9-9700-928e84323346" CreationDate="2017-01-13T19:16:40.717" UserId="5843" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10490" PostHistoryTypeId="2" PostId="4538" RevisionGUID="eb9d7844-bb21-42e9-8ba3-285085b90f45" CreationDate="2017-01-13T19:19:47.913" UserDisplayName="user4718" Text="I've been reading some code which setups a ray tracer and I've realized I've a doubt regarding what's a screen and what's a window in this context. Here's the relevant code using Qt:&#xD;&#xA;&#xD;&#xA;    void CCanvas::paint()&#xD;&#xA;    {&#xD;&#xA;      // check if we have something to draw on&#xD;&#xA;      if (!image) return;&#xD;&#xA;      &#xD;&#xA;      // camera position&#xD;&#xA;      Point3d camera (0.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // screen resolution&#xD;&#xA;      int w = image-&gt;width();&#xD;&#xA;      int h = image-&gt;height();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;      // horizontal opening angle&#xD;&#xA;      double alpha = PI/2.0;&#xD;&#xA;    &#xD;&#xA;      // horizontal window dimension [-X,X]&#xD;&#xA;      double X = tan(alpha/2.0);&#xD;&#xA;    &#xD;&#xA;      // pixel size&#xD;&#xA;      double s = 2.0 * X / (double)w;&#xD;&#xA;    &#xD;&#xA;      // vertical window dimension [-Y,Y]&#xD;&#xA;      double Y = s * h / 2.0;&#xD;&#xA;      ...&#xD;&#xA;&#xD;&#xA;I think I know what's the screen resolution: if we think of the screen as a matrix, `w` and `h` would be respectively the number of columns and rows in this &quot;matrix&quot;.&#xD;&#xA;&#xD;&#xA;After obtaining the resolution of the image, we define an opening angle $\alpha$. I interpreted this opening angle as the opening angle of the camera, i.e., it defines basically what's visible from the camera.&#xD;&#xA;&#xD;&#xA;Then we compute `X`, which is half of the horizontal window (according to the comments in the code). &#xD;&#xA;&#xD;&#xA;Now, mathematically I understood these calculations, _what I don't understand is the difference between $2X$ and $w$_. Is the &quot;window&quot; here the same thing as &quot;screen&quot;? &#xD;&#xA;&#xD;&#xA;I've this picture here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;which makes me think that $X$ is half of the width of the window.  If the window is the same thing as the screen, I wonder why do we need $w$? I mean, couldn't we just decide how many rows and columns could we have in the screen? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GOwkb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10491" PostHistoryTypeId="1" PostId="4538" RevisionGUID="eb9d7844-bb21-42e9-8ba3-285085b90f45" CreationDate="2017-01-13T19:19:47.913" UserDisplayName="user4718" Text="Is there a difference between window and screen in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10492" PostHistoryTypeId="3" PostId="4538" RevisionGUID="eb9d7844-bb21-42e9-8ba3-285085b90f45" CreationDate="2017-01-13T19:19:47.913" UserDisplayName="user4718" Text="|raytracing|c++|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10493" PostHistoryTypeId="5" PostId="4538" RevisionGUID="15cb388a-b79e-416e-b4bc-5e0016bf11f6" CreationDate="2017-01-13T19:25:35.427" UserDisplayName="user4718" Comment="added 83 characters in body" Text="I've been reading some code which setups a ray tracer and I've realized I've a doubt regarding what's a screen and what's a window in this context. Here's the relevant code using Qt:&#xD;&#xA;&#xD;&#xA;    void CCanvas::paint()&#xD;&#xA;    {&#xD;&#xA;      // check if we have something to draw on&#xD;&#xA;      if (!image) return;&#xD;&#xA;      &#xD;&#xA;      // camera position&#xD;&#xA;      Point3d camera (0.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // screen resolution&#xD;&#xA;      int w = image-&gt;width();&#xD;&#xA;      int h = image-&gt;height();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;      // horizontal opening angle&#xD;&#xA;      double alpha = PI/2.0;&#xD;&#xA;    &#xD;&#xA;      // horizontal window dimension [-X,X]&#xD;&#xA;      double X = tan(alpha/2.0);&#xD;&#xA;    &#xD;&#xA;      // pixel size&#xD;&#xA;      double s = 2.0 * X / (double)w;&#xD;&#xA;    &#xD;&#xA;      // vertical window dimension [-Y,Y]&#xD;&#xA;      double Y = s * h / 2.0;&#xD;&#xA;      ...&#xD;&#xA;&#xD;&#xA;I think I know what's the screen resolution: if we think of the screen as a matrix, `w` and `h` would be respectively the number of columns and rows in this &quot;matrix&quot;.&#xD;&#xA;&#xD;&#xA;After obtaining the resolution of the image, we define an opening angle $\alpha$. I interpreted this opening angle as the opening angle of the camera, i.e., it defines basically what's visible from the camera.&#xD;&#xA;&#xD;&#xA;Then we compute `X`, which is half of the horizontal window (according to the comments in the code). (**_Note this `X` is not the same X representing the x axis in the picture below.** Yes, whoever wrote this code had no common sense!_) &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Now, mathematically I understood these calculations, _what I don't understand is the difference between $2X$ and $w$_. &#xD;&#xA;&#xD;&#xA;Is the &quot;window&quot; here the same thing as &quot;screen&quot;? &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I've this picture here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;which makes me think that $X$ is half of the width of the window.  &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If the window is the same thing as the screen, I wonder why do we need $w$. I mean, couldn't we just decide how many rows and columns we have in the visible area?  &#xD;&#xA;&#xD;&#xA;Again, it's not clear if the visible area of the camera is the same thing as the screen or window...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GOwkb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10494" PostHistoryTypeId="5" PostId="4538" RevisionGUID="814d5620-a8db-493c-a2aa-62a954ac0297" CreationDate="2017-01-13T19:39:07.513" UserDisplayName="user4718" Comment="added 13 characters in body" Text="I've been reading some code which setups a ray tracer and I've realized I've a doubt regarding what's a screen and what's a window in this context. Here's the relevant code using Qt:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    void CCanvas::paint()&#xD;&#xA;    {&#xD;&#xA;      // check if we have something to draw on&#xD;&#xA;      if (!image) return;&#xD;&#xA;      &#xD;&#xA;      // camera position&#xD;&#xA;      Point3d camera (0.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // screen resolution&#xD;&#xA;      int w = image-&gt;width();&#xD;&#xA;      int h = image-&gt;height();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;      // horizontal opening angle&#xD;&#xA;      double alpha = PI/2.0;&#xD;&#xA;    &#xD;&#xA;      // horizontal window dimension [-X,X]&#xD;&#xA;      double X = tan(alpha/2.0);&#xD;&#xA;    &#xD;&#xA;      // pixel size&#xD;&#xA;      double s = 2.0 * X / (double)w;&#xD;&#xA;    &#xD;&#xA;      // vertical window dimension [-Y,Y]&#xD;&#xA;      double Y = s * h / 2.0;&#xD;&#xA;      ...&#xD;&#xA;&#xD;&#xA;I think I know what's the screen resolution: if we think of the screen as a matrix, `w` and `h` would be respectively the number of columns and rows in this &quot;matrix&quot;.&#xD;&#xA;&#xD;&#xA;After obtaining the resolution of the image, we define an opening angle $\alpha$. I interpreted this opening angle as the opening angle of the camera, i.e., it defines basically what's visible from the camera.&#xD;&#xA;&#xD;&#xA;Then we compute `X`, which is half of the horizontal window (according to the comments in the code). (**_Note this `X` is not the same X representing the x axis in the picture below.** Yes, whoever wrote this code had no common sense!_) &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Now, mathematically I understood these calculations, _what I don't understand is the difference between $2X$ and $w$_. &#xD;&#xA;&#xD;&#xA;Is the &quot;window&quot; here the same thing as &quot;screen&quot;? &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I've this picture here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;which makes me think that $X$ is half of the width of the window.  &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If the window is the same thing as the screen, I wonder why do we need $w$. I mean, couldn't we just decide how many rows and columns we have in the visible area?  &#xD;&#xA;&#xD;&#xA;Again, it's not clear if the visible area of the camera is the same thing as the screen or window...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GOwkb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10495" PostHistoryTypeId="2" PostId="4539" RevisionGUID="36a4c4a2-1160-4713-9333-d74273843662" CreationDate="2017-01-13T19:41:42.197" UserId="2654" Text="The common names for the components of texture coordinates are U and V. However, because the next letter used (for 3D textures) is W, that causes a conflict with the names for the components of a *position*: X, Y, Z, and **W**.&#xD;&#xA;&#xD;&#xA;To avoid such conflicts, OpenGL's convention is that the components of texture coordinates are named S, T, and R. Thus, you have function calls like this:&#xD;&#xA;&#xD;&#xA;glTexParameter(..., GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;&#xD;&#xA;Where `GL_TEXTURE_WRAP_S` refers to wrapping in the S component of the texture coordinate.&#xD;&#xA;&#xD;&#xA;Unfortunately, OpenGL picked S, T, and R long before GLSL and [swizzle masks][1] came around. R, of course, conflicts with **R**, G, B, and A. To avoid such conflicts, in GLSL, the texture coordinate swizzle mask uses S, T, **P**, and Q.&#xD;&#xA;&#xD;&#xA;In GLSL, you can swizzle with XYZW, STPQ, or RGBA. They all mean exactly the same thing. So `position.st` is exactly the same as `position.xy`. However, you're not allowed to combine swizzle masks from different sets. So `position.xt` is not allowed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Swizzling" ContentLicense="CC BY-SA 3.0" />
  <row Id="10497" PostHistoryTypeId="5" PostId="4538" RevisionGUID="d9752f34-b288-4956-b380-6e3de649dd4f" CreationDate="2017-01-13T22:09:35.867" UserDisplayName="user4718" Comment="edited body" Text="I've been reading some code which setups a ray tracer and I've realized I've a doubt regarding what's a screen and what's a window in this context. Here's the relevant code using Qt:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    void CCanvas::paint()&#xD;&#xA;    {&#xD;&#xA;      // check if we have something to draw on&#xD;&#xA;      if (!image) return;&#xD;&#xA;      &#xD;&#xA;      // camera position&#xD;&#xA;      Point3d camera (0.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;      // screen resolution&#xD;&#xA;      int w = image-&gt;width();&#xD;&#xA;      int h = image-&gt;height();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;      // horizontal opening angle&#xD;&#xA;      double alpha = PI/2.0;&#xD;&#xA;    &#xD;&#xA;      // horizontal window dimension [-X,X]&#xD;&#xA;      double X = tan(alpha/2.0);&#xD;&#xA;    &#xD;&#xA;      // pixel size&#xD;&#xA;      double s = 2.0 * X / (double)w;&#xD;&#xA;    &#xD;&#xA;      // vertical window dimension [-Y,Y]&#xD;&#xA;      double Y = s * h / 2.0;&#xD;&#xA;      ...&#xD;&#xA;&#xD;&#xA;I think I know what's the screen resolution: if we think of the screen as a matrix, `w` and `h` would be respectively the number of columns and rows in this &quot;matrix&quot;.&#xD;&#xA;&#xD;&#xA;After obtaining the resolution of the image, we define an opening angle $\alpha$. I interpreted this opening angle as the opening angle of the camera, i.e., it defines basically what's visible from the camera.&#xD;&#xA;&#xD;&#xA;Then we compute `X`, which is half of the horizontal window (according to the comments in the code). (**_Note this `X` is not the same X representing the x axis in the picture below.** Yes, whoever wrote this code had no common sense!_) &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Now, mathematically I understood these calculations, _what I don't understand is the difference between $2X$ and $w$_. &#xD;&#xA;&#xD;&#xA;Is the &quot;window&quot; here the same thing as &quot;screen&quot;? &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I've this picture here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've added the $X=\tan \left( \frac{\alpha}{2}\right)$ to the picture according to what I think $X$ is from the code above.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If the window is the same thing as the screen, I wonder why do we need $w$. I mean, couldn't we just decide how many rows and columns we have in the visible area?  &#xD;&#xA;&#xD;&#xA;Again, it's not clear if the visible area of the camera is the same thing as the screen or window...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/H9Ye3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10500" PostHistoryTypeId="5" PostId="4539" RevisionGUID="b9170230-00da-4ae3-835e-3cc4a5bd0d47" CreationDate="2017-01-14T00:12:14.447" UserId="2654" Comment="added 4 characters in body" Text="The common names for the components of texture coordinates are U and V. However, because the next letter used (for 3D textures) is W, that causes a conflict with the names for the components of a *position*: X, Y, Z, and **W**.&#xD;&#xA;&#xD;&#xA;To avoid such conflicts, OpenGL's convention is that the components of texture coordinates are named S, T, and R. Thus, you have function calls like this:&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;&#xD;&#xA;Where `GL_TEXTURE_WRAP_S` refers to wrapping in the S component of the texture coordinate.&#xD;&#xA;&#xD;&#xA;Unfortunately, OpenGL picked S, T, and R long before GLSL and [swizzle masks][1] came around. R, of course, conflicts with **R**, G, B, and A. To avoid such conflicts, in GLSL, the texture coordinate swizzle mask uses S, T, **P**, and Q.&#xD;&#xA;&#xD;&#xA;In GLSL, you can swizzle with XYZW, STPQ, or RGBA. They all mean exactly the same thing. So `position.st` is exactly the same as `position.xy`. However, you're not allowed to combine swizzle masks from different sets. So `position.xt` is not allowed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Swizzling" ContentLicense="CC BY-SA 3.0" />
  <row Id="10501" PostHistoryTypeId="2" PostId="4540" RevisionGUID="bbf7a429-9801-4547-8a07-937baf3f4e4b" CreationDate="2017-01-14T01:14:23.337" UserId="56" Text="In the paper [Real-time Reflection using Ray Tracing with Geometry Field&#xD;&#xA;][1], it mentions this:&#xD;&#xA;&#xD;&#xA;&gt; A ray is represented&#xD;&#xA;by its two intersection points (in,out) with the bounding box&#xD;&#xA;of the surface. Hence, the geometry field is a 4 dimensional&#xD;&#xA;function.&#xD;&#xA;&#xD;&#xA;Having two $3D$ points gives 6 values: $A=(A_x,A_y,A_z), B = (B_x, B_y, B_z)$.&#xD;&#xA;&#xD;&#xA;How is it that those 6 values, which are on the surface of a unit cube, can be represented with only 4 numbers?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www3.cs.stonybrook.edu/~mueller/papers/EG06_geomfield.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10502" PostHistoryTypeId="1" PostId="4540" RevisionGUID="bbf7a429-9801-4547-8a07-937baf3f4e4b" CreationDate="2017-01-14T01:14:23.337" UserId="56" Text="Enter/Exit of unit cube representable as 4 numbers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10503" PostHistoryTypeId="3" PostId="4540" RevisionGUID="bbf7a429-9801-4547-8a07-937baf3f4e4b" CreationDate="2017-01-14T01:14:23.337" UserId="56" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10504" PostHistoryTypeId="5" PostId="4540" RevisionGUID="22646cd4-d62d-4e5b-b97d-8b0bea0b148d" CreationDate="2017-01-14T02:14:35.530" UserId="56" Comment="added 266 characters in body; added 4 characters in body" Text="In the paper [Real-time Reflection using Ray Tracing with Geometry Field&#xD;&#xA;][1], it mentions this:&#xD;&#xA;&#xD;&#xA;&gt; A ray is represented&#xD;&#xA;by its two intersection points (in,out) with the bounding box&#xD;&#xA;of the surface. Hence, the geometry field is a 4 dimensional&#xD;&#xA;function.&#xD;&#xA;&#xD;&#xA;Having two $3D$ points gives 6 values: $A=(A_x,A_y,A_z), B = (B_x, B_y, B_z)$.&#xD;&#xA;&#xD;&#xA;How is it that those 6 values, which are on the surface of a unit cube, can be represented with only 4 numbers?&#xD;&#xA;&#xA;Edit: the best I can think of is to convert each point to spherical coordinates and throw away the length, effectively converting these points to points on a unit sphere.  That way involves some trig operations though. Is there a better way that uses less computation?&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www3.cs.stonybrook.edu/~mueller/papers/EG06_geomfield.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10505" PostHistoryTypeId="2" PostId="4541" RevisionGUID="aef62abd-b5a3-42a5-9464-3fcb8f77b9e2" CreationDate="2017-01-14T07:44:08.223" UserId="5847" Text="Simply put, what does the transparency data of an EXR file represent? " ContentLicense="CC BY-SA 3.0" />
  <row Id="10506" PostHistoryTypeId="1" PostId="4541" RevisionGUID="aef62abd-b5a3-42a5-9464-3fcb8f77b9e2" CreationDate="2017-01-14T07:44:08.223" UserId="5847" Text="Explanation of a the transparency of an .EXR file" ContentLicense="CC BY-SA 3.0" />
  <row Id="10507" PostHistoryTypeId="3" PostId="4541" RevisionGUID="aef62abd-b5a3-42a5-9464-3fcb8f77b9e2" CreationDate="2017-01-14T07:44:08.223" UserId="5847" Text="|image-processing|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10508" PostHistoryTypeId="5" PostId="4534" RevisionGUID="5be96a49-c173-4911-8e02-7f06bfcb40d4" CreationDate="2017-01-14T10:26:04.210" UserId="38" Comment="fixed most garing typos" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathematics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathematics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because its easier to think in one orientation or just simply because you want to move/rotate/scale objects out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minimum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straight ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. Preferably automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other. &#xD;&#xA;&#xD;&#xA;Although this could be done in any number of ways it is commonly done with a tree structure using affine matrices. Mainly because this takes care of 2 issues. A the tree structure is easy to traverse and find the path to any other part in the hierarchy and matrices being appendable to form a compound transform independent of geometry calculation for each point in a object.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to transform the object to its parents coordinates, which in turn describes the transform to its parent all the way to the world. Since all objects share one common ancestor we can easily traverse the tree to find a transform from any one space to another. Whenever we travel in the opposite direction away from the world we simply use the inverse transform of the stored transform , whenever we work our way towards world we use the stored transform. &#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why. You should understand also that we do not have any limit to complexity of the hierarchy to facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This hierarchy is called a scene graph and such things can be found in web pages, vector and cad applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because its a tree, and earliest tree graphs are genealogical studies, aka family trees. Where the previous level is simply the parents and the next one is their children. &#xD;&#xA;&#xD;&#xA;PS: Written on my  phone at after work beer waiting for my coworkers to arrive so maybe i will still improve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10510" PostHistoryTypeId="2" PostId="4542" RevisionGUID="f0198faa-a81d-42ad-a520-f36a5da7539f" CreationDate="2017-01-14T13:04:20.307" UserId="2041" Text="In this code, the &quot;screen resolution&quot; means the number of pixels in the output image (which happens to be a window in the windowing system), while the &quot;window dimension&quot; means the corresponding size in the 3D scene. Computing `s` tells you the ratio between one unit of 3D space in your scene and one pixel of output image. You need to do this in order to know how far apart in world-space to cast your primary rays.&#xD;&#xA;&#xD;&#xA;These uses of &quot;screen&quot; and &quot;window&quot; aren't standard; they're specific to this code. No wonder you're confused." ContentLicense="CC BY-SA 3.0" />
  <row Id="10511" PostHistoryTypeId="2" PostId="4543" RevisionGUID="c4e2adde-cc86-47b2-a86a-93ba44573412" CreationDate="2017-01-14T16:10:34.077" UserId="1952" Text="3D object surface is 2D domain and can thus be parametrized with a 2D function. In case of a unit cube you could parametrize the surface for example by mapping each 6 faces to a 2D image strip. So if you know two points of the ray that intersects the cube, you can define it with 4D function using the parametrization" ContentLicense="CC BY-SA 3.0" />
  <row Id="10512" PostHistoryTypeId="2" PostId="4544" RevisionGUID="8253e4be-9eb2-4008-9c73-f87c1f2d032e" CreationDate="2017-01-14T16:11:42.713" UserDisplayName="user4718" Text="I was looking at this Wikipedia article about the _image plane_ or the _screen space_&#xD;&#xA;&#xD;&#xA;&gt; https://en.wikipedia.org/wiki/Image_plane&#xD;&#xA;&#xD;&#xA;and at a certain point there's&#xD;&#xA;&#xD;&#xA;&gt; A rectangular region of this plane, called the viewing window or viewport, maps to the monitor.&#xD;&#xA;&#xD;&#xA;Here plane they are I think referring to the _image plane_. But I'm wondering now what do they mean here by monitor. &#xD;&#xA;&#xD;&#xA;Is the monitor the same thing as the screen? &#xD;&#xA;&#xD;&#xA;Or, maybe first of all, what is intended by screen and monitor in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10513" PostHistoryTypeId="1" PostId="4544" RevisionGUID="8253e4be-9eb2-4008-9c73-f87c1f2d032e" CreationDate="2017-01-14T16:11:42.713" UserDisplayName="user4718" Text="Are the terms screen and the monitor in computer graphics used interchangeably?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10514" PostHistoryTypeId="3" PostId="4544" RevisionGUID="8253e4be-9eb2-4008-9c73-f87c1f2d032e" CreationDate="2017-01-14T16:11:42.713" UserDisplayName="user4718" Text="|space|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10515" PostHistoryTypeId="5" PostId="4544" RevisionGUID="3c0692a9-6841-4341-9f30-12ea25e36abd" CreationDate="2017-01-14T16:17:08.770" UserDisplayName="user4718" Comment="added 8 characters in body" Text="I was looking at this Wikipedia article about the _image plane_ or the _screen space_&#xD;&#xA;&#xD;&#xA;&gt; https://en.wikipedia.org/wiki/Image_plane&#xD;&#xA;&#xD;&#xA;and at a certain point there's&#xD;&#xA;&#xD;&#xA;&gt; A rectangular region of this plane, called the viewing window or viewport, maps to the monitor.&#xD;&#xA;&#xD;&#xA;Here, by &quot;plane&quot; they are (I think) referring to the _image plane_ (or screen space); but I'm wondering now what do they mean here by monitor. &#xD;&#xA;&#xD;&#xA;Is the monitor the same thing as the screen? Is the screen the plane in the monitor, but people in computer graphics usually say only _monitor_ to refer to the _screen_?&#xD;&#xA;&#xD;&#xA;Or, maybe first of all, what is intended by screen and monitor in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10516" PostHistoryTypeId="2" PostId="4545" RevisionGUID="b672d86c-b7b0-4af5-95fe-940d72ca5d9b" CreationDate="2017-01-14T17:42:46.897" UserId="48" Text="The terms _screen_, _monitor_, and _display_ are used more or less interchangeably to refer to the real-world physical device that shows the image you're looking at. (They're not 100% interchangeable: _monitor_ means a discrete display device such as you'd use with a desktop PC. However, a built-in display such as the one in a laptop, tablet, or phone is never called a monitor.)&#xD;&#xA;&#xD;&#xA;The _image plane_ means the abstract geometric plane that identifies the surface of the display, but extends infinitely in all directions, i.e. isn't bounded by the edges of the display. The _viewport_ or _viewing window_ is the rectangle within this plane that identifies the edges of the display (or more generally, the edges of the image you're rendering, in case your app is running in a window and not fullscreen).&#xD;&#xA;&#xD;&#xA;The term _screen_ might also be used more colloquially to mean various other things, such as: various coordinate systems on the image plane (&quot;screen space&quot;), the viewport or view frustum (&quot;the object is off-screen&quot;), the back buffer (&quot;render it to the screen&quot;), and probably more." ContentLicense="CC BY-SA 3.0" />
  <row Id="10518" PostHistoryTypeId="2" PostId="4546" RevisionGUID="342706b4-9adb-46d9-9a35-62245a68df4f" CreationDate="2017-01-15T00:37:15.240" UserId="4958" Text="As stated in [documentation][1] possible values for layout qualifiers of image formats are (for example floating point):&#xD;&#xA;&#xD;&#xA;&gt; Floating-point layout image formats:&#xD;&#xA;&#xD;&#xA;&gt;  - rgba32f&#xD;&#xA;&gt;  - rgba16f&#xD;&#xA;&gt;  - rg32f&#xD;&#xA;&gt;  - rg16f&#xD;&#xA;&gt;  - r11f_g11f_b10f&#xD;&#xA;&gt;  - r32f&#xD;&#xA;&gt;  - r16f&#xD;&#xA;&gt;  - rgba16&#xD;&#xA;&gt;  - rgb10_a2&#xD;&#xA;&gt;  - rgba8&#xD;&#xA;&gt;  - rg16&#xD;&#xA;&gt;  - rg8&#xD;&#xA;&gt;  - r16&#xD;&#xA;&gt;  - r8&#xD;&#xA;&gt;  - rgba16_snorm&#xD;&#xA;&gt;  - rgba8_snorm&#xD;&#xA;&gt;  - rg16_snorm&#xD;&#xA;&gt;  - rg8_snorm&#xD;&#xA;&gt;  - r16_snorm&#xD;&#xA;&gt;  - r8_snorm&#xD;&#xA;&#xD;&#xA;So we can use `R`, `RG` and `RGBA` formats. But why `RGB` is not allowed?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Image_formats" ContentLicense="CC BY-SA 3.0" />
  <row Id="10519" PostHistoryTypeId="1" PostId="4546" RevisionGUID="342706b4-9adb-46d9-9a35-62245a68df4f" CreationDate="2017-01-15T00:37:15.240" UserId="4958" Text="Using RGB texture format for image load/store" ContentLicense="CC BY-SA 3.0" />
  <row Id="10520" PostHistoryTypeId="3" PostId="4546" RevisionGUID="342706b4-9adb-46d9-9a35-62245a68df4f" CreationDate="2017-01-15T00:37:15.240" UserId="4958" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10521" PostHistoryTypeId="2" PostId="4547" RevisionGUID="554e10c2-5c84-4757-9c7d-309b6a14a80b" CreationDate="2017-01-15T01:27:00.053" UserId="48" Text="RGB format without alpha is often not supported by GPUs (or only supported for a subset of GPU operations) because it doesn't have a power-of-two number of bytes per pixel. RGB would be 24 bits or 3 bytes per pixel. All the formats in that list have 1, 2, 4, 8, or 16 bytes per pixel.&#xD;&#xA;&#xD;&#xA;Using a power of two simplifies addressing calculations in the hardware, because it can be implemented using a shift instead of a full multiply. (A shift by a fixed value such as 2 bits can even be implemented in hardware without any actual &quot;calculations&quot; at all, just by routing wires.) It also means that pixels are always nicely aligned with respect to boundaries of memory pages, cache lines, etc., which no doubt simplifies many things in the hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="10522" PostHistoryTypeId="5" PostId="4547" RevisionGUID="8811001f-9e0b-4a11-af87-7e3f720bcd23" CreationDate="2017-01-15T02:19:05.003" UserId="48" Comment="be more specific that I'm talking about 8-bit RGB" Text="RGB8 format and similar are often not supported by GPUs (or only supported for a subset of GPU operations) because they don't have a power-of-two number of bytes per pixel. RGB8 would be 24 bits or 3 bytes per pixel. All the formats in that list have 1, 2, 4, 8, or 16 bytes per pixel.&#xD;&#xA;&#xD;&#xA;Using a power of two simplifies addressing calculations in the hardware, because it can be implemented using a shift instead of a full multiply. (A shift by a fixed value such as 2 bits can even be implemented in hardware without any actual &quot;calculations&quot; at all, just by routing wires.) It also means that pixels are always nicely aligned with respect to boundaries of memory pages, cache lines, etc., which no doubt simplifies many things in the hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="10523" PostHistoryTypeId="2" PostId="4548" RevisionGUID="11907637-1bb2-4b1a-8e56-8a2b4dfaa701" CreationDate="2017-01-15T03:12:52.950" UserId="3003" Text="Generally, the &quot;a&quot; channel is referred to as the [alpha channel](https://en.wikipedia.org/wiki/Glossary_of_computer_graphics#Alpha_channel). It represents the amount of a pixel that an object covers. For computer-generated imagery this is pretty straightforward. &#xD;&#xA;&#xD;&#xA;If I generate a circle, parts of the circle on the interior will cover a full pixel, but parts on the edges of the circle may only cover a portion of the pixel. Internal pixels would have an alpha channel of 100%, whereas those edge pixels that only cover a portion of the pixel would have a value less than 100%. Outside the circle all pixels would have an alpha value of 0%.&#xD;&#xA;&#xD;&#xA;For captured imagery, generally all pixels have an alpha value of 100%. However, if you use keying or matting tools to remove a green screen or blue screen, for example, there will be some pixels that are partially green (or blue), and they may end up with an alpha value between 0% and 100%. pixels that are solid green (or blue) will have an alpha value of 0%, and pixels that contain no green (or blue) will have an alpha value of 100%." ContentLicense="CC BY-SA 3.0" />
  <row Id="10524" PostHistoryTypeId="5" PostId="4548" RevisionGUID="e6074d1d-133b-434b-8911-ee76473116fa" CreationDate="2017-01-15T03:20:40.020" UserId="3003" Comment="Added mathematical description of normal mode blending." Text="Generally, the &quot;a&quot; channel is referred to as the [alpha channel](https://en.wikipedia.org/wiki/Glossary_of_computer_graphics#Alpha_channel). It represents the amount of a pixel that an object covers. For computer-generated imagery this is pretty straightforward. &#xD;&#xA;&#xD;&#xA;If I generate a circle, parts of the circle on the interior will cover a full pixel, but parts on the edges of the circle may only cover a portion of the pixel. Internal pixels would have an alpha channel of 100%, whereas those edge pixels that only cover a portion of the pixel would have a value less than 100%. Outside the circle all pixels would have an alpha value of 0%.&#xD;&#xA;&#xD;&#xA;For captured imagery, generally all pixels have an alpha value of 100%. However, if you use keying or matting tools to remove a green screen or blue screen, for example, there will be some pixels that are partially green (or blue), and they may end up with an alpha value between 0% and 100%. pixels that are solid green (or blue) will have an alpha value of 0%, and pixels that contain no green (or blue) will have an alpha value of 100%.&#xD;&#xA;&#xD;&#xA;This is used when you want to composite one image over another. For normal compositing, you will mix the top and bottom pixels by multiplying the color value of the top pixel by its coverage or alpha, multiplying the color value of the bottom pixel by the inverse of the alpha (1.0 - alpha), and adding the two together. So it would look something like this:&#xD;&#xA;&#xD;&#xA;    composite = top * alpha + bottom * (1.0 - alpha)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10528" PostHistoryTypeId="2" PostId="4550" RevisionGUID="ab56fcfd-da7d-4916-8251-3b3c2fbbde6b" CreationDate="2017-01-15T03:25:32.707" UserId="5852" Text="As I understand, the back-buffer is used for rendering the image while the front-buffer is drawn on the screen. So if you have only one image to be drawn on the screen, then you only need to swap the buffers one time because in the second swap the image is already drawn and there is no point to draw the same image again. However, when I tried to swap buffers no more than 2 times the graphics slow down a lot and move the window from one position to another takes 10-20 seconds. My question is... Why?&#xD;&#xA;How double-buffers works then?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10529" PostHistoryTypeId="1" PostId="4550" RevisionGUID="ab56fcfd-da7d-4916-8251-3b3c2fbbde6b" CreationDate="2017-01-15T03:25:32.707" UserId="5852" Text="How double-buffers works in opengl?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10530" PostHistoryTypeId="3" PostId="4550" RevisionGUID="ab56fcfd-da7d-4916-8251-3b3c2fbbde6b" CreationDate="2017-01-15T03:25:32.707" UserId="5852" Text="|opengl|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10531" PostHistoryTypeId="2" PostId="4551" RevisionGUID="10398f7a-2558-4183-b28b-e31096028b4e" CreationDate="2017-01-15T05:10:55.160" UserId="5854" Text="I am trying to implement a physically based renderer, in OpenGL. I was planning to implement the Cook-Torrance BRDF. I read about radiance cubemaps (for reflections), like the one discussed [here][1], for example. I a bit confused however. My test environment is Sponza with some other models thrown in, where you can move the camera around freely. How would an environmental cubemap work with a scene like that, where there are arcades or similar architectural pieces, and other things in the way? Would there need be multiple cubemaps? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.codinglabs.net/article_physically_based_rendering.aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="10532" PostHistoryTypeId="1" PostId="4551" RevisionGUID="10398f7a-2558-4183-b28b-e31096028b4e" CreationDate="2017-01-15T05:10:55.160" UserId="5854" Text="Trying to understand environmental cubemaps" ContentLicense="CC BY-SA 3.0" />
  <row Id="10533" PostHistoryTypeId="3" PostId="4551" RevisionGUID="10398f7a-2558-4183-b28b-e31096028b4e" CreationDate="2017-01-15T05:10:55.160" UserId="5854" Text="|opengl|rendering|brdf|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10534" PostHistoryTypeId="2" PostId="4552" RevisionGUID="5b622e58-8e5d-480e-9757-09f6a8f10a09" CreationDate="2017-01-15T05:15:45.130" UserId="5556" Text="In an EXR, the convention is to store *associated alpha*, also known as *premultiplied*. The latter term however doesn't do justice to the nuances of the alpha format as compared to its evil distant cousin known as *unassociated alpha*, aka *straight* or *key* alpha.&#xA;&#xA;In an associated alpha image, two facets are represented via the RGB triplet and its associated alpha channel:&#xA;&#xA; 1. Occlusion.&#xA; 1. Emission.&#xA;&#xA;In an associated alpha image, the alpha channel could be considered to represent a distillation of the geometry of occlusion covering a given pixel coordinate. 0.5 would represent a baked down 50% occlusion, while the RGB values would represent the degree of emission.&#xA;&#xA;This also means that an RGBA triplet such as 0.0,12.4,10282.9,0.0 is entirely valid, and represents a pixel that is emitting and unoccluding. Naturally occuring things such as candles represent such a combination. Consider the following image:&#xA;[![Candle flame with no shadow][1]][1]&#xA;&#xA;The above image could not be created using unassociated alpha, and is symptomatic as to why ray tracing renderers cannot generate any alpha model other than associated alpha.&#xA;&#xA;The fundamental difference between the two alpha formats is defined by the two different over operations, as described by [Porter Duff][2].&#xA;&#xA;Associated alpha over:&#xA;&#xA;    FG.RGB + ((1.0-FG.Alpha) * BG.RGB&#xA;&#xA;Unassociated alpha over:&#xA;&#xA;    (FG.Alpha * FG.RGB) + ((1.0-FG.Alpha) * BG.RGB&#xA;&#xA;The nuances of the difference mean that care should be taken when dealing with alpha and the RGB channels.&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/aINLh.jpg&#xA;  [2]: http://ssp.impulsetrain.com/porterduff.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="10535" PostHistoryTypeId="2" PostId="4553" RevisionGUID="135b30c3-c713-49ea-b80f-af22822e0fb2" CreationDate="2017-01-15T07:44:37.087" UserId="4546" Text="Since you've used the &quot;path tracing&quot; tag, I'm assuming you're thinking mainly about light transport. At SIGGRAPH 2015, there was a course on the topic of path tracing in movie production that may be interesting:&#xD;&#xA;https://sites.google.com/site/pathtracingrevolution/&#xD;&#xA;Some of the presenters point out unsolved challenges towards the end of their presentation, for example see the second to last slides in the presentations from Alexander Keller and Johannes Hanika.&#xD;&#xA;&#xD;&#xA;Then there are challenges in rendering that are not necessarily tied to path tracing but also present in game engines. Triangle meshes as an approximation of smooth solid surfaces are one, the use of shading normals or even worse, bumped normals have been pointed out as a source of artifacts a long time ago: [&quot;It's not really a rendering bug, you see...&quot;][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://pdfs.semanticscholar.org/7986/ebd7b5427bbe54edb7c0c9cf674fee817933.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10536" PostHistoryTypeId="5" PostId="4546" RevisionGUID="cda3aa28-1a85-46fd-980b-f18fa7aa91f9" CreationDate="2017-01-15T10:17:31.000" UserId="4958" Comment="added 24 characters in body" Text="As stated in [documentation][1] possible values for layout qualifiers of image formats are (for example floating point):&#xD;&#xA;&#xD;&#xA;&gt; Floating-point layout image formats:&#xD;&#xA;&#xD;&#xA;&gt;  - rgba32f&#xD;&#xA;&gt;  - rgba16f&#xD;&#xA;&gt;  - rg32f&#xD;&#xA;&gt;  - rg16f&#xD;&#xA;&gt;  - r11f_g11f_b10f&#xD;&#xA;&gt;  - r32f&#xD;&#xA;&gt;  - r16f&#xD;&#xA;&gt;  - rgba16&#xD;&#xA;&gt;  - rgb10_a2&#xD;&#xA;&gt;  - rgba8&#xD;&#xA;&gt;  - rg16&#xD;&#xA;&gt;  - rg8&#xD;&#xA;&gt;  - r16&#xD;&#xA;&gt;  - r8&#xD;&#xA;&gt;  - rgba16_snorm&#xD;&#xA;&gt;  - rgba8_snorm&#xD;&#xA;&gt;  - rg16_snorm&#xD;&#xA;&gt;  - rg8_snorm&#xD;&#xA;&gt;  - r16_snorm&#xD;&#xA;&gt;  - r8_snorm&#xD;&#xA;&#xD;&#xA;So we can use `R`, `RG` and `RGBA` formats. But why `RGB` (except r11f_g11f_b10f) is not allowed?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Image_formats" ContentLicense="CC BY-SA 3.0" />
  <row Id="10537" PostHistoryTypeId="2" PostId="4554" RevisionGUID="aa15783b-aa8f-4cff-887a-4725b23aaa75" CreationDate="2017-01-15T11:59:14.617" UserId="5855" Text="I am converting some Unity3D scenes to a proprietary json format to be used by my OpenGL renderer that uses a different coordinate system from Unity's.&#xD;&#xA;&#xD;&#xA;I have multiple sets of {translation, rotation(quat), scale} pairs that describe some node transformations. The engine that uses them (Unity) uses the positive x-axis looking to the right, the positive y-axis looking up and the positive z-axis looking front.&#xD;&#xA;&#xD;&#xA;I want to convert each pair into a {new_translation, new_rotation(quat), new_scale} in order to use them in my engine using the same coordinate convention with the z-axis inverted (positive z-axis looking back, the most common OpenGL convention).&#xD;&#xA;&#xD;&#xA;How should the new pairs be constructed?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10538" PostHistoryTypeId="1" PostId="4554" RevisionGUID="aa15783b-aa8f-4cff-887a-4725b23aaa75" CreationDate="2017-01-15T11:59:14.617" UserId="5855" Text="How to convert decomposed transformations between different coordinate systems?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10539" PostHistoryTypeId="3" PostId="4554" RevisionGUID="aa15783b-aa8f-4cff-887a-4725b23aaa75" CreationDate="2017-01-15T11:59:14.617" UserId="5855" Text="|opengl|transformations|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10540" PostHistoryTypeId="2" PostId="4555" RevisionGUID="ae36ab95-c67d-4de9-b75d-147eb8891850" CreationDate="2017-01-15T12:23:22.520" UserId="4958" Text="Your confusion comes from fact that in some basic tutorials like one you point cubemap which is used for applying lighting is global and static - it does not come from actual geometry but from infite sky box which moves with camera position so it is valid everywhere. &#xD;&#xA;&#xD;&#xA;And there is nothing mentioned about second type - local cubemaps which are actually computed using local geometry and are valid only in point of their placement. &#xD;&#xA;&#xD;&#xA;This can be approached using multiple local cubemaps rendered offline and connecting them with local objects but what is problematic is that it generates seams between them especially for high frequency reflections, which you probably would like to test. &#xD;&#xA;&#xD;&#xA;For now you can generate few local cubemaps centered at your small objects which would move with them if you plan to change their position. They would take into account your local geometry and, if you render it, your global skybox or skydome. You can precompute these cubemaps each time you change the position of your objects or do it every frame.&#xD;&#xA;&#xD;&#xA;If you want to make your whole sponza reflective with high frequency, that's harder problem but one idea is to voxelize whole sponza with different mipmap voxel levels and then ray trace it as in voxel cone tracing technique. Voxelization could be done as precomputation but it is generally memory intensive.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10541" PostHistoryTypeId="5" PostId="4555" RevisionGUID="649349a0-fabc-43a8-add7-698197e5d403" CreationDate="2017-01-15T12:53:02.083" UserId="4958" Comment="added 20 characters in body" Text="Your confusion comes from fact that in some basic tutorials like one you point cubemap which is used for applying lighting is global and static - it does not come from actual geometry but from infite sky box which moves with camera position so it is valid everywhere. &#xD;&#xA;&#xD;&#xA;And there is nothing mentioned about second type - local cubemaps which are actually computed using local geometry and are valid only in point of their placement. &#xD;&#xA;&#xD;&#xA;This can be approached using multiple local cubemaps rendered offline and connecting them with local objects but what is problematic is that it generates seams between them especially for high frequency reflections, which you probably would like to test. &#xD;&#xA;&#xD;&#xA;For now you can generate few local cubemaps centered at your small objects and used on them. They would move with objects if you plan to change their position. They would take into account your local geometry and, if you render it, your global skybox or skydome. You can precompute these cubemaps each time you change the position of your objects or do it every frame.&#xD;&#xA;&#xD;&#xA;If you want to make your whole sponza reflective with high frequency, that's harder problem but one idea is to voxelize whole sponza with different mipmap voxel levels and then ray trace it as in voxel cone tracing technique. Voxelization could be done as precomputation but it is generally memory intensive.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10542" PostHistoryTypeId="5" PostId="4555" RevisionGUID="0b1520e2-fa46-4f73-9622-3d39c9c7797d" CreationDate="2017-01-15T13:11:51.967" UserId="4958" Comment="added 21 characters in body" Text="Your confusion comes from fact that in some basic tutorials like one you point cubemap which is used for applying lighting is global and static - it does not come from actual geometry but from infite sky box which moves with camera position so it is valid everywhere. &#xD;&#xA;&#xD;&#xA;And there is nothing mentioned about second type - local cubemaps which are actually computed using local geometry and are valid only in point of their placement. &#xD;&#xA;&#xD;&#xA;This can be approached using multiple local cubemaps and connecting them with local objects situated around them but what is problematic is that it generates seams between them especially for high frequency reflections, which you probably would like to test. &#xD;&#xA;&#xD;&#xA;For now you can generate few local cubemaps centered at your small objects and used on them. They would move with objects if you plan to change their position. They would take into account your local geometry and, if you render it, your global skybox or skydome. You can precompute these cubemaps each time you change the position of your objects or do it every frame.&#xD;&#xA;&#xD;&#xA;If you want to make your whole sponza reflective with high frequency, that's harder problem but one idea is to voxelize whole sponza with different mipmap voxel levels and then ray trace it as in voxel cone tracing technique. Voxelization could be done as precomputation but it is generally memory intensive.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10543" PostHistoryTypeId="5" PostId="4555" RevisionGUID="0b65f01b-701a-4733-850f-2c4be3764b92" CreationDate="2017-01-15T13:27:00.043" UserId="4958" Comment="added 16 characters in body" Text="Your confusion comes from fact that in some basic tutorials like one you point cubemap which is used for applying lighting is global and static - it does not come from actual geometry but from infite sky box which moves with camera position so it is valid everywhere. &#xD;&#xA;&#xD;&#xA;And there is nothing mentioned about second type - local cubemaps which are actually computed using local geometry and are valid only in point of their placement. &#xD;&#xA;&#xD;&#xA;This can be approached using multiple local cubemaps and connecting them with local objects situated around them but what is problematic is that it generates seams between them especially for high frequency reflections, which you probably would like to test. &#xD;&#xA;&#xD;&#xA;For now you can generate few local cubemaps - each one centered at one of your small objects and used on it. They would move with objects if you plan to change their position. They would take into account your local geometry and, if you render it, your global skybox or skydome. You can precompute these cubemaps each time you change the position of your objects or do it every frame.&#xD;&#xA;&#xD;&#xA;If you want to make your whole sponza reflective with high frequency, that's harder problem but one idea is to voxelize whole sponza with different mipmap voxel levels and then ray trace it as in voxel cone tracing technique. Voxelization could be done as precomputation but it is generally memory intensive.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10544" PostHistoryTypeId="2" PostId="4556" RevisionGUID="8ce0c4c6-e30b-452e-8f44-2d3adb9cc183" CreationDate="2017-01-15T14:22:32.480" UserId="5856" Text="I need to generate an easy animation video in Python (I use PIL to create every frame, then combine them using `avconv`). The animation is just an image being zoomed out.&#xD;&#xA;&#xD;&#xA;That's my code:&#xD;&#xA;&#xD;&#xA;    for i in xrange(zoom_length):&#xD;&#xA;&#xD;&#xA;        # zoom level on this step&#xD;&#xA;        zoom = 1.0 - 1.0 * i * (max_zoom / zoom_length)&#xD;&#xA;        &#xD;&#xA;        # &quot;size&quot; is the resulting video frame size&#xD;&#xA;        # &quot;img.size&quot; is the source image size (around 2.5x bigger than the frame)&#xD;&#xA;        anti_zoomed_frame_size = int(size[0] / zoom), int(size[1] / zoom)&#xD;&#xA;        anti_zoomed_frame_margins = (img.size[0] - anti_zoomed_frame_size[0]) / 2, (img.size[1] - anti_zoomed_frame_size[1]) / 2&#xD;&#xA;        &#xD;&#xA;        anti_zoomed_frame = img.crop(anti_zoomed_frame_margins +&#xD;&#xA;                                     (anti_zoomed_frame_size[0] + anti_zoomed_frame_margins[0],&#xD;&#xA;                                      anti_zoomed_frame_size[1] + anti_zoomed_frame_margins[1]))&#xD;&#xA;&#xD;&#xA;        frame = anti_zoomed_frame.resize(size, resample=Image.BILINEAR)&#xD;&#xA;        &#xD;&#xA;        print i, img.size, anti_zoomed_frame_size, anti_zoomed_frame_margins&#xD;&#xA;        &#xD;&#xA;        # frame No for debugging&#xD;&#xA;        draw = ImageDraw.Draw(frame)&#xD;&#xA;        draw.text((size[0] - 200, size[1] - 100), str(i), (0,0,0), font=font)&#xD;&#xA;&#xD;&#xA;        yield frame&#xD;&#xA;&#xD;&#xA;So what happens is I crop out of the source image a rectangle of size `frame_size / zoom` , then I resize it `zoom` times to get the needed frame size. `zoom &lt;= 1.0` so doing it in this order seems to be a good idea, though I also tried doing it the other way (resize, then crop).&#xD;&#xA;&#xD;&#xA;Anyway in both cases the resulting video is kind of shaking at times. It seems that the problem is in rounding the numbers. The math I'm doing inevitably leads to non-integers, yet PIL requires integers everywhere (also the resulting frame size is obviously a pair of integer constants). This rounding operation seems to affect the smoothness of the animation badly.&#xD;&#xA;&#xD;&#xA;How smooth zooming is implemented in real life? " ContentLicense="CC BY-SA 3.0" />
  <row Id="10545" PostHistoryTypeId="1" PostId="4556" RevisionGUID="8ce0c4c6-e30b-452e-8f44-2d3adb9cc183" CreationDate="2017-01-15T14:22:32.480" UserId="5856" Text="smooth zoom animation formulas (and rounding numbers)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10546" PostHistoryTypeId="3" PostId="4556" RevisionGUID="8ce0c4c6-e30b-452e-8f44-2d3adb9cc183" CreationDate="2017-01-15T14:22:32.480" UserId="5856" Text="|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10547" PostHistoryTypeId="2" PostId="4557" RevisionGUID="c95bc4cf-3e6a-4720-8479-afeb0f9ac6aa" CreationDate="2017-01-15T16:50:15.950" UserId="5556" Text="&gt; I have some colors in RGB in [0,1] and want to find a way to rate&#xA;&gt; their similarity, as percieved by a human.&#xA;&#xA;This is a huge subject, and loosely is found under the banner of *colour appearance models*. Why is it not strictly a more simple formation is due to the psychophysical nature of colour in that colour does not exist beyond the human organism.&#xA;&#xA;&gt; My first idea is to treat the RGB colors as XYZ points and calculate&#xA;&gt; their distance.&#xA;&gt; &#xA;&gt; Another idea I have is to treat the RGB values as a histogram and use&#xA;&gt; dot product to get a similarity value between them, where a larger&#xA;&gt; value is better.&#xA;&#xA;&gt; I know however, that not all of the color channels have the same&#xA;&gt; percieved brightness so maybe i ought to weight the color channels&#xA;&gt; differently for both cases?&#xA;&#xA;Best advice is, much like cryptography, do not roll your own.&#xA;&#xA;One could point at the historical developments around CAMs, but it is easier here to suggest that you research the IPT colour encoding model and its cylindrical equivalent that models colourfulness and hue as an angle. The evolutions in the IPT model overcome most of the issues of the earlier Lab model, and simplifies some of the work involved in CIECAM02.&#xA;&#xA;&gt; Another challenge to this may be that different displays will display&#xA;&gt; the same color values differently. Not sure if that's relevant in this&#xA;&gt; case.&#xA;&#xA;IPT, and every RGB colour space for that matter, are anchored in the 1931 CIE research. As such, these sorts of issues are solved at a lower level." ContentLicense="CC BY-SA 3.0" />
  <row Id="10548" PostHistoryTypeId="5" PostId="4557" RevisionGUID="7b0a75bd-f4c4-49b7-9fbf-9b5100f02fd8" CreationDate="2017-01-15T20:55:49.967" UserId="5556" Comment="Expand region due to Wolfe's comment." Text="&gt; I have some colors in RGB in [0,1] and want to find a way to rate&#xD;&#xA;&gt; their similarity, as percieved by a human.&#xD;&#xA;&#xD;&#xA;This is a huge subject, and loosely is found under the banner of *colour appearance models*. Why is it not strictly a more simple formation is due to the psychophysical nature of colour in that colour does not exist beyond the human organism.&#xD;&#xA;&#xD;&#xA;&gt; My first idea is to treat the RGB colors as XYZ points and calculate&#xD;&#xA;&gt; their distance.&#xD;&#xA;&gt; &#xD;&#xA;&gt; Another idea I have is to treat the RGB values as a histogram and use&#xD;&#xA;&gt; dot product to get a similarity value between them, where a larger&#xD;&#xA;&gt; value is better.&#xD;&#xA;&#xD;&#xA;&gt; I know however, that not all of the color channels have the same&#xD;&#xA;&gt; percieved brightness so maybe i ought to weight the color channels&#xD;&#xA;&gt; differently for both cases?&#xD;&#xA;&#xD;&#xA;Best advice is, much like cryptography, do not roll your own; you are likely to arrive at a sub-optimal system that will, in the best of cases, hit walls already hit by other researchers in the field. If you base your work on existing models and research, you might find it to be more accurate for your needs[1].&#xD;&#xA;&#xD;&#xA;One could point at the historical developments around CAMs, but it is easier here to suggest that you research the IPT colour encoding model and its cylindrical equivalent that models colourfulness and hue as an angle. The evolutions in the IPT model overcome most of the issues of the earlier Lab model, and simplifies some of the work involved in CIECAM02.&#xD;&#xA;&#xD;&#xA;&gt; Another challenge to this may be that different displays will display&#xD;&#xA;&gt; the same color values differently. Not sure if that's relevant in this&#xD;&#xA;&gt; case.&#xD;&#xA;&#xD;&#xA;IPT, and every RGB colour space for that matter, are anchored in the 1931 CIE research. As such, these sorts of issues are solved at a lower level.&#xD;&#xA;&#xD;&#xA;[1] This expanded answer is due to Mr. Wolfe's comment below in an attempt to explain why rolling your own solution might be a sub-optimal approach." ContentLicense="CC BY-SA 3.0" />
  <row Id="10549" PostHistoryTypeId="2" PostId="4558" RevisionGUID="766856a8-844f-4408-97d2-eebbc0acc232" CreationDate="2017-01-16T10:50:19.880" UserId="2041" Text="Yes, the back buffer is for the GPU to write the frame that's in-progress, while the display controller sends the front buffer to the attached display. *Swapping* buffers doesn't really copy anything these days. The display controller has a register which tells it the address of the frame buffer to display. Swapping buffers simply puts the address of the old back buffer in this register, making it the front buffer. You should only swap buffers when the frame is complete (i.e. you've finished drawing all the objects) and you want it to be displayed. This frame will continue to be displayed until you swap buffers again.&#xD;&#xA;&#xD;&#xA;In some configurations (e.g. in EGL it depends on what swap interval you set) swapping buffers will make the CPU wait (block) until the GPU has finished rendering that frame. In others, the CPU can continue to queue up draw calls for further frames." ContentLicense="CC BY-SA 3.0" />
  <row Id="10550" PostHistoryTypeId="2" PostId="4559" RevisionGUID="d516eb15-a7eb-4056-9446-61d46fb1c15e" CreationDate="2017-01-16T11:53:27.893" UserId="137" Text="Map the mouse position to the circle by drawing an imaginary line between the mouse and the center of the gizmo on the plane of the current circle. Do this for the start and current positions.&#xD;&#xA;&#xD;&#xA;Then you can easily get the quaternion rotation around the center from the start to the end by doing `normalize(quat(1+dot(v_1, v_2), cross(v_1, v_2)))`.&#xD;&#xA;&#xD;&#xA;This works because the dot product is the cos of the angle between the vectors and the cross is the vector perpendicular to the 2 vectors (aka the rotation angle) and has length of the sin of the angle between the vectors. This means that you can create the double quaternion out of them. Then you can nlerp that double quaternion with the unit quaternion to get the rotation you need.&#xD;&#xA;&#xD;&#xA;However with that information you can do an arcball by projecting the mouse onto the ball that is the gizmo and using the start and end vectors that way." ContentLicense="CC BY-SA 3.0" />
  <row Id="10559" PostHistoryTypeId="2" PostId="4562" RevisionGUID="2514fb27-1f44-4bff-ba38-2e89d3245872" CreationDate="2017-01-16T23:51:58.473" UserId="5852" Text="I am pretty confused about that function. [GLFW Context reference][1] says as follow:&lt;br&gt;&#xD;&#xA;&#xD;&#xA;&gt; This function makes the OpenGL or OpenGL ES context of the specified&#xD;&#xA;&gt; window current on the calling thread. A context can only be made&#xD;&#xA;&gt; current on a single thread at a time and each thread can have only a&#xD;&#xA;&gt; single current context at a time.&#xD;&#xA;&#xD;&#xA;but it does not help me much.Can it work like &quot;glBind-&quot; methods? (glBindBuffer, glBindVertexArray and so on)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glfw.org/docs/latest/group__context.html#ga1c04dc242268f827290fe40aa1c91157" ContentLicense="CC BY-SA 3.0" />
  <row Id="10560" PostHistoryTypeId="1" PostId="4562" RevisionGUID="2514fb27-1f44-4bff-ba38-2e89d3245872" CreationDate="2017-01-16T23:51:58.473" UserId="5852" Text="What does &quot;makeContextCurrent&quot; do exactly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10561" PostHistoryTypeId="3" PostId="4562" RevisionGUID="2514fb27-1f44-4bff-ba38-2e89d3245872" CreationDate="2017-01-16T23:51:58.473" UserId="5852" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10562" PostHistoryTypeId="5" PostId="4562" RevisionGUID="01914db6-68fc-480a-9c93-5cbc70b88ccf" CreationDate="2017-01-16T23:57:00.750" UserId="5852" Comment="added 8 characters in body" Text="I am pretty confused about that function. [GLFW Context reference][1] says as follow:&lt;br&gt;&#xD;&#xA;&#xD;&#xA;&gt; This function makes the OpenGL or OpenGL ES context of the specified&#xD;&#xA;&gt; window current on the calling thread. A context can only be made&#xD;&#xA;&gt; current on a single thread at a time and each thread can have only a&#xD;&#xA;&gt; single current context at a time.&#xD;&#xA;&#xD;&#xA;But it does not help me much.&lt;br /&gt;&#xD;&#xA;Can it work like &quot;glBind-&quot; methods? (glBindBuffer, glBindVertexArray and so on)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glfw.org/docs/latest/group__context.html#ga1c04dc242268f827290fe40aa1c91157" ContentLicense="CC BY-SA 3.0" />
  <row Id="10563" PostHistoryTypeId="2" PostId="4563" RevisionGUID="74b555c9-33e1-44b9-baea-7527609549ed" CreationDate="2017-01-17T00:05:26.303" UserId="3003" Text="OpenGL is a state machine. An OpenGL context holds that state. The state contains information such as which textures are bound to which texture units, which attachments the current FBO has, and things like that.&#xD;&#xA;&#xD;&#xA;When you set the current context, you are switching all the state from the old context to the new context. Here's an example:&#xD;&#xA;&#xD;&#xA;    glfwMakeContextCurrent(window1);&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture1);&#xD;&#xA;    &#xD;&#xA;    glfwMakeContextCurrent(window2);&#xD;&#xA;&#xD;&#xA;What this does is makes the context of `window1` current. It then enables the 2D texture unit and binds `texture1` to it. &#xD;&#xA;&#xD;&#xA;Next it makes the context of `window2` current. If you were to check the enabled state of `GL_TEXTURE_2D` it would be false (unless you had previously enabled it on the `window2` context). Likewise, if you check which texture is bound to the 2D texture unit, you would likely find no texture was bound, or some texture other than `texture1` was bound.&#xD;&#xA;&#xD;&#xA;Basically all drawing happens in the current context. If you make a different context current, then all drawing will now happen in that context.&#xD;&#xA;&#xD;&#xA;It is common to have a single context per thread in a multi-threaded OpenGL application. That way each thread is drawing into its own context and doesn't mess up the state of contexts on other threads." ContentLicense="CC BY-SA 3.0" />
  <row Id="10564" PostHistoryTypeId="5" PostId="4562" RevisionGUID="48a0eaee-c06b-4189-8772-f823d0caf937" CreationDate="2017-01-17T00:31:17.157" UserId="5852" Comment="added 56 characters in body" Text="I am pretty confused about that function. [GLFW Context reference][1] says as follow:&lt;br&gt;&#xD;&#xA;&#xD;&#xA;&gt; This function makes the OpenGL or OpenGL ES context of the specified&#xD;&#xA;&gt; window current on the calling thread. A context can only be made&#xD;&#xA;&gt; current on a single thread at a time and each thread can have only a&#xD;&#xA;&gt; single current context at a time.&#xD;&#xA;&#xD;&#xA;But it does not help me much.&lt;br /&gt;&#xD;&#xA;Can it work like [`glBind-`][2] methods? (glBindBuffer, glBindVertexArray and so on)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glfw.org/docs/latest/group__context.html#ga1c04dc242268f827290fe40aa1c91157&#xD;&#xA;  [2]: http://stackoverflow.com/q/9758884/5744858" ContentLicense="CC BY-SA 3.0" />
  <row Id="10566" PostHistoryTypeId="2" PostId="4564" RevisionGUID="87a38e0a-40a5-4b7b-9386-05873f660a40" CreationDate="2017-01-17T09:20:48.213" UserId="1614" Text="In shaders, when using `SampleLevel` intrinsic, if we pass `0.5` in the mip level parameter, and the sampler is a `point sampler`, what mip level is selected ?&#xD;&#xA;&#xD;&#xA;According to this blog: https://blogs.msdn.microsoft.com/shawnhar/2009/09/14/texture-filtering-mipmaps/  &#xD;&#xA;It seems as if the coarser level of `1` is selected, so that would be a `ceil` operation going on internally.&#xD;&#xA;&#xD;&#xA;I still ask because the wording in the blog:&#xD;&#xA;&gt; rounds up to the next larger mip level&#xD;&#xA;&#xD;&#xA;Is open to interpretation, that could mean the larger in dimensions, therefore finer.  &#xD;&#xA;And honestly it feels that using `ceil` is a very unfair convention for the `mip 0`, which can only be selected with exactly `0.0`, poor thing." ContentLicense="CC BY-SA 3.0" />
  <row Id="10567" PostHistoryTypeId="1" PostId="4564" RevisionGUID="87a38e0a-40a5-4b7b-9386-05873f660a40" CreationDate="2017-01-17T09:20:48.213" UserId="1614" Text="Rounding rules for mip level with point sampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="10568" PostHistoryTypeId="3" PostId="4564" RevisionGUID="87a38e0a-40a5-4b7b-9386-05873f660a40" CreationDate="2017-01-17T09:20:48.213" UserId="1614" Text="|shader|directx|mipmap|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10573" PostHistoryTypeId="2" PostId="4565" RevisionGUID="cf1783e4-ca6d-4c0b-91f4-0f9104a26b7f" CreationDate="2017-01-17T15:58:03.663" UserId="5871" Text="I need to write a function (in Javascript) that accepts the endpoints of a line segment and an additional point and returns coordinates for the point relative to the start point. So, based on this picture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1,y1, x2,y2, xp,yp)&#xD;&#xA;&#xD;&#xA;returns `[xp',yp']` where xp' is the distance from (xp,yp) along a line perpendicular to the line segment, and yp' is the distance from (x1,y1) to the point where that perpendicular line intersects the line segment.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TESQW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10574" PostHistoryTypeId="1" PostId="4565" RevisionGUID="cf1783e4-ca6d-4c0b-91f4-0f9104a26b7f" CreationDate="2017-01-17T15:58:03.663" UserId="5871" Text="translate coordinates relative to line segment" ContentLicense="CC BY-SA 3.0" />
  <row Id="10575" PostHistoryTypeId="3" PostId="4565" RevisionGUID="cf1783e4-ca6d-4c0b-91f4-0f9104a26b7f" CreationDate="2017-01-17T15:58:03.663" UserId="5871" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10576" PostHistoryTypeId="5" PostId="4565" RevisionGUID="e44408f1-baa1-49fc-aa58-8eee30c3b657" CreationDate="2017-01-17T16:13:50.653" UserId="5871" Comment="added 392 characters in body" Text="I need to write a function (in Javascript) that accepts the endpoints of a line segment and an additional point and returns coordinates for the point relative to the start point. So, based on this picture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1,y1, x2,y2, xp,yp)&#xD;&#xA;&#xD;&#xA;returns `[xp',yp']` where xp' is the distance from (xp,yp) along a line perpendicular to the line segment, and yp' is the distance from (x1,y1) to the point where that perpendicular line intersects the line segment.&#xD;&#xA;&#xD;&#xA;What I've tried so far:&#xD;&#xA;&#xD;&#xA;    function rotateRad(cx, cy, x, y, radians) {&#xD;&#xA;        var cos = Math.cos(radians),&#xD;&#xA;            sin = Math.sin(radians),&#xD;&#xA;            nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,&#xD;&#xA;            ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;&#xD;&#xA;        return [nx, ny];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [xp', yp'] = rotateRad(x1,y1, xp, yp, Math.atan2(y2,x2) / (Math.PI/180));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TESQW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10577" PostHistoryTypeId="5" PostId="4565" RevisionGUID="44e8991d-5e77-4214-bbe8-17615fa05da1" CreationDate="2017-01-17T16:20:12.840" UserId="5871" Comment="added 97 characters in body" Text="I need to write a function (in Javascript) that accepts the endpoints of a line segment and an additional point and returns coordinates for the point relative to the start point. So, based on this picture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1,y1, x2,y2, xp,yp)&#xD;&#xA;&#xD;&#xA;returns `[xp',yp']` where xp' is the distance from (xp,yp) along a line perpendicular to the line segment, and yp' is the distance from (x1,y1) to the point where that perpendicular line intersects the line segment.&#xD;&#xA;&#xD;&#xA;What I've tried so far:&#xD;&#xA;&#xD;&#xA;    function rotateRad(cx, cy, x, y, radians) {&#xD;&#xA;        var cos = Math.cos(radians),&#xD;&#xA;            sin = Math.sin(radians),&#xD;&#xA;            nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,&#xD;&#xA;            ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;&#xD;&#xA;        return [nx, ny];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [xp', yp'] = rotateRad(x1,y1, xp, yp, Math.atan2(y2,x2) / (Math.PI/180));&#xD;&#xA;&#xD;&#xA;I don't really understand the function; got it from http://stackoverflow.com/a/17411276/1368860&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TESQW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10579" PostHistoryTypeId="5" PostId="4510" RevisionGUID="e85c9a80-0723-4a34-aa6c-470b7cdfdd3c" CreationDate="2017-01-17T17:23:13.810" UserId="231" Comment="Minor typos" Text="I have trouble understanding the following Javascript code.&#xD;&#xA;&#xD;&#xA;It calculates, given a mesh described by its vertices `vs` and indices `ind`, the normals for each vertex. The mesh faces are a triangle list, and are oriented counterclockwise.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: javascript --&gt;&#xD;&#xA;&#xD;&#xA;    utilsObject.prototype.calculateNormals = function(vs, ind){&#xD;&#xA;        var x=0; &#xD;&#xA;        var y=1;&#xD;&#xA;        var z=2;&#xD;&#xA;        &#xD;&#xA;        var ns = [];&#xD;&#xA;        for(var i=0;i&lt;vs.length;i++){ //for each vertex, initialize normal x, normal y, normal z&#xD;&#xA;            ns[i]=0.0;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        for(var i=0;i&lt;ind.length;i=i+3){ //we work on triads of vertices to calculate normals so i = i+3 (i = indices index)&#xD;&#xA;            var v1 = [];&#xD;&#xA;            var v2 = [];&#xD;&#xA;            var normal = [];&#xD;&#xA;&#xD;&#xA;            //p1 - p0&#xD;&#xA;            v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;            v1[y] = vs[3*ind[i+1]+y] - vs[3*ind[i]+y];&#xD;&#xA;            v1[z] = vs[3*ind[i+1]+z] - vs[3*ind[i]+z];&#xD;&#xA;&#xD;&#xA;            // p0 - p1&#xD;&#xA;            v2[x] = vs[3*ind[i+2]+x] - vs[3*ind[i+1]+x];&#xD;&#xA;            v2[y] = vs[3*ind[i+2]+y] - vs[3*ind[i+1]+y];&#xD;&#xA;            v2[z] = vs[3*ind[i+2]+z] - vs[3*ind[i+1]+z];            &#xD;&#xA;&#xD;&#xA;            //cross product by Sarrus Rule&#xD;&#xA;            normal[x] = v1[y]*v2[z] - v1[z]*v2[y];&#xD;&#xA;            normal[y] = v1[z]*v2[x] - v1[x]*v2[z];&#xD;&#xA;            normal[z] = v1[x]*v2[y] - v1[y]*v2[x];&#xD;&#xA;            &#xD;&#xA;            for(j=0;j&lt;3;j++){ //update the normals of that triangle: sum of vectors&#xD;&#xA;                ns[3*ind[i+j]+x] =  ns[3*ind[i+j]+x] + normal[x];&#xD;&#xA;                ns[3*ind[i+j]+y] =  ns[3*ind[i+j]+y] + normal[y];&#xD;&#xA;                ns[3*ind[i+j]+z] =  ns[3*ind[i+j]+z] + normal[z];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;How does this function work? For example, could you explain the use of indices in the instruction:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: javascript --&gt;&#xD;&#xA;&#xD;&#xA;    v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;&#xD;&#xA;Rather than a high-level explanation, I am interested in the logic of the implementation details." ContentLicense="CC BY-SA 3.0" />
  <row Id="10580" PostHistoryTypeId="4" PostId="4510" RevisionGUID="e85c9a80-0723-4a34-aa6c-470b7cdfdd3c" CreationDate="2017-01-17T17:23:13.810" UserId="231" Comment="Minor typos" Text="How does this function calculate normals of a mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10581" PostHistoryTypeId="2" PostId="4566" RevisionGUID="d31067b7-0dcd-4213-92f9-aea1e0bbf59f" CreationDate="2017-01-17T17:54:11.663" UserId="5841" Text="Ratchet Freak's answer might work. I'm not sure, I didn't spend much time on it because I didn't know how to create the quaternion from the dot and cross product as described.&#xD;&#xA;&#xD;&#xA;What we ended up doing was:&#xD;&#xA;&#xD;&#xA;- Project the center of the gizmo to screen space.&#xD;&#xA;&#xD;&#xA;- Get the angle between the vectors GizmoToLastMouse and GizmoToCurrentMouse using the formula acos(Dot(GizmoToLastMouse, GizmoToCurrentMouse) / (GizmoToLastMouse.Length() * GizmoToCurrentMouse.Length()))&#xD;&#xA;&#xD;&#xA;- Get the sign of the angle by taking the cross of the GizmoToLastMouse and GizmoToCurrentMouse and dotting it with the screen normal.&#xD;&#xA;&#xD;&#xA;- Get another sign (times 1.0f or -1.0f) based on the orientation of the gizmo, by taking the dot product between the rotated axis and a vector from the center of the gizmo to the camera&#xD;&#xA;&#xD;&#xA;- Apply the rotation based on the angle and the two signs to the appropriate axis&#xD;&#xA;&#xD;&#xA;There might be a better way to do it, but this works pretty well for our needs." ContentLicense="CC BY-SA 3.0" />
  <row Id="10585" PostHistoryTypeId="50" PostId="4274" RevisionGUID="d0df2468-e7ca-4096-a93d-f26c229430d9" CreationDate="2017-01-17T18:21:12.723" UserId="-1" />
  <row Id="10586" PostHistoryTypeId="2" PostId="4568" RevisionGUID="af0afa1d-f6e0-4ab7-944e-c80dca3d8794" CreationDate="2017-01-17T20:27:31.020" UserId="5852" Text="I know that when you call glVertexAttribPointer, you are specifying how the buffer currently binded should take its own data. But if you can have binded one buffer per type (Let's say GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER) then, Are you specifying two buffers simultaneously? In [this][1] tutorial says:&#xD;&#xA;&#xD;&#xA;&gt; glVertexAttribPointer always refers to whatever buffer is bound to&#xD;&#xA;&gt; GL_ARRAY_BUFFER at the time that this function is called. Therefore it&#xD;&#xA;&gt; does not take a buffer object handle; it simply uses the handle we&#xD;&#xA;&gt; bound previously.&#xD;&#xA;&#xD;&#xA;If glVertexAttribPointer refers to the GL_ARRAY_BUFFER buffer binded, How I call glVertexAttribPointer for a GL_ELEMENT_ARRAY_BUFFER buffer?&#xD;&#xA;&#xD;&#xA;  [1]: http://alfonse.bitbucket.org/oldtut/Basics/Tut01%20Following%20the%20Data.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="10587" PostHistoryTypeId="1" PostId="4568" RevisionGUID="af0afa1d-f6e0-4ab7-944e-c80dca3d8794" CreationDate="2017-01-17T20:27:31.020" UserId="5852" Text="How glVertexAttribPointer works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10588" PostHistoryTypeId="3" PostId="4568" RevisionGUID="af0afa1d-f6e0-4ab7-944e-c80dca3d8794" CreationDate="2017-01-17T20:27:31.020" UserId="5852" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10589" PostHistoryTypeId="5" PostId="4568" RevisionGUID="56dcd5f9-2d77-43a0-b870-0457ff06171a" CreationDate="2017-01-17T20:37:53.040" UserId="5852" Comment="added 12 characters in body" Text="I know that when you call glVertexAttribPointer, you are specifying how the buffer currently binded should take its own data. But if you can have binded one buffer per type (Let's say GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER) then, Are you specifying two buffers simultaneously? In [this][1] tutorial says:&#xD;&#xA;&#xD;&#xA;&gt; glVertexAttribPointer always refers to whatever buffer is bound to&#xD;&#xA;&gt; GL_ARRAY_BUFFER at the time that this function is called. Therefore it&#xD;&#xA;&gt; does not take a buffer object handle; it simply uses the handle we&#xD;&#xA;&gt; bound previously.&#xD;&#xA;&#xD;&#xA;If glVertexAttribPointer refers to the GL_ARRAY_BUFFER buffer currently binded, How I call glVertexAttribPointer for the GL_ELEMENT_ARRAY_BUFFER buffer?&#xD;&#xA;&#xD;&#xA;  [1]: http://alfonse.bitbucket.org/oldtut/Basics/Tut01%20Following%20the%20Data.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="10591" PostHistoryTypeId="2" PostId="4569" RevisionGUID="21d3c56e-8a33-4282-9ed5-77a738122839" CreationDate="2017-01-17T21:31:44.923" UserId="5874" Text="I'm running a Python program whose GUI uses OpenGL. I'm getting all sorts of graphics error messages. I want to check the OpenGL version to make sure it's all good, but the OpenGL Extensions Viewer doesn't work. Even as admin, the extensions viewer just fails when I try to open it (and the install fails when I'm not admin).&#xD;&#xA;&#xD;&#xA;So, how do I access info about OpenGL's current status on my machine without using that program? I looked all over and didn't see any real alternatives. I'm using Windows 7, Intel Xeon CPU, X5680 3.33GHz (x2), 24 GB RAM, NVIDIA Quadro 4000.&#xD;&#xA;&#xD;&#xA;Keep in mind that I'm not an OpenGL programmer -- I work in Python and I use PyQt etc. So, I'd like to find a solution to this without needing a Visual tutorial...&#xD;&#xA;&#xD;&#xA;Thanks, and sorry if this question is too basic/in the wrong place!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10592" PostHistoryTypeId="1" PostId="4569" RevisionGUID="21d3c56e-8a33-4282-9ed5-77a738122839" CreationDate="2017-01-17T21:31:44.923" UserId="5874" Text="Super basic question: OpenGL version/install issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="10593" PostHistoryTypeId="3" PostId="4569" RevisionGUID="21d3c56e-8a33-4282-9ed5-77a738122839" CreationDate="2017-01-17T21:31:44.923" UserId="5874" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10594" PostHistoryTypeId="2" PostId="4570" RevisionGUID="eb778a88-0cf5-4440-b6f6-ff892b40586f" CreationDate="2017-01-17T21:52:15.573" UserId="48" Text="&gt; How I call glVertexAttribPointer for the GL_ELEMENT_ARRAY_BUFFER buffer?&#xD;&#xA;&#xD;&#xA;You don't. The element array buffer is used to store vertex indices, not vertex attribute data and therefore it doesn't have attribute pointers. The count, size, and offset for index data is specified in the draw call, e.g. `glDrawElements`." ContentLicense="CC BY-SA 3.0" />
  <row Id="10595" PostHistoryTypeId="5" PostId="4565" RevisionGUID="884bd570-442c-4eb5-aa73-cf2f346dbd68" CreationDate="2017-01-17T22:00:35.087" UserId="5871" Comment="deleted 10 characters in body" Text="I need to write a function (in Javascript) that accepts the endpoints of a line segment and an additional point and returns coordinates for the point relative to the start point. So, based on this picture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1,y1, x2,y2, xp,yp)&#xD;&#xA;&#xD;&#xA;returns `[xp',yp']` where xp' is the distance from (xp,yp) along a line perpendicular to the line segment, and yp' is the distance from (x1,y1) to the point where that perpendicular line intersects the line segment.&#xD;&#xA;&#xD;&#xA;What I've tried so far:&#xD;&#xA;&#xD;&#xA;    function rotateRad(cx, cy, x, y, radians) {&#xD;&#xA;        var cos = Math.cos(radians),&#xD;&#xA;            sin = Math.sin(radians),&#xD;&#xA;            nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,&#xD;&#xA;            ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;&#xD;&#xA;        return [nx, ny];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [xp', yp'] = rotateRad(x1,y1, xp, yp, Math.atan2(y2-y1,x2-x1));&#xD;&#xA;&#xD;&#xA;I don't really understand the function; got it from http://stackoverflow.com/a/17411276/1368860&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TESQW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10599" PostHistoryTypeId="5" PostId="4292" RevisionGUID="4313ae73-8140-4a99-9623-e04c929f6ee3" CreationDate="2017-01-18T13:01:56.667" UserDisplayName="user4718" Comment="added 471 characters in body" Text="From what I've learnt, since I'm also a student, is that you want to work with $4 \times 4$ matrices in order to treat rotations, scaling and translations in the same way, that is, _multiplying by a matrix_ (i.e., a $4 \times 4$ matrix).&#xD;&#xA;&#xD;&#xA;Remember that without these $4 \times 4$ matrices, translations would be represented by summing with a vector, whereas rotations and scaling are represented using multiplications with respectively a vector and a scalar factor.&#xD;&#xA;&#xD;&#xA;Now the question is: _how do we pass from a 3D coordinate systems to a 4D one_? The answer is &quot;**homogenous coordinates**&quot;. &#xD;&#xA;&#xD;&#xA;So, what does it mean? We construct $4 \times 4$ matrices to represent rotations, scaling and translation, so that we only use matrix multiplications to represent transformations (e.g., rotations, scaling, etc). How we construct them individually, it's more specific, but you can have a look it on the web. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At this point, we have $4 \times 4$ matrices and 3D vectors, not useful yet, because you can't multiply $4 \times 4$ matrices and $3D$ vectors, since the dimensions do not match. That's why, when we work with homegeneous coordinates, we also need to convert our given 3D points into corresponding 4D ones. &#xD;&#xA;&#xD;&#xA;_How do we do it?_&#xD;&#xA;&#xD;&#xA;We distinguish between _direction_ and _position_ vectors. Direction vectors, as the name suggests, have a direction at which they are pointing; we also care about their length, but they are not affected by translations, since we don't care about their position. Position vectors (or simply &quot;points&quot;) can be translated or moved around; they are usually represented with respect to the origin, i.e. as a vector from the origin to the point itself.&#xD;&#xA;&#xD;&#xA;We transform 3D direction vectors by adding a $0$ as the $4$th coordinate of the corresponding homogeneous vector: we add a zero because this basically eliminates the effect of translations. We do a similar thing with position vectors, but instead of a $0$ we add a $1$, for the opposite reason.&#xD;&#xA;&#xD;&#xA;For example, if we have a $3D$ direction vector $v = \begin{pmatrix} v_1 \\ v_2 \\ v_3\end{pmatrix}$, we transform it by doing $v' = \begin{pmatrix} v_1 \\ v_2 \\ v_3 \\ 0\end{pmatrix}$. Similarly, if we had a point vector $u = \begin{pmatrix} u_1 \\ u_2 \\ u_3\end{pmatrix}$ we would transform it to $u' = \begin{pmatrix} u_1 \\ u_2 \\ u_3 \\ 1\end{pmatrix}$&#xD;&#xA;&#xD;&#xA;Note: to convert from homogeneous coordinates back to corresponding $3D$ ones, you can't simply remove the $4th$ coordinate ... ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10600" PostHistoryTypeId="5" PostId="4292" RevisionGUID="65689475-201a-4038-8e74-14d747277d3e" CreationDate="2017-01-18T13:09:35.250" UserDisplayName="user4718" Comment="added 53 characters in body" Text="From what I've learnt, since I'm also a student, is that you want to work with $4 \times 4$ matrices in order to treat rotations, scaling and translations in the same way, that is, _multiplying by a matrix_ (i.e., a $4 \times 4$ matrix).&#xD;&#xA;&#xD;&#xA;Remember that without these $4 \times 4$ matrices, translations would be represented by summing with a vector, whereas rotations and scaling are represented using multiplications with respectively a vector and a scalar factor.&#xD;&#xA;&#xD;&#xA;Now the question is: _how do we pass from a 3D coordinate systems to a 4D one_? The answer is &quot;**homogenous coordinates**&quot;. &#xD;&#xA;&#xD;&#xA;So, what does it mean? We construct $4 \times 4$ matrices to represent rotations, scaling and translation, so that we only use matrix multiplications to represent transformations (e.g., rotations, scaling, etc). How we construct them individually, it's more specific, but you can have a look it on the web. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At this point, we have $4 \times 4$ matrices and 3D vectors, not useful yet, because you can't multiply $4 \times 4$ matrices and $3D$ vectors, since the dimensions do not match. That's why, when we work with homegeneous coordinates, we also need to convert our given 3D points into corresponding 4D ones. &#xD;&#xA;&#xD;&#xA;_How do we do it?_&#xD;&#xA;&#xD;&#xA;We distinguish between _direction_ and _position_ vectors. Direction vectors, as the name suggests, have a direction at which they are pointing; we also care about their length, but they are not affected by translations, since we don't care about their position. Position vectors (or simply &quot;points&quot;) can be translated or moved around; they are usually represented with respect to the origin, i.e. as a vector from the origin to the point itself.&#xD;&#xA;&#xD;&#xA;We transform 3D direction vectors by adding a $0$ as the $4$th coordinate of the corresponding homogeneous vector: we add a zero because this basically eliminates the effect of translations. We do a similar thing with position vectors, but instead of a $0$ we add a $1$, for the opposite reason.&#xD;&#xA;&#xD;&#xA;For example, if we have a $3D$ direction vector $v = \begin{pmatrix} v_1 \\ v_2 \\ v_3\end{pmatrix}$, we transform it by doing $v' = \begin{pmatrix} v_1 \\ v_2 \\ v_3 \\ 0\end{pmatrix}$. Similarly, if we had a point vector $u = \begin{pmatrix} u_1 \\ u_2 \\ u_3\end{pmatrix}$ we would transform it to $u' = \begin{pmatrix} u_1 \\ u_2 \\ u_3 \\ 1\end{pmatrix}$&#xD;&#xA;&#xD;&#xA;Note: to convert from homogeneous coordinates back to corresponding $3D$ ones, you can't simply remove the $4th$ coordinate, unless it's **still** equal to $1$ (or $0$ respectively).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10601" PostHistoryTypeId="5" PostId="4566" RevisionGUID="af7c2f31-8576-45b4-873f-09ebdf8de5b4" CreationDate="2017-01-18T14:39:24.213" UserId="5841" Comment="added 13 characters in body" Text="Ratchet Freak's answer might work. I'm not sure, I didn't spend much time on it because I didn't know how to create the quaternion from the dot and cross product as described.&#xD;&#xA;&#xD;&#xA;What we ended up doing was:&#xD;&#xA;&#xD;&#xA;- Project the center of the gizmo to screen space.&#xD;&#xA;&#xD;&#xA;- Get the angle between the vectors GizmoToLastMouse and GizmoToCurrentMouse using the dot product formula: acos(Dot(GizmoToLastMouse, GizmoToCurrentMouse) / (GizmoToLastMouse.Length() * GizmoToCurrentMouse.Length()))&#xD;&#xA;&#xD;&#xA;- Get the sign of the angle by taking the cross of the GizmoToLastMouse and GizmoToCurrentMouse and dotting it with the screen normal.&#xD;&#xA;&#xD;&#xA;- Get another sign (times 1.0f or -1.0f) based on the orientation of the gizmo, by taking the dot product between the rotated axis and a vector from the center of the gizmo to the camera&#xD;&#xA;&#xD;&#xA;- Apply the rotation based on the angle and the two signs to the appropriate axis&#xD;&#xA;&#xD;&#xA;There might be a better way to do it, but this works pretty well for our needs." ContentLicense="CC BY-SA 3.0" />
  <row Id="10602" PostHistoryTypeId="2" PostId="4571" RevisionGUID="8c65c178-4602-43a9-b57f-12398d34fa61" CreationDate="2017-01-18T14:54:25.577" UserId="137" Text="A VAO holds the attribute information. This means that for each attribute it has a buffer, offset, size, type, stride and whether it's normalized. Separately from those is the element buffer binding that is set by binding the `GL_ELEMENT_ARRAY_BUFFER` while the VAO is bound.&#xD;&#xA;&#xD;&#xA;Yes that odd but the reason this is the case is because VAO's were added after VBO and EBO.&#xD;&#xA;&#xD;&#xA;In 4.5 (or with the Direct_state_access extension) you can instead use `glVertexArrayElementBuffer` to directly set the element buffer of a vao." ContentLicense="CC BY-SA 3.0" />
  <row Id="10603" PostHistoryTypeId="2" PostId="4572" RevisionGUID="5a4abeca-59ad-4072-93d8-a79bca635baf" CreationDate="2017-01-19T06:21:57.630" UserId="5256" Text="After reading about the new [Disney Diffuse BRDF][1], I have been wondering if this is currently the best Diffuse BRDF at the moment? How much more of a difference would this make compared to using a Lambertian BRDF? I have heard of other BRDFs such as Hanrahan-Krueger and Oren-Nayar, are these also better? &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/MyOOc.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10604" PostHistoryTypeId="1" PostId="4572" RevisionGUID="5a4abeca-59ad-4072-93d8-a79bca635baf" CreationDate="2017-01-19T06:21:57.630" UserId="5256" Text="Better alternatives to the Lambert BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="10605" PostHistoryTypeId="3" PostId="4572" RevisionGUID="5a4abeca-59ad-4072-93d8-a79bca635baf" CreationDate="2017-01-19T06:21:57.630" UserId="5256" Text="|brdf|physically-based|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10606" PostHistoryTypeId="2" PostId="4573" RevisionGUID="ab19ed12-48f3-4f60-8ff5-d7554524eceb" CreationDate="2017-01-19T06:45:09.883" UserId="5256" Text="I am currently following a tutorial at Scratchapixel.com on [**refraction**][1]&#xD;&#xA;&#xD;&#xA;Here is the **refract function**:&#xD;&#xA;&#xD;&#xA;    Vec3f refract(const Vec3f &amp;I, const Vec3f &amp;N, const float &amp;ior) &#xD;&#xA;    { &#xD;&#xA;        float cosi = clamp(-1, 1, dotProduct(I, N)); &#xD;&#xA;        float etai = 1, etat = ior; &#xD;&#xA;        Vec3f n = N; &#xD;&#xA;        if (cosi &lt; 0) { cosi = -cosi; } else { std::swap(etai, etat); n= -N; } &#xD;&#xA;        float eta = etai / etat; &#xD;&#xA;        float k = 1 - eta * eta * (1 - cosi * cosi); &#xD;&#xA;        return k &lt; 0 ? 0 : eta * I + (eta * cosi - sqrtf(k)) * n; &#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;**1)** I understand that if there is no total internal reflection, **first we must find the refraction direction** (`ior` is the object's index of refraction):&#xD;&#xA;&#xD;&#xA;    Vec3f refractionDirection = refract(dir, hitNormal, isect.hitObject-&gt;ior).normalize(); &#xD;&#xA;&#xD;&#xA;**2)** We then compute the **refraction ray origin** (which is the point where the ray will leave the object?) &#xD;&#xA;&#xD;&#xA;    Vec3f refractionRayOrig = outside ? hitPoint - bias : hitPoint + bias; &#xD;&#xA;**3)** Finally to get the refracted ray color we cast a ray using the `refractionDirection` &amp; `refractionRayOrig`&#xD;&#xA;&#xD;&#xA;    refractionColor = castRay(refractionRayOrig, refractionDirection, objects, lights, options, depth + 1); &#xD;&#xA;&#xD;&#xA;So far I understand how a glass block (or any other transparent object which undergoes refraction) bends the light towards the normal when entering the object and then away from the normal when exiting but **I am confused as to how refraction works or is computed when there is another object in the medium as shown in the image below.** &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel&#xD;&#xA;  [2]: https://i.stack.imgur.com/c6p4j.png&#xD;&#xA;&#xD;&#xA;So when the ray hits the object from the inside do we use a BRDF to calculate the surface properties and then that ray leaves the glass block with the refraction origin and direction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10607" PostHistoryTypeId="1" PostId="4573" RevisionGUID="ab19ed12-48f3-4f60-8ff5-d7554524eceb" CreationDate="2017-01-19T06:45:09.883" UserId="5256" Text="Refraction in a Ray Tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="10608" PostHistoryTypeId="3" PostId="4573" RevisionGUID="ab19ed12-48f3-4f60-8ff5-d7554524eceb" CreationDate="2017-01-19T06:45:09.883" UserId="5256" Text="|lighting|brdf|reflection|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10609" PostHistoryTypeId="2" PostId="4574" RevisionGUID="3183c846-5687-484f-bf47-be6a5ebdd33e" CreationDate="2017-01-19T07:52:29.097" UserId="3073" Text="You need to spawn a new ray at each IOR interface. &#xD;&#xA;&#xD;&#xA;So let's say your ray hits the surface of the glass object. You spawn a new ray from the intersection point along the new IOR direction for air-&gt;glass interfaces, this new ray is inside the glass. This ray will then either hit a solid object or the interior surface of the glass. If we hit a solid object we can light it as normal. If the ray exits the glass, you spawn a new ray again at the exit point but now using the Glass-&gt;air IOR. &#xD;&#xA;&#xD;&#xA;You can also have cases for total-internal reflection where the exiting ray is reflected back inside instead of leaving the glass, same principle applies, generate a new ray from the intersect position using the reflected direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="10610" PostHistoryTypeId="12" PostId="4574" RevisionGUID="363bfbc2-1289-4c73-927d-54cd2f6a2c32" CreationDate="2017-01-19T07:59:06.727" UserId="3073" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:3073,&quot;DisplayName&quot;:&quot;PaulHK&quot;}]}" />
  <row Id="10611" PostHistoryTypeId="13" PostId="4574" RevisionGUID="b3323762-7124-489b-afc5-f182f4e939ec" CreationDate="2017-01-19T08:04:46.663" UserId="3073" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:3073,&quot;DisplayName&quot;:&quot;PaulHK&quot;}]}" />
  <row Id="10617" PostHistoryTypeId="2" PostId="4576" RevisionGUID="418cab93-e3ad-4b2b-9365-14d60476be72" CreationDate="2017-01-19T10:59:57.347" UserId="5828" Text="I have successful developed an algorithm with the help of a Kd-tree and a simple test for overlapping lines. Here is a result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/X8Igv.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10618" PostHistoryTypeId="2" PostId="4577" RevisionGUID="cb40ee01-46cd-43ad-8712-887d33e98527" CreationDate="2017-01-19T12:50:29.113" UserId="5871" Text="I got a good answer on StackOverflow: http://stackoverflow.com/questions/41701713/translate-coordinates-relative-to-line-segment/41702475#41702475 from http://stackoverflow.com/users/1579780/giladd:&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1, y1, x2, y2, xp, yp) {&#xD;&#xA;      var dx = x2 - x1,&#xD;&#xA;          dy = y2 - y1;&#xD;&#xA;    &#xD;&#xA;      //find intersection point    &#xD;&#xA;      var k = (dy * (xp-x1) - dx * (yp-y1)) / (dy*dy + dx*dx);&#xD;&#xA;      var x4 = xp - k * dy;&#xD;&#xA;      var y4 = yp + k * dx;&#xD;&#xA;    &#xD;&#xA;      var ypt = Math.sqrt((y4-y1)*(y4-y1)+(x4-x1)*(x4-x1));&#xD;&#xA;      var xpt = distance(x1, y1, x2, y2, xp, yp);&#xD;&#xA;      return [xpt, ypt];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Distance of point from line&#xD;&#xA;    function distance(x1, y1, x2, y2, xp, yp) {&#xD;&#xA;      var dx = x2 - x1;&#xD;&#xA;      var dy = y2 - y1;&#xD;&#xA;    &#xD;&#xA;      return Math.abs(dy*xp - dx*yp + x2*y1 - y2*x1) / Math.sqrt(dy*dy + dx*dx);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10619" PostHistoryTypeId="5" PostId="4531" RevisionGUID="5e565821-812f-40e9-8f34-5086435092e8" CreationDate="2017-01-19T14:17:18.273" UserId="5399" Comment="added 90 characters in body" Text="If you are writing your own Vertex/Fragment Shader there is another additional possibility to do this. It is much more complicated but might be useful for you and/or others. Additionally it speeds up the whole drawing process since it uses only one call to a draw command. The maximum number of Viewports is defined by GL_MAX_VIEWPORTS and is usually 16. &#xD;&#xA;&#xD;&#xA;Since OpenGL 4.1 the method [glViewportArrayv][1] exists. It can define an array of Viewports. The Viewports which are created by this method have an index assigned. &#xD;&#xA;&#xD;&#xA;This index can be used in the Vertex Shader to set the Viewport to which the scene is rendered. (You have to include the &quot;*ARB_shader_viewport_layer_array*&quot; extension in the shader code)&#xD;&#xA;&#xD;&#xA;In your case I would suggest to do the following:&#xD;&#xA;&#xD;&#xA;- Store the 4 camera matrices in a Shader Storage Buffer (Array of mat4) to have them in the Vertex Shader&#xD;&#xA;- Use [indexed drawing][2], for example :[glDrawElementsInstanced][3]&#xD;&#xA;- use the build in [gl_InstanceID][4] of the Vertex Shader to access the camera matrix array&#xD;&#xA;- set the build in variable output variable gl_ViewportIndex in the Fragment Shader to the gl_InstanceID. (for details see [ARB_fragment_layer_viewport][5])&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/sdk/docs/man4/html/glViewportArray.xhtml&#xD;&#xA;  [2]: https://learnopengl.com/#!Advanced-OpenGL/Instancing&#xD;&#xA;  [3]: https://www.opengl.org/sdk/docs/man/html/glDrawElementsInstanced.xhtml&#xD;&#xA;  [4]: https://www.opengl.org/sdk/docs/man/html/gl_InstanceID.xhtml&#xD;&#xA;  [5]: https://www.opengl.org/registry/specs/ARB/fragment_layer_viewport.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="10622" PostHistoryTypeId="2" PostId="4578" RevisionGUID="2385a7c2-4ce3-43fa-a30d-4932ce23a7e0" CreationDate="2017-01-19T21:44:33.960" UserId="5882" Text="I am trying to get a normal of a triangle on a sphere, however the normal equations (straight line) give the wrong answer.&#xD;&#xA;&#xD;&#xA;For the points:&#xD;&#xA;&#xD;&#xA;-986.786743,-93.348259,-132.439041 &#xD;&#xA;210.731644,-534.785583,-818.290039&#xD;&#xA; 637.734985,-449.826904,-553.501648 &#xD;&#xA;&#xD;&#xA;on a radius 1000 sphere, the average point (straight line) is (-0.074536,-0.580873,-0.810574) * 1000, which is visibly incorrect on a sphere.&#xD;&#xA;&#xD;&#xA;The triangle's normal normalized to distance 1000 gives: (0.086455,0.899604,-0.428062) * 1000 which is different from the average value above (which would have also given a normal) and also far off from the spherical triangle." ContentLicense="CC BY-SA 3.0" />
  <row Id="10623" PostHistoryTypeId="1" PostId="4578" RevisionGUID="2385a7c2-4ce3-43fa-a30d-4932ce23a7e0" CreationDate="2017-01-19T21:44:33.960" UserId="5882" Text="Average point on sphere between 3 other points (spherical triangle)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10624" PostHistoryTypeId="3" PostId="4578" RevisionGUID="2385a7c2-4ce3-43fa-a30d-4932ce23a7e0" CreationDate="2017-01-19T21:44:33.960" UserId="5882" Text="|computational-geometry|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10625" PostHistoryTypeId="2" PostId="4579" RevisionGUID="869a50f0-e828-4d63-9244-4fd83023ecd9" CreationDate="2017-01-19T22:21:26.007" UserId="1608" Text="this is an interesting question (and I am actually an author on Scratchapixel so I can maybe help on that one)). &#xD;&#xA;&#xD;&#xA;Things go as follows:&#xD;&#xA;&#xD;&#xA;  1. you cast the primary ray into the scene&#xD;&#xA;  2. the ray hits the glass which is a refractive-reflective/transparent material&#xD;&#xA;  3. you compute and cast two rays from the point of intersection: a reflective ray and a refractive ray&#xD;&#xA;  4. if the refractive ray hits an object contained in the transparent object (the glass) then you need to shade that object too. So if it's a plastic material, compute the result of that shader (including the lighting, so loop over all lights and add their contribution, etc.)&#xD;&#xA;  5. the color at the intersection point can finally be computed as a mix between the reflection and the refraction color (where as the mix is driven by the fresnel effect).&#xD;&#xA;&#xD;&#xA;Now that works but this is essentially **wrong**.&#xD;&#xA;&#xD;&#xA;Why? Because in fact light rays too are bent by say glass and water. So in fact when you cast a shadow ray from a point on the pen (which is water say) and the light, this ray direction is fact wrong since. You should account for refraction (and reflection) but this is impossible to do with what this algorithm/approach.&#xD;&#xA;&#xD;&#xA;Though in general this gives acceptable results so no one cares much but if your goal is really a physically plausible image then this approach is wrong.&#xD;&#xA;&#xD;&#xA;A solution to this maybe is to use photon mapping, where photons of light are cast from the light into the scene in a pre-pass. Thus when a light-photon hits the glass/water surface it will bent due to the law of refraction and eventually it will be &quot;deposited&quot; onto the pen. This is a bit hard to explain here but hopefully there will be a lesson on Scratchapixel about this in the future. Hope it helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="10626" PostHistoryTypeId="2" PostId="4580" RevisionGUID="eea6d38f-653c-42e6-8e37-c5239b025dd6" CreationDate="2017-01-19T22:32:22.790" UserId="56" Text="If i read you right, you have a triangular patch which is on the surface of a sphere - so the triangle isn't really a true triangle in that it isn't flat, but instead is just made up of 3 points on a sphere connected by lines across the spheres surface.&#xD;&#xA;&#xD;&#xA;Also if I understand you correctly, you have a point on this triangle that you want to get the normal at.&#xD;&#xA;&#xD;&#xA;If all that is right, the way to get the normal is to subject subtract the origin from your point on the triangle (since it is also a point on the sphere) and normalize it.&#xD;&#xA;&#xD;&#xA;The normal at any point on a sphere is parallel to the point from the center of the sphere to that point on the surface. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10627" PostHistoryTypeId="5" PostId="4578" RevisionGUID="e91c9428-db66-410a-a0a5-de0155050042" CreationDate="2017-01-19T22:46:46.883" UserId="231" Comment="Make coordinates more readable" Text="I am trying to get a normal of a triangle on a sphere, however the normal equations (straight line) give the wrong answer.&#xD;&#xA;&#xD;&#xA;For the points:&#xD;&#xA;&#xD;&#xA;$$(-986.786743, -93.348259, -132.439041)\\&#xD;&#xA;(210.731644, -534.785583, -818.290039)\\&#xD;&#xA;(637.734985, -449.826904, -553.501648)$$&#xD;&#xA;&#xD;&#xA;on a radius $1000$ sphere, the average point (straight line) is $(-0.074536, -0.580873, -0.810574) * 1000$, which is visibly incorrect on a sphere.&#xD;&#xA;&#xD;&#xA;The triangle's normal normalized to distance $1000$ gives: $(0.086455, 0.899604, -0.428062) * 1000$ which is different from the average value above (which would have also given a normal) and also far off from the spherical triangle.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10629" PostHistoryTypeId="2" PostId="4581" RevisionGUID="354bcf86-5d83-483c-bf45-4d3c0a83bc7c" CreationDate="2017-01-20T00:51:17.867" UserId="5884" Text="The triangle spans from one side of the sphere to the other so using straight line equations is very inaccurate.&#xD;&#xA;&#xD;&#xA;I think I can figure it out like so:&#xD;&#xA;&#xD;&#xA;The centroid of a triangle is where its medians intersect: http://www.mathopenref.com/trianglemedians.html&#xD;&#xA;&#xD;&#xA;So use the equations given elsewhere to find the shortest path between two points on a sphere for all the vertices, and get the intersection between two midpoints on those with the opposing vertices to get two curves along the sphere and their point intersection.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10630" PostHistoryTypeId="5" PostId="4579" RevisionGUID="d1ebfaa0-f7d1-4b77-99a4-4621a5d25f45" CreationDate="2017-01-20T08:27:30.037" UserId="1608" Comment="added 118 characters in body" Text="this is an interesting question (and I am actually an author on Scratchapixel so I can maybe help on that one)). &#xD;&#xA;&#xD;&#xA;Things go as follows:&#xD;&#xA;&#xD;&#xA;  1. you cast the primary ray into the scene&#xD;&#xA;  2. the ray hits the glass which is a refractive-reflective/transparent material&#xD;&#xA;  3. you compute and cast two rays from the point of intersection: a reflective ray and a refractive ray&#xD;&#xA;  4. if the refractive ray hits an object contained in the transparent object (the glass) then you need to shade that object too. So if it's a plastic material, compute the result of that shader (including the lighting, so loop over all lights and add their contribution, etc.)&#xD;&#xA;  5. the color at the intersection point can finally be computed as a mix between the reflection and the refraction color (where as the mix is driven by the fresnel effect).&#xD;&#xA;&#xD;&#xA;Now that works but this is essentially **wrong**.&#xD;&#xA;&#xD;&#xA;Why? Because in fact light rays too are bent by say glass and water. So in fact when you cast a shadow ray from a point on the pen in the direction of the light, this ray direction is in fact wrong, since you should account for refraction and reflection (the ray should be bent when it goes from one medium to another in this case from water to air) but this is impossible to do with this algorithm/approach.&#xD;&#xA;&#xD;&#xA;Though in general this gives acceptable results so no one cares much but if your goal is really a physically plausible image then this approach is wrong.&#xD;&#xA;&#xD;&#xA;A solution to this maybe is to use photon mapping, where photons of light are cast from the light into the scene in a pre-pass. Thus when a light-photon hits the glass/water surface it will bent due to the law of refraction and eventually it will be &quot;deposited&quot; onto the pen. This is a bit hard to explain here but hopefully there will be a lesson on Scratchapixel about this in the future. Hope it helps." ContentLicense="CC BY-SA 3.0" />
  <row Id="10631" PostHistoryTypeId="5" PostId="4579" RevisionGUID="22f274a1-ed06-4341-9b93-9a67bdd6c99c" CreationDate="2017-01-20T08:42:24.863" UserId="1608" Comment="added 118 characters in body" Text="this is an interesting question (and I am actually an author on Scratchapixel so I can maybe help on that one)). &#xD;&#xA;&#xD;&#xA;Things go as follows:&#xD;&#xA;&#xD;&#xA;  1. you cast the primary ray into the scene&#xD;&#xA;  2. the ray hits the glass which is a refractive-reflective/transparent material&#xD;&#xA;  3. you compute and cast two rays from the point of intersection: a reflective ray and a refractive ray&#xD;&#xA;  4. if the refractive ray hits an object contained in the transparent object (the glass) then you need to shade that object too. So if it's a plastic material, compute the result of that shader (including the lighting, so loop over all lights and add their contribution, etc.)&#xD;&#xA;  5. the color at the intersection point can finally be computed as a mix between the reflection and the refraction color (where as the mix is driven by the fresnel effect).&#xD;&#xA;&#xD;&#xA;Now that works but this is essentially **wrong**.&#xD;&#xA;&#xD;&#xA;Why? Because in fact light rays too are bent by say glass and water. So in fact when you cast a shadow ray from a point on the pen in the direction of the light, this ray direction is in fact wrong, since you should account for refraction and reflection (the ray should be bent when it goes from one medium to another in this case from water to air) but this is impossible to do with this algorithm/approach.&#xD;&#xA;&#xD;&#xA;Though in general this gives acceptable results so no one cares much but if your goal is really a physically plausible image then this approach is wrong.&#xD;&#xA;&#xD;&#xA;A solution to this maybe is to use photon mapping, where photons of light are cast from the light into the scene in a pre-pass. Thus when a light-photon hits the glass/water surface it will bent due to the law of refraction and eventually it will be &quot;deposited&quot; onto the pen. This is a bit hard to explain here but hopefully there will be a lesson on Scratchapixel about this in the future. Hope it helps.&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;*&gt; Thanks for clarifying, I had one other issue though. In the source code provided on the website for that lesson there doesn't seem to be code present to spawn a ray when the light ray leaves the glass cylinder. Is this unnescessary or is it actually already present? If it is could you point out where in the code?* &#xD;&#xA;&#xD;&#xA;Hum it seems like my explanation wasn't clear if you ask this question. When the refractive ray hits the surface of the pen you need to compute the color of the pen at that intersection point (where the refractive ray intersected the pen's geometry). Now the pen is made out of wood for example which is for the sake of simplicity is a diffuse material only (no specular). So in order to compute the color of the pen at the intersection point, you simply execute the traditional illumination loop:&#xD;&#xA;&#xD;&#xA;    Vec3f computePenColor(const Vec3f&amp; objectColor, const Vec3f&amp; intersectionPoint, normalAtIntersection) {&#xD;&#xA;        Vec3f shadedPontColor = 0;&#xD;&#xA;        // loop over all lights in the scene to cadd their contribution&#xD;&#xA;        for (i = 0; i &lt; scene.lights.size(); ++i) {&#xD;&#xA;            Light currentLight = scene.lights[i];&#xD;&#xA;            // let's say this light source is a point light source&#xD;&#xA;            Vec3f lightDirection = currentLight.position - intersectionPoint;&#xD;&#xA;            // this cast a shadow ray from the shaded point to the light position&#xD;&#xA;            // if this ray intersects an object along the way then this point is in the shadow of this light and the function returns true&#xD;&#xA;            bool shadow = castShadowRay(lightDirection.length(), lightDirection.normalize());&#xD;&#xA;            if (!shadow) {&#xD;&#xA;                shadedPointColor += max(0, normalAtIntersection.dot(lightDirection)) * currentLight-&gt;intensity * currentLight-&gt;color; &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return shadedPointColor * objectColor;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10632" PostHistoryTypeId="5" PostId="4579" RevisionGUID="ba2a6c05-28fe-4601-8a55-bb04a23f3ef9" CreationDate="2017-01-20T08:50:59.700" UserId="1608" Comment="added 118 characters in body" Text="this is an interesting question (and I am actually an author on Scratchapixel so I can maybe help on that one)). &#xD;&#xA;&#xD;&#xA;Things go as follows:&#xD;&#xA;&#xD;&#xA;  1. you cast the primary ray into the scene&#xD;&#xA;  2. the ray hits the glass which is a refractive-reflective/transparent material&#xD;&#xA;  3. you compute and cast two rays from the point of intersection: a reflective ray and a refractive ray&#xD;&#xA;  4. if the refractive ray hits an object contained in the transparent object (the glass) then you need to shade that object too. So if it's a plastic material, compute the result of that shader (including the lighting, so loop over all lights and add their contribution, etc.)&#xD;&#xA;  5. the color at the intersection point can finally be computed as a mix between the reflection and the refraction color (where as the mix is driven by the fresnel effect).&#xD;&#xA;&#xD;&#xA;Now that works but this is essentially **wrong**.&#xD;&#xA;&#xD;&#xA;Why? Because in fact light rays too are bent by say glass and water. So in fact when you cast a shadow ray from a point on the pen in the direction of the light, this ray direction is in fact wrong, since you should account for refraction and reflection (the ray should be bent when it goes from one medium to another in this case from water to air) but this is impossible to do with this algorithm/approach.&#xD;&#xA;&#xD;&#xA;Though in general this gives acceptable results so no one cares much but if your goal is really a physically plausible image then this approach is wrong.&#xD;&#xA;&#xD;&#xA;A solution to this maybe is to use photon mapping, where photons of light are cast from the light into the scene in a pre-pass. Thus when a light-photon hits the glass/water surface it will bent due to the law of refraction and eventually it will be &quot;deposited&quot; onto the pen. This is a bit hard to explain here but hopefully there will be a lesson on Scratchapixel about this in the future. Hope it helps.&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;*&gt; Thanks for clarifying, I had one other issue though. In the source code provided on the website for that lesson there doesn't seem to be code present to spawn a ray when the light ray leaves the glass cylinder. Is this unnescessary or is it actually already present? If it is could you point out where in the code?* &#xD;&#xA;&#xD;&#xA;Hum it seems like my explanation wasn't clear if you ask this question. When the refractive ray hits the surface of the pen you need to compute the color of the pen at that intersection point (where the refractive ray intersected the pen's geometry). Now the pen is made out of wood for example which is for the sake of simplicity is a diffuse material only (no specular). So in order to compute the color of the pen at the intersection point, you simply execute the traditional illumination loop:&#xD;&#xA;&#xD;&#xA;    Vec3f computePenColor(const Vec3f&amp; objectColor, const Vec3f&amp; intersectionPoint, normalAtIntersection) {&#xD;&#xA;        Vec3f shadedPointColor = 0;&#xD;&#xA;        // loop over all lights in the scene to cadd their contribution&#xD;&#xA;        for (i = 0; i &lt; scene.lights.size(); ++i) {&#xD;&#xA;            Light currentLight = scene.lights[i];&#xD;&#xA;            // let's say this light source is a point light source&#xD;&#xA;            Vec3f lightDirection = currentLight.position - intersectionPoint;&#xD;&#xA;            // this cast a shadow ray from the shaded point to the light position&#xD;&#xA;            // if this ray intersects an object along the way then this point is in the shadow of this light and the function returns true&#xD;&#xA;            bool shadow = castShadowRay(lightDirection.length(), lightDirection.normalize());&#xD;&#xA;            // this point is not in the shadow of the light so add its contribution&#xD;&#xA;            if (!shadow) {&#xD;&#xA;                // the object is diffuse so apply cosine law only&#xD;&#xA;                shadedPointColor += max(0, normalAtIntersection.dot(lightDirection)) * currentLight-&gt;intensity * currentLight-&gt;color; &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return shadedPointColor * objectColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So maybe as you can see more clearly from this example, is that when I say &quot;cast a ray from the point of intersection to the light&quot; I mean cast a shadow ray. This shadow ray helps to determine if the shaded point is in the shadow of that light. If not, then you can add the contribution of that light to the shaded point.&#xD;&#xA;&#xD;&#xA;Now you can also see that the direction of this shadow ray is computed as the position of the point on the pen (the intersection point or shaded point) to the light position (we assume a point light source here for simplicity). So this is a **straight line** between the point on the pen and the light.&#xD;&#xA;&#xD;&#xA;But this where things are wrong. This **shoudn't** be a straight line, since when the &quot;shadow ray&quot; (which is also a light ray but we go from the point on the pen to the light rather than from the light to the pen, but in essence they are the same thing) exits the water volume it should be bent due to refraction (and part of it should be reflected to). You can compute this new direction if you wish, but then if the shadow ray is bent when it leaves the volume of water then it won't travel in the direction of the light anymore (as showed in the pic below), so you can't use it as a shadow or light ray any longer.&#xD;&#xA;&#xD;&#xA;So this algorithm that consists of looping over the lights and casting shadow ray can't be used if you **really** want to account for light ray bending due to reflection and refraction. Though as I said few people care about that because in reality, ignoring this fact, doesn't make much of a visual difference in 99% of cases. And as I pointed out, the solution to **get it right** if really needed is something like photon mapping where photon of lights are cast from the light into the scene into a pre-pass, which allows to follow the paths of light rays into the scene as they are being bent by refractive/reflective surfaces. But photon mapping is a rather complex algorithm to implement." ContentLicense="CC BY-SA 3.0" />
  <row Id="10633" PostHistoryTypeId="5" PostId="4579" RevisionGUID="54a4c7c0-1e57-48fe-9082-1b976f6e6c4c" CreationDate="2017-01-20T08:56:55.633" UserId="1608" Comment="deleted 3 characters in body" Text="this is an interesting question (and I am actually an author on Scratchapixel so I can maybe help on that one)). &#xD;&#xA;&#xD;&#xA;Things go as follows:&#xD;&#xA;&#xD;&#xA;  1. you cast the primary ray into the scene&#xD;&#xA;  2. the ray hits the glass which is a refractive-reflective/transparent material&#xD;&#xA;  3. you compute and cast two rays from the point of intersection: a reflective ray and a refractive ray&#xD;&#xA;  4. if the refractive ray hits an object contained in the transparent object (the glass) then you need to shade that object too. So if it's a plastic material, compute the result of that shader (including the lighting, so loop over all lights and add their contribution, etc.)&#xD;&#xA;  5. the color at the intersection point can finally be computed as a mix between the reflection and the refraction color (where as the mix is driven by the fresnel effect).&#xD;&#xA;&#xD;&#xA;Now that works but this is essentially **wrong**.&#xD;&#xA;&#xD;&#xA;Why? Because in fact light rays too are bent by say glass and water. So in fact when you cast a shadow ray from a point on the pen in the direction of the light, this ray direction is in fact wrong, since you should account for refraction and reflection (the ray should be bent when it goes from one medium to another in this case from water to air) but this is impossible to do with this algorithm/approach.&#xD;&#xA;&#xD;&#xA;Though in general this gives acceptable results so no one cares much but if your goal is really a physically plausible image then this approach is wrong.&#xD;&#xA;&#xD;&#xA;A solution to this maybe is to use photon mapping, where photons of light are cast from the light into the scene in a pre-pass. Thus when a light-photon hits the glass/water surface it will bent due to the law of refraction and eventually it will be &quot;deposited&quot; onto the pen. This is a bit hard to explain here but hopefully there will be a lesson on Scratchapixel about this in the future. Hope it helps.&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;*&gt; Thanks for clarifying, I had one other issue though. In the source code provided on the website for that lesson there doesn't seem to be code present to spawn a ray when the light ray leaves the glass cylinder. Is this unnescessary or is it actually already present? If it is could you point out where in the code?* &#xD;&#xA;&#xD;&#xA;Hum it seems like my explanation wasn't clear if you ask this question. When the refractive ray hits the surface of the pen you need to compute the color of the pen at that intersection point (where the refractive ray intersected the pen's geometry). Now the pen is made out of wood for example which for the sake of simplicity is a diffuse material only (no specular). So in order to compute the color of the pen at the intersection point, you simply execute the traditional illumination loop:&#xD;&#xA;&#xD;&#xA;    Vec3f computePenColor(const Vec3f&amp; objectColor, const Vec3f&amp; intersectionPoint, normalAtIntersection) {&#xD;&#xA;        Vec3f shadedPointColor = 0;&#xD;&#xA;        // loop over all lights in the scene to cadd their contribution&#xD;&#xA;        for (i = 0; i &lt; scene.lights.size(); ++i) {&#xD;&#xA;            Light currentLight = scene.lights[i];&#xD;&#xA;            // let's say this light source is a point light source&#xD;&#xA;            Vec3f lightDirection = currentLight.position - intersectionPoint;&#xD;&#xA;            // this cast a shadow ray from the shaded point to the light position&#xD;&#xA;            // if this ray intersects an object along the way then this point is in the shadow of this light and the function returns true&#xD;&#xA;            bool shadow = castShadowRay(lightDirection.length(), lightDirection.normalize());&#xD;&#xA;            // this point is not in the shadow of the light so add its contribution&#xD;&#xA;            if (!shadow) {&#xD;&#xA;                // the object is diffuse so apply cosine law only&#xD;&#xA;                shadedPointColor += max(0, normalAtIntersection.dot(lightDirection)) * currentLight-&gt;intensity * currentLight-&gt;color; &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return shadedPointColor * objectColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So maybe as you can see more clearly from this example, is that when I say &quot;cast a ray from the point of intersection to the light&quot; I mean cast a shadow ray. This shadow ray helps to determine if the shaded point is in the shadow of that light. If not, then you can add the contribution of that light to the shaded point.&#xD;&#xA;&#xD;&#xA;Now you can also see that the direction of this shadow ray is computed as the position of the point on the pen (the intersection point or shaded point) to the light position (we assume a point light source here for simplicity). So this is a **straight line** between the point on the pen and the light.&#xD;&#xA;&#xD;&#xA;But this where things are wrong. This **shoudn't** be a straight line, since when the &quot;shadow ray&quot; (which is also a light ray but we go from the point on the pen to the light rather than from the light to the pen, but in essence they are the same thing) exits the water volume it should be bent due to refraction (and part of it should be reflected to). You can compute this new direction if you wish, but then if the shadow ray is bent when it leaves the volume of water then it won't travel in the direction of the light anymore (as showed in the pic below), so you can't use it as a shadow or light ray any longer.&#xD;&#xA;&#xD;&#xA;So this algorithm that consists of looping over the lights and casting shadow ray can't be used if you **really** want to account for light ray bending due to reflection and refraction. Though as I said few people care about that because in reality, ignoring this fact, doesn't make much of a visual difference in 99% of cases. And as I pointed out, the solution to **get it right** if really needed is something like photon mapping where photon of lights are cast from the light into the scene into a pre-pass, which allows to follow the paths of light rays into the scene as they are being bent by refractive/reflective surfaces. But photon mapping is a rather complex algorithm to implement." ContentLicense="CC BY-SA 3.0" />
  <row Id="10634" PostHistoryTypeId="5" PostId="4579" RevisionGUID="59fd9720-0ebb-41ea-86a6-fa649b71ef31" CreationDate="2017-01-20T09:23:19.177" UserId="1608" Comment="added 91 characters in body" Text="this is an interesting question (and I am actually an author on Scratchapixel so I can maybe help on that one)). &#xD;&#xA;&#xD;&#xA;Things go as follows:&#xD;&#xA;&#xD;&#xA;  1. you cast the primary ray into the scene&#xD;&#xA;  2. the ray hits the glass which is a refractive-reflective/transparent material&#xD;&#xA;  3. you compute and cast two rays from the point of intersection: a reflective ray and a refractive ray&#xD;&#xA;  4. if the refractive ray hits an object contained in the transparent object (the glass) then you need to shade that object too. So if it's a plastic material, compute the result of that shader (including the lighting, so loop over all lights and add their contribution, etc.)&#xD;&#xA;  5. the color at the intersection point can finally be computed as a mix between the reflection and the refraction color (where as the mix is driven by the fresnel effect).&#xD;&#xA;&#xD;&#xA;Now that works but this is essentially **wrong**.&#xD;&#xA;&#xD;&#xA;Why? Because in fact light rays too are bent by say glass and water. So in fact when you cast a shadow ray from a point on the pen in the direction of the light, this ray direction is in fact wrong, since you should account for refraction and reflection (the ray should be bent when it goes from one medium to another in this case from water to air) but this is impossible to do with this algorithm/approach.&#xD;&#xA;&#xD;&#xA;Though in general this gives acceptable results so no one cares much but if your goal is really a physically plausible image then this approach is wrong.&#xD;&#xA;&#xD;&#xA;A solution to this maybe is to use photon mapping, where photons of light are cast from the light into the scene in a pre-pass. Thus when a light-photon hits the glass/water surface it will bent due to the law of refraction and eventually it will be &quot;deposited&quot; onto the pen. This is a bit hard to explain here but hopefully there will be a lesson on Scratchapixel about this in the future. Hope it helps.&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;*&gt; Thanks for clarifying, I had one other issue though. In the source code provided on the website for that lesson there doesn't seem to be code present to spawn a ray when the light ray leaves the glass cylinder. Is this unnescessary or is it actually already present? If it is could you point out where in the code?* &#xD;&#xA;&#xD;&#xA;Hum it seems like my explanation wasn't clear if you ask this question. When the refractive ray hits the surface of the pen you need to compute the color of the pen at that intersection point (where the refractive ray intersected the pen's geometry). Now the pen is made out of wood for example which for the sake of simplicity is a diffuse material only (no specular). So in order to compute the color of the pen at the intersection point, you simply execute the traditional illumination loop:&#xD;&#xA;&#xD;&#xA;    Vec3f computePenColor(const Vec3f&amp; objectColor, const Vec3f&amp; intersectionPoint, normalAtIntersection) {&#xD;&#xA;        Vec3f shadedPointColor = 0;&#xD;&#xA;        // loop over all lights in the scene to cadd their contribution&#xD;&#xA;        for (i = 0; i &lt; scene.lights.size(); ++i) {&#xD;&#xA;            Light currentLight = scene.lights[i];&#xD;&#xA;            // let's say this light source is a point light source&#xD;&#xA;            Vec3f lightDirection = currentLight.position - intersectionPoint;&#xD;&#xA;            // this cast a shadow ray from the shaded point to the light position&#xD;&#xA;            // if this ray intersects an object along the way then this point is in the shadow of this light and the function returns true&#xD;&#xA;            bool shadow = castShadowRay(lightDirection.length(), lightDirection.normalize());&#xD;&#xA;            // this point is not in the shadow of the light so add its contribution&#xD;&#xA;            if (!shadow) {&#xD;&#xA;                // the object is diffuse so apply cosine law only&#xD;&#xA;                shadedPointColor += max(0, normalAtIntersection.dot(lightDirection)) * currentLight-&gt;intensity * currentLight-&gt;color; &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return shadedPointColor * objectColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So maybe as you can see more clearly from this example, is that when I say &quot;cast a ray from the point of intersection to the light&quot; I mean cast a shadow ray. This shadow ray helps to determine if the shaded point is in the shadow of that light. If not, then you can add the contribution of that light to the shaded point.&#xD;&#xA;&#xD;&#xA;Now you can also see that the direction of this shadow ray is computed as the position of the point on the pen (the intersection point or shaded point) to the light position (we assume a point light source here for simplicity). So this is a **straight line** between the point on the pen and the light.&#xD;&#xA;&#xD;&#xA;But this where things are wrong. This **shoudn't** be a straight line, since when the &quot;shadow ray&quot; (which is also a light ray but we go from the point on the pen to the light rather than from the light to the pen, but in essence they are the same thing) exits the water volume it should be bent due to refraction (and part of it should be reflected to). You can compute this new direction if you wish, but then if the shadow ray is bent when it leaves the volume of water then it won't travel in the direction of the light anymore (as showed in the pic below), so you can't use it as a shadow or light ray any longer.&#xD;&#xA;&#xD;&#xA;So this algorithm that consists of looping over the lights and casting shadow ray can't be used if you **really** want to account for light ray bending due to reflection and refraction. Though as I said few people care about that because in reality, ignoring this fact, doesn't make much of a visual difference in 99% of cases. And as I pointed out, the solution to **get it right** if really needed is something like photon mapping where photon of lights are cast from the light into the scene into a pre-pass, which allows to follow the paths of light rays into the scene as they are being bent by refractive/reflective surfaces. But photon mapping is a rather complex algorithm to implement.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ADgso.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10636" PostHistoryTypeId="2" PostId="4583" RevisionGUID="15bec8b9-2ef0-43fc-84d9-afad2b3e98c1" CreationDate="2017-01-20T11:42:58.187" UserId="1608" Text="First start to be sure you understand what matrices are (4x4 which are the most common in CG).&#xD;&#xA;&#xD;&#xA;1) about your first question. You are taking about a hierarchy of transforms. I don't know if you use Maya at all, but if you do, you know you can for example create a sphere and group this sphere. So you have:&#xD;&#xA;&#xD;&#xA;    Group1&#xD;&#xA;       |&#xD;&#xA;       --Sphere1&#xD;&#xA;&#xD;&#xA;That's the a hierarchy where `Group1` is the parent of `Sphere1`. What does that mean is that if you move `Group1` then `Sphere1` will move with it. If you move `Sphere1` instead, then of course `Sphere1` will move but `Group1` will stay where it is. That's what parenting is used for.&#xD;&#xA;&#xD;&#xA;So I as mentioned you can apply a transform to `Group1` as well as a transform to `Sphere1` and transforms as you know can be expressed as 4x4 matrices. So `Group1` has a 4x4 matrix to represent its transformation (scale, rotation, translation) and `sphere1` has one too.&#xD;&#xA;&#xD;&#xA;2) so the sphere is affected by the matrix applied to `Group1` (since it is parented to `Group1`) and the matrix applied to the sphere itself do you agree? If you want to transform the sphere then you need to apply both transformation:&#xD;&#xA;&#xD;&#xA;    Sphere_Final_Rot_Scale_Trans = Sphere_Default_Scale_Rot_Trans * Mgroup1 * Msphere1&#xD;&#xA;&#xD;&#xA;Where `Mgroup1` is the 4x4 matrix of `Group1` and `MSphere1` is the 4x4 matrix of the sphere.&#xD;&#xA;&#xD;&#xA;However rather than multiplying the sphere by the 2 matrices, you can combine their effect into a single matrix. Just do:&#xD;&#xA;&#xD;&#xA;    Matrix44f Mcombined = Mgroup1 * Msphere1&#xD;&#xA;&#xD;&#xA;Then you can do:&#xD;&#xA;&#xD;&#xA;    Sphere_Final_Rot_Scale_Trans = Sphere_Default_Scale_Rot_Trans * Mcombined &#xD;&#xA;&#xD;&#xA;Simple!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10637" PostHistoryTypeId="5" PostId="4583" RevisionGUID="ece862ad-dedb-4695-ae6d-cb34619aa2fb" CreationDate="2017-01-20T11:48:22.627" UserId="1608" Comment="added 178 characters in body" Text="First start to be sure you understand what matrices are (4x4 which are the most common in CG).&#xD;&#xA;&#xD;&#xA;1) about your first question. You are taking about a hierarchy of transforms. I don't know if you use Maya at all, but if you do, you know you can for example create a sphere and group this sphere. So you have:&#xD;&#xA;&#xD;&#xA;    Group1&#xD;&#xA;       |&#xD;&#xA;       --Sphere1&#xD;&#xA;&#xD;&#xA;That's the a hierarchy where `Group1` is the parent of `Sphere1`. What does that mean is that if you move `Group1` then `Sphere1` will move with it. If you move `Sphere1` instead, then of course `Sphere1` will move but `Group1` will stay where it is. That's what parenting is used for.&#xD;&#xA;&#xD;&#xA;So I as mentioned you can apply a transform to `Group1` as well as a transform to `Sphere1` and transforms as you know can be expressed as 4x4 matrices. So `Group1` has a 4x4 matrix to represent its transformation (scale, rotation, translation) and `sphere1` has one too.&#xD;&#xA;&#xD;&#xA;2) so the sphere is affected by the matrix applied to `Group1` (since it is parented to `Group1`) and the matrix applied to the sphere itself do you agree? If you want to transform the sphere then you need to apply both transformation:&#xD;&#xA;&#xD;&#xA;    Sphere_Final_Rot_Scale_Trans = Sphere_Default_Scale_Rot_Trans * Mgroup1 * Msphere1&#xD;&#xA;&#xD;&#xA;Where `Mgroup1` is the 4x4 matrix of `Group1` and `MSphere1` is the 4x4 matrix of the sphere.&#xD;&#xA;&#xD;&#xA;However rather than multiplying the sphere by the 2 matrices, you can combine their effect into a single matrix. Just do:&#xD;&#xA;&#xD;&#xA;    Matrix44f Mcombined = Mgroup1 * Msphere1&#xD;&#xA;&#xD;&#xA;Then you can do:&#xD;&#xA;&#xD;&#xA;    Sphere_Final_Rot_Scale_Trans = Sphere_Default_Scale_Rot_Trans * Mcombined &#xD;&#xA;&#xD;&#xA;Simple! So all you need to know here is about matrix multiplication. Do you know that if you multiply 2 matrices together you get a third matrix that combines the effect of the first 2?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10639" PostHistoryTypeId="5" PostId="4534" RevisionGUID="47cb5979-1a5b-4d99-8ed3-a7d9ff96b27e" CreationDate="2017-01-20T13:20:46.203" UserId="38" Comment="added 942 characters in body" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathematics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;# The modellers perspective on things&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathematics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because its easier to think in one orientation or just simply because you want to move/rotate/scale objects out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minimum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straight ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;# Computational perspective&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. For example you need to know the point localtion in camera space to render. Preferably all this space transform happens automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other, a hierarchy, for modelers benefit. &#xD;&#xA;&#xD;&#xA;Although this could be done in any number of ways it is commonly done with a tree structure, much like a filesystem, using affine matrices. Mainly because this takes care of 2 issues. A the tree structure is easy to traverse and find the path to any other part in the hierarchy and matrices being appendable to form a compound transform independent of geometry calculation for each point in a object.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to transform the object to the coordinates of the object it is described in relation to, the parent. This parent in turn in turn describes the transform to it's parent all the way to the world. Since all objects share one common ancestor, world, we can easily traverse the tree to find a transform from any one coordinate system to another coordinate system.&#xD;&#xA;&#xD;&#xA;Since linear transforms are invertible, we do not need to store a description separately for moving in the opposite direction, away from world towards the children/leaves of the tree structure. All we need to do is to invert the matrix. This is almost always needed as its practical to describe camera as a separate object under the world, there is no reason to describe the cameras transform from world to camera just treat it like any other object.&#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why. You should understand also that we do not have any limit to complexity of the hierarchy to &#xD;&#xA;facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This kind of hierarchy is called a scene graph and such things can be found in web pages, vector and cad applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;# Do we absolutely need these?&#xD;&#xA;&#xD;&#xA;No, we do not. we can dispense all the matrices and describe all of our data directly in the cameras final coordinates. Its just that this is horribly complicated in 98% of the cases.&#xD;&#xA;&#xD;&#xA;In practice we need this hierarchy if we try to do even something more complex than a stationary box.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because its a tree, and earliest tree graphs are genealogical studies, aka family trees. Where the previous level is simply the parents and the next one is their children. &#xD;&#xA;&#xD;&#xA;PS: Written on my  phone at after work beer waiting for my coworkers to arrive so maybe i will still improve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10640" PostHistoryTypeId="2" PostId="4584" RevisionGUID="862f4f82-77b1-4c18-ade2-07455a8119b6" CreationDate="2017-01-20T13:40:02.377" UserId="2687" Text="The title says it all, given two convex patches, how to find points/faces that have distance &lt; x?  Can I use GJK for this case?&#xD;&#xA;&#xD;&#xA;Convex patches are obtained from convex decomposition, see [here](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.9.3141&amp;rep=rep1&amp;type=pdf). If I read it correctly, I don't think methods used in that paper can give points/faces that satisfy above condition." ContentLicense="CC BY-SA 3.0" />
  <row Id="10641" PostHistoryTypeId="1" PostId="4584" RevisionGUID="862f4f82-77b1-4c18-ade2-07455a8119b6" CreationDate="2017-01-20T13:40:02.377" UserId="2687" Text="Given two convex patches, how to find points/faces that have distance &lt; x?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10642" PostHistoryTypeId="3" PostId="4584" RevisionGUID="862f4f82-77b1-4c18-ade2-07455a8119b6" CreationDate="2017-01-20T13:40:02.377" UserId="2687" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10643" PostHistoryTypeId="5" PostId="4534" RevisionGUID="ed7759d9-fade-4a9b-a815-0b6b8c17006b" CreationDate="2017-01-20T13:50:21.200" UserId="38" Comment="added 1069 characters in body" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathematics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;# The modellers perspective on things&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathematics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because its easier to think in one orientation or just simply because you want to move/rotate/scale objects out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minimum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straight ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;# Computational perspective&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. For example you need to know the point localtion in camera space to render. Preferably all this space transform happens automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other, a hierarchy, for modelers benefit. &#xD;&#xA;&#xD;&#xA;Although this could be done in any number of ways it is commonly done with a tree structure, much like a filesystem, using affine matrices. Mainly because this takes care of 2 issues. A the tree structure is easy to traverse and find the path to any other part in the hierarchy and matrices being appendable to form a compound transform independent of geometry calculation for each point in a object.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to transform the object to the coordinates of the object it is described in relation to, the parent. This parent in turn in turn describes the transform to it's parent all the way to the world. Since all objects share one common ancestor, world, we can easily traverse the tree to find a transform path from any one coordinate system to another coordinate system.&#xD;&#xA;&#xD;&#xA;Since linear transforms are invertible, we do not need to store a description separately for moving in the opposite direction, away from world towards the children/leaves of the tree structure. All we need to do is to invert the matrix. This is almost always needed as its practical to describe camera as a separate object under the world, there is no reason to describe the cameras transform from world to camera just treat it like any other object.&#xD;&#xA;&#xD;&#xA;To compute a point from one space to another you do as follows:&#xD;&#xA;&#xD;&#xA;1. use the tree to find a relationship between spaces.&#xD;&#xA;2. For each step on the way pre multiply your matrix/ or its inverse if your traversing away from world. \*\*&#xD;&#xA;&#xD;&#xA;Example:  You have a following hierarchy because it makes sense (this way you do not need to model each petal separately)&#xD;&#xA;&#xD;&#xA;    World&#xD;&#xA;      |&#xD;&#xA;      +---- Flower&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 1&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 2&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 3&#xD;&#xA;      |&#xD;&#xA;      +---- Track&#xD;&#xA;             |&#xD;&#xA;             +--- Boom&#xD;&#xA;                   |&#xD;&#xA;                   +--- Camera&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To render Petal 1 you need to transform the vertices of petal one into the camera object space and form there to perspective space etc. Your calculation would be:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    T_{Perspective} \cdot T_{Camera}^{-1} \cdot T_{Boom}^{-1} \cdot T_{Track}^{-1} \cdot T_{Flower} \cdot T_{Petal 1} \cdot \vec{v}_{PetalPoint}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why. You should understand also that we do not have any limit to complexity of the hierarchy to &#xD;&#xA;facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This kind of hierarchy is called a scene graph and such things can be found in web pages, vector and cad applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;# Do we absolutely need these?&#xD;&#xA;&#xD;&#xA;No, we do not. we can dispense all the matrices and describe all of our data directly in the cameras final coordinates. Its just that this is horribly complicated in 98% of the cases.&#xD;&#xA;&#xD;&#xA;In practice we need this hierarchy if we try to do even something more complex than a stationary box.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because its a tree, and earliest tree graphs are genealogical studies, aka family trees. Where the previous level is simply the parents and the next one is their children. &#xD;&#xA;&#xD;&#xA;\*\* or the other way around if you want to transpose your calculations.&#xD;&#xA;&#xD;&#xA;PS: Written on my  phone at after work beer waiting for my coworkers to arrive so maybe i will still improve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10644" PostHistoryTypeId="5" PostId="4534" RevisionGUID="7f8b0b0f-92e6-4f00-a8bf-c5ff0d54008d" CreationDate="2017-01-20T14:04:35.263" UserId="38" Comment="added 234 characters in body" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathematics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;# The modellers perspective on things&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathematics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because its easier to think in one orientation or just simply because you want to move/rotate/scale objects out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minimum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straight ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;# Computational perspective&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. For example you need to know the point localtion in camera space to render. Preferably all this space transform happens automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other, a hierarchy, for modelers benefit. &#xD;&#xA;&#xD;&#xA;Although this could be done in any number of ways it is commonly done with a tree structure, much like a filesystem with much the same effect. Each level stores in addition to tree information a affine matrix that describes the transform to its predecessor in the hierarchy. Mainly because this takes care of two core issues. A the tree structure is easy to traverse and find the path to any other part. The matrices solve the problem of needing to do a lot of work transforming form a transform from one hierarchy space to another.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to transform the object to the coordinates of the object it is described in relation to, the parent. This parent in turn in turn describes the transform to it's parent all the way to the world. Since all objects share one common ancestor, world, we can easily traverse the tree to find a transform path from any one coordinate system to another coordinate system.&#xD;&#xA;&#xD;&#xA;Since linear transforms are invertible, we do not need to store a description separately for moving in the opposite direction, away from world towards the children/leaves of the tree structure. All we need to do is to invert the matrix. This is almost always needed as its practical to describe camera as a separate object under the world, there is no reason to describe the cameras transform from world to camera just treat it like any other object.&#xD;&#xA;&#xD;&#xA;To compute a point from one space to another you do as follows:&#xD;&#xA;&#xD;&#xA;1. use the tree to find a relationship between spaces.&#xD;&#xA;2. For each step on the way pre multiply your matrix/ or its inverse if your traversing away from world. \*\*&#xD;&#xA;&#xD;&#xA;Example:  You have a following hierarchy because it makes sense (this way you do not need to model each petal separately)&#xD;&#xA;&#xD;&#xA;    World&#xD;&#xA;      |&#xD;&#xA;      +---- Flower&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 1&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 2&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 3&#xD;&#xA;      |&#xD;&#xA;      +---- Track&#xD;&#xA;             |&#xD;&#xA;             +--- Boom&#xD;&#xA;                   |&#xD;&#xA;                   +--- Camera&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To render Petal 1 you need to transform the vertices of petal one into the camera object space and form there to perspective space etc. Your calculation would be:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    T_{Perspective} \cdot T_{Camera}^{-1} \cdot T_{Boom}^{-1} \cdot T_{Track}^{-1} \cdot T_{Flower} \cdot T_{Petal 1} \cdot \vec{v}_{PetalPoint}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why. You should understand also that we do not have any limit to complexity of the hierarchy to &#xD;&#xA;facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This kind of hierarchy is called a scene graph and such things can be found in web pages, vector and cad applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;# Do we absolutely need these?&#xD;&#xA;&#xD;&#xA;No, we do not. we can dispense all the matrices and describe all of our data directly in the cameras final coordinates. Its just that this is horribly complicated in 98% of the cases.&#xD;&#xA;&#xD;&#xA;In practice we need this hierarchy if we try to do even something more complex than a stationary box. Most of this deign is to make scene modellers life easier. So that simple operations make more sense.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because its a tree, and earliest tree graphs are genealogical studies, aka family trees. Where the previous level is simply the parents and the next one is their children. &#xD;&#xA;&#xD;&#xA;\*\* or the other way around if you want to transpose your calculations.&#xD;&#xA;&#xD;&#xA;PS: Written on my  phone at after work beer waiting for my coworkers to arrive so maybe i will still improve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10645" PostHistoryTypeId="2" PostId="4585" RevisionGUID="dbadac30-ca9c-4241-af6f-1f8e71dc1f46" CreationDate="2017-01-20T15:44:53.310" UserId="5887" Text="Purely out of curiosity, are mirror-like reflections in computer graphics purely handled with ray-tracing/ ray-casting techniques or are there some situations where they are achieved through rasterisation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10646" PostHistoryTypeId="1" PostId="4585" RevisionGUID="dbadac30-ca9c-4241-af6f-1f8e71dc1f46" CreationDate="2017-01-20T15:44:53.310" UserId="5887" Text="Reflections in computer graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="10647" PostHistoryTypeId="3" PostId="4585" RevisionGUID="dbadac30-ca9c-4241-af6f-1f8e71dc1f46" CreationDate="2017-01-20T15:44:53.310" UserId="5887" Text="|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10648" PostHistoryTypeId="5" PostId="4583" RevisionGUID="fbb3232c-85bd-4f19-a18c-ad62e07497a5" CreationDate="2017-01-20T15:47:25.677" UserId="1608" Comment="added 44 characters in body" Text="First start to be sure you understand what matrices are (4x4 which are the most common in CG).&#xD;&#xA;&#xD;&#xA;1) about your first question. You are taking about a hierarchy of transforms. I don't know if you use Maya at all, but if you do, you know you can for example create a sphere and group this sphere. So you have:&#xD;&#xA;&#xD;&#xA;    Group1&#xD;&#xA;       |&#xD;&#xA;       --Sphere1&#xD;&#xA;&#xD;&#xA;That's the a hierarchy where `Group1` is the parent of `Sphere1`. What does that mean is that if you move `Group1` then `Sphere1` will move with it. If you move `Sphere1` instead, then of course `Sphere1` will move but `Group1` will stay where it is. That's what parenting is used for.&#xD;&#xA;&#xD;&#xA;So I as mentioned you can apply a transform to `Group1` as well as a transform to `Sphere1` and transforms as you know can be expressed as 4x4 matrices. So `Group1` has a 4x4 matrix to represent its transformation (scale, rotation, translation) and `sphere1` has one too.&#xD;&#xA;&#xD;&#xA;2) so the sphere is affected by the matrix applied to `Group1` (since it is parented to `Group1`) and the matrix applied to the sphere itself do you agree? If you want to transform the sphere then you need to apply both transformation:&#xD;&#xA;&#xD;&#xA;    Sphere_Final_Rot_Scale_Trans = Sphere_Default_Scale_Rot_Trans * Mgroup1 * Msphere1&#xD;&#xA;&#xD;&#xA;Where `Mgroup1` is the 4x4 matrix of `Group1` and `MSphere1` is the 4x4 matrix of the sphere.&#xD;&#xA;&#xD;&#xA;However rather than multiplying the sphere by the 2 matrices, you can combine their effect into a single matrix. Just do:&#xD;&#xA;&#xD;&#xA;    Matrix44f Mcombined = Mgroup1 * Msphere1&#xD;&#xA;&#xD;&#xA;This is also called a matrix concatenation. Then you can do:&#xD;&#xA;&#xD;&#xA;    Sphere_Final_Rot_Scale_Trans = Sphere_Default_Scale_Rot_Trans * Mcombined &#xD;&#xA;&#xD;&#xA;Simple! So all you need to know here is about matrix multiplication. Do you know that if you multiply 2 matrices together you get a third matrix that combines the effect of the first 2?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10649" PostHistoryTypeId="2" PostId="4586" RevisionGUID="7db5bbf3-3583-447e-9663-663980f3c299" CreationDate="2017-01-20T15:57:10.400" UserId="1608" Text="Help!&#xD;&#xA;&#xD;&#xA;;-)&#xD;&#xA;&#xD;&#xA;This is one of the most common &quot;misconception&quot; on rendering, rasterisation and ray-tracing. Don't get me wrong. This is a good question, but one that should be answered once and for all))). &#xD;&#xA;&#xD;&#xA;So to answer your question:&#xD;&#xA;&#xD;&#xA;1) it is much easier to simulate reflection and refraction with ray-tracing than with rasterisation, which is often why you see an image produced with a ray-tracer you see spheres reflecting each other.&#xD;&#xA;&#xD;&#xA;2) the misconception (even among people working in the CG business) is that you can NOT produce reflection or refraction with rasterisation. In fact, you can.&#xD;&#xA;&#xD;&#xA;Generally, ray-tracing rasterisation have nothing to do with reflection or refraction. These are two ways of solving a single problem which is to sort out (in short) if two points in space are visible to each other (the visibility problem). Ray-tracing solves this problem in one way, rasterisation in other. Rasterisation is very efficient at solving this problem from primary rays (or camera rays) and less efficient to solve this problem for secondary rays (reflection, refraction, shadows, etc.). Ray-tracing is slower than rasterisation for primary rays but offer a simpler solution for secondary rays. Yet ray-tracing is not good for solving problems like caustics, so this is far from being a solution to every problem in computer graphics.&#xD;&#xA;&#xD;&#xA;I am sorry to repeat myself here (http://computergraphics.stackexchange.com/questions/4573/refraction-in-a-ray-tracer) but there are resources on the web that explains this well. I am tired to promote the same ones all the time) but Google `ray-tracing vs rasterisation` (I have just done it) you will stumble upon a couple of good ones. You now just need to make the effort to read)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10650" PostHistoryTypeId="5" PostId="4586" RevisionGUID="a92c709c-ffc0-44a6-9cec-35386228b166" CreationDate="2017-01-20T16:00:14.007" UserId="1608" Comment="added 167 characters in body" Text="Help!&#xD;&#xA;&#xD;&#xA;;-)&#xD;&#xA;&#xD;&#xA;This is one of the most common &quot;misconceptions&quot; on rendering, rasterisation and ray-tracing. Don't get me wrong. This is a good question, but one that should be answered once and for all))). &#xD;&#xA;&#xD;&#xA;So to answer your question:&#xD;&#xA;&#xD;&#xA;1) it is much easier to simulate reflection and refraction with ray-tracing than with rasterisation, which is often why when you see an image produced with a ray-tracer you see spheres reflecting each other.&#xD;&#xA;&#xD;&#xA;2) the misconception (even among people working in the CG business) is that you can NOT produce reflection or refraction with rasterisation. In fact, you can.&#xD;&#xA;&#xD;&#xA;Generally, ray-tracing/rasterisation have nothing to do with reflection or refraction or whatever else. These are two ways of solving a single problem which is to find out (in short) if two points in space are visible to each other (the visibility problem). Ray-tracing solves this problem in one way, rasterisation in an other. Rasterisation is very efficient at solving this problem from primary rays (or camera rays) and less efficient to solve this problem for secondary rays (reflection, refraction, shadows, etc.) than ray-tracing. Ray-tracing is slower than rasterisation for primary rays but offer a simpler solution for secondary rays compared to rasterisation. Yet ray-tracing is not good for solving problems like caustics, so this is far from being a solution to every problem in computer graphics. Yet rasterisation can be used (different techniques exist) to simulate reflections and refractions.&#xD;&#xA;&#xD;&#xA;I am sorry to repeat myself here (http://computergraphics.stackexchange.com/questions/4573/refraction-in-a-ray-tracer) but there are resources on the web that explains this well. I am tired to promote the same ones all the time) but Google `ray-tracing vs rasterisation` (I have just done it) and you will stumble upon a couple of good ones. You now just need to make the effort to read)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10651" PostHistoryTypeId="2" PostId="4587" RevisionGUID="0d6b9fd4-f27a-4593-bbb3-8fb68e7880d4" CreationDate="2017-01-20T16:46:45.810" UserId="137" Text="You can mimic a mirror by masking out the visible reflective surface when you first render and then mirror the world around the reflective plane and render again while only drawing where the reflective surface was.&#xD;&#xA;&#xD;&#xA;There are some other details to worry about like not drawing stuff on the far side of the mirror when drawing the mirrored world which can be done with a second depth test (only draw stuff farther away from the camera than the mirror). &#xD;&#xA;&#xD;&#xA;This works very well for flat mirrors, when you add curves things get a lot more complicated." ContentLicense="CC BY-SA 3.0" />
  <row Id="10652" PostHistoryTypeId="2" PostId="4588" RevisionGUID="a1d9f8d0-cf1b-4bf7-8367-4dc1fd03e4e7" CreationDate="2017-01-20T17:00:29.737" UserId="137" Text="Yes GJK is appropriate for this. &#xD;&#xA;&#xD;&#xA;The overall algorithm of GJK goes something like &#xD;&#xA;&#xD;&#xA;    simplex = empty&#xD;&#xA;    direction n = arbitrary&#xD;&#xA;    &#xD;&#xA;    while(not finished){&#xD;&#xA;    &#xD;&#xA;        find furthest point p1 in mesh 1 in direction n&#xD;&#xA;        find furthest point p2 in mesh 2 in direction -n&#xD;&#xA;    &#xD;&#xA;        supplement simplex with point p1-p2&#xD;&#xA;    &#xD;&#xA;        if(simplex is tetrahedron) simplify simplex&#xD;&#xA;    &#xD;&#xA;        direction n = pick direction perpendicular to simplex pointing to origin&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;you can then use the simplex at the end of the loop to calculate the distance from it tot he origin and set finished to true and you will get a collection of points on each mesh which make up a pair of faces that are closer than x." ContentLicense="CC BY-SA 3.0" />
  <row Id="10654" PostHistoryTypeId="2" PostId="4589" RevisionGUID="59a6c834-7c44-483c-a10f-ec6e08bb079b" CreationDate="2017-01-20T20:36:32.873" UserId="48" Text="There are a couple of special cases where mirror-like reflections can be rendered efficiently using rasterization techniques, and these are commonly used in games, although they don't work for the general case.&#xD;&#xA;&#xD;&#xA;### Planar reflections&#xD;&#xA;&#xD;&#xA;If the reflecting surface is flat or reasonably close to flat, the reflected image can be rasterized in an separate rendering pass, by applying a reflection transform and clip plane to the scene. The reflection is then composited into the final image using a shader (or, in older games, stencil buffer masking). Also, a small amount of distortion or blurring might be applied to the image if the reflecting surface isn't intended to appear perfectly flat and smooth.&#xD;&#xA;&#xD;&#xA;This is very commonly used in games for water reflection in lakes or the ocean, as long as any waves aren't too large. [This page from the UE4 docs](https://docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/PlanarReflections/) shows a number of examples of planar reflections used for water. The same technique is also often used for mirror reflections in glossy floors, or for [actual mirrors](https://i.stack.imgur.com/KgrG1.png).&#xD;&#xA;&#xD;&#xA;The main strength of planar reflection is that it automatically gives you correct perspective and occlusion in the reflected image. The main limitation, aside from being limited to planar surfaces, is the performance cost of rendering an extra copy of the scene (with full lighting, etc) for each reflection plane. For instance, having multiple water surfaces at different elevations (e.g. in a boat lock) would require another rendering pass for each elevation. For this reason, usually when planar reflections are used, they're set up in such a way that only one reflection plane is visible at a time.&#xD;&#xA;&#xD;&#xA;### Cubemap reflections&#xD;&#xA;&#xD;&#xA;Another special case is when the reflecting object is reasonably small and, ideally, not too close to other objects around it. In that case, you can approximate reflections by rasterizing a cubemap around the object. Then it can be used as an environment map during shading, by sampling the cubemap along the reflection vector calculated in the shader.&#xD;&#xA;&#xD;&#xA;Many games use pre-rendered cubemaps to render static environment reflections on characters and dynamic objects; somewhat less commonly, you can also dynamically re-render a cubemap every frame to get dynamic reflections of other objects. This might be used on the cars in a racing game, for instance.&#xD;&#xA;&#xD;&#xA;The advantage of cubemap reflections is that they can be applied to any shape of object, not just planar ones. However, since the cubemap is rendered from a single point, the reflections have increasingly incorrect perspective and occlusion the farther you get from that point. This can be partly addressed by [parallax correction](https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/), and by blending between multiple cubemaps based on location, but ultimately cubemaps just don't give you the accuracy of either planar reflections or raytracing. Moreover, re-rendering a dynamic cubemap every frame is quite expensive, as it requires 6 extra rendering passes (one for each face of the cube).&#xD;&#xA;&#xD;&#xA;### Hybrid techniques&#xD;&#xA;&#xD;&#xA;There are also cases where rasterization is used to build an initial data structure for ray tracing / casting to traverse into.&#xD;&#xA;&#xD;&#xA;* Screen-space reflection can be understood this way, as it involves first rendering the screen using ordinary rasterization techniques, then treating the Z-buffer as a heightfield and marching rays through it. &#xD;&#xA;* Voxel cone tracing is a similar case, where the scene is voxelized using rasterization, and then rays can be marched through the voxel grid. This perhaps doesn't qualify as &quot;mirror-like&quot; reflections since in practice the voxel grid isn't high-resolution enough for that, but it could be done in principle.&#xD;&#xA;&#xD;&#xA;So yes, depending on what degree of approximation you can accept and what constraints you can work within, there are quite a few cases where mirror-like reflections can be achieved using rasterization, or hybrid rasterization/raytracing techniques." ContentLicense="CC BY-SA 3.0" />
  <row Id="10655" PostHistoryTypeId="2" PostId="4590" RevisionGUID="dd2a0fab-07f4-4a4c-8898-20effe9893ed" CreationDate="2017-01-20T23:19:45.310" UserId="5890" Text="I am fairly new to graphics programming and I am trying to pass a custom Matrix4 (non-glm) to my vertex shader by using a uniform.&#xD;&#xA;&#xD;&#xA;        Matrix44 transform;  //creates a 4x4 identity matrix&#xD;&#xA;		transform.SetTranslation(Vector3(0.5f, 0.3f, 0.0f));&#xD;&#xA;		GLint transformLocation = glGetUniformLocation(ourShader.Program, &quot;transformation&quot;);&#xD;&#xA;		glUniformMatrix4fv(transformLocation, sizeof(transform), GL_FALSE, &amp;transform.m[0][0]);&#xD;&#xA;&#xD;&#xA;Above is the code which I am using to send the matrix to the shaders.&#xD;&#xA;&#xD;&#xA;(the .m allows me to access the matrix as a 2D array of 4x4 floats);&#xD;&#xA;&#xD;&#xA;This is how my vertex shader looks like:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {					&#xD;&#xA;	   gl_Position = transform*vec4(position,1.0f);		&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When I run it, I don't get anything drawn on my screen, except the background color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Below is the matrix which I send to the shader. I am using column major, so as far as I've read this should be the translation part of the 4x4. I've also tried transposing the matrix with no luck whatsoever.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The last clue I have is that the values which I am sending are 0s. I came to this conclusion because I tried playing with the fragment shader and I set the color to be equal to the last column from the uniform mat4:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform mat4 transform;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	 color = vec4(transform[0][3],transform[1][3], transform[2][3], transform[3][3]);	&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;Which gives me a black triangle i.e. the color vec4 is filled with 0s.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I apologize in advance if the question is too noob-ish but I've been struggling with this for several days and I could not find a way to run it :(&#xD;&#xA;&#xD;&#xA;Any advise would be appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ay01I.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fi9c5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10656" PostHistoryTypeId="1" PostId="4590" RevisionGUID="dd2a0fab-07f4-4a4c-8898-20effe9893ed" CreationDate="2017-01-20T23:19:45.310" UserId="5890" Text="Unable to pass custom Matrix4 to GLSL as a uniform" ContentLicense="CC BY-SA 3.0" />
  <row Id="10657" PostHistoryTypeId="3" PostId="4590" RevisionGUID="dd2a0fab-07f4-4a4c-8898-20effe9893ed" CreationDate="2017-01-20T23:19:45.310" UserId="5890" Text="|opengl|shader|glsl|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10658" PostHistoryTypeId="2" PostId="4591" RevisionGUID="7bd5720c-efd8-4fab-b192-aabdedb8483a" CreationDate="2017-01-21T00:27:46.957" UserId="2654" Text="&gt;     glUniformMatrix4fv(transformLocation, sizeof(transform), GL_FALSE, &amp;transform.m[0][0]);&#xD;&#xA;&#xD;&#xA;The [second parameter to `glUniformMatrix`][1] is not the number of bytes in the data. OpenGL can figure that out from the `4fv` part of the command (a 4x4 matrix of `GLfloat`s). The second parameter is the number of *matrices* you're sending to that uniform, in case it is an array of `mat4`s.&#xD;&#xA;&#xD;&#xA;So that value ought to be 1. You almost certainly got a `GL_INVALID_OPERATION` error from calling it with `sizeof(transform)`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://docs.gl/gl4/glUniform" ContentLicense="CC BY-SA 3.0" />
  <row Id="10661" PostHistoryTypeId="5" PostId="4586" RevisionGUID="69b439c7-4196-4905-8800-f09ebe886527" CreationDate="2017-01-21T10:53:32.483" UserId="231" Comment="Minor typos and removing confusing parentheses" Text="This is one of the most common &quot;misconceptions&quot; on rendering, rasterisation and ray-tracing. Don't get me wrong. This is a good question, but one that should be answered once and for all. &#xD;&#xA;&#xD;&#xA;So to answer your question:&#xD;&#xA;&#xD;&#xA;1) it is much easier to simulate reflection and refraction with ray-tracing than with rasterisation, which is often why when you see an image produced with a ray-tracer you see spheres reflecting each other.&#xD;&#xA;&#xD;&#xA;2) the misconception (even among people working in the CG business) is that you can NOT produce reflection or refraction with rasterisation. In fact, you can.&#xD;&#xA;&#xD;&#xA;Generally, ray-tracing/rasterisation have nothing to do with reflection or refraction or whatever else. These are two ways of solving a single problem which is to find out (in short) if two points in space are visible to each other (the visibility problem). Ray-tracing solves this problem in one way, rasterisation in an other. Rasterisation is very efficient at solving this problem from primary rays (or camera rays) and less efficient to solve this problem for secondary rays (reflection, refraction, shadows, etc.) than ray-tracing. Ray-tracing is slower than rasterisation for primary rays but offers a simpler solution for secondary rays compared to rasterisation. Yet ray-tracing is not good for solving problems like caustics, so this is far from being a solution to every problem in computer graphics. Yet rasterisation can be used (different techniques exist) to simulate reflections and refractions.&#xD;&#xA;&#xD;&#xA;I am sorry to repeat myself [here](http://computergraphics.stackexchange.com/questions/4573/refraction-in-a-ray-tracer) but there are resources on the web that explain this well. I am tired of promoting the same ones all the time but Google `ray-tracing vs rasterisation` (I have just done it) and you will stumble upon a couple of good ones. You now just need to make the effort to read." ContentLicense="CC BY-SA 3.0" />
  <row Id="10662" PostHistoryTypeId="5" PostId="4588" RevisionGUID="6604bb86-8242-4d5c-a806-b431bac8c46c" CreationDate="2017-01-21T11:18:33.813" UserId="231" Comment="Minor typo" Text="Yes GJK is appropriate for this. &#xD;&#xA;&#xD;&#xA;The overall algorithm of GJK goes something like &#xD;&#xA;&#xD;&#xA;    simplex = empty&#xD;&#xA;    direction n = arbitrary&#xD;&#xA;    &#xD;&#xA;    while(not finished){&#xD;&#xA;    &#xD;&#xA;        find furthest point p1 in mesh 1 in direction n&#xD;&#xA;        find furthest point p2 in mesh 2 in direction -n&#xD;&#xA;    &#xD;&#xA;        supplement simplex with point p1-p2&#xD;&#xA;    &#xD;&#xA;        if(simplex is tetrahedron) simplify simplex&#xD;&#xA;    &#xD;&#xA;        direction n = pick direction perpendicular to simplex pointing to origin&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;you can then use the simplex at the end of the loop to calculate the distance from it to the origin and set finished to true and you will get a collection of points on each mesh which make up a pair of faces that are closer than x." ContentLicense="CC BY-SA 3.0" />
  <row Id="10663" PostHistoryTypeId="4" PostId="4573" RevisionGUID="5e763f1b-63a2-447b-82b4-81f43424c4b1" CreationDate="2017-01-21T13:29:10.300" UserId="5256" Comment="Improved Title" Text="Refraction in a Ray Tracer: What do with an intersection within the medium?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10667" PostHistoryTypeId="5" PostId="4585" RevisionGUID="232b635e-b697-4199-b2fa-ae376757fb12" CreationDate="2017-01-21T15:29:01.360" UserId="5256" Comment="Added an image, improved tags and made the title clearer as to what the user is asking. " Text="Are **mirror-like reflections** in computer graphics **purely handled** with **ray-tracing/ray-casting** techniques or are there **some situations where they are achieved through rasterization?**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IYlur.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10668" PostHistoryTypeId="4" PostId="4585" RevisionGUID="232b635e-b697-4199-b2fa-ae376757fb12" CreationDate="2017-01-21T15:29:01.360" UserId="5256" Comment="Added an image, improved tags and made the title clearer as to what the user is asking. " Text="Mirror Reflections: Ray Tracing or Rasterisation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10669" PostHistoryTypeId="6" PostId="4585" RevisionGUID="232b635e-b697-4199-b2fa-ae376757fb12" CreationDate="2017-01-21T15:29:01.360" UserId="5256" Comment="Added an image, improved tags and made the title clearer as to what the user is asking. " Text="|raytracing|rasterizer|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10670" PostHistoryTypeId="24" PostId="4585" RevisionGUID="232b635e-b697-4199-b2fa-ae376757fb12" CreationDate="2017-01-21T15:29:01.360" Comment="Proposed by 5256 approved by -1 edit id of 193" ContentLicense="CC BY-SA 3.0" />
  <row Id="10671" PostHistoryTypeId="5" PostId="4585" RevisionGUID="f832ef72-f59b-42c1-a232-0a7ee7e24e4c" CreationDate="2017-01-21T15:29:01.360" UserId="48" Comment="removed unnecessary bold text" Text="Are mirror-like reflections in computer graphics purely handled with ray-tracing/ray-casting techniques or are there some situations where they are achieved through rasterisation?&#xD;&#xA;&#xD;&#xA;![example of raytraced reflection on a sphere][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IYlur.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10672" PostHistoryTypeId="2" PostId="4593" RevisionGUID="e8dfe546-48dc-4fa1-b70d-08cf7d56f866" CreationDate="2017-01-21T16:33:28.520" UserId="5852" Text="This code snippet:&#xD;&#xA;&#xD;&#xA;    GLint versionMajor;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);&#xD;&#xA;	glGetIntegerv(GLFW_CONTEXT_VERSION_MAJOR, &amp;versionMajor);&#xD;&#xA;    std::cout &lt;&lt; &quot;Version major:&quot; &lt;&lt; version &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;prints &quot;3&quot; in my screen, but in the first line I set the the GLFW_CONTEXT_VERSION_MAJOR to &quot;2&quot;. How I can get back that value?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10673" PostHistoryTypeId="1" PostId="4593" RevisionGUID="e8dfe546-48dc-4fa1-b70d-08cf7d56f866" CreationDate="2017-01-21T16:33:28.520" UserId="5852" Text="How to get the GLFW_CONTEXT_VERSION_MAJOR value?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10674" PostHistoryTypeId="3" PostId="4593" RevisionGUID="e8dfe546-48dc-4fa1-b70d-08cf7d56f866" CreationDate="2017-01-21T16:33:28.520" UserId="5852" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10675" PostHistoryTypeId="2" PostId="4594" RevisionGUID="9b7c97eb-d767-4199-be72-38f8a52aaeab" CreationDate="2017-01-21T16:39:47.863" UserId="48" Text="According to [the GLFW docs](http://www.glfw.org/docs/latest/window_guide.html#window_hints_ctx), the context version hint acts as a _minimum_ version, i.e. the context you actually get may be a higher version than what you request. However, the context should be backward-compatible, so even if you get a GL 3.x context you're OK to use GL 2.x code." ContentLicense="CC BY-SA 3.0" />
  <row Id="10680" PostHistoryTypeId="2" PostId="4596" RevisionGUID="a63b67ba-950e-4548-90b5-10b24b7237f3" CreationDate="2017-01-22T00:39:37.217" UserId="5852" Text="If you want to send a value from vertex shader to fragment shader, the vertex shader should declare one variable as `out`, the fragment shader should declare other variable as `in` and both variables must have their names and types equal. But this doesn't happen when you want to send the color value from the fragment shader. In fact, you can call the output variable as you want. Why? In older version there was one variable called `gl_FragColor`&lt;br /&gt;&#xD;&#xA;How the program links your output fragment variable with gl_FragColor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10681" PostHistoryTypeId="1" PostId="4596" RevisionGUID="a63b67ba-950e-4548-90b5-10b24b7237f3" CreationDate="2017-01-22T00:39:37.217" UserId="5852" Text="Fragment shader's output variables" ContentLicense="CC BY-SA 3.0" />
  <row Id="10682" PostHistoryTypeId="3" PostId="4596" RevisionGUID="a63b67ba-950e-4548-90b5-10b24b7237f3" CreationDate="2017-01-22T00:39:37.217" UserId="5852" Text="|opengl|shader|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10683" PostHistoryTypeId="2" PostId="4597" RevisionGUID="2388a458-9d39-4d1b-89cb-15239ed5c0f9" CreationDate="2017-01-22T02:00:59.087" UserId="5900" Text="I am currently a beginner when it comes to anti-aliasing, I have read some notes online that how anti-aliasing works is that you first draw the line using an algorithm such as Bresenham's algorithm. Then you modify it to include anti-aliasing. &#xD;&#xA;&#xD;&#xA;Now, I understand that one method of antialiasing is to simply imagine there being a rectangle that encompasses the line and any pixel that touches that will be turned on or filled with an RBG value. &#xD;&#xA;&#xD;&#xA;Now if I know that area of the segment of the pixel that is cut off by the rectangle (lets assume the pixel is a circle) how would I use that area of the segment to compute the density of the colour which is from 0-1 (where 0 is very light and 1 is the darkest)?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10684" PostHistoryTypeId="1" PostId="4597" RevisionGUID="2388a458-9d39-4d1b-89cb-15239ed5c0f9" CreationDate="2017-01-22T02:00:59.087" UserId="5900" Text="Anti-aliasing - Controlling colour density of pixel that comes within the &quot;rectangle&quot; surrounding my line" ContentLicense="CC BY-SA 3.0" />
  <row Id="10685" PostHistoryTypeId="3" PostId="4597" RevisionGUID="2388a458-9d39-4d1b-89cb-15239ed5c0f9" CreationDate="2017-01-22T02:00:59.087" UserId="5900" Text="|line-drawing|antialiasing|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10686" PostHistoryTypeId="2" PostId="4598" RevisionGUID="2951b5da-276f-43e2-a7a2-125d143d5125" CreationDate="2017-01-22T03:05:38.667" UserId="2654" Text="It works almost exactly the same way as vertex shader inputs.&#xD;&#xA;&#xD;&#xA;In vertex shaders, you have inputs. And these inputs represent vertex attribute indices, the numbers you pass to `glVertexAttribPointer` and `glEnableVertexAttribArray` and so forth. You set up which input pulls from which attribute. In GLSL 3.30, you use this syntax:&#xD;&#xA;&#xD;&#xA;    layout(location = 2) in color;&#xD;&#xA;&#xD;&#xA;This sets the `color` vertex shader input to come from attribute location 2. Before 3.30 (or without ARB_explicit_attrib_location), you would have to either set this up explicitly with [`glBindAttrbLocation`][1] before linking or query the program for the attribute index with [`glGetAttribLocation`][2]. If you don't explicitly provide an attribute location, GLSL will assign a location *arbitrarily* (ie: in an implementation-defined manner).&#xD;&#xA;&#xD;&#xA;Setting it in the shader is almost always the better option.&#xD;&#xA;&#xD;&#xA;In any case, fragment shader outputs work almost exactly the same way. Fragment shaders can write to multiple buffers. Therefore, you need to indicate which output goes to which buffer.&#xD;&#xA;&#xD;&#xA;This process begins with the fragment output location value. It's set very similarly to vertex shader input locations:&#xD;&#xA;&#xD;&#xA;    layout(location = 1) out secColor;&#xD;&#xA;&#xD;&#xA;There are also the API functions [`glBindFragDataLocation`][3] and [`glGetFragDataLocation`][4], which are analogous to `glBindAttribLocation` and `glGetAttribLocation`.&#xD;&#xA;&#xD;&#xA;If you don't do any explicit assignments, implementations usually will assign one of your output variables to location 0. However, the OpenGL standard does not *require* this behavior, so you should not depend on it either.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl.org/wiki/GLAPI/glBindAttribLocation&#xD;&#xA;  [2]: http://www.opengl.org/wiki/GLAPI/glGetAttribLocation&#xD;&#xA;  [3]: http://www.opengl.org/wiki/GLAPI/glBindFragDataLocation&#xD;&#xA;  [4]: http://www.opengl.org/wiki/GLAPI/glGetFragDataLocation&#xD;&#xA;  [5]: http://www.opengl.org/wiki/GLAPI/glDrawBuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="10687" PostHistoryTypeId="5" PostId="4597" RevisionGUID="cc899562-811b-47fd-990d-a460e002e0f9" CreationDate="2017-01-22T03:11:47.250" UserId="231" Comment="Minor typos" Text="I am currently a beginner when it comes to anti-aliasing. I have read some notes online that how anti-aliasing works is that you first draw the line using an algorithm such as Bresenham's algorithm. Then you modify it to include anti-aliasing. &#xD;&#xA;&#xD;&#xA;Now, I understand that one method of anti-aliasing is to simply imagine there being a rectangle that encompasses the line and any pixel that touches that will be turned on or filled with an RGB value. &#xD;&#xA;&#xD;&#xA;Now if I know that area of the segment of the pixel that is cut off by the rectangle (let's assume the pixel is a circle) how would I use that area of the segment to compute the density of the colour which is from 0-1 (where 0 is very light and 1 is the darkest)?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10688" PostHistoryTypeId="5" PostId="4598" RevisionGUID="55a5bc36-c3af-4558-a091-b7410f52c084" CreationDate="2017-01-22T03:12:36.043" UserId="2654" Comment="added 190 characters in body" Text="It works almost exactly the same way as vertex shader inputs.&#xD;&#xA;&#xD;&#xA;In vertex shaders, you have inputs. And these inputs represent vertex attribute indices, the numbers you pass to `glVertexAttribPointer` and `glEnableVertexAttribArray` and so forth. You set up which input pulls from which attribute. In GLSL 3.30, you use this syntax:&#xD;&#xA;&#xD;&#xA;    layout(location = 2) in color;&#xD;&#xA;&#xD;&#xA;This sets the `color` vertex shader input to come from attribute location 2. Before 3.30 (or without ARB_explicit_attrib_location), you would have to either set this up explicitly with [`glBindAttrbLocation`][1] before linking or query the program for the attribute index with [`glGetAttribLocation`][2]. If you don't explicitly provide an attribute location, GLSL will assign a location *arbitrarily* (ie: in an implementation-defined manner).&#xD;&#xA;&#xD;&#xA;Setting it in the shader is almost always the better option.&#xD;&#xA;&#xD;&#xA;In any case, fragment shader outputs work almost exactly the same way. Fragment shaders can write to [multiple output colors][3], which themselves get mapped to [multiple buffers in the framebuffer][4]. Therefore, you need to indicate which output goes to which fragment output color.&#xD;&#xA;&#xD;&#xA;This process begins with the fragment output location value. It's set very similarly to vertex shader input locations:&#xD;&#xA;&#xD;&#xA;    layout(location = 1) out secColor;&#xD;&#xA;&#xD;&#xA;There are also the API functions [`glBindFragDataLocation`][5] and [`glGetFragDataLocation`][6], which are analogous to `glBindAttribLocation` and `glGetAttribLocation`.&#xD;&#xA;&#xD;&#xA;If you don't do any explicit assignments, implementations usually will assign one of your output variables to location 0. However, the OpenGL standard does not *require* this behavior, so you should not depend on it either.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl.org/wiki/GLAPI/glBindAttribLocation&#xD;&#xA;  [2]: http://www.opengl.org/wiki/GLAPI/glGetAttribLocation&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Fragment#Fragment_shader_outputs&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Framebuffer_Draw_Buffer&#xD;&#xA;  [5]: http://www.opengl.org/wiki/GLAPI/glBindFragDataLocation&#xD;&#xA;  [6]: http://www.opengl.org/wiki/GLAPI/glGetFragDataLocation" ContentLicense="CC BY-SA 3.0" />
  <row Id="10690" PostHistoryTypeId="2" PostId="4599" RevisionGUID="27ddd271-39e1-4e4a-bf2f-17798255b2e1" CreationDate="2017-01-22T07:30:09.780" UserId="5256" Text="Where can I learn about particle and fluid simulation? Is there a good book available?  I want to couple volume rendering with fluid/particle simulation to be able to finally render smoke and ocean with foam etc. Is there a chapter in PBRT on it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10691" PostHistoryTypeId="1" PostId="4599" RevisionGUID="27ddd271-39e1-4e4a-bf2f-17798255b2e1" CreationDate="2017-01-22T07:30:09.780" UserId="5256" Text="Particle &amp; Fluid Simulation: Where to learn?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10692" PostHistoryTypeId="3" PostId="4599" RevisionGUID="27ddd271-39e1-4e4a-bf2f-17798255b2e1" CreationDate="2017-01-22T07:30:09.780" UserId="5256" Text="|raytracing|rasterizer|fluid-sim|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10693" PostHistoryTypeId="2" PostId="4600" RevisionGUID="8deb4257-9174-4345-a97f-edd8bdc04bef" CreationDate="2017-01-22T07:47:39.300" UserId="4546" Text="PBRT handles only the rendering part, not the simulation part. There are several books out on game physics that handle fluid simulation, the one on my bookshelf is [David Eberly's &quot;Game Physics&quot;.][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.crcpress.com/Game-Physics/Eberly/p/book/9780123749031" ContentLicense="CC BY-SA 3.0" />
  <row Id="10694" PostHistoryTypeId="5" PostId="4596" RevisionGUID="5908ffca-a75a-47fd-85ac-fe2ecaede89a" CreationDate="2017-01-22T13:31:41.750" UserId="5852" Comment="added 192 characters in body" Text="**EDIT:** This is a duplicate of a question from stack overflow:&#xD;&#xA;http://stackoverflow.com/questions/9222217/how-does-the-fragment-shader-know-what-variable-to-use-for-the-color-of-a-pixel&#xD;&#xA;&#xD;&#xA;If you want to send a value from vertex shader to fragment shader, the vertex shader should declare one variable as `out`, the fragment shader should declare other variable as `in` and both variables must have their names and types equal. But this doesn't happen when you want to send the color value from the fragment shader. In fact, you can call the output variable as you want. Why? In older version there was one variable called `gl_FragColor`&lt;br /&gt;&#xD;&#xA;How the program links your output fragment variable with gl_FragColor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10695" PostHistoryTypeId="10" PostId="4599" RevisionGUID="82011cdf-3075-45d6-9029-d78b85882992" CreationDate="2017-01-22T14:34:13.780" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="10696" PostHistoryTypeId="5" PostId="4596" RevisionGUID="481a545d-4678-4201-8a47-36213dddea9c" CreationDate="2017-01-22T16:02:57.703" UserId="5852" Comment="added 823 characters in body" Text="**EDIT:** This is a duplicate of a question from stack overflow:&#xD;&#xA;http://stackoverflow.com/questions/9222217/how-does-the-fragment-shader-know-what-variable-to-use-for-the-color-of-a-pixel&#xD;&#xA;&#xD;&#xA;If you want to send a value from vertex shader to fragment shader, the vertex shader should declare one variable as `out`, the fragment shader should declare other variable as `in` and both variables must have their names and types equal. But this doesn't happen when you want to send the color value from the fragment shader. In fact, you can call the output variable as you want. Why? In older version there was one variable called `gl_FragColor`&lt;br /&gt;&#xD;&#xA;How the program links your output fragment variable with gl_FragColor?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;I cannot understand how fragment shaders can write to multiple buffers. As far as I understand, two shaders must have a variable with the same type and name for linking that variable between shaders. In the vertex shader you make a variable called &quot;position&quot; of the type &quot;ver3&quot; and &quot;in&quot;, but Where is defined a variable called &quot;color&quot; with the type &quot;in&quot; and &quot;vec4&quot; that collect the value of our &quot;color&quot; variable? How do you specify the buffers (and what are those buffers?) you want to send the value? what does really mean the sending of a vertex value from fragment shader to any buffer? If you want to draw a variable, you have to fill a buffer with 3 vertex data, but the shader takes all values between those 3 vertices (aka interpolation, I think). What of those values between the 3 vertices are sent?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10697" PostHistoryTypeId="5" PostId="4596" RevisionGUID="87dd4215-5928-4e7c-9fb1-dc613776695a" CreationDate="2017-01-22T16:08:31.160" UserId="5852" Comment="added 56 characters in body" Text="**EDIT:** This is a duplicate of a question from stack overflow:&#xD;&#xA;http://stackoverflow.com/questions/9222217/how-does-the-fragment-shader-know-what-variable-to-use-for-the-color-of-a-pixel&#xD;&#xA;&#xD;&#xA;If you want to send a value from vertex shader to fragment shader, the vertex shader should declare one variable as `out`, the fragment shader should declare other variable as `in` and both variables must have their names and types equal. But this doesn't happen when you want to send the color value from the fragment shader. In fact, you can call the output variable as you want. Why? In older version there was one variable called `gl_FragColor`&lt;br /&gt;&#xD;&#xA;How the program links your output fragment variable with gl_FragColor?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;I cannot understand how fragment shaders can write to multiple buffers. As far as I understand, two shaders must have a variable with the same type and name for linking that variable between shaders. In the vertex shader you make a variable called &quot;position&quot; of the type &quot;ver3&quot; and &quot;in&quot;, but Where is defined a variable called &quot;color&quot; with the type &quot;in&quot; and &quot;vec4&quot; that collect the value of our &quot;color&quot; variable? How do you specify the buffers (and what are those buffers?) you want to send the value? what does really mean the sending of a vertex value from fragment shader to any buffer? If you want to draw a variable, you have to fill a buffer with 3 vertex data, but the shader takes all values between those 3 vertices (aka interpolation, I think). What of those values between the 3 vertices are sent?&#xD;&#xA;&#xD;&#xA;I'm trying to learn opengl, but it seems impossible!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10698" PostHistoryTypeId="33" PostId="4554" RevisionGUID="48347bb6-b270-4f6b-a8c0-79ef178870a6" CreationDate="2017-01-23T06:31:55.287" UserId="5855" Comment="24" />
  <row Id="10700" PostHistoryTypeId="2" PostId="4601" RevisionGUID="f944239c-5bb1-4125-aabb-e7ad49d17db5" CreationDate="2017-01-23T14:49:30.837" UserId="3123" Text="Maybe not the best solution but one that should work would be to multiply them by matrix like&#xD;&#xA;\begin{bmatrix}-1&amp;0&amp;0\\0&amp;1&amp;0\\0&amp;0&amp;-1\end{bmatrix}&#xD;&#xA;And multiply by this your `mvp` matrix to convert meshes vertices (this could be done offline).&#xD;&#xA;&#xD;&#xA;Quaternion can be change to matrix form, multiply and save as quaternion.&#xD;&#xA;&#xD;&#xA;You also need to change culling in `OpenGL` because triangle order will be inverted.&#xD;&#xA;&#xD;&#xA;I did this in one project and it works fine. If I will find this project I will write something more about it.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;This matrix will invert your Z-axis and X-axis&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10701" PostHistoryTypeId="5" PostId="4601" RevisionGUID="26068088-5452-4159-bfea-2d97a491bcda" CreationDate="2017-01-23T16:47:53.753" UserId="3123" Comment="added 339 characters in body" Text="Maybe not the best solution but one that should work would be to multiply them by matrix like&#xD;&#xA;\begin{bmatrix}-1&amp;0&amp;0\\0&amp;1&amp;0\\0&amp;0&amp;-1\end{bmatrix}&#xD;&#xA;And multiply by this your `mvp` matrix to convert meshes vertices (this could be done offline).&#xD;&#xA;&#xD;&#xA;Quaternion can be change to matrix form, multiply and save as quaternion.&#xD;&#xA;&#xD;&#xA;You also need to change culling in `OpenGL` because triangle order will be inverted.&#xD;&#xA;&#xD;&#xA;I did this in one project and it works fine. If I will find this project I will write something more about it.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;This matrix will invert your Z-axis and X-axis&#xD;&#xA;&#xD;&#xA;//EDIT2&#xD;&#xA;&#xD;&#xA;To apply this solution to each to component you need to:&#xD;&#xA;&#xD;&#xA; 1. Change translation `x` and `z` component to `-x` and `-z`.&#xD;&#xA; 2. Rotation in matrix form multiply by matrix above and change it to quaternion.&#xD;&#xA; 3. Scale leave how it is.&#xD;&#xA; 4. Iterate through all meshes and multiply each of their vertices by this matrix.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10702" PostHistoryTypeId="2" PostId="4602" RevisionGUID="df52c5a6-eafc-46ce-a7a1-b405c0b7d527" CreationDate="2017-01-23T16:54:27.387" UserId="5910" Text="I had some magical tasks to do on my lessons. I had to write an app which performs some operations: basic (adding, substracting, multiplying a constant and a second image), geometric, filtering, histograms etc. There were ~50 tasks.&#xD;&#xA;&#xD;&#xA;I've made them all, even with Prewitt filters and other down/upbandwith and gradient things.&#xD;&#xA;&#xD;&#xA;Now, my teacher sent me an info, that I did my normalization wrong in basic operations, for ex. in adding a constant. &#xD;&#xA;&#xD;&#xA;As he wrote in his document there are 3 ways of handling the pixel overflow &gt;255 or &lt;0:&#xD;&#xA;&#xD;&#xA; - cutting the overflow - which means a simple clamp&#xD;&#xA; - scaling images before processing - dafuq&#xD;&#xA; - NORMALIZATION of the final image - scaling and moving the image function with a specified range that the final image fills the given range.&#xD;&#xA;&#xD;&#xA;I've left first two and got the third one, cause he said it's the correct way. I've read somewhere that I still need to combine it with a clamp (0,255).&#xD;&#xA;&#xD;&#xA;Now, I got his formula:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And  I thought it's easy to understand, but I have some problems with it.&#xD;&#xA;&#xD;&#xA;As I understand:&#xD;&#xA;&#xD;&#xA; - Fnorm - final pixel (normalized)&#xD;&#xA; - f - given pixel&#xD;&#xA; - fmin - minimum&#xD;&#xA; - fmax - extremum&#xD;&#xA; - Zrep - clamp 0-255?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*I have the following questions:*&#xD;&#xA;&#xD;&#xA;1. Are `fmin` and `fmax` taken from the given image, or from the image after the operation (for ex. adding a constant)? I know what extremes are, but I can't figure it out which two should I use in this formula.&#xD;&#xA;&#xD;&#xA;2. Is Zrep really a clamp method as I thought which just cuts to 0-255? I've read somewhere that even with normalization there can be an overflow.&#xD;&#xA;&#xD;&#xA;3. Does normalization work like: no matter what value you'll add or substract from the image, I'll make for you a beautiful 0-255 values? Or am I wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've even made some calculations, made some images in photoshop with extremes 30,200 and even 0,255, put them into the formula and got some results, but I still don't know if it's done well. &#xD;&#xA;&#xD;&#xA;I'm sitting here for 3 weeks, really and can't get which extremes should I use and if I should clamp or not. &#xD;&#xA;&#xD;&#xA;If there's anyone that could help me with it I would be grateful! Thanks very much!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vS1qd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10703" PostHistoryTypeId="1" PostId="4602" RevisionGUID="df52c5a6-eafc-46ce-a7a1-b405c0b7d527" CreationDate="2017-01-23T16:54:27.387" UserId="5910" Text="How to perform an image normalization after for ex. adding a constant to it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10704" PostHistoryTypeId="3" PostId="4602" RevisionGUID="df52c5a6-eafc-46ce-a7a1-b405c0b7d527" CreationDate="2017-01-23T16:54:27.387" UserId="5910" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10705" PostHistoryTypeId="2" PostId="4603" RevisionGUID="fa53714f-c8ff-4247-b448-3f6f6e2e4e73" CreationDate="2017-01-23T18:01:22.457" UserId="56" Text="Coming from an audio perspective dealing with dynamics processing (which is also digital signal processing of course!), here's the answers I would believe to be true.&#xD;&#xA;&#xD;&#xA; 1. fmin and fmax are the global min and max values of the image before it's processed.  Since in an RGB image you have three channels of data, the max would be the maximum value seen in any channel, and min would be the minimum value seen in any channel.&#xD;&#xA; 2. I have no idea what Zrep is unfortunately.  If you are truly normalizing the data, the only cause of overflow I can think of is due to rounding issues which can definitely happen.  Yes, I would clamp, but also I would do my operations in a larger non integer intermediary data format (such as floating point, or maybe fixed point) before clamping and then converting to the final data format (eg. from float to uint8).&#xD;&#xA; 3. Normalization will modify the signal such that it will span the entire range possible (0-255) however the result may not be &quot;beautiful&quot;.  Basically, you might find banding in the results where instead of a smooth gradient from one color to the next you might have very distinct bands of color steps.  You will see this being especially true if you don't use a larger non integer intermediary format like i mentioned in the last point, but can come up even if you do.&#xD;&#xA;&#xD;&#xA;By the way, there are other ways to deal with this situation of going out of range.  In the audio world there is such thing as limiters and compressors which deal with adjusting dynamics in a non linear way.&#xD;&#xA;&#xD;&#xA;A simplistic look at how they would apply to graphics would be that maybe you leave the color values that are between 32 and 223 alone so that most colors are unaffected, but then, colors less than 32 and colors greater than 223 get a non linear transformation to &quot;squish&quot; them into the valid range of values.&#xD;&#xA;&#xD;&#xA;If you are dealing with a high dynamic range image (HDR), you may have very large values in the thousands or ten thousands or higher.  As you can imagine, trying to squish all of that into the 223-255 range with a non linear transformation might be a little rediculous, so you may just squish in a certain amount (maybe make it so 512 input = 255 output in your remapping function), and then clamp the result.&#xD;&#xA;&#xD;&#xA;In case you are interested, games sometimes deal with this situation as you move from an indoors darker area to an outdoors brighter area.  Some games will make it so that the brighter outside is far too bright at first, and then over time, their colors will scale more towards being &quot;normal&quot;.  This is to mimic how it takes time for your eyes to adjust to bright light after being in the dark.  The reverse effect is also valid of course, of going from a bright area to a dark one, and having things be too dark until your eyes adjust.&#xD;&#xA;&#xD;&#xA;Lastly, in case you are interested, there is a lot of work being done in games and graphics on mapping HDR color values to LDR values, and applying color grading and tone mapping.  The work is focused not only on quality, but on speed, so there are different trade offs for real time processing vs off line processing." ContentLicense="CC BY-SA 3.0" />
  <row Id="10706" PostHistoryTypeId="5" PostId="4603" RevisionGUID="bff2009d-f195-4192-9587-ac6f81ff7eb2" CreationDate="2017-01-23T18:51:26.450" UserId="56" Comment="added 77 characters in body" Text="Coming from an audio perspective dealing with dynamics processing (which is also digital signal processing of course!), here's the answers I would believe to be true.&#xD;&#xA;&#xD;&#xA; 1. fmin and fmax are the global min and max values of the image before it's normalized (but after the adding a constant or whatever other processing has happened).  Since in an RGB image you have three channels of data, the max would be the maximum value seen in any channel, and min would be the minimum value seen in any channel.&#xD;&#xA; 2. I have no idea what Zrep is unfortunately.  If you are truly normalizing the data, the only cause of overflow I can think of is due to rounding issues which can definitely happen.  Yes, I would clamp, but also I would do my operations in a larger non integer intermediary data format (such as floating point, or maybe fixed point) before clamping and then converting to the final data format (eg. from float to uint8).&#xD;&#xA; 3. Normalization will modify the signal such that it will span the entire range possible (0-255) however the result may not be &quot;beautiful&quot;.  Basically, you might find banding in the results where instead of a smooth gradient from one color to the next you might have very distinct bands of color steps.  You will see this being especially true if you don't use a larger non integer intermediary format like i mentioned in the last point, but can come up even if you do.&#xD;&#xA;&#xD;&#xA;By the way, there are other ways to deal with this situation of going out of range.  In the audio world there is such thing as limiters and compressors which deal with adjusting dynamics in a non linear way.&#xD;&#xA;&#xD;&#xA;A simplistic look at how they would apply to graphics would be that maybe you leave the color values that are between 32 and 223 alone so that most colors are unaffected, but then, colors less than 32 and colors greater than 223 get a non linear transformation to &quot;squish&quot; them into the valid range of values.&#xD;&#xA;&#xD;&#xA;If you are dealing with a high dynamic range image (HDR), you may have very large values in the thousands or ten thousands or higher.  As you can imagine, trying to squish all of that into the 223-255 range with a non linear transformation might be a little rediculous, so you may just squish in a certain amount (maybe make it so 512 input = 255 output in your remapping function), and then clamp the result.&#xD;&#xA;&#xD;&#xA;In case you are interested, games sometimes deal with this situation as you move from an indoors darker area to an outdoors brighter area.  Some games will make it so that the brighter outside is far too bright at first, and then over time, their colors will scale more towards being &quot;normal&quot;.  This is to mimic how it takes time for your eyes to adjust to bright light after being in the dark.  The reverse effect is also valid of course, of going from a bright area to a dark one, and having things be too dark until your eyes adjust.&#xD;&#xA;&#xD;&#xA;Lastly, in case you are interested, there is a lot of work being done in games and graphics on mapping HDR color values to LDR values, and applying color grading and tone mapping.  The work is focused not only on quality, but on speed, so there are different trade offs for real time processing vs off line processing." ContentLicense="CC BY-SA 3.0" />
  <row Id="10707" PostHistoryTypeId="5" PostId="4601" RevisionGUID="e8011c12-b142-4400-8a02-1d8beeb87bc8" CreationDate="2017-01-23T21:24:55.267" UserId="3123" Comment="added 9 characters in body" Text="Maybe not the best solution but one that should work would be to multiply them by matrix like&#xD;&#xA;\begin{bmatrix}-1&amp;0&amp;0\\0&amp;1&amp;0\\0&amp;0&amp;-1\end{bmatrix}&#xD;&#xA;And multiply by this your `mvp` matrix to convert meshes vertices (this could be done offline).&#xD;&#xA;&#xD;&#xA;Quaternion can be change to matrix form, multiply and save as quaternion.&#xD;&#xA;&#xD;&#xA;You also need to change culling in `OpenGL` because triangle order will be inverted.&#xD;&#xA;&#xD;&#xA;I did this in one project and it works fine. If I will find this project I will write something more about it.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;This matrix will invert your Z-axis and X-axis&#xD;&#xA;&#xD;&#xA;//EDIT2&#xD;&#xA;&#xD;&#xA;To apply this solution to each to component you need to:&#xD;&#xA;&#xD;&#xA; 1. Change translation `x` and `z` component to `-x` and `-z`.&#xD;&#xA; 2. Rotation in matrix form multiply by matrix above and change it to quaternion.&#xD;&#xA; 3. Scale leave how it is.&#xD;&#xA;&#xD;&#xA; &lt;s&gt;4. Iterate through all meshes and multiply each of their vertices by this matrix.&lt;/s&gt;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10711" PostHistoryTypeId="5" PostId="4602" RevisionGUID="f1e89416-6c84-4bec-9174-7796e81704c5" CreationDate="2017-01-23T23:07:27.067" UserId="231" Comment="Remove redundant obsenity, fix typos, make formula formating consistent" Text="I had some magical tasks to do on my lessons. I had to write an app which performs some operations: basic (adding, subtracting, multiplying a constant and a second image), geometric, filtering, histograms etc. There were ~50 tasks.&#xD;&#xA;&#xD;&#xA;I've made them all, even with Prewitt filters and other down/upbandwith and gradient things.&#xD;&#xA;&#xD;&#xA;Now, my teacher sent me an info, that I did my normalization wrong in basic operations, for example in adding a constant. &#xD;&#xA;&#xD;&#xA;As he wrote in his document there are 3 ways of handling the pixel overflow &gt;255 or &lt;0:&#xD;&#xA;&#xD;&#xA; - cutting the overflow - which means a simple clamp&#xD;&#xA; - scaling images before processing&#xD;&#xA; - ***normalization*** of the final image - scaling and moving the image function with a specified range that the final image fills the given range.&#xD;&#xA;&#xD;&#xA;I've left first two and got the third one, because he said it's the correct way. I've read somewhere that I still need to combine it with a clamp (0,255).&#xD;&#xA;&#xD;&#xA;Now, I got his formula:&#xD;&#xA;&#xD;&#xA;$$\large f_{norm}=Z_{rep}[(f-f_{min})\div(f_{max}-f_{min})]$$&#xD;&#xA;&#xD;&#xA;And  I thought it's easy to understand, but I have some problems with it.&#xD;&#xA;&#xD;&#xA;As I understand:&#xD;&#xA;&#xD;&#xA; - $f_{norm}$ - final pixel (normalized)&#xD;&#xA; - $f$ - given pixel&#xD;&#xA; - $f_{min}$ - minimum&#xD;&#xA; - $f_{max}$ - extremum&#xD;&#xA; - $Z_{rep}$ - clamp 0-255?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*I have the following questions:*&#xD;&#xA;&#xD;&#xA;1. Are $f_{min}$ and $f_{max}$ taken from the given image, or from the image after the operation (for ex. adding a constant)? I know what extremes are, but I can't figure it out which two should I use in this formula.&#xD;&#xA;&#xD;&#xA;2. Is $Z_{rep}$ really a clamp method as I thought which just cuts to 0-255? I've read somewhere that even with normalization there can be an overflow.&#xD;&#xA;&#xD;&#xA;3. Does normalization work like: no matter what value you'll add or subtract from the image, I'll make for you a beautiful 0-255 values? Or am I wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've even made some calculations, made some images in photoshop with extremes 30,200 and even 0,255, put them into the formula and got some results, but I still don't know if it's done well. &#xD;&#xA;&#xD;&#xA;I'm sitting here for 3 weeks, really and can't get which extremes should I use and if I should clamp or not. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10712" PostHistoryTypeId="4" PostId="4602" RevisionGUID="f1e89416-6c84-4bec-9174-7796e81704c5" CreationDate="2017-01-23T23:07:27.067" UserId="231" Comment="Remove redundant obsenity, fix typos, make formula formating consistent" Text="How to perform an image normalization after for example adding a constant to it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10714" PostHistoryTypeId="2" PostId="4605" RevisionGUID="4809a659-7b10-4a42-a6d8-cb642e36140d" CreationDate="2017-01-24T04:10:30.857" UserId="3003" Text="I believe that `Zrep` is the output range. In 8-bit it would be 255. Let's say `fmin` was 25, `fmax` was 132. You want to scale that range to 0-255. The part of the equation in brackets: `[(f-fmin) / (fmax-fmin)]` will give you a percentage - a value between 0 and 1. If `f` is 25, you'd get 0%. If `f` is 89, you'd get ~60%. If it's 132, you'd get 100%&#xD;&#xA;&#xD;&#xA;So once you have the percentage, you then need to multiply that by the output range, `Zrep`. That converts from a percentage to whatever range you need it in, and ensures that the largest value in the input is mapped to the largest output value, and the smallest input is mapped to the smallest output value." ContentLicense="CC BY-SA 3.0" />
  <row Id="10717" PostHistoryTypeId="5" PostId="4601" RevisionGUID="8b873f7f-900c-4cb6-9646-fd8453c7a261" CreationDate="2017-01-24T12:41:48.473" UserId="3123" Comment="added 238 characters in body" Text="Maybe not the best solution but one that should work would be to multiply them by matrix like&#xD;&#xA;\begin{bmatrix}-1&amp;0&amp;0\\0&amp;1&amp;0\\0&amp;0&amp;-1\end{bmatrix}&#xD;&#xA;And multiply by this your `mvp` matrix to convert meshes vertices (this could be done offline).&#xD;&#xA;&#xD;&#xA;Quaternion can be change to matrix form, multiply and save as quaternion.&#xD;&#xA;&#xD;&#xA;You also need to change culling in `OpenGL` because triangle order will be inverted.&#xD;&#xA;&#xD;&#xA;I did this in one project and it works fine. If I will find this project I will write something more about it.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;This matrix will invert your Z-axis and X-axis&#xD;&#xA;&#xD;&#xA;//EDIT2&#xD;&#xA;&#xD;&#xA;To apply this solution to each to component you need to:&#xD;&#xA;&#xD;&#xA; 1. Change translation `x` and `z` component to `-x` and `-z`.&#xD;&#xA; 2. Rotation in matrix form multiply by matrix above and change it to quaternion.&#xD;&#xA; 3. Scale leave how it is.&#xD;&#xA;&#xD;&#xA; &lt;s&gt;4. Iterate through all meshes and multiply each of their vertices by this matrix.&lt;/s&gt;&#xD;&#xA;&#xD;&#xA;//EDIT3&#xD;&#xA;&#xD;&#xA;Instead of matrix you can just multiply rotation by quaternion `(0, 0, 1, 0)` (in order `(w, x, y, z)`) and new quaternion will look like this: `(-y,-z,w,-x)`. This operation (and matrix too) just rotate object by 180 degree in y-axis.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10718" PostHistoryTypeId="5" PostId="4601" RevisionGUID="301361cb-7e31-44a5-bb91-60d6cf098709" CreationDate="2017-01-24T13:10:29.947" UserId="3123" Comment="deleted 1 character in body" Text="Maybe not the best solution but one that should work would be to multiply them by matrix like&#xD;&#xA;\begin{bmatrix}-1&amp;0&amp;0\\0&amp;1&amp;0\\0&amp;0&amp;-1\end{bmatrix}&#xD;&#xA;And multiply by this your `mvp` matrix to convert meshes vertices (this could be done offline).&#xD;&#xA;&#xD;&#xA;Quaternion can be change to matrix form, multiply and save as quaternion.&#xD;&#xA;&#xD;&#xA;You also need to change culling in `OpenGL` because triangle order will be inverted.&#xD;&#xA;&#xD;&#xA;I did this in one project and it works fine. If I will find this project I will write something more about it.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;This matrix will invert your Z-axis and X-axis&#xD;&#xA;&#xD;&#xA;//EDIT2&#xD;&#xA;&#xD;&#xA;To apply this solution to each to component you need to:&#xD;&#xA;&#xD;&#xA; 1. Change translation `x` and `z` component to `-x` and `-z`.&#xD;&#xA; 2. Rotation in matrix form multiply by matrix above and change it to quaternion.&#xD;&#xA; 3. Scale leave how it is.&#xD;&#xA;&#xD;&#xA; &lt;s&gt;4. Iterate through all meshes and multiply each of their vertices by this matrix.&lt;/s&gt;&#xD;&#xA;&#xD;&#xA;//EDIT3&#xD;&#xA;&#xD;&#xA;Instead of matrix you can just multiply rotation by quaternion `(0, 0, 1, 0)` (in order `(w, x, y, z)`) and new quaternion will look like this: `(-y,z,w,-x)`. This operation (and matrix too) just rotate object by 180 degree in y-axis.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10719" PostHistoryTypeId="8" PostId="4596" RevisionGUID="3c26a15d-c0db-4e63-b8bc-b393eca3d562" CreationDate="2017-01-25T01:44:51.697" UserId="231" Comment="Rollback to [5908ffca-a75a-47fd-85ac-fe2ecaede89a]" Text="**EDIT:** This is a duplicate of a question from stack overflow:&#xD;&#xA;http://stackoverflow.com/questions/9222217/how-does-the-fragment-shader-know-what-variable-to-use-for-the-color-of-a-pixel&#xD;&#xA;&#xD;&#xA;If you want to send a value from vertex shader to fragment shader, the vertex shader should declare one variable as `out`, the fragment shader should declare other variable as `in` and both variables must have their names and types equal. But this doesn't happen when you want to send the color value from the fragment shader. In fact, you can call the output variable as you want. Why? In older version there was one variable called `gl_FragColor`&lt;br /&gt;&#xD;&#xA;How the program links your output fragment variable with gl_FragColor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10720" PostHistoryTypeId="5" PostId="4578" RevisionGUID="8c0fac61-163b-485a-a048-b73fbe4a2f26" CreationDate="2017-01-25T01:46:54.440" UserId="5884" Comment="Answering trichoplaxs question " Text="I am trying to get a normal of a triangle on a sphere, however the normal equations (straight line) give the wrong answer.&#xD;&#xA;&#xD;&#xA;For the points:&#xD;&#xA;&#xD;&#xA;$$(-986.786743, -93.348259, -132.439041)\\&#xD;&#xA;(210.731644, -534.785583, -818.290039)\\&#xD;&#xA;(637.734985, -449.826904, -553.501648)$$&#xD;&#xA;&#xD;&#xA;on a radius $1000$ sphere, the average point (straight line) is $(-0.074536, -0.580873, -0.810574) * 1000$, which is visibly incorrect on a sphere.&#xD;&#xA;&#xD;&#xA;The triangle's normal normalized to distance $1000$ gives: $(0.086455, 0.899604, -0.428062) * 1000$ which is different from the average value above (which would have also given a normal) and also far off from the spherical triangle.&#xD;&#xA;&#xD;&#xA;Edit: I was trying to unwrap a mesh into a globe to map it to a texture. I needed to know if triangles were upside down using normals." ContentLicense="CC BY-SA 3.0" />
  <row Id="10721" PostHistoryTypeId="24" PostId="4578" RevisionGUID="8c0fac61-163b-485a-a048-b73fbe4a2f26" CreationDate="2017-01-25T01:46:54.440" Comment="Proposed by 5884 approved by 209, 231 edit id of 195" ContentLicense="CC BY-SA 3.0" />
  <row Id="10722" PostHistoryTypeId="2" PostId="4606" RevisionGUID="3c753ed7-52cf-41e5-ab48-3699aa28dcdb" CreationDate="2017-01-25T09:02:25.943" UserId="2372" Text="Alright, this is a very general question but I've never found a precise and clear answer about this. This question might not be appropriate for [Computer Graphics StackExchange][1] but it's for learning purpose and I think that it might help a lot of people. So here it is :&#xD;&#xA;&#xD;&#xA;If Statements - implications and consequences&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;I've heard a lot that in shader development, you absolutely need to avoid branching and so if statements.&#xD;&#xA;&#xD;&#xA;But why ? Does this have a real impact on performances on old and modern hardware or is it more a case by case choice depending on your scenario.&#xD;&#xA;&#xD;&#xA;When possible, it's better to use preprocessor macros but when it's not, what can we do ?&#xD;&#xA;&#xD;&#xA;What are the purpose of using `flatten` or `branch` attributes ? Are there other solutions available ?&#xD;&#xA;&#xD;&#xA;Thanks a lot !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10723" PostHistoryTypeId="1" PostId="4606" RevisionGUID="3c753ed7-52cf-41e5-ab48-3699aa28dcdb" CreationDate="2017-01-25T09:02:25.943" UserId="2372" Text="If statements in shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="10724" PostHistoryTypeId="3" PostId="4606" RevisionGUID="3c753ed7-52cf-41e5-ab48-3699aa28dcdb" CreationDate="2017-01-25T09:02:25.943" UserId="2372" Text="|opengl|shader|glsl|hlsl|directx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10725" PostHistoryTypeId="2" PostId="4607" RevisionGUID="d4b20ed5-61ac-491c-8cc4-739f62dc092e" CreationDate="2017-01-25T09:12:49.897" UserId="5811" Text="Here's a very speedy 10 line maths fix for converting mesh to voxels... forget rays, dot products, square roots etc, edges, intersections do this:&#xD;&#xA;http://gamedev.stackexchange.com/questions/136243/how-can-i-randomly-pick-points-on-a-triangle/136250#136250" ContentLicense="CC BY-SA 3.0" />
  <row Id="10729" PostHistoryTypeId="5" PostId="4606" RevisionGUID="f9a5d4ad-c3a2-45f4-a6ac-e655fc735c14" CreationDate="2017-01-25T12:40:45.030" UserId="231" Comment="Remove &quot;thanks&quot; and &quot;maybe off topic&quot; and redundant second title and intro" Text="I've heard a lot that in shader development, you absolutely need to avoid branching and so if statements.&#xD;&#xA;&#xD;&#xA;But why? Does this have a real impact on performances on old and modern hardware or is it more a case by case choice depending on your scenario?&#xD;&#xA;&#xD;&#xA;When possible, it's better to use preprocessor macros but when it's not, what can we do?&#xD;&#xA;&#xD;&#xA;What is the purpose of using `flatten` or `branch` attributes? Are there other solutions available?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10730" PostHistoryTypeId="4" PostId="4606" RevisionGUID="f9a5d4ad-c3a2-45f4-a6ac-e655fc735c14" CreationDate="2017-01-25T12:40:45.030" UserId="231" Comment="Remove &quot;thanks&quot; and &quot;maybe off topic&quot; and redundant second title and intro" Text="If statements in shaders - implications and consequences" ContentLicense="CC BY-SA 3.0" />
  <row Id="10732" PostHistoryTypeId="10" PostId="4606" RevisionGUID="bb4c3cda-9448-4219-8098-61d8bdd6ff85" CreationDate="2017-01-25T18:12:42.110" UserId="-1" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[280],&quot;Voters&quot;:[{&quot;Id&quot;:137,&quot;DisplayName&quot;:&quot;ratchet freak&quot;},{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;}]}" />
  <row Id="10734" PostHistoryTypeId="50" PostId="4060" RevisionGUID="41136928-c3f3-4776-b123-b56f6e5b2cda" CreationDate="2017-01-26T16:49:07.363" UserId="-1" />
  <row Id="10738" PostHistoryTypeId="2" PostId="4609" RevisionGUID="8227e835-fed1-42ae-859f-72e4e6f44c2c" CreationDate="2017-01-26T18:34:21.427" UserId="5114" Text="### Short introduction###&#xD;&#xA;I created a function that interpolates the IES luminious intensities (candelas) using Hermite interpolation, so in my code all light sources have $I(\theta, \phi)$ function - but for simplicity lets assume we are dealing with a hemispherical light source with constant intensity $I = 100cd$ and we are dealing with monochromatic light.&#xD;&#xA;&#xD;&#xA;I managed to compute the direct illumination part from an IES point light source by calculating illuminance at each shading point using $E = \frac{I \cos(\theta_i)}{r^2}$ which I can easily convert to luminance $L_o$ by multiplying it by BRDF (since all my materials are diffuse, so $f_r = \frac{\rho}{\pi}$).&#xD;&#xA;&#xD;&#xA;This time I decided to implement _Instant Radiosity_ to approximate the global illumination using _Virtual Point Lights_. I did some research, and I found a [presentation with equations at slide 10 and 11](http://www.cs.cornell.edu/courses/cs6630/2012sp/slides/Boyadzhiev-Matzen-InstantRadiosity.pdf#10). So I spent my last month experimenting with it, but the results I've got are too dark.&#xD;&#xA;&#xD;&#xA;My current implementation is split into 2 applications. The first one is tracing random rays from light source. The second one is an OpenGL application for shading.&#xD;&#xA;&#xD;&#xA;### VPL generation (for single light path) ###&#xD;&#xA;1. Create a new ray in random direction&#xD;&#xA;2. Since I'm dealing with a point light, I believe that we can't calculate $L_i$, but I know that $L_o = f_r \times E$ and $E = \frac{I \cos{\theta_i}}{r^2}$ so now I know the outgoing luminance. Since I'm using a Lambertian BRDF, I know that $L_o$ is constant - that's why I store it as light intensity (I know that this is not &quot;luminious intensity&quot; per se, but at this point I don't know the outgoing direction).&#xD;&#xA;3. Randomize a new outgoing reflection direction.&#xD;&#xA;4. This time I know $L_i$ (it is equal to $L_o$ from previous iteration - no participating medium). I use [the equation from slide 10](http://www.cs.cornell.edu/courses/cs6630/2012sp/slides/Boyadzhiev-Matzen-InstantRadiosity.pdf#10), so $L_o = \frac{\rho}{\pi} L_i$. Again I store $L_o$ as VPL's intensity.&#xD;&#xA;5. Randomize a new outgoing (reflected) direction.&#xD;&#xA;6. `if (depth++ &lt; max_depth) goto step_4;`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Shading with VPLs ###&#xD;&#xA;1. Set the illumination accumulator to $E = 0$&#xD;&#xA;2. `foreach (vpl in vpls)`&#xD;&#xA;&#xD;&#xA;  a. Check light visibility $V$ (from shadow map), if in shadow then `continue`.&#xD;&#xA;&#xD;&#xA;  b. Compute the distance $r$ to light and a normalized vector $\hat{l}$ &quot;to the light&quot;&#xD;&#xA;&#xD;&#xA;  c. $E_{vpl} = I_{vpl} \frac{\cos{\theta_i} \cos{\theta_e}}{r^2}$, where $\cos \theta_e = \hat{l} \circ \hat{n}_{vpl}$ based on [equation from slide 11](http://www.cs.cornell.edu/courses/cs6630/2012sp/slides/Boyadzhiev-Matzen-InstantRadiosity.pdf#11)&#xD;&#xA;&#xD;&#xA;  d. `E += ` $\frac{E_{vpl}}{N}$, where $N$ is the number of traced light paths&#xD;&#xA;&#xD;&#xA;3. $L_o = f_r \times E$&#xD;&#xA;&#xD;&#xA;## Problem ##&#xD;&#xA;1. The problem is that the resulting $L_o$ values are always below $1$, while an identical scene rendered in Radiance (and limited to 1 bounce) has values above $20$.&#xD;&#xA;&#xD;&#xA;2. (If my method is wrong) How to compute VPLs intensity?&#xD;&#xA;&#xD;&#xA;3. In the mentioned [presentation at page 13](www.cs.cornell.edu/courses/cs6630/2012sp/slides/Boyadzhiev-Matzen-InstantRadiosity.pdf#13) is an algorithm (which I don't fully understand). Can somebody enlighten me how to calculate &quot;average_reflectivity&quot;? As you can see my implementation is derived from The Rendering Equation and the equations look similar.  " ContentLicense="CC BY-SA 3.0" />
  <row Id="10739" PostHistoryTypeId="1" PostId="4609" RevisionGUID="8227e835-fed1-42ae-859f-72e4e6f44c2c" CreationDate="2017-01-26T18:34:21.427" UserId="5114" Text="Calculating intensities of Virtual Point Lights in Instant Radiosity from IES lights" ContentLicense="CC BY-SA 3.0" />
  <row Id="10740" PostHistoryTypeId="3" PostId="4609" RevisionGUID="8227e835-fed1-42ae-859f-72e4e6f44c2c" CreationDate="2017-01-26T18:34:21.427" UserId="5114" Text="|rendering|raytracing|reflection|radiosity|photometric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10742" PostHistoryTypeId="2" PostId="4610" RevisionGUID="fd9b8db5-ae85-462c-9c20-163591dabf65" CreationDate="2017-01-27T00:23:32.123" UserId="2308" Text="I am in awe at [this app][1] I just found. It was actually one of the first things I installed when I first bought my iPad 2 but now they have updated it to add an HDR effect.&#xD;&#xA;&#xD;&#xA;I have never seen a real-time glow effect that looked quite this amazing. I have no clue how the developer pulled off such a large radius in realtime graphics.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have a game with similar unprocessed graphics to his. I have been trying to get a glow effect like this working but it has been near impossible. I am currently using separable convolution gaussian blur methods in addition to downscaling my blur mask. Still, it barely runs in real-time. It is nowhere near as big as a radius as this app pulls off and it certainly isn't as good of quality.&#xD;&#xA;&#xD;&#xA;Is there some method I am not thinking of?&#xD;&#xA;&#xD;&#xA;I am open to the possibility (but doubtful) that they are using really large textures with a falloff distance or that lighting is computed from the distance from a fragment to light sources. If you play with it and notice when the FPS drops it it just doesn't seem to have the right FPS to particle amount and HDR on/off quality to it to be that.&#xD;&#xA;&#xD;&#xA;  [1]: https://play.google.com/store/apps/details?id=com.volutopia.forgeofneon3d&amp;hl=en&#xD;&#xA;  [2]: https://i.stack.imgur.com/fTjVa.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10743" PostHistoryTypeId="1" PostId="4610" RevisionGUID="fd9b8db5-ae85-462c-9c20-163591dabf65" CreationDate="2017-01-27T00:23:32.123" UserId="2308" Text="How does this app pull off fast, high radius HDR" ContentLicense="CC BY-SA 3.0" />
  <row Id="10744" PostHistoryTypeId="3" PostId="4610" RevisionGUID="fd9b8db5-ae85-462c-9c20-163591dabf65" CreationDate="2017-01-27T00:23:32.123" UserId="2308" Text="|lighting|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10745" PostHistoryTypeId="2" PostId="4611" RevisionGUID="14c7ce3f-fba4-4714-bdb6-83eb2f308396" CreationDate="2017-01-27T01:32:22.360" UserId="2330" Text="I'm currently trying to implement a monte carlo path tracer. I've done some research and it seems that a common approach to materials is to use a layered model. Something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When light hits the surface, Fresnel tells us how much of that light is reflected by the first layer and how much goes to the second, and so forth.&#xD;&#xA;&#xD;&#xA;So I did something similar, but simpler: only one layer of specular and one layer of diffuse. No transmittance yet. So far so good, i use a simple cosine-weighted brdf for my diffuse and the Cook-Torrace microfaceted model for my specular. &#xD;&#xA;&#xD;&#xA;Now comes the hard part: what should i do once a ray hits the surface?&#xD;&#xA;Normally, I'd pick the brdf corresponding to the surface material, sample an incident light direction, evalue the brdf and divide by the right probability distribution function.&#xD;&#xA;But here, a surface hit effectively corresponds to multiple materials. The naive way to handle this would be to sample once for each layer hit. But this clearly is source of a huge performance hit, causing my path to effectively become a tree.&#xD;&#xA;&#xD;&#xA;Is there a better solution? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2ABBQ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10746" PostHistoryTypeId="1" PostId="4611" RevisionGUID="14c7ce3f-fba4-4714-bdb6-83eb2f308396" CreationDate="2017-01-27T01:32:22.360" UserId="2330" Text="Path tracer - multi layered materials and importance sampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="10747" PostHistoryTypeId="3" PostId="4611" RevisionGUID="14c7ce3f-fba4-4714-bdb6-83eb2f308396" CreationDate="2017-01-27T01:32:22.360" UserId="2330" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10748" PostHistoryTypeId="5" PostId="4611" RevisionGUID="1e4c57ff-aaf7-4662-b846-b543e548e00a" CreationDate="2017-01-27T02:41:31.480" UserId="2330" Comment="added 1 character in body" Text="I'm currently trying to implement a monte carlo path tracer. I've done some research and it seems that a common approach to materials is to use a layered model. Something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When light hits the surface, Fresnel tells us how much of that light is reflected by the first layer and how much goes to the second, and so forth.&#xD;&#xA;&#xD;&#xA;So I did something similar, but simpler: only one layer of specular and one layer of diffuse. No transmittance yet. So far so good, i use a simple cosine-weighted brdf for my diffuse and the Cook-Torrance microfaceted model for my specular. &#xD;&#xA;&#xD;&#xA;Now comes the hard part: what should i do once a ray hits the surface?&#xD;&#xA;Normally, I'd pick the brdf corresponding to the surface material, sample an incident light direction, evalue the brdf and divide by the right probability distribution function.&#xD;&#xA;But here, a surface hit effectively corresponds to multiple materials. The naive way to handle this would be to sample once for each layer hit. But this clearly is source of a huge performance hit, causing my path to effectively become a tree.&#xD;&#xA;&#xD;&#xA;Is there a better solution? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2ABBQ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10749" PostHistoryTypeId="2" PostId="4612" RevisionGUID="23f22497-4a92-4a6d-866e-7e66cbe30067" CreationDate="2017-01-27T03:06:37.117" UserId="182" Text="At CEDEC and GDC in the early 2000s, Masaki Kawase has presented a series of fast post-processing based lens effects, including large bloom. This presentation from GDC 2004 details them: [Practical Implementation of High Dynamic Range Rendering][1] (see slides 44 and upward: _&quot;Glare generation&quot;_).&#xD;&#xA;&#xD;&#xA;His bloom consist in sampling downsized versions of the original image using a carefully crafted equation to achieve a large yet spiky Gaussian blur.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.daionet.gr.jp/~masa/archives/GDC2004/GDC2004_PIoHDRR_EN.ppt" ContentLicense="CC BY-SA 3.0" />
  <row Id="10750" PostHistoryTypeId="5" PostId="4612" RevisionGUID="23aca2a9-78b1-429a-8851-871b19af28bf" CreationDate="2017-01-27T03:12:40.317" UserId="182" Comment="added 338 characters in body" Text="At CEDEC and GDC in the early 2000s, Masaki Kawase has presented a series of fast post-processing based lens effects, including large bloom.&#xD;&#xA;&#xD;&#xA;This presentation from GDC 2003, [Frame Buffer Postprocessing Effects in DOUBLE-S.T.E.A.L (Wreckless)][1] (see slides 15 and upwards: _&quot;Bloom&quot;_), gives a first version of the bloom. It consists in doing a Gaussian blur by sampling at exponentially increasing distances.&#xD;&#xA;&#xD;&#xA;In this presentation from GDC 2004, [Practical Implementation of High Dynamic Range Rendering][2] (see slides 44 and upward: _&quot;Glare generation&quot;_), he updates the technique. Instead of varying the sampling distance, he uses downsized versions of the original image, using a carefully crafted equation to achieve a large yet spiky Gaussian blur.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.daionet.gr.jp/~masa/archives/GDC2003_DSTEAL.ppt&#xD;&#xA;  [2]: http://www.daionet.gr.jp/~masa/archives/GDC2004/GDC2004_PIoHDRR_EN.ppt" ContentLicense="CC BY-SA 3.0" />
  <row Id="10751" PostHistoryTypeId="2" PostId="4613" RevisionGUID="e8456d6d-e4d9-4652-b28a-0177ceeb85e7" CreationDate="2017-01-27T06:38:04.500" UserId="3003" Text="One way to speed things up if you're doing this on a mobile GPU is to avoid indirect texture look-ups. This is where you calculate the texture coordinates then use the results of that calculation in the call to sample the texture. So it might be natural to write a 3-tap blur fragment shader doing something like this:&#xD;&#xA;&#xD;&#xA;    sample1 = texture2D(inputTexture, gl_TexCoord [ 0 ] - vec2(1.0, 0.0));&#xD;&#xA;    sample2 = texture2D(inputTexture, gl_TexCoord [ 0 ]);&#xD;&#xA;    sample3 = texture2D(inputTexture, gl_TexCoord [ 0 ] + vec2(1.0, 0.0));&#xD;&#xA;&#xD;&#xA;You can get around this by doing the calculation in the vertex shader or on the CPU. You can use multi texturing to get around this when you have very straightforward situations like above. You can set texture coordinates for textures 1 and 2 to be offset by 1 pixel in either direction from those in texture 0. Your fragment shader then becomes:&#xD;&#xA;&#xD;&#xA;    sample1 = texture2D(inputTexture, gl_TexCoord [ 0 ]);&#xD;&#xA;    sample2 = texture2D(inputTexture, gl_TexCoord [ 1 ]);&#xD;&#xA;    sample3 = texture2D(inputTexture, gl_TexCoord [ 2 ]);&#xD;&#xA;&#xD;&#xA;Now you're not doing any calculations to figure out texture coordinates." ContentLicense="CC BY-SA 3.0" />
  <row Id="10752" PostHistoryTypeId="2" PostId="4614" RevisionGUID="58926afa-9f07-4112-a4c7-c4d71db5197a" CreationDate="2017-01-27T10:58:22.070" UserId="2372" Text="I've heard a lot about **jittering** and **dithering** but I would like to know more about those technics, especially when used to avoid visible sampling in a fragment shader.&#xD;&#xA;&#xD;&#xA; - What are the differences between both ?&#xD;&#xA; - When are they used the most ?&#xD;&#xA; - What's the best way to implement them&#xD;&#xA; - Can we combine them ?&#xD;&#xA;&#xD;&#xA;Thanks a lot !" ContentLicense="CC BY-SA 3.0" />
  <row Id="10753" PostHistoryTypeId="1" PostId="4614" RevisionGUID="58926afa-9f07-4112-a4c7-c4d71db5197a" CreationDate="2017-01-27T10:58:22.070" UserId="2372" Text="What are Jittering and Dithering" ContentLicense="CC BY-SA 3.0" />
  <row Id="10754" PostHistoryTypeId="3" PostId="4614" RevisionGUID="58926afa-9f07-4112-a4c7-c4d71db5197a" CreationDate="2017-01-27T10:58:22.070" UserId="2372" Text="|opengl|shader|glsl|hlsl|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10755" PostHistoryTypeId="2" PostId="4615" RevisionGUID="3895650d-9c87-42a1-b0fa-c8e0de7b11a8" CreationDate="2017-01-27T11:48:34.043" UserId="5256" Text="In my ray tracer, I render my images out to a .PPM file and then view it in photoshop. To make things easier and faster I want my ray tracer to open up another window and show the image being rendered each ray at a time like how modern renderers like Mental Ray or V-Ray do it. &#xD;&#xA;&#xD;&#xA;How can I do this? Do I simply just open a window read the .PPM file into the window as it is being rendered? Should I use a UI framework like .NET? " ContentLicense="CC BY-SA 3.0" />
  <row Id="10756" PostHistoryTypeId="1" PostId="4615" RevisionGUID="3895650d-9c87-42a1-b0fa-c8e0de7b11a8" CreationDate="2017-01-27T11:48:34.043" UserId="5256" Text="Ray Tracing: How to watch image being ray traced?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10757" PostHistoryTypeId="3" PostId="4615" RevisionGUID="3895650d-9c87-42a1-b0fa-c8e0de7b11a8" CreationDate="2017-01-27T11:48:34.043" UserId="5256" Text="|raytracing|c++|ui|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10758" PostHistoryTypeId="5" PostId="4615" RevisionGUID="43c811dc-f72a-4484-93ea-bc1ecabd6c0a" CreationDate="2017-01-27T14:25:18.617" UserId="5256" Comment="added 89 characters in body" Text="In my ray tracer, I render my images out to a .PPM file and then view it in photoshop. To make things easier and faster I want my ray tracer to open up another window and show the image being rendered each ray at a time like how modern renderers like Mental Ray or V-Ray do it. &#xD;&#xA;&#xD;&#xA;How can I do this? Do I simply just open a window read the .PPM file into the window as it is being rendered? Should I use a UI framework like .NET? &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UyUk5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10759" PostHistoryTypeId="2" PostId="4616" RevisionGUID="0f9aefae-a017-4488-91bc-1a7932e2cb82" CreationDate="2017-01-27T14:42:29.203" UserId="5807" Text="Probably a simple question.&#xD;&#xA;&#xD;&#xA;I would like to downsample my depth buffer and my normals.&#xD;&#xA;For that, I take in input of my shader, the corresponding textures (depth, normal), and I write my new values in a multi render target.&#xD;&#xA;&#xD;&#xA;I downsample the normals by doing a simple average of four texels and for the depth buffer, I can choose the max or min of four texels.&#xD;&#xA;&#xD;&#xA;My color attachment's format for the downsampled buffer is R32F.&#xD;&#xA;How could I write my new depth floating point value in it ?&#xD;&#xA;I tried : `gl_FragData[1].r = newDepth;` &#xD;&#xA;But it doesn't seem to store correctly a float with 32 bits precision.&#xD;&#xA;&#xD;&#xA;To get a pixel's depth, I know that I can do : &#xD;&#xA;`float depth = texture2D(depth, tc).x;`&#xD;&#xA;But what about to output a single float with 32 bits precision ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10760" PostHistoryTypeId="1" PostId="4616" RevisionGUID="0f9aefae-a017-4488-91bc-1a7932e2cb82" CreationDate="2017-01-27T14:42:29.203" UserId="5807" Text="How to output a 32 floating value in a render buffer with fragment shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="10761" PostHistoryTypeId="3" PostId="4616" RevisionGUID="0f9aefae-a017-4488-91bc-1a7932e2cb82" CreationDate="2017-01-27T14:42:29.203" UserId="5807" Text="|shader|3d|glsl|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10762" PostHistoryTypeId="2" PostId="4617" RevisionGUID="6a8208d4-bb8f-45e5-a837-7c4c57762539" CreationDate="2017-01-27T15:00:28.523" UserId="2041" Text="Jittering and dithering are both techniques of adding noise to reduce visible artefacts (such as banding) in an image. They solve different kinds of artefacts so they are used in different situations. Jittering moves sample positions in space to reduce artefacts caused by regular sampling. Dithering changes the way colours are rounded (when reducing precision), replacing banding with noise.&#xD;&#xA;&#xD;&#xA;# When is jittering used?&#xD;&#xA;&#xD;&#xA;A use case for jittering is when generating eye rays in a ray-tracer. Without jittering, you might generate one ray in the centre of each pixel. But then if you trace those at a regular pattern, such as a grille of bars each one pixel wide, you might find that every ray hits a bar, making the grille solid; or that every ray hits a gap, and the grille isn't seen at all.&#xD;&#xA;&#xD;&#xA;Instead, you can add a small stochastic displacement to each ray direction, so that each ray goes through a different part of its pixel. That way, some rays will hit the bars of the grille and some will hit the gaps, making a noisy image instead of a completely wrong image.&#xD;&#xA;&#xD;&#xA;# When is dithering used?&#xD;&#xA;&#xD;&#xA;The normal use of dithering is when rounding colours (intensity values) from a high-precision format (such as floating-point numbers) to a low-precision format (such as 8-bit integers). Say you have a smooth gradient you want to represent in an 8-bit image. If you round each number separately, then starting from the black end of the gradient, you get a lot of black pixels until they get light enough to round to 1/256; then these all have the same value until you get to 2/256; and so on. You end up with regular bands where all the pixels have the same value.&#xD;&#xA;&#xD;&#xA;Instead, when you round the first number down, you can let it &quot;donate&quot; the lost intensity to another nearby pixel. That way, then at the black end of the gradient, maybe every tenth pixel is 1/256 and the other nine are 0. The ratio of black to nearly-black pixels increases gradually, until eventually all the pixels are 1/256, and then every tenth is 2/256, and so on. Instead of visible bands, the overall intensity increases smoothly along the gradient - but the price of this is that pixels which should be the same are slightly different, adding noise.&#xD;&#xA;&#xD;&#xA;Dithering is used a lot in printing, where the colour resolution is quite poor (i.e. the steps between colours are big) but the spatial resolution (how small you can make each dot of colour) is very fine. It used to be used in the days of 256-colour displays for making colours which couldn't otherwise be represented, and it's still used to avoid banding when displaying (for example) a 16-bit-per-channel image on an 8-bit display.&#xD;&#xA;&#xD;&#xA;## Is dithering the only way?&#xD;&#xA;Because traditional dithering algorithms involve giving information from each pixel to its neighbours, they don't parallelise well, so they're not suited to modern hardware. Another popular technique is to deliberately add noise to the source image. The range of the noise is less than one step of the destination format (e.g. the noise ranges from -1/512 to 1/512), so it can't be seen directly, but it means that each pixel will be rounded differently. Like true dithering, it replaces any banding with subtle noise in the output image.&#xD;&#xA;&#xD;&#xA;# Can we combine them?&#xD;&#xA;There's no reason you can't use both in the same image, but as they solve different problems, that's not really &quot;combining&quot; them. It's like asking if we can combine hoses and axes. A fire truck has both, and the firefighters might use both at the same incident, but one is for extinguishing fires and the other is for freeing trapped people.&#xD;&#xA;&#xD;&#xA;An example of when you might use both is if you ray-trace an image into a floating-point framebuffer, using jittered ray positions to avoid sampling artefacts, and then reduce that to an 8-bit image using dithering to better preserve the colours." ContentLicense="CC BY-SA 3.0" />
  <row Id="10763" PostHistoryTypeId="5" PostId="4615" RevisionGUID="2181b1d9-7675-49e9-a187-5bbdd9353cdd" CreationDate="2017-01-27T19:56:50.397" UserId="5256" Comment="added 10 characters in body" Text="In my ray tracer, I render my images out to a .PPM file and then view it in photoshop. To make things easier and faster I want my ray tracer to open up another window and show the image being rendered each ray at a time like how modern renderers like Mental Ray or V-Ray do it. &#xD;&#xA;&#xD;&#xA;If I do this by displaying the image in the win32 window, will I continuosly need to 'refresh' the image to see the changes or will loading the image be fine?&#xD;&#xA; &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UyUk5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10764" PostHistoryTypeId="5" PostId="4615" RevisionGUID="423c8f65-c48c-4aa0-9de7-0d31375481e4" CreationDate="2017-01-28T05:50:52.703" UserId="5256" Comment="added 237 characters in body" Text="In my ray tracer, I render my images out to a .PPM file and then view it in photoshop. To make things easier and faster I want my ray tracer to open up another window and show the image being rendered each ray at a time like how modern renderers like Mental Ray or V-Ray do it. &#xD;&#xA;&#xD;&#xA;If I do this by displaying the image in the win32 window, will I continuosly need to 'refresh' the image to see the changes or will loading the image be fine?&#xD;&#xA;&#xD;&#xA;Could I use `set pixel `in the loop where I store the color data for the image each time a pixel is shaded?&#xD;&#xA;&#xD;&#xA;*(the image below is 3DS Max with Mental Ray which shows image being rendered each Ray at a time, I want to achieve this)*&#xD;&#xA; &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UyUk5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10765" PostHistoryTypeId="5" PostId="4615" RevisionGUID="09460546-c684-4c49-a92e-331bf9993c65" CreationDate="2017-01-28T07:20:30.227" UserId="5256" Comment="added 458 characters in body" Text="In my ray tracer, I render my images out to a .PPM file and then view it in photoshop. To make things easier and faster I want my ray tracer to open up another window and show the image being rendered each ray at a time like how modern renderers like Mental Ray or V-Ray do it. &#xD;&#xA;&#xD;&#xA;How is this done? What is the most common method? I tried writing a viewer in C# that uses a `picturebox` to load the image which is then constantly refreshed but that doesn't work since the image cannot be shared. After asking on reddit most people suggested writing the image to an OpenGL quad as a texture but I don't want to do this as it complicates things. I've taken a look at at the `setpixel` function which will set the pixel's color at a specified coordinate and color, is this the way to do it? &#xD;&#xA;&#xD;&#xA;It is really great to watch your image be rendered, it is also helpful because if your image is rendering wrong you can stop rather than waiting for the entire image to rendered and then noticing there is a problem. &#xD;&#xA;&#xD;&#xA;*(the image below is 3DS Max with Mental Ray which shows image being rendered each Ray at a time, I want to achieve this)*&#xD;&#xA; &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UyUk5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="10766" PostHistoryTypeId="4" PostId="4615" RevisionGUID="09460546-c684-4c49-a92e-331bf9993c65" CreationDate="2017-01-28T07:20:30.227" UserId="5256" Comment="added 458 characters in body" Text="How to watch image being ray traced?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10767" PostHistoryTypeId="5" PostId="4534" RevisionGUID="916e9411-99c5-4788-8985-a0fccd64c49a" CreationDate="2017-01-28T09:23:15.077" UserId="38" Comment="deleted 2 characters in body" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathematics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;# The modellers perspective on things&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathematics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because its easier to think in one orientation or just simply because you want to move/rotate/scale objects out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minimum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straight ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;# Computational perspective&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. For example you need to know the point localtion in camera space to render. Preferably all this space transform happens automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other, a hierarchy, for modelers benefit. &#xD;&#xA;&#xD;&#xA;Although this could be done in any number of ways it is commonly done with a tree structure, much like a filesystem with much the same effect. Each level stores in addition to tree information a affine matrix that describes the transform to its predecessor in the hierarchy. Mainly because this takes care of two core issues. The tree structure is easy to traverse and find the path to any other part. The matrices solve the problem of needing to do a lot of work transforming form a transform from one hierarchy space to another.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to transform the object to the coordinates of the object it is described in relation to, the parent. This parent in turn in turn describes the transform to it's parent all the way to the world. Since all objects share one common ancestor, world, we can easily traverse the tree to find a transform path from any one coordinate system to another coordinate system.&#xD;&#xA;&#xD;&#xA;Since linear transforms are invertible, we do not need to store a description separately for moving in the opposite direction, away from world towards the children/leaves of the tree structure. All we need to do is to invert the matrix. This is almost always needed as its practical to describe camera as a separate object under the world, there is no reason to describe the cameras transform from world to camera just treat it like any other object.&#xD;&#xA;&#xD;&#xA;To compute a point from one space to another you do as follows:&#xD;&#xA;&#xD;&#xA;1. use the tree to find a relationship between spaces.&#xD;&#xA;2. For each step on the way pre multiply your matrix/ or its inverse if your traversing away from world. \*\*&#xD;&#xA;&#xD;&#xA;Example:  You have a following hierarchy because it makes sense (this way you do not need to model each petal separately)&#xD;&#xA;&#xD;&#xA;    World&#xD;&#xA;      |&#xD;&#xA;      +---- Flower&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 1&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 2&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 3&#xD;&#xA;      |&#xD;&#xA;      +---- Track&#xD;&#xA;             |&#xD;&#xA;             +--- Boom&#xD;&#xA;                   |&#xD;&#xA;                   +--- Camera&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To render Petal 1 you need to transform the vertices of petal one into the camera object space and form there to perspective space etc. Your calculation would be:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    T_{Perspective} \cdot T_{Camera}^{-1} \cdot T_{Boom}^{-1} \cdot T_{Track}^{-1} \cdot T_{Flower} \cdot T_{Petal 1} \cdot \vec{v}_{PetalPoint}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why. You should understand also that we do not have any limit to complexity of the hierarchy to &#xD;&#xA;facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This kind of hierarchy is called a scene graph and such things can be found in web pages, vector and cad applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;# Do we absolutely need these?&#xD;&#xA;&#xD;&#xA;No, we do not. we can dispense all the matrices and describe all of our data directly in the cameras final coordinates. Its just that this is horribly complicated in 98% of the cases.&#xD;&#xA;&#xD;&#xA;In practice we need this hierarchy if we try to do even something more complex than a stationary box. Most of this deign is to make scene modellers life easier. So that simple operations make more sense.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because its a tree, and earliest tree graphs are genealogical studies, aka family trees. Where the previous level is simply the parents and the next one is their children. &#xD;&#xA;&#xD;&#xA;\*\* or the other way around if you want to transpose your calculations.&#xD;&#xA;&#xD;&#xA;PS: Written on my  phone at after work beer waiting for my coworkers to arrive so maybe i will still improve this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10768" PostHistoryTypeId="2" PostId="4618" RevisionGUID="6dcbdd7a-6c15-4c4a-a367-221080268515" CreationDate="2017-01-28T12:24:24.843" UserId="1608" Text="This is a very common question that most people in your situation (interested or fascinated shall I say in Computer Graphics) have and a problem they want to figure out. The solution is pretty simple, though not necessarily that straightforward to implement.&#xD;&#xA;&#xD;&#xA;I can't make a specific answer because it depends on the OS you are using, and as I said this is not something you can do in 2 lines of code.&#xD;&#xA;&#xD;&#xA;The answer is to use some sort of library that:&#xD;&#xA;&#xD;&#xA; 1. allows you to create a window on your system&#xD;&#xA; 2. allows you to display some content (an image) in the window you created and displayed to the screen&#xD;&#xA;&#xD;&#xA;The first task is generally quite complex regardless of the OS you use (MacOS, Windows, Linux). For the second step, you need to generally go through some sort of graphics API (like OpenGL).&#xD;&#xA;&#xD;&#xA;So there is hope for you. One thing you can do is use some other library that works as a wrapper around 1) and 2) In other words they help you especially with the creation of the window, and then if you know OpenGL you can do the rest of the work. You will need to create some texture that you will fill with the content of your image as it gets rendered and display this texture to the screen (that's pretty basic in OpenGL though you need to know this API in order to do so).&#xD;&#xA;&#xD;&#xA;[GLFW][1] is a great library that will allow you to do that. It's simple to use and compile and install, etc. You can alternatively use Qt but I don't recommend it unless you want to become a professional programmer.&#xD;&#xA;&#xD;&#xA;I had some documentation about the whole process but it's offline right now. I might put it back in a few weeks but you will need to wait I am afraid.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glfw.org/docs/latest/quick.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="10769" PostHistoryTypeId="2" PostId="4619" RevisionGUID="926e11fb-0064-42ed-8f57-b3dbc5f3ea8a" CreationDate="2017-01-28T13:22:55.387" UserId="4546" Text="Wenzel Jakob et al presented a [framework for layered Materials][1] at SIGGRAPH 2014. Section 6.2 explains importance sampling. If you prefer code over equations, the method is implemented in the [Mitsuba renderer][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.cornell.edu/projects/layered-sg14/layered.pdf&#xD;&#xA;  [2]: http://www.mitsuba-renderer.org" ContentLicense="CC BY-SA 3.0" />
  <row Id="10771" PostHistoryTypeId="5" PostId="4614" RevisionGUID="7b73e0b9-5ac5-483f-a1ef-63efcdb8c91f" CreationDate="2017-01-28T14:15:19.090" UserId="231" Comment="Minor typos and remove &quot;thanks!&quot;" Text="I've heard a lot about **jittering** and **dithering** but I would like to know more about those techniques, especially when used to avoid visible sampling in a fragment shader.&#xD;&#xA;&#xD;&#xA; - What are the differences between both?&#xD;&#xA; - When are they used the most?&#xD;&#xA; - What's the best way to implement them?&#xD;&#xA; - Can we combine them?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10772" PostHistoryTypeId="5" PostId="4618" RevisionGUID="a732bbb4-6f66-451d-972e-18abe8616738" CreationDate="2017-01-28T14:22:48.743" UserId="1608" Comment="added 1078 characters in body" Text="This is a very common question that most people in your situation (interested or fascinated shall I say in Computer Graphics) have and a problem they want to figure out. The solution is pretty simple, though not necessarily that straightforward to implement.&#xD;&#xA;&#xD;&#xA;I can't make a specific answer because it depends on the OS you are using, and as I said this is not something you can do in 2 lines of code.&#xD;&#xA;&#xD;&#xA;The answer is to use some sort of library that:&#xD;&#xA;&#xD;&#xA; 1. allows you to create a window on your system&#xD;&#xA; 2. allows you to display some content (an image) in the window you created and displayed to the screen&#xD;&#xA;&#xD;&#xA;The first task is generally quite complex regardless of the OS you use (MacOS, Windows, Linux). For the second step, you need to generally go through some sort of graphics API (like OpenGL).&#xD;&#xA;&#xD;&#xA;So there is hope for you. One thing you can do is use some other library that works as a wrapper around 1) and 2) In other words they help you especially with the creation of the window, and then if you know OpenGL you can do the rest of the work. You will need to create some texture that you will fill with the content of your image as it gets rendered and display this texture to the screen (that's pretty basic in OpenGL though you need to know this API in order to do so).&#xD;&#xA;&#xD;&#xA;[GLFW][1] is a great library that will allow you to do that. It's simple to use and compile and install, etc. You can alternatively use Qt but I don't recommend it unless you want to become a professional programmer.&#xD;&#xA;&#xD;&#xA;I had some documentation about the whole process but it's offline right now. I might put it back in a few weeks but you will need to wait I am afraid.&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;I am editing the answer to respond to your comment. The algorithm would look like this:&#xD;&#xA;&#xD;&#xA;    Color *buffer = Color  char [w * h];&#xD;&#xA;    // create a texture that you can map onto the quad stretched over the area&#xD;&#xA;    // of the window. You will need to create a quad rendered in the space of the&#xD;&#xA;    // window, aka you in 2D not 3D.&#xD;&#xA;    ...&#xD;&#xA;    // now render your image using you ray-tracer&#xD;&#xA;    for (j = 0; j &lt; h; ++h) {&#xD;&#xA;        for (i =0; i &lt; w; ++i) {&#xD;&#xA;            buffer[j * w + i] =  trace(orig, dir, ...);&#xD;&#xA;        }&#xD;&#xA;        // it is not very efficient to update your window each time you have &#xD;&#xA;        // a new pixel so do this every row or every 10 rows ... you get the idea&#xD;&#xA;        // copy content of your buffer into the GL texture&#xD;&#xA;        // I am not using the right calls here, too lazy to find the right ones&#xD;&#xA;        glCopyTexture(myGLTextureId, buffer, (sizeof(char) * 3 * w * h); &#xD;&#xA;        // do the texture binding, etc... all GL or DX stuff&#xD;&#xA;        ...&#xD;&#xA;        // this will update your window with the content of the buffer&#xD;&#xA;        glSwapBuffer(); &#xD;&#xA;    }&#xD;&#xA;    // now save content of buffer to image file&#xD;&#xA;    saveToDisk(buffer);&#xD;&#xA;&#xD;&#xA;Windows? Arg(. You will have to use DirectX calls indeed but they 2 APIs are very close.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glfw.org/docs/latest/quick.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="10773" PostHistoryTypeId="5" PostId="4616" RevisionGUID="626a7a49-b9ec-41cc-8562-b8075d38426b" CreationDate="2017-01-28T14:23:17.460" UserId="231" Comment="Add 2 spaces after newlines to produce intended formatting (please revert if not your intention)" Text="I would like to downsample my depth buffer and my normals.  &#xD;&#xA;For that, I take in input of my shader, the corresponding textures (depth, normal), and I write my new values in a multi render target.&#xD;&#xA;&#xD;&#xA;I downsample the normals by doing a simple average of four texels and for the depth buffer, I can choose the max or min of four texels.&#xD;&#xA;&#xD;&#xA;My color attachment's format for the downsampled buffer is R32F.  &#xD;&#xA;How could I write my new depth floating point value in it?  &#xD;&#xA;I tried: `gl_FragData[1].r = newDepth;` &#xD;&#xA;But it doesn't seem to store correctly a float with 32 bits precision.&#xD;&#xA;&#xD;&#xA;To get a pixel's depth, I know that I can do:  &#xD;&#xA;`float depth = texture2D(depth, tc).x;`  &#xD;&#xA;But what about to output a single float with 32 bits precision?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10775" PostHistoryTypeId="2" PostId="4620" RevisionGUID="9aac43c9-12fa-4fee-b547-7cc1b7d617f4" CreationDate="2017-01-28T14:44:13.377" UserId="4958" Text="In QtCreator IDE (C++) any kind of image buffer - result of CPU raytracing or (what I did) frames captured from the camera can be easily rendered or painted on Widget - which is simplest part of the UI available in QtDesigner - UI designer.&#xD;&#xA;&#xD;&#xA;You could send your ray tracing engine class to another thread and use timer which would emit signal to send your image through signal/slot mechanism to GUI main thread and paint it on the widget. It's quite simple actually. No need of OpenGL or DirectX API. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10776" PostHistoryTypeId="5" PostId="4620" RevisionGUID="f6c2284b-a726-4d0f-98be-a6fc0aae5c14" CreationDate="2017-01-28T14:51:49.923" UserId="4958" Comment="added 22 characters in body" Text="In QtCreator IDE (C++) any kind of image buffer - result of CPU raytracing or (what I did) frames captured from the camera can be easily rendered or painted on Widget - which is simplest part of the UI available in QtDesigner - UI designer.&#xD;&#xA;&#xD;&#xA;You could send your ray tracing engine class to another thread and use timer which every once in a while would emit signal to send your image through signal/slot mechanism to GUI main thread and paint it on the widget. It's quite simple actually. No need of OpenGL or DirectX API. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10777" PostHistoryTypeId="2" PostId="4621" RevisionGUID="6280cba8-788f-4965-8b8a-6178b9f5ee44" CreationDate="2017-01-28T23:33:50.787" UserId="5943" Text="Given a point and a line segment, how do you calculate the barycentric coordinates of the point to the line?&#xD;&#xA;&#xD;&#xA;bool BarycentricCoordinates(const Vector3&amp; point, const Vector3&amp; a, const Vector3&amp; b, float&amp; u, float&amp; v, float epsilon)" ContentLicense="CC BY-SA 3.0" />
  <row Id="10778" PostHistoryTypeId="1" PostId="4621" RevisionGUID="6280cba8-788f-4965-8b8a-6178b9f5ee44" CreationDate="2017-01-28T23:33:50.787" UserId="5943" Text="Barycentric Coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="10779" PostHistoryTypeId="3" PostId="4621" RevisionGUID="6280cba8-788f-4965-8b8a-6178b9f5ee44" CreationDate="2017-01-28T23:33:50.787" UserId="5943" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10784" PostHistoryTypeId="2" PostId="4623" RevisionGUID="3a4b527d-3ef5-4323-8e1d-b6b716f4f6b0" CreationDate="2017-01-29T10:31:39.703" UserId="3434" Text="Let's say I have a have 10 different terrains. Each terrain have the same x and z coordinates, but they have different y coordinate, normals and colors. The indices used for element rendering is also the same.&#xD;&#xA;&#xD;&#xA;The data looks like this:&#xD;&#xA;&#xD;&#xA;    std::vector&lt;GLfloat&gt; xzCoords;&#xD;&#xA;    std::vector&lt;GLuint&gt; indices;&#xD;&#xA;    &#xD;&#xA;    std::vector&lt;GLfloat&gt; yCoords[10];&#xD;&#xA;    std::vector&lt;GLfloat&gt; normals[10];&#xD;&#xA;    std::vector&lt;GLfloat&gt; colors[10];&#xD;&#xA;&#xD;&#xA;And the VBO and VAO IDs:&#xD;&#xA;&#xD;&#xA;    GLuint VAO_IDs[10];&#xD;&#xA;    GLuint VBO_xzCoord_IDs[10];&#xD;&#xA;    GLuint VBO_yCoord_IDs[10];&#xD;&#xA;    GLuint VBO_indices_IDs[10];&#xD;&#xA;    GLuint VBO_normals_IDs[10];&#xD;&#xA;    GLuint VBO_colors_IDs[10];&#xD;&#xA;	&#xD;&#xA;If I want one VAO for each of the terrain deffinitions, how would that look if the VBO for xz coordinates and indices are the same for each?&#xD;&#xA;&#xD;&#xA;What I am doing now looks like this:&#xD;&#xA;&#xD;&#xA;Setting up the buffers:&#xD;&#xA;&#xD;&#xA;    for (size_t i = 0; i &lt; 10; i++){&#xD;&#xA;    		//VAO&#xD;&#xA;    		glGenVertexArrays(1, &amp;VAO_IDs[i]);&#xD;&#xA;    		glBindVertexArray(VAO_IDs[i]);&#xD;&#xA;    &#xD;&#xA;    		//VBO&#xD;&#xA;    		glGenBuffers(1, &amp;VBO_xzCoord_IDs[i]);&#xD;&#xA;    		glGenBuffers(1, &amp;VBO_yCoord_IDs[i]);&#xD;&#xA;    		glGenBuffers(1, &amp;VBO_indices_IDs[i]);&#xD;&#xA;            glGenBuffers(1, &amp;VBO_normals_IDs[i]);&#xD;&#xA;            glGenBuffers(1, &amp;VBO_colors_IDs[i]);&#xD;&#xA;    &#xD;&#xA;    		//xz coords&#xD;&#xA;    		glBindBuffer(GL_ARRAY_BUFFER, VBO_xzCoord_IDs[i]);&#xD;&#xA;    		glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*xzCoords.size(), &amp;xzCoords[0], GL_STATIC_DRAW);&#xD;&#xA;    		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;    		glEnableVertexAttribArray(0);&#xD;&#xA;    		//y coords&#xD;&#xA;    		glBindBuffer(GL_ARRAY_BUFFER, VBO_yCoord_IDs[i]);&#xD;&#xA;    		glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*yCoords[i].size(), &amp;yCoords[i][0], GL_STREAM_DRAW);&#xD;&#xA;    		glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;    		glEnableVertexAttribArray(1);&#xD;&#xA;    		//normals&#xD;&#xA;    		glBindBuffer(GL_ARRAY_BUFFER, VBO_normals_IDs[i]);&#xD;&#xA;    		glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VBO_normals_IDs[i].size(), &amp;VBO_normals_IDs[i][0], GL_STREAM_DRAW);&#xD;&#xA;    		glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;    		glEnableVertexAttribArray(2);&#xD;&#xA;    		//colors&#xD;&#xA;    		glBindBuffer(GL_ARRAY_BUFFER, VBO_colors_IDs[i]);&#xD;&#xA;    		glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VBO_colors_IDs[i].size(), &amp;VBO_colors_IDs[i][0], GL_STREAM_DRAW);&#xD;&#xA;    		glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;    		glEnableVertexAttribArray(3);&#xD;&#xA;    &#xD;&#xA;    //indices&#xD;&#xA;    		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);&#xD;&#xA;    		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indices.size(), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;Rendering function:&#xD;&#xA;&#xD;&#xA;    for (size_t i = 0; i &lt; 10; i++)&#xD;&#xA;    	{&#xD;&#xA;    		glBindVertexArray(VAO_IDs[i]);&#xD;&#xA;    		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);&#xD;&#xA;    		glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void*)0);&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So as you can see, I create a new xz-coordinates and indices buffer for each VAO. I doubt this is the most effective way to do it. How should I do this?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10785" PostHistoryTypeId="1" PostId="4623" RevisionGUID="3a4b527d-3ef5-4323-8e1d-b6b716f4f6b0" CreationDate="2017-01-29T10:31:39.703" UserId="3434" Text="Multiple VAO share a VBO" ContentLicense="CC BY-SA 3.0" />
  <row Id="10786" PostHistoryTypeId="3" PostId="4623" RevisionGUID="3a4b527d-3ef5-4323-8e1d-b6b716f4f6b0" CreationDate="2017-01-29T10:31:39.703" UserId="3434" Text="|opengl|rendering|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10789" PostHistoryTypeId="2" PostId="4625" RevisionGUID="245672c5-b069-43d4-b218-0f53a3010d4a" CreationDate="2017-01-29T15:52:14.177" UserId="4958" Text="VAO can share VBO's because they do not store vertex data itself but references to Vertex Buffer Objects. &#xD;&#xA;&#xD;&#xA;So you can first generate your buffers and upload your buffer data (vertex data and index data) to currently bound buffers.&#xD;&#xA;&#xD;&#xA;    glGenBuffers(1, &amp;VBO_xzCoord_IDs[i]);&#xD;&#xA;    glGenBuffers(1, &amp;VBO_yCoord_IDs[i]);&#xD;&#xA;    glGenBuffers(1, &amp;VBO_indices_IDs[i]);&#xD;&#xA;    glGenBuffers(1, &amp;VBO_normals_IDs[i]);&#xD;&#xA;    glGenBuffers(1, &amp;VBO_colors_IDs[i]);&#xD;&#xA;&#xD;&#xA;    //xz coords&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO_xzCoord_IDs[i]);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*xzCoords.size(), &amp;xzCoords[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    //indices&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indices.size(), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And then generate your VAO's and connect vertex array object data index you provide in `glVertexAttribPointer` call with currently bound `GL_ARRAY_BUFFER`.&#xD;&#xA;&#xD;&#xA;The `GL_ELEMENT_ARRAY_BUFFER` can be a little confusing because it doesn't require `glVertexAttribPointer` call. So how it is connected with VAO? It seems that binding the buffer ties it to the currently bound VAO.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAO&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO_IDs[i]);&#xD;&#xA;    glBindVertexArray(VAO_IDs[i]);&#xD;&#xA;&#xD;&#xA;    //xz coords&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO_xzCoord_IDs[i]);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;            &#xD;&#xA;    ...&#xD;&#xA;            &#xD;&#xA;    //indices&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;And in your rendering call you don't need to bind `GL_ELEMENT_ARRAY_BUFFER` because it was already connected with VAO." ContentLicense="CC BY-SA 3.0" />
  <row Id="10790" PostHistoryTypeId="2" PostId="4626" RevisionGUID="80de9eab-43d1-4807-a791-30edf7f7f213" CreationDate="2017-01-29T16:24:12.903" UserId="3434" Text="In my project, for convenience I would like to use many buffers. &#xD;&#xA;Many buffers in my case means 50-100 terrain patches represented by buffers with vertex coordinates, normals, indices and maybe color. The magnitude of data would be, let's say **10^4 floats** per buffer. Some of this data can be shared between each terrain patch, f.ex. xz-coordinates and indices.&#xD;&#xA;&#xD;&#xA;During the rendering loop, some terrain patches will be updated. Which means that for certain buffers I call `glBufferSubData()` for the whole buffer.&#xD;&#xA;  &#xD;&#xA;My question is; is there pros/cons performance wise of these two methods:&#xD;&#xA;&#xD;&#xA;**1)** Controlling my data in many buffers (50-100), thus letting me call `glBufferSubData` on a complete buffer when needed.&#xD;&#xA;&#xD;&#xA;**2)** Controlling my data in fewer (5-20) buffers, with more data in each. But then having to set up a system where I need to call *glBufferSubData* on smaller portion of a buffer. (Which leads to a more complex design in my case). &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10791" PostHistoryTypeId="1" PostId="4626" RevisionGUID="80de9eab-43d1-4807-a791-30edf7f7f213" CreationDate="2017-01-29T16:24:12.903" UserId="3434" Text="Multiple buffers and calling glBufferSubData" ContentLicense="CC BY-SA 3.0" />
  <row Id="10792" PostHistoryTypeId="3" PostId="4626" RevisionGUID="80de9eab-43d1-4807-a791-30edf7f7f213" CreationDate="2017-01-29T16:24:12.903" UserId="3434" Text="|opengl|vertex-buffer-object|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10793" PostHistoryTypeId="5" PostId="4626" RevisionGUID="0035cf63-f68e-4e02-bfea-e0d4f64db1e7" CreationDate="2017-01-29T16:29:22.060" UserId="3434" Comment="added 11 characters in body" Text="In my project, for convenience I would like to use many buffers. &#xD;&#xA;Many buffers in my case means 50-100 terrain patches represented by buffers with vertex coordinates, normals, indices and maybe color. The magnitude of data would be, let's say **10^4 floats** per buffer. Some of this data can be shared between each terrain patch, f.ex. xz-coordinates and indices.&#xD;&#xA;&#xD;&#xA;During the rendering loop, some terrain patches will be updated. Which means that for certain buffers I call `glBufferSubData()` for the whole buffer.&#xD;&#xA;  &#xD;&#xA;My question is; are there any pros/cons, performance wise between these two methods:&#xD;&#xA;&#xD;&#xA;**1)** Controlling my data in many buffers (50-100), thus letting me call `glBufferSubData` on a complete buffer when needed.&#xD;&#xA;&#xD;&#xA;**2)** Controlling my data in fewer (5-20) buffers, with more data in each. But then having to set up a system where I need to call *glBufferSubData* on smaller portion of a buffer. (Which leads to a more complex design in my case). &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10794" PostHistoryTypeId="2" PostId="4627" RevisionGUID="71961c69-6d6d-493d-aae5-72a4aafb92fc" CreationDate="2017-01-29T17:05:14.790" UserId="2096" Text="I want to about some technique with which i can generate nice reflections on the surface. I know one conventional technique where we invert an object and render it and blend it with the floor but in this technique each object has to be rendered twice which is not good. Is there any other technique to achieve the same result?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10795" PostHistoryTypeId="1" PostId="4627" RevisionGUID="71961c69-6d6d-493d-aae5-72a4aafb92fc" CreationDate="2017-01-29T17:05:14.790" UserId="2096" Text="Which technique is fast to generate real-time reflections?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10796" PostHistoryTypeId="3" PostId="4627" RevisionGUID="71961c69-6d6d-493d-aae5-72a4aafb92fc" CreationDate="2017-01-29T17:05:14.790" UserId="2096" Text="|opengl|rendering|real-time|reflection|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10797" PostHistoryTypeId="2" PostId="4628" RevisionGUID="22ffc242-5864-42b5-bae8-b6b0c86f8abd" CreationDate="2017-01-29T19:58:21.713" UserId="5002" Text="Usually modern game engines use [Screen Space Reflections][1] which iq some kind of screen space raymarching.&#xD;&#xA;&#xD;&#xA;Basically, a simple way to achieve this is to shoot rays from the G-buffer. This means you use your depth buffer as a height field by raymarching any ray you cast. Then sample the normal at this position and take the final composed lighting from you previous frame and project it.&#xD;&#xA;&#xD;&#xA;You can find a few [articles][2] about that and [presentations][3] on the Internet.&#xD;&#xA;&#xD;&#xA;Although it has the usual drawbacks associated with any screen space method. This means you only have what is visible in front of you (screen space) to compute your reflections, so anything outside the screen would require tricks to have them get reflected on your current frame (e.g. you can combine this with environment mapping reflections and such).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/ScreenSpaceReflection/&#xD;&#xA;  [2]: http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html&#xD;&#xA;  [3]: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10798" PostHistoryTypeId="5" PostId="4628" RevisionGUID="5a818450-7019-43bd-b208-e85eb0295878" CreationDate="2017-01-29T20:35:15.287" UserId="5002" Comment="edited body" Text="Usually modern game engines use [Screen Space Reflections][1] which is some kind of screen space raymarching.&#xD;&#xA;&#xD;&#xA;Basically, a simple way to achieve this is to shoot rays from the G-buffer. This means you use your depth buffer as a height field by raymarching any ray you cast. Then sample the normal at this position and take the final composed lighting from you previous frame and project it.&#xD;&#xA;&#xD;&#xA;You can find a few [articles][2] about that and [presentations][3] on the Internet.&#xD;&#xA;&#xD;&#xA;Although it has the usual drawbacks associated with any screen space method. This means you only have what is visible in front of you (screen space) to compute your reflections, so anything outside the screen would require tricks to have them get reflected on your current frame (e.g. you can combine this with environment mapping reflections and such).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/ScreenSpaceReflection/&#xD;&#xA;  [2]: http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html&#xD;&#xA;  [3]: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10799" PostHistoryTypeId="5" PostId="4628" RevisionGUID="b50017a3-342d-4342-b842-fc24ccf9369f" CreationDate="2017-01-29T22:14:55.970" UserId="5002" Comment="deleted 2 characters in body" Text="Usually modern game engines use [Screen Space Reflections][1] which is some kind of screen space raymarching.&#xD;&#xA;&#xD;&#xA;Basically, a simple way to achieve this is to shoot rays from the G-buffer. This means you use your depth buffer as a height field by raymarching any ray you cast. Then sample the normal at this position and take the final composed lighting from you previous frame and project it.&#xD;&#xA;&#xD;&#xA;Although it has the usual drawbacks associated with any screen space method. This means you only have what is visible in front of you (screen space) to compute your reflections, so anything outside the screen would require tricks to have them get reflected on your current frame (e.g. you can combine this with environment mapping reflections and such).&#xD;&#xA;&#xD;&#xA;You can find a few [articles][2] about that and [presentations][3] on the Internet.&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/ScreenSpaceReflection/&#xD;&#xA;  [2]: http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html&#xD;&#xA;  [3]: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10801" PostHistoryTypeId="5" PostId="4627" RevisionGUID="fa4a04ea-49da-4ac2-9218-7f240d2da79e" CreationDate="2017-01-30T14:50:15.433" UserId="2096" Comment="added 5 characters in body" Text="I want to know about some technique with which i can generate nice reflections on the surface. I know one conventional technique where we invert an object and render it and blend it with the floor but in this technique each object has to be rendered twice which is not good. Is there any other technique to achieve the same result?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10805" PostHistoryTypeId="2" PostId="4630" RevisionGUID="ec22628f-d8dd-4edf-be16-e2377e5dd3e1" CreationDate="2017-01-30T17:29:42.183" UserId="5958" Text="This is PNG was exported from Inkscape.  I created it manually and used the&#xD;&#xA;connector tool to link tables.&#xD;&#xA;&#xD;&#xA;I find the plain SVG for this diagram more complicated than I was expecting so would like to know if there are simpler graphic languages or specifications for this task?&#xD;&#xA;&#xD;&#xA;I would like to write something using Python.&#xD;&#xA;&#xD;&#xA;Here's the pastebin: [SVG for database diagram][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://pastebin.com/PDEupPFr&#xD;&#xA;  [2]: https://i.stack.imgur.com/ixSgo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10806" PostHistoryTypeId="1" PostId="4630" RevisionGUID="ec22628f-d8dd-4edf-be16-e2377e5dd3e1" CreationDate="2017-01-30T17:29:42.183" UserId="5958" Text="What graphic languages are simpler than SVG for database diagrams?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10807" PostHistoryTypeId="3" PostId="4630" RevisionGUID="ec22628f-d8dd-4edf-be16-e2377e5dd3e1" CreationDate="2017-01-30T17:29:42.183" UserId="5958" Text="|api|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10808" PostHistoryTypeId="2" PostId="4631" RevisionGUID="6752c426-5688-4479-9bd8-af75a262d30b" CreationDate="2017-01-30T17:50:53.680" UserId="48" Text="[Graphviz](http://www.graphviz.org/) is a popular tool for making network diagrams. It takes a text format (&quot;DOT language&quot;) describing the nodes and edges as input, and can render the resulting diagram to SVG or other image formats." ContentLicense="CC BY-SA 3.0" />
  <row Id="10809" PostHistoryTypeId="6" PostId="4630" RevisionGUID="8dfdc719-2341-4be1-a266-aa09fd7882c2" CreationDate="2017-01-30T17:54:30.523" UserId="48" Comment="improve tags" Text="|2d|vector-graphics|diagram|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10810" PostHistoryTypeId="2" PostId="4632" RevisionGUID="b7241242-3f19-482b-a299-90bc3453532c" CreationDate="2017-01-30T19:16:44.263" UserId="5960" Text="I'm creating a renderer using modern OpenGL (3.1 and up) and now I'm trying to create an efficient but flexible way of handling uniforms. I've been reading up on uniform buffer objects and on what a 'common' approach is to using these (the latter unfortunately didn't give me as many results as I had hoped).&#xD;&#xA;&#xD;&#xA;In order to reduce OpenGL API calls and storing data in contiguous memory, I'm considering creating multiple large buffers for each data structure that should be uploaded to the GPU. Each buffer has a maximum size of 16kb (as from what I understand this much is guaranteed to be available for an UBO). When an object wants to be able to upload uniforms to the GPU it fetches the first buffer of the to-be-uploaded-type that isn't full yet and gets the next available index in that buffer. When the object is drawn it binds the UBO (if not bound yet) and uploads the element index of the UBO.&#xD;&#xA;&#xD;&#xA;This results in something like this:&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform ModelData { &#xD;&#xA;        mat4 model_matrix[kNumInstancesPerModelUbo]; &#xD;&#xA;    }&#xD;&#xA;    uniform int u_ModelDataIndex;&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform SkeletonData { &#xD;&#xA;        mat4 bone_transforms[kNumInstancesPerSkeletonUbo][kMaxBones]; &#xD;&#xA;    }&#xD;&#xA;    uniform int u_SkeletonDataIndex;&#xD;&#xA;&#xD;&#xA;However I'm also considering the following:&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform MeshData {&#xD;&#xA;        mat4 model_matrix[kNumInstancesPerMeshUbo];&#xD;&#xA;        mat4 bone_transforms[kNumInstancesPerMeshUbo][kMaxBones];&#xD;&#xA;    }&#xD;&#xA;    uniform int u_MeshDataIndex;&#xD;&#xA;&#xD;&#xA;In some ways this feels a lot cleaner in that it takes a single index to access all data related to the mesh to be uploaded. On the other hand this could get out of hand (buffer size larger than 16kb, handles to irrelevant data (e.g. a mesh with no skeleton) or even synchronization issues as you're not allowed access to say the bones while uploading the model matrices) and I'm not sure how this would affect the memory layout on the GPU either.&#xD;&#xA;&#xD;&#xA;Frankly it feels like I'm stuck here and I can't find a good concrete example of how you'd go about handling UBO's fast and flexible. &#xD;&#xA;&#xD;&#xA;Do you have any advice or resources for me that could help me out here?&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10811" PostHistoryTypeId="1" PostId="4632" RevisionGUID="b7241242-3f19-482b-a299-90bc3453532c" CreationDate="2017-01-30T19:16:44.263" UserId="5960" Text="What is a good approach for handing uniforms in modern opengl?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10812" PostHistoryTypeId="3" PostId="4632" RevisionGUID="b7241242-3f19-482b-a299-90bc3453532c" CreationDate="2017-01-30T19:16:44.263" UserId="5960" Text="|opengl|rendering|glsl|c++|uniform-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10816" PostHistoryTypeId="2" PostId="4634" RevisionGUID="ee8c5535-1680-4ee1-8b5a-cda93bad9eee" CreationDate="2017-01-30T19:56:54.660" UserId="56" Text="If you have a point $C$ on a line defined by a point $A$ and a point $B$, here is how you calculate the barycentric coordinates $(t_0,t_1)$:&#xD;&#xA;&#xD;&#xA;$t_0 = \frac{sqrt((C_x-A_x)^2+(C_y-A_y)^2)}{sqrt((B_x-A_x)^2+(B_y-A_y)^2)}$&#xD;&#xA;&#xD;&#xA;$t_1 = 1.0 - t_0$&#xD;&#xA;&#xD;&#xA;In other words, you calculate the length of the vector from $A$ to $C$, and divide that by the length of the vector from $A$ to $B$.  This gives you $t_0$, and you can subtract that from 1.0 to get $t_1$ since barycentric coordinates always add up to 1.0.&#xD;&#xA;&#xD;&#xA;A more mathish style version of the above is this:&#xD;&#xA;&#xD;&#xA;$t_0 = \frac{\left\| C-A\right\|}{\left\| B-A\right\|}$&#xD;&#xA;&#xD;&#xA;$t_1 = 1.0 - t_0$&#xD;&#xA;&#xD;&#xA;But it's important to note that $C$ must be on the line defined by $A$ and $B$.  If that isn't the case, let us know and let us know what it is you are trying to do specifically.  For instance, maybe you want to project some other point $D$ onto the line $\overline{AB}$ and then find the barycentric coordinates of that projected point?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10817" PostHistoryTypeId="4" PostId="4621" RevisionGUID="613916a4-c884-44b1-855a-bb2edc295006" CreationDate="2017-01-30T20:03:22.677" UserId="56" Comment="edited title" Text="Barycentric Coordinates of a Point on a Line" ContentLicense="CC BY-SA 3.0" />
  <row Id="10818" PostHistoryTypeId="2" PostId="4635" RevisionGUID="fa144305-7e56-475c-86b3-063b2099993b" CreationDate="2017-01-30T20:10:13.587" UserId="5961" Text="How do I test to see if a polygon edge is facing another polygon? The edge being tested needs to be a polygon which has a different attribute than itself.&#xD;&#xA;&#xD;&#xA;![polygon example](https://drive.google.com/uc?export=download&amp;id=0B5gF5vQzfd2SMDFERkhxUE1heEk)&#xD;&#xA;&#xD;&#xA;In this example, I am iterating through the edges on Polygon A. Segment 0 and segment 1 would return true for facing the polygon, where segment 2 would return false, because, while it is still facing a polygon, the polygon has the same 'green' attribute." ContentLicense="CC BY-SA 3.0" />
  <row Id="10819" PostHistoryTypeId="1" PostId="4635" RevisionGUID="fa144305-7e56-475c-86b3-063b2099993b" CreationDate="2017-01-30T20:10:13.587" UserId="5961" Text="Test if polygon edge is facing another polygon" ContentLicense="CC BY-SA 3.0" />
  <row Id="10820" PostHistoryTypeId="3" PostId="4635" RevisionGUID="fa144305-7e56-475c-86b3-063b2099993b" CreationDate="2017-01-30T20:10:13.587" UserId="5961" Text="|algorithm|computational-geometry|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10821" PostHistoryTypeId="5" PostId="4635" RevisionGUID="14540cc2-bb38-48d2-8d03-f8e1df8ac2e9" CreationDate="2017-01-30T20:30:24.947" UserId="5961" Comment="added 7 characters in body" Text="How do I test to see if a polygon edge is facing another polygon? For the edge being tested to return true, the edge needs to be facing a polygon which has a different attribute than itself.&#xD;&#xA;&#xD;&#xA;![polygon example](https://drive.google.com/uc?export=download&amp;id=0B5gF5vQzfd2SMDFERkhxUE1heEk)&#xD;&#xA;&#xD;&#xA;In this example, I am iterating through the edges on Polygon A. Segment 0 and segment 1 would return true for facing the polygon, where segment 2 would return false, because, while it is still facing a polygon, the polygon has the same 'green' attribute." ContentLicense="CC BY-SA 3.0" />
  <row Id="10822" PostHistoryTypeId="2" PostId="4636" RevisionGUID="dafd0712-ba12-47e9-9287-440224bc2512" CreationDate="2017-01-30T21:22:18.990" UserId="48" Text="It depends. There are a few competing factors at work here.&#xD;&#xA;&#xD;&#xA;First, consolidating terrain data into fewer buffers (or one) may allow you to combine multiple terrain patches together in a single draw call—assuming there aren't other state changes between patches that would prevent this. So, you may be able to reduce draw-call overhead this way, or at least reduce the state-change overhead between draws. That being said, 50–100 draw calls is not that many, so this may not be a real performance concern.&#xD;&#xA;&#xD;&#xA;In addition, do you anticipate needing to use the terrain data for other shader effects? For example, maybe a shader procedurally generates grass growing on the terrain, or you use height above the terrain to influence lighting or AO or some such. In that case having all the terrain data in one big buffer that you can pass to those shaders may simplify things.&#xD;&#xA;&#xD;&#xA;On the other hand, if you're having the terrain deformed/edited in real-time (which it sounds like you are), then it may be faster to update the entirety of a small buffer than to update a small portion of a large buffer. The problem is when the CPU and GPU are working asynchronously, and you update a buffer from the CPU, the GPU may still be using the previous version of that buffer. To fix this, the driver internally keeps 2–3 instances of the buffer (much like double/triple buffering the screen). If you always update the entire buffer at once, the driver can just put the updated data into the &quot;next&quot; instance of that buffer. But if you update only part of the buffer, the driver must copy all the _rest_ of the data from the current instance to the next instance. This extra copy will consume some performance either on the CPU or on the GPU.&#xD;&#xA;&#xD;&#xA;So, if the terrain data was entirely static I'd say it's better to put it all in one big buffer. However, if you're going to be updating portions of the data in real-time, it may be better to keep it in smaller buffers so that you can update exactly the ones that have changed while leaving others alone.&#xD;&#xA;&#xD;&#xA;In the end, you'll have to do some profiling to see which approach is better." ContentLicense="CC BY-SA 3.0" />
  <row Id="10824" PostHistoryTypeId="2" PostId="4637" RevisionGUID="c27fbbe8-227b-44ae-9e20-75e3742c0b38" CreationDate="2017-01-30T23:55:32.017" UserId="5852" Text="If no, Should I create a new VAO for every VBO that has its own vertex attribute configurations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10825" PostHistoryTypeId="1" PostId="4637" RevisionGUID="c27fbbe8-227b-44ae-9e20-75e3742c0b38" CreationDate="2017-01-30T23:55:32.017" UserId="5852" Text="Can one VAO store multiple calls to glVertexAttribPointer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10826" PostHistoryTypeId="3" PostId="4637" RevisionGUID="c27fbbe8-227b-44ae-9e20-75e3742c0b38" CreationDate="2017-01-30T23:55:32.017" UserId="5852" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10827" PostHistoryTypeId="2" PostId="4638" RevisionGUID="d720f498-903e-49f5-8657-7eca33fd1c3b" CreationDate="2017-01-31T01:48:48.497" UserId="2654" Text="Yes, VAO state includes vertex attribute specification for multiple attributes. Each attribute has its own format information and can come from a distinct buffer object. That's part of why you can only bind one VAO at a time." ContentLicense="CC BY-SA 3.0" />
  <row Id="10828" PostHistoryTypeId="2" PostId="4639" RevisionGUID="4cfa3ecd-55f8-4745-af01-bfae0fe53a7b" CreationDate="2017-01-31T05:00:08.793" UserId="3003" Text="You can take the normal of the line segment you're testing and find the dot product of that normal and the normal of each segment of the polygon you're testing against. If it is positive, then they are facing the same way. If the dot product is negative, then the line segments are facing in opposite directions. &#xD;&#xA;&#xD;&#xA;If they are facing in opposite directions, then they're either pointing at each other, or away from each other. You can figure out which by calculating a vector from a point on the first segment to a point on the other segment and seeing if it's facing the same direction as its normal (by again using the dot product). If so, they are facing each other, otherwise they're facing away.&#xD;&#xA;&#xD;&#xA;You can skip all the tests above by first testing if the polygons are the same color and only doing the tests if they're not." ContentLicense="CC BY-SA 3.0" />
  <row Id="10829" PostHistoryTypeId="2" PostId="4640" RevisionGUID="c751e402-18ac-43bf-ad25-57b3c1c8e047" CreationDate="2017-01-31T05:43:42.517" UserId="5943" Text="How do I classify a point with respect to a plane, returning whether the point is inside, outside, or coplanar?&#xD;&#xA;&#xD;&#xA;I know that if a point is on the plane the Dot product + the plane distance would equal to 0, but what does inside, outside, and coplanar mean. Also how it is computed." ContentLicense="CC BY-SA 3.0" />
  <row Id="10830" PostHistoryTypeId="1" PostId="4640" RevisionGUID="c751e402-18ac-43bf-ad25-57b3c1c8e047" CreationDate="2017-01-31T05:43:42.517" UserId="5943" Text="Point respect to plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="10831" PostHistoryTypeId="3" PostId="4640" RevisionGUID="c751e402-18ac-43bf-ad25-57b3c1c8e047" CreationDate="2017-01-31T05:43:42.517" UserId="5943" Text="|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10832" PostHistoryTypeId="34" PostId="4554" RevisionGUID="f0a59ad3-4bb4-4cd5-8e02-d35ade3ad480" CreationDate="2017-01-31T07:54:15.823" UserId="-1" Comment="24" />
  <row Id="10833" PostHistoryTypeId="2" PostId="4641" RevisionGUID="24fe2d02-b66f-47c4-8836-b461c72b2990" CreationDate="2017-01-31T09:46:08.293" UserId="137" Text="In version 4.3+ the vao layout can be set independently from the VBO buffer which allows you to rebind the vbo without having to call vertexAttribPointer every time:&#xD;&#xA;&#xD;&#xA;    //in init&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));&#xD;&#xA;    // set the details of a single attribute&#xD;&#xA;    glVertexAttribBinding(posAttrLoc, 0);&#xD;&#xA;    // which buffer binding point it is attached to&#xD;&#xA;    glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;&#xD;&#xA;    glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));&#xD;&#xA;    glVertexAttribBinding(normalAttrLoc, 0);&#xD;&#xA;    glEnableVertexAttribArray(normalAttrLoc);&#xD;&#xA;&#xD;&#xA;    glVertexAttribFormat(texAttrLoc, 2, GL_FLOAT, false, offsetof(Vertex, tex));&#xD;&#xA;    glVertexAttribBinding(texAttrLoc, 0);&#xD;&#xA;    glEnableVertexAttribArray(texAttrLoc);&#xD;&#xA;&#xD;&#xA;Note that there is no mention of any VBO during init, just the binding points. That binding point is then used during draw to specify which vbo to pull the vertex data from:&#xD;&#xA;&#xD;&#xA;    //draw&#xD;&#xA;    &#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    foreach(mesh in meshes){&#xD;&#xA;        glBindVertexBuffer(0, mesh.vbo, mesh.vboOffset, sizeof(Vertex));&#xD;&#xA;        // bind the buffer to the binding point&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);&#xD;&#xA;        //draw&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In pre 4.3 you would create a VAO per mesh and per mesh call glVertexAttribPointer for each attribute:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(mesh.vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribPointer (posAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, pos));&#xD;&#xA;    glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;    //...&#xD;&#xA;&#xD;&#xA;Then during draw bind the per mesh vao before drawing it:&#xD;&#xA;&#xD;&#xA;    foreach(mesh in meshes){        &#xD;&#xA;        glBindVertexArray(mesh.vao);&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10834" PostHistoryTypeId="2" PostId="4642" RevisionGUID="e6b3cc74-1ef1-47eb-9bab-609cee390732" CreationDate="2017-01-31T10:34:49.637" UserId="1608" Text="&#xD;&#xA;    Vec3 v = myPoint - pointOnPlane;&#xD;&#xA;    float vDotPlaneNormal = dot(v, planeNormal)&#xD;&#xA;    if (vDotPlaneNormal == 0) &#xD;&#xA;        printf(&quot;point on plane&quot;);&#xD;&#xA;    else if (vDotPlaneNormal &gt; 0)&#xD;&#xA;        printf(&quot;point above somehow...&quot;);&#xD;&#xA;    else&#xD;&#xA;        printf(&quot;point under sadly...&quot;);&#xD;&#xA;&#xD;&#xA;If you wonder what is `pointOnPlane`. In fact it can be any point that lies on the plane. Imagine this as a sheet of paper; draw two lines on this sheet to define the center of the piece of paper, imagine that this point is aligned with the world coordinate system origin and that sheet is in xz plane of that coordinate system (in which y defines the up vector). So the paper is horizontal in a way. Now move the sheet around. The `pointOnPlane` can be the coordinates of the point you drew in the center of the sheet of paper with respect to the world origin.&#xD;&#xA;&#xD;&#xA;All you have to do is rotate that sheet of paper. That rotation is given to you by the plane's normal.&#xD;&#xA;&#xD;&#xA;The rest is basic trig. If the point P is one the plane, the dot product between the vector defined by (P - PointOnPlane) and the plane's normal will be equal to 0. The dot product tells you whether two vectors are orthogonal, on the same side of the plane or point in opposite directions." ContentLicense="CC BY-SA 3.0" />
  <row Id="10835" PostHistoryTypeId="5" PostId="4637" RevisionGUID="6981adef-8962-41ce-957f-fa8f69996ebc" CreationDate="2017-01-31T12:13:42.127" UserId="5852" Comment="added 294 characters in body" Text="If no, Should I create a new VAO for every VBO that has its own vertex attribute configurations?&#xD;&#xA;&#xD;&#xA;Could you please give me a snippet code example that shows how to use one VAO for multiple VBOs? All examples I find on the internet call to glVertexAttribPointer before drawing a buffer, but if you have to call that method everytime you want to draw a buffer, then VAOs doesn't make sense." ContentLicense="CC BY-SA 3.0" />
  <row Id="10836" PostHistoryTypeId="6" PostId="4637" RevisionGUID="6981adef-8962-41ce-957f-fa8f69996ebc" CreationDate="2017-01-31T12:13:42.127" UserId="5852" Comment="added 294 characters in body" Text="|opengl|c++|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10840" PostHistoryTypeId="5" PostId="4638" RevisionGUID="dde15100-53ba-48c3-a541-4f396718213a" CreationDate="2017-01-31T16:56:54.283" UserId="1608" Comment="Added some code per OP request" Text="Yes, VAO state includes vertex attribute specification for multiple attributes. Each attribute has its own format information and can come from a distinct buffer object. That's part of why you can only bind one VAO at a time.&#xD;&#xA;&#xD;&#xA;    // two VBOs but one VAO&#xD;&#xA;    GLuint points_vbo = 0;&#xD;&#xA;    glGenBuffers(1, &amp;points_vbo);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    GLuint colours_vbo = 0;&#xD;&#xA;    glGenBuffers(1, &amp;colours_vbo);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colours, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    GLuint vao = 0;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;&#xD;&#xA;    rendering-loop {&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, points_vbo);&#xD;&#xA;        glBindVertexArray(vao);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;        &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;        ...&#xD;&#xA;        // then disable vertex attribute&#xD;&#xA;        ... &#xD;&#xA;        // render next object&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;PS: you will need to be careful about the location of the vertex attribute. Those used in the rendering loop need to match those in the vertex shader." ContentLicense="CC BY-SA 3.0" />
  <row Id="10841" PostHistoryTypeId="24" PostId="4638" RevisionGUID="dde15100-53ba-48c3-a541-4f396718213a" CreationDate="2017-01-31T16:56:54.283" Comment="Proposed by 1608 approved by -1 edit id of 196" ContentLicense="CC BY-SA 3.0" />
  <row Id="10842" PostHistoryTypeId="5" PostId="4638" RevisionGUID="fde9001d-2763-4c1d-8bba-f24f3b578178" CreationDate="2017-01-31T16:56:54.283" UserId="2654" Comment="Added some code per OP request" Text="Yes, VAO state includes vertex attribute specification for multiple attributes. Each attribute has its own format information and can come from a distinct buffer object. That's part of why you can only bind one VAO at a time.&#xD;&#xA;&#xD;&#xA;    // two VBOs but one VAO&#xD;&#xA;    GLuint points_vbo = 0;&#xD;&#xA;    glGenBuffers(1, &amp;points_vbo);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    GLuint colours_vbo = 0;&#xD;&#xA;    glGenBuffers(1, &amp;colours_vbo);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colours, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    GLuint vao = 0;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    rendering-loop&#xD;&#xA;    {&#xD;&#xA;        glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, points_vbo);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;        &#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;PS: you will need to be careful about the location of the vertex attribute. Those used in the rendering loop need to match those in the vertex shader." ContentLicense="CC BY-SA 3.0" />
  <row Id="10844" PostHistoryTypeId="5" PostId="4637" RevisionGUID="607c6823-edf8-45d9-b362-fa48f7b4ee33" CreationDate="2017-01-31T19:36:51.077" UserId="5852" Comment="added 50 characters in body" Text="If no, Should I create a new VAO for every VBO that has its own vertex attribute configurations?&#xD;&#xA;&#xD;&#xA;Could you please give me a snippet code example that shows how to use one VAO for multiple VBOs? All examples I find on the internet call to glVertexAttribPointer before drawing a buffer, but if you have to call that method everytime you want to draw a buffer, then VAOs doesn't make sense.&#xD;&#xA;&#xD;&#xA;PS: The tutorial I'm following uses Opengl 3.3" ContentLicense="CC BY-SA 3.0" />
  <row Id="10845" PostHistoryTypeId="5" PostId="4642" RevisionGUID="9c6d8f5d-4a3b-4745-bc61-c8d866bc91ca" CreationDate="2017-01-31T20:00:41.833" UserId="1608" Comment="added 577 characters in body" Text="    Vec3 v = myPoint - pointOnPlane;&#xD;&#xA;    float vDotPlaneNormal = dot(v, planeNormal)&#xD;&#xA;    if (vDotPlaneNormal == 0) &#xD;&#xA;        printf(&quot;point on plane&quot;);&#xD;&#xA;    else if (vDotPlaneNormal &gt; 0)&#xD;&#xA;        printf(&quot;point above somehow...&quot;);&#xD;&#xA;    else&#xD;&#xA;        printf(&quot;point under sadly...&quot;);&#xD;&#xA;&#xD;&#xA;If you wonder what is `pointOnPlane`. In fact it can be any point that lies on the plane. Imagine this as a sheet of paper; draw two lines on this sheet to define the center of the piece of paper, imagine that this point is aligned with the world coordinate system origin and that sheet is in xz plane of that coordinate system (in which y defines the up vector). So the paper is horizontal in a way. Now move the sheet around. The `pointOnPlane` can be the coordinates of the point you drew in the center of the sheet of paper with respect to the world origin.&#xD;&#xA;&#xD;&#xA;All you have to do is rotate that sheet of paper. That rotation is given to you by the plane's normal.&#xD;&#xA;&#xD;&#xA;The rest is basic trig. If the point P is one the plane, the dot product between the vector defined by (P - PointOnPlane) and the plane's normal will be equal to 0. The dot product tells you whether two vectors are orthogonal, on the same side of the plane or point in opposite directions.&#xD;&#xA;&#xD;&#xA;FASTER SOLUTION - EDIT&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;As mentioned by SimonF in a comment, you don't really need the `pointOnPlane` parameter and save the subtraction between this point and the tested point:&#xD;&#xA;&#xD;&#xA;&gt; As you imply, a plane can be represented by its normal, N, and a scalar, d. A point X is on the plane if N.X+d = 0. As for inside and outside typically you define a rule, e.g., that the normal points &quot;out&quot; from the plane which just means that if N.X+d &gt; 0, then X is outside the plane, while N.X+d&lt;0, implies it's inside&#xD;&#xA;&#xD;&#xA;You can test/use both techniques." ContentLicense="CC BY-SA 3.0" />
  <row Id="10851" PostHistoryTypeId="2" PostId="4645" RevisionGUID="2ab0ab6c-2d04-4aac-8c9c-d6401e0b110d" CreationDate="2017-01-31T21:11:24.653" UserId="5972" Text="I have an obj file together with an associated mtl file and texture jpg file. I have managed to find some code that sets a specific camera view and raytraces the image to output a depth map plus a point cloud. The code is using assimp and CGAL to do this. I have access to the specific face the ray intersects but I don't know how to find the pixel color value at the intersection point. Can this be done? Or is there are better way to do this using some software or library? &#xD;&#xA;&#xD;&#xA;My final goal is to create depth and color images of different viewpoints from a set of viewpoints for given camera parameters." ContentLicense="CC BY-SA 3.0" />
  <row Id="10852" PostHistoryTypeId="1" PostId="4645" RevisionGUID="2ab0ab6c-2d04-4aac-8c9c-d6401e0b110d" CreationDate="2017-01-31T21:11:24.653" UserId="5972" Text="Getting texture value of cartesian coordinate from a Obj file" ContentLicense="CC BY-SA 3.0" />
  <row Id="10853" PostHistoryTypeId="3" PostId="4645" RevisionGUID="2ab0ab6c-2d04-4aac-8c9c-d6401e0b110d" CreationDate="2017-01-31T21:11:24.653" UserId="5972" Text="|opengl|texture|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10855" PostHistoryTypeId="2" PostId="4646" RevisionGUID="ce3e4601-c1e2-4d1e-b7ac-28d59aaeb17d" CreationDate="2017-02-01T07:10:39.080" UserId="1608" Text="Your question is very broad because it is close again to &quot;how to I render 3D objects&quot;. So some people might give you a more precise answer than mine but at least I will try to give you some pointers.&#xD;&#xA;&#xD;&#xA;1. First look on the web. There are plenty of tutorials that explains to you exactly what you to do (which is to raytrace texture mapped objects). While it's great to ask questions, there is really no excuse for posting such a generic question here, considering the amount of information that is available on the topic on the Web.&#xD;&#xA;2. Though I will try to give you some pointers nonetheless&#xD;&#xA;&#xD;&#xA;What you want to do is called texture mapping. The way it's done is simple. Each triangle of your geometry holds what we call vertex coordinates, basically it explains how a triangle is actually mapped onto an image (or texture). Imagine your triangle laying flat on the image. The part that it lays on is that part of the texture that should appear on the triangle once rendered. Note that texture coordinates are 2D coordinates and that the shape of the triangle in the texture space (when it lays flat on the texture) doesn't have to match the shape of the triangle in 3D space (in which case the texture will be stretched).&#xD;&#xA;&#xD;&#xA;So your 3D object when you render it should have a set of 3D points (the vertex position) 3D normals (the normals of the object at the vertex position) and 2D coordinates (read from the OBJ file).&#xD;&#xA;&#xD;&#xA;When the ray hits a triangle your compute the texture coordinates at the intersection point using the [barycentric coordinates][1] of the intersection point and the texture coordinates set at the 3 vertices of the hit triangle. This is very common technique you will find many tutorials about that.&#xD;&#xA;&#xD;&#xA;Then once you have your interpolated texture coordinates you use it to do a lookup into the texture. The texture coordinates are in the range [0:1] (in general), where (0,0) might be the top-left corner if your texture and (1,1) the bottom right. You need to remap that texture coordinate to pixel space (multiply it by image width and height and cast to integers eventually).&#xD;&#xA;&#xD;&#xA;Now just read the pixel value at that position (remapped to pixel coordinates), and that's the color of the mapped intersection point.&#xD;&#xA;&#xD;&#xA;Easy, breezy!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage" ContentLicense="CC BY-SA 3.0" />
  <row Id="10857" PostHistoryTypeId="5" PostId="4646" RevisionGUID="20e759ef-f708-4974-a64b-df5e5dbe913a" CreationDate="2017-02-01T09:54:22.953" UserId="1608" Comment="deleted 1 character in body" Text="Your question is very broad because it is close again to &quot;how to I render 3D objects&quot;. So some people might give you a more precise answer than mine but at least I will try to give you some pointers.&#xD;&#xA;&#xD;&#xA;1. First look on the web. There are plenty of tutorials that explain to you exactly what you to do (which is to raytrace texture mapped objects). While it's great to ask questions, there is really no excuse for posting such a generic question here, considering the amount of information that is available on the topic on the Web.&#xD;&#xA;2. Though I will try to give you some pointers nonetheless (because we are kind and not here to judge each other;0)&#xD;&#xA;&#xD;&#xA;What you want to do is called texture mapping. The way it's done is simple. Each triangle of your geometry holds what we call vertex coordinates, basically it explains how a triangle is actually mapped onto an image (or texture). Imagine your triangle laying flat on the image. The part that it lays on is that part of the texture that should appear on the triangle once rendered. Note that texture coordinates are 2D coordinates and that the shape of the triangle in the texture space (when it lays flat on the texture) doesn't have to match the shape of the triangle in 3D space (in which case the texture will be stretched).&#xD;&#xA;&#xD;&#xA;So your 3D object when you render it should have a set of 3D points (the vertex position) 3D normals (the normals of the object at the vertex position) and 2D coordinates (read from the OBJ file).&#xD;&#xA;&#xD;&#xA;When the ray hits a triangle your compute the texture coordinates at the intersection point using the [barycentric coordinates][1] of the intersection point and the texture coordinates set at the 3 vertices of the hit triangle. This is very common technique you will find many tutorials about that.&#xD;&#xA;&#xD;&#xA;Then once you have your interpolated texture coordinates you use it to do a lookup into the texture. The texture coordinates are in the range [0:1] (in general), where (0,0) might be the top-left corner if your texture and (1,1) the bottom right. You need to remap that texture coordinate to pixel space (multiply it by image width and height and cast to integers eventually).&#xD;&#xA;&#xD;&#xA;Now just read the pixel value at that position (remapped to pixel coordinates), and that's the color of the mapped intersection point.&#xD;&#xA;&#xD;&#xA;Easy, breezy!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage" ContentLicense="CC BY-SA 3.0" />
  <row Id="10863" PostHistoryTypeId="5" PostId="4641" RevisionGUID="5096a9bf-9c95-4e6c-957f-109acad58edc" CreationDate="2017-02-01T16:50:10.010" UserId="137" Comment="added 82 characters in body" Text="In version 4.3+ the vao layout can be set independently from the VBO buffer which allows you to rebind the vbo without having to call vertexAttribPointer every time:&#xD;&#xA;&#xD;&#xA;    //in init&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));&#xD;&#xA;    // set the details of a single attribute&#xD;&#xA;    glVertexAttribBinding(posAttrLoc, 0);&#xD;&#xA;    // which buffer binding point it is attached to&#xD;&#xA;    glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;&#xD;&#xA;    glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));&#xD;&#xA;    glVertexAttribBinding(normalAttrLoc, 0);&#xD;&#xA;    glEnableVertexAttribArray(normalAttrLoc);&#xD;&#xA;&#xD;&#xA;    glVertexAttribFormat(texAttrLoc, 2, GL_FLOAT, false, offsetof(Texture, tex));&#xD;&#xA;    glVertexAttribBinding(texAttrLoc, 1);&#xD;&#xA;    glEnableVertexAttribArray(texAttrLoc);&#xD;&#xA;&#xD;&#xA;Note that there is no mention of any VBO during init, just the binding points. That binding point is then used during draw to specify which vbo to pull the vertex data from:&#xD;&#xA;&#xD;&#xA;    //draw&#xD;&#xA;    &#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    foreach(mesh in meshes){&#xD;&#xA;        glBindVertexBuffer(0, mesh.vbo, mesh.vboOffset, sizeof(Vertex));&#xD;&#xA;        glBindVertexBuffer(1, mesh.texVbo, mesh.texVboOffset, sizeof(Texture));&#xD;&#xA;        // bind the buffer to the binding point&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);&#xD;&#xA;        //draw&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In pre 4.3 you would create a VAO per mesh and per mesh call glVertexAttribPointer for each attribute:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(mesh.vao);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribPointer (posAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, pos));&#xD;&#xA;    glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;    //...&#xD;&#xA;&#xD;&#xA;Then during draw bind the per mesh vao before drawing it:&#xD;&#xA;&#xD;&#xA;    foreach(mesh in meshes){        &#xD;&#xA;        glBindVertexArray(mesh.vao);&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="10864" PostHistoryTypeId="2" PostId="4648" RevisionGUID="31b0278f-b29d-4ef8-b1c5-f5ebf7fd1835" CreationDate="2017-02-02T05:56:18.780" UserId="2096" Text="I was trying to make a CPU-based ray tracer but i know after all the calculation i will end up with an array of pixels. I don't know how to paint it on the screen. What are the various ways to do that? I am using C++." ContentLicense="CC BY-SA 3.0" />
  <row Id="10865" PostHistoryTypeId="1" PostId="4648" RevisionGUID="31b0278f-b29d-4ef8-b1c5-f5ebf7fd1835" CreationDate="2017-02-02T05:56:18.780" UserId="2096" Text="How can i send custom bitmap to frame buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10866" PostHistoryTypeId="3" PostId="4648" RevisionGUID="31b0278f-b29d-4ef8-b1c5-f5ebf7fd1835" CreationDate="2017-02-02T05:56:18.780" UserId="2096" Text="|rendering|raytracing|c++|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10867" PostHistoryTypeId="5" PostId="4648" RevisionGUID="526fab13-59af-4efc-b95d-1a0c360d58ad" CreationDate="2017-02-02T06:24:11.887" UserId="2096" Comment="added 89 characters in body" Text="I was trying to make a CPU-based ray tracer but i know after all the calculation i will end up with an array of pixels. I don't know how to paint it on the screen. What are the various ways to do that? I am using C++ and i am working on windows 10. I know OpenGL(useless since i am not gonna use my gpu),Allegro 5 game library and I am also familiar with win32 C++ API. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10868" PostHistoryTypeId="2" PostId="4649" RevisionGUID="4b8266dd-a142-4c10-85e6-e01f95173c68" CreationDate="2017-02-02T13:52:12.987" UserId="5985" Text="I was always interested how programs like: Unity, AE, godot engine and other render their custom guis. So my question is, do they use graphics library to render custom guis or something else. If they don't use graphics library, should I use it? Thanks :)." ContentLicense="CC BY-SA 3.0" />
  <row Id="10869" PostHistoryTypeId="1" PostId="4649" RevisionGUID="4b8266dd-a142-4c10-85e6-e01f95173c68" CreationDate="2017-02-02T13:52:12.987" UserId="5985" Text="Does programs like After effects and Unity engine use graphics library to render custom guis?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10870" PostHistoryTypeId="3" PostId="4649" RevisionGUID="4b8266dd-a142-4c10-85e6-e01f95173c68" CreationDate="2017-02-02T13:52:12.987" UserId="5985" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10872" PostHistoryTypeId="2" PostId="4650" RevisionGUID="5f9b090e-eff5-4f99-b77d-f2c2c6c82ded" CreationDate="2017-02-02T15:11:42.530" UserId="5986" Text="I can't find any paper about a bevel/chamfer algorithm for 3D mesh. Bevel has a lot of special cases (corners, different bevel profile, bevel larger than a face). I am looking for robustness.&#xD;&#xA;Do you know any algorithm for this ?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="10873" PostHistoryTypeId="1" PostId="4650" RevisionGUID="5f9b090e-eff5-4f99-b77d-f2c2c6c82ded" CreationDate="2017-02-02T15:11:42.530" UserId="5986" Text="Bevel/Chamfer algorithm for arbitrary 3D mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="10874" PostHistoryTypeId="3" PostId="4650" RevisionGUID="5f9b090e-eff5-4f99-b77d-f2c2c6c82ded" CreationDate="2017-02-02T15:11:42.530" UserId="5986" Text="|3d|computational-geometry|geometry|mesh|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10875" PostHistoryTypeId="2" PostId="4651" RevisionGUID="fddb1aec-d22a-4475-8643-b56c3f5c746e" CreationDate="2017-02-02T16:03:42.733" UserId="270" Text="I am trying to retrofit weighted blended OIT (http://jcgt.org/published/0002/02/09/) to my pipeline and while it works well, producing convincing results for normal alpha blending (based on the OVER) operator, I am struggling to make it support additive blending (for example Colour1 + Colour2 + Background Colour) correctly using the blending formula:&#xD;&#xA;&#xD;&#xA; C1*w1 + C2*w2  &#xD;&#xA;----------------------- * (1-(1-a1)*(1-a2)) + Bg * (1-a1)(1-a2)  &#xD;&#xA; a1*w1 + a2*w2  &#xD;&#xA;&#xD;&#xA;I could hack it outputting weight values of 1 and very low alphas (eg 0.01), which would make it to sort of converge to additive blending, trouble is, this does not weight the colours at all and does not blend nicely with normal alpha blending.&#xD;&#xA;&#xD;&#xA;I was wondering how people have tackled this problem.&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;Kostas&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10876" PostHistoryTypeId="1" PostId="4651" RevisionGUID="fddb1aec-d22a-4475-8643-b56c3f5c746e" CreationDate="2017-02-02T16:03:42.733" UserId="270" Text="Additive blending with weighted-blended order independent transparency" ContentLicense="CC BY-SA 3.0" />
  <row Id="10877" PostHistoryTypeId="3" PostId="4651" RevisionGUID="fddb1aec-d22a-4475-8643-b56c3f5c746e" CreationDate="2017-02-02T16:03:42.733" UserId="270" Text="|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10878" PostHistoryTypeId="5" PostId="4651" RevisionGUID="5f18cbc8-d6eb-4d8e-97c9-fa7f8037182e" CreationDate="2017-02-02T16:08:55.757" UserId="270" Comment="added 11 characters in body" Text="I am trying to retrofit weighted blended OIT (http://jcgt.org/published/0002/02/09/) to my rendering pipeline and while it works well, producing convincing results, for normal alpha blending (based on the OVER) operator, I am struggling to make it support additive blending (for example Colour1 + Colour2 + Background Colour) correctly using the blending formula:&#xD;&#xA;&#xD;&#xA; C1*w1 + C2*w2  &#xD;&#xA;----------------------- * (1-(1-a1)*(1-a2)) + Bg * (1-a1)(1-a2)  &#xD;&#xA; a1*w1 + a2*w2  &#xD;&#xA;&#xD;&#xA;I could hack it outputting weight values of 1 and very low alphas (eg 0.01), which would make it to sort of converge to additive blending, trouble is, this does not weight the colours at all and does not blend nicely with normal alpha blending.&#xD;&#xA;&#xD;&#xA;I was wondering how people have tackled this problem.&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;Kostas&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10879" PostHistoryTypeId="50" PostId="4008" RevisionGUID="9fe25b47-b825-446b-867b-995daaa2d66d" CreationDate="2017-02-02T17:07:31.097" UserId="-1" />
  <row Id="10880" PostHistoryTypeId="2" PostId="4652" RevisionGUID="298fd9b4-1631-4ef9-8924-dac2d7dbaa6c" CreationDate="2017-02-02T17:40:41.843" UserId="1608" Text="So:&#xD;&#xA;&#xD;&#xA; 1. All GUI are somehow graphics. They don't have to be accelerated by the GPU but these days most are. In the old times, they could be rendered on the CPU (X11 times).&#xD;&#xA; 2. You need to be careful between making a distinction between the frameworks/libraries that are potentially being used for building up UIs and what these libraries use to render the graphics making up these UIs.&#xD;&#xA;&#xD;&#xA;A lot of applications like Maya for instance use libraries for creating their UIs (Maya uses Qt so as most products developed by the Foundry: Nuke, Marri, etc.) which is why a lot of these applications look the same ... (sadly).&#xD;&#xA;&#xD;&#xA;Qt and most UI library/framework use a graphics API to accelerate the rendering of widgets. &#xD;&#xA;&#xD;&#xA;Some applications like Unity do not use &quot;commercial&quot; libraries like Qt. They develop their own, but in the end they also use the GPU to render their GUIs." ContentLicense="CC BY-SA 3.0" />
  <row Id="10881" PostHistoryTypeId="5" PostId="4651" RevisionGUID="0a871482-89ae-450e-b372-20be0dfacd11" CreationDate="2017-02-02T18:20:26.063" UserId="48" Comment="math formatting" Text="I am trying to retrofit [weighted blended OIT](http://jcgt.org/published/0002/02/09/) to my rendering pipeline and while it works well, producing convincing results, for normal alpha blending (based on the OVER) operator, I am struggling to make it support additive blending (for example Colour1 + Colour2 + Background Colour) correctly using the blending formula:&#xD;&#xA;&#xD;&#xA;$$ \frac{C_1 w_1 + C_2 w_2}{\alpha_1 w_1 + \alpha_2 w_2} \cdot \bigl(1 - (1 - \alpha_1)(1 - \alpha_2)\bigr) + \text{Bg} \cdot (1 - \alpha_1)(1 - \alpha_2) $$&#xD;&#xA;&#xD;&#xA;I could hack it outputting weight values of 1 and very low alphas (eg 0.01), which would make it to sort of converge to additive blending, trouble is, this does not weight the colours at all and does not blend nicely with normal alpha blending.&#xD;&#xA;&#xD;&#xA;I was wondering how people have tackled this problem.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10882" PostHistoryTypeId="2" PostId="4653" RevisionGUID="cbbb8eb7-94d6-4b67-828b-079afac512b4" CreationDate="2017-02-02T21:26:21.273" UserId="2941" Text="This answer uses GDI and a little bit of MFC. The MFC bits aren't necessary and just there for my convenience. You can hit the Windows API directly if you need to.&#xD;&#xA;&#xD;&#xA;In your window class have some data members for the bitmap. I currently use MFC's CBitmap for convenience:&#xD;&#xA;&#xD;&#xA;	CBitmap				bitmap_;&#xD;&#xA;	unsigned char*		bitmapBits_;&#xD;&#xA;&#xD;&#xA;`bitmapBits_` is a pointer to the bitmap data that you can write directly into.&#xD;&#xA;&#xD;&#xA;Before rendering, you'll need to create the bitmap using `CreateDIBSection()` and get the pointer to the bits of the bitmap:&#xD;&#xA;&#xD;&#xA;	BITMAPINFO bmi;&#xD;&#xA;	memset(&amp;bmi.bmiHeader,0,sizeof(bmi.bmiHeader));&#xD;&#xA;	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);&#xD;&#xA;	bmi.bmiHeader.biWidth = widthOfTheImage;&#xD;&#xA;	bmi.bmiHeader.biHeight = heightOfTheImage;&#xD;&#xA;	bmi.bmiHeader.biPlanes = 1;&#xD;&#xA;	bmi.bmiHeader.biBitCount = 24;&#xD;&#xA;	bmi.bmiHeader.biCompression = BI_RGB;&#xD;&#xA;&#xD;&#xA;	void* bitmapBits;&#xD;&#xA;	bitmap_.Attach(CreateDIBSection(0,&amp;bmi,DIB_RGB_COLORS,&amp;bitmapBits,0,0));&#xD;&#xA;	if(bitmap_.m_hObject == NULL)&#xD;&#xA;		AfxMessageBox(&quot;CreateDIBSection() FAILED!\n&quot;);&#xD;&#xA;	bitmapBits_ = reinterpret_cast&lt;unsigned char*&gt;(bitmapBits);&#xD;&#xA;&#xD;&#xA;When writing to the bitmap bits, you first need to determine the row size (see [here][1]).&#xD;&#xA;&#xD;&#xA;	// Compute the row size of a DIB.&#xD;&#xA;	// (See https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage and ComputePitch() from atlimage.h)&#xD;&#xA;	const unsigned int rowSize = ((24 * imageWidth + 31) / 32) * 4;&#xD;&#xA;&#xD;&#xA;Then you can write the colour information into the bitmap's data. Note this is a bottom-up DIB; memory earlier in the buffer represents scanlines lower in the image. Another way of putting it is that the the first element of the bitdata relates to the bottom-left. Colour components are in BGR order. &#xD;&#xA;&#xD;&#xA;	unsigned char* dibPtr = &amp;bitmapBits_[pixelY * rowSize + pixelX * 3];&#xD;&#xA;	dibPtr[0] = ???; // blue between 0 and 255&#xD;&#xA;	dibPtr[1] = ???; // green between 0 and 255&#xD;&#xA;	dibPtr[2] = ???; // red between 0 and 255&#xD;&#xA;&#xD;&#xA;Sorry if the previous part is already known to you, as you asked simply how to get it painted to the screen. Here's my simplified paint routine from my MFC application:&#xD;&#xA;&#xD;&#xA;    void RendererWnd::OnPaint()&#xD;&#xA;    {&#xD;&#xA;    	CPaintDC dc(this);&#xD;&#xA;    &#xD;&#xA;   		CDC dcMemory;&#xD;&#xA;   		dcMemory.CreateCompatibleDC(&amp;dc);&#xD;&#xA;   		CBitmap* oldBmp = dcMemory.SelectObject(&amp;bitmap_);&#xD;&#xA;   		dc.BitBlt(0,0,imageWidth,imageHeight,&amp;dcMemory,0,0,SRCCOPY);&#xD;&#xA;   		dcMemory.SelectObject(oldBmp);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;There are going to be many other ways of doing this. If you're doing a long render and want to update the window periodically then you'll probably want to have a timer in your window. When this timer fires you want to request a repaint of your window using `InvalidateRect()`. You'll need to synchronise access to the bitmap data between your rendering thread(s) and the thread that's doing the painting. This will ensure the painter can access the bitmap when it's not being written to. I use a `CRITICAL_SECTION` for this.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/BMP_file_format#Pixel_storage&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10883" PostHistoryTypeId="2" PostId="4654" RevisionGUID="fbf79e8f-3a47-4a7f-b90d-c85106e970b4" CreationDate="2017-02-03T01:17:58.430" UserId="5989" Text="I recently ran across the paper [RAISR: Rapid and Accurate Image Super Resolution](https://arxiv.org/abs/1606.01299) and thought it seemed like an interesting technique for scaling up images. However, I haven't seen any implementation of it, and I would like to see what it would be like to use it for scaling up a video in realtime, if that is possible. So I'm thinking of implementing my own version of it, but I will need to use GPU acceleration in some way if I want to at least give it a chance to run in realtime. Ultimately, I would like to see if I could successfully implemented this in an open source media player.&#xD;&#xA;&#xD;&#xA;**So**, what library should I use to implement this algorithm? DirectX and CUDA are out of the question, since I want to make it run under any (major) OS and on any graphics card (well, on most of the popular ones, at least), so I'm thinking that my only options are&#xD;&#xA;&#xD;&#xA; 1. OpenGL (ES) + GLSL (ES), and&#xD;&#xA; &#xD;&#xA; 2. OpenCL.&#xD;&#xA;&#xD;&#xA;(Vulkan also exists but I don't know whether this API is mature enough yet.)&#xD;&#xA;&#xD;&#xA;If I choose OpenGL + GLSL, is this approach flexible enough to allow this algorithm to be implemented? Are there algorithms that cannot be implemented this way and have to be implemented in OpenCL, and if so, how do I know if my algorithm is one of them?&#xD;&#xA;&#xD;&#xA;If I on the other hand choose OpenCL, will it be possible for other people to use my implementation without installing OpenCL on their computer? " ContentLicense="CC BY-SA 3.0" />
  <row Id="10884" PostHistoryTypeId="1" PostId="4654" RevisionGUID="fbf79e8f-3a47-4a7f-b90d-c85106e970b4" CreationDate="2017-02-03T01:17:58.430" UserId="5989" Text="What framework shoud I use to implement the RAISR upscaling algorithm on the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10885" PostHistoryTypeId="3" PostId="4654" RevisionGUID="fbf79e8f-3a47-4a7f-b90d-c85106e970b4" CreationDate="2017-02-03T01:17:58.430" UserId="5989" Text="|opengl|glsl|real-time|gpgpu|opencl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10887" PostHistoryTypeId="2" PostId="4655" RevisionGUID="aa7c6e1c-df4b-47d2-8330-e78aa676bfc8" CreationDate="2017-02-03T03:29:57.760" UserId="3003" Text="&gt;  Are there algorithms that cannot be implemented this way and have to be implemented in OpenCL, and if so, how do I know if my algorithm is one of them?&#xD;&#xA;&#xD;&#xA;Yes. Generally [scatter-gather algorithms](https://en.wikipedia.org/wiki/Gather-scatter_(vector_addressing)) work poorly in OpenGL as the data locality is poor. When you have to grab bits from all over the input image for each output pixel, it's going to be slow or nearly impossible to implement in a typical GL shader. Likewise, when a calculation on an input pixel results in data that needs to be spread out to several output pixels, it's a poor fit.&#xD;&#xA;&#xD;&#xA;It's hard to tell just from the abstract, but it looks to me like this wouldn't be a great fit for a typical OpenGL shader. I think you'll end up needing to sample an area of the input, classify it, then sample from one or more of a large set of small exemplars.&#xD;&#xA;&#xD;&#xA;I mainly work on iOS and macOS which both come with OpenGL and OpenCL. Not sure how Windows and Linux handle that." ContentLicense="CC BY-SA 3.0" />
  <row Id="10888" PostHistoryTypeId="2" PostId="4656" RevisionGUID="a62c114a-e5b4-4453-805d-87ccfa299401" CreationDate="2017-02-03T04:00:09.103" UserId="5991" Text="I'm implementing mesh skinning in a project of mine. I can calculate vertex positions based on bone transformations, but I've run into a problem with calculating their normals.&#xD;&#xA;&#xD;&#xA;From the resources I've read, it appears that a given vertex's skinned normal is the weighted sum of each influencing bone's transform applied to the vertex's normal.&#xD;&#xA;&#xD;&#xA;What I don't understand, is how this would produce equivalent normals to what you *would* get if you calculated each vertex's normal directly. (I.E. from the sum of the normals of its adjacent faces)&#xD;&#xA;&#xD;&#xA;For example, consider the case of three connected vertices with the normals shown below. Note the bone in the center, which has the same position as the center vertex.&#xD;&#xA;&#xD;&#xA;[![A simple rigged mesh][1]][1]&#xD;&#xA;&#xD;&#xA;Next, suppose this bone is turned 45 degrees CCW. If this bone only influenced the vertex to its right, my understanding is that it would produce the following result:&#xD;&#xA;&#xD;&#xA;[![Single influenced vertex][2]][2]&#xD;&#xA;&#xD;&#xA;This is because there is only one influencing bone, and the normal is rotated by the same rotation as the bone, 45 degrees CCW.&#xD;&#xA;&#xD;&#xA;Next, consider that the bone influenced the middle *and* right vertices. Each vertex's normal would be rotated exactly as in the previous image.&#xD;&#xA;&#xD;&#xA;[![Two influenced vertices][3]][3]&#xD;&#xA;&#xD;&#xA;But, neither of these would produce the &quot;correct&quot; normal for the middle vertex, shown here:&#xD;&#xA;&#xD;&#xA;[![Presumably the correct middle normal][4]][4]&#xD;&#xA;&#xD;&#xA;So, my question is, is this the intended behavior for this algorithm? Is it only meant to be an approximation, or have I missed something critical? How are these normals meant to be calculated?&#xD;&#xA;&#xD;&#xA;For what it's worth, the resources I've been following are presented [here][5] and [here][6].&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/stboN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mQfeC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/MG97U.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/dKPYh.png&#xD;&#xA;  [5]: http://ruh.li/AnimationVertexSkinning.html&#xD;&#xA;  [6]: http://www.3dgep.com/loading-and-animating-md5-models-with-opengl/#The_MD5Model::PrepareMesh_Method" ContentLicense="CC BY-SA 3.0" />
  <row Id="10889" PostHistoryTypeId="1" PostId="4656" RevisionGUID="a62c114a-e5b4-4453-805d-87ccfa299401" CreationDate="2017-02-03T04:00:09.103" UserId="5991" Text="Calculating Skeleton-Deformed Mesh Normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="10890" PostHistoryTypeId="3" PostId="4656" RevisionGUID="a62c114a-e5b4-4453-805d-87ccfa299401" CreationDate="2017-02-03T04:00:09.103" UserId="5991" Text="|algorithm|mesh|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10891" PostHistoryTypeId="5" PostId="4203" RevisionGUID="a3b09d02-4c22-4ab7-83f8-3b0a89792d9e" CreationDate="2017-02-03T04:49:49.170" UserId="2654" Comment="added 2 characters in body" Text="D3D12 has 4 separate kinds of command lists: direct, bundle, compute, and copy.&#xD;&#xA;&#xD;&#xA;Vulkan has similar concepts, but they happen in a different way. Command buffers are allocated from command pools. And command pools are directly associated with a queue family. And command buffers allocated from a pool can only be submitted to the queue family for which the pool was built.&#xD;&#xA;&#xD;&#xA;Queue families specify the kinds of operations that the queue can take: graphics, compute, or memory copying operations. D3D12's command queues have a similar concept, but D3D12's command list API has you to specify the list type. Vulkan's gets this information from the queue family the pool is meant for.&#xD;&#xA;&#xD;&#xA;The D3D12 &quot;bundle&quot; command list type seems similar on the surface to Vulkan secondary command buffers. However, they are quite different.&#xD;&#xA;&#xD;&#xA;The principle difference is this: bundles inherit *all state* from their executing direct command list, except for the bound PSO itself. This includes resource descriptor bindings.&#xD;&#xA;&#xD;&#xA;Vulkan secondary command buffers inherit *no state* from their primary command buffer execution environment, except for secondary CBs that execute in a subpass of a renderpass instance (and queries). And those *only* inherit the current subpass state (and queries).&#xD;&#xA;&#xD;&#xA;This means you do different things with them, compared to D3D bundles.&#xD;&#xA;&#xD;&#xA;Bundles are sometimes used to modify descriptor tables and render stuff, on the assumption that the direct command list they're executed within will have set those tables up. So bundles are kind of like light-weight OpenGL display lists, only without all of the bad things those do. So the intent with bundles is that you build them once and keep them around. They're supposed to be small things.&#xD;&#xA;&#xD;&#xA;Vulkan secondary CBs are essential for threaded building of commands intended for a single render pass instance. This is because a render pass instance can only be created within a primary CB, so for optimal use of threads, there needs to be a way to create commands meant to execute in the same subpass in different threads. That's one of the main use-cases of secondary CBs. So the intent is that you'll probably build secondary CBs each frame (though you can reuse them if you want).&#xD;&#xA;&#xD;&#xA;So in the end, bundles and secondary CBs are intended to solve separate problems. Bundles are generally dependent on the executing environment, while secondary CBs are more stand-alone.&#xD;&#xA;&#xD;&#xA;At the same time, Vulkan secondary CBs can do something bundles cannot: they can execute on compute/copy-only queues. Since Vulkan makes a distinction between the primary/secondary level of the command buffer and the queues where that CB can be sent, it is possible in Vulkan to have secondary command buffers that execute on compute or copy-only queues.&#xD;&#xA;&#xD;&#xA;Direct3D 12 can't do that with bundles. The [`ExecuteBundle` function][1] can only be called on a direct command list. So a copy-only command list cannot execute bundles.&#xD;&#xA;&#xD;&#xA;Granted, because Vulkan doesn't inherit anything between secondary CBs except for subpass state, and compute/copy operations don't use render passes, there isn't much to be gained from putting such commands in a secondary CB rather than a primary one.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;D3D12 has the same separation between [compute pipelines][2] and [graphics pipelines][3] that Vulkan does. However, when issuing commands, D3D12 has only one pipeline binding point, to which you can bind any kind of pipeline. By contrast, Vulkan has separate binding points for compute and graphics pipelines. Of course, Vulkan doesn't have different descriptor binding points for them, so the two pipelines can interfere with one another. But if you design their resource usage carefully, it is possible to invoke a dispatch operation without disturbing the needs of the graphics pipeline.&#xD;&#xA;&#xD;&#xA;So overall, there's no real difference in pipeline architecture here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn903882(v=vs.85).aspx&#xD;&#xA;  [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn788663(v=vs.85).aspx&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn770348(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="10892" PostHistoryTypeId="2" PostId="4657" RevisionGUID="db2482f7-b3c6-4788-be9b-0843918258fe" CreationDate="2017-02-03T07:07:19.220" UserId="5881" Text="Use the following equation for blending&#xD;&#xA;$$&#xD;&#xA;\frac{\alpha_1 w_1 C_1 + \alpha_2 w_2 C_2}{\alpha_1 w_1 + \alpha_2 w_2}.(1-(1-\alpha_1)(1-\alpha_2)) + Bg.(1-\alpha_1)(1-\alpha_2)&#xD;&#xA;$$&#xD;&#xA;Also note that $\alpha$ value must always be between $0$ and $1$" ContentLicense="CC BY-SA 3.0" />
  <row Id="10894" PostHistoryTypeId="2" PostId="4659" RevisionGUID="eb47fb8f-94e2-467e-894c-4992046e25b6" CreationDate="2017-02-03T18:22:16.563" UserId="4958" Text="Currently I got interested in implementation of Precomputed Radiance Transfer. &#xD;&#xA;&#xD;&#xA;I decided that occlusion representation (which is not trivial to compute) would be precomputed as CPU raytracing and stored as vertex buffer in addition to usual vertices. This representation would be stored as SH coefficients because I need to have information about occluded and unoccluded directions (probably 4 so additional `vec4` buffer). I don't know yet how that would behave but using this foreach vertex should make it quite accurate despite being low frequency.&#xD;&#xA;&#xD;&#xA;And as for color representation, computing it is quite trivial (transforming image representing skymap scattering and normals into SH set) and I want it to be dynamic so it would be done every frame. These would be 9 coefficients because why not.&#xD;&#xA;&#xD;&#xA;So in reconstruction step I would have two sets of coefficients: precomputed occlusion (4 coefficients) and real time color (9 coefficients for RGB so in sum 27 coefficients). Can I multiply them (as in the picture from [this][1]) so in the result I would get representation with occluded color filtered out?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.inf.ufrgs.br/~oliveira/pubs_files/Slomp_Oliveira_Patricio-Tutorial-PRT.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/oJomp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10895" PostHistoryTypeId="1" PostId="4659" RevisionGUID="eb47fb8f-94e2-467e-894c-4992046e25b6" CreationDate="2017-02-03T18:22:16.563" UserId="4958" Text="Multiplication of SH coefficient sets representing occlusion and color" ContentLicense="CC BY-SA 3.0" />
  <row Id="10896" PostHistoryTypeId="3" PostId="4659" RevisionGUID="eb47fb8f-94e2-467e-894c-4992046e25b6" CreationDate="2017-02-03T18:22:16.563" UserId="4958" Text="|lighting|global-illumination|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10897" PostHistoryTypeId="5" PostId="4659" RevisionGUID="af31c3f3-b1d8-441c-9c45-1686b3d187b3" CreationDate="2017-02-03T18:28:34.813" UserId="4958" Comment="added 10 characters in body" Text="Currently I got interested in implementation of Precomputed Radiance Transfer. &#xD;&#xA;&#xD;&#xA;I decided that occlusion representation (which is not trivial to compute) would be precomputed as CPU raytracing and stored as vertex buffer in addition to usual vertices. This representation would be stored as SH coefficients because I need to have information about occluded and unoccluded directions (probably 4 so additional `vec4` buffer). I don't know yet how that would behave but using this foreach vertex should make it quite accurate despite being low frequency.&#xD;&#xA;&#xD;&#xA;And as for color representation, computing it is quite trivial (transforming image representing skymap scattering and normals into SH set) and I want it to be dynamic so it would be done every frame. These would be 9 coefficients because why not.&#xD;&#xA;&#xD;&#xA;So in reconstruction step I would have two sets of coefficients: precomputed occlusion (4 coefficients) and real time color (9 coefficients for RGB so in sum 27 coefficients). Can I (and how) multiply them (as in the picture from [this][1]) so in the result I would get representation with occluded color filtered out?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.inf.ufrgs.br/~oliveira/pubs_files/Slomp_Oliveira_Patricio-Tutorial-PRT.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/oJomp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10898" PostHistoryTypeId="5" PostId="4659" RevisionGUID="87df4748-e72e-4616-8b3a-9435ccba8268" CreationDate="2017-02-03T18:43:47.820" UserId="4958" Comment="added 49 characters in body" Text="Currently I got interested in implementation of Precomputed Radiance Transfer. &#xD;&#xA;&#xD;&#xA;I decided that occlusion representation (which is not trivial to compute) would be precomputed as CPU raytracing and stored as vertex buffer in addition to usual vertices. This representation would be stored as SH coefficients because I need to have information about occluded and unoccluded directions (probably 4 so additional `vec4` buffer). So these would store only unoccluded directions. I don't know yet how that would behave but using this foreach vertex should make it quite accurate despite being low frequency.&#xD;&#xA;&#xD;&#xA;And as for color representation, computing it is quite trivial (transforming image representing skymap scattering and normals into SH set) and I want it to be dynamic so it would be done every frame. These would be 9 coefficients because why not.&#xD;&#xA;&#xD;&#xA;So in reconstruction step I would have two sets of coefficients: precomputed occlusion (4 coefficients) and real time color (9 coefficients for RGB so in sum 27 coefficients). Can I (and how) multiply them (as in the picture from [this][1]) so in the result I would get representation with occluded color filtered out?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.inf.ufrgs.br/~oliveira/pubs_files/Slomp_Oliveira_Patricio-Tutorial-PRT.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/oJomp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10900" PostHistoryTypeId="5" PostId="4659" RevisionGUID="bcd05ac1-a99c-4abf-ae04-f94a8eaef655" CreationDate="2017-02-03T22:21:25.040" UserId="4958" Comment="added 16 characters in body" Text="Currently I got interested in implementation of Precomputed Radiance Transfer. &#xD;&#xA;&#xD;&#xA;I decided that occlusion representation (which is not trivial to compute) would be precomputed as CPU raytracing and stored as vertex buffer in addition to usual vertices. This representation would be stored as SH coefficients because I need to have information about occluded and unoccluded directions (probably 4 so additional `vec4` buffer). So these would store only unoccluded directions. I don't know yet how that would behave but using this foreach vertex should make it quite accurate despite being low frequency.&#xD;&#xA;&#xD;&#xA;And as for color representation, computing it is quite trivial (transforming image representing skymap scattering and normals into SH set) and I want it to be dynamic so it would be done every frame. These would be 9 coefficients because why not.&#xD;&#xA;&#xD;&#xA;So in reconstruction step I would have two sets of coefficients: precomputed occlusion (4 coefficients) and real time color (9 coefficients for RGB so in sum 27 coefficients). &#xD;&#xA;&#xD;&#xA;Can I (and how) multiply them (as in the picture below from [this paper][1]) so in the result I would get representation with occluded color filtered out?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.inf.ufrgs.br/~oliveira/pubs_files/Slomp_Oliveira_Patricio-Tutorial-PRT.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/oJomp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10901" PostHistoryTypeId="10" PostId="4630" RevisionGUID="c7b63fac-2c18-405f-8c33-3bbe4da2a543" CreationDate="2017-02-04T02:02:40.960" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:3003,&quot;DisplayName&quot;:&quot;user1118321&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="10903" PostHistoryTypeId="2" PostId="4660" RevisionGUID="7181de37-239d-4d5c-a840-3e72fb3e38ec" CreationDate="2017-02-04T09:30:13.033" UserId="2096" Text="I am working on a ray tracer. But i want to put more than 10 objects in the scene. How can i make the intersection fast so that it can give me reasonable FPS.&#xD;&#xA;Its a cpu-based ray tracer." ContentLicense="CC BY-SA 3.0" />
  <row Id="10904" PostHistoryTypeId="1" PostId="4660" RevisionGUID="7181de37-239d-4d5c-a840-3e72fb3e38ec" CreationDate="2017-02-04T09:30:13.033" UserId="2096" Text="How can i make my ray tracing algorithm fast in terms of intersection testing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10905" PostHistoryTypeId="3" PostId="4660" RevisionGUID="7181de37-239d-4d5c-a840-3e72fb3e38ec" CreationDate="2017-02-04T09:30:13.033" UserId="2096" Text="|raytracing|shading|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10906" PostHistoryTypeId="2" PostId="4661" RevisionGUID="37496052-d6e6-4b77-a317-0dbd59e88ce8" CreationDate="2017-02-04T17:37:22.263" UserId="1608" Text="You have several techniques.&#xD;&#xA;&#xD;&#xA;1. Use acceleration structures. The idea is that you store your geometry (triangles) into generally some kind of volumes. The general idea behind acceleration structure is to discard quickly large parts of the scene, which we know (using these structure) don't have any object that your ray will intersect. An introduction to the topic can be found [here][1].&#xD;&#xA;2. You can also take advantage of multi-threading and parallelism (threads and SSE instructions or similar - this is harder than 1. and the benefits are not always as high but you optimise for your hardware).&#xD;&#xA;3. You can ray-trace in the GPU but ray-tracing is a memory-bound problem so you will have memory problems quicker with the GPU than with CPU.&#xD;&#xA;&#xD;&#xA;These are just some ideas. &#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/advanced-rendering/introduction-acceleration-structure" ContentLicense="CC BY-SA 3.0" />
  <row Id="10907" PostHistoryTypeId="2" PostId="4662" RevisionGUID="547580da-4fcc-43c0-a3aa-8040b0b501f7" CreationDate="2017-02-04T20:45:00.333" UserId="5998" Text="So I've been messing with perspective projection matrices recently. I used numpy and GTK/Cairo to make a very small Python renderer. I'm very confused with the results I'm getting though.&#xD;&#xA;&#xD;&#xA;I took this Homogeneous Coordinates technique from an online lecture. If I understood correctly, the objective is to transform every point inside a &quot;Viewing Pyramid&quot; that's frustum shaped so they fit in a cube. (Image from of songho.ca)&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![Image courtesy of songho.ca][1]][1]&#xD;&#xA;&#xD;&#xA;You need a Field of View angle ($\alpha$), the Near and Far plane distances ($n$ and $f$ respectively), and the aspect ratio ($r$). Firstly you turn every 3D Point into a Homogeneous Point by adding  a 1 like so:&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;  x &amp; y &amp; z&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\xrightarrow{\text{4D}}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;  x &amp; y &amp; z &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align*}&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;Then you multiply your point matrix by a perspective projection matrix:&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;\begin{bmatrix}x &amp; y &amp;z &amp; 1 \end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;  1\over\tan(\alpha/2) &amp; 0 &amp; 0 &amp; 0\\ &#xD;&#xA;  0 &amp; r\over\tan(\alpha/2) &amp; 0 &amp; 0\\&#xD;&#xA;  0 &amp; 0 &amp; (f+n)\over(f-n) &amp; -1 \\&#xD;&#xA;  0 &amp; 0 &amp; (2nf)\over(f-n) &amp; 0&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x' &amp; y' &amp; z' &amp; w&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align*}&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;And to go back to a 3D point in space you divide by the fourth dimension:&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;  x' &amp; y' &amp; z' &amp; w&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\xrightarrow{\text{3D}}&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;  x' \over w &amp; y' \over w &amp; z' \over w&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\end{align*}&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is exactly what I've done with numpy:&#xD;&#xA;&#xD;&#xA;    def projection_matrix(fov, aspect, near, far):&#xD;&#xA;        t = 1/math.tan(math.radians(fov)/2)&#xD;&#xA;        a = (far + near)/(far - near)&#xD;&#xA;        b = (2*near*far)/(far-near)&#xD;&#xA;        r = aspect&#xD;&#xA;        &#xD;&#xA;        return numpy.matrix([[t,   0,   0,   0],&#xD;&#xA;                             [0, r*t,   0,   0],&#xD;&#xA;                             [0,   0,   a,  -1],&#xD;&#xA;                             [0,   0,   b,   0]])&#xD;&#xA;&#xD;&#xA;But for some reason the renderer is totally messed up. This is supposed to be a spinning cube... What am I missing here?&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![Messed up cube][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AoWoV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YSERI.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="10908" PostHistoryTypeId="1" PostId="4662" RevisionGUID="547580da-4fcc-43c0-a3aa-8040b0b501f7" CreationDate="2017-02-04T20:45:00.333" UserId="5998" Text="My perspective projection is messed up?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10909" PostHistoryTypeId="3" PostId="4662" RevisionGUID="547580da-4fcc-43c0-a3aa-8040b0b501f7" CreationDate="2017-02-04T20:45:00.333" UserId="5998" Text="|rendering|projections|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10910" PostHistoryTypeId="2" PostId="4663" RevisionGUID="235911e4-e2fa-4047-8050-cc19d6723883" CreationDate="2017-02-04T21:59:09.617" UserId="5999" Text="I have an idea of how to render opaque rasterized geometry alongside raycast volumes:&#xD;&#xA;&#xD;&#xA; - Render rasterized geometry to a depth map and also a render target&#xD;&#xA; - When raycasting, check position against the depth map. When the ray penetrates the opaque geometry, alpha blend its color (from the render target) with the current color &quot;rolling sum&quot; of the ray, and stop raycasting&#xD;&#xA;&#xD;&#xA;This might even work for a single piece of transparent geometry (say a piece of glass in front of the raycast volume), but it will break down with multiple pieces of transparent geometry. &#xD;&#xA;&#xD;&#xA;For example, imagine a red transparent quad in front of a raycast volume, and a green transparent quad behind the same volume. On the rasterized geometry pass, the render target will receive a yellow color (blend of the red and green of the quads). This yellow color will be alpha blended with every sample of the raycast volume, making it look as if the green quad was also in front of it. Ideally we would want to see a reddish volume with effectively no green. &#xD;&#xA; &#xD;&#xA;How could I go about solving this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10911" PostHistoryTypeId="1" PostId="4663" RevisionGUID="235911e4-e2fa-4047-8050-cc19d6723883" CreationDate="2017-02-04T21:59:09.617" UserId="5999" Text="Volumetric raycasting with transparent rasterized geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="10912" PostHistoryTypeId="3" PostId="4663" RevisionGUID="235911e4-e2fa-4047-8050-cc19d6723883" CreationDate="2017-02-04T21:59:09.617" UserId="5999" Text="|raytracing|transparency|volumetric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10913" PostHistoryTypeId="2" PostId="4664" RevisionGUID="548eaec7-2703-4216-ac4e-5b34d3eb845e" CreationDate="2017-02-05T07:36:17.750" UserId="6001" Text="When converting from uniform hemisphere sampling to cosine weighted hemisphere sampling I am confused by a statement in an article.&#xD;&#xA;&#xD;&#xA;My current indirect contribution is calculated as:&#xD;&#xA;&#xD;&#xA;Vec3 rayDirectionUniform = UniformGenerator.Next()&#xD;&#xA;Color3 indirectDiffuse = N.dot(rayDirectionUniform) * castRay(P, rayDirectionUniform)&#xD;&#xA;&#xD;&#xA;Where the dot product is cos(θ)&#xD;&#xA;&#xD;&#xA;But in this article on better sampling (http://www.rorydriscoll.com/2009/01/07/better-sampling/) the author suggests the PDF is (cos(θ) / pi). &#xD;&#xA;&#xD;&#xA;My question is - does that mean that I no longer ned to perform the normal dot rayDirection because it is included in the PDF, or is it in addition to the pdf?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10914" PostHistoryTypeId="1" PostId="4664" RevisionGUID="548eaec7-2703-4216-ac4e-5b34d3eb845e" CreationDate="2017-02-05T07:36:17.750" UserId="6001" Text="Does cosine weighted hemisphere sampling still require NdotL when calculating contribution for indirect light?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10915" PostHistoryTypeId="3" PostId="4664" RevisionGUID="548eaec7-2703-4216-ac4e-5b34d3eb845e" CreationDate="2017-02-05T07:36:17.750" UserId="6001" Text="|raytracing|sampling|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10916" PostHistoryTypeId="2" PostId="4665" RevisionGUID="e771d581-6aba-49c7-a96e-4b5019cdc5e7" CreationDate="2017-02-05T10:24:41.067" UserId="1608" Text="You always need to multiply by the cosine term indeed (that's part of the rendering equation). Though when you do indirect diffuse using ray-tracing and thus monte-carlo integration (which is the most common technique in this case), you have to divide the contribution of each sample by your PDF. This is well exampled [here][1].&#xD;&#xA;&#xD;&#xA;Note also that in the mentioned reference, if the PDF has terms that you also find in the rendering equations then you can optimise the code if you wish by canceling out these terms.&#xD;&#xA;&#xD;&#xA;&gt; Don't forget that the BRDF of a diffuse surface is ρ/π where ρ stands for the surface albedo. So we need to divide the result by π. Though in the case of the indirect diffuse component, don't forget that we should have divided the result of castRay by the PDF of the random variable, which as we showed earlier in this chapter is 1/(2π). Dividing indirectDiffuseby 1/(2π) mis the same as multiplying this value by 2π. And since the albedo is also divided by π we can simplify the code...&#xD;&#xA;&#xD;&#xA;You have a similar situation. If you look at the PDF for the cosine sampling, then you will realise that terms can be cancelled out. Which doesn't mean they are 'not' strictly necessary. They are, they just cancel each other out which allows to optimize the code slightly (and avoid a few division, multiplication, etc.). You are more in the micro-optimisation here... which can be confusing if you try to learn the theory by just looking at optimised code (which is often not properly commented).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="10917" PostHistoryTypeId="2" PostId="4666" RevisionGUID="ff39c57c-7da5-42c0-b23b-9258cda25361" CreationDate="2017-02-05T10:27:08.100" UserId="1608" Text="This is called &quot;[deep shadow mapping][1]&quot; and deep compositing.&#xD;&#xA;&#xD;&#xA;Sadly invented long before you had this ideas yourself);&#xD;&#xA;&#xD;&#xA;Now you are talking about implementing this idea specifically on a given architecture (GPU). It's up to you to make it work for this given architecture, and if you have technical difficulties with that maybe you can ask a question on this forum again.&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/deepshadows/deepshad.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="10918" PostHistoryTypeId="2" PostId="4667" RevisionGUID="7240176b-7da4-49b8-83f1-7e49cdd5507e" CreationDate="2017-02-05T10:34:22.213" UserId="4958" Text="I was overthinking it. The usual reconstruction for given direction and then multiplication will work fine probably." ContentLicense="CC BY-SA 3.0" />
  <row Id="10919" PostHistoryTypeId="5" PostId="4665" RevisionGUID="467e3efe-ab25-43a6-8f8f-cffdb933e761" CreationDate="2017-02-05T10:57:39.233" UserId="1608" Comment="added 49 characters in body" Text="You always need to multiply by the cosine term indeed (that's part of the rendering equation). Though when you do indirect diffuse using ray-tracing and thus monte-carol integration (which is the most common technique in this case), you have to **divide** the contribution of each sample by your **PDF**. This is well exampled [here][1].&#xD;&#xA;&#xD;&#xA;Note also that in the mentioned reference, if the PDF has terms that you also find in the rendering equations then you can optimise the code if you wish by cancelling out these terms.&#xD;&#xA;&#xD;&#xA;&gt; Don't forget that the BRDF of a diffuse surface is ρ/π where ρ stands for the surface albedo. So we need to divide the result by π. Though in the case of the indirect diffuse component, don't forget that we should have divided the result of castRay by the PDF of the random variable, which as we showed earlier in this chapter is 1/(2π). Dividing indirectDiffuseby 1/(2π) mis the same as multiplying this value by 2π. And since the albedo is also divided by π we can simplify the code...&#xD;&#xA;&#xD;&#xA;You have a similar situation. If you look at the PDF for the cosine sampling, then you will realise that terms can be cancelled out. Which doesn't mean they are 'not' strictly necessary. They are, they just cancel each other out which allows to optimize the code slightly (and avoid a few division, multiplication, etc.). You are more in the micro-optimisation here... which can be confusing if you try to learn the theory by just looking at optimised code (which is often not properly commented).&#xD;&#xA;&#xD;&#xA;$ \dfrac{(cos(\theta) ... )}{PDF} = \dfrac{(cos(\theta) ... )}{\dfrac{cos(\theta)}{\pi}} = ... $&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="10920" PostHistoryTypeId="2" PostId="4668" RevisionGUID="0f0e02ce-debc-4367-85f9-70e5291ec6d7" CreationDate="2017-02-05T11:48:42.317" UserId="6003" Text="I'm familiar with the &quot;look-at&quot; matrix and the fact that, when it's created, the vector for the Z-axis needs to have its components negated, because the camera is assumed to be at the origin in view-space.&#xD;&#xA;&#xD;&#xA;However, sometimes you need to have other non-`Camera` objects &quot;look-at&quot; other objects, such as telling a `Dog` to &quot;look-at&quot; some `Food`, so that the `Dog` &quot;points&quot; in its direction. But in this case, if the look-at matrix used for the `Camera` is used without modification for the `Dog`, the `Dog` will end up looking in the *opposite* direction. Some sort of &quot;special corner case&quot; would need to be in place to detect what kind of object is trying to &quot;look-at&quot; something else, which is not desirable.&#xD;&#xA;&#xD;&#xA;Since my system has multiple, and different, `SceneObject`s at any given moment, some of which could be `Dog`s and some of which could be `Camera`s, I *really* need a way to build a matrix that will accomplish the goal of &quot;look-at&quot;, but that will work regardless of which kind of object it gets applied to.&#xD;&#xA;&#xD;&#xA;In other words, the logic a `Camera` would use to &quot;look-at&quot; the `Dog` should be the same logic the `Dog` would use to &quot;look-at&quot; the `Food`. **Is there a way to build such a &quot;look-at&quot;/equivalent matrix that would work for both cases so that I can avoid &quot;special corner cases&quot;?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="10921" PostHistoryTypeId="1" PostId="4668" RevisionGUID="0f0e02ce-debc-4367-85f9-70e5291ec6d7" CreationDate="2017-02-05T11:48:42.317" UserId="6003" Text="Is there a &quot;look-at&quot; matrix that also works on non-camera objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10922" PostHistoryTypeId="3" PostId="4668" RevisionGUID="0f0e02ce-debc-4367-85f9-70e5291ec6d7" CreationDate="2017-02-05T11:48:42.317" UserId="6003" Text="|opengl|3d|transformations|matrix|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10923" PostHistoryTypeId="2" PostId="4669" RevisionGUID="58bec5e4-d9a4-4578-bf4b-47ec47176984" CreationDate="2017-02-05T12:16:33.900" UserId="1608" Text="You don't seem to get the concept right:&#xD;&#xA;&#xD;&#xA;A [look-at camera matrix][1] is created by defining two points, the &quot;from&quot; point (the dog eyes for example assuming you take the position of the eyes of the dog and average them to get the point in between) and a &quot;to&quot; point which is where the dog looks at. So if your dog is at (3,3,3) and that you want it to look at the some food which is at (-10, 100, 20), then you need to call the lookAt() method with these 2 points and it will create a matrix that will actually orient and position the camera properly.&#xD;&#xA;&#xD;&#xA;Now you are getting confused (probably) because most cameras in most 3D packages are positioned at the origin (by default) and looking down the z-axis (by default). You can create such camera with a lookAt() function btw that would look like that:&#xD;&#xA;&#xD;&#xA;    lookAt(Vec3f(0), Vec3f(0,0,-1));&#xD;&#xA;&#xD;&#xA;For example. Now check what the matrix this call will produce with the matrix of the default camera in Maya. You will notice they are **different**. The second is an identity matrix, the first one is not.&#xD;&#xA;&#xD;&#xA;Now for example if you create a default camera in Maya it will be position at (0,0,0) and looking down the negative z-axis. If you look at the 4x4 matrix of this camera you will get identity. And maybe what you are trying to do is to create a 4x4matrix using the `lookAt` function and multiply this matrix by the Maya's default camera matrix in which case, your camera will point in the wrong direction (it will be flipped along the camera's local coordinate z-axis). That's because the matrix returns by `lookAt` properly orient the camera (as suggested in the first paragraph) but since the `default` camera in Maya is already oriented along the negative-z axis, your Maya camera will look the wrong way.&#xD;&#xA;&#xD;&#xA;So in summary:&#xD;&#xA;&#xD;&#xA;1. If you use the `lookAt` method in a renderer, it will work as you expect. There's no z problem.&#xD;&#xA;2. if you try to use it on a camera that is already oriented along the negative z-axis *and yet has identity matrix* yes indeed you will be looking the wrong way. This can be fixed easily by flipping the camera back one more time along the z-axis. Simply create another matrix that scales the object/camera by (1,1,-1).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="10924" PostHistoryTypeId="2" PostId="4670" RevisionGUID="ee336590-4c11-4e1b-8d4b-2c887d60535e" CreationDate="2017-02-05T12:26:53.187" UserId="6003" Text="The math for the projection matrix is:&#xD;&#xA;&#xD;&#xA;    def perspective_projection_matrix(fov, aspect, near, far):&#xD;&#xA;        q = 1 / tan(radians(fov * 0.5))&#xD;&#xA;        a = q / aspect&#xD;&#xA;        b = (far + near) / (near - far)&#xD;&#xA;        c = (2*near*far) / (near - far)&#xD;&#xA;&#xD;&#xA;**NOTE:** I left the last part out because I'm not familiar enough with `numpy` to know whether it expects row-major or column-major order.&#xD;&#xA;&#xD;&#xA;Notice that there're some things you're doing that are different, such as the subtractions between `near` and `far` and also how you organize the matrix values (e.g. the multiplication between your `r * t`).&#xD;&#xA;&#xD;&#xA;The column-major matrix below would be the resulting perspective projection matrix:&#xD;&#xA;&#xD;&#xA;    [a  0  0  0]&#xD;&#xA;    [0  q  0  0]&#xD;&#xA;    [0  0  b -1]&#xD;&#xA;    [0  0  c  0]&#xD;&#xA;&#xD;&#xA;Also, you should validate that both `near &gt; 0` and `far &gt; 0` and that `far &gt; near` if you want to avoid future headaches. This is the logic I'm using in my system to create perspective projection matrices, and it's working correctly." ContentLicense="CC BY-SA 3.0" />
  <row Id="10925" PostHistoryTypeId="5" PostId="4670" RevisionGUID="0a1f675d-2174-4e2d-b6d4-408d45134527" CreationDate="2017-02-05T12:39:52.360" UserId="6003" Comment="Corrected some typos" Text="The math for the projection matrix is:&#xD;&#xA;&#xD;&#xA;    def perspective_projection_matrix(fov, aspect, near, far):&#xD;&#xA;        q = 1 / tan(radians(fov * 0.5))&#xD;&#xA;        a = q / aspect&#xD;&#xA;        b = (far + near) / (near - far)&#xD;&#xA;        c = (2*near*far) / (near - far)&#xD;&#xA;&#xD;&#xA;**NOTE:** I left the last part out because I'm not familiar enough with `numpy` to know whether it expects row-major or column-major order.&#xD;&#xA;&#xD;&#xA;Notice that there're some things you're doing that are different, such as the subtractions between `near` and `far` and also how you organize the matrix values, and the multiplication between your `r * t`.&#xD;&#xA;&#xD;&#xA;The column-major matrix below would be the resulting perspective projection matrix:&#xD;&#xA;&#xD;&#xA;    [a  0  0  0]&#xD;&#xA;    [0  q  0  0]&#xD;&#xA;    [0  0  b -1]&#xD;&#xA;    [0  0  c  0]&#xD;&#xA;&#xD;&#xA;Also, you should validate that both `near &gt; 0` and `far &gt; 0` and that `far &gt; near` if you want to avoid future headaches. This is the logic I'm using in my system to create perspective projection matrices, and it's working correctly." ContentLicense="CC BY-SA 3.0" />
  <row Id="10926" PostHistoryTypeId="2" PostId="4671" RevisionGUID="8dc9ae64-11e3-4c69-af74-7271f86b1c34" CreationDate="2017-02-05T12:51:12.860" UserId="1608" Text="Please read the [references][1] that are given to you:&#xD;&#xA;&#xD;&#xA;$$S = \dfrac{1}{\tan(\dfrac{fov}{2}*\dfrac{\pi}{180})}$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left[\begin{array}{cccc}&#xD;&#xA;S &amp;&amp; 0 &amp;&amp; 0 &amp;&amp; 0 \\&#xD;&#xA;0 &amp;&amp; S &amp;&amp; 0 &amp;&amp; 0 \\&#xD;&#xA;0 &amp;&amp; 0 &amp;&amp; -\dfrac{f}{(f-n)} &amp;&amp; -1\\&#xD;&#xA;0 &amp;&amp; 0 &amp;&amp; -\dfrac{f*n}{(f-n)} &amp;&amp; 0\\&#xD;&#xA;\end{array}\right]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In this reference they use row-major order matrices so your assumption that your matrix is column-major is wrong (to start with). Then you will need to check the code you use to multiply this matrix with points. All source code is provided on the reference, so you just need to **read** and reproduce.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/building-basic-perspective-projection-matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="10927" PostHistoryTypeId="5" PostId="4670" RevisionGUID="b6abc6f3-c0b8-4999-8832-e8ab6110ee12" CreationDate="2017-02-05T13:36:21.037" UserId="6003" Comment="Fixed a typo" Text="The math for the projection matrix is:&#xD;&#xA;&#xD;&#xA;    def perspective_projection_matrix(fov, aspect, near, far):&#xD;&#xA;        q = 1 / tan(radians(fov * 0.5))&#xD;&#xA;        a = q / aspect&#xD;&#xA;        b = (far + near) / (near - far)&#xD;&#xA;        c = (2*near*far) / (near - far)&#xD;&#xA;&#xD;&#xA;**NOTE:** I left the last part out because I'm not familiar enough with `numpy` to know whether it expects row-major or column-major order.&#xD;&#xA;&#xD;&#xA;Notice that there're some things you're doing that are different, such as the subtractions between `near` and `far` and also how you organize the matrix values, and the multiplication between your `r * t`.&#xD;&#xA;&#xD;&#xA;The column-major matrix below would be the resulting perspective projection matrix:&#xD;&#xA;&#xD;&#xA;    [a  0  0  0]&#xD;&#xA;    [0  q  0  0]&#xD;&#xA;    [0  0  b  c]&#xD;&#xA;    [0  0 -1  0]&#xD;&#xA;&#xD;&#xA;Also, you should validate that both `near &gt; 0` and `far &gt; 0` and that `far &gt; near` if you want to avoid future headaches. This is the logic I'm using in my system to create perspective projection matrices, and it's working correctly." ContentLicense="CC BY-SA 3.0" />
  <row Id="10931" PostHistoryTypeId="5" PostId="4664" RevisionGUID="db86abf5-4591-4cb8-9ca4-7e58ec700554" CreationDate="2017-02-05T16:38:43.883" UserId="6001" Comment="added 1 character in body" Text="When converting from uniform hemisphere sampling to cosine weighted hemisphere sampling I am confused by a statement in an article.&#xD;&#xA;&#xD;&#xA;My current indirect contribution is calculated as:&#xD;&#xA;&#xD;&#xA;Vec3 rayDirectionUniform = UniformGenerator.Next()&#xD;&#xA;Color3 indirectDiffuse = N.dot(rayDirectionUniform) * castRay(P, rayDirectionUniform)&#xD;&#xA;&#xD;&#xA;Where the dot product is cos(θ)&#xD;&#xA;&#xD;&#xA;But in this article on better sampling (http://www.rorydriscoll.com/2009/01/07/better-sampling/) the author suggests the PDF is (cos(θ) / pi). &#xD;&#xA;&#xD;&#xA;My question is - does that mean that I no longer need to perform the normal dot rayDirection because it is included in the PDF, or is it in addition to the pdf?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10932" PostHistoryTypeId="5" PostId="4664" RevisionGUID="49ea21b4-fe73-45cd-a7b2-882486c08197" CreationDate="2017-02-05T17:27:39.723" UserId="6001" Comment="added 33 characters in body" Text="When converting from uniform hemisphere sampling to cosine weighted hemisphere sampling I am confused by a statement in an article.&#xD;&#xA;&#xD;&#xA;My current indirect contribution is calculated as:&#xD;&#xA;&#xD;&#xA;    Vec3 RayDir = UniformGenerator.Next()&#xD;&#xA;    Color3 indirectDiffuse = Normal.dot(RayDir) * castRay(Origin, RayDir)&#xD;&#xA;&#xD;&#xA;Where the dot product is cos(θ)&#xD;&#xA;&#xD;&#xA;But in this article on better sampling (http://www.rorydriscoll.com/2009/01/07/better-sampling/) the author suggests the PDF is (cos(θ) / pi), and there is no evidence of the N dot L calculation.&#xD;&#xA;&#xD;&#xA;My question is - does that mean that I no longer need to perform the normal dot rayDirection because it is included in the PDF, or is it in addition to the pdf?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10934" PostHistoryTypeId="5" PostId="4668" RevisionGUID="aaee4d8d-fb72-439f-9537-b619f4135f6a" CreationDate="2017-02-06T11:51:08.380" UserId="6003" Comment="Updated question title" Text="I'm familiar with the &quot;look-at&quot; matrix and the goal of being able to rotate a `Camera` at a specific location towards a specified target.&#xD;&#xA;&#xD;&#xA;When I tell the `Camera` to look at some target, there're no issues. However, when some other non-`Camera` object needs to &quot;look-at&quot; another object, such as a hypothetical `Dog` looking at some `Food`, so that the `Dog` &quot;points&quot; in its direction, it doesn't work as expected. In this case, when the look-at matrix used for the `Camera` is used (without modification) for the `Dog`, the `Dog` ends up looking in the *opposite* direction I intended it to face.&#xD;&#xA;&#xD;&#xA;What follows is the code I've been using to build my look-at matrix:&#xD;&#xA;&#xD;&#xA;    public static Matrix4 createLookAtMatrix(&#xD;&#xA;        Vector4 eyePosition,&#xD;&#xA;        Vector4 targetPosition,&#xD;&#xA;        Vector4 upDirection)&#xD;&#xA;    {&#xD;&#xA;        // forward, side, up&#xD;&#xA;        // &#xD;&#xA;        // f = normalize(targetPosition - eyePosition);&#xD;&#xA;        // s = normalize(f × normalize(upDirection));&#xD;&#xA;        // u = s × f;&#xD;&#xA;        Vector4 f = targetPosition.sub(eyePosition).normalize();&#xD;&#xA;        Vector4 s = f.cross(upDirection.normalize()).normalize();&#xD;&#xA;        Vector4 u = s.cross(f);&#xD;&#xA;&#xD;&#xA;        float[][] values = new float[][] {&#xD;&#xA;            { s.x(),  s.y(),  s.z(), -s.dot(eyePosition) },&#xD;&#xA;            { u.x(),  u.y(),  u.z(), -u.dot(eyePosition) },&#xD;&#xA;            {-f.x(), -f.y(), -f.z(), -f.dot(eyePosition) },&#xD;&#xA;            { 0f   ,  0f   ,  0f   ,  1f                 }&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        return createFrom(values);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What am I missing? Is there a way to build such a &quot;look-at&quot; matrix so that it works for both regardless of who/what the viewer is (i.e. `Camera` or `Dog`)?&#xD;&#xA;&#xD;&#xA;I'd like to avoid depending on &quot;special corner cases&quot; to detect what kind of object is trying to &quot;look-at&quot; something else, and so on.&#xD;&#xA;&#xD;&#xA;My system can have multiple `SceneObject`s at any given moment connected to the same `SceneNode` (`SceneNode`s are the objects that actually contain the transforms) and I *really* need a way to build a &quot;look-at&quot; matrix that will work regardless of which kind of object happens to get attached to the `SceneNode`." ContentLicense="CC BY-SA 3.0" />
  <row Id="10935" PostHistoryTypeId="4" PostId="4668" RevisionGUID="aaee4d8d-fb72-439f-9537-b619f4135f6a" CreationDate="2017-02-06T11:51:08.380" UserId="6003" Comment="Updated question title" Text="Correcting my &quot;look-at&quot; matrix so that it works on non-camera objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10936" PostHistoryTypeId="5" PostId="4668" RevisionGUID="f43e0096-b723-4473-9640-3fb735671cfc" CreationDate="2017-02-06T12:01:20.950" UserId="6003" Comment="Added look-at matrix book reference" Text="I'm familiar with the &quot;look-at&quot; matrix and the goal of being able to rotate a `Camera` at a specific location towards a specified target.&#xD;&#xA;&#xD;&#xA;When I tell the `Camera` to look at some target, there're no issues. However, when some other non-`Camera` object needs to &quot;look-at&quot; another object, such as a hypothetical `Dog` looking at some `Food`, so that the `Dog` &quot;points&quot; in its direction, it doesn't work as expected. In this case, when the look-at matrix used for the `Camera` is used (without modification) for the `Dog`, the `Dog` ends up looking in the *opposite* direction I intended it to face.&#xD;&#xA;&#xD;&#xA;What follows is the code I've been using to build my look-at matrix:&#xD;&#xA;&#xD;&#xA;    public static Matrix4 createLookAtMatrix(&#xD;&#xA;        Vector4 eyePosition,&#xD;&#xA;        Vector4 targetPosition,&#xD;&#xA;        Vector4 upDirection)&#xD;&#xA;    {&#xD;&#xA;        // forward, side, up&#xD;&#xA;        // &#xD;&#xA;        // f = normalize(targetPosition - eyePosition);&#xD;&#xA;        // s = normalize(f × normalize(upDirection));&#xD;&#xA;        // u = s × f;&#xD;&#xA;        Vector4 f = targetPosition.sub(eyePosition).normalize();&#xD;&#xA;        Vector4 s = f.cross(upDirection.normalize()).normalize();&#xD;&#xA;        Vector4 u = s.cross(f);&#xD;&#xA;&#xD;&#xA;        float[][] values = new float[][] {&#xD;&#xA;            { s.x(),  s.y(),  s.z(), -s.dot(eyePosition) },&#xD;&#xA;            { u.x(),  u.y(),  u.z(), -u.dot(eyePosition) },&#xD;&#xA;            {-f.x(), -f.y(), -f.z(), -f.dot(eyePosition) },&#xD;&#xA;            { 0f   ,  0f   ,  0f   ,  1f                 }&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        return createFrom(values);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What am I missing? Is there a way to build such a &quot;look-at&quot; matrix so that it works for both regardless of who/what the viewer is (i.e. `Camera` or `Dog`)?&#xD;&#xA;&#xD;&#xA;I'd like to avoid depending on &quot;special corner cases&quot; to detect what kind of object is trying to &quot;look-at&quot; something else, and so on.&#xD;&#xA;&#xD;&#xA;My system can have multiple `SceneObject`s at any given moment connected to the same `SceneNode` (`SceneNode`s are the objects that actually contain the transforms) and I *really* need a way to build a &quot;look-at&quot; matrix that will work regardless of which kind of object happens to get attached to the `SceneNode`.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;This is a screenshot of the reference book I was reading/using when writing my code above:&#xD;&#xA;&#xD;&#xA; [![The Look-At Matrix][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LV0gi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="10937" PostHistoryTypeId="5" PostId="4669" RevisionGUID="4ca0cb2e-a65a-4da7-819c-c7ccc018caf2" CreationDate="2017-02-06T12:14:37.027" UserId="1608" Comment="added 917 characters in body" Text="You don't seem to get the concept right:&#xD;&#xA;&#xD;&#xA;A [look-at camera matrix][1] is created by defining two points, the &quot;from&quot; point (the dog eyes for example assuming you take the position of the eyes of the dog and average them to get the point in between) and a &quot;to&quot; point which is where the dog looks at. So if your dog is at (3,3,3) and that you want it to look at the some food which is at (-10, 100, 20), then you need to call the lookAt() method with these 2 points and it will create a matrix that will actually orient and position the camera properly.&#xD;&#xA;&#xD;&#xA;Now you are getting confused (probably) because most cameras in most 3D packages are positioned at the origin (by default) and looking down the z-axis (by default). You can create such camera with a lookAt() function btw that would look like that:&#xD;&#xA;&#xD;&#xA;    lookAt(Vec3f(0), Vec3f(0,0,-1));&#xD;&#xA;&#xD;&#xA;For example. Now check what the matrix this call will produce with the matrix of the default camera in Maya. You will notice they are **different**. The second is an identity matrix, the first one is not.&#xD;&#xA;&#xD;&#xA;Now for example if you create a default camera in Maya it will be position at (0,0,0) and looking down the negative z-axis. If you look at the 4x4 matrix of this camera you will get identity. And maybe what you are trying to do is to create a 4x4matrix using the `lookAt` function and multiply this matrix by the Maya's default camera matrix in which case, your camera will point in the wrong direction (it will be flipped along the camera's local coordinate z-axis). That's because the matrix returns by `lookAt` properly orient the camera (as suggested in the first paragraph) but since the `default` camera in Maya is already oriented along the negative-z axis, your Maya camera will look the wrong way.&#xD;&#xA;&#xD;&#xA;So in summary:&#xD;&#xA;&#xD;&#xA;1. If you use the `lookAt` method in a renderer, it will work as you expect. There's no z problem.&#xD;&#xA;2. if you try to use it on a camera that is already oriented along the negative z-axis *and yet has identity matrix* yes indeed you will be looking the wrong way. This can be fixed easily by flipping the camera back one more time along the z-axis. Simply create another matrix that scales the object/camera by (1,1,-1).&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;The OP says:&#xD;&#xA;&#xD;&#xA;&gt; Blockquote&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; The camera is aligned along the negative z-axis. Does it mean I need to rotate the camera by 180 degrees along the y-axis or scale it up by -1 along the z-axis? Not at all. Transforming a camera is no different from transforming any other object in a scene. Keep in mind that in ray-tracing, we build the primary rays as if the camera was located in its default position. This is explained in the lesson Ray Tracing: Generating Camera Rays. This is when we actually reverse the direction of the rays. In other words, the z-coordinates of the rays' directions at this point are always negative: the camera in its default position, looks down along the negative z-axis. Those primary rays are then transformed by the camera-to-world matrix. Therefore, there is no need to account for the default orientation of the camera when the 4x4 camera-to-world matrix is built.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="10938" PostHistoryTypeId="5" PostId="4669" RevisionGUID="e1a8a96a-4b42-452f-9fac-311d28b4e418" CreationDate="2017-02-06T12:24:11.830" UserId="1608" Comment="added 917 characters in body" Text="You don't seem to get the concept right:&#xD;&#xA;&#xD;&#xA;A [look-at camera matrix][1] is created by defining two points, the &quot;from&quot; point (the dog eyes for example assuming you take the position of the eyes of the dog and average them to get the point in between) and a &quot;to&quot; point which is where the dog looks at. So if your dog is at (3,3,3) and that you want it to look at the some food which is at (-10, 100, 20), then you need to call the lookAt() method with these 2 points and it will create a matrix that will actually orient and position the camera properly.&#xD;&#xA;&#xD;&#xA;Now you are getting confused (probably) because most cameras in most 3D packages are positioned at the origin (by default) and looking down the z-axis (by default). You can create such camera with a lookAt() function btw that would look like that:&#xD;&#xA;&#xD;&#xA;    lookAt(Vec3f(0), Vec3f(0,0,-1));&#xD;&#xA;&#xD;&#xA;For example. Now check what the matrix this call will produce with the matrix of the default camera in Maya. You will notice they are **different**. The second is an identity matrix, the first one is not.&#xD;&#xA;&#xD;&#xA;Now for example if you create a default camera in Maya it will be position at (0,0,0) and looking down the negative z-axis. If you look at the 4x4 matrix of this camera you will get identity. And maybe what you are trying to do is to create a 4x4matrix using the `lookAt` function and multiply this matrix by the Maya's default camera matrix in which case, your camera will point in the wrong direction (it will be flipped along the camera's local coordinate z-axis). That's because the matrix returns by `lookAt` properly orient the camera (as suggested in the first paragraph) but since the `default` camera in Maya is already oriented along the negative-z axis, your Maya camera will look the wrong way.&#xD;&#xA;&#xD;&#xA;So in summary:&#xD;&#xA;&#xD;&#xA;1. If you use the `lookAt` method in a renderer, it will work as you expect. There's no z problem.&#xD;&#xA;2. if you try to use it on a camera that is already oriented along the negative z-axis *and yet has identity matrix* yes indeed you will be looking the wrong way. This can be fixed easily by flipping the camera back one more time along the z-axis. Simply create another matrix that scales the object/camera by (1,1,-1).&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;The OP says (see comment):&#xD;&#xA;&#xD;&#xA;&gt; I did spot what looks like a typo: it says &quot;(mind the direction of this vector: it is To − From not From − To)&quot;, but then you go on to write the line of code Vec3f forward = Normalize(from - to);, which contradicts what you were trying to clarify.&#xD;&#xA;&#xD;&#xA;But a note in the reference says:&#xD;&#xA;&#xD;&#xA;&gt; The camera is aligned along the negative z-axis. Does it mean I need to rotate the camera by 180 degrees along the y-axis or scale it up by -1 along the z-axis? Not at all. Transforming a camera is no different from transforming any other object in a scene. Keep in mind that in ray-tracing, we build the primary rays as if the camera was located in its default position. This is explained in the lesson Ray Tracing: Generating Camera Rays. This is when we actually reverse the direction of the rays. In other words, the z-coordinates of the rays' directions at this point are always negative: the camera in its default position, looks down along the negative z-axis. Those primary rays are then transformed by the camera-to-world matrix. Therefore, there is no need to account for the default orientation of the camera when the 4x4 camera-to-world matrix is built.&#xD;&#xA;&#xD;&#xA;So if you look at the reference they use by default a right-hand coordinate system, which means x-axis points to the right, y is up and z goes out of the screen (outward, going your direction when x-axis points to the right). So they build a matrix that &quot;follows this convention&quot; which makes sense. Then they say in the note &quot;yes but wait, normally the camera points down the negative z-axis, so you should be doing `to - from` and not `from - to`, and they explain that in the case of ray-tracing the fact that the camera looks down the z-axis is performed when the rays are cast (by inverting their z-coordinate).&#xD;&#xA;&#xD;&#xA;    Vec3f rayDirectionInCamSpace{ x, y, -1 }; // invert here&#xD;&#xA;    normalize(rayDirectionInCamSpace);&#xD;&#xA;    Vec3f rayDirInWorldSpace = transform(rayDirectionInCamSpace, camToWorldMat);&#xD;&#xA;    pixelColor = trace(rayOrigWorldSpace, rayDirInWorldSpace);&#xD;&#xA;&#xD;&#xA;So no it's not a typo. Now the reference you are pointing out maybe assume this matrix needs to be used in some OpenGL render in which there is no possibility to invert they ray direction when they cast. So they indeed use `to - from` instead which is the same as multiplying the cam-to-world matrix you would get from the reference by a matrix that flips the coordinates z-axis (multiply by (1,1,1-)).&#xD;&#xA;&#xD;&#xA;So no typo, things are quite logical in both cases. The result you get is always constrained to a lot of small details, such as the handiness of the coordinate system and how is the matrix later used down your graphics pipeline (OpenGL pipeline, ray-tracer, renderer, animation package, etc. which may follow its own conventions, etc.).&#xD;&#xA;&#xD;&#xA;EDIT 2&#xD;&#xA;======&#xD;&#xA;&#xD;&#xA;Note that in the terence your provide (screenshot of book) they do `target - eye` but then they use the negative of that in the matrix construction. Not sure why. Then also no idea why the multiply the eye by the side vector for the translation part of the matrix. It seems to be using column-order matrices as well). So you will need to understand why they do all this or take this into account in writing code.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="10939" PostHistoryTypeId="5" PostId="4669" RevisionGUID="58965d0e-8d64-4904-bc86-df1cac59b904" CreationDate="2017-02-06T12:30:04.067" UserId="1608" Comment="added 917 characters in body" Text="You don't seem to get the concept right:&#xD;&#xA;&#xD;&#xA;A [look-at camera matrix][1] is created by defining two points, the &quot;from&quot; point (the dog eyes for example assuming you take the position of the eyes of the dog and average them to get the point in between) and a &quot;to&quot; point which is where the dog looks at. So if your dog is at (3,3,3) and that you want it to look at the some food which is at (-10, 100, 20), then you need to call the lookAt() method with these 2 points and it will create a matrix that will actually orient and position the camera properly.&#xD;&#xA;&#xD;&#xA;Now you are getting confused (probably) because most cameras in most 3D packages are positioned at the origin (by default) and looking down the z-axis (by default). You can create such camera with a lookAt() function btw that would look like that:&#xD;&#xA;&#xD;&#xA;    lookAt(Vec3f(0), Vec3f(0,0,-1));&#xD;&#xA;&#xD;&#xA;For example. Now check what the matrix this call will produce with the matrix of the default camera in Maya. You will notice they are **different**. The second is an identity matrix, the first one is not.&#xD;&#xA;&#xD;&#xA;Now for example if you create a default camera in Maya it will be position at (0,0,0) and looking down the negative z-axis. If you look at the 4x4 matrix of this camera you will get identity. And maybe what you are trying to do is to create a 4x4matrix using the `lookAt` function and multiply this matrix by the Maya's default camera matrix in which case, your camera will point in the wrong direction (it will be flipped along the camera's local coordinate z-axis). That's because the matrix returns by `lookAt` properly orient the camera (as suggested in the first paragraph) but since the `default` camera in Maya is already oriented along the negative-z axis, your Maya camera will look the wrong way.&#xD;&#xA;&#xD;&#xA;So in summary:&#xD;&#xA;&#xD;&#xA;1. If you use the `lookAt` method in a renderer, it will work as you expect. There's no z problem.&#xD;&#xA;2. if you try to use it on a camera that is already oriented along the negative z-axis *and yet has identity matrix* yes indeed you will be looking the wrong way. This can be fixed easily by flipping the camera back one more time along the z-axis. Simply create another matrix that scales the object/camera by (1,1,-1).&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;The OP says (see comment):&#xD;&#xA;&#xD;&#xA;&gt; I did spot what looks like a typo: it says &quot;(mind the direction of this vector: it is To − From not From − To)&quot;, but then you go on to write the line of code Vec3f forward = Normalize(from - to);, which contradicts what you were trying to clarify.&#xD;&#xA;&#xD;&#xA;But a note in the reference says:&#xD;&#xA;&#xD;&#xA;&gt; The camera is aligned along the negative z-axis. Does it mean I need to rotate the camera by 180 degrees along the y-axis or scale it up by -1 along the z-axis? Not at all. Transforming a camera is no different from transforming any other object in a scene. Keep in mind that in ray-tracing, we build the primary rays as if the camera was located in its default position. This is explained in the lesson Ray Tracing: Generating Camera Rays. This is when we actually reverse the direction of the rays. In other words, the z-coordinates of the rays' directions at this point are always negative: the camera in its default position, looks down along the negative z-axis. Those primary rays are then transformed by the camera-to-world matrix. Therefore, there is no need to account for the default orientation of the camera when the 4x4 camera-to-world matrix is built.&#xD;&#xA;&#xD;&#xA;So if you look at the reference they use by default a right-hand coordinate system, which means x-axis points to the right, y is up and z goes out of the screen (outward, going your direction when x-axis points to the right). So they build a matrix that &quot;follows this convention&quot; which makes sense. Then they say in the note &quot;yes but wait, normally the camera points down the negative z-axis, so you should be doing `to - from` and not `from - to`, and they explain that in the case of ray-tracing the fact that the camera looks down the z-axis is performed when the rays are cast (by inverting their z-coordinate).&#xD;&#xA;&#xD;&#xA;    Vec3f rayDirectionInCamSpace{ x, y, -1 }; // invert here&#xD;&#xA;    normalize(rayDirectionInCamSpace);&#xD;&#xA;    Vec3f rayDirInWorldSpace = transform(rayDirectionInCamSpace, camToWorldMat);&#xD;&#xA;    pixelColor = trace(rayOrigWorldSpace, rayDirInWorldSpace);&#xD;&#xA;&#xD;&#xA;So no it's not a typo. Now the reference you are pointing out maybe assume this matrix needs to be used in some OpenGL render in which there is no possibility to invert they ray direction when they cast. So they indeed use `to - from` instead which is the same as multiplying the cam-to-world matrix you would get from the reference by a matrix that flips the coordinates z-axis (multiply by (1,1,1-)).&#xD;&#xA;&#xD;&#xA;So no typo, things are quite logical in both cases. The result you get is always constrained to a lot of small details, such as the handiness of the coordinate system and how is the matrix later used down your graphics pipeline (OpenGL pipeline, ray-tracer, renderer, animation package, etc. which may follow its own conventions, etc.).&#xD;&#xA;&#xD;&#xA;EDIT 2&#xD;&#xA;======&#xD;&#xA;&#xD;&#xA;Note that in the reference your provide (screenshot of book) they do `target - eye` but then they use the negative of that in the matrix construction. Not sure why. Then also no idea why the multiply the eye by the vectors for the translation part of the matrix. It seems to be using row-order matrices for the axis of the coordinate system but then the translation part should be at m[3][0], m[3][1] and m[3][2] and not m[0][3], m[1][3] and m[2][3]. Not sure what book this is but seems to be terribly wrong and confusing.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="10940" PostHistoryTypeId="5" PostId="4669" RevisionGUID="d236f9cc-8e49-44e3-8b6b-88f4512d589f" CreationDate="2017-02-06T12:32:57.597" UserId="1608" Comment="added 917 characters in body" Text="You don't seem to get the concept right:&#xD;&#xA;&#xD;&#xA;A [look-at camera matrix][1] is created by defining two points, the &quot;from&quot; point (the dog eyes for example assuming you take the position of the eyes of the dog and average them to get the point in between) and a &quot;to&quot; point which is where the dog looks at. So if your dog is at (3,3,3) and that you want it to look at the some food which is at (-10, 100, 20), then you need to call the lookAt() method with these 2 points and it will create a matrix that will actually orient and position the camera properly.&#xD;&#xA;&#xD;&#xA;Now you are getting confused (probably) because most cameras in most 3D packages are positioned at the origin (by default) and looking down the z-axis (by default). You can create such camera with a lookAt() function btw that would look like that:&#xD;&#xA;&#xD;&#xA;    lookAt(Vec3f(0), Vec3f(0,0,-1));&#xD;&#xA;&#xD;&#xA;For example. Now check what the matrix this call will produce with the matrix of the default camera in Maya. You will notice they are **different**. The second is an identity matrix, the first one is not.&#xD;&#xA;&#xD;&#xA;Now for example if you create a default camera in Maya it will be position at (0,0,0) and looking down the negative z-axis. If you look at the 4x4 matrix of this camera you will get identity. And maybe what you are trying to do is to create a 4x4matrix using the `lookAt` function and multiply this matrix by the Maya's default camera matrix in which case, your camera will point in the wrong direction (it will be flipped along the camera's local coordinate z-axis). That's because the matrix returns by `lookAt` properly orient the camera (as suggested in the first paragraph) but since the `default` camera in Maya is already oriented along the negative-z axis, your Maya camera will look the wrong way.&#xD;&#xA;&#xD;&#xA;So in summary:&#xD;&#xA;&#xD;&#xA;1. If you use the `lookAt` method in a renderer, it will work as you expect. There's no z problem.&#xD;&#xA;2. if you try to use it on a camera that is already oriented along the negative z-axis *and yet has identity matrix* yes indeed you will be looking the wrong way. This can be fixed easily by flipping the camera back one more time along the z-axis. Simply create another matrix that scales the object/camera by (1,1,-1).&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;The OP says (see comment):&#xD;&#xA;&#xD;&#xA;&gt; I did spot what looks like a typo: it says &quot;(mind the direction of this vector: it is To − From not From − To)&quot;, but then you go on to write the line of code Vec3f forward = Normalize(from - to);, which contradicts what you were trying to clarify.&#xD;&#xA;&#xD;&#xA;But a note in the reference says:&#xD;&#xA;&#xD;&#xA;&gt; The camera is aligned along the negative z-axis. Does it mean I need to rotate the camera by 180 degrees along the y-axis or scale it up by -1 along the z-axis? Not at all. Transforming a camera is no different from transforming any other object in a scene. Keep in mind that in ray-tracing, we build the primary rays as if the camera was located in its default position. This is explained in the lesson Ray Tracing: Generating Camera Rays. This is when we actually reverse the direction of the rays. In other words, the z-coordinates of the rays' directions at this point are always negative: the camera in its default position, looks down along the negative z-axis. Those primary rays are then transformed by the camera-to-world matrix. Therefore, there is no need to account for the default orientation of the camera when the 4x4 camera-to-world matrix is built.&#xD;&#xA;&#xD;&#xA;So if you look at the reference they use by default a right-hand coordinate system, which means x-axis points to the right, y is up and z goes out of the screen (outward, going your direction when x-axis points to the right). So they build a matrix that &quot;follows this convention&quot; which makes sense. Then they say in the note &quot;yes but wait, normally the camera points down the negative z-axis, so you should be doing `to - from` and not `from - to`, and they explain that in the case of ray-tracing the fact that the camera looks down the z-axis is performed when the rays are cast (by inverting their z-coordinate).&#xD;&#xA;&#xD;&#xA;    Vec3f rayDirectionInCamSpace{ x, y, -1 }; // invert here&#xD;&#xA;    normalize(rayDirectionInCamSpace);&#xD;&#xA;    Vec3f rayDirInWorldSpace = transform(rayDirectionInCamSpace, camToWorldMat);&#xD;&#xA;    pixelColor = trace(rayOrigWorldSpace, rayDirInWorldSpace);&#xD;&#xA;&#xD;&#xA;So no it's not a typo. Now the reference you are pointing out maybe assume this matrix needs to be used in some OpenGL render in which there is no possibility to invert they ray direction when they cast. So they indeed use `to - from` instead which is the same as multiplying the cam-to-world matrix you would get from the reference by a matrix that flips the coordinates z-axis (multiply by (1,1,1-)).&#xD;&#xA;&#xD;&#xA;So no typo, things are quite logical in both cases. The result you get is always constrained to a lot of small details, such as the handiness of the coordinate system and how is the matrix later used down your graphics pipeline (OpenGL pipeline, ray-tracer, renderer, animation package, etc. which may follow its own conventions, etc.).&#xD;&#xA;&#xD;&#xA;EDIT 2&#xD;&#xA;======&#xD;&#xA;&#xD;&#xA;Note that in the reference your provide (screenshot of book) they do `target - eye` but then they use the negative of that in the matrix construction. Not sure why. Then also no idea why the multiply the eye by the vectors for the translation part of the matrix. It seems to be using row-order matrices for the axis of the coordinate system but then the translation part should be at `mat[3][0]`, `mat[3][1]` and `mat[3][2]` and not `mat[0][3]`, `mat[1][3]` and `mat[2][3]`. Not sure what book this is but seems to be terribly wrong and confusing.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="10941" PostHistoryTypeId="5" PostId="4669" RevisionGUID="095a0507-40bc-49ba-a71f-66d618ade09d" CreationDate="2017-02-06T12:39:26.050" UserId="1608" Comment="added 917 characters in body" Text="You don't seem to get the concept right:&#xD;&#xA;&#xD;&#xA;A [look-at camera matrix][1] is created by defining two points, the &quot;from&quot; point (the dog eyes for example assuming you take the position of the eyes of the dog and average them to get the point in between) and a &quot;to&quot; point which is where the dog looks at. So if your dog is at (3,3,3) and that you want it to look at the some food which is at (-10, 100, 20), then you need to call the lookAt() method with these 2 points and it will create a matrix that will actually orient and position the camera properly.&#xD;&#xA;&#xD;&#xA;Now you are getting confused (probably) because most cameras in most 3D packages are positioned at the origin (by default) and looking down the z-axis (by default). You can create such camera with a lookAt() function btw that would look like that:&#xD;&#xA;&#xD;&#xA;    lookAt(Vec3f(0), Vec3f(0,0,-1));&#xD;&#xA;&#xD;&#xA;For example. Now check what the matrix this call will produce with the matrix of the default camera in Maya. You will notice they are **different**. The second is an identity matrix, the first one is not.&#xD;&#xA;&#xD;&#xA;Now for example if you create a default camera in Maya it will be position at (0,0,0) and looking down the negative z-axis. If you look at the 4x4 matrix of this camera you will get identity. And maybe what you are trying to do is to create a 4x4matrix using the `lookAt` function and multiply this matrix by the Maya's default camera matrix in which case, your camera will point in the wrong direction (it will be flipped along the camera's local coordinate z-axis). That's because the matrix returns by `lookAt` properly orient the camera (as suggested in the first paragraph) but since the `default` camera in Maya is already oriented along the negative-z axis, your Maya camera will look the wrong way.&#xD;&#xA;&#xD;&#xA;So in summary:&#xD;&#xA;&#xD;&#xA;1. If you use the `lookAt` method in a renderer, it will work as you expect. There's no z problem.&#xD;&#xA;2. if you try to use it on a camera that is already oriented along the negative z-axis *and yet has identity matrix* yes indeed you will be looking the wrong way. This can be fixed easily by flipping the camera back one more time along the z-axis. Simply create another matrix that scales the object/camera by (1,1,-1).&#xD;&#xA;&#xD;&#xA;EDIT&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;The OP says (see comment):&#xD;&#xA;&#xD;&#xA;&gt; I did spot what looks like a typo: it says &quot;(mind the direction of this vector: it is To − From not From − To)&quot;, but then you go on to write the line of code Vec3f forward = Normalize(from - to);, which contradicts what you were trying to clarify.&#xD;&#xA;&#xD;&#xA;But a note in the reference says:&#xD;&#xA;&#xD;&#xA;&gt; The camera is aligned along the negative z-axis. Does it mean I need to rotate the camera by 180 degrees along the y-axis or scale it up by -1 along the z-axis? Not at all. Transforming a camera is no different from transforming any other object in a scene. Keep in mind that in ray-tracing, we build the primary rays as if the camera was located in its default position. This is explained in the lesson Ray Tracing: Generating Camera Rays. This is when we actually reverse the direction of the rays. In other words, the z-coordinates of the rays' directions at this point are always negative: the camera in its default position, looks down along the negative z-axis. Those primary rays are then transformed by the camera-to-world matrix. Therefore, there is no need to account for the default orientation of the camera when the 4x4 camera-to-world matrix is built.&#xD;&#xA;&#xD;&#xA;So if you look at the reference they use by default a right-hand coordinate system, which means x-axis points to the right, y is up and z goes out of the screen (outward, going your direction when x-axis points to the right). So they build a matrix that &quot;follows this convention&quot; which makes sense. Then they say in the note &quot;yes but wait, normally the camera points down the negative z-axis, so you should be doing `to - from` and not `from - to`, and they explain that in the case of ray-tracing the fact that the camera looks down the z-axis is performed when the rays are cast (by inverting their z-coordinate).&#xD;&#xA;&#xD;&#xA;    Vec3f rayDirectionInCamSpace{ x, y, -1 }; // invert here&#xD;&#xA;    normalize(rayDirectionInCamSpace);&#xD;&#xA;    Vec3f rayDirInWorldSpace = transform(rayDirectionInCamSpace, camToWorldMat);&#xD;&#xA;    pixelColor = trace(rayOrigWorldSpace, rayDirInWorldSpace);&#xD;&#xA;&#xD;&#xA;So no it's not a typo. Now the reference you are pointing out maybe assume this matrix needs to be used in some OpenGL render in which there is no possibility to invert they ray direction when they cast. So they indeed use `to - from` instead which is the same as multiplying the cam-to-world matrix you would get from the reference by a matrix that flips the coordinates z-axis (multiply by (1,1,1-)).&#xD;&#xA;&#xD;&#xA;So no typo, things are quite logical in both cases. The result you get is always constrained to a lot of small details, such as the handiness of the coordinate system and how is the matrix later used down your graphics pipeline (OpenGL pipeline, ray-tracer, renderer, animation package, etc. which may follow its own conventions, etc.).&#xD;&#xA;&#xD;&#xA;EDIT 2&#xD;&#xA;======&#xD;&#xA;&#xD;&#xA;Note that in the reference your provide (screenshot of book) they do `target - eye` but then they use the negative of that in the matrix construction. Not sure why. Then also no idea why the multiply the eye by the vectors for the translation part of the matrix. It seems to be using row-order matrices for the axis of the coordinate system but then the translation part should be at `mat[3][0]`, `mat[3][1]` and `mat[3][2]` and not `mat[0][3]`, `mat[1][3]` and `mat[2][3]`. Not sure what book this is but seems to be terribly wrong and confusing.&#xD;&#xA;&#xD;&#xA;EDIT 3&#xD;&#xA;======&#xD;&#xA;&#xD;&#xA;Code (that seems to be the only solution):&#xD;&#xA;&#xD;&#xA;    void lookAt(const Vec3f&amp; from, const Vec3f&amp; to, Matrix44f &amp;V)&#xD;&#xA;    {&#xD;&#xA;        static const Vec3f tmp(0, 1, 0);&#xD;&#xA;        Vec3f forward = normalize(from - to);&#xD;&#xA;        Vec3f right = crossProduct(normalize(tmp), forward); &#xD;&#xA;        Vec3f up = crossProduct(forward, right); &#xD;&#xA;      &#xD;&#xA;        V[0][0] = right.x;&#xD;&#xA;        V[0][1] = right.y;&#xD;&#xA;        V[0][2] = right.z;&#xD;&#xA;        V[1][0] = up.x;&#xD;&#xA;        V[1][1] = up.y;&#xD;&#xA;        V[1][2] = up.z;&#xD;&#xA;        V[2][0] = forward.x;&#xD;&#xA;        V[2][1] = forward.y;&#xD;&#xA;        V[2][2] = forward.z;&#xD;&#xA;     &#xD;&#xA;        V[3][0] = from.x;&#xD;&#xA;        V[3][1] = from.y;&#xD;&#xA;        V[3][2] = from.z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int main(int argc, char **argv)&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        lookAt(from, to, camToWorldMatrix);&#xD;&#xA;        worldToCamMatrix = camera.camToWorldMatrix.inverse();&#xD;&#xA;&#xD;&#xA;        Matrix44f projectionMatrix;&#xD;&#xA;&#xD;&#xA;        Matrix44f openGLWorldToCamMatrix = worldToCamMatrix;&#xD;&#xA;        Matrix44f openGLProjectionMatrix = projectionMatrix;&#xD;&#xA;&#xD;&#xA;        while (!glfwWindowShouldClose(window)) {        &#xD;&#xA;            glViewport(0, 0, width, height);&#xD;&#xA;&#xD;&#xA;            glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, (const GLfloat *)&amp;openGLProjectionMatrix[0][0]);&#xD;&#xA;            glUniformMatrix4fv(viewLocation, 1, GL_FALSE, (const GLfloat *)&amp;openGLWorldToCamMatrix[0][0]);&#xD;&#xA;        &#xD;&#xA;            ...            &#xD;&#xA;            wwapBuffers(window);&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="10942" PostHistoryTypeId="2" PostId="4673" RevisionGUID="ed35cff3-8e5c-48ed-a728-0c881bb11b56" CreationDate="2017-02-06T16:41:25.357" UserId="6011" Text="You're right, standard skinning pipelines don't produce correct normals. You get similar problems when using translation on joints, which is very common in facial animation. The only way to get a correct result is to take the average of the surrounding face normals - this is not information you will be able to get in the vertex shader, so you'll have to use a geometry shader or run your skinning on CPU or a compute shader. " ContentLicense="CC BY-SA 3.0" />
  <row Id="10946" PostHistoryTypeId="2" PostId="4675" RevisionGUID="8e0f0647-dcea-4529-bb62-1ddb6d46b225" CreationDate="2017-02-06T21:02:46.383" UserId="5960" Text="In order to reduce the amount of draw calls per frame I've decided to use a vertex array object to store vertex data from several different meshes. More precisely, I use the vao to the define the vertex format (attributes) and the buffers which contain the vertex and index data.&#xD;&#xA;&#xD;&#xA;Now I could call glDrawElements on the batch's vao once and draw all the stored vertex data directly. But I also see a lot of discussions about sorting your draw data front-to-back for opaque objects (in order to reduce overdraw) and back-to-front for translucent objects (in order to blend 'correctly'). &#xD;&#xA;&#xD;&#xA;I was wondering how you would go about sorting the contents of several vertex batches (vaos) even though a batch most likely contains data for objects at different distances from the camera. &#xD;&#xA;Say batch **A** contains objects with depth { 1, 3, 5 } and batch **B** contains objects with depth { 2, 4 }, how could this be sorted properly so that it can be drawn in the order { 1, 2, 3, 4, 5 } without specifying 5 separate draw calls (with each a different buffer offset).&#xD;&#xA;&#xD;&#xA;Were it just the overdraw *optimization* I would probably just say *screw it* as it would allow me to draw an entire buffer's contents in one go (instead of having a draw call with a different offset for each object), but then there's still the sorting of translucent objects.&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10947" PostHistoryTypeId="1" PostId="4675" RevisionGUID="8e0f0647-dcea-4529-bb62-1ddb6d46b225" CreationDate="2017-02-06T21:02:46.383" UserId="5960" Text="Can you batch vertex data and still sort by depth?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10948" PostHistoryTypeId="3" PostId="4675" RevisionGUID="8e0f0647-dcea-4529-bb62-1ddb6d46b225" CreationDate="2017-02-06T21:02:46.383" UserId="5960" Text="|opengl|rendering|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10949" PostHistoryTypeId="2" PostId="4676" RevisionGUID="913f4390-3b85-4f86-ab19-c8f0c9e2ec2a" CreationDate="2017-02-07T02:55:16.393" UserId="6015" Text="I am making an iOS game using Unity. I am testing some shaders that I have made for the game, and in some cases the device will run at under 30 FPS but not have 100% device utilization.&#xD;&#xA;&#xD;&#xA;Sometimes a test will start at a higher device utilization %, and then over time go lower, even though the test is simply rendering a plane with a material on it.&#xD;&#xA;&#xD;&#xA;For example, a shader test I just ran on an iPad 4: Device utilization 85% Renderer utilization 85% Tiler utilization 1% Core Animation Frames Per Second 12&#xD;&#xA;&#xD;&#xA;This test is using barely any CPU, and is only rendering 4 triangles (2 big planes covering the screen).&#xD;&#xA;&#xD;&#xA;Does anyone have any ideas why this could be happening? Usually the renderer utilization goes up to 100%... pretty stumped, being a graphics rookie.&#xD;&#xA;&#xD;&#xA;Thanks for the help!" ContentLicense="CC BY-SA 3.0" />
  <row Id="10950" PostHistoryTypeId="1" PostId="4676" RevisionGUID="913f4390-3b85-4f86-ab19-c8f0c9e2ec2a" CreationDate="2017-02-07T02:55:16.393" UserId="6015" Text="GPU not reaching 100% usage when frame rate is dropping" ContentLicense="CC BY-SA 3.0" />
  <row Id="10951" PostHistoryTypeId="3" PostId="4676" RevisionGUID="913f4390-3b85-4f86-ab19-c8f0c9e2ec2a" CreationDate="2017-02-07T02:55:16.393" UserId="6015" Text="|shader|performance|unity|mobile|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10952" PostHistoryTypeId="2" PostId="4677" RevisionGUID="ec243e1c-7f4a-4a55-985f-25dff60f2818" CreationDate="2017-02-07T03:01:01.057" UserId="2654" Text="Drawing back-to-front is *not optional* with blending (unless you use an order-independent blending technique), so getting the visual effect you actually want has to trump performance.&#xD;&#xA;&#xD;&#xA;But drawing front-to-back is purely a performance thing. Specifically, it makes it possible for early-Z to save you fragment processing time, as earlier objects are in front of later ones. So it's a GPU performance improvement.&#xD;&#xA;&#xD;&#xA;Batching is a performance improvement for the *CPU*, in that you're spending less CPU time doing state change stuff.&#xD;&#xA;&#xD;&#xA;So you need to decide which is more important: CPU performance or GPU performance. With deferred rendering, saving FS computation time also means saving memory bandwidth.&#xD;&#xA;&#xD;&#xA;But the general construction of your scene, what you're actually drawing, can help inform which is more important.&#xD;&#xA;&#xD;&#xA;Oftentimes what happens is that you render static terrain first, perhaps using your visibility system to order what you render coarsely front-to-back. Then you render your dynamic objects. Because dynamic objects usually require a lot of state changes, you won't necessarily draw all of them in a single batch (though there are techniques you can use to hide even texture changes).&#xD;&#xA;&#xD;&#xA;In any case, the point is that there is a tradeoff. And the one you pick depends on exactly what you're rendering. A top-down game like StarCraft or DotA would never bother with front-to-back sorting; you just render the terrain after the characters. A tight-quarters FPS by contrast would probably really need to employ such techniques, particularly for terrain." ContentLicense="CC BY-SA 3.0" />
  <row Id="10953" PostHistoryTypeId="2" PostId="4678" RevisionGUID="d2d85ea7-1a18-4ad7-bbea-fdf9abad5f7c" CreationDate="2017-02-07T03:12:49.807" UserId="2707" Text="Yes, but with tradeoffs.&#xD;&#xA;&#xD;&#xA;The problem is that there are two optimizations going on here at different potential bottlenecks, the CPU and the GPU.&#xD;&#xA;&#xD;&#xA;# Reducing Overdraw&#xD;&#xA;The goal of reducing overdraw primarily is to reduce the number of times the fragment shader runs via early-z discard. This is usually desirable when you have expensive fragment shaders. However, maintaining a strict depth ordering here may not be necessary. A few common techniques are to either use deferred rendering or to use a depth pre-pass (particularly if you have a forward renderer variant) to minimize the time it takes to run the fragment shaders.&#xD;&#xA;&#xD;&#xA;The depth pre-pass technique will require double the draw calls and double the execution of the rest of the shader types (vertex, tessellation control, tessellation evaluation, and geometry) twice, but it may be worth it depending on the scene. The fragment shader is executed twice as well, but usually you would use a very simple one for the pre-pass.&#xD;&#xA;&#xD;&#xA;# Preserving Transparency&#xD;&#xA;Transparency of course is a different story. Many applications avoided transparency because of two problems:&#xD;&#xA;&#xD;&#xA;  - Objects blending in order&#xD;&#xA;  - Fragments blending in order&#xD;&#xA;&#xD;&#xA;Even if you are able to sort each object by depth at the VBO or VAO level, it's still not guaranteed to be accurate. For example, two objects could overlap each other. Even within the same object, two triangles can overlap each other, so unless you perform clipping, the transparency order may not be correct. You can sort by the fragment level. There are various order-independent transparency techniques, ranging from screen-door transparency to more accurate variants such as depth-peeling.&#xD;&#xA;&#xD;&#xA;However, if you are concerned about draw calls and want accurate transparency, then there are techniques that are single-pass order-independent transparency that are becoming more popular. These rely on saving fragment shader output values in additional buffers (generally called A-buffers) and sorting through them later, performing blending manually. These single-pass techniques requires shader atomics though, so OpenGL 4.2 is required." ContentLicense="CC BY-SA 3.0" />
  <row Id="10956" PostHistoryTypeId="2" PostId="4680" RevisionGUID="79a8e611-bbde-4b58-bd4c-d8882d27f5bc" CreationDate="2017-02-07T06:55:00.263" UserId="3003" Text="You should look into [Medial Axis Transform](https://en.wikipedia.org/wiki/Medial_axis) or [Straight Skeletons](https://en.wikipedia.org/wiki/Straight_skeleton). They are often used to generate the information you need to bevel things properly. They give you a distance from the bounds of your object at any point in space, which allows you to generate bevels correctly. They are difficult to calculate, though.&#xD;&#xA;&#xD;&#xA;You may also want to look into [this paper](http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf) from Valve Software for an alternative way to generate the distance field." ContentLicense="CC BY-SA 3.0" />
  <row Id="10963" PostHistoryTypeId="5" PostId="4670" RevisionGUID="77dfad5f-ad44-4716-a64a-571ca0ae51a7" CreationDate="2017-02-08T00:16:12.833" UserId="6003" Comment="Reworded and reformatted answer to use MathJax equations for the matrix and variable assignments" Text="The math for the projection matrix is (with `fov` as $\alpha$):&#xD;&#xA;&#xD;&#xA;$q \leftarrow \frac{1}{tan(\frac{\alpha}{2})}$&#xD;&#xA;&#xD;&#xA;$a \leftarrow \frac{q}{aspect}$&#xD;&#xA;&#xD;&#xA;$b \leftarrow \frac{(far + near)}{(near - far)}$&#xD;&#xA;&#xD;&#xA;$c \leftarrow \frac{(2 * far * near)}{(near - far)}$&#xD;&#xA;&#xD;&#xA;Notice that there're some things you're doing that are differently, such as the order of your subtractions between `near` and `far`, how you organize the matrix values, and your multiplication between your `r * t`.&#xD;&#xA;&#xD;&#xA;Using the variables above, the column-major matrix below would be the resulting perspective projection matrix:&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;  a &amp; 0 &amp;  0 &amp; 0 \\&#xD;&#xA;  0 &amp; q &amp;  0 &amp; 0 \\&#xD;&#xA;  0 &amp; 0 &amp;  b &amp; c \\&#xD;&#xA;  0 &amp; 0 &amp; -1 &amp; 0&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;From the above, we get:&#xD;&#xA;&#xD;&#xA;    def perspective_projection_matrix(fov, aspect, near, far):&#xD;&#xA;        q = 1 / tan(radians(fov * 0.5))&#xD;&#xA;        a = q / aspect&#xD;&#xA;        b = (far + near) / (near - far)&#xD;&#xA;        c = (2*near*far) / (near - far)&#xD;&#xA;&#xD;&#xA;        # construct column-major matrix here...&#xD;&#xA;&#xD;&#xA;**NOTE:** I left the last part out because I'm not familiar enough with `numpy` to know whether it expects row-major or column-major order.&#xD;&#xA;&#xD;&#xA;Also, you should validate all your arguments (e.g. both `near &gt; 0` and `far &gt; 0`, `far &gt; near`, etc.) if you want to avoid future headaches." ContentLicense="CC BY-SA 3.0" />
  <row Id="10964" PostHistoryTypeId="2" PostId="4682" RevisionGUID="2cfa6ba7-4703-47b7-b068-a7a32e52f807" CreationDate="2017-02-08T03:07:14.083" UserId="6023" Text="I wrote a small python script with recursion to create a &quot;lattice&quot; of non-overlapping pentagons. Below one can see the first stages of recursion.&#xD;&#xA;&#xD;&#xA;[![first recursion][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![second recursion][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WIGNE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1uVtg.png&#xD;&#xA;&#xD;&#xA;One can see that 5 small pentagons are missing in the second stage of recursion. The code in python to generate these figures is this:&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;    # fill the plane with pentagons as tightly as possible in a regular way&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    phi = (1.0+np.sqrt(5.0))/2&#xD;&#xA;    def pentagon (X, Y, n):&#xD;&#xA;        if n == 0:&#xD;&#xA;            rx = np.append(X, X[0])&#xD;&#xA;            ry = np.append(Y, Y[0])&#xD;&#xA;            plt.plot(rx, ry, 'r-')&#xD;&#xA;            return&#xD;&#xA;        for i in range(N):&#xD;&#xA;            Xn = np.array([X[i], X[i], X[i], X[i], X[i]])&#xD;&#xA;            Yn = np.array([Y[i], Y[i], Y[i], Y[i], Y[i]])&#xD;&#xA;        U = Xn/phi+X*(1-1.0/phi)&#xD;&#xA;        V = Yn/phi+Y*(1-1.0/phi)&#xD;&#xA;        pentagon (U, V, n-1)&#xD;&#xA;    Xn = X/phi +np.roll(X, 2)*(1-1.0/phi)&#xD;&#xA;    Yn = Y/phi +np.roll(Y, 2)*(1-1.0/phi)&#xD;&#xA;    # center pentagon&#xD;&#xA;    pentagon (Xn, Yn, n-1)&#xD;&#xA;    Ind = np.arange(N)&#xD;&#xA;    theta =np.pi/10&#xD;&#xA;    X = np.cos(Ind*2*np.pi/N+theta)&#xD;&#xA;    Y = np.sin(Ind*2*np.pi/N+theta)&#xD;&#xA;    plt.figure()&#xD;&#xA;    plt.axes().set_aspect('equal')&#xD;&#xA;    n_iter = 2 # number of iterations&#xD;&#xA;    pentagon (X, Y, n_iter)&#xD;&#xA;    figure = &quot;pentagons%d.png&quot; % n_iter&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(figure)&#xD;&#xA;    plt.show()&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;Any suggestions on how to fill in the missing pentagons in a simple way (e.g. keeping the recursive nature of the algorithm)? " ContentLicense="CC BY-SA 3.0" />
  <row Id="10965" PostHistoryTypeId="1" PostId="4682" RevisionGUID="2cfa6ba7-4703-47b7-b068-a7a32e52f807" CreationDate="2017-02-08T03:07:14.083" UserId="6023" Text="Fill the plane with pentagons as tightly as possible in a regular way" ContentLicense="CC BY-SA 3.0" />
  <row Id="10966" PostHistoryTypeId="3" PostId="4682" RevisionGUID="2cfa6ba7-4703-47b7-b068-a7a32e52f807" CreationDate="2017-02-08T03:07:14.083" UserId="6023" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10967" PostHistoryTypeId="2" PostId="4683" RevisionGUID="710ef41b-d24c-45a7-a141-c2539eea3639" CreationDate="2017-02-08T04:53:45.517" UserId="3003" Text="If you're trying to tile the plane with regular pentagons with no spacing, [that's not possible.](https://en.wikipedia.org/wiki/Pentagonal_tiling)&#xD;&#xA;&#xD;&#xA;&gt; A regular pentagonal tiling on the Euclidean plane is impossible because the internal angle of a regular pentagon, 108°, is not a divisor of 360°, the angle measure of a whole turn.&#xD;&#xA;&#xD;&#xA;From the same link, though, there are several non-regular pentagons you can use to tile it as shown in the above link. Additionally, you can do a [pentagonal/hexagonal tiling](https://en.wikipedia.org/wiki/Pentagonal_tiling#Pentagonal.2Fhexagonal_tessellation) of the plane.&#xD;&#xA;&#xD;&#xA;If I've misunderstood what you're trying to do, please clarify." ContentLicense="CC BY-SA 3.0" />
  <row Id="10968" PostHistoryTypeId="2" PostId="4684" RevisionGUID="5af7ccdb-7d55-4fdc-a373-495c2d2f228c" CreationDate="2017-02-08T13:33:28.823" UserId="6025" Text="I'm new to computer graphics.  I played around with OpenGL and now am trying out Vulkan.&#xD;&#xA;&#xD;&#xA;Basically what I want to do, in 2D is have an 800x800 window, and I want that to represent 800 meters by 800 meters.  Then I want a circle with a radius of 1 meter.&#xD;&#xA;&#xD;&#xA;I am going off of the Vulkan tutorial.  &#xD;&#xA;&#xD;&#xA;My data structure is this:&#xD;&#xA;&#xD;&#xA;    struct Vertex {&#xD;&#xA;        glm::vec2 pos;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I create my circle:&#xD;&#xA;&#xD;&#xA;    const int NUM_POINTS = 20;&#xD;&#xA;    uint32_t angle = 360/NUM_POINTS;&#xD;&#xA;    Vertex vertex;&#xD;&#xA;    std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;&#xD;&#xA;    for(uint32_t i=0; i &lt;= 360; i+=angle){&#xD;&#xA;      vertex.pos.x = cos(glm::radians(float(i)));&#xD;&#xA;      vertex.pos.y = sin(glm::radians(float(i)));&#xD;&#xA;      vertices.push_back(vertex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Something to do with the viewport:&#xD;&#xA;&#xD;&#xA;    VkViewport viewport = {};&#xD;&#xA;    viewport.x = 0.0f;&#xD;&#xA;    viewport.y = 0.0f;&#xD;&#xA;    viewport.width = (float) swapChainExtent.width;&#xD;&#xA;    viewport.height = (float) swapChainExtent.height;&#xD;&#xA;    viewport.minDepth = 0.0f;&#xD;&#xA;    viewport.maxDepth = 1.0f;&#xD;&#xA;&#xD;&#xA;viewport.width and viewport.height both equal 800.0f.&#xD;&#xA;&#xD;&#xA;Projection matrices:&#xD;&#xA;&#xD;&#xA;    struct UniformBufferObject{&#xD;&#xA;      glm::mat4 model;&#xD;&#xA;      glm::mat4 view;&#xD;&#xA;      glm::mat4 proj;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;projections:&#xD;&#xA;&#xD;&#xA;    ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;    ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 10.0f);&#xD;&#xA;    ubo.proj[1][1] *= -1;&#xD;&#xA;&#xD;&#xA;This shows the circle, but it's almost as big as the window and it's tilted 45° away from me.&#xD;&#xA;&#xD;&#xA;First of all, I don't understand why, if I make the first argument to glm::lookAt be glm::vec3(0.0f, 0.0f, 2.0f), I see nothing.  I mean the circle is in the x-y plane.  If I move in the z-direction, shouldn't I see it?&#xD;&#xA;&#xD;&#xA;Then I tried glu::ortho&#xD;&#xA;&#xD;&#xA;    ubo.proj = glm::ortho(0.0f, 800.0f, 800.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;But I still see nothing." ContentLicense="CC BY-SA 3.0" />
  <row Id="10969" PostHistoryTypeId="1" PostId="4684" RevisionGUID="5af7ccdb-7d55-4fdc-a373-495c2d2f228c" CreationDate="2017-02-08T13:33:28.823" UserId="6025" Text="understanding glm::perspective vs glm::ortho" ContentLicense="CC BY-SA 3.0" />
  <row Id="10970" PostHistoryTypeId="3" PostId="4684" RevisionGUID="5af7ccdb-7d55-4fdc-a373-495c2d2f228c" CreationDate="2017-02-08T13:33:28.823" UserId="6025" Text="|projections|vulkan|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10971" PostHistoryTypeId="2" PostId="4685" RevisionGUID="6e895552-5550-4d9a-a4e4-53f9ed0a1a5c" CreationDate="2017-02-08T16:47:44.643" UserId="2041" Text="&gt; I don't understand why, if I make the first argument to glm::lookAt be glm::vec3(0.0f, 0.0f, 2.0f), I see nothing.&#xD;&#xA;&#xD;&#xA;It's because of the *up* vector. If you think about the look-at operation, you specify where the camera is and what point it's looking towards. These two things alone leave one degree of freedom: the rotation around that axis. Which way is up on your screen? The third argument is for specifying that: it's a direction in world space which will correspond to *up* on the screen. If your first argument is that and the rest of the code is as your example, you're calling `lookAt((0,0,2), (0,0,0), (0,0,1))`. Your up vector points along the $z$-axis, which is the same direction the camera is looking (well, the opposite direction. This can't define which way is *up* on the screen. &#xD;&#xA;&#xD;&#xA;You probably want to pass a vector `(0,1,0)` as the third argument, which will make $y$ point up on your screen.&#xD;&#xA;&#xD;&#xA;If you're making a plan view of a 3D scene, then perspective projection is probably the right answer, but if all your content is going to be in the $z=0$ plane, then you probably want to use an orthographic rather than a perspective projection. Look at http://computergraphics.stackexchange.com/questions/2383/whats-the-difference-between-orthographic-and-perspective-projection to learn more about that.&#xD;&#xA;&#xD;&#xA;Last of all, remember that if you're projecting an $800m \times 800m$ scene onto $800 \times 800$ pixels, then a $1m$ radius circle will only be one pixel large. You probably need to scale up the size of your circle." ContentLicense="CC BY-SA 3.0" />
  <row Id="10972" PostHistoryTypeId="2" PostId="4686" RevisionGUID="ccc794ab-3d02-49f2-b811-d176bd966fe1" CreationDate="2017-02-08T20:36:37.163" UserId="6028" Text="I want to recreate this smoke/cloud effect which is used in the Arrival (2016) movie end credits.&#xD;&#xA;&#xD;&#xA;I uploaded a sped up version of the credits to see the smoke dynamics.&#xD;&#xA;&#xD;&#xA;[![thumbnail](https://i.stack.imgur.com/9eaAH.jpg)&#xD;&#xA;](http://streamable.com/n3309)&#xD;&#xA;&#xD;&#xA;*[http://streamable.com/n3309](http://streamable.com/n3309) 49s x6 sped up video of the credits*&#xD;&#xA;&#xD;&#xA;I know how shaders work and can comfortably implement simple GLSL fragment shaders, but looking at this I can't seem to find a way to get started.&#xD;&#xA;&#xD;&#xA;Starting points I considered:&#xD;&#xA;&#xD;&#xA; - *Using a noise function:* Every noise function I could find looks unnatural and unsmooth. Not what I need.&#xD;&#xA; - *Creating 2D/3D particle simulation:* This seems a bit overkill and even then I need functions that do not look calculated.&#xD;&#xA; - *Just use some sprites and transform them randomly around:* That's lame and still looks 'fake'.&#xD;&#xA;&#xD;&#xA;If you could guide me to a starting point on how to accomplish a somewhat similar looking GLSL shader implementation that would be great!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10973" PostHistoryTypeId="1" PostId="4686" RevisionGUID="ccc794ab-3d02-49f2-b811-d176bd966fe1" CreationDate="2017-02-08T20:36:37.163" UserId="6028" Text="Advice on how to create GLSL 2D soft smoke/cloud shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="10974" PostHistoryTypeId="3" PostId="4686" RevisionGUID="ccc794ab-3d02-49f2-b811-d176bd966fe1" CreationDate="2017-02-08T20:36:37.163" UserId="6028" Text="|shader|pixel-shader|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10975" PostHistoryTypeId="2" PostId="4687" RevisionGUID="2441431a-7dd0-4e66-8113-c84d29085f59" CreationDate="2017-02-08T23:45:46.797" UserId="506" Text="Noise functions are definitely your friend here—[FBM](https://code.google.com/archive/p/fractalterraingeneration/wikis/Fractional_Brownian_Motion.wiki) would be one good candidate. You’re right that it can look a too uniform on its own, but if you blend multiple layers of it together, using different speeds / directions for each and maybe distorting their domains a bit, you should be able to get very close to the look of that footage. There’s lots of clever uses of noise functions on [Shadertoy](https://www.shadertoy.com/results?query=tag=noise&amp;sort=popular); for an example of something like the approach described above, check out [this one](https://www.shadertoy.com/view/Mtd3W7).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="10976" PostHistoryTypeId="2" PostId="4688" RevisionGUID="ca525278-7fc0-4fc2-8b50-3f3ec8cfc0bc" CreationDate="2017-02-09T05:26:50.003" UserId="6001" Text="I know how to generate cosine weighted hemisphere samples, and I know how to generate stratified uniform samples, but I wanted to experiment with combining the two. However, how do I correctly stratify the hemisphere when performing the cosine weighted sampling? Do I cosine-weight the stratification? How many rays do I cast in each stratum? &#xD;&#xA;&#xD;&#xA;My application is the collection of indirect samples in a lightmapper." ContentLicense="CC BY-SA 3.0" />
  <row Id="10977" PostHistoryTypeId="1" PostId="4688" RevisionGUID="ca525278-7fc0-4fc2-8b50-3f3ec8cfc0bc" CreationDate="2017-02-09T05:26:50.003" UserId="6001" Text="Generation of stratified cosine weighted samples on hemisphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="10978" PostHistoryTypeId="3" PostId="4688" RevisionGUID="ca525278-7fc0-4fc2-8b50-3f3ec8cfc0bc" CreationDate="2017-02-09T05:26:50.003" UserId="6001" Text="|raytracing|global-illumination|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10979" PostHistoryTypeId="5" PostId="4688" RevisionGUID="fcc25179-6126-44c1-8727-2fc46ccf48dc" CreationDate="2017-02-09T05:35:03.333" UserId="6001" Comment="deleted 6 characters in body" Text="I have luck with cosine weighted hemisphere samples, and I know how to generate stratified uniform samples, but I wanted to experiment with combining the two. However, how do I correctly stratify the hemisphere when performing the cosine weighted sampling? Do I cosine-weight the stratification? How many rays do I cast in each stratum? &#xD;&#xA;&#xD;&#xA;My application is the collection of indirect samples in a lightmapper." ContentLicense="CC BY-SA 3.0" />
  <row Id="10980" PostHistoryTypeId="5" PostId="4688" RevisionGUID="2c508280-f83b-42a5-8410-532233be7406" CreationDate="2017-02-09T05:53:24.547" UserId="6001" Comment="added 4 characters in body" Text="I have had luck with cosine weighted hemisphere samples, and I know how to generate stratified uniform samples, but I wanted to experiment with combining the two. However, how do I correctly stratify the hemisphere when performing the cosine weighted sampling? Do I cosine-weight the stratification? How many rays do I cast in each stratum? &#xD;&#xA;&#xD;&#xA;My application is the collection of indirect samples in a lightmapper." ContentLicense="CC BY-SA 3.0" />
  <row Id="10981" PostHistoryTypeId="2" PostId="4689" RevisionGUID="501909fa-79d3-4240-832d-c4de05104cbc" CreationDate="2017-02-09T09:39:17.250" UserId="6029" Text="So I have a matrix:&#xD;&#xA;&#xD;&#xA;    Matrix4f Mbsp = Matrix4f(Vector4f(1.0, 4.0, 1.0, 0.0)&#xD;&#xA;                , Vector4f(-3.0, 0.0, 3.0, 0.0)&#xD;&#xA;                , Vector4f(3.0, -6.0, 3.0, 0.0)&#xD;&#xA;                , Vector4f(-1.0, 3.0, -3.0, 1.0), true);&#xD;&#xA;&#xD;&#xA;and I'm doing a scalar multiplication to it, e.g.:&#xD;&#xA;&#xD;&#xA;    Mbsp = (1.0/6.0)*Mbsp;&#xD;&#xA;&#xD;&#xA;One would now expect Mbsp to be&#xD;&#xA;&#xD;&#xA;$$\begin{array} &amp;1/6&amp;-1/2&amp;1/2&amp;-1/6\\2/3&amp;0&amp;-1&amp;1/2\\1/6&amp;1/2&amp;1/2&amp;-1/2\\ 0&amp;0&amp;0&amp;1/6 \end{array}$$&#xD;&#xA;&#xD;&#xA;However Mbsp now is:&#xD;&#xA;&#xD;&#xA;$$\begin{array} &amp;1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0\\1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0\\1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0&amp;\\ 1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0 \end{array}$$&#xD;&#xA;&#xD;&#xA;What's wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10982" PostHistoryTypeId="1" PostId="4689" RevisionGUID="501909fa-79d3-4240-832d-c4de05104cbc" CreationDate="2017-02-09T09:39:17.250" UserId="6029" Text="Scalar multiplication on Matrix4f results in strange values" ContentLicense="CC BY-SA 3.0" />
  <row Id="10983" PostHistoryTypeId="3" PostId="4689" RevisionGUID="501909fa-79d3-4240-832d-c4de05104cbc" CreationDate="2017-02-09T09:39:17.250" UserId="6029" Text="|opengl|bezier-curve|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10984" PostHistoryTypeId="5" PostId="4689" RevisionGUID="c73f3c79-7a84-4cd1-881d-83e6fc6a84f4" CreationDate="2017-02-09T09:44:29.943" UserId="6029" Comment="added 157 characters in body" Text="So I have a matrix:&#xD;&#xA;&#xD;&#xA;    Matrix4f Mbsp = Matrix4f(Vector4f(1.0, 4.0, 1.0, 0.0)&#xD;&#xA;                , Vector4f(-3.0, 0.0, 3.0, 0.0)&#xD;&#xA;                , Vector4f(3.0, -6.0, 3.0, 0.0)&#xD;&#xA;                , Vector4f(-1.0, 3.0, -3.0, 1.0), true);&#xD;&#xA;&#xD;&#xA;and I'm doing a scalar multiplication to it, e.g.:&#xD;&#xA;&#xD;&#xA;    Mbsp = (1.0/6.0)*Mbsp;&#xD;&#xA;&#xD;&#xA;One would now expect Mbsp to be&#xD;&#xA;&#xD;&#xA;$$\begin{array} &amp;1/6&amp;-1/2&amp;1/2&amp;-1/6\\2/3&amp;0&amp;-1&amp;1/2\\1/6&amp;1/2&amp;1/2&amp;-1/2\\ 0&amp;0&amp;0&amp;1/6 \end{array}$$&#xD;&#xA;&#xD;&#xA;However Mbsp now is:&#xD;&#xA;&#xD;&#xA;$$\begin{array} &amp;1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0\\1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0\\1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0&amp;\\ 1.0&amp;1.4901161e-008&amp;1.4901161e-008&amp;0 \end{array}$$&#xD;&#xA;&#xD;&#xA;Similarly, doing (using the original Mbsp): &#xD;&#xA;&#xD;&#xA;    Mbsp = 2.0*Mbsp;&#xD;&#xA;&#xD;&#xA;Gives&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\begin{array} &amp;12&amp;0&amp;0&amp;0\\12&amp;0&amp;0&amp;0\\12&amp;0&amp;0&amp;0\\ 12&amp;0&amp;0&amp;0 \end{array}$$&#xD;&#xA;&#xD;&#xA;What's wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="10985" PostHistoryTypeId="4" PostId="4689" RevisionGUID="f80ab974-f910-43de-92b7-e61a70c90cfa" CreationDate="2017-02-09T11:06:13.280" UserId="6029" Comment="edited title" Text="Scalar multiplication in vecmath on Matrix4f results in strange values" ContentLicense="CC BY-SA 3.0" />
  <row Id="10986" PostHistoryTypeId="2" PostId="4690" RevisionGUID="d5c52e97-3734-4d23-bd50-550ea2fc24ce" CreationDate="2017-02-09T11:14:46.130" UserId="2287" Text="I read the [mtl][1] specification for materials and noticed that the specular exponent **Ns** must be a scalar value instead of a spectrum. Would a specular exponent with three color channels (i.e. RGB, XYZ, ...) make sense (i.e. could *represent* (the specular exponent is of course not physically based at all) something *physically plausible*)?&#xD;&#xA;&#xD;&#xA;  [1]: http://paulbourke.net/dataformats/mtl/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10987" PostHistoryTypeId="1" PostId="4690" RevisionGUID="d5c52e97-3734-4d23-bd50-550ea2fc24ce" CreationDate="2017-02-09T11:14:46.130" UserId="2287" Text="Specular exponent spectrum" ContentLicense="CC BY-SA 3.0" />
  <row Id="10988" PostHistoryTypeId="3" PostId="4690" RevisionGUID="d5c52e97-3734-4d23-bd50-550ea2fc24ce" CreationDate="2017-02-09T11:14:46.130" UserId="2287" Text="|shading|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10989" PostHistoryTypeId="5" PostId="4690" RevisionGUID="8bcf9049-9e59-4938-bd3f-65b78bf34d6a" CreationDate="2017-02-09T11:22:39.530" UserId="2287" Comment="edited body" Text="I read the [MTL][1] specification for materials and noticed that the specular exponent **Ns** must be a scalar value instead of a spectrum. Would a specular exponent with three color channels (i.e. RGB, XYZ, ...) make sense (i.e. could *represent* (the specular exponent is of course not physically based at all) something *physically plausible*)?&#xD;&#xA;&#xD;&#xA;  [1]: http://paulbourke.net/dataformats/mtl/" ContentLicense="CC BY-SA 3.0" />
  <row Id="10990" PostHistoryTypeId="2" PostId="4691" RevisionGUID="0b84a3e2-b7b8-49da-ae96-b27b18227ed0" CreationDate="2017-02-09T12:50:50.153" UserId="5717" Text="The classic method is to uniformly sample the disc at the base of your hemisphere and to project your samples upwards on the hemisphere (eg. compute z from x and y). This yields a cosine weighted distribution." ContentLicense="CC BY-SA 3.0" />
  <row Id="10991" PostHistoryTypeId="2" PostId="4692" RevisionGUID="c3db6274-4a0b-4222-82be-342c2bc562c1" CreationDate="2017-02-09T13:05:42.390" UserId="6030" Text="in OpenCV there is functions to warp any 2D image using a homography matrix (3x3), e.g. `cv2.warpPerspective`. These matrices are generally constructed using point correspondences 2D-&gt;2D and solving for the matrix that maps the first set of points to the second, e.g. using `cv2.findHomography`.&#xD;&#xA;&#xD;&#xA;Now I'm wondering what the rotations and translations of the camera are, that lead to a homography. So if I rotate and translate the (virtual) camera (6 degrees of freedom) by given values - what does the matrix look like to project a 2D image to the version seen by the rotated and translated camera. I somehow feel that this can't be solved in 2D but I can't really tell why." ContentLicense="CC BY-SA 3.0" />
  <row Id="10992" PostHistoryTypeId="1" PostId="4692" RevisionGUID="c3db6274-4a0b-4222-82be-342c2bc562c1" CreationDate="2017-02-09T13:05:42.390" UserId="6030" Text="image warping, given the rotations/translations" ContentLicense="CC BY-SA 3.0" />
  <row Id="10993" PostHistoryTypeId="3" PostId="4692" RevisionGUID="c3db6274-4a0b-4222-82be-342c2bc562c1" CreationDate="2017-02-09T13:05:42.390" UserId="6030" Text="|image-processing|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="10994" PostHistoryTypeId="5" PostId="4691" RevisionGUID="fd6e9377-827d-4146-a51a-f3854ef33cb9" CreationDate="2017-02-09T13:55:36.607" UserId="5717" Comment="Clarified how stratification is achieved." Text="The classic method is to uniformly sample the disc at the base of your hemisphere and to project your samples upwards on the hemisphere (eg. compute z from x and y). This yields a cosine weighted distribution.&#xD;&#xA;&#xD;&#xA;As the projection preserves stratification, you need only use stratified sampling of the disc to get a stratified cosine distribution." ContentLicense="CC BY-SA 3.0" />
  <row Id="10995" PostHistoryTypeId="2" PostId="4693" RevisionGUID="8c20164c-9e36-4dac-a325-08e2d4c892bd" CreationDate="2017-02-09T15:15:01.967" UserId="2479" Text="More general answer:&#xD;&#xA;&#xD;&#xA;If you have a method for sampling the desired PDF (cosine weighted in your case) which takes uniformly distributed samples as its input, you just feed it with stratified uniformly distributed samples. That's it. The mapping of your sampling method should keep the strata separated.&#xD;&#xA;&#xD;&#xA;How many samples to use per strata is a different question. Usually you use just one per stratum and set the number of strata according to the total amount of needed samples per one Monte Carlo estimation. However, more samples per stratum should be doable too, you just need to make sure that each stratum gets the same amount of samples not to break uniformity of the (input) distribution." ContentLicense="CC BY-SA 3.0" />
  <row Id="10996" PostHistoryTypeId="2" PostId="4694" RevisionGUID="0d95b533-3884-4936-991f-eb8047e846f2" CreationDate="2017-02-09T15:35:00.203" UserId="2479" Text="Using independent settings for each colour channel is like using settings dependent on wavelength when doing spectral rendering. So the question could be re-formulated as:&#xD;&#xA;&#xD;&#xA;&gt; Is a material which changes its roughness with wavelengths physically plausible?&#xD;&#xA;&#xD;&#xA;With some kind of nano-fabrication process you could build a material surface using some microfacets reflecting certain parts of spectrum and distributing each type of microfacets in a different way. So not only it is physically plausible, but it is also physically realisable. On the other hand, you normally don't encounter such behaviour in &quot;common&quot; materials." ContentLicense="CC BY-SA 3.0" />
  <row Id="11000" PostHistoryTypeId="2" PostId="4696" RevisionGUID="90001113-871f-4dbf-bce0-ac45812a9882" CreationDate="2017-02-09T16:31:17.233" UserId="4958" Text="There is good glsl source of noise (simplex noise) [online][1] to make real time noise. In addition to this, to make effect of moving fog/smoke like in this video you can make 3D FBM function. This is my function:&#xD;&#xA;&#xD;&#xA;    float default3DFbm(vec3 P, float frequency, float lacunarity, int octaves, float addition)&#xD;&#xA;    {&#xD;&#xA;        float t = 0.0f;&#xD;&#xA;        float amplitude = 1.0;&#xD;&#xA;        float amplitudeSum = 0.0;&#xD;&#xA;        for(int k = 0; k &lt; octaves; ++k)&#xD;&#xA;        {&#xD;&#xA;            t += min(snoise(P * frequency)+addition, 1.0) * amplitude;&#xD;&#xA;            amplitudeSum += amplitude;&#xD;&#xA;            amplitude *= 0.5;&#xD;&#xA;            frequency *= lacunarity;&#xD;&#xA;        }&#xD;&#xA;        return t/amplitudeSum;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Where `snoise` is 3D noise function from link and `P` is used to seed noise, for example&#xD;&#xA;&#xD;&#xA;    P = vec3(texcoord, uniform_speed)&#xD;&#xA;&#xD;&#xA;Where `uniform_speed` is uniform variable incremented each frame with some value.&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ashima/webgl-noise/tree/master/src&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11001" PostHistoryTypeId="5" PostId="4693" RevisionGUID="1233e682-1a18-4930-a38f-ccbe536d4711" CreationDate="2017-02-09T16:51:18.067" UserId="2479" Comment="re-wording" Text="If you have a method for sampling the desired PDF (cosine weighted in your case) which takes uniformly distributed samples as its input, you just feed it with stratified uniformly distributed samples. That's it. The mapping of your sampling method should keep the strata separated.&#xD;&#xA;&#xD;&#xA;Usually you use just use one sample per stratum and set the number of strata according to the total amount of needed samples per one Monte Carlo estimation. More samples per stratum will somehow work too, you just need to make sure that each stratum gets the same amount of samples not to break uniformity of the (input) distribution. Keep in mind, however, that using more samples per stratum will degrade the performance of stratification due to sample clustering which usually happen for simple non-stratified random sampling." ContentLicense="CC BY-SA 3.0" />
  <row Id="11003" PostHistoryTypeId="5" PostId="4693" RevisionGUID="55ecf0f6-a3ba-432f-a31c-52a90d29ce1b" CreationDate="2017-02-09T22:05:56.967" UserId="2479" Comment="Re-formulation" Text="If you have a deterministic mapping function which transforms uniformly distributed samples into the desired PDF (cosine shaped in your case), just feed it directly with stratified uniformly distributed samples. The mapping will keep the strata separated.&#xD;&#xA;&#xD;&#xA;Usually one sample per stratum is used and the number of strata is set according to the total amount of needed samples per one Monte Carlo estimation. More samples per stratum will somehow work too, you just need to make sure that each stratum gets the same amount of samples not to break uniformity of the (input) distribution. Keep in mind, however, that using more samples per stratum will degrade the performance of the Monte Carlo estimator due to sample clustering which usually happen for simple non-stratified random sampling." ContentLicense="CC BY-SA 3.0" />
  <row Id="11007" PostHistoryTypeId="5" PostId="4693" RevisionGUID="e446c1f2-4b82-4b8b-b210-8501cd79433e" CreationDate="2017-02-09T23:03:16.517" UserId="2479" Comment="added detail" Text="If you have a deterministic mapping function which transforms uniformly distributed samples into the desired PDF (cosine shaped in your case), just feed it directly with stratified uniformly distributed samples. The mapping will keep the strata separated.&#xD;&#xA;&#xD;&#xA;Usually one sample per stratum is used and the number of strata is set according to the total amount of needed samples per one Monte Carlo estimation. More samples per stratum will somehow work too, you just need to make sure that each stratum gets the same amount of samples not to break uniformity of the (input) distribution. Keep in mind, however, that using more samples per stratum will degrade the per-sample performance of the Monte Carlo estimator due to sample clustering which usually happen for simple non-stratified random sampling." ContentLicense="CC BY-SA 3.0" />
  <row Id="11008" PostHistoryTypeId="2" PostId="4698" RevisionGUID="bccb84f6-33db-435f-bb5f-1690eee52c54" CreationDate="2017-02-09T23:49:34.187" UserId="6033" Text="I'm attempting to apply a height map to a ray-traced sphere. The height map is stored as a texture. I have the intersection point on the sphere $p$, and I compute the normal vector at that point $N = normalize(p - c)$, where $c$ is the center of the sphere.&#xD;&#xA;&#xD;&#xA;I then use the components of the normalized $N$ with a sqrt and a couple of atan2's to get texture coordinates $u$ and $v$ (which correspond to sphere longitude and latitude, respectively.)&#xD;&#xA;&#xD;&#xA;Unfortunately, I can't quite see how to get a perturbed normal from the height map. Here's what I have so far:&#xD;&#xA;&#xD;&#xA;$p^{'} = p + h(u,v) N$ is the sphere perturbed by the height map $h$ in the direction of the normalized normal $N$.&#xD;&#xA;&#xD;&#xA;The perturbed normal is then, by definition, $N^{'} = p^{'}_u \times p^{'}_v$.&#xD;&#xA;&#xD;&#xA;The first question I have is, how do I know that normal points to the outside of the sphere? (To light the sphere properly, I do need outward-pointing normals.)&#xD;&#xA;&#xD;&#xA;I know that, at worst, I can just run the shader and change the sign if it looks wrong, but I'd like to understand from first principles how I should order the cross product. I've looked around, and could not find any discussion of this point.&#xD;&#xA;&#xD;&#xA;Now, we can define the sphere as $p = c + N r$ with $c$ the center and $r$ the scalar radius. Substituting this into the perturbed height map equation, we get&#xD;&#xA;&#xD;&#xA;$p^{'} = c + N(r + h)$, which makes perfect sense: the radius is being perturbed by the height.&#xD;&#xA;&#xD;&#xA;Differentiating that, we get&#xD;&#xA;&#xD;&#xA;$p^{'}_u = N_u(r+h) + h_uN$ and $p^{'}_v = N_v(r+h) + h_vN$. &#xD;&#xA;&#xD;&#xA;Computing the cross product directly, we get&#xD;&#xA;&#xD;&#xA;$N^{'} = (N_u(r+h) + h_uN) \times (N_v(r+h) + h_vN)$&#xD;&#xA;&#xD;&#xA;$N^{'} = (r+h)^2(N_u \times N_v) + (r+h)(h_u(N \times N_v) + h_v(N_u \times N))$&#xD;&#xA;&#xD;&#xA;(because $N \times N = 0$.)&#xD;&#xA;&#xD;&#xA;The next question I have is that the sphere longitude is discontinuous ($u$ jumps from 1 to 0 as you cross the meridian); won't that cause the cross product to be computed incorrectly?&#xD;&#xA;&#xD;&#xA;The final problem is, I'm not seeing how to compute $N(u,v)$. I'm just hitting a blank here. ($h_u$ and $h_v$ are easy enough to compute; they're just the derivative of the texture.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11009" PostHistoryTypeId="1" PostId="4698" RevisionGUID="bccb84f6-33db-435f-bb5f-1690eee52c54" CreationDate="2017-02-09T23:49:34.187" UserId="6033" Text="Bump mapping a ray-traced sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="11010" PostHistoryTypeId="3" PostId="4698" RevisionGUID="bccb84f6-33db-435f-bb5f-1690eee52c54" CreationDate="2017-02-09T23:49:34.187" UserId="6033" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11011" PostHistoryTypeId="5" PostId="4698" RevisionGUID="30db8b76-0e7f-4da2-8c8a-5bee60cd1155" CreationDate="2017-02-10T00:09:59.913" UserId="6033" Comment="added 358 characters in body" Text="I'm attempting to apply a height map to a ray-traced sphere. The height map is stored as a texture. I have the intersection point on the sphere $p$, and I compute the normal vector at that point $N = normalize(p - c)$, where $c$ is the center of the sphere.&#xD;&#xA;&#xD;&#xA;I then use the components of the normalized $N$ with a sqrt and a couple of atan2's to get texture coordinates $u$ and $v$ (which correspond to sphere longitude and latitude, respectively.)&#xD;&#xA;&#xD;&#xA;Unfortunately, I can't quite see how to get a perturbed normal from the height map. Here's what I have so far:&#xD;&#xA;&#xD;&#xA;$p^{'} = p + h(u,v) N$ is the sphere perturbed by the height map $h$ in the direction of the normalized normal $N$.&#xD;&#xA;&#xD;&#xA;The perturbed normal is then, by definition, $N^{'} = p^{'}_u \times p^{'}_v$.&#xD;&#xA;&#xD;&#xA;The first question I have is, how do I know that normal points to the outside of the sphere? (To light the sphere properly, I do need outward-pointing normals.)&#xD;&#xA;&#xD;&#xA;I know that, at worst, I can just run the shader and change the sign if it looks wrong, but I'd like to understand from first principles how I should order the cross product. I've looked around, and could not find any discussion of this point.&#xD;&#xA;&#xD;&#xA;Now, we can define the sphere as $p = c + N r$ with $c$ the center and $r$ the scalar radius. Substituting this into the perturbed height map equation, we get&#xD;&#xA;&#xD;&#xA;$p^{'} = c + N(r + h)$, which makes perfect sense: the radius is being perturbed by the height.&#xD;&#xA;&#xD;&#xA;Differentiating that, we get&#xD;&#xA;&#xD;&#xA;$p^{'}_u = N_u(r+h) + h_uN$ and $p^{'}_v = N_v(r+h) + h_vN$. &#xD;&#xA;&#xD;&#xA;Computing the cross product directly, we get&#xD;&#xA;&#xD;&#xA;$N^{'} = (N_u(r+h) + h_uN) \times (N_v(r+h) + h_vN)$&#xD;&#xA;&#xD;&#xA;$N^{'} = (r+h)^2(N_u \times N_v) + (r+h)(h_u(N \times N_v) + h_v(N_u \times N))$&#xD;&#xA;&#xD;&#xA;(because $N \times N = 0$.)&#xD;&#xA;&#xD;&#xA;The next question I have is that the sphere longitude is discontinuous ($u$ jumps from 1 to 0 as you cross the meridian); won't that cause the cross product to be computed incorrectly?&#xD;&#xA;&#xD;&#xA;The final problem is, I'm not seeing how to compute $N(u,v)$. I'm just hitting a blank here. ($h_u$ and $h_v$ are easy enough to compute; they're just the derivative of the texture.)&#xD;&#xA;&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;Boy do I feel stupid. I just use spherical to cartesian to get a point on the sphere as a function of $u$ and $v$. And that is precisely the function $N(u,v)$. D'oh.&#xD;&#xA;&#xD;&#xA;I still have my first question pending, and I'll see if there are any problems with singularities after I compute the derivative of $N$ (I suspect there will be no issues.)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11012" PostHistoryTypeId="2" PostId="4699" RevisionGUID="08682973-a76c-42bf-b125-d9e9af018dcd" CreationDate="2017-02-10T01:46:04.253" UserId="6001" Text="I have a working light mapper that captures global illumination. I evaluate a hemisphere when collecting the data and store the result in the texel. However, I want to support directional lightmaps so that I can more realistically light normal maps at runtime. What strategies are there to adapt my light mapper's final gather operation to capture this data? Is it as simple as performing three hemisphere samples per texel in orthogonal directions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11013" PostHistoryTypeId="1" PostId="4699" RevisionGUID="08682973-a76c-42bf-b125-d9e9af018dcd" CreationDate="2017-02-10T01:46:04.253" UserId="6001" Text="How to adapt diffuse/GI light mapper to directional light maps?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11014" PostHistoryTypeId="3" PostId="4699" RevisionGUID="08682973-a76c-42bf-b125-d9e9af018dcd" CreationDate="2017-02-10T01:46:04.253" UserId="6001" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11015" PostHistoryTypeId="5" PostId="4698" RevisionGUID="50c5ba9f-3c61-4267-bef2-59647ab29224" CreationDate="2017-02-10T02:51:49.833" UserId="6033" Comment="added 229 characters in body" Text="I'm attempting to apply a height map to a ray-traced sphere. The height map is stored as a texture. I have the intersection point on the sphere $p$, and I compute the normal vector at that point $N = normalize(p - c)$, where $c$ is the center of the sphere.&#xD;&#xA;&#xD;&#xA;I then use the components of the normalized $N$ with a sqrt and a couple of atan2's to get texture coordinates $u$ and $v$ (which correspond to sphere longitude and latitude, respectively.)&#xD;&#xA;&#xD;&#xA;Unfortunately, I can't quite see how to get a perturbed normal from the height map. Here's what I have so far:&#xD;&#xA;&#xD;&#xA;$p^{'} = p + h(u,v) N$ is the sphere perturbed by the height map $h$ in the direction of the normalized normal $N$.&#xD;&#xA;&#xD;&#xA;The perturbed normal is then, by definition, $N^{'} = p^{'}_u \times p^{'}_v$.&#xD;&#xA;&#xD;&#xA;The first question I have is, how do I know that normal points to the outside of the sphere? (To light the sphere properly, I do need outward-pointing normals.)&#xD;&#xA;&#xD;&#xA;I know that, at worst, I can just run the shader and change the sign if it looks wrong, but I'd like to understand from first principles how I should order the cross product. I've looked around, and could not find any discussion of this point.&#xD;&#xA;&#xD;&#xA;Now, we can define the sphere as $p = c + N r$ with $c$ the center and $r$ the scalar radius. Substituting this into the perturbed height map equation, we get&#xD;&#xA;&#xD;&#xA;$p^{'} = c + N(r + h)$, which makes perfect sense: the radius is being perturbed by the height.&#xD;&#xA;&#xD;&#xA;Differentiating that, we get&#xD;&#xA;&#xD;&#xA;$p^{'}_u = N_u(r+h) + h_uN$ and $p^{'}_v = N_v(r+h) + h_vN$. &#xD;&#xA;&#xD;&#xA;Computing the cross product directly, we get&#xD;&#xA;&#xD;&#xA;$N^{'} = (N_u(r+h) + h_uN) \times (N_v(r+h) + h_vN)$&#xD;&#xA;&#xD;&#xA;$N^{'} = (r+h)^2(N_u \times N_v) + (r+h)(h_u(N \times N_v) + h_v(N_u \times N))$&#xD;&#xA;&#xD;&#xA;$N^{'} = (r+h)(N_u \times N_v) + h_u(N \times N_v) + h_v(N_u \times N)$&#xD;&#xA;&#xD;&#xA;$N^{'} = (r+h)N + h_u(N \times N_v) + h_v(N_u \times N)$&#xD;&#xA;&#xD;&#xA;(because $N \times N = 0$, the common factor $(r+h)$ will drop out from the normalized vector, and $N = N_u \times N_v$.)&#xD;&#xA;&#xD;&#xA;The next question I have is that the sphere longitude is discontinuous ($u$ jumps from 1 to 0 as you cross the meridian); won't that cause the cross product to be computed incorrectly?&#xD;&#xA;&#xD;&#xA;The final problem is, I'm not seeing how to compute $N(u,v)$. I'm just hitting a blank here. ($h_u$ and $h_v$ are easy enough to compute; they're just the derivative of the texture.)&#xD;&#xA;&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;Boy do I feel stupid. I just use spherical to cartesian to get a point on the sphere as a function of $u$ and $v$. And that is precisely the function $N(u,v)$. D'oh.&#xD;&#xA;&#xD;&#xA;I still have my first question pending, and I'll see if there are any problems with singularities after I compute the derivative of $N$ (I suspect there will be no issues.)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11019" PostHistoryTypeId="6" PostId="4664" RevisionGUID="73a59886-ad1f-4681-996b-05173d7502c9" CreationDate="2017-02-10T13:21:11.203" UserId="2479" Comment="Added tag importance-sampling" Text="|raytracing|sampling|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11020" PostHistoryTypeId="24" PostId="4664" RevisionGUID="73a59886-ad1f-4681-996b-05173d7502c9" CreationDate="2017-02-10T13:21:11.203" Comment="Proposed by 2479 approved by 209, 100 edit id of 197" ContentLicense="CC BY-SA 3.0" />
  <row Id="11022" PostHistoryTypeId="2" PostId="4700" RevisionGUID="945a1328-5b20-413e-b327-ea57dfb3285a" CreationDate="2017-02-10T15:40:13.627" UserId="6040" Text="The technic what Benedikt mentioned&#xD;&#xA;is explained in Section 2.4.1 of this thesis.&#xD;&#xA;&#xD;&#xA;http://www.cmlab.csie.ntu.edu.tw/~ming/courses/icg/Reference/Real_time_water_rendering_pj14.pdf&#xD;&#xA;&#xD;&#xA;Implementing this should solve your problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="11023" PostHistoryTypeId="50" PostId="4503" RevisionGUID="9956557c-573d-401c-87d8-220cf3f8bcd9" CreationDate="2017-02-10T15:43:34.500" UserId="-1" />
  <row Id="11024" PostHistoryTypeId="2" PostId="4701" RevisionGUID="550adeea-1067-4301-ba00-2c61faa12a77" CreationDate="2017-02-10T16:15:16.373" UserId="6041" Text="How is sun modelled for ray tracing rendering? Is it part of the scene, like a&#xD;&#xA;sphere with a centre in some far location or it is just considered as a point?&#xD;&#xA;&#xD;&#xA;Also regarding sending shadow rays to the sun, is it, again, sampling a sphere&#xD;&#xA;or just sending shadow rays to one point?&#xD;&#xA;&#xD;&#xA;Thanks," ContentLicense="CC BY-SA 3.0" />
  <row Id="11025" PostHistoryTypeId="1" PostId="4701" RevisionGUID="550adeea-1067-4301-ba00-2c61faa12a77" CreationDate="2017-02-10T16:15:16.373" UserId="6041" Text="Sending shadow rays to sun" ContentLicense="CC BY-SA 3.0" />
  <row Id="11026" PostHistoryTypeId="3" PostId="4701" RevisionGUID="550adeea-1067-4301-ba00-2c61faa12a77" CreationDate="2017-02-10T16:15:16.373" UserId="6041" Text="|raytracing|shadow|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11027" PostHistoryTypeId="2" PostId="4702" RevisionGUID="925b6da0-fa87-42af-9d4a-90e448bfd42a" CreationDate="2017-02-10T17:16:32.643" UserId="137" Text="Sunlight is typically modeled as a directional light. All rays point the same direction off into infinity. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11029" PostHistoryTypeId="5" PostId="4699" RevisionGUID="c3b82880-3045-4adb-bf18-221cb61d04a1" CreationDate="2017-02-10T20:21:17.290" UserId="6001" Comment="added 98 characters in body" Text="I have a working light mapper that captures global illumination. I evaluate a hemisphere when collecting the data and store the result in the texel. However, I want to support directional lightmaps so that I can more realistically light normal maps at runtime. What strategies are there to adapt my light mapper's final gather operation to capture this data? Is it as simple as performing three hemisphere samples per texel in orthogonal directions? Or should I uniformly sample the hemisphere once, and project the results onto the basis vectors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11030" PostHistoryTypeId="5" PostId="4699" RevisionGUID="0723ba44-de90-46b7-855b-3f112d9a8d5e" CreationDate="2017-02-10T21:43:41.400" UserId="6001" Comment="added 131 characters in body" Text="I have a working light mapper that captures global illumination. I evaluate a hemisphere when collecting the data and store the result in the texel. However, I want to support directional lightmaps so that I can more realistically light normal maps at runtime. What strategies are there to adapt my light mapper's final gather operation to capture this data? Is it as simple as performing three hemisphere samples per texel in orthogonal directions? Or should I uniformly sample the hemisphere once, and project the results onto the basis vectors?&#xD;&#xA;&#xD;&#xA;I've done some tests with the latter, but I'm not quite sure how to calculate the PDF for the projected colours on the vectors." ContentLicense="CC BY-SA 3.0" />
  <row Id="11031" PostHistoryTypeId="2" PostId="4703" RevisionGUID="8fc0b997-5ec1-42b4-ac0d-bebc16347a74" CreationDate="2017-02-11T08:20:36.757" UserId="6044" Text="I have a 3D triangular mesh representing cortical surface of a brain. I also have one vertex of interest. I would like to unfold a neighborhood of this vertex in such a way that both the angles and distances of paths from this vertex are preserved as much as possible.&#xD;&#xA;&#xD;&#xA;I read some reviews on mesh parameterization techniques (eg. [this](http://people.eecs.berkeley.edu/~jrs/meshpapers/ShefferPraunRose.pdf) one by Scheffer et al.). My understanding is that all the algorithms try to preserve a certain property (angle, distance, area) or a combination of those properties for all of the vertices or faces. In my case I need to preserve angles and distance of paths going from only one point. My intuition tells me that what I need should be quite simple because I demand much less from the output than all those parameterization algorithms. Yet I cannot come up with the solution. Any help is greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="11032" PostHistoryTypeId="1" PostId="4703" RevisionGUID="8fc0b997-5ec1-42b4-ac0d-bebc16347a74" CreationDate="2017-02-11T08:20:36.757" UserId="6044" Text="Algorithm to map a triangular mesh onto plane preserving angles and distances from one vertex" ContentLicense="CC BY-SA 3.0" />
  <row Id="11033" PostHistoryTypeId="3" PostId="4703" RevisionGUID="8fc0b997-5ec1-42b4-ac0d-bebc16347a74" CreationDate="2017-02-11T08:20:36.757" UserId="6044" Text="|mesh|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11034" PostHistoryTypeId="2" PostId="4704" RevisionGUID="712d2f74-0435-4988-b167-e9fc490850e8" CreationDate="2017-02-11T15:17:23.673" UserId="1608" Text="To just make a more precise answer.&#xD;&#xA;&#xD;&#xA;1. Sun light can be represented as a distant light. Light sources are radial light a bulb though in the case of the sun, the sol is so far away from the Earth, that a reasonable approximation is to consider that all rays coming out of the sun are parallel at the Earth's surface. Using a distant light is an approximation. Because it's far away it is also assumed that there is no variation of light intensity as you go up or down (change height).&#xD;&#xA;&#xD;&#xA;2. If you do physically based rendering, the sun is an area light. From the Earth it looks like a small disk so you can approximation this with a small disk that is far far away. Area light like all light sources obey a light intensity square fall off. So you will need to put your area light far away so that the intensity on the ground or as you change height doesn't carry much. Representing the sun as an area right avoid having to do strange things to the surface shader such as specifying a specular size." ContentLicense="CC BY-SA 3.0" />
  <row Id="11037" PostHistoryTypeId="2" PostId="4706" RevisionGUID="b6ca2d86-412f-4f99-a959-2418d37af2dc" CreationDate="2017-02-11T17:21:45.813" UserId="6047" Text="I too could not see my GPU through clinfo.&#xD;&#xA;&#xD;&#xA;The fix for me was disabling Secure Boot in the BIOS which did not let the Ubuntu kernel load DKMS code. There was even a ncurses warning after installing the driver, in my case AMDGPU PRO 16.60 on Ubuntu 16.10.&#xD;&#xA;&#xD;&#xA;I hope this helps!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11038" PostHistoryTypeId="2" PostId="4707" RevisionGUID="306ad67e-2d97-4d41-8b14-f3d6f9c995ef" CreationDate="2017-02-11T17:43:46.127" UserId="6046" Text="What others said. Sun is modelled as a directional light, i.e. the direction of light is independent of the intersection point as it's very far away. So you just define a point in space and that itself is the &quot;direction towards the light source&quot;. If you want the direction of light rays towards the objects you gotta negate that.&#xD;&#xA;&#xD;&#xA;Coming to your second part. For shadow rays, you need to send a ray from the point of intersection towards the light source, since it's the sun in your case, the direction is just the location of the sun. Do note that the origin of the ray is not `intersection point` rather it's `intersection point + epsilon` where epsilon is a very small value (say 0.001) in order to avoid intersection of the ray with the object it generated from.&#xD;&#xA;&#xD;&#xA;After that you check for intersection of objects with this shadow ray. You don't need to compute the intersection points, you just need to know whether the ray intersected with an object or not. If it did you set the pixel color to just the ambient color." ContentLicense="CC BY-SA 3.0" />
  <row Id="11039" PostHistoryTypeId="2" PostId="4708" RevisionGUID="f4eff79e-b1fb-410d-902f-611b22ced23a" CreationDate="2017-02-11T18:18:43.907" UserId="6046" Text="Different rendering systems have different definitions for screen space i guess. According to Renderman Screen Space means coordinates in the range [-1,1] where as other systems such as OpenGL thinks of it as Pixel coordinates ranging from 0 or 1 to the width/height of the actual screen.&#xD;&#xA;&#xD;&#xA;In CG, before converting all the points to the actual pixel coordinates i.e where they are projected on the screen, we usually normalize all the points in the range [0,1] or [-1,1]. This is known as the Normalized device coordinates. It's done because it's easier to scale it back to screen size that may vary and it's usually easier to perform other calculation in this range.&#xD;&#xA;&#xD;&#xA;I think the coder there was just trying to do that.&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      // horizontal window dimension [-X,X]&#xD;&#xA;      double X = tan(alpha/2.0);&#xD;&#xA;&#xD;&#xA;according to him the horizontal window ranges from -X to X. Since alpha was PI/2 or 90 degrees. tan(alpha/2) comes out 1. So X is in the range -1,1. &#xD;&#xA;&#xD;&#xA;     // pixel size&#xD;&#xA;      double s = 2.0 * X / (double)w;&#xD;&#xA;    &#xD;&#xA;      // vertical window dimension [-Y,Y]&#xD;&#xA;      double Y = s * h / 2.0;&#xD;&#xA;      ...&#xD;&#xA;&#xD;&#xA;Dunno about the fancy stuff but here the Y range has been mapped to `[-a,a]` where `a` is the aspect ratio. which is `width/height` or `height/width`. You can see that clearly if you substitue the value of &quot;s&quot; in the final equation. You'll get&#xD;&#xA;&#xD;&#xA;    double Y = 2 * X * h / (2 * w)&#xD;&#xA;    Y = h/w    // X = 1&#xD;&#xA;&#xD;&#xA;The mapping to [-a,a] is done because our screen is not always a square. Its usually a rectangle. You can fix the Y values in [-1,1] and let X be in the range [-a, a] as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="11040" PostHistoryTypeId="5" PostId="4708" RevisionGUID="7a339278-a259-49b6-a758-da40cafcfa13" CreationDate="2017-02-11T18:24:33.900" UserId="6046" Comment="added 85 characters in body" Text="Just leaving my opinion here in case someone else comes searching for the answer.&#xD;&#xA;&#xD;&#xA;Different rendering systems have different definitions for screen space i guess. According to Renderman Screen Space means coordinates in the range [-1,1] where as other systems such as OpenGL thinks of it as Pixel coordinates ranging from 0 or 1 to the width/height of the actual screen.&#xD;&#xA;&#xD;&#xA;In CG, before converting all the points to the actual pixel coordinates i.e where they are projected on the screen, we usually normalize all the points in the range [0,1] or [-1,1]. This is known as the Normalized device coordinates. It's done because it's easier to scale it back to screen size that may vary and it's usually easier to perform other calculation in this range.&#xD;&#xA;&#xD;&#xA;I think the coder there was just trying to do that.&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      // horizontal window dimension [-X,X]&#xD;&#xA;      double X = tan(alpha/2.0);&#xD;&#xA;&#xD;&#xA;according to him the horizontal window ranges from -X to X. Since alpha was PI/2 or 90 degrees. tan(alpha/2) comes out 1. So X is in the range -1,1. &#xD;&#xA;&#xD;&#xA;     // pixel size&#xD;&#xA;      double s = 2.0 * X / (double)w;&#xD;&#xA;    &#xD;&#xA;      // vertical window dimension [-Y,Y]&#xD;&#xA;      double Y = s * h / 2.0;&#xD;&#xA;      ...&#xD;&#xA;&#xD;&#xA;Dunno about the fancy stuff but here the Y range has been mapped to `[-a,a]` where `a` is the aspect ratio. which is `width/height` or `height/width`. You can see that clearly if you substitue the value of &quot;s&quot; in the final equation. You'll get&#xD;&#xA;&#xD;&#xA;    double Y = 2 * X * h / (2 * w)&#xD;&#xA;    Y = h/w    // X = 1&#xD;&#xA;&#xD;&#xA;The mapping to [-a,a] is done because our screen is not always a square. Its usually a rectangle. You can fix the Y values in [-1,1] and let X be in the range [-a, a] as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="11041" PostHistoryTypeId="2" PostId="4709" RevisionGUID="e61104d5-4439-44e2-be80-45431bb2a96e" CreationDate="2017-02-11T18:43:13.620" UserId="6046" Text="So i am currently making a Ray-tracer as a personal project. My lighting equation looks like this&#xD;&#xA;&#xD;&#xA;    Pixel_color[i] = 255 * (Ma*Ig*Ca + Md*I*Cd * diffuse  + Ms*I*Cs * glossy)&#xD;&#xA;    // M = material color (ambient, diffuse and specular)&#xD;&#xA;    // I = intensity of light (Ig is the global ambient intensity)&#xD;&#xA;    // C = color of the light (ambient , diffuse and specular)&#xD;&#xA;&#xD;&#xA;Here `diffuse` and `glossy` contains all the necessary dot products and the normalization factors ( PI for diffuse and n+8/8*PI for blinn phong). Also everything is in range 0-1. I've read from some books and it says to make sure that `&quot;Ks + Kd&quot; &lt;= 1` And now i am confused. &#xD;&#xA;&#xD;&#xA;1) What exactly is Ks and Kd? Is it just my surface diffuse color and specular color divided by 255 to make it in the range 0-1? Or is it the reflectance ratio that i have to multiply with my color? If it's something else then what should i set them to? For example if i have a color `rgb(66, 170, 244)` which is somewhat light blue. What should the Ks and Kd be for the above color?&#xD;&#xA;&#xD;&#xA;2) These books don't include the ambient component when talking about this conservation so should it be  Ka+Kd+Ks &lt;= 1? Again if that's the case what will Ka be?&#xD;&#xA;&#xD;&#xA;3) If i consider Ks = Ms and Kd = Md. It doesn't fit out. for example if i want a surface with the above color `rgb(66, 170, 244)` to be shiny and the specular highlight should be white. Then my Ms would be (255-66, 255-170, 255-244) which won't be white. Another way i could do is subtract the maximum from every component Ms(255-244, 255-244, 255-244). But this means the specular color would be very low. What if i wanted a very shiny surface?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11042" PostHistoryTypeId="1" PostId="4709" RevisionGUID="e61104d5-4439-44e2-be80-45431bb2a96e" CreationDate="2017-02-11T18:43:13.620" UserId="6046" Text="Energy Conservation in Lighting equation" ContentLicense="CC BY-SA 3.0" />
  <row Id="11043" PostHistoryTypeId="3" PostId="4709" RevisionGUID="e61104d5-4439-44e2-be80-45431bb2a96e" CreationDate="2017-02-11T18:43:13.620" UserId="6046" Text="|raytracing|lighting|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11044" PostHistoryTypeId="5" PostId="4701" RevisionGUID="d8007a2d-9ff5-4434-8745-65d96c8d14c7" CreationDate="2017-02-11T20:34:29.563" UserId="231" Comment="Minor typo and remove &quot;Thanks&quot;" Text="How is sun modelled for ray tracing rendering? Is it part of the scene, like a&#xD;&#xA;sphere with a centre in some far location or it is just considered as a point?&#xD;&#xA;&#xD;&#xA;Also regarding sending shadow rays to the sun, is it, again, sampling a sphere&#xD;&#xA;or just sending shadow rays to one point?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11045" PostHistoryTypeId="4" PostId="4701" RevisionGUID="d8007a2d-9ff5-4434-8745-65d96c8d14c7" CreationDate="2017-02-11T20:34:29.563" UserId="231" Comment="Minor typo and remove &quot;Thanks&quot;" Text="Sending shadow rays to the sun" ContentLicense="CC BY-SA 3.0" />
  <row Id="11046" PostHistoryTypeId="5" PostId="4704" RevisionGUID="d53f9057-07e7-4482-b59f-197673ac120a" CreationDate="2017-02-11T23:30:45.983" UserId="231" Comment="Remove intro that is redundant with further answers, plus minor typos" Text="1. Sun light can be represented as a distant light. Light sources are radial like a bulb, though in the case of the sun, it is so far away from the Earth, that a reasonable approximation is to consider that all rays coming out of the sun are parallel at the Earth's surface. Using a distant light is an approximation. Because it's far away it is also assumed that there is no variation of light intensity as you go up or down (change height).&#xD;&#xA;&#xD;&#xA;2. If you do physically based rendering, the sun is an area light. From the Earth it looks like a small disk so you can approximate this with a large disk that is far far away. Area light like all light sources obeys a light intensity square fall off. So you will need to put your area light far away so that the intensity on the ground or as you change height doesn't vary much. Representing the sun as an area light avoids having to do strange things to the surface shader such as specifying a specular size." ContentLicense="CC BY-SA 3.0" />
  <row Id="11047" PostHistoryTypeId="5" PostId="4668" RevisionGUID="7d735dfe-a407-4756-9fe0-465851ceb003" CreationDate="2017-02-12T03:00:55.387" UserId="6003" Comment="Minor clarification comments" Text="I'm familiar with the &quot;look-at&quot; matrix and the goal of being able to rotate a `Camera` at a specific location towards a specified target.&#xD;&#xA;&#xD;&#xA;When I tell the `Camera` to look at some target, there're no issues. However, when some other non-`Camera` object needs to &quot;look-at&quot; another object, such as a hypothetical `Dog` looking at some `Food`, so that the `Dog` &quot;points&quot; in its direction, it doesn't work as expected. In this case, when the look-at matrix used for the `Camera` is used (without modification) for the `Dog`, the `Dog` ends up looking in the *opposite* direction I intended it to face.&#xD;&#xA;&#xD;&#xA;What follows is the code I've been using to build my look-at matrix:&#xD;&#xA;&#xD;&#xA;    public static Matrix4 createLookAtMatrix(&#xD;&#xA;        Vector4 eyePosition,&#xD;&#xA;        Vector4 targetPosition,&#xD;&#xA;        Vector4 upDirection)&#xD;&#xA;    {&#xD;&#xA;        // forward, side, up&#xD;&#xA;        // &#xD;&#xA;        // f = normalize(targetPosition - eyePosition);&#xD;&#xA;        // s = normalize(f × normalize(upDirection));&#xD;&#xA;        // u = s × f;&#xD;&#xA;        Vector4 f = targetPosition.sub(eyePosition).normalize();&#xD;&#xA;        Vector4 s = f.cross(upDirection.normalize()).normalize();&#xD;&#xA;        Vector4 u = s.cross(f);&#xD;&#xA;&#xD;&#xA;        float[][] values = new float[][] {&#xD;&#xA;            { s.x(),  s.y(),  s.z(), -s.dot(eyePosition) }, // row 0&#xD;&#xA;            { u.x(),  u.y(),  u.z(), -u.dot(eyePosition) }, // row 1&#xD;&#xA;            {-f.x(), -f.y(), -f.z(), -f.dot(eyePosition) }, // row 2&#xD;&#xA;            { 0f   ,  0f   ,  0f   ,  1f                 }  // row 3&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        return createFrom(values);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What am I missing? Is there a way to build such a &quot;look-at&quot; matrix so that it works for both regardless of who/what the viewer is (i.e. `Camera` or `Dog`)?&#xD;&#xA;&#xD;&#xA;I'd like to avoid depending on &quot;special corner cases&quot; to detect what kind of object is trying to &quot;look-at&quot; something else, and so on.&#xD;&#xA;&#xD;&#xA;My system can have multiple `SceneObject`s at any given moment connected to the same `SceneNode` (`SceneNode`s are the objects that actually contain the transforms) and I *really* need a way to build a &quot;look-at&quot; matrix that will work regardless of which kind of object happens to get attached to the `SceneNode`.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;This is a screenshot of the reference book I was reading/using when writing my code above:&#xD;&#xA;&#xD;&#xA; [![The Look-At Matrix][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LV0gi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11049" PostHistoryTypeId="2" PostId="4710" RevisionGUID="b0c7dcbf-3051-4957-a349-ee9d23d2cefa" CreationDate="2017-02-12T08:42:13.213" UserId="1608" Text="Comment: if you make references to book, then it would be good if you could provide references.&#xD;&#xA;&#xD;&#xA;To answer your questions:&#xD;&#xA;&#xD;&#xA;1. First, it is quite unusual these days to see people representing colors using a computer byte that is integer values within the range [0:255]. Most people these days use floats, and you will understand why in a moment. When you look at a material in general you can see a shiny part and a diffuse part. Shininess and diffuse appearance are computed using two different types of equation. Let's call the functions that compute the diffuse part `diffuse()` and the function that compute the specular component `specular()`. So now you can write:&#xD;&#xA;&#xD;&#xA;    ObjectColor = Ks * specular() + Kd * diffuse();&#xD;&#xA;&#xD;&#xA;`Ks` and `Kd` control how shiny or/and diffuse your object is. &#xD;&#xA;&#xD;&#xA;About conservation of energy. In short an object can not reflect more light that it receives. So that means that technically if the specular() and diffuse() function do the right thing `Ks + Kd` ought to be `1`. If that wasn't true you would violate the principle of conservation of energy. In practice, it is generally good to follow this rule though most of the basic shading models are based on simple diffuse and specular models (for example the Phong model) and are not themselves energy conserving, so trying to be purely energy conserving at this level, is like trying to say you can paint a miniature with a paint roller. Forget about it, just try to be more or less in the right range.&#xD;&#xA;&#xD;&#xA;`ks` and `kd` generally stand for the specular and diffuse coefficients.&#xD;&#xA;&#xD;&#xA;2. if you don't do path tracing (aka don't simulate global illumination) the object won't reflect light from other objects in the scene, just light from direct light sources. So in the old time, in order to compensate for that, they would add an ambient term. In these days in age, this is considered as 'heresy'. Though if you account for the ambient term still then Ka + Kd + Ks should be again equal to 1 (same principle).&#xD;&#xA;&#xD;&#xA;3. Not sure to understand what you say here but all these components are additive. You compute the diffuse multiplied by Kd and then you multiply the specular multiplied by Ks and then you add the two resulting numbers together. And that's your object color at the intersection point.&#xD;&#xA;&#xD;&#xA;For an introduction to these topics I recommend you read:&#xD;&#xA;&#xD;&#xA;[Introduction Ray-Tracing][1]&#xD;&#xA;&#xD;&#xA;[Introduction to Shading][2]&#xD;&#xA;&#xD;&#xA;[The Phong Model][3]&#xD;&#xA;&#xD;&#xA;In order for you to progress, I personally recommend you proceed by step and don't try to understand everything at once. The problem of rendering and shading is very complex. You need to first understand the principle of light-matter interactions, what is diffuse what is specular and how are objects illuminated (direct and indirect lighting). Once you have these notions you can jump onto shading and understand or learn about the concept of shading model, and what the flaws and strengths of existing shading models (many of them exist).&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-ray-tracing&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading&#xD;&#xA;  [3]: https://www.scratchapixel.com/lessons/3d-basic-rendering/phong-shader-BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="11050" PostHistoryTypeId="2" PostId="4711" RevisionGUID="9178a059-c338-475d-b6b5-f5384151ff8d" CreationDate="2017-02-12T09:08:25.593" UserId="1608" Text="You have two issues at stake here:&#xD;&#xA;&#xD;&#xA;1. What conventions are used in the particular program you use (or use as a template). The meaning that people gave to certain words within the context of your program.&#xD;&#xA;&#xD;&#xA;2. The meaning of the terms 'screen coordinate' and 'window coordinates' in the Computer Graphics world. In the CG world, these terms have very precise meaning which do not necessarily correspond to meaning they have in the context of your program. &#xD;&#xA;&#xD;&#xA;So does your question related to &quot;what do these terms mean in the context of my program&quot; or &quot;what do they mean in CG&quot;? It seems like your more interested in the former.&#xD;&#xA;&#xD;&#xA;Let's try to reconcile the two questions:&#xD;&#xA;&#xD;&#xA;1. When you render a CG image you use a virtual camera. The image plane of that camera exists in the virtual world (thing of it as a rectangle if the image resolution width != than the image resolution height what we call the image aspect ratio), and has the same coordinates than all the objects that are in your scene. Think of this camera as a pyramid whose apex is the eye position and the base of the pyramid the image plane. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Imagine that the image plane (the base of the pyramid) is 1 unit away from the apex. By changing the size of this image plane which you do by changing the field-of-view angle as shown in the image above, you can control how much of the scene you see (this equivalent in photography to zooming in or out).&#xD;&#xA;&#xD;&#xA;Points that lie onto these planes, are said to be in `screen coordinates`. Though at some point you need to transform these coordinates to pixel coordinates what we call `raster coordinates` (which I believe in OpenGL are also called somehow `window coordinates`). There is &quot;no&quot; conventions for what the range screen coordinates should lie into because it depends entirely on the way you actually build your camera model, but they go from -something to +something in height and -something * imageAspectRation and +something * imageAspectRation in width. You raster coordinates always go from [0:height] for the y-coordinate and [0:width] for the x-coordinate.&#xD;&#xA;&#xD;&#xA;Understand all these concepts might take time and can't be properly explained in just a few lines. I would recommend additional source for you to look at and really understand and learn about the difference coordinate systems that are used and involved in the process of simulating physical cameras in computer graphics.&#xD;&#xA;&#xD;&#xA;[Start from the start by understanding the geometry behind projecting points on screens][2].&#xD;&#xA;[Continue with learning about the pinhole camera model][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LFJxf.png&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point&#xD;&#xA;  [3]: https://www.scratchapixel.com/lessons/3d-basic-rendering/3d-viewing-pinhole-camera" ContentLicense="CC BY-SA 3.0" />
  <row Id="11051" PostHistoryTypeId="5" PostId="4709" RevisionGUID="367ab596-c87d-4a0d-86c8-ce1606bac6ee" CreationDate="2017-02-12T09:13:29.660" UserId="6046" Comment="added 1088 characters in body" Text="So i am currently making a Ray-tracer as a personal project. My lighting equation looks like this&#xD;&#xA;&#xD;&#xA;    Pixel_color[i] = 255 * (Ma*Ig*Ca + Md*I*Cd * diffuse  + Ms*I*Cs * glossy)&#xD;&#xA;    // M = material color (ambient, diffuse and specular)&#xD;&#xA;    // I = intensity of light (Ig is the global ambient intensity)&#xD;&#xA;    // C = color of the light (ambient , diffuse and specular)&#xD;&#xA;&#xD;&#xA;Here `diffuse` and `glossy` contains all the necessary dot products and the normalization factors ( PI for diffuse and n+8/8*PI for blinn phong). Also everything is in range 0-1. I've read from some books and it says to make sure that `&quot;Ks + Kd&quot; &lt;= 1` And now i am confused. &#xD;&#xA;&#xD;&#xA;1) What exactly is Ks and Kd? Is it just my surface diffuse color and specular color divided by 255 to make it in the range 0-1? Or is it the reflectance ratio that i have to multiply with my color? If it's something else then what should i set them to? For example if i have a color `rgb(66, 170, 244)` which is somewhat light blue. What should the Ks and Kd be for the above color?&#xD;&#xA;&#xD;&#xA;2) These books don't include the ambient component when talking about this conservation so should it be  Ka+Kd+Ks &lt;= 1? Again if that's the case what will Ka be?&#xD;&#xA;&#xD;&#xA;3) If i consider Ks = Ms and Kd = Md. It doesn't fit out. for example if i want a surface with the above color `rgb(66, 170, 244)` to be shiny and the specular highlight should be white. Then my Ms would be (255-66, 255-170, 255-244) which won't be white. Another way i could do is subtract the maximum from every component Ms(255-244, 255-244, 255-244). But this means the specular color would be very low. What if i wanted a very shiny surface?&#xD;&#xA;&#xD;&#xA;UPDATE:-&#xD;&#xA;&#xD;&#xA;So according to the book Computer Graphics Principles and Practice, Chapter 6 &quot;Fixed Function and Hierarchial Modeling in WPF&quot; &#xD;&#xA;&#xD;&#xA;    Cd Innate color of “diffuse layer” (Cd,R,Cd,G,Cd,B)&#xD;&#xA;    Cs Innate color of “specular layer” (Cs,R,Cs,G,Cs,B)&#xD;&#xA;    ka Efficiency of diffuse layer at reflecting ambient light (ka,R, ka,G, ka,B)&#xD;&#xA;    kd Efficiency of diffuse layer at reflecting light (kd,R, kd,G, kd,B)&#xD;&#xA;    ks Efficiency of specular layer at reflecting light (ks,R, ks,G, ks,B)&#xD;&#xA;&#xD;&#xA;After that it writes, &#xD;&#xA;&#xD;&#xA;&gt; Note that for solid-color materials, the distinction between the two terms Cd&#xD;&#xA;and kd is unnecessary, as far as the math is concerned; you can think of them as&#xD;&#xA;a single term. That is, you can fix kd,R at 1. 0 and use Cd,R to achieve any effect,&#xD;&#xA;and conversely you could fix Cd,R and specify only kd,R. However, the distinction&#xD;&#xA;between the two terms is meaningful when the innate color Cd is being provided&#xD;&#xA;via texture mapping; in that case, there is a need for a kd,R factor affecting the&#xD;&#xA;reflection of the varying color Cd specified by the texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11052" PostHistoryTypeId="5" PostId="4709" RevisionGUID="4a7f4166-60d1-4539-9172-b52232897ce9" CreationDate="2017-02-12T09:22:12.830" UserId="6046" Comment="added 1088 characters in body" Text="So i am currently making a Ray-tracer as a personal project. My lighting equation looks like this&#xD;&#xA;&#xD;&#xA;    Pixel_color[i] = 255 * (Ma*Ig*Ca + Md*I*Cd * diffuse  + Ms*I*Cs * glossy)&#xD;&#xA;    // M = material color (ambient, diffuse and specular)&#xD;&#xA;    // I = intensity of light (Ig is the global ambient intensity)&#xD;&#xA;    // C = color of the light (ambient , diffuse and specular)&#xD;&#xA;&#xD;&#xA;Here `diffuse` and `glossy` contains all the necessary dot products and the normalization factors ( PI for diffuse and n+8/8*PI for blinn phong). Also everything is in range 0-1. I've read from some books and it says to make sure that `&quot;Ks + Kd&quot; &lt;= 1` And now i am confused. &#xD;&#xA;&#xD;&#xA;1) What exactly is Ks and Kd? Is it just my surface diffuse color and specular color divided by 255 to make it in the range 0-1? Or is it the reflectance ratio that i have to multiply with my color? If it's something else then what should i set them to? For example if i have a color `rgb(66, 170, 244)` which is somewhat light blue. What should the Ks and Kd be for the above color?&#xD;&#xA;&#xD;&#xA;2) These books don't include the ambient component when talking about this conservation so should it be  Ka+Kd+Ks &lt;= 1? Again if that's the case what will Ka be?&#xD;&#xA;&#xD;&#xA;3) If i consider Ks = Ms and Kd = Md. It doesn't fit out. for example if i want a surface with the above color `rgb(66, 170, 244)` to be shiny and the specular highlight should be white. Then my Ms would be (255-66, 255-170, 255-244) which won't be white. Another way i could do is subtract the maximum from every component Ms(255-244, 255-244, 255-244). But this means the specular color would be very low. What if i wanted a very shiny surface?&#xD;&#xA;&#xD;&#xA;UPDATE:-&#xD;&#xA;&#xD;&#xA;So according to the book Computer Graphics Principles and Practice, Chapter 6 &quot;Fixed Function and Hierarchial Modeling in WPF&quot; &#xD;&#xA;&#xD;&#xA;    Cd Innate color of “diffuse layer” (Cd,R,Cd,G,Cd,B)&#xD;&#xA;    Cs Innate color of “specular layer” (Cs,R,Cs,G,Cs,B)&#xD;&#xA;    ka Efficiency of diffuse layer at reflecting ambient light (ka,R, ka,G, ka,B)&#xD;&#xA;    kd Efficiency of diffuse layer at reflecting light (kd,R, kd,G, kd,B)&#xD;&#xA;    ks Efficiency of specular layer at reflecting light (ks,R, ks,G, ks,B)&#xD;&#xA;&#xD;&#xA;After that it writes, &#xD;&#xA;&#xD;&#xA;&gt; Note that for solid-color materials, the distinction between the two terms Cd&#xD;&#xA;and kd is unnecessary, as far as the math is concerned; you can think of them as&#xD;&#xA;a single term. That is, you can fix kd,R at 1. 0 and use Cd,R to achieve any effect,&#xD;&#xA;and conversely you could fix Cd,R and specify only kd,R. However, the distinction&#xD;&#xA;between the two terms is meaningful when the innate color Cd is being provided&#xD;&#xA;via texture mapping; in that case, there is a need for a kd,R factor affecting the&#xD;&#xA;reflection of the varying color Cd specified by the texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After that in Chapter 14.9 it removes Kd/Ks and Cd/Cs and replaces both with K_L and K_G&#xD;&#xA;&#xD;&#xA;&gt; These k parameters are no longer potentially ambiguous RGB triples (each 0 . . . 1), but constants representing the net probability over all directions of&#xD;&#xA;that term contributing to scattering.&#xD;&#xA;&#xD;&#xA;Which led me to think they are just a single constant like &quot;0.5&quot; However in the next example they are telling the same thing to ensure that K_L + K_G &lt;= 1 across all channel which implies that k_L and k_G are infact RGB triples." ContentLicense="CC BY-SA 3.0" />
  <row Id="11053" PostHistoryTypeId="5" PostId="4711" RevisionGUID="3a62f1c2-0203-4a77-ab9a-d4cc85835426" CreationDate="2017-02-12T11:26:28.857" UserId="1608" Comment="added 199 characters in body" Text="You have two issues at stake here:&#xD;&#xA;&#xD;&#xA;1. What conventions are used in the particular program you use (or use as a template). The meaning that people gave to certain words within the context of your program.&#xD;&#xA;&#xD;&#xA;2. The meaning of the terms 'screen coordinate' and 'window coordinates' in the Computer Graphics world. In the CG world, these terms have very precise meaning which do not necessarily correspond to meaning they have in the context of your program. &#xD;&#xA;&#xD;&#xA;So does your question related to &quot;what do these terms mean in the context of my program&quot; or &quot;what do they mean in CG&quot;? It seems like your more interested in the former.&#xD;&#xA;&#xD;&#xA;Let's try to reconcile the two questions:&#xD;&#xA;&#xD;&#xA;1. When you render a CG image you use a virtual camera. The image plane of that camera exists in the virtual world (thing of it as a rectangle if the image resolution width != than the image resolution height what we call the image aspect ratio), and has the same coordinates than all the objects that are in your scene. Think of this camera as a pyramid whose apex is the eye position and the base of the pyramid the image plane. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Imagine that the image plane (the base of the pyramid) is 1 unit away from the apex. By changing the size of this image plane which you do by changing the field-of-view angle as shown in the image above, you can control how much of the scene you see (this equivalent in photography to zooming in or out).&#xD;&#xA;&#xD;&#xA;Points that lie onto these planes, are said to be in `screen coordinates`. Though at some point you need to transform these coordinates to pixel coordinates what we call `raster coordinates` (which I believe in OpenGL are also called somehow `window coordinates`). There is &quot;no&quot; conventions for what the range screen coordinates should lie into because it depends entirely on the way you actually build your camera model, but they go from -something to +something in height and -something * imageAspectRation and +something * imageAspectRation in width. You raster coordinates always go from [0:height] for the y-coordinate and [0:width] for the x-coordinate. Screen coordinates are `floats` raster/window coordinates are `integers` (they correspond to pixel position in the digital image representation, the stuff you save to disk or display to the screen).&#xD;&#xA;&#xD;&#xA;Understand all these concepts might take time and can't be properly explained in just a few lines. I would recommend additional source for you to look at and really understand and learn about the difference coordinate systems that are used and involved in the process of simulating physical cameras in computer graphics.&#xD;&#xA;&#xD;&#xA;[Start from the start by understanding the geometry behind projecting points on screens][2].&#xD;&#xA;[Continue with learning about the pinhole camera model][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LFJxf.png&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point&#xD;&#xA;  [3]: https://www.scratchapixel.com/lessons/3d-basic-rendering/3d-viewing-pinhole-camera" ContentLicense="CC BY-SA 3.0" />
  <row Id="11054" PostHistoryTypeId="5" PostId="4711" RevisionGUID="cb5ec88c-8281-461a-811f-40db39ece3b1" CreationDate="2017-02-12T14:05:38.507" UserId="231" Comment="Minor typos and formatting" Text="You have two issues at stake here:&#xD;&#xA;&#xD;&#xA;1. What conventions are used in the particular program you use (or use as a template). The meaning that people gave to certain words within the context of your program.&#xD;&#xA;&#xD;&#xA;2. The meaning of the terms 'screen coordinates' and 'window coordinates' in the Computer Graphics world. In the CG world, these terms have very precise meaning which do not necessarily correspond to the meaning they have in the context of your program. &#xD;&#xA;&#xD;&#xA;So does your question relate to &quot;what do these terms mean in the context of my program&quot; or &quot;what do they mean in CG&quot;? It seems like you're more interested in the former.&#xD;&#xA;&#xD;&#xA;Let's try to reconcile the two questions:&#xD;&#xA;&#xD;&#xA;1. When you render a CG image you use a virtual camera. The image plane of that camera exists in the virtual world (think of it as a rectangle if the image resolution width != the image resolution height what we call the image aspect ratio), and has the same coordinates as all the objects that are in your scene. Think of this camera as a pyramid whose apex is the eye position and the base of the pyramid the image plane. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Imagine that the image plane (the base of the pyramid) is 1 unit away from the apex. By changing the size of this image plane which you do by changing the field-of-view angle as shown in the image above, you can control how much of the scene you see (this is equivalent in photography to zooming in or out).&#xD;&#xA;&#xD;&#xA;Points that lie on these planes, are said to be in `screen coordinates`. Though at some point you need to transform these coordinates to pixel coordinates that we call `raster coordinates` (which I believe in OpenGL are also called somehow `window coordinates`). There are ***no*** conventions for what range the screen coordinates should lie in because it depends entirely on the way you actually build your camera model, but they go from -something to +something in height and -something * imageAspectRatio and +something * imageAspectRatio in width. Your raster coordinates always go from [0:height] for the y-coordinate and [0:width] for the x-coordinate. Screen coordinates are `floats`, raster/window coordinates are `integers` (they correspond to pixel position in the digital image representation, the stuff you save to disk or display to the screen).&#xD;&#xA;&#xD;&#xA;Understand that all these concepts might take time and can't be properly explained in just a few lines. I would recommend additional sources for you to look at and really understand and learn about the different coordinate systems that are used and involved in the process of simulating physical cameras in computer graphics.&#xD;&#xA;&#xD;&#xA;- [Start from the start by understanding the geometry behind projecting points on screens][2].  &#xD;&#xA;- [Continue with learning about the pinhole camera model][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LFJxf.png&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point&#xD;&#xA;  [3]: https://www.scratchapixel.com/lessons/3d-basic-rendering/3d-viewing-pinhole-camera" ContentLicense="CC BY-SA 3.0" />
  <row Id="11055" PostHistoryTypeId="2" PostId="4712" RevisionGUID="c178b8d9-0154-4c0a-b442-0dd8050c46e1" CreationDate="2017-02-12T18:24:12.840" UserId="6049" Text="Doing post-process gamma correction is showing texture artifacts, here is a small example on a skybox:&#xD;&#xA;&#xD;&#xA;[![Correction on Skybox vs Post Process][1]][1]&#xD;&#xA;&#xD;&#xA;The first image is gamma correcting on the skybox shader and seems correct, the lower is doing it in post-process and has terrible artifacts near the edges of the clouds, however both versions do it the same usual way:&#xD;&#xA;&#xD;&#xA;    Color.rgb = pow(Color.rgb, vec3(1.0/2.2));&#xD;&#xA; 	Color.a = 1.0;&#xD;&#xA;&#xD;&#xA;So that makes me believe there's something wrong with the way I'm creating and using frame buffers, here's sort of how I'm doing it:&#xD;&#xA;&#xD;&#xA;    // Generate FirstFBO, specify this as the color attachment&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FramebufferSize.x, FramebufferSize.y, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); &#xD;&#xA;    &#xD;&#xA;    // ...&#xD;&#xA;&#xD;&#xA;    while (true) {&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, FirstFBO.ID);&#xD;&#xA;        DrawStuff();&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, FirstFBO.ColorTexture);&#xD;&#xA;        DrawFullscreenQuad();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HAqRT.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11056" PostHistoryTypeId="1" PostId="4712" RevisionGUID="c178b8d9-0154-4c0a-b442-0dd8050c46e1" CreationDate="2017-02-12T18:24:12.840" UserId="6049" Text="Artifacts when gamma correcting" ContentLicense="CC BY-SA 3.0" />
  <row Id="11057" PostHistoryTypeId="3" PostId="4712" RevisionGUID="c178b8d9-0154-4c0a-b442-0dd8050c46e1" CreationDate="2017-02-12T18:24:12.840" UserId="6049" Text="|c++|gamma|artifacts|post-processing|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11058" PostHistoryTypeId="2" PostId="4713" RevisionGUID="b639c801-68e8-4eef-8187-dfadb6a4677e" CreationDate="2017-02-12T19:46:23.880" UserId="4908" Text="Short answer, set the precision of the image to a higher value.&#xD;&#xA;&#xD;&#xA;Long answer,&#xD;&#xA;&#xD;&#xA;When looking at a gamma correction curve, you can see that the lower values get changed much more, this means that the difference between lower values will get greater and that causes this effect. You have a limited amount of values for a color channel and this means that when it rounds the number down to the 8 bit value, it makes some neighboring pixels the same color. You don't notice this in a normal image, but after gamma correcting it this effect comes out, because you lose that bit of change in the color that later on can become a much bigger difference in color.&#xD;&#xA;&#xD;&#xA;To fix this, you just give the gamma correction more precision to also get that small color change it would've else rounded away.&#xD;&#xA;&#xD;&#xA;In the actual shader, it has floating point color information and that means that it has more precision and thus not the weird artifact.&#xD;&#xA;&#xD;&#xA;So when making the frame buffer, you can use for example GL_RGBA16F or GL_RGBA32F. This would increase the precision and remove the artifact.&#xD;&#xA;&#xD;&#xA;I hope that this can help you fix the problem, good luck and have a great day!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11062" PostHistoryTypeId="2" PostId="4715" RevisionGUID="5114c45e-458f-4e38-93ae-9790998f9af0" CreationDate="2017-02-13T02:33:56.647" UserId="5905" Text="I'm learning about subdivision surface algorithms. The &quot;Catmull-Clark&quot; algorithm seems to be one of the most widely-used classical algorithms.&#xD;&#xA;&#xD;&#xA;The introduction of new face points and edges is straightforward, but I'm confused by the following formula for modifying the locations of original points&#xD;&#xA;&#xD;&#xA;$$ \frac{F + 2R + (n-3)P}{n} $$&#xD;&#xA;&#xD;&#xA;where:&#xD;&#xA;&#xD;&#xA;- $P$ is the original point&#xD;&#xA;- $R$ is the average of all $n$ edges touching $P$&#xD;&#xA;- $F$ is the average of all $n$ face points touching $P$&#xD;&#xA;&#xD;&#xA;I understand the result is a weighted average of three points $F$, $R$ and $P$, but where do the coefficients $1$, $2$, and $(n-3)$ come from? Why $2R$? Why not $2.01R$? Or $1R$ and $2F$?&#xD;&#xA;&#xD;&#xA;All the introductions I've seen just present the formula without presenting a justification." ContentLicense="CC BY-SA 3.0" />
  <row Id="11063" PostHistoryTypeId="1" PostId="4715" RevisionGUID="5114c45e-458f-4e38-93ae-9790998f9af0" CreationDate="2017-02-13T02:33:56.647" UserId="5905" Text="Where do the coefficients in the Catmull-Clark subdivision algorithm come from?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11064" PostHistoryTypeId="3" PostId="4715" RevisionGUID="5114c45e-458f-4e38-93ae-9790998f9af0" CreationDate="2017-02-13T02:33:56.647" UserId="5905" Text="|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11065" PostHistoryTypeId="2" PostId="4716" RevisionGUID="e0bdbaa4-a4bb-4b1c-a704-1975551d3764" CreationDate="2017-02-13T09:16:21.083" UserId="4546" Text="The derivation is presented in the original paper that introduced CC subdivisions as a generalisation of B-Spline patches: https://people.eecs.berkeley.edu/~sequin/CS284/PAPERS/CatmullClark_SDSurf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11068" PostHistoryTypeId="5" PostId="4703" RevisionGUID="1f8a6240-ef76-4fca-9ccb-37026f7fc80f" CreationDate="2017-02-13T17:14:58.693" UserId="6044" Comment="Specified that I want the ratios of angles to be preserved, not the angles themselves." Text="I have a 3D triangular mesh representing cortical surface of a brain. I also have one vertex of interest. I would like to unfold a neighborhood of this vertex in such a way that both the angles (their ratios) and distances of paths from this vertex are preserved as much as possible.&#xD;&#xA;&#xD;&#xA;I read some reviews on mesh parameterization techniques (eg. [this](http://people.eecs.berkeley.edu/~jrs/meshpapers/ShefferPraunRose.pdf) one by Scheffer et al.). My understanding is that all the algorithms try to preserve a certain property (angle, distance, area) or a combination of those properties for all of the vertices or faces. In my case I need to preserve angles and distance of paths going from only one point. My intuition tells me that what I need should be quite simple because I demand much less from the output than all those parameterization algorithms. Yet I cannot come up with the solution. Any help is greatly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="11074" PostHistoryTypeId="5" PostId="4715" RevisionGUID="24e226de-bf74-4650-8e0d-37247e940d20" CreationDate="2017-02-13T20:02:57.813" UserId="5905" Comment="added 10 characters in body" Text="I'm learning about subdivision surface algorithms. The &quot;Catmull-Clark&quot; algorithm seems to be one of the most widely-used classical algorithms.&#xD;&#xA;&#xD;&#xA;The introduction of new face points and edges is straightforward, but I'm confused by the following formula for modifying the locations of original points&#xD;&#xA;&#xD;&#xA;$$ \frac{F + 2R + (n-3)P}{n} $$&#xD;&#xA;&#xD;&#xA;where:&#xD;&#xA;&#xD;&#xA;- $P$ is the original point&#xD;&#xA;- $R$ is the average of all $n$ edges midpoints touching $P$&#xD;&#xA;- $F$ is the average of all $n$ face points touching $P$&#xD;&#xA;&#xD;&#xA;I understand the result is a weighted average of three points $F$, $R$ and $P$, but where do the coefficients $1$, $2$, and $(n-3)$ come from? Why $2R$? Why not $2.01R$? Or $1R$ and $2F$?&#xD;&#xA;&#xD;&#xA;All the introductions I've seen just present the formula without presenting a justification." ContentLicense="CC BY-SA 3.0" />
  <row Id="11075" PostHistoryTypeId="2" PostId="4718" RevisionGUID="d1a6730c-0895-4a5c-9afd-d3b95e203bdf" CreationDate="2017-02-13T20:52:12.473" UserId="6061" Text="I'm using GLSL 4.0 to write a subdivision routine that divides the triangles on an object through a geometry shader. I'm not using barycentric co-ordinates but vector arithmetic to output the triangle vertices. I managed to get the subdivision working but I don't understand how to interpolate the vertex normals to produce the correct shading:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 400 &#xD;&#xA;    &#xD;&#xA;    layout(triangles) in;&#xD;&#xA;    layout(triangle_strip, max_vertices = 93) out; //MAX 128&#xD;&#xA;    &#xD;&#xA;    uniform mat4 mvMatrix;&#xD;&#xA;    uniform mat4 pMatrix;&#xD;&#xA;    uniform mat3 normalMatrix; //mv matrix without translation&#xD;&#xA;    uniform int subdivision_level;&#xD;&#xA;    uniform vec4 lightPosition_camSpace; //light Position in camera space&#xD;&#xA;    &#xD;&#xA;    uniform int time;&#xD;&#xA;    &#xD;&#xA;    in data&#xD;&#xA;    {&#xD;&#xA;      vec4 position_camSpace;&#xD;&#xA;      vec3 normal_camSpace;&#xD;&#xA;      vec2 textureCoordinate;&#xD;&#xA;      vec4 color;&#xD;&#xA;    }vertexIn[3];&#xD;&#xA;    &#xD;&#xA;    out fragmentData&#xD;&#xA;    {&#xD;&#xA;      vec4 position_camSpace;&#xD;&#xA;      vec3 normal_camSpace;&#xD;&#xA;      vec2 textureCoordinate;&#xD;&#xA;      vec4 color;&#xD;&#xA;    } frag;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void emit_triangle(vec4 position, vec4 width, vec4 hyp, float s) {&#xD;&#xA;    	&#xD;&#xA;    	/* NORMALS NOT FIXED */&#xD;&#xA;    &#xD;&#xA;        //A&#xD;&#xA;        gl_Position = position;&#xD;&#xA;        frag.color = vertexIn[0].color;&#xD;&#xA;    	frag.position_camSpace = vertexIn[0].position_camSpace;&#xD;&#xA;        frag.normal_camSpace = vertexIn[0].normal_camSpace;&#xD;&#xA;        frag.textureCoordinate = vertexIn[0].textureCoordinate;&#xD;&#xA;        EmitVertex();&#xD;&#xA;        &#xD;&#xA;        //B&#xD;&#xA;        gl_Position = position + width;&#xD;&#xA;    	frag.color = vertexIn[1].color;&#xD;&#xA;    	frag.position_camSpace = vertexIn[1].position_camSpace;&#xD;&#xA;        frag.normal_camSpace = vertexIn[1].normal_camSpace;&#xD;&#xA;        frag.textureCoordinate = vertexIn[1].textureCoordinate;&#xD;&#xA;    &#xD;&#xA;        EmitVertex();&#xD;&#xA;        &#xD;&#xA;        //C&#xD;&#xA;    	gl_Position = position + hyp;&#xD;&#xA;    	frag.color = vertexIn[2].color;&#xD;&#xA;    	frag.position_camSpace = vertexIn[2].position_camSpace;&#xD;&#xA;        frag.normal_camSpace = vertexIn[2].normal_camSpace;&#xD;&#xA;        frag.textureCoordinate = vertexIn[2].textureCoordinate;&#xD;&#xA;    &#xD;&#xA;        EmitVertex();&#xD;&#xA;    &#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;      // A gl_In[0].gl_Position;&#xD;&#xA;      // B gl_In[1].gl_Position;&#xD;&#xA;      // C gl_In[2].gl_Position;&#xD;&#xA;                &#xD;&#xA;      float s = 1/pow(2,subdivision_level);&#xD;&#xA;      int triangles_render = int(1/s);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      vec4 hyp_off = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;      vec4 width_off = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;    &#xD;&#xA;      vec4 position = gl_in[0].gl_Position;&#xD;&#xA;      vec4 width = s*(gl_in[1].gl_Position - gl_in[0].gl_Position);&#xD;&#xA;      vec4 hyp = s*(gl_in[2].gl_Position - gl_in[0].gl_Position);&#xD;&#xA;    &#xD;&#xA;      vec4 hyp_off_f = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;      vec4 width_off_f = width;&#xD;&#xA;      &#xD;&#xA;    &#xD;&#xA;      for (int i=0; i&lt;=subdivision_level+1; i++) {&#xD;&#xA;        for (int j=0; j&lt;triangles_render-i; j++) {&#xD;&#xA;    &#xD;&#xA;    	  // Normal triangle&#xD;&#xA;          emit_triangle(position + hyp_off + width_off, width, hyp,s);&#xD;&#xA;    	  width_off += width;  &#xD;&#xA;    &#xD;&#xA;          // Flipped triangle&#xD;&#xA;          if (j &lt;triangles_render-i-1)&#xD;&#xA;          {&#xD;&#xA;    	    emit_triangle(position + width_off_f + hyp_off_f, hyp, hyp - width,s);&#xD;&#xA;            width_off_f += width;&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;        hyp_off += hyp;&#xD;&#xA;        width_off = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;    &#xD;&#xA;    	hyp_off_f += hyp;&#xD;&#xA;        width_off_f = width;&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Currently the result looks like flat shading because I just use the normals of the vertices from the vertex shader. How do I compute the correct normals so that the shading looks correct? Also do I need to modify the vertex position too? I'm unsure about this part. I've read &#xD;&#xA;http://stackoverflow.com/questions/4703432/why-does-my-opengl-phong-shader-behave-like-a-flat-shader But they use barycentric co-ordinates for the solution." ContentLicense="CC BY-SA 3.0" />
  <row Id="11076" PostHistoryTypeId="1" PostId="4718" RevisionGUID="d1a6730c-0895-4a5c-9afd-d3b95e203bdf" CreationDate="2017-02-13T20:52:12.473" UserId="6061" Text="Subdivision vertex normal interpolation" ContentLicense="CC BY-SA 3.0" />
  <row Id="11077" PostHistoryTypeId="3" PostId="4718" RevisionGUID="d1a6730c-0895-4a5c-9afd-d3b95e203bdf" CreationDate="2017-02-13T20:52:12.473" UserId="6061" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11081" PostHistoryTypeId="2" PostId="4720" RevisionGUID="a854aad7-36cf-4568-9d6d-bdd6907663f3" CreationDate="2017-02-14T17:29:39.060" UserId="6063" Text="Generally, with VSYNC, your CPU is effectively doing nothing 99% of the time, as it merely sent the simple vertex buffer batch (few triangles, as you said) to the driver. If the shader is bandwidth-heavy, it takes multiple frames to render. In your case, you said it's 12 fps, e.g. 60/12 = 5 frames. So, the CPU (or the core that runs your thread), is literally doing nothing for 5 frames (other than waiting for vsync). That's an egregious waste of performance for a 3d engine.&#xD;&#xA;&#xD;&#xA;Why is the 'utilization' statistics important, anyway ? What matters is your framerate, that's how you know how well you're doing, not some arbitrary 'utilization' number in the OS, that god-knows-how it got assembled in the first place." ContentLicense="CC BY-SA 3.0" />
  <row Id="11082" PostHistoryTypeId="2" PostId="4721" RevisionGUID="181ab83d-0f07-49d7-bd80-8763793f806f" CreationDate="2017-02-14T17:41:44.410" UserId="6063" Text="Try searching for Valve's paper on combining Radiosity and Normal Mapping. It had a lot of useful insights.&#xD;&#xA;&#xD;&#xA;If I'm not mistaken, it looks to me like you're trying to compute normal mapping using the energy value at the texel that is a result of Radiosity - e.g. it came from all directions through almost-endless bumping around the room across thousands of surfaces. &#xD;&#xA;&#xD;&#xA;But your point light, for the normal mapping, has a very specific position, direction, distance and intensity. Meaning, you're combining apples and goats.&#xD;&#xA;&#xD;&#xA;What I believe you should do is:&#xD;&#xA;- compute the normal mapping separately for those surfaces&#xD;&#xA;- blend the GI solution with normal mapping&#xD;&#xA;- experiment with the blending factor till it looks 'good enough' for you" ContentLicense="CC BY-SA 3.0" />
  <row Id="11083" PostHistoryTypeId="2" PostId="4722" RevisionGUID="86864fe1-0145-4ca1-b799-9743d8fc3d5c" CreationDate="2017-02-14T19:05:10.187" UserId="6064" Text="After z buffer testing does the fragment shader runs or not for the discarded fragment.&#xA;Or &#xA;Does z test happens after fragment shader runs.&#xA;&#xA;Please,Tell me the step by step events that occurs in z test.&#xA;&#xA;Also what is early z test and how to achieve it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11084" PostHistoryTypeId="1" PostId="4722" RevisionGUID="86864fe1-0145-4ca1-b799-9743d8fc3d5c" CreationDate="2017-02-14T19:05:10.187" UserId="6064" Text="Z buffer working in opengl" ContentLicense="CC BY-SA 3.0" />
  <row Id="11085" PostHistoryTypeId="3" PostId="4722" RevisionGUID="86864fe1-0145-4ca1-b799-9743d8fc3d5c" CreationDate="2017-02-14T19:05:10.187" UserId="6064" Text="|opengl|rasterizer|fragment-shader|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11086" PostHistoryTypeId="2" PostId="4723" RevisionGUID="831c0ac0-52b2-476d-8b08-6043ff25812f" CreationDate="2017-02-14T22:48:50.527" UserId="6041" Text="According to Peter Shirely [paper][1], one pdf(probability density function) can be defined for the union of the light sources and pick only one using a random number from this density:&#xD;&#xA;&#xD;&#xA;p(x) = a1 * P1(x) + (1-a1) * P2(x); &#xD;&#xA;&#xD;&#xA;This has been referred to as mixture densities. where a=[0,1] and P1 is a pdf for selecting a point on the L1 geometry(usually 1/A). If the random number is less than a1 then the total estimate is (estimated L1)/a1. &#xD;&#xA;&#xD;&#xA;This has been extended for N:&#xD;&#xA;p(x) = a1 * P1(x) + a2 * P2(x) + ... + an * Pn(x)&#xD;&#xA;&#xD;&#xA;My question is how one pick two or multiple light sources, instead of just one, from the above density and what the estimate would be in that case.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~jdl/bib/globillum/mis/shirley96.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11087" PostHistoryTypeId="1" PostId="4723" RevisionGUID="831c0ac0-52b2-476d-8b08-6043ff25812f" CreationDate="2017-02-14T22:48:50.527" UserId="6041" Text="Picking multiple light sources from a mixture densities" ContentLicense="CC BY-SA 3.0" />
  <row Id="11088" PostHistoryTypeId="3" PostId="4723" RevisionGUID="831c0ac0-52b2-476d-8b08-6043ff25812f" CreationDate="2017-02-14T22:48:50.527" UserId="6041" Text="|raytracing|lighting|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11089" PostHistoryTypeId="5" PostId="4723" RevisionGUID="c0cc57e1-708f-4694-9a4b-3a7dfee76afa" CreationDate="2017-02-14T23:13:43.833" UserId="48" Comment="math formatting" Text="According to Peter Shirely [paper][1], one pdf(probability density function) can be defined for the union of the light sources and pick only one using a random number from this density:&#xD;&#xA;&#xD;&#xA;$$p(x) = \alpha_1 P_1(x) + (1-\alpha_1) P_2(x)$$&#xD;&#xA;&#xD;&#xA;This has been referred to as mixture densities. where $\alpha_1 \in [0,1]$ and $P_1$ is a pdf for selecting a point on the $L_1$ geometry (usually $1/A$). If the random number is less than $\alpha_1$ then the total estimate is $(\text{estimated }L_1)/\alpha_1$. &#xD;&#xA;&#xD;&#xA;This has been extended for N:&#xD;&#xA;$$p(x) = \alpha_1 P_1(x) + \alpha_2 P_2(x) + \cdots + \alpha_n P_n(x)$$&#xD;&#xA;&#xD;&#xA;My question is how one pick two or multiple light sources, instead of just one, from the above density and what the estimate would be in that case.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~jdl/bib/globillum/mis/shirley96.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11090" PostHistoryTypeId="2" PostId="4724" RevisionGUID="1d4e3e74-5130-4945-934c-65928b741020" CreationDate="2017-02-15T02:55:06.983" UserId="2707" Text="When depth testing is enabled, the testing occurs after the fragment shader executes. The procedure is relatively simple (and spelled out pretty well [here][1]):&#xD;&#xA;&#xD;&#xA; - Get depth of fragment&#xD;&#xA; - Test against depth buffer&#xD;&#xA; - Discard if it fails&#xD;&#xA;&#xD;&#xA;The early-z discard is when a rasterizer discards a fragment before a fragment shader runs because it fails the depth test. However, the rasterizer can't safely do this is certain things happen (such as calling `discard()` or modifying the fragment depth in a fragment shader). This is a hardware optimization (although you can enforce it in OpenGL 4.2 or with an extension).&#xD;&#xA;&#xD;&#xA;There are things that can [prevent this from occurring][2]. To achieve it:&#xD;&#xA;&#xD;&#xA; - Don't use `discard()` in a fragment shader&#xD;&#xA; - Don't modify the depth of a fragment in a fragment shader&#xD;&#xA; - Don't use alpha testing (deprecated)&#xD;&#xA; - Make sure you have depth testing turned on&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Depth_Test&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Early_Fragment_Test#Limitations" ContentLicense="CC BY-SA 3.0" />
  <row Id="11091" PostHistoryTypeId="5" PostId="4724" RevisionGUID="816718a4-cb81-46f3-a030-f57f00d62da5" CreationDate="2017-02-15T03:01:45.460" UserId="2707" Comment="Clarified some language/fixed some typos" Text="When depth testing is enabled, the testing occurs after the fragment shader executes. The procedure is relatively simple (and spelled out pretty well [here][1]):&#xD;&#xA;&#xD;&#xA; - Get depth of fragment&#xD;&#xA; - Test against depth buffer&#xD;&#xA; - Discard if it fails&#xD;&#xA;&#xD;&#xA;Early-z discard is when a rasterizer discards a fragment before a fragment shader runs because it's clear early on that it won't pass the depth test. However, the rasterizer can't safely do this if certain things happen (such as calling `discard()` or modifying the fragment depth in a fragment shader). This is a hardware optimization and isn't required to occur unless you force it with OpenGL 4.2 or with an extension.&#xD;&#xA;&#xD;&#xA;There are things that can [prevent early-z discard from occurring][2]. To achieve it:&#xD;&#xA;&#xD;&#xA; - Don't use `discard()` in a fragment shader&#xD;&#xA; - Don't modify the depth of a fragment in a fragment shader&#xD;&#xA; - Don't use alpha testing (deprecated)&#xD;&#xA; - Make sure you have depth testing turned on&#xD;&#xA; - Make sure you have a depth buffer&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Depth_Test&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Early_Fragment_Test#Limitations" ContentLicense="CC BY-SA 3.0" />
  <row Id="11092" PostHistoryTypeId="5" PostId="4699" RevisionGUID="6991c0e5-8aee-4ea8-8f41-5b6c7804f6fa" CreationDate="2017-02-15T04:57:38.297" UserId="6001" Comment="added 213 characters in body" Text="I have a working light mapper that captures global illumination. I evaluate a hemisphere when collecting the data and store the result in the texel. However, I want to support directional lightmaps so that I can more realistically light normal maps at runtime. What strategies are there to adapt my light mapper's final gather operation to capture this data? Is it as simple as performing three hemisphere samples per texel in orthogonal directions? Or should I uniformly sample the hemisphere once, and project the results onto the basis vectors? Or do I sample the hemisphere and project each sample on to the basis.&#xD;&#xA;&#xD;&#xA;I've done some tests with the latter - projecting the each sample on the hemisphere onto the three basis vectors - and this works mostly, but I'm not sure about whether the projected samples should be clamped when their dot product is facing away from the basis or not." ContentLicense="CC BY-SA 3.0" />
  <row Id="11093" PostHistoryTypeId="2" PostId="4725" RevisionGUID="656aa009-6292-434f-b2bd-a1a4e2b27372" CreationDate="2017-02-15T08:21:24.800" UserId="5905" Text="I'm just going to add a few more details to [the paper](https://people.eecs.berkeley.edu/~sequin/CS284/PAPERS/CatmullClark_SDSurf.pdf) that Stefan linked to.&#xD;&#xA;&#xD;&#xA;First of all, the matrix $H_1$ displayed in the paper is incorrect; every element should be multiplied by a factor of $\frac{1}{8}$.&#xD;&#xA;&#xD;&#xA;$$ H_1 = \frac{1}{8} \begin{bmatrix}&#xD;&#xA;    4 &amp; 4 &amp; 0 &amp; 0 \\&#xD;&#xA;    1 &amp; 6 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 4 &amp; 4 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 6 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Second, the derivation of the new face point formula for quads in the first half of the paper is confusing, so I will fill in some of the details. &#xD;&#xA;&#xD;&#xA;The matrix $G_1 = HGH^T$ contains the 16 control points for one sub-quad of the original quad with control points $G$. The entries of $G_1$ are referred to with $q_{i,j}$. Of most interest are the elements $q_{1,1}$, $q_{1,2}$ and $q_{2,2}$, which represent control points for a corner, edge, and interior of the $4\times 4$ control point grid for the sub-quad. All the other elements have similar formulas due to the symmetry of the subdivision process.&#xD;&#xA;&#xD;&#xA;By carrying out the matrix multiplication, we get:&#xD;&#xA;&#xD;&#xA;$q_{2,2} = \frac{P_{1,1} +P_{3,1} +P_{3,1} +P_{3,3}}{64} + \frac{6(P_{1,2} +P_{2,1} +P_{3,2} +P_{2,3})}{64} + \frac{36P_{2,2}}{64}$&#xD;&#xA;&#xD;&#xA;We can see from this formula that, when relocating a control point, its new location is determined by the $3\times 3$ grid of points surrounding it. Here we see that in this grid, corner points have $\frac{1}{64}$ influence, edge points have $\frac{6}{64} = \frac{3}{32}$ influence, and the center (&quot;old&quot;) point has $\frac{36}{64} = \frac{9}{16}$ influence. These weights are consistent with the ones given at the bottom of [this blog post](http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/).&#xD;&#xA;&#xD;&#xA;With a bit of rearranging, we get:&#xD;&#xA;&#xD;&#xA;$q_{2,2} = \frac{1}{4} \big[ \frac{1}{4}(\frac{P_{1,1} + P_{1,2} + P_{2,1} + P_{2,2}}{4} + \frac{P_{1,2} + P_{2,2} + P_{1,3} + P_{2,3}}{4} + \frac{P_{2,1} + P_{2,2} + P_{3,2} + P_{3,1}}{4} + \frac{P_{2,2} + P_{2,3} + P_{3,2} + P_{3,3}}{4}) + 2\frac{1}{4}(\frac{P_{1,2} + P_{2,2}}{2} + \frac{P_{2,1} + P_{2,2}}{2} + \frac{P_{2,3} + P_{2,2}}{2} + \frac{P_{3,2} + P_{2,2}}{2}) + P_{2,2}\big]$&#xD;&#xA;&#xD;&#xA;The first term is merely the average of the four surrounding face points; in other words, it is $F$. The second term is the average of the four surrounding edge midpoints multiplied by $2$; in other words, it is $2R$. Finally, $P_{2,2}$ is simply the original control point $P$.&#xD;&#xA;&#xD;&#xA;And so we see this is the same as the original formula for quads: $\frac{1}{4}(F + 2R + P)$.&#xD;&#xA;&#xD;&#xA;The paper does not provide a derivation of the general case for an $n$-sided polygon, but it seems like a reasonable extension based on intuition.&#xD;&#xA;_______&#xD;&#xA;&#xD;&#xA;As an aside, here is an explanation for the other points, and [their meanings as seen on wikipedia](https://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface):&#xD;&#xA;&#xD;&#xA;$q_{1,1} = \frac{P_{1,1} +P_{1,2} +P_{2,1} +P_{2,2}}{4}$&#xD;&#xA;&#xD;&#xA;This is simply the formula for adding a new control point at the center of an existing quad.&#xD;&#xA;&#xD;&#xA;$q_{1,2} = \frac{P_{1,1} +P_{1,2} +P_{2,1} +P_{2,3}}{16} + \frac{6(P_{1,2} +P_{2,1})}{16}$&#xD;&#xA;&#xD;&#xA;Rearranging this, we see it is just the average of the two neighbouring face points and the edge endpoints:&#xD;&#xA;&#xD;&#xA;$q_{1,2} = \frac{1}{4}(\frac{P_{1,1} +P_{2,1} +P_{1,2} +P_{2,2}}{4} + \frac{P_{1,2} +P_{2,2} +P_{1,3} +P_{2,3}}{4} + P_{1,2} + P_{2,1})$" ContentLicense="CC BY-SA 3.0" />
  <row Id="11095" PostHistoryTypeId="5" PostId="4699" RevisionGUID="ab501f48-ba54-4878-b9d8-317c17eede81" CreationDate="2017-02-15T17:28:53.027" UserId="6001" Comment="added 1392 characters in body; edited tags" Text="I have a working light mapper that captures global illumination. I evaluate a hemisphere when collecting the data and store the result in the texel. However, I want to support directional lightmaps so that I can more realistically light normal maps at runtime. What strategies are there to adapt my light mapper's final gather operation to capture this data? Is it as simple as performing three hemisphere samples per texel in orthogonal directions? Or should I uniformly sample the hemisphere once, and project the results onto the basis vectors? Or do I sample the hemisphere and project each sample on to the basis.&#xD;&#xA;&#xD;&#xA;I've done some tests with the latter - projecting the each sample on the hemisphere onto the three basis vectors - and this works mostly, but I'm not sure about whether the projected samples should be clamped when their dot product is facing away from the basis or not.&#xD;&#xA;&#xD;&#xA;When reading all of Valve's HL2 Radiosity Normal Mapping articles, the need to generate three lightmaps for the bases vectors is clear, as are the coordinates for the bases vectors, as is the reconstruction in a shader of the data - this is straight forward enough. See [Valve SIGGRAPH06][1], [Valve Tutorial][2] and [Peter Houska on Directional Lightmaps][3]). &#xD;&#xA;&#xD;&#xA;The complication comes from *how* to generate those three samples:&#xD;&#xA;&#xD;&#xA;For example - from a Valve GDC talk:&#xD;&#xA;&#xD;&#xA;&gt; • Traditionally, when computing light map values using a radiosity&#xD;&#xA;&gt; preprocessor, a single color value is calculated&#xD;&#xA;&gt;&#xD;&#xA;&gt; • In Radiosity Normal&#xD;&#xA;&gt; Mapping, we transform our basis into tangent space and compute light&#xD;&#xA;&gt; values for each vector&#xD;&#xA;&#xD;&#xA;Given that I am currently sampling on a hemisphere, do I simply project each sample onto the bases and store those accumulations? If I do that, how do I handle the fact that data within my original hemisphere, when projected onto the bases, could create a projection that actually *subtracts* energy, given that a sample ray pointing away from the bases gives a negative dot product.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.valvesoftware.com/publications/2006/SIGGRAPH06_Course_ShadingInValvesSourceEngine.pdf&#xD;&#xA;  [2]: http://www.valvesoftware.com/publications/2004/GDC2004_Half-Life2_Shading.pdf&#xD;&#xA;  [3]: http://www.decew.net/OSS/References/sem_ss06_07-Independant%20Explanation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11096" PostHistoryTypeId="6" PostId="4699" RevisionGUID="ab501f48-ba54-4878-b9d8-317c17eede81" CreationDate="2017-02-15T17:28:53.027" UserId="6001" Comment="added 1392 characters in body; edited tags" Text="|raytracing|lighting|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11097" PostHistoryTypeId="2" PostId="4726" RevisionGUID="7f437da7-bd64-437a-83f1-2492868d63eb" CreationDate="2017-02-16T04:26:53.823" UserId="5183" Text="I'm writing a function that reads the number of red pixels on the left and right halves of the screen, it makes adjustments while the difference between the number of red pixels falls outside of a threshold. I'm having trouble with the buffers (back and front) because when I finally swap to the front buffer, it dynamically draws all changes I made in the loop meant for the back buffer but I only want the final one drawn to screen. In pseudocode, &#xD;&#xA;&#xD;&#xA;    do {&#xD;&#xA;    draw scene to back buffer&#xD;&#xA;    read number of left, right red pixels&#xD;&#xA;    if (abs(left-right)&gt;threshold) {&#xD;&#xA;    //some function to jitter objects in the scene&#xD;&#xA;    }&#xD;&#xA;    else done=true,&#xD;&#xA;    }while(!done);&#xD;&#xA;    draw to front buffer&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is some C++/OpenGL code:&#xD;&#xA;    &#xD;&#xA;    do{		&#xD;&#xA;	glDrawBuffer(GL_BACK_LEFT);&#xD;&#xA;	display(0);&#xD;&#xA;	&#xD;&#xA;	glDrawBuffer(GL_BACK_RIGHT);&#xD;&#xA;	display(1);&#xD;&#xA;	&#xD;&#xA;	 redsleft = 0;&#xD;&#xA;	 redsright = 0;&#xD;&#xA;	&#xD;&#xA;	glReadBuffer(GL_BACK_LEFT);&#xD;&#xA;		&#xD;&#xA;	glReadPixels(0, 0, resolution.first, resolution.second, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);&#xD;&#xA;	for (int j = 0; j &lt; resolution.first*resolution.second * 4; j += 4){&#xD;&#xA;		if (frameBuffer[j]&gt;0 &amp;&amp; frameBuffer[j + 1] == 0 &amp;&amp; frameBuffer[j + 2] == 0 &amp;&amp; frameBuffer[j + 3] &gt; 0)&#xD;&#xA;				{&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;					if (j % 4 == 0 &amp;&amp; i == 0)&#xD;&#xA;&#xD;&#xA;					{&#xD;&#xA;&#xD;&#xA;						int redX = (j / 4) % resolution.first;&#xD;&#xA;&#xD;&#xA;						int redY = j / 4 / resolution.first;&#xD;&#xA;&#xD;&#xA;						if (redX &lt; resolution.first / 2)&#xD;&#xA;							redsleft++;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;						else&#xD;&#xA;							redsright++;&#xD;&#xA;&#xD;&#xA;					}&#xD;&#xA;&#xD;&#xA;				}&#xD;&#xA;		&#xD;&#xA;&#xD;&#xA;			}&#xD;&#xA;			//if above threshold, call function to adjust &#xD;&#xA;			//else done&#xD;&#xA;&#xD;&#xA;		}	&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	}while (!done);&#xD;&#xA;	&#xD;&#xA;	glDrawBuffer(GL_BACK_LEFT);&#xD;&#xA;	display(0);&#xD;&#xA;	&#xD;&#xA;	glDrawBuffer(GL_BACK_RIGHT);&#xD;&#xA;	display(1);&#xD;&#xA;	&#xD;&#xA;	glutSwapBuffers();&#xD;&#xA;	glutPostRedisplay();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11098" PostHistoryTypeId="1" PostId="4726" RevisionGUID="7f437da7-bd64-437a-83f1-2492868d63eb" CreationDate="2017-02-16T04:26:53.823" UserId="5183" Text="OpenGL back and front buffer - counting and adjusting the number of red pixels before displaying to screen" ContentLicense="CC BY-SA 3.0" />
  <row Id="11099" PostHistoryTypeId="3" PostId="4726" RevisionGUID="7f437da7-bd64-437a-83f1-2492868d63eb" CreationDate="2017-02-16T04:26:53.823" UserId="5183" Text="|opengl|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11100" PostHistoryTypeId="2" PostId="4727" RevisionGUID="13762d18-538c-4734-b746-6d9d7de7925e" CreationDate="2017-02-16T05:44:46.617" UserId="5256" Text="If I want to use my own Ray Tracer in a program like 3DS Max to render geometry, how could I do this? Can someone explain to me what I need to do and where I can learn to use an SDK to make this happen? Is this worth it to render test scenes to compare and test my ray tracer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11101" PostHistoryTypeId="1" PostId="4727" RevisionGUID="13762d18-538c-4734-b746-6d9d7de7925e" CreationDate="2017-02-16T05:44:46.617" UserId="5256" Text="How to use my Ray Tracer in 3DS Max" ContentLicense="CC BY-SA 3.0" />
  <row Id="11102" PostHistoryTypeId="3" PostId="4727" RevisionGUID="13762d18-538c-4734-b746-6d9d7de7925e" CreationDate="2017-02-16T05:44:46.617" UserId="5256" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11103" PostHistoryTypeId="6" PostId="4726" RevisionGUID="ae83c07b-a398-4d1b-ac2e-d1c903afbfd9" CreationDate="2017-02-16T05:53:46.780" UserId="5183" Comment="edited tags" Text="|opengl|buffers|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11104" PostHistoryTypeId="6" PostId="4723" RevisionGUID="33a76e32-84b0-45c6-8977-79c644760165" CreationDate="2017-02-16T08:46:42.547" UserId="2479" Comment="Added the &quot;sampling&quot; tag" Text="|raytracing|lighting|global-illumination|sampling|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11105" PostHistoryTypeId="24" PostId="4723" RevisionGUID="33a76e32-84b0-45c6-8977-79c644760165" CreationDate="2017-02-16T08:46:42.547" Comment="Proposed by 2479 approved by 48, 209 edit id of 200" ContentLicense="CC BY-SA 3.0" />
  <row Id="11106" PostHistoryTypeId="5" PostId="4721" RevisionGUID="a4db02df-bdba-4964-88fb-2e432d3d647d" CreationDate="2017-02-16T08:46:57.793" UserId="506" Comment="better paper link—previous cited paper was an extension, not the main technique" Text="Take a look at [Valve's paper](http://valvesoftware.com/publications/2006/SIGGRAPH06_Course_ShadingInValvesSourceEngine.pdf) on combining Radiosity and Normal Mapping. It had a lot of useful insights.&#xD;&#xA;&#xD;&#xA;If I'm not mistaken, it looks to me like you're trying to compute normal mapping using the energy value at the texel that is a result of Radiosity - e.g. it came from all directions through almost-endless bumping around the room across thousands of surfaces. &#xD;&#xA;&#xD;&#xA;But your point light, for the normal mapping, has a very specific position, direction, distance and intensity. Meaning, you're combining apples and goats.&#xD;&#xA;&#xD;&#xA;What I believe you should do is:&#xD;&#xA;- compute the normal mapping separately for those surfaces&#xD;&#xA;- blend the GI solution with normal mapping&#xD;&#xA;- experiment with the blending factor till it looks 'good enough' for you" ContentLicense="CC BY-SA 3.0" />
  <row Id="11107" PostHistoryTypeId="24" PostId="4721" RevisionGUID="a4db02df-bdba-4964-88fb-2e432d3d647d" CreationDate="2017-02-16T08:46:57.793" Comment="Proposed by 506 approved by 2041, 209 edit id of 198" ContentLicense="CC BY-SA 3.0" />
  <row Id="11108" PostHistoryTypeId="2" PostId="4728" RevisionGUID="2fe3cbdf-b7f6-4beb-887c-b9cbcfa4d196" CreationDate="2017-02-16T10:06:05.250" UserId="6072" Text="I've difficulties in looking for an answer by myself because I don't know the jargon. I need somebody who'll points me in the right direction.&#xD;&#xA;&#xD;&#xA;Assume I have 100000 points with coordinates in the unit square, so points like (0.55313, 0.236831).&#xD;&#xA;&#xD;&#xA;I want to create a B/W picture with a given side in pixels (say 1000 x 1000) which shows these points.&#xD;&#xA;&#xD;&#xA;The naive approach is to multiply by the side the coordinates and round, so point (0.55313, 0.236831) becomes pixel (553, 237) and to turn pixel (553,237) on.&#xD;&#xA;&#xD;&#xA;This is rather unsatisfactory. If the points are many, say millions, I could easily fill all the area with a black blob that gives me 0 information.&#xD;&#xA;&#xD;&#xA;So, what I thought was to have an array 1000x1000 of floating point numbers that I can update somehow when I add a point, and at the end I can normalize the values and obtain a grayscale image, which will be &quot;blacker&quot; where more points are.&#xD;&#xA;&#xD;&#xA;**Now the question**: which algorithms are used to add a &quot;blurred&quot; point? I.e., I would like to take into account the real coordinates, so that, if a point is near the border of a &quot;pixel&quot; I would like its addition to my array to &quot;smudge&quot; a little the nearby pixels. Like when you draw a point in a drawing program and it actually adds a little disk with decreasing (linear? Gaussian?) intensity.&#xD;&#xA;&#xD;&#xA;Surely it is a problem that has been already been studied and solved, just I don't know how it is called...&#xD;&#xA;&#xD;&#xA;thanks&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11109" PostHistoryTypeId="1" PostId="4728" RevisionGUID="2fe3cbdf-b7f6-4beb-887c-b9cbcfa4d196" CreationDate="2017-02-16T10:06:05.250" UserId="6072" Text="Main techniques to draw a point at non integer coordinates?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11110" PostHistoryTypeId="3" PostId="4728" RevisionGUID="2fe3cbdf-b7f6-4beb-887c-b9cbcfa4d196" CreationDate="2017-02-16T10:06:05.250" UserId="6072" Text="|algorithm|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11111" PostHistoryTypeId="2" PostId="4729" RevisionGUID="915c4c51-b476-41af-83c4-a1e90cf92fa9" CreationDate="2017-02-16T11:10:17.193" UserId="137" Text="Instead of having a binary on/off per pixel you can instead make a heat map. The more points fall within the pixel the brighter the pixel is. Essentially create a 2D histogram which you then renormalize to get the grayscale for the output.&#xD;&#xA;&#xD;&#xA;If you want to blur the points then you can move a portion of the brightness to the next pixel based on the remaining fraction after multiplying to the resolution. If it the coordinate is `(0.55313, 0.236831)` and your resolution is 1000x1000 then `0.87*0.17` goes to `553, 236`, `0.87*0.83` goes to `553, 237`, `0.13*0.17` goes to `554, 236` and `0.13*0.83` goes to `554, 237`. This is distributed linearly but there are other options." ContentLicense="CC BY-SA 3.0" />
  <row Id="11113" PostHistoryTypeId="2" PostId="4730" RevisionGUID="6a3df274-6cba-490a-aa49-30c328cfcde8" CreationDate="2017-02-16T16:47:12.630" UserId="2041" Text="You can do this by writing a renderer plugin for 3ds Max. This gives you the same kind of access as the built-in renderers, including a settings dialog, a preview window, and an interface where you can write the final frame of a full render (and 3ds Max will write it to the output file). The renderer plugin gets full access to the scene graph when the user hits &quot;Render&quot; (or when the preview window is in use). Any complex geometry (such as subdivision surfaces) will already have been converted to a triangle mesh for you.&#xD;&#xA;&#xD;&#xA;PaulHK already linked the official [*Programmers' Guide*](http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/index.html?url=files/GUID-40ED5D02-BBCF-4EE3-9EE7-E59425B49CBB.htm,topicNumber=d30e2631) online. You'll also find it in the help files that are installed with 3ds Max, along with sample source code for a trivial renderer plugin. Because your plugin needs to link against the 3ds Max SDK, you'll need to compile it with the same version of Microsoft Visual Studio that was used to compile the particular version of 3ds Max you're targeting. (This means that if you want to target multiple versions of 3ds Max, you might need multiple builds.) Again, how to do this is described in the Programmers' Guide." ContentLicense="CC BY-SA 3.0" />
  <row Id="11114" PostHistoryTypeId="2" PostId="4731" RevisionGUID="c77f2999-6301-48d1-ad83-a0f63208de8d" CreationDate="2017-02-16T18:33:37.293" UserId="6074" Text="[![enter image description here][1]][1]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/FL0Xn.jpg&#xA;Download this picture and see it as a thumbnail, like in whatsapp or your phone gallery and you'll find that it shows another picture in the thumbnail or you can simply do some changes in color, or do some filters on it using PicsArt and you'll notice the difference.  I've searched the whole internet, but haven't got the answer yet.&#xA;Please explain how is this happening. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11115" PostHistoryTypeId="1" PostId="4731" RevisionGUID="c77f2999-6301-48d1-ad83-a0f63208de8d" CreationDate="2017-02-16T18:33:37.293" UserId="6074" Text="Why thumbnail shows just another pic?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11116" PostHistoryTypeId="3" PostId="4731" RevisionGUID="c77f2999-6301-48d1-ad83-a0f63208de8d" CreationDate="2017-02-16T18:33:37.293" UserId="6074" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11117" PostHistoryTypeId="2" PostId="4732" RevisionGUID="7aa24f91-63f7-441d-a16e-89dc31c3be67" CreationDate="2017-02-16T21:03:22.210" UserId="6001" Text="In the end, what I gleaned from the Valve paper, and what I found in an existing light mapper implementation, led me to the following conclusion:&#xD;&#xA;&#xD;&#xA;When performing my final global illumination integration, instead of using a cosine-weighted hemisphere of samples, use a uniform hemisphere of samples. For each sample, project the sample's direction on each of the three basis vectors, scaling the sample colour by the resulting projection. The three sums are accumulated, and then divided by the number of samples. At runtime, the normal map is projected onto the basis and the contributing lightmap colour for each basis is scaled by the projection prior to accumulating.&#xD;&#xA;&#xD;&#xA;    Color3 basisSum[3] = { 0, 0, 0 };&#xD;&#xA;&#xD;&#xA;    for ( each sample in hemisphere... )&#xD;&#xA;    {&#xD;&#xA;      Color3 colour = trace_sample(sample);&#xD;&#xA;&#xD;&#xA;      for ( int b = 0; b &lt; 3; b++ )&#xD;&#xA;      {&#xD;&#xA;        float dot = Dot( sample.directionTS, basisTS[b] ); // both in tangent space&#xD;&#xA;        basisSum[b] += colour * dot;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    for ( int b = 0; b &lt; 3; b++ )&#xD;&#xA;    {&#xD;&#xA;      basisSum[b] /= numSamples;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I made no special case handling for clamping the back-side of the basis in the tool - my experiments and research lead me to conclude that the entire hemisphere should be represented for each basis, even if intuitively the backwards-facing samples seem like they would 'subtract' colour because of a negative dot product.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11119" PostHistoryTypeId="2" PostId="4733" RevisionGUID="a53b32d3-b1e7-4cd2-bde4-8061d61ca61a" CreationDate="2017-02-17T11:01:58.830" UserId="2041" Text="You can't see it in the image you uploaded because it's a JPEG, but PNG files which have a full alpha channel can do the trick you mentioned. It works with websites or apps where the &quot;thumbnail&quot; image is displayed on a white background and the &quot;full&quot; image is displayed on a black background. In the thumbnail display, white pixels and completely transparent pixels look the same, because of the white background; in the full image, black pixels and completely transparent pixels look the same.&#xD;&#xA;&#xD;&#xA;Thus, you can have a white-on-black picture and a black-on-white picture in the same image, and the background hides one of the two images. You can easily see what's going on if you look at the image against a background of some other colour." ContentLicense="CC BY-SA 3.0" />
  <row Id="11123" PostHistoryTypeId="5" PostId="4731" RevisionGUID="395adb78-dbe3-46e4-beb8-01172f310935" CreationDate="2017-02-18T14:46:14.697" UserId="6074" Comment="added 211 characters in body; deleted 41 characters in body; deleted 1 character in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FL0Xn.jpg&#xD;&#xA;Download this picture and see it as a thumbnail, like in whatsapp or your phone gallery and you'll find that it shows another picture in the thumbnail.&#xD;&#xA;&#xD;&#xA; *If you can't see the thumbnail:*&#xD;&#xA;You can simply do some changes in color, or do some filters on it using PicsArt and you'll notice the difference.  I've searched the whole internet, but haven't got the answer yet.&#xD;&#xA;Please explain how is this happening. &#xD;&#xA;&#xD;&#xA;**Note:** I know about the trick with PNG files, but this is a JPEG file and the trick works with this too.&#xD;&#xA;I added a video to elaborate." ContentLicense="CC BY-SA 3.0" />
  <row Id="11124" PostHistoryTypeId="5" PostId="4731" RevisionGUID="469650ad-9e9a-4a40-9bae-d04ebf0859cd" CreationDate="2017-02-18T14:57:02.013" UserId="6074" Comment="added 44 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Download this picture and see it as a thumbnail, like in whatsapp or your phone gallery and you'll find that it shows another picture in the thumbnail.&#xD;&#xA;&#xD;&#xA; *If you can't see the thumbnail:*&#xD;&#xA;You can simply do some changes in color, or do some filters on it using PicsArt and you'll notice the difference.  I've searched the whole internet, but haven't got the answer yet.&#xD;&#xA;Please explain how is this happening. &#xD;&#xA;&#xD;&#xA;**Note:** I know about the trick with PNG files, but this is a JPEG file and the trick works with this too.&#xD;&#xA;I added [video][2] a to elaborate.&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/FL0Xn.jpg&#xA;  [2]: https://youtu.be/j6gFEULzAdE" ContentLicense="CC BY-SA 3.0" />
  <row Id="11126" PostHistoryTypeId="2" PostId="4735" RevisionGUID="97e4642a-576f-4ffd-9d76-03954d8656ae" CreationDate="2017-02-18T22:57:13.080" UserId="6085" Text="So i'm currently trying to draw a 3D cube, and from what I understand everything should be working right, but It's coming out weird and I believe it's because the ordering of my indexes is wrong. Is there any way to view what vertex is associated with an index? for instance something along the lines of&#xD;&#xA;&#xD;&#xA;    print(index[5]);&#xD;&#xA;&#xD;&#xA;that would output something along the lines of:&#xD;&#xA;   &#xD;&#xA;    index[5]: (0.5, 0.5, 0.5)&#xD;&#xA;&#xD;&#xA;Is this possible at all? or at least to view it in a debugger?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11127" PostHistoryTypeId="1" PostId="4735" RevisionGUID="97e4642a-576f-4ffd-9d76-03954d8656ae" CreationDate="2017-02-18T22:57:13.080" UserId="6085" Text="View / print index values?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11128" PostHistoryTypeId="3" PostId="4735" RevisionGUID="97e4642a-576f-4ffd-9d76-03954d8656ae" CreationDate="2017-02-18T22:57:13.080" UserId="6085" Text="|webgl|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11129" PostHistoryTypeId="2" PostId="4736" RevisionGUID="b7c9257c-9ba6-4ebf-836d-13149a4cafee" CreationDate="2017-02-19T04:11:31.440" UserId="6089" Text="Vectorizing continuous tone images is often met with color palette reduction and visual artifacts. Half-tone images, on the hand, have constant patterns in their tones, which would intuitively lead to the conclusion that these images can be vectorized with greater success, if without any visual artifacts at all.&#xD;&#xA;   Failing to find any sufficient comparisons against vectorizing continuous tone images and half-tone images on separate research, I now pose this: **What behaviors occur during vectorization of &quot;raster&quot; half-tone images?**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11130" PostHistoryTypeId="1" PostId="4736" RevisionGUID="b7c9257c-9ba6-4ebf-836d-13149a4cafee" CreationDate="2017-02-19T04:11:31.440" UserId="6089" Text="Vectorizing half tone images" ContentLicense="CC BY-SA 3.0" />
  <row Id="11131" PostHistoryTypeId="3" PostId="4736" RevisionGUID="b7c9257c-9ba6-4ebf-836d-13149a4cafee" CreationDate="2017-02-19T04:11:31.440" UserId="6089" Text="|vector-graphics|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11132" PostHistoryTypeId="2" PostId="4737" RevisionGUID="35f78cf6-481b-467b-9eca-6cf8c32f80e3" CreationDate="2017-02-19T16:39:03.550" UserId="5513" Text="My lecturer is complete trash. This type of question has come up in the exam the last three years. How do I answer this. Please help.&#xD;&#xA;&#xD;&#xA;For a 3D scene in the World Coordinates, its View Reference Point (VRP) is at (5,-2,1), and a viewer is looking towards point A(1,1,1). Construct a transform matrix which will map World Coordinate points to a right-handed (UVN) viewing space, so that VRP is the origin, the line joining VRP to A is the positive N axis, and the View-Up Vector is (0,0,1)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11133" PostHistoryTypeId="1" PostId="4737" RevisionGUID="35f78cf6-481b-467b-9eca-6cf8c32f80e3" CreationDate="2017-02-19T16:39:03.550" UserId="5513" Text="How to answer this question?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11134" PostHistoryTypeId="3" PostId="4737" RevisionGUID="35f78cf6-481b-467b-9eca-6cf8c32f80e3" CreationDate="2017-02-19T16:39:03.550" UserId="5513" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11135" PostHistoryTypeId="4" PostId="4737" RevisionGUID="5a8a86ad-352b-4e2a-a2d7-bda7613c3800" CreationDate="2017-02-19T19:05:05.143" UserId="2654" Comment="edited title" Text="Building view transform matrices" ContentLicense="CC BY-SA 3.0" />
  <row Id="11136" PostHistoryTypeId="5" PostId="4737" RevisionGUID="536f80f8-4b07-4c79-ae92-e29431ac3e26" CreationDate="2017-02-19T19:56:28.970" UserId="231" Comment="Remove abuse, redundancy, and &quot;please help&quot;" Text="For a 3D scene in the World Coordinates, its View Reference Point (VRP) is at (5,-2,1), and a viewer is looking towards point A(1,1,1). Construct a transform matrix which will map World Coordinate points to a right-handed (UVN) viewing space, so that VRP is the origin, the line joining VRP to A is the positive N axis, and the View-Up Vector is (0,0,1)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11138" PostHistoryTypeId="5" PostId="4722" RevisionGUID="37fabc8b-3664-4007-a374-b72d8b4d6a59" CreationDate="2017-02-19T21:12:23.263" UserId="231" Comment="Minor typos and applying assumed intended formating" Text="After z buffer testing does the fragment shader run or not for the discarded fragment?  &#xD;&#xA;Or  &#xD;&#xA;Does the z test happen after the fragment shader runs?&#xD;&#xA;&#xD;&#xA;Please, tell me the step by step events that occur in the z test.&#xD;&#xA;&#xD;&#xA;Also what is early z test and how to achieve it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11139" PostHistoryTypeId="5" PostId="4676" RevisionGUID="516e9491-6584-466a-a372-7f87512f0fe4" CreationDate="2017-02-19T21:28:53.673" UserId="231" Comment="Remove &quot;thanks&quot; and add in additional thoughts that were posted as an answer" Text="I am making an iOS game using Unity. I am testing some shaders that I have made for the game, and in some cases the device will run at under 30 FPS but not have 100% device utilization.&#xD;&#xA;&#xD;&#xA;Sometimes a test will start at a higher device utilization %, and then over time go lower, even though the test is simply rendering a plane with a material on it.&#xD;&#xA;&#xD;&#xA;For example, a shader test I just ran on an iPad 4: Device utilization 85% Renderer utilization 85% Tiler utilization 1% Core Animation Frames Per Second 12&#xD;&#xA;&#xD;&#xA;This test is using barely any CPU, and is only rendering 4 triangles (2 big planes covering the screen).&#xD;&#xA;&#xD;&#xA;Does anyone have any ideas why this could be happening? Usually the renderer utilization goes up to 100%... pretty stumped, being a graphics rookie.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;IOS has mandatory v-sync. I am curious why the &quot;Core Animation Frames Per Second&quot; in the Instruments profiler would say 12 FPS if v-sync is enabled, and how that would correspond to the 85% device utilization.&#xD;&#xA;&#xD;&#xA;Perhaps the device is rendering 12 frames, and 2 are dropped to get it down to the v-synced frame rate of 10? That would result in ~83-84% effective device utilization.&#xD;&#xA;&#xD;&#xA;Or perhaps it is that given the above stats (85% utilization and 12 FPS), the GPU could render 14 FPS if at 100% usage. However v-sync requires either 10, or 15 FPS, nothing in between. This may result in the GPU slowing down, to not waste power and CPU, but still remain safely above the next step down on v-sync." ContentLicense="CC BY-SA 3.0" />
  <row Id="11151" PostHistoryTypeId="2" PostId="4740" RevisionGUID="b4123cc5-b333-421d-b05e-72dd786e579c" CreationDate="2017-02-21T00:32:20.080" UserId="6099" Text="I apologize in advance for the long question...&#xD;&#xA;&#xD;&#xA;I am working on a &quot;CAD&quot; like program in HTML5 that requires drawing many thousands (700,000+) of images on the screen. I think, &quot;fortunately&quot; the many images are replicated uses of a unique set of images. The unique set is many orders of magnitudes less than the instances of them. One example I am working with has 700,000+ instances of a 360 unique set of images. The images are actually generated on the fly when the program first loads and they are rectangles with the &quot;name&quot; of the image centered about the middle of the rectangle (no color within the rectange, etc...just a rectangle outline with the text in the middle, text and rectangle outline is black). The program should be able to display the images at many magnification levels, and of course, be fast enough for it to be useful.&#xD;&#xA;&#xD;&#xA;A first implementation worked well with SVG images loaded. Due to the vector aspect of the images, it worked nicely at all magnifications. But after about 70,000 or so instances the program started to run out of memory. I assume because the DOM is not able to keep up with so many instances...&#xD;&#xA;&#xD;&#xA;After a lot of studying and experimentation, I was able to implement a working version of the program using WebGL. It works pretty well, and it is fast. I know I will have to implement all the fun things I got from SVG for free, like css colors, listeners, individual elements in the DOM, etc, but I was not using a lot of that anyhow.&#xD;&#xA;&#xD;&#xA;So far I've been able to implement a system that can render a lot of different instances of a subset of rectangles using a shape atlas with 1 texture and then using the standard technique of passing the texture coordinates to the pixel shader for rendering. This worked OK, except that the strings in the center of the atlas shape did not look too good at all magnifications. For the program to be most useful, I need to be able to display the strings clearly. Generating the rectangle atlases form a canvas 2d, even at high resolutions, with the strings as part of the atlas rectangles, while quite straight forward to do, did not seem to render well at all magnifications. I looked into generating string atlases by themselves, which is fine, but it seems to me that I should be able to create an image atlas that can display pretty well at a reasonable number of magnifications including the text, and perhaps save a bunch of unique draw calls for simply generating the text using Signed Distance Fields.&#xD;&#xA;&#xD;&#xA;This is where I have hit a wall... I found a few places that reference this paper -&gt; Improved Alpha-Tested Magnification for Vector Textures and Special Effects . It seems exactly what I am looking for. I think of my unique set of rectangle, text pairs as &quot;decals&quot; as outlined in the paper above. In my case, I would have all my unique instances generate a lower resolution SDF version (64x64) of a high resolution version (2048x2048) of the instances and then change my fragment shader to be able to render at any resolution as outlined here -&gt; Drawing Text with Signed Distance Fields in Mapbox GL. However, I have not found anywhere that shows how to generate a lower resolution version SDF from a high resolution image.&#xD;&#xA;&#xD;&#xA;My question(s) is (are) the following:&#xD;&#xA;&#xD;&#xA;1) How do I generate a lower resolution SDF version (64x64) of a hi-res image (2048x2048) generated on the fly using canvas and javascript so I can create a texture to use in my fragment shader? Ideally, this would only have to be generated once at the start of the program.&#xD;&#xA;&#xD;&#xA;2) Am I thinking about his correctly? Is the text doomed to have to be drawn by itself separately using an SDF font atlas?&#xD;&#xA;&#xD;&#xA;Thanks, Jose&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11152" PostHistoryTypeId="1" PostId="4740" RevisionGUID="b4123cc5-b333-421d-b05e-72dd786e579c" CreationDate="2017-02-21T00:32:20.080" UserId="6099" Text="Creating Signed Distance Fields Images On The Fly For WebGL Application" ContentLicense="CC BY-SA 3.0" />
  <row Id="11153" PostHistoryTypeId="3" PostId="4740" RevisionGUID="b4123cc5-b333-421d-b05e-72dd786e579c" CreationDate="2017-02-21T00:32:20.080" UserId="6099" Text="|webgl|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11154" PostHistoryTypeId="2" PostId="4741" RevisionGUID="5e981edf-ca7c-4093-94e1-b0ec18edc760" CreationDate="2017-02-21T00:47:10.527" UserId="6100" Text="I have a (2d) region defined as a list of vertices that I'm currently drawing as a line loop in opengl. I want to draw this region solidly. I started by using triangle fan, but that doesn't work if the region has vertices positioned at the same angle (relative to the center) but different radii, because then that whole region is draw solid.&#xD;&#xA;&#xD;&#xA;So, I think I just need some general method to convert an enclosed spline/list of points into a triangle mesh. Maybe there's a better way?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11155" PostHistoryTypeId="1" PostId="4741" RevisionGUID="5e981edf-ca7c-4093-94e1-b0ec18edc760" CreationDate="2017-02-21T00:47:10.527" UserId="6100" Text="Turn an enclosed region into a triangle mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="11156" PostHistoryTypeId="3" PostId="4741" RevisionGUID="5e981edf-ca7c-4093-94e1-b0ec18edc760" CreationDate="2017-02-21T00:47:10.527" UserId="6100" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11157" PostHistoryTypeId="2" PostId="4742" RevisionGUID="33bd20fa-e2d0-4a46-a305-877d21a75106" CreationDate="2017-02-21T01:25:21.483" UserId="48" Text="If the number of vertices is not too large, I would suggest looking into &quot;ear clipping&quot;. It's a straightforward method to triangulate possibly-concave polygons, as long as they don't have holes. However, it's $O(n^2)$ in the number of vertices, so may not a great choice if you need to handle a large number of verts. Dave Eberly has [a paper on ear clipping](https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf) and also [an open-source implementation in C++](https://www.geometrictools.com/Source/ComputationalGeometry.html). There are many other links available on the web, too.&#xD;&#xA;&#xD;&#xA;The basic idea is to find an &quot;ear&quot; of the polygon, which is defined as a triangular subset of the polygon, formed by three consecutive vertices of the polygon. Once you find an ear, you add it to the output triangle list, and remove it from the original polygon (which reduces the number of vertices by one). Repeat this until the polygon is gone.&#xD;&#xA;&#xD;&#xA;The reason it's $O(n^2)$ is that you have to repeatedly search the list of vertices to find another ear to remove. There are more efficient triangulation algorithms as well, but they're more difficult to implement." ContentLicense="CC BY-SA 3.0" />
  <row Id="11158" PostHistoryTypeId="2" PostId="4743" RevisionGUID="3744d7a5-c117-4e04-b48a-a819f755b2f7" CreationDate="2017-02-21T12:16:05.027" UserId="209" Text="Since you say you're using opengl, as an alternative to Nathan's suggestion of using a triangulation algorithm&lt;sup&gt;++&lt;/sup&gt;, you could use the stencil buffer. Assuming you want odd/even fill, clear the stencil buffer, dice up your polygon as before but have your triangles just (IIRC) invert the stencil. When all are sent, draw again but only where the stencil is non-zero. (It's been a while but I think you can clear the stencil buffer at the same time as this second pass to save time on the next complex polygon.)&#xD;&#xA;&#xD;&#xA;The stencil buffer approach should also work with self-intersecting polygons.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;++&lt;/sup&gt; Though, if you do want to use a triangulation algorithm but have a very large number of vertices, you could try Seidel's method as it's 'relatively' easy to implement but with *nearly* O(n) time complexity. However if you do a search for Seidel, note that the code in http://www.cs.unc.edu/%7Edm/CODE/GEM/chapter.html is *not* actually Seidel's method as theirs is only O(N log N) not the much faster O(N log* N)." ContentLicense="CC BY-SA 3.0" />
  <row Id="11159" PostHistoryTypeId="5" PostId="4743" RevisionGUID="f3677321-9d81-4458-8389-537581b5e509" CreationDate="2017-02-21T12:22:28.607" UserId="209" Comment="added 217 characters in body" Text="Since you say you're using opengl, as an alternative to Nathan's suggestion of using a triangulation algorithm&lt;sup&gt;++&lt;/sup&gt;, you could use the stencil buffer. Assuming you want odd/even fill, clear the stencil buffer, dice up your polygon as before but have your triangles just (IIRC) invert the stencil. When all are sent, draw again but only where the stencil is non-zero. (It's been a while but I think you can clear the stencil buffer at the same time as this second pass to save time on the next complex polygon.)&#xD;&#xA;&#xD;&#xA;The stencil buffer approach should also work with self-intersecting polygons.&#xD;&#xA;&#xD;&#xA;One final thing, I think it is more fill-efficient if you use a triangle strip rather than a fan when you chop up your polygon. You just need to access your vertices in something like  0, 1, N-1, 2, N-2 etc. order&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;++&lt;/sup&gt; Though, if you do want to use a triangulation algorithm but have a very large number of vertices, you could try Seidel's method as it's 'relatively' easy to implement but with *nearly* O(n) time complexity. However if you do a search for Seidel, note that the code in http://www.cs.unc.edu/%7Edm/CODE/GEM/chapter.html is *not* actually Seidel's method as theirs is only O(N log N) not the much faster O(N log* N)." ContentLicense="CC BY-SA 3.0" />
  <row Id="11160" PostHistoryTypeId="5" PostId="4743" RevisionGUID="b0bf52ef-d4c9-4b6d-9caa-451df97def17" CreationDate="2017-02-21T13:11:58.547" UserId="209" Comment="added 303 characters in body" Text="Since you say you're using opengl, as an alternative to Nathan's suggestion of using a triangulation algorithm&lt;sup&gt;++&lt;/sup&gt;, you could use the stencil buffer. Assuming you want odd/even fill, clear the stencil buffer, dice up your polygon as before but have your triangles just (IIRC) invert the stencil. When all are sent, draw again but only where the stencil is non-zero. (It's been a while but I think you can clear the stencil buffer at the same time as this second pass to save time on the next complex polygon.)&#xD;&#xA;&#xD;&#xA;The stencil buffer approach should also work with self-intersecting polygons.&#xD;&#xA;&#xD;&#xA;One final thing, I think it is more fill-efficient if you use a triangle strip rather than a fan when you chop up your polygon. You just need to access your vertices in something like  0, 1, N-1, 2, N-2 etc. order&#xD;&#xA;&#xD;&#xA;More information on the stencil buffer can be found in [OpenGL Stencil Tests][1] and in [Drawing Filled, Concave Polygons Using the Stencil Buffer][2]&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;++&lt;/sup&gt; Though, if you do want to use a triangulation algorithm but have a very large number of vertices, you could try Seidel's method as it's 'relatively' easy to implement but has *nearly* O(n) time complexity. However if you do a search for Seidel, note that the code in [Narkhede &amp;&#xD;&#xA;Manocha][3] is *not* actually Seidel's method as theirs is only O(N log N) not the faster O(N log* N).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Stencil_Test&#xD;&#xA;  [2]: http://www.glprogramming.com/red/chapter14.html#name13&#xD;&#xA;  [3]: http://www.cs.unc.edu/%7Edm/CODE/GEM/chapter.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="11161" PostHistoryTypeId="5" PostId="4743" RevisionGUID="782d3068-809e-480e-aa88-ac883f5ed160" CreationDate="2017-02-21T15:04:56.410" UserId="209" Comment="added 58 characters in body" Text="If your aim is just to fill the region and since you say you're using opengl, an alternative to Nathan's suggestion of using a triangulation algorithm&lt;sup&gt;++&lt;/sup&gt;, is to use the stencil buffer. &#xD;&#xA;&#xD;&#xA;Assuming you want odd/even fill, clear the stencil buffer, dice up your polygon as before but have your triangles just (IIRC) invert the stencil. When all are sent, draw again but only where the stencil is non-zero. (It's been a while but I think you can clear the stencil buffer at the same time as this second pass to save time on the next complex polygon.)&#xD;&#xA;&#xD;&#xA;The stencil buffer approach should also work with self-intersecting polygons.&#xD;&#xA;&#xD;&#xA;One final thing, I think it is more fill-efficient if you use a triangle strip rather than a fan when you chop up your polygon. You just need to access your vertices in something like  0, 1, N-1, 2, N-2 etc. order&#xD;&#xA;&#xD;&#xA;More information on the stencil buffer can be found in [OpenGL Stencil Tests][1] and in [Drawing Filled, Concave Polygons Using the Stencil Buffer][2]&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;++&lt;/sup&gt; Though, if you do want to use a triangulation algorithm but have a very large number of vertices, you could try Seidel's method as it's 'relatively' easy to implement but has *nearly* O(n) time complexity. However if you do a search for Seidel, note that the code in [Narkhede &amp;&#xD;&#xA;Manocha][3] is *not* actually Seidel's method as theirs is only O(N log N) not the faster O(N log* N) you should expect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Stencil_Test&#xD;&#xA;  [2]: http://www.glprogramming.com/red/chapter14.html#name13&#xD;&#xA;  [3]: http://www.cs.unc.edu/%7Edm/CODE/GEM/chapter.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="11162" PostHistoryTypeId="5" PostId="4740" RevisionGUID="b43f9bac-dc30-4b85-a3cc-3de3a9beabc5" CreationDate="2017-02-21T17:06:23.563" UserId="231" Comment="Remove &quot;thanks&quot; and apology (question is not too long) and minor typos and formating" Text="I am working on a &quot;CAD&quot; like program in HTML5 that requires drawing many thousands (700,000+) of images on the screen. I think, &quot;fortunately&quot; the many images are replicated uses of a unique set of images. The unique set is many orders of magnitude less than the instances of them. One example I am working with has 700,000+ instances from a set of 360 unique images. The images are actually generated on the fly when the program first loads and they are rectangles with the &quot;name&quot; of the image centered about the middle of the rectangle (no color within the rectangle, etc... just a rectangle outline with the text in the middle, text and rectangle outline is black). The program should be able to display the images at many magnification levels, and of course, be fast enough for it to be useful.&#xD;&#xA;&#xD;&#xA;A first implementation worked well with SVG images loaded. Due to the vector aspect of the images, it worked nicely at all magnifications. But after about 70,000 or so instances the program started to run out of memory. I assume because the DOM is not able to keep up with so many instances...&#xD;&#xA;&#xD;&#xA;After a lot of studying and experimentation, I was able to implement a working version of the program using WebGL. It works pretty well, and it is fast. I know I will have to implement all the fun things I got from SVG for free, like CSS colors, listeners, individual elements in the DOM, etc, but I was not using a lot of that anyhow.&#xD;&#xA;&#xD;&#xA;So far I've been able to implement a system that can render a lot of different instances of a subset of rectangles using a shape atlas with 1 texture and then using the standard technique of passing the texture coordinates to the pixel shader for rendering. This worked OK, except that the strings in the center of the atlas shape did not look too good at all magnifications. For the program to be most useful, I need to be able to display the strings clearly. Generating the rectangle atlases from a canvas 2d, even at high resolutions, with the strings as part of the atlas rectangles, while quite straight forward to do, did not seem to render well at all magnifications. I looked into generating string atlases by themselves, which is fine, but it seems to me that I should be able to create an image atlas that can display pretty well at a reasonable number of magnifications including the text, and perhaps save a bunch of unique draw calls for simply generating the text using Signed Distance Fields.&#xD;&#xA;&#xD;&#xA;This is where I have hit a wall... I found a few places that reference the paper &quot;Improved Alpha-Tested Magnification for Vector Textures and Special Effects&quot;. It seems exactly what I am looking for. I think of my unique set of rectangle, text pairs as &quot;decals&quot; as outlined in the paper above. In my case, I would have all my unique instances generate a lower resolution SDF version (64x64) of a high resolution version (2048x2048) of the instances and then change my fragment shader to be able to render at any resolution as outlined here -&gt; Drawing Text with Signed Distance Fields in Mapbox GL. However, I have not found anywhere that shows how to generate a lower resolution version SDF from a high resolution image.&#xD;&#xA;&#xD;&#xA;My questions are the following:&#xD;&#xA;&#xD;&#xA;1. How do I generate a lower resolution SDF version (64x64) of a hi-res image (2048x2048) generated on the fly using canvas and JavaScript so I can create a texture to use in my fragment shader? Ideally, this would only have to be generated once at the start of the program.&#xD;&#xA;&#xD;&#xA;2. Am I thinking about his correctly? Is the text doomed to have to be drawn by itself separately using an SDF font atlas?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11163" PostHistoryTypeId="2" PostId="4744" RevisionGUID="e0f0083b-4b4b-4442-aff2-50a6ca2d627c" CreationDate="2017-02-21T21:13:30.893" UserId="4991" Text="I am starting to learn WebGL. Can a scene graph be stored in the GPU? Or is that type of thing more for the main thread (or webworker)?&#xD;&#xA;&#xD;&#xA;For example, I want to calculate some layout, and apply it as a transform matrix. Can I keep track of a scene graph node in the GPU over time, and modify it's properties over time?&#xD;&#xA;&#xD;&#xA;I'm just wondering because I know the GPU architecture is different. Do people normally do scene graph stuff outside the GPU? Can it be done in the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11164" PostHistoryTypeId="1" PostId="4744" RevisionGUID="e0f0083b-4b4b-4442-aff2-50a6ca2d627c" CreationDate="2017-02-21T21:13:30.893" UserId="4991" Text="Can a scene graph be stored in the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11165" PostHistoryTypeId="3" PostId="4744" RevisionGUID="e0f0083b-4b4b-4442-aff2-50a6ca2d627c" CreationDate="2017-02-21T21:13:30.893" UserId="4991" Text="|transformations|gpu|webgl|javascript|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11169" PostHistoryTypeId="2" PostId="4746" RevisionGUID="5873e4cc-2f6c-47b9-97d4-ae88c87f52d5" CreationDate="2017-02-22T00:06:54.373" UserId="137" Text="A gpu only cares about the full transform used for a particular object. It's much better that the CPU (webworker) collates the transformation hierarchy into a single matrix.&#xD;&#xA;&#xD;&#xA;What you can do is use UBO and create a block where the final transform is stored and as you traverse the scenegraph update the data on the gpu. In the vertex shader you then index into it to get the data that applies to the vertexes. But you shouldn't store graph data in there only the final data needed for rendering." ContentLicense="CC BY-SA 3.0" />
  <row Id="11170" PostHistoryTypeId="2" PostId="4747" RevisionGUID="f3a61b8b-8676-4e57-a4af-2a93ca94d323" CreationDate="2017-02-22T00:10:33.493" UserId="2941" Text="Have you access to the OpenGL utility library? If so, you could use the tesselation functions from that. See http://www.glprogramming.com/red/chapter11.html#name1" ContentLicense="CC BY-SA 3.0" />
  <row Id="11171" PostHistoryTypeId="2" PostId="4748" RevisionGUID="d7ee9ec8-a3d1-424f-8fb3-ca0a6b2db434" CreationDate="2017-02-22T01:56:03.817" UserId="2448" Text="We know that in PNG,BMP,etc... the pixel value stored is not in the linear RGB space. But I found no document saying anything about the alpha channel. Is the alpha channel stored in image files in linear space or not?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11172" PostHistoryTypeId="1" PostId="4748" RevisionGUID="d7ee9ec8-a3d1-424f-8fb3-ca0a6b2db434" CreationDate="2017-02-22T01:56:03.817" UserId="2448" Text="Should the alpha channel be gamma corrected" ContentLicense="CC BY-SA 3.0" />
  <row Id="11173" PostHistoryTypeId="3" PostId="4748" RevisionGUID="d7ee9ec8-a3d1-424f-8fb3-ca0a6b2db434" CreationDate="2017-02-22T01:56:03.817" UserId="2448" Text="|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11174" PostHistoryTypeId="2" PostId="4749" RevisionGUID="cb919093-157e-4d75-a95c-dc30f91fcee5" CreationDate="2017-02-22T02:08:18.270" UserId="2448" Text="Short answer: Yes, It can be done. But no one do so.&#xD;&#xA;&#xD;&#xA;Long answer: &#xD;&#xA;Scene graphs can be stored and processed on a GPU using OpenCL/WebCL. But it is not piratical to do so. Updating scene graphs(a tree not in flat memory) on a GPU is slow. And procession it on a GPU is also slow (again, the tree is not in flat memory). While computing transformation matrices are cheep on a CPU. Thus no one is doing this.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11175" PostHistoryTypeId="2" PostId="4750" RevisionGUID="71605ad8-b2b2-4f27-9c74-1b0a2ca81df6" CreationDate="2017-02-22T02:42:03.827" UserId="2707" Text="It is generally linear. The alpha channel doesn't get displayed, but it is generally a non-color term used for transparency (or whatever else). Because they don't need to display on a monitor, there's no reason to store in in gamma space. [Normals maps follow a similar line of reasoning][1].&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/3842/why-shouldnt-bump-normal-and-displacement-maps-be-gamma-corrected?rq=1" ContentLicense="CC BY-SA 3.0" />
  <row Id="11176" PostHistoryTypeId="5" PostId="4750" RevisionGUID="c8901a50-034c-4dc3-8832-036c5e19f3b5" CreationDate="2017-02-22T02:49:27.110" UserId="2707" Comment="added 388 characters in body" Text="&gt; We know that in PNG,BMP,etc... the pixel value stored is not in the linear RGB space.&#xD;&#xA;&#xD;&#xA;This is not necessarily true. You can store whatever color space you want into an image, it doesn't even need to be colors (such as normal maps).&#xD;&#xA;&#xD;&#xA;The alpha channel is generally linear. The alpha channel doesn't get displayed, but it is generally a non-color term used for transparency (or whatever else). Because they don't need to display on a monitor, there's no reason to store in in gamma space. If you did, you would unnecessarily lose precision at the lower end of the alpha values. [Normals maps follow a similar line of reasoning, as explained very well by Julien Guertault][1].&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/3842/why-shouldnt-bump-normal-and-displacement-maps-be-gamma-corrected?rq=1" ContentLicense="CC BY-SA 3.0" />
  <row Id="11177" PostHistoryTypeId="2" PostId="4751" RevisionGUID="fd0b9665-bc32-4e2b-ae33-039ab5a1c149" CreationDate="2017-02-22T03:30:47.747" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="11178" PostHistoryTypeId="1" PostId="4751" RevisionGUID="fd0b9665-bc32-4e2b-ae33-039ab5a1c149" CreationDate="2017-02-22T03:30:47.747" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="11179" PostHistoryTypeId="2" PostId="4752" RevisionGUID="c5e2550a-6c06-4dd3-8e87-30d0e973c459" CreationDate="2017-02-22T03:30:47.747" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="11180" PostHistoryTypeId="1" PostId="4752" RevisionGUID="c5e2550a-6c06-4dd3-8e87-30d0e973c459" CreationDate="2017-02-22T03:30:47.747" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="11183" PostHistoryTypeId="5" PostId="4749" RevisionGUID="8655a31c-217d-4a59-8085-7b24abec3ce6" CreationDate="2017-02-22T08:13:08.287" UserId="48" Comment="spelling &amp; grammar" Text="Short answer: Yes, It can be done. But no one does so.&#xD;&#xA;&#xD;&#xA;Long answer: &#xD;&#xA;Scene graphs can be stored and processed on a GPU using OpenCL/WebCL. But it is not practical to do so. Updating scene graphs (a tree not in flat memory) on a GPU is slow, and processing it on a GPU is also slow (again, the tree is not in flat memory), while computing transformation matrices is cheap on a CPU. Thus no one is doing this.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11184" PostHistoryTypeId="2" PostId="4753" RevisionGUID="7d1f983a-2953-4583-9045-392c44a8e2b7" CreationDate="2017-02-22T10:36:54.167" UserId="1831" Text="As far as I understand, radiance is a measure of the &quot;intensity&quot; of light in a direction defined as a differential cone . It's measure is Flux per solid angle per projected area.  $L = \frac{d\phi}{d\omega dA^\perp} = \frac{d\phi}{d\omega cos(\theta)} $ . Using this definition, it seems like as the $\theta$ angle increases, radiance increases, thus light is somehow more &quot;intense&quot; in a direction nearly perpendicular to the normal at point p. This contradicts my intuition.  &#xD;&#xA;Where am I interpreting this wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11185" PostHistoryTypeId="1" PostId="4753" RevisionGUID="7d1f983a-2953-4583-9045-392c44a8e2b7" CreationDate="2017-02-22T10:36:54.167" UserId="1831" Text="Radiance at a nearly perpendicular angle is almost infinite?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11186" PostHistoryTypeId="3" PostId="4753" RevisionGUID="7d1f983a-2953-4583-9045-392c44a8e2b7" CreationDate="2017-02-22T10:36:54.167" UserId="1831" Text="|raytracing|lighting|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11190" PostHistoryTypeId="5" PostId="4752" RevisionGUID="6f56001f-1643-4076-b939-e14e50b7139d" CreationDate="2017-02-22T13:39:49.013" UserId="2707" Comment="added 52 characters in body" Text="For questions about the Vulkan graphics/compute API." ContentLicense="CC BY-SA 3.0" />
  <row Id="11191" PostHistoryTypeId="24" PostId="4752" RevisionGUID="6f56001f-1643-4076-b939-e14e50b7139d" CreationDate="2017-02-22T13:39:49.013" Comment="Proposed by 2707 approved by 209, 100 edit id of 202" ContentLicense="CC BY-SA 3.0" />
  <row Id="11192" PostHistoryTypeId="5" PostId="4751" RevisionGUID="8af120c7-48e9-4adc-9752-47e0895aa018" CreationDate="2017-02-22T13:39:57.570" UserId="2707" Comment="added 133 characters in body" Text="The [Vulkan](https://www.khronos.org/vulkan/) is a low-level, cross-platform graphics and compute API developed by the Khronos Group." ContentLicense="CC BY-SA 3.0" />
  <row Id="11193" PostHistoryTypeId="24" PostId="4751" RevisionGUID="8af120c7-48e9-4adc-9752-47e0895aa018" CreationDate="2017-02-22T13:39:57.570" Comment="Proposed by 2707 approved by 209, 100 edit id of 201" ContentLicense="CC BY-SA 3.0" />
  <row Id="11194" PostHistoryTypeId="5" PostId="4753" RevisionGUID="85e5f1ab-49fc-4cc0-b85d-a58cd9b551e6" CreationDate="2017-02-22T14:14:07.533" UserId="1831" Comment="Fixed wrongly typed formula" Text="As far as I understand, radiance is a measure of the &quot;intensity&quot; of light in a direction defined as a differential cone . It's measure is Flux per solid angle per projected area.  $L = \frac{d\phi}{d\omega dA^\perp} = \frac{d\phi}{d\omega dAcos(\theta)} $ . Using this definition, it seems like as the $\theta$ angle increases, radiance increases, thus light is somehow more &quot;intense&quot; in a direction nearly perpendicular to the normal at point p. This contradicts my intuition.  &#xD;&#xA;Where am I interpreting this wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11195" PostHistoryTypeId="2" PostId="4755" RevisionGUID="3774260b-8699-4f9f-9290-311a6e193154" CreationDate="2017-02-22T15:26:51.890" UserId="1952" Text="Image file formats themselves do not regard the gamma but store pixel values unmodified as the authoring program (e.g. Photoshop) decides to store the values, so RGB and alpha channels have no distinction from image file format point of view (barring potential lossy compression strategies, but that's another topic).&#xD;&#xA;&#xD;&#xA;However, when you author images in Photoshop, they are displayed on the screen in sRGB space including the alpha channel, so if you author alpha channel relying that the perceived brightness of pixels represents transparency, then you can say that alpha is also stored in the gamma space. BUT, if you author alpha by using layer transparency in Photoshop, then the alpha is stored linearly (e.g. 50% transparent layer is stored as alpha=128).&#xD;&#xA;&#xD;&#xA;So in the end it depends how you author the data that in which space the data is stored and how you should interpret it.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11196" PostHistoryTypeId="5" PostId="4755" RevisionGUID="96a3226d-037a-4388-b404-140b5048b233" CreationDate="2017-02-22T15:36:13.627" UserId="1952" Comment="added 407 characters in body" Text="Image file formats themselves do not regard the gamma but store pixel values unmodified as the authoring program (e.g. Photoshop) decides to store the values, so RGB and alpha channels have no distinction from image file format point of view (barring potential lossy compression strategies, but that's another topic).&#xD;&#xA;&#xD;&#xA;However, when you author images in Photoshop, they are displayed on the screen in sRGB space including the alpha channel, so if you author alpha channel relying that the perceived brightness of pixels represents transparency, then you can say that alpha is also stored in the gamma space. BUT, if you author alpha by using layer transparency in Photoshop, then the alpha is stored linearly (e.g. 50% transparent layer is stored as alpha=128).&#xD;&#xA;&#xD;&#xA;So in the end it depends how you author the data that in which space the data is stored and how you should interpret it. Also a thing to consider is if non-linear distribution of values gives you any precision benefits. Color values are stored in sRGB because human visual system responds logarithmically to light brightness, so it makes sense to have more details in darks than in brights to reduce perceived banding, but you could ask if such distribution would benefit say normal maps or roughness values stored in textures.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11197" PostHistoryTypeId="2" PostId="4756" RevisionGUID="7b8c1dee-2c3f-4bb6-a274-07f3506213d5" CreationDate="2017-02-22T17:46:46.373" UserId="1952" Text="It's only more intense if $d\phi$ remains constant. However, for light source with constant luminance the flux is a function of $cos(\theta)$, i.e. depends on the light's angle of incidence with the surface and cancels out the term." ContentLicense="CC BY-SA 3.0" />
  <row Id="11198" PostHistoryTypeId="2" PostId="4757" RevisionGUID="10cc2d31-1424-4171-87a0-579c53756ce9" CreationDate="2017-02-22T18:45:00.967" UserId="2941" Text="Remember radiance corresponds to a particular direction. When the equation is considering directions quasi parallel to the surface normal, the differential flux (the numerator) will typically be a much greater quantity than for grazing angles. The numerator is not remaining constant." ContentLicense="CC BY-SA 3.0" />
  <row Id="11199" PostHistoryTypeId="2" PostId="4758" RevisionGUID="4a219aa5-b720-444c-a18c-adc7c0e02bae" CreationDate="2017-02-22T20:22:30.670" UserId="6001" Text="My light mapper can generate soft shadows just fine - for each texel I cast a ray to the light, offset by some distribution of the 'area' of the light on disc. The problem is that I am casting many rays and that slows down production. I note that even for texels completely in shadow, I still cast 128 rays towards the light, but none of them hit it. This seems like a waste of effort. I imagine I could try to intersect a cone with the scene to reject cases when the texel is so deeply in shadow that multiple rays would be ineffective, but I currently only have a ray-tracer at my disposal, so before I go on I wanted to know if anyone has any good ideas. How can I accelerate the calculation of soft-shadows on the CPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11200" PostHistoryTypeId="1" PostId="4758" RevisionGUID="4a219aa5-b720-444c-a18c-adc7c0e02bae" CreationDate="2017-02-22T20:22:30.670" UserId="6001" Text="Acceleration techniques for CPU soft-shadow calculation in light mapper" ContentLicense="CC BY-SA 3.0" />
  <row Id="11201" PostHistoryTypeId="3" PostId="4758" RevisionGUID="4a219aa5-b720-444c-a18c-adc7c0e02bae" CreationDate="2017-02-22T20:22:30.670" UserId="6001" Text="|raytracing|lighting|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11203" PostHistoryTypeId="5" PostId="4756" RevisionGUID="fa40692f-c77e-4d53-a8d2-4c83d42a60ae" CreationDate="2017-02-22T21:18:16.620" UserId="1952" Comment="added 685 characters in body" Text="It's only more intense if $d\phi$ remains constant. However, for light source with constant luminance the flux is a function of $cos(\theta)$, i.e. depends on the light's angle of incidence with the surface and cancels out the term.&#xD;&#xA;&#xD;&#xA;Edit: I feel the need to clarify this a bit because you say that:&#xD;&#xA;&gt; thus light is somehow more &quot;intense&quot;&#xD;&#xA;&#xD;&#xA;It's not that the &quot;light is somehow more intense&quot;, but rather that the light **has to be** more intense to have same flux in grazing angles as when it's parallel to the surface. If you think of flux as particles hitting to this differential surface, the number of particles hitting the surface is smaller more perpendicular the light gets to the surface. So you have to throw more particles at the surface (i.e. increase the radiance) for the same flux until when the surface is completely perpendicular to the light, none of the particles hit the surface, thus the radiance goes to infinity." ContentLicense="CC BY-SA 3.0" />
  <row Id="11209" PostHistoryTypeId="5" PostId="4737" RevisionGUID="a7cf7f8e-90bd-4b0e-9dde-bfdf8fad9969" CreationDate="2017-02-23T02:46:03.673" UserId="5513" Comment="I added some of my calculations and would like to know if i answered the question correctly" Text="For a 3D scene in the World Coordinates, its View Reference Point (VRP) is at (5,-2,1), and a viewer is looking towards point A(1,1,1). Construct a transform matrix which will map World Coordinate points to a right-handed (UVN) viewing space, so that VRP is the origin, the line joining VRP to A is the positive N axis, and the View-Up Vector is (0,0,1). &#xD;&#xA;&#xD;&#xA;To my knowledge, the final answer should be a single transform matrix.&#xD;&#xA;To calculate the final matrix, I first find the matrix which translates the coordinate system to the to the origin in homogeneous matrix form:&#xD;&#xA;&#xD;&#xA;Translation matrix:&#xD;&#xA;&#xD;&#xA;1 0 0 -5 &#xD;&#xA;&#xD;&#xA;0 1 0 2&#xD;&#xA;&#xD;&#xA;0 0 1 -1&#xD;&#xA;&#xD;&#xA;0 0 0 1&#xD;&#xA;&#xD;&#xA;Using the unit vectors of the coordinate axes, the resulting rotation matrix is:&#xD;&#xA;&#xD;&#xA;-0.6 -0.8 0 0&#xD;&#xA;&#xD;&#xA;0 0 0 1&#xD;&#xA;&#xD;&#xA;-0.8 0.6 0 0&#xD;&#xA;&#xD;&#xA;0 0 0 1&#xD;&#xA;&#xD;&#xA;Then the final matrix (the final answer for full marks) would be the rotation matrix multiplied by the translation matrix:&#xD;&#xA;&#xD;&#xA;-0.6 -0.8 0 1.4&#xD;&#xA;&#xD;&#xA;0 0 0 1&#xD;&#xA;&#xD;&#xA;-0.8 0.6 0 5.2&#xD;&#xA;&#xD;&#xA;0 0 0 1&#xD;&#xA;&#xD;&#xA;Is my method and final answer correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11210" PostHistoryTypeId="12" PostId="4737" RevisionGUID="67e27551-f4eb-4c84-aed1-2b73ee321fc5" CreationDate="2017-02-23T02:46:38.380" UserId="5513" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:5513,&quot;DisplayName&quot;:&quot;S.A&quot;}]}" />
  <row Id="11213" PostHistoryTypeId="2" PostId="4760" RevisionGUID="0d7e7d7d-8b46-46df-8c1c-12caad003d49" CreationDate="2017-02-23T03:30:33.140" UserId="6097" Text="I have drawn a cylinder and an icosahedron using OpenGL.&#xD;&#xA;&#xD;&#xA;Now, i need to use the icosahedron and the open cylinder to build a structure motivated by crystal lattices, where i use an icosahedron for each atom and a cylinder to connect each 2 icosahedrons. &#xD;&#xA;&#xD;&#xA;I would have to use 12 icosahedrons for atoms and about 20 cylinders for the lines connecting the atoms, as i need to place them all to form the shape of an icosahedron itself.&#xD;&#xA;&#xD;&#xA;Is there anybody that could give me any ideas regarding how to go about this? I can arrange 12 icosahedrons to simulate the 12 vertices of an icosahedron, but i'm not sure how to place all of the cylinders around properly.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11214" PostHistoryTypeId="1" PostId="4760" RevisionGUID="0d7e7d7d-8b46-46df-8c1c-12caad003d49" CreationDate="2017-02-23T03:30:33.140" UserId="6097" Text="OpenGL - drawing icosahedrons and cylinders and combining them" ContentLicense="CC BY-SA 3.0" />
  <row Id="11215" PostHistoryTypeId="3" PostId="4760" RevisionGUID="0d7e7d7d-8b46-46df-8c1c-12caad003d49" CreationDate="2017-02-23T03:30:33.140" UserId="6097" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11216" PostHistoryTypeId="2" PostId="4761" RevisionGUID="4a2d386f-cee7-4e1c-b84e-0ba5b9c8f19e" CreationDate="2017-02-23T04:39:04.937" UserDisplayName="user3412" Text="I often use a 2D Perlin noise texture to displace a grid in the vertex shader (e.g. terrain, ocean).  However, every time I google the method to calculate post-displacement normals there is a slight difference.  For example, the value to place in the Y-component varies depending on the source.  In this example, they place a '1' in the Y-component prior to normalization:&#xD;&#xA;&#xD;&#xA;https://software.intel.com/en-us/articles/real-time-parametric-shallow-wave-simulation&#xD;&#xA;&#xD;&#xA;Whereas in these codes, the value '2' is chosen:&#xD;&#xA;&#xD;&#xA;http://www.dian-xiang.com/blog/2&#xD;&#xA;&#xD;&#xA;What gives?  Is there a definitive source for calculating normals from a height map?  &#xD;&#xA;&#xD;&#xA;The second part of my question concerns choosing an epsilon to sample the height map.  Before I learned about height maps, I read about getting the normal from an implicit surface as in this link:&#xD;&#xA;&#xD;&#xA;http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm&#xD;&#xA;&#xD;&#xA;It seems like the epsilon number is just made up though.  In my projects, I typically just fudge the value until it looks good.  Is there a definitive source, or at least a good rule of thumb?&#xD;&#xA;&#xD;&#xA;Might this be related to unprojecting mouse clicks?  It always bothered me that you could throw a '0.5' in the Z-component, as mrdoob mentioned here:&#xD;&#xA;&#xD;&#xA;http://stackoverflow.com/questions/11036106/three-js-projector-and-ray-objects&#xD;&#xA;&#xD;&#xA;Or use a '1' in the Z-component as Anton does here:&#xD;&#xA;&#xD;&#xA;http://antongerdelan.net/opengl/raycasting.html&#xD;&#xA;&#xD;&#xA;Is there a connection between calculating normals from height maps and unprojecting mouse clicks?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11217" PostHistoryTypeId="1" PostId="4761" RevisionGUID="4a2d386f-cee7-4e1c-b84e-0ba5b9c8f19e" CreationDate="2017-02-23T04:39:04.937" UserDisplayName="user3412" Text="Correct post-displacement normal calculation (Y-component and epsilon)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11218" PostHistoryTypeId="3" PostId="4761" RevisionGUID="4a2d386f-cee7-4e1c-b84e-0ba5b9c8f19e" CreationDate="2017-02-23T04:39:04.937" UserDisplayName="user3412" Text="|mathematics|real-time|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11220" PostHistoryTypeId="5" PostId="4761" RevisionGUID="350e68ae-dac9-48ce-ab25-6476fbb3aa18" CreationDate="2017-02-23T05:29:55.617" UserDisplayName="user3412" Comment="deleted 2 characters in body" Text="I often use a 2D Perlin noise texture to displace a grid in the vertex shader (e.g. terrain, ocean).  However, every time I google the method to calculate post-displacement normals there is a slight difference.  For example, the value to place in the Y-component varies depending on the source.  In this example, they place a '1' in the Y-component prior to normalization:&#xD;&#xA;&#xD;&#xA;https://software.intel.com/en-us/articles/real-time-parametric-shallow-wave-simulation&#xD;&#xA;&#xD;&#xA;Whereas in these codes, the value '2' is chosen:&#xD;&#xA;&#xD;&#xA;http://www.dian-xiang.com/blog/2&#xD;&#xA;&#xD;&#xA;What gives?  Is there a definitive source for calculating normals from a height map?  &#xD;&#xA;&#xD;&#xA;Might this be related to unprojecting mouse clicks?  It always bothered me that you could throw a '0.5' in the Z-component, as mrdoob mentioned here:&#xD;&#xA;&#xD;&#xA;http://stackoverflow.com/questions/11036106/three-js-projector-and-ray-objects&#xD;&#xA;&#xD;&#xA;Or use a '1' in the Z-component as Anton does here:&#xD;&#xA;&#xD;&#xA;http://antongerdelan.net/opengl/raycasting.html&#xD;&#xA;&#xD;&#xA;Is there a connection between calculating normals from height maps and unprojecting mouse clicks?&#xD;&#xA;&#xD;&#xA;The second part of my question concerns choosing an epsilon to sample the height map.  Before I learned about height maps, I read about getting the normal from an implicit surface as in this link:&#xD;&#xA;&#xD;&#xA;http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm&#xD;&#xA;&#xD;&#xA;It seems like the epsilon number is just made up though.  In my projects, I typically just fudge the value until it looks good.  Is there a definitive source, or at least a good rule of thumb?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11221" PostHistoryTypeId="2" PostId="4762" RevisionGUID="61cb7d57-411d-4462-9db0-0fbe5eb26c67" CreationDate="2017-02-23T13:32:29.873" UserId="1952" Text="You could try to optimize the calculation by first casting a smaller number of &quot;feeler rays&quot; (say 32) to check for penumbra, and cast the remaining rays if the result is in penumbra according to the rays. Of course this can give you false negatives, but you could then try to improve the heuristics by checking the results of nearby feeler rays." ContentLicense="CC BY-SA 3.0" />
  <row Id="11222" PostHistoryTypeId="2" PostId="4763" RevisionGUID="640a9327-bab4-4333-a1cb-703cfc6ed8d5" CreationDate="2017-02-23T18:43:31.500" UserId="6114" Text="To easily understand the 'dipole theory' we have first to understand from where it comes from the 'diffusion theory'.&#xD;&#xA;&#xD;&#xA;And it comes from simulating light transport in participating media by solving the radiance transport equation (RTE).&#xD;&#xA;&#xD;&#xA;The classical diffusion approximation solves the RTE by considering only a first-order spherical harmonic expansion of the radiance. If we further assume that the source function is a unit power isotropic point source in an infinite homogeneous medium we get to the classical diffusion Green's function (monopole).&#xD;&#xA;&#xD;&#xA;When rendering translucent materials, it is convenient to re-formulate this problem in analogy to the local surface reflection integral. This results in an integral equation which computes the outgoing radiance, Lo, at position and direction as a convolution of the incident illumination, Li, and the BSSRDF, S, over all incident positions and directions.&#xD;&#xA;&#xD;&#xA;Now with Green's diffusion function we don't account for boundary conditions imposed by the material surfaces. These conditions can be simply handled by placing a mirrored negative source outside the medium for every positive source inside the medium such that the fluence is zeroed at an extrapolated distance above the surface. This is the dipole approximation.&#xD;&#xA;&#xD;&#xA;So without boundary conditions our fluence is expressed volumetrically within the medium. To render subsurface scattering we have to compute light leaving various points on the surface. For this to happen we have to compute diffusion profiles due to a dipole so to evaluate the directional derivative of the fluence in the direction of the surface normal.&#xD;&#xA;&#xD;&#xA;Latest advancements on BSSRDF comes from shifting the initial volumetric and participating media approach with ad-hoc stuff that better takes into account surface boundary conditions.&#xD;&#xA;&#xD;&#xA;As for the ..&#xD;&#xA;&#xD;&#xA;&gt; BSSRDF model still requires integrating over a radius of nearby points&#xD;&#xA;&gt; on the surface to gather incoming light .. ?&#xD;&#xA;&#xD;&#xA;Yes, we integrate incident light togheter with the BSSRDF over all incident positions and directions.&#xD;&#xA;&#xD;&#xA;Now we can adopt here a brute force method or a dart-throwing approach with russian rouletting. But they are both naive approaches.&#xD;&#xA;&#xD;&#xA;SSS came to production (Pixar Renderman) when an approximation method has been developed to use hierarchical light gathering using an octree data structure where to bake diffuse lighting to be available in clusters for SSS computation. With Renderman this was a natural approach because of REYES so that every micropoligon generated from REYES could be easily 'splatted' into a point and inserted into an octree.&#xD;&#xA;&#xD;&#xA;A second wave of improvements relies on disk based importance sampling (Arnold) that is now the de-facto approach for many SSS implementations outthere. Generally we define a search volume (sphere), distribute samples on disk above the surface and probe along normal directions and orthogonal directions to find all hits inside the volume.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11223" PostHistoryTypeId="2" PostId="4764" RevisionGUID="c9d6c41a-bfa2-4481-bdb1-0117a1f3ebc7" CreationDate="2017-02-24T00:14:57.873" UserId="2076" Text="I'm having trouble figuring out the math to create a 2D IK system with more than 2 segments and more than 3 joints. I'm creating this in Adobe After Effects so using an existing solver isn't going to work.&#xD;&#xA;&#xD;&#xA;What I have so far works great for 2 segments (3 joints)—akin to how an arm or leg bends. Once I add a 4th joint, everything gets weird.&#xD;&#xA;&#xD;&#xA;Here's my setup for reference:&#xD;&#xA;&#xD;&#xA;![ik reference](https://i.stack.imgur.com/eQknI.png)&#xD;&#xA;&#xD;&#xA;What I'm aiming for is that when the blue box is moved (target) joints 2 and 3 bend appropriately to maintain their length. Joint 1 is static and doesn't move.&#xD;&#xA;&#xD;&#xA;To make this work, I need x,y coordinates to be calculated in real time. No need to render anything on screen—just the position values for each joint.&#xD;&#xA;&#xD;&#xA;Here's my javascript code so far:&#xD;&#xA;&#xD;&#xA;    var angle1, angle2, angle3, theta1, theta2, theta3, targetSqrDist;&#xD;&#xA;    &#xD;&#xA;    // joints&#xD;&#xA;    var joint1 = thisComp.layer(&quot;joint 1&quot;);&#xD;&#xA;    var joint2 = thisComp.layer(&quot;joint 2&quot;);&#xD;&#xA;    var joint3 = thisComp.layer(&quot;joint 3&quot;);&#xD;&#xA;    var joint4 = thisComp.layer(&quot;joint 4&quot;);&#xD;&#xA;    &#xD;&#xA;    // segment lengths&#xD;&#xA;    var segment1Len = length(joint2.transform.position, joint1.transform.position);&#xD;&#xA;    var segment2Len = length(joint3.transform.position, joint2.transform.position);&#xD;&#xA;    var segment3Len = length(joint4.transform.position, joint3.transform.position);&#xD;&#xA;    &#xD;&#xA;    // target position&#xD;&#xA;    var target = thisComp.layer(&quot;target&quot;);&#xD;&#xA;    var ix = target.transform.position[0] - joint1.transform.position[0];&#xD;&#xA;    var iy = target.transform.position[1] - joint1.transform.position[1];&#xD;&#xA;    &#xD;&#xA;    // target square distance&#xD;&#xA;    targetSqrDist = ix * ix + iy * iy;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 1&#xD;&#xA;    angle1 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist + (segment1Len*segment1Len) - (segment2Len*segment2Len)) / (2 * segment1Len * Math.sqrt(targetSqrDist))&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta1 = Math.atan2(iy, ix) - Math.acos(angle1);&#xD;&#xA;    &#xD;&#xA;    var s1X = joint1.transform.position[0] + segment1Len * Math.cos(theta1);&#xD;&#xA;    var s1Y = joint1.transform.position[1] + segment1Len * Math.sin(theta1);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 2&#xD;&#xA;    angle2 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist - (segment1Len*segment1Len) - (segment2Len*segment2Len)) / (2 * segment1Len * segment2Len)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta2 = Math.acos(angle2);&#xD;&#xA;    &#xD;&#xA;    var s2X = s1X + segment2Len * Math.cos(theta2 + theta1);&#xD;&#xA;    var s2Y = s1Y + segment2Len * Math.sin(theta2 + theta1);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 3&#xD;&#xA;    angle3 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist - (segment2Len*segment2Len) - (segment3Len*segment3Len)) / (2 * segment2Len * segment3Len)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta3 = Math.acos(angle3);&#xD;&#xA;    &#xD;&#xA;    var s3X = s2X + segment3Len * Math.cos(theta3 + theta2);&#xD;&#xA;    var s3Y = s2Y + segment3Len * Math.sin(theta3 + theta2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This code would be applied to each joint with a unique value assigned to it, depending on the joint's location." ContentLicense="CC BY-SA 3.0" />
  <row Id="11224" PostHistoryTypeId="1" PostId="4764" RevisionGUID="c9d6c41a-bfa2-4481-bdb1-0117a1f3ebc7" CreationDate="2017-02-24T00:14:57.873" UserId="2076" Text="Inverse Kinematics with more than 2 segments" ContentLicense="CC BY-SA 3.0" />
  <row Id="11225" PostHistoryTypeId="3" PostId="4764" RevisionGUID="c9d6c41a-bfa2-4481-bdb1-0117a1f3ebc7" CreationDate="2017-02-24T00:14:57.873" UserId="2076" Text="|animation|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11226" PostHistoryTypeId="2" PostId="4765" RevisionGUID="5664ecfe-c06d-45fe-a4d4-35f2f2171aaa" CreationDate="2017-02-24T03:58:44.900" UserId="1614" Text="I've generalized Everitt's results if that's needed.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VyA1o.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11227" PostHistoryTypeId="2" PostId="4766" RevisionGUID="7f4ba4c0-bc25-4440-9c4f-267f3ef27296" CreationDate="2017-02-24T04:13:10.053" UserId="3003" Text="When drawing in OpenGL and related APIs you usually have one or more models. In your case, this would be the cylinder and the icosahedron. The models are generally generated at some default size which may or may not suit your needs for a particular task. You move them, scale them, and rotate them by setting up a model matrix which describes how you want to transform them.&#xD;&#xA;&#xD;&#xA;So how would this work in your case? I recommend having 2 functions. One which draws a unit cylinder and another which draws a unit icosahedron. Say you have a data structure for your coordinates like this (I'm assuming a C-like language):&#xD;&#xA;&#xD;&#xA;    typedef struct Position3D {&#xD;&#xA;        float x;&#xD;&#xA;        float y;&#xD;&#xA;        float z;&#xD;&#xA;    } Position3D;&#xD;&#xA;&#xD;&#xA;You can then construct a triangle by making a structure for one:&#xD;&#xA;&#xD;&#xA;    typedef struct Triangle3D {&#xD;&#xA;        Position3D p0;&#xD;&#xA;        Position3D p1;&#xD;&#xA;        Position3D p2;&#xD;&#xA;    } Triangle3D;&#xD;&#xA;&#xD;&#xA;Then you'd have functions for generating the vertices you need. Something like this:&#xD;&#xA;&#xD;&#xA;    void generateCylinder (Triangle3D* triangles) // &lt;-assumes you allocated triangles before calling and that you have enough space for all of them!&#xD;&#xA;    {&#xD;&#xA;        int i = 0;&#xD;&#xA;        const float kRadius = 1.0;&#xD;&#xA;        const float kDeltaH = 0.1; // &lt;- change this to make the mesh more or less dense&#xD;&#xA;        const float kDeltaAngle = M_PI / 10.0; // &lt;- change this to make the mesh more or less curved&#xD;&#xA;        for (float h = -1.0; h &lt; 1.0; h += kDeltah)&#xD;&#xA;        {&#xD;&#xA;            for (float angle = 0; angle &lt; 2.0 * M_PI; angle += kDeltaAngle)&#xD;&#xA;            {&#xD;&#xA;                float x = kRadius * cos(angle);&#xD;&#xA;                float y = h;&#xD;&#xA;                float z = kRadius * sin(angle);&#xD;&#xA;                //... add points to triangles array here...&#xD;&#xA;                // p0 = &lt;x,y,z&gt;&#xD;&#xA;                // p1 = &lt;x, y + kDeltaH, z&gt;&#xD;&#xA;                // p1 = &lt;x + radius * cos(angle + kDeltaAngle), y, z  + radius * sin(angle + kDeltaAngle)&gt;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And a similar function for the icosahedron. &#xD;&#xA;&#xD;&#xA;Next, you'll create a matrix for every object you draw and send that to your shader before drawing it. So you'll have the translations for the vertices of the (big) icosahedron, and you want to draw a (small) icosahedron at each one. You'd do the following:&#xD;&#xA;&#xD;&#xA;    float translationMatrix [ 16 ] = {&#xD;&#xA;        1, 0, 0, 0,&#xD;&#xA;        0, 1, 0, 0,&#xD;&#xA;        0, 0, 1, 0,&#xD;&#xA;        0, 0, 0, 1&#xD;&#xA;    };&#xD;&#xA;    translationMatrix [ 12 ] = xPos;&#xD;&#xA;    translationMatrix [ 13 ] = yPos;&#xD;&#xA;    translationMatrix [ 14 ] = zPos;&#xD;&#xA;    GLuint modelMatrixLoc = glGetUniformLocation(program, &quot;modelMatrix&quot;);&#xD;&#xA;    glUniformMatrix4fv(modelMatrixLoc, 1, GL_FALSE, translationMatrix);&#xD;&#xA;&#xD;&#xA;Then you'd draw your icosahedron. For the cylinders you would need to scale vertically, rotate to the appropriate angle and translate it to the position between 2 icosahedrons." ContentLicense="CC BY-SA 3.0" />
  <row Id="11228" PostHistoryTypeId="2" PostId="4767" RevisionGUID="0d32772d-ce4a-4d23-a44b-ce214808054d" CreationDate="2017-02-24T12:42:00.360" UserId="5944" Text="I know the BRDF of specular reflection is nonzero only in the reflection direction.&#xD;&#xA;&#xD;&#xA;But why it is infinite?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11229" PostHistoryTypeId="1" PostId="4767" RevisionGUID="0d32772d-ce4a-4d23-a44b-ce214808054d" CreationDate="2017-02-24T12:42:00.360" UserId="5944" Text="Why the BRDF of specular reflection is infinite in the reflection direction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11230" PostHistoryTypeId="3" PostId="4767" RevisionGUID="0d32772d-ce4a-4d23-a44b-ce214808054d" CreationDate="2017-02-24T12:42:00.360" UserId="5944" Text="|rendering|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11231" PostHistoryTypeId="2" PostId="4768" RevisionGUID="f30223f3-18f6-4941-bd27-69548963e257" CreationDate="2017-02-24T13:31:18.200" UserId="5944" Text="I'm reading [Advanced Global Illumination][1].&#xD;&#xA;&#xD;&#xA;Here is the part confusing me:&#xD;&#xA;[![Advanced Global Illumination 2nd Edition, page 34][2]][2]&#xD;&#xA;&#xD;&#xA;1. What do the second equation and $\delta$-function mean?&#xD;&#xA;&#xD;&#xA;2. Why the third equation is a sufficient condition even though a reason is given?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.advancedglobalillumination.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/CDfwS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11232" PostHistoryTypeId="1" PostId="4768" RevisionGUID="f30223f3-18f6-4941-bd27-69548963e257" CreationDate="2017-02-24T13:31:18.200" UserId="5944" Text="Energy conservation of BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="11233" PostHistoryTypeId="3" PostId="4768" RevisionGUID="f30223f3-18f6-4941-bd27-69548963e257" CreationDate="2017-02-24T13:31:18.200" UserId="5944" Text="|rendering|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11234" PostHistoryTypeId="5" PostId="4767" RevisionGUID="7c837894-e254-475c-b037-89765f9d70ee" CreationDate="2017-02-24T13:36:15.887" UserId="5944" Comment="added 202 characters in body" Text="I know the BRDF of specular reflection is nonzero only in the reflection direction.&#xD;&#xA;&#xD;&#xA;But why it is infinite?&#xD;&#xA;&#xD;&#xA;A paragraph on page 36 of [Advanced Global Illumination][1]:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: http://www.advancedglobalillumination.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/GQgcj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11235" PostHistoryTypeId="5" PostId="4768" RevisionGUID="71c8ad94-be28-405c-b553-520ee65cc067" CreationDate="2017-02-24T13:36:51.043" UserId="5944" Comment="added 2 characters in body" Text="I'm reading [Advanced Global Illumination][1].&#xD;&#xA;&#xD;&#xA;Here is the part confusing me:&#xD;&#xA;&#xD;&#xA;[![Advanced Global Illumination 2nd Edition, page 34][2]][2]&#xD;&#xA;&#xD;&#xA;1. What do the second equation and $\delta$-function mean?&#xD;&#xA;&#xD;&#xA;2. Why the third equation is a sufficient condition even though a reason is given?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.advancedglobalillumination.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/CDfwS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11236" PostHistoryTypeId="2" PostId="4769" RevisionGUID="9e3f8119-75d7-4c00-85d8-5363a7f4d0fa" CreationDate="2017-02-24T14:02:14.297" UserId="2041" Text="In the BRDF curve, the total area under the curve is the albedo: what fraction of incident light is reflected in total (as opposed to being absorbed or transmitted). For a perfect reflector, the area under the curve sums to 1, because it reflects all of the incident light. This area limits how high the curve can be. For example, a *perfect* diffuse reflector has a BRDF that's a flat line at $\frac{1}{2\pi}$, because it reflects the light evenly across the whole hemisphere, the solid angle of a hemisphere is $2\pi$, and the area has to be 1.&#xD;&#xA;&#xD;&#xA;In a *perfect* specular reflector, the area under the curve is still 1: it still reflects all of the incident light. But this time, it's reflecting all of that light in one direction. The BRDF curve is a single spike. If you draw a graph with an infinitely thin spike, and the area under the graph has to be 1, then the spike must also be infinitely high. It's the only way to make the area correct.&#xD;&#xA;&#xD;&#xA;Obviously a real material can't be a *perfect* specular reflector, so it will have two differences. First, the area under the curve will be less than 1,  because some light is absorbed. This doesn't matter much to us. More importantly, the reflection peak can't be infinitely thin: the reflection will be blurred ever so slightly. This means the peak won't be infinitely high: the wider the peak, the less high it has to be to still have an area of 1.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The remark about &quot;$\delta$-functions&quot; is because of a function (properly speaking, it's not a function but a *distribution*) called the Dirac $\delta$ (delta). This distribution is an infinitely thin, infinitely tall spike at $x = 0$, whose area is 1, just like our perfect specular BRDF." ContentLicense="CC BY-SA 3.0" />
  <row Id="11241" PostHistoryTypeId="2" PostId="4771" RevisionGUID="63bd2b02-ae9d-49a5-8fac-1f4733283e27" CreationDate="2017-02-24T21:25:29.627" UserId="2941" Text="I'm trying to implement Cook-Torrance BRDF and had previously bookmarked [this question][1] as it looked very well thought out. Going through it, I'm confused about the Fresnel equation. The author has the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5 \tag{1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and says &quot;*$c_{spec}$ is the specular color*&quot;&#xD;&#xA;&#xD;&#xA;Looking elsewhere, I can see this equation is [Schlick's approximation][2], but in other references, $c_{spec}$ is called $R_0$ and is $\left(\frac{n_1-n_2}{n_1+n_2}\right)^2$ which is clearly a number based upon refractive indices and **not** a colour.&#xD;&#xA;&#xD;&#xA;Does equation $(1)$ make sense with colour?&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/4394/path-tracing-the-cook-torrance-brdf&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Schlick%27s_approximation" ContentLicense="CC BY-SA 3.0" />
  <row Id="11242" PostHistoryTypeId="1" PostId="4771" RevisionGUID="63bd2b02-ae9d-49a5-8fac-1f4733283e27" CreationDate="2017-02-24T21:25:29.627" UserId="2941" Text="Fresnel and specular colour" ContentLicense="CC BY-SA 3.0" />
  <row Id="11243" PostHistoryTypeId="3" PostId="4771" RevisionGUID="63bd2b02-ae9d-49a5-8fac-1f4733283e27" CreationDate="2017-02-24T21:25:29.627" UserId="2941" Text="|brdf|specular|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11245" PostHistoryTypeId="2" PostId="4772" RevisionGUID="a01030fa-8675-46e7-aeba-62abeba1f0a2" CreationDate="2017-02-24T23:52:37.747" UserId="48" Text="Yes, because refractive index can vary with wavelength. This is the origin of colored specular reflection in metals such as gold and copper; most other materials have essentially uncolored specular. At each wavelength, the specular reflectance at normal incidence is related to the refractive index at that wavelength according to the formula you mentioned.&#xD;&#xA;&#xD;&#xA;In case you're interested, the site [refractiveindex.info](https://refractiveindex.info/) has data tables and graphs of refractive index versus wavelength for various materials. For example, [here's gold](https://refractiveindex.info/?shelf=main&amp;book=Au&amp;page=Johnson):&#xD;&#xA;&#xD;&#xA;![refractive index of gold vs wavelength][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XX9FC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11250" PostHistoryTypeId="5" PostId="4700" RevisionGUID="acc42945-d881-4c0a-a7eb-92b5b4bf36ff" CreationDate="2017-02-25T13:49:26.930" UserId="6040" Comment="deleted 19 characters in body" Text="The technic what Benedikt mentioned&#xD;&#xA;is explained in Section 2.4.1 of this thesis.&#xD;&#xA;&#xD;&#xA;http://fileadmin.cs.lth.se/graphics/theses/projects/projgrid/projgrid-lq.pdf&#xD;&#xA;&#xD;&#xA;Implementing this should solve your problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="11251" PostHistoryTypeId="2" PostId="4774" RevisionGUID="5db786e9-e7ff-4319-a1b0-8cf5be39cb12" CreationDate="2017-02-25T14:37:15.800" UserId="6040" Text="The Epsilon is chosen to hit the appropriated Nyquist-Frequency avoiding aliasing. It refers to the highest frequency in your heightfield function. You'll need well knowledge of the definition of your function to find it. For example, the figure shows an iterated Brownian motion (IBM) which approximate Perlin noise. The frequency of each added noise function is given by 2^i. So the Epsilon would be the last added frequency: 1/2^(N-1). That means the Epsilon is predefined for each Noise.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vhVN4.png&#xD;&#xA;IBM by Hugo Elias approximating Perlin Noise." ContentLicense="CC BY-SA 3.0" />
  <row Id="11252" PostHistoryTypeId="5" PostId="4774" RevisionGUID="58dd22de-51ba-43df-8ce4-5f608743e336" CreationDate="2017-02-25T14:49:24.793" UserId="6040" Comment="added 129 characters in body" Text="The Epsilon is chosen to hit the appropriated Nyquist-Frequency avoiding aliasing. It refers to the highest frequency in your heightfield function. You'll need well knowledge of the definition of your function to find it. For example, the figure shows an iterated Brownian motion (IBM) which approximate Perlin noise. The frequency of each added noise function is given by ![](https://chart.googleapis.com/chart?cht=tx&amp;chl=2^{i}). So the Epsilon would be the last added frequency: ![\frac{1}{2^{N-1}}](https://chart.googleapis.com/chart?cht=tx&amp;chl=\frac{1}{2^{N-1}}). That means the Epsilon is predefined for each Noise.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vhVN4.png&#xD;&#xA;IBM by Hugo Elias approximating Perlin Noise." ContentLicense="CC BY-SA 3.0" />
  <row Id="11253" PostHistoryTypeId="5" PostId="4774" RevisionGUID="484d70b8-70d2-456b-8f69-b3eaa99f71f2" CreationDate="2017-02-25T15:16:44.470" UserId="6040" Comment="added 620 characters in body" Text="The Epsilon is chosen to hit the appropriated Nyquist-Frequency avoiding aliasing. It refers to the highest frequency in your heightfield function. You'll need well knowledge of the definition of your function to find it. For example, the figure shows an iterated Brownian motion (IBM) which approximate Perlin noise. The frequency of each added noise function is given by ![](https://chart.googleapis.com/chart?cht=tx&amp;chl=2^{i}). So the Epsilon would be the last added frequency: ![\frac{1}{2^{N-1}}](https://chart.googleapis.com/chart?cht=tx&amp;chl=\frac{1}{2^{N-1}}). That means the Epsilon is predefined for each Noise.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vhVN4.png&#xD;&#xA;IBM by Hugo Elias approximating Perlin Noise.&#xD;&#xA;&#xD;&#xA;&gt; Might this be related to unprojecting mouse clicks? It always bothered me that you could throw a '0.5' in the Z-component, as mrdoob mentioned here:&#xD;&#xA;&#xD;&#xA;Your first question has nothing to do with mouse picking in my opinion. Your mouse is defined in normalized-device-coordinates (NDC) meaning a click in a window is ranging from -1 to 1 in each direction. The Z component is not given since our screen is just 2-dimensional, meaning we have to select a value from -1 to 1. -1 refers to the near plane and 1 to the far plane.&#xD;&#xA;&#xD;&#xA;For further information on that topic: http://antongerdelan.net/opengl/raycasting.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="11254" PostHistoryTypeId="5" PostId="4774" RevisionGUID="e6c02cad-6316-41f0-9180-48fb8e8b1668" CreationDate="2017-02-25T16:10:53.883" UserId="6040" Comment="added 5 characters in body" Text="The Epsilon is chosen to hit the appropriated Nyquist-Frequency avoiding aliasing. It refers to the highest frequency in your heightfield function. You'll need well knowledge of the definition of your function to find it. For example, the figure shows an iterated Brownian motion (IBM) which approximate Perlin noise. The frequency of each added noise function is given by ![](https://chart.googleapis.com/chart?cht=tx&amp;chl=2^{i}). So the Epsilon would be the last added frequency: ![\frac{1}{2^{N-1}}](https://chart.googleapis.com/chart?cht=tx&amp;chl=\frac{1}{2^{N-1}}). That means the Epsilon is predefined for each Noise.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vhVN4.png&#xD;&#xA;IBM by Hugo Elias approximating Perlin Noise.&#xD;&#xA;&#xD;&#xA;&gt; Might this be related to unprojecting mouse clicks? It always bothered me that you could throw a '0.5' in the Z-component, as mrdoob mentioned here:&#xD;&#xA;&#xD;&#xA;Your first question has nothing to do with mouse picking in my opinion. Your mouse is defined in normalized-device-coordinates (NDC) meaning a click in a window is ranging from -1 to 1 in each direction. The Z component is not given since our screen is just 2-dimensional, meaning we have to select a value from -1 to 1. -1 refers to the near plane and 1 to the far plane.&#xD;&#xA;&#xD;&#xA;For further information on that topic: &#xD;&#xA;https://www.youtube.com/watch?v=DLKN0jExRIM&amp;t=371s" ContentLicense="CC BY-SA 3.0" />
  <row Id="11256" PostHistoryTypeId="50" PostId="4060" RevisionGUID="4270cd49-81a9-4815-9a08-50ba8990c7e3" CreationDate="2017-02-25T17:12:01.713" UserId="-1" />
  <row Id="11258" PostHistoryTypeId="2" PostId="4775" RevisionGUID="40559cd1-d933-495f-be7b-509a3218b07a" CreationDate="2017-02-25T17:31:52.827" UserId="6125" Text="You are right to be confused. What I think they mean to say in the second equation is:&#xD;&#xA;$$&#xD;&#xA;L( x \leftarrow \Psi ) = L_{in} \delta(\Psi - \alpha)&#xD;&#xA;$$&#xD;&#xA;In other words, they should have used $ \alpha $ instead of $ \Theta $, which is already used as a dummy variable in the integral.&#xD;&#xA;&#xD;&#xA;You should look up the Dirac delta function to learn its meaning and properties. In this context, you can imagine the $ L$ above as representing a very concentrated beam (a laser) coming from the angle $ \alpha $. Practically, to do the integral over $ \Psi $ with the $ \delta (\Psi - \alpha) $ present in the integrand, simply remove the integration and replace $ \Psi $ with $ \alpha $. Then it should be clear how they arrive at the next line, which should read, for all $ \alpha $: $$ \int f_r(x, \alpha \rightarrow \Theta) \; \cos(N_x, \Theta)\; d \omega_\Theta \leq 1 $$.&#xD;&#xA;&#xD;&#xA;The fact that this condition is sufficient follows from two facts: 1. that any function (e.g. $ L $) can be approximated by a sum of many $ \delta $ functions, and 2. from the fact that everything is linear. In other words, if I write $ N(L) $ and $ D(L) $ for the numerator and denominator of the left hand side of (2.21), then you can see that if $ L = L_1 + L_2 $, then $ N(L_1+L_2) = N(L_1) + N(L_2) $ and $ D(L_1+L_2) = D(L_1) + D(L_2) $. So if I know $ N(L_1) \leq D(L_1) $ and $ N(L_2) \leq D(L_2) $, then I know $ N(L) \leq D(L) $ since $$ N(L) = N(L_1) + N(L_2) \leq D(L_1) + D(L_2) = D(L) $$. &#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11262" PostHistoryTypeId="5" PostId="4775" RevisionGUID="0350b81b-0ca8-4a70-a8d6-4a861ced9efa" CreationDate="2017-02-25T19:49:27.607" UserId="6125" Comment="deleted 50 characters in body" Text="You are right to be confused. What I think they should have written:&#xD;&#xA;$$&#xD;&#xA;L( x \leftarrow \Psi ) = L_{in} \delta(\Psi - \alpha)&#xD;&#xA;$$&#xD;&#xA;using $ \alpha $ instead of $ \Theta $, which is already used as a dummy variable in the integral.&#xD;&#xA;&#xD;&#xA;You should look up the Dirac delta function to learn its meaning and properties. In this context, you can imagine the $ L$ above as representing a very concentrated beam (a laser) coming from the angle $ \alpha $. Practically, to do the integral over $ \Psi $ with $ \delta (\Psi - \alpha) $ present in the integrand, remove the integration and replace all occurrences of $ \Psi $ with $ \alpha $. Then it should be clear how they arrive at the next line, which should read, for all $ \alpha $: $$ \int f_r(x, \alpha \rightarrow \Theta) \; \cos(N_x, \Theta)\; d \omega_\Theta \leq 1 $$.&#xD;&#xA;&#xD;&#xA;The fact that this condition is sufficient follows from two facts: 1. that any function (e.g. $ L $) can be approximated by a sum of many $ \delta $ functions, and 2. that everything is linear. In other words, if I write $ N(L) $ and $ D(L) $ for the numerator and denominator of the left hand side of (2.21), then you can see that if $ L = L_1 + L_2 $, then $ N(L_1+L_2) = N(L_1) + N(L_2) $ and $ D(L_1+L_2) = D(L_1) + D(L_2) $. So if I know $ N(L_1) \leq D(L_1) $ and $ N(L_2) \leq D(L_2) $, then I know $ N(L) \leq D(L) $ since $$ N(L) = N(L_1) + N(L_2) \leq D(L_1) + D(L_2) = D(L) $$. &#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11264" PostHistoryTypeId="2" PostId="4777" RevisionGUID="a319228d-f5fb-4a9d-be2d-82a30b3be4fc" CreationDate="2017-02-25T20:29:55.600" UserDisplayName="user3412" Text="I understand that Fresnel tells us what percentage of light reflects vs refracts, but what law tells me the  percentage of refracted light that is transmitted versus the percentage of refracted light that is scattered back out as diffuse?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11265" PostHistoryTypeId="1" PostId="4777" RevisionGUID="a319228d-f5fb-4a9d-be2d-82a30b3be4fc" CreationDate="2017-02-25T20:29:55.600" UserDisplayName="user3412" Text="Equivalent of Fresnel law for determining transmitted/diffuse split" ContentLicense="CC BY-SA 3.0" />
  <row Id="11266" PostHistoryTypeId="3" PostId="4777" RevisionGUID="a319228d-f5fb-4a9d-be2d-82a30b3be4fc" CreationDate="2017-02-25T20:29:55.600" UserDisplayName="user3412" Text="|color-science|transparency|diffuse|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11273" PostHistoryTypeId="2" PostId="4778" RevisionGUID="6c7110c1-9059-4849-877d-a6bea56c2506" CreationDate="2017-02-26T06:48:21.620" UserId="5256" Text="Right now I am reading Peter Shirley's [Ray Tracing in One Weekend][1] book, I want to be able to use the provided [source code][2] but I am not sure what platform or IDE it was written on, because of this it does not compile in Visual Studio.&#xD;&#xA;&#xD;&#xA;Can somebody help me? Whenever I try compiling the code it asks me to 'attach to process'.&#xD;&#xA;&#xD;&#xA;How can I get this working? In a few reviews I have read online it says that I'll need to do some tweaking to get it working but I honestly don't know how.&#xD;&#xA;Would it mean rewriting the entire ray tracer as a Win32 Project? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.amazon.com/Ray-Tracing-Weekend-Minibooks-Book-ebook/dp/B01B5AODD8&#xD;&#xA;  [2]: https://github.com/petershirley/raytracinginoneweekend" ContentLicense="CC BY-SA 3.0" />
  <row Id="11274" PostHistoryTypeId="1" PostId="4778" RevisionGUID="6c7110c1-9059-4849-877d-a6bea56c2506" CreationDate="2017-02-26T06:48:21.620" UserId="5256" Text="How to get Ray Tracer working in Visual Studio" ContentLicense="CC BY-SA 3.0" />
  <row Id="11275" PostHistoryTypeId="3" PostId="4778" RevisionGUID="6c7110c1-9059-4849-877d-a6bea56c2506" CreationDate="2017-02-26T06:48:21.620" UserId="5256" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11276" PostHistoryTypeId="2" PostId="4779" RevisionGUID="f7582929-0413-42b9-bd41-96ce6784d7d1" CreationDate="2017-02-26T11:19:21.013" UserId="2287" Text="No MakeFile or Visual Studio Solution file is provided. So you will need to do the setup yourself in the Visual Studio IDE. Note that you could just drag and drop the files (.h and .cc are known extensions to Visual Studio) in a new console application if you are not/less familiar with Visual Studio.&#xD;&#xA;&#xD;&#xA;The code itself is just plain C++ code. No special stuff. So it does not matter which platform or IDE was used during development. In fact the code is pretty self containing except for&#xD;&#xA;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &quot;float.h&quot; -&gt; &lt;float.h&gt;&#xD;&#xA;&#xD;&#xA;But if your Visual Studio is installed and configured correctly, every **console** application can just include these headers without any problems. (Just try a basic `hello world` **console** application, since the problem has in my opinion nothing to do with the code you want to use.) Note that you need a **Win32 Console application** and NOT a **Win32 Project**.&#xD;&#xA;&#xD;&#xA;It could be possible that the pre-compiled header file is enabled (`StdAfx.h` or `pch.h`) in which case you could disable this or include the header as the first included header in every `.cpp` file." ContentLicense="CC BY-SA 3.0" />
  <row Id="11277" PostHistoryTypeId="2" PostId="4780" RevisionGUID="26a3fe43-3fbd-4df6-9a5a-32fbef10ec9e" CreationDate="2017-02-26T19:38:06.853" UserId="48" Text="Physically, the origin of diffuse light is subsurface scattering, which happens continuously as light travels through a material. So, the proportion of transmitted light depends on the thickness of the object.&#xD;&#xA;&#xD;&#xA;There's no precise equivalent to the Fresnel law, but maybe the closest thing is the [Beer–Lambert law](https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law). It states that the transmitted light falls off exponentially with distance, proportional to $e^{-\sigma x}$, where $x$ is the distance the light has traveled through the material and $\sigma$ is the extinction coefficient (with units of inverse length). The non-transmitted portion of the light may be partly absorbed, and partly scattered through the material.&#xD;&#xA;&#xD;&#xA;You get the appearance of &quot;diffuse&quot; when typical length scale of scattering is smaller than you can see ($1/\sigma \ll  1\text{ pixel}$). Then the light gets scattered so many times in such a short distance that by the time it comes back out, its distribution looks isotropic (Lambertian). The apparent diffuse color is controlled by the wavelength-dependence of the scattering and attenuation coefficients.&#xD;&#xA;&#xD;&#xA;When the scattering length scale is larger, you get a soft appearance to the material (as in wax, marble, human skin, etc), or partial translucency." ContentLicense="CC BY-SA 3.0" />
  <row Id="11279" PostHistoryTypeId="13" PostId="4737" RevisionGUID="41805315-8987-422e-a584-edf84ff62ac6" CreationDate="2017-02-26T22:31:55.447" UserId="5513" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:5513,&quot;DisplayName&quot;:&quot;S.A&quot;}]}" />
  <row Id="11280" PostHistoryTypeId="33" PostId="4737" RevisionGUID="d11df9d2-f28c-4583-bcc1-aabea2504eee" CreationDate="2017-02-26T22:38:30.943" UserId="5513" Comment="25" />
  <row Id="11281" PostHistoryTypeId="5" PostId="4765" RevisionGUID="5aa68937-a96b-431d-aced-08054dabc80f" CreationDate="2017-02-27T03:52:47.363" UserId="1614" Comment="respect convention of the schema" Text="I've generalized Everitt's results if that's needed.&#xD;&#xA;&#xD;&#xA;[![generalized common frustum][1]][1]&#xD;&#xA;&#xD;&#xA;As a bonus, a way to extract left0/right0 from the eyes perspective matrices:&#xD;&#xA;&#xD;&#xA;    left0   = n0 * (Mle13 - 1) / Mle11;&#xD;&#xA;    right1  = n1 * (Mre13 + 1) / Mre11;&#xD;&#xA;If you have row major. transpose for column major. c.f. [this answer][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VyA1o.png&#xD;&#xA;  [2]: http://stackoverflow.com/a/12926655/893406" ContentLicense="CC BY-SA 3.0" />
  <row Id="11282" PostHistoryTypeId="6" PostId="4777" RevisionGUID="1f4e1dcb-e5e2-4d77-bc13-2eeac565133e" CreationDate="2017-02-27T09:33:46.980" UserId="2041" Comment="Remove &quot;color science&quot; tag, as the question isn't about describing or measuring color" Text="|transparency|diffuse|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11284" PostHistoryTypeId="2" PostId="4781" RevisionGUID="0b38263a-a781-4488-ae99-3edee1ec9a05" CreationDate="2017-02-27T18:35:17.340" UserId="6136" Text="I am interested in building a program to accomodate the following workflow:&#xD;&#xA;&#xD;&#xA;A user begins with an arbitrary vector/CAD shape, which they wish to transfer onto paper without using a printer (there are both realistic and novelty reasons why this problem is interesting to me). The program will accept this file and create a list of instructions to draft the shape using ruler, square, compass, and standard curve forms. I am not currently concerned with the details of this program (file formats, types of vector curve [spline, bezier, etc], output formatting, etc) but with the core geometric description problem. I think it is fairly straightforward to accomplish this with straight lines, angles, and offsets.&#xD;&#xA;&#xD;&#xA;However, I am not sure how to approach the problem of curve fitting. Ideally, the user would be able to have curves in the cad file fit (probably approximated) so that they may draft them using standard French curve forms, including:&#xD;&#xA;&#xD;&#xA;[![][2]][2]&#xD;&#xA;Hip Curve&#xD;&#xA;&#xD;&#xA;[![][3]][3]&#xD;&#xA;Vary form curve&#xD;&#xA;&#xD;&#xA;Assume that these curves are made to standard shapes and sizes and are modeled with dimensional accuracy. Furthermore, they are ruled at specific points and a user can place them on the paper diagram at specific positions and angles (relative to the other elements in the diagram that have already been drafted).&#xD;&#xA;&#xD;&#xA;What would be the first steps towards solving this problem? Are there existant computational geometry methods for approximating curves with (segments and combinations of) standard forms? What literature would I want to read? I apologize for the somewhat open-ended nature of this question, but it's difficult for me to determine where to begin.&#xD;&#xA;&#xD;&#xA;If it's helpful, the CAD patterns are probably such that the curves can, in fact, be very closely approximated with just one or two of these shapes - the primary use would be for fashion pattern drafting, and these French curves are specifically designed for creating the geometry of flat patterns that fit a human body.&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/P2YSE.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/DSB3q.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11285" PostHistoryTypeId="1" PostId="4781" RevisionGUID="0b38263a-a781-4488-ae99-3edee1ec9a05" CreationDate="2017-02-27T18:35:17.340" UserId="6136" Text="First steps towards CAD standard curve fitting" ContentLicense="CC BY-SA 3.0" />
  <row Id="11286" PostHistoryTypeId="3" PostId="4781" RevisionGUID="0b38263a-a781-4488-ae99-3edee1ec9a05" CreationDate="2017-02-27T18:35:17.340" UserId="6136" Text="|computational-geometry|line-drawing|vector-graphics|bezier-curve|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11296" PostHistoryTypeId="5" PostId="4737" RevisionGUID="5a3bd911-8a9f-4e79-9e83-9b45d72deb47" CreationDate="2017-02-28T10:28:41.413" UserId="4958" Comment="mathjax for matrices" Text="For a 3D scene in the World Coordinates, its View Reference Point (VRP) is at (5,-2,1), and a viewer is looking towards point A(1,1,1). Construct a transform matrix which will map World Coordinate points to a right-handed (UVN) viewing space, so that VRP is the origin, the line joining VRP to A is the positive N axis, and the View-Up Vector is (0,0,1). &#xD;&#xA;&#xD;&#xA;To my knowledge, the final answer should be a single transform matrix.&#xD;&#xA;To calculate the final matrix, I first find the matrix which translates the coordinate system to the to the origin in homogeneous matrix form:&#xD;&#xA;&#xD;&#xA;Translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        1 &amp;0 &amp;0 &amp;-5 \\&#xD;&#xA;        0 &amp;1 &amp;0&amp; 2 \\&#xD;&#xA;        0 &amp;0 &amp;1 &amp;-1 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Using the unit vectors of the coordinate axes, the resulting rotation matrix is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        -0.6 &amp;-0.8 &amp;0 &amp;0 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        -0.8 &amp;0.6 &amp;0 &amp;0 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Then the final matrix (the final answer for full marks) would be the rotation matrix multiplied by the translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        -0.6 &amp;-0.8 &amp;0 &amp;1.4 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        -0.8 &amp;0.6 &amp;0 &amp;5.2 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Is my method and final answer correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11297" PostHistoryTypeId="24" PostId="4737" RevisionGUID="5a3bd911-8a9f-4e79-9e83-9b45d72deb47" CreationDate="2017-02-28T10:28:41.413" Comment="Proposed by 4958 approved by 209, 2041 edit id of 203" ContentLicense="CC BY-SA 3.0" />
  <row Id="11300" PostHistoryTypeId="2" PostId="4785" RevisionGUID="f6235942-768f-4090-abf6-35526a8e6da2" CreationDate="2017-02-28T13:50:00.070" UserId="5476" Text="It's been a long time since I last used OpenGL and I can't figure out VAOs anymore... I want to make a simple voxel engine using geometry shaders. This is what I want to do: &#xD;&#xA;&#xD;&#xA;vbo1: array of GLfloat for the positions (3 floats per vertex)&#xD;&#xA;&#xD;&#xA;vbo2: array of GLfloat for the size of the cube (1 float per vertex)&#xD;&#xA;&#xD;&#xA;vbo3: array of GLbyte for the type of voxel (1 byte per vertex)&#xD;&#xA;&#xD;&#xA;-&gt; vao: GLfloat x, GLfloat y, GLfloat z, GLfloat size, GLbyte type&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's my code:&#xD;&#xA;&#xD;&#xA;        float *positions = new GLfloat[size * 3];&#xD;&#xA;    &#xD;&#xA;    	positions[0] = 0.5;&#xD;&#xA;    	positions[1] = 0.5;&#xD;&#xA;    	positions[2] = 0;&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;positionsId);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, positionsId);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, size * 3 * sizeof(GLfloat), positions, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	byte * voxelValues = new GLubyte[size];&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	voxelValues[0] = 0;&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;voxelValuesId);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, voxelValuesId);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, size * sizeof(GLubyte), voxelValues, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	float * sizes = new GLfloat[size];&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	sizes[0] = 1;&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;sizesId);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, sizesId);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, size * sizeof(GLfloat), sizes, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    &#xD;&#xA;    	glBindVertexArray(vao);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, positionsId);&#xD;&#xA;    	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, sizesId);&#xD;&#xA;    	glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, voxelValuesId);&#xD;&#xA;    	glVertexAttribPointer(2, 1, GL_UNSIGNED_BYTE, GL_FALSE, 0, NULL);&#xD;&#xA;    &#xD;&#xA;    	glEnableVertexAttribArray(0);&#xD;&#xA;    	glEnableVertexAttribArray(1);&#xD;&#xA;    	glEnableVertexAttribArray(2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is the code even doing what I want it to do? And is it even possible to use different datatypes in the vao? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11301" PostHistoryTypeId="1" PostId="4785" RevisionGUID="f6235942-768f-4090-abf6-35526a8e6da2" CreationDate="2017-02-28T13:50:00.070" UserId="5476" Text="Need help with VBO/VAO" ContentLicense="CC BY-SA 3.0" />
  <row Id="11302" PostHistoryTypeId="3" PostId="4785" RevisionGUID="f6235942-768f-4090-abf6-35526a8e6da2" CreationDate="2017-02-28T13:50:00.070" UserId="5476" Text="|opengl|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11303" PostHistoryTypeId="2" PostId="4786" RevisionGUID="d6186485-70bc-45bd-90b5-33a91ccff88e" CreationDate="2017-02-28T13:55:13.977" UserId="137" Text="Look good to me.&#xD;&#xA;&#xD;&#xA;And yes you can use different datatypes for different attributes in a vao, that's the entire point of having the type parameter there in the first place." ContentLicense="CC BY-SA 3.0" />
  <row Id="11304" PostHistoryTypeId="5" PostId="4764" RevisionGUID="d070f237-6a9b-4afd-af9f-2b50ef7a1ab8" CreationDate="2017-02-28T18:21:16.987" UserId="2076" Comment="added 96 characters in body" Text="I'm building a 2D inverse kinematics system and can't figure out how to find all the joint positions. I have the math to make a typical IK set up with a single bend (e.g. arm, leg), but I get stuck when adding another bend.&#xD;&#xA;&#xD;&#xA;**How do I find the position of all joints for an inverse kinematic chain that is longer than 2 segments?**&#xD;&#xA;&#xD;&#xA;I'm building this in Adobe After Effects so using an existing IK solver isn't going to work.&#xD;&#xA;&#xD;&#xA;Here's my visual setup for reference:&#xD;&#xA;&#xD;&#xA;![ik reference](https://i.stack.imgur.com/eQknI.png)&#xD;&#xA;&#xD;&#xA;What I'm aiming for is that when the blue box is moved (target) joints 2 and 3 bend appropriately to maintain their length. Joint 1 is static and doesn't move.&#xD;&#xA;&#xD;&#xA;To make this work, I need x,y coordinates to be calculated in real time. No need to render anything on screen—just the position values for each joint.&#xD;&#xA;&#xD;&#xA;Here's my javascript so far:&#xD;&#xA;&#xD;&#xA;    var angle1, angle2, angle3, theta1, theta2, theta3, targetSqrDist;&#xD;&#xA;    &#xD;&#xA;    // joints&#xD;&#xA;    var joint1 = thisComp.layer(&quot;joint 1&quot;);&#xD;&#xA;    var joint2 = thisComp.layer(&quot;joint 2&quot;);&#xD;&#xA;    var joint3 = thisComp.layer(&quot;joint 3&quot;);&#xD;&#xA;    var joint4 = thisComp.layer(&quot;joint 4&quot;);&#xD;&#xA;    &#xD;&#xA;    // segment lengths&#xD;&#xA;    var segment1Len = length(joint2.transform.position, joint1.transform.position);&#xD;&#xA;    var segment2Len = length(joint3.transform.position, joint2.transform.position);&#xD;&#xA;    var segment3Len = length(joint4.transform.position, joint3.transform.position);&#xD;&#xA;    &#xD;&#xA;    // target position&#xD;&#xA;    var target = thisComp.layer(&quot;target&quot;);&#xD;&#xA;    var ix = target.transform.position[0] - joint1.transform.position[0];&#xD;&#xA;    var iy = target.transform.position[1] - joint1.transform.position[1];&#xD;&#xA;    &#xD;&#xA;    // target square distance&#xD;&#xA;    targetSqrDist = ix * ix + iy * iy;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 1&#xD;&#xA;    angle1 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist + (segment1Len*segment1Len) - (segment2Len*segment2Len)) / (2 * segment1Len * Math.sqrt(targetSqrDist))&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta1 = Math.atan2(iy, ix) - Math.acos(angle1);&#xD;&#xA;    &#xD;&#xA;    var s1X = joint1.transform.position[0] + segment1Len * Math.cos(theta1);&#xD;&#xA;    var s1Y = joint1.transform.position[1] + segment1Len * Math.sin(theta1);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 2&#xD;&#xA;    angle2 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist - (segment1Len*segment1Len) - (segment2Len*segment2Len)) / (2 * segment1Len * segment2Len)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta2 = Math.acos(angle2);&#xD;&#xA;    &#xD;&#xA;    var s2X = s1X + segment2Len * Math.cos(theta2 + theta1);&#xD;&#xA;    var s2Y = s1Y + segment2Len * Math.sin(theta2 + theta1);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 3&#xD;&#xA;    angle3 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist - (segment2Len*segment2Len) - (segment3Len*segment3Len)) / (2 * segment2Len * segment3Len)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta3 = Math.acos(angle3);&#xD;&#xA;    &#xD;&#xA;    var s3X = s2X + segment3Len * Math.cos(theta3 + theta2);&#xD;&#xA;    var s3Y = s2Y + segment3Len * Math.sin(theta3 + theta2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This code would be applied to each joint with a unique position value assigned to it, depending on the joint's location." ContentLicense="CC BY-SA 3.0" />
  <row Id="11305" PostHistoryTypeId="2" PostId="4787" RevisionGUID="468de376-70e0-4d56-8fb9-dd19de9eba07" CreationDate="2017-03-01T09:30:44.637" UserId="38" Text="What you have here is a [Overconstrained mechanism](https://en.wikipedia.org/wiki/Overconstrained_mechanism)\*. To solve this problem you do what you do to any other over constrained system. This is also why you mostly only see the 2 joint version as it is not over constrained in the planar solution, and in any case the preregistration is trivial.&#xD;&#xA;&#xD;&#xA;Basically you have 2 options:&#xD;&#xA;&#xD;&#xA;* Add more constraints&#xD;&#xA;* Deal with the freedom&#xD;&#xA;&#xD;&#xA;Adding more constraints to the system reduces the degrees of freedom. For example if you only permit one of the joint to rotate about its z axis and the another around its X axis then y then you have reduced the problem to the same 2 member problem. Another way to constrain it is  force the orientation of the last link. This also reduces it to the same case as 2 links. But there are other meaningful ways to reduce complexity that depend on your application.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1: Costraining one member reduces problem to a 2 member problem. In planar case that means 2 solutions (other in blue).&#xD;&#xA;&#xD;&#xA;Dealing with the freedom just means that your answer is going to be a family of answers. Then you develop a way to choose the solution form that family. Letting user adjust the parameter is equivalent to adding one more constraint. But there are other methods such as least squares, or energy methods that yield different results. Sky is the limit here. For example I have worked with robot controllers that decided the overcosntraint based on what was the least amount of rotation on joints. The problem was that this wasn't entirely detertministic so over time the robot ended to do things differently...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* This is more suited to Engineering.SE but since IK is a common graphics problem lets deal with it here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OoFDT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11307" PostHistoryTypeId="5" PostId="4787" RevisionGUID="f620d31c-5da8-47ef-a7ba-595f5cabdcb4" CreationDate="2017-03-01T09:42:12.810" UserId="38" Comment="deleted 61 characters in body" Text="What you have here is a overconstrained problem\*. To solve this problem you do what you do to any other over constrained system. This is also why you mostly only see the 2 joint version as it is not over constrained in the planar solution, and in any case the preregistration is trivial.&#xD;&#xA;&#xD;&#xA;Basically you have 2 options:&#xD;&#xA;&#xD;&#xA;* Add more constraints&#xD;&#xA;* Deal with the freedom&#xD;&#xA;&#xD;&#xA;Adding more constraints to the system reduces the degrees of freedom. For example if you only permit one of the joint to rotate about its z axis and the another around its X axis then y then you have reduced the problem to the same 2 member problem. Another way to constrain it is  force the orientation of the last link. This also reduces it to the same case as 2 links. But there are other meaningful ways to reduce complexity that depend on your application.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1: Costraining one member reduces problem to a 2 member problem. In planar case that means 2 solutions (other in blue).&#xD;&#xA;&#xD;&#xA;Dealing with the freedom just means that your answer is going to be a family of answers. Then you develop a way to choose the solution form that family. Letting user adjust the parameter is equivalent to adding one more constraint. But there are other methods such as least squares, or energy methods that yield different results. Sky is the limit here. For example I have worked with robot controllers that decided the overcosntraint based on what was the least amount of rotation on joints. The problem was that this wasn't entirely detertministic so over time the robot ended to do things differently...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* This is more suited to Engineering.SE but since IK is a common graphics problem lets deal with it here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OoFDT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11308" PostHistoryTypeId="5" PostId="4787" RevisionGUID="5e78f4c4-e4ab-481f-b4b1-6f086618a0ea" CreationDate="2017-03-01T12:47:09.507" UserId="38" Comment="deleted 7 characters in body" Text="What you have here is a undercostrained problem\*. To solve this problem you do what you do to any other undercostrained system. This is also why you mostly only see the 2 joint version as it is not undercostrained in the planar solution, and in any case the preregistration is trivial.&#xD;&#xA;&#xD;&#xA;Basically you have 2 options:&#xD;&#xA;&#xD;&#xA;* Add more constraints&#xD;&#xA;* Deal with the freedom&#xD;&#xA;&#xD;&#xA;Adding more constraints to the system reduces the degrees of freedom. For example if you only permit one of the joint to rotate about its z axis and the another around its X axis then y then you have reduced the problem to the same 2 member problem. Another way to constrain it is  force the orientation of the last link. This also reduces it to the same case as 2 links. But there are other meaningful ways to reduce complexity that depend on your application.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1: Costraining one member reduces problem to a 2 member problem. In planar case that means 2 solutions (other in blue).&#xD;&#xA;&#xD;&#xA;Dealing with the freedom just means that your answer is going to be a family of answers. Then you develop a way to choose the solution form that family. Letting user adjust the parameter is equivalent to adding one more constraint. But there are other methods such as least squares, or energy methods that yield different results. Sky is the limit here. For example I have worked with robot controllers that decided the parameter based on what was the least amount of rotation on joints. The problem was that this wasn't entirely detertministic so over time the robot ended to do things differently...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* This is more suited to Engineering.SE but since IK is a common graphics problem lets deal with it here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OoFDT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11309" PostHistoryTypeId="5" PostId="4394" RevisionGUID="5555cb35-bb92-4679-a876-825a78b8c2b8" CreationDate="2017-03-01T14:06:15.297" UserDisplayName="user5681" Comment="added 442 characters in body" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, spectral.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations, with the exception of $F$, were extracted from the original paper. $F$, also known as the [Schlick's approximation][3], is an efficient and less accurate approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][4] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D_{new} = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr_{new}(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{D_{new}FG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;As pointed out by [PeterUK][5], the Fresnel equation presented above was not the one originally proposed by Cook and Torrance, but an efficient (and less accurate) alternative kown as the [Schlick's approximation][3]. The text above was fixed accordingly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Schlick's_approximation&#xD;&#xA;  [4]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [5]: http://computergraphics.stackexchange.com/q/4771/5681" ContentLicense="CC BY-SA 3.0" />
  <row Id="11310" PostHistoryTypeId="5" PostId="4394" RevisionGUID="3c624789-450f-43ac-8f06-29e531332019" CreationDate="2017-03-01T14:17:40.953" UserDisplayName="user5681" Comment="added 442 characters in body" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, spectral.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations, with the exception of $F$, were extracted from the original paper. $F$, also known as the [Schlick's approximation][3], is an efficient and less accurate approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][4] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D_{new} = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr_{new}(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{D_{new}FG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;As pointed out by [PeterUK][5], the authorship of the Fresnel formulation presented in the original text of my question was wrongly attributed to Cook and Torrance. The Fresnel formulation used above is actually known as the [Schlick's approximation][3] and is named after Christophe Schlick. The original text of the question was modified accordingly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Schlick's_approximation&#xD;&#xA;  [4]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [5]: http://computergraphics.stackexchange.com/q/4771/5681" ContentLicense="CC BY-SA 3.0" />
  <row Id="11311" PostHistoryTypeId="2" PostId="4788" RevisionGUID="ffac3c38-1314-45e8-923b-9cce9de53806" CreationDate="2017-03-01T14:50:43.980" UserId="6097" Text="I have 3 objects in my scene, each one is being passed to the buffer and drawn as part of a different Vertex Array Object, so for the 3 objects i have:&#xD;&#xA;`vao1`, `vao2`, `vao3`.&#xD;&#xA;&#xD;&#xA;`Object1` is drawn using `glDrawElementsInstanced`.&#xD;&#xA;&#xD;&#xA;`Object2` is drawn using `glDrawElementsInstanced`.&#xD;&#xA;&#xD;&#xA;`Object3` is drawn using `glDrawArraysInstanced`.&#xD;&#xA;&#xD;&#xA;All of those instances of all of those objects create one big object. So how can i take that big object (meaning - treat all 3 object as one) and draw it 5 times using instancing?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11312" PostHistoryTypeId="1" PostId="4788" RevisionGUID="ffac3c38-1314-45e8-923b-9cce9de53806" CreationDate="2017-03-01T14:50:43.980" UserId="6097" Text="OpenGL - how to draw instances of several objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11313" PostHistoryTypeId="3" PostId="4788" RevisionGUID="ffac3c38-1314-45e8-923b-9cce9de53806" CreationDate="2017-03-01T14:50:43.980" UserId="6097" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11314" PostHistoryTypeId="5" PostId="4787" RevisionGUID="c45f76a8-56a5-4ea8-bc8d-6fb56a7e2ec2" CreationDate="2017-03-01T15:35:05.323" UserId="38" Comment="added 2 characters in body" Text="What you have here is a undercostrained problem\*. To solve this problem you do what you do to any other undercostrained system. This is also why you mostly only see the 2 joint version as it is not undercostrained in the planar solution, and in any case the preregistration is trivial.&#xD;&#xA;&#xD;&#xA;Basically you have 2 options:&#xD;&#xA;&#xD;&#xA;* Add more constraints&#xD;&#xA;* Deal with the freedom&#xD;&#xA;&#xD;&#xA;Adding more constraints to the system reduces the degrees of freedom. For example if you only permit one of the joint to rotate about its z axis and the another around its X axis then y then you have reduced the problem to the same 2 member problem. Another way to constrain it is  force the orientation of the last link. This also reduces it to the same case as 2 links. But there are other meaningful ways to reduce complexity that depend on your application.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Costraining one member reduces problem to a 2 member problem. In planar case that means 2 solutions (other in blue).&#xD;&#xA;&#xD;&#xA;Dealing with the freedom just means that your answer is going to be a family of answers. Then you develop a way to choose the solution form that family. Letting user adjust the parameter is equivalent to adding one more constraint. But there are other methods such as least squares, or energy methods that yield different results. Sky is the limit here. For example I have worked with robot controllers that decided the parameter based on what was the least amount of rotation on joints. The problem was that this wasn't entirely detertministic so over time the robot ended to do things differently...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* This is more suited to Engineering.SE but since IK is a common graphics problem lets deal with it here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OoFDT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11315" PostHistoryTypeId="5" PostId="4764" RevisionGUID="9c606639-4124-400d-896f-025fdec85a5c" CreationDate="2017-03-01T18:57:24.860" UserId="2076" Comment="added 95 characters in body" Text="I'm building a 2D inverse kinematics system and can't figure out how to find all the joint positions. I have the math to make a typical IK set up with a single bend (e.g. arm, leg), but I get stuck when adding another bend.&#xD;&#xA;&#xD;&#xA;**How do I find the position of all joints for an inverse kinematic chain that is longer than 2 segments?**&#xD;&#xA;&#xD;&#xA;Here's an example of the planar solution I'm looking for: https://youtu.be/3sqd_CZNq7s?t=6s&#xD;&#xA;&#xD;&#xA;I'm building this in Adobe After Effects so using an existing IK solver isn't going to work.&#xD;&#xA;&#xD;&#xA;Here's my visual setup for reference:&#xD;&#xA;&#xD;&#xA;![ik reference](https://i.stack.imgur.com/eQknI.png)&#xD;&#xA;&#xD;&#xA;What I'm aiming for is that when the blue box is moved (target) joints 2 and 3 bend appropriately to maintain their length. Joint 1 is static and doesn't move.&#xD;&#xA;&#xD;&#xA;To make this work, I need x,y coordinates to be calculated in real time. No need to render anything on screen—just the position values for each joint.&#xD;&#xA;&#xD;&#xA;Here's my javascript so far:&#xD;&#xA;&#xD;&#xA;    var angle1, angle2, angle3, theta1, theta2, theta3, targetSqrDist;&#xD;&#xA;    &#xD;&#xA;    // joints&#xD;&#xA;    var joint1 = thisComp.layer(&quot;joint 1&quot;);&#xD;&#xA;    var joint2 = thisComp.layer(&quot;joint 2&quot;);&#xD;&#xA;    var joint3 = thisComp.layer(&quot;joint 3&quot;);&#xD;&#xA;    var joint4 = thisComp.layer(&quot;joint 4&quot;);&#xD;&#xA;    &#xD;&#xA;    // segment lengths&#xD;&#xA;    var segment1Len = length(joint2.transform.position, joint1.transform.position);&#xD;&#xA;    var segment2Len = length(joint3.transform.position, joint2.transform.position);&#xD;&#xA;    var segment3Len = length(joint4.transform.position, joint3.transform.position);&#xD;&#xA;    &#xD;&#xA;    // target position&#xD;&#xA;    var target = thisComp.layer(&quot;target&quot;);&#xD;&#xA;    var ix = target.transform.position[0] - joint1.transform.position[0];&#xD;&#xA;    var iy = target.transform.position[1] - joint1.transform.position[1];&#xD;&#xA;    &#xD;&#xA;    // target square distance&#xD;&#xA;    targetSqrDist = ix * ix + iy * iy;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 1&#xD;&#xA;    angle1 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist + (segment1Len*segment1Len) - (segment2Len*segment2Len)) / (2 * segment1Len * Math.sqrt(targetSqrDist))&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta1 = Math.atan2(iy, ix) - Math.acos(angle1);&#xD;&#xA;    &#xD;&#xA;    var s1X = joint1.transform.position[0] + segment1Len * Math.cos(theta1);&#xD;&#xA;    var s1Y = joint1.transform.position[1] + segment1Len * Math.sin(theta1);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 2&#xD;&#xA;    angle2 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist - (segment1Len*segment1Len) - (segment2Len*segment2Len)) / (2 * segment1Len * segment2Len)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta2 = Math.acos(angle2);&#xD;&#xA;    &#xD;&#xA;    var s2X = s1X + segment2Len * Math.cos(theta2 + theta1);&#xD;&#xA;    var s2Y = s1Y + segment2Len * Math.sin(theta2 + theta1);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Segment 3&#xD;&#xA;    angle3 = Math.max(-1, Math.min( 1, &#xD;&#xA;    	(targetSqrDist - (segment2Len*segment2Len) - (segment3Len*segment3Len)) / (2 * segment2Len * segment3Len)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    theta3 = Math.acos(angle3);&#xD;&#xA;    &#xD;&#xA;    var s3X = s2X + segment3Len * Math.cos(theta3 + theta2);&#xD;&#xA;    var s3Y = s2Y + segment3Len * Math.sin(theta3 + theta2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This code would be applied to each joint with a unique position value assigned to it, depending on the joint's location." ContentLicense="CC BY-SA 3.0" />
  <row Id="11316" PostHistoryTypeId="5" PostId="4787" RevisionGUID="b33ddea4-95a4-4a60-ad22-cb714e561060" CreationDate="2017-03-01T19:47:55.513" UserId="231" Comment="Typos" Text="What you have here is an underconstrained problem\*. To solve this problem you do what you do to any other underconstrained system. This is also why you mostly only see the 2 joint version as it is not underconstrained in the planar solution, and in any case the preregistration is trivial.&#xD;&#xA;&#xD;&#xA;Basically you have 2 options:&#xD;&#xA;&#xD;&#xA;* Add more constraints&#xD;&#xA;* Deal with the freedom&#xD;&#xA;&#xD;&#xA;Adding more constraints to the system reduces the degrees of freedom. For example if you only permit one of the joints to rotate about its z axis and the another around its x axis then y then you have reduced the problem to the same 2 member problem. Another way to constrain it is to force the orientation of the last link. This also reduces it to the same case as 2 links. But there are other meaningful ways to reduce complexity that depend on your application.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Constraining one member reduces the problem to a 2 member problem. In the planar case that means 2 solutions (other in blue).&#xD;&#xA;&#xD;&#xA;Dealing with the freedom just means that your answer is going to be a family of answers. Then you develop a way to choose the solution from that family. Letting the user adjust the parameter is equivalent to adding one more constraint. But there are other methods such as least squares, or energy methods that yield different results. Sky is the limit here. For example I have worked with robot controllers that decided the parameter based on what was the least amount of rotation on joints. The problem was that this wasn't entirely deterministic so over time the robot ended up doing things differently...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* This is more suited to Engineering.SE but since IK is a common graphics problem lets deal with it here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OoFDT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11317" PostHistoryTypeId="2" PostId="4789" RevisionGUID="11ef4663-828b-4234-88e4-9e752ca882e0" CreationDate="2017-03-02T02:12:58.190" UserId="6140" Text="To solve the problem, we will flow three steps, first, calculate translation matrix, second, calculate rotation matrix, third, get transformation matrix.&#xD;&#xA;&#xD;&#xA;Because translation is a *affine transformation*, we need to use a 4x4 matrix to represent translation. I find you use column vector post-multiply matrix. the result of the translation matrix is same as yours.&#xD;&#xA;     &#xD;&#xA;   Translation matrix = [![translation matrix][1]][1]&#xD;&#xA;&#xD;&#xA;Then, same as your idea, we use basis vectors(same as unit vectors of the coordinate axes) to calculate rotation matrix.&#xD;&#xA;&#xD;&#xA; 1. basis **z** vector: we can get rotated basis **z** vector by using a vector from VRP to point A, and normalize it.&#xD;&#xA;  &#xD;&#xA;   **z** = **b**(VRP) - **a** = [5,-2,1] - [1,1,1] = [4,-3,0] ,then, normalize to [0.8,-0.6,0]&#xD;&#xA; 2. basis **x** vector: we know basis vector is a vector perpendicular to **z-up** plane, we get the **x** vector by cross product **up** and **z**&#xD;&#xA;   &#xD;&#xA; **x** = **up** x **z** = [1,1,1] x [0.8 ,-0.6 ,0] = [0.6, 0.8, 0]&#xD;&#xA; 3. basis **y** vector, **y** is prependicular to **z-x** plane.&#xD;&#xA;&#xD;&#xA; **y** = **z** x **x** = [0.8 ,-0.6, 0] x [0.6, 0.8, 0] = [0, 0, 1]&#xD;&#xA;&#xD;&#xA; finally, the rotation matrix is:&#xD;&#xA;&#xD;&#xA; Rotation Matrix = &#xD;&#xA;       [![rotation matrix][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; The 4x4 matrix is:&#xD;&#xA;&#xD;&#xA; Transformation matrix = [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA; Refer to [3D Math Primer for Graphics and Game Developmen][4].&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lk5Xn.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/gmygD.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/8ue8L.gif&#xD;&#xA;  [4]: https://tfetimes.com/wp-content/uploads/2015/04/F.Dunn-I.Parberry-3D-Math-Primer-for-Graphics-and-Game-Development.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11319" PostHistoryTypeId="50" PostId="4635" RevisionGUID="fcbfdda6-9100-429b-b843-44ff467348c9" CreationDate="2017-03-02T05:44:32.570" UserId="-1" />
  <row Id="11320" PostHistoryTypeId="5" PostId="4789" RevisionGUID="12f7d87d-960c-49c3-a666-0a9d03091039" CreationDate="2017-03-02T06:06:33.543" UserId="6140" Comment="added 192 characters in body" Text="To solve the problem, we will flow three steps, first, calculate translation matrix, second, calculate rotation matrix, third, get transformation matrix.&#xD;&#xA;&#xD;&#xA;Because translation is a *affine transformation*, we need to use a 4x4 matrix to represent translation. I find you use column vector post-multiply matrix. the result of the translation matrix is same as yours.&#xD;&#xA;     &#xD;&#xA;   Translation matrix = [![translation matrix][1]][1]&#xD;&#xA;&#xD;&#xA;Then, same as your idea, we use basis vectors(same as unit vectors of the coordinate axes) to calculate rotation matrix.&#xD;&#xA;&#xD;&#xA; 1. basis **z** vector: we can get rotated basis **z** vector by using a vector from VRP to point A, and normalize it.&#xD;&#xA;  &#xD;&#xA;   **z** = **b**(VRP) - **a** = [5,-2,1] - [1,1,1] = [4,-3,0] ,then, normalize to [0.8,-0.6,0]&#xD;&#xA; 2. basis **x** vector: we know basis vector is a vector perpendicular to **z-up** plane, we get the **x** vector by cross product **up** and **z**&#xD;&#xA;   &#xD;&#xA; **x** = **up** x **z** = [1,1,1] x [0.8 ,-0.6 ,0] = [0.6, 0.8, 0]&#xD;&#xA; 3. basis **y** vector, **y** is prependicular to **z-x** plane.&#xD;&#xA;&#xD;&#xA; **y** = **z** x **x** = [0.8 ,-0.6, 0] x [0.6, 0.8, 0] = [0, 0, 1]&#xD;&#xA;&#xD;&#xA; finally, the rotation matrix is:&#xD;&#xA;&#xD;&#xA; Rotation Matrix = &#xD;&#xA;       [![rotation matrix][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; The 4x4 matrix is:&#xD;&#xA;&#xD;&#xA; Transformation matrix = [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA; The transformation matrix is a matrix from *Object Space* to *World Space*, we should invert this matrix to get *World Space* to *Camera Space* matrix.(Thanks for @JarkkoL correcting me).&#xD;&#xA;&#xD;&#xA; Refer to [3D Math Primer for Graphics and Game Developmen][4].&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lk5Xn.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/gmygD.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/8ue8L.gif&#xD;&#xA;  [4]: https://tfetimes.com/wp-content/uploads/2015/04/F.Dunn-I.Parberry-3D-Math-Primer-for-Graphics-and-Game-Development.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11324" PostHistoryTypeId="2" PostId="4791" RevisionGUID="1798b544-c259-440c-bbf5-1f3215352139" CreationDate="2017-03-02T14:21:09.160" UserId="6157" Text="Having taken a basic CG course, I remember that transformations are relative, so rotating the camera is identical to rotating the view in the opposite direction. Right now I want to implement camera rotation using the mouse. In OpenGL, I can see the family of functions called `lookAt()` as implemented by the various libraries. However, those take vectors for camera positions. I feel it is incorrect to calculate the vector for camera position when we can rotate the world with a matrix transformation, e.g. using quaternions (as implemented handily by Qt5 or GLM). Thus, is it a correct and adopted solution to apply a transformation to the `model` matrix as opposed to the `view` matrix in the following line of code:&#xD;&#xA;&#xD;&#xA;    gl_Position = proj * view * model * vec4(position, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;ref. https://open.gl/transformations, subsection &quot;*Going 3D*&quot;?&#xD;&#xA;&#xD;&#xA;Or, should I rather apply a rotation transformation as defined by a matrix received using quaternion algebra analogous to the solution above, but, this time around, to the matrix position vector? Will those be identical? (My common sense tells me they will only be identical if the camera is pointing to 0 and the object is located at point 0 - but I lack the required knowledge about transformations yet.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11325" PostHistoryTypeId="1" PostId="4791" RevisionGUID="1798b544-c259-440c-bbf5-1f3215352139" CreationDate="2017-03-02T14:21:09.160" UserId="6157" Text="With OpenGL, is it correct to apply model transformation to rotate the camera?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11326" PostHistoryTypeId="3" PostId="4791" RevisionGUID="1798b544-c259-440c-bbf5-1f3215352139" CreationDate="2017-03-02T14:21:09.160" UserId="6157" Text="|opengl|transformations|glm|camera-matrix|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11327" PostHistoryTypeId="2" PostId="4792" RevisionGUID="139ab575-7f76-441f-8f8f-de2b06c91c31" CreationDate="2017-03-02T16:13:49.933" UserId="5764" Text="I've got my path tracer working great for a single light, but I'm having trouble coming up with a solution for scenes with multiple lights. My first thought was to just send a ray to each light and sum up all the contributions. That worked fine, but it was very slow, especially for many lights. I tried researching techniques for working around this, but I found very little. I did find that some renderers weight each light and then pick one based on how much light they might contribute, but I couldn't find any detailed process of how that's actually done.&#xD;&#xA;&#xD;&#xA;So my question is, could someone give me an overview of how this might be accomplished, or point me to a resource that goes over multiple lights? &#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11328" PostHistoryTypeId="1" PostId="4792" RevisionGUID="139ab575-7f76-441f-8f8f-de2b06c91c31" CreationDate="2017-03-02T16:13:49.933" UserId="5764" Text="Path Tracing With Multiple Lights" ContentLicense="CC BY-SA 3.0" />
  <row Id="11329" PostHistoryTypeId="3" PostId="4792" RevisionGUID="139ab575-7f76-441f-8f8f-de2b06c91c31" CreationDate="2017-03-02T16:13:49.933" UserId="5764" Text="|lighting|pathtracing|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11330" PostHistoryTypeId="2" PostId="4793" RevisionGUID="bdfe617c-dfe0-4a43-bc65-0472622fe268" CreationDate="2017-03-02T19:02:11.807" UserId="5852" Text="OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(dis)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11331" PostHistoryTypeId="1" PostId="4793" RevisionGUID="bdfe617c-dfe0-4a43-bc65-0472622fe268" CreationDate="2017-03-02T19:02:11.807" UserId="5852" Text="How I can generate mipmaps manually?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11332" PostHistoryTypeId="3" PostId="4793" RevisionGUID="bdfe617c-dfe0-4a43-bc65-0472622fe268" CreationDate="2017-03-02T19:02:11.807" UserId="5852" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11333" PostHistoryTypeId="5" PostId="4793" RevisionGUID="3ff365cc-7c66-4fb3-97f3-180e47db35b6" CreationDate="2017-03-02T19:52:18.697" UserId="5852" Comment="added 430 characters in body" Text="OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(dis)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;For any reason, these two lines doesn't work together&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);" ContentLicense="CC BY-SA 3.0" />
  <row Id="11334" PostHistoryTypeId="2" PostId="4794" RevisionGUID="c2925786-5350-47a0-acaa-879b698787b1" CreationDate="2017-03-02T20:13:40.953" UserId="5852" Text="Nearest interpolation between 2 texels mean to take the texel whose center is nearest to a given coordinate to draw or, in other words, the texel the coordinate is matching.&#xD;&#xA;&#xD;&#xA;Linear interpolation between 2 texels mean to mix the colors of them using more of the nearest texel and less of the others according to the distance to a certain coordinate.&#xD;&#xA;&#xD;&#xA;Nearest interpolation between 2 mipmap levels consist in to take the mipmap whose size fits better the size of the image to draw&#xD;&#xA;&#xD;&#xA;But I cannot understand how linear interpolation works with mipmap levels. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11335" PostHistoryTypeId="1" PostId="4794" RevisionGUID="c2925786-5350-47a0-acaa-879b698787b1" CreationDate="2017-03-02T20:13:40.953" UserId="5852" Text="How linear interpolation works between mipmaps?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11336" PostHistoryTypeId="3" PostId="4794" RevisionGUID="c2925786-5350-47a0-acaa-879b698787b1" CreationDate="2017-03-02T20:13:40.953" UserId="5852" Text="|opengl|image-processing|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11337" PostHistoryTypeId="4" PostId="4793" RevisionGUID="55f8c553-dc19-4763-bc04-dc3ee8ec1f6d" CreationDate="2017-03-02T20:15:12.493" UserId="5852" Comment="edited title" Text="How can I generate mipmaps manually?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11338" PostHistoryTypeId="2" PostId="4795" RevisionGUID="fad51880-74c8-45cb-9d56-5894c4a518ad" CreationDate="2017-03-02T22:42:02.590" UserId="38" Text="Since you have a limited set of tools you are not actually doing a classical fitting. What you have is a discrete problem. And since you are looking for a somwehat easysily drawn fit, no more that twice segmented for example.&#xD;&#xA;&#xD;&#xA;One way to approach this is to find all the points that match your curvature requirements. Then find the point x units away from point on both ends for all of these see how well it matches. If the curvature match at the endpoint is too much off then this isnt a good candidate. If you dont find a good candidate split the problem into two. Omce you have found a goodish candidate slide the result to see if relaxing the thing makes the error more symmetric.&#xD;&#xA;&#xD;&#xA;Some things to note. Since your french curve is accelerating from one end to another you need to split beziers and b-splines at each span where the curve changes direction. Also be one youve found a good endpoints be sure to check that the halfway isnt too much off.&#xD;&#xA;&#xD;&#xA;Now if you want to do a classical fitting like approach then you need to parametrize the sliding and scale of your curve. This is not likely useful since you in fact can not scale your rules at whim.&#xD;&#xA;&#xD;&#xA;Or then you could just get a spline, you know one of those things that were used before computers and stuff, and write instructions on how to set up the spline." ContentLicense="CC BY-SA 3.0" />
  <row Id="11339" PostHistoryTypeId="2" PostId="4796" RevisionGUID="cbb8550d-3abd-41fc-80cd-5c51f2548323" CreationDate="2017-03-02T23:21:24.430" UserId="6160" Text="If I understand the general idea correctly, you are going to close the gaps which are appearing after further structure growth. I cannot do it algorithmically but geometrically it is quite easy to do. I use Illustrator here and manually cover the gaps with two additional shapes.  &#xD;&#xA;&#xD;&#xA;So in addition to the pentagon and flat rhombus, I will need a 5-fold star and another rhombus:  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So after first steps we get such a structure and the filling will be:  &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;(Initial center is marked red)  &#xD;&#xA;&#xD;&#xA;I don't fill all holes and I leave out the obvious ones just to make arrangements more visible.&#xD;&#xA;&#xD;&#xA;Then next step will give this:  &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here I do only halves of crack fillings, those are symmetrical. As seen those cracks indeed can be covered using same shapes without gaps and have self-similar patterns. How this can be achieved algorithmically, I don't know unfortunatelly. But this is interesting question, probably there are solutions somewhere, IDK.  &#xD;&#xA;&#xD;&#xA;Theoretically if one analyse several crack fillings for each step, one can guess a relatively&#xD;&#xA;simple algorithm.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5J0CX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Xjcoj.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/d75He.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11340" PostHistoryTypeId="2" PostId="4797" RevisionGUID="2811b6ef-d40e-450b-9191-6853b009ebc4" CreationDate="2017-03-02T23:52:29.450" UserId="3003" Text="It's called [trilinear interpolation](https://en.wikipedia.org/wiki/Trilinear_interpolation). You first do a bilinear interpolation of the higher-res texture, then do a bilinear interpolation on the lower-res texture, then interpolate between the 2 results. The weight of the final interpolation is based on where between the 2 textures your Z-coordinate falls. If 0 is fully the low-res texture and 1 is fully the high-res texture, then you can use the standard glsl `mix()` function to combine the two:&#xD;&#xA;&#xD;&#xA;    result = (highres texture color * weight) + (lowres texture color * (1.0 - weight));&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11341" PostHistoryTypeId="5" PostId="4394" RevisionGUID="f564224b-464f-410c-8633-b3d8a1a0b4dc" CreationDate="2017-03-03T02:10:34.880" UserDisplayName="user5681" Comment="deleted 1 character in body" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, spectral.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations, with the exception of $F$, were extracted from the original paper. $F$, also known as the [Schlick's approximation][3], is an efficient and less accurate approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][4] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D_{new} = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr_{new}(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{D_{new}FG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;As pointed out by [PeteUK][5], the authorship of the Fresnel formulation presented in the original text of my question was wrongly attributed to Cook and Torrance. The Fresnel formulation used above is actually known as the [Schlick's approximation][3] and is named after Christophe Schlick. The original text of the question was modified accordingly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Schlick's_approximation&#xD;&#xA;  [4]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [5]: http://computergraphics.stackexchange.com/q/4771/5681" ContentLicense="CC BY-SA 3.0" />
  <row Id="11342" PostHistoryTypeId="2" PostId="4798" RevisionGUID="271185c7-5971-4c37-a226-e9c361c7c66c" CreationDate="2017-03-03T05:44:19.293" UserId="4848" Text="Recently, I am writing a simple software rasterizer for self-studying and fun. But the texture mapping has problems. The texture I want to map is below:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Texture][1]][1] &#xD;&#xA;&#xD;&#xA;But the final image of two triangles is problematic, it shows below:&#xD;&#xA;&#xD;&#xA;[![final image][2]][2]&#xD;&#xA;&#xD;&#xA;The triangle rasterizing algorithm I use is the Triangle barycentric coordinates interpolation. It seems the mapping of second triangle is not correct. My code is below, As the code shows, the three vertices of the triangle is, p1, p2, p3.&#xD;&#xA;&#xD;&#xA;I hope someone can help me to fix the problem. Thanks very much!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    if (mRenderState &amp; (RENDERING_TEXTURE | RENDERING_COLOR))&#xD;&#xA;    {&#xD;&#xA;        int x0 = p1.x();&#xD;&#xA;        int x1 = p2.x();&#xD;&#xA;        int x2 = p3.x();&#xD;&#xA;        int y0 = p1.y();&#xD;&#xA;        int y1 = p2.y();&#xD;&#xA;        int y2 = p3.y();&#xD;&#xA;&#xD;&#xA;        //Firstly build the bounding box&#xD;&#xA;        int xMin = std::min(x0, std::min(x1, x2));&#xD;&#xA;        int xMax = std::max(x0, std::max(x1, x2));&#xD;&#xA;        int yMin = std::min(y0, std::min(y1, y2));&#xD;&#xA;        int yMax = std::max(y0, std::max(y1, y2));&#xD;&#xA;&#xD;&#xA;        // Triangle setup.&#xD;&#xA;        // Compute the edge equation coefficients.&#xD;&#xA;        float edge_a_0 = -(y1 - y0);&#xD;&#xA;        float edge_a_1 = -(y2 - y1);&#xD;&#xA;        float edge_a_2 = -(y0 - y2);&#xD;&#xA;&#xD;&#xA;        float edge_b_0 =   x1 - x0;&#xD;&#xA;        float edge_b_1 =   x2 - x1;&#xD;&#xA;        float edge_b_2 =   x0 - x2;&#xD;&#xA;&#xD;&#xA;        float edge_c_0 = edge_a_0 * -x0 + edge_b_0 * -y0;&#xD;&#xA;        float edge_c_1 = edge_a_1 * -x1 + edge_b_1 * -y1;&#xD;&#xA;        float edge_c_2 = edge_a_2 * -x2 + edge_b_2 * -y2;&#xD;&#xA;&#xD;&#xA;        // Triangle area and inverse area&#xD;&#xA;        float area = 0.5f * ((x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0));&#xD;&#xA;        float inv2Area = 1.f / (2.f * area);&#xD;&#xA;&#xD;&#xA;        // Check the triangle is backfacing.&#xD;&#xA;        if (area &lt;= 0.)&#xD;&#xA;            return;&#xD;&#xA;&#xD;&#xA;        // Loop over the bounding box of the pixels that the triangle possibly&#xD;&#xA;        // covers.&#xD;&#xA;        int py;&#xD;&#xA;        int px;&#xD;&#xA;        for (int py = yMin; py &lt; yMax; ++py)&#xD;&#xA;        for (int px = xMin; px &lt; xMax; ++px)&#xD;&#xA;        {&#xD;&#xA;            float e0 = edge_a_0 * px + edge_b_0 * py + edge_c_0;&#xD;&#xA;            float e1 = edge_a_1 * px + edge_b_1 * py + edge_c_1;&#xD;&#xA;            float e2 = edge_a_2 * px + edge_b_2 * py + edge_c_2;&#xD;&#xA;&#xD;&#xA;            //Check the sample is outside the triangle&#xD;&#xA;            if (e0 &lt;= 0.f || e1 &lt;= 0.f || e2 &lt;= 0.f)&#xD;&#xA;                continue;&#xD;&#xA;&#xD;&#xA;            float wt0 = e1 * inv2Area;&#xD;&#xA;            float wt1 = e2 * inv2Area;&#xD;&#xA;            float wt2 = e0 * inv2Area;&#xD;&#xA;&#xD;&#xA;            // Interpolate z&#xD;&#xA;            float z = (wt0 * p1.z() + wt1 * p2.z() + wt2 * p3.z());&#xD;&#xA;            float zrhw = 1.0f / z;&#xD;&#xA;&#xD;&#xA;            if (z &lt; mZBuffer[py*mWidth + px])&#xD;&#xA;            {&#xD;&#xA;                mZBuffer[py*mWidth + px] = z;&#xD;&#xA;&#xD;&#xA;                if (mRenderState &amp; RENDERING_COLOR)&#xD;&#xA;                {&#xD;&#xA;                    float r = wt0 * v1-&gt;r + wt1 * v2-&gt;r + wt2 * v3-&gt;r;&#xD;&#xA;                    float g = wt0 * v1-&gt;g + wt1 * v2-&gt;g + wt2 * v3-&gt;g;&#xD;&#xA;                    float b = wt0 * v1-&gt;b + wt1 * v2-&gt;b + wt2 * v3-&gt;b;&#xD;&#xA;					DrawPixel(px, py, Color(r, g, b));&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (mRenderState &amp; RENDERING_TEXTURE)&#xD;&#xA;                {&#xD;&#xA;                    float u = wt0 * v1-&gt;u + wt1 * v2-&gt;u + wt2 * v3-&gt;u;&#xD;&#xA;                    float v = wt0 * v1-&gt;v + wt1 * v2-&gt;v + wt2 * v3-&gt;v;&#xD;&#xA;                    unsigned int cc = TextureRead(u, v);&#xD;&#xA;                    unsigned char r = (cc &amp; (0xff &lt;&lt; 16)) &gt;&gt; 16;&#xD;&#xA;                    unsigned char g = (cc &amp; (0xff &lt;&lt; 8 )) &gt;&gt; 8;&#xD;&#xA;                    unsigned char b = cc &amp; (0xff);&#xD;&#xA;                    Color color;&#xD;&#xA;                    color.setColor(r, g, b);&#xD;&#xA;                    DrawPixel(px, py, color);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8xj8w.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/lqNhi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11343" PostHistoryTypeId="1" PostId="4798" RevisionGUID="271185c7-5971-4c37-a226-e9c361c7c66c" CreationDate="2017-03-03T05:44:19.293" UserId="4848" Text="What happen to my texture mapping?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11344" PostHistoryTypeId="3" PostId="4798" RevisionGUID="271185c7-5971-4c37-a226-e9c361c7c66c" CreationDate="2017-03-03T05:44:19.293" UserId="4848" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11345" PostHistoryTypeId="34" PostId="4737" RevisionGUID="1046890b-12da-4bc5-98af-04d3050c6db9" CreationDate="2017-03-03T08:40:22.497" UserId="5513" Comment="25" />
  <row Id="11346" PostHistoryTypeId="2" PostId="4799" RevisionGUID="193391b2-7384-4c8e-b2a0-c5ac6008c1bb" CreationDate="2017-03-03T12:25:02.800" UserId="209" Text="You aren't doing perspective correct texturing. Per pixel, you need to be computing U and V with the equivalent of:&#xD;&#xA;&#xD;&#xA;$U=\frac{aX+bY+c}{pX+qY+r}$&#xD;&#xA;&#xD;&#xA;$V=\frac{dX+eY+f}{pX+qY+r}$&#xD;&#xA;&#xD;&#xA;The denominator of both is linearly interpolating 1/W, while the numerators are, respectively, interpolating U/W and V/W.  &#xD;&#xA;&#xD;&#xA;I.E. for each triangle vertex you need to compute 1/W, U/W and V/W and then interpolate these. You can do it via barycentrics if you wish but you must do the division per pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="11347" PostHistoryTypeId="2" PostId="4800" RevisionGUID="904a0f12-ffdf-4de3-b4f3-f789fe6132d3" CreationDate="2017-03-03T12:44:18.320" UserId="209" Text="You might find the 1983 paper that introduced this, i.e. [Lance Williams' &quot;Pyramidal Parametrics&quot;](https://classes.soe.ucsc.edu/cmps160/Fall05/papers/p1-williams.pdf) informative.  &#xD;&#xA;&#xD;&#xA;You can ignore the scheme, in Figure 1, he used for the layout of the MIP maps as I doubt any hardware, at least in the 2 decades, used that approach." ContentLicense="CC BY-SA 3.0" />
  <row Id="11348" PostHistoryTypeId="5" PostId="4800" RevisionGUID="eb58868e-7b96-4781-80f5-177e0a5019fd" CreationDate="2017-03-03T12:52:30.723" UserId="209" Comment="added 167 characters in body" Text="You might find the 1983 paper that introduced this**, i.e. [Lance Williams' &quot;Pyramidal Parametrics&quot;](https://classes.soe.ucsc.edu/cmps160/Fall05/papers/p1-williams.pdf) informative.  &#xD;&#xA;&#xD;&#xA;You can ignore the scheme, in Figure 1, he used for the layout of the MIP maps as I doubt any hardware, at least in the 2 decades, used that approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  ** _(Actually, Williams *may* have described the technique at an earlier SIGGRAPH as part of tutorial/course but I've never been able to get hold of a copy)_" ContentLicense="CC BY-SA 3.0" />
  <row Id="11349" PostHistoryTypeId="5" PostId="4799" RevisionGUID="5762bc1b-ae4c-4349-8451-5df3f3ebe1ad" CreationDate="2017-03-03T14:08:30.720" UserId="209" Comment="made X,Y coordinates clearer" Text="You aren't doing perspective correct texturing. At each pixel, $(X,Y)$, you need to be computing U and V with the equivalent of:&#xD;&#xA;&#xD;&#xA;$U=\frac{aX+bY+c}{pX+qY+r}$&#xD;&#xA;&#xD;&#xA;$V=\frac{dX+eY+f}{pX+qY+r}$&#xD;&#xA;&#xD;&#xA;The denominator of both is linearly interpolating 1/W, while the numerators are, respectively, interpolating U/W and V/W.  &#xD;&#xA;&#xD;&#xA;I.E. for each triangle vertex you need to compute 1/W, U/W and V/W and then interpolate these. You can do it via barycentrics if you wish but you must do the division per pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="11350" PostHistoryTypeId="4" PostId="4798" RevisionGUID="0f557bd7-59c1-428b-88cb-2f10f46e1c43" CreationDate="2017-03-03T14:42:02.160" UserId="209" Comment="Just corrected the title" Text="What happened to my texture mapping?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11351" PostHistoryTypeId="5" PostId="4800" RevisionGUID="8e3b4b08-e340-4038-bb38-c3c59b5a905b" CreationDate="2017-03-03T14:43:59.700" UserId="209" Comment="1981 not 91!" Text="You might find the 1983 paper that introduced this**, i.e. [Lance Williams' &quot;Pyramidal Parametrics&quot;](https://classes.soe.ucsc.edu/cmps160/Fall05/papers/p1-williams.pdf) informative.  &#xD;&#xA;&#xD;&#xA;You can ignore the scheme, in Figure 1, he used for the layout of the MIP maps as I doubt any hardware, at least in the last 20+ years, used that approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  ** _(Actually, Williams *may* have described the technique at an earlier SIGGRAPH (1981) as part of tutorial/course but I've never been able to get hold of a copy)_" ContentLicense="CC BY-SA 3.0" />
  <row Id="11352" PostHistoryTypeId="2" PostId="4801" RevisionGUID="0f0aa15d-0e5f-48a8-9488-5299c44393fe" CreationDate="2017-03-03T14:44:50.877" UserId="6164" Text="I am working on a 2D lighting system for my game. My approach has been to:&#xD;&#xA;&#xD;&#xA;1. Create a transparency quad representing 'darkness'.&#xD;&#xA;2. Create a stencil shader for light sources to clip from the darkness quad.&#xD;&#xA;3. Create a shader that blends alpha from 0 -&gt; {darkness alpha} to soften the edges of the light source.&#xD;&#xA;&#xD;&#xA;This looks like the following:&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can see the problem - the two light source shaders that soften the shadow edges are being blended like normal transparency layers should and causing the colour to intensify. Here is another image without the darkness quad, which might make things a bit clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vZ77t.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bpC3M.png&#xD;&#xA;&#xD;&#xA;My question: Is there any sort of alpha blending I can do to make this intersection appear 'normal' i.e. it doesn't intensify the color? If not, is there another approach which could help with this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11353" PostHistoryTypeId="1" PostId="4801" RevisionGUID="0f0aa15d-0e5f-48a8-9488-5299c44393fe" CreationDate="2017-03-03T14:44:50.877" UserId="6164" Text="Alpha blending between two overlapping semi-transparent shapes" ContentLicense="CC BY-SA 3.0" />
  <row Id="11354" PostHistoryTypeId="3" PostId="4801" RevisionGUID="0f0aa15d-0e5f-48a8-9488-5299c44393fe" CreationDate="2017-03-03T14:44:50.877" UserId="6164" Text="|shader|transparency|unity|blending|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11356" PostHistoryTypeId="2" PostId="4803" RevisionGUID="8705ff97-c177-4c7e-a5b9-c6155b890ea5" CreationDate="2017-03-03T16:18:43.253" UserId="6167" Text="This summer I will be working with a professor on a research topic of my choice, in the field of graphics &amp; simulation. While my professor is knowledgeable in the area he is being very hands off as he does not want to make the student research his research. The intent is to use OpenGL to work on the topic.&#xD;&#xA;&#xD;&#xA;We previously had a talk about the idea of taking a scene, specifying a water level, flow direction, and then generating a heat map at that height level of water disturbance to then allow us to render a scene at low cost with &quot;semi-realistic&quot; water flow.&#xD;&#xA;&#xD;&#xA;While this idea interests me, I was looking to try to look into more ideas regarding fluid's or possible other area's of the field to attempt to find other possible projects.&#xD;&#xA;&#xD;&#xA;In short, what would be a good place to look for entry level research projects regarding computer graphics? Or just idea's in general to help steer a beginner." ContentLicense="CC BY-SA 3.0" />
  <row Id="11357" PostHistoryTypeId="1" PostId="4803" RevisionGUID="8705ff97-c177-4c7e-a5b9-c6155b890ea5" CreationDate="2017-03-03T16:18:43.253" UserId="6167" Text="Beginner CG Research Project" ContentLicense="CC BY-SA 3.0" />
  <row Id="11358" PostHistoryTypeId="3" PostId="4803" RevisionGUID="8705ff97-c177-4c7e-a5b9-c6155b890ea5" CreationDate="2017-03-03T16:18:43.253" UserId="6167" Text="|opengl|rendering|3d|mathematics|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11359" PostHistoryTypeId="2" PostId="4804" RevisionGUID="023d6d4c-cf49-4f65-9cae-6ad484f81115" CreationDate="2017-03-03T17:40:26.487" UserId="6165" Text="**This [question][1] is comming from ComputerScience after suggestion**&#xD;&#xA;&#xD;&#xA;I'm trying to understand the Naive Surface Nets algorithm which is related to surface generation out of Voxels. I've learned of it [here][2]&#xD;&#xA;&#xD;&#xA;I already understood how the marching cubes algorithm works but not how the interpolation works. Especially the definition of Voxel is unclear to me? I understood that Voxels are in pseudo code:&#xD;&#xA;&#xD;&#xA;    type Voxel = &#xD;&#xA;            val scalar:float&#xD;&#xA;&#xD;&#xA;Is this correct?  If not please explain me the correct interpretation of it.&#xD;&#xA;&#xD;&#xA;I've also done a 2 dimensional implementation of the marching cubes example but without interpolation(simply because I do not understand all).&#xD;&#xA;&#xD;&#xA;[![2D marching Squares with filled polygons][3]][3]&#xD;&#xA;After all my question on which base is the _naive surface nets_ algorithm build? How does is work? An example which shows how it works step by step calculating the surface of 2D Voxels would help me a lot.  I tried to find examples but I wasn't really lucky. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS I'm very sorry if this isn't the right place to ask. I wasn't sure at all where to ask because I want a application independent explanation&#xD;&#xA;&#xD;&#xA;An implementation is not needed (nice but not necessary).&#xD;&#xA;I simply want to know how the naive surface net algorithm calculates the points for a given voxel input.&#xD;&#xA;e.g this:&#xD;&#xA;&#xD;&#xA;[![Marching squares algorithm result][4]][4]&#xD;&#xA;&#xD;&#xA;Where red stands for binary 1 and blue for binary 0&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://cs.stackexchange.com/questions/71085/how-does-the-naive-surface-nets-algorithm-work&#xD;&#xA;  [2]: https://www.google.de/amp/s/0fps.net/2012/07/12/smooth-voxel-terrain-part-2/amp/&#xD;&#xA;  [3]: https://i.stack.imgur.com/ASLW0.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/5Fi9E.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11360" PostHistoryTypeId="1" PostId="4804" RevisionGUID="023d6d4c-cf49-4f65-9cae-6ad484f81115" CreationDate="2017-03-03T17:40:26.487" UserId="6165" Text="Workflow of the Naive Surface Nets algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="11361" PostHistoryTypeId="3" PostId="4804" RevisionGUID="023d6d4c-cf49-4f65-9cae-6ad484f81115" CreationDate="2017-03-03T17:40:26.487" UserId="6165" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11362" PostHistoryTypeId="5" PostId="4804" RevisionGUID="038add4a-5a87-4bae-9a7e-cc1fcfa19bc8" CreationDate="2017-03-03T17:49:02.687" UserId="6165" Comment="added 312 characters in body" Text="**This [question][1] is comming from ComputerScience after suggestion**&#xD;&#xA;&#xD;&#xA;I'm trying to understand the Naive Surface Nets algorithm which is related to surface generation out of Voxels. I've learned of it [here][2]&#xD;&#xA;&#xD;&#xA;I already understood how the marching cubes algorithm works but not how the interpolation works. Especially the definition of Voxel is unclear to me? I understood that Voxels are in pseudo code:&#xD;&#xA;&#xD;&#xA;    type Voxel = &#xD;&#xA;            val scalar:float&#xD;&#xA;&#xD;&#xA;Is this correct?  If not please explain me the correct interpretation of it.&#xD;&#xA;&#xD;&#xA;I've also done a 2 dimensional implementation of the marching cubes example but without interpolation(simply because I do not understand all).&#xD;&#xA;&#xD;&#xA;[![2D marching Squares with filled polygons][3]][3]&#xD;&#xA;After all my question on which base is the _naive surface nets_ algorithm build? How does is work? An example which shows how it works step by step calculating the surface of 2D Voxels would help me a lot.  I tried to find examples but I wasn't really lucky. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS I'm very sorry if this isn't the right place to ask. I wasn't sure at all where to ask because I want a application independent explanation&#xD;&#xA;&#xD;&#xA;An implementation is not needed (nice but not necessary).&#xD;&#xA;I simply want to know how the naive surface net algorithm calculates the points for a given voxel input.&#xD;&#xA;e.g this:&#xD;&#xA;&#xD;&#xA;[![Marching squares algorithm result][4]][4]&#xD;&#xA;&#xD;&#xA;Where red stands for binary 1 and blue for binary 0&#xD;&#xA;&#xD;&#xA;Sample data:&#xD;&#xA;&#xD;&#xA;    let gridmap=Map[(Point2D(0., 0.), true); (Point2D(1., 0.), true);   (Point2D(2., 0.), true);&#xD;&#xA;                    (Point2D(0., 1.), false); (Point2D(1., 1.), true); (Point2D(2., 1.), false);&#xD;&#xA;                    (Point2D(0., 2.), false); (Point2D(1., 2.), false); (Point2D(2., 2.), false) ]&#xD;&#xA;&#xD;&#xA;  [1]: http://cs.stackexchange.com/questions/71085/how-does-the-naive-surface-nets-algorithm-work&#xD;&#xA;  [2]: https://www.google.de/amp/s/0fps.net/2012/07/12/smooth-voxel-terrain-part-2/amp/&#xD;&#xA;  [3]: https://i.stack.imgur.com/ASLW0.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/5Fi9E.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11363" PostHistoryTypeId="5" PostId="4793" RevisionGUID="ce29b290-dbd9-4560-bf18-f0f5f88d5675" CreationDate="2017-03-03T20:08:00.677" UserId="5852" Comment="added 703 characters in body" Text="OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(dis)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;For any reason, these two lines doesn't work together&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;**EDIT:** I think that the two lines above doesn't work because mipmaps only works with GL_TEXTURE_MIN_FILTER. However, when I replace&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;it shows a black triangle :(&#xD;&#xA;&#xD;&#xA;I used glGetError as Dan Hulme stated in the comments but with the last change I made to my code I have not errors returned by glGetError but still showing a black triangle." ContentLicense="CC BY-SA 3.0" />
  <row Id="11364" PostHistoryTypeId="2" PostId="4805" RevisionGUID="686e1462-379d-4ab1-bf74-d90a6376dba6" CreationDate="2017-03-03T21:48:16.963" UserId="5828" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;For a visibility algorithm I want to remove verts of polygon that are guaranteed not visible from a vert S. The idea is to remove pockets that points are on the backside of a plane formed by the vector n, the perpendicular vector between S and 0, and a point S.&#xD;&#xA;&#xD;&#xA;The prerequisites are:&#xD;&#xA;&#xD;&#xA; - the points of a polygon are in ccw order&#xD;&#xA; - the labeled points are the cutting-points between g(t) and the edges of the polygon&#xD;&#xA;    - sorted by occurrence with respect to S&#xD;&#xA;    - only the points with a positive t are retained&#xD;&#xA;    - the points are part of a new created polygon, we are working with&#xD;&#xA;  &#xD;&#xA;The difficult task is to identify a pocket respectively the pair of indices a pocket starts and ends.&#xD;&#xA;&#xD;&#xA;Here are my approaches:&#xD;&#xA;&#xD;&#xA;1. Use the natural order of cutting-points and remove items with a smaller t to their previous ones (works on I, III and IV).&#xD;&#xA;2. Sort the cutting-points by t. If the second point has the highest index in the original order, then all other cutting-points are part of the pocket and can be ignored (works on II).&#xD;&#xA;&#xD;&#xA;Now the questions are:&#xD;&#xA;&#xD;&#xA;1. When should I use the first and when the second approach (I can't see it)?&#xD;&#xA;2. Is there an easier way?&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pp9Ug.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11365" PostHistoryTypeId="1" PostId="4805" RevisionGUID="686e1462-379d-4ab1-bf74-d90a6376dba6" CreationDate="2017-03-03T21:48:16.963" UserId="5828" Text="Remove clearly not visible vertices from a polygon" ContentLicense="CC BY-SA 3.0" />
  <row Id="11366" PostHistoryTypeId="3" PostId="4805" RevisionGUID="686e1462-379d-4ab1-bf74-d90a6376dba6" CreationDate="2017-03-03T21:48:16.963" UserId="5828" Text="|2d|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11367" PostHistoryTypeId="5" PostId="4793" RevisionGUID="15b5d3d0-0a8d-4058-bc4a-c4253eda5477" CreationDate="2017-03-03T23:20:59.120" UserId="5852" Comment="added 5592 characters in body" Text="OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(dis)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;For any reason, these two lines doesn't work together&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT:&lt;/h1&gt;** I think that the two lines above doesn't work because mipmaps only works with GL_TEXTURE_MIN_FILTER. However, when I replace&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;it shows a black triangle :(&#xD;&#xA;&#xD;&#xA;I used glGetError as Dan Hulme stated in the comments but with the last change I made to my code I have not errors returned by glGetError but still showing a black triangle.&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT 2:&lt;/h1&gt;** I solved the problem setting the sizes by powers of 2. However, it now takes only the first mipmap level. Here is the new source code:&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//Change the value of size by 1,2,4,8,16,32,64,128 or 256 and see how the color of the triangle doesn't change. Why does it happen?&#xD;&#xA;	GLint size = 128;&#xD;&#xA;&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(size,size, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0,size,size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with odd level and green color&#xD;&#xA;    //The dimensions are 256 x 256 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if((i+2)%3 == 0)&#xD;&#xA;    		imageArray[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with pair level and red color&#xD;&#xA;    unsigned char imageArray2[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if(i%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);&#xD;&#xA;&#xD;&#xA;    //All mipmap levels defined by hand&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 64,  64,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 32,  32,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 16,  16,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 8,   8,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,	//vertex coordinates&#xD;&#xA;			0.0f, 0.0f								//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11368" PostHistoryTypeId="5" PostId="4804" RevisionGUID="e069ae56-b783-4b1c-ba50-fdd531037c89" CreationDate="2017-03-03T23:33:14.600" UserId="6165" Comment="deleted 761 characters in body; added 47 characters in body" Text="**This [question][1] is comming from ComputerScience after suggestion**&#xD;&#xA;&#xD;&#xA;I'm trying to understand the Naive Surface Nets algorithm which is related to surface generation out of Voxels. I've learned of it [here][1]&#xA;&#xA;So far I understood that the naive surface nets algorithm calculates the &quot;optimal&quot; edge crossings for a given input. Problem is that I don't understand how it's supposed to calculate the edge crossings compared to the marching cubes algorithm. If the input data is represented in binary values (only one and zero) like for marching cubes algorithm shouldn't the computation of the edge crossings have the same results?&#xA;&#xA;I suppose a step by step showcase of what the algorithm does for aquiring the surface of 2D sample voxels data would help me a lot understanding it. Sample code is fine too but is not a must have.&#xA;&#xA;For example for this data the marching cubes algorithm gives as result the image show below (the lines). Would the naive surface nets algorithm return the same result?&#xA;&#xA;[![Marching squares algorithm result][3]][3]&#xA;&#xA;Where red stands for binary 1 and blue for binary 0 asuming each voxel has the same space between each other (as always I think).&#xA;&#xA;&#xA;&#xA;  [1]: https://www.google.de/amp/s/0fps.net/2012/07/12/smooth-voxel-terrain-part-2/amp/&#xA;  [3]: https://i.stack.imgur.com/5Fi9E.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11369" PostHistoryTypeId="5" PostId="4793" RevisionGUID="291f79f4-54e2-4353-8797-77546c58b501" CreationDate="2017-03-03T23:33:39.310" UserId="5852" Comment="added 239 characters in body" Text="OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&#xD;&#xA;I really hate putting a bunch of code in my questions because I force others to waste time analyzing the code instead of putting the most revelant snippet code, but I don't know where is the problem and I have not alternative. Sorry :(&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(dis)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;For any reason, these two lines doesn't work together&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT:&lt;/h1&gt;** I think that the two lines above doesn't work because mipmaps only works with GL_TEXTURE_MIN_FILTER. However, when I replace&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;it shows a black triangle :(&#xD;&#xA;&#xD;&#xA;I used glGetError as Dan Hulme stated in the comments but with the last change I made to my code I have not errors returned by glGetError but still showing a black triangle.&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT 2:&lt;/h1&gt;** I solved the problem setting the sizes by powers of 2. However, it now takes only the first mipmap level. Here is the new source code:&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//Change the value of size by 1,2,4,8,16,32,64,128 or 256 and see how the color of the triangle doesn't change. Why does it happen?&#xD;&#xA;	GLint size = 128;&#xD;&#xA;&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(size,size, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0,size,size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with odd level and green color&#xD;&#xA;    //The dimensions are 256 x 256 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if((i+2)%3 == 0)&#xD;&#xA;    		imageArray[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with pair level and red color&#xD;&#xA;    unsigned char imageArray2[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if(i%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);&#xD;&#xA;&#xD;&#xA;    //All mipmap levels defined by hand&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 64,  64,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 32,  32,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 16,  16,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 8,   8,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,	//vertex coordinates&#xD;&#xA;			0.0f, 0.0f								//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11380" PostHistoryTypeId="5" PostId="4793" RevisionGUID="18d24a53-cf78-490b-ab14-06d4c9bcb1d0" CreationDate="2017-03-04T15:38:00.293" UserId="5852" Comment="added 175 characters in body" Text="This question has an answer here:&lt;br /&gt;&#xD;&#xA;https://stackoverflow.com/questions/42596516/generating-mipmaps-manually&lt;br /&gt;&#xD;&#xA;It was a silly mistake. Sorry for the inconvenience.&#xD;&#xA;&#xD;&#xA;OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&#xD;&#xA;I really hate putting a bunch of code in my questions because I force others to waste time analyzing the code instead of putting the most revelant snippet code, but I don't know where is the problem and I have not alternative. Sorry :(&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(dis)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;For any reason, these two lines doesn't work together&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT:&lt;/h1&gt;** I think that the two lines above doesn't work because mipmaps only works with GL_TEXTURE_MIN_FILTER. However, when I replace&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and discomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;it shows a black triangle :(&#xD;&#xA;&#xD;&#xA;I used glGetError as Dan Hulme stated in the comments but with the last change I made to my code I have not errors returned by glGetError but still showing a black triangle.&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT 2:&lt;/h1&gt;** I solved the problem setting the sizes by powers of 2. However, it now takes only the first mipmap level. Here is the new source code:&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//Change the value of size by 1,2,4,8,16,32,64,128 or 256 and see how the color of the triangle doesn't change. Why does it happen?&#xD;&#xA;	GLint size = 128;&#xD;&#xA;&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(size,size, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0,size,size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with odd level and green color&#xD;&#xA;    //The dimensions are 256 x 256 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if((i+2)%3 == 0)&#xD;&#xA;    		imageArray[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with pair level and red color&#xD;&#xA;    unsigned char imageArray2[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if(i%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);&#xD;&#xA;&#xD;&#xA;    //All mipmap levels defined by hand&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 64,  64,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 32,  32,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 16,  16,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 8,   8,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,	//vertex coordinates&#xD;&#xA;			0.0f, 0.0f								//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11381" PostHistoryTypeId="50" PostId="4008" RevisionGUID="677dd711-f5ee-44cd-9460-799f7a9f68db" CreationDate="2017-03-04T17:33:56.843" UserId="-1" />
  <row Id="11382" PostHistoryTypeId="2" PostId="4806" RevisionGUID="2ef5a338-ba9a-4c58-99f5-c97137c0cf29" CreationDate="2017-03-04T18:34:18.343" UserId="2448" Text="If you are going for physics. You can do physically based rendering. Physically Based Rendering(PBR for short) is a filed of computer graphics where we take consider of physics(energy conservation, spectrum, etc) in to account and try to not do approximations.&#xD;&#xA;&#xD;&#xA;The are two main sub fields of PBR. &lt;br&gt;&#xD;&#xA;(quick intro, layman's term below)&#xD;&#xA;&#xD;&#xA;1. Production Rendering.&#xD;&#xA;This is where accuracy is the focus. We do as little or no approximations as possible. There are algorithms in this field where if the wave-like property of light is ignored. Then the result generated by the algorithm is physically accurate. But each frame might take more than a few minutes or even hours to render. There are a lot of different topics actively being researched in this field(fast ray-scene intersection, better Monticello integration, fast/robust acceleration struct building)&#xD;&#xA;&#xD;&#xA;2. Realtime Rendering.&#xD;&#xA;In this field, speed is the key concern. Where accuracy is achieved by doing good approximations. But will never be physically accurate. Most research on this field is focusing on doing good and fast approximations.&#xD;&#xA;&#xD;&#xA;These are my random ideas for fluids.&#xD;&#xA;&#xD;&#xA; 1. Fast Ray-Liquid intersection testing&#xD;&#xA; 2. Fast triangle mesh generation from particles.&#xD;&#xA; 3. Fast acceleration structure building from particles.&#xD;&#xA; 4. Simplification of liquid surface to generate simpler mesh&#xD;&#xA;&#xD;&#xA;And some random ideas for general GC.&#xD;&#xA;&#xD;&#xA; 1. Improve sampling efficiency for sky maps in ray based rendering algorithm&#xD;&#xA; 2. Robust method of dealing with floating point accuracy problem in shadow maps&#xD;&#xA;&#xD;&#xA;I don't know the above topic is even possible. Those are just ideas." ContentLicense="CC BY-SA 3.0" />
  <row Id="11383" PostHistoryTypeId="5" PostId="4806" RevisionGUID="e47ae2cb-eff9-45b2-af4c-292203bbe701" CreationDate="2017-03-04T18:40:41.257" UserId="2448" Comment="added 7 characters in body" Text="If you are going for physics. You can do physically based rendering. Physically Based Rendering(PBR for short) is a filed of computer graphics where we take consider of physics(energy conservation, spectrum, etc) in to account and try to not do approximations.&#xD;&#xA;&#xD;&#xA;The are two main sub fields of PBR. &lt;br&gt;&#xD;&#xA;(quick intro, layman's term below)&#xD;&#xA;&#xD;&#xA;1. Production Rendering.&#xD;&#xA;This is where accuracy is the focus. We do as little or no approximations as possible. There are algorithms in this field where if the wave-like property of light is ignored. Then the result generated by the algorithm is physically accurate. But each frame might take more than a few minutes or even hours to render. There are a lot of different topics actively being researched in this field(fast ray-scene intersection, better Monticello integration, fast/robust acceleration struct building)&#xD;&#xA;&#xD;&#xA;2. Realtime Rendering.&#xD;&#xA;In this field, speed is the key concern. Where accuracy is achieved by doing good approximations. But will never be physically accurate. Most research on this field is focusing on doing good and fast approximations.&#xD;&#xA;&#xD;&#xA;These are my random ideas for fluids.&#xD;&#xA;&#xD;&#xA; 1. Fast Ray-Liquid intersection testing&#xD;&#xA; 2. Fast triangle mesh generation from particles.&#xD;&#xA; 3. Fast acceleration structure building from particles.&#xD;&#xA; 4. Simplification of liquid surface to generate simpler mesh&#xD;&#xA;&#xD;&#xA;And some random ideas for general GC.&#xD;&#xA;&#xD;&#xA; 1. Improve sampling efficiency for sky maps in ray based rendering algorithm&#xD;&#xA; 2. Robust method of dealing with floating point accuracy problem in shadow maps&#xD;&#xA;&#xD;&#xA;I don't know if the above topics are possible or not. Those are just ideas." ContentLicense="CC BY-SA 3.0" />
  <row Id="11385" PostHistoryTypeId="2" PostId="4807" RevisionGUID="bd5d497f-75ee-408b-8a8d-1ea37ce6b051" CreationDate="2017-03-04T21:07:10.787" UserId="6099" Text="I would like to generate a bitmap for use with a webgl texture generated from a 2d canvas, but I don't think I am doing it correctly. I know how to display the contents of one canvas into another by using &quot;drawImage&quot;. As has been posted many times, the trick is to make sure the width and height values of the canvas are multiplied by the &quot;display&quot; ratio (1.25 in my case). So if I create some graphics in canvas &quot;a&quot;, by using ctx.rect, ctx.fillText, etc. and display the graphics of canvas a into canvas b I have to make sure that both canvases are multiplied by the ratio above and css displayed accordingly.  &#xD;&#xA;&#xD;&#xA;What is the proper way to generate the bitmap for a WebGL texture using a the  canvas? I thought the webgl canvas should have also had the multiplier as above, but that does not seem to work for me. Assuming the image is displayed 1:1 I was thinking I could create the image 1:1 zoom, generate a texture vertext that exactly (0,0) to (1,1) and a &quot;point&quot; vertext that was also 1:1 the size of the image (translated to -1,1 space, of course). Is this correct or am I thinking about it wrong?&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;Jose" ContentLicense="CC BY-SA 3.0" />
  <row Id="11386" PostHistoryTypeId="1" PostId="4807" RevisionGUID="bd5d497f-75ee-408b-8a8d-1ea37ce6b051" CreationDate="2017-03-04T21:07:10.787" UserId="6099" Text="How To Generate High Quality Bitmap From Canvas For WebGL Texture" ContentLicense="CC BY-SA 3.0" />
  <row Id="11387" PostHistoryTypeId="3" PostId="4807" RevisionGUID="bd5d497f-75ee-408b-8a8d-1ea37ce6b051" CreationDate="2017-03-04T21:07:10.787" UserId="6099" Text="|webgl|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11390" PostHistoryTypeId="50" PostId="1755" RevisionGUID="60059b20-bc87-44df-9cb7-44060830578a" CreationDate="2017-03-05T08:02:06.733" UserId="-1" />
  <row Id="11391" PostHistoryTypeId="50" PostId="4651" RevisionGUID="81b1f430-dfb4-4b6b-84a4-27a72d55433f" CreationDate="2017-03-05T09:02:06.353" UserId="-1" />
  <row Id="11392" PostHistoryTypeId="2" PostId="4808" RevisionGUID="7e577d8c-58cc-44d1-9f63-3ed1c896c7b4" CreationDate="2017-03-05T15:49:05.427" UserId="6175" Text="How can I calculate the rigid transformation [R|t] between two 3d triangles, but restricted to a given N degrees of freedom (for N = 1..6) ?&#xD;&#xA;&#xD;&#xA;I know for N=6 I can get a least-squares solution via SVD of a certain matrix, but how can I integrate further constraints (fewer DOF) into the system?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="11393" PostHistoryTypeId="1" PostId="4808" RevisionGUID="7e577d8c-58cc-44d1-9f63-3ed1c896c7b4" CreationDate="2017-03-05T15:49:05.427" UserId="6175" Text="Calculate Transformation between two point sets - but with constrained Degrees of Freedom" ContentLicense="CC BY-SA 3.0" />
  <row Id="11394" PostHistoryTypeId="3" PostId="4808" RevisionGUID="7e577d8c-58cc-44d1-9f63-3ed1c896c7b4" CreationDate="2017-03-05T15:49:05.427" UserId="6175" Text="|transformations|geometry|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11395" PostHistoryTypeId="2" PostId="4809" RevisionGUID="3bb6e44d-2376-442c-b72c-723d91b6f22b" CreationDate="2017-03-05T17:25:47.820" UserId="6041" Text="How is distant directional light source(like sun) added in BDPT?&#xD;&#xA;If this is an indoor scene that gets sunlight through windows, how is this handled in BDPT(other than to consider Sun as a big disc far away and to sample a position on it's area, as this probably wouldn't be efficient for points within the room)&#xD;&#xA;&#xD;&#xA;Would it be valid instead to consider window polylines as area sources that emits light in one direction(directional source)? The light samplePosition would be same as sampling a point on the window area (with pdf 1/A ?) and sampleDirection with pdf=1? How about connecting s=1 and t and MIS weights? are they need to be modified or same codes can be used?&#xD;&#xA;&#xD;&#xA;Any help/hint is appreciated, Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="11396" PostHistoryTypeId="1" PostId="4809" RevisionGUID="3bb6e44d-2376-442c-b72c-723d91b6f22b" CreationDate="2017-03-05T17:25:47.820" UserId="6041" Text="How Sunlight is added in Bidirectional Path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11397" PostHistoryTypeId="3" PostId="4809" RevisionGUID="3bb6e44d-2376-442c-b72c-723d91b6f22b" CreationDate="2017-03-05T17:25:47.820" UserId="6041" Text="|raytracing|lighting|pathtracing|physically-based|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11398" PostHistoryTypeId="2" PostId="4810" RevisionGUID="929e877e-3cf8-45f5-bcdb-7650dce37607" CreationDate="2017-03-05T22:05:05.670" UserId="5609" Text="I have a simple **cube** mesh, which I **scale** with modifying the **model** matrix.&#xD;&#xA;&#xD;&#xA;**Texture settings:**&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, m_texture);&#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);&#xD;&#xA;&#xD;&#xA;	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I set `GL_REPEAT` as wrap mode, but in my case it doesn't help, because the texture coordinates don't exceed `[0...1]`.&#xD;&#xA;&#xD;&#xA;**For example** from the unit cube I want to make a column whose dimensions are (1,10,1).&#xD;&#xA;&#xD;&#xA;Just scaling this doesn't work because it textures the cube and then applies the scaling, which means that the texture will be stretched, instead of repeated along the y axis.&#xD;&#xA;&#xD;&#xA;**How can I implement this so I could set the length, width and depth of a cube dynamically so the texture will be repeated on it instead of stretched?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="11399" PostHistoryTypeId="1" PostId="4810" RevisionGUID="929e877e-3cf8-45f5-bcdb-7650dce37607" CreationDate="2017-03-05T22:05:05.670" UserId="5609" Text="Stretch the cube mesh but repeat the texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11400" PostHistoryTypeId="3" PostId="4810" RevisionGUID="929e877e-3cf8-45f5-bcdb-7650dce37607" CreationDate="2017-03-05T22:05:05.670" UserId="5609" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11401" PostHistoryTypeId="2" PostId="4811" RevisionGUID="4d21b6bc-0d15-4709-a3d7-eb2c1ace1f14" CreationDate="2017-03-05T22:31:17.853" UserId="2479" Text="It's not that hard. If you have just planar or angular light sources, you can think of them as one light source split into multiple chunks. Then the only thing to deal with is how to sample them and how to compute the PDF of samples.&#xD;&#xA;&#xD;&#xA;You first need to setup the picking probability for each light source. Ideally, they would be proportional to their respective contributions the rendering integral, but since this is usually not known in advance, one have to resort to some estimates (based on the output power, distance, angular size, orientation, etc.).&#xD;&#xA;&#xD;&#xA;When sampling the lights, you just select one light with the appropriate probability and then sample the light surface/angle with its own sampling strategy. The resulting PDF will be the PDF obtained from the single light strategy times the probability of picking this light source.&#xD;&#xA;&#xD;&#xA;When computing the light sampling PDF for given direction (as needed for MIS), you just find the light source at the direction, evaluate the PDF of the lights own strategy and, again, multiply it by the probability of picking this particular light.&#xD;&#xA;&#xD;&#xA;&amp;hellip;now you can easily do your usual Monte Carlo magic :-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11402" PostHistoryTypeId="5" PostId="4810" RevisionGUID="e2718d25-3f87-4a02-b0fc-1ffb778678b3" CreationDate="2017-03-05T22:41:43.983" UserId="5609" Comment="added 1 character in body" Text="I have a simple **cube** mesh, which I **scale** with modifying the **model** matrix.&#xD;&#xA;&#xD;&#xA;**Texture settings:**&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, m_texture);&#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);&#xD;&#xA;&#xD;&#xA;	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I set `GL_REPEAT` as wrap mode, but in my case it doesn't help, because the texture coordinates don't exceed `[0...1]`.&#xD;&#xA;&#xD;&#xA;**For example** from the unit cube I want to make a column whose dimensions are (1,10,1).&#xD;&#xA;&#xD;&#xA;Just scaling this doesn't work because it textures the cube and then applies the scaling, which means that the texture will be stretched, instead of repeated along the y axis.&#xD;&#xA;&#xD;&#xA;**How can I implement this so I could set the length, width and depth of a cube dynamically and the texture will be repeated on it instead of stretched?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="11403" PostHistoryTypeId="2" PostId="4812" RevisionGUID="d0dada48-a395-4f7c-a435-299f049c2411" CreationDate="2017-03-06T04:28:53.877" UserId="3003" Text="You need to set your texture coordinates appropriately. Let's look at one side of your cube. Let's say it's 100 x 100. If the user stretches the cube to be 100 x 150, you need to set the texture coordinates of the corner vertices to be:&#xD;&#xA;&#xD;&#xA;    lower left = &lt;0.0, 0.0&gt;&#xD;&#xA;    lower right = &lt;1.5, 0.0&gt;&#xD;&#xA;    upper right = &lt;1.5, 1.0&gt;&#xD;&#xA;    upper left = &lt;0.0, 1.0&gt;&#xD;&#xA;&#xD;&#xA;That's the easiest way to handle it. Another way to handle it would be to pass either as scale factor or scale matrix into your fragment shader and apply that to your texture coordinates before doing any sampling." ContentLicense="CC BY-SA 3.0" />
  <row Id="11404" PostHistoryTypeId="5" PostId="3671" RevisionGUID="dfd4fc33-c2d3-4609-82f1-3c5913c5cb67" CreationDate="2017-03-06T09:28:38.470" UserId="2785" Comment="Improved formatting: 1. horizontal-rule instead of “=====…”; 2. images put into same paragraph so portrait ones side side-by-side; 3. sized-down larger portrait images to 325px-wide so they too sit side-by-side (used &lt;img …&gt; syntax so that detail is preserved on High-DPI/Retina screens)." Text="Inspired by Minecraft and LEGOs, we created an app to promote creativity on smartphones. Many people like being creative but find a blank canvas daunting. &quot;Recipes&quot; inside the app let users create like the most talented individuals -- similar to how a cooking recipe lets anyone cook like Thomas Keller.&#xD;&#xA;&#xD;&#xA;The problem so far is users say the app doesn't look &quot;3D&quot; enough.&#xD;&#xA;&#xD;&#xA;Here's the relevant code that creates the scene and creates blocks: https://gist.github.com/panabee/dca88a591f94a3904023dacabd020ad9.&#xD;&#xA;&#xD;&#xA;What they mean is they expect the app to look more like apps like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;With encouragement from one of the admins, these screenshots from our app illustrate the disparity in &quot;3Dness&quot;:&#xD;&#xA;&#xD;&#xA;&lt;a href=&quot;https://i.stack.imgur.com/ntHkQ.jpg&quot;&gt;&#xD;&#xA;  &lt;img src=&quot;https://i.stack.imgur.com/ntHkQ.jpg&quot; width=&quot;325&quot; alt=&quot;enter image description here&quot;/&gt;&#xD;&#xA;&lt;/a&gt;&#xD;&#xA;&lt;a href=&quot;https://i.stack.imgur.com/dodAZ.png&quot;&gt;&#xD;&#xA;  &lt;img src=&quot;https://i.stack.imgur.com/dodAZ.png&quot; width=&quot;325&quot; alt=&quot;enter image description here&quot;/&gt;&#xD;&#xA;&lt;/a&gt;&#xD;&#xA;&#xD;&#xA;We're using SceneKit on iOS, but are having trouble identifying what is needed to make the app look more like the images above. We played with lighting and textures, but are new to 3D graphics as well as SceneKit and are unsure what to do.&#xD;&#xA;&#xD;&#xA;We have tried to find consultants on StackOverflow, LinkedIn, Github, but this expertise appears not so common.&#xD;&#xA;&#xD;&#xA;A few questions:&#xD;&#xA;&#xD;&#xA;1) For iOS, is SceneKit capable of producing the images above, or do we need to use something like Metal?&#xD;&#xA;&#xD;&#xA;2) If SceneKit is capable, what are the key concepts to learn?&#xD;&#xA;&#xD;&#xA;3) (Happy to strike this question if it's considered off-topic) Which websites/forums could we find people to help provide advice if we get stuck?&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4Kh0S.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LMePj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/mGfva.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11405" PostHistoryTypeId="24" PostId="3671" RevisionGUID="dfd4fc33-c2d3-4609-82f1-3c5913c5cb67" CreationDate="2017-03-06T09:28:38.470" Comment="Proposed by 2785 approved by 209, 385 edit id of 205" ContentLicense="CC BY-SA 3.0" />
  <row Id="11406" PostHistoryTypeId="5" PostId="4801" RevisionGUID="daaf2252-84a2-49e5-9ca2-9ff6d83f3ad2" CreationDate="2017-03-06T11:54:31.817" UserId="6164" Comment="added 1282 characters in body" Text="I am working on a 2D lighting system for my game. My approach has been to:&#xD;&#xA;&#xD;&#xA;1. Create a transparency quad representing 'darkness'.&#xD;&#xA;2. Create a stencil shader for light sources to clip from the darkness quad.&#xD;&#xA;3. Create a shader that blends alpha from 0 -&gt; {darkness alpha} to soften the edges of the light source.&#xD;&#xA;&#xD;&#xA;This looks like the following:&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can see the problem - the two light source shaders that soften the shadow edges are being blended like normal transparency layers should and causing the colour to intensify. Here is another image without the darkness quad, which might make things a bit clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vZ77t.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bpC3M.png&#xD;&#xA;&#xD;&#xA;My question: Is there any sort of alpha blending I can do to make this intersection appear 'normal' i.e. it doesn't intensify the color? If not, is there another approach which could help with this?&#xD;&#xA;&#xD;&#xA;**Update:**&#xD;&#xA;&#xD;&#xA;Here is the shader code that generates the fade on the light source - note that the _Radius is set for each light source. &#xD;&#xA;&#xD;&#xA;    Properties&#xD;&#xA;	{&#xD;&#xA;		_Color(&quot;Bottom Color&quot;, Color) = (1,1,1,1)&#xD;&#xA;		_Radius(&quot;Radius&quot;, Float) = 1&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	SubShader&#xD;&#xA;	{&#xD;&#xA;		Tags&#xD;&#xA;		{ &#xD;&#xA;			&quot;RenderType&quot; = &quot;Transparent&quot; &#xD;&#xA;			&quot;IgnoreProjector&quot; = &quot;True&quot;&#xD;&#xA;			&quot;Queue&quot; = &quot;Transparent&quot; &#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;		Cull Back&#xD;&#xA;		Blend One OneMinusSrcAlpha&#xD;&#xA;&#xD;&#xA;		Pass&#xD;&#xA;		{&#xD;&#xA;			CGPROGRAM&#xD;&#xA;			#pragma vertex vert&#xD;&#xA;			#pragma fragment frag&#xD;&#xA;&#xD;&#xA;			#include &quot;UnityCG.cginc&quot;&#xD;&#xA;&#xD;&#xA;			struct appdata&#xD;&#xA;			{&#xD;&#xA;				float4 vertex : POSITION;&#xD;&#xA;			};&#xD;&#xA;&#xD;&#xA;			struct v2f&#xD;&#xA;			{&#xD;&#xA;				float4 vertex : SV_POSITION;&#xD;&#xA;				float distance : float2;&#xD;&#xA;			};&#xD;&#xA;&#xD;&#xA;			fixed4 _Color;&#xD;&#xA;			float _Radius;&#xD;&#xA;&#xD;&#xA;			v2f vert(appdata v)&#xD;&#xA;			{&#xD;&#xA;				v2f o;&#xD;&#xA;				o.vertex = UnityObjectToClipPos(v.vertex);&#xD;&#xA;				o.distance = distance(float3(0, 0, 0), v.vertex);&#xD;&#xA;				return o;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			fixed4 frag(v2f i) : SV_Target&#xD;&#xA;			{				&#xD;&#xA;				float distance = (i.distance / _Radius); // 0 -&gt; 1 as progressing to outside&#xD;&#xA;				float normalizedDistance = 1 - distance; // 1 -&gt; 0 as progressing to outside &#xD;&#xA;				&#xD;&#xA;				// 0 -&gt; 0.43&#xD;&#xA;				fixed colorOffset = lerp(0, _Color.a, distance);&#xD;&#xA;&#xD;&#xA;				// return alpha &#xD;&#xA;				return fixed4(0, 0, 0, colorOffset);&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			ENDCG&#xD;&#xA;		}&#xD;&#xA;	}" ContentLicense="CC BY-SA 3.0" />
  <row Id="11407" PostHistoryTypeId="5" PostId="4811" RevisionGUID="a282d6b9-6040-4168-9629-dfdf8699b78e" CreationDate="2017-03-06T13:41:09.327" UserId="2479" Comment="Minor polishing" Text="It's not that hard. If you have just planar or angular light sources, you can think of them as one light source split into multiple chunks and the only thing to deal with is how to sample this multilight and how to compute the PDF of the resulting samples.&#xD;&#xA;&#xD;&#xA;You first need to setup the picking probability for each light source. Ideally, they would be proportional to their respective contributions the rendering integral, but since this is usually not known in advance, one have to resort to some estimates (based on the output power, distance, angular size, orientation, etc.).&#xD;&#xA;&#xD;&#xA;When sampling the lights, you just select one light with the appropriate probability and then sample the light surface/angle with its own sampling strategy. The resulting PDF will be the PDF obtained from the single light strategy times the probability of picking this light source.&#xD;&#xA;&#xD;&#xA;When computing the light sampling PDF for given direction (as needed for MIS), you just find the light source at the direction, evaluate the PDF of the lights own strategy and, again, multiply it by the probability of picking this particular light.&#xD;&#xA;&#xD;&#xA;&amp;hellip;now you can easily do your usual Monte Carlo magic :-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11408" PostHistoryTypeId="2" PostId="4813" RevisionGUID="cd0bc8bf-95f0-416f-80be-485f386d3123" CreationDate="2017-03-06T14:21:46.133" UserId="6179" Text="a) I have used an online service where you can upload an image.&#xD;&#xA;&#xD;&#xA;b) Afterwards, you can select a print size and it gives you information on what is actual DPI based on that print size.&#xD;&#xA;&#xD;&#xA;c) When it gives you information if that particular DPI (dots per inch) for that print size is enough quality to print, so basically it outputs &quot;bad&quot;, &quot;average&quot; or &quot;good&quot;.&#xD;&#xA;&#xD;&#xA;I want to built this functionality on my own site, but I lack logic's behind how they count DPI.&#xD;&#xA;&#xD;&#xA;This is my two tests where I upload slightly different photos. As site outputs DPI it is easy to try to get how it counts it, but as for different photos it does differently. I just can not grasp the pattern on why it does so.&#xD;&#xA;&#xD;&#xA;Here is my two different photos uploaded:&#xD;&#xA;&#xD;&#xA;Product: Poster&#xD;&#xA;Size: 1000x1200&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I will just explain the first value - 8x10 -&gt; 1200 / 10  -  you get DPI by subtracting photo height with print size height.&#xD;&#xA;&#xD;&#xA;    8x10 -&gt; 1200 / 10   -&gt;&gt;&gt; why this DPI is counted differently from other image?     &#xD;&#xA;    10x10 -&gt; 1000 / 10                &#xD;&#xA;    12x12 -&gt; 1000 / 12               &#xD;&#xA;    12x16 -&gt; 1200 / 16  -&gt;&gt;&gt; why this DPI is counted differently from other image?     &#xD;&#xA;    14x14 -&gt; 1000 / 14                &#xD;&#xA;    16x16 -&gt; 1000 / 16                &#xD;&#xA;    12x18 -&gt; 1200 / 18                &#xD;&#xA;    18x18 -&gt; 1000 / 18                &#xD;&#xA;    16x20 -&gt; 1200 / 20  -&gt;&gt;&gt; why this DPI is counted differently from other image?     &#xD;&#xA;    18x24 -&gt; 1200 / 24  -&gt;&gt;&gt; why this DPI is counted differently from other image?     &#xD;&#xA;    24x36 -&gt; 1200 / 36   &#xD;&#xA;&#xD;&#xA;           &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Product: Poster&#xD;&#xA;Size: 1000x1333&#xD;&#xA;&#xD;&#xA;    8x10 -&gt; 1000 / 8    -&gt;&gt;&gt; comparing to this value &#xD;&#xA;    10x10 -&gt; 1000 / 10&#xD;&#xA;    12x12 -&gt; 1000 / 12&#xD;&#xA;    12x16 -&gt; 1000 / 12  -&gt;&gt;&gt; comparing to this value   &#xD;&#xA;    14x14 -&gt; 1000 / 14&#xD;&#xA;    16x16 -&gt; 1000 / 16&#xD;&#xA;    12x18 -&gt; 1333 / 18                   &#xD;&#xA;    18x18 -&gt; 1000 / 18&#xD;&#xA;    16x20 -&gt; 1000 / 20  -&gt;&gt;&gt; comparing to this value &#xD;&#xA;    18x24 -&gt; 1000 / 18  -&gt;&gt;&gt; comparing to this value &#xD;&#xA;    24x36 -&gt; 1333 / 36    &#xD;&#xA;&#xD;&#xA;          &#xD;&#xA;&#xD;&#xA;Just do not get it why for a very similar image, counting of the same print sizes are different for particular values?&#xD;&#xA;&#xD;&#xA;Any ideas?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11409" PostHistoryTypeId="1" PostId="4813" RevisionGUID="cd0bc8bf-95f0-416f-80be-485f386d3123" CreationDate="2017-03-06T14:21:46.133" UserId="6179" Text="How to count DPI of an image (challenge)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11410" PostHistoryTypeId="3" PostId="4813" RevisionGUID="cd0bc8bf-95f0-416f-80be-485f386d3123" CreationDate="2017-03-06T14:21:46.133" UserId="6179" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11412" PostHistoryTypeId="2" PostId="4814" RevisionGUID="6e5d08b4-9cb2-4088-97cb-d869e6d40a67" CreationDate="2017-03-06T18:01:39.370" UserId="6125" Text="I think the basic idea, as explained in the article to which you linked, is to associate a vertex (shown in light blue) to each square that intersects the surface, with the vertex positioned at the average of the adjacent edge crossings (shown in gray). Then connect up with dual edges (shown also in light blue).[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v6qSj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11413" PostHistoryTypeId="5" PostId="3995" RevisionGUID="bbab3a02-74b2-47bc-9720-9f1fcba23485" CreationDate="2017-03-06T19:43:06.857" UserId="6143" Comment="Removed thank you " Text="So, I started writing my second raytracer - this time focusing on photometric rendering that uses IES lights and standard photometric units.  I've got the basic raytracing up and running (using pure geometry), I've read any article I could found on radio- and photometry (I think I developed an intuition for it) but the issues started when I tried to validate/play with the underlying math.&#xD;&#xA;&#xD;&#xA;I use IES lights as a function of spherical coordinates that gives me the intensity of light in that direction in candelas (lumens per unit solid angle). Also in the equation for Luminance/Radiance there are differential solid angle and differential surface area. On the paper everything looks good, however:&#xD;&#xA;&#xD;&#xA;**My question is**: how should I deal with those parameters in my raytracer? I assume (but I'm not sure) that my (differential) solid angle is just a (unit) vector in descrete world and the surface area is simply a point - but what values should I plug in to those equations? I saw that on some websites that people just ignored those terms and replaced the integral with sum - but no explanation was given...&#xD;&#xA;&#xD;&#xA;And my second question is related to those IES lights - how can I simply convert intensity to radiance? The intensity already has the solid angle, but for radiance I need the surface area... Or should I somehow integrate the luminious intensity to get luminious flux and then somehow calculate the radiance from that.&#xD;&#xA;&#xD;&#xA;**EDIT:** I decided to try to grab a sheet of paper, try again and share with you my thought process. In order to simplify a lot of things:&#xD;&#xA;&#xD;&#xA;- each plane has a single scalar value as material (let's name it *reflectivity* between 0 and 1)&#xD;&#xA;  - $p1$ has $reflectivity = 0.5$&#xD;&#xA;  - $p2$ has $reflectivity = 1$&#xD;&#xA;&#xD;&#xA;- all materials are lambertian (no specular reflections nor emission)&#xD;&#xA;&#xD;&#xA;So with those in mind let's imagine that we have following scene:&#xD;&#xA;[![Example scene with 2 planes][1]][1]&#xD;&#xA;&#xD;&#xA;**Step 1 - Illuminance at $p1$**&#xD;&#xA;&#xD;&#xA;The light luminious intensity at vertical angle $V=0$ is $I = 6619 [cd]$. In order to compute the illuminance at point $p1$ we can create a sphere with radius equal to the distance between the light and intersection point $p1$ which is $r = 2$ meters. That virtual sphere intersects with the first plane creating a small differential area $dA$. Knowing that $d\omega = \frac {dA}{r^2}$ we get $E_L(r) = \frac {I}{r^2} [ \frac {W}{m^2}]$ which is equal to illuminance measured at a plane perpendicular to light. We have to project it to know how many light hits the $p1$, so $E = E_L \times cos \theta$. I **assume** that $L_i = E$, but that is just a guess. I hope that at this point I got it right...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Step 2 - Outgoing luminance**&#xD;&#xA;&#xD;&#xA;In order to calculate the outgoing radiance I think that is the place for the rendering equation to kick in:&#xD;&#xA;$$&#xD;&#xA;L_o = L_e + \int_{\Omega} f_r(\omega_i, \omega_o) L_i(p, \omega_i) cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;since I ignore the emission and my BRDF is $f_r(\omega_i, \omega_o) = \frac {reflectivity}{\pi}$ which is constant across the integral giving me:&#xD;&#xA;$$&#xD;&#xA;L_o = \frac {reflectivity}{\pi} \int_{\Omega} L_i(p, \omega_i) cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;Now I have to discretize it, which I don't fully understand. Based on my notes that I've made based on many pages I've got:&#xD;&#xA;$L_o = \frac {reflectivity}{\pi} \sum L_i(p, \omega_i) cos \theta \Rightarrow L_o = \frac {0.5}{\pi} L_i cos \theta$, where $L_i$ was calculated in step 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Step 3 - Luminance at $p2$**&#xD;&#xA;&#xD;&#xA;Can I assume that $L_{i_{p2}} = L(p_1 \rightarrow p_2) \times cos \theta = L_{o_{p1}} \times cos \theta$ ? I'm not sure if I have to apply the $cos \theta$ twice (for outgoing and incoming $dA$s).&#xD;&#xA;&#xD;&#xA;_I also would like to apologize for making this question sooo long - but I had never taken any course that would introduce radiometry and I was forced to (try to) learn it by myself._&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BRL0Y.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11414" PostHistoryTypeId="24" PostId="3995" RevisionGUID="bbab3a02-74b2-47bc-9720-9f1fcba23485" CreationDate="2017-03-06T19:43:06.857" Comment="Proposed by 6143 approved by 385, 2041 edit id of 204" ContentLicense="CC BY-SA 3.0" />
  <row Id="11415" PostHistoryTypeId="5" PostId="4808" RevisionGUID="72277676-f09d-4c18-b2ac-d9fbd046bfac" CreationDate="2017-03-06T20:41:41.757" UserId="231" Comment="Remove &quot;Thanks&quot;" Text="How can I calculate the rigid transformation [R|t] between two 3d triangles, but restricted to a given N degrees of freedom (for N = 1..6) ?&#xD;&#xA;&#xD;&#xA;I know for N=6 I can get a least-squares solution via SVD of a certain matrix, but how can I integrate further constraints (fewer DOF) into the system?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11416" PostHistoryTypeId="2" PostId="4815" RevisionGUID="ceb4a600-1ba2-4d33-85fb-437a51342993" CreationDate="2017-03-07T01:33:20.277" UserId="6023" Text="Although this is not the solution I was looking for initially, the figure below is the tightest filling without overlaps of the plane with pentagons that I could come up with so far. I haven't found a recursive algorithm yet. I think it's not possible or it is too complicated to code. &#xD;&#xA;&#xD;&#xA;[![pentagon-rhombus lattice][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Below is the python script:&#xD;&#xA;&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    def pentagon (Xorig, Yorig, theta):&#xD;&#xA;        Ind = np.arange(N+1)&#xD;&#xA;        X = np.cos(Ind*2*np.pi/N+theta)+Xorig&#xD;&#xA;        Y = np.sin(Ind*2*np.pi/N+theta)+Yorig&#xD;&#xA;        plt.fill(X, Y, 'r-')&#xD;&#xA;&#xD;&#xA;    plt.axes().set_aspect ('equal')&#xD;&#xA;    r = 2*np.cos(np.pi/5)&#xD;&#xA;    plt.xlim(-2, 30)&#xD;&#xA;    plt.ylim(-2, 30)&#xD;&#xA;    Lx = np.cos(np.pi/10)&#xD;&#xA;    for j in np.arange(0, 10):&#xD;&#xA;        Xorig = (j%2)*Lx*np.ones(N+1)&#xD;&#xA;        Yorig = j*(1+2*np.cos(np.pi/5)+np.cos(2*np.pi/5))*np.ones(N+1)&#xD;&#xA;        theta = np.pi/(2*N)&#xD;&#xA;        sign = 1&#xD;&#xA;        for i in np.arange(1, 32):&#xD;&#xA;            pentagon(Xorig, Yorig, theta)&#xD;&#xA;            Xorig += r*np.cos(3*theta)*np.ones(N+1)&#xD;&#xA;            Yorig += r*np.sin(3*theta)*np.ones(N+1)&#xD;&#xA;            sign *= -1&#xD;&#xA;            theta = sign*np.pi/(2*N)&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(&quot;pentagonLattice.png&quot;, bbox_inches='tight')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;Also I haven't found yet a simple way to make a quasi-periodic tiling of the plane with only pentagons and rhombi yet. The figure below indicates that it is possible&#xD;&#xA;&#xD;&#xA;[![pentagon quasi-periodic lattice][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TLnKi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vgjui.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11419" PostHistoryTypeId="2" PostId="4816" RevisionGUID="8d60a31a-d923-4371-b7ed-b8c91cd651e5" CreationDate="2017-03-07T06:10:11.150" UserId="2654" Text="They are not &quot;very similar images&quot;. They have quite different aspect ratios. The first one has a 5:6 aspect ratio, while the other has a 3:4 ratio.&#xD;&#xA;&#xD;&#xA;If you try to print a 5:6 image at 8x10, what you find is that if the width is 8, then a 5:6 image would have a height of 9.6, which is less than 10. So that means the 5:6 image can fit into the 8x10 region with its full width; some of the height will go unused.&#xD;&#xA;&#xD;&#xA;However, a 3:4 aspect ratio image at 8x10 doesn't do that. If the width is 8, then the 3:4 aspect ratio would require a height of 10.6. That would exceed the maximum available height, so the width cannot be full width. Instead, it uses the full height of 10, and the width used will only be 7.5.&#xD;&#xA;&#xD;&#xA;You will find that this is the case for all of the ones where you noted such a difference.&#xD;&#xA;&#xD;&#xA;The &quot;DPI&quot; its computing is essentially the number of pixels in the dimension that *isn't* the maximum. For the 3:4 image at 8x10, it takes the image width (1000) and divides by the area width (8). For the 5:6 image at 8x10, it takes the image height (1200) and divided by the area height (10).&#xD;&#xA;&#xD;&#xA;This number only makes sense if we assume that the image is being scaled independently in width and height to fit the page. That is, the aspect ratio of the image is not being preserved when printed. So a 5:6 image is being transformed into a 4:5 aspect ratio image when printed at 8x10.&#xD;&#xA;&#xD;&#xA;Since each dimension is being scaled differently, each dimension has its own DPI. The lowest DPI will be for the dimension being stretched the most. And that's what this formula seems to be computing.&#xD;&#xA;&#xD;&#xA;Of course... *who cares?* Stretching images creates obvious visual distortion, and should pretty much never be done when printing something you actually want to have a paper copy of. So I would declare this computation algorithm to be bogus and move to something that actually makes sense with a reasonable printing methodology." ContentLicense="CC BY-SA 3.0" />
  <row Id="11420" PostHistoryTypeId="2" PostId="4817" RevisionGUID="88c6670d-a786-48ea-8002-50c230e574e3" CreationDate="2017-03-07T10:24:44.110" UserId="6175" Text="Suppose I have two 3D triangles before &amp; after a single rotation around an unknown axis.&#xD;&#xA;How would I go about finding this axis?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11421" PostHistoryTypeId="1" PostId="4817" RevisionGUID="88c6670d-a786-48ea-8002-50c230e574e3" CreationDate="2017-03-07T10:24:44.110" UserId="6175" Text="Calculate a rotation around an arbitrary axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="11422" PostHistoryTypeId="3" PostId="4817" RevisionGUID="88c6670d-a786-48ea-8002-50c230e574e3" CreationDate="2017-03-07T10:24:44.110" UserId="6175" Text="|transformations|geometry|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11423" PostHistoryTypeId="50" PostId="4663" RevisionGUID="f93f1a74-56c5-4717-8a74-de8b4a8ffef1" CreationDate="2017-03-07T10:59:01.290" UserId="-1" />
  <row Id="11424" PostHistoryTypeId="2" PostId="4818" RevisionGUID="045ca774-195d-4ae3-b710-fc07087fbc7f" CreationDate="2017-03-07T11:08:32.130" UserId="137" Text="Take a point $P$ and it's rotated point $P'$.&#xD;&#xA;&#xD;&#xA;Find the plan that runs through the middle between them $C = \frac{P+P'}{2}$ and is perpendicular to the line connecting them.&#xD;&#xA;&#xD;&#xA;Do this for all 3 of them and find the line of the planes' intersection. That will be the rotation axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="11425" PostHistoryTypeId="5" PostId="4818" RevisionGUID="f7252372-f6e7-41f9-90f4-c87b27bcec06" CreationDate="2017-03-07T11:43:34.693" UserId="137" Comment="added 92 characters in body" Text="Take a point $P$ and it's rotated point $P'$.&#xD;&#xA;&#xD;&#xA;Find the plan that runs through the middle between them $C = \frac{P+P'}{2}$ and is perpendicular to the line connecting them.&#xD;&#xA;&#xD;&#xA;Do this for all 3 of them and find the line of the planes' intersection. That will be the rotation axis.&#xD;&#xA;&#xD;&#xA;If all mid-planes are coplanar then you can use the planes of the triangles themselves." ContentLicense="CC BY-SA 3.0" />
  <row Id="11426" PostHistoryTypeId="50" PostId="4659" RevisionGUID="3d270e27-1474-4183-9125-45ce16fe3398" CreationDate="2017-03-07T11:59:01.533" UserId="-1" />
  <row Id="11427" PostHistoryTypeId="2" PostId="4819" RevisionGUID="cf07ce6a-73ad-4913-b7f6-af1b79630d80" CreationDate="2017-03-07T13:03:03.557" UserId="6187" Text="I was suprised to learn that RGB tertiary colors are much more similar to RGB primary then secondary colors.&#xD;&#xA;I was expecting they will be halfway between them and look more like this: &lt;br/&gt;&#xD;&#xA;[![tertiary][1]][1]&#xD;&#xA;&#xD;&#xA;Rather then this: &lt;br/&gt;&#xD;&#xA;[![tertiary RGB][2]][2]&#xD;&#xA;&#xD;&#xA;Is there a reason/purpose for this disproportion? &lt;br/&gt;&#xD;&#xA;(I know how to calculate values- this is not my question. I'd like to know why correctly calculated tertiary RGB colors seems to be much closer to primary then secondary RGB colors)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M20cO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/nigie.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11428" PostHistoryTypeId="1" PostId="4819" RevisionGUID="cf07ce6a-73ad-4913-b7f6-af1b79630d80" CreationDate="2017-03-07T13:03:03.557" UserId="6187" Text="Why are RGB tertiary colors so similar to RGB primary colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11429" PostHistoryTypeId="3" PostId="4819" RevisionGUID="cf07ce6a-73ad-4913-b7f6-af1b79630d80" CreationDate="2017-03-07T13:03:03.557" UserId="6187" Text="|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11430" PostHistoryTypeId="5" PostId="4818" RevisionGUID="e89cf2d9-3893-46d4-a5a5-b4277b48f95f" CreationDate="2017-03-07T13:19:40.897" UserId="137" Comment="added 293 characters in body" Text="Take a point $P$ and it's rotated point $P'$.&#xD;&#xA;&#xD;&#xA;Find the plan that runs through the middle between them $C = \frac{P+P'}{2}$ and is perpendicular to the line connecting them.&#xD;&#xA;&#xD;&#xA;Do this for all 3 of them and find the line of the planes' intersection. That will be the rotation axis.&#xD;&#xA;&#xD;&#xA;If all mid-planes are coplanar then you can use the planes of the triangles themselves.&#xD;&#xA;&#xD;&#xA;To get the angle you can take a $P$ and $P'$ again and project them onto the axis.&#xD;&#xA;&#xD;&#xA;Take a point $A$ on the axis and the direction $v$ of the axis. The projected point is $P_p=A+\frac{v \cdot (P-A)}{v\cdot v} v$. And then the angle is $acos(\frac{dot(P-P_p, P'-P_p)}{|P-P_p|* |P'-P_p|})$" ContentLicense="CC BY-SA 3.0" />
  <row Id="11431" PostHistoryTypeId="2" PostId="4820" RevisionGUID="af54de23-dedd-4a3a-a4e4-081e00b03516" CreationDate="2017-03-07T14:47:37.547" UserId="6183" Text="I have trouble understanding the way a camera is set in Processing. For starters, when I set the eye position of the camera I have to set three coordinates. I'm assuming that the X coordinate is the horizontal border of the display and the Y coordinate would be the vertical border. I think the Z coordinate to be behind or in front my computer. &#xD;&#xA;&#xD;&#xA;So when I do:&#xD;&#xA;&#xD;&#xA;    camera(width/2, height/2, depth, 250, 250, 0, 0, 1, 0);&#xD;&#xA;&#xD;&#xA;I'm setting the camera in the middle of the display and putting it some depth in the axis that comes into my eyes.&#xD;&#xA;&#xD;&#xA;I think this part is clear enough. However, the two other parameters are not as clear. In particular in don't see the difference between the center of the scene and the last parameter which is the axis that is facing upward. &#xD;&#xA;&#xD;&#xA;For the center of the scene I'm assuming that it gives me the direction the camera is looking to but what is the axis that is facing upward? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11432" PostHistoryTypeId="1" PostId="4820" RevisionGUID="af54de23-dedd-4a3a-a4e4-081e00b03516" CreationDate="2017-03-07T14:47:37.547" UserId="6183" Text="Understanding camera() settings in processing" ContentLicense="CC BY-SA 3.0" />
  <row Id="11433" PostHistoryTypeId="3" PostId="4820" RevisionGUID="af54de23-dedd-4a3a-a4e4-081e00b03516" CreationDate="2017-03-07T14:47:37.547" UserId="6183" Text="|camera|processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11434" PostHistoryTypeId="5" PostId="4820" RevisionGUID="950eefad-1b7c-4334-bede-6dded8c28e47" CreationDate="2017-03-07T15:58:34.000" UserId="6183" Comment="added 46 characters in body" Text="I have trouble understanding the way a camera is set in [Processing][1] (according to the reference this shoudn't be very different from OpenGl). For starters, when I set the eye position of the camera I have to set three coordinates. I'm assuming that the X coordinate is the horizontal border of the display and the Y coordinate would be the vertical border. I think the Z coordinate to be behind or in front my computer. &#xD;&#xA;&#xD;&#xA;So when I do:&#xD;&#xA;&#xD;&#xA;    camera(width/2, height/2, depth, 250, 250, 0, 0, 1, 0);&#xD;&#xA;&#xD;&#xA;I'm setting the camera in the middle of the display and putting it some depth in the axis that comes into my eyes.&#xD;&#xA;&#xD;&#xA;I think this part is clear enough. However, the two other parameters are not as clear. In particular in don't see the difference between the center of the scene and the last parameter which is the axis that is facing upward. &#xD;&#xA;&#xD;&#xA;For the center of the scene I'm assuming that it gives me the direction the camera is looking to but what is the axis that is facing upward? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://processing.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="11435" PostHistoryTypeId="5" PostId="4812" RevisionGUID="4e4b12bf-1cac-4579-9963-1da8f5d668b3" CreationDate="2017-03-07T17:19:56.697" UserId="3003" Comment="Added example of using a texture matrix." Text="You need to set your texture coordinates appropriately. Let's look at one side of your cube. Let's say it's 100 x 100. If the user stretches the cube to be 100 x 150, you need to set the texture coordinates of the corner vertices to be:&#xD;&#xA;&#xD;&#xA;    lower left = &lt;0.0, 0.0&gt;&#xD;&#xA;    lower right = &lt;1.5, 0.0&gt;&#xD;&#xA;    upper right = &lt;1.5, 1.0&gt;&#xD;&#xA;    upper left = &lt;0.0, 1.0&gt;&#xD;&#xA;&#xD;&#xA;That's the easiest way to handle it. Another way to handle it would be to pass either as scale factor or scale matrix into your fragment shader and apply that to your texture coordinates before doing any sampling.&#xD;&#xA;&#xD;&#xA;To elaborate on the texture matrix idea, it's fairly simple. In your fragment shader, you'd have a uniform, say `textureMatrix` that's a `mat4`. It can contain any sort of transform you need - scale, rotation, translation, shear, etc. Before you sample any texture, you run the uv coordinates through the texture matrix, and then use the resulting values for your lookup. Something like this:&#xD;&#xA;&#xD;&#xA;    vec4 uv = gl_TexCoord[ 0 ]; // or whatever you called it coming from your vert. shader&#xD;&#xA;    vec4 newUV = textureMatrix * uv;&#xD;&#xA;    vec4 pixel = texture2D(texture, newUV.xy);&#xD;&#xA;&#xD;&#xA;To do your non-uniform scaling, your matrix would be a scale matrix. For example if you wanted to scale the Y coordinate, you could use a matrix like this:&#xD;&#xA;&#xD;&#xA;    | 1 0 0 0 |&#xD;&#xA;    | 0 2 0 0 |&#xD;&#xA;    | 0 0 0 0 |&#xD;&#xA;    | 0 0 0 1 |&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11436" PostHistoryTypeId="2" PostId="4821" RevisionGUID="718fe34e-f94c-4a2a-8226-1f7807e01388" CreationDate="2017-03-07T23:35:07.460" UserId="506" Text="As the [documentation](https://processing.org/reference/camera_.html) describes it, it looks like each group of three parameters is a vector in 3D space. The first three are the position of the “eye”, the next three are the position it’s looking at, and the last three are the “up vector”, i.e. the direction of an arrow pointing out of the top (…sort of—more detail below) of the eye. The positions aren’t related to the size of your display window—the view of your 3D geometry from the camera at that point will fill the display.&#xD;&#xA;&#xD;&#xA;In other words, if you have a [box](https://processing.org/reference/box_.html) centered at (0, 0, 0) that’s 1×1×1 units in size, then your camera should be positioned a few units away—say (2, 3, 4)—and looking roughly at the center of the box, i.e. (0, 0, 0). If the box is 100×100×100 instead, then the eye position should be on the same order of magnitude in distance, e.g. (200, 300, 400). The behavior of the up vector is a little more complicated to explain, but leaving it at (0,1,0) is fine for most purposes—it’s mostly there to help you avoid [gimbal lock](https://en.wikipedia.org/wiki/Gimbal_lock)." ContentLicense="CC BY-SA 3.0" />
  <row Id="11438" PostHistoryTypeId="2" PostId="4822" RevisionGUID="51dff76c-e7b2-4299-a114-4a48ad343e99" CreationDate="2017-03-08T01:35:32.813" UserId="1578" Text="This can be done in two ways - either use a sky with a sun in it as an cubemap-type light source outside your building, or use the windows as light sources. With BDPT, you could sort of do both, and consider the windows area light sources where the light differs depending upon the angle, using a sun and sky image/model, and then you could implement importance sampling so that you usually get light rays going from the sun instead of the darker sky. This way you get all the accuracy of a full sun and sky model, and it'll still look good at low sample rates." ContentLicense="CC BY-SA 3.0" />
  <row Id="11439" PostHistoryTypeId="2" PostId="4823" RevisionGUID="85ae16ae-2fff-4fc9-93f4-b4e814887a00" CreationDate="2017-03-08T05:27:29.110" UserId="1937" Text="Likely a gamma correction issue. Tertiary colours are some permutation of (1, 0.5, 0) in RGB, right? So the issue arises because without applying gamma, 0.5 appears less than half as bright as 1, so the blended colour skews towards the primary (1,0,0) rather than the secondary (1,1,0). The image below has linear colour on top, gamma corrected on the bottom, you can see the gamma corrected colours appear much closer to a halfway tone.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7wZsK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11440" PostHistoryTypeId="2" PostId="4824" RevisionGUID="1fa59950-48a4-454d-b2d7-7e2bd90024da" CreationDate="2017-03-08T09:18:14.720" UserId="6194" Text="When I download this image http://www.ucn.edu.ni/media/2016/03/graduados-ucn-nicaragua.jpg then its total size is 341,0 kB.&#xD;&#xA;&#xD;&#xA;The image has a width of 2880 pixels and height of 1100 pixel and 1 X/Y resolution pixel/in.&#xD;&#xA;&#xD;&#xA;I opened the image with gimp and pressed **scale image** and reduced the width to 1920px and auto adjusted height of 733px, and keeped the resolution as it is and used the interpolation cubic. If I now export this as a jpg with 90% quality, then the image size is 546 kB! &#xD;&#xA;&#xD;&#xA;How is that possible and how can I avoid that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11441" PostHistoryTypeId="1" PostId="4824" RevisionGUID="1fa59950-48a4-454d-b2d7-7e2bd90024da" CreationDate="2017-03-08T09:18:14.720" UserId="6194" Text="reducing image size increases file size?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11442" PostHistoryTypeId="3" PostId="4824" RevisionGUID="1fa59950-48a4-454d-b2d7-7e2bd90024da" CreationDate="2017-03-08T09:18:14.720" UserId="6194" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11443" PostHistoryTypeId="2" PostId="4825" RevisionGUID="2bc2564b-3df7-4328-b8d4-1df42606115b" CreationDate="2017-03-08T09:28:19.447" UserId="3073" Text="JPEG is a lossless format and depends on both the 2d frequency components of the image and the user specified quality level.&#xD;&#xA;&#xD;&#xA;It is possible that downscaling an image can increase the higher frequency components and potentially result in an increase in file size, typically higher frequency components a encoded using a higher number of bits compared to lower frequency components. An example would be to imagine shrinking a checkerboard texture, the smaller it gets the more it shifts into higher frequency.  &#xD;&#xA;&#xD;&#xA;It may also be possible that your original image was encoded with a low quality factor and your new image has a high quality factor so it can also gain extra bytes from that. On a more technical level this may be because of a mismatch in quantisation bands leading to higher number of DCT coefficients being needed compared to the original JPEG.&#xD;&#xA;&#xD;&#xA;Another problem is that because you are using JPEG as a source image it will introduce ringing artefacts into the image, which then need more bits to encode when trying to encode it.&#xD;&#xA;&#xD;&#xA;Unfortunately there is no easy fix for this apart from reducing quality." ContentLicense="CC BY-SA 3.0" />
  <row Id="11444" PostHistoryTypeId="5" PostId="4825" RevisionGUID="9ecfda82-5cb2-4dc5-9809-403c4424c021" CreationDate="2017-03-08T09:37:12.840" UserId="3073" Comment="added 119 characters in body" Text="JPEG is a lossless format and depends on both the 2d frequency components of the image and the user specified quality level.&#xD;&#xA;&#xD;&#xA;It is possible that downscaling an image can increase the higher frequency components and potentially result in an increase in file size, typically higher frequency components a encoded using a higher number of bits compared to lower frequency components. An example would be to imagine shrinking a checkerboard texture, the smaller it gets the more it shifts into higher frequency.  &#xD;&#xA;&#xD;&#xA;It may also be possible that your original image was encoded with a low quality factor and your new image has a high quality factor so it can also gain extra bytes from that. On a more technical level this may be because of a mismatch in quantisation bands leading to higher number of DCT coefficients being needed compared to the original JPEG. The quality parameter is not standardised and different applications have different ideas of what '90% quality' means.&#xD;&#xA;&#xD;&#xA;Another problem is that because you are using JPEG as a source image it will introduce ringing artefacts into the image, which then need more bits to encode when trying to encode it.&#xD;&#xA;&#xD;&#xA;Unfortunately there is no easy fix for this apart from reducing quality." ContentLicense="CC BY-SA 3.0" />
  <row Id="11445" PostHistoryTypeId="5" PostId="4825" RevisionGUID="cb3c0f3d-30d4-4fb7-9c3c-5c32f38984c9" CreationDate="2017-03-08T09:50:06.233" UserId="137" Comment="spelling and you meant lossy" Text="JPEG is a lossy format and depends on both the 2d frequency components of the image and the user specified quality level.&#xD;&#xA;&#xD;&#xA;It is possible that down-scaling an image can increase the higher frequency components and potentially result in an increase in file size, typically higher frequency components a encoded using a higher number of bits compared to lower frequency components. An example would be to imagine shrinking a checkerboard texture, the smaller it gets the more it shifts into higher frequency.  &#xD;&#xA;&#xD;&#xA;It may also be possible that your original image was encoded with a low quality factor and your new image has a high quality factor so it can also gain extra bytes from that. On a more technical level this may be because of a mismatch in quantization bands leading to higher number of DCT coefficients being needed compared to the original JPEG. The quality parameter is not standardized and different applications have different ideas of what '90% quality' means.&#xD;&#xA;&#xD;&#xA;Another problem is that because you are using JPEG as a source image it will introduce ringing artifacts into the image, which then need more bits to encode when trying to encode it.&#xD;&#xA;&#xD;&#xA;Unfortunately there is no easy fix for this apart from reducing quality." ContentLicense="CC BY-SA 3.0" />
  <row Id="11446" PostHistoryTypeId="4" PostId="4820" RevisionGUID="46793b24-0e94-412b-9fd4-593255cb6fe5" CreationDate="2017-03-08T10:21:41.930" UserId="506" Comment="capitalized Processing in title to clarify it’s a proper noun and not the generic process of processing something" Text="Understanding camera() settings in Processing" ContentLicense="CC BY-SA 3.0" />
  <row Id="11447" PostHistoryTypeId="24" PostId="4820" RevisionGUID="46793b24-0e94-412b-9fd4-593255cb6fe5" CreationDate="2017-03-08T10:21:41.930" Comment="Proposed by 506 approved by 100, 209 edit id of 206" ContentLicense="CC BY-SA 3.0" />
  <row Id="11448" PostHistoryTypeId="2" PostId="4826" RevisionGUID="a9c5d152-ae53-4d04-aeb0-7fe54abc62d1" CreationDate="2017-03-08T15:24:17.080" UserId="303" Text="Every 3D rotation has an associated space that can be generated by 3 basis vectors, which can be seen as the axis of the coordenate system of this space. These vectors are also the 3 columns of the transformation matrix. In order to decrease the dof of the rotation, you should provide one or more of these basis vectors and solve for the rest of the matrix. The same principle applies to the translation vector, you should provide constants for one or more distances of the translation. Of course, if you restrict the transformation too much you will end with an unsolvable exact system or a transformation that take the first triangle too far away from the second one, if you are using a non-linear solver." ContentLicense="CC BY-SA 3.0" />
  <row Id="11449" PostHistoryTypeId="2" PostId="4827" RevisionGUID="f6d8cd96-befc-4366-84cd-177fd0fb7650" CreationDate="2017-03-09T02:24:19.703" UserId="537" Text="Your original image is very low in quality and talking with experance image with such dimension should have 3MB size but your file  is already compressed using lossy data FFT algorithm, deflated upto 0.1 rate and had lost a lot of data before you download it!&#xA;&#xA;In order to reduce the dimensions and preserving the filesize ratio, image editor program needs to extract the image and omit the lines vertically and horiznotally to reach to the desired dimensions and compress it again using a lossy data algorithm upto 10 percent but unfortunately  this time the image will loose too much data and you will unable to recognize the faces in it. So you must select a higher quality cause the file just can not tolerate to loose any data again!&#xA;This means you can not compress the extracted file as well as it was at first place.&#xA;&#xA;Jpg uses fast fourier transform to move color data from space to frequency and it does something like regression so the neibour pixels affect each other tile by tile, this is the nature of lossy data compression,you loose too much data, and if you select a high quality output you may get a big file in this case with low quality cause it has already lost some data.&#xA;&#xA;Comparing with PNG which uses ZLIb algorithm(non lossy data) I believe you may recieve a better result if you save your altered dimension file in to PNG, the image has a lot of same color pixel that will let ZLIB to compress it very well." ContentLicense="CC BY-SA 3.0" />
  <row Id="11450" PostHistoryTypeId="2" PostId="4828" RevisionGUID="895cd55a-f7d9-4e16-af36-766848c9bf86" CreationDate="2017-03-09T10:35:36.013" UserId="3123" Text="What are ways to render high resolution screenshot from application?&#xD;&#xA;Problem is I have to capture screenshot in higher resolution that it is present on screen. Resolution can be higher than 4K so making one big render target isn't option also rendering parts of scene and merging them will have artifacts in effects like `SSR` or `vignette`.&#xD;&#xA;&#xD;&#xA;Are there any other options to do this?&#xD;&#xA;&#xD;&#xA;Rendering is done with classic triangle rasterisation and it have to stay this way." ContentLicense="CC BY-SA 3.0" />
  <row Id="11451" PostHistoryTypeId="1" PostId="4828" RevisionGUID="895cd55a-f7d9-4e16-af36-766848c9bf86" CreationDate="2017-03-09T10:35:36.013" UserId="3123" Text="High resolution screenshot" ContentLicense="CC BY-SA 3.0" />
  <row Id="11452" PostHistoryTypeId="3" PostId="4828" RevisionGUID="895cd55a-f7d9-4e16-af36-766848c9bf86" CreationDate="2017-03-09T10:35:36.013" UserId="3123" Text="|capture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11456" PostHistoryTypeId="2" PostId="4830" RevisionGUID="ccef129f-823f-4fed-a464-4eb82f6740cc" CreationDate="2017-03-09T12:30:16.693" UserId="5406" Text="I'm having trouble understanding the JFA (http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). As far as I understood the algorithm, it walks *log(n)* times through every pixel (no matter if it is a seed or not) and looks at that pixels neighbors in $(x+i, y+j)$ where $i,j \in \{-step length, 0, step length\}$. When finding a seed (i.e., a colored pixel) among those neighbors, it checks whether the distance between the found neighbor seed and the current pixel is less than the distance the current pixel has already stored (after a previous round). If it is, the current pixel will be overwritten with the color of the found seed and the new distance. &#xD;&#xA;&#xD;&#xA;So I tried to comprehend an example in some slides by the author himself but failed at step length 2, especially with the three bottommost red seeds:[![example][1]][1] For example, why does the blue circled seed keep its red color even though at step length 2 it finds two green seeds with a smaller distance (in my understanding the circled red pixel has stored a 4 and the distance to its top and bottom green neighbors is 2)? Or why does the other blue circled pixel become red, though its *(x+2, y)* neighbor is a green one with a smaller distance than its *(x+2, y+2)* red neighbor? I also sketched another example on paper but when it comes to step length 1 the algorithm finds more than one neighbor seed with equal distances, so how will it decide? We can also imagine a very simple example with a resolution of 4x4 and the [0,0] pixel being a red seed and the [3,3] pixel being a green seed. What are the diagonal pixels supposed to be according to the algorithm?&#xD;&#xA;&#xD;&#xA;What am I getting wrong?&#xD;&#xA;  [1]: https://i.stack.imgur.com/dGXJd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11457" PostHistoryTypeId="1" PostId="4830" RevisionGUID="ccef129f-823f-4fed-a464-4eb82f6740cc" CreationDate="2017-03-09T12:30:16.693" UserId="5406" Text="Understanding Jump Flooding Algorithm (JFA) for Voronoi Diagrams" ContentLicense="CC BY-SA 3.0" />
  <row Id="11458" PostHistoryTypeId="3" PostId="4830" RevisionGUID="ccef129f-823f-4fed-a464-4eb82f6740cc" CreationDate="2017-03-09T12:30:16.693" UserId="5406" Text="|algorithm|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11459" PostHistoryTypeId="5" PostId="4827" RevisionGUID="597a8e13-79e0-48e2-b50d-4cc28805d691" CreationDate="2017-03-09T13:04:37.927" UserId="537" Comment="deleted 247 characters in body" Text="Your original image is very low in quality and talking with experance image with such dimension should have 3MB size but your file  is already compressed using lossy data DCT algorithm, deflated upto 0.1 rate and had lost a lot of data before you download it!&#xA;&#xA;In order to reduce the dimensions and preserving the filesize ratio, image editor program needs to extract the image and omit the lines vertically and horiznotally to reach to the desired dimensions and compress it again using a lossy data algorithm upto 10 percent but unfortunately  this time the image will loose too much data and you will unable to recognize the faces in it. So you must select a higher quality cause the file just can not tolerate to loose any data again!&#xA;This means you can not compress the extracted file as well as it was at first place.&#xA;&#xA;Comparing JPEG encoding (after resizing the image ) with PNG which uses ZLIb algorithm(non lossy data) I believe you may recieve a better result if you save your altered dimension file in to PNG, the image has a lot of same color pixel that will let ZLIB to compress it very well. This is only true in case you have a file which is once compressed using JPEG." ContentLicense="CC BY-SA 3.0" />
  <row Id="11463" PostHistoryTypeId="2" PostId="4832" RevisionGUID="cd745784-7e68-4a00-b643-ce0135e2edd3" CreationDate="2017-03-09T16:24:25.097" UserId="6204" Text="I'm trying to calculate camera paramters and a hand eye calibration (Transformation from camera to eye (display) coordinates) for rendering on a see-through HMD.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have already calculated a Projection matrix P (using SPAAM) which transforms points in the camera coordinate system to the screen (Tested by custom rendering).&#xD;&#xA;&#xD;&#xA;Cause of the used framework (metaio) I can't set the projection matrix directly  but have to separately set the camera parameters and Hand Eye calibration for rendering.&#xD;&#xA;&#xD;&#xA;Therefore I have extracted the extrinsic (E) and intrinsic (I) camera parameters from the Projection matrix P.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But those are not working correctly when set. The result seems to be not completely off, cause the rendered scale seems to be correct.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I guess I'm missing some additional step I'm not aware of or the extrinsics are not the hand-eye-calibration I'm looking for.&#xD;&#xA;&#xD;&#xA;I appreciate any ideas and help.&#xD;&#xA;&#xD;&#xA;Additional information:&#xD;&#xA;&#xD;&#xA; - right handed coordinate system with camera looking in negative z axsis, x to the right and y up&#xD;&#xA; - Since The translation part of HEC on the x- axis has to be positive (known from working configs) (camera is on the right side of the HMD) I assume it's transformation is specified from eye to camera?&#xD;&#xA;&#xD;&#xA;PS: Before I realized this stackexchange exist, I have already asked the question [here][2]. I got unfortunately no feedback so far.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WKalf.png&#xD;&#xA;  [2]: http://stackoverflow.com/questions/42623966/calculate-camera-parameters-and-handeyecalibration" ContentLicense="CC BY-SA 3.0" />
  <row Id="11464" PostHistoryTypeId="1" PostId="4832" RevisionGUID="cd745784-7e68-4a00-b643-ce0135e2edd3" CreationDate="2017-03-09T16:24:25.097" UserId="6204" Text="Calculate Camera parameters and HandEyeCalibration" ContentLicense="CC BY-SA 3.0" />
  <row Id="11465" PostHistoryTypeId="3" PostId="4832" RevisionGUID="cd745784-7e68-4a00-b643-ce0135e2edd3" CreationDate="2017-03-09T16:24:25.097" UserId="6204" Text="|transformations|projections|perspective|camera-matrix|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11466" PostHistoryTypeId="5" PostId="4830" RevisionGUID="3e04b7fd-2ad9-492c-9553-89e73a198678" CreationDate="2017-03-09T22:34:07.000" UserId="5406" Comment="added 54 characters in body" Text="I'm having trouble understanding the JFA (http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). As far as I understood the algorithm, it walks *log(n)* times through every pixel (no matter if it is a seed or not) and looks at that pixels neighbors in $(x+i, y+j)$ where $i,j \in \{-step length, 0, step length\}$. When finding a seed (i.e., a colored pixel) among those neighbors, it checks whether the distance between the found neighbor seed and the current pixel is less than the distance the current pixel has already stored (after a previous round). If it is, the current pixel will be overwritten with the color of the found seed and the new distance and therefore serves as input seed for the next round. &#xD;&#xA;&#xD;&#xA;So I tried to comprehend an example in some slides by the author himself but failed at step length 2, especially with the three bottommost red seeds:[![example][1]][1] For example, why does the blue circled seed keep its red color even though at step length 2 it finds two green seeds with a smaller distance (in my understanding the circled red pixel has stored a 4 and the distance to its top and bottom green neighbors is 2)? Or why does the other blue circled pixel become red, though its *(x+2, y)* neighbor is a green one with a smaller distance than its *(x+2, y+2)* red neighbor? I also sketched another example on paper but when it comes to step length 1 the algorithm finds more than one neighbor seed with equal distances, so how will it decide? We can also imagine a very simple example with a resolution of 4x4 and the [0,0] pixel being a red seed and the [3,3] pixel being a green seed. What are the diagonal pixels supposed to be according to the algorithm?&#xD;&#xA;&#xD;&#xA;What am I getting wrong?&#xD;&#xA;  [1]: https://i.stack.imgur.com/dGXJd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11468" PostHistoryTypeId="5" PostId="257" RevisionGUID="d3bd83ed-f7db-4d91-85bf-aab6960777bf" CreationDate="2017-03-10T09:42:35.270" UserId="-1" Comment="replaced http://docs.gimp.org/ with https://docs.gimp.org/" Text="In image editing software, you often have the ability to do a directional blur where you can choose and angle and a magnitude of a blur.&#xD;&#xA;&#xD;&#xA;How does this actually work in practice with Gaussian blurring?&#xD;&#xA;&#xD;&#xA;I could see possibly doing something like making the blur go across the axis specified by the angle and use some sort of texture sampling to find the appropriate sample (bilinear or bicubic sampling), but that seems like it probably isn't correct.&#xD;&#xA;&#xD;&#xA;How does directional blurring usually work?&#xD;&#xA;&#xD;&#xA;I would say this is in fact motion blur, but I'm asking specifically about the blurring portion, not the whole set up for motion blur within a renderer.&#xD;&#xA;&#xD;&#xA;For instance before and after:&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.gimp.org/en_GB/images/filters/examples/taj_orig.jpg&#xD;&#xA;  [2]: https://docs.gimp.org/en_GB/images/filters/examples/blur-taj-mblur-linear.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11469" PostHistoryTypeId="5" PostId="1524" RevisionGUID="36a154c1-e803-4b93-aa96-65a6bd69e897" CreationDate="2017-03-10T09:42:35.410" UserId="-1" Comment="replaced http://latex.codecogs.com/ with https://latex.codecogs.com/" Text="I wrote a particle based fluid simulating program. It's hard to tell if I get the right result. The visualized result seems reasonable, but some part of it looks weird. I don't know wether it's a feature of fluid. Is there some accurate method to verify if my program is right?&#xD;&#xA;&#xD;&#xA;Amending some details：&#xD;&#xA;&#xD;&#xA;My program is a 2D particle-based simulating program. The fluid is compressible. The implementation is almost based on a classical paper:&#xD;&#xA;&#xD;&#xA;&gt; Müller, Matthias, David Charypar, and Markus Gross. &quot;Particle-based fluid simulation for interactive applications.&quot; Proceedings of the 2003 ACM SIGGRAPH&#xD;&#xA;&#xD;&#xA;I solved the Navier-Stokes equation with iteration method. It only considered pressure, gravity, viscosity and surface tension.&#xD;&#xA;&#xD;&#xA;&lt;a href=&quot;http://www.codecogs.com/eqnedit.php?latex=\rho&amp;space;(\frac{\mathbf{\partial&amp;space;v}}{\partial&amp;space;t}&amp;space;&amp;plus;&amp;space;\mathbf{v}&amp;space;\cdot&amp;space;\bigtriangledown&amp;space;\mathbf{v})&amp;space;=&amp;space;-\bigtriangledown&amp;space;p&amp;space;&amp;plus;&amp;space;\rho\mathbf{g}&amp;space;&amp;plus;&amp;space;\mu&amp;space;\bigtriangledown^2&amp;space;\mathbf{v}&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?\rho&amp;space;(\frac{\mathbf{\partial&amp;space;v}}{\partial&amp;space;t}&amp;space;&amp;plus;&amp;space;\mathbf{v}&amp;space;\cdot&amp;space;\bigtriangledown&amp;space;\mathbf{v})&amp;space;=&amp;space;-\bigtriangledown&amp;space;p&amp;space;&amp;plus;&amp;space;\rho\mathbf{g}&amp;space;&amp;plus;&amp;space;\mu&amp;space;\bigtriangledown^2&amp;space;\mathbf{v}&quot; title=&quot;\rho (\frac{\mathbf{\partial v}}{\partial t} + \mathbf{v} \cdot \bigtriangledown \mathbf{v}) = -\bigtriangledown p + \rho\mathbf{g} + \mu \bigtriangledown^2 \mathbf{v}&quot; /&gt;&lt;/a&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11470" PostHistoryTypeId="5" PostId="4437" RevisionGUID="b4df2c32-5df3-4110-8fa2-3d5ecd202254" CreationDate="2017-03-10T09:42:35.423" UserId="-1" Comment="replaced http://i.giphy.com/ with https://i.giphy.com/" Text="Rotations in 3D are normally done with matrices. The xyz Euler angles can be converted to matrices so that it can be used in the rotation.&#xD;&#xA;That is where something called rotation order comes in.&#xD;&#xA;Basically it says in what order you rotate the object.&#xD;&#xA;First you rotate the object around the x axis, then the y axis and lastly the z axis for example.&#xD;&#xA;&#xD;&#xA;This means that when you rotate the object around the x axis first, you change the way the y axis and z axis rotate.&#xD;&#xA;Of course this changes depending on the rotation order.&#xD;&#xA;&#xD;&#xA;This GIF shows how changing one axis value can change the others, but it doesn't work that way for everything.&#xD;&#xA;&#xD;&#xA;![gimbal lock](https://i.giphy.com/3oz8xXJ5NB2owg5V16.gif)&#xD;&#xA;&#xD;&#xA;Here you can also see at the end that I add in that gimbal lock.&#xD;&#xA;This is where I lose one axis of rotation.&#xD;&#xA;&#xD;&#xA;This could be fixed by changing the rotation order to an order, where it doesn't break the way it should work.&#xD;&#xA;It could also be fixed by not using Euler angles but Euler angles are handy and simple in 3D animation.&#xD;&#xA;&#xD;&#xA;In 3D animation it could lead to weird rotations since the values of the rotations have to be changed a lot to get a certain rotation that you want.&#xD;&#xA;If you would look at the xyz Euler angle values in a graph, you would see spikes because of that.&#xD;&#xA;This could lead to weird interpolation of the keyframes and a weird end result.&#xD;&#xA;&#xD;&#xA;If you would like to read more about the math behind it, I would recommend reading about rotation matrices in 3D.&#xD;&#xA;https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A little extra explanation for the animation:&#xD;&#xA;Rotation in this case is around axis (shown as circles) and by rotating on one axis, you rotate the other axis. The consequence is that with a normal rotation sphere (the sphere in the animation, but then without the axis being rotated) in the animation, you don't see these axis being rotated. If you get a gimbal lock, one axis is the same as another one, but with a normal rotation sphere it still tries to rotate as if that axis wasn't the same as another one, this means that it uses weird values to get to that rotation and this can make an animation look weird.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope this helps!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11471" PostHistoryTypeId="5" PostId="4830" RevisionGUID="5dcbf985-4635-469b-a334-b9bed2079179" CreationDate="2017-03-10T11:32:05.187" UserId="5406" Comment="added second picture" Text="I'm having trouble understanding the JFA (http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). As far as I understood the algorithm, it walks *log(n)* times through every pixel (no matter if it is a seed or not) and looks at that pixels neighbors in $(x+i, y+j)$ where $i,j \in \{-step length, 0, step length\}$. When finding a seed (i.e., a colored pixel) among those neighbors, it checks whether the distance between the found neighbor seed and the current pixel is less than the distance the current pixel has already stored (after a previous round). If it is, the current pixel will be overwritten with the color of the found seed and the new distance and therefore serves as input seed for the next round. &#xD;&#xA;&#xD;&#xA;So I tried to comprehend an example in some slides by the author himself but failed at step length 2, especially with the three bottommost red seeds:[![example][1]][1] For example, why does the blue circled seed keep its red color even though at step length 2 it finds two green seeds with a smaller distance (in my understanding the circled red pixel has stored a 4 and the distance to its top and bottom green neighbors is 2)? Or why does the other blue circled pixel become red, though its *(x+2, y)* neighbor is a green one with a smaller distance than its *(x+2, y+2)* red neighbor? I also sketched another example on paper but when it comes to step length 1 the algorithm finds more than one neighbor seed with equal distances, so how will it decide? We could also think of a more simple example like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What are the diagonal pixels supposed to be according to the algorithm in that case?&#xD;&#xA;&#xD;&#xA;What am I getting wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dGXJd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mWkzJs.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11472" PostHistoryTypeId="5" PostId="4828" RevisionGUID="7eaf3c6e-3978-4b9c-8282-11fe87a37c37" CreationDate="2017-03-10T11:47:45.860" UserId="3123" Comment="added 226 characters in body" Text="What are ways to render high resolution screenshot from application?&#xD;&#xA;Problem is I have to capture screenshot in higher resolution that it is present on screen. Resolution can be higher than 4K so making one big render target isn't option also rendering parts of scene and merging them will have artifacts in effects like `SSR` or `vignette`.&#xD;&#xA;&#xD;&#xA;Are there any other options to do this?&#xD;&#xA;&#xD;&#xA;Rendering is done with classic triangle rasterisation and it have to stay this way.&#xD;&#xA;&#xD;&#xA;//EDIT&#xD;&#xA;&#xD;&#xA;Screenshots are from game and saved in `PNG`.&#xD;&#xA;&#xD;&#xA;Can't render to higher resolution because no everyone have enough `VRAM` (it can be higer than 7680x4320)&#xD;&#xA;&#xD;&#xA;I use standard `Tiled Deferred Rendering` with `DX11`." ContentLicense="CC BY-SA 3.0" />
  <row Id="11473" PostHistoryTypeId="5" PostId="4830" RevisionGUID="ceccbae4-68b4-47c2-83f9-943e855a0e52" CreationDate="2017-03-10T13:42:31.800" UserId="5406" Comment="grammar" Text="I'm having trouble understanding the JFA (http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). As far as I understood the algorithm, it walks *log(n)* times through every pixel (no matter if it is a seed or not) and looks at that pixel's neighbors in $(x+i, y+j)$ where $i,j \in \{-step length, 0, step length\}$. When finding a seed (i.e., a colored pixel) among those neighbors, it checks whether the distance between the found neighbor seed and the current pixel is less than the distance the current pixel has already stored (after a previous round). If it is, the current pixel will be overwritten with the color of the found seed and the new distance and therefore serves as input seed for the next round. &#xD;&#xA;&#xD;&#xA;So I tried to comprehend an example in some slides by the author himself but failed at step length 2, especially with the three bottommost red seeds:[![example][1]][1] For example, why does the blue circled seed keep its red color even though at step length 2 it finds two green seeds with a smaller distance (in my understanding the circled red pixel has stored a 4 and the distance to its top and bottom green neighbors is 2)? Or why does the other blue circled pixel become red, though its *(x+2, y)* neighbor is a green one with a smaller distance than its *(x+2, y+2)* red neighbor? I also sketched another example on paper but when it comes to step length 1 the algorithm finds more than one neighbor seed with equal distances, so how will it decide? We could also think of a more simple example like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What are the diagonal pixels supposed to be according to the algorithm in that case?&#xD;&#xA;&#xD;&#xA;What am I getting wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dGXJd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mWkzJs.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11477" PostHistoryTypeId="50" PostId="4684" RevisionGUID="67871477-c740-4a56-aa2a-40686aff639b" CreationDate="2017-03-10T17:15:11.177" UserId="-1" />
  <row Id="11478" PostHistoryTypeId="5" PostId="4830" RevisionGUID="2ae12598-c453-4cb1-ae6b-1d068e7caec8" CreationDate="2017-03-10T19:56:16.560" UserId="361" Comment="Link and paragraph formatting; tags." Text="I'm having trouble understanding the [JFA](http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). As far as I understood the algorithm, it walks *log(n)* times through every pixel (no matter if it is a seed or not) and looks at that pixel's neighbors in $(x+i, y+j)$ where $i,j \in \{-step\ length, 0, step\ length\}$. &#xD;&#xA;&#xD;&#xA;When finding a seed (i.e., a colored pixel) among those neighbors, it checks whether the distance between the found neighbor seed and the current pixel is less than the distance the current pixel has already stored (after a previous round). If it is, the current pixel will be overwritten with the color of the found seed and the new distance and therefore serves as input seed for the next round. &#xD;&#xA;&#xD;&#xA;So I tried to comprehend an example in some slides by the author himself but failed at step length 2, especially with the three bottommost red seeds:&#xD;&#xA;&#xD;&#xA;[![complex example][1]][1]&#xD;&#xA;&#xD;&#xA;For example, why does the blue circled seed keep its red color even though at step length 2 it finds two green seeds with a smaller distance (in my understanding the circled red pixel has stored a 4 and the distance to its top and bottom green neighbors is 2)? Or why does the other blue circled pixel become red, though its *(x+2, y)* neighbor is a green one with a smaller distance than its *(x+2, y+2)* red neighbor? &#xD;&#xA;&#xD;&#xA;I also sketched another example on paper but when it comes to step length 1 the algorithm finds more than one neighbor seed with equal distances, so how will it decide? We could also think of a more simple example like this:&#xD;&#xA;&#xD;&#xA;[![simple example][2]][2]&#xD;&#xA;&#xD;&#xA;What are the diagonal pixels supposed to be according to the algorithm in that case? What am I getting wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dGXJd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mWkzJs.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11479" PostHistoryTypeId="6" PostId="4830" RevisionGUID="2ae12598-c453-4cb1-ae6b-1d068e7caec8" CreationDate="2017-03-10T19:56:16.560" UserId="361" Comment="Link and paragraph formatting; tags." Text="|algorithm|color|mathematics|2d|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11480" PostHistoryTypeId="24" PostId="4830" RevisionGUID="2ae12598-c453-4cb1-ae6b-1d068e7caec8" CreationDate="2017-03-10T19:56:16.560" Comment="Proposed by 361 approved by 5406 edit id of 207" ContentLicense="CC BY-SA 3.0" />
  <row Id="11482" PostHistoryTypeId="2" PostId="4835" RevisionGUID="3ac5e173-15c7-42a3-8451-b372cc3ef5e3" CreationDate="2017-03-10T20:33:09.150" UserId="6125" Text="I think that there is a bit of confusion in terminology. My understanding is that only the initially colored points, before step 1, are called seeds. &#xD;&#xA;&#xD;&#xA;Maybe this helps clarify the algorithm as well. When the a point $ p $ with color $ s $ finds a neighbor $ q $ with color $ s' $, he compares the distance $ d(p,s) $ with $ d(p,s') $ (not $ d(p,q) $) to decide his new color. This is why each pixel crucially holds the $ (x,y) $ coordinates of his seed color (in the paper they used the r,g channels for this) and not just the distance. In each step this data is also passed to the neighbor. &#xD;&#xA;&#xD;&#xA;So in that example, in moving from step length 4 to step length 2, that red square that remains read sees the green square who tells red square that the green seed is at $ (3,10) $. Red square then computes his distance to green square to be $ \sqrt{2^2 + 4^2} $, which is bigger than the distance to red ($ 4 $), and so remains red." ContentLicense="CC BY-SA 3.0" />
  <row Id="11483" PostHistoryTypeId="5" PostId="4835" RevisionGUID="45b9a39f-bb71-490b-bbc4-1ce4437557d0" CreationDate="2017-03-10T20:38:28.327" UserId="6125" Comment="added 17 characters in body" Text="I think that there is a bit of confusion in terminology. My understanding is that only the initially colored points, before step 1, are called seeds. &#xD;&#xA;&#xD;&#xA;Maybe this helps clarify the algorithm as well. When the a point $ p $ with color $ s $ finds a neighbor $ q $ with color $ s' $, he compares the distance $ d(p,s) $ with $ d(p,s') $ (not $ d(p,q) $) to decide his new color. This is why each pixel crucially holds the $ (x,y) $ coordinates of his seed color (in the paper they used the r,g channels for this) and not just the distance. In each step this data is also passed to the neighbor. &#xD;&#xA;&#xD;&#xA;So in that example, in moving from step length 4 to step length 2, that red square (the circled one that remains red) sees the green square who tells red square that the green seed is at $ (8,6) $. Red square then computes his distance to green square to be $ \sqrt{2^2 + 4^2} $, which is bigger than the distance to red ($ 4 $), and so remains red." ContentLicense="CC BY-SA 3.0" />
  <row Id="11487" PostHistoryTypeId="2" PostId="4836" RevisionGUID="cb26782b-43f9-4eec-961a-1c9f1e07b97d" CreationDate="2017-03-11T05:57:37.130" UserId="2308" Text="To keep things short in sweet I am going to have the following texture drawn hundreds of times all over the screen using a 4 point GL Triangle Strip. I would use GL's dots except I need to be able to orient the texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The color does not really matter as that will change so often.&#xD;&#xA;&#xD;&#xA;Technically this is not the only image. Occasionally the thing will switch to being just a dot texture. I am not sure how I will be implementing that quite yet however. Worst case scenario I will pass two textures into the shader.&#xD;&#xA;&#xD;&#xA;I need the drawing of this texture to be done as efficiently as humanly possible so I need to know if there is anything I can do to make sure that this does not cause OpenGL any hickups. If there is any good way to initialize the texture that will hold this, pass it in, or sample it please let me know.&#xD;&#xA;&#xD;&#xA;I am also not sure what resolution I want this shape to be drawn at. I dont know what the relationship between texture sampling cost and resolution is. Any suggestions?&#xD;&#xA;&#xD;&#xA;I considered drawing the shape inside of a fragment shader but my hunch is that it will be more expensive. But I shall see.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/35Hk6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11488" PostHistoryTypeId="1" PostId="4836" RevisionGUID="cb26782b-43f9-4eec-961a-1c9f1e07b97d" CreationDate="2017-03-11T05:57:37.130" UserId="2308" Text="Is this the fastest way to do this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11489" PostHistoryTypeId="3" PostId="4836" RevisionGUID="cb26782b-43f9-4eec-961a-1c9f1e07b97d" CreationDate="2017-03-11T05:57:37.130" UserId="2308" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11490" PostHistoryTypeId="2" PostId="4837" RevisionGUID="f1628328-5143-48eb-9bb7-f9104bc87786" CreationDate="2017-03-11T06:01:57.790" UserId="2308" Text="I am trying to make it so that objects leave trails behind them and if an object is in the back and tries to draw over a previous trail it is transparent because of it.&#xD;&#xA;&#xD;&#xA;The problem is whenever I do not GL_CLEAR the depth buffer after each frame the screen goes blank. Is there a way around this in Open GL ES 2.0?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11491" PostHistoryTypeId="1" PostId="4837" RevisionGUID="f1628328-5143-48eb-9bb7-f9104bc87786" CreationDate="2017-03-11T06:01:57.790" UserId="2308" Text="Do you have to clear the depth buffer each frame in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="11492" PostHistoryTypeId="3" PostId="4837" RevisionGUID="f1628328-5143-48eb-9bb7-f9104bc87786" CreationDate="2017-03-11T06:01:57.790" UserId="2308" Text="|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11493" PostHistoryTypeId="5" PostId="4837" RevisionGUID="794e5d37-2204-4656-adb0-2fbee6f81a65" CreationDate="2017-03-11T07:01:36.757" UserId="2308" Comment="added 101 characters in body" Text="I am trying to make it so that objects leave trails behind them and if an object is in the back and tries to draw over a previous trail it is transparent because of it.&#xD;&#xA;&#xD;&#xA;The problem is whenever I do not GL_CLEAR the depth buffer after each frame the screen goes blank. Is there a way around this in Open GL ES 2.0?&#xD;&#xA;&#xD;&#xA;Diagram:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LPxF6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11494" PostHistoryTypeId="6" PostId="4792" RevisionGUID="e89bfbd3-7038-44f6-837a-40fabf107d16" CreationDate="2017-03-11T16:11:25.067" UserId="2479" Comment="Added tags: monte-carlo, sampling" Text="|lighting|pathtracing|sampling|monte-carlo|render|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11495" PostHistoryTypeId="24" PostId="4792" RevisionGUID="e89bfbd3-7038-44f6-837a-40fabf107d16" CreationDate="2017-03-11T16:11:25.067" Comment="Proposed by 2479 approved by 5764 edit id of 209" ContentLicense="CC BY-SA 3.0" />
  <row Id="11496" PostHistoryTypeId="2" PostId="4838" RevisionGUID="f3e9cf2c-9206-4e28-8977-332daa7c673a" CreationDate="2017-03-11T17:39:01.493" UserId="6179" Text="What formula is for counting aspect ratio of the image as in this site:&#xD;&#xA;&#xD;&#xA;https://www.ninjaunits.com/calculators/aspect-ratio/&#xD;&#xA;&#xD;&#xA;For example: &#xD;&#xA;&#xD;&#xA;	 1000x1200 its aspect ratio 5:6 &#xD;&#xA;	 1000x1333 its aspect ratio 3:4&#xD;&#xA;     2592x3888 its aspect ratio 2:3&#xD;&#xA;&#xD;&#xA;I want to determine this by handling an uploaded image so it should be a formula for counting this, but did not figure out this yet." ContentLicense="CC BY-SA 3.0" />
  <row Id="11497" PostHistoryTypeId="1" PostId="4838" RevisionGUID="f3e9cf2c-9206-4e28-8977-332daa7c673a" CreationDate="2017-03-11T17:39:01.493" UserId="6179" Text="How to count an aspect ratio of an image when you have dimensions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11498" PostHistoryTypeId="3" PostId="4838" RevisionGUID="f3e9cf2c-9206-4e28-8977-332daa7c673a" CreationDate="2017-03-11T17:39:01.493" UserId="6179" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11499" PostHistoryTypeId="4" PostId="4838" RevisionGUID="0e5c864e-be21-40da-8a13-03c505b49881" CreationDate="2017-03-11T17:48:42.893" UserId="6179" Comment="edited title" Text="How to count aspect ratio of an image when you have dimensions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11500" PostHistoryTypeId="2" PostId="4839" RevisionGUID="8cd055a0-c5da-4928-abac-bd9088aaad5f" CreationDate="2017-03-11T18:46:56.427" UserId="5513" Text="Consider a triangular face of three vertices A(0,2,1), B(3,0,1) and the origin, and the normal vectors at the vertices are nA=(0,0,1), nB=(1,1,0) and nO=(-1,-1,1), respectively. The incident light is white and directional in the direction of L=(0,3,4) and the intensity is 1, the background ambient light intensity is 0.1, and the diffuse reflection coefficients for (red, green, blue) are (0.6,0.7,0.8). No specular light contribution need be considered. &#xD;&#xA;&#xD;&#xA;a) Find the (red, green, blue) intensity values at the centre of the face using flat shading.&#xD;&#xA;&#xD;&#xA;First, I try to calculate ambient light intensity&#xD;&#xA; &#xD;&#xA;ambient light intensity = ambient reflection coefficient x incident ambient light intensity&#xD;&#xA;&#xD;&#xA;so,&#xD;&#xA;&#xD;&#xA;red = 0.6 x 0.1 = 0.06&#xD;&#xA;&#xD;&#xA;green = 0.7 x 0.1 = 0.07&#xD;&#xA;&#xD;&#xA;blue = 0.8 x 0.1 = 0.08&#xD;&#xA;&#xD;&#xA;Then, I try to calculate diffuse light:&#xD;&#xA;&#xD;&#xA;diffuse light = incident light intensity x diffusive reflection light x costheta&#xD;&#xA;&#xD;&#xA;so,&#xD;&#xA;&#xD;&#xA;incident light intensity = 1&#xD;&#xA;&#xD;&#xA;diffusive reflection light is given as (0.6, 0.7, 0.8)&#xD;&#xA;&#xD;&#xA;I am not sure how to calculate costheta. I believe it to be the angle between the normal vector of a vertex and the incident light. But I am having difficulties because there are three different normal vectors.&#xD;&#xA;&#xD;&#xA;After that, I think I should sum the ambient light intensity with the diffuse light to get the final RGB values.&#xD;&#xA;&#xD;&#xA;I would really appreciate it if you could help me fill the gaps to my calculations. Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="11501" PostHistoryTypeId="1" PostId="4839" RevisionGUID="8cd055a0-c5da-4928-abac-bd9088aaad5f" CreationDate="2017-03-11T18:46:56.427" UserId="5513" Text="Rendering using flat shading" ContentLicense="CC BY-SA 3.0" />
  <row Id="11502" PostHistoryTypeId="3" PostId="4839" RevisionGUID="8cd055a0-c5da-4928-abac-bd9088aaad5f" CreationDate="2017-03-11T18:46:56.427" UserId="5513" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11503" PostHistoryTypeId="5" PostId="4811" RevisionGUID="1556d412-e97e-4cdc-948f-a8a79aa8fc61" CreationDate="2017-03-11T21:50:36.183" UserId="2479" Comment="Extended with requested details" Text="It's not that hard. If you have just planar or angular light sources, you can think of them as one light source split into multiple chunks and the only thing to deal with is how to sample this multi-light and how to compute the PDF of the resulting samples.&#xD;&#xA;&#xD;&#xA;Picking probability&#xD;&#xA;---------------------&#xD;&#xA;&#xD;&#xA;First, you need to setup the picking probability $P(l)$ for each light source $l$. The picking probabilities can be any non-negative numbers, you just have to make sure that are always non-zero if the contributions of the respective lights are non-zero. However, the more proportional the probabilities are to the actual light contribution, the better the overall performance of your Monte Carlo estimator will be.&#xD;&#xA;&#xD;&#xA;Contribution estimates may be:&#xD;&#xA;&#xD;&#xA; - $1$: naive, uniform probability; good to start with; used by PBRT&#xD;&#xA; - $power$: better&#xD;&#xA; - $power / distance^2$: even better; closer light sources have greater contributions&#xD;&#xA; - &amp;hellip;and other improvements: make zero if no visible at all, multiply by the cosine of the inclination angle, etc.&#xD;&#xA;&#xD;&#xA;Note that to get the light-picking probabilities, you need to normalise the contribution estimates to the sum of all of them:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;P(l)=&#xD;&#xA;  \frac&#xD;&#xA;    {ContrEstimate_l}&#xD;&#xA;    {\sum_{a\in\mathrm{Lights}}&#xD;&#xA;      {ContrEstimate_a}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You could even use more different picking strategies if you find they work just for certain type of scenes and combine them using multiple importance sampling technique&amp;hellip;&#xD;&#xA;&#xD;&#xA;Sampling&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;When sampling the lights, you just select one light $l$ with the appropriate probability $P(l)$ and then sample the light surface/angle with its own sampling strategy (with PDF $p_l$). The resulting PDF $p$ will be:&#xD;&#xA;$$&#xD;&#xA;p(x)=P(l) * p_l(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Evaluating PDF&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;When computing the light sampling PDF for given direction (as needed for multiple importance sampling), you just find the light source at the direction, evaluate the PDF of the lights own strategy and, again, multiply it by the probability of picking this particular light.&#xD;&#xA;&#xD;&#xA;Conclusion&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Now you have a sampling strategy which gives you PDF which can be used in the Monte Carlo estimators (e.g. $f(x)/p(x)$) and the resulting estimator will stay unbiased." ContentLicense="CC BY-SA 3.0" />
  <row Id="11504" PostHistoryTypeId="5" PostId="4811" RevisionGUID="aa541184-5c1d-4bd5-b2a3-61f0afcafb1b" CreationDate="2017-03-11T21:55:45.097" UserId="2479" Comment="Minors" Text="It's not that hard. If you have just planar or angular light sources, you can think of them as one light source split into multiple chunks and the only thing to deal with is how to sample this multi-light and how to compute the PDF of the resulting samples.&#xD;&#xA;&#xD;&#xA;Picking probability&#xD;&#xA;---------------------&#xD;&#xA;&#xD;&#xA;First, you need to setup the picking probability $P(l)$ for each light source $l$. The picking probabilities can be any non-negative numbers, you just have to make sure that are always non-zero if the contributions of the respective lights are non-zero. However, the closer the probabilities are to the actual (relative) light contribution, the better the overall performance of your Monte Carlo estimator will be.&#xD;&#xA;&#xD;&#xA;Contribution estimates may be:&#xD;&#xA;&#xD;&#xA; - $1$: naive, uniform probability; good to start with; used by PBRT&#xD;&#xA; - $power$: better&#xD;&#xA; - $power / distance^2$: even better; closer light sources have greater contributions&#xD;&#xA; - &amp;hellip;and other improvements: make zero if not visible at all, multiply by the cosine of the inclination angle, etc.&#xD;&#xA;&#xD;&#xA;Note that to get the light-picking probabilities, you need to normalise the contribution estimates to the sum of all of them:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;P(l)=&#xD;&#xA;  \frac&#xD;&#xA;    {ContrEstimate_l}&#xD;&#xA;    {\sum_{a\in\mathrm{Lights}}&#xD;&#xA;      {ContrEstimate_a}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You could even use more different picking strategies if you find they work just for certain type of scenes and combine them using multiple importance sampling technique&amp;hellip;&#xD;&#xA;&#xD;&#xA;Sampling&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;When sampling the lights, you just select one light $l$ with the appropriate probability $P(l)$ and then sample the light surface/angle with its own sampling strategy (with PDF $p_l$). The resulting PDF $p$ will be:&#xD;&#xA;$$&#xD;&#xA;p(x)=P(l) * p_l(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Evaluating PDF&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;When computing the light sampling PDF for given direction (as needed for multiple importance sampling), you just find the light source at the direction, evaluate the PDF of the lights own strategy and, again, multiply it by the probability of picking this particular light.&#xD;&#xA;&#xD;&#xA;Conclusion&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Now you have a sampling strategy which gives you PDF which can be used in the Monte Carlo estimators (e.g. $f(x)/p(x)$) and the resulting estimator will be unbiased." ContentLicense="CC BY-SA 3.0" />
  <row Id="11505" PostHistoryTypeId="2" PostId="4840" RevisionGUID="0d595158-5749-476e-9f3f-73098d78d443" CreationDate="2017-03-12T03:48:04.913" UserId="2707" Text="With flat shading, the normal is the same across the whole triangle (or quad or whatever).&#xD;&#xA;&#xD;&#xA;You'll most likely want to get the average vector to use as the triangle's normal. The assumption is that each vertex contributes the same amount of weight towards the triangle normal.&#xD;&#xA;&#xD;&#xA;$$\frac{(0,0,1) + (1,1,0) + (-1,-1,1)}{3} = (0,0,0.67)$$&#xD;&#xA;$$normalize(0,0,0.67) = (0,0,1)$$&#xD;&#xA;&#xD;&#xA;For Lambert shading:&#xD;&#xA;$$cos(\theta) = normalize(0,3,4) \cdot (0,0,1) $$" ContentLicense="CC BY-SA 3.0" />
  <row Id="11506" PostHistoryTypeId="2" PostId="4841" RevisionGUID="c13229cd-5745-4e1e-adec-c55dc83459a4" CreationDate="2017-03-12T09:04:58.073" UserId="3083" Text="One way you could do it is by writing the dimensions as a fraction, and simplifying that fraction (dividing each of the numbers by their greatest common denominator). From that you can then create a string and format it as [simplified numerator]:[simplified denominator].&#xA;&#xA;[This SO question][1] talks about this too, and it shows some code to implementing it in JavaScript and also suggests some libraries... although I don't know what language you're using, I think this will still help.&#xA;&#xA;&#xA;  [1]: http://stackoverflow.com/questions/4652468/is-there-a-javascript-function-that-reduces-a-fraction" ContentLicense="CC BY-SA 3.0" />
  <row Id="11507" PostHistoryTypeId="5" PostId="4839" RevisionGUID="be559a15-fa24-4486-927a-a747af19208f" CreationDate="2017-03-12T09:26:37.177" UserId="2707" Comment="I edited the question title to be more specific to your specific problem and reformatted the math." Text="Consider a triangular face of three vertices $A=(0,2,1)$, $B=(3,0,1)$ and the origin $O$, with normal vectors $(0,0,1)$, $(1,1,0)$, and $(-1,-1,1)$, respectively. The incident light is white and directional in the direction of $L = (0,3,4)$ and the intensity is $1$, the background ambient light intensity is $0.1$, and the diffuse reflection coefficients for $(red, green, blue)$ are $(0.6,0.7,0.8)$. No specular light contribution need be considered. &#xD;&#xA;&#xD;&#xA;To find the $(red, green, blue)$ intensity values at the centre of the face using flat shading, I follow this procedure:&#xD;&#xA;&#xD;&#xA;First, I try to calculate ambient light intensity&#xD;&#xA; &#xD;&#xA;$$ambient\ light\ intensity = (ambient\ reflection\ coefficient) \cdot (incident\ ambient\ light\ intensity)$$&#xD;&#xA;&#xD;&#xA;so,&#xD;&#xA;&#xD;&#xA;$$red = 0.6 \cdot 0.1 = 0.06$$&#xD;&#xA;&#xD;&#xA;$$green = 0.7 \cdot 0.1 = 0.07$$&#xD;&#xA;&#xD;&#xA;$$blue = 0.8 \cdot 0.1 = 0.08$$&#xD;&#xA;&#xD;&#xA;Then, I try to calculate diffuse light:&#xD;&#xA;&#xD;&#xA;$$diffuse\ light = (incident\ light\ intensity) \cdot (diffusive\ reflection\ light) \cdot \cos{\theta}$$&#xD;&#xA;&#xD;&#xA;so,&#xD;&#xA;&#xD;&#xA;$$incident\ light\ intensity = 1$$&#xD;&#xA;&#xD;&#xA;$diffusive\ reflection\ light$ is given as $(0.6, 0.7, 0.8)$&#xD;&#xA;&#xD;&#xA;I am not sure how to calculate $\cos{\theta}$. I believe it to be the angle between the normal vector of a vertex and the incident light. But I am having difficulties because there are three different normal vectors.&#xD;&#xA;&#xD;&#xA;After that, I think I should sum the ambient light intensity with the diffuse light to get the final RGB values.&#xD;&#xA;&#xD;&#xA;I would really appreciate it if you could help me fill the gaps to my calculations. Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="11508" PostHistoryTypeId="4" PostId="4839" RevisionGUID="be559a15-fa24-4486-927a-a747af19208f" CreationDate="2017-03-12T09:26:37.177" UserId="2707" Comment="I edited the question title to be more specific to your specific problem and reformatted the math." Text="How do you calculate cos(theta) for diffuse in flat shading?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11509" PostHistoryTypeId="24" PostId="4839" RevisionGUID="be559a15-fa24-4486-927a-a747af19208f" CreationDate="2017-03-12T09:26:37.177" Comment="Proposed by 2707 approved by 5513 edit id of 212" ContentLicense="CC BY-SA 3.0" />
  <row Id="11510" PostHistoryTypeId="2" PostId="4842" RevisionGUID="a132c2e3-e887-451b-93a3-984032302683" CreationDate="2017-03-12T09:42:45.390" UserId="5513" Text="Consider a triangular face of three vertices A(0,2,1), B(3,0,1) and the origin, and the normal vectors at the vertices are nA=(0,0,1), nB=(1,1,0) and nO=(-1,-1,1), respectively. The incident light is white and directional in the direction of L=(0,3,4) and the intensity is 1, the background ambient light intensity is 0.1, and the diffuse reflection coefficients for (red, green, blue) are (0.6,0.7,0.8). No specular light contribution need be considered. &#xD;&#xA;&#xD;&#xA;How do I find the (red, green, blue) intensity values at the centre of the face using flat shading?&#xD;&#xA;&#xD;&#xA;First, I get the ambient light intensity:&#xD;&#xA;&#xD;&#xA;ambient light intensity=(ambient reflection coefficient)&#xD;&#xA;⋅(incident ambient light intensity)&#xD;&#xA;&#xD;&#xA;so, &#xD;&#xA;&#xD;&#xA;red=0.6 x 0.1=0.06&#xD;&#xA;&#xD;&#xA;I do the same for green and blue...&#xD;&#xA;&#xD;&#xA;Then, I get the diffuse light:&#xD;&#xA;&#xD;&#xA;diffuse light=(incident light intensity)⋅(diffusive reflection light)⋅cosθ&#xD;&#xA;&#xD;&#xA;so, &#xD;&#xA;&#xD;&#xA;incident light intensity=1 &#xD;&#xA;&#xD;&#xA;red diffusive reflection light=0.6&#xD;&#xA;&#xD;&#xA;cosθ = 0.8&#xD;&#xA;&#xD;&#xA;inverse cosθ(0.8) = 36.9&#xD;&#xA;&#xD;&#xA;red = 1 x 0.6 x 36.9 = 22.1&#xD;&#xA;&#xD;&#xA;I do the same for green and blue...&#xD;&#xA;&#xD;&#xA;Finally, red intensity value at the centre of the face using flat shading would be:&#xD;&#xA;&#xD;&#xA;0.06 + 22.1 = 22.16&#xD;&#xA;&#xD;&#xA;I do the same things for green and blue...&#xD;&#xA;&#xD;&#xA;Is this correct?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11511" PostHistoryTypeId="1" PostId="4842" RevisionGUID="a132c2e3-e887-451b-93a3-984032302683" CreationDate="2017-03-12T09:42:45.390" UserId="5513" Text="How to calculate the RGB intensity values at center of face using flat shading?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11512" PostHistoryTypeId="3" PostId="4842" RevisionGUID="a132c2e3-e887-451b-93a3-984032302683" CreationDate="2017-03-12T09:42:45.390" UserId="5513" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11513" PostHistoryTypeId="2" PostId="4843" RevisionGUID="c01ee365-610b-46ca-bdd3-41bc5a3909c5" CreationDate="2017-03-12T12:57:28.707" UserId="6029" Text="In Ray-Sphere intersection is $b=2*(O-C) \cdot dirv$?&#xD;&#xA;&#xD;&#xA;Where $dirv$ is the Ray direction vector. $O$ is origin and $C$ is center of the sphere.&#xD;&#xA;&#xD;&#xA;I've also seen this without the $2$, i.e. $b=(O-C)\cdot dirv$.&#xD;&#xA;&#xD;&#xA;Particularly [here][1] it's calculated like:&#xD;&#xA;&#xD;&#xA;    // Compute:&#xD;&#xA;    //    d = L - E ; // Direction vector of ray, from start to end&#xD;&#xA;    //    f = E - C ; // Vector from center sphere to ray start&#xD;&#xA;    const Vector &amp;d = ray.direction ;&#xD;&#xA;    Vector f = ray.startPos - this-&gt;pos ;&#xD;&#xA;    real a = d • d ;  // a is non-negative, this is actually always 1.0&#xD;&#xA;    real b = 2*(f • d) ;&#xD;&#xA;    real c = f • f - radius*radius ;&#xD;&#xA;    &#xD;&#xA;    real discriminant = b*b-4*a*c;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://bobobobo.wordpress.com/2013/03/03/ray-sphere-intersection/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11514" PostHistoryTypeId="1" PostId="4843" RevisionGUID="c01ee365-610b-46ca-bdd3-41bc5a3909c5" CreationDate="2017-03-12T12:57:28.707" UserId="6029" Text="In Ray-Sphere intersection is $b=2*(O-C) \cdot dirv$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11515" PostHistoryTypeId="3" PostId="4843" RevisionGUID="c01ee365-610b-46ca-bdd3-41bc5a3909c5" CreationDate="2017-03-12T12:57:28.707" UserId="6029" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11516" PostHistoryTypeId="2" PostId="4844" RevisionGUID="22f56ba0-b0d3-451b-b179-06fbe2e130bb" CreationDate="2017-03-12T20:48:54.123" UserId="2941" Text="TL;DR $b = 2(f \cdot d)$&#xD;&#xA;&#xD;&#xA;I'll try to derive it and then we can see what $b$ should be. If the sphere is centered at point $a$ with radius $r$, its equation is $|p - a| = r$, where $p$ is a point on the sphere. $|p - a|$ is the distance from a point $p$ to the centre of the sphere, and if that is equal to the radius, then it's a point on the sphere.&#xD;&#xA;&#xD;&#xA;We'll assume the centre of the sphere is at the origin, so $a = 0$ and we have $|\vec{p}| = r$. Squaring both sides gives $|\vec{p}|^2 = r^2$ which I'm going to write as $$\vec{p}^2 = r^2 \tag{1}$$&#xD;&#xA;&#xD;&#xA;Ray has equation $$x + td\tag{2}$$ where $x$ is the endpoint, $d$ is the direction, and $t$ is the parameter.&#xD;&#xA;&#xD;&#xA;If the ray doesn't intersect the sphere, we will not be able to find a $t$ satisfying the ray equation. In the quadratic equation the discriminant (the bit under the square root) will be $&lt; 0$. If it grazes the sphere (i.e. tangent) then we'll have a single point of intersection and a single $t$ and the discriminant will be $0$. If it goes through the sphere, we'll get a $t$ for the sphere entry, and a distinct $t$ for the sphere exit and the discriminant will be $&gt; 0$. We need to plug $(2)$ into $(1)$ and solve for $t$:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{alignat}{2}&#xD;&#xA;  &amp;&amp;(x + td)^2  &amp;= r^2\\&#xD;&#xA;  &amp;\Rightarrow\quad&#xD;&#xA;  &amp;(x + td)(x + td)  &amp;= r^2\\&#xD;&#xA;  &amp;\Rightarrow\quad&#xD;&#xA;  &amp;x \cdot x + 2t(x \cdot d) + t^2(d \cdot d)  &amp;= r^2\\&#xD;&#xA;  &amp;\Rightarrow\quad&#xD;&#xA;  &amp;(d \cdot d)t^2 + 2(x \cdot d)t + (x \cdot x - r^2) &amp;= 0 \tag{3}\\&#xD;&#xA;\end{alignat}$$&#xD;&#xA;&#xD;&#xA;Equation $3$ is a quadratic expression in $t$ (i.e. $at^2 + bt + c = 0$) where $$a = (d \cdot d)$$ $$b = 2(x \cdot d)$$ $$c = (x \cdot x - r^2)$$&#xD;&#xA;&#xD;&#xA;This matches the code you posted, but the code is allowing spheres to be centered at an arbitrary point `C`. The code then has this line:&#xD;&#xA;&#xD;&#xA;    // f = E - C ; // Vector from center sphere to ray start&#xD;&#xA;&#xD;&#xA;which effectively translates the endpoint of the ray `E` to a new endpoint `f` so that we can now consider the sphere to be centered at the origin. The ray direction is unchanged." ContentLicense="CC BY-SA 3.0" />
  <row Id="11517" PostHistoryTypeId="2" PostId="4845" RevisionGUID="96145725-56b5-428a-a494-873eb0ee5489" CreationDate="2017-03-12T22:33:13.340" UserId="3003" Text="You need to take your width and height and make them into a fraction, then [reduce it](https://en.wikipedia.org/wiki/Irreducible_fraction). To do that, you'll need to find the [greatest common divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the numerator and denominator, and divide them both by that. &#xD;&#xA;&#xD;&#xA;Now take the new fraction you got by dividing both the numerator and denominator by the greatest common divisor and do it again. Repeat this process until the greatest common divisor is 1. At that point you have your irreducible fraction and you can print it.&#xD;&#xA;&#xD;&#xA;Another way to do it is to use [Euclid's Algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm)." ContentLicense="CC BY-SA 3.0" />
  <row Id="11518" PostHistoryTypeId="5" PostId="4845" RevisionGUID="45c8c973-f891-4954-82ee-1e0f65c6c8e0" CreationDate="2017-03-12T23:57:58.030" UserId="3003" Comment="Added an example, fixed formatting of example." Text="You need to take your width and height and make them into a fraction, then [reduce it](https://en.wikipedia.org/wiki/Irreducible_fraction). To do that, you'll need to find the [greatest common divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the numerator and denominator, and divide them both by that. &#xD;&#xA;&#xD;&#xA;Now take the new fraction you got by dividing both the numerator and denominator by the greatest common divisor and do it again. Repeat this process until the greatest common divisor is 1. At that point you have your irreducible fraction and you can print it.&#xD;&#xA;&#xD;&#xA;Another way to do it is to use [Euclid's Algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).&#xD;&#xA;&#xD;&#xA;**Example:**&#xD;&#xA;&#xD;&#xA;Let's look at your top example, 1,000 x 1,200&#xD;&#xA;&#xD;&#xA;    1,000 / 2,000 = ?&#xD;&#xA;&#xD;&#xA;We can see by examination that they both end in &quot;00&quot; so they're both divisible by 100. So start there:&#xD;&#xA;&#xD;&#xA;    1,000 ÷ 100 = 10&#xD;&#xA;    1,200 ÷ 100 = 12&#xD;&#xA;&#xD;&#xA;Next, we see that 10 and 12 are both even, so they're both divisible by 2:&#xD;&#xA;&#xD;&#xA;    10 ÷ 2 = 5&#xD;&#xA;    12 ÷ 2 = 6&#xD;&#xA;&#xD;&#xA;Finally, we see that 5 and 6 share no common factors besides 1. (This is because 5 is prime, so its only factors are 5 and 1. 6 has the factor 2 and 3, as well as 1 and 6.) So we have reached the end. The reduced fraction is 5 / 6.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11519" PostHistoryTypeId="5" PostId="4845" RevisionGUID="d870659d-20b8-42b0-a937-7d827c382dae" CreationDate="2017-03-13T00:07:40.800" UserId="3003" Comment="Added description of Phi" Text="You need to take your width and height and make them into a fraction, then [reduce it](https://en.wikipedia.org/wiki/Irreducible_fraction). To do that, you'll need to find the [greatest common divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the numerator and denominator, and divide them both by that. &#xD;&#xA;&#xD;&#xA;Now take the new fraction you got by dividing both the numerator and denominator by the greatest common divisor and do it again. Repeat this process until the greatest common divisor is 1. At that point you have your irreducible fraction and you can print it.&#xD;&#xA;&#xD;&#xA;Another way to do it is to use [Euclid's Algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).&#xD;&#xA;&#xD;&#xA;**Example:**&#xD;&#xA;&#xD;&#xA;Let's look at your top example, 1,000 x 1,200&#xD;&#xA;&#xD;&#xA;    1,000 / 2,000 = ?&#xD;&#xA;&#xD;&#xA;We can see by examination that they both end in &quot;00&quot; so they're both divisible by 100. So start there:&#xD;&#xA;&#xD;&#xA;    1,000 ÷ 100 = 10&#xD;&#xA;    1,200 ÷ 100 = 12&#xD;&#xA;&#xD;&#xA;Next, we see that 10 and 12 are both even, so they're both divisible by 2:&#xD;&#xA;&#xD;&#xA;    10 ÷ 2 = 5&#xD;&#xA;    12 ÷ 2 = 6&#xD;&#xA;&#xD;&#xA;Finally, we see that 5 and 6 share no common factors besides 1. (This is because 5 is prime, so its only factors are 5 and 1. 6 has the factor 2 and 3, as well as 1 and 6.) So we have reached the end. The reduced fraction is 5 / 6.&#xD;&#xA;&#xD;&#xA;**One More Thing**&#xD;&#xA;&#xD;&#xA;You might also want to be able to detect cases of irrational ratios, such as [the golden ratio](https://en.wikipedia.org/wiki/Golden_ratio), which is quite popular in visual arts. Such a ratio will not be possible to divide into small integers, so checking whether `width / height` is within some small distance of the golden ratio may be sufficient." ContentLicense="CC BY-SA 3.0" />
  <row Id="11520" PostHistoryTypeId="5" PostId="3940" RevisionGUID="939283fc-5582-42d4-996f-c2ceb344260b" CreationDate="2017-03-13T00:22:51.953" UserDisplayName="user246" Comment="spelling corrections" Text="In my simulation I draw a bunch of rectangles with GL_TRIANGLE_STRIP inside of one draw call.&#xD;&#xA;&#xD;&#xA;What will happen if I turn off GL_DEPTH_SORT? If all of the rectangles were stacked on top of themselves in a 2D screenspace sense would they always be in the same order?&#xD;&#xA;&#xD;&#xA;I'm assuming it's just like when you do multiple draw calls (the first one is in back, the last one is in front) how it essentially just draws over what was previously drawn.&#xD;&#xA;&#xD;&#xA;I am using OpenglES 2.0.&#xD;&#xA;&#xD;&#xA;Also what happens with blend modes? Let's say I am doing additive blending, and then multiply the colors by 0.5 making them transparent. Would additive blending work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11521" PostHistoryTypeId="24" PostId="3940" RevisionGUID="939283fc-5582-42d4-996f-c2ceb344260b" CreationDate="2017-03-13T00:22:51.953" Comment="Proposed by 246 approved by 231 edit id of 211" ContentLicense="CC BY-SA 3.0" />
  <row Id="11522" PostHistoryTypeId="4" PostId="4836" RevisionGUID="525646b5-2372-4f73-aa15-84be339f1cd7" CreationDate="2017-03-13T00:24:16.043" UserId="3003" Comment="Fixed the title to be related to the question. Added OpenGL tag" Text="How to quickly draw multiple instances of a texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11523" PostHistoryTypeId="6" PostId="4836" RevisionGUID="525646b5-2372-4f73-aa15-84be339f1cd7" CreationDate="2017-03-13T00:24:16.043" UserId="3003" Comment="Fixed the title to be related to the question. Added OpenGL tag" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11524" PostHistoryTypeId="24" PostId="4836" RevisionGUID="525646b5-2372-4f73-aa15-84be339f1cd7" CreationDate="2017-03-13T00:24:16.043" Comment="Proposed by 3003 approved by 231 edit id of 208" ContentLicense="CC BY-SA 3.0" />
  <row Id="11525" PostHistoryTypeId="5" PostId="4321" RevisionGUID="505e2c10-72f1-4cd6-8b3c-367d7ca9e5e0" CreationDate="2017-03-13T00:24:42.417" UserDisplayName="user246" Comment="spelling corrections" Text="I have some colors in RGB in [0,1] and want to find a way to rate their similarity, as perceived by a human.&#xD;&#xA;&#xD;&#xA;I have two ideas in mind, but I am sure there are other options as well, but am unsure which is best, or if perhaps there is no best, but only trade offs.&#xD;&#xA;&#xD;&#xA;My first idea is to treat the RGB colors as XYZ points and calculate their distance.&#xD;&#xA;&#xD;&#xA;Another idea I have is to treat the RGB values as a histogram and use dot product to get a similarity value between them, where a larger value is better.&#xD;&#xA;&#xD;&#xA;I know however, that not all of the color channels have the same perceived brightness so maybe I ought to weight the color channels differently for both cases?&#xD;&#xA;&#xD;&#xA;I'm also thinking I perhaps would need to do sRGB correction on the color values (such as, sqrt each color channel).&#xD;&#xA;&#xD;&#xA;I also know other color spaces exist, so maybe one of those would be better at giving a similarity value.&#xD;&#xA;&#xD;&#xA;Another challenge to this may be that different displays will display the same color values differently.  Not sure if that's relevant in this case.&#xD;&#xA;&#xD;&#xA;Anyone able to provide some help/direction?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11526" PostHistoryTypeId="24" PostId="4321" RevisionGUID="505e2c10-72f1-4cd6-8b3c-367d7ca9e5e0" CreationDate="2017-03-13T00:24:42.417" Comment="Proposed by 246 approved by 231 edit id of 210" ContentLicense="CC BY-SA 3.0" />
  <row Id="11527" PostHistoryTypeId="5" PostId="4836" RevisionGUID="0f10ce9f-0bf4-4640-bce9-2371afd3c492" CreationDate="2017-03-13T00:36:32.227" UserId="231" Comment="Tidying" Text="I am going to have the following texture drawn hundreds of times all over the screen using a 4 point GL Triangle Strip. I would use GL's dots except I need to be able to orient the texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The color does not really matter as that will change every so often.&#xD;&#xA;&#xD;&#xA;Technically this is not the only image. Occasionally the thing will switch to being just a dot texture. I am not sure how I will be implementing that quite yet however. Worst case scenario I will pass two textures into the shader.&#xD;&#xA;&#xD;&#xA;I need the drawing of this texture to be done as efficiently as humanly possible so I need to know if there is anything I can do to make sure that this does not cause OpenGL any hiccups. If there is any good way to initialize the texture that will hold this, pass it in, or sample it please let me know.&#xD;&#xA;&#xD;&#xA;I am also not sure what resolution I want this shape to be drawn at. I don't know what the relationship between texture sampling cost and resolution is. Any suggestions?&#xD;&#xA;&#xD;&#xA;I considered drawing the shape inside of a fragment shader but my hunch is that it will be more expensive. But I shall see.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/35Hk6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11528" PostHistoryTypeId="5" PostId="4845" RevisionGUID="42cadeb8-4ae8-4df6-aad4-7d6e9f329c7e" CreationDate="2017-03-13T00:44:50.290" UserId="231" Comment="Numerical typo" Text="You need to take your width and height and make them into a fraction, then [reduce it](https://en.wikipedia.org/wiki/Irreducible_fraction). To do that, you'll need to find the [greatest common divisor](https://en.wikipedia.org/wiki/Greatest_common_divisor) of the numerator and denominator, and divide them both by that. &#xD;&#xA;&#xD;&#xA;Now take the new fraction you got by dividing both the numerator and denominator by the greatest common divisor and do it again. Repeat this process until the greatest common divisor is 1. At that point you have your irreducible fraction and you can print it.&#xD;&#xA;&#xD;&#xA;Another way to do it is to use [Euclid's Algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm).&#xD;&#xA;&#xD;&#xA;**Example:**&#xD;&#xA;&#xD;&#xA;Let's look at your top example, 1,000 x 1,200&#xD;&#xA;&#xD;&#xA;    1,000 / 1,200 = ?&#xD;&#xA;&#xD;&#xA;We can see by examination that they both end in &quot;00&quot; so they're both divisible by 100. So start there:&#xD;&#xA;&#xD;&#xA;    1,000 ÷ 100 = 10&#xD;&#xA;    1,200 ÷ 100 = 12&#xD;&#xA;&#xD;&#xA;Next, we see that 10 and 12 are both even, so they're both divisible by 2:&#xD;&#xA;&#xD;&#xA;    10 ÷ 2 = 5&#xD;&#xA;    12 ÷ 2 = 6&#xD;&#xA;&#xD;&#xA;Finally, we see that 5 and 6 share no common factors besides 1. (This is because 5 is prime, so its only factors are 5 and 1. 6 has the factor 2 and 3, as well as 1 and 6.) So we have reached the end. The reduced fraction is 5 / 6.&#xD;&#xA;&#xD;&#xA;**One More Thing**&#xD;&#xA;&#xD;&#xA;You might also want to be able to detect cases of irrational ratios, such as [the golden ratio](https://en.wikipedia.org/wiki/Golden_ratio), which is quite popular in visual arts. Such a ratio will not be possible to divide into small integers, so checking whether `width / height` is within some small distance of the golden ratio may be sufficient." ContentLicense="CC BY-SA 3.0" />
  <row Id="11529" PostHistoryTypeId="5" PostId="4792" RevisionGUID="9c721a03-07d6-4907-9a62-03feeb113923" CreationDate="2017-03-13T00:56:06.863" UserId="231" Comment="Remove &quot;Thank you!&quot;" Text="I've got my path tracer working great for a single light, but I'm having trouble coming up with a solution for scenes with multiple lights. My first thought was to just send a ray to each light and sum up all the contributions. That worked fine, but it was very slow, especially for many lights. I tried researching techniques for working around this, but I found very little. I did find that some renderers weight each light and then pick one based on how much light they might contribute, but I couldn't find any detailed process of how that's actually done.&#xD;&#xA;&#xD;&#xA;So my question is, could someone give me an overview of how this might be accomplished, or point me to a resource that goes over multiple lights? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11530" PostHistoryTypeId="2" PostId="4846" RevisionGUID="77b7c821-5a9a-4c25-b77f-d77745c7a510" CreationDate="2017-03-13T02:41:03.990" UserId="6227" Text="Yes, it is possible.  Remember that a shift in space is equivalent to a linear-phase multiplication in frequency.  A rotation can be accomplished by a shearing operation in one direction followed by a shearing operation in the perpendicular direction followed by a final shear in the original direction (Alan Paeth, ``A Fast Algorithm for General Raster Rotation,'' Proceedings of Graphics Interface 1986.  Larkin et al. have shown how to take this concept and turn it into 1D FFTs multiplied by linear-phase terms, another set of perpendicular 1D FFTs followed by linear-phase multiplication, followed by a final set of 1D FFTs, etc., in the original direction (&quot;Fast Fourier method for the accurate rotation of sampled images&quot;, Optic Communications, 1997).  &#xD;&#xA;&#xD;&#xA;Alternately, you can definitely rotate the Fourier matrix to accomplish rotation.  But you have to keep in mind that the rotation must be around the origin in DFT space.  Since the DFT is periodic, you have to circularly shift the array to the center, rotate around that, and then shift back.  Even then it induces a rotation of the image around the origin (upper left corner), accounting for the fact that the image itself is now treated by the DFT as if it is periodic." ContentLicense="CC BY-SA 3.0" />
  <row Id="11531" PostHistoryTypeId="2" PostId="4847" RevisionGUID="16cf52e9-b0fa-4cbb-a7c4-6b1adeed17c4" CreationDate="2017-03-13T10:39:27.830" UserId="6041" Text="For rendering an indoor scene where light source is skylight coming in through&#xD;&#xA;the window opening, one can consider the window polyline as the light &#xD;&#xA;source, with the sky distribution, in direct lighting calculation. And sample&#xD;&#xA;the window area(or solid angle).&#xD;&#xA;&#xD;&#xA;It works as long as it's just an opening. Once a glazing is introduced I cannot figure out how to do direct lighting(in a path tracer) correctly. Shadow rays either are transmitted or reflected. I guess the transmitted ray needs to be traced again but this is not easy I suppose(as the the Brdf.SampleDirection method returns only direction), considering also that it might be a double &#xD;&#xA;glazing which inter-reflection can happen too. &#xD;&#xA;&#xD;&#xA;Does any one have any suggestion or experience on this?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11532" PostHistoryTypeId="1" PostId="4847" RevisionGUID="16cf52e9-b0fa-4cbb-a7c4-6b1adeed17c4" CreationDate="2017-03-13T10:39:27.830" UserId="6041" Text="How to send shadow rays to window light source with galzing" ContentLicense="CC BY-SA 3.0" />
  <row Id="11533" PostHistoryTypeId="3" PostId="4847" RevisionGUID="16cf52e9-b0fa-4cbb-a7c4-6b1adeed17c4" CreationDate="2017-03-13T10:39:27.830" UserId="6041" Text="|raytracing|lighting|pathtracing|shadow|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11534" PostHistoryTypeId="4" PostId="4847" RevisionGUID="41f9ad8d-2a65-4c67-8945-43e22c86bfe2" CreationDate="2017-03-13T10:51:55.543" UserId="209" Comment="Fixed minor typo in title" Text="How to send shadow rays to window light source with glazing" ContentLicense="CC BY-SA 3.0" />
  <row Id="11535" PostHistoryTypeId="2" PostId="4848" RevisionGUID="4daa6ebd-2060-4616-837a-4098dfe47800" CreationDate="2017-03-14T06:01:41.660" UserId="5770" Text="After taking a look at the [Mobius strip](https://www.wikiwand.com/en/M%C3%B6bius_strip#/Geometry_and_topology), I noticed its equation is really simple and tried to add it into my Raytracer.&#xD;&#xA;&#xD;&#xA;I tried a &quot;naive&quot; way by simply generating `N` triangles attached to each other to obtain the desired shape. While this approach works, the result it not really pretty:&#xD;&#xA;&#xD;&#xA;[![IMG][1]][1]&#xD;&#xA;&#xD;&#xA;`By the way I probably have an issue with my normals but I don't know where it comes from.`&#xD;&#xA;&#xD;&#xA;I tried it with PovRay and the result was astonishing. Perfectly smooth strip made in a far far FAR smaller time than mine. I'm pretty sure Povray is **well** optimized but I also think it won't generate triangles like I did.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In case that might help, here is the actual code used (C++) :&#xD;&#xA;&#xD;&#xA;    float step = .1f;&#xD;&#xA;    float halW = 0.5f;&#xD;&#xA;&#xD;&#xA;    _facets.clear();&#xD;&#xA;&#xD;&#xA;    auto lambda = [this] (float v, float t) {&#xD;&#xA;      Vec_t p;&#xD;&#xA;&#xD;&#xA;      float cdv = Tools::Cos(2 * v);&#xD;&#xA;      float sdv = Tools::Sin(2 * v);&#xD;&#xA;      float ctv = Tools::Cos(v);&#xD;&#xA;      float stv = Tools::Sin(v);&#xD;&#xA;&#xD;&#xA;      float c = 2 + t * ctv;&#xD;&#xA;&#xD;&#xA;      p.x = c * cdv;&#xD;&#xA;      p.z = c * sdv;&#xD;&#xA;      p.y = t * stv;&#xD;&#xA;&#xD;&#xA;      return p;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (float v = 0.f; v &lt; Globals::PI; v += step)&#xD;&#xA;    {&#xD;&#xA;      if (v &gt; Globals::PI)&#xD;&#xA;        v = Globals::PI;&#xD;&#xA;&#xD;&#xA;      for (float t = -halW; t &lt; halW; t += step)&#xD;&#xA;      {&#xD;&#xA;        if (t &gt; halW)&#xD;&#xA;          t = halW;&#xD;&#xA;&#xD;&#xA;        Vec3 p1 = lambda(v, t);&#xD;&#xA;        Vec3 p2 = lambda(v + step, t);&#xD;&#xA;        Vec3 p3 = lambda(v, t + step);&#xD;&#xA;        Vec3 p4 = lambda(v + step, t + step);&#xD;&#xA;        _facets.emplace_back(p1, p2, p3);&#xD;&#xA;        _facets.emplace_back(p3, p2, p4);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;How can I handle parametric surfaces like [this one](https://www.wikiwand.com/en/M%C3%B6bius_strip#/Geometry_and_topology) in raytracing?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1w5Kx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DN5p4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11536" PostHistoryTypeId="1" PostId="4848" RevisionGUID="4daa6ebd-2060-4616-837a-4098dfe47800" CreationDate="2017-03-14T06:01:41.660" UserId="5770" Text="How to handle a parametric equation in raytracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11537" PostHistoryTypeId="3" PostId="4848" RevisionGUID="4daa6ebd-2060-4616-837a-4098dfe47800" CreationDate="2017-03-14T06:01:41.660" UserId="5770" Text="|raytracing|rendering|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11538" PostHistoryTypeId="2" PostId="4849" RevisionGUID="deee94bd-de3d-4662-a6f1-9e5eb8536c9e" CreationDate="2017-03-14T09:44:21.260" UserId="209" Text="*Many* years ago I worked on a ray tracer that handled parametric surfaces, so this is unlikely to be state of the art, but, IIRC, I used a combination of interval arithmetic with (binary?) subdivision and Newton-Rhapson.&#xD;&#xA;&#xD;&#xA;The interval arithmetic + subdivision constructed (conservative) bounding boxes which could be used for intersection rejection. I think I *may* also have used interval arithmetic on the 1st derivative to help determine when it was safe to launch into Newton-Rhapson. Typically the Newton steps converged very rapidly. &#xD;&#xA;&#xD;&#xA;You can also pre-dice your parametric surfaces and put them into an acceleration structure (Voxel grid/BVH) to speed up the process.&#xD;&#xA;&#xD;&#xA;This work was based on/inspired by Daniel Toth's 1985 paper [&quot;On Ray Tracing Parametric Surfaces&quot;][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p171-toth.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11539" PostHistoryTypeId="2" PostId="4850" RevisionGUID="61352033-4996-41b4-970c-23c54570de24" CreationDate="2017-03-14T09:47:48.797" UserId="137" Text="In general when doing parametric in a ray tracer you need a solution for &#xD;&#xA;&#xD;&#xA;$\begin{cases}  P = v * t + C \\&#xD;&#xA; P = f(u,v)&#xD;&#xA;\end{cases}$&#xD;&#xA;&#xD;&#xA;for the lowest $t$ where $f(u,v)$ is your parametric function $C$ is the camera position and $v$ is the ray direction.&#xD;&#xA;&#xD;&#xA;There are a few general ways, for example if you can tell whether 2 points are on the same side or not you can take 2 points on the ray on opposite sides and binary search until you have the depth. You can find the first pair by marching along the ray." ContentLicense="CC BY-SA 3.0" />
  <row Id="11540" PostHistoryTypeId="2" PostId="4851" RevisionGUID="52a3fba3-6fe9-4876-a046-eec4d28e64cf" CreationDate="2017-03-14T09:52:59.677" UserId="6230" Text="I don't completely understand the last part of the MVP matrix (projection).&#xD;&#xA;&#xD;&#xA;In orthographic projection we simply scale the view volume into the default view volume (+-1 on all axis).&#xD;&#xA;&#xD;&#xA;In perspective projection we scale and skew the view frustrum into the default view volume (+-1 on all axis) which causes non-uniform foreshortening giving the appearance of perspective that we're used to.&#xD;&#xA;&#xD;&#xA;So now, regardless of which type of projection we have used, we have the default viewing volume (+-1 on all axis). So how do we get from this cube to an image on the screen?&#xD;&#xA;&#xD;&#xA;I understand that we need this volume for the z-buffer. But how are points (anywhere in this volume) finally transformed from 3d to 2d and is it the same procedure for orthographic projection as it is for perspective projection?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11541" PostHistoryTypeId="1" PostId="4851" RevisionGUID="52a3fba3-6fe9-4876-a046-eec4d28e64cf" CreationDate="2017-03-14T09:52:59.677" UserId="6230" Text="Getting from the default view volume to an image on the screen" ContentLicense="CC BY-SA 3.0" />
  <row Id="11542" PostHistoryTypeId="3" PostId="4851" RevisionGUID="52a3fba3-6fe9-4876-a046-eec4d28e64cf" CreationDate="2017-03-14T09:52:59.677" UserId="6230" Text="|transformations|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11543" PostHistoryTypeId="2" PostId="4852" RevisionGUID="e9770dad-3980-44c9-9ab7-9cba255c521c" CreationDate="2017-03-14T10:01:29.640" UserId="137" Text="The mapping from NDC space to screen space is orthographic.&#xD;&#xA;&#xD;&#xA;The x is mapped linearly from [-1, 1] to [0,viewport width], same with y and viewport height.&#xD;&#xA;&#xD;&#xA;This mapping happens after the projection matrix has been applied and the divide by w happened. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11544" PostHistoryTypeId="33" PostId="4842" RevisionGUID="37817608-86ae-4d7d-a318-e390cfc0e540" CreationDate="2017-03-14T10:53:40.853" UserId="5513" Comment="26" />
  <row Id="11545" PostHistoryTypeId="2" PostId="4853" RevisionGUID="5dd245cc-68dc-4d90-9e65-840f5e72a495" CreationDate="2017-03-14T14:23:55.450" UserId="6029" Text="I'm learning Ray Tracing using this MIT tutorial:&#xD;&#xA;&#xD;&#xA;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/assignments/MIT6_837F12_assn4.pdf&#xD;&#xA;&#xD;&#xA;I've heard Ray Tracing only in the context of lightning. I.e. I understand that ray casting is used to light an object that has been already drawn. However, I've also seen ray casting in the context of just drawing the picture (not lightning). So which one are rays about?&#xD;&#xA;&#xD;&#xA;What's the concept of &quot;ray&quot; really?&#xD;&#xA;&#xD;&#xA;E.g. in that tutorial one draws the picture like:&#xD;&#xA;&#xD;&#xA;    image.SetPixel( x, y, pixelColor );&#xD;&#xA;&#xD;&#xA;where `pixelColor` has been acquired from the Ray Caster. But I read this to mean that `pixelColor` already has lightning information." ContentLicense="CC BY-SA 3.0" />
  <row Id="11546" PostHistoryTypeId="1" PostId="4853" RevisionGUID="5dd245cc-68dc-4d90-9e65-840f5e72a495" CreationDate="2017-03-14T14:23:55.450" UserId="6029" Text="What's the concept of &quot;Ray&quot; really?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11547" PostHistoryTypeId="3" PostId="4853" RevisionGUID="5dd245cc-68dc-4d90-9e65-840f5e72a495" CreationDate="2017-03-14T14:23:55.450" UserId="6029" Text="|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11548" PostHistoryTypeId="2" PostId="4854" RevisionGUID="a5be1162-15cc-41ab-892f-c353235c65a8" CreationDate="2017-03-14T15:08:38.553" UserId="2041" Text="A *ray* is just a semi-infinite line, and *casting* the ray finds intersections between the ray and an object in the scene. It doesn't just tell you the position in space that the ray intersected the object: it also tells you the texture co-ordinates of that point on the object, the surface normal and tangent, and (depending on the algorithm you use) filter widths.&#xD;&#xA;&#xD;&#xA;So in a ray-tracer, there are different kinds of rays. *Primary rays* and reflection and refraction rays use their intersection to run a shader and compute a fragment colour. They also fire *shadow rays* at lights, which don't compute a colour but just tell you whether any object is shadowing the light.&#xD;&#xA;&#xD;&#xA;So rays are about finding the objects which are in the scene, and shading those objects to make an image. They're also about finding the reflections and refractions on shiny objects. They are used to draw shadows. They're also used for more advanced effects like ambient occlusion and photon tracing.&#xD;&#xA;&#xD;&#xA;This is one of the main conceptual advantages of ray-tracing over scanline rasterisation: instead of having to use different techniques for computing reflections, shadows, and all those other effects, the same core ray-cast algorithm can be used recursively to compute the whole image." ContentLicense="CC BY-SA 3.0" />
  <row Id="11549" PostHistoryTypeId="2" PostId="4855" RevisionGUID="a21f0c1c-73f2-4471-adef-e3207674468f" CreationDate="2017-03-14T15:17:08.503" UserId="2041" Text="Most renderers allow you to set a flag on an object to make shadow rays ignore it (so it won't cast shadows). You could set this flag on your glazing.&#xD;&#xA;&#xD;&#xA;That said, it's not unusual to make it so that refraction is disabled on shadow rays: that is, if they would be transmitted by an object, a child ray is traced in the same direction, ignoring any refraction that would be caused by the ior of the material. Although this gives wrong results for objects such as crystal balls, you need photon mapping or similar to get good results for that situation anyway. Just tracing a child ray is an easy way of making objects like stained-glass windows give simple coloured shadows." ContentLicense="CC BY-SA 3.0" />
  <row Id="11550" PostHistoryTypeId="2" PostId="4856" RevisionGUID="c9b37c0d-5ff9-430a-85b4-5f9d308108ad" CreationDate="2017-03-14T15:21:24.343" UserId="2707" Text="You shouldn't solve for $\cos^{-1}(\theta)$.&#xD;&#xA;&#xD;&#xA;The ambient component is as follows (we are assuming the ambient light is white):&#xD;&#xA;$$ambient\ color = (ambient\ light\ color)(ambient\ intensity)(diffuse\ color) = (1,1,1)(0.1)(0.6,0.7,0.8) = (0.06,0.07,0.08)$$&#xD;&#xA;&#xD;&#xA;The diffuse component is as follows:&#xD;&#xA;$$diffuse\ color = (light\ color)(light\ intensity)(diffuse\ color)(\cos(\theta)) = (1,1,1)(1)(0.6,0.7,0.8)(0.8) = (0.48,0.56,0.64)$$&#xD;&#xA;&#xD;&#xA;Now we just need to add them up:&#xD;&#xA;$$final\ intensity = (diffuse\ color) + (ambient\ color) = (0.06,0.07,0.08) + (0.48,0.56,0.64) = (0.54,0.63,0.72)$$&#xD;&#xA;&#xD;&#xA;For more information, here's a pretty decent [summary](https://learnopengl.com/#!Lighting/Basic-Lighting) of various lighting calculations." ContentLicense="CC BY-SA 3.0" />
  <row Id="11551" PostHistoryTypeId="5" PostId="4853" RevisionGUID="65858288-b2f9-44e6-affc-ccc3d8989dd0" CreationDate="2017-03-14T16:49:15.590" UserId="48" Comment="fix typo; add more tags" Text="I'm learning Ray Tracing using this MIT tutorial:&#xD;&#xA;&#xD;&#xA;https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/assignments/MIT6_837F12_assn4.pdf&#xD;&#xA;&#xD;&#xA;I've heard Ray Tracing only in the context of lighting. I.e. I understand that ray casting is used to light an object that has been already drawn. However, I've also seen ray casting in the context of just drawing the picture (not lighting). So which one are rays about?&#xD;&#xA;&#xD;&#xA;What's the concept of &quot;ray&quot; really?&#xD;&#xA;&#xD;&#xA;E.g. in that tutorial one draws the picture like:&#xD;&#xA;&#xD;&#xA;    image.SetPixel( x, y, pixelColor );&#xD;&#xA;&#xD;&#xA;where `pixelColor` has been acquired from the Ray Caster. But I read this to mean that `pixelColor` already has lighting information." ContentLicense="CC BY-SA 3.0" />
  <row Id="11552" PostHistoryTypeId="6" PostId="4853" RevisionGUID="65858288-b2f9-44e6-affc-ccc3d8989dd0" CreationDate="2017-03-14T16:49:15.590" UserId="48" Comment="fix typo; add more tags" Text="|raytracing|lighting|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11553" PostHistoryTypeId="5" PostId="4848" RevisionGUID="37ba3f5d-5f98-4ccb-802f-f5e490bc37f4" CreationDate="2017-03-14T16:50:50.170" UserId="48" Comment="formatting" Text="After taking a look at the [Mobius strip](https://www.wikiwand.com/en/M%C3%B6bius_strip#/Geometry_and_topology), I noticed its equation is really simple and tried to add it into my Raytracer.&#xD;&#xA;&#xD;&#xA;I tried a &quot;naive&quot; way by simply generating `N` triangles attached to each other to obtain the desired shape. While this approach works, the result it not really pretty:&#xD;&#xA;&#xD;&#xA;[![IMG][1]][1]&#xD;&#xA;&#xD;&#xA;(By the way I probably have an issue with my normals but I don't know where it comes from.)&#xD;&#xA;&#xD;&#xA;I tried it with PovRay and the result was astonishing. Perfectly smooth strip made in a far far FAR smaller time than mine. I'm pretty sure Povray is **well** optimized but I also think it won't generate triangles like I did.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In case that might help, here is the actual code used (C++) :&#xD;&#xA;&#xD;&#xA;    float step = .1f;&#xD;&#xA;    float halW = 0.5f;&#xD;&#xA;&#xD;&#xA;    _facets.clear();&#xD;&#xA;&#xD;&#xA;    auto lambda = [this] (float v, float t) {&#xD;&#xA;      Vec_t p;&#xD;&#xA;&#xD;&#xA;      float cdv = Tools::Cos(2 * v);&#xD;&#xA;      float sdv = Tools::Sin(2 * v);&#xD;&#xA;      float ctv = Tools::Cos(v);&#xD;&#xA;      float stv = Tools::Sin(v);&#xD;&#xA;&#xD;&#xA;      float c = 2 + t * ctv;&#xD;&#xA;&#xD;&#xA;      p.x = c * cdv;&#xD;&#xA;      p.z = c * sdv;&#xD;&#xA;      p.y = t * stv;&#xD;&#xA;&#xD;&#xA;      return p;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (float v = 0.f; v &lt; Globals::PI; v += step)&#xD;&#xA;    {&#xD;&#xA;      if (v &gt; Globals::PI)&#xD;&#xA;        v = Globals::PI;&#xD;&#xA;&#xD;&#xA;      for (float t = -halW; t &lt; halW; t += step)&#xD;&#xA;      {&#xD;&#xA;        if (t &gt; halW)&#xD;&#xA;          t = halW;&#xD;&#xA;&#xD;&#xA;        Vec3 p1 = lambda(v, t);&#xD;&#xA;        Vec3 p2 = lambda(v + step, t);&#xD;&#xA;        Vec3 p3 = lambda(v, t + step);&#xD;&#xA;        Vec3 p4 = lambda(v + step, t + step);&#xD;&#xA;        _facets.emplace_back(p1, p2, p3);&#xD;&#xA;        _facets.emplace_back(p3, p2, p4);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;How can I handle parametric surfaces like [this one](https://www.wikiwand.com/en/M%C3%B6bius_strip#/Geometry_and_topology) in raytracing?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1w5Kx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DN5p4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11556" PostHistoryTypeId="5" PostId="4840" RevisionGUID="b5897c69-b815-4a53-bcd7-33f2ed184ca0" CreationDate="2017-03-14T20:10:26.087" UserId="2707" Comment="Fixed some issues with average normal calculation. Added technique recommended by Nathan Reed." Text="With flat shading, the normal is the same across the whole triangle (or quad or whatever). There are some assumptions that were made here and two approaches. The latter approach will probably be best for most basic problems (although more work). We don't have the winding order, so we need to calculate the normal based on the vertices.&#xD;&#xA;&#xD;&#xA;# Average normal approach&#xD;&#xA;The assumption is that each vertex contributes the same amount of weight towards the triangle normal.&#xD;&#xA;&#xD;&#xA;We first calculate the average of each:&#xD;&#xA;$$normal = \frac{normalize(0,0,1) + normalize(1,1,0) + normalize(-1,-1,1)}{3} \approx \frac{(0,0,1)+(0.7,0.7,0)+(-0.58,-0.58,0.58)}{3} \approx (0.12,0.12,1.58)$$&#xD;&#xA;$$normalize(0.12,0.12,1.58) \approx (0.076,0.076,0.994)$$&#xD;&#xA;&#xD;&#xA;For Lambert shading:&#xD;&#xA;$$cos(\theta) = normalize(0,3,4) \cdot (0.76,0.76, 0.994) \approx 0.84 $$&#xD;&#xA;&#xD;&#xA;# Geometric approach (recommended for this problem)&#xD;&#xA;Another assumption Nathan Reed suggested was that each vertex normal holds equal weight, which would make sense in more common use cases. For this, we will probably want to find the face normals in both winding directions to compare this value to:&#xD;&#xA;&#xD;&#xA;## Winding order 1&#xD;&#xA;$$normal1 = normalize((A-B) \times (A-O)) \approx (0.29,0.43,-0.85)$$&#xD;&#xA;&#xD;&#xA;## Winding order 2&#xD;&#xA;$$normal2 = normalize((A-O) \times (A-B)) \approx (-0.29,-0.43,0.85)$$&#xD;&#xA;&#xD;&#xA;Now, we can take the dot product between these two vectors and the one we computed above. Whichever one is greater or equal to 0:&#xD;&#xA;$$geometric\ normal1 = normal \cdot normal1 \approx -0.79$$&#xD;&#xA;$$geometric\ normal2 = normal \cdot normal2 \approx 0.79$$&#xD;&#xA;&#xD;&#xA;So then,&#xD;&#xA;$$normal = geometric\ normal2$$&#xD;&#xA;&#xD;&#xA;For Lambert shading:&#xD;&#xA;$$cos(\theta) = normalize(0,3,4) \cdot (-0.29,-0.43,0.85) \approx 0.42 $$" ContentLicense="CC BY-SA 3.0" />
  <row Id="11557" PostHistoryTypeId="5" PostId="4840" RevisionGUID="fc95784e-3906-4233-9738-a66e7331bcca" CreationDate="2017-03-14T20:27:39.237" UserId="2707" Comment="Fixed some small issues" Text="With flat shading, the normal is the same across the whole triangle (or quad or whatever). There are some assumptions that were made here and two approaches. The latter approach will probably be best for most basic problems (although more work). We don't have the winding order, so we need to calculate the normal based on the vertices.&#xD;&#xA;&#xD;&#xA;# Average normal approach&#xD;&#xA;The assumption is that each vertex contributes the same amount of weight towards the triangle normal.&#xD;&#xA;&#xD;&#xA;We first calculate the average of each:&#xD;&#xA;$$normal = normalize(0,0,1) + normalize(1,1,0) + normalize(-1,-1,1) \approx \frac{(0,0,1)+(0.7,0.7,0)+(-0.58,-0.58,0.58)}{3} \approx (0.04,0.04,0.53)$$&#xD;&#xA;$$normalize(0.04,0.04,0.53) \approx (0.076,0.076,0.994)$$&#xD;&#xA;&#xD;&#xA;For Lambert shading:&#xD;&#xA;$$cos(\theta) = normalize(0,3,4) \cdot (0.76,0.76, 0.994) \approx 0.84 $$&#xD;&#xA;&#xD;&#xA;# Geometric approach (recommended for this problem)&#xD;&#xA;Another assumption Nathan Reed suggested was that each vertex normal holds equal weight, which would make sense in more common use cases. For this, we will want to find the face normals in both winding directions to compare this value to:&#xD;&#xA;&#xD;&#xA;## Winding order 1&#xD;&#xA;$$normal1 = normalize((B-A) \times (O-A)) \approx (0.29,0.43,-0.85)$$&#xD;&#xA;&#xD;&#xA;## Winding order 2&#xD;&#xA;$$normal2 = normalize((O-A) \times (B-A)) \approx (-0.29,-0.43,0.85)$$&#xD;&#xA;&#xD;&#xA;Now, we can take the dot product between these two vectors and the one we computed above. Whichever one is greater or equal to 0:&#xD;&#xA;$$geometric\ normal1 = normal \cdot normal1 \approx -0.79$$&#xD;&#xA;$$geometric\ normal2 = normal \cdot normal2 \approx 0.79$$&#xD;&#xA;&#xD;&#xA;So then,&#xD;&#xA;$$normal = geometric\ normal2$$&#xD;&#xA;&#xD;&#xA;For Lambert shading:&#xD;&#xA;$$cos(\theta) = normalize(0,3,4) \cdot (-0.29,-0.43,0.85) \approx 0.42 $$" ContentLicense="CC BY-SA 3.0" />
  <row Id="11558" PostHistoryTypeId="2" PostId="4857" RevisionGUID="4413d0e5-ea57-4155-bc31-1af790afd909" CreationDate="2017-03-15T10:33:48.220" UserId="4646" Text="I'm wondering which properties of 3D objects are to be considered and used for distance discrimination in VR, for example, and why.&#xD;&#xA;For example the level of detail, colour (?)... " ContentLicense="CC BY-SA 3.0" />
  <row Id="11559" PostHistoryTypeId="1" PostId="4857" RevisionGUID="4413d0e5-ea57-4155-bc31-1af790afd909" CreationDate="2017-03-15T10:33:48.220" UserId="4646" Text="What 3D object properties are to be considered for distance metrics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11560" PostHistoryTypeId="3" PostId="4857" RevisionGUID="4413d0e5-ea57-4155-bc31-1af790afd909" CreationDate="2017-03-15T10:33:48.220" UserId="4646" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11561" PostHistoryTypeId="2" PostId="4858" RevisionGUID="c1f4467c-50bd-4802-9deb-03de1849674a" CreationDate="2017-03-15T11:14:17.397" UserId="4646" Text="I'm wondering what metrics I could use to decide upon the visibility of a 3D object in VR or other 3D applications and what advantages each has." ContentLicense="CC BY-SA 3.0" />
  <row Id="11562" PostHistoryTypeId="1" PostId="4858" RevisionGUID="c1f4467c-50bd-4802-9deb-03de1849674a" CreationDate="2017-03-15T11:14:17.397" UserId="4646" Text="What metrics are used for deciding if a 3D object is visible?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11563" PostHistoryTypeId="3" PostId="4858" RevisionGUID="c1f4467c-50bd-4802-9deb-03de1849674a" CreationDate="2017-03-15T11:14:17.397" UserId="4646" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11564" PostHistoryTypeId="2" PostId="4859" RevisionGUID="9969766d-f46b-452f-8a04-edbb410ce0b7" CreationDate="2017-03-15T11:33:40.107" UserId="137" Text="Visibility for culling (or passing to the render pipeline) is very sensitive to false negatives. False positives are not a big deal because when rendering the Z buffer will take care of that.&#xD;&#xA;&#xD;&#xA;This means that one very simple metric is simply assuming that it's always visible. If any other metric gives too much overhead than simply processing the object requires then this is a good fallback. For example in a redering api with command buffers rebuilding the command buffer would be too expensive compared to the processing required to render a single object to warrant it.&#xD;&#xA;&#xD;&#xA;The next option is to see if the object is in front or behind the camera, This can be done with a dot product with the view vector and the forward most point of the bounding volume of the object. If it's negative then the object is behind the camera and you can skip it.&#xD;&#xA;&#xD;&#xA;The next is using the view pyramid. From the camera you extrude the frustum and do a collision check between it and the object. If it collides then the object is visible. Instead of 1 plane you now check against 4 and the object must pass All 4 to be considered visible.&#xD;&#xA;&#xD;&#xA;Next you can take into account when the object is fully occluded by another object. This can be done by various methods. With static geometry you can partition the world and say for each section which other sections you can see from it. You can also ask the GPU to do occlusion queries which basically means &quot;did any fragments of these render commands pass the depth test&quot;. But getting the information back from the GPU typically has a decently long latency, by which time the camera may have moved." ContentLicense="CC BY-SA 3.0" />
  <row Id="11571" PostHistoryTypeId="2" PostId="4862" RevisionGUID="af0b0989-6dd8-4013-8565-df8af1334478" CreationDate="2017-03-15T17:07:46.003" UserId="6029" Text="So I'm reading some Ray-Sphere interaction codes and in one there was &quot;texCoord&quot;, which I think means &quot;texel coordinate&quot;. However, what does this refer to &quot;visually&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11572" PostHistoryTypeId="1" PostId="4862" RevisionGUID="af0b0989-6dd8-4013-8565-df8af1334478" CreationDate="2017-03-15T17:07:46.003" UserId="6029" Text="What's a &quot;texel coordinate&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11573" PostHistoryTypeId="3" PostId="4862" RevisionGUID="af0b0989-6dd8-4013-8565-df8af1334478" CreationDate="2017-03-15T17:07:46.003" UserId="6029" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11574" PostHistoryTypeId="2" PostId="4863" RevisionGUID="f71d989b-0287-4c3a-9c90-4f51c48562f2" CreationDate="2017-03-15T17:10:12.380" UserId="137" Text="It stands for texture coordinate.&#xD;&#xA;&#xD;&#xA;It's a 2D value between 0 and 1 to indicate where in the texture to sample from for the color.&#xD;&#xA;&#xD;&#xA;For sphere that means creating a map projection to map the curved surface to the flat plane, a simple option is to use the lat/long remapped to 0-1 though that gives awful distortion at the poles." ContentLicense="CC BY-SA 3.0" />
  <row Id="11585" PostHistoryTypeId="2" PostId="4866" RevisionGUID="b37eb691-f193-49d7-923d-5aabb0696eef" CreationDate="2017-03-16T09:44:48.307" UserId="5513" Text="Flat Shading:&#xD;&#xA;&#xD;&#xA;I = Ia x Ka + Fatt x Il x (Kd x (N x L))&#xD;&#xA;&#xD;&#xA;Final intensity = ambient reflection x ambient reflection coefficient + (attenuation x incident light intensity x (diffusive reflection coefficient x (surface normal x Light intensity))&#xD;&#xA;&#xD;&#xA;He told me that because ambient reflection coefficient and attenuation are not given, I can forget about it. Also specular light contribution need not be considered.&#xD;&#xA;&#xD;&#xA;The surface normal is:&#xD;&#xA;A = (0, 2, 1) B = (3, 0, 1) O = (0, 0, 0)&#xD;&#xA;&#xD;&#xA;U = A - O = (0, 2, 1) &#xD;&#xA;V = B - O = (3, 0, 1)&#xD;&#xA;&#xD;&#xA;Surface normal = U x V (cross-product) = (2, 3, -6)&#xD;&#xA;&#xD;&#xA;I = 0.1 + (1, 1, 1) x ((0.6, 0.7, 0.8) x ((2, 3, -6) x (0, 3, 4)))&#xD;&#xA;&#xD;&#xA;I = 0.1 + (1, 1, 1) x ((0.6, 0.7, 0.8) x (0, 9, -2.4))&#xD;&#xA;&#xD;&#xA;I = 0.1 + (1, 1, 1) x (0, 6.3, -1.92)&#xD;&#xA;&#xD;&#xA;I = (0.1, 6.4, -1.82) = RGB intensity values&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11586" PostHistoryTypeId="6" PostId="4698" RevisionGUID="2579545e-b9cd-47da-9713-9b85a1d8b860" CreationDate="2017-03-16T13:22:15.900" UserId="2479" Comment="added tags" Text="|raytracing|computational-geometry|normal-mapping|height-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11587" PostHistoryTypeId="24" PostId="4698" RevisionGUID="2579545e-b9cd-47da-9713-9b85a1d8b860" CreationDate="2017-03-16T13:22:15.900" Comment="Proposed by 2479 approved by 2041, 209 edit id of 213" ContentLicense="CC BY-SA 3.0" />
  <row Id="11588" PostHistoryTypeId="2" PostId="4867" RevisionGUID="904be1d6-daa2-4897-91a3-07932fe6d8d9" CreationDate="2017-03-16T15:09:31.147" UserId="5828" Text="I solved it myself. Here is a result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The example is out of this post: [here][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/18HYq.png&#xD;&#xA;  [2]: http://computergraphics.stackexchange.com/questions/4507/finding-the-nearest-neighbor-of-polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="11589" PostHistoryTypeId="5" PostId="405" RevisionGUID="771cfe75-ddcf-4f82-b885-c323c6744f0d" CreationDate="2017-03-16T16:43:40.910" UserId="-1" Comment="replaced http://meta.computergraphics.stackexchange.com/ with https://computergraphics.meta.stackexchange.com/" Text="In my answer about [Affine Transformations](http://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392) I made some little illustrations to help the explanation.&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Ltr0w.png)&#xD;&#xA;&#xD;&#xA;How do you make an upload-able PNG quickly which expresses a geometrical or mathematical idea?&#xD;&#xA;&#xD;&#xA;*This question was contrived to support [my postscript answer]() but is intended to solicit other solutions that may benefit the SE network more generally. But for credibility, an answer must link to a post where this technique has in fact been used, as well as a sufficient &quot;howto&quot; portion if it involves more than something obvious like &quot;Select export from menu&quot;.*&#xD;&#xA;&#xD;&#xA;*There are two meta questions [here](https://computergraphics.meta.stackexchange.com/questions/147/simple-2d-illustrations-question-main-or-meta) and [here](https://computergraphics.meta.stackexchange.com/questions/150/2d-illustrations-question-help-crafting-the-question) concerning how to scope this question in light of the precedences it may set for our site.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="11591" PostHistoryTypeId="33" PostId="4848" RevisionGUID="6212d740-faa4-4576-832b-6fd1028834c6" CreationDate="2017-03-16T16:52:39.953" UserId="5770" Comment="27" />
  <row Id="11592" PostHistoryTypeId="5" PostId="4848" RevisionGUID="f6eb9336-f3db-48b3-a891-6c51f2f65703" CreationDate="2017-03-16T16:59:54.710" UserId="5770" Comment="Better one" Text="After taking a look at the [Mobius strip](https://www.wikiwand.com/en/M%C3%B6bius_strip#/Geometry_and_topology), I noticed its equation is really simple and tried to add it into my Raytracer.&#xD;&#xA;&#xD;&#xA;I tried a &quot;naive&quot; way by simply generating `N` triangles attached to each other to obtain the desired shape. While this approach works, the result it not really pretty:&#xD;&#xA;&#xD;&#xA;[![IMG][1]][1]&#xD;&#xA;&#xD;&#xA;(By the way I probably have an issue with my normals but I don't know where it comes from.)&#xD;&#xA;&#xD;&#xA;I tried it with PovRay and the result was astonishing. Perfectly smooth strip made in a far far FAR smaller time than mine. I'm pretty sure Povray is **well** optimized but I also think it won't generate triangles like I did.&#xD;&#xA;&#xD;&#xA;[![povray][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In case that might help, here is the actual code used (C++) :&#xD;&#xA;&#xD;&#xA;    float step = .1f;&#xD;&#xA;    float halW = 0.5f;&#xD;&#xA;&#xD;&#xA;    _facets.clear();&#xD;&#xA;&#xD;&#xA;    auto lambda = [this] (float v, float t) {&#xD;&#xA;      Vec_t p;&#xD;&#xA;&#xD;&#xA;      float cdv = Tools::Cos(2 * v);&#xD;&#xA;      float sdv = Tools::Sin(2 * v);&#xD;&#xA;      float ctv = Tools::Cos(v);&#xD;&#xA;      float stv = Tools::Sin(v);&#xD;&#xA;&#xD;&#xA;      float c = 2 + t * ctv;&#xD;&#xA;&#xD;&#xA;      p.x = c * cdv;&#xD;&#xA;      p.z = c * sdv;&#xD;&#xA;      p.y = t * stv;&#xD;&#xA;&#xD;&#xA;      return p;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (float v = 0.f; v &lt; Globals::PI; v += step)&#xD;&#xA;    {&#xD;&#xA;      if (v &gt; Globals::PI)&#xD;&#xA;        v = Globals::PI;&#xD;&#xA;&#xD;&#xA;      for (float t = -halW; t &lt; halW; t += step)&#xD;&#xA;      {&#xD;&#xA;        if (t &gt; halW)&#xD;&#xA;          t = halW;&#xD;&#xA;&#xD;&#xA;        Vec3 p1 = lambda(v, t);&#xD;&#xA;        Vec3 p2 = lambda(v + step, t);&#xD;&#xA;        Vec3 p3 = lambda(v, t + step);&#xD;&#xA;        Vec3 p4 = lambda(v + step, t + step);&#xD;&#xA;        _facets.emplace_back(p1, p2, p3);&#xD;&#xA;        _facets.emplace_back(p3, p2, p4);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;How can I handle parametric surfaces like [this one](https://www.wikiwand.com/en/M%C3%B6bius_strip#/Geometry_and_topology) in raytracing?&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;After letting the above algorithm run for about 20 hours, I got a way prettier result (with 3 torsions instead of 1)&#xD;&#xA;&#xD;&#xA;[![Better result][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1w5Kx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DN5p4.png&#xD;&#xA;  [3]: https://cdn.discordapp.com/attachments/148687431728627713/291972504245895178/unknown.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11593" PostHistoryTypeId="5" PostId="4842" RevisionGUID="6387e7b4-cbb9-4727-a81d-d80ffafad5ef" CreationDate="2017-03-16T19:31:26.957" UserId="5513" Comment="added 151 characters in body" Text="Consider a triangular face of three vertices A(0,2,1), B(3,0,1) and the origin, and the normal vectors at the vertices are nA=(0,0,1), nB=(1,1,0) and nO=(-1,-1,1), respectively. The incident light is white and directional in the direction of L=(0,3,4) and the intensity is 1, the background ambient light intensity is 0.1, and the diffuse reflection coefficients for (red, green, blue) are (0.6,0.7,0.8). No specular light contribution need be considered. &#xD;&#xA;&#xD;&#xA;How do I find the (red, green, blue) intensity values at the centre of the face using flat shading?&#xD;&#xA;&#xD;&#xA;Flat Shading:&#xD;&#xA;&#xD;&#xA;I = Ia x Ka + Fatt x Il x (Kd x (N x L))&#xD;&#xA;&#xD;&#xA;Final intensity = ambient reflection x ambient reflection coefficient + (attenuation x incident light intensity x (diffusive reflection coefficient x (surface normal x Light intensity))&#xD;&#xA;&#xD;&#xA;My lecturer told me that because ambient reflection coefficient and attenuation are not given, I can forget about it. Also specular light contribution need not be considered.&#xD;&#xA;&#xD;&#xA;The surface normal is: &#xD;&#xA;&#xD;&#xA;A = (0, 2, 1) B = (3, 0, 1) O = (0, 0, 0)&#xD;&#xA;&#xD;&#xA;U = A - O = (0, 2, 1) V = B - O = (3, 0, 1)&#xD;&#xA;&#xD;&#xA;Surface normal = U x V (cross-product) = (2, 3, -6)&#xD;&#xA;&#xD;&#xA;I = 0.1 + (1, 1, 1) x ((0.6, 0.7, 0.8) x ((2, 3, -6) x (0, 3, 4)))&#xD;&#xA;&#xD;&#xA;I = 0.1 + (1, 1, 1) x ((0.6, 0.7, 0.8) x (0, 9, -2.4))&#xD;&#xA;&#xD;&#xA;I = 0.1 + (1, 1, 1) x (0, 6.3, -1.92)&#xD;&#xA;&#xD;&#xA;I = (0.1, 6.4, -1.82) = RGB intensity values&#xD;&#xA;&#xD;&#xA;Is this correct?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11594" PostHistoryTypeId="2" PostId="4868" RevisionGUID="0154da49-ab49-42a8-9d08-d4d91b18a23c" CreationDate="2017-03-16T20:31:41.430" UserId="6041" Text="Appology for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;Q1: The definition of multi sample estimator that Veach has defined, the integrand is same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, shadow rays that miss the light geometry are to be considered, as the integrand is not zero(and pdf is not zero too) but has some value, not from the light of-curse but, due to the surfaces that have occluded the light? &#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and brdf which is what MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;Q2: My main problem is to sample adequately part of the scene where light come form the external obstructions(marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is pdf for sampling window area(or solid angle) to get direct light; P2 is same pdf but to account for external surfaces contributions; and P3 is brdf sampling for indirect light from indoor surfaces. I could rely just on brdf sampling to account for external surfaces but as their contribution is large(illuminance from infinite source) I want to explicitly account for them.   &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from brdf P3 with W3 = p3/p3+p2, and one from P2 pdf &#xD;&#xA;with W2 = p2/p2+p3. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the sudo code:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P1&#xD;&#xA;    weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;    throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11595" PostHistoryTypeId="1" PostId="4868" RevisionGUID="0154da49-ab49-42a8-9d08-d4d91b18a23c" CreationDate="2017-03-16T20:31:41.430" UserId="6041" Text="Efficiently sampling specific surfaces using MIS in path tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="11596" PostHistoryTypeId="3" PostId="4868" RevisionGUID="0154da49-ab49-42a8-9d08-d4d91b18a23c" CreationDate="2017-03-16T20:31:41.430" UserId="6041" Text="|raytracing|pathtracing|global-illumination|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11598" PostHistoryTypeId="5" PostId="4868" RevisionGUID="ee6cdba7-4702-4c38-9de7-a55e9fabe165" CreationDate="2017-03-16T22:14:30.520" UserId="6041" Comment="added 132 characters in body" Text="Appology for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;Q1: The definition of multi sample estimator that Veach has defined, the integrand is same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, shadow rays that miss the light geometry are to be considered, as the integrand is not zero(and pdf is not zero too) but has some value, not from the light of-curse but, due to the surfaces that have occluded the light? &#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and brdf which is what MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;Q2: My main problem is to sample adequately part of the scene where light come form the external obstructions(marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is pdf for sampling window area(or solid angle) to get direct light; P2 is same pdf but to account for external surfaces contributions; and P3 is brdf sampling for indirect light from indoor surfaces. I could rely just on brdf sampling to account for external surfaces but as their contribution is large(illuminance from infinite source) I want to explicitly account for them.   &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from brdf P3 with W3 = p3/p3+p2, and one from P2 pdf &#xD;&#xA;with W2 = p2/p2+p3. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the sudo code:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P1&#xD;&#xA;    weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;    throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11599" PostHistoryTypeId="5" PostId="4868" RevisionGUID="b02e8800-894a-40f9-ad4d-c4b27c452fdd" CreationDate="2017-03-16T22:40:58.830" UserId="6041" Comment="added 9 characters in body" Text="Appology for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;Q1: In the definition of multi sample estimator that Veach has defined, the integrand is same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero(and pdf is not zero too) but has some value, not from the light of-curse but, due to the surfaces that have occluded the light? &#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and brdf which is what MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;Q2: My main problem is to sample adequately part of the scene where light come form the external obstructions(marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is pdf for sampling window area(or solid angle) to get direct light; P2 is same pdf but to account for external surfaces contributions; and P3 is brdf sampling for indirect light from indoor surfaces. I could rely just on brdf sampling to account for external surfaces but as their contribution is large(illuminance from infinite source) I want to explicitly account for them.   &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from brdf P3 with W3 = p3/p3+p2, and one from P2 pdf &#xD;&#xA;with W2 = p2/p2+p3. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the sudo code:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P3&#xD;&#xA;    weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;    throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11600" PostHistoryTypeId="5" PostId="4868" RevisionGUID="85b13b23-f45c-4b50-a246-c7d3384cff97" CreationDate="2017-03-16T22:46:42.757" UserId="6041" Comment="added 9 characters in body" Text="Appology for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;Q1: In the definition of multi sample estimator that Veach has defined, the integrand is same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero(and pdf is not zero too) but has some value, not from the light of-curse but, due to the surfaces that have occluded the light? &#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and brdf which is what MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;Q2: My main problem is to sample adequately part of the scene where light come form the external obstructions(marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is pdf for sampling window area(or solid angle) to get direct light; P2 is same pdf but to account for external surfaces contributions; and P3 is brdf sampling for indirect light from indoor surfaces. I could rely just on brdf sampling to account for external surfaces but as their contribution is large(illuminance from infinite source) I want to explicitly account for them.   &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from brdf P3 with W3 = p3/p3+p2, and one from P2 pdf &#xD;&#xA;with W2 = p2/p2+p3. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the sudo code:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P3&#xD;&#xA;    if z is a hit{&#xD;&#xA;        weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;        throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    else &#xD;&#xA;        break;&#xD;&#xA;&#xD;&#xA;    //using russian roulette to terminate the path.. &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11601" PostHistoryTypeId="2" PostId="4869" RevisionGUID="32b9a8ba-650a-44a4-8771-469f66e182ff" CreationDate="2017-03-17T07:35:31.833" UserId="5513" Text="Is there an equation for flat shading?&#xD;&#xA;&#xD;&#xA;To my understanding, it is this:&#xD;&#xA;&#xD;&#xA;I = Ia x Ka + Fatt x Il x (Kd x (N x L))&#xD;&#xA;&#xD;&#xA;Final intensity = ambient reflection x ambient reflection coefficient + (attenuation x incident light intensity x (diffusive reflection coefficient x (surface normal x Light intensity))&#xD;&#xA;&#xD;&#xA;However, I have only found one source for this equation (my lecture slides).&#xD;&#xA;&#xD;&#xA;Are there any other sources to confirm this is the equation for flat shading? I can't find one." ContentLicense="CC BY-SA 3.0" />
  <row Id="11602" PostHistoryTypeId="1" PostId="4869" RevisionGUID="32b9a8ba-650a-44a4-8771-469f66e182ff" CreationDate="2017-03-17T07:35:31.833" UserId="5513" Text="What is the equation for flat shading?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11603" PostHistoryTypeId="3" PostId="4869" RevisionGUID="32b9a8ba-650a-44a4-8771-469f66e182ff" CreationDate="2017-03-17T07:35:31.833" UserId="5513" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11604" PostHistoryTypeId="2" PostId="4870" RevisionGUID="e321220c-cdf4-4e0c-957e-f74d0066a219" CreationDate="2017-03-17T09:19:17.510" UserId="38" Text="I don't think having a equation for flat shading is meaningful as such. Mainly because the formula for flat shading is same as the formula for the model the flat shading is emulating. The difference is that flat shading is operating per primitive rather than per point or per vertex.&#xD;&#xA;&#xD;&#xA;So there can in fact exist multiple formulas that work differently but are still all flat shading." ContentLicense="CC BY-SA 3.0" />
  <row Id="11606" PostHistoryTypeId="2" PostId="4871" RevisionGUID="fa43bdfa-e3bd-41bd-8fb3-179ef3403b70" CreationDate="2017-03-17T14:06:30.177" UserId="38" Text="Id like to leave a longish comment with pictures on the drawing aspect. Raytracing is not limited to computer graphics you can and often do see see artists manually raytrace to figure out intersections of shapes on paper with a ruler or even freehand by elbow twisting /*.&#xD;&#xA;&#xD;&#xA;While @DanHulme correctly surmises that the mathematical definition of a ray is just a line with a starting point and no ending point (goes to infinity). This is not really what people do, instead its defined that way to be rigorous. In general its just a line that goes far enough for the job, and we aren't really interested in the other end but rather how the line interacts with something. Infinity is just a safe way of saying it will in fact interact if possible. Mathematicians are very particular about stuff like that.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: An example of manually tracing shadows of objects with ruler and pen for a as of yet unfinished answer on the subject [here](http://graphicdesign.stackexchange.com/a/86754/18306). Mainly here because i had spent yesterday evening doing the rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you see you would use rays whenever you try to find a geometric intersection between two geometric primitives. Its not only useful for shadows, its for anything where you can intersect two things, with a starting point somewhere. So tracing can be used to find the shape of 2 intersecting surfaces, manually drawing perpective images, volumetric problems, rendering implicit surfaces like metaballs solving mathematical functions numerically etc etc. &#xD;&#xA;&#xD;&#xA;The definition of what now is called a ray was first described by Euclid's Elements about 300 bc. Which predates computers by a safe(ish) margin.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WwdR3.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11607" PostHistoryTypeId="5" PostId="4871" RevisionGUID="8b0a570b-2c6e-4f68-acf2-cefdbdf8d8e0" CreationDate="2017-03-17T14:14:38.923" UserId="38" Comment="added 89 characters in body" Text="Id like to leave a longish comment with pictures on the drawing aspect. Raytracing is not limited to computer graphics you can and often do see see artists manually raytrace to figure out intersections of shapes on paper with a ruler or even freehand by elbow twisting /*.&#xD;&#xA;&#xD;&#xA;It is also useful for many physical sciences like mechanical engineering and surveying. Or anywhere where you can use geometry to solve your problem.&#xD;&#xA;&#xD;&#xA;While @DanHulme correctly surmises that the mathematical definition of a ray is just a line with a starting point and no ending point (goes to infinity). This is not really what people do, instead its defined that way to be rigorous. In general its just a line that goes far enough for the job, and we aren't really interested in the other end but rather how the line interacts with something. Infinity is just a safe way of saying it will in fact interact if possible. Mathematicians are very particular about stuff like that.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: An example of manually tracing shadows of objects with ruler and pen for a as of yet unfinished answer on the subject [here](http://graphicdesign.stackexchange.com/a/86754/18306). Mainly here because i had spent yesterday evening doing the rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you see you would use rays whenever you try to find a geometric intersection between two geometric primitives. Its not only useful for shadows, its for anything where you can intersect two things, with a starting point somewhere. So tracing can be used to find the shape of 2 intersecting surfaces, manually drawing perpective images, volumetric problems, rendering implicit surfaces like metaballs solving mathematical functions numerically etc etc. &#xD;&#xA;&#xD;&#xA;\* The definition of what now is called a ray was first described by Euclid's Elements about 300 bc. Which predates computers by a safe(ish) margin.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WwdR3.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11608" PostHistoryTypeId="2" PostId="4872" RevisionGUID="14af7f45-53c1-4115-93de-f533f6a61543" CreationDate="2017-03-17T15:28:38.707" UserId="6041" Text="Keeping in mind the definition of wave-front:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now quoting from [Image Acquisition][2] book:&#xD;&#xA;&#xD;&#xA;&quot;A **ray** of light is a straight line connecting the wavefront normals in a series of radiative wavefronts. Connecting together the like-angle normals of the wavefronts emanating from a source defines a ray of light from that source. A collection of rays emanating from a *point* is referred to as a **pencil** of light, while a group of pencils emanating from a *finite-area patch* is called a **beam** of light.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Upuwr.gif&#xD;&#xA;  [2]: http://www.springer.com/gp/book/9789401065207" ContentLicense="CC BY-SA 3.0" />
  <row Id="11609" PostHistoryTypeId="2" PostId="4873" RevisionGUID="30657936-96bb-424e-8020-50c0489e72df" CreationDate="2017-03-18T00:22:37.870" UserId="2479" Text="I will not answer your questions directly, but will try to change your mindset a bit. I hope got your intentions reasonably well... &#xA;&#xA;The way it is usually done in path tracing is that the reflection integral is split into direct and indirect illumination contribution.&#xA;&#xA;The direction illumination can be estimated using more sampling strategies which are combined together using the multiple importance sampling method by Veach. Typically, there is BSDF sampling and light sampling available, but you can also add things like light portals in windows and other stuff. I guess this is where you are headed.&#xA;&#xA;The indirect illumination is usually estimated by just one sampling strategy (typically BSDF sampling) because you want to avoid splitting recursive paths. That's the reason why path tracing has so poor performance for glossy indirect illumination and caustics. &#xA;&#xA;One nice thing about the split integral is that you can share the BSDF samples between the direct and indirect integral to avoid wasting samples.&#xA;&#xA;----------&#xA;&#xA;PS: I guess that for indirect illumination estimator you could possibly use the single sample multiple importance sampling method (I believe that it was also proposed by Veach) to incorporate the light portals and other sampling strategies, but I must admit I'm not well acquainted with this technique, I have some doubts about the efficiency of the resulting estimator, and I'm afraid you will not be able to reuse the samples for the direct illumination integral." ContentLicense="CC BY-SA 3.0" />
  <row Id="11610" PostHistoryTypeId="2" PostId="4874" RevisionGUID="1cac554a-02fc-47a2-ba57-1a4e72979e5e" CreationDate="2017-03-18T07:55:13.137" UserId="6253" Text="&#xD;&#xA;&#xD;&#xA;I'm using Urho3D on Raspberry Pi, but the following questions apply to all platforms.&#xD;&#xA;&#xD;&#xA;What should I do in order to reduce the load of online real-time rendering of the game? Does building/compiling/rendering the game (before running it) makes it easier and lighter to be run afterwards?&#xD;&#xA;&#xD;&#xA;When making animations with 3dsmax, we use high-end computers to design the animation and render it. After that, any low-end and simple computer can play the animation. Now can we use a similar approach? Can I build/compile/render the game in a high-end machine and run the game in a low-end machine?&#xD;&#xA;&#xD;&#xA;What is exactly the difference between building/compiling/rendering when designing a game, and running/real-time-rendering when playing the game?&#xD;&#xA;&#xD;&#xA;Does a game needs rendering after designing? Or all the renderings are left to the playing time!?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11611" PostHistoryTypeId="1" PostId="4874" RevisionGUID="1cac554a-02fc-47a2-ba57-1a4e72979e5e" CreationDate="2017-03-18T07:55:13.137" UserId="6253" Text="Fundamental Questions: Building vs Compiling vs Rendering vs Coding vs Running?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11612" PostHistoryTypeId="3" PostId="4874" RevisionGUID="1cac554a-02fc-47a2-ba57-1a4e72979e5e" CreationDate="2017-03-18T07:55:13.137" UserId="6253" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11613" PostHistoryTypeId="5" PostId="4873" RevisionGUID="523eae87-a864-4f56-9915-0304a0c52933" CreationDate="2017-03-18T14:42:15.503" UserId="2479" Comment="Extended and reworded" Text="I will not answer your questions directly, but will try to change your mindset a bit. I hope got your intentions reasonably well... &#xD;&#xA;&#xD;&#xA;The usual way the path tracing is implemented is that the reflection integral is split into direct and indirect illumination and they are estimated separately.&#xD;&#xA;&#xD;&#xA;**The direct illumination** can be estimated using more sampling strategies which are combined together using the multi-sample multiple importance sampling method by Veach. Typically, there is just BSDF sampling and light sampling used, but you can also add things like light portals sampling and other more sophisticated stuff. I guess this is where you are headed.&#xD;&#xA;&#xD;&#xA;**The indirect illumination** is usually estimated by just one sampling strategy (typically BSDF sampling) because you want to avoid exponential growth of recursive paths count. That's the reason why path tracing has poor performance for indirect illumination reflected/refracted through glossy/specular materials.&#xD;&#xA;&#xD;&#xA;A nice thing about the split integral is that you can share samples between the direct and indirect integral. If you have two integrals over the same domain and have a sampling strategy that can be used for both, then you can generate a sample to estimate the first integral and then use the same sample for the second integral as well. There is no problem with correlated samples here because we have two separate computations. In practice you generate a BSDF sample with some PDF, shoot a ray in that direction and use the intersection point to estimate both direct and indirect integral separately.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;PS: I guess that for indirect illumination estimator you could possibly use the one-sample multiple importance sampling method by Veach to incorporate the light portals and other sampling strategies, but I have some doubts about the efficiency of the resulting estimator, especially when reusing the samples for the direct illumination integral." ContentLicense="CC BY-SA 3.0" />
  <row Id="11614" PostHistoryTypeId="5" PostId="4868" RevisionGUID="d9a9299f-53cd-43e3-97f9-9436c3199992" CreationDate="2017-03-18T16:31:26.907" UserId="6041" Comment="added 189 characters in body" Text="Appology for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;Q1: In the definition of multi sample estimator that Veach has defined, the integrand is same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero(and pdf is not zero too) but has some value, not from the light of-curse but, due to the surfaces that have occluded the light? &#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and brdf which is what MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;Q2: My main problem is to sample adequately part of the scene where light come form the external obstructions(marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is pdf for sampling window area(or solid angle) to get direct light; P2 is same pdf but to account for external surfaces contributions; and P3 is brdf sampling for indirect light from indoor surfaces. I could rely just on brdf sampling to account for external surfaces but as their contribution is large(illuminance from infinite source) I want to explicitly account for them.   &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from brdf P3 with W3 = p3/p3+p2, and one from P2 pdf &#xD;&#xA;with W2 = p2/p2+p3. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the sudo code:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P3&#xD;&#xA;    if z is a hit{&#xD;&#xA;        weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;        throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    else &#xD;&#xA;        break;&#xD;&#xA;&#xD;&#xA;    //using russian roulette to terminate the path.. &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;This excersise in PBRT seems to be relevant to this question. So I post it here&#xD;&#xA;in case it helps.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ABK7X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11615" PostHistoryTypeId="5" PostId="4868" RevisionGUID="01659173-adf2-4c1f-892e-347c283d2ded" CreationDate="2017-03-18T17:23:17.000" UserId="6041" Comment="added 13 characters in body" Text="Appology for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;Q1: In the definition of multi sample estimator that Veach has defined, the integrand is same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero(and pdf is not zero too) but has some value, not from the light of-curse but, due to the surfaces that have occluded the light? &#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and brdf which is what MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;Q2: My main problem is to sample adequately part of the scene where light come form the external obstructions(marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is pdf for sampling window area(or solid angle) to get direct light; P2 is same pdf but to account for external surfaces contributions; and P3 is brdf sampling for indirect light from indoor surfaces. I could rely just on brdf sampling to account for external surfaces but as their contribution is large(illuminance from infinite source) I want to explicitly account for them.   &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from brdf P3 with W3 = p3/p3+p2, and one from P2 pdf &#xD;&#xA;with W2 = p2/p2+p3. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the sudo code:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P3&#xD;&#xA;    if z is a hit{&#xD;&#xA;        weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;        throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    else &#xD;&#xA;        break;&#xD;&#xA;&#xD;&#xA;    //using russian roulette to terminate the path.. &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;**Update**:&#xD;&#xA;&#xD;&#xA;This excersise in PBRT seems to be relevant to this question. So I post it here&#xD;&#xA;in case it helps.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ABK7X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11616" PostHistoryTypeId="5" PostId="4868" RevisionGUID="a210c894-8592-4b90-9726-af69773eec1e" CreationDate="2017-03-19T00:23:22.090" UserId="231" Comment="Tidying" Text="Apologies for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;### Question 1&#xD;&#xA;&#xD;&#xA;In the definition of multi sample estimator that Veach has defined, the integrand is the same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero (and the PDF is also not zero) but has some value, not from the light of course, but due to the surfaces that have occluded the light? &#xD;&#xA;&#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and BRDF, whereas MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;### Question 2&#xD;&#xA;&#xD;&#xA;My main problem is to sample adequately part of the scene where light comes from the external obstructions (marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is PDF for sampling window area (or solid angle) to get direct light; P2 is same PDF but to account for external surfaces contributions; and P3 is BRDF sampling for indirect light from indoor surfaces. I could rely just on BRDF sampling to account for external surfaces but as their contribution is large (illuminance from infinite source) I want to explicitly account for them.  &#xD;&#xA; &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from BRDF P3 with $W3 = p_3/p_3+p_2$, and one from P2 PDF with $W2 = p_2/p_2+p_3$. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the pseudocode:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / p2(y)+p3(y)&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P3&#xD;&#xA;    if z is a hit{&#xD;&#xA;        weight = p3(z) / p3(z)+p2(z)&#xD;&#xA;        throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    else &#xD;&#xA;        break;&#xD;&#xA;&#xD;&#xA;    //using russian roulette to terminate the path.. &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;**Update**:&#xD;&#xA;&#xD;&#xA;This excersise in PBRT seems to be relevant to this question. So I post it here&#xD;&#xA;in case it helps.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ABK7X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11617" PostHistoryTypeId="5" PostId="4853" RevisionGUID="53728a1c-a2fd-404f-9927-0c30ca842d64" CreationDate="2017-03-19T00:49:34.497" UserId="231" Comment="Hide large URL behind link text" Text="I'm learning Ray Tracing using [this MIT tutorial].&#xD;&#xA;&#xD;&#xA;I've heard Ray Tracing only in the context of lighting. I.e. I understand that ray casting is used to light an object that has been already drawn. However, I've also seen ray casting in the context of just drawing the picture (not lighting). So which one are rays about?&#xD;&#xA;&#xD;&#xA;What's the concept of &quot;ray&quot; really?&#xD;&#xA;&#xD;&#xA;E.g. in that tutorial one draws the picture like:&#xD;&#xA;&#xD;&#xA;    image.SetPixel( x, y, pixelColor );&#xD;&#xA;&#xD;&#xA;where `pixelColor` has been acquired from the Ray Caster. But I read this to mean that `pixelColor` already has lighting information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [this MIT tutorial]: https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/assignments/MIT6_837F12_assn4.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11618" PostHistoryTypeId="5" PostId="4871" RevisionGUID="35a135c3-cc0f-41e2-bf67-3a56250d219c" CreationDate="2017-03-19T00:57:10.797" UserId="231" Comment="Remove redundant forward slash as asterisk already displays literally in this case" Text="Id like to leave a longish comment with pictures on the drawing aspect. Raytracing is not limited to computer graphics you can and often do see see artists manually raytrace to figure out intersections of shapes on paper with a ruler or even freehand by elbow twisting*.&#xD;&#xA;&#xD;&#xA;It is also useful for many physical sciences like mechanical engineering and surveying. Or anywhere where you can use geometry to solve your problem.&#xD;&#xA;&#xD;&#xA;While @DanHulme correctly surmises that the mathematical definition of a ray is just a line with a starting point and no ending point (goes to infinity). This is not really what people do, instead its defined that way to be rigorous. In general its just a line that goes far enough for the job, and we aren't really interested in the other end but rather how the line interacts with something. Infinity is just a safe way of saying it will in fact interact if possible. Mathematicians are very particular about stuff like that.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: An example of manually tracing shadows of objects with ruler and pen for a as of yet unfinished answer on the subject [here](http://graphicdesign.stackexchange.com/a/86754/18306). Mainly here because i had spent yesterday evening doing the rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you see you would use rays whenever you try to find a geometric intersection between two geometric primitives. Its not only useful for shadows, its for anything where you can intersect two things, with a starting point somewhere. So tracing can be used to find the shape of 2 intersecting surfaces, manually drawing perpective images, volumetric problems, rendering implicit surfaces like metaballs solving mathematical functions numerically etc etc. &#xD;&#xA;&#xD;&#xA;\* The definition of what now is called a ray was first described by Euclid's Elements about 300 bc. Which predates computers by a safe(ish) margin.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WwdR3.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11619" PostHistoryTypeId="5" PostId="4869" RevisionGUID="01982eec-5418-4b95-8d3f-32f1b0972bd1" CreationDate="2017-03-19T01:00:58.800" UserId="231" Comment="Add MathJax for ease of reading" Text="Is there an equation for flat shading?&#xD;&#xA;&#xD;&#xA;To my understanding, it is this:&#xD;&#xA;&#xD;&#xA;$$I = I_a \times K_a + F_{att} \times  I_l \times  (K_d \times  (N \times  L))$$&#xD;&#xA;&#xD;&#xA;Final intensity = ambient reflection x ambient reflection coefficient + (attenuation x incident light intensity x (diffusive reflection coefficient x (surface normal x Light intensity))&#xD;&#xA;&#xD;&#xA;However, I have only found one source for this equation (my lecture slides).&#xD;&#xA;&#xD;&#xA;Are there any other sources to confirm this is the equation for flat shading? I can't find one." ContentLicense="CC BY-SA 3.0" />
  <row Id="11620" PostHistoryTypeId="5" PostId="4868" RevisionGUID="26dff99a-0278-4657-b02b-812fcbd0a31f" CreationDate="2017-03-19T06:46:59.617" UserId="6041" Comment="added 4 characters in body" Text="Apologies for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;### Question 1&#xD;&#xA;&#xD;&#xA;In the definition of multi sample estimator that Veach has defined, the integrand is the same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero (and the PDF is also not zero) but has some value, not from the light of course, but due to the surfaces that have occluded the light? &#xD;&#xA;&#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and BRDF, whereas MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;### Question 2&#xD;&#xA;&#xD;&#xA;My main problem is to sample adequately part of the scene where light comes from the external obstructions (marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is PDF for sampling window area (or solid angle) to get direct light; P2 is same PDF but to account for external surfaces contributions; and P3 is BRDF sampling for indirect light from indoor surfaces. I could rely just on BRDF sampling to account for external surfaces but as their contribution is large (illuminance from infinite source) I want to explicitly account for them.  &#xD;&#xA; &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from BRDF P3 with $W3 = p_3/(p_3+p_2)$, and one from P2 PDF with $W2 = p_2/(p_2+p_3)$. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the pseudocode:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;    while(1){&#xD;&#xA;    //P1&#xD;&#xA;    //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;    //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;    totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;    //P2&#xD;&#xA;    y = Trace one sample from P2&#xD;&#xA;    if y is external surface {&#xD;&#xA;       weight = p2(y) / (p2(y)+p3(y))&#xD;&#xA;       totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //P3&#xD;&#xA;    z = Trace one sample form P3&#xD;&#xA;    if z is a hit{&#xD;&#xA;        weight = p3(z) / (p3(z)+p2(z))&#xD;&#xA;        throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;    }&#xD;&#xA;    else &#xD;&#xA;        break;&#xD;&#xA;&#xD;&#xA;    //using russian roulette to terminate the path.. &#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;**Update**:&#xD;&#xA;&#xD;&#xA;This excersise in PBRT seems to be relevant to this question. So I post it here&#xD;&#xA;in case it helps.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ABK7X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11622" PostHistoryTypeId="2" PostId="4875" RevisionGUID="5a5ea1c6-69c7-42e5-9cb6-67c8c487b445" CreationDate="2017-03-19T18:31:12.817" UserId="5852" Text="If you clear the color buffer and draw a triangle, you have nothing in the buffer that is shown in the screen and a triangle in the other buffer, so you have to swap buffers for showing the triangle. If you swap buffers, you have a triangle in your screen and a empty color buffer in the other side. If you swap buffers again you should see and empty screen because you changed the buffer with the triangle by the other empty buffer. Instead of this, the triangle is shown again. Why?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11623" PostHistoryTypeId="1" PostId="4875" RevisionGUID="5a5ea1c6-69c7-42e5-9cb6-67c8c487b445" CreationDate="2017-03-19T18:31:12.817" UserId="5852" Text="Swap buffers twice does not show the first scene" ContentLicense="CC BY-SA 3.0" />
  <row Id="11624" PostHistoryTypeId="3" PostId="4875" RevisionGUID="5a5ea1c6-69c7-42e5-9cb6-67c8c487b445" CreationDate="2017-03-19T18:31:12.817" UserId="5852" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11625" PostHistoryTypeId="2" PostId="4876" RevisionGUID="9d9901b4-43fb-4e2f-af8b-21b025da8b81" CreationDate="2017-03-19T20:32:25.210" UserId="2654" Text="&gt; If you swap buffers, you have a triangle in your screen and a empty color buffer in the other side.&#xD;&#xA;&#xD;&#xA;No, you do not. Buffer swapping does not necessarily mean that the current contents of the front buffer are preserved. When you do a swap, the contents of the back buffer become the front buffer, but the state of the back buffer is *undefined* after the swap.&#xD;&#xA;&#xD;&#xA;Some implementations use a true swap, where the two buffers really are switched. Other implementations copy the data from the back buffer on a swap, leaving the back buffer as whatever was there before. Still others could do something else." ContentLicense="CC BY-SA 3.0" />
  <row Id="11626" PostHistoryTypeId="2" PostId="4877" RevisionGUID="46750100-ca8d-4d0b-8ca2-a34178c6710a" CreationDate="2017-03-19T20:59:46.397" UserDisplayName="user5681" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms (for conductors and dielectrics):&#xD;&#xA;&#xD;&#xA;**For conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**For dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;I the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info" ContentLicense="CC BY-SA 3.0" />
  <row Id="11627" PostHistoryTypeId="1" PostId="4877" RevisionGUID="46750100-ca8d-4d0b-8ca2-a34178c6710a" CreationDate="2017-03-19T20:59:46.397" UserDisplayName="user5681" Text="More accurate Fresnel approximation for a RGB-based Path Tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="11628" PostHistoryTypeId="3" PostId="4877" RevisionGUID="46750100-ca8d-4d0b-8ca2-a34178c6710a" CreationDate="2017-03-19T20:59:46.397" UserDisplayName="user5681" Text="|raytracing|pathtracing|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11630" PostHistoryTypeId="5" PostId="4877" RevisionGUID="ad5a574d-2586-40a9-9142-b62de6deaeb9" CreationDate="2017-03-19T22:30:25.923" UserDisplayName="user5681" Comment="added 1 character in body" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms (for conductors and dielectrics):&#xD;&#xA;&#xD;&#xA;**For conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**For dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;In the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info" ContentLicense="CC BY-SA 3.0" />
  <row Id="11631" PostHistoryTypeId="2" PostId="4878" RevisionGUID="55ac950a-3ef2-4ba7-9f1d-0e4bfc4f0942" CreationDate="2017-03-20T02:39:18.593" UserId="5506" Text="I'm working on my own engine and I'm struggling to find any techniques that give okay-ish reflections in realtime on dynamic scene.&#xD;&#xA;So far the only technique I found that work in real time on dynamic scene is SSR but it's really heavy and have a lot of bias.&#xD;&#xA;&#xD;&#xA;The idea of having multiple cubemaps and updating them in real time crossed my mind but because that mean re-rasterising the scene that also mean that every cubemap updated in realtime is a shadow casting that I can't do.&#xD;&#xA;&#xD;&#xA;So my question is: is there another technique other than reflection probe (cubemap) or Screen Space Reflections ?&#xD;&#xA;&#xD;&#xA;The artstyle of the game where the engine will be used is based on a lot of &quot;almost mirror&quot; reflections and it's not PBR." ContentLicense="CC BY-SA 3.0" />
  <row Id="11632" PostHistoryTypeId="1" PostId="4878" RevisionGUID="55ac950a-3ef2-4ba7-9f1d-0e4bfc4f0942" CreationDate="2017-03-20T02:39:18.593" UserId="5506" Text="realtime dynamic reflections, which way to go?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11633" PostHistoryTypeId="3" PostId="4878" RevisionGUID="55ac950a-3ef2-4ba7-9f1d-0e4bfc4f0942" CreationDate="2017-03-20T02:39:18.593" UserId="5506" Text="|opengl|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11635" PostHistoryTypeId="2" PostId="4879" RevisionGUID="fec9b4e5-b1f3-4cdf-a4d7-edfb94f64070" CreationDate="2017-03-20T07:23:33.077" UserId="5944" Text="The [book][1] omitted the explanation of [the constructor of hyperboloid][2].&#xD;&#xA;&#xD;&#xA;Could someone give some explanations about:&#xD;&#xA;&#xD;&#xA; 1. Why the arguments are two points?&#xD;&#xA; 2. What are the meanings of ***ah*** and ***ch***?&#xD;&#xA; 3. Why is there a while loop?&#xD;&#xA;&#xD;&#xA;  [1]: http://pbrt.org/&#xD;&#xA;  [2]: https://github.com/mmp/pbrt-v3/blob/master/src/shapes/hyperboloid.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="11636" PostHistoryTypeId="1" PostId="4879" RevisionGUID="fec9b4e5-b1f3-4cdf-a4d7-edfb94f64070" CreationDate="2017-03-20T07:23:33.077" UserId="5944" Text="The constructor of hyperboloid in pbrt-v3" ContentLicense="CC BY-SA 3.0" />
  <row Id="11637" PostHistoryTypeId="3" PostId="4879" RevisionGUID="fec9b4e5-b1f3-4cdf-a4d7-edfb94f64070" CreationDate="2017-03-20T07:23:33.077" UserId="5944" Text="|rendering|computational-geometry|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11638" PostHistoryTypeId="2" PostId="4880" RevisionGUID="c3e69e15-b598-40fb-84f5-20113a9a46b7" CreationDate="2017-03-20T07:54:09.673" UserId="6255" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, It suggests a way to setup up a phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are bit off. This could be from somewhere else ofc, which is why I asking for clarification. &#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curios of:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment im sending these matrices:&#xD;&#xA; &#xD;&#xA;    view*model //ModelViewMatrix;&#xD;&#xA;    transpose(inverse(model))) //NormalMatrix;&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;These are just assumptions I've pieced together from various sites. The shader &quot;works&quot;, but I'm unsure if they are correct or not&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11639" PostHistoryTypeId="1" PostId="4880" RevisionGUID="c3e69e15-b598-40fb-84f5-20113a9a46b7" CreationDate="2017-03-20T07:54:09.673" UserId="6255" Text="Am I passing the correct matrices for my shader? openGL/C++" ContentLicense="CC BY-SA 3.0" />
  <row Id="11640" PostHistoryTypeId="3" PostId="4880" RevisionGUID="c3e69e15-b598-40fb-84f5-20113a9a46b7" CreationDate="2017-03-20T07:54:09.673" UserId="6255" Text="|opengl|c++|glsl|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11641" PostHistoryTypeId="5" PostId="4868" RevisionGUID="b138fdcb-c0ef-4e3f-ad52-15fbcdaa640a" CreationDate="2017-03-20T07:55:17.530" UserId="2479" Comment="Improved formating of the code" Text="Apologies for posting two questions in one post, but as they are relevant I kept them in one.&#xD;&#xA; &#xD;&#xA;### Question 1&#xD;&#xA;&#xD;&#xA;In the definition of multi sample estimator that Veach has defined, the integrand is the same for all the n sampling strategies. If this is so, then is it not the case that, in direct lighting, those shadow rays that miss the light geometry are to be considered, as the integrand is not zero (and the PDF is also not zero) but has some value, not from the light of course, but due to the surfaces that have occluded the light? &#xD;&#xA;&#xD;&#xA;Would missing those contributions not be the same as partitioning the integral in sampling the lights and BRDF, whereas MIS claims to give &#xD;&#xA;a solution without partitioning the integral?&#xD;&#xA;&#xD;&#xA;### Question 2&#xD;&#xA;&#xD;&#xA;My main problem is to sample adequately part of the scene where light comes from the external obstructions (marked as P2 in the image). The only source of light is skylight coming in through the window opening. P1 is PDF for sampling window area (or solid angle) to get direct light; P2 is same PDF but to account for external surfaces contributions; and P3 is BRDF sampling for indirect light from indoor surfaces. I could rely just on BRDF sampling to account for external surfaces but as their contribution is large (illuminance from infinite source) I want to explicitly account for them.  &#xD;&#xA; &#xD;&#xA;I don't intend to partition the integral into three regions as it ends up to have recursive calls to get the contribution of external hits; it also slows down and makes the code too complex. I therefore guess I need to use MIS to account for indirect contribution of externals surfaces but am not clear how it is to be done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to take one sample from BRDF P3 with $W3 = p_3/(p_3+p_2)$, and one from P2 PDF with $W2 = p_2/(p_2+p_3)$. I am not clear how to evaluate the integrand for samples taken from P2 distributions. This is the pseudocode:&#xD;&#xA;    &#xD;&#xA;    for each measurement point x {&#xD;&#xA;        while(1){&#xD;&#xA;            //P1&#xD;&#xA;            //DirectLight routine uses P1 if x is indoor hit or &#xD;&#xA;            //sampling hemisphere if x is outdoor, to get direct light from sky &#xD;&#xA;            totalEstimate += DirectLight(x) * throughput&#xD;&#xA;    &#xD;&#xA;            //P2&#xD;&#xA;            y = Trace one sample from P2&#xD;&#xA;            if y is external surface {&#xD;&#xA;               weight = p2(y) / (p2(y)+p3(y))&#xD;&#xA;               totalestimate += DirectRadiance(y) * weight * brdf(x) * dot(x, Nx) / P2  &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            //P3&#xD;&#xA;            z = Trace one sample form P3&#xD;&#xA;            if z is a hit{&#xD;&#xA;                weight = p3(z) / (p3(z)+p2(z))&#xD;&#xA;                throughput *= weight * brdf(x) * dot(x, Nx) / P3  &#xD;&#xA;            }&#xD;&#xA;            else &#xD;&#xA;                break;&#xD;&#xA;&#xD;&#xA;            //using russian roulette to terminate the path.. &#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I tried this but had increase in variance. The measurement points are few points in room floor area and a contour line is drawn based on a the values. The above gives higher variance than using only P1 and P3 with no MIS weights.&#xD;&#xA;&#xD;&#xA;**Update**:&#xD;&#xA;&#xD;&#xA;This excersise in PBRT seems to be relevant to this question. So I post it here&#xD;&#xA;in case it helps.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N92zY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ABK7X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11642" PostHistoryTypeId="24" PostId="4868" RevisionGUID="b138fdcb-c0ef-4e3f-ad52-15fbcdaa640a" CreationDate="2017-03-20T07:55:17.530" Comment="Proposed by 2479 approved by 6041 edit id of 215" ContentLicense="CC BY-SA 3.0" />
  <row Id="11643" PostHistoryTypeId="5" PostId="4880" RevisionGUID="5a88e589-5a12-4f83-8f34-2ab654d10d0e" CreationDate="2017-03-20T08:41:26.710" UserId="6255" Comment="added 2 characters in body" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, It suggests a way to setup up a phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are a bit off. This could be from somewhere else in the code ofc, but I'd rather know for sure.&#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curios of:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment im sending these matrices:&#xD;&#xA; &#xD;&#xA;    view*model //ModelViewMatrix;&#xD;&#xA;    transpose(inverse(model))) //NormalMatrix;&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;These are just assumptions I've pieced together from various sites. The shader &quot;works&quot;, but I'm unsure if they are correct or not&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11644" PostHistoryTypeId="2" PostId="4881" RevisionGUID="e6c191ad-84ed-4967-9d48-e40aeb2c1af9" CreationDate="2017-03-20T09:12:07.217" UserId="137" Text="If there is only a single flat mirrored surface the solution is to render the scene twices, once normally. Afterwards you use stencil to mark the area where the mirror is visible.&#xD;&#xA;&#xD;&#xA;Then only drawing into that area you render the scene again but mirror it around the mirror's plane and cull any geometry on the other side of the mirror." ContentLicense="CC BY-SA 3.0" />
  <row Id="11645" PostHistoryTypeId="5" PostId="165" RevisionGUID="ad09822a-eb7e-40b4-ad3b-492a87757e6b" CreationDate="2017-03-20T10:18:35.050" UserId="-1" Comment="replaced http://superuser.com/ with https://superuser.com/" Text="I recently had an [issue with sub-pixel anti-aliasing of text](https://superuser.com/q/930036/264276), which produces very harsh colours and made me wonder how it is meant to be done properly:&#xD;&#xA;&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've drawn some cases of a black tile covering thirds of pixels below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The colours match the ones I'm seeing, however when I look at properly antialiased text, the result is not nearly as bright and distracting:&#xD;&#xA;&#xD;&#xA;&gt; ![from www.lagom.nl](https://i.stack.imgur.com/4Vrfz.png)&#xD;&#xA;&#xD;&#xA;I assume there has to be a balance between a good light intensity and the right colour. What methods are used for sub-pixel anti-aliasing that give such good results?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;*Update:*&#xD;&#xA;&#xD;&#xA;I've rendered a white teapot to an image with 3x width and with multisampling. Below I compare averaging every 3 pixels with assigning each to RGB. The colours still seem overly bright in some cases (especially compared to the example above from [here](http://www.lagom.nl/lcd-test/subpixel.php)), not that my phone captures them well.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5][![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7][![enter image description here][8]][8]&#xD;&#xA;&lt;sup&gt;OK, so my monitor needs a little dusting&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SQWSI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CE16y.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/19ABb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/RE5Jv.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/BZxjL.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/WT6ci.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/qveN5m.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/wPGG7m.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11646" PostHistoryTypeId="5" PostId="4880" RevisionGUID="b2e7da0b-baaa-47c7-bd35-04182249d3c1" CreationDate="2017-03-20T11:15:32.093" UserId="6255" Comment="deleted 64 characters in body" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, It suggests a way to setup up a phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are a bit off. This could be from somewhere else in the code ofc, but I'd rather know for sure.&#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curios of:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment im sending these matrices:&#xD;&#xA; &#xD;&#xA;    view*model //ModelViewMatrix;&#xD;&#xA;    transpose(inverse(model))) //NormalMatrix;&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;The shader &quot;works&quot;, but I cant get the lighting direction right&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11647" PostHistoryTypeId="5" PostId="4857" RevisionGUID="0f79fcf1-dc9e-4fef-9fd5-23498f892305" CreationDate="2017-03-20T12:00:01.647" UserId="4646" Comment="added 5 characters in body; edited title" Text="Which 3D object properties should be affected by distance in VR and other 3D applications and how important is it that they are changed?&#xD;&#xA;For example the level of detail, colour (?)... " ContentLicense="CC BY-SA 3.0" />
  <row Id="11648" PostHistoryTypeId="4" PostId="4857" RevisionGUID="0f79fcf1-dc9e-4fef-9fd5-23498f892305" CreationDate="2017-03-20T12:00:01.647" UserId="4646" Comment="added 5 characters in body; edited title" Text="Which 3D object properties should be affected by distance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11649" PostHistoryTypeId="5" PostId="4815" RevisionGUID="a26b9735-37e4-4f1b-9cf4-c8f22d6db41a" CreationDate="2017-03-20T15:23:37.293" UserId="6023" Comment="added 2443 characters in body" Text="Although this is not the solution I was looking for initially, the figure below is the tightest filling without overlaps of the plane with pentagons that I could come up with so far. I haven't found a recursive algorithm yet. I think it's not possible or it is too complicated to code. &#xD;&#xA;&#xD;&#xA;[![pentagon-rhombus lattice][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Below is the python script:&#xD;&#xA;&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    def pentagon (Xorig, Yorig, theta):&#xD;&#xA;        Ind = np.arange(N+1)&#xD;&#xA;        X = np.cos(Ind*2*np.pi/N+theta)+Xorig&#xD;&#xA;        Y = np.sin(Ind*2*np.pi/N+theta)+Yorig&#xD;&#xA;        plt.fill(X, Y, 'r-')&#xD;&#xA;&#xD;&#xA;    plt.axes().set_aspect ('equal')&#xD;&#xA;    r = 2*np.cos(np.pi/5)&#xD;&#xA;    plt.xlim(-2, 30)&#xD;&#xA;    plt.ylim(-2, 30)&#xD;&#xA;    Lx = np.cos(np.pi/10)&#xD;&#xA;    for j in np.arange(0, 10):&#xD;&#xA;        Xorig = (j%2)*Lx*np.ones(N+1)&#xD;&#xA;        Yorig = j*(1+2*np.cos(np.pi/5)+np.cos(2*np.pi/5))*np.ones(N+1)&#xD;&#xA;        theta = np.pi/(2*N)&#xD;&#xA;        sign = 1&#xD;&#xA;        for i in np.arange(1, 32):&#xD;&#xA;            pentagon(Xorig, Yorig, theta)&#xD;&#xA;            Xorig += r*np.cos(3*theta)*np.ones(N+1)&#xD;&#xA;            Yorig += r*np.sin(3*theta)*np.ones(N+1)&#xD;&#xA;            sign *= -1&#xD;&#xA;            theta = sign*np.pi/(2*N)&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(&quot;pentagonLattice.png&quot;, bbox_inches='tight')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;Also I haven't found yet a simple way to make a quasi-periodic tiling of the plane with only pentagons and rhombi yet. I did find out though how to fill the plane with pentagons and rhombi with a center with f-fold symmetry, but which is not a quasi-periodic lattice.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The code is the following:&#xD;&#xA;&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    # The golden ratio&#xD;&#xA;    phi = (1.0+np.sqrt(5.0))/2&#xD;&#xA;    # angle increment&#xD;&#xA;    theta0 = np.pi/5&#xD;&#xA;    LEFT = 0&#xD;&#xA;    RIGHT = 1&#xD;&#xA;    # fill plot a pentagon with center at (Xorig, Yorig) and orientation theta&#xD;&#xA;    def pentagon (Xorig, Yorig, theta):&#xD;&#xA;        Ind = np.arange(N+1)&#xD;&#xA;        X = np.cos(Ind*2*np.pi/N+theta)+Xorig&#xD;&#xA;        Y = np.sin(Ind*2*np.pi/N+theta)+Yorig&#xD;&#xA;        plt.fill(X, Y, 'r-')&#xD;&#xA;    # At each step three edges are generated&#xD;&#xA;    # and two recursive calls are made&#xD;&#xA;    def stepSplit (previousPoint, previousTurn, theta, nIter):&#xD;&#xA;        if nIter == 0:&#xD;&#xA;            return&#xD;&#xA;        if previousTurn == RIGHT:&#xD;&#xA;            # Turn left &#xD;&#xA;            theta = theta+theta0&#xD;&#xA;        elif previousTurn == LEFT:&#xD;&#xA;            # turn right &#xD;&#xA;            theta = theta-theta0&#xD;&#xA;        nextPoint = previousPoint + phi*np.array([np.cos(theta), np.sin(theta)])&#xD;&#xA;        X, Y = zip(previousPoint, nextPoint)&#xD;&#xA;        pentagon (nextPoint[0], nextPoint[1], theta)&#xD;&#xA;        # Update&#xD;&#xA;        previousPoint[:] = nextPoint[:]&#xD;&#xA;        # Bifurcation&#xD;&#xA;        # Turn left &#xD;&#xA;        theta1 = theta+theta0&#xD;&#xA;&#xD;&#xA;        nextPoint = previousPoint + phi*np.array([np.cos(theta1), np.sin(theta1)])&#xD;&#xA;        X, Y = zip(previousPoint, nextPoint)&#xD;&#xA;        pentagon (nextPoint[0], nextPoint[1], theta1)&#xD;&#xA;        stepSplit(nextPoint, LEFT, theta1, nIter-1)&#xD;&#xA;&#xD;&#xA;        # Turn right &#xD;&#xA;        theta1 = theta-theta0&#xD;&#xA;        nextPoint = previousPoint + phi*np.array([np.cos(theta1), np.sin(theta1)])&#xD;&#xA;        X, Y = zip(previousPoint, nextPoint)&#xD;&#xA;        pentagon (nextPoint[0], nextPoint[1], theta1)&#xD;&#xA;        stepSplit(nextPoint, RIGHT, theta1, nIter-1)&#xD;&#xA;&#xD;&#xA;    # fill plot pentagons&#xD;&#xA;    # Central pentagon&#xD;&#xA;    pentagon (0.0, 0.0, 0.0)&#xD;&#xA;    for i in [1, 3, 5, 7, 9]:&#xD;&#xA;        stepSplit (np.array([0.0, 0.0]), -1, i*theta0, 5)&#xD;&#xA;&#xD;&#xA;    for i in [0, 2, 4, 6, 8]:&#xD;&#xA;        theta = i*np.pi/5&#xD;&#xA;        x0 = phi*(1.0+2*np.cos(np.pi/5))*np.cos(theta)&#xD;&#xA;        y0 = phi*(1.0+2*np.cos(np.pi/5))*np.sin(theta)&#xD;&#xA;        pentagon (x0, y0, theta0)&#xD;&#xA;        stepSplit (np.array([x0, y0]), -1, theta, 4)&#xD;&#xA;&#xD;&#xA;    plt.axes().set_aspect ('equal')&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(&quot;pentagonLattice4.png&quot;, bbox_inches='tight')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TLnKi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/djejd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11650" PostHistoryTypeId="2" PostId="4882" RevisionGUID="842e46fb-6a32-4525-a452-737355e19baa" CreationDate="2017-03-20T18:30:25.327" UserId="5225" Text="**Problem.** I have inherited a large C++ 3D graphics codebase (with some shader code). The program runs for about 1-5 minutes before crashing. &#xD;&#xA;&#xD;&#xA;**Problem Data.** Using system tools, one can see a sharp rise in VRAM memory usage after the program launches, which eclipses into a crash. The same is true for GTT memory usage also (although the spike isn't quite as dramatic as with the VRAM).&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;1. Does this (probably) mean that there is a memory leak in OpenGL shader code somewhere (as opposed to a leak in regular C++ code)?&#xD;&#xA;&#xD;&#xA;2. Are there well-known tools for tracking down vram/gtt memory leaks (similar to the way that valgrind can be used to track down system memory usage)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11651" PostHistoryTypeId="1" PostId="4882" RevisionGUID="842e46fb-6a32-4525-a452-737355e19baa" CreationDate="2017-03-20T18:30:25.327" UserId="5225" Text="Are there well-known tools for chasing down VRAM &amp; GTT memory leaks?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11652" PostHistoryTypeId="3" PostId="4882" RevisionGUID="842e46fb-6a32-4525-a452-737355e19baa" CreationDate="2017-03-20T18:30:25.327" UserId="5225" Text="|memory|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11653" PostHistoryTypeId="2" PostId="4883" RevisionGUID="cf705dc5-58c6-46ad-b2df-69755775bc8a" CreationDate="2017-03-20T20:10:09.437" UserId="2041" Text="1. Probably not. Most OpenGL resources (framebuffers, vertex buffer objects, textures &amp;c.) are controlled by host code (i.e. your C++ code), but take up GPU memory. OpenGL doesn't make it very easy to manage these resources, so it's most likely that they're being created but not deleted from your C++ code. For example, it might create a new VBO per frame but never delete the old VBOs.&#xD;&#xA;&#xD;&#xA;2. I've never used it for this purpose, but if you're on Windows I'd suggest RenderDoc as your first stop. It's not specifically designed for debugging source - it intercepts GL and DX calls so you can see how the application is using the library even if you don't have the source - so it won't point you to the offending line of code, but it does show you what resources are being created and when, so it should at least tell you *what* is being leaked and how often. It might even be that this is enough information is enough for you to guess the rest, or that the easiest way to continue after this is to do something by hand (e.g. printing `__FILE__` and `__LINE__` every time such a resource is created).&#xD;&#xA;&#xD;&#xA;Sorry this is a bit of a half-answer but it's too big for a comment. I hope it gives you a good starting point at least." ContentLicense="CC BY-SA 3.0" />
  <row Id="11654" PostHistoryTypeId="4" PostId="4882" RevisionGUID="e35489ea-32b5-4704-93c4-1631d870c495" CreationDate="2017-03-20T20:31:51.247" UserId="231" Comment="Remove request for off site resources from title to avoid question being closed as off topic (as that is not the bulk of the question)" Text="How can I chase down VRAM &amp; GTT memory leaks?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11655" PostHistoryTypeId="5" PostId="4880" RevisionGUID="7faac076-13fe-4269-b622-72d81afc885d" CreationDate="2017-03-20T20:41:37.180" UserId="231" Comment="Minor typos" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, it suggests a way to set up up a Phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are a bit off. This could be from somewhere else in the code of course, but I'd rather know for sure.&#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curious about:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment I'm sending these matrices:&#xD;&#xA; &#xD;&#xA;    view*model //ModelViewMatrix;&#xD;&#xA;    transpose(inverse(model))) //NormalMatrix;&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;The shader &quot;works&quot;, but I cant get the lighting direction right&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11656" PostHistoryTypeId="5" PostId="4878" RevisionGUID="d53e89e2-6d24-4c39-9c06-7ac95ec56fdc" CreationDate="2017-03-20T22:12:24.587" UserId="5506" Comment="adding more precision" Text="I'm working on my own engine and I'm struggling to find any techniques that give okay-ish reflections in realtime on dynamic scene.&#xD;&#xA;So far the only technique I found that work in real time on dynamic scene is SSR but it's really heavy and have a lot of bias.&#xD;&#xA;&#xD;&#xA;The idea of having multiple cubemaps and updating them in real time crossed my mind but because that mean re-rasterising the scene that also mean that every cubemap updated in realtime is a shadow casting that I can't do.&#xD;&#xA;&#xD;&#xA;So my question is: is there another technique other than reflection probe (cubemap) or Screen Space Reflections ?&#xD;&#xA;&#xD;&#xA;The artstyle of the game where the engine will be used is based on a lot of &quot;almost mirror&quot; reflections and it's not PBR.&#xD;&#xA;&#xD;&#xA;[Edit]&#xD;&#xA;To be a bit more precise with what I'm searching:&#xD;&#xA;&#xD;&#xA; - I do not need more than one bounce.&#xD;&#xA; - I do not want any baking that cannot be done at &quot;loading time&quot;.&#xD;&#xA; - I prefer if the technique work with a per-pixel normal but if you&#xD;&#xA;   know a technique that work with a per-vertex normal I am also open.&#xD;&#xA; - I am open to techniques that only work in specific cases (like tiny&#xD;&#xA;   scene, deferred rendering only etc...) as long as it meet other&#xD;&#xA;   requirements.&#xD;&#xA; - If your technique is a feature of a global illumination technique I am&#xD;&#xA;   also open but I would prefer if it work stand alone.&#xD;&#xA; - If it can easily support GGX it's better but not required.&#xD;&#xA; - Inaccuracy is not a problem as long as it is predictable by the&#xD;&#xA;   artist&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11657" PostHistoryTypeId="2" PostId="4884" RevisionGUID="628c9b7c-580b-41ab-8fd9-aa53df56afc2" CreationDate="2017-03-21T01:22:30.937" UserId="6255" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(model)))&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // light position: vec4(0,0,0,1); &#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return LightIntensity * ( Ka + Kd * max( dot(s, n), 0.0 ) +  Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0); //phong last?&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldnt the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesnt just come from the wrong spot, but it also doesnt change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesnt come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however. Any idea what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11658" PostHistoryTypeId="1" PostId="4884" RevisionGUID="628c9b7c-580b-41ab-8fd9-aa53df56afc2" CreationDate="2017-03-21T01:22:30.937" UserId="6255" Text="Why is my ads shader not rendering light direction correctly? opengl/c++" ContentLicense="CC BY-SA 3.0" />
  <row Id="11659" PostHistoryTypeId="3" PostId="4884" RevisionGUID="628c9b7c-580b-41ab-8fd9-aa53df56afc2" CreationDate="2017-03-21T01:22:30.937" UserId="6255" Text="|opengl|glsl|glm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11660" PostHistoryTypeId="5" PostId="4884" RevisionGUID="02060a6c-41f5-4210-8e3f-9c74f77b7686" CreationDate="2017-03-21T01:28:25.057" UserId="6255" Comment="deleted 14 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(model)))&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // light position: vec4(0,0,0,1); &#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return LightIntensity * ( Ka + Kd * max( dot(s, n), 0.0 ) +  Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldnt the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesnt just come from the wrong spot, but it also doesnt change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesnt come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however. Any idea what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11661" PostHistoryTypeId="5" PostId="4884" RevisionGUID="2167713e-c633-49fd-b1c6-7edb3f03a1b3" CreationDate="2017-03-21T01:34:57.673" UserId="6255" Comment="added 40 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(model)))&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // light position: vec4(0,0,0,1); &#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldnt the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesnt just come from the wrong spot, but it also doesnt change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesnt come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however. Any idea what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11662" PostHistoryTypeId="4" PostId="4884" RevisionGUID="5b74eff0-0117-4692-add1-03d38b3b3ed2" CreationDate="2017-03-21T01:45:55.197" UserId="6255" Comment="edited title" Text="My (ads) shader doesn't render the light direction correctly opengl/c++/glsl" ContentLicense="CC BY-SA 3.0" />
  <row Id="11663" PostHistoryTypeId="5" PostId="4884" RevisionGUID="d726668d-911e-4f15-b356-780e3b69f3fe" CreationDate="2017-03-21T04:03:53.977" UserId="6255" Comment="added 174 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(model)))&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // light position: vec4(0,0,0,1); &#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldnt the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesnt just come from the wrong spot, but it also doesnt change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesnt come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however.&#xD;&#xA;&#xD;&#xA;So, the diffuse value is calculated by getting the dot(s,n), where s is (lightposition-position), and position is (view * model * vertex_position). But like you can see, the results are not as expected&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11664" PostHistoryTypeId="2" PostId="4885" RevisionGUID="59fca961-acb3-401d-b1f0-9ae06c0e26de" CreationDate="2017-03-21T07:35:21.053" UserId="4908" Text="It seems to me, to be that your different positions and normals are not in the same space. Having them in the same space is important because else it might think the normal is pointing left while it shpuld point to the right.&#xD;&#xA;&#xD;&#xA;If you don't know what I mean with space in this context it's basically a coordinate system. Think about a grid, grid A. On grid A you have a point. Then you have another grid, grid B. You place grid A on grid B. If you move grid A around, the point on grid A does not move relative to grid A. It does however move relative to grid B, so they are different spaces. Hope that clarifies it for you, if not I am so sorry.&#xD;&#xA;&#xD;&#xA;You have a few coordinate spaces.&#xD;&#xA;Local : This is the vertex locations relative to the model position.&#xD;&#xA;World: This is the location relative to the actual world origin.&#xD;&#xA;View: This is the location relative to the camera.&#xD;&#xA;&#xD;&#xA;You have the light position, vertex position and normal.&#xD;&#xA;Light position is in world space.&#xD;&#xA;Normal is in world space, since you multiplied it with a model matrix making it go from local to world.&#xD;&#xA;Vertex position is in view space, since you put it to world space with the model matrix and then to view space with the view matrix.&#xD;&#xA;&#xD;&#xA;Do you see that you have one of the three variables in a different space?&#xD;&#xA;I have a strong feeling this is the problem and if you do not multiply the vertex position with the view matrix, in the vertex shader, this should be fixed.&#xD;&#xA;&#xD;&#xA;I hope that this helps you and good luck!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11665" PostHistoryTypeId="5" PostId="4885" RevisionGUID="46f9ef85-ae66-4529-83bc-9c4ab43b9131" CreationDate="2017-03-21T08:05:40.443" UserId="231" Comment="Typo and formatting" Text="It seems to me, to be that your different positions and normals are not in the same space. Having them in the same space is important because else it might think the normal is pointing left while it should point to the right.&#xD;&#xA;&#xD;&#xA;If you don't know what I mean with space in this context it's basically a coordinate system. Think about a grid, grid A. On grid A you have a point. Then you have another grid, grid B. You place grid A on grid B. If you move grid A around, the point on grid A does not move relative to grid A. It does however move relative to grid B, so they are different spaces. Hope that clarifies it for you, if not I am so sorry.&#xD;&#xA;&#xD;&#xA;You have a few coordinate spaces:&#xD;&#xA;&#xD;&#xA;- **Local**: This is the vertex locations relative to the model position.&#xD;&#xA;- **World**: This is the location relative to the actual world origin.&#xD;&#xA;- **View**: This is the location relative to the camera.&#xD;&#xA;&#xD;&#xA;You have the light position, vertex position and normal:&#xD;&#xA;&#xD;&#xA;- Light position is in world space.&#xD;&#xA;- Normal is in world space, since you multiplied it with a model matrix making it go from local to world.&#xD;&#xA;- Vertex position is in view space, since you put it to world space with the model matrix and then to view space with the view matrix.&#xD;&#xA;&#xD;&#xA;Do you see that you have one of the three variables in a different space?&#xD;&#xA;I have a strong feeling this is the problem and if you do not multiply the vertex position with the view matrix, in the vertex shader, this should be fixed.&#xD;&#xA;&#xD;&#xA;I hope that this helps you and good luck!" ContentLicense="CC BY-SA 3.0" />
  <row Id="11666" PostHistoryTypeId="5" PostId="4884" RevisionGUID="8afce714-eb15-4251-a2de-bedb3c88cfcb" CreationDate="2017-03-21T08:41:11.000" UserId="6255" Comment="added 46 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model ||this was the error, should be model only ;)&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(model)))&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // light position: vec4(0,0,0,1); &#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldnt the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesnt just come from the wrong spot, but it also doesnt change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesnt come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however.&#xD;&#xA;&#xD;&#xA;So, the diffuse value is calculated by getting the dot(s,n), where s is (lightposition-position), and position is (view * model * vertex_position). But like you can see, the results are not as expected&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11667" PostHistoryTypeId="5" PostId="4880" RevisionGUID="cf8953ac-f2cf-4c49-8a84-3754b4a4fb57" CreationDate="2017-03-21T08:46:01.783" UserId="6255" Comment="added 40 characters in body" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, it suggests a way to set up up a Phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are a bit off. This could be from somewhere else in the code of course, but I'd rather know for sure.&#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curious about:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment I'm sending these matrices:&#xD;&#xA; &#xD;&#xA;    model //ModelViewMatrix; //this was wrong (view*model is wrong space)&#xD;&#xA;    transpose(inverse(model))) //NormalMatrix;&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;The shader &quot;works&quot;, but I cant get the lighting direction right&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Solved: It works after I send model matrix without multiplying with view. This will put &quot;position&quot; in view space, when I should be in world space&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11671" PostHistoryTypeId="2" PostId="4887" RevisionGUID="16d77d3b-d6c9-4954-afa9-5c6520511772" CreationDate="2017-03-21T11:10:39.660" UserId="2041" Text="When you offline-render an animation, you take all the 3D information and turn it into a video file: a sequence of 2D images. The video file doesn't have any of the 3D information. A 3D game doesn't work this way because when you run the game, the 3D information needs to be present.&#xD;&#xA;&#xD;&#xA;It's quite common to use 3D models for making 2D games. Donkey Kong was a very early example of this: all the characters and backgrounds were modelled and animated in 3D, then rendered to 2D animations. These 2D animations were then used as sprites in the game. It allowed the sprites to look a lot more impressive than could be achieved with hand-made 2D sprites, using 3D ray-tracing techniques that weren't usable in real-time on the available hardware.&#xD;&#xA;&#xD;&#xA;More recently than that, it was common for cutscenes in 3D games to be pre-rendered videos. Cutscenes don't need to be interactive like the rest of the game. Using a pre-rendered video means that the artists can use expensive, non-real-time techniques to make the cutscenes look better than the interactive parts of the game can look. This isn't so popular nowadays: video files are big, and real-time rendering is a lot better than it used to be, so doing the cutscenes in real-time gives you lighting and shading that's almost as good, without having a fixed-resolution video file with compression artefacts.&#xD;&#xA;&#xD;&#xA;That said, there are some graphics techniques that use an offline pre-processing step to allow you to use techniques that wouldn't be possible in real-time (on the target hardware). The simplest example is texture compression: the compression is typically quite expensive, but it makes the textures use less memory, so you can have higher-quality textures.&#xD;&#xA;&#xD;&#xA;If your scene has static lighting, it's common to *bake* lighting including global illumination and shadows into a texture, or into static light probes. This replaces the expensive lighting calculations with a simple texture look-up at run-time.&#xD;&#xA;&#xD;&#xA;However, at the stage you're at, you shouldn't start worrying about any of these techniques yet. All of the rendering you'll be doing will be at run-time, so you need to optimize it to run at the target frame-rate on your target hardware." ContentLicense="CC BY-SA 3.0" />
  <row Id="11674" PostHistoryTypeId="2" PostId="4888" RevisionGUID="7d402e44-5b96-488b-9eb7-7c2537c3d9ff" CreationDate="2017-03-21T12:08:01.220" UserId="6255" Text="I was passing the wrong matrix. When it comes to these things, you have to think in terms of spaces, and I was multiplying the view matrix and the model matrix, which was putting the vertice position in view space, rather than world space (the models identity). &#xD;&#xA;&#xD;&#xA;The solution was passing only the models identity matrix, as my ModelViewMatrix. Which is confusing, since the name is misleading, but its right, since every  value related to lighting in the shader, ends up being calculated in world space.&#xD;&#xA;&#xD;&#xA;So, for me, ModelViewMatrix = identity matrix (aka spin, translation), not view*model, wich would put it in view space. &#xD;&#xA;&#xD;&#xA;I hope that helps anyone else facing the same/similar problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="11675" PostHistoryTypeId="5" PostId="4815" RevisionGUID="afed9026-5cba-477e-8609-3fa46c576802" CreationDate="2017-03-21T12:13:46.197" UserId="6023" Comment="added 14 characters in body" Text="Although this is not the solution I was looking for initially, the figure below is the tightest filling without overlaps of the plane with pentagons that I could come up with so far. I haven't found a recursive algorithm yet. I think it's not possible or it is too complicated to code. &#xD;&#xA;&#xD;&#xA;[![pentagon-rhombus lattice][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Below is the python script:&#xD;&#xA;&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    def pentagon (Xorig, Yorig, theta):&#xD;&#xA;        Ind = np.arange(N+1)&#xD;&#xA;        X = np.cos(Ind*2*np.pi/N+theta)+Xorig&#xD;&#xA;        Y = np.sin(Ind*2*np.pi/N+theta)+Yorig&#xD;&#xA;        plt.fill(X, Y, 'r-')&#xD;&#xA;&#xD;&#xA;    plt.axes().set_aspect ('equal')&#xD;&#xA;    r = 2*np.cos(np.pi/5)&#xD;&#xA;    plt.xlim(-2, 30)&#xD;&#xA;    plt.ylim(-2, 30)&#xD;&#xA;    Lx = np.cos(np.pi/10)&#xD;&#xA;    for j in np.arange(0, 10):&#xD;&#xA;        Xorig = (j%2)*Lx*np.ones(N+1)&#xD;&#xA;        Yorig = j*(1+2*np.cos(np.pi/5)+np.cos(2*np.pi/5))*np.ones(N+1)&#xD;&#xA;        theta = np.pi/(2*N)&#xD;&#xA;        sign = 1&#xD;&#xA;        for i in np.arange(1, 32):&#xD;&#xA;            pentagon(Xorig, Yorig, theta)&#xD;&#xA;            Xorig += r*np.cos(3*theta)*np.ones(N+1)&#xD;&#xA;            Yorig += r*np.sin(3*theta)*np.ones(N+1)&#xD;&#xA;            sign *= -1&#xD;&#xA;            theta = sign*np.pi/(2*N)&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(&quot;pentagonLattice.png&quot;, bbox_inches='tight')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;Also I haven't found yet a simple way to make a quasi-periodic tiling of the plane with only pentagons and rhombi yet. I did find out though how to fill the plane with pentagons and rhombi with a center with 5-fold symmetry.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here's a python script with a recursive algorithm (though not optimized):&#xD;&#xA;&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    # The golden ratio&#xD;&#xA;    phi = (1.0+np.sqrt(5.0))/2&#xD;&#xA;    # angle increment&#xD;&#xA;    theta0 = np.pi/5&#xD;&#xA;    LEFT = 0&#xD;&#xA;    RIGHT = 1&#xD;&#xA;    # fill plot a pentagon with center at (Xorig, Yorig) and orientation theta&#xD;&#xA;    def pentagon (Xorig, Yorig, theta):&#xD;&#xA;        Ind = np.arange(N+1)&#xD;&#xA;        X = np.cos(Ind*2*np.pi/N+theta)+Xorig&#xD;&#xA;        Y = np.sin(Ind*2*np.pi/N+theta)+Yorig&#xD;&#xA;        plt.fill(X, Y, 'r-')&#xD;&#xA;    # At each step three edges are generated&#xD;&#xA;    # and two recursive calls are made&#xD;&#xA;    def stepSplit (previousPoint, previousTurn, theta, nIter):&#xD;&#xA;        if nIter == 0:&#xD;&#xA;            return&#xD;&#xA;        if previousTurn == RIGHT:&#xD;&#xA;            # Turn left &#xD;&#xA;            theta = theta+theta0&#xD;&#xA;        elif previousTurn == LEFT:&#xD;&#xA;            # turn right &#xD;&#xA;            theta = theta-theta0&#xD;&#xA;        nextPoint = previousPoint + phi*np.array([np.cos(theta), np.sin(theta)])&#xD;&#xA;        X, Y = zip(previousPoint, nextPoint)&#xD;&#xA;        pentagon (nextPoint[0], nextPoint[1], theta)&#xD;&#xA;        # Update&#xD;&#xA;        previousPoint[:] = nextPoint[:]&#xD;&#xA;        # Bifurcation&#xD;&#xA;        # Turn left &#xD;&#xA;        theta1 = theta+theta0&#xD;&#xA;&#xD;&#xA;        nextPoint = previousPoint + phi*np.array([np.cos(theta1), np.sin(theta1)])&#xD;&#xA;        X, Y = zip(previousPoint, nextPoint)&#xD;&#xA;        pentagon (nextPoint[0], nextPoint[1], theta1)&#xD;&#xA;        stepSplit(nextPoint, LEFT, theta1, nIter-1)&#xD;&#xA;&#xD;&#xA;        # Turn right &#xD;&#xA;        theta1 = theta-theta0&#xD;&#xA;        nextPoint = previousPoint + phi*np.array([np.cos(theta1), np.sin(theta1)])&#xD;&#xA;        X, Y = zip(previousPoint, nextPoint)&#xD;&#xA;        pentagon (nextPoint[0], nextPoint[1], theta1)&#xD;&#xA;        stepSplit(nextPoint, RIGHT, theta1, nIter-1)&#xD;&#xA;&#xD;&#xA;    # fill plot pentagons&#xD;&#xA;    # Central pentagon&#xD;&#xA;    pentagon (0.0, 0.0, 0.0)&#xD;&#xA;    for i in [1, 3, 5, 7, 9]:&#xD;&#xA;        stepSplit (np.array([0.0, 0.0]), -1, i*theta0, 5)&#xD;&#xA;&#xD;&#xA;    for i in [0, 2, 4, 6, 8]:&#xD;&#xA;        theta = i*np.pi/5&#xD;&#xA;        x0 = phi*(1.0+2*np.cos(np.pi/5))*np.cos(theta)&#xD;&#xA;        y0 = phi*(1.0+2*np.cos(np.pi/5))*np.sin(theta)&#xD;&#xA;        pentagon (x0, y0, theta0)&#xD;&#xA;        stepSplit (np.array([x0, y0]), -1, theta, 4)&#xD;&#xA;&#xD;&#xA;    plt.axes().set_aspect ('equal')&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(&quot;pentagonLattice4.png&quot;, bbox_inches='tight')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TLnKi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/djejd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11677" PostHistoryTypeId="5" PostId="4394" RevisionGUID="e86c9a2c-f227-403c-98fc-2877b029bc9a" CreationDate="2017-03-21T15:05:52.740" UserDisplayName="user5681" Comment="deleted 5 characters in body" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, RGB.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations, with the exception of $F$, were extracted from the original paper. $F$, also known as the [Schlick's approximation][3], is an efficient and less accurate approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][4] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D_{new} = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr_{new}(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{D_{new}FG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;As pointed out by [PeteUK][5], the authorship of the Fresnel formulation presented in the original text of my question was wrongly attributed to Cook and Torrance. The Fresnel formulation used above is actually known as the [Schlick's approximation][3] and is named after Christophe Schlick. The original text of the question was modified accordingly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Schlick's_approximation&#xD;&#xA;  [4]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [5]: http://computergraphics.stackexchange.com/q/4771/5681" ContentLicense="CC BY-SA 3.0" />
  <row Id="11678" PostHistoryTypeId="5" PostId="4877" RevisionGUID="622ea134-5d0b-40ea-bc68-5287b738ab33" CreationDate="2017-03-21T17:00:51.580" UserDisplayName="user5681" Comment="added 1712 characters in body" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms (for conductors and dielectrics):&#xD;&#xA;&#xD;&#xA;**For conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**For dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;In the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I've found a potential answer to this question and, despite missing technical soundness (that's why I've just added as an update and not as an answer), I am posting it here in the case someone may be interested or may have comments to add. &#xD;&#xA;&#xD;&#xA;According to this [OSL Shader][3], at least the complex Fresnel term (for conductors), in the context of an RGB-based path tracer, can be evaluated by simply substituting $\eta$ and $\kappa$ by those values corresponding to the R, G and B representative wavelengths.&#xD;&#xA;&#xD;&#xA;For instance, suppose that our representative wavelengths for R, G and B components are, respectively, 0.65$\mu$m, 0.55$\mu$m and 0.45$\mu$m, and that we want to render the gold material. The $\eta$ and $\kappa$ values of gold, for our representative wavelengths, can be obtained from [https://refractiveindex.info][2], and will be:&#xD;&#xA;&#xD;&#xA;$$\eta_{gold} = ( 0.15557, 0.42415, 1.3831 )$$&#xD;&#xA;&#xD;&#xA;$$\kappa_{gold} = ( 3.6024, 2.4721, 1.9155 )$$ &#xD;&#xA;&#xD;&#xA;Now it is just a matter of evaluating the Fresnel term, with the above equation, such that:&#xD;&#xA;&#xD;&#xA;$$Fresnel[i] = F(\eta[i],\kappa[i], \theta)$$&#xD;&#xA;&#xD;&#xA;Folowing this procedure, I've obtained the following results (compared to the [Mitsuba][4], which is assumed to be correct):&#xD;&#xA;&#xD;&#xA;[![Gold. Left: Mitsuba. Right: My renderer.][5]][5]&#xD;&#xA;&#xD;&#xA;Above image: Gold material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Above image: Copper material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info&#xD;&#xA;  [3]: https://docs.chaosgroup.com/display/OSLShaders/Complex+Fresnel+shader&#xD;&#xA;  [4]: http://www.mitsuba-renderer.org/&#xD;&#xA;  [5]: https://i.stack.imgur.com/mSf98.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/EfU5C.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11682" PostHistoryTypeId="5" PostId="4877" RevisionGUID="bfc9b19b-1cef-455b-aa27-25fd7225cad5" CreationDate="2017-03-21T18:47:51.130" UserDisplayName="user5681" Comment="added 942 characters in body" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms:&#xD;&#xA;&#xD;&#xA;**Fresnel term for conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**Fresnel term for dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;For both equations, the resulting Fresnel reflectance is obtained with:&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;In the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I've found a potential answer to the question and, despite missing technical soundness (that's why I've just added it as an update and not as the actual answer), I am posting it here in the case someone may be interested or may have comments to add. &#xD;&#xA;&#xD;&#xA;According to this [OSL Shader][3], at least the complex Fresnel term (for conductors), in the context of an RGB-based path tracer, can be evaluated by simply substituting $\eta$ and $\kappa$ by those values corresponding to the R, G and B &quot;representative&quot; wavelengths. Since R, G and B are not narrow spikes on the electromagnetic spectrum, the &quot;representative&quot; wavelength may be a little different from one implementation to another. I've seen that the most common values for these representative wavelengths are 0.65$\mu$m for Red, 0.55$\mu$m for Green and 0.45$\mu$m for Blue.&#xD;&#xA;&#xD;&#xA;For instance, suppose that we want to render the gold material. The $\eta$ and $\kappa$ values of gold, for our representative wavelengths (0.65$\mu$m, 0.55$\mu$m and 0.45$\mu$m), can be obtained from [https://refractiveindex.info][2], and will be:&#xD;&#xA;&#xD;&#xA;$$\eta_{gold} = ( 0.15557, 0.42415, 1.3831 )$$&#xD;&#xA;&#xD;&#xA;$$\kappa_{gold} = ( 3.6024, 2.4721, 1.9155 )$$ &#xD;&#xA;&#xD;&#xA;Now, it is just a matter of evaluating the Fresnel reflectance for each color channel:&#xD;&#xA;&#xD;&#xA;$$Fresnel_{Red} = F(\eta[0],\kappa[0], \theta)$$&#xD;&#xA;$$Fresnel_{Green} = F(\eta[1],\kappa[1], \theta)$$&#xD;&#xA;$$Fresnel_{Blue} = F(\eta[2],\kappa[2], \theta)$$&#xD;&#xA;&#xD;&#xA;I have used this complex Fresnel equation within my Cook-Torrance BRDF, whose formulation can be seen [here][4], and I've obtained the following results (I've compared them to reference images rendered with [Mitsuba][5]):&#xD;&#xA;&#xD;&#xA;[![Gold. Left: Mitsuba. Right: My renderer.][6]][6]&#xD;&#xA;&#xD;&#xA;Above image: Gold material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Above image: Copper material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;The images generated by my path tracer are noisier because it uses only BRDF importance sampling. With respect to copper, the images are, at least visually, very close. With respect to gold, they look a little bit different. This might be because the &quot;representative wavelengths&quot; used to represent the R,G and B color channels are different from one renderer to another, &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info&#xD;&#xA;  [3]: https://docs.chaosgroup.com/display/OSLShaders/Complex+Fresnel+shader&#xD;&#xA;  [4]: http://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/&#xD;&#xA;  [6]: https://i.stack.imgur.com/mSf98.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/EfU5C.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11683" PostHistoryTypeId="5" PostId="4877" RevisionGUID="7b775652-ce30-4ca9-b122-c3706ffbc681" CreationDate="2017-03-21T19:02:51.680" UserDisplayName="user5681" Comment="added 198 characters in body" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms:&#xD;&#xA;&#xD;&#xA;**Fresnel term for conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**Fresnel term for dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;For both equations, the resulting Fresnel reflectance is obtained with:&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;In the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I've found a potential answer to the question and, despite missing technical soundness (that's why I've just added it as an update and not as the actual answer), I am posting it here in the case someone may be interested or may have comments to add. &#xD;&#xA;&#xD;&#xA;According to this [OSL Shader][3], at least the complex Fresnel term (for conductors), in the context of an RGB-based path tracer, can be evaluated by simply substituting $\eta$ and $\kappa$ by those values corresponding to the R, G and B &quot;representative&quot; wavelengths. Since R, G and B are not narrow spikes on the electromagnetic spectrum, the &quot;representative&quot; wavelength may be a little different from one implementation to another. I've seen that the most common values for these representative wavelengths are 0.65$\mu$m for Red, 0.55$\mu$m for Green and 0.45$\mu$m for Blue.&#xD;&#xA;&#xD;&#xA;For instance, suppose that we want to render the gold material. The $\eta$ and $\kappa$ values of gold, for our representative wavelengths (0.65$\mu$m, 0.55$\mu$m and 0.45$\mu$m), can be obtained from [https://refractiveindex.info][2], and will be:&#xD;&#xA;&#xD;&#xA;$$\eta_{gold} = ( 0.15557, 0.42415, 1.3831 )$$&#xD;&#xA;&#xD;&#xA;$$\kappa_{gold} = ( 3.6024, 2.4721, 1.9155 )$$ &#xD;&#xA;&#xD;&#xA;Now, it is just a matter of evaluating the Fresnel reflectance for each color channel:&#xD;&#xA;&#xD;&#xA;$$Fresnel_{Red} = F(\eta[0],\kappa[0], \theta)$$&#xD;&#xA;$$Fresnel_{Green} = F(\eta[1],\kappa[1], \theta)$$&#xD;&#xA;$$Fresnel_{Blue} = F(\eta[2],\kappa[2], \theta)$$&#xD;&#xA;&#xD;&#xA;I have used this complex Fresnel equation within my Cook-Torrance BRDF, whose formulation can be seen [here][4], and I've obtained the following results (I've compared them to reference images rendered with [Mitsuba][5]):&#xD;&#xA;&#xD;&#xA;[![Gold. Left: Mitsuba. Right: My renderer.][6]][6]&#xD;&#xA;&#xD;&#xA;Above image: Gold material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Above image: Copper material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;The images generated by my path tracer are noisier because it uses only BRDF importance sampling. With respect to copper, the images are, at least visually, almost identical. With respect to gold, colors are slightly different. I have made some experiments, and observed that very small changes on the values of the &quot;representative wavelengths&quot; might have significant impact on the final color. Thus, the color difference regarding gold rendering would be attributed to a eventual difference regarding the &quot;representative wavelengths&quot; for R,G and B used by each renderer.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info&#xD;&#xA;  [3]: https://docs.chaosgroup.com/display/OSLShaders/Complex+Fresnel+shader&#xD;&#xA;  [4]: http://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/&#xD;&#xA;  [6]: https://i.stack.imgur.com/mSf98.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/EfU5C.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11684" PostHistoryTypeId="2" PostId="4890" RevisionGUID="6f75355f-13a8-452c-9500-0587564b2804" CreationDate="2017-03-21T20:14:58.007" UserId="6282" Text="I am building my own graphic engine.&#xD;&#xA;&#xD;&#xA;My depth texture is significantly smaller than that of the screen.&#xD;&#xA;&#xD;&#xA;The low resolution depth map results in rigid shadow like this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am sure this is a common issue.&#xD;&#xA;&#xD;&#xA;I would like to learn &quot;go to&quot; technique to resolve this issue.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kniJw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11685" PostHistoryTypeId="1" PostId="4890" RevisionGUID="6f75355f-13a8-452c-9500-0587564b2804" CreationDate="2017-03-21T20:14:58.007" UserId="6282" Text="In forward rendering what's the go to technique to smooth out rigid shadow due to low resolution shadowmap texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11686" PostHistoryTypeId="3" PostId="4890" RevisionGUID="6f75355f-13a8-452c-9500-0587564b2804" CreationDate="2017-03-21T20:14:58.007" UserId="6282" Text="|shadow|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11687" PostHistoryTypeId="5" PostId="4877" RevisionGUID="f5696adb-0428-4684-b009-196d748deb80" CreationDate="2017-03-21T23:45:08.060" UserDisplayName="user5681" Comment="added 64 characters in body" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms:&#xD;&#xA;&#xD;&#xA;**Fresnel term for conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**Fresnel term for dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;For both equations, the resulting Fresnel reflectance is obtained with:&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;In the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I've found a potential answer to the question and, despite missing technical soundness (that's why I've just added it as an update and not as the actual answer), I am posting it here in the case someone may be interested or may have comments to add. &#xD;&#xA;&#xD;&#xA;According to this [OSL Shader][3], at least the complex Fresnel term (for conductors), in the context of an RGB-based path tracer, can be evaluated by simply substituting $\eta$ and $\kappa$ by those values corresponding to the R, G and B &quot;representative&quot; wavelengths. Since R, G and B are not narrow spikes on the electromagnetic spectrum, the &quot;representative&quot; wavelength may be a little different from one implementation to another. I've seen that the most common values for these representative wavelengths are 0.65$\mu$m for Red, 0.55$\mu$m for Green and 0.45$\mu$m for Blue.&#xD;&#xA;&#xD;&#xA;For instance, suppose that we want to render the gold material. The $\eta$ and $\kappa$ values of gold, for our representative wavelengths (0.65$\mu$m, 0.55$\mu$m and 0.45$\mu$m), can be obtained from [https://refractiveindex.info][2], and will be:&#xD;&#xA;&#xD;&#xA;$$\eta_{gold} = ( 0.15557, 0.42415, 1.3831 )$$&#xD;&#xA;&#xD;&#xA;$$\kappa_{gold} = ( 3.6024, 2.4721, 1.9155 )$$ &#xD;&#xA;&#xD;&#xA;Now, it is just a matter of evaluating the Fresnel reflectance for each color channel:&#xD;&#xA;&#xD;&#xA;$$Fresnel_{Red} = F(\eta[0],\kappa[0], \theta)$$&#xD;&#xA;$$Fresnel_{Green} = F(\eta[1],\kappa[1], \theta)$$&#xD;&#xA;$$Fresnel_{Blue} = F(\eta[2],\kappa[2], \theta)$$&#xD;&#xA;&#xD;&#xA;I have used this complex Fresnel equation within my Cook-Torrance BRDF, whose formulation can be seen [here][4], and I've obtained the following results (I've compared them to reference images rendered with [Mitsuba][5]):&#xD;&#xA;&#xD;&#xA;[![Gold. Left: Mitsuba. Right: My renderer.][6]][6]&#xD;&#xA;&#xD;&#xA;Above image: Gold material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Above image: Copper material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;The images generated by my path tracer are noisier because it uses only BRDF importance sampling. With respect to copper, the images are, at least visually, almost identical. With respect to gold, colors are slightly different. I have made some experiments, and observed that very small changes on the values of the &quot;representative wavelengths&quot; might have significant impact on the final color. Thus, the color difference regarding the rendering of the gold material could be eventually attributed to differences regarding the &quot;representative&quot; wavelengths used by each renderer for R,G and B.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info&#xD;&#xA;  [3]: https://docs.chaosgroup.com/display/OSLShaders/Complex+Fresnel+shader&#xD;&#xA;  [4]: http://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/&#xD;&#xA;  [6]: https://i.stack.imgur.com/mSf98.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/EfU5C.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11691" PostHistoryTypeId="2" PostId="4891" RevisionGUID="40624f01-120c-4256-a901-b74d61d350c8" CreationDate="2017-03-22T10:01:56.727" UserId="6291" Text="Using a shader that works like Phong, what would be the difference between painted Metal and plastic?&#xD;&#xA;&#xD;&#xA;I seem to remember reading in books years ago, that I no longer have access to, the following:&#xD;&#xA;&#xD;&#xA;- Specular color for painted metal is same color as the paint.&#xD;&#xA;- Specular color for plastic is always white.&#xD;&#xA;- Ambient for metal should be darker than for plastic.&#xD;&#xA;&#xD;&#xA;This also seems to correlate with what I see when I observe objects (in real world)&#xD;&#xA;&#xD;&#xA;But I tried to verify this also by checking the Internet, and found conflicting versions, some said the complete opposite.&#xD;&#xA;&#xD;&#xA;So what is true?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11692" PostHistoryTypeId="1" PostId="4891" RevisionGUID="40624f01-120c-4256-a901-b74d61d350c8" CreationDate="2017-03-22T10:01:56.727" UserId="6291" Text="Phong: Real-time rendering of Metal and Plastic Materials" ContentLicense="CC BY-SA 3.0" />
  <row Id="11693" PostHistoryTypeId="3" PostId="4891" RevisionGUID="40624f01-120c-4256-a901-b74d61d350c8" CreationDate="2017-03-22T10:01:56.727" UserId="6291" Text="|lighting|real-time|shading|specular|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11694" PostHistoryTypeId="5" PostId="4891" RevisionGUID="f4c0733b-e073-4fab-bdcd-fc9aad52d6af" CreationDate="2017-03-22T10:38:21.567" UserId="6291" Comment="added 4 characters in body" Text="Using a shader that works like Phong, what would be the difference between painted Metal and plastic?&#xD;&#xA;&#xD;&#xA;I seem to remember reading in books years ago, that I no longer have access to, the following:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- Specular color for painted metal is same color as the paint.&#xD;&#xA;- Specular color for plastic is always white.&#xD;&#xA;- Ambient for metal should be darker than for plastic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This also seems to correlate with what I see when I observe objects (in real world)&#xD;&#xA;&#xD;&#xA;But I tried to verify this also by checking the Internet, and found conflicting versions, some said the complete opposite.&#xD;&#xA;&#xD;&#xA;So what is true?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11695" PostHistoryTypeId="2" PostId="4892" RevisionGUID="debb5577-307e-4133-810d-286b1c68fd3c" CreationDate="2017-03-22T10:59:43.597" UserId="2041" Text="Diffuse colours on materials typically come from within the material, while the specular colour is from the very surface. Coloured plastic materials are made by embedding particles of dye inside a colourless medium, so the diffuse colour is the colour of the dye, while the specular colour is white from the colourless surface. With metals, all of the reflection is at the surface, so the diffuse and specular colours are the same.&#xD;&#xA;&#xD;&#xA;There are many different kinds of paint, but most commonly they're made like plastics: putting dye particles inside a white or colourless medium. Emulsion, acrylic, and enamel paints are all made this way. For this reason, painted or varnished metal surfaces have white specular as if they were plastic. There are some kinds of paint (metallic paints being the most obvious example) that aren't made this way, so it's not always true.&#xD;&#xA;&#xD;&#xA;Ambient doesn't correspond to a physical property of the material: it's a cheap substitute for global illumination. It represents all of the indirect light that falls on the shading point and is reflected in the viewing direction. There's no physically correct way to set it: you should just do what looks best in your scene. That said, I'd offer a rule of thumb that shinier objects probably want less ambient, because less of the indirect light is going to be reflected diffusely to where you can see it. However, you might consider not using ambient at all, and pointing dim *fill lights* at places that will come out too dark without indirect light." ContentLicense="CC BY-SA 3.0" />
  <row Id="11696" PostHistoryTypeId="34" PostId="4842" RevisionGUID="aa8b1283-b09b-4ee7-a83d-e9314bcb6f13" CreationDate="2017-03-22T12:07:35.900" UserId="-1" Comment="26" />
  <row Id="11697" PostHistoryTypeId="2" PostId="4893" RevisionGUID="d26e57d6-cb85-47f6-b87e-e1f90c3874a6" CreationDate="2017-03-22T12:18:41.047" UserId="6098" Text="I want to run audio FFT transformations on a GPU using, possibly, OpenCL.&#xD;&#xA;What are the best optimization strategies for:&#xD;&#xA;&#xD;&#xA;- converting audio signals to FFT;&#xD;&#xA;- transfer them to the graphics card;&#xD;&#xA;- compute those&#xD;&#xA;- return the FFT into audio signal domain&#xD;&#xA;&#xD;&#xA;if possible, i would like to do such a thing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- with minimum latency possible;&#xD;&#xA;- in real time;&#xD;&#xA;- using really big fft window sizes;&#xD;&#xA;- using really high sample rates and bit depth&#xD;&#xA;&#xD;&#xA;looking forward for your answers,&#xD;&#xA;kind regards, T.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Ever Tried. Ever Failed. No Matter. Try Again. Fail Again. Fail Better&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11698" PostHistoryTypeId="1" PostId="4893" RevisionGUID="d26e57d6-cb85-47f6-b87e-e1f90c3874a6" CreationDate="2017-03-22T12:18:41.047" UserId="6098" Text="Optimization Strategies for FFT sound transformations using GPGPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="11699" PostHistoryTypeId="3" PostId="4893" RevisionGUID="d26e57d6-cb85-47f6-b87e-e1f90c3874a6" CreationDate="2017-03-22T12:18:41.047" UserId="6098" Text="|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11700" PostHistoryTypeId="5" PostId="4893" RevisionGUID="2d76d80b-bb34-4814-b171-7c2bf3fb5b4c" CreationDate="2017-03-22T12:53:54.653" UserId="2041" Comment="This isn't an email list or a forum. Don't add signatures to your questions." Text="I want to run audio FFT transformations on a GPU using, possibly, OpenCL.&#xD;&#xA;What are the best optimization strategies for:&#xD;&#xA;&#xD;&#xA;- converting audio signals to FFT;&#xD;&#xA;- transfer them to the graphics card;&#xD;&#xA;- compute those&#xD;&#xA;- return the FFT into audio signal domain&#xD;&#xA;&#xD;&#xA;if possible, i would like to do such a thing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- with minimum latency possible;&#xD;&#xA;- in real time;&#xD;&#xA;- using really big fft window sizes;&#xD;&#xA;- using really high sample rates and bit depth" ContentLicense="CC BY-SA 3.0" />
  <row Id="11701" PostHistoryTypeId="5" PostId="4893" RevisionGUID="26fb00dc-c6c9-41c6-9694-c1988d6c3c5e" CreationDate="2017-03-22T12:54:23.400" UserId="6098" Comment="deleted 137 characters in body" Text="I want to run audio FFT transformations on a GPU using, possibly, OpenCL.&#xD;&#xA;What are the best optimization strategies for:&#xD;&#xA;&#xD;&#xA;- converting audio signals to FFT;&#xD;&#xA;- transfer them to the graphics card;&#xD;&#xA;- compute those&#xD;&#xA;- return the FFT into audio signal domain&#xD;&#xA;&#xD;&#xA;if possible, i would like to do such a thing:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- with minimum latency possible;&#xD;&#xA;- in real time;&#xD;&#xA;- using really big fft window sizes;&#xD;&#xA;- using really high sample rates and bit depth&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11702" PostHistoryTypeId="2" PostId="4894" RevisionGUID="034e6aea-3ac2-4c12-9a91-a6b04538cc3c" CreationDate="2017-03-23T02:51:41.967" UserId="3003" Text="One technique is [adaptive shadow maps](http://www.graphics.cornell.edu/pubs/2001/FFBG01.pdf) where you use a low resolution map for shadows that are rendered far away from the camera, a mid-resolution map for stuff that's in the mid range, and a high resolution map for stuff that's close." ContentLicense="CC BY-SA 3.0" />
  <row Id="11704" PostHistoryTypeId="2" PostId="4895" RevisionGUID="816b7e78-0ff0-408a-ab23-dc86aa6e7d80" CreationDate="2017-03-23T13:16:51.900" UserId="6025" Text="I'm playing around with OpenGL.  I wrote a small program to simulate a falling object.  My code looks like the following:&#xD;&#xA;&#xD;&#xA;    static GLfloat last = glfwGetTime();&#xD;&#xA;    GLfloat now = glfwGetTime();&#xD;&#xA;    GLfloat delta = now - last;&#xD;&#xA;    const GLfloat g = -9.8;&#xD;&#xA;    &#xD;&#xA;    velocity += g * delta;&#xD;&#xA;    distance += velocity * delta;&#xD;&#xA;&#xD;&#xA;now for some reason the object falls really slowly.  However, if I remove the `* delta` from the last line&#xD;&#xA;&#xD;&#xA;    distance += velocity;&#xD;&#xA;&#xD;&#xA;the simulation appears correct.  But if g = acceleration = $m/s^2$ then g * delta = $m/s$ = velocity.  Then velocity * delta = $m$, right? Where did I go wrong?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11705" PostHistoryTypeId="1" PostId="4895" RevisionGUID="816b7e78-0ff0-408a-ab23-dc86aa6e7d80" CreationDate="2017-03-23T13:16:51.900" UserId="6025" Text="animating falling object" ContentLicense="CC BY-SA 3.0" />
  <row Id="11706" PostHistoryTypeId="3" PostId="4895" RevisionGUID="816b7e78-0ff0-408a-ab23-dc86aa6e7d80" CreationDate="2017-03-23T13:16:51.900" UserId="6025" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11711" PostHistoryTypeId="2" PostId="4897" RevisionGUID="40b7a989-ac0b-44d0-a51c-9769969b647d" CreationDate="2017-03-23T16:56:42.633" UserId="110" Text="If you want a real-time solution (no baking), and only need one reflection bounce, you can try to generate (or update) a cubemap of the scene every frame, as described in this graphics study of GTA5:   &#xA;http://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study/  &#xA;  &#xA;This solution should work in general cases (be sure to handle cases when the cubemap probe would be in an object of the scene).  &#xA;   &#xA;If rendering the six faces of the cube every frame seems too heavy, you can try for example to update only one face at a time. You can then use some kind of average function when updating the faces so that the change between each frame looks smoother.  &#xA;  &#xA;It is only an idea, there are many other solutions that one can think of.  &#xA;  " ContentLicense="CC BY-SA 3.0" />
  <row Id="11712" PostHistoryTypeId="2" PostId="4898" RevisionGUID="f5b8aa27-68bf-42bc-b176-986242bfa066" CreationDate="2017-03-23T17:04:31.433" UserId="5717" Text="Percentage Closer Filtering with some amount of blur (ie. a minimum filter size in texture space) is the most basic method I know of. For example, see [GPU Gems][1]. My experience is that it is also quite robust.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="11713" PostHistoryTypeId="2" PostId="4899" RevisionGUID="695b482e-9cd7-44eb-9b8f-1ce83aef14ee" CreationDate="2017-03-23T17:11:24.093" UserId="110" Text="Assuming your code has several locations that can allocate/release GPU memory, but you don't know which one leaks.&#xA;Maybe you can try to add a GPU memory monitor to that code. &#xA;  &#xA;When GPU memory is allocated in code, insert the buffer handle that was returned, the buffer size, the function/file name (or even better, stack trace) in a globally defined array.&#xA;When GPU memory is released, remove the handle of the buffer that was released from that array.&#xA;Run the application a while and exit before it crashes. Output the contents of the array before leaving. It shows information about the GPU memory that was not released. You might see some patterns leading you to understand how to fix the &quot;leak&quot;.&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11714" PostHistoryTypeId="2" PostId="4900" RevisionGUID="6f64e51d-0730-4aa9-931d-317289ed030c" CreationDate="2017-03-23T17:18:39.640" UserId="5717" Text="1. They must define it as a surface of revolution of a line segment.&#xD;&#xA;2. From the comments, they are probably the *a* and *c* coefficients of the canonical hyperboloid equation. With a surface of revolution, *a* == *b* so no need to store *b* separately.&#xD;&#xA;3. It's clearly related to figuring out *ah* and *ch* from the line segment. I can't say more precisely without working out the math involved. I'll leave that to someone with more free time." ContentLicense="CC BY-SA 3.0" />
  <row Id="11715" PostHistoryTypeId="2" PostId="4901" RevisionGUID="959f86a3-1653-439a-9667-e5e187c1f1c3" CreationDate="2017-03-23T17:30:51.187" UserId="110" Text="Ah, shadows. They still are bothering after so many people spent years trying to improve them.  &#xA;Whether your engine is deferred or forward, the shadow pass should be quite the same, and suffer the same issues.  &#xA;You are correct, this is a famous problem. Some methods can improve these artifacts in some cases, see the methods mentioned already, or for example &quot;light-perspective-cascades&quot;, &quot;variance shadow maps&quot;, &quot;shadow atlas&quot; (compute optimal resolution for shadows of each light given available memory, and arrange them accordingly in a big buffer), &quot;moment shadow mapping&quot;.  &#xA;Some other workarounds are &quot;baking&quot; the shadow maps if light and object do not move.&#xA;I am missing a lot, but don't recall seeing a solution that works well when resolution / number of filtering passes / samples is restricted...  &#xA;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11716" PostHistoryTypeId="2" PostId="4902" RevisionGUID="6398685e-689a-4ea9-b41d-3184ebc2dbc0" CreationDate="2017-03-23T21:10:35.083" UserId="5249" Text="Consider hypothetical camera with pinhole (in mathematical sense) lens and is sensor, like in below image. Is it the case that the central region of the sensor will receive more light (pixels will be brighter) than the pixels closer to the border?&#xD;&#xA;&#xD;&#xA;Will the darkening be proportional to the cosine of the sensor normal and the direction which the light comes from?&#xD;&#xA;&#xD;&#xA;Is this phenomenon occurring in digital cameras, is it corrected digitally?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALd2E.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11717" PostHistoryTypeId="1" PostId="4902" RevisionGUID="6398685e-689a-4ea9-b41d-3184ebc2dbc0" CreationDate="2017-03-23T21:10:35.083" UserId="5249" Text="Amount of light reaching the sensor of pinhole camera model" ContentLicense="CC BY-SA 3.0" />
  <row Id="11718" PostHistoryTypeId="3" PostId="4902" RevisionGUID="6398685e-689a-4ea9-b41d-3184ebc2dbc0" CreationDate="2017-03-23T21:10:35.083" UserId="5249" Text="|raytracing|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11719" PostHistoryTypeId="2" PostId="4903" RevisionGUID="0f7f9cb3-5fa0-45ed-b525-a69bfaf5bb51" CreationDate="2017-03-24T06:01:32.157" UserId="38" Text="There is only one major thing that I can think of in nonstereographic view that is affected by size and that is:&#xD;&#xA;&#xD;&#xA;* Atmospheric haze and subsurface scattering, even this is similar at most or all macroscopic ranges.&#xD;&#xA;&#xD;&#xA;That said you can easily do this by fudging one constant in a shader. Or slightly more tediously by adding aerosols in the air if you are in fact doing this in real photography, altough getting it exactly right is hard.&#xD;&#xA;&#xD;&#xA;This changes in stereoscopy as humans have some sense of their own scale. So the disparity between cameras sets a scale. But if you change the distance between the cameras then you change scale so even they do not have to be in absolute scale just relative scale.&#xD;&#xA;&#xD;&#xA;So in fact most things are self similar at all practical scales. And only when you start to see effects that are fixed light wavelength do you get into this problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11724" PostHistoryTypeId="2" PostId="4905" RevisionGUID="beeae88a-9790-468b-a018-5c97c37ec3be" CreationDate="2017-03-24T13:50:31.327" UserId="1952" Text="This effect is called [vignetting][1]. The cases you talk about are specifically natural and pixel vignetting as explained on the wiki page. Digital cameras compensate these effects, but optical vignetting has to be done in image software for DSLR's with interchangeable lenses. For example if you import an image to Lightroom, there's &quot;lens correction&quot; option, which removes vignetting, distortion and chromatic aberration caused by the lens based on the lens profile.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Vignetting" ContentLicense="CC BY-SA 3.0" />
  <row Id="11725" PostHistoryTypeId="34" PostId="4848" RevisionGUID="5fede1d4-8ad2-4b8a-a262-3eed560ef157" CreationDate="2017-03-24T18:16:54.277" UserId="-1" Comment="27" />
  <row Id="11726" PostHistoryTypeId="5" PostId="4902" RevisionGUID="c9405aef-1ebd-4ab3-a6ca-1a419709737c" CreationDate="2017-03-24T20:45:17.373" UserId="5249" Comment="clarification" Text="Consider hypothetical camera with pinhole (in mathematical sense) lens and is sensor, like in below image. Is it the case that the central region of the sensor will receive more light (pixels will be brighter) than the pixels closer to the border?&#xD;&#xA;&#xD;&#xA;Will the darkening be proportional to the cosine of the sensor normal and the direction which the light comes from?&#xD;&#xA;&#xD;&#xA;Is this phenomenon occurring in digital cameras, is it corrected digitally?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALd2E.jpg&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I mostly interested in case of idealized film. Digital cameras exhibit this effect due to light attenuation caused be some participating media.&#xD;&#xA;I'm asking about pure geometrical effect like in Lambertian law." ContentLicense="CC BY-SA 3.0" />
  <row Id="11727" PostHistoryTypeId="2" PostId="4906" RevisionGUID="3f6d00f7-1b98-4fc3-b828-922a5ac9dffd" CreationDate="2017-03-24T23:29:06.743" UserId="6318" Text="Like the question says I have a scene kit app im working on and at a certain point I move the camera under a list of objects and tilt it up to give a star wars type view of them. I then need to pull the objects up one at a time and face them at the camera. All of this is working however the last step is making them rotate so while facing the camera it looks like it's spinning on it' y axis.&#xD;&#xA;&#xD;&#xA;I'm setting my camera's eularAngle.x to .75. I then do the same to the object i'm bringing to the foreground so it faces the camera. I cannot for the life of me figure the matrix math to make it spin correctly. Please help." ContentLicense="CC BY-SA 3.0" />
  <row Id="11728" PostHistoryTypeId="1" PostId="4906" RevisionGUID="3f6d00f7-1b98-4fc3-b828-922a5ac9dffd" CreationDate="2017-03-24T23:29:06.743" UserId="6318" Text="Tilting a 3d object to face a camera and have it look like it's spinning on the y axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="11729" PostHistoryTypeId="3" PostId="4906" RevisionGUID="3f6d00f7-1b98-4fc3-b828-922a5ac9dffd" CreationDate="2017-03-24T23:29:06.743" UserId="6318" Text="|3d|transformations|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11730" PostHistoryTypeId="5" PostId="4906" RevisionGUID="f5080f74-0520-48d1-82a8-1080474f3512" CreationDate="2017-03-25T00:09:02.807" UserId="6318" Comment="added 2 characters in body" Text="Like the question says I have a scene kit app I'm working on and at a certain point I move the camera under a list of objects and tilt it up to give a star wars type view of them. I then need to pull the objects up one at a time and face them at the camera. All of this is working however the last step is making them rotate so while facing the camera it looks like it's spinning on it's y axis.&#xD;&#xA;&#xD;&#xA;I'm setting my camera's eularAngle.x to .75. I then do the same to the object i'm bringing to the foreground so it faces the camera. I cannot for the life of me figure the matrix math to make it spin correctly. Please help." ContentLicense="CC BY-SA 3.0" />
  <row Id="11732" PostHistoryTypeId="5" PostId="4906" RevisionGUID="04d5063e-50f5-435f-a206-55b93de893c8" CreationDate="2017-03-25T13:08:00.823" UserId="231" Comment="Remove redundant intro and &quot;Please help&quot;, add leading zero for readability and minor typos" Text="I have a scene kit app I'm working on and at a certain point I move the camera under a list of objects and tilt it up to give a star wars type view of them. I then need to pull the objects up one at a time and face them at the camera. All of this is working however the last step is making them rotate so while facing the camera it looks like it's spinning on its y axis.&#xD;&#xA;&#xD;&#xA;I'm setting my camera's eularAngle.x to 0.75. I then do the same to the object I'm bringing to the foreground so it faces the camera. I cannot for the life of me figure out the matrix math to make it spin correctly." ContentLicense="CC BY-SA 3.0" />
  <row Id="11733" PostHistoryTypeId="2" PostId="4907" RevisionGUID="e42aaced-bcd0-4076-a1b7-56cbbf5fe6f5" CreationDate="2017-03-25T14:42:29.927" UserId="6320" Text="I am trying to make 3D drawing software. I wanted to have the drag feature so I am using object picking using the OBB algorithm. I am facing problems in understanding the algorithm, and my implementation thus is having bugs.&#xD;&#xA;&#xD;&#xA;How do I implement object picking, using OBB in OpenGL? As I am new to OpenGL (free-glut library), a step by step explanation would be helpful.&#xD;&#xA;&#xD;&#xA;thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="11734" PostHistoryTypeId="1" PostId="4907" RevisionGUID="e42aaced-bcd0-4076-a1b7-56cbbf5fe6f5" CreationDate="2017-03-25T14:42:29.927" UserId="6320" Text="How do I implement object picking, using OBB in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11735" PostHistoryTypeId="3" PostId="4907" RevisionGUID="e42aaced-bcd0-4076-a1b7-56cbbf5fe6f5" CreationDate="2017-03-25T14:42:29.927" UserId="6320" Text="|opengl|raytracing|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11736" PostHistoryTypeId="2" PostId="4908" RevisionGUID="21c0e638-ece9-4877-8e12-f9b9c79052b8" CreationDate="2017-03-25T16:59:26.117" UserId="4776" Text="Ray vs OBB intersection works by shooting a ray towards the OBB's planes. This results in 2 intersections referred to as `t1` and `t2` (per axis), also referred to as `tNear` and `tFar` or `tMin` and `tMax`.&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/saY7S.png&#xD;&#xA;&#xD;&#xA;Checking whether the ray intersects with the box, can then be done by comparing the largest `tNear` against the smallest `tFar`. If the largest `tNear` is less than the smallest `tFar` then there is a intersection.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11738" PostHistoryTypeId="50" PostId="4760" RevisionGUID="fec818b4-4f9e-4ade-ba98-8ed3dd44d806" CreationDate="2017-03-26T04:13:52.787" UserId="-1" />
  <row Id="11739" PostHistoryTypeId="2" PostId="4909" RevisionGUID="6cc48094-70cf-494e-bfb0-f6ee0cbd88f2" CreationDate="2017-03-26T11:00:55.810" UserId="231" Text="As Dan Hulme points out in a comment, the variable `last` is not updated each frame. Assuming this code is within a function, it is initialised to the current time once, the first time this function is called. Every time the function is called after that, the `static` keyword prevents the `last` variable from being updated. This variable therefore remains unchanged throughout the animation, always set to the initial time.&#xD;&#xA;&#xD;&#xA;If this suspected problem is indeed the case, you can correct it by either not using static variables, or by initialising the static variables and then separately updating them in lines that do not contain the `static` keyword.&#xD;&#xA;&#xD;&#xA;In the current code, I can't think of a way that `last` could already be set to the current time each frame unless there is more code that has not been posted, in which case we will not be able to help you without seeing it.&#xD;&#xA;&#xD;&#xA;There are more subtle problems with simply multiplying by delta, which will give a different trajectory for different delta sizes, but they may not be relevant depending on the accuracy that you require. I have focused on what appears to be the most significant problem, as nothing else can be tested until that is either addressed or proved to be not a problem.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11740" PostHistoryTypeId="5" PostId="4907" RevisionGUID="dde035c6-c55b-496d-89f7-0d9991982761" CreationDate="2017-03-26T11:05:59.973" UserId="4776" Comment="Unnecessary " Text="I am trying to make 3D drawing software. I wanted to have the drag feature so I am using object picking using the OBB algorithm. I am facing problems in understanding the algorithm, and my implementation thus is having bugs.&#xD;&#xA;&#xD;&#xA;How do I implement object picking, using OBB in OpenGL? As I am new to OpenGL (free-glut library), a step by step explanation would be helpful." ContentLicense="CC BY-SA 3.0" />
  <row Id="11741" PostHistoryTypeId="24" PostId="4907" RevisionGUID="dde035c6-c55b-496d-89f7-0d9991982761" CreationDate="2017-03-26T11:05:59.973" Comment="Proposed by 4776 approved by 2654, 231 edit id of 216" ContentLicense="CC BY-SA 3.0" />
  <row Id="11751" PostHistoryTypeId="2" PostId="4912" RevisionGUID="c0f16a55-8047-4c91-baaf-1166dad1abd5" CreationDate="2017-03-27T03:21:25.450" UserId="6331" Text="I briefly read the paper and I think I got the basic idea of it. The paper doesn't really go into implementation details though so my question is mostly on that. &#xD;&#xA;&#xD;&#xA;In the paper, needed tiles are identified by going through the vertex stage and the vertices that make it to the fragment stage have paging data written into another texture at the vert's texcoord. Tiles are then assigned a tile from some form of pager. Cpu reads paging and assignment data and streams image data from disk to said tiles. At least that's from what I understand. &#xD;&#xA;&#xD;&#xA;I'm unclear on the TLM implementation. I assume it's using image load stores (glsl. Don't know what the hlsl equivalent is). Is this a correct assumption to make or is there a better way to do this? &#xD;&#xA;&#xD;&#xA;Also, is this better than just streaming in data based on the object distance from the camera? Their implementation may be more efficient that it streams in only when needed, but it sounds like it might introduce more pop in since it doesn't guarantee that objects nearby will have the appropriate mip level in memory. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11752" PostHistoryTypeId="1" PostId="4912" RevisionGUID="c0f16a55-8047-4c91-baaf-1166dad1abd5" CreationDate="2017-03-27T03:21:25.450" UserId="6331" Text="Implementation of the paper &quot;unified texture management of arbitrary meshes&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11753" PostHistoryTypeId="3" PostId="4912" RevisionGUID="c0f16a55-8047-4c91-baaf-1166dad1abd5" CreationDate="2017-03-27T03:21:25.450" UserId="6331" Text="|texture|glsl|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11754" PostHistoryTypeId="2" PostId="4913" RevisionGUID="19fa35d9-cd40-4fe7-8dda-95f5a2daec68" CreationDate="2017-03-27T04:51:13.653" UserId="6290" Text="    GLfloat now = glfwGetTime();&#xD;&#xA;    delta = last - now;&#xD;&#xA;    last = now;&#xD;&#xA;&#xD;&#xA;`delta` and `last` should be initialized as 0.0f outside the gameloop." ContentLicense="CC BY-SA 3.0" />
  <row Id="11755" PostHistoryTypeId="2" PostId="4914" RevisionGUID="7ec08c32-ff9a-44de-8cbe-b5f487e215a0" CreationDate="2017-03-27T05:32:04.817" UserId="2096" Text="I was in my elevator when i saw this... [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7JbXE.jpg&#xD;&#xA;&#xD;&#xA;As you can see here that reflections are kind of stretched. What causes this? And how can we achieve something like this in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11756" PostHistoryTypeId="1" PostId="4914" RevisionGUID="7ec08c32-ff9a-44de-8cbe-b5f487e215a0" CreationDate="2017-03-27T05:32:04.817" UserId="2096" Text="How can i achieve reflections like this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11757" PostHistoryTypeId="3" PostId="4914" RevisionGUID="7ec08c32-ff9a-44de-8cbe-b5f487e215a0" CreationDate="2017-03-27T05:32:04.817" UserId="2096" Text="|opengl|algorithm|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11764" PostHistoryTypeId="2" PostId="4915" RevisionGUID="80c52db5-37a3-40f7-8664-365d5313f276" CreationDate="2017-03-27T09:56:55.150" UserId="6337" Text="I'm interseted how to orginize in code (I prefer C++) lightning.  &#xD;&#xA;Problem is: Now I have `Scene` which contain `Model` where model contain `Shader`, some`Texture`s and geometry `Mesh`. Now I want to add `Light` with fields like as  &#xD;&#xA;```struct Light&#xD;&#xA;{&#xD;&#xA;    Vector3f Color;&#xD;&#xA;    float AmbientIntensity;&#xD;&#xA;    Vector3f Direction;&#xD;&#xA;    float DiffuseIntensity;&#xD;&#xA;    float SpecularIntensity;&#xD;&#xA;    Vector3f Position;&#xD;&#xA;};&#xD;&#xA;```   &#xD;&#xA;To apply light I need to know values of this field and position of fragment pixel of geometry. This means I need to make a function like `Light::lightModel(Model mdl)` to get data from `Model` which I want light. But also I want to make `Light ` **debuggable** - show it in scene like a `Model` (cube). How to light all `Models` and do not lite itself?  Make two `Scenes`? `Scene&lt;Model&gt; models` and `Scene&lt;Light&gt; lights` and for loop for each like   &#xD;&#xA;```&#xD;&#xA;for (const auto&amp; light : lights-&gt;data()) {&#xD;&#xA;        for (const auto&amp; model : models-&gt;data())&#xD;&#xA;        {&#xD;&#xA;            light-&gt;lightModel(model);&#xD;&#xA;            model-&gt;draw(camera);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;```  &#xD;&#xA;Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11765" PostHistoryTypeId="1" PostId="4915" RevisionGUID="80c52db5-37a3-40f7-8664-365d5313f276" CreationDate="2017-03-27T09:56:55.150" UserId="6337" Text="How to organize Lights and Models?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11766" PostHistoryTypeId="3" PostId="4915" RevisionGUID="80c52db5-37a3-40f7-8664-365d5313f276" CreationDate="2017-03-27T09:56:55.150" UserId="6337" Text="|opengl|shader|c++|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11767" PostHistoryTypeId="5" PostId="4915" RevisionGUID="3d19214d-42ee-4b8e-9e5e-43b91b317d07" CreationDate="2017-03-27T11:12:35.943" UserId="137" Comment="added 28 characters in body" Text="I'm interseted how to orginize in code (I prefer C++) lightning.  &#xD;&#xA;Problem is: Now I have `Scene` which contain `Model` where model contain `Shader`, some`Texture`s and geometry `Mesh`. Now I want to add `Light` with fields like as  &#xD;&#xA;&#xD;&#xA;    struct Light&#xD;&#xA;    {&#xD;&#xA;        Vector3f Color;&#xD;&#xA;        float AmbientIntensity;&#xD;&#xA;        Vector3f Direction;&#xD;&#xA;        float DiffuseIntensity;&#xD;&#xA;        float SpecularIntensity;&#xD;&#xA;        Vector3f Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;To apply light I need to know values of this field and position of fragment pixel of geometry. This means I need to make a function like `Light::lightModel(Model mdl)` to get data from `Model` which I want light. But also I want to make `Light ` **debuggable** - show it in scene like a `Model` (cube). How to light all `Models` and do not lite itself?  Make two `Scenes`? `Scene&lt;Model&gt; models` and `Scene&lt;Light&gt; lights` and for loop for each like   &#xD;&#xA;&#xD;&#xA;    for (const auto&amp; light : lights-&gt;data()) {&#xD;&#xA;        for (const auto&amp; model : models-&gt;data())&#xD;&#xA;        {&#xD;&#xA;            light-&gt;lightModel(model);&#xD;&#xA;            model-&gt;draw(camera);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11768" PostHistoryTypeId="2" PostId="4916" RevisionGUID="5d1e710b-4cc2-4189-8427-f405e76a1d67" CreationDate="2017-03-27T13:00:17.613" UserId="4958" Text="This might be not laser precision question but this issue appeared a long time ago when first trying to render some scene with 3D models in rasterisation renderer and apply some lighting, posprocessing etc.&#xD;&#xA;&#xD;&#xA;Random squares:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Sometimes it look like flooding model area:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But it appears only on models loaded from file, sponza or any other.&#xD;&#xA;&#xD;&#xA;So what could be the cause? Numerical errors in shaders? `NaN` or negative values? Anyone experiences this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XgquJ.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4WWaw.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="11769" PostHistoryTypeId="1" PostId="4916" RevisionGUID="5d1e710b-4cc2-4189-8427-f405e76a1d67" CreationDate="2017-03-27T13:00:17.613" UserId="4958" Text="Artifacts (numerical errors?) in rasterisation renderer" ContentLicense="CC BY-SA 3.0" />
  <row Id="11770" PostHistoryTypeId="3" PostId="4916" RevisionGUID="5d1e710b-4cc2-4189-8427-f405e76a1d67" CreationDate="2017-03-27T13:00:17.613" UserId="4958" Text="|opengl|rendering|glsl|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11771" PostHistoryTypeId="2" PostId="4917" RevisionGUID="f67d87cd-38e6-4029-9efe-69a84b043641" CreationDate="2017-03-27T14:14:59.757" UserId="5513" Text="For a 3D scene in the World Coordinates, its View Reference Point (VRP) is at (5,&#xD;&#xA;2,1), &#xD;&#xA;and a viewer is looking towards point A(1,1,1). Construct a transform matrix which will &#xD;&#xA;map  World  Coordinate  points  to  a  right-handed  (UVN)  viewing  space,  so  that  VRP  is &#xD;&#xA;the  origin,  the  line  joining  VRP  to  A  is  the  positive  N  axis,  and  the  View-Up  Vector  is &#xD;&#xA;(0,0,1).  &#xD;&#xA;&#xD;&#xA;I have calculated the transformation matrix (T):&#xD;&#xA;&#xD;&#xA;1, 0, 0, -5&#xD;&#xA;&#xD;&#xA;0, 1, 0, 2&#xD;&#xA;&#xD;&#xA;0, 0, 1, -1&#xD;&#xA;&#xD;&#xA;0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;I have calculated the rotation matrix (R):&#xD;&#xA;&#xD;&#xA;-0.6, -0.8, 0, 0&#xD;&#xA;&#xD;&#xA;0, 0, 1, 0&#xD;&#xA;&#xD;&#xA;-0.8, 0.6, 0, 0&#xD;&#xA;&#xD;&#xA;0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;But what would the final transformation matrix (M) be? My lecture slides tell me it would be rotation matrix multiplied by translation matrix, with the last column multiplied by -1 except for the 1. This would equal:&#xD;&#xA;&#xD;&#xA;M = R x T = &#xD;&#xA;&#xD;&#xA;-0.6, -0.8, 0, -1.4&#xD;&#xA;&#xD;&#xA;0, 0, 1, 1&#xD;&#xA;&#xD;&#xA;-0.8, 0.6, 0, -5.2&#xD;&#xA;&#xD;&#xA;0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;But this answer here: http://computergraphics.stackexchange.com/questions/4737/building-view-transform-matrices&#xD;&#xA;&#xD;&#xA;just adds them together somehow. Which one is correct?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11772" PostHistoryTypeId="1" PostId="4917" RevisionGUID="f67d87cd-38e6-4029-9efe-69a84b043641" CreationDate="2017-03-27T14:14:59.757" UserId="5513" Text="Final transformation matrix to transform world coordinate into vrc" ContentLicense="CC BY-SA 3.0" />
  <row Id="11773" PostHistoryTypeId="3" PostId="4917" RevisionGUID="f67d87cd-38e6-4029-9efe-69a84b043641" CreationDate="2017-03-27T14:14:59.757" UserId="5513" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11774" PostHistoryTypeId="2" PostId="4918" RevisionGUID="eb957de9-6c9a-4789-b73d-c752b30dd158" CreationDate="2017-03-27T15:01:24.157" UserId="6340" Text="I'm developing a deep learning algorithm to find and classify (post consumption) plastic bottles on a conveyor belt. A way to train my model is to get tons of labeled images of each bottle, which for now is not feasible. Another possible option is to make a 3D scan of the bottle and render it in different angles thus creating synthetic training data.&#xD;&#xA;&#xD;&#xA;The way I want to obtain the mesh is by using for example ReMake or CapturingReality and 2D images. The problem is that most of the bottles are transparent and are causing problems in those programs. I just ordered Chalk spray to paint them and with a marker add dots allover. Then hopefully I'd be able to render it with the specific material.&#xD;&#xA;&#xD;&#xA;My question is, is there a way to add the visual details like the labels and the color of the bottle cap back to the mesh? I'll be using a RGB-D camera so the priorities are getting both the visual cues as well as the depth information as accurate as possible to what the camera will be classifying in a further stage. &#xD;&#xA;&#xD;&#xA;Any advise and feedback will be highly appreciated, thanks in advanced!! " ContentLicense="CC BY-SA 3.0" />
  <row Id="11775" PostHistoryTypeId="1" PostId="4918" RevisionGUID="eb957de9-6c9a-4789-b73d-c752b30dd158" CreationDate="2017-03-27T15:01:24.157" UserId="6340" Text="Advice on synthetic data generation using 3D mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="11776" PostHistoryTypeId="3" PostId="4918" RevisionGUID="eb957de9-6c9a-4789-b73d-c752b30dd158" CreationDate="2017-03-27T15:01:24.157" UserId="6340" Text="|rendering|3d|texture|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11777" PostHistoryTypeId="5" PostId="4916" RevisionGUID="ddb85ee2-36d5-40c5-b26b-37470f59b4fb" CreationDate="2017-03-27T16:32:04.960" UserId="4958" Comment="added 50 characters in body" Text="This might be not laser precision question but this issue appeared a long time ago when first trying to render some scene with 3D models in rasterisation renderer and apply some lighting, posprocessing etc.&#xD;&#xA;&#xD;&#xA;Random squares:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Sometimes it look like flooding model area:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But it appears only on models loaded from file, sponza or any other.&#xD;&#xA;&#xD;&#xA;So what could be the cause? Numerical errors in shaders? `NaN` or negative values? Anyone experiences this?&#xD;&#xA;&#xD;&#xA;It's hard to explain because its quite random.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XgquJ.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4WWaw.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="11778" PostHistoryTypeId="5" PostId="4915" RevisionGUID="10bdc6df-0942-4d46-ad6a-be290e1c0a90" CreationDate="2017-03-27T22:29:26.117" UserId="231" Comment="Remove &quot;Thanks!&quot; and tidy up wording" Text="I'm interested in how to organize in code (I prefer C++) lighting.  &#xD;&#xA;Problem is: I have `Scene` which contains `Model` where model contains `Shader`, some`Texture`s and geometry `Mesh`. Now I want to add `Light` with the following fields:&#xD;&#xA;&#xD;&#xA;    struct Light&#xD;&#xA;    {&#xD;&#xA;        Vector3f Color;&#xD;&#xA;        float AmbientIntensity;&#xD;&#xA;        Vector3f Direction;&#xD;&#xA;        float DiffuseIntensity;&#xD;&#xA;        float SpecularIntensity;&#xD;&#xA;        Vector3f Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;To apply light I need to know the values of this field and the position of the fragment pixel of geometry. This means I need to make a function like `Light::lightModel(Model mdl)` to get data from `Model` which I want to light. But also I want to make `Light` **debuggable** - show it in the scene like a `Model` (cube). How can I light all `Model`s and do not light the light itself?  Make two `Scene`s? `Scene&lt;Model&gt; models` and `Scene&lt;Light&gt; lights` and for loop for each like this?   &#xD;&#xA;&#xD;&#xA;    for (const auto&amp; light : lights-&gt;data()) {&#xD;&#xA;        for (const auto&amp; model : models-&gt;data())&#xD;&#xA;        {&#xD;&#xA;            light-&gt;lightModel(model);&#xD;&#xA;            model-&gt;draw(camera);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11779" PostHistoryTypeId="2" PostId="4919" RevisionGUID="3f2565e7-5a46-4d1b-94cd-d6653b283d50" CreationDate="2017-03-28T03:30:19.457" UserId="6290" Text="I have a series of MRI images. I want to build a 3D model out of it, which not only presents the surface, but also contains the inside structures. What kind of photogrammetry based method can realize that? " ContentLicense="CC BY-SA 3.0" />
  <row Id="11780" PostHistoryTypeId="1" PostId="4919" RevisionGUID="3f2565e7-5a46-4d1b-94cd-d6653b283d50" CreationDate="2017-03-28T03:30:19.457" UserId="6290" Text="How to build a 3d model from 2d pictures" ContentLicense="CC BY-SA 3.0" />
  <row Id="11781" PostHistoryTypeId="3" PostId="4919" RevisionGUID="3f2565e7-5a46-4d1b-94cd-d6653b283d50" CreationDate="2017-03-28T03:30:19.457" UserId="6290" Text="|3d|algorithm|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11782" PostHistoryTypeId="2" PostId="4920" RevisionGUID="f760f13a-21ff-4977-bd61-5646f38a86fd" CreationDate="2017-03-28T03:42:22.670" UserId="4991" Text="I was thinking that I could pass a timestamp in (from requestAnimationFrame) to the vert shader, and just have my easing curves in the GPU instead of using (for example) Tween.js from the outside.&#xD;&#xA;&#xD;&#xA;Is this a good idea? Why or why not?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11783" PostHistoryTypeId="1" PostId="4920" RevisionGUID="f760f13a-21ff-4977-bd61-5646f38a86fd" CreationDate="2017-03-28T03:42:22.670" UserId="4991" Text="Easing curves on the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11784" PostHistoryTypeId="3" PostId="4920" RevisionGUID="f760f13a-21ff-4977-bd61-5646f38a86fd" CreationDate="2017-03-28T03:42:22.670" UserId="4991" Text="|opengl|shader|glsl|webgl|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11785" PostHistoryTypeId="5" PostId="4912" RevisionGUID="53b8250e-c747-4cc7-818c-196bcd89fc3c" CreationDate="2017-03-28T07:06:19.760" UserId="6331" Comment="added 63 characters in body" Text="I briefly read the paper and I think I got the basic idea of it. The paper doesn't really go into implementation details though so my question is mostly on that. &#xD;&#xA;&#xD;&#xA;In the paper, needed tiles are identified by going through the vertex stage and the vertices that make it to the fragment stage have paging data written into another texture at the vert's texcoord. Tiles are then assigned a tile from some form of pager. Cpu reads paging and assignment data and streams image data from disk to said tiles. At least that's from what I understand. &#xD;&#xA;&#xD;&#xA;I'm unclear on the TLM implementation. I assume it's using image load stores (glsl. Don't know what the hlsl equivalent is). Is this a correct assumption to make or is there a better way to do this? &#xD;&#xA;&#xD;&#xA;Also, is this better than just streaming in data based on the object distance from the camera? Their implementation may be more efficient that it streams in only when needed, but it sounds like it might introduce more pop in since it doesn't guarantee that objects nearby will have the appropriate mip level in memory. &#xD;&#xA;&#xD;&#xA;Edit: link to the paper https://hal.inria.fr/inria-00070783" ContentLicense="CC BY-SA 3.0" />
  <row Id="11788" PostHistoryTypeId="2" PostId="4921" RevisionGUID="831b5842-4d8a-4454-b1bc-b543f41eec4f" CreationDate="2017-03-28T11:08:29.177" UserId="5066" Text="If I understand you correctly then you are probably looking for a way in which lights in the scene interact with models in the scene. Also, you want each light to be visually debuggable in scene, maybe by drawing a cube. Here's one of the simplest way to do it. There could be more better &amp; optimized ways of doing this. &#xD;&#xA;&#xD;&#xA;You can have a class for Each light type eg&gt; PointLight, DirectionalLight etc each with their own properties. You need to have a class which then keeps track of all the lights in the scene. This class will have list of light types in the scene. This class will also have functions for adding active lights from the scene to it's list of lights. Usual get-set functions for accessing individual lights will be required too. &#xD;&#xA;&#xD;&#xA;    class LightsManager&#xD;&#xA;    {&#xD;&#xA;    // maybe create singleton object here..&#xD;&#xA;    public:&#xD;&#xA;       void GatherPointLights(PointLight* light);&#xD;&#xA;       PointLight GetPointLight(int id);&#xD;&#xA;    &#xD;&#xA;    private:&#xD;&#xA;       int numPointLights;&#xD;&#xA;       std::vector&lt;PointLight*&gt; vecPointLights; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void LightsManager::GatherPointLights(PointLight* light)&#xD;&#xA;    {&#xD;&#xA;    	vecPointLights.push_back(light);&#xD;&#xA;    	numPointLights = vecPointLights.size();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In your class where you create objects in the scene, you can then add light objects from the scene to this LightManager using the function you created earlier. &#xD;&#xA;&#xD;&#xA;Assuming scene class where all the objects including Lights are created...&#xD;&#xA;&#xD;&#xA;    void Scene::Init()&#xD;&#xA;    {&#xD;&#xA;        // load mesh&#xD;&#xA;        ...&#xD;&#xA;        ...&#xD;&#xA;        // add lights&#xD;&#xA;        PointLight light1;&#xD;&#xA;        light1.color = Color::Red;&#xD;&#xA;        light1.position = vec3(0,0,0);&#xD;&#xA;        LightManager::getInstance()-&gt;GatherPointLights(&amp;light1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If LightManager creates singleton object then you can then access all the lights in the scene by their type during actual rendering to extract their properties in a class where you render actual scene geometry by passing light color, position etc to a shader which draws scene geometry. &#xD;&#xA;&#xD;&#xA;Now drawing the actual debug geometry for any light object, say cube for point light, I would make sure my PointLight type object has a way of rendering cube at a Point light position, using it's color property to draw cube of that same color with a flat color shader.&#xD;&#xA;&#xD;&#xA;As per making sure lights are not lighting actual light debug geometry, if your cube drawing shader is a flat color shader representing color of a light, then it will not be affected by any light in the scene. &#xD;&#xA;&#xD;&#xA;Hope this is what you asked for. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11789" PostHistoryTypeId="2" PostId="4922" RevisionGUID="0f2968d4-769d-4410-b271-c200025e5f6c" CreationDate="2017-03-28T17:03:49.197" UserId="5513" Text="Consider a triangular face of three vertices A(0,2,-1), B(1,0,1) and the origin O, and the normal vectors at the vertices are nA=(0,1,0), nB=(1,0,0) and nO=(0,0,1), respectively. The incident light is white and directional in direction of L=(1,2,2) and the intensity is 1, the background ambient light intensity is 0.1, and the diffuse reflection coefficients for (red, green, blue) are (0.6,0.7,0.8). No specular light contribution needs to be considered.&#xD;&#xA;&#xD;&#xA;Find the (red, green, blue) intensity values at the centre of the face using Gouraud shading.&#xD;&#xA;&#xD;&#xA;I do not know how to answer this question and have looked at my lecture slides, youtube videos, computer graphics textbook by Foley and Van Damm and obviously used google. Any help would be much appreciated. " ContentLicense="CC BY-SA 3.0" />
  <row Id="11790" PostHistoryTypeId="1" PostId="4922" RevisionGUID="0f2968d4-769d-4410-b271-c200025e5f6c" CreationDate="2017-03-28T17:03:49.197" UserId="5513" Text="Find RGB intensity values at center of face using Gouraud shading" ContentLicense="CC BY-SA 3.0" />
  <row Id="11791" PostHistoryTypeId="3" PostId="4922" RevisionGUID="0f2968d4-769d-4410-b271-c200025e5f6c" CreationDate="2017-03-28T17:03:49.197" UserId="5513" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11792" PostHistoryTypeId="5" PostId="4920" RevisionGUID="d99f1e67-65eb-451f-bc44-4a9d1cf617f2" CreationDate="2017-03-28T17:56:36.370" UserId="4991" Comment="added 288 characters in body" Text="I was thinking that I could pass a timestamp in (from requestAnimationFrame) to the vert shader, and just have my easing curves in the GPU instead of using (for example) Tween.js from the outside.&#xD;&#xA;&#xD;&#xA;Is this a good idea? Why or why not?&#xD;&#xA;&#xD;&#xA;EDIT: After learning more GL and thinking about it, it doesn't seem like I want *every* shader instance to run a tween that I may only use for a handful of vertices. Can we have only certain shaders run tween calculations if the vertex being animated is the one of the current shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11793" PostHistoryTypeId="2" PostId="4923" RevisionGUID="5091399a-e66c-431f-b0de-6cda22a68fa6" CreationDate="2017-03-28T19:42:12.480" UserId="4509" Text="I am trying to implement [Rauwendall and Bailey's][1] Conservative Voxelization algorithm in a compute shader (Section 7)(page 20/34).&#xD;&#xA;&#xD;&#xA;This algorithm is similar to Schwarz &amp; Seidel's, in that it orthogonally projects a triangle into a plane (aligned with an axis - the *depth axis*), then iterates over all the points in the plane, using edge functions to determine if they are within the triangle's projection.&#xD;&#xA;&#xD;&#xA;Rather than then perform a box-plane intersection for each voxel however as in Schwarz and Seidel, this algorithm computes the range of points along the depth axis to check, then just checks the projection in the remaining two planes.&#xD;&#xA;&#xD;&#xA;**What I do not understand is how that algorithm identifies the range in the depth axis.**&#xD;&#xA;&#xD;&#xA;The paper does not go into much more detail than I just did, and I can't work out from the pseudo-code how it functions.&#xD;&#xA;&#xD;&#xA;Can anyone explain?&#xD;&#xA;&#xD;&#xA;(PS. I have tried to implement the pseudo-code as written, and I needed to make a couple of corrections to get it working. The minimal range check is the last bit that is not functioning. I need to understand how it works so I can fix it.)&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0002/01/02/paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11794" PostHistoryTypeId="1" PostId="4923" RevisionGUID="5091399a-e66c-431f-b0de-6cda22a68fa6" CreationDate="2017-03-28T19:42:12.480" UserId="4509" Text="How does the depth range test in Rauwendaal &amp; Bailey's voxelisation algorithm work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11795" PostHistoryTypeId="3" PostId="4923" RevisionGUID="5091399a-e66c-431f-b0de-6cda22a68fa6" CreationDate="2017-03-28T19:42:12.480" UserId="4509" Text="|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11796" PostHistoryTypeId="5" PostId="4912" RevisionGUID="832ecaff-337f-4607-8de7-11433e5f251e" CreationDate="2017-03-29T00:13:19.403" UserId="6331" Comment="added 604 characters in body" Text="I briefly read the paper and I think I got the basic idea of it. The paper doesn't really go into implementation details though so my question is mostly on that. &#xD;&#xA;&#xD;&#xA;In the paper, needed tiles are identified by going through the vertex stage and the vertices that make it to the fragment stage have paging data written into another texture at the vert's texcoord. Tiles are then assigned a tile from some form of pager. Cpu reads paging and assignment data and streams image data from disk to said tiles. At least that's from what I understand. &#xD;&#xA;&#xD;&#xA;I'm unclear on the TLM implementation. I assume it's using image load stores (glsl. Don't know what the hlsl equivalent is). Is this a correct assumption to make or is there a better way to do this? &#xD;&#xA;&#xD;&#xA;Also, is this better than just streaming in data based on the object distance from the camera? Their implementation may be more efficient that it streams in only when needed, but it sounds like it might introduce more pop in since it doesn't guarantee that objects nearby will have the appropriate mip level in memory. &#xD;&#xA;&#xD;&#xA;Edit: link to the paper https://hal.inria.fr/inria-00070783&#xD;&#xA;&#xD;&#xA;Did a proper read through again. It outputs the texcoord as a color frame buffer attachment at the vertex stage. Now the only confusion is how they output the texcoord coordinates but still use the mvp transform for the actual clipping. My solution is probably to abs the x and y mvp coords, take the max of those and output that to the z coord. The vertex will be clipped if the z value is more than one.  That's my solution for this. They vaguely mentioned using the clipping registers in Nvidia hw. I'm guessing that means is a better way to do this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="11797" PostHistoryTypeId="2" PostId="4924" RevisionGUID="b1db3783-0475-46c1-af4d-f64b33f5a44c" CreationDate="2017-03-29T00:51:45.537" UserId="6349" Text="So i am new to the DX12 world. I am currently trying to tweek the nbody_gravity DX12 sample, but appending or calling another Compute Shader which is to add 2 buffers to produce an output in a different buffer. &#xD;&#xA;&#xD;&#xA;Right now, I have made a call to my ComputeBufferAddition shader and was wondering if I need a separate Compute PSO to do this, or can i reuse the one already present to call the NbodyGravity.hlsl&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11798" PostHistoryTypeId="1" PostId="4924" RevisionGUID="b1db3783-0475-46c1-af4d-f64b33f5a44c" CreationDate="2017-03-29T00:51:45.537" UserId="6349" Text="Compute Shader PSO Dx12" ContentLicense="CC BY-SA 3.0" />
  <row Id="11799" PostHistoryTypeId="3" PostId="4924" RevisionGUID="b1db3783-0475-46c1-af4d-f64b33f5a44c" CreationDate="2017-03-29T00:51:45.537" UserId="6349" Text="|directx12|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11805" PostHistoryTypeId="5" PostId="4922" RevisionGUID="c47179f6-7342-457e-a2ba-2c63f73e5c56" CreationDate="2017-03-29T08:08:04.450" UserId="5513" Comment="added 288 characters in body" Text="Consider a triangular face of three vertices A(0,2,-1), B(1,0,1) and the origin O, and the normal vectors at the vertices are nA=(0,1,0), nB=(1,0,0) and nO=(0,0,1), respectively. The incident light is white and directional in direction of L=(1,2,2) and the intensity is 1, the background ambient light intensity is 0.1, and the diffuse reflection coefficients for (red, green, blue) are (0.6,0.7,0.8). No specular light contribution needs to be considered.&#xD;&#xA;&#xD;&#xA;Find the (red, green, blue) intensity values at the centre of the face using Gouraud shading.&#xD;&#xA;&#xD;&#xA;I do not know how to answer this question and have looked at my lecture slides, youtube videos, computer graphics textbook by Foley and Van Damm and obviously used google. Any help would be much appreciated. &#xD;&#xA;&#xD;&#xA;Edit: I want to find the intensity values using Gouraud shading, not flat shading. From my understanding, the intensity at a point is interpolated along polygon edges and scan lines? But with the information I am given in the question, I don't have a clue how to answer this question. This video helped a bit: https://www.youtube.com/watch?v=_SuyLrU2Xr0&amp;t=142s but it doesn't set me up for answering this question." ContentLicense="CC BY-SA 3.0" />
  <row Id="11806" PostHistoryTypeId="5" PostId="4907" RevisionGUID="195db446-e7c8-4c59-912b-a68dd3578b56" CreationDate="2017-03-29T08:19:57.697" UserId="231" Comment="Edit in additional information from comment." Text="I am trying to make 3D drawing software. I wanted to have the drag feature so I am using object picking using the OBB algorithm. I am facing problems in understanding the algorithm, and my implementation thus is having bugs.&#xD;&#xA;&#xD;&#xA;How do I implement object picking, using OBB in OpenGL? As I am new to OpenGL (free-glut library), a step by step explanation would be helpful.&#xD;&#xA;&#xD;&#xA;I am not able to understand what t1 and t2 mean and how the algorithm is working. If you explain the algorithm that would be enough." ContentLicense="CC BY-SA 3.0" />
  <row Id="11807" PostHistoryTypeId="2" PostId="4926" RevisionGUID="7a4dc289-e347-4bed-b237-6c430b88d4be" CreationDate="2017-03-29T09:02:43.823" UserId="6140" Text="Thanks for notification me, In my previous answer, I just combine the translation matrix and the rotation matrix, actually, It's the result translation matrix(T) multiply rotation matrix(R). &#xD;&#xA;&#xD;&#xA;The rotation is a 3x3 matrix, we can extend the matrix to a 4x4 matrix with adding a dimension, the 4x4 rotation matrix is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And the translation matrix is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So, now we can calculate the transform matrix by translation matrix multiply(T) rotation matrix(R):&#xD;&#xA;&#xD;&#xA;Cause the matrix multiply formula is too big for the 4x4 matrix, we just look at the 1st row, In the transform matrix(M), the M11 element equals to T11*R11+T12*R21+T13*R31+T14*R41, cause T12, T13, R41 is 0, so, the M11 equals to R11 right? And in the same way, M14 equals to T11*R14+T12*R24+T13*R34+T14*R44, only R44 equals to 1, so, the M14 equals to T14. so, I just simply put them together in my last answer. For the reason why we put the translation matrix on the left, you can check on the book that I gave you in my previous answer on page 91(translating first and then rotating).&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QOZur.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/l3FFz.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="11812" PostHistoryTypeId="2" PostId="4928" RevisionGUID="bd6d2ad2-d89f-4343-8d98-fc81e9202bf3" CreationDate="2017-03-29T15:08:09.497" UserId="48" Text="If I understand you correctly, you've added a new compute shader. In DX12, you'll need at least one separate PSO for each shader, since the shader code is part of the PSO." ContentLicense="CC BY-SA 3.0" />
  <row Id="11817" PostHistoryTypeId="10" PostId="4922" RevisionGUID="1fee7cce-a5ed-48f9-b0cc-8cd8b1f0b6c5" CreationDate="2017-03-29T15:59:02.933" UserId="2041" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[4842],&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="11819" PostHistoryTypeId="2" PostId="4930" RevisionGUID="fb869ca3-7e93-46fe-aeff-40a43d5356b2" CreationDate="2017-03-29T17:45:38.100" UserId="6356" Text="I'm building an application where I stream video camera feed from one mobile device to another in Unity. I tried searching for answers, but most of the topics deal with how to display a video stream, rather than how to send it.&#xD;&#xA;&#xD;&#xA;I tried looking for plugins and only found two that do something similar [1](https://www.assetstore.unity3d.com/en/#!/content/68030), [2](https://www.assetstore.unity3d.com/en/#!/content/7447), but they don't provide much information in regards to mobile support and the plugin price is way too steep for my student budget and a non-commercial application.&#xD;&#xA;&#xD;&#xA;Another approach I am looking into right now is to try streaming the texture itself, but I haven't figured it out yet. Is there an easier way to stream WebCamTexture content on mobile platforms?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11820" PostHistoryTypeId="1" PostId="4930" RevisionGUID="fb869ca3-7e93-46fe-aeff-40a43d5356b2" CreationDate="2017-03-29T17:45:38.100" UserId="6356" Text="Streaming video camera input from WebCamTexture on mobile? (Possibly via WebRTC or websocket?)" ContentLicense="CC BY-SA 3.0" />
  <row Id="11821" PostHistoryTypeId="3" PostId="4930" RevisionGUID="fb869ca3-7e93-46fe-aeff-40a43d5356b2" CreationDate="2017-03-29T17:45:38.100" UserId="6356" Text="|unity|video|mobile|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11822" PostHistoryTypeId="2" PostId="4931" RevisionGUID="c793d4ed-421a-4013-9670-3ad9f590f3ed" CreationDate="2017-03-29T19:56:36.060" UserId="4652" Text="If you want to implement this with GLSL, the general concept that could be applied is multi-pass rendering. In a first render pass, draw some ink on the screen and write the result in a frame buffer object (FBO). Then in the second render pass, draw a screen-size quad and attach the texture of the FBO. In this second render pass you could use a GLSL shader that distributes the ink. In the example below I used a simple Erode and a Gauss filter but more complicated effects are possible here. The result is then used as the background for the first render pass that draws more ink, which is passed on to the second render pass, and so on...&#xD;&#xA;&#xD;&#xA;[![ink flow animated gif][1]][1]&#xD;&#xA;&#xD;&#xA;I have generated the example above with an online tool called &quot;GSN Composer&quot;, which uses GLSL shaders and WebGL. You find the corresponding node graph here:&#xD;&#xA;&#xD;&#xA;https://www.gsn-lib.org/index.html#projectName=foruminkspread&amp;graphName=erode&#xD;&#xA;&#xD;&#xA;Currently, in this very simple implementation, the spreading of ink will never stop. To achieve this you would need to remember a per-pixel state (e.g. a &quot;mass&quot; or &quot;reservoir&quot;, as you have mentioned in your question) and use this per-pixel state in the shader that performs the spreading. This state could be encoded in the texture output (e.g. in the alpha channel) or could be written into a second texture that is passed along the shader pipeline.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AFA6C.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="11823" PostHistoryTypeId="5" PostId="4880" RevisionGUID="db75ebd5-b243-4ad3-9cf6-f37eea471907" CreationDate="2017-03-29T20:30:17.523" UserId="6255" Comment="deleted 58 characters in body" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, it suggests a way to set up up a Phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are a bit off. This could be from somewhere else in the code of course, but I'd rather know for sure.&#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curious about:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment I'm sending these matrices:&#xD;&#xA; &#xD;&#xA;    modelview //ModelViewMatrix; //(view*model is wrong space)&#xD;&#xA;    transpose(inverse(model))) //top 3x3 row of modelview&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;The shader &quot;works&quot;, but I cant get the lighting direction right&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Solved: It works after I place lightposition into viewspace before sending the uniform.&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11824" PostHistoryTypeId="5" PostId="4888" RevisionGUID="e37a650b-d514-4d00-9a31-40bc73b74fec" CreationDate="2017-03-29T20:33:10.220" UserId="6255" Comment="deleted 282 characters in body" Text="I wasn't placing the lightposition into view space before passing it in. &#xD;&#xA;&#xD;&#xA;    vec4 LightPosition_view=view*LightPosition; //put lp into view space with the rest&#xD;&#xA;&#xD;&#xA;When it comes to these things, you have to think in terms of spaces, and I was multiplying the view matrix and the model matrix, into view space, but not the lightposition itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope that helps anyone else facing the same/similar problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="11825" PostHistoryTypeId="5" PostId="4884" RevisionGUID="cdda5911-16c8-4d84-a6e9-efd3bf6dffe8" CreationDate="2017-03-29T20:36:12.023" UserId="6255" Comment="added 145 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(modelviewmatrix))) //top 3x3 row of model*view&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // *needs to be in view-space* (view*lightpos)&#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldnt the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesnt just come from the wrong spot, but it also doesnt change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesnt come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however.&#xD;&#xA;&#xD;&#xA;So, the diffuse value is calculated by getting the dot(s,n), where s is (lightposition-position), and position is (view * model * vertex_position). But like you can see, the results are not as expected&#xD;&#xA;&#xD;&#xA;Solution: The math needs to take place in the same space, and here Im not placing the lightposition into viewspace, so, It doesnt add up.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11827" PostHistoryTypeId="2" PostId="4932" RevisionGUID="d916ca26-bc1c-4a28-8ba2-7bca67c30026" CreationDate="2017-03-29T22:07:39.817" UserId="38" Text="This is a pure optimisation problem. It depends on many factors like:&#xD;&#xA;&#xD;&#xA;* What you need to do with the tween&#xD;&#xA;* How many different tweens you need to calculate&#xD;&#xA;* How much signaling between systems you need&#xD;&#xA;* Whether you need to use that data in your CPU bound process or not.&#xD;&#xA;* How much time you have to write the code&#xD;&#xA;* What your toolset sypports easiest&#xD;&#xA;* ...&#xD;&#xA;&#xD;&#xA;See if you only need one value to interpolate then your CPU is more than likely faster (unless your running some weird embedded system). Even if you move a bunch of points you can still calculate the tween of that one position and do the needed cluster transformation in the GPU, like bone animation.&#xD;&#xA;&#xD;&#xA;The GPU only starts to win your processor if you need to calculate many truly separate animation curves in paralel. Or your in a otherwise performance bound system like running javascript in a webgl application. If you douse the GPU then its most likely to tween all vertices, atleast unless your object is somehow massive. Since initiating a new drawcall is costly and maintaining many states is more complex. Its just that those vertices that dont move would just move from starting point to starting point.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11829" PostHistoryTypeId="10" PostId="4803" RevisionGUID="88681a66-9f7a-4c6a-8216-8ebea3cc0a2f" CreationDate="2017-03-29T22:20:07.590" UserId="2041" Comment="105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:3003,&quot;DisplayName&quot;:&quot;user1118321&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;}]}" />
  <row Id="11833" PostHistoryTypeId="5" PostId="4932" RevisionGUID="8a2460ad-31c3-41a2-b576-6a0fcc2c7298" CreationDate="2017-03-30T06:50:54.140" UserId="38" Comment="added 4 characters in body" Text="This is a pure optimisation problem. It depends on many factors like:&#xD;&#xA;&#xD;&#xA;* What you need to do with the tween&#xD;&#xA;* How many different tweens you need to calculate&#xD;&#xA;* How much signaling between systems you need&#xD;&#xA;* Whether you need to use that data in your CPU bound process or not.&#xD;&#xA;* How much time you have to write the code&#xD;&#xA;* What your tool set supports easiest&#xD;&#xA;* ...&#xD;&#xA;&#xD;&#xA;See if you only need one value to interpolate then your CPU is more than likely faster (unless your running some weird embedded system). Even if you move a bunch of points you can still calculate the tween of that one position and do the needed cluster transformation in the GPU, like bone animation.&#xD;&#xA;&#xD;&#xA;The GPU only starts to win your processor if you need to calculate many truly separate animation curves in parallel. Or your in a otherwise performance bound system like running javascript in a webgl application. If you douse the GPU then its most likely to tween all vertices, at least unless your object is somehow massive. Since initiating a new draw call is costly and maintaining many states is more complex. Its just that those vertices that dont move would just move from starting point to starting point.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11834" PostHistoryTypeId="5" PostId="4932" RevisionGUID="98d81b52-1f58-4dc9-acbf-b0b0a2379aa6" CreationDate="2017-03-30T06:53:44.660" UserId="231" Comment="Minor typos" Text="This is a pure optimisation problem. It depends on many factors like:&#xD;&#xA;&#xD;&#xA;* What you need to do with the tween&#xD;&#xA;* How many different tweens you need to calculate&#xD;&#xA;* How much signaling between systems you need&#xD;&#xA;* Whether you need to use that data in your CPU bound process or not.&#xD;&#xA;* How much time you have to write the code&#xD;&#xA;* What your tool set supports easiest&#xD;&#xA;* ...&#xD;&#xA;&#xD;&#xA;See if you only need one value to interpolate then your CPU is more than likely faster (unless you're running some weird embedded system). Even if you move a bunch of points you can still calculate the tween of that one position and do the needed cluster transformation in the GPU, like bone animation.&#xD;&#xA;&#xD;&#xA;The GPU only starts to win against your processor if you need to calculate many truly separate animation curves in parallel. Or you're in an otherwise performance bound system like running JavaScript in a WebGL application. If you do use the GPU then it's most likely best to tween all vertices, at least unless your object is somehow massive. Since initiating a new draw call is costly and maintaining many states is more complex. Its just that those vertices that don't move would just move from starting point to starting point.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11835" PostHistoryTypeId="5" PostId="4884" RevisionGUID="af83079b-716d-4ad1-a0cd-e090f6c782cd" CreationDate="2017-03-30T07:00:22.190" UserId="231" Comment="Minor typos" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(modelviewmatrix))) //top 3x3 row of model*view&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // *needs to be in view-space* (view*lightpos)&#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldn't the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesn't just come from the wrong spot, but it also doesn't change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesn't come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however.&#xD;&#xA;&#xD;&#xA;So, the diffuse value is calculated by getting the dot(s,n), where s is (lightposition - position), and position is (view * model * vertex_position). But like you can see, the results are not as expected&#xD;&#xA;&#xD;&#xA;Solution: The math needs to take place in the same space, and here I'm not placing the lightposition into viewspace, so, it doesn't add up.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11836" PostHistoryTypeId="4" PostId="4884" RevisionGUID="af83079b-716d-4ad1-a0cd-e090f6c782cd" CreationDate="2017-03-30T07:00:22.190" UserId="231" Comment="Minor typos" Text="My (ADS) shader doesn't render the light direction correctly opengl/c++/glsl" ContentLicense="CC BY-SA 3.0" />
  <row Id="11837" PostHistoryTypeId="5" PostId="4880" RevisionGUID="40abd6b3-de63-45dc-af3d-1f661699d697" CreationDate="2017-03-30T07:05:55.557" UserId="231" Comment="Remove redundant &quot;solved&quot; (there is an answer and an accept tick for this)" Text="On page 89 of [David Wolff - OpenGL 4.0 Shading Language Cookbook][1] book, it suggests a way to set up up a Phong shader in the fragment stage. It lists some different matrices to pass via uniform, and I suspect I might be passing slightly incorrect matrices, as my results are a bit off. This could be from somewhere else in the code of course, but I'd rather know for sure.&#xD;&#xA;&#xD;&#xA;These are the matrices used that I'm curious about:&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix;&#xD;&#xA;    uniform mat3 NormalMatrix;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;&#xD;&#xA;What exactly are these? At the moment I'm sending these matrices:&#xD;&#xA; &#xD;&#xA;    view*model //ModelViewMatrix;&#xD;&#xA;    transpose(inverse(model))) //top 3x3 row of modelview&#xD;&#xA;    projection*view*model //MVP;&#xD;&#xA;&#xD;&#xA;The shader &quot;works&quot;, but I can't get the lighting direction right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11843" PostHistoryTypeId="2" PostId="4935" RevisionGUID="109cab67-ebdb-4ec1-92e7-fa19c69d68d8" CreationDate="2017-03-30T14:25:30.000" UserId="6255" Text="I've been trying to figure this out for a few days now, but I just cant get it right. Ive read multiple [tutorials][1] and [possible][2] explanations, I even watched a [java tutorial][3] without finding the solution. This is what I do:&#xD;&#xA;&#xD;&#xA;First I build the tangent values to pass as attributes:&#xD;&#xA;&#xD;&#xA;    float f;&#xD;&#xA;	vec3 edge1, edge2, tangentbuf;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;    //for each face, x=vert,y=uv, z=normal&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		normalize(tangentref[tangentcount++]);&#xD;&#xA;		tangentref[totalrefs[i] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 3] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 6] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x); //just normalize is enough?&#xD;&#xA;&#xD;&#xA;Normalizing or dividing seems to give the same result, and I think this is correct this far. With these shaders:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec2 tex_cord;&#xD;&#xA;    layout ( location = 2 ) in vec3 vertex_normal;&#xD;&#xA;    layout ( location = 3 ) in vec3 vertex_tangent;&#xD;&#xA;&#xD;&#xA;    uniform mat4 modelviewmatrix; //view*model matrix&#xD;&#xA;    uniform mat3 normalmatrix; // transpose/invert(view*model)&#xD;&#xA;    uniform mat4 priv_mat; //projection-view-model pre multiplied&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; //after view*lightpos, aka viewspace&#xD;&#xA;&#xD;&#xA;    out vec2 fUV; //fragment uv&#xD;&#xA;    out vec3 lightdir; //tangent lightdir&#xD;&#xA;    out vec3 viewdir; //tangent viewdir&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec3 norm=normalize(normalmatrix*vertex_normal);&#xD;&#xA;	    vec3 tang=normalize(normalmatrix*vec3(vertex_tangent));&#xD;&#xA;	    tang= normalize(tang - dot(tang, norm) * norm); //Gramm-Schmidt process&#xD;&#xA;	    vec3 binormal=normalize(cross(norm,tang));&#xD;&#xA;&#xD;&#xA;	    //matrix for transformation to tangent space&#xD;&#xA;	    mat3 tbn=mat3(tang,binormal,norm);&#xD;&#xA;&#xD;&#xA;	    //turn light dir and view dir to tangent space&#xD;&#xA;	    vec3 pos=vec3(modelviewmatrix*vec4(vertex_position,1.0));&#xD;&#xA;	    lightdir=normalize(tbn*(LightPosition.xyz-pos));&#xD;&#xA;	    viewdir=tbn*normalize(-pos); //tangent view&#xD;&#xA;&#xD;&#xA;	    fUV=tex_cord; //uv&#xD;&#xA;	    gl_Position=priv_mat*vec4(vertex_position,1.0); //model&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And fragment&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;&#xD;&#xA;	in vec2 fUV;&#xD;&#xA;	in float len;&#xD;&#xA;&#xD;&#xA;	in vec3 lightdir; //tang light&#xD;&#xA;	in vec3 viewdir; //tang view&#xD;&#xA;&#xD;&#xA;	uniform sampler2D png_tex;&#xD;&#xA;	uniform sampler2D bump_map;&#xD;&#xA;&#xD;&#xA;	uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;	uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;	uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;	uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;	uniform float Shininess;    // Specular shininess factor&#xD;&#xA;&#xD;&#xA;	out vec4 Color;&#xD;&#xA;&#xD;&#xA;	vec3 phongmodel(vec3 norm, vec3 diffr){&#xD;&#xA;		vec3 r=reflect(-lightdir,norm);&#xD;&#xA;		vec3 ambient=LightIntensity*Ka;&#xD;&#xA;		float sdotn=max(dot(lightdir,norm),0.0);&#xD;&#xA;		vec3 diffuse = LightIntensity*diffr*sdotn;&#xD;&#xA;		vec3 spec=vec3(0.0);&#xD;&#xA;	if(sdotn&gt;0.0)spec=LightIntensity*Ks*pow(max(dot(r,viewdir),0.0),Shininess);&#xD;&#xA;	return ambient+diffuse+spec;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		vec4 bump_normal=texture(bump_map, fUV);&#xD;&#xA;		vec4 tex_color=texture(png_tex,fUV);&#xD;&#xA;		Color=vec4(phongmodel(bump_normal.xyz,tex_color.rgb),1.0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I only get this result:&#xD;&#xA;&#xD;&#xA;[![when rotated it turns dark][4]][4]&#xD;&#xA;&#xD;&#xA;Which has 2 obvious errors: When I rotate the object, the shading doesnt follow the lightsource+goes from dark to full bright, and, it seems to have dents at seams where the cube-sphere wraps. The normalmapping seems to work tho, but again I struggle with the shading. Is there an obvious error here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html&#xD;&#xA;  [2]: http://renderdan.blogspot.no/2006/05/rotation-matrix-from-axis-vectors.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4DUfwAEx4Ts&#xD;&#xA;  [4]: https://i.stack.imgur.com/BBvQS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11844" PostHistoryTypeId="1" PostId="4935" RevisionGUID="109cab67-ebdb-4ec1-92e7-fa19c69d68d8" CreationDate="2017-03-30T14:25:30.000" UserId="6255" Text="NormalMap problems: it just wont work c++/glsl" ContentLicense="CC BY-SA 3.0" />
  <row Id="11845" PostHistoryTypeId="3" PostId="4935" RevisionGUID="109cab67-ebdb-4ec1-92e7-fa19c69d68d8" CreationDate="2017-03-30T14:25:30.000" UserId="6255" Text="|opengl|glsl|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11846" PostHistoryTypeId="5" PostId="4935" RevisionGUID="7b7fa25e-9eb9-4e6d-8d5a-4d7d6e0743ac" CreationDate="2017-03-30T14:31:10.623" UserId="6255" Comment="added 8 characters in body" Text="I've been trying to figure this out for a few days now, but I just cant get it right. Ive read multiple [tutorials][1] and [possible][2] explanations, I even watched a [java tutorial][3] without finding the solution. This is what I do:&#xD;&#xA;&#xD;&#xA;First I build the tangent values to pass as attributes:&#xD;&#xA;&#xD;&#xA;    float f;&#xD;&#xA;	vec3 edge1, edge2, tangentbuf;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;    //for each face, x=vert,y=uv, z=normal&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		normalize(tangentref[tangentcount++]);&#xD;&#xA;		tangentref[totalrefs[i] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 3] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 6] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x); //just normalize is enough?&#xD;&#xA;&#xD;&#xA;Normalizing or dividing seems to give the same result, and I think this is correct this far. With these shaders:&#xD;&#xA;&#xD;&#xA;vert&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec2 tex_cord;&#xD;&#xA;    layout ( location = 2 ) in vec3 vertex_normal;&#xD;&#xA;    layout ( location = 3 ) in vec3 vertex_tangent;&#xD;&#xA;&#xD;&#xA;    uniform mat4 modelviewmatrix; //view*model matrix&#xD;&#xA;    uniform mat3 normalmatrix; // transpose/invert(view*model)&#xD;&#xA;    uniform mat4 priv_mat; //projection-view-model pre multiplied&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; //after view*lightpos, aka viewspace&#xD;&#xA;&#xD;&#xA;    out vec2 fUV; //fragment uv&#xD;&#xA;    out vec3 lightdir; //tangent lightdir&#xD;&#xA;    out vec3 viewdir; //tangent viewdir&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec3 norm=normalize(normalmatrix*vertex_normal);&#xD;&#xA;	    vec3 tang=normalize(normalmatrix*vec3(vertex_tangent));&#xD;&#xA;	         tang= normalize(tang - dot(tang, norm) * norm); //Gramm-Schmidt&#xD;&#xA;	    vec3 binormal=normalize(cross(norm,tang));&#xD;&#xA;&#xD;&#xA;	    //matrix for transformation to tangent space&#xD;&#xA;	    mat3 tbn=mat3(tang,binormal,norm);&#xD;&#xA;&#xD;&#xA;	    //turn light dir and view dir to tangent space&#xD;&#xA;	    vec3 pos=vec3(modelviewmatrix*vec4(vertex_position,1.0));&#xD;&#xA;	    lightdir=normalize(tbn*(LightPosition.xyz-pos));&#xD;&#xA;	    viewdir=tbn*normalize(-pos); //tangent view&#xD;&#xA;&#xD;&#xA;	    fUV=tex_cord; //uv&#xD;&#xA;	    gl_Position=priv_mat*vec4(vertex_position,1.0); //model&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And frag&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;&#xD;&#xA;	in vec2 fUV;&#xD;&#xA;	in vec3 lightdir; //tang light&#xD;&#xA;	in vec3 viewdir; //tang view&#xD;&#xA;&#xD;&#xA;	uniform sampler2D png_tex;&#xD;&#xA;	uniform sampler2D bump_map;&#xD;&#xA;&#xD;&#xA;	uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;	uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;	uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;	uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;	uniform float Shininess;    // Specular shininess factor&#xD;&#xA;&#xD;&#xA;	out vec4 Color;&#xD;&#xA;&#xD;&#xA;	vec3 phongmodel(vec3 norm, vec3 diffr){&#xD;&#xA;		vec3 r=reflect(-lightdir,norm);&#xD;&#xA;		vec3 ambient=LightIntensity*Ka;&#xD;&#xA;		float sdotn=max(dot(lightdir,norm),0.0);&#xD;&#xA;		vec3 diffuse = LightIntensity*diffr*sdotn;&#xD;&#xA;		vec3 spec=vec3(0.0);&#xD;&#xA;	    if(sdotn&gt;0.0)&#xD;&#xA;            spec=LightIntensity*Ks*pow(max(dot(r,viewdir),0.0),Shininess);&#xD;&#xA;	    return ambient+diffuse+spec;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		vec4 bump_normal=texture(bump_map, fUV);&#xD;&#xA;		vec4 tex_color=texture(png_tex,fUV);&#xD;&#xA;		Color=vec4(phongmodel(bump_normal.xyz,tex_color.rgb),1.0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I only get this result:&#xD;&#xA;&#xD;&#xA;[![when rotated it turns dark][4]][4]&#xD;&#xA;&#xD;&#xA;Which has 2 obvious errors: When I rotate the object, the shading doesnt follow the lightsource+goes from dark to full bright, and, it seems to have dents at seams where the cube-sphere wraps. The normalmapping seems to work tho, but again I struggle with the shading. Is there an obvious error here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html&#xD;&#xA;  [2]: http://renderdan.blogspot.no/2006/05/rotation-matrix-from-axis-vectors.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4DUfwAEx4Ts&#xD;&#xA;  [4]: https://i.stack.imgur.com/BBvQS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11847" PostHistoryTypeId="4" PostId="4935" RevisionGUID="7b7fa25e-9eb9-4e6d-8d5a-4d7d6e0743ac" CreationDate="2017-03-30T14:31:10.623" UserId="6255" Comment="added 8 characters in body" Text="NormalMap problems: bumps work, but shade does not c++/glsl" ContentLicense="CC BY-SA 3.0" />
  <row Id="11848" PostHistoryTypeId="5" PostId="4935" RevisionGUID="852f2e44-4e44-45ee-95b7-7798324c7be6" CreationDate="2017-03-30T14:36:36.427" UserId="6255" Comment="added 8 characters in body" Text="I've been trying to figure this out for a few days now, but I just cant get it right. Ive read multiple [tutorials][1] and [possible][2] explanations, I even watched a [java tutorial][3] without finding the solution. This is what I do:&#xD;&#xA;&#xD;&#xA;First I build the tangent values to pass as attributes:&#xD;&#xA;&#xD;&#xA;    float f;&#xD;&#xA;	vec3 edge1, edge2, tangentbuf;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;    //for each face, x=vert,y=uv, z=normal&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		normalize(tangentref[tangentcount++]);&#xD;&#xA;		tangentref[totalrefs[i] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 3] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 6] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x); //just normalize is enough?&#xD;&#xA;&#xD;&#xA;Normalizing or dividing seems to give the same result, and I think this is correct this far. With these shaders:&#xD;&#xA;&#xD;&#xA;vert&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec2 tex_cord;&#xD;&#xA;    layout ( location = 2 ) in vec3 vertex_normal;&#xD;&#xA;    layout ( location = 3 ) in vec3 vertex_tangent;&#xD;&#xA;&#xD;&#xA;    uniform mat4 modelviewmatrix; //view*model matrix&#xD;&#xA;    uniform mat3 normalmatrix; // transpose/invert(view*model)&#xD;&#xA;    uniform mat4 priv_mat; //projection-view-model pre multiplied&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; //after view*lightpos, aka viewspace&#xD;&#xA;&#xD;&#xA;    out vec2 fUV; //fragment uv&#xD;&#xA;    out vec3 lightdir; //tangent lightdir&#xD;&#xA;    out vec3 viewdir; //tangent viewdir&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec3 norm = normalize(normalmatrix*vertex_normal);&#xD;&#xA;	    vec3 tang = normalize(normalmatrix*vec3(vertex_tangent));&#xD;&#xA;	         tang = normalize(tang - dot(tang, norm) * norm); //Gramm-Schmidt&#xD;&#xA;	    vec3 binormal = normalize(cross(norm,tang));&#xD;&#xA;&#xD;&#xA;	    //matrix for transformation to tangent space&#xD;&#xA;	    mat3 tbn=mat3(tang,binormal,norm);&#xD;&#xA;&#xD;&#xA;	    //turn light dir and view dir to tangent space&#xD;&#xA;	    vec3 pos = vec3(modelviewmatrix*vec4(vertex_position,1.0));&#xD;&#xA;	    lightdir = normalize(tbn*(LightPosition.xyz-pos));&#xD;&#xA;	    viewdir  =tbn*normalize(-pos); //tangent view&#xD;&#xA;&#xD;&#xA;	    fUV = tex_cord; //uv&#xD;&#xA;	    gl_Position = priv_mat*vec4(vertex_position,1.0); //model&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And frag&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;&#xD;&#xA;	in vec2 fUV;&#xD;&#xA;	in vec3 lightdir; //tang light&#xD;&#xA;	in vec3 viewdir; //tang view&#xD;&#xA;&#xD;&#xA;	uniform sampler2D png_tex;&#xD;&#xA;	uniform sampler2D bump_map;&#xD;&#xA;&#xD;&#xA;	uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;	uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;	uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;	uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;	uniform float Shininess;    // Specular shininess factor&#xD;&#xA;&#xD;&#xA;	out vec4 Color;&#xD;&#xA;&#xD;&#xA;	vec3 phongmodel(vec3 norm, vec3 diffr){&#xD;&#xA;		vec3 r=reflect(-lightdir,norm);&#xD;&#xA;		vec3 ambient = LightIntensity*Ka;&#xD;&#xA;		float sdotn = max(dot(lightdir,norm),0.0);&#xD;&#xA;		vec3 diffuse = LightIntensity*diffr*sdotn;&#xD;&#xA;		vec3 spec = vec3(0.0);&#xD;&#xA;	    if(sdotn&gt;0.0)&#xD;&#xA;            spec = LightIntensity*Ks*pow(max(dot(r,viewdir),0.0),Shininess);&#xD;&#xA;	    return ambient+diffuse+spec;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		vec4 bump_normal=texture(bump_map, fUV);&#xD;&#xA;		vec4 tex_color=texture(png_tex,fUV);&#xD;&#xA;		Color = vec4(phongmodel(bump_normal.xyz,tex_color.rgb),1.0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I only get this result:&#xD;&#xA;&#xD;&#xA;[![when rotated it turns dark][4]][4]&#xD;&#xA;&#xD;&#xA;Which has 2 obvious errors: When I rotate the object, the shading doesnt follow the lightsource+goes from dark to full bright, and, it seems to have dents at seams where the cube-sphere wraps. The normalmapping seems to work tho, but again I struggle with the shading. Is there an obvious error here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html&#xD;&#xA;  [2]: http://renderdan.blogspot.no/2006/05/rotation-matrix-from-axis-vectors.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4DUfwAEx4Ts&#xD;&#xA;  [4]: https://i.stack.imgur.com/BBvQS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11849" PostHistoryTypeId="2" PostId="4936" RevisionGUID="a41732e7-9197-4731-bb71-e5ca023ab62c" CreationDate="2017-03-30T14:46:56.553" UserId="6092" Text="I have got a texture ID and would like to retrieve its data. The data should be stored in a `BufferedImage` for future use. I am using the LWJGL library in Java, so if there are some library-specific shortcuts I'd like to use them.&#xD;&#xA;&#xD;&#xA;My naive approach is to first fill a buffer with the image data and then pass it to the image.&#xD;&#xA;&#xD;&#xA;			int id = ...;&#xD;&#xA;			IntBuffer buff = BufferUtils.createIntBuffer(1024*512*4);&#xD;&#xA;			GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);&#xD;&#xA;			System.out.println(buff.remaining());&#xD;&#xA;			GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, buff);&#xD;&#xA;			System.out.println(buff.remaining());&#xD;&#xA;			buff.flip();&#xD;&#xA;			buff.rewind();&#xD;&#xA;			System.out.println(buff.remaining());&#xD;&#xA;			// Somehow create a BufferedImage from buff here&#xD;&#xA;&#xD;&#xA;I don't know why, but the first and to `buff.remaining()` return the same value, indicating that nothing has been written which should not be the case." ContentLicense="CC BY-SA 3.0" />
  <row Id="11850" PostHistoryTypeId="1" PostId="4936" RevisionGUID="a41732e7-9197-4731-bb71-e5ca023ab62c" CreationDate="2017-03-30T14:46:56.553" UserId="6092" Text="LWJGL/OpenGL get BufferedImage from texture ID" ContentLicense="CC BY-SA 3.0" />
  <row Id="11851" PostHistoryTypeId="3" PostId="4936" RevisionGUID="a41732e7-9197-4731-bb71-e5ca023ab62c" CreationDate="2017-03-30T14:46:56.553" UserId="6092" Text="|opengl|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11852" PostHistoryTypeId="5" PostId="4935" RevisionGUID="132ee12e-dc88-4e32-a1b7-bf0c82c3b9c7" CreationDate="2017-03-30T15:03:08.927" UserId="6255" Comment="edited body" Text="I've been trying to figure this out for a few days now, but I just cant get it right. Ive read multiple [tutorials][1] and [possible][2] explanations, I even watched a [java tutorial][3] without finding the solution. This is what I do:&#xD;&#xA;&#xD;&#xA;First I build the tangent values to pass as attributes:&#xD;&#xA;&#xD;&#xA;    float f;&#xD;&#xA;	vec3 edge1, edge2, tangentbuf;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;    //for each face, x=vert,y=uv, z=normal&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		normalize(tangentref[tangentcount++]);&#xD;&#xA;		tangentref[totalrefs[i] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 3] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 6] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x); //just normalize is enough?&#xD;&#xA;&#xD;&#xA;Normalizing or dividing seems to give the same result, and I think this is correct this far. With these shaders:&#xD;&#xA;&#xD;&#xA;vert&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec2 tex_cord;&#xD;&#xA;    layout ( location = 2 ) in vec3 vertex_normal;&#xD;&#xA;    layout ( location = 3 ) in vec3 vertex_tangent;&#xD;&#xA;&#xD;&#xA;    uniform mat4 modelviewmatrix; //view*model matrix&#xD;&#xA;    uniform mat3 normalmatrix; // transpose/invert(view*model)&#xD;&#xA;    uniform mat4 priv_mat; //projection-view-model pre multiplied&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; //after view*lightpos, aka viewspace&#xD;&#xA;&#xD;&#xA;    out vec2 fUV; //fragment uv&#xD;&#xA;    out vec3 lightdir; //tangent lightdir&#xD;&#xA;    out vec3 viewdir; //tangent viewdir&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec3 norm = normalize(normalmatrix*vertex_normal);&#xD;&#xA;	    vec3 tang = normalize(normalmatrix*vec3(vertex_tangent));&#xD;&#xA;	         tang = normalize(tang - dot(tang, norm) * norm); //Gramm-Schmidt&#xD;&#xA;	    vec3 binormal = normalize(cross(tang,norm));&#xD;&#xA;&#xD;&#xA;	    //matrix for transformation to tangent space&#xD;&#xA;	    mat3 tbn=mat3(tang,binormal,norm);&#xD;&#xA;&#xD;&#xA;	    //turn light dir and view dir to tangent space&#xD;&#xA;	    vec3 pos = vec3(modelviewmatrix*vec4(vertex_position,1.0));&#xD;&#xA;	    lightdir = normalize(tbn*(LightPosition.xyz-pos));&#xD;&#xA;	    viewdir  =tbn*normalize(-pos); //tangent view&#xD;&#xA;&#xD;&#xA;	    fUV = tex_cord; //uv&#xD;&#xA;	    gl_Position = priv_mat*vec4(vertex_position,1.0); //model&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And frag&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;&#xD;&#xA;	in vec2 fUV;&#xD;&#xA;	in vec3 lightdir; //tang light&#xD;&#xA;	in vec3 viewdir; //tang view&#xD;&#xA;&#xD;&#xA;	uniform sampler2D png_tex;&#xD;&#xA;	uniform sampler2D bump_map;&#xD;&#xA;&#xD;&#xA;	uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;	uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;	uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;	uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;	uniform float Shininess;    // Specular shininess factor&#xD;&#xA;&#xD;&#xA;	out vec4 Color;&#xD;&#xA;&#xD;&#xA;	vec3 phongmodel(vec3 norm, vec3 diffr){&#xD;&#xA;		vec3 r=reflect(-lightdir,norm);&#xD;&#xA;		vec3 ambient = LightIntensity*Ka;&#xD;&#xA;		float sdotn = max(dot(lightdir,norm),0.0);&#xD;&#xA;		vec3 diffuse = LightIntensity*diffr*sdotn;&#xD;&#xA;		vec3 spec = vec3(0.0);&#xD;&#xA;	    if(sdotn&gt;0.0)&#xD;&#xA;            spec = LightIntensity*Ks*pow(max(dot(r,viewdir),0.0),Shininess);&#xD;&#xA;	    return ambient+diffuse+spec;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		vec4 bump_normal=texture(bump_map, fUV);&#xD;&#xA;		vec4 tex_color=texture(png_tex,fUV);&#xD;&#xA;		Color = vec4(phongmodel(bump_normal.xyz,tex_color.rgb),1.0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I only get this result:&#xD;&#xA;&#xD;&#xA;[![when rotated it turns dark][4]][4]&#xD;&#xA;&#xD;&#xA;Which has 2 obvious errors: When I rotate the object, the shading doesnt follow the lightsource+goes from dark to full bright, and, it seems to have dents at seams where the cube-sphere wraps. The normalmapping seems to work tho, but again I struggle with the shading. Is there an obvious error here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html&#xD;&#xA;  [2]: http://renderdan.blogspot.no/2006/05/rotation-matrix-from-axis-vectors.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4DUfwAEx4Ts&#xD;&#xA;  [4]: https://i.stack.imgur.com/BBvQS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11854" PostHistoryTypeId="2" PostId="4937" RevisionGUID="67db32d0-1710-4738-8fa9-14656406d5f2" CreationDate="2017-03-30T21:34:25.473" UserId="2372" Text="I discovered that some engines use **derivative maps** instead of **tangent space normal maps**.&#xD;&#xA;&#xD;&#xA;After some reading, it seems to be a really awesome way to replace tangent space normals but are there some disadvantage using them ? Why still continue using tangent space normals ?&#xD;&#xA;&#xD;&#xA;Is it possible to compare both with advantage and disadvantage ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11855" PostHistoryTypeId="1" PostId="4937" RevisionGUID="67db32d0-1710-4738-8fa9-14656406d5f2" CreationDate="2017-03-30T21:34:25.473" UserId="2372" Text="Derivative maps vs. Tangent Space Normal maps" ContentLicense="CC BY-SA 3.0" />
  <row Id="11856" PostHistoryTypeId="3" PostId="4937" RevisionGUID="67db32d0-1710-4738-8fa9-14656406d5f2" CreationDate="2017-03-30T21:34:25.473" UserId="2372" Text="|opengl|shader|texture|normal-mapping|directx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11857" PostHistoryTypeId="2" PostId="4938" RevisionGUID="99eac465-80f1-4a64-8c27-62e73be55c02" CreationDate="2017-03-31T01:56:23.087" UserId="4776" Text="To make it a more complete example, let's also consider loading a texture from a `BufferedImage`.&#xD;&#xA;&#xD;&#xA;First let's assume:&#xD;&#xA;&#xD;&#xA;    int texture = glGenTextures();&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;When loading an image you can use `ImageIO.read()` and put all the pixels into a `ByteBuffer`.&#xD;&#xA;&#xD;&#xA;    BufferedImage image = ImageIO.read(new File(&quot;image.png&quot;));&#xD;&#xA;    int width = image.getWidth(), height = image.getHeight();&#xD;&#xA;&#xD;&#xA;    int[] pixels = new int[width * height];&#xD;&#xA;    image.getRGB(0, 0, width, height, pixels, 0, width);&#xD;&#xA;&#xD;&#xA;    ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * 4); // 4 because RGBA&#xD;&#xA;&#xD;&#xA;    for(int y = 0; y &lt; height; ++y) {&#xD;&#xA;        for(int x = 0; x &lt; width; ++x) {&#xD;&#xA;            int pixel = pixels[x + y * width];&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 16) &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 8) &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) (pixel &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 24) &amp; 0xFF));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    buffer.flip();&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;&#xD;&#xA;Before we go ahead and call `glGetTexImage()` lets assume that the only thing we have is the texture name (`texture`). Thus we consider that we don't know the size or format of the texture. We can get all this by doing:&#xD;&#xA;&#xD;&#xA;    int format = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT);&#xD;&#xA;    int width = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH);&#xD;&#xA;    int height = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT);&#xD;&#xA;&#xD;&#xA;Using that information we again create a `ByteBuffer` as well as a `BufferedImage`. Pulling the pixels from the `ByteBuffer` and placing them on the `BufferedImage`.&#xD;&#xA;&#xD;&#xA;    int channels = 4;&#xD;&#xA;    if (format == GL_RGB)&#xD;&#xA;        channels = 3;&#xD;&#xA;&#xD;&#xA;    ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * channels);&#xD;&#xA;    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);&#xD;&#xA;&#xD;&#xA;    glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;&#xD;&#xA;    for (int x = 0; x &lt; width; ++x) {&#xD;&#xA;        for (int y = 0; y &lt; height; ++y) {&#xD;&#xA;            int i = (x + y * width) * channels;&#xD;&#xA;&#xD;&#xA;            int r = buffer.get(i) &amp; 0xFF;&#xD;&#xA;            int g = buffer.get(i + 1) &amp; 0xFF;&#xD;&#xA;            int b = buffer.get(i + 2) &amp; 0xFF;&#xD;&#xA;            int a = 255;&#xD;&#xA;            if (channels == 4)&#xD;&#xA;                a = buffer.get(i + 3) &amp; 0xFF;&#xD;&#xA;&#xD;&#xA;            image.setRGB(x, y, (a &lt;&lt; 24) | (r &lt;&lt; 16) | (g &lt;&lt; 8) | b);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now go ahead and save that `BufferedImage` to a file.&#xD;&#xA;&#xD;&#xA;    ImageIO.write(image, &quot;PNG&quot;, new File(&quot;out.png&quot;));&#xD;&#xA;&#xD;&#xA;Last but not least, you can get rid of all those `GL11.` prefixes, by statically importing `GL11`. You do that by doing:&#xD;&#xA;&#xD;&#xA;    import static org.lwjgl.opengl.GL11.*;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11858" PostHistoryTypeId="5" PostId="4938" RevisionGUID="63c59c54-b2d3-41e7-8bbc-71218148ddd5" CreationDate="2017-03-31T02:01:56.310" UserId="4776" Comment="added 27 characters in body" Text="To make it a more complete example, let's also consider loading a texture from a `BufferedImage`.&#xD;&#xA;&#xD;&#xA;First let's assume:&#xD;&#xA;&#xD;&#xA;    int texture = glGenTextures();&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;When loading an image you can use `ImageIO.read()`. Then put all the pixels from the `BufferedImage` into a `ByteBuffer`.&#xD;&#xA;&#xD;&#xA;    BufferedImage image = ImageIO.read(new File(&quot;image.png&quot;));&#xD;&#xA;    int width = image.getWidth(), height = image.getHeight();&#xD;&#xA;&#xD;&#xA;    int[] pixels = new int[width * height];&#xD;&#xA;    image.getRGB(0, 0, width, height, pixels, 0, width);&#xD;&#xA;&#xD;&#xA;    ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * 4); // 4 because RGBA&#xD;&#xA;&#xD;&#xA;    for(int y = 0; y &lt; height; ++y) {&#xD;&#xA;        for(int x = 0; x &lt; width; ++x) {&#xD;&#xA;            int pixel = pixels[x + y * width];&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 16) &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 8) &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) (pixel &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 24) &amp; 0xFF));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    buffer.flip();&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;&#xD;&#xA;Before we go ahead and call `glGetTexImage()` lets assume that the only thing we have is the texture name (`texture`). Thus we consider that we don't know the size or format of the texture. We can get all this by doing:&#xD;&#xA;&#xD;&#xA;    int format = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT);&#xD;&#xA;    int width = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH);&#xD;&#xA;    int height = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT);&#xD;&#xA;&#xD;&#xA;Using that information we again create a `ByteBuffer` as well as a `BufferedImage`. Reading the pixels from the `ByteBuffer` and placing them on the `BufferedImage`.&#xD;&#xA;&#xD;&#xA;    int channels = 4;&#xD;&#xA;    if (format == GL_RGB)&#xD;&#xA;        channels = 3;&#xD;&#xA;&#xD;&#xA;    ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * channels);&#xD;&#xA;    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);&#xD;&#xA;&#xD;&#xA;    glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;&#xD;&#xA;    for (int x = 0; x &lt; width; ++x) {&#xD;&#xA;        for (int y = 0; y &lt; height; ++y) {&#xD;&#xA;            int i = (x + y * width) * channels;&#xD;&#xA;&#xD;&#xA;            int r = buffer.get(i) &amp; 0xFF;&#xD;&#xA;            int g = buffer.get(i + 1) &amp; 0xFF;&#xD;&#xA;            int b = buffer.get(i + 2) &amp; 0xFF;&#xD;&#xA;            int a = 255;&#xD;&#xA;            if (channels == 4)&#xD;&#xA;                a = buffer.get(i + 3) &amp; 0xFF;&#xD;&#xA;&#xD;&#xA;            image.setRGB(x, y, (a &lt;&lt; 24) | (r &lt;&lt; 16) | (g &lt;&lt; 8) | b);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now go ahead and save that `BufferedImage` to a file.&#xD;&#xA;&#xD;&#xA;    ImageIO.write(image, &quot;PNG&quot;, new File(&quot;out.png&quot;));&#xD;&#xA;&#xD;&#xA;Last but not least, you can get rid of all those `GL11.` prefixes, by statically importing `GL11`. You do that by doing:&#xD;&#xA;&#xD;&#xA;    import static org.lwjgl.opengl.GL11.*;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11859" PostHistoryTypeId="5" PostId="4938" RevisionGUID="22def01c-cca1-4ca3-b3dd-bd078aaa9b7b" CreationDate="2017-03-31T03:09:59.420" UserId="4776" Comment="added 29 characters in body" Text="To make it a more complete example, let's also consider loading a texture from a `BufferedImage` as well.&#xD;&#xA;&#xD;&#xA;First let's assume:&#xD;&#xA;&#xD;&#xA;    int texture = glGenTextures();&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;First we need to load an image. For this we can use `ImageIO.read()`. Then we put all the pixels from the `BufferedImage` into a `ByteBuffer`.&#xD;&#xA;&#xD;&#xA;    BufferedImage image = ImageIO.read(new File(&quot;image.png&quot;));&#xD;&#xA;    int width = image.getWidth(), height = image.getHeight();&#xD;&#xA;&#xD;&#xA;    int[] pixels = new int[width * height];&#xD;&#xA;    image.getRGB(0, 0, width, height, pixels, 0, width);&#xD;&#xA;&#xD;&#xA;    ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * 4); // 4 because RGBA&#xD;&#xA;&#xD;&#xA;    for(int y = 0; y &lt; height; ++y) {&#xD;&#xA;        for(int x = 0; x &lt; width; ++x) {&#xD;&#xA;            int pixel = pixels[x + y * width];&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 16) &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 8) &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) (pixel &amp; 0xFF));&#xD;&#xA;            buffer.put((byte) ((pixel &gt;&gt; 24) &amp; 0xFF));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    buffer.flip();&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;&#xD;&#xA;Before we go ahead and call `glGetTexImage()` lets assume that the only thing we have is the texture name (`texture`). Thus we consider that we don't know the size or format of the texture. We can get all this by doing:&#xD;&#xA;&#xD;&#xA;    int format = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT);&#xD;&#xA;    int width = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH);&#xD;&#xA;    int height = glGetTexLevelParameteri(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT);&#xD;&#xA;&#xD;&#xA;Using that information we again create a `ByteBuffer` as well as a `BufferedImage`. Reading the pixels from the `ByteBuffer` and placing them on the `BufferedImage`.&#xD;&#xA;&#xD;&#xA;    int channels = 4;&#xD;&#xA;    if (format == GL_RGB)&#xD;&#xA;        channels = 3;&#xD;&#xA;&#xD;&#xA;    ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * channels);&#xD;&#xA;    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);&#xD;&#xA;&#xD;&#xA;    glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;&#xD;&#xA;    for (int x = 0; x &lt; width; ++x) {&#xD;&#xA;        for (int y = 0; y &lt; height; ++y) {&#xD;&#xA;            int i = (x + y * width) * channels;&#xD;&#xA;&#xD;&#xA;            int r = buffer.get(i) &amp; 0xFF;&#xD;&#xA;            int g = buffer.get(i + 1) &amp; 0xFF;&#xD;&#xA;            int b = buffer.get(i + 2) &amp; 0xFF;&#xD;&#xA;            int a = 255;&#xD;&#xA;            if (channels == 4)&#xD;&#xA;                a = buffer.get(i + 3) &amp; 0xFF;&#xD;&#xA;&#xD;&#xA;            image.setRGB(x, y, (a &lt;&lt; 24) | (r &lt;&lt; 16) | (g &lt;&lt; 8) | b);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now go ahead and save that `BufferedImage` to a file.&#xD;&#xA;&#xD;&#xA;    ImageIO.write(image, &quot;PNG&quot;, new File(&quot;out.png&quot;));&#xD;&#xA;&#xD;&#xA;Last but not least, you can get rid of all those `GL11.` prefixes, by statically importing `GL11`. You do that by doing:&#xD;&#xA;&#xD;&#xA;    import static org.lwjgl.opengl.GL11.*;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11861" PostHistoryTypeId="2" PostId="4939" RevisionGUID="f185feaf-4813-4b30-91a2-b4ea42329dbc" CreationDate="2017-03-31T17:08:41.877" UserId="6255" Text="Silly me, posting all of this hoping to get someone to solve it for me, I managed to find the solution tho, but perhaps more as a result of trial and error, than of actual understanding. Either way, this is the object I'm looking at now:&#xD;&#xA;&#xD;&#xA;[![UV ordering, transpose and crossing in the wrong order][1]][1]&#xD;&#xA;&#xD;&#xA;Looking at the correct tangent calculation:&#xD;&#xA;&#xD;&#xA;    vector&lt;vec4&gt;tangentref(texkoordref.size()); //math UV size, w=amount for divide&#xD;&#xA;	vec3 tangentbuf;&#xD;&#xA;&#xD;&#xA;	float f;&#xD;&#xA;	vec3 edge1, edge2;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		//i=vert, i+1=uv, i+2 vn//i+3=vert2,i+4=uv2,i+5=vn2;//i+6=vert3, i+7=uv3, i+8=vn3;&#xD;&#xA;		//get the tangent for each face&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		//one tangent per uv coordinate&#xD;&#xA;		tangentref[totalrefs[i+1] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 4] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 7] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;    //some tutorials say to just normalize these&#xD;&#xA;&#xD;&#xA;I cycle through every face, and totalref[i], is here 9 integers per cycle, that each refer to 0=vert, 1=uv, and 2 vert normal. By populating the tangentref according to each of the UVs, I get a list of tangents that go along with the UV values.&#xD;&#xA;&#xD;&#xA;I think its worth mentioning specifically, the tangents describe not the normal, or the vertex, but the direction of the uv, together with the bitangent, they make out an xy coordinate that describes the UV direction.&#xD;&#xA;&#xD;&#xA;It only makes sense to make tangents according to UVs, and the results are not disagreeing.&#xD;&#xA;&#xD;&#xA;Secondly, I was building the tbn matrix incorrectly.&#xD;&#xA;    &#xD;&#xA;    //in the vert shader&#xD;&#xA;    vec3 bitangent = normalize( cross( n, t ) );&#xD;&#xA;&#xD;&#xA;The bitangent was in the wrong order, and&#xD;&#xA;&#xD;&#xA;    mat3 tbn = transpose(mat3(t,bitangent,n)); //why transpose??&#xD;&#xA;&#xD;&#xA;The tbn was supposed to be transpose. Transpose is cheap (apparently) so thats not a problem, but why exactly this is correct? I'm not sure.&#xD;&#xA;&#xD;&#xA;It works however, so maybe It will make sense later.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cN0vN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11862" PostHistoryTypeId="5" PostId="4935" RevisionGUID="c78250b9-b77b-4a6b-95ed-91343c966ff0" CreationDate="2017-03-31T17:16:05.957" UserId="6255" Comment="added 592 characters in body" Text="I've been trying to figure this out for a few days now, but I just cant get it right. Ive read multiple [tutorials][1] and [possible][2] explanations, I even watched a [java tutorial][3] without finding the solution. This is what I do:&#xD;&#xA;&#xD;&#xA;First I build the tangent values to pass as attributes:&#xD;&#xA;&#xD;&#xA;    //this parsing has not been updated, unlike the shaders, correct parsing in the answer below&#xD;&#xA;    float f;&#xD;&#xA;	vec3 edge1, edge2, tangentbuf;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;    //for each face, x=vert,y=uv, z=normal&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		normalize(tangentref[tangentcount++]);&#xD;&#xA;		tangentref[totalrefs[i] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 3] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 6] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x); //just normalize is enough?&#xD;&#xA;&#xD;&#xA;Normalizing or dividing seems to give the same result, and I think this is correct this far. With these shaders:&#xD;&#xA;&#xD;&#xA;vert&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec2 tex_cord;&#xD;&#xA;    layout ( location = 2 ) in vec3 vertex_normal;&#xD;&#xA;    layout ( location = 3 ) in vec3 vertex_tangent;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model; //model matrix, aka model 2 world&#xD;&#xA;&#xD;&#xA;    uniform mat4 modelviewmatrix; //view*model matrix&#xD;&#xA;    uniform mat3 normalmatrix; // transpose/invert(view*model)&#xD;&#xA;    uniform mat4 priv_mat; //projection-view-model pre multiplied&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; //after view*lightpos, ie viewspace&#xD;&#xA;&#xD;&#xA;    out vec3 lightdir;&#xD;&#xA;    out vec3 viewdir;&#xD;&#xA;    out vec2 fUV;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;	    fUV=tex_cord;&#xD;&#xA;	    position=(model*vec4(vertex_position,1.0)).xyz;&#xD;&#xA;	    len=length(vertex_position);&#xD;&#xA;&#xD;&#xA;	    // Transform normal and tangent to eye space&#xD;&#xA;        vec3 n = normalize(normalmatrix * vertex_normal);&#xD;&#xA;        vec3 t = normalize(normalmatrix * vec3(vertex_tangent));&#xD;&#xA;	    	 t = normalize(t-dot(t,n)*n);  //Gramm-Schmidt process&#xD;&#xA;	    vec3 bitangent = normalize( cross( n, t ) );&#xD;&#xA;	    mat3 tbn = transpose(mat3(t,bitangent,n)); //why transpose??&#xD;&#xA;&#xD;&#xA;	    vec3 pos=vec3(modelviewmatrix*vec4(vertex_position,1.0));&#xD;&#xA;&#xD;&#xA;	    // Transform light dir. and view dir. to tangent space&#xD;&#xA;	    lightdir = normalize( tbn *  (LightPosition.xyz - pos) );&#xD;&#xA;	    viewdir = tbn * normalize(-pos);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And frag&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;&#xD;&#xA;    in float len;&#xD;&#xA;    in vec3 lightdir; //tang light&#xD;&#xA;    in vec3 viewdir; //tang view&#xD;&#xA;    in vec2 fUV;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D png_tex;&#xD;&#xA;    uniform sampler2D bump_map;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition;&#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Specular shininess factor&#xD;&#xA;&#xD;&#xA;    out vec4 Color;&#xD;&#xA;    vec3 phongModel( vec3 norm, vec3 diffr );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 b_normal = (255.0/128.0) * texture( bump_map, fUV )-1.0; // Lookup the normal from the normal map&#xD;&#xA;        vec4 texColor = texture( png_tex, fUV ); // The color texture is used as the diffuse reflectivity&#xD;&#xA;        Color = vec4( phongModel(b_normal.xyz, texColor.rgb), 1.0 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec3 phongModel( vec3 norm, vec3 diffr )&#xD;&#xA;    {&#xD;&#xA;	    vec3 r = reflect( -lightdir, norm );&#xD;&#xA;	    vec3 ambient = LightIntensity * Ka;&#xD;&#xA;	    float sDotN = max( dot(lightdir, norm), 0.0 );&#xD;&#xA;        vec3 diffuse = Kd*LightIntensity * diffr * sDotN;&#xD;&#xA;        vec3 spec = vec3(0.0);&#xD;&#xA;        if( sDotN &gt; 0.0 )&#xD;&#xA;            spec = LightIntensity * Ks * pow( max( dot(r,viewdir), 0.0 ), Shininess );&#xD;&#xA;        return ambient + diffuse + spec;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I only got this result: //the shaders are updated as I went along, so the ones posted above work (for me anyway)&#xD;&#xA;&#xD;&#xA;[![when rotated it turns dark][4]][4]&#xD;&#xA;&#xD;&#xA;Which has 2 obvious errors: When I rotate the object, the shading doesnt follow the lightsource+goes from dark to full bright, and, it seems to have dents at seams where the cube-sphere wraps. The normalmapping seems to work tho, but again I struggle with the shading. Is there an obvious error here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html&#xD;&#xA;  [2]: http://renderdan.blogspot.no/2006/05/rotation-matrix-from-axis-vectors.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4DUfwAEx4Ts&#xD;&#xA;  [4]: https://i.stack.imgur.com/BBvQS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11863" PostHistoryTypeId="5" PostId="4939" RevisionGUID="c4c1a9a7-b1e0-4bc3-9d57-4d22946762c1" CreationDate="2017-03-31T17:19:28.730" UserId="6255" Comment="added 3 characters in body" Text="Silly me, posting all of this hoping to get someone to solve it for me, I managed to find the solution tho, but perhaps more as a result of trial and error, than of actual understanding. Either way, this is the object I'm looking at now:&#xD;&#xA;&#xD;&#xA;[![UV ordering, transpose and crossing in the wrong order][1]][1]&#xD;&#xA;&#xD;&#xA;Looking at the correct tangent calculation:&#xD;&#xA;&#xD;&#xA;    vector&lt;vec4&gt;tangentref(texkoordref.size()); //math UV size, w=amount for divide&#xD;&#xA;	vec3 tangentbuf;&#xD;&#xA;&#xD;&#xA;	float f;&#xD;&#xA;	vec3 edge1, edge2;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		//i=vert, i+1=uv, i+2 vn//i+3=vert2,i+4=uv2,i+5=vn2;//i+6=vert3, i+7=uv3, i+8=vn3;&#xD;&#xA;		//get the tangent for each face&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		//one tangent per uv coordinate&#xD;&#xA;		tangentref[totalrefs[i+1] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 4] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 7] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;    //some tutorials say to just normalize these&#xD;&#xA;&#xD;&#xA;I cycle through every face, and totalref[i], is here 9 integers per cycle, that each refer to +0=vert, +1=uv, and +2=vert normal. By populating the tangentref according to each of the UVs, I get a list of tangents that go along with the UV values.&#xD;&#xA;&#xD;&#xA;I think its worth mentioning specifically, the tangents describe not the normal, or the vertex, but the direction of the uv, together with the bitangent, they make out an xy coordinate that describes the UV direction.&#xD;&#xA;&#xD;&#xA;It only makes sense to make tangents according to UVs, and the results are not disagreeing.&#xD;&#xA;&#xD;&#xA;Secondly, I was building the tbn matrix incorrectly.&#xD;&#xA;    &#xD;&#xA;    //in the vert shader&#xD;&#xA;    vec3 bitangent = normalize( cross( n, t ) );&#xD;&#xA;&#xD;&#xA;The bitangent was in the wrong order, and&#xD;&#xA;&#xD;&#xA;    mat3 tbn = transpose(mat3(t,bitangent,n)); //why transpose??&#xD;&#xA;&#xD;&#xA;The tbn was supposed to be transpose. Transpose is cheap (apparently) so thats not a problem, but why exactly this is correct? I'm not sure.&#xD;&#xA;&#xD;&#xA;It works however, so maybe It will make sense later.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cN0vN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FVeYM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11867" PostHistoryTypeId="2" PostId="4941" RevisionGUID="96403132-61dc-4f59-a692-65fd990ceda1" CreationDate="2017-03-31T23:42:12.983" UserId="6371" Text="I am just trying to make a simple Skia program. A very simple program, but as I run this code, the output image file never writes anything. I am running this code on VS 2015 and included the skia.lib and OpenGL32.lib static libraries.&#xD;&#xA;&#xD;&#xA;Can someone tell me why this simple example does not work?&#xD;&#xA;&#xD;&#xA;    #include &quot;skiaIncludes.h&quot;&#xD;&#xA;&#xD;&#xA;    void draw(SkCanvas* canvas) {&#xD;&#xA;	SkPaint paint;&#xD;&#xA;	paint.setColor(SK_ColorWHITE);&#xD;&#xA;	canvas-&gt;drawPaint(paint);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main ()&#xD;&#xA;    {&#xD;&#xA;	try {&#xD;&#xA;		FILE * pFile;&#xD;&#xA;		char buffer[100];&#xD;&#xA;&#xD;&#xA;		pFile = fopen(&quot;myfile.png&quot;, &quot;wb&quot;);&#xD;&#xA;&#xD;&#xA;    sk_sp&lt;SkSurface&gt; rasterSurface(&#xD;&#xA;			SkSurface::MakeRasterN32Premul(300, 300));&#xD;&#xA;		SkCanvas* rasterCanvas = rasterSurface-&gt;getCanvas();&#xD;&#xA;&#xD;&#xA;		//rasterCanvas-&gt;save();&#xD;&#xA;		rasterCanvas-&gt;translate(SkIntToScalar(128), SkIntToScalar(128));&#xD;&#xA;		rasterCanvas-&gt;rotate(SkIntToScalar(45));&#xD;&#xA;		SkRect rect = SkRect::MakeXYWH(-90.5f, -90.5f, 181.0f, 181.0f);&#xD;&#xA;		SkPaint paint;&#xD;&#xA;		paint.setColor(SK_ColorBLUE);&#xD;&#xA;		rasterCanvas-&gt;drawRect(rect, paint);&#xD;&#xA;		//rasterCanvas-&gt;restore();&#xD;&#xA;&#xD;&#xA;		sk_sp&lt;SkImage&gt; img = rasterSurface-&gt;makeImageSnapshot();&#xD;&#xA;		sk_sp&lt;SkData&gt; png(img-&gt;encode(SkEncodedImageFormat::kPNG, 100));&#xD;&#xA;		rasterCanvas-&gt;drawImage(img, 0, 0);&#xD;&#xA;		png-&gt;MakeFromFILE(pFile);&#xD;&#xA;&#xD;&#xA;		//sk_sp&lt;SkImage&gt; bmap = SkImage::MakeFromBitmap(bitmap);&#xD;&#xA;		//SkData * encBmap = bmap-&gt;encode(SkEncodedImageFormat::kJPEG, 100);&#xD;&#xA;		//encBmap-&gt;MakeFromFILE(pFile);&#xD;&#xA;&#xD;&#xA;		fclose(pFile);&#xD;&#xA;	}&#xD;&#xA;	catch (std::exception ex){&#xD;&#xA;		printf(ex.what());&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Header file :&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #include &quot;core/SkData.h&quot;&#xD;&#xA;    #include &quot;core/SkImage.h&quot;&#xD;&#xA;    #include &quot;core/SkStream.h&quot;&#xD;&#xA;    #include &quot;core/SkSurface.h&quot;&#xD;&#xA;    #include &quot;core/SkCanvas.h&quot;&#xD;&#xA;    #include &quot;core/SkGraphics.h&quot;&#xD;&#xA;    #include &quot;core/SkImageEncoder.h&quot;&#xD;&#xA;    #include &quot;gpu/gl/GrGLInterface.h&quot;&#xD;&#xA;    #include &quot;gpu/gl/GrGLExtensions.h&quot;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    #include &lt;sys/stat.h&gt;&#xD;&#xA;    #include &lt;sys/types.h&gt;&#xD;&#xA;    #include &lt;fcntl.h&gt;&#xD;&#xA;    #include &lt;exception&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    //#include &quot;gpu/gl/GrGLUtil.h&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11868" PostHistoryTypeId="1" PostId="4941" RevisionGUID="96403132-61dc-4f59-a692-65fd990ceda1" CreationDate="2017-03-31T23:42:12.983" UserId="6371" Text="Skia example code not writing an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="11869" PostHistoryTypeId="3" PostId="4941" RevisionGUID="96403132-61dc-4f59-a692-65fd990ceda1" CreationDate="2017-03-31T23:42:12.983" UserId="6371" Text="|c++|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11870" PostHistoryTypeId="2" PostId="4942" RevisionGUID="5ab40279-b6bf-4fbb-8bea-c1de43dd101e" CreationDate="2017-04-01T00:44:50.680" UserId="6373" Text="I'm researching highlighting accessible color contrast via filter operations. I have a test screenshot of SRGB hex values compared with [WCAG's official contrast algorithm](https://www.w3.org/TR/WCAG20/relative-luminance.xml):&#xD;&#xA;&#xD;&#xA;[![Text on various bands of color, with the contrast ratios listed next to them. They descend from maximum contrast to minimum contrast.][1]][1]&#xD;&#xA;&#xD;&#xA;I converted it to its luminosity:&#xD;&#xA;&#xD;&#xA;[![The previous image, with the colors changed to grayscale using a luminosity algorithm, not brightness.][2]][2]&#xD;&#xA;&#xD;&#xA;Then an edge detect:&#xD;&#xA;&#xD;&#xA;[![The edge detection results no longer smoothly progress from maximum contrast to minimum contrast, instead having asymmetrical progression and discontinuities.][3]][3]&#xD;&#xA;&#xD;&#xA;This no longer looks like a smooth progression; there's a noticeable reversal between, say, `#f00` and `#777`. And after applying a threshold to remove insufficient contrast, it seems like one side is favored out of proportion. Inverting the &#xD;&#xA;&#xD;&#xA;I have a few leads, but not enough understanding of color theory to know which to attack:&#xD;&#xA;&#xD;&#xA;* Is it a byproduct of how browsers antialias text?&#xD;&#xA;* Am I in the wrong color space?&#xD;&#xA;* I tried inverting the input and averaging its results together with the original's results, but I'm not seeing a difference other than which way the ringing travels.&#xD;&#xA;* Similarly, switching the kernel matrix's signs doesn't change the progression.&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;These images are from The GIMP's filter operations, but ultimately I aim to create an SVG `&lt;filter&gt;` to dynamically highlight insufficient color contrast in web pages. I'm sure I'm not articulating with the right terminology, so please ask for more context if I'm unclear.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iiLxk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xBHPX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jM5nb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11871" PostHistoryTypeId="1" PostId="4942" RevisionGUID="5ab40279-b6bf-4fbb-8bea-c1de43dd101e" CreationDate="2017-04-01T00:44:50.680" UserId="6373" Text="Why does this edge detect show different results for the same color combinations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11872" PostHistoryTypeId="3" PostId="4942" RevisionGUID="5ab40279-b6bf-4fbb-8bea-c1de43dd101e" CreationDate="2017-04-01T00:44:50.680" UserId="6373" Text="|color|edge-detection|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11873" PostHistoryTypeId="50" PostId="4635" RevisionGUID="2fc97515-5cd2-4225-b8ca-adc2f5779663" CreationDate="2017-04-01T05:56:19.297" UserId="-1" />
  <row Id="11877" PostHistoryTypeId="2" PostId="4943" RevisionGUID="079d3192-7215-4c6e-9feb-38814b46489e" CreationDate="2017-04-01T20:48:27.873" UserId="6379" Text="RGB has the advantage over schemes like YP&lt;sub&gt;B&lt;/sub&gt;P&lt;sub&gt;R&lt;/sub&gt; in that it's more intuitive to understand, so why use the latter?  The only advantage I can think of right now is that it allows you to encode greyscale images more easily.  Is this the reason, or are there other reasons?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11878" PostHistoryTypeId="1" PostId="4943" RevisionGUID="079d3192-7215-4c6e-9feb-38814b46489e" CreationDate="2017-04-01T20:48:27.873" UserId="6379" Text="What are the advantages of having two chroma channels and a luma channel vs. three chroma channels?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11879" PostHistoryTypeId="3" PostId="4943" RevisionGUID="079d3192-7215-4c6e-9feb-38814b46489e" CreationDate="2017-04-01T20:48:27.873" UserId="6379" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11880" PostHistoryTypeId="2" PostId="4944" RevisionGUID="4d1a14fd-a0b2-48b8-b8b3-4fab853cb1a4" CreationDate="2017-04-01T21:22:09.983" UserId="38" Text="Human eye is less sensitive to chrominance than luminance, which means you have a nifty way to compress the data by not measuring chrominance for each pixel, while you do measure luminance of all pixels. Although the black and white thing is part of the reason.&#xD;&#xA;&#xD;&#xA;On the subject RGB might be more intuitive, but its not actually a very good intuition when you start going deeper into how the human senses actually work. As it turns out RGB is a gross simplification. RGB is not good for measuring how far away different colors are from each other visually for example." ContentLicense="CC BY-SA 3.0" />
  <row Id="11881" PostHistoryTypeId="2" PostId="4945" RevisionGUID="1af64493-7c8b-47d1-a502-ce8676614868" CreationDate="2017-04-01T21:41:58.253" UserId="6380" Text="From a historical context, the YUV color encoding was originally designed to support the existing black-and-white infrastructure. In addition, as jooja mentioned, humans are generally less perceptive to changes in chroma and more perceptive to changes in luma. Both NTSC and PAL use less bandwidth for the chroma channel than the luma channel. In a digital context, we can use [chroma subsampling][1] to achieve the same effect.&#xD;&#xA;&#xD;&#xA;YUV/YIQ/YDbDr is used for color PAL/NTSC/SECAM television broadcasts.  &#xD;&#xA;YPbPr is used for component video cables.  &#xD;&#xA;YCbCr is used for everything else.  &#xD;&#xA;YCgCo is like YCbCr but is easier to compute.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Chroma_subsampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="11882" PostHistoryTypeId="2" PostId="4946" RevisionGUID="8d6308d6-f492-45d0-a8c1-dec780575ce9" CreationDate="2017-04-01T23:09:33.567" UserId="6380" Text="I assume that you're using precomputed height map derivatives rather than calculating them on the fly (for details see [this post][1] on Mikkelsen's blog). If we need to supply pre-computed height derivatives, then we have to supply two channels, just like a normal map. One could argue that derivative mapping doesn't require the presence of a tangent map like normal mapping does, but the extra differentiation operations on the height map somewhat nullify that performance gain. Derivative maps are a cool concept, but at the end of the day I don't think they are significantly better than normal mapping performance-wise (although conceptually I agree that derivative maps are easier to work with because we don't have to deal with tangent space).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="11883" PostHistoryTypeId="5" PostId="4946" RevisionGUID="d913588e-97ae-47c7-a0b7-733e5b9acc92" CreationDate="2017-04-02T00:01:57.743" UserId="6380" Comment="map -&gt; vertex attribute" Text="I assume that you're using precomputed height map derivatives rather than calculating them on the fly (for details see [this post][1] on Mikkelsen's blog). If we need to supply pre-computed height derivatives, then we have to supply two channels, just like a normal map. One could argue that derivative mapping doesn't require the presence of a tangent vertex attribute like normal mapping does, but the extra differentiation operations on the height map somewhat nullify that performance gain. Derivative maps are a cool concept, but at the end of the day I don't think they are significantly better than normal mapping performance-wise (although conceptually I agree that derivative maps are easier to work with because we don't have to deal with tangent space).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="11884" PostHistoryTypeId="2" PostId="4947" RevisionGUID="4b8d0197-3683-424c-8f1e-40578110cdae" CreationDate="2017-04-02T01:18:05.610" UserId="6376" Text="I'm gonna start this off with an... &quot;indexed image&quot;? If that's the proper term for it?&#xD;&#xA;&#xD;&#xA;[![All 12 possible cross-sections of both possible sorted RGB-6 cubes; each color represented in 12x12 pixel tiles][1]][1]&#xD;&#xA;&#xD;&#xA;If this 384x144 image were actually only the top-left 192x48 pixels (I'll refer to that portion as &quot;0,0&quot;), I feel like the other five sections could most likely be generated by using a single automatic operation that applies the following RGB value (swaps/rotations) to all pixels in section 0,0 simultaneously:&#xD;&#xA;&#xD;&#xA; - 0,1: Red -&gt; Green -&gt; Blue -&gt; Red (#FFAA55 -&gt; #55FFAA for one example)&#xD;&#xA; - 0,2: Red -&gt; Blue -&gt; Green -&gt; Red (#FFAA55 -&gt; #AA55FF)&#xD;&#xA; - 1,0: Green &lt;-&gt; Blue (#FFAA55 -&gt; #FF55AA)&#xD;&#xA; - 1,1: Red &lt;-&gt; Green (#FFAA55 -&gt; #AAFF55)&#xD;&#xA; - 1,2: Red &lt;-&gt; Blue (#FFAA55 -&gt; #55AAFF)&#xD;&#xA;&#xD;&#xA;What is the name of the operation I'm looking for + what image editing programs can perform that operation? I tried Googling a bunch of things along the lines of &quot;rgb rotate&quot;, &quot;rgb exchange&quot;, &quot;rgb swap&quot;, &quot;rgb trade&quot;, etc. etc. etc. and I couldn't quickly + intuitively find anything that did what I wanted it to do in a single swing. The amount of stuff completely unrelated to what I had in mind that came up honestly quickly got _really_ frustrating. I even tried Googling &quot;triadic rotation&quot; and nothing related to what I had in mind showed up on the 1st page.&#xD;&#xA;&#xD;&#xA;The reason for the sorted colors instead of an actual image is basically the same reason I have to ask this question in the first place; I can't do it automatically with the free tools that I'm currently aware of the existence of.&#xD;&#xA;&#xD;&#xA;I had to sort those 64 colors manually 6 times over with paint.net; which thankfully has functions that made it slightly easier to do, though there's definitely no way that I could quickly apply the effect I'm talking about to any actual image of any kind using paint.net (unless it has some feature I'm not yet aware of). I'm pretty sure there should be a way to apply that effect automatically; I just don't know the name of that effect + therefore can't even search for it.&#xD;&#xA;&#xD;&#xA;One thing that came up a few times during my failed attempts at searching was &quot;hue rotation&quot;; however as far as I know + could observe that not only applies to only one hue range at a time, but also pays more attention to hue angle than actual RGB values (if that makes any sense). So I really don't think hue rotation is what I'm looking for; though if it's suggested to me anyway I will try it again as long as I'm given specific instructions on how to use it to achieve the effect that I desire.&#xD;&#xA;&#xD;&#xA;If I'm not using a tag that I should be using, or even outright posting on the wrong Stack Exchange site for the question; please let me know.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cao4b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11885" PostHistoryTypeId="1" PostId="4947" RevisionGUID="4b8d0197-3683-424c-8f1e-40578110cdae" CreationDate="2017-04-02T01:18:05.610" UserId="6376" Text="What is the name of the RGB thing I want to be able to do, and what free program(s) can do it automatically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11886" PostHistoryTypeId="3" PostId="4947" RevisionGUID="4b8d0197-3683-424c-8f1e-40578110cdae" CreationDate="2017-04-02T01:18:05.610" UserId="6376" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11887" PostHistoryTypeId="2" PostId="4948" RevisionGUID="e01cd0f7-ee1b-40c1-91f7-925a77553757" CreationDate="2017-04-02T01:54:13.180" UserId="1647" Text="The field you want to study is called ***Photogrammetry***.&#xD;&#xA;&#xD;&#xA;One place to begin is [the Wikipedia article on the topic][1].&#xD;&#xA;&#xD;&#xA;Actually the field is broader than what you are asking about but there is a more specific Wikipedia article on just this subfield too: **[3D reconstruction from multiple images][2]**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Photogrammetry&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/3D_reconstruction_from_multiple_images" ContentLicense="CC BY-SA 3.0" />
  <row Id="11888" PostHistoryTypeId="2" PostId="4949" RevisionGUID="ac734804-04f9-458f-ae07-292b48541b38" CreationDate="2017-04-02T02:30:28.350" UserId="3003" Text="Swapping color channels is called channel swap or swizzling. (Searching for &quot;RGB channel swap&quot; brings up lots of relevant results.) Looking at your image, the squares in the right half appear to be flipped across the diagonal.&#xD;&#xA;&#xD;&#xA;Most editing apps have a channel mixer tool that allows you to calculate each output color channel as some combination of the input color channels. In Photoshop it's called &quot;Channel Mixer&quot;. I've also seen it referred to as &quot;Color Operations&quot; or just &quot;Color Ops&quot;. &#xD;&#xA;&#xD;&#xA;The flipping can usually be done with a horizontal flip followed by a vertical flip." ContentLicense="CC BY-SA 3.0" />
  <row Id="11889" PostHistoryTypeId="5" PostId="4942" RevisionGUID="836e9a11-4237-4570-9ad5-a564ce0ed317" CreationDate="2017-04-02T02:59:53.277" UserId="6373" Comment="Removed grammar error" Text="I'm researching highlighting accessible color contrast via filter operations. I have a test screenshot of SRGB hex values compared with [WCAG's official contrast algorithm](https://www.w3.org/TR/WCAG20/relative-luminance.xml):&#xD;&#xA;&#xD;&#xA;[![Text on various bands of color, with the contrast ratios listed next to them. They descend from maximum contrast to minimum contrast.][1]][1]&#xD;&#xA;&#xD;&#xA;I converted it to its luminosity:&#xD;&#xA;&#xD;&#xA;[![The previous image, with the colors changed to grayscale using a luminosity algorithm, not brightness.][2]][2]&#xD;&#xA;&#xD;&#xA;Then an edge detect:&#xD;&#xA;&#xD;&#xA;[![The edge detection results no longer smoothly progress from maximum contrast to minimum contrast, instead having asymmetrical progression and discontinuities.][3]][3]&#xD;&#xA;&#xD;&#xA;This no longer looks like a smooth progression; there's a noticeable reversal between, say, `#f00` and `#777`. And after applying a threshold to remove insufficient contrast, it seems like one side is favored out of proportion.&#xD;&#xA;&#xD;&#xA;I have a few leads, but not enough understanding of color theory to know which to attack:&#xD;&#xA;&#xD;&#xA;* Is it a byproduct of how browsers antialias text?&#xD;&#xA;* Am I in the wrong color space?&#xD;&#xA;* I tried inverting the input and averaging its results together with the original's results, but I'm not seeing a difference other than which way the ringing travels.&#xD;&#xA;* Similarly, switching the kernel matrix's signs doesn't change the progression.&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;These images are from The GIMP's filter operations, but ultimately I aim to create an SVG `&lt;filter&gt;` to dynamically highlight insufficient color contrast in web pages. I'm sure I'm not articulating with the right terminology, so please ask for more context if I'm unclear.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iiLxk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xBHPX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jM5nb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11890" PostHistoryTypeId="2" PostId="4950" RevisionGUID="5cf3d5c7-b96b-41d6-beae-88c84fd4dfc8" CreationDate="2017-04-02T14:37:49.790" UserId="6384" Text="I am an aspiring CG programmer and would like to know what some of the more nuanced aspects of computer architecture are.&#xD;&#xA;&#xD;&#xA;I have already taken several introductory arch courses where we've covered things like cache levels, basic multi-staged piplined datapaths, and memory structures (NUMA, Von Neumann), etc. I have also spent time understanding the basics of CUDA programming and SIMT work distribution models.&#xD;&#xA;&#xD;&#xA;Is there any special aspect of architecture that you only learned outside of the classroom/in the real world that comes in handy when writing graphics applications?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11891" PostHistoryTypeId="1" PostId="4950" RevisionGUID="5cf3d5c7-b96b-41d6-beae-88c84fd4dfc8" CreationDate="2017-04-02T14:37:49.790" UserId="6384" Text="What aspects of GPU architecture are computer graphics programmers expected to be intimately familiar with?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11892" PostHistoryTypeId="3" PostId="4950" RevisionGUID="5cf3d5c7-b96b-41d6-beae-88c84fd4dfc8" CreationDate="2017-04-02T14:37:49.790" UserId="6384" Text="|gpu|gpgpu|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11894" PostHistoryTypeId="2" PostId="4951" RevisionGUID="91832d7f-ed86-4e81-ae13-6bf50434c75f" CreationDate="2017-04-03T00:24:11.490" UserId="6387" Text="In path-tracing, is a specular reflection model like Blinn-Phong useful? Is it more accurate to render a complete reflection dependent on the objects roughness?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11895" PostHistoryTypeId="1" PostId="4951" RevisionGUID="91832d7f-ed86-4e81-ae13-6bf50434c75f" CreationDate="2017-04-03T00:24:11.490" UserId="6387" Text="Pathtracing specular reflections vs. specular highlights" ContentLicense="CC BY-SA 3.0" />
  <row Id="11896" PostHistoryTypeId="3" PostId="4951" RevisionGUID="91832d7f-ed86-4e81-ae13-6bf50434c75f" CreationDate="2017-04-03T00:24:11.490" UserId="6387" Text="|pathtracing|specular|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11898" PostHistoryTypeId="6" PostId="4935" RevisionGUID="738ddba7-ff3a-4e2e-b2da-b6dd016fb7f1" CreationDate="2017-04-03T12:32:38.457" UserId="231" Comment="edited tags" Text="|opengl|c++|glsl|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11899" PostHistoryTypeId="5" PostId="4935" RevisionGUID="eef90f39-6868-41be-b41b-8d8305264485" CreationDate="2017-04-03T12:38:34.560" UserId="231" Comment="Move c++ and glsl from title to tags, plus minor typos" Text="I've been trying to figure this out for a few days now, but I just can't get it right. I've read multiple [tutorials][1] and [possible][2] explanations, I even watched a [java tutorial][3] without finding the solution. This is what I do:&#xD;&#xA;&#xD;&#xA;First I build the tangent values to pass as attributes:&#xD;&#xA;&#xD;&#xA;    //this parsing has not been updated, unlike the shaders, correct parsing in the answer below&#xD;&#xA;    float f;&#xD;&#xA;	vec3 edge1, edge2, tangentbuf;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;    //for each face, x=vert,y=uv, z=normal&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		normalize(tangentref[tangentcount++]);&#xD;&#xA;		tangentref[totalrefs[i] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 3] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 6] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x); //just normalize is enough?&#xD;&#xA;&#xD;&#xA;Normalizing or dividing seems to give the same result, and I think this is correct this far. With these shaders:&#xD;&#xA;&#xD;&#xA;vert&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec2 tex_cord;&#xD;&#xA;    layout ( location = 2 ) in vec3 vertex_normal;&#xD;&#xA;    layout ( location = 3 ) in vec3 vertex_tangent;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model; //model matrix, aka model 2 world&#xD;&#xA;&#xD;&#xA;    uniform mat4 modelviewmatrix; //view*model matrix&#xD;&#xA;    uniform mat3 normalmatrix; // transpose/invert(view*model)&#xD;&#xA;    uniform mat4 priv_mat; //projection-view-model pre multiplied&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; //after view*lightpos, ie viewspace&#xD;&#xA;&#xD;&#xA;    out vec3 lightdir;&#xD;&#xA;    out vec3 viewdir;&#xD;&#xA;    out vec2 fUV;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;	    fUV=tex_cord;&#xD;&#xA;	    position=(model*vec4(vertex_position,1.0)).xyz;&#xD;&#xA;	    len=length(vertex_position);&#xD;&#xA;&#xD;&#xA;	    // Transform normal and tangent to eye space&#xD;&#xA;        vec3 n = normalize(normalmatrix * vertex_normal);&#xD;&#xA;        vec3 t = normalize(normalmatrix * vec3(vertex_tangent));&#xD;&#xA;	    	 t = normalize(t-dot(t,n)*n);  //Gramm-Schmidt process&#xD;&#xA;	    vec3 bitangent = normalize( cross( n, t ) );&#xD;&#xA;	    mat3 tbn = transpose(mat3(t,bitangent,n)); //why transpose??&#xD;&#xA;&#xD;&#xA;	    vec3 pos=vec3(modelviewmatrix*vec4(vertex_position,1.0));&#xD;&#xA;&#xD;&#xA;	    // Transform light dir. and view dir. to tangent space&#xD;&#xA;	    lightdir = normalize( tbn *  (LightPosition.xyz - pos) );&#xD;&#xA;	    viewdir = tbn * normalize(-pos);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And frag&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;&#xD;&#xA;    in float len;&#xD;&#xA;    in vec3 lightdir; //tang light&#xD;&#xA;    in vec3 viewdir; //tang view&#xD;&#xA;    in vec2 fUV;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D png_tex;&#xD;&#xA;    uniform sampler2D bump_map;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition;&#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Specular shininess factor&#xD;&#xA;&#xD;&#xA;    out vec4 Color;&#xD;&#xA;    vec3 phongModel( vec3 norm, vec3 diffr );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 b_normal = (255.0/128.0) * texture( bump_map, fUV )-1.0; // Lookup the normal from the normal map&#xD;&#xA;        vec4 texColor = texture( png_tex, fUV ); // The color texture is used as the diffuse reflectivity&#xD;&#xA;        Color = vec4( phongModel(b_normal.xyz, texColor.rgb), 1.0 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec3 phongModel( vec3 norm, vec3 diffr )&#xD;&#xA;    {&#xD;&#xA;	    vec3 r = reflect( -lightdir, norm );&#xD;&#xA;	    vec3 ambient = LightIntensity * Ka;&#xD;&#xA;	    float sDotN = max( dot(lightdir, norm), 0.0 );&#xD;&#xA;        vec3 diffuse = Kd*LightIntensity * diffr * sDotN;&#xD;&#xA;        vec3 spec = vec3(0.0);&#xD;&#xA;        if( sDotN &gt; 0.0 )&#xD;&#xA;            spec = LightIntensity * Ks * pow( max( dot(r,viewdir), 0.0 ), Shininess );&#xD;&#xA;        return ambient + diffuse + spec;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I only got this result: *the shaders are updated as I went along, so the ones posted above work (for me anyway)*&#xD;&#xA;&#xD;&#xA;[![when rotated it turns dark][4]][4]&#xD;&#xA;&#xD;&#xA;Which has 2 obvious errors: When I rotate the object, the shading doesn't follow the lightsource and goes from dark to full bright, and, it seems to have dents at seams where the cube-sphere wraps. The normalmapping seems to work though, but again I struggle with the shading. Is there an obvious error here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial26/tutorial26.html&#xD;&#xA;  [2]: http://renderdan.blogspot.no/2006/05/rotation-matrix-from-axis-vectors.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4DUfwAEx4Ts&#xD;&#xA;  [4]: https://i.stack.imgur.com/BBvQS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11900" PostHistoryTypeId="4" PostId="4935" RevisionGUID="eef90f39-6868-41be-b41b-8d8305264485" CreationDate="2017-04-03T12:38:34.560" UserId="231" Comment="Move c++ and glsl from title to tags, plus minor typos" Text="NormalMap problems: bumps work, but shade does not" ContentLicense="CC BY-SA 3.0" />
  <row Id="11901" PostHistoryTypeId="10" PostId="4950" RevisionGUID="1c6bbe1a-2709-418b-af5e-ee1d6829bffe" CreationDate="2017-04-03T12:49:44.383" UserId="231" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:3003,&quot;DisplayName&quot;:&quot;user1118321&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="11902" PostHistoryTypeId="5" PostId="4950" RevisionGUID="84066339-4f9c-4f44-9f6b-4fd3fed1479d" CreationDate="2017-04-03T14:22:03.940" UserId="6384" Comment="Elaborated" Text="I am an aspiring CG programmer and would like to know what some of the more nuanced aspects of computer architecture are.&#xD;&#xA;&#xD;&#xA;I have already taken several introductory arch courses where we've covered things like cache levels, basic multi-staged piplined datapaths, and memory structures (NUMA, Von Neumann), etc. I have also spent time understanding the basics of CUDA programming and SIMT work distribution models.&#xD;&#xA;&#xD;&#xA;Is there any special aspect of architecture that you only learned outside of the classroom/in the real world that comes in handy when writing graphics applications?&#xD;&#xA;&#xD;&#xA;**Edit**: some people think my phrasing is too broad. When I say CG programmer, I mean someone who writes their own Vulkan/D3D application from scratch. I do not mean someone who writes games in Unity and wants to improve their performance based on platform architecture.&#xD;&#xA;&#xD;&#xA;To be **even more** specific, I should mention that I'm asking because of a presentation on architecture that I'm supposed to give that's coming up. I'm supposed to present on a topic *related* to architecture, but I'm kinda sick of going over the same old things. This is my third course on the subject and am a little sick of learning how caches work. A good example of something that I'm looking for is hyperthreading. I'd never heard about this until someone presented on it earlier in the semester." ContentLicense="CC BY-SA 3.0" />
  <row Id="11903" PostHistoryTypeId="5" PostId="4950" RevisionGUID="bff3876d-6bb8-4c6c-bfe8-3181f14b7558" CreationDate="2017-04-03T16:31:57.080" UserId="6384" Comment="added 401 characters in body" Text="I am an aspiring CG programmer and would like to know what some of the more nuanced aspects of computer architecture are.&#xD;&#xA;&#xD;&#xA;I have already taken several introductory arch courses where we've covered things like cache levels, basic multi-staged piplined datapaths, and memory structures (NUMA, Von Neumann), etc. I have also spent time understanding the basics of CUDA programming and SIMT work distribution models.&#xD;&#xA;&#xD;&#xA;Is there any special aspect of architecture that you only learned outside of the classroom/in the real world that comes in handy when writing graphics applications?&#xD;&#xA;&#xD;&#xA;**Edit**: some people think my phrasing is too broad. When I say CG programmer, I mean someone who writes their own Vulkan/D3D application from scratch. I do not mean someone who writes games in Unity and wants to improve their performance based on platform architecture.&#xD;&#xA;&#xD;&#xA;To be **even more** specific, I should mention that I'm asking because of a presentation on architecture that I'm supposed to give that's coming up. I'm supposed to present on a topic *related* to architecture, but I'm kinda sick of going over the same old things. This is my third course on the subject and am a little sick of learning how caches work. A good example of something that I'm looking for is hyperthreading. I'd never heard about this until someone presented on it earlier in the semester.&#xD;&#xA;&#xD;&#xA;**Edit 2** I think I've found my own answer. [This CMU lecture series][1] has a bunch of slides talking about modern parallel architecture and algorithms. [These][2] slides on heterogeneous systems is particularly interesting to me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://15418.courses.cs.cmu.edu/spring2017/&#xD;&#xA;  [2]: http://15418.courses.cs.cmu.edu/spring2013content/lectures/22_heterogeneity/heterogeneity_slides.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="11904" PostHistoryTypeId="50" PostId="4008" RevisionGUID="6de24f4a-6de0-427c-908c-6e91a19cf6c2" CreationDate="2017-04-03T17:47:13.013" UserId="-1" />
  <row Id="11905" PostHistoryTypeId="2" PostId="4952" RevisionGUID="f5f10b41-8b35-4e3b-89dc-3d53c0f922cf" CreationDate="2017-04-03T23:11:37.860" UserDisplayName="user3412" Text="I am working on a planet visualizer, which at this point is little more than the NASA blue marble image applied as a diffuse texture.  For the atmospheric rim, I am simply blending in a constant color depending on Fresnel.  It looks like this:&#xD;&#xA;&#xD;&#xA;[![earth from space][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qClko.png&#xD;&#xA;&#xD;&#xA;Besides the obvious problems (no clouds) I am struggling to understand what techniques are applicable at this scale.  As I understand it, normal mapping is simply a modeling of surface features below the threshold of polygon resolution.  Likewise, roughness-based BRDFs are simply a modeling of surface features below the threshold of normal maps.  In my case, I am using the 8k texture map at 500m resolution.  Does it make sense to normal map the Earth from this distance?  How would I even do that?  Is there a height map for the planet?&#xD;&#xA;&#xD;&#xA;Are there other techniques that are more applicable to rendering (real) planets like this?  My next step is to make a specular mask based on water cover, but I feel like I am missing something else.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Nick&#xD;&#xA;&#xD;&#xA;P.S.  I noticed that the NASA blue marble image didn't render well when I enabled gamma correction, nor when I divided its texel values by PI before computing the light value.  I'm not sure why that is." ContentLicense="CC BY-SA 3.0" />
  <row Id="11906" PostHistoryTypeId="1" PostId="4952" RevisionGUID="f5f10b41-8b35-4e3b-89dc-3d53c0f922cf" CreationDate="2017-04-03T23:11:37.860" UserDisplayName="user3412" Text="Does normal mapping make sense for a view of earth from space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11907" PostHistoryTypeId="3" PostId="4952" RevisionGUID="f5f10b41-8b35-4e3b-89dc-3d53c0f922cf" CreationDate="2017-04-03T23:11:37.860" UserDisplayName="user3412" Text="|texture|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11909" PostHistoryTypeId="2" PostId="4953" RevisionGUID="5e9b9acb-948f-4445-be7d-23d6210fe141" CreationDate="2017-04-04T02:43:50.083" UserId="1988" Text="* When you say $acos(\|v\|\|p\|)$ are you saying $acos(\|\hat{v} \cdot \hat{p}\|)$? If not the second, your angle will be some bizarre thing (In fact, you'll always get 90deg).&#xD;&#xA;&#xD;&#xA;* How are you applying the rotation? `glRotate`? Have you tried glRotate with the negative of your estimated angle?&#xD;&#xA;&#xD;&#xA;* Are you doing rotation/scaling/translation in the right order? Could you post the actual code that is executing if it is short? (If not, then a small runnable excerpt?)&#xD;&#xA;&#xD;&#xA;Also: I'd be quite careful, as the cross-product-as-axis approach will produce goofy results when $v \parallel u$.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11910" PostHistoryTypeId="2" PostId="4954" RevisionGUID="3b597207-0c96-4548-8d92-76fe6d87778b" CreationDate="2017-04-04T02:51:53.187" UserId="1988" Text="This is a bit different from a conventional photogrammetry problem. You're not trying to estimate a 3D world from 2D projections. You have actual 3D information - you have the imaging slices - and you want to assemble them into a 3D model. That's a much easier problem, the kind you can solve from the comfort of your couch.&#xD;&#xA;&#xD;&#xA;Do know the cutting planes that each image belongs to? If so, you can easily assemble them. Just plop down the images at each plane. If not, it will be hard to determine how the images stack. (Is image N on top of or below image K?)&#xD;&#xA;&#xD;&#xA;If the images are not all taken from parallel cutting planes, then your problem is a bit easier. You can compute point correspondences between the slices and solve the alignment as an iterative registration problem. (i.e. every point in every image that &quot;corresponds&quot; should be at the same point in 3D space)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, making this into a 3D point cloud is easy - I would drop points based on the density at each point in each image, so that empty spaces are empty and dense objects have many points.&#xD;&#xA;&#xD;&#xA;Building a mesh is way more difficult. If that's what you intend to do, and you're okay with hokey results, you might consider a triangulation approach to mesh building.&#xD;&#xA;&#xD;&#xA;If you want good results, I would forego trying to fit a mesh to the cloud, and instead try to find density level sets in each 2D image, and see if you can build volumetric objects by following those level sets as isosurfaces in the 3D assembled scan." ContentLicense="CC BY-SA 3.0" />
  <row Id="11912" PostHistoryTypeId="50" PostId="1755" RevisionGUID="c03c392d-427b-4c6b-bf43-52aa2d386899" CreationDate="2017-04-04T08:07:58.803" UserId="-1" />
  <row Id="11913" PostHistoryTypeId="50" PostId="4651" RevisionGUID="36be9bea-c801-4d90-964f-7643468298b2" CreationDate="2017-04-04T09:08:00.037" UserId="-1" />
  <row Id="11914" PostHistoryTypeId="2" PostId="4955" RevisionGUID="3275d569-3616-49e9-848d-739c3149e34f" CreationDate="2017-04-04T12:00:32.950" UserId="3305" Text="I am trying to measure width of an object in image. The object size is 2D object 15cm X 15cm.&#xD;&#xA;&#xD;&#xA;When I capture a frame with resolution 1280 X 720 (16:9) I am getting that the object width is 50px.&#xD;&#xA;&#xD;&#xA;But when I capture a frame resolution 640 X 480 (4:3) I am getting that the object width is 30px.&#xD;&#xA;&#xD;&#xA;The distance between the object and the camera did not changed during the test.&#xD;&#xA;I didn't find a transformation that can convert the width in pixels from 1280 X 720 to 640 X 480. I think that the aspect ratio is the issue here but I didn't succeed to solve it out.&#xD;&#xA;&#xD;&#xA;How can I know that the width in pixels is both resolutions is actually the same object size?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11915" PostHistoryTypeId="1" PostId="4955" RevisionGUID="3275d569-3616-49e9-848d-739c3149e34f" CreationDate="2017-04-04T12:00:32.950" UserId="3305" Text="Transformation between aspect ratio" ContentLicense="CC BY-SA 3.0" />
  <row Id="11916" PostHistoryTypeId="3" PostId="4955" RevisionGUID="3275d569-3616-49e9-848d-739c3149e34f" CreationDate="2017-04-04T12:00:32.950" UserId="3305" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11917" PostHistoryTypeId="2" PostId="4956" RevisionGUID="26c8dec0-0bf4-4c9d-a2e0-73f50995fee8" CreationDate="2017-04-04T12:42:12.333" UserId="2041" Text="This never writes anything to the output file because you haven't included any code to write to the output file. The only time you touch the file after opening it is in the line&#xD;&#xA;&#xD;&#xA;    png-&gt;MakeFromFILE(pFile);&#xD;&#xA;&#xD;&#xA;which **reads** from the file **into** the `SkData` instance. It won't even do that in this case, because the file handle has to be open for reading only.&#xD;&#xA;&#xD;&#xA;I'm no expert on Skia, but you probably want to use [`SkFILEWStream`](https://skia-doc.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkFILEWStream.html) to write the file. Or just call `png.bytes()` and write the bytes to the file using the standard library." ContentLicense="CC BY-SA 3.0" />
  <row Id="11918" PostHistoryTypeId="2" PostId="4957" RevisionGUID="b7077a4a-c030-4213-8b74-1af74f8eb981" CreationDate="2017-04-04T16:30:24.900" UserId="48" Text="It looks to me like the vertical dimension is the one to use for scaling:&#xD;&#xA;&#xD;&#xA;$$\frac{50\text{ px}}{720\text{ px}} \approx \frac{30\text{ px}}{480\text{ px}}$$&#xD;&#xA;&#xD;&#xA;There's a slight error there, but it's only a few pixels. I'm not sure if the object sizes you mentioned were intended to be precise to the nearest pixel (30 and 50 are roundish numbers).&#xD;&#xA;&#xD;&#xA;Typically when switching between aspect ratios, the vertical FOV would remain constant while the horizontal FOV widens or narrows to match the aspect ratio." ContentLicense="CC BY-SA 3.0" />
  <row Id="11921" PostHistoryTypeId="5" PostId="4952" RevisionGUID="aac62f13-76b0-4499-be49-60e17424e662" CreationDate="2017-04-04T20:57:33.890" UserId="231" Comment="Remove signature as username is displayed below every post" Text="I am working on a planet visualizer, which at this point is little more than the NASA blue marble image applied as a diffuse texture.  For the atmospheric rim, I am simply blending in a constant color depending on Fresnel.  It looks like this:&#xD;&#xA;&#xD;&#xA;[![earth from space][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qClko.png&#xD;&#xA;&#xD;&#xA;Besides the obvious problems (no clouds) I am struggling to understand what techniques are applicable at this scale.  As I understand it, normal mapping is simply a modeling of surface features below the threshold of polygon resolution.  Likewise, roughness-based BRDFs are simply a modeling of surface features below the threshold of normal maps.  In my case, I am using the 8k texture map at 500m resolution.  Does it make sense to normal map the Earth from this distance?  How would I even do that?  Is there a height map for the planet?&#xD;&#xA;&#xD;&#xA;Are there other techniques that are more applicable to rendering (real) planets like this?  My next step is to make a specular mask based on water cover, but I feel like I am missing something else.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;P.S.  I noticed that the NASA blue marble image didn't render well when I enabled gamma correction, nor when I divided its texel values by $\pi$ before computing the light value.  I'm not sure why that is." ContentLicense="CC BY-SA 3.0" />
  <row Id="11922" PostHistoryTypeId="2" PostId="4958" RevisionGUID="b62a1307-5622-43d8-bb94-8a69ca4d8f26" CreationDate="2017-04-05T02:34:16.480" UserId="3003" Text="In my opinion, yes, it does. I've heard it claimed that in reality, the ratio of the tallest mountain on Earth to the Earth's diameter is smaller than the variations in height of an apple's skin to its diameter. So I can't say that it would be realistic, but it certainly looks better than not doing it. At the least it gives you some shading between high and low spots, even with a simple directional light." ContentLicense="CC BY-SA 3.0" />
  <row Id="11924" PostHistoryTypeId="2" PostId="4959" RevisionGUID="3c728c7e-7c5e-423e-b5cc-7f3daeb1b7ec" CreationDate="2017-04-05T06:50:29.980" UserId="1614" Text="Problem X: I need to provide &quot;compensation&quot; streams for attributes that are not plugged by the mesh data, but the shader requires them.&#xD;&#xA;(In d3d not matching the input layout is a hard error)&#xD;&#xA;&#xD;&#xA;Solution Y: In D3D I've created a 16 bytes buffer initialized with some default color (when the missing semantic is color, let's take this as my typical use case) and specified a stride of zero so that one element is repeated whatever the index in the index buffer, and this way I don't need to clog VRAM with the biggest buffer that's necessary to cover all objects. This works in D3D.&#xD;&#xA;&#xD;&#xA;But looking at https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glVertexAttribPointer.xml I see that the API is eating away my stride and makes it automatic when I specify zero.&#xD;&#xA;&#xD;&#xA;Any workaround ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11925" PostHistoryTypeId="1" PostId="4959" RevisionGUID="3c728c7e-7c5e-423e-b5cc-7f3daeb1b7ec" CreationDate="2017-04-05T06:50:29.980" UserId="1614" Text="OpenGL set a vertex element stride of zero" ContentLicense="CC BY-SA 3.0" />
  <row Id="11926" PostHistoryTypeId="3" PostId="4959" RevisionGUID="3c728c7e-7c5e-423e-b5cc-7f3daeb1b7ec" CreationDate="2017-04-05T06:50:29.980" UserId="1614" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11927" PostHistoryTypeId="2" PostId="4960" RevisionGUID="e93cb08c-f355-4dd0-adf5-75918fcf2294" CreationDate="2017-04-05T07:59:44.857" UserId="137" Text="Disable the vertex attrib array and use `glVertexAttrib` to set the data that should be used." ContentLicense="CC BY-SA 3.0" />
  <row Id="11928" PostHistoryTypeId="2" PostId="4961" RevisionGUID="b4a7e4fb-b5dd-480c-82b9-3dc82b589e75" CreationDate="2017-04-05T13:54:10.807" UserId="2654" Text="You can set a stride of zero with OpenGL 4.3's [separate attribute format][1] API, or the ARB_vertex_attrib_binding extension:&#xD;&#xA;&#xD;&#xA;    glBindVertexBuffer(index, buffer, offset, 0);&#xD;&#xA;&#xD;&#xA;The stride of zero will be a real stride of zero.&#xD;&#xA;&#xD;&#xA;This also has the benefit of looking a lot more familiar to D3D users than the `glVertexAttribPointer` API.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Separate_attribute_format" ContentLicense="CC BY-SA 3.0" />
  <row Id="11929" PostHistoryTypeId="2" PostId="4962" RevisionGUID="9b62934b-61ed-470b-ae0c-da73622eea27" CreationDate="2017-04-05T18:15:09.107" UserId="5215" Text="For the fun of it, I've taken up a task of writing a level editor for a voxel game.&#xD;&#xA;&#xD;&#xA;The idea is to have window that contains two main components. First component is openGL viewport placed in lower left or right corner of the window (or anywhere, really). The rest would be occupied with the second component, you guessed it, the GUI. It would consist of the menu bar, status bar and various options to select tools to use. It could also contain dialog boxes to manage metadata contained in the map. The GUI stuff. It would have this general look:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The question here is whether those two would get along. I've been googling for a while and have failed to find any specific info on openGL to GUI interaction and vice versa.&#xD;&#xA;&#xD;&#xA;Am I free to just use any GUI library with openGL, limiting the latter to a part of the window, or are there some things I'd have to look out after. I know it's a bit of a general question, but I really didn't manage to find any specific information on this. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Z4w4f.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="11930" PostHistoryTypeId="1" PostId="4962" RevisionGUID="9b62934b-61ed-470b-ae0c-da73622eea27" CreationDate="2017-04-05T18:15:09.107" UserId="5215" Text="Clashes when combining openGL and GUI" ContentLicense="CC BY-SA 3.0" />
  <row Id="11931" PostHistoryTypeId="3" PostId="4962" RevisionGUID="9b62934b-61ed-470b-ae0c-da73622eea27" CreationDate="2017-04-05T18:15:09.107" UserId="5215" Text="|opengl|ui|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11937" PostHistoryTypeId="2" PostId="4964" RevisionGUID="345f71d2-0dbc-48c9-a48d-4de235b657cc" CreationDate="2017-04-06T10:01:24.110" UserId="6404" Text="gl.drawArrays()/gl.drawElements() initiates a drawing and returns immediately.&#xD;&#xA;There is also (non-recommended) gl.finish() that blocks execution until rendering is complete.&#xD;&#xA;&#xD;&#xA;Is there a way to receive event when rendering is complete, or other ways to track status of rendering, without blocking execution of the main thread? If there are, how well they work with Offscreen rendering (to a buffer)?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11938" PostHistoryTypeId="1" PostId="4964" RevisionGUID="345f71d2-0dbc-48c9-a48d-4de235b657cc" CreationDate="2017-04-06T10:01:24.110" UserId="6404" Text="How to know when rendering is complete in WebGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11939" PostHistoryTypeId="3" PostId="4964" RevisionGUID="345f71d2-0dbc-48c9-a48d-4de235b657cc" CreationDate="2017-04-06T10:01:24.110" UserId="6404" Text="|rendering|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11940" PostHistoryTypeId="2" PostId="4965" RevisionGUID="1e64082f-35aa-4f16-bdf0-f43d2c74c7db" CreationDate="2017-04-06T10:01:55.410" UserId="4958" Text="General answer is that creating a window as a GUI element with some GUI designer library involves subclassing some basic GUI element (like widget in QtCreator for example) with class providing handling GL context in more or less user friendly way (like `QOpenGLWidget` in QtCreator which provide some user friendly wrapper or on the other hand basic Win32 API handle) and override methods for handling its framebuffer drawing or resizing, swapping buffers etc. with usual gl extensions privided by some lib you use.&#xD;&#xA;&#xD;&#xA;This will work perfectly fine with other GUI elements.&#xD;&#xA;&#xD;&#xA;I don't know which GUI lib or IDE with GUI designer or language you prefer but most good libs can handle this. You can even do it in Assembler with WinApi GUI elements.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11941" PostHistoryTypeId="5" PostId="4965" RevisionGUID="68459f14-5655-47e6-bb3c-524ad5399afe" CreationDate="2017-04-06T10:13:27.050" UserId="4958" Comment="edited body" Text="General answer is that creating a window as a GUI element with some GUI designer library involves subclassing some basic GUI element (like widget in QtCreator for example) with class providing handling GL context in more or less user friendly way (like `QOpenGLWidget` in QtCreator which provide some user friendly wrapper or on the other hand basic Win32 API handle) and override methods for handling its framebuffer drawing or resizing, swapping buffers etc. with usual gl extensions provided by some lib you use.&#xD;&#xA;&#xD;&#xA;This will work perfectly fine with other GUI elements.&#xD;&#xA;&#xD;&#xA;I don't know which GUI lib or IDE with GUI designer or language you prefer but most good libs can handle this. You can even do it in Assembler with WinApi GUI elements.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11942" PostHistoryTypeId="50" PostId="4663" RevisionGUID="f195b868-5b3b-4822-a9af-951965937287" CreationDate="2017-04-06T11:14:10.723" UserId="-1" />
  <row Id="11943" PostHistoryTypeId="5" PostId="4964" RevisionGUID="affa39e5-1ca6-4113-a8c3-5af5c1a7b277" CreationDate="2017-04-06T12:41:15.740" UserId="6404" Comment="added 16 characters in body" Text="gl.drawArrays()/gl.drawElements() initiates a drawing and returns immediately.&#xD;&#xA;There is also (non-recommended) gl.finish() that (theoretically) blocks execution until rendering is complete.&#xD;&#xA;&#xD;&#xA;Is there a way to receive event when rendering is complete, or other ways to track status of rendering, without blocking execution of the main thread? If there are, how well they work with Offscreen rendering (to a buffer)?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11947" PostHistoryTypeId="2" PostId="4967" RevisionGUID="14692a46-dfd1-49eb-ae6c-3d7e530ac432" CreationDate="2017-04-06T17:19:42.487" UserId="2372" Text="After some researches and some answers from professionals here is my conclusion.&#xD;&#xA;&#xD;&#xA;**Pros**&#xD;&#xA;&#xD;&#xA; - Don’t require tangents or binormals. Less interpolators.&#xD;&#xA; - Only need two channels. less texture memory.&#xD;&#xA; - Don’t suffer from tangent seams.&#xD;&#xA; - Can be blended using alpha blending, without renormalization.&#xD;&#xA; - Less mesh memory: We don’t need to store a tangent vector.&#xD;&#xA; - Fast implementation.&#xD;&#xA;&#xD;&#xA;**Cons**&#xD;&#xA;&#xD;&#xA; - More ALU&#xD;&#xA; - Less flexible. A normal map can represent any derivative map, but the reverse is not true. As an example, sharp edges can be difficult to represent.&#xD;&#xA;&#xD;&#xA;So, that's a lot of pros compared to cons. But the major problem is that it's not an industry standard.&lt;br&gt;&#xD;&#xA;There are almost no content authoring tools nor artist know-how.&#xD;&#xA;&#xD;&#xA;Here's is a quote from [Bart Wronski][1] that illustrates well the current status of derivative maps :&#xD;&#xA;&#xD;&#xA;&gt; Sadly in life / technology not always best solution wins / not even&#xD;&#xA;&gt; gets deserved attention... It's more about standards and inertia.&#xD;&#xA;&#xD;&#xA;If you are interested in knowing more about derivative maps here are some interesting articles.&#xD;&#xA;&#xD;&#xA; - http://mmikkelsen3d.blogspot.fr/2011/07/derivative-maps.html&#xD;&#xA; - http://www.rorydriscoll.com/2012/01/11/derivative-maps/&#xD;&#xA; - http://www.rorydriscoll.com/2012/01/15/derivative-maps-vs-normal-maps/&#xD;&#xA; - http://therobotseven.com/devlog/triplanar-texturing-derivative-maps/&#xD;&#xA; - http://polycount.com/discussion/91605/derivative-normal-maps-what-are-they&#xD;&#xA; - https://docs.knaldtech.com/doku.php?id=derivative_maps_knald&#xD;&#xA;&#xD;&#xA;If I forgot something or if your don't agree feel free to tell in the comments, I would be glad to improve this answer.&#xD;&#xA;&#xD;&#xA;  [1]: https://twitter.com/BartWronsk" ContentLicense="CC BY-SA 3.0" />
  <row Id="11948" PostHistoryTypeId="2" PostId="4968" RevisionGUID="dfa4b1f8-339f-4b79-830a-d1bedf8b991e" CreationDate="2017-04-06T18:09:07.647" UserId="4776" Text="You can utilize [ARB_sync][ARB_sync] or in other words [sync objects][Sync_Object] which have been core since 3.2.&#xD;&#xA;&#xD;&#xA;From the point-of-view of OpenGL then right after issuing a specific command (you want to know whether has finished), you'd insert a fence.&#xD;&#xA;&#xD;&#xA;*Say you want to check if a `glDrawArrays()` call is done.*&#xD;&#xA;&#xD;&#xA;    glDrawArrays(...);&#xD;&#xA;    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);&#xD;&#xA;&#xD;&#xA;You can now check whether it has finished by doing:&#xD;&#xA;&#xD;&#xA;    GLint signaled = 0;&#xD;&#xA;    glGetSynciv(sync, GL_SYNC_STATUS, 1, NULL, &amp;signaled);&#xD;&#xA;&#xD;&#xA;    if (signaled == GL_SIGNALED)&#xD;&#xA;        // Done&#xD;&#xA;    else&#xD;&#xA;        // Not done&#xD;&#xA;&#xD;&#xA;You can then of course repeatably call `glGetSynciv()` and check when you receive `GL_SIGNALED`.&#xD;&#xA;&#xD;&#xA;If you want to completely block you can also do:&#xD;&#xA;&#xD;&#xA;    GLenum status = glClientWaitSync(sync, 0, 0);&#xD;&#xA;&#xD;&#xA;    if (status == GL_CONDITION_SATISFIED)&#xD;&#xA;        // Done&#xD;&#xA;&#xD;&#xA;It blocks and waits for up to `timeout` nanoseconds (the last parameter).&#xD;&#xA;&#xD;&#xA;Remember to delete the [sync object][Sync_Object] again:&#xD;&#xA;&#xD;&#xA;    glDeleteSync(sync);&#xD;&#xA;&#xD;&#xA;When it comes to WebGL. Then note that sync objects are not supported in WebGL 1.0. They are however in WebGL 2.0 in the form of [WebGLSync][WebGLSync].&#xD;&#xA;&#xD;&#xA;*The equivalent to the above code in WebGL 2.0 would be the following:*&#xD;&#xA;&#xD;&#xA;    var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);&#xD;&#xA;&#xD;&#xA;    if (gl.isSync(sync))&#xD;&#xA;        // Done&#xD;&#xA;    else&#xD;&#xA;        // Not done&#xD;&#xA;&#xD;&#xA;    var status = gl.clientWaitSync(sync, 0, 0);&#xD;&#xA;&#xD;&#xA;    if (status == gl.CONDITION_SATISFIED)&#xD;&#xA;        // Done&#xD;&#xA;&#xD;&#xA;    gl.deleteSync(sync);&#xD;&#xA;&#xD;&#xA;   [ARB_sync]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sync.txt&#xD;&#xA;   [Sync_Object]: https://www.khronos.org/opengl/wiki/Sync_Object&#xD;&#xA;   [WebGLSync]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLSync&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11949" PostHistoryTypeId="5" PostId="4968" RevisionGUID="b6aa7417-f46c-4ed3-a02a-e2a53c96224d" CreationDate="2017-04-06T18:18:19.080" UserId="4776" Comment="added 60 characters in body" Text="You can utilize [ARB_sync][ARB_sync] or in other words [sync objects][Sync_Object] which have been core since 3.2.&#xD;&#xA;&#xD;&#xA;From the point-of-view of OpenGL then right after issuing a specific command (you want to know whether has finished), you'd insert a fence.&#xD;&#xA;&#xD;&#xA;*Say you want to check if a `glDrawArrays()` call is done.*&#xD;&#xA;&#xD;&#xA;    glDrawArrays(...);&#xD;&#xA;    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);&#xD;&#xA;&#xD;&#xA;*Note that if `glFenceSync()` fails it will return `0`.*&#xD;&#xA;&#xD;&#xA;You can now check whether it has finished by doing:&#xD;&#xA;&#xD;&#xA;    GLint signaled = 0;&#xD;&#xA;    glGetSynciv(sync, GL_SYNC_STATUS, 1, NULL, &amp;signaled);&#xD;&#xA;&#xD;&#xA;    if (signaled == GL_SIGNALED)&#xD;&#xA;        // Done&#xD;&#xA;    else&#xD;&#xA;        // Not done&#xD;&#xA;&#xD;&#xA;You can then of course repeatably call `glGetSynciv()` and check when you receive `GL_SIGNALED`.&#xD;&#xA;&#xD;&#xA;If you want to completely block you can also do:&#xD;&#xA;&#xD;&#xA;    GLenum status = glClientWaitSync(sync, 0, 0);&#xD;&#xA;&#xD;&#xA;    if (status == GL_CONDITION_SATISFIED)&#xD;&#xA;        // Done&#xD;&#xA;&#xD;&#xA;It blocks and waits for up to `timeout` nanoseconds (the last parameter).&#xD;&#xA;&#xD;&#xA;Remember to delete the [sync object][Sync_Object] again:&#xD;&#xA;&#xD;&#xA;    glDeleteSync(sync);&#xD;&#xA;&#xD;&#xA;When it comes to WebGL. Then note that sync objects are not supported in WebGL 1.0. They are however in WebGL 2.0 in the form of [WebGLSync][WebGLSync].&#xD;&#xA;&#xD;&#xA;*The equivalent to the above code in WebGL 2.0 would be the following:*&#xD;&#xA;&#xD;&#xA;    var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);&#xD;&#xA;&#xD;&#xA;    var signaled = gl.getSyncParameter(sync, gl.SYNC_STATUS);&#xD;&#xA;&#xD;&#xA;    if (signaled == gl.SIGNALED)&#xD;&#xA;        // Done&#xD;&#xA;    else&#xD;&#xA;        // Not done&#xD;&#xA;&#xD;&#xA;    var status = gl.clientWaitSync(sync, 0, 0);&#xD;&#xA;&#xD;&#xA;    if (status == gl.CONDITION_SATISFIED)&#xD;&#xA;        // Done&#xD;&#xA;&#xD;&#xA;    gl.deleteSync(sync);&#xD;&#xA;&#xD;&#xA;   [ARB_sync]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sync.txt&#xD;&#xA;   [Sync_Object]: https://www.khronos.org/opengl/wiki/Sync_Object&#xD;&#xA;   [WebGLSync]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLSync&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11950" PostHistoryTypeId="2" PostId="4969" RevisionGUID="ee32519a-4d08-446e-bd77-b56b4c2c6844" CreationDate="2017-04-06T21:59:09.380" UserId="6406" Text="I'm in the process of working out how to pack all the information I need for a Physically Based Deferred Renderer into a G-Buffer without using an obscene amount of render targets. &#xD;&#xA;&#xD;&#xA;What I have so far is 4 3-part vectors: &#xD;&#xA;&#xD;&#xA; - Albedo/Diffuse&#xD;&#xA; - Normal&#xD;&#xA; - Tangent&#xD;&#xA; - Position&#xD;&#xA;&#xD;&#xA;And 4 single components&#xD;&#xA;&#xD;&#xA; - Metallic&#xD;&#xA; - Roughness&#xD;&#xA; - Height&#xD;&#xA; - Ambient Occlusion&#xD;&#xA;&#xD;&#xA;A naive approach is to bundle one of the single components into the alpha (fourth) channel with one of the 3-part vectors, which is my current line of investigation. However, given that four 4-channel full precision floating point render targets isn't small I understand it's common to use half precision and even smaller representations to be more memory conscious. &#xD;&#xA;&#xD;&#xA;What I'm asking is: which components can I safely cut precision down on without losing quality, and by how much?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11951" PostHistoryTypeId="1" PostId="4969" RevisionGUID="ee32519a-4d08-446e-bd77-b56b4c2c6844" CreationDate="2017-04-06T21:59:09.380" UserId="6406" Text="How much precision do I need in my G-Buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11952" PostHistoryTypeId="3" PostId="4969" RevisionGUID="ee32519a-4d08-446e-bd77-b56b4c2c6844" CreationDate="2017-04-06T21:59:09.380" UserId="6406" Text="|optimisation|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11953" PostHistoryTypeId="2" PostId="4970" RevisionGUID="1500b487-b08a-4192-a6d3-5e8186295a9c" CreationDate="2017-04-06T22:57:54.143" UserId="6282" Text="Link to paper : http://www2.lawrence.edu/fast/GREGGJ/CMSC420/chapter21/Irradiance.html&#xD;&#xA;&#xD;&#xA;&gt; Using a shader to compute En&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&gt; &#xD;&#xA;&gt; Computing En as described above is a very compute intensive operation,&#xD;&#xA;&gt; because we have to compute the integral over the cube map for each new&#xD;&#xA;&gt; direction vector n that we want to work with. At the same time, the&#xD;&#xA;&gt; details for different values of n are highly repetitive. This suggests&#xD;&#xA;&gt; that we should enlist the aid of shaders to compute this mapping for&#xD;&#xA;&gt; us. Here is the outline of a strategy that makes it possible to do&#xD;&#xA;&gt; this.&#xD;&#xA;&gt; &#xD;&#xA;&gt; 1. Use OpenGL to render a two dimensional square centered at the origin&#xD;&#xA;&gt; with sides of length 2. This square represents one of the sides of our&#xD;&#xA;&gt; cubical irradiance map. Given the mapping above we can map any point&#xD;&#xA;&gt; (x , y) on the square to a direction vector n. &#xD;&#xA;2. We render the square to&#xD;&#xA;&gt; a framebuffer with dimensions size by size pixels, where size is the&#xD;&#xA;&gt; desired size of our irradiance cube map texture. &#xD;&#xA;3. In the fragment&#xD;&#xA;&gt; shader, we translate the interpolated fragment positions we are given&#xD;&#xA;&gt; into direction vectors n and construct loops that sum over the six&#xD;&#xA;&gt; faces of the environment map:&#xD;&#xA;&gt; &#xD;&#xA;&gt; &#xD;&#xA;&gt; When rendering is done, we convert the image in the frame buffer to a&#xD;&#xA;&gt; texture for use by our irradiance cube map.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I understand that Li is color at i. ωi is the direction of incoming light.&#xD;&#xA;&#xD;&#xA;However I do not understand what dωi is.&#xD;&#xA;&#xD;&#xA;Paper describes it as...&#xD;&#xA;&#xD;&#xA;&gt; Computing the solid angle dωi subtended by a particular texel is a&#xD;&#xA;&gt; little more involved. Texels near the center of the texture subtend a&#xD;&#xA;&gt; somewhat larger angle, while texels near the corner take up a smaller&#xD;&#xA;&gt; solid angle when we map the cube texture onto a sphere. Here is a&#xD;&#xA;&gt; reference that explains how to compute the solid angle correctly from&#xD;&#xA;&gt; the positions xi and yi.&#xD;&#xA;&#xD;&#xA;However I am not following words to understand what it means.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FeT3I.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="11954" PostHistoryTypeId="1" PostId="4970" RevisionGUID="1500b487-b08a-4192-a6d3-5e8186295a9c" CreationDate="2017-04-06T22:57:54.143" UserId="6282" Text="Irradiance Map Equation What is &quot;dω&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11955" PostHistoryTypeId="3" PostId="4970" RevisionGUID="1500b487-b08a-4192-a6d3-5e8186295a9c" CreationDate="2017-04-06T22:57:54.143" UserId="6282" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11956" PostHistoryTypeId="2" PostId="4971" RevisionGUID="380f41b1-3341-4a02-b3f6-6b0d971e12d9" CreationDate="2017-04-06T23:22:46.880" UserId="48" Text="First of all, you don't need position in the G-buffer at all. The position of a pixel can be [reconstructed from the depth buffer](https://mynameismjp.wordpress.com/2010/09/05/position-from-depth-3/), knowing the camera setup and the pixel's screen-space xy position. So you can get rid of that whole buffer.&#xD;&#xA;&#xD;&#xA;Also, you don't ordinarily need tangent vectors in the G-buffer either. They're only needed for converting normal maps from tangent space, and for parallax mapping; these would be done during the G-buffer fill pass (when you have tangents from the mesh you're rendering), and the G-buffer would only store normals in world or view space.&#xD;&#xA;&#xD;&#xA;Material properties like colors, roughness, and metallic are usually just 8-bit values in the G-buffer, since they're sourced from 8-bit textures. Same for AO.&#xD;&#xA;&#xD;&#xA;Height is also not needed in the G-buffer unless you're going to be doing some kind of multi-pass blending that depends on it, but if you do need it, 8 bits is probably enough for that too.&#xD;&#xA;&#xD;&#xA;Normals can be benefit from being stored as 16-bit values rather than 8-bit. Half-float is okay, but 16-bit fixed-point is even better, as it gives you more uniform precision across all orientations (half-float is more precise near the axes and loses some precision away from them). Moreover, you can cut them from 3 components down to 2 using [octahedral mapping](http://jcgt.org/published/0003/02/01/).&#xD;&#xA;&#xD;&#xA;So, at the end of the day, a minimal G-buffer might look like:&#xD;&#xA;&#xD;&#xA;* Material color + metallic: RGBA8&#xD;&#xA;* Octahedral world-space normal + roughness + AO: RGBA16&#xD;&#xA;&#xD;&#xA;and that's all! Only 12 bytes per pixel.&#xD;&#xA;&#xD;&#xA;Alternatively, you could use an RG16 buffer for the normals, and move roughness + AO into a separate 8-bit buffer. That would give you some room to grow should you eventually need more G-buffer components of either 8-bit or 16-bit sizes." ContentLicense="CC BY-SA 3.0" />
  <row Id="11957" PostHistoryTypeId="5" PostId="4968" RevisionGUID="94283967-0a9a-4b14-a562-35b0feb7439a" CreationDate="2017-04-06T23:45:22.017" UserId="4776" Comment="added 10 characters in body" Text="You can utilize [ARB_sync][ARB_sync] or in other words [sync objects][Sync_Object] which have been core since 3.2.&#xD;&#xA;&#xD;&#xA;From the point-of-view of OpenGL then right after issuing a specific command (you want to know whether has finished), you'd insert a fence.&#xD;&#xA;&#xD;&#xA;*Say you want to check if a `glDrawArrays()` call has been executed.*&#xD;&#xA;&#xD;&#xA;    glDrawArrays(...);&#xD;&#xA;    GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);&#xD;&#xA;&#xD;&#xA;*Note that if `glFenceSync()` fails it will return `0`.*&#xD;&#xA;&#xD;&#xA;You can now check whether it has finished by doing:&#xD;&#xA;&#xD;&#xA;    GLint signaled = 0;&#xD;&#xA;    glGetSynciv(sync, GL_SYNC_STATUS, 1, NULL, &amp;signaled);&#xD;&#xA;&#xD;&#xA;    if (signaled == GL_SIGNALED)&#xD;&#xA;        // Done&#xD;&#xA;    else&#xD;&#xA;        // Not done&#xD;&#xA;&#xD;&#xA;You can then of course repeatably call `glGetSynciv()` and check when you receive `GL_SIGNALED`.&#xD;&#xA;&#xD;&#xA;If you want to completely block until it's done then you can do:&#xD;&#xA;&#xD;&#xA;    GLenum status = glClientWaitSync(sync, 0, 0);&#xD;&#xA;&#xD;&#xA;    if (status == GL_CONDITION_SATISFIED)&#xD;&#xA;        // Done&#xD;&#xA;&#xD;&#xA;It blocks and waits for up to `timeout` nanoseconds (the last parameter).&#xD;&#xA;&#xD;&#xA;Remember to delete the [sync object][Sync_Object] again:&#xD;&#xA;&#xD;&#xA;    glDeleteSync(sync);&#xD;&#xA;&#xD;&#xA;When it comes to WebGL. Then note that sync objects are not supported in WebGL 1.0. They are however in WebGL 2.0 in the form of [WebGLSync][WebGLSync].&#xD;&#xA;&#xD;&#xA;*The equivalent to the above code in WebGL 2.0 would be the following:*&#xD;&#xA;&#xD;&#xA;    var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);&#xD;&#xA;&#xD;&#xA;    var signaled = gl.getSyncParameter(sync, gl.SYNC_STATUS);&#xD;&#xA;&#xD;&#xA;    if (signaled == gl.SIGNALED)&#xD;&#xA;        // Done&#xD;&#xA;    else&#xD;&#xA;        // Not done&#xD;&#xA;&#xD;&#xA;    var status = gl.clientWaitSync(sync, 0, 0);&#xD;&#xA;&#xD;&#xA;    if (status == gl.CONDITION_SATISFIED)&#xD;&#xA;        // Done&#xD;&#xA;&#xD;&#xA;    gl.deleteSync(sync);&#xD;&#xA;&#xD;&#xA;   [ARB_sync]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sync.txt&#xD;&#xA;   [Sync_Object]: https://www.khronos.org/opengl/wiki/Sync_Object&#xD;&#xA;   [WebGLSync]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLSync&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11958" PostHistoryTypeId="2" PostId="4972" RevisionGUID="7e8b963d-df88-4e17-8b81-f7d5ff9ac36c" CreationDate="2017-04-07T07:54:11.457" UserId="6407" Text="I'm confused by the `Waves` class [implementation](https://github.com/utilForever/DirectX/blob/master/DirectX%2011/Frank%20D.%20Luna/Common/Waves.cpp#L55) in the source code of the book *Introduction to 3D Game Programming with DirecX11*:&#xD;&#xA;&#xD;&#xA;    float d = damping*dt+2.0f;&#xD;&#xA;    float e = (speed*speed)*(dt*dt)/(dx*dx);&#xD;&#xA;    mK1     = (damping*dt-2.0f)/ d;&#xD;&#xA;    mK2     = (4.0f-8.0f*e) / d;&#xD;&#xA;    mK3     = (2.0f*e) / d;&#xD;&#xA;&#xD;&#xA;How does the code work? I've tried searching waves implementation and found http://stackoverflow.com/questions/6716887/how-to-render-ocean-wave-using-opengl-in-3d , I looked up the links mentioned by the answer but I couldn't understand the complicated equations and it seems that the equations have no relation with the code above. I also tried searching &quot;spatially damped wave&quot;, and then I found http://physics.stackexchange.com/questions/223366/wave-equation-with-spatial-damping, that didn't help me, neither...&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11959" PostHistoryTypeId="1" PostId="4972" RevisionGUID="7e8b963d-df88-4e17-8b81-f7d5ff9ac36c" CreationDate="2017-04-07T07:54:11.457" UserId="6407" Text="How does the Waves class in the book Introduction to 3D Game Programming with DirecX11 work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="11960" PostHistoryTypeId="3" PostId="4972" RevisionGUID="7e8b963d-df88-4e17-8b81-f7d5ff9ac36c" CreationDate="2017-04-07T07:54:11.457" UserId="6407" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="11961" PostHistoryTypeId="50" PostId="4808" RevisionGUID="17176bc6-30af-4295-be35-35d70cd16b20" CreationDate="2017-04-07T15:53:10.347" UserId="-1" />
  <row Id="11962" PostHistoryTypeId="5" PostId="4972" RevisionGUID="a9a47f24-a3bf-402d-9c03-cea6d3063406" CreationDate="2017-04-08T02:48:47.713" UserId="6407" Comment="Be more specific to the problem." Text="I'm confused by the `Waves` class [implementation](https://github.com/utilForever/DirectX/blob/master/DirectX%2011/Frank%20D.%20Luna/Common/Waves.cpp#L55) in the source code of the book *Introduction to 3D Game Programming with DirecX11*:&#xD;&#xA;&#xD;&#xA;    float d = damping*dt+2.0f;&#xD;&#xA;    float e = (speed*speed)*(dt*dt)/(dx*dx);&#xD;&#xA;    mK1     = (damping*dt-2.0f)/ d;&#xD;&#xA;    mK2     = (4.0f-8.0f*e) / d;&#xD;&#xA;    mK3     = (2.0f*e) / d;&#xD;&#xA;&#xD;&#xA;What do the parameters mean? How are the waves generated? I've tried searching waves implementation and found http://stackoverflow.com/questions/6716887/how-to-render-ocean-wave-using-opengl-in-3d , I looked up the links mentioned by the answer but I couldn't understand the complicated equations and it seems that the equations have no relation with the code above. I also tried searching &quot;spatially damped wave&quot;, and then I found http://physics.stackexchange.com/questions/223366/wave-equation-with-spatial-damping, that didn't help me, neither...&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="11965" PostHistoryTypeId="2" PostId="4973" RevisionGUID="7ac125bb-b6c4-45ef-a453-5df3e423db10" CreationDate="2017-04-08T06:18:54.387" UserId="5066" Text="Some of the easy to use GUI libraries for OpenGL I have come across are (in no specific order):&#xD;&#xA;&#xD;&#xA; 1. [imGUI][1]&#xD;&#xA; 2. [NanoGUI][2]&#xD;&#xA; 3. [AntTweakBar][3]&#xD;&#xA;&#xD;&#xA;Although AntTweakBar is bit outdated, it's still pretty easy to use. imGUI is definitely the one you should have a look at once. I personally haven't used NanoGUI but have heard good things about it. &#xD;&#xA;&#xD;&#xA;Hope this helps. &#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ocornut/imgui&#xD;&#xA;  [2]: https://github.com/wjakob/nanogui&#xD;&#xA;  [3]: http://anttweakbar.sourceforge.net/doc/" ContentLicense="CC BY-SA 3.0" />
  <row Id="11966" PostHistoryTypeId="2" PostId="4974" RevisionGUID="5d25cb80-19a4-4e02-a28c-d9ed7e553393" CreationDate="2017-04-08T10:46:11.840" UserId="5256" Text="At one point I had a similiar issue, however, I was using DirectX as opposed to OpenGL so this may not be very helpful but you might be able to gain some knowledge out of this.&#xD;&#xA;&#xD;&#xA;My main objective was to create a level editor with basic functionality such as importing models and postioning. I wanted to use C# and WinForms rather than having to learn another entire framework like Qt. I made my engine available as a DLL and exposed a C-style function that intialized my engine with a provided HWND (a C# panel). This enabled me to render to the panel, so I then expanded upon this 'link' and proceeded to add on additional functionality like importing objects.&#xD;&#xA;&#xD;&#xA;    // in C++:&#xD;&#xA;    extern &quot;C&quot; &#xD;&#xA;    {&#xD;&#xA;      void InitializeMyEngine(HWND window);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can then then use P/Invoke in C# to access that function:&#xD;&#xA;&#xD;&#xA;    class Engine&#xD;&#xA;    {&#xD;&#xA;      [DllImport(&quot;engine.dll&quot;)]&#xD;&#xA;      public static extern void Initialize(IntPtr window);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I then called `Engine.Initialize(someWindowHandle)` in my C# code to initialize the engine. &#xD;&#xA;&#xD;&#xA;Here's a link to where asked how I could do this on the gamedev stack exchange: http://gamedev.stackexchange.com/questions/124249/how-do-i-render-my-directx-c-engine-to-a-c-panel&#xD;&#xA;&#xD;&#xA;I got a few answers and I managed to do what I needed to do (which I've of course detailed there). There is much more detail and code available regarding the implementation aswell. I would suggest asking on the [GameDev Stack Exchange][1] if you don't find a sufficient answer here.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;(photo of the engine rendering a cyan screen when the button is pressed using the method I described)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com&#xD;&#xA;  [2]: https://i.stack.imgur.com/jcvYM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="12977" PostHistoryTypeId="2" PostId="4977" RevisionGUID="5fb753af-4137-4e94-bb3d-c14eb5372bfe" CreationDate="2017-04-10T10:10:59.200" UserId="5256" Text="I am currently reading through Peter Shirley's [Ray Tracing in One Weekend][1]. In the beginning chapters where the author introduces diffuse surfaces we a presented with this function:&#xD;&#xA;&#xD;&#xA;    vec3 color(const ray&amp; r, hitable *world)&#xD;&#xA;    {&#xD;&#xA;    hit_record rec;&#xD;&#xA;    if(world-&gt;hit(r, 0.0, MAXFLOAT,rec))&#xD;&#xA;      {&#xD;&#xA;       vec3 target = rec.p + rec.normal + random_in_unit_sphere();&#xD;&#xA;       return 0.5*color(ray(rec.p, target-rec.p), world);&#xD;&#xA;      }&#xD;&#xA;    else&#xD;&#xA;      {&#xD;&#xA;       vec3 unit_direction = unit_vector(r.direction());&#xD;&#xA;       float t = 0.5*(unit_direction.y() + 1.0);&#xD;&#xA;       return (1.0-t)*vec3(1.0, 1.0, 1.0) + t*vec3(0.5, 0.7, 1.0);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Can somebody where the actual definition for the function is? Because in the first part of the `if`the return `value` is `0.5*color(ray(rec.p, target-rec.p), world);`. Will it execute the function again except go through the `else`? &#xD;&#xA;&#xD;&#xA;Regarding what the function actually does here is what I have gathered from the book based on my current understanding:&#xD;&#xA;&#xD;&#xA; 1. Pick a random point s from the unit radius sphere that is tangent to the hitpoint, and send a&#xD;&#xA;ray from the hitpoint p to the random point s. That sphere has center (p+N)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA; 2. Which then gives us:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.amazon.in/Ray-Tracing-Weekend-Minibooks-Book-ebook/dp/B01B5AODD8&#xD;&#xA;  [2]: https://i.stack.imgur.com/BmPFx.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/edqsj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="12978" PostHistoryTypeId="1" PostId="4977" RevisionGUID="5fb753af-4137-4e94-bb3d-c14eb5372bfe" CreationDate="2017-04-10T10:10:59.200" UserId="5256" Text="Can somebody explain this Ray Tracing Function?" ContentLicense="CC BY-SA 3.0" />
  <row Id="12979" PostHistoryTypeId="3" PostId="4977" RevisionGUID="5fb753af-4137-4e94-bb3d-c14eb5372bfe" CreationDate="2017-04-10T10:10:59.200" UserId="5256" Text="|raytracing|c++|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="12980" PostHistoryTypeId="2" PostId="4978" RevisionGUID="f9e0e785-ef94-49d1-9791-f09119e160d0" CreationDate="2017-04-10T10:36:13.927" UserId="137" Text="    vec3 target = rec.p + rec.normal + random_in_unit_sphere();&#xD;&#xA;    return 0.5*color(ray(rec.p, target-rec.p), world);&#xD;&#xA;&#xD;&#xA;this is the exact same as &#xD;&#xA;&#xD;&#xA;    vec3 targetDir = rec.normal + random_in_unit_sphere();&#xD;&#xA;    return 0.5*color(ray(rec.p, targetDir), world);&#xD;&#xA;&#xD;&#xA;In other words the sphere is a way to pick a random direction which is biased towards the normal direction without doing a lot of fancy maths.&#xD;&#xA;&#xD;&#xA;And yeah if that hits again it will repeat the process again and again until it hits the sky box. this can be avoided by adding a parameter to avoid unlimited recursion. &#xD;&#xA;&#xD;&#xA;However that function is bad in general for a few reasons:&#xD;&#xA;&#xD;&#xA;1. The color on hit should depend on the object's material (the color) and the relation between the normal vector the incoming eye ray and the outgoing light ray.&#xD;&#xA;&#xD;&#xA;2. The light sky box is hardcoded to be a gradiant.&#xD;&#xA;&#xD;&#xA;3. only a single recursive sample on each hit. This gives very grainy images and requires a lot of samples per pixel to converge to a proper image." ContentLicense="CC BY-SA 3.0" />
  <row Id="12981" PostHistoryTypeId="2" PostId="4979" RevisionGUID="e4b47ab5-148e-4b5f-9e45-49064de10a13" CreationDate="2017-04-10T17:52:03.400" UserId="5256" Text="What is importance sampling? Every article I read about it mentions 'PDF' what is that aswell?&#xD;&#xA;&#xD;&#xA;From what I gather importance sampling is a technique to only sample areas on a hemisphere that matter more than others. So ideally I should sample rays towards light sources to reduce noise and increase speed, also some BRDF's at grazing angles have little no difference in the calculation so using importance sampling to avoid that is good? &#xD;&#xA;&#xD;&#xA;If I were to implement importance sampling for a Cook-Torrance BRDF how could I do this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="12982" PostHistoryTypeId="1" PostId="4979" RevisionGUID="e4b47ab5-148e-4b5f-9e45-49064de10a13" CreationDate="2017-04-10T17:52:03.400" UserId="5256" Text="What is Importance Sampling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="12983" PostHistoryTypeId="3" PostId="4979" RevisionGUID="e4b47ab5-148e-4b5f-9e45-49064de10a13" CreationDate="2017-04-10T17:52:03.400" UserId="5256" Text="|brdf|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="12986" PostHistoryTypeId="2" PostId="4980" RevisionGUID="f0c87137-7b38-4e01-8914-4fd4dab7ab83" CreationDate="2017-04-10T18:29:00.203" UserId="6422" Text="Good answer above.    (I like that the book adds in p then subtracts it.)&#xD;&#xA;&#xD;&#xA;This is a hard-coded grey world as a &quot;hello world&quot; kind of ray tracer.   The 0.5 is the hard-coded reflectance.   Keep working through book and the object reflectance and max-recursion will be addressed.   Ray branching I avoid like the plague.   In cost benefit I am always a skeptic on ray trees versus ray paths." ContentLicense="CC BY-SA 3.0" />
  <row Id="12987" PostHistoryTypeId="2" PostId="4981" RevisionGUID="0a962809-a838-446f-8564-21d35d90de7d" CreationDate="2017-04-10T20:33:01.677" UserId="3332" Text="Take a look at Qt.  Qt is built on opengl and therefore integrates with it pretty easily.&#xD;&#xA;&#xD;&#xA;http://doc.qt.io/qt-5/qtopengl-hellogl2-example.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="12988" PostHistoryTypeId="2" PostId="4982" RevisionGUID="2913d23a-2c07-40b6-8f8b-8b011b0bd7a8" CreationDate="2017-04-10T21:35:15.237" UserId="4837" Text="Recently I have been having a rather confusing performance drop with loading in layers of a 2D texture array, but only in one case from what I can tell, leaving me to speculate on why it is happening as I have never seen anything like this before.&#xD;&#xA;&#xD;&#xA;Firstly to explain some context for this problem, I implemented a simple version of a virtual texture atlas based on some papers I read by NVIDIA and idTech which in short loads textures (which have been split into fixed size tiles) into various levels of the 2D texture array based on which layers are considered &quot;free&quot; in a CPU-side list of free indices. Sampling in the fragment shader is then preformed by accessing a page table stored as a persistently coherently mapped SSBO (for CPU-side updating) which associates offsets in the UVs with layers of the texture array.&#xD;&#xA;&#xD;&#xA;Due to the fact that the texture when created is uninitialized, every layer is considered free, so texture tiles to be loaded will slowly fill up the uninitialized layers (preferring them over previously freed layers). Once all of the uninitialized layers have been used, additional tiles will then begin overwriting previously freed layers, if any exist when needed. Also note that I am using `glCompressedTexSubImage3D` to load in each layer and that I load in mipmap levels as well manually per layer with this call as well.&#xD;&#xA;&#xD;&#xA;This system works fine and was tested rather extensively until I began to notice the problem which this question is about. In short, after all of the uninitialized layers of the texture array were used up, the next 5-15 (I don't know exactly how many, but it's just a few) texture tiles which are loaded suffer massive performance drops. After that, everything returns to normal and the problem never returns (from what I can tell). Also note that this is while some currently drawn textures were also in use at the lower end of the texture array which is right before where the first free tiles begin (due to the first in first out nature of the free list).&#xD;&#xA;&#xD;&#xA;Upon examining the problem further, I noticed through using the NVIDIA Nsight graphics profiling tool that the call after `glCompressedTexSubImage3D` in the cases where performance was impacted blocks on the CPU for very long periods of time, usually 10-40ms per mipmap level (in this case it was `glGetError`, but any other call following it had the same effect after disabling error checking to ensure that was not the problem).&#xD;&#xA;&#xD;&#xA;Since the API was blocking, I assumed that it was some sort of synchronization issue with the GPU perhaps due to the locality of the newly loaded tiles with respect to tiles currently being drawn as it may have considered them &quot;in use&quot;. That hypothesis did not add up in my mind due to how long the calls were blocking for as each one was the length of multiple frames at 16ms as well as how this problem never appears to return multiple additional times through this same process, though I'm not ignoring that possibility.&#xD;&#xA;&#xD;&#xA;Another odd thing I found was that during the time the next call was blocking, many tiny GPU commands were being executed according to NVIDIA Nsight, which I usually only see under any sort of drawing activity.&#xD;&#xA;&#xD;&#xA;At this point I'm pretty much stumped and don't know what could possibly be causing this, so any help would be greatly appreciated. Additional details are provided below (and more can be requested if needed):&#xD;&#xA;&#xD;&#xA;**Texture Array** (there are 3 of them):&#xD;&#xA;&#xD;&#xA; - Format: `COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT`, `COMPRESSED_RED_RGTC1`,&#xD;&#xA;   `COMPRESSED_RG_RGTC2`&#xD;&#xA; - Extents: 256x256x512, 9 mipmap levels&#xD;&#xA;&#xD;&#xA;**GPU**:&#xD;&#xA;&#xD;&#xA;GeForce GTX 960M&#xD;&#xA;&#xD;&#xA;**NVIDIA Nsight Results**:&#xD;&#xA;&#xD;&#xA;Wide view of 3 long frames where the slow texture loading happens:&#xD;&#xA;&#xD;&#xA;[![Overall view][1]][1]&#xD;&#xA;&#xD;&#xA;Zoomed in view near the very start of the first slow call to `glCompressedTexSubImage3D` (which cannot be seen as it only blocks for a few microseconds), note the many tiny green lines below the blocking `glGetError` calls representing GPU commands:&#xD;&#xA;&#xD;&#xA;[![Zoomed view][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nwjN4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SfLfV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="12989" PostHistoryTypeId="1" PostId="4982" RevisionGUID="2913d23a-2c07-40b6-8f8b-8b011b0bd7a8" CreationDate="2017-04-10T21:35:15.237" UserId="4837" Text="Performance impact during texture layer loading" ContentLicense="CC BY-SA 3.0" />
  <row Id="12990" PostHistoryTypeId="3" PostId="4982" RevisionGUID="2913d23a-2c07-40b6-8f8b-8b011b0bd7a8" CreationDate="2017-04-10T21:35:15.237" UserId="4837" Text="|opengl|texture|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="12991" PostHistoryTypeId="5" PostId="4982" RevisionGUID="048d10ea-6864-47f4-8f00-3176a5339769" CreationDate="2017-04-10T21:40:19.603" UserId="4837" Comment="edited body" Text="Recently I have been having a rather confusing performance drop with loading in layers of a 2D texture array, but only in one case from what I can tell, leaving me to speculate on why it is happening as I have never seen anything like this before.&#xD;&#xA;&#xD;&#xA;Firstly to explain some context for this problem, I implemented a simple version of a virtual texture atlas based on some papers I read by NVIDIA and idTech which in short loads textures (which have been split into fixed size tiles) into various levels of the 2D texture array based on which layers are considered &quot;free&quot; in a CPU-side list of free indices. Sampling in the fragment shader is then preformed by accessing a page table stored as a persistently coherently mapped SSBO (for CPU-side updating) which associates offsets in the UVs with layers of the texture array.&#xD;&#xA;&#xD;&#xA;Due to the fact that the texture when created is uninitialized, every layer is considered free, so texture tiles to be loaded will slowly fill up the uninitialized layers (preferring them over previously freed layers). Once all of the uninitialized layers have been used, additional tiles will then begin overwriting previously freed layers, if any exist when needed. Also note that I am using `glCompressedTexSubImage3D` to load in each layer and that I load in mipmap levels as well manually per layer with this call as well.&#xD;&#xA;&#xD;&#xA;This system works fine and was tested rather extensively until I began to notice the problem which this question is about. In short, after all of the uninitialized layers of the texture array were used up, the next 5-15 (I don't know exactly how many, but it's just a few) texture tiles which are loaded suffer massive performance drops. After that, everything returns to normal and the problem never returns (from what I can tell). Also note that this is while some currently drawn textures were also in use at the lower end of the texture array which is right before where the first free tiles begin (due to the first in first out nature of the free list).&#xD;&#xA;&#xD;&#xA;Upon examining the problem further, I noticed through using the NVIDIA Nsight graphics profiling tool that the call after `glCompressedTexSubImage3D` in the cases where performance was impacted blocks on the CPU for very long periods of time, usually 10-40ms per mipmap level (in this case it was `glGetError`, but any other call following it had the same effect after disabling error checking to ensure that was not the problem).&#xD;&#xA;&#xD;&#xA;Since the API was blocking, I assumed that it was some sort of synchronization issue with the GPU perhaps due to the locality of the newly loaded tiles with respect to tiles currently being drawn as it may have considered them &quot;in use&quot;. That hypothesis did not add up in my mind due to how long the calls were blocking for as each one was the length of multiple frames at 16ms as well as how this problem never appears to return even after multiple times through this same process, though I'm not ignoring that possibility.&#xD;&#xA;&#xD;&#xA;Another odd thing I found was that during the time the next call was blocking, many tiny GPU commands were being executed according to NVIDIA Nsight, which I usually only see under any sort of drawing activity.&#xD;&#xA;&#xD;&#xA;At this point I'm pretty much stumped and don't know what could possibly be causing this, so any help would be greatly appreciated. Additional details are provided below (and more can be requested if needed):&#xD;&#xA;&#xD;&#xA;**Texture Array** (there are 3 of them):&#xD;&#xA;&#xD;&#xA; - Format: `COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT`, `COMPRESSED_RED_RGTC1`,&#xD;&#xA;   `COMPRESSED_RG_RGTC2`&#xD;&#xA; - Extents: 256x256x512, 9 mipmap levels&#xD;&#xA;&#xD;&#xA;**GPU**:&#xD;&#xA;&#xD;&#xA;GeForce GTX 960M&#xD;&#xA;&#xD;&#xA;**NVIDIA Nsight Results**:&#xD;&#xA;&#xD;&#xA;Wide view of 3 long frames where the slow texture loading happens (the line down the screen is centered on the first texture loading call):&#xD;&#xA;&#xD;&#xA;[![Overall view][1]][1]&#xD;&#xA;&#xD;&#xA;Zoomed in view near the very start of the first slow call to `glCompressedTexSubImage3D` (which cannot be seen as it only blocks for a few microseconds), note the many tiny green lines below the blocking `glGetError` calls representing GPU commands (as again the line down the screen is centered on the first texture loading call):&#xD;&#xA;&#xD;&#xA;[![Zoomed view][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nwjN4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SfLfV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="12992" PostHistoryTypeId="2" PostId="4983" RevisionGUID="1564599e-f3ea-4d02-b26c-a3de2d1c860f" CreationDate="2017-04-10T21:44:37.270" UserId="6349" Text="Can i have a root signature with 3 root parameters all being of the UAV type? Because what I am trying to do is, add two buffers and put the output of that in a output buffer.&#xD;&#xA;&#xD;&#xA;In the following snippet I am trying to do the afroementioned. However, I get an error at the line calling D3DX12SerializeVersionedRootSignature()&#xD;&#xA;&#xD;&#xA;Is it because I am not allowed to have 3 uav ranges?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;CD3DX12_DESCRIPTOR_RANGE1 ranges_madhu[3];&#xD;&#xA;			ranges_madhu[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;			ranges_madhu[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;			ranges_madhu[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;			&#xD;&#xA;			CD3DX12_ROOT_PARAMETER1 rootParameters_madhu[ComputeRootParametersCount_madhu]; // this is 3   (thus all 3 ranges have been initialized as UAVs)&#xD;&#xA;			rootParameters_madhu[ComputeRootUAVTable_in1].InitAsDescriptorTable(1, &amp;ranges_madhu[0], D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;			rootParameters_madhu[ComputeRootUAVTable_in2].InitAsDescriptorTable(1, &amp;ranges_madhu[1], D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;			rootParameters_madhu[ComputeRootUAVTable_outp1].InitAsDescriptorTable(1, &amp;ranges_madhu[2], D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;			&#xD;&#xA;			CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC computeRootSignatureDesc_madhu;&#xD;&#xA;			computeRootSignatureDesc_madhu.Init_1_1(_countof(rootParameters_madhu), rootParameters_madhu, 0, nullptr);&#xD;&#xA;			&#xD;&#xA;			ComPtr&lt;ID3DBlob&gt; signature1;&#xD;&#xA;			ComPtr&lt;ID3DBlob&gt; error1;&#xD;&#xA;			&#xD;&#xA;			ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&amp;computeRootSignatureDesc_madhu, featureData_madhu.HighestVersion, &amp;signature1, &amp;error1));&#xD;&#xA;ThrowIfFailed(m_device-&gt;CreateRootSignature(0, signature1-&gt;GetBufferPointer(), signature1-&gt;GetBufferSize(), IID_PPV_ARGS(&amp;m_computeRootSignature1)));&#xD;&#xA;NAME_D3D12_OBJECT(m_computeRootSignature1);" ContentLicense="CC BY-SA 3.0" />
  <row Id="12993" PostHistoryTypeId="1" PostId="4983" RevisionGUID="1564599e-f3ea-4d02-b26c-a3de2d1c860f" CreationDate="2017-04-10T21:44:37.270" UserId="6349" Text="DX12 compute signature" ContentLicense="CC BY-SA 3.0" />
  <row Id="12994" PostHistoryTypeId="3" PostId="4983" RevisionGUID="1564599e-f3ea-4d02-b26c-a3de2d1c860f" CreationDate="2017-04-10T21:44:37.270" UserId="6349" Text="|directx12|" ContentLicense="CC BY-SA 3.0" />
  <row Id="12995" PostHistoryTypeId="5" PostId="4983" RevisionGUID="3be436c7-63a7-4101-8761-597423130b4b" CreationDate="2017-04-10T21:59:48.300" UserId="48" Comment="fix code formatting" Text="Can i have a root signature with 3 root parameters all being of the UAV type? Because what I am trying to do is, add two buffers and put the output of that in a output buffer.&#xD;&#xA;&#xD;&#xA;In the following snippet I am trying to do the afroementioned. However, I get an error at the line calling D3DX12SerializeVersionedRootSignature()&#xD;&#xA;&#xD;&#xA;Is it because I am not allowed to have 3 uav ranges?&#xD;&#xA;&#xD;&#xA;	CD3DX12_DESCRIPTOR_RANGE1 ranges_madhu[3];&#xD;&#xA;	ranges_madhu[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;	ranges_madhu[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;	ranges_madhu[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;			&#xD;&#xA;	CD3DX12_ROOT_PARAMETER1 rootParameters_madhu[ComputeRootParametersCount_madhu]; // this is 3   (thus all 3 ranges have been initialized as UAVs)&#xD;&#xA;	rootParameters_madhu[ComputeRootUAVTable_in1].InitAsDescriptorTable(1, &amp;ranges_madhu[0], D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;	rootParameters_madhu[ComputeRootUAVTable_in2].InitAsDescriptorTable(1, &amp;ranges_madhu[1], D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;	rootParameters_madhu[ComputeRootUAVTable_outp1].InitAsDescriptorTable(1, &amp;ranges_madhu[2], D3D12_SHADER_VISIBILITY_ALL);&#xD;&#xA;&#xD;&#xA;	CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC computeRootSignatureDesc_madhu;&#xD;&#xA;	computeRootSignatureDesc_madhu.Init_1_1(_countof(rootParameters_madhu), rootParameters_madhu, 0, nullptr);&#xD;&#xA;&#xD;&#xA;	ComPtr&lt;ID3DBlob&gt; signature1;&#xD;&#xA;	ComPtr&lt;ID3DBlob&gt; error1;&#xD;&#xA;&#xD;&#xA;	ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&amp;computeRootSignatureDesc_madhu, featureData_madhu.HighestVersion, &amp;signature1, &amp;error1));&#xD;&#xA;	ThrowIfFailed(m_device-&gt;CreateRootSignature(0, signature1-&gt;GetBufferPointer(), signature1-&gt;GetBufferSize(), IID_PPV_ARGS(&amp;m_computeRootSignature1)));&#xD;&#xA;	NAME_D3D12_OBJECT(m_computeRootSignature1);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="12996" PostHistoryTypeId="2" PostId="4984" RevisionGUID="228c5cd5-cff5-4581-90ae-240cc4fda4dd" CreationDate="2017-04-10T23:24:46.677" UserId="48" Text="You're trying to map all three UAVs to the same descriptor slot (slot 0).&#xD;&#xA;&#xD;&#xA;    ranges_madhu[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;    ranges_madhu[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;    ranges_madhu[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE);&#xD;&#xA;&#xD;&#xA;The `baseShaderRegister` value (the third parameter to these calls) indicates which descriptor slot to use. You have all of them set to 0, which won't work. They need to be distinct. For example, they could be 0, 1, and 2." ContentLicense="CC BY-SA 3.0" />
  <row Id="12997" PostHistoryTypeId="2" PostId="4985" RevisionGUID="753c6cad-f3bb-4379-9a77-fa38403c8b8e" CreationDate="2017-04-11T00:13:55.873" UserId="48" Text="From the way the problem only manifests when you start overwriting previously used texture tiles, I suspect you're running afoul of some driver heuristic that's attempting to manage the lifetime of the texture data on the GPU.&#xD;&#xA;&#xD;&#xA;In general, when you update buffer or texture data from the CPU, the driver has to make sure it doesn't overwrite anything that might still be in use by the GPU (considering that the CPU and GPU run asynchronously to each other). There are various ways the driver can do this, such as internally double-buffering the texture, inserting sync points (for the CPU to wait on the GPU), or initially copying data to a temporary staging buffer and then later re-copying it to its final destination. All this stuff is under-the-hood and the driver makes its own decisions about what strategy to employ in any given situation, using some heuristics based on texture size, usage patterns, etc.&#xD;&#xA;&#xD;&#xA;I can only guess at the details, but I suspect what's happening is that the driver is getting into a state where it thinks those previously-used texture tiles are still in use on the GPU somehow. Then when you start to overwrite them, it decides that it needs to make a second instance of the whole texture, and laboriously copies everything over before finally doing the updates you wanted—or something like that. That could be the many tiny draws you see in Nsight.&#xD;&#xA;&#xD;&#xA;It's still a mystery why it's taking tens of milliseconds to do that, though. Maybe the textures are large enough that a second copy of them causes you to run out of VRAM? In that case, you'd get a lot of thrashing as things are spilled to main RAM. That's just a guess, though. As for why the bad behavior only happens for a few tiles and then goes back to normal, it could be that the driver heuristics are deciding to switch to a different strategy at that point.&#xD;&#xA;&#xD;&#xA;Anyway, as for how to fix it, you might try using [`glInvalidateTexSubImage`](http://docs.gl/gl4/glInvalidateTexSubImage) whenever you free a texture tile. This lets the driver know that you don't care what was in that texture tile before, which _hopefully_ will convince it to just update the texture in-place rather than doing anything crazy with it.&#xD;&#xA;&#xD;&#xA;Another thing to try is to make sure you don't try to re-use a texture tile in the very next frame after you free it, but give it a frame or two of &quot;downtime&quot; before re-using it. But it sounds like that's probably the case already, given that you prefer unused tiles before you start re-using them.&#xD;&#xA;&#xD;&#xA;If that doesn't help, I'd recommend sending an email to devsupport@nvidia.com. The OpenGL driver team there can likely take your Nsight captures and help diagnose the issue, and fix it if it's due to a driver bug." ContentLicense="CC BY-SA 3.0" />
  <row Id="12999" PostHistoryTypeId="2" PostId="4986" RevisionGUID="7fca0c73-fee5-4b39-9e54-dcdc781d962c" CreationDate="2017-04-11T08:21:18.333" UserId="385" Text="By using smooth shading (i.e. interpolation of normals), an object can have a smooth look despite low polygon count. A nasty artifact that can happen when casting shadow rays is the [Shadow Line Artifact][1]. Since shadow rays originate from a certain position and don't usually take the normal into account, a complete face on a smooth object will either be shadowed or not, revealing the hard edges again:&#xD;&#xA;&#xD;&#xA;[![Flat and smooth shading, right one with artifacts.][2]][2]&#xD;&#xA;&#xD;&#xA;The shadow is, so to speak, 'correct' and the weird appearance results from the normal map interpolation 'cheat'. Nevertheless, it is visually distracting. The linked article above, written in 2009, suggests removing shadows or self-shadows on objects that show this kind of artifact, which (especially for non-convex objects) is not a satisfying solution.&#xD;&#xA;&#xD;&#xA;This is a very common problem inherent to ray tracing algorithms. I wonder if there are any better solution to it than getting rid of the shadows altogether.&#xD;&#xA;&#xD;&#xA;  [1]: http://wiki.povray.org/content/Knowledgebase:The_Shadow_Line_Artifact&#xD;&#xA;  [2]: https://i.stack.imgur.com/VH8eM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13000" PostHistoryTypeId="1" PostId="4986" RevisionGUID="7fca0c73-fee5-4b39-9e54-dcdc781d962c" CreationDate="2017-04-11T08:21:18.333" UserId="385" Text="Ray Tracing Shadows: The Shadow Line Artifact" ContentLicense="CC BY-SA 3.0" />
  <row Id="13001" PostHistoryTypeId="3" PostId="4986" RevisionGUID="7fca0c73-fee5-4b39-9e54-dcdc781d962c" CreationDate="2017-04-11T08:21:18.333" UserId="385" Text="|raytracing|shadow|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13002" PostHistoryTypeId="5" PostId="4986" RevisionGUID="84e5fde8-de7b-4bf1-8057-2809c1259c2a" CreationDate="2017-04-11T08:28:47.623" UserId="385" Comment="Grammar correction" Text="By using smooth shading (i.e. interpolation of normals), an object can have a smooth look despite low polygon count. A nasty artifact that can happen when casting shadow rays is the [Shadow Line Artifact][1]. Since shadow rays originate from a certain position and don't usually take the normal into account, a complete face on a smooth object will either be shadowed or not, revealing the hard edges again:&#xD;&#xA;&#xD;&#xA;[![Flat and smooth shading, right one with artifacts.][2]][2]&#xD;&#xA;&#xD;&#xA;The shadow is, so to speak, 'correct' and the weird appearance results from the normal map interpolation 'cheat'. Nevertheless, it is visually distracting. The linked article above, written in 2009, suggests removing shadows or self-shadows on objects that show this kind of artifact, which (especially for non-convex objects) is not a satisfying solution.&#xD;&#xA;&#xD;&#xA;This is a very common problem inherent to ray tracing algorithms. I wonder if there is any better solution to it than subdividing the mesh into flat-shaded high-poly or getting rid of the shadows altogether.&#xD;&#xA;&#xD;&#xA;  [1]: http://wiki.povray.org/content/Knowledgebase:The_Shadow_Line_Artifact&#xD;&#xA;  [2]: https://i.stack.imgur.com/VH8eM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13003" PostHistoryTypeId="2" PostId="4987" RevisionGUID="1cf61a11-276d-4bb4-9995-adf661957802" CreationDate="2017-04-11T16:07:27.453" UserId="2041" Text="The shadow terminator problem (as it's also known) is still something of an open problem in ray-tracing. As you say, disabling self-shadowing is not a very good workaround, because non-convex meshes often *need* to self-shadow. There's a possible refinement to this method. Instead of throwing away all shadow ray intersections with the same object, you can only throw away the intersection if it's with the same object and it's through the reverse face of the triangle (i.e. discard the intersection if $d\dot\ N &gt; 0$, where $N$ is the geometric normal of the intersected polygon and $d$ is the shadow ray direction).&#xD;&#xA;&#xD;&#xA;One alternative that I've used successfully is to offset the origin of the shadow ray a short distance along the surface normal. This way, the shadow ray originates not at the geometric surface of the mesh (which is only an approximation) but at the hypothetical surface of the real object.&#xD;&#xA;&#xD;&#xA;In theory, you should choose the distance along the normal according to the point's distance from that polygon's vertices, so that the origin is on the approximated surface, but in practice, a small fixed offset works for almost all situations.&#xD;&#xA;&#xD;&#xA;You should also be sure to use the normal rather than the geometric surface to decide whether the light is &quot;behind&quot; the surface. That is, if $N\dot\ L &lt; 0$, the shading point is in shadow (without needing to cast a ray), where $N$ is the interpolated and shaded normal." ContentLicense="CC BY-SA 3.0" />
  <row Id="13004" PostHistoryTypeId="2" PostId="4988" RevisionGUID="36d9ff9b-7448-413b-bb30-fb2cb68cf92c" CreationDate="2017-04-11T20:07:54.760" UserId="303" Text="This implementation represents the water as a regular height field grid. The funcion parameters m and n are the dimensions of the grid, dx is the regular distance between the water vertices, dt is the time step, speed is the speed of the movement and damping is a constant to ease disturbance as the water flows from the disturbance center." ContentLicense="CC BY-SA 3.0" />
  <row Id="13005" PostHistoryTypeId="5" PostId="4682" RevisionGUID="a916b136-7d03-4a20-aafe-e45ab76d31f0" CreationDate="2017-04-11T20:37:08.920" UserId="6023" Comment="added 74 characters in body" Text="I wrote a small python script with recursion to create a &quot;lattice&quot; of non-overlapping pentagons. Below one can see the first stages of recursion.&#xD;&#xA;&#xD;&#xA;[![first recursion][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![second recursion][2]][2]&#xD;&#xA;&#xD;&#xA;[![third recursion][3]][3]&#xD;&#xA;&#xD;&#xA;One can see that 5 small pentagons are missing in the second stage of recursion. The code in python to generate these figures is this:&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;    # fill the plane with pentagons as tightly as possible in a regular way&#xD;&#xA;    #!/usr/bin/python&#xD;&#xA;    import numpy as np&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    N = 5&#xD;&#xA;    phi = (1.0+np.sqrt(5.0))/2&#xD;&#xA;    def pentagon (X, Y, n):&#xD;&#xA;        if n == 0:&#xD;&#xA;            rx = np.append(X, X[0])&#xD;&#xA;            ry = np.append(Y, Y[0])&#xD;&#xA;            plt.plot(rx, ry, 'r-')&#xD;&#xA;            return&#xD;&#xA;        for i in range(N):&#xD;&#xA;            Xn = np.array([X[i], X[i], X[i], X[i], X[i]])&#xD;&#xA;            Yn = np.array([Y[i], Y[i], Y[i], Y[i], Y[i]])&#xD;&#xA;        U = Xn/phi+X*(1-1.0/phi)&#xD;&#xA;        V = Yn/phi+Y*(1-1.0/phi)&#xD;&#xA;        pentagon (U, V, n-1)&#xD;&#xA;    Xn = X/phi +np.roll(X, 2)*(1-1.0/phi)&#xD;&#xA;    Yn = Y/phi +np.roll(Y, 2)*(1-1.0/phi)&#xD;&#xA;    # center pentagon&#xD;&#xA;    pentagon (Xn, Yn, n-1)&#xD;&#xA;    Ind = np.arange(N)&#xD;&#xA;    theta =np.pi/10&#xD;&#xA;    X = np.cos(Ind*2*np.pi/N+theta)&#xD;&#xA;    Y = np.sin(Ind*2*np.pi/N+theta)&#xD;&#xA;    plt.figure()&#xD;&#xA;    plt.axes().set_aspect('equal')&#xD;&#xA;    n_iter = 2 # number of iterations&#xD;&#xA;    pentagon (X, Y, n_iter)&#xD;&#xA;    figure = &quot;pentagons%d.png&quot; % n_iter&#xD;&#xA;    plt.axis('off')&#xD;&#xA;    plt.savefig(figure)&#xD;&#xA;    plt.show()&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;Any suggestions on how to fill in the missing pentagons in a simple way (e.g. keeping the recursive nature of the algorithm)? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WIGNE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1uVtg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/QQscK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13006" PostHistoryTypeId="2" PostId="4989" RevisionGUID="0b579261-b697-4166-8fd4-96fa21fee348" CreationDate="2017-04-11T21:18:18.350" UserId="6349" Text="I am pretty new to graphics programming using DX12. I was testing out my skills by building a shader to add 2 buffers and put the result in an output buffer. I have written this code in &quot;ComputeShader.hlsl&quot; however when i tried to invoke it using the following, i get an error sayin &quot;file not found&quot;&#xD;&#xA;&#xD;&#xA;ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L&quot;ComputeShader.hlsl&quot;).c_str(), nullptr, nullptr, &quot;main&quot;, &quot;cs_5_0&quot;, compileFlags, 0, &amp;computeShader_madhu, nullptr));&#xD;&#xA;&#xD;&#xA;Is there something that I am doing wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13007" PostHistoryTypeId="1" PostId="4989" RevisionGUID="0b579261-b697-4166-8fd4-96fa21fee348" CreationDate="2017-04-11T21:18:18.350" UserId="6349" Text="DX12- hlsl code invoking" ContentLicense="CC BY-SA 3.0" />
  <row Id="13008" PostHistoryTypeId="3" PostId="4989" RevisionGUID="0b579261-b697-4166-8fd4-96fa21fee348" CreationDate="2017-04-11T21:18:18.350" UserId="6349" Text="|directx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13012" PostHistoryTypeId="2" PostId="4991" RevisionGUID="c37e49e0-5337-486c-bfc0-431db1d86dc7" CreationDate="2017-04-11T22:12:51.680" UserId="6349" Text="So i am new to the DX12 world. I am currently trying to tweek the nbody_gravity DX12 sample, but appending or calling another Compute Shader which is to add 2 buffers to produce an output in a different buffer.&#xD;&#xA;&#xD;&#xA;1)I have written this code in &quot;ComputeShader.hlsl&quot; however when i tried to invoke it using the following, i get an error sayin &quot;file not found&quot;&#xD;&#xA;2)When i printed the debug error it says the following: D3D12GetDebugInterface: This method requires the D3D12 SDK Layers for Windows 10, but they are not present on the system.&#xD;&#xA;&#xD;&#xA;I am invoking my shader after the default invocation to the nBodyGravity.hlsl is done:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;ComPtr&lt;ID3DBlob&gt; computeShader;&#xD;&#xA;ComPtr&lt;ID3DBlob&gt; computeShader_m;&#xD;&#xA;&#xD;&#xA;#if defined(_DEBUG)&#xD;&#xA;		// Enable better shader debugging with the graphics debugging tools.&#xD;&#xA;		UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;&#xD;&#xA;#else&#xD;&#xA;		UINT compileFlags = 0;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L&quot;NBodyGravityCS.hlsl&quot;).c_str(), nullptr, nullptr, &quot;CSMain&quot;, &quot;cs_5_0&quot;, compileFlags, 0, &amp;computeShader, nullptr));&#xD;&#xA;&#xD;&#xA;//extra call for my shader&#xD;&#xA;ComPtr&lt;ID3DBlob&gt; error_ptr;&#xD;&#xA;		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L&quot;ComputeShader.hlsl&quot;).c_str(), nullptr, nullptr, &quot;main&quot;, &quot;cs_5_0&quot;, compileFlags, 0, &amp;computeShader_m, &amp;error_ptr));&#xD;&#xA;&#xD;&#xA;if (error_ptr)&#xD;&#xA;{&#xD;&#xA;	OutputDebugStringA((char *)error_ptr-&gt;GetBufferPointer());&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there somthing amiss?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13013" PostHistoryTypeId="1" PostId="4991" RevisionGUID="c37e49e0-5337-486c-bfc0-431db1d86dc7" CreationDate="2017-04-11T22:12:51.680" UserId="6349" Text="Invoking shader in DX" ContentLicense="CC BY-SA 3.0" />
  <row Id="13014" PostHistoryTypeId="3" PostId="4991" RevisionGUID="c37e49e0-5337-486c-bfc0-431db1d86dc7" CreationDate="2017-04-11T22:12:51.680" UserId="6349" Text="|directx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13016" PostHistoryTypeId="5" PostId="4991" RevisionGUID="3cc0f9c2-ab55-41a6-ae5d-25133ac7c975" CreationDate="2017-04-12T07:06:51.280" UserId="231" Comment="Apply code formatting and numbered bullets" Text="So I am new to the DX12 world. I am currently trying to tweek the nbody_gravity DX12 sample, but appending or calling another Compute Shader which is to add 2 buffers to produce an output in a different buffer.&#xD;&#xA;&#xD;&#xA;1. I have written this code in &quot;ComputeShader.hlsl&quot; however when i tried to invoke it using the following, i get an error sayin &quot;file not found&quot;&#xD;&#xA;2. When i printed the debug error it says the following: D3D12GetDebugInterface: This method requires the D3D12 SDK Layers for Windows 10, but they are not present on the system.&#xD;&#xA;&#xD;&#xA;I am invoking my shader after the default invocation to the nBodyGravity.hlsl is done:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    ComPtr&lt;ID3DBlob&gt; computeShader;&#xD;&#xA;    ComPtr&lt;ID3DBlob&gt; computeShader_m;&#xD;&#xA;&#xD;&#xA;    #if defined(_DEBUG)&#xD;&#xA;    		// Enable better shader debugging with the graphics debugging tools.&#xD;&#xA;    		UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;&#xD;&#xA;    #else&#xD;&#xA;    		UINT compileFlags = 0;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L&quot;NBodyGravityCS.hlsl&quot;).c_str(), nullptr, nullptr, &quot;CSMain&quot;, &quot;cs_5_0&quot;, compileFlags, 0, &amp;computeShader, nullptr));&#xD;&#xA;    &#xD;&#xA;    //extra call for my shader&#xD;&#xA;    ComPtr&lt;ID3DBlob&gt; error_ptr;&#xD;&#xA;    		ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L&quot;ComputeShader.hlsl&quot;).c_str(), nullptr, nullptr, &quot;main&quot;, &quot;cs_5_0&quot;, compileFlags, 0, &amp;computeShader_m, &amp;error_ptr));&#xD;&#xA;    &#xD;&#xA;    if (error_ptr)&#xD;&#xA;    {&#xD;&#xA;    	OutputDebugStringA((char *)error_ptr-&gt;GetBufferPointer());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there somthing amiss?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13017" PostHistoryTypeId="5" PostId="1598" RevisionGUID="1c917a6d-bce4-4ac1-94bb-238a348891a7" CreationDate="2017-04-12T07:32:01.480" UserId="-1" Comment="replaced http://programmers.stackexchange.com/ with https://softwareengineering.stackexchange.com/" Text="Google said how in 2012, avoiding explaining too many details&#xD;&#xA;&#xD;&#xA;[The never-ending quest for the perfect map][1]&#xD;&#xA;&#xD;&#xA;&gt; ...new imagery rendering techniques and computer vision that let us&#xD;&#xA;&gt; automatically create 3D cityscapes, complete with buildings, terrain&#xD;&#xA;&gt; and even landscaping, from 45-degree aerial imagery&#xD;&#xA;&#xD;&#xA;and here it's a [video][2] of the feature.&#xD;&#xA;&#xD;&#xA;So we know that &quot;Computer Vision&quot; is used. I guess the edges are detected, along with the shadows, to build the elevation of the object. Then the segmented image is used as a texture on the built mesh.&#xD;&#xA;&#xD;&#xA;However, i saw [this paper][3] linked, and i think a similar technique is used in Google to extract the 3d mesh from different 45° images.&#xD;&#xA;&#xD;&#xA;There are a lot of papers (a book too) about &quot;building extraction/detection&quot;.&#xD;&#xA;&#xD;&#xA;- [Detection of buildings in urban and suburban areas using very high resolution satellite][4]&#xD;&#xA;- [Google Scholar: Building Detection][5]&#xD;&#xA;- [Google Scholar: Building Detection from Satellite Images][6]&#xD;&#xA;&#xD;&#xA;src: [How does the new google maps make buildings and cityscapes 3D?][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://googleblog.blogspot.it/2012/06/never-ending-quest-for-perfect-map.html&#xD;&#xA;  [2]: https://www.youtube.com/watch?t=44&amp;v=N6Douyfa7l8&#xD;&#xA;  [3]: http://iris.usc.edu/outlines/papers/1998/lin-cviu98.pdf&#xD;&#xA;  [4]: http://www.asprs.org/a/publications/proceedings/Louisville2014/Jabari_1.pdf&#xD;&#xA;  [5]: https://scholar.google.it/scholar?q=Building+Detection&#xD;&#xA;  [6]: https://scholar.google.it/scholar?q=Building%20Detection%20from%20Satellite%20Images&amp;btnG=&amp;hl=en&amp;as_sdt=0%2C5&amp;as_vis=1&#xD;&#xA;  [7]: https://softwareengineering.stackexchange.com/questions/202599/how-does-the-new-google-maps-make-buildings-and-cityscapes-3d" ContentLicense="CC BY-SA 3.0" />
  <row Id="13018" PostHistoryTypeId="5" PostId="3700" RevisionGUID="ea87ade5-73a1-42ec-afe9-ee67752d7e36" CreationDate="2017-04-12T07:32:01.480" UserId="-1" Comment="replaced http://programmers.stackexchange.com/ with https://softwareengineering.stackexchange.com/" Text="So i was reading [this][1], so i sort of got the reason why there are a lot more games on Microsoft windows than on any other OS. The main issue presented was that Direct3D is preferred over OpenGL. &#xD;&#xA;&#xD;&#xA;What i don't understand why would any developer sacrifice compatibility ? , that is simply a financial loss to the company. I understand that OpenGL is kind of mess, but that should hardly be a issue for experts. Even if it is, i think that people would go a extra mile than to incur a financial loss. &#xD;&#xA;&#xD;&#xA;Also if i not wrong then many cross platform applications use both Direct3D and OpenGL. I think they switch between the APIs.     &#xD;&#xA;&#xD;&#xA;This is weird as they can just use OpenGL, why even care about Direct3D ? &#xD;&#xA;&#xD;&#xA;So the question is , are there any technical issues with OpenGL ? or is there any support that that Direct3D provide that OpenGL lacks ?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;i am aware that this question might be closed as being off-topic or too broad, i tried my best to narrow it down.    &#xD;&#xA;&#xD;&#xA;  [1]: https://softwareengineering.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13019" PostHistoryTypeId="5" PostId="3702" RevisionGUID="1881a3c6-9d20-46af-8430-fc0e05b082ab" CreationDate="2017-04-12T07:32:01.480" UserId="-1" Comment="replaced http://programmers.stackexchange.com/ with https://softwareengineering.stackexchange.com/" Text="About the fact that there are more games for Windows, some reasons are&#xD;&#xA;&#xD;&#xA; 1. Windows has the majority of the market and in the past to develop cross platform games was more complicated than it is today.&#xD;&#xA; 2. DirectX comes with way better tools for developing (e.g. debugging)&#xD;&#xA; 3. Big innovations are generally first created/implemented in DirectX, and then ported to/implemented in OpenGL. &#xD;&#xA; 4. As for Windows vs Linux, you have to consider that when there is an actual standard due to marketing and historical reasons (for that see https://softwareengineering.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows, as I said in the comments), it has its inertia.&#xD;&#xA;&#xD;&#xA;The inertia thing is very important. If your team develop for DirectX, targeting 90% of the market (well... if you play games on pc you probaly have windows, so... 99% of the market?), why would you want to invest in OpenGL? If you already develop in OpenGL, again targeting 99% of the market, you will stick to it as long as you can. For exampe Id Tech by Id Software is an excellent game engine (powering the DOOM series) that uses OpenGL.&#xD;&#xA;&#xD;&#xA;**About the topic of your discussion, a comment.**&#xD;&#xA;&#xD;&#xA;As of today, there are many many APIs, and a common practice is to use a Game Engine that abstracts over them. For example, consider that&#xD;&#xA; &#xD;&#xA; - On most mobile platform you have to use OpenGl ES.&#xD;&#xA; - On PC you can use both DirectX and OpenGL&#xD;&#xA; - I think on XBOX you have to use DirectX.&#xD;&#xA; - I think that on PS you use their own API. &#xD;&#xA; - With old hardware you use DirectX9 or OpenGL 3, or OpenGL ES 2.&#xD;&#xA; - With more recent hardware you can (and want to) use DirectX 11, OpenGL 4, OpenGL ES 3.&#xD;&#xA;  &#xD;&#xA;Recently, with the advent of the new low overhead APIs - whch is a major turning point for graphical programming - there are DirectX 12 for Windows and XBOX, Metal for iOS and Vulkan (the new OpenGL) for Windows and Linux (including Android and Tizen).&#xD;&#xA;&#xD;&#xA;There still are games that only target Windows and XBOX, but IMHO today that can only be marketing choice.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13020" PostHistoryTypeId="10" PostId="4989" RevisionGUID="fc1436c3-3aa3-4432-a004-e5b97da7b413" CreationDate="2017-04-12T08:55:03.440" UserId="2041" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[4991],&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="13022" PostHistoryTypeId="5" PostId="4988" RevisionGUID="c9812510-856d-401e-9286-940fcffc342c" CreationDate="2017-04-12T11:28:55.877" UserId="231" Comment="Typo plus code formatting for ease of reading. Please reverse anything which does not match your intention" Text="This implementation represents the water as a regular height field grid. The function parameters `m` and `n` are the dimensions of the grid, `dx` is the regular distance between the water vertices, `dt` is the time step, `speed` is the speed of the movement and `damping` is a constant to ease disturbance as the water flows from the disturbance center." ContentLicense="CC BY-SA 3.0" />
  <row Id="13023" PostHistoryTypeId="2" PostId="4992" RevisionGUID="9896b176-3fec-4710-8c43-59750de4a8a2" CreationDate="2017-04-12T14:33:20.173" UserId="1952" Text="$E_n$ is illuminance (or irradiance), $L_i$ is luminance (or radiance) in direction $\omega_i$ and $d\omega$ is differential solid angle.&#xD;&#xA;&#xD;&#xA;**TL;DR**: $d\omega_i$ is the area of a pixel in the cubemap projected onto the unit sphere.&#xD;&#xA;&#xD;&#xA;And then a longer explanation (:&#xD;&#xA;&#xD;&#xA;Solid angle is essentially the projected area of an object on a unit sphere and has unit of steradians (sr). Entire unit sphere has surface area of $4\pi$ and hemisphere has the area of $2\pi$, which comes up a lot in lighting calculations due to integrals over spheres and hemispheres respectively.&#xD;&#xA;&#xD;&#xA;If you would want to calculate solid angle for an object and point $p$, you would project the object on the unit sphere at $p$ and calculate the area of the projection. Further the object is from $p$ smaller the solid angle gets. As an example, we can calculate solid angle for Sun as seen from the Earth. We know that Sun has about 0.52 degrees [subtended angle][1] from Earth, so we can calculate that the solid angle is:&#xD;&#xA;$$2\pi*(1-Cos(0.52/2))\simeq0.00006469sr$$&#xD;&#xA;&#xD;&#xA;So the differential solid angle is just an infinitesimally small solid angle. If you would numerically integrate over a sphere ($4\pi$ steradians) by taking $N$ uniform samples on the sphere, your $d\omega$ would be $4\pi/N$. With integrals $N$ goes to infinity, while with numerical approximation of the integral $N$ is some &quot;sufficiently large&quot; number.&#xD;&#xA;&#xD;&#xA;However, in this paper you refer to they perform integration by rendering to a cubemap at $p$ and then iterating through all the rendered pixels. But because these pixels are rendered onto planes (cubemap faces), their projection on the unit sphere isn't constant, so $d\omega$ needs to be weighted by the position in the rendered image, which they explain in your second quote:&#xD;&#xA;&#xD;&#xA;&gt; Computing the solid angle dωi subtended by a particular texel is a&#xD;&#xA;&gt; little more involved. Texels near the center of the texture subtend a&#xD;&#xA;&gt; somewhat larger angle, while texels near the corner take up a smaller&#xD;&#xA;&gt; solid angle when we map the cube texture onto a sphere.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://er.jsc.nasa.gov/seh/math30.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="13024" PostHistoryTypeId="2" PostId="4993" RevisionGUID="9d6ee11f-8434-4ee9-8f15-302f53110c5e" CreationDate="2017-04-12T17:08:08.050" UserId="1952" Text="If you have a 1D function $f(x)$ and you want to integrate this function from say 0 to 1, one way to perform this integration is by taking N random samples in range [0, 1], evaluate $f(x)$ for each sample and calculate the average of the samples. However, this &quot;naive&quot; Monte Carlo integration is said to &quot;converge slowly&quot;, i.e. you need a large number of samples to get close to the ground truth, particularly if the function has high frequencies.&#xD;&#xA;&#xD;&#xA;With importance sampling, instead of taking N random samples in [0, 1] range, you take more samples in the &quot;important&quot; regions of $f(x)$ that contribute most to the final result. However, because you bias sampling towards the important regions of the function, these samples must be weighted less to counter the bias, which is where the PDF (probability density function) comes along. PDF tells the probability of a sample at given position and is used to calculate weighted average of the samples by dividing the each sample with the PDF value at each sample position.&#xD;&#xA;&#xD;&#xA;With Cook-Torrance importance sampling the common practice is to distribute samples based on the normal distribution function NDF. If NDF is already normalized, it can serve directly as PDF, which is convenient since it cancels the term out from the BRDF evaluation. Only thing you need to do then is to distribute sample positions based on PDF and evaluate BRDF without the NDF term, i.e.&#xD;&#xA;$$f=\frac{FG}{\pi(n\cdot\omega_i)(n\cdot\omega_o)}$$&#xD;&#xA;And calculate average of the sample results multiplied by the solid angle of the domain you integrate over (e.g. $2\pi$ for hemisphere).&#xD;&#xA;&#xD;&#xA;For NDF you need to calculate [Cumulative Distribution Function][1] of the PDF to convert uniformly distributed sample position to PDF weighted sample position. For isotropic NDF this simplifies to 1D function because of the symmetry of the function. For more details about the CDF derivation you can check [this old GPU Gems article][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cumulative_distribution_function&#xD;&#xA;  [2]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="13026" PostHistoryTypeId="2" PostId="4994" RevisionGUID="c4ca7983-0ca3-44d8-8fbe-16ae66eb93e7" CreationDate="2017-04-12T22:48:41.963" UserId="310" Text="Short answer:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;**Importance sampling** is a method to reduce variance in Monte Carlo Integration by choosing an estimator close to the shape of the actual function.&#xD;&#xA;&#xD;&#xA;**PDF** is an abbreviation for [Probability Density Function][1]. A $pdf(x)$ gives the probability of a random sample generated being $x$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Long Answer:&#xD;&#xA;=====&#xD;&#xA;&#xD;&#xA;To start, let's review what Monte Carlo Integration is, and what it looks like mathematically. &#xD;&#xA;&#xD;&#xA;Monte Carlo Integration is an technique to estimate the value of an integral. It's typically used when there isn't a closed form solution to the integral. It looks like this:&#xD;&#xA;&#xD;&#xA;$$\int f(x) \, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;In english, this says that you can approximate an integral by averaging successive random samples from the function. As $N$ gets large, the approximation gets closer and closer to the solution. $pdf(x_{i})$ represents the probability density function of each random sample.&#xD;&#xA;&#xD;&#xA;Let's do an example: Calculate the value of the integral $I$.&#xD;&#xA;&#xD;&#xA;$$I = \int_{0}^{2\pi} e^{-x} \sin(x) dx$$&#xD;&#xA;&#xD;&#xA;Let's use Monte Carlo Integration:&#xD;&#xA;&#xD;&#xA;$$I \approx \frac{1}{N} \sum_{i=1}^N \frac{e^{-x} \sin(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;A simple python program to calculate this is:&#xD;&#xA;&#xD;&#xA;    import random&#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    N = 200000&#xD;&#xA;    TwoPi = 2.0 * math.pi&#xD;&#xA;&#xD;&#xA;    sum = 0.0&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;        x = random.uniform(0, TwoPi)&#xD;&#xA;        &#xD;&#xA;        fx = math.exp(-x) * math.sin(x)&#xD;&#xA;        pdf = 1 / (TwoPi - 0.0)&#xD;&#xA;        &#xD;&#xA;        sum += fx / pdf&#xD;&#xA;&#xD;&#xA;    I = (1 / N) * sum&#xD;&#xA;    print(I)&#xD;&#xA;&#xD;&#xA;If we run the program we get $I = 0.4986941$&#xD;&#xA;&#xD;&#xA;Using separation by parts, we can get the exact solution:&#xD;&#xA;&#xD;&#xA;$$I = \frac{1}{2} (1 − e−2π) = 0.4990663$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You'll notice that the Monte Carlo Solution is not quite correct. This is because it is an estimate. That said, as $N$ goes to infinity, the estimate should get closer and closer to the correct answer. Already at $N = 2000$ some runs are almost identical to the correct answer.&#xD;&#xA;&#xD;&#xA;A note about the PDF: In this simple example, we always take a uniform random sample. A uniform random sample means every sample has the exact same probability of being chosen. We sample in the range $[0, 2\pi]$ so, $pdf(x) = 1 / (2\pi - 0)$&#xD;&#xA;&#xD;&#xA;Importance sampling works by *not* uniformly sampling. Instead we try to choose more samples that contribute a lot to the result (important), and less samples that only contribute a little to the result (less important). Hence the name, importance sampling.&#xD;&#xA;&#xD;&#xA;If you choose a sampling function whose pdf very closely matches the shape of $f$, you can greatly reduce the variance, which means you can take less samples. However, if you choose a sampling function whose value is very different from $f$, you can ***increase*** the variance. See the picture below:&#xD;&#xA;[![Comparison of good sampling vs bad sampling][2]][2]&#xD;&#xA;Image from Wojciech Jarosz's [Dissertation Appendix A][3]&#xD;&#xA;&#xD;&#xA;One example of importance sampling in Path Tracing is how to choose the direction of a ray when after it hits a surface. If the surface is not perfectly specular (ie. a mirror or glass), the outgoing ray can be anywhere in the hemisphere.&#xD;&#xA;&#xD;&#xA;[![Outgoing rays can go anywhere in the hemisphere][4]][4]&#xD;&#xA;&#xD;&#xA;We ***could*** uniformly sample the hemisphere to generate the new ray. However, if we're using a BRDF, for example, Lambert, we know that any rays at the horizon will be heavily attenuated (specifically, $\cos(x)$ ). So, rays generated near the horizon will not contribute very much to the final value.&#xD;&#xA;&#xD;&#xA;To combat this, we use importance sampling. If we generate rays according to a cosine weighted hemisphere, we ensure that more rays are generated well above the horizon, and less near the horizon. This will lower variance and reduce noise.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGyXh.png&#xD;&#xA;  [3]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/appendixA.pdf&#xD;&#xA;  [4]: https://i.stack.imgur.com/6crnH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13029" PostHistoryTypeId="2" PostId="4995" RevisionGUID="6b49add1-7ffb-4e7f-bc5c-baae91a60278" CreationDate="2017-04-13T03:43:49.593" UserId="6435" Text="I am trying to implement a shape matching algorithm for vector images discussed in a paper.&#xD;&#xA;&#xD;&#xA;The input to the algorithm is a model of 2D shapes deﬁned by contour segments. According to the paper, such segments can be deﬁned as polylines, obtained for example by vectorizing the output of an edge detector like Canny.&#xD;&#xA;&#xD;&#xA;I am trying to vectorize a tiff image using Inkscape's bitmap tracing feature. The svg image I got from it has a path node with many attribute values, but that is not what the algorithm wants:&#xD;&#xA;&#xD;&#xA;[![output of canny edge detector][2]][2] [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Is there a image tracer that vectorizes an image using polylines?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/SVWx7.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7f7RQ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13030" PostHistoryTypeId="1" PostId="4995" RevisionGUID="6b49add1-7ffb-4e7f-bc5c-baae91a60278" CreationDate="2017-04-13T03:43:49.593" UserId="6435" Text="Vectorizer that provides polylines instead of paths" ContentLicense="CC BY-SA 3.0" />
  <row Id="13031" PostHistoryTypeId="3" PostId="4995" RevisionGUID="6b49add1-7ffb-4e7f-bc5c-baae91a60278" CreationDate="2017-04-13T03:43:49.593" UserId="6435" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13036" PostHistoryTypeId="5" PostId="163" RevisionGUID="7b1c1112-6a39-44df-8942-e485510ace0e" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="### TL;DR&#xD;&#xA;&#xD;&#xA;They belong to the same family of solvers, where sphere tracing is one method of ray marching, which is the family name.&#xD;&#xA;&#xD;&#xA;###Raymarching a definition&#xD;&#xA;&#xD;&#xA;Raymarching is a technique a bit like traditional raytracing where the surface function is not easy to solve (or impossible without numeric iterative methods). In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xD;&#xA;&#xD;&#xA;This can be useful if you:&#xD;&#xA;&#xD;&#xA;* Need to render volumetrics that arenot uniform&#xD;&#xA;* Rendering implicit functions, fractals&#xD;&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xD;&#xA;* Etc&#xD;&#xA;&#xD;&#xA;![Traditional raymarching][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Traditional ray marching for surface finding&#xD;&#xA;&#xD;&#xA;Related posts:&#xD;&#xA;&#xD;&#xA;* [how-do-raymarch-shaders-work](https://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Sphere tracing &#xD;&#xA;&#xD;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xD;&#xA;&#xD;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xD;&#xA;&#xD;&#xA;    F(X,Y,Z) = 0&#xD;&#xA;&#xD;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xD;&#xA;&#xD;&#xA;![Sphere tracing has a adaptive step size][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Sphere tracing\* in action note how the step size is adaptive&#xD;&#xA;&#xD;&#xA;For more info see: &#xD;&#xA;&#xD;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bc4D5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;&#xD;&#xA;\* Perhaps in 2d it's should be called circle tracing :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13037" PostHistoryTypeId="5" PostId="224" RevisionGUID="05a69533-e3d6-4099-a0a4-a2b50a2f37ed" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="For rendering of gases, I think the usual approach is to simply render each particle as a tiny disc. Gases don't really coalesce into surfaces like liquids do, so this should produce acceptable results. You could perhaps apply a light blur over the gas layer afterwards to soften it and hide the fact that it is made of discrete elements.&#xD;&#xA;&#xD;&#xA;Liquids, on the other hand, tend to coalesce together to form droplets and smooth surfaces, so you need to derive a surface from the particles somehow. One way to do this is to use [Metaballs][1], which also display this behavior and can be tweaked to suit different liquids and particle densities. By interpreting each particle as a metaball, you will have an implicit equation representing your liquid surface. To render this implicit surface you can then use an algorithm like [Marching Tetrahedra][2] to convert it to triangles, or utilize [Ray Marching][3] to directly render it. (Ray marching can be easily done in realtime in a fragment shader these days.) You can also use this approach for gases if you want a somewhat softer look.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Metaballs&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Marching_tetrahedra&#xD;&#xA;  [3]: https://gamedev.stackexchange.com/a/67745/5337" ContentLicense="CC BY-SA 3.0" />
  <row Id="13038" PostHistoryTypeId="5" PostId="1692" RevisionGUID="d77bf7e8-46fc-4b27-b1ca-3784915272c9" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="This a follow up for a question I answered on GameDev SE. The question was simply [Is glDrawArraysInstanced in OpenGL parallel when drawing those instances?][1]&#xD;&#xA;&#xD;&#xA;My answer was in the lines of &quot;the GPU might execute multiple draw calls in parallel depending on multiple things, for instance if two draw calls use the same vertex shaders.&quot; [Here is the full answer][2].&#xD;&#xA;&#xD;&#xA;In the comments the OP mentioned, &quot;I think it should be sequential. After all, some of blending mode depends of sequence&quot;&#xD;&#xA;&#xD;&#xA;Now, I am little bit confused. Is my answer of *it will still parallelize them when it can* valid? Can someone clarify this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/questions/110781/is-gldrawarraysinstanced-in-opengl-parallel-when-drawing-those-instances&#xD;&#xA;  [2]: https://gamedev.stackexchange.com/questions/110781/is-gldrawarraysinstanced-in-opengl-parallel-when-drawing-those-instances/110806#110806" ContentLicense="CC BY-SA 3.0" />
  <row Id="13039" PostHistoryTypeId="5" PostId="1867" RevisionGUID="2a7a0282-f195-417c-bb36-9cc875492bc7" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="This is achieved via **[Barycentric][1] Interpolation**.&#xD;&#xA;&#xD;&#xA;First, we find the barycentric coordinates of $P$. Barycentric coordinates represent how much weight each vertex contributes to the point, and can be used to interpolate any value which is known at the vertices across the face of a triangle.&#xD;&#xA;&#xD;&#xA;Consider the 3 inner triangles $ABP$, $PBC$ and $PCA$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We can say that the barycentric coordinate, or weight of the vertex $A$ on the point $P$ is proportional to the ratio of the area of inner triangle $PBC$ to the area of the whole triangle $ABC$.&#xD;&#xA;&#xD;&#xA;This is intuitively evident if we consider that as $P$ approaches $A$ the triangle $PBC$ grows larger and the other two become smaller. &#xD;&#xA;&#xD;&#xA;Also intuitively evident should be that the sum of the barycentric coordinates of a point **inside a triangle** always equals $1$. So, it is enough to find only two of the coordinates to derive the 3rd.&#xD;&#xA;&#xD;&#xA;The method for computing the barycentric coordinates is:&#xD;&#xA;&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;{Bary}_A &amp;= \frac{(B_y-C_y)(P_x-C_x) + (C_x-B_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_B &amp;= \frac{(C_y-A_y)(P_x-C_x) + (A_x-C_x)(P_y-C_y)}{(B_y-C_y)(A_x-C_x) + (C_x-B_x)(A_y-C_y)}\\&#xD;&#xA;{Bary}_C &amp;= 1 - {Bary}_A - {Bary}_B&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The derivation and reasoning is explained in the [wikipedia article][1].&#xD;&#xA;&#xD;&#xA;Once you have coordinates, you can determine the texture coordinates of $P$ by interpolating the values at the vertices using the barycentric coordinates as weights:&#xD;&#xA;&#xD;&#xA;$$P_{uv} = {Bary}_A \cdot A_{uv} + {Bary}_B \cdot B_{uv} + {Bary}_C \cdot C_{uv}$$&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;The reasoning is also explained very nicely in [this][3] presentation.&#xD;&#xA;&#xD;&#xA;Also see [this question][4] for efficient methods of computation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ob83U.jpg&#xD;&#xA;  [3]: https://classes.soe.ucsc.edu/cmps160/Fall10/resources/barycentricInterpolation.pdf&#xD;&#xA;  [4]: https://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="13040" PostHistoryTypeId="5" PostId="2347" RevisionGUID="42bc6323-7df8-4e4d-b17a-607f6ccabb3f" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="Another code review question.&#xD;&#xA;&#xD;&#xA;I am trying to draw an arrow to represent a vector. I have started with an unit arrow with vertices defined as follows:&#xD;&#xA;&#xD;&#xA;    //vertex data for vector with arrow    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;		//line&#xD;&#xA;		0.0f, 0.0f, 0.0f,&#xD;&#xA;		1.0f, 0.0f, 0.0f,&#xD;&#xA;&#xD;&#xA;		//arrow bases&#xD;&#xA;		0.95f, 0.01f, 0.0f,&#xD;&#xA;		0.95f,-0.01f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    GLuint indices[] = {&#xD;&#xA;		0, 1,		// Line&#xD;&#xA;		1, 2, 3    // Arrow Triangle&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I have another array that contains the actual vector start and end positions:&#xD;&#xA;&#xD;&#xA;    GLfloat lineVertices[] = {&#xD;&#xA;						&#xD;&#xA;		1.0f, 2.0f, 3.0f, //v1 start&#xD;&#xA;		3.0f, 5.0f,-5.0f, //v1 end&#xD;&#xA;&#xD;&#xA;	   -1.0f,-1.0f,-1.0f, //v2 start&#xD;&#xA;	   -3.0f, 5.0f,-10.0f //v2 end&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am trying to construct the `model` matrix to apply the transformation from `lineVertices` for each vectors on the unit arrow.&#xD;&#xA;&#xD;&#xA;    //'view', and 'projection' matrix is set out side of the loop&#xD;&#xA;	for (GLint i = 0; i &lt; sizeof(lineVertices) / sizeof(GLfloat); i += 6)&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 model;&#xD;&#xA;&#xD;&#xA;		//apply transformation&#xD;&#xA;		glm::vec3 start(lineVertices[i], lineVertices[i + 1], lineVertices[i + 2]);&#xD;&#xA;		glm::vec3 end(lineVertices[i + 3], lineVertices[i + 4], lineVertices[i + 5]);&#xD;&#xA;		glm::vec3 startToEnd = end - start;&#xD;&#xA;		GLfloat length = glm::length(startToEnd);&#xD;&#xA;&#xD;&#xA;        //translate&#xD;&#xA;		model = glm::translate(model, start);&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		//GLfloat xyAngle = glm::atan(startToEnd.z, length);&#xD;&#xA;		//GLfloat xzAngle = glm::atan(startToEnd.y, length);&#xD;&#xA;		//GLfloat yzAngle = glm::atan(startToEnd.x, length);&#xD;&#xA;&#xD;&#xA;		//model = glm::rotate(model, xyAngle, glm::vec3(1.0f, 1.0f, 0.0f));&#xD;&#xA;		//model = glm::rotate(model, xzAngle, glm::vec3(1.0f, 0.0f, 1.0f));&#xD;&#xA;		//model = glm::rotate(model, yzAngle, glm::vec3(0.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		GLfloat angleWithZ = glm::acos(startToEnd.z/length);&#xD;&#xA;		GLfloat angleWithY = glm::acos(startToEnd.y/length);&#xD;&#xA;		GLfloat angleWithX = glm::acos(startToEnd.x/length);&#xD;&#xA;&#xD;&#xA;		model = glm::rotate(model, angleWithX, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithY, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithZ, glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;		//scale&#xD;&#xA;		model = glm::scale(model, glm::vec3(length));&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			&#xD;&#xA;		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Though this seems to work, as I can see all those arrows, however, I am not sure whether this is the right implementation or not. Please let me know, if this is correct and/or there is room for improvement, or there are easier ways to achieve this, and so on.&#xD;&#xA;&#xD;&#xA;**Edit:** updated my code sample (only the rotation part) based on [Direction cosine (wikipedia)][1]. Old code is still kept commented. &#xD;&#xA;&#xD;&#xA;P.S.: this implementation is based on following stack exchange discussions: [1][2], [2][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Direction_cosine&#xD;&#xA;  [2]: https://gamedev.stackexchange.com/a/96960/82355&#xD;&#xA;  [3]: http://math.stackexchange.com/a/799812/298948" ContentLicense="CC BY-SA 3.0" />
  <row Id="13041" PostHistoryTypeId="5" PostId="3581" RevisionGUID="4d94b0b2-c3d1-44d9-a6bc-af3984dc4cc9" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="You should be learning OpenGL first, as that is the standard for Graphics, across so many platforms.&#xD;&#xA;&#xD;&#xA;Even if there is a newer library, understanding the basics, and working with a language that is used all over the industry, is very important... Especially since Vulkan wont be used in Big Companies for awhile, since.&#xD;&#xA;&#xD;&#xA;1.  No one wants to adapt right away and end up screwing themselves over with a non-stable Framework/Library.&#xD;&#xA;&#xD;&#xA;2.  They would need to hire / re-train their current Open-GL programmers, and there is no need to.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;------------------------------&#xD;&#xA;&#xD;&#xA;Also, I've heard that OpenGL, and Vulkan, aren't exactly the same.  I hear Vulkan is a lower level API, and closer to machine code, than OpenGL.&#xD;&#xA;&#xD;&#xA;This answer I just found seems to have a lot of great info&#xD;&#xA;&#xD;&#xA;https://gamedev.stackexchange.com/questions/96014/what-is-vulkan-and-how-does-it-differ-from-opengl&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------------------&#xD;&#xA;&#xD;&#xA;Another thing that is something to consider is the issue that happened back with OpenGL 1.&#xD;&#xA;&#xD;&#xA;OpenGL 1 to OpenGL 2 had MAJOR changes, and since many people were using OpenGL1, and hardware supported it, there is heavy backwards compatibility needed to be implemented in some applications/engines, and that sometimes is really painful for the devs to keep supporting it.&#xD;&#xA;&#xD;&#xA;Besides the support, the language shifted so much, that you had to learn new stuff.&#xD;&#xA;&#xD;&#xA;This has happened with frameworks such as JavaFX (from 1.x to 2.x) and Play! Framework (Also 1.x to 2.x).  Complete changes to the framework, meaning we have to relearn... everything...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;--------------------------------------&#xD;&#xA;&#xD;&#xA;So essentially what you should do is wait until Vulkan is STABLE.  That means wait until Probably the 2.0 patch.  IT doesn't mean you cannot learn about the basics of Vulkan, but just know this might change.  I would assume that a group like Kronos would provide a very stable API from the start, especially since there are multiple Nvidia and AMD engineers working on Vulkan, including a high up Nvidia person overseeing the project apparently, as well as The base of Mantle; however, like any software, we the coders will see how well it works from the start, but many are wary and waiting to see what happens.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13042" PostHistoryTypeId="5" PostId="3673" RevisionGUID="86f20b52-e1dc-442d-8f0e-72e421f720b0" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="1) Drawing a bunch of 3d cubes with simple textures? Yes, SceneKit can do that.  &#xD;&#xA;&#xD;&#xA;2) Way too broad a question... try [reading the docs.](https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/)&#xD;&#xA;&#xD;&#xA;3) Since this is a platform specific question try the **scenekit** and **scene-kit** tags on [stackOverflow](http://stackoverflow.com/) and [Game Development](https://gamedev.stackexchange.com/), but see answer 2 first.&#xD;&#xA;&#xD;&#xA;good luck!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13043" PostHistoryTypeId="5" PostId="4212" RevisionGUID="d796fbfc-2ff4-4b8e-9971-b9841d105cd8" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="I just tried using [this approach][1] to create a tiling 2d simplex noise function with [Gustavson's java implementation][2]. The result tiled, but the texture seemed muddy / washed out. &#xD;&#xA;&#xD;&#xA;I decided to compare the result of using the 2d, 3d &amp; 4d versions to make a 2d texture by holding any 'extra' dimension parameters at zero. The 4d output looked the same as my tiled 2d output. Furthermore, I noticed a trend: as the dimensions increase, the noise starts to drift away from the min &amp; max toward the average. Here are the results along with their histograms:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] [![enter image description here][4]][4] [![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I ran across [this post][6] discussing some artifacts in Gustavson's implementation &amp; wondered if that might be contributing to the problem, so I tried using [OpenSimplex noise][7] instead &amp; got very similar results.&#xD;&#xA;&#xD;&#xA;What's going on here? I'd like to use the 4d simplex noise to make a tiling 2d texture that looks more like the &#xD;&#xA;regular 2d simplex noise. If necessary I can try to massage the output, but that seems like hack &amp; I'd rather &#xD;&#xA;treat the problem rather than the symptoms if possible.&#xD;&#xA;&#xD;&#xA;Again, just to clarify, I'm asking: why does the dimensionality seem to affect the final 2D as illustrated?&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/questions/23625/how-do-you-generate-tileable-perlin-noise/23639#23639&#xD;&#xA;  [2]: http://staffwww.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java&#xD;&#xA;  [3]: https://i.stack.imgur.com/qOF9n.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/D2JD7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/St0Ha.png&#xD;&#xA;  [6]: https://stackoverflow.com/questions/18885440/why-does-simplex-noise-seem-to-have-more-artifacts-than-classic-perlin-noise&#xD;&#xA;  [7]: https://gist.github.com/KdotJPG/b1270127455a94ac5d19" ContentLicense="CC BY-SA 3.0" />
  <row Id="13044" PostHistoryTypeId="5" PostId="4363" RevisionGUID="1c47bb3d-7f65-41df-a6d7-849dd84249da" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="I am trying to implement [Blades of Waving Grass][1] and I am still stuck at the point where I need to achieve texture arrangements like in the figure below (the first one).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So my plan is to draw the first texture, then draw the second and rotate it by 30°, then another and rotate it by 60° etc. Drawing the first texture is not a problem but I have some issues rotating the second one. I would expect it to look something like this (view from above):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Instead the actual result looks something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I suspect that this deviation occurs due to the object being rotated around the world-space axes and not around its own.&#xD;&#xA;&#xD;&#xA;Vertex and position data:&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    	-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;    	0.5f, -0.5f, -0.5f, 1.0f, 0.0f,&#xD;&#xA;    	0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;    	0.5f, 0.5f, -0.5f, 1.0f, 1.0f,&#xD;&#xA;    	-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,&#xD;&#xA;    	-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    glm::vec3 texturePositions[] = {&#xD;&#xA;    	glm::vec3(0.0f, 0.0f, 0.0f),&#xD;&#xA;        glm::vec3(0.0f, 0.0f, 0.0f)&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Camera/View transformations:&#xD;&#xA;&#xD;&#xA;		// Camera/View transformation&#xD;&#xA;		glm::mat4 view;&#xD;&#xA;		view = camera.GetViewMatrix();&#xD;&#xA;		// Projection&#xD;&#xA;		glm::mat4 projection;&#xD;&#xA;		projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 1000.0f);&#xD;&#xA;		// Get the uniform locations&#xD;&#xA;		GLint modelLoc = glGetUniformLocation(ourShader.Program, &quot;model&quot;);&#xD;&#xA;		GLint viewLoc = glGetUniformLocation(ourShader.Program, &quot;view&quot;);&#xD;&#xA;		GLint projectionLoc = glGetUniformLocation(ourShader.Program, &quot;projection&quot;);&#xD;&#xA;		// Pass the matrices to the shader&#xD;&#xA;		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));&#xD;&#xA;		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;&#xD;&#xA;Drawing the first two textures:&#xD;&#xA;&#xD;&#xA;			//Texture 1&#xD;&#xA;			glm::mat4 model;&#xD;&#xA;			model = glm::translate(model, texturePositions[0]);			&#xD;&#xA;			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;			//Texture 2&#xD;&#xA;			GLfloat angle = glm::radians(30.0f);&#xD;&#xA;			model = glm::translate(model, texturePositions[1]);&#xD;&#xA;			model = glm::rotate(model, angle, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;			glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;Online search showed that this might have several reasons:&#xD;&#xA;&#xD;&#xA; 1. Order of the applied transformations are crucial&#xD;&#xA; 2. One solution might be to first move the &quot;object&quot; until its center&#xD;&#xA;    matches the world-space origin, apply the rotation and then move it&#xD;&#xA;    to the desired position.&#xD;&#xA;&#xD;&#xA;As I am still in the very early learning process so I am kind of clueless here.&#xD;&#xA;&#xD;&#xA; 1. I think that the order of transformations for the second texture is fine in my code, isn't it?&#xD;&#xA; 2. Also how would I determine the right position for the object where&#xD;&#xA;    the rotation would be applied correctly? (see above point 2)&#xD;&#xA; 3. Might it be more efficient to apply the rotation in the objects&#xD;&#xA;    local space? Is that possible in my case?&#xD;&#xA;&#xD;&#xA;I do not expect anybody to write code for me (though some snippet would be nice) but I would appreciate some hints or somebody pointing me in the right direction. I think that I have a basic fallacy here.&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA; 1. If I change the rotation axis from `y` to `z` the object rotates&#xD;&#xA;    around its own center just like expected.&#xD;&#xA; 2. I also tried to apply the following solutions (taken from [here][5]&#xD;&#xA;    and [here][6]) where I moved the object to `glm::vec3(-x,-y,-z)`&#xD;&#xA;    rotate it and then moving it back to `glm::vec3(x,y,z)`,&#xD;&#xA;    unfortunately with no success. Which makes sence as the position&#xD;&#xA;    vector is set to (0,0,0) anyway. I also tried to change thisposition&#xD;&#xA;    to something else than the origin also with no success.&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems/gpugems_ch07.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/QVbKy.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/7xhvk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7qQrc.png&#xD;&#xA;  [5]: https://gamedev.stackexchange.com/questions/18854/rotating-an-object-in-opengl-about-its-centre&#xD;&#xA;  [6]: https://www.opengl.org/discussion_boards/showthread.php/169200-Rotating-an-Object-around-its-center" ContentLicense="CC BY-SA 3.0" />
  <row Id="13045" PostHistoryTypeId="5" PostId="4607" RevisionGUID="be2a5d66-dfae-40cd-8e6c-1a70b5096c9c" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="Here's a very speedy 10 line maths fix for converting mesh to voxels... forget rays, dot products, square roots etc, edges, intersections do this:&#xD;&#xA;https://gamedev.stackexchange.com/questions/136243/how-can-i-randomly-pick-points-on-a-triangle/136250#136250" ContentLicense="CC BY-SA 3.0" />
  <row Id="13047" PostHistoryTypeId="5" PostId="4974" RevisionGUID="cddc7d32-afec-4a75-a2d1-c25f7ad5c36a" CreationDate="2017-04-13T12:18:54.697" UserId="-1" Comment="replaced http://gamedev.stackexchange.com/ with https://gamedev.stackexchange.com/" Text="At one point I had a similiar issue, however, I was using DirectX as opposed to OpenGL so this may not be very helpful but you might be able to gain some knowledge out of this.&#xD;&#xA;&#xD;&#xA;My main objective was to create a level editor with basic functionality such as importing models and postioning. I wanted to use C# and WinForms rather than having to learn another entire framework like Qt. I made my engine available as a DLL and exposed a C-style function that intialized my engine with a provided HWND (a C# panel). This enabled me to render to the panel, so I then expanded upon this 'link' and proceeded to add on additional functionality like importing objects.&#xD;&#xA;&#xD;&#xA;    // in C++:&#xD;&#xA;    extern &quot;C&quot; &#xD;&#xA;    {&#xD;&#xA;      void InitializeMyEngine(HWND window);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can then then use P/Invoke in C# to access that function:&#xD;&#xA;&#xD;&#xA;    class Engine&#xD;&#xA;    {&#xD;&#xA;      [DllImport(&quot;engine.dll&quot;)]&#xD;&#xA;      public static extern void Initialize(IntPtr window);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I then called `Engine.Initialize(someWindowHandle)` in my C# code to initialize the engine. &#xD;&#xA;&#xD;&#xA;Here's a link to where asked how I could do this on the gamedev stack exchange: https://gamedev.stackexchange.com/questions/124249/how-do-i-render-my-directx-c-engine-to-a-c-panel&#xD;&#xA;&#xD;&#xA;I got a few answers and I managed to do what I needed to do (which I've of course detailed there). There is much more detail and code available regarding the implementation aswell. I would suggest asking on the [GameDev Stack Exchange][1] if you don't find a sufficient answer here.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;(photo of the engine rendering a cyan screen when the button is pressed using the method I described)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com&#xD;&#xA;  [2]: https://i.stack.imgur.com/jcvYM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13048" PostHistoryTypeId="5" PostId="118" RevisionGUID="efad0a11-d70d-4944-aae7-8120d089f061" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="The mathematical approach to this is to represent the other colors/light sources in terms of your standard primaries in the color space. Represent your target color and available light sources as vectors with, say, the RGB color space as the basis. Figuring out how to display your target color using your available sources then becomes a [change of basis][1], a standard linear algebra operation, where the target basis consists of your LEDs/nonstandard primaries.&#xD;&#xA;&#xD;&#xA;If the dimensions of the source and destination bases are different, the change of basis matrix won't be square and thus won't be invertible. In that case, you need to solve a system of linear equations, expressed in matrix form:&#xD;&#xA;&#xD;&#xA;$$c_{RGB} = [r, y, b, v] \cdot c_{RYBV}$$&#xD;&#xA;&#xD;&#xA;Where $c_{RGB}$ and $c_{RYBV}$ are the coordinate vectors of your desired color expressed in terms of RGB and custom primaries, respectively, and $r$, $y$, $b$ and $v$ are your custom primaries (basis vectors) in RGB coordinates.&#xD;&#xA;&#xD;&#xA;Solving this system is another common linear algebra operation, and there are a variety of numerical and symbolical algorithms to do so. The system is over-constrained, so solutions will likely have a free variable, however since we can't physically produce negative light, nor do the primaries have infinite dynamic range, for most practical purposes each coefficient will have to be limited to be within the $[0, 1]$ range. This will render many colors unrepresentable under certain sets of primaries.&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/a/340991/166490" ContentLicense="CC BY-SA 3.0" />
  <row Id="13049" PostHistoryTypeId="5" PostId="237" RevisionGUID="e1a8add0-53fe-4b19-908a-112234ac9e11" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="This is the [Camera re-sectioning problem](https://en.wikipedia.org/wiki/Camera_resectioning). &#xD;&#xA;&#xD;&#xA;We need to have a few points, like the end points of the walls, to take the roles of x&lt;sub&gt;w&lt;/sub&gt;, y&lt;sub&gt;w&lt;/sub&gt; and z&lt;sub&gt;w&lt;/sub&gt; in the following equation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here A is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;These are the values of the camera itself.&#xD;&#xA;&#xD;&#xA;R and T are defined as the Rotation and Translation matrices for the camera, and are the values we need to solve for. The position, C, of the camera expressed in world coordinates is C = -R&lt;sup&gt;-1&lt;/sup&gt;T = -R&lt;sup&gt;T&lt;/sup&gt; T .&#xD;&#xA;&#xD;&#xA;The linked Wikipedia article mentions a few algorithms to solve these equations.&#xD;&#xA;&#xD;&#xA;An example of a practical application of these is also found on [Math Stack Exchange](https://math.stackexchange.com/questions/82602/how-to-find-camera-position-and-rotation-from-a-4x4-matrix).&#xD;&#xA;&#xD;&#xA;Another example, with some code samples that you may want to use, is found [Stack Overflow](http://stackoverflow.com/questions/76134/how-do-i-reverse-project-2d-points-into-3d).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qXr4W.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Xs4BR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13050" PostHistoryTypeId="5" PostId="374" RevisionGUID="3f88e5f0-8b62-4742-8add-09e953c34f70" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="I tried [this question on math.SE](https://math.stackexchange.com/questions/348806/intersect-a-line-with-a-bicubic-bezier-surface-patch) and surprisingly, the answer was &quot;the equations are too nasty, just feed the function it to a numerical root-finder&quot;. But if you consider yourself &quot;a graphics guy&quot; like me, and have played extensively with Bezier curves for design work, I got to believe that better can be done. There is a published algorithm by Kajiya that I don't have the background to understand (Sylvester Matrices), but the related advice on math.SE was that the result is a degree-18 polynomial in t, and you still need to solve that numerically. [I had another idea with similar result](https://math.stackexchange.com/questions/1083240/can-a-bicubic-bezier-surface-be-represented-as-a-bernstein-polynomial).&#xD;&#xA;&#xD;&#xA;So, is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically, thus making it possible to code explicitly and have super-fast super-smoothness?&#xD;&#xA;&#xD;&#xA;Barring that, what's the fastest method for performing this calculation? Can you &quot;find the wiggles&quot; to get a tight bound (and target) for recursive subdivision? If you have to use a numerical root-finder (sigh), what properties does it need and is there a best choice for speed?&#xD;&#xA;&#xD;&#xA;My original thought was about preparing for a specific surface, similar to Laplace expansion as described in the answer to my [other math question about triangles](https://math.stackexchange.com/questions/297588/for-bsp-generation-how-to-intersect-or-locate-a-triangle-with-a-plane-defined-b). But I'd be interested in general methods, too. I'm just thinking of a fixed set of shapes, like [the Utah teapot](http://stackoverflow.com/questions/14807341/how-to-do-a-space-partitioning-of-the-utah-teapot). But I'd be very interested in ways of optimizing for temporal coherence across animated frames." ContentLicense="CC BY-SA 3.0" />
  <row Id="13051" PostHistoryTypeId="5" PostId="1467" RevisionGUID="1322a079-4ae6-4abf-a748-d49656f06e6f" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="I am looking for a good introduction to Lane-Riesenfeld algorithms, which are a family of subdivision methods for generating uniform B-splines. Any suggestions?&#xD;&#xA;&#xD;&#xA;*Note.* This is a copy of [the question I asked on Mathematics StackExchange][1]. One of the users there suggested this site might have more answers to offer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/1428101/an-introduction-to-lane-riesenfeld-algorithms" ContentLicense="CC BY-SA 3.0" />
  <row Id="13052" PostHistoryTypeId="5" PostId="2058" RevisionGUID="a361bc37-42c8-44e3-81bf-27df1168f0bc" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="I am a bit unsure if my calculations are correct, but on my scribbling paper it seemed to work out.&#xD;&#xA;&#xD;&#xA;P1 and P2 lie on a circle around M.&#xD;&#xA;&#xD;&#xA;This allows us to measure the distance of the two points by just taking the radius (which is half the line length) of the circle and constructing two rectangular triangles. The accepted answer [here][1] provides a sketch for this construction.&#xD;&#xA;So given your rotation angle is $\gamma$ and the line is $l$ long it follows:&#xD;&#xA;&#xD;&#xA;$x = 2* sin(\frac{\gamma}{2}) * \frac{l}{2}$&#xD;&#xA;&#xD;&#xA;The lines M to P1 and M to P2 form a isosceles triangle with the third side being the line segment between P1 and P2.&#xD;&#xA;&#xD;&#xA;The angle at point M is known to be the rotation angle $\gamma$ so the remaining two angles in this triangle are given by&#xD;&#xA;&#xD;&#xA;$\alpha = \frac{180 - \gamma}{2}$ &#xD;&#xA;&#xD;&#xA;And therefore the angle between the wrong line and the needed translation vector is just &#xD;&#xA;&#xD;&#xA;$\beta = \alpha + \gamma$&#xD;&#xA;&#xD;&#xA;So now you rotate a unit vector that starts along the wrong line.&#xD;&#xA;&#xD;&#xA;You rotate it around P1 for $\beta$ and scale it to length x.&#xD;&#xA;&#xD;&#xA;This yields the translation vector from P1 to P2. The rotation of the line should indeed be correct.&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/134606/distance-between-any-two-points-on-a-unit-circle" ContentLicense="CC BY-SA 3.0" />
  <row Id="13053" PostHistoryTypeId="5" PostId="2152" RevisionGUID="419a06bf-c70d-4151-81c0-02436d274840" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="&lt;strike&gt;The &quot;Uniform Mapping&quot; here is incorrect.  It does not transform to a uniform distribution on the sphere.&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;Very very bad me.  I misread the equation AND I didn't even consult my own reference [1], if I had I would have seen my mistake.&#xD;&#xA;&#xD;&#xA;Still the method from [2] is interesting and is described below.&#xD;&#xA;&#xD;&#xA;#Additional note:&#xD;&#xA;To map a uniform point set from the unit square to the sphere or half sphere requires an area-preserving map.  That will maintain the uniform property.  For pseudo-random that's sufficient (points are independent), however low-discrepancy point set will have its discrepancy measure effected by distortions in area introduced by the map.  I'm not aware of any references with respect to this point.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The method from [2] starts by mapping unit square to the unit disk.  One way we can do this is by using a rejection method.  Pseudo-code looks like this:&#xD;&#xA;&#xD;&#xA;    d = 0;&#xD;&#xA;&#xD;&#xA;    do {&#xD;&#xA;      p = uniform2d(...);  // [0,1) x [0,1)   given to be uniform&#xD;&#xA;      p = 2p;              // [0,2) x [0,2)   scaling (area-preserving)&#xD;&#xA;      p = p-1;             // (-1,1) x (-1,1) translating (area-preserving)&#xD;&#xA;      d = dot(p,p);        // is p in disk?&#xD;&#xA;    } while(d &gt;= 1);       //   if not rinse-and-repeat&#xD;&#xA;&#xD;&#xA;the area of the transformed square is $4$ and the unit disk is $\pi$, so the acceptance rate is $\frac{\pi }{4}$ (~.785) so on average requires $\frac{4}{\pi}$ (~1.273) iterations.&#xD;&#xA;&#xD;&#xA;Also non-rejection based methods exist, for example [3] which requires one square root and one trig operation. Note that the rejection method does not distort areas so the discrepancy measure remains the same.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Once we have $ p = \left(u_0, u_1 \right) $ uniformly distributed in the unit disk, we have:&#xD;&#xA;&#xD;&#xA;$$ u_0, u_1 \in \left(-1,1\right) $$&#xD;&#xA;$$ d = p\cdot p = u_0^2+u_1^2,\; d &lt; 1 $$&#xD;&#xA;&#xD;&#xA;then the transform to the sphere is:&#xD;&#xA;&#xD;&#xA;$$ s=2\sqrt{1-d} $$&#xD;&#xA;$$ p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, 1-2d\right\} $$&#xD;&#xA;&#xD;&#xA;or if you wanted a half-sphere, say positive Z, (just to state the obvious):&#xD;&#xA;&#xD;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, d\right\} $$&#xD;&#xA;&#xD;&#xA;There is a Stackexchange: Mathematics thread that discusses this method ([4],[5]).&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Also if you want to procedurally generate a LDS the additive recurrence formulation of the Weyl sequence is very cheap.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA;1. [Wolfram MathWorld: Sphere Point Picking](http://mathworld.wolfram.com/SpherePointPicking.html)&#xD;&#xA;2. &quot;Choosing a Point from the Surface of a Sphere.&quot;, George Marsaglia, 1972. \([PDF](http://projecteuclid.org/euclid.aoms/1177692644;))&#xD;&#xA;3. [Wolfram MathWorld: Disk Point Picking](http://mathworld.wolfram.com/DiskPointPicking.html)&#xD;&#xA;4. [SE Mathematics](https://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838336#838336)&#xD;&#xA;5. [SE Mathematics](https://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838882#838882)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13054" PostHistoryTypeId="5" PostId="2220" RevisionGUID="e33be301-c7e8-4d36-9ba6-b4255a8e2a04" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="Funnily enough, I asked this exact question on Math.SE a couple years ago: [Maximum number of vertices in intersection of triangle with box](https://math.stackexchange.com/questions/859454/maximum-number-of-vertices-in-intersection-of-triangle-with-box/).&#xD;&#xA;&#xD;&#xA;The answer is 9 vertices, because each of the 6 planes of the box can cut off one corner of the polygon, replacing one vertex with two. So 3 vertices + 6 added vertices due to clipping = 9 total." ContentLicense="CC BY-SA 3.0" />
  <row Id="13055" PostHistoryTypeId="5" PostId="2347" RevisionGUID="67ed0460-96e2-4506-8aa9-b55d731c7d85" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="Another code review question.&#xD;&#xA;&#xD;&#xA;I am trying to draw an arrow to represent a vector. I have started with an unit arrow with vertices defined as follows:&#xD;&#xA;&#xD;&#xA;    //vertex data for vector with arrow    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;		//line&#xD;&#xA;		0.0f, 0.0f, 0.0f,&#xD;&#xA;		1.0f, 0.0f, 0.0f,&#xD;&#xA;&#xD;&#xA;		//arrow bases&#xD;&#xA;		0.95f, 0.01f, 0.0f,&#xD;&#xA;		0.95f,-0.01f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    GLuint indices[] = {&#xD;&#xA;		0, 1,		// Line&#xD;&#xA;		1, 2, 3    // Arrow Triangle&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I have another array that contains the actual vector start and end positions:&#xD;&#xA;&#xD;&#xA;    GLfloat lineVertices[] = {&#xD;&#xA;						&#xD;&#xA;		1.0f, 2.0f, 3.0f, //v1 start&#xD;&#xA;		3.0f, 5.0f,-5.0f, //v1 end&#xD;&#xA;&#xD;&#xA;	   -1.0f,-1.0f,-1.0f, //v2 start&#xD;&#xA;	   -3.0f, 5.0f,-10.0f //v2 end&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am trying to construct the `model` matrix to apply the transformation from `lineVertices` for each vectors on the unit arrow.&#xD;&#xA;&#xD;&#xA;    //'view', and 'projection' matrix is set out side of the loop&#xD;&#xA;	for (GLint i = 0; i &lt; sizeof(lineVertices) / sizeof(GLfloat); i += 6)&#xD;&#xA;	{&#xD;&#xA;		glm::mat4 model;&#xD;&#xA;&#xD;&#xA;		//apply transformation&#xD;&#xA;		glm::vec3 start(lineVertices[i], lineVertices[i + 1], lineVertices[i + 2]);&#xD;&#xA;		glm::vec3 end(lineVertices[i + 3], lineVertices[i + 4], lineVertices[i + 5]);&#xD;&#xA;		glm::vec3 startToEnd = end - start;&#xD;&#xA;		GLfloat length = glm::length(startToEnd);&#xD;&#xA;&#xD;&#xA;        //translate&#xD;&#xA;		model = glm::translate(model, start);&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		//GLfloat xyAngle = glm::atan(startToEnd.z, length);&#xD;&#xA;		//GLfloat xzAngle = glm::atan(startToEnd.y, length);&#xD;&#xA;		//GLfloat yzAngle = glm::atan(startToEnd.x, length);&#xD;&#xA;&#xD;&#xA;		//model = glm::rotate(model, xyAngle, glm::vec3(1.0f, 1.0f, 0.0f));&#xD;&#xA;		//model = glm::rotate(model, xzAngle, glm::vec3(1.0f, 0.0f, 1.0f));&#xD;&#xA;		//model = glm::rotate(model, yzAngle, glm::vec3(0.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;		//rotate&#xD;&#xA;		GLfloat angleWithZ = glm::acos(startToEnd.z/length);&#xD;&#xA;		GLfloat angleWithY = glm::acos(startToEnd.y/length);&#xD;&#xA;		GLfloat angleWithX = glm::acos(startToEnd.x/length);&#xD;&#xA;&#xD;&#xA;		model = glm::rotate(model, angleWithX, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithY, glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;		model = glm::rotate(model, angleWithZ, glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;		//scale&#xD;&#xA;		model = glm::scale(model, glm::vec3(length));&#xD;&#xA;&#xD;&#xA;		glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, &quot;model&quot;), 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;			&#xD;&#xA;		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, 0);&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, BUFFER_OFFSET(2));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Though this seems to work, as I can see all those arrows, however, I am not sure whether this is the right implementation or not. Please let me know, if this is correct and/or there is room for improvement, or there are easier ways to achieve this, and so on.&#xD;&#xA;&#xD;&#xA;**Edit:** updated my code sample (only the rotation part) based on [Direction cosine (wikipedia)][1]. Old code is still kept commented. &#xD;&#xA;&#xD;&#xA;P.S.: this implementation is based on following stack exchange discussions: [1][2], [2][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Direction_cosine&#xD;&#xA;  [2]: https://gamedev.stackexchange.com/a/96960/82355&#xD;&#xA;  [3]: https://math.stackexchange.com/a/799812/298948" ContentLicense="CC BY-SA 3.0" />
  <row Id="13056" PostHistoryTypeId="5" PostId="3609" RevisionGUID="3ab94c06-7f70-4a89-88a4-41c641508753" CreationDate="2017-04-13T12:19:38.027" UserId="-1" Comment="replaced http://math.stackexchange.com/ with https://math.stackexchange.com/" Text="The benefit of perlin noise is the overall distribution of frequencies. Since value noise uses simple values that are interpolated, there is a higher chance, that a row of several values only differs a little. The consequence is, that some regions of your picture may contain little changes and some regions a lot of changes. &#xD;&#xA;&#xD;&#xA;By using gradients you are reducing this effect because the interpolation is not done by value but instead calculated between tangents. Now it's more difficult to have a flat curve (both tangents must be collinear).&#xD;&#xA;&#xD;&#xA;[![perlin noise vs value noise][1]][1]&#xD;&#xA;&#xD;&#xA;Source: As noted by Martin Ender the question was already posted on a different StackExchange community: see [this Math.SE post][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7kSzR.png&#xD;&#xA;  [2]: https://math.stackexchange.com/q/184121/50421" ContentLicense="CC BY-SA 3.0" />
  <row Id="13057" PostHistoryTypeId="5" PostId="1837" RevisionGUID="7a54521b-827f-4dd2-80ce-3a2c40293ec1" CreationDate="2017-04-13T12:32:23.057" UserId="-1" Comment="replaced http://ux.stackexchange.com/ with https://ux.stackexchange.com/" Text="This question should most probably be asked on [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](https://ux.stackexchange.com/). These sites specialize in how to design the graphics and how to choose the graphics for your purpose. But since you are here basic options are:&#xD;&#xA;&#xD;&#xA;1. Routes dont overlap but are parallel like electronic layouts (image 1, A), Works well unless you have many overlapping things.&#xD;&#xA;2. Space interleaved lines, differently colored line regions (image 1, B). Such as dashed lines, however many other interleaved shapes are possible. &#xD;&#xA;3. Spatial solutions, lines on top of each other but laid over in 3d (image 1, C), Works well in isometric drawing.&#xD;&#xA;4. Different line widths (image 1, D)&#xD;&#xA;5. User suggested, overlay (image 1, E).&#xD;&#xA;6. Same color but labels on segments (image 1, F), note not all segments need to be labeled as humans can interpolate values somewhat. This has benefit of being able to be paired with any other effect and works well with selection highlights with info intact. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 1**: Different overlay methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: None, except the labeling works well when there are very many different lines as humans capability to see different colors in this kind of context as differing data is not very good (ask [UX.SE](https://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;As for what is best depends. None of these are particularity hard to do in code or vector drawing application (but that is out of scope ask [GD.SE](http://graphicdesign.stackexchange.com/)). Whichever is best for the user or the design is also not within the scope of this software (ask  [GD.SE](http://graphicdesign.stackexchange.com/) or [UX.SE](https://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ZfX0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13059" PostHistoryTypeId="5" PostId="4972" RevisionGUID="57b41b1c-713d-493c-a275-206c69ac5655" CreationDate="2017-04-13T12:40:18.170" UserId="-1" Comment="replaced http://physics.stackexchange.com/ with https://physics.stackexchange.com/" Text="I'm confused by the `Waves` class [implementation](https://github.com/utilForever/DirectX/blob/master/DirectX%2011/Frank%20D.%20Luna/Common/Waves.cpp#L55) in the source code of the book *Introduction to 3D Game Programming with DirecX11*:&#xD;&#xA;&#xD;&#xA;    float d = damping*dt+2.0f;&#xD;&#xA;    float e = (speed*speed)*(dt*dt)/(dx*dx);&#xD;&#xA;    mK1     = (damping*dt-2.0f)/ d;&#xD;&#xA;    mK2     = (4.0f-8.0f*e) / d;&#xD;&#xA;    mK3     = (2.0f*e) / d;&#xD;&#xA;&#xD;&#xA;What do the parameters mean? How are the waves generated? I've tried searching waves implementation and found http://stackoverflow.com/questions/6716887/how-to-render-ocean-wave-using-opengl-in-3d , I looked up the links mentioned by the answer but I couldn't understand the complicated equations and it seems that the equations have no relation with the code above. I also tried searching &quot;spatially damped wave&quot;, and then I found https://physics.stackexchange.com/questions/223366/wave-equation-with-spatial-damping, that didn't help me, neither...&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13060" PostHistoryTypeId="5" PostId="3939" RevisionGUID="26d6413e-b8de-433f-8704-0aa3cfda83bd" CreationDate="2017-04-13T12:41:06.387" UserId="-1" Comment="replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/" Text="There's already something called K-nearest neighbour algorithm with gives nearest neighbour to points. But what I want is unique neighbour which is not shared by any other neighbour.&#xD;&#xA;I've implemented this logic but it's very slow. You can review my code [here][n].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [n]: https://codereview.stackexchange.com/questions/140292&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Let's assume there're 2 galaxies with 5 stars in each. GalaxyA neighbour list(let's call it closestNeighbourList) in GalaxyB starting from closest to fartherest...&#xD;&#xA;&#xD;&#xA;star 0: [4, 1, 0, 3, 2]&#xD;&#xA;&#xD;&#xA;star 1: [2, 0, 4, 3, 1]&#xD;&#xA;&#xD;&#xA;star 2: [2, 1, 3, 0, 4]&#xD;&#xA;&#xD;&#xA;star 3: [0, 3, 2, 4, 1]&#xD;&#xA;&#xD;&#xA;star 4: [0, 3, 1, 4, 2]&#xD;&#xA;&#xD;&#xA;from these lists default first neighbour list:&#xD;&#xA;&#xD;&#xA;star 0: [4]&#xD;&#xA;&#xD;&#xA;star 1: [2]&#xD;&#xA;&#xD;&#xA;star 2: [2]&#xD;&#xA;&#xD;&#xA;star 3: [0]&#xD;&#xA;&#xD;&#xA;star 4: [0]&#xD;&#xA;&#xD;&#xA;Since I want unique neighbour in GalaxyB, but here you see a problem, star 2 in GalaxyB is closest to two GalaxyA stars 1 &amp; 2 and same for star 0. So these are not unique neighbour as shared by two or more stars. So to overcome this problem what I'm doing first storing all neighbours in a list(closestNeighbourList) then looping over those to check if it's closer to(shared by) some other star then go to next neighbour and when it's find unique neighbour break out of the loop.&#xD;&#xA;&#xD;&#xA;after applying unique neighbour algorithm first neighbour list will be:&#xD;&#xA;&#xD;&#xA;star 0: [4]&#xD;&#xA;&#xD;&#xA;star 1: [2]&#xD;&#xA;&#xD;&#xA;star 2: [1]&#xD;&#xA;&#xD;&#xA;star 3: [3]&#xD;&#xA;&#xD;&#xA;star 4: [0]" ContentLicense="CC BY-SA 3.0" />
  <row Id="13061" PostHistoryTypeId="5" PostId="1505" RevisionGUID="5e080b6c-14bb-40b3-88b5-288dd10658a7" CreationDate="2017-04-13T12:44:05.773" UserId="-1" Comment="replaced http://photo.stackexchange.com/ with https://photo.stackexchange.com/" Text="A fairly basic but effective technique is [median filtering](https://en.wikipedia.org/wiki/Median_filter).  For video, you can apply it (spatio)temporally by replacing the value of each pixel in each frame by the median of the values of the pixel (and its neighbors) in the current and the *N* previous and later frames.&#xD;&#xA;&#xD;&#xA;A nice feature of median filtering is that it preserves linear edges (and, when used temporally, edges that move at a steady rate).  It does, however, tend to erode sharp corners and narrow ridges (and, temporally, narrow fast-moving features).  When overused, spatial median filtering has a tendency to create an over-smooth &quot;plastic&quot; appearance, while excessive temporal median filtering can even make small, fast-moving objects disappear completely.  ([Sometimes](https://photo.stackexchange.com/a/20960) this is considered a [feature.](http://www.deke.com/content/dekes-techniques-022-removing-people-with-image-stacks))&#xD;&#xA;&#xD;&#xA;It's possible to fine-tune and improve median filtering further with advanced techniques like motion tracking and threshold detection, but those also introduce an extra layer of complexity, and thus extra opportunities for unwanted artifacts if applied carelessly.  For many purposes, a simple median filter *of moderate size and strength* is often all you really need." ContentLicense="CC BY-SA 3.0" />
  <row Id="13062" PostHistoryTypeId="5" PostId="3755" RevisionGUID="a3862d43-53ad-47ec-97f4-f908bf84ea28" CreationDate="2017-04-13T12:44:05.773" UserId="-1" Comment="replaced http://photo.stackexchange.com/ with https://photo.stackexchange.com/" Text="I may be misunderstanding what you're asking, but if you know the sensor size and the number of pixels in the object, then you can calculate the object size. For example, a [Canon 7D](http://www.dpreview.com/products/canon/slrs/canon_eos7d/specifications) has an APS-C sensor that's 22.3 x 14.9mm and 5184 x 3456 pixels. That works out to ~0.0043mm/pixel. So if you have an object that's 250 pixels wide, then the projection of the object onto the sensor would have been 250 pixels * 0.0043mm/pixel = 1.075mm wide.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;So just for fun, I gave this a try. I took a 300mm ruler, put it at 1 meter from the camera and shot it with a 50mm lens on a Canon 7D. According to the ruler tool in Photoshop, it was 3734 pixels wide. That gives me the following equation:&#xD;&#xA;&#xD;&#xA;3734 * 0.0043 = (300 * 50) / 1000&#xD;&#xA;&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;16.0562 = 15.0&#xD;&#xA;&#xD;&#xA;Well, it's close, but not exact. (Over by 7%.) My guess is that the sensor site size is actually slightly smaller than 0.0043mm or the sensor size is slightly bigger than the reported size. In fact, the specs for the camera say 18MP effective size, but 19MP actual sensor size. So I'm not sure what that means, but I'm guessing it explains the difference between my actual result and the calculated result. (Either that or I'm misreading the length in Photoshop and it should actually be 3488 pixels instead of 3734.) But it was fun to try!&#xD;&#xA;&#xD;&#xA;**2nd EDIT:** [This question on the Photo Stack Exchange](https://photo.stackexchange.com/questions/69582/why-isnt-my-computation-of-the-actual-size-of-an-object-in-a-photograph-matchin) explains it. Camera lenses are often slightly longer or shorter than claimed, but rounded to the nearest nice focal length. So (assuming my calculations and measurements were correct) my lens is actually a ~53.5mm lens." ContentLicense="CC BY-SA 3.0" />
  <row Id="13064" PostHistoryTypeId="5" PostId="1880" RevisionGUID="a1cdfc1e-63e7-4613-8b31-bde82ee5dbf5" CreationDate="2017-04-13T12:46:08.230" UserId="-1" Comment="replaced http://video.stackexchange.com/ with https://video.stackexchange.com/" Text="TWO PART QUESTION - We've all seen the movies/TV shows where the police/feds/spies use computer software to take a grainy photo and do a &quot;clean-up&quot; to see a better picture and more details. I assume the concept is executed by some sort of **uber-power** pixel-smoothing or anti-aliasing type of algorithms to fill in the blanks based on deductive processing.&#xD;&#xA;&#xD;&#xA;PART 1: How *real* is this technology in the public/commercial software world? I'm not asking about any *speculation* on alleged secret gov software or such, I just want to know where we actually are with this concept today? How much is fully automated vs human-assisted. &#xD;&#xA;&#xD;&#xA;PART 2: Assuming there actually is *some* reality with this technology for photographs the second part of this question is how (if at all) has this been applied to videos? Again the issue of fully automated vs human assisted is of interest here.&#xD;&#xA;&#xD;&#xA;At the heart of this post is the ultimate question of how viable is today's software for being able to take an old VHS or DVD recording and process the frames to create a new HD-resolution remaster. Considering that doing this would mean cleaning up tens-of-thousands of frames for even a simple wedding video I am **not** expecting this technology to be fast of course.&#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;NOTE: Per in-topic and meta discussions I went ahead and cross-posted this in two other suggested SE forums to acquire their viewpoints and expertise on this matter. So far (it is still a little &quot;early in the day&quot; so to speak) I have received some pretty interesting information in 2 of the 3.&#xD;&#xA;&#xD;&#xA;When this is all done (when good answers have been selected) I would appreciate a way to merge these **for the benefit of all three SE communities**:&#xD;&#xA;&#xD;&#xA; - Computer Graphics: http://computergraphics.stackexchange.com/questions/1880&#xD;&#xA; - Signal Processing: http://dsp.stackexchange.com/questions/28168&#xD;&#xA; - Video Production: https://video.stackexchange.com/questions/17363" ContentLicense="CC BY-SA 3.0" />
  <row Id="13065" PostHistoryTypeId="5" PostId="83" RevisionGUID="ba27da17-aa8d-4a44-b5b6-385f2854bab0" CreationDate="2017-04-13T12:46:19.383" UserId="-1" Comment="replaced http://graphicdesign.stackexchange.com/ with https://graphicdesign.stackexchange.com/" Text="[Trichoplax question][1] aroused my curiosity and [the answers in this question](https://graphicdesign.stackexchange.com/questions/11445/gamma-vs-brightness-any-difference) also reminded me why I sometimes use different gamma &quot;amounts&quot; to enhance images.&#xD;&#xA;&#xD;&#xA;Therefore, is it possible to determine the amount of gamma applied to an image by knowing its source (the original image)? I.e. can the mathematical formula be applied to compare two images and determine the difference in gamma &quot;amount&quot;?&#xD;&#xA;&#xD;&#xA;Example: which of the following have a different gamma amount (I'll give you a non-edible cookie if you find out, and sorry trichoplax for snatching [your ball][2]):&#xD;&#xA;&#xD;&#xA;[![t_1][3]][3][![t_2][4]][4][![t_3][5]][5][![t_4][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://computergraphics.stackexchange.com/questions/68/is-gamma-still-important-to-take-into-account&#xD;&#xA;  [2]: https://i.stack.imgur.com/iukw5.png?s=328&amp;g=1&#xD;&#xA;  [3]: https://i.stack.imgur.com/msMpT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/qMPrK.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/5GsqI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/NxJLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13066" PostHistoryTypeId="5" PostId="418" RevisionGUID="20075520-c20a-4a5b-8efc-59fca8ea3ffc" CreationDate="2017-04-13T12:46:19.383" UserId="-1" Comment="replaced http://graphicdesign.stackexchange.com/ with https://graphicdesign.stackexchange.com/" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](https://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](https://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](https://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](http://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](http://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside a table [as per](http://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="13067" PostHistoryTypeId="5" PostId="1825" RevisionGUID="efe71480-9951-4515-b1bd-627eece15bc3" CreationDate="2017-04-13T12:46:19.383" UserId="-1" Comment="replaced http://graphicdesign.stackexchange.com/ with https://graphicdesign.stackexchange.com/" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;[![Art optimized versus screen preview of illustrator][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The different render modes of illustrator. Art optimized on left and hinted on right. Note that hinted shows slight background through. I dont have the new CC version so i can not show the third.&#xD;&#xA;&#xD;&#xA;### How does art optimized work then&#xD;&#xA;&#xD;&#xA;Art optimized render mode is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render uses. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters and computing in linear color space. All multi sample methods exhibit the same correct rendering (given enough samples even mathematically correct).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Multi pixel filtering, on left illustrator native 'Art Optimized'. On right same image at 16x16 pixels with multi lobed [Lanczos filter in linear space](https://graphicdesign.stackexchange.com/questions/58162/how-to-draw-smooth-curved-shapes-in-illustrator/58175#58175). Make sure your zoom is 1:1.&#xD;&#xA;&#xD;&#xA;### The problem&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0 when chained over semitransparent surfaces so background show trough. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](https://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;**Other questions** You can get same result in any other engine by just simply multisampling a non-antialiased image. You can not get the effect in on screen renderings without doing the overlap trick because they optimize for speed. Does illustrator use 3D? New CC might depends on your interpretation of what 3D is. This issue has nothing to do with 3D just about signal reconstruction methods so its not applicable to the question really.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](http://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tf7V4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EfM61.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13068" PostHistoryTypeId="5" PostId="1837" RevisionGUID="bde583ea-3fca-4b7f-97c8-8ac81b7611f5" CreationDate="2017-04-13T12:46:19.383" UserId="-1" Comment="replaced http://graphicdesign.stackexchange.com/ with https://graphicdesign.stackexchange.com/" Text="This question should most probably be asked on [GD.SE](https://graphicdesign.stackexchange.com/) or [UX.SE](https://ux.stackexchange.com/). These sites specialize in how to design the graphics and how to choose the graphics for your purpose. But since you are here basic options are:&#xD;&#xA;&#xD;&#xA;1. Routes dont overlap but are parallel like electronic layouts (image 1, A), Works well unless you have many overlapping things.&#xD;&#xA;2. Space interleaved lines, differently colored line regions (image 1, B). Such as dashed lines, however many other interleaved shapes are possible. &#xD;&#xA;3. Spatial solutions, lines on top of each other but laid over in 3d (image 1, C), Works well in isometric drawing.&#xD;&#xA;4. Different line widths (image 1, D)&#xD;&#xA;5. User suggested, overlay (image 1, E).&#xD;&#xA;6. Same color but labels on segments (image 1, F), note not all segments need to be labeled as humans can interpolate values somewhat. This has benefit of being able to be paired with any other effect and works well with selection highlights with info intact. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Image 1**: Different overlay methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: None, except the labeling works well when there are very many different lines as humans capability to see different colors in this kind of context as differing data is not very good (ask [UX.SE](https://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;As for what is best depends. None of these are particularity hard to do in code or vector drawing application (but that is out of scope ask [GD.SE](https://graphicdesign.stackexchange.com/)). Whichever is best for the user or the design is also not within the scope of this software (ask  [GD.SE](https://graphicdesign.stackexchange.com/) or [UX.SE](https://ux.stackexchange.com/)).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ZfX0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13069" PostHistoryTypeId="5" PostId="2368" RevisionGUID="0a372e05-cd2e-4ffa-b05b-1034aaea4846" CreationDate="2017-04-13T12:46:19.383" UserId="-1" Comment="replaced http://graphicdesign.stackexchange.com/ with https://graphicdesign.stackexchange.com/" Text="I have a 3D scene I use to generate some images which I then process in Matlab. I noticed that when global illumination (GI) is not enabled, rendering always generates exactly the same pixel-for-pixel image (as far as I can tell). However, when I enable GI, the image is not exactly the same. I have been told (I originally accidentally posted [here][1]) that GI is stochastic and so this is to be somewhat expected. However, I am curious if there's any way to avoid it (while still using GI).&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphicdesign.stackexchange.com/questions/70432/gi-leading-to-image-variation/70480#70480" ContentLicense="CC BY-SA 3.0" />
  <row Id="13070" PostHistoryTypeId="5" PostId="4871" RevisionGUID="7ecc3cf9-005f-4168-b2a0-24d265f6a3de" CreationDate="2017-04-13T12:46:19.383" UserId="-1" Comment="replaced http://graphicdesign.stackexchange.com/ with https://graphicdesign.stackexchange.com/" Text="Id like to leave a longish comment with pictures on the drawing aspect. Raytracing is not limited to computer graphics you can and often do see see artists manually raytrace to figure out intersections of shapes on paper with a ruler or even freehand by elbow twisting*.&#xD;&#xA;&#xD;&#xA;It is also useful for many physical sciences like mechanical engineering and surveying. Or anywhere where you can use geometry to solve your problem.&#xD;&#xA;&#xD;&#xA;While @DanHulme correctly surmises that the mathematical definition of a ray is just a line with a starting point and no ending point (goes to infinity). This is not really what people do, instead its defined that way to be rigorous. In general its just a line that goes far enough for the job, and we aren't really interested in the other end but rather how the line interacts with something. Infinity is just a safe way of saying it will in fact interact if possible. Mathematicians are very particular about stuff like that.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: An example of manually tracing shadows of objects with ruler and pen for a as of yet unfinished answer on the subject [here](https://graphicdesign.stackexchange.com/a/86754/18306). Mainly here because i had spent yesterday evening doing the rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you see you would use rays whenever you try to find a geometric intersection between two geometric primitives. Its not only useful for shadows, its for anything where you can intersect two things, with a starting point somewhere. So tracing can be used to find the shape of 2 intersecting surfaces, manually drawing perpective images, volumetric problems, rendering implicit surfaces like metaballs solving mathematical functions numerically etc etc. &#xD;&#xA;&#xD;&#xA;\* The definition of what now is called a ray was first described by Euclid's Elements about 300 bc. Which predates computers by a safe(ish) margin.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WwdR3.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13071" PostHistoryTypeId="5" PostId="29" RevisionGUID="cb7b1bd9-7876-4cfd-87fe-c9c40f47e429" CreationDate="2017-04-13T12:47:29.743" UserId="-1" Comment="replaced http://dsp.stackexchange.com/ with https://dsp.stackexchange.com/" Text="It turns out that no, while you can use bicubic Lagrange interpolation for bicubic texture sampling, it isn't the highest quality option, and probably not actually likely to be used.&#xD;&#xA;&#xD;&#xA;Cubic hermite splines are a better tool for the job.&#xD;&#xA;&#xD;&#xA;Lagrange interpolation will make a curve that passes through the data points, thus preserving C0 continuity, but hermite splines preserve the derivatives at the edges while also passing through the data points, thus preserving C1 continuity and looking much better.&#xD;&#xA;&#xD;&#xA;This question has some great info on cubic hermite splines:&#xD;&#xA;https://dsp.stackexchange.com/questions/18265/bicubic-interpolation&#xD;&#xA;&#xD;&#xA;Here is the cubic hermite version of the code I posted in the question:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 CubicHermite (vec3 A, vec3 B, vec3 C, vec3 D, float t)&#xD;&#xA;    {&#xD;&#xA;    	float t2 = t*t;&#xD;&#xA;        float t3 = t*t*t;&#xD;&#xA;        vec3 a = -A/2.0 + (3.0*B)/2.0 - (3.0*C)/2.0 + D/2.0;&#xD;&#xA;        vec3 b = A - (5.0*B)/2.0 + 2.0*C - D / 2.0;&#xD;&#xA;        vec3 c = -A/2.0 + C/2.0;&#xD;&#xA;       	vec3 d = B;&#xD;&#xA;        &#xD;&#xA;        return a*t3 + b*t2 + c*t + d;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //=======================================================================================&#xD;&#xA;    vec3 BicubicHermiteTextureSample (vec2 P)&#xD;&#xA;    {&#xD;&#xA;        vec2 pixel = P * c_textureSize + 0.5;&#xD;&#xA;        &#xD;&#xA;        vec2 frac = fract(pixel);&#xD;&#xA;        pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);&#xD;&#xA;        &#xD;&#xA;        vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;&#xD;&#xA;        vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;&#xD;&#xA;        &#xD;&#xA;        vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;&#xD;&#xA;        vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;&#xD;&#xA;        vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;&#xD;&#xA;        vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;&#xD;&#xA;        vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;&#xD;&#xA;        vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;    &#xD;&#xA;        &#xD;&#xA;        vec3 CP0X = CubicHermite(C00, C10, C20, C30, frac.x);&#xD;&#xA;        vec3 CP1X = CubicHermite(C01, C11, C21, C31, frac.x);&#xD;&#xA;        vec3 CP2X = CubicHermite(C02, C12, C22, C32, frac.x);&#xD;&#xA;        vec3 CP3X = CubicHermite(C03, C13, C23, C33, frac.x);&#xD;&#xA;        &#xD;&#xA;        return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a picture showing the difference between sampling methods.  From left to right: Nearest Neighbor, Bilinear, Lagrange Bicubic, Hermite Bicubic&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/h0Ot0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13072" PostHistoryTypeId="5" PostId="1880" RevisionGUID="fe722a38-291b-4b91-910d-946aa12f31e3" CreationDate="2017-04-13T12:47:29.743" UserId="-1" Comment="replaced http://dsp.stackexchange.com/ with https://dsp.stackexchange.com/" Text="TWO PART QUESTION - We've all seen the movies/TV shows where the police/feds/spies use computer software to take a grainy photo and do a &quot;clean-up&quot; to see a better picture and more details. I assume the concept is executed by some sort of **uber-power** pixel-smoothing or anti-aliasing type of algorithms to fill in the blanks based on deductive processing.&#xD;&#xA;&#xD;&#xA;PART 1: How *real* is this technology in the public/commercial software world? I'm not asking about any *speculation* on alleged secret gov software or such, I just want to know where we actually are with this concept today? How much is fully automated vs human-assisted. &#xD;&#xA;&#xD;&#xA;PART 2: Assuming there actually is *some* reality with this technology for photographs the second part of this question is how (if at all) has this been applied to videos? Again the issue of fully automated vs human assisted is of interest here.&#xD;&#xA;&#xD;&#xA;At the heart of this post is the ultimate question of how viable is today's software for being able to take an old VHS or DVD recording and process the frames to create a new HD-resolution remaster. Considering that doing this would mean cleaning up tens-of-thousands of frames for even a simple wedding video I am **not** expecting this technology to be fast of course.&#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;NOTE: Per in-topic and meta discussions I went ahead and cross-posted this in two other suggested SE forums to acquire their viewpoints and expertise on this matter. So far (it is still a little &quot;early in the day&quot; so to speak) I have received some pretty interesting information in 2 of the 3.&#xD;&#xA;&#xD;&#xA;When this is all done (when good answers have been selected) I would appreciate a way to merge these **for the benefit of all three SE communities**:&#xD;&#xA;&#xD;&#xA; - Computer Graphics: http://computergraphics.stackexchange.com/questions/1880&#xD;&#xA; - Signal Processing: https://dsp.stackexchange.com/questions/28168&#xD;&#xA; - Video Production: https://video.stackexchange.com/questions/17363" ContentLicense="CC BY-SA 3.0" />
  <row Id="13073" PostHistoryTypeId="5" PostId="418" RevisionGUID="52f3393a-115f-4b0e-8dcb-8d3c779f5b7b" CreationDate="2017-04-13T12:51:48.840" UserId="-1" Comment="replaced http://engineering.stackexchange.com/ with https://engineering.stackexchange.com/" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](https://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](https://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](https://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](https://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](http://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside a table [as per](http://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="13074" PostHistoryTypeId="5" PostId="2131" RevisionGUID="ef1ed7e8-8aa9-4185-82ac-604d2ba6d18d" CreationDate="2017-04-13T12:53:56.223" UserId="-1" Comment="replaced http://scicomp.stackexchange.com/ with https://scicomp.stackexchange.com/" Text="I am trying to implement a 2D version of Foster and Fedkiw's paper, &quot;Practical Animation of Liquids&quot; here: http://physbam.stanford.edu/~fedkiw/papers/stanford2001-02.pdf&#xD;&#xA;&#xD;&#xA;Mostly everything works, except for section 8: &quot;Conservation of Mass.&quot; There, we set up a matrix of equations to compute the pressures needed to make the liquid divergent free. &#xD;&#xA;&#xD;&#xA;I believe my code matches the paper, however I am getting an unsolvable matrix during the conservation of mass step.&#xD;&#xA;&#xD;&#xA;Here are my steps for generating the matrix A:&#xD;&#xA;&#xD;&#xA; 1. Set the diagonal entries $A_{i,i}$ to the negative of number of adjacent liquid cells to cell i.&#xD;&#xA; 2. Set the entries $A_{i,j}$ and $A_{j,i}$ to 1 if both cells i and j have liquid.&#xD;&#xA;&#xD;&#xA;Note that, in my implementation, cell $i$,$j$ in the liquid grid corresponds to row $i + $gridWidth$ * j$ in the matrix.&#xD;&#xA;&#xD;&#xA;The paper mentions, &quot;Static object and empty cells don’t disrupt this&#xD;&#xA;structure. In that case pressure and velocity terms can disappear&#xD;&#xA;from both sides&quot;, so I delete the columns and rows for cells that have no liquid.&#xD;&#xA;&#xD;&#xA;So my question is: Why is my matrix singular? Am I missing some kind of boundary condition in some other place in the paper? Is it the fact that my implementation is 2D?&#xD;&#xA;&#xD;&#xA;Here is an example matrix from my implementation for a 2x2 grid where the cell at 0,0 has no liquid:&#xD;&#xA;&#xD;&#xA;    -1   0   1&#xD;&#xA;&#xD;&#xA;     0  -1   1&#xD;&#xA;&#xD;&#xA;     1   1  -2&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;My research has led me to believe that I'm not properly handling the boundary conditions.&#xD;&#xA;&#xD;&#xA;First of all, at this point I can say that my matrix represents the discrete pressure Poisson equation. It is the discrete analog of applying the Laplacian operator coupling local pressure changes to cell divergence.&#xD;&#xA;&#xD;&#xA;As far as I can understand, since we're dealing with pressure differences, boundary conditions are needed to &quot;anchor&quot; the pressures to an absolute reference value. Otherwise there may be an infinite number of solutions to the set of equations.&#xD;&#xA;&#xD;&#xA;In [these notes][1], 3 different ways are given to apply boundary conditions, to the best of my understanding:&#xD;&#xA;&#xD;&#xA; 1. Dirichlet - specifies absolute values at the boundaries.&#xD;&#xA;&#xD;&#xA; 2. Neummann - specifies the derivative at the boundaries.&#xD;&#xA;&#xD;&#xA; 3. Robin - specifies some kind of linear combination of the absolute value and the derivative at the boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Foster and Fedki's paper does not mention any of these, but I believe that they enforce Dirichlet boundary conditions, notable because of this statement at the end of 7.1.2, &quot;The pressure in a surface cell is set to atmospheric pressure.&quot;&#xD;&#xA;&#xD;&#xA;I've read the notes I linked a few times and still don't quite understand the math going on. How exactly do we enforce these boundary conditions? Looking at other implementations, there seems to be some kind of notion of a &quot;Ghost&quot; cells that lie at the boundary. &#xD;&#xA;&#xD;&#xA;Here I've linked to a few sources that may be helpful to others reading this.&#xD;&#xA;&#xD;&#xA;[Notes on boundary conditions for Poisson Matrices][1]&#xD;&#xA;&#xD;&#xA;[Computational Science StackExchange post on Neumann boundary conditions][2]&#xD;&#xA;&#xD;&#xA;[Computational Science StackExchange post on Poisson Solver][3]&#xD;&#xA;&#xD;&#xA;[Water Physbam Implementation][4]&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the code I use to generate the matrix. Note that, instead of explicitly deleting columns and rows, I generate and use a map from liquid cell indices to the final matrix columns/rows.&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; cells.length; i++) {&#xD;&#xA;      for (int j = 0; j &lt; cells[i].length; j++) {&#xD;&#xA;        FluidGridCell cell = cells[i][j];&#xD;&#xA;        &#xD;&#xA;        if (!cell.hasLiquid)&#xD;&#xA;          continue;&#xD;&#xA;        &#xD;&#xA;        // get indices for the grid and matrix&#xD;&#xA;        int gridIndex = i + cells.length * j;&#xD;&#xA;        int matrixIndex = gridIndexToMatrixIndex.get((Integer)gridIndex);&#xD;&#xA;        &#xD;&#xA;        // count the number of adjacent liquid cells&#xD;&#xA;        int adjacentLiquidCellCount = 0;&#xD;&#xA;        if (i != 0) {&#xD;&#xA;          if (cells[i-1][j].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (i != cells.length-1) {&#xD;&#xA;          if (cells[i+1][j].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (j != 0) {&#xD;&#xA;          if (cells[i][j-1].hasLiquid)&#xD;&#xA;          adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        if (j != cells[0].length-1) {&#xD;&#xA;          if (cells[i][j+1].hasLiquid)&#xD;&#xA;            adjacentLiquidCellCount++;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        // the diagonal entries are the negative count of liquid cells&#xD;&#xA;        liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                              matrixIndex, // row&#xD;&#xA;                              -adjacentLiquidCellCount); // value&#xD;&#xA;                                &#xD;&#xA;        // set off-diagonal values of the pressure matrix&#xD;&#xA;        if (cell.hasLiquid) {&#xD;&#xA;          if (i != 0) {&#xD;&#xA;            if (cells[i-1][j].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = (i-1) + j * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (i != cells.length-1) {&#xD;&#xA;            if (cells[i+1][j].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = (i+1) + j * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (j != 0) {&#xD;&#xA;            if (cells[i][j-1].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = i + (j-1) * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          if (j != cells[0].length-1) {&#xD;&#xA;            if (cells[i][j+1].hasLiquid) {&#xD;&#xA;              int adjacentGridIndex = i + (j+1) * cells.length;&#xD;&#xA;              int adjacentMatrixIndex = gridIndexToMatrixIndex.get((Integer)adjacentGridIndex);&#xD;&#xA;              liquidMatrix.setEntry(matrixIndex, // column&#xD;&#xA;                                    adjacentMatrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;              liquidMatrix.setEntry(adjacentMatrixIndex, // column&#xD;&#xA;                                    matrixIndex, // row&#xD;&#xA;                                    1.0); // value&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.math.toronto.edu/mpugh/Teaching/Mat1062/notes2.pdf&#xD;&#xA;  [2]: https://scicomp.stackexchange.com/questions/5355/writing-the-poisson-equation-finite-difference-matrix-with-neumann-boundary-cond&#xD;&#xA;  [3]: https://scicomp.stackexchange.com/questions/19485/2d-poisson-solver-for-taylor-green-vortex-problem&#xD;&#xA;  [4]: http://physbam.stanford.edu/~mlentine/project.html#water" ContentLicense="CC BY-SA 3.0" />
  <row Id="13075" PostHistoryTypeId="5" PostId="3580" RevisionGUID="342edef5-9d52-448b-9804-3fc6b2ffb029" CreationDate="2017-04-13T12:56:17.167" UserId="-1" Comment="replaced http://cogsci.stackexchange.com/ with https://cogsci.stackexchange.com/" Text="This question was originally asked on Physics, then moved to [Cognitive Sciences][1].&#xD;&#xA;&#xD;&#xA;Consider the following image:&#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;You might want to display the image in a new page, in case it gets resized for mobile displays.&#xD;&#xA;&#xD;&#xA;On the top half, there is a pixel-sized checkerboard pattern with alternating black and white pixels; on the bottom half, there's a black to white gradient. Now, I don't know if you see the same, but for me, when viewing from distance or defocusing my eyes and the top half blending into one color, I can't find any color in the gradient below which would match it.&#xD;&#xA;&#xD;&#xA;With simple arithmetics, I would guess at first guess the resulting color be either RGB $(0.5, 0.5, 0.5)$ or, with gamma, $(\sqrt{0.5}, \sqrt{0.5}, \sqrt{0.5})$. I cannot help myself, but the resulting color appears a lot warmer than the metallic gray which would appear if you for example zoomed this page or used a blur filter. I tried to add some yellow to the gradient, and the result looks more similar to the perceived color.&#xD;&#xA;&#xD;&#xA;Now, based on the comments, it appears some people perceive yellowish tint and some don't. And I do on my LCD computer screen but not on my mobile display. Thus I guess it's based on some property of the display.&#xD;&#xA;&#xD;&#xA;Why don't we perceive the resulting color like real gray? Where does the yellow color come from?&#xD;&#xA;&#xD;&#xA;I have a theory: Based on the [color arrangement in a typical LCD pixel][3], one white pixel would contain the red and green color together and blue on the right side. Blue color appears darker to human eye than colors with the same physical intensity, so a white pixel is more green than red than blue. Green and red have roughy the same perceptional insensity, and mixing red and green color addivitely gives yellow, thus the yellow tint? Well, shouldn't then all white pixels on the display appear a bit yellow?&#xD;&#xA;&#xD;&#xA;Is this possible? Are there any other explanations?&#xD;&#xA;&#xD;&#xA;A side question: Do you know any computer image scaling algorithm or blur filter that tries to mimic this, simulating a blurry vision of a human eye correctly?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/IxOzp.png&#xD;&#xA;  [3]: https://upload.wikimedia.org/wikipedia/commons/4/4d/Pixel_geometry_01_Pengo.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://cogsci.stackexchange.com/questions/15186/why-does-checkerboard-pattern-on-a-computer-screen-appear-with-a-yellowish-tint" ContentLicense="CC BY-SA 3.0" />
  <row Id="13076" PostHistoryTypeId="5" PostId="1489" RevisionGUID="86a5e537-814a-4d55-9025-86cf32dae5a8" CreationDate="2017-04-13T12:57:46.990" UserId="-1" Comment="replaced http://blender.stackexchange.com/ with https://blender.stackexchange.com/" Text="[Blender][1] likely meets your requirements. I have used it in the past to make 3D models and export to model files which Unity can import.&#xD;&#xA;&#xD;&#xA;I would highly recommend watching some tutorial videos before using it:&#xD;&#xA;&#xD;&#xA; - [one][2]&#xD;&#xA; - [two][3]&#xD;&#xA; - [three][4]&#xD;&#xA;&#xD;&#xA;[Blender StackExchange][5] can help answer more questions about Blender.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blender.org/&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=gF6qkByl-_M&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=y__uzGKmxt8&#xD;&#xA;  [4]: https://www.youtube.com/watch?v=2zd1AI198I8&#xD;&#xA;  [5]: https://blender.stackexchange.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13077" PostHistoryTypeId="5" PostId="4052" RevisionGUID="ff7f9f33-dfe7-41de-bcb1-331cbeeaa62b" CreationDate="2017-04-13T12:57:46.990" UserId="-1" Comment="replaced http://blender.stackexchange.com/ with https://blender.stackexchange.com/" Text="Judging by the interface that would be blender:&#xD;&#xA;&#xD;&#xA;https://www.blender.org/&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Please note that here is a bender-specific stackexchange site as well:&#xD;&#xA;&#xD;&#xA;https://blender.stackexchange.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13078" PostHistoryTypeId="5" PostId="4480" RevisionGUID="d7655606-ffe8-46f7-a1d9-3f305837437f" CreationDate="2017-04-13T12:57:46.990" UserId="-1" Comment="replaced http://blender.stackexchange.com/ with https://blender.stackexchange.com/" Text="What black magic is behind [this][1]?&#xD;&#xA;&#xD;&#xA;[![rigged finger][2]][2]&#xD;&#xA;&#xD;&#xA;Starting from a pile of polygons, a skeleton, and an initial conformation, how is a new conformation turned into a new pile of polygons?&#xD;&#xA;&#xD;&#xA;  [1]: https://blender.stackexchange.com/a/46319/13953&#xD;&#xA;  [2]: https://i.stack.imgur.com/1frCY.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="13079" PostHistoryTypeId="5" PostId="4466" RevisionGUID="accb3168-f180-48ff-a580-9b39f3b99b3a" CreationDate="2017-04-13T12:58:47.570" UserId="-1" Comment="replaced http://mathoverflow.net/ with https://mathoverflow.net/" Text="A key search phrase is &quot;collision detection.&quot; You may find some references at this MO posting, &quot;[Intersection of Polyhedra](https://mathoverflow.net/a/141730/6094).&quot;&#xD;&#xA;And here is a more recent reference:&#xD;&#xA;&#xD;&#xA;&gt; Jiménez, Juan J., and Rafael J. Segura. &quot;Collision detection between complex polyhedra.&quot; *Computers &amp; Graphics* 32.4 (2008): 402-411. ([Journal link](http://www.sciencedirect.com/science/article/pii/S0097849308000526).)&#xD;&#xA;&#xD;&#xA;Google Scholar shows this has been cited by 33 papers since." ContentLicense="CC BY-SA 3.0" />
  <row Id="13080" PostHistoryTypeId="5" PostId="64" RevisionGUID="daff471e-1869-45ff-b771-19984f521471" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In entirely technical terms, `fwidth(p)` is defined as&#xD;&#xA;&#xD;&#xA;    fwidth(p) := abs(dFdx(p)) + abs(dFdy(p))&#xD;&#xA;&#xD;&#xA;And `dFdx(p)`/`dFdy(p)` are the partial derivates of the value `p` with respect to the `x` and `y` screen dimensions. So they denote how the value of `p` behaves when going one pixel to the right (`x`) or one pixel up (`y`).&#xD;&#xA;&#xD;&#xA;Now how can they be practically computed? Well, if you know the neighbour pixels' values for `p`, you can just compute those derivates as direct **finite differences** as an approximation for their actual mathematical derivatives (which might not have an exact analytical solution at all):&#xD;&#xA;&#xD;&#xA;    dFdx(p) := p(x+1) - p(x)&#xD;&#xA;&#xD;&#xA;But of course now you may ask, how do we even know the values of `p` (which could afterall be any arbitrarily computed value inside the shader program) for the neighbouring pixels? How do we compute those values without incurring major overhead by doing the whole shader computation two (or three) times?&#xD;&#xA;&#xD;&#xA;Well, you know what, those neighbouring values are computed anyway, since for the neighbouring pixel you also run a fragment shader. So all that you need is access to this neighbouring fragment shader invocation when run for the neighbouring pixel. But it's even easier, because those neighbouring values are also computed at the exact same time.&#xD;&#xA;&#xD;&#xA;Modern rasterizers call fragment shaders in larger tiles of more than one neighbouring pixels. At the smallest those would be a 2x2 grid of pixels. And for each such a pixel block the fragment shader is invoked for each pixel and those invocations run **in perfectly parallel lock-step** so that all computations are done in the exact same order and at the exact same time for each of those pixels in the block (which is also why branching in the fragment shader, while not deadly, should be avoided if possible, since each invocation of a block would have to explore every branch that is taken by at least one of the invocations, even if it just throws away the results afterwards, as also adressed in the answers to [this related question](https://computergraphics.stackexchange.com/q/259/6)). So at any moment, a fragment shader theoretically has access to its neighbouring pixels' fragment shader values. And while you don't have direct access to those values, you have access to values computed from them, like the derivative functions `dFdx`, `dFdy`, `fwidth`, ..." ContentLicense="CC BY-SA 3.0" />
  <row Id="13081" PostHistoryTypeId="5" PostId="66" RevisionGUID="8609f11c-9064-4f21-a774-8871da472eff" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I know that depth of field involves blurring.&#xD;&#xA;&#xD;&#xA;There's some great information about how to do a Gaussian blur in the question https://computergraphics.stackexchange.com/questions/39/how-is-gaussian-blur-implemented&#xD;&#xA;&#xD;&#xA;But, other than that, how is depth of field implemented?&#xD;&#xA;&#xD;&#xA;What are the rules about how you blur each pixel, and how do you handle the case of when there is a pixel that wants to blur a lot next to a pixel that doesn't want to blur as much?&#xD;&#xA;&#xD;&#xA;I've also heard of the &quot;circle of confusion&quot; but have no idea what that is.&#xD;&#xA;&#xD;&#xA;Can anyone explain DOF in a plain, easy to understand way?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13082" PostHistoryTypeId="5" PostId="83" RevisionGUID="42363cad-c43d-4436-a9a7-883f483eb898" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="[Trichoplax question][1] aroused my curiosity and [the answers in this question](https://graphicdesign.stackexchange.com/questions/11445/gamma-vs-brightness-any-difference) also reminded me why I sometimes use different gamma &quot;amounts&quot; to enhance images.&#xD;&#xA;&#xD;&#xA;Therefore, is it possible to determine the amount of gamma applied to an image by knowing its source (the original image)? I.e. can the mathematical formula be applied to compare two images and determine the difference in gamma &quot;amount&quot;?&#xD;&#xA;&#xD;&#xA;Example: which of the following have a different gamma amount (I'll give you a non-edible cookie if you find out, and sorry trichoplax for snatching [your ball][2]):&#xD;&#xA;&#xD;&#xA;[![t_1][3]][3][![t_2][4]][4][![t_3][5]][5][![t_4][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/68/is-gamma-still-important-to-take-into-account&#xD;&#xA;  [2]: https://i.stack.imgur.com/iukw5.png?s=328&amp;g=1&#xD;&#xA;  [3]: https://i.stack.imgur.com/msMpT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/qMPrK.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/5GsqI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/NxJLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13083" PostHistoryTypeId="5" PostId="88" RevisionGUID="1e8cd7f8-7f4f-4cbe-a6c2-3c6afd6916fc" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Start with a precalculated &quot;ray cloud&quot; - the starting point and direction of a large number of rays, most of which will not contribute to the image. The image plane's position and orientation are then specified, and the task is to search the ray cloud for rays that intersect the image plane without occlusion by other objects, and output the resulting pixel values. No ray reflections would be required, as all of the work has already been done in generating the ray cloud. The only step left is to convert the rays to an image. This means that a single ray cloud can be used to generate images from arbitrary view angles.&#xD;&#xA;&#xD;&#xA;How could I go about accelerating this process using a GPU? The decision for each ray of whether it intersects the image plane is parallelisable as these decisions are independent, but each requires access to the objects in the scene as some rays will reach some potential image planes but not others. The final step of sampling the relevant rays across the pixels of the image requires each ray to contribute to a number of the surrounding pixels. Is this also parallelisable using a GPU?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To clarify, [RichieSams]' understanding is correct:&#xD;&#xA;&#xD;&#xA;- Start with a set of rays pointing in arbitrary directions.&#xD;&#xA;- Find which of these rays intersect with the image plane, taking into account occlusion. &#xD;&#xA;- Calculate the colour of each pixel based on the rays that hit the image plane.&#xD;&#xA;&#xD;&#xA;Ideally I would like to be able to accelerate this process sufficiently to move around a scene in real time, given a precomputed ray cloud over the whole scene.&#xD;&#xA;&#xD;&#xA;  [RichieSams]: https://computergraphics.stackexchange.com/users/310/richiesams" ContentLicense="CC BY-SA 3.0" />
  <row Id="13084" PostHistoryTypeId="5" PostId="101" RevisionGUID="38960640-50a3-43be-b195-bce75a06f1a1" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="As far as I know there are no tools that allows you to steps through code in a shader (also, in that case you would have to be able to select just a pixel/vertex you want to &quot;debug&quot;, the execution is likely to vary depending on that). &#xD;&#xA;&#xD;&#xA;What I personally do is a very hacky &quot;colourful debugging&quot;. So I sprinkle a bunch of dynamic branches with &lt;code&gt;#if DEBUG / #endif&lt;/code&gt; guards that basically say &#xD;&#xA; &#xD;&#xA;    &#xD;&#xA;	#if DEBUG&#xD;&#xA;	if( condition ) &#xD;&#xA;		outDebugColour = aColorSignal;&#xD;&#xA;	#endif&#xD;&#xA;	&#xD;&#xA;	.. rest of code .. &#xD;&#xA;	&#xD;&#xA;	// Last line of the pixel shader&#xD;&#xA;	#if DEBUG&#xD;&#xA;	OutColor = outDebugColour;&#xD;&#xA;	#endif&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you can &quot;observe&quot; debug info this way. I usually do various tricks like lerping or blending between various &quot;colour codes&quot; to test various more complex events or non-binary stuff. &#xD;&#xA;&#xD;&#xA;In this &quot;framework&quot; I also find useful to have a set of fixed conventions for common cases so that if I don't have to constantly go back and check what colour I associated with what. &#xD;&#xA;The important thing is have a good support for hot-reloading of shader code, so you can almost interactively change your tracked data/event and switch easily on/off the debug visualization. &#xD;&#xA;&#xD;&#xA;If need to debug something that you cannot display on screen easily, you can always do the same and use one frame analyser tool to inspect your results. I've listed a couple of them [as answer of this other question.][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Obv, it goes without saying that if I am not &quot;debugging&quot; a pixel shader or compute shader, I pass this &quot;debugColor&quot; info throughout the pipeline without interpolating it (in GLSL with &lt;code&gt; flat &lt;/code&gt; keyword ) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, this is very hacky and far from proper debugging, but is what I am stuck with not knowing any proper alternative.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/23/how-can-i-debug-what-is-being-rendered-to-a-frame-buffer-object-in-opengl/25#25" ContentLicense="CC BY-SA 3.0" />
  <row Id="13085" PostHistoryTypeId="5" PostId="203" RevisionGUID="a352ca54-b465-4d04-9cd4-c51c098c14c7" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In graphics we use RGB and other color spaces as an approximation to the full spectrum of light wavelengths. This evidently works pretty well in general, but are there any reasonably common objects/materials/phenomena, things you might encounter in your everyday life, whose appearance isn't represented well by RGB rendering due to having a complex emission/reflection/absorption spectrum?&#xD;&#xA;&#xD;&#xA;While the current answers are focusing mainly on colors outside a given RGB gamut, I'm also interested in hearing if there are examples where, for instance, the color of an object appears &quot;wrong&quot; when rendered in RGB because of an interaction between the light source spectrum and the object's reflection spectrum. In other words, a case where a spectral renderer would give you more correct results.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*Credit: I liked this question in the previous private beta so I'm reproducing it here. It was originally asked by [Nathan Reed]*&#xD;&#xA;&#xD;&#xA;  [Nathan Reed]: https://computergraphics.stackexchange.com/users/48/nathan-reed" ContentLicense="CC BY-SA 3.0" />
  <row Id="13086" PostHistoryTypeId="5" PostId="238" RevisionGUID="daf2e688-6e95-49c1-951b-d293eb381582" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In my torus light implementation(Unity3D) I use the same real-time method [described in @JohnCalsbeek's answer](https://computergraphics.stackexchange.com/a/232/376). Just treat it the same way you treat your regular point/spot light and calculate a single direction and distance.&#xD;&#xA;&#xD;&#xA;I use the torus distance equation from [Inigo Quilez's site](http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) and&#xD;&#xA;here's the function I made to get the direction to a torus&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    float3 torusDirection(float3 p) {&#xD;&#xA;	float3 torusRel;&#xD;&#xA;	torusRel.xz = normalize(p.xz-_TorusLocation.xz);&#xD;&#xA;	torusRel.y = 0;&#xD;&#xA;	&#xD;&#xA;	return -normalize(p-(TorusLocation+torusRel*TorusCenterRadius));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Overall I think it works well minus a few areas that look off where the torus loops around [![Example scene lit by a torus][1]][1]. &#xD;&#xA;&#xD;&#xA;The specular hint is also off but @JohnCalsbeek's point of modifying the roughness seems like it should fix that :). &#xD;&#xA;&#xD;&#xA;The hardest challenge for me with the light right now is making a forward shader that supports different kinds of area lights and multiple lights. I don't know how I would do this besides just having a whole bunch of shader properties for all the different lights though. Currently I apply the light as a deferred pass so it only works with opaque objects but soon I'll need to make a forward version for transparent objects. That's the real challenge I think, getting multiple area lights in a forward shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And here's a [Shadertoy demo](https://www.shadertoy.com/view/MllSWS) of a torus light I made to test mine, its based off of BeyondTheStatics shape light demo.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gBzMT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13087" PostHistoryTypeId="5" PostId="249" RevisionGUID="585327da-e095-4e4e-b38c-619b6e1d08e0" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="There are various different types of limitation to take into consideration.&#xD;&#xA;&#xD;&#xA;## Effects for which the path of a ray is dependent on its wavelength&#xD;&#xA;&#xD;&#xA;These are a class of effects for which spectral rendering is required, and a number of interesting examples have already been given in [Benedikt Bitterli's answer]. A simple example is a prism splitting white light into a spectrum, giving rainbow colours. Rays of different wavelength are refracted by different angles as they pass through the prism, resulting in the light striking the wall behind the prism being split into its constituent colours.&#xD;&#xA;&#xD;&#xA;This means that in real life, shining monochromatic yellow light through a prism will result in yellow light coming out, but shining a mixture of red and green light that approximates yellow will result in separate red and green light emerging. When rendering using only 3 primary colours, white light will split into only those three colours, giving rainbow effects that look discontinuous, and monochromatic light that should not split at all will split into its approximating primary colour components. The splitting of white light can be improved by using a larger number of primary colours, but this will still give discontinuities close up, and the results for monochromatic light will still be split, albeit more narrowly. For accurate results a continuous spectrum must be sampled, with wavelengths distributed according to the light source being simulated.&#xD;&#xA;&#xD;&#xA;## Surface effects that cannot be captured in a single still image&#xD;&#xA;&#xD;&#xA;[Iridescence], for example, shows a different colour to each eye so that a still image will not look the same as the original object. There are many everyday examples that you might not notice at first. Many common birds have iridescent feathers even though they appear black or grey from a distance. Close up they are surprisingly colourful. &#xD;&#xA;&#xD;&#xA;A renderer using only 3 primary colours will not be able to produce the spreading of light based on wavelength required for this effect. A spectral renderer can simulate the spreading correctly, but the full effect still cannot be captured in a single image. Even a 2d photograph cannot capture this correctly, whereas a 3d photograph of an iridescent object will give that shimmering effect as the photographs corresponding to left and right eyes will be coloured differently. This is a limitation of 2d images rather than the RGB colour space itself. However, even in a 3d image there will be colours in the iridescent object that are not displayed correctly, due to the inability of RGB to display monochromatic colours as described below.&#xD;&#xA;&#xD;&#xA;## Colours that the human eye can detect that cannot be displayed in RGB&#xD;&#xA;&#xD;&#xA;RGB was historically device dependent and therefore unreliable between platforms. There are device independent perceptually uniform improvements such as the colour space [Lab], but these are still trichromatic (having 3 components). It is not immediately obvious why three components is insufficient to display all the colours that can be perceived by a trichromatic eye, but [this paper] explains it well, and accessibly. From page 7:&#xD;&#xA;&#xD;&#xA;&gt; For example, using a modern laser-display system with monochromatic primaries at 635 nm (red), 532 nm (green), and 447 nm (blue), lets see if we can simulate the perception of a monochromatic light at 580 nm (an orange color). Since the monochromatic orange stimulus excites the greenish and reddish cones, a contribution is required by both the green and red primaries, while no contribution is required from the blue primary. The problem is that the green primary also excites the bluish cones, making it impossible to exactly replicate the orange stimulus&#xD;&#xA;&#xD;&#xA;The diagram of human eye cones sensitivities (also on page 7) shows how wide the overlap is and helps to visualise this explanation. I've included a similar graph from Wikipedia here: (click on the graph for the Wikipedia location)&#xD;&#xA;&#xD;&#xA;[![Graph of the sensitivities of the 3 different cones in the human eye][cones sensitivities graph]][cones sensitivities wikipedia location]&#xD;&#xA;&#xD;&#xA;In short, the overlap between the range of colours that can be picked up by each of the three different cones (colour sensors) of the human eye means that a monochromatic colour can be distinguished from an approximating mixture of primary colours, and therefore mixing primary colours can never accurately display all monochromatic colours.&#xD;&#xA;&#xD;&#xA;This difference is not usually noticeable in everyday life as most of our surroundings emit or reflect light across a wide range of frequencies rather than single monochromatic colours. However, a notable exception is sodium lamps. If you live in a part of the world that uses these yellow-orange street lights, the light emitted is monochromatic and will look subtly different from a printed photograph or an image on a screen. The wavelength of sodium light happens to be the 580 nm from the example quoted above. If you don't live somewhere that has sodium street lights, you can see the same single wavelength light by sprinkling finely crushed table salt (sodium chloride) over a flame. The scintillating yellow points of light cannot be accurately captured on film or displayed on a screen. Whatever three primary colours you choose, there will always be a range of monochromatic colours that cannot be displayed.&#xD;&#xA;&#xD;&#xA;Note that this limitation applies equally to mixing 3 primary colours of paint, using 3 photoreactive chemicals on a camera film, or taking a photograph with a digital camera with 3 different colour sensors, or a single sensor with 3 different primary colour filters. It isn't just a digital problem, and isn't just restricted to the RGB colour space. Even the improvements introduced by the Lab colour space and its variants cannot recover the missing colours.&#xD;&#xA;&#xD;&#xA;# Miscellaneous effects&#xD;&#xA;&#xD;&#xA;### Multiple diffuse reflections (colour bleeding)&#xD;&#xA;&#xD;&#xA;If a brightly coloured matt surface is near a white matt surface, the white surface will show some of the colour of the other surface. This can be modeled reasonably well using purely red, green and blue components. The same combination of red, green and blue that gave the colour of the coloured surface can reflect off the white surface and show some of that colour again. However, this only works if the second surface is white. If the second surface is also coloured, then the colour bleeding will be inaccurate, in some cases drastically.&#xD;&#xA;&#xD;&#xA;Imagine two surfaces that look a similar colour. One reflects a narrow range of wavelengths around yellow. The other reflects a wide range of wavelengths between red and green, and as a result also looks yellow. In real life, the light showing on one surface due to the other will not be symmetrical. Most of the light reaching the wide wavelength range surface from the other will be reflected again, as the narrow range of incoming wavelengths are all within the wider range. However, most of the light reaching the narrow wavelength range surface from the other will be outside the narrow range, and will not be reflected. In an RGB renderer, both surfaces will be modelled as a mixture of monochromatic red and monochromatic green, giving no difference in reflected light.&#xD;&#xA;&#xD;&#xA;This is an extreme example where the difference will be instantly noticeable to the eye, but there will be at least a subtle difference in most images that include colour bleeding.&#xD;&#xA;&#xD;&#xA;### Materials that absorb one wavelength and emit another&#xD;&#xA;&#xD;&#xA;[joojaa's answer] describes the absorption of ultraviolet light by snow, to be re-emitted as visible light. I hadn't heard of this happening with snow before (and frustratingly I've been unable to find any evidence to support it - although it would explain why snow is &quot;whiter than white&quot;). However, there is plenty of evidence of it happening with a wide range of other materials, some of which are added to clothes washing detergents and paper, to give extra bright whites. This allows the total visible light outgoing from a surface to be more than the total visible light received by that surface, which again is not modelled well using only RGB. If you want to read more about it, the term to search for is [Fluorescence].&#xD;&#xA;&#xD;&#xA;### Eyes with more than 3 primary colours&#xD;&#xA;&#xD;&#xA;There are animals that have more than 3 types of cones in their eyes, allowing them to perceive more than 3 primary colours. For example, many birds, insects and fish are [tetrachromats], perceiving four primary colours. Some are even [pentachromats], perceiving five. The range of colours that such creatures can see dwarfs the range displayable using only RGB. Far beyond them is the [mantis shrimp], which is a dodecachromat, seeing colours based on 12 different cones. None of these animals would be satisfied by an RGB display.&#xD;&#xA;&#xD;&#xA;But more seriously, even for images intended for human eyes, there are believed to be [human tetrachromats] who see in 4 primary colours, and possibly some who see as many as 5 or 6. At present, such people don't seem to be present in sufficient numbers to make displays with more than 3 primary colours commercially viable, but if in future it becomes easier to identify how many primary colours a person can see, this may become an attractive trait leading to it spreading throughout the population in future generations. So if you want your great grandchildren to appreciate your work you may need to make it compatible with a hexachromatic monitor...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*Not really relevant to this question, but related: If you want to see colours that are not available in either the real world* **or** *RGB images, have a look at [Chimerical Colours]...*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Benedikt Bitterli's answer]: https://computergraphics.stackexchange.com/a/204/231&#xD;&#xA;&#xD;&#xA;  [Iridescence]: http://en.wikipedia.org/wiki/Iridescence&#xD;&#xA;&#xD;&#xA;  [Lab]: http://en.wikipedia.org/wiki/Lab_color_space&#xD;&#xA;&#xD;&#xA;  [this paper]: http://www.babelcolor.com/download/A%20review%20of%20RGB%20color%20spaces.pdf&#xD;&#xA;&#xD;&#xA;  [cones sensitivities graph]: https://upload.wikimedia.org/wikipedia/commons/1/1e/Cones_SMJ2_E.svg&#xD;&#xA;&#xD;&#xA;  [cones sensitivities wikipedia location]: https://en.wikipedia.org/wiki/Spectral_sensitivity#/media/File:Cones_SMJ2_E.svg&#xD;&#xA;&#xD;&#xA;  [joojaa's answer]: https://computergraphics.stackexchange.com/a/207/231&#xD;&#xA;&#xD;&#xA;  [Fluorescence]: https://en.wikipedia.org/wiki/Fluorescence&#xD;&#xA;&#xD;&#xA;  [tetrachromats]: https://en.wikipedia.org/wiki/Tetrachromacy&#xD;&#xA;&#xD;&#xA;  [pentachromats]: https://en.wikipedia.org/wiki/Pentachromacy&#xD;&#xA;&#xD;&#xA;  [mantis shrimp]: https://en.wikipedia.org/wiki/Mantis_shrimp#Eyes&#xD;&#xA;&#xD;&#xA;  [human tetrachromats]:https://en.wikipedia.org/wiki/Tetrachromacy#Human_tetrachromats&#xD;&#xA;&#xD;&#xA;  [Chimerical Colours]: https://en.wikipedia.org/wiki/Impossible_color#Chimerical_colors&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13088" PostHistoryTypeId="5" PostId="273" RevisionGUID="047b1fbe-05b4-4f59-aa23-f0dfa25378dc" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I realized that littlecms, [suggested by _joojaa_ in a comment above][1] is very complete in dealing with the ICC profiles.&#xD;&#xA;&#xD;&#xA;I did a few tests in their color translator program with different destination color spaces and the differences are great as you can see:&#xD;&#xA;&#xD;&#xA;Original&#xD;&#xA;&#xD;&#xA;[![Original][2]][2]&#xD;&#xA;&#xD;&#xA;sRGB-like&#xD;&#xA;&#xD;&#xA;[![sRGB][3]][3]&#xD;&#xA;&#xD;&#xA;adobeRGB1998 (it seems it's the original color space)&#xD;&#xA;&#xD;&#xA;[![adobeRGB][4]][4]&#xD;&#xA;&#xD;&#xA;appleRGB&#xD;&#xA;&#xD;&#xA;[![apple][5]][5]&#xD;&#xA;&#xD;&#xA;And the most desirable results in my case are within the ProPhotoRGB color space:&#xD;&#xA;&#xD;&#xA;[![prophoto][6]][6]&#xD;&#xA;&#xD;&#xA;linearProPhotoRGB&#xD;&#xA;&#xD;&#xA;[![linearProPhoto][7]][7]&#xD;&#xA;&#xD;&#xA;All of the above were following an automatic _rendering intent_ but other _intents_ bring slight variations (samples applied together with linearProPhotoRGB destination color space):&#xD;&#xA;&#xD;&#xA;Absolute Colorimetric&#xD;&#xA;&#xD;&#xA;[![ICC absolute colorimetric][8]][8]&#xD;&#xA;&#xD;&#xA;Legacy Unadapted Absolute Colorimetric&#xD;&#xA;&#xD;&#xA;[![Legacy][9]][9]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I also realized that GIMP was actually restoring the original profile (not the opposite as I thought, i.e. instead of applying an embedded ICC profile, it was taking it off) and with this littlecms, now it does seem much simpler to &quot;translate&quot; color spaces than I thought.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/175/how-is-an-icc-profile-embedded-or-built-into-an-image#comment247_175&#xD;&#xA;  [2]: https://i.stack.imgur.com/xe6IM.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/NbIee.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/P7aGm.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/iAmh5.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/gp5GS.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/MIJk4.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/ik2TL.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/vUR7g.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13089" PostHistoryTypeId="5" PostId="277" RevisionGUID="b50ee6de-1c09-4c1c-a158-6cd8821b276c" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Applying multiple Gaussian blurs can result in an effect that is equivalent to a stronger Gaussian blur.&#xD;&#xA;&#xD;&#xA;For instance this question says that: https://computergraphics.stackexchange.com/questions/256/is-doing-multiple-gaussian-blurs-the-same-as-doing-one-larger-blur&#xD;&#xA;&#xD;&#xA;Wikipedia also says it, but says that it will always be just as many calculations or more to do it in multiple blurs versus doing it in a single blur.&#xD;&#xA;&#xD;&#xA;&gt; Applying multiple, successive gaussian blurs to an image has the same effect as applying a single, larger gaussian blur, whose radius is the square root of the sum of the squares of the blur radii that were actually applied. For example, applying successive gaussian blurs with radii of 6 and 8 gives the same results as applying a single gaussian blur of radius 10, since \sqrt{6^2 + 8^2} = 10. Because of this relationship, processing time cannot be saved by simulating a gaussian blur with successive, smaller blurs — the time required will be at least as great as performing the single large blur.&#xD;&#xA;&#xD;&#xA;Source: https://en.wikipedia.org/wiki/Gaussian_blur#Mechanics&#xD;&#xA;&#xD;&#xA;However, I've heard and read about people doing multiple blurs in realtime graphics to achieve a stronger blur.&#xD;&#xA;&#xD;&#xA;What benefit is there if it isn't a reduction in computation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13090" PostHistoryTypeId="5" PostId="278" RevisionGUID="daad0ef0-cb9e-4e39-b70d-08bbb9318b40" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Intuitively, dust settles onto surfaces at a higher rate in areas where the air flow is slower. This means instead of a surface gathering an even layer of dust, there will be more in corners - corners of a room/shelf, corners formed by the placement of objects on a surface, concavities in a surface.&#xD;&#xA;&#xD;&#xA;I can get an increase in realism simply by making the thickness/density of dust reduce with distance from an object, and combine that effect for several objects including walls. This naturally gives the expected ordering of thicknesses - the edges of a floor have more dust than the centre, the corners where the edges meet have more dust then the centre of the edges. However, the increase in realism from getting the order correct still leaves the problem of getting the ratio right. There is more dust in the places you expect to have more dust, but not necessarily the right amount more.&#xD;&#xA;&#xD;&#xA;Is there an established method of approximating a realistic ratio of thickness between different points on a surface? I don't need this to be completely physically accurate (that would need to take into account objects that move through the environment during the long period taken for dust to accumulate). I'm just looking for average behaviour that will look believable to the human eye.&#xD;&#xA;&#xD;&#xA;In searching online I've mostly found atmospheric models for suspended dust, rather than a way of modelling dust deposition on a surface.&#xD;&#xA;&#xD;&#xA;## My attempts - linear and exponential distributions&#xD;&#xA;Here is some code in Python 3 using pillow (the PIL fork) that demonstrates a couple of distributions I have experimented with:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;    &#xD;&#xA;    from PIL import Image&#xD;&#xA;    from math import exp&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def linear(distance, scale):&#xD;&#xA;        return max(0, 64 - distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def exponential(distance, scale):&#xD;&#xA;        return 64 * exp(-distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def exponential_squared(distance, scale):&#xD;&#xA;        return 64 * exp(-distance * distance * scale)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def gamma_corrected(value):&#xD;&#xA;        corrected_value = int((value/255)**(1/2.2)*255)&#xD;&#xA;        return corrected_value&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def produce_image(image_size=(1024,1024),&#xD;&#xA;                      glasses=(((100,300),90),((300,300),110)),&#xD;&#xA;                      distribution=exponential,&#xD;&#xA;                      scale=0.1,&#xD;&#xA;                      background_level=0,&#xD;&#xA;                      gamma=2.2,&#xD;&#xA;                      filename='dusttest.png'&#xD;&#xA;                      ):&#xD;&#xA;        width, height = image_size&#xD;&#xA;        pixels = []&#xD;&#xA;        for y in range(height):&#xD;&#xA;            for x in range(width):&#xD;&#xA;                red, green, blue = pixel_value(x, y, image_size, glasses,&#xD;&#xA;                                               distribution, scale,&#xD;&#xA;                                               background_level&#xD;&#xA;                                               )&#xD;&#xA;                pixels.append((red, green, blue))&#xD;&#xA;    &#xD;&#xA;        image = Image.new('RGB', image_size, color=None)&#xD;&#xA;        image.putdata(pixels)&#xD;&#xA;        image.save(filename)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def pixel_value(x, y, image_size, glasses, distribution, scale,&#xD;&#xA;                    background_level&#xD;&#xA;                    ):&#xD;&#xA;        width, height = image_size&#xD;&#xA;        value = background_level&#xD;&#xA;        value += distribution(x, scale)&#xD;&#xA;        value += distribution(width-x, scale)&#xD;&#xA;        value += distribution(y, scale)&#xD;&#xA;        for glass in glasses:&#xD;&#xA;            coords, radius = glass&#xD;&#xA;            a, b = coords&#xD;&#xA;            distance = ((x-a) ** 2 + (y-b) ** 2) ** 0.5 - radius&#xD;&#xA;            if distance &lt; 0:&#xD;&#xA;                value = 0&#xD;&#xA;                break&#xD;&#xA;            value += distribution(distance, scale)&#xD;&#xA;        value = 255 - gamma_corrected(value)&#xD;&#xA;        return ((value, value, value))&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;        for scale in [0.1, 0.2, 0.4, 0.8]:&#xD;&#xA;            produce_image(distribution=linear,&#xD;&#xA;                          scale=scale,&#xD;&#xA;                          background_level=20,&#xD;&#xA;                          filename='linear-' + str(scale) + '-dusttest.png'&#xD;&#xA;                          )&#xD;&#xA;        for scale in [0.1, 0.05, 0.03, 0.01]:&#xD;&#xA;            produce_image(distribution=exponential,&#xD;&#xA;                          scale=scale,&#xD;&#xA;                          background_level=0,&#xD;&#xA;                          filename='exponential-' + str(scale) + '-dusttest.png'&#xD;&#xA;                          )&#xD;&#xA;        for scale in [0.01, 0.001, 0.0001, 0.00001]:&#xD;&#xA;            produce_image(distribution=exponential_squared,&#xD;&#xA;                          scale=scale,&#xD;&#xA;                          background_level=0,&#xD;&#xA;                          filename='exponential-squared-' + str(scale) + '-dusttest.png'&#xD;&#xA;                          )&#xD;&#xA;&#xD;&#xA;Imagine looking down from above on a white shelf that has had drinking glasses placed on it. Some time later the glasses are removed to leave dust free circular regions and a distribution of dust over the rest of the shelf. The dust is affected by the positions of the glasses and the back and side walls. The front of the shelf (bottom of the image) is open, with no wall to increase dust.&#xD;&#xA;&#xD;&#xA;## Output&#xD;&#xA;&#xD;&#xA;*(Click for larger images)*&#xD;&#xA;&#xD;&#xA;**Linear reduction in dust density plus constant background level of dust:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][linear1m]][linear1]&#xD;&#xA;[![enter image description here][linear2m]][linear2]&#xD;&#xA;[![enter image description here][linear3m]][linear3]&#xD;&#xA;[![enter image description here][linear4m]][linear4]&#xD;&#xA;&#xD;&#xA;**Exponential reduction in dust density (zero background level):**&#xD;&#xA;&#xD;&#xA;[![enter image description here][exp1m]][exp1]&#xD;&#xA;[![enter image description here][exp2m]][exp2]&#xD;&#xA;[![enter image description here][exp3m]][exp3]&#xD;&#xA;[![enter image description here][exp4m]][exp4]&#xD;&#xA;&#xD;&#xA;I expected the exponential version to be closer to reality, and I prefer the result visually. However, I still don't know if this is close enough.&#xD;&#xA;&#xD;&#xA;**Following [Alan Wolfe]'s suggestion of the normal distribution, I've also added images using `exp(-distance ** 2)` at a variety of scales.**&#xD;&#xA;&#xD;&#xA;[![enter image description here][exp2_1m]][exp2_1]&#xD;&#xA;[![enter image description here][exp2_2m]][exp2_2]&#xD;&#xA;[![enter image description here][exp2_3m]][exp2_3]&#xD;&#xA;[![enter image description here][exp2_4m]][exp2_4]&#xD;&#xA;&#xD;&#xA;I quite like this too, but I still couldn't guess which of this and exponential (`exp(-distance)`) is best.&#xD;&#xA;&#xD;&#xA;I'm looking for feedback in two ways:&#xD;&#xA;&#xD;&#xA;1. Do any of these distributions look right/natural to you? I want input from a wider range of human eyes, ideally with specific problems/inconsistencies.&#xD;&#xA;1. Is there a physical interpretation that would justify using one of these distributions, or that would suggest a better one?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [linear1m]: https://i.stack.imgur.com/4FtgDm.png&#xD;&#xA;  [linear1]: https://i.stack.imgur.com/4FtgD.png&#xD;&#xA;  [linear2m]: https://i.stack.imgur.com/cnyaSm.png&#xD;&#xA;  [linear2]: https://i.stack.imgur.com/cnyaS.png&#xD;&#xA;  [linear3m]: https://i.stack.imgur.com/RXWlgm.png&#xD;&#xA;  [linear3]: https://i.stack.imgur.com/RXWlg.png&#xD;&#xA;  [linear4m]: https://i.stack.imgur.com/IgPu0m.png&#xD;&#xA;  [linear4]: https://i.stack.imgur.com/IgPu0.png&#xD;&#xA;  [exp1m]: https://i.stack.imgur.com/4Td7bm.png&#xD;&#xA;  [exp1]: https://i.stack.imgur.com/4Td7b.png&#xD;&#xA;  [exp2m]: https://i.stack.imgur.com/KUdEnm.png&#xD;&#xA;  [exp2]: https://i.stack.imgur.com/KUdEn.png&#xD;&#xA;  [exp3m]: https://i.stack.imgur.com/hbgk3m.png&#xD;&#xA;  [exp3]: https://i.stack.imgur.com/hbgk3.png&#xD;&#xA;  [exp4m]: https://i.stack.imgur.com/X29him.png&#xD;&#xA;  [exp4]: https://i.stack.imgur.com/X29hi.png&#xD;&#xA;  [exp2_1m]: https://i.stack.imgur.com/n1oOrm.png&#xD;&#xA;  [exp2_1]: https://i.stack.imgur.com/n1oOr.png&#xD;&#xA;  [exp2_2m]: https://i.stack.imgur.com/2SJD9m.png&#xD;&#xA;  [exp2_2]: https://i.stack.imgur.com/2SJD9.png&#xD;&#xA;  [exp2_3m]: https://i.stack.imgur.com/LVfCgm.png&#xD;&#xA;  [exp2_3]: https://i.stack.imgur.com/LVfCg.png&#xD;&#xA;  [exp2_4m]: https://i.stack.imgur.com/M0N8om.png&#xD;&#xA;  [exp2_4]: https://i.stack.imgur.com/M0N8o.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Alan Wolfe]: https://computergraphics.stackexchange.com/users/56/alan-wolfe" ContentLicense="CC BY-SA 3.0" />
  <row Id="13091" PostHistoryTypeId="5" PostId="287" RevisionGUID="a92ab680-6f6a-4f99-b7aa-151d52e9ca1d" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I understand how a 1D Fourier transform separates a signal into its component frequencies, but I'm having difficulty understanding how a 2D Fourier transform affects a 2D image.&#xD;&#xA;&#xD;&#xA;From [another question], [John Calsbeek] linked to an [interesting paper about measuring the quality of noise functions]. This showed various noise functions and the Fourier transform of each.&#xD;&#xA;&#xD;&#xA;Is this a discrete transform of the pixel data, or a continuous transform of the continuous interpolating function which is used to generate the noise at arbitrary points?&#xD;&#xA;&#xD;&#xA;Is the annular shape analagous to taking 1D Fourier transforms of the line through the centre of the image at every possible angle? Or is the transform for each possible angle also measured across the whole 2D space rather than only along a line through the centre? I'm trying to get an intuitive feel for what changes in the input image correspond to what changes in the Fourier transform.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [another question]: https://computergraphics.stackexchange.com/questions/283/is-all-grid-based-noise-inevitably-anisotropic &quot;Is all grid based noise inevitably anisotropic?&quot;&#xD;&#xA;&#xD;&#xA;  [John Calsbeek]: https://computergraphics.stackexchange.com/users/196/john-calsbeek&#xD;&#xA;&#xD;&#xA;  [interesting paper about measuring the quality of noise functions]: http://www.cs.utah.edu/~aek/research/noise.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13092" PostHistoryTypeId="5" PostId="291" RevisionGUID="b48c6b94-6aa1-43c3-9015-52d61d29d1f6" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="The following naïve approach will probably not yield as nicely distributed points as the [ones given by Lhf](https://computergraphics.stackexchange.com/a/251/394), but it should be much easier to implement and computationally faster:&#xD;&#xA;&#xD;&#xA;For two points $x$ and $y$ let $d(x,y)$ denote the average distance you want points with the average curvature of $x$ and $y$ to have, e.g., some constant multiplied with the inverse of the average curvature of $x$ and $y$.&#xD;&#xA;&#xD;&#xA;Now build up your collection of points $A$ successively:&#xD;&#xA;&#xD;&#xA;1. Select a random point $x$ and add two points, such that all three points form a equilateral triangle with edge length $d(x,x)$.&#xD;&#xA;&#xD;&#xA;2. Add all points to $A$ and mark them as adjacent.&#xD;&#xA;&#xD;&#xA;3. Repeatedly do the following until there are no adjacencies in $A$ anymore:&#xD;&#xA;&#xD;&#xA;  1. Select two adjacent points $x$ and $y$ from $A$. Mark them as non-adjacent.&#xD;&#xA;  1. Consider a point $z$ that has a distance of $d(x,y)$ from both these points. Of the two possible such points select the one pointing outwards of $A$ (this needs some work, but should be straightforward).&#xD;&#xA;  1. Check whether $z$ is closer than $d(x,y)$ to any point from $A$ that is still adjacent to another point.&#xD;&#xA;&#xD;&#xA;    * if yes, discard it.&#xD;&#xA;    * if no, mark $x$ and $z$ as well as $y$ and $z$ as adjacent and add $z$ to $A$.&#xD;&#xA;&#xD;&#xA;At the end, $A$ should be a collection of points matching your criteria. You sort-of just created a triangulation but it may be pathological and thus you should probably triangulate the points afresh." ContentLicense="CC BY-SA 3.0" />
  <row Id="13093" PostHistoryTypeId="5" PostId="342" RevisionGUID="4bfa5c84-8e2d-48b5-90ee-4d2a842ca9c7" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I thought of this after my [radiosity vs ray tracing question][1].&#xD;&#xA;&#xD;&#xA;A radiosity algorithm seems to require [increased calculations because it's viewpoint independent][2] and therefore, [false radiosity][3] was born (at least it's the way it was explained). It is mentioned that in order to simulate radiosity, changes were done directly in texture maps (in PS for example) or omni-type lights are placed where radiosity effects occur.&#xD;&#xA;&#xD;&#xA;I wonder if false radiosity is still used nowadays (I'm assuming this may happen more often in games development). If so, are these techniques currently used or are there others methods to achieve the same purpose? Any examples would be a plus.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/337/radiosity-vs-ray-tracing&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Radiosity_%28computer_graphics%29&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/False_radiosity" ContentLicense="CC BY-SA 3.0" />
  <row Id="13094" PostHistoryTypeId="5" PostId="351" RevisionGUID="28de9c9f-b6d8-427f-938d-c6eb9a2ddd7c" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="The short answer: They are not interchangeable, but their meaning can sometimes appear to overlap in computer graphics literature, giving the potential for confusion.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;***Albedo*** is the proportion of incident light that is reflected away from a surface.&#xD;&#xA;&#xD;&#xA;***Diffuse reflection*** is the reflection of light in many directions, rather than in just one direction like a mirror ([specular reflection]).&#xD;&#xA;&#xD;&#xA;In the case of ideal diffuse reflection ([Lambertian reflectance]), incident light is reflected in all directions independently of the angle at which it arrived. Since in computer graphics rendering literature there is sometimes a &quot;diffuse coefficient&quot; when calculating the colour of a pixel, which indicates the proportion of light reflected diffusely, there is an opportunity for confusion with the term *albedo*, which also means the proportion of light reflected.&#xD;&#xA;&#xD;&#xA;If you are rendering a material which only has ideal diffuse reflectance, then the albedo will be equal to the diffuse coefficient. However, in general a surface may reflect some light diffusely and other light specularly or in other direction-dependent ways, so that the diffuse coefficient is only a fraction of the albedo.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that [albedo] is a term from observation of planets, moons and other large scale bodies, and is an average over the surface, and often an average over time. The albedo is thus not a useful value in itself for rendering a surface, where you need the specific, current surface property at any given location on the surface. Also note that in astronomy the term albedo can refer to different parts of the spectrum in different contexts - it will not always be refering to human visible light.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Another difference, as [Nathan Reed] points out in a comment, is that albedo is a single average value, which gives you no colour information. For basic rendering the diffuse coefficient gives proportions for red, green and blue components separately, so albedo would only allow you to render greyscale images. For more realistic images, spectral rendering requires the reflectance of a surface as a function of the whole visible spectrum - far more than a single average value.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Nathan Reed]: https://computergraphics.stackexchange.com/users/48/nathan-reed&#xD;&#xA;&#xD;&#xA;  [albedo]: https://en.wikipedia.org/wiki/Albedo&#xD;&#xA;&#xD;&#xA;  [Lambertian reflectance]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;&#xD;&#xA;  [specular reflection]: https://en.wikipedia.org/wiki/Specular_reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="13095" PostHistoryTypeId="5" PostId="354" RevisionGUID="771eb0b6-bbff-434d-aeeb-15adae53f3fd" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I know GPU prefetches textures and that's why dependent texture reads are slower, but how does it work and at what point that happens?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;___________________________________________________&#xD;&#xA;EDIT: Split the content of this question into others as suggested by trichoplax&#xD;&#xA;Here's a link to other questions:&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/355/how-does-texture-cache-work-considering-multiple-shader-units&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/356/how-does-texture-cache-work-in-tile-based-rendering-gpu&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13096" PostHistoryTypeId="5" PostId="358" RevisionGUID="dea4da75-f004-405f-abb6-e82a153859f5" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In [Splitting of NURBS curves](https://computergraphics.stackexchange.com/questions/340/splitting-of-nurbs-curves) there the answer relied on &quot;maximum knot multiplicity&quot;. In order not to mix-up different topics I would like to kindly ask to answer it in another question: what is this &quot;knot multiplicity&quot; all about?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13097" PostHistoryTypeId="5" PostId="387" RevisionGUID="8083c699-796e-42e4-9e24-ccd6a5cbf702" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="[Ambient occlusion][1] &quot;is a shading and rendering technique used to calculate **how exposed** each point in a scene is **to ambient lighting**.&#xD;&#xA;&#xD;&#xA;Ambient lighting is regarding to https://computergraphics.stackexchange.com/questions/375/what-is-ambient-lighting/:&#xD;&#xA;&gt; ... lighting to be constant and independent from position: that's ambient&#xD;&#xA;&gt; lighting.&#xD;&#xA;&#xD;&#xA;If ambient lighting has no fixed position, how can points then be more or less **exposed** to it? Ambient lighting is &quot;[shining by a constant amount in all directions.][2]&quot; So if the light is coming from **all directions**, every point should be exposed by **the same factor** to the ambient lighting.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ambient_occlusion&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/a/380/480" ContentLicense="CC BY-SA 3.0" />
  <row Id="13098" PostHistoryTypeId="5" PostId="405" RevisionGUID="dd5d7710-46c8-4e68-a3db-a5f37f393a47" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In my answer about [Affine Transformations](https://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392) I made some little illustrations to help the explanation.&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Ltr0w.png)&#xD;&#xA;&#xD;&#xA;How do you make an upload-able PNG quickly which expresses a geometrical or mathematical idea?&#xD;&#xA;&#xD;&#xA;*This question was contrived to support [my postscript answer]() but is intended to solicit other solutions that may benefit the SE network more generally. But for credibility, an answer must link to a post where this technique has in fact been used, as well as a sufficient &quot;howto&quot; portion if it involves more than something obvious like &quot;Select export from menu&quot;.*&#xD;&#xA;&#xD;&#xA;*There are two meta questions [here](https://computergraphics.meta.stackexchange.com/questions/147/simple-2d-illustrations-question-main-or-meta) and [here](https://computergraphics.meta.stackexchange.com/questions/150/2d-illustrations-question-help-crafting-the-question) concerning how to scope this question in light of the precedences it may set for our site.*" ContentLicense="CC BY-SA 3.0" />
  <row Id="13099" PostHistoryTypeId="5" PostId="406" RevisionGUID="3bfed647-14aa-4326-9d35-f870fa5955d8" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="# PostScript+ps2eps+mogrify&#xD;&#xA;&#xD;&#xA;For the [Affine Transformations answer](https://computergraphics.stackexchange.com/questions/391/what-are-affine-transformations/392#392), I wrote a very small postscript program and then saved several copies under different names and edited each one to do each different task: scale, translate, rotate. For example, here's the basic one, `ident.ps` which does nothing to change the coordinates between the red drawing and the black drawing. I made the red lines a little larger and always draw it first, so the two show up nicely superposed and visible (IMO). I previewed with ghostscript with the vi (ex) command `:!gs %`. ([all source files](https://groups.google.com/d/topic/comp.lang.postscript/m2QqV4QFFaM/discussion))&#xD;&#xA;&#xD;&#xA;    %!&#xD;&#xA;    /axis {&#xD;&#xA;        currentpoint 4 { &#xD;&#xA;            2 copy moveto&#xD;&#xA;                50 0 lineto&#xD;&#xA;                90 rotate&#xD;&#xA;        } repeat pop pop &#xD;&#xA;    } def &#xD;&#xA;    /shape {&#xD;&#xA;        20 0 moveto&#xD;&#xA;        30 20 lineto&#xD;&#xA;        40 0 lineto&#xD;&#xA;        closepath&#xD;&#xA;    } def &#xD;&#xA;    &#xD;&#xA;    100 100 translate&#xD;&#xA;    &#xD;&#xA;    gsave&#xD;&#xA;    % do transform here&#xD;&#xA;    currentlinewidth 1.5 mul setlinewidth&#xD;&#xA;    1 0 0 setrgbcolor&#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    grestore&#xD;&#xA;    &#xD;&#xA;    0 0 moveto axis shape stroke&#xD;&#xA;    &#xD;&#xA;    showpage&#xD;&#xA;&#xD;&#xA;I then used the `ps2eps` command from `psutils` to calculate bounding-boxes automatically&#xD;&#xA;&#xD;&#xA;    $ ps2eps -f *.ps&#xD;&#xA;    Input files: ident.ps rotate.ps scale.ps skewx.ps skewy.ps translate.ps&#xD;&#xA;    Processing: ident.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file ident.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: rotate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 150 150&#xD;&#xA;    Creating output file rotate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: scale.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 25 25 175 175&#xD;&#xA;    Creating output file scale.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewx.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 49 150 151&#xD;&#xA;    Creating output file skewx.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: skewy.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 49 50 151 150&#xD;&#xA;    Creating output file skewy.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;    Processing: translate.ps&#xD;&#xA;    Calculating Bounding Box...ready. %%BoundingBox: 50 50 165 165&#xD;&#xA;    Creating output file translate.eps ... ** Warning **: Weird heading line -- %! -- ready.&#xD;&#xA;&#xD;&#xA;And finally used imagemagick's `convert` command to produce cropped png images. (I didn't think of a quick way to automate this part. *Edit:* as commented, this can be done with `mogrify -format png *.eps`. Thanks, joojaa!)&#xD;&#xA;&#xD;&#xA;    $ convert ident.eps ident.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert scale.eps scale.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert rotate.eps rotate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewx.eps skewx.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert translate.eps translate.png&#xD;&#xA;    &#xD;&#xA;    josh@cadabra ~/affine&#xD;&#xA;    $ convert skewy.eps skewy.png&#xD;&#xA;&#xD;&#xA;Which produces PNGs, ready to upload.&#xD;&#xA;&#xD;&#xA;    $ ls -l *.png&#xD;&#xA;    -rw-r--r-- 1 josh None  587 Sep  1 21:16 ident.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1431 Sep  1 21:21 rotate.png&#xD;&#xA;    -rw-r--r-- 1 josh None  798 Sep  1 21:19 scale.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1133 Sep  1 21:22 skewx.png&#xD;&#xA;    -rw-r--r-- 1 josh None 1197 Sep  1 21:23 skewy.png&#xD;&#xA;    -rw-r--r-- 1 josh None  756 Sep  1 21:23 translate.png&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/gyZCZ.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13100" PostHistoryTypeId="5" PostId="413" RevisionGUID="9e006632-f635-4401-b380-609460a435c6" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I just use Powerpoint to make such diagrams and it works great as soon as you're comfortable with its basic primitives. It supports all simple operations like rotation, translation, etc. and recent revisions also have shear and 3D transforms. Examples:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here is an [example of a Powerpoint diagram][3] I made for an answer.&#xD;&#xA;&#xD;&#xA;For more complicated diagrams, especially in 3D, I sometimes use Blender with shadeless materials. I can elaborate and show examples if it is relevant to your question.&#xD;&#xA;&#xD;&#xA;Looks like [jsfiddle][4] is also popular around here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Hzmcd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ESDaY.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/1487/14&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/questions/324/is-this-smaller-grid-for-poisson-disc-sampling-still-correct" ContentLicense="CC BY-SA 3.0" />
  <row Id="13101" PostHistoryTypeId="5" PostId="418" RevisionGUID="45cfcdef-5d9b-4b1b-a012-3ce91622e8cd" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](https://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](https://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](https://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](https://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](https://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside a table [as per](http://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="13102" PostHistoryTypeId="5" PostId="429" RevisionGUID="40996708-0700-42d1-ba0c-65b1eb2decad" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I use a variety of tools depending on the particular needs of the moment. I have a bias toward free tools, as I don't have access to things like Illustrator or Mathematica.&#xD;&#xA;&#xD;&#xA;For general vector art purposes I use the free [Inkscape](https://inkscape.org/en/). It operates on .svg files and can also render them out as high-quality .pngs or other bitmap formats. For example, here's a diagram I made in Inkscape [to explain UV mapping](https://gamedev.stackexchange.com/questions/22103/confusion-with-the-texture-coordinate-system-in-xna):&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/t99e7.png)&#xD;&#xA;&#xD;&#xA;For 2D function graphs, I often use the online graphing calculator [Desmos](https://www.desmos.com/), which has the handy capability of letting you share graphs online so others can view and modify them. You can also create sliders that can be varied to play with curve parameters in real time. For example, here is a [configurable sharpening function](https://www.desmos.com/calculator/id7k8wn7ud).&#xD;&#xA;&#xD;&#xA;For more complex graphing tasks that involve a bit of programming, I use [Maxima](http://maxima.sourceforge.net/), a free computer algebra system that also has graphing features. I used Maxima to create the graphs in [this answer about Gaussian blurs](https://computergraphics.stackexchange.com/a/289/48):&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/ugYom.png)&#xD;&#xA;&#xD;&#xA;This was a bit too complex for Desmos, since it involved programmatically creating a piecewise approximation of a Gaussian.&#xD;&#xA;&#xD;&#xA;For really odd graphing tasks that aren't handled well by anything else, I've used Python with the [svgwrite](https://pypi.python.org/pypi/svgwrite/) package to programmatically generate diagrams into .svg files. These can then be touched up in Inkscape if desired and rendered to bitmaps using Inkscape or ImageMagick. I used that workflow to create the images in [this blog post on depth precision](http://www.reedbeta.com/blog/2015/07/03/depth-precision-visualized/), like this:&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/MVLUh.png)&#xD;&#xA;&#xD;&#xA;In this case I wanted to not only graph a function, but place tick marks programmatically and nonuniformly along both the axes and the graph, to illustrate discrete depth buffer values.&#xD;&#xA;&#xD;&#xA;And finally, if nothing else suffices, I'll use Python with [numpy](http://www.numpy.org/) and [pillow](https://python-pillow.github.io/) to render images pixel-by-pixel. That's how I created the Perlin noise images in [this answer](https://computergraphics.stackexchange.com/a/252/48) (with the help of the [noise](https://pypi.python.org/pypi/noise/) package too, in this case).&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Micts.png)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13103" PostHistoryTypeId="5" PostId="1434" RevisionGUID="69954e16-1d02-4aaf-95cc-45668cd85f4a" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In the style of [trichoplax' question][1], I want to talk about yet another Wikipedia article: [Radiosity (computer graphics)][2]. The article states:&#xD;&#xA;&gt;Radiosity is viewpoint independent, which increases the calculations involved, but makes them useful for all viewpoints.&#xD;&#xA;&#xD;&#xA;The technique works with diffuse surfaces only. This way, form factors can be precalculated and are independent of the viewer. The lighting needs to be updated only if some light source changed. If, on the other hand, the technique would support specular reflection, the form factors would depend on the viewer. Form factors and lighting would need to be updated constantly when the camera moves.&#xD;&#xA;&#xD;&#xA;How does the limitation to diffuse surfaces *increase* calculations? Diffuse surfaces need to take light from all directions into account, which is more complex than taking light only from a smaller specular lobe. Is this what this sentence means? Is it just me or should this be rephrased?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/361/is-this-a-mistake-in-the-wikipedia-article-for-lambertian-reflectance&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Radiosity_%28computer_graphics%29" ContentLicense="CC BY-SA 3.0" />
  <row Id="13105" PostHistoryTypeId="5" PostId="1495" RevisionGUID="cc8fc26b-2867-4cac-ab92-918e4c20827f" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I first read [Alan's answer about video noise removal][1] which lead me to this question. I found later [some algorithms ideas][2] which capture motion in a similar way (frame comparison, as Alan described).&#xD;&#xA;&#xD;&#xA;And then I found this [&quot;motion detection: fast and robust algorithms&quot; paper][3] where they propose a hierarchical and conditional motion detection algorithm... I didn't read it throughly, but they seem to have isolated well all the objects in motion, since noise was almost completely removed (last image of the paper). However they say:&#xD;&#xA;&#xD;&#xA;&gt; As its complexity remains low, this algorithm is well suited for very&#xD;&#xA;&gt; light embedded systems. Future work will consider other difficult&#xD;&#xA;&gt; sequences with the presence of clutter like snow, rain or moving&#xD;&#xA;&gt; trees.&#xD;&#xA;&#xD;&#xA;What if my intention was actually use their &quot;morphological post-processing&quot; technique to remove the detection of small objects instead of &quot;stand-alone pixels&quot; (their size would be defined according to the frame resolution)? This paper was published in 2009 and I found [this related paper][4], also from 2009... Are there any newer updates on this or different techniques?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/401/157&#xD;&#xA;  [2]: http://www.codeproject.com/Articles/10248/Motion-Detection-Algorithms&#xD;&#xA;  [3]: http://perso.ensta-paristech.fr/~manzaner/Publis/icip09.pdf&#xD;&#xA;  [4]: http://link.springer.com/article/10.1007%2Fs11554-008-0096-7" ContentLicense="CC BY-SA 3.0" />
  <row Id="13106" PostHistoryTypeId="5" PostId="1556" RevisionGUID="253e3bb8-7f01-4000-a9b4-2d07b7d6d7df" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I've been trying to understand some of the [physical principles][1] behind light and material interaction lately. In his talk [Physics and Math of Shading][2], Naty Hoffman explains Fresnel reflectance and defines the characteristic specular color **F&lt;sub&gt;0&lt;/sub&gt;** of a material as the Fresnel reflectance at 0° incident light angle.&#xD;&#xA;&#xD;&#xA;On slide 65, **F&lt;sub&gt;0&lt;/sub&gt;** of gold is given as *1.022, 0.782, 0.344* (linear). Hoffman adds: &#xD;&#xA;&#xD;&#xA;&gt; its red channel value is greater than 1 (it’s outside sRGB gamut)&#xD;&#xA;&#xD;&#xA;All of this doesn't make too much sense to me. A value greater than 1 would mean that in the wavelengths contributing to the red channel, *more energy is reflected than is received*. Does this really happen, and if so, how and why?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In addition, here is a reflectance curve from [Wikipedia][3] for some materials including gold (Au). The curve is certainly high for red wavelengths around 600nm but does not seem to go over 100%.&#xD;&#xA;&#xD;&#xA;[![Reflectance (Au)][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/1513/how-physically-based-is-the-diffuse-and-specular-distinction&#xD;&#xA;  [2]: http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Reflectance&#xD;&#xA;  [4]: https://i.stack.imgur.com/P2Vwr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13107" PostHistoryTypeId="5" PostId="1569" RevisionGUID="f6d75a72-9d04-41b0-a893-27ddc9bb8a47" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="As mentioned in [this][1] answer, Physically-Based Rendering isn't a set number of things. It's a *concept*. It's akin to saying something is 'Environmentally Friendly'. There are many different techniques to be environmentally friendly *and* someone can implement those techniques to varying degrees. The same is for PBR.&#xD;&#xA;&#xD;&#xA;In the end, Physically Based Rendering is just that, based on Physics in some way, shape, or form. One of the most basic 'physical' rendering techniques I can think of is using [Lambert shading][2]. While you may say, &quot;Well that doesn't take into account specular light, or etc, etc. etc.&quot;, I agree. Lambert shading is a crude representation of the physics of light. But, pedantically, it *is* PBR, because it is based off the physical observation that light intensity decreases with viewing angle.&#xD;&#xA;&#xD;&#xA;A renderer can implement as many, or as few PBR techniques as they choose. Some can be very computationally expensive, others, quite cheap. They can also choose to enable or disable certain techniques for different targets. For example, UE4 has a different set of techniques for mobile games, than for high end PC games. &#xD;&#xA;&#xD;&#xA;Now, that all said, when today's modern renderers talk about being &quot;Physically-based&quot;, they are generally referring to using a modern BRDF, generally some form of [Cook-Torrance][3], and physically plausible inputs. Inputs being: materials with physically-plausible color values and lights with physically based intensity values. &#xD;&#xA;&#xD;&#xA;Using a modern BRDF can be very computationally expensive, but, there are many approximations that can make it more friendly.&#xD;&#xA;&#xD;&#xA;Using physically-plausible inputs is generally not that difficult to implement on the renderer side, rather it's more difficult for artists. IE. teaching them what the different material values mean, and what are physically plausible values. This can be a huge task, depending on your artists, as seen in the presentations [here][4], [here][5], and [here][6], for example. In my opinion, this is the hardest task in switching a studio.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;One last issue, as brought up by @NathanReed in the comments:&#xD;&#xA;&#xD;&#xA;Implementing a modern BRDF in the shader doesn't necessarily immediately make the rendering better. In many cases, it can make other parts of the pipeline a glaring issue. Below are some additional things that are important in getting the most out of a modern BRDF:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - HDR lights and doing all rendering calculations in HDR&#xD;&#xA; - Gamma correct rendering&#xD;&#xA; - Indirect lighting of some kind (skybox lighting, static environment probes, screen space reflections, etc)&#xD;&#xA;   - This is huge for metals. [Metals have no diffuse reflectance][7], so most of the surface of the metal will be black if you don't have indirect reflections&#xD;&#xA;   - This is also one of the more difficult things to get real-time, especially for dynamic scenes. &#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/1468/310&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lambertian_reflectance&#xD;&#xA;  [3]: http://ruh.li/GraphicsCookTorrance.html&#xD;&#xA;  [4]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [5]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf&#xD;&#xA;  [6]: http://www.slideshare.net/guerrillagames/lighting-of-killzone-shadow-fall&#xD;&#xA;  [7]: http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13108" PostHistoryTypeId="5" PostId="1621" RevisionGUID="476383c2-3942-470f-8834-25032b67df35" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="The hint with the perspective division was already [mentioned by ratchet freak](https://computergraphics.stackexchange.com/a/1607/127), but I'd like to add some explanation of how to come up with the solution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First of all, remember that homogenous coordinates add a fourth value $w$ to your 3D vector. For points in the 3D space, $w \neq 0$ holds and $[x, y, z, w] = [n*x, n*y, n*z, n*w]$ also holds for every $n$.&#xD;&#xA;&#xD;&#xA;Now the goal is to find a transformation matrix $T$, which solves&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    \begin{bmatrix} \frac{2}{x + y} \\ \frac{5y + z}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;= T \cdot &#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These are basically four equations, but having a look at the first row, being&#xD;&#xA;&#xD;&#xA;$$\frac{2}{x + y} = t_{11}\cdot x + t_{21}\cdot y + t_{31} \cdot z + t_{41}$$&#xD;&#xA;&#xD;&#xA;and trying to find values for the $t$s, you'll see that this is not possible without further restructuring. The main problems are the $x$ and $y$ in the denominator. But as we can make use of the fourth value in the vector, we can expand the $w$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{5y + z}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} \frac{2}{x + y} \\ \frac{2.5y + 0.5z}{x + y} \\ 3 \\ 1 \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the first step, I removed the factor of $2$ from the second values denominator, leading to every values denominator either being $1$ or $(x + y)$. In the second step, I made use of the above mentioned rule ($[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$), setting $n = (x + y)$, thus eliminating the denominator of the first two values.&#xD;&#xA;&#xD;&#xA;Now we've got&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} t_{11} &amp; t_{21} &amp; t_{31} &amp; t_{41}  \\ t_{12} &amp; t_{22} &amp; t_{32} &amp; t_{42} \\ t_{13} &amp; t_{23} &amp; t_{33} &amp; t_{43} \\ t_{14} &amp; t_{24} &amp; t_{34} &amp; t_{44} \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which is not that hard anymore.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix} 0  &amp;  0 &amp;   0  &amp;  2   \\ 0 &amp;  2.5 &amp; 0.5 &amp;  0 \\ 3 &amp;   3  &amp;  0 &amp;   0 \\ 1  &amp;  1  &amp;  0  &amp;  0 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;* Remember the advantage of homogenous coordinates $w$.&#xD;&#xA;* $[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$ is the key.&#xD;&#xA;* Push everything that's in the denominator to the $w$ coordinate." ContentLicense="CC BY-SA 3.0" />
  <row Id="13109" PostHistoryTypeId="5" PostId="1673" RevisionGUID="232287c1-316f-47cd-93ee-e46f4aabd511" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I had posted about this issue in a [previous question](https://computergraphics.stackexchange.com/questions/1663/incorrect-instanced-rendering), however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly. I said **somewhat** because the output is the following: &#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched and the last one's UV coords are wrong][1]][1]&#xD;&#xA;&#xD;&#xA;The middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background. So long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // VAO definition&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /*** VBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;VBO);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** Vertex Format ***/&#xD;&#xA;        //Position Vertex&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;        //Normal Vertex&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3)));&#xD;&#xA;        //Texture Coordinate Vertex&#xD;&#xA;        glEnableVertexAttribArray(2);&#xD;&#xA;        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3) * 2));&#xD;&#xA;    /*** EBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;EBO);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** SSBO ***/&#xD;&#xA;        glGenBuffers(1, &amp;SSBO);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Quad adding function&#xD;&#xA;    auto iter = std::find(quads.begin(), quads.end(), quad);&#xD;&#xA;&#xD;&#xA;    if(iter == quads.end())&#xD;&#xA;    {&#xD;&#xA;        quads.push_back(quad);&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;            vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;&#xD;&#xA;        GLuint start = (indices.empty()) ? 0 : indices[indices.size() - 1] + 1;&#xD;&#xA;&#xD;&#xA;        GLuint newIndices[] = {&#xD;&#xA;            start, start + 1, start + 2,&#xD;&#xA;            start, start + 2, start + 3&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;            indices.push_back(newIndices[i]);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;        instanceData.push_back(quad-&gt;data);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, SSBO, 0, sizeof(RenderingData) * quads.size());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    program-&gt;Use();&#xD;&#xA;&#xD;&#xA;    program-&gt;SetStorageBlock(&quot;RenderingData&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY, texture-&gt;GetTexture());&#xD;&#xA;    program-&gt;SetInteger(&quot;diffuseTextureArray&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;NOTE: I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?&#xD;&#xA;&#xD;&#xA;EDIT: I made a sample code which replicates the problem; it should render a green quad and a red quad, however, it just renders 2 red quads. Also, even if you try to change the second quads' attributes (even like placing all 0s), it'll still just render. Somehow only the first quads' vertices are getting read and used for each subsequent quad.&#xD;&#xA;&#xD;&#xA;**C++ code:**&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    #include &lt;string&gt;&#xD;&#xA;    #include &lt;sstream&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #define GLEW_STATIC&#xD;&#xA;    #include &quot;GL/glew.h&quot;&#xD;&#xA;    #include &quot;GLFW/glfw3.h&quot;&#xD;&#xA;    #include &lt;IL/il.h&gt;&#xD;&#xA;    #include &lt;IL/ilu.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;&#xD;&#xA;    struct Vertex{&#xD;&#xA;        glm::vec2 pos, tex;&#xD;&#xA;        glm::vec3 color;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Quad{&#xD;&#xA;        std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;        glm::mat4 model;&#xD;&#xA;    &#xD;&#xA;        Quad(glm::vec2 pos, glm::vec2 size, const std::vector&lt;Vertex&gt; &amp;v){&#xD;&#xA;            vertices = v;&#xD;&#xA;            model = glm::mat4();&#xD;&#xA;            model = glm::translate(model, glm::vec3(pos, 0.f));&#xD;&#xA;            model = glm::scale(model, glm::vec3(size, 1.f));&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    class Renderer{&#xD;&#xA;        private:&#xD;&#xA;            GLuint VAO, VBO, instanceVBO, EBO;&#xD;&#xA;            std::vector&lt;Quad*&gt; quads;&#xD;&#xA;            std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;            std::vector&lt;glm::mat4&gt; models;&#xD;&#xA;            std::vector&lt;GLuint&gt; indices;&#xD;&#xA;    &#xD;&#xA;        public:&#xD;&#xA;            Renderer(){&#xD;&#xA;                /*** VAO ***/&#xD;&#xA;                glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;                glBindVertexArray(VAO);&#xD;&#xA;                /*** Per-vertex VBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;VBO);&#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;                glEnableVertexAttribArray(0);   // Position&#xD;&#xA;                glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;                glEnableVertexAttribArray(1);   // Tex Coord&#xD;&#xA;                glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec2)));&#xD;&#xA;                glEnableVertexAttribArray(2);   // Color&#xD;&#xA;                glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec2) * 2));&#xD;&#xA;                /*** Per-instance VBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;instanceVBO);&#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;                glEnableVertexAttribArray(3);   // Model matrix - row1&#xD;&#xA;                glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), nullptr);&#xD;&#xA;                glVertexAttribDivisor(3, 1);&#xD;&#xA;                glEnableVertexAttribArray(4);   // Model matrix - row2&#xD;&#xA;                glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4)));&#xD;&#xA;                glVertexAttribDivisor(4, 1);&#xD;&#xA;                glEnableVertexAttribArray(5);   // Model matrix - row3&#xD;&#xA;                glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * 2));&#xD;&#xA;                glVertexAttribDivisor(5, 1);&#xD;&#xA;                glEnableVertexAttribArray(6);   // Model matrix - row4&#xD;&#xA;                glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * 3));&#xD;&#xA;                glVertexAttribDivisor(6, 1);&#xD;&#xA;                /*** EBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;EBO);&#xD;&#xA;                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;                glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;            }&#xD;&#xA;            ~Renderer(){&#xD;&#xA;                glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;                glDeleteBuffers(1, &amp;instanceVBO);&#xD;&#xA;                glDeleteBuffers(1, &amp;EBO);&#xD;&#xA;                glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;            }&#xD;&#xA;            void AddQuad(Quad *const quad){&#xD;&#xA;                quads.push_back(quad);&#xD;&#xA;    &#xD;&#xA;                for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;                    vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;    &#xD;&#xA;                models.push_back(quad-&gt;model);&#xD;&#xA;    &#xD;&#xA;                GLuint start = ((indices.empty()) ? 0 : indices[indices.size() - 1] + 1);&#xD;&#xA;    &#xD;&#xA;                GLuint newIndices[] = {&#xD;&#xA;                    start,  start + 1,  start + 2,&#xD;&#xA;                    start,  start + 3,  start + 2&#xD;&#xA;                };&#xD;&#xA;&#xD;&#xA;                for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;                    indices.push_back(newIndices[i]);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * quads.size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;            }&#xD;&#xA;            void Render(GLuint &amp;program){&#xD;&#xA;                glUseProgram(program);&#xD;&#xA;    &#xD;&#xA;                glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;            }&#xD;&#xA;            void CheckQuads(){&#xD;&#xA;                for(unsigned int i = 0; i &lt; quads.size(); i++)&#xD;&#xA;                {&#xD;&#xA;                    std::cout &lt;&lt; &quot;Quad n.&quot; &lt;&lt; i &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                    for(unsigned int j = 0; j &lt; 4; j++)&#xD;&#xA;                    {&#xD;&#xA;                        std::cout &lt;&lt; &quot;\tVert &quot; &lt;&lt; j &lt;&lt; &quot;:\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].pos.x &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].pos.y &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].tex.x &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].tex.y &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].color.r &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].color.g &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].color.b &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    GLuint GenerateShader(const std::string &amp;filename, GLenum shaderType)&#xD;&#xA;    {&#xD;&#xA;        GLuint shader;&#xD;&#xA;        std::ifstream file(filename.c_str());&#xD;&#xA;        std::stringstream ss;&#xD;&#xA;        ss &lt;&lt; file.rdbuf();&#xD;&#xA;        file.close();&#xD;&#xA;        const GLchar *source = ss.str().c_str();&#xD;&#xA;        shader = glCreateShader(shaderType);&#xD;&#xA;        glShaderSource(shader, 1, &amp;source, nullptr);&#xD;&#xA;        glCompileShader(shader);&#xD;&#xA;        return shader;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        /*** Window + Context ***/&#xD;&#xA;        glfwInit();&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;        GLFWwindow *window = glfwCreateWindow(640, 480, &quot;OpenGL Incorrect Rendering Test&quot;, nullptr, nullptr);&#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;        glewExperimental = GL_TRUE;&#xD;&#xA;        glewInit();&#xD;&#xA;        glViewport(0, 0, 640, 480);&#xD;&#xA;        glClearColor(0.f, 0.f, 0.f, 1.f);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projection = glm::ortho(0.f, 640.f, 480.f, 0.f, -1.f, 1.f);&#xD;&#xA;    &#xD;&#xA;        /*** Shader Program ***/&#xD;&#xA;        GLuint program = glCreateProgram();&#xD;&#xA;        glAttachShader(program, GenerateShader(&quot;vertex_shader.glsl&quot;, GL_VERTEX_SHADER));&#xD;&#xA;        glAttachShader(program, GenerateShader(&quot;fragment_shader.glsl&quot;, GL_FRAGMENT_SHADER));&#xD;&#xA;        glLinkProgram(program);&#xD;&#xA;    &#xD;&#xA;        glUseProgram(program);&#xD;&#xA;        glUniformMatrix4fv(glGetUniformLocation(program, &quot;projection&quot;), 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;        /*** Renderer ***/&#xD;&#xA;        Renderer *renderer = new Renderer();&#xD;&#xA;        // Quad 1&#xD;&#xA;        Vertex v1 = {glm::vec2(0.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v2 = {glm::vec2(1.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v3 = {glm::vec2(1.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v4 = {glm::vec2(0.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        renderer-&gt;AddQuad(new Quad(glm::vec2(300, 10), glm::vec2(150, 150), {v1, v2, v3, v4}));&#xD;&#xA;        // Quad 2&#xD;&#xA;        Vertex v5 = {glm::vec2(0.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v6 = {glm::vec2(1.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v7 = {glm::vec2(1.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v8 = {glm::vec2(0.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        renderer-&gt;AddQuad(new Quad(glm::vec2(30, 10), glm::vec2(150, 150), {v5, v6, v7, v8}));&#xD;&#xA;&#xD;&#xA;        while(!glfwWindowShouldClose(window))&#xD;&#xA;        {&#xD;&#xA;            glfwPollEvents();&#xD;&#xA;    &#xD;&#xA;            if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;                glfwSetWindowShouldClose(window, true);&#xD;&#xA;    &#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;            renderer-&gt;Render(program);&#xD;&#xA;    &#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        delete renderer;&#xD;&#xA;    &#xD;&#xA;        glfwDestroyWindow(window);&#xD;&#xA;        glfwTerminate();&#xD;&#xA;    &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**vertex_shader.glsl:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    layout (location = 0) in vec2 position;&#xD;&#xA;    layout (location = 1) in vec2 texCoord;&#xD;&#xA;    layout (location = 2) in vec3 color;&#xD;&#xA;    layout (location = 3) in mat4 model;&#xD;&#xA;    &#xD;&#xA;    out vec2 uv;&#xD;&#xA;    out vec3 col;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uv = texCoord;&#xD;&#xA;        col = color;&#xD;&#xA;    &#xD;&#xA;        gl_Position = projection * model * vec4(position, 0.f, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**fragment_shader.glsl:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    in vec2 uv;&#xD;&#xA;    in vec3 col;&#xD;&#xA;    out vec4 color;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        color = vec4(col, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ULWbw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13110" PostHistoryTypeId="5" PostId="1825" RevisionGUID="6b56e57d-dac7-4fcd-9266-de535558aa1f" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="As as far as I can tell Illustrator has 2 or 3 different rasterizer. The onscreen preview is also prone to the same gap artifacting as your show though its tuned to minimize the effect. Your post seems to imply that your interested in the &quot;*art optimized*&quot; output.&#xD;&#xA;&#xD;&#xA;[![Art optimized versus screen preview of illustrator][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The different render modes of illustrator. Art optimized on left and hinted on right. Note that hinted shows slight background through. I dont have the new CC version so i can not show the third.&#xD;&#xA;&#xD;&#xA;### How does art optimized work then&#xD;&#xA;&#xD;&#xA;Art optimized render mode is simply a un-antialiased image rendered at higher resolution, that has then been subjected to a **box filtering**. This is called super sampling which is costly. A box filter is simply the mean value of the samples in the box (pixel). This is indeed a similar technology as what the multi pixel filter used in your blender render uses. You can do the same thing manually and get same results. &#xD;&#xA;&#xD;&#xA;In fact the render you get form illustrator is not really good. Its rendered in nonlinear space and not corrected for and you can get better results by swapping to higher order filters and computing in linear color space. All multi sample methods exhibit the same correct rendering (given enough samples even mathematically correct).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Multi pixel filtering, on left illustrator native 'Art Optimized'. On right same image at 16x16 pixels with multi lobed [Lanczos filter in linear space](https://graphicdesign.stackexchange.com/questions/58162/how-to-draw-smooth-curved-shapes-in-illustrator/58175#58175). Make sure your zoom is 1:1.&#xD;&#xA;&#xD;&#xA;### The problem&#xD;&#xA;&#xD;&#xA;You have in fact come at terms with the real problem of current generation of onscreen renderers. They try to avoid multi sampling in favor for coverage calculation. But it simply can not work perfectly! Simply because alpha blend is:&#xD;&#xA;&#xD;&#xA;$$c_0= c_1*\alpha + c_2*(1-\alpha)$$&#xD;&#xA;&#xD;&#xA;When chained never reaches 0 when chained over semitransparent surfaces so background show trough. Also it does not know how the coverage is distributed so it will do it wrong. There's simply no way around this in a non-overlapping case like this. but if you allow the shapes overlap then the coverage calculation can be solved (See [here](https://graphicdesign.stackexchange.com/questions/47342/space-between-2-paths-illustrator)).&#xD;&#xA;&#xD;&#xA;**Other questions** You can get same result in any other engine by just simply multisampling a non-antialiased image. You can not get the effect in on screen renderings without doing the overlap trick because they optimize for speed. Does illustrator use 3D? New CC might depends on your interpretation of what 3D is. This issue has nothing to do with 3D just about signal reconstruction methods so its not applicable to the question really.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;* Related post [how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves](https://computergraphics.stackexchange.com/questions/148/how-do-i-accurately-compute-coverage-of-overlapping-analytical-curves/150#150)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tf7V4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EfM61.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13111" PostHistoryTypeId="5" PostId="1863" RevisionGUID="4f8c36e4-3999-4773-9e3d-86659710b622" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Deducing the angle and rotating by that angle works quite well in 2D (describe in [TLousky's post](https://computergraphics.stackexchange.com/a/1859/38)). This strategy, does not extend very well into three-dimensional realm. I will provide an alternative solution that shows a general strategy that works in a larger set of cases. As a bonus this without needing to think of trigonometry as it can be encoded away.&#xD;&#xA;&#xD;&#xA;1. First identify the vector that you want to be transformed to orientation in your reference space. Let us call this vector $\vec{a}$, or a along vector.&#xD;&#xA;&#xD;&#xA;2. Next you will need to identify a vector that is perpendicular to this vector. Let us call this vector $\vec{b}$, it is sometimes also called a up vector. In three-dimensions you need 3 vectors but once you identify 2 you can compute the third.&#xD;&#xA;&#xD;&#xA;  Finding out the $\vec{b}$ in 2-D realm is especially easy you could just rotate the vector by $90^{\circ}$ or simply swap the coordinates and make the x coordinate negative (see 1). Alternatively you can use the same procedure as in 3D.&#xD;&#xA;&#xD;&#xA;   $$\vec{b} = rotate(90^{\circ})\cdot\vec{a} =&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         \cos(\pi/2) &amp; -\sin(\pi/2) \\ &#xD;&#xA;         \sin(\pi/2) &amp; \cos(\pi/2) &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         x \\ &#xD;&#xA;         y &#xD;&#xA;      \end{bmatrix}&#xD;&#xA;         =       &#xD;&#xA;      \begin{bmatrix} &#xD;&#xA;         -y \\ &#xD;&#xA;         x &#xD;&#xA;      \end{bmatrix} &#xD;&#xA;     \tag{1}$$&#xD;&#xA;&#xD;&#xA;  In 3-D this usually requires a trick. Since each triangle is flat, one can use this to ones advantage. This gives us a perpendicular direction, now we still need a third one and we can get it by cross product of the 2 known vectors. You now have 3 vector.&#xD;&#xA;&#xD;&#xA;  [![enter image description here][1]][1]&#xD;&#xA;  &#xD;&#xA;  **Image 1**: Vector $\vec{a}$ and derived $\vec{b}$&#xD;&#xA;3. Normalize the vectors&#xD;&#xA;&#xD;&#xA;4. Use these vectors to produce a a rotation matrix (or a affine matrix wich allows you to specify point to be at zero, your choice). This matrix represents the local coordinate of the rotated object. &#xD;&#xA;&#xD;&#xA;5. All you now need is to invert this matrix and point matrix multiply your polygon corner vectors for a aligned version of the polygon.&#xD;&#xA;&#xD;&#xA;What is especially nifty is the sidestepping of trigonometrical operations. Now i see no point i defining basic matrix operations but i see value in code. So i will use numpy.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    import numpy as np, pylab&#xD;&#xA;&#xD;&#xA;    pts = np.array([&#xD;&#xA;            [0.,0.],[10.,1.],[12.,12.],[-2.,11.],[0.,0.]&#xD;&#xA;          ]).transpose()&#xD;&#xA;         &#xD;&#xA;    f = pylab.figure(facecolor=&quot;1.&quot;)     &#xD;&#xA;    pylab.axis('off')&#xD;&#xA;    pylab.axis('equal')&#xD;&#xA;    pylab.plot(pts[0], pts[1])  &#xD;&#xA;&#xD;&#xA;    # 1. Get the vector&#xD;&#xA;    vec_a = np.copy(pts[:,2]) - np.copy(pts[:,1])&#xD;&#xA;&#xD;&#xA;    # 2. up vector&#xD;&#xA;    vec_b = np.copy(vec_a[::-1])&#xD;&#xA;    vec_b[0] *= -1&#xD;&#xA;&#xD;&#xA;    # 3. normalize&#xD;&#xA;    vec_a /= np.linalg.norm(vec_a)&#xD;&#xA;    vec_b /= np.linalg.norm(vec_b)&#xD;&#xA;&#xD;&#xA;    # 4. build rotation matrix&#xD;&#xA;    mtx_R = np.concatenate(([vec_a], [vec_b])).transpose()&#xD;&#xA;    mtx_R = np.linalg.inv(mtx_R)&#xD;&#xA;&#xD;&#xA;    # 5. transform, or set hierarchy transform&#xD;&#xA;    pts2 = np.copy(pts)&#xD;&#xA;    for i in range(len(pts2[0])):&#xD;&#xA;        pts2[:,i] =  np.dot(mtx_R, pts2[:,i])&#xD;&#xA;&#xD;&#xA;    pylab.plot(pts2[0],pts2[1])&#xD;&#xA;    pylab.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I admit it cold be have slightly shorter by refactoring the code and eliminate redundant manipulations but its a demo only so... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Polygon, in blue axis fixed in green.&#xD;&#xA;&#xD;&#xA;Same method works well for straightening, skew and other problems such as perspective correction. You can extend this to affine matrices that way you can encode the translation into the calculation with just 1 more lines. In essence you specify what point is at origin and with 2 more operations one could define around what to rotate. Now it just just rotates about the origin.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BcxhU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xkgLB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13112" PostHistoryTypeId="5" PostId="1880" RevisionGUID="de35daab-3d7c-46a5-ad9c-d33d8e2455aa" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="TWO PART QUESTION - We've all seen the movies/TV shows where the police/feds/spies use computer software to take a grainy photo and do a &quot;clean-up&quot; to see a better picture and more details. I assume the concept is executed by some sort of **uber-power** pixel-smoothing or anti-aliasing type of algorithms to fill in the blanks based on deductive processing.&#xD;&#xA;&#xD;&#xA;PART 1: How *real* is this technology in the public/commercial software world? I'm not asking about any *speculation* on alleged secret gov software or such, I just want to know where we actually are with this concept today? How much is fully automated vs human-assisted. &#xD;&#xA;&#xD;&#xA;PART 2: Assuming there actually is *some* reality with this technology for photographs the second part of this question is how (if at all) has this been applied to videos? Again the issue of fully automated vs human assisted is of interest here.&#xD;&#xA;&#xD;&#xA;At the heart of this post is the ultimate question of how viable is today's software for being able to take an old VHS or DVD recording and process the frames to create a new HD-resolution remaster. Considering that doing this would mean cleaning up tens-of-thousands of frames for even a simple wedding video I am **not** expecting this technology to be fast of course.&#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;&#xD;&#xA;NOTE: Per in-topic and meta discussions I went ahead and cross-posted this in two other suggested SE forums to acquire their viewpoints and expertise on this matter. So far (it is still a little &quot;early in the day&quot; so to speak) I have received some pretty interesting information in 2 of the 3.&#xD;&#xA;&#xD;&#xA;When this is all done (when good answers have been selected) I would appreciate a way to merge these **for the benefit of all three SE communities**:&#xD;&#xA;&#xD;&#xA; - Computer Graphics: https://computergraphics.stackexchange.com/questions/1880&#xD;&#xA; - Signal Processing: https://dsp.stackexchange.com/questions/28168&#xD;&#xA; - Video Production: https://video.stackexchange.com/questions/17363" ContentLicense="CC BY-SA 3.0" />
  <row Id="13113" PostHistoryTypeId="5" PostId="1882" RevisionGUID="670378fd-99eb-4aac-b4f5-b61ecbe04315" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="This is a good solution. &#xD;&#xA;&#xD;&#xA;I just had a problem transforming `AxisVector` in screen coordinates, it turns out I must project two points from this vector on the screen, as explained in [this answer](https://computergraphics.stackexchange.com/a/1772/2173)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13114" PostHistoryTypeId="5" PostId="1931" RevisionGUID="89d1ee3e-3e6c-4235-96aa-511baab0a121" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In general, the idea of importance sampling is to distribute samples in a way that matches the function being integrated (or more practically, matching some factor in it). This reduces the variance of the output values, allowing the Monte Carlo integration to converge faster.&#xD;&#xA;&#xD;&#xA;In volume scattering, when a medium is homogeneous, we have the [Beer–Lambert law](https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law), which states that the transmittance falls off exponentially with depth. That's the source of factors like $e^{-\sigma x}$ in those equations. So when raymarching through a medium, the regions closer to the start of the ray generally contribute more light to the output, while the farther regions have more of their light absorbed along the way.&#xD;&#xA;&#xD;&#xA;So, if you sample points along the ray from an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution), the samples cluster toward the closer, more important regions. Then you just have to evaluate the scattering at those points and average over them.&#xD;&#xA;&#xD;&#xA;BTW, importance sampling in the context of *surface* scattering is explained pretty well by [this answer](https://computergraphics.stackexchange.com/a/1667/48) to another question.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;On your second question, &quot;where does single scattering fit into the general rendering equation?&quot;, well, it doesn't! What people call the &quot;general rendering equation&quot; actually only includes surface scattering, not volume scattering. So it's not really that &quot;general&quot;. A general rendering equation for volume scattering might look something like:&#xD;&#xA;&#xD;&#xA;$$ \nabla_\omega \, L(x, \omega) = \sigma_e(x) L_e(x, \omega) - \sigma_t(x) L(x, \omega) + \sigma_s(x) \int p(\omega, \omega') \, L(x, \omega') \, d\omega' $$&#xD;&#xA;&#xD;&#xA;This states that the derivative of radiance as you move along a ray is given by the sum of emitted light from the volume, minus extinction, plus in-scattering.&#xD;&#xA;&#xD;&#xA;To combine surface and volume scattering, we usually just say that the surface version of the equation applies at points on surfaces, and the volume version applies everywhere else." ContentLicense="CC BY-SA 3.0" />
  <row Id="13115" PostHistoryTypeId="5" PostId="2130" RevisionGUID="a807dbcb-4e3b-416d-9b61-3be65c728f18" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In ray tracing / path tracing, one of the simplest way to anti-alias the image is to supersample the pixel values and average the results. IE. instead of shooting every sample through the center of the pixel, you offset the samples by some amount.&#xD;&#xA;&#xD;&#xA;In searching around the internet, I've found two somewhat different methods to do this:&#xD;&#xA;&#xD;&#xA;1. Generate samples however you want and weigh the result with a filter&#xD;&#xA;  - One example is [PBRT][1]&#xD;&#xA;2. Generate the samples with a distribution equal to the shape of a filter&#xD;&#xA;  - Two examples are [smallpt][2] and [Benedikt Bitterli][3]'s [Tungsten Renderer][4] &#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate and Weigh**&#xD;&#xA;&#xD;&#xA;The basic process is:&#xD;&#xA;&#xD;&#xA;  1. Create samples however you want (randomly, stratified, low-discrepancy sequences, etc.) &#xD;&#xA;  2. Offset the camera ray using two samples (x and y)&#xD;&#xA;  3. Render the scene with the ray&#xD;&#xA;  4. Calculate a weight using a filter function and the distance of the sample in reference to the pixel center. For example, Box Filter, Tent Filter, Gaussian Filter, etc.)&#xD;&#xA;[![Filter Shapes][5]][5]&#xD;&#xA;  5. Apply the weight to the color from the render&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Generate in the shape of a filter**&#xD;&#xA;&#xD;&#xA;The basic premise is to use [Inverse Transform Sampling][6] to create samples that are distributed according to the shape of a filter. For example a histogram of a samples distributed in the shape of a Gaussian would be:&lt;br/&gt;&#xD;&#xA;[![Gaussian Histogram][7]][7]&#xD;&#xA;&#xD;&#xA;This can either be done exactly, or by binning the function into a discrete pdf/cdf. [smallpt][2] uses the exact inverse cdf of a tent filter. Examples of binning method can be found [here][8]&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;What are the pros and cons of each method? And why would you use one over the other? I can think of a few things:&#xD;&#xA;&#xD;&#xA;Generate and Weigh seems to be the most robust, allowing any combination of any sampling method with any filter. However, it requires you to track the weights in the ImageBuffer and then do a final resolve.&#xD;&#xA;&#xD;&#xA;Generate in the Shape of a Filter can only support positive filter shapes (ie. no Mitchell, Catmull Rom, or Lanczos), since you can not have a negative pdf. But, as mentioned above, it's easier to implement, since you don't need to track any weights.&#xD;&#xA;&#xD;&#xA;Though, in the end, I guess you can think of method 2 as a simplification of method 1, since it's essentially using an implicit Box Filter weight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/master/src/core/film.h#L114&#xD;&#xA;  [2]: http://www.kevinbeason.com/smallpt/&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/users/79/benedikt-bitterli&#xD;&#xA;  [4]: https://github.com/tunabrain/tungsten/blob/master/src/core/cameras/ReconstructionFilter.hpp&#xD;&#xA;  [5]: https://i.stack.imgur.com/gz7Bg.png&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Inverse_transform_sampling&#xD;&#xA;  [7]: https://i.stack.imgur.com/7pGFS.png&#xD;&#xA;  [8]: https://gist.github.com/RichieSams/ce2ca2a201227c1de543&#xD;&#xA;  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13116" PostHistoryTypeId="5" PostId="2233" RevisionGUID="9dc2975f-7641-40f1-b339-1066f41f43e9" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Just to add to [joojaa's answer](https://computergraphics.stackexchange.com/a/2232/), things *are* still being drawn pixel by pixel. You're just generating the pixels using a vertex shader/assembler/rasterizer, then texturing and lighting them using a fragment shader. This was all done in software in the 90's when your video card wasn't much more than a blitter and a frame buffer, but it was slow as hell. Hence the invention of modern GPUs. &#xD;&#xA;&#xD;&#xA;The drawing maths that's happening is basically the same as it was back in the Doom days, but now it's running on hundreds/thousands of shader ALUs rather than a handful of CPU cores. The APIs map down to basically the same set of GPU instructions behind the scenes. They're just there to stop you having to write a ton of gnarly GPU assembly across multiple vendor platforms." ContentLicense="CC BY-SA 3.0" />
  <row Id="13118" PostHistoryTypeId="5" PostId="2244" RevisionGUID="99c2796e-84c6-414b-ba2c-af1e2d84a117" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Well obviously nobody except the makers of this program can answer the exact algorithms used. I have done a quick explanation on each. Each separate task really deserves its own question and answer.&#xD;&#xA;&#xD;&#xA;Just iterate each polygon, for each vertex check if all of them are above the cut line eliminate the face. To make this check easy you can transom each vertex to the plane orientation. If not all vertices are above the cut line then the triangle is split along one of the edge that has a eliminated vertex. Then use the internal face closing algorithm. [Heres some math](http://geomalgorithms.com/a06-_intersect-2.html).&#xD;&#xA;&#xD;&#xA;Face closing algorithm works by finding open edges and then tessellating the new polygon closed. Please note: That this produces somewhat erratic results if the open holes are not planar. See [polygon triangulation](https://en.wikipedia.org/wiki/Polygon_triangulation)&#xD;&#xA;&#xD;&#xA;Simplifying planar regions is basically the same face closing algorithm except they you first build up polygons out of regions. Also decimation might come to play. There is a lot of lore, and different algorithms for simplification and going trough all of it its way too bread for a post like this. &#xD;&#xA;&#xD;&#xA;Self intersection is a sorting problem. Quite a bit of lore on this exists too. The one that i mostly do is putting the polygons one by one into a BSP self organizing tree and checking against polygons against items in that tree to reduce the check complexity to *n* log *n*. &#xD;&#xA;&#xD;&#xA;Internal cavities can be detected by splitting each mesh into shells and then for each shell check if the other shell is contained within each other. See [this post](https://computergraphics.stackexchange.com/questions/2208/model-separation-several-models-reside-in-a-single-stl-file/2209#2209)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13119" PostHistoryTypeId="5" PostId="2266" RevisionGUID="310cf79c-41bf-430a-9f55-1f6d89352525" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="What the video is talking about is called [gamma correction](https://en.wikipedia.org/wiki/Gamma_correction) and it's a very familiar topic for graphics programmers. The first 30 minutes of John Hable's [talk on Uncharted 2 rendering](http://www.gdcvault.com/play/1012351/Uncharted-2-HDR) is my favorite introduction to &quot;why graphics programmers should care about gamma&quot;, as well as being a good introduction to HDR rendering. If you don't want to watch the talk (though I highly recommend it), [The Importance of Being Linear](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html) is also a good article, and Charles Poynton has a [Gamma FAQ](http://www.poynton.com/notes/colour_and_gamma/GammaFAQ.html) that goes into more technical detail and explains the terminology used.&#xD;&#xA;&#xD;&#xA;By the way, square/squareroot is only an approximation; the [sRGB gamma curve](https://en.wikipedia.org/wiki/SRGB) is what's most commonly used in practice (see the formulas there mentioning $C_\text{srgb}$ and $C_\text{linear}$). See also [this related question](https://computergraphics.stackexchange.com/questions/68/is-gamma-still-important-to-take-into-account) about gamma and color spaces. It's a bit more complicated of a topic than the video makes it sound. :)&#xD;&#xA;&#xD;&#xA;To answer your specific questions:&#xD;&#xA;&#xD;&#xA;1. Yes, most image data is stored in gamma format, so the pixel values do _not_ represent linear luminance. I wouldn't describe it as &quot;incorrect&quot;, since gamma encoding has the useful property of putting more values in the darks, which is better for perceptual precision (as mentioned in the video). Gamma encoding is absolutely necessary to make good-looking images with only 8 bits per RGB component; if you stored linear values you would need more like 12 bits per component to get enough precision in the darks.&#xD;&#xA;&#xD;&#xA;2. To be more physically correct, when blurring an image, one should convert it to linear luminance, then do the blur (Gaussian or otherwise), then convert it back to the original color space.&#xD;&#xA;&#xD;&#xA;3. The monitor accepts image data in gamma format. So the pixel values do not represent linear luminance, and the output brightness is not linearly proportional to the pixel values.&#xD;&#xA;&#xD;&#xA; If it's a good-quality, calibrated monitor, then it accepts data in a specific color space such as sRGB or Adobe RGB and reproduces the colors accurately based on the definition of that color space. If it's a crap uncalibrated monitor, then who knows what you'll get, but it'll be something _kinda_ like sRGB.&#xD;&#xA;&#xD;&#xA;4. GPUs can be configured to do various things here. Modern GPUs have hardware support to automatically convert values between gamma and linear when sampling a texture, or storing a value out to the framebuffer, but the programmer has to explicitly enable that using an API such as Direct3D or OpenGL.&#xD;&#xA;&#xD;&#xA;5. Computer graphics people certainly do know about this topic, and it's critical to get it right when building a realistic renderer for film, AAA games, and so on. However, a lot of more &quot;everyday&quot; apps like web browsers and image editors (even Photoshop, as the video mentions) don't really handle gamma correctly.&#xD;&#xA;&#xD;&#xA; It's not an issue of processing power; maybe that was a problem 20 years ago, but today even mobile phones have ample processing power to convert images between gamma and linear. The reason why web browsers and image editors still don't get this right is some combination of (a) ignorance, (b) not believing that gamma is important enough to be worth getting right, and (c) simply being stuck with bad behavior because it's been that way for a long time and users have come to expect it, so they freak out if something changes.&#xD;&#xA;&#xD;&#xA;6. As mentioned, we have to think a lot about gamma when building a renderer. Most computations (e.g. lighting) should be done in linear space, but the input textures and output image should be in gamma space. Also, maybe some parts of rendering such as UI compositing should happen in gamma space because it's more familiar to artists (it works more like Photoshop layer compositing and such). Also, we have to decide if internal render targets are going to be stored in linear or gamma space, as it will affect precision. And we have to get all the conversions right, so that data gets converted between linear and gamma at the right spots in the rendering process." ContentLicense="CC BY-SA 3.0" />
  <row Id="13120" PostHistoryTypeId="5" PostId="2291" RevisionGUID="d0ae2ad9-2382-4f16-856d-fc4c47770082" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="## The problem appears to be unintentionally transparent surfaces&#xD;&#xA;&#xD;&#xA;Although the image is grainy, it is sufficiently clear to estimate that all of the darker regions are due to surfaces facing away from the light, rather than due to shadows cast onto surfaces facing towards the light. So it does seem that there is a problem, and the lack of shadows is not just due to having soft shadows from a large area light that don't show up well, or excessively reflective surfaces that provide too much ambient light. Somehow light is getting through your surfaces.&#xD;&#xA;&#xD;&#xA;## The probable source of this problem&#xD;&#xA;Since you check for intersection with the light and the objects separately, the crucial point where this could go wrong is where you check&#xD;&#xA;&#xD;&#xA;    if (distFromLight &lt; distFromObj)&#xD;&#xA;&#xD;&#xA;You correctly terminate the path and return the light colour if this check is true (that is, if the light is closer than the nearest object in that direction). So the problem is likely to be with one of the two variables you are comparing. If they were both correct, then you would see shadows.&#xD;&#xA;&#xD;&#xA;These are calculated on the preceding lines&#xD;&#xA;&#xD;&#xA;    float distFromObj = length(vert.p);&#xD;&#xA;    float distFromLight = length(hitLightPoint);&#xD;&#xA;&#xD;&#xA;As pointed out in [Julien Guertault's answer], these calculations may be redundant.&#xD;&#xA;&#xD;&#xA;`length(vert.p)` should still be available as `t`, used 11 lines previously in the calculation of `vert.p`. This not only avoids unnecessary calculation, but eliminates a potential source of error. Then this length is likely to be correct unless there is a problem with `checkIfRayIntersectSomething()`.&#xD;&#xA;&#xD;&#xA;This leaves only `length(hitLightPoint)` as a source of error, unless there is a more subtle problem. It would be useful to be able to eliminate the possibility of problems with `length()` or `hitLightPoint`, which is calculated by `checkRayLightIntersection()`.&#xD;&#xA;&#xD;&#xA;## We need to see the code to be able to help&#xD;&#xA;&#xD;&#xA;`length()`, `checkIfRayIntersectSomething()` and `checkRayLightIntersection()` are not currently included with the code in your question, so we can't analyse these. If you are able to share these that would help narrow down the source of the problem.&#xD;&#xA;&#xD;&#xA;## A simple way to check whether this is the real problem&#xD;&#xA;&#xD;&#xA;You could also verify whether this analysis of the problem is correct by rendering a scene which will eliminate the other possibilities (shadows too soft to distinguish, or shadows washed out by too much reflected light from the rest of the scene). If the light getting through the surfaces is the source of your problem, then it will apply even if there is no path from the light to a surface, provided that surface is facing the light. So render a simple scene that has a light with a plane beneath it, and another plane beneath that, separated by a gap big enough to easily be seen. The lower plane is completely occluded by the upper plane, so should receive no light (no soft shadows and no reflected light from elsewhere). If the lower plane is lit, then you know that this is indeed the problem and you can focus your efforts here.&#xD;&#xA;&#xD;&#xA;If the lower plane is *not* lit, then either this is not the problem, or there is a problem with the scale and the occluding plane may need to be at a different distance from the light in order for the problem to show up. You can use your existing scene as a source of estimated distances for which this problem occurs, and you can use inclined planes in order to see the effect for a variety of ratios of object distance to light distance within a single image.&#xD;&#xA;&#xD;&#xA;Sharing the images resulting from such simple scenes may help us identify the problem more precisely.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I notice that in a comment on the question you mention that you do not have a straightforward way of generating scenes yourself. Perhaps there are much simpler scenes already publicly available in the same file format, that you can use to test this?&#xD;&#xA;&#xD;&#xA;If not, it sounds like the only thing you have control over is the light. In that case, you could try putting the light underground. If surfaces are not transparent, the scene should be uniformly black. If surfaces are being lit despite an occluding surface, you may see evidence for it this way that would be hard to discern when there is lots of secondary light bouncing around.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Julien Guertault's answer]: https://computergraphics.stackexchange.com/a/2281/231" ContentLicense="CC BY-SA 3.0" />
  <row Id="13121" PostHistoryTypeId="5" PostId="2326" RevisionGUID="d988ea05-25d4-4685-8fd7-7b5deaa1ef4f" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I'm interested in virtual reality, but according to some sources, less than 1% of computers in use today have the necessary performance to run modern VR games, granted many of them are not intended for gaming, that's still a huge barrier for the widespread adoption of VR headsets into the market. So I was wondering what could be done to reduce the performance requirements of a VR game that hasn't been implemented with such optimizations in mind.&#xD;&#xA;&#xD;&#xA;I'm talking about technologies like foveated rendering, which (ab)uses the fact that we only ever perceive a few degrees in the center of our field of vision as sharp while everything else is blurry. This can be combined with eye tracking so that only the areas where the player is looking are rendered in full quality, while we can reduce the render quality and therefore the performance requirements everywhere else.&#xD;&#xA;This seems like a great advantage and I honestly wonder why none of the major VR companies have implemented eye tracking into their headsets and foveated rendering into their SDKs into their headsets. The technology exists and I can't imagine that it would add much to the price tag.&#xD;&#xA;[Paper about foveated rendering](http://research.microsoft.com/pubs/176610/foveated_final15.pdf)&#xD;&#xA;	&#xD;&#xA;There's also instanced stereo rendering which basically renders things to both eyes at the same time rather than rendering it for each eye individually.&#xD;&#xA;![Example gif for Instanced Stero Rendering - Epic Games, Unreal Engine 4.11 release notes](https://docs.unrealengine.com/latest/images/Support/Builds/ReleaseNotes/2016/4_11/image_16.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It's also possible to use just one frustum for both eyes rather than two as discussed here.&#xD;&#xA;[VR and frustum culling](https://computergraphics.stackexchange.com/questions/1736/vr-and-frustum-culling)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But are there other approaches to the performane problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13122" PostHistoryTypeId="5" PostId="2362" RevisionGUID="97461f43-5e5c-49cf-bd0b-afc64cdcd206" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Thanks for the [suggestions]. Now I am doing it as follows:&#xD;&#xA;&#xD;&#xA;First off it is identified if two line segments intersect or not. And I am using the algorithm described in the book - &quot;Introduction to Algorithms&quot; chapter 33 (Computational Geometry). &#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    int orientation(glm::i16vec2 &amp;p1,&#xD;&#xA;    				glm::i16vec2 &amp;p2,&#xD;&#xA;    				glm::i16vec2 &amp;p3)&#xD;&#xA;    {&#xD;&#xA;       return (((p3.x - p1.x) * (p2.y - p1.y)) - ((p2.x - p1.x) * (p3.y - p1.y)));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool onSegment(const glm::i16vec2 &amp;pi,&#xD;&#xA;    				 const glm::i16vec2 &amp;pj,&#xD;&#xA;    				 const glm::i16vec2 &amp;pk)&#xD;&#xA;    {&#xD;&#xA;    	if((std::min(pi.x,pj.x) &lt;= pk.x &amp;&amp; pk.x &lt;= std::max(pi.x,pj.x))  &amp;&amp;&#xD;&#xA;    	(std::min(pi.y,pj.y) &lt;= pk.y &amp;&amp; pk.y &lt;= std::max(pi.y,pj.y)))&#xD;&#xA;    		return true;&#xD;&#xA;    	else&#xD;&#xA;    		return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool intersects(const glm::i16vec2 &amp;p1,const glm::i16vec2 &amp;p2,&#xD;&#xA;                    const glm::i16vec2 &amp;p3,const glm::i16vec2 &amp;p4)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    	int d1 = orientation(p1,p2,p3);&#xD;&#xA;    	int d2 = orientation(p1,p2,p4);&#xD;&#xA;    	int d3 = orientation(p3,p4,p1);&#xD;&#xA;    	int d4 = orientation(p3,p4,p2);&#xD;&#xA;    &#xD;&#xA;    	if(((d1 &gt; 0 &amp;&amp; d2 &lt; 0) || (d1 &lt; 0 &amp;&amp; d2 &gt; 0)) &amp;&amp;&#xD;&#xA;    	    ((d3 &gt; 0 &amp;&amp; d4 &lt; 0) || (d3 &lt; 0 &amp;&amp; d4 &gt; 0)))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d1 == 0 &amp;&amp; onSegment(p3,p4,p1))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d2 == 0 &amp;&amp; onSegment(p3,p4,p2))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d3 == 0 &amp;&amp; onSegment(p1,p2,p3))&#xD;&#xA;              return true;&#xD;&#xA;    	else if(d4 == 0 &amp;&amp; onSegment(p1,p2,p4))&#xD;&#xA;              return true;&#xD;&#xA;    	else&#xD;&#xA;    		  return false;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	glm::i16vec2 hs(5,1);  // p1&#xD;&#xA;    	glm::i16vec2 he(5,3); // p2&#xD;&#xA;    &#xD;&#xA;    	glm::i16vec2 cs(5,1);   // p3&#xD;&#xA;    	glm::i16vec2 ce(5,3); // p4&#xD;&#xA;&#xD;&#xA;        if(intersects(hs,he,cs,ce))&#xD;&#xA;          std::cout &lt;&lt; &quot;It has intersection&quot; &lt;&lt; std::endl;&#xD;&#xA;        else&#xD;&#xA;          std::cout &lt;&lt; &quot;No intersection&quot; &lt;&lt; std::endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Once the boolean flag mentions that the intersection point is found, then the exact intersection point is extracted as follows:&#xD;&#xA;&#xD;&#xA;    short int getXIntersection(float x1,&#xD;&#xA;                               float y1,&#xD;&#xA;                               float x2,&#xD;&#xA;                               float y2,&#xD;&#xA;                               float yPos)&#xD;&#xA;    {&#xD;&#xA;        float t = (x2 - x1) / (y2 - y1);&#xD;&#xA;&#xD;&#xA;        float xDbl = (static_cast&lt;double&gt;(yPos) - y1) * t + x1;&#xD;&#xA;&#xD;&#xA;        return static_cast&lt;short int&gt;(std::floor(0.5+xDbl));&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;     &#xD;&#xA;The above function snippet is for the case when one of the line segments is parallel to the X-axis and the other segment is of arbitrary orientation.&#xD;&#xA;&#xD;&#xA;The other case is when one of the line segments is parallel to Y-axis and the other segment is of arbitrary orientation. For the sake of brevity, the code snippet is not written here. I hope you can imagine how it will be? Yet it is included in the following snippet as for some coordinate values I am having wrong output:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    short int getYIntersection(float x1,&#xD;&#xA;                               float y1,&#xD;&#xA;                               float x2,&#xD;&#xA;                               float y2,&#xD;&#xA;                               float xPos)&#xD;&#xA;    {&#xD;&#xA;        float t = (y2 - y1)/(x2 - x1);&#xD;&#xA;&#xD;&#xA;        float yDbl = (static_cast&lt;double&gt;(xPos) - x1) * t + y1;&#xD;&#xA;&#xD;&#xA;        return static_cast&lt;short int&gt;(std::floor(0.5+yDbl));&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;RECENT : Lets a line segment that is parallel to the Y-axis and it has the following coordinates as start and end point.&#xD;&#xA;&#xD;&#xA;hs(3124,-3168)&#xD;&#xA;he(3124,-3094)&#xD;&#xA;&#xD;&#xA;The other arbitrarily oriented line segment has the following coordinates:&#xD;&#xA;&#xD;&#xA;cs(3124,-3168)&#xD;&#xA;ce(3125,-3116)&#xD;&#xA;&#xD;&#xA;Since the line segment parallel to Y-axis has the constant X-value, should not the function getYIntersection() get the correct Y-value . But I am not getting it- instead I am getting -3213 as the Y-intersection value. Is there anything I am missing here ? The Y-value of the intersection must be within both the line segment, unfortunately it is not.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can you imagine any loop hole in this overall algorithm? In practice, I am getting some huge intersection point value that is way out of the region.&#xD;&#xA;The intersection point is saved as&#xD;&#xA;&#xD;&#xA;        short int&#xD;&#xA;&#xD;&#xA;And I am getting the  X-intersection value -32768. This value is way out of the bounding area where all the intersection points must lie within.&#xD;&#xA;&#xD;&#xA;Any thoughts?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After several comments and one answer , some adjustments is made within the code. It is found that with overlapping line segments the algorithm return true. It is not intended in my case, all overlapping line segments must not be flagged as intersection. Some hint would be nice. The issue of getting the intersection point is still in the pipeline. I believe that I missed the part that must be done after the initial true/false algorithm - that is to test if the calculated intersectin point lies within both the line segments or not. If it does, only then we eventually have the true intersection otherwise no intersection at all. &#xD;&#xA;&#xD;&#xA;Some feed-back would be great! &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [suggestions]: https://computergraphics.stackexchange.com/questions/2140/intersection-between-line-segments-narrowed-precondition&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13123" PostHistoryTypeId="5" PostId="2364" RevisionGUID="0e8203d2-ccf4-4aed-bda5-7b3c18705bf8" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I have implemented line segments [intersetion test][1] and at the very same test I want to include the fact that if two line segments overlap each other partially or fully , it will be flagged as no intersection.&#xD;&#xA;&#xD;&#xA;Some hint to it would be great to have!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/2362/line-segment-intersection-test-and-find-the-point-of-intersection" ContentLicense="CC BY-SA 3.0" />
  <row Id="13124" PostHistoryTypeId="5" PostId="2388" RevisionGUID="c42d35e8-98ae-49fb-92a8-b12f435a8615" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="@ratchetfreak's answer describes shadow mapping, however, there's another not so difficult to implement way of drawing hard shadows. The [*shadow volume*](https://en.wikipedia.org/wiki/Shadow_volume) technique uses extruded geometry plus some [stencil buffer](https://computergraphics.stackexchange.com/q/12/54) tricks to simulate the area occluded by an object. The idea behind it is to generate a volume from the light source's perspective and then render it as you would render other geometry. The resulting shadow geometry will be as accurate as your graphics hardware is capable of rendering it, so the shadows will be very clear cut. There's no simple way of producing soft shadow edges with this technique though.&#xD;&#xA;&#xD;&#xA;[![shadow volume][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sRO84.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13125" PostHistoryTypeId="5" PostId="2509" RevisionGUID="15be11ff-72ed-4c6f-aa6f-3cd57dfe448a" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Not all threads will execute in lockstep but they are split into groups whose threads are locked to each other.&#xD;&#xA;&#xD;&#xA;This means that if only 1 thread out of all threads enters a branch then only 1 group will need to enter that branch while all the others will skip it.&#xD;&#xA;&#xD;&#xA;In that group that has to execute both branches it will actually execute both branches but threads will throw away the result of the branch that it didn't need to go into.&#xD;&#xA;&#xD;&#xA;For more information [see this question][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/280/137" ContentLicense="CC BY-SA 3.0" />
  <row Id="13127" PostHistoryTypeId="5" PostId="3625" RevisionGUID="6fedb50f-352b-4dde-9fea-8d5c43b4effd" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I've finally managed to write the buffers myself using [JavaScript][1].&#xD;&#xA;&#xD;&#xA;The result is a base64 encoded String, like:&#xD;&#xA;&#xD;&#xA;    data:application/octet-stream;base64,AAACAAIABAAEAAAAAAABAAEABAB7g689dnGbPb1SFj1Q/Hg/vsF3P7hAAj3Qs3k/bcVuPw==&#xD;&#xA;&#xD;&#xA;If you paste this Data URI into the browser, you can download a binary blob which is exactly what the glTF files can use.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The 52 bytes in this case contain 10 indices of 2 bytes size (`U_SHORT`) and 8 vertices of 4 bytes size (`FLOAT`), so `10 * 2 B + 8 * 4 B = 52 B`.&#xD;&#xA;&#xD;&#xA;See [this post][3] to find out how I generated the buffer and see [this answer][4] on how to read the data again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jsfiddle.net/6cevt681/1/&#xD;&#xA;  [2]: https://i.stack.imgur.com/x2dxF.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/3624/361&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/3623/361" ContentLicense="CC BY-SA 3.0" />
  <row Id="13128" PostHistoryTypeId="5" PostId="3628" RevisionGUID="1e0a87b5-8728-436d-8b67-67783d90fe1c" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="After spending a hard time to understand the way [how the binary buffers work in the gltf files][1] I finally managed to generate a truely _minimal_ gltf file. It's a single yellow triangle ([demo][2]). &#xD;&#xA;&#xD;&#xA;[![minimal triangle][3]][3]&#xD;&#xA;&#xD;&#xA;I tried to remove everything which is not needed from the gltf. This is what is required it seems ([github][4]):&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;        &quot;accessors&quot;: {&#xD;&#xA;            &quot;accessor0&quot;: {&#xD;&#xA;                &quot;bufferView&quot;: &quot;bufferView0&quot;,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;componentType&quot;: 5123,&#xD;&#xA;                &quot;count&quot;: 3,&#xD;&#xA;                &quot;type&quot;: &quot;SCALAR&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;accessor1&quot;: {&#xD;&#xA;                &quot;bufferView&quot;: &quot;bufferView1&quot;,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;byteStride&quot;: 12,&#xD;&#xA;                &quot;componentType&quot;: 5126,&#xD;&#xA;                &quot;count&quot;: 3,&#xD;&#xA;                &quot;max&quot;: [&#xD;&#xA;                    0.5,&#xD;&#xA;                    0.5,&#xD;&#xA;                    0.5&#xD;&#xA;                ],&#xD;&#xA;                &quot;min&quot;: [&#xD;&#xA;                    0.0,&#xD;&#xA;                    0.0,&#xD;&#xA;                    0.0&#xD;&#xA;                ],&#xD;&#xA;                &quot;type&quot;: &quot;VEC3&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;asset&quot;: {&#xD;&#xA;            &quot;generator&quot;: &quot;5chdn&quot;,&#xD;&#xA;            &quot;profile&quot;: {&#xD;&#xA;                &quot;api&quot;: &quot;WebGL&quot;,&#xD;&#xA;                &quot;version&quot;: &quot;1.0.3&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;version&quot;: &quot;1.0&quot;,&#xD;&#xA;            &quot;extras&quot;: {&#xD;&#xA;                &quot;description&quot;: &quot;minimal gltf, single triangle&quot;,&#xD;&#xA;                &quot;base64encoder&quot;: &quot;https://jsfiddle.net/opkxy0xb/&quot;,&#xD;&#xA;                &quot;stackexchange&quot;: &quot;https://computergraphics.stackexchange.com/q/1934/361&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;bufferViews&quot;: {&#xD;&#xA;            &quot;bufferView0&quot;: {&#xD;&#xA;                &quot;buffer&quot;: &quot;Min&quot;,&#xD;&#xA;                &quot;byteLength&quot;: 6,&#xD;&#xA;                &quot;byteOffset&quot;: 0,&#xD;&#xA;                &quot;target&quot;: 34963&#xD;&#xA;            },&#xD;&#xA;            &quot;bufferView1&quot;: {&#xD;&#xA;                &quot;buffer&quot;: &quot;Min&quot;,&#xD;&#xA;                &quot;byteLength&quot;: 36,&#xD;&#xA;                &quot;byteOffset&quot;: 6,&#xD;&#xA;                &quot;target&quot;: 34962&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;buffers&quot;: {&#xD;&#xA;            &quot;Min&quot;: {&#xD;&#xA;                &quot;bytelength&quot;: 42,&#xD;&#xA;                &quot;type&quot;: &quot;arraybuffer&quot;,&#xD;&#xA;                &quot;uri&quot;: &quot;data:application/octet-stream;base64,AAABAAIArK34PnZxmz29UhY9T6+UPXuD7z64QAI9UWuaPW/wBT3ysPA+&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;materials&quot;: {&#xD;&#xA;            &quot;effect0&quot;: {&#xD;&#xA;                &quot;values&quot;: {&#xD;&#xA;                    &quot;emission&quot;: [&#xD;&#xA;                        0.8,&#xD;&#xA;                        0.8,&#xD;&#xA;                        0.0,&#xD;&#xA;                        1.0&#xD;&#xA;                    ]&#xD;&#xA;                },&#xD;&#xA;                &quot;technique&quot;: &quot;technique0&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;meshes&quot;: {&#xD;&#xA;            &quot;mesh0&quot;: {&#xD;&#xA;                &quot;name&quot;: &quot;Triangle&quot;,&#xD;&#xA;                &quot;primitives&quot;: [&#xD;&#xA;                    {&#xD;&#xA;                        &quot;attributes&quot;: {&#xD;&#xA;                            &quot;POSITION&quot;: &quot;accessor1&quot;&#xD;&#xA;                        },&#xD;&#xA;                        &quot;indices&quot;: &quot;accessor0&quot;,&#xD;&#xA;                        &quot;material&quot;: &quot;effect0&quot;,&#xD;&#xA;                        &quot;mode&quot;: 4&#xD;&#xA;                    }&#xD;&#xA;                ]&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;nodes&quot;: {&#xD;&#xA;            &quot;node0&quot;: {&#xD;&#xA;                &quot;matrix&quot;: [&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    0,&#xD;&#xA;                    1&#xD;&#xA;                ],&#xD;&#xA;                &quot;meshes&quot;: [&#xD;&#xA;                    &quot;mesh0&quot;&#xD;&#xA;                ],&#xD;&#xA;                &quot;name&quot;: &quot;TriangleMesh&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;programs&quot;: {&#xD;&#xA;            &quot;program0&quot;: {&#xD;&#xA;                &quot;attributes&quot;: [&#xD;&#xA;                    &quot;a_position&quot;&#xD;&#xA;                ],&#xD;&#xA;                &quot;fragmentShader&quot;: &quot;fragmentShader0&quot;,&#xD;&#xA;                &quot;vertexShader&quot;: &quot;vertexShader0&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;scenes&quot;: {&#xD;&#xA;            &quot;scene0&quot;: {&#xD;&#xA;                &quot;nodes&quot;: [&#xD;&#xA;                    &quot;node0&quot;&#xD;&#xA;                ]&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;shaders&quot;: {&#xD;&#xA;            &quot;vertexShader0&quot;: {&#xD;&#xA;                &quot;type&quot;: 35633,&#xD;&#xA;                &quot;uri&quot;: &quot;data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Ow0KdW5pZm9ybSBtYXQ0IHVfcHJvamVjdGlvbk1hdHJpeDsNCmF0dHJpYnV0ZSB2ZWMzIGFfcG9zaXRpb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX1Bvc2l0aW9uID0gdV9wcm9qZWN0aW9uTWF0cml4ICogdV9tb2RlbFZpZXdNYXRyaXggKiB2ZWM0KGFfcG9zaXRpb24sMS4wKTsNCn0=&quot;&#xD;&#xA;            },&#xD;&#xA;            &quot;fragmentShader0&quot;: {&#xD;&#xA;                &quot;type&quot;: 35632,&#xD;&#xA;                &quot;uri&quot;: &quot;data:text/plain;base64,cHJlY2lzaW9uIGhpZ2hwIGZsb2F0Ow0KdW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247DQp2b2lkIG1haW4odm9pZCkNCnsNCmdsX0ZyYWdDb2xvciA9IHVfZW1pc3Npb247DQp9&quot;&#xD;&#xA;            }&#xD;&#xA;        },&#xD;&#xA;        &quot;techniques&quot;: {&#xD;&#xA;            &quot;technique0&quot;: {&#xD;&#xA;                &quot;attributes&quot;: {&#xD;&#xA;                    &quot;a_position&quot;: &quot;position&quot;&#xD;&#xA;                },&#xD;&#xA;                &quot;parameters&quot;: {&#xD;&#xA;                    &quot;modelViewMatrix&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;MODELVIEW&quot;,&#xD;&#xA;                        &quot;type&quot;: 35676&#xD;&#xA;                    },&#xD;&#xA;                    &quot;projectionMatrix&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;PROJECTION&quot;,&#xD;&#xA;                        &quot;type&quot;: 35676&#xD;&#xA;                    },&#xD;&#xA;                    &quot;emission&quot;: {&#xD;&#xA;                        &quot;type&quot;: 35666&#xD;&#xA;                    },&#xD;&#xA;                    &quot;position&quot;: {&#xD;&#xA;                        &quot;semantic&quot;: &quot;POSITION&quot;,&#xD;&#xA;                        &quot;type&quot;: 35665&#xD;&#xA;                    }&#xD;&#xA;                },&#xD;&#xA;                &quot;program&quot;: &quot;program0&quot;,&#xD;&#xA;                &quot;states&quot;: {&#xD;&#xA;                    &quot;enable&quot;: [&#xD;&#xA;                        2884,&#xD;&#xA;                        2929&#xD;&#xA;                    ]&#xD;&#xA;                },&#xD;&#xA;                &quot;uniforms&quot;: {&#xD;&#xA;                    &quot;u_modelViewMatrix&quot;: &quot;modelViewMatrix&quot;,&#xD;&#xA;                    &quot;u_projectionMatrix&quot;: &quot;projectionMatrix&quot;,&#xD;&#xA;                    &quot;u_emission&quot;: &quot;emission&quot;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A good starting point was the [Appendix A of the gltf Specification][5] which defines a default material and shaders. All I had to do was adding the scene description and the buffers.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/3624/361&#xD;&#xA;  [2]: http://5chdn.github.io/gltf-tiles-loader-poc/&#xD;&#xA;  [3]: https://i.stack.imgur.com/kMZO0.png&#xD;&#xA;  [4]: https://github.com/5chdn/gltf-tiles-loader-poc/blob/8f25b30fed2324820e0a4a8958715fa2a424305d/data/Min/glTF-Embedded/Min.gltf&#xD;&#xA;  [5]: https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a" ContentLicense="CC BY-SA 3.0" />
  <row Id="13129" PostHistoryTypeId="5" PostId="3646" RevisionGUID="ce407967-81be-4214-b3e9-4983b667e294" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="With respect to [this topic ][1] I've successfully implemented the [Sobel Edge Detection][2] filter in GLSL. Here is the fragment shader code of the filter:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D screenTexture;&#xD;&#xA;&#xD;&#xA;    mat3 sx = mat3( &#xD;&#xA;	    1.0, 2.0, 1.0, &#xD;&#xA;	    0.0, 0.0, 0.0, &#xD;&#xA;	   -1.0, -2.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;    mat3 sy = mat3( &#xD;&#xA;	    1.0, 0.0, -1.0, &#xD;&#xA;	    2.0, 0.0, -2.0, &#xD;&#xA;	    1.0, 0.0, -1.0 &#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    vec3 diffuse = texture(screenTexture, TexCoords.st).rgb;&#xD;&#xA;        mat3 I;&#xD;&#xA;	    for (int i=0; i&lt;3; i++) {&#xD;&#xA;		    for (int j=0; j&lt;3; j++) {&#xD;&#xA;			    vec3 sample  = texelFetch(screenTexture, ivec2(gl_FragCoord) + ivec2(i-1,j-1), 0 ).rgb;&#xD;&#xA;			    I[i][j] = length(sample); &#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float gx = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]); &#xD;&#xA;	float gy = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);&#xD;&#xA;&#xD;&#xA;	float g = sqrt(pow(gx, 2.0)+pow(gy, 2.0));&#xD;&#xA;	color = vec4(diffuse - vec3(g), 1.0);&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And here is the result of a cube with Sobel edge detection:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cube with Sobel edge detection filter][3]][3]&#xD;&#xA;&#xD;&#xA;If you enlarge the picture, you will see that there is a lot of &quot;noise&quot; produced by Sobel: &#xD;&#xA;There are gray horizontal stripes all over the scene due to the blue/white gradient. Futhermore, the light cones produce an unwanted pattern on the cube. The black edges on the left of the cube also seem to fade because of the light cone on the left half of the cube.&#xD;&#xA;&#xD;&#xA;So I read [this article][4] which stated that one should grayscale the image first and use a Gaussian blur filter to make the edges more apparent. On the bottom of the article, there is also the canny edge detection filter which seem to produce better results.&#xD;&#xA;&#xD;&#xA;Now I have two questions:&#xD;&#xA;&#xD;&#xA; 1. Are the following steps correct to produce the best possible edge detection results:&#xD;&#xA;  - Grayscale&#xD;&#xA;  - Gaussian Blur&#xD;&#xA;  - Sobel/Canny edge detection&#xD;&#xA;&#xD;&#xA; 2. If yes, how would I merge the original image with the processed image? I mean, after processing the steps stated above, I get an image that is either completely black with white edges or vice verca. How would I put the edges on my original image/texture?&#xD;&#xA;&#xD;&#xA;Thanks for your help!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/2450/opengl-detection-of-edges&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Sobel_operator&#xD;&#xA;  [3]: https://i.stack.imgur.com/PawMD.png&#xD;&#xA;  [4]: https://www.objc.io/issues/21-camera-and-photos/gpu-accelerated-machine-vision/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13130" PostHistoryTypeId="5" PostId="3779" RevisionGUID="51c00095-5fa6-4608-8415-5d8d5de5f666" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="# Question #&#xD;&#xA;&#xD;&#xA;How to manage data (GPU,CPU) for dynamic label placement in 3d for thousands of objects (OpenGL)?&#xD;&#xA;&#xD;&#xA;# Details #&#xD;&#xA;objects:&#xD;&#xA;&#xD;&#xA; - **count:** 2k-10k&#xD;&#xA; - **type:** points/quads&#xD;&#xA;&#xD;&#xA;labels: &#xD;&#xA;&#xD;&#xA; - **bilboarding**&#xD;&#xA; - **data**: text and colors&#xD;&#xA;&#xD;&#xA;placing:&#xD;&#xA; &#xD;&#xA; - **labels are not overlaping**&#xD;&#xA;&#xD;&#xA;more on this in my another [question][1]&#xD;&#xA;&#xD;&#xA;# Elaboration #&#xD;&#xA;To calculate label placing I need screen space coordinates. There are lots of algorithms for the purpose, but I do not even know if they are implementable (w/o some hard hacking) on shaders since Vertex Shader has access to only one vertex. But with many objects calculating matrix multiplication (MVP * vertex position) for all vertexes so as to get screen-space coordinates on CPU-side and sending them each frame seems to be fairly slow and badly designed, imo. &#xD;&#xA;&#xD;&#xA;So, should I:&#xD;&#xA;&#xD;&#xA; - compute screen-space coordinates on CPU and send them to GPU so as to draw objects, compute label placing on CPU and send data to GPU&#xD;&#xA; - send only vertice's word coordinates and calculate screen space coordinates on GPU, then somehow implement label placing on GPU&#xD;&#xA; - Read the GPU-side calculated screen-side coordinates and compute on CPU&#xD;&#xA; - something different&#xD;&#xA;&#xD;&#xA;I know that it depends on the load on CPU/GPU from other things, but what do you think?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/3765/proper-architecture-for-rendering-history-of-stramed-data-points" ContentLicense="CC BY-SA 3.0" />
  <row Id="13131" PostHistoryTypeId="5" PostId="3922" RevisionGUID="c927faad-0585-498a-a4ec-9638996f0e1d" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Several other rendering paradigms exist aside from conventional rasterization of triangles using vertex and fragment shaders.&#xD;&#xA;&#xD;&#xA;* [Ray tracing](https://en.wikipedia.org/wiki/Ray_tracing_(graphics)) works by intersecting light rays with surfaces (triangle meshes, or more general surfaces: anything that can be tested for intersection) and then firing additional rays to gather information about lighting, shadows, reflections, etc at the intersection point. Path tracing and photon mapping are refinements of this concept.&#xD;&#xA;* [REYES rendering](https://en.wikipedia.org/wiki/Reyes_rendering) subdivides all primitives into micropolygons the size of a single pixel or smaller, calculates lighting and shading per micropolygon vertex, then uses a specialized rasterizing algorithm to render the micropolygons in screen space with motion blur and depth of field.&#xD;&#xA;* [Distance field ray-marching](http://iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm) (also called [sphere tracing](https://computergraphics.stackexchange.com/questions/161/what-is-ray-marching-is-sphere-tracing-the-same-thing)) represents all primitives in terms of distance fields: 3D functions and/or volumetric textures that give the distance from any given point to the nearest surface in any direction. The distance field is used to step adaptively along a ray until it hits a surface, and can also be used for lighting effects such as ambient occlusion.&#xD;&#xA;&#xD;&#xA;However, all rendering algorithms use linear transformation matrices. That's not part of the &quot;paradigm&quot; so much as it's the basic machinery for manipulating objects, the camera, etc in 3D space. It would be hard to do anything interesting without it." ContentLicense="CC BY-SA 3.0" />
  <row Id="13132" PostHistoryTypeId="5" PostId="3927" RevisionGUID="c86e51ed-1c75-42f9-a3ec-e50284eecca6" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="This is the same problem as the rotation about an axis. What you need is a matrix (any matrix) that satisfies the following corner constraint: one axis must point toward $(-2, 2, 0)$ in the case of a rotation this matrix must be a rotation matrix, in the case of a planar mirror it just has to span the 3D space. But since we know how to make an arbitrary rotation matrix we use the same approach.&#xD;&#xA;&#xD;&#xA;1. Pick any vector (u) that's not parallel to the normal (n)&#xD;&#xA;2. Take cross product of u and n for b&#xD;&#xA;3. Take cross product of n and b for a&#xD;&#xA;&#xD;&#xA;You now have an arbitrary rotation matrix with one axis defined using vectors n, b and a. Otherwise same as [the last question].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [the last question]: https://computergraphics.stackexchange.com/questions/3911/transformation-matrices" ContentLicense="CC BY-SA 3.0" />
  <row Id="13133" PostHistoryTypeId="5" PostId="3970" RevisionGUID="5e8b0e7a-ebad-4725-a941-d4c94d320294" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Suppose you have generated an image using linear values for RGB channels. E.g. you linearly interpolated it when doing blending, etc.. When you're going to present this on the screen, should the values be transformed as $C_{\mathrm{linear}}\to C_{\mathrm{sRGB}}$ as given [here](https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29) or backwards as described [here](https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation)?&#xD;&#xA;&#xD;&#xA;It would seem that the image should be encoded in sRGB, thus the forward transformation is necessary. But I've measured response of my monitor, and it appears that to have linearly changing brightness with input RGB, the color data have to be transformed as $C_{\mathrm{sRGB}}\to C_{\mathrm{linear}}$ as if my image were already in sRGB color space (the behavior is consistent with that described in [another question](https://computergraphics.stackexchange.com/q/1587/4647)).&#xD;&#xA;&#xD;&#xA;So is it correct that to render and present an image one has to do the following:&#xD;&#xA;&#xD;&#xA;1. Draw in linear RGB to have correct blending&#xD;&#xA;2. Treating the data _as if_ they were sRGB, convert to linear RGB&#xD;&#xA;3. Present on screen, so that monitor now converts this back&#xD;&#xA;&#xD;&#xA;Then the result will be linear as expected. Or am I missing something?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13134" PostHistoryTypeId="5" PostId="4013" RevisionGUID="e716a109-692b-45f4-bc23-cdb0e301a9f2" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="In graphics, it's common to take multiple samples within the bounds of a pixel and combine them together (most commonly just doing an average) for a final sample pixel color.  This has the effect of anti aliasing an image.&#xD;&#xA;&#xD;&#xA;On one hand this makes sense to me because what you are effectively doing is integrating the color of the pixel over the area that the pixel represents.  In this line of thinking, averaging &quot;random&quot; samples seems to be the ideal setup, for doing monte carlo integration.  (&quot;random&quot; could be stratified, blue noise based, low discrepency sequences etc)&#xD;&#xA;&#xD;&#xA;On the other hand, this feels wrong (or at least not as correct as it could be) from a digital signal processing point of view.  From that point of view, it feels like we are taking a lot of samples and then downsampling using a box filter (box blur) to get the final pixel value.  In that light, it seems like the ideal thing to do would be to use sinc filtering instead of averaging the samples.  I could see that the box filter is a cheaper aproximation to sinc thinking along these lines.&#xD;&#xA;&#xD;&#xA;This leaves me a bit confused.  Is the core idea that we are integrating the pixel area and averaging is correct?  Or is it that we are downsampling and should be using sinc, but are using a box filter because it's fast?&#xD;&#xA;&#xD;&#xA;Or is it something else entirely?&#xD;&#xA;&#xD;&#xA;A little bit related: https://computergraphics.stackexchange.com/questions/2130/anti-aliasing-filtering-in-ray-tracing&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13135" PostHistoryTypeId="5" PostId="4032" RevisionGUID="4c6cd77c-7955-49d4-ad5f-64daf612401f" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Computing the normal from vertex positions is quite simple using the vector cross product.&#xD;&#xA;&#xD;&#xA;The [cross product][1] of two vectors $u$ and $v$ (noted $u \times v$, or sometimes $u \wedge v$) is a vector perpendicular to $u$ and $v$, of length $||u \times v|| = ||u|| \cdot ||v|| sin(\theta)$, with $\theta$ the angle between $u$ and $v$. The direction of the vector will depend on the order of the multiplication: $u \times v$ is the opposite of $v \times u$ (the two directions perpendicular to the plane).&#xD;&#xA;&#xD;&#xA;If you are not familiar with the cross product, I invite you to read about it and get comfortable with it. Normals will then seem simple.&#xD;&#xA;&#xD;&#xA;#Flat shading normals&#xD;&#xA;&#xD;&#xA;If you have a triangle $ABC$, $AB \times AC$ is a vector perpendicular to the triangle and with a length proportional to its area. Since the normal is the unit vector perpendicular to the triangle's plane, you can get the normal with:&#xD;&#xA;&#xD;&#xA;$N = \dfrac{AB \times AC}{||AB \times AC||}$&#xD;&#xA;&#xD;&#xA;In code, this would look like `n = normalize(cross(b-a, c-a))` for example. Just apply this over all your faces and you will have your normals per face.&#xD;&#xA;&#xD;&#xA;    For each triangle ABC&#xD;&#xA;        n := normalize(cross(B-A, C-A))&#xD;&#xA;        A.n := n&#xD;&#xA;        B.n := n&#xD;&#xA;        C.n := n&#xD;&#xA;&#xD;&#xA;Note that this assumes vertices are not shared between triangles. I am not familiar with the Kinect API; it's quite possible that they are shared, in which case you would have to duplicate them, or move on to the next solution:&#xD;&#xA;&#xD;&#xA;#Smooth shading normals&#xD;&#xA;&#xD;&#xA;After lighting with normals computed as above, you will notice that triangle edges are apparent. If this in not desirable, you can compute smooth normals instead, by taking into account all the faces that share a same vertex.&#xD;&#xA;&#xD;&#xA;The idea is that if a same vertex is shared by three triangles $T1$, $T2$ and $T3$ for example, the normal $N$ will be the average of $N1$, $N2$ and $N3$. Moreover, if $T1$ is a big triangle and $T2$ is a tiny one, you probably want $N$ to be more influenced by $N1$ than by $N2$.&#xD;&#xA;&#xD;&#xA;Remember how the cross product is proportional to the area? If you add up the cross products then normalize the sum, it will do exactly the weighted sum we want. So the algorithm becomes:&#xD;&#xA;&#xD;&#xA;    For each vertex&#xD;&#xA;        vertex.n := (0, 0, 0)&#xD;&#xA;&#xD;&#xA;    For each triangle ABC&#xD;&#xA;        // compute the cross product and add it to each vertex&#xD;&#xA;        p := cross(B-A, C-A)&#xD;&#xA;        A.n += p&#xD;&#xA;        B.n += p&#xD;&#xA;        C.n += p&#xD;&#xA;&#xD;&#xA;    For each vertex&#xD;&#xA;        vertex.n := normalize(vertex.n)&#xD;&#xA;&#xD;&#xA;This technique is explained in longer detail this article by Iñigo Quilez: [clever normalization of a mesh][2].&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For more on normals, see also:&#xD;&#xA;&#xD;&#xA; * https://computergraphics.stackexchange.com/questions/1562/how-to-calculate-surface-normals-for-generated-geomtery/1576#1576&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cross_product&#xD;&#xA;  [2]: http://www.iquilezles.org/www/articles/normals/normals.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="13136" PostHistoryTypeId="5" PostId="4095" RevisionGUID="2d0a3649-8668-4c4a-8f10-0219dfa8502e" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Even though I didn't know about monte carlo path tracing when I wrote this, I accidentally described it.  Ironically, monte carlo path tracing is the answer I was looking for at the time.&#xD;&#xA;&#xD;&#xA;Naive monte carlo path tracing works by evaluating something called the rendering equation to numerically solve the color value of a pixel.  It takes random samples by randomly jittering within a pixel (there are better sampling strategies, and filtering: https://computergraphics.stackexchange.com/questions/4013/what-is-the-fundamental-reasoning-for-anti-aliasing-using-multiple-random-sample) and also by bouncing in random directions when a ray hits a surface.&#xD;&#xA;&#xD;&#xA;It can take a lot of samples to give you good results, and with not enough samples, your image will look noisy.  It takes 4 times as many samples to cut the noise in half.  Render times can be on the order of an hour using 8 modern CPU cores for a simple scene.&#xD;&#xA;&#xD;&#xA;There are more advanced monte carlo path tracing techniques that let you get better images more quickly, such as importance sampling, or denoising the image after it's rendered.&#xD;&#xA;&#xD;&#xA;Monte carlo path tracing can make photorealistic images and gives you many advanced rendering features just because it follows physical laws so gives realistic results.&#xD;&#xA;&#xD;&#xA;You can read more about it here:&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/&#xD;&#xA;&#xD;&#xA;Here is an example image, which took about an hour to render using all 8 of my cpu cores:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EacNQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13137" PostHistoryTypeId="5" PostId="4122" RevisionGUID="ffbf2a6b-07bb-450e-8c0c-f1028546b7e7" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I would like to address an issue in your naming. This issue makes the question a bit odd, but not impossible, as I will try to show.&#xD;&#xA;&#xD;&#xA;There is an, often unspoken, implied relationship between the matrices. For a matrix to be meaningful there has to be a common ancestor of the matrix that all matrices relate to. See a transformation chain works like a disk system or the root node of a XML document. There is always a base node, in computer graphics texts we choose to call this node **World**\*. Calling something else world is just defining your own definition of things.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The implied hierarchy of matrices, we have agreed to name the root **World**.&#xD;&#xA;&#xD;&#xA;Now there is assumed to be nothing outside the world. Although just like zeroes before numbers there is a possibility of infinite worlds within worlds, but those extra worlds do not participate in our model so they hardly matter.&#xD;&#xA;&#xD;&#xA;The hierarchy determines how the matrices interact with each other. All matrices are identity matrices ($I$) when viewed from inside the object. Therefore we have the following property for world:&#xD;&#xA;&#xD;&#xA;$$T_{world} = I.$$&#xD;&#xA;&#xD;&#xA;Anything else would imply that World is not World but rather an object as [@JarkkoL's answer](https://computergraphics.stackexchange.com/a/4119/38) implies, so there is yet another World outside what you call World. Also because world is the identity it can be omitted from your calculations, which is why it's sometimes left unnamed.&#xD;&#xA;&#xD;&#xA;Now it is obviously possible to name objects. This is smart as it makes talking about things easier. So you could call a bicycle object object &quot;bicycle&quot;, makes sense. In fact we do this by calling the camera, &quot;Camera&quot;. These names are arbitrary, so it is possible to call an object space World. But then the discussion just drops into confusion.&#xD;&#xA;&#xD;&#xA;Now we can address the confusion as your description is ambiguous. This is also is why you have problems reasoning about this. So either what you describe is like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Since you have renamed World we do not know what your relationship is. &#xD;&#xA;&#xD;&#xA;So by reinventing naming convention you have made the question confused. If you had not then there would be a really easy rule you would append the multiplication as normal as long as you move towards the world and inverted if you move away from the world.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* There are traditions where this is called the *Inertial frame*, *Reference Frame* and even sometimes rarely *Base*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lF8WK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysBhE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13139" PostHistoryTypeId="5" PostId="4254" RevisionGUID="0f391aff-f3b6-4ffe-97a7-f49c4877da48" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Raxvan is completely right that &quot;traditional&quot; anti aliasing techniques will work in raytracing, including those that use information such as depth to do antialiasing.  You could even do temporal anti aliasing in ray tracing for instance.&#xD;&#xA;&#xD;&#xA;Julien expanded on Raxvan's 2nd item which was an explanation of super sampling, and showed how you'd actually do that, also mentioning that you can randomize the location of the samples within the pixel but then you are entering signal processing country which is a lot deeper, and it definitely is!&#xD;&#xA;&#xD;&#xA;As Julien said, if you want to do $N$ samples per pixel, you can break the pixel up into $N$ evenly distributed sample points (on a grid basically) and average those samples.&#xD;&#xA;&#xD;&#xA;If you do that, you can still get aliasing though.  It is better than NOT doing it, because you are increasing your sampling rate, so will be able to handle higher frequency data (aka smaller details), but it can still cause aliasing.&#xD;&#xA;&#xD;&#xA;If you instead take $N$ random samples within a pixel, you are effectively trading aliasing for noise.  Noise is easier on the eyes and looks more natural than aliasing, so is the preferred result usually.  I believe it's even provably the ideal situation with higher sample counts but don't have more info on that ):&#xD;&#xA;&#xD;&#xA;When you use just &quot;regular&quot; random numbers like you'd get from rand() or std::uniform_int_distribution, that is called &quot;white noise&quot; because it contains all frequencies, like how white light is made up of all other colors (frequencies) of light.&#xD;&#xA;&#xD;&#xA;Using white noise to randomize the samples within a pixel has the problem that sometimes your samples will clump together.  For instance, if you average 100 samples in a pixel, but they ALL end up being in the upper left corner of the pixel, you aren't going to get ANY information about the other parts of the pixel, so your final resulting pixel color will be missing information about what color it should be.&#xD;&#xA;&#xD;&#xA;A better approach is to use something called blue noise which only contains high frequency components (like how blue light is high frequency light).&#xD;&#xA;&#xD;&#xA;The benefit of blue noise is that you get even coverage over the pixel, like you get with a uniform sampling grid, but, you still get some randomness, which turns aliasing into noise and gives you a better looking image.&#xD;&#xA;&#xD;&#xA;Unfortunately, blue noise can be very costly to compute, and the best methods all seem to be patented (what the heck?!), but one way to do this, invented by pixar (and patented too i think but not 100% sure) is to make an even grid of sample points, then randomly offset each sample point a small amount - like a random amount between plus or minus half the width and height of the sampling grid.  This way you get a sort of blue noise sampling for pretty cheap.&#xD;&#xA;&#xD;&#xA;Note that this is a form of stratified sampling, and poisson disk sampling is a form of that too, which is also a way of generating blue noise:&#xD;&#xA;https://www.jasondavies.com/poisson-disc/&#xD;&#xA;&#xD;&#xA;If you are interested in going deeper you probably will also want to check out this question and answer!&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/4013/what-is-the-fundamental-reasoning-for-anti-aliasing-using-multiple-random-sample&#xD;&#xA;&#xD;&#xA;Lastly, this stuff is starting to stray into the realm of monte carlo path tracing which is the common method for doing photorealistic raytracing.  if you are interested in learning more about that, give this a read!&#xD;&#xA;&#xD;&#xA;http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13140" PostHistoryTypeId="5" PostId="4264" RevisionGUID="96f91075-baf9-4999-bd2d-542b65fc3014" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="You're actually already doing color interpolation in the code you posted, in these expressions:&#xD;&#xA;&#xD;&#xA;    qRgb( 255-I, 255, 255-I )&#xD;&#xA;    qRgb(     I, 255,     I )&#xD;&#xA;&#xD;&#xA;The first one is interpolating from white to green by `I`, and the second one from green to white by `I`. In both cases `I` is acting as an integer form of the variable $\alpha$ from the equation. I note that you have already a fractional variable `I0` there, which is exactly what's needed for interpolation.&#xD;&#xA;&#xD;&#xA;So, if I rewrite your `qRgb` expressions a little bit, I can make them look closer to the form of the interpolation equation:&#xD;&#xA;&#xD;&#xA;    (1.0 - I0) * qRgb(255, 255, 255) + I0 * qRgb(0, 255, 0)&#xD;&#xA;    I0 * qRgb(255, 255, 255) + (1.0 - I0) * qRgb(0, 255, 0)&#xD;&#xA;&#xD;&#xA;This hopefully makes it clearer that $C_1$ is the color we're interpolating from, white, and $C_2$ is the color we're interpolating to, green. In the first line $\alpha$ is `I0` and in the second, $\alpha$ is `1.0 - I0`. Note that interpolating from white to green by `1.0 - I0` is equivalent to interpolating from green to white by `I0`.&#xD;&#xA;&#xD;&#xA;So, to make this work against an arbitrary colored background, you just have to change white to the actual background color of the pixel you're rasterizing to.&#xD;&#xA;&#xD;&#xA;Technically, [gamma correction](https://computergraphics.stackexchange.com/questions/2264/how-are-we-supposed-to-fix-brightness-with-square-roots) should also be applied when interpolating, but that's a relatively minor visual change that you can safely ignore for awhile." ContentLicense="CC BY-SA 3.0" />
  <row Id="13141" PostHistoryTypeId="5" PostId="4269" RevisionGUID="45effec0-69f1-4508-80bd-7a0956652d9e" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Made a new question as suggested, follow up to that [one][1].&#xD;&#xA;&#xD;&#xA;I was experimenting with texture declaration to find solution and thats how I done that before (`unsigned int`):&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_3D, m_texture);&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER, &#xD;&#xA;    GL_UNSIGNED_INT, NULL);&#xD;&#xA;    glGenerateMipap(GL_TEXTURE_3D);&#xD;&#xA;    &#xD;&#xA;    glGenSamplers(1, &amp;m_sampler);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And for that using `imagestore` for `int`/`unsigned int` didnt work despite correct binding for writing as `uimage` , `rgba32ui`, `uvec4` format and for reading as `usampler`, `uvec4` format. Of course also binding `sampler` object for reading.&#xD;&#xA;&#xD;&#xA;But I added two lines:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_3D, m_texture);&#xD;&#xA;    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32UI, width, height, depth, 0, GL_RGBA_INTEGER, &#xD;&#xA;    GL_UNSIGNED_INT, NULL);&#xD;&#xA;    &#xD;&#xA;    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); //&#xD;&#xA;    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); //&#xD;&#xA;    &#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_3D);&#xD;&#xA;    &#xD;&#xA;    glGenSamplers(1, &amp;m_sampler);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST );&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glSamplerParameteri(m_sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And now it seems to work. Still need to bind `sampler` thought. But I fail to see any logic in this. I use [sampler][2] objects to set texture filtering not `glTexParameteri` functions. &#xD;&#xA;&#xD;&#xA;`Float` textures work with `sampler` objects as in first block of code. Anyone can explain?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4197/setting-up-integer-texture-and-binding-as-image&#xD;&#xA;  [2]: https://www.opengl.org/wiki/Sampler_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="13142" PostHistoryTypeId="5" PostId="4294" RevisionGUID="43fb298f-03ca-4e38-9d49-ebefe3023cbf" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="To continue with [this](https://computergraphics.stackexchange.com/questions/4293/projected-points-and-screen-coordinates) my other question, here's the problem. So, I've a slide, which I'm trying to understand. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here are my questions.&#xD;&#xA;&#xD;&#xA;1. What are the barycentric coordinates of? From my previous question, $(x_1, y_1)$ and $(x_2, y_2)$ are also screen coordinates. So, we're interpolating between screen coordinates. Why would we do that?&#xD;&#xA;&#xD;&#xA;2. Why is $\lambda = \frac{x - x_1}{x_2 - x_1}$?&#xD;&#xA;&#xD;&#xA;3. Are $p_1$ and $p_2$ points given in global coordinates? That is, are they $3D$ points or screen points? &#xD;&#xA;&#xD;&#xA;4. Why is $\mu$ defined as it is?&#xD;&#xA;&#xD;&#xA;5. Why do we want to know $p^z$? By the way, what is it? A vector, right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UK1Ia.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13143" PostHistoryTypeId="5" PostId="4319" RevisionGUID="f7503fcd-dd1f-4883-8782-84e4a6d60ba2" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="While creating a set of glTF models for a tutorial, I also intended to create **THE** minimal glTF file. &#xD;&#xA;&#xD;&#xA;As already mentioned in the [answer by 5chdn](https://computergraphics.stackexchange.com/a/3628/1649), one issue may be the *material*. According to the [Appendix A: Default Material](https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a) of the specification, an asset that does not contain a material should be rendered with a *default* material that simply shows the object in a uniform, 50% gray color. &#xD;&#xA;&#xD;&#xA;Some viewers might not support this, and even if they do, there have been some minor subtleties in the spec regarding this point: In glTF 1.0, it was still necessary to define an &quot;empty&quot; material, because the `mesh.primitive.material` property was not yet optional. But this should be fixed in glTF 1.1. &#xD;&#xA;&#xD;&#xA;So the following should indeed be **THE** minimal possible glTF asset (version 1.1) :&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;      &quot;scenes&quot; : {&#xD;&#xA;        &quot;scene0&quot; : {&#xD;&#xA;          &quot;nodes&quot; : [ &quot;node0&quot; ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;nodes&quot; : {&#xD;&#xA;        &quot;node0&quot; : {&#xD;&#xA;          &quot;meshes&quot; : [ &quot;mesh0&quot; ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;    &#xD;&#xA;      &quot;meshes&quot; : {&#xD;&#xA;        &quot;mesh0&quot; : {&#xD;&#xA;          &quot;primitives&quot; : [ {&#xD;&#xA;            &quot;attributes&quot; : {&#xD;&#xA;              &quot;POSITION&quot; : &quot;positionsAccessor&quot;&#xD;&#xA;            }&#xD;&#xA;          } ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;    &#xD;&#xA;      &quot;buffers&quot; : {&#xD;&#xA;        &quot;buffer0&quot; : {&#xD;&#xA;          &quot;uri&quot; : &quot;data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA&quot;,&#xD;&#xA;          &quot;byteLength&quot; : 36&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;bufferViews&quot; : {&#xD;&#xA;        &quot;positionsBufferView&quot; : {&#xD;&#xA;          &quot;buffer&quot; : &quot;buffer0&quot;,&#xD;&#xA;          &quot;byteOffset&quot; : 0,&#xD;&#xA;          &quot;byteLength&quot; : 36,&#xD;&#xA;          &quot;target&quot; : 34962&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;accessors&quot; : {&#xD;&#xA;        &quot;positionsAccessor&quot; : {&#xD;&#xA;          &quot;bufferView&quot; : &quot;positionsBufferView&quot;,&#xD;&#xA;          &quot;byteOffset&quot; : 0,&#xD;&#xA;          &quot;componentType&quot; : 5126,&#xD;&#xA;          &quot;count&quot; : 3,&#xD;&#xA;          &quot;type&quot; : &quot;VEC3&quot;,&#xD;&#xA;          &quot;max&quot; : [ 1.0, 1.0, 0.0 ],&#xD;&#xA;          &quot;min&quot; : [ 0.0, 0.0, 0.0 ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &#xD;&#xA;      &quot;asset&quot; : {&#xD;&#xA;        &quot;version&quot; : &quot;1.1&quot;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It also shows a single triangle:&#xD;&#xA;&#xD;&#xA;[![TriangleWithoutIndices][1]][1]&#xD;&#xA;&#xD;&#xA;The version without embedded buffers is available at https://github.com/javagl/gltfTutorialModels , as well as a triangle with indices, at https://github.com/javagl/gltfTutorialModels/tree/master/Triangle &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ElVqk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13144" PostHistoryTypeId="5" PostId="4394" RevisionGUID="f7ab1768-e2a6-4a09-a1c6-c637ecc302c7" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="-- Sorry for the long post, but I prefer to do that way because &quot;*Devil is in the details.*&quot; :)&#xD;&#xA;&#xD;&#xA;I am writing a path tracer from the scratch and it is working nicely for perfectly diffuse (Lambertian) surfaces (*i.e.* the furnace test indicates - at least visually - that it is energy conserving, and rendered images match those generated with Mitsuba renderer for the same parameters). Now I am implementing the support for the specular term of the original Cook-Torrance microfacet model, in order to render some metallic surfaces. However, it seems that this BRDF is reflecting more energy than that received. See the example images below:&#xD;&#xA;&#xD;&#xA;[![Mitsuba reference image.][1]][1]&#xD;&#xA;&#xD;&#xA;Above image: *Mitsuba reference (assumed to be correct) image: Path tracing with direct light sampling, importance hemisphere sampling, max path lenght = 5, 32 stratified spp, box filter, surface roughness = 0.2, RGB.*&#xD;&#xA;&#xD;&#xA;[![Rendered image][2]][2]&#xD;&#xA;&#xD;&#xA;Above image: *Actual rendered image: Brute force naïve path tracing, uniform hemisphere sampling, max path lenght = 5, 4096 stratified spp, box filter, surface roughness = 0.2, RGB. Despite some differences with respect to the rendering settings, it is clear that the rendered image will not converge to the reference shown before.*&#xD;&#xA;&#xD;&#xA;I tend to think that it is not an implementation problem, but an issue regarding the proper use of the Cook-Torrance model within the rendering equation framework. Below I explain how I am evaluating the specular BRDF and I would like to know if I am doing it properly and, if not, why. &#xD;&#xA;&#xD;&#xA;Before going into the nitty-gritty details, notice that the renderer is quite simple: 1) implements only the brute force naïve path tracing algorithm - no direct light sampling, no bi-directional path tracing, no MLT; 2) all sampling is uniform on the hemisphere above the intersection point - no importance sampling at all, neither for diffuse surfaces; 3) the ray path has a fixed maximum length of 5 - no russian roulette; 4) radiance/reflectance is informed through RGB tuples - no spectral rendering.&#xD;&#xA;&#xD;&#xA;**Cook Torrance microfacet model**&#xD;&#xA;&#xD;&#xA;Now I will try to construct the path I've followed to implement the specular BRDF evaluation expression. Everything starts with the rendering equation&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;where $\textbf{p}$ is the intersection point at the surface, $\mathbf{w_o}$ is the viewing vector, $\mathbf{w_i}$ is the light vector, $L_o$ is the outgoing radiance along $\mathbf{w_o}$, $L_i$ is the radiance incident upon $\textbf{p}$ along $\mathbf{w_i}$ and $\cos \theta = \mathbf{n} \cdot \mathbf{w_i}$.&#xD;&#xA;&#xD;&#xA;The above integral (*i.e.* the reflection term of the rendering equation) can be approximated with the following Monte Carlo estimator&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;where $p$ is the probability density function (PDF) that describes the distribution of the sampling vectors $\mathbf{w_k}$.&#xD;&#xA;&#xD;&#xA;For actual rendering, the BRDF and PDF must be specified. In the case of the specular term of the Cook-Torrance model, I am using the following BRDF&#xD;&#xA;$$&#xD;&#xA;fr(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;where &#xD;&#xA;$$&#xD;&#xA;D = \frac{1}{m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;G = \min \left( 1, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_o})}{\mathbf{w_o} \cdot \mathbf{h}}, \frac{2(\mathbf{n} \cdot \mathbf{h})(\mathbf{n} \cdot \mathbf{w_i})}{\mathbf{w_o} \cdot \mathbf{h}} \right)&#xD;&#xA;$$&#xD;&#xA;In the above equations, $\mathbf{h} = \frac{\mathbf{w_o} + \mathbf{w_i}}{|\mathbf{w_o} + \mathbf{w_i}|}$ and $c_{spec}$ is the specular color. All equations, with the exception of $F$, were extracted from the original paper. $F$, also known as the [Schlick's approximation][3], is an efficient and less accurate approximation to the actual Fresnel term.&#xD;&#xA;&#xD;&#xA;It would be mandatory to use importance sampling in the case of rendering smooth specular surfaces. However, I am modeling only reasonably rough surfaces ($m \approx 0.2$), thus, I've decided to keep with uniform sampling for a while (at the cost of longer rendering times). In this case, the PDF is&#xD;&#xA;$$&#xD;&#xA;p(\mathbf{w_k}) = \frac{1}{2 \pi}&#xD;&#xA;$$&#xD;&#xA;By substituting the uniform PDF and Cook-Torrance BRDF into the Monte Carlo estimator (notice that $\mathbf{w_i}$ is substituted by $\mathbf{w_k}$, the random variable), I get&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\pi (\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta }{\left( \frac{1}{2\pi} \right)}&#xD;&#xA;$$&#xD;&#xA;Now we can cancel the $\pi$'s and remove the summation because we shoot only one random ray from the intersection point. We end up with&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{(\mathbf{n} \cdot \mathbf{w_k})(\mathbf{n} \cdot \mathbf{w_o})} \right) \cos \theta&#xD;&#xA;$$&#xD;&#xA;Since $\cos \theta = \mathbf{n} \cdot \mathbf{w_k}$, we can further simplify it&#xD;&#xA;$$&#xD;&#xA;2 L_i(\textbf{p}, \mathbf{w_k})\left( \frac{DFG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, that's the expression I am evaluating when a ray hits an specular surface whose reflectance is described by the Cook-Torrance BRDF. That is the expression that seems to be reflecting more energy than that received.&#xD;&#xA;I am almost sure that there is something wrong with it (or in the derivation process), but I just can't spot it. &#xD;&#xA;&#xD;&#xA;Interestingly enough, if I multiply the above expression by $\frac{1}{\pi}$, I get results that look correct. However, I've refused to do that because I can't mathematicaly justify it.&#xD;&#xA;&#xD;&#xA;Any help is very welcome! Thank you!&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;As @wolle pointed out below, [this paper][4] presents a new formulation better suited for path tracing, where the normal distribution function (NDF) $D$ includes the $\frac{1}{\pi}$ factor and the BRDF $fr$ includes the $\frac{1}{4}$ factor. Thus&#xD;&#xA;$$&#xD;&#xA;D_{new} = \frac{1}{\pi m^2 (\mathbf{n} \cdot \mathbf{h})^4} \exp \left( {\frac{(\mathbf{n} \cdot \mathbf{h})^2 - 1}{m^2 (\mathbf{n} \cdot \mathbf{h})^2}} \right)&#xD;&#xA;$$&#xD;&#xA;and&#xD;&#xA;$$&#xD;&#xA;fr_{new}(\mathbf{w_i}, \mathbf{w_o}) = \frac{DFG}{4 (\mathbf{n} \cdot \mathbf{w_i})(\mathbf{n} \cdot \mathbf{w_o})}&#xD;&#xA;$$&#xD;&#xA;Afer the inclusion of the above equations into the rendering equation, I ended up with&#xD;&#xA;$$&#xD;&#xA;\frac{\pi}{2} L_i(\textbf{p}, \mathbf{w_k})\left( \frac{D_{new}FG}{\mathbf{n} \cdot \mathbf{w_o}} \right)&#xD;&#xA;$$&#xD;&#xA;which worked nicely!&#xD;&#xA;PS: The issue now is to better understand how the new formulation for $D$ and $fr$ help in maintaining the energy conservation... but this is another topic.&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;As pointed out by [PeteUK][5], the authorship of the Fresnel formulation presented in the original text of my question was wrongly attributed to Cook and Torrance. The Fresnel formulation used above is actually known as the [Schlick's approximation][3] and is named after Christophe Schlick. The original text of the question was modified accordingly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3T0K5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BU0s0.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Schlick's_approximation&#xD;&#xA;  [4]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [5]: https://computergraphics.stackexchange.com/q/4771/5681" ContentLicense="CC BY-SA 3.0" />
  <row Id="13145" PostHistoryTypeId="5" PostId="4445" RevisionGUID="6b8278ae-000b-4b01-8957-6af48e369fa9" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I think that it is important to *classify* between different types of animations here. One rough classification could be&#xD;&#xA;&#xD;&#xA;1. Rigid body animations&#xD;&#xA;2. Vertex skinning animations&#xD;&#xA;3. Others...&#xD;&#xA;&#xD;&#xA;# Rigid body animations&#xD;&#xA;&#xD;&#xA;This refers to animations where the actual geometry data does not change. For example, you could have a geometric object, like a unit cube, and apply (usually affine) transformations to it: You can rotate, translate or scale this object. This is usually accomplished by some sort of scene graph: Each *node* of this scene graph can have information about the rotation, translation and scaling that should be applied to the objects. In general, this is something that can be expressed with a 4x4 transformation matrix.&#xD;&#xA;&#xD;&#xA;The key point is that you don't have to store &quot;animated geometry data&quot;. You only have to store the geometry data *once*, in its original state. In addition to that, you store the key frames of the transformation. &#xD;&#xA;&#xD;&#xA;In your case, if you wanted to do a rigid body animation, you could store the geometry in an OBJ file, and additionally store the key frame information in an arbitrary form, for example&#xD;&#xA;&#xD;&#xA;    TIME  TRANSLATION&#xD;&#xA;    0.0   ( 0, 0, 0)&#xD;&#xA;    0.1   (10, 0, 0)&#xD;&#xA;    0.2   (10,10, 0)&#xD;&#xA;    0.3   ( 0,10, 0)&#xD;&#xA;    0.4   ( 0, 0, 0)&#xD;&#xA;&#xD;&#xA;This could describe a movement of the object along a rectangular path, taking 0.4 seconds. Fortunately, you don't have to create your own file format for that. There already are solutions for storing this sort of animation data. For example, the COLLADA format already supports animations like this. A more compact representation of such an animation can be stored in a [glTF asset](https://github.com/KhronosGroup/glTF/). For example, it can represent animations like this one, from the glTF sample models repository:&#xD;&#xA;&#xD;&#xA;[![animation][1]][1]&#xD;&#xA;&#xD;&#xA;# Vertex skinning animations&#xD;&#xA;&#xD;&#xA;This technique refers, roughly speaking, to cases where you have an &quot;initial&quot; geometry, and you can define &quot;rules&quot; of how this geometry should be deformed based on the pose of a skeleton. As the name suggests, this is mainly intended for character animations, where you define a skeleton consisting of the &quot;bones&quot; of the character, and the geometry defines the &quot;skin&quot; of the character. Vertex skinning is also supported by different file formats like COLLADA or glTF. The effect is shown in this image, again, from the glTF sample models:&#xD;&#xA;&#xD;&#xA;[![skinning][2]][2]&#xD;&#xA;&#xD;&#xA;As already mentioned by [joojaa in his answer](https://computergraphics.stackexchange.com/a/4443/1649), implementing vertex skinning according to the specifications of these file formats may be a bit tricky. Additionally, a considerable amount of the skinning computations is usually done by the *vertex shader*. So for a ray-tracer, you would have to move these computations into your application code. &#xD;&#xA;&#xD;&#xA;# Others...&#xD;&#xA;&#xD;&#xA;This refers to what you already alluded to in the question: There may be cases where the animation is *not* a simple transformation of rigid objects, and where you cannot define any &quot;rules&quot; of how the vertices should be transformed. For example, when the vertex positions are computed by a simulator, like a fluid simulator or a *soft* body simulator. &#xD;&#xA;&#xD;&#xA;In doubt, it may simply be necessary to actually store the positions of all vertices, frame for frame. You could achieve this as a sequence of OBJ files. But note that OBJ files contain ASCII data, and thus, are usually *large* and the geometry data has to be parsed before it can be used. Storing the data in a binary form that can be used by the application directly may be beneficial here. &#xD;&#xA;&#xD;&#xA;There are some possible approaches for reducing the amount of data that has to be stored. For example, one could extend the concept of &quot;key frames&quot; here. For example, one could store the initial configuration of al vertices, and then only store the *movement* of vertices that acutally have *changed* between two frames. But of course, if (nearly) *all* vertices changed, the savings may be diminishing. &#xD;&#xA;&#xD;&#xA;I'm not aware of any universally applicable, &quot;standardized&quot; solutions for this. Maybe some of the solutions that [joojaa referred to in his answer](https://computergraphics.stackexchange.com/a/4443/1649) could be helpful here. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mm5ek.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/C85k5.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="13146" PostHistoryTypeId="5" PostId="4486" RevisionGUID="e7164cd5-ee9a-4e5d-8641-02a5544e0f5d" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="Recently I asked a question regarding how to mix a glossy and diffuse shader in my path tracer: [Mix shader looks wrong on my path tracer][1]. &#xD;&#xA;I thought it was incorrect, but a comparison between mine and Blender's seems correct. However, now I am lost in how I would approach making the surface of a mirror look rough as this example shows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have done some research, and discovered that there are different types of reflectance models such as Beckmann and GGX. I've found some explanations of how to find the BRDF such as this site: [Specular BRDF][3], but I can't find any explanation on how to do the reflection ray with explicit lighting. As shown in the pseudo code of my path tracer (below), for every object I shoot a ray towards a light and use the surface transport rendering equation to incorporate the BRDF. I am assuming this is where the GGX/Beckmann BRDF would be plugged in. (I'm guessing it's not quite that simple though and some probability must be involved). What really gets me though is that reflection ray. For diffuse it's easy because I just send off a random ray anywhere in the hemisphere of the surface normal. However, for specular, there's a more sharp bump in the BRDF. How would I translate that into a reflected ray? If I just jittered the ideal reflection ray a little, that wouldn't relate to how the microfacets are modeled in the GGX/Beckmann reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Explicit lighting equation from Peter Shirley's Realistic Ray Tracing:&#xD;&#xA;&#xD;&#xA;$$\large L_S(\mathbf x,\mathbf k_o)\approx\frac{\rho(\mathbf k_i,\mathbf k_o)L_e(\mathbf x',\mathbf x-\mathbf x')v(\mathbf x,\mathbf x')\cos\theta_i\cos\theta'}{p(\mathbf x')\left\lVert \mathbf x-\mathbf x'\right\rVert^2}$$&#xD;&#xA;&#xD;&#xA;Where $p(\mathbf x)$ is the density function of the light triangle $1/\text{Area}$&#xD;&#xA;&#xD;&#xA;$\mathbf x'$ is a random point on the light triangle&#xD;&#xA;&#xD;&#xA;$\mathbf x$  is the hit point on the object&#xD;&#xA;&#xD;&#xA;The cosines are the angles between the light's normal and the light ray, and the object's normal and the light ray&#xD;&#xA;&#xD;&#xA;$\rho$ is the BRDF ($1/\pi$ for ideal diffuse)&#xD;&#xA;&#xD;&#xA;And $v$ is either $1$ or $0$ depending on if it's in shadow&#xD;&#xA;&#xD;&#xA;Pseudo code:&#xD;&#xA;&#xD;&#xA;    rayColor(ray r, depth, int E=1)&#xD;&#xA;    {&#xD;&#xA;        if(r doesn't hit triangle)&#xD;&#xA;            return 0&#xD;&#xA;        if(r hit is a light)&#xD;&#xA;        {&#xD;&#xA;           if(E)&#xD;&#xA;             return light_emission&#xD;&#xA;           else&#xD;&#xA;             return 0&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vector x = r.origin + r.direction*t // x is point where r hit tri&#xD;&#xA;        vector n = normal where ray hit triangle&#xD;&#xA;        n.normalize()&#xD;&#xA;        vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal&#xD;&#xA;&#xD;&#xA;        if(++depth &gt; 5) return 0 // max bounces&#xD;&#xA;&#xD;&#xA;        float triangle_area   = area of emitting triangle&#xD;&#xA;        vector x_light_random = random point on emitting triangle&#xD;&#xA;        vector light_normal   = normal of emitting triangle&#xD;&#xA;&#xD;&#xA;        vector d = x_light_random = x_converted;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit&#xD;&#xA;                                                        // both sides&#xD;&#xA;     &#xD;&#xA;        object_normal.normalize();&#xD;&#xA;        light_normal.normalize();&#xD;&#xA;&#xD;&#xA;        BRDF = 1/PI // perfect diffuse&#xD;&#xA;        light_emitted = 1 // emission of 1&#xD;&#xA;        vector light_out = 0&#xD;&#xA;        if(ray starting at x towards d hits light (i.e. not in shadow))&#xD;&#xA;        {&#xD;&#xA;             light_out = BRDF*light_emitted*(object_normal.dot(d))*&#xD;&#xA;                                (-1*light_normal.dot(d)*triangle_area)/&#xD;&#xA;                                (d.length*d.length*d.length*d.length)&#xD;&#xA;        }&#xD;&#xA;        vector direct_light = color_of_object_triangle*light_out;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      //----SPECULAR-----&#xD;&#xA;      vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection&#xD;&#xA;      vector light_color = 1 // white since dialectics don't change spec&#xD;&#xA;      vector specular = light_color*rayColor(createRay(x, d2),depth)&#xD;&#xA;      &#xD;&#xA;      float P = 0.5; // 50/50 chance of mirror/diffuse&#xD;&#xA;      if(erand(Xi) &lt; P)&#xD;&#xA;          return direct_light/P&#xD;&#xA;      else&#xD;&#xA;          return spec/(1-P)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4483/mix-shader-looks-wrong-on-my-path-tracer&#xD;&#xA;  [2]: https://i.stack.imgur.com/lBTPz.jpg&#xD;&#xA;  [3]: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13147" PostHistoryTypeId="5" PostId="4532" RevisionGUID="b1003645-141d-4a12-b863-0d3815542493" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="After asking [this](https://computergraphics.stackexchange.com/questions/4523/how-is-that-possible-that-matrices-can-be-thought-as-coordinate-systems) question, a few new terms that I had never heard of came up. Note, I'm quite familiar with linear algebra, but I've never heard these terms in the context of linear algebra. &#xD;&#xA;&#xD;&#xA;Comments like &#xD;&#xA;&#xD;&#xA;&gt; In my example, you can use the columns to get the basis vectors of the coordinate system it describes. _The columns are in the coordinate system of whatever the **parent coordinate system** is. If there is no parent coordinate system, they are in global space. Else, they are in the coordinate system of the parent._&#xD;&#xA;&#xD;&#xA;What's a parent coordinate system? When is this term used? Why is it called a parent coordinate system?&#xD;&#xA;&#xD;&#xA;Then the author of the comment tries to explain me the meaning as follows:&#xD;&#xA;&#xD;&#xA;&gt; Matrices can be parented off of each other, but that is probably too confusing to visualize as you are just trying to learn things. Just imagine that if there was a matrix hierarchy, that all the matrices are multiplied together into one matrix M then you can ignore hierarchies.&#xD;&#xA;&#xD;&#xA;This hasn't really cleared things up. What is it mean that _matrices can be parented off of each other_? What is it meant by _matrix hierarchy_? &#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;I know that if you have $m$ $A_1, A_2, \cdots, A_m \in \mathbb{R}^{n \times n}$ matrices which represent transformations, any combination of products of these matrices represents clearly a new transformation. For example, say that $A_1 * A_2 = B_{12}$. Suppose now that we have a vector $v \in \mathbb{R}^{n \times 1}$. Then the following two statements should clearly be equivalent&#xD;&#xA;&#xD;&#xA;$$A_1 * A_2 * v$$&#xD;&#xA;&#xD;&#xA;and &#xD;&#xA;&#xD;&#xA;$$B_{12} * v$$&#xD;&#xA;&#xD;&#xA;but the transformations used are different, i.e., in one case we use two single transformations (i.e., $A_1$ and $A_2$) and in the other case we use only one transformation, namely $B_{12}$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I don't know if this has something to do with &quot;parent coordinate systems&quot;, but I just wanted to show you a few things that I'm suspecting could be related to this terminology and concepts of computer graphics.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Final question would be: does it make sense to talk just about &quot;parent _coodinate systems_&quot; or does it also make sense to talk about &quot;parent vector spaces&quot;? Why?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13148" PostHistoryTypeId="5" PostId="4586" RevisionGUID="0280eaa1-13a4-458b-8487-d7f1ec0320d4" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="This is one of the most common &quot;misconceptions&quot; on rendering, rasterisation and ray-tracing. Don't get me wrong. This is a good question, but one that should be answered once and for all. &#xD;&#xA;&#xD;&#xA;So to answer your question:&#xD;&#xA;&#xD;&#xA;1) it is much easier to simulate reflection and refraction with ray-tracing than with rasterisation, which is often why when you see an image produced with a ray-tracer you see spheres reflecting each other.&#xD;&#xA;&#xD;&#xA;2) the misconception (even among people working in the CG business) is that you can NOT produce reflection or refraction with rasterisation. In fact, you can.&#xD;&#xA;&#xD;&#xA;Generally, ray-tracing/rasterisation have nothing to do with reflection or refraction or whatever else. These are two ways of solving a single problem which is to find out (in short) if two points in space are visible to each other (the visibility problem). Ray-tracing solves this problem in one way, rasterisation in an other. Rasterisation is very efficient at solving this problem from primary rays (or camera rays) and less efficient to solve this problem for secondary rays (reflection, refraction, shadows, etc.) than ray-tracing. Ray-tracing is slower than rasterisation for primary rays but offers a simpler solution for secondary rays compared to rasterisation. Yet ray-tracing is not good for solving problems like caustics, so this is far from being a solution to every problem in computer graphics. Yet rasterisation can be used (different techniques exist) to simulate reflections and refractions.&#xD;&#xA;&#xD;&#xA;I am sorry to repeat myself [here](https://computergraphics.stackexchange.com/questions/4573/refraction-in-a-ray-tracer) but there are resources on the web that explain this well. I am tired of promoting the same ones all the time but Google `ray-tracing vs rasterisation` (I have just done it) and you will stumble upon a couple of good ones. You now just need to make the effort to read." ContentLicense="CC BY-SA 3.0" />
  <row Id="13149" PostHistoryTypeId="5" PostId="4685" RevisionGUID="496ad87a-0920-464d-b215-d7b74d63853f" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="&gt; I don't understand why, if I make the first argument to glm::lookAt be glm::vec3(0.0f, 0.0f, 2.0f), I see nothing.&#xD;&#xA;&#xD;&#xA;It's because of the *up* vector. If you think about the look-at operation, you specify where the camera is and what point it's looking towards. These two things alone leave one degree of freedom: the rotation around that axis. Which way is up on your screen? The third argument is for specifying that: it's a direction in world space which will correspond to *up* on the screen. If your first argument is that and the rest of the code is as your example, you're calling `lookAt((0,0,2), (0,0,0), (0,0,1))`. Your up vector points along the $z$-axis, which is the same direction the camera is looking (well, the opposite direction. This can't define which way is *up* on the screen. &#xD;&#xA;&#xD;&#xA;You probably want to pass a vector `(0,1,0)` as the third argument, which will make $y$ point up on your screen.&#xD;&#xA;&#xD;&#xA;If you're making a plan view of a 3D scene, then perspective projection is probably the right answer, but if all your content is going to be in the $z=0$ plane, then you probably want to use an orthographic rather than a perspective projection. Look at https://computergraphics.stackexchange.com/questions/2383/whats-the-difference-between-orthographic-and-perspective-projection to learn more about that.&#xD;&#xA;&#xD;&#xA;Last of all, remember that if you're projecting an $800m \times 800m$ scene onto $800 \times 800$ pixels, then a $1m$ radius circle will only be one pixel large. You probably need to scale up the size of your circle." ContentLicense="CC BY-SA 3.0" />
  <row Id="13150" PostHistoryTypeId="5" PostId="4750" RevisionGUID="87d72d93-9e47-4aa4-95de-01ff39810924" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="&gt; We know that in PNG,BMP,etc... the pixel value stored is not in the linear RGB space.&#xD;&#xA;&#xD;&#xA;This is not necessarily true. You can store whatever color space you want into an image, it doesn't even need to be colors (such as normal maps).&#xD;&#xA;&#xD;&#xA;The alpha channel is generally linear. The alpha channel doesn't get displayed, but it is generally a non-color term used for transparency (or whatever else). Because they don't need to display on a monitor, there's no reason to store in in gamma space. If you did, you would unnecessarily lose precision at the lower end of the alpha values. [Normals maps follow a similar line of reasoning, as explained very well by Julien Guertault][1].&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/3842/why-shouldnt-bump-normal-and-displacement-maps-be-gamma-corrected?rq=1" ContentLicense="CC BY-SA 3.0" />
  <row Id="13151" PostHistoryTypeId="5" PostId="4771" RevisionGUID="419b6929-2b42-41b2-8715-875587adb0ac" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I'm trying to implement Cook-Torrance BRDF and had previously bookmarked [this question][1] as it looked very well thought out. Going through it, I'm confused about the Fresnel equation. The author has the equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;F = c_{spec} + (1 - c_{spec}) (1 - \mathbf{w_i} \cdot \mathbf{h})^5 \tag{1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and says &quot;*$c_{spec}$ is the specular color*&quot;&#xD;&#xA;&#xD;&#xA;Looking elsewhere, I can see this equation is [Schlick's approximation][2], but in other references, $c_{spec}$ is called $R_0$ and is $\left(\frac{n_1-n_2}{n_1+n_2}\right)^2$ which is clearly a number based upon refractive indices and **not** a colour.&#xD;&#xA;&#xD;&#xA;Does equation $(1)$ make sense with colour?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4394/path-tracing-the-cook-torrance-brdf&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Schlick%27s_approximation" ContentLicense="CC BY-SA 3.0" />
  <row Id="13152" PostHistoryTypeId="5" PostId="4867" RevisionGUID="082e8e12-3b6d-4ea4-a93f-658eeffc8d57" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I solved it myself. Here is a result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The example is out of this post: [here][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/18HYq.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/4507/finding-the-nearest-neighbor-of-polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="13153" PostHistoryTypeId="5" PostId="4877" RevisionGUID="f7cf3799-957d-4567-98bb-6d252ea1c1cd" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="I'm writing a path tracer and, for the moment, spectra related data (spectral power distributions and spectral reflectance curves) are stored as RGB tuples. In the Cook-Torrance specular BRDF I am using the Schlick's approximation for the Fresnel term:&#xD;&#xA;&#xD;&#xA;$$F(\theta) = R_0 + (1-R_0)(1-\cos \theta)^5$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$R_0 = \left( \frac{\eta_1 - \eta_2}{\eta_1 + \eta_2} \right)^2$$&#xD;&#xA;&#xD;&#xA;Schlick's approximation is fast and very convenient in the current context (*e.g.* for conductors, $R_0$ is simply the RGB tuple of the normal incidence reflectance of the metallic material).&#xD;&#xA;&#xD;&#xA;However, despite being fast, Schlick's approximation is very simple (it does not take into account, for instance, the extinction coefficients of conductors). Some path tracers use much more accurate Fresnel formulations. [PBRT][1], for instance, uses the following equations for the Fresnel terms:&#xD;&#xA;&#xD;&#xA;**Fresnel term for conductors**&#xD;&#xA;&#xD;&#xA;$$r^2_{||} = \frac{(\eta^2 + k^2) \cos \theta_i^2 - 2 \eta \cos \theta_i + 1}{(\eta^2 + k^2) \cos \theta_i^2 + 2 \eta \cos \theta_i + 1}$$&#xD;&#xA;&#xD;&#xA;$$r^2_{\perp} = \frac{(\eta^2 + k^2) - 2 \eta \cos \theta_i + \cos \theta_i^2}{(\eta^2 + k^2) + 2 \eta \cos \theta_i + \cos \theta_i^2}$$&#xD;&#xA;&#xD;&#xA;**Fresnel term for dielectrics**&#xD;&#xA;&#xD;&#xA;$$r_{||} = \frac{\eta_t \cos \theta_i - \eta_i \cos \theta_t}{\eta_t \cos \theta_i + \eta_i \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;$$r_{\perp} = \frac{\eta_i \cos \theta_i - \eta_t \cos \theta_t}{\eta_i \cos \theta_i + \eta_t \cos \theta_t}$$&#xD;&#xA;&#xD;&#xA;For both equations, the resulting Fresnel reflectance is obtained with:&#xD;&#xA;&#xD;&#xA;$$ F=\frac{r^2_{||} + r^2_{\perp}}{2}$$&#xD;&#xA;&#xD;&#xA;In the case of spectral path tracers, I believe that the use of the above Fresnel formulations would be straightforward (just a matter of feeding the formulas with already tabulated IORs and $\kappa$ data - such as those available at [https://refractiveindex.info][2]). &#xD;&#xA;&#xD;&#xA;However, how could these formulations be used in a RGB-based path tracer? Is this even possible (I believe so, because these are the only Fresnel formulations used by PBRT and it works both with spectral and RGB-based spectral data - at least, to the best of my knowledge)? So, if yes, how to generate the IOR and $\kappa$ triplets to be used in the above formulations? If not, what would be the alternatives (with the exception of going fully spectral)?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I've found a potential answer to the question and, despite missing technical soundness (that's why I've just added it as an update and not as the actual answer), I am posting it here in the case someone may be interested or may have comments to add. &#xD;&#xA;&#xD;&#xA;According to this [OSL Shader][3], at least the complex Fresnel term (for conductors), in the context of an RGB-based path tracer, can be evaluated by simply substituting $\eta$ and $\kappa$ by those values corresponding to the R, G and B &quot;representative&quot; wavelengths. Since R, G and B are not narrow spikes on the electromagnetic spectrum, the &quot;representative&quot; wavelength may be a little different from one implementation to another. I've seen that the most common values for these representative wavelengths are 0.65$\mu$m for Red, 0.55$\mu$m for Green and 0.45$\mu$m for Blue.&#xD;&#xA;&#xD;&#xA;For instance, suppose that we want to render the gold material. The $\eta$ and $\kappa$ values of gold, for our representative wavelengths (0.65$\mu$m, 0.55$\mu$m and 0.45$\mu$m), can be obtained from [https://refractiveindex.info][2], and will be:&#xD;&#xA;&#xD;&#xA;$$\eta_{gold} = ( 0.15557, 0.42415, 1.3831 )$$&#xD;&#xA;&#xD;&#xA;$$\kappa_{gold} = ( 3.6024, 2.4721, 1.9155 )$$ &#xD;&#xA;&#xD;&#xA;Now, it is just a matter of evaluating the Fresnel reflectance for each color channel:&#xD;&#xA;&#xD;&#xA;$$Fresnel_{Red} = F(\eta[0],\kappa[0], \theta)$$&#xD;&#xA;$$Fresnel_{Green} = F(\eta[1],\kappa[1], \theta)$$&#xD;&#xA;$$Fresnel_{Blue} = F(\eta[2],\kappa[2], \theta)$$&#xD;&#xA;&#xD;&#xA;I have used this complex Fresnel equation within my Cook-Torrance BRDF, whose formulation can be seen [here][4], and I've obtained the following results (I've compared them to reference images rendered with [Mitsuba][5]):&#xD;&#xA;&#xD;&#xA;[![Gold. Left: Mitsuba. Right: My renderer.][6]][6]&#xD;&#xA;&#xD;&#xA;Above image: Gold material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Above image: Copper material rendered with (left) Mitsuba and (right) my renderer.&#xD;&#xA;&#xD;&#xA;The images generated by my path tracer are noisier because it uses only BRDF importance sampling. With respect to copper, the images are, at least visually, almost identical. With respect to gold, colors are slightly different. I have made some experiments, and observed that very small changes on the values of the &quot;representative wavelengths&quot; might have significant impact on the final color. Thus, the color difference regarding the rendering of the gold material could be eventually attributed to differences regarding the &quot;representative&quot; wavelengths used by each renderer for R,G and B.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org&#xD;&#xA;  [2]: https://refractiveindex.info&#xD;&#xA;  [3]: https://docs.chaosgroup.com/display/OSLShaders/Complex+Fresnel+shader&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/&#xD;&#xA;  [6]: https://i.stack.imgur.com/mSf98.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/EfU5C.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13154" PostHistoryTypeId="5" PostId="4917" RevisionGUID="51b3d1b1-e4d7-4c2c-ae63-3ef811553a26" CreationDate="2017-04-13T13:00:43.660" UserId="-1" Comment="replaced http://computergraphics.stackexchange.com/ with https://computergraphics.stackexchange.com/" Text="For a 3D scene in the World Coordinates, its View Reference Point (VRP) is at (5,&#xD;&#xA;2,1), &#xD;&#xA;and a viewer is looking towards point A(1,1,1). Construct a transform matrix which will &#xD;&#xA;map  World  Coordinate  points  to  a  right-handed  (UVN)  viewing  space,  so  that  VRP  is &#xD;&#xA;the  origin,  the  line  joining  VRP  to  A  is  the  positive  N  axis,  and  the  View-Up  Vector  is &#xD;&#xA;(0,0,1).  &#xD;&#xA;&#xD;&#xA;I have calculated the transformation matrix (T):&#xD;&#xA;&#xD;&#xA;1, 0, 0, -5&#xD;&#xA;&#xD;&#xA;0, 1, 0, 2&#xD;&#xA;&#xD;&#xA;0, 0, 1, -1&#xD;&#xA;&#xD;&#xA;0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;I have calculated the rotation matrix (R):&#xD;&#xA;&#xD;&#xA;-0.6, -0.8, 0, 0&#xD;&#xA;&#xD;&#xA;0, 0, 1, 0&#xD;&#xA;&#xD;&#xA;-0.8, 0.6, 0, 0&#xD;&#xA;&#xD;&#xA;0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;But what would the final transformation matrix (M) be? My lecture slides tell me it would be rotation matrix multiplied by translation matrix, with the last column multiplied by -1 except for the 1. This would equal:&#xD;&#xA;&#xD;&#xA;M = R x T = &#xD;&#xA;&#xD;&#xA;-0.6, -0.8, 0, -1.4&#xD;&#xA;&#xD;&#xA;0, 0, 1, 1&#xD;&#xA;&#xD;&#xA;-0.8, 0.6, 0, -5.2&#xD;&#xA;&#xD;&#xA;0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;But this answer here: https://computergraphics.stackexchange.com/questions/4737/building-view-transform-matrices&#xD;&#xA;&#xD;&#xA;just adds them together somehow. Which one is correct?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13156" PostHistoryTypeId="5" PostId="4994" RevisionGUID="d0846a93-7661-4f53-8b08-0f8d8f983c4a" CreationDate="2017-04-13T14:24:34.867" UserId="310" Comment="Add a section on sampling Cook Torrance" Text="Short answer:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;**Importance sampling** is a method to reduce variance in Monte Carlo Integration by choosing an estimator close to the shape of the actual function.&#xD;&#xA;&#xD;&#xA;**PDF** is an abbreviation for [Probability Density Function][1]. A $pdf(x)$ gives the probability of a random sample generated being $x$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Long Answer:&#xD;&#xA;=====&#xD;&#xA;&#xD;&#xA;To start, let's review what Monte Carlo Integration is, and what it looks like mathematically. &#xD;&#xA;&#xD;&#xA;Monte Carlo Integration is an technique to estimate the value of an integral. It's typically used when there isn't a closed form solution to the integral. It looks like this:&#xD;&#xA;&#xD;&#xA;$$\int f(x) \, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;In english, this says that you can approximate an integral by averaging successive random samples from the function. As $N$ gets large, the approximation gets closer and closer to the solution. $pdf(x_{i})$ represents the probability density function of each random sample.&#xD;&#xA;&#xD;&#xA;Let's do an example: Calculate the value of the integral $I$.&#xD;&#xA;&#xD;&#xA;$$I = \int_{0}^{2\pi} e^{-x} \sin(x) dx$$&#xD;&#xA;&#xD;&#xA;Let's use Monte Carlo Integration:&#xD;&#xA;&#xD;&#xA;$$I \approx \frac{1}{N} \sum_{i=1}^N \frac{e^{-x} \sin(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;A simple python program to calculate this is:&#xD;&#xA;&#xD;&#xA;    import random&#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    N = 200000&#xD;&#xA;    TwoPi = 2.0 * math.pi&#xD;&#xA;&#xD;&#xA;    sum = 0.0&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;        x = random.uniform(0, TwoPi)&#xD;&#xA;        &#xD;&#xA;        fx = math.exp(-x) * math.sin(x)&#xD;&#xA;        pdf = 1 / (TwoPi - 0.0)&#xD;&#xA;        &#xD;&#xA;        sum += fx / pdf&#xD;&#xA;&#xD;&#xA;    I = (1 / N) * sum&#xD;&#xA;    print(I)&#xD;&#xA;&#xD;&#xA;If we run the program we get $I = 0.4986941$&#xD;&#xA;&#xD;&#xA;Using separation by parts, we can get the exact solution:&#xD;&#xA;&#xD;&#xA;$$I = \frac{1}{2} (1 − e−2π) = 0.4990663$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You'll notice that the Monte Carlo Solution is not quite correct. This is because it is an estimate. That said, as $N$ goes to infinity, the estimate should get closer and closer to the correct answer. Already at $N = 2000$ some runs are almost identical to the correct answer.&#xD;&#xA;&#xD;&#xA;A note about the PDF: In this simple example, we always take a uniform random sample. A uniform random sample means every sample has the exact same probability of being chosen. We sample in the range $[0, 2\pi]$ so, $pdf(x) = 1 / (2\pi - 0)$&#xD;&#xA;&#xD;&#xA;Importance sampling works by *not* uniformly sampling. Instead we try to choose more samples that contribute a lot to the result (important), and less samples that only contribute a little to the result (less important). Hence the name, importance sampling.&#xD;&#xA;&#xD;&#xA;If you choose a sampling function whose pdf very closely matches the shape of $f$, you can greatly reduce the variance, which means you can take less samples. However, if you choose a sampling function whose value is very different from $f$, you can ***increase*** the variance. See the picture below:&#xD;&#xA;[![Comparison of good sampling vs bad sampling][2]][2]&#xD;&#xA;Image from Wojciech Jarosz's [Dissertation Appendix A][3]&#xD;&#xA;&#xD;&#xA;One example of importance sampling in Path Tracing is how to choose the direction of a ray when after it hits a surface. If the surface is not perfectly specular (ie. a mirror or glass), the outgoing ray can be anywhere in the hemisphere.&#xD;&#xA;&#xD;&#xA;[![Outgoing rays can go anywhere in the hemisphere][4]][4]&#xD;&#xA;&#xD;&#xA;We ***could*** uniformly sample the hemisphere to generate the new ray. However, we can exploit the fact that the rendering equation has a cosine factor in it:&#xD;&#xA;&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) + \int_{\Omega} f(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}$$&#xD;&#xA;&#xD;&#xA;Specifically, we know that any rays at the horizon will be heavily attenuated (specifically, $\cos(x)$ ). So, rays generated near the horizon will not contribute very much to the final value.&#xD;&#xA;&#xD;&#xA;To combat this, we use importance sampling. If we generate rays according to a cosine weighted hemisphere, we ensure that more rays are generated well above the horizon, and less near the horizon. This will lower variance and reduce noise.&#xD;&#xA;&#xD;&#xA;In your case, you specified that you will be using a Cook-Torrance, microfacet-based BRDF. The common form being:&#xD;&#xA;&#xD;&#xA;$$f(p, \omega_{\text{i}}, \omega_{\text{o}}) = \frac{F(\omega_{\text{i}}, h) G(\omega_{\text{i}}, \omega_{\text{o}}, h) D(h)}{4 \cos(\theta_{i}) \cos(\theta_{o})}$$&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;$$F(\omega_{\text{i}}, h) = \text{Fresnel function} \\&#xD;&#xA;G(\omega_{\text{i}}, \omega_{\text{o}}, h) = \text{Geometry Masking and Shadowing function} \\&#xD;&#xA;D(h) = \text{Normal Distribution Function}$$&#xD;&#xA;&#xD;&#xA;The blog &quot;A Graphic's Guy's Note&quot; has an excellent write up on how to sample Cook-Torrance BRDFs. I will refer you to [his blog post][5]. That said, I will try to create a brief overview below:&#xD;&#xA;&#xD;&#xA;The NDF is generally the dominant portion of the Cook-Torrance BRDF, so if we are going to importance sample, the we should sample based on the NDF.&#xD;&#xA;&#xD;&#xA;Cook-Torrance doesn't specify a specific NDF to use; we are free to choose whichever one suits our fancy. That said, there are a few popular NDFs:&#xD;&#xA;&#xD;&#xA; - GGX&#xD;&#xA; - Beckmann&#xD;&#xA; - Blinn&#xD;&#xA;&#xD;&#xA;Each NDF has it's own formula, thus each must be sampled differently. I am only going to show the final sampling function for each. If you would like to see how the formula is derived, see the blog post.&#xD;&#xA;&#xD;&#xA;**GGX** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{GGX}(m) = \frac{\alpha^2}{\pi((\alpha^2-1) \cos^2(\theta) + 1)^2}$$&#xD;&#xA;&#xD;&#xA;To sample the spherical coordinates angle $\theta$, we can use the formula:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left( \sqrt{\frac{\alpha^2}{\xi_1 (\alpha^2 - 1) + 1}} \right)$$&#xD;&#xA;&#xD;&#xA;where $\xi$ is a uniform random variable.&#xD;&#xA;&#xD;&#xA;We assume that the NDF is isotropic, so we can sample $\phi$ uniformly:&#xD;&#xA;&#xD;&#xA;$$\phi = \xi_{2}$$&#xD;&#xA;&#xD;&#xA;**Beckmann** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Beckmann}(m) = \frac{1}{\pi \alpha^2\cos^4(\theta)} e^{-\frac{\tan^2(\theta)}{\alpha^2}}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\sqrt{\frac{1}{1 = \alpha^2 \ln(1 - \xi_1)}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;Lastly, **Blinn** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Blinn}(m) = \frac{\alpha + 2}{2 \pi} (\cos(\theta))^{\alpha}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\frac{1}{\xi_{1}^{\alpha + 1}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGyXh.png&#xD;&#xA;  [3]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/appendixA.pdf&#xD;&#xA;  [4]: https://i.stack.imgur.com/6crnH.png&#xD;&#xA;  [5]: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13160" PostHistoryTypeId="5" PostId="4995" RevisionGUID="b0ecda4a-a3b8-4b26-88dd-8681515cd806" CreationDate="2017-04-14T09:37:07.473" UserId="231" Comment="Remove request for off site resources so the question does not need to be closed" Text="I am trying to implement a shape matching algorithm for vector images discussed in a paper.&#xD;&#xA;&#xD;&#xA;The input to the algorithm is a model of 2D shapes deﬁned by contour segments. According to the paper, such segments can be deﬁned as polylines, obtained for example by vectorizing the output of an edge detector like Canny.&#xD;&#xA;&#xD;&#xA;I am trying to vectorize a tiff image using Inkscape's bitmap tracing feature. The svg image I got from it has a path node with many attribute values, but that is not what the algorithm wants:&#xD;&#xA;&#xD;&#xA;[![output of canny edge detector][2]][2] [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;How can I vectorize to polylines instead of paths?&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/SVWx7.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7f7RQ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13161" PostHistoryTypeId="4" PostId="4995" RevisionGUID="b0ecda4a-a3b8-4b26-88dd-8681515cd806" CreationDate="2017-04-14T09:37:07.473" UserId="231" Comment="Remove request for off site resources so the question does not need to be closed" Text="Vectorizing to polylines instead of paths" ContentLicense="CC BY-SA 3.0" />
  <row Id="13162" PostHistoryTypeId="2" PostId="4997" RevisionGUID="26c8b619-4cd1-491e-ae2a-8e0b8a2e6581" CreationDate="2017-04-14T11:36:59.443" UserId="6282" Text="https://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;http://xlgames-inc.github.io/posts/sphericalharmonics0/&#xD;&#xA;&#xD;&#xA;I am using Spherical Harmonics to turn reflective(mirror like) cube map to diffuse light cube map.&#xD;&#xA;&#xD;&#xA;From what I understand for an image, I calculate 9 coefficient(for red green blue) that describes the color of the cube map.&#xD;&#xA;&#xD;&#xA;The nine coefficients are this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And when you visualize them they become...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I do something with these coefficients to get color of the cube map.&#xD;&#xA;&#xD;&#xA;The part that I am not understanding is using an image to get that 9 coefficients. All the papers kinda assume that you somehow got that coefficient calculated because it is &quot;easy&quot;.&#xD;&#xA;&#xD;&#xA;I don't know how to do that calculation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kmjyY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oRvEP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13163" PostHistoryTypeId="1" PostId="4997" RevisionGUID="26c8b619-4cd1-491e-ae2a-8e0b8a2e6581" CreationDate="2017-04-14T11:36:59.443" UserId="6282" Text="Spherical Harmonics Diffuse CubeMap. How to get coefficients&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13164" PostHistoryTypeId="3" PostId="4997" RevisionGUID="26c8b619-4cd1-491e-ae2a-8e0b8a2e6581" CreationDate="2017-04-14T11:36:59.443" UserId="6282" Text="|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13165" PostHistoryTypeId="2" PostId="4998" RevisionGUID="e4d5edad-2b5a-4838-b8ca-277d7961fee6" CreationDate="2017-04-14T12:47:58.287" UserId="137" Text="For each color you make a matrix n x 9 $A$ where each row is the sequence $y_0, y_1^{-1}, y_1^{0}, y_1^{1}, y_2^{-2}, y_2^{-1}, y_2^{0}, y_2^{1}, y_2^{2}$ of that point and a n x 3 matrix $b$ with the color at that point.&#xD;&#xA;&#xD;&#xA;Then you take a 9x3 matrix $x$ of the unknown coefficients. Then $Ax=b$ is the equation to solve. This equation will be overdetermined so you'll need to approximate the solution.&#xD;&#xA;&#xD;&#xA;This means doing a [linear regression][1] to find the coefficients that give the smaller error.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Linear_regression" ContentLicense="CC BY-SA 3.0" />
  <row Id="13166" PostHistoryTypeId="2" PostId="4999" RevisionGUID="4682d07e-6333-405b-aa56-05376b3399a3" CreationDate="2017-04-14T16:03:10.307" UserId="6454" Text="In [this][1] question I asked how to implement a chain of blurs in one single step. &#xD;&#xA;&#xD;&#xA;Then I found out from the [gaussian blur][2] page of Wikipedia that:&#xD;&#xA;&#xD;&#xA;&gt; Applying multiple, successive gaussian blurs to an image has the same&#xD;&#xA;&gt; effect as applying a single, larger gaussian blur, whose radius is the&#xD;&#xA;&gt; square root of the sum of the squares of the blur radii that were&#xD;&#xA;&gt; actually applied. For example, applying successive gaussian blurs with&#xD;&#xA;&gt; radii of 6 and 8 gives the same results as applying a single gaussian&#xD;&#xA;&gt; blur of radius 10, since sqrt {6^{2}+8^{2}}=10.&#xD;&#xA;&#xD;&#xA;So I thought that `blur` and `singleBlur` were the same in the following code:&#xD;&#xA;&#xD;&#xA;    cv::Mat firstLevel;&#xD;&#xA;    float sigma1, sigma2;&#xD;&#xA;    //intialize firstLevel, sigma1 and sigma2&#xD;&#xA;    cv::Mat blur = gaussianBlur(firstLevel, sigma1);&#xD;&#xA;            blur = gaussianBlur(blur, sigma2);&#xD;&#xA;    float singleSigma = std::sqrt(std::pow(sigma1,2)+std::pow(sigma2,2));&#xD;&#xA;    cv::Mat singleBlur = gaussianBlur(firstLevel, singleSigma);&#xD;&#xA;	cv::Mat diff = blur != singleBLur;&#xD;&#xA;	// Equal if no elements disagree&#xD;&#xA;	assert( cv::countNonZero(diff) == 0);&#xD;&#xA;&#xD;&#xA;But this `assert` fails (and actually, for example, the first row of `blur` is different from the first one of `singleBlur`).&#xD;&#xA;&#xD;&#xA;Why?&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/43163337/parallelize-chain-of-gaussian-blurs&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Gaussian_blur" ContentLicense="CC BY-SA 3.0" />
  <row Id="13167" PostHistoryTypeId="1" PostId="4999" RevisionGUID="4682d07e-6333-405b-aa56-05376b3399a3" CreationDate="2017-04-14T16:03:10.307" UserId="6454" Text="Replace a chain of image blurs with one blur" ContentLicense="CC BY-SA 3.0" />
  <row Id="13168" PostHistoryTypeId="3" PostId="4999" RevisionGUID="4682d07e-6333-405b-aa56-05376b3399a3" CreationDate="2017-04-14T16:03:10.307" UserId="6454" Text="|gaussian-blur|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13170" PostHistoryTypeId="5" PostId="4998" RevisionGUID="9d007fa1-cb24-40b8-bbd7-f7b8aac3e868" CreationDate="2017-04-15T00:16:46.417" UserId="137" Comment="added 140 characters in body" Text="To get the coefficients you make a matrix n x 9 $A$ where each row is a sample of the color you want the cubemap to have, each row is the sequence $y_0, y_1^{-1}, y_1^{0}, y_1^{1}, y_2^{-2}, y_2^{-1}, y_2^{0}, y_2^{1}, y_2^{2}$ of that point and a also n x 3 matrix $b$ with the color at that point.&#xD;&#xA;&#xD;&#xA;Then you take a 9x3 matrix $x$ of the unknown coefficients (9 for each color). Then $Ax=b$ is the equation to solve. This equation will be overdetermined so you'll need to approximate the solution.&#xD;&#xA;&#xD;&#xA;This means doing a [linear regression][1] to find the coefficients that give the smallest error. This is well described in linear algebra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Linear_regression" ContentLicense="CC BY-SA 3.0" />
  <row Id="13174" PostHistoryTypeId="5" PostId="4998" RevisionGUID="a299cd93-d114-4686-895a-03f557618159" CreationDate="2017-04-15T09:40:58.400" UserId="137" Comment="added 178 characters in body" Text="To start I'll assume you have a list of (x,y,z) points each with a r, g, b color that are the samples you want to approximate with the spherical harmonics.&#xD;&#xA;&#xD;&#xA;To get the coefficients you make a matrix n x 9 $A$ where each row is the sequence $y_0(x,y,z), y_1^{-1}(x,y,z), y_1^{0}(x,y,z), y_1^{1}(x,y,z), y_2^{-2}(x,y,z), y_2^{-1}(x,y,z), y_2^{0}(x,y,z), y_2^{1}(x,y,z), y_2^{2}(x,y,z)$ of a point and also a n x 3 matrix $b$ with each corresponding row the color at that point.&#xD;&#xA;&#xD;&#xA;Then you take a 9x3 matrix $x$ of the unknown coefficients (9 for each color). Then $Ax=b$ is the equation to solve. This equation will be overdetermined so you'll need to approximate the solution.&#xD;&#xA;&#xD;&#xA;This means doing a [linear regression][1] to find the coefficients that give the smallest error. This is well described in linear algebra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Linear_regression" ContentLicense="CC BY-SA 3.0" />
  <row Id="13175" PostHistoryTypeId="4" PostId="4997" RevisionGUID="b0527e3f-1ed0-46e8-97bf-bf00e0c8c21e" CreationDate="2017-04-15T10:53:36.147" UserId="385" Comment="Fixed title" Text="Spherical Harmonics Diffuse CubeMap. How to get coefficients?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13177" PostHistoryTypeId="5" PostId="4999" RevisionGUID="8a960ce8-909d-4ed0-be99-8333a4eee1d5" CreationDate="2017-04-15T11:04:39.243" UserId="6454" Comment="added 4864 characters in body" Text="In [this][1] question I asked how to implement a chain of blurs in one single step. &#xD;&#xA;&#xD;&#xA;Then I found out from the [gaussian blur][2] page of Wikipedia that:&#xD;&#xA;&#xD;&#xA;&gt; Applying multiple, successive gaussian blurs to an image has the same&#xD;&#xA;&gt; effect as applying a single, larger gaussian blur, whose radius is the&#xD;&#xA;&gt; square root of the sum of the squares of the blur radii that were&#xD;&#xA;&gt; actually applied. For example, applying successive gaussian blurs with&#xD;&#xA;&gt; radii of 6 and 8 gives the same results as applying a single gaussian&#xD;&#xA;&gt; blur of radius 10, since sqrt {6^{2}+8^{2}}=10.&#xD;&#xA;&#xD;&#xA;So I thought that `blur` and `singleBlur` were the same in the following code:&#xD;&#xA;&#xD;&#xA;    cv::Mat firstLevel;&#xD;&#xA;    float sigma1, sigma2;&#xD;&#xA;    //intialize firstLevel, sigma1 and sigma2&#xD;&#xA;    cv::Mat blur = gaussianBlur(firstLevel, sigma1);&#xD;&#xA;            blur = gaussianBlur(blur, sigma2);&#xD;&#xA;    float singleSigma = std::sqrt(std::pow(sigma1,2)+std::pow(sigma2,2));&#xD;&#xA;    cv::Mat singleBlur = gaussianBlur(firstLevel, singleSigma);&#xD;&#xA;	cv::Mat diff = blur != singleBLur;&#xD;&#xA;	// Equal if no elements disagree&#xD;&#xA;	assert( cv::countNonZero(diff) == 0);&#xD;&#xA;&#xD;&#xA;But this `assert` fails (and actually, for example, the first row of `blur` is different from the first one of `singleBlur`).&#xD;&#xA;&#xD;&#xA;Why?&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;After different comments asking for more information, I'll update the answer. &#xD;&#xA;&#xD;&#xA;What I'm trying to do is to parallelize [this](https://github.com/perdoch/hesaff) code. In particular, I'm focusing now on computing all the blurs at all levels in advance. The serial code (**which works correctly**) is the following:&#xD;&#xA;&#xD;&#xA;       vector&lt;Mat&gt; blurs ((par.numberOfScales+3)*levels, Mat());&#xD;&#xA;       cv::Mat octaveLayer = firstLevel;&#xD;&#xA;       int scaleCycles = par.numberOfScales+2;&#xD;&#xA;&#xD;&#xA;       //compute blurs at all layers (not parallelizable)&#xD;&#xA;       for(int i=0; i&lt;levels; i++){&#xD;&#xA;    	   blurs[i*scaleCycles+1] = octaveLayer.clone();&#xD;&#xA;    	   for (int j = 1; j &lt; scaleCycles; j++){&#xD;&#xA;    		   float sigma = par.sigmas[j]* sqrt(sigmaStep * sigmaStep - 1.0f);&#xD;&#xA;    		   blurs[j+1+i*scaleCycles] = gaussianBlur(blurs[j+i*scaleCycles], sigma);&#xD;&#xA;    		   if(j == par.numberOfScales)&#xD;&#xA;    			   octaveLayer = halfImage(blurs[j+1+i*scaleCycles]);&#xD;&#xA;    	   }&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;I'm sorry for the horrible indexes above, but I tried to respect the original code system (which is horrible, like starting counting from `1` instead of `0`). The code above has `scaleCycles=5` and `levels=6`, so 30 blurs are generated in total.&#xD;&#xA;&#xD;&#xA;This is the &quot;single blur&quot; version, where first I compute the sigmas for each blur that has to be computed (following Wikipedia's formula) and then I apply the blur (notice that this is still serial and not parallelizable):&#xD;&#xA;&#xD;&#xA;       vector&lt;Mat&gt; singleBlurs ((par.numberOfScales+3)*levels, Mat());&#xD;&#xA;       vector&lt;float&gt; singleSigmas(scaleCycles);&#xD;&#xA;       float acc = 0;&#xD;&#xA;       for (int j = 1; j &lt; scaleCycles; j++){&#xD;&#xA;    	   float sigma = par.sigmas[j]* sqrt(sigmaStep * sigmaStep - 1.0f);&#xD;&#xA;    	   acc += pow(sigma, 2);&#xD;&#xA;    	   singleSigmas[j] = sqrt(acc);&#xD;&#xA;       }&#xD;&#xA;    &#xD;&#xA;       octaveLayer = firstLevel;&#xD;&#xA;       for(int i=0; i&lt;levels; i++){&#xD;&#xA;    	   singleBlurs[i*scaleCycles+1] = octaveLayer.clone();&#xD;&#xA;    	   for (int j = 1; j &lt; scaleCycles; j++){&#xD;&#xA;    		   float sigma = singleSigmas[j];&#xD;&#xA;    		   std::cout&lt;&lt;&quot;j=&quot;&lt;&lt;j&lt;&lt;&quot; sigma=&quot;&lt;&lt;sigma&lt;&lt;std::endl;&#xD;&#xA;    		   singleBlurs[j+1+i*scaleCycles] = gaussianBlur(singleBlurs[j+i*scaleCycles], sigma);&#xD;&#xA;    		   if(j == par.numberOfScales)&#xD;&#xA;    			   octaveLayer = halfImage(singleBlurs[j+1+i*scaleCycles]);&#xD;&#xA;    	   }&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;Of course the code above generates 30 blurs also with the same parameters of the previous version.&#xD;&#xA;&#xD;&#xA;And then this is the code to see the difference between each `signgleBlurs` and `blurs`:&#xD;&#xA;&#xD;&#xA;       assert(blurs.size() == singleBlurs.size());&#xD;&#xA;       vector&lt;Mat&gt; blurDiffs(blurs.size());&#xD;&#xA;       for(int i=1; i&lt;levels*scaleCycles; i++){&#xD;&#xA;    	    cv::Mat diff;&#xD;&#xA;    	    absdiff(blurs[i], singleBlurs[i], diff);&#xD;&#xA;    		std::cout&lt;&lt;&quot;i=&quot;&lt;&lt;i&lt;&lt;&quot;diff rows=&quot;&lt;&lt;diff.rows&lt;&lt;&quot; cols=&quot;&lt;&lt;diff.cols&lt;&lt;std::endl;&#xD;&#xA;    		blurDiffs[i] = diff;&#xD;&#xA;    		std::cout&lt;&lt;&quot;blurs rows=&quot;&lt;&lt;blurs[i].rows&lt;&lt;&quot; cols=&quot;&lt;&lt;blurs[i].cols&lt;&lt;std::endl;&#xD;&#xA;    		std::cout&lt;&lt;&quot;singleBlurs rows=&quot;&lt;&lt;singleBlurs[i].rows&lt;&lt;&quot; cols=&quot;&lt;&lt;singleBlurs[i].cols&lt;&lt;std::endl;&#xD;&#xA;    		std::cout&lt;&lt;&quot;blurDiffs rows=&quot;&lt;&lt;blurDiffs[i].rows&lt;&lt;&quot; cols=&quot;&lt;&lt;blurDiffs[i].cols&lt;&lt;std::endl;&#xD;&#xA;    		namedWindow( &quot;blueDiffs[&quot;+std::to_string(i)+&quot;]&quot;, WINDOW_AUTOSIZE );// Create a window for display.&#xD;&#xA;    		//imshow( &quot;blueDiffs[&quot;+std::to_string(i)+&quot;]&quot;, blurDiffs[i] );                   // Show our image inside it.&#xD;&#xA;    		//waitKey(0);                                          // Wait for a keystroke in the window&#xD;&#xA;    		Mat imageF_8UC3;&#xD;&#xA;    		std::cout&lt;&lt;&quot;converting...&quot;&lt;&lt;std::endl;&#xD;&#xA;    		blurDiffs[i].convertTo(imageF_8UC3, CV_8U, 255);&#xD;&#xA;    		std::cout&lt;&lt;&quot;converted&quot;&lt;&lt;std::endl;&#xD;&#xA;    		imwrite( &quot;blurDiffs_&quot;+std::to_string(i)+&quot;.jpg&quot;, imageF_8UC3);&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;Now, what I've seen is that `blurDiffs_1.jpg` and `blurDiffs_2.jpg` are black, but suddendly from `blurDiffs_3.jpg` until the `blurDiffs_29.jpg` becomes whiter and whiter. For some reason, `blurDiffs_30.jpg` is almost completely black.&#xD;&#xA;&#xD;&#xA;**The first (correct) version generates 1761 descriptors. The second  (uncorrect) version generates &gt;2.3k descriptors.**&#xD;&#xA;&#xD;&#xA;I can't post the `blurDiffs` matrices because (especially the first ones) are very big and post's space is limited. I'll post some samples. I'll not post `blurDiffs_1.jpg` and `blurDiffs_2.jpg` because they're totally blacks. Notice that because of `halfImage` the images become smaller and smaller (as expected).&#xD;&#xA;&#xD;&#xA;**blurDiffs_3.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**blurDiffs_6.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4] &#xD;&#xA;&#xD;&#xA;**blurDiffs_15.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**blurDiffs_29.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;**If you need any more details, please let me know**.&#xD;&#xA;&#xD;&#xA;  [1]: http://stackoverflow.com/questions/43163337/parallelize-chain-of-gaussian-blurs&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Gaussian_blur&#xD;&#xA;  [3]: https://i.stack.imgur.com/e0xLz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/58ciq.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/yv8kd.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/EeoDd.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13178" PostHistoryTypeId="2" PostId="5001" RevisionGUID="f3e7bd6a-b495-4907-8e91-d7b46d78c192" CreationDate="2017-04-15T11:40:06.890" UserId="4958" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1], there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at some point of your scene using dot product:&#xD;&#xA;Sh coeffs below are constructed as above but using normal for reconstruction and L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;Disclaimer: This basically works but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13179" PostHistoryTypeId="5" PostId="5001" RevisionGUID="516819a9-3638-4b3f-9f35-b70cbe4ddf95" CreationDate="2017-04-15T11:45:16.277" UserId="4958" Comment="added 4 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1], there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at some point of your scene using dot product:&#xD;&#xA;Sh coeffs below are constructed as above but using normal for reconstruction and L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works but I am not an expert and something might be missing (like some division by pi I didn't care much about) or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13180" PostHistoryTypeId="5" PostId="5001" RevisionGUID="f17c1dac-3c70-4dad-9533-f46754744a63" CreationDate="2017-04-15T11:50:19.100" UserId="4958" Comment="added 4 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at some point of your scene using dot product:&#xD;&#xA;Sh coeffs below are constructed as above but using normal for reconstruction and L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13181" PostHistoryTypeId="5" PostId="5001" RevisionGUID="772072c5-a58f-4034-b4ee-2c1b74121f11" CreationDate="2017-04-15T12:20:52.710" UserId="4958" Comment="added 471 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at some point of your scene using dot product:&#xD;&#xA;&#xD;&#xA;    // cosine lobe in SH&#xD;&#xA;        float sh00  = 0.886226;&#xD;&#xA;        float sh1_1 = 1.023326 * dir.y;&#xD;&#xA;        float sh10  = 1.023326 * dir.z;&#xD;&#xA;        float sh11  = 1.023326 * dir.x;&#xD;&#xA;        float sh2_2 = 0.858086 * dir.x * dir.y;&#xD;&#xA;        float sh2_1 = 0.858086 * dir.y * dir.z;&#xD;&#xA;        float sh20  = 0.743125 * dir.z * dir.z - 0.247708;&#xD;&#xA;        float sh21  = 0.858086 * dir.x * dir.z;&#xD;&#xA;        float sh22  = 0.429043 * (dir.x * dir.x - dir.y * dir.y);&#xD;&#xA;&#xD;&#xA;Sh coeffs below are constructed as above (using cosine lobe) but using normal for reconstruction and L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13182" PostHistoryTypeId="5" PostId="5001" RevisionGUID="da106a2a-a000-4cef-bfd4-d7ebcfc73471" CreationDate="2017-04-15T12:39:52.197" UserId="4958" Comment="added 3 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at some point of your scene using dot product:&#xD;&#xA;&#xD;&#xA;    // cosine lobe in SH&#xD;&#xA;        float sh00  = 0.886226;&#xD;&#xA;        float sh11  = 1.023326 * dir.x;&#xD;&#xA;        float sh10  = 1.023326 * dir.z;&#xD;&#xA;        float sh1_1 = 1.023326 * dir.y; &#xD;&#xA;        float sh21  = 0.858086 * dir.x * dir.z;  &#xD;&#xA;        float sh2_1 = 0.858086 * dir.y * dir.z;&#xD;&#xA;        float sh2_2 = 0.858086 * dir.x * dir.y;&#xD;&#xA;        float sh20  = 0.743125 * dir.z * dir.z - 0.247708;&#xD;&#xA;        float sh22  = 0.429043 * (dir.x * dir.x - dir.y * dir.y);&#xD;&#xA;&#xD;&#xA;Sh coeffs below are constructed as above (using cosine lobe) but using normal for reconstruction and L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13183" PostHistoryTypeId="2" PostId="5002" RevisionGUID="a4e8fd1c-cd08-4914-82d8-60c2a4567cc7" CreationDate="2017-04-15T13:22:49.767" UserId="5225" Text="Would it be possible to make text significantly more legible in VR? I know there are hardware limitations, but are there hanging fruit techniques that aren't being employed in 3D that are in 2D (vector based rendering, signed distance field rendering, and so forth)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13184" PostHistoryTypeId="1" PostId="5002" RevisionGUID="a4e8fd1c-cd08-4914-82d8-60c2a4567cc7" CreationDate="2017-04-15T13:22:49.767" UserId="5225" Text="Rendering Crystal Clear 3D Text in VR" ContentLicense="CC BY-SA 3.0" />
  <row Id="13185" PostHistoryTypeId="3" PostId="5002" RevisionGUID="a4e8fd1c-cd08-4914-82d8-60c2a4567cc7" CreationDate="2017-04-15T13:22:49.767" UserId="5225" Text="|virtual-reality|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13186" PostHistoryTypeId="2" PostId="5003" RevisionGUID="f728e1ce-bba8-45da-a4df-c929e59cc698" CreationDate="2017-04-16T07:15:25.497" UserId="6462" Text="I made this flowchart with draw.io:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It was the first chart I made so it took me a while to make it. I need to be able to dynamically generate variations of this diagram programmatically. I wold need to do things like change the colours of the human shapes, change the text and colours of the boxes. And the trickiest part I think would be adding more children or less children. I want to make it possible to generate diagrams that can have up to 10 children.  &#xD;&#xA;&#xD;&#xA;The only image programming I have ever done was with PHP GD library, I have don't even know what modern graphics experts use for programmatically generating images. I have read about vector images that are programmed, and I read a little bit about HTML5 canvas. &#xD;&#xA;&#xD;&#xA;The javascript flowchar and diagram creation frameworks seem very complicated. If I found one with this particular type of flowchart as a template I could use it, but it would still be difficult. The most ideal scenario would be if I use a visual builder program like draw.io to build a template, and it would output the raw code that I could then convert function for generating these charts dynamically. &#xD;&#xA;&#xD;&#xA;Does anyone know how this can be done? There are actually lots of diagrams I need to be able to make programatically, like metabolic pathways:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What would be the best way of going about generating these kinds of diagrams programatically? The first one would become a great tool for learning about genetics if I can do this. Any insight would be much appreciated. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DQSOf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Iv8r4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13187" PostHistoryTypeId="1" PostId="5003" RevisionGUID="f728e1ce-bba8-45da-a4df-c929e59cc698" CreationDate="2017-04-16T07:15:25.497" UserId="6462" Text="Can draw.io type flowcharts be programmed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13188" PostHistoryTypeId="3" PostId="5003" RevisionGUID="f728e1ce-bba8-45da-a4df-c929e59cc698" CreationDate="2017-04-16T07:15:25.497" UserId="6462" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13193" PostHistoryTypeId="2" PostId="5005" RevisionGUID="670dba9a-b274-4af8-888b-09ada755ddd4" CreationDate="2017-04-17T06:12:54.330" UserId="3003" Text="If you look at [chapter 8](https://www.w3.org/TR/SVG/paths.html) of the [SVG Specification](https://www.w3.org/TR/SVG/), it describes how to parse a `path` element. The short version is that you'll want to find the `d` attribute of the element. That element should be a string describing the curve. It will contain the following commands:&#xD;&#xA;&#xD;&#xA; - `m` - Moveto command&#xD;&#xA; - `l` - Lineto command&#xD;&#xA; - `c`, `s`, `q`, &amp; `a` - Curve commands&#xD;&#xA; - `z` - close path&#xD;&#xA;&#xD;&#xA;Simple lines will just be combinations of `m` and `l` sequences. The curves will be either circular arcs, quadratic bezier or cubic beziers.&#xD;&#xA;&#xD;&#xA;To convert a Bezier curve into line segments, you can do the following:&#xD;&#xA;&#xD;&#xA;    const float kNumPolyLines = 10; // &lt;- change this to make more lines per bezier segment&#xD;&#xA;    const float kDeltaT = 1.0 / kNumPolyLines;&#xD;&#xA;    Point c0;&#xD;&#xA;    Point c1;&#xD;&#xA;    Point c2;&#xD;&#xA;    Point c3;&#xD;&#xA;    GetBezierControlPoints(&amp;c0, &amp;c1, &amp;c2, &amp;c3); // &lt;- get the 3 or 4 control points for the next bezier segment&#xD;&#xA;    Point prevPoint = c0;&#xD;&#xA;    Point currentPoint;&#xD;&#xA;    for (float t = kDeltaT; t &lt;= 1.0; t += kDeltaT)&#xD;&#xA;    {&#xD;&#xA;        currentPoint = CalculateBezier(c0, c1, c2, c3, t);&#xD;&#xA;        &#xD;&#xA;        // Now you have the next line segment in your poly line. &#xD;&#xA;        // It goes from prevPoint to currentPoint. Store it or draw it, &#xD;&#xA;        //or whatever you need&#xD;&#xA;        &#xD;&#xA;        // Get ready for the next iteration&#xD;&#xA;        prevPoint = currentPoint;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can find the formula for both quadratic and cubic bezier curves [on Wikipedia](https://en.wikipedia.org/wiki/Bézier_curve#Specific_cases)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13195" PostHistoryTypeId="5" PostId="5001" RevisionGUID="71dce5fd-c11e-4d8b-ba41-bbc73c436703" CreationDate="2017-04-17T23:27:24.123" UserId="4958" Comment="added 226 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at given point of your scene using dot product:&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;Sh coeffs for reconstruction are constructed as below with performing convolution with cosine lobe using normal at given point of scene. L coeffs are sampled from data structure.&#xD;&#xA;Convolution means, for each SH order, multiplication by $[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$, so we get:&#xD;&#xA; &#xD;&#xA;       // cosine lobe in SH&#xD;&#xA;            float sh00  = 0.886226;&#xD;&#xA;            float sh11  = 1.023326 * normal.x;&#xD;&#xA;            float sh10  = 1.023326 * normal.z;&#xD;&#xA;            float sh1_1 = 1.023326 * normal.y; &#xD;&#xA;            float sh21  = 0.858086 * normal.x * normal.z;  &#xD;&#xA;            float sh2_1 = 0.858086 * normal.y * normal.z;&#xD;&#xA;            float sh2_2 = 0.858086 * normal.x * normal.y;&#xD;&#xA;            float sh20  = 0.743125 * normal.z * normal.z - 0.247708;&#xD;&#xA;            float sh22  = 0.429043 * (normal.x * normal.x - normal.y * normal.y);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13196" PostHistoryTypeId="5" PostId="5001" RevisionGUID="d84bf330-62cd-42f7-a856-9355825b7cf1" CreationDate="2017-04-17T23:36:24.060" UserId="4958" Comment="added 55 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float sh00     = 0.282095;&#xD;&#xA;    float sh11     = 0.488603 * normal.x;&#xD;&#xA;    float sh10     = 0.488603 * normal.z;&#xD;&#xA;    float sh1_1    = 0.488603 * normal.y;&#xD;&#xA;    float sh21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float sh2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float sh2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float sh20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float sh22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * sh00;&#xD;&#xA;    vec3 L11   = L * sh11;&#xD;&#xA;    vec3 L10   = L * sh10;&#xD;&#xA;    vec3 L1_1  = L * sh1_1;&#xD;&#xA;    vec3 L21   = L * sh21;&#xD;&#xA;    vec3 L2_1  = L * sh2_1;&#xD;&#xA;    vec3 L2_2  = L * sh2_2;&#xD;&#xA;    vec3 L20   = L * sh20;&#xD;&#xA;    vec3 L22   = L * sh22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at given point of your scene using dot product:&#xD;&#xA;&#xD;&#xA;    vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;Sh coeffs for reconstruction are constructed as below with, for approximating diffuse irradiance at given point of scene, performing convolution with cosine lobe using normal from that point. L coeffs are sampled from data structure.&#xD;&#xA;Convolution means, for each SH order, multiplication by $[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$, so we get:&#xD;&#xA; &#xD;&#xA;       // cosine lobe in SH&#xD;&#xA;            float sh00  = 0.886226;&#xD;&#xA;            float sh11  = 1.023326 * normal.x;&#xD;&#xA;            float sh10  = 1.023326 * normal.z;&#xD;&#xA;            float sh1_1 = 1.023326 * normal.y; &#xD;&#xA;            float sh21  = 0.858086 * normal.x * normal.z;  &#xD;&#xA;            float sh2_1 = 0.858086 * normal.y * normal.z;&#xD;&#xA;            float sh2_2 = 0.858086 * normal.x * normal.y;&#xD;&#xA;            float sh20  = 0.743125 * normal.z * normal.z - 0.247708;&#xD;&#xA;            float sh22  = 0.429043 * (normal.x * normal.x - normal.y * normal.y);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13197" PostHistoryTypeId="5" PostId="4997" RevisionGUID="b96b2a47-9c47-4577-8f81-4570940ae202" CreationDate="2017-04-18T00:57:30.620" UserId="6282" Comment="added 772 characters in body" Text="https://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;http://xlgames-inc.github.io/posts/sphericalharmonics0/&#xD;&#xA;&#xD;&#xA;I am using Spherical Harmonics to turn reflective(mirror like) cube map to diffuse light cube map.&#xD;&#xA;&#xD;&#xA;From what I understand for an image, I calculate 9 coefficient(for red green blue) that describes the color of the cube map.&#xD;&#xA;&#xD;&#xA;The nine coefficients are this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And when you visualize them they become...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I do something with these coefficients to get color of the cube map.&#xD;&#xA;&#xD;&#xA;The part that I am not understanding is using an image to get that 9 coefficients. All the papers kinda assume that you somehow got that coefficient calculated because it is &quot;easy&quot;.&#xD;&#xA;&#xD;&#xA;I don't know how to do that calculation.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;After reading narthex's answer...&#xD;&#xA;This is the final equation for irradiance that the paper gives you...&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And I linked parts of answer that I believe corresponds to the sections of the equation but the &quot;green part&quot; of the equation is still mystery to me.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;narthex's answer &#xD;&#xA;&#xD;&#xA;&gt; vec3 color = sh00*L00 + sh1_1*L1_1 + sh10*L10 + sh11*L11 + sh2_2*L2_2 + sh2_1*L2_1 + sh20*L20 + sh21*L21 + sh22*L22;&#xD;&#xA;&#xD;&#xA;Didn't seem to require any further values; didn't seem to require that green part of the equation.&#xD;&#xA;&#xD;&#xA;Why is that? Am I understanding something wrong? Are there multiple ways to do this?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kmjyY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oRvEP.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yCRpa.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NaVou.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13199" PostHistoryTypeId="2" PostId="5006" RevisionGUID="5e090241-709c-424c-8cba-93d6e4ae2149" CreationDate="2017-04-18T05:51:03.983" UserId="2687" Text="Given a triangle and a point inside the triangle in Cartesian coordinate system, I compute the Barycentric coordinate of the point like this:&#xD;&#xA;&#xD;&#xA;    double v0[3], v1[3], v2[3];&#xD;&#xA;&#xD;&#xA;	double bary[3];&#xD;&#xA;	vtkMath::Subtract(p1, p2, v0);&#xD;&#xA;	vtkMath::Subtract(p3, p2, v1);&#xD;&#xA;	vtkMath::Subtract(t, p2, v2);&#xD;&#xA;&#xD;&#xA;	float d00 = vtkMath::Dot(v0, v0);&#xD;&#xA;	float d01 = vtkMath::Dot(v0, v1);&#xD;&#xA;	float d11 = vtkMath::Dot(v1, v1);&#xD;&#xA;	float denom = d00 * d11 - d01 * d01;&#xD;&#xA;&#xD;&#xA;	float d20 = vtkMath::Dot(v2, v0);&#xD;&#xA;	float d21 = vtkMath::Dot(v2, v1);&#xD;&#xA;	bary[0] = (d11 * d20 - d01 * d21) / denom;&#xD;&#xA;	bary[1] = (d00 * d21 - d01 * d20) / denom;&#xD;&#xA;	bary[2] = 1.0f - bary[0] - bary[1];&#xD;&#xA;&#xD;&#xA;	return bary;&#xD;&#xA;&#xD;&#xA;Now, how can I use the values in `bary` to interpolate the vertex normal at `p1`, `p2` and `p3`? Specifically, I'm confused which coefficient belongs to which vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="13200" PostHistoryTypeId="1" PostId="5006" RevisionGUID="5e090241-709c-424c-8cba-93d6e4ae2149" CreationDate="2017-04-18T05:51:03.983" UserId="2687" Text="How do I use barycentric coordinates to interpolate vertex normal?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13201" PostHistoryTypeId="3" PostId="5006" RevisionGUID="5e090241-709c-424c-8cba-93d6e4ae2149" CreationDate="2017-04-18T05:51:03.983" UserId="2687" Text="|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13202" PostHistoryTypeId="5" PostId="5001" RevisionGUID="9fdfd8bf-a262-437f-a99d-f72607b94fc9" CreationDate="2017-04-18T09:10:15.040" UserId="4958" Comment="deleted 530 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float Y00     = 0.282095;&#xD;&#xA;    float Y11     = 0.488603 * normal.x;&#xD;&#xA;    float Y10     = 0.488603 * normal.z;&#xD;&#xA;    float Y1_1    = 0.488603 * normal.y;&#xD;&#xA;    float Y21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float Y2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float Y2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float Y20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float Y22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * Y00;&#xD;&#xA;    vec3 L11   = L * Y11;&#xD;&#xA;    vec3 L10   = L * Y10;&#xD;&#xA;    vec3 L1_1  = L * Y1_1;&#xD;&#xA;    vec3 L21   = L * Y21;&#xD;&#xA;    vec3 L2_1  = L * Y2_1;&#xD;&#xA;    vec3 L2_2  = L * Y2_2;&#xD;&#xA;    vec3 L20   = L * Y20;&#xD;&#xA;    vec3 L22   = L * Y22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing you use normal at given point of your scene using dot product and, for approximating diffuse irradiance at given point of scene, performing convolution with cosine lobe using normal from that point. L coeffs are sampled from data structure.&#xD;&#xA;Convolution means, for each SH order, multiplication by $ \hat{A}=[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$&#xD;&#xA;&#xD;&#xA;$\hat{A_0} = 3.141593$, &#xD;&#xA;$\hat{A_1} = 2.094395$, &#xD;&#xA;$\hat{A_2} = 0.785398$&#xD;&#xA;&#xD;&#xA;    vec3 color = A1*Y00*L00 + A2*Y1_1*L1_1 + A2*Y10*L10 + A2*Y11*L11 + A3*Y2_2*L2_2 + A3*Y2_1*L2_1 + A3*Y20*L20 + A3*Y21*L21 + A3*Y22*L22;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13203" PostHistoryTypeId="6" PostId="5003" RevisionGUID="bedbce88-bf76-4f0b-9dbd-1f9f8b756b92" CreationDate="2017-04-18T09:11:11.950" UserId="2041" Comment="add more specific tags" Text="|2d-graphics|diagram|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13204" PostHistoryTypeId="5" PostId="5001" RevisionGUID="475e2fc5-ff41-40e1-a848-4e78a54a7476" CreationDate="2017-04-18T09:20:29.160" UserId="4958" Comment="deleted 530 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float Y00     = 0.282095;&#xD;&#xA;    float Y11     = 0.488603 * normal.x;&#xD;&#xA;    float Y10     = 0.488603 * normal.z;&#xD;&#xA;    float Y1_1    = 0.488603 * normal.y;&#xD;&#xA;    float Y21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float Y2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float Y2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float Y20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float Y22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * Y00;&#xD;&#xA;    vec3 L11   = L * Y11;&#xD;&#xA;    vec3 L10   = L * Y10;&#xD;&#xA;    vec3 L1_1  = L * Y1_1;&#xD;&#xA;    vec3 L21   = L * Y21;&#xD;&#xA;    vec3 L2_1  = L * Y2_1;&#xD;&#xA;    vec3 L2_2  = L * Y2_2;&#xD;&#xA;    vec3 L20   = L * Y20;&#xD;&#xA;    vec3 L22   = L * Y22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing :&#xD;&#xA;&#xD;&#xA; - compute your SH basis one more time for normal at point of the scene.&#xD;&#xA; - for approximating diffuse irradiance at given point of scene,&#xD;&#xA;   convolution with cosine lobe is performed using normal from that point.&#xD;&#xA;   Convolution means, for each SH order, multiplication by $&#xD;&#xA;   \hat{A}=[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$&#xD;&#xA;&#xD;&#xA;$\hat{A_0} = 3.141593$, &#xD;&#xA;$\hat{A_1} = 2.094395$, &#xD;&#xA;$\hat{A_2} = 0.785398$&#xD;&#xA;&#xD;&#xA; - L coeffs are sampled from data structure.      &#xD;&#xA;&#xD;&#xA;        vec3 color = A1*Y00*L00 + A2*Y1_1*L1_1 + A2*Y10*L10 + A2*Y11*L11 + A3*Y2_2*L2_2 + A3*Y2_1*L2_1 + A3*Y20*L20 + A3*Y21*L21 + A3*Y22*L22;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13205" PostHistoryTypeId="5" PostId="5001" RevisionGUID="7ed4a7ef-64d7-4134-a53b-79d6e002dc1b" CreationDate="2017-04-18T09:29:58.540" UserId="4958" Comment="deleted 530 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;So for each sample you:&#xD;&#xA;&#xD;&#xA;Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;    float Y00     = 0.282095;&#xD;&#xA;    float Y11     = 0.488603 * normal.x;&#xD;&#xA;    float Y10     = 0.488603 * normal.z;&#xD;&#xA;    float Y1_1    = 0.488603 * normal.y;&#xD;&#xA;    float Y21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float Y2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float Y2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float Y20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float Y22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA;Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * Y00;&#xD;&#xA;    vec3 L11   = L * Y11;&#xD;&#xA;    vec3 L10   = L * Y10;&#xD;&#xA;    vec3 L1_1  = L * Y1_1;&#xD;&#xA;    vec3 L21   = L * Y21;&#xD;&#xA;    vec3 L2_1  = L * Y2_1;&#xD;&#xA;    vec3 L2_2  = L * Y2_2;&#xD;&#xA;    vec3 L20   = L * Y20;&#xD;&#xA;    vec3 L22   = L * Y22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;Then when reconstructing :&#xD;&#xA;&#xD;&#xA; - compute your SH basis one more time for normal at point of the scene.&#xD;&#xA; - for approximating diffuse irradiance at given point of scene,&#xD;&#xA;   convolution with cosine lobe is performed using normal from that point.&#xD;&#xA;   Convolution means, for each SH order, multiplication by $&#xD;&#xA;   \hat{A}=[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$&#xD;&#xA;&#xD;&#xA;$\hat{A_0} = 3.141593$, &#xD;&#xA;$\hat{A_1} = 2.094395$, &#xD;&#xA;$\hat{A_2} = 0.785398$&#xD;&#xA;&#xD;&#xA; - L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec3 color = A1*Y00*L00 + A2*Y1_1*L1_1 + A2*Y10*L10 + A2*Y11*L11 + A3*Y2_2*L2_2 + A3*Y2_1*L2_1 + A3*Y20*L20 + A3*Y21*L21 + A3*Y22*L22;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13206" PostHistoryTypeId="5" PostId="5001" RevisionGUID="855f3df4-8f2b-4f1a-9a14-8ed4d5730f47" CreationDate="2017-04-18T09:35:59.733" UserId="4958" Comment="deleted 530 characters in body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;**So for constructing for each sample you:**&#xD;&#xA;&#xD;&#xA; - Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    float Y00     = 0.282095;&#xD;&#xA;    float Y11     = 0.488603 * normal.x;&#xD;&#xA;    float Y10     = 0.488603 * normal.z;&#xD;&#xA;    float Y1_1    = 0.488603 * normal.y;&#xD;&#xA;    float Y21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float Y2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float Y2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float Y20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float Y22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA; - Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * Y00;&#xD;&#xA;    vec3 L11   = L * Y11;&#xD;&#xA;    vec3 L10   = L * Y10;&#xD;&#xA;    vec3 L1_1  = L * Y1_1;&#xD;&#xA;    vec3 L21   = L * Y21;&#xD;&#xA;    vec3 L2_1  = L * Y2_1;&#xD;&#xA;    vec3 L2_2  = L * Y2_2;&#xD;&#xA;    vec3 L20   = L * Y20;&#xD;&#xA;    vec3 L22   = L * Y22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;**Then when reconstructing :**&#xD;&#xA;&#xD;&#xA; - compute your SH basis one more time for normal at point of the scene.&#xD;&#xA; - for approximating diffuse irradiance at given point of scene,&#xD;&#xA;   convolution with cosine lobe is performed using normal from that point.&#xD;&#xA;   Convolution means, for each SH order, multiplication by $&#xD;&#xA;   \hat{A}=[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$&#xD;&#xA;&#xD;&#xA;$\hat{A_0} = 3.141593$, &#xD;&#xA;$\hat{A_1} = 2.094395$, &#xD;&#xA;$\hat{A_2} = 0.785398$&#xD;&#xA;&#xD;&#xA; - L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    vec3 color = A1*Y00*L00 + A2*Y1_1*L1_1 + A2*Y10*L10 + A2*Y11*L11 + A3*Y2_2*L2_2 + A3*Y2_1*L2_1 + A3*Y20*L20 + A3*Y21*L21 + A3*Y22*L22;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13207" PostHistoryTypeId="5" PostId="5001" RevisionGUID="858f2215-388a-45f8-9c57-47028905e4c9" CreationDate="2017-04-18T09:43:21.287" UserId="4958" Comment="edited body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;**So for constructing for each sample you:**&#xD;&#xA;&#xD;&#xA; - Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    float Y00     = 0.282095;&#xD;&#xA;    float Y11     = 0.488603 * normal.x;&#xD;&#xA;    float Y10     = 0.488603 * normal.z;&#xD;&#xA;    float Y1_1    = 0.488603 * normal.y;&#xD;&#xA;    float Y21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float Y2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float Y2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float Y20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float Y22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA; - Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * Y00;&#xD;&#xA;    vec3 L11   = L * Y11;&#xD;&#xA;    vec3 L10   = L * Y10;&#xD;&#xA;    vec3 L1_1  = L * Y1_1;&#xD;&#xA;    vec3 L21   = L * Y21;&#xD;&#xA;    vec3 L2_1  = L * Y2_1;&#xD;&#xA;    vec3 L2_2  = L * Y2_2;&#xD;&#xA;    vec3 L20   = L * Y20;&#xD;&#xA;    vec3 L22   = L * Y22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;**Then when reconstructing :**&#xD;&#xA;&#xD;&#xA; - compute your SH basis one more time for normal at point of the scene.&#xD;&#xA; - for approximating diffuse irradiance at given point of scene,&#xD;&#xA;   convolution with cosine lobe is performed using normal from that point.&#xD;&#xA;   Convolution means, for each SH order, multiplication by $&#xD;&#xA;   \hat{A}=[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$&#xD;&#xA;&#xD;&#xA;$\hat{A_0} = 3.141593$, &#xD;&#xA;$\hat{A_1} = 2.094395$, &#xD;&#xA;$\hat{A_2} = 0.785398$&#xD;&#xA;&#xD;&#xA; - L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    vec3 color = A0*Y00*L00 + A1*Y1_1*L1_1 + A1*Y10*L10 + A1*Y11*L11 + A2*Y2_2*L2_2 + A2*Y2_1*L2_1 + A2*Y20*L20 + A2*Y21*L21 + A2*Y22*L22;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13208" PostHistoryTypeId="5" PostId="5001" RevisionGUID="81bfdcce-fdbc-4d42-8457-20efc0641d75" CreationDate="2017-04-18T09:48:56.267" UserId="4958" Comment="edited body" Text="So at start you have samples from your cube map. Each sample has color and normal (dir) at which you sampled that color.&#xD;&#xA;This is how I do it. I use coeffs from this [paper][1] (the same you linked), there are values for the first 9 of them.&#xD;&#xA;&#xD;&#xA;**So for constructing for each sample you:**&#xD;&#xA;&#xD;&#xA; - Compute your SH basis using normal from sample&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    float Y00     = 0.282095;&#xD;&#xA;    float Y11     = 0.488603 * normal.x;&#xD;&#xA;    float Y10     = 0.488603 * normal.z;&#xD;&#xA;    float Y1_1    = 0.488603 * normal.y;&#xD;&#xA;    float Y21     = 1.092548 * normal.x*normal.z;&#xD;&#xA;    float Y2_1    = 1.092548 * normal.y*normal.z;&#xD;&#xA;    float Y2_2    = 1.092548 * normal.y*normal.x;&#xD;&#xA;    float Y20     = 0.946176 * normal.z * normal.z - 0.315392;&#xD;&#xA;    float Y22     = 0.546274 * (normal.x*normal.x - normal.y*normal.y);&#xD;&#xA;&#xD;&#xA; - Then multiply these coeffs by your color (L)&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    vec3 L00   = L * Y00;&#xD;&#xA;    vec3 L11   = L * Y11;&#xD;&#xA;    vec3 L10   = L * Y10;&#xD;&#xA;    vec3 L1_1  = L * Y1_1;&#xD;&#xA;    vec3 L21   = L * Y21;&#xD;&#xA;    vec3 L2_1  = L * Y2_1;&#xD;&#xA;    vec3 L2_2  = L * Y2_2;&#xD;&#xA;    vec3 L20   = L * Y20;&#xD;&#xA;    vec3 L22   = L * Y22;&#xD;&#xA;&#xD;&#xA;And thats it, you have your coeffs. Now, you can store them in some data structure. You accumulate each of them like:&#xD;&#xA;&#xD;&#xA;    someArray[0] += L00;&#xD;&#xA;    someArray[1] += L11;&#xD;&#xA;    etc...&#xD;&#xA;And you divide these accumulated coeffs by a number of samples;&#xD;&#xA;&#xD;&#xA;**Then when reconstructing :**&#xD;&#xA;&#xD;&#xA; - compute your SH basis one more time for normal at point of the scene.&#xD;&#xA; - for approximating diffuse irradiance at given point of scene,&#xD;&#xA;   convolution with cosine lobe is performed using normal from that point.&#xD;&#xA;   Convolution means, for each SH order, multiplication by $&#xD;&#xA;   \hat{A}=[\pi, \frac{2}{3}\pi, \frac{\pi}{4}]$&#xD;&#xA;&#xD;&#xA;$\hat{A_0} = 3.141593$, &#xD;&#xA;$\hat{A_1} = 2.094395$, &#xD;&#xA;$\hat{A_2} = 0.785398$&#xD;&#xA;&#xD;&#xA; - L coeffs are sampled from data structure.&#xD;&#xA;&#xD;&#xA;&lt;!----&gt;&#xD;&#xA;&#xD;&#xA;    vec3 color = A0*Y00*L00  &#xD;&#xA;                 + A1*Y1_1*L1_1 + A1*Y10*L10 + A1*Y11*L11 &#xD;&#xA;                 + A2*Y2_2*L2_2 + A2*Y2_1*L2_1 + A2*Y20*L20 + A2*Y21*L21 + A2*Y22*L22;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Disclaimer:** This basically works (for me) but I am not an expert and something might be missing or not perfect because this **IS** confusing topic...&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13209" PostHistoryTypeId="5" PostId="4997" RevisionGUID="3ab1ba4e-16fe-4cbf-9ef9-76538e9f487a" CreationDate="2017-04-18T11:57:07.783" UserId="6282" Comment="added 734 characters in body" Text="https://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;http://xlgames-inc.github.io/posts/sphericalharmonics0/&#xD;&#xA;&#xD;&#xA;I am using Spherical Harmonics to turn reflective(mirror like) cube map to diffuse light cube map.&#xD;&#xA;&#xD;&#xA;From what I understand for an image, I calculate 9 coefficient(for red green blue) that describes the color of the cube map.&#xD;&#xA;&#xD;&#xA;The nine coefficients are this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And when you visualize them they become...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I do something with these coefficients to get color of the cube map.&#xD;&#xA;&#xD;&#xA;The part that I am not understanding is using an image to get that 9 coefficients. All the papers kinda assume that you somehow got that coefficient calculated because it is &quot;easy&quot;.&#xD;&#xA;&#xD;&#xA;I don't know how to do that calculation.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;After reading narthex's answer...&#xD;&#xA;This is the final equation for irradiance that the paper gives you...&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And I linked parts of answer that I believe corresponds to the sections of the equation but the &quot;green part&quot; of the equation is still mystery to me.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;narthex's answer &#xD;&#xA;&#xD;&#xA;I think I understand how to get coefficients. It is just taking normal of the &quot;mirror like cubemap&quot; then doing multiplications to get those 9 numbers&#xD;&#xA;&#xD;&#xA;And for each 9 numbers, I multiply the color of &quot;mirror like cubemap&quot;s pixel.&#xD;&#xA;&#xD;&#xA;And I believe that's what I am doing when I try to do this equation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;However I still need to do that yellow portion of the equation in order to &quot;divide&quot; the integral sum. &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;I do know that this...&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;means basically iterate through all directions(pixels) of the mirror-like-cubemap.&#xD;&#xA;&#xD;&#xA;I do know what sin(theata) is&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;But I do not understand what the following terms are&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kmjyY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oRvEP.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yCRpa.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NaVou.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iKmvr.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/9mHmH.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/Ez14Z.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/bN6d1.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/vdDSj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13210" PostHistoryTypeId="5" PostId="4997" RevisionGUID="d9b6c8e4-6718-4900-b1c9-3d6ec52f385a" CreationDate="2017-04-18T13:43:55.107" UserId="6282" Comment="added 402 characters in body" Text="https://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;http://xlgames-inc.github.io/posts/sphericalharmonics0/&#xD;&#xA;&#xD;&#xA;I am using Spherical Harmonics to turn reflective(mirror like) cube map to diffuse light cube map.&#xD;&#xA;&#xD;&#xA;From what I understand for an image, I calculate 9 coefficient(for red green blue) that describes the color of the cube map.&#xD;&#xA;&#xD;&#xA;The nine coefficients are this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And when you visualize them they become...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I do something with these coefficients to get color of the cube map.&#xD;&#xA;&#xD;&#xA;The part that I am not understanding is using an image to get that 9 coefficients. All the papers kinda assume that you somehow got that coefficient calculated because it is &quot;easy&quot;.&#xD;&#xA;&#xD;&#xA;I don't know how to do that calculation.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;After reading narthex's answer...&#xD;&#xA;This is the final equation for irradiance that the paper gives you...&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And I linked parts of answer that I believe corresponds to the sections of the equation but the &quot;green part&quot; of the equation is still mystery to me.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;narthex's answer &#xD;&#xA;&#xD;&#xA;I think I understand how to get coefficients. It is just taking normal of the &quot;mirror like cubemap&quot; then doing multiplications to get those 9 numbers&#xD;&#xA;&#xD;&#xA;And for each 9 numbers, I multiply the color of &quot;mirror like cubemap&quot;s pixel.&#xD;&#xA;&#xD;&#xA;And I believe that's what I am doing when I try to do this equation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;However I still need to do that yellow portion of the equation in order to &quot;divide&quot; the integral sum. &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;I do know that this...&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;means basically iterate through all directions(pixels) of the mirror-like-cubemap.&#xD;&#xA;&#xD;&#xA;I do know what sin(theata) is&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;But I do not understand what the following terms are&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;Update&#xD;&#xA;&#xD;&#xA;So while I were looking at http://simonstechblog.blogspot.com/2011/12/spherical-harmonic-lighting.html&#xD;&#xA;&#xD;&#xA;I found this equation...&#xD;&#xA;[![enter image description here][10]][10]&#xD;&#xA;&#xD;&#xA;So now I know that the mysterious yellow part of the equation was &quot;solid angle related&quot;. I do know how to do solid angle but I still don't understand how to do it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kmjyY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oRvEP.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yCRpa.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NaVou.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iKmvr.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/9mHmH.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/Ez14Z.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/bN6d1.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/vdDSj.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/ViYx1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13211" PostHistoryTypeId="5" PostId="4997" RevisionGUID="d88e7782-00d4-463a-9dcc-512089c00639" CreationDate="2017-04-18T15:27:05.263" UserId="6282" Comment="deleted 1196 characters in body" Text="https://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;http://xlgames-inc.github.io/posts/sphericalharmonics0/&#xD;&#xA;&#xD;&#xA;I am using Spherical Harmonics to turn reflective(mirror like) cube map to diffuse light cube map.&#xD;&#xA;&#xD;&#xA;From what I understand for an image, I calculate 9 coefficient(for red green blue) that describes the color of the cube map.&#xD;&#xA;&#xD;&#xA;The nine coefficients are this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And when you visualize them they become...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I do something with these coefficients to get color of the cube map.&#xD;&#xA;&#xD;&#xA;The part that I am not understanding is using an image to get that 9 coefficients. All the papers kinda assume that you somehow got that coefficient calculated because it is &quot;easy&quot;.&#xD;&#xA;&#xD;&#xA;I don't know how to do that calculation.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;Update&#xD;&#xA;&#xD;&#xA;So while I were looking at http://simonstechblog.blogspot.com/2011/12/spherical-harmonic-lighting.html&#xD;&#xA;&#xD;&#xA;I found this equation...&#xD;&#xA;[![enter image description here][10]][10]&#xD;&#xA;&#xD;&#xA;So now I know that the mysterious yellow part of the equation was &quot;solid angle related&quot;. I do know how to do solid angle but I still don't understand how to do it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kmjyY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oRvEP.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yCRpa.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NaVou.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iKmvr.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/9mHmH.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/Ez14Z.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/bN6d1.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/vdDSj.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/ViYx1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13212" PostHistoryTypeId="2" PostId="5007" RevisionGUID="bfacd7e0-954b-438c-9c8b-9480d74720c9" CreationDate="2017-04-19T02:08:11.633" UserId="2687" Text="You can find which coefficient belongs to which vertex empirically by changing `t` to be one of the points on the triangle (`p1, p2, p3`). Then one of the coefficients will be `1` and others are `0`. Based on that you know which coefficient belongs to which vertex. Then, interpolating the normal is trivial:&#xD;&#xA;&#xD;&#xA;    interpolatedNormal = bary[0] * p1_normal + bary[2] * p2_normal + bary[1] * p3_normal;&#xD;&#xA;&#xD;&#xA;But I'm still curious the mathematical explanation behind this." ContentLicense="CC BY-SA 3.0" />
  <row Id="13216" PostHistoryTypeId="2" PostId="5009" RevisionGUID="46fa575c-ec9a-4947-b44e-899b1716ab00" CreationDate="2017-04-19T14:56:08.043" UserId="38" Text="Thats the way your defining the vectors. See your defining vectors $V_1$ and $V_2$ as pointing outwards from the point $P_2$. \*&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now then $denom$ is the square of the area of the parallelogram of formed by completing the triangle with a duplicate of itself. Another way to look at this is that its the 2 tines the square of the are of the triangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now then the calculation:&#xD;&#xA;&#xD;&#xA;    (d11 * d20 - d01 * d21)&#xD;&#xA;&#xD;&#xA;Is the square area of the parallelogram of P2-T-P3&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now if you divide this with denom, then you have calculated the total area relative area of triangle P2-T-P3. So the formula `(d11 * d20 - d01 * d21) / denom` is the triangle size in relation to whole triangle size of: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is the weight that the opposing corner exerts on the point. which in other words it is the barycenter weight related to point $P_1$.&#xD;&#xA;&#xD;&#xA;The next line is simply the relative area of triangle P2-T-P1 or:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Which is opposite to $P_3$ being the barycentric coordinate of $P_3$.&#xD;&#xA;&#xD;&#xA;Lastly you calculate the rest which is the remaining triangle which is opposite of $P_2$.&#xD;&#xA;&#xD;&#xA;\* You could have chosen the first vectors differently for a different order.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DhmzX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/C7Rsq.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ErNBM.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/napil.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YYu3U.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13217" PostHistoryTypeId="2" PostId="5010" RevisionGUID="5f1b39dc-a0df-472f-bf75-84a2918b7202" CreationDate="2017-04-19T17:52:59.037" UserId="6475" Text="I have huge point cloud data I want to render them at interactive frame frate. Process I know is &#xD;&#xA;1.point cloud data &#xD;&#xA;2.triangulate it using delnauy or other triangulation algo&#xD;&#xA;3.surface voxelization for mesh &#xD;&#xA;4.volume tracing ti render&#xD;&#xA;&#xD;&#xA;But triangulation process is very very slow. Can I somehow voxelize my point cloud directly ??&#xD;&#xA;I am newbie to voxelization." ContentLicense="CC BY-SA 3.0" />
  <row Id="13218" PostHistoryTypeId="1" PostId="5010" RevisionGUID="5f1b39dc-a0df-472f-bf75-84a2918b7202" CreationDate="2017-04-19T17:52:59.037" UserId="6475" Text="Can i voxelize 3d set of points without reconstructing surface first?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13219" PostHistoryTypeId="3" PostId="5010" RevisionGUID="5f1b39dc-a0df-472f-bf75-84a2918b7202" CreationDate="2017-04-19T17:52:59.037" UserId="6475" Text="|rendering|performance|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13221" PostHistoryTypeId="5" PostId="2325" RevisionGUID="b5304499-1942-4147-8e99-8c712ebf81e2" CreationDate="2017-04-19T20:19:43.353" UserId="310" Comment="The code is a for a &quot;backwards&quot; path tracer, not &quot;forwards&quot;" Text="In order to understand Russian Roulette, let's look at a very basic backward path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely mathematically unbiased, bounces *should* go to infinity. But this is unrealistic, and as you noted, not visually necessary; for most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.&#xD;&#xA;&#xD;&#xA;So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.&#xD;&#xA;&#xD;&#xA;That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20. &#xD;&#xA;[![2 Bounces from Disney's Big Hero 6][1]][1]&#xD;&#xA;[![9 Bounces from Disney's Big Hero 6][2]][2]&#xD;&#xA;&#xD;&#xA;If we choose too low, the image will be visibly biased. But if we choose to high, we're wasting computation energy and time.&#xD;&#xA;&#xD;&#xA;One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias. &#xD;&#xA;&#xD;&#xA;Clamping after a threshold, will *work*, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.&#xD;&#xA;&#xD;&#xA;Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            // Randomly terminate a path with a probability inversely equal to the throughput&#xD;&#xA;            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;            if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // Add the energy we 'lose' by randomly terminating paths&#xD;&#xA;            throughput *= 1 / p;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So path with low throughput that won't contribute much to the scene are more likely to be terminated. &#xD;&#xA;&#xD;&#xA;If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last questions:&#xD;&#xA;&#xD;&#xA; 1. Does Russian Roulette give an unbiased result?&#xD;&#xA;   - Yes&#xD;&#xA; 2. Is Russian Roulette necessary for an unbiased result?&#xD;&#xA;   - Depends on what you mean by unbiased. If you mean mathematically, then yes. However, if you mean visually, then no. You just have to choose you max path depth and cutoff threshold very very carefully. This can be very tedious since it can change from scene to scene.&#xD;&#xA; 3. Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?&#xD;&#xA;   - If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still mathematically biased. To be completely unbiased, it must be random.&#xD;&#xA; 4. If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;   - Russian Roulette only stops the bouncing. It doesn't remove the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason *not* to use it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ikXSo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BPiZ7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13222" PostHistoryTypeId="5" PostId="4994" RevisionGUID="60e64bcb-42e6-4fc7-867e-bec633f09004" CreationDate="2017-04-19T21:24:24.780" UserId="310" Comment="Add a section explaining how the concepts integrate into a path tracer" Text="Short answer:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;**Importance sampling** is a method to reduce variance in Monte Carlo Integration by choosing an estimator close to the shape of the actual function.&#xD;&#xA;&#xD;&#xA;**PDF** is an abbreviation for [Probability Density Function][1]. A $pdf(x)$ gives the probability of a random sample generated being $x$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Long Answer:&#xD;&#xA;=====&#xD;&#xA;&#xD;&#xA;To start, let's review what Monte Carlo Integration is, and what it looks like mathematically. &#xD;&#xA;&#xD;&#xA;Monte Carlo Integration is an technique to estimate the value of an integral. It's typically used when there isn't a closed form solution to the integral. It looks like this:&#xD;&#xA;&#xD;&#xA;$$\int f(x) \, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;In english, this says that you can approximate an integral by averaging successive random samples from the function. As $N$ gets large, the approximation gets closer and closer to the solution. $pdf(x_{i})$ represents the probability density function of each random sample.&#xD;&#xA;&#xD;&#xA;Let's do an example: Calculate the value of the integral $I$.&#xD;&#xA;&#xD;&#xA;$$I = \int_{0}^{2\pi} e^{-x} \sin(x) dx$$&#xD;&#xA;&#xD;&#xA;Let's use Monte Carlo Integration:&#xD;&#xA;&#xD;&#xA;$$I \approx \frac{1}{N} \sum_{i=1}^N \frac{e^{-x} \sin(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;A simple python program to calculate this is:&#xD;&#xA;&#xD;&#xA;    import random&#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    N = 200000&#xD;&#xA;    TwoPi = 2.0 * math.pi&#xD;&#xA;&#xD;&#xA;    sum = 0.0&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;        x = random.uniform(0, TwoPi)&#xD;&#xA;        &#xD;&#xA;        fx = math.exp(-x) * math.sin(x)&#xD;&#xA;        pdf = 1 / (TwoPi - 0.0)&#xD;&#xA;        &#xD;&#xA;        sum += fx / pdf&#xD;&#xA;&#xD;&#xA;    I = (1 / N) * sum&#xD;&#xA;    print(I)&#xD;&#xA;&#xD;&#xA;If we run the program we get $I = 0.4986941$&#xD;&#xA;&#xD;&#xA;Using separation by parts, we can get the exact solution:&#xD;&#xA;&#xD;&#xA;$$I = \frac{1}{2} (1 − e−2π) = 0.4990663$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You'll notice that the Monte Carlo Solution is not quite correct. This is because it is an estimate. That said, as $N$ goes to infinity, the estimate should get closer and closer to the correct answer. Already at $N = 2000$ some runs are almost identical to the correct answer.&#xD;&#xA;&#xD;&#xA;A note about the PDF: In this simple example, we always take a uniform random sample. A uniform random sample means every sample has the exact same probability of being chosen. We sample in the range $[0, 2\pi]$ so, $pdf(x) = 1 / (2\pi - 0)$&#xD;&#xA;&#xD;&#xA;Importance sampling works by *not* uniformly sampling. Instead we try to choose more samples that contribute a lot to the result (important), and less samples that only contribute a little to the result (less important). Hence the name, importance sampling.&#xD;&#xA;&#xD;&#xA;If you choose a sampling function whose pdf very closely matches the shape of $f$, you can greatly reduce the variance, which means you can take less samples. However, if you choose a sampling function whose value is very different from $f$, you can ***increase*** the variance. See the picture below:&#xD;&#xA;[![Comparison of good sampling vs bad sampling][2]][2]&#xD;&#xA;Image from Wojciech Jarosz's [Dissertation Appendix A][3]&#xD;&#xA;&#xD;&#xA;One example of importance sampling in Path Tracing is how to choose the direction of a ray when after it hits a surface. If the surface is not perfectly specular (ie. a mirror or glass), the outgoing ray can be anywhere in the hemisphere.&#xD;&#xA;&#xD;&#xA;[![Outgoing rays can go anywhere in the hemisphere][4]][4]&#xD;&#xA;&#xD;&#xA;We ***could*** uniformly sample the hemisphere to generate the new ray. However, we can exploit the fact that the rendering equation has a cosine factor in it:&#xD;&#xA;&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) + \int_{\Omega} f(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}$$&#xD;&#xA;&#xD;&#xA;Specifically, we know that any rays at the horizon will be heavily attenuated (specifically, $\cos(x)$ ). So, rays generated near the horizon will not contribute very much to the final value.&#xD;&#xA;&#xD;&#xA;To combat this, we use importance sampling. If we generate rays according to a cosine weighted hemisphere, we ensure that more rays are generated well above the horizon, and less near the horizon. This will lower variance and reduce noise.&#xD;&#xA;&#xD;&#xA;In your case, you specified that you will be using a Cook-Torrance, microfacet-based BRDF. The common form being:&#xD;&#xA;&#xD;&#xA;$$f(p, \omega_{\text{i}}, \omega_{\text{o}}) = \frac{F(\omega_{\text{i}}, h) G(\omega_{\text{i}}, \omega_{\text{o}}, h) D(h)}{4 \cos(\theta_{i}) \cos(\theta_{o})}$$&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;$$F(\omega_{\text{i}}, h) = \text{Fresnel function} \\&#xD;&#xA;G(\omega_{\text{i}}, \omega_{\text{o}}, h) = \text{Geometry Masking and Shadowing function} \\&#xD;&#xA;D(h) = \text{Normal Distribution Function}$$&#xD;&#xA;&#xD;&#xA;The blog &quot;A Graphic's Guy's Note&quot; has an excellent write up on how to sample Cook-Torrance BRDFs. I will refer you to [his blog post][5]. That said, I will try to create a brief overview below:&#xD;&#xA;&#xD;&#xA;The NDF is generally the dominant portion of the Cook-Torrance BRDF, so if we are going to importance sample, the we should sample based on the NDF.&#xD;&#xA;&#xD;&#xA;Cook-Torrance doesn't specify a specific NDF to use; we are free to choose whichever one suits our fancy. That said, there are a few popular NDFs:&#xD;&#xA;&#xD;&#xA; - GGX&#xD;&#xA; - Beckmann&#xD;&#xA; - Blinn&#xD;&#xA;&#xD;&#xA;Each NDF has it's own formula, thus each must be sampled differently. I am only going to show the final sampling function for each. If you would like to see how the formula is derived, see the blog post.&#xD;&#xA;&#xD;&#xA;**GGX** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{GGX}(m) = \frac{\alpha^2}{\pi((\alpha^2-1) \cos^2(\theta) + 1)^2}$$&#xD;&#xA;&#xD;&#xA;To sample the spherical coordinates angle $\theta$, we can use the formula:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left( \sqrt{\frac{\alpha^2}{\xi_1 (\alpha^2 - 1) + 1}} \right)$$&#xD;&#xA;&#xD;&#xA;where $\xi$ is a uniform random variable.&#xD;&#xA;&#xD;&#xA;We assume that the NDF is isotropic, so we can sample $\phi$ uniformly:&#xD;&#xA;&#xD;&#xA;$$\phi = \xi_{2}$$&#xD;&#xA;&#xD;&#xA;**Beckmann** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Beckmann}(m) = \frac{1}{\pi \alpha^2\cos^4(\theta)} e^{-\frac{\tan^2(\theta)}{\alpha^2}}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\sqrt{\frac{1}{1 = \alpha^2 \ln(1 - \xi_1)}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;Lastly, **Blinn** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Blinn}(m) = \frac{\alpha + 2}{2 \pi} (\cos(\theta))^{\alpha}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\frac{1}{\xi_{1}^{\alpha + 1}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Putting it in Practice&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;Let's look at a basic backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. At each bounce, we have to choose a new direction for the ray. As mentioned above, we ***could*** uniformly sample the hemisphere to generate the new ray. However, the code is smarter; it importance samples the new direction based on the BRDF. (Note: This is the input direction, because we are a backwards path tracer)&#xD;&#xA;&#xD;&#xA;    // Get the new ray direction&#xD;&#xA;    // Choose the direction based on the material&#xD;&#xA;    float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;    float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;Which could be implemented as:&#xD;&#xA;&#xD;&#xA;    void LambertBRDF::Sample(float3 outputDirection, float3 normal, UniformSampler *sampler) {&#xD;&#xA;        float rand = sampler-&gt;NextFloat();&#xD;&#xA;        float r = std::sqrtf(rand) * radius;&#xD;&#xA;        float theta = sampler-&gt;NextFloat() * 2.0f * M_PI;&#xD;&#xA;&#xD;&#xA;        float x = r * std::cosf(theta);&#xD;&#xA;        float y = r * std::sinf(theta);&#xD;&#xA;&#xD;&#xA;        // Project z up to the unit hemisphere&#xD;&#xA;        float z = std::sqrtf(1.0f - x * x - y * y);&#xD;&#xA;&#xD;&#xA;        return normalize(TransformToWorld(x, y, z, normal));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float3a TransformToWorld(float x, float y, float z, float3a &amp;normal) {&#xD;&#xA;        // Find an axis that is not parallel to normal&#xD;&#xA;        float3a majorAxis;&#xD;&#xA;        if (abs(normal.x) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(1, 0, 0);&#xD;&#xA;        } else if (abs(normal.y) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(0, 1, 0);&#xD;&#xA;        } else {&#xD;&#xA;            majorAxis = float3a(0, 0, 1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Use majorAxis to create a coordinate system relative to world space&#xD;&#xA;        float3a u = normalize(cross(normal, majorAxis));&#xD;&#xA;        float3a v = cross(normal, u);&#xD;&#xA;        float3a w = normal;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Transform from local coordinates to world coordinates&#xD;&#xA;        return u * x +&#xD;&#xA;               v * y +&#xD;&#xA;               w * z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float LambertBRDF::Pdf(float3 inputDirection, float3 normal) {&#xD;&#xA;        return dot(inputDirection, normal) * M_1_PI;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After we sample the inputDirection ('wi' in the code), we use that to calculate the value of the BRDF. And then we divide by the pdf as per the Monte Carlo formula:&#xD;&#xA;&#xD;&#xA;    // Accumulate the brdf attenuation&#xD;&#xA;    throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;&#xD;&#xA;Where *Eval()* is just the BRDF function itself (Lambert, Blinn-Phong, Cook-Torrance, etc.):&#xD;&#xA;&#xD;&#xA;    float3 LambertBRDF::Eval(float3 inputDirection, float3 outputDirection, float3 normal) const override {&#xD;&#xA;        return m_albedo * M_1_PI * dot(inputDirection, normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGyXh.png&#xD;&#xA;  [3]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/appendixA.pdf&#xD;&#xA;  [4]: https://i.stack.imgur.com/6crnH.png&#xD;&#xA;  [5]: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13223" PostHistoryTypeId="2" PostId="5012" RevisionGUID="8c8683a5-f035-42e5-a041-7a0d0d34711d" CreationDate="2017-04-20T04:53:53.727" UserId="6349" Text="I am pretty new to the dx12 world. As a sample project I am trying to add 2 buffers and store the output in yet another output buffer. As apart of this debugging I am trying to see if the buffers that I am loading actually have the right values. &#xD;&#xA;Thus, once the buffer is loaded, I want to put in a fence and &quot;read back the data uploaded&quot; into the CPU and print out the contents of the buffer. &#xD;&#xA;&#xD;&#xA;But I am not entirely sure how I should go about doing this. Any thoughts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13224" PostHistoryTypeId="1" PostId="5012" RevisionGUID="8c8683a5-f035-42e5-a041-7a0d0d34711d" CreationDate="2017-04-20T04:53:53.727" UserId="6349" Text="Readback Data through Buffers" ContentLicense="CC BY-SA 3.0" />
  <row Id="13225" PostHistoryTypeId="3" PostId="5012" RevisionGUID="8c8683a5-f035-42e5-a041-7a0d0d34711d" CreationDate="2017-04-20T04:53:53.727" UserId="6349" Text="|directx12|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13226" PostHistoryTypeId="5" PostId="5012" RevisionGUID="58e94120-7c20-4b5d-ac2c-21eb4af986fa" CreationDate="2017-04-20T05:17:42.067" UserId="6349" Comment="added 76 characters in body" Text="I am pretty new to the dx12 world. As a sample project I am trying to add 2 buffers and store the output in yet another output buffer. As apart of this debugging I am trying to see if the buffers that I am loading actually have the right values. &#xD;&#xA;Thus, once the buffer is loaded, I want to put in a fence and &quot;read back the data uploaded&quot; into the CPU and print out the contents of the buffer. &#xD;&#xA;After a lot of googling I thought i should use the map function in DXD12. &#xD;&#xA;&#xD;&#xA;But I am not entirely sure how I should go about doing this. Any thoughts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13227" PostHistoryTypeId="5" PostId="5009" RevisionGUID="fad47bc2-2e97-44ee-87c0-852262dc11ad" CreationDate="2017-04-20T05:27:32.077" UserId="2687" Comment="formatting" Text="Thats the way your defining the vectors. See your defining vectors $V_1$ and $V_2$ as pointing outwards from the point $P_2$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now then $denom$ is the square of the area of the parallelogram of formed by completing the triangle with a duplicate of itself. Another way to look at this is that its the 2 tines the square of the are of the triangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now then the calculation:&#xD;&#xA;&#xD;&#xA;    (d11 * d20 - d01 * d21)&#xD;&#xA;&#xD;&#xA;Is the square area of the parallelogram of $P_2$-$T$-$P_3$&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now if you divide this with denom, then you have calculated the total area relative area of triangle $P_2$-$T$-$P_3$. So the formula `(d11 * d20 - d01 * d21) / denom` is the triangle size in relation to whole triangle size of: &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is the weight that the opposing corner exerts on the point. which in other words it is the barycenter weight related to point $P_1$.&#xD;&#xA;&#xD;&#xA;The next line is simply the relative area of triangle $P_2$-$T$-$P_1$ or:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Which is opposite to $P_3$ being the barycentric coordinate of $P_3$.&#xD;&#xA;&#xD;&#xA;Lastly you calculate the rest which is the remaining triangle which is opposite of $P_2$ using `1 - bary[0] - bary[1]`.&#xD;&#xA;&#xD;&#xA;**Note**: You could have chosen the first vectors differently for a different order.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DhmzX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/C7Rsq.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ErNBM.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/napil.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YYu3U.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13228" PostHistoryTypeId="24" PostId="5009" RevisionGUID="fad47bc2-2e97-44ee-87c0-852262dc11ad" CreationDate="2017-04-20T05:27:32.077" Comment="Proposed by 2687 approved by 38 edit id of 218" ContentLicense="CC BY-SA 3.0" />
  <row Id="13229" PostHistoryTypeId="2" PostId="5013" RevisionGUID="e2252e3f-e7ce-4ec7-b123-67f40af68bba" CreationDate="2017-04-20T05:46:49.803" UserId="6475" Text="There is algorithm called as delaunay triangulation which does triangulation or points it's comparably simple to understand . But it is very slow. If you don't want to implement your own algorithm from scratch please have look at pcl &#xD;&#xA;http://pointclouds.org/documentation/tutorials/greedy_projection.php&#xD;&#xA;Also have look at CGAL&#xD;&#xA;http://www.cgal.org.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13230" PostHistoryTypeId="2" PostId="5014" RevisionGUID="b41cae65-a4f2-4cbb-86b0-5653cfbf187e" CreationDate="2017-04-20T05:56:56.747" UserId="5256" Text="What are the recommended ways to render caustics? I am aware bidirectional path tracing and photon mapping can do this. Could someone give a brief overview of photon mapping and a good resource of where to learn about implementation? " ContentLicense="CC BY-SA 3.0" />
  <row Id="13231" PostHistoryTypeId="1" PostId="5014" RevisionGUID="b41cae65-a4f2-4cbb-86b0-5653cfbf187e" CreationDate="2017-04-20T05:56:56.747" UserId="5256" Text="Caustics: methods to render?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13232" PostHistoryTypeId="3" PostId="5014" RevisionGUID="b41cae65-a4f2-4cbb-86b0-5653cfbf187e" CreationDate="2017-04-20T05:56:56.747" UserId="5256" Text="|pathtracing|photon-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13233" PostHistoryTypeId="5" PostId="5006" RevisionGUID="92731060-af18-4597-ba9a-a623f51a1c6c" CreationDate="2017-04-20T06:31:26.373" UserId="2687" Comment="added 32 characters in body" Text="Given a triangle and a point inside the triangle in Cartesian coordinate system, I compute the Barycentric coordinate of the point like this:&#xD;&#xA;&#xD;&#xA;    double v2_1[3], v2_3[3], v2_t[3];&#xD;&#xA;&#xD;&#xA;	double bary[3];&#xD;&#xA;	vtkMath::Subtract(p1, p2, v2_1);&#xD;&#xA;	vtkMath::Subtract(p3, p2, v2_3);&#xD;&#xA;	vtkMath::Subtract(t, p2, v2_t);&#xD;&#xA;&#xD;&#xA;	float d00 = vtkMath::Dot(v2_1, v2_1);&#xD;&#xA;	float d01 = vtkMath::Dot(v2_1, v2_3);&#xD;&#xA;	float d11 = vtkMath::Dot(v2_3, v2_3);&#xD;&#xA;	float denom = d00 * d11 - d01 * d01;&#xD;&#xA;&#xD;&#xA;	float d20 = vtkMath::Dot(v2_t, v2_1);&#xD;&#xA;	float d21 = vtkMath::Dot(v2_t, v2_3);&#xD;&#xA;	bary[0] = (d11 * d20 - d01 * d21) / denom;&#xD;&#xA;	bary[1] = (d00 * d21 - d01 * d20) / denom;&#xD;&#xA;	bary[2] = 1.0f - bary[0] - bary[1];&#xD;&#xA;&#xD;&#xA;	return bary;&#xD;&#xA;&#xD;&#xA;Now, how can I use the values in `bary` to interpolate the vertex normal at `p1`, `p2` and `p3`? Specifically, I'm confused which coefficient belongs to which vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="13234" PostHistoryTypeId="2" PostId="5015" RevisionGUID="05a54f5b-0564-42d9-9049-27de00d21b1c" CreationDate="2017-04-20T08:49:32.683" UserId="2448" Text="First of all, you can get caustucs just by Path Tracing. Caustics isn't a difficult phenomenon of orbitan in CG. Almost any global illimination algorithm can render it. It's just the matter of the converging speed.&#xD;&#xA;&#xD;&#xA;While (naieve) Path Tracing can render caustics. It takes a long time to clean the rendered image due to how the algorithm wirks. Photon Mapping make the converging speedfaster by doing some trick on how light pathes are interpolated. BiDriectional Path Tracing in the other hand tries to make some difficult-to-sample light path easier.&#xD;&#xA;&#xD;&#xA;Besices the two alogithm, Metropolis Ligth Transport can render caustics efficently by finding the most significant light path in the scene and explore other possiblity arround it.&#xD;&#xA;&#xD;&#xA;Here is a good lecsure on ray based rendering algorithms.&lt;br&gt;&#xD;&#xA;https://www.youtube.com/watch?v=pjc1QAI6zS0&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&#xD;&#xA;&#xD;&#xA;Path Tracing&lt;br&gt;&#xD;&#xA;https://www.youtube.com/watch?v=cDi-uti2oLQ&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=29&#xD;&#xA;&#xD;&#xA;Photon Mapping&lt;br&gt;&#xD;&#xA;https://www.youtube.com/watch?v=-1C2kL5pTbs&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=34&#xD;&#xA;&#xD;&#xA;Tere is the original paper of BDPT. It's not too difficult if you can implement ecplcite light sampling and multiple importance sampling by your self.&#xD;&#xA;https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, I reocomend the book : Physically Based Rendering: From Theory to Implementation. It talks about all the algorithms above and more. It is basiclly a must have if you want to dive deep into CG." ContentLicense="CC BY-SA 3.0" />
  <row Id="13235" PostHistoryTypeId="2" PostId="5016" RevisionGUID="a349b82b-ed2a-4ddc-a37e-a962ae15dde3" CreationDate="2017-04-20T10:54:02.307" UserId="6401" Text="I have to add a spotlight to my rotating cube so this is my code:&#xD;&#xA;&#xD;&#xA;HTML&#xD;&#xA;&#xD;&#xA;            &lt;!DOCTYPE html&gt;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;button id = &quot;ButtonX&quot;&gt;Rotate X&lt;/button&gt;&#xD;&#xA;    &lt;button id = &quot;ButtonY&quot;&gt;Rotate Y&lt;/button&gt;&#xD;&#xA;    &lt;button id = &quot;ButtonZ&quot;&gt;Rotate Z&lt;/button&gt;&#xD;&#xA;    &lt;button id = &quot;ButtonT&quot;&gt;Toggle Rotation&lt;/button&gt;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &lt;script id=&quot;vertex-shader&quot; type=&quot;x-shader/x-vertex&quot;&gt;&#xD;&#xA;    &#xD;&#xA;    attribute  vec4 vPosition;&#xD;&#xA;    attribute  vec4 vColor;&#xD;&#xA;    attribute  vec2 vTexCoord;&#xD;&#xA;    attribute  vec3 vNormal;&#xD;&#xA;    &#xD;&#xA;    uniform float shininess;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 posLightPosition;&#xD;&#xA;    uniform vec4 posAmbientProduct, posDiffuseProduct,      posSpecularProduct;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 dirLightPosition;&#xD;&#xA;    uniform vec4 dirAmbientProduct, dirDiffuseProduct,      dirSpecularProduct;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 spotLightPosition;&#xD;&#xA;    uniform vec4 spotAmbientProduct, spotDiffuseProduct,spotSpecularProduct;&#xD;&#xA;    uniform vec4 spotLightDirection;&#xD;&#xA;    uniform float lCutOff;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    varying vec4 fColor;&#xD;&#xA;    varying vec2 fTexCoord;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 theta;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // Compute the sines and cosines of theta for each of&#xD;&#xA;        //   the three axes in one computation.&#xD;&#xA;        vec3 angles = radians( theta );&#xD;&#xA;        vec3 c = cos( angles );&#xD;&#xA;        vec3 s = sin( angles );&#xD;&#xA;    &#xD;&#xA;        // Remeber: thse matrices are column-major&#xD;&#xA;        mat4 rx = mat4( 1.0,  0.0,  0.0, 0.0,&#xD;&#xA;    		    0.0,  c.x,  s.x, 0.0,&#xD;&#xA;    		    0.0, -s.x,  c.x, 0.0,&#xD;&#xA;    		    0.0,  0.0,  0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;        mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,&#xD;&#xA;    		    0.0, 1.0,  0.0, 0.0,&#xD;&#xA;    		    s.y, 0.0,  c.y, 0.0,&#xD;&#xA;    		    0.0, 0.0,  0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        mat4 rz = mat4( c.z, s.z, 0.0, 0.0,&#xD;&#xA;    		    -s.z,  c.z, 0.0, 0.0,&#xD;&#xA;    		    0.0,  0.0, 1.0, 0.0,&#xD;&#xA;    		    0.0,  0.0, 0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;        vec3 N=normalize((rz*ry*rx*vNormal).xyz);&#xD;&#xA;    &#xD;&#xA;        // positional light&#xD;&#xA;        vec3 pos=-(rz*ry*rx*vPosition).xyz;&#xD;&#xA;        vec3 posLight=posLightPosition.xyz;&#xD;&#xA;        vec3 posL=normalize(posLight-pos);&#xD;&#xA;        vec3 posE=normalize(-pos);&#xD;&#xA;        vec3 posH=normalize(posL+posE);&#xD;&#xA;        vec4 posAmbient=posAmbientProduct;&#xD;&#xA;        float posKd=max(dot(posL,N),0.0);&#xD;&#xA;        vec4 posDiffuse=posKd*posDiffuseProduct;&#xD;&#xA;        float posKs=pow(max(dot(N,posH),0.0), shininess);&#xD;&#xA;        vec4 posSpecular=posKs*posSpecularProduct;&#xD;&#xA;        if(dot(posL,N)&lt;0.0){&#xD;&#xA;        posSpecular=vec4(0.0,0.0,0.0,1.0);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // directional light&#xD;&#xA;        vec3 dirLight=dirLightPosition.xyz;&#xD;&#xA;        vec3 dirL=normalize(dirLight);&#xD;&#xA;        vec3 dirE=normalize(-pos);&#xD;&#xA;        vec3 dirH=normalize(dirL+dirE);&#xD;&#xA;        vec4 dirAmbient=dirAmbientProduct;&#xD;&#xA;        float dirKd=max(dot(dirL,N),0.0);&#xD;&#xA;        vec4 dirDiffuse=dirKd*dirDiffuseProduct;&#xD;&#xA;        float dirKs=pow(max(dot(N,dirH),0.0), shininess);&#xD;&#xA;        vec4 dirSpecular=dirKs*dirSpecularProduct;&#xD;&#xA;        if(dot(dirL,N)&lt;0.0){&#xD;&#xA;        dirSpecular=vec4(0.0,0.0,0.0,1.0);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        &#xD;&#xA;        //spotlight&#xD;&#xA;        vec3 spotLight=spotLightPosition.xyz;&#xD;&#xA;        vec3 spotL=normalize(spotLight);&#xD;&#xA;        vec3 spotE=normalize(-pos);&#xD;&#xA;        vec3 spotH=normalize(spotL+spotE);&#xD;&#xA;        vec3 spotD=spotLightDirection.xyz;&#xD;&#xA;        vec4 spotAmbient=spotAmbientProduct;&#xD;&#xA;        float spotKd=max(dot(spotL,N),0.0);&#xD;&#xA;        vec4 spotDiffuse=spotKd*spotDiffuseProduct;&#xD;&#xA;        float spotKs=pow(max(dot(N,spotH),0.0), shininess);&#xD;&#xA;        vec4 spotSpecular=spotKs*spotSpecularProduct;&#xD;&#xA;        if(dot(spotL,N)&lt;0.0){&#xD;&#xA;        spotSpecular=vec4(0.0,0.0,0.0,1.0);&#xD;&#xA;        }&#xD;&#xA;        float lEffect= dot(normalize(spotD), normalize((spotL+spotE)));&#xD;&#xA;        if(lEffect&gt;lCutOff)&#xD;&#xA;        {&#xD;&#xA;        vec4 ambient=posAmbient+dirAmbient+spotAmbient;&#xD;&#xA;        vec4 diffuse=posDiffuse+dirDiffuse+spotDiffuse;&#xD;&#xA;        vec4 specular=posSpecular+dirSpecular+spotSpecular;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        fColor = ambient+vColor*(diffuse+specular);&#xD;&#xA;        fColor.a = 1.0;&#xD;&#xA;        }&#xD;&#xA;        else{&#xD;&#xA;        vec4 ambient=posAmbient+dirAmbient;&#xD;&#xA;        vec4 diffuse=posDiffuse+dirDiffuse;&#xD;&#xA;        vec4 specular=posSpecular+dirSpecular;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        fColor = ambient+vColor*(diffuse+specular);&#xD;&#xA;        fColor.a = 1.0;&#xD;&#xA;    &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            fTexCoord = vTexCoord;&#xD;&#xA;        gl_Position = rz * ry * rx * vPosition;&#xD;&#xA;        gl_Position.z = -gl_Position.z;&#xD;&#xA;    }&#xD;&#xA;    &lt;/script&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;script id=&quot;fragment-shader&quot; type=&quot;x-shader/x-fragment&quot;&gt;&#xD;&#xA;    &#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    varying vec4 fColor;&#xD;&#xA;    varying  vec2 fTexCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D Tex0;&#xD;&#xA;    uniform sampler2D Tex1;&#xD;&#xA;    &#xD;&#xA;    void&#xD;&#xA;    main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = fColor*(texture2D(Tex0, fTexCoord)*texture2D(Tex1, fTexCoord));&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &lt;/script&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;../Common/webgl-utils.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;../Common/initShaders.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;../Common/MV.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;Homework1.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;body&gt;&#xD;&#xA;    &lt;canvas id=&quot;gl-canvas&quot; width=&quot;1024&quot; height=&quot;1024&quot;&gt;&#xD;&#xA;    Oops ... your browser doesn't support the HTML5 canvas element&#xD;&#xA;    &lt;/canvas&gt;&#xD;&#xA;    &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;  JAVASCRIPT&#xD;&#xA;&#xD;&#xA;    &quot;use strict&quot;;&#xD;&#xA;    &#xD;&#xA;    var canvas;&#xD;&#xA;    var gl;&#xD;&#xA;    &#xD;&#xA;    var numVertices  = 36;&#xD;&#xA;    &#xD;&#xA;    var texSize = 256;&#xD;&#xA;    var numChecks = 8;&#xD;&#xA;    &#xD;&#xA;    var program;&#xD;&#xA;    &#xD;&#xA;    var texture1, texture2;&#xD;&#xA;    var t1, t2;&#xD;&#xA;    var normalsArray = [];&#xD;&#xA;    &#xD;&#xA;    var dirLightPosition = vec4(1.0, 1.0, 1.0, 0.0 );&#xD;&#xA;    var dirLightAmbient = vec4(0.2, 0.2, 0.2, 1.0 );&#xD;&#xA;    var dirLightDiffuse = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var dirLightSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    var posLightPosition = vec4(1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var posLightAmbient = vec4(0.2, 0.2, 0.2, 1.0 );&#xD;&#xA;    var posLightDiffuse = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var posLightSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    var materialAmbient = vec4( 1.0, 0.0, 1.0, 1.0 );&#xD;&#xA;    var materialDiffuse = vec4( 1.0, 0.8, 0.0, 1.0 );&#xD;&#xA;    var materialSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var materialShininess = 20.0;&#xD;&#xA;    &#xD;&#xA;    var spotLightPosition = vec4(1.0, 2.0, 3.0, 1.0 );&#xD;&#xA;    var spotLightAmbient = vec4(0.2, 0.2, 0.2, 1.0 );&#xD;&#xA;    var spotLightDiffuse = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var spotLightSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var spotLightDirection = vec4(-0.5,1.0,2.0,1.0);&#xD;&#xA;    var lCutOff=0.867;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    var c;&#xD;&#xA;    &#xD;&#xA;    var flag = true;&#xD;&#xA;    &#xD;&#xA;    var image1 = new Uint8Array(4*texSize*texSize);&#xD;&#xA;    &#xD;&#xA;        for ( var i = 0; i &lt; texSize; i++ ) {&#xD;&#xA;            for ( var j = 0; j &lt;texSize; j++ ) {&#xD;&#xA;                var patchx = Math.floor(i/(texSize/numChecks));&#xD;&#xA;                var patchy = Math.floor(j/(texSize/numChecks));&#xD;&#xA;                if(patchx%2 ^ patchy%2) c = 255;&#xD;&#xA;                else c = 0;&#xD;&#xA;                //c = 255*(((i &amp; 0x8) == 0) ^ ((j &amp; 0x8)  == 0))&#xD;&#xA;                image1[4*i*texSize+4*j] = c;&#xD;&#xA;                image1[4*i*texSize+4*j+1] = c;&#xD;&#xA;                image1[4*i*texSize+4*j+2] = c;&#xD;&#xA;                image1[4*i*texSize+4*j+3] = 255;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    var image2 = new Uint8Array(4*texSize*texSize);&#xD;&#xA;    &#xD;&#xA;        // Create a checkerboard pattern&#xD;&#xA;        for ( var i = 0; i &lt; texSize; i++ ) {&#xD;&#xA;            for ( var j = 0; j &lt;texSize; j++ ) {&#xD;&#xA;                image2[4*i*texSize+4*j] = 127+127*Math.sin(0.1*i*j);&#xD;&#xA;                image2[4*i*texSize+4*j+1] = 127+127*Math.sin(0.1*i*j);&#xD;&#xA;                image2[4*i*texSize+4*j+2] = 127+127*Math.sin(0.1*i*j);&#xD;&#xA;                image2[4*i*texSize+4*j+3] = 255;&#xD;&#xA;               }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    var pointsArray = [];&#xD;&#xA;    var colorsArray = [];&#xD;&#xA;    var texCoordsArray = [];&#xD;&#xA;    &#xD;&#xA;    var texCoord = [&#xD;&#xA;        vec2(0, 0),&#xD;&#xA;        vec2(0, 1),&#xD;&#xA;        vec2(1, 1),&#xD;&#xA;        vec2(1, 0)&#xD;&#xA;    ];&#xD;&#xA;    &#xD;&#xA;    var vertices = [&#xD;&#xA;        vec4( -0.5, -0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( -0.5,  0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5,  0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5, -0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( -0.5, -0.5, -0.5, 1.0 ),&#xD;&#xA;        vec4( -0.5,  0.5, -0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5,  0.5, -0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5, -0.5, -0.5, 1.0 )&#xD;&#xA;    ];&#xD;&#xA;    &#xD;&#xA;    var vertexColors = [&#xD;&#xA;        vec4( 0.0, 0.0, 0.0, 1.0 ),  // black&#xD;&#xA;        vec4( 1.0, 0.0, 0.0, 1.0 ),  // red&#xD;&#xA;        vec4( 1.0, 1.0, 0.0, 1.0 ),  // yellow&#xD;&#xA;        vec4( 0.0, 1.0, 0.0, 1.0 ),  // green&#xD;&#xA;        vec4( 0.0, 0.0, 1.0, 1.0 ),  // blue&#xD;&#xA;        vec4( 1.0, 0.0, 1.0, 1.0 ),  // magenta&#xD;&#xA;        vec4( 0.0, 1.0, 1.0, 1.0 ),  // white&#xD;&#xA;        vec4( 0.0, 1.0, 1.0, 1.0 )   // cyan&#xD;&#xA;    ];&#xD;&#xA;    &#xD;&#xA;    var xAxis = 0;&#xD;&#xA;    var yAxis = 1;&#xD;&#xA;    var zAxis = 2;&#xD;&#xA;    var axis = xAxis;&#xD;&#xA;    &#xD;&#xA;    var theta = [45.0, 45.0, 45.0];&#xD;&#xA;    &#xD;&#xA;    var thetaLoc;&#xD;&#xA;    &#xD;&#xA;    function configureTexture() {&#xD;&#xA;        texture1 = gl.createTexture();&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture1 );&#xD;&#xA;        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);&#xD;&#xA;        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, image1);&#xD;&#xA;        gl.generateMipmap( gl.TEXTURE_2D );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,&#xD;&#xA;                          gl.NEAREST_MIPMAP_LINEAR );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;    &#xD;&#xA;        texture2 = gl.createTexture();&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture2 );&#xD;&#xA;        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);&#xD;&#xA;        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, image2);&#xD;&#xA;        gl.generateMipmap( gl.TEXTURE_2D );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,&#xD;&#xA;                          gl.NEAREST_MIPMAP_LINEAR );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    function quad(a, b, c, d) {&#xD;&#xA;    &#xD;&#xA;         var t1 = subtract(vertices[b], vertices[a]);&#xD;&#xA;         var t2 = subtract(vertices[c], vertices[b]);&#xD;&#xA;         var normal = cross(t1, t2);&#xD;&#xA;         var normal = vec3(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[a]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[0]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[b]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[1]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[c]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[2]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[a]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[0]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[c]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[2]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[d]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[3]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    function colorCube()&#xD;&#xA;    {&#xD;&#xA;        quad( 1, 0, 3, 2 );&#xD;&#xA;        quad( 2, 3, 7, 6 );&#xD;&#xA;        quad( 3, 0, 4, 7 );&#xD;&#xA;        quad( 6, 5, 1, 2 );&#xD;&#xA;        quad( 4, 5, 6, 7 );&#xD;&#xA;        quad( 5, 4, 0, 1 );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    window.onload = function init() {&#xD;&#xA;    &#xD;&#xA;        canvas = document.getElementById( &quot;gl-canvas&quot; );&#xD;&#xA;    &#xD;&#xA;        gl = WebGLUtils.setupWebGL( canvas );&#xD;&#xA;        if ( !gl ) { alert( &quot;WebGL isn't available&quot; ); }&#xD;&#xA;    &#xD;&#xA;        gl.viewport( 0, 0, canvas.width, canvas.height );&#xD;&#xA;        gl.clearColor( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;        gl.enable(gl.DEPTH_TEST);&#xD;&#xA;    &#xD;&#xA;        //&#xD;&#xA;        //  Load shaders and initialize attribute buffers&#xD;&#xA;        //&#xD;&#xA;        program = initShaders( gl, &quot;vertex-shader&quot;, &quot;fragment-shader&quot; );&#xD;&#xA;        gl.useProgram( program );&#xD;&#xA;    &#xD;&#xA;        colorCube();&#xD;&#xA;    &#xD;&#xA;        var nBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, nBuffer );&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vNormal = gl.getAttribLocation( program, &quot;vNormal&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vNormal, 3, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vNormal );&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        var cBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(colorsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vColor = gl.getAttribLocation( program, &quot;vColor&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vColor );&#xD;&#xA;    &#xD;&#xA;        var vBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer);&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vPosition = gl.getAttribLocation( program, &quot;vPosition&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vPosition );&#xD;&#xA;    &#xD;&#xA;        var tBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, tBuffer);&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(texCoordsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vTexCoord = gl.getAttribLocation( program, &quot;vTexCoord&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vTexCoord, 2, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vTexCoord );&#xD;&#xA;    &#xD;&#xA;        var dirAmbientProduct = mult(dirLightAmbient, materialAmbient);&#xD;&#xA;        var dirDiffuseProduct = mult(dirLightDiffuse, materialDiffuse);&#xD;&#xA;        var dirSpecularProduct = mult(dirLightSpecular, materialSpecular);&#xD;&#xA;    &#xD;&#xA;        var posAmbientProduct = mult(posLightAmbient, materialAmbient);&#xD;&#xA;        var posDiffuseProduct = mult(posLightDiffuse, materialDiffuse);&#xD;&#xA;        var posSpecularProduct = mult(posLightSpecular, materialSpecular);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        var spotAmbientProduct = mult(spotLightAmbient, materialAmbient);&#xD;&#xA;        var spotDiffuseProduct = mult(spotLightDiffuse, materialDiffuse);&#xD;&#xA;        var spotSpecularProduct = mult(spotLightSpecular, materialSpecular);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        configureTexture();&#xD;&#xA;    &#xD;&#xA;        gl.activeTexture( gl.TEXTURE0 );&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture1 );&#xD;&#xA;        gl.uniform1i(gl.getUniformLocation( program, &quot;Tex0&quot;), 0);&#xD;&#xA;    &#xD;&#xA;        gl.activeTexture( gl.TEXTURE1 );&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture2 );&#xD;&#xA;        gl.uniform1i(gl.getUniformLocation( program, &quot;Tex1&quot;), 1);&#xD;&#xA;    &#xD;&#xA;        thetaLoc = gl.getUniformLocation(program, &quot;theta&quot;);&#xD;&#xA;    &#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirAmbientProduct&quot;),flatten(dirAmbientProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posAmbientProduct&quot;),flatten(posAmbientProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotAmbientProduct&quot;),flatten(spotAmbientProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirDiffuseProduct&quot;),flatten(dirDiffuseProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posDiffuseProduct&quot;),flatten(posDiffuseProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotDiffuseProduct&quot;),flatten(spotDiffuseProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirSpecularProduct&quot;),flatten(dirSpecularProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posSpecularProduct&quot;),flatten(posSpecularProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotSpecularProduct&quot;),flatten(spotSpecularProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posLightPosition&quot;),flatten(posLightPosition) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirLightPosition&quot;),flatten(dirLightPosition) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotLightPosition&quot;),flatten(spotLightPosition) );&#xD;&#xA;        gl.uniform1f( gl.getUniformLocation(program,&#xD;&#xA;           &quot;shininess&quot;),materialShininess );&#xD;&#xA;        gl.uniform1f( gl.getUniformLocation(program,&#xD;&#xA;           &quot;lCutOff&quot;),lCutOff );&#xD;&#xA;        gl.uniform1f( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotLightDirection&quot;),spotLightDirection );&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;     document.getElementById(&quot;ButtonX&quot;).onclick = function(){axis = xAxis;};&#xD;&#xA;     document.getElementById(&quot;ButtonY&quot;).onclick = function(){axis = yAxis;};&#xD;&#xA;     document.getElementById(&quot;ButtonZ&quot;).onclick = function(){axis = zAxis;};&#xD;&#xA;     document.getElementById(&quot;ButtonT&quot;).onclick = function(){flag = !flag;};&#xD;&#xA;    &#xD;&#xA;        render();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    var render = function() {&#xD;&#xA;        gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);&#xD;&#xA;        if(flag) theta[axis] += 2.0;&#xD;&#xA;        gl.uniform3fv(thetaLoc, theta);&#xD;&#xA;        gl.drawArrays( gl.TRIANGLES, 0, numVertices );&#xD;&#xA;        requestAnimFrame(render);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I computed tha angle between the spotlight direction and the vector to light source from vertex and if this angle is greater than the cutoff angle defined by the spotlight I compute the three products for the Phong lighting model.&#xD;&#xA;&#xD;&#xA;Where am I wrong?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13236" PostHistoryTypeId="1" PostId="5016" RevisionGUID="a349b82b-ed2a-4ddc-a37e-a962ae15dde3" CreationDate="2017-04-20T10:54:02.307" UserId="6401" Text="WebGL Spotlight" ContentLicense="CC BY-SA 3.0" />
  <row Id="13237" PostHistoryTypeId="3" PostId="5016" RevisionGUID="a349b82b-ed2a-4ddc-a37e-a962ae15dde3" CreationDate="2017-04-20T10:54:02.307" UserId="6401" Text="|lighting|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13238" PostHistoryTypeId="5" PostId="5015" RevisionGUID="b8c706d1-337c-4d2b-92c4-46c6fa38c3f2" CreationDate="2017-04-20T16:12:17.620" UserId="5256" Comment="Tried to improve spelling and grammar mistakes" Text="First of all, you can get caustics just by Path Tracing. Caustics isn't a difficult phenomenon in CG. Almost any global illumination algorithm can render it. It's just the matter of the converging speed.&#xD;&#xA;&#xD;&#xA;While (naive) Path Tracing can render caustics, it takes a long time to clean the rendered image due to how the algorithm works. Photon Mapping makes the converging speed faster by doing some tricks on how light paths are interpolated. Bi-Directional Path Tracing on the other hand tries to make some difficult-to-sample light paths easier.&#xD;&#xA;&#xD;&#xA;Besides the two algorithms, Metropolis Light Transport can render caustics efficently by finding the most significant light path in the scene and explore other possibilities arround it.&#xD;&#xA;&#xD;&#xA;Here is a good lecture on ray based rendering algorithms.&lt;br&gt;&#xD;&#xA;https://www.youtube.com/watch?v=pjc1QAI6zS0&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&#xD;&#xA;&#xD;&#xA;Path Tracing&lt;br&gt;&#xD;&#xA;https://www.youtube.com/watch?v=cDi-uti2oLQ&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=29&#xD;&#xA;&#xD;&#xA;Photon Mapping&lt;br&gt;&#xD;&#xA;https://www.youtube.com/watch?v=-1C2kL5pTbs&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=34&#xD;&#xA;&#xD;&#xA;There is the original paper of BDPT. It's not too difficult if you can implement ecplcite light sampling and multiple importance sampling by your self.&#xD;&#xA;https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, I reocomend the book Physically Based Rendering: From Theory to Implementation. It talks about all the algorithms above and more. It is basiclly a must have if you want to dive deep into CG." ContentLicense="CC BY-SA 3.0" />
  <row Id="13239" PostHistoryTypeId="24" PostId="5015" RevisionGUID="b8c706d1-337c-4d2b-92c4-46c6fa38c3f2" CreationDate="2017-04-20T16:12:17.620" Comment="Proposed by 5256 approved by 231 edit id of 219" ContentLicense="CC BY-SA 3.0" />
  <row Id="13240" PostHistoryTypeId="5" PostId="5015" RevisionGUID="20254772-fda5-4b05-bfc7-881d5d29bf06" CreationDate="2017-04-20T16:16:46.213" UserId="231" Comment="Typos" Text="First of all, you can get caustics just by Path Tracing. Caustics isn't a difficult phenomenon in computer graphics. Almost any global illumination algorithm can render it. It's just a matter of the converging speed.&#xD;&#xA;&#xD;&#xA;While (naive) Path Tracing can render caustics, it takes a long time to clean the rendered image due to how the algorithm works. Photon Mapping makes the converging speed faster by doing some tricks on how light paths are interpolated. Bi-Directional Path Tracing on the other hand tries to make some difficult-to-sample light paths easier.&#xD;&#xA;&#xD;&#xA;Besides the two algorithms, Metropolis Light Transport can render caustics efficiently by finding the most significant light path in the scene and exploring other possibilities around it.&#xD;&#xA;&#xD;&#xA;Here is a good lecture on ray based rendering algorithms.  &#xD;&#xA;https://www.youtube.com/watch?v=pjc1QAI6zS0&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&#xD;&#xA;&#xD;&#xA;Path Tracing  &#xD;&#xA;https://www.youtube.com/watch?v=cDi-uti2oLQ&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=29&#xD;&#xA;&#xD;&#xA;Photon Mapping  &#xD;&#xA;https://www.youtube.com/watch?v=-1C2kL5pTbs&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=34&#xD;&#xA;&#xD;&#xA;There is the original paper of BDPT. It's not too difficult if you can implement explicit light sampling and multiple importance sampling by your self.&#xD;&#xA;https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, I recommend the book Physically Based Rendering: From Theory to Implementation. It talks about all the algorithms above and more. It is basically a must have if you want to dive deep into computer graphics." ContentLicense="CC BY-SA 3.0" />
  <row Id="13243" PostHistoryTypeId="5" PostId="5015" RevisionGUID="5a7ae9cf-c15b-4008-a6b5-ea43e94938eb" CreationDate="2017-04-20T16:46:43.533" UserId="231" Comment="Hide URLs behind link text" Text="First of all, you can get caustics just by Path Tracing. Caustics isn't a difficult phenomenon in computer graphics. Almost any global illumination algorithm can render it. It's just a matter of the converging speed.&#xD;&#xA;&#xD;&#xA;While (naive) Path Tracing can render caustics, it takes a long time to clean the rendered image due to how the algorithm works. Photon Mapping makes the converging speed faster by doing some tricks on how light paths are interpolated. Bi-Directional Path Tracing on the other hand tries to make some difficult-to-sample light paths easier.&#xD;&#xA;&#xD;&#xA;Besides the two algorithms, Metropolis Light Transport can render caustics efficiently by finding the most significant light path in the scene and exploring other possibilities around it.&#xD;&#xA;&#xD;&#xA;Here are some good lectures on:&#xD;&#xA;&#xD;&#xA;- [Ray based rendering algorithms]&#xD;&#xA;- [Path Tracing]&#xD;&#xA;- [Photon Mapping]&#xD;&#xA;&#xD;&#xA;There is the [original paper of BDPT]. It's not too difficult if you can implement explicit light sampling and multiple importance sampling by your self.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, I recommend the book Physically Based Rendering: From Theory to Implementation. It talks about all the algorithms above and more. It is basically a must have if you want to dive deep into computer graphics.&#xD;&#xA;&#xD;&#xA;  [Ray based rendering algorithms]: https://www.youtube.com/watch?v=pjc1QAI6zS0&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&#xD;&#xA;&#xD;&#xA;  [Path Tracing]: https://www.youtube.com/watch?v=cDi-uti2oLQ&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=29&#xD;&#xA;&#xD;&#xA;  [Photon Mapping]: https://www.youtube.com/watch?v=-1C2kL5pTbs&amp;list=PLujxSBD-JXgnGmsn7gEyN28P1DnRZG7qi&amp;index=34&#xD;&#xA;&#xD;&#xA;  [original paper of BDPT]: https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13244" PostHistoryTypeId="5" PostId="5016" RevisionGUID="a435428a-447c-4f36-b2a3-53ac7d55c2b9" CreationDate="2017-04-20T17:54:07.303" UserId="6401" Comment="deleted 18 characters in body" Text="I have to add a spotlight to my rotating cube so this is my code:&#xD;&#xA;&#xD;&#xA;HTML&#xD;&#xA;&#xD;&#xA;            &lt;!DOCTYPE html&gt;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;button id = &quot;ButtonX&quot;&gt;Rotate X&lt;/button&gt;&#xD;&#xA;    &lt;button id = &quot;ButtonY&quot;&gt;Rotate Y&lt;/button&gt;&#xD;&#xA;    &lt;button id = &quot;ButtonZ&quot;&gt;Rotate Z&lt;/button&gt;&#xD;&#xA;    &lt;button id = &quot;ButtonT&quot;&gt;Toggle Rotation&lt;/button&gt;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &lt;script id=&quot;vertex-shader&quot; type=&quot;x-shader/x-vertex&quot;&gt;&#xD;&#xA;    &#xD;&#xA;    attribute  vec4 vPosition;&#xD;&#xA;    attribute  vec4 vColor;&#xD;&#xA;    attribute  vec2 vTexCoord;&#xD;&#xA;    attribute  vec3 vNormal;&#xD;&#xA;    &#xD;&#xA;    uniform float shininess;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 posLightPosition;&#xD;&#xA;    uniform vec4 posAmbientProduct, posDiffuseProduct,      posSpecularProduct;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 dirLightPosition;&#xD;&#xA;    uniform vec4 dirAmbientProduct, dirDiffuseProduct,      dirSpecularProduct;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 spotLightPosition;&#xD;&#xA;    uniform vec4 spotAmbientProduct, spotDiffuseProduct,spotSpecularProduct;&#xD;&#xA;    uniform vec4 spotLightDirection;&#xD;&#xA;    uniform float lCutOff;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    varying vec4 fColor;&#xD;&#xA;    varying vec2 fTexCoord;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 theta;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // Compute the sines and cosines of theta for each of&#xD;&#xA;        //   the three axes in one computation.&#xD;&#xA;        vec3 angles = radians( theta );&#xD;&#xA;        vec3 c = cos( angles );&#xD;&#xA;        vec3 s = sin( angles );&#xD;&#xA;    &#xD;&#xA;        // Remeber: thse matrices are column-major&#xD;&#xA;        mat4 rx = mat4( 1.0,  0.0,  0.0, 0.0,&#xD;&#xA;    		    0.0,  c.x,  s.x, 0.0,&#xD;&#xA;    		    0.0, -s.x,  c.x, 0.0,&#xD;&#xA;    		    0.0,  0.0,  0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;        mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,&#xD;&#xA;    		    0.0, 1.0,  0.0, 0.0,&#xD;&#xA;    		    s.y, 0.0,  c.y, 0.0,&#xD;&#xA;    		    0.0, 0.0,  0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        mat4 rz = mat4( c.z, s.z, 0.0, 0.0,&#xD;&#xA;    		    -s.z,  c.z, 0.0, 0.0,&#xD;&#xA;    		    0.0,  0.0, 1.0, 0.0,&#xD;&#xA;    		    0.0,  0.0, 0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;        vec3 N=normalize((rz*ry*rx*vNormal).xyz);&#xD;&#xA;    &#xD;&#xA;        // positional light&#xD;&#xA;        vec3 pos=-(rz*ry*rx*vPosition).xyz;&#xD;&#xA;        vec3 posLight=posLightPosition.xyz;&#xD;&#xA;        vec3 posL=normalize(posLight-pos);&#xD;&#xA;        vec3 posE=normalize(-pos);&#xD;&#xA;        vec3 posH=normalize(posL+posE);&#xD;&#xA;        vec4 posAmbient=posAmbientProduct;&#xD;&#xA;        float posKd=max(dot(posL,N),0.0);&#xD;&#xA;        vec4 posDiffuse=posKd*posDiffuseProduct;&#xD;&#xA;        float posKs=pow(max(dot(N,posH),0.0), shininess);&#xD;&#xA;        vec4 posSpecular=posKs*posSpecularProduct;&#xD;&#xA;        if(dot(posL,N)&lt;0.0){&#xD;&#xA;        posSpecular=vec4(0.0,0.0,0.0,1.0);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // directional light&#xD;&#xA;        vec3 dirLight=dirLightPosition.xyz;&#xD;&#xA;        vec3 dirL=normalize(dirLight);&#xD;&#xA;        vec3 dirE=normalize(-pos);&#xD;&#xA;        vec3 dirH=normalize(dirL+dirE);&#xD;&#xA;        vec4 dirAmbient=dirAmbientProduct;&#xD;&#xA;        float dirKd=max(dot(dirL,N),0.0);&#xD;&#xA;        vec4 dirDiffuse=dirKd*dirDiffuseProduct;&#xD;&#xA;        float dirKs=pow(max(dot(N,dirH),0.0), shininess);&#xD;&#xA;        vec4 dirSpecular=dirKs*dirSpecularProduct;&#xD;&#xA;        if(dot(dirL,N)&lt;0.0){&#xD;&#xA;        dirSpecular=vec4(0.0,0.0,0.0,1.0);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        &#xD;&#xA;        //spotlight&#xD;&#xA;        vec3 spotLight=spotLightPosition.xyz;&#xD;&#xA;        vec3 spotL=normalize(spotLight);&#xD;&#xA;        vec3 spotE=normalize(-pos);&#xD;&#xA;        vec3 spotH=normalize(spotL+spotE);&#xD;&#xA;        vec3 spotD=spotLightDirection.xyz;&#xD;&#xA;        vec4 spotAmbient=spotAmbientProduct;&#xD;&#xA;        float spotKd=max(dot(spotL,N),0.0);&#xD;&#xA;        vec4 spotDiffuse=spotKd*spotDiffuseProduct;&#xD;&#xA;        float spotKs=pow(max(dot(N,spotH),0.0), shininess);&#xD;&#xA;        vec4 spotSpecular=spotKs*spotSpecularProduct;&#xD;&#xA;        if(dot(spotL,N)&lt;0.0){&#xD;&#xA;        spotSpecular=vec4(0.0,0.0,0.0,1.0);&#xD;&#xA;        }&#xD;&#xA;        float lEffect= dot(normalize(spotD), -spotH);&#xD;&#xA;        if(lEffect&gt;lCutOff)&#xD;&#xA;        {&#xD;&#xA;        vec4 ambient=posAmbient+dirAmbient+spotAmbient;&#xD;&#xA;        vec4 diffuse=posDiffuse+dirDiffuse+spotDiffuse;&#xD;&#xA;        vec4 specular=posSpecular+dirSpecular+spotSpecular;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        fColor = ambient+vColor*(diffuse+specular);&#xD;&#xA;        fColor.a = 1.0;&#xD;&#xA;        }&#xD;&#xA;        else{&#xD;&#xA;        vec4 ambient=posAmbient+dirAmbient;&#xD;&#xA;        vec4 diffuse=posDiffuse+dirDiffuse;&#xD;&#xA;        vec4 specular=posSpecular+dirSpecular;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        fColor = ambient+vColor*(diffuse+specular);&#xD;&#xA;        fColor.a = 1.0;&#xD;&#xA;    &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            fTexCoord = vTexCoord;&#xD;&#xA;        gl_Position = rz * ry * rx * vPosition;&#xD;&#xA;        gl_Position.z = -gl_Position.z;&#xD;&#xA;    }&#xD;&#xA;    &lt;/script&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;script id=&quot;fragment-shader&quot; type=&quot;x-shader/x-fragment&quot;&gt;&#xD;&#xA;    &#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    varying vec4 fColor;&#xD;&#xA;    varying  vec2 fTexCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D Tex0;&#xD;&#xA;    uniform sampler2D Tex1;&#xD;&#xA;    &#xD;&#xA;    void&#xD;&#xA;    main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = fColor*(texture2D(Tex0, fTexCoord)*texture2D(Tex1, fTexCoord));&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &lt;/script&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;../Common/webgl-utils.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;../Common/initShaders.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;../Common/MV.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;Homework1.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;    &#xD;&#xA;    &lt;body&gt;&#xD;&#xA;    &lt;canvas id=&quot;gl-canvas&quot; width=&quot;1024&quot; height=&quot;1024&quot;&gt;&#xD;&#xA;    Oops ... your browser doesn't support the HTML5 canvas element&#xD;&#xA;    &lt;/canvas&gt;&#xD;&#xA;    &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;  JAVASCRIPT&#xD;&#xA;&#xD;&#xA;    &quot;use strict&quot;;&#xD;&#xA;    &#xD;&#xA;    var canvas;&#xD;&#xA;    var gl;&#xD;&#xA;    &#xD;&#xA;    var numVertices  = 36;&#xD;&#xA;    &#xD;&#xA;    var texSize = 256;&#xD;&#xA;    var numChecks = 8;&#xD;&#xA;    &#xD;&#xA;    var program;&#xD;&#xA;    &#xD;&#xA;    var texture1, texture2;&#xD;&#xA;    var t1, t2;&#xD;&#xA;    var normalsArray = [];&#xD;&#xA;    &#xD;&#xA;    var dirLightPosition = vec4(1.0, 1.0, 1.0, 0.0 );&#xD;&#xA;    var dirLightAmbient = vec4(0.2, 0.2, 0.2, 1.0 );&#xD;&#xA;    var dirLightDiffuse = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var dirLightSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    var posLightPosition = vec4(1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var posLightAmbient = vec4(0.2, 0.2, 0.2, 1.0 );&#xD;&#xA;    var posLightDiffuse = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var posLightSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    var materialAmbient = vec4( 1.0, 0.0, 1.0, 1.0 );&#xD;&#xA;    var materialDiffuse = vec4( 1.0, 0.8, 0.0, 1.0 );&#xD;&#xA;    var materialSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var materialShininess = 20.0;&#xD;&#xA;    &#xD;&#xA;    var spotLightPosition = vec4(1.0, 2.0, 3.0, 1.0 );&#xD;&#xA;    var spotLightAmbient = vec4(0.2, 0.2, 0.2, 1.0 );&#xD;&#xA;    var spotLightDiffuse = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var spotLightSpecular = vec4( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    var spotLightDirection = vec4(-0.5,1.0,2.0,1.0);&#xD;&#xA;    var lCutOff=0.867;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    var c;&#xD;&#xA;    &#xD;&#xA;    var flag = true;&#xD;&#xA;    &#xD;&#xA;    var image1 = new Uint8Array(4*texSize*texSize);&#xD;&#xA;    &#xD;&#xA;        for ( var i = 0; i &lt; texSize; i++ ) {&#xD;&#xA;            for ( var j = 0; j &lt;texSize; j++ ) {&#xD;&#xA;                var patchx = Math.floor(i/(texSize/numChecks));&#xD;&#xA;                var patchy = Math.floor(j/(texSize/numChecks));&#xD;&#xA;                if(patchx%2 ^ patchy%2) c = 255;&#xD;&#xA;                else c = 0;&#xD;&#xA;                //c = 255*(((i &amp; 0x8) == 0) ^ ((j &amp; 0x8)  == 0))&#xD;&#xA;                image1[4*i*texSize+4*j] = c;&#xD;&#xA;                image1[4*i*texSize+4*j+1] = c;&#xD;&#xA;                image1[4*i*texSize+4*j+2] = c;&#xD;&#xA;                image1[4*i*texSize+4*j+3] = 255;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    var image2 = new Uint8Array(4*texSize*texSize);&#xD;&#xA;    &#xD;&#xA;        // Create a checkerboard pattern&#xD;&#xA;        for ( var i = 0; i &lt; texSize; i++ ) {&#xD;&#xA;            for ( var j = 0; j &lt;texSize; j++ ) {&#xD;&#xA;                image2[4*i*texSize+4*j] = 127+127*Math.sin(0.1*i*j);&#xD;&#xA;                image2[4*i*texSize+4*j+1] = 127+127*Math.sin(0.1*i*j);&#xD;&#xA;                image2[4*i*texSize+4*j+2] = 127+127*Math.sin(0.1*i*j);&#xD;&#xA;                image2[4*i*texSize+4*j+3] = 255;&#xD;&#xA;               }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    var pointsArray = [];&#xD;&#xA;    var colorsArray = [];&#xD;&#xA;    var texCoordsArray = [];&#xD;&#xA;    &#xD;&#xA;    var texCoord = [&#xD;&#xA;        vec2(0, 0),&#xD;&#xA;        vec2(0, 1),&#xD;&#xA;        vec2(1, 1),&#xD;&#xA;        vec2(1, 0)&#xD;&#xA;    ];&#xD;&#xA;    &#xD;&#xA;    var vertices = [&#xD;&#xA;        vec4( -0.5, -0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( -0.5,  0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5,  0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5, -0.5,  0.5, 1.0 ),&#xD;&#xA;        vec4( -0.5, -0.5, -0.5, 1.0 ),&#xD;&#xA;        vec4( -0.5,  0.5, -0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5,  0.5, -0.5, 1.0 ),&#xD;&#xA;        vec4( 0.5, -0.5, -0.5, 1.0 )&#xD;&#xA;    ];&#xD;&#xA;    &#xD;&#xA;    var vertexColors = [&#xD;&#xA;        vec4( 0.0, 0.0, 0.0, 1.0 ),  // black&#xD;&#xA;        vec4( 1.0, 0.0, 0.0, 1.0 ),  // red&#xD;&#xA;        vec4( 1.0, 1.0, 0.0, 1.0 ),  // yellow&#xD;&#xA;        vec4( 0.0, 1.0, 0.0, 1.0 ),  // green&#xD;&#xA;        vec4( 0.0, 0.0, 1.0, 1.0 ),  // blue&#xD;&#xA;        vec4( 1.0, 0.0, 1.0, 1.0 ),  // magenta&#xD;&#xA;        vec4( 0.0, 1.0, 1.0, 1.0 ),  // white&#xD;&#xA;        vec4( 0.0, 1.0, 1.0, 1.0 )   // cyan&#xD;&#xA;    ];&#xD;&#xA;    &#xD;&#xA;    var xAxis = 0;&#xD;&#xA;    var yAxis = 1;&#xD;&#xA;    var zAxis = 2;&#xD;&#xA;    var axis = xAxis;&#xD;&#xA;    &#xD;&#xA;    var theta = [45.0, 45.0, 45.0];&#xD;&#xA;    &#xD;&#xA;    var thetaLoc;&#xD;&#xA;    &#xD;&#xA;    function configureTexture() {&#xD;&#xA;        texture1 = gl.createTexture();&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture1 );&#xD;&#xA;        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);&#xD;&#xA;        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, image1);&#xD;&#xA;        gl.generateMipmap( gl.TEXTURE_2D );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,&#xD;&#xA;                          gl.NEAREST_MIPMAP_LINEAR );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;    &#xD;&#xA;        texture2 = gl.createTexture();&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture2 );&#xD;&#xA;        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);&#xD;&#xA;        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize, texSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, image2);&#xD;&#xA;        gl.generateMipmap( gl.TEXTURE_2D );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,&#xD;&#xA;                          gl.NEAREST_MIPMAP_LINEAR );&#xD;&#xA;        gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    function quad(a, b, c, d) {&#xD;&#xA;    &#xD;&#xA;         var t1 = subtract(vertices[b], vertices[a]);&#xD;&#xA;         var t2 = subtract(vertices[c], vertices[b]);&#xD;&#xA;         var normal = cross(t1, t2);&#xD;&#xA;         var normal = vec3(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[a]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[0]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[b]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[1]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[c]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[2]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[a]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[0]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[c]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[2]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    &#xD;&#xA;         pointsArray.push(vertices[d]);&#xD;&#xA;         colorsArray.push(vertexColors[a]);&#xD;&#xA;         texCoordsArray.push(texCoord[3]);&#xD;&#xA;         normalsArray.push(normal);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    function colorCube()&#xD;&#xA;    {&#xD;&#xA;        quad( 1, 0, 3, 2 );&#xD;&#xA;        quad( 2, 3, 7, 6 );&#xD;&#xA;        quad( 3, 0, 4, 7 );&#xD;&#xA;        quad( 6, 5, 1, 2 );&#xD;&#xA;        quad( 4, 5, 6, 7 );&#xD;&#xA;        quad( 5, 4, 0, 1 );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    window.onload = function init() {&#xD;&#xA;    &#xD;&#xA;        canvas = document.getElementById( &quot;gl-canvas&quot; );&#xD;&#xA;    &#xD;&#xA;        gl = WebGLUtils.setupWebGL( canvas );&#xD;&#xA;        if ( !gl ) { alert( &quot;WebGL isn't available&quot; ); }&#xD;&#xA;    &#xD;&#xA;        gl.viewport( 0, 0, canvas.width, canvas.height );&#xD;&#xA;        gl.clearColor( 1.0, 1.0, 1.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;        gl.enable(gl.DEPTH_TEST);&#xD;&#xA;    &#xD;&#xA;        //&#xD;&#xA;        //  Load shaders and initialize attribute buffers&#xD;&#xA;        //&#xD;&#xA;        program = initShaders( gl, &quot;vertex-shader&quot;, &quot;fragment-shader&quot; );&#xD;&#xA;        gl.useProgram( program );&#xD;&#xA;    &#xD;&#xA;        colorCube();&#xD;&#xA;    &#xD;&#xA;        var nBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, nBuffer );&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vNormal = gl.getAttribLocation( program, &quot;vNormal&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vNormal, 3, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vNormal );&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        var cBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(colorsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vColor = gl.getAttribLocation( program, &quot;vColor&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vColor );&#xD;&#xA;    &#xD;&#xA;        var vBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer);&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(pointsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vPosition = gl.getAttribLocation( program, &quot;vPosition&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vPosition );&#xD;&#xA;    &#xD;&#xA;        var tBuffer = gl.createBuffer();&#xD;&#xA;        gl.bindBuffer( gl.ARRAY_BUFFER, tBuffer);&#xD;&#xA;        gl.bufferData( gl.ARRAY_BUFFER, flatten(texCoordsArray), gl.STATIC_DRAW );&#xD;&#xA;    &#xD;&#xA;        var vTexCoord = gl.getAttribLocation( program, &quot;vTexCoord&quot; );&#xD;&#xA;        gl.vertexAttribPointer( vTexCoord, 2, gl.FLOAT, false, 0, 0 );&#xD;&#xA;        gl.enableVertexAttribArray( vTexCoord );&#xD;&#xA;    &#xD;&#xA;        var dirAmbientProduct = mult(dirLightAmbient, materialAmbient);&#xD;&#xA;        var dirDiffuseProduct = mult(dirLightDiffuse, materialDiffuse);&#xD;&#xA;        var dirSpecularProduct = mult(dirLightSpecular, materialSpecular);&#xD;&#xA;    &#xD;&#xA;        var posAmbientProduct = mult(posLightAmbient, materialAmbient);&#xD;&#xA;        var posDiffuseProduct = mult(posLightDiffuse, materialDiffuse);&#xD;&#xA;        var posSpecularProduct = mult(posLightSpecular, materialSpecular);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        var spotAmbientProduct = mult(spotLightAmbient, materialAmbient);&#xD;&#xA;        var spotDiffuseProduct = mult(spotLightDiffuse, materialDiffuse);&#xD;&#xA;        var spotSpecularProduct = mult(spotLightSpecular, materialSpecular);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        configureTexture();&#xD;&#xA;    &#xD;&#xA;        gl.activeTexture( gl.TEXTURE0 );&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture1 );&#xD;&#xA;        gl.uniform1i(gl.getUniformLocation( program, &quot;Tex0&quot;), 0);&#xD;&#xA;    &#xD;&#xA;        gl.activeTexture( gl.TEXTURE1 );&#xD;&#xA;        gl.bindTexture( gl.TEXTURE_2D, texture2 );&#xD;&#xA;        gl.uniform1i(gl.getUniformLocation( program, &quot;Tex1&quot;), 1);&#xD;&#xA;    &#xD;&#xA;        thetaLoc = gl.getUniformLocation(program, &quot;theta&quot;);&#xD;&#xA;    &#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirAmbientProduct&quot;),flatten(dirAmbientProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posAmbientProduct&quot;),flatten(posAmbientProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotAmbientProduct&quot;),flatten(spotAmbientProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirDiffuseProduct&quot;),flatten(dirDiffuseProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posDiffuseProduct&quot;),flatten(posDiffuseProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotDiffuseProduct&quot;),flatten(spotDiffuseProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirSpecularProduct&quot;),flatten(dirSpecularProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posSpecularProduct&quot;),flatten(posSpecularProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotSpecularProduct&quot;),flatten(spotSpecularProduct) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;posLightPosition&quot;),flatten(posLightPosition) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;dirLightPosition&quot;),flatten(dirLightPosition) );&#xD;&#xA;        gl.uniform4fv( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotLightPosition&quot;),flatten(spotLightPosition) );&#xD;&#xA;        gl.uniform1f( gl.getUniformLocation(program,&#xD;&#xA;           &quot;shininess&quot;),materialShininess );&#xD;&#xA;        gl.uniform1f( gl.getUniformLocation(program,&#xD;&#xA;           &quot;lCutOff&quot;),lCutOff );&#xD;&#xA;        gl.uniform1f( gl.getUniformLocation(program,&#xD;&#xA;           &quot;spotLightDirection&quot;),spotLightDirection );&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;     document.getElementById(&quot;ButtonX&quot;).onclick = function(){axis = xAxis;};&#xD;&#xA;     document.getElementById(&quot;ButtonY&quot;).onclick = function(){axis = yAxis;};&#xD;&#xA;     document.getElementById(&quot;ButtonZ&quot;).onclick = function(){axis = zAxis;};&#xD;&#xA;     document.getElementById(&quot;ButtonT&quot;).onclick = function(){flag = !flag;};&#xD;&#xA;    &#xD;&#xA;        render();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    var render = function() {&#xD;&#xA;        gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);&#xD;&#xA;        if(flag) theta[axis] += 2.0;&#xD;&#xA;        gl.uniform3fv(thetaLoc, theta);&#xD;&#xA;        gl.drawArrays( gl.TRIANGLES, 0, numVertices );&#xD;&#xA;        requestAnimFrame(render);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I computed tha angle between the spotlight direction and the vector to light source from vertex and if this angle is greater than the cutoff angle defined by the spotlight I compute the three products for the Phong lighting model.&#xD;&#xA;&#xD;&#xA;Where am I wrong?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13245" PostHistoryTypeId="2" PostId="5017" RevisionGUID="c9994f8b-307c-43b8-81b0-6e64ba941647" CreationDate="2017-04-21T01:41:52.290" UserId="113" Text="Some games claim to use subsurface scattering but my current understanding of sss is only achieved with ray tracing. How would you sub surface scatter without ray tracing? Do some claim to use sss but really use some approximation trick that doesn't use rays. I can't even imagine doing the below real time.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U6i0v.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13246" PostHistoryTypeId="1" PostId="5017" RevisionGUID="c9994f8b-307c-43b8-81b0-6e64ba941647" CreationDate="2017-04-21T01:41:52.290" UserId="113" Text="Subsurface Scattering Without Rays?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13247" PostHistoryTypeId="3" PostId="5017" RevisionGUID="c9994f8b-307c-43b8-81b0-6e64ba941647" CreationDate="2017-04-21T01:41:52.290" UserId="113" Text="|raytracing|rasterizer|subsurface-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13248" PostHistoryTypeId="2" PostId="5018" RevisionGUID="07b745fe-cf1e-4363-90bc-d453841cd8e9" CreationDate="2017-04-21T14:23:35.873" UserId="2372" Text="I am trying to achieve a special texture tiling effect in my shader.&#xD;&#xA;Here is how I define my uv before sampling my texture, nothing really special.&#xD;&#xA;&#xD;&#xA;    // uv_ST contains the tiling and offset values&#xD;&#xA;    uv.xy = uv.xy * uv_ST.xy + uv_ST.zw&#xD;&#xA;&#xD;&#xA;This gives the standard tiling and offset behaviour when you tile a clamped texture as you can see in the image below. First is normal, second is offset and last is tiling.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But I want to avoid the deformation behaviour when tiling, I want to keep margins when tiling my texture. Here is an illustration below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;How could I do that inside my shader when defining my uvs before sampling the texture ?&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zwj4l.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/XyMKq.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13249" PostHistoryTypeId="1" PostId="5018" RevisionGUID="07b745fe-cf1e-4363-90bc-d453841cd8e9" CreationDate="2017-04-21T14:23:35.873" UserId="2372" Text="Special Texture Tiling without deformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="13250" PostHistoryTypeId="3" PostId="5018" RevisionGUID="07b745fe-cf1e-4363-90bc-d453841cd8e9" CreationDate="2017-04-21T14:23:35.873" UserId="2372" Text="|shader|texture|glsl|hlsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13251" PostHistoryTypeId="5" PostId="5018" RevisionGUID="5465f871-8761-4fad-8814-c0e149ce5afd" CreationDate="2017-04-21T15:18:14.687" UserId="2372" Comment="added 53 characters in body" Text="I am trying to achieve a special texture tiling effect in my shader.&#xD;&#xA;Here is how I define my uv before sampling my texture, nothing really special.&#xD;&#xA;&#xD;&#xA;    // uv_ST contains the tiling and offset values&#xD;&#xA;    uv.xy = uv.xy * uv_ST.xy + uv_ST.zw&#xD;&#xA;&#xD;&#xA;This gives the standard tiling and offset behaviour when you tile a clamped texture as you can see in the image below. First is normal, second is offset and last is tiling.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But I want to avoid the deformation behaviour when tiling, I want to keep margins when tiling my texture or simply cut it in the middle and stretching it. Here is an illustration below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;How could I do that inside my shader when defining my uvs before sampling the texture ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zwj4l.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/HdUgs.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13252" PostHistoryTypeId="5" PostId="5018" RevisionGUID="3d2c4f0d-31e2-4a05-acc5-a802649dfbd0" CreationDate="2017-04-21T15:40:27.670" UserId="2372" Comment="added 36 characters in body; edited title" Text="I am trying to achieve a special texture stretching effect in my shader.&#xD;&#xA;Here is how I define my uv before sampling my texture, nothing really special.&#xD;&#xA;&#xD;&#xA;    // uv_ST contains the tiling and offset values&#xD;&#xA;    uv.xy = uv.xy * uv_ST.xy + uv_ST.zw&#xD;&#xA;&#xD;&#xA;This gives the standard tiling/stretching and offset behaviour when you tile/stretche a clamped texture as you can see in the image below. First is normal, second is offset and last is stretching.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But I want to avoid the deformation behaviour when stretching, I want to keep margins when stretching my texture or simply cut it in the middle and stretching it. Here is an illustration below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;How could I do that inside my shader when defining my uvs before sampling the texture ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zwj4l.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/HdUgs.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13253" PostHistoryTypeId="4" PostId="5018" RevisionGUID="3d2c4f0d-31e2-4a05-acc5-a802649dfbd0" CreationDate="2017-04-21T15:40:27.670" UserId="2372" Comment="added 36 characters in body; edited title" Text="Special Texture Stretching without deformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="13254" PostHistoryTypeId="2" PostId="5019" RevisionGUID="f4e8c70d-ed34-4601-82a7-6b554b3d2a6e" CreationDate="2017-04-21T17:53:45.463" UserId="506" Text="There are lots of ways to fake SSS with greater or lesser fidelity. A few recent-ish methods:&#xD;&#xA;&#xD;&#xA;- Screen-space blurring of object lighting (described in detail [here](http://www.iryoku.com/sssss/))&#xD;&#xA;&#xD;&#xA;![screen-space light blurring](https://i.stack.imgur.com/WyOYZ.png)&#xD;&#xA;&#xD;&#xA;- Using “interior” ambient-occlusion maps generated from a normal-flipped version of the geometry to approximate local thickness, providing an easy way to fake light transmission (more information [here](https://colinbarrebrisebois.com/2011/03/07/gdc-2011-approximating-translucency-for-a-fast-cheap-and-convincing-subsurface-scattering-look/), with an addendum [here](https://colinbarrebrisebois.com/2011/04/04/approximating-translucency-part-ii-addendum-to-gdc-2011-talk-gpu-pro-2-article/))&#xD;&#xA;&#xD;&#xA;![local thickness map](https://i.stack.imgur.com/NFG3W.png)&#xD;&#xA;&#xD;&#xA;There’s also the assortment of techniques in the GPU Gems article PaulHK linked to. One thing I’d add is about the light-falloff-texture approach mentioned at the beginning of it, which Valve used for a couple of interesting effects in Source games in addition to fake SSS—see their [`$lightwarptexture`](https://developer.valvesoftware.com/wiki/$lightwarptexture) documentation for some information about that.&#xD;&#xA;&#xD;&#xA;![Team Fortress 2 illustrative rendering](https://i.stack.imgur.com/0AXjk.png)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13258" PostHistoryTypeId="50" PostId="4879" RevisionGUID="7e4326ed-c5e9-4d1a-8656-88984bfe1956" CreationDate="2017-04-22T17:48:24.467" UserId="-1" />
  <row Id="13267" PostHistoryTypeId="2" PostId="5021" RevisionGUID="a7de0e3d-a8c3-47cd-8e9a-73e2ec48f70c" CreationDate="2017-04-23T16:08:02.317" UserId="6401" Text="I have to build a texture of a cube that models the emission of light by the object. Any tips? I really don't know where to start." ContentLicense="CC BY-SA 3.0" />
  <row Id="13268" PostHistoryTypeId="1" PostId="5021" RevisionGUID="a7de0e3d-a8c3-47cd-8e9a-73e2ec48f70c" CreationDate="2017-04-23T16:08:02.317" UserId="6401" Text="Emission of light from texture on WebGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="13269" PostHistoryTypeId="3" PostId="5021" RevisionGUID="a7de0e3d-a8c3-47cd-8e9a-73e2ec48f70c" CreationDate="2017-04-23T16:08:02.317" UserId="6401" Text="|texture|lighting|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13270" PostHistoryTypeId="6" PostId="5017" RevisionGUID="ebc04b51-822d-4989-9f72-8546837cbd8f" CreationDate="2017-04-24T09:02:38.007" UserId="2479" Comment="Added tag real-time" Text="|raytracing|real-time|rasterizer|subsurface-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13271" PostHistoryTypeId="24" PostId="5017" RevisionGUID="ebc04b51-822d-4989-9f72-8546837cbd8f" CreationDate="2017-04-24T09:02:38.007" Comment="Proposed by 2479 approved by 113 edit id of 224" ContentLicense="CC BY-SA 3.0" />
  <row Id="13272" PostHistoryTypeId="2" PostId="5022" RevisionGUID="2664e6ee-3475-4ae2-8ee3-1d817891f7d2" CreationDate="2017-04-24T09:49:29.407" UserId="113" Text="I'm playing around with volume rendering and looking into multi dimensional transfer functions. I keep seeing images like this for 2d transfer functions:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZUJqV.jpg&#xD;&#xA;&#xD;&#xA;I've read numerous papers and articles but haven't gotten very far because I can't seem to understand how the image on the right is generated from the volume data set. Also what would you call this image? From my understanding the two axis are data values (intensities) on the x and gradient magnitude on the y. But where is the gradient magnitude coming from? I have a basic understanding of gradient magnitude and don't see how it can be used to make that picture.&#xD;&#xA;How is it calculated? How can I generate a picture like the one on the right?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13273" PostHistoryTypeId="1" PostId="5022" RevisionGUID="2664e6ee-3475-4ae2-8ee3-1d817891f7d2" CreationDate="2017-04-24T09:49:29.407" UserId="113" Text="How to generate a 2d histogram?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13274" PostHistoryTypeId="3" PostId="5022" RevisionGUID="2664e6ee-3475-4ae2-8ee3-1d817891f7d2" CreationDate="2017-04-24T09:49:29.407" UserId="113" Text="|rendering|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13275" PostHistoryTypeId="5" PostId="4871" RevisionGUID="a505e917-0633-40a0-8cd0-020ece359235" CreationDate="2017-04-24T10:17:59.363" UserDisplayName="user246" Comment="spelling corrections" Text="I'd like to leave a longish comment with pictures on the drawing aspect. Raytracing is not limited to computer graphics you can and often do see see artists manually raytrace to figure out intersections of shapes on paper with a ruler or even freehand by elbow twisting*.&#xD;&#xA;&#xD;&#xA;It is also useful for many physical sciences like mechanical engineering and surveying. Or anywhere where you can use geometry to solve your problem.&#xD;&#xA;&#xD;&#xA;While @DanHulme correctly surmises that the mathematical definition of a ray is just a line with a starting point and no ending point (goes to infinity). This is not really what people do, instead it's defined that way to be rigorous. In general it's just a line that goes far enough for the job, and we aren't really interested in the other end but rather how the line interacts with something. Infinity is just a safe way of saying it will in fact interact if possible. Mathematicians are very particular about stuff like that.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: An example of manually tracing shadows of objects with ruler and pen for an as of yet unfinished answer on the subject [here](https://graphicdesign.stackexchange.com/a/86754/18306). Mainly here because I had spent yesterday evening doing the rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you see you would use rays whenever you try to find a geometric intersection between two geometric primitives. It's not only useful for shadows, it's for anything where you can intersect two things, with a starting point somewhere. So tracing can be used to find the shape of 2 intersecting surfaces, manually drawing perspective images, volumetric problems, rendering implicit surfaces like metaballs solving mathematical functions numerically etc etc. &#xD;&#xA;&#xD;&#xA;\* The definition of what now is called a ray was first described by Euclid's Elements about 300 bc. Which predates computers by a safe(ish) margin.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WwdR3.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13276" PostHistoryTypeId="24" PostId="4871" RevisionGUID="a505e917-0633-40a0-8cd0-020ece359235" CreationDate="2017-04-24T10:17:59.363" Comment="Proposed by 246 approved by 310, 209 edit id of 220" ContentLicense="CC BY-SA 3.0" />
  <row Id="13277" PostHistoryTypeId="5" PostId="4534" RevisionGUID="26a37e65-88c2-45c3-b598-cdb97c768747" CreationDate="2017-04-24T10:18:52.637" UserDisplayName="user246" Comment="proofreading; the last meta-remark is no longer relevant" Text="You have to step outside the world of mathematics for a while and look at what we are trying to achieve. Mathematics in its purest form only tells us what kinds of properties certain constructs have, it does not tell us why and how that would be useful.&#xD;&#xA;&#xD;&#xA;# The modeler's perspective on things&#xD;&#xA;&#xD;&#xA;So we have to look at the problem from modeling perspective. In this perspective it is mostly irrelevant how the mathematics work. As long as it provides the modeler with a system that yields with a understandable toolset to do his work everything is as it should be.&#xD;&#xA;&#xD;&#xA;It is frequently beneficial to describe things such as physical objects (creatures, mechanisms etc.), forces or any number of other things independent of each other. Either because it's easier to think in one orientation or just simply because you want to move/rotate/scale objects out of convenience.&#xD;&#xA;&#xD;&#xA;In practice you want at minimum that the camera is separated from the rest of the objects. While in more complex cases you want to have a more rich system. For example a bug is walking straight ahead on a straw. For practical reasons it would be neat if the bug only move forward in relation to the straw while the straw sways in the wind in relation to the world and the camera is independent of the straw. Similar modeling cases happen a lot, in human hands, robotics, car simulations, Finite object modeling etc.&#xD;&#xA;&#xD;&#xA;# Computational perspective&#xD;&#xA;&#xD;&#xA;The rendering and other functions need to be able to transform elements from these modeling hierarchies to each other. For example you need to know the point location in camera space to render. Preferably all this space transform happens automatically. For this purpose the modeler tells your application how the modeling elements are structured in relation to each other, a hierarchy, for modeler's benefit. &#xD;&#xA;&#xD;&#xA;Although this could be done in any number of ways it is commonly done with a tree structure, much like a filesystem with much the same effect. Each level stores in addition to tree information a affine matrix that describes the transform to its predecessor in the hierarchy. Mainly because this takes care of two core issues. The tree structure is easy to traverse and find the path to any other part. The matrices solve the problem of needing to do a lot of work transforming form a transform from one hierarchy space to another.&#xD;&#xA;&#xD;&#xA;So the user provides a tree where each object describes the transform required to transform the object to the coordinates of the object it is described in relation to, the parent. This parent in turn in turn describes the transform to its parent all the way to the world. Since all objects share one common ancestor, world, we can easily traverse the tree to find a transform path from any one coordinate system to another coordinate system.&#xD;&#xA;&#xD;&#xA;Since linear transforms are invertible, we do not need to store a description separately for moving in the opposite direction, away from world towards the children/leaves of the tree structure. All we need to do is to invert the matrix. This is almost always needed as it's practical to describe camera as a separate object under the world, there is no reason to describe the cameras transform from world to camera just treat it like any other object.&#xD;&#xA;&#xD;&#xA;To compute a point from one space to another you do as follows:&#xD;&#xA;&#xD;&#xA;1. Use the tree to find a relationship between spaces.&#xD;&#xA;2. For each step on the way pre multiply your matrix/ or its inverse if you're traversing away from world. \*\*&#xD;&#xA;&#xD;&#xA;Example:  You have the following hierarchy because it makes sense (this way you do not need to model each petal separately)&#xD;&#xA;&#xD;&#xA;    World&#xD;&#xA;      |&#xD;&#xA;      +---- Flower&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 1&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 2&#xD;&#xA;      |      |&#xD;&#xA;      |      +--- Petal 3&#xD;&#xA;      |&#xD;&#xA;      +---- Track&#xD;&#xA;             |&#xD;&#xA;             +--- Boom&#xD;&#xA;                   |&#xD;&#xA;                   +--- Camera&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To render Petal 1 you need to transform the vertices of petal one into the camera object space and from there to perspective space etc. Your calculation would be:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;    T_{\text{Perspective}} \cdot T_{\text{Camera}}^{-1} \cdot T_{\text{Boom}}^{-1} \cdot T_{\text{Track}}^{-1} \cdot T_{\text{Flower}} \cdot T_{\text{Petal 1}} \cdot \vec{v}_{\text{PetalPoint}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This way you can model a flower in a flowerpot totally independently from  from the robot shaking the camera about. At the same time freeing the modeler of the need to do complex trigonometric calculations, and in fact a big load of mathematics. Pretty neat.&#xD;&#xA;&#xD;&#xA;Now that you understand why, you should understand also that we do not have any limit to complexity of the hierarchy to &#xD;&#xA;facilitate a broad range of things you could do. &#xD;&#xA;&#xD;&#xA;This kind of hierarchy is called a scene graph and such things can be found in web pages, vector and CAD applications, many scientific modeling applications, most games.&#xD;&#xA;&#xD;&#xA;This should answer why as well as the less exciting how.&#xD;&#xA;&#xD;&#xA;# Do we absolutely need these?&#xD;&#xA;&#xD;&#xA;No, we do not. We can dispense all the matrices and describe all of our data directly in the camera's final coordinates. It's just that this is horribly complicated in 98% of the cases.&#xD;&#xA;&#xD;&#xA;In practice we need this hierarchy if we try to do even something more complex than a stationary box. Most of this deign is to make scene modelers' life easier. So that simple operations make more sense.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* why do we call it a parent child relationship? Because it's a tree, and earliest tree graphs are genealogical studies, aka family trees. Where the previous level is simply the parents and the next one is their children. &#xD;&#xA;&#xD;&#xA;\*\* or the other way around if you want to transpose your calculations." ContentLicense="CC BY-SA 3.0" />
  <row Id="13278" PostHistoryTypeId="24" PostId="4534" RevisionGUID="26a37e65-88c2-45c3-b598-cdb97c768747" CreationDate="2017-04-24T10:18:52.637" Comment="Proposed by 246 approved by 310, 209 edit id of 221" ContentLicense="CC BY-SA 3.0" />
  <row Id="13279" PostHistoryTypeId="5" PostId="3578" RevisionGUID="5a022058-9a3a-4f7d-a053-62846bbfc008" CreationDate="2017-04-24T10:19:22.833" UserDisplayName="user246" Comment="language corrections; dropped the unnecessary apology" Text="It depends on what you want to do. If you want to learn graphics programming only for yourself, it really doesn't matter what you choose.&#xD;&#xA;&#xD;&#xA;If you are thinking about professional work I recommend Vulkan. It is closer to hardware and I think knowledge about what hardware do is important for graphics programmers.&#xD;&#xA;&#xD;&#xA;Vulkan is closer to hardware because OpenGL does a lot of stuff under the hood which in Vulkan you do manually, like execute command queue.&#xD;&#xA;Also memory management is up to application not driver. You need to worry about allocate memory for `uniforms`(variable that you pass from CPU to GPU), about tracking them. You have more things to worry about but also it gives more freedom on usage of memory.&#xD;&#xA;It can sound scary and overwhelming but it really isn't. It's only next API that you need to learn.&#xD;&#xA;&#xD;&#xA;Understanding this things also will help in understanding how GPU work. What will allow you to do some optimization both on Vulkan and OpenGL. &#xD;&#xA;&#xD;&#xA;And one more thing that come to my mind, if you are starting to learn graphics programming probably when you look for a job as one Vulkan will be more popular (maybe more popular than OpenGL). Also, as far as I know most of companies that are using some graphics API write own functions around it so there is a chance that on the job you will not be writing in OpenGL nor in Vulkan but knowledge about GPU will be always useful." ContentLicense="CC BY-SA 3.0" />
  <row Id="13280" PostHistoryTypeId="24" PostId="3578" RevisionGUID="5a022058-9a3a-4f7d-a053-62846bbfc008" CreationDate="2017-04-24T10:19:22.833" Comment="Proposed by 246 approved by 310, 209 edit id of 222" ContentLicense="CC BY-SA 3.0" />
  <row Id="13281" PostHistoryTypeId="5" PostId="3611" RevisionGUID="4a4ada3a-5241-43b9-8841-943782d14ee8" CreationDate="2017-04-24T10:19:49.680" UserDisplayName="user246" Comment="trimmed down the post to the actual question" Text="I am decrementing/incrementing position x until it reaches y. However, this creates a rectangular-like path. I want position x to smoothly curve towards y (diagonally) on a 2D plane.&#xD;&#xA;&#xD;&#xA;What kind of maths would I need to achieve this? &#xD;&#xA;Example image attached.&#xD;&#xA;&#xD;&#xA;[![Algorithm][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MMbkN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13282" PostHistoryTypeId="24" PostId="3611" RevisionGUID="4a4ada3a-5241-43b9-8841-943782d14ee8" CreationDate="2017-04-24T10:19:49.680" Comment="Proposed by 246 approved by 310, 209 edit id of 223" ContentLicense="CC BY-SA 3.0" />
  <row Id="13283" PostHistoryTypeId="2" PostId="5023" RevisionGUID="098ba2e3-127f-4ad1-a614-1b30cfc8cc76" CreationDate="2017-04-24T11:30:14.640" UserId="2687" Text="I wanted to use [Monotone cubic interpolation](https://en.wikipedia.org/wiki/Monotone_cubic_interpolation), but the site only provide explanation for 2D case. How can I extend it to 3D?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13284" PostHistoryTypeId="1" PostId="5023" RevisionGUID="098ba2e3-127f-4ad1-a614-1b30cfc8cc76" CreationDate="2017-04-24T11:30:14.640" UserId="2687" Text="How to use Monotone cubic interpolation in 3D?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13285" PostHistoryTypeId="3" PostId="5023" RevisionGUID="098ba2e3-127f-4ad1-a614-1b30cfc8cc76" CreationDate="2017-04-24T11:30:14.640" UserId="2687" Text="|interpolation|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13286" PostHistoryTypeId="2" PostId="5024" RevisionGUID="2ea239fd-1a26-414a-a2fd-5632815ae181" CreationDate="2017-04-24T15:17:09.370" UserId="6501" Text="I am working on a project which plots points over a checkerboard (representing seats for people).  I would like each pixel in the image to represent each integer matrix entry.  After updating my Octave from $3.8$ to $4.2$, any image takes up $\frac 14$ of the actual plot window, as seen here:&#xD;&#xA;&#xD;&#xA;![Image][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MhMTv.png&#xD;&#xA;&#xD;&#xA;The simple code for this is as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clear&#xD;&#xA;    hold off&#xD;&#xA;&#xD;&#xA;    A = [1,2;3,4];&#xD;&#xA;&#xD;&#xA;    image(A)&#xD;&#xA;&#xD;&#xA;    axis xy %orients to bottom left&#xD;&#xA;&#xD;&#xA;Does anyone know how to get the image to take up the entire $2\times 2$ window, such that each pixel is the size of current image?&#xD;&#xA;&#xD;&#xA;Thank you in advance." ContentLicense="CC BY-SA 3.0" />
  <row Id="13287" PostHistoryTypeId="1" PostId="5024" RevisionGUID="2ea239fd-1a26-414a-a2fd-5632815ae181" CreationDate="2017-04-24T15:17:09.370" UserId="6501" Text="Octave matrix to image pixels too small (do not have 1 pixel per integer)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13288" PostHistoryTypeId="3" PostId="5024" RevisionGUID="2ea239fd-1a26-414a-a2fd-5632815ae181" CreationDate="2017-04-24T15:17:09.370" UserId="6501" Text="|image-processing|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13289" PostHistoryTypeId="50" PostId="4760" RevisionGUID="0ccb2113-bacb-40a5-bbd8-99d8b57a74a2" CreationDate="2017-04-25T05:09:51.583" UserId="-1" />
  <row Id="13290" PostHistoryTypeId="2" PostId="5025" RevisionGUID="7e84bc4d-1bbc-4e74-b931-48f7a4684ad1" CreationDate="2017-04-25T22:42:55.887" UserId="3123" Text="Ok, so I made little example of how to do this.&#xD;&#xA;&#xD;&#xA;**Short version**&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;You need to allocate additional buffer with heap type `D3D12_HEAP_TYPE_READBACK` and resource state set to `D3D12_RESOURCE_STATE_COPY_DEST`. Then create command list with type `D3D12_COMMAND_LIST_TYPE_COPY`. After dispatch compute shader use fence to check if buffer is ready, then copy from this buffer to buffer on `D3D12_HEAP_TYPE_READBACK` heap. Check again with fence if copying is finished and call `Map` on this buffer.&#xD;&#xA;&#xD;&#xA;I would suggest that you stop reading here and try implement it from description above and check longer version if its still doesn't work. Copy/Past isn't the best way to learn :)&#xD;&#xA;&#xD;&#xA;**Longer version**&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;First lets create new command list.&#xD;&#xA;&#xD;&#xA;    ID3D12CommandQueue* copyQueue;&#xD;&#xA;    ID3D12CommandAllocator* copyAllocator;&#xD;&#xA;    ID3D12GraphicsCommandList* copyList;&#xD;&#xA;    &#xD;&#xA;    D3D12_COMMAND_QUEUE_DESC descCopyQueue = {};&#xD;&#xA;    descCopyQueue.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;&#xD;&#xA;    descCopyQueue.Type = D3D12_COMMAND_LIST_TYPE_COPY;&#xD;&#xA;    device-&gt;CreateCommandQueue(&amp;descCopyQueue, IID_PPV_ARGS(&amp;copyQueue));&#xD;&#xA;    device-&gt;CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&amp;copyAllocator));&#xD;&#xA;    device-&gt;CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, copyAllocator, nullptr, IID_PPV_ARGS(&amp;copyList));&#xD;&#xA;&#xD;&#xA;Notice type `D3D12_COMMAND_LIST_TYPE_COPY`.&#xD;&#xA;&#xD;&#xA;Next thing is new buffer.&#xD;&#xA;&#xD;&#xA;    D3D12_HEAP_PROPERTIES const heapPropertiesReadback =&#xD;&#xA;    {&#xD;&#xA;    	/*Type*/					D3D12_HEAP_TYPE_READBACK&#xD;&#xA;    	/*CPUPageProperty*/			,D3D12_CPU_PAGE_PROPERTY_UNKNOWN&#xD;&#xA;    	/*MemoryPoolPreference*/	,D3D12_MEMORY_POOL_UNKNOWN&#xD;&#xA;    	/*CreationNodeMask*/		,0&#xD;&#xA;    	/*VisibleNodeMask*/			,0&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    D3D12_RESOURCE_DESC buffersDesc = {};&#xD;&#xA;    buffersDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;&#xD;&#xA;    buffersDesc.Alignment = 0;&#xD;&#xA;    buffersDesc.Width = sizeof( unsigned int ) * 5;&#xD;&#xA;    buffersDesc.Height = 1;&#xD;&#xA;    buffersDesc.DepthOrArraySize = 1;&#xD;&#xA;    buffersDesc.MipLevels = 1;&#xD;&#xA;    buffersDesc.Format = DXGI_FORMAT_UNKNOWN;&#xD;&#xA;    buffersDesc.SampleDesc.Count = 1;&#xD;&#xA;    buffersDesc.SampleDesc.Quality = 0;&#xD;&#xA;    buffersDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;&#xD;&#xA;    buffersDesc.Flags = D3D12_RESOURCE_FLAG_NONE;&#xD;&#xA;    &#xD;&#xA;    ID3D12Resource* bufferReadback;&#xD;&#xA;    	&#xD;&#xA;    device-&gt;CreateCommittedResource(&amp;heapPropertiesReadback, D3D12_HEAP_FLAG_NONE, &amp;buffersDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&amp;bufferReadback));&#xD;&#xA;&#xD;&#xA;Remember to set `D3D12_RESOURCE_DESC ::Width` to size of your buffers.&#xD;&#xA;&#xD;&#xA;Then after you `Dispatch` compute list and call `ExecuteCommandLists` on compute queue you need to use fence, copy buffer and use fence again.&#xD;&#xA;&#xD;&#xA;    computeQueue-&gt;Signal(fence, fenceValue);&#xD;&#xA;    fence-&gt;SetEventOnCompletion(fenceValue, fenceEvent);&#xD;&#xA;    ++fenceValue;&#xD;&#xA;    WaitForSingleObject(fenceEvent, INFINITE);&#xD;&#xA;    &#xD;&#xA;    copyList-&gt;CopyResource(bufferReadback, bufferB);&#xD;&#xA;    copyList-&gt;Close();&#xD;&#xA;    copyQueue-&gt;ExecuteCommandLists(1, (ID3D12CommandList**)(&amp;copyList));&#xD;&#xA;    &#xD;&#xA;    copyQueue-&gt;Signal(fence, fenceValue);&#xD;&#xA;    fence-&gt;SetEventOnCompletion(fenceValue, fenceEvent);&#xD;&#xA;    ++fenceValue;&#xD;&#xA;    WaitForSingleObject(fenceEvent, INFINITE);&#xD;&#xA;&#xD;&#xA;After this you can call `Map` on resource.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    unsigned int* data;&#xD;&#xA;    bufferReadback-&gt;Map(0, nullptr, reinterpret_cast&lt;void**&gt;(&amp;data));&#xD;&#xA;&#xD;&#xA;I hope this will help, let me know if you have any questions." ContentLicense="CC BY-SA 3.0" />
  <row Id="13292" PostHistoryTypeId="2" PostId="5026" RevisionGUID="63707049-b8a7-4c94-a2a6-287264990e5f" CreationDate="2017-04-26T07:32:22.853" UserId="38" Text="Ok, monotonic interpolation depends on what you are monotonic about. For a simple 1D function interpolation monotonicity is easy to define. But for a 2D and 3D dataset its not so self evident what the situation would be.&#xD;&#xA;&#xD;&#xA;* First you could interpolate along a independent variable t in which case your monotonicity is most probably in relation to t. This is the same as interpolating each direction separately.&#xD;&#xA;&#xD;&#xA;* Second you could interpolate along one of the axes, so that your interpolant becomes a function of position on that axis. Reducing a 2D case into a 1D case and a 3D case to two separate 2D cases.&#xD;&#xA;&#xD;&#xA;* Third you could interpolate on some other spatial variable.&#xD;&#xA;&#xD;&#xA;So you see the question is a bit open ended and is hard to say for sure." ContentLicense="CC BY-SA 3.0" />
  <row Id="13293" PostHistoryTypeId="2" PostId="5027" RevisionGUID="6cb98260-767f-4939-b348-9250cd9e059f" CreationDate="2017-04-26T17:31:25.210" UserDisplayName="user3412" Text="I'm working my way through this paper about GGX-filtering environment maps:&#xD;&#xA;&#xD;&#xA;http://www.ppsloan.org/publications/ggx_filtering.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I find myself stuck on the basics.  In particular, I am confused by two statements in section 1.1, related work:&#xD;&#xA;&#xD;&#xA;&gt; Most recent reflection models assume&#xD;&#xA;dielectric materials, and in the case of a metal would simply multiply&#xD;&#xA;the specular color by an auxiliary specular color map.&#xD;&#xA;&#xD;&#xA;This sentence immediately follows an overview of old-school mirrored torus environment mapping, which it refers to as &quot;metal&quot;.  However, I'm not sure what the author means by specular color here -- incident light or material color.  Likewise, what is this secondary map that is referenced.  Is that the metalness map from the currently popular PBR texturing workflow?  Or is &quot;auxillary specular color map&quot; a cubemap?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Importance&#xD;&#xA;sampling is inefficient for texture filtering because raster images&#xD;&#xA;are band-limited, which results in the peak of the function being&#xD;&#xA;oversampled&#xD;&#xA;&#xD;&#xA;I don't understand this at all.  I am still learning importance sampling via Peter Shirley's weekend book, so I kind of get the difference between sampling a function with infinite resolution and sampling a down sampled raster grid... but I don't know what the author means by band-limited and how that produces the peak oversampling effect.&#xD;&#xA;&#xD;&#xA;Sorry if these questions are overly naive!  I'm going to try to read (Kautz 03) now to hopefully fill in some gaps.  My ultimate goal is to write the simplest possible dynamic environment mapping demo to show an after school class the connection between offline global illumination and high-end realtime rendering.&#xD;&#xA;&#xD;&#xA;A side goal is to synthesize for myself a history of these techniques from the end of this article until today:&#xD;&#xA;&#xD;&#xA;http://www.pauldebevec.com/ReflectionMapping/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13294" PostHistoryTypeId="1" PostId="5027" RevisionGUID="6cb98260-767f-4939-b348-9250cd9e059f" CreationDate="2017-04-26T17:31:25.210" UserDisplayName="user3412" Text="Confused about prefiltering environment maps (Manson 16)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13295" PostHistoryTypeId="3" PostId="5027" RevisionGUID="6cb98260-767f-4939-b348-9250cd9e059f" CreationDate="2017-04-26T17:31:25.210" UserDisplayName="user3412" Text="|lighting|real-time|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13296" PostHistoryTypeId="2" PostId="5028" RevisionGUID="8c6be021-3b23-4bdd-a415-477cdaf29716" CreationDate="2017-04-26T20:55:08.593" UserId="6515" Text="I am trying to write my own path tracer in JavaSceipt, but I have a problem with implementation of russian roulette. First, let me describe how my path tracer works.&#xD;&#xA;&#xD;&#xA;I have a function called _traceRay_ where I am looking for ray-objects intersections and doing some shading. Shading is divided into direct and indirect illumination. I have a separate function that does Importance Sampling only and it is being called inside _traceRay_. This function gets Monte Carlo samples count and max recursion depth as parameters, generates sample rays and calls _traceRay_ again (if max recursion depth is not exceeded).&#xD;&#xA;&#xD;&#xA;(To recap: _traceRay_ calls a function for indirect illumination that calls _traceRay_)&#xD;&#xA;&#xD;&#xA;The problem is that when I remove recursion depth test and add russian roulette to my indirect illumination function I get &quot;Maximum call stack size exceeded&quot; error. Same problem is when I implement roulette in _traceRay_ function. But when I use only one Monte Carlo sample, everything works fine.&#xD;&#xA;&#xD;&#xA;My russian roulette algorithm works as follows: at the beginning of a function, I am checking if a pseudo-random number is less then some constant threshold. If so, I am returning black color. In other case, function does what it would do without roulette, but the returned value is divided by the threshold.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, the question is: how do I implement Russian Roulette properly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13297" PostHistoryTypeId="1" PostId="5028" RevisionGUID="8c6be021-3b23-4bdd-a415-477cdaf29716" CreationDate="2017-04-26T20:55:08.593" UserId="6515" Text="Russian Roulette - Maximum call stack size exceeded" ContentLicense="CC BY-SA 3.0" />
  <row Id="13298" PostHistoryTypeId="3" PostId="5028" RevisionGUID="8c6be021-3b23-4bdd-a415-477cdaf29716" CreationDate="2017-04-26T20:55:08.593" UserId="6515" Text="|pathtracing|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13299" PostHistoryTypeId="10" PostId="5028" RevisionGUID="a4969a05-f8b7-4432-9a26-931dd936cbbb" CreationDate="2017-04-27T08:37:33.740" UserId="2041" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="13300" PostHistoryTypeId="5" PostId="5028" RevisionGUID="c362c034-5942-4c61-8269-ac2165bc6883" CreationDate="2017-04-27T14:29:43.793" UserId="6515" Comment="added code" Text="I am trying to write my own path tracer in JavaSceipt, but I have a problem with implementation of russian roulette. First, let me describe how my path tracer works.&#xD;&#xA;&#xD;&#xA;I have a function called _traceRay_ where I am looking for ray-objects intersections and doing some shading. Shading is divided into direct and indirect illumination. I have a separate function that does Importance Sampling only and it is being called inside _traceRay_. This function gets Monte Carlo samples count and max recursion depth as parameters, generates sample rays and calls _traceRay_ again (if max recursion depth is not exceeded).&#xD;&#xA;&#xD;&#xA;    RayTracer.indirectLighting = function(scene, camera, intersectionPoint, normal, options)&#xD;&#xA;    {&#xD;&#xA;      var prob = 0.5;&#xD;&#xA;      var oneOverProb = 1/prob;&#xD;&#xA;      if(Math.random() &lt; prob) return new Vector(0,0,0);&#xD;&#xA;&#xD;&#xA;      var diffuse = new Vector(0, 0, 0);&#xD;&#xA;      var specular = new Vector(0, 0, 0);&#xD;&#xA;&#xD;&#xA;      if(options.MC_SAMPLES &gt; 0)// &amp;&amp; options.MC_DEPTH &gt; 0)&#xD;&#xA;      {&#xD;&#xA;        var basis = createCoordinationSystem(normal);&#xD;&#xA;        var sampleVector, sampleTransformed, mcRay;&#xD;&#xA;        for(var i = 0; i &lt; options.MC_SAMPLES; ++i)&#xD;&#xA;        {&#xD;&#xA;          sampleVector = getCosineWeightedSample(Math.random(), Math.random());&#xD;&#xA;          sampleTransformed = new Vector(sampleVector.x * basis.tangent.x + sampleVector.y * normal.x + sampleVector.z * basis.bitangent.x,&#xD;&#xA;                                     sampleVector.x * basis.tangent.y + sampleVector.y * normal.y + sampleVector.z * basis.bitangent.y,&#xD;&#xA;                                     sampleVector.x * basis.tangent.z + sampleVector.y * normal.z + sampleVector.z * basis.bitangent.z);&#xD;&#xA;          mcRay = new Ray(intersectionPoint.clone().add(sampleTransformed.clone().mul(0.000001)), sampleTransformed);&#xD;&#xA;&#xD;&#xA;          diffuse.add(RayTracer.traceRay(mcRay, scene, camera, {&#xD;&#xA;            MC_DEPTH: options.MC_DEPTH - 1,&#xD;&#xA;            MC_SAMPLES: options.MC_SAMPLES,&#xD;&#xA;            AREA_LIGHT_SAMPLES: options.AREA_LIGHT_SAMPLES&#xD;&#xA;          }));&#xD;&#xA;        }&#xD;&#xA;        diffuse.mul(1 / options.MC_SAMPLES);&#xD;&#xA;      }&#xD;&#xA;      return Vector.add(diffuse, specular).mul(oneOverProb);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RayTracer.traceRay = function(ray, scene, camera, options)&#xD;&#xA;    {&#xD;&#xA;      var color = new Vector(0, 0, 0);&#xD;&#xA;      //Depth test - finding closest object&#xD;&#xA;      var minT = 1e12, currentT;&#xD;&#xA;      var object = null;&#xD;&#xA;      var objectI;&#xD;&#xA;      for(var i = 0; i &lt; scene.objects.length; ++i)&#xD;&#xA;      {&#xD;&#xA;        currentT = scene.objects[i].intersects(ray);&#xD;&#xA;        if(currentT &gt; 0 &amp;&amp; currentT &lt; minT)&#xD;&#xA;        {&#xD;&#xA;          objectI = i;&#xD;&#xA;          minT = currentT;&#xD;&#xA;          object = scene.objects[i];&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      var emissiveObjects = [];&#xD;&#xA;      for(var i = 0; i &lt; scene.objects.length; ++i)&#xD;&#xA;      {&#xD;&#xA;        if(i == objectI) continue;&#xD;&#xA;        else if(scene.objects[i].isFinite &amp;&amp; scene.objects[i].material.emittance.lengthSq() &gt; 0.3)&#xD;&#xA;          emissiveObjects.push(scene.objects[i]);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      if(object == null) return new Vector(0, 0, 0);&#xD;&#xA;&#xD;&#xA;      var indirectLighting = new Vector(0, 0, 0);&#xD;&#xA;      var directLighting = new Vector(0, 0, 0);&#xD;&#xA;&#xD;&#xA;      var intersectionPoint = ray.getPoint(minT);&#xD;&#xA;      var normal = object.getNormalAt(intersectionPoint);&#xD;&#xA;      var toEye = camera.position.clone().sub(intersectionPoint).normalize();&#xD;&#xA;      var albedo = object.material.color.clone().mul(object.material.diffuseFactor);&#xD;&#xA;&#xD;&#xA;      //Direct illumination&#xD;&#xA;      for(var n = 0; n &lt; scene.lights.length; ++n)&#xD;&#xA;      {&#xD;&#xA;        //Searching for objects occluding light&#xD;&#xA;        var shadowRay = scene.lights[n].getShadowRay(intersectionPoint);&#xD;&#xA;        var inShadow = RayTracer.visabilityTest(shadowRay, scene.objects,&#xD;&#xA;      scene.lights[n].occlusionTestLimit(shadowRay)).occlusion;&#xD;&#xA;&#xD;&#xA;        if(!inShadow)&#xD;&#xA;        {&#xD;&#xA;          var lighting = scene.lights[n].getLightingInfo(intersectionPoint, normal, toEye);&#xD;&#xA;&#xD;&#xA;          directLighting.add(scene.lights[n].color.clone().mul(&#xD;&#xA;        lighting.diffuse * lighting.attenuation * scene.lights[n].intensity / Math.PI))&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      color.add(Vector.componetesMul(object.material.color, scene.ambient));&#xD;&#xA;&#xD;&#xA;      directLighting.add(RayTracer.sampleAreaLights(scene, emissiveObjects, intersectionPoint, normal, options.AREA_LIGHT_SAMPLES));&#xD;&#xA;      indirectLighting = RayTracer.indirectLighting(scene, camera, intersectionPoint, normal, options);&#xD;&#xA;&#xD;&#xA;      color.add(object.material.emittance.clone().clamp(0, 1));&#xD;&#xA;      color.add(Vector.componetesMul(directLighting.add(indirectLighting), albedo));&#xD;&#xA;&#xD;&#xA;      return color&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;The problem is that when I remove recursion depth test and add russian roulette to my indirect illumination function I get &quot;Maximum call stack size exceeded&quot; error. Same problem is when I implement roulette in _traceRay_ function. But when I use only one Monte Carlo sample, everything works fine.&#xD;&#xA;&#xD;&#xA;My russian roulette algorithm works as follows: at the beginning of a function, I am checking if a pseudo-random number is less then some constant threshold. If so, I am returning black color. In other case, function does what it would do without roulette, but the returned value is divided by the threshold.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, the question is: how do I implement Russian Roulette properly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13302" PostHistoryTypeId="5" PostId="5027" RevisionGUID="6ab3c9fc-fda3-453d-ad3f-8334bd944d8d" CreationDate="2017-04-27T15:30:18.527" UserDisplayName="user3412" Comment="added 2 characters in body" Text="I'm working my way through this paper about GGX-filtering environment maps:&#xD;&#xA;&#xD;&#xA;http://www.ppsloan.org/publications/ggx_filtering.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I find myself stuck on the basics.  In particular, I am confused by two statements in section 1.1, *Related Work*:&#xD;&#xA;&#xD;&#xA;&gt; Most recent reflection models assume&#xD;&#xA;dielectric materials, and in the case of a metal would simply multiply&#xD;&#xA;the specular color by an auxiliary specular color map.&#xD;&#xA;&#xD;&#xA;This sentence immediately follows an overview of old-school mirrored torus environment mapping, which it refers to as &quot;metal&quot;.  However, I'm not sure what the author means by specular color here -- incident light or material color.  Likewise, what is this secondary map that is referenced.  Is that the metalness map from the currently popular PBR texturing workflow?  Or is &quot;auxillary specular color map&quot; a cubemap?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Importance&#xD;&#xA;sampling is inefficient for texture filtering because raster images&#xD;&#xA;are band-limited, which results in the peak of the function being&#xD;&#xA;oversampled&#xD;&#xA;&#xD;&#xA;I don't understand this at all.  I am still learning importance sampling via Peter Shirley's weekend book, so I kind of get the difference between sampling a function with infinite resolution and sampling a down sampled raster grid... but I don't know what the author means by band-limited and how that produces the peak oversampling effect.&#xD;&#xA;&#xD;&#xA;Sorry if these questions are overly naive!  I'm going to try to read (Kautz 03) now to hopefully fill in some gaps.  My ultimate goal is to write the simplest possible dynamic environment mapping demo to show an after school class the connection between offline global illumination and high-end realtime rendering.&#xD;&#xA;&#xD;&#xA;A side goal is to synthesize for myself a history of these techniques from the end of this article until today:&#xD;&#xA;&#xD;&#xA;http://www.pauldebevec.com/ReflectionMapping/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13303" PostHistoryTypeId="2" PostId="5029" RevisionGUID="8cd7b78d-0bdc-4fa2-a841-a68020945d06" CreationDate="2017-04-27T19:45:51.180" UserId="5852" Text="This is the vertex shader code:&#xD;&#xA;&#xD;&#xA;	#version 330 core&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec3 position;&#xD;&#xA;	layout (location = 1) in vec3 myColor;&#xD;&#xA;&#xD;&#xA;	out vec3 MyColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		MyColor = myColor;&#xD;&#xA;		vec3 v = position;&#xD;&#xA;		v.x = v.x/v.z;&#xD;&#xA;		v.y = v.y/v.z;&#xD;&#xA;		gl_Position = vec4(v, 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This shader is fairly simple, but when I draw a square at the bottom instead of leaving the screen empty draws this shapes and I was wondering why does it happen:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uXmRW.png&#xD;&#xA;&#xD;&#xA;The following is an example code showing this behaviour so you only have to uncomment certain code snippets for checking it:&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT LIBRARIES&#xD;&#xA;	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;	GLFWwindow* window = glfwCreateWindow(200 ,200 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;	glViewport(0, 0, 200, 200);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//SHADERS&#xD;&#xA;	const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;void main()							\n&quot;&#xD;&#xA;		&quot;{										\n&quot;&#xD;&#xA;		&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;		&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;		&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;		&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;		&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;		&quot;}										\n&quot;;&#xD;&#xA;&#xD;&#xA;	const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;out vec4 color;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;void main()					\n&quot;&#xD;&#xA;		&quot;{								\n&quot;&#xD;&#xA;		&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;		&quot;}								\n&quot;;&#xD;&#xA;&#xD;&#xA;	GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;	glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;	fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;	glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;	program = glCreateProgram();&#xD;&#xA;	glAttachShader(program, vertex);&#xD;&#xA;	glAttachShader(program, fragment);&#xD;&#xA;	glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;	glDeleteShader(vertex);&#xD;&#xA;	glDeleteShader(fragment);&#xD;&#xA;	glUseProgram(program);&#xD;&#xA;&#xD;&#xA;	//VAOs &amp; VBOs&#xD;&#xA;	GLfloat vertices[] =&#xD;&#xA;//Uncomment one of the following set of vertices to see the program in action&#xD;&#xA;//The last one produces the strange behaviour&#xD;&#xA;	/*{&#xD;&#xA;			//This set will show you a square occuping the full window&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			 0.5f,  0.5f,  0.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw a square at the bottom&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw the square to the left (Z is negative therefore z/x is also negative and the x value is inversed)&#xD;&#xA;			-0.5f, -0.5f, -0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f, -0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f,  0.5f, -1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	{&#xD;&#xA;			//This set should not draw anything because y = y/z -&gt; y = -0.5/[-0.25,+0.25] -&gt; y = (-inf,-4] U [4,inf)&#xD;&#xA;			//[-0.25,+0.25] means any value between -0.25 and 0.25&#xD;&#xA;			//(-inf,-4] U [4,inf) means any value that is not between -4 and 4&#xD;&#xA;			//Whathever value 'y' gets is out of the range [-1,1] so it should not be visible, but instead a figure is drawn causing the strange behaviour&#xD;&#xA;			 1.0f, -1.0f, -1.0f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-1.0f, -1.0f, -1.0f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 1.0f, -1.0f,  1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-1.0f, -1.0f,  1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;&#xD;&#xA;	GLuint VAO, VBO;&#xD;&#xA;	glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;	glBindVertexArray(VAO);&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//DRAW&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;	glfwSwapBuffers(window);&#xD;&#xA;	while (!glfwWindowShouldClose(window))&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//END&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;&#xD;&#xA;	return 0;&#xD;&#xA;}&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13304" PostHistoryTypeId="1" PostId="5029" RevisionGUID="8cd7b78d-0bdc-4fa2-a841-a68020945d06" CreationDate="2017-04-27T19:45:51.180" UserId="5852" Text="Strange behaviour in vertex shader with divisions" ContentLicense="CC BY-SA 3.0" />
  <row Id="13305" PostHistoryTypeId="3" PostId="5029" RevisionGUID="8cd7b78d-0bdc-4fa2-a841-a68020945d06" CreationDate="2017-04-27T19:45:51.180" UserId="5852" Text="|opengl|shader|c++|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13306" PostHistoryTypeId="2" PostId="5030" RevisionGUID="cf7e07e0-80b2-430f-b5db-d41b19020b42" CreationDate="2017-04-27T22:19:58.360" UserId="506" Text="I’m not sure where you’re getting the `y = -0.5/[-0.25, +0.25]` in your comments from, or what you’re expecting to produce values of `inf`. Going by the code in your vertex shader, the last set of vertices produces the following:&#xD;&#xA;&#xD;&#xA;    ( 1,  1, -1) → (-1,  1)&#xD;&#xA;    (-1, -1, -1) → ( 1,  1)&#xD;&#xA;    ( 1, -1,  1) → ( 1, -1)&#xD;&#xA;    (-1, -1,  1) → (-1, -1)&#xD;&#xA;&#xD;&#xA;…which is a 2×2 square, centered on (0,0), with the points specified in clockwise order (which won’t draw correctly with a triangle strip, as you’re seeing in the above screenshot)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13307" PostHistoryTypeId="5" PostId="5029" RevisionGUID="9bd6bce7-8eb2-4bc4-a54b-c99f389f3827" CreationDate="2017-04-27T22:25:40.607" UserId="5852" Comment="added 4 characters in body" Text="This is the vertex shader code:&#xD;&#xA;&#xD;&#xA;	#version 330 core&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec3 position;&#xD;&#xA;	layout (location = 1) in vec3 myColor;&#xD;&#xA;&#xD;&#xA;	out vec3 MyColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		MyColor = myColor;&#xD;&#xA;		vec3 v = position;&#xD;&#xA;		v.x = v.x/v.z;&#xD;&#xA;		v.y = v.y/v.z;&#xD;&#xA;		gl_Position = vec4(v, 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This shader is fairly simple, but when I draw a square at the bottom instead of leaving the screen empty draws this shapes and I was wondering why does it happen:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uXmRW.png&#xD;&#xA;&#xD;&#xA;The following is an example code showing this behaviour so you only have to uncomment certain code snippets for checking it:&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT LIBRARIES&#xD;&#xA;	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;	GLFWwindow* window = glfwCreateWindow(200 ,200 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;	glViewport(0, 0, 200, 200);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//SHADERS&#xD;&#xA;	const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;void main()							\n&quot;&#xD;&#xA;		&quot;{										\n&quot;&#xD;&#xA;		&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;		&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;		&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;		&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;		&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;		&quot;}										\n&quot;;&#xD;&#xA;&#xD;&#xA;	const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;out vec4 color;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;void main()					\n&quot;&#xD;&#xA;		&quot;{								\n&quot;&#xD;&#xA;		&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;		&quot;}								\n&quot;;&#xD;&#xA;&#xD;&#xA;	GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;	glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;	fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;	glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;	program = glCreateProgram();&#xD;&#xA;	glAttachShader(program, vertex);&#xD;&#xA;	glAttachShader(program, fragment);&#xD;&#xA;	glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;	glDeleteShader(vertex);&#xD;&#xA;	glDeleteShader(fragment);&#xD;&#xA;	glUseProgram(program);&#xD;&#xA;&#xD;&#xA;	//VAOs &amp; VBOs&#xD;&#xA;	GLfloat vertices[] =&#xD;&#xA;//Uncomment one of the following set of vertices to see the program in action&#xD;&#xA;//The last one produces the strange behaviour&#xD;&#xA;	/*{&#xD;&#xA;			//This set will show you a square occuping the full window&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			 0.5f,  0.5f,  0.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw a square at the bottom&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw the square to the left (Z is negative therefore z/x is also negative and the x value is inversed)&#xD;&#xA;			-0.5f, -0.5f, -0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f, -0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f,  0.5f, -1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	{&#xD;&#xA;			//This set should not draw anything because y = y/z -&gt; y = -0.5/[-0.25,+0.25] -&gt; y = (-inf,-4] U [4,inf)&#xD;&#xA;			//[-0.25,+0.25] means any value between -0.25 and 0.25&#xD;&#xA;			//(-inf,-4] U [4,inf) means any value that is not between -4 and 4&#xD;&#xA;			//Whathever value 'y' gets is out of the range [-1,1] so it should not be visible, but instead a figure is drawn causing the strange behaviour&#xD;&#xA;			 0.5f, -0.5f, -0.25f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -0.25f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.25f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.25f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;&#xD;&#xA;	GLuint VAO, VBO;&#xD;&#xA;	glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;	glBindVertexArray(VAO);&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//DRAW&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;	glfwSwapBuffers(window);&#xD;&#xA;	while (!glfwWindowShouldClose(window))&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//END&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;&#xD;&#xA;	return 0;&#xD;&#xA;}&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13308" PostHistoryTypeId="5" PostId="5030" RevisionGUID="8f47c954-c021-4aee-843d-aa2086a18738" CreationDate="2017-04-27T23:14:32.577" UserId="506" Comment="added 63 characters in body" Text="Going by the code in your vertex shader, the last set of vertices produces the following:&#xD;&#xA;&#xD;&#xA;    ( 0.5, -0.5, -0.25) → (-2,  2)&#xD;&#xA;    (-0.5, -0.5, -0.25) → ( 2,  2)&#xD;&#xA;    ( 0.5, -0.5,  0.25) → ( 2, -2)&#xD;&#xA;    (-0.5, -0.5,  0.25) → (-2, -2)&#xD;&#xA;&#xD;&#xA;…which is a 4×4 square, centered on (0,0), with the points specified in clockwise order (which won’t draw correctly with a triangle strip, as you’re seeing in the above screenshot).&#xD;&#xA;&#xD;&#xA;It looks like you’re expecting `y` values outside of the [-1, 1] range to not be drawn at all, but all that’s doing is drawing triangles that are larger than the viewport." ContentLicense="CC BY-SA 3.0" />
  <row Id="13309" PostHistoryTypeId="2" PostId="5031" RevisionGUID="154c1aa1-df7a-4759-8d5a-e13c31acf343" CreationDate="2017-04-28T01:29:40.230" UserId="1952" Text="Your first quote is referring to &quot;Split-sum approximation&quot; presented in &quot;[Real Shading in Unreal Engine 4][1]&quot; by Brian Karis, and also referred in the paper [Kar13]:&#xD;&#xA;&#xD;&#xA;$$\frac{1}{N}\sum_{k=1}^N \frac{L_i(l_k)f(l_k,v)cos\theta_{l_k}}{p(l_k,v)}\approx \bigg(\frac{1}{N}L_i(l_k)\bigg)\bigg(\frac{1}{N}\sum_{k=1}^N \frac{f(l_k,v)cos\theta_{l_k}}{p(l_k,v)}\bigg)$$&#xD;&#xA;&#xD;&#xA;In split-sum approximation the incident radiance (cubemap) is pre-convolved with GGX kernel using for example importance sampling, and normal-incident specular reflectance ($F_0$ or &quot;specular color&quot; you refer to) is multiplied with another pre-convolved 2D look-up-texture (referred as &quot;an auxiliary specular color map&quot;) shown below.&#xD;&#xA;&#xD;&#xA;[![Split-Sum 2D LUT][2]][2]&#xD;&#xA;&#xD;&#xA;Next about your second question of importance sampling being inefficient due to band-limited signal - It simply means that the incident radiance is sampled with finite resolution (cubemap resolution) and thus higher frequencies have been filtered out. But because importance sampling biases samples to important regions of the function (peak of the GGX BRDF) this region may be sampled in unnecessarily high frequency thus wasting samples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://de45xmedrsdbp.cloudfront.net/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/OlGdF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13310" PostHistoryTypeId="5" PostId="2240" RevisionGUID="4efadd9b-17d3-4d2e-b75b-4034db6077e9" CreationDate="2017-04-28T04:33:33.773" UserDisplayName="user246" Comment="math formula syntax, spelling" Text="I'm stuck on this question asking me to calculate the intensity of a pixel using Ray Tracing. It gives values such as $I_i$ but doesn't give any coordinates. &#xD;&#xA;&#xD;&#xA;I know for the diffuse component, $I_ik_d(n,l)$ can be written as $I_ik_d(\cos\theta)$ but for the specular component $I_ik_s(h\cdot n)$ is there any other way to write it so that it doesn't require any vectors such as $h$ and $n$?&#xD;&#xA; &#xD;&#xA;This is the question:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3s0AC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13311" PostHistoryTypeId="24" PostId="2240" RevisionGUID="4efadd9b-17d3-4d2e-b75b-4034db6077e9" CreationDate="2017-04-28T04:33:33.773" Comment="Proposed by 246 approved by 2359 edit id of 227" ContentLicense="CC BY-SA 3.0" />
  <row Id="13312" PostHistoryTypeId="5" PostId="4795" RevisionGUID="fd714d9f-7009-4b41-a934-3e14d52d5d5e" CreationDate="2017-04-28T04:41:04.670" UserDisplayName="user246" Comment="corrected spelling" Text="Since you have a limited set of tools you are not actually doing a classical fitting. What you have is a discrete problem. And since you are looking for a somewhat easily drawn fit, no more that twice segmented for example.&#xD;&#xA;&#xD;&#xA;One way to approach this is to find all the points that match your curvature requirements. Then find the point x units away from point on both ends for all of these see how well it matches. If the curvature match at the endpoint is too much off then this isn't a good candidate. If you don't find a good candidate split the problem into two. Once you have found a goodish candidate slide the result to see if relaxing the thing makes the error more symmetric.&#xD;&#xA;&#xD;&#xA;Some things to note. Since your french curve is accelerating from one end to another you need to split beziers and b-splines at each span where the curve changes direction. Also be one you've found a good endpoints be sure to check that the halfway isn't too much off.&#xD;&#xA;&#xD;&#xA;Now if you want to do a classical fitting like approach then you need to parametrize the sliding and scale of your curve. This is not likely useful since you in fact can not scale your rules at whim.&#xD;&#xA;&#xD;&#xA;Or then you could just get a spline, you know one of those things that were used before computers and stuff, and write instructions on how to set up the spline." ContentLicense="CC BY-SA 3.0" />
  <row Id="13313" PostHistoryTypeId="24" PostId="4795" RevisionGUID="fd714d9f-7009-4b41-a934-3e14d52d5d5e" CreationDate="2017-04-28T04:41:04.670" Comment="Proposed by 246 approved by 38 edit id of 225" ContentLicense="CC BY-SA 3.0" />
  <row Id="13318" PostHistoryTypeId="2" PostId="5033" RevisionGUID="8df0cd47-ba5c-4875-82a4-70c219ef7c33" CreationDate="2017-04-28T06:54:53.087" UserId="6524" Text="What is the name of effect, that we see on far objects in outdoors ? These objects are low-contrast, foggy ? Is it only fog or some scattering ? [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1EEw5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13319" PostHistoryTypeId="1" PostId="5033" RevisionGUID="8df0cd47-ba5c-4875-82a4-70c219ef7c33" CreationDate="2017-04-28T06:54:53.087" UserId="6524" Text="What is name for far lowcontrast blueish landspace?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13320" PostHistoryTypeId="3" PostId="5033" RevisionGUID="8df0cd47-ba5c-4875-82a4-70c219ef7c33" CreationDate="2017-04-28T06:54:53.087" UserId="6524" Text="|rendering|fog|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13321" PostHistoryTypeId="11" PostId="5028" RevisionGUID="89ddafa4-d4d1-4fe6-9bee-d6f324af80a1" CreationDate="2017-04-28T08:15:07.623" UserId="2041" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="13322" PostHistoryTypeId="2" PostId="5034" RevisionGUID="cba15e0e-3df3-4af9-b87a-8eb91252052d" CreationDate="2017-04-28T08:15:41.523" UserId="209" Text="Do you mean [haze](http://www.thefreedictionary.com/haze)?&#xD;&#xA;&#xD;&#xA;FWIW, in Australia the Blue Mountains get their name from the [release of oil into the atmosphere from the eucalypts](http://www.australia.gov.au/about-australia/australian-story/eucalypts)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13323" PostHistoryTypeId="5" PostId="2366" RevisionGUID="30ebf713-70f5-478b-abac-f98adcc5f7ec" CreationDate="2017-04-28T08:15:44.547" UserDisplayName="user246" Comment="moved text to beginning, corrected spelling, trimmed" Text="I'm currently trying to develop a game using Cocos2d-x using C++.&#xD;&#xA;I really need to generate this burst or (donut-shaped) pulse.&#xD;&#xA;I'm having a difficult time how to generate such shape.&#xD;&#xA;&#xD;&#xA;At first, I was thinking of scaling the image but that didn't work out because the line or &quot;diameter&quot; of the donut shape gets bigger accordingly.&#xD;&#xA;Any experienced coders who can provide an equation of this thing? or maybe &quot;mathematics&quot; is more exact.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![c++ code sample][1]][1]&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=ewnEE5mt1ZM&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t5yOY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13324" PostHistoryTypeId="24" PostId="2366" RevisionGUID="30ebf713-70f5-478b-abac-f98adcc5f7ec" CreationDate="2017-04-28T08:15:44.547" Comment="Proposed by 246 approved by 38, 2041 edit id of 226" ContentLicense="CC BY-SA 3.0" />
  <row Id="13326" PostHistoryTypeId="2" PostId="5035" RevisionGUID="b73820dd-7eea-443f-a3b2-caa567e99407" CreationDate="2017-04-28T08:34:48.740" UserId="2041" Text="As Simon F says, the meterological phenomenon that causes this is *haze*. A physicist would call it an example of *scattering*, but the visual effect is known as *[aerial perspective](https://en.wikipedia.org/wiki/Aerial_perspective)*. Reproducing this in paintings has been a technique since the 15th Century, with Leonardo da Vinci one of the early proponents.&#xD;&#xA;&#xD;&#xA;Since your question included a nice real-world example, here's a computer graphics example, courtesy of Dave Pape (CC-by) from a [slide deck of techniques for showing depth](http://resumbrae.com/ub/dms423_f07/09/):&#xD;&#xA;&#xD;&#xA;![Aerial perspective in GTA](https://i.stack.imgur.com/rT2lh.jpg)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13327" PostHistoryTypeId="50" PostId="4917" RevisionGUID="2da3b030-caf5-4e4b-9a30-e32846693769" CreationDate="2017-04-28T09:39:22.340" UserId="-1" />
  <row Id="13328" PostHistoryTypeId="2" PostId="5036" RevisionGUID="27e30a0a-8693-409e-97a1-fbfdae8a8f53" CreationDate="2017-04-28T13:53:00.643" UserId="1952" Text="In computer graphics the effect is called &quot;[atmospheric scattering][1]&quot;, that's sun light scattering from atoms and other particles in the atmosphere. In modern computer games atmospheric scattering is commonly modelled with [Bruneton sky model][2] by Eric Bruneton and is most prevalent in the clear sky due to long view distances, but also visible for distant objects on ground as you have observed.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Atmospheric scattering in Bruneton model is composed of Mie and Rayleigh scattering. Mie scattering is mostly wavelength independent strongly anisotropic scattering from particles that are quite a bit larger than the wavelength of light (water droplets &amp; pollution in the atmosphere). Mie scattering results in effects like halo around the sun.&#xD;&#xA;&#xD;&#xA;Rayleigh scattering on the other hand is wavelength dependent scattering from atoms in the atmosphere whose size is close to the visible light wavelength range. Rayleigh scattering is responsible of effects such as the blueish sky at noon and blueish tint of objects in the distance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.severewx.com/Radiation/scattering.html&#xD;&#xA;  [2]: http://www-evasion.imag.fr/people/Eric.Bruneton/&#xD;&#xA;  [3]: https://i.stack.imgur.com/I681a.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13329" PostHistoryTypeId="5" PostId="5036" RevisionGUID="1d2f2058-c899-43b4-9a5c-c6b8b4031022" CreationDate="2017-04-28T14:00:57.553" UserId="1952" Comment="added 132 characters in body" Text="In computer graphics the effect is called &quot;[atmospheric scattering][1]&quot;, that's sun light scattering from atoms and other particles in the atmosphere. In modern computer games atmospheric scattering is commonly modelled with [Bruneton sky model][2] by Eric Bruneton and is most prevalent in the clear sky due to long view distances, but also visible for distant objects on ground as you have observed.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Atmospheric scattering in Bruneton model is composed of [Mie scattering][4] and [Rayleigh scattering][5]. Mie scattering is mostly wavelength independent strongly anisotropic scattering from particles that are quite a bit larger than the wavelength of light (water droplets &amp; pollution in the atmosphere). Mie scattering results in effects like halo around the sun.&#xD;&#xA;&#xD;&#xA;Rayleigh scattering on the other hand is wavelength dependent scattering from atoms in the atmosphere whose size is close to the visible light wavelength range. Rayleigh scattering is responsible of effects such as the blueish sky at noon and blueish tint of objects in the distance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.severewx.com/Radiation/scattering.html&#xD;&#xA;  [2]: http://www-evasion.imag.fr/people/Eric.Bruneton/&#xD;&#xA;  [3]: https://i.stack.imgur.com/I681a.jpg&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Mie_scattering&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Rayleigh_scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13330" PostHistoryTypeId="5" PostId="5029" RevisionGUID="1f3985b1-fe6c-4d0e-8b7a-c5d15f09942a" CreationDate="2017-04-28T16:36:44.800" UserId="5852" Comment="added 4803 characters in body" Text="This is the vertex shader code:&#xD;&#xA;&#xD;&#xA;	#version 330 core&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec3 position;&#xD;&#xA;	layout (location = 1) in vec3 myColor;&#xD;&#xA;&#xD;&#xA;	out vec3 MyColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		MyColor = myColor;&#xD;&#xA;		vec3 v = position;&#xD;&#xA;		v.x = v.x/v.z;&#xD;&#xA;		v.y = v.y/v.z;&#xD;&#xA;		gl_Position = vec4(v, 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This shader is fairly simple, but when I draw a square at the bottom instead of leaving the screen empty draws this shapes and I was wondering why does it happen:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uXmRW.png&#xD;&#xA;&#xD;&#xA;The following is an example code showing this behaviour so you only have to uncomment certain code snippets for checking it:&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT LIBRARIES&#xD;&#xA;	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;	GLFWwindow* window = glfwCreateWindow(200 ,200 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;	glViewport(0, 0, 200, 200);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//SHADERS&#xD;&#xA;	const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;void main()							\n&quot;&#xD;&#xA;		&quot;{										\n&quot;&#xD;&#xA;		&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;		&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;		&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;		&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;		&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;		&quot;}										\n&quot;;&#xD;&#xA;&#xD;&#xA;	const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;out vec4 color;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;void main()					\n&quot;&#xD;&#xA;		&quot;{								\n&quot;&#xD;&#xA;		&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;		&quot;}								\n&quot;;&#xD;&#xA;&#xD;&#xA;	GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;	glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;	fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;	glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;	program = glCreateProgram();&#xD;&#xA;	glAttachShader(program, vertex);&#xD;&#xA;	glAttachShader(program, fragment);&#xD;&#xA;	glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;	glDeleteShader(vertex);&#xD;&#xA;	glDeleteShader(fragment);&#xD;&#xA;	glUseProgram(program);&#xD;&#xA;&#xD;&#xA;	//VAOs &amp; VBOs&#xD;&#xA;	GLfloat vertices[] =&#xD;&#xA;//Uncomment one of the following set of vertices to see the program in action&#xD;&#xA;//The last one produces the strange behaviour&#xD;&#xA;	/*{&#xD;&#xA;			//This set will show you a square occuping the full window&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			 0.5f,  0.5f,  0.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw a square at the bottom&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw the square to the left (Z is negative therefore z/x is also negative and the x value is inversed)&#xD;&#xA;			-0.5f, -0.5f, -0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f, -0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f,  0.5f, -1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	{&#xD;&#xA;			//This set should not draw anything because y = y/z -&gt; y = -0.5/[-0.25,+0.25] -&gt; y = (-inf,-4] U [4,inf)&#xD;&#xA;			//[-0.25,+0.25] means any value between -0.25 and 0.25&#xD;&#xA;			//(-inf,-4] U [4,inf) means any value that is not between -4 and 4&#xD;&#xA;			//Whathever value 'y' gets is out of the range [-1,1] so it should not be visible, but instead a figure is drawn causing the strange behaviour&#xD;&#xA;			 0.5f, -0.5f, -0.25f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -0.25f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.25f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.25f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;&#xD;&#xA;	GLuint VAO, VBO;&#xD;&#xA;	glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;	glBindVertexArray(VAO);&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//DRAW&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;	glfwSwapBuffers(window);&#xD;&#xA;	while (!glfwWindowShouldClose(window))&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//END&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;&#xD;&#xA;	return 0;&#xD;&#xA;}&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;&#xD;&#xA;**EDIT** The following link is a youtube video will show you how the square gets transformed with different Z values:&#xD;&#xA;&#xD;&#xA;https://youtu.be/S4TsfZjCIbM&#xD;&#xA;&#xD;&#xA;And this is the code that I used for the video:&#xD;&#xA;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	&#xD;&#xA;	#define GLEW_STATIC&#xD;&#xA;	#include &lt;GL/glew.h&gt;&#xD;&#xA;	&#xD;&#xA;	#include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;	&#xD;&#xA;	int main()&#xD;&#xA;	{&#xD;&#xA;		//INIT LIBRARIES&#xD;&#xA;		glfwInit();&#xD;&#xA;		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;		glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;		GLFWwindow* window = glfwCreateWindow(400 ,400 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;		glfwMakeContextCurrent(window);&#xD;&#xA;		glewExperimental = GL_TRUE;&#xD;&#xA;		glewInit();&#xD;&#xA;		glViewport(0, 0, 400, 400);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//SHADERS&#xD;&#xA;		const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;			&quot;#version 330 core						\n&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;			&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;			&quot;&quot;&#xD;&#xA;			&quot;uniform float movement;&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;void main()							\n&quot;&#xD;&#xA;			&quot;{										\n&quot;&#xD;&#xA;			&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;			&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;			&quot;	v.z = v.z - movement;				\n&quot;&#xD;&#xA;			&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;			&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;			&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;			&quot;}										\n&quot;;&#xD;&#xA;	&#xD;&#xA;		const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;			&quot;#version 330 core				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;out vec4 color;				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;void main()					\n&quot;&#xD;&#xA;			&quot;{								\n&quot;&#xD;&#xA;			&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;			&quot;}								\n&quot;;&#xD;&#xA;	&#xD;&#xA;		GLuint program;&#xD;&#xA;		GLuint vertex, fragment;&#xD;&#xA;	&#xD;&#xA;		vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;		glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;		glCompileShader(vertex);&#xD;&#xA;	&#xD;&#xA;		fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;		glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;		glCompileShader(fragment);&#xD;&#xA;	&#xD;&#xA;		program = glCreateProgram();&#xD;&#xA;		glAttachShader(program, vertex);&#xD;&#xA;		glAttachShader(program, fragment);&#xD;&#xA;		glLinkProgram(program);&#xD;&#xA;	&#xD;&#xA;		glDeleteShader(vertex);&#xD;&#xA;		glDeleteShader(fragment);&#xD;&#xA;	&#xD;&#xA;		GLfloat uniform = glGetUniformLocation(program, &quot;movement&quot;);&#xD;&#xA;		glUseProgram(program);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//VAOs &amp; VBOs&#xD;&#xA;		GLfloat vertices[] =&#xD;&#xA;	//Uncomment one of the following set of vertices to see the program in action&#xD;&#xA;	//The last one produces the strange behaviour&#xD;&#xA;		/*{&#xD;&#xA;				//This set will show you a square occuping the full window&#xD;&#xA;				-0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;				-0.5f,  0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;				 0.5f, -0.5f,  0.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;				 0.5f,  0.5f,  0.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;		};/**/&#xD;&#xA;		{&#xD;&#xA;				//This set draw a square at the bottom&#xD;&#xA;				 0.25f, -0.25f,  1.0f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;				-0.25f, -0.25f,  1.0f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;				 0.25f, -0.25f,  1.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;				-0.25f, -0.25f,  1.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;		};/**/&#xD;&#xA;		/*{&#xD;&#xA;				//This set draw the square to the left (Z is negative therefore z/x is also negative and the x value is inversed)&#xD;&#xA;				-0.5f, -0.5f, -0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;				-0.5f,  0.5f, -0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;				-0.5f, -0.5f, -1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;				-0.5f,  0.5f, -1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;		};/**/&#xD;&#xA;		/*{&#xD;&#xA;				//This set should not draw anything because y = y/z -&gt; y = -0.5/[-0.25,+0.25] -&gt; y = (-inf,-4] U [4,inf)&#xD;&#xA;				//[-0.25,+0.25] means any value between -0.25 and 0.25&#xD;&#xA;				//(-inf,-4] U [4,inf) means any value that is not between -4 and 4&#xD;&#xA;				//Whathever value 'y' gets is out of the range [-1,1] so it should not be visible, but instead a figure is drawn causing the strange behaviour&#xD;&#xA;				 0.5f, -0.5f, -0.25f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;				-0.5f, -0.5f, -0.25f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;				 0.5f, -0.5f,  0.25f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;				-0.5f, -0.5f,  0.25f,		1.0f, 1.0f, 0.0f&#xD;&#xA;		};/**/&#xD;&#xA;	&#xD;&#xA;		GLuint VAO, VBO;&#xD;&#xA;		glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;		glBindVertexArray(VAO);&#xD;&#xA;		glGenBuffers(1, &amp;VBO);&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);&#xD;&#xA;		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//DRAW&#xD;&#xA;		GLfloat movement = 0.0f;&#xD;&#xA;		glfwSetTime(0.0);&#xD;&#xA;	&#xD;&#xA;		while (!glfwWindowShouldClose(window))&#xD;&#xA;		{&#xD;&#xA;			if(movement &gt;= 2.5f)&#xD;&#xA;				glfwSetTime(0.0);&#xD;&#xA;			glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;			movement = glfwGetTime()/4;&#xD;&#xA;			glUniform1f(uniform, movement);&#xD;&#xA;			glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;			glfwSwapBuffers(window);&#xD;&#xA;			glfwPollEvents();&#xD;&#xA;		}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//END&#xD;&#xA;		glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;		glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;		glfwTerminate();&#xD;&#xA;	&#xD;&#xA;		return 0;&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13331" PostHistoryTypeId="5" PostId="5029" RevisionGUID="ff6cbdb6-c731-4c1a-b80a-1b440371e3a1" CreationDate="2017-04-28T16:42:57.340" UserId="5852" Comment="added 5 characters in body" Text="This is the vertex shader code:&#xD;&#xA;&#xD;&#xA;	#version 330 core&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec3 position;&#xD;&#xA;	layout (location = 1) in vec3 myColor;&#xD;&#xA;&#xD;&#xA;	out vec3 MyColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		MyColor = myColor;&#xD;&#xA;		vec3 v = position;&#xD;&#xA;		v.x = v.x/v.z;&#xD;&#xA;		v.y = v.y/v.z;&#xD;&#xA;		gl_Position = vec4(v, 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This shader is fairly simple, but when I draw a square at the bottom instead of leaving the screen empty draws this shapes and I was wondering why does it happen:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uXmRW.png&#xD;&#xA;&#xD;&#xA;The following is an example code showing this behaviour so you only have to uncomment certain code snippets for checking it:&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT LIBRARIES&#xD;&#xA;	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;	GLFWwindow* window = glfwCreateWindow(200 ,200 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;	glViewport(0, 0, 200, 200);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//SHADERS&#xD;&#xA;	const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;void main()							\n&quot;&#xD;&#xA;		&quot;{										\n&quot;&#xD;&#xA;		&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;		&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;		&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;		&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;		&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;		&quot;}										\n&quot;;&#xD;&#xA;&#xD;&#xA;	const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;out vec4 color;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;void main()					\n&quot;&#xD;&#xA;		&quot;{								\n&quot;&#xD;&#xA;		&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;		&quot;}								\n&quot;;&#xD;&#xA;&#xD;&#xA;	GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;	glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;	fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;	glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;	program = glCreateProgram();&#xD;&#xA;	glAttachShader(program, vertex);&#xD;&#xA;	glAttachShader(program, fragment);&#xD;&#xA;	glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;	glDeleteShader(vertex);&#xD;&#xA;	glDeleteShader(fragment);&#xD;&#xA;	glUseProgram(program);&#xD;&#xA;&#xD;&#xA;	//VAOs &amp; VBOs&#xD;&#xA;	GLfloat vertices[] =&#xD;&#xA;//Uncomment one of the following set of vertices to see the program in action&#xD;&#xA;//The last one produces the strange behaviour&#xD;&#xA;	/*{&#xD;&#xA;			//This set will show you a square occuping the full window&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			 0.5f,  0.5f,  0.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw a square at the bottom&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw the square to the left (Z is negative therefore z/x is also negative and the x value is inversed)&#xD;&#xA;			-0.5f, -0.5f, -0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f, -0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f,  0.5f, -1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	{&#xD;&#xA;			//This set should not draw anything because y = y/z -&gt; y = -0.5/[-0.25,+0.25] -&gt; y = (-inf,-4] U [4,inf)&#xD;&#xA;			//[-0.25,+0.25] means any value between -0.25 and 0.25&#xD;&#xA;			//(-inf,-4] U [4,inf) means any value that is not between -4 and 4&#xD;&#xA;			//Whathever value 'y' gets is out of the range [-1,1] so it should not be visible, but instead a figure is drawn causing the strange behaviour&#xD;&#xA;			 0.5f, -0.5f, -0.25f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -0.25f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.25f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.25f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;&#xD;&#xA;	GLuint VAO, VBO;&#xD;&#xA;	glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;	glBindVertexArray(VAO);&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//DRAW&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;	glfwSwapBuffers(window);&#xD;&#xA;	while (!glfwWindowShouldClose(window))&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//END&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;&#xD;&#xA;	return 0;&#xD;&#xA;}&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;&#xD;&#xA;**EDIT** The following link is a youtube video that will show you how the square gets transformed with different Z values:&#xD;&#xA;&#xD;&#xA;https://youtu.be/S4TsfZjCIbM&#xD;&#xA;&#xD;&#xA;And this is the code that I used for the video:&#xD;&#xA;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	&#xD;&#xA;	#define GLEW_STATIC&#xD;&#xA;	#include &lt;GL/glew.h&gt;&#xD;&#xA;	&#xD;&#xA;	#include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;	&#xD;&#xA;	int main()&#xD;&#xA;	{&#xD;&#xA;		//INIT LIBRARIES&#xD;&#xA;		glfwInit();&#xD;&#xA;		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;		glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;		GLFWwindow* window = glfwCreateWindow(400 ,400 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;		glfwMakeContextCurrent(window);&#xD;&#xA;		glewExperimental = GL_TRUE;&#xD;&#xA;		glewInit();&#xD;&#xA;		glViewport(0, 0, 400, 400);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//SHADERS&#xD;&#xA;		const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;			&quot;#version 330 core						\n&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;			&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;			&quot;&quot;&#xD;&#xA;			&quot;uniform float movement;&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;void main()							\n&quot;&#xD;&#xA;			&quot;{										\n&quot;&#xD;&#xA;			&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;			&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;			&quot;	v.z = v.z - movement;				\n&quot;&#xD;&#xA;			&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;			&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;			&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;			&quot;}										\n&quot;;&#xD;&#xA;	&#xD;&#xA;		const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;			&quot;#version 330 core				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;out vec4 color;				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;void main()					\n&quot;&#xD;&#xA;			&quot;{								\n&quot;&#xD;&#xA;			&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;			&quot;}								\n&quot;;&#xD;&#xA;	&#xD;&#xA;		GLuint program;&#xD;&#xA;		GLuint vertex, fragment;&#xD;&#xA;	&#xD;&#xA;		vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;		glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;		glCompileShader(vertex);&#xD;&#xA;	&#xD;&#xA;		fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;		glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;		glCompileShader(fragment);&#xD;&#xA;	&#xD;&#xA;		program = glCreateProgram();&#xD;&#xA;		glAttachShader(program, vertex);&#xD;&#xA;		glAttachShader(program, fragment);&#xD;&#xA;		glLinkProgram(program);&#xD;&#xA;	&#xD;&#xA;		glDeleteShader(vertex);&#xD;&#xA;		glDeleteShader(fragment);&#xD;&#xA;	&#xD;&#xA;		GLfloat uniform = glGetUniformLocation(program, &quot;movement&quot;);&#xD;&#xA;		glUseProgram(program);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//VAOs &amp; VBOs&#xD;&#xA;		GLfloat vertices[] =&#xD;&#xA;		{&#xD;&#xA;				 0.25f, -0.25f,  1.0f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;				-0.25f, -0.25f,  1.0f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;				 0.25f, -0.25f,  1.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;				-0.25f, -0.25f,  1.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;		};&#xD;&#xA;	&#xD;&#xA;		GLuint VAO, VBO;&#xD;&#xA;		glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;		glBindVertexArray(VAO);&#xD;&#xA;		glGenBuffers(1, &amp;VBO);&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);&#xD;&#xA;		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//DRAW&#xD;&#xA;		GLfloat movement = 0.0f;&#xD;&#xA;		glfwSetTime(0.0);&#xD;&#xA;	&#xD;&#xA;		while (!glfwWindowShouldClose(window))&#xD;&#xA;		{&#xD;&#xA;			if(movement &gt;= 2.5f)&#xD;&#xA;				glfwSetTime(0.0);&#xD;&#xA;			glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;			movement = glfwGetTime()/4;&#xD;&#xA;			glUniform1f(uniform, movement);&#xD;&#xA;			glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;			glfwSwapBuffers(window);&#xD;&#xA;			glfwPollEvents();&#xD;&#xA;		}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//END&#xD;&#xA;		glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;		glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;		glfwTerminate();&#xD;&#xA;	&#xD;&#xA;		return 0;&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13332" PostHistoryTypeId="5" PostId="5029" RevisionGUID="fd488c0c-808a-4133-86fb-c8052e267e66" CreationDate="2017-04-28T16:55:31.200" UserId="5852" Comment="added 190 characters in body" Text="This is the vertex shader code:&#xD;&#xA;&#xD;&#xA;	#version 330 core&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec3 position;&#xD;&#xA;	layout (location = 1) in vec3 myColor;&#xD;&#xA;&#xD;&#xA;	out vec3 MyColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		MyColor = myColor;&#xD;&#xA;		vec3 v = position;&#xD;&#xA;		v.x = v.x/v.z;&#xD;&#xA;		v.y = v.y/v.z;&#xD;&#xA;		gl_Position = vec4(v, 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This shader is fairly simple, but when I draw a square at the bottom instead of leaving the screen empty draws this shapes and I was wondering why does it happen:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uXmRW.png&#xD;&#xA;&#xD;&#xA;The following is an example code showing this behaviour so you only have to uncomment certain code snippets for checking it:&#xD;&#xA;&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT LIBRARIES&#xD;&#xA;	glfwInit();&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;	GLFWwindow* window = glfwCreateWindow(200 ,200 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;	glfwMakeContextCurrent(window);&#xD;&#xA;	glewExperimental = GL_TRUE;&#xD;&#xA;	glewInit();&#xD;&#xA;	glViewport(0, 0, 200, 200);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//SHADERS&#xD;&#xA;	const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;		&quot;										\n&quot;&#xD;&#xA;		&quot;void main()							\n&quot;&#xD;&#xA;		&quot;{										\n&quot;&#xD;&#xA;		&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;		&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;		&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;		&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;		&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;		&quot;}										\n&quot;;&#xD;&#xA;&#xD;&#xA;	const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;out vec4 color;				\n&quot;&#xD;&#xA;		&quot;								\n&quot;&#xD;&#xA;		&quot;void main()					\n&quot;&#xD;&#xA;		&quot;{								\n&quot;&#xD;&#xA;		&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;		&quot;}								\n&quot;;&#xD;&#xA;&#xD;&#xA;	GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;	glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;	fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;	glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;	glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;	program = glCreateProgram();&#xD;&#xA;	glAttachShader(program, vertex);&#xD;&#xA;	glAttachShader(program, fragment);&#xD;&#xA;	glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;	glDeleteShader(vertex);&#xD;&#xA;	glDeleteShader(fragment);&#xD;&#xA;	glUseProgram(program);&#xD;&#xA;&#xD;&#xA;	//VAOs &amp; VBOs&#xD;&#xA;	GLfloat vertices[] =&#xD;&#xA;//Uncomment one of the following set of vertices to see the program in action&#xD;&#xA;//The last one produces the strange behaviour&#xD;&#xA;	/*{&#xD;&#xA;			//This set will show you a square occuping the full window&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			 0.5f,  0.5f,  0.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw a square at the bottom&#xD;&#xA;			 0.5f, -0.5f,  0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	/*{&#xD;&#xA;			//This set draw the square to the left (Z is negative therefore z/x is also negative and the x value is inversed)&#xD;&#xA;			-0.5f, -0.5f, -0.5f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f,  0.5f, -0.5f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -1.0f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f,  0.5f, -1.0f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;	{&#xD;&#xA;			//This set should not draw anything because y = y/z -&gt; y = -0.5/[-0.25,+0.25] -&gt; y = (-inf,-4] U [4,inf)&#xD;&#xA;			//[-0.25,+0.25] means any value between -0.25 and 0.25&#xD;&#xA;			//(-inf,-4] U [4,inf) means any value that is not between -4 and 4&#xD;&#xA;			//Whathever value 'y' gets is out of the range [-1,1] so it should not be visible, but instead a figure is drawn causing the strange behaviour&#xD;&#xA;			 0.5f, -0.5f, -0.25f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;			-0.5f, -0.5f, -0.25f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;			 0.5f, -0.5f,  0.25f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;			-0.5f, -0.5f,  0.25f,		1.0f, 1.0f, 0.0f&#xD;&#xA;	};/**/&#xD;&#xA;&#xD;&#xA;	GLuint VAO, VBO;&#xD;&#xA;	glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;	glBindVertexArray(VAO);&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//DRAW&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;	glfwSwapBuffers(window);&#xD;&#xA;	while (!glfwWindowShouldClose(window))&#xD;&#xA;		glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//END&#xD;&#xA;	glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;	glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;	glfwTerminate();&#xD;&#xA;&#xD;&#xA;	return 0;&#xD;&#xA;}&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;&#xD;&#xA;**EDIT** The following link is a youtube video that will show you how the square gets transformed with different Z values:&#xD;&#xA;&#xD;&#xA;https://youtu.be/S4TsfZjCIbM&#xD;&#xA;&#xD;&#xA;And this is the code that I used for the video:&#xD;&#xA;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	&#xD;&#xA;	#define GLEW_STATIC&#xD;&#xA;	#include &lt;GL/glew.h&gt;&#xD;&#xA;	&#xD;&#xA;	#include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;	&#xD;&#xA;	int main()&#xD;&#xA;	{&#xD;&#xA;		//INIT LIBRARIES&#xD;&#xA;		glfwInit();&#xD;&#xA;		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;		glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;		GLFWwindow* window = glfwCreateWindow(400 ,400 , &quot;&quot;, nullptr, nullptr);&#xD;&#xA;		glfwMakeContextCurrent(window);&#xD;&#xA;		glewExperimental = GL_TRUE;&#xD;&#xA;		glewInit();&#xD;&#xA;		glViewport(0, 0, 400, 400);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//SHADERS&#xD;&#xA;		const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;			&quot;#version 330 core						\n&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;layout (location = 0) in vec3 position;\n&quot;&#xD;&#xA;			&quot;layout (location = 1) in vec3 myColor;	\n&quot;&#xD;&#xA;			&quot;&quot;&#xD;&#xA;			&quot;uniform float movement;&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;out vec3 MyColor;						\n&quot;&#xD;&#xA;			&quot;										\n&quot;&#xD;&#xA;			&quot;void main()							\n&quot;&#xD;&#xA;			&quot;{										\n&quot;&#xD;&#xA;			&quot;	MyColor = myColor;					\n&quot;&#xD;&#xA;			&quot;	vec3 v = position;					\n&quot;&#xD;&#xA;			&quot;	v.z = v.z - movement;				\n&quot;&#xD;&#xA;			&quot;	v.x = v.x/v.z;						\n&quot;&#xD;&#xA;			&quot;	v.y = v.y/v.z;						\n&quot;&#xD;&#xA;			&quot;	gl_Position = vec4(v, 1.0f);		\n&quot;&#xD;&#xA;			&quot;}										\n&quot;;&#xD;&#xA;	&#xD;&#xA;		const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;			&quot;#version 330 core				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;in vec3 MyColor;				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;out vec4 color;				\n&quot;&#xD;&#xA;			&quot;								\n&quot;&#xD;&#xA;			&quot;void main()					\n&quot;&#xD;&#xA;			&quot;{								\n&quot;&#xD;&#xA;			&quot;	color = vec4(MyColor,1.0f);	\n&quot;&#xD;&#xA;			&quot;}								\n&quot;;&#xD;&#xA;	&#xD;&#xA;		GLuint program;&#xD;&#xA;		GLuint vertex, fragment;&#xD;&#xA;	&#xD;&#xA;		vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;		glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;		glCompileShader(vertex);&#xD;&#xA;	&#xD;&#xA;		fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;		glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;		glCompileShader(fragment);&#xD;&#xA;	&#xD;&#xA;		program = glCreateProgram();&#xD;&#xA;		glAttachShader(program, vertex);&#xD;&#xA;		glAttachShader(program, fragment);&#xD;&#xA;		glLinkProgram(program);&#xD;&#xA;	&#xD;&#xA;		glDeleteShader(vertex);&#xD;&#xA;		glDeleteShader(fragment);&#xD;&#xA;	&#xD;&#xA;		GLfloat uniform = glGetUniformLocation(program, &quot;movement&quot;);&#xD;&#xA;		glUseProgram(program);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//VAOs &amp; VBOs&#xD;&#xA;		GLfloat vertices[] =&#xD;&#xA;		{&#xD;&#xA;				 0.25f, -0.25f,  1.0f,		1.0f, 0.0f, 0.0f,&#xD;&#xA;				-0.25f, -0.25f,  1.0f,		0.0f, 1.0f, 0.0f,&#xD;&#xA;				 0.25f, -0.25f,  1.5f,		0.0f, 0.0f, 1.0f,&#xD;&#xA;				-0.25f, -0.25f,  1.5f,		1.0f, 1.0f, 0.0f&#xD;&#xA;		};&#xD;&#xA;	&#xD;&#xA;		GLuint VAO, VBO;&#xD;&#xA;		glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;		glBindVertexArray(VAO);&#xD;&#xA;		glGenBuffers(1, &amp;VBO);&#xD;&#xA;		glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);&#xD;&#xA;		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;		glEnableVertexAttribArray(0);&#xD;&#xA;		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));&#xD;&#xA;		glEnableVertexAttribArray(1);&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//DRAW&#xD;&#xA;		GLfloat movement = 0.0f;&#xD;&#xA;		glfwSetTime(0.0);&#xD;&#xA;	&#xD;&#xA;		while (!glfwWindowShouldClose(window))&#xD;&#xA;		{&#xD;&#xA;			if(movement &gt;= 2.5f)&#xD;&#xA;				glfwSetTime(0.0);&#xD;&#xA;			glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;			movement = glfwGetTime()/4;&#xD;&#xA;			glUniform1f(uniform, movement);&#xD;&#xA;			glDrawArrays(GL_TRIANGLE_STRIP, 0,4);&#xD;&#xA;			glfwSwapBuffers(window);&#xD;&#xA;			glfwPollEvents();&#xD;&#xA;		}&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;	&#xD;&#xA;		//END&#xD;&#xA;		glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;		glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;		glfwTerminate();&#xD;&#xA;	&#xD;&#xA;		return 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**EDIT 2** The problem was that I believed the vertex shader runs for every point in the square, but instead it only run for the 4 vertex specified. Now the problem is... How can I fix it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13333" PostHistoryTypeId="2" PostId="5037" RevisionGUID="6798a4a0-605c-4e31-9b24-3798f43c6aec" CreationDate="2017-04-28T17:18:44.537" UserId="48" Text="The vertex shader only runs per vertex, not for every point in the square. So the four vertices are mapped to (±2, ±2), and then the GPU draws a polygon between those vertices, which does cross the viewport.&#xD;&#xA;&#xD;&#xA;The points interior to the polygon do not go through the `v.y = v.y/v.z` transform, so the resulting point set is not $(-\infty,-2] \cup [2,\infty)$ after all.&#xD;&#xA;&#xD;&#xA;For this reason, one can't generally do non-linear geometry transformations in the vertex shader alone—except for perspective projection, which has special hardware support. (You run into this problem as well if you try to do any non-linear camera projection, such as a fisheye projection.) There are two ways to solve it:&#xD;&#xA;&#xD;&#xA;1. Subdivide the geometry into small pieces so that the vertices are closely spaced. Then, applying the nonlinear transform per vertex may be a good-enough approximation.&#xD;&#xA;&#xD;&#xA; Also, since in your case the transform has a discontinuity at $z = 0$, you would need to split the original polygon into two pieces (each with its own set of vertices) where it crosses the $z = 0$ plane, and push the split vertices away from that plane, so you'd have $z = \pm \epsilon$, where $\epsilon$ is some small number. [It might even work to use IEEE floating point &quot;negative zero&quot; values here; not sure.] Otherwise the pieces that cross $z = 0$ will cause the same problem all over again.&#xD;&#xA;&#xD;&#xA;2. Do the transform as an image-space process, i.e. in the pixel shader rather than the vertex shader. This is used for example for lens distortion correction in VR: the image is rendered first using an ordinary perspective projection, then resampled to the distorted projection. This requires being able to invert the transform, i.e. map from the destination pixel position back to the corresponding source position, then sampling the source pixel from a texture." ContentLicense="CC BY-SA 3.0" />
  <row Id="13335" PostHistoryTypeId="5" PostId="5031" RevisionGUID="797688c3-ef78-4666-850d-4bb02e52c07a" CreationDate="2017-04-29T01:37:46.317" UserId="1952" Comment="added 13 characters in body" Text="Your first quote is referring to &quot;Split-sum approximation&quot; presented in &quot;[Real Shading in Unreal Engine 4][1]&quot; by Brian Karis, and also referred in the paper [Kar13]:&#xD;&#xA;&#xD;&#xA;$$\frac{1}{N}\sum_{k=1}^N \frac{L_i(l_k)f(l_k,v)cos\theta_{l_k}}{p(l_k,v)}\approx \bigg(\frac{1}{N}\sum_{k=1}^N L_i(l_k)\bigg)\bigg(\frac{1}{N}\sum_{k=1}^N \frac{f(l_k,v)cos\theta_{l_k}}{p(l_k,v)}\bigg)$$&#xD;&#xA;&#xD;&#xA;In split-sum approximation the incident radiance (cubemap) is pre-convolved with GGX kernel using for example importance sampling, and normal-incident specular reflectance ($F_0$ or &quot;specular color&quot; you refer to) is multiplied with another pre-convolved 2D look-up-texture (referred as &quot;an auxiliary specular color map&quot;) shown below.&#xD;&#xA;&#xD;&#xA;[![Split-Sum 2D LUT][2]][2]&#xD;&#xA;&#xD;&#xA;Next about your second question of importance sampling being inefficient due to band-limited signal - It simply means that the incident radiance is sampled with finite resolution (cubemap resolution) and thus higher frequencies have been filtered out. But because importance sampling biases samples to important regions of the function (peak of the GGX BRDF) this region may be sampled in unnecessarily high frequency thus wasting samples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://de45xmedrsdbp.cloudfront.net/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/OlGdF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13337" PostHistoryTypeId="2" PostId="5039" RevisionGUID="441be6ce-9e01-467d-a484-d59bdddf0205" CreationDate="2017-04-29T16:37:22.760" UserId="6534" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems to go crazy as the cosine between wo and the shading space z axis gets past .9999, which in my cornell box scene  is a pretty big 8 - 9 degree circle of crazy results.  when I say crazy, i mean that the samples seems to incorrectly switch the sign of the an axis and backwards-offset themselves angularly a small amount, when in that small area, and the samples that exceed the cosine .9999 angle with the surface normal (shading space z-axis) produce results that are sane and agree with each other.&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, most of which has been incredibly enlightening, and I have seen their sample_wi function, but it performs this crazy way too, generating seemingly wild vectors when close to normal incidence.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what." ContentLicense="CC BY-SA 3.0" />
  <row Id="13338" PostHistoryTypeId="1" PostId="5039" RevisionGUID="441be6ce-9e01-467d-a484-d59bdddf0205" CreationDate="2017-04-29T16:37:22.760" UserId="6534" Text="How to generate a half vector from a distribution (cook-torrence, trowbridge-reitz, etc)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13339" PostHistoryTypeId="3" PostId="5039" RevisionGUID="441be6ce-9e01-467d-a484-d59bdddf0205" CreationDate="2017-04-29T16:37:22.760" UserId="6534" Text="|raytracing|brdf|sampling|monte-carlo|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13343" PostHistoryTypeId="2" PostId="5040" RevisionGUID="2e815ba6-c151-46cd-88d8-ecb4803e290c" CreationDate="2017-04-29T21:26:31.417" UserId="6535" Text="Lately I've been reading about texture filtering, namely Nearest-neighbor filtering, Bilinear filtering, Trilinear filtering, Anisotropic filtering, Mip maps, Rip Maps and so on. &#xD;&#xA;&#xD;&#xA;From a high-level perspective I think I can understand these techniques, how the work and why they exist, with the exception of Anisotropic filtering. Anisotropic filtering is driving me nuts. &#xD;&#xA;&#xD;&#xA;I can see the problem of having to texturize a surface that is at an angle relative to the camera, but I don't get how sampling trapezoidal footprints could solve this (although I can see the result). This is probably because I DO NOT understand how the trapezoidal footprint is calculated and how the enclosed telexes are weighted to sample the texture. &#xD;&#xA;&#xD;&#xA;This article by [Nvidia](http://www.geforce.com/whats-new/guides/aa-af-guide#1) confuses me even more, by using sentences as &quot;*when a texel is trapezoidal*&quot; or &quot;*anisotropic filtering scales either the height or width of a mipmap by a ratio relative to the perspective distortion of the texture*&quot;. Trapezoidal texel? Scaling a MIPmap? What does this even mean?&#xD;&#xA;&#xD;&#xA;Could you help me grasp how AF and AF levels work? &#xD;&#xA;&#xD;&#xA;Please note that my goal is NOT to have an OpenGL or DirectX AF implementation, but rather to grasp how AF works from a high-level perspective." ContentLicense="CC BY-SA 3.0" />
  <row Id="13344" PostHistoryTypeId="1" PostId="5040" RevisionGUID="2e815ba6-c151-46cd-88d8-ecb4803e290c" CreationDate="2017-04-29T21:26:31.417" UserId="6535" Text="Help me grasp Anisotropic Filtering (AF)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13345" PostHistoryTypeId="3" PostId="5040" RevisionGUID="2e815ba6-c151-46cd-88d8-ecb4803e290c" CreationDate="2017-04-29T21:26:31.417" UserId="6535" Text="|opengl|texture|filtering|directx|mipmap|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13346" PostHistoryTypeId="5" PostId="5040" RevisionGUID="578dd7df-4c35-4402-844a-ca40cf710b4b" CreationDate="2017-04-29T21:58:06.757" UserId="6535" Comment="edited body" Text="Lately I've been reading about texture filtering, namely Nearest-neighbor filtering, Bilinear filtering, Trilinear filtering, Anisotropic filtering, MIP maps, RIP Maps and so on. &#xD;&#xA;&#xD;&#xA;From a high-level perspective I think I can understand these techniques, how the work and why they exist, with the exception of Anisotropic filtering. Anisotropic filtering is driving me nuts. &#xD;&#xA;&#xD;&#xA;I can see the problem of having to texturize a surface that is at an angle relative to the camera, but I don't get how sampling trapezoidal footprints could solve this (although I can see the result). This is probably because I DO NOT understand how the trapezoidal footprint is calculated and how the enclosed telexes are weighted to sample the texture. &#xD;&#xA;&#xD;&#xA;This article by [Nvidia](http://www.geforce.com/whats-new/guides/aa-af-guide#1) confuses me even more, by using sentences as &quot;*when a texel is trapezoidal*&quot; or &quot;*anisotropic filtering scales either the height or width of a mipmap by a ratio relative to the perspective distortion of the texture*&quot;. Trapezoidal texel? Scaling a MIPmap? What does this even mean?&#xD;&#xA;&#xD;&#xA;Could you help me grasp how AF and AF levels work? &#xD;&#xA;&#xD;&#xA;Please note that my goal is NOT to have an OpenGL or DirectX AF implementation, but rather to grasp how AF works from a high-level perspective." ContentLicense="CC BY-SA 3.0" />
  <row Id="13347" PostHistoryTypeId="2" PostId="5041" RevisionGUID="71849d9b-824b-436f-ad3e-98aa13bf3f4f" CreationDate="2017-04-29T23:28:28.417" UserId="3003" Text="A few points that you probably already know, but that I just want to put out there for others reading this. Filtering in this case refers to low-pass filtering like you might get from a Gaussian Blur or a box blur. We need to do this because we are taking some media that has high frequencies in it, and rendering it into a smaller space. If we didn't filter it, we would get aliasing artifacts, which would look bad. So we filter out the frequencies that are too high to be accurately reproduced in the scaled version. (And we pass the low frequencies, so we use a &quot;low pass&quot; filter like a blur.)&#xD;&#xA;&#xD;&#xA;So let's think about this first from the point of view of a blur. A blur is a type of convolution. We take the convolution kernel and multiply it by all the pixels in an area and then add them together and divide by the weight. That gives us the output of one pixel. Then we move it over and do it again for the next pixel over, and again, etc.&#xD;&#xA;&#xD;&#xA;It's really expensive to do it that way, so there's a way to cheat. Some convolution kernels (particularly a Gaussian blur kernel and a box blur kernel) can be separated into a horizontal and vertical pass. You can filter everything with just a horizontal kernel first, then take the result of that and filter it with just a vertical kernel, and the result will be identical to doing the more expensive calculation at every point. Here's an example:&#xD;&#xA;&#xD;&#xA;Original:&#xD;&#xA;&#xD;&#xA;[![Hawaii][1]][1]&#xD;&#xA;&#xD;&#xA;Horizontal Blur:&#xD;&#xA;&#xD;&#xA;[![Hawaii blurred horizontally][2]][2]&#xD;&#xA;&#xD;&#xA;Horizontal followed by Vertical Blur:&#xD;&#xA;&#xD;&#xA;[![Hawaii blurred horizontally and then vertically][3]][3]&#xD;&#xA;&#xD;&#xA;So we can separate the filtering into a vertical and horizontal pass. So what? Well, it turns out that we can do the same thing for spatial transforms. If you think about a perspective rotation, like this:&#xD;&#xA;&#xD;&#xA;[![Hawaii Rotated around Y-axis][4]][4]&#xD;&#xA;&#xD;&#xA;It can be broken down into an X scale:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;followed by a scale of each column by a slightly different amount:&#xD;&#xA;&#xD;&#xA;[![Hawaii scaled in X and then proportionally in Y][6]][6]&#xD;&#xA;&#xD;&#xA;So now you have 2 different scaling operations. To get the filtering correct for this, you're going to want to filter more heavily in X than in Y, and you're going to want to filter by a different amount for each column. The first column gets no filtering because it's the same size as the original. The second column gets just a little because it's just slightly smaller than the first, etc. The last column gets the most filtering of any column.&#xD;&#xA;&#xD;&#xA;The word &quot;anisotropy&quot; comes from the greek &quot;an&quot; meaning &quot;not&quot;, &quot;isos&quot; meaning equal, and &quot;tropos&quot; meaning &quot;direction&quot;. So it means &quot;not equal in all directions.&quot; And that's exactly what we see - the scaling and the filtering are done in different amounts in each direction.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NFK7C.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5BbgB.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/AGa3e.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/OzqBz.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/u6orj.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/FDSRm.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13348" PostHistoryTypeId="5" PostId="5040" RevisionGUID="39af82b2-ee2b-4f56-aa97-619bdbbe1a50" CreationDate="2017-04-29T23:47:16.007" UserId="6535" Comment="deleted 1 character in body" Text="Lately I've been reading about texture filtering, namely Nearest-neighbor filtering, Bilinear filtering, Trilinear filtering, Anisotropic filtering, MIP maps, RIP Maps and so on. &#xD;&#xA;&#xD;&#xA;From a high-level perspective I think I can understand these techniques, how the work and why they exist, with the exception of Anisotropic filtering. Anisotropic filtering is driving me nuts. &#xD;&#xA;&#xD;&#xA;I can see the problem of having to texturize a surface that is at an angle relative to the camera, but I don't get how sampling trapezoidal footprints could solve this (although I can see the result). This is probably because I DO NOT understand how the trapezoidal footprint is calculated and how the enclosed telexes are weighted to sample the texture. &#xD;&#xA;&#xD;&#xA;This article by [Nvidia](http://www.geforce.com/whats-new/guides/aa-af-guide#1) confuses me even more by using sentences as &quot;*when a texel is trapezoidal*&quot; or &quot;*anisotropic filtering scales either the height or width of a mipmap by a ratio relative to the perspective distortion of the texture*&quot;. Trapezoidal texel? Scaling a MIPmap? What does this even mean?&#xD;&#xA;&#xD;&#xA;Could you help me grasp how AF and AF levels work? &#xD;&#xA;&#xD;&#xA;Please note that my goal is NOT to have an OpenGL or DirectX AF implementation, but rather to grasp how AF works from a high-level perspective." ContentLicense="CC BY-SA 3.0" />
  <row Id="13349" PostHistoryTypeId="2" PostId="5042" RevisionGUID="881cbec3-a063-40a0-9a5a-19ae46045191" CreationDate="2017-04-30T03:04:03.403" UserId="2654" Text="To understand the nature of anisotropic filtering, you need to have a firm understanding of what texture mapping really means.&#xD;&#xA;&#xD;&#xA;The term &quot;texture mapping&quot; means to assign positions on an object to locations in a texture. This permits the rasterizer/shader to, for each position on the object, fetch the corresponding data from the texture. The traditional method for doing this is to assign each vertex on an object a texture coordinate, which directly maps that position to a location in the texture. The rasterizer will interpolate this texture coordinate across the faces of the various triangles to produce the texture coordinate used to fetch the color from the texture.&#xD;&#xA;&#xD;&#xA;Now, let's think about the process of rasterization. How does that work? It takes a triangle and breaks it up into pixel-sized blocks which we will call &quot;fragments&quot;. Now, these pixel-sized blocks are pixel-sized relative to the screen.&#xD;&#xA;&#xD;&#xA;But these fragments are not pixel-sized relative to the *texture.* Imagine if our rasterizer generated a texture coordinate for each corner of the fragment. Now imagine drawing those 4 corners, not in screen space, but in *texture space*. What shape would this be?&#xD;&#xA;&#xD;&#xA;Well, that depends on the texture coordinates. That is, it depends on how the texture is mapped to the polygon. For any particular fragment, it might be an axis-aligned square. It might be a non-axis-aligned square. It might be a rectangle. It might be a trapezoid. It might be pretty much *any four-sided figure* (or at least, convex ones).&#xD;&#xA;&#xD;&#xA;If you were doing texture accessing correctly, the way to get the texture color for a fragment would be to figure out what this rectangle is. Then fetch every texel from the texture within that rectangle (using coverage to scale colors that are on the border). Then average them all together. That would be perfect texture mapping.&#xD;&#xA;&#xD;&#xA;It would also be *exceedingly slow*.&#xD;&#xA;&#xD;&#xA;In the interest of performance, we instead try to approximate the real answer. We base things on one texture coordinate, rather than the 4 that cover the entire fragment's area in texel space.&#xD;&#xA;&#xD;&#xA;Mipmap-based filtering uses lower-resolution images. These images are basically a shortcut for the perfect method, by pre-computing what large blocks of colors would look like when blended together. So when it selects a lower mipmap, it is using pre-computed values where each texel represents an area of the texture.&#xD;&#xA;&#xD;&#xA;Anisotropic filtering works by approximating the perfect method (which can, and should, be coupled with mipmapping) through taking up to a fixed number of additional samples. But how does it figure out the area in texel space to fetch from, since it's still only given one texture coordinate?&#xD;&#xA;&#xD;&#xA;Basically, it cheats. Because fragment shaders are executed in 2x2 neighboring blocks, it is possible to compute the derivative of any value in the fragment shader in screen-space X and Y. It then uses these derivatives, coupled with the actual texture coordinate, to compute an approximation of what the true fragment's texture footprint would be. And then it performs a number of samples within this area.&#xD;&#xA;&#xD;&#xA;Here's a diagram to help explain it:&#xD;&#xA;&#xD;&#xA;[![Fragment footprint and anisotropic samples. FYI: if you've seen it before, it's mine.][1]][1]&#xD;&#xA;&#xD;&#xA;The black-and-white squares represent our texture. It's just a checkerboard of 2x2 white and black texels.&#xD;&#xA;&#xD;&#xA;The orange dot is the texture coordinate for the fragment in question. The red outline is the fragment's footprint, which is centered on the texture coordinate.&#xD;&#xA;&#xD;&#xA;The green boxes represent the texels that an anisotropic filtering implementation *might* access (the details of anisotropic filtering algorithms are platform specific, so I can only explain the general idea). &#xD;&#xA;&#xD;&#xA;This particular diagram suggests that an implementation might access 4 texels. Oh yes, the green boxes cover 7 of them, but the green box in the center could fetch from a smaller mipmap, thus fetching the equivalent of 4 texels in one fetch. The implementation would of course weight the average for that fetch by 4 relative to the single texel ones.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/H9G6E.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13350" PostHistoryTypeId="5" PostId="5042" RevisionGUID="68354f48-8c91-4104-a8f4-abe2b7702456" CreationDate="2017-04-30T03:14:36.227" UserId="2654" Comment="added 164 characters in body" Text="To understand the nature of anisotropic filtering, you need to have a firm understanding of what texture mapping really means.&#xD;&#xA;&#xD;&#xA;The term &quot;texture mapping&quot; means to assign positions on an object to locations in a texture. This permits the rasterizer/shader to, for each position on the object, fetch the corresponding data from the texture. The traditional method for doing this is to assign each vertex on an object a texture coordinate, which directly maps that position to a location in the texture. The rasterizer will interpolate this texture coordinate across the faces of the various triangles to produce the texture coordinate used to fetch the color from the texture.&#xD;&#xA;&#xD;&#xA;Now, let's think about the process of rasterization. How does that work? It takes a triangle and breaks it up into pixel-sized blocks which we will call &quot;fragments&quot;. Now, these pixel-sized blocks are pixel-sized relative to the screen.&#xD;&#xA;&#xD;&#xA;But these fragments are not pixel-sized relative to the *texture.* Imagine if our rasterizer generated a texture coordinate for each corner of the fragment. Now imagine drawing those 4 corners, not in screen space, but in *texture space*. What shape would this be?&#xD;&#xA;&#xD;&#xA;Well, that depends on the texture coordinates. That is, it depends on how the texture is mapped to the polygon. For any particular fragment, it might be an axis-aligned square. It might be a non-axis-aligned square. It might be a rectangle. It might be a trapezoid. It might be pretty much *any four-sided figure* (or at least, convex ones).&#xD;&#xA;&#xD;&#xA;If you were doing texture accessing correctly, the way to get the texture color for a fragment would be to figure out what this rectangle is. Then fetch every texel from the texture within that rectangle (using coverage to scale colors that are on the border). Then average them all together. That would be perfect texture mapping.&#xD;&#xA;&#xD;&#xA;It would also be *exceedingly slow*.&#xD;&#xA;&#xD;&#xA;In the interest of performance, we instead try to approximate the real answer. We base things on one texture coordinate, rather than the 4 that cover the entire fragment's area in texel space.&#xD;&#xA;&#xD;&#xA;Mipmap-based filtering uses lower-resolution images. These images are basically a shortcut for the perfect method, by pre-computing what large blocks of colors would look like when blended together. So when it selects a lower mipmap, it is using pre-computed values where each texel represents an area of the texture.&#xD;&#xA;&#xD;&#xA;Anisotropic filtering works by approximating the perfect method (which can, and should, be coupled with mipmapping) through taking up to a fixed number of additional samples. But how does it figure out the area in texel space to fetch from, since it's still only given one texture coordinate?&#xD;&#xA;&#xD;&#xA;Basically, it cheats. Because fragment shaders are executed in 2x2 neighboring blocks, it is possible to compute the derivative of any value in the fragment shader in screen-space X and Y. It then uses these derivatives, coupled with the actual texture coordinate, to compute an approximation of what the true fragment's texture footprint would be. And then it performs a number of samples within this area.&#xD;&#xA;&#xD;&#xA;Here's a diagram to help explain it:&#xD;&#xA;&#xD;&#xA;[![Fragment footprint and anisotropic samples. FYI: if you've seen it before, it's mine.][1]][1]&#xD;&#xA;&#xD;&#xA;The black-and-white squares represent our texture. It's just a checkerboard of 2x2 white and black texels.&#xD;&#xA;&#xD;&#xA;The orange dot is the texture coordinate for the fragment in question. The red outline is the fragment's footprint, which is centered on the texture coordinate.&#xD;&#xA;&#xD;&#xA;The green boxes represent the texels that an anisotropic filtering implementation *might* access (the details of anisotropic filtering algorithms are platform specific, so I can only explain the general idea). &#xD;&#xA;&#xD;&#xA;This particular diagram suggests that an implementation might access 4 texels. Oh yes, the green boxes cover 7 of them, but the green box in the center could fetch from a smaller mipmap, thus fetching the equivalent of 4 texels in one fetch. The implementation would of course weight the average for that fetch by 4 relative to the single texel ones.&#xD;&#xA;&#xD;&#xA;If the anisotropic filtering limit was 2 rather than 4 (or higher), then the implementation would pick 2 of those samples to represent the fragment's footprint.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/H9G6E.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13351" PostHistoryTypeId="5" PostId="5028" RevisionGUID="bf6a7407-5db6-471d-8856-78a01ce02e1d" CreationDate="2017-04-30T10:26:31.120" UserId="231" Comment="Minor typo" Text="I am trying to write my own path tracer in JavaScript, but I have a problem with the implementation of russian roulette. First, let me describe how my path tracer works.&#xD;&#xA;&#xD;&#xA;I have a function called _traceRay_ where I am looking for ray-objects intersections and doing some shading. Shading is divided into direct and indirect illumination. I have a separate function that does Importance Sampling only and it is being called inside _traceRay_. This function gets Monte Carlo samples count and max recursion depth as parameters, generates sample rays and calls _traceRay_ again (if max recursion depth is not exceeded).&#xD;&#xA;&#xD;&#xA;    RayTracer.indirectLighting = function(scene, camera, intersectionPoint, normal, options)&#xD;&#xA;    {&#xD;&#xA;      var prob = 0.5;&#xD;&#xA;      var oneOverProb = 1/prob;&#xD;&#xA;      if(Math.random() &lt; prob) return new Vector(0,0,0);&#xD;&#xA;&#xD;&#xA;      var diffuse = new Vector(0, 0, 0);&#xD;&#xA;      var specular = new Vector(0, 0, 0);&#xD;&#xA;&#xD;&#xA;      if(options.MC_SAMPLES &gt; 0)// &amp;&amp; options.MC_DEPTH &gt; 0)&#xD;&#xA;      {&#xD;&#xA;        var basis = createCoordinationSystem(normal);&#xD;&#xA;        var sampleVector, sampleTransformed, mcRay;&#xD;&#xA;        for(var i = 0; i &lt; options.MC_SAMPLES; ++i)&#xD;&#xA;        {&#xD;&#xA;          sampleVector = getCosineWeightedSample(Math.random(), Math.random());&#xD;&#xA;          sampleTransformed = new Vector(sampleVector.x * basis.tangent.x + sampleVector.y * normal.x + sampleVector.z * basis.bitangent.x,&#xD;&#xA;                                     sampleVector.x * basis.tangent.y + sampleVector.y * normal.y + sampleVector.z * basis.bitangent.y,&#xD;&#xA;                                     sampleVector.x * basis.tangent.z + sampleVector.y * normal.z + sampleVector.z * basis.bitangent.z);&#xD;&#xA;          mcRay = new Ray(intersectionPoint.clone().add(sampleTransformed.clone().mul(0.000001)), sampleTransformed);&#xD;&#xA;&#xD;&#xA;          diffuse.add(RayTracer.traceRay(mcRay, scene, camera, {&#xD;&#xA;            MC_DEPTH: options.MC_DEPTH - 1,&#xD;&#xA;            MC_SAMPLES: options.MC_SAMPLES,&#xD;&#xA;            AREA_LIGHT_SAMPLES: options.AREA_LIGHT_SAMPLES&#xD;&#xA;          }));&#xD;&#xA;        }&#xD;&#xA;        diffuse.mul(1 / options.MC_SAMPLES);&#xD;&#xA;      }&#xD;&#xA;      return Vector.add(diffuse, specular).mul(oneOverProb);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RayTracer.traceRay = function(ray, scene, camera, options)&#xD;&#xA;    {&#xD;&#xA;      var color = new Vector(0, 0, 0);&#xD;&#xA;      //Depth test - finding closest object&#xD;&#xA;      var minT = 1e12, currentT;&#xD;&#xA;      var object = null;&#xD;&#xA;      var objectI;&#xD;&#xA;      for(var i = 0; i &lt; scene.objects.length; ++i)&#xD;&#xA;      {&#xD;&#xA;        currentT = scene.objects[i].intersects(ray);&#xD;&#xA;        if(currentT &gt; 0 &amp;&amp; currentT &lt; minT)&#xD;&#xA;        {&#xD;&#xA;          objectI = i;&#xD;&#xA;          minT = currentT;&#xD;&#xA;          object = scene.objects[i];&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      var emissiveObjects = [];&#xD;&#xA;      for(var i = 0; i &lt; scene.objects.length; ++i)&#xD;&#xA;      {&#xD;&#xA;        if(i == objectI) continue;&#xD;&#xA;        else if(scene.objects[i].isFinite &amp;&amp; scene.objects[i].material.emittance.lengthSq() &gt; 0.3)&#xD;&#xA;          emissiveObjects.push(scene.objects[i]);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      if(object == null) return new Vector(0, 0, 0);&#xD;&#xA;&#xD;&#xA;      var indirectLighting = new Vector(0, 0, 0);&#xD;&#xA;      var directLighting = new Vector(0, 0, 0);&#xD;&#xA;&#xD;&#xA;      var intersectionPoint = ray.getPoint(minT);&#xD;&#xA;      var normal = object.getNormalAt(intersectionPoint);&#xD;&#xA;      var toEye = camera.position.clone().sub(intersectionPoint).normalize();&#xD;&#xA;      var albedo = object.material.color.clone().mul(object.material.diffuseFactor);&#xD;&#xA;&#xD;&#xA;      //Direct illumination&#xD;&#xA;      for(var n = 0; n &lt; scene.lights.length; ++n)&#xD;&#xA;      {&#xD;&#xA;        //Searching for objects occluding light&#xD;&#xA;        var shadowRay = scene.lights[n].getShadowRay(intersectionPoint);&#xD;&#xA;        var inShadow = RayTracer.visabilityTest(shadowRay, scene.objects,&#xD;&#xA;      scene.lights[n].occlusionTestLimit(shadowRay)).occlusion;&#xD;&#xA;&#xD;&#xA;        if(!inShadow)&#xD;&#xA;        {&#xD;&#xA;          var lighting = scene.lights[n].getLightingInfo(intersectionPoint, normal, toEye);&#xD;&#xA;&#xD;&#xA;          directLighting.add(scene.lights[n].color.clone().mul(&#xD;&#xA;        lighting.diffuse * lighting.attenuation * scene.lights[n].intensity / Math.PI))&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      color.add(Vector.componetesMul(object.material.color, scene.ambient));&#xD;&#xA;&#xD;&#xA;      directLighting.add(RayTracer.sampleAreaLights(scene, emissiveObjects, intersectionPoint, normal, options.AREA_LIGHT_SAMPLES));&#xD;&#xA;      indirectLighting = RayTracer.indirectLighting(scene, camera, intersectionPoint, normal, options);&#xD;&#xA;&#xD;&#xA;      color.add(object.material.emittance.clone().clamp(0, 1));&#xD;&#xA;      color.add(Vector.componetesMul(directLighting.add(indirectLighting), albedo));&#xD;&#xA;&#xD;&#xA;      return color&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;The problem is that when I remove recursion depth test and add russian roulette to my indirect illumination function I get &quot;Maximum call stack size exceeded&quot; error. Same problem is when I implement roulette in _traceRay_ function. But when I use only one Monte Carlo sample, everything works fine.&#xD;&#xA;&#xD;&#xA;My russian roulette algorithm works as follows: at the beginning of a function, I am checking if a pseudo-random number is less then some constant threshold. If so, I am returning black color. In other case, function does what it would do without roulette, but the returned value is divided by the threshold.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, the question is: how do I implement Russian Roulette properly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13352" PostHistoryTypeId="2" PostId="5043" RevisionGUID="2ebc7c27-e189-4e7e-ab35-29caf55b8025" CreationDate="2017-04-30T11:09:43.513" UserId="231" Text="# Forking defeats Russian Roulette&#xD;&#xA;&#xD;&#xA;A key difference between path tracing and ray tracing is that unlike ray tracing, which can have a branching tree of rays splitting at each intersection, path tracing follows a single path with no recursive branching. &#xD;&#xA;&#xD;&#xA;Russian Roulette requires that only one recursive function call be made each time through the function. However, the code currently branches at each function call, so each call triggers several more calls. This prevents the roulette process from killing the recursion. New recursive function calls are being introduced faster than they can be killed off. The problem is similar to a [fork bomb], growing exponentially, so that the killing cannot keep up.&#xD;&#xA;&#xD;&#xA;The clue that led me to look for this problem was that you said that it works fine when the number of Monte Carlo samples is set to 1. In this case the function is only called once each time, so the recursion can only maintain the same number of rays, not introduce new ones. So there is no forking and when the recursion is killed that is the end of it.&#xD;&#xA;&#xD;&#xA;If you want more than one Monte Carlo sample per pixel, you will need to move that loop out of the recursive function so that the number of samples does not grow.&#xD;&#xA;&#xD;&#xA;# Pseudocode example&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    function RECURSIVE_FUNCTION()&#xD;&#xA;    {&#xD;&#xA;        RECURSIVE_FUNCTION()&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*This sends 1 ray that bounces around the scene but does not fork.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    function RECURSIVE_FUNCTION()&#xD;&#xA;    {&#xD;&#xA;        for(var i = 0; i &lt; 10; ++i)&#xD;&#xA;        {&#xD;&#xA;            RECURSIVE_FUNCTION()&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*This sends 10 rays that each spawn 10 new rays, giving 100 rays, then 1000, then 10000...*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If you want 10 samples per pixel, simply call the first function 10 times. Currently the code uses the second function, which causes far more than 10 samples per pixel, exploding to arbitrarily large numbers of rays until the stack overflows.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [fork bomb]: https://en.wikipedia.org/wiki/Fork_bomb" ContentLicense="CC BY-SA 3.0" />
  <row Id="13354" PostHistoryTypeId="5" PostId="4795" RevisionGUID="a0f72e94-5e46-4896-add6-d8ad174c1e97" CreationDate="2017-04-30T11:21:30.250" UserId="231" Comment="Typos" Text="Since you have a limited set of tools you are not actually doing a classical fitting. What you have is a discrete problem. And since you are looking for a somewhat easily drawn fit, no more than twice segmented for example.&#xD;&#xA;&#xD;&#xA;One way to approach this is to find all the points that match your curvature requirements. Then find the point x units away from point on both ends for all of these and see how well it matches. If the curvature match at the endpoint is too much off then this isn't a good candidate. If you don't find a good candidate split the problem into two. Once you have found a goodish candidate slide the result to see if relaxing the thing makes the error more symmetric.&#xD;&#xA;&#xD;&#xA;Some things to note. Since your french curve is accelerating from one end to another you need to split beziers and b-splines at each span where the curve changes direction. Also once you've found good endpoints be sure to check that the halfway isn't too much off.&#xD;&#xA;&#xD;&#xA;Now if you want to do a classical fitting like approach then you need to parametrize the sliding and scale of your curve. This is not likely useful since you in fact can not scale your rules at whim.&#xD;&#xA;&#xD;&#xA;Or then you could just get a spline, you know one of those things that were used before computers and stuff, and write instructions on how to set up the spline." ContentLicense="CC BY-SA 3.0" />
  <row Id="13355" PostHistoryTypeId="5" PostId="4760" RevisionGUID="da5fa361-f500-4742-9e12-c1509eaf7277" CreationDate="2017-04-30T11:27:56.647" UserId="231" Comment="Remove &quot;Thanks&quot;" Text="I have drawn a cylinder and an icosahedron using OpenGL.&#xD;&#xA;&#xD;&#xA;Now, I need to use the icosahedron and the open cylinder to build a structure motivated by crystal lattices, where I use an icosahedron for each atom and a cylinder to connect each 2 icosahedrons. &#xD;&#xA;&#xD;&#xA;I would have to use 12 icosahedrons for atoms and about 20 cylinders for the lines connecting the atoms, as I need to place them all to form the shape of an icosahedron itself.&#xD;&#xA;&#xD;&#xA;Is there anybody that could give me any ideas regarding how to go about this? I can arrange 12 icosahedrons to simulate the 12 vertices of an icosahedron, but I'm not sure how to place all of the cylinders around properly." ContentLicense="CC BY-SA 3.0" />
  <row Id="13356" PostHistoryTypeId="5" PostId="5024" RevisionGUID="04a409be-5a84-4fe5-9ba9-c741537d7cd4" CreationDate="2017-04-30T11:34:28.597" UserId="231" Comment="Remove thank you" Text="I am working on a project which plots points over a checkerboard (representing seats for people).  I would like each pixel in the image to represent each integer matrix entry.  After updating my Octave from $3.8$ to $4.2$, any image takes up $\frac 14$ of the actual plot window, as seen here:&#xD;&#xA;&#xD;&#xA;![Image][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MhMTv.png&#xD;&#xA;&#xD;&#xA;The simple code for this is as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clear&#xD;&#xA;    hold off&#xD;&#xA;&#xD;&#xA;    A = [1,2;3,4];&#xD;&#xA;&#xD;&#xA;    image(A)&#xD;&#xA;&#xD;&#xA;    axis xy %orients to bottom left&#xD;&#xA;&#xD;&#xA;Does anyone know how to get the image to take up the entire $2\times 2$ window, such that each pixel is the size of current image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13361" PostHistoryTypeId="5" PostId="5043" RevisionGUID="257f4b31-d57b-4381-8e6f-a650018340ad" CreationDate="2017-04-30T21:35:32.853" UserId="231" Comment="Disclaimer as the real code involves 2 functions in the recursion" Text="# Forking defeats Russian Roulette&#xD;&#xA;&#xD;&#xA;A key difference between path tracing and ray tracing is that unlike ray tracing, which can have a branching tree of rays splitting at each intersection, path tracing follows a single path with no recursive branching. &#xD;&#xA;&#xD;&#xA;Russian Roulette requires that only one recursive function call be made each time through the function. However, the code currently branches at each function call, so each call triggers several more calls. This prevents the roulette process from killing the recursion. New recursive function calls are being introduced faster than they can be killed off. The problem is similar to a [fork bomb], growing exponentially, so that the killing cannot keep up.&#xD;&#xA;&#xD;&#xA;The clue that led me to look for this problem was that you said that it works fine when the number of Monte Carlo samples is set to 1. In this case the function is only called once each time, so the recursion can only maintain the same number of rays, not introduce new ones. So there is no forking and when the recursion is killed that is the end of it.&#xD;&#xA;&#xD;&#xA;If you want more than one Monte Carlo sample per pixel, you will need to move that loop out of the recursive function so that the number of samples does not grow.&#xD;&#xA;&#xD;&#xA;# Pseudocode examples&#xD;&#xA;&#xD;&#xA;### Approach 1&#xD;&#xA;&#xD;&#xA;    function RECURSIVE_FUNCTION()&#xD;&#xA;    {&#xD;&#xA;        RECURSIVE_FUNCTION()&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*This sends 1 ray that bounces around the scene but does not fork.*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;### Approach 2&#xD;&#xA;&#xD;&#xA;    function RECURSIVE_FUNCTION()&#xD;&#xA;    {&#xD;&#xA;        for(var i = 0; i &lt; 10; ++i)&#xD;&#xA;        {&#xD;&#xA;            RECURSIVE_FUNCTION()&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*This sends 10 rays that each spawn 10 new rays, giving 100 rays, then 1000, then 10000...*&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If you want 10 samples per pixel, use the function from approach 1, and call it 10 times. Currently the code uses approach 2, which causes far more than 10 samples per pixel, exploding to arbitrarily large numbers of rays until the stack overflows.&#xD;&#xA;&#xD;&#xA;*Note that I've simplified the recursive calls in the pseudocode for the sake of explanation, but the same problem presents itself in the real code:* `traceRay` *calls* `indirectLighting` *once, then* `indirectLighting` *calls* `traceRay` *multiple times depending on* `MC_SAMPLES`*, then each of those calls to* `traceRay` *calls* `indirectLighting` *again. Each time through this cycle there are* `MC_SAMPLES` *times as many calls as the previous time, and Russian Roulette cannot cull enough of these calls to prevent runaway growth.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [fork bomb]: https://en.wikipedia.org/wiki/Fork_bomb" ContentLicense="CC BY-SA 3.0" />
  <row Id="13362" PostHistoryTypeId="50" PostId="4635" RevisionGUID="99b8aeb6-1709-4a9c-a4e5-5a707cada8cb" CreationDate="2017-05-01T06:54:44.677" UserId="-1" />
  <row Id="13364" PostHistoryTypeId="5" PostId="5039" RevisionGUID="36ed67e0-f7fa-4d53-beaf-bf14022f5b41" CreationDate="2017-05-01T17:58:27.150" UserId="6534" Comment="deleted 322 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, most of which has been incredibly enlightening, and I have seen their sample_wi function, but it performs this crazy way too, generating seemingly wild vectors when close to normal incidence.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what." ContentLicense="CC BY-SA 3.0" />
  <row Id="13365" PostHistoryTypeId="5" PostId="5039" RevisionGUID="73835e27-c33e-46cb-a3dc-58ffe8a5f29d" CreationDate="2017-05-01T18:18:07.393" UserId="6534" Comment="added 481 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, most of which has been incredibly enlightening, and I have seen their sample_wi function, but it performs this crazy way too, generating seemingly wild vectors when close to normal incidence.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what.&#xD;&#xA;&#xD;&#xA;Here is a visualization of only the half vector normals.  They have been put into a range of [0,1] for viewing in the RGB spectrum.  I have also boosted the contrast of the image to make the error more easily visible.  You can clearly see that instead of randomly orienting themselves about the surface normal, they are instead correlating themselves radially about the camera eye-vector.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M6975.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13366" PostHistoryTypeId="4" PostId="5039" RevisionGUID="73835e27-c33e-46cb-a3dc-58ffe8a5f29d" CreationDate="2017-05-01T18:18:07.393" UserId="6534" Comment="added 481 characters in body" Text="Troubleshoot half vector sampling from a distribution (cook-torrence, trowbridge-reitz, etc)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13367" PostHistoryTypeId="2" PostId="5045" RevisionGUID="90bf1a5a-61a3-453a-afff-43392bb08889" CreationDate="2017-05-01T19:19:37.580" UserId="5717" Text="The general idea for sampling half vector based distributions is that you generate $H$ and then compute $w_i$ by reflecting $w_o$ about $H$. This is so $H$ will be the half vector of your $w_i$ and $w_o$ pair. It is standard reflection:&#xD;&#xA;$$w_i = -w_o + 2(w_o\cdot H)H $$&#xD;&#xA;&#xD;&#xA;How you generate $H$ depends on the specific distribution. Generally, it is done in polar coordinates, with the angle from your distribution's center being picked using some specific function. Then the azimuth will be a uniform distribution, unless your distribution is anisotropic, in which case it gets more complicated.&#xD;&#xA;&#xD;&#xA;For example, with Cook-Torrance, it goes something like:&#xD;&#xA;$$\theta = m \sqrt{ - \log \xi_1 }$$&#xD;&#xA;$$\phi = \xi_2 \pi$$&#xD;&#xA;&#xD;&#xA;If you need help troubleshooting specific code, you should post that code as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="13368" PostHistoryTypeId="5" PostId="5045" RevisionGUID="03785a56-75a7-4314-9a1b-232c464d98e4" CreationDate="2017-05-01T19:35:06.587" UserId="5717" Comment="Removed nonsense matrix notation." Text="The general idea for sampling half vector based distributions is that you generate $H$ and then compute $w_i$ by reflecting $w_o$ about $H$. This is so $H$ will be the half vector of your $w_i$ and $w_o$ pair. It is standard reflection:&#xD;&#xA;$$w_i = -w_o + 2(w_o\cdot H)H $$&#xD;&#xA;&#xD;&#xA;How you generate $H$ depends on the specific distribution. Generally, it is done in polar coordinates, with the angle from your distribution's center being picked using some specific function. Then the azimuth will be a uniform distribution, unless your distribution is anisotropic, in which case it gets more complicated.&#xD;&#xA;&#xD;&#xA;For example, with Cook-Torrance, it goes something like:&#xD;&#xA;$$\tan \theta = m \sqrt{ - \log \xi_1 }$$&#xD;&#xA;$$\phi = \xi_2 2\pi$$&#xD;&#xA;&#xD;&#xA;Then, given an orthonormal basis made of vectors $N$, $a$, $b$:&#xD;&#xA;&#xD;&#xA;$$H = a\sin\theta\cos\phi + b\sin\theta\sin\phi + N\cos\theta$$&#xD;&#xA;If you need help troubleshooting specific code, you should post that code as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="13369" PostHistoryTypeId="5" PostId="5039" RevisionGUID="221664fd-c24c-4291-995c-296acfebf38c" CreationDate="2017-05-01T20:25:10.447" UserId="6534" Comment="added 327 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, most of which has been incredibly enlightening, and I have seen their sample_wi function, but it performs this crazy way too, generating seemingly wild vectors when close to normal incidence.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what.&#xD;&#xA;&#xD;&#xA;Here is a visualization of only the half vector normals.  They have been put into a range of [0,1] for viewing in the RGB spectrum.  I have also boosted the contrast of the image to make the error more easily visible.  You can clearly see that instead of randomly orienting themselves about the surface normal, they are instead correlating themselves radially about the camera eye-vector.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M6975.jpg&#xD;&#xA;&#xD;&#xA;UPDATE:  &#xD;&#xA;here is a webgl &quot;proof&quot; i put together to isolate and illustrate my problem.  What should happen is the color should be fairly blended together, interpolated rather nicely.  Instead I get this obvious hard shift in the distribution throughout the 4 quadrants: http://rdtests.ml3ds-test.com/microfacettesting.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="13370" PostHistoryTypeId="5" PostId="5039" RevisionGUID="73ee5d29-129c-4253-87e7-80b1e3f38651" CreationDate="2017-05-01T20:30:48.987" UserId="6534" Comment="added 102 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, most of which has been incredibly enlightening, and I have seen their sample_wi function, but it performs this crazy way too, generating seemingly wild vectors when close to normal incidence.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what.&#xD;&#xA;&#xD;&#xA;Here is a visualization of only the half vector normals.  They have been put into a range of [0,1] for viewing in the RGB spectrum.  I have also boosted the contrast of the image to make the error more easily visible.  You can clearly see that instead of randomly orienting themselves about the surface normal, they are instead correlating themselves radially about the camera eye-vector.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M6975.jpg&#xD;&#xA;&#xD;&#xA;UPDATE:  &#xD;&#xA;here is a webgl &quot;proof&quot; i put together to isolate and illustrate my problem.  What should happen is the color should be fairly blended together, interpolated rather nicely.  Instead I get this obvious hard shift in the distribution throughout the 4 quadrants: http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;The &quot;good&quot; part will be located in the &quot;main&quot; function inside the final script block in that page." ContentLicense="CC BY-SA 3.0" />
  <row Id="13371" PostHistoryTypeId="5" PostId="5039" RevisionGUID="c3e1b2a7-fda7-4eb9-9363-7cae08695992" CreationDate="2017-05-01T20:44:53.903" UserId="6534" Comment="deleted 4 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, all of which has been incredibly enlightening, and I have seen their sample_wi function, i even went so far as to directly copy and translate it to webgl for troubleshooting my functions.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what.&#xD;&#xA;&#xD;&#xA;Here is a visualization of only the half vector normals.  They have been put into a range of [0,1] for viewing in the RGB spectrum.  I have also boosted the contrast of the image to make the error more easily visible.  You can clearly see that instead of randomly orienting themselves about the surface normal, they are instead correlating themselves radially about the camera eye-vector.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M6975.jpg&#xD;&#xA;&#xD;&#xA;UPDATE:  &#xD;&#xA;here is a webgl &quot;proof&quot; i put together to isolate and illustrate my problem.  What should happen is the color should be fairly blended together, interpolated rather nicely.  Instead I get this obvious hard shift in the distribution throughout the 4 quadrants: http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;The functions referenced by main function here can all be viewed directly in the source code of the page I linked to: &#xD;&#xA;&#xD;&#xA;            vec3 finalColor = vec3(0.);&#xD;&#xA;			&#xD;&#xA;			// create a changing &quot;wo&quot; vector across screen space (simulates perspective ray change)&#xD;&#xA;			vec2 screenUv = gl_FragCoord.xy / u_resolution;&#xD;&#xA;			// fire rays into positive z (forward) space from &quot;camera&quot;s&#xD;&#xA;			float z = 1.;&#xD;&#xA;&#xD;&#xA;			vec3 rd = normalize(vec3(screenUv, z));&#xD;&#xA;			&#xD;&#xA;			// remap 0,1 to -1,1&#xD;&#xA;			vec3 wo = (rd * 2.) - 1.;&#xD;&#xA;			// wo is outward facing&#xD;&#xA;			wo *= -wo;&#xD;&#xA;&#xD;&#xA;			// convert wo to spherical coordinates&#xD;&#xA;			vec3 Nt, Nb;&#xD;&#xA;			// simulate hitting an infinite plane, facing us like a wall&#xD;&#xA;			vec3 normal = vec3(0., 0.,-1.);&#xD;&#xA;			CoordinateSystem(wo, Nt, Nb);&#xD;&#xA;&#xD;&#xA;			// put wo into the shading space coordinate system of the &quot;wall&quot; normal&#xD;&#xA;			vec3 shadingWo = WorldToShading(wo, Nt, Nb, normal);&#xD;&#xA;&#xD;&#xA;			// sample half vector distribution from trowbridge-reitz&#xD;&#xA;			// make random input a constant to allow error to be more clearly seen&#xD;&#xA;			vec3 wh = Dist_TR_Sample_wh(wo, vec2(.2,.1), .5, .5);&#xD;&#xA;			&#xD;&#xA;			// Reflect wo about the half vector normal&#xD;&#xA;			vec3 wi = Reflect(wo, wh);&#xD;&#xA;&#xD;&#xA;			// put wi back into cartesian coordinate system&#xD;&#xA;			vec3 wiWorld = ShadingToWorld(wi, Nt, Nb, normal);&#xD;&#xA;&#xD;&#xA;			// now remap wi to a viewable color: 0,1&#xD;&#xA;			finalColor = normalize((wiWorld + 1.) / 2.);&#xD;&#xA;&#xD;&#xA;			gl_FragColor = vec4(finalColor, 1.);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13372" PostHistoryTypeId="2" PostId="5046" RevisionGUID="9eff4286-1152-4114-b5b2-23b1e9d9d173" CreationDate="2017-05-01T21:07:20.933" UserId="6546" Text="I've been doing OpenGL tutorials using learnopengl.com. Currently I'm reading about Stencil Buffers and in his example he uses a Stencil Buffer to draw an outline around an object. I've also read that it can be used to create shadows and refelctions. My question is, what are other practical uses for a Stencil Buffer and why were they invented in the first place?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13373" PostHistoryTypeId="1" PostId="5046" RevisionGUID="9eff4286-1152-4114-b5b2-23b1e9d9d173" CreationDate="2017-05-01T21:07:20.933" UserId="6546" Text="Uses for Stencil Buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="13374" PostHistoryTypeId="3" PostId="5046" RevisionGUID="9eff4286-1152-4114-b5b2-23b1e9d9d173" CreationDate="2017-05-01T21:07:20.933" UserId="6546" Text="|opengl|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13375" PostHistoryTypeId="5" PostId="5039" RevisionGUID="1067b230-4b17-4c35-9135-b7a7e123b929" CreationDate="2017-05-01T21:12:08.657" UserId="6534" Comment="added 7 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, all of which has been incredibly enlightening, and I have seen their sample_wi function, i even went so far as to directly copy and translate it to webgl for troubleshooting my functions.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what.&#xD;&#xA;&#xD;&#xA;Here is a visualization of only the half vector normals.  They have been put into a range of [0,1] for viewing in the RGB spectrum.  I have also boosted the contrast of the image to make the error more easily visible.  You can clearly see that instead of randomly orienting themselves about the surface normal, they are instead correlating themselves radially about the camera eye-vector.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M6975.jpg&#xD;&#xA;&#xD;&#xA;UPDATE:  &#xD;&#xA;here is a webgl &quot;proof&quot; i put together to isolate and illustrate my problem.  What should happen is the color should be fairly blended together, interpolated rather nicely.  Instead I get this obvious hard shift in the distribution throughout the 4 quadrants: http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;The functions referenced by main function here can all be viewed directly in the source code of the page I linked to: &#xD;&#xA;&#xD;&#xA;            vec3 finalColor = vec3(0.);&#xD;&#xA;			&#xD;&#xA;			// create a changing &quot;wo&quot; vector across screen space (simulates perspective ray change)&#xD;&#xA;			vec2 screenUv = gl_FragCoord.xy / u_resolution;&#xD;&#xA;			// fire rays into positive z (forward) space from &quot;camera&quot;s&#xD;&#xA;			float z = 1.;&#xD;&#xA;&#xD;&#xA;			vec3 rd = normalize(vec3(screenUv, z));&#xD;&#xA;			&#xD;&#xA;			// remap 0,1 to -1,1&#xD;&#xA;			vec3 wo = (rd * 2.) - 1.;&#xD;&#xA;			// wo is outward facing&#xD;&#xA;			wo *= -wo;&#xD;&#xA;&#xD;&#xA;			// convert wo to spherical coordinates&#xD;&#xA;			vec3 Nt, Nb;&#xD;&#xA;			// simulate hitting an infinite plane, facing us like a wall&#xD;&#xA;			vec3 normal = vec3(0., 0.,-1.);&#xD;&#xA;			CoordinateSystem(wo, Nt, Nb);&#xD;&#xA;&#xD;&#xA;			// put wo into the shading space coordinate system of the &quot;wall&quot; normal&#xD;&#xA;			vec3 shadingWo = WorldToShading(wo, Nt, Nb, normal);&#xD;&#xA;&#xD;&#xA;			// sample half vector distribution from trowbridge-reitz&#xD;&#xA;			// make random input a constant to allow error to be more clearly seen&#xD;&#xA;			vec3 wh = Dist_TR_Sample_wh(shadingWo, vec2(.2,.1), .5, .5);&#xD;&#xA;			&#xD;&#xA;			// Reflect wo about the half vector normal&#xD;&#xA;			vec3 wi = Reflect(shadingWo, wh);&#xD;&#xA;&#xD;&#xA;			// put wi back into cartesian coordinate system&#xD;&#xA;			vec3 wiWorld = ShadingToWorld(wi, Nt, Nb, normal);&#xD;&#xA;&#xD;&#xA;			// now remap wi to a viewable color: 0,1&#xD;&#xA;			finalColor = normalize((wiWorld + 1.) / 2.);&#xD;&#xA;&#xD;&#xA;			gl_FragColor = vec4(finalColor, 1.);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13376" PostHistoryTypeId="5" PostId="5046" RevisionGUID="18ef0f41-696f-46fb-8720-53ba544b66b8" CreationDate="2017-05-01T21:17:06.393" UserId="6546" Comment="added 40 characters in body" Text="I've been doing OpenGL tutorials using [LearnOpenGL][1]&#xD;&#xA;. Currently I'm reading about Stencil Buffers and in his example he uses a Stencil Buffer to draw an outline around an object. I've also read that it can be used to create shadows and refelctions. My question is, what are other practical uses for a Stencil Buffer and why were they invented in the first place?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com" ContentLicense="CC BY-SA 3.0" />
  <row Id="13379" PostHistoryTypeId="5" PostId="5039" RevisionGUID="47e22f82-1c40-498a-83da-5d175e0a9eeb" CreationDate="2017-05-01T22:15:03.717" UserId="6534" Comment="added 4 characters in body" Text="I am learning ray tracing and the mathematics behind it.  I have a working monte-carlo raytracer I am experimenting on.  I have gotten past pure diffuse BRDFS, area lights, acceleration structures, etc, and now I'm working on properly sampling the next ray direction from an anisotropic distribution.  I believe I have interpreted the D,G,F factors correctly, and have working tests that verify those function's outputs.  &#xD;&#xA;&#xD;&#xA;I am having trouble with drawing a &quot;wi&quot; sample from the half vector distribution function.   The purpose of the function is to give you a randomized half vector in shading space based on the &quot;incoming&quot; wo ray, which is the eye ray, and a roughness parameter.  As I graph out the function outputs, it seems like the &#xD;&#xA;half-vector sampling function begins to rotate the spherical coordinates about the wrong axis (I know this makes no sense, but I'm just observing the graphed results).&#xD;&#xA;&#xD;&#xA;Knowing that situation, I was hoping some people could post some pointers to good academic articles, open source code examples, or other educational material that could help me investigate and educate myself on the behavior of functions that generate half-vectors from distributions.  I have found plenty of the original source papers from Cook-Torrence, etc that explain their algorithms, but I cannot find any that explain in plain language HOW to generate the half vector for the eye ray to reflect about.&#xD;&#xA;&#xD;&#xA;Note: I have also extensively explored PBRT and its source code, all of which has been incredibly enlightening, and I have seen their sample_wi function, i even went so far as to directly copy and translate it to webgl for troubleshooting my functions.  I know i must be doing or interpreting something wrong - I just can't find enough material out there to help me figure out what.&#xD;&#xA;&#xD;&#xA;Here is a visualization of only the half vector normals.  They have been put into a range of [0,1] for viewing in the RGB spectrum.  I have also boosted the contrast of the image to make the error more easily visible.  You can clearly see that instead of randomly orienting themselves about the surface normal, they are instead correlating themselves radially about the camera eye-vector.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M6975.jpg&#xD;&#xA;&#xD;&#xA;UPDATE:  &#xD;&#xA;here is a webgl &quot;proof&quot; i put together to isolate and illustrate my problem.  What should happen is the color should be fairly blended together, interpolated rather nicely.  Instead I get this obvious hard shift in the distribution throughout the 4 quadrants: http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;The functions referenced by main function here can all be viewed directly in the source code of the page I linked to: &#xD;&#xA;&#xD;&#xA;            vec3 finalColor = vec3(0.);&#xD;&#xA;			&#xD;&#xA;			// create a changing &quot;wo&quot; vector across screen space (simulates perspective ray change)&#xD;&#xA;			vec2 screenUv = gl_FragCoord.xy / u_resolution;&#xD;&#xA;			// fire rays into positive z (forward) space from &quot;camera&quot;s&#xD;&#xA;			float z = 1.;&#xD;&#xA;&#xD;&#xA;			vec3 rd = normalize(vec3(screenUv, z));&#xD;&#xA;			&#xD;&#xA;			// remap 0,1 to -1,1&#xD;&#xA;			vec3 wo = (rd * 2.) - 1.;&#xD;&#xA;			// wo is outward facing&#xD;&#xA;			wo *= -wo;&#xD;&#xA;&#xD;&#xA;			// convert wo to spherical coordinates&#xD;&#xA;			vec3 Nt, Nb;&#xD;&#xA;			// simulate hitting an infinite plane, facing us like a wall&#xD;&#xA;			vec3 normal = vec3(0., 0.,-1.);&#xD;&#xA;			CoordinateSystem(normal, Nt, Nb);&#xD;&#xA;&#xD;&#xA;			// put wo into the shading space coordinate system of the &quot;wall&quot; normal&#xD;&#xA;			vec3 shadingWo = WorldToShading(wo, Nt, Nb, normal);&#xD;&#xA;&#xD;&#xA;			// sample half vector distribution from trowbridge-reitz&#xD;&#xA;			// make random input a constant to allow error to be more clearly seen&#xD;&#xA;			vec3 wh = Dist_TR_Sample_wh(shadingWo, vec2(.2,.1), .5, .5);&#xD;&#xA;			&#xD;&#xA;			// Reflect wo about the half vector normal&#xD;&#xA;			vec3 wi = Reflect(shadingWo, wh);&#xD;&#xA;&#xD;&#xA;			// put wi back into cartesian coordinate system&#xD;&#xA;			vec3 wiWorld = ShadingToWorld(wi, Nt, Nb, normal);&#xD;&#xA;&#xD;&#xA;			// now remap wi to a viewable color: 0,1&#xD;&#xA;			finalColor = normalize((wiWorld + 1.) / 2.);&#xD;&#xA;&#xD;&#xA;			gl_FragColor = vec4(finalColor, 1.);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13380" PostHistoryTypeId="5" PostId="5046" RevisionGUID="0e4f7bb4-88ba-4b48-9730-81d3c58cf276" CreationDate="2017-05-01T22:25:36.097" UserId="48" Comment="typo" Text="I've been doing OpenGL tutorials using [LearnOpenGL][1]. Currently I'm reading about Stencil Buffers and in his example he uses a Stencil Buffer to draw an outline around an object. I've also read that it can be used to create shadows and reflections. My question is, what are other practical uses for a Stencil Buffer and why were they invented in the first place?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com" ContentLicense="CC BY-SA 3.0" />
  <row Id="13382" PostHistoryTypeId="5" PostId="5045" RevisionGUID="0464bcac-db6c-4e45-8151-fe0a3e593b30" CreationDate="2017-05-02T00:12:46.617" UserId="5717" Comment="minor precision" Text="The general idea for sampling half vector based distributions is that you generate $H$ and then compute $w_i$ by reflecting $w_o$ about $H$. This is so $H$ will be the half vector of your $w_i$ and $w_o$ pair. It is standard reflection:&#xD;&#xA;$$w_i = -w_o + 2(w_o\cdot H)H $$&#xD;&#xA;&#xD;&#xA;How you generate $H$ depends on the specific distribution. Generally, it is done in polar coordinates, with the angle from your distribution's center being picked using some specific function. Then the azimuth will be a uniform distribution, unless your distribution is anisotropic, in which case it gets more complicated.&#xD;&#xA;&#xD;&#xA;For example, with Cook-Torrance, it goes something like:&#xD;&#xA;$$\tan \theta = m \sqrt{ - \log \xi_1 }$$&#xD;&#xA;$$\phi = \xi_2 2\pi$$&#xD;&#xA;&#xD;&#xA;Then, given an orthonormal basis made of vectors $N$, $a$, $b$:&#xD;&#xA;&#xD;&#xA;$$H = a\sin\theta\cos\phi + b\sin\theta\sin\phi + N\cos\theta$$&#xD;&#xA;&#xD;&#xA;As for problems in your code, replacing this:&#xD;&#xA;&#xD;&#xA;    vec3 rd = normalize(vec3(screenUv, z));&#xD;&#xA;&#xD;&#xA;    // remap 0,1 to -1,1&#xD;&#xA;    vec3 wo = (rd * 2.) - 1.;&#xD;&#xA;    // wo is outward facing&#xD;&#xA;    wo *= -wo;&#xD;&#xA;&#xD;&#xA;with:&#xD;&#xA;&#xD;&#xA;    vec3 wo = normalize(vec3(screenUv*2.0-1.0, -z));&#xD;&#xA;&#xD;&#xA;Gives me a much nicer plot. Your remapping was incorrect as it was done on a vector which includes z and is no longer in 0,1 for x and y because of the normalization. This explains why the center was not in the center of the frame and the whole thing was leaning. Removing ` wo *= -wo;` (a transformation which makes no sense) and using `-z` instead fixes what I think you were calling the hard transition in the 4 quadrants. That was caused by squaring the components of the vector.&#xD;&#xA;&#xD;&#xA;The remaining glitch in the center appears to be numerical issues. Fixing that will require reworking the code to better handle some cases (likely where you have the `0.0008` constant for a sin and the `0.9999` for a cos)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13383" PostHistoryTypeId="5" PostId="4924" RevisionGUID="d8398674-7265-47a3-9cca-9cc592ee4993" CreationDate="2017-05-02T00:25:31.073" UserId="6546" Comment="Reworded and Capitalized Words" Text="I am new to the DX12 world and I am currently trying to tweak the nbody_gravity DX12 sample, but appending or calling another Compute Shader which is to add 2 buffers to produce an output in a different buffer. &#xD;&#xA;&#xD;&#xA;Right now, I have made a call to my ComputeBufferAddition shader and was wondering if I need a separate Compute PSO to do this, or can I reuse the one already present to call the NbodyGravity.hlsl&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13384" PostHistoryTypeId="24" PostId="4924" RevisionGUID="d8398674-7265-47a3-9cca-9cc592ee4993" CreationDate="2017-05-02T00:25:31.073" Comment="Proposed by 6546 approved by 231 edit id of 231" ContentLicense="CC BY-SA 3.0" />
  <row Id="13385" PostHistoryTypeId="6" PostId="56" RevisionGUID="5304d9bd-296b-4332-a513-c05da4b666e3" CreationDate="2017-05-02T00:25:41.647" UserId="6546" Comment="Added relevant tag" Text="|opengl|glsl|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13386" PostHistoryTypeId="24" PostId="56" RevisionGUID="5304d9bd-296b-4332-a513-c05da4b666e3" CreationDate="2017-05-02T00:25:41.647" Comment="Proposed by 6546 approved by 48, 231 edit id of 228" ContentLicense="CC BY-SA 3.0" />
  <row Id="13387" PostHistoryTypeId="5" PostId="1640" RevisionGUID="659c90fe-51d0-437a-a4e1-4afeccf64605" CreationDate="2017-05-02T00:25:59.583" UserId="6546" Comment="Capitalized Pronouns and Fixed Spelling Error" Text="I've written an implementation of the sphere tracing algorithm in OpenGL 4+.&#xD;&#xA;As an experiment/toy project, I'm re-implementing it using the OpenGL 4.3 compute shader, but I'm having trouble with the whole local/global invocation ID thing.&#xD;&#xA;The basic idea is to use the compute shader to calculate the image and output it in a texture, then use a trivial program to copy it onto the framebuffer.&#xD;&#xA;&#xD;&#xA;This is the compute shader I'm using:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (binding = 0, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA; &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec2 coord = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;        imageStore(output_image, coord, vec4(0.0, 0.0, 1.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is how I initialize the texture:&#xD;&#xA;&#xD;&#xA;    GLuint offscreen_texture;&#xD;&#xA;  	glGenTextures(1, &amp;offscreen_texture);&#xD;&#xA;&#xD;&#xA; 	glActiveTexture(GL_TEXTURE0);&#xD;&#xA; 	glBindTexture(GL_TEXTURE_2D, offscreen_texture);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, nullptr);&#xD;&#xA;	glBindImageTexture(0, offscreen_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;And these are the trivial vertex shader I'm using:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        const vec4 verts[4] = vec4[4](vec4(-1.0, -1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4( 1.0, -1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4(-1.0,  1.0, 0.5, 1.0),&#xD;&#xA;                                      vec4( 1.0,  1.0, 0.5, 1.0));&#xD;&#xA;&#xD;&#xA;        gl_Position = verts[gl_VertexID];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And fragment:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 color_out;&#xD;&#xA;    layout(binding = 0) uniform sampler2D source_image;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    color_out = texture(source_image, gl_FragCoord.xy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is the render code:&#xD;&#xA;&#xD;&#xA;    compute_program.use();&#xD;&#xA;    glDispatchCompute(WINDOW_WIDTH / 16, WINDOW_HEIGHT / 16, 1);&#xD;&#xA;	glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;	copy_program.use();&#xD;&#xA;	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;&#xD;&#xA;Up to this point everything works correctly and I see my screen completely blue instead of the usual clear color.&#xD;&#xA;&#xD;&#xA;Things start to break down when I try to use the Invocation ID to generate actual data (like the rays from the camera).&#xD;&#xA;I tried to switch to a compute shader like:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;&#xD;&#xA;    layout (binding = 0, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec2 coord = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;        imageStore(output_image, coord, vec4(0.0, 0.0, coord.x / 1280.0, 1.0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;which uses the global ID to generate the blue tint of the pixel.&#xD;&#xA;As I understand from the OpenGL Suberbible book and the OpenGL wiki, I should be able to use the global ID as screen space coordinates (it's pretty easy to do the math using local IDs and work groups IDs and confirm that), much like gl_FragCoord, and this is confirmed by the previous trivial compute shader which paint every pixel.&#xD;&#xA;&#xD;&#xA;I would expect a sort of horizontal gradient going from black to blue as an output of this compute shader, but instead everything turns black.&#xD;&#xA;I've tried several combination of &quot;painting&quot; based on the local/global IDs of the threads, but I haven't got any luck no matter what.&#xD;&#xA;&#xD;&#xA;Did I misunderstand the way the whole threads ID work?&#xD;&#xA;What is the correct way to use them/map them to screen space coordinates like gl_FragCoord?&#xD;&#xA;&#xD;&#xA;EDIT: Just to add, I've tested this with both my integrated Intel HD 5100 and my discrete Nvidia 765M GPUs and the result is the same, so there is clearly something wrong on my side." ContentLicense="CC BY-SA 3.0" />
  <row Id="13388" PostHistoryTypeId="24" PostId="1640" RevisionGUID="659c90fe-51d0-437a-a4e1-4afeccf64605" CreationDate="2017-05-02T00:25:59.583" Comment="Proposed by 6546 approved by 48, 231 edit id of 229" ContentLicense="CC BY-SA 3.0" />
  <row Id="13389" PostHistoryTypeId="5" PostId="4722" RevisionGUID="e8dff8ba-af6d-47e4-9b59-2853b78e6869" CreationDate="2017-05-02T00:26:31.770" UserId="6546" Comment="Capitalized Words and Fixed Grammatical Errors" Text="After Z-Buffer Testing does the fragment shader run on the discarded fragments?&#xD;&#xA;Does the Z-Test happen after the fragment shader runs?&#xD;&#xA;&#xD;&#xA;Please, tell me the step by step events that occur in the Z-Test.&#xD;&#xA;&#xD;&#xA;Also what is early Z-Test and how to achieve it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13390" PostHistoryTypeId="4" PostId="4722" RevisionGUID="e8dff8ba-af6d-47e4-9b59-2853b78e6869" CreationDate="2017-05-02T00:26:31.770" UserId="6546" Comment="Capitalized Words and Fixed Grammatical Errors" Text="Z buffer working in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="13391" PostHistoryTypeId="24" PostId="4722" RevisionGUID="e8dff8ba-af6d-47e4-9b59-2853b78e6869" CreationDate="2017-05-02T00:26:31.770" Comment="Proposed by 6546 approved by 231 edit id of 232" ContentLicense="CC BY-SA 3.0" />
  <row Id="13392" PostHistoryTypeId="5" PostId="4709" RevisionGUID="b6fb56b5-8221-4f0b-abdc-fd0aa20a7259" CreationDate="2017-05-02T00:26:52.560" UserId="6546" Comment="Capitalized Pronouns" Text="I am currently making a Ray-tracer as a personal project. My lighting equation looks like this&#xD;&#xA;&#xD;&#xA;    Pixel_color[i] = 255 * (Ma*Ig*Ca + Md*I*Cd * diffuse  + Ms*I*Cs * glossy)&#xD;&#xA;    // M = material color (ambient, diffuse and specular)&#xD;&#xA;    // I = intensity of light (Ig is the global ambient intensity)&#xD;&#xA;    // C = color of the light (ambient , diffuse and specular)&#xD;&#xA;&#xD;&#xA;Here `diffuse` and `glossy` contains all the necessary dot products and the normalization factors ( PI for diffuse and n+8/8*PI for Blinn Phong). Also everything is in range 0-1. I've read from some books and it says to make sure that `&quot;Ks + Kd&quot; &lt;= 1` And now I am confused. &#xD;&#xA;&#xD;&#xA;1) What exactly is Ks and Kd? Is it just my surface diffuse color and specular color divided by 255 to make it in the range 0-1? Or is it the reflectance ratio that I have to multiply with my color? If it's something else then what should I set them to? For example if I have a color `rgb(66, 170, 244)` which is somewhat light blue. What should the Ks and Kd be for the above color?&#xD;&#xA;&#xD;&#xA;2) These books don't include the ambient component when talking about this conservation so should it be  Ka+Kd+Ks &lt;= 1? Again if that's the case what will Ka be?&#xD;&#xA;&#xD;&#xA;3) If I consider Ks = Ms and Kd = Md. It doesn't fit out. for example if I want a surface with the above color `rgb(66, 170, 244)` to be shiny and the specular highlight should be white. Then my Ms would be (255-66, 255-170, 255-244) which won't be white. Another way I could do is subtract the maximum from every component Ms(255-244, 255-244, 255-244). But this means the specular color would be very low. What if I wanted a very shiny surface?&#xD;&#xA;&#xD;&#xA;UPDATE:-&#xD;&#xA;&#xD;&#xA;So according to the book Computer Graphics Principles and Practice, Chapter 6 &quot;Fixed Function and Hierarchial Modeling in WPF&quot; &#xD;&#xA;&#xD;&#xA;    Cd Innate color of “diffuse layer” (Cd,R,Cd,G,Cd,B)&#xD;&#xA;    Cs Innate color of “specular layer” (Cs,R,Cs,G,Cs,B)&#xD;&#xA;    ka Efficiency of diffuse layer at reflecting ambient light (ka,R, ka,G, ka,B)&#xD;&#xA;    kd Efficiency of diffuse layer at reflecting light (kd,R, kd,G, kd,B)&#xD;&#xA;    ks Efficiency of specular layer at reflecting light (ks,R, ks,G, ks,B)&#xD;&#xA;&#xD;&#xA;After that it writes, &#xD;&#xA;&#xD;&#xA;&gt; Note that for solid-color materials, the distinction between the two terms Cd&#xD;&#xA;and kd is unnecessary, as far as the math is concerned; you can think of them as&#xD;&#xA;a single term. That is, you can fix kd,R at 1. 0 and use Cd,R to achieve any effect,&#xD;&#xA;and conversely you could fix Cd,R and specify only kd,R. However, the distinction&#xD;&#xA;between the two terms is meaningful when the innate color Cd is being provided&#xD;&#xA;via texture mapping; in that case, there is a need for a kd,R factor affecting the&#xD;&#xA;reflection of the varying color Cd specified by the texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After that in Chapter 14.9 it removes Kd/Ks and Cd/Cs and replaces both with K_L and K_G&#xD;&#xA;&#xD;&#xA;&gt; These k parameters are no longer potentially ambiguous RGB triples (each 0 . . . 1), but constants representing the net probability over all directions of&#xD;&#xA;that term contributing to scattering.&#xD;&#xA;&#xD;&#xA;Which led me to think they are just a single constant like &quot;0.5&quot; However in the next example they are telling the same thing to ensure that K_L + K_G &lt;= 1 across all channel which implies that k_L and k_G are infact RGB triples." ContentLicense="CC BY-SA 3.0" />
  <row Id="13393" PostHistoryTypeId="4" PostId="4709" RevisionGUID="b6fb56b5-8221-4f0b-abdc-fd0aa20a7259" CreationDate="2017-05-02T00:26:52.560" UserId="6546" Comment="Capitalized Pronouns" Text="Energy Conservation in Lighting Equation" ContentLicense="CC BY-SA 3.0" />
  <row Id="13394" PostHistoryTypeId="24" PostId="4709" RevisionGUID="b6fb56b5-8221-4f0b-abdc-fd0aa20a7259" CreationDate="2017-05-02T00:26:52.560" Comment="Proposed by 6546 approved by 231 edit id of 233" ContentLicense="CC BY-SA 3.0" />
  <row Id="13400" PostHistoryTypeId="5" PostId="3700" RevisionGUID="ccc6668b-63b4-4b25-9041-0025da389cc0" CreationDate="2017-05-02T00:52:55.220" UserId="6546" Comment="Capitalized Pronouns and Fixed Grammatical Errors" Text="So I was reading [this][1], I sort of got the reason why there are a lot more games on Microsoft windows than on any other OS. The main issue presented was that Direct3D is preferred over OpenGL. &#xD;&#xA;&#xD;&#xA;What I don't understand is why would any developer sacrifice compatibility? That is simply a financial loss to the company. I understand that OpenGL is kind of a mess, but that should hardly be a issue for experts. Even if it is, I think that people would go a extra mile than to incur a financial loss. &#xD;&#xA;&#xD;&#xA;Also if I'm not wrong then many cross platform applications use both Direct3D and OpenGL. I think they switch between the APIs.     &#xD;&#xA;&#xD;&#xA;This is weird as they can just use OpenGL, why even care about Direct3D? &#xD;&#xA;&#xD;&#xA;So the question is, are there any technical issues with OpenGL or is there any support that Direct3D provides that OpenGL lacks?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;I am aware that this question might be closed as being off-topic or too broad, I tried my best to narrow it down.    &#xD;&#xA;&#xD;&#xA;  [1]: https://softwareengineering.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13401" PostHistoryTypeId="24" PostId="3700" RevisionGUID="ccc6668b-63b4-4b25-9041-0025da389cc0" CreationDate="2017-05-02T00:52:55.220" Comment="Proposed by 6546 approved by 3437 edit id of 235" ContentLicense="CC BY-SA 3.0" />
  <row Id="13403" PostHistoryTypeId="5" PostId="1488" RevisionGUID="6d948b75-f414-4fcd-b13d-46839c1f0c50" CreationDate="2017-05-02T08:27:43.637" UserId="6546" Comment="Fixed Grammatical Errors" Text="I'm using Unity 5 to make a small game (I'm a beginner) and I want to make a 3D model of a character. I'm not sure what software there is to do this and if there is some, I would like it to be preferably free, but if anyone can help or give advice I would appreciate it. I want to be able to make a 3D model and then import it to Unity 5. Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="13404" PostHistoryTypeId="4" PostId="1488" RevisionGUID="6d948b75-f414-4fcd-b13d-46839c1f0c50" CreationDate="2017-05-02T08:27:43.637" UserId="6546" Comment="Fixed Grammatical Errors" Text="How to make a 3D model for Unity 5" ContentLicense="CC BY-SA 3.0" />
  <row Id="13405" PostHistoryTypeId="24" PostId="1488" RevisionGUID="6d948b75-f414-4fcd-b13d-46839c1f0c50" CreationDate="2017-05-02T08:27:43.637" Comment="Proposed by 6546 approved by 48, 2041 edit id of 238" ContentLicense="CC BY-SA 3.0" />
  <row Id="13406" PostHistoryTypeId="5" PostId="5010" RevisionGUID="1a975aa0-adb7-49d6-a1c8-147aecc97a77" CreationDate="2017-05-02T08:28:09.843" UserId="6546" Comment="Restructured Points" Text="I have huge point cloud data I want to render them at interactive frame frate. Process I know is&#xD;&#xA;&#xD;&#xA;1.point cloud data &#xD;&#xA;&#xD;&#xA;2.triangulate it using delnauy or other triangulation algo&#xD;&#xA;&#xD;&#xA;3.surface voxelization for mesh&#xD;&#xA;&#xD;&#xA;4.volume tracing ti render&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But triangulation process is very very slow. Can I somehow voxelize my point cloud directly?&#xD;&#xA;I am newbie to voxelization." ContentLicense="CC BY-SA 3.0" />
  <row Id="13407" PostHistoryTypeId="4" PostId="5010" RevisionGUID="1a975aa0-adb7-49d6-a1c8-147aecc97a77" CreationDate="2017-05-02T08:28:09.843" UserId="6546" Comment="Restructured Points" Text="Can I voxelize 3D set of points without reconstructing surface first?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13408" PostHistoryTypeId="24" PostId="5010" RevisionGUID="1a975aa0-adb7-49d6-a1c8-147aecc97a77" CreationDate="2017-05-02T08:28:09.843" Comment="Proposed by 6546 approved by 2041 edit id of 240" ContentLicense="CC BY-SA 3.0" />
  <row Id="13409" PostHistoryTypeId="5" PostId="1445" RevisionGUID="b7ce2cbd-cc47-4305-9071-7d4d7d492871" CreationDate="2017-05-02T08:29:33.817" UserId="6546" Comment="Capitalized Pronouns" Text="I recently started to read about spherical harmonics. I have a question about this spherical harmonics basis function equation which is mentioned in this StupidSH article:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What are those lm() and Re() used for?&#xD;&#xA;&#xD;&#xA;The article can be found here: http://www.ppsloan.org/publications/StupidSH36.pdf&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sBx4G.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13410" PostHistoryTypeId="24" PostId="1445" RevisionGUID="b7ce2cbd-cc47-4305-9071-7d4d7d492871" CreationDate="2017-05-02T08:29:33.817" Comment="Proposed by 6546 approved by 48, 2041 edit id of 239" ContentLicense="CC BY-SA 3.0" />
  <row Id="13411" PostHistoryTypeId="10" PostId="4340" RevisionGUID="1733565e-6093-4211-bbfa-ef4636d627c4" CreationDate="2017-05-02T08:31:31.287" UserId="2041" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="13414" PostHistoryTypeId="2" PostId="5048" RevisionGUID="f92d813d-6cf4-40c7-a35a-d0e575388a24" CreationDate="2017-05-02T13:17:49.447" UserId="2041" Text="The original use for the stencil buffer was for non-3D content. Say you're making a 3D game. Most of the screen is the 3D content, but you also have some GUI around the outside which is not drawn through OpenGL but through a 2D canvas API. You can mask off the shape of the 2D GUI using the stencil buffer, and then make sure that your 3D/OpenGL content won't affect it and won't cause overdraw (which wastes fragment shading time).&#xD;&#xA;&#xD;&#xA;As you've seen, it's also used for techniques like shadow volumes and some reflection techniques. In general, it can be used for techniques where you draw an object and then want to run another fragment shader (or some more draw calls) to alter that object's appearance, by adding reflections, lighting, or screen-space effects. In that case, when you draw the object the first time, it's very cheap to fill the stencil buffer at the same time. Then, your later pass (to add the reflections or whatever) can use the stencil test to only run on those fragments that eventually did get drawn on the screen.&#xD;&#xA;&#xD;&#xA;Another common use is when rendering a scene in multiple parts. For example, in a flight simulator, it's common for the cockpit (and aircraft exterior) and the terrain (and other aircraft) to be done in completely separate passes. This lets you use a lower-precision depth buffer without causing z fighting, because you can use different depth ranges for the near content and the far content. But if you do this, you can't reuse the same depth values for both passes. In this case, you can fill the stencil buffer when you're drawing the cockpit, and use the stencil test to avoid overdrawing the cockpit when you draw the terrain. (You need to do more to handle glass effects on the cockpit windows: this description is an oversimplification.) You can use similar techniques for drawing the player's weapon and/or hands in first-person shooters.&#xD;&#xA;&#xD;&#xA;The stencil buffer is used in many techniques: too many to list them all individually. But in general, if you want to have some render passes only affect some fragments, and the fragments you want to affect are those corresponding to particular objects or shaders, then the stencil buffer is a cheap way to enable that." ContentLicense="CC BY-SA 3.0" />
  <row Id="13415" PostHistoryTypeId="2" PostId="5049" RevisionGUID="7c4ad824-7b7b-486d-8782-5e604641e061" CreationDate="2017-05-02T14:36:12.060" UserId="2941" Text="I'm trying to figure out why the probability density function for picking a uniform direction on the hemisphere is $\frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Something tells me this is related to the number of steradians in a hemisphere being $2\pi$, but I can't see how this is connected. We could come up with another measure for solid angle (&quot;blibs&quot; for example) where the number of blibs in the hemisphere would be $8000\pi$, but I'd expect the probability for picking a direction uniformly to be unchanged." ContentLicense="CC BY-SA 3.0" />
  <row Id="13416" PostHistoryTypeId="1" PostId="5049" RevisionGUID="7c4ad824-7b7b-486d-8782-5e604641e061" CreationDate="2017-05-02T14:36:12.060" UserId="2941" Text="Why is $pdf(\Psi) = \frac{1}{2\pi}$ when picking from hemisphere uniformly?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13417" PostHistoryTypeId="3" PostId="5049" RevisionGUID="7c4ad824-7b7b-486d-8782-5e604641e061" CreationDate="2017-05-02T14:36:12.060" UserId="2941" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13418" PostHistoryTypeId="5" PostId="4687" RevisionGUID="f1c79c83-50d2-4d85-bd01-3f988c19683b" CreationDate="2017-05-02T15:40:07.213" UserId="506" Comment="typo" Text="Noise functions are definitely your friend here—[FBM](https://code.google.com/archive/p/fractalterraingeneration/wikis/Fractional_Brownian_Motion.wiki) would be one good candidate. You’re right that it can look too uniform on its own, but if you blend multiple layers of it together, using different speeds / directions for each and maybe distorting their domains a bit, you should be able to get very close to the look of that footage. There’s lots of clever uses of noise functions on [Shadertoy](https://www.shadertoy.com/results?query=tag=noise&amp;sort=popular); for an example of something like the approach described above, check out [this one](https://www.shadertoy.com/view/Mtd3W7).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13419" PostHistoryTypeId="2" PostId="5050" RevisionGUID="91fabb30-f919-4a6a-b0c8-a6ab093bdde8" CreationDate="2017-05-02T15:52:36.140" UserId="2041" Text="It's like this because the surface area of a unit sphere is $4\pi$. As ratchet freak points out, the integral of a probability distribution over its domain has to be 1. Put another way, the probability of choosing some direction is 1. The surface area of the hemisphere is $2\pi$. The constant that you integrate over a $2\pi$ domain to get 1 is $\frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;The connection to steradians is that 1 steradian is defined as the solid angle that subtends a surface of area 1 on a unit sphere. That is, a unit sphere has $4\pi$ steradians and a surface area of $4\pi$.&#xD;&#xA;&#xD;&#xA;It's just the same in two dimensions. A radian is chosen so that a 1 radian arc of a unit circle has length 1, so there are $2\pi$ radians in a circle, and $\pi$ radians in a semicircle. If you choose 2D directions uniformly on a semicircle, the probability distribution is $\frac{1}{\pi}$." ContentLicense="CC BY-SA 3.0" />
  <row Id="13420" PostHistoryTypeId="2" PostId="5051" RevisionGUID="23951c39-422a-49c3-8caf-4383d9ac79ff" CreationDate="2017-05-02T16:38:40.207" UserId="5717" Text="Actually, it would change if you changed units in the $pdf$ definition. The fundamental reason is that the $pdf$ is defined as the probability per steradian. That's what the density part means. You could very well redefine it as the probability per hemisphere and end up with a $pdf$ of $1$ for your example." ContentLicense="CC BY-SA 3.0" />
  <row Id="13421" PostHistoryTypeId="5" PostId="5051" RevisionGUID="d9a5093f-fad6-4704-bcdf-cc31e892c203" CreationDate="2017-05-02T17:49:07.707" UserId="5717" Comment="typography" Text="Actually, it would change if you changed units in the $\textit{pdf}$ definition. The fundamental reason is that the $\textit{pdf}$ is defined as the probability per steradian. That's what the density part means. You could very well redefine it as the probability per hemisphere and end up with a $\textit{pdf}$ of $1$ for your example." ContentLicense="CC BY-SA 3.0" />
  <row Id="13423" PostHistoryTypeId="2" PostId="5052" RevisionGUID="61f6a53f-9a8f-49ed-b5dd-c43d56092d0d" CreationDate="2017-05-03T08:25:02.333" UserId="209" Text="Another use, that I think Dan didn't mention, is for filling non-convex polygons, e.g,&#xD;&#xA;hmm where is the add pictures options" ContentLicense="CC BY-SA 3.0" />
  <row Id="13424" PostHistoryTypeId="5" PostId="5052" RevisionGUID="1744eb6d-4df8-4427-a506-afcf49f2bcb0" CreationDate="2017-05-03T08:33:32.663" UserId="209" Comment="added 439 characters in body" Text="Another use, that I think Dan didn't mention, is for filling non-convex polygons, e.g,&#xD;&#xA;[![Concavities][1]][1] and [![Self intersections][2]][2]&#xD;&#xA;&#xD;&#xA;The stencil can be used to implement the fill rule which is typically either *odd/even* (as used in these examples) or *non-zero*, simply by, say, treating the list of vertices as a triangle fan (or with reordering) a triangle strip, and then sending an enclosing object and filling the pixels that match the appropriate rule.&#xD;&#xA;&#xD;&#xA;If, however, you are going to draw the same polygon repeatedly (with or without transformations), it might be more efficient to first apply a triangulation algorithm, which would reduce the amount of wasted overdraw.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/i3eZb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/fEApM.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13425" PostHistoryTypeId="5" PostId="5052" RevisionGUID="e673e00d-b76b-427a-867b-b4e5edb3cec0" CreationDate="2017-05-03T08:38:57.840" UserId="209" Comment="added 439 characters in body" Text="Another use, that I think Dan didn't mention, is for filling non-convex polygons, e.g,&#xD;&#xA;[![Concavities][1]][1] and [![Self intersections][2]][2]&#xD;&#xA;&#xD;&#xA;The stencil can be used to implement the fill rule which is typically either *odd/even* (as used in these examples) or *non-zero*, simply by, say, treating the list of vertices as a triangle fan (or with reordering) a triangle strip, and setting the stencil appropriately. Finally an enclosing object is drawn but restricted to just those pixels that match the appropriate rule. One catch, if you use the non-zero rule, is that you don't want to &quot;overflow&quot; the max stencil value.&#xD;&#xA;&#xD;&#xA;If, however, you are going to draw the same polygon repeatedly (with or without transformations), it might be more efficient to first apply a triangulation algorithm, which would eliminate the wasted overdraw. FWIW the supplied images come from a triangulation algorithm I worked on about a decade ago)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/i3eZb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/fEApM.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13426" PostHistoryTypeId="5" PostId="5052" RevisionGUID="a4bd6f24-d508-4af5-988b-e7a76251d84c" CreationDate="2017-05-03T08:50:54.200" UserId="209" Comment="edited body" Text="Another use, that I think Dan didn't mention, is for filling non-convex polygons, e.g,&#xD;&#xA;[![Concavities][1]][1] and [![Self intersections][2]][2]&#xD;&#xA;&#xD;&#xA;The stencil can be used to implement the fill rule which is typically either *odd/even* (as used in these examples) or *non-zero*, simply by, say, treating the list of vertices as a triangle fan or, with reordering, a triangle strip, and setting the stencil appropriately. Finally an enclosing object is drawn but restricted to just those pixels that match the appropriate rule. One catch, if you use the non-zero rule, is that you don't want to &quot;overflow&quot; the max stencil value.&#xD;&#xA;&#xD;&#xA;If, however, you are going to draw the same polygon repeatedly (with or without transformations), it might be more efficient to first apply a triangulation algorithm, which would eliminate the wasted overdraw. (FWIW the supplied images come from a triangulation algorithm I worked on about a decade ago for SVG/OpenVG.)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/i3eZb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/fEApM.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13427" PostHistoryTypeId="2" PostId="5053" RevisionGUID="349d3c2e-bf70-4194-8268-704b34cf1f4c" CreationDate="2017-05-03T15:27:52.273" UserId="6534" Text="I am attempting to visualize the raw output from PBRT's half-vector sampling function, based on the trowbridge-reitz distribution.  I'm isolating only the distribution and the associated functions necessary to sample it. &#xD;&#xA;&#xD;&#xA;The function runs the standard GGX half vector sampling formula: &#xD;&#xA;&#xD;&#xA;$$\theta_s = arctan(\frac{\alpha\sqrt{\xi_1}}{\sqrt{1-\xi_1}})$$&#xD;&#xA;$$\phi_s = 2\pi\xi_2$$&#xD;&#xA;&#xD;&#xA;(from Walter GGX: http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)&#xD;&#xA;&#xD;&#xA;these come back from the sampling function as a vector 3 and spherical coordinates with $$Normalize([\theta_s,\phi_s, 1.0])$$ which should perturb the surface normal, creating the half vector to reflect around.&#xD;&#xA;&#xD;&#xA;At this point I am only trying to make sense of the output from the &quot;sample wh&quot; function.  To visualize the results (raw &quot;wh&quot; output) I made a little graphics utility to output the results to a &quot;normal map&quot;.  Here is the output:[![GGX half vector samples][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0G3ei.jpg&#xD;&#xA;&#xD;&#xA;And a live webgl example here that continually runs new random numbers through the output (as if monte carlo sampling were running): http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;My expectation of the output would be a somewhat smooth gradient blend of the wh orientations as the x and y slopes cross into each other.  But what i'm seeing is an area between the 2 axes that doesn't want to blend well.  The random noise is good/expected, but you can see that inside the x/y blend areas, even the noise becomes fairly non-random.  &#xD;&#xA;&#xD;&#xA;Can anyone give me some tips on what the half vector sampling *should* graph like, or some pointers to papers/published work that I can use to locate test data, graphs, or other educational material that could help me figure this out?  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13428" PostHistoryTypeId="1" PostId="5053" RevisionGUID="349d3c2e-bf70-4194-8268-704b34cf1f4c" CreationDate="2017-05-03T15:27:52.273" UserId="6534" Text="Visualize the output of a Trowbridge-Reitz Half Vector Sampling Function" ContentLicense="CC BY-SA 3.0" />
  <row Id="13429" PostHistoryTypeId="3" PostId="5053" RevisionGUID="349d3c2e-bf70-4194-8268-704b34cf1f4c" CreationDate="2017-05-03T15:27:52.273" UserId="6534" Text="|raytracing|pathtracing|sampling|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13430" PostHistoryTypeId="5" PostId="5053" RevisionGUID="734d0f0e-7a88-4bd0-b572-6f7bc7027ca2" CreationDate="2017-05-03T15:32:52.517" UserId="6534" Comment="added 2 characters in body" Text="I am attempting to visualize the raw output from PBRT's half-vector sampling function, based on the trowbridge-reitz distribution.  I'm isolating only the distribution and the associated functions necessary to sample it. &#xD;&#xA;&#xD;&#xA;The function runs the standard GGX half vector sampling formula: &#xD;&#xA;&#xD;&#xA;$$\theta_s = arctan(\frac{\alpha_g\sqrt{\xi_1}}{\sqrt{1-\xi_1}})$$&#xD;&#xA;$$\phi_s = 2\pi\xi_2$$&#xD;&#xA;&#xD;&#xA;(from Walter GGX: http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)&#xD;&#xA;&#xD;&#xA;these come back from the sampling function as a vector 3 and spherical coordinates with $$Normalize([\theta_s,\phi_s, 1.0])$$ which should perturb the surface normal, creating the half vector to reflect around.&#xD;&#xA;&#xD;&#xA;At this point I am only trying to make sense of the output from the &quot;sample wh&quot; function.  To visualize the results (raw &quot;wh&quot; output) I made a little graphics utility to output the results to a &quot;normal map&quot;.  Here is the output:[![GGX half vector samples][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0G3ei.jpg&#xD;&#xA;&#xD;&#xA;And a live webgl example here that continually runs new random numbers through the output (as if monte carlo sampling were running): http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;My expectation of the output would be a somewhat smooth gradient blend of the wh orientations as the x and y slopes cross into each other.  But what i'm seeing is an area between the 2 axes that doesn't want to blend well.  The random noise is good/expected, but you can see that inside the x/y blend areas, even the noise becomes fairly non-random.  &#xD;&#xA;&#xD;&#xA;Can anyone give me some tips on what the half vector sampling *should* graph like, or some pointers to papers/published work that I can use to locate test data, graphs, or other educational material that could help me figure this out?  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13431" PostHistoryTypeId="5" PostId="5053" RevisionGUID="387a88e7-8c6d-47a4-a4e3-6b27229576d2" CreationDate="2017-05-03T16:07:52.830" UserId="6534" Comment="added 358 characters in body" Text="I am attempting to visualize the raw output from PBRT's half-vector sampling function, based on the trowbridge-reitz distribution.  I'm isolating only the distribution and the associated functions necessary to sample it. &#xD;&#xA;&#xD;&#xA;The function is based on the standard GGX half vector sampling formula: &#xD;&#xA;&#xD;&#xA;$$\theta_s = arctan(\frac{\alpha_g\sqrt{\xi_1}}{\sqrt{1-\xi_1}})$$&#xD;&#xA;$$\phi_s = 2\pi\xi_2$$&#xD;&#xA;&#xD;&#xA;(from Walter GGX: http://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)&#xD;&#xA;&#xD;&#xA;but the PBRT version has a lot more black magic related to importance sampling only directions that make significant contributions based on the incoming &quot;wo&quot; angle.  That one detail is making it hard for me to find published papers which specify how to add this directional importance sampling to the standard GGX sampling function.&#xD;&#xA;&#xD;&#xA;Anyway, these angles come back from the sampling function as a vector 3 and spherical coordinates with $$Normalize([\theta_s,\phi_s, 1.0])$$ which should perturb the surface normal, creating the half vector to reflect around.&#xD;&#xA;&#xD;&#xA;At this point I am only trying to make sense of the output from the &quot;sample wh&quot; function.  To visualize the results (raw &quot;wh&quot; output) I made a little graphics utility to output the results to a &quot;normal map&quot;.  Here is the output:[![GGX half vector samples][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0G3ei.jpg&#xD;&#xA;&#xD;&#xA;And a live webgl example here that continually runs new random numbers through the output (as if monte carlo sampling were running): http://rdtests.ml3ds-test.com/microfacettesting.html&#xD;&#xA;&#xD;&#xA;My expectation of the output would be a somewhat smooth gradient blend of the wh orientations as the x and y slopes cross into each other.  But what i'm seeing is an area between the 2 axes that doesn't want to blend well.  The random noise is good/expected, but you can see that inside the x/y blend areas, even the noise becomes fairly non-random.  &#xD;&#xA;&#xD;&#xA;Can anyone give me some tips on what the half vector sampling *should* graph like, or some pointers to papers/published work that I can use to locate test data, graphs, or other educational material that could help me figure this out?  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13432" PostHistoryTypeId="2" PostId="5054" RevisionGUID="1bcbfedc-2a51-4f4f-a681-e4623e4219d4" CreationDate="2017-05-03T16:54:57.977" UserId="6560" Text="So ordinarily we have this&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But I'm after this!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is it possible to do this? Ideally by changing the projection matrix?&#xD;&#xA;&#xD;&#xA;The reasoning is kinda interesting - I am developing for mobile VR, and I have found that putting my phone (and surely many others) in headsets that are too wide for them makes its so that your horizontal perspective convergence point is in the wrong place.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/W7GLv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3bVXX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13433" PostHistoryTypeId="1" PostId="5054" RevisionGUID="1bcbfedc-2a51-4f4f-a681-e4623e4219d4" CreationDate="2017-05-03T16:54:57.977" UserId="6560" Text="Render with camera perspective off-center" ContentLicense="CC BY-SA 3.0" />
  <row Id="13434" PostHistoryTypeId="3" PostId="5054" RevisionGUID="1bcbfedc-2a51-4f4f-a681-e4623e4219d4" CreationDate="2017-05-03T16:54:57.977" UserId="6560" Text="|projections|perspective|matrix|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13436" PostHistoryTypeId="2" PostId="5056" RevisionGUID="ceea9836-955f-4354-b16c-7e1361e494ca" CreationDate="2017-05-03T18:05:42.833" UserId="6534" Text="So for anyone who was interested - after studying the source material by Walter, I became convinced the error had to be in the rotation of the slopes back into &quot;normal shading space&quot;.  PBRT does this in a one-liner: &quot;CosPhi(wiStretched) * slope_x - SinPhi(wiStretched) * slope_y;&quot; etc etc.  I had split it out into separate sinTheta, sinPhi, sinPhiX steps.  One of those steps wasn't correct so the rotation wasn't unstreching correctly.  &#xD;&#xA;&#xD;&#xA;So the correct visualization for a GGX normal distribution of half vectors is this: &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rcyw8.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13437" PostHistoryTypeId="2" PostId="5057" RevisionGUID="19574257-7199-4785-97bb-96c7080af045" CreationDate="2017-05-03T19:43:39.773" UserId="6562" Text="In [my real time ray tracer][1], I shoot primary rays from the eye, and at hit points, I trace to a single light source to determine if the object is shadowed or lit.&#xD;&#xA;&#xD;&#xA;Pretty straightforward stuff so far.&#xD;&#xA;However I have recently added perfect mirrors to my scene.&#xD;&#xA;The reflections work just fine.&#xD;&#xA;&#xD;&#xA;However, the shadow calculation breaks down!&#xD;&#xA;&#xD;&#xA;A shadowed point could still be lit by the light source via a mirror.&#xD;&#xA;&#xD;&#xA;Is there an easy way to handle shadow rays towards bounced light?&#xD;&#xA;&#xD;&#xA;NOTE: I am not talking about the projection visible in the mirror surface: this shows shadowed and lit objects. But the directly visible scene itself, there are more shadowed objects than there should be, as some of the scene is lit via a mirror.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=cWSdORU-Gnk" ContentLicense="CC BY-SA 3.0" />
  <row Id="13438" PostHistoryTypeId="1" PostId="5057" RevisionGUID="19574257-7199-4785-97bb-96c7080af045" CreationDate="2017-05-03T19:43:39.773" UserId="6562" Text="Tracing shadow rays in a scene with mirrors" ContentLicense="CC BY-SA 3.0" />
  <row Id="13439" PostHistoryTypeId="3" PostId="5057" RevisionGUID="19574257-7199-4785-97bb-96c7080af045" CreationDate="2017-05-03T19:43:39.773" UserId="6562" Text="|raytracing|shadow|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13440" PostHistoryTypeId="2" PostId="5058" RevisionGUID="9be06752-2a01-40ba-a08e-a784de7c6115" CreationDate="2017-05-03T21:12:54.930" UserId="6562" Text="Yes, you can use an off-axis projection matrix.&#xD;&#xA;This is what I use in my code (note: I shift the centre upwards, not left as you do in your example.)&#xD;&#xA;&#xD;&#xA;    void camera_setAspectRatio(float aspect, float zNear, float zFar, bool offaxis)&#xD;&#xA;    {&#xD;&#xA;            // create a projection matrix&#xD;&#xA;            const float f = 1.0f / tanf(fovy_radians/2.0f);&#xD;&#xA;            fovx_radians = 2.0f * atanf( aspect * tanf(fovy_radians/2.0f) );&#xD;&#xA;            float* mout = proj.data;&#xD;&#xA;    &#xD;&#xA;            mout[0] = f / aspect;&#xD;&#xA;            mout[1] = 0.0f;&#xD;&#xA;            mout[2] = 0.0f;&#xD;&#xA;            mout[3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;            mout[4] = 0.0f;&#xD;&#xA;            mout[5] = f;&#xD;&#xA;            mout[6] = 0.0f;&#xD;&#xA;            mout[7] = 0.0f;&#xD;&#xA;    &#xD;&#xA;            mout[8] = 0.0f;&#xD;&#xA;            mout[9] = offaxis ? -0.25f : 0.0f; // off axis projection!&#xD;&#xA;            mout[10] = (zFar+zNear) / (zNear-zFar);&#xD;&#xA;            mout[11] = -1.0f;&#xD;&#xA;    &#xD;&#xA;            mout[12] = 0.0f;&#xD;&#xA;            mout[13] = 0.0f;&#xD;&#xA;            mout[14] = 2 * zFar * zNear /  (zNear-zFar);&#xD;&#xA;            mout[15] = 0.0f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Stereo Projection screens (not head-mounted) tend to use Off-Axis projection matrices as well. [Paul Bourke][1] has a great write up on these projections.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://paulbourke.net/stereographics/stereorender/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13441" PostHistoryTypeId="2" PostId="5059" RevisionGUID="2d17f837-bf91-4846-b8d1-75b8ca38e1a8" CreationDate="2017-05-03T23:35:40.103" UserId="6567" Text="More out of curiosity than for any practical purpose, I'm wondering what is lacking from older GPUs that causes them to be unable to support Vulkan.&#xD;&#xA;&#xD;&#xA;I know that some argue that some hardware, such as nVidia's Fermi series of GPUs, could support Vulkan in hardware but the vendors simply won't implement it for business reasons, but even disregarding that, there is obviously some most recent hardware that really doesn't support Vulkan, and I'm curious what they lack. Like, say, the nVidia Tesla GPUs, AMD's TeraScale (VLIW) GPUs, or Intel's Gen8 hardware.&#xD;&#xA;&#xD;&#xA;I'm mostly curious in knowing if the features in Vulkan that precludes support for these GPUs are somewhat &quot;peripheral&quot; in the API (like, say, required support for some particular texture format that the API *could* have just as well not required but did anyway to create a baseline that was considered reasonable), or if it's truly central to the Vulkan model." ContentLicense="CC BY-SA 3.0" />
  <row Id="13442" PostHistoryTypeId="1" PostId="5059" RevisionGUID="2d17f837-bf91-4846-b8d1-75b8ca38e1a8" CreationDate="2017-05-03T23:35:40.103" UserId="6567" Text="What prevents older GPUs from supporting Vulkan?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13443" PostHistoryTypeId="3" PostId="5059" RevisionGUID="2d17f837-bf91-4846-b8d1-75b8ca38e1a8" CreationDate="2017-05-03T23:35:40.103" UserId="6567" Text="|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13444" PostHistoryTypeId="2" PostId="5060" RevisionGUID="1b57b6c6-a80b-47c0-8a30-5cc5406aa820" CreationDate="2017-05-04T00:36:54.467" UserId="5717" Text="It depends how you define easy and what kind of constraints you have. The general case of this is rendering caustics but that's probably not what you're looking for if real time is your target.&#xD;&#xA;&#xD;&#xA;If your mirrors are always flat as in your demo and you only want to support a single bounce, the easiest I can see would be to reflect your light sources on the other side of the mirror's plane, before you start a frame. Let's call each reflection a virtual light source. Then for each of these, test if the ray between whatever you're shading and the virtual light source hits inside the mirror (simple plane/ray test). If it does hit then you trace the actual shadow ray to the mirror and the rest of the shadow ray from the mirror to the actual light source.&#xD;&#xA;&#xD;&#xA;This obviously won't scale well to many mirrors. I think it could be adapted to 2-3 bounces if the mirror and light count is low. The number of virtual lights could quickly grow out of hand though." ContentLicense="CC BY-SA 3.0" />
  <row Id="13447" PostHistoryTypeId="50" PostId="4651" RevisionGUID="ee5af87d-245b-48fa-b481-00fa62a42bfd" CreationDate="2017-05-04T09:33:11.673" UserId="-1" />
  <row Id="13448" PostHistoryTypeId="2" PostId="5062" RevisionGUID="c809c614-5be5-4ef1-94b9-e2179c6fd23a" CreationDate="2017-05-04T11:53:38.683" UserId="6572" Text="I have been looking for an algorithm that evaluates a shared complex edge between two objects to determine which of the two is 'facing inwards', which can then be simplified by converting the edge in a straight line. In my situation the adjusted object will be painted beneath the unmodified object, and thus will have no visual effect.&#xD;&#xA;&#xD;&#xA;The image below illustrates what I want to achieve.&#xD;&#xA;&#xD;&#xA;![example](https://i.stack.imgur.com/ECjNI.jpg)&#xD;&#xA;&#xD;&#xA;Is anyone aware of an algorithm that does this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13449" PostHistoryTypeId="1" PostId="5062" RevisionGUID="c809c614-5be5-4ef1-94b9-e2179c6fd23a" CreationDate="2017-05-04T11:53:38.683" UserId="6572" Text="Algorithm for shared complex edge simplification" ContentLicense="CC BY-SA 3.0" />
  <row Id="13450" PostHistoryTypeId="3" PostId="5062" RevisionGUID="c809c614-5be5-4ef1-94b9-e2179c6fd23a" CreationDate="2017-05-04T11:53:38.683" UserId="6572" Text="|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13451" PostHistoryTypeId="6" PostId="5028" RevisionGUID="2d823359-6366-4eed-ab64-d85c31d6ef77" CreationDate="2017-05-04T12:52:41.193" UserId="6515" Comment="edited tags" Text="|raytracing|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13454" PostHistoryTypeId="6" PostId="5028" RevisionGUID="276b70e2-3850-4491-beed-74e24b8f8d6a" CreationDate="2017-05-04T19:41:17.070" UserId="231" Comment="edited tags" Text="|raytracing|pathtracing|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13455" PostHistoryTypeId="2" PostId="5063" RevisionGUID="c41caa02-8c0c-426d-a549-c9bd0b788c74" CreationDate="2017-05-05T06:48:27.043" UserId="6546" Text="I've been following the [LearnOpenGL][1] tutorials and I've come across a piece of code I don't understand.&#xD;&#xA;&#xD;&#xA;    glUniform1i(glGetUniformLocation(ShaderID, &quot;textureVar&quot;), 0);&#xD;&#xA;&#xD;&#xA;In the above code _ShaderID_ is a _GLuint_ which references a shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_textureVar_ is a _sampler2D_ in the shader.&#xD;&#xA;&#xD;&#xA;I don't understand the last parameter in that line of code. Does the _0_ represent **GL_TEXTURE0** or what exactly does the last parameter mean?&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/code_viewer.php?code=advanced-lighting/normal_mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="13456" PostHistoryTypeId="1" PostId="5063" RevisionGUID="c41caa02-8c0c-426d-a549-c9bd0b788c74" CreationDate="2017-05-05T06:48:27.043" UserId="6546" Text="Send Texture to Shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="13457" PostHistoryTypeId="3" PostId="5063" RevisionGUID="c41caa02-8c0c-426d-a549-c9bd0b788c74" CreationDate="2017-05-05T06:48:27.043" UserId="6546" Text="|opengl|shader|texture|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13458" PostHistoryTypeId="5" PostId="2163" RevisionGUID="87c5caa1-c8ec-4d72-9144-7062bef6aa82" CreationDate="2017-05-05T07:44:19.203" UserId="6546" Comment="Fixed Spelling Mistakes" Text="I've been researching for quite a while and I couldn't find any explanation or at least a how to create a vector graphic application (specifically in windows) where I can create a 3D vector shape, say a box. I know there is OpenGL and DirectX for that and the new Vulkan API but I don't wan't to use those APIs and libraries. What I am asking is where can I find examples or at least tutorials for creating custom made API graphics library for the C++ language. If there is not a way in C++ language then any other way to do it. By example masm or nasm Assembly language.&#xD;&#xA;&#xD;&#xA;If my question is too broad please specify any additional information you need to be able to answer my question." ContentLicense="CC BY-SA 3.0" />
  <row Id="13459" PostHistoryTypeId="4" PostId="2163" RevisionGUID="87c5caa1-c8ec-4d72-9144-7062bef6aa82" CreationDate="2017-05-05T07:44:19.203" UserId="6546" Comment="Fixed Spelling Mistakes" Text="Creating vector shapes using only C++" ContentLicense="CC BY-SA 3.0" />
  <row Id="13460" PostHistoryTypeId="24" PostId="2163" RevisionGUID="87c5caa1-c8ec-4d72-9144-7062bef6aa82" CreationDate="2017-05-05T07:44:19.203" Comment="Proposed by 6546 approved by 310, 209 edit id of 241" ContentLicense="CC BY-SA 3.0" />
  <row Id="13461" PostHistoryTypeId="2" PostId="5064" RevisionGUID="90619e40-9140-4cd5-9b53-7d5cfa2cd6a8" CreationDate="2017-05-05T09:51:46.833" UserId="113" Text="What would cause this grayscaled backside?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mkpo3.gif&#xD;&#xA;&#xD;&#xA;When my camera is behind my model I see a grayscale specular highlight. However, in front of it is perfectly fine. Here's my shading code. (Software rendering)&#xD;&#xA;&#xD;&#xA;      // diffuse cosines&#xD;&#xA;      float diffVal1 = MathHelper::Dot(n1, dirLight);&#xD;&#xA;      float diffVal2 = MathHelper::Dot(n2, dirLight);&#xD;&#xA;      float diffVal3 = MathHelper::Dot(n3, dirLight);&#xD;&#xA;&#xD;&#xA;      // Get the specular shade&#xD;&#xA;      // Reflectance vectors&#xD;&#xA;      float3 r1 = dirLight - n1 * 2 * diffVal1;&#xD;&#xA;      float3 r2 = dirLight - n2 * 2 * diffVal2;&#xD;&#xA;      float3 r3 = dirLight - n3 * 2 * diffVal3;&#xD;&#xA;&#xD;&#xA;      float spec1 = pow(MathHelper::Dot(r1, cam-&gt;GetViewDir()), mesh-&gt;mat-&gt;specularShine);    &#xD;&#xA;      float spec2 = pow(MathHelper::Dot(r2, cam-&gt;GetViewDir()), mesh-&gt;mat-&gt;specularShine);&#xD;&#xA;      float spec3 = pow(MathHelper::Dot(r3, cam-&gt;GetViewDir()), mesh-&gt;mat-&gt;specularShine);&#xD;&#xA;&#xD;&#xA;      Color col1 = mesh-&gt;mat-&gt;diffuse * Utility::Saturate(diff1) + mesh-&gt;mat-&gt;specular * Utility::Saturate(spec1) + mesh-&gt;mat-&gt;ambient;&#xD;&#xA;      Color col2 = mesh-&gt;mat-&gt;diffuse * Utility::Saturate(diff2) + mesh-&gt;mat-&gt;specular * Utility::Saturate(spec2) + mesh-&gt;mat-&gt;ambient;&#xD;&#xA;      Color col3 = mesh-&gt;mat-&gt;diffuse * Utility::Saturate(diff3) + mesh-&gt;mat-&gt;specular * Utility::Saturate(spec3) + mesh-&gt;mat-&gt;ambient);&#xD;&#xA;&#xD;&#xA;      DrawBaryTriangle(screen, triangle, col1, col2, col3);&#xD;&#xA;&#xD;&#xA;It's simply &#xD;&#xA;&#xD;&#xA;    Diffuse Color * Sat(diffuseVal) + Specular Color * Sat(specularVal) + Ambient Color&#xD;&#xA;&#xD;&#xA;Where Sat clamps any color values above 255 to 255." ContentLicense="CC BY-SA 3.0" />
  <row Id="13462" PostHistoryTypeId="1" PostId="5064" RevisionGUID="90619e40-9140-4cd5-9b53-7d5cfa2cd6a8" CreationDate="2017-05-05T09:51:46.833" UserId="113" Text="Specular Highlight Gray When Behind Model" ContentLicense="CC BY-SA 3.0" />
  <row Id="13463" PostHistoryTypeId="3" PostId="5064" RevisionGUID="90619e40-9140-4cd5-9b53-7d5cfa2cd6a8" CreationDate="2017-05-05T09:51:46.833" UserId="113" Text="|rendering|shader|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13464" PostHistoryTypeId="5" PostId="5064" RevisionGUID="d3a9db99-1946-4787-a5cf-ed119ed4fdd5" CreationDate="2017-05-05T10:22:55.370" UserId="113" Comment="added 18 characters in body" Text="What would cause this grayscaled backside?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mkpo3.gif&#xD;&#xA;&#xD;&#xA;When my camera is behind my model I see a grayscale specular highlight. However, in front of it is perfectly fine. Here's my shading code. (Software rendering)&#xD;&#xA;&#xD;&#xA;      // diffuse cosines&#xD;&#xA;      float diffVal1 = MathHelper::Dot(n1, dirLight);&#xD;&#xA;      float diffVal2 = MathHelper::Dot(n2, dirLight);&#xD;&#xA;      float diffVal3 = MathHelper::Dot(n3, dirLight);&#xD;&#xA;&#xD;&#xA;      // Get the specular shade&#xD;&#xA;      // Reflectance vectors&#xD;&#xA;      float3 r1 = dirLight - n1 * 2 * diffVal1;&#xD;&#xA;      float3 r2 = dirLight - n2 * 2 * diffVal2;&#xD;&#xA;      float3 r3 = dirLight - n3 * 2 * diffVal3;&#xD;&#xA;&#xD;&#xA;      float spec1 = pow(MathHelper::Dot(r1, cam-&gt;GetViewDir()), mesh-&gt;mat-&gt;specularShine);    &#xD;&#xA;      float spec2 = pow(MathHelper::Dot(r2, cam-&gt;GetViewDir()), mesh-&gt;mat-&gt;specularShine);&#xD;&#xA;      float spec3 = pow(MathHelper::Dot(r3, cam-&gt;GetViewDir()), mesh-&gt;mat-&gt;specularShine);&#xD;&#xA;&#xD;&#xA;      Color col1 = mesh-&gt;mat-&gt;diffuse * Utility::Saturate(diff1) + mesh-&gt;mat-&gt;specular * Utility::Saturate(spec1) + mesh-&gt;mat-&gt;ambient;&#xD;&#xA;      Color col2 = mesh-&gt;mat-&gt;diffuse * Utility::Saturate(diff2) + mesh-&gt;mat-&gt;specular * Utility::Saturate(spec2) + mesh-&gt;mat-&gt;ambient;&#xD;&#xA;      Color col3 = mesh-&gt;mat-&gt;diffuse * Utility::Saturate(diff3) + mesh-&gt;mat-&gt;specular * Utility::Saturate(spec3) + mesh-&gt;mat-&gt;ambient);&#xD;&#xA;&#xD;&#xA;      DrawBaryTriangle(screen, triangle, col1, col2, col3);&#xD;&#xA;&#xD;&#xA;It's simply &#xD;&#xA;&#xD;&#xA;    Diffuse Color * Sat(diffuseVal) + Specular Color * Sat(specularVal) + Ambient Color&#xD;&#xA;&#xD;&#xA;Where Sat clamps any color values to [0, 255] and any scalars [0, 1]." ContentLicense="CC BY-SA 3.0" />
  <row Id="13465" PostHistoryTypeId="2" PostId="5065" RevisionGUID="980780e5-7a25-4142-8da0-1d84227810af" CreationDate="2017-05-05T15:35:38.160" UserId="6546" Text="As was stated by @PaulHK, the last parameter represents the Texture Unit the texture us bound to.&#xD;&#xA;&#xD;&#xA;For example:&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glUniform1i(glGetUniformLocation(shaderRed, &quot;texture1&quot;), GL_TEXTURE0);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13466" PostHistoryTypeId="5" PostId="4648" RevisionGUID="bbe5754c-f6f2-45ac-b1f0-4350d63d1a3d" CreationDate="2017-05-05T16:40:51.833" UserId="6546" Comment="Fixed Spelling Mistakes" Text="I was trying to make a CPU-based ray tracer but I know after all the calculation I will end up with an array of pixels. I don't know how to paint it on the screen. What are the various ways to do that? I am using C++ and I am working on Windows 10. I know OpenGL(useless since I am not gonna use my GPU), Allegro 5 game library and I am also familiar with win32 C++ API. " ContentLicense="CC BY-SA 3.0" />
  <row Id="13467" PostHistoryTypeId="4" PostId="4648" RevisionGUID="bbe5754c-f6f2-45ac-b1f0-4350d63d1a3d" CreationDate="2017-05-05T16:40:51.833" UserId="6546" Comment="Fixed Spelling Mistakes" Text="How can I send custom bitmap to frame buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13468" PostHistoryTypeId="24" PostId="4648" RevisionGUID="bbe5754c-f6f2-45ac-b1f0-4350d63d1a3d" CreationDate="2017-05-05T16:40:51.833" Comment="Proposed by 6546 approved by 209, 48 edit id of 242" ContentLicense="CC BY-SA 3.0" />
  <row Id="13474" PostHistoryTypeId="2" PostId="5067" RevisionGUID="3767a266-d864-4941-9214-7996957dbb05" CreationDate="2017-05-05T19:43:44.567" UserId="5609" Text="I implemented a Phong shader in GLSL, but there is a bug.&#xD;&#xA;&#xD;&#xA;**What you are (supposed) to see down below:**&#xD;&#xA;&#xD;&#xA; * A point light source rotating around the center of the world,&#xD;&#xA;&#xD;&#xA;  * with a **radiance of (0, 100, 0)**&#xD;&#xA;&#xD;&#xA; * A textured quad with **kd of (1, 0, 0)**.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**The problem is:**&#xD;&#xA;&#xD;&#xA; * Why is there a a **green line to the center** instead of a **green spot light**?&#xD;&#xA;&#xD;&#xA;  * (Btw in this case there would be only a yellow spot of light, because red + green = yellow)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Vertex Shader:**&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;      &#xD;&#xA;    uniform mat4 ModelMatrix, ViewMatrix, ProjectionMatrix;   &#xD;&#xA;    &#xD;&#xA;    uniform vec4 wLiPos[5];       // pos of light source &#xD;&#xA;    uniform vec3 wEye;         // pos of eye&#xD;&#xA;    uniform int lightSize;		//number of lights&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 vtxPos;&#xD;&#xA;    layout(location = 1) in vec3 vtxNorm;&#xD;&#xA;    layout(location = 2) in vec2 vtxUV;&#xD;&#xA;    &#xD;&#xA;    out vec2 texCoord;&#xD;&#xA;    out vec3 wNormal;           // normal in world space&#xD;&#xA;    out vec3 wView[5];             // view in world space&#xD;&#xA;    out vec3 wLight[5];            // light dir in world space&#xD;&#xA;                                                                &#xD;&#xA;    void main() {&#xD;&#xA;    	gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vtxPos, 1);&#xD;&#xA;    	texCoord = vtxUV;&#xD;&#xA;    	vec4 wPos = ModelMatrix * vec4(vtxPos, 1);&#xD;&#xA;    	wNormal = (vec4(vtxNorm, 0) * inverse(ModelMatrix)).xyz;&#xD;&#xA;    	for(int i = 0; i &lt; lightSize; i++) {&#xD;&#xA;    		wView[i] = wEye * wPos.w - wPos.xyz;&#xD;&#xA;    		wLight[i] = wLiPos[i].xyz * wPos.w - wPos.xyz * wLiPos[i].w;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Fragment shader:**&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D samplerUnit;&#xD;&#xA;     &#xD;&#xA;    uniform vec3 kd, ks, ka;   // diffuse, specular, ambient ref&#xD;&#xA;    uniform vec3 La, Le[5];    // ambient and point source rad&#xD;&#xA;    uniform float shininess;    // shininess for specular ref&#xD;&#xA;    uniform int lightSize;&#xD;&#xA;       &#xD;&#xA;    in vec2 texCoord;    &#xD;&#xA;    in vec3 wNormal;       // interpolated world sp normal&#xD;&#xA;    in vec3 wView[5];         // interpolated world sp view&#xD;&#xA;    in vec3 wLight[5];        // interpolated world sp illum dir&#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;    layout(location = 0) out vec4 fragmentColor;&#xD;&#xA;            &#xD;&#xA;    void main() {     &#xD;&#xA;    	vec3 color = vec3(0, 0, 0);&#xD;&#xA;    	for(int i = 0; i &lt; lightSize; i++) {&#xD;&#xA;    		vec3 N = normalize(wNormal);&#xD;&#xA;    		vec3 V = normalize(wView[i]);&#xD;&#xA;    		vec3 L = normalize(wLight[i]);&#xD;&#xA;    		vec3 H = normalize(L + V);&#xD;&#xA;    		float cost = max(dot(N,L), 0);&#xD;&#xA;    		float cosd = max(dot(N,H), 0);&#xD;&#xA;    		color += ka * La + (kd * cost + (ks * pow(cosd, shininess)) * Le[i]) / pow(length(wLight[i]), 2);&#xD;&#xA;    	}&#xD;&#xA;    	vec3 gamma = vec3(1.0/2.2);&#xD;&#xA;    	fragmentColor = vec4(pow(color * vec3(texture2D(samplerUnit, texCoord)), gamma), 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oPH5d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13475" PostHistoryTypeId="1" PostId="5067" RevisionGUID="3767a266-d864-4941-9214-7996957dbb05" CreationDate="2017-05-05T19:43:44.567" UserId="5609" Text="Phong shading in OpenGL: line of light from the center of the world" ContentLicense="CC BY-SA 3.0" />
  <row Id="13476" PostHistoryTypeId="3" PostId="5067" RevisionGUID="3767a266-d864-4941-9214-7996957dbb05" CreationDate="2017-05-05T19:43:44.567" UserId="5609" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13477" PostHistoryTypeId="5" PostId="5049" RevisionGUID="de83cd2d-4109-4e9e-a7b7-fc5bb46ee14b" CreationDate="2017-05-05T22:00:55.370" UserId="2941" Comment="added 2 characters in body" Text="I'm trying to figure out why the probability density function for picking a direction uniformly on the hemisphere is $\frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Something tells me this is related to the number of steradians in a hemisphere being $2\pi$, but I can't see how this is connected. We could come up with another measure for solid angle (&quot;blibs&quot; for example) where the number of blibs in the hemisphere would be $8000\pi$, but I'd expect the probability for picking a direction uniformly to be unchanged." ContentLicense="CC BY-SA 3.0" />
  <row Id="13478" PostHistoryTypeId="2" PostId="5068" RevisionGUID="d9639c41-f9ca-4424-b32f-d71ed3c53caa" CreationDate="2017-05-06T09:57:20.703" UserId="6282" Text="I have multiple reflection cube map that's prebaked before a scene.&#xD;&#xA;&#xD;&#xA;However I am being confused as to which one to choose.&#xD;&#xA;&#xD;&#xA;I am told I need to choose &quot;closest cube map&quot; then use it.&#xD;&#xA;&#xD;&#xA;However it is unclear to me that whether I should do that based off of per pixel or per object(object's position).&#xD;&#xA;&#xD;&#xA;I looked at Unity to get some ideas as well.&#xD;&#xA;&#xD;&#xA;Unity chooses a reflection probe based off of distance and area probe affects the object.&#xD;&#xA;&#xD;&#xA;However there is no clear &quot;do this&quot;. So I am tentative and left unsure." ContentLicense="CC BY-SA 3.0" />
  <row Id="13479" PostHistoryTypeId="1" PostId="5068" RevisionGUID="d9639c41-f9ca-4424-b32f-d71ed3c53caa" CreationDate="2017-05-06T09:57:20.703" UserId="6282" Text="How to choose which reflection probe to use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13480" PostHistoryTypeId="3" PostId="5068" RevisionGUID="d9639c41-f9ca-4424-b32f-d71ed3c53caa" CreationDate="2017-05-06T09:57:20.703" UserId="6282" Text="|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13481" PostHistoryTypeId="50" PostId="4663" RevisionGUID="a4712f2d-56c5-4f72-9c8d-eb432a90a8ef" CreationDate="2017-05-06T11:21:32.850" UserId="-1" />
  <row Id="13482" PostHistoryTypeId="12" PostId="5065" RevisionGUID="fe954d75-2f2e-4b08-80d1-f965bedfefa6" CreationDate="2017-05-06T15:24:51.337" UserId="6546" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6546,&quot;DisplayName&quot;:&quot;Archmede&quot;}]}" />
  <row Id="13483" PostHistoryTypeId="13" PostId="5065" RevisionGUID="7fb8befd-912b-4458-98bb-500947c85e1a" CreationDate="2017-05-06T16:31:45.927" UserId="6546" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6546,&quot;DisplayName&quot;:&quot;Archmede&quot;}]}" />
  <row Id="13484" PostHistoryTypeId="5" PostId="5065" RevisionGUID="3d1b573c-9d7e-4ad6-b8ee-cf3e714ea17c" CreationDate="2017-05-06T16:34:19.867" UserId="6546" Comment="edited body" Text="As was stated by @PaulHK, the last parameter represents the Texture Unit the texture is bound to.&#xD;&#xA;&#xD;&#xA;For example:&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glUniform1i(glGetUniformLocation(shaderRed, &quot;texture1&quot;), GL_TEXTURE0);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13485" PostHistoryTypeId="5" PostId="5065" RevisionGUID="cd6e77e0-a692-4f03-bd33-ba33603e2fd9" CreationDate="2017-05-06T16:53:38.740" UserId="6546" Comment="added 445 characters in body" Text="As was stated by @PaulHK, the last parameter represents the Texture Unit the texture is bound to.&#xD;&#xA;&#xD;&#xA;For example:&#xD;&#xA;&#xD;&#xA;    GLuint unit = 0;&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + unit);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glUniform1i(glGetUniformLocation(shaderRef, &quot;texture1&quot;), unit);&#xD;&#xA;&#xD;&#xA;    unit = 1;&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + unit);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture2);&#xD;&#xA;    glUniform1i(glGetUniformLocation(shaderRef, &quot;texture2&quot;), unit);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The above code binds Texture Unit 0 to the fragment shader and then sends it texture1. Then it binds Texture Unit 1 to the shader and sends it texture2. The `unit` var represents the Texture Unit we are binding to the `sampler` in the shader to.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13486" PostHistoryTypeId="2" PostId="5069" RevisionGUID="bd3fe7ed-41f7-42ff-ac75-c3c3afb30120" CreationDate="2017-05-06T19:04:47.600" UserId="6" Text="Yes, the `0` in there represents the **texture unit that the sampler references**. So in order for a texture to be referenced by `textureVar` in the shader, it should be bound to texture unit 0 (e.g. by `glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ...)` or any other means you can bind a texture to a texture unit.&#xD;&#xA;&#xD;&#xA;However, note that it **doesn't actually matter which texture unit is active when setting that uniform, nor what texture is bound to that unit**. Effectively to the outside world the sampler uniform is just an integer value specifying the texture unit to take its texture and sampler information from. It can be set to that texture unit whenever you want and the texture can be bound to that unit whenever you want (in fact in GLSL 4.20+ you can actually initialize the uniform right in the shader with e.g. `layout(binding=0) uniform sampler2D textureVar`). All that matters is that at the point the shader gets invoked (i.e. when actually `glDraw...`ing something) the sampler is set to the proper a unit and the texture is bound to that unit.&#xD;&#xA;&#xD;&#xA;For more information on the matter, take a look at the [corresponding section in the OpenGL Wiki](https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Binding_textures_to_samplers)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13487" PostHistoryTypeId="2" PostId="5070" RevisionGUID="ad169314-8661-4064-a1fe-e97d68217cbc" CreationDate="2017-05-07T03:44:31.897" UserId="6579" Text="I'm on OpenGL ES 3.0 using Mesa 17.0.3. When calling &#xD;&#xA;`glDrawArrays(GL_TRIANGLE_FAN, 0, 4)`, &#xD;&#xA;`glGetError()` returns `GL_INVALID_ENUM`. &#xD;&#xA;&#xD;&#xA;I have no idea what's causing it and https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glDrawArrays.xhtml is claiming that GL_TRIANGLE_FAN is an accepted value for `mode`.&#xD;&#xA;&#xD;&#xA;I'm checking for GL errors immediately before the call, and everything's fine then." ContentLicense="CC BY-SA 3.0" />
  <row Id="13488" PostHistoryTypeId="1" PostId="5070" RevisionGUID="ad169314-8661-4064-a1fe-e97d68217cbc" CreationDate="2017-05-07T03:44:31.897" UserId="6579" Text="glDrawArrays is failing with GL_INVALID_ENUM" ContentLicense="CC BY-SA 3.0" />
  <row Id="13489" PostHistoryTypeId="3" PostId="5070" RevisionGUID="ad169314-8661-4064-a1fe-e97d68217cbc" CreationDate="2017-05-07T03:44:31.897" UserId="6579" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13490" PostHistoryTypeId="5" PostId="5069" RevisionGUID="1ca5d14c-0939-43be-a57c-1347d3b3e1f6" CreationDate="2017-05-07T07:51:13.510" UserId="231" Comment="Typo" Text="Yes, the `0` in there represents the **texture unit that the sampler references**. So in order for a texture to be referenced by `textureVar` in the shader, it should be bound to texture unit 0 (e.g. by `glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ...)` or any other means you can bind a texture to a texture unit.&#xD;&#xA;&#xD;&#xA;However, note that it **doesn't actually matter which texture unit is active when setting that uniform, nor what texture is bound to that unit**. Effectively to the outside world the sampler uniform is just an integer value specifying the texture unit to take its texture and sampler information from. It can be set to that texture unit whenever you want and the texture can be bound to that unit whenever you want (in fact in GLSL 4.20+ you can actually initialize the uniform right in the shader with e.g. `layout(binding=0) uniform sampler2D textureVar`). All that matters is that at the point the shader gets invoked (i.e. when actually `glDraw...`ing something) the sampler is set to the proper unit and the texture is bound to that unit.&#xD;&#xA;&#xD;&#xA;For more information on the matter, take a look at the [corresponding section in the OpenGL Wiki](https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Binding_textures_to_samplers)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13491" PostHistoryTypeId="2" PostId="5071" RevisionGUID="1c23831f-4bc4-441a-b4a6-a049d9096e4d" CreationDate="2017-05-07T12:46:08.733" UserId="6583" Text="&lt;br&gt;   &#xD;&#xA;I have a task to join two bezier curves, so that the resulting curve is two-times continuously differentiable.&lt;br&gt;&#xD;&#xA;I have the cubic bezier Curve C with control points:&lt;br&gt;&#xD;&#xA;c0 = (1,1)&lt;br&gt;&#xD;&#xA;c1 = (3,4)&lt;br&gt;&#xD;&#xA;c2 = (7,5)&lt;br&gt;&#xD;&#xA;c3 = (8,2)&lt;br&gt;&#xD;&#xA;I shall continue this curve C with Curve D from control point c3 to a control point d3 = (12,1) so that this curve is two-times continuously differentiable.&lt;br&gt;&#xD;&#xA;First Task: Determine control points d0, d1, d1 for the new curve.&#xD;&#xA;Second Task: Specify a pecewise defined formula for the new curve G(v) with v out of [0,1] that passes through c0,c3 and d3. Thus connect curves C and D in v = 1/2.&#xD;&#xA;Third Task: Prove by calculation that the transition between C and D is two-times continuously differentiable.&lt;br&gt;&lt;br&gt;&#xD;&#xA;Regarding first task: I don't know how to determine the points. Can someone help to do this? The rest of the tasks is then maybe something easier to do for me. Tank You!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13492" PostHistoryTypeId="1" PostId="5071" RevisionGUID="1c23831f-4bc4-441a-b4a6-a049d9096e4d" CreationDate="2017-05-07T12:46:08.733" UserId="6583" Text="Join two bezier curves so that the result is two-times continuously differentiable" ContentLicense="CC BY-SA 3.0" />
  <row Id="13493" PostHistoryTypeId="3" PostId="5071" RevisionGUID="1c23831f-4bc4-441a-b4a6-a049d9096e4d" CreationDate="2017-05-07T12:46:08.733" UserId="6583" Text="|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13494" PostHistoryTypeId="5" PostId="5067" RevisionGUID="a1533776-528e-44df-8c72-196601b70dbd" CreationDate="2017-05-07T14:16:56.003" UserId="5609" Comment="added 83 characters in body" Text="I implemented a Phong shader in GLSL, but there is a bug.&#xD;&#xA;&#xD;&#xA;**What you are (supposed) to see down below:**&#xD;&#xA;&#xD;&#xA; * A point light source rotating around the center of the world,&#xD;&#xA;&#xD;&#xA;  * with a **radiance of (0, 100, 0)**&#xD;&#xA;&#xD;&#xA; * A textured quad with **kd of (1, 0, 0)**.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**The problem is:**&#xD;&#xA;&#xD;&#xA; * Why is there a a **green line to the center of the world** instead of a **green spot light where the quad is lit**? (where the center of the point light source is)&#xD;&#xA;&#xD;&#xA;  * (Btw in this case there would be only a yellow spot of light, because red + green = yellow)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Vertex Shader:**&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;      &#xD;&#xA;    uniform mat4 ModelMatrix, ViewMatrix, ProjectionMatrix;   &#xD;&#xA;    &#xD;&#xA;    uniform vec4 wLiPos[5];       // pos of light source &#xD;&#xA;    uniform vec3 wEye;         // pos of eye&#xD;&#xA;    uniform int lightSize;		//number of lights&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 vtxPos;&#xD;&#xA;    layout(location = 1) in vec3 vtxNorm;&#xD;&#xA;    layout(location = 2) in vec2 vtxUV;&#xD;&#xA;    &#xD;&#xA;    out vec2 texCoord;&#xD;&#xA;    out vec3 wNormal;           // normal in world space&#xD;&#xA;    out vec3 wView[5];             // view in world space&#xD;&#xA;    out vec3 wLight[5];            // light dir in world space&#xD;&#xA;                                                                &#xD;&#xA;    void main() {&#xD;&#xA;    	gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(vtxPos, 1);&#xD;&#xA;    	texCoord = vtxUV;&#xD;&#xA;    	vec4 wPos = ModelMatrix * vec4(vtxPos, 1);&#xD;&#xA;    	wNormal = (vec4(vtxNorm, 0) * inverse(ModelMatrix)).xyz;&#xD;&#xA;    	for(int i = 0; i &lt; lightSize; i++) {&#xD;&#xA;    		wView[i] = wEye * wPos.w - wPos.xyz;&#xD;&#xA;    		wLight[i] = wLiPos[i].xyz * wPos.w - wPos.xyz * wLiPos[i].w;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Fragment shader:**&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D samplerUnit;&#xD;&#xA;     &#xD;&#xA;    uniform vec3 kd, ks, ka;   // diffuse, specular, ambient ref&#xD;&#xA;    uniform vec3 La, Le[5];    // ambient and point source rad&#xD;&#xA;    uniform float shininess;    // shininess for specular ref&#xD;&#xA;    uniform int lightSize;&#xD;&#xA;       &#xD;&#xA;    in vec2 texCoord;    &#xD;&#xA;    in vec3 wNormal;       // interpolated world sp normal&#xD;&#xA;    in vec3 wView[5];         // interpolated world sp view&#xD;&#xA;    in vec3 wLight[5];        // interpolated world sp illum dir&#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;    layout(location = 0) out vec4 fragmentColor;&#xD;&#xA;            &#xD;&#xA;    void main() {     &#xD;&#xA;    	vec3 color = vec3(0, 0, 0);&#xD;&#xA;    	for(int i = 0; i &lt; lightSize; i++) {&#xD;&#xA;    		vec3 N = normalize(wNormal);&#xD;&#xA;    		vec3 V = normalize(wView[i]);&#xD;&#xA;    		vec3 L = normalize(wLight[i]);&#xD;&#xA;    		vec3 H = normalize(L + V);&#xD;&#xA;    		float cost = max(dot(N,L), 0);&#xD;&#xA;    		float cosd = max(dot(N,H), 0);&#xD;&#xA;    		color += ka * La + (kd * cost + (ks * pow(cosd, shininess)) * Le[i]) / pow(length(wLight[i]), 2);&#xD;&#xA;    	}&#xD;&#xA;    	vec3 gamma = vec3(1.0/2.2);&#xD;&#xA;    	fragmentColor = vec4(pow(color * vec3(texture2D(samplerUnit, texCoord)), gamma), 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oPH5d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13495" PostHistoryTypeId="50" PostId="4808" RevisionGUID="a913cae2-2fba-423d-8b07-c07cb22d835d" CreationDate="2017-05-07T16:00:50.640" UserId="-1" />
  <row Id="13497" PostHistoryTypeId="33" PostId="5067" RevisionGUID="3c549c3a-6ae8-40fc-9c2f-6b2a738da9b0" CreationDate="2017-05-07T19:57:47.340" UserId="5609" Comment="28" />
  <row Id="13498" PostHistoryTypeId="5" PostId="5071" RevisionGUID="fa658279-79e0-4c23-83be-9ed631e5335f" CreationDate="2017-05-07T21:10:09.950" UserId="231" Comment="Remove initial blank space" Text="I have a task to join two bezier curves, so that the resulting curve is two-times continuously differentiable.&lt;br&gt;&#xD;&#xA;I have the cubic bezier Curve C with control points:&lt;br&gt;&#xD;&#xA;c0 = (1,1)&lt;br&gt;&#xD;&#xA;c1 = (3,4)&lt;br&gt;&#xD;&#xA;c2 = (7,5)&lt;br&gt;&#xD;&#xA;c3 = (8,2)&lt;br&gt;&#xD;&#xA;I shall continue this curve C with Curve D from control point c3 to a control point d3 = (12,1) so that this curve is two-times continuously differentiable.&lt;br&gt;&#xD;&#xA;First Task: Determine control points d0, d1, d1 for the new curve.&#xD;&#xA;Second Task: Specify a pecewise defined formula for the new curve G(v) with v out of [0,1] that passes through c0,c3 and d3. Thus connect curves C and D in v = 1/2.&#xD;&#xA;Third Task: Prove by calculation that the transition between C and D is two-times continuously differentiable.&lt;br&gt;&lt;br&gt;&#xD;&#xA;Regarding first task: I don't know how to determine the points. Can someone help to do this? The rest of the tasks is then maybe something easier to do for me. Tank You!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13499" PostHistoryTypeId="2" PostId="5072" RevisionGUID="93fe68d7-0783-4c6d-b9e0-b0789cafa1df" CreationDate="2017-05-07T22:46:57.750" UserId="6589" Text="I'm currently enrolled in an entry level Computer Graphics class, and as I'm studying for my final, I realize I have a question regarding the Cohen-Sutherland line clipping algorithm. I understand the basics of the algorithm, such as how to compute the 4-bit outcodes associated with each region and the test conditions for the endpoints of a line segment, but where I'm struggling is how to determine what the worst case scenario is for the algorithm.&#xD;&#xA;&#xD;&#xA;**I've had the following question on both my midterm and a homework assignment: &quot;Draw two line segments (one with a positive slope and one with a negative slope) that reflect the worst case scenarios for the corresponding checking order.&quot;** &#xD;&#xA;&#xD;&#xA;The following image file shows what the checking order was for each question, along with my original answers to the questions followed by the correct answers. If anyone could point me in the right direction, it would be greatly appreciated. The only &quot;answer&quot; from my professor I received when asking for an explanation was &quot;the worst case has to do with the checking order&quot;, and that answers absolutely nothing for me.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/212kU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13500" PostHistoryTypeId="1" PostId="5072" RevisionGUID="93fe68d7-0783-4c6d-b9e0-b0789cafa1df" CreationDate="2017-05-07T22:46:57.750" UserId="6589" Text="Worst Case Scenario for Cohen-Sutherland Line Clipping Algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="13501" PostHistoryTypeId="3" PostId="5072" RevisionGUID="93fe68d7-0783-4c6d-b9e0-b0789cafa1df" CreationDate="2017-05-07T22:46:57.750" UserId="6589" Text="|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13505" PostHistoryTypeId="2" PostId="5074" RevisionGUID="39398395-ec38-4143-be0d-6cd2114471d1" CreationDate="2017-05-08T05:10:40.827" UserId="3003" Text="For 2 bezier curves to connect and be continuous at all, the last control point of the first curve (C in your case) must be the same as the first control point of the next curve (D). So c3 has to equal d0. That gives you [C0 continuity](https://en.wikipedia.org/wiki/Smoothness) or positional continuity.&#xD;&#xA;&#xD;&#xA;The next step is to make sure that the tangents where the 2 curves meet are the same. That will ensure c1 continuity. (That is continuity of the first derivatives of the 2 curves.) To do this, the slope must be equal at both points. In order to do that, you need to ensure that the line from c2 to c3/d0 is continuous with the line from c3/d0 to d1.&#xD;&#xA;&#xD;&#xA;I don't know of a good way to describe C2 continuity, but this [Stack Overflow answer](http://stackoverflow.com/questions/12295773/joining-two-bézier-curves-smoothly-c2-continuous) describes it better than I could. That answer should also explain the calculation you need for your proof." ContentLicense="CC BY-SA 3.0" />
  <row Id="13506" PostHistoryTypeId="2" PostId="5075" RevisionGUID="5d2c23f4-2e13-43b5-a315-d4299e9be7f8" CreationDate="2017-05-08T05:21:21.710" UserId="6579" Text="I used `MESA_DEBUG=1` (https://www.mesa3d.org/debugging.html https://www.mesa3d.org/envvars.html) and found out that `glEnable(TEXTURE_2D)` was causing the error.&#xD;&#xA;&#xD;&#xA;I don't know why it only got triggered on the `glDrawArrays` (maybe weird bindings) but when I removed that call it no longer failed with `GL_INVALID_ENUM`." ContentLicense="CC BY-SA 3.0" />
  <row Id="13507" PostHistoryTypeId="5" PostId="5071" RevisionGUID="7a7a5570-8605-4ef0-8c12-6776d9db47e2" CreationDate="2017-05-08T06:49:00.107" UserId="231" Comment="Remove thank you" Text="I have a task to join two bezier curves, so that the resulting curve is two-times continuously differentiable.&lt;br&gt;&#xD;&#xA;I have the cubic bezier Curve C with control points:&lt;br&gt;&#xD;&#xA;c0 = (1,1)&lt;br&gt;&#xD;&#xA;c1 = (3,4)&lt;br&gt;&#xD;&#xA;c2 = (7,5)&lt;br&gt;&#xD;&#xA;c3 = (8,2)&lt;br&gt;&#xD;&#xA;I shall continue this curve C with Curve D from control point c3 to a control point d3 = (12,1) so that this curve is two-times continuously differentiable.&lt;br&gt;&#xD;&#xA;First Task: Determine control points d0, d1, d1 for the new curve.&#xD;&#xA;Second Task: Specify a pecewise defined formula for the new curve G(v) with v out of [0,1] that passes through c0,c3 and d3. Thus connect curves C and D in v = 1/2.&#xD;&#xA;Third Task: Prove by calculation that the transition between C and D is two-times continuously differentiable.&lt;br&gt;&lt;br&gt;&#xD;&#xA;Regarding first task: I don't know how to determine the points. Can someone help to do this? The rest of the tasks is then maybe something easier to do for me." ContentLicense="CC BY-SA 3.0" />
  <row Id="13519" PostHistoryTypeId="2" PostId="5077" RevisionGUID="730bd3a4-6355-4350-9f25-3d4cc5aecb05" CreationDate="2017-05-08T18:43:25.410" UserId="110" Text="Are you trying to make your own rendering engine?   &#xA;  &#xA;Here is a solution that prioritizes visual quality ; it is slightly more complex than the object-based solution you are referring to.  &#xA;For better visual quality your shading should be on a per-pixel basis.  &#xA;(If you highly prioritize performance, or do not require detailed reflections, you should probably stick to the object-based solution though).&#xA;&#xA;  &#xA;If you are doing deferred rendering, instead of selecting only a single cubemap for each pixel, you can use a formula that combines all the cubemaps that are close enough to a pixel.  &#xA;   &#xA;A trick sometimes used to achieve this is to add a pass that computes the number of cubemaps that affect a single pixel (so you can do averages in the final shading pass).  &#xA;If you are doing forward rendering for transparent objects for example, I think it might be a bit trickier to compute the average of cubemaps.  &#xA;That's because you need to have pixel positions already available before shading ; you might think it could be possible to do it if you had a kind of depth pre-pass buffer for that purpose, however for transparent objects you usually do not want to write their depth in that buffer, because this leads to artifacts when transparent objects are overlapping.   &#xA;You would therefore need to have a rather complex logic to handle those cases...  &#xA;  &#xA;However even with forward rendering you can still select the closest cubemap on a per-pixel basis, although without the &quot;averaging&quot; formula the transitions between the boundaries of two cubemap influence zones will be very visible and reflections will not look realistic." ContentLicense="CC BY-SA 3.0" />
  <row Id="13520" PostHistoryTypeId="2" PostId="5078" RevisionGUID="d681aeea-3952-4cc7-a084-2013b7a8821d" CreationDate="2017-05-09T02:54:07.127" UserId="2308" Text="I am trying to recreate a filter that Facebook released back in 2015 when gay marriage was legalized in the US.&#xD;&#xA;&#xD;&#xA;Unfortunately, that filter no longer works/exists so people are left with only knockoff ones that dont do quite as good as a job. None of them manage to do quite what the actual one did espeically in the red, yellow, and purple stripes.&#xD;&#xA;&#xD;&#xA;I am trying to figure out what kind of filter they used to achieve this.&#xD;&#xA;&#xD;&#xA;I have tried a bunch of colors with each of the blend modes available in my photo editing software with no luck. Perhaps it is more complicated than just one math equation? Perhaps they processed the background image before putting on the overlay?&#xD;&#xA;&#xD;&#xA;I did find in the blog that the algorithm to achieve this was a O(n^2) algorithm but that is about all I know.&#xD;&#xA;&#xD;&#xA;Any ideas of what could have caused this?&#xD;&#xA;&#xD;&#xA;Below are some reference photos I used to attempt to find a pattern.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Example 1: Mark Zuckerburg (note this isn't exact. I couldn't perfectly recreate the crop they used)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Example 2: Facebook logo with colors pulled out on the right&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LNbOZ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/nYlfQ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13521" PostHistoryTypeId="1" PostId="5078" RevisionGUID="d681aeea-3952-4cc7-a084-2013b7a8821d" CreationDate="2017-05-09T02:54:07.127" UserId="2308" Text="What kind of image processing was used in the Facebook &quot;Celebrate Pride&quot; filter?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13522" PostHistoryTypeId="3" PostId="5078" RevisionGUID="d681aeea-3952-4cc7-a084-2013b7a8821d" CreationDate="2017-05-09T02:54:07.127" UserId="2308" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13523" PostHistoryTypeId="2" PostId="5079" RevisionGUID="70bab3d5-45b6-430e-82cf-8b1259a1a74c" CreationDate="2017-05-09T06:19:47.080" UserId="3073" Text="The top Zuckerberg image looks like you first convert your background Zuckerberg image to grayscale. Then you can add a second layer with the rainbow texture but use the 'Screen' blending mode, this will cause it to colourise the layers beneath it, but in such a way the whites are preserved. You could also try 'Multiply' mode too if the results are too bright.&#xD;&#xA;&#xD;&#xA;The second one with the facebook logo looks like alpha blending. This can be done using a default layer in photoshop but setting the layer opacity to some midway value, i'd guess around 75% opacity. In this version the rainbow texture is the background, and the layer contains the 'F' logo." ContentLicense="CC BY-SA 3.0" />
  <row Id="13524" PostHistoryTypeId="2" PostId="5080" RevisionGUID="7ee0ec89-2615-4782-bc36-6f663227233a" CreationDate="2017-05-09T07:01:58.150" UserId="5055" Text="A self-illuminating texture is rather easy. You can use the fragmentshader to increase the color value of those pixels.&#xD;&#xA;&#xD;&#xA;If you want a &quot;halo&quot;-like effect it gets more complicated. As Charlie said, you'd have to render in multiple passes. Render your texture only in a first pass, blur it and adjust color / brightness and put that information on top of your main render pass.&#xD;&#xA;&#xD;&#xA;If you even want your texture to illuminate surrounding objects it gets even more complicated. &#xD;&#xA;You could go for a texture projection for static purposes. Or you could average the texture information into one color and place an omni light in front of the emitting cube face.&#xD;&#xA;There are better solutions though, I am sure." ContentLicense="CC BY-SA 3.0" />
  <row Id="13525" PostHistoryTypeId="2" PostId="5081" RevisionGUID="0d46aaf0-83cc-4422-bf87-b20bddd72216" CreationDate="2017-05-09T09:48:45.650" UserId="5609" Text="I forgot to set the **wEye uniform**, so it was always **(0, 0, 0)**." ContentLicense="CC BY-SA 3.0" />
  <row Id="13526" PostHistoryTypeId="2" PostId="5082" RevisionGUID="7ead94f1-5e97-4927-a531-217f1b2a7fa8" CreationDate="2017-05-09T09:53:38.163" UserId="3073" Text="Presumably you are using a lighting system already, let's say Lambert shading for simplicity..&#xD;&#xA;&#xD;&#xA;So we have a texture which is going to be illuminated by some light source. The following psuedo/shader code will do lambert shading as normal..&#xD;&#xA;&#xD;&#xA;    diffuseIllum = lightColour * dot(normal, lightDir);&#xD;&#xA;    outputColour = textureColour.rgb * diffuseIllum;&#xD;&#xA;&#xD;&#xA;But we want certain parts of our texture to emit colours instead of being illuminated by only our light source.&#xD;&#xA;&#xD;&#xA;One method would be to use an extra channel in the input texture, say the Alpha channel, to control which pixels are emissive&#xD;&#xA;&#xD;&#xA;    diffuseIllum = lightColour * dot(normal, lightDir);&#xD;&#xA;    outputColor = mix(textureColour.rgb * diffuseIllum, textureColour.rgb, texture.a);&#xD;&#xA;&#xD;&#xA;Unfortunately this won't work so well if you want say a dark red glow because the output pixel will either be the emissive colour (dark red) or the lit texture colour, which could be much brighter. In effect our emissive areas could end up darker than the surrounding illuminated areas.&#xD;&#xA;&#xD;&#xA;We could add the emissive colour to the illuminated texture but that limits how much control over final colour we have.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    outputColour = textureColour.rgb * diffuseIllum + textureColour.rgb * textureColour.a;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13527" PostHistoryTypeId="5" PostId="5082" RevisionGUID="68ac45c0-66f5-43d3-a242-a78176d2e011" CreationDate="2017-05-09T10:01:10.883" UserId="3073" Comment="added 268 characters in body" Text="Presumably you are using a lighting system already, let's say Lambert shading for simplicity..&#xD;&#xA;&#xD;&#xA;So we have a texture which is going to be illuminated by some light source. The following psuedo/shader code will do lambert shading as normal..&#xD;&#xA;&#xD;&#xA;    diffuseIllum = lightColour * dot(normal, lightDir);&#xD;&#xA;    outputColour = textureColour.rgb * diffuseIllum;&#xD;&#xA;&#xD;&#xA;But we want certain parts of our texture to emit colours instead of being illuminated by only our light source.&#xD;&#xA;&#xD;&#xA;One method would be to use an extra channel in the input texture, say the Alpha channel, to control which pixels are emissive&#xD;&#xA;&#xD;&#xA;    diffuseIllum = lightColour * dot(normal, lightDir);&#xD;&#xA;    outputColor = mix(textureColour.rgb * diffuseIllum, textureColour.rgb, texture.a);&#xD;&#xA;&#xD;&#xA;Unfortunately this won't work so well if you want say a dark red glow because the output pixel will either be the emissive colour (dark red) or the lit texture colour, which could be much brighter. In effect our emissive areas could end up darker than the surrounding illuminated areas.&#xD;&#xA;&#xD;&#xA;We could add the emissive colour to the illuminated texture but that limits how much control over final colour we have.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    outputColour = textureColour.rgb * diffuseIllum + textureColour.rgb * textureColour.a;&#xD;&#xA;&#xD;&#xA;A more correct method would involve using 2 textures, one for diffuse illumination and another for purely emissive. These would be added together in the pixel shader.&#xD;&#xA;&#xD;&#xA;e.g. &#xD;&#xA;&#xD;&#xA;     outputColour = textureColour.rgb * diffuseIllum + emissiveTextureColour.rgb;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13531" PostHistoryTypeId="2" PostId="5085" RevisionGUID="89fe95ce-3846-44db-ac0c-a6810b9c8fda" CreationDate="2017-05-09T14:44:27.940" UserId="6603" Text="You can calculate subjective brightness of an RGB value by weighting the three channels according to their perceived brightness, e.g. with something like:&#xD;&#xA;&#xD;&#xA;    (0.21 × R) + (0.72 × G) + (0.07 × B)&#xD;&#xA;&#xD;&#xA;But, ignoring human biology and perception, is there an accepted way to calculate the objective, theoretical &quot;light intensity&quot; of an RGB value? (Theoretical because the real value will vary between displays)&#xD;&#xA;&#xD;&#xA;My first thought, given that the RGB values correspond to the intensity of the pixel's three lights, is to take the average: &#xD;&#xA;&#xD;&#xA;    (R + G + B) ÷ 3&#xD;&#xA;&#xD;&#xA;So, for instance, that makes yellow (`#ffff00`) twice as intense as red (`#ff0000`). &#xD;&#xA;&#xD;&#xA;That makes sense, thinking about two lights being on rather than one, but looking at the colours I would have guessed they were of somewhat equal intensity. &#xD;&#xA;&#xD;&#xA;Unlike dark yellow (`#808000`) which actually is equal to the red in intensity! &#xD;&#xA;&#xD;&#xA;I suspect there isn't a linear relationship which is confusing the issue.&#xD;&#xA;&#xD;&#xA;**Can objective light intensity be calculated from an RGB value?**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13532" PostHistoryTypeId="1" PostId="5085" RevisionGUID="89fe95ce-3846-44db-ac0c-a6810b9c8fda" CreationDate="2017-05-09T14:44:27.940" UserId="6603" Text="&quot;Light intensity&quot; of an RGB value" ContentLicense="CC BY-SA 3.0" />
  <row Id="13533" PostHistoryTypeId="3" PostId="5085" RevisionGUID="89fe95ce-3846-44db-ac0c-a6810b9c8fda" CreationDate="2017-05-09T14:44:27.940" UserId="6603" Text="|color-science|brightness|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13534" PostHistoryTypeId="5" PostId="5085" RevisionGUID="df6f6fcd-f085-4c14-9d6d-fdb967313454" CreationDate="2017-05-09T15:18:56.960" UserId="6603" Comment="[Edit removed during grace period]" Text="You can calculate subjective brightness of an RGB value by weighting the three channels according to their perceived brightness, e.g. with something like:&#xD;&#xA;&#xD;&#xA;    (0.21 × R) + (0.72 × G) + (0.07 × B)&#xD;&#xA;&#xD;&#xA;But, ignoring human biology and perception, is there an accepted way to calculate the objective, theoretical &quot;light intensity&quot; of an RGB value? (Theoretical because the real value will vary between displays)&#xD;&#xA;&#xD;&#xA;My first thought, given that the RGB values correspond to the intensity of the pixel's three lights, is to take the average: &#xD;&#xA;&#xD;&#xA;    (R + G + B) ÷ 3&#xD;&#xA;&#xD;&#xA;So, for instance, that makes yellow (`#ffff00`) twice as intense as red (`#ff0000`). &#xD;&#xA;&#xD;&#xA;That makes sense, thinking about two lights being on rather than one, but looking at the colours I would have guessed they were of somewhat equal intensity. &#xD;&#xA;&#xD;&#xA;Unlike dark yellow (`#808000`) which actually is equal to the red in intensity! &#xD;&#xA;&#xD;&#xA;I suspect there isn't a linear relationship which is confusing the issue.&#xD;&#xA;&#xD;&#xA;**Can objective light intensity be calculated from an RGB value?**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13536" PostHistoryTypeId="5" PostId="5085" RevisionGUID="aa0f3982-9040-414d-a819-0d169586eae2" CreationDate="2017-05-09T15:34:32.883" UserId="6603" Comment="clarify terminology" Text="*EDIT: I'm not fully clear on terminology here, what I previously understood to be called &quot;brightness&quot; seems poorly defined. I think I am asking about [radiant intensity](https://en.wikipedia.org/wiki/Radiant_intensity), that is, the measurable intensity of energy emitted, not weighted for subjective perception.*&#xD;&#xA;&#xD;&#xA;You can calculate subjective brightness of an RGB value by weighting the three channels according to their perceived brightness, e.g. with something like:&#xD;&#xA;&#xD;&#xA;    (0.21 × R) + (0.72 × G) + (0.07 × B)&#xD;&#xA;&#xD;&#xA;But, ignoring human biology and perception, is there an accepted way to calculate the objective, theoretical &quot;light intensity&quot; of an RGB value? (Theoretical because the real value will vary between displays)&#xD;&#xA;&#xD;&#xA;My first thought, given that the RGB values correspond to the intensity of the pixel's three lights, is to take the average: &#xD;&#xA;&#xD;&#xA;    (R + G + B) ÷ 3&#xD;&#xA;&#xD;&#xA;So, for instance, that makes yellow (`#ffff00`) twice as intense as red (`#ff0000`). &#xD;&#xA;&#xD;&#xA;That makes sense, thinking about two lights being on rather than one, but looking at the colours I would have guessed they were of somewhat equal intensity. &#xD;&#xA;&#xD;&#xA;Unlike dark yellow (`#808000`) which actually is equal to the red in intensity! &#xD;&#xA;&#xD;&#xA;I suspect there isn't a linear relationship which is confusing the issue.&#xD;&#xA;&#xD;&#xA;**Can objective light intensity be calculated from an RGB value?**&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13537" PostHistoryTypeId="2" PostId="5086" RevisionGUID="0e36f730-f61e-438f-82a2-b7e7cec5d947" CreationDate="2017-05-09T20:27:31.777" UserId="6596" Text="[![per vertex operation][2]][2]&#xD;&#xA;[![offset triangles][1]][1]&#xD;&#xA;&#xD;&#xA;I need to offset all triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges.&#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hN8dz.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13538" PostHistoryTypeId="1" PostId="5086" RevisionGUID="0e36f730-f61e-438f-82a2-b7e7cec5d947" CreationDate="2017-05-09T20:27:31.777" UserId="6596" Text="How can I offset/shrink a triangular polygon in GLSL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13539" PostHistoryTypeId="3" PostId="5086" RevisionGUID="0e36f730-f61e-438f-82a2-b7e7cec5d947" CreationDate="2017-05-09T20:27:31.777" UserId="6596" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13542" PostHistoryTypeId="5" PostId="5086" RevisionGUID="9e9b530d-4923-47f8-a820-2c461fc5dcde" CreationDate="2017-05-09T23:08:43.710" UserId="6596" Comment="clarified by request ion comments" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges.&#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="13543" PostHistoryTypeId="5" PostId="5086" RevisionGUID="294637eb-13b3-401c-955c-57e935fcbeaa" CreationDate="2017-05-10T02:03:59.253" UserId="6596" Comment="added 135 characters in body" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="13544" PostHistoryTypeId="2" PostId="5087" RevisionGUID="581b1e28-1747-4626-8867-d6f5bc8259e6" CreationDate="2017-05-10T03:09:24.577" UserId="5521" Text="I am trying to write a simple WebGL script to display a pyramid with a brick texture and Phong lighting. The lighting works fine but when I incorporate the texture, the pyramid turns black. I've checked and set my parameters to use with power-of-two textures since my texture is 512x512. This scene should be straight out of the the Mozilla WebGL examples but some reason it is not working. I am now desperate and cannot figure out why adding textures objects black. Below is my code.&#xD;&#xA;&#xD;&#xA;        &lt;html&gt;&#xD;&#xA;        &lt;head&gt;&#xD;&#xA;        &lt;title&gt;WebGL Simple Pyramid&lt;/&#xD;&#xA;&#xD;&#xA;        CanvasMatrix class&#xD;&#xA;        (c) Apple Inc&#xD;&#xA;        --&gt;&#xD;&#xA;        &lt;script src=&quot;CanvasMatrix.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;&#xD;&#xA;&#xD;&#xA;        &lt;!--&#xD;&#xA;          Vertex shader&#xD;&#xA;        --&gt;&#xD;&#xA;        &lt;script id=&quot;shader-vs&quot; type=&quot;x-shader/x-vertex&quot;&gt; &#xD;&#xA;           precision highp float;&#xD;&#xA;           attribute vec3 XYZ;&#xD;&#xA;           attribute vec3 RGB;&#xD;&#xA;           attribute vec3 NOR;&#xD;&#xA;           attribute vec2 TEX;&#xD;&#xA;           uniform mat4 ProjectionMatrix;&#xD;&#xA;           uniform mat4 ModelviewMatrix;&#xD;&#xA;           varying vec3 col;&#xD;&#xA;           varying vec2 tex;&#xD;&#xA;           vec3 ambient = vec3(0.3, 0.3, 0.3);&#xD;&#xA;           vec3 diffuse = vec3(1.0, 1.0, 1.0);&#xD;&#xA;           vec3 specular = vec3(1.0, 1.0, 1.0);&#xD;&#xA;           vec4 position = vec4(-2.0, 1.0, -2.0, 1.0);&#xD;&#xA;           void main(void)&#xD;&#xA;           {&#xD;&#xA;	           //  P is the vertex coordinate on body&#xD;&#xA;	           vec3 P = vec3(ModelviewMatrix * vec4(XYZ, 1));&#xD;&#xA;	           //  N is the object normal at P&#xD;&#xA;	           vec4 norm = normalize(ModelviewMatrix * vec4(NOR, 1));&#xD;&#xA;	           vec3 N = vec3(norm.xyz);&#xD;&#xA;	           //  L is the light vector&#xD;&#xA;	           vec3 L = normalize(vec3(ModelviewMatrix*position) - P);&#xD;&#xA;	           //  Emission and ambient color&#xD;&#xA;	           vec3 color = ambient;&#xD;&#xA;	           //  Diffuse light intensity is cosine of light and normal vectors&#xD;&#xA;	           float Id = dot(L,N);&#xD;&#xA;	           if (Id&gt;0.0)&#xD;&#xA;	           {&#xD;&#xA;	              //  Add diffuse&#xD;&#xA;	              color += Id*diffuse;&#xD;&#xA;	              //  R is the reflected light vector R = 2(L.N)N - L&#xD;&#xA;	              vec3 R = reflect(-L, N);&#xD;&#xA;	              //  V is the view vector (eye at the origin)&#xD;&#xA;	              vec3 V = normalize(-P);&#xD;&#xA;	              //  Specular is cosine of reflected and view vectors&#xD;&#xA;	              float Is = dot(R,V);&#xD;&#xA;	              if (Is&gt;0.0) color += pow(Is,32.0)*specular;&#xD;&#xA;	           }&#xD;&#xA;	           //  Pass color to fragment shader&#xD;&#xA;	           col = color*RGB;&#xD;&#xA;	           //  Pass texture coordinates to fragment shader (will be interpolated)&#xD;&#xA;	           tex = TEX;&#xD;&#xA;	           //  Set transformed vertex location&#xD;&#xA;	           gl_Position = ProjectionMatrix * ModelviewMatrix *            vec4(XYZ,1);&#xD;&#xA;           }&#xD;&#xA;        &lt;/script&gt; &#xD;&#xA; &#xD;&#xA;        &lt;!--&#xD;&#xA;          Fragment shader&#xD;&#xA;          --&gt;&#xD;&#xA;        &lt;script id=&quot;shader-fs&quot; type=&quot;x-shader/x-fragment&quot;&gt; &#xD;&#xA;           precision highp float;&#xD;&#xA;           varying vec3 col;&#xD;&#xA;           varying vec2 tex;&#xD;&#xA;           uniform sampler2D uSampler;&#xD;&#xA;           void main(void)&#xD;&#xA;           {&#xD;&#xA;              gl_FragColor = vec4(col,1) * texture2D(uSampler, tex);&#xD;&#xA;           }&#xD;&#xA;        &lt;/script&gt; &#xD;&#xA;&#xD;&#xA;        &lt;!--&#xD;&#xA;          WebGL program&#xD;&#xA;          --&gt;&#xD;&#xA;        &lt;script type=&quot;text/javascript&quot;&gt; &#xD;&#xA;&#xD;&#xA;        //&#xD;&#xA;        //  Compile a shader&#xD;&#xA;        //&#xD;&#xA;        function CompileShader(gl,id)&#xD;&#xA;        {&#xD;&#xA;           //  Get shader by id&#xD;&#xA;           var src = document.getElementById(id);&#xD;&#xA;           //  Create shader based on type setting&#xD;&#xA;           var shader;&#xD;&#xA;           if (src.type == &quot;x-shader/x-fragment&quot;)&#xD;&#xA;              shader = gl.createShader(gl.FRAGMENT_SHADER);&#xD;&#xA;           else if (src.type == &quot;x-shader/x-vertex&quot;)&#xD;&#xA;              shader = gl.createShader(gl.VERTEX_SHADER);&#xD;&#xA;           else&#xD;&#xA;              return null;&#xD;&#xA;           //  Read source into str&#xD;&#xA;           var str = &quot;&quot;;&#xD;&#xA;           var k = src.firstChild;&#xD;&#xA;           while (k)&#xD;&#xA;           {&#xD;&#xA;              if (k.nodeType == 3) str += k.textContent;&#xD;&#xA;              k = k.nextSibling;&#xD;&#xA;           }&#xD;&#xA;           gl.shaderSource(shader, str);&#xD;&#xA;           //  Compile the shader&#xD;&#xA;           gl.compileShader(shader);&#xD;&#xA;           //  Check for errors&#xD;&#xA;           if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) == 0)&#xD;&#xA;              alert(gl.getShaderInfoLog(shader));&#xD;&#xA;           //  Return shader&#xD;&#xA;           return shader;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        //&#xD;&#xA;        //  Compile shader program&#xD;&#xA;        //&#xD;&#xA;        function CompileShaderProg(gl,vert,frag)&#xD;&#xA;        {&#xD;&#xA;           //  Compile the program&#xD;&#xA;           var prog  = gl.createProgram();&#xD;&#xA;           gl.attachShader(prog , CompileShader(gl,vert));&#xD;&#xA;           gl.attachShader(prog , CompileShader(gl,frag));&#xD;&#xA;           gl.linkProgram(prog);&#xD;&#xA;           //  Check for errors&#xD;&#xA;           if (gl.getProgramParameter(prog, gl.LINK_STATUS) == 0)&#xD;&#xA;              alert(gl.getProgramInfoLog(prog));&#xD;&#xA;           //  Return program&#xD;&#xA;           return prog;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        var text;&#xD;&#xA;        var image;&#xD;&#xA;        function initTexture() &#xD;&#xA;        {&#xD;&#xA;           text = gl.createTexture();&#xD;&#xA;           image = new Image();&#xD;&#xA;           image.onload = function() {handleTextureLoaded(text, image)}&#xD;&#xA;           image.src = &quot;wall.png&quot;;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        function handleTextureLoaded(txt, img) &#xD;&#xA;        {&#xD;&#xA;           gl.bindTexture(gl.TEXTURE_2D, txt);&#xD;&#xA;           gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);&#xD;&#xA;           gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);&#xD;&#xA;           gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);&#xD;&#xA;           gl.generateMipmap(gl.TEXTURE_2D);&#xD;&#xA;           gl.bindTexture(gl.TEXTURE_2D, null);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        var gl,canvas;&#xD;&#xA;        function webGLStart()&#xD;&#xA;        {&#xD;&#xA;           //  Set canvas&#xD;&#xA;           canvas = document.getElementById(&quot;canvas&quot;);&#xD;&#xA;           //  Select canvas size&#xD;&#xA;           var size = Math.min(window.innerWidth,window.innerHeight)-10;&#xD;&#xA;           canvas.width  = size;&#xD;&#xA;           canvas.height = size;&#xD;&#xA;           //  Start WebGL&#xD;&#xA;           if (!window.WebGLRenderingContext)&#xD;&#xA;           {&#xD;&#xA;              alert(&quot;Your browser does not support WebGL. See http://get.webgl.org&quot;);&#xD;&#xA;              return;&#xD;&#xA;           }&#xD;&#xA;           try&#xD;&#xA;           {&#xD;&#xA;              gl = canvas.getContext(&quot;experimental-webgl&quot;);&#xD;&#xA;           }&#xD;&#xA;           catch(e)&#xD;&#xA;           {}&#xD;&#xA;           if (!gl)&#xD;&#xA;           {&#xD;&#xA;              alert(&quot;Can't get WebGL&quot;);&#xD;&#xA;              return;&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;           //  Set viewport to entire canvas&#xD;&#xA;           gl.viewport(0,0,size,size);&#xD;&#xA;&#xD;&#xA;           //  Initialize textures&#xD;&#xA;           initTexture();&#xD;&#xA;&#xD;&#xA;           //  Load Shader&#xD;&#xA;           var prog = CompileShaderProg(gl,&quot;shader-vs&quot;,&quot;shader-fs&quot;);&#xD;&#xA;&#xD;&#xA;           //  Set program&#xD;&#xA;           gl.useProgram(prog);&#xD;&#xA;&#xD;&#xA;           //  Set projection&#xD;&#xA;           var ProjectionMatrix = new CanvasMatrix4();&#xD;&#xA;           ProjectionMatrix.ortho(-2.5,+2.5,-2.5,+2.5,-2.5,+2.5);&#xD;&#xA;&#xD;&#xA;           //  Vertex array count&#xD;&#xA;           var n = 18;&#xD;&#xA;           //  Pyramid vertex coordinates&#xD;&#xA;           var xyz = &#xD;&#xA;           [&#xD;&#xA;        	-1,-1,-1,	1,-1,-1,	-1,-1,1,&#xD;&#xA;        	1,-1,-1,	-1,-1,1,	1,-1,1,&#xD;&#xA;        	0,1,0,		-1,-1,1,	1,-1,1,&#xD;&#xA;        	0,1,0,		1,-1,-1,	-1,-1,-1,&#xD;&#xA;        	0,1,0,		1,-1,1,		1,-1,-1,&#xD;&#xA;        	0,1,0,		-1,-1,-1,	-1,-1,1,&#xD;&#xA;           ];&#xD;&#xA;           var verts = gl.createBuffer();&#xD;&#xA;           gl.bindBuffer(gl.ARRAY_BUFFER,verts);&#xD;&#xA;           gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(xyz),gl.STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;           //  Pyramid colors&#xD;&#xA;           var rgb = &#xD;&#xA;           [&#xD;&#xA;        	0.84,0.62,0.32,	0.84,0.62,0.32,	0.84,0.62,0.32,&#xD;&#xA;        	0.84,0.62,0.32, 0.84,0.62,0.32,	0.84,0.62,0.32,    &#xD;&#xA;        	0.84,0.62,0.32,	0.84,0.62,0.32,	0.84,0.62,0.32,&#xD;&#xA;        	0.84,0.62,0.32,	0.84,0.62,0.32,	0.84,0.62,0.32,&#xD;&#xA;        	0.84,0.62,0.32,	0.84,0.62,0.32,	0.84,0.62,0.32,&#xD;&#xA;        	0.84,0.62,0.32,	0.84,0.62,0.32,	0.84,0.62,0.32,&#xD;&#xA;           ];&#xD;&#xA;           var color = gl.createBuffer();&#xD;&#xA;           gl.bindBuffer(gl.ARRAY_BUFFER,color);&#xD;&#xA;           gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(rgb),gl.STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;           //  Pyramid texture coordinates&#xD;&#xA;           var tex =&#xD;&#xA;           [&#xD;&#xA;	        0,0,	4,0,	0,4,&#xD;&#xA;	        4,0,	0,4,	4,4,&#xD;&#xA;	        2,4,	0,0,	4,0,&#xD;&#xA;	        2,4,	0,0,	4,0,&#xD;&#xA;	        2,4,	0,0,	4,0,&#xD;&#xA;	        2,4,	0,0,	4,0,&#xD;&#xA;           ];&#xD;&#xA;           var texture = gl.createBuffer();&#xD;&#xA;           gl.bindBuffer(gl.ARRAY_BUFFER,texture);&#xD;&#xA;           gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(tex),gl.STATIC_DRAW); &#xD;&#xA;   &#xD;&#xA;           //  Cube normals&#xD;&#xA;           var nor =&#xD;&#xA;           [&#xD;&#xA;        	0,-1, 0,					0,-1, 0,					0,-1, 0,&#xD;&#xA;        	0,-1, 0,					0,-1, 0,					0,-1, 0,&#xD;&#xA;	        0,0.4472136,0.89442719,		0,0.4472136,0.89442719,		0,0.4472136,0.89442719,&#xD;&#xA;	        0,0.4472136,-0.89442719,	0,0.4472136,-0.89442719,	0,0.4472136,-0.89442719,&#xD;&#xA;	        0.89442719,0.4472136,0,		0.89442719,0.4472136,0,		0.89442719,0.4472136,0,&#xD;&#xA;        	-0.89442719,0.4472136,0,	-0.89442719,0.4472136,0,	-0.89442719,0.4472136,0,&#xD;&#xA;           ];&#xD;&#xA;           var normals = gl.createBuffer();&#xD;&#xA;           gl.bindBuffer(gl.ARRAY_BUFFER,normals);&#xD;&#xA;           gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(nor),gl.STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;           //  Set state to draw scene&#xD;&#xA;           gl.enable(gl.DEPTH_TEST);&#xD;&#xA;           gl.clearColor(0.8,0.8,0.8,1);&#xD;&#xA;           //  Mouse control variables&#xD;&#xA;           var x0 = y0 = move  = 0;&#xD;&#xA;           //  Rotation angles&#xD;&#xA;           var th = ph = 15;&#xD;&#xA;           //  Draw scene the first time&#xD;&#xA;           Display();&#xD;&#xA;&#xD;&#xA;           //&#xD;&#xA;           //  Display the scene&#xD;&#xA;           //&#xD;&#xA;           function Display()&#xD;&#xA;           {&#xD;&#xA;              //  Clear the screen and Z buffer&#xD;&#xA;              gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;              // Compute modelview matrix&#xD;&#xA;              var ModelviewMatrix = new CanvasMatrix4();&#xD;&#xA;              ModelviewMatrix.makeIdentity();&#xD;&#xA;              ModelviewMatrix.rotate(ph,0,1,0);&#xD;&#xA;              ModelviewMatrix.rotate(th,1,0,0);&#xD;&#xA;&#xD;&#xA;              // Set shader&#xD;&#xA;              gl.useProgram(prog);&#xD;&#xA;&#xD;&#xA;              //  Set projection and modelview matrixes&#xD;&#xA;                     gl.uniformMatrix4fv(gl.getUniformLocation(prog,&quot;ProjectionMatrix&quot;) , false , new Float32Array(ProjectionMatrix.getAsArray()));&#xD;&#xA;      gl.uniformMatrix4fv(gl.getUniformLocation(prog,&quot;ModelviewMatrix&quot;)  , false , new Float32Array(ModelviewMatrix.getAsArray()));&#xD;&#xA;&#xD;&#xA;      //  Set up 3D vertex array&#xD;&#xA;      gl.bindBuffer(gl.ARRAY_BUFFER,verts);&#xD;&#xA;      var XYZ = gl.getAttribLocation(prog,&quot;XYZ&quot;);&#xD;&#xA;      gl.enableVertexAttribArray(XYZ);&#xD;&#xA;      gl.vertexAttribPointer(XYZ,3,gl.FLOAT,false,0,0);&#xD;&#xA;&#xD;&#xA;      //  Set up 3D color array&#xD;&#xA;      gl.bindBuffer(gl.ARRAY_BUFFER,color);&#xD;&#xA;      var RGB = gl.getAttribLocation(prog,&quot;RGB&quot;);&#xD;&#xA;      gl.enableVertexAttribArray(RGB);&#xD;&#xA;      gl.vertexAttribPointer(RGB,3,gl.FLOAT,false,0,0);&#xD;&#xA;      &#xD;&#xA;      //  Set up 3D normal array&#xD;&#xA;      gl.bindBuffer(gl.ARRAY_BUFFER,normals);&#xD;&#xA;      var NOR = gl.getAttribLocation(prog,&quot;NOR&quot;);&#xD;&#xA;      gl.enableVertexAttribArray(NOR);&#xD;&#xA;      gl.vertexAttribPointer(NOR,3,gl.FLOAT,false,0,0);&#xD;&#xA;      &#xD;&#xA;      //  Set up 2D texture array&#xD;&#xA;      gl.bindBuffer(gl.ARRAY_BUFFER,texture);&#xD;&#xA;      var TEX = gl.getAttribLocation(prog,&quot;TEX&quot;);&#xD;&#xA;      gl.enableVertexAttribArray(TEX);&#xD;&#xA;      gl.vertexAttribPointer(TEX,2,gl.FLOAT,false,0,0);&#xD;&#xA;&#xD;&#xA;      gl.activeTexture(gl.TEXTURE0);&#xD;&#xA;      gl.bindTexture(gl.TEXTURE_2D, text);&#xD;&#xA;      gl.uniform1i(gl.getUniformLocation(prog, &quot;uSampler&quot;), 0);&#xD;&#xA;&#xD;&#xA;      //  Draw all vertexes&#xD;&#xA;      gl.drawArrays(gl.TRIANGLES,0,n);&#xD;&#xA;&#xD;&#xA;      //  Disable vertex arrays&#xD;&#xA;      gl.disableVertexAttribArray(XYZ);&#xD;&#xA;      gl.disableVertexAttribArray(RGB);&#xD;&#xA;      gl.disableVertexAttribArray(NOR);&#xD;&#xA;      gl.disableVertexAttribArray(TEX);&#xD;&#xA;&#xD;&#xA;      //  Flush&#xD;&#xA;      gl.flush();&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;           //&#xD;&#xA;           //  Resize canvas&#xD;&#xA;           //&#xD;&#xA;           canvas.resize = function ()&#xD;&#xA;           {&#xD;&#xA;              var size = Math.min(window.innerWidth, window.innerHeight)-10;&#xD;&#xA;              canvas.width  = size;&#xD;&#xA;              canvas.height = size;&#xD;&#xA;              gl.viewport(0,0,size,size);&#xD;&#xA;              Display();&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;           //&#xD;&#xA;           //  Mouse button pressed&#xD;&#xA;           //&#xD;&#xA;           canvas.onmousedown = function (ev)&#xD;&#xA;           {&#xD;&#xA;              move  = 1;&#xD;&#xA;              x0 = ev.clientX;&#xD;&#xA;              y0 = ev.clientY;&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;           //&#xD;&#xA;           //  Mouse button released&#xD;&#xA;           //&#xD;&#xA;           canvas.onmouseup = function (ev)&#xD;&#xA;           {&#xD;&#xA;              move  = 0;&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;           //&#xD;&#xA;           //  Mouse movement&#xD;&#xA;           //&#xD;&#xA;           canvas.onmousemove = function (ev)&#xD;&#xA;           {&#xD;&#xA;              if (move==0) return;&#xD;&#xA;              //  Update angles&#xD;&#xA;              ph -= ev.clientX-x0;&#xD;&#xA;              th += ev.clientY-y0;&#xD;&#xA;              //  Store location&#xD;&#xA;              x0 = ev.clientX;&#xD;&#xA;              y0 = ev.clientY;&#xD;&#xA;              //  Redisplay&#xD;&#xA;              Display();&#xD;&#xA;           }&#xD;&#xA;        }&#xD;&#xA;        &lt;/script&gt; &#xD;&#xA;&#xD;&#xA;        &lt;!--&#xD;&#xA;          Web page&#xD;&#xA;          --&gt;&#xD;&#xA;        &lt;/head&gt;&#xD;&#xA;        &lt;body onload=&quot;webGLStart();&quot; onresize=&quot;canvas.resize();&quot;&gt; &#xD;&#xA;        &lt;H1&gt;WebGL Simple Pyramid&lt;/H1&gt;&#xD;&#xA;        &lt;canvas id=&quot;canvas&quot; width=&quot;500&quot; height=&quot;500&quot;&gt;&lt;/canvas&gt; &#xD;&#xA;        &lt;/body&gt;&#xD;&#xA;        &lt;/html&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13545" PostHistoryTypeId="1" PostId="5087" RevisionGUID="581b1e28-1747-4626-8867-d6f5bc8259e6" CreationDate="2017-05-10T03:09:24.577" UserId="5521" Text="WebGL: Why are my textures black?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13546" PostHistoryTypeId="3" PostId="5087" RevisionGUID="581b1e28-1747-4626-8867-d6f5bc8259e6" CreationDate="2017-05-10T03:09:24.577" UserId="5521" Text="|opengl|texture|webgl|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13547" PostHistoryTypeId="2" PostId="5088" RevisionGUID="2100ee79-8e49-4e65-9f96-9ae80470b103" CreationDate="2017-05-10T07:50:43.090" UserId="6606" Text="&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/V1N2t.png&quot; width=&quot;300&quot; height=&quot;250&quot;&gt;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/AtyZf.jpg&quot; width=&quot;300&quot; height=&quot;250&quot;&gt;&lt;br/&gt;&#xD;&#xA;Above on the left is my attempt and on the right is what I'm aiming for.As you can see my sphere with the specular brdf is far too &quot;shiny&quot;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;In my radiance function I am recursing through the intersected objects with the next intersection from the ray that's being traced. I'm using russian roulette with a depth of 5 to avoid infinite recursion. After this I find a point of intersection `Vec y` and calculate the normal there. After this I sample the brdf, which in this case is specular, to get the incoming direction vector, stored in i. Finally I call the function using a new ray with the point of intersection and -i.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;I have a feeling the my error is with my normal vector n being sent to brdf.eval or brdf.sample. I am not sure if the normal is supposed to be the normal at the origin of the ray, r.o, or at the intersection point y. When I try changing it the specular sphere ends up completely black, or my diffuse brdf for the rest of the scene becomes incorrect.&#xD;&#xA;&#xD;&#xA;    Vec receivedRadiance(const Ray &amp;r, int depth, bool flag) {&#xD;&#xA;	double t, p;                                   // Distance to intersection/pdf&#xD;&#xA;	int id = 0;                                 // id of intersected sphere&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;	if (!intersect(r, t, id)) return Vec();   // if miss, return black&#xD;&#xA;	const Sphere &amp;obj = spheres[id];            // the hit object&#xD;&#xA;	Vec rad = obj.e;							// Emitted radiance&#xD;&#xA;&#xD;&#xA;	if (depth &lt;= 5)&#xD;&#xA;		p = 1.0;&#xD;&#xA;	else&#xD;&#xA;		p = .9;&#xD;&#xA;&#xD;&#xA;	if (rng() &lt; p)&#xD;&#xA;	{&#xD;&#xA;		Vec i;&#xD;&#xA;		Vec y = r.o + r.d*t;                        // The intersection point&#xD;&#xA;		Vec n = (y - obj.p).normalize();            // The normal direction&#xD;&#xA;		if (n.dot(r.d) &lt; 0) n = n*-1.0;                   &#xD;&#xA;		const BRDF &amp;brdf = obj.brdf;                // Surface BRDF at x&#xD;&#xA;		brdf.sample(n, r.d, i, p);&#xD;&#xA;		rad = rad + (receivedRadiance(Ray(y, Vec() - i.normalize()), depth + 1, true) * (PI)).mult(brdf.eval(n, r.d, i));&#xD;&#xA;		rad = rad * (1 / p);&#xD;&#xA;	}&#xD;&#xA;	return rad;}&#xD;&#xA;&#xD;&#xA;Here is my specular BRDF struct:&#xD;&#xA;&#xD;&#xA;    struct SpecularBRDF : public BRDF {&#xD;&#xA;	SpecularBRDF(Vec ks_) : ks(ks_) {}&#xD;&#xA;	&#xD;&#xA;	Vec eval(const Vec &amp;n, const Vec &amp;o, const Vec &amp;i) const {&#xD;&#xA;		Vec m;&#xD;&#xA;		mirroredDir(n, o, m);&#xD;&#xA;		if (abs(i.x - m.x) &lt; 1e-5 &amp;&amp; abs(i.y - m.y) &lt; 1e-5 &amp;&amp; abs(i.z - m.z) &lt; 1e-5) //i == m&#xD;&#xA;			return ks * (1 / n.dot(i));&#xD;&#xA;		else&#xD;&#xA;			return Vec(0.0, 0.0, 0.0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void sample(const Vec &amp;n, const Vec &amp;o, Vec &amp;i, double &amp;pdf) const {&#xD;&#xA;		mirroredDir(n, o, i);&#xD;&#xA;		pdf = 1.0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	Vec ks;}&#xD;&#xA;And my mirrorDir function:&#xD;&#xA;&#xD;&#xA;    inline void mirroredDir(const Vec &amp;n, const Vec &amp;o, Vec &amp;m){&#xD;&#xA;	m = n * 2.0 * (n.dot(o)) - o;}&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V1N2t.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/AtyZf.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13548" PostHistoryTypeId="1" PostId="5088" RevisionGUID="2100ee79-8e49-4e65-9f96-9ae80470b103" CreationDate="2017-05-10T07:50:43.090" UserId="6606" Text="Problem with specular BRDF (Monte Carlo &amp; Path Tracing)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13549" PostHistoryTypeId="3" PostId="5088" RevisionGUID="2100ee79-8e49-4e65-9f96-9ae80470b103" CreationDate="2017-05-10T07:50:43.090" UserId="6606" Text="|raytracing|c++|pathtracing|specular|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13553" PostHistoryTypeId="2" PostId="5090" RevisionGUID="e4424f6a-c87c-43ea-ab9a-bcbab8dd5d9d" CreationDate="2017-05-10T13:33:27.430" UserId="6063" Text="I'm working on a Software Rasterizer on a sub-30 MHz RISC CPU My current focus is on zooming-in on a slowly rotating planet. For maximum quality, no 3D polygons are involved with the planet - the planet texturing is purely image-based. This is what I have:&#xD;&#xA;&#xD;&#xA; - the planet rotates only around Y axis and is always viewed straight&#xD;&#xA;   on with camera at the equator (so you can't see poles, hence the&#xD;&#xA;   default pole distortion artifact is not an issue here at all)&#xD;&#xA;   - midpoint Bresenham circle algorithm to compute 8 endpoints at each iteration, effectively giving me 4 horizontal scanlines&#xD;&#xA;   - simple linear remapping between texture row and planet's scanline - e.g. if the planet is 64 pixels tall on screen and texture is 128&#xD;&#xA;   pixels tall, I simply skip every other row&#xD;&#xA;   - same linear remapping within each scanline - e.g. if the current scanline is 64 pixels wide, and texture is 128 pixels wide, I simply&#xD;&#xA;   skip every other texel in current texture row&#xD;&#xA;&#xD;&#xA;The above works and is great as a first working and reasonably fast  prototype. However, when the planet rotates, despite the low screen resolution, due to the simple linear remapping (within each scanline), it does not *feel and look* like planet rotation, as the perspective/distortion/stretching at the sphere edges (left and right edge of the circle) is obviously missing.&#xD;&#xA;&#xD;&#xA;What is the equation that can give me the exact texture coordinate, for a current texture row, of each on-screen pixel of that circle's scanline ? &#xD;&#xA;&#xD;&#xA;Please note that I can't afford to compute sin/cos (or use precomputed tables). Division is expensive, but I could perhaps hide its latency via interleaving with other instructions (while division is being computed). So, ideally, I could compute it just via add/sub/mul/bitshift. &#xD;&#xA;Obviously, due to symmetry, that computed coordinate will be reused for 3 other points, so we're in reality computing that for only 25% points of the circle." ContentLicense="CC BY-SA 3.0" />
  <row Id="13554" PostHistoryTypeId="1" PostId="5090" RevisionGUID="e4424f6a-c87c-43ea-ab9a-bcbab8dd5d9d" CreationDate="2017-05-10T13:33:27.430" UserId="6063" Text="Fast approximation of spehrical texture coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="13555" PostHistoryTypeId="3" PostId="5090" RevisionGUID="e4424f6a-c87c-43ea-ab9a-bcbab8dd5d9d" CreationDate="2017-05-10T13:33:27.430" UserId="6063" Text="|texture|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13557" PostHistoryTypeId="2" PostId="5091" RevisionGUID="2d403398-32a9-48f0-a28f-a804f72fd4e8" CreationDate="2017-05-10T13:45:00.500" UserId="6608" Text="Maybe it helps to draw out the steps of the algorithm. Here is an example for TBLR &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The red is the worst case: clip top, clip bottom, clip left, clip right. Four steps!&#xD;&#xA;&#xD;&#xA;The green is the best case: clip top, clip bottom, done. Two steps.&#xD;&#xA;&#xD;&#xA;The blue is a middle case: clip top, clip bottom, clip left, done. Three steps.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bNJzf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13558" PostHistoryTypeId="2" PostId="5092" RevisionGUID="88c84ed9-b3de-40ff-a5db-50dc6fed320a" CreationDate="2017-05-10T13:49:43.373" UserId="137" Text="With the correct mapping used for the texture you can avoid a lot of complex math for the sample point. For example the [Lambert cylindrical equal-area projection][1] will let you keep the y coordinate unmodified and the x coordinate only depends on which meridian you are on.&#xD;&#xA;&#xD;&#xA;Then you could use bresenham's ellipse algorithm to draw every visible meridian on the planet.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Lambert_cylindrical_equal-area_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="13559" PostHistoryTypeId="2" PostId="5093" RevisionGUID="0d320191-877b-40ee-9077-70d655f85ade" CreationDate="2017-05-10T16:48:57.933" UserId="5521" Text="Okay, I figured it out. It has to do with the texture not loading before the first display function is called. The texture displays after a mouse or keyboard event. To remedy this, I added a timer to refresh the scene. This only works on Firefox however. I'm not sure why the image does not display on Chrome." ContentLicense="CC BY-SA 3.0" />
  <row Id="13560" PostHistoryTypeId="5" PostId="5086" RevisionGUID="bc39b252-3d0b-4bdc-b856-f809d6a86181" CreationDate="2017-05-10T20:08:22.323" UserId="6596" Comment="added 327 characters in body" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;EDIT: I've made progress on this, but suspect I'll be unable to affect this in screen space due to the fact that the operation I really want to control is handled within the vertex post-processing stage of the pipeline. Regardless, here is a screen shot:&#xD;&#xA;[![offset faces][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/VSYkP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13561" PostHistoryTypeId="5" PostId="5086" RevisionGUID="24652a47-af68-4dce-942c-d4c17f74006c" CreationDate="2017-05-10T20:32:43.333" UserId="6596" Comment="deleted 102 characters in body" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;EDIT: I've made progress on this, but I still have bugs. Regardless, here is a screen shot:&#xD;&#xA;[![offset faces][4]][4]&#xD;&#xA;I will answer my own question once I fully debug my solution.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/VSYkP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13565" PostHistoryTypeId="2" PostId="5095" RevisionGUID="1ba2952a-5de0-4de0-92ae-1311b353cf1c" CreationDate="2017-05-10T23:20:26.937" UserId="1952" Text="Incidentally I [implemented something similar][1] for similar hardware some 20 years ago (:&#xA;&#xA;IIRC, I calculated 1D look-up-table using acos for parallel projection of a cylinder and just scaled it for each scanline to reduce computation cost. The LUT just gives you x-coordinate offset to the texture and you add constant offset for each scanline for the rotation.&#xA;&#xA;For y-axis the input texture can be preprocessed to have proper spherical distortion applied and you can just linearly scale the texture vertically. Though it's not that much extra computation to do it run-time either.&#xA;&#xA;This doesn't give you proper perspective projection but might be enough for your purposes.&#xA;&#xA;  [1]: https://youtu.be/AZTqTrCrNlw" ContentLicense="CC BY-SA 3.0" />
  <row Id="13566" PostHistoryTypeId="5" PostId="5095" RevisionGUID="a0bcca2f-9eb2-4dca-8844-7c6335f51479" CreationDate="2017-05-11T00:33:42.320" UserId="1952" Comment="added 269 characters in body" Text="Incidentally I [implemented something similar][1] for similar hardware some 20 years ago (:&#xA;&#xA;IIRC, I calculated 1D look-up-table using acos for parallel projection of a cylinder and just scaled it for each scanline to reduce computation cost. The LUT just gives you x-coordinate offset to the texture and you add constant offset for each scanline for the rotation.&#xA;&#xA;For y-axis the input texture can be preprocessed to have proper spherical distortion applied and you can just linearly scale the texture vertically. Though it's not that much extra computation to do it run-time either.&#xA;&#xA;This doesn't give you proper perspective projection but might be enough for your purposes.&#xA; &#xA;Edit: Didn't notice you said you can't afford LUT. You could do the table look-up every N pixels and linearly interpolate inbetween. This was a common method in the past to do affordable perspective correct texture mapping for software rasterizers to avoid div/pixel&#xA;&#xA;  [1]: https://youtu.be/AZTqTrCrNlw" ContentLicense="CC BY-SA 3.0" />
  <row Id="13568" PostHistoryTypeId="5" PostId="5088" RevisionGUID="3f25ec46-01ca-4faa-992c-8e6a97a58f76" CreationDate="2017-05-11T03:28:41.967" UserId="6606" Comment="updated to show changes made" Text="&lt;img src=&quot;https://i.stack.imgur.com/D2uft.png&quot; width=&quot;300&quot; height=&quot;250&quot;&gt;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/AtyZf.jpg&quot; width=&quot;300&quot; height=&quot;250&quot;&gt;&lt;br/&gt;&#xD;&#xA;Above on the left is my attempt and on the right is what I'm aiming for.As you can see my sphere with the specular brdf has a weird dark ring&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;In my radiance function I am recursing through the intersected objects with the next intersection from the ray that's being traced. I'm using russian roulette with a depth of 5 to avoid infinite recursion. After this I find a point of intersection `Vec y` and calculate the normal there. After this I sample the brdf, which in this case is specular, to get the incoming direction vector, stored in i. Finally I call the function using a new ray with the point of intersection and -i.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;I have a feeling the my error is with my normal vector n being sent to brdf.eval or brdf.sample. I am not sure if the normal is supposed to be the normal at the origin of the ray, r.o, or at the intersection point y. When I try changing it the specular sphere ends up completely black, or my diffuse brdf for the rest of the scene becomes incorrect.&#xD;&#xA;&#xD;&#xA;    Vec receivedRadiance(const Ray &amp;r, int depth, bool flag) {&#xD;&#xA;	double t, p;                                   // Distance to intersection/pdf&#xD;&#xA;	int id = 0;                                 // id of intersected sphere&#xD;&#xA;&#xD;&#xA;	if (!intersect(r, t, id)) return Vec();   // if miss, return black&#xD;&#xA;	const Sphere &amp;obj = spheres[id];            // the hit object&#xD;&#xA;	const BRDF &amp;brdf = obj.brdf;                // Surface BRDF at x&#xD;&#xA;	Vec rad = obj.e;							// Emitted radiance&#xD;&#xA;&#xD;&#xA;	Vec o = (Vec() - r.d).normalize();          // The outgoing direction (= -r.d)&#xD;&#xA;	Vec x = r.o + r.d*t;                        // The intersection point&#xD;&#xA;	&#xD;&#xA;	Vec n = (x - obj.p).normalize();            // The normal direction&#xD;&#xA;	if (n.dot(r.d) &lt; 0) n = n*-1.0;&#xD;&#xA;&#xD;&#xA;	if (depth &lt;= 5)&#xD;&#xA;		p = 1.0;&#xD;&#xA;	else&#xD;&#xA;		p = .9;&#xD;&#xA;&#xD;&#xA;	if (rng() &lt; p)&#xD;&#xA;	{&#xD;&#xA;		Vec i, b;&#xD;&#xA;		brdf.sample(n, o, i, p);&#xD;&#xA;		b = brdf.eval(n, o, i);&#xD;&#xA;		Ray y = Ray(x, i * -1);&#xD;&#xA;		rad = rad + (receivedRadiance(y, depth + 1, true) * (PI)).mult(b) * (1 / p);&#xD;&#xA;	}&#xD;&#xA;	return rad;}&#xD;&#xA;&#xD;&#xA;Here is my specular BRDF struct:&#xD;&#xA;&#xD;&#xA;    struct SpecularBRDF : public BRDF {&#xD;&#xA;	SpecularBRDF(Vec ks_) : ks(ks_) {}&#xD;&#xA;	&#xD;&#xA;	Vec eval(const Vec &amp;n, const Vec &amp;o, const Vec &amp;i) const {&#xD;&#xA;		Vec m;&#xD;&#xA;		mirroredDir(n, o, m);&#xD;&#xA;		if (abs(i.x - m.x) &lt; 1e-5 &amp;&amp; abs(i.y - m.y) &lt; 1e-5 &amp;&amp; abs(i.z - m.z) &lt; 1e-5) //i == m&#xD;&#xA;			return ks * (1 / n.dot(i));&#xD;&#xA;		else&#xD;&#xA;			return Vec(0.0, 0.0, 0.0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void sample(const Vec &amp;n, const Vec &amp;o, Vec &amp;i, double &amp;pdf) const {&#xD;&#xA;		mirroredDir(n, o, i);&#xD;&#xA;		pdf = 1.0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	Vec ks;}&#xD;&#xA;And my mirrorDir function:&#xD;&#xA;&#xD;&#xA;    inline void mirroredDir(const Vec &amp;n, const Vec &amp;o, Vec &amp;m){&#xD;&#xA;	m = n * 2.0 * (n.dot(o)) - o;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/D2uft.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13569" PostHistoryTypeId="5" PostId="5086" RevisionGUID="76e576d4-7db9-4f59-91e4-a75ffe51723e" CreationDate="2017-05-11T04:51:33.787" UserId="6596" Comment="added 2 characters in body" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;EDIT: I've made progress on this, but I still have bugs. Regardless, here is a screen shot:&#xD;&#xA;[![offset faces][4]][4]&#xD;&#xA;&#xD;&#xA;I will answer my own question once I fully debug my solution.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/VSYkP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13570" PostHistoryTypeId="5" PostId="5086" RevisionGUID="14be6c1b-cddf-43af-bf71-e6e9c0380bbe" CreationDate="2017-05-11T05:03:38.593" UserId="6596" Comment="added 2 characters in body" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;EDIT: I've made progress on this, but I still have bugs. Regardless, here is a screen shot:&#xD;&#xA;[![offset faces][4]][4]&#xD;&#xA;&#xD;&#xA;I'm trying to offset the xy-values of the points in clip-space, but still need to adjust the z-value at the offset point. I was expecting that the offset would remain constant when rotating the object, but something is broken.&#xD;&#xA;&#xD;&#xA;Here is my code:&#xD;&#xA;&#xD;&#xA;    		attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 trans = projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 newPos = trans * vec4( position, 1.0 );&#xD;&#xA;				vec4 newLeft = trans * vec4( left, 1.0 );&#xD;&#xA;				vec4 newRight = trans * vec4( right, 1.0 );&#xD;&#xA;				vec4 newNorm = trans * vec4( normal, 1.0 );&#xD;&#xA;				&#xD;&#xA;				//deal with these triangles in 2D screen space (transformed xy)&#xD;&#xA;				&#xD;&#xA;				vec2 leftRight = newRight.xy - newLeft.xy;&#xD;&#xA;				float b = length(vec2(newLeft.xy-newPos.xy))/length(vec2(newRight.xy-newPos.xy));&#xD;&#xA;				vec2 endPt = newLeft.xy + vec2(b)*leftRight.xy;&#xD;&#xA;				vec2 bisect = normalize(endPt - newPos.xy);&#xD;&#xA;				&#xD;&#xA;				newPos.x += bisect.x*4.0;&#xD;&#xA;				newPos.y += bisect.y*4.0;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/VSYkP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13571" PostHistoryTypeId="5" PostId="1778" RevisionGUID="0eb1e75b-e955-4a80-ac19-324541a6c2dd" CreationDate="2017-05-11T05:20:34.097" UserId="4766" Comment="learingwebgl is a poor resource, it's blog has also not been updated in over 2 years." Text="WebGL is [OpenGL ES 2.0][1] graphics for web pages. It extends the capability of the [HTML canvas element][2] to allow it to render accelerated 3D graphics in any compatible web browser. &#xD;&#xA;&#xD;&#xA;WebGL is based on [OpenGL ES 2.0][3] and is driven via a JavaScript API. It does not require the use of plug-ins. Official specifications and additional information can be found at [Khronos][4].&#xD;&#xA;&#xD;&#xA;**Engines:**&#xD;&#xA;&#xD;&#xA;There are also many different webGL based 3D engines available:&#xD;&#xA;&#xD;&#xA; - [Three.js][5] - the most popular and the most used&#xD;&#xA; - [Goo Engine][9]&#xD;&#xA; - [SceneJS][8]&#xD;&#xA; - [BabylonJS][7]&#xD;&#xA; - [GLGE][14]&#xD;&#xA; - [PhiloGL][17]&#xD;&#xA; - [CopperLicht][6]&#xD;&#xA; - [KickJS][10]&#xD;&#xA; - [A3][11]&#xD;&#xA; - [CubicVR][12]&#xD;&#xA; - [C3DL][13]&#xD;&#xA; - [Kuda][15]&#xD;&#xA; - [O3D][16]&#xD;&#xA; - [SpiderGL][18]&#xD;&#xA;&#xD;&#xA;  [1]: http://en.wikipedia.org/wiki/OpenGL&#xD;&#xA;  [2]: http://en.wikipedia.org/wiki/Canvas_element&#xD;&#xA;  [3]: http://en.wikipedia.org/wiki/OpenGL_ES&#xD;&#xA;  [4]: http://www.khronos.org/webgl/&#xD;&#xA;  [5]: http://threejs.org/&#xD;&#xA;  [6]: http://www.ambiera.com/copperlicht/&#xD;&#xA;  [7]: http://www.babylonjs.com/&#xD;&#xA;  [8]: http://scenejs.org/&#xD;&#xA;  [9]: http://www.gooengine.com/&#xD;&#xA;  [10]: http://www.kickjs.org/&#xD;&#xA;  [11]: http://www.aerotwist.com/a3/&#xD;&#xA;  [12]: http://www.cubicvr.org/cubicvr-js/webgl-cubicvr&#xD;&#xA;  [13]: http://www.c3dl.org/&#xD;&#xA;  [14]: http://www.glge.org/&#xD;&#xA;  [15]: https://code.google.com/p/kuda/&#xD;&#xA;  [16]: https://code.google.com/p/o3d/&#xD;&#xA;  [17]: http://www.sencha.com/blog/introducing-philogl-a-webgl-javascript-library-from-sencha-labs/&#xD;&#xA;  [18]: http://www.spidergl.org/&#xD;&#xA;  [19]: http://learningwebgl.com/&#xD;&#xA;  [20]: http://learningthreejs.com/&#xD;&#xA;&#xD;&#xA;**Getting started with webGL:**&#xD;&#xA;&#xD;&#xA;Start with [WebGLFundamentals.org](http://webglfundamentals.org).&#xD;&#xA;&#xD;&#xA;Other resources include [LearningWebGL][19]. LearningWebGL has basic tutorials.&#xD;&#xA;&#xD;&#xA;If you don't want to learn WebGL and you just want to use a library that makes it easy to display 3d three.js is the most popular 3d library and there are plenty of Three.js tutorials and examples here - [LearningThreeJS][20]." ContentLicense="CC BY-SA 3.0" />
  <row Id="13572" PostHistoryTypeId="24" PostId="1778" RevisionGUID="0eb1e75b-e955-4a80-ac19-324541a6c2dd" CreationDate="2017-05-11T05:20:34.097" Comment="Proposed by 4766 approved by 48, 38 edit id of 243" ContentLicense="CC BY-SA 3.0" />
  <row Id="13573" PostHistoryTypeId="2" PostId="5096" RevisionGUID="225d9595-e2d9-45fd-8b02-9317f3f5a32c" CreationDate="2017-05-11T07:50:08.453" UserId="2644" Text="Is there any open-source implementation of n*log(n) visibility graph construction algorithm?&#xD;&#xA;&#xD;&#xA;I'm trying to understand [S. K. GHOSH and D. M. MOUNT][1] algorithm, but it's known for having very hard implementation. It would be great if I saw at least some implementation, in any programming language. Or in pseudo-code.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www-lb.cs.umd.edu/~mount/Papers/sicomp91-visib.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13574" PostHistoryTypeId="1" PostId="5096" RevisionGUID="225d9595-e2d9-45fd-8b02-9317f3f5a32c" CreationDate="2017-05-11T07:50:08.453" UserId="2644" Text="Is there any open-source implementation of n*log(n) visibility graph construction algorithm?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13575" PostHistoryTypeId="3" PostId="5096" RevisionGUID="225d9595-e2d9-45fd-8b02-9317f3f5a32c" CreationDate="2017-05-11T07:50:08.453" UserId="2644" Text="|computational-geometry|2d|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13576" PostHistoryTypeId="6" PostId="5096" RevisionGUID="07f5ed66-e2ac-4bbf-9f0c-23c313f8bfae" CreationDate="2017-05-11T08:04:24.847" UserId="2644" Comment="edited tags" Text="|algorithm|computational-geometry|2d|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13577" PostHistoryTypeId="2" PostId="5097" RevisionGUID="b3cade69-3531-49e1-9f10-80be3cc9d6a4" CreationDate="2017-05-11T12:26:45.180" UserId="5887" Text="As the title says i have been trying to understand the normal interpolation for the Phong shading/lighting model. I am unsure of the equation to calculate the normal but i have come across this equation: &#xD;&#xA;N=Na*α+Nb(1−α)&#xD;&#xA;Where N is the interpolated vector, Na and Nb are unit vectors to interpolate between and im assuming α is the percentage between the two. However in using this model as shown here: &#xD;&#xA;&#xD;&#xA;    public static Vector3 lerp(Vector3 a, Vector3 b, double alpha){&#xD;&#xA;		 return (a.multiply(alpha)).add(b.multiply(1-alpha)).normalize();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;i am not obtaining the correct results, so any advice on the topic, such as what i may be doing wrong etc, would be appreciated" ContentLicense="CC BY-SA 3.0" />
  <row Id="13578" PostHistoryTypeId="1" PostId="5097" RevisionGUID="b3cade69-3531-49e1-9f10-80be3cc9d6a4" CreationDate="2017-05-11T12:26:45.180" UserId="5887" Text="Normal Interpolation for Phong shading" ContentLicense="CC BY-SA 3.0" />
  <row Id="13579" PostHistoryTypeId="3" PostId="5097" RevisionGUID="b3cade69-3531-49e1-9f10-80be3cc9d6a4" CreationDate="2017-05-11T12:26:45.180" UserId="5887" Text="|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13580" PostHistoryTypeId="5" PostId="5097" RevisionGUID="5e3e9f72-91eb-422f-91c2-e7125b79feb7" CreationDate="2017-05-11T12:41:39.663" UserId="5887" Comment="Solved my quesiton" Text="As the title says i have been trying to understand the normal interpolation for the Phong shading/lighting model. I am unsure of the equation to calculate the normal but i have come across this equation: &#xD;&#xA;N=Na*α+Nb(1−α)&#xD;&#xA;Where N is the interpolated vector, Na and Nb are unit vectors to interpolate between and im assuming α is the percentage between the two. However in using this model as shown here: &#xD;&#xA;&#xD;&#xA;    public static Vector3 lerp(Vector3 a, Vector3 b, double alpha){&#xD;&#xA;		 return (a.multiply(alpha)).add(b.multiply(1-alpha)).normalize();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;i am not obtaining the correct results, so any advice on the topic, such as what i may be doing wrong etc, would be appreciated&#xD;&#xA;&#xD;&#xA;EDIT: I found my mistake in the interpolation, here is the updated method for those who are interested:&#xD;&#xA;&#xD;&#xA;    public static Vector3 lerp(Vector3 a, Vector3 b, double gradient){&#xD;&#xA;	    return a.add((b.minus(a)).multiply(gradient));&#xD;&#xA;	}" ContentLicense="CC BY-SA 3.0" />
  <row Id="13581" PostHistoryTypeId="5" PostId="5096" RevisionGUID="d29adf91-5ed3-42c1-81cb-955145b4c3df" CreationDate="2017-05-11T12:54:49.767" UserId="2644" Comment="added 11 characters in body" Text="Is there any open-source implementation of n*log(n) visibility graph construction algorithm?&#xD;&#xA;&#xD;&#xA;I'm trying to understand [S. K. GHOSH and D. M. MOUNT][1] sweep line algorithm, but it's known for having very hard implementation. It would be great if I saw at least some implementation, in any programming language. Or in pseudo-code.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www-lb.cs.umd.edu/~mount/Papers/sicomp91-visib.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13582" PostHistoryTypeId="2" PostId="5098" RevisionGUID="bb74deda-57c3-48d7-886f-0ea838887486" CreationDate="2017-05-11T13:52:09.930" UserId="48" Text="Your first version was correct, except that `alpha` and `1-alpha` should be swapped (the result should be `a` when `alpha == 0` and `b` when `alpha == 1`). &#xD;&#xA;&#xD;&#xA;For Phong shading, you _do_ want to keep the normalize on the end; that's the key thing that makes Phong different from Gouraud shading. But also, normalize isn't part of the usual definition of &quot;lerp&quot; (linear interpolation), so I would keep it out of the `lerp` function, and move the normalize to the Phong shading function where you call `lerp`." ContentLicense="CC BY-SA 3.0" />
  <row Id="13583" PostHistoryTypeId="5" PostId="5086" RevisionGUID="f626d5f7-5655-4705-8f22-c3b4efc4db43" CreationDate="2017-05-11T14:04:11.283" UserId="6596" Comment="debugged code" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;EDIT: I've made progress on this, but I still have bugs. Regardless, here is a screen shot:&#xD;&#xA;[![offset faces][4]][4]&#xD;&#xA;&#xD;&#xA;I'm offsetting the xy-values of the points in clip-space, but still need to adjust the z-value at the offset point.&#xD;&#xA;&#xD;&#xA;Here is my code:&#xD;&#xA;&#xD;&#xA;    		attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 trans = projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 newPos = trans * vec4( position, 1.0 );&#xD;&#xA;				vec4 newLeft = trans * vec4( left, 1.0 );&#xD;&#xA;				vec4 newRight = trans * vec4( right, 1.0 );&#xD;&#xA;				vec4 newNorm = trans * vec4( normal, 1.0 );&#xD;&#xA;				&#xD;&#xA;				//deal with these triangles in 2D screen space (transformed xy)&#xD;&#xA;				&#xD;&#xA;				vec2 leftRight = newRight.xy - newLeft.xy;&#xD;&#xA;				vec2 leftVec = newLeft.xy-newPos.xy;&#xD;&#xA;				vec2 rightVec = newRight.xy-newPos.xy;&#xD;&#xA;				float b = length(leftVec)/(length(rightVec)+length(leftVec));&#xD;&#xA;				vec2 endPt = newLeft.xy + vec2(b)*leftRight.xy;&#xD;&#xA;				vec2 bisect = normalize(endPt - newPos.xy);&#xD;&#xA;				&#xD;&#xA;				newPos.x += bisect.x*4.0;&#xD;&#xA;				newPos.y += bisect.y*4.0;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/VSYkP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13584" PostHistoryTypeId="5" PostId="5086" RevisionGUID="21c57407-1d89-46aa-931d-d45c7d0e2100" CreationDate="2017-05-11T14:26:12.410" UserId="6596" Comment="added 18 characters in body" Text="[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader. &#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;EDIT: I've made progress on this, but I still have bugs. Regardless, here is a screen shot:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I'm offsetting the xy-values of the points in clip-space, but still need to adjust the z-value at the offset point.&#xD;&#xA;&#xD;&#xA;Here is my code:&#xD;&#xA;&#xD;&#xA;    		attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 trans = projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 newPos = trans * vec4( position, 1.0 );&#xD;&#xA;				vec4 newLeft = trans * vec4( left, 1.0 );&#xD;&#xA;				vec4 newRight = trans * vec4( right, 1.0 );&#xD;&#xA;				vec4 newNorm = trans * vec4( normal, 1.0 );&#xD;&#xA;				&#xD;&#xA;				//deal with these triangles in 2D screen space (transformed xy)&#xD;&#xA;				&#xD;&#xA;				vec2 leftRight = newRight.xy - newLeft.xy;&#xD;&#xA;				vec2 leftVec = newLeft.xy-newPos.xy;&#xD;&#xA;				vec2 rightVec = newRight.xy-newPos.xy;&#xD;&#xA;				float b = length(leftVec)/(length(rightVec)+length(leftVec));&#xD;&#xA;				vec2 endPt = newLeft.xy + vec2(b)*leftRight.xy;&#xD;&#xA;				vec2 bisect = normalize(endPt - newPos.xy);&#xD;&#xA;				&#xD;&#xA;				newPos.x += bisect.x*4.0;&#xD;&#xA;				newPos.y += bisect.y*4.0;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/W9AzA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13585" PostHistoryTypeId="4" PostId="5090" RevisionGUID="b0a8966c-c076-494e-8244-dabc222c7456" CreationDate="2017-05-11T14:45:17.697" UserId="1952" Comment="typo fix" Text="Fast approximation of spherical texture coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="13588" PostHistoryTypeId="6" PostId="5086" RevisionGUID="c605c202-1d9b-4abd-8c5c-3b9b0f2236c4" CreationDate="2017-05-11T16:28:52.183" UserId="2654" Comment="edited tags" Text="|shader|three.js|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13589" PostHistoryTypeId="2" PostId="5099" RevisionGUID="59854fdf-de68-4c68-88fd-9d60ff1f3405" CreationDate="2017-05-12T11:24:41.030" UserId="6618" Text="So what I would like to achieve is this:&#xD;&#xA;&#xD;&#xA; 1. User submits *Image 1* - this image is then broken down into X by X sized blocks&#xD;&#xA; 2. User submits *Image 2* - then the program/algorithm takes all the blocks generated in the above step, and reconstructs *Image 2* using them&#xD;&#xA;&#xD;&#xA;What I would like to know is, are there any libraries, or some easy way of doing this (ideally in Javascript, as I don't know any other languages) - or even some standalone software tool to accomplish this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13590" PostHistoryTypeId="1" PostId="5099" RevisionGUID="59854fdf-de68-4c68-88fd-9d60ff1f3405" CreationDate="2017-05-12T11:24:41.030" UserId="6618" Text="Image regeneration with nearest neighbor search" ContentLicense="CC BY-SA 3.0" />
  <row Id="13591" PostHistoryTypeId="3" PostId="5099" RevisionGUID="59854fdf-de68-4c68-88fd-9d60ff1f3405" CreationDate="2017-05-12T11:24:41.030" UserId="6618" Text="|algorithm|image-processing|javascript|image-comparison|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13592" PostHistoryTypeId="50" PostId="4972" RevisionGUID="b8f97ec2-4539-4b7c-94ce-863bc611f0ec" CreationDate="2017-05-12T12:25:25.207" UserId="-1" />
  <row Id="13593" PostHistoryTypeId="5" PostId="5099" RevisionGUID="131a34fe-8d90-4d5a-981e-7a3f895fbac1" CreationDate="2017-05-12T15:15:36.030" UserId="6618" Comment="added 112 characters in body" Text="So what I would like to achieve is this:&#xD;&#xA;&#xD;&#xA; 1. User submits *Image 1* - this image is then broken down into X by X sized blocks&#xD;&#xA; 2. User submits *Image 2* - then the program/algorithm takes all the blocks generated in the above step, and reconstructs *Image 2* using them&#xD;&#xA;&#xD;&#xA;Example *Image 2*:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Example *Output*:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What I would like to know is, are there any libraries, or some easy way of doing this (ideally in Javascript, as I don't know any other languages) - or even some standalone software tool to accomplish this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lbKpH.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/4w5qk.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13594" PostHistoryTypeId="2" PostId="5100" RevisionGUID="8cda0f55-2c44-4264-a499-e1908fa32564" CreationDate="2017-05-12T17:50:49.733" UserId="6596" Text="Given triangle ▲ABC, we bisect angle ∠BAC with line AD, derived with [Angle Bisector Theorem][1]:&#xD;&#xA;&#xD;&#xA;BA / BD = CA / CD&#xD;&#xA;[![Triangle Inset Diagram][2]][2]&#xD;&#xA;Point E represents our objective refined position on the desired resulting inset triangle. As it lies upon angle bisector AD, it is equidistant from sides BA &amp; CA, forming identical right triangles ▲AFE &amp; ▲AGE. We can now use [Pythagorean Theorem][3] to find the length of AE:&#xD;&#xA;&#xD;&#xA;AE = EG / Sin(∠BAC)&#xD;&#xA;&#xD;&#xA;That's all the math we need, so let's cook up some GLSL!&#xD;&#xA;&#xD;&#xA;  We start off with all the typical attributes: position, normal, and transformation matrices, but since the vertex shader only works on a single vertex, we need to add the neighboring vertices as additional attributes. This way, each vertex will find its own &quot;point E&quot;, creating the resulting inset triangle. (Note: I don't call them &quot;B&quot; &amp; &quot;C&quot; here, because they are not yet in *screen space*.)&#xD;&#xA;&#xD;&#xA;    	attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;		attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;  Speaking of screen space, I'm also including the aspect ratio of the display, (and making it a uniform, in case the window is resized.)&#xD;&#xA;&#xD;&#xA;  After preparing varying normals for the fragment shader, and transforming the face into clipping-space, we can get down to the business of applying the above math:&#xD;&#xA;&#xD;&#xA;			attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;			uniform float aspect;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 xform= projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 A = xform * vec4( position, 1.0 );&#xD;&#xA;				vec4 B = xform * vec4( left, 1.0 );&#xD;&#xA;				vec4 C = xform * vec4( right, 1.0 );&#xD;&#xA;				&#xD;&#xA;				vec3 CB = C.xyz - B.xyz;&#xD;&#xA;				vec2 BA = B.xy - A.xy;&#xD;&#xA;				vec2 CA = C.xy - A.xy;&#xD;&#xA;				float lengthBA = length(BA);&#xD;&#xA;				float lengthCA = length(CA);&#xD;&#xA;				float ratio = lengthBA / ( lengthBA + lengthCA );&#xD;&#xA;				vec3 D = B.xyz + ratio * CB.xyz;&#xD;&#xA;				vec3 AD = D - A.xyz;&#xD;&#xA;				vec3 bisect = normalize(AD);&#xD;&#xA;				&#xD;&#xA;				float theta = acos( dot(BA, CA) / (lengthBA * lengthCA) );&#xD;&#xA;				float AE = 1.0/(sin(theta)*aspect);&#xD;&#xA;				newPos.z += AE/length(AD) * (D.z - A.z);&#xD;&#xA;				newPos.x += bisect.x*AE;&#xD;&#xA;				newPos.y += bisect.y*AE;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;This code gives us the results below.&#xD;&#xA;&#xD;&#xA;[![Screen Shot][4]][4]&#xD;&#xA;&#xD;&#xA;Note, there are a few edge-cases having to do with backface-culled triangles being flipped by this process, and I began to address this in code, yet decided to simply avoid these cases for now. Perhaps I'll revisit it when I get this project done.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Angle_bisector_theorem&#xD;&#xA;  [2]: https://i.stack.imgur.com/kKiYW.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Pythagorean_theorem&#xD;&#xA;  [4]: https://i.stack.imgur.com/0Gu9i.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13595" PostHistoryTypeId="5" PostId="5086" RevisionGUID="7a6d8315-a56e-474d-a828-3a3187e9ae29" CreationDate="2017-05-12T17:52:55.690" UserId="6596" Comment="deleted 1161 characters in body" Text="I need to offset all (blue) triangles using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader.&#xD;&#xA;&#xD;&#xA;[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;Here is a screen shot of the effect I'm aiming for:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/W9AzA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13596" PostHistoryTypeId="5" PostId="5100" RevisionGUID="6e33c292-dac7-4da5-b220-2628f41e25f7" CreationDate="2017-05-12T18:01:03.320" UserId="6596" Comment="added 9 characters in body" Text="Given triangle ▲ABC, we bisect angle ∠BAC with line AD, derived with [Angle Bisector Theorem][1]:&#xD;&#xA;&#xD;&#xA;BA / BD = CA / CD&#xD;&#xA;[![Triangle Inset Diagram][2]][2]&#xD;&#xA;Point E represents our objective refined position on the desired resulting inset triangle. As it lies upon angle bisector AD, it is equidistant from sides BA &amp; CA, forming identical right triangles ▲AFE &amp; ▲AGE. We can now use [Pythagorean Theorem][3] to find the length of AE:&#xD;&#xA;&#xD;&#xA;AE = EG / Sin(∠BAC)&#xD;&#xA;&#xD;&#xA;That's all the math we need, so let's cook up some GLSL!&#xD;&#xA;&#xD;&#xA;  We start off with all the typical attributes: position, normal, and transformation matrices, but since the vertex shader only works on a single vertex, we need to add the neighboring vertices as additional attributes. This way, each vertex will find its own &quot;point E&quot;, creating the resulting inset triangle. (Note: I don't call them &quot;B&quot; &amp; &quot;C&quot; here, because they are not yet in *screen space*.)&#xD;&#xA;&#xD;&#xA;    	attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;		attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;  Speaking of screen space, I'm also including the aspect ratio of the display, (and making it a uniform, in case the window is resized.)&#xD;&#xA;&#xD;&#xA;  After preparing varying normals for the fragment shader, and transforming the face into clipping-space, we can get down to the business of applying the above math:&#xD;&#xA;&#xD;&#xA;			attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;			uniform float aspect;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 xform= projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 A = xform * vec4( position, 1.0 );&#xD;&#xA;				vec4 B = xform * vec4( left, 1.0 );&#xD;&#xA;				vec4 C = xform * vec4( right, 1.0 );&#xD;&#xA;				&#xD;&#xA;				vec3 CB = C.xyz - B.xyz;&#xD;&#xA;				vec2 BA = B.xy - A.xy;&#xD;&#xA;				vec2 CA = C.xy - A.xy;&#xD;&#xA;				float lengthBA = length(BA);&#xD;&#xA;				float lengthCA = length(CA);&#xD;&#xA;				float ratio = lengthBA / ( lengthBA + lengthCA );&#xD;&#xA;				vec3 D = B.xyz + ratio * CB.xyz;&#xD;&#xA;				vec3 AD = D - A.xyz;&#xD;&#xA;				vec3 bisect = normalize(AD);&#xD;&#xA;				&#xD;&#xA;				float theta = acos( dot(BA, CA) / (lengthBA * lengthCA) );&#xD;&#xA;				float AE = 1.0/(sin(theta)*aspect);&#xD;&#xA;				newPos.z += AE/length(AD) * (D.z - A.z);&#xD;&#xA;				newPos.x += bisect.x*AE;&#xD;&#xA;				newPos.y += bisect.y*AE;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;This code gives us the results below.&#xD;&#xA;&#xD;&#xA;[![Screen Shot][4]][4]&#xD;&#xA;&#xD;&#xA;Note, there are a few edge-cases having to do with *almost* backface-culled triangles being flipped by this process, and I began to address this in code, yet decided to simply avoid these cases for now. Perhaps I'll revisit it when I get this project done.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Angle_bisector_theorem&#xD;&#xA;  [2]: https://i.stack.imgur.com/kKiYW.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Pythagorean_theorem&#xD;&#xA;  [4]: https://i.stack.imgur.com/0Gu9i.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13597" PostHistoryTypeId="5" PostId="5100" RevisionGUID="712e77ac-82a8-4807-8e23-18f2c9a489a9" CreationDate="2017-05-12T18:18:15.663" UserId="6596" Comment="error in code and diagram" Text="Given triangle ▲ABC, we bisect angle ∠BAC with line AD, derived with [Angle Bisector Theorem][1]:&#xD;&#xA;&#xD;&#xA;BA / BD = CA / CD&#xD;&#xA;[![Triangle Inset Diagram][2]][2]&#xD;&#xA;Point E represents our objective refined position on the desired resulting inset triangle. As it lies upon angle bisector AD, it is equidistant from sides BA &amp; CA, forming identical right triangles ▲AFE &amp; ▲AGE. We can now use [Pythagorean Theorem][3] to find the length of AE:&#xD;&#xA;&#xD;&#xA;AE = EG / Sin(∠EAG)&#xD;&#xA;&#xD;&#xA;That's all the math we need, so let's cook up some GLSL!&#xD;&#xA;&#xD;&#xA;  We start off with all the typical attributes: position, normal, and transformation matrices, but since the vertex shader only works on a single vertex, we need to add the neighboring vertices as additional attributes. This way, each vertex will find its own &quot;point E&quot;, creating the resulting inset triangle. (Note: I don't call them &quot;B&quot; &amp; &quot;C&quot; here, because they are not yet in *screen space*.)&#xD;&#xA;&#xD;&#xA;    	attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;		attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;  Speaking of screen space, I'm also including the aspect ratio of the display, (and making it a uniform, in case the window is resized.)&#xD;&#xA;&#xD;&#xA;  After preparing varying normals for the fragment shader, and transforming the face into clipping-space, we can get down to the business of applying the above math:&#xD;&#xA;&#xD;&#xA;			attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;			uniform float aspect;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 xform= projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 A = xform * vec4( position, 1.0 );&#xD;&#xA;				vec4 B = xform * vec4( left, 1.0 );&#xD;&#xA;				vec4 C = xform * vec4( right, 1.0 );&#xD;&#xA;				&#xD;&#xA;				vec3 CB = C.xyz - B.xyz;&#xD;&#xA;				vec2 BA = B.xy - A.xy;&#xD;&#xA;				vec2 CA = C.xy - A.xy;&#xD;&#xA;				float lengthBA = length(BA);&#xD;&#xA;				float lengthCA = length(CA);&#xD;&#xA;				float ratio = lengthBA / ( lengthBA + lengthCA );&#xD;&#xA;				vec3 D = B.xyz + ratio * CB.xyz;&#xD;&#xA;				vec3 AD = D - A.xyz;&#xD;&#xA;				vec3 bisect = normalize(AD);&#xD;&#xA;				&#xD;&#xA;				float theta = acos( dot(BA, CA) / (lengthBA * lengthCA) ) / 2.0;&#xD;&#xA;				float AE = 1.0/(sin(theta)*aspect);&#xD;&#xA;				newPos.z += AE/length(AD) * (D.z - A.z);&#xD;&#xA;				newPos.x += bisect.x*AE;&#xD;&#xA;				newPos.y += bisect.y*AE;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;This code gives us the results below.&#xD;&#xA;&#xD;&#xA;[![Screen Shot][4]][4]&#xD;&#xA;&#xD;&#xA;Note, there are a few edge-cases having to do with *almost* backface-culled triangles being flipped by this process, and I began to address this in code, yet decided to simply avoid these cases for now. Perhaps I'll revisit it when I get this project done.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Angle_bisector_theorem&#xD;&#xA;  [2]: https://i.stack.imgur.com/kKiYW.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Pythagorean_theorem&#xD;&#xA;  [4]: https://i.stack.imgur.com/0Gu9i.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13598" PostHistoryTypeId="2" PostId="5101" RevisionGUID="726a72b8-faaf-448a-a5d5-cd6655897cf9" CreationDate="2017-05-12T19:48:09.700" UserId="6622" Text="I understand that ambient light is light that occurs a result of light from a given source refecting off an infinite number of points in a scene, thereby illuminating all objects in the scene uniformly and explains why areas not directly illuminated by a light source in a scene aren't pitch black.&#xD;&#xA;&#xD;&#xA;So I guess ambient light gives everything in the scene the same basic &quot;brightness&quot;. But how does one determine this value? I presume the ambient light is proportional to the primary light source intensity (a floodlight in a bedroom will surely produce more ambient light than a lit match in the same room) and inversely proportional to the scene size (a lamp in a closet surely produces more ambient light than a match in a hall). Is there a formula that gives ambient light &quot;brightness&quot; as a function of scene volume, light source intensity, and any other variables please?&#xD;&#xA;&#xD;&#xA;Please excuse my naivety, as I'm a noob to computer graphics, and only a hobbyist at that.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13599" PostHistoryTypeId="1" PostId="5101" RevisionGUID="726a72b8-faaf-448a-a5d5-cd6655897cf9" CreationDate="2017-05-12T19:48:09.700" UserId="6622" Text="Formula for the ambient light intensity of a scene?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13600" PostHistoryTypeId="3" PostId="5101" RevisionGUID="726a72b8-faaf-448a-a5d5-cd6655897cf9" CreationDate="2017-05-12T19:48:09.700" UserId="6622" Text="|rendering|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13601" PostHistoryTypeId="2" PostId="5102" RevisionGUID="a7eb0a4b-17fe-47b3-97a8-79fce5181d6c" CreationDate="2017-05-12T21:23:44.517" UserId="6623" Text="I have developed a c++ core application, which needs a relatively simple gui, like a mind map. Now i wish to find a multipurpose solution for the visualization. So far my effort:&#xD;&#xA;&#xD;&#xA;- three.js (webgl) in browser&#xD;&#xA;- QT (qml) rendering three.js in a container , also win/lin/osx solution&#xD;&#xA;&#xD;&#xA;everything works and i am enthusiastic to see same code runs on so much platforms. But the problem is, that i use some newly released features of three.js and qt uses an older version. More specific: there is no way to render a css3drenderer object.&#xD;&#xA;&#xD;&#xA;Now i gave up almost and try to find a opengl solution (imgui?) or some funky solution like electron (node.js).&#xD;&#xA;&#xD;&#xA;But it seems to be, that there is no way and i have to develop native apps, may be based on OpenGL ES.&#xD;&#xA;&#xD;&#xA;I will appreciate any concept for my GUI solution" ContentLicense="CC BY-SA 3.0" />
  <row Id="13602" PostHistoryTypeId="1" PostId="5102" RevisionGUID="a7eb0a4b-17fe-47b3-97a8-79fce5181d6c" CreationDate="2017-05-12T21:23:44.517" UserId="6623" Text="Is there a concept for a most cross plattform gui" ContentLicense="CC BY-SA 3.0" />
  <row Id="13603" PostHistoryTypeId="3" PostId="5102" RevisionGUID="a7eb0a4b-17fe-47b3-97a8-79fce5181d6c" CreationDate="2017-05-12T21:23:44.517" UserId="6623" Text="|opengl|webgl|opengl-es|three.js|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13604" PostHistoryTypeId="5" PostId="5102" RevisionGUID="ec4f254a-49f9-4fd3-811d-1da2ffab5ea0" CreationDate="2017-05-13T04:07:55.407" UserId="6546" Comment="Reworded Question and Fixed Spelling/Grammatical Errors" Text="I have developed a C++ core application, which needs a relatively simple GUI, like a mind map. Now I wish to find a multipurpose solution for the visualization. So far my effort:&#xD;&#xA;&#xD;&#xA;- three.js (webgl) in browser&#xD;&#xA;- QT (qml) rendering three.js in a container , also win/lin/osx solution&#xD;&#xA;&#xD;&#xA;Everything works and I am enthusiastic to see the same code run on so many platforms. But the problem is, that I'm using some newly released features of three.js and qt uses an older version. More specific: there is no way to render a css3drenderer object.&#xD;&#xA;&#xD;&#xA;Now I almost gave up and tried to find an OpenGL solution (imgui?) or some funky solution like electron (node.js).&#xD;&#xA;&#xD;&#xA;But it seems to be, that there is no way and I have to develop native apps, may be based on OpenGL ES.&#xD;&#xA;&#xD;&#xA;I will appreciate any concept for my GUI solution" ContentLicense="CC BY-SA 3.0" />
  <row Id="13605" PostHistoryTypeId="4" PostId="5102" RevisionGUID="ec4f254a-49f9-4fd3-811d-1da2ffab5ea0" CreationDate="2017-05-13T04:07:55.407" UserId="6546" Comment="Reworded Question and Fixed Spelling/Grammatical Errors" Text="Is there a concept for a cross platform GUI?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13606" PostHistoryTypeId="24" PostId="5102" RevisionGUID="ec4f254a-49f9-4fd3-811d-1da2ffab5ea0" CreationDate="2017-05-13T04:07:55.407" Comment="Proposed by 6546 approved by 3003, 48 edit id of 244" ContentLicense="CC BY-SA 3.0" />
  <row Id="13607" PostHistoryTypeId="5" PostId="5101" RevisionGUID="c3f815ab-4302-4972-aa3f-57dfdcae5448" CreationDate="2017-05-13T06:42:38.020" UserId="6622" Comment="deleted 1 character in body" Text="I understand that ambient light is light that occurs a result of light from a given source refecting off an infinite number of points in a scene, thereby illuminating all objects in the scene uniformly and explains why areas not directly illuminated by a light source in a scene aren't pitch black.&#xD;&#xA;&#xD;&#xA;So I guess ambient light gives everything in the scene the same basic &quot;brightness&quot;. But how does one determine this value? I presume the ambient light is proportional to the primary light source intensity (a floodlight in a bedroom will surely produce more ambient light than a lit match in the same room) and inversely proportional to the scene size (a lamp in a closet surely produces more ambient light than a lamp in a hall). Is there a formula that gives ambient light &quot;brightness&quot; as a function of scene volume, light source intensity, and any other variables please?&#xD;&#xA;&#xD;&#xA;Please excuse my naivety, as I'm a noob to computer graphics, and only a hobbyist at that.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13608" PostHistoryTypeId="2" PostId="5103" RevisionGUID="e3b52848-8fe9-4398-8a8d-2e15b586f04a" CreationDate="2017-05-13T12:52:32.560" UserId="310" Text="Using an 'ambient light' term in your lighting calculations is an approximation of the indirect light reflected around the scene. Usually it's up to the artist to choose an appropriate value. There isn't really a formula, because the indirect light is dependent on many factors:&#xD;&#xA;&#xD;&#xA; - Light intensity&#xD;&#xA; - Light shape&#xD;&#xA; - The BRDFs of the surfaces the light will bounce off of&#xD;&#xA; - Visibility to the light source (Think the back of a deep cave)&#xD;&#xA; - etc.&#xD;&#xA;&#xD;&#xA;You *could* use some kind of formula to get an approximate value, based on these factors, but, in my opinion, it's simpler just to do it manually per scene. Or, you can remove it entirely, and use more sophisticated methods to calculate indirect lighting." ContentLicense="CC BY-SA 3.0" />
  <row Id="13609" PostHistoryTypeId="5" PostId="5100" RevisionGUID="0d33814b-d849-488c-b067-6f4686716221" CreationDate="2017-05-13T13:07:48.043" UserId="6596" Comment="corrected reference" Text="Given triangle ▲ABC, we bisect angle ∠BAC with line AD, derived with [Angle Bisector Theorem][1]:&#xD;&#xA;&#xD;&#xA;BA / BD = CA / CD&#xD;&#xA;[![Triangle Inset Diagram][2]][2]&#xD;&#xA;Point E represents our objective refined position on the desired resulting inset triangle. As it lies upon angle bisector AD, it is equidistant from sides BA &amp; CA, forming identical right triangles ▲AFE &amp; ▲AGE. We can now use [Sine for Right Triangles][3] to find the length of AE:&#xD;&#xA;&#xD;&#xA;AE = EG / Sin(∠EAG)&#xD;&#xA;&#xD;&#xA;That's all the math we need, so let's cook up some GLSL!&#xD;&#xA;&#xD;&#xA;  We start off with all the typical attributes: position, normal, and transformation matrices, but since the vertex shader only works on a single vertex, we need to add the neighboring vertices as additional attributes. This way, each vertex will find its own &quot;point E&quot;, creating the resulting inset triangle. (Note: I don't call them &quot;B&quot; &amp; &quot;C&quot; here, because they are not yet in *screen space*.)&#xD;&#xA;&#xD;&#xA;    	attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;		attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;&#xD;&#xA;  Speaking of screen space, I'm also including the aspect ratio of the display, (and making it a uniform, in case the window is resized.)&#xD;&#xA;&#xD;&#xA;  After preparing varying normals for the fragment shader, and transforming the face into clipping-space, we can get down to the business of applying the above math:&#xD;&#xA;&#xD;&#xA;			attribute vec3 left; //vertex to the left of this vertex&#xD;&#xA;			attribute vec3 right; //vertex to the right of this vertex&#xD;&#xA;			uniform float aspect;&#xD;&#xA;			varying vec3 vNormal;&#xD;&#xA;			varying vec2 vUv;&#xD;&#xA;&#xD;&#xA;			void main() {&#xD;&#xA;				vNormal = normal;&#xD;&#xA;				vUv = uv;&#xD;&#xA;				&#xD;&#xA;				mat4 xform= projectionMatrix * modelViewMatrix;&#xD;&#xA;				vec4 A = xform * vec4( position, 1.0 );&#xD;&#xA;				vec4 B = xform * vec4( left, 1.0 );&#xD;&#xA;				vec4 C = xform * vec4( right, 1.0 );&#xD;&#xA;				&#xD;&#xA;				vec3 CB = C.xyz - B.xyz;&#xD;&#xA;				vec2 BA = B.xy - A.xy;&#xD;&#xA;				vec2 CA = C.xy - A.xy;&#xD;&#xA;				float lengthBA = length(BA);&#xD;&#xA;				float lengthCA = length(CA);&#xD;&#xA;				float ratio = lengthBA / ( lengthBA + lengthCA );&#xD;&#xA;				vec3 D = B.xyz + ratio * CB.xyz;&#xD;&#xA;				vec3 AD = D - A.xyz;&#xD;&#xA;				vec3 bisect = normalize(AD);&#xD;&#xA;				&#xD;&#xA;				float theta = acos( dot(BA, CA) / (lengthBA * lengthCA) ) / 2.0;&#xD;&#xA;				float AE = 1.0/(sin(theta)*aspect);&#xD;&#xA;				newPos.z += AE/length(AD) * (D.z - A.z);&#xD;&#xA;				newPos.x += bisect.x*AE;&#xD;&#xA;				newPos.y += bisect.y*AE;&#xD;&#xA;				&#xD;&#xA;				gl_Position = newPos;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;This code gives us the results below.&#xD;&#xA;&#xD;&#xA;[![Screen Shot][4]][4]&#xD;&#xA;&#xD;&#xA;Note, there are a few edge-cases having to do with *almost* backface-culled triangles being flipped by this process, and I began to address this in code, yet decided to simply avoid these cases for now. Perhaps I'll revisit it when I get this project done.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Angle_bisector_theorem&#xD;&#xA;  [2]: https://i.stack.imgur.com/kKiYW.png&#xD;&#xA;  [3]: https://en.wikibooks.org/wiki/Geometry/Right_Triangles_and_Pythagorean_Theorem&#xD;&#xA;  [4]: https://i.stack.imgur.com/0Gu9i.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13610" PostHistoryTypeId="5" PostId="5086" RevisionGUID="c81375d2-1744-47b3-9a82-28cd37a4daa8" CreationDate="2017-05-13T13:09:17.780" UserId="6596" Comment="added 35 characters in body" Text="I need to offset all (blue) triangles, each independently of the others, using the vertex-shader. In order to manipulate the triangle as a whole, I've created custom (vec3) attributes for each vertex (red) representing the leftward (purple) and rightward (green) neighboring vertices. From this, I need to derive the orange point, equidistant (in ***screen space***) from both adjoining edges. With three such orange points derived from each triangle, the processed (orange) triangle is passed on to the fragment shader.&#xD;&#xA;&#xD;&#xA;[![per vertex operation][1]][1]&#xD;&#xA;[![offset triangles][2]][2]&#xD;&#xA;&#xD;&#xA;Ideally, the triangle will be culled (as in backfacing/ not rendered) if the offsets negate any available space within the triangle, such as in the second triangle in the second picture.&#xD;&#xA;&#xD;&#xA;I'm using [THREE.BufferGeometry()][3] as my data structure.&#xD;&#xA;&#xD;&#xA;Here is a screen shot of the effect I'm aiming for:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hN8dz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tmoMe.png&#xD;&#xA;  [3]: http://threejs.org/docs/#api/core/BufferGeometry&#xD;&#xA;  [4]: https://i.stack.imgur.com/W9AzA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13611" PostHistoryTypeId="2" PostId="5104" RevisionGUID="46d5cbcc-5b51-4dcb-9835-8694522f74d3" CreationDate="2017-05-14T14:16:19.003" UserId="6628" Text="I came across [this YouTube video](https://youtu.be/7oSH-aZKyU8?t=72) of a flip-dot display (physical b/w pixels) showing the reverse of an effect that might be called dissolve or dispersion, i.e. a text emerges from noise by pixels moving in to form letters.&#xD;&#xA;&#xD;&#xA;Using those words, I found [After Effects: Text That Blows Away Like Sand][1] which has a _Shatter_ effect, apparently a 3D [particle system][2] with physics simulation.&#xD;&#xA;&#xD;&#xA;For a particle system, I can imagine that &quot;dissolving&quot; every pixel (of a character) randomly isn't too hard. Reversing the effect as shown in the video could use a precalculated sequence or even just animated sprites for each letter. Or, each pixel in the noise gets chosen to gravitate towards a letter (seems more complicated, may require clustering).&#xD;&#xA;&#xD;&#xA;Is there an approach does does not require particles?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.macprovideo.com/hub/after-effects/after-effects-text-that-blows-away-like-sand&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Particle_system" ContentLicense="CC BY-SA 3.0" />
  <row Id="13612" PostHistoryTypeId="1" PostId="5104" RevisionGUID="46d5cbcc-5b51-4dcb-9835-8694522f74d3" CreationDate="2017-05-14T14:16:19.003" UserId="6628" Text="Pixel dispersion (dissolving) algorithms" ContentLicense="CC BY-SA 3.0" />
  <row Id="13613" PostHistoryTypeId="3" PostId="5104" RevisionGUID="46d5cbcc-5b51-4dcb-9835-8694522f74d3" CreationDate="2017-05-14T14:16:19.003" UserId="6628" Text="|image-processing|animation|filtering|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13614" PostHistoryTypeId="5" PostId="5104" RevisionGUID="47fc26a6-1c11-483a-bd4a-e516e558fd4a" CreationDate="2017-05-14T15:07:00.200" UserId="6628" Comment="add effect demo and sources" Text="I came across [this YouTube video](https://youtu.be/7oSH-aZKyU8?t=72) of a flip-dot display (physical b/w pixels) showing the reverse of an effect that might be called dissolve or dispersion, i.e. a text emerges from noise by pixels moving in to form letters.&#xD;&#xA;&#xD;&#xA;Using those words, I found [After Effects: Text That Blows Away Like Sand][1] which has a _Shatter_ effect, apparently a 3D [particle system][2] with physics simulation.&#xD;&#xA;&#xD;&#xA;For a particle system, I can imagine that &quot;dissolving&quot; every pixel (of a character) randomly isn't too hard. Reversing the effect as shown in the video could use a precalculated sequence or even just animated sprites for each letter. Or, each pixel in the noise gets chosen to gravitate towards a letter (seems more complicated, may require clustering).&#xD;&#xA;&#xD;&#xA;Is there an approach that does not require particles (i.e. that is less memory-expensive)?&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;&#xD;&#xA;Additional info on this or similar effects:&#xD;&#xA;&#xD;&#xA;*   Particles text effects&#xD;&#xA;&#xD;&#xA;    Uses particles with a seek behavior to make up a word.&#xD;&#xA;    The word is loaded into memory so that each particle can figure out their own position they need to seek.&#xD;&#xA;    Inspired by Daniel Shiffman's arrival explantion from The Nature of Code. (natureofcode.com)&#xD;&#xA;&#xD;&#xA;    https://www.openprocessing.org/sketch/377231&#xD;&#xA;&#xD;&#xA;    The reference resolves to&#xD;&#xA;    - http://natureofcode.com/book/chapter-4-particle-systems&#xD;&#xA;    - http://natureofcode.com/book/chapter-6-autonomous-agents/ (6.4 Arriving Behavior)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.macprovideo.com/hub/after-effects/after-effects-text-that-blows-away-like-sand&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Particle_system" ContentLicense="CC BY-SA 3.0" />
  <row Id="13616" PostHistoryTypeId="5" PostId="5104" RevisionGUID="1fc3f853-c14e-45ac-a62d-6f08dca34386" CreationDate="2017-05-14T18:30:45.640" UserId="6628" Comment="fix grammar, remove non-essential" Text="I came across [this YouTube video](https://youtu.be/7oSH-aZKyU8?t=72) of a flip-dot display (physical b/w pixels) showing the reverse of an effect that might be called dissolve or dispersion, i.e. a text emerges from noise by pixels moving in to form letters.&#xD;&#xA;&#xD;&#xA;I found [After Effects: Text That Blows Away Like Sand][1] which has a _Shatter_ effect, apparently a 3D [particle system][2] with physics simulation.&#xD;&#xA;&#xD;&#xA;For a particle system, I can imagine that &quot;dissolving&quot; every pixel (of a character) randomly isn't too hard. Reversing the effect as shown in the video could use a precalculated sequence or even just animated sprites for each letter. Or, each pixel in the noise gets chosen to gravitate towards a letter (seems more complicated, may require clustering).&#xD;&#xA;&#xD;&#xA;Is there an approach that does not require particles (i.e. less memory-expensive)?&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;&#xD;&#xA;Additional info on this or similar effects:&#xD;&#xA;&#xD;&#xA;*   Particles text effects&#xD;&#xA;&#xD;&#xA;    Uses particles with a seek behavior to make up a word.&#xD;&#xA;    The word is loaded into memory so that each particle can figure out their own position they need to seek.&#xD;&#xA;    Inspired by Daniel Shiffman's arrival explantion from The Nature of Code. (natureofcode.com)&#xD;&#xA;&#xD;&#xA;    https://www.openprocessing.org/sketch/377231&#xD;&#xA;&#xD;&#xA;    The reference resolves to&#xD;&#xA;    - http://natureofcode.com/book/chapter-4-particle-systems&#xD;&#xA;    - http://natureofcode.com/book/chapter-6-autonomous-agents/ (6.4 Arriving Behavior)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.macprovideo.com/hub/after-effects/after-effects-text-that-blows-away-like-sand&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Particle_system" ContentLicense="CC BY-SA 3.0" />
  <row Id="13617" PostHistoryTypeId="2" PostId="5105" RevisionGUID="d88cbd58-3c0c-48a9-8bb5-a4354d1251ac" CreationDate="2017-05-14T19:05:59.660" UserId="6546" Text="I'm developing a general Mesh class with the help of [LearnOpenGL][1]. In the example he creates a class which assumes that you want to generate a VAO, VBO, and an EBO but I don't usually use EBOs so I only want to generate an EBO under certain circumstances. So if I decide not to generate an EBO then I want to set my EBO to a number which cannot be generated by `glGenBuffers`.&#xD;&#xA;&#xD;&#xA;    // Draw Mesh&#xD;&#xA;    glBindVertexArray(this-&gt;VAO);&#xD;&#xA;&#xD;&#xA;    if(EBO not in range generated by glGenBuffers)&#xD;&#xA;	    glDrawArrays(GL_TRIANGLES, 0, numVertices);&#xD;&#xA;    } else {&#xD;&#xA;        glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;My question is what is the range that a buffer object's name can be in?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13618" PostHistoryTypeId="1" PostId="5105" RevisionGUID="d88cbd58-3c0c-48a9-8bb5-a4354d1251ac" CreationDate="2017-05-14T19:05:59.660" UserId="6546" Text="Range of integers returned by glGenBuffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13619" PostHistoryTypeId="3" PostId="5105" RevisionGUID="d88cbd58-3c0c-48a9-8bb5-a4354d1251ac" CreationDate="2017-05-14T19:05:59.660" UserId="6546" Text="|opengl|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13621" PostHistoryTypeId="2" PostId="5106" RevisionGUID="7208ca54-fbfd-4023-9eaf-31ef55b18664" CreationDate="2017-05-14T20:10:00.883" UserId="48" Text="According to the OpenGL spec, any integer other than zero can be a potential name. Zero is the only value that's guaranteed not to be an object name.&#xD;&#xA;&#xD;&#xA;Relevant quote from [the spec](https://khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf):&#xD;&#xA;&#xD;&#xA;&gt; **2.6.1.1    Name Spaces, Name Generation, and Object Creation**&#xD;&#xA;&#xD;&#xA;&gt; Each object type has a corresponding _name space_.  Names of objects are represented by unsigned integers of type `uint`.  The name zero is reserved by the GL; for some object types, zero names a _default object_ of that type, and in others zero will never correspond to an actual instance of that object type.&#xD;&#xA;&#xD;&#xA;&gt; Names of most types of objects are created by _generating_ unused names using commands starting with **Gen** followed by the object type.  For example, the command **GenBuffers** returns one or more previously unused buffer object names." ContentLicense="CC BY-SA 3.0" />
  <row Id="13625" PostHistoryTypeId="5" PostId="5097" RevisionGUID="af148ba4-6b4b-4621-a4b4-d0636a0a28a7" CreationDate="2017-05-15T03:05:39.467" UserId="6546" Comment="Fixed Spelling Mistakes and Restructured" Text="As the title says I have been trying to understand the normal interpolation for the Phong shading/lighting model. I am unsure of the equation to calculate the normal but I have come across this equation:&#xD;&#xA; &#xD;&#xA;N=Na*α+Nb(1−α)&#xD;&#xA;&#xD;&#xA;Where N is the interpolated vector, Na and Nb are unit vectors to interpolate between and I'm assuming α is the percentage between the two. However in using this model as shown here: &#xD;&#xA;&#xD;&#xA;    public static Vector3 lerp(Vector3 a, Vector3 b, double alpha){&#xD;&#xA;		 return (a.multiply(alpha)).add(b.multiply(1-alpha)).normalize();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I am not obtaining the correct results, so any advice on the topic, such as what I may be doing wrong etc, would be appreciated.&#xD;&#xA;&#xD;&#xA;EDIT: I found my mistake in the interpolation, here is the updated method for those who are interested:&#xD;&#xA;&#xD;&#xA;    public static Vector3 lerp(Vector3 a, Vector3 b, double gradient){&#xD;&#xA;	    return a.add((b.minus(a)).multiply(gradient));&#xD;&#xA;	}" ContentLicense="CC BY-SA 3.0" />
  <row Id="13626" PostHistoryTypeId="24" PostId="5097" RevisionGUID="af148ba4-6b4b-4621-a4b4-d0636a0a28a7" CreationDate="2017-05-15T03:05:39.467" Comment="Proposed by 6546 approved by 48, 3073 edit id of 245" ContentLicense="CC BY-SA 3.0" />
  <row Id="13627" PostHistoryTypeId="33" PostId="5085" RevisionGUID="4c791ac5-032a-4584-b9da-aea4524310f4" CreationDate="2017-05-15T08:57:35.653" UserId="6603" Comment="29" />
  <row Id="13628" PostHistoryTypeId="2" PostId="5108" RevisionGUID="4b70e1b1-0c1e-42be-96c4-e5e7a169bc9d" CreationDate="2017-05-15T10:35:13.343" UserId="6175" Text="If I have some 3d points, how can I discover parallel planes within them (not just arbitrary planes).&#xD;&#xA;&#xD;&#xA;I want to know how many &quot;levels&quot; or &quot;floors&quot; something can travel within, after it has done so, so I want to cluster the positions into planes.&#xD;&#xA;&#xD;&#xA;Some of them might not be in a plane, most of them are noisy (not perfectly planar), and I have no knowledge of the world orientation, so the planes aren't necessarily orthogonal to some known axis.&#xD;&#xA;&#xD;&#xA;I know one way is a 3d-hough transform, but is there something better?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13629" PostHistoryTypeId="1" PostId="5108" RevisionGUID="4b70e1b1-0c1e-42be-96c4-e5e7a169bc9d" CreationDate="2017-05-15T10:35:13.343" UserId="6175" Text="Best way to group 3d points into planes, if any" ContentLicense="CC BY-SA 3.0" />
  <row Id="13630" PostHistoryTypeId="3" PostId="5108" RevisionGUID="4b70e1b1-0c1e-42be-96c4-e5e7a169bc9d" CreationDate="2017-05-15T10:35:13.343" UserId="6175" Text="|3d|mathematics|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13631" PostHistoryTypeId="2" PostId="5109" RevisionGUID="40fbe9db-32a5-43c5-8bfe-85b88fb8a0fd" CreationDate="2017-05-15T12:00:36.697" UserId="6633" Text="&#xD;&#xA;The &quot;Ambient&quot; term more accurately is described as the light emitted by the object itself. While it's not wrong to see it as a constant which approximates indirect lighting, it's still more accurate to call it the former, especially for the thinking process.&#xD;&#xA;&#xD;&#xA;As such, the answer depends on your scene. Considering that all objects emit their own &quot;light&quot;, there is no way to manually set a global ambient term without sacrificing image quality, as no object will be equally shaded compared to the next one. That causes the brain to perceive it as &quot;wrong looking&quot;.&#xD;&#xA;&#xD;&#xA;So, there is no formula for ambient, because ambient in the way it has been introduced a few decades ago has no basis in reality. The values are set based on the scenes, to make sure they look &quot;good enough&quot;.&#xD;&#xA;&#xD;&#xA;Indirect light though, as found in modern graphics engines, can be calculated on the fly and removes the need for a manually set ambient term completely.&#xD;&#xA;&#xD;&#xA;In short: For &quot;ambient&quot; they guess, for &quot;indirect light&quot; they calculate.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13636" PostHistoryTypeId="5" PostId="5104" RevisionGUID="3f6f5b90-8e0d-48ee-8a4a-1984bedfa160" CreationDate="2017-05-15T15:32:36.933" UserId="6628" Comment="add sample animation" Text="I came across [this YouTube video](https://youtu.be/7oSH-aZKyU8?t=72) of a flip-dot display (physical b/w pixels) showing the reverse of an effect that might be called dissolve or dispersion, i.e. a text emerges from noise by pixels moving in to form letters:&#xD;&#xA;&#xD;&#xA;![animated gif extract from youtu.be/7oSH-aZKyU8 copyright BREAKFAST NY](https://i.stack.imgur.com/9BXg0.gif)(source: [BREAKFAST NY](https://youtu.be/7oSH-aZKyU8))&#xD;&#xA;&#xD;&#xA;I found [After Effects: Text That Blows Away Like Sand][1] which has a _Shatter_ effect, apparently a 3D [particle system][2] with physics simulation.&#xD;&#xA;&#xD;&#xA;For a particle system, I can imagine that &quot;dissolving&quot; every pixel (of a character) randomly isn't too hard. Reversing the effect as shown in the video could use a precalculated sequence or even just animated sprites for each letter. Or, each pixel in the noise gets chosen to gravitate towards a letter (seems more complicated, may require clustering).&#xD;&#xA;&#xD;&#xA;Is there an approach that does not require particles (i.e. less memory-expensive)?&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;&#xD;&#xA;Additional info on this or similar effects:&#xD;&#xA;&#xD;&#xA;*   Particles text effects&#xD;&#xA;&#xD;&#xA;    Uses particles with a seek behavior to make up a word.&#xD;&#xA;    The word is loaded into memory so that each particle can figure out their own position they need to seek.&#xD;&#xA;    Inspired by Daniel Shiffman's arrival explantion from The Nature of Code. (natureofcode.com)&#xD;&#xA;&#xD;&#xA;    https://www.openprocessing.org/sketch/377231&#xD;&#xA;&#xD;&#xA;    The reference resolves to&#xD;&#xA;    - http://natureofcode.com/book/chapter-4-particle-systems&#xD;&#xA;    - http://natureofcode.com/book/chapter-6-autonomous-agents/ (6.4 Arriving Behavior)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.macprovideo.com/hub/after-effects/after-effects-text-that-blows-away-like-sand&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Particle_system" ContentLicense="CC BY-SA 3.0" />
  <row Id="13639" PostHistoryTypeId="2" PostId="5112" RevisionGUID="dddc33d8-92dd-41c1-a2a7-5c875066fbd2" CreationDate="2017-05-15T19:07:39.017" UserId="6596" Text="You could do this entirely within an OpenGL/WebGL fragment shader:&#xD;&#xA;&#xD;&#xA;Attach the image you wish to emerge as a texture/sampler2D.&#xD;&#xA;Attach uniforms for the current time, as well as the time you want the effect to finish.&#xD;&#xA;&#xD;&#xA;    uniform sampler2D myTexture;&#xD;&#xA;    uniform float currentTime;&#xD;&#xA;    uniform float finishTime;&#xD;&#xA;&#xD;&#xA;Note, the above *clamp* stops the effect at the appropriate time, as well as sets a maximum (10 sec, in this example) duration of the effect.&#xD;&#xA;&#xD;&#xA;Next, apply a deterministic pseudo-random noise algorithm for displacing pixels a given distance and compass direction. Something like:&#xD;&#xA;&#xD;&#xA;    float rand(vec2 co){&#xD;&#xA;    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);&#xD;&#xA;    }&#xD;&#xA;    float R = rand(thisPixel.xy);&#xD;&#xA;&#xD;&#xA;    var float timeLeft = clamp((finishTime - currentTime) * R, 0.0, 10000.0);&#xD;&#xA;&#xD;&#xA;    float direction = classic1dPerlinNoise( R + currentTime );&#xD;&#xA;    float offsetX = thisPixel.x + sin(direction) * timeLeft / 500.0;&#xD;&#xA;    float offsetY = thisPixel.Y + cos(direction) * timeLeft / 500.0;&#xD;&#xA;    vec2 texCoord = vec2( offsetX, offsetY );&#xD;&#xA;&#xD;&#xA;Look up your texture sample.&#xD;&#xA;&#xD;&#xA;    gl_FragColor = gl_Color * texture2D(myTexture, texCoord);&#xD;&#xA;&#xD;&#xA;Voila! While the pixels may not navigate around each other, they'll at least wander into place, each arriving at it's own distinct time within the time frame allotted to the effect, and using very little memory and CPU time." ContentLicense="CC BY-SA 3.0" />
  <row Id="13644" PostHistoryTypeId="5" PostId="5112" RevisionGUID="a5f0bd6a-b227-4cd8-897d-cd1164fe0352" CreationDate="2017-05-15T20:07:57.437" UserId="6596" Comment="added 64 characters in body" Text="You could do this entirely within an OpenGL/WebGL fragment shader:&#xD;&#xA;&#xD;&#xA;Attach the image you wish to emerge as a texture/sampler2D.&#xD;&#xA;Attach uniforms for the current time, as well as the time you want the effect to finish.&#xD;&#xA;&#xD;&#xA;    uniform sampler2D myTexture;&#xD;&#xA;    uniform float currentTime;&#xD;&#xA;    uniform float finishTime;&#xD;&#xA;&#xD;&#xA;    #define TWO_PI 6.283185307179586476925286766559&#xD;&#xA;&#xD;&#xA;Next, apply a deterministic pseudo-random noise algorithm for displacing pixels a given distance and compass direction. Something like:&#xD;&#xA;&#xD;&#xA;    float rand(vec2 co){&#xD;&#xA;    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);&#xD;&#xA;    }&#xD;&#xA;    float R = rand(thisPixel.xy);&#xD;&#xA;&#xD;&#xA;    var float timeLeft = clamp((finishTime - currentTime) * R, 0.0, 10000.0);&#xD;&#xA;&#xD;&#xA;    float direction = classic1dPerlinNoise( R + currentTime ) * TWO_PI;&#xD;&#xA;    float offsetX = thisPixel.x + sin(direction) * timeLeft / 500.0;&#xD;&#xA;    float offsetY = thisPixel.Y + cos(direction) * timeLeft / 500.0;&#xD;&#xA;    vec2 texCoord = vec2( offsetX, offsetY );&#xD;&#xA;&#xD;&#xA;Note, the above *clamp* stops the effect at the appropriate time, as well as sets a maximum (10 sec, in this example) duration of the effect.&#xD;&#xA;&#xD;&#xA;Finally, look up your texture sample:&#xD;&#xA;&#xD;&#xA;    gl_FragColor = gl_Color * texture2D(myTexture, texCoord);&#xD;&#xA;&#xD;&#xA;Voila! While the pixels may not navigate around each other, they'll at least wander into place, each arriving at it's own distinct time within the timeframe allotted to the effect, and using very little memory and CPU time." ContentLicense="CC BY-SA 3.0" />
  <row Id="13645" PostHistoryTypeId="5" PostId="5104" RevisionGUID="0d030c2a-98a4-4067-934b-10f412fd3652" CreationDate="2017-05-15T20:26:27.320" UserId="6628" Comment="restructure, add example" Text="[This YouTube video](https://youtu.be/7oSH-aZKyU8?t=72) of a flip-dot display (physical b/w pixels) shows the reverse of an effect that might be called dissolve or dispersion, i.e. a text emerges from noise by pixels moving in to form letters. Here's a short cropped clip showing just the &quot;crystallization&quot; (wouldn't that be an appropriate name?):&#xD;&#xA;&#xD;&#xA;![animated gif extract from youtu.be/7oSH-aZKyU8 copyright BREAKFAST NY](https://i.stack.imgur.com/9BXg0.gif)(source: [BREAKFAST NY](https://youtu.be/7oSH-aZKyU8))&#xD;&#xA;&#xD;&#xA;Looking for more info on this or similar effects I found [After Effects: Text That Blows Away Like Sand][1] which has a _Shatter_ effect, apparently a 3D [particle system][2] with physics simulation.&#xD;&#xA;&#xD;&#xA;For a particle system, I can imagine that &quot;dissolving&quot; every pixel (of a character) randomly wouldn't be too hard. Reversing the effect as shown in the video could be done using a precalculated sequence or even just animated sprites for each letter. Or, each pixel in the noise gets chosen to gravitate towards a letter (seems more complicated, may require clustering).&#xD;&#xA;&#xD;&#xA;Then I found an implementation and live demo:&#xD;&#xA;&#xD;&#xA;*   _Particles text effects_&#xD;&#xA;&#xD;&#xA;    Uses particles with a seek behavior to make up a word.&#xD;&#xA;    The word is loaded into memory so that each particle can figure out their own position they need to seek.&#xD;&#xA;    Inspired by Daniel Shiffman's arrival explantion from The Nature of Code. (natureofcode.com)&#xD;&#xA;&#xD;&#xA;    https://www.openprocessing.org/sketch/377231&#xD;&#xA;&#xD;&#xA;    The reference resolves to&#xD;&#xA;    - http://natureofcode.com/book/chapter-4-particle-systems&#xD;&#xA;    - http://natureofcode.com/book/chapter-6-autonomous-agents/ (6.4 Arriving Behavior)&#xD;&#xA;&#xD;&#xA;I think the effect is very similar, so I think they used a particle system.&#xD;&#xA;&#xD;&#xA;**Q: Is there an approach that does not require particles (i.e. less memory-expensive)?**&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;&#xD;&#xA;Just for comparison, here's an attempt at creating a &quot;normal&quot; animated noise dissolve ([random dither](https://math.stackexchange.com/questions/2280900/pseudorandom-binary-mask-for-animated-dissolve-effect)), [as suggested in a comment](https://computergraphics.stackexchange.com/questions/5104/pixel-dispersion-dissolving-algorithms#comment7504_5104), but I think it's obvious that the pixels in the original _do_ move and it's not just a binary blending effect:&#xD;&#xA;&#xD;&#xA;![Imgur](https://i.stack.imgur.com/gy8az.gif)&#xD;&#xA;&#xD;&#xA;It requires at least one random value for each pixel: on which frame of the animation to become active.&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;&#xD;&#xA;Next will be [mixing it up](https://computergraphics.stackexchange.com/questions/5104/pixel-dispersion-dissolving-algorithms#comment7514_5104)..&#xD;&#xA;&#xD;&#xA;  [1]: https://www.macprovideo.com/hub/after-effects/after-effects-text-that-blows-away-like-sand&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Particle_system" ContentLicense="CC BY-SA 3.0" />
  <row Id="13646" PostHistoryTypeId="34" PostId="5067" RevisionGUID="7859a319-94ab-47da-b131-6b9d3c3344e6" CreationDate="2017-05-15T21:53:52.680" UserId="-1" Comment="28" />
  <row Id="13648" PostHistoryTypeId="2" PostId="5113" RevisionGUID="dbca266f-253d-47fb-9aa4-98fbee99ba96" CreationDate="2017-05-15T22:41:07.660" UserId="6063" Text="The formula you are seeking (and implying with the examples of a match and a lamp) is really a Radiosity formula - at which point we have to stop using the term &quot;ambient light&quot;, as with Radiosity, everything (light source and surfaces of all scene objects including) is just energy, only converted to the monitor's RGB values at the last [rendering] stage.&#xD;&#xA;&#xD;&#xA;As a 10,000 ft overview, during radiosity, you break up all polygons into patches, and it's the FormFactor portion of the formula that takes care of how much energy of the current patch ends up at the target patch.&#xD;&#xA;&#xD;&#xA;Going back to your examples - a match will have different amount of starting energy than a lamp. Also, the distance from the light source to the closet walls vs hall walls will ensure a drastically different amount of energy arriving at those patches (due to the distance falloff)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13649" PostHistoryTypeId="2" PostId="5114" RevisionGUID="e32ce65f-b4f4-4801-b3ac-9f3872e09937" CreationDate="2017-05-16T03:57:10.810" UserId="1952" Text="The short answer: no, but if you are interested in details, please keep reading (:&#xD;&#xA;&#xD;&#xA;About lighting units&#xD;&#xA;--------------------&#xD;&#xA;&#xD;&#xA;Light “brightness” is indeed quite poor/ambiguous layman’s definition for brightness of a light source. Below is a list of different lighting properties/units commonly used in lighting calculations that define the light “brightness”. I listed both [radiometric][1] and [photometric][2] [in brackets] properties/units. Radiometric units are Human Visual System (HVS) neutral &quot;physical&quot; units defined based on **Watts (W)**, while photometric units are HVS weighted units defined based on **Lumens (lm)**.&#xD;&#xA;&#xD;&#xA;Photometric units are commonly used in rendering because practically all consumer image input and output devices operate in these units as they are designed &amp; optimized for image acquisition &amp; consumption by normal [tristimulus][3] ([LMS][4]) HVS. Proper conversion between photometric &amp; radiometric units isn’t simply a matter of multiplication by some factor (like between kilometers &amp; miles or kilograms &amp; pounds), but different projection from [Spectral Power Distribution (SPD)][5] of visible light spectrum (explained later). Some people use constant [luminous efficacy][6] of 683 **lm/W** to convert between the units, but this has very little touch with reality and results in unrealistic values.&#xD;&#xA;&#xD;&#xA; - [Radiant Flux][7] in **Watts (W)** [[Luminous Flux][8] in **Lumen (lm)**] - Total energy emitted by a light (regardless&#xD;&#xA;   of shape or size)&#xD;&#xA; - [Radiant Exitance][9] in **W/m^2** [[Luminous Exitance][10] in **lm/m^2** or **Lux**] - Energy emitted by a light per unit area to all directions (think different size light sources with equivalent Radiant Flux)&#xD;&#xA; - [Radiant Intensity][11] in **W/sr** (sr=steradian) [[Luminous Intensity][12] in **lm/sr** or **Candela**] - Energy emitted by a light to certain direction (think of a spot vs omni light with equivalent Radiant Flux)&#xD;&#xA; - [Radiance][13] in **W/sr/m^2** [[Luminance][14] in **lm/sr/m^2** or **Nits**] - Energy that falls on a patch of surface from some direction (e.g. pixel on screen or patch of surface from certain direction)&#xD;&#xA; - [Irradiance][15] in **W/m^2** [[Illuminance][10] in **lm/m^2** or **Lux**] - Energy that falls on a patch of surface regardless of direction (e.g. hemispherical sky illuminating a patch of ground).&#xD;&#xA;&#xD;&#xA;It’s important to understand the difference between these properties when performing lighting calculations, just like it is important not to confuse properties of length and speed when doing physics calculations. There are various other light properties but having good grasp of the above gets you pretty far already.&#xD;&#xA;&#xD;&#xA;Visible light spectrum and RGB projection&#xD;&#xA;-----------------------------------------&#xD;&#xA;&#xD;&#xA;Visible light spectrum contains “infinite” number of electromagnetic wavelengths from ~390nm to ~730nm.&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The energy spectrum emitted by light is defined with SPD (in **W/m^2/nm**) and you can calculate the “HVS neutral” physical light intensity, i.e. Radiant Exitance $M_e$ (in **W/m^2**) by integrating the spectrum over the visible light range:&#xD;&#xA;$$M_e=\int_{390}^{730} S(\lambda)d\lambda$$&#xD;&#xA;However, RGB color space is defined in photometric units by projecting SPD using HVS weighted color matching functions. This projection is done because storing SPD would consume immense amount of memory for little gain for image visualization purposes. The projection of SDP to RGB is defined with integrals over the visible light range as follows:&#xD;&#xA;$$R=\int_{390}^{730} S(\lambda)\bar{r}(\lambda)d\lambda$$&#xD;&#xA;$$G=\int_{390}^{730} S(\lambda)\bar{g}(\lambda)d\lambda$$&#xD;&#xA;$$B=\int_{390}^{730} S(\lambda)\bar{b}(\lambda)d\lambda$$&#xD;&#xA;CIE 1931 defines standard observer RGB color matching functions as shown below, based on measurement of 10 human observers&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;As you can see the functions are not discrete wavelengths for RGB, but rather weighted averages of (overlapping) wavelengths.&#xD;&#xA;&#xD;&#xA;It’s not possible to unambiguously calculate Radiant Exitance from RGB values because many different SDF’s may resulting different Radiant Exitance but project to the same RGB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Radiometry&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photometry_(optics)&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/CIE_1931_color_space#Tristimulus_values&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/LMS_color_space&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Spectral_power_distribution&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Luminous_efficacy&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Radiant_flux&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Luminous_flux&#xD;&#xA;  [9]: https://en.wikipedia.org/wiki/Radiant_exitance&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Illuminance&#xD;&#xA;  [11]: https://en.wikipedia.org/wiki/Radiant_intensity&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Luminous_intensity&#xD;&#xA;  [13]: https://en.wikipedia.org/wiki/Radiance&#xD;&#xA;  [14]: https://en.wikipedia.org/wiki/Luminance&#xD;&#xA;  [15]: https://en.wikipedia.org/wiki/Irradiance&#xD;&#xA;  [16]: https://i.stack.imgur.com/makY5.png&#xD;&#xA;  [17]: https://i.stack.imgur.com/yDQwT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13650" PostHistoryTypeId="5" PostId="5114" RevisionGUID="e9ad9bcb-5650-4b52-ac01-6043f355c2da" CreationDate="2017-05-16T04:30:49.343" UserId="1952" Comment="deleted 6 characters in body" Text="The short answer: no, but if you are interested in details, please keep reading (:&#xD;&#xA;&#xD;&#xA;About lighting units&#xD;&#xA;--------------------&#xD;&#xA;&#xD;&#xA;Light “brightness” is indeed quite poor/ambiguous layman’s definition for brightness of a light source. Below is a list of different lighting properties/units commonly used in lighting calculations that define the light “brightness”. I listed both [radiometric][1] and [photometric][2] [in brackets] properties/units. Radiometric units are Human Visual System (HVS) neutral &quot;physical&quot; units defined based on **Watts (W)**, while photometric units are HVS weighted units defined based on **Lumens (lm)**.&#xD;&#xA;&#xD;&#xA;Photometric units are commonly used in rendering because practically all consumer image input and output devices operate in these units as they are designed &amp; optimized for image acquisition &amp; consumption by normal [tristimulus][3] ([LMS][4]) HVS. Proper conversion between photometric &amp; radiometric units isn’t simply a matter of multiplication by some factor (like between kilometers &amp; miles or kilograms &amp; pounds), but different projection from [Spectral Power Distribution (SPD)][5] of visible light spectrum (explained later). Some people use constant [luminous efficacy][6] of 683 **lm/W** to convert between the units, but this has very little touch with reality and results in unrealistic values.&#xD;&#xA;&#xD;&#xA; - [Radiant Flux][7] in **Watts (W)** [[Luminous Flux][8] in **Lumen (lm)**] - Total power emitted by a light (regardless&#xD;&#xA;   of shape or size)&#xD;&#xA; - [Radiant Exitance][9] in **W/m^2** [[Luminous Exitance][10] in **lm/m^2** or **Lux**] - Power emitted by a light per unit area to all directions (think different size light sources with equivalent Radiant Flux)&#xD;&#xA; - [Radiant Intensity][11] in **W/sr** (sr=steradian) [[Luminous Intensity][12] in **lm/sr** or **Candela**] - Power emitted by a light to certain direction (think of a spot vs omni light with equivalent Radiant Flux)&#xD;&#xA; - [Radiance][13] in **W/sr/m^2** [[Luminance][14] in **lm/sr/m^2** or **Nits**] - Power that falls on a patch of surface from some direction (e.g. pixel on screen or patch of surface from certain direction)&#xD;&#xA; - [Irradiance][15] in **W/m^2** [[Illuminance][10] in **lm/m^2** or **Lux**] - Power that falls on a patch of surface regardless of direction (e.g. hemispherical sky illuminating a patch of ground).&#xD;&#xA;&#xD;&#xA;It’s important to understand the difference between these properties when performing lighting calculations, just like it is important not to confuse properties of length and speed when doing physics calculations. There are various other light properties but having good grasp of the above gets you pretty far already.&#xD;&#xA;&#xD;&#xA;Visible light spectrum and RGB projection&#xD;&#xA;-----------------------------------------&#xD;&#xA;&#xD;&#xA;Visible light spectrum contains “infinite” number of electromagnetic wavelengths from ~390nm to ~730nm.&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The power spectrum emitted by light is defined with SPD (in **W/m^2/nm**) and you can calculate the “HVS neutral” physical light intensity, i.e. Radiant Exitance $M_e$ (in **W/m^2**) by integrating the spectrum over the visible light range:&#xD;&#xA;$$M_e=\int_{390}^{730} S(\lambda)d\lambda$$&#xD;&#xA;However, RGB color space is defined in photometric units by projecting SPD using HVS weighted color matching functions. This projection is done because storing SPD would consume immense amount of memory for little gain for image visualization purposes. The projection of SDP to RGB is defined with integrals over the visible light range as follows:&#xD;&#xA;$$R=\int_{390}^{730} S(\lambda)\bar{r}(\lambda)d\lambda$$&#xD;&#xA;$$G=\int_{390}^{730} S(\lambda)\bar{g}(\lambda)d\lambda$$&#xD;&#xA;$$B=\int_{390}^{730} S(\lambda)\bar{b}(\lambda)d\lambda$$&#xD;&#xA;CIE 1931 defines standard observer RGB color matching functions as shown below, based on measurement of 10 human observers&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;As you can see the functions are not discrete wavelengths for RGB, but rather weighted averages of (overlapping) wavelengths.&#xD;&#xA;&#xD;&#xA;It’s not possible to unambiguously calculate Radiant Exitance from RGB values because many different SDF’s may resulting different Radiant Exitance but project to the same RGB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Radiometry&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photometry_(optics)&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/CIE_1931_color_space#Tristimulus_values&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/LMS_color_space&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Spectral_power_distribution&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Luminous_efficacy&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Radiant_flux&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Luminous_flux&#xD;&#xA;  [9]: https://en.wikipedia.org/wiki/Radiant_exitance&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Illuminance&#xD;&#xA;  [11]: https://en.wikipedia.org/wiki/Radiant_intensity&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Luminous_intensity&#xD;&#xA;  [13]: https://en.wikipedia.org/wiki/Radiance&#xD;&#xA;  [14]: https://en.wikipedia.org/wiki/Luminance&#xD;&#xA;  [15]: https://en.wikipedia.org/wiki/Irradiance&#xD;&#xA;  [16]: https://i.stack.imgur.com/makY5.png&#xD;&#xA;  [17]: https://i.stack.imgur.com/yDQwT.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13651" PostHistoryTypeId="5" PostId="5114" RevisionGUID="a7d9d2fd-ad55-42e3-bc93-869518099673" CreationDate="2017-05-16T04:52:10.800" UserId="1952" Comment="added 87 characters in body" Text="The short answer: no, but if you are interested in details, please keep reading (:&#xD;&#xA;&#xD;&#xA;About lighting units&#xD;&#xA;--------------------&#xD;&#xA;&#xD;&#xA;Light “brightness” is indeed quite poor/ambiguous layman’s definition for brightness of a light source. Below is a list of different lighting properties/units commonly used in lighting calculations that define the light “brightness”. I listed both [radiometric][1] and [photometric][2] [in brackets] properties/units. Radiometric units are Human Visual System (HVS) neutral &quot;physical&quot; units defined based on **Watts (W)**, while photometric units are HVS weighted units defined based on **Lumens (lm)**.&#xD;&#xA;&#xD;&#xA;Photometric units are commonly used in rendering because practically all consumer image input and output devices operate in these units as they are designed &amp; optimized for image acquisition &amp; consumption by normal [tristimulus][3] ([LMS][4]) HVS. Proper conversion between photometric &amp; radiometric units isn’t simply a matter of multiplication by some factor (like between kilometers &amp; miles or kilograms &amp; pounds), but different projection from [Spectral Power Distribution (SPD)][5] of visible light spectrum (explained later). Some people use constant [luminous efficacy][6] of 683 **lm/W** to convert between the units, but this has very little touch with reality and results in unrealistic values.&#xD;&#xA;&#xD;&#xA; - [Radiant Flux][7] in **Watts (W)** [[Luminous Flux][8] in **Lumen (lm)**] - Total power emitted by a light (regardless&#xD;&#xA;   of shape or size)&#xD;&#xA; - [Radiant Exitance][9] in **W/m^2** [[Luminous Exitance][10] in **lm/m^2** or **Lux**] - Power emitted by a light per unit area to all directions (think different size light sources with equivalent Radiant Flux)&#xD;&#xA; - [Radiant Intensity][11] in **W/sr** (sr=steradian) [[Luminous Intensity][12] in **lm/sr** or **Candela**] - Power emitted by a light to certain direction (think of a spot vs omni light with equivalent Radiant Flux)&#xD;&#xA; - [Radiance][13] in **W/sr/m^2** [[Luminance][14] in **lm/sr/m^2** or **Nits**] - Power that falls on a patch of surface from some direction (e.g. pixel on screen or patch of surface from certain direction)&#xD;&#xA; - [Irradiance][15] in **W/m^2** [[Illuminance][10] in **lm/m^2** or **Lux**] - Power that falls on a patch of surface regardless of direction (e.g. hemispherical sky illuminating a patch of ground).&#xD;&#xA;&#xD;&#xA;It’s important to understand the difference between these properties when performing lighting calculations, just like it is important not to confuse properties of length and speed when doing physics calculations. There are various other light properties but having good grasp of the above gets you pretty far already.&#xD;&#xA;&#xD;&#xA;Visible light spectrum and RGB projection&#xD;&#xA;-----------------------------------------&#xD;&#xA;&#xD;&#xA;Visible light spectrum contains “infinite” number of electromagnetic wavelengths from ~390nm to ~730nm.&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The power spectrum emitted by light is defined with SPD (in **W/m^2/nm**) and you can calculate the “HVS neutral” physical light intensity, i.e. Radiant Exitance $M_e$ (in **W/m^2**) by integrating the spectrum over the visible light range:&#xD;&#xA;$$M_e=\int_{390}^{730} S(\lambda)d\lambda$$&#xD;&#xA;However, RGB color space is defined in photometric units by projecting SPD using HVS weighted color matching functions. This projection is done because storing SPD would consume immense amount of memory for little gain for image visualization purposes. The projection of SPD to RGB is defined with integrals over the visible light range as follows:&#xD;&#xA;$$R=\int_{390}^{730} S(\lambda)\bar{r}(\lambda)d\lambda$$&#xD;&#xA;$$G=\int_{390}^{730} S(\lambda)\bar{g}(\lambda)d\lambda$$&#xD;&#xA;$$B=\int_{390}^{730} S(\lambda)\bar{b}(\lambda)d\lambda$$&#xD;&#xA;CIE 1931 defines standard observer RGB color matching functions as shown below, based on measurement of 10 human observers&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;As you can see the functions are not discrete wavelengths for RGB, but rather weighted averages of (overlapping) wavelengths.&#xD;&#xA;&#xD;&#xA;It’s not possible to unambiguously calculate Radiant Exitance from RGB values because many different SPD's may resulting different Radiant Exitance but project to the same RGB. This is called [metamerism][18].&#xD;&#xA;&#xA;&#xA;  [1]: https://en.wikipedia.org/wiki/Radiometry&#xA;  [2]: https://en.wikipedia.org/wiki/Photometry_(optics)&#xA;  [3]: https://en.wikipedia.org/wiki/CIE_1931_color_space#Tristimulus_values&#xA;  [4]: https://en.wikipedia.org/wiki/LMS_color_space&#xA;  [5]: https://en.wikipedia.org/wiki/Spectral_power_distribution&#xA;  [6]: https://en.wikipedia.org/wiki/Luminous_efficacy&#xA;  [7]: https://en.wikipedia.org/wiki/Radiant_flux&#xA;  [8]: https://en.wikipedia.org/wiki/Luminous_flux&#xA;  [9]: https://en.wikipedia.org/wiki/Radiant_exitance&#xA;  [10]: https://en.wikipedia.org/wiki/Illuminance&#xA;  [11]: https://en.wikipedia.org/wiki/Radiant_intensity&#xA;  [12]: https://en.wikipedia.org/wiki/Luminous_intensity&#xA;  [13]: https://en.wikipedia.org/wiki/Radiance&#xA;  [14]: https://en.wikipedia.org/wiki/Luminance&#xA;  [15]: https://en.wikipedia.org/wiki/Irradiance&#xA;  [16]: https://i.stack.imgur.com/makY5.png&#xA;  [17]: https://i.stack.imgur.com/yDQwT.png&#xA;  [18]: https://en.m.wikipedia.org/wiki/Metamerism_(color) &quot;metamerism&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13656" PostHistoryTypeId="2" PostId="5116" RevisionGUID="b8f615e9-5b59-45aa-a13e-40ace1cda26d" CreationDate="2017-05-16T14:23:29.357" UserId="6646" Text="I'm learning about 3D computer graphics, but I'm having a hard time understanding why the [near plane of a viewing frustum](https://en.wikipedia.org/wiki/Viewing_frustum) can not be placed at z position $0$ (right at the camera).&#xD;&#xA;&#xD;&#xA;I can understand conceptually that the near plane is essentially the retinal canvas -- so by definition it must exist to some extent -- but I have trouble understanding why the near plane isn't simply an abstract concept where it's actual position is infinitesimally close to the camera position, as opposed to a definite z position away.&#xD;&#xA;&#xD;&#xA;In several explanations, the following formula is given to explain why $0$ cannot be used as the near plan position (where $A$ is the camera position, $B$ is an object vertex, and $D$ is the perspective projection of point $B$ onto the near plane):&#xD;&#xA;&#xD;&#xA;[![similar right triangles][1]][1]&#xD;&#xA;&#xD;&#xA;$${ BC \over AC } = { DE \over AE }$$&#xD;&#xA;&#xD;&#xA;In this case, the geometry of similar triangles $ABC$ and $ADE$ is used to determine the height of $D$ via the solution of $DE$. It is obvious that if the near plane is at $0$ ($AE = 0$), then a division by $0$ occurs -- hence, why the near plane cannot be located at position $0$.&#xD;&#xA;&#xD;&#xA;**However, why is this method used to determine the position of $D$ on the canvas?**&#xD;&#xA;&#xD;&#xA;I've written a simple raycasting visualizer before and didn't have an explicitly defined near plane. In my engine, I simply defined a $60^\circ$ field of view and divided the number pixels on my screen among that field of view. For example, for a $300$x$300$ screen:&#xD;&#xA;&#xD;&#xA;$$1\text{ pixel} = 300/60^\circ = 5^\circ$$&#xD;&#xA;&#xD;&#xA;Next, I found the angle between my camera and the object vertex ($\angle BAC$) and divided it by $5^\circ$ to acquire the pixel coordinate on my screen. In this method, no explicit near plane was necessary and I used my actual camera position to determine the angle.&#xD;&#xA;&#xD;&#xA;So how was I able to perform a perspective projection without a near plane in my raycasting method?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gO1nR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13657" PostHistoryTypeId="1" PostId="5116" RevisionGUID="b8f615e9-5b59-45aa-a13e-40ace1cda26d" CreationDate="2017-05-16T14:23:29.357" UserId="6646" Text="How am I able to perform perspective projection without a near plane?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13658" PostHistoryTypeId="3" PostId="5116" RevisionGUID="b8f615e9-5b59-45aa-a13e-40ace1cda26d" CreationDate="2017-05-16T14:23:29.357" UserId="6646" Text="|raytracing|perspective|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13659" PostHistoryTypeId="5" PostId="5116" RevisionGUID="15269f34-c731-4c3c-87f8-d03390e9ab6e" CreationDate="2017-05-16T15:11:00.890" UserId="6646" Comment="added 4 characters in body" Text="I'm learning about 3D computer graphics, but I'm having a hard time understanding why the [near plane of a viewing frustum](https://en.wikipedia.org/wiki/Viewing_frustum) can not be placed at z position $0$ (right at the camera).&#xD;&#xA;&#xD;&#xA;I can understand conceptually that the near plane is essentially the retinal canvas -- so by definition it must exist to some extent -- but I have trouble understanding why the near plane isn't simply an abstract concept where it's actual position is infinitesimally close to the camera position, as opposed to a definite z position away.&#xD;&#xA;&#xD;&#xA;In several explanations, the following formula is given to explain why $0$ cannot be used as the near plan position (where $A$ is the camera position, $B$ is an object vertex, and $D$ is the perspective projection of point $B$ onto the near plane):&#xD;&#xA;&#xD;&#xA;[![similar right triangles][1]][1]&#xD;&#xA;&#xD;&#xA;$${ BC \over AC } = { DE \over AE }$$&#xD;&#xA;&#xD;&#xA;In this case, the geometry of similar triangles $ABC$ and $ADE$ is used to determine the height of $D$ via the solution of $DE$. It is obvious that if the near plane is at $0$ ($AE = 0$), then a division by $0$ occurs -- hence, why the near plane cannot be located at position $0$.&#xD;&#xA;&#xD;&#xA;**However, why is this method used to determine the position of $D$ on the canvas?**&#xD;&#xA;&#xD;&#xA;I've written a simple raycasting visualizer before and didn't have an explicitly defined near plane. In my engine, I simply defined a $60^\circ$ field of view and divided the number pixels on my screen among that field of view. For example, for a $300$x$300$ screen:&#xD;&#xA;&#xD;&#xA;$$1\text{ pixel} = 300/60^\circ = 5^\circ$$&#xD;&#xA;&#xD;&#xA;Next, I found the angle between my camera and the object vertex ($\angle BAC$) and divided it by $5^\circ$ to acquire the pixel coordinate on my screen. In this method, no explicit near plane was necessary and I used my actual camera position to determine the angle.&#xD;&#xA;&#xD;&#xA;**So how was I able to perform a perspective projection without a near plane in my raycasting method?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gO1nR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13663" PostHistoryTypeId="2" PostId="5118" RevisionGUID="b9bbdf5a-f405-412e-a0c8-b98096746d42" CreationDate="2017-05-16T16:08:20.913" UserId="2654" Text="&gt; In this case, the geometry of similar triangles ABC and ADE is used to determine the height of D via the solution of DE. It is obvious that if the near plane is at 0 (AE=0), then a division by 0 occurs -- hence, why the near plane cannot be located at position 0.&#xD;&#xA;&#xD;&#xA;This is *not* why the nearZ plane cannot be zero. The goal of perspective math is not to project the E onto the near plane. If you look at the actual perspective matrices, you'll find that the nearZ *only* applies to the computed clip-space Z coordinate, not the X and Y.&#xD;&#xA;&#xD;&#xA;Remember: projection is essentially transforming a position such that you lose one or more dimensions. You're projecting from 3D space to 2D space. So projection is removing the Z component, projecting a scene into a 2D region of space. Orthographic projection just discards the Z; perspective projection does something more complex, rescaling the X and Y based on the Z.&#xD;&#xA;&#xD;&#xA;Of course, we're not *really* doing that; Z still exists. Otherwise, the depth buffer wouldn't work. But the basic perspective projection math does not define how the Z is computed.&#xD;&#xA;&#xD;&#xA;Therefore, we can compute the Z however we want. The traditional depth equation (for OpenGL's standard NDC space) is where near/farZ come from:&#xD;&#xA;&#xD;&#xA;$$Z_{ndc} = \frac{\frac{Z_{camera}(F + N)}{N - F} + \frac{2NF}{N - F}}{-Z_{camera}}$$&#xD;&#xA;&#xD;&#xA;`N` and `F` are near/farZ, respectively. If `N` is zero, then the equation degenerates:&#xD;&#xA;&#xD;&#xA;$$Z_{ndc} = \frac{\frac{Z_{camera}(F)}{-F} + 0}{-Z_{camera}}$$&#xD;&#xA;$$Z_{ndc} = \frac{-Z_{camera}}{-Z_{camera}}$$&#xD;&#xA;$$Z_{ndc} = 1$$&#xD;&#xA;&#xD;&#xA;Oops.&#xD;&#xA;&#xD;&#xA;So your question really is why we use depth computations (which again, don't really have anything to do with perspective projection) that require near/farZ values like this.&#xD;&#xA;&#xD;&#xA;This equation, and those like it, has some very nice properties. It plays well with the clip-space W component needed for perspective projection (the division by $-Z_{camera}$). But it also has the effect of being a non-linear Z projection. It puts more precision at the front of the scene than in the distance. And that's generally where you *need* depth precision the most.&#xD;&#xA;&#xD;&#xA;There are alternative ways to compute the clip-space Z. You can use a linear method, which doesn't forbid near Z from being 0. You can also use a method that allows for an infinitely distant far Z (but still relies on near Z); this requires a floating-point Z buffer, though. And so forth.&#xD;&#xA;&#xD;&#xA;You haven't really shown your code, so I can't say if it truly &quot;works&quot;. The clip-space W in particular is important, as it is used for [perspective-correct interpolation of vertex data][1]. If you set it to one, then you won't get proper perspective-correct interpolation. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://alfonse.bitbucket.io/oldtut/Texturing/Tut14%20Interpolation%20Redux.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="13664" PostHistoryTypeId="6" PostId="5116" RevisionGUID="a89ed338-f450-4767-93e6-2ae4c43a4f96" CreationDate="2017-05-16T19:42:45.977" UserId="6646" Comment="edited tags" Text="|raytracing|projections|perspective|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13668" PostHistoryTypeId="2" PostId="5119" RevisionGUID="6139be46-e96d-44c8-abb4-bbe19765abf8" CreationDate="2017-05-17T02:19:48.653" UserId="48" Text="The near and far planes of a viewing frustum aren't needed for simple 3D→2D projection. What the near and far planes actually do, in a typical rasterizer setup, is define the range of values for the depth buffer. &#xD;&#xA;&#xD;&#xA;Depths in the [near, far] range will be mapped into [0, 1] to be stored in the depth buffer. However, the depths aren't simply linearly rescaled. Instead, we use a hyperbolic mapping for depth: the value stored in the depth buffer is the _reciprocal_ of the actual depth distance, with a scale and offset applied.&#xD;&#xA;&#xD;&#xA;[![Graph of standard hyperbolic depth mapping][1]][1]&#xD;&#xA;&#xD;&#xA;If you look at this curve and imagine moving the near plane value toward $z = 0$, the corresponding point on the $1/z$ curve would shoot up toward infinity. The math blows up and the depth buffer becomes useless (it suffers a catastrophic loss of precision).&#xD;&#xA;&#xD;&#xA;The reason why we use the reciprocal instead of some other function of depth is basically convenience: the reciprocal depth interpolates nicely in screen space, and it fits naturally into the mathematical framework of perspective projections: there's already a divide by $z$ being applied to the $x, y$ coordinates.&#xD;&#xA;&#xD;&#xA;If you'd like to know more, I have a short article on the topic: [Depth Precision Visualized](http://reedbeta.com/blog/depth-precision-visualized/).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2Ovvk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13669" PostHistoryTypeId="2" PostId="5120" RevisionGUID="99a88162-0b66-4cc7-91b9-62d8c776358f" CreationDate="2017-05-17T04:12:25.817" UserDisplayName="user4613" Text="When drawing billboards to a cubemap, the billboard texture was incorrectly aligned on the boundaries of the cubemap between different sides. &#xD;&#xA;&#xD;&#xA;My guess is that the false projection of the billboard texture shape using the perspective cameras when drawing the cubemap caused this.&#xD;&#xA;&#xD;&#xA;My question is that without using a geometry with dimensions (such as using a plane geometry for the billboard texture to attach ) to achieve the correct projection, is there any other methods to reduce the artifacts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13670" PostHistoryTypeId="1" PostId="5120" RevisionGUID="99a88162-0b66-4cc7-91b9-62d8c776358f" CreationDate="2017-05-17T04:12:25.817" UserDisplayName="user4613" Text="Possible methods to deal with artifacts when drawing billboards to a cubemap" ContentLicense="CC BY-SA 3.0" />
  <row Id="13671" PostHistoryTypeId="3" PostId="5120" RevisionGUID="99a88162-0b66-4cc7-91b9-62d8c776358f" CreationDate="2017-05-17T04:12:25.817" UserDisplayName="user4613" Text="|texture|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13672" PostHistoryTypeId="2" PostId="5121" RevisionGUID="a22a2b19-dcd2-4c2a-9ef4-0976e7c3c8ab" CreationDate="2017-05-17T08:09:02.443" UserId="137" Text="Change the projection to always be the same no matter which face is being rendered.&#xD;&#xA;&#xD;&#xA;The simplest way is you use the direction from billboard to the camera instead of the direction the camera is facing to rotate the billboard." ContentLicense="CC BY-SA 3.0" />
  <row Id="13673" PostHistoryTypeId="5" PostId="5049" RevisionGUID="36d983a6-a5a4-402a-af34-3b28a9732623" CreationDate="2017-05-17T14:24:36.460" UserId="2941" Comment="Explanation on why I was getting confused." Text="I'm trying to figure out why the probability density function for picking a direction uniformly on the hemisphere is $\frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Something tells me this is related to the number of steradians in a hemisphere being $2\pi$, but I can't see how this is connected. We could come up with another measure for solid angle (&quot;blibs&quot; for example) where the number of blibs in the hemisphere would be $8000\pi$, but I'd expect the probability for picking a direction uniformly to be unchanged.&#xD;&#xA;&#xD;&#xA;EDIT: I understand this now. My confusion arose because I wasn't thinking clearly about the **units** of the probability density function, i.e. $\frac{1}{sr}$. I got thrown off by thinking of area, and confusingly thought the pdf units were inverse area (or something)!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13674" PostHistoryTypeId="2" PostId="5122" RevisionGUID="7668ed64-eefb-4c79-9ba3-46bacdd721ac" CreationDate="2017-05-17T16:35:08.200" UserId="2096" Text="I have been working on a ray tracer and I was trying to use multiple threads to maximize the performance. I tried couple of approaches but there's no difference in performance. Here's my shot...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      void ray_tracer::render()&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;          #define USE_THREADS&#xD;&#xA;    &#xD;&#xA;          #ifdef USE_THREADS&#xD;&#xA;    &#xD;&#xA;    	for (int threadIndex = 0; threadIndex &lt; mMaxThreads; ++threadIndex) {&#xD;&#xA;    		mThreads[threadIndex] = std::thread(&amp;ray_tracer::put_pixel_with_thread, this, threadIndex);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	for (int threadIndex = 0; threadIndex &lt; mMaxThreads; ++threadIndex) {&#xD;&#xA;    		if (mThreads[threadIndex].joinable())&#xD;&#xA;    			mThreads[threadIndex].join();&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;        #else&#xD;&#xA;    	put_pixel(); //uses single thread&#xD;&#xA;    &#xD;&#xA;        #endif&#xD;&#xA;    &#xD;&#xA;    	stbi_write_bmp(&quot;result.bmp&quot;,mImageWidth,mImageHeight,3,mFrameBuffer);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;and here's the put_pixel_with_thread(int)...&#xD;&#xA;&#xD;&#xA;        void ray_tracer::put_pixel_with_thread(int threadIndex)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    	for (int row = 0; row &lt;mImageHeight; ++row)&#xD;&#xA;    	{&#xD;&#xA;    		for (int col = int((threadIndex / mMaxThreads)*mImageWidth);&#xD;&#xA;    			col &lt; int(((threadIndex + 1) / mMaxThreads)*mImageWidth);&#xD;&#xA;    			++col)&#xD;&#xA;    		{&#xD;&#xA;    &#xD;&#xA;    			int index = ((row * mImageWidth) + col) * 3;&#xD;&#xA;    &#xD;&#xA;    			mFrameBuffer[index] = 0;&#xD;&#xA;    			mFrameBuffer[index + 1] = 0;&#xD;&#xA;    			mFrameBuffer[index + 2] = 244;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see in put_pixel_with_threads(int) that I tried to split the row for each thread. I don't know what am i doing wrong. I am working on intel i5 6th gen which has 2 hyper-threaded cores. Please help. &#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13675" PostHistoryTypeId="1" PostId="5122" RevisionGUID="7668ed64-eefb-4c79-9ba3-46bacdd721ac" CreationDate="2017-05-17T16:35:08.200" UserId="2096" Text="How can I utilize all cores of CPU In my ray tracer with std::thread?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13676" PostHistoryTypeId="3" PostId="5122" RevisionGUID="7668ed64-eefb-4c79-9ba3-46bacdd721ac" CreationDate="2017-05-17T16:35:08.200" UserId="2096" Text="|raytracing|c++|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13677" PostHistoryTypeId="2" PostId="5123" RevisionGUID="616be630-8269-456c-823c-9333611fc753" CreationDate="2017-05-17T17:51:15.463" UserId="5717" Text="This is not really a CG issue but you appear to have an integer division problem. Assuming `mMaxThreads` is an integer,  `(threadIndex / mMaxThreads)` is always 0 and `((threadIndex + 1) / mMaxThreads)` is 0 for all threads but the last one, where it is 1. So one thread is doing all the work." ContentLicense="CC BY-SA 3.0" />
  <row Id="13678" PostHistoryTypeId="5" PostId="5120" RevisionGUID="bc875d6a-ef49-4379-a5a1-1080911f1c7a" CreationDate="2017-05-17T17:59:39.167" UserDisplayName="user4613" Comment="added 31 characters in body" Text="When drawing billboards to a cubemap, the billboard texture was incorrectly aligned on the boundaries of the cubemap between different sides. &#xD;&#xA;&#xD;&#xA;My guess is that the false projection of the billboard texture shape using the perspective cameras when drawing the cubemap caused this.&#xD;&#xA;&#xD;&#xA;My question is that without using a geometry with dimensions (such as using a plane geometry for the billboard texture to attach) to achieve the correct projection, is there any other methods to reduce the artifacts? e.g. process on the pointCoord?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13679" PostHistoryTypeId="2" PostId="5124" RevisionGUID="ded041a3-7601-4da2-bba3-f551629a3588" CreationDate="2017-05-18T00:24:27.203" UserId="231" Text="# A very simple low memory approach&#xD;&#xA;&#xD;&#xA;If you really want to use as little memory as possible, it can be done with not much more memory than that required to store a single image (the first frame) provided it is acceptable to do some preprocessing in advance.&#xD;&#xA;&#xD;&#xA;[This jsfiddle] will take the following jumbled image as input:&#xD;&#xA;&#xD;&#xA;[![Blurred image showing a jumble of pixels][blurred]][blurred]&#xD;&#xA;&#xD;&#xA;It will then move the pixels around one step at a time so they drift into place to give the original image again:&#xD;&#xA;&#xD;&#xA;[![Original image of clear text][original]][original]&#xD;&#xA;&#xD;&#xA;This does not require any memory for tracking particles. The algorithm is very simple:&#xD;&#xA;&#xD;&#xA;- Pick a pixel at random&#xD;&#xA;- Swap it with one of its 4 neighbours&#xD;&#xA;- Repeat a million times&#xD;&#xA;&#xD;&#xA;No additional memory is required as no particles are being used. We're simply swapping pixels at random, with no destination locations in mind. The key is in choosing that apparently jumbled initial image to have the pixels in exactly the right places such that applying a million random swaps will happen to leave all the pixels in exactly the right places to give the desired text.&#xD;&#xA;&#xD;&#xA;# Setting up the initial jumbled image&#xD;&#xA;&#xD;&#xA;To do that, [this preparatory jsfiddle] takes an image as input and outputs a jumbled image that is precisely arranged to work as input for the main jsfiddle.&#xD;&#xA;&#xD;&#xA;This one takes more memory, but is still a very simple algorithm:&#xD;&#xA;&#xD;&#xA;- Generate a large number of random numbers and store them&#xD;&#xA;- Using these numbers in reverse order (using the last first):&#xD;&#xA; - Pick a pixel at random&#xD;&#xA; - Swap it with one of its 4 neighbours&#xD;&#xA; - Repeat a million times&#xD;&#xA;&#xD;&#xA;This is exactly the opposite of what the main jsfiddle will do, so the jumbling will be completely reversed, restoring the original image. You can paste in a colour image, or if you want just text with only black and white pixels that will work too. The example image shown above is between these two extremes, as it has greyscale pixels for the antialiasing, which wander around alongside the black and white pixels.&#xD;&#xA;&#xD;&#xA;A million pixel swaps works for fairly small images. For larger sizes this won't jumble them enough to completely obscure the original image, so you would need to adjust the number of swaps.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that this only works because the pseudorandom number generator is reseeded at the start of both algorithms, to ensure that they are both working with exactly the same list of &quot;random&quot; numbers. Most languages will allow you to reseed the random number generator, making this an easy approach. JavaScript does not, so the jsfiddles include an implementation of [xorshift] to allow reseeding.&#xD;&#xA;&#xD;&#xA;Even with a language that does allow reseeding, if the hardware is particularly limited then you may want to consider xorshift as it is very fast and uses only 4 bytes of memory for its state. It's also only a few lines of code.&#xD;&#xA;  &#xD;&#xA;  [This jsfiddle]: https://jsfiddle.net/rxaacpp1/&#xD;&#xA;  [blurred]: https://i.stack.imgur.com/Qx7Ao.png&#xD;&#xA;  [original]: https://i.stack.imgur.com/NnZON.png&#xD;&#xA;  [this preparatory jsfiddle]: https://jsfiddle.net/2f9a3jcm/&#xD;&#xA;  [xorshift]: https://en.wikipedia.org/wiki/Xorshift" ContentLicense="CC BY-SA 3.0" />
  <row Id="13680" PostHistoryTypeId="5" PostId="5124" RevisionGUID="13c87c1d-1f48-4bb5-88c6-8317b81dffc3" CreationDate="2017-05-18T00:32:31.637" UserId="231" Comment="added 16 characters in body" Text="# A very simple low memory approach&#xD;&#xA;&#xD;&#xA;If you really want to use as little memory as possible, it can be done with not much more memory than that required to store a single image (the first frame) provided it is acceptable to do some preprocessing in advance.&#xD;&#xA;&#xD;&#xA;If you copy the following jumbled image, [this jsfiddle] will take it as input:&#xD;&#xA;&#xD;&#xA;[![Blurred image showing a jumble of pixels][blurred]][blurred]&#xD;&#xA;&#xD;&#xA;It will then move the pixels around one step at a time so they drift into place to give the original image again:&#xD;&#xA;&#xD;&#xA;[![Original image of clear text][original]][original]&#xD;&#xA;&#xD;&#xA;This does not require any memory for tracking particles. The algorithm is very simple:&#xD;&#xA;&#xD;&#xA;- Pick a pixel at random&#xD;&#xA;- Swap it with one of its 4 neighbours&#xD;&#xA;- Repeat a million times&#xD;&#xA;&#xD;&#xA;No additional memory is required as no particles are being used. We're simply swapping pixels at random, with no destination locations in mind. The key is in choosing that apparently jumbled initial image to have the pixels in exactly the right places such that applying a million random swaps will happen to leave all the pixels in exactly the right places to give the desired text.&#xD;&#xA;&#xD;&#xA;# Setting up the initial jumbled image&#xD;&#xA;&#xD;&#xA;To do that, [this preparatory jsfiddle] takes an image as input and outputs a jumbled image that is precisely arranged to work as input for the main jsfiddle.&#xD;&#xA;&#xD;&#xA;This one takes more memory, but is still a very simple algorithm:&#xD;&#xA;&#xD;&#xA;- Generate a large number of random numbers and store them&#xD;&#xA;- Using these numbers in reverse order (using the last first):&#xD;&#xA; - Pick a pixel at random&#xD;&#xA; - Swap it with one of its 4 neighbours&#xD;&#xA; - Repeat a million times&#xD;&#xA;&#xD;&#xA;This is exactly the opposite of what the main jsfiddle will do, so the jumbling will be completely reversed, restoring the original image. You can paste in a colour image, or if you want just text with only black and white pixels that will work too. The example image shown above is between these two extremes, as it has greyscale pixels for the antialiasing, which wander around alongside the black and white pixels.&#xD;&#xA;&#xD;&#xA;A million pixel swaps works for fairly small images. For larger sizes this won't jumble them enough to completely obscure the original image, so you would need to adjust the number of swaps.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note that this only works because the pseudorandom number generator is reseeded at the start of both algorithms, to ensure that they are both working with exactly the same list of &quot;random&quot; numbers. Most languages will allow you to reseed the random number generator, making this an easy approach. JavaScript does not, so the jsfiddles include an implementation of [xorshift] to allow reseeding.&#xD;&#xA;&#xD;&#xA;Even with a language that does allow reseeding, if the hardware is particularly limited then you may want to consider xorshift as it is very fast and uses only 4 bytes of memory for its state. It's also only a few lines of code.&#xD;&#xA;  &#xD;&#xA;  [this jsfiddle]: https://jsfiddle.net/rxaacpp1/&#xD;&#xA;  [blurred]: https://i.stack.imgur.com/Qx7Ao.png&#xD;&#xA;  [original]: https://i.stack.imgur.com/NnZON.png&#xD;&#xA;  [this preparatory jsfiddle]: https://jsfiddle.net/2f9a3jcm/&#xD;&#xA;  [xorshift]: https://en.wikipedia.org/wiki/Xorshift" ContentLicense="CC BY-SA 3.0" />
  <row Id="13683" PostHistoryTypeId="2" PostId="5125" RevisionGUID="dbf6ff89-41dc-44dc-8a9f-ec3943689914" CreationDate="2017-05-18T12:48:09.397" UserId="6655" Text="I have a 2D space of dimensions (X,Y) with toroidal properties :&#xD;&#xA;In this space, when a point A(x,y) change it's position such as x is getting &gt; X or &lt; 0, then x becomes (x % X).&#xD;&#xA;So when the point reach the bottom of the space, it get back to the top.&#xD;&#xA;And the same for y coordinate.&#xD;&#xA;&#xD;&#xA;What is the name of such a space ?&#xD;&#xA;&#xD;&#xA;I supposed it was toroidal space, but I can't find any resources with such terms." ContentLicense="CC BY-SA 3.0" />
  <row Id="13684" PostHistoryTypeId="1" PostId="5125" RevisionGUID="dbf6ff89-41dc-44dc-8a9f-ec3943689914" CreationDate="2017-05-18T12:48:09.397" UserId="6655" Text="What is the name of toroidal 2D space" ContentLicense="CC BY-SA 3.0" />
  <row Id="13685" PostHistoryTypeId="3" PostId="5125" RevisionGUID="dbf6ff89-41dc-44dc-8a9f-ec3943689914" CreationDate="2017-05-18T12:48:09.397" UserId="6655" Text="|geometry|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13690" PostHistoryTypeId="5" PostId="407" RevisionGUID="5d8de64a-4cbf-44e4-963d-439adc97128c" CreationDate="2017-05-18T18:45:01.277" UserId="171" Comment="tags, minor typos, particularly &quot;I&quot; is always uppercase" Text="I am currently working on some simple pixel shader in HLSL. I send to shader texture and I want to make it more colorful (something like in the picture below). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the picture 1 there is original texture. Picture 2 shows an effect that I want to achieve. Is there some mathematical formula to do that? My input is the RGBA value of each pixel.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I'll try to write more concrete. &#xD;&#xA;&#xD;&#xA;Let's say I want to make that garden texture more red. I suppose that what I need to do is:&#xD;&#xA;&#xD;&#xA;    OutputR = InputR * X,&#xD;&#xA;    &#xD;&#xA;    OuputG = InputG * Y,&#xD;&#xA;    &#xD;&#xA;    OutputB = InpputB * Z&#xD;&#xA;&#xD;&#xA;But how do I find X, Y and Z?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AvcUu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13691" PostHistoryTypeId="6" PostId="407" RevisionGUID="5d8de64a-4cbf-44e4-963d-439adc97128c" CreationDate="2017-05-18T18:45:01.277" UserId="171" Comment="tags, minor typos, particularly &quot;I&quot; is always uppercase" Text="|texture|algorithm|image-processing|hlsl|pixel-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13692" PostHistoryTypeId="24" PostId="407" RevisionGUID="5d8de64a-4cbf-44e4-963d-439adc97128c" CreationDate="2017-05-18T18:45:01.277" Comment="Proposed by 171 approved by 205 edit id of 250" ContentLicense="CC BY-SA 3.0" />
  <row Id="13693" PostHistoryTypeId="5" PostId="4611" RevisionGUID="ecc6f94c-3ee0-4983-81f1-46766f958a87" CreationDate="2017-05-19T01:24:13.250" UserId="171" Comment="tags, typos, &quot;i&quot; -&gt; &quot;I&quot;, link added" Text="I'm currently trying to implement a Monte Carlo path tracer. I've done some research and it seems that a common approach to materials is to use a layered model. Something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When light hits the surface, Fresnel tells us how much of that light is reflected by the first layer and how much goes to the second, and so forth.&#xD;&#xA;&#xD;&#xA;So I did something similar, but simpler: only one layer of specular and one layer of diffuse. No transmittance yet. So far so good, I use a simple cosine-weighted [brdf][2] for my diffuse and the Cook-Torrance microfaceted model for my specular. &#xD;&#xA;&#xD;&#xA;Now comes the hard part: what should I do once a ray hits the surface?&#xD;&#xA;Normally, I'd pick the brdf corresponding to the surface material, sample an incident light direction, evaluate the brdf, and divide by the right probability distribution function.&#xD;&#xA;&#xD;&#xA;But here, a surface hit effectively corresponds to multiple materials. The naive way to handle this would be to sample once for each layer hit. But this clearly is source of a huge performance hit, causing my path to effectively become a tree.&#xD;&#xA;&#xD;&#xA;Is there a better solution? &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2ABBQ.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="13694" PostHistoryTypeId="6" PostId="4611" RevisionGUID="ecc6f94c-3ee0-4983-81f1-46766f958a87" CreationDate="2017-05-19T01:24:13.250" UserId="171" Comment="tags, typos, &quot;i&quot; -&gt; &quot;I&quot;, link added" Text="|pathtracing|material|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13695" PostHistoryTypeId="24" PostId="4611" RevisionGUID="ecc6f94c-3ee0-4983-81f1-46766f958a87" CreationDate="2017-05-19T01:24:13.250" Comment="Proposed by 171 approved by 48, 2330 edit id of 246" ContentLicense="CC BY-SA 3.0" />
  <row Id="13696" PostHistoryTypeId="2" PostId="5126" RevisionGUID="0fa1c523-8d6d-40c9-bd18-fa61390005a1" CreationDate="2017-05-19T05:03:34.127" UserId="6658" Text="(I initially posted this in a section that is less suited for the particular issue, oops)&#xD;&#xA;&#xD;&#xA;I'm having this issue on some of my client's computers (this is for a Unity asset) that I cannot reproduce on my machine, so finding a fix is incredibly difficult. I'm using camera.rect to render to only part of a screenspace rendertexture to save on render time. For those of you unfamiliar with Unity, as far as I can tell it's analogous to glviewport.&#xD;&#xA;&#xD;&#xA;The issue is, on some older mac computers, realtime lighting is totally shot. The lighting appears to render only within a rectangle that is of the same SIZE as the correct one, but that is docked at 0,0. Additionally, it's not like the lighting data is just slid over, since even though the lighting is only rendering for part of the screen it's not computing it incorrectly in that portion.&#xD;&#xA;&#xD;&#xA;This happens in both forward and deferred rendering, and does not happen with baked lights. It is only reproducible on older mac machines, which I do not have access to. What on earth could cause this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Issue visualization][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oNN0b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13697" PostHistoryTypeId="1" PostId="5126" RevisionGUID="0fa1c523-8d6d-40c9-bd18-fa61390005a1" CreationDate="2017-05-19T05:03:34.127" UserId="6658" Text="What could cause realtime lighting within a viewport to be calculated on the wrong part of the screen?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13698" PostHistoryTypeId="3" PostId="5126" RevisionGUID="0fa1c523-8d6d-40c9-bd18-fa61390005a1" CreationDate="2017-05-19T05:03:34.127" UserId="6658" Text="|rendering|lighting|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13699" PostHistoryTypeId="5" PostId="2147" RevisionGUID="72e68b66-cb67-4f53-a6b3-27c4e24f7571" CreationDate="2017-05-19T07:39:42.760" UserId="171" Comment="readibility, minor typos, outlook" Text="So let assume that I have some convex smooth and unclosed surface.&#xD;&#xA;I'm moving each point of it in a normal direction by some constant factor (This factor is same for all points on surface).&#xD;&#xA;&#xD;&#xA;Can I replace this operation by Uniform or Non-uniform Scaling + Translate? &#xD;&#xA;&#xD;&#xA;Will resulting surfaces be mathematically identical in these cases?&#xD;&#xA;&#xD;&#xA;For example, I want to transform this surface (side view):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JuAlC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13700" PostHistoryTypeId="24" PostId="2147" RevisionGUID="72e68b66-cb67-4f53-a6b3-27c4e24f7571" CreationDate="2017-05-19T07:39:42.760" Comment="Proposed by 171 approved by 48, 3073 edit id of 247" ContentLicense="CC BY-SA 3.0" />
  <row Id="13701" PostHistoryTypeId="5" PostId="297" RevisionGUID="98ba88d2-039e-4606-a36e-40b655480543" CreationDate="2017-05-19T08:22:41.087" UserId="171" Comment="&quot;i&quot; is always uppercase in English, helping with link" Text="When I implement Beer's law (color absorption over distance through an object), it never looks very good for some reason.&#xD;&#xA;&#xD;&#xA;When i have the color behind the object, I calculate the adjusted color like this:&#xD;&#xA;&#xD;&#xA;    const vec3 c_absorb = vec3(0.2,1.8,1.8);&#xD;&#xA;    vec3 absorb = exp(-c_absorb * (distanceInObject));&#xD;&#xA;    behindColor *= absorb;&#xD;&#xA;&#xD;&#xA;That will give me something that looks like this (note a little bit of refraction applied):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here it is without refraction:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note that this is implemented as a shader toy [here][3].&#xD;&#xA;&#xD;&#xA;That fulfills the description of what Beer's law does, but it doesn't look very good, not when compared to shots like this:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Specular highlights aside, I'm trying to figure out the difference.  Could it just be that my geometry is too simple to really show it off very well? Or am I implementing it incorrectly?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XQbjV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gOPZn.png&#xD;&#xA;  [3]: https://www.shadertoy.com/view/4lXSDf&#xD;&#xA;  [4]: https://i.stack.imgur.com/nchoX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13702" PostHistoryTypeId="24" PostId="297" RevisionGUID="98ba88d2-039e-4606-a36e-40b655480543" CreationDate="2017-05-19T08:22:41.087" Comment="Proposed by 171 approved by 48, 209 edit id of 249" ContentLicense="CC BY-SA 3.0" />
  <row Id="13703" PostHistoryTypeId="5" PostId="73" RevisionGUID="f6b1e28e-d067-433b-a32a-5a1ad4eaf004" CreationDate="2017-05-19T08:22:56.183" UserId="171" Comment="minor spelling, readibility" Text="The idea I would try to apply would be the following: I make the example for the curve, but it should be straightforward for the application for the surface.&#xD;&#xA;&#xD;&#xA;Let's say we have a curve $\gamma$ uniformly parametrized. Let's say the parameter of the curve is $s$. Your goal is to sample point corresponding to value of $s$ such that the curvature is high.&#xD;&#xA;&#xD;&#xA;If you get the magnitude of the curvature $c$, this will be function of $s$ too. So, if you normalize the function $|c|$, you will get a probability distribution. If you get the integral of such distribution, you will have the cumulative distribution. Let's call this cumulative function $C(s)$.&#xD;&#xA;&#xD;&#xA;The sampling problem from a distribution given by the cumulative function is well known, so basically once you have sampled a set of value $s_0,s_1,\dots,s_n$, such value will be related to the points of interest.&#xD;&#xA;&#xD;&#xA;The application of this method to the case of surface should be straight, since basically you have a two dimensional cumulative distribution function, but the sampling problem is exactly the same.&#xD;&#xA;&#xD;&#xA;Just to give some detail, it is basically sampling from a distribution given the cumulative function involves two steps:&#xD;&#xA;&#xD;&#xA;1. take a random value in the interval $[0,1]$, let's say $k$ &#xD;&#xA;&#xD;&#xA;2. solve the equation $C(s) = k$.&#xD;&#xA;&#xD;&#xA;This approach is exact, of course it is expensive, but if you like such approach you can work on optimization." ContentLicense="CC BY-SA 3.0" />
  <row Id="13704" PostHistoryTypeId="24" PostId="73" RevisionGUID="f6b1e28e-d067-433b-a32a-5a1ad4eaf004" CreationDate="2017-05-19T08:22:56.183" Comment="Proposed by 171 approved by 48, 209 edit id of 248" ContentLicense="CC BY-SA 3.0" />
  <row Id="13705" PostHistoryTypeId="2" PostId="5127" RevisionGUID="aeeeeb06-a72f-4228-bd1a-a7148631fea5" CreationDate="2017-05-19T08:56:12.097" UserId="1981" Text="As I said in the comments, this is indeed called *torus* or *toroidal space* when it comes to the topology.&#xD;&#xA;&#xD;&#xA;Regarding the distance between two points, I think you mean following: &#xD;&#xA;Just consider the coordinates $p=(x_1,y_1)$ and $q=(x_2,y_2)$ in the $[0,X)\times [0,Y) \simeq (\mathbb R / X\mathbb Z)\times (\mathbb R / Y\mathbb Z)$ square. Then define all the translations $q_i$ of $q$ :&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align*}&#xD;&#xA;q_0 &amp;= (x_2\hphantom{+X\,\,\,},y_2\hphantom{+X\,\,\,})\\&#xD;&#xA;q_1 &amp;= (x_2+X,y_2+Y)\\&#xD;&#xA;q_2 &amp;= (x_2\hphantom{+X\,\,\,},y_2+Y)\\&#xD;&#xA;q_3 &amp;= (x_2-X,y_2+Y)\\&#xD;&#xA;q_4 &amp;= (x_2-X,y_2\hphantom{+X\,\,\,})\\&#xD;&#xA;q_5 &amp;= (x_2-X,y_2-Y)\\&#xD;&#xA;q_6 &amp;= (x_2\hphantom{+X\,\,\,},y_2-Y)\\&#xD;&#xA;q_7 &amp;= (x_2+X,y_2-Y)\\&#xD;&#xA;q_8 &amp;= (x_2+X,y_2\hphantom{+X\,\,\,})&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;Then I think the distance you're looking for is&#xD;&#xA;&#xD;&#xA;$$d(p,q) = \min_{i=0}^8 \Vert p-q_i \Vert$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="13706" PostHistoryTypeId="5" PostId="5127" RevisionGUID="efc29d6e-32c1-4b2b-8930-3f8c5aff14df" CreationDate="2017-05-19T09:01:19.537" UserId="1981" Comment="added 132 characters in body" Text="As I said in the comments, this is indeed called *torus* or *toroidal space* when it comes to the topology. Even if the images suggest something 3 dimensional, this is just a visualization of the embedding of such a space in $\mathbb R^3$.&#xD;&#xA;&#xD;&#xA;Regarding the distance between two points, I think you mean following: &#xD;&#xA;Just consider the coordinates $p=(x_1,y_1)$ and $q=(x_2,y_2)$ in the $[0,X)\times [0,Y) \simeq (\mathbb R / X\mathbb Z)\times (\mathbb R / Y\mathbb Z)$ square. Then define all the translations $q_i$ of $q$ :&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align*}&#xD;&#xA;q_0 &amp;= (x_2\hphantom{+X\,\,\,},y_2\hphantom{+X\,\,\,})\\&#xD;&#xA;q_1 &amp;= (x_2+X,y_2+Y)\\&#xD;&#xA;q_2 &amp;= (x_2\hphantom{+X\,\,\,},y_2+Y)\\&#xD;&#xA;q_3 &amp;= (x_2-X,y_2+Y)\\&#xD;&#xA;q_4 &amp;= (x_2-X,y_2\hphantom{+X\,\,\,})\\&#xD;&#xA;q_5 &amp;= (x_2-X,y_2-Y)\\&#xD;&#xA;q_6 &amp;= (x_2\hphantom{+X\,\,\,},y_2-Y)\\&#xD;&#xA;q_7 &amp;= (x_2+X,y_2-Y)\\&#xD;&#xA;q_8 &amp;= (x_2+X,y_2\hphantom{+X\,\,\,})&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;Then I think the distance you're looking for is&#xD;&#xA;&#xD;&#xA;$$d(p,q) = \min_{i=0}^8 \Vert p-q_i \Vert$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="13710" PostHistoryTypeId="34" PostId="5085" RevisionGUID="ede2cd53-20cc-4d74-90f1-00c18d52f8f4" CreationDate="2017-05-19T13:58:13.463" UserId="6603" Comment="29" />
  <row Id="13711" PostHistoryTypeId="2" PostId="5129" RevisionGUID="4cc192f5-5cdd-41fa-91d2-50755f238df5" CreationDate="2017-05-19T14:16:45.537" UserId="6633" Text="o7&#xD;&#xA;&#xD;&#xA;I am unable to find an answer to my question, because apparently it's not well enough defined to seperate itself from a similar one. So I have to ask here.&#xD;&#xA;&#xD;&#xA;My problem is quite simple. I have multiple shaderpasses and want to render each output into the same texture, which apparently isn't possible even using discard to, ahem, discard empty pixels each shaderpass isn't rendering to anyway. Each pass is supposed to only draw its own part to the texture.&#xD;&#xA;&#xD;&#xA;I can use other methods of rendering only the necessary parts. I picked &quot;discard&quot;, because it was the quickest to implement... and it's probably a bad idea compared to stencil.&#xD;&#xA;&#xD;&#xA;Anyhow: The output-texture only contains one pass, which means it works, but not how i hoped.&#xD;&#xA;&#xD;&#xA;Is it even possible to render multiple shaderpasses to the same texture without having each pass overwrite the output of the predecessing pass?&#xD;&#xA;&#xD;&#xA;And if it is... how?&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13712" PostHistoryTypeId="1" PostId="5129" RevisionGUID="4cc192f5-5cdd-41fa-91d2-50755f238df5" CreationDate="2017-05-19T14:16:45.537" UserId="6633" Text="Multiple shader passes to the same texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13713" PostHistoryTypeId="3" PostId="5129" RevisionGUID="4cc192f5-5cdd-41fa-91d2-50755f238df5" CreationDate="2017-05-19T14:16:45.537" UserId="6633" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13714" PostHistoryTypeId="2" PostId="5130" RevisionGUID="4fc40b74-fc16-4095-907d-d366ea7fb40a" CreationDate="2017-05-19T15:01:14.780" UserId="137" Text="You want to use blending, &#xD;&#xA;&#xD;&#xA;This takes the previous color and the output color of your fragment shader and mixes them together based on the blend parameters and the alpha values.&#xD;&#xA;&#xD;&#xA;This only works for simple math but when doing more complex things you will need to &quot;ping-pong&quot; between 2 textures making sure to draw to every pixel (or copy it over). " ContentLicense="CC BY-SA 3.0" />
  <row Id="13715" PostHistoryTypeId="5" PostId="5129" RevisionGUID="329a3618-990a-4c3e-9b8e-359041c2d5f3" CreationDate="2017-05-19T15:13:08.543" UserId="209" Comment="minor spelling corrections" Text="o7&#xD;&#xA;&#xD;&#xA;I am unable to find an answer to my question, because apparently it's not well enough defined to separate itself from a similar one. So I have to ask here.&#xD;&#xA;&#xD;&#xA;My problem is quite simple. I have multiple shaderpasses and want to render each output into the same texture, which apparently isn't possible even using discard to, ahem, discard empty pixels each shaderpass isn't rendering to anyway. Each pass is supposed to only draw its own part to the texture.&#xD;&#xA;&#xD;&#xA;I can use other methods of rendering only the necessary parts. I picked &quot;discard&quot;, because it was the quickest to implement... and it's probably a bad idea compared to stencil.&#xD;&#xA;&#xD;&#xA;Anyhow: The output-texture only contains one pass, which means it works, but not how I hoped.&#xD;&#xA;&#xD;&#xA;Is it even possible to render multiple shaderpasses to the same texture without having each pass overwrite the output of the preceding pass?&#xD;&#xA;&#xD;&#xA;And if it is... how?&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13716" PostHistoryTypeId="5" PostId="5024" RevisionGUID="7761770d-fbbc-4506-945b-f238aa59b6b7" CreationDate="2017-05-19T17:47:27.467" UserId="6501" Comment="added 741 characters in body" Text="I am working on a project which plots points over a checkerboard (representing seats for people).  I would like each pixel in the image to represent each integer matrix entry.  After updating my Octave from $3.8$ to $4.2$, any image takes up $\frac 14$ of the actual plot window, as seen here:&#xD;&#xA;&#xD;&#xA;The simple code for this is as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clear&#xD;&#xA;    hold off&#xD;&#xA;&#xD;&#xA;    A = [1,2;3,4];&#xD;&#xA;&#xD;&#xA;    image(A)&#xD;&#xA;&#xD;&#xA;    axis xy %orients to bottom left&#xD;&#xA;&#xD;&#xA;I need the purple to take up the entire plot window.&#xD;&#xA;&#xD;&#xA;I can plot overtop the image using the line() function and I get:&#xD;&#xA;&#xD;&#xA;[![OpenGL with Line plotted overtop][1]][1]&#xD;&#xA;&#xD;&#xA;Now, if I enter graphics_toolkit(&quot;gnuplot&quot;) into the octave command window prior to running the code then I get the correct purple image taking up the entire plot window.&#xD;&#xA;&#xD;&#xA;However, if I then use the line() function under gnuplot and plot the same line as before with&#xD;&#xA;&#xD;&#xA;    x=[0.5,2.5];&#xD;&#xA;    y=[1,1];&#xD;&#xA;    line(x,y,'color','red','linewidth',2)&#xD;&#xA;&#xD;&#xA;the following bug appears:&#xD;&#xA;&#xD;&#xA;multiplot&gt; lot &quot;-&quot; binary format='%float64' record=2 using ($1):($2) axes x1y1 title &quot;&quot; with lines linestyle 10 ;&#xD;&#xA;           ^&#xD;&#xA;           line 0: invalid command&#xD;&#xA;&#xD;&#xA;and I get the following image:&#xD;&#xA;&#xD;&#xA;[![Gnuplot with Line() function overtop][2]][2]&#xD;&#xA;&#xD;&#xA;Does anyone know the issue?  Thank you.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iweRz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6LR2U.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13717" PostHistoryTypeId="5" PostId="5024" RevisionGUID="912d3581-cbf5-4d00-b46f-22d2d06fe978" CreationDate="2017-05-19T17:52:48.090" UserId="6501" Comment="added 741 characters in body" Text="I am working on a project which plots points over a checkerboard (representing seats for people).  I would like each pixel in the image to represent each integer matrix entry.  After updating my Octave from $3.8$ to $4.2$, any image takes up $\frac 14$ of the actual plot window using the default OpenGL/ FLTK, as seen below.&#xD;&#xA;&#xD;&#xA;The sample code:&#xD;&#xA;&#xD;&#xA;    clear&#xD;&#xA;    hold off&#xD;&#xA;&#xD;&#xA;    A = [1,2;3,4];&#xD;&#xA;&#xD;&#xA;    image(A)&#xD;&#xA;&#xD;&#xA;    axis xy %orients to bottom left&#xD;&#xA;&#xD;&#xA;I need the purple to take up the entire plot window.&#xD;&#xA;&#xD;&#xA;I can plot overtop the image using the line() function and I get:&#xD;&#xA;&#xD;&#xA;[![OpenGL with Line plotted overtop][1]][1]&#xD;&#xA;&#xD;&#xA;Now, if I enter graphics_toolkit(&quot;gnuplot&quot;) into the octave command window prior to running the code then I get the correct purple image taking up the entire plot window.&#xD;&#xA;&#xD;&#xA;However, if I then use the line() function under gnuplot and plot the same line as before with&#xD;&#xA;&#xD;&#xA;    x=[0.5,2.5];&#xD;&#xA;    y=[1,1];&#xD;&#xA;    line(x,y,'color','red','linewidth',2)&#xD;&#xA;&#xD;&#xA;the following bug appears:&#xD;&#xA;&#xD;&#xA;multiplot&gt; lot &quot;-&quot; binary format='%float64' record=2 using ($1):($2) axes x1y1 title &quot;&quot; with lines linestyle 10 ;&#xD;&#xA;           ^&#xD;&#xA;           line 0: invalid command&#xD;&#xA;&#xD;&#xA;and I get the following image:&#xD;&#xA;&#xD;&#xA;[![Gnuplot with Line() function overtop][2]][2]&#xD;&#xA;&#xD;&#xA;Does anyone know the issue?  Thank you.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iweRz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6LR2U.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13718" PostHistoryTypeId="5" PostId="5024" RevisionGUID="48196fda-5f3f-459d-afcb-367dbd65621e" CreationDate="2017-05-19T18:50:47.850" UserId="6501" Comment="deleted 12 characters in body" Text="I am working on a project which plots points over a checkerboard (representing seats for people).  I would like each pixel in the image to represent each integer matrix entry.  After updating my Octave from $3.8$ to $4.2$, any image takes up $\frac 14$ of the actual plot window using the default OpenGL/ FLTK, as seen below.&#xD;&#xA;&#xD;&#xA;The sample code:&#xD;&#xA;&#xD;&#xA;    clear&#xD;&#xA;&#xD;&#xA;    A = [1,2;3,4];&#xD;&#xA;&#xD;&#xA;    image(A)&#xD;&#xA;&#xD;&#xA;    axis xy %orients to bottom left&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I need the purple to take up the entire plot window.&#xD;&#xA;&#xD;&#xA;I can plot overtop the image using the line() function and I get:&#xD;&#xA;&#xD;&#xA;[![OpenGL with Line plotted overtop][1]][1]&#xD;&#xA;&#xD;&#xA;Now, if I enter graphics_toolkit(&quot;gnuplot&quot;) into the octave command window prior to running the code then I get the correct purple image taking up the entire plot window.&#xD;&#xA;&#xD;&#xA;However, if I then use the line() function under gnuplot and plot the same line as before with&#xD;&#xA;&#xD;&#xA;    x=[0.5,2.5];&#xD;&#xA;    y=[1,1];&#xD;&#xA;    line(x,y,'color','red','linewidth',2)&#xD;&#xA;&#xD;&#xA;the following bug appears:&#xD;&#xA;&#xD;&#xA;multiplot&gt; lot &quot;-&quot; binary format='%float64' record=2 using ($1):($2) axes x1y1 title &quot;&quot; with lines linestyle 10 ;&#xD;&#xA;           ^&#xD;&#xA;           line 0: invalid command&#xD;&#xA;&#xD;&#xA;and I get the following image:&#xD;&#xA;&#xD;&#xA;[![Gnuplot with Line() function overtop][2]][2]&#xD;&#xA;&#xD;&#xA;Does anyone know the issue?  Thank you.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iweRz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6LR2U.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13720" PostHistoryTypeId="2" PostId="5131" RevisionGUID="d70e9571-63cf-4089-9f0c-df891da123bb" CreationDate="2017-05-20T00:15:48.683" UserId="6401" Text="I defined my Model-View Matrix defining a function lookAt that represents the eye of the camera, the position of the object that I'm representing and the &quot;up&quot; vector of the camera. How can I move the object in the line of sight of the camera? Any tips? If I define the vector that points to the position of the object and starts at the eye of the camera (so if I define the line of sight) how can I use this to make the object move along this direction?&#xD;&#xA;&#xD;&#xA;This is my lookAt function&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      function lookAt( eye, at, up )&#xD;&#xA;    {&#xD;&#xA;        if ( !Array.isArray(eye) || eye.length != 3) {&#xD;&#xA;            throw &quot;lookAt(): first parameter [eye] must be an a vec3&quot;;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if ( !Array.isArray(at) || at.length != 3) {&#xD;&#xA;            throw &quot;lookAt(): first parameter [at] must be an a vec3&quot;;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if ( !Array.isArray(up) || up.length != 3) {&#xD;&#xA;            throw &quot;lookAt(): first parameter [up] must be an a vec3&quot;;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if ( equal(eye, at) ) {&#xD;&#xA;            return mat4();&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        var v = normalize( subtract(at, eye) );  // view direction vector&#xD;&#xA;        var n = normalize( cross(v, up) );       // perpendicular vector&#xD;&#xA;        var u = normalize( cross(n, v) );        // &quot;new&quot; up vector&#xD;&#xA;    &#xD;&#xA;        v = negate( v );&#xD;&#xA;    &#xD;&#xA;        var result = mat4(&#xD;&#xA;            vec4( n, -dot(n, eye) ),&#xD;&#xA;            vec4( u, -dot(u, eye) ),&#xD;&#xA;            vec4( v, -dot(v, eye) ),&#xD;&#xA;            vec4()&#xD;&#xA;        );&#xD;&#xA;    &#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13721" PostHistoryTypeId="1" PostId="5131" RevisionGUID="d70e9571-63cf-4089-9f0c-df891da123bb" CreationDate="2017-05-20T00:15:48.683" UserId="6401" Text="WebGL- moving an object in the line of sight" ContentLicense="CC BY-SA 3.0" />
  <row Id="13722" PostHistoryTypeId="3" PostId="5131" RevisionGUID="d70e9571-63cf-4089-9f0c-df891da123bb" CreationDate="2017-05-20T00:15:48.683" UserId="6401" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13725" PostHistoryTypeId="5" PostId="5126" RevisionGUID="857fe9b9-4bfd-47e9-857f-b603c56baf16" CreationDate="2017-05-20T02:09:09.060" UserId="6658" Comment="added new info" Text="(I initially posted this in a section that is less suited for the particular issue, oops)&#xD;&#xA;&#xD;&#xA;I'm having this issue on some of my client's computers (this is for a Unity asset) that I cannot reproduce on my machine, so finding a fix is incredibly difficult. I'm using camera.rect to render to only part of a screenspace rendertexture to save on render time. For those of you unfamiliar with Unity, as far as I can tell it's analogous to glviewport.&#xD;&#xA;&#xD;&#xA;The issue is, on some older mac computers, realtime lighting is totally shot. The lighting appears to render only within a rectangle that is of the same SIZE as the correct one, but that is docked at 0,0. Additionally, it's not like the lighting data is just slid over, since even though the lighting is only rendering for part of the screen it's not computing it incorrectly in that portion.&#xD;&#xA;&#xD;&#xA;This happens in both forward and deferred rendering, and does not happen with baked lights. It is only reproducible on older mac machines, which I do not have access to. What on earth could cause this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Issue visualization][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;Well, that's not good. It looks like this issue is present in Unity version 5.6 as well, even on my windows 10 machine with a GTX 1080. I cannot for the life of me figure out what could cause this, but I'll be inspecting it with renderdoc to see what I can find.&#xD;&#xA;[![5.6 bug][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oNN0b.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vXx2W.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13726" PostHistoryTypeId="50" PostId="4370" RevisionGUID="40b12523-06b8-4bd0-9c00-956710be227f" CreationDate="2017-05-20T05:46:57.450" UserId="-1" />
  <row Id="13727" PostHistoryTypeId="5" PostId="5120" RevisionGUID="0a1cb3da-a8be-43b8-b8fd-33eab394dffc" CreationDate="2017-05-20T06:28:19.797" UserDisplayName="user4613" Comment="added 178 characters in body" Text="When drawing billboards to a cubemap, the billboard texture was incorrectly aligned on the boundaries of the cubemap between different sides. &#xD;&#xA;&#xD;&#xA;My guess is that the false projection of the billboard texture shape using the perspective cameras when drawing the cubemap caused this.&#xD;&#xA;&#xD;&#xA;My question is that without using a geometry with dimensions (such as using a plane geometry for the billboard texture to attach) to achieve the correct projection, is there any other methods to reduce the artifacts? e.g. process on the pointCoord?&#xD;&#xA;&#xD;&#xA;[![cubemap problem][1]][1]&#xD;&#xA;&#xD;&#xA;[a screen record showing the matter](https://www.youtube.com/watch?v=a-cMGQFCOYs&amp;feature=youtu.be)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DnSD1.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13728" PostHistoryTypeId="4" PostId="1895" RevisionGUID="4f13362d-7934-4bf7-bace-1574dc076ae3" CreationDate="2017-05-20T08:43:52.837" UserId="5349" Comment="fixed typo in question title (bezier cures might make a good band name though)" Text="How should I fill a shape consisting of Bezier curves and straight lines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13729" PostHistoryTypeId="24" PostId="1895" RevisionGUID="4f13362d-7934-4bf7-bace-1574dc076ae3" CreationDate="2017-05-20T08:43:52.837" Comment="Proposed by 5349 approved by 38, 2447 edit id of 251" ContentLicense="CC BY-SA 3.0" />
  <row Id="13734" PostHistoryTypeId="5" PostId="5104" RevisionGUID="6d91e31b-5550-4d47-8c9e-1a355ea85681" CreationDate="2017-05-21T10:50:42.607" UserId="6628" Comment="add solution example image (animated gif)" Text="[This YouTube video](https://youtu.be/7oSH-aZKyU8?t=72) of a flip-dot display (physical b/w pixels) shows the reverse of an effect that might be called dissolve or dispersion, i.e. a text emerges from noise by pixels moving in to form letters. Here's a short cropped clip showing just the &quot;crystallization&quot; (wouldn't that be an appropriate name?):&#xD;&#xA;&#xD;&#xA;![animated gif extract from youtu.be/7oSH-aZKyU8 copyright BREAKFAST NY](https://i.stack.imgur.com/9BXg0.gif)(source: [BREAKFAST NY](https://youtu.be/7oSH-aZKyU8))&#xD;&#xA;&#xD;&#xA;Looking for more info on this or similar effects I found [After Effects: Text That Blows Away Like Sand][1] which has a _Shatter_ effect, apparently a 3D [particle system][2] with physics simulation.&#xD;&#xA;&#xD;&#xA;For a particle system, I can imagine that &quot;dissolving&quot; every pixel (of a character) randomly wouldn't be too hard. Reversing the effect as shown in the video could be done using a precalculated sequence or even just animated sprites for each letter. Or, each pixel in the noise gets chosen to gravitate towards a letter (seems more complicated, may require clustering).&#xD;&#xA;&#xD;&#xA;Then I found an implementation and live demo:&#xD;&#xA;&#xD;&#xA;*   _Particles text effects_&#xD;&#xA;&#xD;&#xA;    Uses particles with a seek behavior to make up a word.&#xD;&#xA;    The word is loaded into memory so that each particle can figure out their own position they need to seek.&#xD;&#xA;    Inspired by Daniel Shiffman's arrival explantion from The Nature of Code. (natureofcode.com)&#xD;&#xA;&#xD;&#xA;    https://www.openprocessing.org/sketch/377231&#xD;&#xA;&#xD;&#xA;    The reference resolves to&#xD;&#xA;    - http://natureofcode.com/book/chapter-4-particle-systems&#xD;&#xA;    - http://natureofcode.com/book/chapter-6-autonomous-agents/ (6.4 Arriving Behavior)&#xD;&#xA;&#xD;&#xA;I think the effect is very similar, so I think they used a particle system.&#xD;&#xA;&#xD;&#xA;**Q: Is there an approach that does not require particles (i.e. less memory-expensive)?**&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;&#xD;&#xA;Just for comparison, here's an attempt at creating a &quot;normal&quot; animated noise dissolve ([random dither](https://math.stackexchange.com/questions/2280900/pseudorandom-binary-mask-for-animated-dissolve-effect)), [as suggested in a comment](https://computergraphics.stackexchange.com/questions/5104/pixel-dispersion-dissolving-algorithms#comment7504_5104), but I think it's obvious that the pixels in the original _do_ move and it's not just a binary blending effect:&#xD;&#xA;&#xD;&#xA;![Imgur](https://i.stack.imgur.com/gy8az.gif)&#xD;&#xA;&#xD;&#xA;It requires at least one random value for each pixel: on which frame of the animation to become active.&#xD;&#xA;&#xD;&#xA;&lt;hr/&gt;&#xD;&#xA;This is what [trichoplax's solution][3] looks like (pseudorandomly swapping 10,000 neighboring pixels in each of 100 frames, and then reversing it using the same pseudorandom number sequence, just reversed):&#xD;&#xA;&#xD;&#xA;![Imgur](https://i.stack.imgur.com/iYoQz.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.macprovideo.com/hub/after-effects/after-effects-text-that-blows-away-like-sand&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Particle_system&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/5124/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13735" PostHistoryTypeId="5" PostId="5124" RevisionGUID="31b01ede-20e2-47fb-9223-39a7f4eeaec4" CreationDate="2017-05-21T11:16:04.630" UserId="231" Comment="Add footnote with missing part of explanation" Text="# A very simple low memory approach&#xD;&#xA;&#xD;&#xA;If you really want to use as little memory as possible, it can be done with not much more memory than that required to store a single image (the first frame) provided it is acceptable to do some preprocessing in advance.&#xD;&#xA;&#xD;&#xA;If you copy the following jumbled image, [this jsfiddle] will take it as input:&#xD;&#xA;&#xD;&#xA;[![Blurred image showing a jumble of pixels][blurred]][blurred]&#xD;&#xA;&#xD;&#xA;It will then move the pixels around one step at a time so they drift into place to give the original image again:&#xD;&#xA;&#xD;&#xA;[![Original image of clear text][original]][original]&#xD;&#xA;&#xD;&#xA;This does not require any memory for tracking particles. The algorithm is very simple:&#xD;&#xA;&#xD;&#xA;- Pick a pixel at random&#xD;&#xA;- Swap it with one of its 4 neighbours&#xD;&#xA;- Repeat a million times&#xD;&#xA;&#xD;&#xA;No additional memory is required as no particles are being used. We're simply swapping pixels at random, with no destination locations in mind. The key is in choosing that apparently jumbled initial image to have the pixels in exactly the right places such that applying a million random swaps will happen to leave all the pixels in exactly the right places to give the desired text.&#xD;&#xA;&#xD;&#xA;# Setting up the initial jumbled image&#xD;&#xA;&#xD;&#xA;To do that, [this preparatory jsfiddle] takes an image as input and outputs a jumbled image that is precisely arranged to work as input for the main jsfiddle.&#xD;&#xA;&#xD;&#xA;This one takes more memory, but is still a very simple algorithm:&#xD;&#xA;&#xD;&#xA;- Generate a large number of random numbers and store them&#xD;&#xA;- Using these numbers in reverse order* (using the last first):&#xD;&#xA; - Pick a pixel at random&#xD;&#xA; - Swap it with one of its 4 neighbours&#xD;&#xA; - Repeat a million times&#xD;&#xA;&#xD;&#xA;This is exactly the opposite of what the main jsfiddle will do, so the jumbling will be completely reversed, restoring the original image. You can paste in a colour image, or if you want just text with only black and white pixels that will work too. The example image shown above is between these two extremes, as it has greyscale pixels for the antialiasing, which wander around alongside the black and white pixels.&#xD;&#xA;&#xD;&#xA;A million pixel swaps works for fairly small images. For larger sizes this won't jumble them enough to completely obscure the original image, so you would need to adjust the number of swaps.&#xD;&#xA;&#xD;&#xA;# Languages without reseeding&#xD;&#xA;&#xD;&#xA;Note that this only works because the pseudorandom number generator is reseeded at the start of both algorithms, to ensure that they are both working with exactly the same list of &quot;random&quot; numbers. Most languages will allow you to reseed the random number generator, making this an easy approach. JavaScript does not, so the jsfiddles include an implementation of [xorshift] to allow reseeding.&#xD;&#xA;&#xD;&#xA;Even with a language that does allow reseeding, if the hardware is particularly limited then you may want to consider xorshift as it is very fast and uses only 4 bytes of memory for its state. It's also only a few lines of code.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*Note that the order isn't quite the same as just reversed. In this example code, three random numbers are used for each pair of pixels to be swapped. So the order of each triple must be kept the same to avoid choosing different pairs of pixels. For example:&#xD;&#xA;&#xD;&#xA;[1, 2, 3], [4, 5, 6], [7, 8, 9]&#xD;&#xA;&#xD;&#xA;must be reversed to&#xD;&#xA;&#xD;&#xA;[7, 8, 9], [4, 5, 6], [1, 2, 3]&#xD;&#xA;&#xD;&#xA;in order that the same x value, y value and direction be chosen for each pixel pair when running in reverse.&#xD;&#xA;  &#xD;&#xA;  [this jsfiddle]: https://jsfiddle.net/rxaacpp1/&#xD;&#xA;  [blurred]: https://i.stack.imgur.com/Qx7Ao.png&#xD;&#xA;  [original]: https://i.stack.imgur.com/NnZON.png&#xD;&#xA;  [this preparatory jsfiddle]: https://jsfiddle.net/2f9a3jcm/&#xD;&#xA;  [xorshift]: https://en.wikipedia.org/wiki/Xorshift" ContentLicense="CC BY-SA 3.0" />
  <row Id="13736" PostHistoryTypeId="2" PostId="5132" RevisionGUID="f430933a-05a5-4ed3-a9df-c429c611de59" CreationDate="2017-05-21T13:53:36.040" UserId="2736" Text="So Bidirectional essentially means &quot;two directions&quot;, right? But **what are these two direction** (left-right? up-down? north-south?) we are talking about in regards to bidirectional reflectance distribution function (BRDF), bidirectional scattering distribution function (BSDF), or bidirectional transmittance distribution function (BTDF) in computer graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13737" PostHistoryTypeId="1" PostId="5132" RevisionGUID="f430933a-05a5-4ed3-a9df-c429c611de59" CreationDate="2017-05-21T13:53:36.040" UserId="2736" Text="What does &quot;Bidirectional&quot; in BRDF mean?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13738" PostHistoryTypeId="3" PostId="5132" RevisionGUID="f430933a-05a5-4ed3-a9df-c429c611de59" CreationDate="2017-05-21T13:53:36.040" UserId="2736" Text="|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13739" PostHistoryTypeId="2" PostId="5133" RevisionGUID="fa694a6c-7a23-4735-966c-6ed2deac8ccb" CreationDate="2017-05-21T18:13:48.967" UserId="2654" Text="BRDFs are functions the define the distribution of the way light reflects off of a surface. They effectively answer the question, &quot;given a light source here, how much light is reflected to me?&quot; Well, that question has the two directions right there: the direction from the surface point to the light source, and the direction from the surface point to &quot;me&quot;: the viewer.&#xD;&#xA;&#xD;&#xA;BSDFs and BTDFs work in the same way, just asking slightly different questions. But the givens to those questions are the same: a light source and a viewer. And thus, they use the same directions." ContentLicense="CC BY-SA 3.0" />
  <row Id="13740" PostHistoryTypeId="2" PostId="5134" RevisionGUID="b8aac224-5aca-4973-a068-7248187574bf" CreationDate="2017-05-21T20:36:09.770" UserId="6677" Text="It seems to me that the algorithm is over complicated.&#xD;&#xA;&#xD;&#xA;It makes use of tables, buckets, and sorting, which all seem unnecessary.&#xD;&#xA;&#xD;&#xA;I don't understand why I can't just fill between pairs of scan line intersections, ignoring vertices and edges with gradient 0.&#xD;&#xA;&#xD;&#xA;My lecturer didn't provide the best notes on this algorithm, and all I can find online are even more complicated versions of it.&#xD;&#xA;&#xD;&#xA;An ideal answer would be an explanation of the algorithm, and a reason why simply filling between pairs of intersections won't work.&#xD;&#xA;&#xD;&#xA;Thank you" ContentLicense="CC BY-SA 3.0" />
  <row Id="13741" PostHistoryTypeId="1" PostId="5134" RevisionGUID="b8aac224-5aca-4973-a068-7248187574bf" CreationDate="2017-05-21T20:36:09.770" UserId="6677" Text="Why is the scan line filling algorithm so seemingly over complicated?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13742" PostHistoryTypeId="3" PostId="5134" RevisionGUID="b8aac224-5aca-4973-a068-7248187574bf" CreationDate="2017-05-21T20:36:09.770" UserId="6677" Text="|rasterizer|scanline|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13743" PostHistoryTypeId="5" PostId="5134" RevisionGUID="e0742523-0132-4b46-97ea-118365087bb3" CreationDate="2017-05-22T00:18:17.037" UserId="231" Comment="Remove near duplication of title in first line, and &quot;Thank you&quot;" Text="It makes use of tables, buckets, and sorting, which all seem unnecessary.&#xD;&#xA;&#xD;&#xA;I don't understand why I can't just fill between pairs of scan line intersections, ignoring vertices and edges with gradient 0.&#xD;&#xA;&#xD;&#xA;My lecturer didn't provide the best notes on this algorithm, and all I can find online are even more complicated versions of it.&#xD;&#xA;&#xD;&#xA;An ideal answer would be an explanation of the algorithm, and a reason why simply filling between pairs of intersections won't work." ContentLicense="CC BY-SA 3.0" />
  <row Id="13744" PostHistoryTypeId="2" PostId="5135" RevisionGUID="197ce23d-26fa-4f73-bc7a-4d170054fa7f" CreationDate="2017-05-22T01:01:42.507" UserId="1952" Text="In general the two directions in BxDF are incoming $\omega_i$ and outgoing $\omega_o$ radiance directions, often defined in [spherical coordinates][1] $[\theta, \phi]$ or as a 3D unit vector in [Cartesian coordinates][2] $[x, y, z]$. The BxDF $f(\omega_i, \omega_o)$ defines how much of the incident radiance $L_i$ from direction $\omega_i$ hitting the surface is scattered towards direction $\omega_o$. What $\omega_i$ and $\omega_o$ exactly represent depends on the context.&#xD;&#xA;&#xD;&#xA;Often $\omega_i$ represents the direction of a light source, but it could also be the direction of a surfel reflecting light or some other light emitting/scattering element in space. $\omega_o$ often represent the direction of the viewpoint (camera/eye), but it could as well be the direction of a surfel or other point in space whose incident radiance we are interested in calculating.&#xD;&#xA;&#xD;&#xA;While $\omega_o$ is valid for normal oriented hemisphere above the surface, there are differences in valid $\omega_i$ domain between BxDF's. Because BRDF defines the amount of reflected light $\omega_i$ is valid for the normal oriented hemisphere **above** the surface. On the other hand, BTDF defines the amount of light transmitted through the surface so $\omega_i$ is valid for the normal oriented hemisphere **below** the surface. BSDF is the sum of the two so $\omega_i$ is valid for the entire sphere.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Spherical_coordinate_system&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cartesian_coordinate_system" ContentLicense="CC BY-SA 3.0" />
  <row Id="13745" PostHistoryTypeId="2" PostId="5136" RevisionGUID="4b260885-f78f-4a82-860b-ddb6eca45806" CreationDate="2017-05-22T05:43:33.280" UserId="6674" Text="I want to make a basic video oscillator for the web. What I want to do is basically illustrated in a tutorial for [Lumen][1]: essentially, I want to define an oscillator to turn on and off a color signal at a given frequency. This is simple to do for a frequency below 60hz, but anything higher does not seem to get the effect that the program is showing.&#xD;&#xA;&#xD;&#xA;It seems likely to me that the tutorial is far more simplified than what is going on behind the scenes, and since I don't have background in graphics programming I don't really have the tools to even know what I need to know. I'd like to understand what is going on and if it is possible to produce such things for the web&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://lumen-app.com/guide/oscillators/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13746" PostHistoryTypeId="1" PostId="5136" RevisionGUID="4b260885-f78f-4a82-860b-ddb6eca45806" CreationDate="2017-05-22T05:43:33.280" UserId="6674" Text="Need help reasoning about video oscillation &gt;60hz" ContentLicense="CC BY-SA 3.0" />
  <row Id="13747" PostHistoryTypeId="3" PostId="5136" RevisionGUID="4b260885-f78f-4a82-860b-ddb6eca45806" CreationDate="2017-05-22T05:43:33.280" UserId="6674" Text="|rendering|webgl|javascript|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13748" PostHistoryTypeId="2" PostId="5137" RevisionGUID="44879bfe-7f77-4593-880e-dab9dabc8e8f" CreationDate="2017-05-22T06:50:07.923" UserId="38" Text="Yeah, that makes sense. Most flat panel monitors on the market have a 60Hz refresh rate! So you are not going to be able to flicker faster than 60Hz due to technical limitation.&#xD;&#xA;&#xD;&#xA;Were you to do this with a electron sweeping oscilloscope, or a LED lamp connected to a PWM source fast enough then no problem (you can find this in arduino samples). It would work. &#xD;&#xA;&#xD;&#xA;You can also emulate the effect by rendering multiple frames and then blending them. But you should take caretodo correct kind of blending as the monitor output is not nesseserily linear!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13749" PostHistoryTypeId="5" PostId="5137" RevisionGUID="86b6cc67-953d-4042-8d85-83ec2b421333" CreationDate="2017-05-22T07:10:26.917" UserId="38" Comment="added 1 character in body" Text="Yeah, that makes sense. Most flat panel monitors on the market have a 60Hz refresh rate! So you are not going to be able to flicker faster than 60Hz due to technical limitation.&#xD;&#xA;&#xD;&#xA;Were you to do this with a electron sweeping oscilloscope, or a LED lamp connected to a PWM source fast enough then no problem (you can find this in arduino samples). It would work. &#xD;&#xA;&#xD;&#xA;You can also emulate the effect by rendering multiple frames and then blending them. But you should take careto do correct kind of blending as the monitor output is not nesseserily linear!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13754" PostHistoryTypeId="2" PostId="5139" RevisionGUID="0fd04a70-e315-458b-a3aa-838b3b48d305" CreationDate="2017-05-22T17:19:49.283" UserId="213" Text="I implemented [dual paraboloid][1] shadows for point lights.The goal was to redue amount of shadow passes.Also the target is GLES3.0 so no layered rendering available.The shadows work,and actually the quality is not bad at all.&#xD;&#xA;There is one issue though.I store both hemisphere shadows maps into single atlas during the shadow pass.During the lighting pass I sample from that atlas,from the relevant part based on the direction (forward or backward).When the shadow crosses both maps there is a white seam in the middle.I tried to change filter mode of the FBO texture,also changed wrapping mode,but nothing helps.&#xD;&#xA;Here is the screenshot:[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The point source is the small white sphere at the top and currently it is located so that the shader samples half from each map in the atlas.It results in the white line in the middle of the shadow.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the code in the light pass:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       float Shadow(vec3 viewPos,vec3 lightViewPos,vec3 viewNormal,float bias)&#xD;&#xA;       {&#xD;&#xA;         vec3 vPosDP = vec3(u_lightViewMatrix * v_worldPosition); &#xD;&#xA;         float fLength = length(vPosDP);&#xD;&#xA;         vPosDP /= fLength;&#xD;&#xA;         lightViewPos = (u_viewMatrix * vec4(lightViewPos,1.0)).xyz;&#xD;&#xA;         vec3 L = normalize(lightViewPos - viewPos);&#xD;&#xA;         float NdotL = saturate(dot(L, viewNormal));&#xD;&#xA;         bias =  max(0.01 *(1.0 - NdotL), bias); &#xD;&#xA;         float fDPDepth;&#xD;&#xA;         float fSceneDepth;&#xD;&#xA;&#xD;&#xA;        if(vPosDP.z &gt;=  0.0)&#xD;&#xA;         {       &#xD;&#xA;            vec2 vTexFront;&#xD;&#xA;            vTexFront.x =  ((vPosDP.x /  (1.0 + vPosDP.z))  * 0.25  + 0.25 ); &#xD;&#xA;            vTexFront.y =  ((vPosDP.y /  (1.0 + vPosDP.z))  * 0.5  + 0.5  );     &#xD;&#xA;            fSceneDepth = (fLength - u_nearFarPlanes.x) / (u_nearFarPlanes.y - u_nearFarPlanes.x);&#xD;&#xA;            fDPDepth =   texture(u_shadowMap, vec3(vTexFront,fSceneDepth - bias));            &#xD;&#xA;        }&#xD;&#xA;       else&#xD;&#xA;        {&#xD;&#xA;            // for the back the z has to be inverted        &#xD;&#xA;            vec2 vTexBack;&#xD;&#xA;            vTexBack.x =  ((vPosDP.x /  (1.0 - vPosDP.z)) * 0.25  + 0.75); &#xD;&#xA;            vTexBack.y =  ((vPosDP.y /  (1.0 - vPosDP.z)) * 0.5  + 0.5); &#xD;&#xA;&#xD;&#xA;            fSceneDepth = (fLength - u_nearFarPlanes.x) / (u_nearFarPlanes.y - u_nearFarPlanes.x);&#xD;&#xA;        &#xD;&#xA;            fDPDepth =   texture(u_shadowMap, vec3(vTexBack,fSceneDepth - bias)); &#xD;&#xA; &#xD;&#xA;        }&#xD;&#xA;        return  fDPDepth; &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;I read that this shadow technique has negative effect when low res geometry is involved.Is my issue related to that effect?&#xD;&#xA;&#xD;&#xA;  [1]: http://advancedgraphics.marries.nl/presentationslides/10_dual-paraboloid_shadow_mapping.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/KPiIN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13755" PostHistoryTypeId="1" PostId="5139" RevisionGUID="0fd04a70-e315-458b-a3aa-838b3b48d305" CreationDate="2017-05-22T17:19:49.283" UserId="213" Text="dual paraboloid shadow texture edge seams" ContentLicense="CC BY-SA 3.0" />
  <row Id="13756" PostHistoryTypeId="3" PostId="5139" RevisionGUID="0fd04a70-e315-458b-a3aa-838b3b48d305" CreationDate="2017-05-22T17:19:49.283" UserId="213" Text="|shader|lighting|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13757" PostHistoryTypeId="2" PostId="5140" RevisionGUID="ade1f278-511e-4755-bc2f-5e4ac10dfc88" CreationDate="2017-05-22T17:25:59.793" UserId="6682" Text="I'am currently working on a project where a 3D model gets computed thorugh&#xD;&#xA;a isosurface algorithm. This algorithm outputs single triangles&#xD;&#xA;with vertices and normals, but without indices. So therefore I have&#xD;&#xA;a lot of duplicates which a can't be avoided, because of a software&#xD;&#xA;restriction.&#xD;&#xA;&#xD;&#xA;I was now asked to write smooth lightning for this model,&#xD;&#xA;by sending the proper normals to the visualisation software, which uses OpenGL and run under Windows. What I now tried was to set the normals for duplicated vertices to the same direction but this also results in unsmoothed lighting. &#xD;&#xA;&#xD;&#xA;Is it possible to have smooth gouraud shading on a 3D Model&#xD;&#xA;which consists out of many single unconnected triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13758" PostHistoryTypeId="1" PostId="5140" RevisionGUID="ade1f278-511e-4755-bc2f-5e4ac10dfc88" CreationDate="2017-05-22T17:25:59.793" UserId="6682" Text="Does smooth lightning work with gouraud shading on single triangles" ContentLicense="CC BY-SA 3.0" />
  <row Id="13759" PostHistoryTypeId="3" PostId="5140" RevisionGUID="ade1f278-511e-4755-bc2f-5e4ac10dfc88" CreationDate="2017-05-22T17:25:59.793" UserId="6682" Text="|opengl|lighting|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13766" PostHistoryTypeId="50" PostId="4879" RevisionGUID="5175af15-73fa-4310-9b89-24a764df409e" CreationDate="2017-05-22T18:23:02.717" UserId="-1" />
  <row Id="13770" PostHistoryTypeId="5" PostId="5140" RevisionGUID="fc6ad02f-c529-4ef8-ad28-5b647d116c12" CreationDate="2017-05-23T10:12:54.517" UserId="231" Comment="Typos" Text="I'm currently working on a project where a 3D model gets computed through&#xD;&#xA;an isosurface algorithm. This algorithm outputs single triangles&#xD;&#xA;with vertices and normals, but without indices. So therefore I have&#xD;&#xA;a lot of duplicates which can't be avoided, because of a software&#xD;&#xA;restriction.&#xD;&#xA;&#xD;&#xA;I was asked to write smooth lighting for this model, by sending the proper normals to the visualisation software, which uses OpenGL and runs under Windows. What I tried was to set the normals for duplicated vertices to the same direction but this also results in unsmoothed lighting. &#xD;&#xA;&#xD;&#xA;Is it possible to have smooth Gouraud shading on a 3D Model&#xD;&#xA;which consists of many single unconnected triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13771" PostHistoryTypeId="4" PostId="5140" RevisionGUID="fc6ad02f-c529-4ef8-ad28-5b647d116c12" CreationDate="2017-05-23T10:12:54.517" UserId="231" Comment="Typos" Text="Does smooth lighting work with Gouraud shading on single triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13772" PostHistoryTypeId="5" PostId="5139" RevisionGUID="db133e48-1d90-43a3-a34c-5e067fc69c8c" CreationDate="2017-05-23T10:28:03.857" UserId="231" Comment="Typos and formatting" Text="I implemented [dual paraboloid][1] shadows for point lights. The goal was to reduce the number of shadow passes. Also the target is GLES3.0 so no layered rendering is available. The shadows work, and actually the quality is not bad at all.&#xD;&#xA;&#xD;&#xA;There is one issue though. I store both hemisphere shadow maps into a single atlas during the shadow pass. During the lighting pass I sample from that atlas,from the relevant part based on the direction (forward or backward). When the shadow crosses both maps there is a white seam in the middle. I tried to change the filter mode of the FBO texture, also changed wrapping mode, but nothing helps.&#xD;&#xA;&#xD;&#xA;Here is the screenshot:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The point source is the small white sphere at the top and currently it is located so that the shader samples half from each map in the atlas.It results in the white line in the middle of the shadow.&#xD;&#xA;&#xD;&#xA;Here is the code in the light pass:&#xD;&#xA;&#xD;&#xA;       float Shadow(vec3 viewPos,vec3 lightViewPos,vec3 viewNormal,float bias)&#xD;&#xA;       {&#xD;&#xA;         vec3 vPosDP = vec3(u_lightViewMatrix * v_worldPosition); &#xD;&#xA;         float fLength = length(vPosDP);&#xD;&#xA;         vPosDP /= fLength;&#xD;&#xA;         lightViewPos = (u_viewMatrix * vec4(lightViewPos,1.0)).xyz;&#xD;&#xA;         vec3 L = normalize(lightViewPos - viewPos);&#xD;&#xA;         float NdotL = saturate(dot(L, viewNormal));&#xD;&#xA;         bias =  max(0.01 *(1.0 - NdotL), bias); &#xD;&#xA;         float fDPDepth;&#xD;&#xA;         float fSceneDepth;&#xD;&#xA;&#xD;&#xA;        if(vPosDP.z &gt;=  0.0)&#xD;&#xA;         {       &#xD;&#xA;            vec2 vTexFront;&#xD;&#xA;            vTexFront.x =  ((vPosDP.x /  (1.0 + vPosDP.z))  * 0.25  + 0.25 ); &#xD;&#xA;            vTexFront.y =  ((vPosDP.y /  (1.0 + vPosDP.z))  * 0.5  + 0.5  );     &#xD;&#xA;            fSceneDepth = (fLength - u_nearFarPlanes.x) / (u_nearFarPlanes.y - u_nearFarPlanes.x);&#xD;&#xA;            fDPDepth =   texture(u_shadowMap, vec3(vTexFront,fSceneDepth - bias));            &#xD;&#xA;        }&#xD;&#xA;       else&#xD;&#xA;        {&#xD;&#xA;            // for the back the z has to be inverted        &#xD;&#xA;            vec2 vTexBack;&#xD;&#xA;            vTexBack.x =  ((vPosDP.x /  (1.0 - vPosDP.z)) * 0.25  + 0.75); &#xD;&#xA;            vTexBack.y =  ((vPosDP.y /  (1.0 - vPosDP.z)) * 0.5  + 0.5); &#xD;&#xA;&#xD;&#xA;            fSceneDepth = (fLength - u_nearFarPlanes.x) / (u_nearFarPlanes.y - u_nearFarPlanes.x);&#xD;&#xA;        &#xD;&#xA;            fDPDepth =   texture(u_shadowMap, vec3(vTexBack,fSceneDepth - bias)); &#xD;&#xA; &#xD;&#xA;        }&#xD;&#xA;        return  fDPDepth; &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;I read that this shadow technique has negative effect when low res geometry is involved. Is my issue related to that effect?&#xD;&#xA;&#xD;&#xA;  [1]: http://advancedgraphics.marries.nl/presentationslides/10_dual-paraboloid_shadow_mapping.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/KPiIN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13773" PostHistoryTypeId="4" PostId="5139" RevisionGUID="db133e48-1d90-43a3-a34c-5e067fc69c8c" CreationDate="2017-05-23T10:28:03.857" UserId="231" Comment="Typos and formatting" Text="Dual paraboloid shadow texture edge seams" ContentLicense="CC BY-SA 3.0" />
  <row Id="13774" PostHistoryTypeId="5" PostId="5140" RevisionGUID="20b751ef-3b1c-42df-b57d-a278a997b4c5" CreationDate="2017-05-23T12:15:51.083" UserId="6682" Comment="Added image of the model" Text="I'm currently working on a project where a 3D model gets computed through&#xD;&#xA;an isosurface algorithm. This algorithm outputs single triangles&#xD;&#xA;with vertices and normals, but without indices. So therefore I have&#xD;&#xA;a lot of duplicates which can't be avoided, because of a software&#xD;&#xA;restriction.&#xD;&#xA;&#xD;&#xA;I was asked to write smooth lighting for this model, by sending the proper normals to the visualisation software, which uses OpenGL and runs under Windows. What I tried was to set the normals for duplicated vertices to the same direction but this also results in unsmoothed lighting (as visible here https://i.stack.imgur.com/G8X14.jpg). &#xD;&#xA;&#xD;&#xA;Is it possible to have smooth Gouraud shading on a 3D Model&#xD;&#xA;which consists of many single unconnected triangles?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13775" PostHistoryTypeId="5" PostId="41" RevisionGUID="21cd6421-d877-4e08-aa7d-6df4a6a4e01a" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="In convolution, two mathematical functions are combined to produce a third function. In image processing functions are usually called kernels. A kernel is nothing more than a (square) array of pixels (a small image so to speak). Usually, the values in the kernel add up to one. This is to make sure noe energy is added or removed from the image after the operation.&#xD;&#xA;&#xD;&#xA;Specifically, a Gaussian kernal (used for Gaussian blur) is a square array of pixels where the pixel values correspond to the values of a Gaussian curve (in 2d).&#xD;&#xA;&#xD;&#xA;[![Image linked from http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm][1]][1]&#xD;&#xA;&#xD;&#xA;Each pixel in the image gets multiplied by the Gaussian kernel. This is done by placing the center pixel of the kernel on the image pixel and multiplying the values in the original image with the pixels in the kernel that overlap. The values resulting from these multiplications are added up and that result is used for the value at the destination pixel. Looking at the image, you would multiply the value at (0,0) in the input array by the value a (i) in the kernel array, the value at (1,0) in the input array by the value a (h) in the kernel array, etc. and then add all these values to get the value for (1,1) at the output image.&#xD;&#xA;&#xD;&#xA;[![Image linked from http://www.songho.ca/dsp/convolution/convolution.html][2]][2]&#xD;&#xA;&#xD;&#xA;To answer your second question first, the larger the kernel, the more expensive the operation. So, the larger the radius of the blur, the longer the operation will take.&#xD;&#xA;&#xD;&#xA;To answer your first question, as explained above, convolution can be done by multiplying each input pixel with the entire kernel. However, if the kernel is symmetrical (wich a Gaussian kernel is) you can also multiply each axis (x and y) independently, which will decrease the total number of multiplications. In proper mathematical terms, if a matrix is separable it can be decomposed into (M×1) and (1×N) matrices. For the Gaussian kernel above this means you can also use the following kernels:&#xD;&#xA;&#xD;&#xA;$$\frac1{256}\cdot\begin{bmatrix}&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1\\&#xD;&#xA;4&amp;16&amp;24&amp;16&amp;4\\&#xD;&#xA;6&amp;24&amp;36&amp;24&amp;6\\&#xD;&#xA;4&amp;16&amp;24&amp;16&amp;4\\&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\frac1{256}\cdot\begin{bmatrix}&#xD;&#xA;1\\4\\6\\4\\1&#xD;&#xA;\end{bmatrix}\cdot\begin{bmatrix}&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You would now multiply each pixel in the input image with both kernels and add the resulting values to get the value for the output pixel.&#xD;&#xA;&#xD;&#xA;For more information on how to see if a kernel is separable, follow this [link][4].&#xD;&#xA;&#xD;&#xA;Edit: the two kernels shown above use slightly different values. This is because the (sigma) parameter used for the Gaussian curve to create these kernels were slightly different in both cases. For an explanation on which parameters influence the shape of the Gaussian curve and thus the values in the kernel follow this [link][5]&#xD;&#xA;&#xD;&#xA;Edit: in the second image above it says the kernel that is used is flipped. This of course only makes any difference if the kernel you use is not symmetric. The reason why you need to flip the kernel has to do with the mathematical properties of the convolution operation (see [link][6] for a more in depth explanation on convolution). Simply put: if you would not flip the kernel, the result of the convolution operation will be flipped. By flipping the kernel, you get the correct result.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Qc4Mq.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/bRN2c.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UsU96.gif&#xD;&#xA;  [4]: https://stackoverflow.com/questions/5886529/how-can-i-determine-if-my-convolution-is-separable&#xD;&#xA;  [5]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;  [6]: http://songho.ca/dsp/convolution/convolution.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="13776" PostHistoryTypeId="5" PostId="150" RevisionGUID="28d3273d-ea20-49e1-a934-6a06c5395809" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="There is really no good way of doing this efficiently analytically for all corner cases. Most or all commercial 2D renderers that attempt to do analytic coverage calculation make predictable errors that multisampling methods do not.&#xD;&#xA;&#xD;&#xA;A typical problem is two overlapping shapes that share the same edge. The common situation is that alpha channels sum up to a too thick alpha edge that aliases slightly. Or if shapes are differently colored the system confuses what color the background is. This is extremely annoying.&#xD;&#xA;&#xD;&#xA;![image][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: The rendering engine confuses the coverage and makes a thin white outline where no outline should be.&#xD;&#xA;&#xD;&#xA;Second perfect coverage amounts to box filtering. We can certainly do better. Considering that there are so many special corner cases that would require boolean operations on the shapes to do right, super sampling is still superior. In fact the coverage estimates may be used to concentrate sampling where it's most likely needed.&#xD;&#xA;&#xD;&#xA;The situation could be simplified to polygons at sub pixel levels then the discrete analytical solution could be solved. But this at the expense of flexibility. For example its not out of the question that future vector systems might want to allow for variable width blurred lines which pose a problem for analytic solutions, as do other variably colored objects.&#xD;&#xA;&#xD;&#xA;### How to do it analytically&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Analytic scene][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Suppose you have this scene, exploded view on right&#xD;&#xA;&#xD;&#xA;Now you can not just do this analytically, each piece separately and then merge the data. Because it results in wrong data. See alpha blending would let the blue shine trough the gaps if you did so.&#xD;&#xA;&#xD;&#xA;What you have to so is split the scene up so that each shape eliminates what is under the other:&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: You need to cut the underlying surfaces.&#xD;&#xA;&#xD;&#xA;Now if everything is opaque then this is all straight forward. just calculate the area of each piece and multiply that by color and sum them together. Now you can use something like [this](https://stackoverflow.com/questions/10039679/how-can-i-calculate-the-area-of-a-bezier-curve).&#xD;&#xA;&#xD;&#xA;This all breaks down if your individual shapes aren't opaque off course but even that can be done at some level.&#xD;&#xA;&#xD;&#xA;Remember:&#xD;&#xA;&#xD;&#xA;* AA calculation need to be done in linear color space, and converted back to use space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/Tfs4k.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CihEg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rJu1X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13777" PostHistoryTypeId="5" PostId="189" RevisionGUID="d8dd4ab2-8231-41b0-bd74-4145fb34666f" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="There is no standard format for 3D models. Some common ones are listed in glampert's answer, more can be found [in this SE answer][1].&#xD;&#xA;&#xD;&#xA;If you are designing your own format for your own purposes, (a fairly common thing to do, actually) it's a good first step to look at how you are using your model data. For example, if you are focused on rendering, you can use the format that the graphics library expects. If you want to reduce the load time of your software as much as possible then reducing the amount of parsing and processing you have to do can help. A simple utility that can output a file in the format that your engine expects will mean you can simply map the file into memory and then pass a pointer into your graphics library.&#xD;&#xA;&#xD;&#xA;On the other hand, if rendering is not your main concern and editing is more important to you, you might consider a format more amenable to editing, such as [winged edge][2]. Using a general purpose model format may suit your purposes at the beginning of a project, but ultimately there are many things you can do with 3D models and each format has its own benefits and drawbacks, so you can choose the one that works best for you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/13600158/recommended-file-formats-and-graphics-libraries-for-importing-3d-model-into-open&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Winged_edge" ContentLicense="CC BY-SA 3.0" />
  <row Id="13778" PostHistoryTypeId="5" PostId="237" RevisionGUID="5a683cc9-facc-4ab9-89b0-5813c28e64d2" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="This is the [Camera re-sectioning problem](https://en.wikipedia.org/wiki/Camera_resectioning). &#xD;&#xA;&#xD;&#xA;We need to have a few points, like the end points of the walls, to take the roles of x&lt;sub&gt;w&lt;/sub&gt;, y&lt;sub&gt;w&lt;/sub&gt; and z&lt;sub&gt;w&lt;/sub&gt; in the following equation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here A is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;These are the values of the camera itself.&#xD;&#xA;&#xD;&#xA;R and T are defined as the Rotation and Translation matrices for the camera, and are the values we need to solve for. The position, C, of the camera expressed in world coordinates is C = -R&lt;sup&gt;-1&lt;/sup&gt;T = -R&lt;sup&gt;T&lt;/sup&gt; T .&#xD;&#xA;&#xD;&#xA;The linked Wikipedia article mentions a few algorithms to solve these equations.&#xD;&#xA;&#xD;&#xA;An example of a practical application of these is also found on [Math Stack Exchange](https://math.stackexchange.com/questions/82602/how-to-find-camera-position-and-rotation-from-a-4x4-matrix).&#xD;&#xA;&#xD;&#xA;Another example, with some code samples that you may want to use, is found [Stack Overflow](https://stackoverflow.com/questions/76134/how-do-i-reverse-project-2d-points-into-3d).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qXr4W.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Xs4BR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13779" PostHistoryTypeId="5" PostId="259" RevisionGUID="772a66ed-4e67-48a6-9da9-8f5dddb38a1e" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I have set up some FPS-measuring code in WebGL (based on [this SO answer](https://stackoverflow.com/a/16447895/1633117)) and have discovered some oddities with the performance of my fragment shader. The code just renders a single quad (or rather two triangles) over a 1024x1024 canvas, so all the magic happens in the fragment shader.&#xD;&#xA;&#xD;&#xA;Consider this simple shader (GLSL; the vertex shader is just a pass-through):&#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-cplusplus --&gt;&#xD;&#xA;&#xD;&#xA;    // some definitions&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;        // Nothing to see here...&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this just renders a white canvas. It averages around 30 fps on my machine.&#xD;&#xA;&#xD;&#xA;Now let's ramp up the number crunching and compute each fragment based on a few octaves of position-dependent noise:&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        float seed = uSeed;&#xD;&#xA;        float x = vPos.x;&#xD;&#xA;        float y = vPos.y;&#xD;&#xA;&#xD;&#xA;        float value = 1.0;&#xD;&#xA;&#xD;&#xA;          float noise;&#xD;&#xA;          for ( int j=0; j&lt;10; ++j)&#xD;&#xA;          {&#xD;&#xA;            noise = 0.0;&#xD;&#xA;            for ( int i=4; i&gt;0; i-- )&#xD;&#xA;            {&#xD;&#xA;                float oct = pow(2.0,float(i));&#xD;&#xA;                noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        &#xD;&#xA;          value = noise/2.0+0.5;&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(value, value, value, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;If you want to run the above code, I've been using [this implementation of `snoise`](https://github.com/ashima/webgl-noise).&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;This brings down the fps to something like 7. That makes sense.&#xD;&#xA;&#xD;&#xA;Now the weird part... let's compute only one of every 16 fragments as noise and leave the others white, by wrapping the noise computation in the following conditional:&#xD;&#xA;&#xD;&#xA;    if (int(mod(x*512.0,4.0)) == 0 &amp;&amp; int(mod(y*512.0,4.0)) == 0)) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You'd expect this to be much faster, but it's still only 7 fps.&#xD;&#xA;&#xD;&#xA;For one more test, let's instead filter the pixels with the following conditional:&#xD;&#xA;&#xD;&#xA;    if (x &gt; 0.5 &amp;&amp; y &gt; 0.5) {&#xD;&#xA;        // same noise computation&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This gives the exact same number of noise pixels as before, but now we're back up to almost 30 fps.&#xD;&#xA;&#xD;&#xA;**What is going on here?** Shouldn't the two ways to filter out a 16th of the pixels give the exact same number of cycles? And why is the slower one as slow as rendering *all* pixels as noise?&#xD;&#xA;&#xD;&#xA;Bonus question: **What can I do about this?** Is there any way to work around the horrible performance if I actually *do* want to speckle my canvas with only a few expensive fragments?&#xD;&#xA;&#xD;&#xA;(Just to be sure, I have confirmed that the actual modulo computation does not affect the frame rate at all, by rendering every 16th pixel black instead of white.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13780" PostHistoryTypeId="5" PostId="374" RevisionGUID="087040a0-4917-467b-a71e-a78c5932b2f6" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I tried [this question on math.SE](https://math.stackexchange.com/questions/348806/intersect-a-line-with-a-bicubic-bezier-surface-patch) and surprisingly, the answer was &quot;the equations are too nasty, just feed the function it to a numerical root-finder&quot;. But if you consider yourself &quot;a graphics guy&quot; like me, and have played extensively with Bezier curves for design work, I got to believe that better can be done. There is a published algorithm by Kajiya that I don't have the background to understand (Sylvester Matrices), but the related advice on math.SE was that the result is a degree-18 polynomial in t, and you still need to solve that numerically. [I had another idea with similar result](https://math.stackexchange.com/questions/1083240/can-a-bicubic-bezier-surface-be-represented-as-a-bernstein-polynomial).&#xD;&#xA;&#xD;&#xA;So, is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically, thus making it possible to code explicitly and have super-fast super-smoothness?&#xD;&#xA;&#xD;&#xA;Barring that, what's the fastest method for performing this calculation? Can you &quot;find the wiggles&quot; to get a tight bound (and target) for recursive subdivision? If you have to use a numerical root-finder (sigh), what properties does it need and is there a best choice for speed?&#xD;&#xA;&#xD;&#xA;My original thought was about preparing for a specific surface, similar to Laplace expansion as described in the answer to my [other math question about triangles](https://math.stackexchange.com/questions/297588/for-bsp-generation-how-to-intersect-or-locate-a-triangle-with-a-plane-defined-b). But I'd be interested in general methods, too. I'm just thinking of a fixed set of shapes, like [the Utah teapot](https://stackoverflow.com/questions/14807341/how-to-do-a-space-partitioning-of-the-utah-teapot). But I'd be very interested in ways of optimizing for temporal coherence across animated frames." ContentLicense="CC BY-SA 3.0" />
  <row Id="13781" PostHistoryTypeId="5" PostId="392" RevisionGUID="7cd10062-037b-4de1-aedc-2b37b3632afe" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="An Affine Transform is a Linear Transform + a Translation Vector.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b \\ c&amp;d\end{bmatrix}&#xD;&#xA;+&#xD;&#xA;\begin{bmatrix}e&amp; f\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It can be applied to individual points or to lines or even Bezier curves. For lines, it preserves the property that parallel lines remain parallel. For Bezier curves, it preserves the convex-hull property of the control points.&#xD;&#xA;&#xD;&#xA;Multiplied-out, it produces 2 equations for yielding a &quot;transformed&quot; coordinate pair $(x', y')$ from the original pair $(x, y)$ and a list of constants $(a, b, c, d, e, f)$.&#xD;&#xA;$$&#xD;&#xA;    x' =  a\cdot x + c\cdot y + e \\&#xD;&#xA;    y' =  b\cdot x + d\cdot y + f&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Conveniently, the Linear transform and the Translation vector can be put together into a 3D matrix which can operate over 2D homogeneous coordinates.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}x'&amp; y'&amp;1\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which yields the same 2 equations above.&#xD;&#xA;&#xD;&#xA;*Very conveniently*, the matrices themselves can be multiplied together to produce a third matrix (of constants) which performs the same transformation as the original 2 would perform in sequence. Put simply, the matrix multiplications are associative.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}x''&amp; y''&amp;1\end{bmatrix}&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}\right)&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp; = &amp;&#xD;&#xA;\begin{bmatrix}a \cdot x + c \cdot y+e &amp; b \cdot x + d \cdot y+f &amp;1 \end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}g(a \cdot x + c \cdot y+e) + i( b \cdot x + d \cdot y+f) + k &#xD;&#xA;\\&#xD;&#xA;h(a \cdot x + c \cdot y+e) + j( b \cdot x + d \cdot y+f) + m&#xD;&#xA;\\1 \end{bmatrix}^T&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\left(&#xD;&#xA;\begin{bmatrix}a&amp; b &amp;0\\ c&amp;d&amp;0 \\ e&amp;f&amp;1\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}g&amp; h &amp;0\\ i&amp;j&amp;0 \\ k&amp;m&amp;1\end{bmatrix}&#xD;&#xA;\right)&#xD;&#xA;\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\begin{bmatrix}x&amp; y&amp;1\end{bmatrix} \cdot&#xD;&#xA;\begin{bmatrix}ag+bi&amp; ah+bj &amp;0\\ cg+di&amp;ch+dj&amp;0 \\ eg+fi+k&amp;eh+fj+m&amp;1\end{bmatrix}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively you can consider a few basic transform types and compose any more complex transform by combining these (multiplying them together).&#xD;&#xA;&#xD;&#xA;Identity transform&#xD;&#xA;&#xD;&#xA;[![identity transform][1]][1]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;&#xD;&#xA;[![scaling][2]][2]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    S_x &amp; 0 &amp; 0 \\&#xD;&#xA;    0  &amp; S_y &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;*Note: a reflection can be performed with scaling parameters $(S_x, S_y) = (-1,1)$ or $(1,-1)$.&#xD;&#xA;&#xD;&#xA;Translation&#xD;&#xA;&#xD;&#xA;[![translation][3]][3]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    T_x &amp; T_y &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew x by y&#xD;&#xA;&#xD;&#xA;[![skew x by y][4]][4]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; Q_x &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Skew y by x&#xD;&#xA;&#xD;&#xA;[![skew y by x][5]][5]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    1  &amp; 0 &amp; 0 \\&#xD;&#xA;    Q_y &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Rotation&#xD;&#xA;&#xD;&#xA;[![rotation][6]][6]&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;    \cos\theta &amp; -sin\theta &amp; 0\\&#xD;&#xA;    \sin\theta &amp; \cos\theta &amp; 0\\&#xD;&#xA;    0  &amp;  0 &amp;  1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[Note I've shown the form of Matrix here which accepts a row vector on the *left*. The transpose of these matrices will work with a column vector on the right.]&#xD;&#xA;&#xD;&#xA;A matrix composed purely from scaling, rotation, and translation can be [decomposed back into these three components](https://stackoverflow.com/a/11942636/733077).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/icgx0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVdBw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kH8uS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gyZCZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7zEWw.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ltr0w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13782" PostHistoryTypeId="5" PostId="418" RevisionGUID="052dc86a-0db0-4d06-b280-914439a8f475" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](https://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](https://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](https://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](https://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](https://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Graphics[{&#xD;&#xA;          orig = {&#xD;&#xA;            Table[GeometricTransformation[&#xD;&#xA;              Line[{{0, 0}, {50, 0}}],&#xD;&#xA;              RotationTransform[ang]],&#xD;&#xA;             {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;             ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;            }, Red,&#xD;&#xA;          GeometricTransformation[&#xD;&#xA;           orig,&#xD;&#xA;           RotationTransform[Pi/6]&#xD;&#xA;           ]&#xD;&#xA;          }&#xD;&#xA;         ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside a table [as per](https://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="13783" PostHistoryTypeId="5" PostId="1533" RevisionGUID="ea12fdd5-6967-4104-a05d-9adb56846ee4" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="Quickly Googling produces:&#xD;&#xA;&#xD;&#xA;1. [This related question](https://stackoverflow.com/questions/4148831/how-to-offset-a-cubic-bezier-curve) on StackOverflow&#xD;&#xA;2. &quot;Computing offsets of NURBS curves and surfaces&quot; (paper)&#xD;&#xA;3. Discussions of 2.&#xD;&#xA;&#xD;&#xA;To summarize them:&#xD;&#xA;&#xD;&#xA;1. Suggests that this is impossible to do exactly.&#xD;&#xA;2. Gives an algorithm to compute an offset curve approximately (though to within a tiny epsilon).  If you can't access the paper, then:&#xD;&#xA;3. Look at any of these.  [This presentation](https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=7&amp;cad=rja&amp;uact=8&amp;ved=0CDwQFjAGahUKEwiihLzeg47IAhVHN4gKHfsmCaM&amp;url=http%3A%2F%2Fwww.math.zju.edu.cn%2Fcagd%2FSeminar%2F2005_AutumnWinter%2F2005_Master_LH.ppt&amp;usg=AFQjCNGlb556TMftSL8d4xU7kT1x7Q9G7Q&amp;sig2=9rYaCjpqD-VMKu94ke5O7w) for example seems to cover it." ContentLicense="CC BY-SA 3.0" />
  <row Id="13784" PostHistoryTypeId="5" PostId="1641" RevisionGUID="cbc430e3-582b-405f-902c-b98923adb08f" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I would like to implement a Maya plugin (this question is independent from Maya) to create 3D Voronoi patterns, Something like &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I just know that I have to start from point sampling (I implemented the adaptive poisson sampling algorithm described in [this paper][2]). &#xD;&#xA;&#xD;&#xA;I thought that, from those points, I should create the 3D wire of the mesh applying Voronoi (I tried to use (Python) scipy.spatial.Voronoi but the result was something different from what I expected).&#xD;&#xA;&#xD;&#xA;I am missing something? Can anyone suggest the proper pipeline and algorithms I have to implement to create such patterns?&#xD;&#xA;&#xD;&#xA;[EDIT] Here are a few example of what I get handling the result i get from scipy.spatial.Voronoi like this (as suggested [here][3]):&#xD;&#xA;&#xD;&#xA;    vor = Voronoi(points)&#xD;&#xA;    for vpair in vor.ridge_vertices:&#xD;&#xA;        for i in range(len(vpair) - 1):&#xD;&#xA;            if all(x &gt;= 0 for x in vpair):&#xD;&#xA;                v0 = vor.vertices[vpair[i]]&#xD;&#xA;                v1 = vor.vertices[vpair[i+1]]&#xD;&#xA;                create_line(v0.tolist(), v1.tolist())&#xD;&#xA;&#xD;&#xA;The grey vertices are the sampled points (the original shape was a simple sphere):&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Here is a more complex shape (an arm)&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8RYgU.jpg&#xD;&#xA;  [2]: http://link.springer.com/article/10.1007%2Fs11432-011-4322-8#/page-1&#xD;&#xA;  [3]: https://stackoverflow.com/questions/23658776/voronoi-diagram-edges-how-to-get-edges-in-the-form-point1-point2-from-a-scip&#xD;&#xA;  [4]: https://i.stack.imgur.com/gz8hD.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/mCkPm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13786" PostHistoryTypeId="5" PostId="1859" RevisionGUID="c3134b7d-f46c-4669-a67c-137170c81415" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="This algorithm is based on [this answer for finding the angle between vectors][1], and [this answer for rotating polygon points][2]. It's written in Python, and assumes you want to align an edge with the X axis (horizontal axis). If you want to align it with the Y axis, replace the `xVec` in the code below with a `yVec = [0,1]`.&#xD;&#xA;&#xD;&#xA;**EDITED**: Added code for rotating the polygon and displaying the original and rotated polygons. Result of this script is displayed in the image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw&#xD;&#xA;    from matplotlib import pyplot as plt&#xD;&#xA;    from math import radians, degrees, sqrt, acos, cos, sin&#xD;&#xA;&#xD;&#xA;    def dotproduct(v1, v2):&#xD;&#xA;      return sum( (a*b) for a, b in zip(v1, v2) )&#xD;&#xA;&#xD;&#xA;    def length(v):&#xD;&#xA;      return sqrt( dotproduct(v, v) )&#xD;&#xA;&#xD;&#xA;    def angle(v1, v2):&#xD;&#xA;      return acos( dotproduct(v1, v2) / ( length(v1) * length(v2) ) )&#xD;&#xA;&#xD;&#xA;    def vec_subtraction( v1, v2 ):&#xD;&#xA;        return [ e1 - e2 for e1, e2 in zip( v1, v2 ) ]&#xD;&#xA;&#xD;&#xA;    def calc_edge_vec( poly, edge ):&#xD;&#xA;        p1 = poly['points'][ edge[0] ]&#xD;&#xA;        p2 = poly['points'][ edge[1] ]&#xD;&#xA;&#xD;&#xA;        return vec_subtraction( p2, p1 )&#xD;&#xA;&#xD;&#xA;    def rotatePolygon( poly, theta ):&#xD;&#xA;        ''' Rotates the given polygon which consists of corners represented&#xD;&#xA;            as (x,y), around the ORIGIN, clock-wise, theta degrees&#xD;&#xA;        '''&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = []&#xD;&#xA;        for corner in poly:&#xD;&#xA;            rotatedPolygon.append((&#xD;&#xA;                corner[0] * cos( theta ) - corner[1] * sin( theta ), # x&#xD;&#xA;                corner[0] * sin( theta ) + corner[1] * cos( theta )  # y&#xD;&#xA;            ))&#xD;&#xA;&#xD;&#xA;        # Make sure rotated polygon coordinates are within image boundaries&#xD;&#xA;        minX = min( [ c[0] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minX = minX if minX &gt; 0 else 0&#xD;&#xA;        minY = min( [ c[1] for c in rotatedPolygon ] ) * -1&#xD;&#xA;        minY = minY if minY &gt; 0 else 0&#xD;&#xA;&#xD;&#xA;        rotatedPolygon = [ ( x + minX, y + minY ) for x, y in rotatedPolygon ]&#xD;&#xA;&#xD;&#xA;        return rotatedPolygon&#xD;&#xA;&#xD;&#xA;    def draw_and_plot_polygon( im, poly, color, plotTitle, plotIndex ):&#xD;&#xA;        draw = ImageDraw.Draw( im )&#xD;&#xA;&#xD;&#xA;        for e in poly['edges']:&#xD;&#xA;            p1 = tuple( poly['points'][ e[0] ] )&#xD;&#xA;            p2 = tuple( poly['points'][ e[1] ] )&#xD;&#xA;            draw.line( [p1, p2], fill = color )&#xD;&#xA;&#xD;&#xA;        del draw&#xD;&#xA;&#xD;&#xA;        plt.subplot( 3, 2, plotIndex ),&#xD;&#xA;        plt.imshow( im ),&#xD;&#xA;        plt.title( plotTitle ),&#xD;&#xA;        plt.xticks([]), plt.yticks([])&#xD;&#xA;&#xD;&#xA;        # Draw point names (ABCD)&#xD;&#xA;        for i, c in enumerate( poly['points'] ):&#xD;&#xA;            plt.text( c[0], c[1], &quot;ABCD&quot;[i], color = 'white' )&#xD;&#xA;&#xD;&#xA;    # Define polygon as dictionary of point coordinates and edges&#xD;&#xA;    # each edge is a pair of point indices&#xD;&#xA;    p = {&#xD;&#xA;        'points' : [ (50,10), (95,30), (80,20), (62,48) ],&#xD;&#xA;        'edges'  : [ (3,0), (3,1), (1,2), (2,0) ]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    xVec = [1,0] # Horizontal axis&#xD;&#xA;&#xD;&#xA;    # Draw original poly in white&#xD;&#xA;    im = Image.new( 'RGB', (100,100) )&#xD;&#xA;    draw_and_plot_polygon( im, p, (255,255,255), 'Original', 1 )&#xD;&#xA;&#xD;&#xA;    colors = [ (50,50,255), (255,0,0), (0,255,0), (200, 150, 50) ]&#xD;&#xA;&#xD;&#xA;    i = 2&#xD;&#xA;    for e, color in zip( p['edges'], colors ):&#xD;&#xA;        edgeVec = calc_edge_vec( p, e )&#xD;&#xA;        a       = angle( edgeVec, xVec )&#xD;&#xA;&#xD;&#xA;        rotPol = p.copy()&#xD;&#xA;        rotPol['points'] = rotatePolygon( p['points'], a )&#xD;&#xA;&#xD;&#xA;        im = Image.new( 'RGB', (100,100) )&#xD;&#xA;&#xD;&#xA;        # Place aligned edge at bottom&#xD;&#xA;        alingedEdgeY = im.size[1] - rotPol['points'][ e[0] ][ 1 ] # Current edge height&#xD;&#xA;        rotPol['points'] = [ ( p[0], p[1] + alingedEdgeY ) for p in rotPol['points'] ]&#xD;&#xA;&#xD;&#xA;        # Draw rotated polygon&#xD;&#xA;        angleTitle = &quot;Angle: &quot; + str( round( degrees(a), 2 ) )&#xD;&#xA;        draw_and_plot_polygon( im, rotPol, color, angleTitle, i )&#xD;&#xA;&#xD;&#xA;        i += 1&#xD;&#xA;&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-python --&gt;    &#xD;&#xA;    &#xD;&#xA;**EDITED 2**: Added some code to position the rotated polygon so that the aligned edge is on the floor (lines 90-91). Here's the result:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/2827393/angles-between-two-n-dimensional-vectors-in-python&#xD;&#xA;  [2]: https://stackoverflow.com/questions/20023209/python-function-for-rotating-2d-objects&#xD;&#xA;  [3]: https://i.stack.imgur.com/oeSfK.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/SRPg3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13787" PostHistoryTypeId="5" PostId="1997" RevisionGUID="a2010058-928c-4ad2-a57e-096ca655e1f0" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I am implementing foveated rendering. My [FBO] is divided into 2 layers which are concentric. The first layer covers 1/3 of the Framebuffer whereas the second one covers the rest of the screen. Now I want to avoid rendering meshes in the outer layer which are already in the inner layer.&#xD;&#xA;&#xD;&#xA;I have implemented the following culling algorithm which is only concerned with culling between the layers:&#xD;&#xA;&#xD;&#xA;1. I create rectangles with min and max corners from the radii of the 2 layers. Now these coordinates are in [NDC]. &#xD;&#xA;2. I have the min and max corner of each mesh in the local coordinate system. So I transform them into NDC using:&#xD;&#xA;&#xD;&#xA;        vec4 min = mvp * vec4(min_corner, 1.0);&#xD;&#xA;        min = min.xyzw / min.w;&#xD;&#xA;&#xD;&#xA;3. I create a bounding box using min and max corners.&#xD;&#xA;4. I check whether 2 rectangles overlap or not.&#xD;&#xA;&#xD;&#xA;Now, when I transform into clip space, the x or y coordinates of the min are sometimes greater than the max corner. The same issue occurs when I divide them by w. What's going wrong here?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Okay. I found the problem. Now I iterate over all the vertices, transform each of them into NDC using [MVP] and then calculate the min and max corners which works perfect. But this is much more overhead for each frame. Is there any optimization I can do here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [FBO]: https://en.wikipedia.org/wiki/Framebuffer_Object &quot;Framebuffer Object&quot;&#xD;&#xA;&#xD;&#xA;  [NDC]: https://www.ncl.ucar.edu/Document/Graphics/ndc.shtml &quot;Normalized Device Coordinates&quot;&#xD;&#xA;&#xD;&#xA;  [MVP]: https://stackoverflow.com/questions/5550620/the-purpose-of-model-view-projection-matrix &quot;Model View Projection matrix&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13788" PostHistoryTypeId="5" PostId="2049" RevisionGUID="757ce3a3-f184-4f9b-8d4c-169116ecc8e1" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I'm looking into the graphics pipeline processes and at the moment in particular, perspective projection matrices.&#xD;&#xA;&#xD;&#xA;After looking in several different sources, and across the breadth of previous questions such as https://stackoverflow.com/questions/25659623/how-does-a-projection-matrix-work, I've found that most solutions seem to use the following two matrices;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;So far, I've been expecting these matrices to take the view frustum and convert it into a unit sized cube - however this doesn't seem to be happening.&#xD;&#xA;&#xD;&#xA;Taking the left matrix first (which I attempted to use first), I assumed the parameters were as such;&#xD;&#xA;&#xD;&#xA;n/f = **z** value of near and far planes&#xD;&#xA;&#xD;&#xA;r/l = **x** values of left and right planes&#xD;&#xA;&#xD;&#xA;t/b = **y** values of top and bottom planes&#xD;&#xA;&#xD;&#xA;For the right hand matrix, my book is very vague, and the only parameters that seem to fit are&#xD;&#xA;&#xD;&#xA;d/f - distances to near/far planes (but not necessarily the **z** values?)&#xD;&#xA;h - height of the near clip plane.&#xD;&#xA;&#xD;&#xA;My initial method of experimentation has been to plot the vertices of the frustum and using the transforms get a resultant that the X, Y values can be used to display the image in 2D and with Z values that can be used to decide what polygons overlay others.&#xD;&#xA;&#xD;&#xA;However, whilst I've been expecting a cube with dimensions of 1 -&gt; -1 along all axes, instead I've been getting just an inverted frustrum.&#xD;&#xA;&#xD;&#xA;I feel I'm either making an elementary mistake or am missing something key - would appreciate any help in clearing up both my uncertainties in what I need to do to convert my shape from the 3D to the 2D, and what I should be expecting. So far, my results are below. &#xD;&#xA;&#xD;&#xA;The left hand picture shows the shape in a view frustum - and the right shows the original frustum and transformed frustum in green after applying the perspective transform which I believe should be transformed to a unit sized cube and not just a reflected frustum.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I've put my code below, and tried to simplify it as much as possible to make it easier to evaluate!. Thanks very much!&#xD;&#xA;&#xD;&#xA;**Updates**&#xD;&#xA;I've updated my coordinates for view space coordinates - using a different method generates view space coordinates that go 'back' towards negative z values. Not sure if that makes it more correct but I hope it helps (but as per the comment).&#xD;&#xA;&#xD;&#xA;Following the answer below I've added an attempt to perform perspective division. I've added the following code below the main bulk. Any further recommendations would be massively appreciated&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %======Create View Space (hard-coded values for demo) &amp; Plot  ===========&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    ws_vtx = [-1.3416,0.4472,-1.3416,0.4472,-1.3416,-0.8944,0,0,0.8944,-0.8944,0,0,0.8944;&#xD;&#xA;              -1.0954,-1.4606,0.7303,0.3651,-1.0954,-0.7303,-0.9129,0,-0.1826,0.1826,0,0.9129,0.7303;&#xD;&#xA;              -4.899,-4.0825,-4.0825,-3.266,-2.4495,-4.4907,-4.0825,-6.1237,-5.7155,-4.0825,-3.6742,-5.7155,-5.3072];&#xD;&#xA;    &#xD;&#xA;    position = [0;0;0;1]; focus = [0;0;-3.6742]; %Transformed set points&#xD;&#xA;    &#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s');&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],[position(2); position(2)+focus(2)],...&#xD;&#xA;        [position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.1);&#xD;&#xA;    %====================Create View Volume===========================&#xD;&#xA;    asp_rat = 0.75; %Most displays arent square&#xD;&#xA;    focus = focus/norm(focus); %Normalise focus vector&#xD;&#xA;    nheight = 1; %height of near clip plane&#xD;&#xA;    hoz_angle = 2*pi/3;&#xD;&#xA;    ndistance = 1/tan(hoz_angle/2); %distance of near view plane from origin&#xD;&#xA;    fdistance = 5.5; %Define a far distance&#xD;&#xA;    &#xD;&#xA;    nc = ndistance*focus; %Centre point is focus vector * distance&#xD;&#xA;    ntr = nc + [asp_rat*nheight; nheight; 0]; %Go from centre to TL corner&#xD;&#xA;    nbr = ntr + [0; -2*nheight;0]; %Go down 2* height to bottom&#xD;&#xA;    nbl = nbr + [-2*asp_rat*nheight; 0; 0];&#xD;&#xA;    ntl = nbl + [0; 2*nheight;0];&#xD;&#xA;    nr_plan = [ntr, nbr, nbl, ntl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    fc = fdistance*focus;&#xD;&#xA;    fheight = tan(hoz_angle/2)*fdistance; %Find far plane height by trig&#xD;&#xA;    ftr = fc + [asp_rat*fheight; fheight; 0]; %Go from centre to TL corner&#xD;&#xA;    fbr = ftr + [0; -2*fheight;0]; %Go down 2* height to bottom&#xD;&#xA;    fbl = fbr + [-2*asp_rat*fheight; 0; 0];&#xD;&#xA;    ftl = fbl + [0; 2*fheight;0];&#xD;&#xA;    fr_plan = [ftr, fbr, fbl, ftl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    frust_vtx = horzcat(nr_plan, fr_plan); %Create frustum vertex array&#xD;&#xA;    frust_fcs = [1,8,5,6,4,5;  %Faces defined with normals inwards&#xD;&#xA;                 4,5,1,2,8,8;&#xD;&#xA;                 3,6,2,3,7,4;&#xD;&#xA;                 2,7,6,7,3,1];&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %=============Create Perspective Matrix ==============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot orig frustrum &#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    &#xD;&#xA;    left = nc(1) - asp_rat*nheight; %Get values for projection matrix&#xD;&#xA;    right = nc(1) + asp_rat*nheight;&#xD;&#xA;    top = nc(2) + nheight;&#xD;&#xA;    bottom = nc(2) -nheight;&#xD;&#xA;    near = ndistance;&#xD;&#xA;    far = fdistance;&#xD;&#xA;    &#xD;&#xA;    proj_mat = [2*near/(right - left),0,(right + left)/(right - left),0;&#xD;&#xA;        0, 2*near/(top-bottom),(top+bottom)/(top-bottom),0;&#xD;&#xA;        0,0, -(far+near)/(far-near), -2*far*near/(far-near);&#xD;&#xA;        0,0,-1,0];&#xD;&#xA;    %====================Perspective Projection Transformation=============&#xD;&#xA;    frust_vtx = proj_mat*vertcat(frust_vtx,(ones(1,length(frust_vtx)))); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Perspective Division**&#xD;&#xA;&#xD;&#xA;    %========================Perspective Division==========================&#xD;&#xA;    for i = 1:length(frust_vtx) &#xD;&#xA;        frust_vtx(:,i) = frust_vtx(:,i)/frust_vtx(4,i);&#xD;&#xA;    end&#xD;&#xA;    for i = 1:length(ws_vtx) &#xD;&#xA;        ws_vtx(:,i) = ws_vtx(:,i)/ws_vtx(4,i);&#xD;&#xA;    end&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)); %Plot shape points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx(1:3,:)','FaceColor','r','FaceAlpha', 0.05); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/adExB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EG3Iu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/W4xni.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13790" PostHistoryTypeId="5" PostId="2151" RevisionGUID="9dcaeaae-1b85-464c-ada7-8f057617f884" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="**EDIT: Please see my other answer with a concrete solution.**&#xD;&#xA;&#xD;&#xA;I have actually solved this exact problem over a year ago for my master's thesis. In the Valve paper, they show that you can AND two distance fields to achieve this, which works as long as you only have one convex corner. For concave corners, you also need the OR operation. [This guy][1] actually developed some obscure system to switch between the two operations using four texture channels.&#xD;&#xA;&#xD;&#xA;However, there is a much simpler operation that can facilitate both AND and OR depending on the situation, and this is the principal idea of my thesis: **the median of three**. So basically, you use exactly three channels (ideal for RGB), which are completely interchangeable, and combine them using the median operation (choose the middle value out of the three).&#xD;&#xA;&#xD;&#xA;To accomodate anti-aliasing, we don't work with just booleans, but floating point values, and the AND operation becomes the minimum, and the OR becomes the maximum of two values. The median of three can indeed do both: if *a* &lt; *b*, for (*a*, *a*, *b*), the median is the minimum, and for (*a*, *b*, *b*), it is the maximum.&#xD;&#xA;&#xD;&#xA;The rendering process is still extremely simple. The entire fragment shader including anti-aliasing can look something like this:&#xD;&#xA;&#xD;&#xA;    int main() {&#xD;&#xA;        // Bilinear sampling of the distance field&#xD;&#xA;        vec3 s = texture2D(sdf, p).rgb;&#xD;&#xA;        // Acquire the signed distance&#xD;&#xA;        float d = median(s.r, s.g, s.b) - 0.5;&#xD;&#xA;        // Weight between inside and outside (anti-aliasing)&#xD;&#xA;        float w = clamp(d/fwidth(d) + 0.5, 0.0, 1.0);&#xD;&#xA;        // Combining the background and foreground color&#xD;&#xA;        gl_FragColor = mix(outsideColor, insideColor, w);&#xD;&#xA;    }&#xD;&#xA;So the only difference from the original method is computing the median right after sampling the texture. You will have to implement the median function though, [which can be done with just 4 min/max operations][2].&#xD;&#xA;&#xD;&#xA;Now of course, the question is, **how do I build such a three-channel distance field?** And this is the tricky part. The most obvious approach that I took in the beginning was to perform a decomposition of the input shape/glyph into three components, and then generate a conventional distance field out of each. The rules for this decomposition aren't that complicated. Firstly , the area with at least 2 out of 3 channels on is the inside. Then, if you imagine this as the RGB color channels, convex corners must be made of a secondary color, and its two primary components continue outward. Concave corners are the inverse: Two secondary colors enclose their common primary color, and the wedge between where both edges continue inward is white. I also found that some padding is necessary where two primary or two secondary colors would otherwise touch to avoid artifacts (for example, in the middle stroke of the &quot;N&quot; in the picture).&#xD;&#xA;&#xD;&#xA;The following image is an example decomposition generated by the program from my thesis:&#xD;&#xA;&#xD;&#xA;[![Multi-channel decomposition of glyphs][3]][3]&#xD;&#xA;&#xD;&#xA;This approach however has some drawbacks. One of them is that the special effects, such as outlines and shadows will no longer work correctly. Fortunatelly, I also came up with a second, much more elegant method, which generates the distance fields directly, and even supports all of the graphical effects. It is also included in my thesis and so is also over a year old. I am not going to give any more details right now, because I am currently writing a paper that describes this second technique in detail, but I will post it here as soon as it's finished.&#xD;&#xA;&#xD;&#xA;Anyway, here is an example of the difference in quality. The texture resolution is the same in each image, but the left one uses a regular texture, the middle one uses an ordinary distance field, and the right one uses my three-channel distance field. The performance overhead is only the difference between sampling an RGB texture versus a monochrome one.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lambdacube3d.wordpress.com/2014/11/12/playing-around-with-font-rendering/&#xD;&#xA;  [2]: https://stackoverflow.com/a/19045659/1189488&#xD;&#xA;  [3]: https://i.stack.imgur.com/2fVah.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/aG1NR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13791" PostHistoryTypeId="5" PostId="2158" RevisionGUID="084156fe-00c9-49ed-8706-d1e0595c607e" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="Ok guys, tricky one!&#xD;&#xA;&#xD;&#xA;I'm trying to modify [this](http://wiki.unity3d.com/index.php?title=MirrorReflection2) Unity script + shader to include normal mapping. The tl;dr is, it uses a single texture rather than a cubemap as it is only for reflecting in a planar surface. So it doesn't use the standard ray bounce onto an axis aligned cube. Instead it :&#xD;&#xA;&#xD;&#xA; - creates a reflection matrix from the plane (pos and normal)&#xD;&#xA; - reflects the camera position and view matrix through the plane&#xD;&#xA; - renders to texture from the reflected camera (with oblique near clipping plane set to cull everything behind the mirror)&#xD;&#xA; - creates a projection matrix and sends it as uniform to the shader (basically just a standard MVP matrix but with scale cancelled, and biased from [-1, 1] to [0, 1]&#xD;&#xA; - multiplies the object space coordinate by the projection matrix to get a texcoord and then looks up the mirror texture with this&#xD;&#xA;&#xD;&#xA;So there are no normals actually used in the shader at all at present. I know how to construct a TBN matrix and use this to warp the per-pixel normals, but I have no idea how this translates into a texture offset in this case. I have a feeling I might need screen-space normals like in the question [here](https://stackoverflow.com/questions/14317350/transform-world-space-normals-to-screen-space-normals) but pretty stumped beyond that. Any ideas?&#xD;&#xA;&#xD;&#xA;EDIT -- Here's the script&#xD;&#xA;&#xD;&#xA;    using UnityEngine;&#xD;&#xA;    using System.Collections;&#xD;&#xA;&#xD;&#xA;    [ExecuteInEditMode()]&#xD;&#xA;    public class PlanarRealtimeReflection : MonoBehaviour&#xD;&#xA;    {&#xD;&#xA;    	public bool m_DisablePixelLights = true;&#xD;&#xA;    	public int m_TextureResolution = 1024;&#xD;&#xA;    	public float m_clipPlaneOffset = 0.07f;&#xD;&#xA;    	private float m_finalClipPlaneOffset = 0.0f;&#xD;&#xA;    	public bool m_NormalsFromMesh = false;&#xD;&#xA;    	public bool m_BaseClipOffsetFromMesh = false;&#xD;&#xA;    	public bool m_BaseClipOffsetFromMeshInverted = false;&#xD;&#xA;    	private Vector3 m_calculatedNormal = Vector3.zero;&#xD;&#xA;        private Vector3 m_calculatedTangent = Vector4.zero;&#xD;&#xA;    	public LayerMask m_ReflectLayers = -1;&#xD;&#xA;    	&#xD;&#xA;    	private Hashtable m_ReflectionCameras = new Hashtable(); //Camera -&gt; Camera table&#xD;&#xA;    	&#xD;&#xA;    	private RenderTexture m_ReflectionTexture = null;&#xD;&#xA;    	private int m_OldReflectionTextureSize = 0;&#xD;&#xA;    	&#xD;&#xA;    	private static bool s_InsideRendering = false;&#xD;&#xA;    	&#xD;&#xA;    	//This is called when it's known that the object will be rendered by some&#xD;&#xA;    	//camera. We render reflections and do other updates here.&#xD;&#xA;    	//Because the script executes in edit mode, reflections for the scene view&#xD;&#xA;    	//camera will just work!&#xD;&#xA;    	public void OnWillRenderObject()&#xD;&#xA;    	{&#xD;&#xA;    		if(!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled)&#xD;&#xA;    			return;&#xD;&#xA;    &#xD;&#xA;    		Camera cam = Camera.current;&#xD;&#xA;    		if(!cam)&#xD;&#xA;    			return;&#xD;&#xA;    		&#xD;&#xA;    		if(m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;    			m_calculatedNormal = transform.TransformDirection(GetComponent&lt;MeshFilter&gt;().sharedMesh.normals[0]);&#xD;&#xA;                m_calculatedTangent = transform.TransformDirection(GetComponent&lt;MeshFilter&gt;().sharedMesh.tangents[0]);&#xD;&#xA;    		    &#xD;&#xA;    		if(m_BaseClipOffsetFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;    			m_finalClipPlaneOffset = (transform.position - transform.TransformPoint(GetComponent&lt;MeshFilter&gt;().sharedMesh.vertices[0])).magnitude + m_clipPlaneOffset;&#xD;&#xA;    		else if(m_BaseClipOffsetFromMeshInverted &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null)&#xD;&#xA;    			m_finalClipPlaneOffset = -(transform.position - transform.TransformPoint(GetComponent&lt;MeshFilter&gt;().sharedMesh.vertices[0])).magnitude + m_clipPlaneOffset;&#xD;&#xA;    		else&#xD;&#xA;    			m_finalClipPlaneOffset = m_clipPlaneOffset;&#xD;&#xA;    		&#xD;&#xA;    		//Safeguard from recursive reflections.        &#xD;&#xA;    		if(s_InsideRendering)&#xD;&#xA;    			return;&#xD;&#xA;    		s_InsideRendering = true;&#xD;&#xA;    		&#xD;&#xA;    		Camera reflectionCamera;&#xD;&#xA;    		CreateSurfaceObjects(cam, out reflectionCamera);&#xD;&#xA;    		&#xD;&#xA;    		//Find out the reflection plane: position and normal in world space&#xD;&#xA;    		Vector3 pos = transform.position;&#xD;&#xA;    		Vector3 normal = m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null ? m_calculatedNormal : transform.up;&#xD;&#xA;            Vector3 tangent = m_NormalsFromMesh &amp;&amp; GetComponent&lt;MeshFilter&gt;() != null ? m_calculatedTangent : transform.right;&#xD;&#xA;            Vector3 bitangent = Vector3.Cross(normal, tangent);&#xD;&#xA;    &#xD;&#xA;    		//Optionally disable pixel lights for reflection&#xD;&#xA;    		int oldPixelLightCount = QualitySettings.pixelLightCount;&#xD;&#xA;    		if(m_DisablePixelLights)&#xD;&#xA;    			QualitySettings.pixelLightCount = 0;&#xD;&#xA;    		&#xD;&#xA;    		UpdateCameraModes(cam, reflectionCamera);&#xD;&#xA;    		&#xD;&#xA;    		//Render reflection&#xD;&#xA;    		//Reflect camera around reflection plane&#xD;&#xA;    		float d = -Vector3.Dot (normal, pos) - m_finalClipPlaneOffset;&#xD;&#xA;    		Vector4 reflectionPlane = new Vector4 (normal.x, normal.y, normal.z, d);&#xD;&#xA;    		Matrix4x4 reflection = Matrix4x4.zero;&#xD;&#xA;    		CalculateReflectionMatrix (ref reflection, reflectionPlane);&#xD;&#xA;    		Vector3 oldpos = cam.transform.position;&#xD;&#xA;    		Vector3 newpos = reflection.MultiplyPoint(oldpos);&#xD;&#xA;    		reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;&#xD;&#xA;    		&#xD;&#xA;    		//Setup oblique projection matrix so that near plane is our reflection plane.&#xD;&#xA;    		//This way we clip everything below/above it for free.&#xD;&#xA;    		Vector4 clipPlane = CameraSpacePlane(reflectionCamera, pos, normal, 1.0f);&#xD;&#xA;    		Matrix4x4 projection = cam.projectionMatrix;&#xD;&#xA;    		CalculateObliqueMatrix (ref projection, clipPlane);&#xD;&#xA;    		reflectionCamera.projectionMatrix = projection;&#xD;&#xA;    		&#xD;&#xA;    		reflectionCamera.cullingMask = ~(1&lt;&lt;4) &amp; m_ReflectLayers.value; //never render water layer&#xD;&#xA;    		reflectionCamera.targetTexture = m_ReflectionTexture;&#xD;&#xA;    		GL.SetRevertBackfacing (true);&#xD;&#xA;    		reflectionCamera.transform.position = newpos;&#xD;&#xA;    		//Vector3 euler = cam.transform.eulerAngles;&#xD;&#xA;            //reflectionCamera.transform.eulerAngles = euler; // new Vector3(0, euler.y, euler.z);&#xD;&#xA;    		reflectionCamera.Render();&#xD;&#xA;    		reflectionCamera.transform.position = oldpos;&#xD;&#xA;    		GL.SetRevertBackfacing (false);&#xD;&#xA;    		Material[] materials = renderer.sharedMaterials;&#xD;&#xA;    		foreach(Material mat in materials)&#xD;&#xA;    		{&#xD;&#xA;                if (mat.HasProperty(&quot;_ReflectionTex&quot;))  &#xD;&#xA;    				mat.SetTexture(&quot;_ReflectionTex&quot;, m_ReflectionTexture);&#xD;&#xA;                mat.SetVector(&quot;_Normal&quot;, new Vector4(normal.x,normal.y,normal.z,0));&#xD;&#xA;                mat.SetVector(&quot;_Tangent&quot;, new Vector4(tangent.x, tangent.y, tangent.z));&#xD;&#xA;                mat.SetVector(&quot;_Bitangent&quot;, new Vector4(bitangent.x, bitangent.y, bitangent.z));&#xD;&#xA;    		}&#xD;&#xA;    		&#xD;&#xA;    		//Set matrix on the shader that transforms UVs from object space into screen&#xD;&#xA;    		//space. We want to just project reflection texture on screen.&#xD;&#xA;    		Matrix4x4 scaleOffset = Matrix4x4.TRS(&#xD;&#xA;    			new Vector3(0.5f,0.5f,0.5f), Quaternion.identity, new Vector3(0.5f,0.5f,0.5f));&#xD;&#xA;    		Vector3 scale = transform.localScale;//.lossyScale;&#xD;&#xA;            Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z));&#xD;&#xA;            mtx = scaleOffset *  cam.projectionMatrix * cam.worldToCameraMatrix * mtx;&#xD;&#xA;    		foreach(Material mat in materials)&#xD;&#xA;    			mat.SetMatrix(&quot;_ProjMatrix&quot;, mtx);&#xD;&#xA;    		//Restore pixel light count&#xD;&#xA;    		if(m_DisablePixelLights)&#xD;&#xA;    			QualitySettings.pixelLightCount = oldPixelLightCount;&#xD;&#xA;    		&#xD;&#xA;    		s_InsideRendering = false;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	//Cleanup all the objects we possibly have created&#xD;&#xA;    	void OnDisable()&#xD;&#xA;    	{&#xD;&#xA;    		if(m_ReflectionTexture)&#xD;&#xA;    		{&#xD;&#xA;    			DestroyImmediate(m_ReflectionTexture);&#xD;&#xA;    			m_ReflectionTexture = null;&#xD;&#xA;    		}&#xD;&#xA;    		foreach(DictionaryEntry kvp in m_ReflectionCameras)&#xD;&#xA;    			DestroyImmediate(((Camera)kvp.Value).gameObject);&#xD;&#xA;    		m_ReflectionCameras.Clear();&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	private void UpdateCameraModes(Camera src, Camera dest)&#xD;&#xA;    	{&#xD;&#xA;    		if(dest == null)&#xD;&#xA;    			return;&#xD;&#xA;    		//set camera to clear the same way as current camera&#xD;&#xA;    		dest.clearFlags = src.clearFlags;&#xD;&#xA;    		dest.backgroundColor = src.backgroundColor;        &#xD;&#xA;    		if(src.clearFlags == CameraClearFlags.Skybox)&#xD;&#xA;    		{&#xD;&#xA;    			Skybox sky = src.GetComponent(typeof(Skybox)) as Skybox;&#xD;&#xA;    			Skybox mysky = dest.GetComponent(typeof(Skybox)) as Skybox;&#xD;&#xA;    			if(!sky || !sky.material)&#xD;&#xA;    			{&#xD;&#xA;    				mysky.enabled = false;&#xD;&#xA;    			}&#xD;&#xA;    			else&#xD;&#xA;    			{&#xD;&#xA;    				mysky.enabled = true;&#xD;&#xA;    				mysky.material = sky.material;&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    		//update other values to match current camera.&#xD;&#xA;    		//even if we are supplying custom camera&amp;projection matrices,&#xD;&#xA;    		//some of values are used elsewhere (e.g. skybox uses far plane)&#xD;&#xA;    		dest.farClipPlane = src.farClipPlane;&#xD;&#xA;    		dest.nearClipPlane = src.nearClipPlane;&#xD;&#xA;    		dest.orthographic = src.orthographic;&#xD;&#xA;    		dest.fieldOfView = src.fieldOfView;&#xD;&#xA;    		dest.aspect = src.aspect;&#xD;&#xA;    		dest.orthographicSize = src.orthographicSize;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//On-demand create any objects we need&#xD;&#xA;    	private void CreateSurfaceObjects(Camera currentCamera, out Camera reflectionCamera)&#xD;&#xA;    	{&#xD;&#xA;    		reflectionCamera = null;&#xD;&#xA;    		&#xD;&#xA;    		//Reflection render texture&#xD;&#xA;    		if(!m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureResolution)&#xD;&#xA;    		{&#xD;&#xA;    			if(m_ReflectionTexture)&#xD;&#xA;    				DestroyImmediate(m_ReflectionTexture);&#xD;&#xA;    			m_ReflectionTexture = new RenderTexture(m_TextureResolution, m_TextureResolution, 16);&#xD;&#xA;    			m_ReflectionTexture.name = &quot;__SurfaceReflection&quot; + GetInstanceID();&#xD;&#xA;    			m_ReflectionTexture.isPowerOfTwo = true;&#xD;&#xA;    			m_ReflectionTexture.hideFlags = HideFlags.DontSave;&#xD;&#xA;    			m_OldReflectionTextureSize = m_TextureResolution;&#xD;&#xA;    		}&#xD;&#xA;    		&#xD;&#xA;    		//Camera for reflection&#xD;&#xA;    		reflectionCamera = m_ReflectionCameras[currentCamera] as Camera;&#xD;&#xA;    		if(!reflectionCamera) //catch both not-in-dictionary and in-dictionary-but-deleted-GO&#xD;&#xA;    		{&#xD;&#xA;    			GameObject go = new GameObject(&quot;Surface Refl Camera id&quot; + GetInstanceID() + &quot; for &quot; + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox));&#xD;&#xA;    			reflectionCamera = go.camera;&#xD;&#xA;    			reflectionCamera.enabled = false;&#xD;&#xA;    			reflectionCamera.transform.position = transform.position;&#xD;&#xA;    			reflectionCamera.transform.rotation = transform.rotation;&#xD;&#xA;    			reflectionCamera.gameObject.AddComponent(&quot;FlareLayer&quot;);&#xD;&#xA;    			go.hideFlags = HideFlags.HideAndDontSave;&#xD;&#xA;    			m_ReflectionCameras[currentCamera] = reflectionCamera;&#xD;&#xA;    		}        &#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Extended sign: returns -1, 0 or 1 based on sign of a&#xD;&#xA;    	private static float sgn(float a)&#xD;&#xA;    	{&#xD;&#xA;    		if (a &gt; 0.0f) return 1.0f;&#xD;&#xA;    		if (a &lt; 0.0f) return -1.0f;&#xD;&#xA;    		return 0.0f;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Given position/normal of the plane, calculates plane in camera space.&#xD;&#xA;    	private Vector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)&#xD;&#xA;    	{&#xD;&#xA;    		Vector3 offsetPos = pos + normal * m_finalClipPlaneOffset;&#xD;&#xA;    		Matrix4x4 m = cam.worldToCameraMatrix;&#xD;&#xA;    		Vector3 cpos = m.MultiplyPoint(offsetPos);&#xD;&#xA;    		Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;&#xD;&#xA;    		return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal));&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Adjusts the given projection matrix so that near plane is the given clipPlane&#xD;&#xA;    	//clipPlane is given in camera space. See article in Game Programming Gems 5 and&#xD;&#xA;    	//http://aras-p.info/texts/obliqueortho.html&#xD;&#xA;    	private static void CalculateObliqueMatrix (ref Matrix4x4 projection, Vector4 clipPlane)&#xD;&#xA;    	{&#xD;&#xA;    		Vector4 q = projection.inverse * new Vector4(&#xD;&#xA;    			sgn(clipPlane.x),&#xD;&#xA;    			sgn(clipPlane.y),&#xD;&#xA;    			1.0f,&#xD;&#xA;    			1.0f&#xD;&#xA;    			);&#xD;&#xA;    		Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlane, q)));&#xD;&#xA;    		//third row = clip plane - fourth row&#xD;&#xA;    		projection[2] = c.x - projection[3];&#xD;&#xA;    		projection[6] = c.y - projection[7];&#xD;&#xA;    		projection[10] = c.z - projection[11];&#xD;&#xA;    		projection[14] = c.w - projection[15];&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	//Calculates reflection matrix around the given plane&#xD;&#xA;    	private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)&#xD;&#xA;    	{&#xD;&#xA;    		reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);&#xD;&#xA;    		reflectionMat.m01 = (  - 2F*plane[0]*plane[1]);&#xD;&#xA;    		reflectionMat.m02 = (  - 2F*plane[0]*plane[2]);&#xD;&#xA;    		reflectionMat.m03 = (  - 2F*plane[3]*plane[0]);&#xD;&#xA;    		&#xD;&#xA;    		reflectionMat.m10 = (  - 2F*plane[1]*plane[0]);&#xD;&#xA;    		reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);&#xD;&#xA;    		reflectionMat.m12 = (  - 2F*plane[1]*plane[2]);&#xD;&#xA;    		reflectionMat.m13 = (  - 2F*plane[3]*plane[1]);&#xD;&#xA;    		&#xD;&#xA;    		reflectionMat.m20 = (  - 2F*plane[2]*plane[0]);&#xD;&#xA;    		reflectionMat.m21 = (  - 2F*plane[2]*plane[1]);&#xD;&#xA;    		reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);&#xD;&#xA;    		reflectionMat.m23 = (  - 2F*plane[3]*plane[2]);&#xD;&#xA;    		&#xD;&#xA;    		reflectionMat.m30 = 0F;&#xD;&#xA;    		reflectionMat.m31 = 0F;&#xD;&#xA;    		reflectionMat.m32 = 0F;&#xD;&#xA;    		reflectionMat.m33 = 1F;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the shader so far&#xD;&#xA;&#xD;&#xA;    Shader &quot;Realtime Reflections/New Shader&quot;&#xD;&#xA;    {&#xD;&#xA;        Properties {		&#xD;&#xA;            _MainAlpha(&quot;MainAlpha&quot;, Range(0, 1)) = 1&#xD;&#xA;    		_MapAmount(&quot;Distortion Amount&quot;, Range(0, 0.05)) = 0&#xD;&#xA;            _MainTex (&quot;Base (RGB) Gloss (A)&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;            _ReflectionTex (&quot;Reflection&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;    		_NormalMap (&quot;Normal Map&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;    		_RefColor(&quot;Color&quot;,Color) = (1,1,1,1)&#xD;&#xA;    	}&#xD;&#xA;    	SubShader {&#xD;&#xA;            Tags {&#xD;&#xA;                &quot;RenderType&quot;=&quot;Opaque&quot;}&#xD;&#xA;    		LOD 100&#xD;&#xA;    		Pass {&#xD;&#xA;                CGPROGRAM&#xD;&#xA;    			#pragma vertex vert&#xD;&#xA;    			#pragma fragment frag&#xD;&#xA;    			#include &quot;UnityCG.cginc&quot;&#xD;&#xA;    &#xD;&#xA;    			uniform float4x4	_ProjMatrix;&#xD;&#xA;    			uniform float		_RefType;&#xD;&#xA;    			uniform float4		_Normal;&#xD;&#xA;    			uniform float4		_Tangent;&#xD;&#xA;    			uniform float4		_Bitangent;&#xD;&#xA;                sampler2D			_ReflectionTex;&#xD;&#xA;    			sampler2D			_MainTex;&#xD;&#xA;    			sampler2D			_NormalMap;&#xD;&#xA;    			float4				_MainTex_ST;&#xD;&#xA;    			float4				_NormalMap_ST;       &#xD;&#xA;                float4				_RefColor;&#xD;&#xA;                float				_MainAlpha;&#xD;&#xA;    			float				_MapAmount;&#xD;&#xA;    &#xD;&#xA;                struct outvertex {&#xD;&#xA;                    float4 pos :		SV_POSITION;&#xD;&#xA;                    float2 colorUV :	TEXCOORD0;&#xD;&#xA;    				float2 bumpUV :		TEXCOORD1;&#xD;&#xA;    				float4 varyingPos : TEXCOORD2;&#xD;&#xA;                };&#xD;&#xA;                &#xD;&#xA;    			outvertex vert(appdata_full v) {&#xD;&#xA;    			&#xD;&#xA;                    outvertex o;&#xD;&#xA;                    o.pos = mul (UNITY_MATRIX_MVP,v.vertex);&#xD;&#xA;                    o.colorUV = TRANSFORM_TEX(v.texcoord.xy,_MainTex);&#xD;&#xA;    				o.bumpUV = TRANSFORM_TEX(v.texcoord1.xy,_NormalMap);&#xD;&#xA;    				o.varyingPos = v.vertex;	&#xD;&#xA;    				o. color = fixed4(mul(float3x3(UNITY_MATRIX_IT_MV),v.normal),1);&#xD;&#xA;    				return o;&#xD;&#xA;                }&#xD;&#xA;    										&#xD;&#xA;    			float4 frag(outvertex i) : COLOR {          &#xD;&#xA;    				float4 posProj = mul(_ProjMatrix, i.varyingPos);      &#xD;&#xA;    				float2 normPosProj = posProj.xy / posProj.w;&#xD;&#xA;    				float3 bump = (float3(tex2D(_NormalMap, i.bumpUV));&#xD;&#xA;    				//normPosProj += ?????????&#xD;&#xA;    				half4 flecol = tex2D(_ReflectionTex, normPosProj);	&#xD;&#xA;    				half4 maincol =  tex2D(_MainTex, i.colorUV);									&#xD;&#xA;    				half4 outcolor = half4(1,1,1,1);				&#xD;&#xA;    				outcolor = maincol*_MainAlpha+flecol*(1-_MainAlpha);&#xD;&#xA;                    return outcolor*_RefColor;&#xD;&#xA;                }&#xD;&#xA;    			ENDCG&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I had the idea to get the normal in screen space (so z is always toward camera) then simply find the delta between the regular normal and the warped one in x,y and use this as the texture offset, but I have no idea if this is feasible or how to do it." ContentLicense="CC BY-SA 3.0" />
  <row Id="13792" PostHistoryTypeId="5" PostId="2243" RevisionGUID="86d3101b-c99f-41fb-91fe-02b3894d130e" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="This is a hard problem since the systems do not in fact tell you how it should operate. The problem is that there are several ways to address this issue:&#xD;&#xA;&#xD;&#xA;1. Apply a LUT to all output&#xD;&#xA;2. Let the system color manage&#xD;&#xA;3. Let each application color manage&#xD;&#xA;&#xD;&#xA;Nearly all of our color management systems are borderline braindead. There is really no sane way to ensure that you are doing the proper thing without extensively testing the system. You can not ask or specify your intent. In case of multi operating system situations. If there is reason for me to color manage something myself im at the mercy of each operating system peculiarities.&#xD;&#xA;&#xD;&#xA;For a alternate discussion on this see this [stackoverflow post](https://stackoverflow.com/questions/23026151/do-i-need-to-gamma-correct-the-final-color-output-on-a-modern-computer-monitor). But its not really a robust enough talk to cover all cases." ContentLicense="CC BY-SA 3.0" />
  <row Id="13793" PostHistoryTypeId="5" PostId="2354" RevisionGUID="c5c944c0-8851-415a-8a62-12974a047804" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="In order to replace a color with another color, you need some sort of [distance metric](https://en.wikipedia.org/wiki/Metric_(mathematics)) between the colors and a function for calculating the [blending](https://en.wikipedia.org/wiki/Blend_modes) based on that distance. &#xD;&#xA;&#xD;&#xA;Finding a distance between 2 colors can be tricky. RGB is a bad color space to measure the distance between colors for perceptual uses. HSV or YCbCr are better. &#xD;&#xA;&#xD;&#xA;Once you have the colors in a color space you like, you need to decide how to calculate the distance. I generally calculate the hue distance for starters. If the hue of the color I'm considering replacing is within +/- some threshold (possibly set by the user), then I check to see if the saturation and value are within a certain range, too. &#xD;&#xA;&#xD;&#xA;Once I've found a color that's within the ranges specified, I calculate a blending amount. Usually this will be 100% if the color in the image exactly matches the color I want to replace, and will fall off to 0 at the thresholds of hue, saturation and brightness. &#xD;&#xA;&#xD;&#xA;You then need to calculate the color you're going to use as a replacement color. It's useful to offset the hue, saturation and value (or Y, Cb, and Cr components) by the same amount as the color in the image differs from the replacement color.&#xD;&#xA;&#xD;&#xA;So now you have the original color in the image, the color to replace it with, and a blending amount. You still need to figure out which blend mode you want to use. I would start with what Photoshop calls &quot;Normal&quot; or &quot;Over&quot;. That would be a linear mix of the two. If you have colors A and B with a mix amount of 25%, it would be calculated like this:&#xD;&#xA;&#xD;&#xA;newColor = A * .25 + B * (1.0 - .25);&#xD;&#xA;&#xD;&#xA;Here are some relevant answers I gave to similar questions on Stack Overflow:&#xD;&#xA;&#xD;&#xA;[How to Change the Hue of a Texture with GLSL](https://stackoverflow.com/questions/9234724/how-to-change-hue-of-a-texture-with-glsl/9234854#9234854)&#xD;&#xA;&#xD;&#xA;[Better Image Coloring Logic/Algorithm](https://stackoverflow.com/questions/9064556/better-image-coloring-logic-algorithm/9075340#9075340)" ContentLicense="CC BY-SA 3.0" />
  <row Id="13794" PostHistoryTypeId="5" PostId="2449" RevisionGUID="c5155463-a16f-4216-b982-a3f9a228b449" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="The interpolation looks fine. The main problem here is that the hash function you're using isn't very good. If I look at just one octave, and visualize the hash result by outputting `hash(PT).x`, I get something like this:&#xD;&#xA;&#xD;&#xA;[![bad hash function][1]][1]&#xD;&#xA;&#xD;&#xA;This is supposed to be completely random per grid square, but you can see that it has a lot of diagonal line patterns in it (it almost looks like a checkerboard), so it's not a very random hash, and those patterns will show up in the noise produced by it.&#xD;&#xA;&#xD;&#xA;The other problem is that your hash only returns gradient vectors in [0, 1], while they should be in [&amp;minus;1, 1] to get gradients in all directions. That part's easy to fix by remapping.&#xD;&#xA;&#xD;&#xA;To fix those problems, I switched the code to use this hash function (which I learned from Mikkel Gjoel, and [is probably due to a paper by W.J.J. Rey](https://stackoverflow.com/questions/12964279/whats-the-origin-of-this-glsl-rand-one-liner/)):&#xD;&#xA;&#xD;&#xA;    vec2 hash(vec2 co) {&#xD;&#xA;        float m = dot(co, vec2(12.9898, 78.233));&#xD;&#xA;        return fract(vec2(sin(m),cos(m))* 43758.5453) * 2. - 1.;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note that due to the trig functions it's going to be a bit more expensive than your version. However, it considerably improves the appearance of the resulting noise:&#xD;&#xA;&#xD;&#xA;[![fbm noise with better hash function][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LcFJV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ND8Es.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13795" PostHistoryTypeId="5" PostId="3605" RevisionGUID="848169db-e35a-4116-8b6d-e1da62833e6f" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="At first: I already posted this on the stackoverflow community. I'm new and didn't know about this community here. I apologize.&#xD;&#xA;&#xD;&#xA;I basically got the same question as the guy who asked here: https://stackoverflow.com/questions/36457138/dynamically-sized-arrays-in-opengl-es-vertex-shader-used-for-blend-shapes-morph.&#xD;&#xA;Especially his last unanswered question bothers me too.&#xD;&#xA;&#xD;&#xA;So I also want to use an arbitrary number of blendshapes for each mesh I'm processing. At the moment I'm using a fixed number and treat the shapes as vertex attribute. The advantage here is that I always have the relevant data for the current vertex availiable. Now, if I want to use an arbitrary number of shapes, I figured I'd use SSBOs since their clue is exactly what I want: Dynamically sized data. However SSBOs are, as far as I understand it, static and for each processed vertex in the shader I have the blendshape data for the whole mesh availiable. That means I would have to introduce some kind of counter and try to pick the correct data piece out of my SSBO for each vertex.&#xD;&#xA;&#xD;&#xA;Is this understanding correct? I'm really not sure whether this is the optimal solution, maybe you can give me some hints.&#xD;&#xA;&#xD;&#xA;Thank you for your answers!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13796" PostHistoryTypeId="5" PostId="3637" RevisionGUID="17fcfa9e-5459-41f2-8826-452cab5bc77d" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="WebGL 1.0 specification does not allow [to create 32-bit index buffers][1]. Now I'm in trouble, I'm trying to render huge objects with 100 thousands to 1 million indices. In OpenGL this is no issue at all, and I think it will be no issue in WebGL too, in most cases.&#xD;&#xA;&#xD;&#xA;I am not able [to split my data into smaller subsets][2] as I'm already working with split data sets and can't divide it further without breaking up my full program logic.&#xD;&#xA;&#xD;&#xA;Now I came across a new extension for WebGL from 2012, [OES_element_index_uint][3], which looks like it enables unsigned integers (32 bit) for `drawElements` calls. &#xD;&#xA;&#xD;&#xA;    /* draw geometry lines by indices */&#xD;&#xA;    gl.drawElements(gl.LINES, getIndexBuffer().length, gl.UNSIGNED_INT, idxBuffer);&#xD;&#xA;&#xD;&#xA;But when I try to use the `gl.UNSIGNED_INT` I run into the following error:&#xD;&#xA;&#xD;&#xA;    Error: WebGL: drawElements: Invalid `type`: 0x1405&#xD;&#xA;    uncaught exception: gl.INVALID_ENUM was caused by call to drawElements&#xD;&#xA;&#xD;&#xA;How to use 32 bit Integers for Element Indices in WebGL 1.0? How to enable this extension in Chrome or Firefox?&#xD;&#xA;&#xD;&#xA;Does this mean in general such a call won't be compatible with most devices running WebGL 1.0?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/webgl/public-mailing-list/archives/1102/msg00093.php&#xD;&#xA;  [2]: https://stackoverflow.com/a/5189502/1260906&#xD;&#xA;  [3]: https://www.khronos.org/registry/webgl/extensions/OES_element_index_uint/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13797" PostHistoryTypeId="5" PostId="3673" RevisionGUID="ea770313-6e26-47e9-8c9e-c1ed7589129e" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="1) Drawing a bunch of 3d cubes with simple textures? Yes, SceneKit can do that.  &#xD;&#xA;&#xD;&#xA;2) Way too broad a question... try [reading the docs.](https://developer.apple.com/library/ios/documentation/SceneKit/Reference/SceneKit_Framework/)&#xD;&#xA;&#xD;&#xA;3) Since this is a platform specific question try the **scenekit** and **scene-kit** tags on [stackOverflow](https://stackoverflow.com/) and [Game Development](https://gamedev.stackexchange.com/), but see answer 2 first.&#xD;&#xA;&#xD;&#xA;good luck!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13798" PostHistoryTypeId="5" PostId="3680" RevisionGUID="f9112166-4873-47c7-b77d-64f305829e80" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="_This is a copy-paste of [my answer](https://stackoverflow.com/a/38039733/673852) to the same [question at StackOverflow](https://stackoverflow.com/q/2508818/673852)_.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;At the bottom of this answer is an example of GLSL code which allows to output the full `float` value as color, encoding IEEE 754 `binary32`. I use it like follows (this snippet gives out `yy` component of modelview matrix):&#xD;&#xA;&#xD;&#xA;&lt;!-- NOTE: setting highlighting language to C since it has similar syntax while GLSL highlighting isn't supported on stackexchange --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);&#xD;&#xA;    if(bool(1)) // put 0 here to get lowest byte instead of three highest&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.rgb,1);&#xD;&#xA;    else&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.a,0,0,1);&#xD;&#xA;&#xD;&#xA;After you get this on screen, you can just take any color picker, format the color as HTML (appending `00` to the `rgb` value if you don't need higher precision, and doing a second pass to get the lower byte if you do), and you get the hexadecimal representation of the `float` as IEEE 754 `binary32`.&#xD;&#xA;&#xD;&#xA;Here's the actual implementation of `toColor()`:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;    &#xD;&#xA;    const int emax=127;&#xD;&#xA;    // Input: x&gt;=0&#xD;&#xA;    // Output: base 2 exponent of x if (x!=0 &amp;&amp; !isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    //         -emax if x==0&#xD;&#xA;    //         emax+1 otherwise&#xD;&#xA;    int floorLog2(float x)&#xD;&#xA;    {&#xD;&#xA;        if(x==0) return -emax;&#xD;&#xA;        // NOTE: there exist values of x, for which floor(log2(x)) will give wrong&#xD;&#xA;        // (off by one) result as compared to the one calculated with infinite precision.&#xD;&#xA;        // Thus we do it in a brute-force way.&#xD;&#xA;        for(int e=emax;e&gt;=1-emax;--e)&#xD;&#xA;            if(x&gt;=exp2(float(e))) return e;&#xD;&#xA;        // If we are here, x must be infinity or NaN&#xD;&#xA;        return emax+1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x&#xD;&#xA;    // Output: IEEE 754 biased exponent with bias=emax&#xD;&#xA;    int biasedExp(float x) { return emax+floorLog2(abs(x)); }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that (!isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    // Output: significand AKA mantissa of x if !isnan(x) &amp;&amp; !isinf(x)&#xD;&#xA;    //         undefined otherwise&#xD;&#xA;    float significand(float x)&#xD;&#xA;    {&#xD;&#xA;        // converting int to float so that exp2(genType) gets correctly-typed value&#xD;&#xA;        float expo=floorLog2(abs(x));&#xD;&#xA;        return abs(x)/exp2(expo);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: x\in[0,1)&#xD;&#xA;    //        N&gt;=0&#xD;&#xA;    // Output: Nth byte as counted from the highest byte in the fraction&#xD;&#xA;    int part(float x,int N)&#xD;&#xA;    {&#xD;&#xA;        // All comments about exactness here assume that underflow and overflow don't occur&#xD;&#xA;        const int byteShift=256;&#xD;&#xA;        // Multiplication is exact since it's just an increase of exponent by 8&#xD;&#xA;        for(int n=0;n&lt;N;++n)&#xD;&#xA;            x*=byteShift;&#xD;&#xA;    &#xD;&#xA;        // Cut higher bits away.&#xD;&#xA;        // $q \in [0,1) \cap \mathbb Q'.$&#xD;&#xA;        float q=fract(x);&#xD;&#xA;    &#xD;&#xA;        // Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected&#xD;&#xA;        // results of rounding by the GPU later in the pipeline when transforming to TrueColor&#xD;&#xA;        // the resulting subpixel value.&#xD;&#xA;        // $c \in [0,255] \cap \mathbb Z.$&#xD;&#xA;        // Multiplication is exact since it's just and increase of exponent by 8&#xD;&#xA;        float c=floor(byteShift*q);&#xD;&#xA;        return int(c);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x acceptable to significand()&#xD;&#xA;    // Output: significand of x split to (8,8,8)-bit data vector&#xD;&#xA;    ivec3 significandAsIVec3(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec3 result;&#xD;&#xA;        float sig=significand(x)/2; // shift all bits to fractional part&#xD;&#xA;        result.x=part(sig,0);&#xD;&#xA;        result.y=part(sig,1);&#xD;&#xA;        result.z=part(sig,2);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that !isnan(x)&#xD;&#xA;    // Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)&#xD;&#xA;    ivec4 packIEEE754binary32(float x)&#xD;&#xA;    {&#xD;&#xA;        int e = biasedExp(x);&#xD;&#xA;        // sign to bit 7&#xD;&#xA;        int s = x&lt;0 ? 128 : 0;&#xD;&#xA;    &#xD;&#xA;        ivec4 binary32;&#xD;&#xA;        binary32.yzw=significandAsIVec3(x);&#xD;&#xA;        // clear the implicit integer bit of significand&#xD;&#xA;        if(binary32.y&gt;=128) binary32.y-=128;&#xD;&#xA;        // put lowest bit of exponent into its position, replacing just cleared integer bit&#xD;&#xA;        binary32.y+=128*int(mod(e,2));&#xD;&#xA;        // prepare high bits of exponent for fitting into their positions&#xD;&#xA;        e/=2;&#xD;&#xA;        // pack highest byte&#xD;&#xA;        binary32.x=e+s;&#xD;&#xA;    &#xD;&#xA;        return binary32;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec4 toColor(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec4 binary32=packIEEE754binary32(x);&#xD;&#xA;        // Transform color components to [0,1] range.&#xD;&#xA;        // Division is inexact, but works reliably for all integers from 0 to 255 if&#xD;&#xA;        // the transformation to TrueColor by GPU uses rounding to nearest or upwards.&#xD;&#xA;        // The result will be multiplied by 255 back when transformed&#xD;&#xA;        // to TrueColor subpixel value by OpenGL.&#xD;&#xA;        return binary32/255.;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="13799" PostHistoryTypeId="5" PostId="3758" RevisionGUID="daa89828-831b-4e99-bb5f-92e863df2f08" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I am trying to implement [Ray Tracing with Cones (Amanatides 1984)][1]. Instead of rays, cones are shot into the scene and intersected with geometry. Since multiple triangles can occupy the cone's aperture, we need to calculate (or rather quickly estimate, since cone tracing makes a lot of approximations anyway) the relative area of the circle that is covered by the triangle. Afterwards, the individual contributions are weighted and summed up.&#xD;&#xA;&#xD;&#xA;The author, unfortunately, does not give a lot of detail about his solution. Here is what he writes on cone-plane intersections:&#xD;&#xA;&#xD;&#xA;&gt; The spread angle and the angle between the ray and plane computed&#xD;&#xA;&gt; above together indicate how the distance between the center of the&#xD;&#xA;&gt; circle and the edge of the half plane [sic]. Given this distance, the area&#xD;&#xA;&gt; of intersection is computed using a polynomial approximation. This&#xD;&#xA;&gt; completes the intersection calculation for planes.&#xD;&#xA;&#xD;&#xA;And then, after projecting a polygon to the plane perpendicular to the&#xD;&#xA;direction vector of the cone:&#xD;&#xA;&#xD;&#xA;&gt; We then must calculate the intersection between the projected polygon&#xD;&#xA;&gt; and a circle. This can be accomplished by calculating the distance&#xD;&#xA;&gt; from the center of the circle to each of the edges and then using the&#xD;&#xA;&gt; circle - half plane intersection estimation mentioned earlier.&#xD;&#xA;&#xD;&#xA;I found [a solution to the problem][2] over at StackExchange. I have ported the code from [NowIGetToLearnWhatAHeadIs' answer][3], and it works fine, but seems pretty complicated to me. I am working with Compute Shaders, so branching is a bad thing, and the solutions rely heavily on it.&#xD;&#xA;&#xD;&#xA; 1. What is this *polynomial approximation* that Amanatides talks about, and how is it to be applied to polygons (espc. triangles)?&#xD;&#xA; 2. Is there any approximation to the problem that will give resonably accurate results (say ±10%) at considerable performance / code simplicity gains?&#xD;&#xA; 3. Working with GPUs, I am interested in an optimized solution that uses min/max over branching, for example. Maybe something like this already exists. Any luck?&#xD;&#xA;&#xD;&#xA;  [1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.32.6170&amp;rep=rep1&amp;type=pdf&#xD;&#xA;  [2]: https://stackoverflow.com/questions/540014/compute-the-area-of-intersection-between-a-circle-and-a-triangle&#xD;&#xA;  [3]: https://stackoverflow.com/a/22420313/776142" ContentLicense="CC BY-SA 3.0" />
  <row Id="13800" PostHistoryTypeId="5" PostId="4151" RevisionGUID="49ef55eb-5fba-4eb2-9b57-45fde1f2ff22" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I have [a WebGL circuit simulator](http://algorithmicassertions.com/quirk). One of the problems it has is that, due to using quite a lot of intermediate float textures as it simulates, it doesn't work on various mobile devices. They only support byte textures.&#xD;&#xA;&#xD;&#xA;My intended solution to this problem is to encode the high-precision (i.e. 32-bit) floats as bytes. Every output float is packed into a nearly-IEEE format (I put the sign bit at the other end to avoid a few shifts, I don't do denormalized values, and I don't do infinities/NaNs). Similarly, every input is unpacked before being used.&#xD;&#xA;&#xD;&#xA;I have found various blog posts and answers related to this task out on the internet ([example 1](http://www.ozone3d.net/blogs/lab/20080604/glsl-float-to-rgba8-encoder/), [example 2](https://stackoverflow.com/questions/28159591/how-to-pack4bytes-and-unpackvec4-between-c-and-glsl), [example 3](https://gist.github.com/Flexi23/1713774)), but I haven't found any that work properly on all finite non-denormalized floats.&#xD;&#xA;&#xD;&#xA;The problem I'm running into is precision. I want to round trip the floats **without introducing any error**, but I can't seem to make a shader that preserves all 23 bits of the mantissa. There always seems to be some rounding on some machine that loses the last bit, though I can perturb the cases where the rounding happens and it happens differently on the various machines I've tested on.&#xD;&#xA;&#xD;&#xA;Here is my packing method:&#xD;&#xA;&#xD;&#xA;    vec4 packFloatIntoBytes(float val) {&#xD;&#xA;        if (val == 0.0) {&#xD;&#xA;            return vec4(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float mag = abs(val);&#xD;&#xA;        float exponent = floor(log2(mag));&#xD;&#xA;        // Correct log2 approximation errors.&#xD;&#xA;        exponent += float(exp2(exponent) &lt;= mag / 2.0);&#xD;&#xA;        exponent -= float(exp2(exponent) &gt; mag);&#xD;&#xA;&#xD;&#xA;        float mantissa;&#xD;&#xA;        if (exponent &gt; 100.0) {&#xD;&#xA;            // Not sure why this needs to be done in two steps for the largest float to work.&#xD;&#xA;            // Best guess is the optimizer rewriting '/ exp2(e)' into '* exp2(-e)',&#xD;&#xA;            // but exp2(-128.0) is too small to represent.&#xD;&#xA;            mantissa = mag / 1024.0 / exp2(exponent - 10.0) - 1.0;&#xD;&#xA;        } else {&#xD;&#xA;            mantissa = mag / float(exp2(exponent)) - 1.0;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float a = exponent + 127.0;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float b = floor(mantissa);&#xD;&#xA;        mantissa -= b;&#xD;&#xA;        mantissa *= 256.0;&#xD;&#xA;        float c = floor(mantissa);&#xD;&#xA;        mantissa -= c;&#xD;&#xA;        mantissa *= 128.0;&#xD;&#xA;        float d = floor(mantissa) * 2.0 + float(val &lt; 0.0);&#xD;&#xA;        return vec4(a, b, c, d) / 255.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my unpacking method:&#xD;&#xA;&#xD;&#xA;    float unpackBytesIntoFloat(vec4 v) {&#xD;&#xA;        float a = floor(v.r * 255.0 + 0.5);&#xD;&#xA;        float b = floor(v.g * 255.0 + 0.5);&#xD;&#xA;        float c = floor(v.b * 255.0 + 0.5);&#xD;&#xA;        float d = floor(v.a * 255.0 + 0.5);&#xD;&#xA;&#xD;&#xA;        float exponent = a - 127.0;&#xD;&#xA;        float sign = 1.0 - mod(d, 2.0)*2.0;&#xD;&#xA;        float mantissa = float(a &gt; 0.0)&#xD;&#xA;                       + b / 256.0&#xD;&#xA;                       + c / 65536.0&#xD;&#xA;                       + floor(d / 2.0) / 8388608.0;&#xD;&#xA;        return sign * mantissa * exp2(exponent);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This method is close. It works on my laptop, as far as I can tell. But it doesn't work on my Nexus tablet. For example, the float `-0.20717763900756836` should be encoded as `[124, 168, 76, 193]`. When I unpack that then repack it on the Nexus tablet the output is one ulp lower: `[124, 168, 76, 191]` (which encodes `-0.2071776[5390872955]`). Close, but I want perfect.&#xD;&#xA;&#xD;&#xA;Mostly I'm at a loss trying to figure out where the precision is being destroyed in this method. Changes almost seem to have random effects, like replacing `x * exp2(n)` with `x / exp2(-n)` might fix an error in one place but introduce an error in another place.&#xD;&#xA;&#xD;&#xA;**Is there any *exact* way to pack floats into bytes, without losing precision?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Some example values that such a method should work on:&#xD;&#xA;&#xD;&#xA;    var testValues = new Float32Array([&#xD;&#xA;        0,&#xD;&#xA;        0.5,&#xD;&#xA;        1,&#xD;&#xA;        2,&#xD;&#xA;        -1,&#xD;&#xA;        1.1,&#xD;&#xA;        42,&#xD;&#xA;        16777215,&#xD;&#xA;        16777216,&#xD;&#xA;        16777218,&#xD;&#xA;        0.9999999403953552, // An ulp below 1.&#xD;&#xA;        1.0000001192092896, // An ulp above 1.&#xD;&#xA;        Math.pow(2.0, -126), // Smallest non-denormalized 32-bit float.&#xD;&#xA;        0.9999999403953552 * Math.pow(2.0, 128), // Largest finite 32-bit float.&#xD;&#xA;        Math.PI,&#xD;&#xA;        Math.E&#xD;&#xA;    ]);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13801" PostHistoryTypeId="5" PostId="4184" RevisionGUID="bd88f020-5005-429f-80e2-28ff055a8b19" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="This is related to [question on SO](https://stackoverflow.com/questions/40268554/texture-coordinates-for-part-of-model) *(but the purpose of this question is different)*.&#xD;&#xA;&#xD;&#xA;I have model with *UVs* (3DS max UVW editor screenshot)&#xD;&#xA;&#xD;&#xA;[![3dsmax uvws editor screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;I have grouped some unused parts of *UVs* on the top right corner. *Bump map* is 512x512 (large enough), so Id like to decrease its dimensions if possible (e.g. tile a texture of smaller size). Currently I am using only *bump map* for the top part of the object and this solution is enough for now, but I want to improve it.&#xD;&#xA;&#xD;&#xA;I am asking for advice:&#xD;&#xA;&#xD;&#xA; - How to optimize this *UVs* mapping to be more universal and applicable for future usage (best practice/article/advice/example/other, leading to right direction)?&#xD;&#xA; - What steps and techniques I will need to do to use multiple *UVs* for single object (I would like make each texture obtain all avalable space)?&#xD;&#xA;&#xD;&#xA;P.S. For the second question:&#xD;&#xA;&#xD;&#xA;Imagine a cube with image of &quot;sun&quot; on left side, bump map on right side and another combinations of textures on rest sides. Then (in case of single UV) UVs would be divided into 9 parts (6 for each side and 3 unused free space) and each texture (for example image of &quot;sun&quot;) can obtain only a part of texture space and the rest space - empty. Greater dimensions of each texture is needed to get better result. &#xD;&#xA;&#xD;&#xA;So, I am looking for a way to do like so (make each texture use max avalable space):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zOJrI.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/iOkhI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13803" PostHistoryTypeId="5" PostId="4503" RevisionGUID="00232844-dda9-462c-a5bf-bc56a5514191" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I'm having some trouble trying to figure out how to go from a coordinate on the screen, to 3D world coordinates on a plane.&#xD;&#xA;&#xD;&#xA;My case is as seen on the picture further down. World origin is in the center with the grid representing the X-Y plane.  &#xD;&#xA;I want to be able to click/touch on the screen, and transform the screen coordinates to the correct 3D world coordinates on the X-Y plane.&#xD;&#xA;&#xD;&#xA;I first tried to figure out the maths myself by simple geometry, but got stuck...  &#xD;&#xA;I then tried the function `glm::unProject()` after checking out [this post].&#xD;&#xA;&#xD;&#xA;The screen has dimensions `mWindowWidth` and `mWindowHeight`.  &#xD;&#xA;`x`, `y` are the screen coordinates where origin is in the top left corner. Positive x to the right, positive y down.&#xD;&#xA;&#xD;&#xA;`projM` is the projection matrix.&#xD;&#xA;&#xD;&#xA;Third parameter is the model matrix, which I believe in my case only needs to be an identity matrix.&#xD;&#xA;&#xD;&#xA;I get the world coordinates X and Y (Z is already known as it is on the plane) by using these parameters in `glm::unProject`:&#xD;&#xA;&#xD;&#xA;    glm::vec3 posVec = glm::unProject(&#xD;&#xA;       glm::vec3(x, float(mWindowHeight) - y, 1.0f), &#xD;&#xA;       glm::mat4(1.0f), &#xD;&#xA;       projM, &#xD;&#xA;       glm::vec4(0.0f, 0.0f, float(mWindowWidth), float(mWindowHeight))&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;What happens is that if I have screen coordinates near world origin, the world coordinates seems correct. But If I use screen coordinates near the edges and corners of the screen, I get a certain offset (see image below).&#xD;&#xA;&#xD;&#xA;Where is this offset coming from, and what am I misunderstanding?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [this post]: https://stackoverflow.com/questions/9901453/using-glms-unproject&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;As mentioned in the comments, the second parameter should be the &quot;model-view&quot; matrix. I tried to switch `glm::mat4(1.0f)` with `viewM` (view matrix). The effect is still the same, if not with even more offset.&#xD;&#xA;&#xD;&#xA;I also tried to get the `z` buffer depth value by using:&#xD;&#xA;(Got it from this [tutorial][2])&#xD;&#xA;&#xD;&#xA;    float z;&#xD;&#xA;    glReadPixels(int(x), int(mWindowHeight) - int(y), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &amp;z);&#xD;&#xA;&#xD;&#xA;This results in very small values of X and Y world coordinates, and essentially where ever I touch, the resulting coordinates are near the origin.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gc5Mu.png&#xD;&#xA;  [2]: http://nehe.gamedev.net/article/using_gluunproject/16013/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13804" PostHistoryTypeId="5" PostId="4562" RevisionGUID="1612acef-a61b-4b52-ba62-a44f30fc9f58" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I am pretty confused about that function. [GLFW Context reference][1] says as follow:&lt;br&gt;&#xD;&#xA;&#xD;&#xA;&gt; This function makes the OpenGL or OpenGL ES context of the specified&#xD;&#xA;&gt; window current on the calling thread. A context can only be made&#xD;&#xA;&gt; current on a single thread at a time and each thread can have only a&#xD;&#xA;&gt; single current context at a time.&#xD;&#xA;&#xD;&#xA;But it does not help me much.&lt;br /&gt;&#xD;&#xA;Can it work like [`glBind-`][2] methods? (glBindBuffer, glBindVertexArray and so on)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glfw.org/docs/latest/group__context.html#ga1c04dc242268f827290fe40aa1c91157&#xD;&#xA;  [2]: https://stackoverflow.com/q/9758884/5744858" ContentLicense="CC BY-SA 3.0" />
  <row Id="13805" PostHistoryTypeId="5" PostId="4565" RevisionGUID="e1b604d6-1557-4dc4-9388-842664475d1d" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I need to write a function (in Javascript) that accepts the endpoints of a line segment and an additional point and returns coordinates for the point relative to the start point. So, based on this picture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1,y1, x2,y2, xp,yp)&#xD;&#xA;&#xD;&#xA;returns `[xp',yp']` where xp' is the distance from (xp,yp) along a line perpendicular to the line segment, and yp' is the distance from (x1,y1) to the point where that perpendicular line intersects the line segment.&#xD;&#xA;&#xD;&#xA;What I've tried so far:&#xD;&#xA;&#xD;&#xA;    function rotateRad(cx, cy, x, y, radians) {&#xD;&#xA;        var cos = Math.cos(radians),&#xD;&#xA;            sin = Math.sin(radians),&#xD;&#xA;            nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,&#xD;&#xA;            ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;&#xD;&#xA;        return [nx, ny];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [xp', yp'] = rotateRad(x1,y1, xp, yp, Math.atan2(y2-y1,x2-x1));&#xD;&#xA;&#xD;&#xA;I don't really understand the function; got it from https://stackoverflow.com/a/17411276/1368860&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TESQW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13806" PostHistoryTypeId="5" PostId="4577" RevisionGUID="abb0a5e9-2729-4c94-b0d7-83d32becfda6" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I got a good answer on StackOverflow: https://stackoverflow.com/questions/41701713/translate-coordinates-relative-to-line-segment/41702475#41702475 from https://stackoverflow.com/users/1579780/giladd:&#xD;&#xA;&#xD;&#xA;    function perpendicular_coords(x1, y1, x2, y2, xp, yp) {&#xD;&#xA;      var dx = x2 - x1,&#xD;&#xA;          dy = y2 - y1;&#xD;&#xA;    &#xD;&#xA;      //find intersection point    &#xD;&#xA;      var k = (dy * (xp-x1) - dx * (yp-y1)) / (dy*dy + dx*dx);&#xD;&#xA;      var x4 = xp - k * dy;&#xD;&#xA;      var y4 = yp + k * dx;&#xD;&#xA;    &#xD;&#xA;      var ypt = Math.sqrt((y4-y1)*(y4-y1)+(x4-x1)*(x4-x1));&#xD;&#xA;      var xpt = distance(x1, y1, x2, y2, xp, yp);&#xD;&#xA;      return [xpt, ypt];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Distance of point from line&#xD;&#xA;    function distance(x1, y1, x2, y2, xp, yp) {&#xD;&#xA;      var dx = x2 - x1;&#xD;&#xA;      var dy = y2 - y1;&#xD;&#xA;    &#xD;&#xA;      return Math.abs(dy*xp - dx*yp + x2*y1 - y2*x1) / Math.sqrt(dy*dy + dx*dx);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="13807" PostHistoryTypeId="5" PostId="4596" RevisionGUID="25bcf2b5-3a1d-4fe7-ab9a-72bec1792f0e" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="**EDIT:** This is a duplicate of a question from stack overflow:&#xD;&#xA;https://stackoverflow.com/questions/9222217/how-does-the-fragment-shader-know-what-variable-to-use-for-the-color-of-a-pixel&#xD;&#xA;&#xD;&#xA;If you want to send a value from vertex shader to fragment shader, the vertex shader should declare one variable as `out`, the fragment shader should declare other variable as `in` and both variables must have their names and types equal. But this doesn't happen when you want to send the color value from the fragment shader. In fact, you can call the output variable as you want. Why? In older version there was one variable called `gl_FragColor`&lt;br /&gt;&#xD;&#xA;How the program links your output fragment variable with gl_FragColor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13809" PostHistoryTypeId="5" PostId="4718" RevisionGUID="e5c4bd1b-a01a-42cd-8125-24c9898365f7" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I'm using GLSL 4.0 to write a subdivision routine that divides the triangles on an object through a geometry shader. I'm not using barycentric co-ordinates but vector arithmetic to output the triangle vertices. I managed to get the subdivision working but I don't understand how to interpolate the vertex normals to produce the correct shading:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 400 &#xD;&#xA;    &#xD;&#xA;    layout(triangles) in;&#xD;&#xA;    layout(triangle_strip, max_vertices = 93) out; //MAX 128&#xD;&#xA;    &#xD;&#xA;    uniform mat4 mvMatrix;&#xD;&#xA;    uniform mat4 pMatrix;&#xD;&#xA;    uniform mat3 normalMatrix; //mv matrix without translation&#xD;&#xA;    uniform int subdivision_level;&#xD;&#xA;    uniform vec4 lightPosition_camSpace; //light Position in camera space&#xD;&#xA;    &#xD;&#xA;    uniform int time;&#xD;&#xA;    &#xD;&#xA;    in data&#xD;&#xA;    {&#xD;&#xA;      vec4 position_camSpace;&#xD;&#xA;      vec3 normal_camSpace;&#xD;&#xA;      vec2 textureCoordinate;&#xD;&#xA;      vec4 color;&#xD;&#xA;    }vertexIn[3];&#xD;&#xA;    &#xD;&#xA;    out fragmentData&#xD;&#xA;    {&#xD;&#xA;      vec4 position_camSpace;&#xD;&#xA;      vec3 normal_camSpace;&#xD;&#xA;      vec2 textureCoordinate;&#xD;&#xA;      vec4 color;&#xD;&#xA;    } frag;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void emit_triangle(vec4 position, vec4 width, vec4 hyp, float s) {&#xD;&#xA;    	&#xD;&#xA;    	/* NORMALS NOT FIXED */&#xD;&#xA;    &#xD;&#xA;        //A&#xD;&#xA;        gl_Position = position;&#xD;&#xA;        frag.color = vertexIn[0].color;&#xD;&#xA;    	frag.position_camSpace = vertexIn[0].position_camSpace;&#xD;&#xA;        frag.normal_camSpace = vertexIn[0].normal_camSpace;&#xD;&#xA;        frag.textureCoordinate = vertexIn[0].textureCoordinate;&#xD;&#xA;        EmitVertex();&#xD;&#xA;        &#xD;&#xA;        //B&#xD;&#xA;        gl_Position = position + width;&#xD;&#xA;    	frag.color = vertexIn[1].color;&#xD;&#xA;    	frag.position_camSpace = vertexIn[1].position_camSpace;&#xD;&#xA;        frag.normal_camSpace = vertexIn[1].normal_camSpace;&#xD;&#xA;        frag.textureCoordinate = vertexIn[1].textureCoordinate;&#xD;&#xA;    &#xD;&#xA;        EmitVertex();&#xD;&#xA;        &#xD;&#xA;        //C&#xD;&#xA;    	gl_Position = position + hyp;&#xD;&#xA;    	frag.color = vertexIn[2].color;&#xD;&#xA;    	frag.position_camSpace = vertexIn[2].position_camSpace;&#xD;&#xA;        frag.normal_camSpace = vertexIn[2].normal_camSpace;&#xD;&#xA;        frag.textureCoordinate = vertexIn[2].textureCoordinate;&#xD;&#xA;    &#xD;&#xA;        EmitVertex();&#xD;&#xA;    &#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;      // A gl_In[0].gl_Position;&#xD;&#xA;      // B gl_In[1].gl_Position;&#xD;&#xA;      // C gl_In[2].gl_Position;&#xD;&#xA;                &#xD;&#xA;      float s = 1/pow(2,subdivision_level);&#xD;&#xA;      int triangles_render = int(1/s);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      vec4 hyp_off = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;      vec4 width_off = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;    &#xD;&#xA;      vec4 position = gl_in[0].gl_Position;&#xD;&#xA;      vec4 width = s*(gl_in[1].gl_Position - gl_in[0].gl_Position);&#xD;&#xA;      vec4 hyp = s*(gl_in[2].gl_Position - gl_in[0].gl_Position);&#xD;&#xA;    &#xD;&#xA;      vec4 hyp_off_f = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;      vec4 width_off_f = width;&#xD;&#xA;      &#xD;&#xA;    &#xD;&#xA;      for (int i=0; i&lt;=subdivision_level+1; i++) {&#xD;&#xA;        for (int j=0; j&lt;triangles_render-i; j++) {&#xD;&#xA;    &#xD;&#xA;    	  // Normal triangle&#xD;&#xA;          emit_triangle(position + hyp_off + width_off, width, hyp,s);&#xD;&#xA;    	  width_off += width;  &#xD;&#xA;    &#xD;&#xA;          // Flipped triangle&#xD;&#xA;          if (j &lt;triangles_render-i-1)&#xD;&#xA;          {&#xD;&#xA;    	    emit_triangle(position + width_off_f + hyp_off_f, hyp, hyp - width,s);&#xD;&#xA;            width_off_f += width;&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;        hyp_off += hyp;&#xD;&#xA;        width_off = vec4(0.0,0.0,0.0,0.0);&#xD;&#xA;    &#xD;&#xA;    	hyp_off_f += hyp;&#xD;&#xA;        width_off_f = width;&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Currently the result looks like flat shading because I just use the normals of the vertices from the vertex shader. How do I compute the correct normals so that the shading looks correct? Also do I need to modify the vertex position too? I'm unsure about this part. I've read &#xD;&#xA;https://stackoverflow.com/questions/4703432/why-does-my-opengl-phong-shader-behave-like-a-flat-shader But they use barycentric co-ordinates for the solution." ContentLicense="CC BY-SA 3.0" />
  <row Id="13810" PostHistoryTypeId="5" PostId="4761" RevisionGUID="b0bd404b-c9ee-41ca-a8b7-cc72f939d679" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I often use a 2D Perlin noise texture to displace a grid in the vertex shader (e.g. terrain, ocean).  However, every time I google the method to calculate post-displacement normals there is a slight difference.  For example, the value to place in the Y-component varies depending on the source.  In this example, they place a '1' in the Y-component prior to normalization:&#xD;&#xA;&#xD;&#xA;https://software.intel.com/en-us/articles/real-time-parametric-shallow-wave-simulation&#xD;&#xA;&#xD;&#xA;Whereas in these codes, the value '2' is chosen:&#xD;&#xA;&#xD;&#xA;http://www.dian-xiang.com/blog/2&#xD;&#xA;&#xD;&#xA;What gives?  Is there a definitive source for calculating normals from a height map?  &#xD;&#xA;&#xD;&#xA;Might this be related to unprojecting mouse clicks?  It always bothered me that you could throw a '0.5' in the Z-component, as mrdoob mentioned here:&#xD;&#xA;&#xD;&#xA;https://stackoverflow.com/questions/11036106/three-js-projector-and-ray-objects&#xD;&#xA;&#xD;&#xA;Or use a '1' in the Z-component as Anton does here:&#xD;&#xA;&#xD;&#xA;http://antongerdelan.net/opengl/raycasting.html&#xD;&#xA;&#xD;&#xA;Is there a connection between calculating normals from height maps and unprojecting mouse clicks?&#xD;&#xA;&#xD;&#xA;The second part of my question concerns choosing an epsilon to sample the height map.  Before I learned about height maps, I read about getting the normal from an implicit surface as in this link:&#xD;&#xA;&#xD;&#xA;http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm&#xD;&#xA;&#xD;&#xA;It seems like the epsilon number is just made up though.  In my projects, I typically just fudge the value until it looks good.  Is there a definitive source, or at least a good rule of thumb?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13811" PostHistoryTypeId="5" PostId="4765" RevisionGUID="93a55716-f471-4b2d-8beb-1af9bee61ff9" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I've generalized Everitt's results if that's needed.&#xD;&#xA;&#xD;&#xA;[![generalized common frustum][1]][1]&#xD;&#xA;&#xD;&#xA;As a bonus, a way to extract left0/right0 from the eyes perspective matrices:&#xD;&#xA;&#xD;&#xA;    left0   = n0 * (Mle13 - 1) / Mle11;&#xD;&#xA;    right1  = n1 * (Mre13 + 1) / Mre11;&#xD;&#xA;If you have row major. transpose for column major. c.f. [this answer][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VyA1o.png&#xD;&#xA;  [2]: https://stackoverflow.com/a/12926655/893406" ContentLicense="CC BY-SA 3.0" />
  <row Id="13812" PostHistoryTypeId="5" PostId="4832" RevisionGUID="b855eeee-7e5a-4c33-902a-57a5537396a3" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I'm trying to calculate camera paramters and a hand eye calibration (Transformation from camera to eye (display) coordinates) for rendering on a see-through HMD.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have already calculated a Projection matrix P (using SPAAM) which transforms points in the camera coordinate system to the screen (Tested by custom rendering).&#xD;&#xA;&#xD;&#xA;Cause of the used framework (metaio) I can't set the projection matrix directly  but have to separately set the camera parameters and Hand Eye calibration for rendering.&#xD;&#xA;&#xD;&#xA;Therefore I have extracted the extrinsic (E) and intrinsic (I) camera parameters from the Projection matrix P.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But those are not working correctly when set. The result seems to be not completely off, cause the rendered scale seems to be correct.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I guess I'm missing some additional step I'm not aware of or the extrinsics are not the hand-eye-calibration I'm looking for.&#xD;&#xA;&#xD;&#xA;I appreciate any ideas and help.&#xD;&#xA;&#xD;&#xA;Additional information:&#xD;&#xA;&#xD;&#xA; - right handed coordinate system with camera looking in negative z axsis, x to the right and y up&#xD;&#xA; - Since The translation part of HEC on the x- axis has to be positive (known from working configs) (camera is on the right side of the HMD) I assume it's transformation is specified from eye to camera?&#xD;&#xA;&#xD;&#xA;PS: Before I realized this stackexchange exist, I have already asked the question [here][2]. I got unfortunately no feedback so far.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WKalf.png&#xD;&#xA;  [2]: https://stackoverflow.com/questions/42623966/calculate-camera-parameters-and-handeyecalibration" ContentLicense="CC BY-SA 3.0" />
  <row Id="13813" PostHistoryTypeId="5" PostId="4841" RevisionGUID="ce09d51e-2d9e-4eef-98fb-60b81aeabca5" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="One way you could do it is by writing the dimensions as a fraction, and simplifying that fraction (dividing each of the numbers by their greatest common denominator). From that you can then create a string and format it as [simplified numerator]:[simplified denominator].&#xA;&#xA;[This SO question][1] talks about this too, and it shows some code to implementing it in JavaScript and also suggests some libraries... although I don't know what language you're using, I think this will still help.&#xA;&#xA;&#xA;  [1]: https://stackoverflow.com/questions/4652468/is-there-a-javascript-function-that-reduces-a-fraction" ContentLicense="CC BY-SA 3.0" />
  <row Id="13814" PostHistoryTypeId="5" PostId="4972" RevisionGUID="1badbf83-a081-4fdb-b340-abf82c2093a5" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="I'm confused by the `Waves` class [implementation](https://github.com/utilForever/DirectX/blob/master/DirectX%2011/Frank%20D.%20Luna/Common/Waves.cpp#L55) in the source code of the book *Introduction to 3D Game Programming with DirecX11*:&#xD;&#xA;&#xD;&#xA;    float d = damping*dt+2.0f;&#xD;&#xA;    float e = (speed*speed)*(dt*dt)/(dx*dx);&#xD;&#xA;    mK1     = (damping*dt-2.0f)/ d;&#xD;&#xA;    mK2     = (4.0f-8.0f*e) / d;&#xD;&#xA;    mK3     = (2.0f*e) / d;&#xD;&#xA;&#xD;&#xA;What do the parameters mean? How are the waves generated? I've tried searching waves implementation and found https://stackoverflow.com/questions/6716887/how-to-render-ocean-wave-using-opengl-in-3d , I looked up the links mentioned by the answer but I couldn't understand the complicated equations and it seems that the equations have no relation with the code above. I also tried searching &quot;spatially damped wave&quot;, and then I found https://physics.stackexchange.com/questions/223366/wave-equation-with-spatial-damping, that didn't help me, neither...&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13815" PostHistoryTypeId="5" PostId="4999" RevisionGUID="bf036718-1a5a-4d3e-b18a-e0965a5d73ba" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="In [this][1] question I asked how to implement a chain of blurs in one single step. &#xD;&#xA;&#xD;&#xA;Then I found out from the [gaussian blur][2] page of Wikipedia that:&#xD;&#xA;&#xD;&#xA;&gt; Applying multiple, successive gaussian blurs to an image has the same&#xD;&#xA;&gt; effect as applying a single, larger gaussian blur, whose radius is the&#xD;&#xA;&gt; square root of the sum of the squares of the blur radii that were&#xD;&#xA;&gt; actually applied. For example, applying successive gaussian blurs with&#xD;&#xA;&gt; radii of 6 and 8 gives the same results as applying a single gaussian&#xD;&#xA;&gt; blur of radius 10, since sqrt {6^{2}+8^{2}}=10.&#xD;&#xA;&#xD;&#xA;So I thought that `blur` and `singleBlur` were the same in the following code:&#xD;&#xA;&#xD;&#xA;    cv::Mat firstLevel;&#xD;&#xA;    float sigma1, sigma2;&#xD;&#xA;    //intialize firstLevel, sigma1 and sigma2&#xD;&#xA;    cv::Mat blur = gaussianBlur(firstLevel, sigma1);&#xD;&#xA;            blur = gaussianBlur(blur, sigma2);&#xD;&#xA;    float singleSigma = std::sqrt(std::pow(sigma1,2)+std::pow(sigma2,2));&#xD;&#xA;    cv::Mat singleBlur = gaussianBlur(firstLevel, singleSigma);&#xD;&#xA;	cv::Mat diff = blur != singleBLur;&#xD;&#xA;	// Equal if no elements disagree&#xD;&#xA;	assert( cv::countNonZero(diff) == 0);&#xD;&#xA;&#xD;&#xA;But this `assert` fails (and actually, for example, the first row of `blur` is different from the first one of `singleBlur`).&#xD;&#xA;&#xD;&#xA;Why?&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;After different comments asking for more information, I'll update the answer. &#xD;&#xA;&#xD;&#xA;What I'm trying to do is to parallelize [this](https://github.com/perdoch/hesaff) code. In particular, I'm focusing now on computing all the blurs at all levels in advance. The serial code (**which works correctly**) is the following:&#xD;&#xA;&#xD;&#xA;       vector&lt;Mat&gt; blurs ((par.numberOfScales+3)*levels, Mat());&#xD;&#xA;       cv::Mat octaveLayer = firstLevel;&#xD;&#xA;       int scaleCycles = par.numberOfScales+2;&#xD;&#xA;&#xD;&#xA;       //compute blurs at all layers (not parallelizable)&#xD;&#xA;       for(int i=0; i&lt;levels; i++){&#xD;&#xA;    	   blurs[i*scaleCycles+1] = octaveLayer.clone();&#xD;&#xA;    	   for (int j = 1; j &lt; scaleCycles; j++){&#xD;&#xA;    		   float sigma = par.sigmas[j]* sqrt(sigmaStep * sigmaStep - 1.0f);&#xD;&#xA;    		   blurs[j+1+i*scaleCycles] = gaussianBlur(blurs[j+i*scaleCycles], sigma);&#xD;&#xA;    		   if(j == par.numberOfScales)&#xD;&#xA;    			   octaveLayer = halfImage(blurs[j+1+i*scaleCycles]);&#xD;&#xA;    	   }&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;I'm sorry for the horrible indexes above, but I tried to respect the original code system (which is horrible, like starting counting from `1` instead of `0`). The code above has `scaleCycles=5` and `levels=6`, so 30 blurs are generated in total.&#xD;&#xA;&#xD;&#xA;This is the &quot;single blur&quot; version, where first I compute the sigmas for each blur that has to be computed (following Wikipedia's formula) and then I apply the blur (notice that this is still serial and not parallelizable):&#xD;&#xA;&#xD;&#xA;       vector&lt;Mat&gt; singleBlurs ((par.numberOfScales+3)*levels, Mat());&#xD;&#xA;       vector&lt;float&gt; singleSigmas(scaleCycles);&#xD;&#xA;       float acc = 0;&#xD;&#xA;       for (int j = 1; j &lt; scaleCycles; j++){&#xD;&#xA;    	   float sigma = par.sigmas[j]* sqrt(sigmaStep * sigmaStep - 1.0f);&#xD;&#xA;    	   acc += pow(sigma, 2);&#xD;&#xA;    	   singleSigmas[j] = sqrt(acc);&#xD;&#xA;       }&#xD;&#xA;    &#xD;&#xA;       octaveLayer = firstLevel;&#xD;&#xA;       for(int i=0; i&lt;levels; i++){&#xD;&#xA;    	   singleBlurs[i*scaleCycles+1] = octaveLayer.clone();&#xD;&#xA;    	   for (int j = 1; j &lt; scaleCycles; j++){&#xD;&#xA;    		   float sigma = singleSigmas[j];&#xD;&#xA;    		   std::cout&lt;&lt;&quot;j=&quot;&lt;&lt;j&lt;&lt;&quot; sigma=&quot;&lt;&lt;sigma&lt;&lt;std::endl;&#xD;&#xA;    		   singleBlurs[j+1+i*scaleCycles] = gaussianBlur(singleBlurs[j+i*scaleCycles], sigma);&#xD;&#xA;    		   if(j == par.numberOfScales)&#xD;&#xA;    			   octaveLayer = halfImage(singleBlurs[j+1+i*scaleCycles]);&#xD;&#xA;    	   }&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;Of course the code above generates 30 blurs also with the same parameters of the previous version.&#xD;&#xA;&#xD;&#xA;And then this is the code to see the difference between each `signgleBlurs` and `blurs`:&#xD;&#xA;&#xD;&#xA;       assert(blurs.size() == singleBlurs.size());&#xD;&#xA;       vector&lt;Mat&gt; blurDiffs(blurs.size());&#xD;&#xA;       for(int i=1; i&lt;levels*scaleCycles; i++){&#xD;&#xA;    	    cv::Mat diff;&#xD;&#xA;    	    absdiff(blurs[i], singleBlurs[i], diff);&#xD;&#xA;    		std::cout&lt;&lt;&quot;i=&quot;&lt;&lt;i&lt;&lt;&quot;diff rows=&quot;&lt;&lt;diff.rows&lt;&lt;&quot; cols=&quot;&lt;&lt;diff.cols&lt;&lt;std::endl;&#xD;&#xA;    		blurDiffs[i] = diff;&#xD;&#xA;    		std::cout&lt;&lt;&quot;blurs rows=&quot;&lt;&lt;blurs[i].rows&lt;&lt;&quot; cols=&quot;&lt;&lt;blurs[i].cols&lt;&lt;std::endl;&#xD;&#xA;    		std::cout&lt;&lt;&quot;singleBlurs rows=&quot;&lt;&lt;singleBlurs[i].rows&lt;&lt;&quot; cols=&quot;&lt;&lt;singleBlurs[i].cols&lt;&lt;std::endl;&#xD;&#xA;    		std::cout&lt;&lt;&quot;blurDiffs rows=&quot;&lt;&lt;blurDiffs[i].rows&lt;&lt;&quot; cols=&quot;&lt;&lt;blurDiffs[i].cols&lt;&lt;std::endl;&#xD;&#xA;    		namedWindow( &quot;blueDiffs[&quot;+std::to_string(i)+&quot;]&quot;, WINDOW_AUTOSIZE );// Create a window for display.&#xD;&#xA;    		//imshow( &quot;blueDiffs[&quot;+std::to_string(i)+&quot;]&quot;, blurDiffs[i] );                   // Show our image inside it.&#xD;&#xA;    		//waitKey(0);                                          // Wait for a keystroke in the window&#xD;&#xA;    		Mat imageF_8UC3;&#xD;&#xA;    		std::cout&lt;&lt;&quot;converting...&quot;&lt;&lt;std::endl;&#xD;&#xA;    		blurDiffs[i].convertTo(imageF_8UC3, CV_8U, 255);&#xD;&#xA;    		std::cout&lt;&lt;&quot;converted&quot;&lt;&lt;std::endl;&#xD;&#xA;    		imwrite( &quot;blurDiffs_&quot;+std::to_string(i)+&quot;.jpg&quot;, imageF_8UC3);&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;Now, what I've seen is that `blurDiffs_1.jpg` and `blurDiffs_2.jpg` are black, but suddendly from `blurDiffs_3.jpg` until the `blurDiffs_29.jpg` becomes whiter and whiter. For some reason, `blurDiffs_30.jpg` is almost completely black.&#xD;&#xA;&#xD;&#xA;**The first (correct) version generates 1761 descriptors. The second  (uncorrect) version generates &gt;2.3k descriptors.**&#xD;&#xA;&#xD;&#xA;I can't post the `blurDiffs` matrices because (especially the first ones) are very big and post's space is limited. I'll post some samples. I'll not post `blurDiffs_1.jpg` and `blurDiffs_2.jpg` because they're totally blacks. Notice that because of `halfImage` the images become smaller and smaller (as expected).&#xD;&#xA;&#xD;&#xA;**blurDiffs_3.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**blurDiffs_6.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4] &#xD;&#xA;&#xD;&#xA;**blurDiffs_15.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**blurDiffs_29.jpg:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;**If you need any more details, please let me know**.&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/43163337/parallelize-chain-of-gaussian-blurs&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Gaussian_blur&#xD;&#xA;  [3]: https://i.stack.imgur.com/e0xLz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/58ciq.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/yv8kd.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/EeoDd.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13816" PostHistoryTypeId="5" PostId="5074" RevisionGUID="7e27f895-716d-4b55-b761-b353421a9cc4" CreationDate="2017-05-23T12:39:19.850" UserId="-1" Comment="replaced http://stackoverflow.com/ with https://stackoverflow.com/" Text="For 2 bezier curves to connect and be continuous at all, the last control point of the first curve (C in your case) must be the same as the first control point of the next curve (D). So c3 has to equal d0. That gives you [C0 continuity](https://en.wikipedia.org/wiki/Smoothness) or positional continuity.&#xD;&#xA;&#xD;&#xA;The next step is to make sure that the tangents where the 2 curves meet are the same. That will ensure c1 continuity. (That is continuity of the first derivatives of the 2 curves.) To do this, the slope must be equal at both points. In order to do that, you need to ensure that the line from c2 to c3/d0 is continuous with the line from c3/d0 to d1.&#xD;&#xA;&#xD;&#xA;I don't know of a good way to describe C2 continuity, but this [Stack Overflow answer](https://stackoverflow.com/questions/12295773/joining-two-bézier-curves-smoothly-c2-continuous) describes it better than I could. That answer should also explain the calculation you need for your proof." ContentLicense="CC BY-SA 3.0" />
  <row Id="13817" PostHistoryTypeId="2" PostId="5144" RevisionGUID="7218994a-0ab9-4c38-925e-819884bc5e2f" CreationDate="2017-05-23T13:47:02.440" UserId="4978" Text="I read jos stam's code and book but I am still confused of the boundaries in the set_bnd function in the code. I don't know what kind of boundaries is this. Is it Neuman Boundary condition or dirchlet boundaries? " ContentLicense="CC BY-SA 3.0" />
  <row Id="13818" PostHistoryTypeId="1" PostId="5144" RevisionGUID="7218994a-0ab9-4c38-925e-819884bc5e2f" CreationDate="2017-05-23T13:47:02.440" UserId="4978" Text="Jos stam's stable fluids boundary conditions" ContentLicense="CC BY-SA 3.0" />
  <row Id="13819" PostHistoryTypeId="3" PostId="5144" RevisionGUID="7218994a-0ab9-4c38-925e-819884bc5e2f" CreationDate="2017-05-23T13:47:02.440" UserId="4978" Text="|c++|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13820" PostHistoryTypeId="5" PostId="5144" RevisionGUID="b18255a6-3968-4d52-a2b9-3bfb6aada7ec" CreationDate="2017-05-23T14:47:07.917" UserId="4978" Comment="added 89 characters in body" Text="I read jos stam's code and book but I am still confused of the boundaries in the set_bnd function in the code. I don't know what kind of boundaries is this. Is it Neuman Boundary condition or dirchlet boundaries? &#xA;&#xA;&#xA;This is the paper &#xA;&#xA;http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13822" PostHistoryTypeId="5" PostId="5144" RevisionGUID="2da4a0f8-5a1a-4a49-939e-4bff688402b9" CreationDate="2017-05-23T15:05:18.863" UserId="4978" Comment="added 103 characters in body" Text="I read jos stam's code and book but I am still confused of the boundaries in the set_bnd function in the code. I don't know what kind of boundaries is this. Is it Neuman Boundary condition or dirchlet boundaries? &#xA;&#xA;&#xA;This is the paper &#xA;&#xA;http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf&#xA;&#xA;This is the code&#xA;&#xA;https://www.autodeskresearch.com/sites/default/files/TheArtOfFluidAnimationCode.zip" ContentLicense="CC BY-SA 3.0" />
  <row Id="13823" PostHistoryTypeId="5" PostId="5144" RevisionGUID="05d8b7e8-3d94-4820-8b24-cb06acb6c677" CreationDate="2017-05-23T15:08:37.217" UserId="48" Comment="put the code in the post" Text="In the paper [Stable Fluids](http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf) by Jos Stam, I am confused about the boundaries in the set_bnd function in the code. I don't know what kind of boundaries is this. Is it Neumann boundary condition or Dirichlet boundaries? &#xD;&#xA;&#xD;&#xA;Here is the `set_bnd` function; the full code can be found [here](https://www.autodeskresearch.com/sites/default/files/TheArtOfFluidAnimationCode.zip).&#xD;&#xA;&#xD;&#xA;	void set_bnd ( int N, int b, float * x )&#xD;&#xA;	{&#xD;&#xA;		int i;&#xD;&#xA;&#xD;&#xA;		for ( i=1 ; i&lt;=N ; i++ ) {&#xD;&#xA;			x[IX(0  ,i)] = b==1 ? -x[IX(1,i)] : x[IX(1,i)];&#xD;&#xA;			x[IX(N+1,i)] = b==1 ? -x[IX(N,i)] : x[IX(N,i)];&#xD;&#xA;			x[IX(i,0  )] = b==2 ? -x[IX(i,1)] : x[IX(i,1)];&#xD;&#xA;			x[IX(i,N+1)] = b==2 ? -x[IX(i,N)] : x[IX(i,N)];&#xD;&#xA;		}&#xD;&#xA;		x[IX(0  ,0  )] = 0.5f*(x[IX(1,0  )]+x[IX(0  ,1)]);&#xD;&#xA;		x[IX(0  ,N+1)] = 0.5f*(x[IX(1,N+1)]+x[IX(0  ,N)]);&#xD;&#xA;		x[IX(N+1,0  )] = 0.5f*(x[IX(N,0  )]+x[IX(N+1,1)]);&#xD;&#xA;		x[IX(N+1,N+1)] = 0.5f*(x[IX(N,N+1)]+x[IX(N+1,N)]);&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13824" PostHistoryTypeId="4" PostId="5144" RevisionGUID="05d8b7e8-3d94-4820-8b24-cb06acb6c677" CreationDate="2017-05-23T15:08:37.217" UserId="48" Comment="put the code in the post" Text="Jos Stam's &quot;Stable Fluids&quot; boundary conditions" ContentLicense="CC BY-SA 3.0" />
  <row Id="13825" PostHistoryTypeId="5" PostId="4879" RevisionGUID="bd603b3b-048c-4b3e-98e4-4941fed912b8" CreationDate="2017-05-23T15:13:59.847" UserId="48" Comment="link to the exact function in the file" Text="The [book][1] omitted the explanation of [the constructor of hyperboloid][2].&#xD;&#xA;&#xD;&#xA;Could someone give some explanations about:&#xD;&#xA;&#xD;&#xA; 1. Why the arguments are two points?&#xD;&#xA; 2. What are the meanings of ***ah*** and ***ch***?&#xD;&#xA; 3. Why is there a while loop?&#xD;&#xA;&#xD;&#xA;  [1]: http://pbrt.org/&#xD;&#xA;  [2]: https://github.com/mmp/pbrt-v3/blob/master/src/shapes/hyperboloid.cpp#L43" ContentLicense="CC BY-SA 3.0" />
  <row Id="13827" PostHistoryTypeId="2" PostId="5146" RevisionGUID="eb01612a-3513-48b5-bde9-361501f5ab6a" CreationDate="2017-05-23T16:24:39.233" UserId="6688" Text="I implemented cascaded shadow maps, where shadow maps for each cascade is rendered to one canvas:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The light projections for each cascade are calculated from the bounding spheres of camera sub-frustums:[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code for calculation visibility value:&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; 3; i++) {&#xD;&#xA;		v_shadowCoord[i] = u_lightVPshifted[i] * vec4(a_WolrdPosition, 1);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	highp float zTocompare = v_shadowCoord[iCascade].z - bias;&#xD;&#xA;	return texture(u_shadowMap, vec3(v_shadowCoord[iCascade].xy, zTocompare));&#xD;&#xA;&#xD;&#xA;where `v_shadowCoord` for first cascade are in `(0, 1), (0, 0.33)` ranges, for second `(0, 1), (0.33, 0.66)`, third `(0, 1), (0.66, 1)`.&#xD;&#xA;&#xD;&#xA;**The problem** is that I get seams between cascades when anisotropic filtering is enabled. Here is the explanation of problem and suggested fix at the bottom of the page: [link][3]&#xD;&#xA;&#xD;&#xA;As I understand, for cascade borders the wrong mipmap is selected - the smallest. Because the textels for two neighboting vertices on scene come from different cascades and therefore screen-space derivetives are large. I tried the siggested fix from the site, still have same seam:&#xD;&#xA;&#xD;&#xA;	highp vec2 uv = v_shadowCoord[iCascade].xy;&#xD;&#xA;	highp vec2 dx = dFdx (uv) / u_cascadeScales[iCascade];&#xD;&#xA;	highp vec2 dy = dFdy (uv) / u_cascadeScales[iCascade];&#xD;&#xA;	highp float zTocompare = (v_shadowCoord[iCascade].z) - bias;&#xD;&#xA;	return textureGradOffset(u_shadowMap, vec3(uv,  zTocompare), dx, dy, ivec2(0, 0));&#xD;&#xA;&#xD;&#xA;I suppose I don't use the right input there. `v_shadowCoord` I described above, `u_cascadeScales` are scales of projection sizes in light view space relative to first one: I have `(1.0, 14.0, 300.0)`. Could you please explain how just scaling the derivatives will help selecting right mipmap and suggest what is wrong in the code? I expect that even with that scaling, values on the border will still be mapped to distant texels and wrong mimpap will be used.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3kRtI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XcPSK.png&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/ee416307(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="13828" PostHistoryTypeId="1" PostId="5146" RevisionGUID="eb01612a-3513-48b5-bde9-361501f5ab6a" CreationDate="2017-05-23T16:24:39.233" UserId="6688" Text="Cascaded shadow maps. Seams between cascades" ContentLicense="CC BY-SA 3.0" />
  <row Id="13829" PostHistoryTypeId="3" PostId="5146" RevisionGUID="eb01612a-3513-48b5-bde9-361501f5ab6a" CreationDate="2017-05-23T16:24:39.233" UserId="6688" Text="|opengl|shadow|shadow-mapping|mipmap|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13830" PostHistoryTypeId="5" PostId="5146" RevisionGUID="e0c56be0-4e77-4b3f-8271-ae027748ed5b" CreationDate="2017-05-23T16:39:21.827" UserId="213" Comment="fixed several typos " Text="I implemented cascaded shadow maps, where shadow maps for each cascade is rendered to one canvas:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The light projections for each cascade are calculated from the bounding spheres of camera sub-frustums:[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code for calculation visibility value:&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; 3; i++) {&#xD;&#xA;		v_shadowCoord[i] = u_lightVPshifted[i] * vec4(a_WolrdPosition, 1);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	highp float zTocompare = v_shadowCoord[iCascade].z - bias;&#xD;&#xA;	return texture(u_shadowMap, vec3(v_shadowCoord[iCascade].xy, zTocompare));&#xD;&#xA;&#xD;&#xA;where `v_shadowCoord` for first cascade are in `(0, 1), (0, 0.33)` ranges, for second `(0, 1), (0.33, 0.66)`, third `(0, 1), (0.66, 1)`.&#xD;&#xA;&#xD;&#xA;**The problem** is that I get seams between cascades when anisotropic filtering is enabled. Here is the explanation of problem and suggested fix at the bottom of the page: [link][3]&#xD;&#xA;&#xD;&#xA;As I understand, for cascade borders the wrong mipmap is selected - the smallest. Because the texels for two neighboring vertices on scene come from different cascades and therefore screen-space derivatives are large. I tried the suggested fix from the site, still have same seam:&#xD;&#xA;&#xD;&#xA;	highp vec2 uv = v_shadowCoord[iCascade].xy;&#xD;&#xA;	highp vec2 dx = dFdx (uv) / u_cascadeScales[iCascade];&#xD;&#xA;	highp vec2 dy = dFdy (uv) / u_cascadeScales[iCascade];&#xD;&#xA;	highp float zTocompare = (v_shadowCoord[iCascade].z) - bias;&#xD;&#xA;	return textureGradOffset(u_shadowMap, vec3(uv,  zTocompare), dx, dy, ivec2(0, 0));&#xD;&#xA;&#xD;&#xA;I suppose I don't use the right input there. `v_shadowCoord` I described above, `u_cascadeScales` are scales of projection sizes in light view space relative to first one: I have `(1.0, 14.0, 300.0)`. Could you please explain how just scaling the derivatives will help selecting right mipmap and suggest what is wrong in the code? I expect that even with that scaling, values on the border will still be mapped to distant texels and wrong mipmap will be used.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3kRtI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XcPSK.png&#xD;&#xA;  [3]: https://msdn.microsoft.com/en-us/library/windows/desktop/ee416307(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="13831" PostHistoryTypeId="24" PostId="5146" RevisionGUID="e0c56be0-4e77-4b3f-8271-ae027748ed5b" CreationDate="2017-05-23T16:39:21.827" Comment="Proposed by 213 approved by 6688 edit id of 252" ContentLicense="CC BY-SA 3.0" />
  <row Id="13832" PostHistoryTypeId="2" PostId="5147" RevisionGUID="9944746f-49e0-4f92-8fbf-83f7d3f61247" CreationDate="2017-05-24T09:08:53.453" UserId="6691" Text="It's Dirichlet boundary condition. The quantities at domain boundaries will take either the same value as its inner neighbor or the negated value, depending on the condition $\mathbf{b}$. Take velocity field for instance, velocity of fluid will either not change($\mathbf{b}==1$)or gets reflected ($\mathbf{b}==2$) at domain boundary. The condition $\mathbf{b}$ is a user option." ContentLicense="CC BY-SA 3.0" />
  <row Id="13833" PostHistoryTypeId="2" PostId="5148" RevisionGUID="92b3c54a-3f40-4a2a-88cd-c81893869340" CreationDate="2017-05-24T15:12:21.807" UserId="6679" Text="To start, this is my VBO Data Struct:&#xD;&#xA;&#xD;&#xA;    //-----------------------------------------------------------------&#xD;&#xA;    struct Vertex&#xD;&#xA;    //-----------------------------------------------------------------&#xD;&#xA;    {&#xD;&#xA;        //-----------------------------------------------------------------&#xD;&#xA;        Vertex()&#xD;&#xA;        : x(0), y(0), z(0), &#xD;&#xA;          s(0), t(0)&#xD;&#xA;        //-----------------------------------------------------------------&#xD;&#xA;        {}&#xD;&#xA;    &#xD;&#xA;        //-----------------------------------------------------------------&#xD;&#xA;        Vertex(Vertex&amp; rhs)        &#xD;&#xA;        : x(rhs.x), y(rhs.y), z(rhs.z),&#xD;&#xA;          s(rhs.s), t(rhs.t)&#xD;&#xA;        //-----------------------------------------------------------------&#xD;&#xA;        {}&#xD;&#xA;    &#xD;&#xA;        // Position&#xD;&#xA;        float x;&#xD;&#xA;        float y;&#xD;&#xA;        float z;&#xD;&#xA;    &#xD;&#xA;        // Texture Coords&#xD;&#xA;        float s;&#xD;&#xA;        float t;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I am reading a lot of tutorials and all seem to submit the color of their polygons with the VBO to the GPU. However, if you ever change the color, you need resubmit the data to the GPU. Why is that so common, when you can bind the color via an uniform? Isn't that heaps and bounds faster? One could argue that you need to bind the color then for each Polygon or at least Sprite or Model, depending on what you are doing, if you use the same shader for each of them, which is common practice. &#xD;&#xA;&#xD;&#xA;So I am confused how to design my (learning) 2D Game from the ground up. Should I put the 4 floats (r,g,b,a) into the VBO and add it to the layout or simply keep changing it via glUniform4fv? Is there a best practice for this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13834" PostHistoryTypeId="1" PostId="5148" RevisionGUID="92b3c54a-3f40-4a2a-88cd-c81893869340" CreationDate="2017-05-24T15:12:21.807" UserId="6679" Text="What is the best practice for data in a VBO?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13835" PostHistoryTypeId="3" PostId="5148" RevisionGUID="92b3c54a-3f40-4a2a-88cd-c81893869340" CreationDate="2017-05-24T15:12:21.807" UserId="6679" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13836" PostHistoryTypeId="2" PostId="5149" RevisionGUID="6ccc68d9-3534-4d12-a667-06e7e8a1c99f" CreationDate="2017-05-24T15:43:09.403" UserId="137" Text="To have a attribute have a certain values for a subset of vertices in the draw call you need to duplicate the data. You can only change uniforms between draw calls and you will want to minimize the number of draw calls if possible.&#xD;&#xA;&#xD;&#xA;That duplicated bit of data is likely not going to be significant overhead. Most textures will be much larger than that." ContentLicense="CC BY-SA 3.0" />
  <row Id="13837" PostHistoryTypeId="2" PostId="5150" RevisionGUID="9f44ffc2-4adb-4eaa-855f-d6c710718003" CreationDate="2017-05-24T20:47:01.250" UserId="48" Text="If the color needs to vary per vertex, it will need to be an attribute in the vertex buffer. If it's acceptable to have the color be constant per draw call, then by all means make it a uniform.&#xD;&#xA;&#xD;&#xA;By the way, editing a vertex buffer and resubmitting data to the GPU, while certainly slower than updating a uniform, doesn't have to be a huge inefficiency. By using `GL_DYNAMIC_DRAW` when you set up the buffer, combined with using [`glMapBufferRange`](http://docs.gl/gl4/glMapBufferRange) and `GL_MAP_INVALIDATE_BUFFER_BIT` to update it, the driver can manage the buffer memory and transfers efficiently. That's how you would typically do a particle system, for instance, with the particles' positions, colors, etc. changing every frame. Furthermore, if only one or two vertex attributes need to change, you can split those off into their own buffer to decrease the total data updated." ContentLicense="CC BY-SA 3.0" />
  <row Id="13838" PostHistoryTypeId="2" PostId="5151" RevisionGUID="292762c2-d4a8-4d1c-b58f-cec6036d6b26" CreationDate="2017-05-24T21:45:10.007" UserId="48" Text="The scan-line algorithm (as described on [Wikipedia](https://en.wikipedia.org/wiki/Scanline_rendering) for instance) is concerned with generating the pixels in order, left-to-right and top-to-bottom, with each pixel needing to be touched only once. It was developed in the late 1960s, for devices with no framebuffer memory—so it has to generate each pixel just-in-time as it scans out to the display.&#xD;&#xA;&#xD;&#xA;The constraint to generate the pixels exactly in order is a strong one. You have to find the closest triangle at pixel (0,0), then the closest triangle at pixel (1,0), and so on. Now, the simplest imaginable version of the algorithm indeed doesn't need tables, buckets, or sorting. All it needs to do is iterate over all the triangles, test whether the current pixel falls inside it, and keep track of the closest triangle that passes that test. Then go to the next pixel and start all over again!&#xD;&#xA;&#xD;&#xA;It's pretty clear that this is inefficient—it will result in many, many redundant calculations. The complicated data structures and stuff that show up in the classic scan-line algorithm are there to optimize this process. For instance, pre-bucketing the edges by Y-coordinate and maintaining an &quot;active edge table&quot; lets you quickly and incrementally identify the edges that affect each scanline as you move down the image. Keeping the edge intersections sorted by X-coordinate allows you to quickly generate the pixels left-to-right within each scanline, and so on.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Incidentally, this algorithm is of mainly historical interest. It is very far from how modern GPU rasterizers or even software rasterizers work. Nowadays we pretty much always have a framebuffer and use double buffering, so we don't need to generate the pixels precisely in order anymore; consequently, we usually iterate over the triangles first, then find which pixels each triangle covers, rather than the other way around.&#xD;&#xA;&#xD;&#xA;Moreover, the scanline algorithm is pretty inherently serial and doesn't make good use of today's highly parallel hardware. Modern approaches rely on multicore processing and SIMD to test many pixels against many triangles at once, rather than incrementally updating sorted lists of edges and suchlike.&#xD;&#xA;&#xD;&#xA;For more on modernized software rasterization, see Fabian Giesen's articles [Triangle rasterization in practice](https://fgiesen.wordpress.com/2013/02/08/triangle-rasterization-in-practice/) and [Optimizing the basic rasterizer](https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13839" PostHistoryTypeId="2" PostId="5152" RevisionGUID="ebb500c9-03c3-4cc3-89e6-de9efc912cea" CreationDate="2017-05-24T22:08:38.813" UserId="6698" Text="I understood the logic behind the importance sampling for the BRDF part. However, when it comes to sampling light sources explicitly, all becomes confusing. For example, if I have one point light source in my scene and if I directly sample it at each frame constantly, should I count it as one more sample for the monte carlo integration? That is, I take one sample from cosine-weighted distribution and other from the point light. Is it two samples in total or just one? Also, should I divide the radiance coming from the direct sample to any term?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13840" PostHistoryTypeId="1" PostId="5152" RevisionGUID="ebb500c9-03c3-4cc3-89e6-de9efc912cea" CreationDate="2017-05-24T22:08:38.813" UserId="6698" Text="Progressive Path Tracing with Explicit Light Sampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="13841" PostHistoryTypeId="3" PostId="5152" RevisionGUID="ebb500c9-03c3-4cc3-89e6-de9efc912cea" CreationDate="2017-05-24T22:08:38.813" UserId="6698" Text="|raytracing|pathtracing|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13842" PostHistoryTypeId="5" PostId="5151" RevisionGUID="621bccef-2842-458b-989c-7c753444321f" CreationDate="2017-05-24T23:06:11.927" UserId="48" Comment="clarify" Text="The scan-line algorithm (as described on [Wikipedia](https://en.wikipedia.org/wiki/Scanline_rendering) for instance) is concerned with generating the pixels in order, left-to-right and top-to-bottom, with each pixel needing to be touched only once. It was developed in the late 1960s, for devices with no framebuffer memory—so it has to generate each pixel just-in-time as it scans out to the display.&#xD;&#xA;&#xD;&#xA;The constraint to generate the pixels exactly in order is a strong one. Now, it's possible to imagine a very simple and naive algorithm that doesn't need tables, buckets, or sorting to accomplish this. For example, for each pixel, you might just iterate over all the triangles, test whether the current pixel falls inside it, and keep track of the closest triangle that passes that test. (That's effectively ray tracing without any acceleration structure.)&#xD;&#xA;&#xD;&#xA;It's pretty clear that this is inefficient as soon as you have more than a handful of triangles. The complicated data structures and stuff that show up in the classic scan-line algorithm are there to optimize this process. For instance, pre-bucketing the edges by Y-coordinate and maintaining an &quot;active edge table&quot; lets you quickly and incrementally identify the edges that affect each scanline as you move down the image. Keeping the edge intersections sorted by X-coordinate allows you to quickly generate the pixels left-to-right within each scanline, and keeping a Z-sorted list of active triangles as you scan left-to-right enables you to do hidden surface removal at the same time.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Incidentally, this algorithm is of mainly historical interest. It is very far from how modern GPU rasterizers or even software rasterizers work. Nowadays we pretty much always have a framebuffer and use double buffering, so we don't need to generate the pixels precisely in order anymore; consequently, we usually iterate over the triangles first, then find which pixels each triangle covers, rather than the other way around.&#xD;&#xA;&#xD;&#xA;Moreover, the scanline algorithm is pretty inherently serial and doesn't make good use of today's highly parallel hardware. Modern approaches rely on multicore processing and SIMD to test many pixels against many triangles at once, rather than incrementally updating sorted lists of edges and suchlike.&#xD;&#xA;&#xD;&#xA;For more on modernized software rasterization, see Fabian Giesen's articles [Triangle rasterization in practice](https://fgiesen.wordpress.com/2013/02/08/triangle-rasterization-in-practice/) and [Optimizing the basic rasterizer](https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/)." ContentLicense="CC BY-SA 3.0" />
  <row Id="13843" PostHistoryTypeId="5" PostId="5147" RevisionGUID="88134d19-22ea-4c85-ab5f-6760b5d54f15" CreationDate="2017-05-25T01:45:59.150" UserId="6691" Comment="corrected little mistakes in explanation" Text="It's Dirichlet boundary condition. The quantities at domain boundaries will take either the same value as its inner neighbor or the negated value, depending on the condition $\mathbf{b}$. Take velocity field for instance, velocity of fluid will either gets reflected($\mathbf{b}==1||\mathbf{b}==2$)or not change ($\mathbf{b}!=1\&amp;\&amp;\mathbf{b}!=2$) at domain boundary. The condition $\mathbf{b}$ is a user option, $\mathbf{b}==1$ is used to set reflected values at the horizonal boundaries, $\mathbf{b}==2$ is to set reflected values at vertical boundaries, and $\mathbf{b}$ of other values are used to indicate field values won't change for both horizonal and vertical boundaries." ContentLicense="CC BY-SA 3.0" />
  <row Id="13844" PostHistoryTypeId="5" PostId="5147" RevisionGUID="9d1b55cc-d680-4a5c-bb08-b150f4a07039" CreationDate="2017-05-25T02:16:26.863" UserId="6691" Comment="to be more precise" Text="It's Dirichlet boundary condition. The quantities at domain boundaries will take either the same value as its inner neighbor or the negated value, depending on the condition $\mathbf{b}$. Take velocity field for instance, velocity of fluid will either gets reflected or not change at domain boundary. The condition $\mathbf{b}$ is a user option, $\mathbf{b}==1$ is used to set reflected values at the horizonal boundaries, and $\mathbf{b}==2$ is to set reflected values at vertical boundaries. To be more clear:&#xD;&#xA;&#xD;&#xA; - $\mathbf{b}==1$: field values at horizonal boundaries get reflected, field values at vertical boundaries do not change.&#xD;&#xA; - $\mathbf{b}==2$: field values at vertical boundaries get reflected, field values at horizonal boundaries do not change.&#xD;&#xA; - $\mathbf{b}== other\ value$: field values at neither vertical nor horizonal boundaries do not change. &#xD;&#xA;&#xD;&#xA;set_bnd could be called multiple times to set desired boundary values." ContentLicense="CC BY-SA 3.0" />
  <row Id="13846" PostHistoryTypeId="2" PostId="5153" RevisionGUID="02656934-c1ce-405c-b5fe-b4a566442a3b" CreationDate="2017-05-25T04:09:07.557" UserId="310" Text="There are multiple areas in path tracing that can be importance sampled. In addition, each of those areas can also use Multiple Importance Sampling, first proposed in Veach and Guibas's [1995 paper][1]. To better explain, let's look at a backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emission&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Shoot a ray through the scene&#xD;&#xA; 1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA; 1. Check if we hit a light. If so, we add the light emission to our color accumulation&#xD;&#xA; 1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF&#xD;&#xA; 1. Evaluate the BRDF and accumulate it. Here we have to divide by the pdf of our chosen direction, in order to follow the Monte Carlo Algorithm.&#xD;&#xA; 1. Create a new ray based on our chosen direction and where we just came from&#xD;&#xA; 1. [Optional] Use Russian Roulette to choose if we should terminate the ray&#xD;&#xA; 1. Goto 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With this code, we only get color if the ray eventually hits a light. In addition, it doesn't support punctual light sources, since they have no area. &#xD;&#xA;&#xD;&#xA;To fix this, we sample the lights directly at every bounce. We have to do a few small changes:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;            // we need to add the emmisive light&#xD;&#xA;            if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Calculate the direct lighting&#xD;&#xA;            color += throughput * SampleLights(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;First, we add &quot;color += throughput * SampleLights(...)&quot;. I'll go into detail about SampleLights() in a bit. But, essentially, it loops through all the lights, and returns their contribution to the color, attenuated by the BSDF.&#xD;&#xA;&#xD;&#xA;This is great, but we need to make one more change in order to make it correct; specifically, what happens when we hit a light. In the old code, we added the light's emission to the color accumulation. But now we directly sample the light every bounce, so if we added the light's emission, we would &quot;double dip&quot;. Therefore, the correct thing to do is... nothing; we skip accumulating the light's emission.&#xD;&#xA;&#xD;&#xA;However, there are two corner cases: &#xD;&#xA;&#xD;&#xA; 1. The first ray&#xD;&#xA; 2. Perfectly specular bounces (aka mirrors)&#xD;&#xA;&#xD;&#xA;If the first ray hits the light, you should see the light's emission directly. So if we skip it, all the lights will show up as black, even though the surfaces around them are lit.&#xD;&#xA;&#xD;&#xA;When you hit a perfectly specular surfaces you can't directly sample a light, because an input ray has only one output. Well, technically, we *could* check if the input ray is going to hit a light, but there's no point; the main Path Tracing loop is going to do that anyway. Therefore, if we hit a light just after we hit a specular surface, we need to accumulate the color. If we don't, lights will be black in mirrors.&#xD;&#xA;&#xD;&#xA;Now, let's delve into SampleLights(): &#xD;&#xA;&#xD;&#xA;    float3 SampleLights(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {&#xD;&#xA;        std::size_t numLights = m_scene-&gt;NumLights();&#xD;&#xA;        &#xD;&#xA;        float3 L(0.0f);&#xD;&#xA;        for (uint i = 0; i &lt; numLights; ++i) {&#xD;&#xA;            Light *light = &amp;m_scene-&gt;Lights[i];&#xD;&#xA;&#xD;&#xA;            // Don't let a light contribute light to itself&#xD;&#xA;            if (light == hitLight) {&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            L = L + EstimateDirect(light, sampler, interaction, bsdf);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return L;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Loop through all the lights&#xD;&#xA; 1. Skip the light if we hit it&#xD;&#xA;    - Don't double dip&#xD;&#xA; 1. Accumulate the direct lighting from all the lights&#xD;&#xA; 1. Return the direct lighting&#xD;&#xA;&#xD;&#xA;Finally, EstimateDirect() is just evaluating $BSDF(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}})$&#xD;&#xA;&#xD;&#xA;For punctual light sources, this is simple as:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            return float3(0.0f);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        interaction.InputDirection = normalize(light-&gt;Origin - interaction.Position);&#xD;&#xA;        return bsdf-&gt;Eval(interaction) * light-&gt;Li;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, if we want lights to have area, we first need to sample a point on the light. Therefore, the full definition is:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        float3 directLighting = float3(0.0f);&#xD;&#xA;        &#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            float pdf;&#xD;&#xA;            float3 Li = light-&gt;SampleLi(sampler, m_scene, interaction, &amp;pdf);&#xD;&#xA;&#xD;&#xA;            // Make sure the pdf isn't zero and the radiance isn't black&#xD;&#xA;            if (pdf != 0.0f &amp;&amp; !all(Li)) {&#xD;&#xA;                directLighting += bsdf-&gt;Eval(interaction) * Li / pdf;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;We can implement light-&gt;SampleLi however we want; we can choose the point uniformly, or importance sample. In either case, we divide the radiosity by the pdf of choosing the point. Again, to satisfy the requirements of Monte Carlo.&#xD;&#xA;&#xD;&#xA;If the BRDF is highly view dependent, it may be better to choose a point based on the BRDF, instead of a random point on the light. But how do we choose? Sample based on the light, or based on the BRDF?&#xD;&#xA;&#xD;&#xA;Why not both? Enter Multiple Importance Sampling. In short, we evaluate $BSDF(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}})$ multiple times, using different sampling techniques, then average them together using weights based on their pdfs. In code this is:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        float3 directLighting = float3(0.0f);&#xD;&#xA;        float3 f;&#xD;&#xA;        float lightPdf, scatteringPdf;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Sample lighting with multiple importance sampling&#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            float3 Li = light-&gt;SampleLi(sampler, m_scene, interaction, &amp;lightPdf);&#xD;&#xA;&#xD;&#xA;            // Make sure the pdf isn't zero and the radiance isn't black&#xD;&#xA;            if (lightPdf != 0.0f &amp;&amp; !all(Li)) {&#xD;&#xA;                // Calculate the brdf value&#xD;&#xA;                f = bsdf-&gt;Eval(interaction);&#xD;&#xA;                scatteringPdf = bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;                if (scatteringPdf != 0.0f &amp;&amp; !all(f)) {&#xD;&#xA;                    float weight = PowerHeuristic(1, lightPdf, 1, scatteringPdf);&#xD;&#xA;                    directLighting += f * Li * weight / lightPdf;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Sample brdf with multiple importance sampling&#xD;&#xA;        bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;        f = bsdf-&gt;Eval(interaction);&#xD;&#xA;        scatteringPdf = bsdf-&gt;Pdf(interaction);&#xD;&#xA;        if (scatteringPdf != 0.0f &amp;&amp; !all(f)) {&#xD;&#xA;            lightPdf = light-&gt;PdfLi(m_scene, interaction);&#xD;&#xA;            if (lightPdf == 0.0f) {&#xD;&#xA;                // We didn't hit anything, so ignore the brdf sample&#xD;&#xA;                return directLighting;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float weight = PowerHeuristic(1, scatteringPdf, 1, lightPdf);&#xD;&#xA;            float3 Li = light-&gt;Le();&#xD;&#xA;            directLighting += f * Li * weight / scatteringPdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. First, we sample the light&#xD;&#xA;   - This updates interaction.InputDirection&#xD;&#xA;   - Gives us the Li for the light&#xD;&#xA;   - And the pdf of choosing that point on the light&#xD;&#xA; 1. Check that the pdf is valid and the radiance is non-zero&#xD;&#xA; 1. Evaluate the BSDF using the sampled InputDirection&#xD;&#xA; 1. Calculate the pdf for the BSDF given the sampled InputDirection&#xD;&#xA;   - Essentially, how likely is this sample, if we were to sample using the BSDF, instead of the light&#xD;&#xA; 1. Calculate the weight, using the light pdf and the BSDF pdf&#xD;&#xA;   - Veach and Guibas define a couple different ways to calculate the weight. Experimentally, they found the power heuristic with a power of 2 to work the best for most cases. I refer you to the paper for more details. The implementation is below&#xD;&#xA; 1. Multiply the weight with the direct lighting calculation and divide by the light pdf. (For Monte Carlo) And add to the direct light accumulation.&#xD;&#xA; 1. Then, we sample the BRDF&#xD;&#xA;   - This updates interaction.InputDirection&#xD;&#xA; 1. Evaluate the BRDF&#xD;&#xA; 1. Get the pdf for choosing this direction based on the BRDF&#xD;&#xA; 1. Calculate the light pdf, given the sampled InputDirection&#xD;&#xA;   - This is the mirror of before. How likely is this direction, if we were to sample the light&#xD;&#xA; 1. If lightPdf == 0.0f, then the ray missed the light, so just return the direct lighting from the light sample.&#xD;&#xA; 1. Otherwise, calculate the weight, and add the BSDF direct lighting to the accumulation&#xD;&#xA; 1. Finally, return the accumulated direct lighting&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;    inline float PowerHeuristic(uint numf, float fPdf, uint numg, float gPdf) {&#xD;&#xA;        float f = numf * fPdf;&#xD;&#xA;        float g = numg * gPdf;&#xD;&#xA;&#xD;&#xA;        return (f * f) / (f * f + g * g);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;There are a number of optimizations / improvements you can do in these functions, but I've pared them down to try to make them easier to comprehend. If you would like, I can share some of these improvements.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://sites.fas.harvard.edu/~cs278/papers/veach.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13853" PostHistoryTypeId="5" PostId="5153" RevisionGUID="1dc6298f-2f24-42b9-a61c-f1057909799e" CreationDate="2017-05-25T18:47:27.517" UserId="310" Comment="Add section about Sampling One Light and Multiple Improtance Sampling the &quot;New Direction&quot;" Text="There are multiple areas in path tracing that can be importance sampled. In addition, each of those areas can also use Multiple Importance Sampling, first proposed in Veach and Guibas's [1995 paper][1]. To better explain, let's look at a backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emission&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Shoot a ray through the scene&#xD;&#xA; 1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA; 1. Check if we hit a light. If so, we add the light emission to our color accumulation&#xD;&#xA; 1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF&#xD;&#xA; 1. Evaluate the BRDF and accumulate it. Here we have to divide by the pdf of our chosen direction, in order to follow the Monte Carlo Algorithm.&#xD;&#xA; 1. Create a new ray based on our chosen direction and where we just came from&#xD;&#xA; 1. [Optional] Use Russian Roulette to choose if we should terminate the ray&#xD;&#xA; 1. Goto 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With this code, we only get color if the ray eventually hits a light. In addition, it doesn't support punctual light sources, since they have no area. &#xD;&#xA;&#xD;&#xA;To fix this, we sample the lights directly at every bounce. We have to do a few small changes:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;            // we need to add the emmisive light&#xD;&#xA;            if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Calculate the direct lighting&#xD;&#xA;            color += throughput * SampleLights(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;First, we add &quot;color += throughput * SampleLights(...)&quot;. I'll go into detail about SampleLights() in a bit. But, essentially, it loops through all the lights, and returns their contribution to the color, attenuated by the BSDF.&#xD;&#xA;&#xD;&#xA;This is great, but we need to make one more change in order to make it correct; specifically, what happens when we hit a light. In the old code, we added the light's emission to the color accumulation. But now we directly sample the light every bounce, so if we added the light's emission, we would &quot;double dip&quot;. Therefore, the correct thing to do is... nothing; we skip accumulating the light's emission.&#xD;&#xA;&#xD;&#xA;However, there are two corner cases: &#xD;&#xA;&#xD;&#xA; 1. The first ray&#xD;&#xA; 2. Perfectly specular bounces (aka mirrors)&#xD;&#xA;&#xD;&#xA;If the first ray hits the light, you should see the light's emission directly. So if we skip it, all the lights will show up as black, even though the surfaces around them are lit.&#xD;&#xA;&#xD;&#xA;When you hit a perfectly specular surfaces you can't directly sample a light, because an input ray has only one output. Well, technically, we *could* check if the input ray is going to hit a light, but there's no point; the main Path Tracing loop is going to do that anyway. Therefore, if we hit a light just after we hit a specular surface, we need to accumulate the color. If we don't, lights will be black in mirrors.&#xD;&#xA;&#xD;&#xA;Now, let's delve into SampleLights(): &#xD;&#xA;&#xD;&#xA;    float3 SampleLights(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {&#xD;&#xA;        std::size_t numLights = m_scene-&gt;NumLights();&#xD;&#xA;        &#xD;&#xA;        float3 L(0.0f);&#xD;&#xA;        for (uint i = 0; i &lt; numLights; ++i) {&#xD;&#xA;            Light *light = &amp;m_scene-&gt;Lights[i];&#xD;&#xA;&#xD;&#xA;            // Don't let a light contribute light to itself&#xD;&#xA;            if (light == hitLight) {&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            L = L + EstimateDirect(light, sampler, interaction, bsdf);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return L;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Loop through all the lights&#xD;&#xA; 1. Skip the light if we hit it&#xD;&#xA;    - Don't double dip&#xD;&#xA; 1. Accumulate the direct lighting from all the lights&#xD;&#xA; 1. Return the direct lighting&#xD;&#xA;&#xD;&#xA;Finally, EstimateDirect() is just evaluating $BSDF(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}})$&#xD;&#xA;&#xD;&#xA;For punctual light sources, this is simple as:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            return float3(0.0f);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        interaction.InputDirection = normalize(light-&gt;Origin - interaction.Position);&#xD;&#xA;        return bsdf-&gt;Eval(interaction) * light-&gt;Li;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, if we want lights to have area, we first need to sample a point on the light. Therefore, the full definition is:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        float3 directLighting = float3(0.0f);&#xD;&#xA;        &#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            float pdf;&#xD;&#xA;            float3 Li = light-&gt;SampleLi(sampler, m_scene, interaction, &amp;pdf);&#xD;&#xA;&#xD;&#xA;            // Make sure the pdf isn't zero and the radiance isn't black&#xD;&#xA;            if (pdf != 0.0f &amp;&amp; !all(Li)) {&#xD;&#xA;                directLighting += bsdf-&gt;Eval(interaction) * Li / pdf;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;We can implement light-&gt;SampleLi however we want; we can choose the point uniformly, or importance sample. In either case, we divide the radiosity by the pdf of choosing the point. Again, to satisfy the requirements of Monte Carlo.&#xD;&#xA;&#xD;&#xA;If the BRDF is highly view dependent, it may be better to choose a point based on the BRDF, instead of a random point on the light. But how do we choose? Sample based on the light, or based on the BRDF?&#xD;&#xA;&#xD;&#xA;Why not both? Enter Multiple Importance Sampling. In short, we evaluate $BSDF(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}})$ multiple times, using different sampling techniques, then average them together using weights based on their pdfs. In code this is:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        float3 directLighting = float3(0.0f);&#xD;&#xA;        float3 f;&#xD;&#xA;        float lightPdf, scatteringPdf;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Sample lighting with multiple importance sampling&#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            float3 Li = light-&gt;SampleLi(sampler, m_scene, interaction, &amp;lightPdf);&#xD;&#xA;&#xD;&#xA;            // Make sure the pdf isn't zero and the radiance isn't black&#xD;&#xA;            if (lightPdf != 0.0f &amp;&amp; !all(Li)) {&#xD;&#xA;                // Calculate the brdf value&#xD;&#xA;                f = bsdf-&gt;Eval(interaction);&#xD;&#xA;                scatteringPdf = bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;                if (scatteringPdf != 0.0f &amp;&amp; !all(f)) {&#xD;&#xA;                    float weight = PowerHeuristic(1, lightPdf, 1, scatteringPdf);&#xD;&#xA;                    directLighting += f * Li * weight / lightPdf;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Sample brdf with multiple importance sampling&#xD;&#xA;        bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;        f = bsdf-&gt;Eval(interaction);&#xD;&#xA;        scatteringPdf = bsdf-&gt;Pdf(interaction);&#xD;&#xA;        if (scatteringPdf != 0.0f &amp;&amp; !all(f)) {&#xD;&#xA;            lightPdf = light-&gt;PdfLi(m_scene, interaction);&#xD;&#xA;            if (lightPdf == 0.0f) {&#xD;&#xA;                // We didn't hit anything, so ignore the brdf sample&#xD;&#xA;                return directLighting;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float weight = PowerHeuristic(1, scatteringPdf, 1, lightPdf);&#xD;&#xA;            float3 Li = light-&gt;Le();&#xD;&#xA;            directLighting += f * Li * weight / scatteringPdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. First, we sample the light&#xD;&#xA;   - This updates interaction.InputDirection&#xD;&#xA;   - Gives us the Li for the light&#xD;&#xA;   - And the pdf of choosing that point on the light&#xD;&#xA; 1. Check that the pdf is valid and the radiance is non-zero&#xD;&#xA; 1. Evaluate the BSDF using the sampled InputDirection&#xD;&#xA; 1. Calculate the pdf for the BSDF given the sampled InputDirection&#xD;&#xA;   - Essentially, how likely is this sample, if we were to sample using the BSDF, instead of the light&#xD;&#xA; 1. Calculate the weight, using the light pdf and the BSDF pdf&#xD;&#xA;   - Veach and Guibas define a couple different ways to calculate the weight. Experimentally, they found the power heuristic with a power of 2 to work the best for most cases. I refer you to the paper for more details. The implementation is below&#xD;&#xA; 1. Multiply the weight with the direct lighting calculation and divide by the light pdf. (For Monte Carlo) And add to the direct light accumulation.&#xD;&#xA; 1. Then, we sample the BRDF&#xD;&#xA;   - This updates interaction.InputDirection&#xD;&#xA; 1. Evaluate the BRDF&#xD;&#xA; 1. Get the pdf for choosing this direction based on the BRDF&#xD;&#xA; 1. Calculate the light pdf, given the sampled InputDirection&#xD;&#xA;   - This is the mirror of before. How likely is this direction, if we were to sample the light&#xD;&#xA; 1. If lightPdf == 0.0f, then the ray missed the light, so just return the direct lighting from the light sample.&#xD;&#xA; 1. Otherwise, calculate the weight, and add the BSDF direct lighting to the accumulation&#xD;&#xA; 1. Finally, return the accumulated direct lighting&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;    inline float PowerHeuristic(uint numf, float fPdf, uint numg, float gPdf) {&#xD;&#xA;        float f = numf * fPdf;&#xD;&#xA;        float g = numg * gPdf;&#xD;&#xA;&#xD;&#xA;        return (f * f) / (f * f + g * g);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;There are a number of optimizations / improvements you can do in these functions, but I've pared them down to try to make them easier to comprehend. If you would like, I can share some of these improvements.&#xD;&#xA;&#xD;&#xA;Only Sampling One Light&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;In SampleLights() we loop through all the lights, and get their contribution. For a small number of lights, this is fine, but for hundreds or thousands of lights, this gets expensive. Fortunately, we can exploit the fact that Monte Carlo Integration is a giant average. Example:&#xD;&#xA;&#xD;&#xA;Let's define &#xD;&#xA;&#xD;&#xA;$$h(x) = f(x) + g(x)$$&#xD;&#xA;&#xD;&#xA;Currently, we're estimating $h(x)$ by:&#xD;&#xA;&#xD;&#xA;$$h(x) = \frac{1}{N} \sum_{i=1}^N f(x_i) + g(x_i)$$&#xD;&#xA;&#xD;&#xA;But, calculating both $f(x)$ and $g(x)$ is expensive, so instead we do:&#xD;&#xA;&#xD;&#xA;$$h(x) = \frac{1}{N} \sum_{i=1}^N \frac{r(\zeta, x)}{pdf}$$&#xD;&#xA;&#xD;&#xA;Where $\zeta$ is a uniform random variable, and $r(\zeta, x)$ is defined as:&#xD;&#xA;&#xD;&#xA;$$r(\zeta, x) = &#xD;&#xA;    \begin{cases}&#xD;&#xA;      f(x), &amp; 0.0 \leq \zeta \lt 0.5 \\&#xD;&#xA;      g(x), &amp; 0.5 \leq \zeta \lt 1.0&#xD;&#xA;    \end{cases}$$&#xD;&#xA;&#xD;&#xA;In this case $pdf = \frac{1}{2}$ because the pdf must integrate to 1, and there are 2 functions to choose from.&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Randomly choose either $f(x)$ or $g(x)$ to evaluate. &#xD;&#xA; 1. Divide the result by $\frac{1}{2}$ (since there are two items)&#xD;&#xA; 1. Average&#xD;&#xA;&#xD;&#xA;As N gets large, the estimate will converge to the correct solution. &#xD;&#xA;&#xD;&#xA;We can apply this same principle to light sampling. Instead of sampling every light, we randomly pick one, and multiply the result by the number of lights (This is the same as dividing by the fractional pdf):&#xD;&#xA;&#xD;&#xA;    float3 SampleOneLight(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {&#xD;&#xA;        std::size_t numLights = m_scene-&gt;NumLights();&#xD;&#xA;        &#xD;&#xA;        // Return black if there are no lights&#xD;&#xA;        // And don't let a light contribute light to itself&#xD;&#xA;        // Aka, if we hit a light&#xD;&#xA;        // This is the special case where there is only 1 light&#xD;&#xA;        if (numLights == 0 || numLights == 1 &amp;&amp; hitLight != nullptr) {&#xD;&#xA;            return float3(0.0f);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Don't let a light contribute light to itself&#xD;&#xA;        // Choose another one&#xD;&#xA;        Light *light;&#xD;&#xA;        do {&#xD;&#xA;            light = m_scene-&gt;RandomOneLight(sampler);&#xD;&#xA;        } while (light == hitLight);&#xD;&#xA;&#xD;&#xA;        return numLights * EstimateDirect(light, sampler, interaction, bsdf);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In this code, all the lights have an equal chance of being picked. However, we can importance sample, if we like. For example, we can give larger lights a higher chance of being picked, or lights closer to the surface. You just have to divide the result by the pdf, which would no longer be $\frac{1}{\text{numLights}}$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Multiple Importance Sampling the &quot;New Ray&quot; Direction&#xD;&#xA;------------&#xD;&#xA;The current code only importance samples the &quot;New Ray&quot; direction based on the BSDF. What if we want to also importance sample based on the location of lights?&#xD;&#xA;&#xD;&#xA;Taking from what we learned above, one method would be to shoot **two** &quot;new&quot; rays and weight each based on their pdfs. However, this is both computationally expensive, and hard to implement without recursion.&#xD;&#xA;&#xD;&#xA;To overcome this, we can apply the same principles we learned by sampling only one light. That is, randomly choose one to sample, and divide by the pdf of choosing it.&#xD;&#xA;&#xD;&#xA;    // Get the new ray direction&#xD;&#xA;&#xD;&#xA;    // Randomly (uniform) choose whether to sample based on the BSDF or the Lights&#xD;&#xA;    float p = sampler-&gt;NextFloat();&#xD;&#xA;&#xD;&#xA;    Light *light = m_scene-&gt;RandomLight();&#xD;&#xA;&#xD;&#xA;    if (p &lt; 0.5f) {&#xD;&#xA;        // Choose the direction based on the bsdf &#xD;&#xA;        material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;        float bsdfPdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;        &#xD;&#xA;        float lightPdf = light-&gt;PdfLi(m_scene, interaction);&#xD;&#xA;        float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);&#xD;&#xA;        &#xD;&#xA;        // Accumulate the throughput&#xD;&#xA;        throughput = throughput * weight * material-&gt;bsdf-&gt;Eval(interaction) / bsdfPdf;&#xD;&#xA;        &#xD;&#xA;    } else {&#xD;&#xA;        // Choose the direction based on a light&#xD;&#xA;        float lightPdf;&#xD;&#xA;        light-&gt;SampleLi(sampler, m_scene, interaction, &amp;lightPdf);&#xD;&#xA;        &#xD;&#xA;        float bsdfPdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;        float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);&#xD;&#xA;        &#xD;&#xA;        // Accumulate the throughput&#xD;&#xA;        throughput = throughput * weight * material-&gt;bsdf-&gt;Eval(interaction) / lightPdf;&#xD;&#xA;    }&#xD;&#xA;           &#xD;&#xA;That all said, do we really ***want*** to importance sample the &quot;New Ray&quot; direction based on the light? For *direct* lighting, the radiosity is affected by both the BSDF of the surface, and the direction of the light. But for *indirect* lighting, the radiosity is almost exclusively defined by the BSDF of the surface hit before. So, adding light importance sampling doesn't give us anything. &#xD;&#xA;&#xD;&#xA;Therefore, it is common to only importance sample the &quot;New Direction&quot; with the BSDF, but apply Multiple Importance Sampling to the direct lighting.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://sites.fas.harvard.edu/~cs278/papers/veach.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13854" PostHistoryTypeId="5" PostId="5153" RevisionGUID="47cd994e-7064-48fe-8582-ba139e376454" CreationDate="2017-05-25T18:56:47.003" UserId="310" Comment="added 4 characters in body" Text="There are multiple areas in path tracing that can be importance sampled. In addition, each of those areas can also use Multiple Importance Sampling, first proposed in Veach and Guibas's [1995 paper][1]. To better explain, let's look at a backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emission&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Shoot a ray through the scene&#xD;&#xA; 1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA; 1. Check if we hit a light. If so, we add the light emission to our color accumulation&#xD;&#xA; 1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF&#xD;&#xA; 1. Evaluate the BRDF and accumulate it. Here we have to divide by the pdf of our chosen direction, in order to follow the Monte Carlo Algorithm.&#xD;&#xA; 1. Create a new ray based on our chosen direction and where we just came from&#xD;&#xA; 1. [Optional] Use Russian Roulette to choose if we should terminate the ray&#xD;&#xA; 1. Goto 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With this code, we only get color if the ray eventually hits a light. In addition, it doesn't support punctual light sources, since they have no area. &#xD;&#xA;&#xD;&#xA;To fix this, we sample the lights directly at every bounce. We have to do a few small changes:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;            // we need to add the emmisive light&#xD;&#xA;            if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Calculate the direct lighting&#xD;&#xA;            color += throughput * SampleLights(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;First, we add &quot;color += throughput * SampleLights(...)&quot;. I'll go into detail about SampleLights() in a bit. But, essentially, it loops through all the lights, and returns their contribution to the color, attenuated by the BSDF.&#xD;&#xA;&#xD;&#xA;This is great, but we need to make one more change in order to make it correct; specifically, what happens when we hit a light. In the old code, we added the light's emission to the color accumulation. But now we directly sample the light every bounce, so if we added the light's emission, we would &quot;double dip&quot;. Therefore, the correct thing to do is... nothing; we skip accumulating the light's emission.&#xD;&#xA;&#xD;&#xA;However, there are two corner cases: &#xD;&#xA;&#xD;&#xA; 1. The first ray&#xD;&#xA; 2. Perfectly specular bounces (aka mirrors)&#xD;&#xA;&#xD;&#xA;If the first ray hits the light, you should see the light's emission directly. So if we skip it, all the lights will show up as black, even though the surfaces around them are lit.&#xD;&#xA;&#xD;&#xA;When you hit a perfectly specular surfaces you can't directly sample a light, because an input ray has only one output. Well, technically, we *could* check if the input ray is going to hit a light, but there's no point; the main Path Tracing loop is going to do that anyway. Therefore, if we hit a light just after we hit a specular surface, we need to accumulate the color. If we don't, lights will be black in mirrors.&#xD;&#xA;&#xD;&#xA;Now, let's delve into SampleLights(): &#xD;&#xA;&#xD;&#xA;    float3 SampleLights(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {&#xD;&#xA;        std::size_t numLights = m_scene-&gt;NumLights();&#xD;&#xA;        &#xD;&#xA;        float3 L(0.0f);&#xD;&#xA;        for (uint i = 0; i &lt; numLights; ++i) {&#xD;&#xA;            Light *light = &amp;m_scene-&gt;Lights[i];&#xD;&#xA;&#xD;&#xA;            // Don't let a light contribute light to itself&#xD;&#xA;            if (light == hitLight) {&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            L = L + EstimateDirect(light, sampler, interaction, bsdf);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return L;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Loop through all the lights&#xD;&#xA; 1. Skip the light if we hit it&#xD;&#xA;    - Don't double dip&#xD;&#xA; 1. Accumulate the direct lighting from all the lights&#xD;&#xA; 1. Return the direct lighting&#xD;&#xA;&#xD;&#xA;Finally, EstimateDirect() is just evaluating $BSDF(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}})$&#xD;&#xA;&#xD;&#xA;For punctual light sources, this is simple as:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            return float3(0.0f);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        interaction.InputDirection = normalize(light-&gt;Origin - interaction.Position);&#xD;&#xA;        return bsdf-&gt;Eval(interaction) * light-&gt;Li;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, if we want lights to have area, we first need to sample a point on the light. Therefore, the full definition is:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        float3 directLighting = float3(0.0f);&#xD;&#xA;        &#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            float pdf;&#xD;&#xA;            float3 Li = light-&gt;SampleLi(sampler, m_scene, interaction, &amp;pdf);&#xD;&#xA;&#xD;&#xA;            // Make sure the pdf isn't zero and the radiance isn't black&#xD;&#xA;            if (pdf != 0.0f &amp;&amp; !all(Li)) {&#xD;&#xA;                directLighting += bsdf-&gt;Eval(interaction) * Li / pdf;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;We can implement light-&gt;SampleLi however we want; we can choose the point uniformly, or importance sample. In either case, we divide the radiosity by the pdf of choosing the point. Again, to satisfy the requirements of Monte Carlo.&#xD;&#xA;&#xD;&#xA;If the BRDF is highly view dependent, it may be better to choose a point based on the BRDF, instead of a random point on the light. But how do we choose? Sample based on the light, or based on the BRDF?&#xD;&#xA;&#xD;&#xA;Why not both? Enter Multiple Importance Sampling. In short, we evaluate $BSDF(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}})$ multiple times, using different sampling techniques, then average them together using weights based on their pdfs. In code this is:&#xD;&#xA;&#xD;&#xA;    float3 EstimateDirect(Light *light, UniformSampler *sampler, SurfaceInteraction &amp;interaction, BSDF *bsdf) const {&#xD;&#xA;        float3 directLighting = float3(0.0f);&#xD;&#xA;        float3 f;&#xD;&#xA;        float lightPdf, scatteringPdf;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Sample lighting with multiple importance sampling&#xD;&#xA;        // Only sample if the BRDF is non-specular &#xD;&#xA;        if ((bsdf-&gt;SupportedLobes &amp; ~BSDFLobe::Specular) != 0) {&#xD;&#xA;            float3 Li = light-&gt;SampleLi(sampler, m_scene, interaction, &amp;lightPdf);&#xD;&#xA;&#xD;&#xA;            // Make sure the pdf isn't zero and the radiance isn't black&#xD;&#xA;            if (lightPdf != 0.0f &amp;&amp; !all(Li)) {&#xD;&#xA;                // Calculate the brdf value&#xD;&#xA;                f = bsdf-&gt;Eval(interaction);&#xD;&#xA;                scatteringPdf = bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;                if (scatteringPdf != 0.0f &amp;&amp; !all(f)) {&#xD;&#xA;                    float weight = PowerHeuristic(1, lightPdf, 1, scatteringPdf);&#xD;&#xA;                    directLighting += f * Li * weight / lightPdf;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Sample brdf with multiple importance sampling&#xD;&#xA;        bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;        f = bsdf-&gt;Eval(interaction);&#xD;&#xA;        scatteringPdf = bsdf-&gt;Pdf(interaction);&#xD;&#xA;        if (scatteringPdf != 0.0f &amp;&amp; !all(f)) {&#xD;&#xA;            lightPdf = light-&gt;PdfLi(m_scene, interaction);&#xD;&#xA;            if (lightPdf == 0.0f) {&#xD;&#xA;                // We didn't hit anything, so ignore the brdf sample&#xD;&#xA;                return directLighting;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float weight = PowerHeuristic(1, scatteringPdf, 1, lightPdf);&#xD;&#xA;            float3 Li = light-&gt;Le();&#xD;&#xA;            directLighting += f * Li * weight / scatteringPdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. First, we sample the light&#xD;&#xA;   - This updates interaction.InputDirection&#xD;&#xA;   - Gives us the Li for the light&#xD;&#xA;   - And the pdf of choosing that point on the light&#xD;&#xA; 1. Check that the pdf is valid and the radiance is non-zero&#xD;&#xA; 1. Evaluate the BSDF using the sampled InputDirection&#xD;&#xA; 1. Calculate the pdf for the BSDF given the sampled InputDirection&#xD;&#xA;   - Essentially, how likely is this sample, if we were to sample using the BSDF, instead of the light&#xD;&#xA; 1. Calculate the weight, using the light pdf and the BSDF pdf&#xD;&#xA;   - Veach and Guibas define a couple different ways to calculate the weight. Experimentally, they found the power heuristic with a power of 2 to work the best for most cases. I refer you to the paper for more details. The implementation is below&#xD;&#xA; 1. Multiply the weight with the direct lighting calculation and divide by the light pdf. (For Monte Carlo) And add to the direct light accumulation.&#xD;&#xA; 1. Then, we sample the BRDF&#xD;&#xA;   - This updates interaction.InputDirection&#xD;&#xA; 1. Evaluate the BRDF&#xD;&#xA; 1. Get the pdf for choosing this direction based on the BRDF&#xD;&#xA; 1. Calculate the light pdf, given the sampled InputDirection&#xD;&#xA;   - This is the mirror of before. How likely is this direction, if we were to sample the light&#xD;&#xA; 1. If lightPdf == 0.0f, then the ray missed the light, so just return the direct lighting from the light sample.&#xD;&#xA; 1. Otherwise, calculate the weight, and add the BSDF direct lighting to the accumulation&#xD;&#xA; 1. Finally, return the accumulated direct lighting&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;.&#xD;&#xA;&#xD;&#xA;    inline float PowerHeuristic(uint numf, float fPdf, uint numg, float gPdf) {&#xD;&#xA;        float f = numf * fPdf;&#xD;&#xA;        float g = numg * gPdf;&#xD;&#xA;&#xD;&#xA;        return (f * f) / (f * f + g * g);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;There are a number of optimizations / improvements you can do in these functions, but I've pared them down to try to make them easier to comprehend. If you would like, I can share some of these improvements.&#xD;&#xA;&#xD;&#xA;Only Sampling One Light&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;In SampleLights() we loop through all the lights, and get their contribution. For a small number of lights, this is fine, but for hundreds or thousands of lights, this gets expensive. Fortunately, we can exploit the fact that Monte Carlo Integration is a giant average. Example:&#xD;&#xA;&#xD;&#xA;Let's define &#xD;&#xA;&#xD;&#xA;$$h(x) = f(x) + g(x)$$&#xD;&#xA;&#xD;&#xA;Currently, we're estimating $h(x)$ by:&#xD;&#xA;&#xD;&#xA;$$h(x) = \frac{1}{N} \sum_{i=1}^N f(x_i) + g(x_i)$$&#xD;&#xA;&#xD;&#xA;But, calculating both $f(x)$ and $g(x)$ is expensive, so instead we do:&#xD;&#xA;&#xD;&#xA;$$h(x) = \frac{1}{N} \sum_{i=1}^N \frac{r(\zeta, x)}{pdf}$$&#xD;&#xA;&#xD;&#xA;Where $\zeta$ is a uniform random variable, and $r(\zeta, x)$ is defined as:&#xD;&#xA;&#xD;&#xA;$$r(\zeta, x) = &#xD;&#xA;    \begin{cases}&#xD;&#xA;      f(x), &amp; 0.0 \leq \zeta \lt 0.5 \\&#xD;&#xA;      g(x), &amp; 0.5 \leq \zeta \lt 1.0&#xD;&#xA;    \end{cases}$$&#xD;&#xA;&#xD;&#xA;In this case $pdf = \frac{1}{2}$ because the pdf must integrate to 1, and there are 2 functions to choose from.&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA; 1. Randomly choose either $f(x)$ or $g(x)$ to evaluate. &#xD;&#xA; 1. Divide the result by $\frac{1}{2}$ (since there are two items)&#xD;&#xA; 1. Average&#xD;&#xA;&#xD;&#xA;As N gets large, the estimate will converge to the correct solution. &#xD;&#xA;&#xD;&#xA;We can apply this same principle to light sampling. Instead of sampling every light, we randomly pick one, and multiply the result by the number of lights (This is the same as dividing by the fractional pdf):&#xD;&#xA;&#xD;&#xA;    float3 SampleOneLight(UniformSampler *sampler, SurfaceInteraction interaction, BSDF *bsdf, Light *hitLight) const {&#xD;&#xA;        std::size_t numLights = m_scene-&gt;NumLights();&#xD;&#xA;        &#xD;&#xA;        // Return black if there are no lights&#xD;&#xA;        // And don't let a light contribute light to itself&#xD;&#xA;        // Aka, if we hit a light&#xD;&#xA;        // This is the special case where there is only 1 light&#xD;&#xA;        if (numLights == 0 || numLights == 1 &amp;&amp; hitLight != nullptr) {&#xD;&#xA;            return float3(0.0f);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Don't let a light contribute light to itself&#xD;&#xA;        // Choose another one&#xD;&#xA;        Light *light;&#xD;&#xA;        do {&#xD;&#xA;            light = m_scene-&gt;RandomOneLight(sampler);&#xD;&#xA;        } while (light == hitLight);&#xD;&#xA;&#xD;&#xA;        return numLights * EstimateDirect(light, sampler, interaction, bsdf);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In this code, all the lights have an equal chance of being picked. However, we can importance sample, if we like. For example, we can give larger lights a higher chance of being picked, or lights closer to the hit surface. You just have to divide the result by the pdf, which would no longer be $\frac{1}{\text{numLights}}$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Multiple Importance Sampling the &quot;New Ray&quot; Direction&#xD;&#xA;------------&#xD;&#xA;The current code only importance samples the &quot;New Ray&quot; direction based on the BSDF. What if we want to also importance sample based on the location of lights?&#xD;&#xA;&#xD;&#xA;Taking from what we learned above, one method would be to shoot **two** &quot;new&quot; rays and weight each based on their pdfs. However, this is both computationally expensive, and hard to implement without recursion.&#xD;&#xA;&#xD;&#xA;To overcome this, we can apply the same principles we learned by sampling only one light. That is, randomly choose one to sample, and divide by the pdf of choosing it.&#xD;&#xA;&#xD;&#xA;    // Get the new ray direction&#xD;&#xA;&#xD;&#xA;    // Randomly (uniform) choose whether to sample based on the BSDF or the Lights&#xD;&#xA;    float p = sampler-&gt;NextFloat();&#xD;&#xA;&#xD;&#xA;    Light *light = m_scene-&gt;RandomLight();&#xD;&#xA;&#xD;&#xA;    if (p &lt; 0.5f) {&#xD;&#xA;        // Choose the direction based on the bsdf &#xD;&#xA;        material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;        float bsdfPdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;        &#xD;&#xA;        float lightPdf = light-&gt;PdfLi(m_scene, interaction);&#xD;&#xA;        float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf);&#xD;&#xA;        &#xD;&#xA;        // Accumulate the throughput&#xD;&#xA;        throughput = throughput * weight * material-&gt;bsdf-&gt;Eval(interaction) / bsdfPdf;&#xD;&#xA;        &#xD;&#xA;    } else {&#xD;&#xA;        // Choose the direction based on a light&#xD;&#xA;        float lightPdf;&#xD;&#xA;        light-&gt;SampleLi(sampler, m_scene, interaction, &amp;lightPdf);&#xD;&#xA;        &#xD;&#xA;        float bsdfPdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;        float weight = PowerHeuristic(1, lightPdf, 1, bsdfPdf);&#xD;&#xA;        &#xD;&#xA;        // Accumulate the throughput&#xD;&#xA;        throughput = throughput * weight * material-&gt;bsdf-&gt;Eval(interaction) / lightPdf;&#xD;&#xA;    }&#xD;&#xA;           &#xD;&#xA;That all said, do we really ***want*** to importance sample the &quot;New Ray&quot; direction based on the light? For *direct* lighting, the radiosity is affected by both the BSDF of the surface, and the direction of the light. But for *indirect* lighting, the radiosity is almost exclusively defined by the BSDF of the surface hit before. So, adding light importance sampling doesn't give us anything. &#xD;&#xA;&#xD;&#xA;Therefore, it is common to only importance sample the &quot;New Direction&quot; with the BSDF, but apply Multiple Importance Sampling to the direct lighting.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://sites.fas.harvard.edu/~cs278/papers/veach.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13855" PostHistoryTypeId="2" PostId="5155" RevisionGUID="b549aab9-c88b-425c-bdda-d326671af080" CreationDate="2017-05-26T02:10:08.607" UserId="6705" Text="I would have done it with a script and [NETPBM](https://en.wikipedia.org/wiki/Netpbm) like so:&#xD;&#xA;&#xD;&#xA;1) reducing Image1 (the tiles) to size X by X -&gt; Image1R &#xD;&#xA;&#xD;&#xA;3) recording the mapping from pixel values of Image1R to coordinates (no need to worry about duplicates as an exact RGB match of two or more averaged pixels is unlikely)&#xD;&#xA;&#xD;&#xA;5) remapping Image2 using Image1R as the color map -&gt; Image2M&#xD;&#xA;&#xD;&#xA;6) reading pixels of Image2M, consulting the map, and picking the tile corresponding to the coordinates&#xD;&#xA;&#xD;&#xA;7) concatenating the selected tiles across and down&#xD;&#xA;&#xD;&#xA;There is a separate tool for all the above image manipulations in NETPBM.&#xD;&#xA;&#xD;&#xA;Any scripting language that allows spawning other processes and supports associative arrays, would do." ContentLicense="CC BY-SA 3.0" />
  <row Id="13856" PostHistoryTypeId="2" PostId="5156" RevisionGUID="c451409f-9186-45a3-9d15-696256069d07" CreationDate="2017-05-26T02:46:35.170" UserId="6705" Text="I have a JPEG file with a 200 dpi scan of a sample printout from a **badly maintained** old drum printer. I was able to segment it and to collect all instances of each letter together, for example&#xD;&#xA;&#xD;&#xA;[![Letters A][1]][1]&#xD;&#xA;[![Letters G][2]][2]&#xD;&#xA;[![Letters Q][3]][3]&#xD;&#xA;[![Letters W][4]][4]&#xD;&#xA;&#xD;&#xA;I would like to recreate its font; as the first step I've written a utility that estimates the shift amount (in pixels) between two images using MSE, then weighted-averages them according to that shift amount, and continues until all instances of a character have been processed. &#xD;&#xA;&#xD;&#xA;My results look like&#xD;&#xA;&#xD;&#xA;[![Sample result][5]][5]&#xD;&#xA;&#xD;&#xA;Is this the best I can hope for, or are there smarter algorithms that are able to deal with low-quality samples? &#xD;&#xA;&#xD;&#xA;Specifically, I would like to get rid of the ink smear at the top of the characters due to the rotational momentum of the drum with respect to the hammers.&#xD;&#xA;&#xD;&#xA;(As far as I understand, [super-resolution](https://en.wikipedia.org/wiki/Super-resolution_imaging) is not a good match for this task, and I couldn't find a good open source implementation of it.)&#xD;&#xA;&#xD;&#xA;The second step is to use [Potrace](https://en.wikipedia.org/wiki/Potrace), of course.&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZJqH0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rFNd6.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/x3BwS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/dEohV.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/nuumF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13857" PostHistoryTypeId="1" PostId="5156" RevisionGUID="c451409f-9186-45a3-9d15-696256069d07" CreationDate="2017-05-26T02:46:35.170" UserId="6705" Text="Recreating a font from a low-quality printout" ContentLicense="CC BY-SA 3.0" />
  <row Id="13858" PostHistoryTypeId="3" PostId="5156" RevisionGUID="c451409f-9186-45a3-9d15-696256069d07" CreationDate="2017-05-26T02:46:35.170" UserId="6705" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13861" PostHistoryTypeId="5" PostId="5155" RevisionGUID="44c9e666-2e21-4c16-abc5-2127b90963cf" CreationDate="2017-05-26T03:15:06.213" UserId="6705" Comment="edited body" Text="I would have done it with a script and [NETPBM](https://en.wikipedia.org/wiki/Netpbm) like so:&#xD;&#xA;&#xD;&#xA;1) reducing Image1 (the tiles) to size X by X -&gt; Image1R &#xD;&#xA;&#xD;&#xA;2) recording the mapping from pixel values of Image1R to coordinates (no need to worry about duplicates as an exact RGB match of two or more averaged pixels is unlikely)&#xD;&#xA;&#xD;&#xA;3) remapping Image2 using Image1R as the color map -&gt; Image2M&#xD;&#xA;&#xD;&#xA;4) reading pixels of Image2M, consulting the map, and picking the tile corresponding to the coordinates&#xD;&#xA;&#xD;&#xA;5) concatenating the selected tiles across and down&#xD;&#xA;&#xD;&#xA;There is a separate tool for all the above image manipulations in NETPBM.&#xD;&#xA;&#xD;&#xA;Any scripting language that allows spawning other processes and supports associative arrays, would do." ContentLicense="CC BY-SA 3.0" />
  <row Id="13862" PostHistoryTypeId="5" PostId="3834" RevisionGUID="06ecd87e-316d-4dee-960f-45e37a86b539" CreationDate="2017-05-26T05:22:25.380" UserId="182" Comment="Fixed a few minor typos and reworded a little." Text="I am a newbie in computer graphics and I am trying to develop a special case of path tracing really slowly! But first: I came up studying the Mitsuba renderer and one of its uses in the so-called GDPT (Gradient Domain Path Tracer). I am trying to build a Cornell Box in this framework and my silly problem arises in realizing which kind of material is a &quot;mirror&quot;. In simpler words: I want a mirroring sphere in my scene but I don't manage to create it. According to the documentation that you can find here (http://www.mitsuba-renderer.org/releases/current/documentation.pdf) we can have all the different surfaces explained in section 8.2, which are:&#xD;&#xA;&#xD;&#xA; - Smooth Diffuse material (diffuse)&#xD;&#xA; - Rough diffuse material (roughdiffuse) &#xD;&#xA; - Smooth dielectric material (dielectric)&#xD;&#xA; - Thin dielectric material (thindielectric)&#xD;&#xA; - Rough dielectric material  (roughdielectric)&#xD;&#xA; - Smooth conductor (conductor)&#xD;&#xA; - Rough conductor material (roughconductor)&#xD;&#xA; - Smooth plastic material (plastic)&#xD;&#xA; - Rough   plastic material (roughplastic)&#xD;&#xA; - Smooth dielectric coating (coating)&#xD;&#xA; - Rough dielectric coating (roughcoating)&#xD;&#xA;&#xD;&#xA;Can you please help me understand what set of parameters will make a mirroring surface material?&#xD;&#xA;&#xD;&#xA;Usually for each kind of material there is a reference XML code (which is what I am using to build the scene). Therefore, the main question remains understanding how to build a mirror, but please take those examples in considerations because the parameters in those are the only things I can tune. Thanks in advance!" ContentLicense="CC BY-SA 3.0" />
  <row Id="13863" PostHistoryTypeId="4" PostId="3834" RevisionGUID="06ecd87e-316d-4dee-960f-45e37a86b539" CreationDate="2017-05-26T05:22:25.380" UserId="182" Comment="Fixed a few minor typos and reworded a little." Text="How to create specular surface in Mitsuba Renderer" ContentLicense="CC BY-SA 3.0" />
  <row Id="13864" PostHistoryTypeId="2" PostId="5157" RevisionGUID="c963a6ad-0bd4-4420-9229-99b55e30ecc8" CreationDate="2017-05-27T12:47:12.710" UserId="6682" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After thinking about it for some days I came up with a proof sketch (which is hopefully correct) that it is possible to use Gouraud shading on disconnected triangles, if they share an edge with the same normals as in the picture. The simple idea of this proof is to check that there is no discontinuity between the intensity of the triangles by approaching from each side to the edge. So given two triangles $T_1: (P_1,P_2,P_3)$ and $T_2: (P_1', P_2', P_3')$ which share an edge and let's assume w.l.o.g. that this edges are constructed by $(P_2,P_3)$ and $(P_2', P_3')$. Because Gouraud shading only computes the light intensity at the vertex positions and interpolate in between them, it's save to assume that the intensity at $P_2$ is the same as on $P_2'$, same goes for $I_3$. Because it's also save to assume that the values inside the triangles are getting computed correctly so it's only necessary to show that there is no discontinuity between the triangles. To interpolate inside the triangle it's&#xD;&#xA;rational to use Barycentric coordinates so that the intensity at any point inside the triangle is given by&#xD;&#xA;\begin{align*}&#xD;&#xA;	I  &amp;= aI_2   + bI_3   + (1 - (a+b)) I_1\\&#xD;&#xA;	I' &amp;= a'I_2' + b'I_3' + (1 - (a'+b')) I_1'&#xD;&#xA;\end{align*}&#xD;&#xA;By now going from I_1 respectively I_1' to the edge a sequence can be constructed&#xD;&#xA;to archive by setting $a_n = \frac{c}{n+1}, b_n=\frac{d}{n+1}, c + d = 1$ &#xD;&#xA;and analogously for $a_n', b_n'$. Then the intensity is&#xD;&#xA;\begin{align*}&#xD;&#xA;	I_n  &amp;= \frac{c}{n+1} I_2  + \frac{d}{n+1} I_3  + (1 - \frac{c+d}{n+1}) I_1\\&#xD;&#xA;	I_n' &amp;= \frac{c'}{n+1}I_2' + \frac{d'}{n+1}I_3' + (1 - \frac{c'+d'}{n+1}) I_1'&#xD;&#xA;\end{align*}&#xD;&#xA;If one now approaches the edge with:&#xD;&#xA;\begin{align*}&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} I_n = cI_2 + dI_3\\&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} I_n' = c'I_2 + d'I_3'&#xD;&#xA;\end{align*}&#xD;&#xA;and using the requirement that $I_n$ and $I_n'$ share the same position $P_n$&#xD;&#xA;which can be constructed by&#xD;&#xA;\begin{align*}&#xD;&#xA;	P_n &amp;= \frac{c}{n+1} P_2  + \frac{d}{n+1} P_3  + (1 - \frac{c+d}{n+1}) P_1\\&#xD;&#xA;	P_n &amp;= \frac{c'}{n+1}P_2' + \frac{d'}{n+1}P_3' + (1 - \frac{c'+d'}{n+1}) P_1'&#xD;&#xA;\end{align*}&#xD;&#xA;with the fact that $P_2 =P_2$ and $P_3 = P_3'$ it follows:&#xD;&#xA;\begin{align*}&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n = cP_2 + dP_3\\&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n' = c'P_2 + d'P_3&#xD;&#xA;\end{align*}&#xD;&#xA;and $d = 1 - c$&#xD;&#xA;\begin{align*}&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n = cP_2 + (1-c)P_3\\&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n' = c'P_2 + (1-c')P_3&#xD;&#xA;\end{align*}&#xD;&#xA;this results in $c = c'$ and therefore this gives the final result:&#xD;&#xA;\begin{align*}&#xD;&#xA;	\lim\limits_{n\rightarrow 0^+} I_n = cI_2 + (1-c)I_3 = c'I_2' + (1-c')I_3' = \lim\limits_{n\rightarrow 0^+}I_n'&#xD;&#xA;\end{align*}&#xD;&#xA;Thereby is possible to use Gouraud shading over disconnected triangles as in my case because the intensity on the edge is the same on both triangles.&#xD;&#xA;&#xD;&#xA;What actually happened in my case was, that the normals differs slightly (thank you @Rahul for the tip) which therefore results in this strange look. I fixed them by averaging the normals over a small radius to ensure&#xD;&#xA;the proper set up of the normals.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TTgLw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13872" PostHistoryTypeId="2" PostId="5160" RevisionGUID="e5b02e66-e397-478f-850b-6112ec189d84" CreationDate="2017-05-27T16:37:52.760" UserId="5256" Text="Is there a material table that lists all the specific values to obtain a certain type of material (e.g: copper or asphalt) available? &#xD;&#xA;&#xD;&#xA;I found this table in the paper: [A Reflectance Model for Computer Graphics][1]. However, it doesn't really seem to have all the materials I would like to use.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Currently I am looking for a material table for use in a Path Tracer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://inst.cs.berkeley.edu/~cs294-13/fa09/lectures/cookpaper.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/eX6TB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13873" PostHistoryTypeId="1" PostId="5160" RevisionGUID="e5b02e66-e397-478f-850b-6112ec189d84" CreationDate="2017-05-27T16:37:52.760" UserId="5256" Text="Is there a material table for the Cook Torrance BRDF?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13874" PostHistoryTypeId="3" PostId="5160" RevisionGUID="e5b02e66-e397-478f-850b-6112ec189d84" CreationDate="2017-05-27T16:37:52.760" UserId="5256" Text="|brdf|physically-based|pbr|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13875" PostHistoryTypeId="2" PostId="5161" RevisionGUID="6264b789-b2a5-428b-8836-47818dd01c7f" CreationDate="2017-05-27T17:06:03.013" UserId="6715" Text="I'm adding photon mapping to my current raytracer to add indirect lighting.&#xD;&#xA;&#xD;&#xA;Can someone explain how the radiance estimate works in simple terms and with some simple math? I have read a lot of documents about it online, but the math is beyond my understanding so far. I have used Lambertian and Phong shading in my raytracer, so I'm thinking of using that. Next, how do you add up the power of nearby photons at a point? I see a lot of papers that say you have to divide by the number of photons shot, but doesn't that reduce the power of a photon by way too much? (say divide it by a million photons...)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;TLDR: Explain how radiance estimate works in detail but with simple math." ContentLicense="CC BY-SA 3.0" />
  <row Id="13876" PostHistoryTypeId="1" PostId="5161" RevisionGUID="6264b789-b2a5-428b-8836-47818dd01c7f" CreationDate="2017-05-27T17:06:03.013" UserId="6715" Text="Explain Radiance Estimate for photon mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="13877" PostHistoryTypeId="3" PostId="5161" RevisionGUID="6264b789-b2a5-428b-8836-47818dd01c7f" CreationDate="2017-05-27T17:06:03.013" UserId="6715" Text="|raytracing|brdf|photon-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13878" PostHistoryTypeId="5" PostId="5156" RevisionGUID="df475861-30b0-4e36-8315-a66ebc66a88b" CreationDate="2017-05-27T17:35:20.040" UserId="6705" Comment="Added links to data" Text="I have a JPEG file with a [200 dpi scan of a sample printout](https://www.dropbox.com/s/01ygrkzlhylu612/ACPU-128.jpg?dl=0) from a **badly maintained** old drum printer. I was able to segment it and to collect [all instances of each letter together](https://www.dropbox.com/s/doc2bzh155mey26/tiles.zip?dl=0), for example&#xD;&#xA;&#xD;&#xA;[![Letters A][1]][1]&#xD;&#xA;[![Letters G][2]][2]&#xD;&#xA;[![Letters Q][3]][3]&#xD;&#xA;[![Letters W][4]][4]&#xD;&#xA;&#xD;&#xA;I would like to recreate its font; as the first step I've written a utility that estimates the shift amount (in pixels) between two images using MSE, then weighted-averages them according to that shift amount, and continues until all instances of a character have been processed. &#xD;&#xA;&#xD;&#xA;My results look like&#xD;&#xA;&#xD;&#xA;[![Sample result][5]][5]&#xD;&#xA;&#xD;&#xA;Is this the best I can hope for, or are there smarter algorithms that are able to deal with low-quality samples? &#xD;&#xA;&#xD;&#xA;Specifically, I would like to get rid of the ink smear at the top of the characters due to the rotational momentum of the drum with respect to the hammers.&#xD;&#xA;&#xD;&#xA;(As far as I understand, [super-resolution](https://en.wikipedia.org/wiki/Super-resolution_imaging) is not a good match for this task, and I couldn't find a good open source implementation of it.)&#xD;&#xA;&#xD;&#xA;The second step is to use [Potrace](https://en.wikipedia.org/wiki/Potrace), of course.&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZJqH0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rFNd6.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/x3BwS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/dEohV.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/nuumF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13879" PostHistoryTypeId="5" PostId="5157" RevisionGUID="8b5640b5-ad69-4ca3-ab79-a05c035a772e" CreationDate="2017-05-27T17:46:29.623" UserId="6682" Comment="Fixed math typos " Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After thinking about it for some days I came up with a proof sketch (which is hopefully correct) that it is possible to use Gouraud shading on disconnected triangles, if they share an edge with the same normals as in the picture. The simple idea of this proof is to check that there is no discontinuity between the intensity of the triangles by approaching from each side to the edge. So given two triangles $T_1: (P_1,P_2,P_3)$ and $T_2: (P_1', P_2', P_3')$ which share an edge and let's assume w.l.o.g. that this edges are constructed by $(P_2,P_3)$ and $(P_2', P_3')$. Because Gouraud shading only computes the light intensity at the vertex positions and interpolate in between them, it's save to assume that the intensity at $P_2$ is the same as on $P_2'$, same goes for $P_3$ and $P_3'$. Because it's also save to assume that the values inside the triangles are getting computed correctly so it's only necessary to show that there is no discontinuity between the triangles. To interpolate inside the triangle it's rational to use Barycentric coordinates so that the intensity at any point inside the triangle is given by&#xD;&#xA;\begin{align*}&#xD;&#xA;	I  &amp;= aI_2   + bI_3   + (1 - (a+b)) I_1\\&#xD;&#xA;	I' &amp;= a'I_2' + b'I_3' + (1 - (a'+b')) I_1'&#xD;&#xA;\end{align*}&#xD;&#xA;By now going from $I_1$ respectively $I_1'$ to the edge, a sequence can be constructed to archive this, by setting $a_n = \frac{c}{n+1}, b_n=\frac{d}{n+1}, c + d = 1$ and analogously for $a_n', b_n'$. Then the intensity is&#xD;&#xA;\begin{align*}&#xD;&#xA;	I_n  &amp;= \frac{c}{n+1} I_2  + \frac{d}{n+1} I_3  + (1 - \frac{c+d}{n+1}) I_1\\&#xD;&#xA;	I_n' &amp;= \frac{c'}{n+1}I_2' + \frac{d'}{n+1}I_3' + (1 - \frac{c'+d'}{n+1}) I_1'&#xD;&#xA;\end{align*}&#xD;&#xA;If one now approaches the edge with:&#xD;&#xA;\begin{align*}&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} I_n = cI_2 + dI_3\\&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} I_n' = c'I_2 + d'I_3'&#xD;&#xA;\end{align*}&#xD;&#xA;and using the requirement that $I_n$ and $I_n'$ share the same position $P_n$ if they are on an edge, which can be constructed by&#xD;&#xA;\begin{align*}&#xD;&#xA;	P_n &amp;= \frac{c}{n+1} P_2  + \frac{d}{n+1} P_3  + (1 - \frac{c+d}{n+1}) P_1\\&#xD;&#xA;	P_n &amp;= \frac{c'}{n+1}P_2' + \frac{d'}{n+1}P_3' + (1 - \frac{c'+d'}{n+1}) P_1'&#xD;&#xA;\end{align*}&#xD;&#xA;with the fact that $P_2 =P_2'$ and $P_3 = P_3'$ it follows:&#xD;&#xA;\begin{align*}&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n = cP_2 + dP_3\\&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n' = c'P_2 + d'P_3&#xD;&#xA;\end{align*}&#xD;&#xA;and $d = 1 - c$&#xD;&#xA;\begin{align*}&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n = cP_2 + (1-c)P_3\\&#xD;&#xA;	&amp;\lim\limits_{n\rightarrow 0^+} P_n' = c'P_2 + (1-c')P_3&#xD;&#xA;\end{align*}&#xD;&#xA;this results in $c = c'$ and therefore this gives the final result:&#xD;&#xA;\begin{align*}&#xD;&#xA;	\lim\limits_{n\rightarrow 0^+} I_n = cI_2 + (1-c)I_3 = c'I_2' + (1-c')I_3' = \lim\limits_{n\rightarrow 0^+}I_n'&#xD;&#xA;\end{align*}&#xD;&#xA;Thereby is possible to use Gouraud shading over disconnected triangles as in my case, because the intensity on the edge is the same on both triangles.&#xD;&#xA;&#xD;&#xA;What actually happened in my case was that the normals differs slightly (thank you @Rahul for the tip) which therefore results in this strange look. I fixed them by averaging the normals over a small radius to ensure&#xD;&#xA;the proper set up of the normals.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TTgLw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13891" PostHistoryTypeId="50" PostId="4917" RevisionGUID="31061f5f-2d4e-4762-b11f-dfebd6441a0b" CreationDate="2017-05-28T10:35:51.123" UserId="-1" />
  <row Id="13894" PostHistoryTypeId="2" PostId="5166" RevisionGUID="eccba0c7-fd7d-4251-9fe8-7c9dc116d098" CreationDate="2017-05-28T12:14:54.733" UserId="5256" Text="How can I a find the Light Direction/Ray from a Point on a surface to an Area Light? Is there a universal technique to do this for all types of lights (circle, rectangle, sphere &amp; tube)?&#xD;&#xA;&#xD;&#xA;This is for area lighting in a ray tracer. &#xD;&#xA;&#xD;&#xA;For example for a point light I know it can be done like this:&#xD;&#xA;&#xD;&#xA;    class PointLight : public Light &#xD;&#xA;    { &#xD;&#xA;        Vec3f pos; &#xD;&#xA;    public: &#xD;&#xA;        PointLight(const Matrix44f &amp;l2w, const Vec3f &amp;c = 1, const float &amp;i = 1) : Light(l2w, c, i) &#xD;&#xA;        { l2w.multVecMatrix(Vec3f(0), pos); } &#xD;&#xA;        // P: is the shaded point&#xD;&#xA;        void getDirectionAndIntensity(const Vec3f &amp;P, Vec3f &amp;lightDir, Vec3f &amp;lightIntensity) const &#xD;&#xA;        { &#xD;&#xA;            lightDir = pos - P; // compute light direction &#xD;&#xA;            float r2 = lightDir.norm(); &#xD;&#xA;            lightDir.normalize(); &#xD;&#xA;            lightIntensity = intensity * color / (4 * M_PI * r2); &#xD;&#xA;        } &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13895" PostHistoryTypeId="1" PostId="5166" RevisionGUID="eccba0c7-fd7d-4251-9fe8-7c9dc116d098" CreationDate="2017-05-28T12:14:54.733" UserId="5256" Text="How to find Light Direction from a Point to Area Light" ContentLicense="CC BY-SA 3.0" />
  <row Id="13896" PostHistoryTypeId="3" PostId="5166" RevisionGUID="eccba0c7-fd7d-4251-9fe8-7c9dc116d098" CreationDate="2017-05-28T12:14:54.733" UserId="5256" Text="|raytracing|lighting|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13897" PostHistoryTypeId="5" PostId="5166" RevisionGUID="21eb0273-dc74-4656-a136-b175afb8dd63" CreationDate="2017-05-28T12:29:28.813" UserId="5256" Comment="added 196 characters in body; edited title" Text="How can I a find the Light Direction/Ray from a Point on a surface to an Area Light? Is there a universal technique to do this for all types of lights (circle, rectangle, sphere &amp; tube)?&#xD;&#xA;&#xD;&#xA;Although this is for area lighting in a ray tracer, is there another way to implement area lighting through an emissive value that I can apply to any object or surface (I have seen this mentioned online)? As opposed to doing it like this. &#xD;&#xA;&#xD;&#xA;For example for a point light I know it can be done like this:&#xD;&#xA;&#xD;&#xA;    class PointLight : public Light &#xD;&#xA;    { &#xD;&#xA;        Vec3f pos; &#xD;&#xA;    public: &#xD;&#xA;        PointLight(const Matrix44f &amp;l2w, const Vec3f &amp;c = 1, const float &amp;i = 1) : Light(l2w, c, i) &#xD;&#xA;        { l2w.multVecMatrix(Vec3f(0), pos); } &#xD;&#xA;        // P: is the shaded point&#xD;&#xA;        void getDirectionAndIntensity(const Vec3f &amp;P, Vec3f &amp;lightDir, Vec3f &amp;lightIntensity) const &#xD;&#xA;        { &#xD;&#xA;            lightDir = pos - P; // compute light direction &#xD;&#xA;            float r2 = lightDir.norm(); &#xD;&#xA;            lightDir.normalize(); &#xD;&#xA;            lightIntensity = intensity * color / (4 * M_PI * r2); &#xD;&#xA;        } &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13898" PostHistoryTypeId="4" PostId="5166" RevisionGUID="21eb0273-dc74-4656-a136-b175afb8dd63" CreationDate="2017-05-28T12:29:28.813" UserId="5256" Comment="added 196 characters in body; edited title" Text="How to find Light Direction from a Point on a surface to an Area Light" ContentLicense="CC BY-SA 3.0" />
  <row Id="13899" PostHistoryTypeId="2" PostId="5167" RevisionGUID="1104d7fa-2fb4-49a5-8d4d-81f22699c9da" CreationDate="2017-05-28T13:33:44.313" UserId="6682" Text="One way to achieve this, is using the same approach as POV-Ray wich uses multiple point lights to create an area light (as mentioned [here](http://www.povray.org/documentation/view/3.6.2/38/)) by aligning them into an array. This should also work for arbitrary surfaces if you approximate them through point lights. This has also the benefit that you don't need to change much of your code." ContentLicense="CC BY-SA 3.0" />
  <row Id="13900" PostHistoryTypeId="2" PostId="5168" RevisionGUID="d9400fa2-cf23-4a0f-97c2-d5c5c1b93bf2" CreationDate="2017-05-28T17:17:58.473" UserId="6722" Text=" Look at this image[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jVP0a.jpg&#xD;&#xA;&#xD;&#xA; This is CG, Saya, a project meant to make as real of CG as possible to the point of becoming indistinguishable from reality. I would say that it is pretty believable. But, it still doesn't seem real enough, somethings missing. And i don't know what it is. And it drives me nuts. &#xD;&#xA;&#xD;&#xA; I am not saying that CG has to do reality, i am personaly fond of stylization, but i really want to know why we can't get a 3d image just right yet.&#xD;&#xA;&#xD;&#xA; Is it the light? The clothing? The lines above the lip, too defined?&#xD;&#xA;&#xD;&#xA; Any opinion would be appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="13901" PostHistoryTypeId="1" PostId="5168" RevisionGUID="d9400fa2-cf23-4a0f-97c2-d5c5c1b93bf2" CreationDate="2017-05-28T17:17:58.473" UserId="6722" Text="What is missing in CG that stops it from looking like a photograph?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13902" PostHistoryTypeId="3" PostId="5168" RevisionGUID="d9400fa2-cf23-4a0f-97c2-d5c5c1b93bf2" CreationDate="2017-05-28T17:17:58.473" UserId="6722" Text="|rendering|texture|3d|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13904" PostHistoryTypeId="2" PostId="5169" RevisionGUID="2818320a-c20e-47ed-bd58-caed3b870adb" CreationDate="2017-05-29T10:53:30.840" UserId="5225" Text="I'm following [this tutorial](https://learnopengl.com/#!Getting-started/Coordinate-Systems) on the perspective projection.&#xD;&#xA;&#xD;&#xA;**Question:** If the point of a perspective projection is to create the perspective effect (where objects faraway appear to be smaller):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;then why does it generate a frustrum in which the **back** is larger than the **front**? Should it be the other way around?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/W1LpU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jBNlH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13905" PostHistoryTypeId="1" PostId="5169" RevisionGUID="2818320a-c20e-47ed-bd58-caed3b870adb" CreationDate="2017-05-29T10:53:30.840" UserId="5225" Text="Why is the back of a perspective frustrum larger than the front?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13906" PostHistoryTypeId="3" PostId="5169" RevisionGUID="2818320a-c20e-47ed-bd58-caed3b870adb" CreationDate="2017-05-29T10:53:30.840" UserId="5225" Text="|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13907" PostHistoryTypeId="2" PostId="5170" RevisionGUID="253750c1-7234-4549-9364-ec1a5c305c63" CreationDate="2017-05-29T11:05:43.390" UserId="38" Text="It is bigger because it fills the same view and it ts further away. It would be smaller if it wouldn't fill the same view but then it wouldn't fill the camera view and it wouldnt work.&#xD;&#xA;&#xD;&#xA;So the inverse relation applies. If you want something to stay constant in size in the view then it needs to grow as it gets further. &#xD;&#xA;&#xD;&#xA;Your just comparing apples with oranges." ContentLicense="CC BY-SA 3.0" />
  <row Id="13908" PostHistoryTypeId="5" PostId="5170" RevisionGUID="11c8f9f2-5fe6-4dcd-b4f2-4e5a4aa5bf07" CreationDate="2017-05-29T11:10:49.933" UserId="38" Comment="added 1 character in body" Text="It is bigger because it fills the same view and it ts further away. It would be smaller if it wouldn't fill the same view but then it wouldn't fill the camera view and it wouldnt work.&#xD;&#xA;&#xD;&#xA;So the inverse relation applies. If you want something to stay constant in size in the view then it needs to grow as it gets further. &#xD;&#xA;&#xD;&#xA;Your just comparing apples with oranges. " ContentLicense="CC BY-SA 3.0" />
  <row Id="13912" PostHistoryTypeId="4" PostId="5168" RevisionGUID="d7494096-431a-4c11-a22e-a1b3648626b9" CreationDate="2017-05-29T12:28:47.407" UserId="231" Comment="Edit title to be less broad" Text="What is missing in this image that stops it from looking like a photograph?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13913" PostHistoryTypeId="2" PostId="5172" RevisionGUID="4a8a25ba-8715-4e99-90fe-71af636880e1" CreationDate="2017-05-29T12:32:11.353" UserId="6727" Text="if you place your hand by your ear, you can't see it ... now then if you move it forward, suddenly you'll start seeing it ... this is what the frustrum represents, as in your second picture... " ContentLicense="CC BY-SA 3.0" />
  <row Id="13914" PostHistoryTypeId="5" PostId="5168" RevisionGUID="c320fea1-fbc3-4682-84f1-1175d5848953" CreationDate="2017-05-29T12:45:46.750" UserId="231" Comment="Typos" Text=" Look at this image:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is CG, Saya, a project meant to make as real CG as possible to the point of becoming indistinguishable from reality. I would say that it is pretty believable. But, it still doesn't seem real enough, something's missing. And I don't know what it is. And it drives me nuts. &#xD;&#xA;&#xD;&#xA;I am not saying that CG has to do reality, I am personaly fond of stylization, but I really want to know why we can't get a 3d image just right yet.&#xD;&#xA;&#xD;&#xA;Is it the light? The clothing? The lines above the lip, too defined?&#xD;&#xA;&#xD;&#xA;Any insights would be appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jVP0a.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="13915" PostHistoryTypeId="2" PostId="5173" RevisionGUID="afc7152e-3282-4789-adb7-2e4268130dcc" CreationDate="2017-05-29T13:22:58.040" UserId="231" Text="It might help to think of it this way:&#xD;&#xA;&#xD;&#xA;Both the near plane and the far plane are the size that will fit onto the screen you are viewing on. The further away something is, the bigger it can be and still fit on the screen. Close up, a playing card can fill the whole screen, but in the distance, an entire building can fit on the screen.&#xD;&#xA;&#xD;&#xA;Consider the example image:&#xD;&#xA;&#xD;&#xA;[![image of near and far plane][image of near and far plane]][image of near and far plane]&#xD;&#xA;&#xD;&#xA;If a playing card exactly fills the near plane, then you will be able to fit 4 playing cards on the far plane. This reflects the fact that when a playing card is twice as far from the camera, it appears to have half the height and width.&#xD;&#xA;&#xD;&#xA;Think of the near plane and the far plane as simply the area that will fit on your screen. The further away you point your camera, the more will fit on the screen. This matches up with the fact that things look smaller in the distance - this means you can fit bigger things on the screen if they are further away.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [image of near and far plane]: https://i.stack.imgur.com/jBNlH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13916" PostHistoryTypeId="2" PostId="5174" RevisionGUID="69f67a0b-f5ac-4c2a-95e4-828b3ca44641" CreationDate="2017-05-29T13:34:06.867" UserId="5717" Text="- The hair seems to have sampling noise or aliasing in it. This *might* be poor jpeg compression but it does not look like it.&#xD;&#xA;- I've never seen hair part that way (could just be me).&#xD;&#xA;- The neck looks a little too regular (I'm no modeler though).&#xD;&#xA;- The skin's subsurface scattering falls a bit short. Perhaps it's not that but there is something slightly off about the skin.&#xD;&#xA;- The shirt has a slight plastic feel to it.&#xD;&#xA;&#xD;&#xA;Most of this is entirely subjective of course. I think it's fairly good but falls short of the state of the art in many areas." ContentLicense="CC BY-SA 3.0" />
  <row Id="13920" PostHistoryTypeId="2" PostId="5175" RevisionGUID="8abe77cc-704a-47d0-b548-3c62eedfdd0c" CreationDate="2017-05-29T21:22:31.583" UserId="6160" Text="I suppose you'd like to hear the first impression, so to say.&#xD;&#xA;So here are most notable features that uncover the 'synthetic' nature of the image (for my eye).&#xD;&#xA;&#xD;&#xA;- Too smooth textures on the shirt. In real world &#xD;&#xA;every textile is imperfect, regardless how smooth it is and how good the lights are set up.&#xD;&#xA;There is always visible 'grain' and imperfection of textures, but i suppose it is next to impossible&#xD;&#xA;to model due to complexity of real shadow plays. &#xD;&#xA;So on this image the shirt has most noticable &quot;plastic&quot; look.&#xD;&#xA;Face is a bit too smooth textured, but this could be percieved as, say too much cosmetics. So&#xD;&#xA;in general the head looks quite real.&#xD;&#xA;- Shadows, contrast. Every detail of real objects has very different contrast zones of shadows. &#xD;&#xA;Here again on the shirt around the neck and especially near the stud:  there is simply too little&#xD;&#xA;contrast diversity or too simple shadows, as if the objects are flat. &#xD;&#xA;&#xD;&#xA;And something is wrong with her ear, no? but it is hard to say what is it exactly. " ContentLicense="CC BY-SA 3.0" />
  <row Id="13921" PostHistoryTypeId="5" PostId="5175" RevisionGUID="d01ca82a-bbe6-40ac-8dfa-9ca33ea88a4c" CreationDate="2017-05-29T21:42:20.827" UserId="6160" Comment="added 112 characters in body" Text="I suppose you'd like to hear the first impression, so to say.&#xD;&#xA;So here are most notable features that uncover the 'synthetic' nature of the image (for my eye).&#xD;&#xA;&#xD;&#xA;- Too smooth textures on the shirt. In real world &#xD;&#xA;every textile is imperfect, regardless how smooth it is and how good the lights are set up.&#xD;&#xA;There is always visible 'grain' and imperfection of textures, but i suppose it is next to impossible&#xD;&#xA;to model due to complexity of real shadow plays. &#xD;&#xA;So on this image the shirt has most noticable &quot;plastic&quot; look.&#xD;&#xA;Face is a bit too smooth textured, but this could be percieved as, say too much cosmetics. So&#xD;&#xA;in general the head looks quite real.&#xD;&#xA;- Shadows, contrast. Every detail of real objects has very different contrast zones of shadows. &#xD;&#xA;Here again on the shirt around the neck and especially near the stud:  there is simply too little&#xD;&#xA;contrast diversity or too simple shadows, as if the objects are flat. &#xD;&#xA;- Focus of the camera. It is rarely seen on real fotos that all parts of the portrait have equally sharp focus&#xD;&#xA;&#xD;&#xA;And something is wrong with her ear, no? but it is hard to say what is it exactly. " ContentLicense="CC BY-SA 3.0" />
  <row Id="13926" PostHistoryTypeId="50" PostId="4760" RevisionGUID="f0def6bb-bcdf-48d2-9c73-627c6a6a6785" CreationDate="2017-05-30T12:10:53.293" UserId="-1" />
  <row Id="13927" PostHistoryTypeId="2" PostId="5177" RevisionGUID="3711971a-dea9-4ddc-a784-1a77ec3e2f92" CreationDate="2017-05-30T13:36:02.933" UserId="1952" Text="If you want to use only one sample to approximate analytical area lighting (e.g. for real-time applications), you can use Most Representative Point (MRP) approximation as described in &quot;[Lighting in Killzone Shadow Fall][1]&quot;, &quot;[Real Shading in Unreal Engine 4][2]&quot; and &quot;[Moving Frostbite to PBR][3]&quot;. This works reasonably well for specular approximation, though the energy conservation is a challenge. What I have found working best is to find a point on a light source with smallest angle from the view reflection vector, and the solution depends on the shape of the light (for example [here's my solution for rectangular lights][4]).&#xD;&#xA;&#xD;&#xA;For diffuse evaluation there are numerical and analytical approximations depending on light shape presented in the papers, which also properly handle the horizon case. You can also try to use MRP for diffuse lighting, but I haven't found good approximations for it. Depending your application though diffuse MRP might result in feasible quality.&#xD;&#xA;&#xD;&#xA;There's also some more recent work for evaluating area lighting integrals not using MRP. &quot;[Accurate Analytic Approximations For Real-Time Specular Area Lighting][5]&quot; deals with the specular evaluation via edge integrals, though I recall this method is patented. &quot;[Real-Time Polygonal-Light Shading with Linearly Transformed Cosines][6]&quot; looks quite promising, but I haven't checked the paper in more details.&#xD;&#xA;&#xD;&#xA;For non-real time applications and ray tracing area lighting is fundamentally and mathematically much simpler problem. For your integrator you just check the incident radiance at each sample (ray intersection with the scene) and accumulate results for total radiance towards the output direction. The challenge is how to reduce variance of your integrator, but getting basic area lighting to work in a ray tracer is relatively simple.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.guerrilla-games.com/read/killzone-shadow-fall-creating-art-tools-for-a-new-generation&#xD;&#xA;  [2]: https://de45xmedrsdbp.cloudfront.net/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [3]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr_v2.pdf&#xD;&#xA;  [4]: https://math.stackexchange.com/questions/1438242/finding-ray-direction-with-smallest-angle-from-a-ray-to-a-rectangle-in-3d&#xD;&#xA;  [5]: http://jmarvie.free.fr/Publis/2016_I3D/i3d_2016_AccurateAnalyticApproximationsForReal-TimeSpecularAreaLighting.pdf&#xD;&#xA;  [6]: https://eheitzresearch.wordpress.com/415-2/" ContentLicense="CC BY-SA 3.0" />
  <row Id="13928" PostHistoryTypeId="2" PostId="5178" RevisionGUID="53c90810-749f-4a40-9f34-7e784ba18f34" CreationDate="2017-05-30T15:05:58.273" UserId="5256" Text="How is measured BRDF data recorded? Like the [MERL BRDF Database][1].&#xD;&#xA;&#xD;&#xA;What kind of equipment is used and what are the key values that need to be recorded?&#xD;&#xA;&#xD;&#xA;I know one place this data was used was in the [Disney PBR paper][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.merl.com/brdf/&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="13929" PostHistoryTypeId="1" PostId="5178" RevisionGUID="53c90810-749f-4a40-9f34-7e784ba18f34" CreationDate="2017-05-30T15:05:58.273" UserId="5256" Text="How is measured BRDF data recorded?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13930" PostHistoryTypeId="3" PostId="5178" RevisionGUID="53c90810-749f-4a40-9f34-7e784ba18f34" CreationDate="2017-05-30T15:05:58.273" UserId="5256" Text="|raytracing|pathtracing|brdf|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13931" PostHistoryTypeId="2" PostId="5179" RevisionGUID="d443eb07-642d-4eb5-a7ed-c6a79fe09fee" CreationDate="2017-05-30T15:52:40.287" UserId="5717" Text="Section 6 of [Microfacet Models for Refraction through Rough Surfaces][1] has a good description of how they did it to validate their own model. That may not be everything needed to build a full database (eg. more automation) but it's an interesting read.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="13936" PostHistoryTypeId="2" PostId="5181" RevisionGUID="7111794b-1cfb-4e8e-94cb-1df4dbd1b007" CreationDate="2017-05-30T19:47:21.487" UserId="5256" Text="How are fluid simulations handled in Computer Graphics? For a novice, there are hardly any novice friendly tutorials explaining how particles or fluids can be simulated.&#xD;&#xA;&#xD;&#xA;Things like smoke, crown splashes and fog are they animated by artists as opposed to physically based simulations? &#xD;&#xA;&#xD;&#xA;If there are any worthwhile resources that you could recommend please do! :)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13937" PostHistoryTypeId="1" PostId="5181" RevisionGUID="7111794b-1cfb-4e8e-94cb-1df4dbd1b007" CreationDate="2017-05-30T19:47:21.487" UserId="5256" Text="How are fluid simulations handled in Computer Graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13938" PostHistoryTypeId="3" PostId="5181" RevisionGUID="7111794b-1cfb-4e8e-94cb-1df4dbd1b007" CreationDate="2017-05-30T19:47:21.487" UserId="5256" Text="|animation|pbr|simulation|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13939" PostHistoryTypeId="2" PostId="5182" RevisionGUID="37cef116-7a40-4d8d-940f-89e7ee4e1677" CreationDate="2017-05-30T20:47:55.340" UserId="2736" Text="I've seen a Fresnel equation for calculating the reflection amount at *incidence angle* with *n* and *k* values defined. This formula usually comes up in relation to computer graphics, but I can't find this equation anywhere in a science context. &#xD;&#xA;&#xD;&#xA;Here is an example written in Python, taken from this website:&#xD;&#xA;[Fresnel Formula in python][1]&#xD;&#xA;&#xD;&#xA;Here's the code:&#xD;&#xA;&#xD;&#xA;    def IOR(n,k):&#xD;&#xA;    theta_deg = 0&#xD;&#xA;    &#xD;&#xA;    n = n&#xD;&#xA;    k = k&#xD;&#xA;    fresnel = []&#xD;&#xA;      &#xD;&#xA;    while theta_deg &lt;= 90:&#xD;&#xA;    theta = math.radians(theta_deg)&#xD;&#xA;    &#xD;&#xA;    a = math.sqrt((math.sqrt((n**2-k**2-(math.sin(theta))**2)**2 + ((4 * n**2) * k**2)) + (n**2 - k**2 - (math.sin(theta))**2))/2)&#xD;&#xA;    &#xD;&#xA;    b = math.sqrt((math.sqrt((n**2-k**2-(math.sin(theta))**2)**2 + ((4 * n**2) * k**2)) - (n**2 - k**2 - (math.sin(theta))**2))/2)&#xD;&#xA;      &#xD;&#xA;    Fs = (a**2+b**2-(2 * a * math.cos(theta))+(math.cos(theta))**2)/(a**2+b**2+(2 * a * math.cos(theta))+(math.cos(theta))**2)&#xD;&#xA;    Fp = Fs * ((a**2+b**2-(2 * a * math.sin(theta) * math.tan(theta))+(math.sin(theta))**2*(math.tan(theta))**2)/(a**2+b**2+(2 * a * math.sin(theta) * math.tan(theta))+(math.sin(theta))**2*(math.tan(theta))**2))&#xD;&#xA;    R = (Fs + Fp)/2&#xD;&#xA;    fresnel.append(R)&#xD;&#xA;    &#xD;&#xA;    theta_deg += 1&#xD;&#xA;    return fresnel&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But I can't find any references online for this formula, the Wikipedia article on [Fresnel equations][2] contains completely different formulas, and I can't see the connection between them. I've searched high and low, but can't find any reference to this particular formula, why is that? Can you help me find it, or explain to me why I can't find it online? Or could you show me how to derive it from the Fresnel formulas from the Wikipedia article?&#xD;&#xA;&#xD;&#xA;Yes, I realize that I've already have the formula right there in the code sample. But I'm baffled over why I can't find this formula anywhere, I would like to have more sources to cite then just this code example.&#xD;&#xA;&#xD;&#xA;  [1]: http://therenderblog.com/custom-fresnel-curves-in-maya-part-2/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Fresnel_equations" ContentLicense="CC BY-SA 3.0" />
  <row Id="13940" PostHistoryTypeId="1" PostId="5182" RevisionGUID="37cef116-7a40-4d8d-940f-89e7ee4e1677" CreationDate="2017-05-30T20:47:55.340" UserId="2736" Text="Fresnel equation with incident angle, n and k as input" ContentLicense="CC BY-SA 3.0" />
  <row Id="13941" PostHistoryTypeId="3" PostId="5182" RevisionGUID="37cef116-7a40-4d8d-940f-89e7ee4e1677" CreationDate="2017-05-30T20:47:55.340" UserId="2736" Text="|reflection|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13945" PostHistoryTypeId="2" PostId="5183" RevisionGUID="46590a6f-834c-4079-8f3e-87f3bf2311e7" CreationDate="2017-05-31T03:54:49.040" UserId="4978" Text="I am reading about fluids and I read [Stable Fluids][1]&#xD;&#xA;by Jos Stam and [FLUID SIMULATION SIGGRAPH 2007 Course Notes][2] by Robert Bridson. The boundary conditions satisfying in the two papers are different in my sight. I don't understand them. How these two ways are related to solving a linear system of PDE with boundary conditions ? &#xD;&#xA;&#xD;&#xA;In Stam's paper , he use a function called set_bnd to set boundaries , so is this function just setting the boundaries that I need in my matrix of linear systems of Pressure Poission and Diffuse Equation ? In Numerical Analysis , we don't modify the matrix with the boundary values , but we put the boundary condition either it's a Neuman or Dirichlet. And I don't really understand what kind of boundaries is this set_bnd function. My thinking now is that it sets the boundary values which will be used to solve linear systems but what kind of boundaries ? I don't know&#xD;&#xA;&#xD;&#xA;In Bridson's paper , I don't find any implementation about boundaries except for speaking about the normal components of velocity ! Actually , I can't find any relation between this and Stam's way. In the section of making fluid incompressible , he says something about boundaries but I don't understand he just satisfies boundary conditions on the boundary cells then he solves the system or he put the boundaries in the matrix?&#xD;&#xA;Actually I don't know how to satisfy u*n = u_solid * n which I think is the free slip boundaries for interacting between a fluid and solid boundaries.&#xD;&#xA;&#xD;&#xA;Thanks , I am really confused about this and really hope to find help please be patient with me. I If you just have any source or explaination for this , please give me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.autodeskresearch.com/pdf/ns.pdf&#xD;&#xA;  [2]: http://www.cs.uu.nl/docs/vakken/mgp/2013-2014/literature/Fluid%20Simulation.pdf  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13946" PostHistoryTypeId="1" PostId="5183" RevisionGUID="46590a6f-834c-4079-8f3e-87f3bf2311e7" CreationDate="2017-05-31T03:54:49.040" UserId="4978" Text="Some rigorous and simple explain for satisfying boundary condition in Stam and Bridson papers" ContentLicense="CC BY-SA 3.0" />
  <row Id="13947" PostHistoryTypeId="3" PostId="5183" RevisionGUID="46590a6f-834c-4079-8f3e-87f3bf2311e7" CreationDate="2017-05-31T03:54:49.040" UserId="4978" Text="|fluid-sim|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13948" PostHistoryTypeId="5" PostId="1899" RevisionGUID="f625f458-01f5-4a86-843e-8f45e7dc9a79" CreationDate="2017-05-31T07:26:51.043" UserId="209" Comment="Hopefully clarified a couple of points." Text="If you are in a hurry to get your renderer working *and* you already have the filled polygonal routine *functioning correctly*, can I suggest an alternative, possibly easier approach? Though I'm not familiar with Lua, it seems you are solving for the exact intersection of a scan line with the quadratic Bezier which, though admirable, is possibly overkill.&#xD;&#xA;&#xD;&#xA;Instead, tessellate your Beziers into line segments and then throw those into the polygon scan converter. I suggest just using (recursive) binary subdivision: i.e. the quadratic Bezier with control points, $(\overline {A} , \overline {B} , \overline {C})$ can be split into two Beziers, $(\overline {A} , \overline {D} , \overline {E})$ and $(\overline {E} , \overline {F} , \overline {C})$ &#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;\begin{align*} &amp; \overline {D}=\dfrac {\overline {A}+\overline {B}} {2}\\ &amp; &#xD;&#xA;\overline {E} =\dfrac {\overline {A}+2\overline {B}+\overline {C}}{4}\\ &amp;&#xD;&#xA;\overline {F}=\dfrac {\overline {B}+\overline {C}} {2}&#xD;&#xA;\end{align*}&#xD;&#xA;$$&#xD;&#xA;(which is also great if you only have fixed point maths).&#xD;&#xA;&#xD;&#xA;IIRC, each time you subdivide, the error between the Bezier and just a straight line segment joining the end points goes down by a factor of ~4x, so it doesn't take many subdivisions before the piecewise linear approximation will be indistinguishable from the true curve. You can also use the bounding box of the control points to decide if you can skip out of the subdivision process early since that will also be a conservative bound on the curve.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="13949" PostHistoryTypeId="50" PostId="4635" RevisionGUID="ee4aea07-1eb4-4696-89cf-2139bef1344d" CreationDate="2017-05-31T07:26:53.907" UserId="-1" />
  <row Id="13950" PostHistoryTypeId="5" PostId="5183" RevisionGUID="616de5a3-697d-4a2e-9c54-7d8dbd929185" CreationDate="2017-05-31T09:13:55.253" UserId="231" Comment="Tidying and removing redundant intro and thanks" Text="I read [Stable Fluids][1] by Jos Stam and [FLUID SIMULATION SIGGRAPH 2007 Course Notes][2] by Robert Bridson. The boundary conditions in the two papers are different in my sight. I don't understand them. How are these two ways related to solving a linear system of PDEs with boundary conditions? &#xD;&#xA;&#xD;&#xA;In Stam's paper, he uses a function called `set_bnd` to set boundaries, so is this function just setting the boundaries that I need in my matrix of linear systems of Pressure Poisson and Diffuse Equation? In Numerical Analysis, we don't modify the matrix with the boundary values, but we put the boundary condition either it's a Neumann or Dirichlet. I don't really understand what kind of boundaries is this `set_bnd` function. My thinking now is that it sets the boundary values which will be used to solve linear systems but what kind of boundaries?&#xD;&#xA;&#xD;&#xA;In Bridson's paper, I don't find any implementation about boundaries except for speaking about the normal components of velocity. Actually, I can't find any relation between this and Stam's way. In the section on making fluid incompressible, he says something about boundaries but I don't understand. He just satisfies boundary conditions on the boundary cells then he solves the system or he put the boundaries in the matrix?&#xD;&#xA;Actually I don't know how to satisfy `u*n = u_solid * n` which I think is the free slip boundaries for interacting between a fluid and solid boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.autodeskresearch.com/pdf/ns.pdf&#xD;&#xA;  [2]: http://www.cs.uu.nl/docs/vakken/mgp/2013-2014/literature/Fluid%20Simulation.pdf  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13951" PostHistoryTypeId="4" PostId="5183" RevisionGUID="616de5a3-697d-4a2e-9c54-7d8dbd929185" CreationDate="2017-05-31T09:13:55.253" UserId="231" Comment="Tidying and removing redundant intro and thanks" Text="Rigorous and simple explanation for satisfying boundary conditions in Stam and Bridson papers" ContentLicense="CC BY-SA 3.0" />
  <row Id="13952" PostHistoryTypeId="5" PostId="5182" RevisionGUID="f8e944a2-10a9-4abe-953c-6237125215a8" CreationDate="2017-05-31T09:20:12.810" UserId="231" Comment="Streamlining and typo" Text="I've seen a Fresnel equation for calculating the reflection amount at *incidence angle* with *n* and *k* values defined. This formula usually comes up in relation to computer graphics, but I can't find this equation anywhere in a science context. &#xD;&#xA;&#xD;&#xA;Here is an example written in Python, taken from the website&#xD;&#xA;[Fresnel Formula in python][1]:&#xD;&#xA;&#xD;&#xA;    def IOR(n,k):&#xD;&#xA;    theta_deg = 0&#xD;&#xA;    &#xD;&#xA;    n = n&#xD;&#xA;    k = k&#xD;&#xA;    fresnel = []&#xD;&#xA;      &#xD;&#xA;    while theta_deg &lt;= 90:&#xD;&#xA;    theta = math.radians(theta_deg)&#xD;&#xA;    &#xD;&#xA;    a = math.sqrt((math.sqrt((n**2-k**2-(math.sin(theta))**2)**2 + ((4 * n**2) * k**2)) + (n**2 - k**2 - (math.sin(theta))**2))/2)&#xD;&#xA;    &#xD;&#xA;    b = math.sqrt((math.sqrt((n**2-k**2-(math.sin(theta))**2)**2 + ((4 * n**2) * k**2)) - (n**2 - k**2 - (math.sin(theta))**2))/2)&#xD;&#xA;      &#xD;&#xA;    Fs = (a**2+b**2-(2 * a * math.cos(theta))+(math.cos(theta))**2)/(a**2+b**2+(2 * a * math.cos(theta))+(math.cos(theta))**2)&#xD;&#xA;    Fp = Fs * ((a**2+b**2-(2 * a * math.sin(theta) * math.tan(theta))+(math.sin(theta))**2*(math.tan(theta))**2)/(a**2+b**2+(2 * a * math.sin(theta) * math.tan(theta))+(math.sin(theta))**2*(math.tan(theta))**2))&#xD;&#xA;    R = (Fs + Fp)/2&#xD;&#xA;    fresnel.append(R)&#xD;&#xA;    &#xD;&#xA;    theta_deg += 1&#xD;&#xA;    return fresnel&#xD;&#xA;&#xD;&#xA;I can't find any references online for this formula, the Wikipedia article on [Fresnel equations][2] contains completely different formulas, and I can't see the connection between them. I've searched high and low, but can't find any reference to this particular formula, why is that? Can you help me find it, or explain to me why I can't find it online? Or could you show me how to derive it from the Fresnel formulas from the Wikipedia article?&#xD;&#xA;&#xD;&#xA;Yes, I realize that I already have the formula right there in the code sample. But I'm baffled over why I can't find this formula anywhere, I would like to have more sources to cite then just this code example.&#xD;&#xA;&#xD;&#xA;  [1]: http://therenderblog.com/custom-fresnel-curves-in-maya-part-2/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Fresnel_equations" ContentLicense="CC BY-SA 3.0" />
  <row Id="13953" PostHistoryTypeId="2" PostId="5184" RevisionGUID="b34d3cc7-c296-4e48-8fde-0541acde1998" CreationDate="2017-05-31T13:18:02.727" UserId="5256" Text="Can somebody help explain how I can implement Sub Surface Scattering in a Path Tracer based on the Diffuse Approximation in [A Practical Model for Subsurface Light Transport][1] ?&#xD;&#xA;&#xD;&#xA;Currently I have a decent understanding of how everything works based on this [post][2] from a while back which is by far the best explanation I have seen.&#xD;&#xA;&#xD;&#xA;However, when it comes to implementation and all the overwhelming mathematics I get very confused. Can someone help me? I haven't been able to find a beginner friendly resource online so I hoped someone here could share their knowledge. &#xD;&#xA;&#xD;&#xA;(**Code Samples will be very helpful** !)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://A%20Practical%20Model%20for%20Subsurface%20Light%20Transport&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/81/what-is-the-dipole-approximation-for-subsurface-scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13954" PostHistoryTypeId="1" PostId="5184" RevisionGUID="b34d3cc7-c296-4e48-8fde-0541acde1998" CreationDate="2017-05-31T13:18:02.727" UserId="5256" Text="Implementation of Sub Surface Scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13955" PostHistoryTypeId="3" PostId="5184" RevisionGUID="b34d3cc7-c296-4e48-8fde-0541acde1998" CreationDate="2017-05-31T13:18:02.727" UserId="5256" Text="|raytracing|pathtracing|brdf|pbr|subsurface-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13956" PostHistoryTypeId="2" PostId="5185" RevisionGUID="7b614bac-b7ea-4f94-80bd-d88239843192" CreationDate="2017-05-31T16:21:37.193" UserId="5506" Text="I'm discovering the wonderful world of math and I'm hitting a huge wall with PBR and naming so I have a few questions:&#xD;&#xA;As far as I understand BRDF describe how a material react to light (incoming direct light and reflections). But in &quot;Cook-Torrance&quot; I don't see anything about reflections I don't understand how I integrate it so I only get diffuse light and reflections.&#xD;&#xA;&#xD;&#xA;I've read a lot about different &quot;diffuse term&quot; like &quot;oren-nayar&quot; is it a part of cook-torrance like a different &quot;D&quot; in the DFG nominator ? does it remplace it without specular calculations ?&#xD;&#xA;&#xD;&#xA;I've read a lot about &quot;GGX&quot; from my blender artist background I thought it was something that make a blurry reflection but It seems I was wrong and now I find this GGX term in a lot of different situations like in micro-facet normal distribution in this [tutorial][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So in short the question is: how &quot;oren-nayar&quot; and &quot;GGX&quot; and &quot;cook-torrance&quot; are related to each other (if they are) and how do I integrate &quot;vec3 reflection&quot; in those algorithm ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As I said before I'm a newbie in math so If your answer is &quot;math heavy&quot; please write a glsl/hlsl version of your equations it's much easier to understand for me so an equivalence will help me a lot&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: I understand my question is blurry but it is also as blurry as my understanding of the subject.&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!PBR/Lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="13957" PostHistoryTypeId="1" PostId="5185" RevisionGUID="7b614bac-b7ea-4f94-80bd-d88239843192" CreationDate="2017-05-31T16:21:37.193" UserId="5506" Text="Confused with PBR implementations" ContentLicense="CC BY-SA 3.0" />
  <row Id="13958" PostHistoryTypeId="3" PostId="5185" RevisionGUID="7b614bac-b7ea-4f94-80bd-d88239843192" CreationDate="2017-05-31T16:21:37.193" UserId="5506" Text="|glsl|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13959" PostHistoryTypeId="2" PostId="5186" RevisionGUID="3c065010-0598-4497-9503-f32768487bf0" CreationDate="2017-05-31T16:44:02.317" UserDisplayName="user6750" Text="I was reading the Wikipedia entry on Marching Squares, and was confused by the explanation of the saddle point disambiguation:&#xD;&#xA;&#xD;&#xA;Ambiguous Case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Basically, given the saddle points, the ambiguity is resolved by using the average data value for the center of the cell. I don't understand why this would help resolve the ambiguity. It seems to just select the longer pair of lines over the shorter pair. Is there any reason for this approach?&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Marching_squares#Disambiguation_of_saddle_points&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yMvup.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13960" PostHistoryTypeId="1" PostId="5186" RevisionGUID="3c065010-0598-4497-9503-f32768487bf0" CreationDate="2017-05-31T16:44:02.317" UserDisplayName="user6750" Text="Explanation of the Marching Squares saddle points resolution" ContentLicense="CC BY-SA 3.0" />
  <row Id="13961" PostHistoryTypeId="3" PostId="5186" RevisionGUID="3c065010-0598-4497-9503-f32768487bf0" CreationDate="2017-05-31T16:44:02.317" UserDisplayName="user6750" Text="|algorithm|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13962" PostHistoryTypeId="5" PostId="5183" RevisionGUID="8504ffba-7eaa-44c6-ba30-109b2dd5331d" CreationDate="2017-05-31T17:41:04.670" UserId="4978" Comment="deleted 2 characters in body" Text="I read [Stable Fluids][1] by Jos Stam and [FLUID SIMULATION SIGGRAPH 2007 Course Notes][2] by Robert Bridson. The boundary conditions in the two papers are different in my sight. I don't understand them. How are these two ways related to solving a linear system of PDEs with boundary conditions? &#xD;&#xA;&#xD;&#xA;In Stam's paper, he uses a function called `set_bnd` to set boundaries, so is this function just setting the boundaries that I need in my matrix of linear systems of Pressure Poisson and Diffuse Equation? In Numerical Analysis, we don't modify the matrix with the boundary values, but we put the boundary condition either it's a Neumann or Dirichlet. I don't really understand what kind of boundaries is this `set_bnd` function. My thinking now is that it sets the boundary values which will be used to solve linear systems but what kind of boundaries?&#xD;&#xA;&#xD;&#xA;In Bridson's paper, I don't find any implementation about boundaries except for speaking about the normal components of velocity. Actually, I can't find any relation between this and Stam's way. In the section on making fluid incompressible, he says something about boundaries but I don't understand. He just satisfies boundary conditions on the boundary cells then he solves the system or he put the boundaries in the matrix?&#xD;&#xA;Actually I don't know how to satisfy `u*n = u_solid * n` which I think is the no slip boundaries for interacting between a fluid and solid boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.autodeskresearch.com/pdf/ns.pdf&#xD;&#xA;  [2]: http://www.cs.uu.nl/docs/vakken/mgp/2013-2014/literature/Fluid%20Simulation.pdf  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13963" PostHistoryTypeId="5" PostId="5184" RevisionGUID="06b99007-0e57-4d3e-9d16-342a8842a39b" CreationDate="2017-05-31T18:18:24.570" UserId="48" Comment="fix link to paper" Text="Can somebody help explain how I can implement Sub Surface Scattering in a Path Tracer based on the Diffuse Approximation in [A Practical Model for Subsurface Light Transport][1] ?&#xD;&#xA;&#xD;&#xA;Currently I have a decent understanding of how everything works based on this [post][2] from a while back which is by far the best explanation I have seen.&#xD;&#xA;&#xD;&#xA;However, when it comes to implementation and all the overwhelming mathematics I get very confused. Can someone help me? I haven't been able to find a beginner friendly resource online so I hoped someone here could share their knowledge. &#xD;&#xA;&#xD;&#xA;(**Code Samples will be very helpful** !)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.stanford.edu/papers/bssrdf/&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/81/what-is-the-dipole-approximation-for-subsurface-scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13964" PostHistoryTypeId="2" PostId="5187" RevisionGUID="47f694f9-a68e-4cec-8b91-fa3fa9e25ade" CreationDate="2017-06-01T01:55:28.263" UserId="6546" Text="In [GLSL: Common Mistakes][1] it states:&#xD;&#xA;&#xD;&#xA;&gt; Functions parameters must be declared with the `in`, `out`, or `inout` qualifiers.&#xD;&#xA;&#xD;&#xA;but I have never declared function parameters with `in`, `out`, or `inout` qualifiers and I have never run into any problems. Could this be because of my specific graphics card? What are the side effects of not using the `in`, `out`, or `inout` qualifiers?&#xD;&#xA;&#xD;&#xA;Info: I am using GLSL 3.3 and I have an Intel graphics card&#xD;&#xA;&#xD;&#xA; [1]: https://www.khronos.org/opengl/wiki/GLSL_:_common_mistakes#Functions_inputs_and_outputs" ContentLicense="CC BY-SA 3.0" />
  <row Id="13965" PostHistoryTypeId="1" PostId="5187" RevisionGUID="47f694f9-a68e-4cec-8b91-fa3fa9e25ade" CreationDate="2017-06-01T01:55:28.263" UserId="6546" Text="GLSL function parameters" ContentLicense="CC BY-SA 3.0" />
  <row Id="13966" PostHistoryTypeId="3" PostId="5187" RevisionGUID="47f694f9-a68e-4cec-8b91-fa3fa9e25ade" CreationDate="2017-06-01T01:55:28.263" UserId="6546" Text="|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13967" PostHistoryTypeId="2" PostId="5188" RevisionGUID="65b1b0c7-b315-4e32-844b-0ccd617c896c" CreationDate="2017-06-01T04:29:24.750" UserId="3003" Text="As @PaulHK mentions in the comments, [the GLSL Specification](https://khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.40.pdf) in section 6.1.1 &quot;Function Calling Conventions&quot; states:&#xD;&#xA;&#xD;&#xA;&gt;• The keyword **in** is used as a qualifier to denote a parameter is to be copied in, but not copied out.&#xD;&#xA;&#xD;&#xA;&gt;• The keyword **out** is used as a qualifier to denote a parameter is to be copied out, but not copied in. This should be used whenever possible to avoid unnecessarily copying parameters in.&#xD;&#xA;&#xD;&#xA;&gt;• The keyword **inout** is used as a qualifier to denote the parameter is to be both copied in and copied out. It means the same thing as specifying both in and out.&#xD;&#xA;&#xD;&#xA;&gt;• A function parameter declared with no such qualifier means the same thing as specifying **in**." ContentLicense="CC BY-SA 3.0" />
  <row Id="13968" PostHistoryTypeId="5" PostId="5188" RevisionGUID="1778e190-8877-415d-8dd1-70388558df54" CreationDate="2017-06-01T09:08:45.190" UserId="2041" Comment="Remove reference to answer posted as comment, and add list formatting." Text="[The GLSL Specification](https://khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.40.pdf) in section 6.1.1 &quot;Function Calling Conventions&quot; states:&#xD;&#xA;&#xD;&#xA;&gt;- The keyword **in** is used as a qualifier to denote a parameter is to be copied in, but not copied out.&#xD;&#xA;&#xD;&#xA;&gt;- The keyword **out** is used as a qualifier to denote a parameter is to be copied out, but not copied in. This should be used whenever possible to avoid unnecessarily copying parameters in.&#xD;&#xA;&#xD;&#xA;&gt;- The keyword **inout** is used as a qualifier to denote the parameter is to be both copied in and copied out. It means the same thing as specifying both in and out.&#xD;&#xA;&#xD;&#xA;&gt;- A function parameter declared with no such qualifier means the same thing as specifying **in**." ContentLicense="CC BY-SA 3.0" />
  <row Id="13969" PostHistoryTypeId="2" PostId="5189" RevisionGUID="54d13efd-be6f-4f9d-9552-054f6355251c" CreationDate="2017-06-01T09:50:21.427" UserId="3073" Text="This is the complex number version of refraction, were K is the extinction coefficient. This is commonly used for metals.&#xD;&#xA;&#xD;&#xA;You can check the Wikipedia on refraction:  https://en.wikipedia.org/wiki/Refractive_index#Complex_refractive_index" ContentLicense="CC BY-SA 3.0" />
  <row Id="13972" PostHistoryTypeId="2" PostId="5191" RevisionGUID="efaf48b8-be38-47d8-b262-699038c76399" CreationDate="2017-06-01T11:31:58.113" UserId="5026" Text="Ambient Occlusion is a physical approximation to occlude ambient light. If ambient light is not considered post-processing, why is AO? Ambient occlusion has the same inputs as regular deferred lighting, plus kernels and a noise map, but essentially, it can be handled the same way. Is there a reason why it's considered post-processing and deferred lighting/shading isn't?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13973" PostHistoryTypeId="1" PostId="5191" RevisionGUID="efaf48b8-be38-47d8-b262-699038c76399" CreationDate="2017-06-01T11:31:58.113" UserId="5026" Text="Why is AO considered Post-Processing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13974" PostHistoryTypeId="3" PostId="5191" RevisionGUID="efaf48b8-be38-47d8-b262-699038c76399" CreationDate="2017-06-01T11:31:58.113" UserId="5026" Text="|ambient-occlusion|post-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13975" PostHistoryTypeId="5" PostId="5184" RevisionGUID="152630c2-528d-4112-ada1-c2282c6f0934" CreationDate="2017-06-01T12:44:15.493" UserId="5256" Comment="Specified my problems more clearly and added some other general questions. " Text="Can somebody help explain how I can implement Sub Surface Scattering in a Path Tracer based on the Diffuse Approximation in [A Practical Model for Subsurface Light Transport][1] ?&#xD;&#xA;&#xD;&#xA;Currently I have a decent understanding of how everything works based on this [post][2] from a while back which is by far the best explanation I have seen.&#xD;&#xA;&#xD;&#xA;However, when it comes to implementation and all the overwhelming mathematics I get very confused. Can someone help me? I haven't been able to find a beginner friendly resource online so I hoped someone here could share their knowledge. &#xD;&#xA;&#xD;&#xA;**I would like someone to explain the mathematics a little more clearly (why we need both the Fresnel terms, the diffusion profile and why we multiply everything by 1/π)  and show me the implementation steps through pseudocode.**&#xD;&#xA;&#xD;&#xA;Along with that, I had a few questions.&#xD;&#xA;&#xD;&#xA; 1. Why does the BSSRDF approximate as a Diffuse BRDF? Why can't we use&#xD;&#xA;    the acutal BSSRDF itself described in the paper?&#xD;&#xA; 2. Are there any better versatile and more physically based models like&#xD;&#xA;    this one  for Sub Surface Scattering at this point in time?&#xD;&#xA; 3. What are the properties I need to modify to achieve different looks?&#xD;&#xA;    Is this specified in the paper? Is there a table for this?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.stanford.edu/papers/bssrdf/&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/81/what-is-the-dipole-approximation-for-subsurface-scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13976" PostHistoryTypeId="5" PostId="5184" RevisionGUID="7180e04c-3cf4-4425-b3b5-1eecb837db69" CreationDate="2017-06-01T12:52:09.653" UserId="5256" Comment="Specified my problems more clearly and added some other general questions. " Text="Can somebody help explain how I can implement Sub Surface Scattering in a Path Tracer based on the Diffuse Approximation in **[A Practical Model for Subsurface Light Transport][1]** ?&#xD;&#xA;&#xD;&#xA;Currently I have a decent understanding of how everything works based on this **[post][2]** from a while back which is by far the best explanation I have seen.&#xD;&#xA;&#xD;&#xA;However, when it comes to implementation and all the overwhelming mathematics I get very confused. Can someone help me? I haven't been able to find a beginner friendly resource online so I hoped someone here could share their knowledge. &#xD;&#xA;&#xD;&#xA;I would like someone to explain the mathematics a little more clearly (why we need both the fresnel terms, the diffusion profile, why we multiply everything by 1/π and also what everything does) and show me the implementation steps through pseudocode. The symbols in all of the equations are also confusing (I'm still doing high school math), so any definition for each symbol would be great. &#xD;&#xA;&#xD;&#xA;Along with that, I had a few questions.&#xD;&#xA;&#xD;&#xA; 1. Why do we approximate the BSSRDF as a BRDF? Is it because the outgoing rays are usually isotropic? What are the main differences in mathematics between the original and approximation? &#xD;&#xA; 2. Are there any better versatile and more physically based models like&#xD;&#xA;    this one  for Sub Surface Scattering at this point in time?&#xD;&#xA; 3. What are the properties I need to modify to achieve different looks?&#xD;&#xA;    Is this specified in the paper? Is there a table for this?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.stanford.edu/papers/bssrdf/&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/81/what-is-the-dipole-approximation-for-subsurface-scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13977" PostHistoryTypeId="5" PostId="5184" RevisionGUID="69a0c85e-552a-4058-a1a3-bc302a104bc2" CreationDate="2017-06-01T12:58:55.533" UserId="5256" Comment="Specified my problems more clearly and added some other general questions. " Text="Can somebody help explain how I can implement Sub Surface Scattering in a Path Tracer based on the Diffuse Approximation in **[A Practical Model for Subsurface Light Transport][1]** ?&#xD;&#xA;&#xD;&#xA;Currently I have a decent understanding of how everything works based on this **[post][2]** from a while back which is by far the best explanation I have seen.&#xD;&#xA;&#xD;&#xA;However, when it comes to implementation and all the overwhelming mathematics I get very confused. Can someone help me? I haven't been able to find a beginner friendly resource online so I hoped someone here could share their knowledge. &#xD;&#xA;&#xD;&#xA;I would like someone to explain the mathematics a little more clearly (why we need both the fresnel terms, the diffusion profile, why we multiply everything by 1/π and also what everything does) and show me the implementation steps through pseudocode. The symbols in all of the equations are also confusing (I'm still doing high school math), so any definition for each symbol would be great. &#xD;&#xA;&#xD;&#xA;Along with that, I had a few questions.&#xD;&#xA;&#xD;&#xA; 1. Why do we approximate the BSSRDF as a BRDF? Is it because the outgoing rays are usually isotropic? What are the main differences in mathematics between the original and approximation? &#xD;&#xA; 2. Are there any better versatile and more physically based models like&#xD;&#xA;    this one for Sub Surface Scattering at this point in time?&#xD;&#xA; 3. Can this BSSRDF approximation be importance sampled?&#xD;&#xA; 4. Single Scattering vs Multiple Scattering?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.stanford.edu/papers/bssrdf/&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/81/what-is-the-dipole-approximation-for-subsurface-scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13978" PostHistoryTypeId="2" PostId="5192" RevisionGUID="ea23e735-b63e-4619-a360-901d9f001905" CreationDate="2017-06-01T13:41:12.970" UserId="56" Text="You can have blue noise sampling like these poisson disc samples:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And you can have a blue noise texture like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I get that in the first image, there is one input (the index of the sample) and two outputs (the x,y coordinate of the point) and that the second image is basically the reverse where there are two inputs (the x,y coordinate of the sample) and one output (the value of the point).&#xD;&#xA;&#xD;&#xA;I'm curious though, how are these related?&#xD;&#xA;&#xD;&#xA;If you take the DFT of the second image, you can see that it has more high frequency components than low, but I'm not sure how you'd take the DFT of the first set of data points.&#xD;&#xA;&#xD;&#xA;I'm also wondering if it's possible to take other low discrepancy sequences (say, halton, or jittered grid) and make a texture out of the idea, like the second image?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DrzFt.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CgvI3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="13979" PostHistoryTypeId="1" PostId="5192" RevisionGUID="ea23e735-b63e-4619-a360-901d9f001905" CreationDate="2017-06-01T13:41:12.970" UserId="56" Text="Link between blue noise sampling and blue noise textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="13980" PostHistoryTypeId="3" PostId="5192" RevisionGUID="ea23e735-b63e-4619-a360-901d9f001905" CreationDate="2017-06-01T13:41:12.970" UserId="56" Text="|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13981" PostHistoryTypeId="2" PostId="5193" RevisionGUID="623b103e-e0af-45fb-9672-9e595cd70ac8" CreationDate="2017-06-01T15:43:53.170" UserId="231" Text="This is a potentially confusing re-use of terminology. [Ambient Occlusion] is not in itself a post processing effect. [Screen Space Ambient Occlusion] is a post processing effect using the depth buffer to approximate the effects produced by Ambient Occlusion.&#xD;&#xA;&#xD;&#xA;Ambient Occlusion is a relatively expensive global method, while Screen Space Ambient Occlusion is the cheaper alternative for real time animation. Only the latter is considered post processing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Ambient Occlusion]: https://en.wikipedia.org/wiki/Ambient_occlusion&#xD;&#xA;  [Screen Space Ambient Occlusion]: https://en.wikipedia.org/wiki/Screen_space_ambient_occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="13982" PostHistoryTypeId="5" PostId="5183" RevisionGUID="09f0086a-3489-449d-9bd1-7d800a90a34e" CreationDate="2017-06-01T16:18:35.370" UserId="4978" Comment="added 1 character in body" Text="I read [Stable Fluids][1] by Jos Stam and [FLUID SIMULATION SIGGRAPH 2007 Course Notes][2] by Robert Bridson. The boundary conditions in the two papers are different in my sight. I don't understand them. How are these two ways related to solving a linear system of PDEs with boundary conditions? &#xD;&#xA;&#xD;&#xA;In Stam's paper, he uses a function called `set_bnd` to set boundaries, so is this function just setting the boundaries that I need in my matrix of linear systems of Pressure Poisson and Diffuse Equation? In Numerical Analysis, we don't modify the matrix with the boundary values, but we put the boundary condition either it's a Neumann or Dirichlet. I don't really understand what kind of boundaries is this `set_bnd` function. My thinking now is that it sets the boundary values which will be used to solve linear systems but what kind of boundaries?&#xD;&#xA;&#xD;&#xA;In Bridson's paper, I don't find any implementation about boundaries except for speaking about the normal components of velocity. Actually, I can't find any relation between this and Stam's way. In the section on making fluid incompressible, he says something about boundaries but I don't understand. He just satisfies boundary conditions on the boundary cells then he solves the system or he put the boundaries in the matrix?&#xD;&#xA;Actually I don't know how to satisfy `u*n = u_solid * n` which I think is the no stick boundaries for interacting between a fluid and solid boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.autodeskresearch.com/pdf/ns.pdf&#xD;&#xA;  [2]: http://www.cs.uu.nl/docs/vakken/mgp/2013-2014/literature/Fluid%20Simulation.pdf  " ContentLicense="CC BY-SA 3.0" />
  <row Id="13984" PostHistoryTypeId="5" PostId="5184" RevisionGUID="165b9f56-5b16-4f93-9e79-527bbbbe405b" CreationDate="2017-06-01T16:59:20.137" UserId="5256" Comment="deleted 230 characters in body; edited title" Text="Can somebody help explain the mathematics of Sub Surface Scattering in a Path Tracer based on the Diffuse Approximation in **[A Practical Model for Subsurface Light Transport][1]** ?&#xD;&#xA;&#xD;&#xA;I would like someone to explain the mathematics a little more clearly (why we need both the Fresnel terms, the diffusion profile, why we multiply everything by 1/π) and show me what I need to put together finally in Pseudocode. The symbols in all of the equations are also confusing (I'm still doing high school math), so any definition for each symbol would be great. &#xD;&#xA;&#xD;&#xA;Along with that, I had a few simpler questions.&#xD;&#xA;&#xD;&#xA; 1. Why do we approximate the BSSRDF as a BRDF? Is it because the outgoing rays are usually isotropic? What are the main differences in mathematics between the original and approximation? &#xD;&#xA;&#xD;&#xA; 3. Can this BSSRDF approximation be importance sampled?&#xD;&#xA;&#xD;&#xA;Currently I have an understanding of how everything works based on this **[post][2]** from a while back which is a good explanation. However, when it comes to implementation and all the overwhelming mathematics I get very confused. Can someone help me? I haven't been able to find a beginner friendly resource online so I hoped someone here could share their knowledge. &#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.stanford.edu/papers/bssrdf/&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/81/what-is-the-dipole-approximation-for-subsurface-scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13985" PostHistoryTypeId="4" PostId="5184" RevisionGUID="165b9f56-5b16-4f93-9e79-527bbbbe405b" CreationDate="2017-06-01T16:59:20.137" UserId="5256" Comment="deleted 230 characters in body; edited title" Text="Mathematics of Sub Surface Scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="13987" PostHistoryTypeId="2" PostId="5194" RevisionGUID="88426a74-8c5f-43dc-bb28-9b191350815e" CreationDate="2017-06-01T19:27:16.947" UserId="5026" Text="I'm having problems with Ambient Occlusion. I've tried to follow both [John Chapman's improvements over the Crytek AO][1] and [LearnOpenGL's tutorial of it][2] when I failed to properly obtain the correct result. https://i.stack.imgur.com/fhm8V.jpg&#xD;&#xA;&#xD;&#xA;As the camera turns or moves, the screen flashes consistently though it seems arbitrary. Can anyone tell me what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;    #version 140&#xD;&#xA;    &#xD;&#xA;    in vec2 UV;&#xD;&#xA;    in vec4 vRay;&#xD;&#xA;    out vec3 SSAOout;&#xD;&#xA;    &#xD;&#xA;    const int kernelSize = 64;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    uniform sampler2D gbuffer0;&#xD;&#xA;    uniform sampler2D gbuffer1;&#xD;&#xA;    uniform sampler2D gbuffer2;&#xD;&#xA;    uniform sampler2D gbuffer3;&#xD;&#xA;    uniform sampler2D noiseTex;&#xD;&#xA;    uniform vec3 kernels[kernelSize];&#xD;&#xA;    &#xD;&#xA;    vec4 ViewPosFromDepth(float depth, vec2 TexCoord) {&#xD;&#xA;        float z = depth * 2.0 - 1.0;&#xD;&#xA;    &#xD;&#xA;        vec4 clipSpacePosition = vec4(TexCoord * 2.0 - 1.0, z, 1.0);&#xD;&#xA;        vec4 viewSpacePosition = invProjMat * clipSpacePosition;&#xD;&#xA;        viewSpacePosition /= viewSpacePosition.w;&#xD;&#xA;    &#xD;&#xA;        return viewSpacePosition;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const vec2 noiseScale = vec2(1366.0/4.0, 768.0/4.0);&#xD;&#xA;    &#xD;&#xA;    const float near = 0.1;&#xD;&#xA;    const float far = 100.0;&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(float depth)&#xD;&#xA;    {&#xD;&#xA;        float z = depth * 2.0 - 1.0; // back to NDC &#xD;&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	vec4 gbuffer0Val = texture(gbuffer0, UV);&#xD;&#xA;    	vec4 gbuffer1Val = texture(gbuffer1, UV);&#xD;&#xA;    	vec4 gbuffer2Val = texture(gbuffer2, UV);&#xD;&#xA;    	vec4 gbuffer3Val = texture(gbuffer3, UV);&#xD;&#xA;    &#xD;&#xA;    	vec3 fragPos	= ViewPosFromDepth(gbuffer0Val.r, UV).rgb;&#xD;&#xA;        float dist      = LinearizeDepth(gbuffer0Val.r);&#xD;&#xA;    	vec3 normal		= gbuffer1Val.rgb;&#xD;&#xA;        normal          = decodeNormal(normal);&#xD;&#xA;        vec3 randomVec  = vec3(2 * texture(noiseTex, UV * noiseScale).rg - 1, 0); &#xD;&#xA;    &#xD;&#xA;        vec3 tangent   = normalize(randomVec - normal * dot(randomVec, normal));&#xD;&#xA;        vec3 bitangent = cross(normal, tangent);&#xD;&#xA;        mat3 TBN       = mat3(tangent, bitangent, normal);&#xD;&#xA;        &#xD;&#xA;        float bias = 0.025;&#xD;&#xA;        float radius = 3.0;&#xD;&#xA;        float occlusion = 0.0;&#xD;&#xA;        &#xD;&#xA;        for(int i = 0; i &lt; kernelSize; i++) {&#xD;&#xA;            vec3 sampleKernel = TBN * kernels[i];&#xD;&#xA;            sampleKernel = fragPos + sampleKernel * radius;&#xD;&#xA;    &#xD;&#xA;            vec4 offset = vec4(sampleKernel, 1.0);&#xD;&#xA;            offset      = projection * offset;    // from view to clip-space&#xD;&#xA;            offset.xyz /= offset.w;               // perspective divide&#xD;&#xA;            offset.xyz  = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0&#xD;&#xA;    &#xD;&#xA;            float sampleDepth = texture(gbuffer0, 1-offset.xy).r;&#xD;&#xA;            sampleDepth = LinearizeDepth(sampleDepth);&#xD;&#xA;            float rangeCheck = smoothstep(0.0, 1.0, radius / abs(fragPos.z - sampleDepth));&#xD;&#xA;            occlusion += (sampleDepth &gt;= sampleKernel.z + bias ? 1.0 : 0.0) * rangeCheck;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        occlusion = 1.0 - (occlusion / kernelSize);&#xD;&#xA;        SSAOout = vec3(occlusion);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: http://john-chapman-graphics.blogspot.com.eg/2013/01/ssao-tutorial.html&#xD;&#xA;  [2]: https://learnopengl.com/#!Advanced-Lighting/SSAO" ContentLicense="CC BY-SA 3.0" />
  <row Id="13988" PostHistoryTypeId="1" PostId="5194" RevisionGUID="88426a74-8c5f-43dc-bb28-9b191350815e" CreationDate="2017-06-01T19:27:16.947" UserId="5026" Text="Screen Space Ambient Occlusion Issues" ContentLicense="CC BY-SA 3.0" />
  <row Id="13989" PostHistoryTypeId="3" PostId="5194" RevisionGUID="88426a74-8c5f-43dc-bb28-9b191350815e" CreationDate="2017-06-01T19:27:16.947" UserId="5026" Text="|opengl|glsl|ambient-occlusion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="13990" PostHistoryTypeId="2" PostId="5195" RevisionGUID="5d20b80d-216b-49f6-b135-bbe7c16b932b" CreationDate="2017-06-01T19:51:53.180" UserId="5717" Text="DFG pops up in the family of microfacet based BRDFs. It is simply the product of three terms:&#xD;&#xA;&#xD;&#xA;* D : The microfacet distribution.&#xD;&#xA;* F : The fresnel coefficient.&#xD;&#xA;* G : The geometric attenuation between microfacets.&#xD;&#xA;&#xD;&#xA;When someone says Cook-Torrance, they usually mean a microfacet BRDF where the distribution (D) is Beckmann, which I think is what the original Cook-Torrance paper was about.&#xD;&#xA;&#xD;&#xA;GGX is really just a different distribution (D term). GTR is another one. The names are often used as a shortcut to mean a BRDF using that distribution.&#xD;&#xA;&#xD;&#xA;Now all of these assume specular reflection (or refraction) on the microfacets, hence the fresnel term. If you take a similar idea but use diffuse (lambertian) microfacets, you get the Oren-Nayar BRDF. I think that one is based on a gaussian distribution of the microfacets but I'm not familiar with the details." ContentLicense="CC BY-SA 3.0" />
  <row Id="14001" PostHistoryTypeId="2" PostId="5197" RevisionGUID="494dca13-69ef-4afb-818a-af8211e246a1" CreationDate="2017-06-02T13:43:56.020" UserId="6762" Text="Suppose I have a set of points in 3D which are all co-planar, and which describe the vertices of a convex polygon. I know the coordinates of all of these vertices, I know the unit normal to the plane of the polygon, and I know the order (in a right-hand sense with respect to the normal) in which the vertices go around the polygon. &#xD;&#xA;&#xD;&#xA;I also have a polyhedron, which is in general non-convex, and the surface of which is made of triangles. It is a triangle mesh like the one shown [here][1]. It describes a completely enclosed volume (no holes in the surface). I know the coordinates of all the vertices of all the triangles that make up the polyhedron. For a given vertex, I know the list of which triangles it is a vertex of.&#xD;&#xA;&#xD;&#xA;One other thing I know, which may or may not be useful, is that the polygon lies &quot;in the vicinity of&quot; a particular pair of vertices of the polyhedron, say the ones with indices $i$ and $j$. So if there were to some kind of a search of the surface of the polyhedron, that would be the place to start.&#xD;&#xA;&#xD;&#xA;My task is to find the area of the intersection between the polygon and the polyhedron. I believe this is a well-defined quantity. I need an algorithm to calculate this, hopefully efficiently but at this point I'll take anything.&#xD;&#xA;&#xD;&#xA;My thoughts:&#xD;&#xA;&#xD;&#xA;I can classify each polygon vertex as either inside or outside the polyhedron. I've written a ray-casting algorithm that computes this fairly accurately and efficiently. That means that each edge of the polygon can be classified as either &quot;both vertices inside&quot;, &quot;both vertices outside&quot;, or &quot;one in, one out.&quot; I can calculate the point of intersection between a given polygon edge and the polyhedron by checking a bunch of nearby triangles.&#xD;&#xA;&#xD;&#xA;But that's not enough. For instance, just because both vertices of an edge are inside doesn't mean the whole edge is inside. A &quot;finger&quot; of the polyhedron might intersect an edge without touching either of its endpoints. Furthermore, the polyhedron might intersect the polygon in such a way that it doesn't touch any of the edges at all. Clearly, one must also calculate the intersections between the triangles' edges and the polygon as well.&#xD;&#xA;&#xD;&#xA;It gets a bit too complicated for me at that point, and I'm wondering if there is some established algorithm for this?&#xD;&#xA;&#xD;&#xA;Perhaps something like: Project the polyhedron onto the plane containing the polygon and then... I don't know.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Triangle_mesh#/media/File:Dolphin_triangle_mesh.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14002" PostHistoryTypeId="1" PostId="5197" RevisionGUID="494dca13-69ef-4afb-818a-af8211e246a1" CreationDate="2017-06-02T13:43:56.020" UserId="6762" Text="An algorithm to find the area of intersection between a convex polygon and a 3D polyhedron?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14003" PostHistoryTypeId="3" PostId="5197" RevisionGUID="494dca13-69ef-4afb-818a-af8211e246a1" CreationDate="2017-06-02T13:43:56.020" UserId="6762" Text="|computational-geometry|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14004" PostHistoryTypeId="2" PostId="5198" RevisionGUID="a03e3818-e8cf-4da6-8d70-15c5e400f789" CreationDate="2017-06-02T13:56:28.060" UserId="4958" Text="You need to be careful about spaces - position and normal need to be in view space.&#xD;&#xA;&#xD;&#xA;To transform depth into view space position I used [this][1] method.&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;    vec3 viewPositionFromDepth(vec2 vTexCoord)&#xD;&#xA;    {&#xD;&#xA;        float z = texture2D(depthTexture, vTexCoord).r;&#xD;&#xA;        // Get x/w and y/w from the viewport position&#xD;&#xA;        float x = vTexCoord.x * 2.0 - 1.0;&#xD;&#xA;        float y = vTexCoord.y * 2.0 - 1.0;&#xD;&#xA;        vec4 vProjectedPos = vec4(x, y, z, 1.0f);&#xD;&#xA;        // Transform by the inverse projection matrix&#xD;&#xA;        vec4 vPositionVS = invProjection*vProjectedPos;&#xD;&#xA;        // Divide by w to get the view-space position&#xD;&#xA;        return vPositionVS.xyz / vPositionVS.w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;To transform normal into view space you need to multiply it by inverse of transpose of view matrix (should be done on CPU):&#xD;&#xA;&#xD;&#xA;    vec4 n = transpose(inverse(ViewMatrix)) * normalize(texture2D(normalTexture, texCoord)*2.0 - 1.0 );&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And in loop while sampling depth with offset to compare with original position, this depth should be in same space as position so I did it the same way:&#xD;&#xA;&#xD;&#xA;    float sampleDepth = viewPositionFromDepth(offset.xy).z;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is not the most optimal way though, but it worked for me.&#xD;&#xA;&#xD;&#xA;  [1]: https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14005" PostHistoryTypeId="5" PostId="5198" RevisionGUID="2785ea2e-ddf1-4d5a-9ae9-b2bb8769d236" CreationDate="2017-06-02T14:02:59.980" UserId="4958" Comment="deleted 2 characters in body" Text="You need to be careful about spaces - position and normal need to be in view space.&#xD;&#xA;&#xD;&#xA;To transform depth into view space position I used [this][1] method.&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;    vec3 viewPositionFromDepth(vec2 vTexCoord)&#xD;&#xA;    {&#xD;&#xA;        float z = texture2D(depthTexture, vTexCoord).r;&#xD;&#xA;        // Get x/w and y/w from the viewport position&#xD;&#xA;        float x = vTexCoord.x * 2.0 - 1.0;&#xD;&#xA;        float y = vTexCoord.y * 2.0 - 1.0;&#xD;&#xA;        vec4 vProjectedPos = vec4(x, y, z, 1.0f);&#xD;&#xA;        // Transform by the inverse projection matrix&#xD;&#xA;        vec4 vPositionVS = invProjection*vProjectedPos;&#xD;&#xA;        // Divide by w to get the view-space position&#xD;&#xA;        return vPositionVS.xyz / vPositionVS.w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;To transform normal into view space you need to multiply it by inverse of transpose of view matrix (should be done on CPU):&#xD;&#xA;&#xD;&#xA;    vec4 n = transpose(inverse(ViewMatrix)) * normalize(texture2D(normalTexture, texCoord)*2.0 - 1.0 );&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And in loop while sampling depth with offset to compare with kernel position, this depth should be in same space as position so I did it the same way:&#xD;&#xA;&#xD;&#xA;    float sampleDepth = viewPositionFromDepth(offset.xy).z;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is not the most optimal way though, but it worked for me.&#xD;&#xA;&#xD;&#xA;  [1]: https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14006" PostHistoryTypeId="2" PostId="5199" RevisionGUID="f58352c3-0ab2-4d3b-b234-99b8156a513a" CreationDate="2017-06-02T14:50:00.947" UserId="2041" Text="If you have GL (or equivalent) available, the easiest way is probably to set up your projection matrix so that the plane of the polygon is the near clipping plane, draw the polygon into the stencil buffer, and then draw the polyhedron such that inside faces output a 1 fragment. (You could do this by flipping the winding of the polyhedron and turning on back-face culling, or you could check the normal in the fragment shader.) Then the sum of the white pixels in your framebuffer is the intersection area." ContentLicense="CC BY-SA 3.0" />
  <row Id="14007" PostHistoryTypeId="5" PostId="5198" RevisionGUID="10f0ea51-5e87-4d6e-8b6b-a603ec41dd10" CreationDate="2017-06-02T15:11:04.193" UserId="4958" Comment="edited body" Text="You need to be careful about spaces - position and normal need to be in view space.&#xD;&#xA;&#xD;&#xA;To transform depth into view space position I used [this][1] method.&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;    vec3 viewPositionFromDepth(vec2 vTexCoord)&#xD;&#xA;    {&#xD;&#xA;        float z = texture2D(depthTexture, vTexCoord).r;&#xD;&#xA;        // Get x/w and y/w from the viewport position&#xD;&#xA;        float x = vTexCoord.x * 2.0 - 1.0;&#xD;&#xA;        float y = vTexCoord.y * 2.0 - 1.0;&#xD;&#xA;        vec4 vProjectedPos = vec4(x, y, z, 1.0f);&#xD;&#xA;        // Transform by the inverse projection matrix&#xD;&#xA;        vec4 vPositionVS = invProjection*vProjectedPos;&#xD;&#xA;        // Divide by w to get the view-space position&#xD;&#xA;        return vPositionVS.xyz / vPositionVS.w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;To transform normal into view space you need to multiply it by transpose of inverse of view matrix (should be done on CPU):&#xD;&#xA;&#xD;&#xA;    vec4 n = transpose(inverse(ViewMatrix)) * normalize(texture2D(normalTexture, texCoord)*2.0 - 1.0 );&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And in loop while sampling depth with offset to compare with kernel position, this depth should be in same space as position so I did it the same way:&#xD;&#xA;&#xD;&#xA;    float sampleDepth = viewPositionFromDepth(offset.xy).z;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is not the most optimal way though, but it worked for me.&#xD;&#xA;&#xD;&#xA;  [1]: https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14010" PostHistoryTypeId="50" PostId="4651" RevisionGUID="987202f1-032f-4948-b236-943e44d26566" CreationDate="2017-06-03T09:34:37.650" UserId="-1" />
  <row Id="14011" PostHistoryTypeId="2" PostId="5200" RevisionGUID="b918422c-be7e-472f-9613-365d571dc9a3" CreationDate="2017-06-03T09:54:23.520" UserId="6770" Text="I am trying to find a way to go from some proportion of cyan, magenta and yellow where: &#xD;&#xA;&#xD;&#xA;  cyan: 33 % + magenta : 33% + yellow : 33% = 100% black&#xD;&#xA;&#xD;&#xA;so each is represented as a percentage of the sum total. mixing 50% magenta and 50 % yellow should result in red. Mixing some colour with its complement would in effect mix some proportion of all three primaries and result in some amount of black and pulling it further towards one of the primaries, so mixing red and blue would mix cmy in some proportion which would result in some amount of black and a balance of the other two primaries so it would just change chroma.&#xD;&#xA;&#xD;&#xA;Any help is appreciated. I know that the gamuts of devices and colour models vary so it doesn't need to be perfect, it just needs to be intuitive for someone familiar with the cmy colour wheel to be able to use. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14012" PostHistoryTypeId="1" PostId="5200" RevisionGUID="b918422c-be7e-472f-9613-365d571dc9a3" CreationDate="2017-06-03T09:54:23.520" UserId="6770" Text="correct rgb or cmyk code from some proportion of cyan, magenta and yellow" ContentLicense="CC BY-SA 3.0" />
  <row Id="14013" PostHistoryTypeId="3" PostId="5200" RevisionGUID="b918422c-be7e-472f-9613-365d571dc9a3" CreationDate="2017-06-03T09:54:23.520" UserId="6770" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14014" PostHistoryTypeId="5" PostId="5200" RevisionGUID="0250b7ad-a618-46e7-84e8-ba1305c43f4c" CreationDate="2017-06-03T11:51:34.963" UserId="6770" Comment="added 227 characters in body" Text="I am trying to find a way to go from some proportion of cyan, magenta and yellow where: &#xD;&#xA;&#xD;&#xA;  cyan: 33 % + magenta : 33% + yellow : 33% = 100% black&#xD;&#xA;&#xD;&#xA;so each is represented as a percentage of the sum total. mixing 50% magenta and 50 % yellow should result in red. Mixing some colour with its complement would in effect mix some proportion of all three primaries and result in some amount of black and pulling it further towards one of the primaries, so mixing red and blue would mix cmy in some proportion which would result in some amount of black and a balance of the other two primaries so it would just change chroma.&#xD;&#xA;&#xD;&#xA;Any help is appreciated. I know that the gamuts of devices and colour models vary so it doesn't need to be perfect, it just needs to be intuitive for someone familiar with the cmy colour wheel to be able to use. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The desired output is an rgb colour code or a cmyk that could then be converted to rgb. &#xD;&#xA;&#xD;&#xA;There is no white so you're limited to the hues and shades that can be formed from the three primaries. I'm okay with that. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14015" PostHistoryTypeId="2" PostId="5201" RevisionGUID="ab99342a-de59-4292-ac38-db5038ff000d" CreationDate="2017-06-03T15:33:35.077" UserId="1952" Text="There are different numerical approximations you could use:&#xD;&#xA;&#xD;&#xA;A simple solution is to use brute-force Monte Carlo integration. Distribute $N$ random points on the polygon and calculate the number of points inside the 3D polyhedron $N_i$ using ray tracing. The area inside the polyhedron is $A_i=A\frac{N_i}{N}$, where $A$ is the area of the polygon.&#xD;&#xA;&#xD;&#xA;To improve convergence of the above algorithm, you can distribute the points on grid on the polygon and jitter the sample positions within each grid cell. This is called stratified sampling.&#xD;&#xA;&#xD;&#xA;Further improvement would be to perform the MC integration in 1D instead of 2D. Pick a sample line $L$ that's on the polygon plane and a sample direction $D$ that's on the plane parallel to $L$. Select sample line segment $L_s$ that bounds the polygon within $D$-directed lines (min &amp; max of the polygon projection on $L$ for tight fit). For each sample on $L_s$ first calculate the line segment $S$ that intersects the polygon in direction $D$. Next calculate the length of $S$ that's inside the polyhedron $S_i$. You can calculate $S_i$ using ray tracing, by starting from one end of $S$ and marching along $S$ to intersection points of the segment with the polyhedron, summing up the segments of $S$ inside the polyhedron. More specifically, you need to first check if the start point on $S$ is within polyhedron and set the &quot;inside&quot; state accordingly. Then for each intersection flip the state and add the length from previous intersection to $S_i$ if the state changes from inside to outside. The approximation of the polygon area inside the 3D polyhedron is:&#xD;&#xA;$$A_i=\frac{|L_s|}{N}\sum_{i=1}^N S_i$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14016" PostHistoryTypeId="5" PostId="5192" RevisionGUID="c3723354-efc7-4759-8319-bce87b859e17" CreationDate="2017-06-03T17:09:04.203" UserId="56" Comment="deleted 5 characters in body" Text="You can have blue noise sampling like these poisson disc samples:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And you can have a blue noise texture like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I get that in the first image, there is one input (the index of the sample) and two outputs (the x,y coordinate of the point) and that the second image is basically the reverse where there are two inputs (the x,y coordinate of the sample) and one output (the value of the point).&#xD;&#xA;&#xD;&#xA;I'm curious though, how are these related?&#xD;&#xA;&#xD;&#xA;If you take the DFT of the second image, you can see that it has more high frequency components than low, but I'm not sure how you'd take the DFT of the first set of data points.&#xD;&#xA;&#xD;&#xA;I'm wondering if it's possible to take other low discrepancy sequences (say, halton, or jittered grid) and make a texture out of the idea, like the second image?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DrzFt.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CgvI3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14017" PostHistoryTypeId="5" PostId="5201" RevisionGUID="9d73ea6f-28f5-4e8d-90cb-ed8767823d21" CreationDate="2017-06-03T22:13:34.263" UserId="1952" Comment="added 5 characters in body; edited body" Text="There are different numerical approximations you could use:&#xD;&#xA;&#xD;&#xA;A simple solution is to use brute-force Monte Carlo integration. Distribute $N$ random points on the polygon and calculate the number of points inside the 3D polyhedron $N_i$ using ray tracing. The area inside the polyhedron is $A_i=A\frac{N_i}{N}$, where $A$ is the area of the polygon.&#xD;&#xA;&#xD;&#xA;To improve convergence of the above algorithm, you can distribute the points on grid on the polygon and jitter the sample positions within each grid cell. This is called stratified sampling.&#xD;&#xA;&#xD;&#xA;Further improvement would be to perform the MC integration in 1D instead of 2D. Pick a sample line $L$ that's on the polygon plane and a sample direction $D$ that's on the plane perpendicular to $L$. Select sample line segment $L_s$ that bounds the polygon within $D$-directed lines (min &amp; max of the polygon projection on $L$ for tight fit). For each sample on $L_s$ first calculate the line segment $S$ that intersects the polygon in direction $D$. Next calculate the length of $S$ that's inside the polyhedron $S_i$. You can calculate $S_i$ using ray tracing, by starting from one end of $S$ and marching along $S$ to intersection points of the segment with the polyhedron, summing up the segments of $S$ inside the polyhedron. More specifically, you need to first check if the start point on $S$ is within polyhedron and set the &quot;inside&quot; state accordingly. Then for each intersection flip the state and add the length from previous intersection to $S_i$ if the state changes from inside to outside. The approximation of the polygon area inside the 3D polyhedron is:&#xD;&#xA;$$A_i=\frac{|L_s|}{N}\sum_{i=1}^N S_i$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14018" PostHistoryTypeId="2" PostId="5202" RevisionGUID="3156c62e-3fdd-4135-a763-b42adff5569a" CreationDate="2017-06-04T20:32:50.323" UserId="2695" Text=" First of all, I would like to state that handling the boundary conditions correctly is challenging, both from mathematical perspective and from an implementation perspective. Additionally, I think most of the papers don't explain the handling of boundary conditions sufficiently. &#xA;&#xA;Furthermore, it is worth noticing that you have to apply boundary conditions to both the velocity field and the pressure field (and they are linked to each other). Additionally, you have to distinguish between is the pressure solve (or projection step) and the diffusion step, which must be treated separately. &#xA;&#xA;In the very beginning you need to decide what kind of physical behavior you want to have at the boundaries. The standard example is a square surrounded by solid walls where no fluid can enter or leave. In this case you constrain the normal component of the velocity field to be zero ( a dirichlet boundary condition for the diffusion step). As we don't want changes for the normal component of the velocity in the projection step,  we also need to constrain the pressure. If you check the pressure update routine (which makes the velocity field divergency free) you can see that the derivative of the pressure field in direction of the normal must be zero, I.e. a Neumann boundary condition for the pressure field. &#xA;&#xA;With these considerations you need to set up your system of linear equations. For this it is worth to note the equations for some cells (I.e. one row of the system of linear equations) and check how the matrix and the right hand side must be modified to account for the boundary conditions. In a 2d scenario we have a 5 point Laplace stencil that results in a 4 on the diagonal and -1 for each of the adjacent cells (times some constants). In cells that are adjacent to the boundary there is at least one value that is outside of the simulation domain and care has to be taken what we do with this value. For homogenous dirichlet conditions this value is simply zero and no changes are required for the matrix and the right hand side. For Neumann boundaries the constraint is that there is no change across the boundary,  I.e. the value should be identical to the one of the cell. This reduces the value on the diagonal of the matrix by -1, I.e. 3 for a cell with one Neumann boundary. These considerations result in the linear system that you have to solve. &#xA;&#xA;The set bnd method (that doesn't appear in the paper by the way) is a trick to make the computations without the necessity to modify the matrix. This trick only works with gauss seidel or Jacobi iterations (As commented on your other question). The set bnd method is part of the code that stam published. Personally I find it difficult to read and understand because of the variable names and the &quot;b&quot; that changes the behavior significantly and that seems to confuse you as well (see your other question).&#xA;&#xA;There are more subtleties like singular systems for Neumann- only boundary conditions, central differences in staggered or standard grids, distance to the boundary (at cell border or at cell center outside three domain) etc., that I could address if you detail your question. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14019" PostHistoryTypeId="2" PostId="5203" RevisionGUID="fdce46ff-db87-4a9c-8264-ec487793bea5" CreationDate="2017-06-04T23:31:33.737" UserId="2707" Text="I'm trying to understand the [separable subsurface scattering][1] algorithm, but I'm a little confused on what the parameters mean from a notation and implementation standpoint, particularly for the artistic model (the paper includes two models). I'm also confused as to how the kernel should be placed in the equation.&#xD;&#xA;&#xD;&#xA;The equation used is:&#xD;&#xA;$$M_e(x,y) = \int \int E(x',y')\frac{1}{||a_p||_1}a_p(x-x')a_p(y-y')dx'dy'$$&#xD;&#xA;&#xD;&#xA;Later on the artistic model has a kernel equal to:&#xD;&#xA;$$a_m=wG(x,\sigma_{near})+(1-w)G(x,\sigma_{far})$$&#xD;&#xA;$$A_m=a_m(x)a_m(y)$$&#xD;&#xA;&#xD;&#xA;In the supplementary materials, there is an implementation clarification based on depth:&#xD;&#xA;$$a_m(\sqrt{d_{xy}^2+d_{z}^2}) \approx e^{\frac{-d_{z}^2}{2\sigma_{max}}}a_m(d_{xy})$$&#xD;&#xA;&#xD;&#xA;Would this be the correct final form?&#xD;&#xA;$$M_e(x,y)=\int \int E(x',y')e^{\frac{-d_{z}^2}{2\sigma_{max}}}a_m(d_{xy})e^{\frac{-d_{z}^2}{2\sigma_{max}}}a_m(d_{xy})dx'dy'$$&#xD;&#xA;&#xD;&#xA;where (some of these might not be correct interpretations):&#xD;&#xA;&#xD;&#xA; - $M_e$: output color&#xD;&#xA; - $E(x',y')$: color at sampling point (from color attachment)&#xD;&#xA; - $a_p$: kernel in one direction (not sure if this is somehow different than $a_m$)&#xD;&#xA; - $d_z$: linearized depth from depth buffer&#xD;&#xA; - $d_{xy}$: sampling points in the x and y direction (distance in x and y direction from the sampling point), not sure if this is in screen or world space&#xD;&#xA; - $w$: arbitrarily chosen weight between 0 and 1&#xD;&#xA; - $\sigma_{near}/\sigma_{far}$: diffuse profile for near/far Gaussian (3 color channels each), arbitrarily chosen&#xD;&#xA; - $\sigma_{max}$: $max(\sigma_{near}, \sigma_{far})$, this is keep the sampling from undersampling the larger Gaussian form my understanding&#xD;&#xA;&#xD;&#xA;  [1]: http://www.iryoku.com/separable-sss/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14020" PostHistoryTypeId="1" PostId="5203" RevisionGUID="fdce46ff-db87-4a9c-8264-ec487793bea5" CreationDate="2017-06-04T23:31:33.737" UserId="2707" Text="Is this the correct interpretation of the separable SSS artistic model?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14021" PostHistoryTypeId="3" PostId="5203" RevisionGUID="fdce46ff-db87-4a9c-8264-ec487793bea5" CreationDate="2017-06-04T23:31:33.737" UserId="2707" Text="|real-time|post-processing|subsurface-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14022" PostHistoryTypeId="5" PostId="5202" RevisionGUID="faa176c7-02cc-4eea-b168-d55edde74160" CreationDate="2017-06-05T01:47:30.270" UserId="2695" Comment="added 512 characters in body" Text=" First of all, I would like to state that handling the boundary conditions correctly is challenging, both from mathematical perspective and from an implementation perspective. Additionally, I think most of the papers don't explain the handling of boundary conditions sufficiently. &#xA;&#xA;Furthermore, it is worth noticing that you have to apply boundary conditions to both the velocity field and the pressure field (and they are linked to each other). Additionally, you have to distinguish between is the pressure solve (or projection step) and the diffusion step, which must be treated separately. &#xA;&#xA;In the very beginning you need to decide what kind of physical behavior you want to have at the boundaries. The standard example is a square surrounded by solid walls where no fluid can enter or leave. In this case you constrain the normal component of the velocity field to be zero ( a dirichlet boundary condition for the diffusion step). As we don't want changes for the normal component of the velocity in the projection step,  we also need to constrain the pressure. If you check the pressure update routine (which makes the velocity field divergency free) you can see that the derivative of the pressure field in direction of the normal must be zero, I.e. a Neumann boundary condition for the pressure field. &#xA;&#xA;Let's assume you are talking about the boundary conditions in the pressure solve/ projection step. Stam states that for pressure there is a Neumann boundary condition. As written above this condition implies that the velocity won't be modified at the last stage of the projection step (the pressure update). In order to achieve the dirichlet boundaries for the velocity as bridson states it, you require to have homogenous Neumann conditions. So for pressure, both authors have equivalent boundary conditions. &#xA;&#xA;With these considerations you need to set up your system of linear equations. For this it is worth to note the equations for some cells (I.e. one row of the system of linear equations) and check how the matrix and the right hand side must be modified to account for the boundary conditions. In a 2d scenario we have a 5 point Laplace stencil that results in a 4 on the diagonal and -1 for each of the adjacent cells (times some constants). In cells that are adjacent to the boundary there is at least one value that is outside of the simulation domain and care has to be taken what we do with this value. For homogenous dirichlet conditions this value is simply zero and no changes are required for the matrix and the right hand side. For Neumann boundaries the constraint is that there is no change across the boundary,  I.e. the value should be identical to the one of the cell. This reduces the value on the diagonal of the matrix by -1, I.e. 3 for a cell with one Neumann boundary. These considerations result in the linear system that you have to solve. &#xA;&#xA;The set bnd method (that doesn't appear in the paper by the way) is a trick to make the computations without the necessity to modify the matrix. This trick only works with gauss seidel or Jacobi iterations (As commented on your other question). The set bnd method is part of the code that stam published. Personally I find it difficult to read and understand because of the variable names and the &quot;b&quot; that changes the behavior significantly and that seems to confuse you as well (see your other question).&#xA;&#xA;There are more subtleties like singular systems for Neumann- only boundary conditions, central differences in staggered or standard grids, distance to the boundary (at cell border or at cell center outside three domain) etc., that I could address if you detail your question. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14023" PostHistoryTypeId="2" PostId="5204" RevisionGUID="9e1e0168-9987-49a8-8716-0243a6bea94b" CreationDate="2017-06-05T01:48:38.677" UserId="2707" Text="**Ambient occlusion** isn't a technique, but rather a concept. It can be implemented (and approximated) as a post-processing effect such as SSAO, SSDO, HBAO+, etc. @trichoplax gave a good answer, I just wanted to elaborate on the comments.&#xD;&#xA;&#xD;&#xA;&gt; Is there a reason why it's considered post-processing and deferred lighting/shading isn't?&#xD;&#xA;&#xD;&#xA;I personally would consider deferred rendering to be a post-processing effect, but it depends on your definition of a post-processing effect. For this answer, I will assume it's anything that doesn't require geometry other than a screen-space quad or ([triangle][1]) to be rendered.&#xD;&#xA;&#xD;&#xA;# Post-Process Techniques&#xD;&#xA;Screen space AO techniques involve reading the depth and/or normal buffers to determine if light should be occluded. There are expansions on these techniques that deal with temporal aliasing as well as [occlusions by objects in the scene][2]. Some people also apply AO to separate parts of the scene (dynamic and static objects for instance). This is where the definition of post-processing might become ambiguous.&#xD;&#xA;&#xD;&#xA;Some renderers do post-process AO before the lighting pass however. Usually these renderers either do a Z-prepass or are light-prepass renderers. This can be used on devices with lower VRAM or eDRAM to preserve memory since you can also do tonemapping during your lighting pass.&#xD;&#xA;&#xD;&#xA;# World-Space Static Techniques&#xD;&#xA;Lightmaps can be used particularly for static environments AO can be easily computed offline. Similarly, art assets can have AO textures.&#xD;&#xA;&#xD;&#xA;# World-Space Partially Dynamic Techniques&#xD;&#xA;Some objects just need rough AO and are largely rigid. For instance, [AO fields and decals][3] can be used with or without SSAO to improve AO for some objects (by Nathan Reed). Another example includes placing a circle around a character's feet.&#xD;&#xA;&#xD;&#xA;# World-Space Dynamic Techniques&#xD;&#xA;NVidia came up with [VXAO][4], which is a voxel-based ambient occlusion effect that helps simulate AO in places that aren't visible of screen. This has been one of the downsides to SSAO. Another issue with SSAO is that it must be computed each frame and is subject to temporal aliasing (bad for VR, although some people have developed improvements for this). VXAO can also reduce the memory/production costs of having many AO textures. Also, VXAO can have considerable latency with updates (if the application wants this). However, VXAO has a high performance cost.&#xD;&#xA;&#xD;&#xA;Other applications, such as voxel-based games, can approximate AO very easily by using algorithms based on neighborhood information. This is kind of similar to VXAO, but without the rasterization (voxelization) steps, and they may have much rougher approximations.&#xD;&#xA;&#xD;&#xA;As you can see, there are many implementations of AO, many of which aren't post-processing effects.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.saschawillems.de/?p=2148&#xD;&#xA;  [2]: http://graphics.cs.williams.edu/papers/DeepGBuffer14/&#xD;&#xA;  [3]: http://reedbeta.com/talks/ao-fields/&#xD;&#xA;  [4]: https://developer.nvidia.com/vxao-voxel-ambient-occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="14024" PostHistoryTypeId="5" PostId="5183" RevisionGUID="ad475003-b0ee-499f-b723-b23554ad18f6" CreationDate="2017-06-05T02:17:54.003" UserId="4978" Comment="added 109 characters in body" Text="I read [Stable Fluids][1] and [the code][3] by Jos Stam and [FLUID SIMULATION SIGGRAPH 2007 Course Notes][2] by Robert Bridson. The boundary conditions in the two papers are different in my sight. I don't understand them. How are these two ways related to solving a linear system of PDEs with boundary conditions? &#xD;&#xA;&#xD;&#xA;In Stam's paper, he uses a function called `set_bnd` to set boundaries, so is this function just setting the boundaries that I need in my matrix of linear systems of Pressure Poisson and Diffuse Equation? In Numerical Analysis, we don't modify the matrix with the boundary values, but we put the boundary condition either it's a Neumann or Dirichlet. I don't really understand what kind of boundaries is this `set_bnd` function. My thinking now is that it sets the boundary values which will be used to solve linear systems but what kind of boundaries?&#xD;&#xA;&#xD;&#xA;In Bridson's paper, I don't find any implementation about boundaries except for speaking about the normal components of velocity. Actually, I can't find any relation between this and Stam's way. In the section on making fluid incompressible, he says something about boundaries but I don't understand. He just satisfies boundary conditions on the boundary cells then he solves the system or he put the boundaries in the matrix?&#xD;&#xA;Actually I don't know how to satisfy `u*n = u_solid * n` which I think is the no stick boundaries for interacting between a fluid and solid boundaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.autodeskresearch.com/pdf/ns.pdf&#xD;&#xA;  [2]: http://www.cs.uu.nl/docs/vakken/mgp/2013-2014/literature/Fluid%20Simulation.pdf  &#xA;  [3]: https://www.autodeskresearch.com/sites/default/files/TheArtOfFluidAnimationCode.zip" ContentLicense="CC BY-SA 3.0" />
  <row Id="14025" PostHistoryTypeId="2" PostId="5205" RevisionGUID="90c4a0f9-257b-4970-af99-cef27e1a1c0d" CreationDate="2017-06-05T03:40:45.830" UserId="1988" Text="A reasonable approach is a continuous sample consensus method. The hough transform can be though of as a discrete sample consensus method, and so becomes intractable for some problems. Sample consensus is nice, because we can impose arbitrary constraints, and handle even the most horrific noise.&#xD;&#xA;&#xD;&#xA;# Getting Planes: Sample Consensus&#xD;&#xA;&#xD;&#xA;The idea is determine the minimum number of observations needed to form a hypothesis, and then check how many observations agree with that hypothesis. We'll call those observations &quot;inliers&quot;.&#xD;&#xA;&#xD;&#xA;1. Three point determine a plane. Select three points (deterministically, at random, whatever) from your dataset, fit a plane to them.&#xD;&#xA;&#xD;&#xA;2. Check how many points in your point cloud &quot;support&quot; the plane. Meaning that the plane existing in the world could explain what the sensor saw; the observations &quot;support&quot; the conclusion that the plane exists. For your case, a reasonable metric for &quot;support&quot; would be perpendicular distance to the plane.&#xD;&#xA;&#xD;&#xA;3. In postprocessing, you might cull planes that don't have sufficient width.&#xD;&#xA;&#xD;&#xA;# Extracting Parallel Planes: Normal Binning&#xD;&#xA;If you don't have a prior on the structure of your data other than &quot;has parallel planes&quot;, then you're likely trapped trying to discover as many planes as possible and then filtering for parallel ones.&#xD;&#xA;&#xD;&#xA;One might consider a &quot;binning&quot; approach&#xD;&#xA;&#xD;&#xA;1. Start with the first plane, and say its normal belongs to $bin_0$&#xD;&#xA;2. For each discovered plane, check the angle it makes with every existing bin&#xD;&#xA;3. If the angle is less than $\epsilon$, add that plane to $bin_n$&#xD;&#xA;4. If the angle is greater than (or equal, for completeness) to $\epsilon$, create a new bin, $bin_{n+1}$&#xD;&#xA;&#xD;&#xA;Presumably the largest bin is the thing you want if you have culled small planes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Other Notes&#xD;&#xA;&#xD;&#xA;Sample consensus will generally perform better if, after fitting to data and finding points that agree, you run a quick optimization to fit a plane to *all* of the inlier points. Then recompute inliers, and re-run the optimization. After all, it's quite unlikely that the three points you happened to choose were exactly the true plane. Much more likely is that varying plane parameters to minimize point-to-plane error over all of the inlier observations will yield a nice plane, with the noise averaged out." ContentLicense="CC BY-SA 3.0" />
  <row Id="14026" PostHistoryTypeId="5" PostId="5202" RevisionGUID="87c291ad-cef3-49dc-851e-0a5665d2aa6c" CreationDate="2017-06-05T10:19:28.820" UserId="2695" Comment="added 547 characters in body" Text=" First of all, I would like to state that handling the boundary conditions correctly is challenging, both from mathematical perspective and from an implementation perspective. Additionally, I think most of the papers don't explain the handling of boundary conditions sufficiently. &#xA;&#xA;Furthermore, it is worth noticing that you have to apply boundary conditions to both the velocity field and the pressure field (and they are linked to each other). Additionally, you have to distinguish between is the pressure solve (or projection step) and the diffusion step, which must be treated separately. &#xA;&#xA;In the very beginning you need to decide what kind of physical behavior you want to have at the boundaries. The standard example is a square surrounded by solid walls where no fluid can enter or leave. In this case you constrain the normal component of the velocity field to be zero ( a dirichlet boundary condition for the diffusion step). As we don't want changes for the normal component of the velocity in the projection step,  we also need to constrain the pressure. If you check the pressure update routine (which makes the velocity field divergency free) you can see that the derivative of the pressure field in direction of the normal must be zero, I.e. a Neumann boundary condition for the pressure field. &#xA;&#xA;Let's assume you are talking about the boundary conditions in the pressure solve/ projection step. Stam states that for pressure there is a Neumann boundary condition. As written above this condition implies that the velocity won't be modified at the last stage of the projection step (the pressure update). In order to achieve the dirichlet boundaries for the velocity as bridson states it, you require to have homogenous Neumann conditions. So for pressure, both authors have equivalent boundary conditions. &#xA;&#xA;With these considerations you need to set up your system of linear equations. For this it is worth to note the equations for some cells (I.e. one row of the system of linear equations) and check how the matrix and the right hand side must be modified to account for the boundary conditions. In a 2d scenario we have a 5 point Laplace stencil that results in a 4 on the diagonal and -1 for each of the adjacent cells (times some constants). In cells that are adjacent to the boundary there is at least one value that is outside of the simulation domain and care has to be taken what we do with this value. For homogenous dirichlet conditions this value is simply zero and no changes are required for the matrix and the right hand side. For Neumann boundaries the constraint is that there is no change across the boundary,  I.e. the value should be identical to the one of the cell. This reduces the value on the diagonal of the matrix by -1, I.e. 3 for a cell with one Neumann boundary. These considerations result in the linear system that you have to solve. &#xA;&#xA;The set bnd method (that doesn't appear in the paper by the way) is a trick to make the computations without the necessity to modify the matrix. This trick only works with gauss seidel or Jacobi iterations (As commented on your other question). The set bnd method is part of the code that stam published. Personally I find it difficult to read and understand because of the variable names and the &quot;b&quot; that changes the behavior significantly and that seems to confuse you as well (see your other question).&#xA;&#xA;Edit:&#xA;At first glance it looks like stam and bridson apply different boundary conditions, but they are actually the same. If we assume a solid body that is not moving and the velocity is zero before the pressure correction then the difference between them is zero. The term in parentheses in (4.23) will then be evaluated to -p_{i,j} which is exactly a  homogeneous Neumann boundary condition for the pressure. I've got the second edition of bridsons book,  where  this is explained in equation 5.3 and at the bottom of the page in more detail. &#xA;&#xA;There are more subtleties like singular systems for Neumann- only boundary conditions, central differences in staggered or standard grids, distance to the boundary (at cell border or at cell center outside three domain) etc., that I could address if you detail your question. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14027" PostHistoryTypeId="5" PostId="5202" RevisionGUID="659b2a8d-c62f-4df4-9fe0-c04c9847ba46" CreationDate="2017-06-05T10:36:35.620" UserId="2695" Comment="added 704 characters in body" Text=" First of all, I would like to state that handling the boundary conditions correctly is challenging, both from mathematical perspective and from an implementation perspective. Additionally, I think most of the papers don't explain the handling of boundary conditions sufficiently. &#xA;&#xA;Furthermore, it is worth noticing that you have to apply boundary conditions to both the velocity field and the pressure field (and they are linked to each other). Additionally, you have to distinguish between is the pressure solve (or projection step) and the diffusion step, which must be treated separately. &#xA;&#xA;In the very beginning you need to decide what kind of physical behavior you want to have at the boundaries. The standard example is a square surrounded by solid walls where no fluid can enter or leave. In this case you constrain the normal component of the velocity field to be zero ( a dirichlet boundary condition for the diffusion step). As we don't want changes for the normal component of the velocity in the projection step,  we also need to constrain the pressure. If you check the pressure update routine (which makes the velocity field divergency free) you can see that the derivative of the pressure field in direction of the normal must be zero, I.e. a Neumann boundary condition for the pressure field. &#xA;&#xA;Let's assume you are talking about the boundary conditions in the pressure solve/ projection step. Stam states that for pressure there is a Neumann boundary condition. As written above this condition implies that the velocity won't be modified at the last stage of the projection step (the pressure update). In order to achieve the dirichlet boundaries for the velocity as bridson states it, you require to have homogenous Neumann conditions. So for pressure, both authors have equivalent boundary conditions. &#xA;&#xA;With these considerations you need to set up your system of linear equations. For this it is worth to note the equations for some cells (I.e. one row of the system of linear equations) and check how the matrix and the right hand side must be modified to account for the boundary conditions. In a 2d scenario we have a 5 point Laplace stencil that results in a 4 on the diagonal and -1 for each of the adjacent cells (times some constants). In cells that are adjacent to the boundary there is at least one value that is outside of the simulation domain and care has to be taken what we do with this value. For homogenous dirichlet conditions this value is simply zero and no changes are required for the matrix and the right hand side. For Neumann boundaries the constraint is that there is no change across the boundary,  I.e. the value should be identical to the one of the cell. This reduces the value on the diagonal of the matrix by -1, I.e. 3 for a cell with one Neumann boundary. These considerations result in the linear system that you have to solve. &#xA;&#xA;The set bnd method (that doesn't appear in the paper by the way) is a trick to make the computations without the necessity to modify the matrix. This trick only works with gauss seidel or Jacobi iterations (As commented on your other question). The set bnd method is part of the code that stam published. Personally I find it difficult to read and understand because of the variable names and the &quot;b&quot; that changes the behavior significantly and that seems to confuse you as well (see your other question).&#xA;&#xA;Edit:&#xA;At first glance it looks like stam and bridson apply different boundary conditions, but they are actually the same. If we assume a solid body that is not moving and the velocity is zero before the pressure correction then the difference between them is zero. The term in parentheses in (4.23) will then be evaluated to -p_{i,j} which is exactly a  homogeneous Neumann boundary condition for the pressure. I've got the second edition of bridsons book,  where  this is explained in equation 5.3 and at the bottom of the page in more detail. &#xA;&#xA;Edit2: up to know we discussed the Neumann boundary conditions for the pressure. No slip/slip boundary conditions are applied to the velocity and for both (with non-moving walls) you need homogenized Neumann boundary conditions for the pressure. With stam's approach of discretization, I.e. storing all velocity components at the cell center it is easier to realize no slip boundary conditions as the boundary for all velocity components are at cell faces. So to realize no slip boundary conditions in the diffusion step (mathematically you can't realize no slip conditions with the Euler equations ( no diffusion)) you need to use homogeneous dirichlet boundary conditions for all velocity components.&#xA;&#xA;There are more subtleties like singular systems for Neumann- only boundary conditions, central differences in staggered or standard grids, distance to the boundary (at cell border or at cell center outside three domain) etc., that I could address if you detail your question. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14028" PostHistoryTypeId="5" PostId="5200" RevisionGUID="298d2ffd-e4de-41e5-a8fc-302671070443" CreationDate="2017-06-05T12:38:09.740" UserId="6770" Comment="added 99 characters in body" Text="I am trying to find a way to go from some proportion of cyan, magenta and yellow where: &#xD;&#xA;&#xD;&#xA;  cyan: 33 % + magenta : 33% + yellow : 33% = 100% black&#xD;&#xA;&#xD;&#xA;so each is represented as a percentage of the sum total. mixing 50% magenta and 50 % yellow should result in red. Mixing some colour with its complement would in effect mix some proportion of all three primaries and result in some amount of black and pulling it further towards one of the primaries, so mixing red and blue would mix cmy in some proportion which would result in some amount of black and a balance of the other two primaries so it would just change chroma.&#xD;&#xA;&#xD;&#xA;Any help is appreciated. I know that the gamuts of devices and colour models vary so it doesn't need to be perfect, it just needs to be intuitive for someone familiar with the cmy colour wheel to be able to use. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The desired output is an rgb colour code or a cmyk that could then be converted to rgb. &#xD;&#xA;&#xD;&#xA;There is no white so you're limited to the hues and shades that can be formed from the three primaries. I'm okay with that. &#xD;&#xA;&#xD;&#xA;Hey guys, I'm still trying to find a solution to this. If anyone could help it would be great. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14029" PostHistoryTypeId="2" PostId="5206" RevisionGUID="ae04803d-e3ce-49b9-980f-736c1c471fc9" CreationDate="2017-06-05T14:00:28.983" UserId="4978" Text="The answers of my questions is that Stam uses set_bnd to implement both the pressure boundary condition and the velocity. Bridson uses slip boundaries and he derives an equation for the pressure at boundaries. When you subtract the pressure gradient in the chorin's projection method he uses, the boundary condition of the pressure is forced. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14030" PostHistoryTypeId="2" PostId="5207" RevisionGUID="5b965899-6ac1-4751-8981-dcf4c37641b9" CreationDate="2017-06-05T16:32:23.167" UserId="5349" Text="First off, the CMYK model includes black as its own channel, so you typically don't mix a combo of cyan, magenta &amp; yellow to get black, you add black directly as its own independent element. There are a number of reasons for using black directly &amp; without knowing your context, it's difficult to advise you on how to get by without it. [What kind of black should I use when designing for CMYK print?](https://graphicdesign.stackexchange.com/questions/2984/what-kind-of-black-should-i-use-when-designing-for-cmyk-print) on the graphic design SE has some in depth answers regarding use of black by itself &amp; as a mixture (sometimes called composite black).&#xD;&#xA;&#xD;&#xA;Second, CMYK is a subtractive model for mixing inks based on the notion of reducing brightness. RGB is an additive model based on mixing lights. Because they use different models &amp; are both context dependent, there isn't a generalized conversion formula. The [RGB to CMYK and back algorithm](https://stackoverflow.com/questions/4858131/rgb-to-cmyk-and-back-algorithm) question on SO has a number of in depth answers regarding possible conversion algorithms. Again, it's hard to know what to suggest when you haven't clarified what you're using the colors for.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14031" PostHistoryTypeId="5" PostId="5200" RevisionGUID="79efa2e9-99e9-49e8-98c6-36a679565d19" CreationDate="2017-06-05T17:03:07.777" UserId="6770" Comment="added 1955 characters in body" Text="I am trying to find a way to go from some proportion of cyan, magenta and yellow where: &#xD;&#xA;&#xD;&#xA;  cyan: 33 % + magenta : 33% + yellow : 33% = 100% black&#xD;&#xA;&#xD;&#xA;so each is represented as a percentage of the sum total. mixing 50% magenta and 50 % yellow should result in red. Mixing some colour with its complement would in effect mix some proportion of all three primaries and result in some amount of black and pulling it further towards one of the primaries, so mixing red and blue would mix cmy in some proportion which would result in some amount of black and a balance of the other two primaries so it would just change chroma.&#xD;&#xA;&#xD;&#xA;Any help is appreciated. I know that the gamuts of devices and colour models vary so it doesn't need to be perfect, it just needs to be intuitive for someone familiar with the cmy colour wheel to be able to use. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The desired output is an rgb colour code or a cmyk that could then be converted to rgb. &#xD;&#xA;&#xD;&#xA;There is no white so you're limited to the hues and shades that can be formed from the three primaries. I'm okay with that. &#xD;&#xA;&#xD;&#xA;Hey guys, I'm still trying to find a solution to this. If anyone could help it would be great. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;This is for a game, the input is derived from some time value that represents a proportion of primary paints. Sort of.&#xD;&#xA;&#xD;&#xA;I realize that in cmyk k stands for key and is a black dye that is purer than the black that can be obtained from mixing the primaries. In my game cmyk is unimportant, only that I can mix three primary colours cyan, magenta and yellow to mix the colour wheel.&#xD;&#xA;&#xD;&#xA;It is unlikely that black will even be required, but the chroma effect of mixing some proportion of all three primaries together is required as I would want more than just the hues.  I appreciate that lightness of the hues is not possible without white but that is also fine.&#xD;&#xA;&#xD;&#xA;I want it so that given some floating point value for representing some proportion of each primary, I can calculate that as percentages and then resolve that to an rgb colour code. It need not be a perfect conversion as only the rgb colour will be displayed, the cmy will just be for the calculation. A close approximation will suffice.&#xD;&#xA;&#xD;&#xA;I don't need an especially wide gamut. I just need to be able to mix some proportion of the paints to mix a colour palette. If the player mixes equal parts of each primary then it would be black, if they keep mixing in magenta then it will become more and more magenta again as the volume of magenta dwarfs the volume of black. &#xD;&#xA;&#xD;&#xA;If you mix red and blue you're mixing magenta and yellow with magenta and cyan. &#xD;&#xA;&#xD;&#xA;I hope that clarifies some of the questions. The goal is to take the intuitive representation expressed to the player, three primary colours, and resolve that to a colour code that can be used to actually render to the screen.&#xD;&#xA;&#xD;&#xA;The player will be able to clear the colour so they can then return to a pure primary colour. But to mix any particular colour they will do so by mixing the primary colours. Hue, chroma and brightness should be possible though lightness isn't possible without white as this is subtractive. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14033" PostHistoryTypeId="5" PostId="5202" RevisionGUID="1b5f8cae-a37c-46db-8963-5d516474f526" CreationDate="2017-06-05T20:29:23.180" UserId="2695" Comment="added 790 characters in body" Text=" First of all, I would like to state that handling the boundary conditions correctly is challenging, both from mathematical perspective and from an implementation perspective. Additionally, I think most of the papers don't explain the handling of boundary conditions sufficiently. &#xD;&#xA;&#xD;&#xA;Furthermore, it is worth noticing that you have to apply boundary conditions to both the velocity field and the pressure field (and they are linked to each other). Additionally, you have to distinguish between is the pressure solve (or projection step) and the diffusion step, which must be treated separately. &#xD;&#xA;&#xD;&#xA;In the very beginning you need to decide what kind of physical behavior you want to have at the boundaries. The standard example is a square surrounded by solid walls where no fluid can enter or leave. In this case you constrain the normal component of the velocity field to be zero ( a dirichlet boundary condition for the diffusion step). As we don't want changes for the normal component of the velocity in the projection step,  we also need to constrain the pressure. If you check the pressure update routine (which makes the velocity field divergency free) you can see that the derivative of the pressure field in direction of the normal must be zero, I.e. a Neumann boundary condition for the pressure field. &#xD;&#xA;&#xD;&#xA;Let's assume you are talking about the boundary conditions in the pressure solve/ projection step. Stam states that for pressure there is a Neumann boundary condition. As written above this condition implies that the velocity won't be modified at the last stage of the projection step (the pressure update). In order to achieve the dirichlet boundaries for the velocity as bridson states it, you require to have homogenous Neumann conditions. So for pressure, both authors have equivalent boundary conditions. &#xD;&#xA;&#xD;&#xA;With these considerations you need to set up your system of linear equations. For this it is worth to note the equations for some cells (I.e. one row of the system of linear equations) and check how the matrix and the right hand side must be modified to account for the boundary conditions. In a 2d scenario we have a 5 point Laplace stencil that results in a 4 on the diagonal and -1 for each of the adjacent cells (times some constants). In cells that are adjacent to the boundary there is at least one value that is outside of the simulation domain and care has to be taken what we do with this value. For homogenous dirichlet conditions this value is simply zero and no changes are required for the matrix and the right hand side. For Neumann boundaries the constraint is that there is no change across the boundary,  I.e. the value should be identical to the one of the cell. This reduces the value on the diagonal of the matrix by -1, I.e. 3 for a cell with one Neumann boundary. These considerations result in the linear system that you have to solve. &#xD;&#xA;&#xD;&#xA;The set bnd method (that doesn't appear in the paper by the way) is a trick to make the computations without the necessity to modify the matrix. This trick only works with gauss seidel or Jacobi iterations (As commented on your other question). The set bnd method is part of the code that stam published. Personally I find it difficult to read and understand because of the variable names and the &quot;b&quot; that changes the behavior significantly and that seems to confuse you as well (see your other question).&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;At first glance it looks like stam and bridson apply different boundary conditions, but they are actually the same. If we assume a solid body that is not moving and the velocity is zero before the pressure correction then the difference between them is zero. The term in parentheses in (4.23) will then be evaluated to -p_{i,j} which is exactly a  homogeneous Neumann boundary condition for the pressure. I've got the second edition of bridsons book,  where  this is explained in equation 5.3 and at the bottom of the page in more detail. &#xD;&#xA;&#xD;&#xA;Edit2: up to know we discussed the Neumann boundary conditions for the pressure. No slip/slip boundary conditions are applied to the velocity and for both (with non-moving walls) you need homogenized Neumann boundary conditions for the pressure. With stam's approach of discretization, I.e. storing all velocity components at the cell center it is easier to realize no slip boundary conditions as the boundary for all velocity components are at cell faces. So to realize no slip boundary conditions in the diffusion step (mathematically you can't realize no slip conditions with the Euler equations ( no diffusion)) you need to use homogeneous dirichlet boundary conditions for all velocity components.&#xD;&#xA;&#xD;&#xA;Edit3: It is not straight forward to use the set_bnd method on a staggered grid for no slip boundary conditions. The storage for the tangential (to the boundary) components is not ideal. &#xD;&#xA;&#xD;&#xA;Edit 4: A Neumann boundary condition for the pressure implies that there are no changes for the (normal) velocity at this boundary. If you subtract the pressure gradient at such a boundary, the pressure gradient is simply zero due to the boundary condition. &#xD;&#xA;&#xD;&#xA;Edit 5: Slip / no slip boundary conditions (for the velocity) are not(!) realized in the pressure correction step. For non-moving solid walls there is always a homogeneous Neumann boundary condition for the pressure no matter if you impose a slip or no-slip boundary condition. &#xD;&#xA;&#xD;&#xA;Edit 6: I don't &quot;have&quot; facebook ;)&#xD;&#xA;&#xD;&#xA;There are more subtleties like singular systems for Neumann- only boundary conditions, central differences in staggered or standard grids, distance to the boundary (at cell border or at cell center outside three domain) etc., that I could address if you detail your question. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14034" PostHistoryTypeId="2" PostId="5208" RevisionGUID="ee5a76b1-399e-4d3e-8640-fb686eea6d5b" CreationDate="2017-06-06T09:12:49.437" UserId="2372" Text="The **Nine Patches** algorithm is a really nice and powerful solution if you are using textures but I ended up by using a fully procedural solution.&#xD;&#xA;&#xD;&#xA;I am just drawing a round box like this.&#xD;&#xA;&#xD;&#xA;    float udRoundBox( vec3 p, vec3 b, float r )&#xD;&#xA;    {&#xD;&#xA;      return length(max(abs(p)-b,0.0))-r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can simply avoid the 3rd dimension if you don't need it.&#xD;&#xA;This method comes from the [Distance function article][1] from **Inigo Quilez**.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="14035" PostHistoryTypeId="5" PostId="5185" RevisionGUID="60271765-bb22-4acc-9913-61a899840494" CreationDate="2017-06-06T09:40:14.763" UserId="110" Comment="Fix small typo" Text="I'm discovering the wonderful world of math and I'm hitting a huge wall with PBR and naming so I have a few questions:&#xD;&#xA;As far as I understand BRDF describe how a material react to light (incoming direct light and reflections). But in &quot;Cook-Torrance&quot; I don't see anything about reflections I don't understand how I integrate it so I only get diffuse light and reflections.&#xD;&#xA;&#xD;&#xA;I've read a lot about different &quot;diffuse term&quot; like &quot;Oren-Nayar&quot; is it a part of Cook-Torrance like a different &quot;D&quot; in the DFG nominator ? does it replace it without specular calculations ?&#xD;&#xA;&#xD;&#xA;I've read a lot about &quot;GGX&quot; from my blender artist background I thought it was something that make a blurry reflection but It seems I was wrong and now I find this GGX term in a lot of different situations like in micro-facet normal distribution in this [tutorial][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So in short the question is: how &quot;Oren-Nayar&quot; and &quot;GGX&quot; and &quot;Cook-Torrance&quot; are related to each other (if they are) and how do I integrate &quot;vec3 reflection&quot; in those algorithm ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As I said before I'm a newbie in math so If your answer is &quot;math heavy&quot; please write a glsl/hlsl version of your equations it's much easier to understand for me so an equivalence will help me a lot&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: I understand my question is blurry but it is also as blurry as my understanding of the subject.&#xD;&#xA;&#xD;&#xA;  [1]: http://learnopengl.com/#!PBR/Lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="14036" PostHistoryTypeId="24" PostId="5185" RevisionGUID="60271765-bb22-4acc-9913-61a899840494" CreationDate="2017-06-06T09:40:14.763" Comment="Proposed by 110 approved by 4958, 3073 edit id of 253" ContentLicense="CC BY-SA 3.0" />
  <row Id="14043" PostHistoryTypeId="2" PostId="5210" RevisionGUID="925590aa-d907-4c60-bee2-f8e1c9f51190" CreationDate="2017-06-06T12:02:46.587" UserId="6785" Text="I have a lot of data that I generate from an Excel spreadsheet and would like to render them graphically using OpenGL by launching it from within a VBA module.&#xD;&#xA; Here, I mean Visual Basic for **APPLICATIONS**, (not .NET). Could somebody give me a pointer on how to get started.&#xD;&#xA;&#xD;&#xA;I've written lots of C++ code with OpenGL, but I'd like to know how to get that first foot in the door with regards to including OpenGL in a VBA environment. I'm running Windows 7. Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="14044" PostHistoryTypeId="1" PostId="5210" RevisionGUID="925590aa-d907-4c60-bee2-f8e1c9f51190" CreationDate="2017-06-06T12:02:46.587" UserId="6785" Text="OpenGL with VBA" ContentLicense="CC BY-SA 3.0" />
  <row Id="14045" PostHistoryTypeId="3" PostId="5210" RevisionGUID="925590aa-d907-4c60-bee2-f8e1c9f51190" CreationDate="2017-06-06T12:02:46.587" UserId="6785" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14047" PostHistoryTypeId="50" PostId="4808" RevisionGUID="1cdcf2a6-065a-4dfe-ad6e-cf63209602c4" CreationDate="2017-06-06T16:30:18.970" UserId="-1" />
  <row Id="14048" PostHistoryTypeId="2" PostId="5211" RevisionGUID="bf691f96-a7e6-40c4-bf70-2d589cfd2703" CreationDate="2017-06-06T22:33:18.020" UserId="6788" Text="I'm trying to figure out the surface area of a mesh that is the result of various CSG union operations between an arbitrary number of other meshes by summing up the same property of each one of  it's faces (triangles, in this case) but the result is far greater than expected. I believe that this is happening because the mesh that results from the CSG union operations have internal faces, but I'm trying to find only the surface area of it's exterior.&#xD;&#xA;&#xD;&#xA;Is there any technique to remove the inner faces of a triangulated mesh, or maybe some way to just ignore these ones while calculating it's surface area?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14049" PostHistoryTypeId="1" PostId="5211" RevisionGUID="bf691f96-a7e6-40c4-bf70-2d589cfd2703" CreationDate="2017-06-06T22:33:18.020" UserId="6788" Text="Algorithm to remove inner faces of a triangulated mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="14050" PostHistoryTypeId="3" PostId="5211" RevisionGUID="bf691f96-a7e6-40c4-bf70-2d589cfd2703" CreationDate="2017-06-06T22:33:18.020" UserId="6788" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14053" PostHistoryTypeId="2" PostId="5212" RevisionGUID="37439e02-4a22-4738-aad5-98b617653103" CreationDate="2017-06-07T13:25:13.953" UserId="6791" Text="I have a problem of linear interpolation of [CRV (Conformal Rotation Vector)](https://books.google.fr/books?id=94HtCAAAQBAJ&amp;pg=PA9&amp;dq=Rigid+and+Flexible+Mechanisms+A+Finite+Element+Approach+Based+on+the+Conformal+Rotation+Vector&amp;hl=en&amp;sa=X&amp;redir_esc=y#v=onepage&amp;q=Rigid%20and%20Flexible%20Mechanisms%20A%20Finite%20Element%20Approach%20Based%20on%20the%20Conformal%20Rotation%20Vector&amp;f=false) in which CRVs are used to parameterize the orientations. &#xD;&#xA;&#xD;&#xA;In my knowledge, in order to derive a linear interpolation of orientations, we could apply a conversion from CRV into the corresponding unit quaternion, and then a SLERP ([Spherical Linear Interpolation](https://en.wikipedia.org/wiki/Slerp)) could be performed to interpolate linearly the orientation parametrized by CRVs. &#xD;&#xA;&#xD;&#xA;My question is: Could we derive an interpolation of quality directly using CRVs (in linear scope)? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14054" PostHistoryTypeId="1" PostId="5212" RevisionGUID="37439e02-4a22-4738-aad5-98b617653103" CreationDate="2017-06-07T13:25:13.953" UserId="6791" Text="Interpolation of orientations" ContentLicense="CC BY-SA 3.0" />
  <row Id="14055" PostHistoryTypeId="3" PostId="5212" RevisionGUID="37439e02-4a22-4738-aad5-98b617653103" CreationDate="2017-06-07T13:25:13.953" UserId="6791" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14056" PostHistoryTypeId="2" PostId="5213" RevisionGUID="e0e354a8-b265-4712-ae76-e5152ddd8caf" CreationDate="2017-06-07T16:25:00.687" UserId="6792" Text="If I have two applications that I've written running on a machine, is it possible to have one application inject triangles into the scene of the other application? So effectively, the data for meshes is coming from two different applications?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14057" PostHistoryTypeId="1" PostId="5213" RevisionGUID="e0e354a8-b265-4712-ae76-e5152ddd8caf" CreationDate="2017-06-07T16:25:00.687" UserId="6792" Text="Can one application inject triangles into the graphics pipeline of another application?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14058" PostHistoryTypeId="3" PostId="5213" RevisionGUID="e0e354a8-b265-4712-ae76-e5152ddd8caf" CreationDate="2017-06-07T16:25:00.687" UserId="6792" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14060" PostHistoryTypeId="2" PostId="5214" RevisionGUID="fa68d5c9-298e-4a34-88dc-31b40f147082" CreationDate="2017-06-08T10:06:10.043" UserId="6698" Text="I read &quot;A Practical Model for Subsurface Light Transport&quot; and &quot;A Rapid Hierarchical Rendering Technique for Translucent Materials&quot;. If I understand correctly, the former does not consider the case when an object is lit behind and we can see the light is going through it.&#xD;&#xA;&#xD;&#xA;The latter can achieve this but there is a preprocessing stage which is not suitable for my CUDA path tracer and I want it to be as natural as possible. So, do you have any paper in mind which is not obsolete or would you suggest me to solve the full radiative transfer equation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14061" PostHistoryTypeId="1" PostId="5214" RevisionGUID="fa68d5c9-298e-4a34-88dc-31b40f147082" CreationDate="2017-06-08T10:06:10.043" UserId="6698" Text="A recent approach for subsurface scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="14062" PostHistoryTypeId="3" PostId="5214" RevisionGUID="fa68d5c9-298e-4a34-88dc-31b40f147082" CreationDate="2017-06-08T10:06:10.043" UserId="6698" Text="|pathtracing|global-illumination|subsurface-scattering|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14063" PostHistoryTypeId="2" PostId="5215" RevisionGUID="53c0e919-345b-443b-a52d-3a24d7673b7b" CreationDate="2017-06-08T10:35:32.740" UserId="6660" Text="1.How can I update each render unit's uniform variables?&#xD;&#xA;&#xD;&#xA;I know there is one approach to solve question 1, which is using `glVertexAttribDivisor` to specify attribute value for each instance. And this means I should **change my variable's definition from uniform variable to attribute variable**. But in some case, I just want to render only one unit and use normal draw command(not instanced rendering), and here what I need is the uniform variable. So, here is question 2.&#xD;&#xA;&#xD;&#xA;2.Should I keep two version of the same shader program. One is using attribute variable for batch rendering, the other one is using uniform variable for normal rendering. Or Should I use batch rendering in every case even if there is only one unit for rendering?&#xD;&#xA;&#xD;&#xA;Since I am using batch rendering, so I should pack every render units can be batched into one big VBO. But, what if I am in a case where render units are dynamically changed, some new units are added in, and some units are subtracted out. So **I should reconstruct my VBO again and again in very frame.** So here is the question 3.&#xD;&#xA;&#xD;&#xA;3.Should I allocate a big enough storage in the first time and update the data in it, and only reallocate when run out of the storage, or allocate storage according to the size on demand in each frame?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14064" PostHistoryTypeId="1" PostId="5215" RevisionGUID="53c0e919-345b-443b-a52d-3a24d7673b7b" CreationDate="2017-06-08T10:35:32.740" UserId="6660" Text="Few questions about batch rendering with OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="14065" PostHistoryTypeId="3" PostId="5215" RevisionGUID="53c0e919-345b-443b-a52d-3a24d7673b7b" CreationDate="2017-06-08T10:35:32.740" UserId="6660" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14066" PostHistoryTypeId="2" PostId="5216" RevisionGUID="1f56da4b-f041-4223-bbae-da791529d9a8" CreationDate="2017-06-08T12:56:39.470" UserId="6092" Text="So this should be easy and simple, but I still can't get it to work. All I need is a small example program that:&#xD;&#xA;&#xD;&#xA; - Takes in a BufferedImage (TYPE_INT_ARGB)&#xD;&#xA; - Renders that BufferedImage on a textured quad&#xD;&#xA; - Using a VBO&#xD;&#xA; - Without additional shader declaration&#xD;&#xA; - Using LWJGL3" ContentLicense="CC BY-SA 3.0" />
  <row Id="14067" PostHistoryTypeId="1" PostId="5216" RevisionGUID="1f56da4b-f041-4223-bbae-da791529d9a8" CreationDate="2017-06-08T12:56:39.470" UserId="6092" Text="LWJGL/OpenGL render textured quad" ContentLicense="CC BY-SA 3.0" />
  <row Id="14068" PostHistoryTypeId="3" PostId="5216" RevisionGUID="1f56da4b-f041-4223-bbae-da791529d9a8" CreationDate="2017-06-08T12:56:39.470" UserId="6092" Text="|opengl|vertex-buffer-object|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14069" PostHistoryTypeId="2" PostId="5217" RevisionGUID="4eb701df-f0ef-4084-9795-e96c4c3c1598" CreationDate="2017-06-08T13:03:49.863" UserId="6662" Text="I am reading and trying to implement a research paper.&#xD;&#xA;It uses openGL to define which part of an image to use in order to reconstitute a big image composited of several images.&#xD;&#xA;&#xD;&#xA;In order to do so, I have to generate several masks and multiply them together for each image.&#xD;&#xA;&#xD;&#xA;One mask is the &quot;focus mask&quot;, and they say : &#xD;&#xA;&quot;We evaluate the per-pixel &quot;focusness&quot; of the source image using a sharpness operator that is the energy of the image Laplacian applied on a window of 20x20 pixels centered on each evaluated points&quot;.&#xD;&#xA;My incomprehension is that : isn't laplacian filter the convolution matrix &#xD;&#xA;&#xD;&#xA;     0  -1   0   or    -1  -1  -1&#xD;&#xA;    -1   4  -1         -1   8  -1&#xD;&#xA;     0  -1   0         -1  -1  -1&#xD;&#xA;?&#xD;&#xA;But it's of size 3x3 and not 20 x 20.&#xD;&#xA;The fact that i'm not a native english speaker maybe fools me on the words and there is something I don't understand in this sentance... Can you help me?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14070" PostHistoryTypeId="1" PostId="5217" RevisionGUID="4eb701df-f0ef-4084-9795-e96c4c3c1598" CreationDate="2017-06-08T13:03:49.863" UserId="6662" Text="Image Laplacian incomprehension" ContentLicense="CC BY-SA 3.0" />
  <row Id="14071" PostHistoryTypeId="3" PostId="5217" RevisionGUID="4eb701df-f0ef-4084-9795-e96c4c3c1598" CreationDate="2017-06-08T13:03:49.863" UserId="6662" Text="|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14072" PostHistoryTypeId="6" PostId="5217" RevisionGUID="c971a0e8-0ea4-46bc-a5ba-b8146d09cb45" CreationDate="2017-06-08T13:09:16.850" UserId="6662" Comment="edited tags" Text="|opengl|c++|pixel-graphics|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14073" PostHistoryTypeId="5" PostId="5216" RevisionGUID="11acecb3-9d8a-4bf1-81d9-d3f770769821" CreationDate="2017-06-08T13:46:55.850" UserId="6092" Comment="Added minimal not working example" Text="So this should be easy and simple, but I still can't get it to work. All I need is a small example program that:&#xD;&#xA;&#xD;&#xA; - Takes in a BufferedImage (TYPE_INT_ARGB)&#xD;&#xA; - Renders that BufferedImage on a textured quad&#xD;&#xA; - Using a VBO&#xD;&#xA; - Without additional shader declaration&#xD;&#xA; - Using LWJGL3&#xD;&#xA;&#xD;&#xA;Here's what I have got so far:&#xD;&#xA;&#xD;&#xA;    package togos.minecraft.maprend.guistandalone;&#xD;&#xA;    &#xD;&#xA;    import static org.lwjgl.glfw.GLFW.*;&#xD;&#xA;    import static org.lwjgl.opengl.GL11.*;&#xD;&#xA;    import static org.lwjgl.opengl.GL15.*;&#xD;&#xA;    import static org.lwjgl.system.MemoryUtil.NULL;&#xD;&#xA;    import java.io.IOException;&#xD;&#xA;    import java.nio.ByteBuffer;&#xD;&#xA;    import java.nio.FloatBuffer;&#xD;&#xA;    import org.lwjgl.BufferUtils;&#xD;&#xA;    import org.lwjgl.glfw.GLFWErrorCallback;&#xD;&#xA;    import org.lwjgl.glfw.GLFWKeyCallback;&#xD;&#xA;    import org.lwjgl.glfw.GLFWVidMode;&#xD;&#xA;    import org.lwjgl.glfw.GLFWWindowSizeCallback;&#xD;&#xA;    import org.lwjgl.opengl.GL;&#xD;&#xA;    import org.lwjgl.opengl.GLUtil;&#xD;&#xA;    import org.lwjgl.system.Callback;&#xD;&#xA;    &#xD;&#xA;    public class GuiMain2 {&#xD;&#xA;    &#xD;&#xA;    	// We need to strongly reference callback instances.&#xD;&#xA;    	private GLFWErrorCallback		errorCallback;&#xD;&#xA;    	private GLFWKeyCallback			keyCallback;&#xD;&#xA;    	private GLFWWindowSizeCallback	wsCallback;&#xD;&#xA;    	private Callback				debugProc;&#xD;&#xA;    &#xD;&#xA;    	// The window handle&#xD;&#xA;    	private long					window;&#xD;&#xA;    	private int						width, height;&#xD;&#xA;    &#xD;&#xA;    	public void run() {&#xD;&#xA;    		try {&#xD;&#xA;    			init();&#xD;&#xA;    			loop();&#xD;&#xA;    &#xD;&#xA;    			// Release window and window callbacks&#xD;&#xA;    			glfwDestroyWindow(window);&#xD;&#xA;    			keyCallback.free();&#xD;&#xA;    			wsCallback.free();&#xD;&#xA;    			if (debugProc != null)&#xD;&#xA;    				debugProc.free();&#xD;&#xA;    		} catch (IOException e) {&#xD;&#xA;    			e.printStackTrace();&#xD;&#xA;    		} finally {&#xD;&#xA;    			glfwTerminate();&#xD;&#xA;    			errorCallback.free();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	private void init() {&#xD;&#xA;    		glfwSetErrorCallback(errorCallback = GLFWErrorCallback.createPrint(System.err));&#xD;&#xA;    		if (!glfwInit())&#xD;&#xA;    			throw new IllegalStateException(&quot;Unable to initialize GLFW&quot;);&#xD;&#xA;    &#xD;&#xA;    		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);&#xD;&#xA;    		glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);&#xD;&#xA;    &#xD;&#xA;    		// Create the window&#xD;&#xA;    		window = glfwCreateWindow(300, 300, &quot;Hello World!&quot;, NULL, NULL);&#xD;&#xA;    		if (window == NULL)&#xD;&#xA;    			throw new RuntimeException(&quot;Failed to create the GLFW window&quot;);&#xD;&#xA;    &#xD;&#xA;    		// Setup a key callback. It will be called every time a key is pressed, repeated or released.&#xD;&#xA;    		glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {&#xD;&#xA;    &#xD;&#xA;    			@Override&#xD;&#xA;    			public void invoke(long window, int key, int scancode, int action, int mods) {&#xD;&#xA;    				if (key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_RELEASE)&#xD;&#xA;    					glfwSetWindowShouldClose(window, true); // We will detect this in our rendering loop&#xD;&#xA;    			}&#xD;&#xA;    		});&#xD;&#xA;    		glfwSetWindowSizeCallback(window, wsCallback = new GLFWWindowSizeCallback() {&#xD;&#xA;    &#xD;&#xA;    			@Override&#xD;&#xA;    			public void invoke(long window, int w, int h) {&#xD;&#xA;    				if (w &gt; 0 &amp;&amp; h &gt; 0) {&#xD;&#xA;    					width = w;&#xD;&#xA;    					height = h;&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    		});&#xD;&#xA;    &#xD;&#xA;    		GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());&#xD;&#xA;    		glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2);&#xD;&#xA;    		glfwMakeContextCurrent(window);&#xD;&#xA;    		glfwShowWindow(window);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	private void loop() throws IOException {&#xD;&#xA;    		GL.createCapabilities();&#xD;&#xA;    		debugProc = GLUtil.setupDebugMessageCallback();&#xD;&#xA;    &#xD;&#xA;    		glEnable(GL_TEXTURE_2D);&#xD;&#xA;    		glEnable(GL_COLOR_MATERIAL);&#xD;&#xA;    		glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;    		glEnableClientState(GL_TEXTURE_COORD_ARRAY);&#xD;&#xA;    &#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;    		float[] vertices = {&#xD;&#xA;    				-0.5f, -0.5f, 0, 0,&#xD;&#xA;    				0.5f, -0.5f, 1, 0,&#xD;&#xA;    				0.5f, 0.5f, 1, 1,&#xD;&#xA;    				-0.5f, 0.5f, 0, 1 };&#xD;&#xA;    		int vbo = glGenBuffers();&#xD;&#xA;    		glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    		glBufferData(GL_ARRAY_BUFFER, (FloatBuffer) BufferUtils.createFloatBuffer(vertices.length).put(vertices).flip(), GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    		int id = genTexture();&#xD;&#xA;    		while (!glfwWindowShouldClose(window)) {&#xD;&#xA;    			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    			glViewport(0, 0, width, height);&#xD;&#xA;    			glMatrixMode(GL_PROJECTION);&#xD;&#xA;    			float aspect = (float) width / height;&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    			glOrtho(-aspect, aspect, -1, 1, -1, 1);&#xD;&#xA;    &#xD;&#xA;    			{// Rendering&#xD;&#xA;    				glBindTexture(GL_TEXTURE_2D, id);&#xD;&#xA;    				glVertexPointer(2, GL_FLOAT, 4 * 4, 0L);&#xD;&#xA;    				glTexCoordPointer(2, GL_FLOAT, 4 * 4, 4 * 2);&#xD;&#xA;    				glDrawArrays(GL_QUADS, 0, 4);&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			glfwSwapBuffers(window);&#xD;&#xA;    			glfwPollEvents();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	public int genTexture() {&#xD;&#xA;    		int id = glGenTextures();&#xD;&#xA;    		glBindTexture(GL_TEXTURE_2D, id);&#xD;&#xA;    		ByteBuffer pixels = BufferUtils.createByteBuffer(512 * 512 * 4);&#xD;&#xA;    &#xD;&#xA;    		for (int y = 0; y &lt; 512; y++) {&#xD;&#xA;    			for (int x = 0; x &lt; 512; x++) {&#xD;&#xA;    				pixels.put((byte) 255);&#xD;&#xA;    				pixels.put((byte) 0);&#xD;&#xA;    				pixels.put((byte) 0);&#xD;&#xA;    				pixels.put((byte) 255);&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    		pixels.flip();&#xD;&#xA;    &#xD;&#xA;    		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);&#xD;&#xA;    		return id;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	public static void main(String[] args) {&#xD;&#xA;    		new GuiMain2().run();&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When starting, it displays a white quad in the center of the screen. If textures were working, that quad would be red. And I can't get textures to work." ContentLicense="CC BY-SA 3.0" />
  <row Id="14074" PostHistoryTypeId="2" PostId="5218" RevisionGUID="1a51248c-6d08-4f00-b414-6cd5fe50f739" CreationDate="2017-06-08T15:26:10.153" UserId="6092" Text="I figured it out myself, again: just add&#xD;&#xA;&#xD;&#xA;		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;behind the glTexImage2D command and it works as intended." ContentLicense="CC BY-SA 3.0" />
  <row Id="14075" PostHistoryTypeId="6" PostId="5214" RevisionGUID="c4c24a3d-0c0b-494c-a0f9-b34b2025dd91" CreationDate="2017-06-08T16:23:29.667" UserId="6698" Comment="edited tags" Text="|raytracing|pathtracing|global-illumination|subsurface-scattering|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14076" PostHistoryTypeId="5" PostId="5217" RevisionGUID="b9153a81-e639-4ec2-9c26-26f2ec1af810" CreationDate="2017-06-08T20:26:15.853" UserId="231" Comment="Tidying" Text="I am reading and trying to implement a research paper.&#xD;&#xA;It uses openGL to define which part of an image to use in order to reconstitute a big image composited of several images.&#xD;&#xA;&#xD;&#xA;In order to do so, I have to generate several masks and multiply them together for each image.&#xD;&#xA;&#xD;&#xA;One mask is the &quot;focus mask&quot;, and they say:&#xD;&#xA;&#xD;&#xA;&gt; We evaluate the per-pixel &quot;focusness&quot; of the source image using a sharpness operator that is the energy of the image Laplacian applied on a window of 20x20 pixels centered on each evaluated points.&#xD;&#xA;&#xD;&#xA;My incomprehension is that: isn't Laplacian filter the convolution matrix:&#xD;&#xA;&#xD;&#xA;     0  -1   0   or    -1  -1  -1&#xD;&#xA;    -1   4  -1         -1   8  -1&#xD;&#xA;     0  -1   0         -1  -1  -1&#xD;&#xA;&#xD;&#xA;But it's of size 3 x 3 and not 20 x 20.&#xD;&#xA;The fact that I'm not a native english speaker maybe fools me on the words and there is something I don't understand in this sentence..." ContentLicense="CC BY-SA 3.0" />
  <row Id="14077" PostHistoryTypeId="5" PostId="5215" RevisionGUID="2c000997-a9d0-43f6-93db-0ec5baf7319b" CreationDate="2017-06-09T02:53:48.173" UserId="6660" Comment="deleted 751 characters in body; edited title" Text="Since I am using batch rendering, so I should pack every render units can be batched into one big VBO. But, what if I am in a case where render units are dynamically changed, some new units are added in, and some units are subtracted out. So **I should reconstruct my VBO again and again in very frame.** So here is the question.&#xD;&#xA;&#xD;&#xA;Should I allocate a big enough storage in the first time and update the data in it, and only reallocate when run out of the storage, or allocate storage according to the size on demand in each frame?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14078" PostHistoryTypeId="4" PostId="5215" RevisionGUID="2c000997-a9d0-43f6-93db-0ec5baf7319b" CreationDate="2017-06-09T02:53:48.173" UserId="6660" Comment="deleted 751 characters in body; edited title" Text="How can deal with batch rendering when the elements in the batch changed every frame?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14080" PostHistoryTypeId="2" PostId="5219" RevisionGUID="a18064e1-652e-434f-b31c-288c4e86df48" CreationDate="2017-06-09T04:22:51.870" UserId="48" Text="Allocate a VBO with a reasonable amount of storage during startup, and update the data in it each frame. This will help the driver manage the memory efficiently. Don't destroy and recreate the buffer unless absolutely necessary; too much resource creation/destruction churn will put more pressure on the driver and can potentially lead to stalls.&#xD;&#xA;&#xD;&#xA;To be more specific: for data that will be updated every frame, you probably want to initialize it using [glBufferStorage](http://docs.gl/gl4/glBufferStorage) with `GL_DYNAMIC_STORAGE_BIT` (or, if you're on an older OpenGL version, [glBufferData](http://docs.gl/gl4/glBufferData) with `GL_DYNAMIC_DRAW`). Then, to update it each frame, use [glMapBufferRange](http://docs.gl/gl4/glMapBufferRange) with `GL_MAP_INVALIDATE_BUFFER_BIT`. This should be an efficient, fast path in the graphics driver." ContentLicense="CC BY-SA 3.0" />
  <row Id="14081" PostHistoryTypeId="5" PostId="5217" RevisionGUID="2f82ca85-bbec-4c46-b2e3-69674a556c00" CreationDate="2017-06-09T09:54:44.387" UserId="6662" Comment="added 255 characters in body" Text="I am reading and trying to implement a research paper.&#xD;&#xA;It uses openGL to define which part of an image to use in order to reconstitute a big image composited of several images.&#xD;&#xA;&#xD;&#xA;In order to do so, I have to generate several masks and multiply them together for each image.&#xD;&#xA;&#xD;&#xA;One mask is the &quot;focus mask&quot;, and they say:&#xD;&#xA;&#xD;&#xA;&gt; We evaluate the per-pixel &quot;focusness&quot; of the source image using a sharpness operator that is the energy of the image Laplacian applied on a window of 20x20 pixels centered on each evaluated points.&#xD;&#xA;&#xD;&#xA;My incomprehension is that: isn't Laplacian filter the convolution matrix:&#xD;&#xA;&#xD;&#xA;     0  -1   0   or    -1  -1  -1&#xD;&#xA;    -1   4  -1         -1   8  -1&#xD;&#xA;     0  -1   0         -1  -1  -1&#xD;&#xA;&#xD;&#xA;But it's of size 3 x 3 and not 20 x 20.&#xD;&#xA;The fact that I'm not a native english speaker maybe fools me on the words and there is something I don't understand in this sentence...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT : &#xD;&#xA;The PDF with the article is downloadable [here][1] for free.&#xD;&#xA;=&gt; §4.1 : Focus Mask&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/publication/220252497_Masked_photo_blending_Mapping_dense_photographic_data_set_on_high-resolution_sampled_3D_models" ContentLicense="CC BY-SA 3.0" />
  <row Id="14082" PostHistoryTypeId="2" PostId="5220" RevisionGUID="5bc2a765-518a-46b0-8161-7220ebb89492" CreationDate="2017-06-09T14:22:04.883" UserId="5256" Text="Can somebody explain how to implement volume rendering and scattering? I've been told that this is the easiest and most effective method to render things like smoke, milk and fog. &#xD;&#xA;&#xD;&#xA;Scratchapixel has a great article about it [here][1] but the lesson on implementation is unavailable. &#xD;&#xA;&#xD;&#xA;I understand what Ray Marching is because of this [answer][2] from a while back but similiar to my previous problem I have no idea how to implement it. &#xD;&#xA;&#xD;&#xA;To make it clear and narrow this question down so it is easier to answer here are my main problems:&#xD;&#xA;&#xD;&#xA; 1. Can someone provide some pseudo code or code of a basic Volume&#xD;&#xA;    Rendering and Ray Marching loop with Absorption &amp; Scattering&#xD;&#xA;    coefficients, Phase Function and a Density function?&#xD;&#xA; 2. How is Ray Marching used alongside Path Tracing?&#xD;&#xA; 3. Is this the best way to render sub surface scattering?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/advanced-rendering/volume-rendering-for-artists&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/4412/volume-rendering-path-tracing-real-time" ContentLicense="CC BY-SA 3.0" />
  <row Id="14083" PostHistoryTypeId="1" PostId="5220" RevisionGUID="5bc2a765-518a-46b0-8161-7220ebb89492" CreationDate="2017-06-09T14:22:04.883" UserId="5256" Text="Volume Rendering: Implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="14084" PostHistoryTypeId="3" PostId="5220" RevisionGUID="5bc2a765-518a-46b0-8161-7220ebb89492" CreationDate="2017-06-09T14:22:04.883" UserId="5256" Text="|pathtracing|subsurface-scattering|raymarching|volumetric-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14085" PostHistoryTypeId="2" PostId="5221" RevisionGUID="d25f7dc6-942e-476c-a7df-d7eb2c03ffb7" CreationDate="2017-06-09T14:44:20.620" UserId="6806" Text="I wonder the variance for the Monte Carlo.&#xD;&#xA;The book (Advanced Global Illumination 2ed, p.60) writes the equation as follows:&#xD;&#xA;&#xD;&#xA;$\sigma^2 = \frac{1}{N} \int(\frac{f(x)}{p(x)} - I)^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\color{red}{\frac{1}{N} \int(\frac{f(x)}{p(x)})^2p(x)dx  -I^2}$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)}dx  -I^2$&#xD;&#xA;&#xD;&#xA;However, the equation is correct. I think the red area is wrong and the equation should be changed as follows:&#xD;&#xA;&#xD;&#xA;$\sigma^2 = \frac{1}{N} \int(\frac{f(x)}{p(x)} - I)^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\color{red}{\frac{1}{N} \int((\frac{f(x)}{p(x)})^2 -2\frac{f(x)}{p(x)} + I^2)p(x)dx}$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} - 2f(x) + I^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} - 2f(x) dx \space + \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} dx - \frac{2}{N}I^2 \space + \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} dx - \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is it right?&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14086" PostHistoryTypeId="1" PostId="5221" RevisionGUID="d25f7dc6-942e-476c-a7df-d7eb2c03ffb7" CreationDate="2017-06-09T14:44:20.620" UserId="6806" Text="The variance for the Monte Carlo estimator" ContentLicense="CC BY-SA 3.0" />
  <row Id="14087" PostHistoryTypeId="3" PostId="5221" RevisionGUID="d25f7dc6-942e-476c-a7df-d7eb2c03ffb7" CreationDate="2017-06-09T14:44:20.620" UserId="6806" Text="|global-illumination|monte-carlo|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14088" PostHistoryTypeId="5" PostId="5221" RevisionGUID="bf465bf3-a63f-4a5e-a3ca-fba7b0586c75" CreationDate="2017-06-09T15:01:02.207" UserId="209" Comment="Fixed typos &amp; minor improvement to English" Text="I was wondering about the variance for Monte Carlo.&#xD;&#xA;The book (Advanced Global Illumination 2ed, p.60) writes the equation as follows:&#xD;&#xA;&#xD;&#xA;$\sigma^2 = \frac{1}{N} \int(\frac{f(x)}{p(x)} - I)^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\color{red}{\frac{1}{N} \int(\frac{f(x)}{p(x)})^2p(x)dx  -I^2}$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)}dx  -I^2$&#xD;&#xA;&#xD;&#xA;However, the equation appears incorrect. I think the red area is wrong and the equation should be changed as follows:&#xD;&#xA;&#xD;&#xA;$\sigma^2 = \frac{1}{N} \int(\frac{f(x)}{p(x)} - I)^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\color{red}{\frac{1}{N} \int((\frac{f(x)}{p(x)})^2 -2\frac{f(x)}{p(x)} + I^2)p(x)dx}$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} - 2f(x) + I^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} - 2f(x) dx \space + \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} dx - \frac{2}{N}I^2 \space + \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} dx - \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is it right?&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14089" PostHistoryTypeId="2" PostId="5222" RevisionGUID="c06f83d6-faff-4ac1-ad3a-ee04e9978409" CreationDate="2017-06-09T19:18:56.963" UserId="20501" Text="Let's assume we have a 3D object (in 3D space). We get a single representation vertex from this whole 3D object. Given the fact that the object can be moved and rotated in the space in any direction, what are the minimum set of other information to add to uniquely identify the object's direction and translation in space?&#xD;&#xA;&#xD;&#xA;For instance lets consider this 3D object. If we have one single point as a reference, we can construct the whole object (the spatial dependency of other points/vertices are known). The single point can infer the movement. But the object can also rotate in any axis. I was initially thinking with a single normal vector added we can infer the object in space. But looks like we need at least two vectors (am I right?) because the object can also rotate around the normal vector. If we have another vector (maybe orthogonal to the first one), we can infer the whole 3D location. With that we can infer the degree of rotation around the normal axis. Is this right?&#xD;&#xA;&#xD;&#xA;Another alternative can be to store 3 reference points. Right?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/73jq5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14090" PostHistoryTypeId="1" PostId="5222" RevisionGUID="c06f83d6-faff-4ac1-ad3a-ee04e9978409" CreationDate="2017-06-09T19:18:56.963" UserId="20501" Text="Minimum requirements to uniquely represent a 3D object in space" ContentLicense="CC BY-SA 3.0" />
  <row Id="14091" PostHistoryTypeId="3" PostId="5222" RevisionGUID="c06f83d6-faff-4ac1-ad3a-ee04e9978409" CreationDate="2017-06-09T19:18:56.963" UserId="20501" Text="|3d|transformations|computational-geometry|normal-mapping|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14092" PostHistoryTypeId="2" PostId="5223" RevisionGUID="5bcae033-a997-4757-9618-0e10899a9776" CreationDate="2017-06-10T01:38:28.147" UserId="6811" Text="I'm trying to implement metropolis light transport based on [this paper][1], and I have the basic thing working. I run the algorithm multiple times with different starting points, add the results for each starting point together and multiply them by a scaling factor to approximate the real image.&#xD;&#xA;&#xD;&#xA;The scaling factor is the one described in the paper:&#xD;&#xA;&#xD;&#xA;$average\_brightess / average\_samples\_per\_pixel$.&#xD;&#xA;&#xD;&#xA;In the resulting image, the starting points are noticeably brighter. The paper I was reading doesn't have any advice on avoiding this start up bias. I found this [other paper][2] that has advice on this, but I find the paper a little hard to understand.&#xD;&#xA;&#xD;&#xA;It says each initial path should be assigned a weight $f(x_0) / p_0(x_0)$. &#xD;&#xA;&#xD;&#xA;$f(x_0)$ should be the luminance of the sample at the starting point $x_0$, but is it raw luminance or normalized? $p_0$ is supposed to be a path distribution (possibly sampled by path tracing). How do I get the value of a path distribution at a specified point? Is it the ratio of the point's luminance over the average luminance of the distribution (i.e. average brightness of the image)?&#xD;&#xA;&#xD;&#xA;Any help would be appreciated, thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pdfs.semanticscholar.org/a386/55316ee7f438ba115b38e8d0b1410c691a26.pdf&#xD;&#xA;  [2]: https://graphics.stanford.edu/papers/metro/metro.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14093" PostHistoryTypeId="1" PostId="5223" RevisionGUID="5bcae033-a997-4757-9618-0e10899a9776" CreationDate="2017-06-10T01:38:28.147" UserId="6811" Text="Help with start up bias in Metropolis Light Transport" ContentLicense="CC BY-SA 3.0" />
  <row Id="14094" PostHistoryTypeId="3" PostId="5223" RevisionGUID="5bcae033-a997-4757-9618-0e10899a9776" CreationDate="2017-06-10T01:38:28.147" UserId="6811" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14095" PostHistoryTypeId="5" PostId="5223" RevisionGUID="749f0285-7171-4ba3-af57-0eb70f1d92a5" CreationDate="2017-06-10T06:37:36.147" UserId="231" Comment="Remove thanks and add tag" Text="I'm trying to implement metropolis light transport based on [this paper][1], and I have the basic thing working. I run the algorithm multiple times with different starting points, add the results for each starting point together and multiply them by a scaling factor to approximate the real image.&#xD;&#xA;&#xD;&#xA;The scaling factor is the one described in the paper:&#xD;&#xA;&#xD;&#xA;$average\_brightess / average\_samples\_per\_pixel$.&#xD;&#xA;&#xD;&#xA;In the resulting image, the starting points are noticeably brighter. The paper I was reading doesn't have any advice on avoiding this start up bias. I found this [other paper][2] that has advice on this, but I find the paper a little hard to understand.&#xD;&#xA;&#xD;&#xA;It says each initial path should be assigned a weight $f(x_0) / p_0(x_0)$. &#xD;&#xA;&#xD;&#xA;$f(x_0)$ should be the luminance of the sample at the starting point $x_0$, but is it raw luminance or normalized? $p_0$ is supposed to be a path distribution (possibly sampled by path tracing). How do I get the value of a path distribution at a specified point? Is it the ratio of the point's luminance over the average luminance of the distribution (i.e. average brightness of the image)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pdfs.semanticscholar.org/a386/55316ee7f438ba115b38e8d0b1410c691a26.pdf&#xD;&#xA;  [2]: https://graphics.stanford.edu/papers/metro/metro.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14096" PostHistoryTypeId="6" PostId="5223" RevisionGUID="749f0285-7171-4ba3-af57-0eb70f1d92a5" CreationDate="2017-06-10T06:37:36.147" UserId="231" Comment="Remove thanks and add tag" Text="|rendering|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14097" PostHistoryTypeId="5" PostId="5223" RevisionGUID="5f6160aa-bef7-4dd6-90ac-57a94d1558a6" CreationDate="2017-06-10T08:52:00.293" UserId="6811" Comment="Added image" Text="I'm trying to implement metropolis light transport based on [this paper][1], and I have the basic thing working. I run the algorithm multiple times with different starting points, add the results for each starting point together and multiply them by a scaling factor to approximate the real image.&#xD;&#xA;&#xD;&#xA;The scaling factor is the one described in the paper:&#xD;&#xA;&#xD;&#xA;$average\_brightess / average\_samples\_per\_pixel$.&#xD;&#xA;&#xD;&#xA;In the resulting image, the starting points are noticeably brighter (they are aligned in a grid below).&#xD;&#xA;&#xD;&#xA;[![resulting image][2]][2]&#xD;&#xA;&#xD;&#xA;The paper I was reading doesn't have any advice on avoiding this start up bias. I found this [other paper][3] that has advice on this, but I find the paper a little hard to understand.&#xD;&#xA;&#xD;&#xA;It says each initial path should be assigned a weight $f(x_0) / p_0(x_0)$. &#xD;&#xA;&#xD;&#xA;$f(x_0)$ should be the luminance of the sample at the starting point $x_0$, but is it raw luminance or normalized? $p_0$ is supposed to be a path distribution (possibly sampled by path tracing). How do I get the value of a path distribution at a specified point? Is it the ratio of the point's luminance over the average luminance of the distribution (i.e. average brightness of the image)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pdfs.semanticscholar.org/a386/55316ee7f438ba115b38e8d0b1410c691a26.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/YT0qH.png&#xD;&#xA;  [3]: https://graphics.stanford.edu/papers/metro/metro.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14098" PostHistoryTypeId="2" PostId="5224" RevisionGUID="7dfd7dfb-6bfb-429c-8bb2-299c1d555542" CreationDate="2017-06-10T10:28:12.517" UserId="38" Text="A spatial object has 6 degrees of freedom. So that means you need 6 values to represent the object. The common way to do this is to store 1 vector for position and 3 rotations. But for obvious reasons any 6 variables that are independent of each other would do this.  &#xD;&#xA;&#xD;&#xA;The problem with vectors is that they arent the most eficient way to store the data. If you have a vector for origin and a normal you still need one value for the rotation around the normal resulting in seven variables (this is called an axis angle rotation). Ofcourse 2 reference points on object has same problem since you dont know the rotation around the axis of point 1 and point 2 leading to 7 variables.&#xD;&#xA;&#xD;&#xA;Now storing extra values can be beneficial for other purposes than position and orientation. So it is quite common to store 7 values for solid bodies. This way it is easier to interpolate so that you dont need to convert between representations all the time." ContentLicense="CC BY-SA 3.0" />
  <row Id="14099" PostHistoryTypeId="5" PostId="5224" RevisionGUID="9efd4f19-0d6f-4ab7-905f-b6878ebbfde1" CreationDate="2017-06-10T11:39:07.803" UserId="38" Comment="added 191 characters in body" Text="A rigid body has 6 degrees of freedom, in 3D- space. So that means you need 6 values to represent the object. The common way to do this is to store a position vector for position and 3 rotations. But for obvious reasons any 6 variables that are independent of each other would do this.  &#xD;&#xA;&#xD;&#xA;The problem with vectors is that they aren't the most efficient way to store the data. If you have a vector for origin and a normal you still need one value for the rotation around the normal resulting in seven variables (this is called an axis angle rotation). Two reference points on object has same problem since you dont know the rotation around the axis of point 1 and point 2 leading to 7 variables.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Storing vectors of 2 points has a freedom to rotate along the axis of those the vectors &#xD;&#xA;&#xD;&#xA;Now storing extra values can be beneficial for other purposes than position and orientation. So it is quite common to store 7 values for solid bodies. This way it is easier to interpolate so that you dont need to convert between representations all the time.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UkkSi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14101" PostHistoryTypeId="2" PostId="5225" RevisionGUID="718595e9-bee1-42eb-901d-955ccb3a0e03" CreationDate="2017-06-10T21:43:46.077" UserId="48" Text="I don't have that book to check the context of this, but from the equations you posted, yes, it looks like you're right. The $1/N$ factor should be applied to both terms. That agrees with the formula for variance from statistics, which is $E[X^2] - E[X]^2$." ContentLicense="CC BY-SA 3.0" />
  <row Id="14102" PostHistoryTypeId="2" PostId="5226" RevisionGUID="0fd195b3-454d-4555-b745-daf74e19dd0f" CreationDate="2017-06-11T02:46:46.023" UserId="6814" Text="(If this is a better fit for ux.stackexchange.com or stackoverflow.com, please move it there rather than closing it.)&#xD;&#xA;&#xD;&#xA;I have a Display P3 color (1, 0, 0), on a scale of 0.0 to 1.0. I want to find out what the closest color to this is in the sRGB gamut. I chose (1, 0, 0) on the right side ...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;... but the left side still shows (1, 0, 0).&#xD;&#xA;&#xD;&#xA;This makes no sense since (1, 0, 0) in sRGB is not the same color as (1, 0, 0) in P3 — the former is less saturated. As you can see in the screenshot above if you're reading this on a P3 monitor.&#xD;&#xA;&#xD;&#xA;So, how do I convert this?&#xD;&#xA;&#xD;&#xA;Conversely, given an sRGB color (1, 0, 0), how do I find out what the most saturated version of this color is in P3?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Kp8O2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14103" PostHistoryTypeId="1" PostId="5226" RevisionGUID="0fd195b3-454d-4555-b745-daf74e19dd0f" CreationDate="2017-06-11T02:46:46.023" UserId="6814" Text="How do I use ColorSync Utility to convert between Display P3 and sRGB?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14104" PostHistoryTypeId="3" PostId="5226" RevisionGUID="0fd195b3-454d-4555-b745-daf74e19dd0f" CreationDate="2017-06-11T02:46:46.023" UserId="6814" Text="|color-management|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14105" PostHistoryTypeId="50" PostId="4972" RevisionGUID="eceb2f07-9a58-4000-9369-bacdb1660823" CreationDate="2017-06-11T12:48:30.117" UserId="-1" />
  <row Id="14106" PostHistoryTypeId="2" PostId="5227" RevisionGUID="e813c3d1-244d-4699-b37f-46d808657a66" CreationDate="2017-06-11T13:43:43.707" UserId="5846" Text="[@PaulHK's answer][1] is correct I'm sure, here's a bit of a check to show that the `IOR()` function is calculating the reflection coefficients for $s$ and $p$ polarizations then averaging the two assuming unpolarized incident light.&#xD;&#xA;&#xD;&#xA;The reflection is for a single interface, and at least at normal incidence the results reduce to the simpler $(n_2-n_1)^2/(n_2+n_1)^2$. With this script you can check against other on-line calculators using non-zero incident angle and nonzero values for $k$.&#xD;&#xA;&#xD;&#xA;I cleaned up the python a bit (indents) and added the plot. You can see when exiting from glass to air, the reflectivity goes to 100% at the critical angle for total internal reflection:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;    def IOR(n,k):&#xD;&#xA;        theta_deg = 0&#xD;&#xA;&#xD;&#xA;        fresnel = []&#xD;&#xA;          &#xD;&#xA;        while theta_deg &lt;= 90:&#xD;&#xA;            theta = math.radians(theta_deg)&#xD;&#xA;&#xD;&#xA;            a = math.sqrt((math.sqrt((n**2-k**2-(math.sin(theta))**2)**2 +&#xD;&#xA;                                     ((4 * n**2) * k**2)) + (n**2 - k**2 -&#xD;&#xA;                                                (math.sin(theta))**2))/2)&#xD;&#xA;&#xD;&#xA;            b = math.sqrt((math.sqrt((n**2-k**2-(math.sin(theta))**2)**2 +&#xD;&#xA;                                     ((4 * n**2) * k**2)) - (n**2 - k**2 -&#xD;&#xA;                                                (math.sin(theta))**2))/2)&#xD;&#xA;              &#xD;&#xA;            Fs = (a**2+b**2-(2 * a * math.cos(theta))+&#xD;&#xA;                  (math.cos(theta))**2)/(a**2+b**2 +&#xD;&#xA;                                (2 * a * math.cos(theta))+(math.cos(theta))**2)&#xD;&#xA;            &#xD;&#xA;            Fp = Fs * ((a**2+b**2 -&#xD;&#xA;                        (2 * a * math.sin(theta) * math.tan(theta)) +&#xD;&#xA;                        (math.sin(theta))**2*(math.tan(theta))**2)/(a**2+b**2 +&#xD;&#xA;                        (2 * a * math.sin(theta) * math.tan(theta)) +&#xD;&#xA;                        (math.sin(theta))**2*(math.tan(theta))**2))&#xD;&#xA;            &#xD;&#xA;            R = (Fs + Fp)/2&#xD;&#xA;            &#xD;&#xA;            fresnel.append((R, Fs, Fp))&#xD;&#xA;&#xD;&#xA;            theta_deg += 1&#xD;&#xA;        return fresnel&#xD;&#xA;&#xD;&#xA;    import math&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;&#xD;&#xA;    n1, n2  = 1.00, 1.45  # into glass, one side only&#xD;&#xA;    n2ovrn1 = n2/n1&#xD;&#xA;&#xD;&#xA;    Rin, Fsin, Fpin = zip(*IOR(n2ovrn1, 0))&#xD;&#xA;&#xD;&#xA;    print Rin[0]&#xD;&#xA;    print (n2ovrn1-1.0)**2 / (n2ovrn1+1.0)**2  # check&#xD;&#xA;&#xD;&#xA;    n1, n2  = 1.45, 1.00  # outof glass, one side only&#xD;&#xA;    n2ovrn1 = n2/n1&#xD;&#xA;&#xD;&#xA;    Rout, Fsout, Fpout = zip(*IOR(n2ovrn1, 0))&#xD;&#xA;&#xD;&#xA;    print Rout[0]&#xD;&#xA;    print (n2ovrn1-1.0)**2 / (n2ovrn1+1.0)**2  # check&#xD;&#xA;&#xD;&#xA;    plt.figure()&#xD;&#xA;    plt.plot(range(91), Rin, '-k', linewidth=2)&#xD;&#xA;    plt.plot(range(91), Rout, '-k', linewidth=2)&#xD;&#xA;    plt.plot(range(91), Fsin, '-k')&#xD;&#xA;    plt.plot(range(91), Fsout, '-k')&#xD;&#xA;    plt.plot(range(91), Fpin, '--k')&#xD;&#xA;    plt.plot(range(91), Fpout, '--k')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fQjfe.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/174bS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14107" PostHistoryTypeId="2" PostId="5228" RevisionGUID="d5aa6743-ed3a-4cc9-b901-980978efe174" CreationDate="2017-06-11T15:51:28.620" UserId="6785" Text="As promised but with apologies for the tardiness, here's a GREAT repository of detailed information for using OpenGL with VBA:&#xD;&#xA;&#xD;&#xA;http://arkham46.developpez.com/articles/office/vbaopengl/?page=page_1&#xD;&#xA;&#xD;&#xA;It's in French, but translates beautifully. I wa able to get OpenGL up and running in less than 15 mins using this SUPERB tutorial." ContentLicense="CC BY-SA 3.0" />
  <row Id="14108" PostHistoryTypeId="2" PostId="5229" RevisionGUID="a5a9e86a-de30-4049-9af7-cc7d9169d2a6" CreationDate="2017-06-11T18:53:07.640" UserId="310" Text="As mentioned in the comments, I would highly suggest starting with Full Volumetric Scattering. This is two fold:&#xD;&#xA;&#xD;&#xA; 1. Since you are doing path tracing, adding volumetrics isn't super difficult&#xD;&#xA; 1. Fully understanding how full volumetric scattering works will great a great basis for understanding the estimations. In addition, it can provide great &quot;references&quot; to see if your estimations are performing well / correctly.&#xD;&#xA;&#xD;&#xA;With that in mind, below is a basic introduction to how to implement Full Volumetric Scattering in a backwards path tracer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To start, let's look at the code for a backwards path tracer with only reflection, no transmission / refraction:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;            // we need to add the emmisive light&#xD;&#xA;            if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Calculate the direct lighting&#xD;&#xA;            color += throughput * SampleLights(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA;1. Shoot a ray through the scene&#xD;&#xA;1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA;1. If this is the first ray, or we just bounced off a specular surface, check if we hit a light. If so, we add the light emission to our color accumulation&#xD;&#xA;1. Sample the direct lighting&#xD;&#xA;1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF&#xD;&#xA;1. Evaluate the BRDF and accumulate it. &#xD;&#xA;1. Create a new ray based on our chosen direction and where we just came from&#xD;&#xA;1. [Optional] Use Russian Roulette to choose if we should terminate the ray&#xD;&#xA;1. Goto 1&#xD;&#xA;&#xD;&#xA;For more details on Direct Light Sampling, see [this answer][1].&#xD;&#xA;&#xD;&#xA;**BSDFs**&#xD;&#xA;&#xD;&#xA;To add transmission, we first need to upgrade some of our BRDF materials to full BSDFs, with a BTDF function.&#xD;&#xA;[![BSDF Explanation][2]][2]&#xD;&#xA;&#xD;&#xA;For example, a BSDF for an ideal specular dielectric (ie. glass) is:&#xD;&#xA;&#xD;&#xA;    class IdealSpecularDielectric : public BSDF {&#xD;&#xA;    public:&#xD;&#xA;        IdealSpecularDielectric(float3 albedo, float ior)&#xD;&#xA;            : BSDF(BSDFLobe::Specular, albedo), &#xD;&#xA;              m_ior(ior) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        float m_ior;&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float3 Eval(SurfaceInteraction &amp;interaction) const override {&#xD;&#xA;            return m_albedo;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        void Sample(SurfaceInteraction &amp;interaction, UniformSampler *sampler) const override {&#xD;&#xA;            float VdotN = dot(interaction.OutputDirection, interaction.Normal);&#xD;&#xA;            float IORo = m_ior;&#xD;&#xA;            if (VdotN &lt; 0.0f) {&#xD;&#xA;                IORo = 1.0f;&#xD;&#xA;                interaction.Normal = -interaction.Normal;&#xD;&#xA;                VdotN = -VdotN;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float eta = interaction.IORi / IORo;&#xD;&#xA;            float sinSquaredThetaT = SinSquaredThetaT(VdotN, eta);&#xD;&#xA;            float fresnel = Fresnel(interaction.IORi, IORo, VdotN, sinSquaredThetaT);&#xD;&#xA;            &#xD;&#xA;            float rand = sampler-&gt;NextFloat();&#xD;&#xA;            if (rand &lt;= fresnel) {&#xD;&#xA;                // Reflect&#xD;&#xA;                interaction.InputDirection = reflect(interaction.OutputDirection, interaction.Normal);&#xD;&#xA;                interaction.SampledLobe = BSDFLobe::SpecularReflection;&#xD;&#xA;                interaction.IORo = interaction.IORi;&#xD;&#xA;            } else {&#xD;&#xA;                // Refract&#xD;&#xA;                interaction.InputDirection = refract(interaction.OutputDirection, interaction.Normal, VdotN, eta, sinSquaredThetaT);&#xD;&#xA;                interaction.SampledLobe = BSDFLobe::SpecularTransmission;&#xD;&#xA;                interaction.IORo = IORo;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (AnyNan(interaction.InputDirection)) {&#xD;&#xA;                printf(&quot;nan&quot;);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float Pdf(SurfaceInteraction &amp;interaction) const override {&#xD;&#xA;            return 1.0f;&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The interesting part of the code is Sample(). This is where a ray will choose whether to reflect or refract. How we do this is really up to us, as shown in [this answer][3]. However, an obvious choice would be to sample based on the [Fresnel equations][4].&#xD;&#xA;&#xD;&#xA;In the case of an ideal Specular Dielectric, there are only two potential output directions: perfect refraction or perfect reflection. So we evaluate the Fresnel and randomly choose to refract / reflect with proportion equal to the Fresnel. &#xD;&#xA;&#xD;&#xA;**Media**&#xD;&#xA;&#xD;&#xA;Next, we need to talk about media, and how they affect light bouncing around. As explained by Nathan Reed in [this answer][5]: &#xD;&#xA;&#xD;&#xA;&quot;The way I like to think about volume scattering is that a photon traveling through a medium has a certain probability per unit length of interacting (getting scattered or absorbed). As long as it doesn't interact, it just goes in a straight line unimpeded and without losing energy. The greater the distance, the greater the probability that it interacts somewhere in that distance. The interaction probability per unit length is the coefficient $\sigma$ that you see in the equations. We usually have separate coefficients for scattering and absorption probabilities, so $\sigma = \sigma_s + \sigma_a$&quot;&#xD;&#xA;&#xD;&#xA;&quot;This probability per unit length is exactly the origin of the Beer-Lambert law. Slice a ray segment into infinitesimal intervals, treat each interval as an independent possible place to interact, then integrate along the ray; you get an exponential distribution (with rate parameter σσ) for the probability of interaction as a function of distance.&quot;&#xD;&#xA;&#xD;&#xA;&quot;You _can_ technically choose the distance between events however you want, as long as you correctly weight the path for the probability that a photon can make it between two adjacent events without interacting with the medium. In other words, each path segment within the medium contributes a weight factor of $e^{-\sigma x}$, where $x$ is the length of the segment.&quot;&#xD;&#xA;&#xD;&#xA;&quot;Given this, a usually good choice for the distance is to importance-sample it from the exponential distribution. In other words, you set $x = -(\ln \xi)/\sigma$&quot;&#xD;&#xA;&#xD;&#xA;In summary:&#xD;&#xA;&#xD;&#xA; 1. A ray travelling through a medium has some probability to:&#xD;&#xA;   - Be absorbed&#xD;&#xA;   - Be scattered&#xD;&#xA; 1. Since this is Monte Carlo Integration, we are free to choose the interaction distance however we want. However, a good choice is to importance sample from an exponential distribution similar to Beer-Lambert.&#xD;&#xA;&#xD;&#xA;I chose to implement this with a scattering coefficient, and letting Beer-Lambert take care of the absorption coefficient.&#xD;&#xA;&#xD;&#xA;	class Medium {&#xD;&#xA;	public:&#xD;&#xA;		Medium(float3 absorptionColor, float absorptionAtDistance) &#xD;&#xA;			: m_absorptionCoefficient(-log(absorptionColor) / absorptionAtDistance) {&#xD;&#xA;			// This method for calculating the absorption coefficient is borrowed from Burley's 2015 Siggraph Course Notes &quot;Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering&quot;&#xD;&#xA;			// It's much more intutive to specify a color and a distance, then back-calculate the coefficient&#xD;&#xA;		}&#xD;&#xA;		virtual ~Medium() {&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	protected:&#xD;&#xA;		const float3a m_absorptionCoefficient;&#xD;&#xA;&#xD;&#xA;	public:&#xD;&#xA;		virtual float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const = 0;&#xD;&#xA;&#xD;&#xA;		virtual float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const = 0;&#xD;&#xA;		virtual float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const = 0;&#xD;&#xA;&#xD;&#xA;		virtual float3 Transmission(float distance) const = 0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A Non-scattering medium is one where a photon travels straight through, but it is attenuated along the way according to Beer-Lambert:&#xD;&#xA;&#xD;&#xA;    class NonScatteringMedium : public Medium {&#xD;&#xA;    public:&#xD;&#xA;        NonScatteringMedium(float3 color, float atDistance)&#xD;&#xA;            : Medium(color, atDistance) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {&#xD;&#xA;            *pdf = 1.0f;&#xD;&#xA;            return tFar;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const override {&#xD;&#xA;            return wo;&#xD;&#xA;        }&#xD;&#xA;        float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const override {&#xD;&#xA;            return 1.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float3 Transmission(float distance) const override {&#xD;&#xA;            return exp(-m_absorptionCoefficient * distance);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;[![Non-scattering example][6]][6]&#xD;&#xA;&#xD;&#xA;An Isotropic Scattering Medium allows the ray to have scattering (reflection) events while the ray is traveling through it. The ray can be reflected in any direction in the sphere around the interaction point (hence Isotropic). &#xD;&#xA;&#xD;&#xA;[![Explanation of Isotropic scattering][7]][7]&#xD;&#xA;&#xD;&#xA;The distance between reflections is random, based on an exponential &quot;scatter&quot; probability.&#xD;&#xA;&#xD;&#xA;    class IsotropicScatteringMedium : public Medium {&#xD;&#xA;    public:&#xD;&#xA;        IsotropicScatteringMedium(float3 absorptionColor, float absorptionAtDistance, float scatteringDistance)&#xD;&#xA;            : Medium(absorptionColor, absorptionAtDistance),&#xD;&#xA;              m_scatteringCoefficient(1 / scatteringDistance) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        float m_scatteringCoefficient;&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {&#xD;&#xA;            float distance = -logf(sampler-&gt;NextFloat()) / m_scatteringCoefficient;&#xD;&#xA;            // If we sample a distance farther than the next intersecting surface, clamp to the surface distance&#xD;&#xA;			if (distance &gt;= tFar) {&#xD;&#xA;                *pdf = 1.0f;&#xD;&#xA;                return tFar;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            *pdf = std::exp(-m_scatteringCoefficient * distance);&#xD;&#xA;            return distance;&#xD;&#xA;        }&#xD;&#xA;        float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const override {&#xD;&#xA;            *pdf = 0.25f * M_1_PI; // 1 / (4 * PI)&#xD;&#xA;            return UniformSampleSphere(sampler);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const override {&#xD;&#xA;            return 0.25f * M_1_PI; // 1 / (4 * PI)&#xD;&#xA;        }&#xD;&#xA;        float3 Transmission(float distance) const override {&#xD;&#xA;            return exp(-m_absorptionCoefficient * distance);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;At high scattering distances, the material behaves almost like a NonScatteringMedium, because the it has a very small probability of scattering before it travels through the medium.&#xD;&#xA;&#xD;&#xA;[![High Scattering Distance][8]][8]&#xD;&#xA;&#xD;&#xA;At low scattering distances, the material behaves like wax or jade. &#xD;&#xA;&#xD;&#xA;[![Low Scattering Distance][9]][9]&#xD;&#xA;&#xD;&#xA;As the scattering distance gets lower and lower, we have a higher and higher chance to scatter while traveling through the medium. This presents a few issues:&#xD;&#xA;&#xD;&#xA;1. The number of bounces per ray is going to explode. &#xD;&#xA;1. If Russian Roulette kills the ray, or if you go over &quot;maxBounces&quot;, you will &quot;lose&quot; any color contribution from inside the medium. [![Over Max bounces example][10]][10]&#xD;&#xA;&#xD;&#xA;Thus, you need to set maxBounces to some high number, and rely on Russian Roulette to terminate rays in the general case. In addition, IsotropicScatteringMedium is extremely inefficient for representing mostly opaque materials. To get better performance, we should use a non Isotropic phase function, [like Henyey-Greenstein or Schlick][11]. These bias the scattering in a certain direction. So we could set them to have high back-scattering, thereby lessening the issue of &quot;lost&quot; rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Putting it all together**&#xD;&#xA;&#xD;&#xA;So, with this new information, how do we modify the integrator to understand BSDFs and media? &#xD;&#xA;&#xD;&#xA;First, we need to start tracking what medium we are currently in, and its Index of Refraction (IOR). &#xD;&#xA;&#xD;&#xA;    SurfaceInteraction interaction;&#xD;&#xA;    interaction.IORi = 1.0f; // Vacuum &#xD;&#xA;    Medium *medium = nullptr; // nullptr == vacuum&#xD;&#xA;&#xD;&#xA;Then, we break the integrator up into two parts: transmission and material interaction.&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) const {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;        interaction.IORi = 1.0f; // Air&#xD;&#xA;        Medium *medium = nullptr;&#xD;&#xA;        bool hitSurface = false;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        uint bounces = 0;&#xD;&#xA;        const uint maxBounces = 1500;&#xD;&#xA;        for (; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            hitSurface = true;&#xD;&#xA;            &#xD;&#xA;            // Calculate any transmission&#xD;&#xA;            if (medium != nullptr) {&#xD;&#xA;                float weight = 1.0f;&#xD;&#xA;                float pdf = 1.0f;&#xD;&#xA;                float distance = medium-&gt;SampleDistance(sampler, ray.TFar, &amp;weight, &amp;pdf);&#xD;&#xA;                float3 transmission = medium-&gt;Transmission(distance);&#xD;&#xA;                throughput = throughput * weight * transmission;&#xD;&#xA;&#xD;&#xA;                if (distance &lt; ray.TFar) {&#xD;&#xA;                    // Create a scatter event&#xD;&#xA;                    hitSurface = false;&#xD;&#xA;                    &#xD;&#xA;                    ray.Origin = ray.Origin + ray.Direction * distance;&#xD;&#xA;&#xD;&#xA;                    // Reset the other ray properties&#xD;&#xA;                    float directionPdf;&#xD;&#xA;                    float3a wo = normalize(ray.Direction);&#xD;&#xA;                    ray.Direction = medium-&gt;SampleScatterDirection(sampler, wo, &amp;directionPdf);&#xD;&#xA;                    ray.TNear = 0.001f;&#xD;&#xA;                    ray.TFar = infinity;&#xD;&#xA;                    ray.GeomID = INVALID_GEOMETRY_ID;&#xD;&#xA;                    ray.PrimID = INVALID_PRIMATIVE_ID;&#xD;&#xA;                    ray.InstID = INVALID_INSTANCE_ID;&#xD;&#xA;                    ray.Mask = 0xFFFFFFFF;&#xD;&#xA;                    ray.Time = 0.0f;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (hitSurface) {&#xD;&#xA;                // Fetch the material&#xD;&#xA;                Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;                // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;                // Otherwise, GetLight will return nullptr&#xD;&#xA;                Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;                // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;                // we need to add the emmisive light&#xD;&#xA;                if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                    color += throughput * light-&gt;Le();&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;                interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;                interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;                interaction.IORo = 0.0f;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;                // Calculate the direct lighting&#xD;&#xA;                color += throughput * SampleOneLight(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;                // Get the new ray direction&#xD;&#xA;                // Choose the direction based on the bsdf        &#xD;&#xA;                material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;                float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;                // Accumulate the weight&#xD;&#xA;                throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;                // Update the current IOR and medium if we refracted&#xD;&#xA;                if (interaction.SampledLobe == BSDFLobe::SpecularTransmission) {&#xD;&#xA;                    interaction.IORi = interaction.IORo;&#xD;&#xA;                    medium = material-&gt;medium;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                // Shoot a new ray&#xD;&#xA;&#xD;&#xA;                // Set the origin at the intersection point&#xD;&#xA;                ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;                // Reset the other ray properties&#xD;&#xA;                ray.Direction = interaction.InputDirection;&#xD;&#xA;                if (AnyNan(ray.Direction))&#xD;&#xA;                    printf(&quot;bad&quot;);&#xD;&#xA;                ray.TNear = 0.001f;&#xD;&#xA;                ray.TFar = infinity;&#xD;&#xA;                ray.GeomID = INVALID_GEOMETRY_ID;&#xD;&#xA;                ray.PrimID = INVALID_PRIMATIVE_ID;&#xD;&#xA;                ray.InstID = INVALID_INSTANCE_ID;&#xD;&#xA;                ray.Mask = 0xFFFFFFFF;&#xD;&#xA;                ray.Time = 0.0f;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (bounces == maxBounces) {&#xD;&#xA;            printf(&quot;Over max bounces&quot;);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**In English:**&#xD;&#xA;&#xD;&#xA;1. Shoot a ray through the scene&#xD;&#xA;1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA;1. Check if we are currently in a medium (not in a vacuum)&#xD;&#xA;  1. Sample the medium for a distance&#xD;&#xA;  1. Evaluate the medium's transmission and accumulate the throughput&#xD;&#xA;  1. If the scatter distance is less than the distance from the ray origin to the next surface, make a scatter event&#xD;&#xA;  1. Sample the medium for a scatter direction&#xD;&#xA;1. Check if we hit a surface (ie, we didn't have a scatter event)&#xD;&#xA;  1. If this is the first ray, or we just bounced off a specular surface, check if we hit a light. If so, we add the light emission to our color accumulation&#xD;&#xA;  1. Sample the direct lighting&#xD;&#xA;  1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF&#xD;&#xA;  1. Evaluate the BRDF and accumulate it. &#xD;&#xA;  1. If we refracted into the material, update the IOR and medium for the next bounce&#xD;&#xA;1. Create a new ray based on our chosen direction and where we just came from&#xD;&#xA;1. [Optional] Use Russian Roulette to choose if we should terminate the ray&#xD;&#xA;1. Goto 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/5152/progressive-path-tracing-with-explicit-light-sampling/5153#5153&#xD;&#xA;  [2]: https://i.stack.imgur.com/2oBo9.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/2482/choosing-reflection-or-refraction-in-path-tracing&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [5]: https://computergraphics.stackexchange.com/a/3570/310&#xD;&#xA;  [6]: https://i.stack.imgur.com/aERCt.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/tOp55.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/H7OX2.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/JgjlE.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/tZ6QO.png&#xD;&#xA;  [11]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/chapter4.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14110" PostHistoryTypeId="5" PostId="5221" RevisionGUID="19f10f47-3fdd-4bee-8890-710fff05c9f2" CreationDate="2017-06-12T17:05:24.697" UserId="1952" Comment="added missing I's: (a-b)^2=a^2-2ab+b^2" Text="I was wondering about the variance for Monte Carlo.&#xD;&#xA;The book (Advanced Global Illumination 2ed, p.60) writes the equation as follows:&#xD;&#xA;&#xD;&#xA;$\sigma^2 = \frac{1}{N} \int(\frac{f(x)}{p(x)} - I)^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\color{red}{\frac{1}{N} \int(\frac{f(x)}{p(x)})^2p(x)dx  -I^2}$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)}dx  -I^2$&#xD;&#xA;&#xD;&#xA;However, the equation appears incorrect. I think the red area is wrong and the equation should be changed as follows:&#xD;&#xA;&#xD;&#xA;$\sigma^2 = \frac{1}{N} \int(\frac{f(x)}{p(x)} - I)^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\color{red}{\frac{1}{N} \int((\frac{f(x)}{p(x)})^2 -2\frac{f(x)}{p(x)}I + I^2)p(x)dx}$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} - 2f(x)I + I^2p(x)dx$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} - 2f(x)I dx \space + \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} dx - \frac{2}{N}I^2 \space + \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;$\space\space\space\space=\frac{1}{N} \int\frac{f(x)^2}{p(x)} dx - \frac{1}{N}I^2$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is it right?&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14111" PostHistoryTypeId="5" PostId="5229" RevisionGUID="5260cbc0-c908-4a9f-96c9-45f34fca0801" CreationDate="2017-06-12T17:45:28.967" UserId="231" Comment="Formatting changes. Hopefully improvements but feel free to revert" Text="As mentioned in the comments, I would highly suggest starting with Full Volumetric Scattering. This is two fold:&#xD;&#xA;&#xD;&#xA; 1. Since you are doing path tracing, adding volumetrics isn't super difficult.&#xD;&#xA; 1. Fully understanding how full volumetric scattering works will be a great basis for understanding the estimations. In addition, it can provide great &quot;references&quot; to see if your estimations are performing well / correctly.&#xD;&#xA;&#xD;&#xA;With that in mind, below is a basic introduction to how to implement Full Volumetric Scattering in a backwards path tracer.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To start, let's look at the code for a backwards path tracer with only reflection, no transmission / refraction:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;            // we need to add the emmisive light&#xD;&#xA;            if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Calculate the direct lighting&#xD;&#xA;            color += throughput * SampleLights(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## In English:&#xD;&#xA;&#xD;&#xA;1. Shoot a ray through the scene.&#xD;&#xA;1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA;1. If this is the first ray, or we just bounced off a specular surface, check if we hit a light. If so, we add the light emission to our color accumulation.&#xD;&#xA;1. Sample the direct lighting.&#xD;&#xA;1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF.&#xD;&#xA;1. Evaluate the BRDF and accumulate it. &#xD;&#xA;1. Create a new ray based on our chosen direction and where we just came from.&#xD;&#xA;1. [Optional] Use Russian Roulette to choose if we should terminate the ray.&#xD;&#xA;1. Goto 1.&#xD;&#xA;&#xD;&#xA;For more details on Direct Light Sampling, see [this answer][1].&#xD;&#xA;&#xD;&#xA;## BSDFs&#xD;&#xA;&#xD;&#xA;To add transmission, we first need to upgrade some of our BRDF materials to full BSDFs, with a BTDF function.&#xD;&#xA;[![BSDF Explanation][2]][2]&#xD;&#xA;&#xD;&#xA;For example, a BSDF for an ideal specular dielectric (ie. glass) is:&#xD;&#xA;&#xD;&#xA;    class IdealSpecularDielectric : public BSDF {&#xD;&#xA;    public:&#xD;&#xA;        IdealSpecularDielectric(float3 albedo, float ior)&#xD;&#xA;            : BSDF(BSDFLobe::Specular, albedo), &#xD;&#xA;              m_ior(ior) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        float m_ior;&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float3 Eval(SurfaceInteraction &amp;interaction) const override {&#xD;&#xA;            return m_albedo;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        void Sample(SurfaceInteraction &amp;interaction, UniformSampler *sampler) const override {&#xD;&#xA;            float VdotN = dot(interaction.OutputDirection, interaction.Normal);&#xD;&#xA;            float IORo = m_ior;&#xD;&#xA;            if (VdotN &lt; 0.0f) {&#xD;&#xA;                IORo = 1.0f;&#xD;&#xA;                interaction.Normal = -interaction.Normal;&#xD;&#xA;                VdotN = -VdotN;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float eta = interaction.IORi / IORo;&#xD;&#xA;            float sinSquaredThetaT = SinSquaredThetaT(VdotN, eta);&#xD;&#xA;            float fresnel = Fresnel(interaction.IORi, IORo, VdotN, sinSquaredThetaT);&#xD;&#xA;            &#xD;&#xA;            float rand = sampler-&gt;NextFloat();&#xD;&#xA;            if (rand &lt;= fresnel) {&#xD;&#xA;                // Reflect&#xD;&#xA;                interaction.InputDirection = reflect(interaction.OutputDirection, interaction.Normal);&#xD;&#xA;                interaction.SampledLobe = BSDFLobe::SpecularReflection;&#xD;&#xA;                interaction.IORo = interaction.IORi;&#xD;&#xA;            } else {&#xD;&#xA;                // Refract&#xD;&#xA;                interaction.InputDirection = refract(interaction.OutputDirection, interaction.Normal, VdotN, eta, sinSquaredThetaT);&#xD;&#xA;                interaction.SampledLobe = BSDFLobe::SpecularTransmission;&#xD;&#xA;                interaction.IORo = IORo;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (AnyNan(interaction.InputDirection)) {&#xD;&#xA;                printf(&quot;nan&quot;);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float Pdf(SurfaceInteraction &amp;interaction) const override {&#xD;&#xA;            return 1.0f;&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The interesting part of the code is `Sample()`. This is where a ray will choose whether to reflect or refract. How we do this is really up to us, as shown in [this answer][3]. However, an obvious choice would be to sample based on the [Fresnel equations][4].&#xD;&#xA;&#xD;&#xA;In the case of an ideal Specular Dielectric, there are only two potential output directions: perfect refraction or perfect reflection. So we evaluate the Fresnel and randomly choose to refract / reflect with proportion equal to the Fresnel. &#xD;&#xA;&#xD;&#xA;## Media&#xD;&#xA;&#xD;&#xA;Next, we need to talk about media, and how they affect light bouncing around. As explained by Nathan Reed in [this answer][5]: &#xD;&#xA;&#xD;&#xA;&gt; The way I like to think about volume scattering is that a photon traveling through a medium has a certain probability per unit length of interacting (getting scattered or absorbed). As long as it doesn't interact, it just goes in a straight line unimpeded and without losing energy. The greater the distance, the greater the probability that it interacts somewhere in that distance. The interaction probability per unit length is the coefficient $\sigma$ that you see in the equations. We usually have separate coefficients for scattering and absorption probabilities, so $\sigma = \sigma_s + \sigma_a$&#xD;&#xA;&#xD;&#xA;&gt; This probability per unit length is exactly the origin of the Beer-Lambert law. Slice a ray segment into infinitesimal intervals, treat each interval as an independent possible place to interact, then integrate along the ray; you get an exponential distribution (with rate parameter σσ) for the probability of interaction as a function of distance.&#xD;&#xA;&#xD;&#xA;&gt; You _can_ technically choose the distance between events however you want, as long as you correctly weight the path for the probability that a photon can make it between two adjacent events without interacting with the medium. In other words, each path segment within the medium contributes a weight factor of $e^{-\sigma x}$, where $x$ is the length of the segment.&#xD;&#xA;&#xD;&#xA;&gt; Given this, a usually good choice for the distance is to importance-sample it from the exponential distribution. In other words, you set $x = -(\ln \xi)/\sigma$&#xD;&#xA;&#xD;&#xA;In summary:&#xD;&#xA;&#xD;&#xA; 1. A ray travelling through a medium has some probability to:&#xD;&#xA;   - Be absorbed&#xD;&#xA;   - Be scattered&#xD;&#xA; 1. Since this is Monte Carlo Integration, we are free to choose the interaction distance however we want. However, a good choice is to importance sample from an exponential distribution similar to Beer-Lambert.&#xD;&#xA;&#xD;&#xA;I chose to implement this with a scattering coefficient, and letting Beer-Lambert take care of the absorption coefficient.&#xD;&#xA;&#xD;&#xA;	class Medium {&#xD;&#xA;	public:&#xD;&#xA;		Medium(float3 absorptionColor, float absorptionAtDistance) &#xD;&#xA;			: m_absorptionCoefficient(-log(absorptionColor) / absorptionAtDistance) {&#xD;&#xA;			// This method for calculating the absorption coefficient is borrowed from Burley's 2015 Siggraph Course Notes &quot;Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering&quot;&#xD;&#xA;			// It's much more intutive to specify a color and a distance, then back-calculate the coefficient&#xD;&#xA;		}&#xD;&#xA;		virtual ~Medium() {&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	protected:&#xD;&#xA;		const float3a m_absorptionCoefficient;&#xD;&#xA;&#xD;&#xA;	public:&#xD;&#xA;		virtual float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const = 0;&#xD;&#xA;&#xD;&#xA;		virtual float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const = 0;&#xD;&#xA;		virtual float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const = 0;&#xD;&#xA;&#xD;&#xA;		virtual float3 Transmission(float distance) const = 0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A Non-scattering medium is one where a photon travels straight through, but it is attenuated along the way according to Beer-Lambert:&#xD;&#xA;&#xD;&#xA;    class NonScatteringMedium : public Medium {&#xD;&#xA;    public:&#xD;&#xA;        NonScatteringMedium(float3 color, float atDistance)&#xD;&#xA;            : Medium(color, atDistance) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {&#xD;&#xA;            *pdf = 1.0f;&#xD;&#xA;            return tFar;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const override {&#xD;&#xA;            return wo;&#xD;&#xA;        }&#xD;&#xA;        float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const override {&#xD;&#xA;            return 1.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float3 Transmission(float distance) const override {&#xD;&#xA;            return exp(-m_absorptionCoefficient * distance);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;[![Non-scattering example][6]][6]&#xD;&#xA;&#xD;&#xA;An Isotropic Scattering Medium allows the ray to have scattering (reflection) events while the ray is traveling through it. The ray can be reflected in any direction in the sphere around the interaction point (hence Isotropic). &#xD;&#xA;&#xD;&#xA;[![Explanation of Isotropic scattering][7]][7]&#xD;&#xA;&#xD;&#xA;The distance between reflections is random, based on an exponential &quot;scatter&quot; probability.&#xD;&#xA;&#xD;&#xA;    class IsotropicScatteringMedium : public Medium {&#xD;&#xA;    public:&#xD;&#xA;        IsotropicScatteringMedium(float3 absorptionColor, float absorptionAtDistance, float scatteringDistance)&#xD;&#xA;            : Medium(absorptionColor, absorptionAtDistance),&#xD;&#xA;              m_scatteringCoefficient(1 / scatteringDistance) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        float m_scatteringCoefficient;&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {&#xD;&#xA;            float distance = -logf(sampler-&gt;NextFloat()) / m_scatteringCoefficient;&#xD;&#xA;            // If we sample a distance farther than the next intersecting surface, clamp to the surface distance&#xD;&#xA;			if (distance &gt;= tFar) {&#xD;&#xA;                *pdf = 1.0f;&#xD;&#xA;                return tFar;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            *pdf = std::exp(-m_scatteringCoefficient * distance);&#xD;&#xA;            return distance;&#xD;&#xA;        }&#xD;&#xA;        float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const override {&#xD;&#xA;            *pdf = 0.25f * M_1_PI; // 1 / (4 * PI)&#xD;&#xA;            return UniformSampleSphere(sampler);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const override {&#xD;&#xA;            return 0.25f * M_1_PI; // 1 / (4 * PI)&#xD;&#xA;        }&#xD;&#xA;        float3 Transmission(float distance) const override {&#xD;&#xA;            return exp(-m_absorptionCoefficient * distance);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;At high scattering distances, the material behaves almost like a NonScatteringMedium, because the it has a very small probability of scattering before it travels through the medium.&#xD;&#xA;&#xD;&#xA;[![High Scattering Distance][8]][8]&#xD;&#xA;&#xD;&#xA;At low scattering distances, the material behaves like wax or jade. &#xD;&#xA;&#xD;&#xA;[![Low Scattering Distance][9]][9]&#xD;&#xA;&#xD;&#xA;As the scattering distance gets lower and lower, we have a higher and higher chance to scatter while traveling through the medium. This presents a few issues:&#xD;&#xA;&#xD;&#xA;1. The number of bounces per ray is going to explode. &#xD;&#xA;1. If Russian Roulette kills the ray, or if you go over &quot;maxBounces&quot;, you will &quot;lose&quot; any color contribution from inside the medium. [![Over Max bounces example][10]][10]&#xD;&#xA;&#xD;&#xA;Thus, you need to set maxBounces to some high number, and rely on Russian Roulette to terminate rays in the general case. In addition, IsotropicScatteringMedium is extremely inefficient for representing mostly opaque materials. To get better performance, we should use a non Isotropic phase function, [like Henyey-Greenstein or Schlick][11]. These bias the scattering in a certain direction. So we could set them to have high back-scattering, thereby lessening the issue of &quot;lost&quot; rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Putting it all together&#xD;&#xA;&#xD;&#xA;So, with this new information, how do we modify the integrator to understand BSDFs and media? &#xD;&#xA;&#xD;&#xA;First, we need to start tracking what medium we are currently in, and its Index of Refraction (IOR). &#xD;&#xA;&#xD;&#xA;    SurfaceInteraction interaction;&#xD;&#xA;    interaction.IORi = 1.0f; // Vacuum &#xD;&#xA;    Medium *medium = nullptr; // nullptr == vacuum&#xD;&#xA;&#xD;&#xA;Then, we break the integrator up into two parts: transmission and material interaction.&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) const {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;        interaction.IORi = 1.0f; // Air&#xD;&#xA;        Medium *medium = nullptr;&#xD;&#xA;        bool hitSurface = false;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        uint bounces = 0;&#xD;&#xA;        const uint maxBounces = 1500;&#xD;&#xA;        for (; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            hitSurface = true;&#xD;&#xA;            &#xD;&#xA;            // Calculate any transmission&#xD;&#xA;            if (medium != nullptr) {&#xD;&#xA;                float weight = 1.0f;&#xD;&#xA;                float pdf = 1.0f;&#xD;&#xA;                float distance = medium-&gt;SampleDistance(sampler, ray.TFar, &amp;weight, &amp;pdf);&#xD;&#xA;                float3 transmission = medium-&gt;Transmission(distance);&#xD;&#xA;                throughput = throughput * weight * transmission;&#xD;&#xA;&#xD;&#xA;                if (distance &lt; ray.TFar) {&#xD;&#xA;                    // Create a scatter event&#xD;&#xA;                    hitSurface = false;&#xD;&#xA;                    &#xD;&#xA;                    ray.Origin = ray.Origin + ray.Direction * distance;&#xD;&#xA;&#xD;&#xA;                    // Reset the other ray properties&#xD;&#xA;                    float directionPdf;&#xD;&#xA;                    float3a wo = normalize(ray.Direction);&#xD;&#xA;                    ray.Direction = medium-&gt;SampleScatterDirection(sampler, wo, &amp;directionPdf);&#xD;&#xA;                    ray.TNear = 0.001f;&#xD;&#xA;                    ray.TFar = infinity;&#xD;&#xA;                    ray.GeomID = INVALID_GEOMETRY_ID;&#xD;&#xA;                    ray.PrimID = INVALID_PRIMATIVE_ID;&#xD;&#xA;                    ray.InstID = INVALID_INSTANCE_ID;&#xD;&#xA;                    ray.Mask = 0xFFFFFFFF;&#xD;&#xA;                    ray.Time = 0.0f;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (hitSurface) {&#xD;&#xA;                // Fetch the material&#xD;&#xA;                Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;                // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;                // Otherwise, GetLight will return nullptr&#xD;&#xA;                Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;                // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;                // we need to add the emmisive light&#xD;&#xA;                if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                    color += throughput * light-&gt;Le();&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;                interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;                interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;                interaction.IORo = 0.0f;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;                // Calculate the direct lighting&#xD;&#xA;                color += throughput * SampleOneLight(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;                // Get the new ray direction&#xD;&#xA;                // Choose the direction based on the bsdf        &#xD;&#xA;                material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;                float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;                // Accumulate the weight&#xD;&#xA;                throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;                // Update the current IOR and medium if we refracted&#xD;&#xA;                if (interaction.SampledLobe == BSDFLobe::SpecularTransmission) {&#xD;&#xA;                    interaction.IORi = interaction.IORo;&#xD;&#xA;                    medium = material-&gt;medium;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                // Shoot a new ray&#xD;&#xA;&#xD;&#xA;                // Set the origin at the intersection point&#xD;&#xA;                ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;                // Reset the other ray properties&#xD;&#xA;                ray.Direction = interaction.InputDirection;&#xD;&#xA;                if (AnyNan(ray.Direction))&#xD;&#xA;                    printf(&quot;bad&quot;);&#xD;&#xA;                ray.TNear = 0.001f;&#xD;&#xA;                ray.TFar = infinity;&#xD;&#xA;                ray.GeomID = INVALID_GEOMETRY_ID;&#xD;&#xA;                ray.PrimID = INVALID_PRIMATIVE_ID;&#xD;&#xA;                ray.InstID = INVALID_INSTANCE_ID;&#xD;&#xA;                ray.Mask = 0xFFFFFFFF;&#xD;&#xA;                ray.Time = 0.0f;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (bounces == maxBounces) {&#xD;&#xA;            printf(&quot;Over max bounces&quot;);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## In English:&#xD;&#xA;&#xD;&#xA;1. Shoot a ray through the scene.&#xD;&#xA;1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA;1. Check if we are currently in a medium (not in a vacuum).&#xD;&#xA;  1. Sample the medium for a distance.&#xD;&#xA;  1. Evaluate the medium's transmission and accumulate the throughput.&#xD;&#xA;  1. If the scatter distance is less than the distance from the ray origin to the next surface, make a scatter event.&#xD;&#xA;  1. Sample the medium for a scatter direction.&#xD;&#xA;1. Check if we hit a surface (ie, we didn't have a scatter event).&#xD;&#xA;  1. If this is the first ray, or we just bounced off a specular surface, check if we hit a light. If so, we add the light emission to our color accumulation.&#xD;&#xA;  1. Sample the direct lighting.&#xD;&#xA;  1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF.&#xD;&#xA;  1. Evaluate the BRDF and accumulate it. &#xD;&#xA;  1. If we refracted into the material, update the IOR and medium for the next bounce.&#xD;&#xA;1. Create a new ray based on our chosen direction and where we just came from.&#xD;&#xA;1. [Optional] Use Russian Roulette to choose if we should terminate the ray.&#xD;&#xA;1. Goto 1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/5152/progressive-path-tracing-with-explicit-light-sampling/5153#5153&#xD;&#xA;  [2]: https://i.stack.imgur.com/2oBo9.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/2482/choosing-reflection-or-refraction-in-path-tracing&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [5]: https://computergraphics.stackexchange.com/a/3570/310&#xD;&#xA;  [6]: https://i.stack.imgur.com/aERCt.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/tOp55.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/H7OX2.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/JgjlE.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/tZ6QO.png&#xD;&#xA;  [11]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/chapter4.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14112" PostHistoryTypeId="5" PostId="5229" RevisionGUID="328db995-7dab-44f7-a1e2-ddb62469375a" CreationDate="2017-06-12T17:56:21.303" UserId="231" Comment="Typo" Text="As mentioned in the comments, I would highly suggest starting with Full Volumetric Scattering. This is two fold:&#xD;&#xA;&#xD;&#xA; 1. Since you are doing path tracing, adding volumetrics isn't super difficult.&#xD;&#xA; 1. Fully understanding how full volumetric scattering works will be a great basis for understanding the estimations. In addition, it can provide great &quot;references&quot; to see if your estimations are performing well / correctly.&#xD;&#xA;&#xD;&#xA;With that in mind, below is a basic introduction to how to implement Full Volumetric Scattering in a backwards path tracer.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To start, let's look at the code for a backwards path tracer with only reflection, no transmission / refraction:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        const uint maxBounces = 15;&#xD;&#xA;        for (uint bounces = 0; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;            // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;            // we need to add the emmisive light&#xD;&#xA;            if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;            interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;            interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Calculate the direct lighting&#xD;&#xA;            color += throughput * SampleLights(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the bsdf        &#xD;&#xA;            material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;            float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;            // Accumulate the weight&#xD;&#xA;            throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.Direction = interaction.InputDirection;&#xD;&#xA;            ray.TNear = 0.001f;&#xD;&#xA;            ray.TFar = infinity;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## In English:&#xD;&#xA;&#xD;&#xA;1. Shoot a ray through the scene.&#xD;&#xA;1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA;1. If this is the first ray, or we just bounced off a specular surface, check if we hit a light. If so, we add the light emission to our color accumulation.&#xD;&#xA;1. Sample the direct lighting.&#xD;&#xA;1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF.&#xD;&#xA;1. Evaluate the BRDF and accumulate it. &#xD;&#xA;1. Create a new ray based on our chosen direction and where we just came from.&#xD;&#xA;1. [Optional] Use Russian Roulette to choose if we should terminate the ray.&#xD;&#xA;1. Goto 1.&#xD;&#xA;&#xD;&#xA;For more details on Direct Light Sampling, see [this answer][1].&#xD;&#xA;&#xD;&#xA;## BSDFs&#xD;&#xA;&#xD;&#xA;To add transmission, we first need to upgrade some of our BRDF materials to full BSDFs, with a BTDF function.&#xD;&#xA;[![BSDF Explanation][2]][2]&#xD;&#xA;&#xD;&#xA;For example, a BSDF for an ideal specular dielectric (ie. glass) is:&#xD;&#xA;&#xD;&#xA;    class IdealSpecularDielectric : public BSDF {&#xD;&#xA;    public:&#xD;&#xA;        IdealSpecularDielectric(float3 albedo, float ior)&#xD;&#xA;            : BSDF(BSDFLobe::Specular, albedo), &#xD;&#xA;              m_ior(ior) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        float m_ior;&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float3 Eval(SurfaceInteraction &amp;interaction) const override {&#xD;&#xA;            return m_albedo;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        void Sample(SurfaceInteraction &amp;interaction, UniformSampler *sampler) const override {&#xD;&#xA;            float VdotN = dot(interaction.OutputDirection, interaction.Normal);&#xD;&#xA;            float IORo = m_ior;&#xD;&#xA;            if (VdotN &lt; 0.0f) {&#xD;&#xA;                IORo = 1.0f;&#xD;&#xA;                interaction.Normal = -interaction.Normal;&#xD;&#xA;                VdotN = -VdotN;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float eta = interaction.IORi / IORo;&#xD;&#xA;            float sinSquaredThetaT = SinSquaredThetaT(VdotN, eta);&#xD;&#xA;            float fresnel = Fresnel(interaction.IORi, IORo, VdotN, sinSquaredThetaT);&#xD;&#xA;            &#xD;&#xA;            float rand = sampler-&gt;NextFloat();&#xD;&#xA;            if (rand &lt;= fresnel) {&#xD;&#xA;                // Reflect&#xD;&#xA;                interaction.InputDirection = reflect(interaction.OutputDirection, interaction.Normal);&#xD;&#xA;                interaction.SampledLobe = BSDFLobe::SpecularReflection;&#xD;&#xA;                interaction.IORo = interaction.IORi;&#xD;&#xA;            } else {&#xD;&#xA;                // Refract&#xD;&#xA;                interaction.InputDirection = refract(interaction.OutputDirection, interaction.Normal, VdotN, eta, sinSquaredThetaT);&#xD;&#xA;                interaction.SampledLobe = BSDFLobe::SpecularTransmission;&#xD;&#xA;                interaction.IORo = IORo;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (AnyNan(interaction.InputDirection)) {&#xD;&#xA;                printf(&quot;nan&quot;);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float Pdf(SurfaceInteraction &amp;interaction) const override {&#xD;&#xA;            return 1.0f;&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The interesting part of the code is `Sample()`. This is where a ray will choose whether to reflect or refract. How we do this is really up to us, as shown in [this answer][3]. However, an obvious choice would be to sample based on the [Fresnel equations][4].&#xD;&#xA;&#xD;&#xA;In the case of an ideal Specular Dielectric, there are only two potential output directions: perfect refraction or perfect reflection. So we evaluate the Fresnel and randomly choose to refract / reflect with proportion equal to the Fresnel. &#xD;&#xA;&#xD;&#xA;## Media&#xD;&#xA;&#xD;&#xA;Next, we need to talk about media, and how they affect light bouncing around. As explained by Nathan Reed in [this answer][5]: &#xD;&#xA;&#xD;&#xA;&gt; The way I like to think about volume scattering is that a photon traveling through a medium has a certain probability per unit length of interacting (getting scattered or absorbed). As long as it doesn't interact, it just goes in a straight line unimpeded and without losing energy. The greater the distance, the greater the probability that it interacts somewhere in that distance. The interaction probability per unit length is the coefficient $\sigma$ that you see in the equations. We usually have separate coefficients for scattering and absorption probabilities, so $\sigma = \sigma_s + \sigma_a$&#xD;&#xA;&#xD;&#xA;&gt; This probability per unit length is exactly the origin of the Beer-Lambert law. Slice a ray segment into infinitesimal intervals, treat each interval as an independent possible place to interact, then integrate along the ray; you get an exponential distribution (with rate parameter σσ) for the probability of interaction as a function of distance.&#xD;&#xA;&#xD;&#xA;&gt; You _can_ technically choose the distance between events however you want, as long as you correctly weight the path for the probability that a photon can make it between two adjacent events without interacting with the medium. In other words, each path segment within the medium contributes a weight factor of $e^{-\sigma x}$, where $x$ is the length of the segment.&#xD;&#xA;&#xD;&#xA;&gt; Given this, a usually good choice for the distance is to importance-sample it from the exponential distribution. In other words, you set $x = -(\ln \xi)/\sigma$&#xD;&#xA;&#xD;&#xA;In summary:&#xD;&#xA;&#xD;&#xA; 1. A ray travelling through a medium has some probability to:&#xD;&#xA;   - Be absorbed&#xD;&#xA;   - Be scattered&#xD;&#xA; 1. Since this is Monte Carlo Integration, we are free to choose the interaction distance however we want. However, a good choice is to importance sample from an exponential distribution similar to Beer-Lambert.&#xD;&#xA;&#xD;&#xA;I chose to implement this with a scattering coefficient, and letting Beer-Lambert take care of the absorption coefficient.&#xD;&#xA;&#xD;&#xA;	class Medium {&#xD;&#xA;	public:&#xD;&#xA;		Medium(float3 absorptionColor, float absorptionAtDistance) &#xD;&#xA;			: m_absorptionCoefficient(-log(absorptionColor) / absorptionAtDistance) {&#xD;&#xA;			// This method for calculating the absorption coefficient is borrowed from Burley's 2015 Siggraph Course Notes &quot;Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering&quot;&#xD;&#xA;			// It's much more intutive to specify a color and a distance, then back-calculate the coefficient&#xD;&#xA;		}&#xD;&#xA;		virtual ~Medium() {&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	protected:&#xD;&#xA;		const float3a m_absorptionCoefficient;&#xD;&#xA;&#xD;&#xA;	public:&#xD;&#xA;		virtual float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const = 0;&#xD;&#xA;&#xD;&#xA;		virtual float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const = 0;&#xD;&#xA;		virtual float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const = 0;&#xD;&#xA;&#xD;&#xA;		virtual float3 Transmission(float distance) const = 0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A Non-scattering medium is one where a photon travels straight through, but it is attenuated along the way according to Beer-Lambert:&#xD;&#xA;&#xD;&#xA;    class NonScatteringMedium : public Medium {&#xD;&#xA;    public:&#xD;&#xA;        NonScatteringMedium(float3 color, float atDistance)&#xD;&#xA;            : Medium(color, atDistance) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {&#xD;&#xA;            *pdf = 1.0f;&#xD;&#xA;            return tFar;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const override {&#xD;&#xA;            return wo;&#xD;&#xA;        }&#xD;&#xA;        float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const override {&#xD;&#xA;            return 1.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float3 Transmission(float distance) const override {&#xD;&#xA;            return exp(-m_absorptionCoefficient * distance);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;[![Non-scattering example][6]][6]&#xD;&#xA;&#xD;&#xA;An Isotropic Scattering Medium allows the ray to have scattering (reflection) events while the ray is traveling through it. The ray can be reflected in any direction in the sphere around the interaction point (hence Isotropic). &#xD;&#xA;&#xD;&#xA;[![Explanation of Isotropic scattering][7]][7]&#xD;&#xA;&#xD;&#xA;The distance between reflections is random, based on an exponential &quot;scatter&quot; probability.&#xD;&#xA;&#xD;&#xA;    class IsotropicScatteringMedium : public Medium {&#xD;&#xA;    public:&#xD;&#xA;        IsotropicScatteringMedium(float3 absorptionColor, float absorptionAtDistance, float scatteringDistance)&#xD;&#xA;            : Medium(absorptionColor, absorptionAtDistance),&#xD;&#xA;              m_scatteringCoefficient(1 / scatteringDistance) {&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        float m_scatteringCoefficient;&#xD;&#xA;&#xD;&#xA;    public:&#xD;&#xA;        float SampleDistance(UniformSampler *sampler, float tFar, float *weight, float *pdf) const override {&#xD;&#xA;            float distance = -logf(sampler-&gt;NextFloat()) / m_scatteringCoefficient;&#xD;&#xA;            // If we sample a distance farther than the next intersecting surface, clamp to the surface distance&#xD;&#xA;			if (distance &gt;= tFar) {&#xD;&#xA;                *pdf = 1.0f;&#xD;&#xA;                return tFar;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            *pdf = std::exp(-m_scatteringCoefficient * distance);&#xD;&#xA;            return distance;&#xD;&#xA;        }&#xD;&#xA;        float3a SampleScatterDirection(UniformSampler *sampler, float3a &amp;wo, float *pdf) const override {&#xD;&#xA;            *pdf = 0.25f * M_1_PI; // 1 / (4 * PI)&#xD;&#xA;            return UniformSampleSphere(sampler);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float ScatterDirectionPdf(float3a &amp;wi, float3a &amp;wo) const override {&#xD;&#xA;            return 0.25f * M_1_PI; // 1 / (4 * PI)&#xD;&#xA;        }&#xD;&#xA;        float3 Transmission(float distance) const override {&#xD;&#xA;            return exp(-m_absorptionCoefficient * distance);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;At high scattering distances, the material behaves almost like a NonScatteringMedium, because it has a very small probability of scattering before it travels through the medium.&#xD;&#xA;&#xD;&#xA;[![High Scattering Distance][8]][8]&#xD;&#xA;&#xD;&#xA;At low scattering distances, the material behaves like wax or jade. &#xD;&#xA;&#xD;&#xA;[![Low Scattering Distance][9]][9]&#xD;&#xA;&#xD;&#xA;As the scattering distance gets lower and lower, we have a higher and higher chance to scatter while traveling through the medium. This presents a few issues:&#xD;&#xA;&#xD;&#xA;1. The number of bounces per ray is going to explode. &#xD;&#xA;1. If Russian Roulette kills the ray, or if you go over &quot;maxBounces&quot;, you will &quot;lose&quot; any color contribution from inside the medium. [![Over Max bounces example][10]][10]&#xD;&#xA;&#xD;&#xA;Thus, you need to set maxBounces to some high number, and rely on Russian Roulette to terminate rays in the general case. In addition, IsotropicScatteringMedium is extremely inefficient for representing mostly opaque materials. To get better performance, we should use a non Isotropic phase function, [like Henyey-Greenstein or Schlick][11]. These bias the scattering in a certain direction. So we could set them to have high back-scattering, thereby lessening the issue of &quot;lost&quot; rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Putting it all together&#xD;&#xA;&#xD;&#xA;So, with this new information, how do we modify the integrator to understand BSDFs and media? &#xD;&#xA;&#xD;&#xA;First, we need to start tracking what medium we are currently in, and its Index of Refraction (IOR). &#xD;&#xA;&#xD;&#xA;    SurfaceInteraction interaction;&#xD;&#xA;    interaction.IORi = 1.0f; // Vacuum &#xD;&#xA;    Medium *medium = nullptr; // nullptr == vacuum&#xD;&#xA;&#xD;&#xA;Then, we break the integrator up into two parts: transmission and material interaction.&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) const {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera-&gt;CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;        SurfaceInteraction interaction;&#xD;&#xA;        interaction.IORi = 1.0f; // Air&#xD;&#xA;        Medium *medium = nullptr;&#xD;&#xA;        bool hitSurface = false;&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        uint bounces = 0;&#xD;&#xA;        const uint maxBounces = 1500;&#xD;&#xA;        for (; bounces &lt; maxBounces; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.GeomID == INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * m_scene-&gt;BackgroundColor;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            hitSurface = true;&#xD;&#xA;            &#xD;&#xA;            // Calculate any transmission&#xD;&#xA;            if (medium != nullptr) {&#xD;&#xA;                float weight = 1.0f;&#xD;&#xA;                float pdf = 1.0f;&#xD;&#xA;                float distance = medium-&gt;SampleDistance(sampler, ray.TFar, &amp;weight, &amp;pdf);&#xD;&#xA;                float3 transmission = medium-&gt;Transmission(distance);&#xD;&#xA;                throughput = throughput * weight * transmission;&#xD;&#xA;&#xD;&#xA;                if (distance &lt; ray.TFar) {&#xD;&#xA;                    // Create a scatter event&#xD;&#xA;                    hitSurface = false;&#xD;&#xA;                    &#xD;&#xA;                    ray.Origin = ray.Origin + ray.Direction * distance;&#xD;&#xA;&#xD;&#xA;                    // Reset the other ray properties&#xD;&#xA;                    float directionPdf;&#xD;&#xA;                    float3a wo = normalize(ray.Direction);&#xD;&#xA;                    ray.Direction = medium-&gt;SampleScatterDirection(sampler, wo, &amp;directionPdf);&#xD;&#xA;                    ray.TNear = 0.001f;&#xD;&#xA;                    ray.TFar = infinity;&#xD;&#xA;                    ray.GeomID = INVALID_GEOMETRY_ID;&#xD;&#xA;                    ray.PrimID = INVALID_PRIMATIVE_ID;&#xD;&#xA;                    ray.InstID = INVALID_INSTANCE_ID;&#xD;&#xA;                    ray.Mask = 0xFFFFFFFF;&#xD;&#xA;                    ray.Time = 0.0f;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (hitSurface) {&#xD;&#xA;                // Fetch the material&#xD;&#xA;                Material *material = m_scene-&gt;GetMaterial(ray.GeomID);&#xD;&#xA;                // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;                // Otherwise, GetLight will return nullptr&#xD;&#xA;                Light *light = m_scene-&gt;GetLight(ray.GeomID);&#xD;&#xA;&#xD;&#xA;                // If this is the first bounce or if we just had a specular bounce,&#xD;&#xA;                // we need to add the emmisive light&#xD;&#xA;                if ((bounces == 0 || (interaction.SampledLobe &amp; BSDFLobe::Specular) != 0) &amp;&amp; light != nullptr) {&#xD;&#xA;                    color += throughput * light-&gt;Le();&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                interaction.Position = ray.Origin + ray.Direction * ray.TFar;&#xD;&#xA;                interaction.Normal = normalize(m_scene-&gt;InterpolateNormal(ray.GeomID, ray.PrimID, ray.U, ray.V));&#xD;&#xA;                interaction.OutputDirection = normalize(-ray.Direction);&#xD;&#xA;                interaction.IORo = 0.0f;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;                // Calculate the direct lighting&#xD;&#xA;                color += throughput * SampleOneLight(sampler, interaction, material-&gt;bsdf, light);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;                // Get the new ray direction&#xD;&#xA;                // Choose the direction based on the bsdf        &#xD;&#xA;                material-&gt;bsdf-&gt;Sample(interaction, sampler);&#xD;&#xA;                float pdf = material-&gt;bsdf-&gt;Pdf(interaction);&#xD;&#xA;&#xD;&#xA;                // Accumulate the weight&#xD;&#xA;                throughput = throughput * material-&gt;bsdf-&gt;Eval(interaction) / pdf;&#xD;&#xA;&#xD;&#xA;                // Update the current IOR and medium if we refracted&#xD;&#xA;                if (interaction.SampledLobe == BSDFLobe::SpecularTransmission) {&#xD;&#xA;                    interaction.IORi = interaction.IORo;&#xD;&#xA;                    medium = material-&gt;medium;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                // Shoot a new ray&#xD;&#xA;&#xD;&#xA;                // Set the origin at the intersection point&#xD;&#xA;                ray.Origin = interaction.Position;&#xD;&#xA;&#xD;&#xA;                // Reset the other ray properties&#xD;&#xA;                ray.Direction = interaction.InputDirection;&#xD;&#xA;                if (AnyNan(ray.Direction))&#xD;&#xA;                    printf(&quot;bad&quot;);&#xD;&#xA;                ray.TNear = 0.001f;&#xD;&#xA;                ray.TFar = infinity;&#xD;&#xA;                ray.GeomID = INVALID_GEOMETRY_ID;&#xD;&#xA;                ray.PrimID = INVALID_PRIMATIVE_ID;&#xD;&#xA;                ray.InstID = INVALID_INSTANCE_ID;&#xD;&#xA;                ray.Mask = 0xFFFFFFFF;&#xD;&#xA;                ray.Time = 0.0f;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            if (bounces &gt; 3) {&#xD;&#xA;                float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;                if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                throughput *= 1 / p;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (bounces == maxBounces) {&#xD;&#xA;            printf(&quot;Over max bounces&quot;);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera-&gt;FrameBufferData.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## In English:&#xD;&#xA;&#xD;&#xA;1. Shoot a ray through the scene.&#xD;&#xA;1. Check if we hit anything. If not we return the skybox color and break.&#xD;&#xA;1. Check if we are currently in a medium (not in a vacuum).&#xD;&#xA;  1. Sample the medium for a distance.&#xD;&#xA;  1. Evaluate the medium's transmission and accumulate the throughput.&#xD;&#xA;  1. If the scatter distance is less than the distance from the ray origin to the next surface, make a scatter event.&#xD;&#xA;  1. Sample the medium for a scatter direction.&#xD;&#xA;1. Check if we hit a surface (ie, we didn't have a scatter event).&#xD;&#xA;  1. If this is the first ray, or we just bounced off a specular surface, check if we hit a light. If so, we add the light emission to our color accumulation.&#xD;&#xA;  1. Sample the direct lighting.&#xD;&#xA;  1. Choose a new direction for the next ray. We can do this uniformly, or importance sample based on the BRDF.&#xD;&#xA;  1. Evaluate the BRDF and accumulate it. &#xD;&#xA;  1. If we refracted into the material, update the IOR and medium for the next bounce.&#xD;&#xA;1. Create a new ray based on our chosen direction and where we just came from.&#xD;&#xA;1. [Optional] Use Russian Roulette to choose if we should terminate the ray.&#xD;&#xA;1. Goto 1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/5152/progressive-path-tracing-with-explicit-light-sampling/5153#5153&#xD;&#xA;  [2]: https://i.stack.imgur.com/2oBo9.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/2482/choosing-reflection-or-refraction-in-path-tracing&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [5]: https://computergraphics.stackexchange.com/a/3570/310&#xD;&#xA;  [6]: https://i.stack.imgur.com/aERCt.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/tOp55.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/H7OX2.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/JgjlE.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/tZ6QO.png&#xD;&#xA;  [11]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/chapter4.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14113" PostHistoryTypeId="2" PostId="5230" RevisionGUID="be394425-88e6-4b40-a610-bcab9aaab691" CreationDate="2017-06-12T19:00:12.177" UserId="20501" Text="This is the follow-up question at here: https://computergraphics.stackexchange.com/questions/5222/&#xD;&#xA;&#xD;&#xA;Assume I have 3 original points in a 3D object (in 3D space) as `A1=&lt;xa,ya,za&gt;`, `A2=&lt;xa,ya,za&gt;`, and `A3=&lt;xa,ya,za&gt;` (assume we have all the requirements mentioned in our previous question). The 3D object is moved and rotated in the 3D space, and the new destination points become `B1=&lt;xb,yb,zb&gt;`, `B2=&lt;xb,yb,zb&gt;`, and `B3=&lt;xb,yb,zb&gt;`. &#xD;&#xA;&#xD;&#xA;What is the formula for the transformation matrix and following that, the degree of rotation in each axis? Basically, I need a matrix that if applied to all points of the origin object, I get the displaced object." ContentLicense="CC BY-SA 3.0" />
  <row Id="14114" PostHistoryTypeId="1" PostId="5230" RevisionGUID="be394425-88e6-4b40-a610-bcab9aaab691" CreationDate="2017-06-12T19:00:12.177" UserId="20501" Text="Rotation matrix for a 3D object in space" ContentLicense="CC BY-SA 3.0" />
  <row Id="14115" PostHistoryTypeId="3" PostId="5230" RevisionGUID="be394425-88e6-4b40-a610-bcab9aaab691" CreationDate="2017-06-12T19:00:12.177" UserId="20501" Text="|3d|transformations|matrix|normal-mapping|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14116" PostHistoryTypeId="5" PostId="5230" RevisionGUID="cecf0366-f35d-47d2-a6c4-206fb09e718b" CreationDate="2017-06-12T19:15:33.963" UserId="20501" Comment="added 2 characters in body" Text="This is the follow-up question from here: https://computergraphics.stackexchange.com/questions/5222/&#xD;&#xA;&#xD;&#xA;Assume I have 3 original points in a 3D object (in 3D space) as `A1=&lt;xa,ya,za&gt;`, `A2=&lt;xa,ya,za&gt;`, and `A3=&lt;xa,ya,za&gt;` (assume we have all the requirements mentioned in our previous question). The 3D object is moved and rotated in the 3D space, and the new destination points become `B1=&lt;xb,yb,zb&gt;`, `B2=&lt;xb,yb,zb&gt;`, and `B3=&lt;xb,yb,zb&gt;`. &#xD;&#xA;&#xD;&#xA;What is the formula for the transformation matrix and following that, the degree of rotation in each axis? Basically, I need a matrix that if applied to all points of the origin object, I get the displaced object." ContentLicense="CC BY-SA 3.0" />
  <row Id="14117" PostHistoryTypeId="2" PostId="5231" RevisionGUID="e9a10e83-74e8-4627-98e7-1885fdddb16b" CreationDate="2017-06-12T19:42:27.477" UserId="231" Text="Assuming that &quot;Display P3&quot; refers to the [DCI-P3] colour space, this covers a wider gamut of colours than sRGB, so that an exact match is not possible for P3 colours that fall outside the gamut of sRGB. The example colour in the question is the reddest red that DCI-P3 can produce. This is considerably redder than the reddest red that sRGB can produce, so the nearest available red is shown instead.&#xD;&#xA;&#xD;&#xA;You are right that (1, 0, 0) in sRGB is not the same as (1, 0, 0) in P3, but it is the closest it is possible to get. If you enter (1, 0, 0) in sRGB, you should see that converting it to P3 gives a red that is not the extreme (1, 0, 0). Any colour in sRGB can be converted to P3, which covers all of sRGB and more. However, only some of the colours in P3 can be converted to sRGB, since sRGB doesn't cover all of those colours. For colours that sRGB doesn't cover, the conversion utility used appears to be giving the nearest approximation available within sRGB.&#xD;&#xA;&#xD;&#xA;It is analogous to converting RGB to greyscale. Any shade of grey in RGB can be converted to greyscale and still look the same, but outside of the set of greys, any other colour will be changed when you convert to greyscale. So red will be converted to a grey that best approximates it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [DCI-P3]: https://en.wikipedia.org/wiki/DCI-P3" ContentLicense="CC BY-SA 3.0" />
  <row Id="14118" PostHistoryTypeId="5" PostId="5226" RevisionGUID="840d5499-7153-449e-bb7c-a8213a6a9603" CreationDate="2017-06-12T19:48:16.633" UserId="231" Comment="Remove redundant intro" Text="I have a Display P3 color (1, 0, 0), on a scale of 0.0 to 1.0. I want to find out what the closest color to this is in the sRGB gamut. I chose (1, 0, 0) on the right side ...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;... but the left side still shows (1, 0, 0).&#xD;&#xA;&#xD;&#xA;This makes no sense since (1, 0, 0) in sRGB is not the same color as (1, 0, 0) in P3 — the former is less saturated. As you can see in the screenshot above if you're reading this on a P3 monitor.&#xD;&#xA;&#xD;&#xA;So, how do I convert this?&#xD;&#xA;&#xD;&#xA;Conversely, given an sRGB color (1, 0, 0), how do I find out what the most saturated version of this color is in P3?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Kp8O2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14119" PostHistoryTypeId="5" PostId="5231" RevisionGUID="2c5a5751-a958-4a11-857e-a40e537972e5" CreationDate="2017-06-12T20:05:19.057" UserId="231" Comment="added 1262 characters in body" Text="Assuming that &quot;Display P3&quot; refers to the [DCI-P3] colour space, this covers a wider gamut of colours than sRGB, so that an exact match is not possible for P3 colours that fall outside the gamut of sRGB. The example colour in the question is the reddest red that DCI-P3 can produce. This is considerably redder than the reddest red that sRGB can produce, so the nearest available red is shown instead.&#xD;&#xA;&#xD;&#xA;You are right that (1, 0, 0) in sRGB is not the same as (1, 0, 0) in P3, but it is the closest it is possible to get. If you enter (1, 0, 0) in sRGB, you should see that converting it to P3 gives a red that is not the extreme (1, 0, 0). Any colour in sRGB can be converted to P3, which covers all of sRGB and more. However, only some of the colours in P3 can be converted to sRGB, since sRGB doesn't cover all of those colours. For colours that sRGB doesn't cover, the conversion utility used appears to be giving the nearest approximation available within sRGB.&#xD;&#xA;&#xD;&#xA;It is analogous to converting RGB to greyscale. Any shade of grey in RGB can be converted to greyscale and still look the same, but outside of the set of greys, any other colour will be changed when you convert to greyscale. So red will be converted to a grey that best approximates it.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In answer to your final sentence, if you want to take an sRGB colour and find the most saturated form of that colour that P3 can represent, then it is going to be less straightforward when you are dealing with a colour other than one of the primaries red, green, and blue. You need to consider whether you want the nearest hue amongst the maximum saturation colours in P3, or the most saturated of the exact hue match colours in P3. These are subtly different, because for a given hue its maximum saturation available within P3 is less than the maximum saturation available for the primaries, since the colour space is a triangle. You can compromise by deviating only slightly from the desired hue to achieve slightly more saturation, but the degree of compromise will depend on your purpose.&#xD;&#xA;&#xD;&#xA;Even for the primaries, you need to ask whether you want to convert the greenest green sRGB can represent to the greenest green P3 can represent, or whether you want to take into account that those two colours are not quite the same hue. since sRGB and P3 don't use quite the same primaries (only the blue primary is identical). If you want the hue to remain constant, it might help to convert to an intermediary colour space that includes hue as a parameter.&#xD;&#xA;&#xD;&#xA;  [DCI-P3]: https://en.wikipedia.org/wiki/DCI-P3" ContentLicense="CC BY-SA 3.0" />
  <row Id="14120" PostHistoryTypeId="5" PostId="5230" RevisionGUID="5a412699-d813-4a23-a087-ed85292c37a2" CreationDate="2017-06-12T20:27:23.653" UserId="20501" Comment="deleted 56 characters in body" Text="This is the follow-up question from here: https://computergraphics.stackexchange.com/questions/5222/&#xD;&#xA;&#xD;&#xA;Assume I have 3 original points in a 3D object (in 3D space) as `A1=&lt;xa,ya,za&gt;`, `A2=&lt;xa,ya,za&gt;`, and `A3=&lt;xa,ya,za&gt;` (assume we have all the requirements mentioned in our previous question). The 3D object is moved and rotated in the 3D space, and the new destination points become `B1=&lt;xb,yb,zb&gt;`, `B2=&lt;xb,yb,zb&gt;`, and `B3=&lt;xb,yb,zb&gt;`. &#xD;&#xA;&#xD;&#xA;What is the formula for the transformation matrix? Basically, I need a matrix that if applied to all points of the origin object, I get the displaced object." ContentLicense="CC BY-SA 3.0" />
  <row Id="14121" PostHistoryTypeId="2" PostId="5232" RevisionGUID="81f87931-b23d-47d4-86e5-0bb3da9cb247" CreationDate="2017-06-12T21:37:12.610" UserId="6824" Text="For column-major rotation matrices (right up forward in columns) do you right-multiply (post-multiply?) a row vector or left-multiply (pre-multiply) a column vector to result in a correct/valid transformation? Or are both &quot;valid&quot; but just transform different spaces?&#xD;&#xA;&#xD;&#xA;In case I'm getting my terminology wrong, suppose we have 3x3 column-major matrix R. Is it R * T, where T is 3x1? Or is it T * R, where T is 1x3? What about for row-major?&#xD;&#xA;&#xD;&#xA;For context: I'm getting quaternion data from some source (android in my case) and I'm converting it to rotation matrices. I don't know if this quaternion-&gt;matrix is row or column major, which I guess depends on the formula used for conversion. I have translation data that I would like to linearly multiply but don't know if its pre or post. But then again, I won't fully know unless I also know if the matrix itself was row or column majored. But I'll figure that out elsewhere.&#xD;&#xA;&#xD;&#xA;Thanks so much for the help!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14122" PostHistoryTypeId="1" PostId="5232" RevisionGUID="81f87931-b23d-47d4-86e5-0bb3da9cb247" CreationDate="2017-06-12T21:37:12.610" UserId="6824" Text="row and column majored rotation matrix pre- or post- multiplied" ContentLicense="CC BY-SA 3.0" />
  <row Id="14123" PostHistoryTypeId="3" PostId="5232" RevisionGUID="81f87931-b23d-47d4-86e5-0bb3da9cb247" CreationDate="2017-06-12T21:37:12.610" UserId="6824" Text="|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14124" PostHistoryTypeId="2" PostId="5233" RevisionGUID="d60575ee-919a-40d8-bd5c-e8136be01766" CreationDate="2017-06-13T03:10:34.970" UserId="2131" Text="I'm working with a object tracking project.  &#xD;&#xA;&#xD;&#xA;    Steps:&#xD;&#xA;    1.Preprocessing the image and achieve some candidates regions of interest.&#xD;&#xA;    2.For each region, test if it is the target by ORB/BF.&#xD;&#xA;    3.After the target region determined, acquire coordinates of some points on the target and their corresponding coordinates in the world coordinate system.&#xD;&#xA;    4.Use solvePnP(in opencv) to get rotation vector and translation vector.&#xD;&#xA;    5.Translation vector is used in VR for localization and view control.&#xD;&#xA;Tracking jitter means, although the object is stationary, because of some tracking errors, such as noise, the position of the target is slightly changing. Then, **look at step 4 and step 5**, due to the change, translation vector is slightly changed and with the Head Mounted Device, I feel the jitter all the time.  &#xD;&#xA;Seems to me that tracking jitter is unavoidable because of change in environment or some noise. But one pixel value change can lead to about a few centimeters change in z value in translation vector. So any proper way to deal with it? &#xD;&#xA; &#xD;&#xA;I have googled but there didn't seem much information.[Effects of Tracking Technology, Latency, and Spatial Jitter on Object Movement](http://www.yorku.ca/mack/3dui2009.html) mentions the phemomenon, but did not provide a solution. So can anyone offer some useful information?  &#xD;&#xA;It occurs to me that fileter is needed to do some post processing to the tracking data. But the idea is not very idea. Kalman filter can be used for tracking and can be used to attenuate noise. I don't know whether it can compensate for this kind of jitter(I mean, very small fluctuation in values) very well. And investigate how to incorporate Kalman filter into this project is another topic and need extra time.&#xD;&#xA;    " ContentLicense="CC BY-SA 3.0" />
  <row Id="14125" PostHistoryTypeId="1" PostId="5233" RevisionGUID="d60575ee-919a-40d8-bd5c-e8136be01766" CreationDate="2017-06-13T03:10:34.970" UserId="2131" Text="how to overcome tracking jitter" ContentLicense="CC BY-SA 3.0" />
  <row Id="14126" PostHistoryTypeId="3" PostId="5233" RevisionGUID="d60575ee-919a-40d8-bd5c-e8136be01766" CreationDate="2017-06-13T03:10:34.970" UserId="2131" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14127" PostHistoryTypeId="5" PostId="5233" RevisionGUID="895f45e1-2132-478a-8162-3abe84fd8a1e" CreationDate="2017-06-13T07:50:25.173" UserId="2041" Comment="Remove erroneous code formatting, make the text into paragraphs, and add some relevant tags." Text="I'm working with a object tracking project.  &#xD;&#xA;&#xD;&#xA;Steps:&#xD;&#xA;&#xD;&#xA;1. Preprocessing the image and achieve some candidates regions of interest.&#xD;&#xA;&#xD;&#xA;2. For each region, test if it is the target by ORB/BF.&#xD;&#xA;&#xD;&#xA;3. After the target region determined, acquire coordinates of some points on the target and their corresponding coordinates in the world coordinate system.&#xD;&#xA;&#xD;&#xA;4. Use solvePnP(in opencv) to get rotation vector and translation vector.&#xD;&#xA;&#xD;&#xA;5. Translation vector is used in VR for localization and view control.&#xD;&#xA;&#xD;&#xA;Tracking jitter means, although the object is stationary, because of some tracking errors, such as noise, the position of the target is slightly changing. Then, **look at step 4 and step 5**, due to the change, translation vector is slightly changed and with the Head Mounted Device, I feel the jitter all the time.&#xD;&#xA;&#xD;&#xA;Seems to me that tracking jitter is unavoidable because of change in environment or some noise. But one pixel value change can lead to about a few centimeters change in z value in translation vector. So any proper way to deal with it? &#xD;&#xA; &#xD;&#xA;I have googled but there didn't seem much information. [Effects of Tracking Technology, Latency, and Spatial Jitter on Object Movement](http://www.yorku.ca/mack/3dui2009.html) mentions the phemomenon, but did not provide a solution. So can anyone offer some useful information?&#xD;&#xA;&#xD;&#xA;It occurs to me that filtering is needed to do some post processing to the tracking data. But the idea is not very idea. Kalman filter can be used for tracking and can be used to attenuate noise. I don't know whether it can compensate for this kind of jitter (I mean, very small fluctuation in values) very well. And investigate how to incorporate Kalman filter into this project is another topic and need extra time.&#xD;&#xA;    " ContentLicense="CC BY-SA 3.0" />
  <row Id="14128" PostHistoryTypeId="6" PostId="5233" RevisionGUID="895f45e1-2132-478a-8162-3abe84fd8a1e" CreationDate="2017-06-13T07:50:25.173" UserId="2041" Comment="Remove erroneous code formatting, make the text into paragraphs, and add some relevant tags." Text="|image-processing|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14129" PostHistoryTypeId="5" PostId="4979" RevisionGUID="0869bf76-1c42-432f-b0f7-cb1c4c974beb" CreationDate="2017-06-13T08:25:41.137" UserId="5256" Comment="added 395 characters in body" Text="What is importance sampling? Every article I read about it mentions 'PDF' what is that aswell?&#xD;&#xA;&#xD;&#xA;From what I gather importance sampling is a technique to only sample areas on a hemisphere that matter more than others. So ideally I should sample rays towards light sources to reduce noise and increase speed, also some BRDF's at grazing angles have little no difference in the calculation so using importance sampling to avoid that is good? &#xD;&#xA;&#xD;&#xA;If I were to implement importance sampling for a Cook-Torrance BRDF how could I do this? &#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;In the path tracer to calculate the importance sampled scattered ray direction as opposed to randomly sampling the hemisphere above point **P** could this function be used?:&#xD;&#xA;&#xD;&#xA;    vec2 importance_sample_ggx(vec2 xi)&#xD;&#xA;    {&#xD;&#xA;      float phi = 2.0f * PI * xi.x;&#xD;&#xA;      float theta = acos(sqrt((1.0f - xi.y)/((a*a - 1.0f) * xi.y + 1.0f)));&#xD;&#xA;      return vec2(phi, theta);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="14130" PostHistoryTypeId="2" PostId="5234" RevisionGUID="c8520463-31b5-4d08-921c-11c28a24a6b4" CreationDate="2017-06-13T09:03:37.640" UserId="38" Text="Okay let us start by pointing out that a colmun major matrix is the same as a transposed row major matrix. So:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;{M_{cm}}^{T} = M_{rm} \tag{1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then notice that matrixes have following properties. Matrix multiplication is associative (2a) and that the distribution of transpose reverses computation order (2b).&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;A(BC)  =  (AB)C \tag{2a}&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;(AB)^T  =  B^TA^T \tag{2b}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;From these follow that the chain of multiplication events can be as long as one likes and all transpose does is inverse the computation. So given that we can conclude &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;{T_1}\ {T_2}\ \ldots\ {T_n}\ \vec{v} = (\vec{v})^T\ {T_n}^T\ \ldots\ {T_2}^T\ {T_1}^T, \tag{3}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;so calculating in column major order **is the same calculation** as calculating in row major orientation. The difference is that the order of computation is reversed. An interpretation of this is that the difference is the same as looking at the object from the outside or looking at the situation from the object out.&#xD;&#xA;&#xD;&#xA;Formula 3 should provide you the insight. Just one more thing a column vector is the same as a transpose of a row vector.&#xD;&#xA;&#xD;&#xA;**Note**: You are allowed to mix and match the computations as much as you like. All you have do is remember is that the other approach is just transposed." ContentLicense="CC BY-SA 3.0" />
  <row Id="14131" PostHistoryTypeId="5" PostId="5234" RevisionGUID="f5a1d999-4855-43a9-b8ca-3892b63ae9b8" CreationDate="2017-06-13T10:22:32.700" UserId="38" Comment="deleted 1 character in body" Text="Okay let us start by pointing out that a colmun major matrix is the same as a transposed row major matrix. So:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;{M_{cm}}^{T} = M_{rm} \tag{1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then notice that matrixes have following properties. Matrix multiplication is associative (2a) and that the distribution of transpose reverses computation order (2b).&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;A(BC)  =  (AB)C \tag{2a}&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;(AB)^T  =  B^TA^T \tag{2b}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;From these follow that the chain of multiplication events can be as long as one likes and all transpose does is inverse the computation. So given that we can conclude &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;{T_1}\ {T_2}\ \ldots\ {T_n}\ \vec{v} = \vec v\,^T\ {T_n}^T\ \ldots\ {T_2}^T\ {T_1}^T, \tag{3}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;so calculating in column major order **is the same calculation** as calculating in row major orientation. The difference is that the order of computation is reversed. An interpretation of this is that the difference is the same as looking at the object from the outside or looking at the situation from the object out.&#xD;&#xA;&#xD;&#xA;Formula 3 should provide you the insight. Just one more thing a column vector is the same as a transpose of a row vector.&#xD;&#xA;&#xD;&#xA;**Note**: You are allowed to mix and match the computations as much as you like. All you have do is remember is that the other approach is just transposed." ContentLicense="CC BY-SA 3.0" />
  <row Id="14135" PostHistoryTypeId="5" PostId="4979" RevisionGUID="1cadba53-9ba9-4743-88c6-988ec2656d03" CreationDate="2017-06-13T14:56:32.563" UserId="5256" Comment="deleted 395 characters in body" Text="What is importance sampling? Every article I read about it mentions 'PDF' what is that aswell?&#xD;&#xA;&#xD;&#xA;From what I gather importance sampling is a technique to only sample areas on a hemisphere that matter more than others. So ideally I should sample rays towards light sources to reduce noise and increase speed, also some BRDF's at grazing angles have little no difference in the calculation so using importance sampling to avoid that is good? &#xD;&#xA;&#xD;&#xA;If I were to implement importance sampling for a Cook-Torrance BRDF how could I do this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14138" PostHistoryTypeId="2" PostId="5236" RevisionGUID="5aa90ff9-ac7b-4185-98ff-a846c6dab1e1" CreationDate="2017-06-13T17:00:00.227" UserId="6832" Text="**tl;dr** Is there a name for a type of (non-physical) projection that causes objects to become larger the farther they are from a camera?&#xD;&#xA;&#xD;&#xA;1. With a **fisheye** projection, an object twice as far from the camera is less than half the size on screen. _(I think; my understanding of fisheye math is fuzzy. I gather there are various projections/mapping functions.)_ There is massive foreshortening, objects shrink very quickly as they move away.&#xD;&#xA;&#xD;&#xA;2. With a **rectilinear** projection, an object twice as from the camera is always half the size on screen, regardless of FoV. This is how trigonometry works. Infinitely-far objects have zero size.&#xD;&#xA;[![Triangles showing two different field of view, showing that twice the distance yields an image plane that is twice the size][1]][1]&#xD;&#xA;&#xD;&#xA;3. With an **orthographic** projection, an object twice as far from the camera is always the same size on screen. There is no foreshortening. Infinitely-far objects have the same size.&#xD;&#xA;&#xD;&#xA;4. Now, go one step farther. I want negative foreshortening. I want to see an object get bigger the farther away it gets. Infinitely-far objects have infinite size.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LmYtx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14139" PostHistoryTypeId="1" PostId="5236" RevisionGUID="5aa90ff9-ac7b-4185-98ff-a846c6dab1e1" CreationDate="2017-06-13T17:00:00.227" UserId="6832" Text="3D projection that increases objects' size as they become more distant" ContentLicense="CC BY-SA 3.0" />
  <row Id="14140" PostHistoryTypeId="3" PostId="5236" RevisionGUID="5aa90ff9-ac7b-4185-98ff-a846c6dab1e1" CreationDate="2017-06-13T17:00:00.227" UserId="6832" Text="|rendering|3d|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14142" PostHistoryTypeId="2" PostId="5237" RevisionGUID="d87924bb-55ab-48a9-b41d-6a93eb7a31c7" CreationDate="2017-06-13T18:30:10.880" UserId="4908" Text="After a quick google of 'Inverted perspective' I found out that you have five different names for it; Reverse perspective, inverse perspective, inverted perspective, divergent perspective and Byzantine perspective. https://en.wikipedia.org/wiki/Reverse_perspective&#xD;&#xA;&#xD;&#xA;I think that if you want to use it in a render engine using a projection matrix, in the perspective divide, you use multiply by w instead of divide. This is because in a perspective projection, the divide by w is what actually gives the perspective. In a orthographic projection w is always 1, meaning that there is no actual perspective.&#xD;&#xA;&#xD;&#xA;For a ray tracer you probably just need to scale the image plane up of course, but probably instead of having the origin of the ray to be the center of the camera, you have some kind of second image plane that is larger than the actual image plane. If both are the same size, the rays are straight and you have an orthographic projection, if the actual image plane is smaller then you have your Reverse perspective.&#xD;&#xA;&#xD;&#xA;Quick extra note: If you have proper lenses, you might be able to get this effect in real life. Yes, you would need to have a lens that is a few meters in diameter, but I do not think it is impossible! :P&#xD;&#xA;&#xD;&#xA;I hope this will help you and that I have not made any mistakes. Good luck with whatever you are doing!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14143" PostHistoryTypeId="2" PostId="5238" RevisionGUID="15f175f5-2bf8-42ec-be93-2c2f09a0b3bd" CreationDate="2017-06-13T19:01:26.207" UserId="4546" Text="For cases where the diffusion approximation is preferred over full volumetric path tracing, the method published by Solid Angle is fairly efficient:&#xD;&#xA;https://www.solidangle.com/research/s2013_bssrdf_slides.pdf&#xD;&#xA;&#xD;&#xA;It is implemented in the Arnold render engine, Blender's Cycles, and pbrt, the latter being open source.&#xD;&#xA;&#xD;&#xA;The file which implements it in PBRT is here:&#xD;&#xA;https://github.com/mmp/pbrt-v3/blob/7095acfd8331cdefb03fe0bcae32c2fc9bd95980/src/core/bssrdf.cpp" ContentLicense="CC BY-SA 3.0" />
  <row Id="14144" PostHistoryTypeId="5" PostId="5232" RevisionGUID="c6ad2bc2-3117-412d-960c-94a453f54aef" CreationDate="2017-06-13T19:35:41.143" UserId="6824" Comment="added 1023 characters in body" Text="For column-major rotation matrices (right up forward in columns) do you right-multiply (post-multiply?) a row vector or left-multiply (pre-multiply) a column vector to result in a correct/valid transformation? Or are both &quot;valid&quot; but just transform different spaces?&#xD;&#xA;&#xD;&#xA;In case I'm getting my terminology wrong, suppose we have 3x3 column-major matrix R. Is it R * T, where T is 3x1? Or is it T * R, where T is 1x3? What about for row-major?&#xD;&#xA;&#xD;&#xA;For context: I'm getting quaternion data from some source (android in my case) and I'm converting it to rotation matrices. I don't know if this quaternion-&gt;matrix is row or column major, which I guess depends on the formula used for conversion. I have translation data that I would like to linearly multiply but don't know if its pre or post. But then again, I won't fully know unless I also know if the matrix itself was row or column majored. But I'll figure that out elsewhere.&#xD;&#xA;&#xD;&#xA;Thanks so much for the help!&#xD;&#xA;&#xD;&#xA;Edit: I believe my question needs further clarification. I am more confused about whether a vector, whether a row or column, is multiplied to the left or right of a row specific (or column specific) majored matrix respectively. I do understand the concept that transposing a matrix will just mean you have to transpose the vector and flip the order of multiplication, which will result in the same thing because you're multiplying the same elements the other way around. And when I say row specific (or column), I'm talking about the way the right up forward vectors are positioned in the matrix. Though at this point, I think I already have figured out my answer just by typing this, but will leave it open for answers.&#xD;&#xA;&#xD;&#xA;My question is simply this:&#xD;&#xA;     X1 Y1 Z1&#xD;&#xA;R =  X2 Y2 Z2&#xD;&#xA;     X3 Y3 Z3&#xD;&#xA;&#xD;&#xA;This is a row majored rotation matrix. Now I have the vector V1 V2 V3 as either a 3x1 or 1x3 (right side or left side respectively, else the multiplication doesn't even work out). So is it R * T or T * R (in this case)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14145" PostHistoryTypeId="5" PostId="5232" RevisionGUID="1a14a18c-9d5e-4147-9011-7e9f67d4255d" CreationDate="2017-06-13T19:42:23.800" UserId="6824" Comment="clarify question" Text="For column-major rotation matrices (right up forward in columns) do you right-multiply (post-multiply?) a row vector or left-multiply (pre-multiply) a column vector to result in a correct/valid transformation? Or are both &quot;valid&quot; but just transform different spaces?&#xD;&#xA;&#xD;&#xA;In case I'm getting my terminology wrong, suppose we have 3x3 column-major matrix R. Is it R * T, where T is 3x1? Or is it T * R, where T is 1x3? What about for row-major?&#xD;&#xA;&#xD;&#xA;For context: I'm getting quaternion data from some source (android in my case) and I'm converting it to rotation matrices. I don't know if this quaternion-&gt;matrix is row or column major, which I guess depends on the formula used for conversion. I have translation data that I would like to linearly multiply but don't know if its pre or post. But then again, I won't fully know unless I also know if the matrix itself was row or column majored. But I'll figure that out elsewhere.&#xD;&#xA;&#xD;&#xA;Thanks so much for the help!&#xD;&#xA;&#xD;&#xA;Edit: I believe my question needs further clarification. I am more confused about whether a vector, whether a row or column, is multiplied to the left or right of a row specific (or column specific) majored matrix respectively. I do understand the concept that transposing a matrix will just mean you have to transpose the vector and flip the order of multiplication, which will result in the same thing because you're multiplying the same elements the other way around. And when I say row specific (or column), I'm talking about the way the right up forward vectors are positioned in the matrix. Though at this point, I think I already have figured out my answer just by typing this, but will leave it open for answers.&#xD;&#xA;&#xD;&#xA;My question is simply this:&#xD;&#xA;(sorry, I don't know how to format things here)&#xD;&#xA;&#xD;&#xA;I have the following matrix:&#xD;&#xA;&#xD;&#xA;X1 Y1 Z1&#xD;&#xA;&#xD;&#xA;X2 Y2 Z2&#xD;&#xA;&#xD;&#xA;X3 Y3 Z3&#xD;&#xA;&#xD;&#xA;This is a row majored rotation matrix. Now I have a vector V as {V1 V2 V3} as either a 3x1 or 1x3 (right side or left side respectively, else the multiplication doesn't even work out). So is it R * T or T * R (in this case)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14146" PostHistoryTypeId="5" PostId="5232" RevisionGUID="19d41288-29b9-4acf-9e13-6d16a67a97b2" CreationDate="2017-06-13T19:48:21.507" UserId="6824" Comment="typo" Text="For column-major rotation matrices (right up forward in columns) do you right-multiply (post-multiply?) a row vector or left-multiply (pre-multiply) a column vector to result in a correct/valid transformation? Or are both &quot;valid&quot; but just transform different spaces?&#xD;&#xA;&#xD;&#xA;In case I'm getting my terminology wrong, suppose we have 3x3 column-major matrix R. Is it R * T, where T is 3x1? Or is it T * R, where T is 1x3? What about for row-major?&#xD;&#xA;&#xD;&#xA;For context: I'm getting quaternion data from some source (android in my case) and I'm converting it to rotation matrices. I don't know if this quaternion-&gt;matrix is row or column major, which I guess depends on the formula used for conversion. I have translation data that I would like to linearly multiply but don't know if its pre or post. But then again, I won't fully know unless I also know if the matrix itself was row or column majored. But I'll figure that out elsewhere.&#xD;&#xA;&#xD;&#xA;Thanks so much for the help!&#xD;&#xA;&#xD;&#xA;Edit: I believe my question needs further clarification. I am more confused about whether a vector, whether a row or column, is multiplied to the left or right of a row specific (or column specific) majored matrix respectively. I do understand the concept that transposing a matrix will just mean you have to transpose the vector and flip the order of multiplication, which will result in the same thing because you're multiplying the same elements the other way around. And when I say row specific (or column), I'm talking about the way the right up forward vectors are positioned in the matrix. Though at this point, I think I already have figured out my answer just by typing this, but will leave it open for answers.&#xD;&#xA;&#xD;&#xA;My question is simply this:&#xD;&#xA;(sorry, I don't know how to format things here)&#xD;&#xA;&#xD;&#xA;I have the following matrix:&#xD;&#xA;&#xD;&#xA;X1 Y1 Z1&#xD;&#xA;&#xD;&#xA;X2 Y2 Z2&#xD;&#xA;&#xD;&#xA;X3 Y3 Z3&#xD;&#xA;&#xD;&#xA;This is a row majored rotation matrix. Now I have a vector V as {V1 V2 V3} as either a 3x1 or 1x3 (right side or left side respectively, else the multiplication doesn't even work out). So is it R * V or V * R (in this case)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14148" PostHistoryTypeId="2" PostId="5239" RevisionGUID="44d5fd27-842f-42fb-932a-9786fdeb5d2d" CreationDate="2017-06-14T01:28:19.090" UserId="6834" Text="How can i store the X,Y,Z vertex points of a mesh into a 2d image, such that reading the image pixel values will correspond to the 3d coordinates? is it possible to just store x, y, values on a grid and use the Z value as an intensity value?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14149" PostHistoryTypeId="1" PostId="5239" RevisionGUID="44d5fd27-842f-42fb-932a-9786fdeb5d2d" CreationDate="2017-06-14T01:28:19.090" UserId="6834" Text="Store 3d coordinates in a 2d image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14150" PostHistoryTypeId="3" PostId="5239" RevisionGUID="44d5fd27-842f-42fb-932a-9786fdeb5d2d" CreationDate="2017-06-14T01:28:19.090" UserId="6834" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14151" PostHistoryTypeId="2" PostId="5240" RevisionGUID="31e1c8e3-b4f4-43b8-8dea-562b98a62c58" CreationDate="2017-06-14T01:56:42.377" UserId="3003" Text="The most straightforward way would be to put x into the red channel, y into the green channel, and z into the blue channel of each pixel. &#xD;&#xA;&#xD;&#xA;You could also make a 1 channel image where intensity is used to describe height. This is called a [height map](https://en.wikipedia.org/wiki/Heightmap). Usually the x and y of the mesh are the same as the x and y of the image, so no need to store them in any way." ContentLicense="CC BY-SA 3.0" />
  <row Id="14158" PostHistoryTypeId="2" PostId="5242" RevisionGUID="5ddf42cc-0cb2-48b2-82b3-035dcacd57f6" CreationDate="2017-06-14T15:22:22.347" UserId="6367" Text="I'm confused by the Mitsuba bidirectional framework for quite a while now, especially by the different `eval` and `connect` functions, as well as the `weight` and `pdf` variables.&#xD;&#xA;&#xD;&#xA;So, what is the difference between `PathVertex::eval` and `PathVertex::weight[]`, and `PathVertex::evalPdf` and `PathVertex::pdf[]`.&#xD;&#xA;&#xD;&#xA;What are the differences between `PathEdge::evalCached`, `PathEdge::eval*`, `PathEdge::weight[]`, `PathEdge::pdf[]`, etc.&#xD;&#xA;&#xD;&#xA;Furthermore, how do the `PathVertex::connect` and `PathEdge::pathConnectAndCollapse` differ?&#xD;&#xA;&#xD;&#xA;To make the problem more concrete, let's say I have two vertices, one at the end of an emitter subpath, call it $y_{s-1}$ and one at the end of a sensor subpath, $x_{t-1}$, both surface interactions. &#xD;&#xA;&#xD;&#xA; - What is the correct way of connecting these two?&#xD;&#xA; - If I want to calculate $f(y_{s-2} \rightarrow y_{s-1} \rightarrow z_{t-1}) G(y_{s-1} \leftrightarrow x_{t-1}) f(y_{s-1} \rightarrow z_{t-1} \rightarrow z_{t-2})$, what is the correct way of going about this?&#xD;&#xA;&#xD;&#xA;Thanks a lot in advance!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14159" PostHistoryTypeId="1" PostId="5242" RevisionGUID="5ddf42cc-0cb2-48b2-82b3-035dcacd57f6" CreationDate="2017-06-14T15:22:22.347" UserId="6367" Text="Mitsuba Bidirectional Framework" ContentLicense="CC BY-SA 3.0" />
  <row Id="14160" PostHistoryTypeId="3" PostId="5242" RevisionGUID="5ddf42cc-0cb2-48b2-82b3-035dcacd57f6" CreationDate="2017-06-14T15:22:22.347" UserId="6367" Text="|rendering|pathtracing|brdf|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14161" PostHistoryTypeId="5" PostId="5232" RevisionGUID="e44ff3e6-942f-4d42-b5dd-75aa377adce8" CreationDate="2017-06-14T16:57:13.230" UserId="6824" Comment="updated matrix for clarification" Text="For column-major rotation matrices (right up forward in columns) do you right-multiply (post-multiply?) a row vector or left-multiply (pre-multiply) a column vector to result in a correct/valid transformation? Or are both &quot;valid&quot; but just transform different spaces?&#xD;&#xA;&#xD;&#xA;In case I'm getting my terminology wrong, suppose we have 3x3 column-major matrix R. Is it R * T, where T is 3x1? Or is it T * R, where T is 1x3? What about for row-major?&#xD;&#xA;&#xD;&#xA;For context: I'm getting quaternion data from some source (android in my case) and I'm converting it to rotation matrices. I don't know if this quaternion-&gt;matrix is row or column major, which I guess depends on the formula used for conversion. I have translation data that I would like to linearly multiply but don't know if its pre or post. But then again, I won't fully know unless I also know if the matrix itself was row or column majored. But I'll figure that out elsewhere.&#xD;&#xA;&#xD;&#xA;Thanks so much for the help!&#xD;&#xA;&#xD;&#xA;Edit: I believe my question needs further clarification. I am more confused about whether a vector, whether a row or column, is multiplied to the left or right of a row specific (or column specific) majored matrix respectively. I do understand the concept that transposing a matrix will just mean you have to transpose the vector and flip the order of multiplication, which will result in the same thing because you're multiplying the same elements the other way around. And when I say row specific (or column), I'm talking about the way the right up forward vectors are positioned in the matrix. Though at this point, I think I already have figured out my answer just by typing this, but will leave it open for answers.&#xD;&#xA;&#xD;&#xA;My question is simply this:&#xD;&#xA;(sorry, I don't know how to format things here)&#xD;&#xA;&#xD;&#xA;I have the following matrix:&#xD;&#xA;&#xD;&#xA;Rx Ry Rz&#xD;&#xA;&#xD;&#xA;Ux Uy Uz&#xD;&#xA;&#xD;&#xA;Fx Fy Fz&#xD;&#xA;&#xD;&#xA;This is a row-majored, orthonormal rotation matrix. Now I have a vector V as {V1 V2 V3} as either a 3x1 or 1x3 (right side or left side respectively, else the multiplication doesn't even work out). So is it R * V or V * R (in this case)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14162" PostHistoryTypeId="5" PostId="5232" RevisionGUID="ff405c34-c43f-4be0-8979-ae9b63332a09" CreationDate="2017-06-14T20:38:15.630" UserId="6824" Comment="even more clarification." Text="For column-major rotation matrices (right up forward in columns) do you right-multiply (post-multiply?) a row vector or left-multiply (pre-multiply) a column vector to result in a correct/valid transformation? Or are both &quot;valid&quot; but just transform different spaces?&#xD;&#xA;&#xD;&#xA;In case I'm getting my terminology wrong, suppose we have 3x3 column-major matrix R. Is it R * V for column-major matrix, where V is 3x1? Or is it V * R for column-major matrix, where V is 1x3? What about for row-major?&#xD;&#xA;&#xD;&#xA;Thanks so much for the help!&#xD;&#xA;&#xD;&#xA;Edit: I believe my question needs further clarification. I am more confused about whether a vector, regardless if it's a row or column, is multiplied to the left or right of a **row specific majored matrix**. And vice versa for column-majored matrix, but it would be implied by answering either which one. I do understand the concept that transposing a matrix will just mean you have to transpose the vector and flip the order of multiplication, which will result in the same thing because you're multiplying the same elements the other way around. That is not the concern of my question (though thanks for those who answered that part). When I say row specific (or column), I'm talking about the way the **right up forward vectors** are positioned in the matrix. Though at this point, I think I already have figured out my answer just by typing this, but will leave it open for answers.&#xD;&#xA;&#xD;&#xA;My question is simply this:&#xD;&#xA;(sorry, I don't know how to format things here)&#xD;&#xA;&#xD;&#xA;I have the following matrix composed of Right Up and Forward vectors:&#xD;&#xA;&#xD;&#xA;Rx Ry Rz&#xD;&#xA;&#xD;&#xA;Ux Uy Uz&#xD;&#xA;&#xD;&#xA;Fx Fy Fz&#xD;&#xA;&#xD;&#xA;This is a row-majored, orthonormal rotation matrix. Now I have a vector V as {V1 V2 V3} as either a 3x1 or 1x3 (right side or left side respectively, else the multiplication doesn't even work out). Is it R * V or V * R in this case of a row-major matrix? Again, not asking about 1x3 on left or 3x1 on right, but rather for a row-specific matrix, which way would produce a valid or meaningful transformation?&#xD;&#xA;&#xD;&#xA;{V1*Rx + V2*Ry + V3*Rz, V1*Ux + V2*Uy + V3*Uz, V1*Fx + V2*Fy + V3*Fz} ?&#xD;&#xA;&#xD;&#xA;OR&#xD;&#xA;&#xD;&#xA;{V1*Rx + V2*Ux + V3*Fx, V1*Ry + V2*Uy + V3*Fy, V1*Rz + V2*Uz + V3*Fz} ?&#xD;&#xA;&#xD;&#xA;I'm guessing the second, but would like clarification/confirmation. Thank you again!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14163" PostHistoryTypeId="2" PostId="5243" RevisionGUID="8baea3da-1387-4f14-9848-80e4a3d523ce" CreationDate="2017-06-14T20:47:35.490" UserId="6838" Text="I'm aware of the fact that you can take a high resolution mesh, turn it into a low resolution mesh, and then do some ray casting to make a normal map. But how does one go about taking a single texture and getting a decent normal map out of it?&#xD;&#xA;&#xD;&#xA;If you can, I'd like to learn about the mechanics behind it, and not a piece of software like CrazyBump that does it for me." ContentLicense="CC BY-SA 3.0" />
  <row Id="14164" PostHistoryTypeId="1" PostId="5243" RevisionGUID="8baea3da-1387-4f14-9848-80e4a3d523ce" CreationDate="2017-06-14T20:47:35.490" UserId="6838" Text="How are Normal Maps created?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14165" PostHistoryTypeId="3" PostId="5243" RevisionGUID="8baea3da-1387-4f14-9848-80e4a3d523ce" CreationDate="2017-06-14T20:47:35.490" UserId="6838" Text="|texture|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14169" PostHistoryTypeId="5" PostId="5243" RevisionGUID="237944f1-b377-4803-a750-6547fd1c8bf1" CreationDate="2017-06-15T13:07:02.297" UserId="6838" Comment="deleted 155 characters in body" Text="How does one go about taking a single texture and getting a decent normal map out of it?&#xD;&#xA;&#xD;&#xA;If you can, I'd like to learn about the mechanics behind it, and not a piece of software like CrazyBump that does it for me." ContentLicense="CC BY-SA 3.0" />
  <row Id="14171" PostHistoryTypeId="2" PostId="5245" RevisionGUID="ea3cec3d-7593-46c9-8adf-1127a8fe6c38" CreationDate="2017-06-15T16:50:43.420" UserId="6092" Text="At the moment, I render everything in my OpenGL application to a single framebuffer (color only, no depth buffer). I then go from the texture ID and read out some data to use it. My problem is, in the init, I first init the GLFW window, make it visible calling `glfwShowWindow(window);` and then create the frame buffer. This means I have an empty window showing up where nothing is rendered. &#xD;&#xA;&#xD;&#xA;But when I comment this line to keep the window hidden, the frame buffer status after creation is `GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT`. How do I go about rendering offscreen without window, and is there a possibility to not use GLFW at all?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14172" PostHistoryTypeId="1" PostId="5245" RevisionGUID="ea3cec3d-7593-46c9-8adf-1127a8fe6c38" CreationDate="2017-06-15T16:50:43.420" UserId="6092" Text="LWJGL 3 render to texture offscreen without display" ContentLicense="CC BY-SA 3.0" />
  <row Id="14173" PostHistoryTypeId="3" PostId="5245" RevisionGUID="ea3cec3d-7593-46c9-8adf-1127a8fe6c38" CreationDate="2017-06-15T16:50:43.420" UserId="6092" Text="|opengl|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14174" PostHistoryTypeId="5" PostId="5236" RevisionGUID="dd58c3b6-6497-434a-94af-ddb62668a0f4" CreationDate="2017-06-15T17:44:27.200" UserId="231" Comment="Missing word" Text="**tl;dr** Is there a name for a type of (non-physical) projection that causes objects to become larger the farther they are from a camera?&#xD;&#xA;&#xD;&#xA;1. With a **fisheye** projection, an object twice as far from the camera is less than half the size on screen. _(I think; my understanding of fisheye math is fuzzy. I gather there are various projections/mapping functions.)_ There is massive foreshortening, objects shrink very quickly as they move away.&#xD;&#xA;&#xD;&#xA;2. With a **rectilinear** projection, an object twice as far from the camera is always half the size on screen, regardless of FoV. This is how trigonometry works. Infinitely-far objects have zero size.&#xD;&#xA;[![Triangles showing two different field of view, showing that twice the distance yields an image plane that is twice the size][1]][1]&#xD;&#xA;&#xD;&#xA;3. With an **orthographic** projection, an object twice as far from the camera is always the same size on screen. There is no foreshortening. Infinitely-far objects have the same size.&#xD;&#xA;&#xD;&#xA;4. Now, go one step farther. I want negative foreshortening. I want to see an object get bigger the farther away it gets. Infinitely-far objects have infinite size.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LmYtx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14175" PostHistoryTypeId="5" PostId="5243" RevisionGUID="c09647e8-9f68-4c50-8acf-24e09abce50e" CreationDate="2017-06-15T17:59:37.277" UserId="6838" Comment="Clarified question" Text="How does one go about taking a single photograph, like a picture of a rock wall, and getting a decent normal map out of it?&#xD;&#xA;&#xD;&#xA;If you can, I'd like to learn about the mechanics behind it, and not a piece of software like CrazyBump that does it for me." ContentLicense="CC BY-SA 3.0" />
  <row Id="14176" PostHistoryTypeId="5" PostId="5211" RevisionGUID="73aafbf0-1e3e-49cf-9f0c-7c78c22d085c" CreationDate="2017-06-15T18:09:12.703" UserId="231" Comment="Include code links from comment" Text="I'm trying to figure out the surface area of a mesh that is the result of various CSG union operations between an arbitrary number of other meshes by summing up the same property of each one of  it's faces (triangles, in this case) but the result is far greater than expected. I believe that this is happening because the mesh that results from the CSG union operations have internal faces, but I'm trying to find only the surface area of it's exterior.&#xD;&#xA;&#xD;&#xA;Is there any technique to remove the inner faces of a triangulated mesh, or maybe some way to just ignore these ones while calculating it's surface area?&#xD;&#xA;&#xD;&#xA;Currently I'm using [Net3dBool](https://github.com/Arakis/Net3dBool) to perform the CSG operations. The code that performs the intersection is on the file [BooleanModeller.cs](https://github.com/Arakis/Net3dBool/blob/master/src/Net3dBool/BooleanModeller.cs), on the `getIntersection` method, wich calls the `composeSolid` method." ContentLicense="CC BY-SA 3.0" />
  <row Id="14177" PostHistoryTypeId="2" PostId="5246" RevisionGUID="dc7b31ce-163b-4f56-a3a1-3265d6531668" CreationDate="2017-06-16T09:02:40.483" UserId="6841" Text="I want to write plugin (library) for Unity3d (it doesn't matter which framework I will choose for this, question is ), for cutting arbitrary mesh with plane (for simplicity it will be plane for beginning). &#xD;&#xA;&#xD;&#xA;[![Cutting simple (convex to be more precise) figures with plane][1]][1]&#xD;&#xA;&#xD;&#xA;There are following steps:&#xD;&#xA;&#xD;&#xA;1) check every triangle whether it lies above, under plane or intersected by plane, assign all vertices to `VER_ABOVE` or `VER_UNDER` lists, recalculate triangles, put them in `TRI_ABOVE` or `TRI_UNDER` lists&#xD;&#xA;&#xD;&#xA;2) Split intersected triangles into triangle and quadrilateral, triangulate last one and put them in corresponding lists (`TRI_ABOVE` or `TRI_UNDER`)&#xD;&#xA;&#xD;&#xA;3) Triangulate slice surface, assign it to `TRI_ABOVE` and `TRI_UNDER`&#xD;&#xA;&#xD;&#xA;**And now the question:** &#xD;&#xA;&#xD;&#xA;Where it is better to calculate intersections, triangulation (for example I will use Constrained Delaunay Triangulation or Sweep Line Non-Convex Polygonal Triangulation cutting into monotone polygonals) and other stuff: on CPU or on GPU (using Shaders), if someone could explain me general pipeline from loading cashing mesh to memory and so on on GPU and on CPU, so I can better understand the most time consuming actions and can optimize some stuff.&#xD;&#xA;&#xD;&#xA;I will also be thankful for sharing link on code examples calculating similar stuff.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qvcgX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14178" PostHistoryTypeId="1" PostId="5246" RevisionGUID="dc7b31ce-163b-4f56-a3a1-3265d6531668" CreationDate="2017-06-16T09:02:40.483" UserId="6841" Text="What is better to use for real-time computing Mesh - Plane intersection points, GPU or CPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14179" PostHistoryTypeId="3" PostId="5246" RevisionGUID="dc7b31ce-163b-4f56-a3a1-3265d6531668" CreationDate="2017-06-16T09:02:40.483" UserId="6841" Text="|shader|real-time|mesh|triangulation|tesselation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14180" PostHistoryTypeId="2" PostId="5247" RevisionGUID="198ae809-7423-44df-a039-794895f34a6a" CreationDate="2017-06-16T12:05:35.587" UserId="2831" Text="Skimming the math.  Starting with a quaternion $Q=w+\left(x,y,z\right)$ then we can rotate $\mathbf{v}$ by:&#xD;&#xA;&#xD;&#xA;$$\mathbf{v}' = Q\mathbf{v}Q^{-1}$$&#xD;&#xA;&#xD;&#xA;and if $Q$ is unit magnitude this reduces to:&#xD;&#xA;&#xD;&#xA;$$\mathbf{v}' = Q\mathbf{v}Q^*$$&#xD;&#xA;&#xD;&#xA;To create a matrix we need to apply the rotation to the basis set to form our three equations:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{x} = \left(1,0,0\right) \\&#xD;&#xA;\mathbf{y} = \left(0,1,0\right) \\&#xD;&#xA;\mathbf{z} = \left(0,0,1\right) \\&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;which expanded and reduced gives:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{x}' = Q\mathbf{x}Q^{-1} = \left(1 - 2 \left(y^2+z^2\right), 2\left(xy+wz\right), 2\left(xz-wy\right) \right) \\&#xD;&#xA;\mathbf{y}' = Q\mathbf{y}Q^{-1} = \left(2 \left(xy-wz\right), 1 - 2\left(x^2+z^2\right), 2\left(wx+yz\right) \right)  \\&#xD;&#xA;\mathbf{z}' = Q\mathbf{z}Q^{-1} = \left(2 \left(wy+xz\right), 2\left(yz-wx\right), 1 - 2\left(x^2+y^2\right) \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Sticking to the math convention of column vectors, then we shove the three equations into the first three columns and to add a translation by $\left(t_x,t_y,t_z\right)$ we shove that into the last column giving:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;{&#xD;&#xA;\left( \begin{array}{ccc}&#xD;&#xA;1 - 2 \left(y^2+z^2\right) &amp; 2\left(xy-wz\right)       &amp;  2\left(xz+wy\right)  &amp; t_x\\&#xD;&#xA;2 \left(xy+wz\right)       &amp; 1 - 2\left(x^2+z^2\right) &amp;  2\left(wx-yz\right)  &amp; t_y \\&#xD;&#xA;2 \left(wy-xz\right)       &amp; 2\left(yz+wx\right)       &amp; 1 - 2\left(x^2+y^2\right) &amp; t_z \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{array} \right)&#xD;&#xA;}&#xD;&#xA;$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14181" PostHistoryTypeId="2" PostId="5248" RevisionGUID="04cff80f-1bfe-49b1-9c40-0d1ddefb2737" CreationDate="2017-06-16T18:01:59.833" UserId="6092" Text="So the way I went by not showing the window seems the way to go, and the error about `GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT`apparently wasn't related to this at all and is gone." ContentLicense="CC BY-SA 3.0" />
  <row Id="14182" PostHistoryTypeId="2" PostId="5249" RevisionGUID="7432b511-955c-4465-b6ae-fb705c923e09" CreationDate="2017-06-17T08:11:39.670" UserId="1952" Text="&quot;decent&quot; is quite subjective and if you are restricting the capture to certain types of surfaces and controlled lighting conditions. For example normals and other [SVBRDF][1] parameters for shiny metallic surfaces are very difficult to capture compared to non-metallic, matte and bright surfaces without texture.&#xD;&#xA;&#xD;&#xA;There are tools proposed in comments ([CrazyBump][2], [AwesomeBump][3]) that try to do what you ask for and may generate normal maps sufficient to your requirements, but you could argue how &quot;decent&quot; the results are and how robust these tools are in capturing different types of surfaces. I don't know about the algorithms these tools use, but I believe they use more of an &quot;artistic&quot; than robust/accurate methods in generating the results.&#xD;&#xA;&#xD;&#xA;There is some recent work to estimate normal map and other SVBRDF parameters using [two images][4] or from a [single image][5] (using neural networks), which is probably your best bet. However these algorithms assume a level of repeating pattern in the input images, but this might be ok for you since you mention rock wall as an example. There are likely other constraints as well such as requiring the captured surface to be dielectric hard surface material.&#xD;&#xA;&#xD;&#xA;For more robust SVBRDF capturing you can check paper on [frequency domain capture][6], but this is more complex capturing setup and far from a single image capture.&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;To my knowledge there's no known generic algorithm to accurately extract SVBRDF parameters from a single image of a non-repeating surface because of the fundamental issue that a single image can't unambiguously represent SVBRDF parameters. E.g. two different normal &amp; albedo combinations of a [Lambertian surface][8] may result in same pixel color in a single image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function&#xD;&#xA;  [2]: http://www.crazybump.com/&#xD;&#xA;  [3]: https://github.com/kmkolasinski/AwesomeBump&#xD;&#xA;  [4]: https://mediatech.aalto.fi/publications/graphics/TwoShotSVBRDF/&#xD;&#xA;  [5]: https://mediatech.aalto.fi/publications/graphics/NeuralSVBRDF/&#xD;&#xA;  [6]: https://mediatech.aalto.fi/publications/graphics/FourierSVBRDF/&#xD;&#xA;  [7]: https://i.stack.imgur.com/Z80R5.png&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Lambertian_reflectance" ContentLicense="CC BY-SA 3.0" />
  <row Id="14188" PostHistoryTypeId="2" PostId="5251" RevisionGUID="50059742-0bb2-4ff9-9b7b-bd735c4cbc93" CreationDate="2017-06-17T13:40:25.280" UserId="6806" Text="I'am studying PBR and the book introduce the potential equation.&#xD;&#xA;They said the potential equation can describe shooting algorithms better, and&#xD;&#xA;$W(x, \theta)$ describes the fraction of the radiance $L(x, \theta)$&#xD;&#xA;&#xD;&#xA;But I could not understand the concept. &#xD;&#xA;&#xD;&#xA;Is just $W(x, \theta)$ a fraction such as $\frac{1}{3}$(I know the original equation is quite complicate, integral) to reduce the radiance $L$ which is derived from a light source? (because the L would be diminished if it collides with objects)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14189" PostHistoryTypeId="1" PostId="5251" RevisionGUID="50059742-0bb2-4ff9-9b7b-bd735c4cbc93" CreationDate="2017-06-17T13:40:25.280" UserId="6806" Text="What is the potential equation in PBR?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14190" PostHistoryTypeId="3" PostId="5251" RevisionGUID="50059742-0bb2-4ff9-9b7b-bd735c4cbc93" CreationDate="2017-06-17T13:40:25.280" UserId="6806" Text="|physically-based|pbr|photo-realistic|realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14191" PostHistoryTypeId="10" PostId="1467" RevisionGUID="a7505a57-c9dc-490e-a979-dd47ad690bf2" CreationDate="2017-06-17T19:18:11.903" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="14193" PostHistoryTypeId="2" PostId="5252" RevisionGUID="71d5e9df-7f8e-4093-9baf-aca38effa10f" CreationDate="2017-06-18T11:55:14.240" UserId="250" Text="Let $M=\Biggl[\begin{matrix} Rx &amp; Ux &amp; Fx\\ Ry &amp; Uy &amp; Fy\\ Ry &amp; Uy &amp; Fy\\ \end{matrix}\Biggl], V = \Biggl(\begin{matrix}Vx\\ Vy\\ Vz \end{matrix}\Biggl)$&#xD;&#xA;&#xD;&#xA;The correct multiplication is:&#xD;&#xA;$V' = M V$ or $V'^T = V^TM^T$&#xD;&#xA;&#xD;&#xA;An easy way to check this is to think about what is a rotation matrix. The matrix &#xD;&#xA;$$RotationZ = \Biggl[\begin{matrix} cos(\theta) &amp; -sin(\theta) &amp; 0\\ sin(\theta) &amp; cos(\theta) &amp; 0\\ 0 &amp; 0 &amp; 1\\ \end{matrix}\Biggl]$$ rotates a vector $V$ by $\theta^{\circ}$ around z axis or, to think in another way, represents $V$ in a basis that is rotated $\theta^{\circ}$ from the standard basis. If you compute the axes of this new rotated basis you'll see that the new $R, U, F$ of this rotated matrix are the columns of $RotationZ$ matrix.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14194" PostHistoryTypeId="2" PostId="5253" RevisionGUID="cb49d6b1-d32c-4d6b-8de8-91d31be4cc11" CreationDate="2017-06-18T15:19:31.403" UserId="5099" Text="I am trying to run the following program on ubuntu 15.04. However on typing &quot;g++ pgm1.cpp -lglut&quot;&#xD;&#xA;I am getting following errors&#xD;&#xA;&#xD;&#xA;**/usr/bin/ld: /tmp/cc9aXqhZ.o: undefined reference to symbol 'glClear'**&#xD;&#xA;&#xD;&#xA;**/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1: error adding symbols: DSO missing from command line**&#xD;&#xA;    &#xD;&#xA;Though I am familiar with C programming in Codeblocks and DevC++, this is the first time I am working on Ubuntu and OpenGL. I installed ubuntu and files related to OpenGL based on information available on the net. The sample program too is from the internet. I would request help in getting the program run. Thanks.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    # include &quot;GL/freeglut.h&quot;&#xD;&#xA;    # include &quot;GL/gl.h&quot;&#xD;&#xA;    # include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;    void init(void)&#xD;&#xA;    {&#xD;&#xA;    glClearColor(0.0f,0.0f,1.0f,1.0f);&#xD;&#xA;    }&#xD;&#xA;    void display (void) &#xD;&#xA;    {&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glFlush();&#xD;&#xA;    }&#xD;&#xA;    int main (int argc, char** argv)&#xD;&#xA;    {&#xD;&#xA;    glutInit(&amp;argc,argv);&#xD;&#xA;    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);&#xD;&#xA;    glutCreateWindow(&quot;A Blank Window&quot;);&#xD;&#xA;    init();&#xD;&#xA;    glutDisplayFunc(display);&#xD;&#xA;    glutMainLoop();&#xD;&#xA;    return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14195" PostHistoryTypeId="1" PostId="5253" RevisionGUID="cb49d6b1-d32c-4d6b-8de8-91d31be4cc11" CreationDate="2017-06-18T15:19:31.403" UserId="5099" Text="Errors on Compiling my first program on OpenGL on Ubuntu" ContentLicense="CC BY-SA 3.0" />
  <row Id="14196" PostHistoryTypeId="3" PostId="5253" RevisionGUID="cb49d6b1-d32c-4d6b-8de8-91d31be4cc11" CreationDate="2017-06-18T15:19:31.403" UserId="5099" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14197" PostHistoryTypeId="5" PostId="5252" RevisionGUID="d94e2f40-241c-4edc-9ab2-6e082cdda422" CreationDate="2017-06-18T18:14:20.567" UserId="250" Comment="added more information to the explanation." Text="**TL;DR**&#xD;&#xA;&#xD;&#xA;Let $M=\Biggl[\begin{matrix} Rx &amp; Ux &amp; Fx\\ Ry &amp; Uy &amp; Fy\\ Ry &amp; Uy &amp; Fy\\ \end{matrix}\Biggl], V = \Biggl(\begin{matrix}Vx\\ Vy\\ Vz \end{matrix}\Biggl)$&#xD;&#xA;&#xD;&#xA;The correct multiplication is:&#xD;&#xA;$V' = M V$ or $V'^T = V^TM^T$&#xD;&#xA;&#xD;&#xA;Now to the proper explanation.&#xD;&#xA;Whenever we define a coordinate in $R^{3}$ space that coordinate must be in respect to a basis. When one state that an arbitrary point in $R^{3}$ is $(x, y, z)$ it is implicit that this is in respect to the standard basis. Let's call $\vec{r}, \vec{u}, \vec{f}$ the axes that define an arbitrary basic $B$ in $R^{3}$. An arbitrary point $P$ can be defined as &#xD;&#xA;$$P = x * \vec{r} + y * \vec{u} + z * \vec{f}$$&#xD;&#xA;&#xD;&#xA;Expanding we have:&#xD;&#xA;&#xD;&#xA;$$P_x = x * \vec{r_x} + y * \vec{u_x} + z * \vec{f_x}$$&#xD;&#xA;$$P_y = x * \vec{r_y} + y * \vec{u_y} + z * \vec{f_y}$$&#xD;&#xA;$$P_z = x * \vec{r_z} + y * \vec{u_z} + z * \vec{f_z}$$&#xD;&#xA;&#xD;&#xA;In matrix form we have that:&#xD;&#xA;$$\Biggl(\begin{matrix}P_x\\ &#xD;&#xA;  P_y\\ &#xD;&#xA;  P_z\\ &#xD;&#xA;\end{matrix}\Biggl)=\Biggl[\begin{matrix} &#xD;&#xA;  \vec{r_x} &amp; \vec{u_x} &amp; \vec{f_x}\\ &#xD;&#xA;  \vec{r_y} &amp; \vec{u_y} &amp; \vec{f_y}\\ &#xD;&#xA;  \vec{r_z} &amp; \vec{u_z} &amp; \vec{f_z}\\ &#xD;&#xA;\end{matrix}\Biggl]\Biggl(\begin{matrix} &#xD;&#xA;  x\\ &#xD;&#xA;  y\\ &#xD;&#xA;  z\\ &#xD;&#xA;\end{matrix}\Biggl)$$&#xD;&#xA;&#xD;&#xA;Another easy way to check this is to think about what is a rotation matrix. The matrix &#xD;&#xA;$$R_z = \Biggl[\begin{matrix} cos(\theta) &amp; -sin(\theta) &amp; 0\\ sin(\theta) &amp; cos(\theta) &amp; 0\\ 0 &amp; 0 &amp; 1\\ \end{matrix}\Biggl]$$ rotates a vector $\vec{v}$ by $\theta^{\circ}$ around $z$ axis or, to think in another way, represents $\vec{v}$ in a basis that is rotated $\theta^{\circ}$ from the standard basis. If you compute the axes of this new rotated basis you'll see that the new $\vec{r}, \vec{u}, \vec{f}$ of this rotated matrix are the columns of $R_z$ matrix.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14198" PostHistoryTypeId="2" PostId="5254" RevisionGUID="c21950ff-2763-4881-a011-acf1aa1c979d" CreationDate="2017-06-19T02:01:58.190" UserId="6832" Text="The following four SVG paths render the same (using the default [`fill-rule=&quot;nonzero&quot;`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule)):&#xD;&#xA;&#xD;&#xA;    &lt;path id=&quot;cwOccwI&quot; d=&quot;M0,0 10,0 10,10zM5,2 8,5 8,2z&quot; transform=&quot;translate( 0,0)&quot;/&gt;&#xD;&#xA;    &lt;path id=&quot;ccwOcwI&quot; d=&quot;M0,0 10,10 10,0zM5,2 8,2 8,5z&quot; transform=&quot;translate(15,0)&quot;/&gt;&#xD;&#xA;    &lt;path id=&quot;ccwIcwO&quot; d=&quot;M5,2 8,5 8,2zM0,0 10,0 10,10z&quot; transform=&quot;translate(30,0)&quot;/&gt;&#xD;&#xA;    &lt;path id=&quot;cwIccwO&quot; d=&quot;M5,2 8,2 8,5zM0,0 10,10 10,0z&quot; transform=&quot;translate(45,0)&quot;/&gt;&#xD;&#xA;&#xD;&#xA;[![Four triangles with triangular holes inside][1]][1]&#xD;&#xA;&#xD;&#xA;As hinted at by the IDs, these are combinations of clockwise (`cw`) and counter-clockwise (`ccw`) orientations for the outer (`O`) and inner (`I`) subpaths, varying the order the subpaths are added.&#xD;&#xA;&#xD;&#xA;I'm converting SVG paths to [GeoJSON](http://geojson.org/). It requires a single 'positive' subpath that is oriented counter-clockwise, and any/all ['hole' subpaths to be oriented clockwise](https://tools.ietf.org/html/rfc7946#section-3.1.6).&#xD;&#xA;&#xD;&#xA;Given an SVG path with subpaths (which I can assume/guarantee will not overlap), how can I determine which subpath(s) are 'positive' paths, and which are 'holes'? As shown above, I cannot rely on the orientation of the points within the path, and I cannot rely on the ordering of sub-paths.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4yENe.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14199" PostHistoryTypeId="1" PostId="5254" RevisionGUID="c21950ff-2763-4881-a011-acf1aa1c979d" CreationDate="2017-06-19T02:01:58.190" UserId="6832" Text="Determining the 'outer' subpath in a compound SVG path" ContentLicense="CC BY-SA 3.0" />
  <row Id="14200" PostHistoryTypeId="3" PostId="5254" RevisionGUID="c21950ff-2763-4881-a011-acf1aa1c979d" CreationDate="2017-06-19T02:01:58.190" UserId="6832" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14201" PostHistoryTypeId="50" PostId="4370" RevisionGUID="1b0878bd-0f8c-450e-b3b9-62ff2c7896f2" CreationDate="2017-06-19T06:12:56.243" UserId="-1" />
  <row Id="14202" PostHistoryTypeId="2" PostId="5255" RevisionGUID="a1c121f4-b275-4032-9036-481b512dd7a8" CreationDate="2017-06-19T06:49:26.527" UserId="182" Text="You need to link with the OpenGL library. Try adding `-lgl` to the compilation command." ContentLicense="CC BY-SA 3.0" />
  <row Id="14204" PostHistoryTypeId="2" PostId="5256" RevisionGUID="f1c39d5c-e060-4360-9c9e-e720fca96069" CreationDate="2017-06-19T12:58:32.157" UserId="6092" Text="Only a few games have resizable windows when running in full screen mode. All others have a finite fixed set of allowed resolutions. But why? I see some reasons, but none of them seems to be that important to me that would justify such a user-unfriendly feature." ContentLicense="CC BY-SA 3.0" />
  <row Id="14205" PostHistoryTypeId="1" PostId="5256" RevisionGUID="f1c39d5c-e060-4360-9c9e-e720fca96069" CreationDate="2017-06-19T12:58:32.157" UserId="6092" Text="Why do games only allow certain resolutions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14206" PostHistoryTypeId="3" PostId="5256" RevisionGUID="f1c39d5c-e060-4360-9c9e-e720fca96069" CreationDate="2017-06-19T12:58:32.157" UserId="6092" Text="|rendering|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14207" PostHistoryTypeId="5" PostId="5256" RevisionGUID="73cf77c7-4939-42ea-a25b-a9d3552a9bcd" CreationDate="2017-06-19T13:47:25.987" UserId="6092" Comment="Added example" Text="Only a few games have resizable windows when running in full screen mode. All others have a finite fixed set of allowed resolutions. But why? I see some reasons, but none of them seems to be that important to me that would justify such a user-unfriendly feature.&#xD;&#xA;&#xD;&#xA;**Example**&#xD;&#xA;&#xD;&#xA;Let's use Dark Souls II, because it's the first I can think of. The allowed resolutions are:&#xD;&#xA;&#xD;&#xA;    800x450&#xD;&#xA;    1024x576&#xD;&#xA;    1152x648&#xD;&#xA;    1280x720&#xD;&#xA;    1440x810&#xD;&#xA;    1600x900&#xD;&#xA;    1680x945&#xD;&#xA;    1920x1080&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the reason to not allow the resolutions `800x451, 800x452, ..., 801x450, 801x451, ...`? What it I think can't be:&#xD;&#xA;&#xD;&#xA; - **The UI.** If we keep minimum and maximum window sizes as limitations, the only issue I can see here is with settings with a weird aspect ratio (1920x450, 800x1080). Otherwise, there shouldn't be any problems with free scaling between the resolutions.&#xD;&#xA; - **Camera, Viewport.** Same as above." ContentLicense="CC BY-SA 3.0" />
  <row Id="14208" PostHistoryTypeId="2" PostId="5257" RevisionGUID="1ea43e78-4cd3-4fd8-b938-ad77602afd71" CreationDate="2017-06-19T14:01:50.707" UserId="2041" Text="If you can assume the subpaths are non-intersecting (and non-self-intersecting), and that the fill rule is always the nonzero rule, the easiest way is probably to pick the first point on the first subpath, and do [a standard point-in-polygon test](https://en.wikipedia.org/wiki/Point_in_polygon) with the polygons defined by each other subpath. If the point is not inside any other subpath, then this subpath is the outermost one. If the point is inside one other subpath, that one must be the outermost one. If the point is inside more than one other subpath, take the set of subpaths it is inside and repeat the test.&#xD;&#xA;&#xD;&#xA;Obviously doing it this way requires that there is only one outermost subpath. It's entirely possible in SVG to have multiple disjoint subpaths in one path, and you didn't say whether this is possible in your source data. If it is possible, then you'll have to test every subpath to find out which other subpath(s) it is inside. Each time you run the point-in-polygon test, you find the subpath you're considering is either an outermost one, or you'll find out which subpath it is inside. If it's inside another path, you don't need to consider it in any further tests. At the end, you have a list of outermost subpaths, each of which has a list of all the subpaths it encloses. You can turn each outermost subpath into a separate GeoJSON polygon." ContentLicense="CC BY-SA 3.0" />
  <row Id="14209" PostHistoryTypeId="2" PostId="5258" RevisionGUID="fd8987b1-7178-41a5-9957-c10c27909ded" CreationDate="2017-06-19T15:43:21.463" UserId="6854" Text="I need a 3D triangular sphere mesh with uniformly sampled vertices, say $V$, with a predefined adjacency. Is there a specific way to achieve that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14210" PostHistoryTypeId="1" PostId="5258" RevisionGUID="fd8987b1-7178-41a5-9957-c10c27909ded" CreationDate="2017-06-19T15:43:21.463" UserId="6854" Text="3D sphere mesh with a predefined number of vertices and a given adjacency matrix of vertices" ContentLicense="CC BY-SA 3.0" />
  <row Id="14211" PostHistoryTypeId="3" PostId="5258" RevisionGUID="fd8987b1-7178-41a5-9957-c10c27909ded" CreationDate="2017-06-19T15:43:21.463" UserId="6854" Text="|3d|computational-geometry|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14216" PostHistoryTypeId="2" PostId="5260" RevisionGUID="3e7973c7-9a16-424f-b351-56c0852b82c1" CreationDate="2017-06-19T15:58:53.210" UserId="6855" Text="Just to comment on the 0.16*Specular^2 term that was mentioned in the comments by Karim:&#xD;&#xA;&#xD;&#xA;Frostbite only **remapps** the specularity for their internal purpose so that they can pack gemstones specularity into the 8bit channel. They just loose some precision in favor of more variation. The specularity value is the original one when rendering.&#xD;&#xA;&#xD;&#xA;Check the disney BRDF viewer which is a awesome start for PBR, since it contains the whole BRDF from Disney.&#xD;&#xA;https://www.disneyanimation.com/technology/brdf.html&#xD;&#xA;&#xD;&#xA;Also, if you are looking at a better fresnel function than&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH) {&#xD;&#xA;    // Fresnel Schlick&#xD;&#xA;    return Specular + (1-Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Use this instead since it takes roughness/gloss into account:&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH, in float gloss) &#xD;&#xA;    {&#xD;&#xA;        return Specular + (max(vec3(gloss), Specular) - Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14218" PostHistoryTypeId="2" PostId="5261" RevisionGUID="a6445c8f-9a3d-4af0-a20b-b373f50b540f" CreationDate="2017-06-19T22:14:25.480" UserId="3332" Text="  Note that in your Dark Souls example, all the resolutions listed are the exact same aspect ratio.  So the question is, why doesn't it support arbitrary aspect ratios?  &#xD;&#xA;&#xD;&#xA;The answer is that it costs time and effort to support arbitrary aspect ratios, and if that money spent doesn't translate to increased profit, then it doesn't make sense to do.&#xD;&#xA;&#xD;&#xA;* This [answer][1] covers the 2d layout issues, which includes extra time and effort to create a versatile layout that can be resized so that elements do not overlap, stretch, or pixelate in an undesired manner, and that the overal UI maintains the best user experience.&#xD;&#xA;&#xD;&#xA;* The developer would have to ensure that the window doesn't get too large or too small.  Does it make the game any better if the user can drag the window size to be smaller than 800 x 450?  probably not.&#xD;&#xA;* you have to define the behavior of the camera when the aspect ratio changes. &#xD;&#xA;&#xD;&#xA;For example, take the following scene:&#xD;&#xA;&#xD;&#xA;[![Original Aspect Ratio][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we allow the user to change the horizontal size, we can decide to &quot;zoom out&quot; horizontally so that the same area still shows up horzontally but now we can see more vertically.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Or, instead, we can keep the same zoom level but just clip the viewing area more:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;These decisions take time and effort to design, code and test, but management has to decide if it actually makes the user experience better enough to be worth the time.  Apparently, most games have decided its not worth the effort.  I'd even go further and suggest that allowing users to screw up the best layout of the game is a bad feature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/a/125316/26734&#xD;&#xA;  [2]: https://i.stack.imgur.com/5YUYg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/998Of.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/cHGce.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14219" PostHistoryTypeId="5" PostId="5261" RevisionGUID="311d1f8d-e2d1-459d-b8b7-9dd2e0698112" CreationDate="2017-06-19T22:24:19.707" UserId="3332" Comment="added 236 characters in body" Text="  Note that in your Dark Souls example, all the resolutions listed are the exact same aspect ratio.  So the question is, why doesn't it support arbitrary aspect ratios?  &#xD;&#xA;&#xD;&#xA;The answer is that it costs time and effort to support arbitrary aspect ratios, and if that money spent doesn't translate to increased profit, then it doesn't make sense to do.&#xD;&#xA;&#xD;&#xA;* This [answer][1] covers the 2d layout issues, which includes extra time and effort to create a versatile layout that can be resized so that elements do not overlap, stretch, or pixelate in an undesired manner, and that the overal UI maintains the best user experience.&#xD;&#xA;&#xD;&#xA;* The developer would have to ensure that the window doesn't get too large or too small.  Does it make the game any better if the user can drag the window size to be smaller than 800 x 450?  probably not.&#xD;&#xA;* you have to define the behavior of the camera when the aspect ratio changes. &#xD;&#xA;&#xD;&#xA;For example, take the following scene:&#xD;&#xA;&#xD;&#xA;[![Original Aspect Ratio][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we allow the user to change the horizontal size, we can decide to &quot;zoom out&quot; horizontally so that the same area still shows up horzontally but now we can see more vertically.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Or, instead, we can keep the same zoom level but just clip the viewing area more:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Note, that if you don't specifically handle the changing aspect ratio, the default graphics pipeline behavior will be to stretch the image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These decisions take time and effort to design, code and test, but management has to decide if it actually makes the user experience better enough to be worth the time.  Apparently, most games have decided its not worth the effort.  I'd even go further and suggest that allowing users to screw up the best layout of the game is a bad feature.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://gamedev.stackexchange.com/a/125316/26734&#xD;&#xA;  [2]: https://i.stack.imgur.com/5YUYg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/998Of.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/cHGce.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/jJbqG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14224" PostHistoryTypeId="2" PostId="5263" RevisionGUID="5fddc137-ff56-4662-9b28-1dd9a24871da" CreationDate="2017-06-20T07:27:43.027" UserId="6834" Text="I want to know what information I can use to extract edge flow/topology flow information from a mesh!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14225" PostHistoryTypeId="1" PostId="5263" RevisionGUID="5fddc137-ff56-4662-9b28-1dd9a24871da" CreationDate="2017-06-20T07:27:43.027" UserId="6834" Text="How do you get edge flow information from mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="14226" PostHistoryTypeId="3" PostId="5263" RevisionGUID="5fddc137-ff56-4662-9b28-1dd9a24871da" CreationDate="2017-06-20T07:27:43.027" UserId="6834" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14227" PostHistoryTypeId="5" PostId="5260" RevisionGUID="b86089ca-811f-4097-a6f7-a10cd7517f74" CreationDate="2017-06-20T09:18:58.877" UserId="209" Comment="Fixed spelling" Text="Just to comment on the 0.16*Specular^2 term that was mentioned in the comments by Karim:&#xD;&#xA;&#xD;&#xA;Frostbite only **remaps** the specularity for their internal purpose so that they can pack gemstones specularity into the 8bit channel. They just lose some precision in favor of more variation. The specularity value is the original one when rendering.&#xD;&#xA;&#xD;&#xA;Check the Disney BRDF viewer which is a awesome start for PBR, since it contains the whole BRDF from Disney.&#xD;&#xA;https://www.disneyanimation.com/technology/brdf.html&#xD;&#xA;&#xD;&#xA;Also, if you are looking at a better Fresnel function than&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH) {&#xD;&#xA;    // Fresnel Schlick&#xD;&#xA;    return Specular + (1-Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Use this instead since it takes roughness/gloss into account:&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH, in float gloss) &#xD;&#xA;    {&#xD;&#xA;        return Specular + (max(vec3(gloss), Specular) - Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14228" PostHistoryTypeId="10" PostId="5263" RevisionGUID="2db6f183-84b7-4614-860d-78faaf397d9e" CreationDate="2017-06-20T11:36:42.880" UserId="231" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="14230" PostHistoryTypeId="2" PostId="5264" RevisionGUID="eeb55ce1-8c2a-45b5-8af7-cd8595638b56" CreationDate="2017-06-20T12:12:02.687" UserId="137" Text="doing the calculation to decide whether a point is on one side of a plane or the other is very simple (a single dot product). Doing that 3 times and having a special case when they don't match to split the triangle is pretty fast. It's also a parallel problem. The hardest part is reserving the space for the output.&#xD;&#xA;&#xD;&#xA;Preparing the data to start computing this on the gpu is already enough overhead that it's not worth doing it on the gpu unless the mesh is very big or you are splitting it multiple times (due to the plane moving for example). Or the data is already in good enough condition to be sent over to the gpu directly through DMA without the cpu needing to touch it at all." ContentLicense="CC BY-SA 3.0" />
  <row Id="14231" PostHistoryTypeId="2" PostId="5265" RevisionGUID="0870b60f-b381-4c53-b8fe-d720538e267b" CreationDate="2017-06-20T13:56:18.387" UserId="6788" Text="I'm currently researching how to compute geometric properties of architectural shapes based on their 3D meshes, and am stuck for some time on the **area** and **perimeter** calculations.&#xD;&#xA;&#xD;&#xA;First, the **area**: assuming that I have the proportions set right, if, for example, I have a wall with 3 meters of height, 7.8 meters of width and 0.290 meters of thickness I'm interested in the result of height * width `(3 * 7.8)`, which would give me 23.4 meters in this case. My idea is to obtain a 2D projection of this 3D mesh onto a plane parallel to it, calculate the surface area of each triangle and sum them up, what I believe would give me the mesh area independent of it's shape, assuming that it is planar. The problem is, how exactly can I obtain this triangulated projection? I believe that if the mesh is aligned to the world axis it would simply be a matter of ignoring one of them, but unfortunatelly this is an assumption that can't be made, as there will be meshes rotated in relation to one or more axis, and just ignoring an axis would distort the projection. Aditionaly, is there any method that would work even in the case of a non-planar mesh?&#xD;&#xA;&#xD;&#xA;Now, for the **perimeter**: having the area problem solved, is there any robust algorithm that would give me the contours of this 2D triangulated projection, and that would work with both convex and concave meshes? I believe that with this it would be a matter of simply adding up all the edges of the contour." ContentLicense="CC BY-SA 3.0" />
  <row Id="14232" PostHistoryTypeId="1" PostId="5265" RevisionGUID="0870b60f-b381-4c53-b8fe-d720538e267b" CreationDate="2017-06-20T13:56:18.387" UserId="6788" Text="Compute area (not surface area) and perimeter of a mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="14233" PostHistoryTypeId="3" PostId="5265" RevisionGUID="0870b60f-b381-4c53-b8fe-d720538e267b" CreationDate="2017-06-20T13:56:18.387" UserId="6788" Text="|computational-geometry|mesh|projections|area|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14234" PostHistoryTypeId="2" PostId="5266" RevisionGUID="59aa1250-058f-40e2-94ab-12390240912a" CreationDate="2017-06-20T14:53:09.700" UserId="137" Text="There's a small problem with your method. When the mesh self shadows then part of the model will be counted twice. &#xD;&#xA;&#xD;&#xA;You can get the projection of a mesh onto an arbitrary plane by finding the rotation from the normal of the plane to the Z axis and rotating the mesh with it. After that you discard the Z component.&#xD;&#xA;&#xD;&#xA;However it's more straightfoward to simply draw the mesh with appropriate projection and counting how many pixels it takes up.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;An edge can be part of the perimeter only when both the triangles that make it are projected onto the same side of the projected line. &#xD;&#xA;&#xD;&#xA;You can use that to walk around the perimeter. Start with the negative x most point after the rotation and follow the lines. When another potential perimeter line crosses the current line you start following that one instead.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14235" PostHistoryTypeId="5" PostId="5252" RevisionGUID="dd7f60e3-813c-4f1e-8b39-d09eb9d57e47" CreationDate="2017-06-20T15:53:08.717" UserId="250" Comment="fixed the matrix M to add missing z" Text="**TL;DR**&#xD;&#xA;&#xD;&#xA;Let $M=\Biggl[\begin{matrix} Rx &amp; Ux &amp; Fx\\ Ry &amp; Uy &amp; Fy\\ Rz &amp; Uz &amp; Fz\\ \end{matrix}\Biggl], V = \Biggl(\begin{matrix}Vx\\ Vy\\ Vz \end{matrix}\Biggl)$&#xD;&#xA;&#xD;&#xA;The correct multiplication is:&#xD;&#xA;$V' = M V$ or $V'^T = V^TM^T$&#xD;&#xA;&#xD;&#xA;Now to the proper explanation:&#xD;&#xA;&#xD;&#xA;Whenever we define a coordinate in $R^{3}$ space that coordinate must be in respect to a basis. When one state that an arbitrary point in $R^{3}$ is $(x, y, z)$ it is implicit that this is in respect to the standard basis. Let's call $\vec{r}, \vec{u}, \vec{f}$ the axes that define an arbitrary basic $B$ in $R^{3}$. An arbitrary point $P$ can be defined as &#xD;&#xA;$$P = x * \vec{r} + y * \vec{u} + z * \vec{f}$$&#xD;&#xA;&#xD;&#xA;Expanding we have:&#xD;&#xA;&#xD;&#xA;$$P_x = x * \vec{r_x} + y * \vec{u_x} + z * \vec{f_x}$$&#xD;&#xA;$$P_y = x * \vec{r_y} + y * \vec{u_y} + z * \vec{f_y}$$&#xD;&#xA;$$P_z = x * \vec{r_z} + y * \vec{u_z} + z * \vec{f_z}$$&#xD;&#xA;&#xD;&#xA;In matrix form we can write that as:&#xD;&#xA;$$\Biggl(\begin{matrix}P_x\\ &#xD;&#xA;  P_y\\ &#xD;&#xA;  P_z\\ &#xD;&#xA;\end{matrix}\Biggl)=\Biggl[\begin{matrix} &#xD;&#xA;  \vec{r_x} &amp; \vec{u_x} &amp; \vec{f_x}\\ &#xD;&#xA;  \vec{r_y} &amp; \vec{u_y} &amp; \vec{f_y}\\ &#xD;&#xA;  \vec{r_z} &amp; \vec{u_z} &amp; \vec{f_z}\\ &#xD;&#xA;\end{matrix}\Biggl]\Biggl(\begin{matrix} &#xD;&#xA;  x\\ &#xD;&#xA;  y\\ &#xD;&#xA;  z\\ &#xD;&#xA;\end{matrix}\Biggl)$$&#xD;&#xA;&#xD;&#xA;Another easy way to check this is to think about what is a rotation matrix. The matrix &#xD;&#xA;$$R_z = \Biggl[\begin{matrix} cos(\theta) &amp; -sin(\theta) &amp; 0\\ sin(\theta) &amp; cos(\theta) &amp; 0\\ 0 &amp; 0 &amp; 1\\ \end{matrix}\Biggl]$$ rotates a vector $\vec{v}$ by $\theta^{\circ}$ around $z$ axis or, to think in another way, represents $\vec{v}$ in a basis that is rotated $\theta^{\circ}$ from the standard basis. If you compute the axes of this new rotated basis you'll see that the new $\vec{r}, \vec{u}, \vec{f}$ of this rotated matrix are the columns of $R_z$ matrix.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14236" PostHistoryTypeId="5" PostId="5263" RevisionGUID="65f2b5a5-cabe-4f1f-81e9-f411becdfbb4" CreationDate="2017-06-21T09:00:02.673" UserId="6834" Comment="added 385 characters in body" Text="I want to know what information I can use to extract edge flow/topology flow information from a mesh!&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;I have two identical meshes, one has good topology one has bad topology, what information can i extract from the good topology mesh that represents the topology (face info? edges info? vertex angles?) i want info to tell me about the topology (what direction it is flowing etc)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4pGat.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14237" PostHistoryTypeId="2" PostId="5267" RevisionGUID="f9306df2-e894-4967-9f8f-c10f8267e95f" CreationDate="2017-06-21T10:14:47.927" UserId="6862" Text="I'm currently learning mathemeticals concepts of distribution and the way to use them in a ray tracer with the book &quot;Physically Based Rendering&quot;&#xD;&#xA;&#xD;&#xA;Let's start by uniformly sampling an hemisphere:&#xD;&#xA;&#xD;&#xA;As you probably know, a way to generate the uniformly distributed direction is to use the inversion method.&#xD;&#xA;&#xD;&#xA;Let note by &quot;p&quot; our uniform probability density functions:&#xD;&#xA;&#xD;&#xA;p(w) = 1/(2PI) and so p(theta,phi) = sin(theta)p(w).&#xD;&#xA;&#xD;&#xA;Then you compute p(theta), p(phi | theta), you integrate your cumulative distribution function and you inverse the function.&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;**What does p(theta, phi) really means ?**&#xD;&#xA;&#xD;&#xA;**What is the transformation between p(w) and p(theta, phi) ?**&#xD;&#xA;&#xD;&#xA;**In the book, to find p(theta,phi) they state that p(theta,phi)d(theta)d(phi) = p(w)d(w), but why ?**&#xD;&#xA;&#xD;&#xA;I know that for p(w), our random variable is a given {w} (a direction), so the function represents a relative probability for this direction (so a solid angle, because the relative term implies a direction and a delta area around this direction).&#xD;&#xA;&#xD;&#xA;But for p(theta, phi), our random variable is now the couple {theta,phi}. To what extent is it different from a direction ?&#xD;&#xA;&#xD;&#xA;Thanks in advance for your time and your answers :)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14238" PostHistoryTypeId="1" PostId="5267" RevisionGUID="f9306df2-e894-4967-9f8f-c10f8267e95f" CreationDate="2017-06-21T10:14:47.927" UserId="6862" Text="2D sampling with ultidimensional distribution" ContentLicense="CC BY-SA 3.0" />
  <row Id="14239" PostHistoryTypeId="3" PostId="5267" RevisionGUID="f9306df2-e894-4967-9f8f-c10f8267e95f" CreationDate="2017-06-21T10:14:47.927" UserId="6862" Text="|raytracing|mathematics|sampling|distribution|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14240" PostHistoryTypeId="4" PostId="5267" RevisionGUID="3bde8433-f2aa-4a7f-bebe-e1d7f43ffe61" CreationDate="2017-06-21T10:23:21.517" UserId="6862" Comment="edited title" Text="2D sampling with multidimensional transformations" ContentLicense="CC BY-SA 3.0" />
  <row Id="14241" PostHistoryTypeId="5" PostId="5267" RevisionGUID="e294375e-17d3-4a42-a6fc-ecd6d45223fa" CreationDate="2017-06-21T12:36:17.643" UserId="2041" Comment="Write up the maths in MathJax." Text="I'm currently learning mathemeticals concepts of distribution and the way to use them in a ray tracer with the book &quot;Physically Based Rendering&quot;&#xD;&#xA;&#xD;&#xA;Let's start by uniformly sampling an hemisphere:&#xD;&#xA;&#xD;&#xA;As you probably know, a way to generate the uniformly distributed direction is to use the inversion method.&#xD;&#xA;&#xD;&#xA;Let note by $p$ our uniform probability density functions:&#xD;&#xA;&#xD;&#xA;$p(\omega) = \cfrac{1}{2\pi}$ and so $p(\theta, \phi) = \sin(\theta)p(\omega)$.&#xD;&#xA;&#xD;&#xA;Then you compute $p(\theta)$, $p(\phi | \theta)$, you integrate your cumulative distribution function and you invert the function.&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;**What does $p(\theta, \phi)$ really mean?**&#xD;&#xA;&#xD;&#xA;**What is the transformation between $p(\omega)$ and $p(\theta, \phi)$?**&#xD;&#xA;&#xD;&#xA;**In the book, to find $p(\theta,\phi)$ they state that $p(\theta, \phi) d\theta d\phi = p(\omega)d\omega$, but why?**&#xD;&#xA;&#xD;&#xA;I know that for $p(\omega)$, our random variable is a given $\omega$ (a direction), so the function represents a relative probability for this direction (so a solid angle, because the relative term implies a direction and a delta area around this direction).&#xD;&#xA;&#xD;&#xA;But for $p(\theta, \phi)$, our random variable is now the couple $(\theta,\phi)$. To what extent is it different from a direction ?&#xD;&#xA;&#xD;&#xA;Thanks in advance for your time and your answers :)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14248" PostHistoryTypeId="2" PostId="5269" RevisionGUID="03fc345b-caf9-4b90-9bec-2d344590cb93" CreationDate="2017-06-21T19:17:54.407" UserId="6865" Text="My goal is to create a noise model so that the PSNR of the noisy image compared to the original is some pre-defined constant $\alpha$. This means the mean squared-error will also be a constant.&#xD;&#xA;&#xD;&#xA;My model is as follows:&#xD;&#xA;&#xD;&#xA;The additive noise is a random normally distributed variable with $\mu = 0$ and unknown $\sigma$.&#xD;&#xA;&#xD;&#xA;$K(i,j) = I(i,j) + f(x; 0, \sigma)$&#xD;&#xA;&#xD;&#xA;So, &#xD;&#xA;&#xD;&#xA;$$ MSE = \frac{1}{mn}\sum_{i = 0}^{m - 1}\sum_{j = 0}^{n - 1}\ [K(i,\ j) - I(i,\ j)]^2 = \frac{1}{mn}\sum_{i = 0}^{m - 1}\sum_{j = 0}^{n - 1}\ [\ f(x;\ 0,\  \sigma)]^2$$&#xD;&#xA;&#xD;&#xA;where $$f(x;\ 0,\ \sigma) = \frac{1}{\sqrt{2\pi}\sigma}e^{\frac{-x^2}{2\sigma^2}}$$&#xD;&#xA;i.e. the Gaussian pdf with unknown variance.&#xD;&#xA;&#xD;&#xA;What I'm confused about is how to solve for sigma when the values of the pdf are supposed to be independent samples from the distribution. If I'm understanding correctly, this means that the MSE itself becomes a random variable and cannot be a constant. &#xD;&#xA;&#xD;&#xA;If we were to make it a constant, wouldn't the values of $f(x)$ for each pixel have to already be known for the equation to be solvable? In which case the distribution would need to be already known to randomly sample the distribution to produce the values of $f(x)$...&#xD;&#xA;&#xD;&#xA;Anyhow, if anyone has advice on how to construct noisy images with a pre-defined PSNR, that would be appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="14249" PostHistoryTypeId="1" PostId="5269" RevisionGUID="03fc345b-caf9-4b90-9bec-2d344590cb93" CreationDate="2017-06-21T19:17:54.407" UserId="6865" Text="How to create a noise model with a constant PSNR?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14250" PostHistoryTypeId="3" PostId="5269" RevisionGUID="03fc345b-caf9-4b90-9bec-2d344590cb93" CreationDate="2017-06-21T19:17:54.407" UserId="6865" Text="|noise|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14251" PostHistoryTypeId="5" PostId="5269" RevisionGUID="a34e1cee-b694-4ae3-97ea-0b666882fb94" CreationDate="2017-06-21T23:38:22.057" UserId="231" Comment="Add link and hovertext for acronym" Text="My goal is to create a noise model so that the [PSNR] of the noisy image compared to the original is some pre-defined constant $\alpha$. This means the mean squared-error will also be a constant.&#xD;&#xA;&#xD;&#xA;My model is as follows:&#xD;&#xA;&#xD;&#xA;The additive noise is a random normally distributed variable with $\mu = 0$ and unknown $\sigma$.&#xD;&#xA;&#xD;&#xA;$K(i,j) = I(i,j) + f(x; 0, \sigma)$&#xD;&#xA;&#xD;&#xA;So, &#xD;&#xA;&#xD;&#xA;$$ MSE = \frac{1}{mn}\sum_{i = 0}^{m - 1}\sum_{j = 0}^{n - 1}\ [K(i,\ j) - I(i,\ j)]^2 = \frac{1}{mn}\sum_{i = 0}^{m - 1}\sum_{j = 0}^{n - 1}\ [\ f(x;\ 0,\  \sigma)]^2$$&#xD;&#xA;&#xD;&#xA;where $$f(x;\ 0,\ \sigma) = \frac{1}{\sqrt{2\pi}\sigma}e^{\frac{-x^2}{2\sigma^2}}$$&#xD;&#xA;i.e. the Gaussian pdf with unknown variance.&#xD;&#xA;&#xD;&#xA;What I'm confused about is how to solve for sigma when the values of the pdf are supposed to be independent samples from the distribution. If I'm understanding correctly, this means that the MSE itself becomes a random variable and cannot be a constant. &#xD;&#xA;&#xD;&#xA;If we were to make it a constant, wouldn't the values of $f(x)$ for each pixel have to already be known for the equation to be solvable? In which case the distribution would need to be already known to randomly sample the distribution to produce the values of $f(x)$...&#xD;&#xA;&#xD;&#xA;Anyhow, if anyone has advice on how to construct noisy images with a pre-defined PSNR, that would be appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [PSNR]: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio &quot;Peak Signal to Noise Ratio&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14252" PostHistoryTypeId="5" PostId="5267" RevisionGUID="ca25a88e-b028-4a9b-b37d-68d887949cf1" CreationDate="2017-06-21T23:47:23.690" UserId="231" Comment="Remove thanks and minor tidying" Text="I'm currently learning mathemetical concepts of distribution and the way to use them in a ray tracer with the book &quot;Physically Based Rendering&quot;.&#xD;&#xA;&#xD;&#xA;Let's start by uniformly sampling an hemisphere:&#xD;&#xA;&#xD;&#xA;As you probably know, a way to generate the uniformly distributed direction is to use the inversion method.&#xD;&#xA;&#xD;&#xA;Let us denote by $p$ our uniform probability density function:&#xD;&#xA;&#xD;&#xA;$p(\omega) = \cfrac{1}{2\pi}$ and so $p(\theta, \phi) = \sin(\theta)p(\omega)$.&#xD;&#xA;&#xD;&#xA;Then you compute $p(\theta)$, $p(\phi | \theta)$, you integrate your cumulative distribution function and you invert the function.&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;- **What does $p(\theta, \phi)$ really mean?**&#xD;&#xA;&#xD;&#xA;- **What is the transformation between $p(\omega)$ and $p(\theta, \phi)$?**&#xD;&#xA;&#xD;&#xA;- **In the book, to find $p(\theta,\phi)$ they state that $p(\theta, \phi) d\theta d\phi = p(\omega)d\omega$, but why?**&#xD;&#xA;&#xD;&#xA;I know that for $p(\omega)$, our random variable is a given $\omega$ (a direction), so the function represents a relative probability for this direction (so a solid angle, because the relative term implies a direction and a delta area around this direction).&#xD;&#xA;&#xD;&#xA;But for $p(\theta,\phi)$, our random variable is now the couple $(\theta,\phi)$. To what extent is it different from a direction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14253" PostHistoryTypeId="2" PostId="5270" RevisionGUID="1c1f2a0a-95c8-4893-bc2b-b10246819024" CreationDate="2017-06-22T05:02:09.163" UserId="2448" Text="I have been working on my own renderer for a while and I'm wondering is there any way to remove the Monticello noise from the rendered image besides waiting for a log time for it to converge?&#xD;&#xA;&#xD;&#xA;The way I found is to blur the image. Which is not helping because it reduces the quality/sharpness of the image by a lot. I can achieve that by render a small image with more samples then scale it up.&#xD;&#xA;&#xD;&#xA;Is there any algorithm designed to deal with noise in image in path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14254" PostHistoryTypeId="1" PostId="5270" RevisionGUID="1c1f2a0a-95c8-4893-bc2b-b10246819024" CreationDate="2017-06-22T05:02:09.163" UserId="2448" Text="Algorithms to Remove High Frequency Noise from Path Tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="14255" PostHistoryTypeId="3" PostId="5270" RevisionGUID="1c1f2a0a-95c8-4893-bc2b-b10246819024" CreationDate="2017-06-22T05:02:09.163" UserId="2448" Text="|algorithm|image-processing|pathtracing|denoise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14256" PostHistoryTypeId="2" PostId="5271" RevisionGUID="8d61c045-2786-4f3e-be59-349c52d62b17" CreationDate="2017-06-22T06:48:51.800" UserId="6868" Text="I have been trying to understand display and graphics. I feel that its hard to make a logical image of the terms. I understand this&#xD;&#xA;&#xD;&#xA;1) Frame buffer is a dedicated memory that have the image/video/3dimage or video to be shown, in pixel format&#xD;&#xA;&#xD;&#xA;2)overlay is some kind of hardware that is used with frame buffer&#xD;&#xA;&#xD;&#xA;3)surfaceflinger is a composition manager. It takes rendered data from gpu, and composite them in one surface. that means, it uses underlying hardware and driver to do all this composition.&#xD;&#xA;&#xD;&#xA;4)Composition means blending, mixing of all the surfaces.&#xD;&#xA;&#xD;&#xA;5) overlay, plane, framebuffer and sprite? What does all this do, or how to combine them and understand?&#xD;&#xA;&#xD;&#xA;Any book, links will be appreciated. A lot of books go to graphics way, instead of taking one particular SoC and explain display first then graphics in detail.&#xD;&#xA;&#xD;&#xA;Thanks in advance" ContentLicense="CC BY-SA 3.0" />
  <row Id="14257" PostHistoryTypeId="1" PostId="5271" RevisionGUID="8d61c045-2786-4f3e-be59-349c52d62b17" CreationDate="2017-06-22T06:48:51.800" UserId="6868" Text="What is the difference in overlay and framebuffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14258" PostHistoryTypeId="3" PostId="5271" RevisionGUID="8d61c045-2786-4f3e-be59-349c52d62b17" CreationDate="2017-06-22T06:48:51.800" UserId="6868" Text="|rendering|gpu|frame-buffer|compositing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14259" PostHistoryTypeId="2" PostId="5272" RevisionGUID="11125204-79b4-450e-a84b-7991679e5b23" CreationDate="2017-06-22T08:58:07.610" UserId="2041" Text="As you've understood, the *framebuffer* is an array in memory that holds all the pixels to display on the screen. On a desktop PC, it's probably special memory on the graphics card, but in a SoC with one memory shared by GPU and CPU, it's probably a normal memory allocation that the display controller uses DMA to read from.&#xD;&#xA;&#xD;&#xA;The *display controller* is a piece of hardware that reads pixels from the frame buffer and displays them on the physical screen.&#xD;&#xA;&#xD;&#xA;Many display controllers support the use of an overlay, which is like a very simple window. Sometimes they're fixed-size, but sometimes they're *masked* off. In this case, then there might be a secondary framebuffer that covers the whole screen. When the display controller reads a pixel of a particular colour from the primary framebuffer, then instead of displaying that pixel, it substitutes the corresponding pixel from the secondary framebuffer. It's like the *chroma key* or green screen technique used in movie effects and weather forecasts.&#xD;&#xA;&#xD;&#xA;That's one particular configuration: sometimes the secondary framebuffer is much smaller than the primary framebuffer, and a particular *register* in the display controller controls the dimensions and offset.&#xD;&#xA;&#xD;&#xA;The overlay technique is commonly used for displaying video streams. The frames of video might be coming from camera hardware or from video decoder hardware. Using an overlay means that this hardware and the GPU that's producing the rest of the screen (such as camera or playback GUI) aren't trying to access the same memory at once. The overlay might also be in a different pixel format to the primary framebuffer.&#xD;&#xA;&#xD;&#xA;The overlay technique only lets you do this simple substitution, though (and maybe some scaling), not anything complicated. You can't make the frame of video spin around and shrink to an icon when you're transitioning between different applications. You can't alpha-blend the video with Also, the number of overlays is limited by the hardware: usually one, but some controllers support two.&#xD;&#xA;&#xD;&#xA;*Composition* in this context refers to something the window manager does. It takes the frames from each application on the screen (the system GUI is also an application), and produces the final frame. On a smartphone, this usually means just taking the current foreground app and the system GUI (notification bar and navigation bar) and drawing them next to each other. But when there are transitions between apps, or if you use the &quot;recent tasks&quot; button, the situation is more complicated. The compositor also has to handle choreographing applications so the screen gets updated at 60 Hz even if applications are drawing at different rates.&#xD;&#xA;&#xD;&#xA;*Surface Flinger* is Android's compositor. It uses OpenGL ES to do the things described in the previous paragraph. It's also in charge of creating a framebuffer for each application to render into. (These framebuffers show up as textures inside Surface Flinger, using `EGLImage`.)&#xD;&#xA;&#xD;&#xA;Android also detects when there are simple cases that the display controller on the phone can handle as an overlay, so that it can switch to the faster, more energy-efficient path of using the overlay instead of using Surface Flinger's full GLES-based composition." ContentLicense="CC BY-SA 3.0" />
  <row Id="14260" PostHistoryTypeId="5" PostId="5270" RevisionGUID="d9dce726-5023-4e5e-aad4-efc81acbd959" CreationDate="2017-06-22T10:55:26.833" UserId="2448" Comment="fix typo" Text="I have been working on my own renderer for a while and I'm wondering is there any way to remove the Monticello noise from the rendered image besides waiting for a long time for it to converge?&#xD;&#xA;&#xD;&#xA;The way I found is to blur the image. Which is not really helping since it reduces the quality/sharpness of the image a lot. And I can achieve the same thing by render a small image with more samples then scale it up.&#xD;&#xA;&#xD;&#xA;Is there any algorithm designed to deal with noise in image in path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14264" PostHistoryTypeId="2" PostId="5274" RevisionGUID="9ab936e4-b52c-42ef-bacd-b79ae3765298" CreationDate="2017-06-22T15:44:42.960" UserId="20501" Text="Let's assume we have a 3D model consisted of `XYZ`-formatted vertices (such as point cloud model). My problem is given the position and normal of camera (i.e. where I am looking at the points), how can I extract the visible points and remove the non-visible points?&#xD;&#xA;&#xD;&#xA;For instance here all points corresponding to the green box and the back surface of the orange box are removed.&#xD;&#xA;&#xD;&#xA;P.S. It doesn't have to be perfect. Just any approach to remove the non-visible points so to decrease the total points works.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SWQgym.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14265" PostHistoryTypeId="1" PostId="5274" RevisionGUID="9ab936e4-b52c-42ef-bacd-b79ae3765298" CreationDate="2017-06-22T15:44:42.960" UserId="20501" Text="Extract visible vertices from a 3D geometry model" ContentLicense="CC BY-SA 3.0" />
  <row Id="14266" PostHistoryTypeId="3" PostId="5274" RevisionGUID="9ab936e4-b52c-42ef-bacd-b79ae3765298" CreationDate="2017-06-22T15:44:42.960" UserId="20501" Text="|3d|computational-geometry|geometry|mesh|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14267" PostHistoryTypeId="5" PostId="5274" RevisionGUID="180f78c4-0007-4dba-ac24-68549fc02eb5" CreationDate="2017-06-22T16:04:59.240" UserId="20501" Comment="added 46 characters in body" Text="Let's assume we have a 3D model consisted of `XYZ`-formatted vertices (such as point cloud model). My problem is given the position and normal of camera or camera projection (i.e. where I am looking at the points- usually given by my API), how can I extract the visible points and remove the non-visible points?&#xD;&#xA;&#xD;&#xA;For instance here all points corresponding to the green box and the back surface of the orange box are removed.&#xD;&#xA;&#xD;&#xA;P.S. It doesn't have to be perfect. Just any approach to remove the non-visible points so to decrease the total points works.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SWQgym.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14268" PostHistoryTypeId="2" PostId="5275" RevisionGUID="1a7fb3ff-c804-49bc-a4f1-851a42d59a51" CreationDate="2017-06-22T18:51:45.090" UserId="56" Text="There are, and I am looking forward to seeing the specifics of other answers, but one way to deal with this is to not have the noise (or as much noise) in the source data to begin with.&#xD;&#xA;&#xD;&#xA;The noise is coming from the fact that there is high variance in the rendering - the number of samples you've taken haven't converged enough to the actual right answer of the integral, and so some pixels are too high/bright and some are too low/dim (in each color channel).&#xD;&#xA;&#xD;&#xA;The problem is this: If you use white noise random numbers to do your sampling, you may get samples clumping together like the image below.  Given enough samples, it will converge, but it will take a while before it gives good coverage over the sampling space.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Alternately, you could sample at even intervals like the below, but that will give you aliasing artifacts instead of noise, which is worse that noise.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;One idea is to use low discrepancy sequences and do quasi monte carlo integration (https://en.wikipedia.org/wiki/Quasi-Monte_Carlo_method).  Low discrepancy sequences are related to blue noise, which has only high frequency components.  Going these routes, you get faster convergence of $O(1/N)$ instead of $O(\sqrt{N})$.&#xD;&#xA;&#xD;&#xA;Here is a &quot;jittered grid&quot; where you sample on a grid, but use small random offsets within a cell size.  This was invented by pixar and was under patent for a while but is no longer:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here is a common low discrepancy sequence called the Halton sequence (basically a 2d version of Van Der Corpus)&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;And here is a poisson disc sampling, using Mitchel's best candidate algorithm:[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;More information, including the source code that generated these images can be found here: https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4cQjK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rHjVE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kSYFd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Ayirs.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/DgPeP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14269" PostHistoryTypeId="5" PostId="5275" RevisionGUID="3391f085-bd27-43ba-8e82-8686ba6aca7c" CreationDate="2017-06-22T18:57:31.190" UserId="56" Comment="added 445 characters in body" Text="There are, and I am looking forward to seeing the specifics of other answers, but one way to deal with this is to not have the noise (or as much noise) in the source data to begin with.&#xD;&#xA;&#xD;&#xA;The noise is coming from the fact that there is high variance in the rendering - the number of samples you've taken haven't converged enough to the actual right answer of the integral, and so some pixels are too high/bright and some are too low/dim (in each color channel).&#xD;&#xA;&#xD;&#xA;The problem is this: If you use white noise random numbers to do your sampling, you may get samples clumping together like the image below.  Given enough samples, it will converge, but it will take a while before it gives good coverage over the sampling space.  Find a region of empty space in the image below (like in the lower right) and imagine that there was a small, bright light there and that the scene was dark everywhere else.  You can see how not having any samples there is going to make a problem for rendering.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Alternately, you could sample at even intervals like the below, but that will give you aliasing artifacts instead of noise, which is worse.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;One idea is to use low discrepancy sequences and do quasi monte carlo integration (https://en.wikipedia.org/wiki/Quasi-Monte_Carlo_method).  Low discrepancy sequences are related to blue noise, which has only high frequency components.  Going these routes, you get faster convergence of $O(1/N)$ instead of $O(\sqrt{N})$.  These give better coverage of the sample space, but since there is some randomness (or random like qualities) to them, they don't have the aliasing issues that regularly spaced sampling does.&#xD;&#xA;&#xD;&#xA;Here is a &quot;jittered grid&quot; where you sample on a grid, but use small random offsets within a cell size.  This was invented by pixar and was under patent for a while but is no longer:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here is a common low discrepancy sequence called the Halton sequence (basically a 2d version of Van Der Corpus)&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;And here is a poisson disc sampling, using Mitchel's best candidate algorithm:[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;More information, including the source code that generated these images can be found here: https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4cQjK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rHjVE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kSYFd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Ayirs.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/DgPeP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14270" PostHistoryTypeId="5" PostId="5274" RevisionGUID="f071a2bd-f8a6-417e-ad55-8e23af7bad44" CreationDate="2017-06-22T18:59:05.023" UserId="20501" Comment="added 55 characters in body" Text="Let's assume we have a 3D model consisted of `XYZ`-formatted vertices (such as point cloud model). My problem is given the position and normal of camera or camera projection (i.e. where I am looking at the points- usually given by my API), how can I extract the visible points and remove the non-visible points?&#xD;&#xA;&#xD;&#xA;For instance here all points corresponding to the green box and the back surface of the orange box are removed.&#xD;&#xA;&#xD;&#xA;P.S. It doesn't have to be perfect. Just any approach to somehow remove the non-visible points so to decrease the total points with not much impact on the visible points will work.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SWQgym.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14271" PostHistoryTypeId="2" PostId="5276" RevisionGUID="6c4c8840-b6bc-41b8-a47f-9a6e3100057a" CreationDate="2017-06-22T19:02:53.857" UserId="6873" Text="How can I identify that an object is patterned (or symmetrical at least?). For example, I give to the algorithm a wall of red bricks. I want it to recognize that if it takes 1,2 or 4 bricks, it's possible to recreate the whole wall with translation. I didn't find anything in literature, I probably have not tried the right keywords. Any suggestion is welcome." ContentLicense="CC BY-SA 3.0" />
  <row Id="14272" PostHistoryTypeId="1" PostId="5276" RevisionGUID="6c4c8840-b6bc-41b8-a47f-9a6e3100057a" CreationDate="2017-06-22T19:02:53.857" UserId="6873" Text="Pattern recognition on 3d geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="14273" PostHistoryTypeId="3" PostId="5276" RevisionGUID="6c4c8840-b6bc-41b8-a47f-9a6e3100057a" CreationDate="2017-06-22T19:02:53.857" UserId="6873" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14274" PostHistoryTypeId="5" PostId="5271" RevisionGUID="771a08e6-d248-40cc-b3b8-5f720a4ff5d4" CreationDate="2017-06-22T23:34:38.627" UserId="231" Comment="Formatting, typo and remove thanks." Text="I have been trying to understand display and graphics. I feel that it's hard to make a logical image of the terms. I understand this:&#xD;&#xA;&#xD;&#xA;1. Frame buffer is a dedicated memory that has the image/video/3dimage or video to be shown, in pixel format.&#xD;&#xA;&#xD;&#xA;1. Overlay is some kind of hardware that is used with the frame buffer.&#xD;&#xA;&#xD;&#xA;1. Surfaceflinger is a composition manager. It takes rendered data from the GPU, and composites them in one surface. That means, it uses the underlying hardware and driver to do all this composition.&#xD;&#xA;&#xD;&#xA;1. Composition means blending, mixing of all the surfaces.&#xD;&#xA;&#xD;&#xA;1. Overlay, plane, framebuffer and sprite? What does all this do, or how to combine them and understand?&#xD;&#xA;&#xD;&#xA;Any book, links will be appreciated. A lot of books go to graphics way, instead of taking one particular SoC and explain display first then graphics in detail." ContentLicense="CC BY-SA 3.0" />
  <row Id="14275" PostHistoryTypeId="2" PostId="5277" RevisionGUID="39893264-17dc-4e76-a029-934cfd47acb9" CreationDate="2017-06-23T00:28:04.167" UserId="6874" Text="New to opengl! I am having issues with passing colours from the program to vertex shader.&#xD;&#xA;&#xD;&#xA;I am creating a grid where I want to control the color of each cell.Thus I am generating each cell and having two vbo's, one for the vertices, and another for the colour. I want my grid to look like this: &#xD;&#xA;&#xD;&#xA;[![Ideal][1]][1] &#xD;&#xA;&#xD;&#xA;But I end up with:&#xD;&#xA;&#xD;&#xA;[![Reality][2]][2]&#xD;&#xA;&#xD;&#xA;I have confirmed if I generate the colour data in the vertex shader and then pass it to the fragment, I get the first case. It is only when I grab the colour data from the program that I get the second case.&#xD;&#xA;&#xD;&#xA;Code for creating each vbo(written in go):&#xD;&#xA;&#xD;&#xA;    var vbo [2]uint32&#xD;&#xA;	gl.GenBuffers(2, &amp;vbo[0])&#xD;&#xA;	gl.BindBuffer(gl.ARRAY_BUFFER, vbo[0])&#xD;&#xA;	gl.BufferData(gl.ARRAY_BUFFER, 4*len(points), gl.Ptr(points), gl.STATIC_DRAW)&#xD;&#xA;	gl.BindBuffer(gl.ARRAY_BUFFER, vbo[1])&#xD;&#xA;	gl.BufferData(gl.ARRAY_BUFFER, 4*3, gl.Ptr([]float32{0.5,0.5,0.0}), gl.STATIC_DRAW)&#xD;&#xA;	var vao uint32&#xD;&#xA;	gl.GenVertexArrays(1, &amp;vao)&#xD;&#xA;	gl.BindVertexArray(vao)&#xD;&#xA;	gl.EnableVertexAttribArray(0)&#xD;&#xA;	gl.BindBuffer(gl.ARRAY_BUFFER, vbo[0])&#xD;&#xA;	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil)&#xD;&#xA;&#xD;&#xA;	gl.EnableVertexAttribArray(1)&#xD;&#xA;	gl.BindBuffer(gl.ARRAY_BUFFER, vbo[1])&#xD;&#xA;	gl.VertexAttribPointer(1, 3, gl.FLOAT, false, 0, nil)&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    /*layout (location=0) */in vec3 vp;&#xD;&#xA;    /*layout (location=1)*/ in vec3 colour;&#xD;&#xA;    /*layout (location=2)*/  out vec3 outcolour;&#xD;&#xA;    void main(){&#xD;&#xA;        gl_Position = vec4(vp,1.0);&#xD;&#xA;        //outcolour = vec3(0.5,0.5,0.0);&#xD;&#xA;        outcolour = vec3(colour);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader&#xD;&#xA;&#xD;&#xA;    #version 410&#xD;&#xA;    in vec3 outcolour;&#xD;&#xA;    out vec4 frag_colour;&#xD;&#xA;    void main(){&#xD;&#xA;        frag_colour = vec4(outcolour,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LIN0W.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Pxew3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14276" PostHistoryTypeId="1" PostId="5277" RevisionGUID="39893264-17dc-4e76-a029-934cfd47acb9" CreationDate="2017-06-23T00:28:04.167" UserId="6874" Text="Passing Colour from program to vertex shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="14277" PostHistoryTypeId="3" PostId="5277" RevisionGUID="39893264-17dc-4e76-a029-934cfd47acb9" CreationDate="2017-06-23T00:28:04.167" UserId="6874" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14278" PostHistoryTypeId="2" PostId="5278" RevisionGUID="7bcd4554-2ed5-494e-8488-de35dc0c0b10" CreationDate="2017-06-23T01:37:30.183" UserId="2654" Text="I don't know what language that is, but I'm going to hazard a guess that the arrays `points` and `gl.Ptr([]float32{0.5,0.5,0.0})` are *not* the same size. If you intend to provide per-vertex colors, then you must provide one color for *every vertex*. If you want to provide a single color that all vertices share, then that would be a `uniform`, not a vertex shader `in`put.&#xD;&#xA;&#xD;&#xA;Also, commenting out your `layout` declarations isn't helping. Though if you are going to declare a `location` for the VS output variable, then the matching FS input needs to have the same `location` declared." ContentLicense="CC BY-SA 3.0" />
  <row Id="14279" PostHistoryTypeId="2" PostId="5279" RevisionGUID="b52d0b71-cb70-4aea-9992-c8fc49cd0804" CreationDate="2017-06-23T02:20:29.577" UserId="3073" Text="One technique you could use is break the image into blocks and measure each blocks variance - this way you can apply more samples to blocks with higher variance. &#xD;&#xA;&#xD;&#xA;The variance can be estimated by using 2 accumulation buffers instead of 1. You render each pass into an alternate buffer. The difference between these buffers (with respect to a block) is proportional to variance. Upon presentation to screen you can add the two buffers together to get your full accumulation buffer back." ContentLicense="CC BY-SA 3.0" />
  <row Id="14280" PostHistoryTypeId="5" PostId="5279" RevisionGUID="16b79c48-0135-421a-92d7-9ac089bb6828" CreationDate="2017-06-23T02:47:17.973" UserId="3073" Comment="added 12 characters in body" Text="One technique you could use is break the image into blocks and measure each blocks variance - this way you can apply more samples to blocks with higher variance. &#xD;&#xA;&#xD;&#xA;The variance can be estimated by using 2 accumulation buffers instead of 1. You render each pass into an alternate buffer. The absolute difference between these buffers (with respect to each block) is proportional to variance. Upon presentation to screen you can add the two buffers together to get your full accumulation buffer back." ContentLicense="CC BY-SA 3.0" />
  <row Id="14282" PostHistoryTypeId="2" PostId="5280" RevisionGUID="23c9a70f-d359-4500-bd6c-01f6ec5b6796" CreationDate="2017-06-23T05:57:20.637" UserId="6875" Text="I am trying to vectorize the contours (skewed rectangle) of the TV in the following original image.&#xD;&#xA;&#xD;&#xA;[![oroginal][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My first step is applying threshold. Tried selection of threshold values based on what skimage has to offer, but non of them managed (for example) to separate correctly the little fawn to the left, or the TV stand from the TV border. For example this is the result using yen's method:&#xD;&#xA;&#xD;&#xA;[![bw][2]][2]&#xD;&#xA;&#xD;&#xA;Can you suggest any preprocessing that may help before applying a threshold ?  &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pndvM.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/aEytA.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14283" PostHistoryTypeId="1" PostId="5280" RevisionGUID="23c9a70f-d359-4500-bd6c-01f6ec5b6796" CreationDate="2017-06-23T05:57:20.637" UserId="6875" Text="Suggested image preprocessing before applying threshold" ContentLicense="CC BY-SA 3.0" />
  <row Id="14284" PostHistoryTypeId="3" PostId="5280" RevisionGUID="23c9a70f-d359-4500-bd6c-01f6ec5b6796" CreationDate="2017-06-23T05:57:20.637" UserId="6875" Text="|transformations|color|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14285" PostHistoryTypeId="5" PostId="5270" RevisionGUID="f7631d51-a25f-44a1-8834-ce6bcf4ba194" CreationDate="2017-06-23T06:36:05.500" UserId="48" Comment="grammar/typos" Text="I have been working on my own renderer for a while, and I'm wondering if there's any way to remove the Monte Carlo noise from the rendered image, besides waiting for a long time for it to converge?&#xD;&#xA;&#xD;&#xA;The way I found is to blur the image, which is not really helpful, since it reduces the quality/sharpness of the image a lot. And I can achieve the same thing by rendering a small image with more samples, then scaling it up.&#xD;&#xA;&#xD;&#xA;Is there any algorithm designed to deal with noise in the image in path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14286" PostHistoryTypeId="5" PostId="5272" RevisionGUID="01c9f02f-029a-45e8-ad84-421aac37e4fb" CreationDate="2017-06-23T08:16:48.473" UserId="2041" Comment="Finish a sentence I wrote half of." Text="As you've understood, the *framebuffer* is an array in memory that holds all the pixels to display on the screen. On a desktop PC, it's probably special memory on the graphics card, but in a SoC with one memory shared by GPU and CPU, it's probably a normal memory allocation that the display controller uses DMA to read from.&#xD;&#xA;&#xD;&#xA;The *display controller* is a piece of hardware that reads pixels from the frame buffer and displays them on the physical screen.&#xD;&#xA;&#xD;&#xA;Many display controllers support the use of an overlay, which is like a very simple window. Sometimes they're fixed-size, but sometimes they're *masked* off. In this case, then there might be a secondary framebuffer that covers the whole screen. When the display controller reads a pixel of a particular colour from the primary framebuffer, then instead of displaying that pixel, it substitutes the corresponding pixel from the secondary framebuffer. It's like the *chroma key* or green screen technique used in movie effects and weather forecasts.&#xD;&#xA;&#xD;&#xA;That's one particular configuration: sometimes the secondary framebuffer is much smaller than the primary framebuffer, and a particular *register* in the display controller controls the dimensions and offset.&#xD;&#xA;&#xD;&#xA;The overlay technique is commonly used for displaying video streams. The frames of video might be coming from camera hardware or from video decoder hardware. Using an overlay means that this hardware and the GPU that's producing the rest of the screen (such as camera or playback GUI) aren't trying to access the same memory at once. The overlay might also be in a different pixel format to the primary framebuffer.&#xD;&#xA;&#xD;&#xA;The overlay technique only lets you do this simple substitution, though (and maybe some scaling), not anything complicated. You can't make the frame of video spin around and shrink to an icon when you're transitioning between different applications. You can't alpha-blend the video with the primary framebuffer. Also, the number of overlays is limited by the hardware: usually one, but some controllers support two.&#xD;&#xA;&#xD;&#xA;*Composition* in this context refers to something the window manager does. It takes the frames from each application on the screen (the system GUI is also an application), and produces the final frame. On a smartphone, this usually means just taking the current foreground app and the system GUI (notification bar and navigation bar) and drawing them next to each other. But when there are transitions between apps, or if you use the &quot;recent tasks&quot; button, the situation is more complicated. The compositor also has to handle choreographing applications so the screen gets updated at 60 Hz even if applications are drawing at different rates.&#xD;&#xA;&#xD;&#xA;*Surface Flinger* is Android's compositor. It uses OpenGL ES to do the things described in the previous paragraph. It's also in charge of creating a framebuffer for each application to render into. (These framebuffers show up as textures inside Surface Flinger, using `EGLImage`.)&#xD;&#xA;&#xD;&#xA;Android also detects when there are simple cases that the display controller on the phone can handle as an overlay, so that it can switch to the faster, more energy-efficient path of using the overlay instead of using Surface Flinger's full GLES-based composition." ContentLicense="CC BY-SA 3.0" />
  <row Id="14287" PostHistoryTypeId="2" PostId="5281" RevisionGUID="f9c0cc02-5187-41b9-a392-23ed5e2485c3" CreationDate="2017-06-23T09:35:41.487" UserId="2041" Text="I think the result you've already shown is about as good as you're going to get. What you need isn't preprocessing of the input image, but to give your edge detector a good idea of what contour it's looking for. If you write your contour extractor to look specifically for quadrilaterals, it'll easily be able to filter where the fawn sticks out at the bottom left, and the stand at the bottom. Then it's just a question of finding the one that corresponds to the TV (probably the largest, but it depends on what other images you're running it on)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14288" PostHistoryTypeId="2" PostId="5282" RevisionGUID="c530076a-cc84-4f6a-93f6-218c7e0a7591" CreationDate="2017-06-23T10:35:14.413" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="14289" PostHistoryTypeId="1" PostId="5282" RevisionGUID="c530076a-cc84-4f6a-93f6-218c7e0a7591" CreationDate="2017-06-23T10:35:14.413" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="14290" PostHistoryTypeId="2" PostId="5283" RevisionGUID="de2134f4-b53f-4f88-bc15-44683e6d5278" CreationDate="2017-06-23T10:35:14.413" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="14291" PostHistoryTypeId="1" PostId="5283" RevisionGUID="de2134f4-b53f-4f88-bc15-44683e6d5278" CreationDate="2017-06-23T10:35:14.413" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="14292" PostHistoryTypeId="5" PostId="5274" RevisionGUID="cd8c0126-bce9-466f-b8e5-a3b6126fcc3e" CreationDate="2017-06-23T10:41:10.067" UserId="20501" Comment="added 109 characters in body" Text="Let's assume we have a 3D model consisted of `XYZ`-formatted vertices (such as point cloud model). My problem is given the position and normal of camera or camera projection (i.e. where I am looking at the points- usually given by my API), how can I extract the visible points and remove the non-visible points?&#xD;&#xA;&#xD;&#xA;For instance here all points corresponding to the green box and the back surface of the orange box are removed.&#xD;&#xA;&#xD;&#xA;P.S. It doesn't have to be perfect. Just any approach to somehow remove the non-visible points so to decrease the total points with not much impact on the visible points will work.&#xD;&#xA;&#xD;&#xA;Here is a test point cloud model to work with: https://www.dropbox.com/s/dfhyy9xa5i9o2fz/testPLY.ply?dl=0&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SWQgym.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14293" PostHistoryTypeId="2" PostId="5284" RevisionGUID="04a3baaa-4aa9-4124-b5b3-31f256eedf90" CreationDate="2017-06-23T14:31:48.053" UserId="6876" Text="The OpenGL Programming Guide states the formula for diffuse hemisphere lighting on a surface with normal vector $\vec{n}$ as&#xD;&#xA;&#xD;&#xA;$L_o(\vec{n}) = L_i(\uparrow) (1-\frac{1}{2}\sin(\theta)) + L_i(\downarrow) \frac{1}{2}\sin(\theta)$ if $0 &lt;= \theta &lt; \frac{1}{2}\pi$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$L_o(\vec{n}) = L_i(\uparrow) \frac{1}{2}\sin(\theta) + L_i(\downarrow) (1 - \frac{1}{2}\sin(\theta))$ if $\frac{1}{2}\pi &lt;= \theta &lt;= \pi$&#xD;&#xA;&#xD;&#xA;with $\theta$ as the polar angle of $\vec{n}$:&#xD;&#xA;&#xD;&#xA;$\theta = \cos^{-1}(n_z)$&#xD;&#xA;&#xD;&#xA;I found various other sources for this formula, however I was unable to find the derivation of this formula.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;On the other hand, I found this [wikibook article](https://en.wikibooks.org/wiki/GLSL_Programming/Unity/Diffuse_Reflection_of_Skylight#Hemisphere_Lighting), suggesting:&#xD;&#xA;$L_o(\vec{n}) = L_{i}(\uparrow) (\frac{1}{2} + \frac{1}{2} \cos(\theta)) + L_{i}(\downarrow) (\frac{1}{2} - \frac{1}{2} \cos(\theta))$&#xD;&#xA;&#xD;&#xA;which is explicitly described as an approximation/cheating in the OpenGL Programming Guide. The derivation of this formula is done without a clear source of error.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Trying to reproduce either formula, I solved&#xD;&#xA;&#xD;&#xA;$L_o(\vec{n}) = \frac{1}{\pi}\int_{H} L_i(\vec{w}) \langle{}\vec{w}, \vec{n}\rangle{} \mathrm{d}\vec{w}$&#xD;&#xA;&#xD;&#xA;both analytically and numerically, and both times I ended up with the latter formula.&#xD;&#xA;&#xD;&#xA;While it may not matter much in practice, I am apparently making some mistake here. So my question is: **How can I derive the former formula from this integral and why is the latter formula only an approximation?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="14294" PostHistoryTypeId="1" PostId="5284" RevisionGUID="04a3baaa-4aa9-4124-b5b3-31f256eedf90" CreationDate="2017-06-23T14:31:48.053" UserId="6876" Text="Exact Formula for Diffuse Hemisphere Lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="14295" PostHistoryTypeId="3" PostId="5284" RevisionGUID="04a3baaa-4aa9-4124-b5b3-31f256eedf90" CreationDate="2017-06-23T14:31:48.053" UserId="6876" Text="|lighting|diffuse|hemisphere|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14296" PostHistoryTypeId="5" PostId="5284" RevisionGUID="73df880f-257c-40cc-b3c6-33d5bae88c26" CreationDate="2017-06-23T17:43:46.240" UserId="6876" Comment="Added a link to one of the sources suggesting the first formula." Text="The OpenGL Programming Guide states the formula for diffuse hemisphere lighting on a surface with normal vector $\vec{n}$ as&#xD;&#xA;&#xD;&#xA;$L_o(\vec{n}) = L_i(\uparrow) (1-\frac{1}{2}\sin(\theta)) + L_i(\downarrow) \frac{1}{2}\sin(\theta)$ if $0 &lt;= \theta &lt; \frac{1}{2}\pi$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$L_o(\vec{n}) = L_i(\uparrow) \frac{1}{2}\sin(\theta) + L_i(\downarrow) (1 - \frac{1}{2}\sin(\theta))$ if $\frac{1}{2}\pi &lt;= \theta &lt;= \pi$&#xD;&#xA;&#xD;&#xA;with $\theta$ as the polar angle of $\vec{n}$:&#xD;&#xA;&#xD;&#xA;$\theta = \cos^{-1}(n_z)$&#xD;&#xA;&#xD;&#xA;I found various other sources (e.g. [this text](http://www2.lawrence.edu/fast/GREGGJ/CMSC420/chapter21/Irradiance.html)) for this formula, however I was unable to find the derivation of this formula.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;On the other hand, I found this [wikibook article](https://en.wikibooks.org/wiki/GLSL_Programming/Unity/Diffuse_Reflection_of_Skylight#Hemisphere_Lighting), suggesting:&#xD;&#xA;$L_o(\vec{n}) = L_{i}(\uparrow) (\frac{1}{2} + \frac{1}{2} \cos(\theta)) + L_{i}(\downarrow) (\frac{1}{2} - \frac{1}{2} \cos(\theta))$&#xD;&#xA;&#xD;&#xA;which is explicitly described as an approximation/cheating in the OpenGL Programming Guide. The derivation of this formula is done without a clear source of error.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Trying to reproduce either formula, I solved&#xD;&#xA;&#xD;&#xA;$L_o(\vec{n}) = \frac{1}{\pi}\int_{H} L_i(\vec{w}) \langle{}\vec{w}, \vec{n}\rangle{} \mathrm{d}\vec{w}$&#xD;&#xA;&#xD;&#xA;both analytically and numerically, and both times I ended up with the latter formula.&#xD;&#xA;&#xD;&#xA;While it may not matter much in practice, I am apparently making some mistake here. So my question is: **How can I derive the former formula from this integral and why is the latter formula only an approximation?**" ContentLicense="CC BY-SA 3.0" />
  <row Id="14297" PostHistoryTypeId="5" PostId="5274" RevisionGUID="4734f6cf-c1c1-4b67-ac3f-5dbecdf1c004" CreationDate="2017-06-23T21:36:13.670" UserId="20501" Comment="added 117 characters in body" Text="Let's assume we have a 3D model consisted of `XYZ`-formatted vertices (such as point cloud model). My problem is given the position and normal of camera or camera projection (i.e. where I am looking at the points- usually given by my API), how can I extract the visible points and remove the non-visible points?&#xD;&#xA;&#xD;&#xA;For instance here all points corresponding to the green box and the back surface of the orange box are removed. In point clouds, points have a size. So let's assume they have a size, say 5 pixel radius just for modeling purpose.&#xD;&#xA;&#xD;&#xA;P.S. It doesn't have to be perfect. Just any approach to somehow remove the non-visible points so to decrease the total points with not much impact on the visible points will work.&#xD;&#xA;&#xD;&#xA;Here is a test point cloud model to work with: https://www.dropbox.com/s/dfhyy9xa5i9o2fz/testPLY.ply?dl=0&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SWQgym.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14298" PostHistoryTypeId="5" PostId="5274" RevisionGUID="90003048-afce-48a2-b31a-9424ddba251d" CreationDate="2017-06-23T23:23:17.363" UserId="20501" Comment="added 5 characters in body" Text="Let's assume we have a 3D model consisted of `XYZ`-formatted vertices (such as point cloud model). My problem is given the position and normal of camera or camera projection (i.e. where I am looking at the points- usually given by my API), how can I extract the visible points and remove the non-visible points?&#xD;&#xA;&#xD;&#xA;For instance here points corresponding to the black point cloud box and the back surface of the red box are removed. In point clouds, points have a size. So let's assume they have a size, say 5 pixel radius just for modeling purpose.&#xD;&#xA;&#xD;&#xA;P.S. It doesn't have to be perfect. Just any approach to somehow remove the non-visible points so to decrease the total points with not much impact on the visible points will work.&#xD;&#xA;&#xD;&#xA;Here is a test point cloud model to work with: https://www.dropbox.com/s/dfhyy9xa5i9o2fz/testPLY.ply?dl=0&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eoovAm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14299" PostHistoryTypeId="5" PostId="5263" RevisionGUID="881a5617-1908-4b33-a8e7-53639d8b8cc1" CreationDate="2017-06-24T01:09:37.547" UserId="6834" Comment="deleted 208 characters in body" Text="Below there are two identical meshes, however the first one has edges moving in random directions, the second one has edges moving in a orderly, uniform fashion (edge flow). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;i want to be able to make a mesh with uniform edges (good edge flow) from a mesh with bad edge flow.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/F99iV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14302" PostHistoryTypeId="2" PostId="5285" RevisionGUID="df49ea63-dbc8-41c5-bfa0-f81654d21ebd" CreationDate="2017-06-24T13:24:24.573" UserId="6882" Text="Existence question. Can exist **convex** polygon witch is not **simple** polygon?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14303" PostHistoryTypeId="1" PostId="5285" RevisionGUID="df49ea63-dbc8-41c5-bfa0-f81654d21ebd" CreationDate="2017-06-24T13:24:24.573" UserId="6882" Text="Convex not simply Polygon" ContentLicense="CC BY-SA 3.0" />
  <row Id="14304" PostHistoryTypeId="3" PostId="5285" RevisionGUID="df49ea63-dbc8-41c5-bfa0-f81654d21ebd" CreationDate="2017-06-24T13:24:24.573" UserId="6882" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14305" PostHistoryTypeId="5" PostId="5283" RevisionGUID="cc1f3eb5-f132-4770-a357-9a528c59df99" CreationDate="2017-06-24T19:02:47.330" UserId="6749" Comment="added 171 characters in body" Text="Compositing is the combining of visual elements from separate sources into single images, often to create the illusion that all those elements are parts of the same scene." ContentLicense="CC BY-SA 3.0" />
  <row Id="14306" PostHistoryTypeId="24" PostId="5283" RevisionGUID="cc1f3eb5-f132-4770-a357-9a528c59df99" CreationDate="2017-06-24T19:02:47.330" Comment="Proposed by 6749 approved by 209, 48 edit id of 255" ContentLicense="CC BY-SA 3.0" />
  <row Id="14307" PostHistoryTypeId="2" PostId="5286" RevisionGUID="e7586625-dd67-460f-ab06-f3d53388d536" CreationDate="2017-06-24T20:20:53.910" UserId="6806" Text="Many books describe that BRDF have the following property (reciprocity):&#xD;&#xA;&#xD;&#xA;$$f_r(x, \Theta\to \Psi ) =  f_r(x,  \Psi \to \Theta)$$&#xD;&#xA;&#xD;&#xA;Why the above equation is coorect?&#xD;&#xA;&#xD;&#xA;I think the above equation should be changed as follow:&#xD;&#xA;&#xD;&#xA;(because the two symbols(theat and psi) are **direction vectors**)&#xD;&#xA;$$f_r(x, \Theta\to \Psi ) =  f_r(x,  -\Psi \to -\Theta)$$&#xD;&#xA;&#xD;&#xA;What is my mistake? &#xD;&#xA;(I am very confused about the concept.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14308" PostHistoryTypeId="1" PostId="5286" RevisionGUID="e7586625-dd67-460f-ab06-f3d53388d536" CreationDate="2017-06-24T20:20:53.910" UserId="6806" Text="The reciprocity of BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="14309" PostHistoryTypeId="3" PostId="5286" RevisionGUID="e7586625-dd67-460f-ab06-f3d53388d536" CreationDate="2017-06-24T20:20:53.910" UserId="6806" Text="|physically-based|pbr|photo-realistic|realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14310" PostHistoryTypeId="2" PostId="5287" RevisionGUID="67591457-ddcc-4ccd-983d-8420a06f69c8" CreationDate="2017-06-24T21:08:57.180" UserId="5256" Text="**How is Iridescence handled in a Path Tracer?** I have little knowledge of this topic but from what I gather in a Ray Tracer each ray is given its own wavelength as opposed to an RGB value. This automatically simulates Dispersion and Fluorescence. Is this called Spectral Rendering?&#xD;&#xA;&#xD;&#xA;What are the approaches usually taken to render Iridescence? Could someone give a brief overview of the method and a reference to a resource I can use to learn more in-depth knowledge I can use for implementation? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14311" PostHistoryTypeId="1" PostId="5287" RevisionGUID="67591457-ddcc-4ccd-983d-8420a06f69c8" CreationDate="2017-06-24T21:08:57.180" UserId="5256" Text="How is Iridescence handled in a Path Tracer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14312" PostHistoryTypeId="3" PostId="5287" RevisionGUID="67591457-ddcc-4ccd-983d-8420a06f69c8" CreationDate="2017-06-24T21:08:57.180" UserId="5256" Text="|pathtracing|physically-based|spectral|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14313" PostHistoryTypeId="5" PostId="5287" RevisionGUID="69e49e42-ad6a-4b3e-bd16-4faaaf07b171" CreationDate="2017-06-24T21:14:10.720" UserId="231" Comment="Remove duplicate title" Text="I have little knowledge of this topic but from what I gather in a Ray Tracer each ray is given its own wavelength as opposed to an RGB value. This automatically simulates Dispersion and Fluorescence. Is this called Spectral Rendering?&#xD;&#xA;&#xD;&#xA;What are the approaches usually taken to render Iridescence? Could someone give a brief overview of the method and a reference to a resource I can use to learn more in-depth knowledge I can use for implementation? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14314" PostHistoryTypeId="2" PostId="5288" RevisionGUID="b9dfdf5a-df1b-4dda-81a1-03e5b088aa2a" CreationDate="2017-06-24T21:35:58.823" UserId="4908" Text="You probably know that the BRDF is to calculate the reflected light, from a light source to a camera (In examples a light source and a camera is used, but it does not need to be just that). &#xD;&#xA;&#xD;&#xA;The property that you are talking about, basically says that when you swap the light source with the camera, it still gives the same result.&#xD;&#xA;&#xD;&#xA;Lets look at an example I quickly made.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Ok, so here you see the basic setup. You have a light source, a camera and a point on a surface. Wi is the direction towards the light, the incoming direction. Wo is the direction towards the camera, the outgoing direction. N is the normal of the surface.&#xD;&#xA;&#xD;&#xA;The property says that if we switch Wi and Wo with each other the result is the same.&#xD;&#xA;&#xD;&#xA;The example would then look like this.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This looks normal and logical. You said that you should invert the direction vectors. If we do that, this is then our result.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;You can see that it now looks like the surface is illuminated from the other side, and since the normal is not inverted, it will end up looking black.&#xD;&#xA;&#xD;&#xA;So that is where you made your mistakes. The property says that you can swap the incoming and outgoing vectors and the result will still be the same. This is called the Helmholtz reciprocity. And where you might got confused was this part &quot;how a ray of light and its reverse ray encounter matched optical adventures&quot; (from the wikipedia). But it is not talking about the inverse (multipled by -1) but about the outgoing ray of the event in something like a reflection or refraction.&#xD;&#xA;&#xD;&#xA;I recommend reading up on the Helmholtz reciprocity. For example on the wikipedia: [https://en.wikipedia.org/wiki/Helmholtz_reciprocity][4] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope I explained this properly, and if I made any mistakes, I am happy to learn and fix this answer.&#xD;&#xA;&#xD;&#xA;Good luck with your adventures through the computer graphics universe!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zTOsg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TjC5p.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/VxHWn.png&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Helmholtz_reciprocity" ContentLicense="CC BY-SA 3.0" />
  <row Id="14315" PostHistoryTypeId="5" PostId="5286" RevisionGUID="1043796c-11ca-42fb-904c-c1b03aac3580" CreationDate="2017-06-24T21:39:25.960" UserId="231" Comment="Formatting and tidying " Text="Many books describe that a BRDF has the following property (reciprocity):&#xD;&#xA;&#xD;&#xA;$$f_r(x, \Theta \to \Psi ) =  f_r(x, \Psi \to \Theta)$$&#xD;&#xA;&#xD;&#xA;Why is the above equation correct?&#xD;&#xA;&#xD;&#xA;I think the above equation should be changed as follows:&#xD;&#xA;&#xD;&#xA;(because the two symbols $\Theta$ and $\Psi$ are **direction vectors**)&#xD;&#xA;&#xD;&#xA;$$f_r(x, \Theta\to \Psi ) =  f_r(x,  -\Psi \to -\Theta)$$&#xD;&#xA;&#xD;&#xA;What is my mistake?  &#xD;&#xA;(I am very confused about the concept.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14317" PostHistoryTypeId="5" PostId="5285" RevisionGUID="fe0812e7-68b7-4d05-bc71-833223b6fa72" CreationDate="2017-06-25T08:57:09.550" UserId="38" Comment="added 10 characters in body; edited title" Text="Existence question: Can there exist a **convex** polygon witch is not a **simple** polygon?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14318" PostHistoryTypeId="4" PostId="5285" RevisionGUID="fe0812e7-68b7-4d05-bc71-833223b6fa72" CreationDate="2017-06-25T08:57:09.550" UserId="38" Comment="added 10 characters in body; edited title" Text="Convex non simple polygon?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14319" PostHistoryTypeId="2" PostId="5289" RevisionGUID="54e99666-c352-4364-9b7d-cdc5b710d93c" CreationDate="2017-06-25T09:16:35.453" UserId="38" Text="For a polygon to be convex the outside angle of the polygon has to be more than or equal to 180 degrees. Now at intersection of 2 lines the outermost angle has to be less than 180 degrees for the lines to intersect between the endpoints.&#xD;&#xA;&#xD;&#xA;Now the answer to this question depends on how you define what is inside of the polygon. If you consider some a even odd filling rule then the answer is **No** such shape exists. But if you consider only the outermost curve to do filling then yes, its possible if you intersect at the endpoint of a line. But to me this sounds more like splitting hairs as that shape reduces to a simple polygon." ContentLicense="CC BY-SA 3.0" />
  <row Id="14321" PostHistoryTypeId="2" PostId="5290" RevisionGUID="d534a259-eab3-4416-9783-f170de2c8152" CreationDate="2017-06-25T10:53:36.243" UserId="2041" Text="I'm not sure I've correctly understood the question, but here goes.&#xD;&#xA;&#xD;&#xA;You're trying to sample directions uniformly, so you've got $p(\omega)$, which is the probability of getting a particular direction. But what is a direction? You actually need your probability distribution to produce numbers in some representation, and the easiest representation to deal with is lat-long (i.e. two angles). So the thing you actually need to sample from is the probability distribution of pairs of angles. This is what $p(\theta, \phi)$ is: the joint probability of two variables.&#xD;&#xA;&#xD;&#xA;$p(\omega)$ and $p(\theta, \phi)$ mean the same thing geometrically, but the former gives you an abstract *direction* you can't sample from directly, while the latter more usefully gives you two numbers that *represent* a direction.&#xD;&#xA;&#xD;&#xA;The reason for your third bullet point is to do with the point you've made about how it isn't just a single direction. These aren't really functions: they're *distributions*. A direction is infinitesimal, so you can't have a probability of just one direction. What you actually need to do is integrate it over the directions you're interested in.&#xD;&#xA;$$&#xD;&#xA;\int p(\omega)d\omega = \int_0^{2\pi}\int_0^\pi p(\theta, \phi)d\theta d\phi = 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Whichever representation you use, the integral over the hemisphere has to be 1, because it's a probability distribution." ContentLicense="CC BY-SA 3.0" />
  <row Id="14322" PostHistoryTypeId="2" PostId="5291" RevisionGUID="15057b66-d66a-433b-a8d1-4cc0e584572c" CreationDate="2017-06-25T16:31:35.673" UserId="6838" Text="I've recently been using **CrazyBump**, and I think I'm starting to understand how it works. But I'm confused about what it calls **Shape Recognition**. According to [this](https://iamsparky.wordpress.com/crazybump/) website, that feature attempts to add directional lighting information, but what exactly does that mean?&#xD;&#xA;&#xD;&#xA;[![Test Texture][1]][1]&lt;br&gt;&#xD;&#xA;Here's my test texture. It's simple, just so I can understand what's going on.&#xD;&#xA;&#xD;&#xA;[![Shape Recognition Off][2]][2]&lt;br&gt;&#xD;&#xA;Here's the generated normal map, before Shape Recognition.&#xD;&#xA;&#xD;&#xA;[![Shape  Recognition On][3]][3]&lt;br&gt;&#xD;&#xA;Here's the generated normal map, after Shape Recognition.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pyg06.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/MwYMx.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/YPgMf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14323" PostHistoryTypeId="1" PostId="5291" RevisionGUID="15057b66-d66a-433b-a8d1-4cc0e584572c" CreationDate="2017-06-25T16:31:35.673" UserId="6838" Text="CrazyBump Shape Recognition" ContentLicense="CC BY-SA 3.0" />
  <row Id="14324" PostHistoryTypeId="3" PostId="5291" RevisionGUID="15057b66-d66a-433b-a8d1-4cc0e584572c" CreationDate="2017-06-25T16:31:35.673" UserId="6838" Text="|texture|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14328" PostHistoryTypeId="2" PostId="5293" RevisionGUID="8727f28d-d718-45d7-ac1e-c38d727de0ec" CreationDate="2017-06-25T16:54:18.873" UserId="6025" Text="I'm using OpenGL to learn computer graphics.  I'm trying to understand projection matrices.  The following are shown in the OpenGL 'Red Book':&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Qi0UI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FBZZ5.png&#xD;&#xA;&#xD;&#xA;I don't understand why the width and height are divided by 2?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14329" PostHistoryTypeId="1" PostId="5293" RevisionGUID="8727f28d-d718-45d7-ac1e-c38d727de0ec" CreationDate="2017-06-25T16:54:18.873" UserId="6025" Text="perspective matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="14330" PostHistoryTypeId="3" PostId="5293" RevisionGUID="8727f28d-d718-45d7-ac1e-c38d727de0ec" CreationDate="2017-06-25T16:54:18.873" UserId="6025" Text="|projections|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14331" PostHistoryTypeId="4" PostId="5293" RevisionGUID="78b72a03-f96a-4d99-9771-40a60ecddb20" CreationDate="2017-06-25T17:11:19.750" UserId="2041" Comment="edited title" Text="Why are width and height divided by 2 in the perspective projection matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14332" PostHistoryTypeId="2" PostId="5294" RevisionGUID="dccf8b8b-b988-4a95-a595-9d17c6731f26" CreationDate="2017-06-25T17:35:05.283" UserId="2041" Text="Because $x_{proj}$ doesn't vary from $0 \to \tfrac{width}{2}$, it varies from $-\tfrac{width}{2} \to \tfrac{width}{2}$.&#xD;&#xA;&#xD;&#xA;What's important is not the width, but the minimum and maximum values of $x_{proj}$. Because $(0, 0)$ is in the centre of the viewport, not the corner, the min and max values are plus and minus half of the width.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;BTW, the Red Book is not a great introduction to graphics in general. It's a technical standard, not a tutorial, so the explanation of concepts is just enough to be unambiguous - it's not trying to *teach* the material. It's also about a scanline rendering library in particular, so there's a lot of important concepts it doesn't describe at all, such as what BRDFs are important, how they relate to real-world surface properties, what an image really is, and many higher-level techniques.&#xD;&#xA;&#xD;&#xA;And finally, even in the area it's about - how to use a GPU to accelerate rendering - it's hideously out of date. The GL architecture is based on GPUs from 20 years ago. Although lots of features have been added to keep up with changes to hardware, the fundamental abstractions are not a good way to understand current GPU architectures.&#xD;&#xA;&#xD;&#xA;If you want to learn about the theory of computer graphics, start with a proper textbook such as Physically Based Rendering or Computer Graphics: Principles and Practice, or an online course. If you want to learn how to make a 3D application, start with a tutorial about the kind of application you're interested in (e.g. if it's a game, try a Unity tutorial)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14339" PostHistoryTypeId="5" PostId="5294" RevisionGUID="c627cc5e-4751-41b6-a6db-61a00f04f42e" CreationDate="2017-06-26T19:20:52.603" UserId="2041" Comment="Correction from the comments" Text="Because $x_{proj}$ doesn't vary from $0 \to width$, it varies from $-\tfrac{width}{2} \to \tfrac{width}{2}$.&#xD;&#xA;&#xD;&#xA;What's important is not the width, but the minimum and maximum values of $x_{proj}$. Because $(0, 0)$ is in the centre of the viewport, not the corner, the min and max values are plus and minus half of the width.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;BTW, the Red Book is not a great introduction to graphics in general. It's a technical standard, not a tutorial, so the explanation of concepts is just enough to be unambiguous - it's not trying to *teach* the material. It's also about a scanline rendering library in particular, so there's a lot of important concepts it doesn't describe at all, such as what BRDFs are important, how they relate to real-world surface properties, what an image really is, and many higher-level techniques.&#xD;&#xA;&#xD;&#xA;And finally, even in the area it's about - how to use a GPU to accelerate rendering - it's hideously out of date. The GL architecture is based on GPUs from 20 years ago. Although lots of features have been added to keep up with changes to hardware, the fundamental abstractions are not a good way to understand current GPU architectures.&#xD;&#xA;&#xD;&#xA;If you want to learn about the theory of computer graphics, start with a proper textbook such as Physically Based Rendering or Computer Graphics: Principles and Practice, or an online course. If you want to learn how to make a 3D application, start with a tutorial about the kind of application you're interested in (e.g. if it's a game, try a Unity tutorial)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14340" PostHistoryTypeId="2" PostId="5295" RevisionGUID="fed11d1e-96b4-4b63-91a2-82a93221187a" CreationDate="2017-06-27T02:46:40.427" UserId="182" Text="###Idea A:&#xD;&#xA;&#xD;&#xA;Draw an invisible mesh that will occlude the points we don't want.&#xD;&#xA;&#xD;&#xA; 1. Create a mesh from the point cloud.&#xD;&#xA; 2. Render that mesh to a depth buffer but not to the color buffer.&#xD;&#xA; 3. Render the point cloud using a depth test &quot;closer or equal&quot;.&#xD;&#xA;&#xD;&#xA;This approach should give the expected result, but the problem with it is the first part, which is not trivial at all.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;###Idea B:&#xD;&#xA;&#xD;&#xA;Approximate the mesh with fat particles, that are big enough to hide points in the background.&#xD;&#xA;&#xD;&#xA; 1. Pick a size that is roughly the typical distance between two points.&#xD;&#xA; 2. Use that size as a particle diameter.&#xD;&#xA; 3. Render the point clouds using such large particles, to a depth buffer but not to the color buffer. Maybe offset that point cloud a little, so it's a bit farther from the camera.&#xD;&#xA; 4. Render the point cloud using points this time, and using a depth test &quot;closer or equal&quot;.&#xD;&#xA;&#xD;&#xA;This method should be a lot simpler to implement than A, because there is no need to triangulate anymore. The result will not be perfect though: some points that should be visible might disappear, and some that shouldn't be visible will remain visible. Tweaking the particle diameter and offset will yield different results.&#xD;&#xA;&#xD;&#xA;###Idea C:&#xD;&#xA;&#xD;&#xA;As a very cheap trick, just render the point cloud with a fog function. The farther points are from the camera, the less visible they are. This method won't hide any point, but still help reading the volume." ContentLicense="CC BY-SA 3.0" />
  <row Id="14341" PostHistoryTypeId="50" PostId="4917" RevisionGUID="55f85a48-aba4-4aa1-91c9-636dbe131f1f" CreationDate="2017-06-27T11:10:21.657" UserId="-1" />
  <row Id="14342" PostHistoryTypeId="2" PostId="5296" RevisionGUID="e5100515-6286-4c99-aa2c-7330c2788b93" CreationDate="2017-06-27T12:22:45.397" UserId="6900" Text="I have a simple test scene setup in a toy software rasterizer.  I have a plane facing the +Z axis at the origin and the camera is facing -Z at Z=2.  Everything works fine and looks good at that orientation but if I turn the camera to face -X it  renders a distorted triangle long after the plane has left the view of the camera.  I have been trying to debug this for weeks and can't find the problem.  I assume I am missing somthing silly, maths are not my strong suit.  I have check my matrix/vector math and it seems good to me.&#xD;&#xA;&#xD;&#xA;Here is the realevent code: NOTE it's emited from the &quot;ReadableC backend&quot; of a toy language so the formating is a little strange.  Also I am fully aware there are important parts of software rasterization that are missing i the implementation.  It has been simplified to isolate the bug.&#xD;&#xA;&#xD;&#xA;[Relevant Source Code][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gist.github.com/Twiebs/3278d2e58d0a51b2d86a101172b2904e" ContentLicense="CC BY-SA 3.0" />
  <row Id="14343" PostHistoryTypeId="1" PostId="5296" RevisionGUID="e5100515-6286-4c99-aa2c-7330c2788b93" CreationDate="2017-06-27T12:22:45.397" UserId="6900" Text="Strange behaviour in simple software rasterizer" ContentLicense="CC BY-SA 3.0" />
  <row Id="14344" PostHistoryTypeId="3" PostId="5296" RevisionGUID="e5100515-6286-4c99-aa2c-7330c2788b93" CreationDate="2017-06-27T12:22:45.397" UserId="6900" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14345" PostHistoryTypeId="2" PostId="5297" RevisionGUID="7c811d5f-73c1-4783-8fb1-da94e21a2491" CreationDate="2017-06-27T13:25:50.940" UserId="6902" Text="I have a question regarding 3D PDF files. &#xD;&#xA;&#xD;&#xA;I have a 3D vector graphics image which is saved as a Product Representation Compact (PRC) file. The PRC file is embedded in a PDF file. I can view and rotate the 3D image in Adobe Acrobat Reader, and it looks beautiful. &#xD;&#xA;&#xD;&#xA;Now, I need to save this image in a 2D file format. In other words, I need to export the view of the 3D image as it appears in Acrobat Reader (from a given point of view) to a 2D file format. The file format could be either bitmap or vector graphics, it is not too important. For instance, I would like to save the image in a PNG- or SVG-file. &#xD;&#xA;&#xD;&#xA;I have to do this because I need the image to be displayed in a graphical user interface (GUI) of a software I am working on. I work in a software company, an the GUI programmers would like me to hand over the image in a 2D file format like PNG or SVG.&#xD;&#xA;&#xD;&#xA;I have tried several approaches to export the view from Acrobat Reader to a 2D file format, but I haven't found a satisfactory solution. I have tried to export the 3D PDF-file to JPEG and PNG using Adobe Acrobat Pro DC. However, the pictures obtained with this method were extremely blurred. I have also tried to print the 3D graphics using the Adobe PDF printer, but this also yields poor results.  &#xD;&#xA;&#xD;&#xA;The only work around I have come up with so far is to make a screen shot when the graphics is shown in Acrobat Reader. This actually works, and I can get a PNG-file, but only at a relatively low solution. In any case, this is hardly a satisfactory solution.  &#xD;&#xA;&#xD;&#xA;My question is: Is there some way that I can obtain a high quality 2D file format from the 3D PDF (PRC-file) format?&#xD;&#xA;&#xD;&#xA;Any input would be highly appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="14346" PostHistoryTypeId="1" PostId="5297" RevisionGUID="7c811d5f-73c1-4783-8fb1-da94e21a2491" CreationDate="2017-06-27T13:25:50.940" UserId="6902" Text="Convert prc-file (3D PDF) to 2D file format" ContentLicense="CC BY-SA 3.0" />
  <row Id="14347" PostHistoryTypeId="3" PostId="5297" RevisionGUID="7c811d5f-73c1-4783-8fb1-da94e21a2491" CreationDate="2017-06-27T13:25:50.940" UserId="6902" Text="|3d|conversion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14351" PostHistoryTypeId="2" PostId="5299" RevisionGUID="86459ad4-8ddf-4efb-8735-c05d4689b8f0" CreationDate="2017-06-28T11:19:37.747" UserId="6908" Text="The title might sound confusing, but this is what I'm trying to achieve:&#xD;&#xA;&#xD;&#xA;[Cartesian bounds of isometric object][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;project to:&#xD;&#xA;&#xD;&#xA;[Isometric bounds of isometric object][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KOqaS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CdpU1.png&#xD;&#xA;&#xD;&#xA;I already have an algorithm in my mind, where we simply detect the corners touching the Cartesian rectangle and calculate the bounds from there, but I just wanted to see if there were more clever ways of solving this problem.&#xD;&#xA;&#xD;&#xA;**Note**&#xD;&#xA;&#xD;&#xA;- It's not a homework&#xD;&#xA;&#xD;&#xA;- I don't want a full answer, just a pointer, wondering if there are more clever ways of solving it.&#xD;&#xA;&#xD;&#xA;- The isometric object can be a rectangle, it's width and height might differ." ContentLicense="CC BY-SA 3.0" />
  <row Id="14352" PostHistoryTypeId="1" PostId="5299" RevisionGUID="86459ad4-8ddf-4efb-8735-c05d4689b8f0" CreationDate="2017-06-28T11:19:37.747" UserId="6908" Text="Rectangle bounds of isometric object to isometric bounds" ContentLicense="CC BY-SA 3.0" />
  <row Id="14353" PostHistoryTypeId="3" PostId="5299" RevisionGUID="86459ad4-8ddf-4efb-8735-c05d4689b8f0" CreationDate="2017-06-28T11:19:37.747" UserId="6908" Text="|computational-geometry|geometry|2d|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14354" PostHistoryTypeId="2" PostId="5300" RevisionGUID="d84c5aca-bcc9-419a-8558-37067c9ba57c" CreationDate="2017-06-28T12:32:45.580" UserId="2040" Text="Is there a public javascript implementation of a color changing algorithm similar to the matrix transform used by image manipulation software (eg gimp, photoshop)? The online tools I've seen only seem to translate RGB into HSV and then alter hue, so they can't change `#00f` blue into `#ffd` pale yellow, for example. Or at least an accessible useful definition of what color space to use and distance definition within that space, so I can implement my own? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14355" PostHistoryTypeId="1" PostId="5300" RevisionGUID="d84c5aca-bcc9-419a-8558-37067c9ba57c" CreationDate="2017-06-28T12:32:45.580" UserId="2040" Text="Public ES6 implementation of color transform that also works on saturation and value/lightness?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14356" PostHistoryTypeId="3" PostId="5300" RevisionGUID="d84c5aca-bcc9-419a-8558-37067c9ba57c" CreationDate="2017-06-28T12:32:45.580" UserId="2040" Text="|transformations|algorithm|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14357" PostHistoryTypeId="5" PostId="5299" RevisionGUID="4e087394-fa97-49dd-8d9f-37f395164855" CreationDate="2017-06-28T13:26:19.820" UserId="2041" Comment="Include the images inline. If people have to click through links to understand the problem, you're much less likely to get answers." Text="The title might sound confusing, but this is what I'm trying to achieve:&#xD;&#xA;&#xD;&#xA;![Cartesian bounds of isometric object][1]&#xD;&#xA;&#xD;&#xA;project to:&#xD;&#xA;&#xD;&#xA;![Isometric bounds of isometric object][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KOqaS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CdpU1.png&#xD;&#xA;&#xD;&#xA;I already have an algorithm in my mind, where we simply detect the corners touching the Cartesian rectangle and calculate the bounds from there, but I just wanted to see if there were more clever ways of solving this problem.&#xD;&#xA;&#xD;&#xA;**Note**&#xD;&#xA;&#xD;&#xA;- It's not a homework&#xD;&#xA;&#xD;&#xA;- I don't want a full answer, just a pointer, wondering if there are more clever ways of solving it.&#xD;&#xA;&#xD;&#xA;- The isometric object can be a rectangle, it's width and height might differ." ContentLicense="CC BY-SA 3.0" />
  <row Id="14358" PostHistoryTypeId="5" PostId="5299" RevisionGUID="97de142d-85c1-4232-ae37-3e29052ba154" CreationDate="2017-06-28T15:14:37.527" UserId="6908" Comment="deleted 5 characters in body" Text="This might sound confusing, but this is what I'm trying to achieve:&#xD;&#xA;&#xD;&#xA;![Cartesian bounds of isometric object][1]&#xD;&#xA;&#xD;&#xA;project to:&#xD;&#xA;&#xD;&#xA;![Isometric bounds of isometric object][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KOqaS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CdpU1.png&#xD;&#xA;&#xD;&#xA;I already have an algorithm in my mind, where we simply detect the corners touching the Cartesian rectangle and calculate the bounds from there, but I just wanted to see if there were more clever ways of solving this problem.&#xD;&#xA;&#xD;&#xA;**Note**&#xD;&#xA;&#xD;&#xA;- It's not a homework&#xD;&#xA;&#xD;&#xA;- I don't want a full answer, just a pointer, wondering if there are more clever ways of solving it.&#xD;&#xA;&#xD;&#xA;- The isometric object can be a rectangle, it's width and height might differ." ContentLicense="CC BY-SA 3.0" />
  <row Id="14359" PostHistoryTypeId="2" PostId="5301" RevisionGUID="ca660129-90d9-45a8-b13b-ba8a199be713" CreationDate="2017-06-28T19:50:22.727" UserId="6785" Text="I'm using OpenGL's stencil test to carve out a semicircular hole in a transition frustum with a cylinder oriented perpendicularly. However as one can see below, while this objective is achieved, the cylinder is still visible through the frustum which shouldn't be the case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[1]: https://i.stack.imgur.com/pmWBD.jpg&#xD;&#xA;&lt;p&gt;&#xD;&#xA;&#xD;&#xA;I'm using the following code fragment that I found at&#xD;&#xA;https://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;      glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;      glEnable(GL_STENCIL_TEST);&#xD;&#xA;      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);&#xD;&#xA;      glDepthMask(GL_FALSE);&#xD;&#xA;      glStencilFunc(GL_NEVER, 1, 0xFF);&#xD;&#xA;      glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);  // draw 1s on test fail (always)&#xD;&#xA;    &#xD;&#xA;      // draw stencil pattern&#xD;&#xA;      glStencilMask(0xFF);&#xD;&#xA;      glClear(GL_STENCIL_BUFFER_BIT);  // needs mask=0xFF&#xD;&#xA;      DRAW_CYLINDER ();&#xD;&#xA;    &#xD;&#xA;      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);&#xD;&#xA;      glDepthMask(GL_TRUE);&#xD;&#xA;      glStencilMask(0x00);&#xD;&#xA;      // draw where stencil's value is 0&#xD;&#xA;      glStencilFunc(GL_EQUAL, 0, 0xFF);&#xD;&#xA;      /* (nothing to draw) */&#xD;&#xA;      // draw only where stencil's value is 1&#xD;&#xA;      glStencilFunc(GL_EQUAL, 1, 0xFF);&#xD;&#xA;    &#xD;&#xA;      DRAW_FRUSTUM();&#xD;&#xA;    &#xD;&#xA;      glDisable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;Moreover I've found that the results are insensitive to the parameters of the **glStencilOp**  and **DepthMask** commands. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14360" PostHistoryTypeId="1" PostId="5301" RevisionGUID="ca660129-90d9-45a8-b13b-ba8a199be713" CreationDate="2017-06-28T19:50:22.727" UserId="6785" Text="Honouring Depth Test with Stencil Test" ContentLicense="CC BY-SA 3.0" />
  <row Id="14361" PostHistoryTypeId="3" PostId="5301" RevisionGUID="ca660129-90d9-45a8-b13b-ba8a199be713" CreationDate="2017-06-28T19:50:22.727" UserId="6785" Text="|opengl|stencil-test|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14362" PostHistoryTypeId="5" PostId="5301" RevisionGUID="26feedc9-4a48-4538-8445-76f1de29e584" CreationDate="2017-06-28T20:35:37.760" UserId="6785" Comment="added 218 characters in body" Text="I'm using OpenGL's stencil test to carve out a semicircular hole in a transition frustum with a cylinder oriented perpendicularly. However as one can see below, while this objective is achieved, the cylinder is still visible through the frustum which shouldn't be the case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[1]: https://i.stack.imgur.com/pmWBD.jpg&#xD;&#xA;&lt;p&gt;&#xD;&#xA;&#xD;&#xA;I'm using the following code fragment that I found at&#xD;&#xA;https://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;      glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;      glEnable(GL_STENCIL_TEST);&#xD;&#xA;      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);&#xD;&#xA;      glDepthMask(GL_FALSE);&#xD;&#xA;      glStencilFunc(GL_NEVER, 1, 0xFF);&#xD;&#xA;      glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);  // draw 1s on test fail (always)&#xD;&#xA;    &#xD;&#xA;      // draw stencil pattern&#xD;&#xA;      glStencilMask(0xFF);&#xD;&#xA;      glClear(GL_STENCIL_BUFFER_BIT);  // needs mask=0xFF&#xD;&#xA;      DRAW_CYLINDER ();&#xD;&#xA;    &#xD;&#xA;      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);&#xD;&#xA;      glDepthMask(GL_TRUE);&#xD;&#xA;      glStencilMask(0x00);&#xD;&#xA;      // draw where stencil's value is 0&#xD;&#xA;      glStencilFunc(GL_EQUAL, 0, 0xFF);&#xD;&#xA;      /* (nothing to draw) */&#xD;&#xA;      // draw only where stencil's value is 1&#xD;&#xA;      glStencilFunc(GL_EQUAL, 1, 0xFF);&#xD;&#xA;    &#xD;&#xA;      DRAW_FRUSTUM();&#xD;&#xA;    &#xD;&#xA;      glDisable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;Moreover I've found that the results are insensitive to the parameters of the **glStencilOp**  and **DepthMask** commands. &#xD;&#xA;&#xD;&#xA;I seem to vaguely remember from several years ag that a multi-pass rendering may be required. If so, could someone point me to how to accomplish this with the proper set of command parameters?&#xD;&#xA;&#xD;&#xA;thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14363" PostHistoryTypeId="10" PostId="5300" RevisionGUID="8b0a5974-f444-425a-9a57-f9c528fa728d" CreationDate="2017-06-28T21:52:43.893" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="14365" PostHistoryTypeId="2" PostId="5302" RevisionGUID="2ec311a6-cf1c-4be9-b303-f52ca719d3fa" CreationDate="2017-06-29T03:28:58.073" UserId="6844" Text="I'm creating a SVG editor.&#xD;&#xA;&#xD;&#xA;I have a simple selection tool that appears when I click and move my mouse from a blank area in my SVG.&#xD;&#xA;&#xD;&#xA;My SVG is populated with rectangles that can have a rotation applied to.&#xD;&#xA;&#xD;&#xA;My question is how can I verify if my selection area is over one ore more of these rectangles?&#xD;&#xA;&#xD;&#xA;Here is the kind of render I'm trying to have:&#xD;&#xA;[![selection][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jtAGY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14366" PostHistoryTypeId="1" PostId="5302" RevisionGUID="2ec311a6-cf1c-4be9-b303-f52ca719d3fa" CreationDate="2017-06-29T03:28:58.073" UserId="6844" Text="How can I verify if a selection area is over a shape in SVG?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14367" PostHistoryTypeId="3" PostId="5302" RevisionGUID="2ec311a6-cf1c-4be9-b303-f52ca719d3fa" CreationDate="2017-06-29T03:28:58.073" UserId="6844" Text="|algorithm|vector-graphics|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14368" PostHistoryTypeId="5" PostId="5300" RevisionGUID="9904b0c4-4a96-4f72-8b7e-ddb866b40872" CreationDate="2017-06-29T06:24:15.813" UserId="2040" Comment="Edit to remove request for js implementation" Text="What color changing algorithm similar to the matrix transform used by image manipulation software (eg gimp, photoshop)? The online tools I've seen only seem to translate RGB into HSV and then alter hue, so they can't change `#00f` blue into `#ffd` pale yellow, for example, so examining their source doesn't really help. Specifically, what color space and distance definition do these algorithms use? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14369" PostHistoryTypeId="4" PostId="5300" RevisionGUID="9904b0c4-4a96-4f72-8b7e-ddb866b40872" CreationDate="2017-06-29T06:24:15.813" UserId="2040" Comment="Edit to remove request for js implementation" Text="Color transform algorithm (that also works on saturation and value/lightness)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14370" PostHistoryTypeId="5" PostId="5300" RevisionGUID="f9cd2f04-15e4-4fe0-8b1e-04985c23eb12" CreationDate="2017-06-29T08:56:36.437" UserId="2040" Comment="added 100 characters in body" Text="To change particular colors in an image, generally you multiply the RGB by a transformation matrix. Image manipulation programs such as gimp &amp; photoshop have a selective color change function that allows a user to convert pixels within a certain &quot;distance&quot; to the original color in some color space to a new color. Eg, changing `#00f` blue into `#ffd` pale yellow. &#xD;&#xA;&#xD;&#xA;I'm trying to implement such a function in a `&lt;canvas&gt;`. What color space and distance definition do these algorithms typically use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14371" PostHistoryTypeId="5" PostId="5300" RevisionGUID="64d3f6e5-61ab-4663-8349-b53156585783" CreationDate="2017-06-29T11:21:19.377" UserId="2040" Comment="added 56 characters in body" Text="To change particular colors in an image, generally you multiply the RGB by a transformation matrix. Image manipulation programs such as gimp &amp; photoshop have a selective color change function that allows a user to convert pixels within a certain &quot;distance&quot; to the original color in some color space to a new color. Eg, changing `#00f` blue into `#ffd` pale yellow. &#xD;&#xA;&#xD;&#xA;I'm trying to implement such a function in a `&lt;canvas&gt;`. What color space and distance definition do these algorithms typically use, and then how do they compute the transformation matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14372" PostHistoryTypeId="2" PostId="5303" RevisionGUID="fc5df520-e07e-4260-bf6e-1f9ef57e8d09" CreationDate="2017-06-29T11:37:48.937" UserId="2138" Text="I'm currently trying to implement a fast algorithm for KD-Tree construction using SAH, as described in this paper: &#xD;&#xA;&#xD;&#xA;[On building fast KD-trees for ray tracing, and on doing that in O(N log N)][1]&#xD;&#xA;&#xD;&#xA;I found one already working implementation by gentlemen Miguel Granados and Richard Socher from the University of Saarland (even though this code does not implement the final O(N log N) algorithm, but a slightly slower O(N log^2 N), which is also described in the paper ). The implementation can be found [here][2]. &#xD;&#xA;&#xD;&#xA;However, I'm not entirely certain their implementation is correct. What makes me particularly unsure is this part:&#xD;&#xA;&#xD;&#xA;    // get primitives's clipped bounding box&#xD;&#xA;	Box clipTriangleToBox(Primitive* t, const Box&amp; V) const {&#xD;&#xA;		Box b = t-&gt;CalcBounds(); // calculates the triangle's AABB&#xD;&#xA;		for(int k=0; k&lt;3; k++) {&#xD;&#xA;			if(V.min[k] &gt; b.min[k])&#xD;&#xA;				b.min[k] = V.min[k];&#xD;&#xA;			if(V.max[k] &lt; b.max[k])&#xD;&#xA;				b.max[k] = V.max[k];&#xD;&#xA;		}&#xD;&#xA;		assert(V.contains(b));&#xD;&#xA;		return b;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This code should return a conservative Axis-Aligned Bounding Box of the given triangle, which is clipped by the given box/voxel, but I'm certain this code will not compute these AABBs correctly, since this case, which is correctly evaluated:&#xD;&#xA;&#xD;&#xA;[![correctly clipped AABB][3]][3]&#xD;&#xA;&#xD;&#xA;( Source of the image [here][4] )&#xD;&#xA;&#xD;&#xA;will be incorrectly evaluated as this:&#xD;&#xA;&#xD;&#xA;[![wrong case][5]][5]&#xD;&#xA;&#xD;&#xA;The output seems to be only a conjunction of AABBs, rather than a real conservative AABB. This, of course, makes the algorithm either crash at deeper levels of KD-Tree construction (with small voxels compared to sizes of the scene triangles) or, in most cases, halt prematurely. I've been trying to find an algorithm that evaluates these cases correctly, but I do not seem to be successful.&#xD;&#xA;&#xD;&#xA;Are my assumptions correct? And if yes, would anyone happen to know of an algorithm which would correctly evaluate the conservative AABB, given the triangle and the voxel?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://dcgi.felk.cvut.cz/publications/2006/wald-rt-fkd&#xD;&#xA;  [2]: http://www.socher.org/uploads/Main/RenderingCompetitionSocherGranados/src/SAHKdtree.h&#xD;&#xA;  [3]: https://i.stack.imgur.com/OB1iB.png&#xD;&#xA;  [4]: https://stackoverflow.com/questions/34653134/conservative-aabb-for-voxel-triangle-intersection&#xD;&#xA;  [5]: https://i.stack.imgur.com/LdCcn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14373" PostHistoryTypeId="1" PostId="5303" RevisionGUID="fc5df520-e07e-4260-bf6e-1f9ef57e8d09" CreationDate="2017-06-29T11:37:48.937" UserId="2138" Text="Computation of conservative AABB for clipped triangle" ContentLicense="CC BY-SA 3.0" />
  <row Id="14374" PostHistoryTypeId="3" PostId="5303" RevisionGUID="fc5df520-e07e-4260-bf6e-1f9ef57e8d09" CreationDate="2017-06-29T11:37:48.937" UserId="2138" Text="|raytracing|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14375" PostHistoryTypeId="50" PostId="4760" RevisionGUID="3b304a44-65fa-40f5-847c-1f1e3bf24136" CreationDate="2017-06-29T12:14:58.700" UserId="-1" />
  <row Id="14376" PostHistoryTypeId="11" PostId="5300" RevisionGUID="30fc59e1-e9c4-44a4-a148-5ecd57c25e96" CreationDate="2017-06-29T12:51:46.923" UserId="2041" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="14378" PostHistoryTypeId="2" PostId="5304" RevisionGUID="5854f3c4-4fd2-46b3-bc41-b7a9229ae924" CreationDate="2017-06-29T13:28:24.047" UserId="6806" Text="Let $I$ = the value of integration and $p$ = probability distribution.&#xD;&#xA;&#xD;&#xA;The estimator is denoted as $\left\langle I \right &gt;$ and is&#xD;&#xA;$$\left\langle I \right &gt;=\frac{1}{N}\sum_{i=1}^{N}\frac{f(x_i)}{p(x_i)}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The expected value of this estimator is computed as follows:&#xD;&#xA;&#xD;&#xA;$$E[\left\langle I \right &gt;] = E[\frac{1}{N}\sum_{i=1}^{N}\frac{f(x_i)}{p(x_i)}]$$&#xD;&#xA;&#xD;&#xA;$$\qquad \qquad  \space \space \space \space = \frac{1}{N}E[\sum_{i=1}^{N}\frac{f(x_i)}{p(x_i)}]\cdots(1)$$&#xD;&#xA;&#xD;&#xA;$$ \qquad \qquad\qquad\quad= \frac{1}{N}N\int\frac{f(x)}{p(x)}p(x)dx\cdots(2)$$&#xD;&#xA;&#xD;&#xA;$$ = \int f(x)dx \space \space$$&#xD;&#xA;$$ = I\qquad\qquad \space$$&#xD;&#xA;&#xD;&#xA;I wonder why the two equation, $(1)$ and $(2)$, are equal??&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14379" PostHistoryTypeId="1" PostId="5304" RevisionGUID="5854f3c4-4fd2-46b3-bc41-b7a9229ae924" CreationDate="2017-06-29T13:28:24.047" UserId="6806" Text="Monte Carlo Integration" ContentLicense="CC BY-SA 3.0" />
  <row Id="14380" PostHistoryTypeId="3" PostId="5304" RevisionGUID="5854f3c4-4fd2-46b3-bc41-b7a9229ae924" CreationDate="2017-06-29T13:28:24.047" UserId="6806" Text="|mathematics|physically-based|pbr|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14381" PostHistoryTypeId="2" PostId="5305" RevisionGUID="d93a0d97-94bc-4753-b2ac-59d443da9f94" CreationDate="2017-06-29T13:48:38.200" UserId="6915" Text="The Diffuse, specular and Reflection terms have lead to a lot of confusion because they have been commonly used to describe different lighting processes along the CG history. &#xD;&#xA;&#xD;&#xA;to clarify this is use my own vocabulary made up of different terms i picked up here and there:&#xD;&#xA;&#xD;&#xA;_________________&#xD;&#xA;&#xD;&#xA;**1- Surface Reflectance**: &#xD;&#xA; &#xD;&#xA; - could correspond to specular map in the old system&#xD;&#xA; - Correspond to the fresnel reflection part of the BRDF model for the dielectric materials and to the global reflection for the metallic ones.&#xD;&#xA;&#xD;&#xA;**Surface relfectance process**: the light is &quot;bouncing&quot; off the surface without any transmission inside the material or micro subsurface scattering involved in the process (no refraction, no absorbtion).&#xD;&#xA;**Light color information remain inchanged during surface reflection process except for some precise cases (colored metallic reflection, shimmering)**&#xD;&#xA;&#xD;&#xA;**1.1 - Rough surface reflectance**: is light &quot;bouncing&quot; off a rough material (micro facets) in a more or less evenly distributed direction.&#xD;&#xA;&#xD;&#xA;**1.2 - smooth surface reflectance**: is light &quot;bouncing&quot; off a glossy or smooth material in an more or less oriented direction.&#xD;&#xA;&#xD;&#xA;__________&#xD;&#xA;     &#xD;&#xA;**2 - Body reflectance**&#xD;&#xA;&#xD;&#xA;- correspond to the diffuse in the old system&#xD;&#xA;&#xD;&#xA;-  correspond to the basecolor or albedo map in the new system.&#xD;&#xA;&#xD;&#xA;**Body Reflectance process**: The light hitting the surface is first being transmitted in the interior of the object and then may be absorbed, further scattered and reflected, and in some cases exit the material again. It involve micro sub-subsurface scattering from internal irregularities.&#xD;&#xA;**Light color information is changed during the absorbtion steps of the body relfectance process.** And if the light manage to get out of the material again, it will transmit its color information.&#xD;&#xA;The body reflectance process is not applyable to metallic material as they only totally absorb or surface-reflect light depending on its wave lenghts.&#xD;&#xA;&#xD;&#xA;Body-reflectance will not be influenced by material surface smoothness as there is scattering involved inside the material no matter the surface, except maybe for transparent materials where there is mostly absorbtion process involved (no light deviation) and very few scattering. Then when going out again, the surface roughness could really influence if these light rays are going out parallels or scattered.&#xD;&#xA;&#xD;&#xA;*Micro subsurface scattering is different than global subsurface scattering as,  for a matter of simplification through approximation, the light is considered as going out of the material at the same exact point it went in.*&#xD;&#xA;&#xD;&#xA;----------------------------&#xD;&#xA;&#xD;&#xA;Ok now, what i've understand from this naming confusion:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1 - concerning the diffuse reflection**&#xD;&#xA;&#xD;&#xA;What we call usually call **diffuse reflection** is the mechanism that include **surface rough reflectance** and **body reflectance** for a rough dielectric surface.&#xD;&#xA;But in some case the term **diffuse reflection** can be used to describe only the **surface reflectance** part when opposed to the transmission process.&#xD;&#xA;&#xD;&#xA;Concerning Metallic materials, diffuse reflection concern, as a matter of fact, only rough surface reflectance. In case of smooth metallic material, the term diffuse reflection is replaced by specular reflection or direct reflection.&#xD;&#xA;&#xD;&#xA;When talking about smooth dielectric material, there are still diffusing processes, in the sense that the light transmitted into the material is still scattered when goign out of it (body-reflectance), but the surface-reflectance part of it could be called specular or direct reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2 - Concerning the albedo**&#xD;&#xA;&#xD;&#xA;In the physicist field, Albedo seems to be the ratio between reflected light intensity (surface-reflectance + body-reflectance) and incident light. So it is a one dimentionnal value.&#xD;&#xA;In CG, in the other hand, we view albedo as a three dimentional value in RGB which correspond to the traditionnal &quot;diffuse&quot; of the old system and to the &quot;baseColor&quot; of the metall/roughness workflow.&#xD;&#xA;&#xD;&#xA;But in the physicist way of the term, albedo also cover the surface-reflectance part of the light re-emmission (fresnel reflection).&#xD;&#xA;&#xD;&#xA;In the metall/roughness workflow though, BaseColor doesn't have any incidence onto the fresnel reflection wich is directly embedded into the shaders. So BaseColor is basically the body-reflectance RGB value for the Dielectric material and the surface relfectance RGB value being surface-reflected by the metallic material (being &quot;Surface-reflected&quot;, but in a colored way because of the conductive property of the metals and their cristalline organisation combined).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is all really confusing indeed... and i'm not even sure that i entirely get it and i'm tired now..&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14382" PostHistoryTypeId="5" PostId="5305" RevisionGUID="1f9c5319-c559-490d-bef8-4d9d034676f8" CreationDate="2017-06-29T13:55:48.037" UserId="6915" Comment="added 216 characters in body" Text="The Diffuse, specular and Reflection terms have lead to a lot of confusion because they have been commonly used to describe different lighting processes along the CG history and sometimes diverge from their scientific usage. &#xD;&#xA;&#xD;&#xA;to clarify this is use my own vocabulary made up of different terms i picked up here and there:&#xD;&#xA;&#xD;&#xA;_________________&#xD;&#xA;&#xD;&#xA;**1- Surface Reflectance**: &#xD;&#xA; &#xD;&#xA; - could correspond to specular map in the old system&#xD;&#xA; - Correspond to the fresnel reflection part of the BRDF model for the dielectric materials and to the global reflection for the metallic ones.&#xD;&#xA;&#xD;&#xA;**Surface relfectance process**: the light is &quot;bouncing&quot; off the surface without any transmission inside the material or micro subsurface scattering involved in the process (no refraction, no absorbtion).&#xD;&#xA;**Light color information remain inchanged during surface reflection process except for some precise cases (colored metallic reflection, shimmering)**&#xD;&#xA;&#xD;&#xA;**1.1 - Rough surface reflectance**: is light &quot;bouncing&quot; off a rough material (micro facets) in a more or less evenly distributed direction.&#xD;&#xA;&#xD;&#xA;**1.2 - smooth surface reflectance**: is light &quot;bouncing&quot; off a glossy or smooth material in an more or less oriented direction.&#xD;&#xA;&#xD;&#xA;__________&#xD;&#xA;     &#xD;&#xA;**2 - Body reflectance**&#xD;&#xA;&#xD;&#xA;- correspond to the diffuse in the old system&#xD;&#xA;&#xD;&#xA;-  correspond to the basecolor or albedo map in the new system.&#xD;&#xA;&#xD;&#xA;**Body Reflectance process**: The light hitting the surface is first being transmitted in the interior of the object and then may be absorbed, further scattered and reflected, and in some cases exit the material again. It involve micro sub-subsurface scattering from internal irregularities.&#xD;&#xA;**Light color information is changed during the absorbtion steps of the body relfectance process.** And if the light manage to get out of the material again, it will transmit its color information.&#xD;&#xA;The body reflectance process is not applyable to metallic material as they only totally absorb or surface-reflect light depending on its wave lenghts.&#xD;&#xA;&#xD;&#xA;Body-reflectance will not be influenced by material surface smoothness as there is scattering involved inside the material no matter the surface, except maybe for transparent materials where there is mostly absorbtion process involved (no light deviation) and very few scattering. Then when going out again, the surface roughness could really influence if these light rays are going out parallels or scattered.&#xD;&#xA;&#xD;&#xA;*Micro subsurface scattering is different than global subsurface scattering as,  for a matter of simplification through approximation, the light is considered as going out of the material at the same exact point it went in. This is a just what makes that regular dielectric objects have color; there must be transmission, then absorbtion and micro scattering, then re-transmission outside of the material in order to get dielectric's color*&#xD;&#xA;&#xD;&#xA;----------------------------&#xD;&#xA;&#xD;&#xA;Ok now, what i've understand from this naming confusion:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1 - concerning the diffuse reflection**&#xD;&#xA;&#xD;&#xA;What we call usually call **diffuse reflection** is the mechanism that include **surface rough reflectance** and **body reflectance** for a rough dielectric surface.&#xD;&#xA;But in some case the term **diffuse reflection** can be used to describe only the **surface reflectance** part when opposed to the transmission process.&#xD;&#xA;&#xD;&#xA;Concerning Metallic materials, diffuse reflection concern, as a matter of fact, only rough surface reflectance. In case of smooth metallic material, the term diffuse reflection is replaced by specular reflection or direct reflection (which add to the confusion as specular is used here to mean &quot;sharp&quot;).&#xD;&#xA;&#xD;&#xA;When talking about smooth dielectric material, there are still diffusing processes, in the sense that the light transmitted into the material is still scattered when goign out of it (body-reflectance), but the surface-reflectance part of it could be called specular or direct reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2 - Concerning the albedo**&#xD;&#xA;&#xD;&#xA;In the physicist field, Albedo seems to be the ratio between reflected light intensity (surface-reflectance + body-reflectance) and incident light. So it is a one dimentionnal value.&#xD;&#xA;In CG, in the other hand, we view albedo as a three dimentional value in RGB which correspond to the traditionnal &quot;diffuse&quot; of the old system and to the &quot;baseColor&quot; of the metall/roughness workflow.&#xD;&#xA;&#xD;&#xA;But in the physicist way of the term, albedo also cover the surface-reflectance part of the light re-emmission (fresnel reflection).&#xD;&#xA;&#xD;&#xA;In the metall/roughness workflow though, BaseColor doesn't have any incidence onto the fresnel reflection wich is directly embedded into the shaders. So BaseColor is basically the body-reflectance RGB value for the Dielectric material and the surface relfectance RGB value being surface-reflected by the metallic material (being &quot;Surface-reflected&quot;, but in a colored way because of the conductive property of the metals and their cristalline organisation combined).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is all really confusing indeed... and i'm not even sure that i entirely get it and i'm tired now..&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14383" PostHistoryTypeId="5" PostId="5305" RevisionGUID="ccca5afe-e376-4f23-8892-43653d6496f9" CreationDate="2017-06-29T14:31:08.853" UserId="6915" Comment="added 121 characters in body" Text="The Diffuse, specular and Reflection terms have lead to a lot of confusion because they have been commonly used to describe different lighting processes along the CG history and sometimes diverge from their scientific usage. &#xD;&#xA;&#xD;&#xA;to clarify this I is use my own vocabulary made up of different terms i picked up here and there:&#xD;&#xA;&#xD;&#xA;_________________&#xD;&#xA;&#xD;&#xA;**1- Surface Reflectance**: &#xD;&#xA; &#xD;&#xA; - could correspond to specular map in the old system&#xD;&#xA; - Correspond to the fresnel reflection part of the BRDF model for the dielectric materials and to the global reflection for the metallic ones.&#xD;&#xA;&#xD;&#xA;**The Surface-Relfectance process description**: the light is &quot;bouncing&quot; off the surface without any transmission inside the material or micro subsurface scattering involved in the process (no refraction, no absorbtion).&#xD;&#xA;**Light color information remain inchanged during surface reflection process except for some precise cases (colored metallic reflection, shimmering)**&#xD;&#xA;&#xD;&#xA;**1.1 - Rough surface reflectance**: is light &quot;bouncing&quot; off a rough material (micro facets) in a more or less evenly distributed direction.&#xD;&#xA;&#xD;&#xA;**1.2 - smooth surface reflectance**: is light &quot;bouncing&quot; off a glossy or smooth material in an more or less oriented direction.&#xD;&#xA;&#xD;&#xA;__________&#xD;&#xA;     &#xD;&#xA;**2 - Body reflectance**&#xD;&#xA;&#xD;&#xA;- correspond to the diffuse in the old system&#xD;&#xA;&#xD;&#xA;-  correspond to the basecolor or albedo map in the new system.&#xD;&#xA;&#xD;&#xA;**The Body-Reflectance process description**: The light hitting the surface that is *not* surface-reflected is first being transmitted in the interior of the object and then may be absorbed, further scattered and reflected, and in some cases exit the material again. It involve micro sub-subsurface scattering from internal irregularities.&#xD;&#xA;**Light color information is changed during the absorbtion steps of the body relfectance process.** And if the light manage to get out of the material again, it will transmit its color information.&#xD;&#xA;The body reflectance process is not applyable to metallic material as they only totally absorb or surface-reflect light depending on its wave lenghts.&#xD;&#xA;&#xD;&#xA;Body-reflectance will not be influenced by material surface smoothness as there is scattering involved inside the material no matter the surface, except maybe for transparent materials where there is mostly absorbtion process involved (no light deviation) and very few scattering. Then when going out again, the surface roughness could really influence if these light rays are going out parallels or scattered.&#xD;&#xA;&#xD;&#xA;*Micro subsurface scattering is different than global subsurface scattering as,  for a matter of simplification through approximation, the light is considered as going out of the material at the same exact point it went in. This is a just what makes that regular dielectric objects have color; there must be transmission, then absorbtion and micro scattering, then re-transmission outside of the material in order to get dielectric's color*&#xD;&#xA;&#xD;&#xA;----------------------------&#xD;&#xA;&#xD;&#xA;Ok now, what i've understand from this naming confusion:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1 - concerning the diffuse reflection**&#xD;&#xA;&#xD;&#xA;What we call usually call **diffuse reflection** is the mechanism that include **surface rough reflectance** and **body reflectance** for a rough dielectric surface.&#xD;&#xA;But in some case the term **diffuse reflection** can be used to describe only the **surface reflectance** part when opposed to the transmission process.&#xD;&#xA;&#xD;&#xA;Concerning Metallic materials, diffuse reflection concern, as a matter of fact, only rough surface reflectance. In case of smooth metallic material, the term diffuse reflection is replaced by specular reflection or direct reflection (which add to the confusion as specular is used here to mean &quot;sharp&quot;).&#xD;&#xA;&#xD;&#xA;When talking about smooth dielectric material, there are still diffusing processes, in the sense that the light transmitted into the material is still scattered when goign out of it (body-reflectance), but the surface-reflectance part of it could be called specular or direct reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2 - Concerning the albedo**&#xD;&#xA;&#xD;&#xA;In the physicist field, Albedo seems to be the ratio between reflected light intensity (surface-reflectance + body-reflectance) and incident light. So it is a one dimentionnal value.&#xD;&#xA;In CG, in the other hand, we view albedo as a three dimentional value in RGB which correspond to the traditionnal &quot;diffuse&quot; of the old system and to the &quot;baseColor&quot; of the metall/roughness workflow.&#xD;&#xA;&#xD;&#xA;But in the physicist way of the term, albedo also cover the surface-reflectance part of the light re-emmission (fresnel reflection).&#xD;&#xA;&#xD;&#xA;In the metall/roughness workflow though, BaseColor doesn't have any incidence onto the fresnel reflection wich is directly embedded into the shaders. So BaseColor is basically the body-reflectance RGB value for the Dielectric material and the surface relfectance RGB value being surface-reflected by the metallic material (being &quot;Surface-reflected&quot;, but in a colored way because of the conductive property of the metals and their cristalline organisation combined).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is all really confusing indeed... and i'm not even sure that i entirely get it&#xD;&#xA;&#xD;&#xA;One of the doc I'm refering to along with substance PBR guidelines:&#xD;&#xA;http://creativecoding.evl.uic.edu/courses/cs488/reportsA/brdf.pdf&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14384" PostHistoryTypeId="5" PostId="5305" RevisionGUID="8157117c-1a57-431e-93c5-16882698e70b" CreationDate="2017-06-29T14:45:13.610" UserId="6915" Comment="added 132 characters in body" Text="The Diffuse, specular and Reflection terms have lead to a lot of confusion because they have been commonly used to describe different lighting processes along the CG history and sometimes diverge from their scientific usage. &#xD;&#xA;&#xD;&#xA;to clarify this I is use my own vocabulary made up of different terms i picked up here and there:&#xD;&#xA;&#xD;&#xA;_________________&#xD;&#xA;&#xD;&#xA;**1- Surface Reflectance**: &#xD;&#xA; &#xD;&#xA; - could correspond to specular map in the old system&#xD;&#xA; - Correspond to the fresnel reflection part of the BRDF model for the dielectric materials and to the global reflection for the metallic ones.&#xD;&#xA;&#xD;&#xA;**The Surface-Relfectance process description**: the light is &quot;bouncing&quot; off the surface without any transmission inside the material or micro subsurface scattering involved in the process (no refraction, no absorbtion).&#xD;&#xA;**Light color information remain inchanged during surface reflection process except for some precise cases (colored metallic reflection, shimmering)**&#xD;&#xA;&#xD;&#xA;**1.1 - Rough surface reflectance**: is light &quot;bouncing&quot; off a rough material (micro facets) in a more or less evenly distributed direction.&#xD;&#xA;&#xD;&#xA;**1.2 - smooth surface reflectance**: is light &quot;bouncing&quot; off a glossy or smooth material in an more or less oriented direction.&#xD;&#xA;&#xD;&#xA;__________&#xD;&#xA;     &#xD;&#xA;**2 - Body reflectance**&#xD;&#xA;&#xD;&#xA;- correspond to the diffuse in the old system&#xD;&#xA;&#xD;&#xA;-  correspond to the basecolor or albedo map in the new system.&#xD;&#xA;&#xD;&#xA;**The Body-Reflectance process description**: The light hitting the surface that is *not* surface-reflected is first being transmitted in the interior of the object and then may be absorbed, further scattered and reflected, and in some cases exit the material again. It involve micro sub-subsurface scattering from internal irregularities.&#xD;&#xA;**Light color information is changed during the absorbtion steps of the body relfectance process.** And if the light manage to get out of the material again, it will transmit its color information.&#xD;&#xA;The body reflectance process is not applyable to metallic material as they only totally absorb or surface-reflect light depending on its wave lenghts.&#xD;&#xA;&#xD;&#xA;Body-reflectance will not be influenced by material surface smoothness as there is scattering involved inside the material no matter the surface, except maybe for transparent materials where there is mostly absorbtion process involved (no light deviation) and very few scattering. Then when going out again, the surface roughness could really influence if these light rays are going out parallels or scattered.&#xD;&#xA;&#xD;&#xA;*Micro subsurface scattering is different than global subsurface scattering as,  for a matter of simplification through approximation, the light is considered as going out of the material at the same exact point it went in. This is a just what makes that regular dielectric objects have color; there must be transmission, then absorbtion and micro scattering, then re-transmission outside of the material in order to get dielectric's color*&#xD;&#xA;&#xD;&#xA;----------------------------&#xD;&#xA;&#xD;&#xA;Ok now, what i've understand from this naming confusion:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1 - concerning the diffuse reflection**&#xD;&#xA;&#xD;&#xA;What we call usually call **diffuse reflection** is the mechanism that include **rough surface-reflectance** and **body-reflectance** for a rough dielectric surface.&#xD;&#xA;But in some case the term **diffuse reflection** can be used to describe only the **surface reflectance** part when opposed to the transmission process.&#xD;&#xA;&#xD;&#xA;Concerning Metallic materials, diffuse reflection concern, as a matter of fact, only rough surface reflectance. In case of smooth metallic material, the term diffuse reflection is replaced by specular reflection or direct reflection (which add to the confusion as specular is used here to mean &quot;sharp&quot;).&#xD;&#xA;&#xD;&#xA;When talking about smooth dielectric material, there are still diffusing processes, in the sense that the light transmitted into the material is still scattered when goign out of it (body-reflectance), but the surface-reflectance part of it could be called specular or direct reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2 - Concerning the albedo**&#xD;&#xA;&#xD;&#xA;In the physicist field, **Albedo** seems to be the **ratio between reflected light intensity (surface-reflectance + body-reflectance) and incident light**. So it is a **one dimentionnal** value.&#xD;&#xA;In CG, in the other hand, we view **albedo** as a **three dimentional value** in RGB which correspond to the traditionnal &quot;diffuse&quot; of the old system and to the &quot;baseColor&quot; of the metall/roughness workflow. In this case albedo would be surface-reflectance + body reflectance for both dielectric and metallic materials.&#xD;&#xA;&#xD;&#xA;But in the physicist way of the term, albedo also cover the surface-reflectance part of the light re-emmission (fresnel reflection).&#xD;&#xA;&#xD;&#xA;In the metall/roughness workflow though, BaseColor doesn't have any incidence onto the fresnel reflection wich is directly embedded into the shaders. So BaseColor is basically the body-reflectance RGB value for the Dielectric material and the surface relfectance RGB value being surface-reflected by the metallic material (being &quot;Surface-reflected&quot;, but in a colored way because of the conductive property of the metals and their cristalline organisation combined).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is all really confusing indeed... and i'm not even sure that i entirely get it&#xD;&#xA;&#xD;&#xA;One of the doc I'm refering to along with substance PBR guidelines:&#xD;&#xA;http://creativecoding.evl.uic.edu/courses/cs488/reportsA/brdf.pdf&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14385" PostHistoryTypeId="5" PostId="5305" RevisionGUID="daba10f7-9c38-4246-b74a-10fe4f7b0f62" CreationDate="2017-06-29T14:51:23.273" UserId="6915" Comment="added 132 characters in body" Text="The Diffuse, specular and Reflection terms have lead to a lot of confusion because they have been commonly used to describe different lighting processes along the CG history and sometimes diverge from their scientific usage. &#xD;&#xA;&#xD;&#xA;to clarify this I is use my own vocabulary made up of different terms i picked up here and there:&#xD;&#xA;&#xD;&#xA;_________________&#xD;&#xA;&#xD;&#xA;**1- Surface Reflectance**: &#xD;&#xA; &#xD;&#xA; - could correspond to specular map in the old system&#xD;&#xA; - Correspond to the fresnel reflection part of the BRDF model for the dielectric materials and to the global reflection for the metallic ones.&#xD;&#xA;&#xD;&#xA;**The Surface-Relfectance process description**: the light is &quot;bouncing&quot; off the surface without any transmission inside the material or micro subsurface scattering involved in the process (no refraction, no absorbtion).&#xD;&#xA;**Light color information remain inchanged during surface reflection process except for some precise cases (colored metallic reflection, shimmering)**&#xD;&#xA;&#xD;&#xA;**1.1 - Rough surface reflectance**: is light &quot;bouncing&quot; off a rough material (micro facets) in a more or less evenly distributed direction.&#xD;&#xA;&#xD;&#xA;**1.2 - smooth surface reflectance**: is light &quot;bouncing&quot; off a glossy or smooth material in an more or less oriented direction.&#xD;&#xA;&#xD;&#xA;__________&#xD;&#xA;     &#xD;&#xA;**2 - Body reflectance**&#xD;&#xA;&#xD;&#xA;- correspond to the diffuse in the old system&#xD;&#xA;&#xD;&#xA;-  correspond to the basecolor or albedo map in the new system.&#xD;&#xA;&#xD;&#xA;**The Body-Reflectance process description**: The light hitting the surface that is *not* surface-reflected is first being transmitted in the interior of the object and then may be absorbed, further scattered and reflected, and in some cases exit the material again. It involve micro sub-subsurface scattering from internal irregularities.&#xD;&#xA;**Light color information is changed during the absorbtion steps of the body relfectance process.** And if the light manage to get out of the material again, it will transmit its color information.&#xD;&#xA;The body reflectance process is not applyable to metallic material as they only totally absorb or surface-reflect light depending on its wave lenghts.&#xD;&#xA;&#xD;&#xA;Body-reflectance will not be influenced by material surface smoothness as there is scattering involved inside the material no matter the surface, except maybe for transparent materials where there is mostly absorbtion process involved (no light deviation) and very few scattering. Then when going out again, the surface roughness could really influence if these light rays are going out parallels or scattered.&#xD;&#xA;&#xD;&#xA;*Micro subsurface scattering is different than global subsurface scattering as,  for a matter of simplification through approximation, the light is considered as going out of the material at the same exact point it went in. This is a just what makes that regular dielectric objects have color; there must be transmission, then absorbtion and micro scattering, then re-transmission outside of the material in order to get dielectric's color*&#xD;&#xA;&#xD;&#xA;----------------------------&#xD;&#xA;&#xD;&#xA;Ok now, what i've understand from this naming confusion:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1 - concerning the diffuse reflection**&#xD;&#xA;&#xD;&#xA;What we call usually call **diffuse reflection** is the mechanism that include **rough surface-reflectance** and **body-reflectance** for a rough dielectric surface.&#xD;&#xA;But in some case the term **diffuse reflection** can be used to describe only the **surface reflectance** part when opposed to the transmission process.&#xD;&#xA;&#xD;&#xA;Concerning Metallic materials, diffuse reflection concern, as a matter of fact, only rough surface reflectance. In case of smooth metallic material, the term diffuse reflection is replaced by specular reflection or direct reflection (which add to the confusion as specular is used here to mean &quot;sharp&quot;).&#xD;&#xA;&#xD;&#xA;When talking about smooth dielectric material, there are still diffusing processes, in the sense that the light transmitted into the material is still scattered when goign out of it (body-reflectance), but the surface-reflectance part of it could be called specular or direct reflection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2 - Concerning the albedo**&#xD;&#xA;&#xD;&#xA;In the physicist field, **Albedo** seems to be the **ratio between reflected light intensity (surface-reflectance + body-reflectance) and incident light**. So it is a **one dimentionnal** value.&#xD;&#xA;In CG, in the other hand, we view **albedo** as a **three dimentional value** in RGB which correspond to the traditionnal &quot;diffuse&quot; of the old system and to the &quot;baseColor&quot; of the metall/roughness workflow. In this case albedo would be, for a metal/roughness workflow the body reflectance for dielectrics and and the Surface-reflectance for metals  **but without the fresnel composant of the fresnel surface reflectance**. &#xD;&#xA;&#xD;&#xA;But in the physicist way of the term, albedo also cover the surface-reflectance part of the light re-emmission (fresnel reflection).&#xD;&#xA;&#xD;&#xA;In the metall/roughness workflow though, BaseColor doesn't have any incidence onto the fresnel reflection wich is directly embedded into the shaders. So BaseColor is basically the body-reflectance RGB value for the Dielectric material and the surface relfectance RGB value being surface-reflected by the metallic material (being &quot;Surface-reflected&quot;, but in a colored way because of the conductive property of the metals and their cristalline organisation combined).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is all really confusing indeed... and i'm not even sure that i entirely get it&#xD;&#xA;&#xD;&#xA;One of the doc I'm refering to along with substance PBR guidelines:&#xD;&#xA;http://creativecoding.evl.uic.edu/courses/cs488/reportsA/brdf.pdf&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14387" PostHistoryTypeId="11" PostId="5263" RevisionGUID="777b18e2-f2ec-4a94-8fd6-210f78eb26b4" CreationDate="2017-06-29T22:07:12.803" UserId="-1" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;},{&quot;Id&quot;:310,&quot;DisplayName&quot;:&quot;RichieSams&quot;},{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;}]}" />
  <row Id="14388" PostHistoryTypeId="2" PostId="5307" RevisionGUID="9d9ef3b9-f647-4eaf-9e2c-b1aa07505823" CreationDate="2017-06-29T23:19:42.447" UserId="6041" Text="How can a diffused(frosted) glass be modelled in path tracing?&#xD;&#xA;&#xD;&#xA;Currently I am able to define a window poly line as a clear glass material where it transmites or reflects the ray. I am not clear though how it should work if the sheet of glass is frosted(diffuses transmission?)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14389" PostHistoryTypeId="1" PostId="5307" RevisionGUID="9d9ef3b9-f647-4eaf-9e2c-b1aa07505823" CreationDate="2017-06-29T23:19:42.447" UserId="6041" Text="How can a diffused(frosted) glass be modelled in path tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="14390" PostHistoryTypeId="3" PostId="5307" RevisionGUID="9d9ef3b9-f647-4eaf-9e2c-b1aa07505823" CreationDate="2017-06-29T23:19:42.447" UserId="6041" Text="|raytracing|pathtracing|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14391" PostHistoryTypeId="2" PostId="5308" RevisionGUID="cd2363a9-31ad-44c2-89b2-d527efc45eaa" CreationDate="2017-06-29T23:35:56.760" UserId="48" Text="In Monte Carlo integration, the samples $x_1, x_2, \ldots x_N$ are [independent, identically-distributed](https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables) random variables. This implies they all have the same expectation value. The derived quantities $f(x_i)/p(x_i)$ also all have the same expectation value. So the expectation of a sum of $N$ of these is the same as $N$ times the expectation of any one of them:&#xD;&#xA;$$E\left[ \sum_{i=1}^N \frac{f(x_i)}{p(x_i)} \right] = N \cdot E\left[\frac{f(x_1)}{p(x_1)}\right]$$&#xD;&#xA;(I picked $x_1$ arbitrarily.)&#xD;&#xA;&#xD;&#xA;Then, the expectation value of a continuous random variable is found by integrating over its probability measure:&#xD;&#xA;$$E\left[\frac{f(x_1)}{p(x_1)}\right] = \int_{\text{domain of }p(x)} \frac{f(x)}{p(x)} \, p(x) \, dx$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="14392" PostHistoryTypeId="5" PostId="5307" RevisionGUID="aadd92c2-2fd1-44e0-87e2-4d5fccb5f495" CreationDate="2017-06-30T06:16:16.333" UserId="6041" Comment="added 72 characters in body" Text="How can a diffused(frosted) glass be modelled in path tracing?&#xD;&#xA;&#xD;&#xA;Currently I am able to define a window poly line as a clear glass material where it transmites or reflects the ray. I am not clear though how it should work if the sheet of glass is frosted(diffuse transmission?).&#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/gr3jB.gif)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14393" PostHistoryTypeId="5" PostId="5301" RevisionGUID="478a5236-2163-4558-aac6-292786bc9dbd" CreationDate="2017-06-30T07:42:14.163" UserId="209" Comment="Moved Sharat's &quot;answer&quot;, which was really additional clarification, to the question." Text="I'm using OpenGL's stencil test to carve out a semicircular hole in a transition frustum with a cylinder oriented perpendicularly. However as one can see below, while this objective is achieved, the cylinder is still visible through the frustum which shouldn't be the case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&lt;p&gt;&#xD;&#xA;&#xD;&#xA;I'm using the following code fragment that I found at&#xD;&#xA;https://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;      glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;      glEnable(GL_STENCIL_TEST);&#xD;&#xA;      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);&#xD;&#xA;      glDepthMask(GL_FALSE);&#xD;&#xA;      glStencilFunc(GL_NEVER, 1, 0xFF);&#xD;&#xA;      glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);  // draw 1s on test fail (always)&#xD;&#xA;    &#xD;&#xA;      // draw stencil pattern&#xD;&#xA;      glStencilMask(0xFF);&#xD;&#xA;      glClear(GL_STENCIL_BUFFER_BIT);  // needs mask=0xFF&#xD;&#xA;      DRAW_CYLINDER ();&#xD;&#xA;    &#xD;&#xA;      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);&#xD;&#xA;      glDepthMask(GL_TRUE);&#xD;&#xA;      glStencilMask(0x00);&#xD;&#xA;      // draw where stencil's value is 0&#xD;&#xA;      glStencilFunc(GL_EQUAL, 0, 0xFF);&#xD;&#xA;      /* (nothing to draw) */&#xD;&#xA;      // draw only where stencil's value is 1&#xD;&#xA;      glStencilFunc(GL_EQUAL, 1, 0xFF);&#xD;&#xA;    &#xD;&#xA;      DRAW_FRUSTUM();&#xD;&#xA;    &#xD;&#xA;      glDisable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;Moreover I've found that the results are insensitive to the parameters of the **glStencilOp**  and **DepthMask** commands. &#xD;&#xA;&#xD;&#xA;I seem to vaguely remember from several years ag that a multi-pass rendering may be required. If so, could someone point me to how to accomplish this with the proper set of command parameters?&#xD;&#xA;&#xD;&#xA;thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;This is an example of what I'm expecting - The cylinder should cut a hole through the frustum. I've rendered it here by trimming the black cylinder within the frustum so that it just just out past the frustum surface.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pmWBD.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/vcxON.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14396" PostHistoryTypeId="2" PostId="5309" RevisionGUID="ef35d355-3e23-450e-83fd-48a39501dc18" CreationDate="2017-06-30T08:55:13.373" UserId="2041" Text="In a fragment shader, I need to draw a line at a given value of *u*. The shader is applied to a planar polygon mesh that's being drawn in the scene with a perspective camera. (It isn't a full-screen textured quad; that would be easy!)&#xD;&#xA;&#xD;&#xA;The problem is, the thickness of the line is given in screen pixels, not in world units. How can I draw this line in my shader?&#xD;&#xA;&#xD;&#xA;The shader is Cg, but a pseudocode answer outlining the technique is fine." ContentLicense="CC BY-SA 3.0" />
  <row Id="14397" PostHistoryTypeId="1" PostId="5309" RevisionGUID="ef35d355-3e23-450e-83fd-48a39501dc18" CreationDate="2017-06-30T08:55:13.373" UserId="2041" Text="How can I draw a line whose position is given in UV space and its width in screen space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14398" PostHistoryTypeId="3" PostId="5309" RevisionGUID="ef35d355-3e23-450e-83fd-48a39501dc18" CreationDate="2017-06-30T08:55:13.373" UserId="2041" Text="|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14399" PostHistoryTypeId="2" PostId="5310" RevisionGUID="f4885983-355c-41c8-89c5-9e04cac2649f" CreationDate="2017-06-30T11:51:03.603" UserId="2138" Text="I'm writing a raytracer and I'm using the assimp library to load objects. I have an object's material specified in a .mtl file:&#xD;&#xA;&#xD;&#xA;    newmtl rightSphere&#xD;&#xA;    Ka 0.01 0.01 0.01&#xD;&#xA;    Kd 0.01 0.01 0.01&#xD;&#xA;    Ks 0.30 0.30 0.30&#xD;&#xA;    Tf 0.10 0.10 0.10&#xD;&#xA;    Ns 200&#xD;&#xA;    Ni 2.5&#xD;&#xA;    illum 7&#xD;&#xA;&#xD;&#xA;and I'm trying to load this material. I've been mostly successful so far, for example I know that to extract the diffuse component (Kd), I can use&#xD;&#xA;&#xD;&#xA;    aiMesh *mesh = scene-&gt;mMeshes[i];&#xD;&#xA;    aiMaterial *mat = scene-&gt;mMaterials[mesh-&gt;mMaterialIndex];&#xD;&#xA;    aiColor3D color;&#xD;&#xA;    mat-&gt;Get(AI_MATKEY_COLOR_DIFFUSE, color);&#xD;&#xA;		&#xD;&#xA;using the identifiers specified in [here][1]. However, I've been unable to extract the Tf component. I understand that this component defines the coefficient of refracted light per color channel, and I need this value along with the index of refraction (Ni) to get it to work.&#xD;&#xA;&#xD;&#xA;My question is: how can I get the Tf value?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://assimp.sourceforge.net/lib_html/materials.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="14400" PostHistoryTypeId="1" PostId="5310" RevisionGUID="f4885983-355c-41c8-89c5-9e04cac2649f" CreationDate="2017-06-30T11:51:03.603" UserId="2138" Text="Loading a material via assimp" ContentLicense="CC BY-SA 3.0" />
  <row Id="14401" PostHistoryTypeId="3" PostId="5310" RevisionGUID="f4885983-355c-41c8-89c5-9e04cac2649f" CreationDate="2017-06-30T11:51:03.603" UserId="2138" Text="|raytracing|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14402" PostHistoryTypeId="5" PostId="5290" RevisionGUID="1326308a-6534-4c01-b87b-6afcc735191d" CreationDate="2017-06-30T12:20:17.527" UserId="2041" Comment="add some more on where the sin factor comes from." Text="I'm not sure I've correctly understood the question, but here goes.&#xD;&#xA;&#xD;&#xA;You're trying to sample directions uniformly, so you've got $p(\omega)$, which is the probability of getting a particular direction. But what is a direction? You actually need your probability distribution to produce numbers in some representation, and the easiest representation to deal with is lat-long (i.e. two angles). So the thing you actually need to sample from is the probability distribution of pairs of angles. This is what $p(\theta, \phi)$ is: the joint probability of two variables.&#xD;&#xA;&#xD;&#xA;$p(\omega)$ and $p(\theta, \phi)$ mean the same thing geometrically, but the former gives you an abstract *direction* you can't sample from directly, while the latter more usefully gives you two numbers that *represent* a direction.&#xD;&#xA;&#xD;&#xA;The reason for your third bullet point is to do with the point you've made about how it isn't just a single direction. These aren't really functions: they're *distributions*. A direction is infinitesimal, so you can't have a probability of just one direction. What you actually need to do is integrate it over the directions you're interested in.&#xD;&#xA;$$&#xD;&#xA;\int p(\omega)d\omega = \int_0^{2\pi}\int_0^\pi p(\theta, \phi)d\theta d\phi = 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Whichever representation you use, the integral over the hemisphere has to be 1, because it's a probability distribution.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I'm not sure if I need to explain this or if you already understood, but here's the origin of the $sin(\theta)$. When you do the double-integral on the right, you're splitting the problem up into a series of rings, or slices of the unit sphere. Each ring has constant $\theta$ while $\phi$ goes from $0$ to $2\pi$. Also, the area of each individual ring decreases as $\theta$ increases: the ring at the equator is huge, while the last &quot;ring&quot; at the pole is tiny. The area decreases as $sin(\theta)$. Because we want each unit of area of the sphere to have the same probability, we need the smaller rings to get a smaller share of the probability.&#xD;&#xA;&#xD;&#xA;As Florian R. explains, you can do that by including the $sin(\theta)$ factor in the integral, or you can put it inside the definition of $p(\theta, \phi)$ like the book does." ContentLicense="CC BY-SA 3.0" />
  <row Id="14403" PostHistoryTypeId="5" PostId="5303" RevisionGUID="dfbcb3b5-f9f2-4436-b076-e98536c679b3" CreationDate="2017-06-30T13:09:12.537" UserId="231" Comment="Add hover text for acronym. Feel free to edit in a better link - I couldn't find a more specific one" Text="I'm currently trying to implement a fast algorithm for KD-Tree construction using [SAH], as described in this paper: &#xD;&#xA;&#xD;&#xA;[On building fast KD-trees for ray tracing, and on doing that in O(N log N)][1]&#xD;&#xA;&#xD;&#xA;I found one already working implementation by Miguel Granados and Richard Socher from the University of Saarland (even though this code does not implement the final O(N log N) algorithm, but a slightly slower O(N log^2 N), which is also described in the paper). The implementation can be found [here][2]. &#xD;&#xA;&#xD;&#xA;However, I'm not entirely certain their implementation is correct. What makes me particularly unsure is this part:&#xD;&#xA;&#xD;&#xA;    // get primitives's clipped bounding box&#xD;&#xA;	Box clipTriangleToBox(Primitive* t, const Box&amp; V) const {&#xD;&#xA;		Box b = t-&gt;CalcBounds(); // calculates the triangle's AABB&#xD;&#xA;		for(int k=0; k&lt;3; k++) {&#xD;&#xA;			if(V.min[k] &gt; b.min[k])&#xD;&#xA;				b.min[k] = V.min[k];&#xD;&#xA;			if(V.max[k] &lt; b.max[k])&#xD;&#xA;				b.max[k] = V.max[k];&#xD;&#xA;		}&#xD;&#xA;		assert(V.contains(b));&#xD;&#xA;		return b;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This code should return a conservative Axis-Aligned Bounding Box of the given triangle, which is clipped by the given box/voxel, but I'm certain this code will not compute these AABBs correctly, since this case, which is correctly evaluated:&#xD;&#xA;&#xD;&#xA;[![correctly clipped AABB][3]][3]&#xD;&#xA;&#xD;&#xA;( Source of the image [here][4] )&#xD;&#xA;&#xD;&#xA;will be incorrectly evaluated as this:&#xD;&#xA;&#xD;&#xA;[![wrong case][5]][5]&#xD;&#xA;&#xD;&#xA;The output seems to be only a conjunction of AABBs, rather than a real conservative AABB. This, of course, makes the algorithm either crash at deeper levels of KD-Tree construction (with small voxels compared to sizes of the scene triangles) or, in most cases, halt prematurely. I've been trying to find an algorithm that evaluates these cases correctly, but I do not seem to be successful.&#xD;&#xA;&#xD;&#xA;Are my assumptions correct? And if yes, would anyone happen to know of an algorithm which would correctly evaluate the conservative AABB, given the triangle and the voxel?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://dcgi.felk.cvut.cz/publications/2006/wald-rt-fkd&#xD;&#xA;  [2]: http://www.socher.org/uploads/Main/RenderingCompetitionSocherGranados/src/SAHKdtree.h&#xD;&#xA;  [3]: https://i.stack.imgur.com/OB1iB.png&#xD;&#xA;  [4]: https://stackoverflow.com/questions/34653134/conservative-aabb-for-voxel-triangle-intersection&#xD;&#xA;  [5]: https://i.stack.imgur.com/LdCcn.png&#xD;&#xA;&#xD;&#xA;  [SAH]: https://en.wikipedia.org/wiki/Bounding_interval_hierarchy &quot;Surface Area Heuristic&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14404" PostHistoryTypeId="2" PostId="5311" RevisionGUID="02b588e8-0698-45ce-8288-449ea089807e" CreationDate="2017-06-30T13:18:54.557" UserId="6346" Text="I have a grayscale image and want to &quot;resize&quot; it in terms of &quot;pixel concentration&quot;.&lt;br&gt;&#xD;&#xA;That means I divide the source image `x_old * y_old` into `x_new * y_new` sections, and all (sub)pixel grayscale values in each section shall be accumulated to make the new grayscale value.&#xD;&#xA;&#xD;&#xA;Writing two loops also considering the sub pixel parts in each section is easy, but doesn't seem very sophisticatd.&lt;br&gt;&#xD;&#xA;Are there some smart and yet efficient algorithms doing the task?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14405" PostHistoryTypeId="1" PostId="5311" RevisionGUID="02b588e8-0698-45ce-8288-449ea089807e" CreationDate="2017-06-30T13:18:54.557" UserId="6346" Text="Image resize with pixel accumulation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14406" PostHistoryTypeId="3" PostId="5311" RevisionGUID="02b588e8-0698-45ce-8288-449ea089807e" CreationDate="2017-06-30T13:18:54.557" UserId="6346" Text="|transformations|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14407" PostHistoryTypeId="2" PostId="5312" RevisionGUID="083692f7-7b93-43cd-9eef-a168dfadc011" CreationDate="2017-06-30T14:07:29.473" UserId="231" Text="### In pseudocode&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-none --&gt;&#xD;&#xA;&#xD;&#xA;    For each rectangle:&#xD;&#xA;        If the rectangle intersects the selection area, highlight the rectangle&#xD;&#xA;&#xD;&#xA;This is all that is required for a correctly working approach, but there are a number of other things you might need to take into account if this approach performs too slowly. I recommend implementing the simple approach, and once it works correctly you can make gradual improvements if it is not sufficiently smooth and responsive (this may not be necessary unless you have a large number of rectangles or restrictive hardware/software).&#xD;&#xA;&#xD;&#xA;### Examples of refinements if speed is unsatisfactory&#xD;&#xA;&#xD;&#xA;- [Acceleration data structures] such as a grid or space partitioning hierarchy so that not every rectangle needs to be checked. &#xD;&#xA;- Only checking the changed parts of the selection (usually one corner of the selection stays fixed while the opposite corner moves).&#xD;&#xA;- Tracking which rectangles are already selected, and each time the selection changes only checking unselected rectangles if the selection has purely grown, and only checking already selected rectangles if the selection has purely shrunk. It will only be necessary to check both selected and unselected rectangles if the selection has grown in one direction and shrunk in the other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Acceleration data structures]: https://en.wikipedia.org/wiki/Space_partitioning#In_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="14408" PostHistoryTypeId="5" PostId="5312" RevisionGUID="d734cb6a-0d05-4816-9ed2-555472f79713" CreationDate="2017-06-30T14:13:44.483" UserId="231" Comment="added 42 characters in body" Text="### In pseudocode&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-none --&gt;&#xD;&#xA;&#xD;&#xA;    For each rectangle:&#xD;&#xA;        If the rectangle intersects the selection area, highlight the rectangle&#xD;&#xA;&#xD;&#xA;This is all that is required for a correctly working approach, but there are a number of other things you might need to take into account if this approach performs too slowly. I recommend implementing the simple approach, and once it works correctly you can make gradual improvements if it is not sufficiently smooth and responsive (this may not be necessary unless you have a large number of rectangles or restrictive hardware/software).&#xD;&#xA;&#xD;&#xA;### Examples of refinements if speed is unsatisfactory&#xD;&#xA;&#xD;&#xA;- [Acceleration data structures] such as a grid or space partitioning hierarchy so that not every rectangle needs to be checked. &#xD;&#xA;- Only checking the changed parts of the selection (usually one corner of the selection stays fixed while the opposite corner moves).&#xD;&#xA;- Tracking which rectangles are already selected to reduce the checking required each time the selection changes:&#xD;&#xA; - No need to check unselected rectangles if the selection has purely shrunk.&#xD;&#xA; - No need to check already selected rectangles if the selection has purely grown.&#xD;&#xA; - It will only be necessary to check both selected and unselected rectangles if the selection has grown in one direction and shrunk in the other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Acceleration data structures]: https://en.wikipedia.org/wiki/Space_partitioning#In_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="14409" PostHistoryTypeId="5" PostId="5302" RevisionGUID="dea3fb10-2169-418c-b031-bb68717ea3f6" CreationDate="2017-06-30T21:00:24.010" UserId="6844" Comment="added more infos" Text="I'm creating a SVG editor.&#xD;&#xA;&#xD;&#xA;I have a simple selection tool that appears when I click and move my mouse from a blank area in my SVG.&#xD;&#xA;&#xD;&#xA;My SVG is populated with rectangles that can have a rotation applied to.&#xD;&#xA;&#xD;&#xA;- I have the X and Y position applied to a translate function.&#xD;&#xA;- Width and height are easy to calculate based on a scale factor and original dimensions of my rectangle(s).&#xD;&#xA;- My rotation angle is applied in a rotate function&#xD;&#xA;&#xD;&#xA;I know about the [point in polygon](https://en.wikipedia.org/wiki/Point_in_polygon) algorithm but I don't know how to calculate the points of my (rotated) rectangles.&#xD;&#xA;&#xD;&#xA;My question is how can I verify if my selection area is over one ore more of these rectangles and if the PIP algorithm is the best, how can I calculate the points of my rectangle(s)?&#xD;&#xA;&#xD;&#xA;Here is the kind of render I'm trying to have:&#xD;&#xA;[![selection][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jtAGY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14410" PostHistoryTypeId="2" PostId="5313" RevisionGUID="2f146d57-8652-4ffa-882c-32276f3ada5f" CreationDate="2017-06-30T23:36:00.927" UserId="6834" Text="I want to find out how the art brush in adobe illustrator works.  &#xD;&#xA;&#xD;&#xA;it looks like its taking some vector art and applying it to a smooth line &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rN7IF.jpg&#xD;&#xA;&#xD;&#xA;how can i implement this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14411" PostHistoryTypeId="1" PostId="5313" RevisionGUID="2f146d57-8652-4ffa-882c-32276f3ada5f" CreationDate="2017-06-30T23:36:00.927" UserId="6834" Text="adobe illustrator art brush, how does it work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14412" PostHistoryTypeId="3" PostId="5313" RevisionGUID="2f146d57-8652-4ffa-882c-32276f3ada5f" CreationDate="2017-06-30T23:36:00.927" UserId="6834" Text="|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14418" PostHistoryTypeId="2" PostId="5315" RevisionGUID="423a4ff3-3045-44ec-a174-6c5a58aff1b3" CreationDate="2017-07-02T06:49:13.320" UserId="3073" Text="AI_MATKEY_COLOR_TRANSPARENT is used to define the transparent colour and AI_MATKEY_REFRACTI is the refractive index.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14421" PostHistoryTypeId="5" PostId="5313" RevisionGUID="ecb2e96d-d2b4-401e-b41e-d5748bff7758" CreationDate="2017-07-02T07:42:53.087" UserId="6546" Comment="Fixed Spelling Mistakes" Text="I want to find out how the art brush in adobe illustrator works.  &#xD;&#xA;&#xD;&#xA;It looks like it's taking some vector art and applying it to a smooth line. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rN7IF.jpg&#xD;&#xA;&#xD;&#xA;How can I go about implementing this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14422" PostHistoryTypeId="24" PostId="5313" RevisionGUID="ecb2e96d-d2b4-401e-b41e-d5748bff7758" CreationDate="2017-07-02T07:42:53.087" Comment="Proposed by 6546 approved by 48, 231 edit id of 257" ContentLicense="CC BY-SA 3.0" />
  <row Id="14423" PostHistoryTypeId="5" PostId="5302" RevisionGUID="e47cd29d-7f68-4435-8df2-96ec6afdc28a" CreationDate="2017-07-02T07:56:46.723" UserId="231" Comment="Typo" Text="I'm creating an SVG editor.&#xD;&#xA;&#xD;&#xA;I have a simple selection tool that appears when I click and move my mouse from a blank area in my SVG.&#xD;&#xA;&#xD;&#xA;My SVG is populated with rectangles that can have a rotation applied to.&#xD;&#xA;&#xD;&#xA;- I have the X and Y position applied to a translate function.&#xD;&#xA;- Width and height are easy to calculate based on a scale factor and original dimensions of my rectangle(s).&#xD;&#xA;- My rotation angle is applied in a rotate function&#xD;&#xA;&#xD;&#xA;I know about the [point in polygon](https://en.wikipedia.org/wiki/Point_in_polygon) algorithm but I don't know how to calculate the points of my (rotated) rectangles.&#xD;&#xA;&#xD;&#xA;My question is how can I verify if my selection area is over one or more of these rectangles and if the PIP algorithm is the best, how can I calculate the points of my rectangle(s)?&#xD;&#xA;&#xD;&#xA;Here is the kind of render I'm trying to have:&#xD;&#xA;[![selection][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jtAGY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14424" PostHistoryTypeId="5" PostId="5311" RevisionGUID="409e2850-4cf3-4daa-8636-f4e18338a735" CreationDate="2017-07-02T08:00:01.340" UserId="231" Comment="Typo and formatting" Text="I have a grayscale image and want to &quot;resize&quot; it in terms of &quot;pixel concentration&quot;.  &#xD;&#xA;That means I divide the source image `x_old * y_old` into `x_new * y_new` sections, and all (sub)pixel grayscale values in each section shall be accumulated to make the new grayscale value.&#xD;&#xA;&#xD;&#xA;Writing two loops also considering the sub pixel parts in each section is easy, but doesn't seem very sophisticated.  &#xD;&#xA;Are there some smart and yet efficient algorithms doing the task?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14425" PostHistoryTypeId="5" PostId="5312" RevisionGUID="7f54cc54-fc4a-4ff9-aea6-a43ce1a038ba" CreationDate="2017-07-02T12:05:36.057" UserId="231" Comment="Update following edit to question: how to check for line segment intersection" Text="# In pseudocode&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-none --&gt;&#xD;&#xA;&#xD;&#xA;    For each rectangle:&#xD;&#xA;        If the rectangle overlaps the selection area, highlight the rectangle&#xD;&#xA;&#xD;&#xA;This is all that is required for a correctly working approach, but there are a number of other things you might need to take into account if this approach performs too slowly. I recommend implementing the simple approach, and once it works correctly you can make gradual improvements if it is not sufficiently smooth and responsive (this may not be necessary unless you have a large number of rectangles or restrictive hardware/software).&#xD;&#xA;&#xD;&#xA;# Determining whether a rectangle overlaps the selection rectangle&#xD;&#xA;&#xD;&#xA;As you point out, using the point in polygon algorithm is impractical for this purpose - each rectangle is made up of an infinite number of points. So we need a completely different approach.&#xD;&#xA;&#xD;&#xA;One way to check if a candidate rectangle overlaps the selection rectangle is to check for the following two cases:&#xD;&#xA;&#xD;&#xA;- Check if any edge of the candidate rectangle intersects an edge of the selection rectangle.&#xD;&#xA;- Check if either the candidate rectangle or the selection rectangle is completely contained within the other.&#xD;&#xA;&#xD;&#xA;If either of these are true, there is some overlap. If neither of these are true, there is no overlap.&#xD;&#xA;&#xD;&#xA;The complete containment check is simplified by the fact that the selection rectangle is never rotated - always remaining aligned to the x and y axes:&#xD;&#xA;&#xD;&#xA;- To check if a candidate rectangle is completely contained within the selection rectangle, check that all 4 of its corners are between the x boundaries of the selection rectangle, and between the y boundaries of the selection rectangle.&#xD;&#xA;- To check if a candidate rectangle completely contains the selection rectangle, check that it has one corner outside the bounds of the selection rectangle in each of the 4 orthogonal directions (left, right, up, and down). If so, it either contains the selection rectangle completely, or one or more of the edges intersect (but edge intersection was checked for in the previous stage, so we're only checking for complete containment if we already know there is no edge intersection).&#xD;&#xA;&#xD;&#xA;# Line segment intersection&#xD;&#xA;&#xD;&#xA;To check whether any of the edges of a candidate rectangle intersects with any of the edges of the selection rectangle, you can either use a general line segment intersection algorithm and apply it to each pair of candidate edge and selection edge, or you can take advantage of the fact that the selection rectangle is never rotated,as follows:&#xD;&#xA;&#xD;&#xA;### Parallel case&#xD;&#xA;&#xD;&#xA;If the candidate rectangle has edges parallel to the x and y axes (that is, it is rotated by 0, 90, 180 or 270 degrees), check each of its edges:&#xD;&#xA;&#xD;&#xA;If the edge is vertical, check if its x position is between the x coordinates of the selection rectangle, and if one of the following holds then there is an intersection:&#xD;&#xA;&#xD;&#xA;- The y coordinate of one of its end points is between the y coordinates of the selection rectangle AND the y coordinate of the other end point is not.&#xD;&#xA;- The end points are both outside the y coordinates of the selection rectangle but in opposite directions.&#xD;&#xA;&#xD;&#xA;Similarly, if the edge is horizontal, check if its y position is between the y coordinates of the selection rectangle, and if one of the following holds then there is an intersection:&#xD;&#xA;&#xD;&#xA;- The x coordinate of one of its end points is between the x coordinates of the selection rectangle AND the x coordinate of the other end point is not.&#xD;&#xA;- The end points are both outside the x coordinates of the selection rectangle but in opposite directions.&#xD;&#xA;&#xD;&#xA;### Non-parallel case&#xD;&#xA;&#xD;&#xA;Check each of the edges of the candidate rectangle as follows:&#xD;&#xA;&#xD;&#xA;First find the points of intersection of the infinite line on which the candidate edge lies, with the infinite lines forming the boundaries of the selection rectangle.&#xD;&#xA;&#xD;&#xA;If either of the intersections with the horizontal y boundaries has an x coordinate between the vertical x boundaries, then there is an intersection of the line segment edge of the selection rectangle with the candidate infinite line (so potentially with the candidate line segment too).&#xD;&#xA;&#xD;&#xA;Similarly, if either of the intersections with the vertical x boundaries has a y coordinate between the horizontal y boundaries, then there is an intersection of the line segment edge of the selection rectangle with the candidate infinite line (so potentially with the candidate line segment too).&#xD;&#xA;&#xD;&#xA;To then check if there is an intersection with the candidate line segment, check if one of the following is true:&#xD;&#xA;&#xD;&#xA;- A y boundary intersection is between the x boundaries of the selection rectangle AND between the y coordinates of the candidate line segment.&#xD;&#xA;- An x boundary intersection is between the y boundaries of the selection rectangle AND between the x coordinates of the candidate line segment.&#xD;&#xA;&#xD;&#xA;# Examples of refinements if speed is unsatisfactory&#xD;&#xA;&#xD;&#xA;- [Acceleration data structures] such as a grid or space partitioning hierarchy so that not every rectangle needs to be checked. &#xD;&#xA;- Only checking the changed parts of the selection (usually one corner of the selection stays fixed while the opposite corner moves).&#xD;&#xA;- Tracking which rectangles are already selected to reduce the checking required each time the selection changes:&#xD;&#xA; - No need to check unselected rectangles if the selection has purely shrunk.&#xD;&#xA; - No need to check already selected rectangles if the selection has purely grown.&#xD;&#xA; - It will only be necessary to check both selected and unselected rectangles if the selection has grown in one direction and shrunk in the other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Acceleration data structures]: https://en.wikipedia.org/wiki/Space_partitioning#In_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="14426" PostHistoryTypeId="5" PostId="5312" RevisionGUID="f3be781d-da51-4a82-b9ec-daa0f28c87c5" CreationDate="2017-07-02T12:11:12.200" UserId="231" Comment="deleted 40 characters in body" Text="# In pseudocode&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-none --&gt;&#xD;&#xA;&#xD;&#xA;    For each rectangle:&#xD;&#xA;        If the rectangle overlaps the selection area, highlight the rectangle&#xD;&#xA;&#xD;&#xA;This is all that is required for a correctly working approach, but there are a number of other things you might need to take into account if this approach performs too slowly. I recommend implementing the simple approach, and once it works correctly you can make gradual improvements if it is not sufficiently smooth and responsive (this may not be necessary unless you have a large number of rectangles or restrictive hardware/software).&#xD;&#xA;&#xD;&#xA;# Determining whether a rectangle overlaps the selection rectangle&#xD;&#xA;&#xD;&#xA;As you point out, using the point in polygon algorithm is impractical for this purpose - each rectangle is made up of an infinite number of points. So we need a completely different approach.&#xD;&#xA;&#xD;&#xA;One way to check if a candidate rectangle overlaps the selection rectangle is to check for the following two cases:&#xD;&#xA;&#xD;&#xA;- Check if any edge of the candidate rectangle intersects an edge of the selection rectangle.&#xD;&#xA;- Check if either the candidate rectangle or the selection rectangle is completely contained within the other.&#xD;&#xA;&#xD;&#xA;If either of these are true, there is some overlap. If neither of these are true, there is no overlap.&#xD;&#xA;&#xD;&#xA;The complete containment check is simplified by the fact that the selection rectangle is never rotated - always remaining aligned to the x and y axes:&#xD;&#xA;&#xD;&#xA;- To check if a candidate rectangle is completely contained within the selection rectangle, check that all 4 of its corners are between the x boundaries of the selection rectangle, and between the y boundaries of the selection rectangle.&#xD;&#xA;- To check if a candidate rectangle completely contains the selection rectangle, check that it has one corner outside the bounds of the selection rectangle in each of the 4 orthogonal directions (left, right, up, and down). If so, it either contains the selection rectangle completely, or one or more of the edges intersect (but edge intersection was checked for in the previous stage, so we're only checking for complete containment if we already know there is no edge intersection).&#xD;&#xA;&#xD;&#xA;# Line segment intersection&#xD;&#xA;&#xD;&#xA;To check whether any of the edges of a candidate rectangle intersects with any of the edges of the selection rectangle, you can either use a general line segment intersection algorithm and apply it to each pair of candidate edge and selection edge, or you can take advantage of the fact that the selection rectangle is never rotated,as follows:&#xD;&#xA;&#xD;&#xA;### Parallel case&#xD;&#xA;&#xD;&#xA;If the candidate rectangle has edges parallel to the x and y axes (that is, it is rotated by 0, 90, 180 or 270 degrees), check each of its edges:&#xD;&#xA;&#xD;&#xA;If the edge is vertical, check if its x position is between the x coordinates of the selection rectangle, and if one of the following holds then there is an intersection:&#xD;&#xA;&#xD;&#xA;- The y coordinate of one of its end points is between the y coordinates of the selection rectangle AND the y coordinate of the other end point is not.&#xD;&#xA;- The end points are both outside the y coordinates of the selection rectangle but in opposite directions.&#xD;&#xA;&#xD;&#xA;Similarly, if the edge is horizontal, check if its y position is between the y coordinates of the selection rectangle, and if one of the following holds then there is an intersection:&#xD;&#xA;&#xD;&#xA;- The x coordinate of one of its end points is between the x coordinates of the selection rectangle AND the x coordinate of the other end point is not.&#xD;&#xA;- The end points are both outside the x coordinates of the selection rectangle but in opposite directions.&#xD;&#xA;&#xD;&#xA;### Non-parallel case&#xD;&#xA;&#xD;&#xA;Check each of the edges of the candidate rectangle as follows:&#xD;&#xA;&#xD;&#xA;First find the points of intersection of the infinite line on which the candidate edge lies, with the infinite lines forming the boundaries of the selection rectangle.&#xD;&#xA;&#xD;&#xA;If either of the intersections with the y boundaries has an x coordinate between the x boundaries, then there is an intersection of the line segment edge of the selection rectangle with the candidate infinite line (so potentially with the candidate line segment too).&#xD;&#xA;&#xD;&#xA;Similarly, if either of the intersections with the x boundaries has a y coordinate between the y boundaries, then there is an intersection of the line segment edge of the selection rectangle with the candidate infinite line (so potentially with the candidate line segment too).&#xD;&#xA;&#xD;&#xA;To then check if there is an intersection with the candidate line segment, check if one of the following is true:&#xD;&#xA;&#xD;&#xA;- A y boundary intersection is between the x boundaries of the selection rectangle AND between the y coordinates of the candidate line segment.&#xD;&#xA;- An x boundary intersection is between the y boundaries of the selection rectangle AND between the x coordinates of the candidate line segment.&#xD;&#xA;&#xD;&#xA;# Examples of refinements if speed is unsatisfactory&#xD;&#xA;&#xD;&#xA;- [Acceleration data structures] such as a grid or space partitioning hierarchy so that not every rectangle needs to be checked. &#xD;&#xA;- Only checking the changed parts of the selection (usually one corner of the selection stays fixed while the opposite corner moves).&#xD;&#xA;- Tracking which rectangles are already selected to reduce the checking required each time the selection changes:&#xD;&#xA; - No need to check unselected rectangles if the selection has purely shrunk.&#xD;&#xA; - No need to check already selected rectangles if the selection has purely grown.&#xD;&#xA; - It will only be necessary to check both selected and unselected rectangles if the selection has grown in one direction and shrunk in the other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Acceleration data structures]: https://en.wikipedia.org/wiki/Space_partitioning#In_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="14427" PostHistoryTypeId="5" PostId="5312" RevisionGUID="fbdd763e-26a9-48c5-89bd-e71901c75687" CreationDate="2017-07-02T12:16:40.190" UserId="231" Comment="Clarification" Text="# In pseudocode&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-none --&gt;&#xD;&#xA;&#xD;&#xA;    For each rectangle:&#xD;&#xA;        If the rectangle overlaps the selection area, highlight the rectangle&#xD;&#xA;&#xD;&#xA;This is all that is required for a correctly working approach, but there are a number of other things you might need to take into account if this approach performs too slowly. I recommend implementing the simple approach, and once it works correctly you can make gradual improvements if it is not sufficiently smooth and responsive (this may not be necessary unless you have a large number of rectangles or restrictive hardware/software).&#xD;&#xA;&#xD;&#xA;# Determining whether a rectangle overlaps the selection rectangle&#xD;&#xA;&#xD;&#xA;As you point out, using the point in polygon algorithm is impractical for this purpose - each rectangle is made up of an infinite number of points. So we need a completely different approach.&#xD;&#xA;&#xD;&#xA;One way to check if a candidate rectangle overlaps the selection rectangle is to check for the following two cases:&#xD;&#xA;&#xD;&#xA;- Check if any edge of the candidate rectangle intersects an edge of the selection rectangle.&#xD;&#xA;- Check if either the candidate rectangle or the selection rectangle is completely contained within the other.&#xD;&#xA;&#xD;&#xA;If either of these are true, there is some overlap. If neither of these are true, there is no overlap.&#xD;&#xA;&#xD;&#xA;The complete containment check is simplified by the fact that the selection rectangle is never rotated - always remaining aligned to the x and y axes:&#xD;&#xA;&#xD;&#xA;- To check if a candidate rectangle is completely contained within the selection rectangle, check that all 4 of its corners are between the x boundaries of the selection rectangle, and between the y boundaries of the selection rectangle.&#xD;&#xA;- To check if a candidate rectangle completely contains the selection rectangle, check that it has one corner outside the bounds of the selection rectangle in each of the 4 orthogonal directions (left, right, up, and down). If so, it either contains the selection rectangle completely, or one or more of the edges intersect (but edge intersection was checked for in the previous stage, so we're only checking for complete containment if we already know there is no edge intersection).&#xD;&#xA;&#xD;&#xA;# Line segment intersection&#xD;&#xA;&#xD;&#xA;To check whether any of the edges of a candidate rectangle intersects with any of the edges of the selection rectangle, you can either use a general line segment intersection algorithm and apply it to each pair of candidate edge and selection edge, or you can take advantage of the fact that the selection rectangle is never rotated,as follows:&#xD;&#xA;&#xD;&#xA;### Parallel case&#xD;&#xA;&#xD;&#xA;If the candidate rectangle has edges parallel to the x and y axes (that is, it is rotated by 0, 90, 180 or 270 degrees), check each of its edges:&#xD;&#xA;&#xD;&#xA;If the edge is vertical, check if its x position is between the x coordinates of the selection rectangle, and if one of the following holds then there is an intersection:&#xD;&#xA;&#xD;&#xA;- The y coordinate of one of its end points is between the y coordinates of the selection rectangle AND the y coordinate of the other end point is not.&#xD;&#xA;- The end points are both outside the y coordinates of the selection rectangle but in opposite directions.&#xD;&#xA;&#xD;&#xA;Similarly, if the edge is horizontal, check if its y position is between the y coordinates of the selection rectangle, and if one of the following holds then there is an intersection:&#xD;&#xA;&#xD;&#xA;- The x coordinate of one of its end points is between the x coordinates of the selection rectangle AND the x coordinate of the other end point is not.&#xD;&#xA;- The end points are both outside the x coordinates of the selection rectangle but in opposite directions.&#xD;&#xA;&#xD;&#xA;### Non-parallel case&#xD;&#xA;&#xD;&#xA;Check each of the edges of the candidate rectangle as follows:&#xD;&#xA;&#xD;&#xA;First find the points of intersection of the infinite line on which the candidate edge lies, with the infinite lines forming the boundaries of the selection rectangle.&#xD;&#xA;&#xD;&#xA;If either of the intersections with the y boundaries of the selection rectangle has an x coordinate between the x boundaries of the selection rectangle, then there is an intersection of one of the horizontal line segment edges of the selection rectangle with the candidate infinite line (so potentially with the candidate line segment too).&#xD;&#xA;&#xD;&#xA;Similarly, if either of the intersections with the x boundaries of the selection rectangle has a y coordinate between the y boundaries of the selection rectangle, then there is an intersection of one of the vertical line segment edges of the selection rectangle with the candidate infinite line (so potentially with the candidate line segment too).&#xD;&#xA;&#xD;&#xA;To then check if there is an intersection with the candidate line segment, check if one of the following is true:&#xD;&#xA;&#xD;&#xA;- An intersection with the y boundary of the selection rectangle is between the x boundaries of the selection rectangle AND between the y coordinates of the candidate line segment.&#xD;&#xA;- An intersection with the x boundary of the selection rectangle is between the y boundaries of the selection rectangle AND between the x coordinates of the candidate line segment.&#xD;&#xA;&#xD;&#xA;# Examples of refinements if speed is unsatisfactory&#xD;&#xA;&#xD;&#xA;- [Acceleration data structures] such as a grid or space partitioning hierarchy so that not every rectangle needs to be checked. &#xD;&#xA;- Only checking the changed parts of the selection (usually one corner of the selection stays fixed while the opposite corner moves).&#xD;&#xA;- Tracking which rectangles are already selected to reduce the checking required each time the selection changes:&#xD;&#xA; - No need to check unselected rectangles if the selection has purely shrunk.&#xD;&#xA; - No need to check already selected rectangles if the selection has purely grown.&#xD;&#xA; - It will only be necessary to check both selected and unselected rectangles if the selection has grown in one direction and shrunk in the other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [Acceleration data structures]: https://en.wikipedia.org/wiki/Space_partitioning#In_computer_graphics" ContentLicense="CC BY-SA 3.0" />
  <row Id="14428" PostHistoryTypeId="2" PostId="5316" RevisionGUID="484ba029-8c63-4e03-8446-179090fb4bea" CreationDate="2017-07-02T15:25:27.840" UserId="2479" Text="Assuming that you are familiar with the concept of BSDFs, the usual way of modelling rough dielectric surfaces (i.e. glass, water, plastics) is to use microfacet-based models like [Microfacet Models for Refraction through Rough Surfaces][1].&#xD;&#xA;&#xD;&#xA;To make it work efficiently in a path tracer you will need a good sampling strategy, like [Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals][2].&#xD;&#xA;&#xD;&#xA;Also keep in mind, that the mentioned BSDF model tends to get darker as you increase roughness because it neglects the light which gets inter-reflected among micro-facets. This can be compensated, but it's not a trivial thing to do.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [2]: http://www.eugenedeon.com/project/importance-sampling-microfacet-based-bsdfs-using-the-distribution-of-visible-normals/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14429" PostHistoryTypeId="2" PostId="5317" RevisionGUID="1cc911b5-43be-4a9f-9904-afc05c2e93ac" CreationDate="2017-07-03T01:41:02.667" UserId="6838" Text="I understand how an artist would make seamless textures by hand, but how can a computer program automate that process? Software like [PixPlant][1] is capable of doing this, but I don't understand **how** it does this.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.pixplant.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14430" PostHistoryTypeId="1" PostId="5317" RevisionGUID="1cc911b5-43be-4a9f-9904-afc05c2e93ac" CreationDate="2017-07-03T01:41:02.667" UserId="6838" Text="Seamless Textures" ContentLicense="CC BY-SA 3.0" />
  <row Id="14431" PostHistoryTypeId="3" PostId="5317" RevisionGUID="1cc911b5-43be-4a9f-9904-afc05c2e93ac" CreationDate="2017-07-03T01:41:02.667" UserId="6838" Text="|texture|algorithm|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14433" PostHistoryTypeId="2" PostId="5318" RevisionGUID="3cd74d08-3386-47cb-b030-1a97f2b04b81" CreationDate="2017-07-03T07:54:01.700" UserId="38" Text="These rely on a transformation from global coordinates to path local coordinates, where the local axes are along and out (or more ofthen u and v). In essence this all works on a priciple similiar to how offset works.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Depiction of local axes.&#xD;&#xA;&#xD;&#xA;Now the first one ($A$) is a sweep of an oval. Which is technically the most challenging of the four. In essence You offset edges directionally and cap them with a fixed directional oval. Altough this has all kinds of interetsing edge cases. A lot of mathematical lore is known about sweeping shapes as this is somewhat hard to do in 3D and doins so with an arbitrary shape is useful for the cad crowd. At it simplest its just sampling many times, which allows for change in shape along line, but quite sophisticated approaches are available.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Oval sweep.&#xD;&#xA;&#xD;&#xA;The second is simply (bombing) a shape in radom places in the new coordinate system. Mathematically this is pretty simple. Generate a number in aliong direction then find that point. Then generate a second number and multiply that by the normal direction vector of your path then add this to the point.&#xD;&#xA;&#xD;&#xA;The third and fourth just do this for a lot of points read in form a cartesian template object. Again you shoudl familiarize yourself with how offset and graduated offset is done. You can find a lot of references but one of my favorite online resource for beziers is in the [Pomax bezier primer](https://pomax.github.io/bezierinfo/#graduatedoffset). Its just lot of small offset lines to transform fom. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GRsF9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rGI67.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14434" PostHistoryTypeId="5" PostId="5318" RevisionGUID="43cb0fd6-8964-4068-ada0-0521a5e17635" CreationDate="2017-07-03T08:00:02.250" UserId="38" Comment="added 1 character in body" Text="These rely on a transformation from global coordinates to path local coordinates, where the local axes are along and out (or more often u and v). In essence this all works on a principle similar to how offset works.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Depiction of local axes.&#xD;&#xA;&#xD;&#xA;Now the first one ($A$) is a sweep of an oval. Which is technically the most challenging of the four. In essence You offset edges directionally and cap them with a fixed directional oval. Although this has all kinds of interesting edge cases. A lot of mathematical lore is known about sweeping shapes as this is somewhat hard to do in 3D and doing so with an arbitrary shape is useful for the cad crowd. At it simplest its just sampling many times, which allows for change in shape along line, but quite sophisticated approaches are available.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Oval sweep.&#xD;&#xA;&#xD;&#xA;The second is simply (bombing) a shape in random places in the new coordinate system. Mathematically this is pretty simple. Generate a number in along direction then find that point. Then generate a second number and multiply that by the normal direction vector of your path then add this to the point.&#xD;&#xA;&#xD;&#xA;The third and fourth just do this for a lot of points read in form a Cartesian template object. Again you should familiarize yourself with how offset and graduated offset is done. You can find a lot of references but one of my favorite online resource for Béziers is in the [Pomax Bézier primer](https://pomax.github.io/bezierinfo/#graduatedoffset). Its just lot of small offset lines to transform from. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GRsF9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rGI67.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14435" PostHistoryTypeId="50" PostId="4651" RevisionGUID="9c97fd56-9fb8-4212-b321-7e27c682fe36" CreationDate="2017-07-03T10:22:41.130" UserId="-1" />
  <row Id="14436" PostHistoryTypeId="2" PostId="5319" RevisionGUID="881d9f96-3f55-4b7d-aa56-32311fba77a0" CreationDate="2017-07-04T11:38:13.837" UserId="6785" Text="I'm rendering clouds by applying a texture map on the inside of an ellipsoid. From a distance (at the center of the cloud ellipsoid) the texture looks quite nice and reasonably realistic. See image below:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is that as I fly close to the boundary of the ellipsoid (into the cloud) I see the boundaries of each of the quads that make up the ellipsoid. See image below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;  [1]: https://i.stack.imgur.com/7eEYB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/OBo1n.jpg&#xD;&#xA;&#xD;&#xA;Any suggestions on how to get around this artifact would be appreciated. I'm using 50 grid segments in both the azimuthal and polar directions of the ellipsoid which is actually truncated 10 degrees below the poles. The texture map uses GL_MODULATE with GL_LINEAR and GL_LINEAR_MIPMAP_LINEAR for the Min and Mag filters. The ellipsoid base colour is white, so that there are no shading issues involved. I have also verified that the texture coordinates are correctly applied and the normals are oriented correctly.&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;I could cheat and use a lot of fog which would mimic actually flying into a cloud, but I'd really like to implement an elegant robust solution.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14437" PostHistoryTypeId="1" PostId="5319" RevisionGUID="881d9f96-3f55-4b7d-aa56-32311fba77a0" CreationDate="2017-07-04T11:38:13.837" UserId="6785" Text="Hiding Boundaries with the Eye close to a set of adjacent textured quads" ContentLicense="CC BY-SA 3.0" />
  <row Id="14438" PostHistoryTypeId="3" PostId="5319" RevisionGUID="881d9f96-3f55-4b7d-aa56-32311fba77a0" CreationDate="2017-07-04T11:38:13.837" UserId="6785" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14439" PostHistoryTypeId="2" PostId="5320" RevisionGUID="b71dafd3-0a11-4c29-b97c-52f2bec00416" CreationDate="2017-07-04T14:04:28.497" UserId="6785" Text="I figured out the mistake that I was making and confirmed the hypothesis in my comment above. I was rendering each quad with its distinct set of vertex normals calculated from the local parametrisation. With lighting enabled, the vertices were therefore shaded differently for adjacent quads owing to the different dot products between the local normal and the light direction vector.&#xD;&#xA;&#xD;&#xA;What I did was average out the normals to create a unique normal at each vertex. Now when I fly into the clouds, I do not see the quad boundaries.&#xD;&#xA;&#xD;&#xA;As Dan suggested, I could avoid the problem altogether by disabling lighting, but it would eliminate the ability to simulate different times of the day and in any case, the fix above worked and only involved about 30 lines of code!&#xD;&#xA;&#xD;&#xA;Problem solved.&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14440" PostHistoryTypeId="2" PostId="5321" RevisionGUID="086c1a1b-3577-44e6-bd01-65457b7d3094" CreationDate="2017-07-04T14:42:26.767" UserId="2041" Text="Conceptually simplest would be to treat it as a ray-casting problem, representing each point as a small sphere. It should work like the shadow rays in a conventional raytracer: iterate over all of your points, and for each one, trace a ray to the camera. If the ray intersects the sphere representing another point, then remove it.&#xD;&#xA;&#xD;&#xA;If the number of points is small enough, you can do this directly, but if that's not fast enough, you should put the points into an acceleration structure such as a kd-tree. (If you need this kind of optimization, it might be best to start from an existing ray-tracer such as PBRT instead of writing it from scratch.)&#xD;&#xA;&#xD;&#xA;If the points represent surface detections (from something like a laser scanner), you might also have the surface normal at each point, depending on the scanner technology. In this case, you might get better results by using small discs instead of spheres. That'll be more robust on faces seen at a glancing angle.&#xD;&#xA;&#xD;&#xA;Finally, if you also need to remove points that are outside the camera's view (e.g. behind the camera), you can do this at the same time by comparing the direction of each ray with the camera's view bounds." ContentLicense="CC BY-SA 3.0" />
  <row Id="14441" PostHistoryTypeId="5" PostId="5320" RevisionGUID="0dfb2d4a-76dc-40d3-8bd8-5ac50ca11a2c" CreationDate="2017-07-04T15:56:56.450" UserId="6785" Comment="added 2952 characters in body" Text="I figured out the mistake that I was making and confirmed the hypothesis in my comment above. I was rendering each quad with its distinct set of vertex normals calculated from the local parametrisation. With lighting enabled, the vertices were therefore shaded differently for adjacent quads owing to the different dot products between the local normal and the light direction vector.&#xD;&#xA;&#xD;&#xA;What I did was average out the normals to create a unique normal at each vertex. Now when I fly into the clouds, I do not see the quad boundaries.&#xD;&#xA;&#xD;&#xA;As Dan suggested, I could avoid the problem altogether by disabling lighting, but it would eliminate the ability to simulate different times of the day and in any case, the fix above worked and only involved about 30 lines of code!&#xD;&#xA;&#xD;&#xA;Problem solved.&#xD;&#xA;&#xD;&#xA;In case anyone lse finds this useful, here's he code (I wrote it in VBA) to calculate averaged vertex normals given a set of vertices on a surface that is topologically rectangular.&#xD;&#xA;&#xD;&#xA;    Sub Calculate_Averaged_Vertex_Normals(Vertx#(), M%, N%, VnormX#())&#xD;&#xA;    ' INPUT:&#xD;&#xA;    'L,M: Array Dimensions&#xD;&#xA;    ' Vertx - 3D array of vertex coordinates&#xD;&#xA;    ' OUTPUT: VnormX: 3D array of Averaged Vertex Normals &#xD;&#xA;    &#xD;&#xA;     Dim i%, j%, k%, p%, q%, w%, NormX#(3), Ncount%(), Vx#(), Fn#(3),Gn#(3),Hn#(3),A#&#xD;&#xA;     ReDim Ncount%(0 To L, NF + 1), Vx(0 To L, NF + 1, 4, 3)&#xD;&#xA;     For k = 0 To M - 1&#xD;&#xA;      For i = 0 To N - 1&#xD;&#xA;       Call Quad_Normal_Vector_Parametrisation(Vertx,k, i,Fn,Gn,Hn) ' Local Normals at each Vertex&#xD;&#xA;       &#xD;&#xA;         p = k: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(0, 0, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;         &#xD;&#xA;         p = k: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(1, 0, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;         &#xD;&#xA;         p = k + 1: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(1, 1, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;    &#xD;&#xA;         p = k + 1: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(0, 1, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;      Next i&#xD;&#xA;     Next k&#xD;&#xA;     &#xD;&#xA;     For k = 0 To M&#xD;&#xA;      For i = 0 To N&#xD;&#xA;       For w = 1 To 3&#xD;&#xA;        A = 0#&#xD;&#xA;        For j = 1 To Ncount(k, i)&#xD;&#xA;         A = A + Vx(k, i, j, w)&#xD;&#xA;        Next j&#xD;&#xA;        VnormX(k, i, w) = A / Ncount(k, i)			' Averaged Vertex Normal&#xD;&#xA;       Next w&#xD;&#xA;      Next i&#xD;&#xA;     Next k&#xD;&#xA;    End Sub&#xD;&#xA;    &#xD;&#xA;    Sub Quad_Normal_Vector_Parametrisation(Vertx#(),k%, i%,Fn#(),Gn#(),Hn#())&#xD;&#xA;     Dim j%, Bv#(3), CV#(3), Dv#(3)&#xD;&#xA;     For j = 1 To 3&#xD;&#xA;      Bv(j) = Vertx(k, i + 1, j) - Vertx(k, i, j)           ' Tangent Vectors from Bilinear Parametrisation&#xD;&#xA;      CV(j) = Vertx(k + 1, i, j) - Vertx(k, i, j)&#xD;&#xA;      Dv(j) = Vertx(k + 1, i + 1, j) - Vertx(k, i + 1, j) - Vertx(k + 1, i, j) + Vertx(k, i, j)&#xD;&#xA;     Next j&#xD;&#xA;     Call CrossProd(Bv, CV, Fn)             ' Normal Vector from Cross Product of Tangent Vectors.&#xD;&#xA;     Call CrossProd(Bv, Dv, Gn)&#xD;&#xA;     Call CrossProd(Dv, CV, Hn)&#xD;&#xA;    End Sub&#xD;&#xA;    &#xD;&#xA;    Sub Quad_Vertex_Normal(x#, y#, NormX#(),Fn#(),Gn#(),Hn#())&#xD;&#xA;     Dim j%, Norm#&#xD;&#xA;     Norm = 0#&#xD;&#xA;     For j = 1 To 3&#xD;&#xA;      NormX(j) = Fn(j) + Gn(j) * x + Hn(j) * y&#xD;&#xA;      Norm = Norm + NormX(j) * NormX(j)&#xD;&#xA;     Next j&#xD;&#xA;     Norm = Sqr(Norm)&#xD;&#xA;     For j = 1 To 3&#xD;&#xA;      NormX(j) = NormX(j) / Norm&#xD;&#xA;     Next j&#xD;&#xA;    End Sub&#xD;&#xA;    &#xD;&#xA;    Sub CrossProd(x#(), y#(), Z#())&#xD;&#xA;     Z(1) = x(2) * y(3) - y(2) * x(3)&#xD;&#xA;     Z(2) = y(1) * x(3) - x(1) * y(3)&#xD;&#xA;     Z(3) = x(1) * y(2) - y(1) * x(2)&#xD;&#xA;    End Sub&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14442" PostHistoryTypeId="2" PostId="5322" RevisionGUID="d7d26345-8fa1-4651-a72f-f0586b021c17" CreationDate="2017-07-04T16:26:02.303" UserDisplayName="user6935" Text="    void display(void) {&#xD;&#xA;    	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    	glColor3f(1.0, 1.0, 1.0);&#xD;&#xA;    	glBegin(GL_LINES);&#xD;&#xA;    	glVertex3d(0.75, 0.25, 0.0);&#xD;&#xA;    	glVertex3d(0.75, 0.25, -0.75);&#xD;&#xA;    	glEnd();&#xD;&#xA;    	glFlush();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void init(void) {&#xD;&#xA;    	glClearColor(0.0, 0.0, 0.0, 0.0);&#xD;&#xA;    	glMatrixMode(GL_PROJECTION);&#xD;&#xA;    	glLoadIdentity();&#xD;&#xA;    	glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I should be able to see line from `(0.75, 0.25, 0.0)`  to `(0.75, 0.25, -0.75)`, but I can't see anything on the screen.&#xD;&#xA;&#xD;&#xA;However, I'm able to see the line using snippet below&#xD;&#xA;&#xD;&#xA;    glVertex3d(0.35, 0.25, 0.0);&#xD;&#xA;    glVertex3d(0.75, 0.25, -0.75);&#xD;&#xA;&#xD;&#xA;Can anyone explain this behavior?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14443" PostHistoryTypeId="1" PostId="5322" RevisionGUID="d7d26345-8fa1-4651-a72f-f0586b021c17" CreationDate="2017-07-04T16:26:02.303" UserDisplayName="user6935" Text="glOrtho() in fixed function pipeline - Unable to see change in z-axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="14444" PostHistoryTypeId="3" PostId="5322" RevisionGUID="d7d26345-8fa1-4651-a72f-f0586b021c17" CreationDate="2017-07-04T16:26:02.303" UserDisplayName="user6935" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14445" PostHistoryTypeId="5" PostId="5320" RevisionGUID="8b9deaae-3443-45e6-af96-e82e543be45a" CreationDate="2017-07-04T16:44:40.883" UserId="6785" Comment="added 2 characters in body" Text="I figured out the mistake that I was making and confirmed the hypothesis in my comment above. I was rendering each quad with its distinct set of vertex normals calculated from the local parametrisation. With lighting enabled, the vertices were therefore shaded differently for adjacent quads owing to the different dot products between the local normal and the light direction vector.&#xD;&#xA;&#xD;&#xA;What I did was average out the normals to create a unique normal at each vertex. Now when I fly into the clouds, I do not see the quad boundaries.&#xD;&#xA;&#xD;&#xA;As Dan suggested, I could avoid the problem altogether by disabling lighting, but it would eliminate the ability to simulate different times of the day and in any case, the fix above worked and only involved about 30 lines of code!&#xD;&#xA;&#xD;&#xA;Problem solved.&#xD;&#xA;&#xD;&#xA;In case anyone else finds this useful, here's the code (I wrote it in VBA) to calculate averaged vertex normals given a set of vertices on a surface that is topologically rectangular.&#xD;&#xA;&#xD;&#xA;    Sub Calculate_Averaged_Vertex_Normals(Vertx#(), M%, N%, VnormX#())&#xD;&#xA;    ' INPUT:&#xD;&#xA;    'L,M: Array Dimensions&#xD;&#xA;    ' Vertx - 3D array of vertex coordinates&#xD;&#xA;    ' OUTPUT: VnormX: 3D array of Averaged Vertex Normals &#xD;&#xA;    &#xD;&#xA;     Dim i%, j%, k%, p%, q%, w%, NormX#(3), Ncount%(), Vx#(), Fn#(3),Gn#(3),Hn#(3),A#&#xD;&#xA;     ReDim Ncount%(0 To L, NF + 1), Vx(0 To L, NF + 1, 4, 3)&#xD;&#xA;     For k = 0 To M - 1&#xD;&#xA;      For i = 0 To N - 1&#xD;&#xA;       Call Quad_Normal_Vector_Parametrisation(Vertx,k, i,Fn,Gn,Hn) ' Local Normals at each Vertex&#xD;&#xA;       &#xD;&#xA;         p = k: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(0, 0, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;         &#xD;&#xA;         p = k: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(1, 0, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;         &#xD;&#xA;         p = k + 1: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(1, 1, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;    &#xD;&#xA;         p = k + 1: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)&#xD;&#xA;         Call Quad_Vertex_Normal(0, 1, NormX,Fn,Gn,Hn)&#xD;&#xA;         For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w&#xD;&#xA;      Next i&#xD;&#xA;     Next k&#xD;&#xA;     &#xD;&#xA;     For k = 0 To M&#xD;&#xA;      For i = 0 To N&#xD;&#xA;       For w = 1 To 3&#xD;&#xA;        A = 0#&#xD;&#xA;        For j = 1 To Ncount(k, i)&#xD;&#xA;         A = A + Vx(k, i, j, w)&#xD;&#xA;        Next j&#xD;&#xA;        VnormX(k, i, w) = A / Ncount(k, i)			' Averaged Vertex Normal&#xD;&#xA;       Next w&#xD;&#xA;      Next i&#xD;&#xA;     Next k&#xD;&#xA;    End Sub&#xD;&#xA;    &#xD;&#xA;    Sub Quad_Normal_Vector_Parametrisation(Vertx#(),k%, i%,Fn#(),Gn#(),Hn#())&#xD;&#xA;     Dim j%, Bv#(3), CV#(3), Dv#(3)&#xD;&#xA;     For j = 1 To 3&#xD;&#xA;      Bv(j) = Vertx(k, i + 1, j) - Vertx(k, i, j)           ' Tangent Vectors from Bilinear Parametrisation&#xD;&#xA;      CV(j) = Vertx(k + 1, i, j) - Vertx(k, i, j)&#xD;&#xA;      Dv(j) = Vertx(k + 1, i + 1, j) - Vertx(k, i + 1, j) - Vertx(k + 1, i, j) + Vertx(k, i, j)&#xD;&#xA;     Next j&#xD;&#xA;     Call CrossProd(Bv, CV, Fn)             ' Normal Vector from Cross Product of Tangent Vectors.&#xD;&#xA;     Call CrossProd(Bv, Dv, Gn)&#xD;&#xA;     Call CrossProd(Dv, CV, Hn)&#xD;&#xA;    End Sub&#xD;&#xA;    &#xD;&#xA;    Sub Quad_Vertex_Normal(x#, y#, NormX#(),Fn#(),Gn#(),Hn#())&#xD;&#xA;     Dim j%, Norm#&#xD;&#xA;     Norm = 0#&#xD;&#xA;     For j = 1 To 3&#xD;&#xA;      NormX(j) = Fn(j) + Gn(j) * x + Hn(j) * y&#xD;&#xA;      Norm = Norm + NormX(j) * NormX(j)&#xD;&#xA;     Next j&#xD;&#xA;     Norm = Sqr(Norm)&#xD;&#xA;     For j = 1 To 3&#xD;&#xA;      NormX(j) = NormX(j) / Norm&#xD;&#xA;     Next j&#xD;&#xA;    End Sub&#xD;&#xA;    &#xD;&#xA;    Sub CrossProd(x#(), y#(), Z#())&#xD;&#xA;     Z(1) = x(2) * y(3) - y(2) * x(3)&#xD;&#xA;     Z(2) = y(1) * x(3) - x(1) * y(3)&#xD;&#xA;     Z(3) = x(1) * y(2) - y(1) * x(2)&#xD;&#xA;    End Sub&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14446" PostHistoryTypeId="2" PostId="5323" RevisionGUID="7ff40703-8e86-431d-a38b-55ed8d98275f" CreationDate="2017-07-05T02:09:35.390" UserId="6546" Text="Is it possible to have a dynamic array in a GLSL shader? For instance what if I have something like this in my GLSL Shader:&#xD;&#xA;&#xD;&#xA;    uniform int size;&#xD;&#xA;    uniform SceneLights lights[size];&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        for(int i = 0; i &lt; size; i++) {&#xD;&#xA;		    /* Do Some Calculation */&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this would be my C++ file:&#xD;&#xA;&#xD;&#xA;    for (GLuint i = 0; i &lt; pointLights.size(); i++) {&#xD;&#xA;		glUniform3f(glGetUniformLocation(shader, (&quot;pointLights[&quot; + std::to_string(i) + &quot;].position&quot;).c_str()), lights[i].someValue);&#xD;&#xA;    }&#xD;&#xA;		" ContentLicense="CC BY-SA 3.0" />
  <row Id="14447" PostHistoryTypeId="1" PostId="5323" RevisionGUID="7ff40703-8e86-431d-a38b-55ed8d98275f" CreationDate="2017-07-05T02:09:35.390" UserId="6546" Text="Dynamic Array in GLSL" ContentLicense="CC BY-SA 3.0" />
  <row Id="14448" PostHistoryTypeId="3" PostId="5323" RevisionGUID="7ff40703-8e86-431d-a38b-55ed8d98275f" CreationDate="2017-07-05T02:09:35.390" UserId="6546" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14449" PostHistoryTypeId="5" PostId="5323" RevisionGUID="f9d0586d-b37f-4085-a995-3aaf117e1eae" CreationDate="2017-07-05T02:15:14.993" UserId="6546" Comment="added 247 characters in body" Text="Is it possible to have a dynamic array in a GLSL shader? For instance, what if I have something like this in my GLSL Shader:&#xD;&#xA;&#xD;&#xA;    uniform int size;&#xD;&#xA;    uniform SceneLights lights[size];&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        for(int i = 0; i &lt; size; i++) {&#xD;&#xA;		    /* Do Some Calculation */&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this would be my C++ file:&#xD;&#xA;&#xD;&#xA;    for (GLuint i = 0; i &lt; pointLights.size(); i++) {&#xD;&#xA;		glUniform3f(glGetUniformLocation(shader, (&quot;pointLights[&quot; + std::to_string(i) + &quot;].position&quot;).c_str()), lights[i].someValue);&#xD;&#xA;    }&#xD;&#xA;		&#xD;&#xA;&#xD;&#xA;I would like to do this because I have a file with the positions of all the light sources in my scene (this may vary for each scene) so I would like to have a dynamic array which will allow me to send different numbers of lights to my shader." ContentLicense="CC BY-SA 3.0" />
  <row Id="14450" PostHistoryTypeId="2" PostId="5324" RevisionGUID="45fe0cde-d484-4ed0-a4d5-2f1dbb483b28" CreationDate="2017-07-05T03:58:48.610" UserId="6938" Text="So I have implemented motion blur via depth re-construction using the depth texture and a previous view projection matrix. The shader basically finds the texel coordinate in by using the previous (frame) view projection matrix and subtract the current UV (what's given to fragment) to find a blurring vector. Then I simply blur along this vector by sampling along it and then normalize it with the number of samples, a constant I set at the beginning.&#xD;&#xA;&#xD;&#xA;The problem I'm having is that even a tiny movement will cause the motion blur to ... well blur the scene. I find this too invasive and would like to ... &quot;soften&quot; this effect. I have tried to cap it by saying if the dot product of this blur vector is greater than 0.01, then blur. This sadly creates an oval like artifact in the middle the screen ...&#xD;&#xA;&#xD;&#xA;Anyone have good suggestions on how to handle this? &#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14451" PostHistoryTypeId="1" PostId="5324" RevisionGUID="45fe0cde-d484-4ed0-a4d5-2f1dbb483b28" CreationDate="2017-07-05T03:58:48.610" UserId="6938" Text="Motion Blur via depth re-construction too sensitive" ContentLicense="CC BY-SA 3.0" />
  <row Id="14452" PostHistoryTypeId="3" PostId="5324" RevisionGUID="45fe0cde-d484-4ed0-a4d5-2f1dbb483b28" CreationDate="2017-07-05T03:58:48.610" UserId="6938" Text="|post-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14453" PostHistoryTypeId="5" PostId="5324" RevisionGUID="7672d9f9-1b4a-44d2-8b14-0af244fa7e85" CreationDate="2017-07-05T04:42:53.790" UserId="231" Comment="Remove &quot;Thanks&quot;" Text="So I have implemented motion blur via depth re-construction using the depth texture and a previous view projection matrix. The shader basically finds the texel coordinate in by using the previous (frame) view projection matrix and subtract the current UV (what's given to fragment) to find a blurring vector. Then I simply blur along this vector by sampling along it and then normalize it with the number of samples, a constant I set at the beginning.&#xD;&#xA;&#xD;&#xA;The problem I'm having is that even a tiny movement will cause the motion blur to ... well blur the scene. I find this too invasive and would like to ... &quot;soften&quot; this effect. I have tried to cap it by saying if the dot product of this blur vector is greater than 0.01, then blur. This sadly creates an oval like artifact in the middle the screen ...&#xD;&#xA;&#xD;&#xA;Anyone have good suggestions on how to handle this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14454" PostHistoryTypeId="5" PostId="5307" RevisionGUID="e3811b75-2298-4484-b2bd-878bc4388a43" CreationDate="2017-07-05T08:03:07.047" UserId="209" Comment="minor spelling corrections" Text="How can a diffused(frosted) glass be modelled in path tracing?&#xD;&#xA;&#xD;&#xA;Currently I am able to define a window poly line as a clear glass material where it transmits or reflects the ray. I am not clear though how it should work if the sheet of glass is frosted(diffuse transmission?).&#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/gr3jB.gif)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14455" PostHistoryTypeId="2" PostId="5325" RevisionGUID="c91f07c2-7eba-409e-94d9-cd6cb6bff4c3" CreationDate="2017-07-05T08:05:30.967" UserId="3073" Text="This projection is a 2d projection, with the Z axis pointing into your screen. When both vertices with the same X&amp;Y are projected to screen space they will occupy the same screen coordinate so your line will either be 1 pixel or invisible.&#xD;&#xA;&#xD;&#xA;If you are expecting a difference in screen position from those 2 coordinates then you need a perspective projection." ContentLicense="CC BY-SA 3.0" />
  <row Id="14456" PostHistoryTypeId="2" PostId="5326" RevisionGUID="a2ef36a8-719b-456f-a92e-e20614525adb" CreationDate="2017-07-05T08:11:40.990" UserId="3073" Text="I don't think uniform arrays can be dynamically sized. In your case you should define the array as the maximum number of lights you will process and then use a uniform to control the number of iterations you do on this array. &#xD;&#xA;&#xD;&#xA;I think (speculate) the likely reason for this is that it would be impossible to determine the location of a uniform if there are variable sized arrays in your uniform list which depend on the value of another uniform.. e.g.&#xD;&#xA;&#xD;&#xA;    uniform int arraySize;               // offset 0&#xD;&#xA;    uniform int myArray[arraySize];      // offset 4&#xD;&#xA;    uniform int anotherVar;              // offset ???? &#xD;&#xA;&#xD;&#xA;GLSL would not know were to place anotherVar, because it would need arraySize to be set with a value before it can compute the offset of 'anotherVar'&#xD;&#xA;&#xD;&#xA;You could also look at using SSBOs if you need larger buffers than uniforms allow&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14457" PostHistoryTypeId="5" PostId="5326" RevisionGUID="a6645dda-287e-47c9-aa3e-16f39d625630" CreationDate="2017-07-05T08:37:40.440" UserId="3073" Comment="added 243 characters in body" Text="I don't think uniform arrays can be dynamically sized. In your case you should define the array as the maximum number of lights you will process and then use a uniform to control the number of iterations you do on this array. On the CPU side you can set a subset of the lights[] array according to the 'size' variable.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    #define MAX_LIGHTS 128&#xD;&#xA;    &#xD;&#xA;    uuniform int size;&#xD;&#xA;    uniform SceneLights lights[MAX_LIGHTS];&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        for(int i = 0; i &lt; size; i++) {&#xD;&#xA;            /* Do Some Calculation */&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I think (speculate) the likely reason for this is that it would be impossible to determine the location of a uniform if there are variable sized arrays in your uniform list which depend on the value of another uniform.. e.g.&#xD;&#xA;&#xD;&#xA;    uniform int arraySize;               // offset 0&#xD;&#xA;    uniform int myArray[arraySize];      // offset 4&#xD;&#xA;    uniform int anotherVar;              // offset ???? &#xD;&#xA;&#xD;&#xA;GLSL would not know were to place anotherVar, because it would need arraySize to be set with a value before it can compute the offset of 'anotherVar'. I suppose the compiler could be clever and re-arrange the order of uniforms to get around this, but this will fail again if you have 2 or more variable sized arrays..&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14458" PostHistoryTypeId="2" PostId="5327" RevisionGUID="e1e99018-27ed-4c86-be4f-9bfd4ab6c6f6" CreationDate="2017-07-05T09:25:43.813" UserId="2687" Text="Is it possible to describe a position of a point $A$ w.r.t. the position and orientation of 3 other points? If so, how?&#xD;&#xA;&#xD;&#xA;FYI, the 3 other points lie on a plane, whereas the point $A$ is not on the plane." ContentLicense="CC BY-SA 3.0" />
  <row Id="14459" PostHistoryTypeId="1" PostId="5327" RevisionGUID="e1e99018-27ed-4c86-be4f-9bfd4ab6c6f6" CreationDate="2017-07-05T09:25:43.813" UserId="2687" Text="How to describe a position of a point w.r.t the position and orientation of 3 other points" ContentLicense="CC BY-SA 3.0" />
  <row Id="14460" PostHistoryTypeId="3" PostId="5327" RevisionGUID="e1e99018-27ed-4c86-be4f-9bfd4ab6c6f6" CreationDate="2017-07-05T09:25:43.813" UserId="2687" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14461" PostHistoryTypeId="5" PostId="5327" RevisionGUID="18c2dadc-51f0-4ea8-9586-d06dbcaee3d8" CreationDate="2017-07-05T09:31:43.673" UserId="2687" Comment="added 8 characters in body" Text="Is it possible to describe a position of a point $A$ (in 3D) w.r.t. the position and orientation of 3 other points? If so, how?&#xD;&#xA;&#xD;&#xA;FYI, the 3 other points lie on a plane, whereas the point $A$ is not on the plane." ContentLicense="CC BY-SA 3.0" />
  <row Id="14462" PostHistoryTypeId="2" PostId="5328" RevisionGUID="665a2143-e786-427a-b1c9-d2ec081a64d5" CreationDate="2017-07-05T10:33:21.623" UserId="2041" Text="&gt; FYI, the 3 other points lie on a plane&#xD;&#xA;&#xD;&#xA;Of course they do. Any set of three points defines a plane (except in the degenerate case joojaa mentions, where they lie on many planes). If the points are $p$, $q$, and $r$, then $(q - p) \wedge (r - p)$ is the normal to the plane; call it $n$.&#xD;&#xA;&#xD;&#xA;This plane defines a co-ordinate system. If you make it the XY plane, then $z = a \dot\ n$. You can also project $a$ onto the plane to get the other two co-ordinates: $x = (a - p) \dot\ (q - p)$ and $y = (a - p) \dot\ (r - p)$.&#xD;&#xA;&#xD;&#xA;Note that the co-ordinate system I've described here is pretty rubbish: it isn't even orthogonal. It's good enough to uniquely identify a point, as long as you're careful about all the signs.&#xD;&#xA;&#xD;&#xA;But if you want an orthonormal basis, you can construct it from this one. First, instead of $q - p$ and $r - p$, normalize those vectors. Then $n$ will also have length 1, and the $x$ axis will also be normal. The last problem is the $y$ axis, which is not orthogonal to the $x$ axis. You can get a better $y$ axis by crossing the other two and normalizing, and while you're doing that you might as well also choose the order to ensure the basis is right-handed. Your three basis vectors are as follows:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\hat{z} &amp; = &amp; \frac{n}{|n|} \\&#xD;&#xA;\hat{x} &amp; = &amp; \frac{q - p}{|q - p} \\&#xD;&#xA;\hat{y} &amp; = &amp; \hat{z} \wedge \hat{x}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="14463" PostHistoryTypeId="5" PostId="5328" RevisionGUID="105a100d-e9bc-4fbd-98ef-efb6cc2c5ecf" CreationDate="2017-07-05T10:42:50.280" UserId="2041" Comment="I missed a normalize bar" Text="&gt; FYI, the 3 other points lie on a plane&#xD;&#xA;&#xD;&#xA;Of course they do. Any set of three points defines a plane (except in the degenerate case joojaa mentions, where they lie on many planes). If the points are $p$, $q$, and $r$, then $(q - p) \wedge (r - p)$ is the normal to the plane; call it $n$.&#xD;&#xA;&#xD;&#xA;This plane defines a co-ordinate system. If you make it the XY plane, then $z = a \dot\ n$. You can also project $a$ onto the plane to get the other two co-ordinates: $x = (a - p) \dot\ (q - p)$ and $y = (a - p) \dot\ (r - p)$.&#xD;&#xA;&#xD;&#xA;Note that the co-ordinate system I've described here is pretty rubbish: it isn't even orthogonal. It's good enough to uniquely identify a point, as long as you're careful about all the signs.&#xD;&#xA;&#xD;&#xA;But if you want an orthonormal basis, you can construct it from this one. First, instead of $q - p$ and $r - p$, normalize those vectors. Then $n$ will also have length 1, and the $x$ axis will also be normal. The last problem is the $y$ axis, which is not orthogonal to the $x$ axis. You can get a better $y$ axis by crossing the other two and normalizing, and while you're doing that you might as well also choose the order to ensure the basis is right-handed. Your three basis vectors are as follows:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\hat{z} &amp; = &amp; \frac{n}{|n|} \\&#xD;&#xA;\hat{x} &amp; = &amp; \frac{q - p}{|q - p|} \\&#xD;&#xA;\hat{y} &amp; = &amp; \hat{z} \wedge \hat{x}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="14464" PostHistoryTypeId="2" PostId="5329" RevisionGUID="60972bc2-1c86-4dfc-9c2f-1ac6117a65b1" CreationDate="2017-07-05T10:56:23.460" UserId="38" Text="What your looking for is closest point on a plane for the 3rd direction but since @DanHulme described this I would not repeat it.&#xD;&#xA;&#xD;&#xA;You can pretty easily use [*affine transformation matrices*](https://en.wikipedia.org/wiki/Affine_transformation) for this. Making a fully defined affine transform from 3 points is a pretty normal operation.&#xD;&#xA;&#xD;&#xA;The standard way is to just use a cross product to produce a third axis (posibly normalized, but wether or not you want to do that depends on application) this way you have 2 axes on the plane and one perpendicular of the plane. &#xD;&#xA;&#xD;&#xA;To form the matrix say you have the vecors $\vec a$, $\vec b$ and $\vec c$ then you formulate the matrix. Then you calcuate the vector from a to b $\vec v_{b-a}$ by subtracting $\vec a$ from $\vec b$,  and a second vector $\vec v_{c-a}$ by subtracting $\vec a$ from $\vec b$. So basically 2 spanning vectors pointing out from $\vec a$. Then you formulate this as a matrix.&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\vec v_{b-a} \\&#xD;&#xA;\vec v_{c-a} \\&#xD;&#xA;|\vec v_{b-a} \times \vec v_{c-a}|\\&#xD;&#xA;\vec a&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Thats about it. Some more meths to orthogonalize the thing." ContentLicense="CC BY-SA 3.0" />
  <row Id="14465" PostHistoryTypeId="5" PostId="5329" RevisionGUID="d46ed5c1-055b-411b-85bd-96592463b60f" CreationDate="2017-07-05T11:03:36.660" UserId="38" Comment="added 11 characters in body" Text="What your looking for is closest point on a plane for the 3rd direction but since @DanHulme described this I would not repeat it.&#xD;&#xA;&#xD;&#xA;You can pretty easily use [*affine transformation matrices*](https://en.wikipedia.org/wiki/Affine_transformation) for this. Making a fully defined affine transform from 3 points is a pretty normal operation.&#xD;&#xA;&#xD;&#xA;The standard way is to just use a cross product to produce a third axis (posibly normalized, but wether or not you want to do that depends on application) this way you have 2 axes on the plane and one perpendicular of the plane. &#xD;&#xA;&#xD;&#xA;To form the matrix say you have the vecors $\vec a$, $\vec b$ and $\vec c$ then you formulate the matrix. Then you calcuate the vector from a to b $\vec v_{b-a}$ by subtracting $\vec a$ from $\vec b$,  and a second vector $\vec v_{c-a}$ by subtracting $\vec a$ from $\vec b$. So basically 2 spanning vectors pointing out from $\vec a$. Then you formulate this as a matrix.&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\vec v_{b-a} \\&#xD;&#xA;\vec v_{c-a} \\&#xD;&#xA;\left|\vec v_{b-a} \times \vec v_{c-a}\right|\\&#xD;&#xA;\vec a&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Thats about it. Some more meths to orthogonalize the thing." ContentLicense="CC BY-SA 3.0" />
  <row Id="14466" PostHistoryTypeId="5" PostId="5329" RevisionGUID="dd1c73b4-6d42-426c-960f-b43f2aacd933" CreationDate="2017-07-05T11:12:59.767" UserId="38" Comment="edited body" Text="What your looking for is closest point on a plane for the 3rd direction but since @DanHulme described this I would not repeat it.&#xD;&#xA;&#xD;&#xA;You can pretty easily use [*affine transformation matrices*](https://en.wikipedia.org/wiki/Affine_transformation) for this. Making a fully defined affine transform from 3 points is a pretty normal operation.&#xD;&#xA;&#xD;&#xA;The standard way is to just use a cross product to produce a third axis (posibly normalized, but wether or not you want to do that depends on application) this way you have 2 axes on the plane and one perpendicular of the plane. &#xD;&#xA;&#xD;&#xA;To form the matrix say you have the vecors $\vec a$, $\vec b$ and $\vec c$ then you formulate the matrix. Then you calcuate the vector from a to b $\vec v_{b-a}$ by subtracting $\vec a$ from $\vec b$,  and a second vector $\vec v_{c-a}$ by subtracting $\vec a$ from $\vec b$. So basically 2 spanning vectors pointing out from $\vec a$. Then you formulate this as a matrix.&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\vec v_{b-a} \\&#xD;&#xA;\vec v_{c-a} \\&#xD;&#xA;\left|\vec v_{b-a} \times \vec v_{c-a}\right|\\&#xD;&#xA;\vec a&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Thats about it. Some more maths to orthogonalize the thing." ContentLicense="CC BY-SA 3.0" />
  <row Id="14467" PostHistoryTypeId="5" PostId="5327" RevisionGUID="eb3d069e-2514-4c33-9631-d92659663b4d" CreationDate="2017-07-05T11:23:53.203" UserId="2687" Comment="added 170 characters in body" Text="Is it possible to describe a position of a point $A$ (in 3D) w.r.t. the position and orientation of 3 other points? If so, how?&#xD;&#xA;&#xD;&#xA;FYI, the 3 other points lie on a plane, whereas the point $A$ is not on the plane.&#xD;&#xA;&#xD;&#xA;Just to elaborate, initially I have the info for all four points. My goal is to find where point $A$ is when the other three points changing position and orientation." ContentLicense="CC BY-SA 3.0" />
  <row Id="14468" PostHistoryTypeId="5" PostId="5329" RevisionGUID="2361223b-c32c-458b-a3b8-831c51b699df" CreationDate="2017-07-05T11:32:44.437" UserId="231" Comment="Typos" Text="What you're looking for is closest point on a plane for the 3rd direction but since @DanHulme described this I would not repeat it.&#xD;&#xA;&#xD;&#xA;You can pretty easily use [*affine transformation matrices*](https://en.wikipedia.org/wiki/Affine_transformation) for this. Making a fully defined affine transform from 3 points is a pretty normal operation.&#xD;&#xA;&#xD;&#xA;The standard way is to just use a cross product to produce a third axis (possibly normalized, but whether or not you want to do that depends on application) this way you have 2 axes on the plane and one perpendicular to the plane. &#xD;&#xA;&#xD;&#xA;To form the matrix say you have the vectors $\vec a$, $\vec b$ and $\vec c$ then you formulate the matrix. Then you calculate the vector from a to b $\vec v_{b-a}$ by subtracting $\vec a$ from $\vec b$, and a second vector $\vec v_{c-a}$ by subtracting $\vec a$ from $\vec c$. So basically 2 spanning vectors pointing out from $\vec a$. Then you formulate this as a matrix.&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\vec v_{b-a} \\&#xD;&#xA;\vec v_{c-a} \\&#xD;&#xA;\left|\vec v_{b-a} \times \vec v_{c-a}\right|\\&#xD;&#xA;\vec a&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Thats about it. Some more maths to orthogonalize the thing." ContentLicense="CC BY-SA 3.0" />
  <row Id="14469" PostHistoryTypeId="2" PostId="5330" RevisionGUID="40f1f3af-5113-486f-8bed-d053327ed581" CreationDate="2017-07-05T14:55:43.540" UserId="6838" Text="So, on the Wikipedia page for the [Phong model][1], it says that the ambient term is a constant, and just gets added on to the other terms. But on other pages, like [Learn OpenGL][2], it says you should take the ambient term and multiply it by the color of the object. So, which one is more correct?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Phong_reflection_model/ &quot;Phong reflection model&quot;&#xD;&#xA;  [2]: https://learnopengl.com/#!Lighting/Basic-Lighting &quot;Learn OpenGL&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14470" PostHistoryTypeId="1" PostId="5330" RevisionGUID="40f1f3af-5113-486f-8bed-d053327ed581" CreationDate="2017-07-05T14:55:43.540" UserId="6838" Text="Ambient Lighting" ContentLicense="CC BY-SA 3.0" />
  <row Id="14471" PostHistoryTypeId="3" PostId="5330" RevisionGUID="40f1f3af-5113-486f-8bed-d053327ed581" CreationDate="2017-07-05T14:55:43.540" UserId="6838" Text="|rendering|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14472" PostHistoryTypeId="2" PostId="5331" RevisionGUID="7278cfdb-fa85-4a84-bae3-c3a79ccd80bb" CreationDate="2017-07-05T15:17:50.497" UserId="2138" Text="Correct is the OpenGL way. If you had a white light ( let's say vec3(255,255,255) )&#xD;&#xA;and just simply added it to a blue object ( vec3(0,0,255) ), the object would seem to be white, which is wrong. But if you were to multiply these colors, the object would be fully illuminated and correctly blue (which is the desired product).&#xD;&#xA;&#xD;&#xA;The thing with ambient light is that it is only influenced by the ambient light intensity and by the color of the object, which means it is not influenced by the lights position, direction or anything of the sort. That is why you can think of it as &quot;simply adding it as a constant&quot;.&#xD;&#xA;&#xD;&#xA;We use ambient light mostly to simulate reflected light in the scene, which is very hard to simulate otherwise (without raytracing). It's a fairly good and cheap alternative." ContentLicense="CC BY-SA 3.0" />
  <row Id="14473" PostHistoryTypeId="5" PostId="5330" RevisionGUID="7e9de0af-6971-4eb5-9015-5f601ca96840" CreationDate="2017-07-05T15:19:40.303" UserId="2041" Comment="correct link" Text="So, on the Wikipedia page for the [Phong model][1], it says that the ambient term is a constant, and just gets added on to the other terms. But on other pages, like [Learn OpenGL][2], it says you should take the ambient term and multiply it by the color of the object. So, which one is more correct?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Phong_reflection_model &quot;Phong reflection model&quot;&#xD;&#xA;  [2]: https://learnopengl.com/#!Lighting/Basic-Lighting &quot;Learn OpenGL&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14474" PostHistoryTypeId="2" PostId="5332" RevisionGUID="3c0c62f9-e84d-4f70-9235-c4b9aefe5530" CreationDate="2017-07-05T15:26:14.490" UserId="2041" Text="The relevant equation on the Wikipedia page follows:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I_\text{p} = k_\text{a} i_\text{a} + \sum_{m\;\in\;\text{lights}} (k_\text{d} (\hat{L}_m \cdot \hat{N}) i_{m,\text{d}} + k_\text{s} (\hat{R}_m \cdot \hat{V})^{\alpha}i_{m,\text{s}})&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In this equation, all the $k$ and $i$ terms are not numbers but colours (RGB intensities). This includes $k_a$ and $i_a$: the ambient colour of the object, and the ambient illumination colour, respectively. The ambient term isn't a constant: it's a product of an intensity and albedo, just like the specular and diffuse terms. The only difference is that the lighting and view directions aren't a factor in this term.&#xD;&#xA;&#xD;&#xA;It's very unusual to have $k_a$ different from the diffuse colour, so you can think of it as multiplying by &quot;the colour of the object&quot;. That said, it's quite common for $i_a$ to be a distinct colour: for example, if you're using a yellowish directional light for direct sunlight, you might want the ambient light to be blueish to stand in for skylight." ContentLicense="CC BY-SA 3.0" />
  <row Id="14475" PostHistoryTypeId="50" PostId="5200" RevisionGUID="6c9073e4-e73e-4379-b7bc-b12792d12f20" CreationDate="2017-07-05T17:54:03.280" UserId="-1" />
  <row Id="14476" PostHistoryTypeId="2" PostId="5333" RevisionGUID="d94d33bd-9d85-404e-9b1b-aff421460022" CreationDate="2017-07-05T22:24:12.907" UserId="6946" Text="    module initial(letter, size) {&#xD;&#xA;      linear_extrude(height=size*4, center=true) {&#xD;&#xA;        text(letter, size=size, halign=&quot;center&quot;, valign=&quot;center&quot;, font=font);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm using this module to generate very tall letters that I then cut out of other shapes using &quot;difference&quot;.&#xD;&#xA;&#xD;&#xA;This works well for some letters (like M), but leaves detached pieces floating in the middle for letters like &quot;O&quot; or &quot;A&quot;.&#xD;&#xA;&#xD;&#xA;I'd like to know how to get just the outline of the letter without changing the shape of that outline the way the &quot;hull&quot; function would." ContentLicense="CC BY-SA 3.0" />
  <row Id="14477" PostHistoryTypeId="1" PostId="5333" RevisionGUID="d94d33bd-9d85-404e-9b1b-aff421460022" CreationDate="2017-07-05T22:24:12.907" UserId="6946" Text="OpenSCAD: Using outline of 2D shape" ContentLicense="CC BY-SA 3.0" />
  <row Id="14478" PostHistoryTypeId="3" PostId="5333" RevisionGUID="d94d33bd-9d85-404e-9b1b-aff421460022" CreationDate="2017-07-05T22:24:12.907" UserId="6946" Text="|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14479" PostHistoryTypeId="2" PostId="5334" RevisionGUID="1d0e5248-0ab4-41b7-932f-a113c0647610" CreationDate="2017-07-05T23:48:02.617" UserId="2108" Text="I'm trying to break a continuous line segment into multiple, straight segments. [![Group of line segments as connected][1]][1]&#xD;&#xA;&#xD;&#xA;I've tried using the Hough transform but have found it unreliable for getting the line segments I'm looking for and because it demands too much fine tuning to fit the automated medium I'm working in. &#xD;&#xA;&#xD;&#xA;Analyzing points (comparing slopes/averages) as they change has shown some success, but the lines found are often too segmented or too unsegmented (just the whole line), proving unreliable so far. These are also prone to give too much of the subsequent line before cutting off when they have worked.&#xD;&#xA;&#xD;&#xA;Contextual restrictions include:&#xD;&#xA;&#xD;&#xA; 1. Only one 'Y' value per X pt (this image doesn't show this, but the property holds).&#xD;&#xA; 2. There are no gaps between pts in the line.&#xD;&#xA; 3. Noise is possible, but not that bad usually (within a few pixels of being correct).&#xD;&#xA; 4. The lines being detected are straight, not curved.&#xD;&#xA; 5. This is being developed in C++ using the SDL2 framework.&#xD;&#xA;&#xD;&#xA;I feel like I'm over complicating this question, how can I find the points that separate the segments? I suspect something comparing averages or averages of averages might be the way to go - Thanks.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ToT9w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14480" PostHistoryTypeId="1" PostId="5334" RevisionGUID="1d0e5248-0ab4-41b7-932f-a113c0647610" CreationDate="2017-07-05T23:48:02.617" UserId="2108" Text="Finding Segments in Continuous line" ContentLicense="CC BY-SA 3.0" />
  <row Id="14481" PostHistoryTypeId="3" PostId="5334" RevisionGUID="1d0e5248-0ab4-41b7-932f-a113c0647610" CreationDate="2017-07-05T23:48:02.617" UserId="2108" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14482" PostHistoryTypeId="5" PostId="5330" RevisionGUID="f75da793-5b10-45b3-9dd1-54f64bb48e2d" CreationDate="2017-07-06T01:00:45.077" UserId="6546" Comment="Reworded Question" Text="On the Wikipedia page for the [Phong model][1], it says that the ambient term is a constant, and just gets added on to the other terms. But on other pages like [LearnOpenGL][2] it says you should take the ambient term and multiply it by the color of the object. Which one is correct?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Phong_reflection_model &quot;Phong reflection model&quot;&#xD;&#xA;  [2]: https://learnopengl.com/#!Lighting/Basic-Lighting &quot;Learn OpenGL&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14483" PostHistoryTypeId="24" PostId="5330" RevisionGUID="f75da793-5b10-45b3-9dd1-54f64bb48e2d" CreationDate="2017-07-06T01:00:45.077" Comment="Proposed by 6546 approved by 6838 edit id of 258" ContentLicense="CC BY-SA 3.0" />
  <row Id="14484" PostHistoryTypeId="2" PostId="5335" RevisionGUID="ac6ef374-df49-480a-a429-0f294781e702" CreationDate="2017-07-06T07:35:15.887" UserId="6951" Text="I'm looking for a way to procedurally create a realistically looking texture overlay simulating the object being shrink wrapped.&#xD;&#xA;&#xD;&#xA;It is only used to be added to single images, so it does not need to behave correctly in an animation with changes of position or angle of the object, camera or light source(s).&#xD;&#xA;&#xD;&#xA;I already tried by implementing a grayscale [plasma effect](https://en.wikipedia.org/wiki/Plasma_effect). It looks nice but not real:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Below you can find some examples of what I am hoping to achieve.&#xD;&#xA;&#xD;&#xA;Do you have any suggestions on how something like this could be generated?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/J6Kzf.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7Omsl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/go88a.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/0pslh.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/OlfMd.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XYHIx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14485" PostHistoryTypeId="1" PostId="5335" RevisionGUID="ac6ef374-df49-480a-a429-0f294781e702" CreationDate="2017-07-06T07:35:15.887" UserId="6951" Text="procedurally generating a texture overlay simulating shrink wrap" ContentLicense="CC BY-SA 3.0" />
  <row Id="14486" PostHistoryTypeId="3" PostId="5335" RevisionGUID="ac6ef374-df49-480a-a429-0f294781e702" CreationDate="2017-07-06T07:35:15.887" UserId="6951" Text="|texture|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14487" PostHistoryTypeId="5" PostId="5335" RevisionGUID="ffff747b-a8be-49c5-b71b-e1609b5395db" CreationDate="2017-07-06T08:51:25.780" UserId="6951" Comment="added 108 characters in body" Text="I'm looking for a way to procedurally create a realistically looking texture overlay simulating the object being shrink wrapped.&#xD;&#xA;&#xD;&#xA;It is only used to be added to single images, so it does not need to behave correctly in an animation with changes of position or angle of the object, camera or light source(s).&#xD;&#xA;&#xD;&#xA;I already tried by implementing a grayscale [plasma effect](https://en.wikipedia.org/wiki/Plasma_effect). It looks nice but not real:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Below you can find some examples of what I am hoping to achieve.&#xD;&#xA;&#xD;&#xA;Do you have any suggestions on how something like this could be generated? I'm looking to produce thousands of unique textures, so there should be some variation/randomness involved.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/J6Kzf.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7Omsl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/go88a.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/0pslh.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/OlfMd.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/XYHIx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14488" PostHistoryTypeId="5" PostId="5334" RevisionGUID="235110c0-ad66-482c-9c52-0191efd78a62" CreationDate="2017-07-06T09:16:02.783" UserId="231" Comment="Minor tidying" Text="I'm trying to break a continuous line segment into multiple, straight segments. [![Group of line segments as connected][1]][1]&#xD;&#xA;&#xD;&#xA;I've tried using the Hough transform but have found it unreliable for getting the line segments I'm looking for and because it demands too much fine tuning to fit the automated medium I'm working in. &#xD;&#xA;&#xD;&#xA;Analyzing points (comparing slopes/averages) as they change has shown some success, but the lines found are often too segmented or too unsegmented (just the whole line), proving unreliable so far. These are also prone to give too much of the subsequent line before cutting off when they have worked.&#xD;&#xA;&#xD;&#xA;Contextual restrictions include:&#xD;&#xA;&#xD;&#xA; 1. Only one 'Y' value per X point (this image doesn't show this, but the property holds).&#xD;&#xA; 2. There are no gaps between points in the line.&#xD;&#xA; 3. Noise is possible, but not that bad usually (within a few pixels of being correct).&#xD;&#xA; 4. The lines being detected are straight, not curved.&#xD;&#xA; 5. This is being developed in C++ using the SDL2 framework.&#xD;&#xA;&#xD;&#xA;I feel like I'm overcomplicating this question. How can I find the points that separate the segments? I suspect something comparing averages or averages of averages might be the way to go.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ToT9w.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14489" PostHistoryTypeId="6" PostId="5334" RevisionGUID="235110c0-ad66-482c-9c52-0191efd78a62" CreationDate="2017-07-06T09:16:02.783" UserId="231" Comment="Minor tidying" Text="|c++|image-processing|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14490" PostHistoryTypeId="2" PostId="5336" RevisionGUID="b3a2307b-04f8-46fa-b179-fec7762d82f8" CreationDate="2017-07-07T08:46:44.143" UserId="4558" Text="I'm in search for an algorithm that takes the left side of the following graphic as an input and outputs a minimal amount of convex polygons as seen on the right side of the graphic.&#xD;&#xA;&#xD;&#xA;[![input and output of the wanted algorithm][1]][1]&#xD;&#xA;&#xD;&#xA;The input mesh can be very complex and could contain several holes. The position of the vertices are not constrained to a grid.&#xD;&#xA;&#xD;&#xA;The use case for this is the creation of multiple polygon shapes for the Box2D physics engine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GMer4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14491" PostHistoryTypeId="1" PostId="5336" RevisionGUID="b3a2307b-04f8-46fa-b179-fec7762d82f8" CreationDate="2017-07-07T08:46:44.143" UserId="4558" Text="List of triangles to minimum amount of convex polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="14492" PostHistoryTypeId="3" PostId="5336" RevisionGUID="b3a2307b-04f8-46fa-b179-fec7762d82f8" CreationDate="2017-07-07T08:46:44.143" UserId="4558" Text="|algorithm|computational-geometry|geometry|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14493" PostHistoryTypeId="5" PostId="5336" RevisionGUID="a36c5590-48b2-4458-8756-04020d526d90" CreationDate="2017-07-07T11:40:03.150" UserId="4558" Comment="added additional information" Text="I'm in search for an algorithm that takes the left side of the following graphic as an input and outputs a minimal amount of convex polygons as seen on the right side of the graphic.&#xD;&#xA;&#xD;&#xA;[![input and output of the wanted algorithm][1]][1]&#xD;&#xA;&#xD;&#xA;The input mesh can be very complex and could contain several holes. The position of the vertices are not constrained to a grid.&#xD;&#xA;&#xD;&#xA;The use case for this is the creation of multiple polygon shapes for the Box2D physics engine.&#xD;&#xA;&#xD;&#xA;Additional information:&#xD;&#xA;&#xD;&#xA;* The result does not need to be deterministic.&#xD;&#xA;* The result does not need to be vertically striped. &#xD;&#xA;* As trichoplax noted, the right part of the picture does not resemble the minimal polygon count that can be achieved. It's just an example.&#xD;&#xA;* It's not necessary that it will find the absolute minimum of convex polygons. A fast algorithm is preferred over a &quot;best solution&quot; one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GMer4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14494" PostHistoryTypeId="2" PostId="5337" RevisionGUID="30d9464c-d19c-46f9-b6b1-58227e00dcf4" CreationDate="2017-07-07T14:17:12.117" UserId="6660" Text="In my program, I use a additional frame buffer to render something into a texture, which I will reference it's handle in next draw command. And draw the texture back to the default frame buffer.&#xD;&#xA;My program almost run like this:&#xD;&#xA;&#xD;&#xA;    frame buffer create and attached by a GL_TEXTURE_2D texture and other setup&#xD;&#xA;    glGetTextureHandle&#xD;&#xA;    glMakeHandleResident&#xD;&#xA;    &#xD;&#xA;    bind this frame buffer&#xD;&#xA;    glclear(1.0f, 0.0f, 0.0f, 1.0f)&#xD;&#xA;&#xD;&#xA;    glBindFramebuffer to 0(back to default frame buffer)&#xD;&#xA;    ShaderUse//nothing but return texture's color&#xD;&#xA;    glUniformHandleui64(location, textureHandle)//witch is the texture above&#xD;&#xA;    //if I use normal bind texture, the result will be correct&#xD;&#xA;    glDraw*//just draw a quad&#xD;&#xA;&#xD;&#xA;Here I got a strange issue, The 2nd glDraw cmd gives an empty result(Back Buffer is an black image). And I also checked the first frame buffer's render texture witch is a pure red image, and it's a correct result. And my GPU is AMD R7 200.&#xD;&#xA;But when I change bindless texture to normal bind texture style, and everything is ok finally.Also I checked in NV GPU-GTX650 with same program, and the result is also ok.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am sure there is no opengl error occurred in my program, and I also checked GL_ARB_bindless_texture extension is supported by my devices.&#xD;&#xA;&#xD;&#xA;So I wonder, am I missing some memory sync or coherent?&#xD;&#xA;&#xD;&#xA;I also looked up to the document and I found this:&#xD;&#xA;&#xD;&#xA;&gt;  (4) Can texture or sampler objects be modified while they are used by&#xD;&#xA;&gt; a&#xD;&#xA;&gt;         texture or image handle?&#xD;&#xA;&gt; &#xD;&#xA;&gt;       RESOLVED:  No.  If such changes were permitted, each modification to the&#xD;&#xA;&gt;       texture object would require potential synchronization with one or more&#xD;&#xA;&gt;       texture/image handles extracted from the texture.  This seems like a lot&#xD;&#xA;&gt;       of bookkeeping with little benefit.  One exception to this rule is that&#xD;&#xA;&gt;       individual texels of such texture objects may still be updated with APIs&#xD;&#xA;&gt;       such as TexSubImage* and by rendering to a framebuffer object to which&#xD;&#xA;&gt;       the texture is attached.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**One exception to this rule is that&#xD;&#xA;      individual texels of such texture objects may still be updated with APIs&#xD;&#xA;      such as TexSubImage* and by rendering to a framebuffer object to which     the texture is attached.**&#xD;&#xA;&#xD;&#xA;Does glClear belong to this exception?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14495" PostHistoryTypeId="1" PostId="5337" RevisionGUID="30d9464c-d19c-46f9-b6b1-58227e00dcf4" CreationDate="2017-07-07T14:17:12.117" UserId="6660" Text="glClear's result can't be seen when using bindless texture" ContentLicense="CC BY-SA 3.0" />
  <row Id="14496" PostHistoryTypeId="3" PostId="5337" RevisionGUID="30d9464c-d19c-46f9-b6b1-58227e00dcf4" CreationDate="2017-07-07T14:17:12.117" UserId="6660" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14497" PostHistoryTypeId="5" PostId="5337" RevisionGUID="0dff91d8-efdf-492c-ba3b-53391346f5b2" CreationDate="2017-07-07T14:26:55.497" UserId="6660" Comment="added 16 characters in body" Text="In my program, I use a additional frame buffer to render something into a texture(only a glClear), which I will reference it's handle in next draw command. And draw the texture back to the default frame buffer.&#xD;&#xA;My program almost run like this:&#xD;&#xA;&#xD;&#xA;    frame buffer create and attached by a GL_TEXTURE_2D texture and other setup&#xD;&#xA;    glGetTextureHandle&#xD;&#xA;    glMakeHandleResident&#xD;&#xA;    &#xD;&#xA;    bind this frame buffer&#xD;&#xA;    glclear(1.0f, 0.0f, 0.0f, 1.0f)&#xD;&#xA;&#xD;&#xA;    glBindFramebuffer to 0(back to default frame buffer)&#xD;&#xA;    ShaderUse//nothing but return texture's color&#xD;&#xA;    glUniformHandleui64(location, textureHandle)//witch is the texture above&#xD;&#xA;    //if I use normal bind texture, the result will be correct&#xD;&#xA;    glDraw*//just draw a quad&#xD;&#xA;&#xD;&#xA;Here I got a strange issue, The 2nd glDraw cmd gives an empty result(Back Buffer is an black image). And I also checked the first frame buffer's render texture witch is a pure red image, and it's a correct result. And my GPU is AMD R7 200.&#xD;&#xA;But when I change bindless texture to normal bind texture style, and everything is ok finally.Also I checked in NV GPU-GTX650 with same program, and the result is also ok.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am sure there is no opengl error occurred in my program, and I also checked GL_ARB_bindless_texture extension is supported by my devices.&#xD;&#xA;&#xD;&#xA;So I wonder, am I missing some memory sync or coherent?&#xD;&#xA;&#xD;&#xA;I also looked up to the document and I found this:&#xD;&#xA;&#xD;&#xA;&gt;  (4) Can texture or sampler objects be modified while they are used by&#xD;&#xA;&gt; a&#xD;&#xA;&gt;         texture or image handle?&#xD;&#xA;&gt; &#xD;&#xA;&gt;       RESOLVED:  No.  If such changes were permitted, each modification to the&#xD;&#xA;&gt;       texture object would require potential synchronization with one or more&#xD;&#xA;&gt;       texture/image handles extracted from the texture.  This seems like a lot&#xD;&#xA;&gt;       of bookkeeping with little benefit.  One exception to this rule is that&#xD;&#xA;&gt;       individual texels of such texture objects may still be updated with APIs&#xD;&#xA;&gt;       such as TexSubImage* and by rendering to a framebuffer object to which&#xD;&#xA;&gt;       the texture is attached.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**One exception to this rule is that&#xD;&#xA;      individual texels of such texture objects may still be updated with APIs&#xD;&#xA;      such as TexSubImage* and by rendering to a framebuffer object to which     the texture is attached.**&#xD;&#xA;&#xD;&#xA;Does glClear belong to this exception?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14498" PostHistoryTypeId="2" PostId="5338" RevisionGUID="2b56f8d8-b93b-4ab2-82df-4346e442ffaf" CreationDate="2017-07-07T14:32:30.150" UserId="137" Text="If a edge corner is concave then it needs to border 2 of the output polygons.&#xD;&#xA;&#xD;&#xA;So one algorithm would be to find all concave corners (including the ones in the holes) and making cuts starting from them to other concave corners. This will either create 2 new polygons or join 2 holes into 1 or connect a hole to the outside. &#xD;&#xA;&#xD;&#xA;The cut from a concave corner should be constrained by the angle or it will create a new concave corner that then needs to be cut again." ContentLicense="CC BY-SA 3.0" />
  <row Id="14499" PostHistoryTypeId="5" PostId="5338" RevisionGUID="cc5d1844-df34-4b9f-a190-99cc39a8bdd6" CreationDate="2017-07-07T15:12:41.807" UserId="137" Comment="deleted 4 characters in body" Text="If a edge corner is concave then it needs to border 2 of the output polygons.&#xD;&#xA;&#xD;&#xA;So one algorithm would be to find all concave corners (including the ones in the holes) and making cuts starting from them to other concave corners. This will split the polygon in two or join 2 holes into 1 or connect a hole to the outside. &#xD;&#xA;&#xD;&#xA;The cut from a concave corner should be constrained by the angle or it will create a new concave corner that then needs to be cut again." ContentLicense="CC BY-SA 3.0" />
  <row Id="14503" PostHistoryTypeId="2" PostId="5340" RevisionGUID="5ed77705-55f0-4e37-880c-973ffdff7312" CreationDate="2017-07-07T19:11:47.757" UserId="2654" Text="This is clearly a bug in AMD's driver, though it's a very understandable one.&#xD;&#xA;&#xD;&#xA;What is probably happening is that the driver does not correctly detect that there is a dependency between the framebuffer operation and the use of the texture. It's easy for an API to tell that you've bound a texture that was the subject of an outstanding render target command, since the API sees exactly what texture you're going to use. It can simply keep track of the texture objects recently used in an FBO, and if it sees you render with one of them bound, it issues whatever dependencies are needed to ensure that the operation is complete before the rendering operation.&#xD;&#xA;&#xD;&#xA;It's much harder when you're not *binding* the texture; you're just passing an arbitrary number to the shader. The API has no idea if that number represents a render target.&#xD;&#xA;&#xD;&#xA;To verify that this is the problem, insert a `glFinish()` between the clear command and the draw command that uses the texture. Odds are good that it will go away (or at least be partially mitigated). A `glTextureBarrier()` call might also fix it. If you're getting the texture handle after attaching the texture to the FBO, you might also want to get the handle first. Just in case that shakes something loose.&#xD;&#xA;&#xD;&#xA;Note that you shouldn't *have* to do any of these; the specification requires that things work exactly as you expect.&#xD;&#xA;&#xD;&#xA;What AMDs driver needs to do is to realize that you're using bindless texturing and emit the appropriate dependency operations when you change framebuffer render targets. That is, it has to assume that any `glBindFramebuffer` or any calls that modify the FBO that's currently bound will result in any subsequent rendering command reading from previously written textures. Therefore, it *must* issue a synchronization at the first rendering command that involves a bindless texture operation.&#xD;&#xA;&#xD;&#xA;Either that, or it somehow has to figure out which arbitrary integers represent which textures. This is very difficult, since you can pass those handles in a variety of ways. UBOs, for example; you don't want implementations combing through images." ContentLicense="CC BY-SA 3.0" />
  <row Id="14504" PostHistoryTypeId="5" PostId="5340" RevisionGUID="3b501e11-e74b-4574-a48a-195b3b6f602a" CreationDate="2017-07-07T19:58:38.320" UserId="2654" Comment="added 50 characters in body" Text="This is clearly a bug in AMD's driver, though it's a very understandable one.&#xD;&#xA;&#xD;&#xA;What is probably happening is that the driver does not correctly detect that there is a dependency between the framebuffer operation and the use of the texture. It's easy for an API to tell that you've bound a texture that was the subject of an outstanding render target command, since the API sees exactly what texture you're going to use. It can simply keep track of the texture objects recently used in an FBO, and if it sees you render with one of them bound, it issues whatever dependencies are needed to ensure that the operation is complete before the rendering operation.&#xD;&#xA;&#xD;&#xA;It's much harder when you're not *binding* the texture; you're just passing an arbitrary number to the shader. The API has no idea if that number represents a render target.&#xD;&#xA;&#xD;&#xA;To verify that this is the problem, insert a `glFinish()` between the clear command and the draw command that uses the texture. Odds are good that it will go away (or at least be partially mitigated). A `glTextureBarrier()` call might also fix it. If you're getting the texture handle after attaching the texture to the FBO, you might also want to get the handle first. Just in case that shakes something loose.&#xD;&#xA;&#xD;&#xA;Note that you shouldn't *have* to do any of these; the specification requires that things work exactly as you expect.&#xD;&#xA;&#xD;&#xA;What AMDs driver needs to do is to realize that you're using bindless texturing and emit the appropriate dependency operations when you change framebuffer render targets. That is, it has to assume that any `glBindFramebuffer` or any calls that modify the FBO that's currently bound will result in any subsequent rendering command reading from previously written textures. Therefore, it *must* issue a synchronization at the first rendering command that involves a bindless texture operation (if the texture used by the FBO is made resident).&#xD;&#xA;&#xD;&#xA;Either that, or it somehow has to figure out which arbitrary integers represent which textures. This is very difficult, since you can pass those handles in a variety of ways. UBOs, for example; you don't want implementations combing through images." ContentLicense="CC BY-SA 3.0" />
  <row Id="14509" PostHistoryTypeId="2" PostId="5342" RevisionGUID="b4de96f8-533d-41fb-9bf9-35a35187b0fc" CreationDate="2017-07-08T18:26:23.773" UserId="6966" Text="You need to round down the mipmap sizes.&#xD;&#xA;In your case the correct sequence is 200, 100, 50, 25, 12, 6, 3, 1." ContentLicense="CC BY-SA 3.0" />
  <row Id="14510" PostHistoryTypeId="5" PostId="4793" RevisionGUID="fa281f51-d419-4cf9-884a-e1719a997a9c" CreationDate="2017-07-08T19:19:46.010" UserId="5852" Comment="deleted 3 characters in body" Text="This question has an answer here:&lt;br /&gt;&#xD;&#xA;https://stackoverflow.com/questions/42596516/generating-mipmaps-manually&lt;br /&gt;&#xD;&#xA;It was a silly mistake. Sorry for the inconvenience.&#xD;&#xA;&#xD;&#xA;OpenGL is fairly difficult to learn.&lt;br /&gt;&#xD;&#xA;According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.&#xD;&#xA;&#xD;&#xA;I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level.&#xD;&#xA;Why?&#xD;&#xA;if the triangle is closer to any other mipmap level, why does not take it?&#xD;&#xA;&#xD;&#xA;I really hate putting a bunch of code in my questions because I force others to waste time analyzing the code instead of putting the most revelant snippet code, but I don't know where is the problem and I have not alternative. Sorry :(&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(800, 600, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0, 800, 600);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //THE MOST INTERESTING PART&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 0 and white color&#xD;&#xA;    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[200*200*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 200*200*3; i++){&#xD;&#xA;    	imageArray[i] = 255;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with level 1-8 and blue color&#xD;&#xA;    unsigned char imageArray2[100*100*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 100*100*3; i++){&#xD;&#xA;    	if((i+1)%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //All mipmap levels&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and uncomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    //(un)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle&#xD;&#xA;    //It doesn't matter, this program always take the first mipmap level&#xD;&#xA;    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?&#xD;&#xA;    {&#xD;&#xA;//    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,		//Bigger triangle&#xD;&#xA;			-0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f,	//Smaller triangle&#xD;&#xA;			-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f		//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;&#xD;&#xA;For any reason, these two lines doesn't work together&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT:&lt;/h1&gt;** I think that the two lines above doesn't work because mipmaps only works with GL_TEXTURE_MIN_FILTER. However, when I replace&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    //If I comment the line above and uncomment the following, the program will show a black triangle. Why?&#xD;&#xA;    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;&#xD;&#xA;with&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;it shows a black triangle :(&#xD;&#xA;&#xD;&#xA;I used glGetError as Dan Hulme stated in the comments but with the last change I made to my code I have not errors returned by glGetError but still showing a black triangle.&#xD;&#xA;&#xD;&#xA;**&lt;h1&gt;EDIT 2:&lt;/h1&gt;** I solved the problem setting the sizes by powers of 2. However, it now takes only the first mipmap level. Here is the new source code:&#xD;&#xA;&lt;pre&gt;&#xD;&#xA;&lt;code&gt;#include &amp;lt;iostream&amp;gt;&#xD;&#xA;&#xD;&#xA;#define GLEW_STATIC&#xD;&#xA;#include &amp;lt;GL/glew.h&amp;gt;&#xD;&#xA;&#xD;&#xA;#include &amp;lt;GLFW/glfw3.h&amp;gt;&#xD;&#xA;&#xD;&#xA;const GLchar* VERTEX_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                           \n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec2 position;     \n&quot;&#xD;&#xA;		&quot;layout (location = 1) in vec2 myTexCoord;   \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;out vec2 TexCoord;                          \n&quot;&#xD;&#xA;		&quot;                                            \n&quot;&#xD;&#xA;		&quot;void main()                                 \n&quot;&#xD;&#xA;		&quot;{                                           \n&quot;&#xD;&#xA;		&quot;    gl_Position = vec4(position,0.0f, 1.0f);\n&quot;&#xD;&#xA;		&quot;    TexCoord = myTexCoord;					 \n&quot;&#xD;&#xA;		&quot;}                                           \n&quot;;&#xD;&#xA;&#xD;&#xA;const GLchar* FRAGMENT_SHADER_SOURCE =&#xD;&#xA;		&quot;#version 330 core                         \n&quot;&#xD;&#xA;		&quot;in vec2 TexCoord;                         \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;out vec4 color;                           \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;uniform sampler2D ourTexture;             \n&quot;&#xD;&#xA;		&quot;                                          \n&quot;&#xD;&#xA;		&quot;void main()                               \n&quot;&#xD;&#xA;		&quot;{                                         \n&quot;&#xD;&#xA;		&quot;    color = texture(ourTexture, TexCoord);\n&quot;&#xD;&#xA;		&quot;}                                         \n&quot;;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	//Change the value of size by 1,2,4,8,16,32,64,128 or 256 and see how the color of the triangle doesn't change. Why does it happen?&#xD;&#xA;	GLint size = 128;&#xD;&#xA;&#xD;&#xA;	//INIT STUFFS&#xD;&#xA;    glfwInit();&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(size,size, &quot;&quot;, nullptr, nullptr);&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    glewExperimental = GL_TRUE;&#xD;&#xA;    glewInit();&#xD;&#xA;    glViewport(0, 0,size,size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with odd level and green color&#xD;&#xA;    //The dimensions are 256 x 256 and is multiplied by 3 because I defined R,G and B colors&#xD;&#xA;    unsigned char imageArray[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if((i+2)%3 == 0)&#xD;&#xA;    		imageArray[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Our image for the mipmap with pair level and red color&#xD;&#xA;    unsigned char imageArray2[256*256*3];&#xD;&#xA;    for(int i = 0; i &amp;lt; 256*256*3; i++){&#xD;&#xA;    	if(i%3 == 0)&#xD;&#xA;    		imageArray2[i] = 255;&#xD;&#xA;    	else&#xD;&#xA;    		imageArray2[i] = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);&#xD;&#xA;&#xD;&#xA;    //All mipmap levels defined by hand&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 64,  64,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 32,  32,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 16,  16,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 8,   8,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;    		-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,	//vertex coordinates&#xD;&#xA;			0.0f, 0.0f								//Triangle's texture coordinates&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //VAOs AND VBOs&#xD;&#xA;    GLuint VAO, VBO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));&#xD;&#xA;&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //SHADERS&#xD;&#xA;    GLuint program;&#xD;&#xA;	GLuint vertex, fragment;&#xD;&#xA;&#xD;&#xA;	vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    glShaderSource(vertex, 1, &amp;VERTEX_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(vertex);&#xD;&#xA;&#xD;&#xA;    fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    glShaderSource(fragment, 1, &amp;FRAGMENT_SHADER_SOURCE, NULL);&#xD;&#xA;    glCompileShader(fragment);&#xD;&#xA;&#xD;&#xA;    program = glCreateProgram();&#xD;&#xA;    glAttachShader(program, vertex);&#xD;&#xA;    glAttachShader(program, fragment);&#xD;&#xA;    glLinkProgram(program);&#xD;&#xA;&#xD;&#xA;    glDeleteShader(vertex);&#xD;&#xA;    glDeleteShader(fragment);&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //DRAWING OUR TRIANGLE&#xD;&#xA;    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0,3);&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;    glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;&lt;/pre&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14512" PostHistoryTypeId="2" PostId="5343" RevisionGUID="ffcfee77-dff1-4e50-9160-74d3c02466d8" CreationDate="2017-07-09T10:11:17.017" UserId="6968" Text="The silhouette curve of a quadric surface is a conic (ellipse, parabola, hyperbola, etc.). Suppose you have the quadric $\mathbf{X}^T \mathbf{M} \mathbf{X} = 0$ and your eye is at the point $\mathbf{Y}$. Then the silhouette curve is the intersection of the quadric and the so-called polar plane of $\mathbf{Y}$, which is $\mathbf{Y}^T \mathbf{M} \mathbf{X} = 0$.&#xD;&#xA;&#xD;&#xA;For anything more complex than quadrics, things get nasty in a hurry, and you won't find any analytic solutions; you'll need numerical methods to trace the curve. Even the silhouette of a torus is pretty complex. So, in essence, the best you can do is compute discrete points along the curve, and use these to construct either a polyline or a spline of some sort. But, of course, you can always get a polyline just by tesselating the surface and finding the silhouette of the tesselation.&#xD;&#xA;&#xD;&#xA;One approach would be to approximate your surface of revolution by quadrics, but that may not be any better than tesselating. You'd get a piecewise conic curve, instead of a polyline, which might be an improvement.&#xD;&#xA;&#xD;&#xA;Note that if your surface is not G2, then it's silhouette will not be G1 (i.e. it may have sharp corners). Tracing a curve with corners is tricky.&#xD;&#xA;&#xD;&#xA;There are silhouette generation functions in geometry kernels like Parasolid and ACIS. Maybe in OpenCascade, too." ContentLicense="CC BY-SA 3.0" />
  <row Id="14513" PostHistoryTypeId="2" PostId="5344" RevisionGUID="e1a174a2-e899-4504-b37a-7593fc442b66" CreationDate="2017-07-09T10:22:58.737" UserId="6968" Text="Since we're not told what defintion of &quot;center&quot; to use, we may as well use the easiest. This would be &#xD;&#xA;$$&#xD;&#xA;\text{Center} = \frac14( \mathbf{P}_0 + \mathbf{P}_1 + \mathbf{P}_2 + \mathbf{P}_3)&#xD;&#xA;$$&#xD;&#xA;where $\mathbf{P}_0$, $\mathbf{P}_1$,  $\mathbf{P}_2$,  $\mathbf{P}_3$ are the control points pf the curve. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14514" PostHistoryTypeId="2" PostId="5345" RevisionGUID="91fdd0f7-875a-4240-92cb-146da68fb786" CreationDate="2017-07-09T10:31:40.207" UserId="6968" Text="As far as I know, there are no standard shapes for (physical) French curves. The folks who manufacture them are free to choose any shapes they like. Of course, they choose shapes that look &quot;nice&quot;, which typically means curvature that's either monotonely increasing or has a single peak value.&#xD;&#xA;&#xD;&#xA;So, you can't solve this problem unless you make some assumptions about the specific shapes of French curves available to your user(s).&#xD;&#xA;&#xD;&#xA;Once you have done this, you can model the shape of the French curve as a Bezier curve (for example). Then the problem is to position/orient this Bezier curve so that it fits the data, which is a simple least-squares fitting problem. I'll provide more details if you confirm that this approach is promising.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14515" PostHistoryTypeId="2" PostId="5346" RevisionGUID="00105d34-6959-4434-a9fa-28c1a96d1786" CreationDate="2017-07-09T10:55:46.910" UserId="6968" Text="If you use the same $\mathbf{B}$ matrix on each segment, then you are constructing a so-called &quot;uniform&quot; b-spline. This means that the parameter increment over each segment is a constant (typically $=1$). Uniform b-splines often have undesirable shapes if the control points are unevenly distributed. But, if the distances between control points don't vary too wildly, then you can use uniform b-splines and get some nice computational simplifications." ContentLicense="CC BY-SA 3.0" />
  <row Id="14524" PostHistoryTypeId="2" PostId="5348" RevisionGUID="a1e430ff-c705-4e43-8db8-c419f34904e8" CreationDate="2017-07-10T02:47:41.113" UserId="2707" Text="For these types of algorithms, you usually have to rely on multiple forms of texture synthesis. That doesn't mean you have to generate the whole texture from scratch. For example, you could regenerate the sides of the texture to achieve a seamless effect. This answer may not be complete because it's a large field, and different approaches will have various effectiveness depending on the input image.&#xD;&#xA;&#xD;&#xA;# Naive blur along edges&#xD;&#xA;As an artist, one way to make seamless textures is to offset the image in two directions. Then, you can blur the edges.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This example isn't the best, but you can get decent results with results with certain texture types.&#xD;&#xA;&#xD;&#xA;Alternatively, you could do a minimum cut on the edge here by overlapping the image with itself, and then taking the difference between the two images.&#xD;&#xA;&#xD;&#xA;# Min-cut algorithms&#xD;&#xA;One of the most popular algorithms is [image quilting][2]. The idea behind this is separate the texture into a bunch of patches. You fill in the texture by first randomly picking a subset of patches from your total set of patches and picking the one with the least amount of error when you overlap the patch with it's neighboring patch(es). You then perform minimum cuts along the overlapping regions.&#xD;&#xA;&#xD;&#xA;My experience with this algorithm is that it works well for many textures that have round details. If the texture is grass for instance, then it can perform poorly. The amount you overlap each patch also has a large impact on quality. The larger the overlap, the better the match, but the more likely there will be repetition. Also, if the subset of candidate patches is too large, then you'll get repetition. Otherwise, you might not find good matches.&#xD;&#xA;&#xD;&#xA;There are extensions of this algorithm including PatchMatch (which was used in Photoshop).&#xD;&#xA;&#xD;&#xA;# Gradient correction&#xD;&#xA;Another way to handle seamless textures is to remove the gradient. [Poisson image editing][3] can help with this if you break up your image and use the various pieces are foreground and background objects.&#xD;&#xA;&#xD;&#xA;A simpler approach is to great a low-frequency (e.g., mipmap) of your texture and then remove the gradient of your image. Of course, high frequency data won't be seamless, but you can remove that with other algorithms.&#xD;&#xA;&#xD;&#xA;# Computer vision approaches&#xD;&#xA;You could use various computer vision approaches as well. The idea here would be that you keep important features intact as you attempt to tile your textures. For instance, if there's a texture of dirt with a rock on the edge of the picture, using various feature detectors such as difference of Gaussians could help you identify this rock and remove it before you do the tiling. You might need to fill in the rest of the texture where the rock was removed, but this could help with making the image more seamless.&#xD;&#xA;&#xD;&#xA;# Additional References&#xD;&#xA;&#xD;&#xA; - [Image quilting and PatchMatch high-level explanation][4]&#xD;&#xA; - [Gradient domain compositing][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nf1L4.png&#xD;&#xA;  [2]: http://dl.acm.org/citation.cfm?id=383296&#xD;&#xA;  [3]: http://dl.acm.org/citation.cfm?id=882269&#xD;&#xA;  [4]: http://www.connellybarnes.com/work/class/2014/comp_photo/proj1/&#xD;&#xA;  [5]: http://www.connellybarnes.com/work/class/2014/comp_photo/proj2/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14525" PostHistoryTypeId="2" PostId="5349" RevisionGUID="5dcf9257-2e55-4b86-b32c-645e3e14ec8a" CreationDate="2017-07-10T09:24:34.713" UserId="6974" Text="I know its a vague question, but can could someone point me to some materials that would provide some insight into 2D image kernels that are similar to Gaussian? &#xD;&#xA;&#xD;&#xA;I have searched a lot and unfortunately the results are not fruitful :-( &#xD;&#xA;&#xD;&#xA;Thanks! " ContentLicense="CC BY-SA 3.0" />
  <row Id="14526" PostHistoryTypeId="1" PostId="5349" RevisionGUID="5dcf9257-2e55-4b86-b32c-645e3e14ec8a" CreationDate="2017-07-10T09:24:34.713" UserId="6974" Text="Filter kernels similar to Gaussian (low pass) ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14527" PostHistoryTypeId="3" PostId="5349" RevisionGUID="5dcf9257-2e55-4b86-b32c-645e3e14ec8a" CreationDate="2017-07-10T09:24:34.713" UserId="6974" Text="|image-processing|image|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14528" PostHistoryTypeId="10" PostId="5349" RevisionGUID="ee96a6ad-3b20-4890-b560-2c400ba767b2" CreationDate="2017-07-10T10:05:08.573" UserId="2041" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="14533" PostHistoryTypeId="5" PostId="5343" RevisionGUID="2a1fd433-aef4-4b38-8ae1-b3aa8161fdd2" CreationDate="2017-07-11T00:20:45.700" UserId="6968" Comment="added 944 characters in body" Text="The silhouette curve of a quadric surface is a conic (ellipse, parabola, hyperbola, etc.). Suppose you have the quadric $\mathbf{X}^T \mathbf{M} \mathbf{X} = 0$ and your eye is at the point $\mathbf{Y}$. Then the silhouette curve is the intersection of the quadric and the so-called polar plane of $\mathbf{Y}$, which is $\mathbf{Y}^T \mathbf{M} \mathbf{X} = 0$.&#xD;&#xA;&#xD;&#xA;For anything more complex than quadrics, things get nasty in a hurry, and you won't find any analytic solutions; you'll need numerical methods to trace the curve. Even the silhouette of a torus is pretty complex. So, in essence, the best you can do is compute discrete points along the curve, and use these to construct either a polyline or a spline of some sort. But, of course, you can always get a polyline just by tesselating the surface and finding the silhouette of the tesselation.&#xD;&#xA;&#xD;&#xA;One approach would be to approximate your surface of revolution by quadrics, but that may not be any better than tesselating. You'd get a piecewise conic curve, instead of a polyline, which might be an improvement.&#xD;&#xA;&#xD;&#xA;Note that if your surface is not G2, then it's silhouette will not be G1 (i.e. it may have sharp corners). Tracing a curve with corners is tricky.&#xD;&#xA;&#xD;&#xA;There are silhouette generation functions in geometry kernels like Parasolid and ACIS. Maybe in OpenCascade, too.&#xD;&#xA;&#xD;&#xA;To illustrate the difficulty, suppose we have a surface with parametric equations $(u,v) \mapsto \mathbf{S}(u,v)$, and we are viewing it from an eye- point $\mathbf{E}$. Let $\mathbf{N}(u,v)$ be the surface normal at parameter values $(u,v)$, which we can calculate as the cross product of partial derivatives: $\mathbf{N}(u,v) = \mathbf{S}^u(u,v) \times \mathbf{S}^v(u,v)$.&#xD;&#xA;If a point $\mathbf{P}$ is on the silhouette curve, then the surface normal at this point is perpendicular to the vector $\mathbf{P} - \mathbf{E}$. So, the silhouette curve is the locus of points where&#xD;&#xA;$$&#xD;&#xA;(\mathbf{S}(u,v) - \mathbf{E}) \cdot \mathbf{N}(u,v) = 0&#xD;&#xA;$$&#xD;&#xA;Substituting for $\mathbf{N}(u,v)$, this becomes&#xD;&#xA;$$&#xD;&#xA;(\mathbf{S}(u,v) - \mathbf{E}) \cdot (\mathbf{S}^u(u,v) \times \mathbf{S}^v(u,v) ) = 0&#xD;&#xA;$$&#xD;&#xA;If $\mathbf{S}(u,v)$ is even a very simple surface, like a torus or a biquadratic or bicubic patch, the silhouette equation will not have any analytic solution." ContentLicense="CC BY-SA 3.0" />
  <row Id="14534" PostHistoryTypeId="5" PostId="5326" RevisionGUID="995f6e73-7e0c-4ceb-ad6f-78a85fc5137a" CreationDate="2017-07-11T02:49:43.297" UserId="3073" Comment="typo in example code" Text="I don't think uniform arrays can be dynamically sized. In your case you should define the array as the maximum number of lights you will process and then use a uniform to control the number of iterations you do on this array. On the CPU side you can set a subset of the lights[] array according to the 'size' variable.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    #define MAX_LIGHTS 128&#xD;&#xA;    &#xD;&#xA;    uniform int size;&#xD;&#xA;    uniform SceneLights lights[MAX_LIGHTS];&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        for(int i = 0; i &lt; size; i++) {&#xD;&#xA;            /* Do Some Calculation */&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I think (speculate) the likely reason for this is that it would be impossible to determine the location of a uniform if there are variable sized arrays in your uniform list which depend on the value of another uniform.. e.g.&#xD;&#xA;&#xD;&#xA;    uniform int arraySize;               // offset 0&#xD;&#xA;    uniform int myArray[arraySize];      // offset 4&#xD;&#xA;    uniform int anotherVar;              // offset ???? &#xD;&#xA;&#xD;&#xA;GLSL would not know were to place anotherVar, because it would need arraySize to be set with a value before it can compute the offset of 'anotherVar'. I suppose the compiler could be clever and re-arrange the order of uniforms to get around this, but this will fail again if you have 2 or more variable sized arrays..&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14535" PostHistoryTypeId="5" PostId="5349" RevisionGUID="e94516cd-f19e-473d-8cac-d247086fc4d9" CreationDate="2017-07-11T09:22:34.227" UserId="6974" Comment="Making the question a bit more detailed." Text="&#xD;&#xA;I know its a vague question, but can could someone point me to some materials that would provide some insight into 2D image kernels that are similar to Gaussian? &#xD;&#xA;&#xD;&#xA;I am trying to reduce aliasing in an image using some filters, I tried the gaussian variant of filters to remove the said high frequency patterns in the image, but I feel its a bit too much of a blur. &#xD;&#xA;&#xD;&#xA;I need a filter that can help me do some kind of anti-aliasing without doing too much blur. &#xD;&#xA;&#xD;&#xA;I have searched a lot and unfortunately the results are not fruitful :-( &#xD;&#xA;&#xD;&#xA;Thanks! " ContentLicense="CC BY-SA 3.0" />
  <row Id="14536" PostHistoryTypeId="4" PostId="5349" RevisionGUID="e94516cd-f19e-473d-8cac-d247086fc4d9" CreationDate="2017-07-11T09:22:34.227" UserId="6974" Comment="Making the question a bit more detailed." Text="Filter kernels similar to Gaussian (low pass)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14537" PostHistoryTypeId="6" PostId="5349" RevisionGUID="e94516cd-f19e-473d-8cac-d247086fc4d9" CreationDate="2017-07-11T09:22:34.227" UserId="6974" Comment="Making the question a bit more detailed." Text="|image-processing|image|antialiasing|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14538" PostHistoryTypeId="5" PostId="5349" RevisionGUID="cd68c8d0-7510-46c5-a781-70e1e724c5fc" CreationDate="2017-07-11T11:05:17.620" UserId="2041" Comment="Focus on the actual problem to be solved" Text="I am trying to reduce aliasing in an image using some filters, I tried the gaussian variant of filters to remove the said high frequency patterns in the image, but I feel its a bit too much of a blur. &#xD;&#xA;&#xD;&#xA;I need a filter that can help me do some kind of anti-aliasing without doing too much blur. &#xD;&#xA;&#xD;&#xA;I have searched a lot and unfortunately the results are not fruitful :-( &#xD;&#xA;&#xD;&#xA;Thanks! " ContentLicense="CC BY-SA 3.0" />
  <row Id="14539" PostHistoryTypeId="4" PostId="5349" RevisionGUID="cd68c8d0-7510-46c5-a781-70e1e724c5fc" CreationDate="2017-07-11T11:05:17.620" UserId="2041" Comment="Focus on the actual problem to be solved" Text="How can I remove aliasing in an image without introducing blur?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14540" PostHistoryTypeId="11" PostId="5349" RevisionGUID="854815e7-7d08-4e18-9f27-f09c206f7e9a" CreationDate="2017-07-11T11:05:17.903" UserId="2041" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="14541" PostHistoryTypeId="50" PostId="4972" RevisionGUID="7080eb55-88fa-4fd6-8703-2f6ef78ecfa0" CreationDate="2017-07-11T13:16:53.933" UserId="-1" />
  <row Id="14542" PostHistoryTypeId="2" PostId="5351" RevisionGUID="5e3c38e1-8f47-4c67-8fa3-dff12b261455" CreationDate="2017-07-11T13:24:03.003" UserId="6968" Text="The curve you are seeking is just the intersection of a plane (the back of the camera) and a right circular cone. This is not really a question about the earth, or views of planets from space; it's just plain simple 3D coordinate geometry. To find a reference, I'd recommend searching for &quot;intersection of a plane and a cone&quot; or &quot;plane section of a cone&quot;, or &quot;plane section of quadric&quot;, something like that.&#xD;&#xA;&#xD;&#xA;I'd expect that you can find the relevant formulae (and derivations) in any standard text on 3D coordinate geometry. Some likely places are:&#xD;&#xA;&#xD;&#xA; - Salmon -- A Treatise on the Analytic Geometry of Three Dimensions&#xD;&#xA; - Somerville -- Analytical Geometry of Three Dimensions&#xD;&#xA; - Snyder and Sisam -- Analytic geometry of Space&#xD;&#xA;&#xD;&#xA;You might also try asking on Math.StackExchange.&#xD;&#xA;&#xD;&#xA;Calling the derivation &quot;original research&quot; seems absurd, to me. It's a high-school homework problem in analytic geometry." ContentLicense="CC BY-SA 3.0" />
  <row Id="14543" PostHistoryTypeId="5" PostId="5351" RevisionGUID="b6f83f23-9740-4757-8be1-cc7121396efb" CreationDate="2017-07-11T13:29:23.913" UserId="6968" Comment="added 75 characters in body" Text="The curve you are seeking is just the intersection of a plane (the back of the camera) and a right circular cone. This is not really a question about the earth, or views of planets from space; it's just plain simple 3D coordinate geometry. To find a reference, I'd recommend searching for &quot;intersection of a plane and a cone&quot; or &quot;plane section of a cone&quot;, or &quot;plane section of quadric&quot;, something like that.&#xD;&#xA;&#xD;&#xA;I'd expect that you can find the relevant formulae (and derivations) in any standard text on 3D coordinate geometry. Some likely places are:&#xD;&#xA;&#xD;&#xA; - Salmon -- A Treatise on the Analytic Geometry of Three Dimensions&#xD;&#xA; - Somerville -- Analytical Geometry of Three Dimensions&#xD;&#xA; - Snyder and Sisam -- Analytic geometry of Space&#xD;&#xA;&#xD;&#xA;These are all pretty old books, and you may have trouble finding them. &#xD;&#xA;&#xD;&#xA;You might also try asking on Math.StackExchange.&#xD;&#xA;&#xD;&#xA;Calling the derivation &quot;original research&quot; seems absurd, to me. It's a high-school homework problem in analytic geometry." ContentLicense="CC BY-SA 3.0" />
  <row Id="14544" PostHistoryTypeId="2" PostId="5352" RevisionGUID="3a7d7c47-9610-4f48-a647-d924d944b031" CreationDate="2017-07-11T13:34:38.400" UserId="2138" Text="Depending on the specific content of your input images, you could either use the Gaussian filter with kernel size varying with distance from the camera ( [Link][1] ) or use a slightly more complex [bilateral filter][2], which is widely used to eliminate noise while keeping edges mostly intact.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Spatial_anti-aliasing&#xD;&#xA;  [2]: http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="14545" PostHistoryTypeId="5" PostId="5351" RevisionGUID="e3a712b0-65d6-46a8-af5a-dc381c300a50" CreationDate="2017-07-11T14:30:23.097" UserId="6968" Comment="edited body" Text="The curve you are seeking is just the intersection of a plane (the back of the camera) and a right circular cone. This is not really a question about the earth, or views of planets from space; it's just plain simple 3D coordinate geometry. To find a reference, I'd recommend searching for &quot;intersection of a plane and a cone&quot; or &quot;plane section of a cone&quot;, or &quot;plane section of quadric&quot;, something like that.&#xD;&#xA;&#xD;&#xA;I'd expect that you can find the relevant formulae (and derivations) in any standard text on 3D coordinate geometry. Some likely places are:&#xD;&#xA;&#xD;&#xA; - Salmon -- A Treatise on the Analytic Geometry of Three Dimensions&#xD;&#xA; - Somerville -- Analytical Geometry of Three Dimensions&#xD;&#xA; - Snyder and Sisam -- Analytic Geometry of Space&#xD;&#xA;&#xD;&#xA;These are all pretty old books, and you may have trouble finding them. &#xD;&#xA;&#xD;&#xA;You might also try asking on Math.StackExchange.&#xD;&#xA;&#xD;&#xA;Calling the derivation &quot;original research&quot; seems absurd, to me. It's a high-school homework problem in analytic geometry." ContentLicense="CC BY-SA 3.0" />
  <row Id="14548" PostHistoryTypeId="2" PostId="5353" RevisionGUID="429527e5-2832-4905-8d21-930d5cf7abb1" CreationDate="2017-07-12T12:37:42.457" UserId="6968" Text="**Journals**:   &#xD;&#xA;Computer Aided Design   &#xD;&#xA;Computer Aided Geometric Design&#xD;&#xA;&#xD;&#xA;**Conferences**   &#xD;&#xA;https://s3pm.icsi.berkeley.edu/s3pm/spm.html   &#xD;&#xA;http://graphics.xmu.edu.cn/gmp2017/   &#xD;&#xA;http://www.siam.org/meetings/gd17/   &#xD;&#xA;&#xD;&#xA;**Organizations**:  &#xD;&#xA;http://solidmodeling.org/   &#xD;&#xA;http://www.siam.org/activity/gd/&#xD;&#xA;&#xD;&#xA;There are **plenty** of open problems.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14549" PostHistoryTypeId="5" PostId="5349" RevisionGUID="04eaa582-16b6-492e-913b-5a2f25df649e" CreationDate="2017-07-12T12:57:27.430" UserId="231" Comment="Remove thanks and minor tidying" Text="I am trying to reduce aliasing in an image using some filters. I tried the Gaussian variant of filters to remove the said high frequency patterns in the image, but I feel it's a bit too much of a blur. &#xD;&#xA;&#xD;&#xA;I need a filter that can help me do some kind of anti-aliasing without doing too much blur. &#xD;&#xA;&#xD;&#xA;I have searched a lot and unfortunately the results are not fruitful." ContentLicense="CC BY-SA 3.0" />
  <row Id="14550" PostHistoryTypeId="2" PostId="5354" RevisionGUID="743ad90a-2eb5-4500-b6ea-0bb743122fc4" CreationDate="2017-07-12T13:01:46.553" UserId="6968" Text="You need a position (3 coordinates), and a rotation.&#xD;&#xA;&#xD;&#xA;Positions are easy, obviously.&#xD;&#xA;&#xD;&#xA;There are **many** different ways to represent a rotation: start reading [here][1], or [here][2]. The common ones are rotation matrices, quaternions, and Euler angles.&#xD;&#xA;&#xD;&#xA;In theory, a rotation has only 3 degrees of freedom, so you ought to be able to represent it with three numbers. But representations that use 3 numbers inevitably have discontinuities or singularities (like &quot;gimbal lock&quot;), so using 4 numbers (e.g. a quaternion) is more practical.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions" ContentLicense="CC BY-SA 3.0" />
  <row Id="14551" PostHistoryTypeId="5" PostId="5354" RevisionGUID="a4eae745-ada2-4c4f-9aa5-16896ce473ce" CreationDate="2017-07-13T00:20:52.597" UserId="6968" Comment="added 73 characters in body" Text="You need a position, and an orientation.&#xD;&#xA;&#xD;&#xA;Positions are easy, obviously -- just 3 coordinates.&#xD;&#xA;&#xD;&#xA;There are **many** different ways to represent an orientation: start reading [here][1], or [here][2]. The common ones are rotation matrices, quaternions, and Euler angles.&#xD;&#xA;&#xD;&#xA;In theory, an orientation has only 3 degrees of freedom, so you ought to be able to represent it with three numbers. But representations that use 3 numbers inevitably have discontinuities or singularities (like &quot;[gimbal lock][3]&quot;), so using 4 numbers (e.g. a quaternion) is more practical.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rotation_formalisms_in_three_dimensions&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Gimbal_lock" ContentLicense="CC BY-SA 3.0" />
  <row Id="14552" PostHistoryTypeId="2" PostId="5355" RevisionGUID="0e0af726-dde7-4ebe-8ca9-277f9b2a6ff0" CreationDate="2017-07-13T01:58:54.427" UserId="6986" Text="As of lately I've been studying a bit of shaders (in Unity), and am trying to recreate the &quot;light-based inline&quot; that can be observed in the latest Legend of Zelda. But maybe the task is a bit above my knowledge, for now.&#xD;&#xA;&#xD;&#xA;[![Annotated reference image][1]][1]&#xD;&#xA;&#xD;&#xA;As from what I can analyze, it seems to behave (when moving) similar to what a &quot;rim shading&quot; does, except it has a sharp cutoff (simple to do), and — the part I'm struggling with — it seems to have a constant width independent from the local curvature of the mesh and distance from camera, essentially having a constant &quot;width&quot; in relation to the screen. (well it actually varies a bit with camera distance, but mostly it doesn't so let's assume it doesn't)&#xD;&#xA;&#xD;&#xA;It's a bit hard to show in a still, but you can find plenty videos on the game, and the effect is visible everywhere. &#xD;&#xA;&#xD;&#xA;I've managed to do the simpler part, the cut-off rim shading. But this gives the awkward effect that depending on camera orientation and the geometry curvature, the &quot;inline&quot; occupies more or less screen area. Below is an image of the current results I get on various camera angles, with green arrows showing good/acceptable areas and red arrows demonstrating deviation from the intended effect.&#xD;&#xA;&#xD;&#xA;[![Current output with annotated good/bads][2]][2]&#xD;&#xA;&#xD;&#xA;This is my current implementation for reference, as a Unity Surface Light Model:&#xD;&#xA;&#xD;&#xA;    half4 LightingToonPoster(SurfaceOutputStandard surf, float3 viewDir, UnityGI gi) {&#xD;&#xA;        // Material properties&#xD;&#xA;        half3 specular;&#xD;&#xA;        half oneMinusReflectivity;&#xD;&#xA;        DiffuseAndSpecularFromMetallic(surf.Albedo, surf.Metallic, /*out*/ specular, /*out*/ oneMinusReflectivity);&#xD;&#xA;        float3 reflected = normalize(-reflect(gi.light.dir, surf.Normal));&#xD;&#xA;        float specularity = dot(viewDir, reflected) * _Specularity;&#xD;&#xA;&#xD;&#xA;        // Light setup&#xD;&#xA;        float ndotl = dot(surf.Normal, gi.light.dir) * 0.5 + 0.5;&#xD;&#xA;        float lightIncidence = gi.light.color * ndotl;&#xD;&#xA;        float3 ramp = tex2D(_Ramp, lightIncidence.xx).rgb;&#xD;&#xA;        float3 specularRamp = tex2D(_Ramp, specularity.xx).rgb;&#xD;&#xA;        gi.light.color = ramp * _LightColor0.rgb;&#xD;&#xA;&#xD;&#xA;        // Rim and camera-light convergence&#xD;&#xA;        float rim = 1 - saturate(dot(surf.Normal, viewDir));&#xD;&#xA;        float facing = -dot(viewDir, gi.light.dir) * 0.5 + 0.25;&#xD;&#xA;&#xD;&#xA;        // sigmoid of rim for smooth falloff centered at _EdgeBias&#xD;&#xA;        float outline = 1 / (1 + exp(-100 * (rim - _EdgeBias)));&#xD;&#xA;        float highlight = _HighlightStrength * outline * facing * outline;&#xD;&#xA;&#xD;&#xA;        float4 std = LightingStandard(surf, viewDir, gi);&#xD;&#xA;&#xD;&#xA;        float3 toonDiffuse = surf.Albedo * (gi.light.color / 2 + ShadeSH9(float4(viewDir, 1)));&#xD;&#xA;        float3 toonSpecular = specular * gi.indirect.specular * specularRamp;&#xD;&#xA;        float4 toon = half4(toonDiffuse + toonSpecular, surf.Alpha);&#xD;&#xA;        return lerp(std, toon, _UnshadeFactor) * half4(1 + highlight.xxx, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[Or check this Gist for the full shader file](https://gist.github.com/kroltan/8eb8ba213dfeea14fde694c967630ae2)&#xD;&#xA;&#xD;&#xA;The question now being, what can I use instead of rim-shading to obtain a similar effect, where the curvature is not taken into account and I get a constant &quot;inset&quot;?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8z0Ex.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dnPyb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14553" PostHistoryTypeId="1" PostId="5355" RevisionGUID="0e0af726-dde7-4ebe-8ca9-277f9b2a6ff0" CreationDate="2017-07-13T01:58:54.427" UserId="6986" Text="Constant screen-space-width rim shading" ContentLicense="CC BY-SA 3.0" />
  <row Id="14554" PostHistoryTypeId="3" PostId="5355" RevisionGUID="0e0af726-dde7-4ebe-8ca9-277f9b2a6ff0" CreationDate="2017-07-13T01:58:54.427" UserId="6986" Text="|shader|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14556" PostHistoryTypeId="2" PostId="5356" RevisionGUID="1c967643-797b-479e-a0c4-8ed854fad847" CreationDate="2017-07-13T08:11:16.030" UserId="182" Text="Nice question! I hadn't seen the game myself but this question got me interested so I watched some footage on Youtube.&#xD;&#xA;&#xD;&#xA;This one for example gives a good view of it: https://youtu.be/Ktjdg3zgRzk?t=15m46s&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;A few things I notice:&#xD;&#xA;&#xD;&#xA; - Hair and right leg: note how only the diffuse lit part has rim lighting.&#xD;&#xA; - Left wrist: note how the width becomes thinner at the angle with the hand.&#xD;&#xA; - On some other part you can also see the rim lighting is affected by cast shadows too. &#xD;&#xA;&#xD;&#xA;From these observations, I think there are two effects used:&#xD;&#xA;&#xD;&#xA; 1. A diffuse shading with a sharp transition between lit a unlit, that happens somewhere below 0 so the light leaks behind a little.&#xD;&#xA; 2. The rim lighting that, as you mention, has an almost constant screenspace width.&#xD;&#xA;&#xD;&#xA;    From the look of it and some of the artifacts, my best guess is that it's actually some edge detection filter based on depth, which is then used in combination with the diffuse lighting so the rim lighting doesn't affect the unlit parts.&#xD;&#xA;&#xD;&#xA;It's a pretty cool effect, thank you for point it out!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hEUiR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14557" PostHistoryTypeId="2" PostId="5357" RevisionGUID="51fc387f-ba74-4937-a183-3df6b979265d" CreationDate="2017-07-13T08:38:24.073" UserId="6662" Text="I've implemented a ping pong rendering that does something according to constraints on the current fragment :&#xD;&#xA;&#xD;&#xA;(1) The value of the fragment depth is equal to the median of neighbors depth values&#xD;&#xA;(2) the value of the fragment depth is equal to a weighted sum of neighbors depth values&#xD;&#xA;(3) The point is black&#xD;&#xA;&#xD;&#xA;I'll say that the easier part is the (3), but for the 2 others (1) and (2), I have optimization problems (my FPS drop to 1.2 when I use it).&#xD;&#xA;&#xD;&#xA;What I do, is if we're in case (1) or (2) I fill an array with all neighbors values that are valid (not the background).&#xD;&#xA;for (1), I use Niklaus_wirth algorithm to sort the array and take the median value.&#xD;&#xA;For (2), I calculate the weigth for each neighbors and then do a Sum.&#xD;&#xA;&#xD;&#xA;Since i'm not very used to work with GPUs, the ways to optimize my program are not known by me. I checked several tuto to improve a shader code, but couldn't find something that fit with me :/ (I saw that I have to remove the most if statement possible, but don't find any ways to do it...)&#xD;&#xA;Here's the code :&#xD;&#xA;&#xD;&#xA;    vec3 PingPongDepth() {&#xD;&#xA;    	return texture(fillingTexDepth, TexCoords).xyz;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //I do the pingpong around &quot;fillingTexDepth&quot;. The next function give me the 3-neighbourhood of the current fragment.&#xD;&#xA;    vec3 PingPongDepth(int i) {														&#xD;&#xA;    	int x = i % 3;&#xD;&#xA;    	int y = i / 3;&#xD;&#xA;    &#xD;&#xA;    	int rx = x - 1;&#xD;&#xA;    	int ry = 1 - y;&#xD;&#xA;    &#xD;&#xA;    	return texture(fillingTexDepth, TexCoords + vec2(rx*dx, ry*dy)).xyz;&#xD;&#xA;    }&#xD;&#xA;    //I Put values in my array if they are valid neighbors&#xD;&#xA;    void PutInArray() {&#xD;&#xA;	for (int i = 0; i &lt; 9; ++i) {&#xD;&#xA;        //We don't want to take the current fragment in the calculus&#xD;&#xA;		if (i != 4) {&#xD;&#xA;			vec3 pIDepth = PingPongDepth(i);&#xD;&#xA;			if (isValid(pIDepth)) {&#xD;&#xA;				xArray[xSize] = pIDepth.x;&#xD;&#xA;				xSize++;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and then, for (1):&#xD;&#xA;&#xD;&#xA;    void xSwap(int a, int b) {&#xD;&#xA;	     float tmp = xArray[a];&#xD;&#xA;	    xArray[a] = xArray[b];&#xD;&#xA;	    xArray[b] = tmp;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void kth_smallest(int k) {&#xD;&#xA;	    int i, j, l, m;&#xD;&#xA;	    float x;&#xD;&#xA;&#xD;&#xA;	    l = 0;&#xD;&#xA;	    m = xSize - 1;&#xD;&#xA;	    while (l &lt; m) {&#xD;&#xA;		    x = xArray[k];&#xD;&#xA;		    i = l;&#xD;&#xA;		    j = m;&#xD;&#xA;		    do {&#xD;&#xA;			    while (xArray[i] &lt; x) i++;&#xD;&#xA;			    while (x &lt; xArray[j]) j--;&#xD;&#xA;			    if (i &lt;= j) {&#xD;&#xA;				    xSwap(i, j);&#xD;&#xA;				    i++; j--;&#xD;&#xA;			    }&#xD;&#xA;		    } while (i &lt;= j);&#xD;&#xA;		    if (j &lt; k) l = i;&#xD;&#xA;		    if (k &lt; i) m = j;&#xD;&#xA;	    }&#xD;&#xA;    //retDepth is the vec4 that is returned by my shader&#xD;&#xA;	retDepth = vec4(vec3(xArray[k], 0.0f, 0.0f), 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void Median_NW(vec3 vDepth, vec3 vCol) {&#xD;&#xA;	    if (xSize == 0) {&#xD;&#xA;	    	retDepth = vec4(vDepth, 1.0f);&#xD;&#xA;	    	retColor = vec4(vCol, 1.0f);&#xD;&#xA;		    return;&#xD;&#xA;	    }&#xD;&#xA;	    else if (xSize == 1) {&#xD;&#xA;	    	retDepth = vec4(vec3(xArray[0], 0.0f, 0.0f), 1.0f);&#xD;&#xA;	    	return;&#xD;&#xA;	    }&#xD;&#xA;	    else&#xD;&#xA;		   kth_smallest(xSize / 2);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and for (2)&#xD;&#xA;&#xD;&#xA;    float xWeight_(vec3 v, int i, float sigma) {&#xD;&#xA;    	float rI = (i % 2 == 0) ? 1.4142 : 1.0;&#xD;&#xA;    &#xD;&#xA;    	return (1.0f - 0.5*rI )*(1 - min(1, abs(xArray[i] - v.x) / sigma));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void WeightedSum(vec3 vDepth, vec3 vCol) {&#xD;&#xA;    	if (xSize == 0) {&#xD;&#xA;    		retDepth = vec4(vDepth, 1.0f);&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	float weightedDepth = 0.0f;&#xD;&#xA;    	float xSum = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	for (int i = 0; i &lt; xSize; ++i) {&#xD;&#xA;    		float w_ = xWeight_(vDepth, i, 2.0f);&#xD;&#xA;    		weightedDepth += xArray[i] * w_;&#xD;&#xA;    		xSum += w_;&#xD;&#xA;    	}&#xD;&#xA;    	retDepth = vec4(vec3(weightedDepth, 0.0f, 0.0f) / xSum, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If someone have an idea... (sorry for the long post)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14558" PostHistoryTypeId="1" PostId="5357" RevisionGUID="51fc387f-ba74-4937-a183-3df6b979265d" CreationDate="2017-07-13T08:38:24.073" UserId="6662" Text="fragment shader median/weigthed sum of neighbors depth values (optimization)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14559" PostHistoryTypeId="3" PostId="5357" RevisionGUID="51fc387f-ba74-4937-a183-3df6b979265d" CreationDate="2017-07-13T08:38:24.073" UserId="6662" Text="|opengl|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14560" PostHistoryTypeId="5" PostId="1562" RevisionGUID="556583ed-3831-4c3d-ac47-55d8f6e1f809" CreationDate="2017-07-13T10:27:55.247" UserId="182" Comment="Fixed some minor typo." Text="I have a class that generates a 3D shape based on inputs from the calling code. The inputs are things like length, depth, arc, etc. My code generates the geometry perfectly, however I am running into trouble when calculating the surface normals. When lit, my shape has very bizarre coloring/texture from the incorrect surface normals that are being calculated. From all my research I believe my math is correct, it seems that something is wrong with my technique or method.&#xD;&#xA;&#xD;&#xA;At a high level how does one go about programmatically calculating the surface normals for a generated shape? I am using Swift/SceneKit on iOS for my code but a generic answer is fine.&#xD;&#xA;&#xD;&#xA;I have two arrays that represent my shape. One is an array of 3D points that represents the vertices that make up the shape. The other array is a list of indexes of the first array that map the vertices into triangles. I need to take that data and generate a 3rd array that is a set of surface normals that aid in the lighting of the shape. (see [`SCNGeometrySourceSemanticNormal` in SceneKit`](https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SceneKit_Constants/index.html#//apple_ref/c/data/SCNGeometrySourceSemanticNormal))&#xD;&#xA;&#xD;&#xA;The list of vertices and indexes is always different depending on the inputs to the class so I cannot pre-calculate or hard code the surface normals." ContentLicense="CC BY-SA 3.0" />
  <row Id="14561" PostHistoryTypeId="4" PostId="1562" RevisionGUID="556583ed-3831-4c3d-ac47-55d8f6e1f809" CreationDate="2017-07-13T10:27:55.247" UserId="182" Comment="Fixed some minor typo." Text="How to Calculate Surface Normals for Generated Geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="14562" PostHistoryTypeId="6" PostId="1562" RevisionGUID="556583ed-3831-4c3d-ac47-55d8f6e1f809" CreationDate="2017-07-13T10:27:55.247" UserId="182" Comment="Fixed some minor typo." Text="|lighting|geometry|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14563" PostHistoryTypeId="5" PostId="5348" RevisionGUID="b4204a81-5047-4c6d-a068-a0e787d58aa5" CreationDate="2017-07-13T10:43:15.777" UserId="209" Comment="spotted a spelling mistake" Text="For these types of algorithms, you usually have to rely on multiple forms of texture synthesis. That doesn't mean you have to generate the whole texture from scratch. For example, you could regenerate the sides of the texture to achieve a seamless effect. This answer may not be complete because it's a large field, and different approaches will have various effectiveness depending on the input image.&#xD;&#xA;&#xD;&#xA;# Naive blur along edges&#xD;&#xA;As an artist, one way to make seamless textures is to offset the image in two directions. Then, you can blur the edges.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This example isn't the best, but you can get decent results with results with certain texture types.&#xD;&#xA;&#xD;&#xA;Alternatively, you could do a minimum cut on the edge here by overlapping the image with itself, and then taking the difference between the two images.&#xD;&#xA;&#xD;&#xA;# Min-cut algorithms&#xD;&#xA;One of the most popular algorithms is [image quilting][2]. The idea behind this is separate the texture into a bunch of patches. You fill in the texture by first randomly picking a subset of patches from your total set of patches and picking the one with the least amount of error when you overlap the patch with it's neighboring patch(es). You then perform minimum cuts along the overlapping regions.&#xD;&#xA;&#xD;&#xA;My experience with this algorithm is that it works well for many textures that have round details. If the texture is grass for instance, then it can perform poorly. The amount you overlap each patch also has a large impact on quality. The larger the overlap, the better the match, but the more likely there will be repetition. Also, if the subset of candidate patches is too large, then you'll get repetition. Otherwise, you might not find good matches.&#xD;&#xA;&#xD;&#xA;There are extensions of this algorithm including PatchMatch (which was used in Photoshop).&#xD;&#xA;&#xD;&#xA;# Gradient correction&#xD;&#xA;Another way to handle seamless textures is to remove the gradient. [Poisson image editing][3] can help with this if you break up your image and use the various pieces are foreground and background objects.&#xD;&#xA;&#xD;&#xA;A simpler approach is to create a low-frequency (e.g., mipmap) of your texture and then remove the gradient of your image. Of course, high frequency data won't be seamless, but you can remove that with other algorithms.&#xD;&#xA;&#xD;&#xA;# Computer vision approaches&#xD;&#xA;You could use various computer vision approaches as well. The idea here would be that you keep important features intact as you attempt to tile your textures. For instance, if there's a texture of dirt with a rock on the edge of the picture, using various feature detectors such as difference of Gaussians could help you identify this rock and remove it before you do the tiling. You might need to fill in the rest of the texture where the rock was removed, but this could help with making the image more seamless.&#xD;&#xA;&#xD;&#xA;# Additional References&#xD;&#xA;&#xD;&#xA; - [Image quilting and PatchMatch high-level explanation][4]&#xD;&#xA; - [Gradient domain compositing][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nf1L4.png&#xD;&#xA;  [2]: http://dl.acm.org/citation.cfm?id=383296&#xD;&#xA;  [3]: http://dl.acm.org/citation.cfm?id=882269&#xD;&#xA;  [4]: http://www.connellybarnes.com/work/class/2014/comp_photo/proj1/&#xD;&#xA;  [5]: http://www.connellybarnes.com/work/class/2014/comp_photo/proj2/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14564" PostHistoryTypeId="5" PostId="5353" RevisionGUID="147c90ff-ea48-4d6d-b58b-af48f9879411" CreationDate="2017-07-13T12:22:33.923" UserId="6968" Comment="added 187 characters in body" Text="**Books**   &#xD;&#xA;Farin - Curves and Surfaces for CAGD   &#xD;&#xA;Hoffman -- Geometric &amp; Solid Modeling: An Introduction   &#xD;&#xA;Hoschek &amp; Lasser -- Fundamentals of Computer Aided Geometric Design&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Journals**:   &#xD;&#xA;Computer Aided Design   &#xD;&#xA;Computer Aided Geometric Design&#xD;&#xA;&#xD;&#xA;**Conferences**   &#xD;&#xA;https://s3pm.icsi.berkeley.edu/s3pm/spm.html   &#xD;&#xA;http://graphics.xmu.edu.cn/gmp2017/   &#xD;&#xA;http://www.siam.org/meetings/gd17/   &#xD;&#xA;&#xD;&#xA;**Organizations**:  &#xD;&#xA;http://solidmodeling.org/   &#xD;&#xA;http://www.siam.org/activity/gd/&#xD;&#xA;&#xD;&#xA;There are **plenty** of open problems.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14566" PostHistoryTypeId="2" PostId="5358" RevisionGUID="65c5ba99-6f2d-4f97-be37-93b63c6e9d6f" CreationDate="2017-07-14T10:46:23.170" UserId="6991" Text="CNT is a promising new material, which [Wikipedia][1] describes as such:&#xD;&#xA;&#xD;&#xA;&gt; Carbon nanotubes (CNTs) are allotropes of carbon with a cylindrical nanostructure. These cylindrical carbon molecules have unusual properties, which are valuable for nanotechnology, electronics, optics and other fields of materials science and technology. Owing to the material's exceptional strength and stiffness, nanotubes have been constructed with length-to-diameter ratio of up to 132,000,000:1, significantly larger than for any other material.&#xD;&#xA;&#xD;&#xA;&gt; In addition, owing to their extraordinary thermal conductivity, mechanical, and electrical properties, carbon nanotubes find applications as additives to various structural materials.&#xD;&#xA;&#xD;&#xA;For this reason, the name carbon nanotubes appear from time to time in various works of science fiction, and I too want to use CNT in a science fiction game, set in the near future which I am making, since I am trying to achieve some degree of photorealistic graphic, I will, however, need to know what CNT will look like.&#xD;&#xA;&#xD;&#xA;specifically, I want to know which of the two main categories of solid, non-transparent material surfaces commonly used in physically based rendering CNT would fall under.&#xD;&#xA;&#xD;&#xA;as [this][2] article on PBR computer graphics explains, &#xD;&#xA;&#xD;&#xA;&gt; »Electrically conductive materials, most notably metals« look quite different from other materials.&#xD;&#xA;&#xD;&#xA;Which is why it often is sufficient to assume that the most common materials in the world are either *metallic* or *dielectric*/*insulating*.&#xD;&#xA;&#xD;&#xA;Given that CNT by Wikipedia is described as:&#xD;&#xA;&#xD;&#xA;&gt; Unlike graphene, which is a two-dimensional semimetal, carbon&#xD;&#xA;&gt; nanotubes are either metallic or semiconducting&#xD;&#xA;&#xD;&#xA;I first assumed was that I should treat CNT as a metal, but I am not certain if CNT has other properties which would make it look significantly different from metal.&#xD;&#xA;&#xD;&#xA;My question is, therefore, is it a fair approximation to render carbon nanotubes using a metallic shader? or would it be better to render it as an insulator?&#xD;&#xA;&#xD;&#xA;Edit: So it looks like we actually already have some macroscopic CNT structures, but I really can't tell whether or not this looks metallic or not:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Carbon_nanotube#Electrical&#xD;&#xA;  [2]: https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/&#xD;&#xA;  [3]: https://i.stack.imgur.com/aSvgK.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14567" PostHistoryTypeId="1" PostId="5358" RevisionGUID="65c5ba99-6f2d-4f97-be37-93b63c6e9d6f" CreationDate="2017-07-14T10:46:23.170" UserId="6991" Text="Would the surface of a large carbon-nanotupe structure look metalic?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14568" PostHistoryTypeId="3" PostId="5358" RevisionGUID="65c5ba99-6f2d-4f97-be37-93b63c6e9d6f" CreationDate="2017-07-14T10:46:23.170" UserId="6991" Text="|physically-based|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14569" PostHistoryTypeId="5" PostId="5358" RevisionGUID="167c3ba3-119a-4827-b04f-0e62a561935f" CreationDate="2017-07-14T10:51:40.790" UserId="6991" Comment="added 43 characters in body" Text="CNT is a promising new material, which [Wikipedia][1] describes as such:&#xD;&#xA;&#xD;&#xA;&gt; Carbon nanotubes (CNTs) are allotropes of carbon with a cylindrical nanostructure. These cylindrical carbon molecules have unusual properties, which are valuable for nanotechnology, electronics, optics and other fields of materials science and technology. Owing to the material's exceptional strength and stiffness, nanotubes have been constructed with length-to-diameter ratio of up to 132,000,000:1, significantly larger than for any other material.&#xD;&#xA;&#xD;&#xA;&gt; In addition, owing to their extraordinary thermal conductivity, mechanical, and electrical properties, carbon nanotubes find applications as additives to various structural materials.&#xD;&#xA;&#xD;&#xA;For this reason, the name carbon nanotubes appear from time to time in various works of science fiction, and I too want to use CNT in a science fiction game, set in the near future which I am making, since I am trying to achieve some degree of photorealistic graphic, I will, however, need to know what CNT will look like.&#xD;&#xA;&#xD;&#xA;specifically, I want to know which of the two main categories of solid, non-transparent material surfaces commonly used in physically based rendering CNT would fall under.&#xD;&#xA;&#xD;&#xA;as [this][2] article on PBR computer graphics explains, &#xD;&#xA;&#xD;&#xA;&gt; »Electrically conductive materials, most notably metals« look quite different from other materials.&#xD;&#xA;&#xD;&#xA;Which is why it often is sufficient to assume that the most common materials in the world are either *metallic* or *dielectric*/*insulating*.&#xD;&#xA;&#xD;&#xA;Given that CNT by Wikipedia is described as:&#xD;&#xA;&#xD;&#xA;&gt; Unlike graphene, which is a two-dimensional semimetal, carbon&#xD;&#xA;&gt; nanotubes are either metallic or semiconducting&#xD;&#xA;&#xD;&#xA;I first assumed was that I should treat CNT as a metal, but I am not certain if CNT has other properties which would make it look significantly different from metal.&#xD;&#xA;&#xD;&#xA;My question is, therefore, is it a fair approximation to render carbon nanotubes using a metallic shader? or would it be better to render it as an insulator? Edit 1: and would CNT look anisotropic.&#xD;&#xA;&#xD;&#xA;Edit 0: So it looks like we actually already have some macroscopic CNT structures, but I really can't tell whether or not this looks metallic or not: &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Carbon_nanotube#Electrical&#xD;&#xA;  [2]: https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/&#xD;&#xA;  [3]: https://i.stack.imgur.com/aSvgK.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14570" PostHistoryTypeId="2" PostId="5359" RevisionGUID="a6c155b9-7622-4cf6-a879-a3d25e9a6aa3" CreationDate="2017-07-14T11:10:24.710" UserId="6990" Text="I have the 8 vertices of a cuboid (red points)(XYZvox) with known distance in millimetres (vox to mm) between each vertex which I transform in 3d space using the 4d transformation matrix (M). I am really struggling to work out the new voxel to millimetre conversion for the transformed vertices. How can I work this out? I feel it should be relatively straightforward:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/o3jR7.png&#xD;&#xA;&#xD;&#xA;    XYZvox =[ 1     1     1     1   409   409   409   409&#xD;&#xA;         1     1   389   389     1     1   389   389&#xD;&#xA;         1   162     1   162     1   162     1   162]&#xD;&#xA;    &#xD;&#xA;    M =[0.0337    0.0958   -0.9616   -2.5360&#xD;&#xA;        0.3706    0.0107    0.1012 -150.2009&#xD;&#xA;        0.0201   -0.3571   -0.2550 -231.0513&#xD;&#xA;             0         0         0    1.0000]&#xD;&#xA;    &#xD;&#xA;    for i=1:8&#xD;&#xA;    &#xD;&#xA;    poi1=XYZvox(:,i);&#xD;&#xA;    poi2=[XYZvox(:,i)];&#xD;&#xA;    poi2(4,1)=1;&#xD;&#xA;    &#xD;&#xA;    poi_trans=M*poi2;&#xD;&#xA;    &#xD;&#xA;    poi_trans=poi_trans(1:3);&#xD;&#xA;    &#xD;&#xA;    scatter3(poi1(1),poi1(2),poi1(3),'red','filled'); xlabel('x'); hold all;&#xD;&#xA;    scatter3(poi_trans(1),poi_trans(2),poi_trans(3),'green','filled'); xlabel('x'); ylabel('y'); zlabel('z'); &#xD;&#xA;    &#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14571" PostHistoryTypeId="1" PostId="5359" RevisionGUID="a6c155b9-7622-4cf6-a879-a3d25e9a6aa3" CreationDate="2017-07-14T11:10:24.710" UserId="6990" Text="Applying 3d transformation to cuboid" ContentLicense="CC BY-SA 3.0" />
  <row Id="14572" PostHistoryTypeId="3" PostId="5359" RevisionGUID="a6c155b9-7622-4cf6-a879-a3d25e9a6aa3" CreationDate="2017-07-14T11:10:24.710" UserId="6990" Text="|3d|affine-transformations|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14573" PostHistoryTypeId="10" PostId="4099" RevisionGUID="18e88d6c-dd7d-4d60-8782-f9c266bc1cd0" CreationDate="2017-07-14T14:03:17.607" UserId="2041" Comment="105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:3003,&quot;DisplayName&quot;:&quot;user1118321&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="14574" PostHistoryTypeId="2" PostId="5360" RevisionGUID="fba193b4-2a7f-4475-83c6-7de53e24f33c" CreationDate="2017-07-14T14:37:00.287" UserId="6974" Text="I was looking into measuring amount of aliasing in an image. After reading through many papers and sites, I came to the conclusion that that best method to measure the amount of aliasing in an image is by utilizing the frequency domain. &#xD;&#xA;&#xD;&#xA;**Is there a relationship between spatial frequency of an image and aliasing ? &#xD;&#xA;Also, is there any other metric that one can use to measure the amount of aliasing that is present in an image ?** " ContentLicense="CC BY-SA 3.0" />
  <row Id="14575" PostHistoryTypeId="1" PostId="5360" RevisionGUID="fba193b4-2a7f-4475-83c6-7de53e24f33c" CreationDate="2017-07-14T14:37:00.287" UserId="6974" Text="Relationship between spatial frequency of an image and Aliasing" ContentLicense="CC BY-SA 3.0" />
  <row Id="14576" PostHistoryTypeId="3" PostId="5360" RevisionGUID="fba193b4-2a7f-4475-83c6-7de53e24f33c" CreationDate="2017-07-14T14:37:00.287" UserId="6974" Text="|image-processing|antialiasing|image-comparison|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14577" PostHistoryTypeId="2" PostId="5361" RevisionGUID="863f3a0e-6618-45b0-a1ac-e547432da28e" CreationDate="2017-07-14T15:32:26.470" UserId="2041" Text="Like in any other kind of signal processing, the relationship is Nyquist's theorem. An image is a discrete sequence of samples of a continuous signal. If the original signal has frequency components higher than half the sampling rate, then there will be aliasing. To put that another way, if you look at the real-world size of a pixel, any details smaller than two pixels wide will be aliased. This applies to synthetic images as well as to photographs. If you define a procedural texture via a mathematical function, the function is continuous but you only evaluate it at certain points.&#xD;&#xA;&#xD;&#xA;The problem is, of course, if you only have the sampled image and not the original signal, the high-frequency components have *already* been aliased, so you can't measure them directly. You have to use statistical techniques to guess which details in your aliased image were originally higher-frequency signals." ContentLicense="CC BY-SA 3.0" />
  <row Id="14578" PostHistoryTypeId="2" PostId="5362" RevisionGUID="682dbfb1-9da1-41bd-9b97-50882dcc1e57" CreationDate="2017-07-14T19:00:06.583" UserId="6838" Text="On the [main page][1] for Allegorithmic's Bitmap2Material, it mentions that the software uses a **Slope Based** approach over a **Luminance Based** approach. What exactly does this mean?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.allegorithmic.com/products/bitmap2material/ &quot;Bitmap2Material&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14579" PostHistoryTypeId="1" PostId="5362" RevisionGUID="682dbfb1-9da1-41bd-9b97-50882dcc1e57" CreationDate="2017-07-14T19:00:06.583" UserId="6838" Text="Slope Based Texturing" ContentLicense="CC BY-SA 3.0" />
  <row Id="14580" PostHistoryTypeId="3" PostId="5362" RevisionGUID="682dbfb1-9da1-41bd-9b97-50882dcc1e57" CreationDate="2017-07-14T19:00:06.583" UserId="6838" Text="|texture|algorithm|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14583" PostHistoryTypeId="2" PostId="5363" RevisionGUID="0e954423-09cd-4b92-af5e-eecc50c7ada2" CreationDate="2017-07-15T07:09:41.110" UserId="6994" Text="I have a bounding box of 1000m x 1000m. I randomly generate 10000 points (sites) inside it. Now, how can I create 'n' polygons (geometries) within the bounding box based on a given constrain. &#xD;&#xA;&#xD;&#xA;The constrain could be anything. For example:&#xD;&#xA;&#xD;&#xA; 1. number of sites inside each polygon are same for all polygons&#xD;&#xA; 2. sum of distances from points inside the geometry to the centroid of geometry are same for all polygons&#xD;&#xA; 3. let's say, I assign a weight to each site then constrain i sum of weights inside each polygon are same for all polygons &#xD;&#xA; 4. area of each polygon is same&#xD;&#xA; 5. etc.&#xD;&#xA;&#xD;&#xA;Is there a way to generate such a geometry. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14584" PostHistoryTypeId="1" PostId="5363" RevisionGUID="0e954423-09cd-4b92-af5e-eecc50c7ada2" CreationDate="2017-07-15T07:09:41.110" UserId="6994" Text="constrain based dynamic geometry generation" ContentLicense="CC BY-SA 3.0" />
  <row Id="14585" PostHistoryTypeId="3" PostId="5363" RevisionGUID="0e954423-09cd-4b92-af5e-eecc50c7ada2" CreationDate="2017-07-15T07:09:41.110" UserId="6994" Text="|geometry|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14586" PostHistoryTypeId="2" PostId="5364" RevisionGUID="844f7d98-8057-475d-a19c-9820cd278251" CreationDate="2017-07-15T09:23:39.413" UserId="6124" Text="Imagine that a black dot represents a value of -1 whereas a white dot represents a value of +1. You are looking for the iso-line(s) where each point upon the line is 0.&#xD;&#xA;&#xD;&#xA;For this example you could either place the iso-lines like on the left or the right:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] or [![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The difference between the solutions is the value in the center. In the left case we assume 1s whereas in the right solution we assume -1s. So we check the center value and based on that value decide which solution fits best. If the center value is 1, we pick the left solution. If the center value is -1, we choose the right solution.&#xD;&#xA;&#xD;&#xA;  [3]: https://i.stack.imgur.com/IMlTY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/mALSW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14587" PostHistoryTypeId="2" PostId="5365" RevisionGUID="17217b33-437e-41e4-a3b4-92c2b590e1d7" CreationDate="2017-07-15T09:51:23.973" UserId="6124" Text="Very often, the [Lab][1] color space is used, since it is close to how humans perceive color. As to which distance to apply: This [wikipedia article][2] mentions a Delta E distance of 1.0 for a just noticeable difference. There are a lot of different formulas resulting in different thresholds.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Lab_color_space&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Color_difference#LAB_Delta_E" ContentLicense="CC BY-SA 3.0" />
  <row Id="14588" PostHistoryTypeId="5" PostId="5360" RevisionGUID="ec656aa5-3af9-4a08-b011-7e72279b9811" CreationDate="2017-07-15T12:40:44.607" UserId="231" Comment="Typos and tidying." Text="I was looking into measuring the amount of aliasing in an image. After reading through many papers and sites, I came to the conclusion that the best method to measure the amount of aliasing in an image is by utilizing the frequency domain. &#xD;&#xA;&#xD;&#xA;Is there a relationship between spatial frequency of an image and aliasing? &#xD;&#xA;Also, is there any other metric that one can use to measure the amount of aliasing that is present in an image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14589" PostHistoryTypeId="5" PostId="5363" RevisionGUID="f4c1574a-bcec-4263-b8ce-f82af7269f0f" CreationDate="2017-07-15T12:49:28.720" UserId="6994" Comment="added 104 characters in body" Text="I have a bounding box of 1000m x 1000m. I randomly generate 10000 points (sites) inside it. Now, how can I create 'n' polygons (geometries) within the bounding box based on a given constrain. &#xD;&#xA;&#xD;&#xA;The constrain could be anything. For example:&#xD;&#xA;&#xD;&#xA; 1. number of sites inside each polygon are same for all polygons&#xD;&#xA; 2. sum of distances from points inside the geometry to the centroid of geometry are same for all polygons&#xD;&#xA; 3. let's say, I assign a weight to each site then constrain i sum of weights inside each polygon are same for all polygons &#xD;&#xA; 4. area of each polygon is same&#xD;&#xA; 5. etc.&#xD;&#xA;&#xD;&#xA;Is there a way to generate such a geometry?&#xD;&#xA;&#xD;&#xA;P.S. -- would be great if someone can also point me in the right direction and then give down vote.  " ContentLicense="CC BY-SA 3.0" />
  <row Id="14594" PostHistoryTypeId="2" PostId="5366" RevisionGUID="94b685f7-0e69-4450-97f0-deb1fca2c814" CreationDate="2017-07-15T21:12:39.003" UserId="3003" Text="I find the hue/saturation or luminance/chrominance spaces to be fairly easy to work in. They follow our intuitive sense of how color works, even if they're not as scientifically accurate as Lab is. The [conversion from RGB to YCbCr](https://en.wikipedia.org/wiki/YCbCr#YCbCr) is a simple matrix multiply. Working in YCbCr would allow you to do things like keep luminance constant while changing hue and/or saturation. You can think of saturation as the distance of the color from the luminance axis (so just the magnitude of CbCr = sqrt(Cb x Cb + Cr x Cr)). The hue is the angle the color point makes with the x-axis when projected onto the CbCr plane. (So you can use atan2(Cr, Cb).) Once you've modified your values, converting back to RGB is another matrix multiply." ContentLicense="CC BY-SA 3.0" />
  <row Id="14595" PostHistoryTypeId="2" PostId="5367" RevisionGUID="088acb46-5881-4be4-b38e-0e284811153c" CreationDate="2017-07-16T03:44:51.177" UserId="6998" Text="This is something that pops up on my mind once a while when I browse around the web for art and desktop wallpaper, since I tend to see JPG and PNG as the common formats. I just had to ask to get it off my mind, hopefully I've posted in the correct stackexchange domain.&#xD;&#xA;&#xD;&#xA;I'm sure many computer users who are aware that PNG is a lossless computer image format (doesn't lose quality) while JPG is a lossy format (losses quality).&#xD;&#xA;&#xD;&#xA;After researching. I've found that PNG has been out since 1995 and the size of computer storage has drastically increased since then. Even if image resolution and file size increases, I'm sure anyone can store over 100,000+ PNG images on a single hard drive today.&#xD;&#xA;&#xD;&#xA;Personally when I look for art. I make sure I get the highest resolution available as a PNG. I'm aware converting from JPG to PNG will still have the lossy image detail from being a JPG." ContentLicense="CC BY-SA 3.0" />
  <row Id="14596" PostHistoryTypeId="1" PostId="5367" RevisionGUID="088acb46-5881-4be4-b38e-0e284811153c" CreationDate="2017-07-16T03:44:51.177" UserId="6998" Text="Why isn't PNG preferred over JPG for being lossless art quality yet?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14597" PostHistoryTypeId="3" PostId="5367" RevisionGUID="088acb46-5881-4be4-b38e-0e284811153c" CreationDate="2017-07-16T03:44:51.177" UserId="6998" Text="|image-comparison|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14598" PostHistoryTypeId="2" PostId="5368" RevisionGUID="3c911b47-7cd7-4636-ba98-c94ca65bef1c" CreationDate="2017-07-16T04:14:11.153" UserId="7000" Text="I am trying to draw a triangle.  Here is my code:&#xD;&#xA;	const char* vertexShaderSource = &quot;#version 330 core\n&quot;&#xD;&#xA;		&quot;layout (location = 0) in vec3 aPos;\n&quot;&#xD;&#xA;		&quot;void main()\n&quot;&#xD;&#xA;		&quot;{\n&quot;&#xD;&#xA;		&quot;   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n&quot;&#xD;&#xA;		&quot;}\0&quot;;&#xD;&#xA;&#xD;&#xA;	const char* fragmentShaderSource = &quot;#version 330 core\n&quot;&#xD;&#xA;		&quot;out vec4 FragColor;\n&quot;&#xD;&#xA;		&quot;void main()\n&quot;&#xD;&#xA;		&quot;{\n&quot;&#xD;&#xA;		&quot;   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n&quot;&#xD;&#xA;		&quot;}\n\0&quot;;&#xD;&#xA;&#xD;&#xA;	GLfloat vertices[] = {&#xD;&#xA;		-0.5f, -0.5f, 0.0f,&#xD;&#xA;		0.5f, -0.5f, 0.0f,&#xD;&#xA;		0.0f,  0.5f, 0.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	// Create the VAO&#xD;&#xA;	GLuint vao;&#xD;&#xA;	GLuint buffer;&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;buffer);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;	glBindVertexArray(vao);&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;This results in the following image:&#xD;&#xA;[![triangle][1]][1]&#xD;&#xA;&#xD;&#xA;However, trying to use newer, DSA type methods does not draw the correct triangle.  If I switch my code to:&#xD;&#xA;&#xD;&#xA;	glCreateBuffers(1, &amp;buffer);&#xD;&#xA;	glNamedBufferStorage(buffer, sizeof(vertices), vertices, 0);&#xD;&#xA;&#xD;&#xA;	glCreateVertexArrays(1, &amp;vao);&#xD;&#xA;	glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(GLfloat) * 3);&#xD;&#xA;	glVertexArrayAttribBinding(vao, 0, 0);&#xD;&#xA;	glEnableVertexArrayAttrib(vao, 0);&#xD;&#xA;&#xD;&#xA;I get this image:&#xD;&#xA;&#xD;&#xA;[![squished triangle][2]][2]&#xD;&#xA;&#xD;&#xA;The triangle is squished.  In fact, changing any of the coordinates of the last row of vertices (the point that is squished) do not change the image result.  Why is this happening?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7uGSN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1hBov.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14599" PostHistoryTypeId="1" PostId="5368" RevisionGUID="3c911b47-7cd7-4636-ba98-c94ca65bef1c" CreationDate="2017-07-16T04:14:11.153" UserId="7000" Text="Different result with DSA (vertexArrayVertexBuffer, vertexArrayAttribBinding) than with glBuffer Data" ContentLicense="CC BY-SA 3.0" />
  <row Id="14600" PostHistoryTypeId="3" PostId="5368" RevisionGUID="3c911b47-7cd7-4636-ba98-c94ca65bef1c" CreationDate="2017-07-16T04:14:11.153" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14601" PostHistoryTypeId="2" PostId="5369" RevisionGUID="93f6c4ab-9301-4e46-bb18-15e5cb0580e6" CreationDate="2017-07-16T12:07:48.543" UserId="2041" Text="I don't know if this is the real reason, but here's one possibility: because it's unnecessary.&#xD;&#xA;&#xD;&#xA;It's easy to say &quot;JPEG = lossy = bad&quot;, but JPEG doesn't just destroy image quality willy-nilly. What the format gives you is a slider with &quot;small, low-quality&quot; at one end and &quot;big, high-quality&quot; at the other. You can easily reduce the byte size of a PNG image by encoding it as JPEG, and if you use the high-quality end of the slider, you needn't lose any **visual** appeal. Although normal JPEG is *lossy* in the information-theoretic sense, a high-quality JPEG appears identical by the naked eye.&#xD;&#xA;&#xD;&#xA;Many image hosting sites will replace images by lower-quality JPEG files not because of the storage cost but because of the **bandwidth** cost. If you're serving millions of views of these files every day, the cost of sending those extra bytes is pretty big, even though the cost of storing them is tiny. And those bytes don't just cost money: they also cost load time for your users on mobile networks. These sites will have targets for how long their pages take to load on slow connections, and reducing the quality slider ever so slightly makes a big total difference.&#xD;&#xA;&#xD;&#xA;In summary, JPEG encoding can be lossless or lossy, and it can be as high- or low-quality as you want. Using PNG everywhere instead of JPEG would be costly for image sites and would make you wait longer for your art files to download. Choosing a high-quality JPEG file can give you something that looks just the same as the PNG without being as &quot;heavy&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="14602" PostHistoryTypeId="2" PostId="5370" RevisionGUID="4c605c52-b818-4351-9bf2-3eaa430b1ab2" CreationDate="2017-07-16T13:12:33.443" UserId="38" Text="Lossy does not nesseserily imply any major quality loss. It is mostly dropping out meaningless information of the image in favor a much smaller image file. Offcourse the amount of quality drop can be adjusted, and in best case scenario this is done so that the quality drop is just invisible.&#xD;&#xA;&#xD;&#xA;In exhange for this quality drop you get quite big file size savings. And for most part the quality drop just makes reusing the image for future edits harder. While this may sound bad, its actually a good thing for the author. The original author will store a master file that has not been compressed, thus making it harder for others to reclaim your work.&#xD;&#xA;&#xD;&#xA;Now it should be mentioned that jpeg only works well for photographic content. For synthetic images like logos PNG fares much better than jpeg in because the image has less variation. Also PNG does not guarantee lossless compression as you can preprocess the image for some compression gain, and often do so." ContentLicense="CC BY-SA 3.0" />
  <row Id="14603" PostHistoryTypeId="5" PostId="5370" RevisionGUID="2eebb666-03d3-4ee9-9f03-787007426747" CreationDate="2017-07-16T13:20:33.813" UserId="38" Comment="added 157 characters in body" Text="Lossy does not nesseserily imply any major quality loss. It is mostly dropping out meaningless information of the image in favor a much smaller image file. Offcourse the amount of quality drop can be adjusted, and in best case scenario this is done so that the quality drop is just invisible.&#xD;&#xA;&#xD;&#xA;In exhange for this quality drop you get quite big file size savings. And for most part the quality drop just makes reusing the image for future edits harder. While this may sound bad, its actually a good thing for the author. The original author will store a master file that has not been compressed, thus making it harder for others to reclaim your work.&#xD;&#xA;&#xD;&#xA;Also quite many times the image starts its life as a JPEG, as quite many cameras only allow output of JPEG files, because the otjer  option is HUGE files.&#xD;&#xA;&#xD;&#xA;Now it should be mentioned that jpeg only works well for photographic content. For synthetic images like logos PNG fares much better than jpeg in because the image has less variation. Also PNG does not guarantee lossless compression as you can preprocess the image for some compression gain, and often do so." ContentLicense="CC BY-SA 3.0" />
  <row Id="14604" PostHistoryTypeId="5" PostId="5370" RevisionGUID="19c39353-bff0-4105-83ec-343efa515004" CreationDate="2017-07-16T16:08:29.740" UserId="38" Comment="deleted 9 characters in body" Text="Lossy does not necessarily imply any major quality loss. It is mostly dropping out meaningless information of the image in favor a much smaller image file. The amount of quality drop can be adjusted, and in best case scenario this is done so that the quality drop is just invisible.&#xD;&#xA;&#xD;&#xA;In exchange for this quality drop you get quite big file size savings. And for most part the quality drop just makes reusing the image for future edits harder. While this may sound bad, its actually a good thing for the author. The original author will store a master file that has not been compressed, thus making it harder for others to reclaim your work.&#xD;&#xA;&#xD;&#xA;Also quite many times the image starts its life as a JPEG, as quite many cameras only allow output of JPEG files, because the other  option is HUGE files.&#xD;&#xA;&#xD;&#xA;Now it should be mentioned that JPEG only works well for photographic content. For synthetic images like logos PNG fares much better than jpeg in because the image has less variation. Also PNG does not guarantee lossless compression as you can preprocess the image for some compression gain, and often do so." ContentLicense="CC BY-SA 3.0" />
  <row Id="14605" PostHistoryTypeId="2" PostId="5371" RevisionGUID="80121465-43bd-4e70-9aaa-460f361fafce" CreationDate="2017-07-16T16:16:17.923" UserId="2654" Text="You forgot to call `glVertexArrayAttribFormat`:&#xD;&#xA;&#xD;&#xA;    glCreateBuffers(1, &amp;buffer);&#xD;&#xA;    glNamedBufferStorage(buffer, sizeof(vertices), vertices, 0);&#xD;&#xA;    &#xD;&#xA;    glCreateVertexArrays(1, &amp;vao);&#xD;&#xA;    glEnableVertexArrayAttrib(vao, 0);&#xD;&#xA;    glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;&#xD;&#xA;    glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(GLfloat) * 3);&#xD;&#xA;    glVertexArrayAttribBinding(vao, 0, 0);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14606" PostHistoryTypeId="2" PostId="5372" RevisionGUID="747f65d7-cc09-489b-9fe7-24b115d4ab09" CreationDate="2017-07-16T22:52:41.590" UserId="38" Text="It is possible to generate geometry from constraints. However, some of your constraints are hard to formulate as continious functions that can be minimized or maximized. Also the ones that can be  formulated this way have a staggering number of dimensions making gradient descents quite costly.&#xD;&#xA;&#xD;&#xA;This means, you can not use a gradient descent method to find the solution. In turn this makes the problem computationally harder to do as the only way to do so is by trying a number of solutions. &#xD;&#xA;&#xD;&#xA;So you would need to take some points by initial condition then solve for the constraints that can be made continious. And then reevaluate if no solution is found. So some genetic algorithm should work fine, altough it would be very ineficient.&#xD;&#xA;&#xD;&#xA;But more likely your looking for some sort of clustering solitions. But if i were to do this with this wague instructions (which would surely fail) i would start by building a voronoi diagram, as it would help me find the connectivity. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14608" PostHistoryTypeId="2" PostId="5373" RevisionGUID="67a604de-1078-4299-ac69-66fbf83265d9" CreationDate="2017-07-17T14:30:50.300" UserId="7008" Text="I am currently working with Earl Hammon Jr's Presentation [PBR Diffuse Lighting for GGX+Smith Microsurfaces][1] (now mentioned as [PBR, p.XYZ] and have read through (among others) Brent Burley's [Physically-Based Shading at Disney][2] (now mentioned as [DIS, p. XYZ] to get a good diffuse BRDF component. I am stuck at combining the two with the Fresnel Term.&#xD;&#xA;&#xD;&#xA;Short introduction for vectors and angles as I use them:&#xD;&#xA;&#xD;&#xA; - omega_i is the light vector&#xD;&#xA; - omega_o is the view vector&#xD;&#xA; - omega_n is the macro geometry normal&#xD;&#xA;&#xD;&#xA; - theta_i is the angle between omega_i and omega_n&#xD;&#xA; - theta_o is the angle between omega_o and omega_n&#xD;&#xA; - theta_h is the angle between omega_n and omega_h&#xD;&#xA; - alpha_hi is the angle between omega_i and omega_h &#xD;&#xA; - alpha_ho is the angle between omega_o and omega_h (this distinction is for clarification)&#xD;&#xA; - alpha_h is any of the angles alpha_hi, alpha_ho, since they are equal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;now given that rest_spec is the BRDF term of the specular component without the fresnel factor and rest_diff accordingly the term of the diffuse component without the fresnel stuff, the fresnel factor is written as F(angle). &#xD;&#xA;[PBR, p.105] mentions that the diffuse light is transmitted two times, once in and once out. Thus, the Fresnel component has to be multiplied two times. &#xD;&#xA;[PBR, p. 106] goes on to say Fresnel's laws are symmetrix, meaning entering and leaving is direction independent (i.e. it does not matter that once we go into the material from air and once we leave into air). Now I would assume (for F_1 is Fresnel for entering and F_2 is for Fresnel leaving the material) to use &#xD;&#xA;&#xD;&#xA;    F_1(alpha_hi)*F_2(alpha_ho)&#xD;&#xA;&#xD;&#xA;F_1 and F_2 are the same function, and alpha_hi and alpha_ho are the same angle, therefore&#xD;&#xA;&#xD;&#xA;    F(alpha_h)^2&#xD;&#xA;&#xD;&#xA;This would lead to a brdf f:&#xD;&#xA;&#xD;&#xA;    f = F(alpha_h) * rest_spec + F(alpha_h)^2 * rest_diff&#xD;&#xA;&#xD;&#xA;But both [PBR, p.113] and [DIS, p.14] use &#xD;&#xA;&#xD;&#xA;    f = F(alpha_h) * rest_spec + F(theta_i)*F(theta_o) * rest_diff&#xD;&#xA;&#xD;&#xA;as does the original paper to use this kind of calculation by Shirely et al. 1997.&#xD;&#xA;I just don't get this, why do they change from the microfacet angles to the macro angles? The microfacet angles lead to energy conversation (since F element of [0, 1] -&gt; F^2 element of [0, 1] and F(alpha_h) &gt;= F(alpha_h)^2), it should be reciprocal and thus fulfill BRDF requirements. The microfacet angle is used for the specular term, therefore it is the more sensible thing to interpolate between specular and diffuse component (ignoring the fact of two transmission for this argument).&#xD;&#xA;Instead, [PBR, p.113] and [DIS, p. 14] put the theta_h into a roughness calculation and leave that rather unexplained.&#xD;&#xA;&#xD;&#xA;Additionally to my confusion about this, in the explanation slides [PBR, p.187] uses the dot product omega_h * omega_o (and therefore the alpha_ho angle) and later on [PBR, p. 191] also the dot product omega_h * omega_i (-&gt; alpha_hi).&#xD;&#xA;&#xD;&#xA;  [1]: http://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14609" PostHistoryTypeId="1" PostId="5373" RevisionGUID="67a604de-1078-4299-ac69-66fbf83265d9" CreationDate="2017-07-17T14:30:50.300" UserId="7008" Text="Why is the half vector not used in diffuse BRDF Fresnel calculations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14610" PostHistoryTypeId="3" PostId="5373" RevisionGUID="67a604de-1078-4299-ac69-66fbf83265d9" CreationDate="2017-07-17T14:30:50.300" UserId="7008" Text="|brdf|pbr|diffuse|fresnel|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14611" PostHistoryTypeId="5" PostId="5372" RevisionGUID="afabf6c6-b7fd-406c-a63b-2ddd1100d11a" CreationDate="2017-07-17T19:57:09.087" UserId="38" Comment="added 2 characters in body" Text="It is possible to generate geometry from constraints. However, some of your constraints are hard to formulate as continuous functions that can be minimized or maximized. Also the ones that can be  formulated this way have a staggering number of dimensions making gradient descents quite costly.&#xD;&#xA;&#xD;&#xA;This means, you can not use a gradient descent method to find the solution. In turn this makes the problem computationally harder to do as the only way to do so is by trying a number of solutions. &#xD;&#xA;&#xD;&#xA;So you would need to take some points by initial condition then solve for the constraints that can be made continuous. And then reevaluate if no solution is found. So some genetic algorithm should work fine, although it would be very inefficient.&#xD;&#xA;&#xD;&#xA;But more likely your looking for some sort of clustering solutions. But if i were to do this with this vague instructions (which would surely fail) i would start by building a voronoi diagram, as it would help me find the connectivity. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14613" PostHistoryTypeId="2" PostId="5374" RevisionGUID="00099a24-88b9-4596-b1d8-9d3429db718b" CreationDate="2017-07-18T01:30:10.600" UserId="2096" Text="I have been learning OpenGL 3.3 and I saw this expression:&#xA;&#xA;gl_Position = projection * view * model * vertex&#xA;&#xA;I am confused because I read in some book that if the vector (vertex) is placed on right side of the matrix then it would be a column vector and to transform this vector you should have a column major matrix.&#xA;&#xA;But glm library follows GLSL right. So I printed the glm::mat4 and It was a row-major matrix. &#xA;&#xA;I am confused. Please help. Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="14614" PostHistoryTypeId="1" PostId="5374" RevisionGUID="00099a24-88b9-4596-b1d8-9d3429db718b" CreationDate="2017-07-18T01:30:10.600" UserId="2096" Text="Why do we multiply vertex from left side in vertex shader with matrices?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14615" PostHistoryTypeId="3" PostId="5374" RevisionGUID="00099a24-88b9-4596-b1d8-9d3429db718b" CreationDate="2017-07-18T01:30:10.600" UserId="2096" Text="|opengl|glsl|matrix|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14616" PostHistoryTypeId="2" PostId="5375" RevisionGUID="15edcc18-d566-45f8-9dd1-09cf2bd79ec8" CreationDate="2017-07-18T03:17:51.180" UserId="3003" Text="OpenGL uses column-major matrices. For example, the translation values will be in the last row rather than the last column of the matrix. For example when loading matrices into uniforms in glsl, the [`glUniformMatrix4fv()` function](https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glUniform.xml) takes its matrix parameters in column-major order:&#xD;&#xA;&#xD;&#xA;&gt; Each matrix is assumed to be supplied in column major order.&#xD;&#xA;&#xD;&#xA;In glm, the matrices are also in column-major order. From the `matrix_transform.hpp` header, the comment for the `translate()` method says this:&#xD;&#xA;&#xD;&#xA;    /// #include &lt;glm/glm.hpp&gt;&#xD;&#xA;	/// #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;	/// ...&#xD;&#xA;	/// glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f));&#xD;&#xA;	/// // m[0][0] == 1.0f, m[0][1] == 0.0f, m[0][2] == 0.0f, m[0][3] == 0.0f&#xD;&#xA;	/// // m[1][0] == 0.0f, m[1][1] == 1.0f, m[1][2] == 0.0f, m[1][3] == 0.0f&#xD;&#xA;	/// // m[2][0] == 0.0f, m[2][1] == 0.0f, m[2][2] == 1.0f, m[2][3] == 0.0f&#xD;&#xA;	/// // m[3][0] == 1.0f, m[3][1] == 1.0f, m[3][2] == 1.0f, m[3][3] == 1.0f&#xD;&#xA;&#xD;&#xA;Note that the translation amount (1,1,1) is in the last row rather than the last column." ContentLicense="CC BY-SA 3.0" />
  <row Id="14618" PostHistoryTypeId="2" PostId="5376" RevisionGUID="2844caf4-0bc5-40ce-b3f3-65f145798c31" CreationDate="2017-07-18T07:58:37.583" UserId="38" Text="There is no 100% consensus on what order matrix multiplication should model things, worse the industry is split along this. Some sources use row major and some sources use column major matrices. Great care should be taken to verify which is being used in your source and what is being used by your API! &#xD;&#xA;&#xD;&#xA;Some API's go as far as allowing one to multiply vectors on both sides of the matrix. The wisdom is thus in reading your API reference and verifying how it works. Old, fixed pipeline OpenGL and glm, does in fact use column major matrices. While (**warning**) DirectX had chosen to use row major matrices \[[source](http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html)\]. Obviously with programmable shaders any application can have any order, even mixed one!&#xD;&#xA;&#xD;&#xA;Due to fundamental properties of matrices this duality is the same as transposing the matrix. If you transpose the matrix you reverse the order of calculation, as you are now thinking outside in instead of inside out or vice versa.&#xD;&#xA;&#xD;&#xA;The moral of the story is that you should always check your assumptions. And just printing out values does always help as the printing function can screw things up. Also simple testing may make you blind to having mixed conventions inside your program. **Read what convention is in use**! Because, as confusing as having two sources with different  conventions is, it pales in comparasion to a piece of software that mixes the two in the codebase." ContentLicense="CC BY-SA 3.0" />
  <row Id="14619" PostHistoryTypeId="5" PostId="5376" RevisionGUID="d70eb105-ebd3-45e7-9c7e-fed28e81bc63" CreationDate="2017-07-18T08:34:18.817" UserId="38" Comment="added 39 characters in body" Text="There is no 100% consensus on what order matrix multiplication should model things, worse the industry is split along this. Some sources use row major and some sources use column major matrices. Great care should be taken to verify which is being used in your source and what is being used by your API!&#xD;&#xA;&#xD;&#xA;Some API's go as far as allowing one to multiply vectors on both sides of the matrix. The wisdom is thus in reading your API reference and verifying how it works. Old, fixed pipeline OpenGL and glm, does in fact use column major matrices. While (**warning**) DirectX had chosen to use row major matrices \[[source](http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html)\]. Obviously with programmable shaders any application can have any order, even mixed one&#xD;&#xA;&#xD;&#xA;Due to fundamental properties of matrices this duality is the same as transposing the matrix. If you transpose the matrix you reverse the order of calculation, as you are now thinking outside in instead of inside out or vice versa.&#xD;&#xA;&#xD;&#xA;The moral of the story is that you should always check your assumptions. And just printing out values does not always help as the printing function can screw things up, and memory not aligned the same way. Also simple testing may make you blind to having mixed conventions inside your program. **Read what convention is in use**! Because, as confusing as having two sources with different  conventions is, it pales in comparasion to a piece of software that mixes the two in the codebase." ContentLicense="CC BY-SA 3.0" />
  <row Id="14620" PostHistoryTypeId="2" PostId="5377" RevisionGUID="8c428b39-e022-4e3c-9066-9f28a9d5228c" CreationDate="2017-07-18T09:18:07.740" UserId="7013" Text="[![enter image description here][1]][1]I have 3 vertices `(V1, V2, V3)` randomly selected on a regular triangle mesh. For these 3 vertices, I have computed the geodesic distance and path (by using Dijkstra) among them and formed a triangle-like surface as in the above figure. &#xD;&#xA;&#xD;&#xA;Now, I have the vertices that lie in each path and can compute geodesic distances from a given vertex.&#xD;&#xA;&#xD;&#xA;What I want to do is to get the vertices or triangles that lies in triangle-like area. How can I do this?&#xD;&#xA;&#xD;&#xA;Thanks. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/49rn8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14621" PostHistoryTypeId="1" PostId="5377" RevisionGUID="8c428b39-e022-4e3c-9066-9f28a9d5228c" CreationDate="2017-07-18T09:18:07.740" UserId="7013" Text="How can I perform a triangle inside test in polygon meshes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14622" PostHistoryTypeId="3" PostId="5377" RevisionGUID="8c428b39-e022-4e3c-9066-9f28a9d5228c" CreationDate="2017-07-18T09:18:07.740" UserId="7013" Text="|mesh|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14623" PostHistoryTypeId="5" PostId="5377" RevisionGUID="63984ae6-129a-430c-87a6-ab84b476d1e9" CreationDate="2017-07-18T12:05:41.060" UserId="231" Comment="Remove thanks" Text="[![enter image description here][1]][1]&#xD;&#xA;I have 3 vertices `(V1, V2, V3)` randomly selected on a regular triangle mesh. For these 3 vertices, I have computed the geodesic distance and path (by using Dijkstra) among them and formed a triangle-like surface as in the above figure. &#xD;&#xA;&#xD;&#xA;Now, I have the vertices that lie in each path and can compute geodesic distances from a given vertex.&#xD;&#xA;&#xD;&#xA;What I want to do is to get the vertices or triangles that lies in triangle-like area. How can I do this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/49rn8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14624" PostHistoryTypeId="5" PostId="5374" RevisionGUID="92f409de-50a6-42ce-9003-ebc8622dc48e" CreationDate="2017-07-18T12:08:30.813" UserId="231" Comment="Tidying" Text="I have been learning OpenGL 3.3 and I saw this expression:&#xD;&#xA;&#xD;&#xA;    gl_Position = projection * view * model * vertex&#xD;&#xA;&#xD;&#xA;I am confused because I read in some book that if the vector (vertex) is placed on the right side of the matrix then it would be a column vector and to transform this vector you should have a column major matrix.&#xD;&#xA;&#xD;&#xA;But glm library follows GLSL right. So I printed the `glm::mat4` and it was a row-major matrix." ContentLicense="CC BY-SA 3.0" />
  <row Id="14625" PostHistoryTypeId="2" PostId="5378" RevisionGUID="a200cf0f-a0e8-489e-abc4-c48dd54b8e1c" CreationDate="2017-07-18T12:22:01.350" UserId="273" Text="I think you can calculate some surface-bound barycentric coordinates for each point on the surface, and then use them to check for inside or outside of the triangle.&#xD;&#xA;&#xD;&#xA;I don't have an exact algorithm at hand but I found this following paper which does seem to handle exactly this kind of coordinates.&#xD;&#xA;&#xD;&#xA;[Barycentric Coordinates On Surfaces][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cct.lsu.edu/~swan2/Reference/DifferentialGeom/papers/BaryCoordonSurf_Rustamov2010SGP.pdf &quot;Barycentric Coordinates On Surfaces&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14626" PostHistoryTypeId="5" PostId="5377" RevisionGUID="32a53bdb-4969-497d-b404-8ea909ec72be" CreationDate="2017-07-18T12:57:17.630" UserId="7013" Comment="added 4 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;I have 3 vertices `(V1, V2, V3)` randomly selected on a regular triangle mesh. For these 3 vertices, I have computed the geodesic distance and the path (by using Dijkstra) among them and formed a triangle-like surface as in the above figure. &#xD;&#xA;&#xD;&#xA;Now, I have the vertices that lie in each path and can compute geodesic distances from a given vertex.&#xD;&#xA;&#xD;&#xA;What I want to do is to get the vertices or triangles that lies in triangle-like area. How can I do this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/49rn8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14627" PostHistoryTypeId="2" PostId="5379" RevisionGUID="c3612ec2-48f9-4ea0-9085-0d66f37574ad" CreationDate="2017-07-18T18:32:50.670" UserId="7000" Text="When using the [GLAD][1] web service, I am allowed to pick any version of OpenGL and any extensions I want.&#xD;&#xA;&#xD;&#xA;If I pick the latest version of OpenGL and &quot;all extensions&quot;, will the header file returned by the Web Service `#define` extensions on my machine that I do not actually have or does it just define those that exist?&#xD;&#xA;&#xD;&#xA;In other words, if I include the `GL_ARB_SHADER_CLOCK` extension, on GLAD, does it get defined even if not available on the machine I use?&#xD;&#xA;&#xD;&#xA;I don't see how it could be selectively defining extensions because the script is generated on a server ahead of time but I want to make sure that I am not trying to use unsupported extensions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://glad.dav1d.de/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14628" PostHistoryTypeId="1" PostId="5379" RevisionGUID="c3612ec2-48f9-4ea0-9085-0d66f37574ad" CreationDate="2017-07-18T18:32:50.670" UserId="7000" Text="How do I include all extensions my system supports using GLAD" ContentLicense="CC BY-SA 3.0" />
  <row Id="14629" PostHistoryTypeId="3" PostId="5379" RevisionGUID="c3612ec2-48f9-4ea0-9085-0d66f37574ad" CreationDate="2017-07-18T18:32:50.670" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14630" PostHistoryTypeId="2" PostId="5380" RevisionGUID="102e90fa-a0fd-4ba1-a3b4-71625cdc95f1" CreationDate="2017-07-18T21:37:16.053" UserId="38" Text="Tere is an alternate method that relies on flood filling. First arrange your edge data to a loop where the edges are forming a  counterclockwise loop. Then start at an arbitrary point on the loop and pick edges joining that point. Use the outbound  boundary edge and cross it with the other outbound edge, if it points in the direction of the face normal then its a edge to be included, if not discard it. From this edge continue until you hit a boundary edge, at which point you terminate the fill. Continue at a yet to bee visited boundary edge vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="14631" PostHistoryTypeId="2" PostId="5381" RevisionGUID="21dff5bb-283a-409d-a665-1ee60ab5136f" CreationDate="2017-07-18T23:28:05.997" UserId="7000" Text="My question is very similar to [this one][1] but the answers there did not help me.&#xD;&#xA;&#xD;&#xA;I am trying to use the DSA approach to bind textures and it is not working.&#xD;&#xA;&#xD;&#xA;Here is my attempt at the DSA code, which leads too all black in as my output:&#xD;&#xA;&#xD;&#xA;    GLuint samplerName;&#xD;&#xA;    glCreateSamplers(1, &amp;samplerName);&#xD;&#xA;    glSamplerParameteri(samplerName, GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;    glSamplerParameteri(samplerName, GL_TEXTURE_WRAP_T, GL_REPEAT);&#xD;&#xA;    glSamplerParameteri(samplerName, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glSamplerParameteri(samplerName, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;    glBindSampler(0, samplerName);&#xD;&#xA;    &#xD;&#xA;    // Create texture&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;texture);&#xD;&#xA;    glTextureStorage2D(texture, 1, GL_RGB, width, height);&#xD;&#xA;    glTextureSubImage2D(texture, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);&#xD;&#xA;    glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glBindTextureUnit(0, texture);&#xD;&#xA;    &#xD;&#xA;If I add these two lines from the older approach:&#xD;&#xA;&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;it works so I do not think it is an issue with my sampler or my data. Does anybody have any advice here? &#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4479/how-to-do-texturing-with-opengl-direct-state-access" ContentLicense="CC BY-SA 3.0" />
  <row Id="14632" PostHistoryTypeId="1" PostId="5381" RevisionGUID="21dff5bb-283a-409d-a665-1ee60ab5136f" CreationDate="2017-07-18T23:28:05.997" UserId="7000" Text="Problem Using DSA And Textures" ContentLicense="CC BY-SA 3.0" />
  <row Id="14633" PostHistoryTypeId="3" PostId="5381" RevisionGUID="21dff5bb-283a-409d-a665-1ee60ab5136f" CreationDate="2017-07-18T23:28:05.997" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14634" PostHistoryTypeId="2" PostId="5382" RevisionGUID="5b2803a1-1756-41c3-812a-14327e17ef05" CreationDate="2017-07-19T00:25:35.180" UserId="7000" Text="My issue was in the call to `glTextureStorage2D(texture, 1, GL_RGB, width, height);`&#xD;&#xA;&#xD;&#xA;From [the man page][1]&#xD;&#xA;&gt; internalformat must be one of the sized internal formats given in Table 1 below, one of the sized depth-component formats GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, or GL_DEPTH_COMPONENT16, one of the combined depth-stencil formats, GL_DEPTH32F_STENCIL8, or GL_DEPTH24_STENCIL8, or the stencil-only format, GL_STENCIL_INDEX8&#xD;&#xA;&#xD;&#xA;Changing `GL_RGB` to `GL_RGB8` fixed my issue. &#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage2D.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="14635" PostHistoryTypeId="5" PostId="5373" RevisionGUID="bbc2787b-b754-41b5-bb4c-951f2a103cb2" CreationDate="2017-07-19T06:03:02.603" UserId="7008" Comment="I used F(angle) for transmission in the original, edited it to be (1-F(angle)) since transmission ratio is everything that is not reflected, i.e. 1-reflected." Text="I am currently working with Earl Hammon Jr's Presentation [PBR Diffuse Lighting for GGX+Smith Microsurfaces][1] (now mentioned as [PBR, p.XYZ] and have read through (among others) Brent Burley's [Physically-Based Shading at Disney][2] (now mentioned as [DIS, p. XYZ] to get a good diffuse BRDF component. I am stuck at combining the two with the Fresnel Term.&#xD;&#xA;&#xD;&#xA;Short introduction for vectors and angles as I use them:&#xD;&#xA;&#xD;&#xA; - omega_i is the light vector&#xD;&#xA; - omega_o is the view vector&#xD;&#xA; - omega_n is the macro geometry normal&#xD;&#xA;&#xD;&#xA; - theta_i is the angle between omega_i and omega_n&#xD;&#xA; - theta_o is the angle between omega_o and omega_n&#xD;&#xA; - theta_h is the angle between omega_n and omega_h&#xD;&#xA; - alpha_hi is the angle between omega_i and omega_h &#xD;&#xA; - alpha_ho is the angle between omega_o and omega_h (this distinction is for clarification)&#xD;&#xA; - alpha_h is any of the angles alpha_hi, alpha_ho, since they are equal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;now given that rest_spec is the BRDF term of the specular component without the fresnel factor and rest_diff accordingly the term of the diffuse component without the fresnel stuff, the fresnel factor is written as F(angle). &#xD;&#xA;[PBR, p.105] mentions that the diffuse light is transmitted two times, once in and once out. Thus, the Fresnel component has to be multiplied two times. &#xD;&#xA;[PBR, p. 106] goes on to say Fresnel's laws are symmetrix, meaning entering and leaving is direction independent (i.e. it does not matter that once we go into the material from air and once we leave into air). Now I would assume (for F_1 is Fresnel for entering and F_2 is for Fresnel leaving the material) to use &#xD;&#xA;&#xD;&#xA;    (1-F_1(alpha_hi))*(1-F_2(alpha_ho))&#xD;&#xA;&#xD;&#xA;F_1 and F_2 are the same function, and alpha_hi and alpha_ho are the same angle, therefore&#xD;&#xA;&#xD;&#xA;    (1-F(alpha_h))^2&#xD;&#xA;&#xD;&#xA;This would lead to a brdf f:&#xD;&#xA;&#xD;&#xA;    f = F(alpha_h) * rest_spec + (1-F(alpha_h))^2 * rest_diff&#xD;&#xA;&#xD;&#xA;But both [PBR, p.113] and [DIS, p.14] use &#xD;&#xA;&#xD;&#xA;    f = F(alpha_h) * rest_spec + (1-F(theta_i))*(1-F(theta_o)) * rest_diff&#xD;&#xA;&#xD;&#xA;as does the original paper to use this kind of calculation by Shirely et al. 1997.&#xD;&#xA;I just don't get this, why do they change from the microfacet angles to the macro angles? The microfacet angles lead to energy conversation&#xD;&#xA;&#xD;&#xA;    F element of [0, 1] &#xD;&#xA;    -&gt; (1-F) element of [0, 1] &#xD;&#xA;    -&gt; (1-F)^2 element of [0, 1] and (1-F(alpha_h)) &gt;= (1-F(alpha_h))^2)&#xD;&#xA;&#xD;&#xA;it should be reciprocal&#xD;&#xA;&#xD;&#xA;    f(theta_i, theta_o) &#xD;&#xA;    = F(alpha_hi) * rest_spec + (1-F(alpha_hi))*(1-F(alpha_ho) * rest_diff &#xD;&#xA;    = F(alpha_h) * rest_spec + (1-F(alpha_h))^2 * rest_diff &#xD;&#xA;    = F(alpha_ho) * rest_spec + (1-F(alpha_ho))*(1-F(alpha_hi)) * rest_diff &#xD;&#xA;    = f(theta_o, theta_i)&#xD;&#xA;&#xD;&#xA;and thus fulfill BRDF requirements. The microfacet angle is used for the specular term, therefore it is the more sensible thing to interpolate between specular and diffuse component (ignoring the fact of two transmissions for this argument).&#xD;&#xA;Instead, [PBR, p.113] and [DIS, p. 14] put the theta_h into a roughness calculation and leave that rather unexplained.&#xD;&#xA;&#xD;&#xA;Additionally to my confusion about this, in the explanation slides [PBR, p.187] uses the dot product omega_h * omega_o (and therefore the alpha_ho angle) and later on [PBR, p. 191] also the dot product omega_h * omega_i (-&gt; alpha_hi).&#xD;&#xA;&#xD;&#xA;  [1]: http://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14636" PostHistoryTypeId="2" PostId="5383" RevisionGUID="f36ec896-7576-4e63-8f82-bd1385740b6f" CreationDate="2017-07-19T07:25:04.967" UserId="113" Text="I've already commented on the use of flood fill and how it would be better as it's more flexible but another possible solution is scanline (I say possible because it makes a lot of assumptions about your geometry but for the particular set shown and many similar ones it would work.).&#xD;&#xA;&#xD;&#xA;For your example with 3 points. Find the intersection vertex from the segment v1,v2 and the line that v3 lies on. (The vertex to the upper left of v2) We'll call this vertex v4. &#xD;&#xA;&#xD;&#xA;    For every vertex pair a,b down v1,v4 and v1,v3 &#xD;&#xA;        For every vertex from a to b&#xD;&#xA;            Mark as in the set&#xD;&#xA;    For every vertex pair a,b down v3,v2 and v4,v3&#xD;&#xA;        For every vertex from a to b&#xD;&#xA;            Mark as in the set&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It's called scanline because (in the image above) you go down the red and green lines simultaneously and then red and blue lines simultaneously scanning the lines in as you go.&#xD;&#xA;&#xD;&#xA;This solution would be very fast if there is a index pattern. Which is often the case. Otherwise a calculation would be needed to determine which neighboring vertex lies on the line.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XsUCe.gif&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14637" PostHistoryTypeId="5" PostId="5383" RevisionGUID="7a4d8d19-d2bc-4ca4-9990-bf6ee7dd2142" CreationDate="2017-07-19T07:32:14.157" UserId="113" Comment="added 142 characters in body" Text="I've already commented on the use of flood fill and how it would be better as it's more flexible but another possible solution is scanline (I say possible because it makes a lot of assumptions about your geometry but for the particular set shown and many similar ones it would work.).&#xD;&#xA;&#xD;&#xA;For your example with 3 points. Find the intersection vertex from the segment v1,v2 and the line that v3 lies on. (The vertex to the upper left of v2) We'll call this vertex v4. &#xD;&#xA;&#xD;&#xA;    For every vertex pair a,b down v1,v4 and v1,v3 &#xD;&#xA;        For every vertex from a to b&#xD;&#xA;            Mark as in the set&#xD;&#xA;    For every vertex pair a,b down v3,v2 and v4,v3&#xD;&#xA;        For every vertex from a to b&#xD;&#xA;            Mark as in the set&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It's called scanline because (in the image above) you go down the red and green lines simultaneously and then red and blue lines simultaneously scanning the lines in as you go.&#xD;&#xA;&#xD;&#xA;This solution would be very fast if there is a index pattern. Which is often the case. Otherwise a calculation would be needed to determine which neighboring vertex lies on the line.&#xD;&#xA;&#xD;&#xA;Funny thing is scanline, barycentric testing (in triangle bounding box), and flood fill are all ways of drawing triangles in 3d rendering.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XsUCe.gif&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14642" PostHistoryTypeId="2" PostId="5386" RevisionGUID="bc4183b0-73ce-4347-a410-5ee4ee321b7b" CreationDate="2017-07-19T14:58:01.647" UserId="2654" Text="The &quot;all&quot; extensions option means exactly what it says: all extensions. If it exists, then its in the generated header. But this doesn't mean that the code will fail to execute on an implementation that doesn't provide every extension. The extensions you select are merely what the generated files make available to you.&#xD;&#xA;&#xD;&#xA;But of course, the whole point of selecting specific extensions is that you don't have stuff you don't use cluttering up your header. If you're going to select everything, you may as well be using GLEW." ContentLicense="CC BY-SA 3.0" />
  <row Id="14646" PostHistoryTypeId="2" PostId="5388" RevisionGUID="5a92bea7-9a7e-4c53-8e6d-6db1f39c4b68" CreationDate="2017-07-19T18:35:45.040" UserId="7000" Text=" this [github issue][1] the GLAD author offers the following way to correctly check if there is an extension is available at runtime:&#xD;&#xA;&#xD;&#xA;&gt; The defines just allow you to check at compile time which extensions&#xD;&#xA;&gt; (and opengl versions) are potentially available. After&#xD;&#xA;&gt; loading/initilaizing glad you can check with GLAD_&lt;name of extension&gt;&#xD;&#xA;&gt; if the extension is available at runtime (= supported by the driver&#xD;&#xA;&gt; and loaded).&#xD;&#xA;&gt;     // [initialize glad] // ...&#xD;&#xA;&gt;     &#xD;&#xA;&gt;     if (!GLAD_GL_EXT_memory_object) {&#xD;&#xA;&gt;         die(&quot;GL_EXT_memory_object not supported!&quot;); &#xD;&#xA;&gt;     }&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;[1]: https://github.com/Dav1dde/glad/issues/97&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14647" PostHistoryTypeId="2" PostId="5389" RevisionGUID="b31b238a-957c-4150-8518-9af10d1ebd53" CreationDate="2017-07-19T19:52:02.130" UserId="7016" Text="The biggest bottleneck of my code is fetching texture RGB values from memory.&#xD;&#xA;&#xD;&#xA;My code looks something like this:&#xD;&#xA;&#xD;&#xA;    game loop{&#xD;&#xA;	    for every mesh{&#xD;&#xA;		    perform clipping;&#xD;&#xA;		    for every 3 verticies in mesh {&#xD;&#xA;			    draw triangle {&#xD;&#xA;			    	interpolate texture coordinates;&#xD;&#xA;			    	fetch texture RGB and place value in backbuffer;&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fetching the texture RGB value from memory takes up so much time!!&#xD;&#xA;&#xD;&#xA;I am not familiar with multithreading but I'm assuming there is some way to apply it here. Let me know what suggestions you have and how I should go about doing this!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14648" PostHistoryTypeId="1" PostId="5389" RevisionGUID="b31b238a-957c-4150-8518-9af10d1ebd53" CreationDate="2017-07-19T19:52:02.130" UserId="7016" Text="How to use multithreading in 3D software renderer to speed up fetching texture values" ContentLicense="CC BY-SA 3.0" />
  <row Id="14649" PostHistoryTypeId="3" PostId="5389" RevisionGUID="b31b238a-957c-4150-8518-9af10d1ebd53" CreationDate="2017-07-19T19:52:02.130" UserId="7016" Text="|texture|3d|c++|rasterizer|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14650" PostHistoryTypeId="5" PostId="5388" RevisionGUID="677df225-2030-481b-9c3a-2b941d802c2a" CreationDate="2017-07-19T22:02:46.043" UserId="7000" Comment="deleted 5 characters in body" Text=" this [github issue][1] the GLAD author offers the following way to correctly check if there is an extension is available at runtime:&#xD;&#xA;&#xD;&#xA;&gt; The defines just allow you to check at compile time which extensions&#xD;&#xA;&gt; (and opengl versions) are potentially available. After&#xD;&#xA;&gt; loading/initilaizing glad you can check with GLAD_&lt;name of extension&gt;&#xD;&#xA;&gt; if the extension is available at runtime (= supported by the driver&#xD;&#xA;&gt; and loaded).&#xD;&#xA;&gt;&#xD;&#xA;&gt;     // [initialize glad] // ...&#xD;&#xA;&gt;     if (!GLAD_GL_EXT_memory_object) {&#xD;&#xA;&gt;         die(&quot;GL_EXT_memory_object not supported!&quot;); &#xD;&#xA;&gt;     }&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;[1]: https://github.com/Dav1dde/glad/issues/97&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14651" PostHistoryTypeId="5" PostId="5380" RevisionGUID="c8397318-cffd-4b2e-b144-a71f521a51d6" CreationDate="2017-07-19T22:05:00.340" UserId="231" Comment="Tidying" Text="There is an alternative method that relies on flood filling. First arrange your edge data into a loop where the edges are forming a counterclockwise loop. Then start at an arbitrary point on the loop and pick edges joining that point. Use the outbound boundary edge and cross it with the other outbound edge, if it points in the direction of the face normal then it's an edge to be included, if not discard it. From this edge continue until you hit a boundary edge, at which point you terminate the fill. Continue at a yet to be visited boundary edge vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="14652" PostHistoryTypeId="5" PostId="5383" RevisionGUID="8b485c82-b240-4af2-97c7-08d8330e49b1" CreationDate="2017-07-19T22:10:48.463" UserId="231" Comment="Minor tidying" Text="I've already commented on the use of flood fill and how it would be better as it's more flexible but another possible solution is scanline. (I say possible because it makes a lot of assumptions about your geometry but for the particular set shown and many similar ones it would work.)&#xD;&#xA;&#xD;&#xA;For your example with 3 points: Find the intersection vertex from the segment v1,v2 and the line that v3 lies on. (The vertex to the upper left of v2) We'll call this vertex v4. &#xD;&#xA;&#xD;&#xA;    For every vertex pair a,b down v1,v4 and v1,v3 &#xD;&#xA;        For every vertex from a to b&#xD;&#xA;            Mark as in the set&#xD;&#xA;    For every vertex pair a,b down v3,v2 and v4,v3&#xD;&#xA;        For every vertex from a to b&#xD;&#xA;            Mark as in the set&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It's called scanline because (in the image above) you go down the red and green lines simultaneously and then red and blue lines simultaneously scanning the lines in as you go.&#xD;&#xA;&#xD;&#xA;This solution would be very fast if there is an index pattern, which is often the case. Otherwise a calculation would be needed to determine which neighboring vertex lies on the line.&#xD;&#xA;&#xD;&#xA;Funny thing is scanline, barycentric testing (in triangle bounding box), and flood fill are all ways of drawing triangles in 3d rendering.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XsUCe.gif&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14653" PostHistoryTypeId="2" PostId="5390" RevisionGUID="80117803-f63e-4f8d-97ea-e4855b7eefd4" CreationDate="2017-07-20T07:14:03.170" UserId="7023" Text="I am using Unreal Engine to export custom render passes for the scene depth in world units. Every pixel in the render pass has a value which is the distance from the camera to that pixel in standard UE4 units. For example, a pixel with a value of 500 (more precisely 500,500,500) would be 500cm away from the camera.&#xD;&#xA;&#xD;&#xA;I am then taking these render passes and trying to project them into point clouds inside Houdini. I have this all working, but I'm having trouble figuring out how to correct for the distortion that arises in the point cloud.&#xD;&#xA;&#xD;&#xA;In my attempt to understand this, I have created a box which is the same aspect ratio as my output (1920 x 1080) and positioned the camera in such a way that it fills the frame more or less exactly.&#xD;&#xA;&#xD;&#xA;Below is the point cloud, with a wireframe showing where the box was in Unreal Engine. After distortion correction, all those points should align with the face of box nearest the camera on the left. The centre pixels are in the correct place, but as you can see the further away from the centre the more offset they become from their true spatial location.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I understand that this distortion is arising because the render pass is essentially drawing a line from each pixel to the camera, so the further away from centre, the longer the line, giving the false impression of increased depth across what should be a flat plane.&#xD;&#xA;&#xD;&#xA;I have been doing a lot of experimenting with varying distances, sizes of boxes, focal lengths, and so on, trying to figure out what the formula is to correct this distortion, but I'm completely stuck.&#xD;&#xA;&#xD;&#xA;I feel like the formula must involve a combination of the distance of camera to pixel, as well as the angle formed between the camera-to-pixel line and the line pointing straight out of the camera. But I might be totally off-base, because I'm not a mathematician by any means.&#xD;&#xA;&#xD;&#xA;Can anyone help me out or point me in the right direction?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N6QeI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14654" PostHistoryTypeId="1" PostId="5390" RevisionGUID="80117803-f63e-4f8d-97ea-e4855b7eefd4" CreationDate="2017-07-20T07:14:03.170" UserId="7023" Text="How to correct point cloud distortion" ContentLicense="CC BY-SA 3.0" />
  <row Id="14655" PostHistoryTypeId="3" PostId="5390" RevisionGUID="80117803-f63e-4f8d-97ea-e4855b7eefd4" CreationDate="2017-07-20T07:14:03.170" UserId="7023" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14656" PostHistoryTypeId="6" PostId="5390" RevisionGUID="82358250-964c-4f8f-8b1b-0bf6c48a2e51" CreationDate="2017-07-20T07:24:54.457" UserId="7023" Comment="edited tags" Text="|3d|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14657" PostHistoryTypeId="2" PostId="5391" RevisionGUID="95626dc7-c535-4d6f-88a6-9c2f449878aa" CreationDate="2017-07-20T08:34:24.757" UserId="4958" Text="This is rather general programming question but parallelizing for loop (most common usage) in c++ is easy with openMP library. Basic example for parallelizing outer loop:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #pragma omp parallel for schedule(static, 1) num_threads(omp_get_num_procs())&#xD;&#xA;    for (int i = 0; i &lt; size1; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int j = 0; j &lt; size2; ++j)&#xD;&#xA;        {&#xD;&#xA;            buffer[i*size1 + j] = ...&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But because of thread race situation below (incrementing array index) which would work in single thread wouldn't work in parallel:&#xD;&#xA;&#xD;&#xA;    int it = 0;&#xD;&#xA;    #pragma omp parallel for schedule(static, 1) num_threads(omp_get_num_procs())&#xD;&#xA;    for (int i = 0; i &lt; size1; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int j = 0; j &lt; size2; ++j)&#xD;&#xA;        {&#xD;&#xA;            buffer[it++] = ...&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Also thing to consider is using SIMD instructions (Single Instruction Multiple Data) which optimize multiple operations to single CPU instruction:&#xD;&#xA;&#xD;&#xA;    #pragma omp parallel for simd schedule(static,10) &#xD;&#xA;    for (i=0; i&lt;N; i++) &#xD;&#xA;    { &#xD;&#xA;        a[i] = b[i] * c[i]; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Some further info:&#xD;&#xA;&#xD;&#xA;http://bisqwit.iki.fi/story/howto/openmp/&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=Pc8DfEyAxzg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14658" PostHistoryTypeId="2" PostId="5392" RevisionGUID="be6e1745-3284-4810-ae3d-7c209d90f92e" CreationDate="2017-07-20T08:49:58.067" UserId="209" Text="It could be that you have to overcome a different bottleneck first.&#xD;&#xA;&#xD;&#xA;Have you ever read Jim Blinn's &quot;The Truth About Texture Mapping&quot; (I had a quick search to see if I could find a non-paywalled version but you may have better luck than me). Though this article is old and describes paging of texture data, it is just as relevant today.&#xD;&#xA;&#xD;&#xA;Essentially, if your textures are large (i.e. too large to fit in the cache), in scan order, and they have been rotated when displayed on the polygons, you are very likely to be thrashing your cache and, as memory is an order or two of magnitude slower than the CPU, this will hurt performance.&#xD;&#xA;&#xD;&#xA;To avoid the cache thrashing, textures are often stored in twiddled-order (that's what we called it in the early 90s but, more correctly, it'll be some variant of Morton order) or in a block order, which is what Blinn describes. This then makes texel/memory accesses far more coherent and the cache more effective." ContentLicense="CC BY-SA 3.0" />
  <row Id="14659" PostHistoryTypeId="5" PostId="5392" RevisionGUID="4f99398d-3e0c-445e-b01a-c77c846076f7" CreationDate="2017-07-20T08:59:19.550" UserId="209" Comment="added 87 characters in body" Text="It could be that you have to overcome a different bottleneck first.&#xD;&#xA;&#xD;&#xA;Have you ever read Jim Blinn's &quot;The Truth About Texture Mapping&quot; (I had a quick search to see if I could find a non-paywalled version but you may have better luck than me. Alternatively you might find a dead tree version of &quot;Jim Blinn's Corner&quot; in a library). Though this article is old and describes paging of texture data, it is just as relevant today.&#xD;&#xA;&#xD;&#xA;Essentially, if your textures are large (i.e. too large to fit in the cache), in scan order, and they have been rotated when displayed on the polygons, you are very likely to be thrashing your cache and, as memory is an order or two of magnitude slower than the CPU, this will hurt performance.&#xD;&#xA;&#xD;&#xA;To avoid the cache thrashing, textures are often stored in twiddled-order (that's what we called it in the early 90s but, more correctly, it'll be some variant of Morton order) or in a block order, which is what Blinn describes. This then makes texel/memory accesses far more coherent and the cache more effective." ContentLicense="CC BY-SA 3.0" />
  <row Id="14660" PostHistoryTypeId="5" PostId="5392" RevisionGUID="b389e7f0-6459-481a-b225-55c7823b7dfc" CreationDate="2017-07-20T13:20:29.260" UserId="209" Comment="added 1 character in body" Text="It could be that you have to overcome a different bottleneck first.&#xD;&#xA;&#xD;&#xA;Have you ever read Jim Blinn's &quot;The Truth About Texture Mapping&quot;? (I had a quick search to see if I could find a non-paywalled version but you may have better luck than me. Alternatively you might find a dead tree version of &quot;Jim Blinn's Corner&quot; in a library). Though this article is old and describes paging of texture data, it is just as relevant today.&#xD;&#xA;&#xD;&#xA;Essentially, if your textures are large (i.e. too large to fit in the cache), in scan order, and they have been rotated when displayed on the polygons, you are very likely to be thrashing your cache and, as memory is an order or two of magnitude slower than the CPU, this will hurt performance.&#xD;&#xA;&#xD;&#xA;To avoid the cache thrashing, textures are often stored in twiddled-order (that's what we called it in the early 90s but, more correctly, it'll be some variant of Morton order) or in a block order, which is what Blinn describes. This then makes texel/memory accesses far more coherent and the cache more effective." ContentLicense="CC BY-SA 3.0" />
  <row Id="14664" PostHistoryTypeId="5" PostId="5390" RevisionGUID="ee7cf555-fd67-4004-86c1-cc8246e4db93" CreationDate="2017-07-20T15:41:01.323" UserId="231" Comment="Remove thanks" Text="I am using Unreal Engine to export custom render passes for the scene depth in world units. Every pixel in the render pass has a value which is the distance from the camera to that pixel in standard UE4 units. For example, a pixel with a value of 500 (more precisely 500,500,500) would be 500cm away from the camera.&#xD;&#xA;&#xD;&#xA;I am then taking these render passes and trying to project them into point clouds inside Houdini. I have this all working, but I'm having trouble figuring out how to correct for the distortion that arises in the point cloud.&#xD;&#xA;&#xD;&#xA;In my attempt to understand this, I have created a box which is the same aspect ratio as my output (1920 x 1080) and positioned the camera in such a way that it fills the frame more or less exactly.&#xD;&#xA;&#xD;&#xA;Below is the point cloud, with a wireframe showing where the box was in Unreal Engine. After distortion correction, all those points should align with the face of box nearest the camera on the left. The centre pixels are in the correct place, but as you can see the further away from the centre the more offset they become from their true spatial location.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I understand that this distortion is arising because the render pass is essentially drawing a line from each pixel to the camera, so the further away from centre, the longer the line, giving the false impression of increased depth across what should be a flat plane.&#xD;&#xA;&#xD;&#xA;I have been doing a lot of experimenting with varying distances, sizes of boxes, focal lengths, and so on, trying to figure out what the formula is to correct this distortion, but I'm completely stuck.&#xD;&#xA;&#xD;&#xA;I feel like the formula must involve a combination of the distance of camera to pixel, as well as the angle formed between the camera-to-pixel line and the line pointing straight out of the camera. But I might be totally off-base, because I'm not a mathematician by any means.&#xD;&#xA;&#xD;&#xA;Can anyone help me out or point me in the right direction?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N6QeI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14665" PostHistoryTypeId="2" PostId="5394" RevisionGUID="63b797d3-c58e-4f96-b4f7-e9364362a35c" CreationDate="2017-07-20T18:10:29.333" UserId="7023" Text="I've figured a difference approach to projecting the point cloud inside Houdini.&#xA;&#xA;I had assumed that the 'Scene Depth World Units' would provide the depth of each pixel along a vector parallel with the camera vector, rather than angled to point at the camera as a single point.&#xA;&#xA;So rather than projecting the point cloud as if the depth was correct, and then trying to adjust for the distortion this creates, it makes more sense to just project the points in the same way they were created.&#xA;&#xA;So, knowing the position and rotation of the camera, I can then use the depth pass to project the points outwards from this location." ContentLicense="CC BY-SA 3.0" />
  <row Id="14667" PostHistoryTypeId="5" PostId="5392" RevisionGUID="59866508-93c0-4113-9434-05c36dcf8196" CreationDate="2017-07-21T08:45:34.500" UserId="209" Comment="minor improvements to text" Text="It could be that you have to overcome a different bottleneck first.&#xD;&#xA;&#xD;&#xA;Have you ever read Jim Blinn's &quot;The Truth About Texture Mapping&quot;? (I had a quick search to see if I could find a non-paywalled version but you may have better luck than me. Alternatively you might find a dead tree version of &quot;Jim Blinn's Corner&quot; in a library). Though this article is old and describes paging of texture data, it is still very relevant today.&#xD;&#xA;&#xD;&#xA;Essentially, if your textures are large (i.e. too large to fit in the cache), in scan order, and they have been rotated when displayed on the polygons, you are very likely to be thrashing your cache and, as memory is an order or two of magnitude slower than the CPU, this will hurt performance.&#xD;&#xA;&#xD;&#xA;To avoid the cache thrashing, textures are often stored in twiddled-order (that's what we called it in the early 90s but, more correctly, it'll be some variant of Morton order) or in a block order, which is what Blinn describes. This then makes texel/memory accesses far more coherent and the cache more effective." ContentLicense="CC BY-SA 3.0" />
  <row Id="14668" PostHistoryTypeId="2" PostId="5395" RevisionGUID="8e140ebb-45d3-4a50-97e3-04932e32ad9c" CreationDate="2017-07-21T09:29:20.313" UserId="7008" Text="I finally figured out a flaw in my argumentation to use the half vector for the diffuse part.&#xD;&#xA;&#xD;&#xA;**tl;dr version:**&#xD;&#xA;==================&#xD;&#xA;&#xD;&#xA;alpha_hi and alpha_ho are not equal, this assumption only works for the specular part. Therefore the energyconservation is not given.&#xD;&#xA;&#xD;&#xA;*More correct: Per definition alpha_hi = alpha_ho, but you are not allowed to use them in the equation, you need to use the microfacet normals instead of the half vectors. The microfacet normal and the half vector are however not generally equal.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;long version:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffuse BRDF (like the specular one) is an integration over all possible microfacet normals. The generalized BRDF form is:&#xD;&#xA;&#xD;&#xA;**(1)**&#xD;&#xA;&#xD;&#xA;    f = int_Omega rho_m * D * G * cos(alpha_hi) * cos(alpha_ho) / (cos(theta_i) * cos(theta_o))&#xD;&#xA;&#xD;&#xA;where rho_m is the behaviour of light when it reaches a microfacet, D is the normal distribution function, G is the geometry function and the rest is normalization [PBR, p.16-25][HEI, p.61f.]&#xD;&#xA;&#xD;&#xA;Now for the specular BRDF, the behaviour is perfect reflection. This means, only microfacets where the microfacet normal omega_m equals the half vector omega_h between light (omega_i) and view (omega_o) direction reflect light from the light direction to the view direction. Mathematically, this translates to a Dirac Delta function delta(omega_h). The amount of light reflected is determined by Fresnel F. With accounting for integration domain changes[PBR, p.31-41], this leads to (rho_m,s being the specular specific reaction of microfacets for the specular part):&#xD;&#xA;&#xD;&#xA;**(2)**&#xD;&#xA;&#xD;&#xA;    rho_m,s = delta(omega_h) * F / (4*alpha_hi*alpha_ho)&#xD;&#xA;&#xD;&#xA;Plug this into **(1)** and you integrate over any omega_m, but the dirac delta function makes you ignore anything where omega_m != omega_h. This is the nice thing about those dirac delta functions, the &quot;cancel&quot; the integral. Therefore, you come to the known well known BRDF [PBR, p.43]&#xD;&#xA;&#xD;&#xA;**(3)**&#xD;&#xA;&#xD;&#xA;    f_s = F * D * G / (4 * cos(theta_i) * cos(theta_o))&#xD;&#xA;&#xD;&#xA;and here you can savely assume alpha_hi = alpha_ho. The Fresnel part makes this one side of a linear interpolation (seeing as this is the ratio of light being specularly reflected).&#xD;&#xA;&#xD;&#xA;On the other side though, you still have an integral and you can't &quot;cancel&quot; it with anything. Let theta_mi be the angle between the microfacet normal and the light dir, theta_mo between the microfacet normal and the view dir (as opposed to alpha_hi and alpha_ho, which specifically are defined for the half angle!).That means 2 important things:&#xD;&#xA;&#xD;&#xA;**(4)**&#xD;&#xA;&#xD;&#xA;    theta_mi != alpha_hi = alpha_h = alpha_ho != theta_mo FORALL omega_m != omega_h&#xD;&#xA;&#xD;&#xA;and rho_m,d (as the diffuse reaction of light when reaching microfacets) is depended upon Fresnel, it can only use non reflected parts, but you cannot just assume EVERY microfacet normal diffusley reflects all the light that was not specularly reflected (i.e. (1-F(alpha_h)).&#xD;&#xA;&#xD;&#xA;So the problem now is, you have one side of that linear interpolation being the analytically solvable specular BRDF without an integral. On the other side, you have the interpolation factor within the integral, and thus you would use it for any microfacet normal. This is not energy conserving anymore, if you model rho_m,d with a lambertian term. &#xD;&#xA;&#xD;&#xA;If you manage to pull the 1-F part out of the integral, then and only then can you use the half vector for both specular and diffuse BRDFs, otherwise you need to handle it differently.&#xD;&#xA;&#xD;&#xA;If you still want to use the half vector for the &quot;Fresnelinterpolation&quot;, then you need to normalize.&#xD;&#xA;&#xD;&#xA;    f = F(alpha_h) * rest_spec + (1-F(alpha_h)) * rest_diff * k&#xD;&#xA;&#xD;&#xA;With k being chosen, such that&#xD;&#xA;&#xD;&#xA;    rest_diff * k = 1&#xD;&#xA;&#xD;&#xA;Note that rest_diff still includes an integral over all possible microfacet normals.&#xD;&#xA;&#xD;&#xA;Using theta_i and theta_o&#xD;&#xA;-------------------------&#xD;&#xA;I guess I should add a sentence about the actually used angles, because the question I originally posed was not just &quot;why not alpha_h&quot; but also &quot;why theta_i and theta_o&quot;. So for the poeple wondering if this is correct: No. It is just an approximation.&#xD;&#xA;&#xD;&#xA;&gt; Instead, we can modify the matte term to be a simple approximation that captures the important qualitative angular behavior[...].&#xD;&#xA;&gt; &#xD;&#xA;&gt; [SHI, p.46]&#xD;&#xA;&#xD;&#xA;Discussion on why this is so hard to figure out&#xD;&#xA;-----------------------------------------------&#xD;&#xA;&#xD;&#xA;Now [DIS, p.14] and [PBR, p.100,184] quoted [SHI] and [ASH] on this, where [ASH] uses [SHI], so it boils down to the model of the latter. And seeing as [DIS] and [PBR] are non-scientific (though pretty well thought through) publications, I can't fault them too much, but really, a better way of quoting papers or an extra explanation might have helped and saved me about 2 weeks of thinking, reading and almost starting a paper on why everybody is (supposedly) wrong. &#xD;&#xA;&#xD;&#xA;Furthermore, neither of them really explains their diffuse approximations, [PBR, p.193] just mentions trying different functions until he saw one he liked.&#xD;&#xA;&#xD;&#xA;Additionally, [SHI, p.46] actually quoted [SCH, p.10f.] who used the linear interpolation between F(alpha_h) and 1-F(alpha_h). However, [SHI, p.46] quoted him incorrectly, they said he used F(theta_i) and 1-F(alpha_h). Assuming this, they are of course right in thinking [SCH] is not energy conserving, but this lead me to believe that F(alpha_h) and 1-F(alpha_h) would be. Their mistake might've come from them using F(theta_i) themselves, I can't say.&#xD;&#xA;&#xD;&#xA;Literature&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA; - [ASH] An anisotropic phong BRDF model, in Journal of Graphics Tools Vol. 5, No. 2, Michael Ashikhmin and Peter Shirley, 2000&#xD;&#xA; - [SCH] An Inexpsensive BRDF Model for Physically-based Rendering, in Computer Graphics Forum Vol. 13, No. 3, Christophe Schlick, 1994&#xD;&#xA; - [SHI] A Practitioners' Assessment of Light Reflection Models, in The Fifth Pacific Conference on Computer Graphics and Applications, 1997. Proceedings, Peter Shirley,  Helen Hu, Brian Smits and Eric Lafortune, 1997&#xD;&#xA; - [DIS] Physically-Based Shading at Disney, at SIGGRAPH 2012 Course: Physically Based Shading in Film and Game Production, Brent Burley, 2012&#xD;&#xA; - [HEI] Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, in Journal of Computer Graphics Techniques Vol. 3, No. 2, Eric Heitz, 2014&#xD;&#xA; - [PBR] PBR Diffuse Lighting for GGX+Smith Microsurfaces, at GDC2017, Earl Hammon Jr., 2017&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14669" PostHistoryTypeId="2" PostId="5396" RevisionGUID="36644de0-97af-4c92-ac5b-e64f9051602f" CreationDate="2017-07-21T10:21:28.957" UserId="1937" Text="I've been writing some custom shaders based around Unity's Standard BRDF, which is uses GGX distribution term and Smith visibility term. It looks great at either end of the smoothness scale (1 and 2 in the pic below). However, with the smoothness set to about 50%, things start to get a little ugly (3). Increasing the metalness makes it worse (4), and strongly coloured specular gets worse still, as different colour channels blow out at different rates(5).&#xD;&#xA;&#xD;&#xA;[![BRDFs][1]][1]&#xD;&#xA;&#xD;&#xA;This seems to be caused by specular term returning &gt;1 around the highlights, probably caused by Unity's hack of multiplying specular by pi (instead of dividing diffuse) as shown in the code snippet below.&#xD;&#xA;&#xD;&#xA;    // Specular term&#xD;&#xA;    // HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!&#xD;&#xA;    // BUT 1) that will make shader look significantly darker than Legacy ones&#xD;&#xA;    // and 2) on engine side &quot;Non-important&quot; lights have to be divided by Pi too in cases when they are injected into ambient SH&#xD;&#xA;    half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);&#xD;&#xA;    half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);&#xD;&#xA;    half D = GGXTerm (nh, roughness);&#xD;&#xA;    half specularTerm = V*D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later&#xD;&#xA;&#xD;&#xA;HDR rendering helps a lot, but unfortunately our project is on mobile and using LDR. I'm making a car paint shader with a clear coat, so the base coat will likely be semi-rough and semi-metallic in a lot of cases which seems to be a worst-case-scenario for this BRDF. Can anyone suggest a way to get saner specular highlights? Either some kind of rolloff for out-of-range specular values, or a different BRDF altogether?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/meanS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14670" PostHistoryTypeId="1" PostId="5396" RevisionGUID="36644de0-97af-4c92-ac5b-e64f9051602f" CreationDate="2017-07-21T10:21:28.957" UserId="1937" Text="Dealing with blown-out highlights in PBR" ContentLicense="CC BY-SA 3.0" />
  <row Id="14671" PostHistoryTypeId="3" PostId="5396" RevisionGUID="36644de0-97af-4c92-ac5b-e64f9051602f" CreationDate="2017-07-21T10:21:28.957" UserId="1937" Text="|brdf|pbr|unity|ggx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14672" PostHistoryTypeId="33" PostId="5377" RevisionGUID="113abeee-68d1-443f-b84c-ae4256513c0c" CreationDate="2017-07-21T10:38:37.857" UserId="7014" Comment="30" />
  <row Id="14674" PostHistoryTypeId="2" PostId="5397" RevisionGUID="18592a18-4472-4df9-b43c-e94d42d56855" CreationDate="2017-07-21T13:26:47.583" UserId="7029" Text="I've been following a guide to learn OpenGL, and I'm now learning how to do post-processing.&#xD;&#xA;In particular, I'm trying to apply a blur to my rendering through the following kernel:&#xD;&#xA;&#xD;&#xA;$\frac{\begin{bmatrix}1&amp;2&amp;1\\2&amp;4&amp;2\\1&amp;2&amp;1\end{bmatrix}}{16}$&#xD;&#xA;&#xD;&#xA;The problem I'm encountering is that whenever I try to access a float array's member through the `[]` operator giving it an int variable as parameter, it returns `0.0`.&#xD;&#xA;Here's my fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 410 core&#xD;&#xA;    in vec2 txcoords;  // Texture coordinates&#xD;&#xA;    out vec4 color;&#xD;&#xA;    uniform sampler2D tx;&#xD;&#xA;    &#xD;&#xA;    const float offset = 1.0 / 300.0;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;    	vec2 offsets[9] = vec2[](&#xD;&#xA;    		vec2(-offset,	 offset),&#xD;&#xA;    		vec2( 0.0,		 offset),&#xD;&#xA;    		vec2( offset, 	 offset),&#xD;&#xA;    		vec2(-offset, 	 0.0),&#xD;&#xA;    		vec2( 0.0, 		 0.0),&#xD;&#xA;    		vec2( offset, 	 0.0),&#xD;&#xA;    		vec2(-offset,	-offset),&#xD;&#xA;    		vec2( 0.0,		-offset),&#xD;&#xA;    		vec2( offset,	-offset)&#xD;&#xA;    	);&#xD;&#xA;    &#xD;&#xA;    	const float kernel[9] = float[9](&#xD;&#xA;    		1.0 / 16, 2.0 / 16, 1.0 / 16,&#xD;&#xA;        	2.0 / 16, 4.0 / 16, 2.0 / 16,&#xD;&#xA;        	1.0 / 16, 2.0 / 16, 1.0 / 16&#xD;&#xA;    	);&#xD;&#xA;    &#xD;&#xA;    	vec3 sampleTex[9];&#xD;&#xA;    	vec3 final = vec3(0.0);&#xD;&#xA;    	for (int i = 0; i &lt; 9; i++) {&#xD;&#xA;    		sampleTex[i] = vec3(texture(tx, txcoords.st + offsets[i]));&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;    	for (int i = 0; i &lt; 9; i++) {&#xD;&#xA;    		final += sampleTex[i] * kernel[i];&#xD;&#xA;    	}&#xD;&#xA;    	color = vec4(final, 1.0);&#xD;&#xA;    }&#xD;&#xA;This code doesn't work(whole screen renders black), but if I change it to&#xD;&#xA;&#xD;&#xA;    final += sampleTex[i] * kernel[0];&#xD;&#xA;then my scene is rendered correctly, but, of course, without any blur, just a bit darker than normal.&#xD;&#xA;It also doesn't just work with `kernel[0]`, but with any number (`[1]`, `[2]`, etc.)&#xD;&#xA;&#xD;&#xA;If instead I change it to &#xD;&#xA;&#xD;&#xA;    final += sampleTex[i] * (kernel[i] + 0.05);&#xD;&#xA;then it renders exactly the same as with&#xD;&#xA;&#xD;&#xA;    final += sampleTex[i] * 0.05;&#xD;&#xA;&#xD;&#xA;And that's why I ended up suspecting that it's the `[i]` part that just won't work, for whatever reason.&#xD;&#xA;&#xD;&#xA;Does anyone have any idea as to why this is happening? I also tried with different shader versions (330, 400, etc.) but they all give the same result.&#xD;&#xA;&#xD;&#xA;Thanks for your time!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14675" PostHistoryTypeId="1" PostId="5397" RevisionGUID="18592a18-4472-4df9-b43c-e94d42d56855" CreationDate="2017-07-21T13:26:47.583" UserId="7029" Text="GLSL broken access operator" ContentLicense="CC BY-SA 3.0" />
  <row Id="14676" PostHistoryTypeId="3" PostId="5397" RevisionGUID="18592a18-4472-4df9-b43c-e94d42d56855" CreationDate="2017-07-21T13:26:47.583" UserId="7029" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14677" PostHistoryTypeId="2" PostId="5398" RevisionGUID="0009e390-d3ea-4ccf-823d-bd711524e9c6" CreationDate="2017-07-21T16:32:09.867" UserId="2096" Text="I have been learning about projection matrix in OpenGL and I am finding it really hard to understand. All I know is that there are other configurations in the projection matrix besides placing z in w for perspective projection. What are those other numbers and why are they there? &#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="14678" PostHistoryTypeId="1" PostId="5398" RevisionGUID="0009e390-d3ea-4ccf-823d-bd711524e9c6" CreationDate="2017-07-21T16:32:09.867" UserId="2096" Text="Is placing z value of vertex in w enough to achieve perspective projection in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14679" PostHistoryTypeId="3" PostId="5398" RevisionGUID="0009e390-d3ea-4ccf-823d-bd711524e9c6" CreationDate="2017-07-21T16:32:09.867" UserId="2096" Text="|opengl|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14680" PostHistoryTypeId="2" PostId="5399" RevisionGUID="8d56ae79-7c25-4e84-9d6f-69f358130e9d" CreationDate="2017-07-21T21:36:59.797" UserId="4546" Text="Using physically based BRDFs only makes sense if your entire pipeline is built for physical units - the extreme range of values can't be displayed properly without some form of tone mapping. You didn't include that part of the code but from the looks of it I'd say you're doing a simple clamp() followed by linear-&gt;sRGB conversion, which causes the bad highlights.&#xD;&#xA;&#xD;&#xA;Since you're not ready to run your entire frame in HDR, you could apply something simple like a sigmoid operator to just the specular component. This may look a bit off next to other BRDFs but should make those highlights much more pleasant." ContentLicense="CC BY-SA 3.0" />
  <row Id="14681" PostHistoryTypeId="2" PostId="5400" RevisionGUID="da0ac158-fa74-4ed9-84f2-aa896a113c47" CreationDate="2017-07-22T06:28:00.507" UserId="1937" Text="The projection matrix distorts the view frustum (the volume the camera can see) into a unit cube. So everything with all coordinates in the range -1 to 1 after projection is potentially visible, and everything else can be clipped.&#xD;&#xA;&#xD;&#xA;To make things further away look smaller, we need to divide by their Z distance. We can't put this value directly into the matrix since it is different for each point we want to project, so instead we place each point's Z into its projected W, giving (X, Y ,Z ,1) -&gt; (X', Y', Z', Z), known as clip coordinates. This is then divided by the new W to give (X'/Z, Y'/Z, Z'/Z, 1),  known as normalized device coordinates. On the GPU this division happens automatically after the vertex shader and before clipping and rasterization.&#xD;&#xA;&#xD;&#xA;The general form of a projection matrix is&#xD;&#xA;&#xD;&#xA;    A 0 0 0&#xD;&#xA;    0 B 0 0&#xD;&#xA;    0 0 C D&#xD;&#xA;    0 0 1 0&#xD;&#xA;&#xD;&#xA;The A and B terms relate to the field of view, higher values give a narrower view. Specifically, B is the cotangent of half the vertical view angle, and A is B/aspect ratio.&#xD;&#xA;&#xD;&#xA;The C and D terms are bias and scale terms which map the near plane to -1 (0 in DirectX), and the far plane to 1. These are used for writes to the depth buffer to determine which objects occlude others. The depth mapping is actually a function of 1/Z, rather than Z, since this gives better precision close to the near plane, and allows perspective-correct interpolation.&#xD;&#xA;&#xD;&#xA;Also note that in OpenGL, W' is -Z rather than Z, since we are using a right-handed coordinate system, with negative Z pointing into the screen.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14688" PostHistoryTypeId="2" PostId="5402" RevisionGUID="110747b6-8d6a-4c5e-b759-89ac8ee12b0c" CreationDate="2017-07-23T01:44:58.527" UserId="7000" Text="I have a very simple OpenGL program where the positions are embedded in the GLSL code. The vertex shader looks like this:&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    uniform float offsetX;&#xD;&#xA;    uniform float offsetY;&#xD;&#xA;&#xD;&#xA;    out VS_OUT&#xD;&#xA;    {&#xD;&#xA;      vec2 tc;&#xD;&#xA;    } vs_out;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;      const vec2[4] position = vec2[4](vec2(-0.5, -0.5),&#xD;&#xA;                                       vec2(0.5, -0.5),&#xD;&#xA;                                       vec2(-0.5, 0.5),&#xD;&#xA;                                       vec2(0.5, 0.5));&#xD;&#xA;    &#xD;&#xA;      vs_out.tc = position[gl_VertexID].xy + vec2(0.5);&#xD;&#xA;      vec2 pos = position[gl_VertexID].xy + vec2(offsetX, offsetY);&#xD;&#xA;      gl_Position = vec4(pos, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To run this, to me it seems like I should basically be able to just be able to call `glDrawArrays` from my application.&#xD;&#xA;&#xD;&#xA;However, this is not the case. I my application I have the following code (reused from an earlier example):&#xD;&#xA;&#xD;&#xA;	// Create buffer&#xD;&#xA;	glCreateBuffers(1, &amp;buffer);&#xD;&#xA;	glNamedBufferStorage(buffer, sizeof(vertices), vertices, bufferFlags);&#xD;&#xA;&#xD;&#xA;	// Create vao&#xD;&#xA;	glCreateVertexArrays(1, &amp;vao);&#xD;&#xA;&#xD;&#xA;	// Enable attributes&#xD;&#xA;	glEnableVertexArrayAttrib(vao, positionIndex);&#xD;&#xA;	glEnableVertexArrayAttrib(vao, texCoordIndex);&#xD;&#xA;&#xD;&#xA;	// Set up formats for attributes&#xD;&#xA;	glVertexArrayAttribFormat(vao, positionIndex, positionSize, GL_FLOAT, GL_FALSE, firstElementOffset);&#xD;&#xA;	glVertexArrayAttribFormat(vao, texCoordIndex, texCoordSize, GL_FLOAT, GL_FALSE, positionSize * sizeof(GLfloat));&#xD;&#xA;&#xD;&#xA;	// Make attributes use binding 0&#xD;&#xA;	glVertexArrayAttribBinding(vao, positionIndex, bufferBindingIndex);&#xD;&#xA;	glVertexArrayAttribBinding(vao, texCoordIndex, bufferBindingIndex);&#xD;&#xA;&#xD;&#xA;	// Bind &quot;buffer&quot; to vertex buffer binding point 0&#xD;&#xA;	glVertexArrayVertexBuffer(vao, bufferBindingIndex, buffer, firstElementOffset, elementStride);&#xD;&#xA;&#xD;&#xA;None of that actually seems necessary because my shaders are now responsible for generating the position and texture coordinates.  However, if I comment out the call to `glVertexArrayVertexBuffer` my program crashes.&#xD;&#xA;&#xD;&#xA;Am I required to have a buffer bound to binding point 0 (even if I do not use any of that buffer's data) before calling `glDraw*`?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14689" PostHistoryTypeId="1" PostId="5402" RevisionGUID="110747b6-8d6a-4c5e-b759-89ac8ee12b0c" CreationDate="2017-07-23T01:44:58.527" UserId="7000" Text="Do I have to have a buffer bound before making a draw call?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14690" PostHistoryTypeId="3" PostId="5402" RevisionGUID="110747b6-8d6a-4c5e-b759-89ac8ee12b0c" CreationDate="2017-07-23T01:44:58.527" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14691" PostHistoryTypeId="50" PostId="5280" RevisionGUID="5e2b26ef-1230-46d7-87ff-a1d96c28c558" CreationDate="2017-07-23T09:55:14.110" UserId="-1" />
  <row Id="14692" PostHistoryTypeId="2" PostId="5403" RevisionGUID="c1e9f71b-51a4-4432-9e11-870b0c6776e6" CreationDate="2017-07-23T14:24:18.913" UserId="2654" Text="There is nothing in the OpenGL specification that requires you to have enabled attribute arrays in the bound VAO when you render. All of the user-defined vertex attributes will have undefined values, but since you're not reading any of them, that won't be a problem.&#xD;&#xA;&#xD;&#xA;What *may* be a problem is driver bugs. Rendering with an empty VAO is not exactly the most common thing in the world, so it's possible that some drivers won't do the right thing. But the implementation *should* allow this.&#xD;&#xA;&#xD;&#xA;&gt;  However, if I comment out the call to `glVertexArrayVertexBuffer` my program crashes.&#xD;&#xA;&#xD;&#xA;Of course it does. You have to not *enable* the attribute array as well. If you have a vertex attribute enabled, it has to come from somewhere. So there must be a buffer behind it. If you don't want to put a buffer there, then you can't have an attribute array source its data from that buffer.&#xD;&#xA;&#xD;&#xA;So while you are not required to have enabled attribute arrays, if you have enabled an array, you are required to provide a buffer for it. If you don't want to use vertex attributes, you have to not use vertex attributes." ContentLicense="CC BY-SA 3.0" />
  <row Id="14693" PostHistoryTypeId="2" PostId="5404" RevisionGUID="35a17faf-ee5e-4623-b444-8fd66217cc41" CreationDate="2017-07-23T19:15:23.890" UserId="7039" Text="I would like to return the XY coordinates of vertex C using math formula. &#xD;&#xA;I have 5 input data what I always know and can be used for solution (green in the image): I know X; Y; coordinates of point A and point B (Ax, Ay, Bx, By), and I know the length of all three sides of triangle (AB, AC, AD). Please help how to get the values of X Y coordinate of point C, what is 70/30 in the example, but I have no formula to get back them.&#xD;&#xA;&#xD;&#xA;[![Example situation to get coordinates with input values][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q6WGF.jpg&#xD;&#xA;&#xD;&#xA;I know that more than one solution of this formula, but:&#xD;&#xA;&#xD;&#xA;- Coordinates cannot be in negative areas. All coordinates must be positive.&#xD;&#xA;- I always use 1 direction for vertex labelling, but because I always know the length of AC and BC, I think to change the label from A to B will not change the position of C.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14694" PostHistoryTypeId="1" PostId="5404" RevisionGUID="35a17faf-ee5e-4623-b444-8fd66217cc41" CreationDate="2017-07-23T19:15:23.890" UserId="7039" Text="Return x; y; coordinates of vertex C of triangle" ContentLicense="CC BY-SA 3.0" />
  <row Id="14695" PostHistoryTypeId="3" PostId="5404" RevisionGUID="35a17faf-ee5e-4623-b444-8fd66217cc41" CreationDate="2017-07-23T19:15:23.890" UserId="7039" Text="|triangulation|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14700" PostHistoryTypeId="10" PostId="5363" RevisionGUID="93009148-e1d1-409d-954a-e1e152b36691" CreationDate="2017-07-24T02:02:37.330" UserId="231" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="14701" PostHistoryTypeId="2" PostId="5406" RevisionGUID="643fb494-eebc-438f-b20b-49acee1d2a28" CreationDate="2017-07-24T09:23:50.647" UserId="7008" Text="You can get the coordinates of C by using circle equations for one circle C_A with point A as center and AC as its radius and one circle C_B with point B as its center and BC as its radius.&#xD;&#xA;&#xD;&#xA;Now you can calculate their intersection points, which leaves you with 2 points (iff C is not on a line between A and B).&#xD;&#xA;&#xD;&#xA;I am not entirely sure how you want to determine which of the two candidates C_1 and C_2 is the correct one. If I understand correctly, you always label the triangle counterclockwise. There is a [neat way][1] to check this, so you should have everything to find your point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order" ContentLicense="CC BY-SA 3.0" />
  <row Id="14703" PostHistoryTypeId="2" PostId="5408" RevisionGUID="3f9d1439-c8b3-4fcc-86f0-24f7e35e70b7" CreationDate="2017-07-24T13:19:43.587" UserId="6785" Text="I'm launching OpenGL from a VBA module linked to an Excel spreadsheet which goes quasi-dormant (the quasi will become clear in a moment) once I enter glutMainLoop. I would like to be able to edit the Excel spreadsheet and observe corresponding changes in the OpenGL simulation. In this context,  I have two issues:&#xD;&#xA;&#xD;&#xA;Issue 1 (as John McLaughlin used to bark on PBS's CrossFire!): Currently, **once within glutMainLoop**, I can only make changes to Excel cells that have pulldown menus, but not cells that require keyboard input. I believe that this issue may be related to the lack of a multi-threading ability either withing glut or VBA (this is WAY above my Mech E pay grade). I'd like to know however, if there's a workaround. &#xD;&#xA;&#xD;&#xA;Issue 2: When I make changes to the Excel cells with pulldown menus, the OpenGL window gets minimised, unless I move it to a second screen or outside the Excel window which is not convenient. I understand that this is typical Windows behaviour, but at the very least, is there an openGL command to maximise it again after the changes to the Excel spreadsheet, **from within glutMainLoop**? &#xD;&#xA;&#xD;&#xA;Thanks in advance. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14704" PostHistoryTypeId="1" PostId="5408" RevisionGUID="3f9d1439-c8b3-4fcc-86f0-24f7e35e70b7" CreationDate="2017-07-24T13:19:43.587" UserId="6785" Text="Manipulating simulation within glutMainLoop from an Excel spreadsheet" ContentLicense="CC BY-SA 3.0" />
  <row Id="14705" PostHistoryTypeId="3" PostId="5408" RevisionGUID="3f9d1439-c8b3-4fcc-86f0-24f7e35e70b7" CreationDate="2017-07-24T13:19:43.587" UserId="6785" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14706" PostHistoryTypeId="5" PostId="5408" RevisionGUID="d8f8d691-3e6b-468a-a4d7-923fffba9f8e" CreationDate="2017-07-24T13:25:10.457" UserId="6785" Comment="deleted 3 characters in body" Text="I'm launching OpenGL from a VBA module linked to an Excel spreadsheet which goes quasi-dormant (the quasi will become clear in a moment) once I enter glutMainLoop. I would like to be able to edit the Excel spreadsheet and observe corresponding changes in the OpenGL simulation. In this context,  I have two issues:&#xD;&#xA;&#xD;&#xA;Issue 1 (as John McLaughlin used to bark on his PBS show!): Currently, **once within glutMainLoop**, I can only make changes to Excel cells that have pulldown menus, but not cells that require keyboard input. I believe that this issue may be related to the lack of a multi-threading ability either withing glut or VBA (this is WAY above my Mech E pay grade). I'd like to know however, if there's a workaround. &#xD;&#xA;&#xD;&#xA;Issue 2: When I make changes to the Excel cells with pulldown menus, the OpenGL window gets minimised, unless I move it to a second screen or outside the Excel window which is not convenient. I understand that this is typical Windows behaviour, but at the very least, is there an openGL command to maximise it again after the changes to the Excel spreadsheet, **from within glutMainLoop**? &#xD;&#xA;&#xD;&#xA;I'd like to emphasise that Issue 1 above - the lack of ability to edit Excel cells requiring keyboard input once within glutMainLoop - is far more important. &#xD;&#xA;&#xD;&#xA;Thanks in advance. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14707" PostHistoryTypeId="5" PostId="5408" RevisionGUID="51024554-d52b-41ba-bbce-a0b96b699b48" CreationDate="2017-07-24T13:42:31.313" UserId="6785" Comment="added 171 characters in body" Text="I'm launching OpenGL from a VBA module linked to an Excel spreadsheet which goes quasi-dormant (the quasi will become clear in a moment) once I enter glutMainLoop. I would like to be able to edit the Excel spreadsheet and observe corresponding changes in the OpenGL simulation. In this context,  I have two issues:&#xD;&#xA;&#xD;&#xA;Issue 1 (as John McLaughlin used to bark on his PBS show!): Currently, **once within glutMainLoop**, I can only make changes to Excel cells that have pulldown menus, but not cells that require keyboard input. I believe that this issue may be related to the lack of a multi-threading ability either withing glut or VBA (this is WAY above my Mech E pay grade). I'd like to know however, if there's a workaround. &#xD;&#xA;&#xD;&#xA;Issue 2: When I make changes to the Excel cells with pulldown menus, the OpenGL window gets minimised, unless I move it to a second screen or outside the Excel window which is not convenient. I understand that this is typical Windows behaviour, but at the very least, is there an openGL command to maximise it again after the changes to the Excel spreadsheet, **from within glutMainLoop**? &#xD;&#xA;&#xD;&#xA;I'd like to emphasise that Issue 1 above - the lack of ability to edit Excel cells requiring keyboard input once within glutMainLoop - is far more important. &#xD;&#xA;&#xD;&#xA;Thanks in advance. I've added an image below that (hopefully!) describes what I'm trying to accomplish.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;  [1]: https://i.stack.imgur.com/IpzMc.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14709" PostHistoryTypeId="2" PostId="5409" RevisionGUID="93eb42ee-8bc2-4df5-ab89-137240f7076f" CreationDate="2017-07-24T15:58:52.647" UserId="6041" Text="I am trying to implement Beer's law according to [this][1] page in dielectric material but I am not sure have done it correctly as the image does not suggest so.&#xD;&#xA;&#xD;&#xA;The formula is: I(s) = I(0) * pow(e, ln(A)*s)&#xD;&#xA;&#xD;&#xA;'A' is said to be transmission coefficient which I am not clear what this is&#xD;&#xA;and what value I should use for it.&#xD;&#xA;&#xD;&#xA;Below is the code and the image. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Could anyone shed some light if I have gone wrong. Thanks.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;            public override LightVector SampleBrdf(ISect isect, Random rand, &#xD;&#xA;                   out LightVector woW, out double pdfDir, out double cosWo)&#xD;&#xA;            { &#xD;&#xA;                woW = LightVector.ZERO;&#xD;&#xA;                cosWo = 0;&#xD;&#xA;                LightVector n = isect.Thing.Normal;&#xD;&#xA;                LightVector tan = isect.Thing.Edge1;&#xD;&#xA;                tan.Normalize();&#xD;&#xA;                LightVector ts = n.Cross(tan);&#xD;&#xA;            &#xD;&#xA;                //set wo to be incoming dir&#xD;&#xA;                LightVector wo = MaterialHelper.WorldToLocal(-isect.Ray.Dir, tan, ts, n);dir&#xD;&#xA;                LightVector refracted = LightVector.ZERO;&#xD;&#xA;                LightVector reflected = new LightVector(-wo.X, -wo.Y, wo.Z);&#xD;&#xA;    &#xD;&#xA;                double F = Fresnel.Evaluate(rindex1, rindex2, MaterialHelper.CosTheta(wo));&#xD;&#xA;                pdfDir = F;&#xD;&#xA;    &#xD;&#xA;                //Figure out which eta is incident and which is transmitted&#xD;&#xA;                double extCoeff = 1;&#xD;&#xA;                double etaI = rindex1;&#xD;&#xA;                double etaT = rindex2;&#xD;&#xA;                LightVector z = new LightVector(0, 0, 1);&#xD;&#xA;                if (MaterialHelper.CosTheta(wo) &lt; 0)//existing&#xD;&#xA;                {&#xD;&#xA;                    etaI = rindex2;&#xD;&#xA;                    etaT = rindex1;&#xD;&#xA;                    z = -z;&#xD;&#xA;                    extCoeff = Math.Exp(-Math.Log(A, Math.E) * isect.Dist);&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                //Compute ray direction for specular transmission&#xD;&#xA;                if (!MaterialHelper.Refract(wo, z, etaI / etaT, out refracted))&#xD;&#xA;                    pdfDir = 1;&#xD;&#xA;    &#xD;&#xA;                if (rand.NextDouble() &lt; pdfDir)&#xD;&#xA;                {&#xD;&#xA;                    woW = MaterialHelper.LocalToWorld(reflected, tan, ts, n);&#xD;&#xA;                    cosWo = MaterialHelper.AbsCosTheta(reflected);&#xD;&#xA;    &#xD;&#xA;                    return R * (F / cosWo);&#xD;&#xA;                }&#xD;&#xA;                else //refracted&#xD;&#xA;                {&#xD;&#xA;                    woW = MaterialHelper.LocalToWorld(refracted, tan, ts, n);&#xD;&#xA;                    cosWo = MaterialHelper.AbsCosTheta(refracted);&#xD;&#xA;                    pdfDir = 1d - F;&#xD;&#xA;    &#xD;&#xA;                    return T * (extCoeff * (1d - F) / cosWo);&#xD;&#xA;                }&#xD;&#xA;            } &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.eng.utah.edu/~cs6620/beers.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/4jgjp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14710" PostHistoryTypeId="1" PostId="5409" RevisionGUID="93eb42ee-8bc2-4df5-ab89-137240f7076f" CreationDate="2017-07-24T15:58:52.647" UserId="6041" Text="Beer's law in dielectric material" ContentLicense="CC BY-SA 3.0" />
  <row Id="14711" PostHistoryTypeId="3" PostId="5409" RevisionGUID="93eb42ee-8bc2-4df5-ab89-137240f7076f" CreationDate="2017-07-24T15:58:52.647" UserId="6041" Text="|pathtracing|global-illumination|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14718" PostHistoryTypeId="2" PostId="5411" RevisionGUID="6b70b9e9-f497-4cad-9f56-c42cba7247e5" CreationDate="2017-07-26T08:03:52.067" UserId="213" Text="I am working on a normal mapping.I need to have ability to scale normal vector to adjust normal strength of the surface.Currently, the way I am doing it, basically shows plausible results. But I am still not sure that's the 100% correct and to my surprise I found no info in the web regarding this subject.&#xD;&#xA;So here is how I do that (my lightning is in camera space):&#xD;&#xA;&#xD;&#xA;**vertex shader:**&#xD;&#xA;&#xD;&#xA;    vec3 N = normalize(normalMatrix * a_normal); &#xD;&#xA;    vec3 T = normalize(normalMatrix * a_tangent.xyz) * nStrength;          &#xD;&#xA;    vec3 B = normalize(normalMatrix * (cross(a_normal, a_tangent.xyz) * a_tangent.w) ) * nStrength; &#xD;&#xA;&#xD;&#xA;    v_TBN =  mat3(T,B,N);&#xD;&#xA;&#xD;&#xA;normalMatrix - inverse-transpose of model-view matrix.&#xD;&#xA;&#xD;&#xA;The shading itself happens in the fragment shader.&#xD;&#xA;The only relevant part which is happening there is transforming normal from&#xD;&#xA;the texture with v_TBN varying:&#xD;&#xA;&#xD;&#xA; **Fragment shader:**   &#xD;&#xA;&#xD;&#xA;     vec3 GetNormal(){&#xD;&#xA;        vec3 n = texture(normalMap,uv).xyz;&#xD;&#xA;        n = normalize(n * 2.0 - 1.0);&#xD;&#xA;        return  normalize (v_TBN * n);&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;  So, as you can see, I scale tangent and bi-tangent vectors with nStrength scalar.That's the most optimal setup I figured out that gives most correct looking effect.Is this the right way of strengthen the normals?                 " ContentLicense="CC BY-SA 3.0" />
  <row Id="14719" PostHistoryTypeId="1" PostId="5411" RevisionGUID="6b70b9e9-f497-4cad-9f56-c42cba7247e5" CreationDate="2017-07-26T08:03:52.067" UserId="213" Text="Correct way to set normal strength(OpenGL)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14720" PostHistoryTypeId="3" PostId="5411" RevisionGUID="6b70b9e9-f497-4cad-9f56-c42cba7247e5" CreationDate="2017-07-26T08:03:52.067" UserId="213" Text="|opengl|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14722" PostHistoryTypeId="5" PostId="5409" RevisionGUID="5d66d166-19c1-419c-92f3-373c70eb56ca" CreationDate="2017-07-26T09:48:29.527" UserId="6041" Comment="added 212 characters in body" Text="I am trying to implement Beer's law according to [this][1] page in dielectric material but I am not sure have done it correctly as the image does not suggest so.&#xD;&#xA;&#xD;&#xA;The formula is: I(s) = I(0) * pow(e, ln(A)*s)&#xD;&#xA;&#xD;&#xA;'A' is said to be transmission coefficient which I am not clear what this is&#xD;&#xA;and what value I should use for it.&#xD;&#xA;&#xD;&#xA;Below is the code and the image. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Could anyone shed some light if I have gone wrong. Thanks.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;            public override LightVector SampleBrdf(ISect isect, Random rand, &#xD;&#xA;                   out LightVector woW, out double pdfDir, out double cosWo)&#xD;&#xA;            { &#xD;&#xA;                woW = LightVector.ZERO;&#xD;&#xA;                cosWo = 0;&#xD;&#xA;                LightVector n = isect.Thing.Normal;&#xD;&#xA;                LightVector tan = isect.Thing.Edge1;&#xD;&#xA;                tan.Normalize();&#xD;&#xA;                LightVector ts = n.Cross(tan);&#xD;&#xA;            &#xD;&#xA;                //set wo to be incoming dir&#xD;&#xA;                LightVector wo = MaterialHelper.WorldToLocal(-isect.Ray.Dir, tan, ts, n);dir&#xD;&#xA;                LightVector refracted = LightVector.ZERO;&#xD;&#xA;                LightVector reflected = new LightVector(-wo.X, -wo.Y, wo.Z);&#xD;&#xA;    &#xD;&#xA;                double F = Fresnel.Evaluate(rindex1, rindex2, MaterialHelper.CosTheta(wo));&#xD;&#xA;                pdfDir = F;&#xD;&#xA;    &#xD;&#xA;                //Figure out which eta is incident and which is transmitted&#xD;&#xA;                double extCoeff = 1;&#xD;&#xA;                double etaI = rindex1;&#xD;&#xA;                double etaT = rindex2;&#xD;&#xA;                LightVector z = new LightVector(0, 0, 1);&#xD;&#xA;                if (MaterialHelper.CosTheta(wo) &lt; 0)//existing&#xD;&#xA;                {&#xD;&#xA;                    etaI = rindex2;&#xD;&#xA;                    etaT = rindex1;&#xD;&#xA;                    z = -z;&#xD;&#xA;                    extCoeff = Math.Exp(-Math.Log(A, Math.E) * isect.Dist);&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                //Compute ray direction for specular transmission&#xD;&#xA;                if (!MaterialHelper.Refract(wo, z, etaI / etaT, out refracted))&#xD;&#xA;                    pdfDir = 1;&#xD;&#xA;    &#xD;&#xA;                if (rand.NextDouble() &lt; pdfDir)&#xD;&#xA;                {&#xD;&#xA;                    woW = MaterialHelper.LocalToWorld(reflected, tan, ts, n);&#xD;&#xA;                    cosWo = MaterialHelper.AbsCosTheta(reflected);&#xD;&#xA;    &#xD;&#xA;                    return R * (F / cosWo);&#xD;&#xA;                }&#xD;&#xA;                else //refracted&#xD;&#xA;                {&#xD;&#xA;                    woW = MaterialHelper.LocalToWorld(refracted, tan, ts, n);&#xD;&#xA;                    cosWo = MaterialHelper.AbsCosTheta(refracted);&#xD;&#xA;                    pdfDir = 1d - F;&#xD;&#xA;    &#xD;&#xA;                    return T * (extCoeff * (1d - F) / cosWo);&#xD;&#xA;                }&#xD;&#xA;            } &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.eng.utah.edu/~cs6620/beers.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/4jgjp.png&#xD;&#xA;&#xD;&#xA;**Update:**&#xD;&#xA;&#xD;&#xA;I was expecting to see the reflection of the light source at the ceiling on the glass. But it was my mistake in the caller method where the specular bounce contribution was dismissed. &#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="14725" PostHistoryTypeId="2" PostId="5412" RevisionGUID="61736186-64b1-46a0-945e-4a584c45dcba" CreationDate="2017-07-26T19:36:53.900" UserId="7057" Text="Assuming that the normal was created by differentiating some height field `f(u,v)`:&#xD;&#xA;&#xD;&#xA;    N = normalize(df_du, df_dv, 1)&#xD;&#xA;&#xD;&#xA;What you probably want to achieve is to &quot;strengthen&quot; your normals as-if by scaling that height field by a factor C:&#xD;&#xA;&#xD;&#xA;    g(u,v) = C*f(u,v)&#xD;&#xA;&#xD;&#xA;Then your new normal would be:&#xD;&#xA;&#xD;&#xA;    M = normalize(dg_du, dg_dv, 1) = normalize(C*N0, C*N1, N2)&#xD;&#xA;&#xD;&#xA;Translating that to GLSL in your shader:&#xD;&#xA;&#xD;&#xA;    vec3 GetNormal(){&#xD;&#xA;        vec3 n = texture(normalMap,uv).xyz;&#xD;&#xA;        n = n * 2.0 - 1.0;&#xD;&#xA;        n.xy *= C;&#xD;&#xA;        n = normalize(n);&#xD;&#xA;        return  normalize (v_TBN * n);&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="14726" PostHistoryTypeId="2" PostId="5413" RevisionGUID="1fa10655-2674-455b-9a49-d1560c0b8e42" CreationDate="2017-07-26T20:07:34.660" UserId="2372" Text="I am trying to do simple PCF with Unity but I am facing some issues and I don't know where they come from. If anybody has an idea...&#xD;&#xA;&#xD;&#xA;Here are two examples&#xD;&#xA;&#xD;&#xA;    // C#&#xD;&#xA;    GetTemporaryRT(_shadowMapProperty, _shadowSettings.shadowAtlasWidth, _shadowSettings.shadowAtlasHeight, _depthBufferBits, FilterMode.Bilinear, RenderTextureFormat.Depth, RenderTextureReadWrite.Linear);&#xD;&#xA;    &#xD;&#xA;    // CG&#xD;&#xA;    sampler2D_float _ShadowMap;&#xD;&#xA;    float4 _ShadowMap_TexelSize;&#xD;&#xA;    &#xD;&#xA;    half ShadowAttenuation(float3 shadowCoord)&#xD;&#xA;    {&#xD;&#xA;    	float depth = tex2D(_ShadowMap, shadowCoord).r;&#xD;&#xA;    #if defined(UNITY_REVERSED_Z)&#xD;&#xA;    	return step(depth - _ShadowData.y, shadowCoord.z);&#xD;&#xA;    #else&#xD;&#xA;    	return step(shadowCoord.z, depth + _ShadowData.y);&#xD;&#xA;    #endif&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    /////// EXAMPLE 1 /////// &#xD;&#xA;    &#xD;&#xA;    float shadow = ShadowAttenuation(half3(shadowCoord.xy, shadowCoord.z));&#xD;&#xA;    return shadow;&#xD;&#xA;    &#xD;&#xA;    /////// EXAMPLE 2 ///////&#xD;&#xA;    &#xD;&#xA;    float3 UnityCombineShadowcoordComponents(float2 baseUV, float2 deltaUV, float depth)&#xD;&#xA;    {&#xD;&#xA;    	float3 uv = float3(baseUV + deltaUV, depth);&#xD;&#xA;    	uv.z += dot(deltaUV, receiverPlaneDepthBias.xy);&#xD;&#xA;    	return uv;&#xD;&#xA;    } &#xD;&#xA;    &#xD;&#xA;    half shadow = 1;&#xD;&#xA;    const float2 offset = float2(0.5, 0.5);&#xD;&#xA;    float2 uv = (shadowCoord.xy * _ShadowMap_TexelSize.zw) + offset;&#xD;&#xA;    float2 base_uv = (floor(uv) - offset) * _ShadowMap_TexelSize.xy;&#xD;&#xA;    float2 st = frac(uv);&#xD;&#xA;    &#xD;&#xA;    float2 uw = float2(3 - 2 * st.x, 1 + 2 * st.x);&#xD;&#xA;    float2 u = float2((2 - st.x) / uw.x - 1, (st.x) / uw.y + 1);&#xD;&#xA;    u *= _ShadowMap_TexelSize.x;&#xD;&#xA;    &#xD;&#xA;    float2 vw = float2(3 - 2 * st.y, 1 + 2 * st.y);&#xD;&#xA;    float2 v = float2((2 - st.y) / vw.x - 1, (st.y) / vw.y + 1);&#xD;&#xA;    v *= _ShadowMap_TexelSize.y;&#xD;&#xA;    &#xD;&#xA;    half sum = 0;&#xD;&#xA;    &#xD;&#xA;    sum += uw[0] * vw[0] * ShadowAttenuation(UnityCombineShadowcoordComponents(base_uv, float2(u[0], v[0]), shadowCoord.z));&#xD;&#xA;    sum += uw[1] * vw[0] * ShadowAttenuation(UnityCombineShadowcoordComponents(base_uv, float2(u[1], v[0]), shadowCoord.z));&#xD;&#xA;    sum += uw[0] * vw[1] * ShadowAttenuation(UnityCombineShadowcoordComponents(base_uv, float2(u[0], v[1]), shadowCoord.z));&#xD;&#xA;    sum += uw[1] * vw[1] * ShadowAttenuation(UnityCombineShadowcoordComponents(base_uv, float2(u[1], v[1]), shadowCoord.z));&#xD;&#xA;    &#xD;&#xA;    shadow = sum / 16.0f;&#xD;&#xA;    return shadow;&#xD;&#xA;&#xD;&#xA;Here are the results.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4NJ9e.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14727" PostHistoryTypeId="1" PostId="5413" RevisionGUID="1fa10655-2674-455b-9a49-d1560c0b8e42" CreationDate="2017-07-26T20:07:34.660" UserId="2372" Text="DX9 Shadow map PCF issue" ContentLicense="CC BY-SA 3.0" />
  <row Id="14728" PostHistoryTypeId="3" PostId="5413" RevisionGUID="1fa10655-2674-455b-9a49-d1560c0b8e42" CreationDate="2017-07-26T20:07:34.660" UserId="2372" Text="|shader|shadow|shadow-mapping|unity|directx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14729" PostHistoryTypeId="12" PostId="5413" RevisionGUID="725398c9-c7f5-4e22-9add-6228cdb232a0" CreationDate="2017-07-26T23:14:27.670" UserId="2372" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2372,&quot;DisplayName&quot;:&quot;MaT&quot;}]}" />
  <row Id="14730" PostHistoryTypeId="2" PostId="5414" RevisionGUID="d8aadc87-b772-41d0-a1c5-a1e7aeeec0cf" CreationDate="2017-07-27T00:24:23.270" UserDisplayName="user5681" Text="I was taking a look at Smallpt (http://www.kevinbeason.com/smallpt), more specifically at the Russian Roulette part. Actually, RR is used in two places along the code: first, to determine ray termination; and second, for the rendering of dielectrics. &#xD;&#xA;&#xD;&#xA;That is the code for the ray termination case (expanded code version):&#xD;&#xA;&#xD;&#xA;    // p = maximum reflectance&#xD;&#xA;    // fr = BRDF&#xD;&#xA;    double p = fr.x &gt; fr.y &amp;&amp; fr.x &gt; fr.z ? fr.x : fr.y &gt; fr.z ? fr.y : fr.z; &#xD;&#xA;&#xD;&#xA;    if ( ++depth &gt; 5 ) &#xD;&#xA;        if ( erand48(Xi) &lt; p )&#xD;&#xA;            fr = fr * ( 1 / p ); &#xD;&#xA;        else &#xD;&#xA;            return obj.emission;&#xD;&#xA;&#xD;&#xA;After five bounces, RR is used to determine if the ray path continues or not. If it continues, the BRDF is scaled to compensate for it. This is Ok for me.&#xD;&#xA;&#xD;&#xA;RR is also used in a second code segment, for the rendering of dielectrics (expanded code version): &#xD;&#xA;&#xD;&#xA;    double Re = R0 + ( 1 - R0 ) * cost * cost * cost * cost * cost;&#xD;&#xA;    double Tr = 1 - Re;&#xD;&#xA;    double P = .25 + .5 * Re;&#xD;&#xA;    double RP = Re / P;&#xD;&#xA;    double TP = Tr / ( 1 - P );&#xD;&#xA;    Vec Lo; // output radiance&#xD;&#xA;&#xD;&#xA;    if ( depth &gt; 2 )&#xD;&#xA;        if ( erand48(Xi) &lt; P )&#xD;&#xA;            Lo = radiance(reflRay,depth,Xi) * RP;&#xD;&#xA;        else&#xD;&#xA;            Lo = radiance(Ray(x,tdir),depth,Xi) * TP;&#xD;&#xA;    else    &#xD;&#xA;        Lo = radiance(reflRay,depth,Xi) * Re + radiance(Ray(x,tdir),depth,Xi) * Tr;&#xD;&#xA;&#xD;&#xA;According to the code above, the path branches recursively if the ray has bounced up to two times. After two bounces, however, RR is used to select the path to be followed. This is also Ok for me. &#xD;&#xA;&#xD;&#xA;What is a bit confusing is the fact that the radiance returned by both possible non-branching paths (refraction and transmission) is scaled. I understand that there are different probabilities regarding reflection and transmission. However, if for instance Re = 0.3 and Tr = 0.7, and 100 rays strike the surface, about 30% of the rays will be reflected and 70% of will be transmitted due RR. In this case, I understand that there is no path termination neither energy loss, so there wouldn't be nothing to compensate for.&#xD;&#xA;&#xD;&#xA;Thus, my first two questions are: why are these radiances scaled? Should they be scaled, or would it work without scaling at all?&#xD;&#xA;&#xD;&#xA;My third question is related to the scaling factors: Why the author have used P, RP and TP instead of Re and Tr?  &#xD;&#xA;&#xD;&#xA;Any indication of a good reading about this topic is also very welcome!! &#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14731" PostHistoryTypeId="1" PostId="5414" RevisionGUID="d8aadc87-b772-41d0-a1c5-a1e7aeeec0cf" CreationDate="2017-07-27T00:24:23.270" UserDisplayName="user5681" Text="About the use of Russian Roulette in Smallpt" ContentLicense="CC BY-SA 3.0" />
  <row Id="14732" PostHistoryTypeId="3" PostId="5414" RevisionGUID="d8aadc87-b772-41d0-a1c5-a1e7aeeec0cf" CreationDate="2017-07-27T00:24:23.270" UserDisplayName="user5681" Text="|raytracing|pathtracing|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14733" PostHistoryTypeId="2" PostId="5415" RevisionGUID="a0ea00a5-5353-4487-af4d-e78f22e620e1" CreationDate="2017-07-27T00:27:57.897" UserId="6282" Text="[![enter image description here][1]][1]&#xD;&#xA;(example of effect i am trying to render)&#xD;&#xA;&#xD;&#xA;Rendering Transparent Object in forward rendering is far easier. However I am having an issue when it comes to transparent glass like object that applies post processing like effect when seen through it.&#xD;&#xA;&#xD;&#xA;I do know how to render &quot;glass&quot; that reflects &quot;skybox&quot; however I do not know how to render a glass like object that applies its distortion effect around its dynamic surroundings.&#xD;&#xA;&#xD;&#xA;I need help figuring out how to render this effect. &#xD;&#xA;  [1]: https://i.stack.imgur.com/KGI2H.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14734" PostHistoryTypeId="1" PostId="5415" RevisionGUID="a0ea00a5-5353-4487-af4d-e78f22e620e1" CreationDate="2017-07-27T00:27:57.897" UserId="6282" Text="Forwad Rendering Distortion Effect" ContentLicense="CC BY-SA 3.0" />
  <row Id="14735" PostHistoryTypeId="3" PostId="5415" RevisionGUID="a0ea00a5-5353-4487-af4d-e78f22e620e1" CreationDate="2017-07-27T00:27:57.897" UserId="6282" Text="|distortion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14736" PostHistoryTypeId="5" PostId="5414" RevisionGUID="99335ab6-510d-4c71-870a-fc0f00479d68" CreationDate="2017-07-27T00:45:41.560" UserDisplayName="user5681" Comment="added 47 characters in body" Text="I was taking a look at Smallpt (http://www.kevinbeason.com/smallpt), more specifically at the Russian Roulette part. Actually, RR is used in two places along the code: first, to determine ray termination; and second, for the rendering of dielectrics. &#xD;&#xA;&#xD;&#xA;That is the code for the ray termination case (expanded code version):&#xD;&#xA;&#xD;&#xA;    // p = maximum reflectance&#xD;&#xA;    // fr = BRDF&#xD;&#xA;    double p = fr.x &gt; fr.y &amp;&amp; fr.x &gt; fr.z ? fr.x : fr.y &gt; fr.z ? fr.y : fr.z; &#xD;&#xA;&#xD;&#xA;    if ( ++depth &gt; 5 ) &#xD;&#xA;        if ( erand48(Xi) &lt; p )&#xD;&#xA;            fr = fr * ( 1 / p ); &#xD;&#xA;        else &#xD;&#xA;            return obj.emission;&#xD;&#xA;&#xD;&#xA;After five bounces, RR is used to determine if the ray path continues or not. If it continues, the BRDF is scaled to compensate for it. This is Ok for me.&#xD;&#xA;&#xD;&#xA;RR is also used in a second code segment to select between refraction or transmission during the rendering of dielectrics (expanded code version): &#xD;&#xA;&#xD;&#xA;    double Re = R0 + ( 1 - R0 ) * cost * cost * cost * cost * cost;&#xD;&#xA;    double Tr = 1 - Re;&#xD;&#xA;    double P = .25 + .5 * Re;&#xD;&#xA;    double RP = Re / P;&#xD;&#xA;    double TP = Tr / ( 1 - P );&#xD;&#xA;    Vec Lo; // output radiance&#xD;&#xA;&#xD;&#xA;    if ( depth &gt; 2 )&#xD;&#xA;        if ( erand48(Xi) &lt; P )&#xD;&#xA;            Lo = radiance(reflRay,depth,Xi) * RP;&#xD;&#xA;        else&#xD;&#xA;            Lo = radiance(Ray(x,tdir),depth,Xi) * TP;&#xD;&#xA;    else    &#xD;&#xA;        Lo = radiance(reflRay,depth,Xi) * Re + radiance(Ray(x,tdir),depth,Xi) * Tr;&#xD;&#xA;&#xD;&#xA;According to the code above, the path branches recursively if the ray has bounced up to two times. After two bounces, however, RR is used to select the path to be followed. This is also Ok for me. &#xD;&#xA;&#xD;&#xA;What is a bit confusing is the fact that the radiance returned by both possible non-branching paths (refraction and transmission) is scaled. I understand that there are different probabilities regarding reflection and transmission. However, if for instance Re = 0.3 and Tr = 0.7, and 100 rays strike the surface, about 30% of the rays will be reflected and 70% of will be transmitted due RR. In this case, I understand that there is no path termination neither energy loss, so there wouldn't be nothing to compensate for.&#xD;&#xA;&#xD;&#xA;Thus, my first two questions are: why are these radiances scaled? Should they be scaled, or would it work without scaling at all?&#xD;&#xA;&#xD;&#xA;My third question is related to the scaling factors: Why the author have used P, RP and TP instead of Re and Tr?  &#xD;&#xA;&#xD;&#xA;Any indication of a good reading about this topic is also very welcome!! &#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14737" PostHistoryTypeId="5" PostId="5414" RevisionGUID="85c3f3a7-fb2e-4d4c-890f-f6c5e86e153d" CreationDate="2017-07-27T02:21:45.690" UserDisplayName="user5681" Comment="deleted 1 character in body" Text="I was taking a look at Smallpt (http://www.kevinbeason.com/smallpt), more specifically at the Russian Roulette part. Actually, RR is used in two places along the code: first, to determine ray termination; and second, for the rendering of dielectrics. &#xD;&#xA;&#xD;&#xA;That is the code for the ray termination case (expanded code version):&#xD;&#xA;&#xD;&#xA;    // p = maximum reflectance&#xD;&#xA;    // fr = BRDF&#xD;&#xA;    double p = fr.x &gt; fr.y &amp;&amp; fr.x &gt; fr.z ? fr.x : fr.y &gt; fr.z ? fr.y : fr.z; &#xD;&#xA;&#xD;&#xA;    if ( ++depth &gt; 5 ) &#xD;&#xA;        if ( erand48(Xi) &lt; p )&#xD;&#xA;            fr = fr * ( 1 / p ); &#xD;&#xA;        else &#xD;&#xA;            return obj.emission;&#xD;&#xA;&#xD;&#xA;After five bounces, RR is used to determine if the ray path continues or not. If it continues, the BRDF is scaled to compensate for it. This is Ok for me.&#xD;&#xA;&#xD;&#xA;RR is also used in a second code segment to select between refraction or transmission during the rendering of dielectrics (expanded code version): &#xD;&#xA;&#xD;&#xA;    double Re = R0 + ( 1 - R0 ) * cost * cost * cost * cost * cost;&#xD;&#xA;    double Tr = 1 - Re;&#xD;&#xA;    double P = .25 + .5 * Re;&#xD;&#xA;    double RP = Re / P;&#xD;&#xA;    double TP = Tr / ( 1 - P );&#xD;&#xA;    Vec Lo; // output radiance&#xD;&#xA;&#xD;&#xA;    if ( depth &gt; 2 )&#xD;&#xA;        if ( erand48(Xi) &lt; P )&#xD;&#xA;            Lo = radiance(reflRay,depth,Xi) * RP;&#xD;&#xA;        else&#xD;&#xA;            Lo = radiance(Ray(x,tdir),depth,Xi) * TP;&#xD;&#xA;    else    &#xD;&#xA;        Lo = radiance(reflRay,depth,Xi) * Re + radiance(Ray(x,tdir),depth,Xi) * Tr;&#xD;&#xA;&#xD;&#xA;According to the code above, the path branches recursively if the ray has bounced up to two times. After two bounces, however, RR is used to select the path to be followed. This is also Ok for me. &#xD;&#xA;&#xD;&#xA;What is a bit confusing is the fact that the radiance returned by both possible non-branching paths (refraction and transmission) is scaled. I understand that there are different probabilities regarding reflection and transmission. However, if for instance Re = 0.3 and Tr = 0.7, and 100 rays strike the surface, about 30% of the rays will be reflected and 70% of will be transmitted due RR. In this case, I understand that there is no path termination neither energy loss, so there wouldn't be nothing to compensate for.&#xD;&#xA;&#xD;&#xA;Thus, my first two questions are: why are these radiances scaled? Should they be scaled, or would it work without scaling at all?&#xD;&#xA;&#xD;&#xA;My third question is related to the scaling factors: Why the author has used P, RP and TP instead of Re and Tr?  &#xD;&#xA;&#xD;&#xA;Any indication of a good reading about this topic is also very welcome!! &#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14738" PostHistoryTypeId="5" PostId="2093" RevisionGUID="1911e3c7-e60d-4eb7-8f57-9fa08f2d9a67" CreationDate="2017-07-27T05:46:46.710" UserId="2750" Comment="Fixed number of vertices" Text="I have a 3D model, which consists of ~50 thousand vertices and 100 thousand triangles. Format is: there's array of vertices' coordinates and array of triangles, which has numbers of vertices (e.g., [1, 2, 5] -- triangle, which consists of first, second and fifth vertex from vertices' array).&#xD;&#xA;&#xD;&#xA;I calculate color of each triangle and rotate the model by myself.&#xD;&#xA;Also I &quot;render&quot; it manually, putting vertices as pixels on `PIL` image, but matrix with colors is enough for my purpose (I need only the matrix).&#xD;&#xA;&#xD;&#xA;I don't know, whether I will implement robust and correct rendering function, but I cannot find light-weight library as well.&#xD;&#xA;All I need is to display the set of triangles with specified colors and  background image fast (far less than for a second)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14739" PostHistoryTypeId="2" PostId="5416" RevisionGUID="7cfd07b8-45fd-42dc-bb35-8e421ca669c5" CreationDate="2017-07-27T06:34:32.850" UserId="7000" Text="[One example][1] of Image Load / Stores that I have seen could be done using framebuffers instead of Image Load / Stores.  Framebuffers have been available longer in OpenGL and so my question is:&#xD;&#xA;&#xD;&#xA;Why would you use Images instead of Framebuffers?&#xD;&#xA;&#xD;&#xA;What advantages do they offer?&#xD;&#xA;&#xD;&#xA;The referenced example says:&#xD;&#xA;&#xD;&#xA;&gt; Note that this demo can also easily be imlemented using Framebuffer Objects. But with Framebuffer Objects you cannot write to arbitrary locations in a texture, though.&#xD;&#xA;&#xD;&#xA;I am not exactly sure what is meant here. My understanding is that you *can* write to whatever pixel coordinates you want in an FBO.  Am I mistaken here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/Erkaman/image-load-store-demo" ContentLicense="CC BY-SA 3.0" />
  <row Id="14740" PostHistoryTypeId="1" PostId="5416" RevisionGUID="7cfd07b8-45fd-42dc-bb35-8e421ca669c5" CreationDate="2017-07-27T06:34:32.850" UserId="7000" Text="Why use image load / stores instead of FBOs" ContentLicense="CC BY-SA 3.0" />
  <row Id="14741" PostHistoryTypeId="3" PostId="5416" RevisionGUID="7cfd07b8-45fd-42dc-bb35-8e421ca669c5" CreationDate="2017-07-27T06:34:32.850" UserId="7000" Text="|opengl|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14743" PostHistoryTypeId="2" PostId="5417" RevisionGUID="3fef6e67-59c8-4d27-8576-db074410ac3e" CreationDate="2017-07-27T10:37:21.597" UserId="7059" Text="As mentioned by previous answers, the best way to solve your issue is to compute the intersections of the two circles centered at A and B. Since you will have two candidates, you will need to choose a specific order for your edges to only select one candidate." ContentLicense="CC BY-SA 3.0" />
  <row Id="14744" PostHistoryTypeId="2" PostId="5418" RevisionGUID="1288ede4-e48a-4cf7-8f55-9c2f86af8ea8" CreationDate="2017-07-27T11:03:05.473" UserId="7059" Text="&#xD;&#xA;&#xD;&#xA;The documentation quickly sum up the idea with: &#xD;&#xA;&#xD;&#xA;&gt; The idea with image load/store is that the user can bind one of the&#xD;&#xA;&gt; images in a Texture to a number of image binding points (which are&#xD;&#xA;&gt; separate from texture image units). Shaders can read information from&#xD;&#xA;&gt; these images and write information to them, in ways that they cannot&#xD;&#xA;&gt; with textures.&#xD;&#xA;&#xD;&#xA;Aside for the simplicity of usage, from http://rastergrid.com/blog/2011/08/an-introduction-to-opengl-4-2/ at the section **ARB_shader_image_load_store** you can perform more complex operations and algorithms in GLSL to a single level of a texture (which is called an image) and from any shader stage.&#xD;&#xA;&#xD;&#xA;I am also curious about the implementation of the example with FBO since I don't understand why you cannot write to a specific pixel coordinate too." ContentLicense="CC BY-SA 3.0" />
  <row Id="14745" PostHistoryTypeId="50" PostId="4917" RevisionGUID="13e4d928-1247-4025-9e90-b732700b57f6" CreationDate="2017-07-27T11:16:51.963" UserId="-1" />
  <row Id="14746" PostHistoryTypeId="2" PostId="5419" RevisionGUID="1cd9f902-69d3-41ea-aa90-23b9f0500d49" CreationDate="2017-07-27T11:28:31.237" UserId="7057" Text="To write to an arbitrary location in a FBO you need to do rasterization of point primitive at that location. This is significantly more costly than a single `imageStore` because it involves invoking the vertex shader, the ROP units, and possibly rasterizing a whole 2x2 quad or more for just a single pixel.&lt;sup&gt;†&lt;/sup&gt; With `imageLoad`/`imageStore` you have greater flexibility and finer control of where you read and write, including atomics, barriers, etc... Since you skip the ROP and give up the API-order guarantee, such direct writes might be faster even for filling triangles.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;† I'm not sure about this last point, but since the screen-space derivatives are still available in the fragment shader, and point primitives are typically used for larger sprites, it means that the implementations are more likely to just go the typical rasterization route used for lines and triangles." ContentLicense="CC BY-SA 3.0" />
  <row Id="14747" PostHistoryTypeId="2" PostId="5420" RevisionGUID="b7b4a0b7-ff49-478c-a851-0cc965824b97" CreationDate="2017-07-27T11:29:57.653" UserId="7059" Text="&gt; Is there any software which would let me import the existing models,&#xD;&#xA;&gt; define the bone hierarchy and the model which corresponds to each&#xD;&#xA;&gt; bone, and export a single articulated model in T-pose?&#xD;&#xA;&#xD;&#xA;I found that it is relatively easy to create articulations using Blender.&#xD;&#xA;This tutorial might be helpful : https://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/Bones" ContentLicense="CC BY-SA 3.0" />
  <row Id="14748" PostHistoryTypeId="12" PostId="5417" RevisionGUID="24cf3a6a-d4df-4db3-9ca7-f97eb6e7f096" CreationDate="2017-07-27T11:31:29.520" UserId="7059" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7059,&quot;DisplayName&quot;:&quot;BallzOfSteel&quot;}]}" />
  <row Id="14749" PostHistoryTypeId="2" PostId="5421" RevisionGUID="595666f5-4589-4ada-9ab2-f7cb1835d19a" CreationDate="2017-07-27T12:33:12.903" UserId="6785" Text="I have a number of (opaque) objects created using the glGenLists() glNewList() utilities. As generated, the Alpha values are all set to 1&#xD;&#xA;&#xD;&#xA;Is there a way to make these objects when summoned blend into the scene (sort of as if they were being teleported using the Star Trek transporter). Likewise, I'd also like them to dissolve away when dismissed.&#xD;&#xA;&#xD;&#xA;I could of course use time-varying alpha blending in a subroutine if they weren't list objects, but I'm wondering if there's a performance penalty associated with that.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14750" PostHistoryTypeId="1" PostId="5421" RevisionGUID="595666f5-4589-4ada-9ab2-f7cb1835d19a" CreationDate="2017-07-27T12:33:12.903" UserId="6785" Text="Make Object created in a list blend in/dissolve out of a scene" ContentLicense="CC BY-SA 3.0" />
  <row Id="14751" PostHistoryTypeId="3" PostId="5421" RevisionGUID="595666f5-4589-4ada-9ab2-f7cb1835d19a" CreationDate="2017-07-27T12:33:12.903" UserId="6785" Text="|opengl|blending|alpha|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14752" PostHistoryTypeId="5" PostId="5421" RevisionGUID="66333467-01f8-479f-9610-4fa480b85c22" CreationDate="2017-07-27T12:42:39.643" UserId="6785" Comment="added 167 characters in body" Text="I have a number of (opaque) objects created using the glGenLists() glNewList() utilities. As generated, the Alpha values are all set to 1&#xD;&#xA;&#xD;&#xA;Is there a way to make these objects when summoned blend into the scene (sort of as if they were being teleported using the Star Trek transporter). Likewise, I'd also like them to dissolve away when dismissed.&#xD;&#xA;&#xD;&#xA;I could of course use time-varying alpha blending in a subroutine if they weren't list objects, but I'm wondering if there's a performance penalty associated with that.&#xD;&#xA;&#xD;&#xA;What I'm really trying to do is replace larger coarser ground texture quads  with finer smaller quads as I descend in altitude from a satellite while looking down.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14753" PostHistoryTypeId="2" PostId="5422" RevisionGUID="cad698d7-2164-495d-8ebe-f34dbec02c29" CreationDate="2017-07-27T14:09:19.767" UserId="4546" Text="The reflected and transmitted values need to be scaled because they are not sampled proportionally to their contribution. You'll notice how the decision whether to reflect or transmit is made based on P, not Re.&#xD;&#xA;&#xD;&#xA;About why that scaling has been done in the first place, only the author can give you the definitive answer. My guess is that this is done to prevent extreme values that would come from tiny probabilities. Imagine that Re is 0.001 and is used without scaling. Then only one in 1000 rays would reflect, and the contribution of that ray would be multiplied by 1000. At a render with, say, 64 rays per pixel, this would leave very visible artefacts, as not every pixel would get a reflected ray. The scaling from this code snipped on the other hand makes sure that the ray budget is more evenly distributed between reflection and transmission and that each potential path taken is guaranteed at least 25% or the rays.&#xD;&#xA;&#xD;&#xA;For further reading about path tracing, there is no better and comprehensive resource than www.pbrt.org - both the book and the source code are worth reading." ContentLicense="CC BY-SA 3.0" />
  <row Id="14754" PostHistoryTypeId="2" PostId="5423" RevisionGUID="325e0ccc-c5a9-4698-955a-1b749495c226" CreationDate="2017-07-27T16:21:35.037" UserId="2654" Text="&gt; Why would you use Images instead of Framebuffers?&#xD;&#xA;&#xD;&#xA;[Image Load/Store][1] is not intended to replace framebuffers. It's a feature that allows (relatively) arbitrary reading and writing to memory. So you would use images when you need to arbitrarily read and write to memory. You would use framebuffers when you're rasterizing primitives for rendering purposes.&#xD;&#xA;&#xD;&#xA;The fact that you can build scenarios where you would use the latter in place of the former does not mean that this is the purpose of the feature.&#xD;&#xA;&#xD;&#xA;&gt; What advantages do they offer?&#xD;&#xA;&#xD;&#xA;Again, it's not meant to replace framebuffers. But the comparison is pretty simple.&#xD;&#xA;&#xD;&#xA;A particular FS invocation cannot:&#xD;&#xA;&#xD;&#xA;* Choose what framebuffer texel(s) to write to. An FS invocation will only ever write outputs to the framebuffer texel(s) that map to its current fragment location. `gl_FragCoord` is an input value; it is non-modifiable. An FS's outputs will either be [discard][2] or written to the framebuffer texel(s) corresponding to `gl_FragCoord.xy`.&#xD;&#xA;&#xD;&#xA;    Yes, through point rasterization, you can select which fragment is being generated. But it isn't the fragment shader *itself* that's deciding this; it's whatever process wrote the vertex to the buffer that it's being read from. That is not under the direct control of the FS invocation itself.&#xD;&#xA;&#xD;&#xA;* Choose to write to multiple distinct framebuffer texel(s) locations. A fragment cannot cover multiple texels.&#xD;&#xA;* Choose which output attachments in the framebuffer to write to. The decision of which [fragment shader outputs][3] will be written is made by the [write mask state][4], which the FS has zero control over. An FS can choose to be [discarded][2], but that discards *all* of its outputs.&#xD;&#xA;* Choose to read from the current framebuffer texel(s) it is writing to. [Blending][5] is done by a fixed-function stage; the FS has zero control over this. The closest you can get is to employ some [texture barrier gymnastics][6], but that's not something the FS can directly control.&#xD;&#xA;* Choose to read from framebuffer texel(s) other than the one it's writing to. Even with texture barrier gymnastics, you cannot read from other people's texels.&#xD;&#xA;&#xD;&#xA;Now granted, image load/store doesn't exactly make read/modify/write passes easy, due to [incoherent memory access rules][7].&#xD;&#xA;&#xD;&#xA;Of course, image load/store cannot handle (easily):&#xD;&#xA;&#xD;&#xA;* Depth testing. Or at least, not in any way that is *nearly* as efficient as the rasterizer. The read/modify/write nature of the depth test makes this exceedingly tricky with image load/store. With a regular depth buffer however, this is trivial.&#xD;&#xA;* Simple blending. Again, you can do it, but it's really hard, and far less efficient than the normal rendering process.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Fragment#Fragment_discard&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Fragment#Fragment_shader_outputs&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Write_Mask&#xD;&#xA;  [5]: https://www.khronos.org/opengl/wiki/Blending&#xD;&#xA;  [6]: https://www.khronos.org/opengl/wiki/Texture_Barrier&#xD;&#xA;  [7]: https://www.khronos.org/opengl/wiki/Memory_Model#Incoherent_memory_access" ContentLicense="CC BY-SA 3.0" />
  <row Id="14759" PostHistoryTypeId="13" PostId="5417" RevisionGUID="fb26bbbc-6c0e-4e83-8386-1a8870f7d99f" CreationDate="2017-07-27T19:27:56.737" UserId="7059" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7059,&quot;DisplayName&quot;:&quot;BallzOfSteel&quot;}]}" />
  <row Id="14761" PostHistoryTypeId="5" PostId="5414" RevisionGUID="40cdcd0f-f005-4d44-ac3f-1cf913b1d84b" CreationDate="2017-07-28T00:10:33.437" UserDisplayName="user5681" Comment="added 1 character in body" Text="I was taking a look at Smallpt (http://www.kevinbeason.com/smallpt), more specifically at the Russian Roulette part. Actually, RR is used in two places along the code: first, to determine ray termination; and second, for the rendering of dielectrics. &#xD;&#xA;&#xD;&#xA;That is the code for the ray termination case (expanded code version):&#xD;&#xA;&#xD;&#xA;    // p = maximum reflectance&#xD;&#xA;    // fr = BRDF&#xD;&#xA;    double p = fr.x &gt; fr.y &amp;&amp; fr.x &gt; fr.z ? fr.x : fr.y &gt; fr.z ? fr.y : fr.z; &#xD;&#xA;&#xD;&#xA;    if ( ++depth &gt; 5 ) &#xD;&#xA;        if ( erand48(Xi) &lt; p )&#xD;&#xA;            fr = fr * ( 1 / p ); &#xD;&#xA;        else &#xD;&#xA;            return obj.emission;&#xD;&#xA;&#xD;&#xA;After five bounces, RR is used to determine if the ray path continues or not. If it continues, the BRDF is scaled to compensate for it. This is Ok for me.&#xD;&#xA;&#xD;&#xA;RR is also used in a second code segment to select between refraction or transmission during the rendering of dielectrics (expanded code version): &#xD;&#xA;&#xD;&#xA;    double Re = R0 + ( 1 - R0 ) * cost * cost * cost * cost * cost;&#xD;&#xA;    double Tr = 1 - Re;&#xD;&#xA;    double P = .25 + .5 * Re;&#xD;&#xA;    double RP = Re / P;&#xD;&#xA;    double TP = Tr / ( 1 - P );&#xD;&#xA;    Vec Lo; // output radiance&#xD;&#xA;&#xD;&#xA;    if ( depth &gt; 2 )&#xD;&#xA;        if ( erand48(Xi) &lt; P )&#xD;&#xA;            Lo = radiance(reflRay,depth,Xi) * RP;&#xD;&#xA;        else&#xD;&#xA;            Lo = radiance(Ray(x,tdir),depth,Xi) * TP;&#xD;&#xA;    else    &#xD;&#xA;        Lo = radiance(reflRay,depth,Xi) * Re + radiance(Ray(x,tdir),depth,Xi) * Tr;&#xD;&#xA;&#xD;&#xA;According to the code above, the path branches recursively if the ray has bounced up to two times. After two bounces, however, RR is used to select the path to be followed. This is also Ok for me. &#xD;&#xA;&#xD;&#xA;What is a bit confusing is the fact that the radiance returned by both possible non-branching paths (refraction and transmission) is scaled. I understand that there are different probabilities regarding reflection and transmission. However, if for instance Re = 0.3 and Tr = 0.7, and 100 rays strike the surface, about 30% of the rays will be reflected and 70% of will be transmitted due RR. In this case, I understand that there is no path termination neither energy loss, so there wouldn't be anything to compensate for.&#xD;&#xA;&#xD;&#xA;Thus, my first two questions are: why are these radiances scaled? Should they be scaled, or would it work without scaling at all?&#xD;&#xA;&#xD;&#xA;My third question is related to the scaling factors: Why the author has used P, RP and TP instead of Re and Tr?  &#xD;&#xA;&#xD;&#xA;Any indication of a good reading about this topic is also very welcome!! &#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14762" PostHistoryTypeId="4" PostId="5415" RevisionGUID="0f1661a5-d919-4e58-8479-98033d171c33" CreationDate="2017-07-28T01:38:08.633" UserId="182" Comment="Minor typo." Text="Forward Rendering Distortion Effect" ContentLicense="CC BY-SA 3.0" />
  <row Id="14763" PostHistoryTypeId="2" PostId="5426" RevisionGUID="42a00393-c0d0-483e-a69c-bb73a0984a63" CreationDate="2017-07-28T02:18:00.760" UserId="182" Text="An effect like that is most likely done as a second pass, after storing a copy of the color buffer.&#xD;&#xA;&#xD;&#xA;When looking carefully, you can see some of the vertices from the shape of the effect above the character. So this scene in particular probably does something like this:&#xD;&#xA;&#xD;&#xA; 1. First render the scene into a color buffer, without the distortion effect.&#xD;&#xA; 2. Because it's not possible to both read from and write to a same frame buffer at the same time, copy it as is (blit) into another frame buffer. From now on, new draws will go into that new frame buffer.&#xD;&#xA; 3. In the new frame buffer, draw a mesh with the shape of the effect, using a shader that will fetch the texture of the first color buffer, with an offset depending on the normal. Also note that:&#xD;&#xA;    - The mesh is opaque (no blending): it's the texture that makes it look transparent.&#xD;&#xA;    - Although we don't see this in the screenshot, it's also perfectly possible to use the depth buffer as usual and have the effect intersect with the scene.&#xD;&#xA;&#xD;&#xA;Finally a simpler effect, like rain drops on the screen, could be done this way:&#xD;&#xA;&#xD;&#xA; 1. First render the scene into a frame buffer, without the distortion effect.&#xD;&#xA; 2. Copy the entire frame buffer into another frame buffer using a custom shader. The shader will apply some offset to the texture coordinates (either directly or maybe using a distortion texture), thus distorting the image.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14764" PostHistoryTypeId="2" PostId="5427" RevisionGUID="20cb7b4b-cab5-4b77-aec5-58f2324b1f84" CreationDate="2017-07-28T07:33:30.007" UserId="38" Text="There are several ways of doing this, the circle intersection way is by no metrics the easiest way. If you have any standard vector maths library available then the simpest way in my mind is as follows:&#xD;&#xA;&#xD;&#xA;* Calculate the direction vector a-b, by subtracting vector a from vector b. Then normalize this vector then multiply it by length of b-c&#xD;&#xA;* calculate the angle at corner b&#xD;&#xA;* rotate the vector calculated by 180 +- the angle. (There are 2 solutions).&#xD;&#xA;* add b to that vector. And you are done.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14765" PostHistoryTypeId="5" PostId="4917" RevisionGUID="ce409e39-bf99-4540-8551-490d73b43c32" CreationDate="2017-07-28T08:43:05.080" UserId="182" Comment="added 206 characters in body; edited tags" Text="&gt; For a 3D scene in the world coordinates, its _View Reference Point_ $\mathrm{VRP}$ is at $(5,2,1)$, and a viewer is looking towards point $A=(1,1,1)$. Construct a transform matrix which will map  world  coordinate  points  to  a  right-handed  $(UVN)$  viewing  space,  so  that  VRP  is &#xD;&#xA;the  origin,  the  line  joining  $\mathrm{VRP}$ to  $A$  is  the  positive  $N$  axis,  and  the  view-up  Vector  is $(0,0,1)$.  &#xD;&#xA;&#xD;&#xA;I have calculated the translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;T=&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -5 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 2 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -1 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I have calculated the rotation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R=&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;-0.6 &amp; -0.8 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;-0.8 &amp; 0.6 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But what would the final transformation matrix $M$ be? My lecture slides tell me it would be rotation matrix multiplied by translation matrix, with the last column multiplied by $-1$ except for the $1$. This would equal:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;M = R \times T = &#xD;&#xA;\begin{pmatrix}&#xD;&#xA;-0.6 &amp; -0.8 &amp; 0 &amp; -1.4 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 1 \\&#xD;&#xA;-0.8 &amp; 0.6 &amp; 0 &amp; -5.2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But this answer here: https://computergraphics.stackexchange.com/questions/4737/building-view-transform-matrices&#xD;&#xA;&#xD;&#xA;just adds them together somehow. Which one is correct?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14766" PostHistoryTypeId="6" PostId="4917" RevisionGUID="ce409e39-bf99-4540-8551-490d73b43c32" CreationDate="2017-07-28T08:43:05.080" UserId="182" Comment="added 206 characters in body; edited tags" Text="|3d|matrix|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14767" PostHistoryTypeId="5" PostId="4737" RevisionGUID="3933db6c-aa53-4b0e-82e3-ea3987cf265c" CreationDate="2017-07-28T08:54:48.010" UserId="182" Comment="Added more MathJax, and quoted the assignment text." Text="&gt; For a 3D scene in the world coordinates, its _View Reference Point_ $\mathrm{VRP}$ is at $(5,-2,1)$, and a viewer is looking towards point $A=(1,1,1)$. Construct a transform matrix which will map world coordinate points to a right-handed $(UVN)$ viewing space, so that $\mathrm{VRP}$ is the origin, the line joining $\mathrm{VRP}$ to $A$ is the positive $N$ axis, and the view-up Vector is $(0,0,1)$.&#xD;&#xA;&#xD;&#xA;To my knowledge, the final answer should be a single transform matrix.&#xD;&#xA;To calculate the final matrix, I first find the matrix which translates the coordinate system to the to the origin in homogeneous matrix form:&#xD;&#xA;&#xD;&#xA;Translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;T=&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        1 &amp;0 &amp;0 &amp;-5 \\&#xD;&#xA;        0 &amp;1 &amp;0&amp; 2 \\&#xD;&#xA;        0 &amp;0 &amp;1 &amp;-1 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Using the unit vectors of the coordinate axes, the resulting rotation matrix is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R=&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        -0.6 &amp;-0.8 &amp;0 &amp;0 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        -0.8 &amp;0.6 &amp;0 &amp;0 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Then the final matrix (the final answer for full marks) would be the rotation matrix multiplied by the translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;M=&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        -0.6 &amp;-0.8 &amp;0 &amp;1.4 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        -0.8 &amp;0.6 &amp;0 &amp;5.2 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Is my method and final answer correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14768" PostHistoryTypeId="6" PostId="4737" RevisionGUID="3933db6c-aa53-4b0e-82e3-ea3987cf265c" CreationDate="2017-07-28T08:54:48.010" UserId="182" Comment="Added more MathJax, and quoted the assignment text." Text="|3d|matrix|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14769" PostHistoryTypeId="13" PostId="5413" RevisionGUID="894511a4-b39c-49bc-a879-c02329da7fe7" CreationDate="2017-07-28T10:10:10.930" UserId="2372" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2372,&quot;DisplayName&quot;:&quot;MaT&quot;}]}" />
  <row Id="14770" PostHistoryTypeId="5" PostId="5412" RevisionGUID="f1320425-c227-41b0-a30a-a1debde876dd" CreationDate="2017-07-28T10:30:17.600" UserId="7057" Comment="added 382 characters in body" Text="Assuming that the normal was created by differentiating some height field `f(u,v)`:&#xD;&#xA;&#xD;&#xA;    N = normalize(df_du, df_dv, 1)&#xD;&#xA;&#xD;&#xA;What you probably want to achieve is to &quot;strengthen&quot; your normals as-if by scaling that height field by a factor C:&#xD;&#xA;&#xD;&#xA;    g(u,v) = C*f(u,v)&#xD;&#xA;&#xD;&#xA;Then your new normal would be:&#xD;&#xA;&#xD;&#xA;    M = normalize(dg_du, dg_dv, 1) = normalize(C*N0, C*N1, N2)&#xD;&#xA;&#xD;&#xA;Translating that to GLSL in your shader:&#xD;&#xA;&#xD;&#xA;    vec3 GetNormal(){&#xD;&#xA;        vec3 n = texture(normalMap,uv).xyz;&#xD;&#xA;        n = n * 2.0 - 1.0;&#xD;&#xA;        n.xy *= C;&#xD;&#xA;        n = normalize(n);&#xD;&#xA;        return  normalize (v_TBN * n);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;By constructing a normal map texture that stores only the height-field gradient `(df_du, df_dv)` without normalization, using the internal format `GL_RG8_SNORM` for the texture, and making sure that `v_TBN` is orthonormal, you can simplify it further to:&#xD;&#xA;&#xD;&#xA;    vec3 GetNormal() {&#xD;&#xA;        vec3 n = normalize(vec3(texture(normalMap,uv).xy, C));&#xD;&#xA;        return v_TBN*n;&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14771" PostHistoryTypeId="2" PostId="5428" RevisionGUID="3f06a723-905a-4684-8b72-3a6062f4d876" CreationDate="2017-07-28T10:46:14.160" UserId="2372" Text="It seems that `sampler2D_float` doesn't allow to interpolate shadow lookup  linearly. So I had to do it by hand. Here's an example of [interpolated shadowing][1].&#xD;&#xA;&#xD;&#xA;    float texture2DCompare(sampler2D depths, vec2 uv, float compare){&#xD;&#xA;        float depth = texture2D(depths, uv).r;&#xD;&#xA;        return step(compare, depth);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float texture2DShadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){&#xD;&#xA;        vec2 texelSize = vec2(1.0)/size;&#xD;&#xA;        vec2 f = fract(uv*size+0.5);&#xD;&#xA;        vec2 centroidUV = floor(uv*size+0.5)/size;&#xD;&#xA;    &#xD;&#xA;        float lb = texture2DCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);&#xD;&#xA;        float lt = texture2DCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);&#xD;&#xA;        float rb = texture2DCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);&#xD;&#xA;        float rt = texture2DCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);&#xD;&#xA;        float a = mix(lb, lt, f.y);&#xD;&#xA;        float b = mix(rb, rt, f.y);&#xD;&#xA;        float c = mix(a, b, f.x);&#xD;&#xA;        return c;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://codeflow.org/entries/2013/feb/15/soft-shadow-mapping/#interpolated-shadowing" ContentLicense="CC BY-SA 3.0" />
  <row Id="14772" PostHistoryTypeId="2" PostId="5429" RevisionGUID="9f594c72-f083-4cd3-a9b0-838669d9adfd" CreationDate="2017-07-28T13:39:36.447" UserId="5430" Text="What is the best way to save video from faces of a cube? The render can produce 6 squares (90°x90°) of 1024x1024 resolution. Faces oriented along axies and only position is changed continuously. I want to save them into the video stream and then play back them into 360° panorama viewver by means of projection on the cube or using cubemap (OpenGL ES).&#xD;&#xA;&#xD;&#xA;What is the best codec suitable and what is the best way to save video for above purposes? Is it better to use six separate synchronized video streams or, instead, to enclose all six faces into the one?&#xD;&#xA;&#xD;&#xA;If cube is unfolded into six square bitmaps and composed into a 3x2 (or 2x3) rectangle, then it is possible to get artifacts on glued inner edges and on the outer edge of the resulting rectangle. I sure it may depend on codec used to compress/decompress resulting video.&#xD;&#xA;&#xD;&#xA;In case of 6 separate video streams it is possible to render only 5 of 6 (or 3 of 6 in case of only pitch and yaw (but not roll) rotations are possible) faces of cube, i.e. only visible ones. But on the other hand it may be waste of resources to support six separate streams due to necessity of attendant metainformation handling.&#xD;&#xA;&#xD;&#xA;What are expected performance issues inherent to different approaches?&#xD;&#xA;&#xD;&#xA;The relevant platform is average home desktop PC." ContentLicense="CC BY-SA 3.0" />
  <row Id="14773" PostHistoryTypeId="1" PostId="5429" RevisionGUID="9f594c72-f083-4cd3-a9b0-838669d9adfd" CreationDate="2017-07-28T13:39:36.447" UserId="5430" Text="Codec to save 360° panorama video" ContentLicense="CC BY-SA 3.0" />
  <row Id="14774" PostHistoryTypeId="3" PostId="5429" RevisionGUID="9f594c72-f083-4cd3-a9b0-838669d9adfd" CreationDate="2017-07-28T13:39:36.447" UserId="5430" Text="|opengl|rendering|projections|video|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14775" PostHistoryTypeId="2" PostId="5430" RevisionGUID="f4bb1bb7-728e-45a8-84bd-5c63e2700617" CreationDate="2017-07-28T14:21:24.263" UserId="3073" Text="I would be tempted to use a solution which involves decoding a single rectangular video stream so you don't need any special video decoder. As you have said there will be performance penalties for decoding multiple seperate streams. &#xD;&#xA;&#xD;&#xA;Something like octohedran cube maps might be a good offline way to convert 6 video streams into a single video stream while minimizing distortion. &#xD;&#xA;&#xD;&#xA;Further reading here &gt; http://www.vis.uni-stuttgart.de/~engelhts/paper/vmvOctaMaps.pdf&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14776" PostHistoryTypeId="5" PostId="5430" RevisionGUID="67759cc6-3379-4741-8cbf-718d79862f67" CreationDate="2017-07-28T14:27:02.617" UserId="3073" Comment="added 91 characters in body" Text="I would be tempted to use a solution which involves decoding a single rectangular video stream so you don't need any special video decoder. As you have said there will be performance penalties for decoding multiple seperate streams. &#xD;&#xA;&#xD;&#xA;Something like octohedran cube maps might be a good offline way to convert 6 video streams into a single video stream while minimizing distortion. A relatively cheap pixel shader can be used to project the 'cube' map back to camera space.&#xD;&#xA;&#xD;&#xA;Further reading here &gt; http://www.vis.uni-stuttgart.de/~engelhts/paper/vmvOctaMaps.pdf&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14777" PostHistoryTypeId="2" PostId="5431" RevisionGUID="b20a9ac1-6c10-4250-8739-44be6941052e" CreationDate="2017-07-28T14:44:29.253" UserId="7066" Text="In the rotation matrix, you actually use trigonometric functions (i.e. sine and cosine with an independent variable known as the angle) which internally implemented by Taylor series (i.e. has some costs). With complex numbers you could avoid that by multiplying the vector (i.e. after represents it as a complex number) by a complex number that represents the rotation. For example, if you need to rotate a vector (1,0) and make it points upward (i.e. no need for an angle), you basically multiple it by a complex number $z=i$, the rotated vector is then (0,1). As you can see no trigonometric functions are being used. See the following Matlab code to perform some rotations&#xD;&#xA;&#xD;&#xA;    clear all&#xD;&#xA;    clc&#xD;&#xA;    &#xD;&#xA;    v =  1 + 0i; % vector&#xD;&#xA;    &#xD;&#xA;    z1 =  1 + 1i; % 45  rotation&#xD;&#xA;    z2 =  0 + 1i; % 90  rotation&#xD;&#xA;    z3 = -1 + 1i; % 135 rotation&#xD;&#xA;    z4 = -1 + 0i; % 180 rotation&#xD;&#xA;    z5 = -1 - 1i; % 225 rotation&#xD;&#xA;    z6 =  1 - 1i; % 270 rotation&#xD;&#xA;    &#xD;&#xA;    %rotate v1 by z deg&#xD;&#xA;    v1 = v*z6" ContentLicense="CC BY-SA 3.0" />
  <row Id="14778" PostHistoryTypeId="5" PostId="5431" RevisionGUID="436cbcd3-fca5-4846-9d4a-b2bc65151c12" CreationDate="2017-07-28T14:59:01.977" UserId="7066" Comment="added 163 characters in body" Text="In the rotation matrix, you actually use trigonometric functions (i.e. sine and cosine with an independent variable known as the angle) which internally implemented by Taylor series (i.e. has some costs). With complex numbers you could avoid that by multiplying the vector (i.e. after represents it as a complex number) by a complex number that represents the rotation. For example, if you need to rotate a vector (1,0) and make it points upward (i.e. no need for an angle), you basically multiple it by a complex number $z=i$, the rotated vector is then (0,1). As you can see no trigonometric functions are being used. See the following Matlab code to perform some rotations&#xD;&#xA;&#xD;&#xA;    clear all&#xD;&#xA;    clc&#xD;&#xA;    &#xD;&#xA;    v =  1 + 0i; % vector&#xD;&#xA;    &#xD;&#xA;    z1 =  1 + 1i; % 45  rotation&#xD;&#xA;    z2 =  0 + 1i; % 90  rotation&#xD;&#xA;    z3 = -1 + 1i; % 135 rotation&#xD;&#xA;    z4 = -1 + 0i; % 180 rotation&#xD;&#xA;    z5 = -1 - 1i; % 225 rotation&#xD;&#xA;    z6 =  1 - 1i; % 270 rotation&#xD;&#xA;    &#xD;&#xA;    %rotate v1 by z deg&#xD;&#xA;    v1 = v*z6&#xD;&#xA;&#xD;&#xA;But remember with 2D, the rotation matrix does fairly a good job however, with 3D the importance of complex numbers represented via quaternion is significant. " ContentLicense="CC BY-SA 3.0" />
  <row Id="14779" PostHistoryTypeId="2" PostId="5432" RevisionGUID="1ede2160-f480-44f9-b341-637eb65211e5" CreationDate="2017-07-28T15:02:37.380" UserId="6337" Text="I trying to highlight vertices which are on &quot;borders&quot;, imagine half of sphere for example. Also for example I added image geomtry with triangles and highlighted necessary vertices. Any ideas? Thanks&#xD;&#xA;![Graph](https://i.stack.imgur.com/o1NfK.jpg)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14780" PostHistoryTypeId="1" PostId="5432" RevisionGUID="1ede2160-f480-44f9-b341-637eb65211e5" CreationDate="2017-07-28T15:02:37.380" UserId="6337" Text="How to find vertices on borders of geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="14781" PostHistoryTypeId="3" PostId="5432" RevisionGUID="1ede2160-f480-44f9-b341-637eb65211e5" CreationDate="2017-07-28T15:02:37.380" UserId="6337" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14782" PostHistoryTypeId="2" PostId="5433" RevisionGUID="ba2bf5e0-c6d0-4f9b-a601-38b606734ed9" CreationDate="2017-07-28T15:04:02.200" UserId="5406" Text="This is more a theoretical question. I'm wondering what happens when I write float values into an empty RGBA texture of type `gl.UNSIGNED_BYTE` in WebGL 1.0. Obviously, every channel then has 8 bits. But that wouldn't be enough to represent floating point values, would it? Nevertheless it somehow works, more or less. See part of a fragment shader code here:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    &#xD;&#xA;    uniform vec2 u_Resolution;&#xD;&#xA;    &#xD;&#xA;    void main(void){&#xD;&#xA;       gl_FragColor = vec4(gl_FragCoord.xy / u_Resolution, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When I specify the texture to be of type `gl.FLOAT` (using the OES_texture_float extension), the results of course look better. But I want to know exactly why they do.&#xD;&#xA;&#xD;&#xA;In addition: does the specified precision have an effect on the texture (to be written)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14783" PostHistoryTypeId="1" PostId="5433" RevisionGUID="ba2bf5e0-c6d0-4f9b-a601-38b606734ed9" CreationDate="2017-07-28T15:04:02.200" UserId="5406" Text="What happens to float values written to UNSIGNED_BYTE texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14784" PostHistoryTypeId="3" PostId="5433" RevisionGUID="ba2bf5e0-c6d0-4f9b-a601-38b606734ed9" CreationDate="2017-07-28T15:04:02.200" UserId="5406" Text="|texture|glsl|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14785" PostHistoryTypeId="4" PostId="5429" RevisionGUID="3e84f6ca-4bde-4fca-a36b-4837d0646251" CreationDate="2017-07-28T17:13:19.933" UserId="5430" Comment="edited title" Text="A way to save 360° panorama video" ContentLicense="CC BY-SA 3.0" />
  <row Id="14786" PostHistoryTypeId="2" PostId="5434" RevisionGUID="ed64d1f1-5a4d-45a6-9a48-ddfec7ea7baa" CreationDate="2017-07-28T17:50:44.740" UserId="48" Text="Unsigned byte textures in a graphics API are usually &quot;normalized&quot;—the byte values are interpreted as ranging from 0.0 to 1.0, with a byte of 255 mapping to 1.0. So no, they aren't truly floating-point values, but the hardware will automatically convert them to/from float when you read/write the texture. If you try to write a value outside the [0, 1] range, it will be clamped.&#xD;&#xA;&#xD;&#xA;As for the `precision highp` part, it doesn't directly affect the texture, but it can certainly affect any calculations of values you write to the texture. For example, to calculate an 8-bit texture you certainly want a _minimum_ of 8 bits of mantissa precision (i.e. `lowp`)—and you _probably_ want more than that, depending on what calculations you're doing. I'd advise you to check what the actual precision levels are on your device, since they vary widely depending on what GPU you have. See [this question](https://stackoverflow.com/questions/4414041/what-is-the-precision-of-highp-floats-in-glsl-es-2-0-for-iphone-ipod-touch-ipad) for more." ContentLicense="CC BY-SA 3.0" />
  <row Id="14787" PostHistoryTypeId="2" PostId="5435" RevisionGUID="cae77a3e-85e7-4c1c-8528-a423fa174fc7" CreationDate="2017-07-28T18:04:53.583" UserId="6883" Text="I'm assuming you are rendering this object as a set of triangles. To do what you are trying to do, you will need to store all your triangles (and vertices) in some sort of buffer or list. Then, for each triangle, test if all three of its sides are matched with another triangle side. If so, it is enclosed and inside the object. Otherwise, it is outside the object. Some basic pseudo-code (I apologize for all the foreach loops :) )&#xD;&#xA;&#xD;&#xA;    foreach t in triangles:&#xD;&#xA;        all_sides_touched = True&#xD;&#xA;        foreach side_t in t:&#xD;&#xA;            this_side_touched = False&#xD;&#xA;            foreach u in triangles.exclude(t):    // run through all other triangles to test&#xD;&#xA;                foreach side_u in u:&#xD;&#xA;                    if side_t.equals(side_u):  this_side_touched = True&#xD;&#xA;            all_sides_touched = all_sides_touched and this_side_touched&#xD;&#xA;        if not all_sides_touched:&#xD;&#xA;            foreach side in t:&#xD;&#xA;                foreach point in side:&#xD;&#xA;                    // do whatever you want to do with outside vertices&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14788" PostHistoryTypeId="2" PostId="5436" RevisionGUID="607304ce-5bd8-472e-8b76-186662af2006" CreationDate="2017-07-29T06:43:44.320" UserId="7068" Text="I'm dealing with hardware that uses quads as its polygonal primitive. Not triangles. A triangle can be expressed by setting 2 of the 4 equal to each other for a degenerate quad.&#xD;&#xA;&#xD;&#xA;For the 3D engine, I'm in need of clipping for polygons outside of clip space volume in order to avoid vertex inversion and division by zero errors when performing the perspective divide.&#xD;&#xA;&#xD;&#xA;My logic is that I first identify the primitives that intersect with the 6 planes. From there I add edges to cut the primitive. What I don't understand at this point is how to cut/add quads. Do I need to &quot;triangulate&quot;, but for quads?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14789" PostHistoryTypeId="1" PostId="5436" RevisionGUID="607304ce-5bd8-472e-8b76-186662af2006" CreationDate="2017-07-29T06:43:44.320" UserId="7068" Text="Algorithm for clipping convex quadrilaterals" ContentLicense="CC BY-SA 3.0" />
  <row Id="14790" PostHistoryTypeId="3" PostId="5436" RevisionGUID="607304ce-5bd8-472e-8b76-186662af2006" CreationDate="2017-07-29T06:43:44.320" UserId="7068" Text="|3d|algorithm|geometry|mathematics|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14791" PostHistoryTypeId="5" PostId="5436" RevisionGUID="62d7a6dd-2a9e-4fba-83d7-8e0548d5b911" CreationDate="2017-07-29T06:52:07.720" UserId="7068" Comment="added 9 characters in body" Text="I'm dealing with hardware that uses quads as its polygonal primitive. Not triangles. A triangle can be expressed by setting 2 of the 4 vertices equal to each other for a degenerate quad.&#xD;&#xA;&#xD;&#xA;For the 3D engine, I'm in need of clipping for polygons outside of clip space volume in order to avoid vertex inversion and division by zero errors when performing the perspective divide.&#xD;&#xA;&#xD;&#xA;My logic is that I first identify the primitives that intersect with the 6 planes. From there I add edges to cut the primitive. What I don't understand at this point is how to cut/add quads. Do I need to &quot;triangulate&quot;, but for quads? Is it possible? Are there constraints other than the quad needing to be convex?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14792" PostHistoryTypeId="5" PostId="5436" RevisionGUID="4e389218-9589-4274-a64a-b1c1f8f3d4d2" CreationDate="2017-07-29T07:48:18.853" UserId="7068" Comment="added 256 characters in body" Text="I'm dealing with hardware that uses quads as its polygonal primitive. Not triangles. A triangle can be expressed by setting 2 of the 4 vertices equal to each other for a degenerate quad.&#xD;&#xA;&#xD;&#xA;For the 3D engine, I'm in need of clipping for polygons outside of clip space volume in order to avoid vertex inversion and division by zero errors when performing the perspective divide.&#xD;&#xA;&#xD;&#xA;My logic is that I first identify the primitives that intersect with the 6 planes. From there I add edges to cut the primitive. What I don't understand at this point is how to cut/add quads. Do I need to &quot;triangulate&quot;, but for quads? Is it possible? Are there constraints other than the quad needing to be convex?&#xD;&#xA;&#xD;&#xA;Edit: I might be over complicating this. I can't come up with a case where I get less than 4 or more than 4 vertices when clipping. The only case is when all points are outside the clipping area, all except one edge. That edge would produce a triangle." ContentLicense="CC BY-SA 3.0" />
  <row Id="14793" PostHistoryTypeId="34" PostId="5377" RevisionGUID="8e98d2fe-0768-4198-b12f-5cacb4cc8194" CreationDate="2017-07-29T11:48:03.493" UserId="-1" Comment="30" />
  <row Id="14794" PostHistoryTypeId="50" PostId="4760" RevisionGUID="7fa433ca-61a7-4cb8-ad31-d8d66e9ddcb8" CreationDate="2017-07-29T12:48:36.333" UserId="-1" />
  <row Id="14795" PostHistoryTypeId="2" PostId="5437" RevisionGUID="aecd202c-2ced-4236-9910-1f1cb6ea77ee" CreationDate="2017-07-29T17:08:59.967" UserId="5978" Text="Does anyone know who to interpolate UVs in a quad tessellation evaluation shader? I can interpolate the position easily like so :&#xD;&#xA;&#xD;&#xA;	vec4 p1 = mix(gl_in[0].gl_Position,&#xD;&#xA;			gl_in[1].gl_Position,&#xD;&#xA;			gl_TessCoord.x);&#xD;&#xA;	vec4 p2 = mix(gl_in[2].gl_Position,&#xD;&#xA;			gl_in[3].gl_Position,&#xD;&#xA;			gl_TessCoord.x);&#xD;&#xA;	gl_Position = mix(p1, p2, gl_TessCoord.y);&#xD;&#xA;&#xD;&#xA;But I can't figure out how to interpolate the incoming UV coordinates. I need to do so to pass them on to the fragment shader.&#xD;&#xA;&#xD;&#xA;With perfect quad UVs from 0 to 1, I can use `gl_TessCoord.xy`. Unfortunately that doesn't work when the UVs aren't mapped 1:1 to a texture.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14796" PostHistoryTypeId="1" PostId="5437" RevisionGUID="aecd202c-2ced-4236-9910-1f1cb6ea77ee" CreationDate="2017-07-29T17:08:59.967" UserId="5978" Text="How do you interpolate UV mapping coords in a quad tessellation evaluation shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14797" PostHistoryTypeId="3" PostId="5437" RevisionGUID="aecd202c-2ced-4236-9910-1f1cb6ea77ee" CreationDate="2017-07-29T17:08:59.967" UserId="5978" Text="|opengl|texture|glsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14798" PostHistoryTypeId="2" PostId="5438" RevisionGUID="4a92addc-34be-43b8-aac8-b77f60b43d12" CreationDate="2017-07-29T17:27:29.600" UserId="5978" Text="The problem was else-where, the same interpolation works for UV coords.&#xD;&#xA;&#xD;&#xA;	vec2 uv1 = mix(teUv[0], teUv[1], gl_TessCoord.x);&#xD;&#xA;	vec2 uv2 = mix(teUv[2], teUv[3], gl_TessCoord.x);&#xD;&#xA;	fUv = mix(uv2, uv1, gl_TessCoord.y);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14799" PostHistoryTypeId="5" PostId="5437" RevisionGUID="dcb6a194-319f-42ab-86e7-7220387667db" CreationDate="2017-07-29T17:27:43.380" UserId="5978" Comment="edited body" Text="Does anyone know who to interpolate UVs in a quad tessellation evaluation shader? I can interpolate the position easily like so :&#xD;&#xA;&#xD;&#xA;	vec4 p1 = mix(gl_in[0].gl_Position,&#xD;&#xA;			gl_in[1].gl_Position,&#xD;&#xA;			gl_TessCoord.x);&#xD;&#xA;	vec4 p2 = mix(gl_in[2].gl_Position,&#xD;&#xA;			gl_in[3].gl_Position,&#xD;&#xA;			gl_TessCoord.x);&#xD;&#xA;	gl_Position = mix(p2, p1, gl_TessCoord.y);&#xD;&#xA;&#xD;&#xA;But I can't figure out how to interpolate the incoming UV coordinates. I need to do so to pass them on to the fragment shader.&#xD;&#xA;&#xD;&#xA;With perfect quad UVs from 0 to 1, I can use `gl_TessCoord.xy`. Unfortunately that doesn't work when the UVs aren't mapped 1:1 to a texture.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14800" PostHistoryTypeId="2" PostId="5439" RevisionGUID="787558ec-2b8d-484c-905f-d405b5fcaca5" CreationDate="2017-07-29T19:42:06.340" UserId="6883" Text="It looks like there are a few steps to make this work:&#xD;&#xA;&#xD;&#xA;1. Linearly interpolate the alpha of the mesh from transparent to fully opaque, or vice versa. &#xD;&#xA;* _Note 1: It seems as if the alpha starts to fade a few seconds after the effect has started._&#xD;&#xA;* _Note 2: The alpha of the &quot;effect meshes&quot; (covered in #2 and #3) should be changed independently of the original mesh. This will help produce the desired effect._&#xD;&#xA;2. Generate (just the color buffer for) a mesh with identical vertices, but make the color blue or green. The brightness of each vertice's/triangle's color should be calculated using either **random noise** (i.e. using a random number generator), or **[Perlin Noise](https://en.wikipedia.org/wiki/Perlin_noise)**; or a combination of the two. For the flashing effect, it would be best to regenerate the mesh each frame (with a different noise seed, if using Perlin Noise). Next, calculate a weighted average between the colors of this &quot;effect mesh&quot; and the those of the original mesh, according to how much time has passed. For instance, assuming `t` is the percentage of the way through the effect that has passed; at `t=0`, make the color buffer `0*effect_mesh + 1*original_mesh`; and at `t=0.3`, make the color buffer `0.3*effect_mesh + 0.7*original_mesh`.&#xD;&#xA;3. For the vertical line effect, think about ray-tracing all the vertices (using multiple vertical rays). If a vertex is hit, make that vertex's color lighter/darker. This effect would be best done with a weighted average also, according to the time (since the lines are stronger towards the beginning).&#xD;&#xA;&#xD;&#xA;*** Although this &quot;Star Trek&quot; effect varies from scene to scene, you should order these effects; don't do them all at the same time." ContentLicense="CC BY-SA 3.0" />
  <row Id="14801" PostHistoryTypeId="2" PostId="5440" RevisionGUID="bad73bcf-64fe-4300-a16a-bafac3588aa0" CreationDate="2017-07-30T03:42:25.000" UserId="5944" Text="Monte Carlo rendering is just a process of sampling and reconstruction to evaluate the rendering equation.&#xD;&#xA;&#xD;&#xA;Why is it called noise rather than error?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14802" PostHistoryTypeId="1" PostId="5440" RevisionGUID="bad73bcf-64fe-4300-a16a-bafac3588aa0" CreationDate="2017-07-30T03:42:25.000" UserId="5944" Text="What's the nature of Monte Carlo noise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14803" PostHistoryTypeId="3" PostId="5440" RevisionGUID="bad73bcf-64fe-4300-a16a-bafac3588aa0" CreationDate="2017-07-30T03:42:25.000" UserId="5944" Text="|raytracing|rendering|monte-carlo|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14807" PostHistoryTypeId="2" PostId="5442" RevisionGUID="678c1b6f-1ca7-4927-9832-09960c94ef86" CreationDate="2017-07-30T16:49:21.710" UserId="7072" Text="I am trying to create an effect where a bumpy billboarded texture is illuminated by a emission map that is also billboarded but is logically closer to the camera in 3D space. &#xA;&#xA;In this way a blue light would be represented by a blue circle drawn on the emission map with transparency representing the brightness of the light. &#xA;&#xA;The light would then illuminate the bumpy texture in the back. Because the texture is bumpy (due to a bump map) the lights might cast slight shadows and unequally light the surface.&#xA;&#xA;I have no clue how to go about achieving this as I am unsure of the math involved in getting a bump map to play well with an emission map. Furthermore i am having difficulty finding a good tutorial or piece of code that represents emission maps that actually cast light onto other objects as if they were comprised of point lights.&#xA;&#xA;Do you have any pointers that might help me get started? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14808" PostHistoryTypeId="1" PostId="5442" RevisionGUID="678c1b6f-1ca7-4927-9832-09960c94ef86" CreationDate="2017-07-30T16:49:21.710" UserId="7072" Text="Emission maps that interact with a bump map" ContentLicense="CC BY-SA 3.0" />
  <row Id="14809" PostHistoryTypeId="3" PostId="5442" RevisionGUID="678c1b6f-1ca7-4927-9832-09960c94ef86" CreationDate="2017-07-30T16:49:21.710" UserId="7072" Text="|texture|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14810" PostHistoryTypeId="2" PostId="5443" RevisionGUID="6fe8ee1d-3b92-488d-b930-78880c342269" CreationDate="2017-07-31T05:14:07.903" UserId="7076" Text="This link says [iPhoneGLU][1] says, this libraray supports below futures.&#xD;&#xA;&#xD;&#xA;Matrix manipulation&#xD;&#xA;Polygon tessellation&#xD;&#xA;&#xD;&#xA;I would like to know whether I can use this library to draw primitives(lines,points,triangles,simple polygon).&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://code.google.com/archive/p/iphone-glu/" ContentLicense="CC BY-SA 3.0" />
  <row Id="14811" PostHistoryTypeId="1" PostId="5443" RevisionGUID="6fe8ee1d-3b92-488d-b930-78880c342269" CreationDate="2017-07-31T05:14:07.903" UserId="7076" Text="iPhone GLU(OpenGL Utility Library)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14812" PostHistoryTypeId="3" PostId="5443" RevisionGUID="6fe8ee1d-3b92-488d-b930-78880c342269" CreationDate="2017-07-31T05:14:07.903" UserId="7076" Text="|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14816" PostHistoryTypeId="2" PostId="5445" RevisionGUID="b684a7a2-f532-4114-9d7c-cf4c409a7e72" CreationDate="2017-07-31T07:57:01.183" UserId="7059" Text="In your case, I don't think a pre-processing is necessary. You may find the [Hough transform useful][1] in your case.&#xD;&#xA;&#xD;&#xA;Since your image is big, it can be difficult to have a straight line due to the noise and blur.&#xD;&#xA;&#xD;&#xA;This is what I got using a sobel contour detection with a smaller version of your image.&#xD;&#xA;&#xD;&#xA;This is maybe a good start to use a line detection algorithm.&#xD;&#xA;&#xD;&#xA;[![Input image after resizing and sobel contour detection][2]][2]&#xD;&#xA;&#xD;&#xA;A second solution would be to use color segmentation. If you assume that your screen would always have black border you can work something in the [L*A*b][3] or [HSV][4] color space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Hough_transform&#xD;&#xA;  [2]: https://i.stack.imgur.com/eAVQh.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Lab_color_space&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/HSL_and_HSV" ContentLicense="CC BY-SA 3.0" />
  <row Id="14818" PostHistoryTypeId="2" PostId="5447" RevisionGUID="7c7d5314-e25c-4cfd-ba1d-11f0d31f6bd5" CreationDate="2017-08-01T06:15:26.000" UserId="7008" Text="I am writing an OpenSceneGraph based program that uses two cameras, one to render the preview for the user and one that uses a callback to make screenshots with MRT. The exporter camera is using an orthographic projection and always from the same position with the same view and up vector, whereas the preview camera can be moved by the user (which is why I use two cameras rather than one for both tasks).&#xD;&#xA;&#xD;&#xA;Upon starting the program, I create the preview camera, add the shaders to it, then set up the viewer and add the preview camera to the viewer.&#xD;&#xA;&#xD;&#xA;Afterwards I create the export camera, add its shaders, textures and callback and then I add the export camera as a child to the preview camera. Up to this point, nothing has been rendered (i.e. no `frame` call has been made).&#xD;&#xA;&#xD;&#xA;The `addChild` call is issued (i.e. the break point is reached in Visual Studio, and stepping further I can see that the exporter camera is now a child of the preview camera). However, once I issue a command to actually make a screenshot, the exporter camera is not the child of the preview camera anymore (by now, a few render calls have been made). &#xD;&#xA;&#xD;&#xA;Why is this, and how can I fix it apart from adding the exporter camera again?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14819" PostHistoryTypeId="1" PostId="5447" RevisionGUID="7c7d5314-e25c-4cfd-ba1d-11f0d31f6bd5" CreationDate="2017-08-01T06:15:26.000" UserId="7008" Text="Why does the camera not remain child of the other camera after adding it in osg?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14820" PostHistoryTypeId="3" PostId="5447" RevisionGUID="7c7d5314-e25c-4cfd-ba1d-11f0d31f6bd5" CreationDate="2017-08-01T06:15:26.000" UserId="7008" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14822" PostHistoryTypeId="2" PostId="5449" RevisionGUID="701d8387-8f03-439b-b6be-860771610a00" CreationDate="2017-08-01T13:39:13.580" UserId="6838" Text="I've been looking up this question on the internet for a while, and I haven't been very successful, so I decided I'll ask it here. Should I apply tone mapping before gamma correction, gamma correction before tone mapping, or should I just use one or the other?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14823" PostHistoryTypeId="1" PostId="5449" RevisionGUID="701d8387-8f03-439b-b6be-860771610a00" CreationDate="2017-08-01T13:39:13.580" UserId="6838" Text="Tone Mapping &amp; Gamma Correction" ContentLicense="CC BY-SA 3.0" />
  <row Id="14824" PostHistoryTypeId="3" PostId="5449" RevisionGUID="701d8387-8f03-439b-b6be-860771610a00" CreationDate="2017-08-01T13:39:13.580" UserId="6838" Text="|rendering|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14825" PostHistoryTypeId="2" PostId="5450" RevisionGUID="6d06987c-d55a-49d2-b871-f51cc9178c6d" CreationDate="2017-08-01T14:29:07.837" UserId="7059" Text="A close solution would be like https://stackoverflow.com/questions/11779797/how-to-detect-border-vertices-of-an-open-mesh-3d-model&#xD;&#xA;&#xD;&#xA;For edge, you test in the edge is connected to at least 2 triangles. If it is not the case, the edge is a border under the assumption that the mesh is a manifold." ContentLicense="CC BY-SA 3.0" />
  <row Id="14826" PostHistoryTypeId="2" PostId="5451" RevisionGUID="2ee35db4-8ea4-4d61-9e1f-d73d15d8684a" CreationDate="2017-08-01T14:37:22.093" UserId="7008" Text="This depends on your calculations really, since you can do it either way. However, probably when you reach tone mapping you will be in linear space (i.e. no gamma correction has been done yet and you don't assume non-linear space for your calculations).&#xD;&#xA;Assuming this, gamma correction should be applied after tone mapping, otherwise you have &quot;linear&quot; tone mapping on non-linear color values.&#xD;&#xA;&#xD;&#xA;To quote from Real-Time Rendering 3rd by Möller, Haines and Hoffman, p. 145:&#xD;&#xA;&#xD;&#xA;&gt; It is important to apply the conversion at the final stage of rendering (when the values are written to the display buffer for the last time), and not before. If post-processing is applied after gamma correction, post-processing effects will be computed in nonlinear space, which is incorrect and will often cause visible artifacts. So operations such as tone mapping [...] can be applied to images to adjust luminance balance, but gamma corection should always be done last." ContentLicense="CC BY-SA 3.0" />
  <row Id="14827" PostHistoryTypeId="5" PostId="5439" RevisionGUID="d2751253-fe48-4a74-a9cc-b4ac91c0c491" CreationDate="2017-08-01T18:40:09.653" UserId="6883" Comment="added 19 characters in body" Text="It looks like there are a few steps to make this work:&#xD;&#xA;&#xD;&#xA;1. Linearly interpolate the alpha of the mesh from transparent to fully opaque, or vice versa. &#xD;&#xA;* _Note 1: It seems as if the alpha starts to fade a few seconds after the effect has started._&#xD;&#xA;* _Note 2: The alpha of the &quot;effect meshes&quot; (covered in #2 and #3) should be changed independently of the original mesh. This will help produce the desired effect._&#xD;&#xA;2. Generate (just the color buffer for) a mesh with identical vertices, but make the color blue or green. The brightness of each vertice's/triangle's color should be calculated using either **random noise** (i.e. using a random number generator), or **[Perlin Noise](https://en.wikipedia.org/wiki/Perlin_noise)**; or a combination of the two. For the flashing effect, it would be best to regenerate the mesh each frame (with a different noise seed, if using Perlin Noise). Next, calculate a weighted average between the colors of this &quot;effect mesh&quot; and the those of the original mesh, according to how much time has passed. For instance, assuming `t` is the percentage of the way through the effect that has passed; at `t=0`, make the color buffer `0*effect_mesh + 1*original_mesh`; and at `t=0.3`, make the color buffer `0.3*effect_mesh + 0.7*original_mesh`.&#xD;&#xA;3. For the vertical line effect, think about ray-tracing all the vertices (using multiple vertical rays). If a vertex is hit by (or near) a ray, make that vertex's color lighter/darker. This effect would be best done with a weighted average also, according to the time (since the lines are stronger towards the beginning).&#xD;&#xA;&#xD;&#xA;*** Although this &quot;Star Trek&quot; effect varies from scene to scene, you should order these effects; don't do them all at the same time." ContentLicense="CC BY-SA 3.0" />
  <row Id="14833" PostHistoryTypeId="2" PostId="5452" RevisionGUID="66e99bab-409a-4b71-bfbb-1c1c71955953" CreationDate="2017-08-02T08:13:34.223" UserId="6951" Text="I finally arrived at a solution that is not perfect, but seems to be good enough for my application right now.&#xD;&#xA;&#xD;&#xA;The pipeline is as follows:&#xD;&#xA;&#xD;&#xA;    grayscale perlin noise with affine transformed (stretched and rotated) coordinate system&#xD;&#xA;    -&gt; gaussian blur (sigma 3.0)&#xD;&#xA;    -&gt; normalize (range 0.0 to 1.0)&#xD;&#xA;    -&gt; pixels = pixels - 0.5&#xD;&#xA;    -&gt; pixels = pixels * 2&#xD;&#xA;    -&gt; threshold (change everything below 0 to 0)&#xD;&#xA;    -&gt; add pixels to original image with an alpha value of 0.7&#xD;&#xA;&#xD;&#xA;Here are some of the results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Sygqn.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7BQSL.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/oFSyv.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/Bime8.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/yY1Ds.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14834" PostHistoryTypeId="50" PostId="4651" RevisionGUID="44627d50-0471-4f23-b54d-d4f7bc4dc16f" CreationDate="2017-08-02T11:07:06.543" UserId="-1" />
  <row Id="14835" PostHistoryTypeId="2" PostId="5453" RevisionGUID="c11c94f8-af36-43a2-bd91-87657af8dafe" CreationDate="2017-08-02T14:14:18.357" UserId="7028" Text="I would like implement physically based rendering, following [this tutorial][1]&#xD;&#xA;&#xD;&#xA;I was able to find a [list of light sources ordered by lumens][2], but I have no idea how to use it in the calculations.&#xD;&#xA;&#xD;&#xA;    float attenuation = 1.0 / (distance * distance);&#xD;&#xA;    vec3 radiance = lightColor * attenuation;&#xD;&#xA;&#xD;&#xA;What should the `lightColor` be, if the light source is a 60W lightbulb (780 lm) and in my scene one unit is one cm?&#xD;&#xA;&#xD;&#xA;How should I define the `radiance`, if I have a directional light, for example the sun?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/#!PBR/Lighting&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Orders_of_magnitude_(luminous_flux)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14836" PostHistoryTypeId="1" PostId="5453" RevisionGUID="c11c94f8-af36-43a2-bd91-87657af8dafe" CreationDate="2017-08-02T14:14:18.357" UserId="7028" Text="How to calculate attenuation and radiance in PBR? (point and directional lights)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14837" PostHistoryTypeId="3" PostId="5453" RevisionGUID="c11c94f8-af36-43a2-bd91-87657af8dafe" CreationDate="2017-08-02T14:14:18.357" UserId="7028" Text="|opengl|lighting|physically-based|pbr|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14838" PostHistoryTypeId="2" PostId="5454" RevisionGUID="f3c6f80b-0a82-40be-98f6-051a14f3e97f" CreationDate="2017-08-02T14:32:12.343" UserId="7096" Text="Most 3D video games since the nineties have used hardware rendering based on polygons. Why polygons? They work well for some things, but not so well for others, e.g. a human figure rendered in polygons looks bad unless the polygon count is very large. I'm guessing it's because they work better for hardware rendering, which is best at doing very simple operations very many times. (Modern graphics cards may be more flexible, but the industry pretty much settled on polygons a long time ago.)&#xD;&#xA;&#xD;&#xA;Suppose you want to write a software rendering game engine (let's say because your target hardware has a fast CPU but a very weak graphics chip). Would polygons still be the way to go?&#xD;&#xA;&#xD;&#xA;Conjecture: if you are going to render software, it's better to play to strengths and use more complex primitives, in particular curved shapes.&#xD;&#xA;&#xD;&#xA;Is this correct? If so, are there any known results regarding what kind of curve primitives should be used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14839" PostHistoryTypeId="1" PostId="5454" RevisionGUID="f3c6f80b-0a82-40be-98f6-051a14f3e97f" CreationDate="2017-08-02T14:32:12.343" UserId="7096" Text="Polygons versus curve primitives in software rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="14840" PostHistoryTypeId="3" PostId="5454" RevisionGUID="f3c6f80b-0a82-40be-98f6-051a14f3e97f" CreationDate="2017-08-02T14:32:12.343" UserId="7096" Text="|rendering|polygon|rasterizer|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14841" PostHistoryTypeId="5" PostId="5454" RevisionGUID="f944fe39-984e-48df-9020-2b2405b321bd" CreationDate="2017-08-02T14:56:37.857" UserId="7096" Comment="typo" Text="Most 3D video games since the nineties have used hardware rendering based on polygons. Why polygons? They work well for some things, but not so well for others, e.g. a human figure rendered in polygons looks bad unless the polygon count is very large. I'm guessing it's because they work better for hardware rendering, which is best at doing very simple operations very many times. (Modern graphics cards may be more flexible, but the industry pretty much settled on polygons a long time ago.)&#xD;&#xA;&#xD;&#xA;Suppose you want to write a software rendering game engine (let's say because your target hardware has a fast CPU but a very weak graphics chip). Would polygons still be the way to go?&#xD;&#xA;&#xD;&#xA;Conjecture: if you are going to render in software, it's better to play to strengths and use more complex primitives, in particular curved shapes.&#xD;&#xA;&#xD;&#xA;Is this correct? If so, are there any known results regarding what kind of curve primitives should be used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14842" PostHistoryTypeId="2" PostId="5455" RevisionGUID="bae39016-aec7-4ebb-a58a-de7dc0895ab8" CreationDate="2017-08-02T15:41:39.987" UserId="38" Text="Most software rendering engines dice the parametric primitives to micropolygons, usually on the fly as needed. In essence this reduces the needed complexity to determine intersections. The surface will still look smooth, since each polygon is smaller than a pixel.&#xD;&#xA;&#xD;&#xA;This allows for &#xD;&#xA;&#xD;&#xA;* Data caching.&#xD;&#xA;* Discrete geometric derivates.&#xD;&#xA;* Displacement is easy to implement.&#xD;&#xA;* Same rendering code to be used on most primitive types.&#xD;&#xA;&#xD;&#xA;[![micropolygon render of trimmed NURBS][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Micropolygon render of trimmed NURBS surfaces usin Renderman from 2003. No polygon is visible as each sample gets more or less a separate polygon.&#xD;&#xA;&#xD;&#xA;But yes it is possible to use iteration method to solve surfaces from implicit formulations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XTfti.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14843" PostHistoryTypeId="5" PostId="5455" RevisionGUID="d20d8e1b-105e-4b5f-b172-cd91d22f25b6" CreationDate="2017-08-02T15:49:42.180" UserId="38" Comment="added 155 characters in body" Text="Most software rendering engines dice the parametric primitives to micropolygons, usually on the fly as needed. In essence this reduces the needed complexity to determine intersections. The surface will still look smooth, since each polygon is smaller than a pixel.&#xD;&#xA;&#xD;&#xA;This allows for &#xD;&#xA;&#xD;&#xA;* Data caching.&#xD;&#xA;* Discrete geometric derivates.&#xD;&#xA;* Displacement is easy to implement.&#xD;&#xA;* Same rendering code to be used on most primitive types.&#xD;&#xA;&#xD;&#xA;[![micropolygon render of trimmed NURBS][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Micropolygon render of trimmed NURBS surfaces using Renderman from 2003. No polygon is visible as each sample gets more or less a separate polygon.&#xD;&#xA;&#xD;&#xA;But yes it is possible to use iteration method to solve surfaces from implicit formulations. It is typically used in raymarching contexts. The entire render engine could work by doing this its essentially a tradeof between memory and computation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XTfti.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14845" PostHistoryTypeId="5" PostId="5452" RevisionGUID="cf0f3c25-a214-474d-bd08-896a72144586" CreationDate="2017-08-03T07:51:12.020" UserId="6951" Comment="added 3 characters in body" Text="I finally arrived at a solution that is not perfect, but seems to be good enough for my application right now.&#xD;&#xA;&#xD;&#xA;The pipeline is as follows:&#xD;&#xA;&#xD;&#xA;    -&gt; grayscale perlin noise with affine transformed (stretched and rotated) coordinate system&#xD;&#xA;    -&gt; gaussian blur (sigma 3.0)&#xD;&#xA;    -&gt; normalize (range 0.0 to 1.0)&#xD;&#xA;    -&gt; pixels = pixels - 0.5&#xD;&#xA;    -&gt; pixels = pixels * 2&#xD;&#xA;    -&gt; threshold (change everything below 0 to 0)&#xD;&#xA;    -&gt; add pixels to original image with an alpha value of 0.7&#xD;&#xA;&#xD;&#xA;Here are some of the results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Sygqn.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7BQSL.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/oFSyv.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/Bime8.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/yY1Ds.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14846" PostHistoryTypeId="2" PostId="5456" RevisionGUID="59159ac3-4a7c-481d-8e6e-162e78b8e21b" CreationDate="2017-08-03T09:46:45.640" UserId="7008" Text="&gt; How should I define the `radiance`, if I have a directional light, for example the sun?&#xD;&#xA;&#xD;&#xA;The radiance in physics has different definitions in different books. I will use the definition with irradiance and radiant flux here.&#xD;&#xA;&#xD;&#xA;Imagine photons having some energy Q. Your **radiant flux** Phi is the amount of energy Q (and therefore the amount of photons) per unit time t. To get the energy for an instant (an infinitesimally short time), you use the change (DELTA) of energy over the change of time for lim_t-&gt;0 i.e. `Phi = lim_t-&gt;0 DELTA Q/DELTA t = dQ/dt`&#xD;&#xA;Energy is measured in Joules, therefore radiant flux is measured in `J/s`.&#xD;&#xA;&#xD;&#xA;This however doesn't say anything about the surface you're measuring the energy at, but if you want to light an object, that needs to be taken into account.&#xD;&#xA;Therefore, you define **irradiance** E as your radiant flux per area A (note that irradiance usually means energy arriving atan area, whereas *radiosity* is energy leaving the area, but is otherwise defined exactly the same way). Since some integrations later on are easier to do with infinitesimally small area patches, we go that route again, but I will not rewrite the limes stuff all the time. `E = dPhi/dA`&#xD;&#xA;Note that it is assumed, that the photons' traveling direction is assumed to be perpendicular to the surface.&#xD;&#xA;Irradiance is thus measured in `J/(s*m^2)`.&#xD;&#xA;&#xD;&#xA;To understand radiance, you need to understand solid angles. I will just assume that you do, otherwise read up on it, this is really an important concept for physically based lighting.&#xD;&#xA;&#xD;&#xA;The problem with irradiance is, that you cannot take into consideration any directionality of the light. The directionality can be expressed through solid angles omega, where an infinitesimally small solid angle domega can be seen as a vector.&#xD;&#xA;Imagine that you have a sheet of paper parallel to another sheet of paper, one emitting and one receiving light, both equal in size. You can express all you need with irradiance. Now let the imitting sheet of paper transform into your light bulb centered at where the emitting sheet of paper was before. All of a sudden, it makes a difference, if you measure the light at the corners of the receiving sheet of paper or at its center.&#xD;&#xA;&#xD;&#xA;Therefore, to take directionality into account, you define **radiance** L as the irradiance per solid angle of the light. omega is the solid angle and we want to use the infinitessimally small one again, thus domega. `L = dE/domega`&#xD;&#xA;Thus your radiance is measured in `J/(s*m^2*sr)` where sr is the solid angle unit steradians and really is dimensionles. &#xD;&#xA;&#xD;&#xA;Looking at the definitions of Watts it's `W = J/s` , therefore radiance measurement can be seen as `W/(m^2*sr)`.&#xD;&#xA;&#xD;&#xA;&gt; What should the `lightColor` be, if the light source is a 60W lightbulb (780 lm) and in my scene one unit is one cm?&#xD;&#xA;&#xD;&#xA;Light usually uses different wave lengths lambda which determine the color of the light. For example, imagine a photon of red light, i.e. lambda=700nm , then it has the energy of h*c/lambda where h is Planck's constant and c is the speed of light, leading to about 2.838*10^-19 J for this red photon.&#xD;&#xA;&#xD;&#xA;If your light bulb &quot;uses&quot; just one single wave length and is a 60W(=60J/s) light bulb, then you can calculate the energy, radiant flux, irradiance and finally radiance... However, that is probably not really what you are looking for.&#xD;&#xA;Therefore, your (or rather the tutorials code) to calculate radiance is an oversimplified (and really probably more useful) of modeling the lightsource, but it does not directly relate to the physics model used in BRDFs and therefore you can't just convert your 60W lightbulb (or the sun) into the radiance you're looking for.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What the tutorial is asking you to do is to think of the color you want your light to be, and write down the RGB value for it. If your light is just white, use an RGB value of (1,1,1), try it in your scene and if you then think it's too bright, lower the values until you're satisfied (or increase them, if it's not bright enough).&#xD;&#xA;&#xD;&#xA;If you want to use the physically based light bulb, then you will need to take more into account and I'd really advice you to read up on this with a book like Physically Based Rendering (by Matt Pharr et al.). &#xD;&#xA;&#xD;&#xA;On a side note, the sun is usually modeled as being so distant to the receiver of the light, that you don't take attenuation into account. Thus you would just multiply by the light color (or set the attenuation to 1).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14850" PostHistoryTypeId="2" PostId="5458" RevisionGUID="65977e2f-1761-4d9d-b7ab-77a5d4a027de" CreationDate="2017-08-03T15:49:16.160" UserId="6883" Text="I am writing a large 3D game in Java with OpenGL. &#xD;&#xA;###Question #1&#xD;&#xA;As of now, I am rendering my 3D objects using a `Model` class that I defined. This class contains vertex, color, model matrix, code (a custom attribute I defined), and index arrays. I defined a method `addModels` that can concatenate an array of `Model` instances into a new, larger `Model` (it concatenates all the attribute arrays using `System.arraycopy`). For instance, to draw a forest; for every tree, I create a `Model`; and at the end I combine them all into one forest `Model`, which I render. This procedure is a very _object-oriented_ way of doing it, and consists of fitting together many bundles of attribute arrays into larger ones.&#xD;&#xA;Simple example code:&#xD;&#xA;    &#xD;&#xA;    Model[] models = new Model[trees.length];&#xD;&#xA;    for (int i=0; i&lt;trees.length; i++) {&#xD;&#xA;        models[i] = getTreeModel(trees[i]);&#xD;&#xA;    }&#xD;&#xA;    Model result = addModels(models);&#xD;&#xA;    return result;&#xD;&#xA;&#xD;&#xA;However, this procedure may be bad practice memory-wise, since I create _many_ `Model` instances per frame. (Nonetheless, I read in [this answer](https://softwareengineering.stackexchange.com/a/149569/279723) that objects do not take much memory.) **Would it be better practice to lean towards a more _data-oriented_ approach; like first declaring large attribute arrays (vertex, color, etc.), and creating them individually?** Simple example code:&#xD;&#xA;    &#xD;&#xA;    float[] vertices, colors;&#xD;&#xA;    for (int i=0; i&lt;trees.length; i++) {&#xD;&#xA;        float[] treeVertices = getTreeVertices(trees[i]),&#xD;&#xA;                treeColors = getTreeColors(trees[i]);&#xD;&#xA;        // copy treeVertices into vertices, and treeColors into colors at appropriate positions&#xD;&#xA;    }&#xD;&#xA;    return new Model(vertices, colors);&#xD;&#xA;_Please note that either option results in_ one _model that is going to be rendered finally._&#xD;&#xA;&#xD;&#xA;Are there any better ways of doing this?&#xD;&#xA;&#xD;&#xA;###Question #2&#xD;&#xA;When I render a `Model`, I convert each attribute array into an attribute buffer (e.g. `float[]` into `FloatBuffer`). Would it make my game run faster to, first, load data into a buffer without using the array at all? (I'm using arrays because they're easier for me to manipulate.) &#xD;&#xA;&#xD;&#xA;###Question #3&#xD;&#xA;Would it be more efficient to call `glBufferSubData` then to concatenate all the attribute arrays into longer ones and then call `glBufferData` (or a similar method)?&#xD;&#xA;&#xD;&#xA;###Question #4&#xD;&#xA;[One tutorial](https://learnopengl.com/#!Model-Loading/Model) I read defined a `Model` class as containing multiple `Mesh`s. _Then, they drew each mesh separately to the screen._ Is this good practice if I have a lot of meshes (trees) per model (forest)? I heard it isn't good to make a lot of `glDraw*` calls." ContentLicense="CC BY-SA 3.0" />
  <row Id="14851" PostHistoryTypeId="1" PostId="5458" RevisionGUID="65977e2f-1761-4d9d-b7ab-77a5d4a027de" CreationDate="2017-08-03T15:49:16.160" UserId="6883" Text="Most efficient way to render many OO meshes in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="14852" PostHistoryTypeId="3" PostId="5458" RevisionGUID="65977e2f-1761-4d9d-b7ab-77a5d4a027de" CreationDate="2017-08-03T15:49:16.160" UserId="6883" Text="|opengl|mesh|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14853" PostHistoryTypeId="2" PostId="5459" RevisionGUID="c358a5cd-b0ef-4cf3-8620-b8ff1c772e54" CreationDate="2017-08-03T16:07:23.753" UserId="137" Text="Don't copy around huge chunks of data if you don't have to.&#xD;&#xA;&#xD;&#xA;I would delay collecting and building the final forest mesh for as long as possible.&#xD;&#xA;&#xD;&#xA;However when you have multiple of the same mesh that just needs to be translated and rotated a bit you can use instancing. Which lets you draw thousands of copies of a tree with a single draw call.&#xD;&#xA;&#xD;&#xA;The most efficient way of getting data to the gpu is to map the buffer and fill that. In java that means using a Buffer." ContentLicense="CC BY-SA 3.0" />
  <row Id="14854" PostHistoryTypeId="2" PostId="5460" RevisionGUID="d9ed834b-ad94-4a4f-acb6-3a05a8f5fb75" CreationDate="2017-08-03T20:22:18.907" UserId="20501" Text="I was told that human's visual sharpness is 60 pixels per degree. As such, pixel per inch is approximately given by:&#xD;&#xA;&#xD;&#xA;    PPI = 1/ (Distance * tg((1/60*pi/180) )&#xD;&#xA;&#xD;&#xA;Is this formula fully correct? (I saw similar, but slightly different versions). How is this formula derived? Maybe some step by step description?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14855" PostHistoryTypeId="1" PostId="5460" RevisionGUID="d9ed834b-ad94-4a4f-acb6-3a05a8f5fb75" CreationDate="2017-08-03T20:22:18.907" UserId="20501" Text="human visual: relation of Distance and DPI" ContentLicense="CC BY-SA 3.0" />
  <row Id="14856" PostHistoryTypeId="3" PostId="5460" RevisionGUID="d9ed834b-ad94-4a4f-acb6-3a05a8f5fb75" CreationDate="2017-08-03T20:22:18.907" UserId="20501" Text="|computational-geometry|2d|pixel-graphics|pixels|human-vision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14857" PostHistoryTypeId="6" PostId="5460" RevisionGUID="111d20d0-4bcb-4387-8f6b-bba88aac1425" CreationDate="2017-08-03T20:43:23.373" UserId="20501" Comment="edited tags" Text="|computational-geometry|maths|pixel-graphics|pixels|human-vision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14858" PostHistoryTypeId="2" PostId="5461" RevisionGUID="aeab61a1-5759-4fc4-a080-697fceca9e0d" CreationDate="2017-08-04T15:43:36.317" UserId="38" Text="According to a review by Legge &amp; Bigelow the arc or degrees of visual angle (A) is,&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;A = 57.3 \times S/D,&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where S is height of object and D is distance to object. \[1] $S/D$ is the small angles approximation of $2 \times arctan(S/2D)$ which follows form geometry.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: the equation comes straight from trigonometric definitions.&#xD;&#xA;&#xD;&#xA;Since humans continuously scan the page with the fovea, small angles assumption is a good approximation for entire pages. The factor $57.3$ is simply $180/\pi$ or conversion form radians to angles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So given that we do not know the nature of $tg$, then its hard to say. But the formula is somewhat plausible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\[1] G. Legge &amp; C Bigelow. 2011. Jornal of vision. [Does print size matter for reading? A review of findings from vision science and typography](http://jov.arvojournals.org/article.aspx?articleid=2191906). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/168C3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14859" PostHistoryTypeId="5" PostId="5461" RevisionGUID="5eb401f9-0dea-4b1f-aca7-b683ce0093fd" CreationDate="2017-08-04T15:48:47.340" UserId="38" Comment="added 12 characters in body" Text="According to a review by Legge &amp; Bigelow the arc or degrees of visual angle ($\alpha$) is,&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\alpha = 57.3 \times S/D,&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where S is height of object and D is distance to object. \[1] $S/D$ is the small angles approximation of $2 \times arctan(S/2D)$ which follows form geometry.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: the equation comes straight from trigonometric definitions.&#xD;&#xA;&#xD;&#xA;Since humans continuously scan the page with the fovea, small angles assumption is a good approximation for entire pages. The factor $57.3$ is simply $180/\pi$ or conversion form radians to angles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So given that we do not know the nature of $tg$, then its hard to say. Looks a bit fishy, but if tg is some sort of inversion of S then its plausible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\[1] G. Legge &amp; C Bigelow. 2011. Jornal of vision. [Does print size matter for reading? A review of findings from vision science and typography](http://jov.arvojournals.org/article.aspx?articleid=2191906). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/168C3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14860" PostHistoryTypeId="5" PostId="5456" RevisionGUID="2a811cae-5a83-4a05-a2f4-206669e8fd92" CreationDate="2017-08-04T16:34:18.217" UserId="7008" Comment="corrected a stupid thinking error which made my conclusion false." Text="&gt; How should I define the `radiance`, if I have a directional light, for example the sun?&#xD;&#xA;&#xD;&#xA;The radiance in physics has different definitions in different books. I will use the definition with irradiance and radiant flux here.&#xD;&#xA;&#xD;&#xA;Imagine photons having some energy Q. Your **radiant flux** Phi is the amount of energy Q (and therefore the amount of photons) per unit time t. To get the energy for an instant (an infinitesimally short time), you use the change (DELTA) of energy over the change of time for lim_t-&gt;0 i.e. `Phi = lim_t-&gt;0 DELTA Q/DELTA t = dQ/dt`&#xD;&#xA;Energy is measured in Joules, therefore radiant flux is measured in `J/s`.&#xD;&#xA;&#xD;&#xA;This however doesn't say anything about the surface you're measuring the energy at, but if you want to light an object, that needs to be taken into account.&#xD;&#xA;Therefore, you define **irradiance** E as your radiant flux per area A (note that irradiance usually means energy arriving atan area, whereas *radiosity* is energy leaving the area, but is otherwise defined exactly the same way). Since some integrations later on are easier to do with infinitesimally small area patches, we go that route again, but I will not rewrite the limes stuff all the time. `E = dPhi/dA`&#xD;&#xA;Note that it is assumed, that the photons' traveling direction is assumed to be perpendicular to the surface.&#xD;&#xA;Irradiance is thus measured in `J/(s*m^2)`.&#xD;&#xA;&#xD;&#xA;To understand radiance, you need to understand solid angles. I will just assume that you do, otherwise read up on it, this is really an important concept for physically based lighting.&#xD;&#xA;&#xD;&#xA;The problem with irradiance is, that you cannot take into consideration any directionality of the light. The directionality can be expressed through solid angles omega, where an infinitesimally small solid angle domega can be seen as a vector.&#xD;&#xA;Imagine that you have a sheet of paper parallel to another sheet of paper, one emitting and one receiving light, both equal in size. You can express all you need with irradiance. Now let the imitting sheet of paper transform into your light bulb centered at where the emitting sheet of paper was before. All of a sudden, it makes a difference, if you measure the light at the corners of the receiving sheet of paper or at its center.&#xD;&#xA;&#xD;&#xA;Therefore, to take directionality into account, you define **radiance** L as the irradiance per solid angle of the light. omega is the solid angle and we want to use the infinitessimally small one again, thus domega. `L = dE/domega`&#xD;&#xA;Thus your radiance is measured in `J/(s*m^2*sr)` where sr is the solid angle unit steradians and really is dimensionles. &#xD;&#xA;&#xD;&#xA;Looking at the definitions of Watts it's `W = J/s` , therefore radiance measurement can be seen as `W/(m^2*sr)`.&#xD;&#xA;&#xD;&#xA;**Edit 04th of August 2017:**&#xD;&#xA;The radiance in the end is exactly what you calculate as a pixel's color, it is what you see. In the real world, it is wave length dependend, but of course in computer graphics it is an RGB color vector. Therefore, **you don't define radiance, you calculate it.**&#xD;&#xA;&#xD;&#xA;&gt; What should the `lightColor` be, if the light source is a 60W lightbulb (780 lm) and in my scene one unit is one cm?&#xD;&#xA;&#xD;&#xA;Light usually uses different wave lengths lambda which determine the color of the light. For example, imagine a photon of red light, i.e. lambda=700nm , then it has the energy of h*c/lambda where h is Planck's constant and c is the speed of light, leading to about 2.838*10^-19 J for this red photon.&#xD;&#xA;&#xD;&#xA;If your light bulb &quot;uses&quot; just one single wave length and is a 60W(=60J/s) light bulb, then you can calculate the energy, radiant flux, irradiance and finally radiance... If you know the exact spectral emission, you can also calculate this.&#xD;&#xA;However, that is probably not really what you are looking for.&#xD;&#xA;&#xD;&#xA;**Edited 04th of August 2017:**&#xD;&#xA;Therefore, your (or rather the tutorials code) to calculate radiance is an oversimplified way of modeling the lightsource.  It does not take into account the power of the light source directly, it is just modelled by a color vector.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What the tutorial is asking you to do is to think of the color you want your light to be, and write down the RGB value for it. If your light is just white, use an RGB value of (1,1,1), try it in your scene and if you then think it's too bright, lower the values until you're satisfied (or increase them, if it's not bright enough).&#xD;&#xA;&#xD;&#xA;**Edited 04th of August 2017:**&#xD;&#xA;If you want to use the physically based light bulb, then you will need to take more into account and I'd really advice you to read up on this.&#xD;&#xA;A good book for this is Physically Based Rendering (by Matt Pharr et al.). &#xD;&#xA;As that is expensive and takes a long time to read, you can also try to get along with some of the Physically Based Shading course materials of previous years, to be found [on the Selfshadow Blog][1]. Especially, there is some explanation on Sebastien Lagarde's [Moving Frostbite to Physically Based Rendering][2]&#xD;&#xA;&#xD;&#xA;On a side note, the sun is usually modeled as being so distant to the receiver of the light, that you don't take attenuation into account. Thus you would just multiply by the light color (or set the attenuation to 1).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/archives/&#xD;&#xA;  [2]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="14861" PostHistoryTypeId="2" PostId="5462" RevisionGUID="00617d3e-8361-465e-8551-6ebe39955ce3" CreationDate="2017-08-04T17:10:52.993" UserId="7108" Text="I am in the process of creating some software in Java for generating 3D gear geometry and saving it as an STL file. I am looking at a means of drawing the geometry so that the user can view the geometry before saving as an STL file. The intended result should appear along the lines of the following:&#xA;&#xA;[![enter image description here][1]][1]&#xA;(MeshLab)&#xA;&#xA;So far, rendering using [ray casting][2] appears to be the best way to approach this. For each pixel, a ray is extended out from the camera in the appropriate direction and its intersection with the triangles that make up the geometry is tested, keeping the closest intersection: simple in concept, doesn't mess around with unnecessary effects, and seems like it should run fast.&#xA;&#xA;My main concern is: will it render fast enough? In my program, it should be possible to rotate and pan the visualisation, and have it render on the fly. My concern stems from this: the largest screen I want to draw the visualisation on will be 1280px by 800px (although in general use it may be somewhat less than this), which means up to 1024,000 pixels need to be processed, and so an equal number of rays will be projected. In each 3D geometric part, there could easily be upward of thousands of triangular facets. That already means have to perform at least $10^9$ operations, a number similar to the order of magnitude of operations per second. Surely it appears ray-casting won't run fast enough, especially if you want to refresh the visualisation at a rate of 10Hz.&#xA;&#xA;What is done to ensure that the rendering is done quickly enough? Is it a matter of using a single ray for every 2x2, 3x3 or larger sub-array of pixels? Is an alternative algorithm to ray casting used? There certainly appears to be a solution to this, as STL visualisation software is not a new thing, with the app MeshLab and the site [viewstl.com][3] being perfectly adequate.&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/V9Szm.jpg&#xA;  [2]: https://en.m.wikipedia.org/wiki/Ray_casting&#xA;  [3]: http://viewstl.com" ContentLicense="CC BY-SA 3.0" />
  <row Id="14862" PostHistoryTypeId="1" PostId="5462" RevisionGUID="00617d3e-8361-465e-8551-6ebe39955ce3" CreationDate="2017-08-04T17:10:52.993" UserId="7108" Text="Rendering of large STL files" ContentLicense="CC BY-SA 3.0" />
  <row Id="14863" PostHistoryTypeId="3" PostId="5462" RevisionGUID="00617d3e-8361-465e-8551-6ebe39955ce3" CreationDate="2017-08-04T17:10:52.993" UserId="7108" Text="|rendering|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14864" PostHistoryTypeId="2" PostId="5463" RevisionGUID="da2c5a8f-e096-4e97-8657-ee7723a976a2" CreationDate="2017-08-04T17:55:03.860" UserId="7109" Text="Two questions which cross over maths/3D imaging/computer science. I'm trying to describe a point of view of an item in a 3d space and subsequently its rotation in a paper I'm writing. Versions I've had read have confused readers.&#xD;&#xA;&#xD;&#xA;The scene is as illustrated in the attached image - we are looking on as it were from the left-hand side of the scene.&#xD;&#xA;&#xD;&#xA; 1. How should I describe the view of the object from the eye symbol? I've termed it a &quot;thirty degree elevated front view&quot; - it's the 'front' that I think is most problematic.&#xD;&#xA; 2. Then if the object is rotated backwards along the x axis how do I describe that? I've said &quot;transformation, specifically a rotation seventy degrees backwards along the x axis&quot;.&#xD;&#xA;&#xD;&#xA;Are these the correct way of describing this point of view and rotation?&#xD;&#xA;&#xD;&#xA;[![point of view][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lPICy.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14865" PostHistoryTypeId="1" PostId="5463" RevisionGUID="da2c5a8f-e096-4e97-8657-ee7723a976a2" CreationDate="2017-08-04T17:55:03.860" UserId="7109" Text="Point of view and rotation" ContentLicense="CC BY-SA 3.0" />
  <row Id="14866" PostHistoryTypeId="3" PostId="5463" RevisionGUID="da2c5a8f-e096-4e97-8657-ee7723a976a2" CreationDate="2017-08-04T17:55:03.860" UserId="7109" Text="|3d|transformations|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14867" PostHistoryTypeId="5" PostId="5460" RevisionGUID="95deef5a-2160-4cb4-a759-e616a7cdda8a" CreationDate="2017-08-04T19:28:26.117" UserId="20501" Comment="deleted 239 characters in body" Text="Is a person's view of screen dependent to the distance? How does it formulate?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14868" PostHistoryTypeId="2" PostId="5464" RevisionGUID="14da3c7c-e88c-420c-9b8c-970ca470d7c8" CreationDate="2017-08-04T19:49:20.240" UserId="7111" Text="Say I have two squares, both 10x10, with some small, unknown overlap.&#xD;&#xA;&#xD;&#xA;Is there a way to draw the intersection of these two squares using the width, height and x,y coordinates of each square, while also not using an if statement?&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="14869" PostHistoryTypeId="1" PostId="5464" RevisionGUID="14da3c7c-e88c-420c-9b8c-970ca470d7c8" CreationDate="2017-08-04T19:49:20.240" UserId="7111" Text="Is it possible to draw the intersection of two squares of known dimension using only x,y coordinates and without an if statement?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14870" PostHistoryTypeId="3" PostId="5464" RevisionGUID="14da3c7c-e88c-420c-9b8c-970ca470d7c8" CreationDate="2017-08-04T19:49:20.240" UserId="7111" Text="|geometry|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14871" PostHistoryTypeId="2" PostId="5465" RevisionGUID="105d7518-afab-499d-8ee2-6393bedcfbf1" CreationDate="2017-08-04T20:06:04.727" UserId="6749" Text="In film school, in the classes of 3D modeling, I was told that when we model something for films we maintain topology of 4 edged polygons. Any polygon which has more or less than 4 edge/vertex is considered bad and should be avoided. Whereas if the same model is used in games, it is triangulated.&#xD;&#xA;&#xD;&#xA;Although I'm not majoring in 3D modeling, the question is still in my mind. Why is 3 edged polygon used in gaming? Does it render faster? Then why not is it used in film renderings?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14872" PostHistoryTypeId="1" PostId="5465" RevisionGUID="105d7518-afab-499d-8ee2-6393bedcfbf1" CreationDate="2017-08-04T20:06:04.727" UserId="6749" Text="Why are quads used in filmmaking and triangle in gaming?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14873" PostHistoryTypeId="3" PostId="5465" RevisionGUID="105d7518-afab-499d-8ee2-6393bedcfbf1" CreationDate="2017-08-04T20:06:04.727" UserId="6749" Text="|3d|mesh|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14874" PostHistoryTypeId="2" PostId="5466" RevisionGUID="da366f42-26f2-4e06-9ba3-de505cfad0db" CreationDate="2017-08-04T23:44:51.457" UserId="506" Text="For 3D modeling, the usual reason to prefer quads is that [subdivision surface](https://en.wikipedia.org/wiki/Subdivision_surface) algorithms work better with them—if your mesh is getting subdivided, triangles can cause problems in the curvature of the resulting surface. For an example, take a look at these two boxes:&#xD;&#xA;&#xD;&#xA;![original boxes](https://i.stack.imgur.com/xvA7K.png)&#xD;&#xA;&#xD;&#xA;The left one is all quads; the right one has the same overall shape, but one corner is made of triangles instead of quads.&#xD;&#xA;&#xD;&#xA;Now see what happens when the boxes get subdivided:&#xD;&#xA;&#xD;&#xA;![subdivided boxes, wireframe](https://i.stack.imgur.com/jVesy.png)&#xD;&#xA;&#xD;&#xA;Different, yeah? Note the way the edge loops have changed from being roughly equidistant on the left box to a more complicated, pinched-and-stretched arrangement on the right. Now let’s turn off the wireframe and see how it’s getting lit.&#xD;&#xA;&#xD;&#xA;![subdivided boxes, smooth](https://i.stack.imgur.com/tHNoz.png)&#xD;&#xA;&#xD;&#xA;See the weird pinching in the highlight on the right box? That’s caused by the messy subdivision. This particular one is a pretty benign case, but you can get way more messed-up-looking results with more complex meshes with higher subdivision levels (like the ones you’d usually use in film).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;All of this still applies when making game assets, if you’re planning to subdivide them, but the key difference is that the subdivision happens **ahead of time**—while you’re still in quad-land—and then the final subdivided result gets turned into triangles because that’s what the graphics hardware speaks (because, as mentioned in the comments above, it makes the math easier)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14876" PostHistoryTypeId="2" PostId="5467" RevisionGUID="6ca04bd0-73e6-49e0-b3e2-86c4394455f3" CreationDate="2017-08-05T03:32:17.380" UserId="6883" Text="##Basic calculations&#xD;&#xA;I'm assuming you want to calculate the bounds of the rectangle of intersection, so you can draw it later. As AlanWolfe mentioned, you will want to use the max and min functions. This is so you can retrieve the left-most, right-most, top and bottom squares. We'll call these placeholders `right`, `bottom`, `left`, and `top` (each of these will point to one of the two squares). &#xD;&#xA;&#xD;&#xA;Now that you know these, you can start mathing. The top-left position of the intersection will be at `(right.x, bottom.y)`. The bottom-right position of the intersection will be at `(left.x + left.width, bottom.y + bottom.height)`.&#xD;&#xA;&#xD;&#xA;##Rendering the intersection&#xD;&#xA;To draw this rectangle (unconditionally), first you will need a location and a dimension, because most draw functions require these.&#xD;&#xA;&#xD;&#xA;    Intersection.width = Intersection.x_right - Intersection.x_left&#xD;&#xA;and the same for the height. Now suppose the squares don't overlap. This would mean at least one dimension is negative. We don't want anything to draw in this case, so we will set any negative dimensions to zero if they are negative.&#xD;&#xA;&#xD;&#xA;    Intersection.width = max(Intersection.width, 0)&#xD;&#xA;and the same for the height. And to wrap up, we render our rectangle:&#xD;&#xA;&#xD;&#xA;    fillRect(Intersection.x_left, Intersection.y_top, Intersection.width, Intersection.height)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14877" PostHistoryTypeId="2" PostId="5468" RevisionGUID="082c8606-4299-4565-9a51-4a6d4a03dfc0" CreationDate="2017-08-05T04:11:27.000" UserId="3003" Text="You could phrase it in terms of elevation away from various planes. So 30° above the x-z plane, and 0° from the y-z plane (or whatever it actually is). It's sort of like [spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system) where you'd have theta and phi." ContentLicense="CC BY-SA 3.0" />
  <row Id="14878" PostHistoryTypeId="2" PostId="5469" RevisionGUID="6c68b68d-0153-4639-a9ae-15e0dcd3ed33" CreationDate="2017-08-05T06:08:50.727" UserId="5978" Text="I am experimenting on a simple wave tessellation shader. I ported it from a working vertex shader. When my frequency is higher than 1, I get strange &quot;saw-tooth&quot; artifacting at peaks of the wave. Here are some images with a frequency of 3.&#xD;&#xA;&#xD;&#xA;[![Wireframe artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;[![Artifacts][2]][2]&#xD;&#xA;&#xD;&#xA;If I keep the frequency lower, it is smooth as butter. Any ideas what the problem could be?&#xD;&#xA;&#xD;&#xA;    #version 410 core&#xD;&#xA;    layout(quads, equal_spacing, ccw) in;&#xD;&#xA;    in vec2 teUv[];&#xD;&#xA;    out vec2 fUv;&#xD;&#xA;    out vec4 fWorld_pos;&#xD;&#xA;    uniform mat4 VP;&#xD;&#xA;    uniform mat4 M;&#xD;&#xA;    uniform sampler2D water_disp;&#xD;&#xA;    uniform float time;&#xD;&#xA;    const float M_PI = 3.1415926535;&#xD;&#xA;    &#xD;&#xA;    float water_displacement(vec2 pos) {&#xD;&#xA;    	const float freq = 3.0; // &lt;-- This is the problematic value.&#xD;&#xA;    	float d = length(pos);&#xD;&#xA;    	return (0.5 + 0.5 * sin(-M_PI * d * freq + time));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	vec4 p1 = mix(gl_in[0].gl_Position,&#xD;&#xA;    			gl_in[1].gl_Position,&#xD;&#xA;    			gl_TessCoord.x);&#xD;&#xA;    	vec4 p2 = mix(gl_in[2].gl_Position,&#xD;&#xA;    			gl_in[3].gl_Position,&#xD;&#xA;    			gl_TessCoord.x);&#xD;&#xA;    	vec4 local_pos = mix(p1, p2, gl_TessCoord.y);&#xD;&#xA;    	fWorld_pos = M * local_pos;&#xD;&#xA;    	fWorld_pos.y += water_displacement(fWorld_pos.xz);&#xD;&#xA;    &#xD;&#xA;    	gl_Position = VP * fWorld_pos;&#xD;&#xA;    &#xD;&#xA;    	vec2 uv1 = mix(teUv[0], teUv[1], gl_TessCoord.x);&#xD;&#xA;    	vec2 uv2 = mix(teUv[2], teUv[3], gl_TessCoord.x);&#xD;&#xA;    	fUv = mix(uv2, uv1, gl_TessCoord.y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And more examples:&#xD;&#xA;&#xD;&#xA;[![Smooooth (freq = 0.5)][3]][3]&#xD;&#xA;[![Not so smooth (freq = 8)][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/evCYZ.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/gGZdw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/QE8Xq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/dM5X5.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14879" PostHistoryTypeId="1" PostId="5469" RevisionGUID="6c68b68d-0153-4639-a9ae-15e0dcd3ed33" CreationDate="2017-08-05T06:08:50.727" UserId="5978" Text="Tesselation sine distortion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14880" PostHistoryTypeId="3" PostId="5469" RevisionGUID="6c68b68d-0153-4639-a9ae-15e0dcd3ed33" CreationDate="2017-08-05T06:08:50.727" UserId="5978" Text="|opengl|artifacts|tesselation|distortion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14881" PostHistoryTypeId="2" PostId="5470" RevisionGUID="72e7e35d-21fa-4662-8c50-ffb83fc61d52" CreationDate="2017-08-05T06:26:59.333" UserId="5978" Text="I personally like glad. The have an online generator as well http://glad.dav1d.de&#xD;&#xA;&#xD;&#xA;It will generate exactly what you need for your platform." ContentLicense="CC BY-SA 3.0" />
  <row Id="14882" PostHistoryTypeId="6" PostId="5469" RevisionGUID="3821f69f-8319-4867-88c9-264766d0041a" CreationDate="2017-08-05T06:39:35.653" UserId="5978" Comment="edited tags" Text="|opengl|glsl|artifacts|tesselation|distortion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14883" PostHistoryTypeId="2" PostId="5471" RevisionGUID="554e6134-ca8c-47b6-bbb2-7891a9fd5e8b" CreationDate="2017-08-05T06:50:10.237" UserId="38" Text="Not enough triangles. The situation is analogous to the saampling tyeorem that states that you can not reconstruct a signal if your sample frequency is below a certain treshold. Altough in this case your not wven attempling to rebuild the signal, and it results in interpolation errors.&#xD;&#xA;&#xD;&#xA;You can aleviate the problem wity less points if your point wavefront follows your waves. So you may want to shift pooints towards the gradient maximum in other directions than UP." ContentLicense="CC BY-SA 3.0" />
  <row Id="14884" PostHistoryTypeId="5" PostId="5467" RevisionGUID="ab662c78-d713-4edf-ab8b-5302b540710d" CreationDate="2017-08-05T12:03:49.120" UserId="6883" Comment="added 18 characters in body" Text="##Basic calculations&#xD;&#xA;I'm assuming you want to calculate the bounds of the rectangle of intersection, so you can draw it later. As AlanWolfe mentioned, you will want to use the max and min functions. This is so you can retrieve the left-most, right-most, top and bottom squares. We'll call these placeholders `right`, `bottom`, `left`, and `top` (each of these will point to one of the two squares). &#xD;&#xA;&#xD;&#xA;Now that you know these, you can start mathing. The top-left position of the intersection will be at `(right.x_left, bottom.y_top)`. The bottom-right position of the intersection will be at `(left.x_left + left.width, bottom.y_top + bottom.height)`.&#xD;&#xA;&#xD;&#xA;##Rendering the intersection&#xD;&#xA;To draw this rectangle (unconditionally), first you will need a location and a dimension, because most draw functions require these.&#xD;&#xA;&#xD;&#xA;    Intersection.width = Intersection.x_right - Intersection.x_left&#xD;&#xA;and the same for the height. Now suppose the squares don't overlap. This would mean at least one dimension is negative. We don't want anything to draw in this case, so we will set any negative dimensions to zero if they are negative.&#xD;&#xA;&#xD;&#xA;    Intersection.width = max(Intersection.width, 0)&#xD;&#xA;and the same for the height. And to wrap up, we render our rectangle:&#xD;&#xA;&#xD;&#xA;    fillRect(Intersection.x_left, Intersection.y_top, Intersection.width, Intersection.height)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14885" PostHistoryTypeId="5" PostId="5467" RevisionGUID="6d9b7234-e36a-471f-a7c6-70544e566369" CreationDate="2017-08-05T12:20:52.950" UserId="6883" Comment="deleted 21 characters in body" Text="##Basic calculations&#xD;&#xA;I'm assuming you want to calculate the bounds of the rectangle of intersection, so you can draw it later. As AlanWolfe mentioned, you will want to use the max and min functions. This is so you can retrieve the left-most, right-most, top and bottom squares. We'll call these placeholders `right`, `bottom`, `left`, and `top` (each of these will point to one of the two squares). &#xD;&#xA;&#xD;&#xA;Now that you know these, you can start mathing. The top-left position of the intersection will be at `(right.x_left, bottom.y_top)`. The bottom-right position of the intersection will be at `(left.x_left + left.width, bottom.y_top + bottom.height)`.&#xD;&#xA;&#xD;&#xA;##Rendering the intersection&#xD;&#xA;To draw this rectangle (unconditionally), first you will need a location and a dimension, because most draw functions require these.&#xD;&#xA;&#xD;&#xA;    Intersection.width = Intersection.x_right - Intersection.x_left&#xD;&#xA;and the same for the height. Now suppose the squares don't overlap. This would mean at least one dimension is negative. We don't want anything to draw in this case, so we will set any negative dimensions to zero.&#xD;&#xA;&#xD;&#xA;    Intersection.width = max(Intersection.width, 0)&#xD;&#xA;and the same for the height. And to wrap up, we render our rectangle:&#xD;&#xA;&#xD;&#xA;    fillRect(Intersection.x_left, Intersection.y_top, Intersection.width, Intersection.height)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14886" PostHistoryTypeId="5" PostId="5471" RevisionGUID="3573130e-047d-498c-afd5-18d9d81a3ce9" CreationDate="2017-08-05T15:07:56.623" UserId="2654" Comment="Spellchecking." Text="Not enough triangles. The situation is analogous to the sampling theorem that states that you can not reconstruct a signal if your sample frequency is below a certain threshold. Although in this, case you're not attempting to rebuild the signal, and it results in interpolation errors.&#xD;&#xA;&#xD;&#xA;You can alleviate the problem with less points if your point wavefront follows your waves. So you may want to shift points towards the gradient maximum in other directions than UP." ContentLicense="CC BY-SA 3.0" />
  <row Id="14887" PostHistoryTypeId="5" PostId="5471" RevisionGUID="035dde86-8f9b-432e-abaf-2b67a48e9c30" CreationDate="2017-08-05T17:20:30.640" UserId="38" Comment="added 27 characters in body" Text="Not enough triangles. The situation is analogous to the sampling theorem that states that you can not reconstruct a signal if your sample frequency is below a certain threshold. Although in this, case you're not attempting to rebuild the signal witha  higher order filter. And it results in interpolation errors.&#xD;&#xA;&#xD;&#xA;You can alleviate the problem with less points if your point wavefront follows your waves. So you may want to shift points towards the gradient maximum in other directions than UP." ContentLicense="CC BY-SA 3.0" />
  <row Id="14888" PostHistoryTypeId="5" PostId="5471" RevisionGUID="bc38d220-0e3e-41c7-a4d2-1aec49e2a80a" CreationDate="2017-08-05T17:26:16.053" UserId="38" Comment="added 36 characters in body" Text="Not enough triangles. The situation is analogous to the sampling theorem that states that you can not reconstruct a signal if your sample frequency is below a certain threshold. Although in this, case you're not attempting to rebuild the signal with a higher order filter so the result is even more dramatic. And it results in interpolation errors.&#xD;&#xA;&#xD;&#xA;You can alleviate the problem with less points if your point wavefront follows your waves. So you may want to shift points towards the gradient maximum in other directions than UP." ContentLicense="CC BY-SA 3.0" />
  <row Id="14889" PostHistoryTypeId="8" PostId="5460" RevisionGUID="c9235313-ca72-4b33-8e3b-3e9c6b102213" CreationDate="2017-08-05T17:27:39.783" UserId="38" Comment="Rollback to [d9ed834b-ad94-4a4f-acb6-3a05a8f5fb75]" Text="I was told that human's visual sharpness is 60 pixels per degree. As such, pixel per inch is approximately given by:&#xD;&#xA;&#xD;&#xA;    PPI = 1/ (Distance * tg((1/60*pi/180) )&#xD;&#xA;&#xD;&#xA;Is this formula fully correct? (I saw similar, but slightly different versions). How is this formula derived? Maybe some step by step description?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14890" PostHistoryTypeId="9" PostId="5460" RevisionGUID="c9235313-ca72-4b33-8e3b-3e9c6b102213" CreationDate="2017-08-05T17:27:39.783" UserId="38" Comment="Rollback to [d9ed834b-ad94-4a4f-acb6-3a05a8f5fb75]" Text="|computational-geometry|2d|pixel-graphics|pixels|human-vision|" />
  <row Id="14891" PostHistoryTypeId="2" PostId="5472" RevisionGUID="52e8b532-ffce-4a41-aca2-61749b1e718d" CreationDate="2017-08-05T19:53:42.923" UserDisplayName="user7115" Text="Lets say i have a picture. I send it to a server. While sending it to the server half way  the upload gets canceled. Now the server has half or some of the picture. Now is there a way in which this can be  processed and viewed. Are there any formats which support this? And are there any other factors which account as to why the picture can or cannot be processed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14892" PostHistoryTypeId="1" PostId="5472" RevisionGUID="52e8b532-ffce-4a41-aca2-61749b1e718d" CreationDate="2017-08-05T19:53:42.923" UserDisplayName="user7115" Text="can half of a picture be processed and viewed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14893" PostHistoryTypeId="3" PostId="5472" RevisionGUID="52e8b532-ffce-4a41-aca2-61749b1e718d" CreationDate="2017-08-05T19:53:42.923" UserDisplayName="user7115" Text="|image-processing|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14894" PostHistoryTypeId="2" PostId="5473" RevisionGUID="86032fda-c666-4fca-bb80-35bd10e41cad" CreationDate="2017-08-05T20:44:20.333" UserId="38" Text="Yes, most, formats work this way! For example JPEG can be decoded up to the point where the chunks are available:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1** Scaled version of original JPEG picture at (1 048 198 bytes) and corrupted one (610 922 bytes) side by side. Original image by *Maruf Mostafa* image available [here](https://commons.wikimedia.org/wiki/File:Colored_Duck.jpg) &#xD;&#xA;&#xD;&#xA;This is easy for you to test take an image and just simply delete some bytes out of it (like with a text editor). Some files are easy just open them, like the JPEG in question that just opens up in many editors without a hitch. some are not so easy like PNG that require special handling to uncompress but still relatively straightforward.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gmc2f.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14895" PostHistoryTypeId="12" PostId="5472" RevisionGUID="0d9d1a28-06d1-43c1-b513-cf16e5935d56" CreationDate="2017-08-05T20:46:06.823" UserDisplayName="user7115" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7115,&quot;DisplayName&quot;:&quot;bangbam&quot;}]}" />
  <row Id="14896" PostHistoryTypeId="13" PostId="5472" RevisionGUID="05ea97f1-959c-4b88-9e59-43e1e7f02b49" CreationDate="2017-08-05T20:46:22.107" UserDisplayName="user7115" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7115,&quot;DisplayName&quot;:&quot;bangbam&quot;}]}" />
  <row Id="14897" PostHistoryTypeId="5" PostId="5473" RevisionGUID="bb2d1005-27c3-4a15-9d3f-e3587bea321f" CreationDate="2017-08-05T20:51:59.693" UserId="38" Comment="added 123 characters in body" Text="Yes, most formats work this way! For example JPEG can be decoded up to the point where the chunks are available:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1** Scaled version of original JPEG picture at (1 048 198 bytes) and corrupted one (610 922 bytes) side by side. Original image by *Maruf Mostafa* image available [here](https://commons.wikimedia.org/wiki/File:Colored_Duck.jpg) &#xD;&#xA;&#xD;&#xA;This is easy for you to test take an image and just simply delete some bytes out of it (like with a text editor). Some files are easy just open them, like the JPEG in question that just opens up in many editors without a hitch. &#xD;&#xA;&#xD;&#xA;PNG required some slight special handling to uncompress. It did't open in Photoshop or windows image preview. But was still relatively straightforward to open as the web browser happily opened even partial PNG files to the point it was defined to.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Gmc2f.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14898" PostHistoryTypeId="5" PostId="4789" RevisionGUID="8824dfd1-f123-4505-9551-d59bfde929e0" CreationDate="2017-08-05T21:28:41.683" UserId="231" Comment="Add in second half of answer from question which is being closed as a duplicate." Text="To solve the problem, we will flow three steps, first, calculate translation matrix, second, calculate rotation matrix, third, get transformation matrix.&#xD;&#xA;&#xD;&#xA;Because translation is a *affine transformation*, we need to use a 4x4 matrix to represent translation. I find you use column vector post-multiply matrix. the result of the translation matrix is same as yours.&#xD;&#xA;     &#xD;&#xA;   Translation matrix = [![translation matrix][1]][1]&#xD;&#xA;&#xD;&#xA;Then, same as your idea, we use basis vectors(same as unit vectors of the coordinate axes) to calculate rotation matrix.&#xD;&#xA;&#xD;&#xA; 1. basis **z** vector: we can get rotated basis **z** vector by using a vector from VRP to point A, and normalize it.&#xD;&#xA;  &#xD;&#xA;   **z** = **b**(VRP) - **a** = [5,-2,1] - [1,1,1] = [4,-3,0] ,then, normalize to [0.8,-0.6,0]&#xD;&#xA; 2. basis **x** vector: we know basis vector is a vector perpendicular to **z-up** plane, we get the **x** vector by cross product **up** and **z**&#xD;&#xA;   &#xD;&#xA; **x** = **up** x **z** = [1,1,1] x [0.8 ,-0.6 ,0] = [0.6, 0.8, 0]&#xD;&#xA; 3. basis **y** vector, **y** is prependicular to **z-x** plane.&#xD;&#xA;&#xD;&#xA; **y** = **z** x **x** = [0.8 ,-0.6, 0] x [0.6, 0.8, 0] = [0, 0, 1]&#xD;&#xA;&#xD;&#xA; finally, the rotation matrix is:&#xD;&#xA;&#xD;&#xA; Rotation Matrix = &#xD;&#xA;       [![rotation matrix][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; The 4x4 matrix is:&#xD;&#xA;&#xD;&#xA; Transformation matrix = [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA; The transformation matrix is a matrix from *Object Space* to *World Space*, we should invert this matrix to get *World Space* to *Camera Space* matrix.(Thanks for @JarkkoL correcting me).&#xD;&#xA;&#xD;&#xA; Refer to [3D Math Primer for Graphics and Game Developmen][4].&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Following your request for clarification: I just combine the translation matrix and the rotation matrix, actually, It's the result translation matrix(T) multiply rotation matrix(R). &#xD;&#xA;&#xD;&#xA;The rotation is a 3x3 matrix, we can extend the matrix to a 4x4 matrix with adding a dimension, the 4x4 rotation matrix is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;And the translation matrix is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;So, now we can calculate the transform matrix by translation matrix multiply(T) rotation matrix(R):&#xD;&#xA;&#xD;&#xA;Cause the matrix multiply formula is too big for the 4x4 matrix, we just look at the 1st row, In the transform matrix(M), the M11 element equals to T11*R11+T12*R21+T13*R31+T14*R41, cause T12, T13, R41 is 0, so, the M11 equals to R11 right? And in the same way, M14 equals to T11*R14+T12*R24+T13*R34+T14*R44, only R44 equals to 1, so, the M14 equals to T14. so, I just simply put them together in my last answer. For the reason why we put the translation matrix on the left, you can check on the book that I gave you in my previous answer on page 91(translating first and then rotating).&#xD;&#xA; &#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lk5Xn.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/gmygD.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/8ue8L.gif&#xD;&#xA;  [4]: https://tfetimes.com/wp-content/uploads/2015/04/F.Dunn-I.Parberry-3D-Math-Primer-for-Graphics-and-Game-Development.pdf&#xD;&#xA;&#xD;&#xA;  [5]: https://i.stack.imgur.com/QOZur.gif&#xD;&#xA;  [6]: https://i.stack.imgur.com/l3FFz.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="14899" PostHistoryTypeId="5" PostId="4737" RevisionGUID="7bef559d-8239-4003-9511-9ce268702fc9" CreationDate="2017-08-05T21:32:15.277" UserId="231" Comment="Add in second half of question (as it is being closed as a duplicate in another post)." Text="&gt; For a 3D scene in the world coordinates, its _View Reference Point_ $\mathrm{VRP}$ is at $(5,-2,1)$, and a viewer is looking towards point $A=(1,1,1)$. Construct a transform matrix which will map world coordinate points to a right-handed $(UVN)$ viewing space, so that $\mathrm{VRP}$ is the origin, the line joining $\mathrm{VRP}$ to $A$ is the positive $N$ axis, and the view-up Vector is $(0,0,1)$.&#xD;&#xA;&#xD;&#xA;To my knowledge, the final answer should be a single transform matrix.&#xD;&#xA;To calculate the final matrix, I first find the matrix which translates the coordinate system to the to the origin in homogeneous matrix form:&#xD;&#xA;&#xD;&#xA;Translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;T=&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        1 &amp;0 &amp;0 &amp;-5 \\&#xD;&#xA;        0 &amp;1 &amp;0&amp; 2 \\&#xD;&#xA;        0 &amp;0 &amp;1 &amp;-1 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Using the unit vectors of the coordinate axes, the resulting rotation matrix is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R=&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        -0.6 &amp;-0.8 &amp;0 &amp;0 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        -0.8 &amp;0.6 &amp;0 &amp;0 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Then the final matrix (the final answer for full marks) would be the rotation matrix multiplied by the translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;M=&#xD;&#xA;        \begin{bmatrix}&#xD;&#xA;        -0.6 &amp;-0.8 &amp;0 &amp;1.4 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        -0.8 &amp;0.6 &amp;0 &amp;5.2 \\&#xD;&#xA;        0 &amp;0 &amp;0 &amp;1 \\&#xD;&#xA;        \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Is my method and final answer correct?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Following the answer to this question, I have calculated the translation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;T=&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; -5 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 2 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; -1 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I have calculated the rotation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R=&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;-0.6 &amp; -0.8 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;-0.8 &amp; 0.6 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But what would the final transformation matrix $M$ be? My lecture slides tell me it would be rotation matrix multiplied by translation matrix, with the last column multiplied by $-1$ except for the $1$. This would equal:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;M = R \times T = &#xD;&#xA;\begin{pmatrix}&#xD;&#xA;-0.6 &amp; -0.8 &amp; 0 &amp; -1.4 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 1 \\&#xD;&#xA;-0.8 &amp; 0.6 &amp; 0 &amp; -5.2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But the answer here just adds them together somehow. Which one is correct?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14900" PostHistoryTypeId="10" PostId="4917" RevisionGUID="746dbdd6-41cf-40f5-83f1-56d888333487" CreationDate="2017-08-05T21:34:55.190" UserId="231" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[4737],&quot;Voters&quot;:[{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="14901" PostHistoryTypeId="2" PostId="5474" RevisionGUID="865274fd-df37-4a99-8827-2341177089b8" CreationDate="2017-08-05T22:25:31.997" UserId="7116" Text="In the early 3D Studio days before it got Max in its name it was possible to make a 3d object by defining its projections in xy, xz and yz plane. 3ds would then interpolate a 3d object from the projections. I cannot remember what was the name of this method and how it was exactly done, so I don't know which words to google. Essentially I want to use this method in Max if it is possible anymore. Can somebody give me a hint for keywords or even better explain the procedure in 3ds max?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14902" PostHistoryTypeId="1" PostId="5474" RevisionGUID="865274fd-df37-4a99-8827-2341177089b8" CreationDate="2017-08-05T22:25:31.997" UserId="7116" Text="Make 3d objects from 3 projections in 3D Studio Max" ContentLicense="CC BY-SA 3.0" />
  <row Id="14903" PostHistoryTypeId="3" PostId="5474" RevisionGUID="865274fd-df37-4a99-8827-2341177089b8" CreationDate="2017-08-05T22:25:31.997" UserId="7116" Text="|projections|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14905" PostHistoryTypeId="2" PostId="5475" RevisionGUID="ad813506-6154-42eb-a4da-e81af664cebd" CreationDate="2017-08-06T12:40:31.687" UserId="6046" Text="One thing i see most people forget is in film making it's mostly about quality not speed. That's cause film making is concerned more with Offline rendering where as in Video games it's all real time so performance/speed is much more crucial than quality.&#xD;&#xA;&#xD;&#xA;Hence when it comes to video games people try to find the best way to &quot;approximate&quot; or &quot;fake&quot; the look of a real thing. When it comes to different calculations and speed triangles are much more easier than polygons. Like @ratchet freak mentioned as all the 3 points are coplanar and it simplifies intersections and other calculations. That's one of the main reasons triangles are used in video-games.&#xD;&#xA;&#xD;&#xA;However in film making rendering one frame can take hours or even days, hence speed isn't that much of an issue. What Noah said is correct, i just wanted to share this point of view as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="14908" PostHistoryTypeId="2" PostId="5477" RevisionGUID="7f8957d8-a637-4756-ac92-460221ff34ef" CreationDate="2017-08-06T13:48:19.513" UserId="38" Text="As @Noah Witherspoon correctly, says triangle subdivision does not work as well as quad subdivision. Although, in the beginning triangles could not be subdivided at all. However, he does not really explain why that is the case. Which is useful information and explains why quads are preferred and how to use them.&#xD;&#xA;&#xD;&#xA;First, observe that a triangle does gets subdivided into 3 quads in many schemes. Since you now have a all quad mesh, clearly keeping the subdivision all quad is not in itself the requirement. There has to be a more profound reason than just being four sided.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: You can subdivide a triangle into 3 quadrangles&#xD;&#xA;&#xD;&#xA;The reason lies in what has become called edge loops. The person doing the modeling have to anticipate how the subdivision happens as the subdivision is going to be the final shape. Unfortunately humans are only really good at deciphering the shape of the object along the edges of your primitives edges. By formulating the shape into continuous multi edge long loops helps us predict the shape after subdivision and importantly after deformation by bones etc. &#xD;&#xA;&#xD;&#xA;A triangle has a nasty way of terminating the loop so we do not understand what happens with the shape within and out of that shape. The subdivided mesh thus has a tendency to behave uncontrollably, causing undesired bumps. **Note**: It is possible to subdivide triangles in a way that this does not happen, they are just harder to work with.&#xD;&#xA;&#xD;&#xA;Now this is not actually the original reason, only it happened in roundabout way. The original reason what that the geometrical patches that they did use a as parametric primitives are square in shape. As extending a line into a surface naturally takes a square shape if you just extrude out. Having a triangle causes one edge to be degenerate and have a singularity. But this is very much related to the subdividing reason as it can be shown that a subdivision surface is just a  general case of a spline patch.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d9TRb.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14909" PostHistoryTypeId="5" PostId="5477" RevisionGUID="d738dff9-0cbd-4b36-bb9b-9332b66d5d31" CreationDate="2017-08-06T13:59:43.243" UserId="38" Comment="added 232 characters in body" Text="As @Noah Witherspoon correctly, says triangle subdivision does not work as well as quad subdivision. Although, in the beginning triangles could not be subdivided at all. However, he does not really explain why that is the case. Which is useful information and explains why quads are preferred and how to use them.&#xD;&#xA;&#xD;&#xA;First, observe that a triangle does gets subdivided into 3 quads in many schemes. Since you now have a all quad mesh, clearly keeping the subdivision all quad is not in itself the requirement. There has to be a more profound reason than just being four sided.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: You can subdivide a triangle into 3 quadrangles&#xD;&#xA;&#xD;&#xA;The reason lies in what has become called edge loops. The person doing the modeling have to anticipate how the subdivision happens as the subdivision is going to be the final shape. Unfortunately humans are only really good at deciphering the shape of the object along the edges of your primitives edges. By formulating the shape into continuous multi edge long loops helps us predict the shape after subdivision and importantly after deformation by bones etc. &#xD;&#xA;&#xD;&#xA;A triangle has a nasty way of terminating the loop so we do not understand what happens with the shape within and out of that shape. The subdivided mesh thus has a tendency to behave uncontrollably, causing undesired bumps. **Note**: It is possible to subdivide triangles in a way that this does not happen, they are just harder to work with and working with quads were well known by then.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this is not actually the original reason, only it happened in roundabout way. The original reason what that the geometrical patches that they did use a as parametric primitives are square in shape. As extending a line into a surface naturally takes a square shape if you just extrude out. Having a triangle causes one edge to be degenerate and have a singularity. But this is very much related to the subdividing reason as it can be shown that a subdivision surface is just a  general case of a spline patch.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Original parametric surfaces were extensions of curves, not arbitrary meshes and these shapes naturally tend to be square.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d9TRb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/GRFa8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14913" PostHistoryTypeId="50" PostId="5336" RevisionGUID="11860492-6876-4382-a0ee-fa2d75ec8cf0" CreationDate="2017-08-06T15:18:28.000" UserId="-1" />
  <row Id="14914" PostHistoryTypeId="2" PostId="5478" RevisionGUID="6f21d9d5-5a8d-4392-b295-cacad64443d5" CreationDate="2017-08-06T16:26:37.153" UserId="7119" Text="I am by no means an expert on the subject, but you might be able to, at least in theory, preserve sharp corners in a monochromatic pseudo-SDF if you used a Bilateral filter instead of a Bilinear filter. Unfortunately, I don't not have any means of testing this currently, and just have been unable to find any documents showing similar tests to what I am describing." ContentLicense="CC BY-SA 3.0" />
  <row Id="14915" PostHistoryTypeId="5" PostId="5478" RevisionGUID="a2db11c8-7a43-42cd-9742-b17fe9a74c32" CreationDate="2017-08-06T16:34:25.693" UserId="7119" Comment="added 551 characters in body" Text="I am by no means an expert on the subject, but you might be able to, at least in theory, preserve sharp corners in a monochromatic pseudo-SDF if you used either a Bilateral filter a Directional Bicubic filter instead of a standard Bilinear filter. Unfortunately, I don't have any means of testing my theory currently, and just have been unable to find any documents showing similar tests to what I am describing.&#xD;&#xA;&#xD;&#xA;Alternatively, if you don't mind using a second channel, then you could also try having one channel for Horizontal Distance and another for Vertical Distance, and use a Difference of Laplacean (DoL) energy pyramid to compress the texture so that redundant information wouldn't be recorded.&#xD;&#xA;&#xD;&#xA;A third and final theoretical solution would be to experiment with a Hexagonally Sampled Texture via Array Set Addressing.&#xD;&#xA;&#xD;&#xA;I will link all of the relevant articles where I got my information/ideas shortly." ContentLicense="CC BY-SA 3.0" />
  <row Id="14916" PostHistoryTypeId="5" PostId="5478" RevisionGUID="11cdcbb2-dc5c-4001-badd-d69987e5bc3f" CreationDate="2017-08-06T16:40:20.090" UserId="7119" Comment="added 551 characters in body" Text="I am by no means an expert on the subject, but you might be able to, at least in theory, preserve sharp corners in a monochromatic pseudo-SDF if you used either a Bilateral filter a Directional Bicubic filter instead of a standard Bilinear filter. Besides the obvious benefit of saving memory, you could also have multiple channels for multi-colored SDF decals.&#xD;&#xA;&#xD;&#xA;Alternatively, if you don't mind using a second channel, then you could also try having one channel for Horizontal Distance and another for Vertical Distance, and use a Difference of Laplacean (DoL) energy pyramid to compress the texture so that redundant information wouldn't be recorded.&#xD;&#xA;&#xD;&#xA;A third and final theoretical solution would be to experiment with a Hexagonally Sampled Texture via Array Set Addressing.&#xD;&#xA;&#xD;&#xA;Unfortunately, I don't have any means of testing my ideas currently, and have been unable to find any documents describing or testing anything similar to my ideas. I will link all of the relevant articles where I got my information/ideas shortly." ContentLicense="CC BY-SA 3.0" />
  <row Id="14918" PostHistoryTypeId="2" PostId="5479" RevisionGUID="aecb73a1-0237-4db5-9c71-2193f8c75968" CreationDate="2017-08-07T19:40:47.790" UserId="6367" Text="I'm mainly trying to understand what it means for Monte Carlo samples to be correlated. Can somebody fit this into the theory of what I know about random variables, covariance and correlation?&#xD;&#xA;&#xD;&#xA;And then specifically, when it comes to Monte Carlo path tracing (within the path integral formulation), what would the paths be analogous to? Let's say I have two variables producing paths of length $l$. The way I understand it right now is that they produce samples from a $3l$-dimensional space -- 3 cartesian coordinates, one for each point on the path. Is this correct?&#xD;&#xA;&#xD;&#xA;If I had two random variables generating paths of some length $l$, how would I measure the correlation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14919" PostHistoryTypeId="1" PostId="5479" RevisionGUID="aecb73a1-0237-4db5-9c71-2193f8c75968" CreationDate="2017-08-07T19:40:47.790" UserId="6367" Text="Sample Correlation and Random Variables -- An Intuitive Explanation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14920" PostHistoryTypeId="3" PostId="5479" RevisionGUID="aecb73a1-0237-4db5-9c71-2193f8c75968" CreationDate="2017-08-07T19:40:47.790" UserId="6367" Text="|pathtracing|sampling|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14921" PostHistoryTypeId="2" PostId="5480" RevisionGUID="c7c4d255-6a2a-4443-aab9-b9c8619494eb" CreationDate="2017-08-08T10:28:34.570" UserId="5944" Text="Being confused about the example of Combining Stratified Sampling and Importance Sampling in *Advanced Global Illumination* (P72,P73).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bskvn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/huQTU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14922" PostHistoryTypeId="1" PostId="5480" RevisionGUID="c7c4d255-6a2a-4443-aab9-b9c8619494eb" CreationDate="2017-08-08T10:28:34.570" UserId="5944" Text="An example of Combining Stratified Sampling and Importance Sampling in AGI" ContentLicense="CC BY-SA 3.0" />
  <row Id="14923" PostHistoryTypeId="3" PostId="5480" RevisionGUID="c7c4d255-6a2a-4443-aab9-b9c8619494eb" CreationDate="2017-08-08T10:28:34.570" UserId="5944" Text="|sampling|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14929" PostHistoryTypeId="5" PostId="5480" RevisionGUID="90ceaaf3-e1f7-41d8-bacf-fd0909b27d3f" CreationDate="2017-08-09T13:46:06.740" UserId="5944" Comment="added 292 characters in body" Text="Being confused about the example of Combining Stratified Sampling and Importance Sampling in *Advanced Global Illumination* (P72,P73).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I know how to do importance sampling and stratified sampling. But I can't understand this example and the code.&#xD;&#xA;&#xD;&#xA;Is this example to calculate $S$ stochastically or to get a random number $u$?&#xD;&#xA;&#xD;&#xA;What is the $u$ for?&#xD;&#xA;&#xD;&#xA;What's the meaning of &quot;Sample the $i$th term of the sum $N_i$ times&quot;?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bskvn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/huQTU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14931" PostHistoryTypeId="2" PostId="5482" RevisionGUID="9c9f53ec-4b81-4cf3-9e2a-f6548b9f5875" CreationDate="2017-08-09T14:04:42.447" UserId="5944" Text="What is the difference between glossy and specular reflection?&#xD;&#xA;&#xD;&#xA;What is their relations with BRDF?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mqALR.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ic1g1.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="14932" PostHistoryTypeId="1" PostId="5482" RevisionGUID="9c9f53ec-4b81-4cf3-9e2a-f6548b9f5875" CreationDate="2017-08-09T14:04:42.447" UserId="5944" Text="What is the difference between glossy and specular reflection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14933" PostHistoryTypeId="3" PostId="5482" RevisionGUID="9c9f53ec-4b81-4cf3-9e2a-f6548b9f5875" CreationDate="2017-08-09T14:04:42.447" UserId="5944" Text="|brdf|reflection|specular|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14934" PostHistoryTypeId="2" PostId="5483" RevisionGUID="aa2f4a6f-fe31-41df-9602-5dc2bf3dd008" CreationDate="2017-08-09T14:05:49.567" UserId="4958" Text="Nvidia in [this article][1] presented a way to upsample low res buffer to full res buffer called Nearest Depth Upsampling.&#xD;&#xA;&#xD;&#xA; This works by comparing four depth values from downsampled low res depth buffer with current value of full res depth buffer and selecting texcoords where difference is minimal to sample the low res buffer.&#xD;&#xA;&#xD;&#xA;In the article they stated the four places to sample as &quot;bilinear footprint of the current full res pixel&quot;. &#xD;&#xA;&#xD;&#xA;In the picture, the circle marks the texcoord of one of the fragments of full res buffer. So if full res is 4x4 then low res is 2x2. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Unfortunaltely it is not clear to me how to sample the low res buffer correctly. My question are:&#xD;&#xA;&#xD;&#xA; - **What are locations of the four samples used to sample low res buffer in relation to current texcoords of full res buffer?**&#xD;&#xA; - **Is downsampling depth using just hardware interpolation is enough?**&#xD;&#xA; - **Can I upsample not only half res buffer but also quarter res buffer to full res?**&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/OpacityMappingSDKWhitePaper.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/JFfPw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14935" PostHistoryTypeId="1" PostId="5483" RevisionGUID="aa2f4a6f-fe31-41df-9602-5dc2bf3dd008" CreationDate="2017-08-09T14:05:49.567" UserId="4958" Text="Nearest depth upsampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="14936" PostHistoryTypeId="3" PostId="5483" RevisionGUID="aa2f4a6f-fe31-41df-9602-5dc2bf3dd008" CreationDate="2017-08-09T14:05:49.567" UserId="4958" Text="|texture|glsl|sampling|supersampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14937" PostHistoryTypeId="2" PostId="5484" RevisionGUID="5ea0271a-141a-4d5e-ae53-fcce5e38560c" CreationDate="2017-08-09T14:22:33.817" UserId="2041" Text="The charts you show aren't showing two different phenomena - &quot;glossy reflection&quot; and &quot;specular reflection&quot; - they're showing two parameters of specular reflection. One is the *specularity* or *specular colour* and gives the amount or brightness of the specular reflection. The other is the *glossiness* or *roughness* and shows how sharp the specular reflection is.&#xD;&#xA;&#xD;&#xA;Put another way, if you picture the curve of the specular reflection over changing angle, the specularity (the vertical axis on your charts) gives the height of the peak - the maximum brightness - and the glossiness gives the width of the peak - the size of the highlight. The highlight gets narrower with increasing glossiness, whereas roughness is the inverse of this.&#xD;&#xA;&#xD;&#xA;*BRDF* is more general: it's a function that tells you how much light is reflected in a given direction (view direction) from a given direction (light direction). Usually (for most materials) we approximate a BRDF using a *diffuse term* and a *specular term*." ContentLicense="CC BY-SA 3.0" />
  <row Id="14938" PostHistoryTypeId="2" PostId="5485" RevisionGUID="4ea1133d-947f-48bf-b809-7362e830a92e" CreationDate="2017-08-09T15:55:00.263" UserId="6046" Text="In the book Computer Graphics Principles and Practice, they use the term specular reflection when they want to imagine things resembling a mirror and glossy reflection when things like a polished door knob or an orange skin.&#xD;&#xA;&#xD;&#xA;The charts shows you exactly that. When a material has more specular color, it should have less diffuse color due to the conservation of energy. Hence when you increase the specular color the material tends to go white or have a slight tint of the color like in metals. &#xD;&#xA;&#xD;&#xA;Where as glossy surfaces can have more diffuse color but show a specular highlight like the surface of an orange skin." ContentLicense="CC BY-SA 3.0" />
  <row Id="14939" PostHistoryTypeId="5" PostId="5485" RevisionGUID="1aaa8e7e-c611-4c13-a555-78f55353390e" CreationDate="2017-08-09T16:02:45.520" UserId="6046" Comment="added 182 characters in body" Text="In the book Computer Graphics Principles and Practice, they use the term specular reflection when they want to imagine things resembling a mirror and glossy reflection when things like a polished door knob or an orange skin.&#xD;&#xA;&#xD;&#xA;The charts shows you exactly that. When a material has more specular color, it should have less diffuse color due to the conservation of energy. That is, the sum of the light reflected specularly and light absorbed and emitted in random directions must be less than equal to 100% (the amount of light incident on the surface). Hence when you increase the specular color the material tends to go white or have a slight tint of the color like in metals. &#xD;&#xA;&#xD;&#xA;Where as glossy surfaces can have more diffuse color but show a specular highlight like the surface of an orange skin.&#xD;&#xA;&#xD;&#xA;So assuming the CGPP's point of view, we can say in pure specular reflection, the diffuse part is much less than the glossy part. Where as in glossy reflection the diffuse part is usually greater." ContentLicense="CC BY-SA 3.0" />
  <row Id="14940" PostHistoryTypeId="2" PostId="5486" RevisionGUID="82b5a949-7832-49e0-95bc-b381008ed995" CreationDate="2017-08-10T02:57:16.860" UserId="5944" Text="In my opinion, geometric surface normal is the cross product of triangle edges, and shading surface normal is the interpolation of the predefined normals at the three vertexes." ContentLicense="CC BY-SA 3.0" />
  <row Id="14941" PostHistoryTypeId="1" PostId="5486" RevisionGUID="82b5a949-7832-49e0-95bc-b381008ed995" CreationDate="2017-08-10T02:57:16.860" UserId="5944" Text="What's the difference between geometric surface normal and shading surface normal?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14942" PostHistoryTypeId="3" PostId="5486" RevisionGUID="82b5a949-7832-49e0-95bc-b381008ed995" CreationDate="2017-08-10T02:57:16.860" UserId="5944" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14943" PostHistoryTypeId="5" PostId="5486" RevisionGUID="f3e38564-7b3e-4bab-adb4-3cbfca6f749e" CreationDate="2017-08-10T03:30:17.840" UserId="5944" Comment="added 301 characters in body; edited tags" Text="In my opinion, geometric surface normal is the cross product of triangle edge vectors, and shading surface normal is the interpolation of the predefined normals at the three vertexes.&#xD;&#xA;&#xD;&#xA;I used Mitsuba to render the geometric normal channel and the shading normal channel:&#xD;&#xA;&#xD;&#xA;geometric normal:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;shading normal:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Slwfb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TOW4d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14944" PostHistoryTypeId="6" PostId="5486" RevisionGUID="f3e38564-7b3e-4bab-adb4-3cbfca6f749e" CreationDate="2017-08-10T03:30:17.840" UserId="5944" Comment="added 301 characters in body; edited tags" Text="|computational-geometry|geometry|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14945" PostHistoryTypeId="5" PostId="5482" RevisionGUID="fa661642-12a4-462b-a2eb-a79ce196c927" CreationDate="2017-08-10T03:58:21.990" UserId="5944" Comment="added 83 characters in body" Text="What is the difference between glossy and specular reflection?&#xD;&#xA;&#xD;&#xA;What is their relations with BRDF?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mqALR.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ic1g1.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/gIaQ5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14946" PostHistoryTypeId="2" PostId="5487" RevisionGUID="a2d4c6c7-566f-4e10-a043-668c381a513d" CreationDate="2017-08-10T06:15:27.740" UserId="5944" Text="Are there some tools or softwares to merge multiple exr into a single multilayer exr?&#xD;&#xA;&#xD;&#xA;I only find a tool to split a multilayer exr into multiple exr.&#xD;&#xA;&#xD;&#xA;And it seems that Blender, Mitsuba, Darktable all can't do this.&#xD;&#xA;&#xD;&#xA;Should I write a tool myself using OpenEXR?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14947" PostHistoryTypeId="1" PostId="5487" RevisionGUID="a2d4c6c7-566f-4e10-a043-668c381a513d" CreationDate="2017-08-10T06:15:27.740" UserId="5944" Text="How to merge multiple exr into a single multilayer exr?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14948" PostHistoryTypeId="3" PostId="5487" RevisionGUID="a2d4c6c7-566f-4e10-a043-668c381a513d" CreationDate="2017-08-10T06:15:27.740" UserId="5944" Text="|image-processing|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14949" PostHistoryTypeId="2" PostId="5488" RevisionGUID="d1dc57d5-ed27-4c58-b5aa-ab47ce6aa04a" CreationDate="2017-08-10T08:54:46.260" UserId="2041" Text="Your existing opinion is correct, though there's one extra detail. The geometric normal is the normal of the actual triangle, based on the vertices' positions (the cross-product of edge vectors, as you said). The shading normal is altered from this, and is used when shading a fragment or ray hit. In the simple case, it's the interpolation of the three normals set at the vertices. This is used for curved objects to hide the polygon boundaries. It might also be modified by a bump map or normal map, to add finer detail to the appearance than the polygon mesh has." ContentLicense="CC BY-SA 3.0" />
  <row Id="14950" PostHistoryTypeId="2" PostId="5489" RevisionGUID="173c7a4c-4126-463c-835e-9247ab7697d5" CreationDate="2017-08-10T09:26:23.707" UserId="7107" Text="Today I found something really interesting (I've never seen something like that). While debugging the buffers used in lightning, I see that the depth information is stored in what looks like cascades of depth.&#xD;&#xA;&#xD;&#xA;[![UE4 Depth Buffer][1]][1]&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/brV9I.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What's going on there? Is that a technique to improve depth precision?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="14951" PostHistoryTypeId="1" PostId="5489" RevisionGUID="173c7a4c-4126-463c-835e-9247ab7697d5" CreationDate="2017-08-10T09:26:23.707" UserId="7107" Text="How does UnrealEngine handle depth?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14952" PostHistoryTypeId="3" PostId="5489" RevisionGUID="173c7a4c-4126-463c-835e-9247ab7697d5" CreationDate="2017-08-10T09:26:23.707" UserId="7107" Text="|lighting|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14953" PostHistoryTypeId="2" PostId="5490" RevisionGUID="10376238-6cb4-4a17-b39e-99607e294005" CreationDate="2017-08-10T12:25:57.527" UserId="7138" Text="Let's say I have a lighting lobe represented as a ndotl ramp texture, how do I compress it into a zonal harmonic?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14954" PostHistoryTypeId="1" PostId="5490" RevisionGUID="10376238-6cb4-4a17-b39e-99607e294005" CreationDate="2017-08-10T12:25:57.527" UserId="7138" Text="Lighting ramps compressed to zonal harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="14955" PostHistoryTypeId="3" PostId="5490" RevisionGUID="10376238-6cb4-4a17-b39e-99607e294005" CreationDate="2017-08-10T12:25:57.527" UserId="7138" Text="|lighting|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14956" PostHistoryTypeId="50" PostId="4972" RevisionGUID="6376a613-acda-4fce-95b2-2c59b7bdee4d" CreationDate="2017-08-10T13:29:45.910" UserId="-1" />
  <row Id="14958" PostHistoryTypeId="2" PostId="5491" RevisionGUID="ccc45b20-35dc-46fd-b442-738674ba4771" CreationDate="2017-08-11T02:47:36.090" UserId="5646" Text="Get the title problem when implementing a walkthrough camera.&#xD;&#xA;&#xD;&#xA;I use normlize(cross(WorldUp, Front)) to get Right vector. And when they are collinear, I get a zero vector.&#xD;&#xA;&#xD;&#xA;Is there any more robust fake version? Or do I need to store the &quot;previous&quot; Right vector as a backup?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14959" PostHistoryTypeId="1" PostId="5491" RevisionGUID="ccc45b20-35dc-46fd-b442-738674ba4771" CreationDate="2017-08-11T02:47:36.090" UserId="5646" Text="How to get camera Right vector when Front vector and WorldUp vector are collinear" ContentLicense="CC BY-SA 3.0" />
  <row Id="14960" PostHistoryTypeId="3" PostId="5491" RevisionGUID="ccc45b20-35dc-46fd-b442-738674ba4771" CreationDate="2017-08-11T02:47:36.090" UserId="5646" Text="|transformations|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14963" PostHistoryTypeId="2" PostId="5492" RevisionGUID="3b8bf6da-0917-48b6-8d01-c2e8a946c9fd" CreationDate="2017-08-11T16:05:54.240" UserId="2041" Text="You can't have a camera with collinear look/front and up vectors. It doesn't make geometric sense. The whole point of the up vector is to disambiguate roll.&#xD;&#xA;&#xD;&#xA;As russ says, for a &quot;first-person&quot; camera it's reasonable to always use world-up for the up vector and simply lock the pitch angle to within (say) 85 degrees of horizontal, to avoid degenerate cases.&#xD;&#xA;&#xD;&#xA;For a CAD viewer where the user would expect to pitch the camera arbitrarily, you should rotate **both** the up and front vectors about the right vector when the user pitches the camera, to ensure they are always perpendicular. Beware that when you do this kind of arbitrary rotation, it's easy for the user to get stuck in unfortunate roll angles. You need to do at least one of the following to let them get themselves out:&#xD;&#xA;&#xD;&#xA;1. Have a &quot;reset up&quot; button that applies the pitch angle limits and resets the up vector to world up.&#xD;&#xA;1. Give the user arbitrary control over camera roll. (This can be confusing, so it's best to offer the first option as well if you do this.)&#xD;&#xA;1. Constrain the up vector so that its dot product with the world up is non-negative. That is, if the user pitches so far up or down that they are upside-down, roll the camera 180 degrees." ContentLicense="CC BY-SA 3.0" />
  <row Id="14969" PostHistoryTypeId="2" PostId="5494" RevisionGUID="88b74943-22dd-4421-a81a-876a3fb51926" CreationDate="2017-08-12T20:24:14.457" UserId="5256" Text="Currently I'm 16 and in high school and I love graphics programming and I'm seriously considering it as a career path. I was wondering what a day as a graphics programmer looks like for offline Rendering (path tracing).&#xD;&#xA;&#xD;&#xA;Since were close to hitting photorealism now it seems like the only main challenge for the next decade is performance. I've been digging through the recent SIGGRAPH papers for the Future directions for rendering but haven't found much.&#xD;&#xA;&#xD;&#xA;So what kinda tasks can graphics programmers do these days? Working on performance can't be the only thing.&#xD;&#xA;&#xD;&#xA;Also, is a lot of the work research based as opposed to traditional programming? " ContentLicense="CC BY-SA 3.0" />
  <row Id="14970" PostHistoryTypeId="1" PostId="5494" RevisionGUID="88b74943-22dd-4421-a81a-876a3fb51926" CreationDate="2017-08-12T20:24:14.457" UserId="5256" Text="Tasks of a professional graphics programmer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14971" PostHistoryTypeId="3" PostId="5494" RevisionGUID="88b74943-22dd-4421-a81a-876a3fb51926" CreationDate="2017-08-12T20:24:14.457" UserId="5256" Text="|pathtracing|performance|pbr|photo-realistic|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14972" PostHistoryTypeId="2" PostId="5495" RevisionGUID="a1038ca5-cf73-49db-9d21-62551636209d" CreationDate="2017-08-12T20:34:06.070" UserId="6046" Text="First of all instead of taking `Cross(WorldUp, Front/LookAt)` you can use Gram-Schmidt orthogonalization to produce an orthogonal vector that's close to the WorldUp vector. Then you take the cross of this orthogonal vector and the look at to get the side vector. However as you mentioned this'd fail if the vectors are parallel.&#xD;&#xA;&#xD;&#xA;Hence the usual solution is to pick another vector that's not parallel to the look at one and again use Gram-Schmidt orthogonalization to produce the orthogonal vector ( camera up) and then take the cross.&#xD;&#xA;&#xD;&#xA;The maths is like this. &#xD;&#xA;&#xD;&#xA;    CameraUp = c&#xD;&#xA;    WorldUp = w&#xD;&#xA;    LookAt = l&#xD;&#xA;&#xD;&#xA;    c = w - ( (w.l) / ||l||^2 ) * l &#xD;&#xA;&#xD;&#xA;What it does is this. We know that world up isn't pure orthogonal to the look at vector. So we take the projection of world up onto the direction of the look at vector. Subtract the parallel part of this projection from the world up vector to obtain the remaining i.e. the orthogonal part. This vector is closer to the world up but is purely orthogonal to the look at vector.&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="14973" PostHistoryTypeId="2" PostId="5496" RevisionGUID="c8a008bc-0aa2-43f1-8f74-f3dc86bff19c" CreationDate="2017-08-13T02:06:13.890" UserId="3003" Text="I don't know if this is exactly what you're looking for. I work tangentially in the film and TV industry. I don't work for a studio, but I work on the software that studios use for their productions. It's software that any user could buy if they wanted to, but it has been used in feature films, television shows, commercials, music videos, and more.&#xD;&#xA;&#xD;&#xA;About half of my time is spent programming and debugging. This is the fun stuff. It involves implementing rendering and filters of various types, sometimes based on papers I've read from SIGGRAPH or cool web sites or book. I don't do very much user interface work, though there is some. I work with OpenGL and Metal mostly. I need to know image processing algorithms in addition to general computer science algorithms, like graph processing and traversing, for example. This includes dealing with source control, continuous integration, stepping through code to find and fix bugs, talking to QA about problems, etc.&#xD;&#xA;&#xD;&#xA;The other half of my time is spent doing non-programming things. This is a variety of things like attending conferences to learn (things like the Game Developers Conference or SIGGRAPH), conventions to promote the company and/or product (things like NAB, IBC, etc.), answering tech support emails and writing sample code (we have an API so 3rd parties can extend our product), attending meetings (scrum, management updates, company-wide meetings, etc.), talking with marketing about how our new features work, meeting with customers to understand how they use the product, explaining to our documentation people how the product works so they can document it, etc.&#xD;&#xA;&#xD;&#xA;This seems like a pretty similar breakdown to other programming jobs in other industries from talking to my friends who work in other areas." ContentLicense="CC BY-SA 3.0" />
  <row Id="14974" PostHistoryTypeId="2" PostId="5497" RevisionGUID="87d8cd51-aa8d-4712-b349-12606323da8d" CreationDate="2017-08-14T10:00:35.807" UserId="7151" Text="I'm doing some parallel computing using my GPU. When I used glDispatchCompute first the program crashed after a few seconds which I found out was due to TDR. I deactivated TDR using the registry key TdrLevel and setting it to 0. Now it works for up to a few minutes but if the computation takes too long (about 3+ minutes) the function seems to return but then the program instantly crashes. Any ideas what the problem could be? The function always seems to fully execute, even if it takes 30 minutes to do so but right after that the program crashes which makes me think that it is not just another layer of TDR because it would probably kill the program after a certain amount of time." ContentLicense="CC BY-SA 3.0" />
  <row Id="14975" PostHistoryTypeId="1" PostId="5497" RevisionGUID="87d8cd51-aa8d-4712-b349-12606323da8d" CreationDate="2017-08-14T10:00:35.807" UserId="7151" Text="C++/OpenGL program crashes after return of glDispatchCompute function (TDR related?)" ContentLicense="CC BY-SA 3.0" />
  <row Id="14976" PostHistoryTypeId="3" PostId="5497" RevisionGUID="87d8cd51-aa8d-4712-b349-12606323da8d" CreationDate="2017-08-14T10:00:35.807" UserId="7151" Text="|opengl|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14977" PostHistoryTypeId="5" PostId="5497" RevisionGUID="ac856179-3b3e-4a26-88e2-ff3d471498dc" CreationDate="2017-08-14T11:28:05.703" UserId="7151" Comment="added 244 characters in body" Text="I'm doing some parallel computing using my GPU. When I used glDispatchCompute first the program crashed after a few seconds which I found out was due to TDR. I deactivated TDR using the registry key TdrLevel and setting it to 0. Now it works for up to a few minutes but if the computation takes too long (about 3+ minutes) the function seems to return but then the program instantly crashes. Any ideas what the problem could be? The function always seems to fully execute, even if it takes 30 minutes to do so but right after that the program crashes which makes me think that it is not just another layer of TDR because it would probably kill the program after a certain amount of time.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;There is an error message: &quot;Unable to communicate with display driver&quot; and &quot;Error code 2&quot;.&#xD;&#xA;I'm using a Nvidia Quadro M2000M, newest drivers are installed. TDR is disabled and Nvidia energy options are set to maximum (from adaptive)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14978" PostHistoryTypeId="2" PostId="5498" RevisionGUID="84187d36-8ae9-438e-b5cf-402c463ce549" CreationDate="2017-08-14T17:43:49.423" UserId="2064" Text="I'm implementing normal mapping on my toy pathtracer. I need to compute the tangent (and bitangent) of any sphere point in order to create the matrix that will transform tangent space to world space.&#xD;&#xA;&#xD;&#xA;More specifically, I want the tangent that runs along the u texture coordinate, and the bitangent that runs along the v coordinate.&#xD;&#xA;&#xD;&#xA;Here's how I implemented it:&#xD;&#xA;&#xD;&#xA; - At the intersection point P, compute the spherical coordinates&#xD;&#xA;   (theta, phi) of P.&#xD;&#xA; - Add a tiny delta to the angle that relates to the u texture&#xD;&#xA;   coordinate (phi), finding another point Q on the sphere.&#xD;&#xA; - Compute Q - P and normalize it to have the tangent.&#xD;&#xA; - The bitangent is then computed by doing the cross product of the&#xD;&#xA;   tangent and the normal at the point P.&#xD;&#xA;&#xD;&#xA;Relevant code on the sphere collision function:&#xD;&#xA;&#xD;&#xA;        hitRecord.point = ray.pointAtParameter(t);&#xD;&#xA;&#xD;&#xA;        Vec3 localCoord = hitRecord.point - center;&#xD;&#xA;    	float theta = asin(localCoord.y / radius); //[-pi/2,pi/2]&#xD;&#xA;    	float phi = atan2(localCoord.z, localCoord.x); //[-pi,+pi]&#xD;&#xA;    &#xD;&#xA;    	float deltaPhi = phi + FLOAT_BIAS;&#xD;&#xA;    	Vec3 deltaPoint(radius * cos(theta) * cos(deltaPhi),&#xD;&#xA;    		radius * sin(theta),&#xD;&#xA;    		radius * cos(theta) * sin(deltaPhi));&#xD;&#xA;    &#xD;&#xA;    	//Assume local space to be aligned with world space&#xD;&#xA;    	//So this is also the tangent in world space&#xD;&#xA;    	hitRecord.tangent = deltaPoint - localCoord;&#xD;&#xA;    	hitRecord.tangent.normalize();&#xD;&#xA;    &#xD;&#xA;    	hitRecord.normal = localCoord / radius;&#xD;&#xA;    	hitRecord.bitangent = hitRecord.tangent.cross(hitRecord.normal);&#xD;&#xA;    	hitRecord.bitangent.normalize();&#xD;&#xA;&#xD;&#xA;This seems to work, but all this trigonometry is not light and makes me wonder if there is a better way of doing it. Does anyone has any ideias/pointers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14979" PostHistoryTypeId="1" PostId="5498" RevisionGUID="84187d36-8ae9-438e-b5cf-402c463ce549" CreationDate="2017-08-14T17:43:49.423" UserId="2064" Text="Compute sphere tangent for normal mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="14980" PostHistoryTypeId="3" PostId="5498" RevisionGUID="84187d36-8ae9-438e-b5cf-402c463ce549" CreationDate="2017-08-14T17:43:49.423" UserId="2064" Text="|raytracing|pathtracing|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14981" PostHistoryTypeId="50" PostId="5300" RevisionGUID="8506a17c-6e9e-4208-8204-f695a21f7f5b" CreationDate="2017-08-14T22:09:06.257" UserId="-1" />
  <row Id="14982" PostHistoryTypeId="2" PostId="5499" RevisionGUID="fe682855-d48d-489d-9c09-b3fa9b8f8af2" CreationDate="2017-08-14T22:22:22.820" UserId="48" Text="You can do this a little bit more efficiently and accurately by calculating derivatives of $P$ with respect to $u, v$—or the derivatives with respect to $\phi, \theta$, equivalently (up to a scalar multiple).&#xD;&#xA;&#xD;&#xA;Start by expressing $P$ in terms of the spherical coordinates:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;P_x &amp;= r \cos \theta \cos \phi \\&#xD;&#xA;P_y &amp;= r \sin \theta \\&#xD;&#xA;P_z &amp;= r \cos \theta \sin \phi&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;Now you can get the tangent as $T = \partial P / \partial \phi$, which works out as:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;T_x &amp;= -r \cos \theta \sin \phi \\&#xD;&#xA;T_y &amp;= 0 \\&#xD;&#xA;T_z &amp;= r \cos \theta \cos \phi&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;Once you normalize it, the $r \cos \theta$ factors drop out and you're left with just $T = (-\sin \phi, 0, \cos \phi)$. Pretty simple!&#xD;&#xA;&#xD;&#xA;You can similarly get the bitangent as $B = \partial P / \partial \theta$, or you can just calculate it as the cross product $N \times T$, which is probably faster. (Note it should be $N \times T$, not $T \times N$, assuming you want $T, B, N$ to form a right-handed basis in that order.)&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The above approach will work for pretty much any kind of surface that can be parameterized, not just spheres. However, in the case of spheres with the usual $\phi, \theta$ coordinates, there's an even quicker shortcut that you can do with just vector math, no trig at all. Let $C$ be the center of the sphere, and $A$ be a vector representing the axis of the spherical coordinates—i.e. pointing from the center toward the north pole. Then you can just calculate $T = \text{normalize}\bigl(A \times (P - C) \bigr)$, then $B = N \times T$ as before." ContentLicense="CC BY-SA 3.0" />
  <row Id="14983" PostHistoryTypeId="2" PostId="5500" RevisionGUID="ec8109f5-0355-4c26-a606-b4336e77082a" CreationDate="2017-08-15T00:50:32.770" UserId="7154" Text="Suppose I can run some graphics in 1366x768 equally well as 1280x720, and I have a 1920x1080 monitor.&#xD;&#xA;&#xD;&#xA;There are more pixels in 1366x768 than in 1280x720.  However, in 1280x720, a 2x2 grid of pixels fits exactly within a 3x3 grid of physical pixels in my monitor.&#xD;&#xA;&#xD;&#xA;So which should look better, and is there any theoretical basis for which one looks better?  Does the 3:2 ratio mean anything at all?" ContentLicense="CC BY-SA 3.0" />
  <row Id="14984" PostHistoryTypeId="1" PostId="5500" RevisionGUID="ec8109f5-0355-4c26-a606-b4336e77082a" CreationDate="2017-08-15T00:50:32.770" UserId="7154" Text="Upscaling 720p to 1080p vs upscaling 768p to 1080p" ContentLicense="CC BY-SA 3.0" />
  <row Id="14985" PostHistoryTypeId="3" PostId="5500" RevisionGUID="ec8109f5-0355-4c26-a606-b4336e77082a" CreationDate="2017-08-15T00:50:32.770" UserId="7154" Text="|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14986" PostHistoryTypeId="2" PostId="5501" RevisionGUID="726d435b-f4e8-4572-847d-197a5bf2eeb1" CreationDate="2017-08-15T15:28:16.820" UserId="48" Text="With a good-quality upscaling filter ([bicubic](https://en.wikipedia.org/wiki/Bicubic_interpolation), for example), there's no particular importance to the 3:2 ratio. Starting from a higher-resolution source will produce a better-looking final image.&#xD;&#xA;&#xD;&#xA;It's true that if you're programming the upscaler from scratch, making one for a fixed ratio like 3:2 is much simpler than making one that handles arbitrary ratios. But image-processing software, monitors, etc probably have arbitrary-ratio upscaling built in anyway." ContentLicense="CC BY-SA 3.0" />
  <row Id="14987" PostHistoryTypeId="2" PostId="5502" RevisionGUID="baf94fba-0009-4a30-97a7-7797f6a728f3" CreationDate="2017-08-16T08:52:47.000" UserId="5944" Text="In the book AGI (Advanced Global Illumination), the Phong BRDF is&#xD;&#xA;&#xD;&#xA;$f_r(x,\Psi\leftrightarrow\Theta)=k_s\cfrac{(R\cdot\Phi)^n}{N\cdot\Psi}+k_d$&#xD;&#xA;&#xD;&#xA;$k_d=\cfrac{albedo}\pi$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In Mitsuba and Tungsten, the Phong BRDF is &#xD;&#xA;&#xD;&#xA;$f_r(x,\Psi\leftrightarrow\Theta)=[\cfrac{ratio_{diffuse}}\pi+\cfrac{(R\cdot\Theta)^n(n+2)(1-ratio_{diffuse})}{2\pi}]\cdot albedo$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Why there is a $\cfrac{n+2}{2\pi}$ in the specular part?&#xD;&#xA;&#xD;&#xA;What's the relation between the two BRDFs?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="14988" PostHistoryTypeId="1" PostId="5502" RevisionGUID="baf94fba-0009-4a30-97a7-7797f6a728f3" CreationDate="2017-08-16T08:52:47.000" UserId="5944" Text="Phong BRDF in Mitsuba, Tungsten and AGI" ContentLicense="CC BY-SA 3.0" />
  <row Id="14989" PostHistoryTypeId="3" PostId="5502" RevisionGUID="baf94fba-0009-4a30-97a7-7797f6a728f3" CreationDate="2017-08-16T08:52:47.000" UserId="5944" Text="|pathtracing|brdf|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="14990" PostHistoryTypeId="5" PostId="5502" RevisionGUID="18413c8e-ca45-49c5-a67e-83dec908ef58" CreationDate="2017-08-16T09:10:19.797" UserId="5944" Comment="added 71 characters in body" Text="[![reflection][1]][1]&#xD;&#xA;&#xD;&#xA;In the book AGI (Advanced Global Illumination), the Phong BRDF is&#xD;&#xA;&#xD;&#xA;$f_r(x,\Psi\leftrightarrow\Theta)=k_s\cfrac{(R\cdot\Phi)^n}{N\cdot\Psi}+k_d$&#xD;&#xA;&#xD;&#xA;$k_d=\cfrac{albedo}\pi$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In Mitsuba and Tungsten, the Phong BRDF is &#xD;&#xA;&#xD;&#xA;$f_r(x,\Psi\leftrightarrow\Theta)=[\cfrac{ratio_{diffuse}}\pi+\cfrac{(R\cdot\Theta)^n(n+2)(1-ratio_{diffuse})}{2\pi}]\cdot albedo$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Why there is a $\cfrac{n+2}{2\pi}$ in the specular part?&#xD;&#xA;&#xD;&#xA;What's the relation between the two BRDFs?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SSqzx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14991" PostHistoryTypeId="2" PostId="5503" RevisionGUID="c4df2a74-9a0e-4534-9568-2b5738f5d0e8" CreationDate="2017-08-16T09:16:36.053" UserId="4546" Text="It's the normalization factor to make sure the BRDF always reflects the same amount of energy regardless of the value of the specular exponent n. Without that factor, changing the specular exponent changes the overall reflectance of the material.&#xD;&#xA;&#xD;&#xA;Further reading: http://www.thetenthplanet.de/archives/255" ContentLicense="CC BY-SA 3.0" />
  <row Id="14992" PostHistoryTypeId="5" PostId="5502" RevisionGUID="78d5f4a3-94dd-4caf-820e-e833c374f071" CreationDate="2017-08-16T09:18:52.977" UserId="5944" Comment="added 2 characters in body" Text="[![reflection][1]][1]&#xD;&#xA;&#xD;&#xA;In the book AGI (Advanced Global Illumination), the Phong BRDF is&#xD;&#xA;&#xD;&#xA;$f_r(x,\Psi\leftrightarrow\Theta)=k_s\cfrac{(R\cdot\Theta)^n}{N\cdot\Psi}+k_d$&#xD;&#xA;&#xD;&#xA;$k_d=\cfrac{albedo}\pi$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In Mitsuba and Tungsten, the Phong BRDF is &#xD;&#xA;&#xD;&#xA;$f_r(x,\Psi\leftrightarrow\Theta)=[\cfrac{ratio_{diffuse}}\pi+\cfrac{(R\cdot\Theta)^n(n+2)(1-ratio_{diffuse})}{2\pi}]\cdot albedo$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Why there is a $\cfrac{n+2}{2\pi}$ in the specular part?&#xD;&#xA;&#xD;&#xA;What's the relation between the two BRDFs?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SSqzx.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="14993" PostHistoryTypeId="2" PostId="5504" RevisionGUID="7c891904-0ef4-4879-90e1-b517250c0650" CreationDate="2017-08-16T15:27:36.590" UserId="5026" Text="Gloss and Specularity are features of the surface. In modern PBR terms we usually refer to the smoothness and metalness of a surface instead (unless you use a specular workflow, then metalness is still linked to specular).&#xD;&#xA;&#xD;&#xA;Basically, dielectric surfaces reflect around 4% of light in a specular way, and the rest is diffuse. Metallic surfaces reflect no light diffused, and all specular. Specular light bounces directly back to the eye and shows clear reflections of the environment more. Diffuse bounces around a lot more and therefore gives a more matte result. Gloss is another term for smoothness of a surface. When a surface is rougher its specular light is bounced all over, and so the reflection appears more blurry.&#xD;&#xA;&#xD;&#xA;TL;DR: Specular is how shiny it is and usually is higher with metals. Gloss is how clear the reflections are.&#xD;&#xA;&#xD;&#xA;Keep in mind that there are some surfaces that don't fall into the metalness workflow, especially when they have a coat on top. There are also materials in between metal and dielectric (semiconductors / metalloids)." ContentLicense="CC BY-SA 3.0" />
  <row Id="14998" PostHistoryTypeId="5" PostId="3744" RevisionGUID="8201cd6d-a0df-42e8-b787-773612772649" CreationDate="2017-08-17T10:30:40.403" UserId="7167" Comment="Clean up sentences" Text="I'm sadly not able to add a comment to the answer above (not enough reputation), so I will do it like this.&#xD;&#xA;&#xD;&#xA;I'd like to point out that what Dragonseel describes is simply an integral equation (specifically a Fredholm equation of the second kind). There are many such equations which do have an analytic solution; even some forms of the rendering equation have one (e.g. the solution of a white furnace can be given using a simple convergent geometric series, even though the rendering equation is infinitely recursive).&#xD;&#xA;&#xD;&#xA;It is also not necessary to bias the estimated solution by bounding the number of recursions. Russian Roulette provides an useful tool for giving us an unbiased solution for an infinitely recursive rendering equation.&#xD;&#xA;&#xD;&#xA;The main difficulty lies in the fact that the functions for reflectance (BRDF), emitted radiance and visibility are highly complex and often contain many discontinuities. In these cases there often is no analytic solution, or it is simply unfeasible to find such a solution. This is also true in the one dimensional case; most integrals lack analytic solutions.&#xD;&#xA;&#xD;&#xA;Finally I'd like to note that even though most cases of the rendering equation do not have analytic solutions, there is a lot of research in forms of the rendering equation which do have an analytic solution. Using such solutions (as approximations) when possible can significantly reduce noise and can speed up rendering times." ContentLicense="CC BY-SA 3.0" />
  <row Id="14999" PostHistoryTypeId="24" PostId="3744" RevisionGUID="8201cd6d-a0df-42e8-b787-773612772649" CreationDate="2017-08-17T10:30:40.403" Comment="Proposed by 7167 approved by 4958, 2041 edit id of 263" ContentLicense="CC BY-SA 3.0" />
  <row Id="15000" PostHistoryTypeId="5" PostId="3740" RevisionGUID="4c4c1770-cf4f-4d18-8bcd-799ca79a94da" CreationDate="2017-08-17T10:30:58.570" UserId="7167" Comment="Make more concise and correct typos" Text="The rendering equation is as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now, the integral is over the sphere around the point $x$.&#xD;&#xA;You integrate over some attenuated light, incoming from every direction.&#xD;&#xA;&#xD;&#xA;But how much light comes in? This is the light $L(x',w_i)$ that some other point $x'$ reflects in the direction $w_i$ of point $x$.&#xD;&#xA;&#xD;&#xA;Now you have to calculate how much light that new point $x'$ reflects, which requires solving the rendering equation for that point. And the solution for that point depends on a huge number of other points, including $x$.&#xD;&#xA;&#xD;&#xA;In short, the rendering equation is infinitely recursive.&#xD;&#xA;&#xD;&#xA;You cannot solve it exactly and analytically because it has infinite integrals over infinite integration domains.&#xD;&#xA;&#xD;&#xA;But since light gets weaker each time it is reflected, at some point a human simply cannot notice the difference any more. And so you do not actually solve the rendering equation, but you limit the number of recursions (say reflections) to something that is 'close enough'.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d9L29.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15001" PostHistoryTypeId="24" PostId="3740" RevisionGUID="4c4c1770-cf4f-4d18-8bcd-799ca79a94da" CreationDate="2017-08-17T10:30:58.570" Comment="Proposed by 7167 approved by 4958, 2041 edit id of 262" ContentLicense="CC BY-SA 3.0" />
  <row Id="15002" PostHistoryTypeId="5" PostId="3738" RevisionGUID="87bce4e0-28a9-4b30-b4a7-c7daefc590f2" CreationDate="2017-08-17T10:31:03.923" UserId="7167" Comment="Fix grammar" Text="Why is the rendering equation, introduced by Kajiya in 1986, not solvable directly/analytically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15003" PostHistoryTypeId="24" PostId="3738" RevisionGUID="87bce4e0-28a9-4b30-b4a7-c7daefc590f2" CreationDate="2017-08-17T10:31:03.923" Comment="Proposed by 7167 approved by 4958, 2041 edit id of 264" ContentLicense="CC BY-SA 3.0" />
  <row Id="15004" PostHistoryTypeId="5" PostId="5456" RevisionGUID="e3d737ad-e77f-45b5-b15d-5567e97ceaf1" CreationDate="2017-08-17T14:06:14.830" UserId="5703" Comment="Added MathJax" Text="&gt; How should I define the `radiance`, if I have a directional light, for example the sun?&#xD;&#xA;&#xD;&#xA;The radiance in physics has different definitions in different books. I will use the definition with irradiance and radiant flux here.&#xD;&#xA;&#xD;&#xA;Imagine photons having some energy $Q$. Your **radiant flux** $\Phi$ is the amount of energy $Q$ (and therefore the amount of photons) per unit time $t$. To get the energy for an instant (an infinitesimally short time), you use the change ($\Delta$) of energy over the change of time for $\lim_{t\rightarrow0}$ i.e.&#xD;&#xA;&#xD;&#xA;$$\Phi = \lim_{t\rightarrow0} \frac{\Delta Q}{ \Delta t} = \frac{dQ}{dt}$$&#xD;&#xA;&#xD;&#xA;Energy is measured in Joules and time in seconds, therefore radiant flux is measured in $\frac{J}{s}$.&#xD;&#xA;&#xD;&#xA;This however doesn't say anything about the surface you're measuring the energy at, but if you want to light an object, that needs to be taken into account.&#xD;&#xA;Therefore, you define **irradiance** $E$ as your radiant flux per area $A$ (note that irradiance usually means energy arriving at an area, whereas *radiosity* is energy leaving the area, but is otherwise defined exactly the same way). Since some integrations later on are easier to do with infinitesimally small area patches, we go that route again, but I will not rewrite the limes stuff all the time.&#xD;&#xA;&#xD;&#xA;$$E = \frac{d\Phi}{dA}$$&#xD;&#xA;&#xD;&#xA;Note that it is assumed, that the photons' traveling direction is assumed to be perpendicular to the surface.&#xD;&#xA;Irradiance is thus measured in $\frac{J}{sm^2}$.&#xD;&#xA;&#xD;&#xA;To understand radiance, you need to understand solid angles. I will just assume that you do, otherwise read up on it, this is really an important concept for physically based lighting.&#xD;&#xA;&#xD;&#xA;The problem with irradiance is, that you cannot take into consideration any directionality of the light. The directionality can be expressed through solid angles $\omega$, where an infinitesimally small solid angle $d\omega$ can be seen as a vector.&#xD;&#xA;&#xD;&#xA;Imagine that you have a sheet of paper parallel to another sheet of paper, one emitting and one receiving light, both equal in size. You can express all you need with irradiance. Now let the emitting sheet of paper transform into your light bulb centered at where the emitting sheet of paper was before. All of a sudden, it makes a difference, if you measure the light at the corners of the receiving sheet of paper or at its center.&#xD;&#xA;&#xD;&#xA;Therefore, to take directionality into account, you define **radiance** $L$ as the irradiance per solid angle of the light. $\omega$ is the solid angle and we want to use the infinitessimally small one again, thus $d\omega$.&#xD;&#xA;$$L = \frac{dE}{d\omega}$$&#xD;&#xA;Thus your radiance is measured in $\frac{J}{sm^2sr}$ where sr is the solid angle unit steradians and really is dimensionles. &#xD;&#xA;&#xD;&#xA;Looking at the definitions of Watts it's $W = \frac{J}{s}$ , therefore radiance measurement can be seen as $\frac{W}{m^2sr}$.&#xD;&#xA;&#xD;&#xA;**Edit 04th of August 2017:**&#xD;&#xA;The radiance in the end is exactly what you calculate as a pixel's color, it is what you see. In the real world, it is wave length dependend, but of course in computer graphics it is an RGB color vector. Therefore, **you don't define radiance, you calculate it.**&#xD;&#xA;&#xD;&#xA;&gt; What should the `lightColor` be, if the light source is a 60W lightbulb (780 lm) and in my scene one unit is one cm?&#xD;&#xA;&#xD;&#xA;Light usually uses different wave lengths lambda which determine the color of the light. For example, imagine a photon of red light, i.e. $\lambda=700nm$ , then it has the energy of $\frac{hc}{\lambda}$ where $h$ is Planck's constant and $c$ is the speed of light, leading to about $2.838\times10^{-19}J$ for this red photon.&#xD;&#xA;&#xD;&#xA;If your light bulb &quot;uses&quot; just one single wave length and is a $60W=60\frac{J}{s}$ light bulb, then you can calculate the energy, radiant flux, irradiance and finally radiance... If you know the exact spectral emission, you can also calculate this.&#xD;&#xA;However, that is probably not really what you are looking for.&#xD;&#xA;&#xD;&#xA;**Edited 04th of August 2017:**&#xD;&#xA;Therefore, your (or rather the tutorials code) to calculate radiance is an oversimplified way of modeling the lightsource.  It does not take into account the power of the light source directly, it is just modelled by a color vector.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What the tutorial is asking you to do is to think of the color you want your light to be, and write down the RGB value for it. If your light is just white, use an RGB value of (1,1,1), try it in your scene and if you then think it's too bright, lower the values until you're satisfied (or increase them, if it's not bright enough).&#xD;&#xA;&#xD;&#xA;**Edited 04th of August 2017:**&#xD;&#xA;If you want to use the physically based light bulb, then you will need to take more into account and I'd really advice you to read up on this.&#xD;&#xA;A good book for this is Physically Based Rendering (by Matt Pharr et al.). &#xD;&#xA;As that is expensive and takes a long time to read, you can also try to get along with some of the Physically Based Shading course materials of previous years, to be found [on the Selfshadow Blog][1]. Especially, there is some explanation on Sebastien Lagarde's [Moving Frostbite to Physically Based Rendering][2]&#xD;&#xA;&#xD;&#xA;On a side note, the sun is usually modeled as being so distant to the receiver of the light, that you don't take attenuation into account. Thus you would just multiply by the light color (or set the attenuation to 1).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/archives/&#xD;&#xA;  [2]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15005" PostHistoryTypeId="24" PostId="5456" RevisionGUID="e3d737ad-e77f-45b5-b15d-5567e97ceaf1" CreationDate="2017-08-17T14:06:14.830" Comment="Proposed by 5703 approved by 209, 273 edit id of 265" ContentLicense="CC BY-SA 3.0" />
  <row Id="15006" PostHistoryTypeId="5" PostId="4198" RevisionGUID="6f57cc00-e912-4bcc-8c5f-796b2c61f8f9" CreationDate="2017-08-17T20:22:34.490" UserId="7167" Comment="Clean up sentences" Text="Radiosity is a way to calculate diffuse GI, i.e. every surface is assumed to be Lambertian surface without specular component. In the radiosity algorithm you split surfaces into small patches and calculate &quot;form factor&quot; between two patches, which defines how much energy is transferred from one patch to the other.&#xD;&#xA;&#xD;&#xA;The form factor between patches is calculated using the distance between patches (patches further apart means less energy transferred between them), their respective orientation (two patches facing each other transfer more energy than when they face away from each other), the visibility (if patch is occluded, it doesn't transfer energy to the patch) and their size (larger surfaces emit more energy). The form factor obeys reciprocity which means that the factor for patches A and B can be used for energy transmission calculation from A to B and from B to A.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To calculate radiosity for a patch, you iterate through all patches and accumulate the energy from other patches using their respective form factors and the luminance of each patch. This is a single iteration of the radiosity algorithm, and for multiple light bounces you can run multiple iterations of this same algorithm. This can be implemented for example by rendering a hemicube around each patch and accumulating the result from the cube for each patch.&#xD;&#xA;&#xD;&#xA;To answer your question if radiosity is a full GI solution - no it's not. Since all surfaces are Lambertian, there's no specular component to it, so you would need to use other techniques in addition for the full lighting solution. The result of radiosity is usually also cached into lightmaps with limited resolution so you may need to use AO to provide higher frequency lighting details.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yh4v5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15007" PostHistoryTypeId="24" PostId="4198" RevisionGUID="6f57cc00-e912-4bcc-8c5f-796b2c61f8f9" CreationDate="2017-08-17T20:22:34.490" Comment="Proposed by 7167 approved by -1 edit id of 266" ContentLicense="CC BY-SA 3.0" />
  <row Id="15008" PostHistoryTypeId="5" PostId="4198" RevisionGUID="83ee6dcb-6c30-43cb-823e-609ae07e157e" CreationDate="2017-08-17T20:22:34.490" UserId="4958" Comment="Clean up sentences" Text="Radiosity is a way to calculate diffuse GI, i.e. every surface is assumed to be Lambertian surface without specular component. In the radiosity algorithm you split surfaces into small patches and calculate &quot;form factor&quot; between two patches, which defines how much energy is transferred from one patch to the other.&#xD;&#xA;&#xD;&#xA;The form factor between patches is calculated using the distance between patches (patches further apart means less energy transferred between them), their respective orientation (two patches facing each other transfer more energy than when they face away from each other), the visibility (if patch is occluded, it doesn't transfer energy to the patch) and their size (larger surfaces emit more energy). The form factor obeys reciprocity which means that the factor for patches A and B can be used for energy transmission calculation from A to B and from B to A.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To calculate radiosity for a patch, you iterate through all patches and accumulate the energy from other patches using their respective form factors and the luminance of each patch. This is a single iteration of the radiosity algorithm, and for multiple light bounces you can run multiple iterations of this same algorithm. This can be implemented for example by rendering scene around each patch to a hemicube and accumulating the result from the cube for each patch.&#xD;&#xA;&#xD;&#xA;To answer your question if radiosity is a full GI solution - no it's not. Since all surfaces are Lambertian, there's no specular component to it, so you would need to use other techniques in addition for the full lighting solution. The result of radiosity is usually also cached into lightmaps with limited resolution so you may need to use AO to provide higher frequency lighting details.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yh4v5.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15010" PostHistoryTypeId="2" PostId="5506" RevisionGUID="a67cd589-cf6d-43cd-af1f-3746337dce91" CreationDate="2017-08-18T04:30:20.457" UserId="7072" Text="I have a very basic grasp of computer graphics however I threw it all away when I wrote this simple application that I am using for scientific purposes. I didn't have a lot of time to write it correctly because my &quot;bosses&quot; didn't see the promise of it but now that it is done they have found it quite useful.&#xD;&#xA;&#xD;&#xA;The problem is I built it stupidly.&#xD;&#xA;&#xD;&#xA;Basically it takes a TON of points stored in a big array and draws them to the screen. The screen can be moved and zoomed.&#xD;&#xA;&#xD;&#xA;Instead of using a matrix to accomplish this I am simply passing in the width, height and center of the screen making my average vertex shader look like so&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout (location = 0) in float ex;&#xD;&#xA;    layout (location = 1) in float ey;&#xD;&#xA;    &#xD;&#xA;    uniform float sizeX;&#xD;&#xA;    uniform float sizeY;&#xD;&#xA;    uniform float centerX;&#xD;&#xA;    uniform float centerY;&#xD;&#xA;    uniform float size;&#xD;&#xA;    &#xD;&#xA;    out vec4 color;&#xD;&#xA;    out float passsize;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	gl_PointSize = size;&#xD;&#xA;    	passsize = size;&#xD;&#xA;    	float x = (ex - centerX) / (sizeX / 2.0);&#xD;&#xA;    	float y = (ey - centerY) / (sizeY / 2.0);&#xD;&#xA;    	gl_Position = vec4(x, y, 0.0, 1.0);&#xD;&#xA;    &#xD;&#xA;    	color = vec4(1.0f, 0.5f, 0.2f, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and an average draw call look about like this&#xD;&#xA;&#xD;&#xA;    glUseProgram(program);&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO1);&#xD;&#xA;	glBindVertexArray(VAO1);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;VBO1);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO1);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO1);&#xD;&#xA;	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;VBO2);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO2);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);&#xD;&#xA;	glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;	glUniform1f(glGetUniformLocation(program, &quot;centerX&quot;), centerX);&#xD;&#xA;	glUniform1f(glGetUniformLocation(program, &quot;centerY&quot;), centerY);&#xD;&#xA;	glUniform1f(glGetUniformLocation(program, &quot;sizeX&quot;), scrwidth);&#xD;&#xA;	glUniform1f(glGetUniformLocation(program, &quot;sizeY&quot;), scrheight);&#xD;&#xA;	glUniform1f(glGetUniformLocation(program, &quot;size&quot;), dotSize);&#xD;&#xA;&#xD;&#xA;	glDrawArrays(GL_POINTS, 0, dot count);&#xD;&#xA;	glfwSwapBuffers(window);&#xD;&#xA;	glfwPollEvents();&#xD;&#xA;&#xD;&#xA;This works very well but I would love to get rid of the low frame rate this causes when I am drawing a ton of points (generally over 10,000 on my small laptop that doesn't actually have a GPU).&#xD;&#xA;&#xD;&#xA;Is there any way I can get the GPU to more intelligently clip points that are going to be off screen?&#xD;&#xA;&#xD;&#xA;I don't have a lot of time to change things around so it would be great if it were something simple to achieve.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15011" PostHistoryTypeId="1" PostId="5506" RevisionGUID="a67cd589-cf6d-43cd-af1f-3746337dce91" CreationDate="2017-08-18T04:30:20.457" UserId="7072" Text="Is there a way I can make this easier for openGL to draw?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15012" PostHistoryTypeId="3" PostId="5506" RevisionGUID="a67cd589-cf6d-43cd-af1f-3746337dce91" CreationDate="2017-08-18T04:30:20.457" UserId="7072" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15013" PostHistoryTypeId="2" PostId="5507" RevisionGUID="a718725c-e7df-4932-8a80-d436ae26a622" CreationDate="2017-08-18T08:29:59.387" UserId="137" Text="You only need to create the VBOs and VAO once and then you can reuse them every frame.&#xD;&#xA;&#xD;&#xA;    void init(){&#xD;&#xA;    &#xD;&#xA;        glGenVertexArrays(1, &amp;VAO1);&#xD;&#xA;        glBindVertexArray(VAO1);&#xD;&#xA;        &#xD;&#xA;        glGenBuffers(1, &amp;VBO1);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO1);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO1);&#xD;&#xA;        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;        &#xD;&#xA;        glGenBuffers(1, &amp;VBO2);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO2);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);&#xD;&#xA;        glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;        glEnableVertexAttribArray(1);&#xD;&#xA;    &#xD;&#xA;        uniformLoc_centerX = glGetUniformLocation(program, &quot;centerX&quot;);&#xD;&#xA;        uniformLoc_centerY = glGetUniformLocation(program, &quot;centerY&quot;);&#xD;&#xA;        uniformLoc_sizeX = glGetUniformLocation(program, &quot;sizeX&quot;);&#xD;&#xA;        uniformLoc_sizeY = glGetUniformLocation(program, &quot;sizeY&quot;);&#xD;&#xA;        uniformLoc_size= glGetUniformLocation(program, &quot;size&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void draw(){&#xD;&#xA;        glUseProgram(program);&#xD;&#xA;        glBindVertexArray(VAO1);&#xD;&#xA;&#xD;&#xA;        glUniform1f(uniformLoc_centerX, centerX);&#xD;&#xA;        glUniform1f(uniformLoc_centerY, centerY);&#xD;&#xA;        glUniform1f(uniformLoc_sizeX, scrwidth);&#xD;&#xA;        glUniform1f(uniformLoc_sizeY, scrheight);&#xD;&#xA;        glUniform1f(uniformLoc_size, dotSize);&#xD;&#xA;&#xD;&#xA;        glDrawArrays(GL_POINTS, 0, dot count);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If the data ever changes then all you need to do is:&#xD;&#xA;&#xD;&#xA;    glGenBuffers(1, &amp;VBO1);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO2);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);" ContentLicense="CC BY-SA 3.0" />
  <row Id="15019" PostHistoryTypeId="2" PostId="5509" RevisionGUID="9b33278f-e421-41e2-988a-19f87c89118b" CreationDate="2017-08-19T09:31:27.877" UserId="7177" Text="I made a convolution testing program for experimenting with stuff. I've created a 5x5 Gaussian kernel for blurring. Everything looked fine, then I tried to blur a transparent png with a white circle in the middle. On the blurred image, the edge looks like a gradient from white to black.&#xD;&#xA;This is mathematically correct, because the transparent points are treated as black, transparent pixels, so the convolution should gradually give darker colors near the edge.&#xD;&#xA;But if I do a gaussian blur on the same image e.g. in GIMP, the circle will be fully white, with gradually more transparency toward the edges. I'd like to get this effect. What am I missing?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15020" PostHistoryTypeId="1" PostId="5509" RevisionGUID="9b33278f-e421-41e2-988a-19f87c89118b" CreationDate="2017-08-19T09:31:27.877" UserId="7177" Text="Gaussian blur with transparency" ContentLicense="CC BY-SA 3.0" />
  <row Id="15021" PostHistoryTypeId="3" PostId="5509" RevisionGUID="9b33278f-e421-41e2-988a-19f87c89118b" CreationDate="2017-08-19T09:31:27.877" UserId="7177" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15022" PostHistoryTypeId="5" PostId="3740" RevisionGUID="64ac57df-e3c2-4989-9c3f-4ddb68521408" CreationDate="2017-08-19T09:41:00.650" UserDisplayName="user106" Comment="w \ne \omega" Text="The rendering equation is as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now, the integral is over the sphere around the point $x$.&#xD;&#xA;You integrate over some attenuated light, incoming from every direction.&#xD;&#xA;&#xD;&#xA;But how much light comes in? This is the light $L(x',\omega_i)$ that some other point $x'$ reflects in the direction $\omega_i$ of point $x$.&#xD;&#xA;&#xD;&#xA;Now you have to calculate how much light that new point $x'$ reflects, which requires solving the rendering equation for that point. And the solution for that point depends on a huge number of other points, including $x$.&#xD;&#xA;&#xD;&#xA;In short, the rendering equation is infinitely recursive.&#xD;&#xA;&#xD;&#xA;You cannot solve it exactly and analytically because it has infinite integrals over infinite integration domains.&#xD;&#xA;&#xD;&#xA;But since light gets weaker each time it is reflected, at some point a human simply cannot notice the difference any more. And so you do not actually solve the rendering equation, but you limit the number of recursions (say reflections) to something that is 'close enough'.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d9L29.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15023" PostHistoryTypeId="24" PostId="3740" RevisionGUID="64ac57df-e3c2-4989-9c3f-4ddb68521408" CreationDate="2017-08-19T09:41:00.650" Comment="Proposed by 106 approved by 4958, 231 edit id of 267" ContentLicense="CC BY-SA 3.0" />
  <row Id="15028" PostHistoryTypeId="2" PostId="5510" RevisionGUID="6e4fa14d-6f20-4a8a-92ef-eba50137a935" CreationDate="2017-08-19T11:27:04.580" UserId="7178" Text="How do you load your image?&#xD;&#xA;&#xD;&#xA;Maybe your image is loaded as RGB instead of RGB-A, which means you are totally ignoring Alpha channel (the transparency value). In this case the transparent pixels are converted into black ones.&#xD;&#xA;&#xD;&#xA;If you are using OpenCV library, [this article][1] might help you load the image with 4-channels (into a 4-dimensional array); then you are able to apply Gaussian-blur function on every 4 channels and get the desired result.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/3803888/opencv-how-to-load-png-images-with-4-channels" ContentLicense="CC BY-SA 3.0" />
  <row Id="15029" PostHistoryTypeId="5" PostId="5509" RevisionGUID="3423e1ca-c0c0-4835-8491-fc9eb1717972" CreationDate="2017-08-19T11:45:26.557" UserId="7177" Comment="added pictures" Text="I made a convolution testing program for experimenting with stuff. I've created a 5x5 Gaussian kernel for blurring. Everything looked fine, then I tried to blur a transparent png with a white circle in the middle. On the blurred image, the edge looks like a gradient from white to black.&#xD;&#xA;This is mathematically correct, because the transparent points are treated as black, transparent pixels, so the convolution should gradually give darker colors near the edge.&#xD;&#xA;But if I do a gaussian blur on the same image e.g. in GIMP, the circle will be fully white, with gradually more transparency toward the edges. I'd like to get this effect. What am I missing?&#xD;&#xA;&#xD;&#xA;If I set the transparent pixels to transparent white, it'll work, but only if the blurred color is white.&#xD;&#xA;&#xD;&#xA;This is the original image:&#xD;&#xA;[![The original image][1]][1]&#xD;&#xA;&#xD;&#xA;This is the result I get if I left the transparent pixels on default:&#xD;&#xA;[![Blur on the original][2]][2]&#xD;&#xA;&#xD;&#xA;And if I set the transparent pixels to #00FFFFFF, I'll get this (this is the intended IF the blurred color is white)&#xD;&#xA;&#xD;&#xA;[![Intended result][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v6Tdw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/u00CV.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/BfVw8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15030" PostHistoryTypeId="2" PostId="5511" RevisionGUID="235c160b-4939-4734-bffc-568afe8eea36" CreationDate="2017-08-19T11:55:10.607" UserId="7177" Text="As it turned out, I forgot to weight the color channel by the transparency, so I got the same issue as written here:&#xD;&#xA;[Blur Transparency Bug][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.imagemagick.org/Usage/bugs/blur_trans/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15031" PostHistoryTypeId="2" PostId="5512" RevisionGUID="49f0f761-20b2-449b-8404-c4282a1dad08" CreationDate="2017-08-20T07:22:06.270" UserId="7180" Text="For the past month, I have been learning on my own and writing a little graphics library and am currently working on the transformation of vertex normals to soon support lighting/shading. I understand how if I transform the vertices by a matrix **M** that I need to apply the inverse-transpose of M (i.e., (**M**^-1 )^T ) to the surface normals. However, I am struggling to understand how this &quot;rule&quot; can be applied to all of the basic transformations (translate, scale, rotate) ... particularly, translation.&#xD;&#xA;&#xD;&#xA;Using a homogeneous (w) coordinate in a 4D vector class, a Translate(x, y, z) would have no effect on a normal since its w-coordinate is 0, indicating that it is a vector, not a point. However, when we transpose the inverse of the Translate then it would have an effect on the normal (which feels incorrect). &#xD;&#xA;&#xD;&#xA;For example, let's say that we have created a 3D triangle and want to apply a basic Translate(1, 2, 3) to the three vertices' positions. Based upon the &quot;rule&quot; for transforming vertex normals (i.e., inverse-transpose), we should be multiplying the three vertices' normals by Transpose(Translate(-1, -2, -3)). However, this feels incorrect since a vertex normal should remain unaffected by Translation and only be affected by Rotation and Scaling. &#xD;&#xA;&#xD;&#xA;Any help in understanding how the inverse-transpose can be applied to vertex normals would be greatly appreciated!&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15032" PostHistoryTypeId="1" PostId="5512" RevisionGUID="49f0f761-20b2-449b-8404-c4282a1dad08" CreationDate="2017-08-20T07:22:06.270" UserId="7180" Text="Inverse-Transpose of Vertex Normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="15033" PostHistoryTypeId="3" PostId="5512" RevisionGUID="49f0f761-20b2-449b-8404-c4282a1dad08" CreationDate="2017-08-20T07:22:06.270" UserId="7180" Text="|3d|transformations|matrix|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15034" PostHistoryTypeId="2" PostId="5513" RevisionGUID="2a3e3957-5c7a-4f1b-9b15-39bc2ae94288" CreationDate="2017-08-20T09:35:52.587" UserId="7181" Text="I am trying to figure out the correct order between edges on edge table on scan line polygon fill.&#xD;&#xA;&#xD;&#xA;One example here on `Y=1` takes first `AB` line&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And another example takes on `Y=0` `v1v0`.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I cannot understand why not `AB` instead of `BA` and why `v1v0` instead of `v0v1` respectively&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XYs28.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2cLWP.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15035" PostHistoryTypeId="1" PostId="5513" RevisionGUID="2a3e3957-5c7a-4f1b-9b15-39bc2ae94288" CreationDate="2017-08-20T09:35:52.587" UserId="7181" Text="Scan Line Polygon Fill Edge Table Entry Order" ContentLicense="CC BY-SA 3.0" />
  <row Id="15036" PostHistoryTypeId="3" PostId="5513" RevisionGUID="2a3e3957-5c7a-4f1b-9b15-39bc2ae94288" CreationDate="2017-08-20T09:35:52.587" UserId="7181" Text="|polygon|scanline|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15039" PostHistoryTypeId="2" PostId="5515" RevisionGUID="83ab3df6-c41a-4601-a645-d88d6b776096" CreationDate="2017-08-20T16:24:38.197" UserId="5240" Text="To start with, you should (almost) never have a glGen*() call in your render loop. Do that during initialization only. &#xA;&#xA;It looks like your vertex data isn't changing. Don't re-set the buffer data, just send it once during initialization. &#xA;&#xA;For the application you've described, about the only thing that should be in your render loop is bindBuffer, setting your uniforms, clear, draw and present. &#xA;&#xA;Fixing those issues will likely have a significant perf impact. If that still isn't enough, look at spatial partitioning and frustum culling - in 2D, your frustum is just going to be a box - to more intelligently clip your data CPU-side. Google &quot;quad trees&quot; to get started. &#xA;&#xA;Also, depending on the use case, you MIGHT be better off just doing this in Unity or another off-the-shelf engine. They already provide much of this functionality.  (However, I'm all for roll-your-own  for the fun factor, and a full engine may be overkill for this.)&#xA;&#xA;And never forget: the profiler is your friend. Without it, everything else is just professional guessing. " ContentLicense="CC BY-SA 3.0" />
  <row Id="15040" PostHistoryTypeId="2" PostId="5516" RevisionGUID="14f8f2bd-69bb-4f70-a861-5fd485c57670" CreationDate="2017-08-21T09:40:09.877" UserId="6046" Text="You are correct, when they are talking about taking the inverse-transpose they are talking about the 3x3 part of the affine transformation leaving the translation since it doesn't affect the normal vector. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Check&#xD;&#xA;https://en.wikipedia.org/wiki/Normal_(geometry)#Transforming_normals&#xD;&#xA;&#xD;&#xA;About how or why is it the inverse transpose, a simple explanation, that is also given in the book &quot;Essential Mathematics for Games&quot; is&#xD;&#xA;&#xD;&#xA;Suppose we have a Point `P` and a normal vector `n`. Then we know that&#xD;&#xA;&#xD;&#xA;`(n)T P = 0  // where T stands for traspose`&#xD;&#xA;&#xD;&#xA;Now if we apply a transformation matrix `M` to point `P`, we'll have to apply some sort of transformation matrix `Q` to `n` also.&#xD;&#xA;&#xD;&#xA;` (Q*n)T M*P =  0`&#xD;&#xA;&#xD;&#xA;`(n)T * (Q)T *  M * P = 0`&#xD;&#xA;&#xD;&#xA;One solution is&#xD;&#xA;&#xD;&#xA;`(Q)T * M = I`&#xD;&#xA;&#xD;&#xA;`Q = ((M)^-1)T`&#xD;&#xA;&#xD;&#xA;Hence the inverse transpose. This stands for any sort of transformation matrix `M` be it scaling, rotation etc. Also for pure rotation matrix, since they are orthogonal, the matrix transforming the normals is the same as that of the vertices. as ` ( (M)T )T = M`" ContentLicense="CC BY-SA 3.0" />
  <row Id="15041" PostHistoryTypeId="5" PostId="5516" RevisionGUID="1fa916e4-0348-46e4-a1d3-a9d86df0ab01" CreationDate="2017-08-21T09:54:36.477" UserId="2041" Comment="Replace the hard-to-read code formatting with mathjax. I don't think I changed the meaning of the maths, but I don't believe that n^T P = 0. Also it's normal for points to be a lower-case p, because they're vectors, not matrices." Text="You are correct, when they are talking about taking the inverse-transpose they are talking about the 3x3 part of the affine transformation leaving the translation since it doesn't affect the normal vector. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Check&#xD;&#xA;https://en.wikipedia.org/wiki/Normal_(geometry)#Transforming_normals&#xD;&#xA;&#xD;&#xA;About how or why is it the inverse transpose, a simple explanation, that is also given in the book &quot;Essential Mathematics for Games&quot; is&#xD;&#xA;&#xD;&#xA;Suppose we have a Point $P$ and a normal vector $n$. Then we know that&#xD;&#xA;$$&#xD;&#xA;n^T P = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now if we apply a transformation matrix $M$ to point $P$, we'll have to apply some sort of transformation matrix $Q$ to $n$ also.&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;(Q n)^T M P &amp; = &amp; 0 \\&#xD;&#xA;n^T Q^T M P &amp; = &amp; 0&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;One solution is&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;Q^T M &amp; = &amp; I \\&#xD;&#xA;Q &amp; = &amp; {M^{-1}}^T&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;Hence the inverse transpose. This stands for any sort of transformation matrix $M$ be it scaling, rotation etc. Also for pure rotation matrix, since they are orthogonal, the matrix transforming the normals is the same as that of the vertices. as ${M^T}^T = M$" ContentLicense="CC BY-SA 3.0" />
  <row Id="15042" PostHistoryTypeId="5" PostId="5516" RevisionGUID="f46d7e67-b76c-4f07-a5da-1e0a8e565a94" CreationDate="2017-08-21T09:58:39.810" UserId="6046" Comment="added 70 characters in body" Text="You are correct, when they are talking about taking the inverse-transpose they are talking about the 3x3 part of the affine transformation leaving the translation since it doesn't affect the normal vector. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Check&#xD;&#xA;https://en.wikipedia.org/wiki/Normal_(geometry)#Transforming_normals&#xD;&#xA;&#xD;&#xA;About how or why is it the inverse transpose, a simple explanation, that is also given in the book &quot;Essential Mathematics for Games&quot; is&#xD;&#xA;&#xD;&#xA;Suppose we have a Point $P$ and a normal vector $n$ both represented by column matrix. Then we know that&#xD;&#xA;$$&#xD;&#xA;n^T P = 0&#xD;&#xA;$$&#xD;&#xA;This is the same as the dot product.&#xD;&#xA;Now if we apply a transformation matrix $M$ to point $P$, we'll have to apply some sort of transformation matrix $Q$ to $n$ also.&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;(Q n)^T M P &amp; = &amp; 0 \\&#xD;&#xA;n^T Q^T M P &amp; = &amp; 0&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;One solution is&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;Q^T M &amp; = &amp; I \\&#xD;&#xA;Q &amp; = &amp; {M^{-1}}^T&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;Hence the inverse transpose. This stands for any sort of transformation matrix $M$ be it scaling, rotation etc. Also for pure rotation matrix, since they are orthogonal, the matrix transforming the normals is the same as that of the vertices. as ${M^T}^T = M$" ContentLicense="CC BY-SA 3.0" />
  <row Id="15045" PostHistoryTypeId="2" PostId="5517" RevisionGUID="e3d4bbfa-41ad-4018-829a-a9209ca22471" CreationDate="2017-08-21T16:27:25.710" UserId="209" Text="I apologise for only skimming through your question/answer and the links you gave but I thought it would be a good idea to post what needs to be done to *correctly* do any blending and/or filtering on images with an alpha channel.&#xD;&#xA;&#xD;&#xA;The first thing to note is that all calculations should be done in a linear colour space, but the image data in PNGs and JPEGs is most likely to be in [sRGB][2] which is non-linear. You should convert this data to a linear form before doing any calculations. For example, the average of black (0,0,0) and white (255,255,255) in sRGB is not (127,127,127) but (off the top of my head) something like (186,186,186). Images, especially filtering of saturated colours can look quite odd if you don't take gamma into account.&#xD;&#xA;&#xD;&#xA;The second part of this theory dates back to Porter and Duff's seminal 1984 paper, &quot;[Compositing Digital Images][1]&quot;, which introduces the concept of pre-multiplied alpha. Pre-multiplied alpha basically means that you multiply the RGBs by the alpha value before doing calculations. &#xD;&#xA;&#xD;&#xA;I get the feeling this was initially done just to reduce computation costs but in his article &quot;Compositing-Theory&quot;, Jim Blinn shows that the correct way to do any filtering or compositing operations is to first convert everything to premultipled. &#xD;&#xA;&#xD;&#xA;Once you have linearised and then pre-multiplied you pixel data, you can do your filtering/blending and, when done, undo the pre-multiply and reapply the gamma function to map back to sRGB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://keithp.com/~keithp/porterduff/p253-porter.pdf&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/SRGB" ContentLicense="CC BY-SA 3.0" />
  <row Id="15046" PostHistoryTypeId="2" PostId="5518" RevisionGUID="5d4251bb-ef5d-4c16-92d8-ced9b9df5661" CreationDate="2017-08-22T01:21:03.783" UserId="7185" Text="I have a series of images obtained from a microscope as follows&#xD;&#xA;&#xD;&#xA;[![Time step 3][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I need to create a series of filters that would isolate the centre section    on the yellow droplet.(This is highlighted by the bright yellow circle area), and remove all the noise and other pictures.&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;I tried using just RGB  channel threshold but its not working. Also ambient light may also change so I am not getting a consistent output. Can anyone provide a MWE for the workflow of the filter required in MATLAB to achieve this?&#xD;&#xA;&#xD;&#xA;  [3]: https://i.stack.imgur.com/qCMPx.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/epfyH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15047" PostHistoryTypeId="1" PostId="5518" RevisionGUID="5d4251bb-ef5d-4c16-92d8-ced9b9df5661" CreationDate="2017-08-22T01:21:03.783" UserId="7185" Text="Appropriate filter steps for resolving a droplet pixel" ContentLicense="CC BY-SA 3.0" />
  <row Id="15048" PostHistoryTypeId="3" PostId="5518" RevisionGUID="5d4251bb-ef5d-4c16-92d8-ced9b9df5661" CreationDate="2017-08-22T01:21:03.783" UserId="7185" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15050" PostHistoryTypeId="2" PostId="5519" RevisionGUID="5e5c70ed-ed33-4f87-ae15-85a916b47b3c" CreationDate="2017-08-22T05:39:09.370" UserId="7178" Text="First simple thresholding is usually not a good idea. However, if you want to do that, I suggest to also consider other [color spaces][1]. In your case, [HSV][2] might be a better choice; You can convert your image into HSV-image then you can define a range on Hue channel to select yellow.&#xD;&#xA;&#xD;&#xA;Also, take a look at [this article][3]; it is about implementing **Adaptive Thresholding**.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_space&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/HSL_and_HSV&#xD;&#xA;  [3]: http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="15051" PostHistoryTypeId="2" PostId="5520" RevisionGUID="33a2a03f-9c91-4aad-ad58-30712e704012" CreationDate="2017-08-22T07:31:11.597" UserId="6041" Text="I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][1]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample along for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; &#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; &#xD;&#xA;    &#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent + &#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48()) * sunDirection; &#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different with the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [2]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15052" PostHistoryTypeId="1" PostId="5520" RevisionGUID="33a2a03f-9c91-4aad-ad58-30712e704012" CreationDate="2017-08-22T07:31:11.597" UserId="6041" Text="Using Monte carlo on Rayleigh scattering" ContentLicense="CC BY-SA 3.0" />
  <row Id="15053" PostHistoryTypeId="3" PostId="5520" RevisionGUID="33a2a03f-9c91-4aad-ad58-30712e704012" CreationDate="2017-08-22T07:31:11.597" UserId="6041" Text="|pathtracing|global-illumination|distribution|volumetric-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15054" PostHistoryTypeId="5" PostId="5520" RevisionGUID="15a6770e-b9d1-483d-a4df-f6f52c78fd7e" CreationDate="2017-08-22T08:21:26.173" UserId="6041" Comment="added 4117 characters in body" Text="I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][1]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample along for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;      public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;            {&#xD;&#xA;                Vector estimatedColor = new Vector();&#xD;&#xA;    &#xD;&#xA;                Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;    &#xD;&#xA;                ISect isect = Scene.Trace(ray);&#xD;&#xA;                if (ISect.IsNull(isect))&#xD;&#xA;                    estimatedColor = Atmosph.ComputeIncidentLight(ray);&#xD;&#xA;                else&#xD;&#xA;                    estimatedColor = isect.Thing.Material.Emission + &#xD;&#xA;                                          ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;                ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;      public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;            {&#xD;&#xA;                r.Start.Z += earthRadius;&#xD;&#xA;    &#xD;&#xA;                ISect isect = earth.Intersect(r);&#xD;&#xA;                if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;                &#xD;&#xA;                int numSamples = 1;&#xD;&#xA;                int numSamplesLight = 1;&#xD;&#xA;                double segmentLength = isect.Dist / numSamples;&#xD;&#xA;                double tCurrent = 0;&#xD;&#xA;                Vector sumR = Vector.ZERO;&#xD;&#xA;                Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;                double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;                double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;                double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;                double g = 0.76f;&#xD;&#xA;                double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;                for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;                {&#xD;&#xA;                    Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;                    double height = samplePosition.Length() - earthRadius;&#xD;&#xA;                    // compute optical depth for light&#xD;&#xA;                    double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;                    double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;                    opticalDepthR += hr;&#xD;&#xA;                    opticalDepthM += hm;&#xD;&#xA;                    // light optical depth&#xD;&#xA;                    ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;                    double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;                    double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;                    int j;&#xD;&#xA;                    for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;                    {&#xD;&#xA;                        Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                        double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                        if (heightLight &lt; 0) break;&#xD;&#xA;                        opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                        opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                        tCurrentLight += segmentLengthLight;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == numSamplesLight)&#xD;&#xA;                    {&#xD;&#xA;                        Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                        Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                        sumR += attenuation * hr;&#xD;&#xA;                        sumM += attenuation * hm;&#xD;&#xA;                    }&#xD;&#xA;                    tCurrent += segmentLength;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;                // scientific in a future revision of this lesson/code&#xD;&#xA;                return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different with the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [2]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15055" PostHistoryTypeId="5" PostId="5520" RevisionGUID="244e8029-bd5e-49f2-a6f2-a449b465bb7f" CreationDate="2017-08-22T08:27:14.377" UserId="6041" Comment="edited body" Text="I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][1]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;      public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;            {&#xD;&#xA;                Vector estimatedColor = new Vector();&#xD;&#xA;    &#xD;&#xA;                Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;    &#xD;&#xA;                ISect isect = Scene.Trace(ray);&#xD;&#xA;                if (ISect.IsNull(isect))&#xD;&#xA;                    estimatedColor = Atmosph.ComputeIncidentLight(ray, rand);&#xD;&#xA;                else&#xD;&#xA;                    estimatedColor = isect.Thing.Material.Emission + &#xD;&#xA;                                          ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;                ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;      public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;            {&#xD;&#xA;                r.Start.Z += earthRadius;&#xD;&#xA;    &#xD;&#xA;                ISect isect = earth.Intersect(r);&#xD;&#xA;                if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;                &#xD;&#xA;                int numSamples = 1;&#xD;&#xA;                int numSamplesLight = 1;&#xD;&#xA;                double segmentLength = isect.Dist / numSamples;&#xD;&#xA;                double tCurrent = 0;&#xD;&#xA;                Vector sumR = Vector.ZERO;&#xD;&#xA;                Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;                double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;                double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;                double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;                double g = 0.76f;&#xD;&#xA;                double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;                for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;                {&#xD;&#xA;                    Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;                    double height = samplePosition.Length() - earthRadius;&#xD;&#xA;                    // compute optical depth for light&#xD;&#xA;                    double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;                    double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;                    opticalDepthR += hr;&#xD;&#xA;                    opticalDepthM += hm;&#xD;&#xA;                    // light optical depth&#xD;&#xA;                    ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;                    double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;                    double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;                    int j;&#xD;&#xA;                    for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;                    {&#xD;&#xA;                        Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                        double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                        if (heightLight &lt; 0) break;&#xD;&#xA;                        opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                        opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                        tCurrentLight += segmentLengthLight;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == numSamplesLight)&#xD;&#xA;                    {&#xD;&#xA;                        Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                        Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                        sumR += attenuation * hr;&#xD;&#xA;                        sumM += attenuation * hm;&#xD;&#xA;                    }&#xD;&#xA;                    tCurrent += segmentLength;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;                // scientific in a future revision of this lesson/code&#xD;&#xA;                return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different with the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [2]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15056" PostHistoryTypeId="5" PostId="5517" RevisionGUID="44fc5629-da09-497b-a1fb-8d19b2783e68" CreationDate="2017-08-22T08:47:10.733" UserId="209" Comment="Added extra link" Text="I apologise for only skimming through your question/answer and the links you gave but I thought it would be a good idea to post what needs to be done to *correctly* do any blending and/or filtering on images with an alpha channel.&#xD;&#xA;&#xD;&#xA;The first thing to note is that all calculations should be done in a linear colour space, but the image data in PNGs and JPEGs is most likely to be in [sRGB][1] which is non-linear. You should convert this data to a linear form before doing any calculations. For example, the average of black (0,0,0) and white (255,255,255) in sRGB is not (127,127,127) but (off the top of my head) something like (186,186,186). Images, especially filtering of saturated colours can look quite odd if you don't take gamma into account.&#xD;&#xA;&#xD;&#xA;The second part of this theory dates back to Porter and Duff's seminal 1984 paper, &quot;[Compositing Digital Images][2]&quot;, which introduces the concept of pre-multiplied alpha. Pre-multiplied alpha basically means that you multiply the RGBs by the alpha value before doing calculations. &#xD;&#xA;&#xD;&#xA;I get the feeling this was initially done just to reduce computation costs but in his article [&quot;Compositing-Theory&quot;][3], Jim Blinn shows that the correct way to do any filtering or compositing operations is to first convert everything to premultipled. &#xD;&#xA;&#xD;&#xA;Once you have linearised and then pre-multiplied your pixel data, do the filtering/blending and, finally, undo the pre-multiply and reapply the gamma function to map back to sRGB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB&#xD;&#xA;  [2]: https://keithp.com/~keithp/porterduff/p253-porter.pdf&#xD;&#xA;  [3]: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.163.5748" ContentLicense="CC BY-SA 3.0" />
  <row Id="15057" PostHistoryTypeId="5" PostId="5520" RevisionGUID="77a9838d-adbc-4382-b62b-d8db775a620d" CreationDate="2017-08-22T11:09:53.023" UserId="6041" Comment="added 45 characters in body" Text="I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][1]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel(not sure why the sun is so small, any idea?):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;      public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;            {&#xD;&#xA;                Vector estimatedColor = new Vector();&#xD;&#xA;    &#xD;&#xA;                Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;    &#xD;&#xA;                ISect isect = Scene.Trace(ray);&#xD;&#xA;                if (ISect.IsNull(isect))&#xD;&#xA;                    estimatedColor = Atmosph.ComputeIncidentLight(ray, rand);&#xD;&#xA;                else&#xD;&#xA;                    estimatedColor = isect.Thing.Material.Emission + &#xD;&#xA;                                          ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;                ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;      public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;            {&#xD;&#xA;                r.Start.Z += earthRadius;&#xD;&#xA;    &#xD;&#xA;                ISect isect = earth.Intersect(r);&#xD;&#xA;                if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;                &#xD;&#xA;                int numSamples = 1;&#xD;&#xA;                int numSamplesLight = 1;&#xD;&#xA;                double segmentLength = isect.Dist / numSamples;&#xD;&#xA;                double tCurrent = 0;&#xD;&#xA;                Vector sumR = Vector.ZERO;&#xD;&#xA;                Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;                double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;                double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;                double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;                double g = 0.76f;&#xD;&#xA;                double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;                for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;                {&#xD;&#xA;                    Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;                    double height = samplePosition.Length() - earthRadius;&#xD;&#xA;                    // compute optical depth for light&#xD;&#xA;                    double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;                    double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;                    opticalDepthR += hr;&#xD;&#xA;                    opticalDepthM += hm;&#xD;&#xA;                    // light optical depth&#xD;&#xA;                    ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;                    double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;                    double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;                    int j;&#xD;&#xA;                    for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;                    {&#xD;&#xA;                        Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                        double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                        if (heightLight &lt; 0) break;&#xD;&#xA;                        opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                        opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                        tCurrentLight += segmentLengthLight;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == numSamplesLight)&#xD;&#xA;                    {&#xD;&#xA;                        Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                        Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                        sumR += attenuation * hr;&#xD;&#xA;                        sumM += attenuation * hm;&#xD;&#xA;                    }&#xD;&#xA;                    tCurrent += segmentLength;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;                // scientific in a future revision of this lesson/code&#xD;&#xA;                return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different from the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [2]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15058" PostHistoryTypeId="5" PostId="5520" RevisionGUID="1a43bed7-6b1f-43db-b97d-9fb3203e1e6e" CreationDate="2017-08-22T18:16:14.720" UserId="6041" Comment="added 80 characters in body" Text="I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][1]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel(not sure why the sun is so small, any idea?):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;The pdf is 1/segmentLength and the sample is taken uniformly in this distance.&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;      public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;            {&#xD;&#xA;                Vector estimatedColor = new Vector();&#xD;&#xA;    &#xD;&#xA;                Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;    &#xD;&#xA;                ISect isect = Scene.Trace(ray);&#xD;&#xA;                if (ISect.IsNull(isect))&#xD;&#xA;                    estimatedColor = Atmosph.ComputeIncidentLight(ray, rand);&#xD;&#xA;                else&#xD;&#xA;                    estimatedColor = isect.Thing.Material.Emission + &#xD;&#xA;                                          ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;                ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;      public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;            {&#xD;&#xA;                r.Start.Z += earthRadius;&#xD;&#xA;    &#xD;&#xA;                ISect isect = earth.Intersect(r);&#xD;&#xA;                if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;                &#xD;&#xA;                int numSamples = 1;&#xD;&#xA;                int numSamplesLight = 1;&#xD;&#xA;                double segmentLength = isect.Dist / numSamples;&#xD;&#xA;                double tCurrent = 0;&#xD;&#xA;                Vector sumR = Vector.ZERO;&#xD;&#xA;                Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;                double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;                double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;                double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;                double g = 0.76f;&#xD;&#xA;                double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;                for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;                {&#xD;&#xA;                    Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;                    double height = samplePosition.Length() - earthRadius;&#xD;&#xA;                    // compute optical depth for light&#xD;&#xA;                    double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;                    double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;                    opticalDepthR += hr;&#xD;&#xA;                    opticalDepthM += hm;&#xD;&#xA;                    // light optical depth&#xD;&#xA;                    ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;                    double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;                    double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;                    int j;&#xD;&#xA;                    for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;                    {&#xD;&#xA;                        Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                        double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                        if (heightLight &lt; 0) break;&#xD;&#xA;                        opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                        opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                        tCurrentLight += segmentLengthLight;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == numSamplesLight)&#xD;&#xA;                    {&#xD;&#xA;                        Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                        Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                        sumR += attenuation * hr;&#xD;&#xA;                        sumM += attenuation * hm;&#xD;&#xA;                    }&#xD;&#xA;                    tCurrent += segmentLength;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;                // scientific in a future revision of this lesson/code&#xD;&#xA;                return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different from the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [2]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15059" PostHistoryTypeId="2" PostId="5521" RevisionGUID="ca3a0c6e-7c8a-409f-abc4-8f8272fb0d6f" CreationDate="2017-08-23T05:38:04.923" UserId="1937" Text="As a pet project, I'm trying to build a small app that visualizes 4D polytopes. I want to use the [Wythoff Construction][1] method, where the shape is generated kaleidoscopically by the interaction of 4 mirrors using a single movable generator vertex. &#xD;&#xA;&#xD;&#xA;I know how to create a reflection matrix from a hypersurface normal, what I am looking for is an simple way to generate all possible matrices generated by the interreflections of the set of mirrors.&#xD;&#xA;&#xD;&#xA;The brute force method would be something like:&#xD;&#xA;&#xD;&#xA;    1: Create the initial set of mirrors and their matrices&#xD;&#xA;    2: Reflect each matrix in each of the other mirrors, add to temp list&#xD;&#xA;    3: Remove duplicates from temp list&#xD;&#xA;    4: Add temp list to master list and remove duplicates&#xD;&#xA;    5: Reflect each matrix in temp list through each mirror except its generating mirror &#xD;&#xA;       and add to new temp list&#xD;&#xA;    6: Repeat from step 3 with new temp list, continue until no non-duplicates found&#xD;&#xA;&#xD;&#xA;This method will work but will involve a huge amount of redundant computation generating, checking, and discarding duplicates, especially in symmetry groups like the 120-cell / 600-cell which contain thousands of permutations. Does anybody know of a more elegant method of creating the full set?&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Wythoff_construction" ContentLicense="CC BY-SA 3.0" />
  <row Id="15060" PostHistoryTypeId="1" PostId="5521" RevisionGUID="ca3a0c6e-7c8a-409f-abc4-8f8272fb0d6f" CreationDate="2017-08-23T05:38:04.923" UserId="1937" Text="Finding all possible reflection matrices for a given Wythoff construction" ContentLicense="CC BY-SA 3.0" />
  <row Id="15061" PostHistoryTypeId="3" PostId="5521" RevisionGUID="ca3a0c6e-7c8a-409f-abc4-8f8272fb0d6f" CreationDate="2017-08-23T05:38:04.923" UserId="1937" Text="|algorithm|matrix|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15062" PostHistoryTypeId="6" PostId="5518" RevisionGUID="46bedc39-a4a8-4330-8993-a13cf14173e4" CreationDate="2017-08-24T15:16:14.057" UserId="506" Comment="added a tag for the desired platform" Text="|image-processing|matlab|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15063" PostHistoryTypeId="24" PostId="5518" RevisionGUID="46bedc39-a4a8-4330-8993-a13cf14173e4" CreationDate="2017-08-24T15:16:14.057" Comment="Proposed by 506 approved by 4958, 231 edit id of 268" ContentLicense="CC BY-SA 3.0" />
  <row Id="15069" PostHistoryTypeId="2" PostId="5523" RevisionGUID="69ff8bb8-0908-48ba-a945-bec835ac05de" CreationDate="2017-08-24T15:50:24.077" UserId="7199" Text="https://www.shadertoy.com/results?query=bezier&#xD;&#xA;sort by age, in case of compatibility issues:&#xD;&#xA;&#xD;&#xA;,...shows many solutions of many spline-subsets, either returning the distance to a 2d spline, or tracing a 3d patch. Splines and patches come in many forms. heavensine beind simplest, bezier being simple, nurbs being overly complex. The more constrains yo add to your spline, the simpler it gets. NURBS is extension overkill; &#xD;&#xA;- its Non-Uniform-ness of weights (the &quot;NU&quot;) diminishes efficiency in comparison to to more symmetric splines &#xD;&#xA;- its Ration-al-ness (the R) also adds some complexity, for segmenting (rationing) and mixing with nearby segments (recursively solved).&#xD;&#xA;&#xD;&#xA;bezier-patch-tracing is root-solving and with that comes contextual prioritization on precision; in what order to solve the quadratic equation.&#xD;&#xA;this becomes impractical on higher exponents than cubic, due to exponential complexity and precision loss.&#xD;&#xA;&#xD;&#xA;ray-marching==sphere-tracking is the simpler heuristic approach to root-solving, which seems to be the simple and most efficient solution to rendering most splines patches.&#xD;&#xA;&#xD;&#xA;Lagrange-representation simplifies tracing/marching (as the L-points are ON the spline while the ControlVector-points (of the exact same spline) are rarely on the spline)&#xD;&#xA;&#xD;&#xA;The special case of a heavensine-spline, where first derivatives of stat and end are ==0. simplifies continuity and involves less differentials (less subtraction).&#xD;&#xA;A heavensine-patch can be traced efficiently in a single pass:&#xD;&#xA;https://www.shadertoy.com/view/4djfW3&#xD;&#xA;while other cubic (or higher) splines make the heuristic sphere-tracking/ray-marching approach more efficient (and &quot;precise enough&quot;) than daring to analytically calculate all the roots to keep the smallest positive root (with exponentially accumulating precision errors for each root).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;In computer graphics, splines and patches have been nearly completely replaced by z-brushing by 2006. z-brushing uses displacement maps with homogeneous coordinates, or even using a &quot;type&quot; that us a union of sphere and linesegments (linesegments have a radius of 0, spheres have a length of 0, a union is simple and useful). For a minor loss in precision for a big gain in performance at relatively low memory cost for a look-up-table, that is easily made dynamic on a gpu." ContentLicense="CC BY-SA 3.0" />
  <row Id="15070" PostHistoryTypeId="2" PostId="5524" RevisionGUID="ecacd826-d802-4f58-aed2-70a2bd10064c" CreationDate="2017-08-24T22:29:53.457" UserId="5406" Text="I have a screen-aligned texture resulting from multiple rendering passes. It looks  about this:&#xD;&#xA;&lt;p&gt;&lt;img src=&quot;https://i.stack.imgur.com/Adod4.png&quot; width=&quot;250&quot; alt=&quot;textureToBeSmoothed&quot;&gt;&lt;/p&gt;&#xD;&#xA;I want the edges to appear smoother than they do now (but still keep their characteristic shape). When zooming in, the blocky appearance becomes very obvious. Is there a common approach in computer graphics (or in OpenGL in particular) to resolve this? Since the texture results from the application of the [jump flooding algorithm](https://computergraphics.stackexchange.com/questions/4830/understanding-jump-flooding-algorithm-jfa-for-voronoi-diagrams) the what-ever approach has to be performed in a post-processing step. I'm so far just interested in the approach(es) itself, not in the implementation." ContentLicense="CC BY-SA 3.0" />
  <row Id="15071" PostHistoryTypeId="1" PostId="5524" RevisionGUID="ecacd826-d802-4f58-aed2-70a2bd10064c" CreationDate="2017-08-24T22:29:53.457" UserId="5406" Text="What is a common approach in computer graphics to smooth structures in textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15072" PostHistoryTypeId="3" PostId="5524" RevisionGUID="ecacd826-d802-4f58-aed2-70a2bd10064c" CreationDate="2017-08-24T22:29:53.457" UserId="5406" Text="|algorithm|image-processing|interpolation|filtering|post-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15078" PostHistoryTypeId="2" PostId="5526" RevisionGUID="4a1526db-78fe-44f7-a64c-93f810826640" CreationDate="2017-08-25T12:27:08.357" UserId="7205" Text="How is this 'w&lt;sub&gt;y&lt;/sub&gt;' equation for thick line segment derived?&#xD;&#xA;&#xD;&#xA;[![Thick line segment][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![equation][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EmgKN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/73syB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15079" PostHistoryTypeId="1" PostId="5526" RevisionGUID="4a1526db-78fe-44f7-a64c-93f810826640" CreationDate="2017-08-25T12:27:08.357" UserId="7205" Text="Thick Line segment" ContentLicense="CC BY-SA 3.0" />
  <row Id="15080" PostHistoryTypeId="3" PostId="5526" RevisionGUID="4a1526db-78fe-44f7-a64c-93f810826640" CreationDate="2017-08-25T12:27:08.357" UserId="7205" Text="|vector-graphics|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15081" PostHistoryTypeId="2" PostId="5527" RevisionGUID="d372f622-e71a-4cec-9fef-f384ab5a45aa" CreationDate="2017-08-25T13:59:42.973" UserId="2041" Text="The main part of it is simply Pythagoras's Theorem. The square root gives the length of the central line segment (which is the hypotenuse of a triangle formed by the change in x and change in y). The ratio between the hypotenuse and the change in x is the same as the ratio between the line width and the line width in y (they are similar triangles). Dividing by two is because $w_y$ is the half-width, not the full width. The -1 doesn't appear to make sense in a continuous context, so I assume it's to make sure the number of pixels is rounded down as part of the division. This prevents the line from jumping in thickness when it crosses a pixel boundary." ContentLicense="CC BY-SA 3.0" />
  <row Id="15082" PostHistoryTypeId="2" PostId="5528" RevisionGUID="aff0baab-aba4-40dc-9381-03b84e011d7c" CreationDate="2017-08-25T14:21:50.707" UserId="1647" Text="When warping the contents of an arbitrary quadrilateral to another by extrapolating equal points along both the &quot;lengths&quot; and &quot;widths&quot;, thus ignoring all perspective effects / foreshortening, we are not using a &quot;homography&quot; or &quot;affine&quot; mapping.&#xD;&#xA;&#xD;&#xA;Is there a correct name to describe the type of mapping we are doing?&#xD;&#xA;&#xD;&#xA;(Looking for example image ...)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15083" PostHistoryTypeId="1" PostId="5528" RevisionGUID="aff0baab-aba4-40dc-9381-03b84e011d7c" CreationDate="2017-08-25T14:21:50.707" UserId="1647" Text="Is there a term for mapping between two arbitrary quadrilaterals without using homography / perspective projection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15084" PostHistoryTypeId="3" PostId="5528" RevisionGUID="aff0baab-aba4-40dc-9381-03b84e011d7c" CreationDate="2017-08-25T14:21:50.707" UserId="1647" Text="|mapping|terminology|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15085" PostHistoryTypeId="5" PostId="5528" RevisionGUID="15b1d434-8d55-4da2-9e2b-342d95119d7f" CreationDate="2017-08-25T14:37:33.280" UserId="1647" Comment="image" Text="When warping the contents of an arbitrary quadrilateral to another by extrapolating equal points along both the &quot;lengths&quot; and &quot;widths&quot;, thus ignoring all perspective effects / foreshortening, we are not using a &quot;homography&quot; or &quot;affine&quot; mapping.&#xD;&#xA;&#xD;&#xA;Is there a correct name to describe the type of mapping we are doing?&#xD;&#xA;&#xD;&#xA;[![(Looking for example image ...)][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Z2ix7.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="15086" PostHistoryTypeId="2" PostId="5529" RevisionGUID="13780570-b961-4278-b7f1-9d72ef016ead" CreationDate="2017-08-25T16:33:49.097" UserId="7107" Text="I don't have enough rep to add a comment so...&#xD;&#xA;&#xD;&#xA;You could use a post process based anti-aliasing technique like FXAA or SMAA. Also, if performance is not a priority, you could go for [SSAA][1]. Another option could be to write to a multi sampled texture (I'm not 100% sure if that is possible in your case).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Supersampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="15088" PostHistoryTypeId="2" PostId="5530" RevisionGUID="571ec7cf-a01e-42dc-8897-0fdad824188e" CreationDate="2017-08-26T08:00:22.163" UserId="5353" Text="You're right, translation is not relevant in this context: it wouldn't affect the normals.&#xD;&#xA;&#xD;&#xA;Consider a non-uniformly scaled object:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;We want to get the normal matrix to transform the normals in the vertex buffer into vectors representing world space normals from the world matrix M, which encodes the translation, rotation and scaling (and shearing) of the model object.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;If you were to interpret the 3x3 of the M in the vertex shader, you would read rotation data with scaling applied. If the world matrix contains non-uniform scaling, your normal vectors will be scaled incorrectly, and you'll get the wrong results. &#xD;&#xA;&#xD;&#xA;The reason we take the transpose of the transform is because the rotation matrix, used to create ` M = TranslationMatrix x RotationMatrix x ScaleMatrix`, is an [Orthagonal Matrix](https://en.wikipedia.org/wiki/Orthogonal_matrix), which means that the row vectors are [**orthogonal**](https://en.wikipedia.org/wiki/Orthogonality), [**unit**](https://en.wikipedia.org/wiki/Unit_vector) vectors, i.e. they are linearly-independent and their length is one.&#xD;&#xA;&#xD;&#xA;This type of matrices hold a property like the following:&#xD;&#xA;&#xD;&#xA;    Q^T * Q = Q * Q^T = I&#xD;&#xA;&#xD;&#xA;If you remember the inverse rule:&#xD;&#xA;&#xD;&#xA;    Q^-1 * Q = Q * Q^-1 = I&#xD;&#xA;&#xD;&#xA;This also means the following for the orthogonal matrices:&#xD;&#xA;&#xD;&#xA;    Q^T = Q^-1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This allows us to apply the inverse of the rotations by transposing the matrix. &#xD;&#xA;&#xD;&#xA;In summary, taking inverse-transpose of the world matrix does 2 important things:&#xD;&#xA;&#xD;&#xA;1. Undo transformation (Inverse)&#xD;&#xA; - undo the scaling (and shearing)&#xD;&#xA; - invert rotations&#xD;&#xA; - translate the object to the world center (irrelevant)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. Un-undo rotations (Transpose)&#xD;&#xA; - Now, if we take the transpose of our matrix, we will get our rotations back to their original state because of the orthogonal property of the rotation matrix.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;We now have our normal matrix ready to transform model-space normals defined in the vertex buffer into world-space normals in the vertex shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MET67.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/aeMoe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/nmGHd.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15095" PostHistoryTypeId="2" PostId="5533" RevisionGUID="f7716d1a-a063-45e9-bede-caf72e784542" CreationDate="2017-08-27T04:32:43.977" UserId="1952" Text="You need to convert luminous flux (lumens, $lm$) to luminance ($\frac{lm}{m^2sr}$) for the [rendering equation][1]. For that you need to know the physical properties of the light source. For example luminance $L$ of spherical light source of radius $r$ radiating over $4\pi$ solid angle and luminous flux $\phi$ has luminance:&#xD;&#xA;$$L = \frac{\phi}{4\pi^2r^2}$$&#xD;&#xA;I think it's better to define lights straight using luminance instead of luminous flux though since you can simply measure luminance with spot meter instead of using [cumbersome special equipment][2] or be limited by values provided by manufacturers in illuminant packaging.&#xD;&#xA;&#xD;&#xA;Regarding distance attenuation, all lights in PBR should be area lights and there's no explicit attenuation formula for lights because the distance attenuation emerges naturally from the rendering equation.&#xD;&#xA;&#xD;&#xA;It's also better use [photometric units][3] instead of [radiometric units][4] for RGB-rendering (not spectral/monochromatic rendering). In photometric units the extraterrestrial sun luminance is ~1.9B cd/m^2. If you want to use radiometric units, you need to take the [spectral power distribution][5] of the sun and integrate that with [CIE color matching functions][6] to get any reasonable values rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luminous_flux#/media/File:Luminance_Chamber.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Category:Units_of_photometry&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Template:SI_radiometry_units&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Spectral_power_distribution&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/CIE_1931_color_space" ContentLicense="CC BY-SA 3.0" />
  <row Id="15096" PostHistoryTypeId="5" PostId="5533" RevisionGUID="d5e76aeb-0dd8-41da-af89-013df4c2808d" CreationDate="2017-08-27T04:42:51.887" UserId="1952" Comment="added 52 characters in body" Text="You need to convert luminous flux (lumens, $lm$) to luminance ($\frac{lm}{m^2sr}$) for the [rendering equation][1]. For that you need to know the physical properties of the light source. For example luminance $L$ of spherical light source of radius $r$ radiating over $4\pi$ solid angle and luminous flux $\phi$ has luminance:&#xD;&#xA;$$L = \frac{\phi}{4\pi^2r^2}$$&#xD;&#xA;I think it's better to define lights straight using luminance instead of luminous flux though since you can simply measure luminance with spot meter instead of using [cumbersome special equipment][2] or be limited by values provided by manufacturers in illuminant packaging.&#xD;&#xA;&#xD;&#xA;Regarding distance attenuation, all lights in PBR should be area lights and there's no explicit attenuation formula for lights because the distance attenuation emerges naturally from the rendering equation.&#xD;&#xA;&#xD;&#xA;It's also better use [photometric units][3] instead of [radiometric units][4] for RGB-rendering (not spectral/monochromatic rendering). In photometric units the extraterrestrial sun luminance is ~1.9B cd/m^2 (don't try to measure sun with spot meter though!). If you want to use radiometric units, you need to take the [spectral power distribution][5] of the sun and integrate that with [CIE color matching functions][6] to get any reasonable values rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luminous_flux#/media/File:Luminance_Chamber.jpg&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Category:Units_of_photometry&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Template:SI_radiometry_units&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Spectral_power_distribution&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/CIE_1931_color_space" ContentLicense="CC BY-SA 3.0" />
  <row Id="15097" PostHistoryTypeId="2" PostId="5534" RevisionGUID="390a1df7-359e-401a-92a7-6ba23d8087bc" CreationDate="2017-08-28T07:57:55.330" UserId="7214" Text="I'm trying to build a raytracer and I use [this article](https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays) on how to build camera system. The problem is that when, after calculating ray direction in camera space, I multiply it by camera-to-world transformation matrix and my camera seems to rotate in opposite directions and works correctly if I inverse transformation matrix before multiplication.  &#xD;&#xA;Here is the code (I use glm library and right-handed coordinate system). &#xD;&#xA;&#xD;&#xA;Some data&#xD;&#xA;&#xD;&#xA;    glm::vec3 origin_ = glm::vec3(0.f);// camera origin&#xD;&#xA;    cont glm::vec3 kDirection = glm::vec3(0.f, 0.f, -1.f);&#xD;&#xA;    cont glm::vec3 kUp = glm::vec3(0.f, 1.f, 0.f);&#xD;&#xA;    float aspect_ratio_ = (float)raster_height_ / raster_width_;&#xD;&#xA;&#xD;&#xA;    // bug !!! rotates in opposite direction  (camera is actually tilted down)&#xD;&#xA;    glm::mat4 camera_to_world_ = glm::lookAtRH(origin_, glm::vec3(0.f, 0.2f, -1.f), kUp);&#xD;&#xA;    // works !!! (camera is tilted up)&#xD;&#xA;    glm::mat4 camera_to_world_ = glm::inverse(glm::lookAtRH(origin_, glm::vec3(0.f, 0.2f, -1.f), kUp));&#xD;&#xA;&#xD;&#xA;And function that generates camera rays &#xD;&#xA;&#xD;&#xA;    // Calculate ray as if camera is located at 0,0,0 and pointing into negative z direction&#xD;&#xA;    // Then transform ray direction to desired plase&#xD;&#xA;    // x,y - pixel coordinates of raster image&#xD;&#xA;    // calculate as if raster image (screen) is 1.0 unit away from origin (eye)&#xD;&#xA;    Ray Camera::GenRay(const uint32_t x, const uint32_t y) {&#xD;&#xA;      glm::vec3 ray_direction = kDirection;&#xD;&#xA;      // from raster space to NDC space&#xD;&#xA;      glm::vec2 pixel_ndc((x + 0.5f) / raster_width_, (y + 0.5f) / raster_height_);&#xD;&#xA;      // from NDC space to camera space&#xD;&#xA;      float scale = tan(fov_ / 2.0f);&#xD;&#xA;      ray_direction.x = (2.0f * pixel_ndc.x - 1.0f) * scale; // *aspect_ratio_;&#xD;&#xA;      ray_direction.y = (1.0f - 2.0f * pixel_ndc.y) * scale * aspect_ratio_;&#xD;&#xA;      // apply camera-to-world rotation matrix to direction&#xD;&#xA;      ray_direction = camera_to_world_ * glm::vec4(ray_direction, 0.0f);&#xD;&#xA;    &#xD;&#xA;      return  Ray(origin_, ray_direction, Ray::Type::kPrimary);&#xD;&#xA;    }&#xD;&#xA;I really can't understand the root of a problem so any help us appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="15098" PostHistoryTypeId="1" PostId="5534" RevisionGUID="390a1df7-359e-401a-92a7-6ba23d8087bc" CreationDate="2017-08-28T07:57:55.330" UserId="7214" Text="Please, help me to understand why my raytracing camera rotates in wrong directions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15099" PostHistoryTypeId="3" PostId="5534" RevisionGUID="390a1df7-359e-401a-92a7-6ba23d8087bc" CreationDate="2017-08-28T07:57:55.330" UserId="7214" Text="|raytracing|c++|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15100" PostHistoryTypeId="2" PostId="5535" RevisionGUID="f4046549-1c9c-4181-a321-3685985e5ea5" CreationDate="2017-08-28T10:26:17.637" UserId="4908" Text="The problem is that instead of a camera-to-world matrix, a world-to-camera matrix is being made by glm::lookAtRH. &#xD;&#xA;&#xD;&#xA;This is because GLM is a math library made for OpenGL. In OpenGL, you do not move the 'camera' as there is no camera in OpenGL. You move the whole world the other way around, so that it lines up in the frustum. The lookAtRH method returns a matrix that moves the whole world in a way that it seems like you have the camera there.&#xD;&#xA;&#xD;&#xA;Inversing the matrix is a fine way to get the proper camera-to-world matrix.&#xD;&#xA;&#xD;&#xA;Scrathapixel does have an article regarding making your own lookAt function. One thing to note about this article is that they use a row-major notation. It might be that you need to switch it up and use a column-major notation (just swap the x index with the y index).&#xD;&#xA;https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function/framing-lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="15101" PostHistoryTypeId="2" PostId="5536" RevisionGUID="b35aba6b-de08-4419-b821-d6bab46e3f09" CreationDate="2017-08-28T10:44:26.777" UserId="7215" Text="I'm sort of struggling to understand the conceptual difference between uniform buffers and push constants. From what I can gather by reading the spec, the main differences are:&#xD;&#xA;&#xD;&#xA;1. Uniform buffers can be *much* larger than push constants.&#xD;&#xA;2. UBOs use std140, PCs use std430.&#xD;&#xA;3. UBOs can be updated at any time with vkCmdUpdateBuffer (or host mapping) and persist their values otherwise, PCs have to be re-pushed for each render pass. (Which surprised me - based on the name. I thought I would literally be updating constants in the pipeline in-place, and have those changes persist)&#xD;&#xA;&#xD;&#xA;In my scenario, I have about ~200 bytes worth of data that I expect to be **mostly constant**. That is, I will change them very infrequently. Would it be better to (assuming the size permits) use push constants even though I have to re-send them in every command buffer? Or would it be better to use a 200-byte UBO and only update it infrequently with vkCmdUpdatebuffer?&#xD;&#xA;&#xD;&#xA;Also. what if I have e.g. a `float random_seed` that I will update every time the shader is run? Assuming I already have a UBO, would it be better to lump that in with the UBO, even though the rest of the UBO is constant, or would I gain a benefit from using push constants for specifically this variable, so I can avoid having to vkCmdUpdateBuffer before every render pass?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15102" PostHistoryTypeId="1" PostId="5536" RevisionGUID="b35aba6b-de08-4419-b821-d6bab46e3f09" CreationDate="2017-08-28T10:44:26.777" UserId="7215" Text="Vulkan: Uniform Buffers versus Push Constants for static data" ContentLicense="CC BY-SA 3.0" />
  <row Id="15103" PostHistoryTypeId="3" PostId="5536" RevisionGUID="b35aba6b-de08-4419-b821-d6bab46e3f09" CreationDate="2017-08-28T10:44:26.777" UserId="7215" Text="|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15104" PostHistoryTypeId="50" PostId="4760" RevisionGUID="e12e2f7f-e56d-4971-8785-2f3724c788a2" CreationDate="2017-08-28T12:55:24.253" UserId="-1" />
  <row Id="15105" PostHistoryTypeId="2" PostId="5537" RevisionGUID="d5f5ba30-7cdd-460c-a00f-e552bd734369" CreationDate="2017-08-28T14:33:07.843" UserId="2654" Text="&gt; UBOs can be updated at any time with vkCmdUpdateBuffer &#xD;&#xA;&#xD;&#xA;From the specification: &quot;vkCmdUpdateBuffer is only allowed outside of a render pass.&quot; So &quot;at any time&quot; is not the case.&#xD;&#xA;&#xD;&#xA;Even if it were allowed inside of a render pass, it's still a transfer operation. Which means you need to synchronize the memory transfer with the commands that use it. Which slows down performance.&#xD;&#xA;&#xD;&#xA;For the genera Push Constant vs. Uniform thing, use your judgment. By &quot;judgment&quot;, I mean just look at what they're for. Push Constants allow you to change their data at any time without doing heavy-weight processes like memory operations, synchronization, or altering the descriptor state. Clearly, they are for frequently changing data. How frequently is &quot;frequently&quot;? Well, that's a judgment call.&#xD;&#xA;&#xD;&#xA;Failing that, profile the performance difference." ContentLicense="CC BY-SA 3.0" />
  <row Id="15106" PostHistoryTypeId="33" PostId="5520" RevisionGUID="b0655a15-49c6-4594-ad0a-8f30134116bd" CreationDate="2017-08-29T05:28:00.567" UserId="182" Comment="31" />
  <row Id="15107" PostHistoryTypeId="2" PostId="5538" RevisionGUID="bd4eb588-7530-4437-9dbe-2f81510293cc" CreationDate="2017-08-29T12:43:00.323" UserDisplayName="user7220" Text="I have asked this question on [ru.stackoverflow.com][1] and have no valid answers.&#xD;&#xA;&#xD;&#xA;Specification:&#xD;&#xA;&#xD;&#xA;1. [Coordinate system][2]&#xD;&#xA;2. Cube spins around its center on all three axes.&#xD;&#xA;3. Turn angle is not known previously.&#xD;&#xA;4. Parallel projection calculated by:&#xD;&#xA;&gt; x`` = x;&#xD;&#xA;&gt;&#xD;&#xA;&gt; y`` = y + z / 4;&#xD;&#xA;5. Per unit of time only 3 sides, closest to the projection pane, are visible.&#xD;&#xA;&#xD;&#xA;Question:&#xD;&#xA;&#xD;&#xA;**How to determine which are the closest sides?**&#xD;&#xA;&#xD;&#xA;I'am going this way: take pairs of sides left and right, front and back, top and bottom, then determine closest and farthest points in (Z) axis, determine the equation of a line, take second farthest point in (Z) axis, and substitute into this equation - so determine the inclination of the side. Based on this choose which side is closer.&#xD;&#xA;&#xD;&#xA;This code don't work:&#xD;&#xA;&#xD;&#xA;&lt;!-- begin snippet: js hide: true console: true babel: false --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;    'use strict';&#xD;&#xA;&#xD;&#xA;        var figures;&#xD;&#xA;&#xD;&#xA;        var figure_111 = {&#xD;&#xA;&#xD;&#xA;            //╔═══╗&#xD;&#xA;            //║   ║&#xD;&#xA;            //╚═══╝&#xD;&#xA;&#xD;&#xA;            figureType: 5,&#xD;&#xA;            figurePositionY: 1,&#xD;&#xA;            figurePositionX: 1,&#xD;&#xA;            figurePositionZ: 1,&#xD;&#xA;            shape: [&#xD;&#xA;                [[5]]&#xD;&#xA;            ],&#xD;&#xA;            rotateZ: function () {&#xD;&#xA;                this.shape = rotateZ(this.shape);&#xD;&#xA;                this.figurePositionZ = changePosition(this.figurePositionZ);&#xD;&#xA;            }&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        function initAnimation() {&#xD;&#xA;            figures = [&#xD;&#xA;                figure_111&#xD;&#xA;            ];&#xD;&#xA;&#xD;&#xA;            // Запускаем падение&#xD;&#xA;            figureStartsFalling();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Текущая фигура&#xD;&#xA;        var currentFigure;&#xD;&#xA;&#xD;&#xA;        // Размер фигуры&#xD;&#xA;        var size = 30;&#xD;&#xA;&#xD;&#xA;        // Объект на основании фигуры&#xD;&#xA;        var fallingObject;&#xD;&#xA;&#xD;&#xA;        // Цвет фигуры&#xD;&#xA;        var figureColor;&#xD;&#xA;&#xD;&#xA;        // Центр фигуры&#xD;&#xA;        var t0;&#xD;&#xA;&#xD;&#xA;        var canvas = document.getElementById('animation');&#xD;&#xA;        var canvas_context = canvas.getContext('2d');&#xD;&#xA;&#xD;&#xA;        // Сместим центр оси (Х) в середину поля&#xD;&#xA;        canvas_context.translate(canvas.width / 2, 0);&#xD;&#xA;&#xD;&#xA;        var doTenTimes;&#xD;&#xA;&#xD;&#xA;        function figureStartsFalling() {&#xD;&#xA;            doTenTimes = 30;&#xD;&#xA;            // Переопределяем текущую фигуру&#xD;&#xA;            currentFigure = figures[Math.floor(Math.random() * figures.length)];&#xD;&#xA;&#xD;&#xA;            // Получим цвет текущей фигуры&#xD;&#xA;            figureColor = 'rgb(0,200,0)';&#xD;&#xA;&#xD;&#xA;            // Высота фигуры&#xD;&#xA;            var figureHeight = currentFigure.shape.length;&#xD;&#xA;&#xD;&#xA;            // Строим 3Д объект на основании фигуры&#xD;&#xA;            fallingObject = [];&#xD;&#xA;            var cube = [];&#xD;&#xA;            var side = [];&#xD;&#xA;&#xD;&#xA;            for (var y = currentFigure.shape.length - 1; y &gt; -1; y--) {&#xD;&#xA;                for (var x = 0; x &lt; currentFigure.shape[0].length; x++) {&#xD;&#xA;                    for (var z = 0; z &lt; currentFigure.shape[0][0].length; z++) {&#xD;&#xA;                        // Для каждой клеточки создаем кубик с 5 гранями&#xD;&#xA;                        cube = [];&#xD;&#xA;                        if (currentFigure.shape[y][x][z] != 0) {&#xD;&#xA;                            // Левая стенка&#xD;&#xA;                            side = [&#xD;&#xA;                                {x:x*size, y:y*size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size, y:y*size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size, y:y*size + size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size, y:y*size + size - figureHeight*size, z:z*size},&#xD;&#xA;                                {m:'left'}&#xD;&#xA;                            ];&#xD;&#xA;                            // Центральная координата, нужна для расчета удаленности по осям (X) и (Z)&#xD;&#xA;                            side[4] = getSidecentralCoordinate(side);&#xD;&#xA;                            // Если левее чтото есть, то не рисуем&#xD;&#xA;                            if (x &gt; 0&#xD;&#xA;                                &amp;&amp; currentFigure.shape[y][x - 1][z] != 0) {&#xD;&#xA;                                side[5] = false;&#xD;&#xA;                            }&#xD;&#xA;                            cube.push(side);&#xD;&#xA;&#xD;&#xA;                            // Правая стенка&#xD;&#xA;                            side = [&#xD;&#xA;                                {x:x*size + size, y:y*size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size + size, y:y*size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size + size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size + size - figureHeight*size, z:z*size},&#xD;&#xA;                                {m:'right'}&#xD;&#xA;                            ];&#xD;&#xA;                            side[4] = getSidecentralCoordinate(side);&#xD;&#xA;                            // Если правее чтото есть, то не рисуем&#xD;&#xA;                            if (x + 1 &lt; currentFigure.shape[0].length&#xD;&#xA;                                &amp;&amp; currentFigure.shape[y][x + 1][z] != 0) {&#xD;&#xA;                                side[5] = false;&#xD;&#xA;                            }&#xD;&#xA;                            cube.push(side);&#xD;&#xA;&#xD;&#xA;                            // Задняя стенка&#xD;&#xA;                            side = [&#xD;&#xA;                                {x:x*size, y:y*size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size + size, y:y*size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size + size, y:y*size + size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size, y:y*size + size - figureHeight*size, z:z*size},&#xD;&#xA;                                {m:'rear'}&#xD;&#xA;                            ];&#xD;&#xA;                            side[4] = getSidecentralCoordinate(side);&#xD;&#xA;                            // Если сзади чтото есть, то не рисуем&#xD;&#xA;                            if (z &gt; 0&#xD;&#xA;                                &amp;&amp; currentFigure.shape[y][x][z - 1] != 0) {&#xD;&#xA;                                side[5] = false;&#xD;&#xA;                            }&#xD;&#xA;                            cube.push(side);&#xD;&#xA;&#xD;&#xA;                            // Передняя стенка&#xD;&#xA;                            side = [&#xD;&#xA;                                {x:x*size, y:y*size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size + size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size, y:y*size + size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {m:'front'}&#xD;&#xA;                            ];&#xD;&#xA;                            side[4] = getSidecentralCoordinate(side);&#xD;&#xA;                            // Если впереди чтото есть, то не рисуем&#xD;&#xA;                            if (z + 1 &lt; currentFigure.shape[0][0].length&#xD;&#xA;                                &amp;&amp; currentFigure.shape[y][x][z + 1] != 0) {&#xD;&#xA;                                side[5] = false;&#xD;&#xA;                            }&#xD;&#xA;                            cube.push(side);&#xD;&#xA;&#xD;&#xA;                            // Верхняя стенка&#xD;&#xA;                            side = [&#xD;&#xA;                                {x:x*size, y:y*size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size, y:y*size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size - figureHeight*size, z:z*size},&#xD;&#xA;                                {m:'top'}&#xD;&#xA;                            ];&#xD;&#xA;                            side[4] = getSidecentralCoordinate(side);&#xD;&#xA;                            // Если сверху чтото есть, то не рисуем&#xD;&#xA;                            if (y &gt; 0&#xD;&#xA;                                &amp;&amp; currentFigure.shape[y - 1][x][z] != 0) {&#xD;&#xA;                                side[5] = false;&#xD;&#xA;                            }&#xD;&#xA;                            cube.push(side);&#xD;&#xA;&#xD;&#xA;                            // Нижняя стенка&#xD;&#xA;                            side = [&#xD;&#xA;                                {x:x*size, y:y*size + size - figureHeight*size, z:z*size},&#xD;&#xA;                                {x:x*size, y:y*size + size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size + size - figureHeight*size, z:z*size + size},&#xD;&#xA;                                {x:x*size + size, y:y*size + size - figureHeight*size, z:z*size},&#xD;&#xA;                                {m:'bottom'}&#xD;&#xA;                            ];&#xD;&#xA;                            side[4] = getSidecentralCoordinate(side);&#xD;&#xA;                            // Если снизу чтото есть, то не рисуем&#xD;&#xA;                            if (y + 1 &lt; currentFigure.shape.length&#xD;&#xA;                                &amp;&amp; currentFigure.shape[y + 1][x][z] != 0) {&#xD;&#xA;                                side[5] = false;&#xD;&#xA;                            }&#xD;&#xA;                            cube.push(side);&#xD;&#xA;                            fallingObject.push(cube);&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Определим центр фигуры&#xD;&#xA;            t0 = {&#xD;&#xA;                y:currentFigure.shape.length / 2 * size - figureHeight*size,&#xD;&#xA;                x:currentFigure.shape[0].length / 2 * size,&#xD;&#xA;                z:currentFigure.shape[0][0].length / 2 * size&#xD;&#xA;            };&#xD;&#xA;&#xD;&#xA;            // Запускаем падение&#xD;&#xA;            setTimeout(figureFalls, 100);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Угол поворота, не изменяется&#xD;&#xA;        var deg = 1;&#xD;&#xA;&#xD;&#xA;        // Текущая проекция&#xD;&#xA;        var arrProj;&#xD;&#xA;&#xD;&#xA;        var tempArr;&#xD;&#xA;&#xD;&#xA;        function figureFalls() {&#xD;&#xA;&#xD;&#xA;            // Сначала очистим экран - закрасим белым цветом&#xD;&#xA;            clearScreen(canvas, canvas_context, 'rgb(255,255,255)');&#xD;&#xA;&#xD;&#xA;            // Изменяем положение текущей фигуры&#xD;&#xA;            for (var i = 0; i &lt; fallingObject.length; i++) {&#xD;&#xA;                for (var j = 0; j &lt; 6; j++) {&#xD;&#xA;                    for (var k = 0; k &lt; 4; k++) {&#xD;&#xA;                        // Повернем фигуру на угол&#xD;&#xA;                        fallingObject[i][j][k] = rotateOnDegreeY(t0, fallingObject[i][j][k]);&#xD;&#xA;                        fallingObject[i][j][k] = rotateOnDegreeX(t0, fallingObject[i][j][k]);&#xD;&#xA;                        fallingObject[i][j][k] = rotateOnDegreeZ(t0, fallingObject[i][j][k]);&#xD;&#xA;                        // и опустим вниз на 1px&#xD;&#xA;                        fallingObject[i][j][k].y += 1;&#xD;&#xA;                    }&#xD;&#xA;                    // Пересчитаем центральную координату плоскости&#xD;&#xA;                    fallingObject[i][j][4] = getSidecentralCoordinate(fallingObject[i][j]);&#xD;&#xA;                }&#xD;&#xA;                doTenTimes -= 1;&#xD;&#xA;                // Пересчитаем центральную координату кубика&#xD;&#xA;                fallingObject[i][6] = getCubecentralCoordinate(fallingObject[i]);&#xD;&#xA;                // Если кубик ушел слишком далеко - удаляем кубик&#xD;&#xA;                if (fallingObject[i][6].y &gt; canvas.height) {&#xD;&#xA;                    fallingObject.splice(i, 1);&#xD;&#xA;                    i -=1;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Центр фигуры тоже опускается&#xD;&#xA;            t0.y += 1;&#xD;&#xA;&#xD;&#xA;            // Сортируем кубики по удаленности от начала координат по (X) и (Z)&#xD;&#xA;            var exit = false;&#xD;&#xA;            while (!exit) {&#xD;&#xA;                exit = true;&#xD;&#xA;                for (var i = 0; i &lt; fallingObject.length - 1; i++) {&#xD;&#xA;                    if (fallingObject[i][6].z &gt; fallingObject[i + 1][6].z) {&#xD;&#xA;                        tempArr = fallingObject[i];&#xD;&#xA;                        fallingObject[i] = fallingObject[i + 1];&#xD;&#xA;                        fallingObject[i + 1] = tempArr;&#xD;&#xA;                        exit = false;&#xD;&#xA;                    } else if (fallingObject[i][6].z == fallingObject[i + 1][6].z) {&#xD;&#xA;                        if (fallingObject[i][6].x &gt; fallingObject[i + 1][6].x) {&#xD;&#xA;                            tempArr = fallingObject[i];&#xD;&#xA;                            fallingObject[i] = fallingObject[i + 1];&#xD;&#xA;                            fallingObject[i + 1] = tempArr;&#xD;&#xA;                            exit = false;&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Отрисовываем фигуру&#xD;&#xA;            for (var i = 0; i &lt; fallingObject.length; i++) {&#xD;&#xA;                // Получим параллельную проекцию&#xD;&#xA;                arrProj = getParallelProjection(fallingObject[i]);&#xD;&#xA;                // Нарисуем параллельную проекцию&#xD;&#xA;                fillFigure(canvas_context, arrProj, figureColor);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Если в видимой области еще есть кубики -&#xD;&#xA;            // переходим на следующий шаг&#xD;&#xA;            if (fallingObject.length &gt; 0) {&#xD;&#xA;                setTimeout(figureFalls, 100);&#xD;&#xA;            }&#xD;&#xA;            // иначе начинаем заново с новой фигурой&#xD;&#xA;            else {&#xD;&#xA;                setTimeout(figureStartsFalling, 100);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Получим центральную координату плоскости&#xD;&#xA;        // для расчета удаленности от задней стенки&#xD;&#xA;        function getSidecentralCoordinate(side) {&#xD;&#xA;&#xD;&#xA;            var centralCoordinate = {x:0, y:0, z:0};&#xD;&#xA;&#xD;&#xA;            for (var i = 0; i &lt; 4; i++) {&#xD;&#xA;                centralCoordinate.x += side[i].x;&#xD;&#xA;                centralCoordinate.y += side[i].y;&#xD;&#xA;                centralCoordinate.z += side[i].z;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            centralCoordinate.x = centralCoordinate.x / 4;&#xD;&#xA;            centralCoordinate.y = centralCoordinate.y / 4;&#xD;&#xA;            centralCoordinate.z = centralCoordinate.z / 4;&#xD;&#xA;&#xD;&#xA;            centralCoordinate.m = side[4].m;&#xD;&#xA;&#xD;&#xA;            return centralCoordinate;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Получим центральную координату кубика&#xD;&#xA;        // для расчета удаленности от начала координат&#xD;&#xA;        function getCubecentralCoordinate(side) {&#xD;&#xA;            var centralCoordinate = {x:0, y:0, z:0};&#xD;&#xA;&#xD;&#xA;            for (var i = 0; i &lt; 6; i++) {&#xD;&#xA;                centralCoordinate.x += side[i][4].x;&#xD;&#xA;                centralCoordinate.y += side[i][4].y;&#xD;&#xA;                centralCoordinate.z += side[i][4].z;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            centralCoordinate.x = centralCoordinate.x / 6;&#xD;&#xA;            centralCoordinate.y = centralCoordinate.y / 6;&#xD;&#xA;            centralCoordinate.z = centralCoordinate.z / 6;&#xD;&#xA;&#xD;&#xA;            return centralCoordinate;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Поворачиваем точку t(x,y,z) на угол (deg) по оси (Y)&#xD;&#xA;        // относительно точки t0(x,y,z)&#xD;&#xA;        function rotateOnDegreeY(t0, t) {&#xD;&#xA;&#xD;&#xA;            var t_new = {};&#xD;&#xA;&#xD;&#xA;            // Переводим угол поворота из градусов в радианы&#xD;&#xA;            var rad = (Math.PI / 180) * deg;&#xD;&#xA;&#xD;&#xA;            // Рассчитываем координаты новой точки по формуле&#xD;&#xA;            t_new.x = t0.x + (t.x - t0.x) * Math.cos(rad) - (t.z - t0.z) * Math.sin(rad);&#xD;&#xA;            t_new.y = t.y;&#xD;&#xA;            t_new.z = t0.z + (t.x - t0.x) * Math.sin(rad) + (t.z - t0.z) * Math.cos(rad);&#xD;&#xA;&#xD;&#xA;            // Возвращаем полученное значение&#xD;&#xA;            return t_new;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Поворачиваем точку t(x,y,z) на угол (deg) по оси (X)&#xD;&#xA;        // относительно точки t0(x,y,z)&#xD;&#xA;        function rotateOnDegreeX(t0, t) {&#xD;&#xA;&#xD;&#xA;            var t_new = {};&#xD;&#xA;&#xD;&#xA;            // Переводим угол поворота из градусов в радианы&#xD;&#xA;            var rad = (Math.PI / 180) * deg;&#xD;&#xA;&#xD;&#xA;            // Рассчитываем координаты новой точки по формуле&#xD;&#xA;            t_new.x = t.x;&#xD;&#xA;            t_new.y = t0.y + (t.y - t0.y) * Math.cos(rad) - (t.z - t0.z) * Math.sin(rad);&#xD;&#xA;            t_new.z = t0.z + (t.y - t0.y) * Math.sin(rad) + (t.z - t0.z) * Math.cos(rad);&#xD;&#xA;&#xD;&#xA;            // Возвращаем полученное значение&#xD;&#xA;            return t_new;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Поворачиваем точку t(x,y,z) на угол (deg) по оси (Z)&#xD;&#xA;        // относительно точки t0(x,y,z)&#xD;&#xA;        function rotateOnDegreeZ(t0, t) {&#xD;&#xA;&#xD;&#xA;            var t_new = {};&#xD;&#xA;&#xD;&#xA;            // Переводим угол поворота из градусов в радианы&#xD;&#xA;            var rad = (Math.PI / 180) * deg;&#xD;&#xA;&#xD;&#xA;            // Рассчитываем координаты новой точки по формуле&#xD;&#xA;            t_new.x = t0.x + (t.x - t0.x) * Math.cos(rad) - (t.y - t0.y) * Math.sin(rad);&#xD;&#xA;            t_new.y = t0.y + (t.x - t0.x) * Math.sin(rad) + (t.y - t0.y) * Math.cos(rad);&#xD;&#xA;            t_new.z = t.z;&#xD;&#xA;&#xD;&#xA;            // Возвращаем полученное значение&#xD;&#xA;            return t_new;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Закрашиваем весь экран определенным цветом&#xD;&#xA;        function clearScreen(canvas, context, color) {&#xD;&#xA;            context.fillStyle = color;&#xD;&#xA;&#xD;&#xA;            context.beginPath();&#xD;&#xA;            context.fillRect(- canvas.width / 2, 0, canvas.width, canvas.height);&#xD;&#xA;            context.closePath();&#xD;&#xA;            context.fill();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Получаем параллельную проекцию кубика на плоскость экрана&#xD;&#xA;        function getParallelProjection(arr) {&#xD;&#xA;&#xD;&#xA;            var i, j, k;&#xD;&#xA;&#xD;&#xA;            var arr_new = [];&#xD;&#xA;&#xD;&#xA;            // Попарно работаем с гранями&#xD;&#xA;            arr_new[0] = getSideParallelProjection(arr[0], arr[1], arr[6]); // Левая и правая&#xD;&#xA;            arr_new[1] = getSideParallelProjection(arr[2], arr[3], arr[6]); // Задняя и передняя&#xD;&#xA;            arr_new[2] = getSideParallelProjection(arr[4], arr[5], arr[6]); // Верхняя и нижняя&#xD;&#xA;&#xD;&#xA;            return arr_new;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Параллельная проекция грани&#xD;&#xA;        function getSideParallelProjection(side1, side2, cubeCenter) {&#xD;&#xA;&#xD;&#xA;            // Сначала выясним какая пара нам попалась&#xD;&#xA;            var centralProjection1 = getPointParallelProjection(side1[4]);&#xD;&#xA;            var centralProjection2 = getPointParallelProjection(side2[4]);&#xD;&#xA;&#xD;&#xA;            var coordinate = {&#xD;&#xA;                x:Math.abs(side1[4].x - side2[4].x),&#xD;&#xA;                y:Math.abs(side1[4].y - side2[4].y),&#xD;&#xA;                z:Math.abs(side1[4].z - side2[4].z)};&#xD;&#xA;&#xD;&#xA;            var i;&#xD;&#xA;&#xD;&#xA;        // Найдем дальнюю (1) и ближнюю (2) от экрана точки&#xD;&#xA;        // по оси (Z) и посчитаем их проекции&#xD;&#xA;        var point1 = {z:10000},&#xD;&#xA;            point2 = {z:-10000},&#xD;&#xA;            point3 = {z:10000};&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 4; i++) {&#xD;&#xA;            if (point1.z &gt; side1[i].z) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point1.z == side1[i].z&#xD;&#xA;                &amp;&amp; point1.x &gt; side1[i].x) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point1.z == side1[i].z&#xD;&#xA;                &amp;&amp; point1.x == side1[i].x&#xD;&#xA;                &amp;&amp; point1.y &lt; side1[i].y) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z &lt; side1[i].z) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z == side1[i].z&#xD;&#xA;                &amp;&amp; point2.x &lt; side1[i].x) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z == side1[i].z&#xD;&#xA;                &amp;&amp; point2.x == side1[i].x&#xD;&#xA;                &amp;&amp; point2.y &gt; side1[i].y) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 4; i++) {&#xD;&#xA;            if (point3.z &gt; side1[i].z&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point3.z == side1[i].z&#xD;&#xA;                &amp;&amp; point3.x &gt; side1[i].x&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point3.z == side1[i].z&#xD;&#xA;                &amp;&amp; point3.x == side1[i].x&#xD;&#xA;                &amp;&amp; point3.y &lt; side1[i].y&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    	var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                                - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;            var projection = [];&#xD;&#xA;&#xD;&#xA;            // (X) Правая и левая грани&#xD;&#xA;            if (coordinate.x &gt; coordinate.y &amp;&amp; coordinate.x &gt; coordinate.z) {&#xD;&#xA;&#xD;&#xA;                point1 = getPointParallelProjection(point1);&#xD;&#xA;                point2 = getPointParallelProjection(point2);&#xD;&#xA;                point3 = getPointParallelProjection(point3);&#xD;&#xA;&#xD;&#xA;                var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                    - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;&#xD;&#xA;                var selected;&#xD;&#xA;&#xD;&#xA;                if (point1.x &gt;= point2.x) {&#xD;&#xA;                    if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                } else {&#xD;&#xA;                    if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (selected.length &lt; 6) {&#xD;&#xA;                    for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                        projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                    }&#xD;&#xA;                    projection[4] = 'rgb(200,200,0)';&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // (Z) Передняя и задняя грани&#xD;&#xA;            else if (coordinate.z &gt; coordinate.x &amp;&amp; coordinate.z &gt; coordinate.y) {&#xD;&#xA;&#xD;&#xA;                var selected;&#xD;&#xA;&#xD;&#xA;                if (point1.x &gt;= point2.x &amp;&amp; direction &lt; 0) {&#xD;&#xA;                    if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                } else {&#xD;&#xA;                    if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (selected.length &lt; 6) {&#xD;&#xA;                    for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                        projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                    }&#xD;&#xA;                    projection[4] = 'rgb(200,0,0)';&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // (Y) Верхняя и нижняя грани&#xD;&#xA;            else {&#xD;&#xA;&#xD;&#xA;                var selected;&#xD;&#xA;&#xD;&#xA;                if (point1.y &lt;= point2.y) {&#xD;&#xA;                    if (centralProjection1.y &lt;= centralProjection2.y) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                } else {&#xD;&#xA;                    if (centralProjection1.y &gt;= centralProjection2.y) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (selected.length &lt; 6) {&#xD;&#xA;                    for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                        projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                    }&#xD;&#xA;                    projection[4] = 'rgb(0,0,0)';&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            return projection;&#xD;&#xA;        }&#xD;&#xA;        // Параллельная проекция точки&#xD;&#xA;        function getPointParallelProjection(point) {&#xD;&#xA;            return {&#xD;&#xA;                x:point.x,&#xD;&#xA;                y:point.y + point.z / 4};&#xD;&#xA;    //        return {&#xD;&#xA;    //            x:point.x + point.z * Math.cos(Math.PI * 3 / 4) / 2,&#xD;&#xA;    //            y:point.y + point.z * Math.sin(Math.PI * 3 / 4) / 2};&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Рисуем фигуру по точкам из массива&#xD;&#xA;        function fillFigure(context, arr, color) {&#xD;&#xA;            context.lineWidth = 2;&#xD;&#xA;            context.strokeStyle = 'rgb(255,255,255)';&#xD;&#xA;            context.fillStyle = color;&#xD;&#xA;&#xD;&#xA;            for (var i = 0; i &lt; arr.length; i++) {&#xD;&#xA;                context.beginPath();&#xD;&#xA;                for (var j = 0; j &lt; arr[i].length; j++) {&#xD;&#xA;                    if (arr[i][4] != undefined) {&#xD;&#xA;                        context.fillStyle = arr[i][4];&#xD;&#xA;                    } else {&#xD;&#xA;                        context.fillStyle = color;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == 0) {&#xD;&#xA;                        context.moveTo(arr[i][j].x, arr[i][j].y);&#xD;&#xA;                    } else {&#xD;&#xA;                        context.lineTo(arr[i][j].x, arr[i][j].y);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                context.closePath();&#xD;&#xA;                context.fill();&#xD;&#xA;                context.stroke();&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Запускаем наш скрипт&#xD;&#xA;        window.onload = function() {&#xD;&#xA;            setTimeout(initAnimation, 200);&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;canvas id=&quot;animation&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&#xD;&#xA;        &lt;p&gt;Your browser does not support Canvas&lt;/p&gt;&#xD;&#xA;    &lt;/canvas&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- end snippet --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://ru.stackoverflow.com/questions/705286/%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D1%82%D0%BE%D1%80%D0%BE%D0%BD-%D0%BA%D1%83%D0%B1%D0%B0-%D0%BE%D1%82-%D0%BF%D0%BB%D0%BE%D1%81%D0%BA%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8&#xD;&#xA;  [2]: https://i.stack.imgur.com/bKXyI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15108" PostHistoryTypeId="1" PostId="5538" RevisionGUID="bd4eb588-7530-4437-9dbe-2f81510293cc" CreationDate="2017-08-29T12:43:00.323" UserDisplayName="user7220" Text="The distance of the cube sides from the parallel projection plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="15109" PostHistoryTypeId="3" PostId="5538" RevisionGUID="bd4eb588-7530-4437-9dbe-2f81510293cc" CreationDate="2017-08-29T12:43:00.323" UserDisplayName="user7220" Text="|3d|projections|javascript|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15110" PostHistoryTypeId="4" PostId="5538" RevisionGUID="9c971770-c4eb-4218-88bd-d596e59b5d90" CreationDate="2017-08-29T12:53:17.773" UserDisplayName="user7220" Comment="edited title" Text="The distance from the cube sides to the parallel projection plane" ContentLicense="CC BY-SA 3.0" />
  <row Id="15111" PostHistoryTypeId="5" PostId="5538" RevisionGUID="08ef1978-ee82-4b50-b03f-097f2dfaed69" CreationDate="2017-08-29T13:44:13.487" UserDisplayName="user7220" Comment="refactor" Text="I have asked this question on [ru.stackoverflow.com][1] and have no valid answers.&#xD;&#xA;&#xD;&#xA;Specification:&#xD;&#xA;&#xD;&#xA;1. [Coordinate system][2]&#xD;&#xA;2. Cube spins around its center on all three axes.&#xD;&#xA;3. Turn angle is not known previously.&#xD;&#xA;4. Parallel projection calculated by:&#xD;&#xA;&gt; x`` = x;&#xD;&#xA;&gt;&#xD;&#xA;&gt; y`` = y + z / 4;&#xD;&#xA;5. Per unit of time only 3 sides, closest to the projection pane, are visible.&#xD;&#xA;&#xD;&#xA;Question:&#xD;&#xA;&#xD;&#xA;**How to determine which are the closest sides?**&#xD;&#xA;&#xD;&#xA;I'am going this way: take pairs of sides left and right, front and back, top and bottom, then determine closest and farthest points in (Z) axis, determine the equation of a line, take second farthest point in (Z) axis, and substitute into this equation - so determine the inclination of the side. Based on this choose which side is closer.&#xD;&#xA;&#xD;&#xA;This code don't work:&#xD;&#xA;&#xD;&#xA;&lt;!-- begin snippet: js hide: true console: true babel: false --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;        // Получаем параллельную проекцию кубика на плоскость экрана&#xD;&#xA;        function getParallelProjection(arr) {&#xD;&#xA;&#xD;&#xA;            var i, j, k;&#xD;&#xA;&#xD;&#xA;            var arr_new = [];&#xD;&#xA;&#xD;&#xA;            // Попарно работаем с гранями&#xD;&#xA;            arr_new[0] = getSideParallelProjection(arr[0], arr[1], arr[6]); // Левая и правая&#xD;&#xA;            arr_new[1] = getSideParallelProjection(arr[2], arr[3], arr[6]); // Задняя и передняя&#xD;&#xA;            arr_new[2] = getSideParallelProjection(arr[4], arr[5], arr[6]); // Верхняя и нижняя&#xD;&#xA;&#xD;&#xA;            return arr_new;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Параллельная проекция грани&#xD;&#xA;        function getSideParallelProjection(side1, side2, cubeCenter) {&#xD;&#xA;&#xD;&#xA;            // Сначала выясним какая пара нам попалась&#xD;&#xA;            var centralProjection1 = getPointParallelProjection(side1[4]);&#xD;&#xA;            var centralProjection2 = getPointParallelProjection(side2[4]);&#xD;&#xA;&#xD;&#xA;            var coordinate = {&#xD;&#xA;                x:Math.abs(side1[4].x - side2[4].x),&#xD;&#xA;                y:Math.abs(side1[4].y - side2[4].y),&#xD;&#xA;                z:Math.abs(side1[4].z - side2[4].z)};&#xD;&#xA;&#xD;&#xA;            var i;&#xD;&#xA;&#xD;&#xA;            // Найдем дальнюю (1) и ближнюю (2) от экрана точки&#xD;&#xA;            // по оси (Z) и посчитаем их проекции&#xD;&#xA;            var point1 = {z:10000},&#xD;&#xA;                point2 = {z:-10000},&#xD;&#xA;                point3 = {z:10000};&#xD;&#xA;    &#xD;&#xA;            for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                if (point1.z &gt; side1[i].z) {&#xD;&#xA;                    point1 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point1.z == side1[i].z&#xD;&#xA;                    &amp;&amp; point1.x &gt; side1[i].x) {&#xD;&#xA;                    point1 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point1.z == side1[i].z&#xD;&#xA;                    &amp;&amp; point1.x == side1[i].x&#xD;&#xA;                    &amp;&amp; point1.y &lt; side1[i].y) {&#xD;&#xA;                    point1 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point2.z &lt; side1[i].z) {&#xD;&#xA;                    point2 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point2.z == side1[i].z&#xD;&#xA;                    &amp;&amp; point2.x &lt; side1[i].x) {&#xD;&#xA;                    point2 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point2.z == side1[i].z&#xD;&#xA;                    &amp;&amp; point2.x == side1[i].x&#xD;&#xA;                    &amp;&amp; point2.y &gt; side1[i].y) {&#xD;&#xA;                    point2 = side1[i];&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                if (point3.z &gt; side1[i].z&#xD;&#xA;                    &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                    point3 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point3.z == side1[i].z&#xD;&#xA;                    &amp;&amp; point3.x &gt; side1[i].x&#xD;&#xA;                    &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                    point3 = side1[i];&#xD;&#xA;                }&#xD;&#xA;                if (point3.z == side1[i].z&#xD;&#xA;                    &amp;&amp; point3.x == side1[i].x&#xD;&#xA;                    &amp;&amp; point3.y &lt; side1[i].y&#xD;&#xA;                    &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                    point3 = side1[i];&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                                    - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;            var projection = [];&#xD;&#xA;&#xD;&#xA;            // (X) Правая и левая грани&#xD;&#xA;            if (coordinate.x &gt; coordinate.y &amp;&amp; coordinate.x &gt; coordinate.z) {&#xD;&#xA;&#xD;&#xA;                point1 = getPointParallelProjection(point1);&#xD;&#xA;                point2 = getPointParallelProjection(point2);&#xD;&#xA;                point3 = getPointParallelProjection(point3);&#xD;&#xA;&#xD;&#xA;                var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                    - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;&#xD;&#xA;                var selected;&#xD;&#xA;&#xD;&#xA;                if (point1.x &gt;= point2.x) {&#xD;&#xA;                    if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                } else {&#xD;&#xA;                    if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (selected.length &lt; 6) {&#xD;&#xA;                    for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                        projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                    }&#xD;&#xA;                    projection[4] = 'rgb(200,200,0)';&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // (Z) Передняя и задняя грани&#xD;&#xA;            else if (coordinate.z &gt; coordinate.x &amp;&amp; coordinate.z &gt; coordinate.y) {&#xD;&#xA;&#xD;&#xA;                var selected;&#xD;&#xA;&#xD;&#xA;                if (point1.x &gt;= point2.x &amp;&amp; direction &lt; 0) {&#xD;&#xA;                    if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                } else {&#xD;&#xA;                    if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (selected.length &lt; 6) {&#xD;&#xA;                    for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                        projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                    }&#xD;&#xA;                    projection[4] = 'rgb(200,0,0)';&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // (Y) Верхняя и нижняя грани&#xD;&#xA;            else {&#xD;&#xA;&#xD;&#xA;                var selected;&#xD;&#xA;&#xD;&#xA;                if (point1.y &lt;= point2.y) {&#xD;&#xA;                    if (centralProjection1.y &lt;= centralProjection2.y) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                } else {&#xD;&#xA;                    if (centralProjection1.y &gt;= centralProjection2.y) {&#xD;&#xA;                        selected = side1;&#xD;&#xA;                    } else {&#xD;&#xA;                        selected = side2;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (selected.length &lt; 6) {&#xD;&#xA;                    for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                        projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                    }&#xD;&#xA;                    projection[4] = 'rgb(0,0,0)';&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            return projection;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Параллельная проекция точки&#xD;&#xA;        function getPointParallelProjection(point) {&#xD;&#xA;            return {&#xD;&#xA;                x:point.x,&#xD;&#xA;                y:point.y + point.z / 4};&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;canvas id=&quot;animation&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&#xD;&#xA;        &lt;p&gt;Your browser does not support Canvas&lt;/p&gt;&#xD;&#xA;    &lt;/canvas&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- end snippet --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://ru.stackoverflow.com/questions/705286/%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D1%82%D0%BE%D1%80%D0%BE%D0%BD-%D0%BA%D1%83%D0%B1%D0%B0-%D0%BE%D1%82-%D0%BF%D0%BB%D0%BE%D1%81%D0%BA%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8&#xD;&#xA;  [2]: https://i.stack.imgur.com/bKXyI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15112" PostHistoryTypeId="2" PostId="5539" RevisionGUID="41824db2-bcbc-4160-a84e-a603288f2454" CreationDate="2017-08-29T22:25:54.133" UserId="7028" Text="There is a [TED presentation][1], where we see really good looking geometries, which are generated using space folding.&#xD;&#xA;&#xD;&#xA;I get the general idea, that we start from a basic geometry like a cube, and then apply linear transformations and conditional foldings (reflecting a point on a plane). I tried it, but my results were not really good looking.&#xD;&#xA;&#xD;&#xA;I am looking for the algorithm, to generate geometries like that. But by guessing I can not progress further. Unfortunately I was not able to find articles, explaining it.&#xD;&#xA;&#xD;&#xA;This is an example from the video:&#xD;&#xA;&#xD;&#xA;[![before folding][2]][2]&#xD;&#xA;&#xD;&#xA;[![after folding][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.ted.com/talks/michael_hansmeyer_building_unimaginable_shapes&#xD;&#xA;  [2]: https://i.stack.imgur.com/0Khps.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/toj2t.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15113" PostHistoryTypeId="1" PostId="5539" RevisionGUID="41824db2-bcbc-4160-a84e-a603288f2454" CreationDate="2017-08-29T22:25:54.133" UserId="7028" Text="How is it possible to generate geometries using space folding?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15114" PostHistoryTypeId="3" PostId="5539" RevisionGUID="41824db2-bcbc-4160-a84e-a603288f2454" CreationDate="2017-08-29T22:25:54.133" UserId="7028" Text="|transformations|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15115" PostHistoryTypeId="2" PostId="5540" RevisionGUID="228dd9a3-7723-4157-8602-8c813e1d1c47" CreationDate="2017-08-30T01:59:26.593" UserId="7202" Text="I've been working on a 2d shadow system for a school project, using [this method][1] to generate visibility polygons. However, I'm having issues figuring out how to draw those visibility polygons in a way that reveals everything drawn within them, rather than drawing over them like a normal sprite would.&#xD;&#xA;&#xD;&#xA;From what I've been able to figure out, it seems like what I want to do is to draw the visibility polygons to some texture first, and then use that texture somehow when drawing the rest of the objects on the screen to get the shadow/light effect.&#xD;&#xA;&#xD;&#xA;Unfortunately all the tutorials I've been able to find aren't very helpful. So, my questions are:&#xD;&#xA;&#xD;&#xA;1) How do I tell OpenGL to render to a texture instead of the screen?&#xD;&#xA;&#xD;&#xA;2) How do I use that texture to create the effect I want?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ncase.me/sight-and-light/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15116" PostHistoryTypeId="1" PostId="5540" RevisionGUID="228dd9a3-7723-4157-8602-8c813e1d1c47" CreationDate="2017-08-30T01:59:26.593" UserId="7202" Text="OpenGL: Rendering 2D shadows" ContentLicense="CC BY-SA 3.0" />
  <row Id="15117" PostHistoryTypeId="3" PostId="5540" RevisionGUID="228dd9a3-7723-4157-8602-8c813e1d1c47" CreationDate="2017-08-30T01:59:26.593" UserId="7202" Text="|opengl|rendering|texture|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15121" PostHistoryTypeId="2" PostId="5542" RevisionGUID="5ec3eb04-e277-4c16-86a4-597802a91dd4" CreationDate="2017-08-30T07:12:36.397" UserId="7028" Text="You don't need to render to texture to achieve an effect like this. Use [stencil buffer][1].&#xD;&#xA;&#xD;&#xA;The geometry of the visible area can be drawn using `GL_TRIANGLE_FAN`, if you start from the middle:&#xD;&#xA;&#xD;&#xA;[![mask][2]][2]&#xD;&#xA;&#xD;&#xA;At the beginning of each frame:&#xD;&#xA;&#xD;&#xA; - Clear the stencil buffer (and enable stencil test)&#xD;&#xA; - Set the stencil function to always pass, and to replace the current value in the buffer to a greater than zero number (for example one)&#xD;&#xA; - Draw the visible part as a `GL_TRIANGLE_FAN`&#xD;&#xA; - Now the stencil buffer contains 1 at visible locations and 0 where the character can't see.&#xD;&#xA;&#xD;&#xA;Once you have a stencil buffer like this, you can control which objects you want to draw using glStencilFunc. Do not write to the stencil buffer, just use the stencil test to discard fragments which are visible/invisible.&#xD;&#xA;&#xD;&#xA;If you want to draw a background which is visible everywhere, use `GL_ALWAYS`. For objects which are only displayed in the visible area use `GL_EQUAL` and `1`. Similarly you can draw something (for example a dark quad) just in the invisible parts of the scene with `GL_EQUAL` and `0`.&#xD;&#xA;&#xD;&#xA;If it is not clear, how to use stencil buffers, check out [this tutorial][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://open.gl/depthstencils&#xD;&#xA;  [2]: https://i.stack.imgur.com/R6FZS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15122" PostHistoryTypeId="5" PostId="5542" RevisionGUID="70394d1b-3fa6-4c8d-9d6f-508d84c7d423" CreationDate="2017-08-30T07:18:24.450" UserId="7028" Comment="added 71 characters in body" Text="You don't need to render to texture to achieve an effect like this. Use [stencil buffer][1].&#xD;&#xA;&#xD;&#xA;The visibility polygon can be drawn using `GL_TRIANGLE_FAN`, if you start from the middle:&#xD;&#xA;&#xD;&#xA;[![mask][2]][2]&#xD;&#xA;&#xD;&#xA;At the beginning of each frame:&#xD;&#xA;&#xD;&#xA; 1. Clear the stencil buffer (and enable stencil test)&#xD;&#xA; 2. Set the stencil function to always pass, and to replace the current value in the buffer to a greater than zero number (for example one)&#xD;&#xA; 3. Draw the visible part as a `GL_TRIANGLE_FAN`. If you have multiple characters/lights, draw the visibility polygon for each.&#xD;&#xA;&#xD;&#xA;Now the stencil buffer contains 1 at visible locations and 0 where the character can't see.&#xD;&#xA;&#xD;&#xA;Once you have a stencil buffer like this, you can control which objects you want to draw using glStencilFunc. Do not write to the stencil buffer, just use the stencil test to discard fragments which are visible/invisible.&#xD;&#xA;&#xD;&#xA;If you want to draw a background which is visible everywhere, use `GL_ALWAYS`. For objects which are only displayed in the visible area use `GL_EQUAL` and `1`. Similarly you can draw something (for example a dark quad) just in the invisible parts of the scene with `GL_EQUAL` and `0`.&#xD;&#xA;&#xD;&#xA;If it is not clear, how to use stencil buffers, check out [this tutorial][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://open.gl/depthstencils&#xD;&#xA;  [2]: https://i.stack.imgur.com/R6FZS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15123" PostHistoryTypeId="2" PostId="5543" RevisionGUID="13e8db59-3d56-4981-b61f-2884d97e0672" CreationDate="2017-08-30T08:54:57.873" UserId="1937" Text="I found an answer in the form of the [Todd-Coxeter Algorithm][1] from group theory. This still involves iterating over permutations of the group, and removing duplicates. However, the group can be defined using symbols to represent different sequences of operations, and duplicate-matching performed on these symbols rather than elements of the group itself.&#xD;&#xA;&#xD;&#xA;For example, if a pair of mirrors A and B have an angle of (PI/3) then they form a cycle of order 3 (since a reflection through a pair of mirrors equals a rotation through twice the angle between them). So the sequence ABABAB maps any element back onto itself. By constructing a path like this for each pair of mirrors, it's possible to define new elements for each step along a path, then eliminate duplicates either through string-matching operations or by constructing a graph and eliminating equivalent nodes. For large sets, this should be much more efficient than multiplying and comparing matrices directly at each step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Todd%E2%80%93Coxeter_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="15124" PostHistoryTypeId="2" PostId="5544" RevisionGUID="ba30f206-21d2-44ef-8105-db0737bc21a3" CreationDate="2017-08-30T11:25:59.247" UserId="7028" Text="According to your comment, your goal is to avoid drawing the invisible faces.&#xD;&#xA;There is no reason to find the closest 3 sides of the cube and draw them, because it is possible that only one or tho sides are visible.&#xD;&#xA;&#xD;&#xA;Finding the exact distance from a polygon in 3D space is computationally expensive. Instead of doing it, I would like to suggest a better method:&#xD;&#xA;&#xD;&#xA;Use [face normals][1]. A normal is a vector, which is perpendicular to a given surface at a given point.&#xD;&#xA;&#xD;&#xA;If you calculate the normal vector (and the points of the polygon) in world space, you can decide using a simple dot product, if the polygon is facing towards the camera:&#xD;&#xA;&#xD;&#xA;    bool is_visisble = 0 &lt; dot(&#xD;&#xA;        transformMat4(face.normal, world_mat_it), // normal in world space&#xD;&#xA;        // vec from face midpoint to the camera position&#xD;&#xA;        sub(&#xD;&#xA;            eye, // camera position&#xD;&#xA;            transformMat4(face.midpoint, world_mat) // Face midpoint in world space&#xD;&#xA;        )&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;Here you can find a renderer written is javascript, which uses this method: https://jsfiddle.net/deadmanswitch/sw22s4fs/&#xD;&#xA;&#xD;&#xA;If there are more complex objects in the scene, then you should order the faces by the distance between the midpoint and the camera, and draw the closer ones first, to avoid rendering farther objects over closer ones.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Normal_(geometry)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15125" PostHistoryTypeId="5" PostId="5544" RevisionGUID="0bdde636-9cfa-4aca-acf9-620009a54337" CreationDate="2017-08-30T11:34:32.957" UserId="7028" Comment="added 2 characters in body" Text="According to your comment, your goal is to avoid drawing the invisible faces.&#xD;&#xA;There is no reason to find the closest 3 sides of the cube and draw them, because it is possible that only one or tho sides are visible.&#xD;&#xA;&#xD;&#xA;Finding the exact distance from a polygon in 3D space is computationally expensive. Instead of doing it, I would like to suggest a better method:&#xD;&#xA;&#xD;&#xA;Use [face normals][1]. A normal is a vector, which is perpendicular to a given surface at a given point.&#xD;&#xA;&#xD;&#xA;If you calculate the normal vector (and the points of the polygon) in world space, you can decide using a simple dot product, if the polygon is facing towards the camera:&#xD;&#xA;&#xD;&#xA;    bool is_visisble = 0 &lt; dot(&#xD;&#xA;        transformMat4(face.normal, world_mat_it), // normal in world space&#xD;&#xA;        // vec from face midpoint to the camera position&#xD;&#xA;        sub(&#xD;&#xA;            eye, // camera position&#xD;&#xA;            transformMat4(face.midpoint, world_mat) // Face midpoint in world space&#xD;&#xA;        )&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;Here you can find a renderer written is javascript, which uses this method: https://jsfiddle.net/deadmanswitch/sw22s4fs/&#xD;&#xA;&#xD;&#xA;If there are more complex objects in the scene, then you should order the faces by the distance between the midpoint and the camera, and draw the farthest ones first, to avoid rendering farther objects over closer ones.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Normal_(geometry)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15135" PostHistoryTypeId="2" PostId="5547" RevisionGUID="cad8d624-1cdc-4bba-b4fb-35260e835ac6" CreationDate="2017-08-31T08:04:29.587" UserId="7008" Text="I'm currently fighting with the spectrum-&gt;RGB color conversions, my algorithm seems to make an error somewhere, e.g. I get values &gt;1 for some spectral responses.&#xD;&#xA;&#xD;&#xA;Now there is a way to calculate an rgb value for normal incidence from index of refraction:&#xD;&#xA;&#xD;&#xA;F(0°) = $(\frac{n-1}{n+1})^2$&#xD;&#xA;&#xD;&#xA;Where n is the index of refraction (Real-Time Rendering 3rd, p.234 f.)&#xD;&#xA;And if $n$ is constant, you can use it for all RGB channels.&#xD;&#xA;&#xD;&#xA;However, if I calculate the spectral value with my spectrum-&gt;RGB conversion and just use a constant $n$, I get different values for R, G and B.&#xD;&#xA;&#xD;&#xA;Specifically, $n = 1.52$ would leat to $RGB_{single} = (0.04257999496;0.04257999496;0.04257999496)$ whereas my program calculates $RGB_{spectrum} = 0.054223;0.042692;0.041095$ (evaluated at $390nm - 780nm$).&#xD;&#xA;&#xD;&#xA;So my question now is: would a constant index of refraction really lead to a grayscale (i.e. all channels the same) value? Because the conversion functions depend on the CIE functions, taking the integral of those and clearly the integrals are different for $x, y, z$.&#xD;&#xA;&#xD;&#xA;Also: since I seem to have a problem with my program in the first place: is there a step by step tutorial for creating the conversion function somewhere?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15136" PostHistoryTypeId="1" PostId="5547" RevisionGUID="cad8d624-1cdc-4bba-b4fb-35260e835ac6" CreationDate="2017-08-31T08:04:29.587" UserId="7008" Text="Does a constant reflection over the light spectrum lead to grayscale value?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15137" PostHistoryTypeId="3" PostId="5547" RevisionGUID="cad8d624-1cdc-4bba-b4fb-35260e835ac6" CreationDate="2017-08-31T08:04:29.587" UserId="7008" Text="|color-science|spectral|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15138" PostHistoryTypeId="5" PostId="5547" RevisionGUID="280ec64b-f36a-4554-bdcb-88c1235c801a" CreationDate="2017-08-31T08:15:30.087" UserId="7008" Comment="added the sampling rate" Text="I'm currently fighting with the spectrum-&gt;RGB color conversions, my algorithm seems to make an error somewhere, e.g. I get values &gt;1 for some spectral responses.&#xD;&#xA;&#xD;&#xA;Now there is a way to calculate an rgb value for normal incidence from index of refraction:&#xD;&#xA;&#xD;&#xA;F(0°) = $(\frac{n-1}{n+1})^2$&#xD;&#xA;&#xD;&#xA;Where n is the index of refraction (Real-Time Rendering 3rd, p.234 f.)&#xD;&#xA;And if $n$ is constant, you can use it for all RGB channels.&#xD;&#xA;&#xD;&#xA;However, if I calculate the spectral value with my spectrum-&gt;RGB conversion and just use a constant $n$, I get different values for R, G and B.&#xD;&#xA;&#xD;&#xA;Specifically, $n = 1.52$ would lead to $RGB_{single} = (0.04257999496;0.04257999496;0.04257999496)$ whereas my program calculates $RGB_{spectrum} = 0.054223;0.042692;0.041095$ (evaluated at $390nm - 780nm$ with $\Delta\lambda = 10nm$).&#xD;&#xA;&#xD;&#xA;So my question now is: would a constant index of refraction really lead to a grayscale (i.e. all channels the same) value? Because the conversion functions depend on the CIE functions, taking the integral of those and clearly the integrals are different for $x, y, z$.&#xD;&#xA;&#xD;&#xA;Also: since I seem to have a problem with my program in the first place: is there a step by step tutorial for creating the conversion function somewhere?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15140" PostHistoryTypeId="5" PostId="5520" RevisionGUID="ec9961c7-6615-4793-914e-8a08eeb788eb" CreationDate="2017-08-31T13:10:27.963" UserId="6041" Comment="added 1103 characters in body" Text="**Update**&#xD;&#xA;&#xD;&#xA;I am editing and posting this question in a different way from the point of view of [Nishita paper][1].&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Sunlight gets scattered at P and attenuated before reaching Pv. Therefore intensity reaching Pv coming from P can be obtained by multiplying the attenuation by intensity at P:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The intensity reaching Pv therefore can be obtained by integrating light due to air molecules along the ray segment PaPb:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Where &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;If I am to solve this integral by Monte Carlo method and without ray marching approach, What would be the estimator and what are the good choices for pdf and sampling method?&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA; &#xD;&#xA;*********************************************************&#xD;&#xA;I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][7]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel(not sure why the sun is so small, any idea?):&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;The pdf is 1/segmentLength and the sample is taken uniformly in this distance.&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;      public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;            {&#xD;&#xA;                Vector estimatedColor = new Vector();&#xD;&#xA;    &#xD;&#xA;                Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;    &#xD;&#xA;                ISect isect = Scene.Trace(ray);&#xD;&#xA;                if (ISect.IsNull(isect))&#xD;&#xA;                    estimatedColor = Atmosph.ComputeIncidentLight(ray, rand);&#xD;&#xA;                else&#xD;&#xA;                    estimatedColor = isect.Thing.Material.Emission + &#xD;&#xA;                                          ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;                ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;      public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;            {&#xD;&#xA;                r.Start.Z += earthRadius;&#xD;&#xA;    &#xD;&#xA;                ISect isect = earth.Intersect(r);&#xD;&#xA;                if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;                &#xD;&#xA;                int numSamples = 1;&#xD;&#xA;                int numSamplesLight = 1;&#xD;&#xA;                double segmentLength = isect.Dist / numSamples;&#xD;&#xA;                double tCurrent = 0;&#xD;&#xA;                Vector sumR = Vector.ZERO;&#xD;&#xA;                Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;                double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;                double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;                double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;                double g = 0.76f;&#xD;&#xA;                double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;                for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;                {&#xD;&#xA;                    Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;                    double height = samplePosition.Length() - earthRadius;&#xD;&#xA;                    // compute optical depth for light&#xD;&#xA;                    double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;                    double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;                    opticalDepthR += hr;&#xD;&#xA;                    opticalDepthM += hm;&#xD;&#xA;                    // light optical depth&#xD;&#xA;                    ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;                    double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;                    double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;                    int j;&#xD;&#xA;                    for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;                    {&#xD;&#xA;                        Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                        double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                        if (heightLight &lt; 0) break;&#xD;&#xA;                        opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                        opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                        tCurrentLight += segmentLengthLight;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == numSamplesLight)&#xD;&#xA;                    {&#xD;&#xA;                        Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                        Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                        sumR += attenuation * hr;&#xD;&#xA;                        sumM += attenuation * hm;&#xD;&#xA;                    }&#xD;&#xA;                    tCurrent += segmentLength;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;                // scientific in a future revision of this lesson/code&#xD;&#xA;                return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different from the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://nishitalab.org/user/nis/cdrom/sig93_nis.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/JCbNW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/t4OWe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zEuOL.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bPZsR.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/WHUw0.png&#xD;&#xA;  [7]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [8]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15141" PostHistoryTypeId="2" PostId="5548" RevisionGUID="bf1d01a4-a9b3-4d38-af1d-a891eb6e4145" CreationDate="2017-08-31T23:36:44.823" UserId="6546" Text="I tried implementing `Perlin Noise` using the `Wikipedia` as my main resource. From what I can tell my implementation of the algorithm is spot on but for some reason I'm getting a lot of values equating to 1 or to 0.&#xD;&#xA;&#xD;&#xA;This is my Perlin function:&#xD;&#xA;&#xD;&#xA;    GLfloat perlin(GLfloat x, GLfloat y)&#xD;&#xA;	{&#xD;&#xA;		// Turn param into vector&#xD;&#xA;		glm::vec2 xy = glm::vec2(x, y);&#xD;&#xA;&#xD;&#xA;		// Grid Cell Coordinates&#xD;&#xA;		glm::vec2 bottomLeft = glm::vec2(std::floor(x), std::floor(y));&#xD;&#xA;		glm::vec2 topRight = glm::vec2(bottomLeft.x + 1, bottomLeft.y + 1);&#xD;&#xA;&#xD;&#xA;		GLfloat sx = x - bottomLeft.x;&#xD;&#xA;		GLfloat sy = y - bottomLeft.y;&#xD;&#xA;&#xD;&#xA;		GLfloat bottomLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)bottomLeft.y], xy - bottomLeft);&#xD;&#xA;		GLfloat bottomRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)bottomLeft.y], xy - glm::vec2(topRight.x, bottomLeft.y));&#xD;&#xA;&#xD;&#xA;		GLfloat smooth1 = glm::smoothstep(bottomLeftDot, bottomRightDot, sx);&#xD;&#xA;&#xD;&#xA;		GLfloat topLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)topRight.y], xy - glm::vec2(bottomLeft.x, topRight.y));&#xD;&#xA;		GLfloat topRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)topRight.y], xy - topRight);&#xD;&#xA;&#xD;&#xA;		GLfloat smooth2 = glm::smoothstep(topLeftDot, topRightDot, sx);&#xD;&#xA;&#xD;&#xA;		GLfloat value = glm::smoothstep(smooth1, smooth2, sy);&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is my gradient vector generator:&#xD;&#xA;&#xD;&#xA;    glm::vec2 randomVector(GLfloat length)&#xD;&#xA;	{&#xD;&#xA;		std::random_device rd;&#xD;&#xA;		std::uniform_real_distribution&lt;GLfloat&gt; dist(0.0, 2.0 * PI);&#xD;&#xA;		GLfloat angle = dist(rd);&#xD;&#xA;&#xD;&#xA;		// Turn angle and length into vector&#xD;&#xA;		// The length of the vector is implicitly 1&#xD;&#xA;		GLfloat x = length * std::cos(angle);&#xD;&#xA;		GLfloat y = length * std::sin(angle);&#xD;&#xA;		return glm::vec2(x, y);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I decided to generate vector in `polar coordinates` so I can easily generate uniformly distributed 2D vectors. (Note: the length of the vectors I'm generating is always 1.0).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p5zn0.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, I am using the generated values as a height map. In the image above you can see that there's a straight wall and I'm wondering if maybe I'm not interpolating correctly or if my `gradient` vector generation is &quot;too&quot; random, or the algorithm is just plain wrong. Can someone point out my mistake?&#xD;&#xA;&#xD;&#xA;I'm generating a 100 by 100 grid and my input values are from 0.00 to 0.99 on each axis.&#xD;&#xA;&#xD;&#xA;Another question I have is Wikipedia says to use a smoothstep function but I'm not sure for what values?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15142" PostHistoryTypeId="1" PostId="5548" RevisionGUID="bf1d01a4-a9b3-4d38-af1d-a891eb6e4145" CreationDate="2017-08-31T23:36:44.823" UserId="6546" Text="Generating gradient vectors for Perlin Noise" ContentLicense="CC BY-SA 3.0" />
  <row Id="15143" PostHistoryTypeId="3" PostId="5548" RevisionGUID="bf1d01a4-a9b3-4d38-af1d-a891eb6e4145" CreationDate="2017-08-31T23:36:44.823" UserId="6546" Text="|interpolation|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15144" PostHistoryTypeId="5" PostId="5548" RevisionGUID="3e5f8d56-fa5a-41f0-b378-969f2914bc0c" CreationDate="2017-09-01T01:40:33.900" UserId="6546" Comment="added 308 characters in body" Text="I tried implementing `Perlin Noise` using the `Wikipedia` as my main resource. From what I can tell my implementation of the algorithm is spot on but for some reason I'm getting a lot of values equating to 1 or to 0.&#xD;&#xA;&#xD;&#xA;This is my Perlin function:&#xD;&#xA;&#xD;&#xA;    GLfloat perlin(GLfloat x, GLfloat y)&#xD;&#xA;	{&#xD;&#xA;		// Turn param into vector&#xD;&#xA;		glm::vec2 xy = glm::vec2(x, y);&#xD;&#xA;&#xD;&#xA;		// Grid Cell Coordinates&#xD;&#xA;		glm::vec2 bottomLeft = glm::vec2(std::floor(x), std::floor(y));&#xD;&#xA;		glm::vec2 topRight = glm::vec2(bottomLeft.x + 1, bottomLeft.y + 1);&#xD;&#xA;&#xD;&#xA;		GLfloat sx = x - bottomLeft.x;&#xD;&#xA;		GLfloat sy = y - bottomLeft.y;&#xD;&#xA;&#xD;&#xA;		GLfloat bottomLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)bottomLeft.y], xy - bottomLeft);&#xD;&#xA;		GLfloat bottomRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)bottomLeft.y], xy - glm::vec2(topRight.x, bottomLeft.y));&#xD;&#xA;&#xD;&#xA;		GLfloat smooth1 = glm::smoothstep(bottomLeftDot, bottomRightDot, sx);&#xD;&#xA;&#xD;&#xA;		GLfloat topLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)topRight.y], xy - glm::vec2(bottomLeft.x, topRight.y));&#xD;&#xA;		GLfloat topRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)topRight.y], xy - topRight);&#xD;&#xA;&#xD;&#xA;		GLfloat smooth2 = glm::smoothstep(topLeftDot, topRightDot, sx);&#xD;&#xA;&#xD;&#xA;		GLfloat value = glm::smoothstep(smooth1, smooth2, sy);&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is my gradient vector generator:&#xD;&#xA;&#xD;&#xA;    glm::vec2 randomVector(GLfloat length)&#xD;&#xA;	{&#xD;&#xA;		std::random_device rd;&#xD;&#xA;		std::uniform_real_distribution&lt;GLfloat&gt; dist(0.0, 2.0 * PI);&#xD;&#xA;		GLfloat angle = dist(rd);&#xD;&#xA;&#xD;&#xA;		// Turn angle and length into vector&#xD;&#xA;		// The length of the vector is implicitly 1&#xD;&#xA;		GLfloat x = length * std::cos(angle);&#xD;&#xA;		GLfloat y = length * std::sin(angle);&#xD;&#xA;		return glm::vec2(x, y);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I decided to generate vector in `polar coordinates` so I can easily generate uniformly distributed 2D vectors. (Note: the length of the vectors I'm generating is always 1.0).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, I am using the generated values as a height map. In the image above you can see that there's a straight wall and I'm wondering if maybe I'm not interpolating correctly or if my `gradient` vector generation is &quot;too&quot; random, or the algorithm is just plain wrong. Can someone point out my mistake?&#xD;&#xA;&#xD;&#xA;I'm generating a 100 by 100 grid and my input values are from 0.00 to 0.99 on each axis.&#xD;&#xA;&#xD;&#xA;Another question I have is Wikipedia says to use a smoothstep function but I'm not sure for what values?&#xD;&#xA;&#xD;&#xA;**Update**:&#xD;&#xA;I changed the `smoothstep` and function to the `lerp` function and now everything seems to be working well but can someone please explain why the outcome is so drastically different.&#xD;&#xA;&#xD;&#xA;New outcome below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p5zn0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qE0qp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15145" PostHistoryTypeId="4" PostId="5548" RevisionGUID="eba3ae01-516a-4d09-a892-8564f16c0f05" CreationDate="2017-09-01T02:15:51.063" UserId="6546" Comment="edited title; deleted 686 characters in body" Text="Perlin Noise with Smooth function vs Lerp" ContentLicense="CC BY-SA 3.0" />
  <row Id="15146" PostHistoryTypeId="5" PostId="5548" RevisionGUID="eba3ae01-516a-4d09-a892-8564f16c0f05" CreationDate="2017-09-01T02:15:51.063" UserId="6546" Comment="edited title; deleted 686 characters in body" Text="I tried implementing `Perlin Noise` using the `Wikipedia` as my main resource. From what I can tell my implementation of the algorithm is spot on but for some reason I'm getting a lot of values equating to 1 or to 0.&#xD;&#xA;&#xD;&#xA;This is my Perlin function:&#xD;&#xA;&#xD;&#xA;    GLfloat perlin(GLfloat x, GLfloat y)&#xD;&#xA;	{&#xD;&#xA;		// Turn param into vector&#xD;&#xA;		glm::vec2 xy = glm::vec2(x, y);&#xD;&#xA;&#xD;&#xA;		// Grid Cell Coordinates&#xD;&#xA;		glm::vec2 bottomLeft = glm::vec2(std::floor(x), std::floor(y));&#xD;&#xA;		glm::vec2 topRight = glm::vec2(bottomLeft.x + 1, bottomLeft.y + 1);&#xD;&#xA;&#xD;&#xA;		GLfloat sx = x - bottomLeft.x;&#xD;&#xA;		GLfloat sy = y - bottomLeft.y;&#xD;&#xA;&#xD;&#xA;		GLfloat bottomLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)bottomLeft.y], xy - bottomLeft);&#xD;&#xA;		GLfloat bottomRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)bottomLeft.y], xy - glm::vec2(topRight.x, bottomLeft.y));&#xD;&#xA;&#xD;&#xA;		GLfloat smooth1 = glm::smoothstep(bottomLeftDot, bottomRightDot, sx);&#xD;&#xA;&#xD;&#xA;		GLfloat topLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)topRight.y], xy - glm::vec2(bottomLeft.x, topRight.y));&#xD;&#xA;		GLfloat topRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)topRight.y], xy - topRight);&#xD;&#xA;&#xD;&#xA;		GLfloat smooth2 = glm::smoothstep(topLeftDot, topRightDot, sx);&#xD;&#xA;&#xD;&#xA;		GLfloat value = glm::smoothstep(smooth1, smooth2, sy);&#xD;&#xA;		return value;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, I am using the generated values as a height map. In the image above you can see that there's a straight wall and I'm wondering if maybe I'm not interpolating correctly. Can someone point out my mistake?&#xD;&#xA;&#xD;&#xA;I'm generating a 100 by 100 grid and my input values are from 0.00 to 0.99 on each axis.&#xD;&#xA;&#xD;&#xA;Another question I have is Wikipedia says to use a smoothstep function but I'm not sure for what values?&#xD;&#xA;&#xD;&#xA;**Update**:&#xD;&#xA;I changed the `smoothstep` and function to the `lerp` function and now everything seems to be working well but can someone please explain why the outcome is so drastically different.&#xD;&#xA;&#xD;&#xA;New outcome below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p5zn0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qE0qp.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15147" PostHistoryTypeId="2" PostId="5549" RevisionGUID="5080066e-f965-487c-ae3d-7a00b06da352" CreationDate="2017-09-01T04:27:54.810" UserId="48" Text="It looks like the way you're using smoothstep isn't quite right.&#xD;&#xA;&#xD;&#xA;With lerp, the first two parameters are the endpoints of the output range, and the third is a 0–1 value specifying how far to interpolate. It looks like you're trying to use smoothstep the same way, but it doesn't work like that: the first two parameters to smoothstep are endpoints of the _input_ range, and the third is a value in the input range; the output of smoothstep is always in 0–1. It's almost the inverse of lerp in that regard. (See also [the GLM docs for smoothstep](https://glm.g-truc.net/0.9.4/api/a00129.html#gabdfe71a62ef69b5ec834601e87588667)).&#xD;&#xA;&#xD;&#xA;To use smoothstep here, you'd want to do something like this:&#xD;&#xA;&#xD;&#xA;    glm::lerp(bottomLeftDot, bottomRightDot, glm::smoothstep(0, 1, sx));&#xD;&#xA;&#xD;&#xA;This applies smoothstep to the `sx` value (which is between 0 and 1). The result, which is another 0–1 value, is then used to lerp between the two &quot;dot&quot; values." ContentLicense="CC BY-SA 3.0" />
  <row Id="15148" PostHistoryTypeId="2" PostId="5550" RevisionGUID="7af13d57-f712-424a-810f-d356b0b5290e" CreationDate="2017-09-01T04:55:33.183" UserId="7000" Text="In [the documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferStorage.xhtml) I see that the final parameter for `glnamedBufferStorage` is `flags` and that `flags`:&#xD;&#xA;&#xD;&#xA;&gt; Specifies the intended usage of the buffer's data store. Must be a bitwise combination of the following flags. GL_DYNAMIC_STORAGE_BIT, GL_MAP_READ_BIT GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT, and GL_CLIENT_STORAGE_BIT.&#xD;&#xA;&#xD;&#xA;However, in the older `glBufferData` we use to specify a `usage` flag which would include things such as `GL_STATIC_DRAW` to specify expected usage patterns.&#xD;&#xA;&#xD;&#xA;Where do we include that with the newer OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15149" PostHistoryTypeId="1" PostId="5550" RevisionGUID="7af13d57-f712-424a-810f-d356b0b5290e" CreationDate="2017-09-01T04:55:33.183" UserId="7000" Text="How to set flags and usage glnamedBufferStorage in new OpenGL 4.4+ (GL_STATIC_DRAW)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15150" PostHistoryTypeId="3" PostId="5550" RevisionGUID="7af13d57-f712-424a-810f-d356b0b5290e" CreationDate="2017-09-01T04:55:33.183" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15151" PostHistoryTypeId="2" PostId="5551" RevisionGUID="d028be02-3e82-4a7f-98a7-6fd60f936e39" CreationDate="2017-09-01T05:00:49.610" UserId="48" Text="Yes, this is called bilinear interpolation or a bilinear mapping. The term &quot;bilinear&quot; crops up more commonly in the context of image resizing or resampling, but it's the same basic idea for transforming quadrilaterals—it's just that the interpolation is applied to the vertex positions of the quad, instead of the colors of pixels in an image.&#xD;&#xA;&#xD;&#xA;One paper that briefly discusses bilinear mappings of quadrilaterals is [Fundamentals of Texture Mapping and Image Warping](https://www.cs.cmu.edu/~ph/texfund/texfund.pdf) by Paul Heckbert; see section 2.2.2." ContentLicense="CC BY-SA 3.0" />
  <row Id="15152" PostHistoryTypeId="2" PostId="5552" RevisionGUID="c1c07c23-e6d3-4408-b47e-220ba2953681" CreationDate="2017-09-01T06:25:39.153" UserId="7000" Text="The typical way I see transform feedback being used is:&#xD;&#xA;&#xD;&#xA;		glGenBuffers(1, &amp;tbo);&#xD;&#xA;		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);&#xD;&#xA;		glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(data), nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;However, new, DSA OpenGL eschews the binding points.  Is there a DSA way to bind a buffer to the transform feedback binding point?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15153" PostHistoryTypeId="1" PostId="5552" RevisionGUID="c1c07c23-e6d3-4408-b47e-220ba2953681" CreationDate="2017-09-01T06:25:39.153" UserId="7000" Text="Is there a DSA technique for transform feedback?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15154" PostHistoryTypeId="3" PostId="5552" RevisionGUID="c1c07c23-e6d3-4408-b47e-220ba2953681" CreationDate="2017-09-01T06:25:39.153" UserId="7000" Text="|opengl|transform-feedback|direct-state-acces|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15155" PostHistoryTypeId="33" PostId="5539" RevisionGUID="fb4cafc8-3304-4368-a4e0-3f2f6d8d1b3f" CreationDate="2017-09-01T06:41:58.023" UserId="7028" Comment="32" />
  <row Id="15156" PostHistoryTypeId="5" PostId="5520" RevisionGUID="b327cc58-fd6b-468f-a381-b8b0d37ff909" CreationDate="2017-09-01T07:54:10.657" UserId="6041" Comment="added 11 characters in body" Text="**Update**&#xD;&#xA;&#xD;&#xA;I am editing and posting this question in a different way; this time from the point of view of [Nishita paper][1].&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Sunlight gets scattered at P and attenuated before reaching Pv. Therefore intensity reaching Pv coming from P can be obtained by multiplying the attenuation by intensity at P:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The intensity reaching Pv therefore can be obtained by integrating light due to air molecules along the ray segment PaPb:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Where &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;If I am to solve this integral by Monte Carlo method and without ray marching approach, What would be the estimator and what are the good choices for pdf and sampling method?&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA; &#xD;&#xA;*********************************************************&#xD;&#xA;I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][7]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel(not sure why the sun is so small, any idea?):&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;The pdf is 1/segmentLength and the sample is taken uniformly in this distance.&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;      public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;            {&#xD;&#xA;                Vector estimatedColor = new Vector();&#xD;&#xA;    &#xD;&#xA;                Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;    &#xD;&#xA;                ISect isect = Scene.Trace(ray);&#xD;&#xA;                if (ISect.IsNull(isect))&#xD;&#xA;                    estimatedColor = Atmosph.ComputeIncidentLight(ray, rand);&#xD;&#xA;                else&#xD;&#xA;                    estimatedColor = isect.Thing.Material.Emission + &#xD;&#xA;                                          ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;                ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;      public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;            {&#xD;&#xA;                r.Start.Z += earthRadius;&#xD;&#xA;    &#xD;&#xA;                ISect isect = earth.Intersect(r);&#xD;&#xA;                if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;                &#xD;&#xA;                int numSamples = 1;&#xD;&#xA;                int numSamplesLight = 1;&#xD;&#xA;                double segmentLength = isect.Dist / numSamples;&#xD;&#xA;                double tCurrent = 0;&#xD;&#xA;                Vector sumR = Vector.ZERO;&#xD;&#xA;                Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;                double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;                double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;                double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;                double g = 0.76f;&#xD;&#xA;                double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;                for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;                {&#xD;&#xA;                    Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;                    double height = samplePosition.Length() - earthRadius;&#xD;&#xA;                    // compute optical depth for light&#xD;&#xA;                    double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;                    double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;                    opticalDepthR += hr;&#xD;&#xA;                    opticalDepthM += hm;&#xD;&#xA;                    // light optical depth&#xD;&#xA;                    ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;                    double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;                    double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;                    int j;&#xD;&#xA;                    for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;                    {&#xD;&#xA;                        Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                        double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                        if (heightLight &lt; 0) break;&#xD;&#xA;                        opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                        opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                        tCurrentLight += segmentLengthLight;&#xD;&#xA;                    }&#xD;&#xA;                    if (j == numSamplesLight)&#xD;&#xA;                    {&#xD;&#xA;                        Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                        Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                        sumR += attenuation * hr;&#xD;&#xA;                        sumM += attenuation * hm;&#xD;&#xA;                    }&#xD;&#xA;                    tCurrent += segmentLength;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;                // scientific in a future revision of this lesson/code&#xD;&#xA;                return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different from the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://nishitalab.org/user/nis/cdrom/sig93_nis.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/JCbNW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/t4OWe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zEuOL.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bPZsR.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/WHUw0.png&#xD;&#xA;  [7]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [8]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15157" PostHistoryTypeId="2" PostId="5553" RevisionGUID="0e6f5d68-9782-4ebc-b78c-9b941cb040a1" CreationDate="2017-09-01T08:10:14.527" UserId="137" Text="Binding points (and other state) are still important when doing actual draw calls. It's only bind to edit that was eschewed.&#xD;&#xA;&#xD;&#xA;In your case the most DSA way to do that would be: &#xD;&#xA;&#xD;&#xA;    glGenBuffers(1, &amp;tbo);&#xD;&#xA;    glNamedBufferData(tbo,sizeof(data), nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15158" PostHistoryTypeId="2" PostId="5554" RevisionGUID="01f81d52-0a3c-4056-8340-04b6e84a8668" CreationDate="2017-09-01T08:15:20.380" UserId="137" Text="The usage flag in BufferData was basically useless. There is no functional difference between each value and drivers used other ways to decide how to handle its data.&#xD;&#xA;&#xD;&#xA;The `flags` parameter on the other hand actually changes what you can do with the buffer." ContentLicense="CC BY-SA 3.0" />
  <row Id="15159" PostHistoryTypeId="5" PostId="5547" RevisionGUID="4d9b5f2d-6e9d-4349-8b81-23df447e6c49" CreationDate="2017-09-01T08:24:58.267" UserId="7008" Comment="added the code upon request" Text="I'm currently fighting with the spectrum-&gt;RGB color conversions, my algorithm seems to make an error somewhere, e.g. I get values &gt;1 for some spectral responses.&#xD;&#xA;&#xD;&#xA;Now there is a way to calculate an rgb value for normal incidence from index of refraction:&#xD;&#xA;&#xD;&#xA;F(0°) = $(\frac{n-1}{n+1})^2$&#xD;&#xA;&#xD;&#xA;Where n is the index of refraction (Real-Time Rendering 3rd, p.234 f.)&#xD;&#xA;And if $n$ is constant, you can use it for all RGB channels.&#xD;&#xA;&#xD;&#xA;However, if I calculate the spectral value with my spectrum-&gt;RGB conversion and just use a constant $n$, I get different values for R, G and B.&#xD;&#xA;&#xD;&#xA;Specifically, $n = 1.52$ would lead to $RGB_{single} = (0.04257999496;0.04257999496;0.04257999496)$ whereas my program calculates $RGB_{spectrum} = 0.054223;0.042692;0.041095$ (evaluated at $390nm - 780nm$ with $\Delta\lambda = 10nm$).&#xD;&#xA;&#xD;&#xA;So my question now is: would a constant index of refraction really lead to a grayscale (i.e. all channels the same) value? Because the conversion functions depend on the CIE functions, taking the integral of those and clearly the integrals are different for $x, y, z$.&#xD;&#xA;&#xD;&#xA;Also: since I seem to have a problem with my program in the first place: is there a step by step tutorial for creating the conversion function somewhere?&#xD;&#xA;&#xD;&#xA;**Edit 01.09.2017 10:25**&#xD;&#xA;After being asked to share my code, here goes (in a somewhat top-down approach):&#xD;&#xA;First I read the CIE functions from file and store them in a std::vector&lt;std::map&lt;float, float&gt;&gt; with wavelength as key and function value as value. the vector just encapsulates x, y and z independently.&#xD;&#xA;&#xD;&#xA;    std::vector&lt;std::map&lt;float, float&gt;&gt; cieFunctions = readCieFunctions(ciePath);&#xD;&#xA;&#xD;&#xA;Now cieFunctions.at(0) is the x function and so forth.&#xD;&#xA;I read in the spectral values basically the same way, into a map with key being the wavelength and value being the reflectivity. Here I take care to match the units, wavelength as $nm$ and reflectivity in values $\in [0, 1]$ (rather than $\in [0, 100]$%).&#xD;&#xA;&#xD;&#xA;Having reached this, I call my `calculateRgbValue(std::map&lt;float, float&gt;spectralValue)` function, where I use the matrix for a D65 white point monitor. I calculate the coordinate, divide it by the integral of Y over the visible wavelength spectrum (constant taken from Physically Based Rendering book) and use that in a multiplcation with said matrix to get the RGB value:&#xD;&#xA;&#xD;&#xA;    QString SpectralToRGBConverter::calculateRgbValue(std::map&lt;float, float&gt; spectralValues)&#xD;&#xA;    {&#xD;&#xA;	QString result;&#xD;&#xA;	Vec3 rgb;&#xD;&#xA;&#xD;&#xA;	Mat3 conversionMatrix(&#xD;&#xA;		3.240479, -1.537150, -0.498535,&#xD;&#xA;		-0.969256, 1.875992, 0.041556,&#xD;&#xA;		0.055648, -0.204043, 1.057311);&#xD;&#xA;&#xD;&#xA;	float X = calcCieCoordinate(spectralValues, cieFunctions.at(0));&#xD;&#xA;	float Y = calcCieCoordinate(spectralValues, cieFunctions.at(1));&#xD;&#xA;	float Z = calcCieCoordinate(spectralValues, cieFunctions.at(2));&#xD;&#xA;&#xD;&#xA;	float yIntegral = 106.856895;	//from Phyiscally Based Rendering 3rd, p. 325&#xD;&#xA;&#xD;&#xA;	Vec3 XYZ(X, Y, Z);&#xD;&#xA;	XYZ /= yIntegral;&#xD;&#xA;&#xD;&#xA;	rgb = conversionMatrix*XYZ;&#xD;&#xA;&#xD;&#xA;	result = (std::to_string(rgb.x) + &quot;;&quot; + std::to_string(rgb.y) + &quot;;&quot; + std::to_string(rgb.z)).c_str();&#xD;&#xA;	return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;The idea of calculating the cie coordinate is best described with the mathematical formula:&#xD;&#xA;$coord = \sum_{i=0}^{n-1}x_i c_i \Delta\lambda$ where $n$ is the number of samples in the spectrum, $x_i$ is the $i-th$ cie function value for the wavelength of the $i-th$ sample and $c_i$ is the $i-th$ function value of the spectrum and $\Delta\lambda$ is the stride between two samples $\Delta\lambda = \lambda_{i+1} - \lambda_i$&#xD;&#xA;&#xD;&#xA;    float SpectralToRGBConverter::calcCieCoordinate(std::map&lt;float, float&gt; spectralValues, std::map&lt;float, float&gt; function)&#xD;&#xA;    {&#xD;&#xA;	//http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html&#xD;&#xA;	//Coordinate = Int_lambda function(lambda) * spectralValue(lambda) dlambda&#xD;&#xA;	//for discrete values:&#xD;&#xA;	//Coordinate = Sum_i function(i) * spectalValue(i) * Delta lambda&#xD;&#xA;	//where Delta lambda is the spacing between two measurements&#xD;&#xA;	float deltaLambda;// in nm&#xD;&#xA;	auto first = spectralValues.begin();&#xD;&#xA;	auto second = std::next(first, 1);&#xD;&#xA;&#xD;&#xA;	if (ui.radioButtonMicroMeter-&gt;isChecked())&#xD;&#xA;	{&#xD;&#xA;		deltaLambda = (second-&gt;first - first-&gt;first) * 1000;&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		deltaLambda = second-&gt;first - first-&gt;first;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float coordinate = 0;&#xD;&#xA;	for (auto pairWavelengthReflectance : spectralValues)&#xD;&#xA;	{&#xD;&#xA;		coordinate += getFunctionValue(function, pairWavelengthReflectance.first) * pairWavelengthReflectance.second * deltaLambda;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return coordinate;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;`getFunctionValue` is basically a nearest neighbor sampling:&#xD;&#xA;&#xD;&#xA;    float SpectralToRGBConverter::getFunctionValue(std::map&lt;float, float&gt; function, float x)&#xD;&#xA;    {&#xD;&#xA;	float conversionFactorWaveLength;&#xD;&#xA;	if (ui.radioButtonMicroMeter-&gt;isChecked())&#xD;&#xA;	{&#xD;&#xA;		//if x is not in nm like function.first&#xD;&#xA;		conversionFactorWaveLength = 1000;&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		conversionFactorWaveLength = 1;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float conversionFactorReflectivityScale;&#xD;&#xA;	if (ui.radioButtonPercentage-&gt;isChecked())&#xD;&#xA;	{&#xD;&#xA;		//if the reflectivity is given in percentages [0, 100] rather than proportions [0, 1]&#xD;&#xA;		conversionFactorReflectivityScale = 0.01;	&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		conversionFactorReflectivityScale = 1;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	float xLookUp = x * conversionFactorWaveLength;&#xD;&#xA;	float previous = 0;&#xD;&#xA;	for (auto pairXY : function)&#xD;&#xA;	{	//maps are sorted&#xD;&#xA;		float current = pairXY.first;&#xD;&#xA;		if (current == xLookUp)&#xD;&#xA;		{&#xD;&#xA;			return function[current] * conversionFactorReflectivityScale;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		if (current &gt; xLookUp)&#xD;&#xA;		{&#xD;&#xA;			//get the closest value to x&#xD;&#xA;			float min;&#xD;&#xA;			if (xLookUp - previous &lt; current - xLookUp)&#xD;&#xA;			{&#xD;&#xA;				min = previous;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				min = current;&#xD;&#xA;			}&#xD;&#xA;			return function[min] * conversionFactorReflectivityScale;&#xD;&#xA;		}&#xD;&#xA;		previous = current;&#xD;&#xA;	}&#xD;&#xA;	return -1;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="15160" PostHistoryTypeId="5" PostId="5553" RevisionGUID="89782105-b288-417e-9d22-becb63951b08" CreationDate="2017-09-01T08:48:38.380" UserId="137" Comment="added 60 characters in body" Text="Binding points (and other state) are still important when doing actual draw calls (stuff like VAOs, UBOs, SSBOs and programs are still bound). It's only bind-to-edit that was eschewed.&#xD;&#xA;&#xD;&#xA;In your case the most DSA way to do that would be: &#xD;&#xA;&#xD;&#xA;    glGenBuffers(1, &amp;tbo);&#xD;&#xA;    glNamedBufferData(tbo,sizeof(data), nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15161" PostHistoryTypeId="50" PostId="4651" RevisionGUID="bc58f9d7-a4ac-44f8-a351-b63bb0853ca0" CreationDate="2017-09-01T11:51:33.073" UserId="-1" />
  <row Id="15162" PostHistoryTypeId="2" PostId="5555" RevisionGUID="eba2e5ac-ba32-42fe-b109-6ae61b2f2768" CreationDate="2017-09-01T14:35:03.900" UserId="2654" Text="There isn't a DSA way to bind buffers to the feedback buffer bindings. But that's because [transform feedbacks are *objects*][1], and there *is* a DSA way to attach buffers to transform feedback objects:&#xD;&#xA;&#xD;&#xA;    GLuint buffer;&#xD;&#xA;    glCreateBuffers(1, &amp;buffer);&#xD;&#xA;    //Fill in buffer's data.&#xD;&#xA;    &#xD;&#xA;    GLuint feedback;&#xD;&#xA;    glCreateTransformFeedbacks(1, &amp;feedback);&#xD;&#xA;    glTransformFeedbackBufferRange(feedback, 0, buffer, offset, size);&#xD;&#xA;&#xD;&#xA;You can then bind `feedback` when you're ready to actually do your feedback operations into those buffers.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Transform_Feedback#Feedback_objects&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15163" PostHistoryTypeId="6" PostId="5552" RevisionGUID="c668d06e-5841-484c-8ccc-ccf41fb63fc9" CreationDate="2017-09-01T16:07:51.327" UserId="127" Comment="Fixed tag spelling." Text="|opengl|transform-feedback|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15164" PostHistoryTypeId="2" PostId="5556" RevisionGUID="9ebff254-8087-4c44-9903-6581649e1c48" CreationDate="2017-09-01T17:42:45.150" UserId="7238" Text="My question is specifically in regards to Metal, since I don't know if the answer would change for another API.&#xD;&#xA;&#xD;&#xA;What I believe I understand so far is this:&#xD;&#xA;&#xD;&#xA;- A mipmapped texture has precomputed &quot;levels of detail&quot;, where lower levels of detail are created by downsampling the original texture in some meaningful way.&#xD;&#xA;&#xD;&#xA;- Mipmap levels are referred to in descending level of detail, where level `0` is the original texture, and higher-levels are power-of-two reductions of it.&#xD;&#xA;&#xD;&#xA;- Most GPUs implement trilinear filtering, which picks two neighboring mipmap levels for each sample, samples from each level using bilinear filtering, and then linearly blends those samples.&#xD;&#xA;&#xD;&#xA;What I don't quite understand is how these mipmap levels are selected. In the [documentation][1] for the Metal standard library, I see that samples can be taken, with or without specifying an instance of a `lod_options` type. I would assume that this argument changes how the mipmap levels are selected, and there are apparently three kinds of `lod_options` for 2D textures:&#xD;&#xA;&#xD;&#xA;- `bias(float value)`&#xD;&#xA;- `level(float lod)`&#xD;&#xA;- `gradient2d(float2 dPdx, float2 dPdy)`&#xD;&#xA;&#xD;&#xA;Unfortunately, the documentation doesn't bother explaining what any of these options do. I can guess that `bias()` biases some automatically chosen level of detail, but then what does the bias `value` mean? What scale does it operate on? Similarly, how is the `lod` of `level()` translated into discrete mipmap levels? And, operating under the assumption that `gradient2d()` uses the gradient of the texture coordinate, how does it use that gradient to select the mipmap level?&#xD;&#xA;&#xD;&#xA;More importantly, if I omit the `lod_options`, how are the mipmap levels selected then? Does this differ depending on the type of function being executed?&#xD;&#xA;&#xD;&#xA;And, if the default no-lod-options-specified operation of the `sample()` function is to do something like `gradient2D()` (at least in a fragment shader), does it utilize simple screen-space derivatives, or does it work directly with rasterizer and interpolated texture coordinates to calculate a precise gradient?&#xD;&#xA;&#xD;&#xA;And finally, how consistent is any of this behavior from device to device? An old article (old as in DirectX 9) I read referred to complex device-specific mipmap selection, but I don't know if mipmap selection is better-defined on newer architectures.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15165" PostHistoryTypeId="1" PostId="5556" RevisionGUID="9ebff254-8087-4c44-9903-6581649e1c48" CreationDate="2017-09-01T17:42:45.150" UserId="7238" Text="How are mipmap levels computed in Metal?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15166" PostHistoryTypeId="3" PostId="5556" RevisionGUID="9ebff254-8087-4c44-9903-6581649e1c48" CreationDate="2017-09-01T17:42:45.150" UserId="7238" Text="|texture|interpolation|rasterizer|filtering|mipmap|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15167" PostHistoryTypeId="2" PostId="5557" RevisionGUID="1cf8b77b-d938-42e7-b762-73dc6fe41900" CreationDate="2017-09-01T20:03:25.607" UserId="7239" Text="Below are the original image and a JPEG encoded/decoded image. To my untrained eyes, cyan becomes yellow, yellow becomes magenta, and magenta becomes cyan. Obviously there's a problem with the encoding and/or decoding, but I'd appreciate a more specific answer, along the lines of: &quot;The image was encoded in X [color space], but was decoded in Y.&quot; Thank you. &#xD;&#xA;&#xD;&#xA;[![original][1]][1]&#xD;&#xA;&#xD;&#xA;[![JPEG][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xJK6x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4Fu3g.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15168" PostHistoryTypeId="1" PostId="5557" RevisionGUID="1cf8b77b-d938-42e7-b762-73dc6fe41900" CreationDate="2017-09-01T20:03:25.607" UserId="7239" Text="What causes this color shift?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15169" PostHistoryTypeId="3" PostId="5557" RevisionGUID="1cf8b77b-d938-42e7-b762-73dc6fe41900" CreationDate="2017-09-01T20:03:25.607" UserId="7239" Text="|color|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15170" PostHistoryTypeId="2" PostId="5558" RevisionGUID="30e58eab-d928-4b89-9204-7355844e3df2" CreationDate="2017-09-02T22:01:33.643" UserId="7000" Text="I am reading the OpenGL SuperBible 7th edition which covers *atomic operations* on memory specifically within shader storage blocks.&#xD;&#xA;&#xD;&#xA;It says (about atomic operations):&#xD;&#xA;&#xD;&#xA;&gt; If two invocations access the same memory locations... then they will be *serialized* and only one will get to go at one time.&#xD;&#xA;&#xD;&#xA;Great. Howver, it then goes on to cover **Synchronizing Access to Memory** specifically and the use of `glMemoryBarrier`&#xD;&#xA;&#xD;&#xA;As I understand it, you need to use `glMemoryBarrier` once you start writing to buffers from shaders.&#xD;&#xA;&#xD;&#xA;However, the distinction is not made clear to me about *why* I need to use a barrier if the operations I am doing within my shader are atomic operations.&#xD;&#xA;&#xD;&#xA;It's possible I am conflating atomic operations and general memory access, but, in the book the line is not clearly drawn.&#xD;&#xA;&#xD;&#xA;When is it that a `glMemoryBarrier` is required? Is it **everytime** a shader writes to memory (whether the operations are atomic or not)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15171" PostHistoryTypeId="1" PostId="5558" RevisionGUID="30e58eab-d928-4b89-9204-7355844e3df2" CreationDate="2017-09-02T22:01:33.643" UserId="7000" Text="Why do I need memory barrier when doing Atomic operations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15172" PostHistoryTypeId="3" PostId="5558" RevisionGUID="30e58eab-d928-4b89-9204-7355844e3df2" CreationDate="2017-09-02T22:01:33.643" UserId="7000" Text="|opengl|memory|synchronization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15173" PostHistoryTypeId="5" PostId="5558" RevisionGUID="8d0024b9-b42a-4c7a-87d8-cb1a38d9a6a5" CreationDate="2017-09-02T22:21:56.270" UserId="7000" Comment="added 1 character in body" Text="I am reading the OpenGL SuperBible 7th edition which covers *atomic operations* on memory specifically within shader storage blocks.&#xD;&#xA;&#xD;&#xA;It says (about atomic operations):&#xD;&#xA;&#xD;&#xA;&gt; If two invocations access the same memory locations... then they will be *serialized* and only one will get to go at one time.&#xD;&#xA;&#xD;&#xA;Great. However, it then goes on to cover **Synchronizing Access to Memory** specifically and the use of `glMemoryBarrier`&#xD;&#xA;&#xD;&#xA;As I understand it, you need to use `glMemoryBarrier` once you start writing to buffers from shaders.&#xD;&#xA;&#xD;&#xA;However, the distinction is not made clear to me about *why* I need to use a barrier if the operations I am doing within my shader are atomic operations.&#xD;&#xA;&#xD;&#xA;It's possible I am conflating atomic operations and general memory access, but, in the book the line is not clearly drawn.&#xD;&#xA;&#xD;&#xA;When is it that a `glMemoryBarrier` is required? Is it **everytime** a shader writes to memory (whether the operations are atomic or not)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15174" PostHistoryTypeId="2" PostId="5559" RevisionGUID="3f97cf03-b4f5-4820-8f1f-e5ba774018d6" CreationDate="2017-09-02T22:31:26.180" UserId="2654" Text="`glMemoryBarrier` is for when you want to make [writes from one rendering command visible to reads from a subsequent rendering command][1].&#xD;&#xA;&#xD;&#xA;That is, you can do all the atomics you like during a rendering command. But without the barrier, there's no guarantee that any of those atomic actions will be visible to later commands. Yes, they will still be *atomic*, but you aren't guaranteed to be able to read the values that were previously written. In part because they haven't necessarily happened yet.&#xD;&#xA;&#xD;&#xA;Sometimes, you actually don't care if you can read what was written; being atomic may be enough. And sometimes, you *do care*.&#xD;&#xA;&#xD;&#xA;Consider the case of a &quot;linked-list&quot; style blending buffer. Each pixel in the image is an integer that represents one of the items in the list. Each FS invocation will use an atomic increment to get a unique identifier, then swap that identifier with the current value in the image. It writes its pixel data to the entry in an SSBO, along with the identifier it swapped out of the image.&#xD;&#xA;&#xD;&#xA;When doing that atomic increment on the unique identifier, you don't care if FS invocations from two different rendering commands execute out of order. You simply need the operation to be atomic. Similarly, the swap doesn't have to be in order; it just needs to be atomic.&#xD;&#xA;&#xD;&#xA;Now, when it comes time to do blending based on this data, *that* is when you need to be able to read all of the data that was previously written. And that rendering operation requires `glMemoryBarrier`.&#xD;&#xA;&#xD;&#xA;Of course, you're not necessarily using atomic operations to *read* these values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Memory_Model#Incoherent_memory_access" ContentLicense="CC BY-SA 3.0" />
  <row Id="15175" PostHistoryTypeId="2" PostId="5560" RevisionGUID="9995f7ea-e269-433e-891c-c357d87abf40" CreationDate="2017-09-02T23:29:48.480" UserId="48" Text="Mip selection is pretty well standardized across devices today—with the exception of some of the nitty-gritty details of anisotropic filtering, which is still up to the individual GPU manufacturers to define (and its precise details are generally not publicly documented).&#xD;&#xA;&#xD;&#xA;A good place to read about mip selection  in detail is in [the OpenGL spec, section 8.14, &quot;Texture Minification&quot;](https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf#page=273). I'd assume it works the same way in Metal. (Apple _could_ have changed something, considering they make both the hardware and the API...but I doubt they have.) I'll summarize it here.&#xD;&#xA;&#xD;&#xA;The default mip selection (not using any of the `lod_options` modifiers) uses the screen-space gradients of the texture coordinates to pick the mip levels. Essentially, it tries to pick the mip levels that produce as close as possible to a 1:1 mapping of texels to pixels. For example, if the gradients have a length of 4 texels per pixel, it would pick mip level 2 (which is 1/4th the size of level 0 and therefore gives you 1 mipped texel per pixel).&#xD;&#xA;&#xD;&#xA;With trilinear filtering, since you usually don't land on an _exact_ 1:1 mapping, it picks the two nearest levels and linearly interpolates between them, so that you have a smooth transition between mip levels as the camera or objects in your scene move around.&#xD;&#xA;&#xD;&#xA;To be mathematically precise: you take the screen-space gradients of the texture coordinates, scale them by the texture size (to get them in units of &quot;texels per pixel&quot;), take their lengths, take the longer of the two (X and Y) gradients, and calculate its logarithm base 2. This quantity is called $\lambda$ in the OpenGL spec; it's also commonly known as the texture LOD (level of detail). It's simply a continuous version of the integer mip level index. So, the mip levels used are the two integers nearest to $\lambda$, and the fractional part of $\lambda$ is used to blend between them. For example if $\lambda = 2.8$, the GPU will sample mip levels 2 and 3 of the texture, then blend to 80% level 3 and 20% level 2.&#xD;&#xA;&#xD;&#xA;If anisotropic filtering is turned on, then instead of simply using the longer of the two gradients, you use the ratio of them to set the number of aniso samples. For example, if the X gradient is 4 times longer than the Y gradient, you'd use 4 aniso samples, with their positions spaced out along the X gradient. Each one would be a trilinear sample, using a $\lambda$ corresponding to 1/4th the length of the X gradient (i.e. two mip levels lower, since $\log_2(1/4) = -2$).&#xD;&#xA;&#xD;&#xA;Now, as for the modifier options:&#xD;&#xA;&#xD;&#xA;* `bias` applies an offset to $\lambda$ before using it to select mip levels. So, for example, a bias of +1 will make it do trilinear filtering using mips one level higher than it would normally. A bias of −1 will use mips one level lower, and so on.&#xD;&#xA;* `level` completely overrides the automatic calculation of $\lambda$ from screen-space gradients, and lets you put in your own value of $\lambda$ (aka `lod`) directly.&#xD;&#xA;* `gradient2d` lets you put in your own gradient vectors, which substitute for the implicit screen-space gradients of the texture coordinates. The rest of the mip selection and sampling process proceeds as normal, but with the altered gradients. This lets you customize anisotropic filtering.&#xD;&#xA;&#xD;&#xA;In other types of shaders besides fragment shaders, there's no notion of &quot;screen-space gradients&quot;, so the latter two operations are typically the only ones allowed—any operation that tries to use implicit gradients would give a compile error. I'm not positive that's how Metal does it, but that's what I'd expect from working with other APIs." ContentLicense="CC BY-SA 3.0" />
  <row Id="15179" PostHistoryTypeId="5" PostId="5559" RevisionGUID="8085a34a-9fac-4dd5-97ad-5ebf04e17025" CreationDate="2017-09-03T14:24:57.533" UserId="2654" Comment="added 198 characters in body" Text="`glMemoryBarrier` is for when you want to make [writes from one rendering command visible to reads from a subsequent rendering command][1].&#xD;&#xA;&#xD;&#xA;That is, you can do all the atomics you like during a rendering command. But without the barrier, there's no guarantee that any of those atomic actions will be visible to later commands. Yes, they will still be *atomic*m but this only ensures that they will each execute in some order and each operation will fully execute before the next. What they won't ensure is that operations which OpenGL defines has happening &quot;later&quot; will execute before earlier operations.&#xD;&#xA;&#xD;&#xA;Sometimes, you actually don't care about the order of the operations; being atomic may be enough. And sometimes, you *do care*.&#xD;&#xA;&#xD;&#xA;Consider the case of a &quot;linked-list&quot; style blending buffer. Each pixel in the image is an integer that represents one of the items in the list. Each FS invocation will use an atomic increment to get a unique identifier, then swap that identifier with the current value in the image. It writes its pixel data to the entry in an SSBO, along with the identifier it swapped out of the image.&#xD;&#xA;&#xD;&#xA;When doing that atomic increment on the unique identifier, you don't care if FS invocations from two different rendering commands execute out of order. You simply need the operation to be atomic. Similarly, the swap doesn't have to be in order; it just needs to be atomic. As long as they all execute, and the atomic operations do their jobs, then they will be fine.&#xD;&#xA;&#xD;&#xA;Now, when it comes time to do blending based on this data, *that* is when you need to be able to read all of the data that was previously written. And that rendering operation requires `glMemoryBarrier`.&#xD;&#xA;&#xD;&#xA;Of course, you're not necessarily using atomic operations to *read* these values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Memory_Model#Incoherent_memory_access" ContentLicense="CC BY-SA 3.0" />
  <row Id="15181" PostHistoryTypeId="2" PostId="5562" RevisionGUID="b783ebd6-0a18-4ee1-8830-a9a6ebb9a9ad" CreationDate="2017-09-04T03:06:21.977" UserId="7000" Text="The OpenGL SuperBible 7th Edition ppoints out that &#xD;&#xA;&#xD;&#xA;&gt; the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline&#xD;&#xA;&#xD;&#xA;and describes its usage.&#xD;&#xA;&#xD;&#xA;The [OpenGL Wiki][1] says:&#xD;&#xA;&#xD;&#xA;&gt; Atomic counter memory access is not incoherent. So it follows the same rules as for texture reads, framebuffer writes, and so forth, not the Image Load/Store rules. You do not need to use a glMemoryBarrier to synchronize counter accesses.&#xD;&#xA;&#xD;&#xA;So now I am confused:&#xD;&#xA;&#xD;&#xA;Do I (and if so when do I) need to use `glMemoryBarrier` when using an atomic counter?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Atomic_Counter" ContentLicense="CC BY-SA 3.0" />
  <row Id="15182" PostHistoryTypeId="1" PostId="5562" RevisionGUID="b783ebd6-0a18-4ee1-8830-a9a6ebb9a9ad" CreationDate="2017-09-04T03:06:21.977" UserId="7000" Text="Do I need to use glMemoryBarrier with atomic counters?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15183" PostHistoryTypeId="3" PostId="5562" RevisionGUID="b783ebd6-0a18-4ee1-8830-a9a6ebb9a9ad" CreationDate="2017-09-04T03:06:21.977" UserId="7000" Text="|opengl|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15184" PostHistoryTypeId="2" PostId="5563" RevisionGUID="2fb528ab-030d-4145-a3fb-3948ad0fafe3" CreationDate="2017-09-04T03:27:43.530" UserId="5978" Text="Scaling up or down a texture is quite simple, modify the UVs.&#xD;&#xA;&#xD;&#xA;In my particular scenario though, I have multiple &quot;quads&quot; (it is a patch tessellation shader) each with a tiling texture. Does anyone know of a way to change the texture scale, while retaining the tiling in the shader?&#xD;&#xA;&#xD;&#xA;Is precomputing/scaling the uvs on the CPU the only option?&#xD;&#xA;&#xD;&#xA;Example of (traditional) tiling problem:&#xD;&#xA;&#xD;&#xA;[![tiling issue][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zHYzP.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15185" PostHistoryTypeId="1" PostId="5563" RevisionGUID="2fb528ab-030d-4145-a3fb-3948ad0fafe3" CreationDate="2017-09-04T03:27:43.530" UserId="5978" Text="How do you scale an image across planes while retaining perfect tiling?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15186" PostHistoryTypeId="3" PostId="5563" RevisionGUID="2fb528ab-030d-4145-a3fb-3948ad0fafe3" CreationDate="2017-09-04T03:27:43.530" UserId="5978" Text="|opengl|texture|glsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15187" PostHistoryTypeId="2" PostId="5564" RevisionGUID="0fa1cfff-5718-4691-90c1-85beb70451d8" CreationDate="2017-09-04T04:21:54.893" UserId="2654" Text="From the OpenGL 4.6 specification, section 7.12: Shader Memory Access:&#xD;&#xA;&#xD;&#xA;&gt; As described in the OpenGL Shading Language Specification, shaders may perform random-access reads and writes to buffer object memory by reading from, assigning to, or performing atomic memory operation on shader buffer variables, or to texture or buffer object memory by using built-in image load, store, and atomic functions operating on shader image variables. The ability to perform such random-access reads and writes in systems that may be highly pipelined results in ordering and synchronization issues discussed in the sections below.&#xD;&#xA;&#xD;&#xA;Notice something missing from that list? It mentions &quot;shader buffer variables&quot;, and &quot;shader image variables&quot;. But atomic counter variables are not mentioned. And atomic counter variables are a different kind of thing from either of those.&#xD;&#xA;&#xD;&#xA;Therefore, that entire section (which is what explains the behavior of `glMemoryBarrier`) does not apply to atomic counters. Well, except where it specifically says otherwise, but that's only where it defines that helper FS invocations don't have side-effects. Note that even this *explicitly* calls out atomic counters as being something different from regular buffer or image operations: &quot;stores, atomics, and atomic counter updates&quot;.&#xD;&#xA;&#xD;&#xA;To lend greater credence to this view, the [ARB_atomic_counter_buffer_object][1] extension does not mention barriers at all. It doesn't require [ARB_shader_image_load_store][2] as a companion extension either, which is what defines `glMemoryBarrier`. Indeed, it has no interactions whatsoever with image load/store, while image load/store does have specified interactions with atomic counters.&#xD;&#xA;&#xD;&#xA;Given the weight of the evidence in the specifications, I would have to say that the Wiki is right. In the interest of full disclosure, I did write that Wiki article. Though I also did all this research *before* I wrote it.&#xD;&#xA;&#xD;&#xA;Basically, what the API seems to be saying is that buffer updates from atomic counters are treated like buffer updates from feedback operations. The implementation is required to track when you attempt to use that buffer for a read operation, then issue any synchronization needed to make sure that you can read the value. Or if you write to the value in the buffer (like clearing it to a value), then the implementation must automatically synchronize this.&#xD;&#xA;&#xD;&#xA;The likely reason the specification permits this for atomic counters but not for image load/store is that the range of data for atomic counters is *fixed*. SSBOs and image load/store through buffer textures can write to arbitrary parts of the bound range of buffer data. By contrast, atomic counters write to 4 bytes times the number of atomic counter variables used by the shader.&#xD;&#xA;&#xD;&#xA;Note however that atomic counters are affected by the in-shader `memoryBarrier` function. That is, atomic counters are subject to the requirements of, as the Wiki calls it, &quot;[Internal Visibility][3]&quot;. Granted, that's not very useful most of the time, as the primary use of atomic counters is for when multiple invocations are all updating the same one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_atomic_counters.txt&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Memory_Model#Internal_visibility" ContentLicense="CC BY-SA 3.0" />
  <row Id="15188" PostHistoryTypeId="5" PostId="5564" RevisionGUID="5c68411f-7665-4872-86b1-b0f1f3abfc43" CreationDate="2017-09-04T04:31:49.260" UserId="2654" Comment="added 925 characters in body" Text="From the OpenGL 4.6 specification, section 7.12: Shader Memory Access:&#xD;&#xA;&#xD;&#xA;&gt; As described in the OpenGL Shading Language Specification, shaders may perform random-access reads and writes to buffer object memory by reading from, assigning to, or performing atomic memory operation on shader buffer variables, or to texture or buffer object memory by using built-in image load, store, and atomic functions operating on shader image variables. The ability to perform such random-access reads and writes in systems that may be highly pipelined results in ordering and synchronization issues discussed in the sections below.&#xD;&#xA;&#xD;&#xA;Notice something missing from that list? It mentions &quot;shader buffer variables&quot;, and &quot;shader image variables&quot;. But atomic counter variables are not mentioned. And atomic counter variables are a different kind of thing from either of those.&#xD;&#xA;&#xD;&#xA;Therefore, that entire section (which is what explains the behavior of `glMemoryBarrier`) does not apply to atomic counters. Well, except where it specifically says otherwise, but that's only where it defines that helper FS invocations don't have side-effects. Note that even this *explicitly* calls out atomic counters as being something different from regular buffer or image operations: &quot;stores, atomics, and atomic counter updates&quot;.&#xD;&#xA;&#xD;&#xA;To lend greater credence to this view, the [ARB_atomic_counter_buffer_object][1] extension does not mention barriers at all. It doesn't require [ARB_shader_image_load_store][2] as a companion extension either, which is what defines `glMemoryBarrier`. Indeed, it has no interactions whatsoever with image load/store, while image load/store does have specified interactions with atomic counters.&#xD;&#xA;&#xD;&#xA;Given the weight of the evidence in the specifications, I would have to say that the Wiki is right. In the interest of full disclosure, I did write that Wiki article. Though I also did all this research *before* I wrote it.&#xD;&#xA;&#xD;&#xA;Basically, what the API seems to be saying is that buffer updates from atomic counters are treated like buffer updates from feedback operations. The implementation is required to track when you attempt to use that buffer for a read operation, then issue any synchronization needed to make sure that you can read the value. Or if you write to the value in the buffer (like clearing it to a value), then the implementation must automatically synchronize this.&#xD;&#xA;&#xD;&#xA;The likely reason the specification permits this for atomic counters but not for image load/store is that the range of data for atomic counters is *fixed*. SSBOs and image load/store through buffer textures can write to arbitrary parts of the bound range of buffer data. By contrast, atomic counters write to 4 bytes times the number of atomic counter variables used by the shader.&#xD;&#xA;&#xD;&#xA;Note however that atomic counters are affected by the in-shader `memoryBarrier` function. That is, atomic counters are subject to the requirements of, as the Wiki calls it, &quot;[Internal Visibility][3]&quot;. Granted, that's not very useful most of the time, as the primary use of atomic counters is for when multiple invocations are all updating the same one.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;On the other hand:&#xD;&#xA;&#xD;&#xA;&gt; the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline&#xD;&#xA;&#xD;&#xA;The specification describes this particular barrier as:&#xD;&#xA;&#xD;&#xA;&gt; Memory accesses using shader atomic counter built-in functions issued after the barrier will reflect data written by shaders prior to the barrier. Additionally, atomic counter function invocations after the barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated prior to the barrier complete.&#xD;&#xA;&#xD;&#xA;What's curious about this is the &quot;all memory accesses&quot; part. This specific wording is only used in two other bits: shader storage and shader image. Other barriers for coherent operations like query buffers and transform feedbacks tend to use the term &quot;all shader writes&quot;.&#xD;&#xA;&#xD;&#xA;So... I would say that there is confusion at the specification level.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_atomic_counters.txt&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Memory_Model#Internal_visibility" ContentLicense="CC BY-SA 3.0" />
  <row Id="15189" PostHistoryTypeId="50" PostId="5463" RevisionGUID="bb36fa76-74f5-402a-99d4-e728df171859" CreationDate="2017-09-04T04:58:41.823" UserId="-1" />
  <row Id="15198" PostHistoryTypeId="2" PostId="5566" RevisionGUID="5bc6baef-2c82-4d5c-af13-8c281a071343" CreationDate="2017-09-04T09:07:43.543" UserId="7028" Text="Just say, that the angle between the surface and the vector pointing from the object to the camera is 30 degrees.&#xD;&#xA;&#xD;&#xA;To describe rotations, I suggest using the &quot;yaw, pitch, roll&quot;:&#xD;&#xA;&#xD;&#xA;[![yaw pitch roll][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iU6GY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15199" PostHistoryTypeId="2" PostId="5567" RevisionGUID="a1d5593f-e211-42c6-b430-db400d98a9b9" CreationDate="2017-09-04T14:29:40.150" UserId="7250" Text="If you are writing a paper, you should just explain what you mean by your terms in the beginning of the paper, and include your illustrations (preferrably rendered in 3D)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15200" PostHistoryTypeId="2" PostId="5568" RevisionGUID="4171f25d-89f8-495c-afee-6d650583f054" CreationDate="2017-09-05T02:31:28.663" UserId="3003" Text="One solution would be to use repeating texture wrapping, and then use a texture transformation matrix. So let's say you normally set the texture coordinates of your `GL_TEXTURE_2D` to be 0-1 in `u` and `v`. Instead, ensure that your `GL_TEXTURE_WRAP_S` and `GL_TEXTURE_WRAP_T` are set to `GL_REPEAT` or `GL_MIRRORED_REPEAT` and set the texture coordinates to be the tile number to tile number + 1. So the first one would still be 0 to 1. The second one would be 1 to 2, the third would be 2 to 3, etc.&#xD;&#xA;&#xD;&#xA;Next, your vertex shader would have a `mat4` uniform called `textureMatrix` or something like that. The texture matrix you pass in could have scaling in it (and probably other transformations, too). You just multiply the texture coordinates for the polygons by the texture matrix in the vertex shader, and it should apply appropriately." ContentLicense="CC BY-SA 3.0" />
  <row Id="15201" PostHistoryTypeId="5" PostId="5562" RevisionGUID="c7e7f9a6-7eae-41de-a506-14df9512821e" CreationDate="2017-09-05T03:52:23.157" UserId="7000" Comment="deleted 1 character in body" Text="The OpenGL SuperBible 7th Edition points out that &#xD;&#xA;&#xD;&#xA;&gt; the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline&#xD;&#xA;&#xD;&#xA;and describes its usage.&#xD;&#xA;&#xD;&#xA;The [OpenGL Wiki][1] says:&#xD;&#xA;&#xD;&#xA;&gt; Atomic counter memory access is not incoherent. So it follows the same rules as for texture reads, framebuffer writes, and so forth, not the Image Load/Store rules. You do not need to use a glMemoryBarrier to synchronize counter accesses.&#xD;&#xA;&#xD;&#xA;So now I am confused:&#xD;&#xA;&#xD;&#xA;Do I (and if so when do I) need to use `glMemoryBarrier` when using an atomic counter?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Atomic_Counter" ContentLicense="CC BY-SA 3.0" />
  <row Id="15206" PostHistoryTypeId="2" PostId="5570" RevisionGUID="0b0261bc-609f-4989-9cee-e6f650502812" CreationDate="2017-09-05T15:26:52.040" UserId="1937" Text="While making a GPU Marching Cubes implementation a while back, I ran into the issue of OpenGL holding on to memory I had asked it to release. There are a lot of threads on this over at Stack Overflow, and the gist seems to be that you simply can't rely on the API to release VRAM  in a timely manner. In my app, I was trying to be smart, releasing all temp buffers used in mesh creation once I was done with them, and allocating an exact-sized vertex buffer each time the mesh changed. This was counterproductive, and rapidly led to out-of-memory crashes.&#xD;&#xA;&#xD;&#xA;In my case, since it was just a toy app for a uni project, I solved it by allocating worst-case sized buffers and leaving them allocated, recycling buffer space wherever possible for different passes during the mesh extraction process. This was also a bit of an edge-case, since buffers were pretty huge (sometimes hundreds of MB) so out of memory errors appeared quickly.&#xD;&#xA;&#xD;&#xA;This is fine for a strictly limited use case like mine, but my question is, how is VRAM handled in environments like games, where large numbers of meshes and textures need to be loaded and unloaded dynamically? I'm thinking particularly of open-world games like GTA where the world is constantly being streamed-in as the player moves around, but even in more linear games, loading a new level would need a lot of unloading and reloading assets.&#xD;&#xA;&#xD;&#xA;Are assets generally loaded to sections of large fixed buffers and space usage tracked somehow? Or if using a large number of smallish buffers, can the APIs keep up with a few of them being created and destroyed regularly?&#xD;&#xA;Can anyone with experience in engine design shed some light on how this is done in real world usage?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15207" PostHistoryTypeId="1" PostId="5570" RevisionGUID="0b0261bc-609f-4989-9cee-e6f650502812" CreationDate="2017-09-05T15:26:52.040" UserId="1937" Text="Best practices for VRAM management in dynamic environments (e.g. games)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15208" PostHistoryTypeId="3" PostId="5570" RevisionGUID="0b0261bc-609f-4989-9cee-e6f650502812" CreationDate="2017-09-05T15:26:52.040" UserId="1937" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15209" PostHistoryTypeId="2" PostId="5571" RevisionGUID="a3a271fc-013b-46e5-9ab0-ec8b60526499" CreationDate="2017-09-05T16:29:56.203" UserId="7255" Text="I've been going over some OpenGL learning resources and one of them is this article: [Modern OpenGL 04 - Cameras, Vectors &amp; Input][1] in which the author presents an approach to building a `Camera` class that can be used to derive the view and projection matrices.&#xD;&#xA;&#xD;&#xA;In the accompanying source code there is a function that returns the orientation of the camera as a transform matrix ([permalink to source code][2]) which is implemented like this:&#xD;&#xA;&#xD;&#xA;    glm::mat4 Camera::orientation() const {&#xD;&#xA;        glm::mat4 orientation;&#xD;&#xA;        orientation = glm::rotate(orientation, glm::radians(_verticalAngle), glm::vec3(1,0,0));&#xD;&#xA;        orientation = glm::rotate(orientation, glm::radians(_horizontalAngle), glm::vec3(0,1,0));&#xD;&#xA;        return orientation;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I'd like to translate the camera relative to the direction it is facing then I would assume that I could multiply the orientation matrix by the translation vector to get a new vector that does the translation in the direction the camera is facing.&#xD;&#xA;&#xD;&#xA;However, this does not yield the result I was expecting. After looking at how the forward, up and right axis are derived ([permalink to source code][3]):&#xD;&#xA;&#xD;&#xA;    glm::vec3 Camera::forward() const {&#xD;&#xA;        glm::vec4 forward = glm::inverse(orientation()) * glm::vec4(0,0,-1,1);&#xD;&#xA;        return glm::vec3(forward);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glm::vec3 Camera::right() const {&#xD;&#xA;        glm::vec4 right = glm::inverse(orientation()) * glm::vec4(1,0,0,1);&#xD;&#xA;        return glm::vec3(right);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glm::vec3 Camera::up() const {&#xD;&#xA;        glm::vec4 up = glm::inverse(orientation()) * glm::vec4(0,1,0,1);&#xD;&#xA;        return glm::vec3(up);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I can see that I need to multiply the translation vector with the inverse of the orientation matrix to get the expected result but I don't understand why. Isn't the orientation (as used in this article) a rotation matrix? If that's the case then why do I need to inverse it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.tomdalling.com/blog/modern-opengl/04-cameras-vectors-and-input/&#xD;&#xA;  [2]: https://github.com/tomdalling/opengl-series/blob/2f1cb93a531f4f9bd5cbad5b2ac1ebe0cfcff7c7/source/04_camera/source/tdogl/Camera.cpp#L74-L79&#xD;&#xA;  [3]: https://github.com/tomdalling/opengl-series/blob/2f1cb93a531f4f9bd5cbad5b2ac1ebe0cfcff7c7/source/04_camera/source/tdogl/Camera.cpp#L104-L117" ContentLicense="CC BY-SA 3.0" />
  <row Id="15210" PostHistoryTypeId="1" PostId="5571" RevisionGUID="a3a271fc-013b-46e5-9ab0-ec8b60526499" CreationDate="2017-09-05T16:29:56.203" UserId="7255" Text="Why do I need to inverse the orientation matrix of a camera to be able to translate it in the direction it is facing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15211" PostHistoryTypeId="3" PostId="5571" RevisionGUID="a3a271fc-013b-46e5-9ab0-ec8b60526499" CreationDate="2017-09-05T16:29:56.203" UserId="7255" Text="|opengl|3d|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15212" PostHistoryTypeId="2" PostId="5572" RevisionGUID="d1ee97c9-9195-4c07-b348-d068d16fda73" CreationDate="2017-09-05T21:29:55.367" UserId="2654" Text="For consoles (and D3D12/Metal/Vulkan), you know everything you need to know to develop an allocation strategy. You know:&#xD;&#xA;&#xD;&#xA;1. How much memory, of each kind, is available.&#xD;&#xA;&#xD;&#xA;2. How big each kind of resource will be. Textures of a particular format and size take up X bytes, require Y alignment, etc.&#xD;&#xA;&#xD;&#xA;Given such information, you can devise an allocation strategy for data uploading. Open-world games use streaming of fixed-sized blocks of data. Each sector of the game contains resources that take up X number of bytes, and therefore, artists have X number of bytes of storage to work with. It's their job to fit all of the stuff needed for that region of the game into that much space. There will also be stream blocks for larger collections of regions, or other data that gets shared between all game regions.&#xD;&#xA;&#xD;&#xA;For other games, some of them load everything at level-load time. Some do hard-loads in the middle of &quot;levels&quot; (see many Source-engine games). Others stream things more dynamically, but even there, artists are restricted to using resources that total up to X number of bytes.&#xD;&#xA;&#xD;&#xA;On consoles, such sizes can be known a priori, but with Vulkan/Metal/D3D12, these have to be queried for a particular piece of hardware. So in the latter case, you have to be more reactive to what's available, but all of the information is *available* to the user.&#xD;&#xA;&#xD;&#xA;For other APIs/platforms (OpenGL/D3D pre-12), things are rather more complicated. Consoles and the lower-level APIs give you direct access to memory allocations, which gives you more flexibility. You can use a piece of memory for vertex data at one point, then put an image into it later on. Memory is divorced from its current use, so it's much easier for an application to choose *how* to recycle memory.&#xD;&#xA;&#xD;&#xA;For GL/D3D-pre-12, things are difficult. A buffer object is a buffer object, and the memory currently associated with it cannot later be used as a texture. Well, it can, but you cannot explicitly ask that to be done. The most you can do is deallocate the buffer, allocate the image, and hope that the buffer's memory was recycled.&#xD;&#xA;&#xD;&#xA;For cases where you're doing dynamic loading in fixed-sized blocks, you basically have to give your artists more limitations. Instead of limiting the artists by memory, you have to spell out the limitations by *object* So you'd say that a stream block can have &quot;X numbers of textures of Y formats and Z size, and W bytes of vertex data&quot;. Artists can't sacrifice 4 textures to allow one texture to be 4 times the size, or sacrifice a texture to get more vertex data, or sacrifice some vertex data to get more texture space.&#xD;&#xA;&#xD;&#xA;That is what you have to do if you don't trust the implementation's memory allocator to effectively recycle resources. For hard-load cases, it's generally OK to just delete all of the objects and expect the implementation to recycle effectively. But even here, it's a good idea to make sure that you don't try to allocate *all* of the available storage; leave the implementation a healthy percentage for fragmentation and so forth.&#xD;&#xA;&#xD;&#xA;Of course, these kinds of things are a big part of the reason why IHVs have application-specific optimizations: they know up-front which resources were allocated for which purpose, and the driver makers can design allocation schemes that work with these assumptions.&#xD;&#xA;&#xD;&#xA;Which is why Vulkan et. al exist: so that application developers don't have to rely on IHVs to work around problems in the API." ContentLicense="CC BY-SA 3.0" />
  <row Id="15216" PostHistoryTypeId="5" PostId="2325" RevisionGUID="d7366d19-73c1-4a50-b676-346fd2c7972a" CreationDate="2017-09-06T01:22:17.140" UserId="310" Comment="Small typo fix" Text="In order to understand Russian Roulette, let's look at a very basic backward path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely mathematically unbiased, bounces *should* go to infinity. But this is unrealistic, and as you noted, not visually necessary; for most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.&#xD;&#xA;&#xD;&#xA;So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.&#xD;&#xA;&#xD;&#xA;That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20. &#xD;&#xA;[![2 Bounces from Disney's Big Hero 6][1]][1]&#xD;&#xA;[![9 Bounces from Disney's Big Hero 6][2]][2]&#xD;&#xA;&#xD;&#xA;If we choose too low, the image will be visibly biased. But if we choose too high, we're wasting computation energy and time.&#xD;&#xA;&#xD;&#xA;One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias. &#xD;&#xA;&#xD;&#xA;Clamping after a threshold, will *work*, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.&#xD;&#xA;&#xD;&#xA;Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            // Randomly terminate a path with a probability inversely equal to the throughput&#xD;&#xA;            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;            if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // Add the energy we 'lose' by randomly terminating paths&#xD;&#xA;            throughput *= 1 / p;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So path with low throughput that won't contribute much to the scene are more likely to be terminated. &#xD;&#xA;&#xD;&#xA;If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last questions:&#xD;&#xA;&#xD;&#xA; 1. Does Russian Roulette give an unbiased result?&#xD;&#xA;   - Yes&#xD;&#xA; 2. Is Russian Roulette necessary for an unbiased result?&#xD;&#xA;   - Depends on what you mean by unbiased. If you mean mathematically, then yes. However, if you mean visually, then no. You just have to choose you max path depth and cutoff threshold very very carefully. This can be very tedious since it can change from scene to scene.&#xD;&#xA; 3. Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?&#xD;&#xA;   - If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still mathematically biased. To be completely unbiased, it must be random.&#xD;&#xA; 4. If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;   - Russian Roulette only stops the bouncing. It doesn't remove the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason *not* to use it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ikXSo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BPiZ7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15218" PostHistoryTypeId="34" PostId="5520" RevisionGUID="f9ca94d6-8359-4c62-8460-f66d56b0147a" CreationDate="2017-09-06T07:26:57.933" UserId="-1" Comment="31" />
  <row Id="15223" PostHistoryTypeId="2" PostId="5575" RevisionGUID="8a0dd642-13f4-4168-bdb5-eba5480fd24f" CreationDate="2017-09-06T09:55:25.500" UserId="6046" Text="People always forget that there is no &quot;camera&quot; in OpenGL. In order to simulate a camera you have to move the whole world inversely. So if you want ur camera looking 30 degrees downward, you move the whole world 30 degrees upwards. If you want your camera moved to the left, you move the whole world right. That's why you will notice the `&quot;-&quot;` sign in the translation vector where he used the variable `position`. &#xD;&#xA;&#xD;&#xA;Hence the reason there is no separate &quot;view&quot; matrix in openGL, it's modelview matrix combined. That's the reason for taking the inverse. Since a view matrix represent's the camera's forward, up and side, you have to take the inverse since the orientation is defined for the world not the camera." ContentLicense="CC BY-SA 3.0" />
  <row Id="15224" PostHistoryTypeId="2" PostId="5576" RevisionGUID="3c125438-45d5-4a85-bca1-5ca4f786fb53" CreationDate="2017-09-06T12:17:30.847" UserId="7261" Text="What's the algorithm for doing so?&#xD;&#xA;&#xD;&#xA;I have flat shading working and I have perspective correct texture mapping working.  Is the way your raster Gouraud shading much different from the perspective correct texture mapping?  (Is gouraud shading even supposed to be perspective correct?)&#xD;&#xA;&#xD;&#xA;It is my understanding that you interpolate the lighting color/value down the edges, then interpolate across each scanline.  However,  I think I'm stuck on how to properly divide by Z for each pixel to get the correct light/color value for each pixel.&#xD;&#xA;&#xD;&#xA;Any algorithm/article/tutorial would be of great help as I've searched everywhere but can only find high level, abstract descriptions of it.&#xD;&#xA;&#xD;&#xA;Thanks in advance!" ContentLicense="CC BY-SA 3.0" />
  <row Id="15225" PostHistoryTypeId="1" PostId="5576" RevisionGUID="3c125438-45d5-4a85-bca1-5ca4f786fb53" CreationDate="2017-09-06T12:17:30.847" UserId="7261" Text="How do you implement perspective correct Gouraud shading across a triangle?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15226" PostHistoryTypeId="3" PostId="5576" RevisionGUID="3c125438-45d5-4a85-bca1-5ca4f786fb53" CreationDate="2017-09-06T12:17:30.847" UserId="7261" Text="|lighting|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15227" PostHistoryTypeId="2" PostId="5577" RevisionGUID="1e72f5e5-f592-433f-9e2e-164075685e82" CreationDate="2017-09-06T13:21:14.370" UserId="209" Text="&gt; (Is gouraud shading even supposed to be perspective correct?)&#xD;&#xA;&#xD;&#xA;Originally, it wouldn't have been perspective correct, but on (hardware) systems these days it will be. FWIW Dreamcast had perspective correct Gouraud shading because, once you are doing perspective correct texturing, it is relatively little additional cost to do Gouraud &quot;correctly&quot;.&#xD;&#xA;&#xD;&#xA;&gt;I have flat shading working and I have perspective correct texture mapping working. Is the way your raster Gouraud shading much different from the perspective correct texture mapping?&#xD;&#xA;&#xD;&#xA;I'm assuming that you've started with homogeneous 'world space' vertices, i.e. something like, &#xD;&#xA;&#xD;&#xA;$[x,y,z, 1, u,v, R,G,B]$,&#xD;&#xA;&#xD;&#xA;applied a projection matrix to get&#xD;&#xA;&#xD;&#xA; $[X_s, Y_s, Z_s, 1, u, v, R, G, B, w]$,&#xD;&#xA;&#xD;&#xA;and then, after clipping, divided through by w to obtain screen coordinates&#xD;&#xA;&#xD;&#xA;$[X_s/w, Y_s/w, Z_s/w, 1/w, u/w, v/w, R/w,... ]$.  &#xD;&#xA;&#xD;&#xA;For convenience, let's rename $u/w$ as $u'$, $v/w$ as $v'$, $1/w$ as $w'$, $R/w$ as $R'$ etc&#xD;&#xA;&#xD;&#xA;To do perspective correct texturing I **assume** you are linearly interpolating, per pixel, the $u'$, $v'$, and $w'$ values, computing the reciprocal of the interpolated  $w'$ and multiplying that by $u'$ and $v'$ to obtain the per-pixel U &amp; V coordinates.&#xD;&#xA;&#xD;&#xA;To do perspective correct Gouraud, simply use the same approach with the interpolated $R'$ , $G'$ and $B'$ values. The most expensive part is typically the division (i.e. reciprocal) but that can be shared with the texturing.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15229" PostHistoryTypeId="2" PostId="5578" RevisionGUID="30294103-3820-49e9-83ce-fd398ffdef54" CreationDate="2017-09-06T22:33:47.717" UserId="7228" Text="I am very new to computer graphics, so I am sorry if this results in a stupid question. &#xD;&#xA;&#xD;&#xA;For educational purposes I am looking through the pbrt code and I have noticed that before computing the direction for the next path for the subsequent bounce, they flip the direction of the incoming ray. Specifically:&#xD;&#xA;&#xD;&#xA;        Vector3f wo = -ray.d, wi;&#xD;&#xA;        Float pdf;&#xD;&#xA;        BxDFType flags;&#xD;&#xA;        Spectrum f = isect.bsdf-&gt;Sample_f(wo, &amp;wi, sampler.Get2D(), &amp;pdf,&#xD;&#xA;                                          BSDF_ALL, &amp;flags);&#xD;&#xA;Now my rationale to justify that (also hinted by the name of the variable), is that we are tracing the rays from the camera, but really the phenomenon we are simulating is light coming from light into the camera, so even if the algorithm does:&#xD;&#xA;&#xD;&#xA;a) Eye --&gt; Object --&gt; Light &#xD;&#xA;&#xD;&#xA;What we are simulating is more like &#xD;&#xA;&#xD;&#xA;b) Eye &lt;-- Object &lt;-- Light &#xD;&#xA;&#xD;&#xA;So my assumption here is that the direction is flipped because of this reason. But if this is the case, should the resulting wi be flipped again before giving it to the next ray as direction? In the next bounce we'll find ourselves in the same process as in the option a) , but if we don't flip wi, don't we have&#xD;&#xA;&#xD;&#xA;PrevObject &lt;-- Object --&gt; Light  instead of &#xD;&#xA;&#xD;&#xA;PrevObject --&gt; Object --&gt; Light &#xD;&#xA;&#xD;&#xA;? &#xD;&#xA;&#xD;&#xA;Is Sample_f returning an already flipped wi (i.e. ready for the next step)? Is my reasoning all wrong? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note that I don't have the book yet, I am just trying to guess from code what's happening." ContentLicense="CC BY-SA 3.0" />
  <row Id="15230" PostHistoryTypeId="1" PostId="5578" RevisionGUID="30294103-3820-49e9-83ce-fd398ffdef54" CreationDate="2017-09-06T22:33:47.717" UserId="7228" Text="PBRT path tracing: negation of ray direction before next event estimation" ContentLicense="CC BY-SA 3.0" />
  <row Id="15231" PostHistoryTypeId="3" PostId="5578" RevisionGUID="30294103-3820-49e9-83ce-fd398ffdef54" CreationDate="2017-09-06T22:33:47.717" UserId="7228" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15232" PostHistoryTypeId="2" PostId="5579" RevisionGUID="f8e6e58b-f609-4ded-9db3-6c3598a49bc1" CreationDate="2017-09-07T09:52:40.797" UserId="6041" Text="The incoming direction woW(coming from eye) is filipped as in pbrt:&#xD;&#xA;&#xD;&#xA;&quot;Another convention we will follow is that the incident light direction wi and the outgoing viewing direction wo will both be normalized and outward facing after being transformed into the local coordinate system at the surface. By convention, the surface normal always points to the outside of the object...&quot;.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aFn0D.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15233" PostHistoryTypeId="5" PostId="5577" RevisionGUID="baa4bde0-d739-41e5-9b10-4d5a541529e8" CreationDate="2017-09-07T13:01:24.020" UserId="209" Comment="minor improvements to text" Text="&gt; (Is gouraud shading even supposed to be perspective correct?)&#xD;&#xA;&#xD;&#xA;Originally, it wouldn't have been perspective correct, but on (hardware) systems these days it will be. FWIW Dreamcast had perspective correct Gouraud shading because, once you are doing perspective correct texturing, it is relatively little additional cost to do Gouraud &quot;correctly&quot;.&#xD;&#xA;&#xD;&#xA;&gt;I have flat shading working and I have perspective correct texture mapping working. Is the way your raster Gouraud shading much different from the perspective correct texture mapping?&#xD;&#xA;&#xD;&#xA;I'm assuming that you've started with homogeneous 'world space' vertices, i.e. something like, &#xD;&#xA;&#xD;&#xA;$[x,y,z, 1, u,v, R,G,B]$,&#xD;&#xA;&#xD;&#xA;applied a projection matrix to get&#xD;&#xA;&#xD;&#xA; $[X_s, Y_s, Z_s, 1, u, v, R, G, B, w]$,&#xD;&#xA;&#xD;&#xA;and then, after clipping, divided through by w to obtain screen coordinates&#xD;&#xA;&#xD;&#xA;$[X_s/w, Y_s/w, Z_s/w, 1/w, u/w, v/w, R/w,... ]$.  &#xD;&#xA;&#xD;&#xA;For convenience, let's rename $u/w$ and $v/w$ as $u'$ &amp; $v'$, $1/w$ as $w'$, $R/w$ as $R'$ etc.&#xD;&#xA;&#xD;&#xA;To do perspective correct texturing I _assume_ you are linearly interpolating, per pixel, the $u'$, $v'$, and $w'$ values, computing the reciprocal of the interpolated  $w'$ and multiplying that by $u'$ and $v'$ to obtain the per-pixel U &amp; V coordinates.&#xD;&#xA;&#xD;&#xA;To do perspective correct Gouraud, simply use the same approach with the interpolated $R'$ , $G'$ and $B'$ values. The most expensive part is typically the division (i.e. reciprocal) but that can be shared with the texturing.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15234" PostHistoryTypeId="5" PostId="5579" RevisionGUID="5900d755-2fcb-4e86-a291-73577e940aa3" CreationDate="2017-09-07T13:10:37.660" UserId="2941" Comment="math formatting, spelling" Text="The incoming direction $\omega_o$ (coming from eye) is flipped in pbrt:&#xD;&#xA;&#xD;&#xA;&quot;Another convention we will follow is that the incident light direction $\omega_i$ and the outgoing viewing direction $\omega_o$ will both be normalized and outward facing after being transformed into the local coordinate system at the surface. By convention, the surface normal always points to the &quot;outside&quot; of the object...&quot;.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aFn0D.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15235" PostHistoryTypeId="24" PostId="5579" RevisionGUID="5900d755-2fcb-4e86-a291-73577e940aa3" CreationDate="2017-09-07T13:10:37.660" Comment="Proposed by 2941 approved by 100, 4958 edit id of 269" ContentLicense="CC BY-SA 3.0" />
  <row Id="15248" PostHistoryTypeId="2" PostId="5583" RevisionGUID="a37f0973-c239-489d-8f69-7d2305c78b63" CreationDate="2017-09-08T02:27:20.823" UserId="7238" Text="Metal seems to provide two very different ways to access vertex data in your vertex shader. You can:&#xD;&#xA;&#xD;&#xA;1. Create an `MTLVertexDescriptor` object, which describes vertex shader inputs, including per-vertex, per-instance, and constant data of basically any Metal-supported primitive type, and compile it into an `MTLRenderPipelineState`. The inputs you describe map to indexed attributes in a single `struct`, which you declare as the `[[stage_in]]` argument of a vertex function.&#xD;&#xA;&#xD;&#xA;**OR**&#xD;&#xA;&#xD;&#xA;2. Use the `[[vertex_id]]` and `[[instance_id]]` inputs to a vertex function as indices into user-defined buffers of arbitrary data.&#xD;&#xA;&#xD;&#xA;The first option is very reminiscent of a classical VBO-centric rendering pipeline, while the second option is a very compute-shader-like approach. Personally, I prefer the second approach, but I'm concerned as to whether it offers the same performance as the first." ContentLicense="CC BY-SA 3.0" />
  <row Id="15249" PostHistoryTypeId="1" PostId="5583" RevisionGUID="a37f0973-c239-489d-8f69-7d2305c78b63" CreationDate="2017-09-08T02:27:20.823" UserId="7238" Text="In Metal, what performance advantages are there, if any, to using vertex descriptors and the [[stage_in]] qualifier?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15250" PostHistoryTypeId="3" PostId="5583" RevisionGUID="a37f0973-c239-489d-8f69-7d2305c78b63" CreationDate="2017-09-08T02:27:20.823" UserId="7238" Text="|shader|performance|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15251" PostHistoryTypeId="2" PostId="5584" RevisionGUID="1e19849e-baf0-4400-a09d-a13a70fa9061" CreationDate="2017-09-08T05:19:44.253" UserDisplayName="user3412" Text="I am a little bit confused about the various flavors of material layering in both online and offline rendering.  I had naively assumed (after using the Mix Shader in Cycles and a few minutes in Substance Painter) that material layering was just a simple mask channel that blended between the final colors, sort of like texture splatting for terrain.&#xD;&#xA;&#xD;&#xA;But reading this question I see that the actual shader inputs are interpolated, rather than the final colors:&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/4157/material-layering&#xD;&#xA;&#xD;&#xA;Is this the same process for offline renderers?  Reading the man page for RenderMan it seems like it is, as they specify only similar Bxdfs can be mixed:&#xD;&#xA;&#xD;&#xA;https://rmanwiki.pixar.com/display/REN/PxrLayerSurface&#xD;&#xA;&#xD;&#xA;Are there any papers that describe the basics?  I found this from SIGGRAPH last month, but it confused the hell out of me:&#xD;&#xA;&#xD;&#xA;http://blog.selfshadow.com/publications/s2017-shading-course/drobot/s2017_pbs_multilayered.pdf&#xD;&#xA;&#xD;&#xA;Lastly, are there any contexts in which material layering is simulation of multiple physical interfaces?  Or is that referred to something else, like nested dielectrics?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15252" PostHistoryTypeId="1" PostId="5584" RevisionGUID="1e19849e-baf0-4400-a09d-a13a70fa9061" CreationDate="2017-09-08T05:19:44.253" UserDisplayName="user3412" Text="Confused about material layering" ContentLicense="CC BY-SA 3.0" />
  <row Id="15253" PostHistoryTypeId="3" PostId="5584" RevisionGUID="1e19849e-baf0-4400-a09d-a13a70fa9061" CreationDate="2017-09-08T05:19:44.253" UserDisplayName="user3412" Text="|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15254" PostHistoryTypeId="2" PostId="5585" RevisionGUID="b51badbf-4782-4e6f-bfc0-5301c5f592ff" CreationDate="2017-09-08T21:11:22.137" UserId="6041" Text="I am implementing light tracing from [this website][1].&#xD;&#xA;&#xD;&#xA;The right wall on the below image is perfect mirror(specular reflection). Its BRDF returns zero that's why it's been rendered black. But how is it to correctly simulate this type of light path in light tracing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://rendering-memo.blogspot.co.uk/2016/03/bidirectional-path-tracing-6-implement.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/mKZLF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15255" PostHistoryTypeId="1" PostId="5585" RevisionGUID="b51badbf-4782-4e6f-bfc0-5301c5f592ff" CreationDate="2017-09-08T21:11:22.137" UserId="6041" Text="How to simulate specular reflection in Light Tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15256" PostHistoryTypeId="3" PostId="5585" RevisionGUID="b51badbf-4782-4e6f-bfc0-5301c5f592ff" CreationDate="2017-09-08T21:11:22.137" UserId="6041" Text="|pathtracing|brdf|global-illumination|specular|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15260" PostHistoryTypeId="2" PostId="5586" RevisionGUID="09aaac07-573c-47a5-bd41-918837406125" CreationDate="2017-09-09T00:17:01.073" UserId="7272" Text="My graphics text explains rotating along the cardinal axes, then generalizes the math to show how to make a rotation matrix for rotating around an arbitrary vector. That all makes sense and I can both follow the math and picture the operations.&#xA;&#xA;Then the text discusses scaling uniformly and in cardinal directions. Again I can follow everything. But then it goes through the math for &quot;scaling in an arbitrary direction&quot;, and although I can follow the vector operations I don't understand what scaling in a non cardinal direction even *means*. I can start with an object rotated &quot;right side up&quot;, and then imagine it getting wider/taller/deeper, but I don't understand what it would mean to scale it in an arbitrary direction.&#xA;&#xA;My first thought was they must just mean scaling each cardinal direction by a different amount, but that can't be right because they don't end up with a diagonal matrix (take the identity matrix, change the first row 1 to 5 and the second row 1 to 3, and now you have a matrix that scales x by 5 and y by 3). Their 2D general scaling matrix is below.&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/U75St.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15261" PostHistoryTypeId="1" PostId="5586" RevisionGUID="09aaac07-573c-47a5-bd41-918837406125" CreationDate="2017-09-09T00:17:01.073" UserId="7272" Text="What does it *mean* to scale in an arbitrary direction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15262" PostHistoryTypeId="3" PostId="5586" RevisionGUID="09aaac07-573c-47a5-bd41-918837406125" CreationDate="2017-09-09T00:17:01.073" UserId="7272" Text="|mathematics|matrix|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15263" PostHistoryTypeId="34" PostId="5539" RevisionGUID="1a760559-f2f5-437a-9e40-ce8a2ec1a05d" CreationDate="2017-09-09T08:28:52.450" UserId="-1" Comment="32" />
  <row Id="15264" PostHistoryTypeId="2" PostId="5587" RevisionGUID="d09e9da7-f3e1-44b9-b5b6-039e7dd97239" CreationDate="2017-09-09T12:42:07.350" UserId="1937" Text="When you scale along the X-axis, the X-coordinate (parallel to the axis) gets stretched, while the Y-coordinate (perpendicular to the axis) remains the same. You can think of scaling along an arbitrary axis as stretching along some diagonal.&#xD;&#xA;&#xD;&#xA;Here's a pic of a square being scaled along the main diagonal (the axis pointing to &lt;1, 1&gt; ) by factors of 2 and 0.5.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can see that the distance along the axis (green line) gets scaled while the perpendicular distance (red line) stays the same.&#xD;&#xA;&#xD;&#xA;Mathematically, this is the same as rotating until your chosen axis lies along the X-axis, scaling by X, then rotating back again. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kUmir.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15265" PostHistoryTypeId="5" PostId="60" RevisionGUID="e07ec9c2-555f-42e4-beeb-f4c70f680f9b" CreationDate="2017-09-09T18:54:14.380" UserId="196" Comment="slightly more correct statements" Text="An architectural *advantage* of compute shaders for image processing is that they skip the [ROP][1] step. It's very likely that writes from pixel shaders go through all the regular blending hardware even if you don't use it. Generally speaking compute shaders go through a different (and often more direct) path to memory, so you may avoid a bottleneck that you would otherwise have. I've heard of fairly sizable performance wins attributed to this.&#xD;&#xA;&#xD;&#xA;An architectural *disadvantage* of compute shaders is that the GPU no longer knows which work items retire to which pixels. If you are using the pixel shading pipeline, the GPU has the opportunity to pack work into a warp/wavefront that write to an area of the render target which is contiguous in memory (which may be [Z-order tiled][2] or something like that for performance reasons). If you are using a compute pipeline, the GPU may no longer kick work in optimal batches, leading to more bandwidth use.&#xD;&#xA;&#xD;&#xA;You may be able to turn that altered warp/wavefront packing into an advantage again, though, if you know that your particular operation has a substructure that you can exploit by packing related work into the same thread group. Like you said, you could in theory give the sampling hardware a break by sampling one value per lane and putting the result in groupshared memory for other lanes to access without sampling. Whether this is a win depends on how expensive your groupshared memory is: if it's cheaper than the lowest-level texture cache, then this may be a win, but there's no guarantee of that. GPUs already deal pretty well with highly local texture fetches (by necessity).&#xD;&#xA;&#xD;&#xA;If you have an intermediate stages in the operation where you want to share results, it may make more sense to use groupshared memory (since you can't fall back on the texture sampling hardware without having actually written out your intermediate result to memory). Unfortunately you also can't depend on having results from any other thread group, so the second stage would have to limit itself to only what is available in the same tile. I think the canonical example here is computing the average luminance of the screen for auto-exposure. I could also imagine combining texture upsampling with some other operation (since upsampling, unlike downsampling and blurs, doesn't depend on any values outside a given tile).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Render_output_unit&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Z-order_curve" ContentLicense="CC BY-SA 3.0" />
  <row Id="15267" PostHistoryTypeId="2" PostId="5588" RevisionGUID="f0d48f3a-cf3b-4a9d-8e10-e6ac9482816f" CreationDate="2017-09-11T07:31:00.197" UserId="7250" Text="For an art project, I need to make an OpenGL visualization run for at least 4 weeks. Is this possible? I can pretty much choose the rest of the hardware and software." ContentLicense="CC BY-SA 3.0" />
  <row Id="15268" PostHistoryTypeId="1" PostId="5588" RevisionGUID="f0d48f3a-cf3b-4a9d-8e10-e6ac9482816f" CreationDate="2017-09-11T07:31:00.197" UserId="7250" Text="How can an OpenGL visualization run for weeks?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15269" PostHistoryTypeId="3" PostId="5588" RevisionGUID="f0d48f3a-cf3b-4a9d-8e10-e6ac9482816f" CreationDate="2017-09-11T07:31:00.197" UserId="7250" Text="|opengl|performance|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15270" PostHistoryTypeId="2" PostId="5589" RevisionGUID="7cf55394-992c-4460-8f3e-2b4246bc00ac" CreationDate="2017-09-11T07:53:16.377" UserId="2041" Text="Yes, of course. The duration it has to run for doesn't make much difference. Your Android smartphone's main GUI is OpenGL, and phones typically have an uptime longer than four weeks. Air Traffic Control centres might use OpenGL SC (the subset of GL for safety-critical applications) continuously for months or years.&#xD;&#xA;&#xD;&#xA;If you do have free choice of software, OpenGL is probably not the thing you're concerned about. Artists often use Processing for art projects, because it's simple and lets you get to drawing stuff on the screen with minimal 'boilerplate' code. It's very nice for drawing maths-as-art: particle systems, L-systems, strange attractors, &amp;c. For a 3D scene that's supposed to look like the real world, Unity 3D might be a good choice: it's a game engine that handles all the use of OpenGL or DirectX for you, so you can create the scene you want to draw without much programming.&#xD;&#xA;&#xD;&#xA;If you have more recommendation- or opinion-based questions about what might be useful to look at, maybe drop into our chat room and be ready to tell us what kind of art project you're making." ContentLicense="CC BY-SA 3.0" />
  <row Id="15271" PostHistoryTypeId="2" PostId="5590" RevisionGUID="18d3f9d1-3488-4f30-811b-51c65bdd7c9c" CreationDate="2017-09-11T09:15:59.833" UserId="137" Text="Opengl doesn't care how long it has been running. &#xD;&#xA;&#xD;&#xA;However there are a few other challenges with long running applications in general:&#xD;&#xA;&#xD;&#xA;1. memory leaks, both normal ones and opengl resources. &#xD;&#xA;&#xD;&#xA;2. lack of precision after incrementing a float to a big number. After 4 weeks your millisecond counter will be at 2.4 billion which is well beyond the point where integers cannot be expressed exactly in a single precision floating point number. Make sure that those numbers are wrapped down to a smaller value explicitly." ContentLicense="CC BY-SA 3.0" />
  <row Id="15275" PostHistoryTypeId="2" PostId="5592" RevisionGUID="2c5d7b61-3e24-4246-aa4d-314e4fb8e307" CreationDate="2017-09-11T12:12:41.450" UserId="4546" Text="There is no single method of layering materials. Some implementations, as you have observed, simply interpolate shader input parameters. This helps especially in contexts where code divergence comes with performance penalties (GPUs for example), since all material layers use the same code path and only have different data. Other blend between the output of the individual shader layers.&#xD;&#xA;&#xD;&#xA;More complex approaches take the interface between material layers into account, as well as layer thickness. A recent publication describing such a method is [&quot;A Comprehensive Framework for Rendering Layered Materials&quot;][1] by Jakob et al.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.cornell.edu/projects/layered-sg14/ &quot;A Comprehensive Framework for Rendering Layered Materials&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15280" PostHistoryTypeId="2" PostId="5594" RevisionGUID="715b1970-99cd-4efe-8fe8-ac007ba5c699" CreationDate="2017-09-11T14:40:32.310" UserId="7282" Text="I'm doing linear tweening of a cyllinder to a cone of equal radius and height in OpenGL. I know parametric equations of both of them, so I derived vertex normals accordingly. Now, I know, that proper interpolation of normals here should be quadratic, but, for some reason, linear looks better. &#xD;&#xA;&#xD;&#xA;Let's call cyllinder $C(u,v) := (r\cos(u),\ v,\ r\sin(u))$&#xD;&#xA;&#xD;&#xA;and the cone $K(u,v) := (\frac{r\cos(u)(h-v)}{h},\ v,\ \frac{r\sin(u)(h-v)}{h})$ where $u \in [0, 2\pi]$ and $v \in [0,h]$. $r, h$ are radius and height, respectively. &#xD;&#xA;&#xD;&#xA;At the moment $t \in [0,1]$, body has equation $T(u,v) := (1-t)C(u,v)+tK(u,v)$.&#xD;&#xA;&#xD;&#xA;Given that the normals are computed using partial derivative cross product formula, we get that normal to $T$ at $(u,v)$ is&#xD;&#xA;&#xD;&#xA;$$(1-t)^2(C'_u\times C'_v)+t^2(K'_u \times K'_v)+t(1-t)M(u,v),$$ where $M(u,v) := C'_u \times K'_v+K'_u \times C'_v$.&#xD;&#xA;&#xD;&#xA;So, apart from $M$, vertex normals to $T$ can be expressed as a quadratic inerpolation of corresponding normals for $C$ and $K$.&#xD;&#xA;&#xD;&#xA;Linear interpolation of normals does not work perfectly, but performs way better in general, because whenever I try and implement the correct interpolation formula, somewhere halfway through, all those polygons in the mesh become very apparent.&#xD;&#xA;&#xD;&#xA;For the reference GL_NORMALIZE is on, but I store parametrically generated normals (so I can apply my formula for intermediary bodies).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15281" PostHistoryTypeId="1" PostId="5594" RevisionGUID="715b1970-99cd-4efe-8fe8-ac007ba5c699" CreationDate="2017-09-11T14:40:32.310" UserId="7282" Text="Interpolating normals during animation" ContentLicense="CC BY-SA 3.0" />
  <row Id="15282" PostHistoryTypeId="3" PostId="5594" RevisionGUID="715b1970-99cd-4efe-8fe8-ac007ba5c699" CreationDate="2017-09-11T14:40:32.310" UserId="7282" Text="|interpolation|shading|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15283" PostHistoryTypeId="2" PostId="5595" RevisionGUID="164cf8e5-fa15-4b1a-99b9-2c92dc1ea0ca" CreationDate="2017-09-11T16:09:09.940" UserId="7282" Text="Say my animation scenario contains one mesh interpolating into another (possibly approximating over other meshes), using Bezier curves. &#xD;&#xA;&#xD;&#xA;I know that for smooth surfaces, where normals can be expressed via cross product of partial derivatives, linear interpolation of vertices would induce quadratic interpolation of normals, involving some expressions with several cross product, not tied to the normals.&#xD;&#xA;&#xD;&#xA;Is it acceptable in practice to do the same interpolation for corresponding vertex normals (linear-linear, quadratic-quadratic and so on)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15284" PostHistoryTypeId="1" PostId="5595" RevisionGUID="164cf8e5-fa15-4b1a-99b9-2c92dc1ea0ca" CreationDate="2017-09-11T16:09:09.940" UserId="7282" Text="General interpolation practices" ContentLicense="CC BY-SA 3.0" />
  <row Id="15285" PostHistoryTypeId="3" PostId="5595" RevisionGUID="164cf8e5-fa15-4b1a-99b9-2c92dc1ea0ca" CreationDate="2017-09-11T16:09:09.940" UserId="7282" Text="|interpolation|shading|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15286" PostHistoryTypeId="2" PostId="5596" RevisionGUID="54a460c8-5105-4d21-a6b5-3ed003aeda6c" CreationDate="2017-09-11T20:05:51.987" UserId="7285" Text="I have just two local axis to rotate a 3D object: X (horizontal) and Y (vertical). How to make from this 2 local axises for example a global Y rotation or a Local Z rotation? What math magic do the trick? " ContentLicense="CC BY-SA 3.0" />
  <row Id="15287" PostHistoryTypeId="1" PostId="5596" RevisionGUID="54a460c8-5105-4d21-a6b5-3ed003aeda6c" CreationDate="2017-09-11T20:05:51.987" UserId="7285" Text="How to rotate an object around any axis if i have just local x and y?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15288" PostHistoryTypeId="3" PostId="5596" RevisionGUID="54a460c8-5105-4d21-a6b5-3ed003aeda6c" CreationDate="2017-09-11T20:05:51.987" UserId="7285" Text="|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15291" PostHistoryTypeId="50" PostId="5491" RevisionGUID="5d71de47-9a62-4122-8779-1020ecaee1a9" CreationDate="2017-09-11T21:11:12.360" UserId="-1" />
  <row Id="15292" PostHistoryTypeId="2" PostId="5598" RevisionGUID="b5017aff-7dea-42dc-b532-e7cb4c9aba6c" CreationDate="2017-09-11T21:24:46.673" UserId="56" Text="If you know how to make a rotation matrix from X,Y,Z basis vectors (just make them the rows or columns, depending on whether you are using a row or column major matrix), you can do that, using the cross product of X and Y to get the Z vector.&#xD;&#xA;&#xD;&#xA;The order of X and Y in the cross product depend on whether you are using a left or right handed coordinate system, but if you are unsure about this, you can check if doing Z=cross(X,Y) looks right and if not, switch to Z=cross(Y,X).&#xD;&#xA;&#xD;&#xA;So, it'll be something like this:&#xD;&#xA;&#xD;&#xA;    // May be Y,X instead, depending on your handedness&#xD;&#xA;    Z = Cross(X,Y);&#xD;&#xA;&#xD;&#xA;    // May need to be transposed based on you using row or column major matrices&#xD;&#xA;    RotationMatrix = matrix3x3(X,Y,Z); &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15293" PostHistoryTypeId="5" PostId="5598" RevisionGUID="efa4aa46-97d7-4fee-94d5-6a347b403013" CreationDate="2017-09-11T22:48:32.167" UserId="56" Comment="added 5 characters in body" Text="If you know how to make a rotation matrix from X,Y,Z basis vectors (just make them the rows or columns, depending on whether you are using a row or column major matrix), you can do that, using the cross product of X and Y to get the Z vector.&#xD;&#xA;&#xD;&#xA;The order of X and Y in the cross product depend on whether you are using a left or right handed coordinate system, but if you are unsure about this, you can check if doing Z=cross(X,Y) looks right and if not, switch to Z=cross(Y,X).&#xD;&#xA;&#xD;&#xA;So, it'll be something like this:&#xD;&#xA;&#xD;&#xA;    // May be Y,X instead, depending on your handedness&#xD;&#xA;    Z = Cross(X,Y);&#xD;&#xA;&#xD;&#xA;    // May need to be transposed based on you using row or column major matrices&#xD;&#xA;    RotationMatrix = MatrixFromRows(X,Y,Z); &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15294" PostHistoryTypeId="5" PostId="5577" RevisionGUID="a357f9c2-38fa-45bd-9a06-73ede283a1c6" CreationDate="2017-09-12T07:38:11.637" UserId="209" Comment="changed subscripts to make a little more sense" Text="&gt; (Is gouraud shading even supposed to be perspective correct?)&#xD;&#xA;&#xD;&#xA;Originally, it wouldn't have been perspective correct, but on (hardware) systems these days it will be. FWIW Dreamcast had perspective correct Gouraud shading because, once you are doing perspective correct texturing, it is relatively little additional cost to do Gouraud &quot;correctly&quot;.&#xD;&#xA;&#xD;&#xA;&gt;I have flat shading working and I have perspective correct texture mapping working. Is the way your raster Gouraud shading much different from the perspective correct texture mapping?&#xD;&#xA;&#xD;&#xA;I'm assuming that you've started with homogeneous 'world space' vertices, i.e. something like, &#xD;&#xA;&#xD;&#xA;$[x,y,z, 1, u,v, R,G,B]$,&#xD;&#xA;&#xD;&#xA;applied a projection matrix to get&#xD;&#xA;&#xD;&#xA; $[X_p, Y_p, Z_p, 1, u, v, R, G, B, w]$,&#xD;&#xA;&#xD;&#xA;and then, after clipping, divided through by w to obtain screen coordinates&#xD;&#xA;&#xD;&#xA;$[X_p/w, Y_p/w, Z_p/w, 1/w, u/w, v/w, R/w,... ]$.  &#xD;&#xA;&#xD;&#xA;For convenience, let's rename $u/w$ and $v/w$ as $u'$ &amp; $v'$, $1/w$ as $w'$, $R/w$ as $R'$ etc.&#xD;&#xA;&#xD;&#xA;To do perspective correct texturing I _assume_ you are linearly interpolating, per pixel, the $u'$, $v'$, and $w'$ values, computing the reciprocal of the interpolated  $w'$ and multiplying that by $u'$ and $v'$ to obtain the per-pixel U &amp; V coordinates.&#xD;&#xA;&#xD;&#xA;To do perspective correct Gouraud, simply use the same approach with the interpolated $R'$ , $G'$ and $B'$ values. The most expensive part is typically the division (i.e. reciprocal) but that can be shared with the texturing.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15295" PostHistoryTypeId="2" PostId="5599" RevisionGUID="7c060364-23bc-429d-b7e3-667fbeb1e501" CreationDate="2017-09-12T12:15:23.683" UserId="1937" Text="I've been trying to build a simple DirectX renderer from the ground up (was an OpenGL guy before but i figure it's good to know different APIs). I've been following the guide at rastertek.com to learn how to get the basics up and running.&#xD;&#xA;&#xD;&#xA;I got as far as [this lesson][1], following the guide verbatim except for variable names, and ran into a really weird bug. The renderer class contains 3 XMMatrix instances, world, perspective and orthographic, but trying to initialize them would crash my application - it ran fine once i commented out these lines :&#xD;&#xA;&#xD;&#xA;    m_projMat = XMMatrixPerspectiveFovLH(fov, aspect, nearplane, farplane);&#xD;&#xA;    m_orthoMat = XMMatrixOrthographicLH(width, height, nearplane, farplane);&#xD;&#xA;    m_worldMat = XMMatrixIdentity();&#xD;&#xA;&#xD;&#xA;At first i thought it was the dreaded SIMD alignment issue, but I'm compiling 64-bit so that should be taken care of. After a bit more tinkering i found out the ortho and world matrices were fine, it was just the projection matrix that was causing problems. Assigning to this matrix with the other XMMatrix... functions also works ok. &#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;    m_projMat = XMMatrixPerspectiveFovLH(fov, aspect, nearplane, farplane); &#xD;&#xA;fails, but:&#xD;&#xA;&#xD;&#xA;    m_projMat = XMMatrixPerspectiveLH(fov*aspect*nearplane, fov*nearplane, nearplane, farplane); &#xD;&#xA;works! The right-handed version also fails. Also, the failure only happens in release mode, not in debug. I'm using Visual Studio 2015 community and the SDKs that installed with it.&#xD;&#xA;&#xD;&#xA;Has anyone else encountered this bug, or have any idea what's going on here?&#xD;&#xA;  [1]: http://www.rastertek.com/dx11s2tut03.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="15296" PostHistoryTypeId="1" PostId="5599" RevisionGUID="7c060364-23bc-429d-b7e3-667fbeb1e501" CreationDate="2017-09-12T12:15:23.683" UserId="1937" Text="XMMatrixPerspectiveFovLH is broken?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15297" PostHistoryTypeId="3" PostId="5599" RevisionGUID="7c060364-23bc-429d-b7e3-667fbeb1e501" CreationDate="2017-09-12T12:15:23.683" UserId="1937" Text="|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15298" PostHistoryTypeId="2" PostId="5600" RevisionGUID="97462434-f119-48ab-8729-1f38f67a3f4f" CreationDate="2017-09-12T20:13:54.217" UserId="7291" Text="I'm trying to understand basis vectors and the plane equation and I am confused. From what I saw, if we take a basis vector i, j, k, each variable point to the axe (x, y, z). Are i,j,k scalars or vectors? It seems that any vector can be seen as i*x, j*y, k*z. Does that mean that changing the values of i,j,k can &quot;rotate&quot; the whole plane (the world)? Does this has any connection with the plane equation? Maybe that I am mixing things up." ContentLicense="CC BY-SA 3.0" />
  <row Id="15299" PostHistoryTypeId="1" PostId="5600" RevisionGUID="97462434-f119-48ab-8729-1f38f67a3f4f" CreationDate="2017-09-12T20:13:54.217" UserId="7291" Text="Basis vectors and plane equation" ContentLicense="CC BY-SA 3.0" />
  <row Id="15300" PostHistoryTypeId="3" PostId="5600" RevisionGUID="97462434-f119-48ab-8729-1f38f67a3f4f" CreationDate="2017-09-12T20:13:54.217" UserId="7291" Text="|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15305" PostHistoryTypeId="2" PostId="5602" RevisionGUID="1e10b73a-9c79-46df-ab51-ed0797faef26" CreationDate="2017-09-13T09:41:48.410" UserId="6046" Text="I Recently posted this question on SO but didn't got any response so i thought to post it here since it's somewhat related to Raytracing. &#xD;&#xA;&#xD;&#xA;I am making a real time ray tracer in OpenGL using Compute Shaders for my project and was following this [link][1] as a reference. The link tells to first draw a full screen quad, then store all the individual pixel colors gotten through intersections in a texture and render the texture to the quad.&#xD;&#xA;&#xD;&#xA;However i was thinking can't we use Frame Buffer Objects to display the texture image instead of rendering the quad and save the over head?&#xD;&#xA;&#xD;&#xA;Like I save all the colors using [ImageStore][2] and [GlBindImageTexture][3] in a texture, then attach it to a FBO to display it. And since I won't be using any rendering commands I won't be causing a Feedback loop as in writing and reading the same texture?&#xD;&#xA;&#xD;&#xA;Here is the snippet&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;      void initialization() {&#xD;&#xA;      int tex = create new texture object&#xD;&#xA;      &#xD;&#xA;      setup min/mag NEAR filtering for that texture&#xD;&#xA;      initialize texture as 2D rgba32f FLOAT and some width/height&#xD;&#xA;      &#xD;&#xA;      int vao = create VertexArrayObject of full-screen-quad&#xD;&#xA;      // This quad is used to render our&#xD;&#xA;      // &quot;framebuffer&quot; texture onto the screen.&#xD;&#xA;    &#xD;&#xA;      int computeProgram = create-and-link program with single compute shader object&#xD;&#xA;    &#xD;&#xA;      int quadProgram = create-and-link simple full-screen quad vertex and fragment shader&#xD;&#xA;      // The fragment shader would fetch&#xD;&#xA;      // texels from our &quot;tex&quot; texture.&#xD;&#xA;      &#xD;&#xA;      Setup constant uniforms in quad program, such as &quot;tex&quot; texture unit = 0&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;     The rendering process to produce one frame will be as follows:&#xD;&#xA;    &#xD;&#xA;    Bind the Compute Shader&#xD;&#xA;    Setup camera properties in compute shader uniforms&#xD;&#xA;    Bind level 0 of framebuffer texture to image binding point 0&#xD;&#xA;    Start/dispatch the compute shader to generate a frame in the framebuffer image&#xD;&#xA;    Unbind image binding point&#xD;&#xA;    Bind the written framebuffer texture in OpenGL to texture unit 0&#xD;&#xA;    Bind the full-screen shader program&#xD;&#xA;    Bind the full-screen-quad VAO&#xD;&#xA;    Draw the VAO&#xD;&#xA;    Release all bindings&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/LWJGL/lwjgl3-wiki/wiki/2.6.1.-Ray-tracing-with-OpenGL-Compute-Shaders-(Part-I)&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/imageStore.xhtml&#xD;&#xA;  [3]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindImageTexture.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="15306" PostHistoryTypeId="1" PostId="5602" RevisionGUID="1e10b73a-9c79-46df-ab51-ed0797faef26" CreationDate="2017-09-13T09:41:48.410" UserId="6046" Text="Raytracing in OpenGL using Compute Shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="15307" PostHistoryTypeId="3" PostId="5602" RevisionGUID="1e10b73a-9c79-46df-ab51-ed0797faef26" CreationDate="2017-09-13T09:41:48.410" UserId="6046" Text="|opengl|raytracing|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15312" PostHistoryTypeId="2" PostId="5604" RevisionGUID="dcc7e6d6-801c-4651-a9d6-695b2ca0cbc0" CreationDate="2017-09-13T12:50:23.057" UserId="7298" Text="I'm using VBO to upload vertex array, colors and then texture coordinates! I did implement mouse pick with color coding technique. it's work fine but when I render texture after ReadPixels, it return's wrong color!&#xD;&#xA;I don't know why this happens! here is my render code :&#xD;&#xA;&#xD;&#xA;            GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);&#xD;&#xA;            GL.ShadeModel(ShadingModel.Flat);&#xD;&#xA;            Debug.Assert(_vbo.VertexBufferId != 0);&#xD;&#xA;            Debug.Assert(_vbo.ElementBufferId != 0);&#xD;&#xA;&#xD;&#xA;            // vertex colors&#xD;&#xA;            if (_vbo.ColorBufferId != 0)&#xD;&#xA;            {&#xD;&#xA;                GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.ColorBufferId);&#xD;&#xA;                GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);&#xD;&#xA;                GL.EnableClientState(ArrayCap.ColorArray);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // vertex position&#xD;&#xA;            GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.VertexBufferId);&#xD;&#xA;            GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);&#xD;&#xA;            GL.EnableClientState(ArrayCap.VertexArray);&#xD;&#xA;&#xD;&#xA;            // primitives&#xD;&#xA;            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _vbo.ElementBufferId);&#xD;&#xA;            GL.DrawElements(OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, _vbo.NumIndices * 3, _vbo.Is32BitIndices ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort, IntPtr.Zero);&#xD;&#xA;&#xD;&#xA;            // Read pixel under mouse cursor&#xD;&#xA;            _selectedPolyIndex = uint.MaxValue;&#xD;&#xA;            Byte4 Pixel = new Byte4();&#xD;&#xA;            GL.ReadPixels(mouse_x, height - mouse_y, 1, 1, PixelFormat.Rgba, PixelType.UnsignedByte, ref Pixel);&#xD;&#xA;            _selectedPolyIndex = Pixel.ToUInt();&#xD;&#xA;&#xD;&#xA;            // Restore the state&#xD;&#xA;            GL.PopClientAttrib();&#xD;&#xA;&#xD;&#xA;            GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);&#xD;&#xA;&#xD;&#xA;            // normals&#xD;&#xA;            if (flags.HasFlag(RenderFlags.Shaded))&#xD;&#xA;            {&#xD;&#xA;                if (_vbo.NormalBufferId != 0)&#xD;&#xA;                {&#xD;&#xA;                    GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.NormalBufferId);&#xD;&#xA;                    GL.NormalPointer(NormalPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);&#xD;&#xA;                    GL.EnableClientState(ArrayCap.NormalArray);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // UV coordinates&#xD;&#xA;            if (flags.HasFlag(RenderFlags.Textured))&#xD;&#xA;            {&#xD;&#xA;                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // this line must move out to line 160&#xD;&#xA;                if (_vbo.TexCoordBufferId != 0)&#xD;&#xA;                {&#xD;&#xA;                    GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.TexCoordBufferId);&#xD;&#xA;                    GL.TexCoordPointer(2, TexCoordPointerType.Float, 8, IntPtr.Zero);&#xD;&#xA;                    GL.EnableClientState(ArrayCap.TextureCoordArray);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // vertex position&#xD;&#xA;            GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.VertexBufferId);&#xD;&#xA;            GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);&#xD;&#xA;            GL.EnableClientState(ArrayCap.VertexArray);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // primitives&#xD;&#xA;            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _vbo.ElementBufferId);&#xD;&#xA;            GL.DrawElements(OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, _vbo.NumIndices * 3, _vbo.Is32BitIndices ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort, IntPtr.Zero);&#xD;&#xA;&#xD;&#xA;            // Restore the state&#xD;&#xA;            GL.PopClientAttrib();&#xD;&#xA;&#xD;&#xA;When texture rendering is enabled openGL read's wrong pixel color under mouse cursor (I want vertex color but it read's texture color), even I call readpixels before texture rendering!&#xD;&#xA;&#xD;&#xA;how can fix this problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15313" PostHistoryTypeId="1" PostId="5604" RevisionGUID="dcc7e6d6-801c-4651-a9d6-695b2ca0cbc0" CreationDate="2017-09-13T12:50:23.057" UserId="7298" Text="How to read vertext color before rendering texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15314" PostHistoryTypeId="3" PostId="5604" RevisionGUID="dcc7e6d6-801c-4651-a9d6-695b2ca0cbc0" CreationDate="2017-09-13T12:50:23.057" UserId="7298" Text="|opengl|rendering|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15315" PostHistoryTypeId="33" PostId="2003" RevisionGUID="c8df308e-9b7f-4445-9cef-bf5082d1ef76" CreationDate="2017-09-13T16:56:21.313" UserId="7299" Comment="33" />
  <row Id="15316" PostHistoryTypeId="2" PostId="5605" RevisionGUID="b3139b27-c47a-467e-b20d-d71d17015114" CreationDate="2017-09-13T17:04:05.110" UserId="7299" Text="I'm trying to implement a segmentation model which will divide a 3d mesh model into charts. But I'm having really hard time to find resources in the web. The papers and some other places these approaches discussed either in very brief or with very complicated math. Really need some step by step guide with example for the algorithm. I'm particularly interested on the approach given in this [LSCM][1] paper. &#xD;&#xA;&#xD;&#xA;There is another algorithm discussed in [here][2] and the code for this can be found in this [repo][3]. This also looks very promising.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.jhu.edu/~misha/Fall09/Levy02.pdf&#xD;&#xA;  [2]: http://the-witness.net/news/2010/03/graphics-tech-texture-parameterization/&#xD;&#xA;  [3]: https://github.com/Thekla/thekla_atlas" ContentLicense="CC BY-SA 3.0" />
  <row Id="15317" PostHistoryTypeId="1" PostId="5605" RevisionGUID="b3139b27-c47a-467e-b20d-d71d17015114" CreationDate="2017-09-13T17:04:05.110" UserId="7299" Text="3D mesh model segmentation to chart" ContentLicense="CC BY-SA 3.0" />
  <row Id="15318" PostHistoryTypeId="3" PostId="5605" RevisionGUID="b3139b27-c47a-467e-b20d-d71d17015114" CreationDate="2017-09-13T17:04:05.110" UserId="7299" Text="|texture|algorithm|computational-geometry|mesh|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15319" PostHistoryTypeId="2" PostId="5606" RevisionGUID="3b919946-9d2d-4b9c-b014-847a353efed2" CreationDate="2017-09-13T17:17:43.010" UserId="6025" Text="Does anyone know how to do run an OpenGL animation and then convert it into a mp4 movie?  I've been trying with apitrace and ffmpeg but I get horrible quality output..." ContentLicense="CC BY-SA 3.0" />
  <row Id="15320" PostHistoryTypeId="1" PostId="5606" RevisionGUID="3b919946-9d2d-4b9c-b014-847a353efed2" CreationDate="2017-09-13T17:17:43.010" UserId="6025" Text="OpenGL animation - turn into mp4 movie" ContentLicense="CC BY-SA 3.0" />
  <row Id="15321" PostHistoryTypeId="3" PostId="5606" RevisionGUID="3b919946-9d2d-4b9c-b014-847a353efed2" CreationDate="2017-09-13T17:17:43.010" UserId="6025" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15322" PostHistoryTypeId="2" PostId="5607" RevisionGUID="1d82daf6-fb3b-4d47-8a05-2c3f0a6a800c" CreationDate="2017-09-13T17:56:57.697" UserId="3041" Text="While I have no idea how UnrealEngine handle depth I have thought of a technique which would result in that kind of depth output.&#xD;&#xA;&#xD;&#xA;The idea is to better manage Z-fighting by rendering multiple (stacked) frustums with shorter distance between ner and far planes. Each step in the cascade would represent one of those frustums. Using near/far plane clipping, stencil masking and optional vf-culling you can easily render the cascade front-to-back, or each frustum to each own framebuffer and consolidate afterwards, with only minor hit in performance.&#xD;&#xA;&#xD;&#xA;This should scale better than increasing depth buffer bit depth which has diminishing returns. Besides not all platforms support high bit depth. OpenGL ES require only 16 bits!&#xD;&#xA;&#xD;&#xA;It is just a theory though :-)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15323" PostHistoryTypeId="2" PostId="5608" RevisionGUID="487b7cd6-9e79-4c68-85dd-9d8126484497" CreationDate="2017-09-13T18:55:24.660" UserId="3041" Text="When cylinder and frustum intersect the hole will be a view into the internals of the cylinder. **The hole is where external of the cylinder occlude frustum and internal of the cylinder does not occlude the frustum.**&#xD;&#xA;&#xD;&#xA;Knowing this you should simply do the following to find the surface (or rather volume) made from the hole.&#xD;&#xA;&#xD;&#xA;Render frustum without color and set depth accordingly. Set a stencil bit where the cylinder (external) occludes the frustum, without setting new depth. Clear the previously set bit where the internal of the cylinder occludes the frustum, without setting new depth. &#xD;&#xA;&#xD;&#xA;Alternate between internal and external using CullFace.&#xD;&#xA;&#xD;&#xA;The stencil mask you now have is the surface where the frustum hole is. Render the frustum (in color) masking it with the stencil. Make sure to use LEQUALS depth test to allow the frustum to render on top of itself. Voila. Note that the depth buffer holds the value of the unmasked frustum so If you need to render something within the hole you would have to render the whole scene again and mask it to only render in the hole unless depth test passes against the frustum. Left as student exercise." ContentLicense="CC BY-SA 3.0" />
  <row Id="15324" PostHistoryTypeId="2" PostId="5609" RevisionGUID="bea8a8d3-e31e-4bca-ad4a-48cd89524a8d" CreationDate="2017-09-13T19:09:44.583" UserId="3041" Text="Include a benchmarking phase for of both solutions in your application and then select the winning solution at runtime. This is simple, portable, and future proof. I mean, you do have test for this, right? ;-)&#xD;&#xA;&#xD;&#xA;I know this is a pretty generic answer to &quot;best practice&quot; for high performance but if you think of it there are thousands of possible target configurations and many vendors to consider. If you need that little extra, go pay your vendor for a driver optimized for your application." ContentLicense="CC BY-SA 3.0" />
  <row Id="15325" PostHistoryTypeId="2" PostId="5610" RevisionGUID="ae6f32a4-ba80-47f7-bd50-c7e744891117" CreationDate="2017-09-13T19:23:35.453" UserId="3041" Text="Depending on your renderer you could make the surfaces more &quot;fuzzy&quot; applying a miniscule offset in multisampling depth using a noise like algorithm. This should result in a sort of blending effect for surfaces in close depth proximity. For what I know setting per-sample depth in fragment shader is quite recent in OpenGL and then only as an extension.&#xD;&#xA;&#xD;&#xA;OpenGL has the PolygonOffset but requires knowing in advance you are about to render something coplanar. While not feasible for surfaces within a single model it could work nicely for example when rendering a road overlaid on a piece of land." ContentLicense="CC BY-SA 3.0" />
  <row Id="15326" PostHistoryTypeId="50" PostId="5300" RevisionGUID="13226b85-db3e-41fc-b52c-2633518bcf50" CreationDate="2017-09-13T22:25:05.773" UserId="-1" />
  <row Id="15327" PostHistoryTypeId="2" PostId="5611" RevisionGUID="148434e9-2575-46f8-9238-a5fc0d57724d" CreationDate="2017-09-13T23:28:33.280" UserId="56" Text="I've heard that pre-multiplied alpha gives you order independent transparency but when I sit down and do the math, it doesn't seem to be working.&#xD;&#xA;&#xD;&#xA;Is that untrue, or am I doing something incorrectly?&#xD;&#xA;&#xD;&#xA;The formula I'm using is:&#xD;&#xA;&#xD;&#xA;$out_{rgba} = in_{rgba} + out_{rgba} * (1 - in_a)$&#xD;&#xA;&#xD;&#xA;where $in$ is premultiplied alpha. In other words, taking a &quot;normal&quot; color in RGBA, i multiply RGB by a.  30% opaque white would start out as (1, 1, 1, 0.3) but would become (0.3, 0.3, 0.3, 0.3) as premultiplied alpha.&#xD;&#xA;&#xD;&#xA;After getting the wrong answers when working it out by hand, I wrote the C++ program below and am still getting the wrong results.&#xD;&#xA;&#xD;&#xA;After execution:&#xD;&#xA;&#xD;&#xA;$out1 = (0.738, 0.913, 0.3, 1.0)\\&#xD;&#xA;out2 = (0.738, 0.875, 0.113, 1.0)$&#xD;&#xA;&#xD;&#xA;Can anyone explain why?&#xD;&#xA;&#xD;&#xA;    #include &lt;array&gt;&#xD;&#xA;&#xD;&#xA;    typedef std::array&lt;float, 4&gt; RGBA;&#xD;&#xA;&#xD;&#xA;    void PremultiplyAlpha (RGBA&amp; rgba)&#xD;&#xA;    {&#xD;&#xA;        rgba[0] *= rgba[3];&#xD;&#xA;        rgba[1] *= rgba[3];&#xD;&#xA;        rgba[2] *= rgba[3];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    RGBA BlendPremultipliedAlpha (const RGBA&amp; dest, const RGBA&amp; src)&#xD;&#xA;    {&#xD;&#xA;        RGBA ret;&#xD;&#xA;        ret[0] = src[0] + dest[0] * (1.0f - src[3]);&#xD;&#xA;        ret[1] = src[1] + dest[1] * (1.0f - src[3]);&#xD;&#xA;        ret[2] = src[2] + dest[2] * (1.0f - src[3]);&#xD;&#xA;        ret[3] = src[3] + dest[3] * (1.0f - src[3]);&#xD;&#xA;        return ret;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main(int argc, char **argv)&#xD;&#xA;    {&#xD;&#xA;        RGBA greenGround = { 0.0f, 1.0f, 0.0f, 1.0f };&#xD;&#xA;        PremultiplyAlpha(greenGround);&#xD;&#xA;&#xD;&#xA;        RGBA red25PercentOpaque = { 1.0f, 0.0f, 0.0f, 0.25f };&#xD;&#xA;        PremultiplyAlpha(red25PercentOpaque);&#xD;&#xA;&#xD;&#xA;        RGBA white30PercentOpaque = { 1.0f, 1.0f, 1.0f, 0.3f };&#xD;&#xA;        PremultiplyAlpha(white30PercentOpaque);&#xD;&#xA;&#xD;&#xA;        RGBA yellow50PercentOpaque = { 1.0f, 1.0f, 0.0f, 0.5f };&#xD;&#xA;        PremultiplyAlpha(yellow50PercentOpaque);&#xD;&#xA;&#xD;&#xA;        // one way&#xD;&#xA;        RGBA out1;&#xD;&#xA;        {&#xD;&#xA;            // start with the green ground and blend in 25% opaque red&#xD;&#xA;            out1 = greenGround;&#xD;&#xA;            out1 = BlendPremultipliedAlpha(out1, red25PercentOpaque);&#xD;&#xA;&#xD;&#xA;            // then blend in 50% yellow&#xD;&#xA;            out1 = BlendPremultipliedAlpha(out1, yellow50PercentOpaque);&#xD;&#xA;&#xD;&#xA;            // then blend in 30% opaque white&#xD;&#xA;            out1 = BlendPremultipliedAlpha(out1, white30PercentOpaque);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // other way&#xD;&#xA;        RGBA out2;&#xD;&#xA;        {&#xD;&#xA;            // start with the green ground and blend in 30% opaque white&#xD;&#xA;            out2 = greenGround;&#xD;&#xA;            out2 = BlendPremultipliedAlpha(out2, white30PercentOpaque);&#xD;&#xA;&#xD;&#xA;            // then blend in 25% red&#xD;&#xA;            out2 = BlendPremultipliedAlpha(out2, red25PercentOpaque);&#xD;&#xA;&#xD;&#xA;            // then blend in 50% yellow&#xD;&#xA;            out2 = BlendPremultipliedAlpha(out2, yellow50PercentOpaque);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15328" PostHistoryTypeId="1" PostId="5611" RevisionGUID="148434e9-2575-46f8-9238-a5fc0d57724d" CreationDate="2017-09-13T23:28:33.280" UserId="56" Text="Does premultiplied alpha give order independent transparency?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15329" PostHistoryTypeId="3" PostId="5611" RevisionGUID="148434e9-2575-46f8-9238-a5fc0d57724d" CreationDate="2017-09-13T23:28:33.280" UserId="56" Text="|mathematics|transparency|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15331" PostHistoryTypeId="2" PostId="5612" RevisionGUID="97c498cf-1905-4291-a25d-74aefd6803ff" CreationDate="2017-09-14T04:14:54.510" UserId="56" Text="Premultiplied alpha itself does not give you order independent transparency, no.&#xD;&#xA;&#xD;&#xA;This page talks about how it can be used as part of an order independent transparency solution however: http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html&#xD;&#xA;&#xD;&#xA;Other benefits of premultiplied alpha include:&#xD;&#xA;&#xD;&#xA; * better mipmaps for textures that contain alpha: https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre&#xD;&#xA; &#xD;&#xA; *  Being able to do both transparency and additive blending within a single texture without needing to change render states or issue multiple draw calls: http://amindforeverprogramming.blogspot.com/2013/07/why-alpha-premultiplied-colour-blending.html&#xD;&#xA;&#xD;&#xA; * Being able to represent more realistic lighting situations, such as the fact that being non opaque doesn't mean transparency: http://distantsoulsdev.blogspot.com.ar/2013/02/premultiplied-alpha-online-interactive.html&#xD;&#xA;&#xD;&#xA; * Being able to more naturally / correctly / effortlessly composite images that have alpha channels.&#xD;&#xA;&#xD;&#xA; * Being able to get better results from image processing (blurs / convolution). No black halo: https://stackoverflow.com/questions/4854839/how-to-use-pre-multiplied-during-image-convolution-to-solve-alpha-bleed-problem&#xD;&#xA;&#xD;&#xA; * Premultiplied alpha also allows transparent objects to be drawn front to back instead of back to front, possibly saving pixel writes." ContentLicense="CC BY-SA 3.0" />
  <row Id="15332" PostHistoryTypeId="5" PostId="5612" RevisionGUID="4ce1d82b-ed30-4042-8801-2141c1c84beb" CreationDate="2017-09-14T04:30:18.637" UserId="56" Comment="added 7 characters in body" Text="Premultiplied alpha itself does not give you order independent transparency, no.&#xD;&#xA;&#xD;&#xA;This page talks about how it can be used as part of an order independent transparency solution however: http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html&#xD;&#xA;&#xD;&#xA;Other benefits of premultiplied alpha include:&#xD;&#xA;&#xD;&#xA; * better mipmaps for textures that contain alpha: https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre&#xD;&#xA; &#xD;&#xA; *  Being able to do both transparency and additive blending within a single texture without needing to change render states or issue multiple draw calls: http://amindforeverprogramming.blogspot.com/2013/07/why-alpha-premultiplied-colour-blending.html&#xD;&#xA;&#xD;&#xA; * Being able to represent more realistic lighting situations, such as the fact that being non opaque doesn't always mean transparency: http://distantsoulsdev.blogspot.com.ar/2013/02/premultiplied-alpha-online-interactive.html&#xD;&#xA;&#xD;&#xA; * Being able to more naturally / correctly / effortlessly composite images that have alpha channels.&#xD;&#xA;&#xD;&#xA; * Being able to get better results from image processing (blurs / convolution). No black halo: https://stackoverflow.com/questions/4854839/how-to-use-pre-multiplied-during-image-convolution-to-solve-alpha-bleed-problem&#xD;&#xA;&#xD;&#xA; * Premultiplied alpha also allows transparent objects to be drawn front to back instead of back to front, possibly saving pixel writes." ContentLicense="CC BY-SA 3.0" />
  <row Id="15333" PostHistoryTypeId="5" PostId="5604" RevisionGUID="7dec98a6-a30b-4fd1-b2a7-58110e847407" CreationDate="2017-09-14T07:08:00.400" UserId="67" Comment="Grammar fixes" Text="I'm using VBO to upload vertex array, colors and then texture coordinates! I did implement mouse pick with color coding technique. It works fine but when I render texture after ReadPixels, it returns wrong color!&#xD;&#xA;I don't know why this happens! Here is my render code:&#xD;&#xA;&#xD;&#xA;            GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);&#xD;&#xA;            GL.ShadeModel(ShadingModel.Flat);&#xD;&#xA;            Debug.Assert(_vbo.VertexBufferId != 0);&#xD;&#xA;            Debug.Assert(_vbo.ElementBufferId != 0);&#xD;&#xA;&#xD;&#xA;            // vertex colors&#xD;&#xA;            if (_vbo.ColorBufferId != 0)&#xD;&#xA;            {&#xD;&#xA;                GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.ColorBufferId);&#xD;&#xA;                GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);&#xD;&#xA;                GL.EnableClientState(ArrayCap.ColorArray);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // vertex position&#xD;&#xA;            GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.VertexBufferId);&#xD;&#xA;            GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);&#xD;&#xA;            GL.EnableClientState(ArrayCap.VertexArray);&#xD;&#xA;&#xD;&#xA;            // primitives&#xD;&#xA;            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _vbo.ElementBufferId);&#xD;&#xA;            GL.DrawElements(OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, _vbo.NumIndices * 3, _vbo.Is32BitIndices ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort, IntPtr.Zero);&#xD;&#xA;&#xD;&#xA;            // Read pixel under mouse cursor&#xD;&#xA;            _selectedPolyIndex = uint.MaxValue;&#xD;&#xA;            Byte4 Pixel = new Byte4();&#xD;&#xA;            GL.ReadPixels(mouse_x, height - mouse_y, 1, 1, PixelFormat.Rgba, PixelType.UnsignedByte, ref Pixel);&#xD;&#xA;            _selectedPolyIndex = Pixel.ToUInt();&#xD;&#xA;&#xD;&#xA;            // Restore the state&#xD;&#xA;            GL.PopClientAttrib();&#xD;&#xA;&#xD;&#xA;            GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);&#xD;&#xA;&#xD;&#xA;            // normals&#xD;&#xA;            if (flags.HasFlag(RenderFlags.Shaded))&#xD;&#xA;            {&#xD;&#xA;                if (_vbo.NormalBufferId != 0)&#xD;&#xA;                {&#xD;&#xA;                    GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.NormalBufferId);&#xD;&#xA;                    GL.NormalPointer(NormalPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);&#xD;&#xA;                    GL.EnableClientState(ArrayCap.NormalArray);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // UV coordinates&#xD;&#xA;            if (flags.HasFlag(RenderFlags.Textured))&#xD;&#xA;            {&#xD;&#xA;                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // this line must move out to line 160&#xD;&#xA;                if (_vbo.TexCoordBufferId != 0)&#xD;&#xA;                {&#xD;&#xA;                    GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.TexCoordBufferId);&#xD;&#xA;                    GL.TexCoordPointer(2, TexCoordPointerType.Float, 8, IntPtr.Zero);&#xD;&#xA;                    GL.EnableClientState(ArrayCap.TextureCoordArray);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // vertex position&#xD;&#xA;            GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo.VertexBufferId);&#xD;&#xA;            GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, IntPtr.Zero);&#xD;&#xA;            GL.EnableClientState(ArrayCap.VertexArray);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // primitives&#xD;&#xA;            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _vbo.ElementBufferId);&#xD;&#xA;            GL.DrawElements(OpenTK.Graphics.OpenGL.PrimitiveType.Triangles, _vbo.NumIndices * 3, _vbo.Is32BitIndices ? DrawElementsType.UnsignedInt : DrawElementsType.UnsignedShort, IntPtr.Zero);&#xD;&#xA;&#xD;&#xA;            // Restore the state&#xD;&#xA;            GL.PopClientAttrib();&#xD;&#xA;&#xD;&#xA;When texture rendering is enabled OpenGL reads wrong pixel color under mouse cursor (I want vertex color but it reads texture color), even I call readpixels before texture rendering!&#xD;&#xA;&#xD;&#xA;How can I fix this problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15334" PostHistoryTypeId="4" PostId="5604" RevisionGUID="7dec98a6-a30b-4fd1-b2a7-58110e847407" CreationDate="2017-09-14T07:08:00.400" UserId="67" Comment="Grammar fixes" Text="How to read vertex color before rendering texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15335" PostHistoryTypeId="24" PostId="5604" RevisionGUID="7dec98a6-a30b-4fd1-b2a7-58110e847407" CreationDate="2017-09-14T07:08:00.400" Comment="Proposed by 67 approved by 182, 231 edit id of 270" ContentLicense="CC BY-SA 3.0" />
  <row Id="15337" PostHistoryTypeId="2" PostId="5613" RevisionGUID="dfdcc7d8-4ab0-4f3a-9755-f6e2120fa711" CreationDate="2017-09-14T08:06:29.790" UserId="209" Text="Alan, [Jim Blinn's compositing article](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.163.5748) also explains why premultiplied is the correct way to do any filtering of transparent images." ContentLicense="CC BY-SA 3.0" />
  <row Id="15346" PostHistoryTypeId="4" PostId="5605" RevisionGUID="dd472e52-9856-4007-805c-a4a44975248c" CreationDate="2017-09-14T13:37:59.393" UserId="7299" Comment="edited title" Text="Algorithm for 3D mesh model segmentation to chart" ContentLicense="CC BY-SA 3.0" />
  <row Id="15347" PostHistoryTypeId="2" PostId="5615" RevisionGUID="7f32eab9-0c3f-4044-b06d-d48ad0a52fbb" CreationDate="2017-09-14T14:39:43.210" UserId="3331" Text="This is just a visualisation. Type the command vis scenedepthz uv0 to see the actual depth buffer used. UE4 uses a &quot;reversed&quot; depth buffer for the scene." ContentLicense="CC BY-SA 3.0" />
  <row Id="15355" PostHistoryTypeId="2" PostId="5618" RevisionGUID="73865fa5-5faa-4236-883a-e43805480420" CreationDate="2017-09-15T01:49:17.137" UserId="56" Text="If you have a bunch of particles to render, using different shaders and/or render states, that have some level of transparency, the naive solution of sorting all particles by depth can be extremely inefficient since it is likely to turn a few large batch draw calls into a multitude of smaller batch calls which have expensive render state switches between those draw calls.&#xA;&#xA;I know of a few ways to help fake things such as sorting particle batches by their emitter location, or using something like additive blending, which gives the same result regardless of draw order.&#xA;&#xA;I also know there are some techniques out there to attempt order independent transparency, often being an approximation, requiring a (sometimes unbounded) amount of memory, or some combination thereof.&#xA;&#xA;Does anyone know any pragmatic solutions (fast/low extra memory requirements/absolute correctness not required) for dealing with this situation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15356" PostHistoryTypeId="1" PostId="5618" RevisionGUID="73865fa5-5faa-4236-883a-e43805480420" CreationDate="2017-09-15T01:49:17.137" UserId="56" Text="Are there tricks for getting proper sort ordering on particle systems?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15357" PostHistoryTypeId="3" PostId="5618" RevisionGUID="73865fa5-5faa-4236-883a-e43805480420" CreationDate="2017-09-15T01:49:17.137" UserId="56" Text="|transparency|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15359" PostHistoryTypeId="2" PostId="5619" RevisionGUID="2427ca59-4e49-4d83-8684-ecbf75a23b74" CreationDate="2017-09-15T08:44:17.403" UserId="137" Text="First option should be to make all particles able to go through the same pipeline. Perhaps with an uber shader. That way you can batch them all.&#xD;&#xA;&#xD;&#xA;Positive ieee floating point numbers can be sorted like unsigned integer. And there are O(n) algorithms to sort those for example radix sort. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15367" PostHistoryTypeId="2" PostId="5621" RevisionGUID="a2dcad9e-aba1-467d-a94c-e985ac1f4f7b" CreationDate="2017-09-15T16:15:02.437" UserId="3041" Text="Sort the particles by Z each rendering cycle using an algorithm such as bubble sort which is good when element changes position in small steps. If the perspective does not change much the errors would be few enough over time to be unnoticable. The technique is easy to configure between quality and performance dependning on the target platform by adjusting how much sorting is performed each cycle." ContentLicense="CC BY-SA 3.0" />
  <row Id="15368" PostHistoryTypeId="2" PostId="5622" RevisionGUID="adfbaf96-0ef3-4f1f-beb4-669027ee5ffc" CreationDate="2017-09-15T16:31:06.277" UserId="3041" Text="To make an application, OpenGL or not, run for extended time safety-critical applications are mostly built to restart on error, be it a driver bug, your application is broken, or hardware failure. If function during the downtime is required you need redundnacy. In your case maybe start multiple sessions of the same program, or even having dual computers running the same program outputing to the same display.&#xD;&#xA;&#xD;&#xA;OpenGL is no different from other applications, BUT vendors optimize and test for certain kinds of customers. Your scenario is not common so be suspicious." ContentLicense="CC BY-SA 3.0" />
  <row Id="15373" PostHistoryTypeId="2" PostId="5623" RevisionGUID="9d887dcf-71cd-4ec4-b82d-b4f28c361c50" CreationDate="2017-09-16T08:01:01.007" UserId="7318" Text="That is not an easy question to answer. First of all you will have to understand the MP4 format. And secondly you will have to keep track of every frame being displayed by OpenGL. So my suggestion to maximize performance is to keep all of the frame data after every frame in a file on the hard drive and after the animation read all of the files and write to an MP4 file." ContentLicense="CC BY-SA 3.0" />
  <row Id="15375" PostHistoryTypeId="2" PostId="5625" RevisionGUID="0bcc749f-000d-404c-be77-57903ea1fc4a" CreationDate="2017-09-16T13:20:47.860" UserId="5256" Text="In my CS class in high school I'm doing a presentation on Computer Graphics and I wanted to talk about Ray Tracing. I was wondering what would be the easiest way to do this without confusing my audience?&#xD;&#xA;&#xD;&#xA;What are some of your personal favorite analogies and explanations that have worked effectively to people who have never touched the field?&#xD;&#xA;&#xD;&#xA;Please don't mistake this as a 'do my homework' type question. I'm just curious to see what has worked and what hasn't. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15376" PostHistoryTypeId="1" PostId="5625" RevisionGUID="0bcc749f-000d-404c-be77-57903ea1fc4a" CreationDate="2017-09-16T13:20:47.860" UserId="5256" Text="An Effective way to explain Ray Tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15377" PostHistoryTypeId="3" PostId="5625" RevisionGUID="0bcc749f-000d-404c-be77-57903ea1fc4a" CreationDate="2017-09-16T13:20:47.860" UserId="5256" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15378" PostHistoryTypeId="2" PostId="5626" RevisionGUID="6c9b8c2a-8d16-4b93-9490-22ce0d3acc28" CreationDate="2017-09-16T14:50:51.570" UserDisplayName="user7220" Text="OK. This is the [answer][1]:&#xD;&#xA;&#xD;&#xA;    function getParallelProjection(arr) {&#xD;&#xA;        var i, j, k;&#xD;&#xA;&#xD;&#xA;        var projected = [];&#xD;&#xA;        var projection;&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 6; i++) {&#xD;&#xA;            projection = [];&#xD;&#xA;            if (arr[i].length &lt; 6) {&#xD;&#xA;                for (j = 0; j &lt; 4; j++) {&#xD;&#xA;                    projection[j] = getPointParallelProjection(arr[i][j]);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            projected[i] = projection;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return projected.filter(isClockwise);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    function isClockwise(point_array) {&#xD;&#xA;        if (point_array.length &lt; 3) return false;&#xD;&#xA;        var p0 = point_array[0];&#xD;&#xA;        var p1 = point_array[1];&#xD;&#xA;        var p2 = point_array[2];&#xD;&#xA;        return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y) &gt; 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;All the magic that we check how the faces are drawn. After the vector product we check the order in wich projected vertices goes. If it is counterclockwise - so this set of vertices is discarded.&#xD;&#xA;&#xD;&#xA;  [1]: https://ru.stackoverflow.com/a/717999/236980" ContentLicense="CC BY-SA 3.0" />
  <row Id="15379" PostHistoryTypeId="2" PostId="5627" RevisionGUID="e5d9351c-2e4f-4485-9011-ef2aa721bc99" CreationDate="2017-09-16T16:24:07.580" UserId="48" Text="It's not too difficult to set up your app to stream frames directly to ffmpeg. [This blog post by Miles Macklin shows how](http://blog.mmacklin.com/2013/06/11/real-time-video-capture-with-ffmpeg/), and I've used this method in my own apps.&#xD;&#xA;&#xD;&#xA;You spawn ffmpeg as a child process from your app, and at the end of each frame you just read back the GL framebuffer and write its contents to ffmpeg's stdin. The relevant code bits are excerpted here.&#xD;&#xA;&#xD;&#xA;Initializing ffmpeg:&#xD;&#xA;&#xD;&#xA;	// start ffmpeg telling it to expect raw rgba 720p-60hz frames&#xD;&#xA;	// -i - tells it to read frames from stdin&#xD;&#xA;	const char* cmd = &quot;ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s 1280x720 -i - &quot;&#xD;&#xA;					  &quot;-threads 0 -preset fast -y -pix_fmt yuv420p -crf 21 -vf vflip output.mp4&quot;;&#xD;&#xA;	&#xD;&#xA;	// open pipe to ffmpeg's stdin in binary write mode&#xD;&#xA;	FILE* ffmpeg = _popen(cmd, &quot;wb&quot;);&#xD;&#xA;&#xD;&#xA;Writing a frame:&#xD;&#xA;&#xD;&#xA;	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);&#xD;&#xA;	fwrite(buffer, sizeof(int)*width*height, 1, ffmpeg);&#xD;&#xA;&#xD;&#xA;You can adjust the quality by altering the `-crf` option in the command line (lower numbers are better quality). Don't forget to change the resolution (`-s`) and framerate (`-r`) to match what you want, as well.&#xD;&#xA;&#xD;&#xA;Depending on the quality, how fast your PC is, etc, it might not quite work in real-time. It's a good idea to set up your app to use a fixed per-frame timestep when you're in video capture mode, so the resulting animation doesn't depend on how much slowdown there was in the capture process." ContentLicense="CC BY-SA 3.0" />
  <row Id="15380" PostHistoryTypeId="2" PostId="5628" RevisionGUID="beaaabca-db4f-4188-8335-0ebb1ce37b79" CreationDate="2017-09-16T16:32:48.923" UserId="6046" Text="So i searched a lot after this and I think it was my confusion on FrameBuffer Objects.&#xD;&#xA;&#xD;&#xA;I thought you could use FBO's just like a default FrameBuffer and display the texture image attached to it but you can't. It's only used for offscreen rendering. So while you can use rendering commands to draw something to a &quot;texture image&quot; attached to it, you can't &quot;display the image&quot; by making it default framebuffer or something like that." ContentLicense="CC BY-SA 3.0" />
  <row Id="15383" PostHistoryTypeId="2" PostId="5629" RevisionGUID="f31daf88-352a-4f33-8f1c-ad04258c444a" CreationDate="2017-09-17T09:12:04.343" UserId="1937" Text="The overhead on this is pretty miniscule anyway. Modern GPU raster and texture rates are on the order of tens of gigapixels per second. Compared to the cost of running a ray tracer, it's a rounding error.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15384" PostHistoryTypeId="12" PostId="5629" RevisionGUID="f23df301-f97e-4d89-b5ce-abd7557fc47e" CreationDate="2017-09-17T09:12:09.553" UserId="1937" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:1937,&quot;DisplayName&quot;:&quot;russ&quot;}]}" />
  <row Id="15385" PostHistoryTypeId="13" PostId="5629" RevisionGUID="ca35cf1c-7f29-47d9-8939-4d5711b5d70d" CreationDate="2017-09-17T09:13:20.833" UserId="1937" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:1937,&quot;DisplayName&quot;:&quot;russ&quot;}]}" />
  <row Id="15386" PostHistoryTypeId="2" PostId="5630" RevisionGUID="c41047ab-103d-4dac-bdfa-13b205214e88" CreationDate="2017-09-17T09:46:18.060" UserId="2041" Text="For this kind of functionality, you shouldn't try to use the same framebuffer for the vertex colours and for the final image. Don't forget that GL is *asynchronous*, so alternating CPU reads and GPU writes to the same framebuffer seriously limit your achievable performance and make it much harder for you to get the concurrency right. (The [OpenGL wiki](https://www.khronos.org/opengl/wiki/Synchronization) has more about synchronization.)&#xD;&#xA;&#xD;&#xA;Instead, you should create an FBO that you only use for your vertex colours render. Draw the vertex colours into that and use it for mouse picking. Only use the 'real' framebuffer (the one that gets drawn) for the final image." ContentLicense="CC BY-SA 3.0" />
  <row Id="15392" PostHistoryTypeId="2" PostId="5632" RevisionGUID="72f963ef-8503-4542-81d8-9869879eab42" CreationDate="2017-09-19T08:14:25.393" UserId="7335" Text="Thanks! A very simple but great way to estimate mean curvatures@NathanReed answer.&#xD;&#xA;For my case, I also need an estimate of triangular mesh curvature, and I support this is what i was looking for.&#xD;&#xA;However, could you please show me (or any recommended literature) how the equation (n1 - n0).(p1 - p0)/(norm(p1-p0))^2 is derived?&#xD;&#xA;&#xD;&#xA;////////&#xD;&#xA;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&#xD;&#xA;  &lt;mfrac&gt;&#xD;&#xA;    &lt;mrow&gt;&#xD;&#xA;      &lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&#xD;&#xA;      &lt;msub&gt;&#xD;&#xA;        &lt;mi&gt;n&lt;/mi&gt;&#xD;&#xA;        &lt;mn&gt;1&lt;/mn&gt;&#xD;&#xA;      &lt;/msub&gt;&#xD;&#xA;      &lt;mo&gt;&amp;#x2212;&lt;!-- − --&gt;&lt;/mo&gt;&#xD;&#xA;      &lt;msub&gt;&#xD;&#xA;        &lt;mi&gt;n&lt;/mi&gt;&#xD;&#xA;        &lt;mn&gt;0&lt;/mn&gt;&#xD;&#xA;      &lt;/msub&gt;&#xD;&#xA;      &lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&#xD;&#xA;      &lt;mo&gt;&amp;#x22C5;&lt;!-- ⋅ --&gt;&lt;/mo&gt;&#xD;&#xA;      &lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&#xD;&#xA;      &lt;msub&gt;&#xD;&#xA;        &lt;mi&gt;p&lt;/mi&gt;&#xD;&#xA;        &lt;mn&gt;1&lt;/mn&gt;&#xD;&#xA;      &lt;/msub&gt;&#xD;&#xA;      &lt;mo&gt;&amp;#x2212;&lt;!-- − --&gt;&lt;/mo&gt;&#xD;&#xA;      &lt;msub&gt;&#xD;&#xA;        &lt;mi&gt;p&lt;/mi&gt;&#xD;&#xA;        &lt;mn&gt;0&lt;/mn&gt;&#xD;&#xA;      &lt;/msub&gt;&#xD;&#xA;      &lt;mo stretchy=&quot;false&quot;&gt;) /&lt;/mo&gt;&#xD;&#xA;    &lt;/mrow&gt;&#xD;&#xA;    &lt;mrow&gt;&#xD;&#xA;      &lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&#xD;&#xA;      &lt;msub&gt;&#xD;&#xA;        &lt;mi&gt;p&lt;/mi&gt;&#xD;&#xA;        &lt;mn&gt;1&lt;/mn&gt;&#xD;&#xA;      &lt;/msub&gt;&#xD;&#xA;      &lt;mo&gt;&amp;#x2212;&lt;!-- − --&gt;&lt;/mo&gt;&#xD;&#xA;      &lt;msub&gt;&#xD;&#xA;        &lt;mi&gt;p&lt;/mi&gt;&#xD;&#xA;        &lt;mn&gt;0&lt;/mn&gt;&#xD;&#xA;      &lt;/msub&gt;&#xD;&#xA;      &lt;msup&gt;&#xD;&#xA;        &lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&#xD;&#xA;        &lt;mn&gt;^2&lt;/mn&gt;&#xD;&#xA;      &lt;/msup&gt;&#xD;&#xA;    &lt;/mrow&gt;&#xD;&#xA;  &lt;/mfrac&gt;&#xD;&#xA;&lt;/math&gt;&#xD;&#xA;///&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15393" PostHistoryTypeId="1" PostId="5632" RevisionGUID="72f963ef-8503-4542-81d8-9869879eab42" CreationDate="2017-09-19T08:14:25.393" UserId="7335" Text="How to derive the formula@NathanReed answer" ContentLicense="CC BY-SA 3.0" />
  <row Id="15394" PostHistoryTypeId="3" PostId="5632" RevisionGUID="72f963ef-8503-4542-81d8-9869879eab42" CreationDate="2017-09-19T08:14:25.393" UserId="7335" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15395" PostHistoryTypeId="5" PostId="5632" RevisionGUID="63a412a2-8b4b-4f78-a18f-15d3530dd22c" CreationDate="2017-09-19T08:37:04.470" UserId="182" Comment="Mathjax'ed the equation." Text="Thanks! A very simple but great way to estimate mean curvatures@NathanReed answer.&#xD;&#xA;For my case, I also need an estimate of triangular mesh curvature, and I support this is what i was looking for.&#xD;&#xA;However, could you please show me (or any recommended literature) how is the following equation derived?&#xD;&#xA;&#xD;&#xA;$$\frac{(n_1 - n_0).(p_1 - p_0)}{||p_1 - p_0||^2}$$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15396" PostHistoryTypeId="2" PostId="5633" RevisionGUID="120674ab-eb13-4fb1-a335-f8c3a4aed101" CreationDate="2017-09-19T10:06:04.793" UserId="7337" Text="For an nVidia only solution you can use floating point atomic add intrinsics (like NvInterlockedAddFp32) [https://developer.nvidia.com/unlocking-gpu-intrinsics-hlsl][1]&#xD;&#xA;&#xD;&#xA;I tried this on 80.000 vertex mesh and it's quite fast (something like 1 or 2 ms on a GTX980M, if I remember correctly)&#xD;&#xA;&#xD;&#xA;Just beware of compiling your shaders in release for the intrinsics to work (due to nvidia bug/limitation)&#xD;&#xA;&#xD;&#xA;Also beware of vertex splits (due to UV discontinuities for example), you'll have to handle them or else you'll have unwanted hard edges at UV seams.&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/unlocking-gpu-intrinsics-hlsl" ContentLicense="CC BY-SA 3.0" />
  <row Id="15397" PostHistoryTypeId="2" PostId="5634" RevisionGUID="4e5367ce-19cb-42af-a0cf-ab3d374cdf21" CreationDate="2017-09-19T10:59:45.120" UserId="7338" Text="I think the solution is looking for the projective transform that correctly transforms the four points.&#xD;&#xA;&#xD;&#xA;i.e. &#xD;&#xA;&#xD;&#xA;y' = P * x'&#xD;&#xA;&#xD;&#xA;where x' = [x_0, x_1, 1]&#xD;&#xA;&#xD;&#xA;and y = [y'_0 / y'_2, y'_1 / y'_2]&#xD;&#xA;&#xD;&#xA;P is a 3x3 matrix with 9 entries. Due to the final normalization it is unique up to scaling, leaving 8 degrees of freedom, which are uniquely determined by the 8 equations given by the correspondence (2 per point pair).&#xD;&#xA;&#xD;&#xA;Now you can use algebra to do this, or just use OpenCV's getPerspectiveTransform :).&#xD;&#xA;&#xD;&#xA;Also check out [homnogenous coordinates][1] on wikipedia to get familiar with the concept.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Homogeneous_coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="15399" PostHistoryTypeId="5" PostId="5537" RevisionGUID="e6b2ea41-6853-477b-ab12-690eac967cbb" CreationDate="2017-09-19T21:28:12.283" UserId="2654" Comment="deleted 2 characters in body" Text="&gt; UBOs can be updated at any time with vkCmdUpdateBuffer &#xD;&#xA;&#xD;&#xA;From the specification: &quot;vkCmdUpdateBuffer is only allowed outside of a render pass.&quot; So &quot;at any time&quot; is not the case.&#xD;&#xA;&#xD;&#xA;Even if it were allowed inside of a render pass, it's still a transfer operation. Which means you need to synchronize the memory transfer with the commands that use it. Which slows down performance.&#xD;&#xA;&#xD;&#xA;For the general Push Constant vs. Uniform thing, use your judgment. By &quot;judgment&quot;, I mean just look at how they work. Push Constants allow you to change their data at any time without doing heavy-weight processes like memory operations, synchronization, or altering the descriptor state. Clearly, they are for frequently changing data. How frequently is &quot;frequently&quot;? Well, that's a judgment call.&#xD;&#xA;&#xD;&#xA;Failing that, profile the performance difference." ContentLicense="CC BY-SA 3.0" />
  <row Id="15400" PostHistoryTypeId="5" PostId="3742" RevisionGUID="a2e522ae-a666-495c-bbf7-1caf90748422" CreationDate="2017-09-20T02:13:33.517" UserId="3003" Comment="Removed spoilers from things that aren't spoilers, and removed &quot;extra tags&quot;" Text="tl;dr: Math problem in projective geometry: **How does one find some 4x4 camera matrix that gives a projection as illustrated below, such that points A,B,C,D are somewhere on the edges of the unit box (e.g. OpenGL normalized device coordinates), and the corners of the unit box fall somewhere reasonable along the rays EA, EB, EC, ED?**&#xD;&#xA;&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;elaboration:&#xD;&#xA;&#xD;&#xA;Given a quadrilateral ABCD within the the viewport, I think there exists a unique(?) transformation that maps it back to a rectangle. As seen in the image below: the quadrilateral ABCD in the viewport acts as a physical 'window', and if we map it back to a rectangle it will appear distorted.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/k5XLm.png&#xD;&#xA;&#xD;&#xA;(the box on the right represents NDC, which I talk about later)&#xD;&#xA;&#xD;&#xA;The goal is to quickly obtain the image on the right. We could raytrace every point to obtain the image (which I've done), but I would prefer to use OpenGL or other projective techniques because I wanted to take advantage of things like blending, primitives, etc.&#xD;&#xA;&#xD;&#xA;first attempt:&#xD;&#xA;&#xD;&#xA;&gt; I believe I can solve the problem of finding the 3x4 [camera matrix](https://en.wikipedia.org/wiki/Camera_matrix) that makes the 3+1-dimensional [homogeneous coordinate](https://en.wikipedia.org/wiki/Homogeneous_coordinates) in 3-space (on the left) and projects it down to the 2+1 dimensional homogeneous coordinates in 2-space (on the right). One can solve this using the [direct linear transformation](https://en.wikipedia.org/wiki/Direct_linear_transformation) to get a system of equations `Ba=0` for the unknown entries `a` of the camera matrix, and solving the system using [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) (SVD). I would take the vectors EA, EB, EC, ED (where E is your physical eye or the camera in world-space) as points in the pre-image, and (0,0), (1,0), (1,1), (0,1) or something as the points in the post-image, and each pair of points would give a few linear equations to plug into the SVD. The resulting matrix would map EA-&gt;(0,0) etc. (assuming there are enough degrees of freedom i.e. if the solution is unique, which I'm not sure about, see note[a].)&#xD;&#xA;&#xD;&#xA;But to my chagrin this is not how OpenGL works. OpenGL does not directly project 3d to 2d with a 3x4 matrix. OpenGL requires &quot;normalized device coordinates&quot; (NDC), which are three-dimensional points. After projecting into NDC, everything in the 'unit' box from (-1,-1,-1,1) to (1,1,1,1) is drawn; everything outside is clipped (since we're dealing with homogenerous coordinates: any point (x,y,z,w) will appear only on-screen only if the first three coordinates of (x/w,y/w,z/w,1) are within the unit box from -1 to 1).&#xD;&#xA;&#xD;&#xA;So the question becomes: does there exist some reasonable transformation that maps some weird-looking cuboid in homogeneous coordinates (specifically the cuboid drawn on the left, with ABCD (front points) and A'B'C'D' (back points, hidden behind front points)) to the unit cube, e.g. using a 4x4 matrix? How does one do it?&#xD;&#xA;&#xD;&#xA;what I've tried: &#xD;&#xA;&gt; I've tried something stronger: I made ABCD and A'B'C'D' look like a regular pyramidal frustrum (e.g. gl frustrum) (i.e. in this hypothetical setup, the image on the left would just have a black rectangle superposed on it, not a quadrilateral), and then used the DLT/direct linear transformation to solve for the alleged 4x4 matrix. However when I tried it, there did not seem to be enough degrees of freedom... the resulting 4x4 matrix did not map every input vector to every output vector. While using A,B,C,D,A' (5 pairs of pre-transform and post-transform vectors), I /almost/ get the result I want... the vectors are mapped correctly, but for example B',C',D' are mapping to (3,3,1,1) instead of (-1,-1,1,1) and are clipped away by OpenGL. If I try adding a sixth point (6 pairs of points for the 4x4 matrix to project), my solution seems degenerate (zeroes, infinites). How many degrees of freedom am I dealing with here, and is this possible with a 4x4 matrix mapping the usual 4vectors (3+1-dimensional homogeneous-coordinate vectors) that we know and love?&#xD;&#xA;&#xD;&#xA;random minor thoughts:&#xD;&#xA;&gt; (I'm guessing that it's not possible to map any arbitrary cuboid to any arbitrary cuboid with a 4x4 matrix, though I'm confused because I thought it was possible to map any convex quadrilateral to any other convex quadrilateral in 2d with some matrix like in, say, Photoshop?... can/can't this not be done with a projective transform? And how does it generalize to 3d? ...... Also given the failed attempt to find a 4x4 matrix, linear algebra says we should not expect an NxN matrix to map more than N linearly independent points to N target points in the best case, but I feel that somehow homogeneous coordinates cheat this because there is some hidden colinearity going on? I guess not?)&#xD;&#xA;&#xD;&#xA;another solution?:&#xD;&#xA;&gt; I guess one could also maybe do the following ugly thing, where you use a typical frustrum camera projection matrix, find the 2d points corresponding to the corners, then perform a 2d perspective distort homography, but if that were to happen after the pixels were rendered (e.g. photoshop) then there would be problems with resolution... maybe hypothetically one could figure out a matrix to perform this transformation on the XY-plane within NDC-space, then compose it with the normal frustrum-based matrix?&#xD;&#xA;&#xD;&#xA;(note [a]: Degree of freedom: ABCD can be further constrained to be the post-image of a projective transformation acting on a rectangle, if that is necessary... that is the black rectangle on the left could be said to be the result of projecting a picture frame clipart model)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15401" PostHistoryTypeId="2" PostId="5636" RevisionGUID="8d65152b-99ac-40cc-96de-9570229a0a73" CreationDate="2017-09-20T11:40:12.210" UserId="4714" Text="I solved my own question by implementing the [Direct Linear Transformation](https://en.wikipedia.org/wiki/Direct_linear_transformation). The examples section on Wikipedia was my use case.&#xD;&#xA;&#xD;&#xA;To get the equations, plug in the matrices (e.g. `[x1 x2 x3 x4; x5 x6 x7 x8; x9 x10 x11 x12]`) into your favorite computer algebra system like SageMath, then Solve the required matrix equation as illustrated, copy-paste the solutions in terms of variables into your code, and adjust formatting.&#xD;&#xA;&#xD;&#xA;One could then adapt the solution to one's use case by scaling or ignoring particular dimensions as appropriate (e.g. ignore the depth/z coordinate in the Normalized Device Coordinates matrix as appropriate to the use case).&#xD;&#xA;&#xD;&#xA;You will need an SVD decomposition function or library in your language." ContentLicense="CC BY-SA 3.0" />
  <row Id="15402" PostHistoryTypeId="8" PostId="3742" RevisionGUID="b09faaa6-4530-4aa2-9800-f8d75d400d9d" CreationDate="2017-09-20T11:45:36.670" UserId="4714" Comment="Rollback to [06df3a27-048a-4488-823b-ed33b5bf4377]" Text="tl;dr: Math problem in projective geometry: **How does one find some 4x4 camera matrix that gives a projection as illustrated below, such that points A,B,C,D are somewhere on the edges of the unit box (e.g. OpenGL normalized device coordinates), and the corners of the unit box fall somewhere reasonable along the rays EA, EB, EC, ED?**&#xD;&#xA;&#xD;&#xA;( extra tags: dlt direct-linear-transform projections opengl homography projective-space perspectivity collineation ndc normalized-device-coordinates matrix svd singular-value-decomposition least-squares camera camera-matrix projective-geometry projective-space homogeneous-coordinates )&#xD;&#xA;&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;elaboration:&#xD;&#xA;&#xD;&#xA;Given a quadrilateral ABCD within the the viewport, I think there exists a unique(?) transformation that maps it back to a rectangle. As seen in the image below: the quadrilateral ABCD in the viewport acts as a physical 'window', and if we map it back to a rectangle it will appear distorted.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/k5XLm.png&#xD;&#xA;&#xD;&#xA;(the box on the right represents NDC, which I talk about later)&#xD;&#xA;&#xD;&#xA;The goal is to quickly obtain the image on the right. We could raytrace every point to obtain the image (which I've done), but I would prefer to use OpenGL or other projective techniques because I wanted to take advantage of things like blending, primitives, etc.&#xD;&#xA;&#xD;&#xA;first attempt (hover to show):&#xD;&#xA;&#xD;&#xA;&gt;! I believe I can solve the problem of finding the 3x4 [camera matrix](https://en.wikipedia.org/wiki/Camera_matrix) that makes the 3+1-dimensional [homogeneous coordinate](https://en.wikipedia.org/wiki/Homogeneous_coordinates) in 3-space (on the left) and projects it down to the 2+1 dimensional homogeneous coordinates in 2-space (on the right). One can solve this using the [direct linear transformation](https://en.wikipedia.org/wiki/Direct_linear_transformation) to get a system of equations `Ba=0` for the unknown entries `a` of the camera matrix, and solving the system using [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) (SVD). I would take the vectors EA, EB, EC, ED (where E is your physical eye or the camera in world-space) as points in the pre-image, and (0,0), (1,0), (1,1), (0,1) or something as the points in the post-image, and each pair of points would give a few linear equations to plug into the SVD. The resulting matrix would map EA-&gt;(0,0) etc. (assuming there are enough degrees of freedom i.e. if the solution is unique, which I'm not sure about, see note[a].)&#xD;&#xA;&#xD;&#xA;But to my chagrin this is not how OpenGL works. OpenGL does not directly project 3d to 2d with a 3x4 matrix. OpenGL requires &quot;normalized device coordinates&quot; (NDC), which are three-dimensional points. After projecting into NDC, everything in the 'unit' box from (-1,-1,-1,1) to (1,1,1,1) is drawn; everything outside is clipped (since we're dealing with homogenerous coordinates: any point (x,y,z,w) will appear only on-screen only if the first three coordinates of (x/w,y/w,z/w,1) are within the unit box from -1 to 1).&#xD;&#xA;&#xD;&#xA;So the question becomes: does there exist some reasonable transformation that maps some weird-looking cuboid in homogeneous coordinates (specifically the cuboid drawn on the left, with ABCD (front points) and A'B'C'D' (back points, hidden behind front points)) to the unit cube, e.g. using a 4x4 matrix? How does one do it?&#xD;&#xA;&#xD;&#xA;what I've tried: &#xD;&#xA;&gt;! I've tried something stronger: I made ABCD and A'B'C'D' look like a regular pyramidal frustrum (e.g. gl frustrum) (i.e. in this hypothetical setup, the image on the left would just have a black rectangle superposed on it, not a quadrilateral), and then used the DLT/direct linear transformation to solve for the alleged 4x4 matrix. However when I tried it, there did not seem to be enough degrees of freedom... the resulting 4x4 matrix did not map every input vector to every output vector. While using A,B,C,D,A' (5 pairs of pre-transform and post-transform vectors), I /almost/ get the result I want... the vectors are mapped correctly, but for example B',C',D' are mapping to (3,3,1,1) instead of (-1,-1,1,1) and are clipped away by OpenGL. If I try adding a sixth point (6 pairs of points for the 4x4 matrix to project), my solution seems degenerate (zeroes, infinites). How many degrees of freedom am I dealing with here, and is this possible with a 4x4 matrix mapping the usual 4vectors (3+1-dimensional homogeneous-coordinate vectors) that we know and love?&#xD;&#xA;&#xD;&#xA;random minor thoughts:&#xD;&#xA;&gt;! (I'm guessing that it's not possible to map any arbitrary cuboid to any arbitrary cuboid with a 4x4 matrix, though I'm confused because I thought it was possible to map any convex quadrilateral to any other convex quadrilateral in 2d with some matrix like in, say, Photoshop?... can/can't this not be done with a projective transform? And how does it generalize to 3d? ...... Also given the failed attempt to find a 4x4 matrix, linear algebra says we should not expect an NxN matrix to map more than N linearly independent points to N target points in the best case, but I feel that somehow homogeneous coordinates cheat this because there is some hidden colinearity going on? I guess not?)&#xD;&#xA;&#xD;&#xA;another solution?:&#xD;&#xA;&gt;! I guess one could also maybe do the following ugly thing, where you use a typical frustrum camera projection matrix, find the 2d points corresponding to the corners, then perform a 2d perspective distort homography, but if that were to happen after the pixels were rendered (e.g. photoshop) then there would be problems with resolution... maybe hypothetically one could figure out a matrix to perform this transformation on the XY-plane within NDC-space, then compose it with the normal frustrum-based matrix?&#xD;&#xA;&#xD;&#xA;(note [a]: Degree of freedom: ABCD can be further constrained to be the post-image of a projective transformation acting on a rectangle, if that is necessary... that is the black rectangle on the left could be said to be the result of projecting a picture frame clipart model)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15403" PostHistoryTypeId="5" PostId="5634" RevisionGUID="30fe048e-4978-4d34-b2da-c460253c6a1b" CreationDate="2017-09-20T12:18:11.700" UserId="182" Comment="Mathjax formatting." Text="I think the solution is looking for the projective transform that correctly transforms the four points.&#xD;&#xA;&#xD;&#xA;i.e. &#xD;&#xA;&#xD;&#xA;$$y' = P \times x'$$&#xD;&#xA;&#xD;&#xA;where $x' = [x_0, x_1, 1]$ and $y = [\frac{y'_0}{y'_2}, \frac{y'_1}{y'_2}]$&#xD;&#xA;&#xD;&#xA;$P$ is a 3x3 matrix with 9 entries. Due to the final normalization it is unique up to scaling, leaving 8 degrees of freedom, which are uniquely determined by the 8 equations given by the correspondence (2 per point pair).&#xD;&#xA;&#xD;&#xA;Now you can use algebra to do this, or just use OpenCV's `getPerspectiveTransform` :).&#xD;&#xA;&#xD;&#xA;Also check out [homnogenous coordinates][1] on wikipedia to get familiar with the concept.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Homogeneous_coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="15404" PostHistoryTypeId="2" PostId="5637" RevisionGUID="35d8a72e-40de-4c99-b668-86f962b0b645" CreationDate="2017-09-20T17:20:17.527" UserId="5960" Text="I'm currently working on a renderer that tries to minimize the amount of state changes when drawing objects.&#xD;&#xA;During each frame the client submits draw instances (the client provides a render state (shader program, vao, vbo) and the vertex offset and count).&#xD;&#xA;At the end of each frame the renderer sorts these draw instances by depth and state and generates a list of draw commands (e.g. BindVertexBuffer, UseProgram, DrawArrays).&#xD;&#xA;Now my question is, how would I go about handling uniforms in a renderer like this which holds on to all actual gpu communication until the end of the frame.&#xD;&#xA;&#xD;&#xA;I have an idea on how to do this using callbacks which would be passed to the renderer when submitting a draw instance.&#xD;&#xA;Something like this:&#xD;&#xA;&#xD;&#xA;    // Called several times by systems during the game loop&#xD;&#xA;    renderer.add(program, vbo, VertexPositionColor::getFormat(), 0, 3, [](){&#xD;&#xA;    	const GLfloat[4] color = { 1, 0, 0, 1 };&#xD;&#xA;    	glUniform4fv(0, color);&#xD;&#xA;    });&#xD;&#xA;    // Called once at the end of the game loop&#xD;&#xA;    renderer.draw(); // sort, generate commands, execute commands&#xD;&#xA;&#xD;&#xA;But this seems like a less than optimal approach as it'll most likely trash the icache if there is significant amount of draw instances.&#xD;&#xA;Would this be a valid approach? And what are some of the alternatives?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15405" PostHistoryTypeId="1" PostId="5637" RevisionGUID="35d8a72e-40de-4c99-b668-86f962b0b645" CreationDate="2017-09-20T17:20:17.527" UserId="5960" Text="How do I handle uniforms in a deferred renderer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15406" PostHistoryTypeId="3" PostId="5637" RevisionGUID="35d8a72e-40de-4c99-b668-86f962b0b645" CreationDate="2017-09-20T17:20:17.527" UserId="5960" Text="|opengl|c++|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15407" PostHistoryTypeId="2" PostId="5638" RevisionGUID="00b1935e-666e-4652-8c78-7753c70d6c3e" CreationDate="2017-09-20T19:12:34.760" UserId="56" Text="I've been working on implementing the technique from the paper &quot;Designing look-and-feel using generalized crosshatching&quot; which can be found at: &#xD;&#xA; http://dl.acm.org/citation.cfm?id=3085054&#xD;&#xA;&#xD;&#xA;The paper uses triplanar texture mapping to put tilable &quot;line shading&quot; style textures onto 3d rendered models.&#xD;&#xA;&#xD;&#xA;It uses the brightness of the pixel to select which texture to use, where it has source textures of varying brightness levels like in the image below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It says:&#xD;&#xA;&#xD;&#xA;&gt; The key part of our approach is a texture synthesis algorithm that&#xD;&#xA;can construct on average constant color crosshatching textures&#xD;&#xA;from a single crosshatching image that can be hand-drawn by&#xD;&#xA;artists&#xD;&#xA;&#xD;&#xA;It then explains that it takes that constant color texture and applies dilation and erosion filters to obtain the darker and lighter versions of the (greyscale) texture.&#xD;&#xA;&#xD;&#xA;My question is this:  Let's say that you have a greyscale image of an artist drawing some cross hatching on a white piece of paper using a pencil.  How would you convert that image to be constant average color or brightness?&#xD;&#xA;&#xD;&#xA;The only other relevant info from the paper seems to be this:&#xD;&#xA;&#xD;&#xA;&gt; Our texture synthesis algorithm is an extremely simple nonstationary&#xD;&#xA;convolution filter that consists of two stages as follows:&#xD;&#xA;(1) For every pixel, compute the average color in a region around&#xD;&#xA;the pixel where the shape of the region and weights are controlled&#xD;&#xA;by a user-defined kernel. (2) If the color of the region is darker than&#xD;&#xA;the goal color, make the color of the pixel lighter; or otherwise&#xD;&#xA;darker&#xD;&#xA;&#xD;&#xA;That information is a bit sparse, and doesn't explain how much lighter or darker you should make a pixel. It's also a bit ambiguous to me whether they are talking about the process that makes the image constant color, or if they are talking about the process that makes lighter or darker versions of the constant color source texture.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qdL0X.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15408" PostHistoryTypeId="1" PostId="5638" RevisionGUID="00b1935e-666e-4652-8c78-7753c70d6c3e" CreationDate="2017-09-20T19:12:34.760" UserId="56" Text="Making an approximately constant color or brightness image" ContentLicense="CC BY-SA 3.0" />
  <row Id="15409" PostHistoryTypeId="3" PostId="5638" RevisionGUID="00b1935e-666e-4652-8c78-7753c70d6c3e" CreationDate="2017-09-20T19:12:34.760" UserId="56" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15410" PostHistoryTypeId="2" PostId="5639" RevisionGUID="ca1c4a5d-08b9-4fc4-9127-ad96190949f4" CreationDate="2017-09-20T22:44:51.663" UserId="2654" Text="I'd say that the fundamental problem here is your approach. You basically want the outside renderer to throw a bunch of random stuff at the wall, then let the internal rendering system sort it out without having any idea what any of that stuff actually *means*.&#xD;&#xA;&#xD;&#xA;Here's what I mean. Consider the case of skinned meshes vs. unskinned meshes. The internal rendering system has no idea which ones are skinned or not; all it knows is that some draw commands use a particular program and a large UBO/SSBO, while others use a different program and much smaller UBOs.&#xD;&#xA;&#xD;&#xA;And that kinda works... to a point. And that point is when you're dealing with state values that are no longer encapsulated in objects.&#xD;&#xA;&#xD;&#xA;Uniform values are program state. And you might reasonably have two different objects that use the same program have the same value for that uniform. They might have different values for other uniforms, but there would be different variance in which objects use which values.&#xD;&#xA;&#xD;&#xA;But here's the thing: in pretty much every case where this happens, someone knows that it happened. And the code that knows that is the higher level code. After all, if two objects have common programs and common uniform values, they probably have a bunch of other stuff in common too. So odds are good that the higher level code knows when such things would happen.&#xD;&#xA;&#xD;&#xA;By using this &quot;throw stuff against the wall&quot; approach, by separating the business end of your renderer from the source of that rendering data, you destroy the semantic information you could have used to detect such things. That is, it is the higher level system that should handle the &quot;sort by state change&quot; part, since it can do a much better job.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;However, given that you've effectively designed yourself into a corner, I'd say that the simplest approach is to develop a way to encode uniform values, rather than relying on callbacks.&#xD;&#xA;&#xD;&#xA;Uniforms can be scalars, vectors, or matrices (arrays and structs use multiple uniform locations). So you need the equivalent of a &quot;variant&quot; type that can store all of such data, of the types supported by GLSL. And then, for each object, you walk through each uniform location in that object's data block and set that value. Sure, &quot;visitation&quot; is not the most instruction-cache friendly approach, but it's a lot better performing than calling a `std::function`. At least with visitation, you're executing the same block of code each time.&#xD;&#xA;&#xD;&#xA;So what you'd have is a (possibly dynamic) array of uniform data, where each uniform datum is a location, a type, and the variant data. I'll leave the storage optimization of the &quot;variant&quot; as an exercise for the reader.&#xD;&#xA;&#xD;&#xA;Generally speaking however, non-block uniform usage should be fairly minimal, dealing only with values that change frequently while rendering with a program. So even in that case, things shouldn't be too bad." ContentLicense="CC BY-SA 3.0" />
  <row Id="15412" PostHistoryTypeId="5" PostId="1719" RevisionGUID="eb885b72-9cfc-4012-bcaa-4072a2f0d32b" CreationDate="2017-09-21T05:31:44.983" UserId="48" Comment="added motivation/explanation of the curvature formula" Text="When I needed an estimate of mesh curvature for a skin shader, the algorithm I ended up settling on was this:&#xD;&#xA;&#xD;&#xA;First, I computed a scalar curvature for each edge in the mesh. If the edge has positions $p_1, p_2$ and normals $n_1, n_2$, then I estimated its curvature as:&#xD;&#xA;&#xD;&#xA;$$\text{curvature} = \frac{(n_2 - n_1) \cdot (p_2 - p_1)}{|p_2 - p_1|^2}$$&#xD;&#xA;&#xD;&#xA;This calculates the difference in normals, projected along the edge, as a fraction of the length of the edge. (See below for how I came up with this formula.)&#xD;&#xA;&#xD;&#xA;Then, for each vertex I looked at the curvatures of all the edges touching it. In my case, I just wanted a scalar estimate of &quot;average curvature&quot;, so I ended up taking the geometric mean of the absolute values of all the edge curvatures at each vertex. For your case, you might find the minimum and maximum curvatures, and take those edges to be the principal curvature directions (maybe orthonormalizing them with the vertex normal). That's a bit rough, but it might give you a good enough result for what you want to do.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The motivation for this formula is looking at what happens in 2D when applied to a circle:&#xD;&#xA;&#xD;&#xA;![curvature formula applied to two points on a circle][1]&#xD;&#xA;&#xD;&#xA;Suppose you have a circle of radius $r$ (so its curvature is $1/r$), and you have two points on the circle, with their normals $n_1, n_2$. The positions of the points, relative to the circle's center, are going to be $p_1 = rn_1$ and $p_2 = rn_2$, due to the property that a circle or sphere's normals always point directly out from its center.&#xD;&#xA;&#xD;&#xA;Therefore you can recover the radius as $r = |p_1| / |n_1|$ or $|p_2| / |n_2|$. But in general, the vertex positions won't be relative to the circle's center. We can work around this by subtracting the two:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;p_2 - p_1 &amp;= rn_2 - rn_1 \\&#xD;&#xA;&amp;= r(n_2 - n_1) \\&#xD;&#xA;r &amp;= \frac{|p_2 - p_1|}{|n_2 - n_1|} \\&#xD;&#xA;\text{curvature} = \frac{1}{r} &amp;= \frac{|n_2 - n_1|}{|p_2 - p_1|}&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The result is exact only for circles and spheres. However, we can extend it to make it a bit more &quot;tolerant&quot;, and use it on arbitrary 3D meshes, and it seems to work reasonably well. We can make the formula more &quot;tolerant&quot; by first projecting the vector $n_2 - n_1$ onto the direction of the edge, $p_2 - p_1$. This allows for these two vectors not being exactly parallel (as they are in the circle case); we'll just project away any component that's not parallel. We can do this by dotting with the normalized edge vector:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;\text{curvature} &amp;= \frac{(n_2 - n_1) \cdot \text{normalize}(p_2 - p_1)}{|p_2 - p_1|} \\&#xD;&#xA;&amp;= \frac{(n_2 - n_1) \cdot (p_2 - p_1)/|p_2 - p_1|}{|p_2 - p_1|} \\&#xD;&#xA;&amp;= \frac{(n_2 - n_1) \cdot (p_2 - p_1)}{|p_2 - p_1|^2}&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;Et voilà, there's the formula that appeared at the top of this answer. By the way, a nice side benefit of using the _signed_ projection (the dot product) is that the formula then gives a signed curvature: positive for convex, and negative for concave surfaces.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Another approach I can imagine using, but haven't tried, would be to estimate the [second fundamental form](https://en.wikipedia.org/wiki/Second_fundamental_form) of the surface at each vertex. This could be done by setting up a tangent basis at the vertex, then converting all neighboring vertices into that tangent space, and using least-squares to find the best-fit 2FF matrix. Then the principal curvature directions would be the eigenvectors of that matrix. This seems interesting as it could let you find curvature directions &quot;implied&quot; by the neighboring vertices without any edges explicitly pointing in those directions, but on the other hand is a lot more code, more computation, and perhaps less numerically robust.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PL8jY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15414" PostHistoryTypeId="34" PostId="2003" RevisionGUID="483a1738-597e-4de8-95b2-f2426099424e" CreationDate="2017-09-21T18:02:56.843" UserId="-1" Comment="33" />
  <row Id="15415" PostHistoryTypeId="5" PostId="1719" RevisionGUID="b53db930-0940-42a5-9e4e-6843cfe800d4" CreationDate="2017-09-21T20:03:44.847" UserId="48" Comment="added reference to a paper that uses the 2FF approach" Text="When I needed an estimate of mesh curvature for a skin shader, the algorithm I ended up settling on was this:&#xD;&#xA;&#xD;&#xA;First, I computed a scalar curvature for each edge in the mesh. If the edge has positions $p_1, p_2$ and normals $n_1, n_2$, then I estimated its curvature as:&#xD;&#xA;&#xD;&#xA;$$\text{curvature} = \frac{(n_2 - n_1) \cdot (p_2 - p_1)}{|p_2 - p_1|^2}$$&#xD;&#xA;&#xD;&#xA;This calculates the difference in normals, projected along the edge, as a fraction of the length of the edge. (See below for how I came up with this formula.)&#xD;&#xA;&#xD;&#xA;Then, for each vertex I looked at the curvatures of all the edges touching it. In my case, I just wanted a scalar estimate of &quot;average curvature&quot;, so I ended up taking the geometric mean of the absolute values of all the edge curvatures at each vertex. For your case, you might find the minimum and maximum curvatures, and take those edges to be the principal curvature directions (maybe orthonormalizing them with the vertex normal). That's a bit rough, but it might give you a good enough result for what you want to do.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The motivation for this formula is looking at what happens in 2D when applied to a circle:&#xD;&#xA;&#xD;&#xA;![curvature formula applied to two points on a circle][1]&#xD;&#xA;&#xD;&#xA;Suppose you have a circle of radius $r$ (so its curvature is $1/r$), and you have two points on the circle, with their normals $n_1, n_2$. The positions of the points, relative to the circle's center, are going to be $p_1 = rn_1$ and $p_2 = rn_2$, due to the property that a circle or sphere's normals always point directly out from its center.&#xD;&#xA;&#xD;&#xA;Therefore you can recover the radius as $r = |p_1| / |n_1|$ or $|p_2| / |n_2|$. But in general, the vertex positions won't be relative to the circle's center. We can work around this by subtracting the two:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;p_2 - p_1 &amp;= rn_2 - rn_1 \\&#xD;&#xA;&amp;= r(n_2 - n_1) \\&#xD;&#xA;r &amp;= \frac{|p_2 - p_1|}{|n_2 - n_1|} \\&#xD;&#xA;\text{curvature} = \frac{1}{r} &amp;= \frac{|n_2 - n_1|}{|p_2 - p_1|}&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The result is exact only for circles and spheres. However, we can extend it to make it a bit more &quot;tolerant&quot;, and use it on arbitrary 3D meshes, and it seems to work reasonably well. We can make the formula more &quot;tolerant&quot; by first projecting the vector $n_2 - n_1$ onto the direction of the edge, $p_2 - p_1$. This allows for these two vectors not being exactly parallel (as they are in the circle case); we'll just project away any component that's not parallel. We can do this by dotting with the normalized edge vector:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;\text{curvature} &amp;= \frac{(n_2 - n_1) \cdot \text{normalize}(p_2 - p_1)}{|p_2 - p_1|} \\&#xD;&#xA;&amp;= \frac{(n_2 - n_1) \cdot (p_2 - p_1)/|p_2 - p_1|}{|p_2 - p_1|} \\&#xD;&#xA;&amp;= \frac{(n_2 - n_1) \cdot (p_2 - p_1)}{|p_2 - p_1|^2}&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;Et voilà, there's the formula that appeared at the top of this answer. By the way, a nice side benefit of using the _signed_ projection (the dot product) is that the formula then gives a signed curvature: positive for convex, and negative for concave surfaces.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Another approach I can imagine using, but haven't tried, would be to estimate the [second fundamental form](https://en.wikipedia.org/wiki/Second_fundamental_form) of the surface at each vertex. This could be done by setting up a tangent basis at the vertex, then converting all neighboring vertices into that tangent space, and using least-squares to find the best-fit 2FF matrix. Then the principal curvature directions would be the eigenvectors of that matrix. This seems interesting as it could let you find curvature directions &quot;implied&quot; by the neighboring vertices without any edges explicitly pointing in those directions, but on the other hand is a lot more code, more computation, and perhaps less numerically robust.&#xD;&#xA;&#xD;&#xA;A paper that takes this approach is [Rusinkiewicz, &quot;Estimating Curvatures and Their Derivatives on Triangle Meshes&quot;](http://gfx.cs.princeton.edu/pubs/_2004_ECA/curvpaper.pdf). It works by estimating the best-fit 2FF matrix per triangle, then averaging the matrices per-vertex (similar to how smooth normals are calculated).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PL8jY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15416" PostHistoryTypeId="10" PostId="5632" RevisionGUID="34f47293-106a-4aa8-89d5-1b526aa59c18" CreationDate="2017-09-21T23:47:06.113" UserId="-1" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[1718],&quot;Voters&quot;:[{&quot;Id&quot;:506,&quot;DisplayName&quot;:&quot;Noah Witherspoon&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;}]}" />
  <row Id="15417" PostHistoryTypeId="5" PostId="3742" RevisionGUID="6855fbad-db6e-4ca1-ba23-e11042ed3282" CreationDate="2017-09-22T08:03:24.957" UserId="2041" Comment="Remove unhelpful &quot;extra tags&quot; and spoiler blocks. It's no use trying to disguise the fact that your question is rambly and too long. Do not rollback this edit, but a further edit to order your thoughts and make the question shorter and clearer would make it much more likely you'll get a good answer." Text="tl;dr: Math problem in projective geometry: **How does one find some 4x4 camera matrix that gives a projection as illustrated below, such that points A,B,C,D are somewhere on the edges of the unit box (e.g. OpenGL normalized device coordinates), and the corners of the unit box fall somewhere reasonable along the rays EA, EB, EC, ED?**&#xD;&#xA;&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;## elaboration&#xD;&#xA;&#xD;&#xA;Given a quadrilateral ABCD within the the viewport, I think there exists a unique(?) transformation that maps it back to a rectangle. As seen in the image below: the quadrilateral ABCD in the viewport acts as a physical 'window', and if we map it back to a rectangle it will appear distorted.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/k5XLm.png&#xD;&#xA;&#xD;&#xA;(the box on the right represents NDC, which I talk about later)&#xD;&#xA;&#xD;&#xA;The goal is to quickly obtain the image on the right. We could raytrace every point to obtain the image (which I've done), but I would prefer to use OpenGL or other projective techniques because I wanted to take advantage of things like blending, primitives, etc.&#xD;&#xA;&#xD;&#xA;## first attempt&#xD;&#xA;&#xD;&#xA;I believe I can solve the problem of finding the 3x4 [camera matrix](https://en.wikipedia.org/wiki/Camera_matrix) that makes the 3+1-dimensional [homogeneous coordinate](https://en.wikipedia.org/wiki/Homogeneous_coordinates) in 3-space (on the left) and projects it down to the 2+1 dimensional homogeneous coordinates in 2-space (on the right). One can solve this using the [direct linear transformation](https://en.wikipedia.org/wiki/Direct_linear_transformation) to get a system of equations `Ba=0` for the unknown entries `a` of the camera matrix, and solving the system using [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) (SVD). I would take the vectors EA, EB, EC, ED (where E is your physical eye or the camera in world-space) as points in the pre-image, and (0,0), (1,0), (1,1), (0,1) or something as the points in the post-image, and each pair of points would give a few linear equations to plug into the SVD. The resulting matrix would map EA-&gt;(0,0) etc. (assuming there are enough degrees of freedom i.e. if the solution is unique, which I'm not sure about, see note[a].)&#xD;&#xA;&#xD;&#xA;But to my chagrin this is not how OpenGL works. OpenGL does not directly project 3d to 2d with a 3x4 matrix. OpenGL requires &quot;normalized device coordinates&quot; (NDC), which are three-dimensional points. After projecting into NDC, everything in the 'unit' box from (-1,-1,-1,1) to (1,1,1,1) is drawn; everything outside is clipped (since we're dealing with homogenerous coordinates: any point (x,y,z,w) will appear only on-screen only if the first three coordinates of (x/w,y/w,z/w,1) are within the unit box from -1 to 1).&#xD;&#xA;&#xD;&#xA;So the question becomes: does there exist some reasonable transformation that maps some weird-looking cuboid in homogeneous coordinates (specifically the cuboid drawn on the left, with ABCD (front points) and A'B'C'D' (back points, hidden behind front points)) to the unit cube, e.g. using a 4x4 matrix? How does one do it?&#xD;&#xA;&#xD;&#xA;## what I've tried&#xD;&#xA;&#xD;&#xA;I've tried something stronger: I made ABCD and A'B'C'D' look like a regular pyramidal frustrum (e.g. gl frustrum) (i.e. in this hypothetical setup, the image on the left would just have a black rectangle superposed on it, not a quadrilateral), and then used the DLT/direct linear transformation to solve for the alleged 4x4 matrix. However when I tried it, there did not seem to be enough degrees of freedom... the resulting 4x4 matrix did not map every input vector to every output vector. While using A,B,C,D,A' (5 pairs of pre-transform and post-transform vectors), I /almost/ get the result I want... the vectors are mapped correctly, but for example B',C',D' are mapping to (3,3,1,1) instead of (-1,-1,1,1) and are clipped away by OpenGL. If I try adding a sixth point (6 pairs of points for the 4x4 matrix to project), my solution seems degenerate (zeroes, infinites). How many degrees of freedom am I dealing with here, and is this possible with a 4x4 matrix mapping the usual 4vectors (3+1-dimensional homogeneous-coordinate vectors) that we know and love?&#xD;&#xA;&#xD;&#xA;## random minor thoughts&#xD;&#xA;&#xD;&#xA;I'm guessing that it's not possible to map any arbitrary cuboid to any arbitrary cuboid with a 4x4 matrix, though I'm confused because I thought it was possible to map any convex quadrilateral to any other convex quadrilateral in 2d with some matrix like in, say, Photoshop?... can/can't this not be done with a projective transform? And how does it generalize to 3d? ...... Also given the failed attempt to find a 4x4 matrix, linear algebra says we should not expect an NxN matrix to map more than N linearly independent points to N target points in the best case, but I feel that somehow homogeneous coordinates cheat this because there is some hidden colinearity going on? I guess not?&#xD;&#xA;&#xD;&#xA;## another solution?&#xD;&#xA;&#xD;&#xA;I guess one could also maybe do the following ugly thing, where you use a typical frustrum camera projection matrix, find the 2d points corresponding to the corners, then perform a 2d perspective distort homography, but if that were to happen after the pixels were rendered (e.g. photoshop) then there would be problems with resolution... maybe hypothetically one could figure out a matrix to perform this transformation on the XY-plane within NDC-space, then compose it with the normal frustrum-based matrix?&#xD;&#xA;&#xD;&#xA;(note [a]: Degree of freedom: ABCD can be further constrained to be the post-image of a projective transformation acting on a rectangle, if that is necessary... that is the black rectangle on the left could be said to be the result of projecting a picture frame clipart model)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15419" PostHistoryTypeId="2" PostId="5640" RevisionGUID="9cfed988-ec39-42de-86f3-b6cc50c24fc3" CreationDate="2017-09-23T10:14:06.407" UserId="7363" Text="In my n-body simulation I would like to color the particles in way which corresponds to the magnitude of the net force acting on them. &#xD;&#xA;&#xD;&#xA;This is so that I can confirm visually that the particles closer to the center of a galaxy have higher accelerations (so for example particles near the rim of a galaxy are lighter colored, and the core is red).&#xD;&#xA;&#xD;&#xA;Let P be a particle. If F is the magntitude of the net force acting on P, the idea is to calculate s=F/F_max where F_max is the maximum possible force between two particles (which exists since my simulation uses gravitational softening). Since s is a number between 0 and 1, I can associate to P an HSV color by fixing saturation and value, and setting hue=s.&#xD;&#xA;&#xD;&#xA;The issue: because the gravitational force scales as 1/r^2 the mapping of F to s is not linear. The result is that, when their are few particles (N&lt;50), the color of a particle seem to change only if it becomes locked in a binary (in a bound system of two particles which are very close to eachother). The binaries are easy to identify because they blink (default color when they are at maximal distance, another color when they are at minimal distance).&#xD;&#xA;&#xD;&#xA;For N=10,000 the result is pretty at least, but I'm not sure how realistic it is.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So how should I map the force to a color in a realistic way? My goal would be to get something more like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rsQtH.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/tqwVR.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15420" PostHistoryTypeId="1" PostId="5640" RevisionGUID="9cfed988-ec39-42de-86f3-b6cc50c24fc3" CreationDate="2017-09-23T10:14:06.407" UserId="7363" Text="How to properly color particles in N body sim?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15421" PostHistoryTypeId="3" PostId="5640" RevisionGUID="9cfed988-ec39-42de-86f3-b6cc50c24fc3" CreationDate="2017-09-23T10:14:06.407" UserId="7363" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15422" PostHistoryTypeId="2" PostId="5641" RevisionGUID="bf26bc55-927d-4f87-9d4f-5c9a95dbfa6c" CreationDate="2017-09-24T21:20:31.143" UserId="7368" Text="I want to create an application to visualize image pairs in stereoscopic 3D. I want it to have a cursor that can move left and right, but also in and out. I think the way to achieve this is to draw a cursor on top of each image and then draw the images on screen (which would be a 3D capable screen).&#xD;&#xA;&#xD;&#xA;How do I create such an application?&#xD;&#xA;&#xD;&#xA;The experience I have is console programming in C, C++, Python. And I once used GTK+ to create a windowed app.&#xD;&#xA;&#xD;&#xA;I've searched around and my problem is that I don't know where to start learning.&#xD;&#xA;&#xD;&#xA;More details:&#xD;&#xA;&#xD;&#xA;This app is meant to run on windows (although it would be nice if I could made multi-platform)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15423" PostHistoryTypeId="1" PostId="5641" RevisionGUID="bf26bc55-927d-4f87-9d4f-5c9a95dbfa6c" CreationDate="2017-09-24T21:20:31.143" UserId="7368" Text="Stereoscopic 3D app development" ContentLicense="CC BY-SA 3.0" />
  <row Id="15424" PostHistoryTypeId="3" PostId="5641" RevisionGUID="bf26bc55-927d-4f87-9d4f-5c9a95dbfa6c" CreationDate="2017-09-24T21:20:31.143" UserId="7368" Text="|3d|stereo-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15427" PostHistoryTypeId="2" PostId="5642" RevisionGUID="6cd303fb-4d0e-4a6f-9e5f-9cf33f3f1265" CreationDate="2017-09-25T03:10:06.253" UserId="3003" Text="This is a *very* broad question. The basic way to do this is to generate 2 frames - one for each eye. You can do this using any modern 3D API from [OpenGL](https://www.opengl.org) to [DirectX](https://msdn.microsoft.com/en-us/library/windows/desktop/ee663274(v=vs.85).aspx) to [Vulkan](https://www.khronos.org/vulkan/), [Metal](https://developer.apple.com/metal/), or DX12. &#xD;&#xA;&#xD;&#xA;You'll need to understand things like interocular distance, [depth cues](http://www.eruptingmind.com/depth-perception-cues-other-forms-of-perception/), and [3D compositing](http://www.wisegeek.com/what-is-3d-compositing.htm).&#xD;&#xA;&#xD;&#xA;You'll also need some way to allow the user to move the curser in and out, so you'll want to read up on various user interface, visual interface, and user experience (UI, VI, and UX, respectively) techniques." ContentLicense="CC BY-SA 3.0" />
  <row Id="15428" PostHistoryTypeId="2" PostId="5643" RevisionGUID="8d162a69-c184-4acf-bbbc-889f165c088e" CreationDate="2017-09-25T12:03:24.207" UserId="7228" Text="I am working my way through my first path tracer and I am currently designing how to deal with area lights. I have two questions:&#xD;&#xA;&#xD;&#xA;Each object in my scene can have a Light attached to it, this is how I represent Area Lights. Given this I have two questions: &#xD;&#xA;&#xD;&#xA;1) **Shadow ray:** When doing shadows, if I use a blind &lt;code&gt;IsOccluded&lt;/code&gt; function that I use successfully for dirac lights, I will obviously have always an &quot;occluded&quot; result, as the light vector by construction ends up at the light source itself which is an object in my scene and therefore will be hit by the shadow ray. &#xD;&#xA;&#xD;&#xA;To rephrase, how do I deal nicely with the light being an object in my scene when casting the shadow ray for that light? &#xD;&#xA;&#xD;&#xA;I would like to keep my &lt;code&gt;IsOccluded&lt;/code&gt; function simple, returning only a boolean and not a position/interaction record. At first glance PBRT manages to do so, but I don't understand how they get around the problem. Am I forced to use a different scene intersection function? If so, what is the most graceful way to solve the problem? &#xD;&#xA;&#xD;&#xA;2) **Secondary rays**: If I have more than one bounce, I often see this black dots appearing (even if I disable shadows). I know this is hard without more context, but I wonder if someone has encountered something like this or can guess: &#xD;&#xA;&#xD;&#xA;**With multiple bounces**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**With only first hit**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I thought it could be related to the way I sample the sphere, but if that was the case, shouldn't I get black dots even with only one event? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also, do you have any suggestion on how to handle area light sources that I am clearly missing here? &#xD;&#xA;&#xD;&#xA;Thank you and sorry for the probably confused question, I am happy to edit it if you have suggestions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oxwtz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VALHH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15429" PostHistoryTypeId="1" PostId="5643" RevisionGUID="8d162a69-c184-4acf-bbbc-889f165c088e" CreationDate="2017-09-25T12:03:24.207" UserId="7228" Text="Path tracing with Next event estimation and area lights auto occlusion" ContentLicense="CC BY-SA 3.0" />
  <row Id="15430" PostHistoryTypeId="3" PostId="5643" RevisionGUID="8d162a69-c184-4acf-bbbc-889f165c088e" CreationDate="2017-09-25T12:03:24.207" UserId="7228" Text="|lighting|pathtracing|shadow|area|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15431" PostHistoryTypeId="5" PostId="5643" RevisionGUID="47d2d5c3-5b09-409a-9498-a82bd7a311dc" CreationDate="2017-09-25T12:14:33.563" UserId="7228" Comment="added 270 characters in body" Text="I am working my way through my first path tracer and I am currently designing how to deal with area lights. I have two questions:&#xD;&#xA;&#xD;&#xA;Each object in my scene can have a Light attached to it, this is how I represent Area Lights. Given this I have two questions: &#xD;&#xA;&#xD;&#xA;1) **Shadow ray:** When doing shadows, if I use a blind &lt;code&gt;IsOccluded&lt;/code&gt; function that I use successfully for dirac lights, I will obviously have always an &quot;occluded&quot; result, as the light vector by construction ends up at the light source itself which is an object in my scene and therefore will be hit by the shadow ray. &#xD;&#xA;&#xD;&#xA;To rephrase, how do I deal nicely with the light being an object in my scene when casting the shadow ray for that light? &#xD;&#xA;&#xD;&#xA;I would like to keep my &lt;code&gt;IsOccluded&lt;/code&gt; function simple, returning only a boolean and not a position/interaction record. At first glance PBRT manages to do so, but I don't understand how they get around the problem. Am I forced to use a different scene intersection function? If so, what is the most graceful way to solve the problem? &#xD;&#xA;&#xD;&#xA;2) **Secondary rays**: If I have more than one bounce, I often see this black dots appearing (even if I disable shadows). I know this is hard without more context, but I wonder if someone has encountered something like this or can guess: &#xD;&#xA;&#xD;&#xA;**With multiple bounces**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**With only first hit**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I thought it could be related to the way I sample the sphere, but if that was the case, shouldn't I get black dots even with only one event? I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated. I am guessing I am trying to lit the light with the light itself, causing a NaN that gets then propagated. Does it make sense? I am more interested to understand the cause than how to fix this. &#xD;&#xA;&#xD;&#xA;Also, do you have any suggestion on how to handle area light sources that I am clearly missing here? &#xD;&#xA;&#xD;&#xA;Thank you and sorry for the probably confused question, I am happy to edit it if you have suggestions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oxwtz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VALHH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15432" PostHistoryTypeId="5" PostId="5643" RevisionGUID="bb00f21f-aad2-4495-9af0-d4285a6c4f8f" CreationDate="2017-09-25T12:21:55.820" UserId="7228" Comment="added 209 characters in body" Text="I am working my way through my first path tracer and I am currently designing how to deal with area lights. I have two questions:&#xD;&#xA;&#xD;&#xA;Each object in my scene can have a Light attached to it, this is how I represent Area Lights. Given this I have two questions: &#xD;&#xA;&#xD;&#xA;1) **Shadow ray:** When doing shadows, if I use a blind &lt;code&gt;IsOccluded&lt;/code&gt; function that I use successfully for dirac lights, I will obviously have always an &quot;occluded&quot; result, as the light vector by construction ends up at the light source itself which is an object in my scene and therefore will be hit by the shadow ray. &#xD;&#xA;&#xD;&#xA;To rephrase, how do I deal nicely with the light being an object in my scene when casting the shadow ray for that light? &#xD;&#xA;&#xD;&#xA;I would like to keep my &lt;code&gt;IsOccluded&lt;/code&gt; function simple, returning only a boolean and not a position/interaction record. At first glance PBRT manages to do so, but I don't understand how they get around the problem. Am I forced to use a different scene intersection function? If so, what is the most graceful way to solve the problem? &#xD;&#xA;&#xD;&#xA;2) **Secondary rays**: If I have more than one bounce, I often see this black dots appearing (even if I disable shadows). I know this is hard without more context, but I wonder if someone has encountered something like this or can guess: &#xD;&#xA;&#xD;&#xA;**With multiple bounces**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**With only first hit**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I thought it could be related to the way I sample the sphere, but if that was the case, shouldn't I get black dots even with only one event? I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated. I am guessing I am trying to lit the light with the light itself, causing a NaN that gets then propagated. Does it make sense? I am more interested to understand the cause than how to fix this. &#xD;&#xA;&#xD;&#xA;3) **Bright pixels**: Somewhat unrelated? (I can open separate question), but I get lots of unnaturally bright pixels all over the place if I have more than 2 bounces. What is the cause of this? How do I fix this? &#xD;&#xA;&#xD;&#xA;Also, do you have any suggestion on how to handle area light sources that I am clearly missing here? &#xD;&#xA;&#xD;&#xA;Thank you and sorry for the probably confused question, I am happy to edit it if you have suggestions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oxwtz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VALHH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15433" PostHistoryTypeId="5" PostId="5643" RevisionGUID="f66f1206-75cd-43d1-a3f5-295de3b27aca" CreationDate="2017-09-25T12:41:23.657" UserId="7228" Comment="edited body" Text="I am working my way through my first path tracer and I am currently designing how to deal with area lights. I have two questions:&#xD;&#xA;&#xD;&#xA;Each object in my scene can have a Light attached to it, this is how I represent Area Lights. Given this I have two questions: &#xD;&#xA;&#xD;&#xA;1) **Shadow ray:** When doing shadows, if I use a blind &lt;code&gt;IsOccluded&lt;/code&gt; function that I use successfully for point lights, I will obviously have always an &quot;occluded&quot; result, as the light vector by construction ends up at the light source itself which is an object in my scene and therefore will be hit by the shadow ray. &#xD;&#xA;&#xD;&#xA;To rephrase, how do I deal nicely with the light being an object in my scene when casting the shadow ray for that light? &#xD;&#xA;&#xD;&#xA;I would like to keep my &lt;code&gt;IsOccluded&lt;/code&gt; function simple, returning only a boolean and not a position/interaction record. At first glance PBRT manages to do so, but I don't understand how they get around the problem. Am I forced to use a different scene intersection function? If so, what is the most graceful way to solve the problem? &#xD;&#xA;&#xD;&#xA;2) **Secondary rays**: If I have more than one bounce, I often see this black dots appearing (even if I disable shadows). I know this is hard without more context, but I wonder if someone has encountered something like this or can guess: &#xD;&#xA;&#xD;&#xA;**With multiple bounces**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**With only first hit**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I thought it could be related to the way I sample the sphere, but if that was the case, shouldn't I get black dots even with only one event? I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated. I am guessing I am trying to lit the light with the light itself, causing a NaN that gets then propagated. Does it make sense? I am more interested to understand the cause than how to fix this. &#xD;&#xA;&#xD;&#xA;3) **Bright pixels**: Somewhat unrelated? (I can open separate question), but I get lots of unnaturally bright pixels all over the place if I have more than 2 bounces. What is the cause of this? How do I fix this? &#xD;&#xA;&#xD;&#xA;Also, do you have any suggestion on how to handle area light sources that I am clearly missing here? &#xD;&#xA;&#xD;&#xA;Thank you and sorry for the probably confused question, I am happy to edit it if you have suggestions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oxwtz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VALHH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15434" PostHistoryTypeId="2" PostId="5644" RevisionGUID="a7927836-d22c-4431-b823-face66559161" CreationDate="2017-09-26T15:06:39.450" UserId="6974" Text="I am trying out different anti-aliasing algorithms on my image to improve the image quality. I want to compare the differences between these generated images via some metric. I was checking online for good metrics and found none.&#xD;&#xA;&#xD;&#xA;Could someone please help me by pointing me to a valid metric that one can use to measure aliasing effects in an image ? " ContentLicense="CC BY-SA 3.0" />
  <row Id="15435" PostHistoryTypeId="1" PostId="5644" RevisionGUID="a7927836-d22c-4431-b823-face66559161" CreationDate="2017-09-26T15:06:39.450" UserId="6974" Text="How to compare anti-aliasing effects on images ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15436" PostHistoryTypeId="3" PostId="5644" RevisionGUID="a7927836-d22c-4431-b823-face66559161" CreationDate="2017-09-26T15:06:39.450" UserId="6974" Text="|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15437" PostHistoryTypeId="2" PostId="5645" RevisionGUID="b5a0bcb3-58c1-4633-a094-418ab566e00b" CreationDate="2017-09-26T17:54:25.353" UserId="56" Text="What you want to do is compare your anti aliased results against a &quot;ground truth&quot; image.&#xD;&#xA;&#xD;&#xA;The ground truth image is the same image but without aliasing.&#xD;&#xA;&#xD;&#xA;There are many ways to make an alias-free image, but a straight forward way would be by doing super sampling.&#xD;&#xA;&#xD;&#xA;**Super Sampling**&#xD;&#xA;&#xD;&#xA;When we render, we usually take a single sample at the center of the pixel (rasterize / shader / etc it to make the color).&#xD;&#xA;&#xD;&#xA;Super sampling works by taking $N$ samples for that pixel, in random parts of the pixel and averaging the result.&#xD;&#xA;&#xD;&#xA;The more samples you take, the closer you get to the ideal &quot;alias free&quot; image.&#xD;&#xA;&#xD;&#xA;One simple way to do super sampling is to render the image at a higher resolution and then shrink it down to a smaller image.  For instance, if you render at double the height and width and then shrink the image down, that's the same as taking 4 samples per pixel.  However, going this route, the samples are evenly spaced on a grid, not randomly placed within each pixel.  Making the samples random instead of evenly spaced is really important to this monte carlo integration working, but evenly spacing them on a grid is a cheaper method that is better than nothing (aka useful in realtime situations sometimes).&#xD;&#xA;&#xD;&#xA;Another way to do super sampling would be to render the image at normal resolution $N$ times, but in each render, you randomly offset the camera by a sub-pixel amount.  You then average your $N$ images together.  That will give you the random sample points, but of course each pixel has the same random sample points.&#xD;&#xA;&#xD;&#xA;This is why you will often see sub-pixel jittering of the camera when doing temporal anti aliasing: it allows for better anti aliased results (a better integration) over time when combining multiple frames.  If they were all in the same position every frame, you wouldn't get any more information about the pixel.&#xD;&#xA;&#xD;&#xA;Doing these methods will give you your ground truth alias free image, if using enough samples.&#xD;&#xA;&#xD;&#xA;**Comparing vs Ground Truth**&#xD;&#xA;&#xD;&#xA;The next step would be to compare the other anti aliased techniques against the super sampled ground truth.&#xD;&#xA;&#xD;&#xA;There are lots and lots of ways that you might want to analyze this data, but I'll give a few ideas.&#xD;&#xA;&#xD;&#xA;One way could be to make a texture where each pixel is the absolute value of the difference between the images for that pixel.  This would let you see the entire image as a whole and get an idea of how different it was from the ground truth.&#xD;&#xA;&#xD;&#xA;Another way could be to calculate the mean and standard deviation of the difference of the images. This would give you an idea of how much on average pixels differed in the images, while also giving you an idea of how much variance there was in the difference. A high variance means some places are much worse than other places, so isn't very consistent.  Ideally, the best AA method will have the lowest mean, and the lowest variance.&#xD;&#xA;&#xD;&#xA;Lastly, since aliasing is ultimately a &quot;frequency&quot; thing, you might find interesting data in doing a discrete Fourier transform on your images and comparing the frequencies in the AA method images vs the frequencies in the super sampled image.&#xD;&#xA;&#xD;&#xA;More info on taking DFT of images here: https://blog.demofox.org/2016/07/28/fourier-transform-and-inverse-of-images/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15438" PostHistoryTypeId="2" PostId="5646" RevisionGUID="d8f7dc87-7e04-48d7-8de3-7811cba0aa12" CreationDate="2017-09-26T19:21:24.273" UserId="100" Text="I am no expert in offline renderers, but I'll give it a go until someone else comes with a better answer :) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;##Shadow rays intersecting area light&#xD;&#xA;&#xD;&#xA;It is *very* common to assign an extent to your rays. How to do so? Think about the parametric formula of a ray:&#xD;&#xA;&#xD;&#xA; $$R(t) = O + t\vec{D}$$&#xD;&#xA;&#xD;&#xA;it should immediately jumps out that how far $R(t)$ can be from the origin $O$ depends on how much we can travel in the direction $\vec{D}$, and this travelling is clearly governed by the parameter $t$. &#xD;&#xA;&#xD;&#xA;Your problem here is that you don't want to let the ray travel indefinitely, but you want to stop just before it hits the source of the light, because otherwise, as you correctly noticed, everything will result occluded. &#xD;&#xA;&#xD;&#xA;So how do you limit how much your ray can travel? You just have to limit the maximum value that $t$ can take. You have two option:&#xD;&#xA;&#xD;&#xA; 1. Probably the most intuitive one is to compute at what $t_{light}$ your light source lies. By using the same parametric formulation of the ray, if $L_p$ is the point you've chosen on the area light, then $t_{light}$ will be:&#xD;&#xA;&#xD;&#xA;$$t_{light} = \frac{L_{p}[i] - O[i]}{\vec{D}[i]}$$&#xD;&#xA;  where $[i]$ represents the coordinate of your choice.  Given this, you want to stop your shadow ray to travel just before $t$ reaches $t_{light}$. If it goes over this value, report an unoccluded result. &#xD;&#xA;&#xD;&#xA; 2. Now while the option above is probably the first thing that comes to mind, it is wasteful as you'd need to both have $L_p$ around and perform some unneeded arithmetic operations if you have your light vector $\vec{D}$ as unnormalized around. In fact, this is none other than $L_p - O$ and in a case like this, the Light lies at exactly $t == 1$: &#xD;&#xA;&#xD;&#xA;$$ O + 1 \times (L_p - O ) = L_p $$&#xD;&#xA;&#xD;&#xA;So if you trace your shadow ray with an unnormalized direction $\vec{D}$, you can just set your maximum $t$ to be *just under* $1$. This is in fact what PBRT does, and as far as I am aware many other renderers.  &#xD;&#xA;&#xD;&#xA;##Black dots (or NaNs)&#xD;&#xA;&#xD;&#xA;Nothing to add over @Dan Hulme comment, so I'll just add it here for completeness of the answer: &#xD;&#xA;&#xD;&#xA;&gt; &quot;I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated.&quot; The common scenario is that you're using floating-point and you have a bug in your code :-) You have to expect that you'll get NaNs during development, so you should either (a) make sure they get filtered out instead of propagated by the filter, or (b) show all NaNs as bright pink so it's immediately obvious when they're there. – Dan Hulme♦ &#xD;&#xA;&#xD;&#xA;and if I may add, you should expect some &lt;code&gt;inf&lt;/code&gt; as well from time to time, so it's always good to account for these two special cases. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;##&quot;Bright pixels&quot;&#xD;&#xA;&#xD;&#xA;With that, I assume you are talking about what is commonly referred to as fireflies. Fireflies avoidance is indeed quite a big topic and probably warrant its own question. However, just briefly.&#xD;&#xA;&#xD;&#xA;Fireflies typically occur when you lots of your paths end in areas with low light and very few paths end up in very bright light. &#xD;&#xA;There is lots of material on how to fight fireflies, a short google search will lead to a lot of techniques depending on your case. &#xD;&#xA;Just to name drop a few: &#xD;&#xA;&#xD;&#xA; - Radiance clamping&#xD;&#xA; - Multiple Importance Sampling (especially if in presence of glossy/shiny surfaces)&#xD;&#xA; - Denoising techniques&#xD;&#xA; - Increment your sample count :-) &#xD;&#xA; - etc.&#xD;&#xA;&#xD;&#xA;Also, generally increasing the size of the light source tends to help as well. Remember, the goal is always to hit those bright spot with higher probability! &#xD;&#xA;&#xD;&#xA;A better solution to the problem is probably to use something like [Bidirectional Path Tracing][1] as this will have sub-paths starting from the light source as well, increasing the likelihood of sampling the bright areas. &#xD;&#xA;&#xD;&#xA;Another cause of fireflies are caustics, but I don't want to make this answer longer, so if you are interested this is well worth an additional question. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15439" PostHistoryTypeId="2" PostId="5647" RevisionGUID="9a8c25a8-bd47-4127-b21b-4ed0c7899613" CreationDate="2017-09-26T19:41:53.557" UserId="7363" Text="I have implemented an N-body simulation using the Barnes-Hut optimisation in Python which runs at a not-unacceptable speed for N=10,000 bodies, but it's still too slow to watch real time. &#xD;&#xA;&#xD;&#xA;A new frame is generated each time-step, and to display the frame we must first calculate the new positions of the bodies, and then draw them all. For N=10,000, it takes about 5 seconds to generate one frame (this is waaay too high as Barnes-Hut should be giving better results). The display is done through the pygame module.&#xD;&#xA;&#xD;&#xA;I would thus like to record my simulation and replay it once after it's done at a higher speed.&#xD;&#xA;&#xD;&#xA;**How can I accomplish this without slowing down the program or exceeding memory limitations?**&#xD;&#xA;&#xD;&#xA;One potential solution is simply to save the pygame screen each timestep, but this is apparently very slow. &#xD;&#xA;&#xD;&#xA;I thought also about storing the list of positions of the bodies generated each time step, and then redrawing all the frames once the situation finishes. Drawing a frame still takes some time, but not as much time as it takes to calculate the new positions." ContentLicense="CC BY-SA 3.0" />
  <row Id="15440" PostHistoryTypeId="1" PostId="5647" RevisionGUID="9a8c25a8-bd47-4127-b21b-4ed0c7899613" CreationDate="2017-09-26T19:41:53.557" UserId="7363" Text="How to record N-body simulation as a video?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15441" PostHistoryTypeId="3" PostId="5647" RevisionGUID="9a8c25a8-bd47-4127-b21b-4ed0c7899613" CreationDate="2017-09-26T19:41:53.557" UserId="7363" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15442" PostHistoryTypeId="2" PostId="5648" RevisionGUID="c52db315-fa98-4c8f-9a6c-36ebe4730dbb" CreationDate="2017-09-27T02:12:08.333" UserId="3003" Text="You could always write each frame out as an image and then use another tool to compress it into a movie that you playback. You don't say what type of system you're running on, but I believe that [ffmpeg](http://ffmpeg.org) could do it for you, as it's a cross-platform tool. It's hard to estimate how long the compression will take since it will depend on the content you're compressing. I'm not sure whether you can continuously feed it frames, or if you need to generate them all at once." ContentLicense="CC BY-SA 3.0" />
  <row Id="15451" PostHistoryTypeId="50" PostId="4760" RevisionGUID="884f31b8-f106-4ee7-a24e-7f28e685d600" CreationDate="2017-09-27T13:15:27.930" UserId="-1" />
  <row Id="15457" PostHistoryTypeId="2" PostId="5650" RevisionGUID="4e2381ff-53d9-4bc5-83b7-e0ca0922003c" CreationDate="2017-09-27T20:14:29.643" UserId="56" Text="user1118321's suggestion is the correct one but i'll elaborate a bit.&#xD;&#xA;&#xD;&#xA;You run your simulation giving it a fixed time step between frames.  This time step would be 1/30th of a second (33.3333 ms) for instance if you wanted a 30 fps movie.&#xD;&#xA;&#xD;&#xA;You let your simulation calculations and your rendering run, taking as long as they need to, and then write the rendered frame out to disk, with the frame number in the name (like frame0.bmp, frame1.bmp, etc).&#xD;&#xA;&#xD;&#xA;After you have all these frames, you can use ffmpeg to combine them into a video of the desired frame rate.&#xD;&#xA;&#xD;&#xA;If you want audio in your video (like sounds when things collide), you can actually keep an audio timeline (what audio events happened on which frames, or at what points in time) while doing your simulation, and then after your rendering is finished, you can generate the audio stream that goes along with your video, which ffmpeg will gladly combine with your video.&#xD;&#xA;&#xD;&#xA;I've used this on a few projects in times past and it's worked great.  I also wrote up some more details about this process a while back: https://blog.demofox.org/2012/09/09/recording-perfectly-lagless-audio-synchronized-video-of-your-game/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15458" PostHistoryTypeId="2" PostId="5651" RevisionGUID="2447f2a7-8a68-46e8-8d13-31b35476e9a3" CreationDate="2017-09-27T22:13:31.273" UserId="7378" Text="- I have done my due hour of research before asking this question, it's a simple question, but I have found no hint at an answer online.&#xD;&#xA;&#xD;&#xA;I want the ability to extend an object infinitely in one direction, such as a tower that appears infinitely high, or a road infinitely long. I have tried my hardest to think up an approach to this that doesn't cheat, but nothing has come to mind.&#xD;&#xA;&#xD;&#xA;An example, take a textured cube, and have it appear infinitely tiled in one direction, to its vanishing point:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Is there a way of doing this while retaining lighting and bumpmaps so it seamlessly blends with level geometry? Is there any way to do this efficiently?&#xD;&#xA;&#xD;&#xA;Hopefully this isn't a stupid or misplaced question, thanks for your time.&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZEwMC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15459" PostHistoryTypeId="1" PostId="5651" RevisionGUID="2447f2a7-8a68-46e8-8d13-31b35476e9a3" CreationDate="2017-09-27T22:13:31.273" UserId="7378" Text="Creating a vanishing point perspective shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="15460" PostHistoryTypeId="3" PostId="5651" RevisionGUID="2447f2a7-8a68-46e8-8d13-31b35476e9a3" CreationDate="2017-09-27T22:13:31.273" UserId="7378" Text="|shader|computational-geometry|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15462" PostHistoryTypeId="2" PostId="5652" RevisionGUID="b43c5bcc-2dcd-4cbc-8fb5-96a17a9dd02e" CreationDate="2017-09-28T05:38:31.193" UserId="1937" Text="I've been getting interested in SIMD programming on CPU using SSE recently, but I'm a complete noob on the subject. I found [this article][1] describing how to make an efficient float3 type using the recent __vectorcall convention, and it made me wonder how best to deal with the wasted space inherent in using a 128-bit type to represent vectors smaller than 4.&#xD;&#xA;&#xD;&#xA;For a typical use case, you might want to transform a bunch of positions and normals on the CPU in order to do a batched draw call. When transmitting the data over to the GPU, though, ideally you'd want this as tightly packed arrays of float3, either interleaved or in separate buffers.&#xD;&#xA;&#xD;&#xA;It seems like there are two options here:&#xD;&#xA;&#xD;&#xA;A - store the data tightly packed, and unpack and repack to and from SSE-friendly format when you need to manipulate it, taking the CPU performance hit, or&#xD;&#xA;&#xD;&#xA;B - store the data loosely packed on 16-byte boundaries, SSE it directly, and take the bandwidth and VRAM hit when sending to GPU.&#xD;&#xA;&#xD;&#xA;Which of these options would be preferred in a real-world 3D engine, or under what circumstances would you prefer one to the other?   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.codersnotes.com/notes/maths-lib-2016/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15463" PostHistoryTypeId="1" PostId="5652" RevisionGUID="b43c5bcc-2dcd-4cbc-8fb5-96a17a9dd02e" CreationDate="2017-09-28T05:38:31.193" UserId="1937" Text="Dealing with wasted space when using SIMD on CPU for vector maths" ContentLicense="CC BY-SA 3.0" />
  <row Id="15464" PostHistoryTypeId="3" PostId="5652" RevisionGUID="b43c5bcc-2dcd-4cbc-8fb5-96a17a9dd02e" CreationDate="2017-09-28T05:38:31.193" UserId="1937" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15465" PostHistoryTypeId="2" PostId="5653" RevisionGUID="6e660300-6eb5-4829-a2e3-67a813b56fe9" CreationDate="2017-09-28T07:24:17.870" UserId="2041" Text="There's a third option you've neglected. Because of how graphics APIs work, typically you have to copy the data between the CPU and GPU anyway - even if you're on a mobile SoC where they share the same physical memory. This copy is the ideal time to take the hit of changing format, since you have to touch all of the memory anyway. So the copy in user memory, owned by the CPU, can be stored padded for SIMD alignment. Then, when you need to send that data to GPU memory, instead of doing a memcpy, just read in the 4-vectors and write out 3-vectors. It's less memory bandwidth than a normal copy (you're reading just as much, but writing less) and negligible CPU work.&#xD;&#xA;&#xD;&#xA;If you've got that fourth float doing nothing, you might as well use it and make your co-ordinates homogeneous instead of just xyz. Depending on what compute you're doing on the CPU, that might make some things easier (transforms are the obvious example, but also reducing divisions if you were renormalising your normals a lot before).&#xD;&#xA;&#xD;&#xA;This is similar but not identical to a trick I used when implementing OpenGL texture upload. On ARM, most Neon instructions operate at memory bandwidth rate, so if you're already doing a memcpy, it's free to do a pipeline-worth of instructions at the same time. You can use those free instructions to do pixel format conversion *and* reordering to Z-order or U-order." ContentLicense="CC BY-SA 3.0" />
  <row Id="15469" PostHistoryTypeId="2" PostId="5655" RevisionGUID="57cdfe4f-97a3-40b4-987c-bd4bbecb012b" CreationDate="2017-09-28T15:16:13.127" UserId="3470" Text="It should be possible to do this properly by using a modified projection matrix for your entire scene that has its far plane at infinity, as detailed [here][1]. That should allow you to properly render points infinitely far away from the camera. The presentation says that such a point is represented by a direction (a vector with .w = 0), so it should be as simple as replacing the position of your vertex with the direction vector pointing towards the desired vanishing point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.terathon.com/gdc07_lengyel.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15470" PostHistoryTypeId="5" PostId="5655" RevisionGUID="7235cd58-f5dc-42bc-8435-2ca771aa94e8" CreationDate="2017-09-28T15:38:46.670" UserId="3470" Comment="added 529 characters in body" Text="It should be possible to do this properly by using a modified projection matrix for your entire scene that has its far plane at infinity, as detailed [here][1]. That should allow you to properly render points infinitely far away from the camera. The presentation says that such a point is represented by a direction (a vector with .w = 0), so it should be as simple as replacing the position of your vertex with the direction vector pointing towards the desired vanishing point.&#xD;&#xA;&#xD;&#xA;One caveat is that any interpolation between the vanishing point and any other vertex would be incorrect, because the perspective correct hardware interpolator can't properly handle infinite values. This shouldn't affect lighting assuming normals are the same, but it will make texturing considerably harder. Probably the easiest way here would be to do an inverse projection of the point back to object space in the fragment shader and define the texture coordinates to be based on the object space position of the fragment.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.terathon.com/gdc07_lengyel.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15472" PostHistoryTypeId="2" PostId="5656" RevisionGUID="fc07ae92-ce33-4116-b6be-62f7d1b01039" CreationDate="2017-09-29T10:47:41.160" UserId="2287" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including Cook-Torrance. Their formula does not include the division by 4. The division by pi belongs to the specular reflectivity coefficient (similar to the diffuse contribution).&#xD;&#xA;&#xD;&#xA;Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;*Proceedings of the Eurographics Symposium on Rendering 2005*.&#xD;&#xA;&#xD;&#xA;[Project Page][1], [Supplemental][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15473" PostHistoryTypeId="2" PostId="5657" RevisionGUID="d5201d01-dae8-4444-adef-96b60680740b" CreationDate="2017-09-29T11:26:31.540" UserId="7390" Text="I am trying to implement bilinear interpolation as described in the paper **Spatial Tranformer Networks** by *Jaderberg et. al* (see [link to paper](https://arxiv.org/pdf/1506.02025.pdf)). They describe bilinear interpolation in Equation 5 as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;V_i^c = \sum_{n}^{H}\sum_{m}^{W} U_{nm}^c \max(0,1-|x_i^s - m|)\cdot\max(0,1-|y_i^s - n|),&#xD;&#xA;$$&#xD;&#xA;where:&#xD;&#xA;&#xD;&#xA;* $V_i^c$ is the resulting pixel value in the new image&#xD;&#xA;* $H$ and $W$ are the height and width of the original image (or feature map) in pixels&#xD;&#xA;* $c$ refers to the channel (e.g. RGB)&#xD;&#xA;* $(x_i^s, y_i^s)$ are the coordinates where the original image is sampled (where the image is normalized such that $-1 \le x_i^s, y_i^s\le 1$)&#xD;&#xA;* $U_{nm}^c$ is defined as the pixel value at location $(n,m)$ in channel $c$.&#xD;&#xA;&#xD;&#xA;I am having trouble interpreting the variables $n$ and $m$. Are these&#xD;&#xA;&#xD;&#xA;* coordinates in the normalized image (i.e. $-1 \le n, m\le 1$, where you would sum $n$ from $n=-1$ to $H=1$ in steps of the normalized resolution, e.g. steps of $1/100$ for an image that is 100 px in height)&#xD;&#xA;* or are these row and column values (e.g. you sum $n$ from $n=0$ to $n=100$ for an image that is 100px in height)?&#xD;&#xA;&#xD;&#xA;I have tried out both to do downsampling of an image, but don't get consistent results.&#xD;&#xA;&#xD;&#xA;If someone can help me out interpreting this, I would appreciate it very much.&#xD;&#xA;&#xD;&#xA;Below I have included what I understand of bilinear interpolation. Maybe that someone can help me out based on this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;In the below figure, a single channel feature map (or image) with one channel is displayed that consists of four pixels with values $ U_{nm} $, where $ n $ and $ m $ are the coordinates of the center of the pixels, i.e. $ m,n \in \{-0.5, 0.5\} $. If we index $ m $ and $ n $ as $ m_k, n_k $, with $ k \in [1,4] $, we can also index the pixel values as $ U_{n_km_k} $. The values of all four pixels can be reduced to a single value $ V $ at position $ (x_i^s, y_i^s) $ by applying bilinear interpolation.&#xD;&#xA;[![Bilinear Interpolation][1]][1]&#xD;&#xA;&#xD;&#xA;The procedure can be divided into three linear interpolations. First the value $ U_1' $ at position $ (x_{U_1'}, y_{U_1'}) $ can be computed by interpolating the values $ U_{n_1m_1} $ and $ U_{n_2m_2} $:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_1' = \Delta x_2\ U_{n_1m_1} + \Delta x_1\ U_{n_2m_2}.&#xD;&#xA;\end{equation}&#xD;&#xA;As the sum of $ \Delta x_1 $ and $ \Delta x_2 $ is equal to one, due to normalization of the axes, the above equation can be rewritten as:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_1' = (1-\Delta x_1) U_{n_1m_1} + (1-\Delta x_2) U_{n_2m_2}.&#xD;&#xA;\end{equation}&#xD;&#xA;The terms $ \Delta x_1 $ and $ \Delta x_2 $ can be expressed as:&#xD;&#xA;\begin{align}&#xD;&#xA;\Delta x_1 = |x_i^s - {m_1}|\\&#xD;&#xA;\Delta x_2 = |x_i^s - {m_2}|,&#xD;&#xA;\end{align}&#xD;&#xA;which, substituted into the equation for $U_1'$ yields:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_1' = U_{n_1m_1}(1-|x_i^s - {m_1}|)  +  U_{n_2m_2}(1-|x_i^s - {m_2}|).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Similarly the value for $ U_2' $ can be computed:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_2' = U_{n_3m_3}(1-|x_i^s - {m_3}|)  +  U_{n_4m_4}(1-|x_i^s - {m_4}|).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Once $ U_1' $ and $ U_2' $ have been computed, $ V $ can be determined by linearly interpolating $ U_1' $ and $ U_2' $:&#xD;&#xA;\begin{equation}&#xD;&#xA;V =  U_1'(1-\Delta y_1) + U_2'(1-\Delta y_2) .&#xD;&#xA;\end{equation}&#xD;&#xA;The values for $ \Delta y_1 $ and $ \Delta y_2 $ can be expressed as follows:&#xD;&#xA;\begin{align}&#xD;&#xA;	\Delta y_1 = |y_i^s - y_{U_1'}| = |y_i^s - {n_1}| = |y_i^s - {n_2}|\\&#xD;&#xA;	\Delta y_2 = |y_i^s - y_{U_2'}| = |y_i^s - {n_3}| = |y_i^s - {n_4}| .&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Substituting the above equations and those of $\Delta x_1$ and $\Delta x_2$ into the equation for $V$ yields:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;V &amp;= U_{n_1m_1}\cdot (1-|x_i^s - {m_1}|) \cdot (1-|y_i^s - {n_1}|) \\&#xD;&#xA;&amp;+ U_{n_2m_2}\cdot (1-|x_i^s - {m_2}|) \cdot (1-|y_i^s - {n_2}|) \\&#xD;&#xA;&amp;+ U_{n_3m_3}\cdot (1-|x_i^s - {m_3}|) \cdot (1-|y_i^s - {n_3}|) \\&#xD;&#xA;&amp;+ U_{n_4m_4}\cdot (1-|x_i^s - {m_4}|) \cdot (1-|y_i^s - {n_4}|),&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;which can be written more compactly as:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;V &amp;= \sum_{k=1}^{4} U_{n_km_k} \cdot (1-|x_i^s - {m_k}|) \cdot (1-|y_i^s - {n_k}|)\\&#xD;&#xA;&amp;=\sum_{n}^{H}\sum_{m}^{W} U_{nm} \cdot (1-|x_i^s - {m}|) \cdot (1-|y_i^s - {n}|).&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m5tiS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15474" PostHistoryTypeId="1" PostId="5657" RevisionGUID="d5201d01-dae8-4444-adef-96b60680740b" CreationDate="2017-09-29T11:26:31.540" UserId="7390" Text="Bilinear Interpolation" ContentLicense="CC BY-SA 3.0" />
  <row Id="15475" PostHistoryTypeId="3" PostId="5657" RevisionGUID="d5201d01-dae8-4444-adef-96b60680740b" CreationDate="2017-09-29T11:26:31.540" UserId="7390" Text="|image-processing|sampling|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15476" PostHistoryTypeId="5" PostId="5656" RevisionGUID="18102986-9255-4a64-be6e-5e0770eee98d" CreationDate="2017-09-29T11:35:28.233" UserId="2287" Comment="added 486 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4. The division by pi belongs to the specular reflectivity coefficient/reflectance (similar to the division by pi in the diffuse contribution for the diffuse reflectivity coefficient/reflectance).&#xD;&#xA;&#xD;&#xA;[Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;*Proceedings of the Eurographics Symposium on Rendering 2005*.][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[Rosana Montes, Carlos Ureña: An Overview of BRDF Models, *Technical Report*, 2012.][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15477" PostHistoryTypeId="5" PostId="5656" RevisionGUID="aa231b3b-412a-4b74-be25-1a5e3da350e5" CreationDate="2017-09-29T11:42:14.390" UserId="2287" Comment="added 486 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4. The division by pi belongs to the specular reflectivity coefficient/reflectance (similar to the division by pi in the diffuse contribution for the diffuse reflectivity coefficient/reflectance).&#xD;&#xA;&#xD;&#xA;[Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;*Proceedings of the Eurographics Symposium on Rendering 2005*.][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[Rosana Montes, Carlos Ureña: An Overview of BRDF Models, *Technical Report*, 2012.][4]&#xD;&#xA;&#xD;&#xA;It puzzles me, however, that there is no specular reflectivity coefficient/reflectance in the Cook-Torrance BRDF of this paper. The same formula is also present in:&#xD;&#xA;&#xD;&#xA;Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.&#xD;&#xA;&#xD;&#xA;whereas a Torrance-Sparrow BRDF, (Blinn-)Phong BRDF family, Ward BRDF family all have such a component.&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15478" PostHistoryTypeId="2" PostId="5658" RevisionGUID="ce8fb8e3-87b6-4fbf-a5cf-69bcaf88f44f" CreationDate="2017-09-29T14:38:00.140" UserId="2041" Text="I think the formula at the top only makes sense if $n$ and $m$ are pixel indices, i.e. row and column numbers from 0 to $H - 1$ and 0 to $W - 1$. This way, for the four surrounding pixels, the weight varies from 0 to 1.&#xD;&#xA;&#xD;&#xA; As a representation of the algorithm it's unnecessarily opaque, because you don't actually want to look at every pixel of the image and multiply most of them by zero.&#xD;&#xA;&#xD;&#xA;To implement it, you want to do something closer to your diagram, where you only look at the four surrounding pixel values, and sum just those four, multiplying each by $(1 - |x - m|)(1 - |y - n|)$. This is exactly how your four-line equation for $V$ (near the bottom of your question) expresses it, and the code should look most like this." ContentLicense="CC BY-SA 3.0" />
  <row Id="15479" PostHistoryTypeId="2" PostId="5659" RevisionGUID="13825bfc-2f7a-4a80-99d4-b7c694bb1240" CreationDate="2017-09-29T17:18:24.943" UserId="2287" Text="**Problem**&#xD;&#xA;&#xD;&#xA;`XMMATRIX` and `XMVECTOR` (which use `__m128` under the hood) require 16 byte alignment. The C++ compiler can automatically ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the stack, but can't ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the heap. In your specific situation (referring to the RasterTek tutorial), three member variables of your `D3DClass` class are declared to be of type `XMMATRIX` and you construct one instance of this `D3DClass` class on the heap by using the default `operator new` (due to the absence of custom one). Using the default `operator new` does not guarantee this 16 byte alignment. Even if your code would have run fine using the default `operator new`, you could still face this issue after adding some extra member variables in the future.&#xD;&#xA;&#xD;&#xA;**Solution 1**&#xD;&#xA;&#xD;&#xA;The most easy fix in this specific case, is allocate your `D3DClass` class instances on the stack instead of the heap. This, however, does not prevent you or future users of your code to allocate an instance on the stack instead.&#xD;&#xA;&#xD;&#xA;**Solution2**&#xD;&#xA;&#xD;&#xA;The programmers of the [DirectXMath](DirectXMath) library advise the general programmer audience to use `XMMATRIX` and `XMVECTOR` for calculations only, and not use them as containers for storing data (i.e. class member variables). For the latter, they advise to use `XMFLOAT4`, `XMFLOAT4x4`, etc. The latter structs do not impose the 16 byte alignment restriction and instances can simply be loaded in SIMD registers by using `XMLoadFloat4` for `XMVECTOR`, `XMLoadFloat4x4` for `XMMATRIX`, etc.&#xD;&#xA;&#xD;&#xA;**Solution 3**&#xD;&#xA;&#xD;&#xA;Ensure the 16 byte alignment by overwriting `operator new`/`operator delete`, `operator new[]`/`operator delete[]`. We declare a template class which does allows heap allocation with arbitrary alignment restrictions:&#xD;&#xA;&#xD;&#xA;    #include &lt;malloc.h&gt;&#xD;&#xA;&#xD;&#xA;    inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept {&#xD;&#xA;        return _aligned_malloc(size, alignment);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline void FreeAligned(void *ptr) noexcept {&#xD;&#xA;    	if (!ptr) {&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	_aligned_free(ptr);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    template&lt; typename DataT &gt;&#xD;&#xA;    struct AlignedData {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    	static void *operator new(size_t size) {&#xD;&#xA;    		const size_t alignment = __alignof(DataT);&#xD;&#xA;    			&#xD;&#xA;    		// __declspec(align) on DataT is required&#xD;&#xA;    		static_assert(alignment &gt; 8, &#xD;&#xA;    			&quot;AlignedData is only useful for types with &gt; 8 byte alignment.&quot;);&#xD;&#xA;    			&#xD;&#xA;    		void * const ptr = AllocAligned(size, alignment);&#xD;&#xA;    		if (!ptr) {&#xD;&#xA;    			throw std::bad_alloc();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return ptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete(void *ptr) noexcept {&#xD;&#xA;    		FreeAligned(ptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void *operator new[](size_t size) {&#xD;&#xA;    		return operator new(size);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete[](void *ptr) noexcept {&#xD;&#xA;    		operator delete(ptr);&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This code snippet is based on the [DirectXTK](https://github.com/Microsoft/DirectXTK) and is also included in my own [codebase](https://github.com/matt77hias/MAGE/blob/master/MAGE/MAGE/src/memory/allocation.hpp) (including documentation).&#xD;&#xA;&#xD;&#xA;This data structure can now be used as follows:&#xD;&#xA;&#xD;&#xA;    __declspec(align(16)) struct Transform final : public AlignedData&lt; Transform &gt; {&#xD;&#xA;        XMMATRIX m_transform;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A Transform structure can now be allocated on the heap with 16 byte alignment since our custom `operator new` will be invoked:&#xD;&#xA;&#xD;&#xA;    Transform transform = new Transform();&#xD;&#xA;&#xD;&#xA;If you use instances of Transform as member variables in your structs of classes, the alignment restrictions remain of course. So instead of having only alignment restrictions for `XMVECTOR` and `XMMATRIX`, you will have now alignment restrictions for `XMVECTOR`, `XMMATRIX` and `Transform`.&#xD;&#xA;&#xD;&#xA;**Smart Pointers Pitfalls**&#xD;&#xA;&#xD;&#xA;Be careful if you use `std::shared_ptr` and especially `std::make_shared`. The latter allocates the data block together with the control block without using customly defined allocators such as are custom `operator new`.&#xD;&#xA;&#xD;&#xA;This means that this method will not work:&#xD;&#xA;&#xD;&#xA;    template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::make_shared&lt; T &gt;(std::forward&lt; ConstructorArgsT &gt;(args)...);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;but you should rather use an explicit invocation of `operator new` (which is also the case for `std::make_unique`):&#xD;&#xA;&#xD;&#xA;	template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeAllocatedShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::shared_ptr&lt; T &gt;(new T(std::forward&lt; ConstructorArgsT &gt;(args)...));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`std::unique_ptr` and especially `std::make_unique` will work as intended since the latter explicitly calls `operator new` (due to the absence of a data block).&#xD;&#xA;&#xD;&#xA;**RasterTek**&#xD;&#xA;&#xD;&#xA;RasterTek's second series of D3D11 tutorials is a subset of RasterTek's first series of D3D11 tutorials;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15480" PostHistoryTypeId="5" PostId="5659" RevisionGUID="854fad13-01b5-405e-bfd0-c1c20515ac81" CreationDate="2017-09-29T17:31:04.610" UserId="2287" Comment="added 1012 characters in body" Text="**Problem**&#xD;&#xA;&#xD;&#xA;`XMMATRIX` and `XMVECTOR` (which use `__m128` under the hood) require 16 byte alignment. The C++ compiler can automatically ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the stack, but can't ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the heap. &#xD;&#xA;&#xD;&#xA;In your specific situation (referring to the RasterTek tutorial), three member variables of your `D3DClass` class are declared to be of type `XMMATRIX` and you construct one instance of this `D3DClass` class on the heap by using the default `operator new` (due to the absence of a custom one). Using the default `operator new` does not guarantee this 16 byte alignment. Even if your code would have run fine using the default `operator new`, you could still face this issue after adding some extra member variables in the future.&#xD;&#xA;&#xD;&#xA;**Solution 1**&#xD;&#xA;&#xD;&#xA;The most easy fix in this specific case, is to allocate your `D3DClass` class instances on the stack instead of on the heap. This, however, does not prevent you or future users of your code to allocate an instance on the stack instead. &#xD;&#xA;&#xD;&#xA;**Solution2**&#xD;&#xA;&#xD;&#xA;The programmers of the [DirectXMath](DirectXMath) library advise the general programmer audience to use `XMMATRIX` and `XMVECTOR` for calculations only, and to not use them as containers for storing persistent data (i.e. class member variables). For the latter, they advise to use `XMFLOAT4`, `XMFLOAT4x4`, etc. The latter structs do not impose the 16 byte alignment restriction and instances can simply be loaded in SIMD registers by using `XMLoadFloat4` for `XMVECTOR`, `XMLoadFloat4x4` for `XMMATRIX`, etc.&#xD;&#xA;&#xD;&#xA;**Solution 3**&#xD;&#xA;&#xD;&#xA;Ensure the 16 byte alignment by overwriting `operator new`/`operator delete`, `operator new[]`/`operator delete[]`. We declare a template class which does allow heap allocation with arbitrary alignment restrictions:&#xD;&#xA;&#xD;&#xA;    #include &lt;malloc.h&gt;&#xD;&#xA;&#xD;&#xA;    inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept {&#xD;&#xA;        return _aligned_malloc(size, alignment);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline void FreeAligned(void *ptr) noexcept {&#xD;&#xA;    	if (!ptr) {&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	_aligned_free(ptr);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    template&lt; typename DataT &gt;&#xD;&#xA;    struct AlignedData {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    	static void *operator new(size_t size) {&#xD;&#xA;    		const size_t alignment = __alignof(DataT);&#xD;&#xA;    			&#xD;&#xA;    		// __declspec(align) on DataT is required&#xD;&#xA;    		static_assert(alignment &gt; 8, &#xD;&#xA;    			&quot;AlignedData is only useful for types with &gt; 8 byte alignment.&quot;);&#xD;&#xA;    			&#xD;&#xA;    		void * const ptr = AllocAligned(size, alignment);&#xD;&#xA;    		if (!ptr) {&#xD;&#xA;    			throw std::bad_alloc();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return ptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete(void *ptr) noexcept {&#xD;&#xA;    		FreeAligned(ptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void *operator new[](size_t size) {&#xD;&#xA;    		return operator new(size);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete[](void *ptr) noexcept {&#xD;&#xA;    		operator delete(ptr);&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This code snippet is based on the [DirectXTK](https://github.com/Microsoft/DirectXTK) and is also included in my own [codebase](https://github.com/matt77hias/MAGE/blob/master/MAGE/MAGE/src/memory/allocation.hpp) (including documentation).&#xD;&#xA;&#xD;&#xA;This data structure can now be used as follows:&#xD;&#xA;&#xD;&#xA;    __declspec(align(16)) struct Transform final : public AlignedData&lt; Transform &gt; {&#xD;&#xA;        XMMATRIX m_transform;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A Transform structure can now be allocated on the heap with 16 byte alignment, since our custom `operator new` will now be invoked:&#xD;&#xA;&#xD;&#xA;    Transform transform = new Transform();&#xD;&#xA;&#xD;&#xA;If you use instances of the `Transform` struct as member variables in other structs of classes, the alignment restrictions remain of course. So instead of having only alignment restrictions for `XMVECTOR` and `XMMATRIX`, you will have now alignment restrictions for `XMVECTOR`, `XMMATRIX` and `Transform`.&#xD;&#xA;&#xD;&#xA;**Smart Pointers Pitfalls**&#xD;&#xA;&#xD;&#xA;Be careful if you use `std::shared_ptr` and especially `std::make_shared`. The latter allocates the data block together with the control block without using customly defined allocators such as are custom `operator new`.&#xD;&#xA;&#xD;&#xA;This means that this method will not work:&#xD;&#xA;&#xD;&#xA;    template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::make_shared&lt; T &gt;(std::forward&lt; ConstructorArgsT &gt;(args)...);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;but you should rather use an explicit invocation of `operator new` (which is also the case for `std::make_unique`):&#xD;&#xA;&#xD;&#xA;	template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeAllocatedShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::shared_ptr&lt; T &gt;(new T(std::forward&lt; ConstructorArgsT &gt;(args)...));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`std::unique_ptr` and especially `std::make_unique` will work as intended since the latter explicitly calls `operator new` (due to the absence of a data block).&#xD;&#xA;&#xD;&#xA;**RasterTek**&#xD;&#xA;&#xD;&#xA;[RasterTek's second series of D3D11 tutorials](http://www.rastertek.com/tutdx11s2.html) is a subset of [RasterTek's first series of D3D11 tutorials](http://www.rastertek.com/tutdx11.html) with the minor difference that the latter uses the obsolete `D3DXMath`. The [transition](https://blogs.msdn.microsoft.com/chuckw/2013/08/20/living-without-d3dx/) is actually from D3DXMath to DirectXMath is actually pretty straightforward. Therefore, it can be interesting to take a look at the first series as well (which I ported to `Visual Studio 2017`, run fine in both `Debug` and `Release` configurations, and can be founded as well in this [repository](https://github.com/matt77hias/RasterTek)).&#xD;&#xA;&#xD;&#xA;If you want to stick to `DirectXMath`, you can also take a look at the D3D11 tutorials of Microsoft itself ([explanation](https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef) + [code](https://github.com/walbourn/directx-sdk-samples/tree/master/Direct3D11Tutorials)). (I also created a [repository](https://github.com/matt77hias/Direct3D-11-Projects) with some code refactors of these tutorials)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15481" PostHistoryTypeId="5" PostId="5659" RevisionGUID="e68e761f-f9fc-43a0-b166-707b9e009e2b" CreationDate="2017-09-29T17:36:25.263" UserId="2287" Comment="added 3 characters in body" Text="**Problem**&#xD;&#xA;&#xD;&#xA;`XMMATRIX` and `XMVECTOR` (which use `__m128` under the hood) require 16 byte alignment. The C++ compiler can automatically ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the stack, but can't ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the heap. &#xD;&#xA;&#xD;&#xA;In your specific situation (referring to the RasterTek tutorial), three member variables of your `D3DClass` class are declared to be of type `XMMATRIX` and you construct one instance of this `D3DClass` class on the heap by using the default `operator new` (due to the absence of a custom one). Using the default `operator new` does not guarantee this 16 byte alignment. Even if your code would have run fine using the default `operator new`, you could still face this issue after adding some extra member variables in the future.&#xD;&#xA;&#xD;&#xA;**Solution 1**&#xD;&#xA;&#xD;&#xA;The most easy fix in this specific case, is to allocate your `D3DClass` class instances on the stack instead of on the heap. This, however, does not prevent you or future users of your code to allocate an instance on the stack instead. &#xD;&#xA;&#xD;&#xA;**Solution2**&#xD;&#xA;&#xD;&#xA;The programmers of the [DirectXMath](DirectXMath) library advise the general programmer audience to use `XMMATRIX` and `XMVECTOR` for calculations only, and to not use them as containers for storing persistent data (i.e. class member variables). For the latter, they advise to use `XMFLOAT4`, `XMFLOAT4x4`, etc. The latter structs do not impose the 16 byte alignment restriction and instances can simply be loaded in SIMD registers by using `XMLoadFloat4` for `XMVECTOR`, `XMLoadFloat4x4` for `XMMATRIX`, etc.&#xD;&#xA;&#xD;&#xA;**Solution 3**&#xD;&#xA;&#xD;&#xA;Ensure the 16 byte alignment by overwriting `operator new`/`operator delete`, `operator new[]`/`operator delete[]`. We declare a template class which does allow heap allocation with arbitrary alignment restrictions:&#xD;&#xA;&#xD;&#xA;    #include &lt;malloc.h&gt;&#xD;&#xA;&#xD;&#xA;    inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept {&#xD;&#xA;        return _aligned_malloc(size, alignment);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline void FreeAligned(void *ptr) noexcept {&#xD;&#xA;    	if (!ptr) {&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	_aligned_free(ptr);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    template&lt; typename DataT &gt;&#xD;&#xA;    struct AlignedData {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    	static void *operator new(size_t size) {&#xD;&#xA;    		const size_t alignment = __alignof(DataT);&#xD;&#xA;    			&#xD;&#xA;    		// __declspec(align) on DataT is required&#xD;&#xA;    		static_assert(alignment &gt; 8, &#xD;&#xA;    			&quot;AlignedData is only useful for types with &gt; 8 byte alignment.&quot;);&#xD;&#xA;    			&#xD;&#xA;    		void * const ptr = AllocAligned(size, alignment);&#xD;&#xA;    		if (!ptr) {&#xD;&#xA;    			throw std::bad_alloc();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return ptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete(void *ptr) noexcept {&#xD;&#xA;    		FreeAligned(ptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void *operator new[](size_t size) {&#xD;&#xA;    		return operator new(size);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete[](void *ptr) noexcept {&#xD;&#xA;    		operator delete(ptr);&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This code snippet is based on the [DirectXTK](https://github.com/Microsoft/DirectXTK) and is also included in my own [codebase](https://github.com/matt77hias/MAGE/blob/master/MAGE/MAGE/src/memory/allocation.hpp) (including documentation).&#xD;&#xA;&#xD;&#xA;This data structure can now be used as follows:&#xD;&#xA;&#xD;&#xA;    __declspec(align(16)) struct Transform final : public AlignedData&lt; Transform &gt; {&#xD;&#xA;        XMMATRIX m_transform;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A Transform structure can now be allocated on the heap with 16 byte alignment, since our custom `operator new` will now be invoked:&#xD;&#xA;&#xD;&#xA;    Transform transform = new Transform();&#xD;&#xA;&#xD;&#xA;If you use instances of the `Transform` struct as member variables in other structs of classes, the alignment restrictions remain of course. So instead of having only alignment restrictions for `XMVECTOR` and `XMMATRIX`, you will have now alignment restrictions for `XMVECTOR`, `XMMATRIX` and `Transform`.&#xD;&#xA;&#xD;&#xA;**Smart Pointer Pitfalls**&#xD;&#xA;&#xD;&#xA;Be careful if you use `std::shared_ptr` and especially `std::make_shared`. The latter allocates the data block together with the control block without using customly defined allocators such as are custom `operator new`.&#xD;&#xA;&#xD;&#xA;This means that this method will not work:&#xD;&#xA;&#xD;&#xA;    template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::make_shared&lt; T &gt;(std::forward&lt; ConstructorArgsT &gt;(args)...);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;but you should rather use an explicit invocation of `operator new` (which is also the case for `std::make_unique`):&#xD;&#xA;&#xD;&#xA;	template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeAllocatedShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::shared_ptr&lt; T &gt;(new T(std::forward&lt; ConstructorArgsT &gt;(args)...));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`std::unique_ptr` and especially `std::make_unique` will work as intended since the latter explicitly calls `operator new` (due to the absence of a control block).&#xD;&#xA;&#xD;&#xA;**RasterTek**&#xD;&#xA;&#xD;&#xA;[RasterTek's second series of D3D11 tutorials](http://www.rastertek.com/tutdx11s2.html) is a subset of [RasterTek's first series of D3D11 tutorials](http://www.rastertek.com/tutdx11.html) with the minor difference that the latter uses the obsolete `D3DXMath`. The [transition](https://blogs.msdn.microsoft.com/chuckw/2013/08/20/living-without-d3dx/) is from D3DXMath to DirectXMath is actually pretty straightforward. Therefore, it can be interesting to take a look at the first series as well (which I ported to `Visual Studio 2017`, run fine in both `Debug` and `Release` configurations, and can be founded as well in this [repository](https://github.com/matt77hias/RasterTek)).&#xD;&#xA;&#xD;&#xA;If you want to stick to `DirectXMath`, you can also take a look at the D3D11 tutorials of Microsoft itself ([explanation](https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef) + [code](https://github.com/walbourn/directx-sdk-samples/tree/master/Direct3D11Tutorials)). (I also created a [repository](https://github.com/matt77hias/Direct3D-11-Projects) with some code refactors of these tutorials)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15482" PostHistoryTypeId="5" PostId="5659" RevisionGUID="a18f0b32-3d43-4cd9-98e0-3ac0961e0ef2" CreationDate="2017-09-29T17:44:25.940" UserId="2287" Comment="added 6 characters in body" Text="**Problem**&#xD;&#xA;&#xD;&#xA;`XMMATRIX` and `XMVECTOR` (which use `__m128` under the hood) require 16 byte alignment. The C++ compiler can automatically ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the stack, but can't ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the heap. &#xD;&#xA;&#xD;&#xA;In your specific situation (referring to the RasterTek tutorial), three member variables of your `D3DClass` class are declared to be of type `XMMATRIX` and you construct one instance of this `D3DClass` class on the heap by using the default `operator new` (due to the absence of a custom one). Using the default `operator new` does not guarantee this 16 byte alignment. Even if your code would have run fine using the default `operator new`, you could still face this issue after adding some extra member variables in the future.&#xD;&#xA;&#xD;&#xA;**Solution 1**&#xD;&#xA;&#xD;&#xA;The most easy fix in this specific case, is to allocate your `D3DClass` class instances on the stack instead of on the heap. This, however, does not prevent you or future users of your code to allocate an instance on the stack instead. &#xD;&#xA;&#xD;&#xA;**Solution2**&#xD;&#xA;&#xD;&#xA;The programmers of the [DirectXMath](DirectXMath) library advise the general programmer audience to use `XMMATRIX` and `XMVECTOR` for calculations only, and to not use them as containers for storing persistent data (i.e. class member variables). For the latter, they advise to use `XMFLOAT4`, `XMFLOAT4x4`, etc. The latter structs do not impose the 16 byte alignment restriction and their instances can simply be loaded in SIMD registers by using `XMLoadFloat4` for `XMVECTOR`, `XMLoadFloat4x4` for `XMMATRIX`, etc.&#xD;&#xA;&#xD;&#xA;**Solution 3**&#xD;&#xA;&#xD;&#xA;Ensure the 16 byte alignment by overwriting `operator new`/`operator delete`, `operator new[]`/`operator delete[]`. We declare a template class which does allow heap allocation with arbitrary alignment restrictions:&#xD;&#xA;&#xD;&#xA;    #include &lt;malloc.h&gt;&#xD;&#xA;&#xD;&#xA;    inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept {&#xD;&#xA;        return _aligned_malloc(size, alignment);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline void FreeAligned(void *ptr) noexcept {&#xD;&#xA;    	if (!ptr) {&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	_aligned_free(ptr);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    template&lt; typename DataT &gt;&#xD;&#xA;    struct AlignedData {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    	static void *operator new(size_t size) {&#xD;&#xA;    		const size_t alignment = __alignof(DataT);&#xD;&#xA;    			&#xD;&#xA;    		// __declspec(align) on DataT is required&#xD;&#xA;    		static_assert(alignment &gt; 8, &#xD;&#xA;    			&quot;AlignedData is only useful for types with &gt; 8 byte alignment.&quot;);&#xD;&#xA;    			&#xD;&#xA;    		void * const ptr = AllocAligned(size, alignment);&#xD;&#xA;    		if (!ptr) {&#xD;&#xA;    			throw std::bad_alloc();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return ptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete(void *ptr) noexcept {&#xD;&#xA;    		FreeAligned(ptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void *operator new[](size_t size) {&#xD;&#xA;    		return operator new(size);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete[](void *ptr) noexcept {&#xD;&#xA;    		operator delete(ptr);&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This code snippet is based on the [DirectXTK](https://github.com/Microsoft/DirectXTK) and is also included in my own [codebase](https://github.com/matt77hias/MAGE/blob/master/MAGE/MAGE/src/memory/allocation.hpp) (including documentation).&#xD;&#xA;&#xD;&#xA;This data structure can now be used as follows:&#xD;&#xA;&#xD;&#xA;    __declspec(align(16)) struct Transform final : public AlignedData&lt; Transform &gt; {&#xD;&#xA;        XMMATRIX m_transform;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A Transform structure can now be allocated on the heap with 16 byte alignment, since our custom `operator new` will now be invoked:&#xD;&#xA;&#xD;&#xA;    Transform transform = new Transform();&#xD;&#xA;&#xD;&#xA;If you use instances of the `Transform` struct as member variables in other structs of classes, the alignment restrictions remain of course. So instead of having only alignment restrictions for `XMVECTOR` and `XMMATRIX`, you will have now alignment restrictions for `XMVECTOR`, `XMMATRIX` and `Transform`.&#xD;&#xA;&#xD;&#xA;**Smart Pointer Pitfalls**&#xD;&#xA;&#xD;&#xA;Be careful if you use `std::shared_ptr` and especially `std::make_shared`. The latter allocates the data block together with the control block without using customly defined allocators such as are custom `operator new`.&#xD;&#xA;&#xD;&#xA;This means that this method will not work:&#xD;&#xA;&#xD;&#xA;    template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::make_shared&lt; T &gt;(std::forward&lt; ConstructorArgsT &gt;(args)...);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;but you should rather use an explicit invocation of `operator new` (which is also the case for `std::make_unique`):&#xD;&#xA;&#xD;&#xA;	template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeAllocatedShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::shared_ptr&lt; T &gt;(new T(std::forward&lt; ConstructorArgsT &gt;(args)...));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`std::unique_ptr` and especially `std::make_unique` will work as intended since the latter explicitly calls `operator new` (due to the absence of a control block).&#xD;&#xA;&#xD;&#xA;**RasterTek**&#xD;&#xA;&#xD;&#xA;[RasterTek's second series of D3D11 tutorials](http://www.rastertek.com/tutdx11s2.html) is a subset of [RasterTek's first series of D3D11 tutorials](http://www.rastertek.com/tutdx11.html) with the minor difference that the latter uses the obsolete `D3DXMath`. The [transition](https://blogs.msdn.microsoft.com/chuckw/2013/08/20/living-without-d3dx/) is from D3DXMath to DirectXMath is actually pretty straightforward. Therefore, it can be interesting to take a look at the first series as well (which I ported to `Visual Studio 2017`, run fine in both `Debug` and `Release` configurations, and can be founded as well in this [repository](https://github.com/matt77hias/RasterTek)).&#xD;&#xA;&#xD;&#xA;If you want to stick to `DirectXMath`, you can also take a look at the D3D11 tutorials of Microsoft itself ([explanation](https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef) + [code](https://github.com/walbourn/directx-sdk-samples/tree/master/Direct3D11Tutorials)). (I also created a [repository](https://github.com/matt77hias/Direct3D-11-Projects) with some code refactors of these tutorials)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15483" PostHistoryTypeId="5" PostId="5659" RevisionGUID="b11f086b-50de-43b0-9d3c-e77a03a52e4d" CreationDate="2017-09-30T10:01:20.793" UserId="2287" Comment="added 58 characters in body" Text="**Problem**&#xD;&#xA;&#xD;&#xA;`XMMATRIX` and `XMVECTOR` (which use [`__m128`](https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx) under the hood) require 16 byte alignment. The C++ compiler can automatically ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the stack, but can't ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the heap. &#xD;&#xA;&#xD;&#xA;In your specific situation (referring to the RasterTek tutorial), three member variables of your `D3DClass` class are declared to be of type `XMMATRIX` and you construct one instance of this `D3DClass` class on the heap by using the default `operator new` (due to the absence of a custom one). Using the default `operator new` does not guarantee this 16 byte alignment. Even if your code would have run fine using the default `operator new`, you could still face this issue after adding some extra member variables in the future.&#xD;&#xA;&#xD;&#xA;**Solution 1**&#xD;&#xA;&#xD;&#xA;The most easy fix in this specific case, is to allocate your `D3DClass` class instances on the stack instead of on the heap. This, however, does not prevent you or future users of your code to allocate an instance on the stack instead. &#xD;&#xA;&#xD;&#xA;**Solution2**&#xD;&#xA;&#xD;&#xA;The programmers of the [DirectXMath](DirectXMath) library advise the general programmer audience to use `XMMATRIX` and `XMVECTOR` for calculations only, and to not use them as containers for storing persistent data (i.e. class member variables). For the latter, they advise to use `XMFLOAT4`, `XMFLOAT4x4`, etc. The latter structs do not impose the 16 byte alignment restriction and their instances can simply be loaded in SIMD registers by using `XMLoadFloat4` for `XMVECTOR`, `XMLoadFloat4x4` for `XMMATRIX`, etc.&#xD;&#xA;&#xD;&#xA;**Solution 3**&#xD;&#xA;&#xD;&#xA;Ensure the 16 byte alignment by overwriting `operator new`/`operator delete`, `operator new[]`/`operator delete[]`. We declare a template class which does allow heap allocation with arbitrary alignment restrictions:&#xD;&#xA;&#xD;&#xA;    #include &lt;malloc.h&gt;&#xD;&#xA;&#xD;&#xA;    inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept {&#xD;&#xA;        return _aligned_malloc(size, alignment);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline void FreeAligned(void *ptr) noexcept {&#xD;&#xA;    	if (!ptr) {&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	_aligned_free(ptr);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    template&lt; typename DataT &gt;&#xD;&#xA;    struct AlignedData {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    	static void *operator new(size_t size) {&#xD;&#xA;    		const size_t alignment = __alignof(DataT);&#xD;&#xA;    			&#xD;&#xA;    		// __declspec(align) on DataT is required&#xD;&#xA;    		static_assert(alignment &gt; 8, &#xD;&#xA;    			&quot;AlignedData is only useful for types with &gt; 8 byte alignment.&quot;);&#xD;&#xA;    			&#xD;&#xA;    		void * const ptr = AllocAligned(size, alignment);&#xD;&#xA;    		if (!ptr) {&#xD;&#xA;    			throw std::bad_alloc();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return ptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete(void *ptr) noexcept {&#xD;&#xA;    		FreeAligned(ptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void *operator new[](size_t size) {&#xD;&#xA;    		return operator new(size);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete[](void *ptr) noexcept {&#xD;&#xA;    		operator delete(ptr);&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This code snippet is based on the [DirectXTK](https://github.com/Microsoft/DirectXTK) and is also included in my own [codebase](https://github.com/matt77hias/MAGE/blob/master/MAGE/MAGE/src/memory/allocation.hpp) (including documentation).&#xD;&#xA;&#xD;&#xA;This data structure can now be used as follows:&#xD;&#xA;&#xD;&#xA;    __declspec(align(16)) struct Transform final : public AlignedData&lt; Transform &gt; {&#xD;&#xA;        XMMATRIX m_transform;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A Transform structure can now be allocated on the heap with 16 byte alignment, since our custom `operator new` will now be invoked:&#xD;&#xA;&#xD;&#xA;    Transform *transform = new Transform();&#xD;&#xA;&#xD;&#xA;If you use instances of the `Transform` struct as member variables in other structs of classes, the alignment restrictions remain of course. So instead of having only alignment restrictions for `XMVECTOR` and `XMMATRIX`, you will have now alignment restrictions for `XMVECTOR`, `XMMATRIX` and `Transform`.&#xD;&#xA;&#xD;&#xA;**Smart Pointer Pitfalls**&#xD;&#xA;&#xD;&#xA;Be careful if you use `std::shared_ptr` and especially `std::make_shared`. The latter allocates the data block together with the control block without using customly defined allocators such as our custom `operator new`.&#xD;&#xA;&#xD;&#xA;This means that this method will not work:&#xD;&#xA;&#xD;&#xA;    template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::make_shared&lt; T &gt;(std::forward&lt; ConstructorArgsT &gt;(args)...);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;but you should rather use an explicit invocation of `operator new` (which is also the case for `std::make_unique`):&#xD;&#xA;&#xD;&#xA;	template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeAllocatedShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::shared_ptr&lt; T &gt;(new T(std::forward&lt; ConstructorArgsT &gt;(args)...));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`std::unique_ptr` and especially `std::make_unique` will work as intended since the latter explicitly calls `operator new` (due to the absence of a control block).&#xD;&#xA;&#xD;&#xA;**RasterTek**&#xD;&#xA;&#xD;&#xA;[RasterTek's second series of D3D11 tutorials](http://www.rastertek.com/tutdx11s2.html) is a subset of [RasterTek's first series of D3D11 tutorials](http://www.rastertek.com/tutdx11.html) with the minor difference that the latter uses the obsolete `D3DXMath`. The [transition](https://blogs.msdn.microsoft.com/chuckw/2013/08/20/living-without-d3dx/) is from D3DXMath to DirectXMath is actually pretty straightforward. Therefore, it can be interesting to take a look at the first series as well (which I ported to `Visual Studio 2017`, run fine in both `Debug` and `Release` configurations, and can be founded as well in this [repository](https://github.com/matt77hias/RasterTek)).&#xD;&#xA;&#xD;&#xA;If you want to stick to `DirectXMath`, you can also take a look at the D3D11 tutorials of Microsoft itself ([explanation](https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef) + [code](https://github.com/walbourn/directx-sdk-samples/tree/master/Direct3D11Tutorials)). (I also created a [repository](https://github.com/matt77hias/Direct3D-11-Projects) with some code refactors of these tutorials)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15484" PostHistoryTypeId="5" PostId="5657" RevisionGUID="c72be2af-eaa3-4ab8-b4ac-c18d4fabf737" CreationDate="2017-09-30T11:44:22.803" UserId="7390" Comment="added 2714 characters in body" Text="I am trying to implement bilinear interpolation as described in the paper **Spatial Tranformer Networks** by *Jaderberg et. al* (see [link to paper](https://arxiv.org/pdf/1506.02025.pdf)). They describe bilinear interpolation in Equation 5 as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;V_i^c = \sum_{n}^{H}\sum_{m}^{W} U_{nm}^c \max(0,1-|x_i^s - m|)\cdot\max(0,1-|y_i^s - n|),&#xD;&#xA;$$&#xD;&#xA;where:&#xD;&#xA;&#xD;&#xA;* $V_i^c$ is the resulting pixel value in the new image&#xD;&#xA;* $H$ and $W$ are the height and width of the original image (or feature map) in pixels&#xD;&#xA;* $c$ refers to the channel (e.g. RGB)&#xD;&#xA;* $(x_i^s, y_i^s)$ are the coordinates where the original image is sampled (where the image is normalized such that $-1 \le x_i^s, y_i^s\le 1$)&#xD;&#xA;* $U_{nm}^c$ is defined as the pixel value at location $(n,m)$ in channel $c$.&#xD;&#xA;&#xD;&#xA;I am having trouble interpreting the variables $n$ and $m$. Are these&#xD;&#xA;&#xD;&#xA;* coordinates in the normalized image (i.e. $-1 \le n, m\le 1$, where you would sum $n$ from $n=-1$ to $H=1$ in steps of the normalized resolution, e.g. steps of $1/100$ for an image that is 100 px in height)&#xD;&#xA;* or are these row and column values (e.g. you sum $n$ from $n=0$ to $n=100$ for an image that is 100px in height)?&#xD;&#xA;&#xD;&#xA;I have tried out both to do downsampling of an image, but don't get consistent results.&#xD;&#xA;&#xD;&#xA;If someone can help me out interpreting this, I would appreciate it very much.&#xD;&#xA;&#xD;&#xA;Below I have included what I understand of bilinear interpolation. Maybe that someone can help me out based on this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;In the below figure, a single channel feature map (or image) with one channel is displayed that consists of four pixels with values $ U_{nm} $, where $ n $ and $ m $ are the coordinates of the center of the pixels, i.e. $ m,n \in \{-0.5, 0.5\} $. If we index $ m $ and $ n $ as $ m_k, n_k $, with $ k \in [1,4] $, we can also index the pixel values as $ U_{n_km_k} $. The values of all four pixels can be reduced to a single value $ V $ at position $ (x_i^s, y_i^s) $ by applying bilinear interpolation.&#xD;&#xA;[![Bilinear Interpolation][1]][1]&#xD;&#xA;&#xD;&#xA;The procedure can be divided into three linear interpolations. First the value $ U_1' $ at position $ (x_{U_1'}, y_{U_1'}) $ can be computed by interpolating the values $ U_{n_1m_1} $ and $ U_{n_2m_2} $:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_1' = \Delta x_2\ U_{n_1m_1} + \Delta x_1\ U_{n_2m_2}.&#xD;&#xA;\end{equation}&#xD;&#xA;As the sum of $ \Delta x_1 $ and $ \Delta x_2 $ is equal to one, due to normalization of the axes, the above equation can be rewritten as:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_1' = (1-\Delta x_1) U_{n_1m_1} + (1-\Delta x_2) U_{n_2m_2}.&#xD;&#xA;\end{equation}&#xD;&#xA;The terms $ \Delta x_1 $ and $ \Delta x_2 $ can be expressed as:&#xD;&#xA;\begin{align}&#xD;&#xA;\Delta x_1 = |x_i^s - {m_1}|\\&#xD;&#xA;\Delta x_2 = |x_i^s - {m_2}|,&#xD;&#xA;\end{align}&#xD;&#xA;which, substituted into the equation for $U_1'$ yields:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_1' = U_{n_1m_1}(1-|x_i^s - {m_1}|)  +  U_{n_2m_2}(1-|x_i^s - {m_2}|).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Similarly the value for $ U_2' $ can be computed:&#xD;&#xA;\begin{equation}&#xD;&#xA;U_2' = U_{n_3m_3}(1-|x_i^s - {m_3}|)  +  U_{n_4m_4}(1-|x_i^s - {m_4}|).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Once $ U_1' $ and $ U_2' $ have been computed, $ V $ can be determined by linearly interpolating $ U_1' $ and $ U_2' $:&#xD;&#xA;\begin{equation}&#xD;&#xA;V =  U_1'(1-\Delta y_1) + U_2'(1-\Delta y_2) .&#xD;&#xA;\end{equation}&#xD;&#xA;The values for $ \Delta y_1 $ and $ \Delta y_2 $ can be expressed as follows:&#xD;&#xA;\begin{align}&#xD;&#xA;	\Delta y_1 = |y_i^s - y_{U_1'}| = |y_i^s - {n_1}| = |y_i^s - {n_2}|\\&#xD;&#xA;	\Delta y_2 = |y_i^s - y_{U_2'}| = |y_i^s - {n_3}| = |y_i^s - {n_4}| .&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Substituting the above equations and those of $\Delta x_1$ and $\Delta x_2$ into the equation for $V$ yields:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;V &amp;= U_{n_1m_1}\cdot (1-|x_i^s - {m_1}|) \cdot (1-|y_i^s - {n_1}|) \\&#xD;&#xA;&amp;+ U_{n_2m_2}\cdot (1-|x_i^s - {m_2}|) \cdot (1-|y_i^s - {n_2}|) \\&#xD;&#xA;&amp;+ U_{n_3m_3}\cdot (1-|x_i^s - {m_3}|) \cdot (1-|y_i^s - {n_3}|) \\&#xD;&#xA;&amp;+ U_{n_4m_4}\cdot (1-|x_i^s - {m_4}|) \cdot (1-|y_i^s - {n_4}|),&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;which can be written more compactly as:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;V &amp;= \sum_{k=1}^{4} U_{n_km_k} \cdot (1-|x_i^s - {m_k}|) \cdot (1-|y_i^s - {n_k}|)\\&#xD;&#xA;&amp;=\sum_{n}^{H}\sum_{m}^{W} U_{nm} \cdot (1-|x_i^s - {m}|) \cdot (1-|y_i^s - {n}|).&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;------&#xD;&#xA;&#xD;&#xA;**Edit to clarify my comment to @Dan Hulme**&#xD;&#xA;	&#xD;&#xA;Initially I also thought that $n$ and $m$ are row and column indices as you normally do a summation over integer values. Also the summation is up to $H$ and $W$, respectively, which are the # of rows and # of columns. So it seems logical to think that $\sum_{n=0}^{H = \#rows-1}\sum_{m=0}^{W = \#columns-1}$, with $n=0,1,2,...,H-1$ and $m=0,1,2,...,W-1$. &#xD;&#xA;&#xD;&#xA;However, when you try to apply this to an image which is larger than 2x2 pixels, it doesn't hold.&#xD;&#xA;&#xD;&#xA;To clarify this, imagine the original image is an 8x8 image and we wish to downsample the image to a 6x6 image (I cannot add a new image to expose this due to reputation constraints, I am new here). If we want to compute the value of the upper left pixel of the downsampled image with coordinates $(x_1^s, y_1^s) = (-0.833, 0.833)$, we would have:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;V_{1} &amp;= \sum_{n}^{H}\sum_{m}^{W} U_{nm}\cdot \max(0, 1-|x_1^s-m|)\cdot \max(0, 1-|y_1^s-n|) \\&#xD;&#xA;&amp;= U_{00}\cdot \max(0, 1-|-0.833-0|)\cdot \max(0, 1-|0.833-0|)\\&#xD;&#xA;&amp;+ U_{01}\cdot \max(0, 1-|-0.833-1|)\cdot \max(0, 1-|0.833-0|)\\&#xD;&#xA;&amp;+ U_{02}\cdot \max(0, 1-|-0.833-2|)\cdot \max(0, 1-|0.833-0|)\\&#xD;&#xA;&amp;+ ...\\&#xD;&#xA;&amp;+ U_{10}\cdot \max(0, 1-|-0.833-0|)\cdot \max(0, 1-|0.833-1|)\\&#xD;&#xA;&amp;+ U_{11}\cdot \max(0, 1-|-0.833-1|)\cdot \max(0, 1-|0.833-1|)\\&#xD;&#xA;&amp;+ ...\\&#xD;&#xA;&amp;+ U_{77}\cdot \max(0, 1-|-0.833-7|)\cdot \max(0, 1-|0.833-7|)\\&#xD;&#xA;&amp;= U_{00}\cdot 0.167^2 + U_{10}\cdot 0.167\cdot 0.833,&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;which is only a function of $U_{00}$ and $U_{10}$ and not of $U_{00}$, $U_{01}$, $U_{10}$ and $U_{11}$ as one would reason.&#xD;&#xA;&#xD;&#xA;If we reason abouth the lower right pixel of the downsampled image with coordinates $(x_{49}^s, y_{49}^s) = (0.833, -0.833)$ and apply the same equation, we have:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;V_{49} &amp;= \sum_{n}^{H}\sum_{m}^{W} U_{nm}\cdot \max(0, 1-|x_{49}^s-m|)\cdot \max(0, 1-|y_{49}^s-n|) \\&#xD;&#xA;&amp;= U_{00}\cdot \max(0, 1-|0.833-0|)\cdot \max(0, 1-|-0.833-0|)\\&#xD;&#xA;&amp;+ U_{01}\cdot \max(0, 1-|0.833-1|)\cdot \max(0, 1-|-0.833-0|)\\&#xD;&#xA;&amp;+ U_{02}\cdot \max(0, 1-|0.833-2|)\cdot \max(0, 1-|-0.833-0|)\\&#xD;&#xA;&amp;+ ...\\&#xD;&#xA;&amp;+ U_{10}\cdot \max(0, 1-|0.833-0|)\cdot \max(0, 1-|-0.833-1|)\\&#xD;&#xA;&amp;+ U_{11}\cdot \max(0, 1-|0.833-1|)\cdot \max(0, 1-|-0.833-1|)\\&#xD;&#xA;&amp;+ ...\\&#xD;&#xA;&amp;+ U_{77}\cdot \max(0, 1-|0.833-7|)\cdot \max(0, 1-|-0.833-7|)\\&#xD;&#xA;&amp;= U_{00}\cdot 0.167^2 + U_{01}\cdot 0.833\cdot 0.167,&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;which again is only function of $U_{00}$ and $U_{01}$ and not of $U_{66}$, $U_{67}$, $U_{76}$ and $U_{77}$ as one would expect.&#xD;&#xA;&#xD;&#xA;I have also tried normalizing $n$ and $m$, such that $n =-1, -1+ 2/8, -1 +4/8, ..., 1$ (and similarly for $m$, but I end up with similar problems. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m5tiS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15488" PostHistoryTypeId="5" PostId="5553" RevisionGUID="8d8f9171-6662-45c2-b267-9fa9c1711484" CreationDate="2017-09-30T15:57:05.677" UserId="2654" Comment="added 3 characters in body" Text="Binding points (and other state) are still important when doing actual draw calls (stuff like VAOs, UBOs, SSBOs and programs are still bound). It's only bind-to-edit that was eschewed.&#xD;&#xA;&#xD;&#xA;In your case the most DSA way to do that would be: &#xD;&#xA;&#xD;&#xA;    glCreateBuffers(1, &amp;tbo);&#xD;&#xA;    glNamedBufferData(tbo,sizeof(data), nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15489" PostHistoryTypeId="2" PostId="5661" RevisionGUID="fcb536ab-1977-4a76-8c80-f3bea9187b73" CreationDate="2017-09-30T16:09:36.020" UserId="6" Text="&gt; I have tried doing glCear(GL_BACK_LEFT) between each iteration but it is not clearing, I'm wondering if I'm missing a line of code before the glClear, or if I'm calling it right. I think the problem is that the back buffer isn't clearing&#xD;&#xA;&#xD;&#xA;This comment of yours sheds some light on the matter. This function call doesn't do what you think it does and is actually wrong usage. The [`glClear`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClear.xhtml) function doesn't actually take the buffer identificator (that you give to `glDraw/ReadBuffer`) to clear rather than a mask of the general parts of the framebuffer to clear.&#xD;&#xA;&#xD;&#xA;The framebuffer usually consists of one or more color buffers, a possible depth buffer and a possible stencil buffer. Therefore you give `glClear` an ORed combination of the respective flags `GL_COLOR_BUFFER_BIT`, `GL_DEPTH_BUFFER_BIT` and `GL_STENCIL_BUFFER_BIT` and those buffers (of the currently specified draw buffer for the color buffer) are then cleared.&#xD;&#xA;&#xD;&#xA;So *after* setting the draw buffer with `glDrawBuffer` you call `glClear` to clear that. As said, the flags depend on what you want cleared (usually at least `GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT`, special algorithms notwithstanding)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15491" PostHistoryTypeId="2" PostId="5662" RevisionGUID="2706514f-71e1-4fac-8596-2d112d2150d6" CreationDate="2017-09-30T17:06:32.490" UserId="6" Text="While the other answers are giving possible techniques to achieve what you're looking for, rending your stuff into a texture is not always the best way if you need it as VBOs (i.e. vertex attributes) in the next render step (requiring either a read into a PBO and some index/coordinate/sizing magic or a vertex texture fetch).&#xD;&#xA;&#xD;&#xA;An approach that would more accurately represent your 2nd point and be better when you need a transformation *from* a buffer *into* a buffer would be what's called [**Transform Feedback**](https://www.khronos.org/opengl/wiki/Transform_Feedback) (or Stream Output in the DirectX world). However, this requires OpenGL 3/DirectX 10 hardware (however, not necessarily the GL4/DX11 needed for compute shaders). It's also a little less of a synchronization mess than compute shaders with arbitrary shader storage buffers when your use case is really just to transform a bunch of vertices/primitives into a nother bunch of vertices/primitives.&#xD;&#xA;&#xD;&#xA;It basically lets you **hook into the render pipeline after the vertex (or rather primitive) processing step and before the rasterization** and write out whatever per-vertex values you computed **directly into a buffer object** (that you can then use as vertex attributes in the next step). It therefore doesn't draw anything into the framebuffer either. You just specify a bunch of `varying/out` variables and how to format them into the buffer and bind a buffer to the corresponding binding point. You can also use a query to gather information of how many primtives were written (since a geometry shader could change that dynamically) or, in later versions, just render the results directly without any need for synchronization. For more details, see the above Wiki article.&#xD;&#xA;&#xD;&#xA;Together with the geometry shader (which TF hardware should have, too) and its abilities for changing the primtive type or removing/adding vertices, this makes a useful tool for transforming your geometry however you deem fit in preparation of further rendering stages. Of course, it **has to be evaluated if that really buys you anything** in the particular use-case, especially if you're really just doing a simple vertex transformation." ContentLicense="CC BY-SA 3.0" />
  <row Id="15492" PostHistoryTypeId="2" PostId="5663" RevisionGUID="cea42870-5f61-44e2-85bd-9cb186854a77" CreationDate="2017-09-30T18:09:39.607" UserId="6" Text="As you analyzed correctly, GPUs aren't particularly good at dynamically sized data structures. A common approach to situations like this is speparating the problem into multiple passes, first **computing the data in a rigid fashion and then compacting it** for further processing. Off the top of my head, one way to approach this would be:&#xD;&#xA;&#xD;&#xA;1. First disregard the sparseness and tiling and basically **just store a *full* boolean grid** where each pixel just stores if it is green or not, could basically just be a 0/1 uchar *per pixel*. Fortunately, since it's a post-processing step and you're not e.g. working on rendered geometry directly, you know that you don't need more storage for possible `true` fragments than the image resolution.&#xD;&#xA;&#xD;&#xA;2. Then perform a so-called **stream compaction** step, which is a common step in GPU computing where you basically compact the full array of flags into a tight array of indices (i.e. coordinates) of the actually set pixels. This is usually done by two sub-steps:&#xD;&#xA;&#xD;&#xA; 1. A ***scan*, basically a partial sum (specifically a *prefix sum*)**, that for each element computes the number of all the `true` values preceding it. This is actually the index of that value in the final compacted array.&#xD;&#xA;&#xD;&#xA; 2. The actual compaction step, which **writes each `true` value to the position it belongs at**, of course now storing its index in the original array rather than just its flag value.&#xD;&#xA;&#xD;&#xA; While still inherently dependent on the preceding/surrounding elements, these steps are rather easy and efficient to implement in a block-based manner in the usual GPU computing frameworks like CUDA/OpenCL or OpenGL/Direct3D Compute Shaders and there's many resources on optimized algorithms for doing that. If using CUDA, there might even be ready-made computing primitives available for that. For a good introduction, see [this GPU Gems article](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch39.html).&#xD;&#xA;&#xD;&#xA;The only problem left here is the tiling issue. Of course together with the compaction step you might also want to compute the **boundaries (i.e. start and end indices) of your individual tiles inside the big coordinate array**. But that should be integratable into the general stream compaction/prefix sum algorithm since that is already inherently block-based and maybe just using the tile size as actual block size in the stream compaction would be the easiest approach there, since the per-block sums of the `true` elements are already a by-product of the straight-forward approaches for block-based stream compaction (of course 32x32 tiles would be much cooler in this case ;-)).&#xD;&#xA;&#xD;&#xA;It might be further simplified by actually storing your tiles not in a 2D-grid rather than one tile after the other in a linear array already when doing the first analysis step of the pixels. On the other hand, it might also be evaluated how far the first step, which afterall just looks at a pixel and creates a boolean flag value could already be intergrated into the stream compaction step. But you can do all that once the general framework is up and running.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;But of course all this also depends on how you actually want to proceed with processing your found per-tile generated green pixels. This way you still end up with varying number of pixels in each tile, but at least they're laid out linearly in memeory and you alleviated the problem of that dynamic count on the generation of those per-tile lists, however you go about processing them now.&#xD;&#xA;&#xD;&#xA;An option you *might* also consider is simply ignoring all that and just restructuring the next processing step in a way that works on a sparse boolean array. This gives you a fixed number of pixels but a scattered layout of the data. As said, heavily depends on how you proceed with the data." ContentLicense="CC BY-SA 3.0" />
  <row Id="15493" PostHistoryTypeId="5" PostId="5663" RevisionGUID="f515ef4f-0217-4103-899b-384bc72a0049" CreationDate="2017-09-30T18:15:47.453" UserId="6" Comment="added 104 characters in body" Text="As you analyzed correctly, GPUs aren't particularly good at dynamically sized data structures. A common approach to situations like this is speparating the problem into multiple passes, first **computing the data in a rigid fashion and then compacting it** for further processing. Off the top of my head, one way to approach this would be:&#xD;&#xA;&#xD;&#xA;1. First disregard the sparseness and tiling and basically **just store a *full* boolean grid** where each pixel just stores if it is green or not, could basically just be a 0/1 uchar *per pixel*. Fortunately, since it's a post-processing step and you're not e.g. working on rendered geometry directly, you know that you don't need more storage for possible `true` fragments than the image resolution.&#xD;&#xA;&#xD;&#xA;2. Then perform a so-called **stream compaction** step, which is a common step in GPU computing where you basically compact the full array of flags into a tight array of indices (i.e. coordinates) of the actually set pixels. This is usually done by two sub-steps:&#xD;&#xA;&#xD;&#xA; 1. A ***scan*, basically a partial sum (specifically a *prefix sum*)**, that for each element computes the number of all the `true` values preceding it. This is actually the index of that value in the final compacted array.&#xD;&#xA;&#xD;&#xA; 2. The actual compaction step, which **writes each `true` value to the position it belongs at**, of course now storing its index in the original array rather than just its flag value.&#xD;&#xA;&#xD;&#xA; While still inherently dependent on the preceding/surrounding elements, these steps are rather easy and efficient to implement in a block-based manner in the usual GPU computing frameworks like CUDA/OpenCL or OpenGL/Direct3D Compute Shaders and there's many resources on optimized algorithms for doing that. If using CUDA, there might even be ready-made computing primitives available for that. For a good introduction, see [this GPU Gems article](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch39.html).&#xD;&#xA;&#xD;&#xA;The only problem left here is the tiling issue. Of course together with the compaction step you might also want to compute the **boundaries (i.e. start and end indices) of your individual tiles inside the big coordinate array**. But that should be integratable into the general stream compaction/prefix sum algorithm since that is already inherently block-based and maybe just using the tile size as actual block size in the stream compaction would be the easiest approach there, since the per-block sums of the `true` elements are already a by-product of the straight-forward approaches for block-based stream compaction (of course 32x32 tiles would be much cooler in this case ;-)).&#xD;&#xA;&#xD;&#xA;It might be further simplified by actually storing your tiles not in a 2D-grid rather than one tile after the other in a linear array already when doing the first analysis step of the pixels. On the other hand, it might also be evaluated how far the first step, which afterall just looks at a pixel and creates a boolean flag value could already be intergrated into the stream compaction step. But you can do all that once the general framework is up and running.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;But of course all this also depends on how you actually want to proceed with processing your found per-tile generated green pixels. This way you still end up with varying number of pixels in each tile, but at least they're laid out linearly in memeory and you alleviated the impact of that &quot;dynamicality&quot; on the generation of those per-tile lists, however you go about processing them now. But maybe all you want is just the sum of all green pixels or some avergae weight or their coordinates?&#xD;&#xA;&#xD;&#xA;An option you *might* also consider is simply ignoring all that and just restructuring the next processing step in a way that works on a sparse boolean array. This gives you a fixed number of pixels but a scattered layout of the data. As said, heavily depends on how you proceed with the data." ContentLicense="CC BY-SA 3.0" />
  <row Id="15497" PostHistoryTypeId="5" PostId="5411" RevisionGUID="0426bd69-5c78-4c8f-80cf-0eef3e74a35b" CreationDate="2017-09-30T20:52:18.293" UserId="6" Comment="Spelling and formatting issues." Text="I am working on a normal mapping. I need to have the ability to scale normal vectors to adjust the normal strength of the surface. Currently the way I am doing it basically shows plausible results. But I am still not sure that it's 100% correct and to my surprise I found no info on the web regarding this subject.&#xD;&#xA;So here is how I do that (my lightning is in camera space):&#xD;&#xA;&#xD;&#xA;**vertex shader:**&#xD;&#xA;&#xD;&#xA;    vec3 N = normalize(normalMatrix * a_normal); &#xD;&#xA;    vec3 T = normalize(normalMatrix * a_tangent.xyz) * nStrength;          &#xD;&#xA;    vec3 B = normalize(normalMatrix * (cross(a_normal, a_tangent.xyz) * a_tangent.w) ) * nStrength; &#xD;&#xA;&#xD;&#xA;    v_TBN =  mat3(T,B,N);&#xD;&#xA;&#xD;&#xA;normalMatrix - inverse-transpose of model-view matrix.&#xD;&#xA;&#xD;&#xA;The shading itself happens in the fragment shader.&#xD;&#xA;The only relevant part which is happening there is transforming normal from&#xD;&#xA;the texture with v_TBN varying:&#xD;&#xA;&#xD;&#xA; **Fragment shader:**   &#xD;&#xA;&#xD;&#xA;     vec3 GetNormal(){&#xD;&#xA;        vec3 n = texture(normalMap,uv).xyz;&#xD;&#xA;        n = normalize(n * 2.0 - 1.0);&#xD;&#xA;        return  normalize (v_TBN * n);&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;  So, as you can see, I scale tangent and bi-tangent vectors with nStrength scalar.That's the most optimal setup I figured out that gives most correct looking effect.Is this the right way to strengthen the normals?                 " ContentLicense="CC BY-SA 3.0" />
  <row Id="15498" PostHistoryTypeId="4" PostId="5411" RevisionGUID="0426bd69-5c78-4c8f-80cf-0eef3e74a35b" CreationDate="2017-09-30T20:52:18.293" UserId="6" Comment="Spelling and formatting issues." Text="Correct way to set normal strength" ContentLicense="CC BY-SA 3.0" />
  <row Id="15499" PostHistoryTypeId="24" PostId="5411" RevisionGUID="0426bd69-5c78-4c8f-80cf-0eef3e74a35b" CreationDate="2017-09-30T20:52:18.293" Comment="Proposed by 6 approved by 48, 182 edit id of 273" ContentLicense="CC BY-SA 3.0" />
  <row Id="15500" PostHistoryTypeId="2" PostId="5664" RevisionGUID="64c53ff1-b306-45d3-a435-167d50676657" CreationDate="2017-10-01T02:15:06.717" UserId="6806" Text="I am studying inverse kinematics.&#xD;&#xA;But I wonder the suggested equations.&#xD;&#xA;(The following equations are taken from 'Computer Animation Algorithms and Techniques Third Edition Page, 181')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To better control the kinematic model such as encouraging joint angle constraints, a control expression can be added to the pesudoinverse Jacobian solution. &#xD;&#xA;&#xD;&#xA;($J$ is Jacobian, $J^+ = J^T(JJ^T)^{-1} = (J^TJ)^{-1}J^T$, and I will explain $z$ later)&#xD;&#xA;&#xD;&#xA;The form for **the control expression** is the below eqution 5.25&#xD;&#xA;&#xD;&#xA;$ \theta = (J^+J - I)z\cdot\cdot\cdot\cdot(5.25) $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But, the $\theta$ is always zero vector because $J^+J = I$, so $\theta = \mathbf 0z$.&#xD;&#xA;&#xD;&#xA;The book said that a change to pose parameters in the form of Equation 5.25 does not add anything to the velocities, so the control expression can be added to the pseudoinverse Jacobian solution without chaining the given velocities to be satisfied. &#xD;&#xA;&#xD;&#xA;$ V = J\theta \\&#xD;&#xA;V = J(J^+J - I)z \\&#xD;&#xA;V = \mathbf0z \\&#xD;&#xA;V = \mathbf0 \cdot\cdot\cdot\cdot(5.26)$&#xD;&#xA;&#xD;&#xA;And the book defined $z$ (Equation (5.27)) to bias the solution toward specific joint angles.&#xD;&#xA;&#xD;&#xA;$z = \alpha_i(\theta_i - \theta_{ci})^2\cdot\cdot\cdot\cdot(5.27)$ where $\theta_i$ is the current joint angles, $\theta_{ci}$ are the desired joint angles, and $\alpha_i$ is joint gains.&#xD;&#xA;&#xD;&#xA;Finally, **The form of the conventional pseudoinverse** of the Jocobian added by **the contorol expression** is Equation 5.28.&#xD;&#xA;&#xD;&#xA;$\theta = J^+V + (J^+J - I)z \cdot\cdot\cdot\cdot(5.28)\\&#xD;&#xA;\theta = J^+(V + Jz) -z \\&#xD;&#xA;\theta = J^T[(JJ^T)^{-1}(V+Jz)] -z&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, I could not understand why the book derived the above equation. Because the equation 5.25 is  zero vector, the equation 5.28 of red part($\theta = J^+V + \color{red}{(J^+J - I)z}$) is zero vector and $z$ doesn't have any effect on the result. We just have $\theta = J^+V$, no difference from the real original conventional pseudoinverse.&#xD;&#xA;&#xD;&#xA;What is wrong with me?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15501" PostHistoryTypeId="1" PostId="5664" RevisionGUID="64c53ff1-b306-45d3-a435-167d50676657" CreationDate="2017-10-01T02:15:06.717" UserId="6806" Text="pseudoinverse Jacobian and adding more control in computer animation" ContentLicense="CC BY-SA 3.0" />
  <row Id="15502" PostHistoryTypeId="3" PostId="5664" RevisionGUID="64c53ff1-b306-45d3-a435-167d50676657" CreationDate="2017-10-01T02:15:06.717" UserId="6806" Text="|3d|transformations|vector-graphics|animation|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15503" PostHistoryTypeId="6" PostId="5664" RevisionGUID="aa934f53-9e59-43e8-8864-5ca5b8ebb133" CreationDate="2017-10-01T03:00:12.673" UserId="6806" Comment="edited tags" Text="|rendering|3d|transformations|vector-graphics|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15504" PostHistoryTypeId="6" PostId="5447" RevisionGUID="663e74f7-fae9-4fb5-919b-2f5808229631" CreationDate="2017-10-01T08:27:27.777" UserId="6" Comment="Fixed tags." Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15505" PostHistoryTypeId="24" PostId="5447" RevisionGUID="663e74f7-fae9-4fb5-919b-2f5808229631" CreationDate="2017-10-01T08:27:27.777" Comment="Proposed by 6 approved by 48, 100 edit id of 272" ContentLicense="CC BY-SA 3.0" />
  <row Id="15507" PostHistoryTypeId="5" PostId="5663" RevisionGUID="823097a9-7d8b-4d60-8507-25474e523769" CreationDate="2017-10-01T11:46:53.130" UserId="6" Comment="added 10 characters in body" Text="As you analyzed correctly, GPUs aren't particularly good at dynamically sized data structures. A common approach to situations like this is speparating the problem into multiple passes, first **computing the data in a rigid fashion and then compacting it** for further processing. Off the top of my head, one way to approach this would be:&#xD;&#xA;&#xD;&#xA;1. First disregard the sparseness and tiling and basically **just store a *full* boolean grid** where each pixel just stores if it is green or not, could basically just be a 0/1 uchar *per pixel*. Fortunately, since it's a post-processing step and you're not e.g. working on rendered geometry directly, you know that you don't need more storage for possible `true` fragments than the image resolution.&#xD;&#xA;&#xD;&#xA;2. Then perform a so-called **stream compaction** step, which is a common step in GPU computing where you basically compact the full array of flags into a tight array of indices (i.e. coordinates) of the actually set pixels. This is usually done by two sub-steps:&#xD;&#xA;&#xD;&#xA; 1. A ***scan*, basically a partial sum (specifically a *prefix sum*)**, that for each element computes the number of all the `true` values preceding it. This is actually the index of that value in the final compacted array.&#xD;&#xA;&#xD;&#xA; 2. The actual compaction step, which **writes each `true` value to the position it belongs at**, of course now storing its index in the original array rather than just its flag value.&#xD;&#xA;&#xD;&#xA; While still inherently dependent on the preceding/surrounding elements, these steps are rather easy and efficient to implement in a block-based manner in the usual GPU computing frameworks like CUDA/OpenCL or OpenGL/Direct3D Compute Shaders and there's many resources on optimized algorithms for doing that. If using CUDA, there might even be ready-made computing primitives available for that. For a good introduction, see [this GPU Gems article](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch39.html).&#xD;&#xA;&#xD;&#xA;The only problem left here is the tiling issue. Of course together with the compaction step you might also want to compute the **boundaries (i.e. start and end indices) of your individual tiles inside the big coordinate array**. But that should be integratable into the general stream compaction/prefix sum algorithm since that is already inherently block-based and maybe just using the tile size as actual block size in the stream compaction would be the easiest approach there, since the per-block sums of the `true` elements are already a by-product of the straight-forward approaches for block-based stream compaction (of course 32x32 tiles would be much cooler in this case ;-)).&#xD;&#xA;&#xD;&#xA;It might be further simplified by actually storing your tiles not in a 2D-grid rather than one tile after the other in a linear array already when doing the first analysis step of the pixels. On the other hand, it might also be evaluated how far the first step, which afterall just looks at a pixel and creates a boolean flag value could already be intergrated into the stream compaction step. But you can do all that once the general framework is up and running.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;But of course all this also depends on how you actually want to proceed with processing your found per-tile generated green pixels. This way you still end up with a varying number of pixels in each tile, but at least they're laid out linearly in memory and you alleviated the impact of that &quot;dynamicality&quot; on the generation of those per-tile lists, however you go about processing them now. But maybe all you want is just the sum of all green pixels or some avergae weight of their coordinates?&#xD;&#xA;&#xD;&#xA;An option you *might* also consider is simply ignoring all that and just restructuring the next processing step in a way that works on a sparse boolean array. This gives you a fixed number of pixels but a scattered layout of the relevant data. As said, heavily depends on how you proceed with the data." ContentLicense="CC BY-SA 3.0" />
  <row Id="15509" PostHistoryTypeId="50" PostId="4651" RevisionGUID="48cf5487-abc8-4f28-800d-b22855a4a690" CreationDate="2017-10-01T12:27:37.167" UserId="-1" />
  <row Id="15511" PostHistoryTypeId="2" PostId="5665" RevisionGUID="fa8b613e-169a-4db0-aa0c-b38e9206ef3b" CreationDate="2017-10-01T15:16:56.470" UserId="6" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[0,1]$ anyway, which you naturally get from a texture, using the common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = texValue.r + texValue.g / 256.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again, though.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated what if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[360];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 360; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 360.f) * TWO_PI);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_1D, 0, ..., GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[360]`) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360]$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int((angle &lt; 0.0) ? (angle + 360.0) : angle];" ContentLicense="CC BY-SA 3.0" />
  <row Id="15512" PostHistoryTypeId="5" PostId="5665" RevisionGUID="4f7c64eb-7a13-4e19-a2f9-1fadd8b041c4" CreationDate="2017-10-01T15:23:57.213" UserId="6" Comment="deleted 3 characters in body" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way you can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[0,1]$ anyway, which you naturally get from a texture, using the common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = texValue.r + texValue.g / 256.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated what if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[360];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 360; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 360.f) * TWO_PI);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_1D, 0, ..., GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[360]`) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360]$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int((angle &lt; 0.0) ? (angle + 360.0) : angle)];" ContentLicense="CC BY-SA 3.0" />
  <row Id="15513" PostHistoryTypeId="5" PostId="5665" RevisionGUID="ca9c5117-2106-49ec-90ec-61a3e10200af" CreationDate="2017-10-01T15:48:02.527" UserId="6" Comment="added 36 characters in body" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way you can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[-1,1]$ anyway, which you can naturally upscale from the normalized $[0,1]$ range of a common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated what if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[360];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 360; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 360.f) * TWO_PI);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_1D, 0, ..., GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[360]`) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360]$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int((angle &lt; 0.0) ? (angle + 360.0) : angle)];" ContentLicense="CC BY-SA 3.0" />
  <row Id="15514" PostHistoryTypeId="6" PostId="5664" RevisionGUID="9a047179-1fb6-42fd-bd30-f31e3cb5fe24" CreationDate="2017-10-01T15:48:51.317" UserId="6" Comment="Fixed tags." Text="|animation|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15515" PostHistoryTypeId="24" PostId="5664" RevisionGUID="9a047179-1fb6-42fd-bd30-f31e3cb5fe24" CreationDate="2017-10-01T15:48:51.317" Comment="Proposed by 6 approved by 100, 48 edit id of 274" ContentLicense="CC BY-SA 3.0" />
  <row Id="15516" PostHistoryTypeId="2" PostId="5666" RevisionGUID="1ca8bdb8-9b67-4f8e-8dc2-f92e9637a36d" CreationDate="2017-10-01T16:14:37.520" UserId="6" Text="It basically **gives *you* control of the semantics of the individual attribute indices**. This mostly pays off in bigger projects, where you have many different shaders which, however, often use rather common attributes, like e.g. positions or texture coordinates. With explicit attribute locations you can establish a semantic for those attributes and enforce that on *all your shaders*, e.g. positions are always in attribute 0, texture coordinates always in attribute 1, ...&#xD;&#xA;&#xD;&#xA;First, this has the advantage of not having to query the attribute index for *every shader*. Of course you could query it once and sotre it in e.g. a map from attribute names/semantics to indices, but establishing this beforehand is even better. And it brings us to the a much bigger advantage, without explicit attribute binding you **would have to bind vertex arrays of a model to the individual attribute channels not only for each model, but also *for each shader***, since your position array might go to attribute 0 in one shader and attribute 1 in another one.&#xD;&#xA;&#xD;&#xA;This is not only a huge hassle, but also basically **destroys the advtage of [Vertey Array Objects (VAO)](https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object)**, which are specfically there to capture all the vertex attribute state, including the enabled attribute indices and their buffer sources so that you can draw your object by just binding the VAO and calling a draw function. Without explicit attribute binding you would *still* have to renable/bind the individual arrays at least for each different shader you use. **With explicit attribute binding you know that your model's positions *always* go into attribute index 0**." ContentLicense="CC BY-SA 3.0" />
  <row Id="15517" PostHistoryTypeId="2" PostId="5667" RevisionGUID="21a1bb2b-e67e-4eb0-bce6-80e385c0523e" CreationDate="2017-10-01T17:24:39.123" UserId="6" Text="You're basically mixing up your spaces.&#xD;&#xA;&#xD;&#xA;If you look at the [documentation for `QVector3D::unproject`](http://doc.qt.io/qt-5/qvector3d.html#unproject), you see that it actually **expects coordinates in *window space***. And this makes sense, since you explicitly query the viewport (i.e. basically the windows *pixel* dimensions) and give that to the function.&#xD;&#xA;&#xD;&#xA;But with your ratio computation above you already transformed your coordinates from that space into normalized device space, i.e. the $[-1,1]$ cube. So this whole computation isn't necessary at all and is already done for you by `unproject`. If we assume that your viewport is your whole window, then all you need to do is put those pixel coordinates you clicked on into `unproject` (still accounting for the different Y-convention, though):&#xD;&#xA;&#xD;&#xA;    dir = QVector3D(event.x, height()-event.y, 0.); //in window space 0 = near, 1 = far&#xD;&#xA;    dir = dir.unproject(modelViewMatrix, projectionMatrix, vp);&#xD;&#xA;&#xD;&#xA;A problem is that you **don't easily know the window space coordinates of the camera position**, since it is in front of the near plane, but the transformation of $[0,1]$ to $[near,far]$ is non-linear. One way to overcome this would be to just unproject a point on the near plane (window-space Z = 0) as origin and the difference to the unproject of that point on the far plane as the direction.&#xD;&#xA;&#xD;&#xA;    QVector3D near(QVector3D(event.x, height()-event.y, 0.);&#xD;&#xA;    QVector3D far( QVector3D(event.x, height()-event.y, 1.);&#xD;&#xA;    origin = near.unproject(modelViewMatrix, projectionMatrix, vp);&#xD;&#xA;    dir = far.unproject(modelViewMatrix, projectionMatrix, vp) - origin;&#xD;&#xA;&#xD;&#xA;Or you compute `dir` just the same and don't unproject the origin at all, rather than just transforming the eye-space origin (which is conveniently $\mathbf{0}$) back into model space (assuming your modelview matrix isn't projective, which it really shouldn't be):&#xD;&#xA;&#xD;&#xA;    origin = QVector3D(modelViewMatrix.inverted() * QVector4D(0., 0., 0., 1.));&#xD;&#xA;    //origin = QVector3D(modelViewMatrix.inverted().column(3); //would work the same&#xD;&#xA;&#xD;&#xA;If your viewport is *not* the same as your window dimensions however, you need to fiddle with the mouse coordinates a little more. But the point is that &#xD;&#xA;&#xD;&#xA;# `unproject` expects window space (i.e. pixel) coordinates." ContentLicense="CC BY-SA 3.0" />
  <row Id="15518" PostHistoryTypeId="2" PostId="5668" RevisionGUID="6d1caff1-c74a-423b-b3fb-6dbd28fce9d7" CreationDate="2017-10-01T17:51:19.740" UserId="6" Text="You seem to do things more complicatedly than you need to, as adressed in the comments. What you actually want to do is simple the opposite of the normal render flow. Rather than drawing your mesh in world space and mapping the texture into it, **you draw it in texture space and map its vertices onto it** and let your graphics hardware worry about interpolation. I'll give the general outline here, as I honestly don't know the actual DirectX terms for the stuff here, but it should be easy to map onto real HLSL if you know your way around DirectX (which I'm sure you do when messing with Compute Shaders).&#xD;&#xA;&#xD;&#xA;You basically render into your output texture using an offscreen render target. You then render your mesh using its texture coordinates as positions rather than its model space vertices, which you just pass through to the pixel shader, where you finally transform them into screen space and write out as the pixel's colour:&#xD;&#xA;&#xD;&#xA;    [Vertex Shader]&#xD;&#xA;&#xD;&#xA;    PER VERTEX float2 uv;&#xD;&#xA;    PER VERTEX float4 v_point;&#xD;&#xA;&#xD;&#xA;    TO PS float4 modelPos;&#xD;&#xA;&#xD;&#xA;    void VSMain() {&#xD;&#xA;        CLIP_POSITION = uv;&#xD;&#xA;        modelPos = v_point;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [Pixel Shader]&#xD;&#xA;&#xD;&#xA;    CONSTANT float4x4 MVP;&#xD;&#xA;    CONSTANT float2 viewportSize;&#xD;&#xA;&#xD;&#xA;    FROM VS float4 modelPos;&#xD;&#xA;&#xD;&#xA;    void PSMain() {&#xD;&#xA;        float4 clipPos = MVP * modelPos;&#xD;&#xA;        float3 ndcPos = clipPos.xyz / clipPos.w;&#xD;&#xA;        float3 screenPos = float3(viewportSize * (screePos.xy * 0.5 + float2(0.5)), ndcPos.z);&#xD;&#xA;        OUT_COLOR = screenPos;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Feel free to adjust this to the realities of proper DirectX screen-space transformations and matrix multiplication orders, but the general idea should be clear." ContentLicense="CC BY-SA 3.0" />
  <row Id="15521" PostHistoryTypeId="5" PostId="5659" RevisionGUID="dab46c4e-8200-4807-a2d3-18bf68541609" CreationDate="2017-10-01T18:33:39.773" UserId="2287" Comment="added 624 characters in body" Text="**Problem**&#xD;&#xA;&#xD;&#xA;`XMMATRIX` and `XMVECTOR` (which use [`__m128`](https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx) under the hood) require 16 byte alignment. The C++ compiler can automatically ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the stack, but can't ensure this for `XMMATRIX` and `XMVECTOR` data allocated on the heap. &#xD;&#xA;&#xD;&#xA;In your specific situation (referring to the RasterTek tutorial), three member variables of your `D3DClass` class are declared to be of type `XMMATRIX` and you construct one instance of this `D3DClass` class on the heap by using the default `operator new` (due to the absence of a custom one). Using the default `operator new` does not guarantee this 16 byte alignment. Even if your code would have run fine using the default `operator new`, you could still face this issue after adding some extra member variables in the future.&#xD;&#xA;&#xD;&#xA;**Solution 1**&#xD;&#xA;&#xD;&#xA;The most easy fix in this specific case, is to allocate your `D3DClass` class instances on the stack instead of on the heap. This, however, does not prevent you or future users of your code to allocate an instance on the stack instead. &#xD;&#xA;&#xD;&#xA;**Solution2**&#xD;&#xA;&#xD;&#xA;The programmers of the [DirectXMath](DirectXMath) library advise the general programmer audience to use `XMMATRIX` and `XMVECTOR` for calculations only, and to not use them as containers for storing persistent data (i.e. class member variables). For the latter, they advise to use `XMFLOAT4`, `XMFLOAT4x4`, etc. The latter structs do not impose the 16 byte alignment restriction and their instances can simply be loaded in SIMD registers by using `XMLoadFloat4` for `XMVECTOR`, `XMLoadFloat4x4` for `XMMATRIX`, etc.&#xD;&#xA;&#xD;&#xA;&gt; However, often it is easier and more compact to avoid using `XMVECTOR`&#xD;&#xA;&gt; or `XMMATRIX` directly in a class or structure. Instead, make use of the&#xD;&#xA;&gt; `XMFLOAT3`, `XMFLOAT4`, `XMFLOAT4X3`, `XMFLOAT4X4`, and so on, as members of&#xD;&#xA;&gt; your structure. Further, you can use the Vector Loading and Vector&#xD;&#xA;&gt; Storage functions to move the data efficiently into `XMVECTOR` or&#xD;&#xA;&gt; `XMMATRIX` local variables, perform computations, and store the results.&#xD;&#xA;&gt; There are also streaming functions (`XMVector3TransformStream`,&#xD;&#xA;&gt; `XMVector4TransformStream`, and so on) that efficiently operate directly&#xD;&#xA;&gt; on arrays of these data types.&#xD;&#xA;&#xD;&#xA;**Solution 3**&#xD;&#xA;&#xD;&#xA;Ensure the 16 byte alignment by overwriting `operator new`/`operator delete`, `operator new[]`/`operator delete[]`. We declare a template class which does allow heap allocation with arbitrary alignment restrictions:&#xD;&#xA;&#xD;&#xA;    #include &lt;malloc.h&gt;&#xD;&#xA;&#xD;&#xA;    inline void *AllocAligned(size_t size, size_t alignment = 16) noexcept {&#xD;&#xA;        return _aligned_malloc(size, alignment);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline void FreeAligned(void *ptr) noexcept {&#xD;&#xA;    	if (!ptr) {&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	_aligned_free(ptr);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    template&lt; typename DataT &gt;&#xD;&#xA;    struct AlignedData {&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;    &#xD;&#xA;    	static void *operator new(size_t size) {&#xD;&#xA;    		const size_t alignment = __alignof(DataT);&#xD;&#xA;    			&#xD;&#xA;    		// __declspec(align) on DataT is required&#xD;&#xA;    		static_assert(alignment &gt; 8, &#xD;&#xA;    			&quot;AlignedData is only useful for types with &gt; 8 byte alignment.&quot;);&#xD;&#xA;    			&#xD;&#xA;    		void * const ptr = AllocAligned(size, alignment);&#xD;&#xA;    		if (!ptr) {&#xD;&#xA;    			throw std::bad_alloc();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return ptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete(void *ptr) noexcept {&#xD;&#xA;    		FreeAligned(ptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void *operator new[](size_t size) {&#xD;&#xA;    		return operator new(size);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	static void operator delete[](void *ptr) noexcept {&#xD;&#xA;    		operator delete(ptr);&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This code snippet is based on the [DirectXTK](https://github.com/Microsoft/DirectXTK) and is also included in my own [codebase](https://github.com/matt77hias/MAGE/blob/master/MAGE/MAGE/src/memory/allocation.hpp) (including documentation).&#xD;&#xA;&#xD;&#xA;This data structure can now be used as follows:&#xD;&#xA;&#xD;&#xA;    __declspec(align(16)) struct Transform final : public AlignedData&lt; Transform &gt; {&#xD;&#xA;        XMMATRIX m_transform;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;A Transform structure can now be allocated on the heap with 16 byte alignment, since our custom `operator new` will now be invoked:&#xD;&#xA;&#xD;&#xA;    Transform *transform = new Transform();&#xD;&#xA;&#xD;&#xA;If you use instances of the `Transform` struct as member variables in other structs of classes, the alignment restrictions remain of course. So instead of having only alignment restrictions for `XMVECTOR` and `XMMATRIX`, you will have now alignment restrictions for `XMVECTOR`, `XMMATRIX` and `Transform`.&#xD;&#xA;&#xD;&#xA;**Smart Pointer Pitfalls**&#xD;&#xA;&#xD;&#xA;Be careful if you use `std::shared_ptr` and especially `std::make_shared`. The latter allocates the data block together with the control block without using customly defined allocators such as our custom `operator new`.&#xD;&#xA;&#xD;&#xA;This means that this method will not work:&#xD;&#xA;&#xD;&#xA;    template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::make_shared&lt; T &gt;(std::forward&lt; ConstructorArgsT &gt;(args)...);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;but you should rather use an explicit invocation of `operator new` (which is also the case for `std::make_unique`):&#xD;&#xA;&#xD;&#xA;	template&lt; typename T, typename... ConstructorArgsT &gt;&#xD;&#xA;	inline std::shared_ptr&lt; T &gt; MakeAllocatedShared(ConstructorArgsT&amp;&amp;... args) {&#xD;&#xA;		return std::shared_ptr&lt; T &gt;(new T(std::forward&lt; ConstructorArgsT &gt;(args)...));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`std::unique_ptr` and especially `std::make_unique` will work as intended since the latter explicitly calls `operator new` (due to the absence of a control block).&#xD;&#xA;&#xD;&#xA;**RasterTek**&#xD;&#xA;&#xD;&#xA;[RasterTek's second series of D3D11 tutorials](http://www.rastertek.com/tutdx11s2.html) is a subset of [RasterTek's first series of D3D11 tutorials](http://www.rastertek.com/tutdx11.html) with the minor difference that the latter uses the obsolete `D3DXMath`. The [transition](https://blogs.msdn.microsoft.com/chuckw/2013/08/20/living-without-d3dx/) is from D3DXMath to DirectXMath is actually pretty straightforward. Therefore, it can be interesting to take a look at the first series as well (which I ported to `Visual Studio 2017`, run fine in both `Debug` and `Release` configurations, and can be founded as well in this [repository](https://github.com/matt77hias/RasterTek)).&#xD;&#xA;&#xD;&#xA;If you want to stick to `DirectXMath`, you can also take a look at the D3D11 tutorials of Microsoft itself ([explanation](https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Tutorial-Win32-829979ef) + [code](https://github.com/walbourn/directx-sdk-samples/tree/master/Direct3D11Tutorials)). (I also created a [repository](https://github.com/matt77hias/Direct3D-11-Projects) with some code refactors of these tutorials)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15522" PostHistoryTypeId="2" PostId="5669" RevisionGUID="7dfa7465-8b25-4d01-a7a3-e65d9e4873b5" CreationDate="2017-10-01T19:18:10.423" UserId="6" Text="As suggested in the comments, there's a few ways you might be able to reduce the geometry before merging it into the big mesh and sending it out for drawing.&#xD;&#xA;&#xD;&#xA;- First of all, you might **not want to draw cubes that are hidden behind other cubes**. While this is not a trivial thing to check, it becomes easier when we at least try to limit it to **cubes that are on the outer surface of the terrain** and the cubes are laid out in a **regular grid**. In this case you first of all make a regular grid storing a boolean flag for each coordinate where there's a cube. Then all you need to do is walk over that array and for each active cell check its neighbours' flags and only add it to the geometry when it doesn't have all 6 face-neighbours active too. You can even optimize this by checking only the 3 neighbours in the direction of the camera.&#xD;&#xA;&#xD;&#xA;- Another thing you can do is **frustum culling**, basically ignoring all cubes that are not inside the actual view volume, which amounts to just checking the cubes against the 6 planes of the viewing frustum.&#xD;&#xA;&#xD;&#xA;- What you also could do is perform basic **backface culling** yourself, and only adding the geometry of the 3 cube faces that actually face the camera.&#xD;&#xA;&#xD;&#xA;But all this only reduces the amount of geometry that you are generating and sending over for drawing. It does *not* do anything for reducing the actual computation you do to generate that geometry (rather on the contrary actually). It is not clear what exactly it is that's causing your script to take too long or acquire too many resources but I also don't know anything about Javascript or Ajax or whatever specific web-stuff you're doing.&#xD;&#xA;&#xD;&#xA;- Maybe it's possible to delegate all this to some kind of **background task that doesn't block** the main process. This way you might also be able to **process the whole file in smaller batches**, generating parts of the whole geometry and updating the display whenever you generated another batch.&#xD;&#xA;- The above method *might* help to reduce overall memory consumption *if* the amount of actually generated geometry is much less than those 11M cubes from the file and if the regular grid isn't too large either. But you actually only need 1 bit for every grid cell, making just 2MB for 256^3 grid and 128 MB for a 1024^3 grid. You might further reduce this by **tiling the grid space into smaller sub grids and processing these each**. However, this might require you to traverse the terrain file multiple times if that isn't already sorted appropriately.&#xD;&#xA;- Which brings us to the possibility of simply **restructuring your input file format** to better facilitate any of the above methods, like already sorting your cubes into spatial subgrids, or even storing a full boolean grid rather than a compact list of coordinates.&#xD;&#xA;&#xD;&#xA;This all really depends on *what* the bottleneck is here. But it should give you some general ideas of how you could approach this for optimization." ContentLicense="CC BY-SA 3.0" />
  <row Id="15523" PostHistoryTypeId="5" PostId="5669" RevisionGUID="31973a8e-f2e4-45dd-9452-7e4ba345ae0a" CreationDate="2017-10-01T20:39:57.980" UserId="6" Comment="added 114 characters in body" Text="As suggested in the comments, there's a few ways you might be able to reduce the geometry before merging it into the big mesh and sending it out for drawing.&#xD;&#xA;&#xD;&#xA;- First of all, you might **not want to draw cubes that are hidden behind other cubes**. While this is not a trivial thing to check, it becomes easier when we at least try to limit it to **cubes that are on the outer surface of the terrain** and the cubes are laid out in a **regular grid**. In this case you first of all make a regular grid storing a boolean flag for each coordinate where there's a cube. Then all you need to do is walk over that array and for each active cell check its neighbours' flags and only add it to the geometry when it doesn't have all 6 face-neighbours active too. You can even optimize this by checking only the 3 neighbours in the direction of the camera.&#xD;&#xA;&#xD;&#xA;- Another thing you can do is **frustum culling**, basically ignoring all cubes that are not inside the actual view volume, which amounts to just checking the cubes against the 6 planes of the viewing frustum.&#xD;&#xA;&#xD;&#xA;- What you also could do is perform basic **backface culling** yourself, and only adding the geometry of the 3 cube faces that actually face the camera (or better yet, combining it with the first point, the ones facing the camera and not having an active neighbour).&#xD;&#xA;&#xD;&#xA;But all this only reduces the amount of geometry that you are generating and sending over for drawing. It does *not* do anything for reducing the actual computation you do to generate that geometry (rather on the contrary actually). It is not clear what exactly it is that's causing your script to take too long or acquire too many resources but I also don't know anything about Javascript or Ajax or whatever specific web-stuff you're doing.&#xD;&#xA;&#xD;&#xA;- Maybe it's possible to delegate all this to some kind of **background task that doesn't block** the main process. This way you might also be able to **process the whole file in smaller batches**, generating parts of the whole geometry and updating the display whenever you generated another batch.&#xD;&#xA;- The above method *might* help to reduce overall memory consumption *if* the amount of actually generated geometry is much less than those 11M cubes from the file and if the regular grid isn't too large either. But you actually only need 1 bit for every grid cell, making just 2MB for 256^3 grid and 128 MB for a 1024^3 grid. You might further reduce this by **tiling the grid space into smaller sub grids and processing these each**. However, this might require you to traverse the terrain file multiple times if that isn't already sorted appropriately.&#xD;&#xA;- Which brings us to the possibility of simply **restructuring your input file format** to better facilitate any of the above methods, like already sorting your cubes into spatial subgrids, or even storing a full boolean grid rather than a compact list of coordinates.&#xD;&#xA;&#xD;&#xA;This all really depends on *what* the bottleneck is here. But it should give you some general ideas of how you could approach this for optimization." ContentLicense="CC BY-SA 3.0" />
  <row Id="15524" PostHistoryTypeId="5" PostId="5662" RevisionGUID="c6dfa422-674d-422b-a4ca-56b74a003f87" CreationDate="2017-10-01T21:57:57.203" UserId="6" Comment="added 2 characters in body" Text="While the other answers are giving possible techniques to achieve what you're looking for, rendering your stuff into a texture is not always the best way if you need it as VBOs (i.e. vertex attributes) in the next render step (requiring either a read into a PBO and some index/coordinate/sizing magic or a vertex texture fetch).&#xD;&#xA;&#xD;&#xA;An approach that would more accurately represent your 2nd point and be better when you need a transformation *from* a buffer *into* a buffer would be what's called [**Transform Feedback**](https://www.khronos.org/opengl/wiki/Transform_Feedback) (or Stream Output in the DirectX world). However, this requires OpenGL 3/DirectX 10 hardware (however, not necessarily the GL4/DX11 needed for compute shaders). It's also a little less of a synchronization mess than compute shaders with arbitrary shader storage buffers when your use case is really just to transform a bunch of vertices/primitives into a nother bunch of vertices/primitives.&#xD;&#xA;&#xD;&#xA;It basically lets you **hook into the render pipeline after the vertex (or rather primitive) processing step and before the rasterization** and write out whatever per-vertex values you computed **directly into a buffer object** (that you can then use as vertex attributes in the next step). It therefore doesn't draw anything into the framebuffer either. You just specify a bunch of `varying/out` variables and how to format them into the buffer and bind a buffer to the corresponding binding point. You can also use a query to gather information of how many primtives were written (since a geometry shader could change that dynamically) or, in later versions, just render the results directly without any need for synchronization. For more details, see the above Wiki article.&#xD;&#xA;&#xD;&#xA;Together with the geometry shader (which TF hardware should have, too) and its abilities for changing the primtive type or removing/adding vertices, this makes a useful tool for transforming your geometry however you deem fit in preparation of further rendering stages. Of course, it **has to be evaluated if that really buys you anything** in the particular use-case, especially if you're really just doing a simple vertex transformation." ContentLicense="CC BY-SA 3.0" />
  <row Id="15525" PostHistoryTypeId="5" PostId="5665" RevisionGUID="1b1d8c6a-a058-4f83-8b2d-569a07ab770e" CreationDate="2017-10-01T22:04:21.723" UserId="6" Comment="added 3 characters in body" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way you can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[-1,1]$ anyway, which you can naturally upscale from the normalized $[0,1]$ range of a common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[360];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 360; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 360.f) * TWO_PI);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_1D, 0, ..., GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[361]`) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360)$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int(((angle &lt; 0.0) ? (angle + 360.0) : angle) + 0.5)];" ContentLicense="CC BY-SA 3.0" />
  <row Id="15528" PostHistoryTypeId="5" PostId="5665" RevisionGUID="5f528e81-0e17-4889-b898-ac5ecf1a218d" CreationDate="2017-10-02T00:12:09.287" UserId="6" Comment="added 8 characters in body" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way you can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[-1,1]$ anyway, which you can naturally upscale from the normalized $[0,1]$ range of a common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[256];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 256; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 256.f) * TWO_PI);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_1D, 0, ..., 256, 0, GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[361]`) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360)$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int(((angle &lt; 0.0) ? (angle + 360.0) : angle) + 0.5)];" ContentLicense="CC BY-SA 3.0" />
  <row Id="15530" PostHistoryTypeId="5" PostId="5667" RevisionGUID="1aca17f8-c4a3-4cc4-8c39-f9b25e8b9abb" CreationDate="2017-10-02T10:24:15.617" UserId="6" Comment="added 288 characters in body" Text="You're basically mixing up your spaces.&#xD;&#xA;&#xD;&#xA;If you look at the [documentation for `QVector3D::unproject`](http://doc.qt.io/qt-5/qvector3d.html#unproject), you see that it actually **expects coordinates in *window space***. And this makes sense, since you explicitly query the viewport (i.e. basically the window's *pixel* dimensions) and give that to the function.&#xD;&#xA;&#xD;&#xA;But with your ratio computation above you already transformed your coordinates from that space into normalized device space, i.e. the $[-1,1]$ square. So this whole computation isn't necessary at all and is already done for you by `unproject`. Likewise are the near and far distances from world/eye space not the same in window space, which uses the normalized $[0,1]$ depth range. If we assume that your viewport is your whole window, then all you need to do is put those pixel coordinates you clicked on into `unproject` (still accounting for the different Y-convention, though):&#xD;&#xA;&#xD;&#xA;    dir = QVector3D(event.x, height()-event.y, 0.);    //in window space 0 = near, 1 = far&#xD;&#xA;    dir = dir.unproject(modelViewMatrix, projectionMatrix, vp);&#xD;&#xA;&#xD;&#xA;A problem is that you **don't easily know the window space coordinates of the camera position**, since it is in front of the near plane, but the transformation from $[0,1]$ to $[near,far]$ is non-linear. One way to overcome this would be to just unproject a point on the near plane (depth = 0) as origin and the difference to the unproject of that same point on the far plane (depth = 1) as the direction.&#xD;&#xA;&#xD;&#xA;    QVector3D near(QVector3D(event.x, height()-event.y, 0.);&#xD;&#xA;    QVector3D far( QVector3D(event.x, height()-event.y, 1.);&#xD;&#xA;    origin = near.unproject(modelViewMatrix, projectionMatrix, vp);&#xD;&#xA;    dir = far.unproject(modelViewMatrix, projectionMatrix, vp) - origin;&#xD;&#xA;&#xD;&#xA;Or you compute `dir` just the same and don't unproject the origin at all, rather than just transforming the eye-space origin (which is conveniently $\mathbf{0}$) back into model space (assuming your modelview matrix isn't projective, which it really shouldn't be, otherwise don't forget the W-division):&#xD;&#xA;&#xD;&#xA;    origin = QVector3D(modelViewMatrix.inverted() * QVector4D(0., 0., 0., 1.));&#xD;&#xA;    //origin = QVector3D(modelViewMatrix.inverted().column(3));    //would work the same&#xD;&#xA;&#xD;&#xA;If your viewport is *not* the same as your window dimensions however, you need to fiddle with the mouse coordinates a little more and transform them from the entire window into your viewport rect before unprojecting them. But the point is that &#xD;&#xA;&#xD;&#xA;# `unproject` expects window space (i.e. pixel) coordinates." ContentLicense="CC BY-SA 3.0" />
  <row Id="15531" PostHistoryTypeId="5" PostId="419" RevisionGUID="1390d938-444d-4a1b-9b71-92f184e3ea7c" CreationDate="2017-10-02T11:05:33.717" UserId="209" Comment="Replaced broken link with a working (but eventually paywalled)  link" Text="Just adding to [imallett's answer](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/404#404), it is true that increasing the number of accesses to different texture data in a shader will increase pressure on the GPU cache(s), but there are several other factors that can significantly influence the effect. It's also possibly complicated by the fact that, like CPU caches, there may be several layers of cache in a GPU, ie. Texture Unit &lt;= L0 &lt;= L1 &lt;= ..Memory&#xD;&#xA;&#xD;&#xA;**Avoid aliasing -&gt; Use MIP maps**&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If you have a scene that has minification of texture data, be it due to perspective or simple scaling and you aren't using MIP mapping, then you will get aliasing. This is not just going to produce visual artefacts; it is very likely to be a performance problem.&#xD;&#xA;&#xD;&#xA;As soon as you get aliasing, the address accesses to the texture will become incoherent which will not only end up thrashing the caches but introduce a lot of DRAM &quot;page breaks&quot; (more correctly, row breaks) which can be costly. MIP mapping helps reduce the incoherency.&#xD;&#xA;&#xD;&#xA;**Texture compression**&#xD;&#xA;-----------------------&#xD;&#xA;&#xD;&#xA;Perhaps a bit of an obvious option, but if you can use texture compression (e.g. DXTn|ETC*|PVRTC*|etc) targeting from 8bpp down to, say, 2bpp, you can greatly increase the effectiveness of the memory bandwidth/cache by factors of 4x through to 16x.&#xD;&#xA;Now I can't speak for all GPUs, but *some* texture compression schemes (e.g. those listed above) are so simple to decode in hardware, that the data *could* stay compressed throughout the entire cache hierarchy and only be decompressed in the texture unit, thus effectively multiplying the size of those caches. &#xD;&#xA;&#xD;&#xA;**Data size**&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;Obviously, some data, e.g. render targets used as texture data in subsequent renders, can't employ texture compression. Whenever you can, use the smallest pixel format that will do the job, i.e, if 32/16bpp (A)RGB will do, don't use 4x32 float formats!&#xD;&#xA;&#xD;&#xA;**Sparse access**&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;This is somewhat related to the aliasing example above, but we've seen cases where large render targets are created, but then only very sparsely sampled. Cache lines, be it in CPUs or GPUs, are quite long so if you are only using one pixel in each cache line, you will be wasting transfers.&#xD;&#xA;&#xD;&#xA;Also, WRT compressed textures, these achieve compression by effectively sharing data between a local region of texels. If you don't have coherent access then, apart from the memory footprint reduction, the compression probably won't help.&#xD;&#xA;&#xD;&#xA;**Dependent Texture Reads**&#xD;&#xA;---------------------------&#xD;&#xA;&#xD;&#xA;Not so much of a cache issue (well, unless the computed accesses are quite incoherent), but texture accesses that aren't directly defined by the UV coordinates supplied with vertices *might* be slower than those that are directly defined.&#xD;&#xA;&#xD;&#xA;**Tiled/Morton VS Strided textures**&#xD;&#xA;------------------------------------&#xD;&#xA;&#xD;&#xA;Although I suspect most textures these days will be stored in either a tiled or Morton-like (aka Twiddled/Swizzled) order (or even a combination of both), some textures *might* still be in scan-line order, which means that rotation of the texture is likely to lead to a significant number of cache misses/page breaks. Unfortunately, I don't really know how to spot if a particular format is arranged in such a way.&#xD;&#xA;&#xD;&#xA;(For background reading, try Blinn's [The Truth About Texture Mapping][1]. FWIW, taking that a few steps further led to the use of Twiddled-order (i.e. Morton order) textures in [at least some early PC hardware](http://worldwide.espacenet.com/publicationDetails/originalDocument?FT=D&amp;date=19960814&amp;DB=EPODOC&amp;locale=en_ep&amp;CC=GB&amp;NR=2297886A&amp;KC=A&amp;ND=4)). &#xD;&#xA;&#xD;&#xA;  [1]: http://ieeexplore.ieee.org/document/50676/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15532" PostHistoryTypeId="2" PostId="5671" RevisionGUID="0477b968-f11d-46ef-984d-2d4cbf3cb041" CreationDate="2017-10-02T11:57:02.027" UserId="6" Text="I think I found your misunderstanding, but it's IMHO based on a little inconsistency (or at least lack of clarity) in the book.&#xD;&#xA;&#xD;&#xA;&gt; But, the θ is always zero vector because J+J=I, so θ=0z.&#xD;&#xA;&#xD;&#xA;This is not true, $J^+J$ is not necessarily $I$. $JJ^+=I$ but the **multiplication by the pseudoinverse is *not* commutative**. Let's look at this in more detail:&#xD;&#xA;&#xD;&#xA;$JJ^+ = JJ^T(JJ^T)^{-1}= (JJ^T)(JJ^T)^{-1} = I$&#xD;&#xA;&#xD;&#xA;$J^+J = J^T(JJ^T)^{-1}J = ?$&#xD;&#xA;&#xD;&#xA;The underlying misunderstanding comes from the assumption that the matrices $J^T(JJ^T)^{-1}$ and $(J^TJ)^{-1}J^T$ are equal (since the latter *would* produce $I$ if right-multiplied by $J$), which is *not* true. They are **both pseudoinverses of $J$ but they are not necessarily the same matrices**, in fact they don't necessarily both *exist*.&#xD;&#xA;&#xD;&#xA;As the book says, the $(JJ^T)^{-1}$ only exists if the *rows* of $J$ are linearly independent, and in turn [Wikipedia](https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse#Definition) says that $(J^TJ)^{-1}$ exists if the *columns* of $J$ are linearly independent. However, they can't both exist if the matrix is not square, since one of the dimensions would necessarily have more vectors than the dimension, which can't all be linearly independent. Specifically, for a normal redundant joint system you probably have **more columns than rows, making only the pseudoinverse $J(JJ^T)^{-1}$ exist**.&#xD;&#xA;&#xD;&#xA;We can, however, see that for a square matrix they are indeed the same and actually the real inverse:&#xD;&#xA;&#xD;&#xA;$J^T(JJ^T)^{-1} = J^TJ^{-T}J^{-1} = (J^{-1}J)^TJ^{-1} = I^TJ^{-1} = J^{-1}$&#xD;&#xA;&#xD;&#xA;$(J^TJ)^{-1}J^T = J^{-1}J^{-T}J^T = J^{-1}(JJ^{-1})^T = J^{-1}I^T = J^{-1}$&#xD;&#xA;&#xD;&#xA;(But in that case the system would have a unique solution and there's no point to angle control anyway.) But you cannot resolve the brackets with a non-square matrix, since the **individual matrices aren't square and don't have an actual inverse**.&#xD;&#xA;&#xD;&#xA;But I understand why you are confused and I am a little, too, since Parent actually seems to use the *alleged* identity $J^T(JJ^T)^{-1}=(J^TJ)^{-1}J^T$ in equation 5.20, where he derives the pseudoinverse's relevance for solving the inverse kinematics problem. He computes everything with the *left inverse* but than concludes with using the *right inverse*. I guess that works conceptually because they're both pseudoinverses, even if it doesn't make complete mathematical sense (to me and you at least). He seemed to have used the assumption of a square matrix as a trick for transforming the problem and then used the conclusion for a non-square matrix, which *might* be conceptually correct.&#xD;&#xA;&#xD;&#xA;I guess it simply **doesn't matter *which* of the two pseudoinverses we use, since only *one* of them ever exists** (for a non-square Jacobian) anyway and if the left inverse *would* exist (making your above assumption true), that means you have more constraints than DoF and thus your system is overconstrained and there's no point in angle control." ContentLicense="CC BY-SA 3.0" />
  <row Id="15533" PostHistoryTypeId="2" PostId="5672" RevisionGUID="5fb6eb3b-b370-4c4b-88fd-c46acd00fd80" CreationDate="2017-10-02T14:17:47.420" UserId="6" Text="In a project where I want to select visible objects using using a screen-aligned polygon and various conditions for what &quot;selected&quot; means with regards to that polygon, I'm basically drawing the polygon into the stencil buffer and then drawing the individual objects with **stencil testing and using occlusion queries** for measuring how much the object and selection polygon overlap in screen space.&#xD;&#xA;&#xD;&#xA;This works pretty well. But imagine my surprise when stumbling over the statement that, [according to the OpenGL Wiki](https://www.khronos.org/opengl/wiki/Query_Object#Occlusion_queries), occlusion queries supposedly don't actually care about the stencil test:&#xD;&#xA;&#xD;&#xA;&gt; They detect whether the scoped drawing commands pass the depth test and if so, how many samples in those triangles passed the Depth Test. Note that the sample count and pass/fail are **based only on the depth test. The Stencil Test, or fragment shader discard is irrelevant** with queries, even though they technically happen after the fragment shader...&#xD;&#xA;&#xD;&#xA;This clearly contradicts my practical experience (I don't use any depth testing at all, i.e. always pass that) and made me a little worried/confused. I took a look at the specification (both the newest 4.6 core as well as good old 2.0, which we're actually targetting in our project for compatibility) and it also says that occlusion queries count the number of **samples passing the depth test**. It does however not make such a definite statement as the wiki pertaining to the stencil test. And since the **depth test technically comes *after* the stencil test**, I'm not entirely sure if that maybe already includes the stencil test anyway and the wording of the specification is simply using the last stage for convenience.&#xD;&#xA;&#xD;&#xA;So, my question is, *do* occlusion queries respect the stencil test (or any other earlier per-fragment tests, I'm actually using scissor testing with occlusion queries in another unrelated algorithm)? I see a few possiblities here:&#xD;&#xA;&#xD;&#xA;- They *do definitely* respect all tests and the wording in the spec is just using the last test for convenience reasons. This would mean that **fragments failing earlier tests and thus not even *reaching* the depth test would technically count as *failing* that**. I'm not sure this comes too clearly out of the specification's wording, though, but maybe I'm missing something and people better-versed in the intricacies of specification laywering can shed more light on this. This would also mean the above Wiki article is slightly misleading (or I just misread it).&#xD;&#xA;- They *definitely don't* respect the stencil test and really only care about the depth test. This would mean that a **fragment failing the stencil test would have to still go through depth testing**. It would also mean that what I experience on my specific hardware (it's an nVidia GeForce GTX 1xxx) is clearly a bug.&#xD;&#xA;- Or this might simply not be a well-specified part of the API and it leaves room for interpretation. This might be rather odd, though, as this isn't a particularly rarely used feature I'd suppose.&#xD;&#xA;&#xD;&#xA;(In practice, I could definitely restrucure my algorithm to use depth testing instead, but it is a problem that makes me curious about the theoretic implications and underpinnings nevertheless.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15534" PostHistoryTypeId="1" PostId="5672" RevisionGUID="5fb6eb3b-b370-4c4b-88fd-c46acd00fd80" CreationDate="2017-10-02T14:17:47.420" UserId="6" Text="Do occlusion queries respect the stencil test at all?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15535" PostHistoryTypeId="3" PostId="5672" RevisionGUID="5fb6eb3b-b370-4c4b-88fd-c46acd00fd80" CreationDate="2017-10-02T14:17:47.420" UserId="6" Text="|opengl|stencil-test|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15536" PostHistoryTypeId="2" PostId="5673" RevisionGUID="889acfba-a215-404d-a46f-57930cafa2e8" CreationDate="2017-10-02T15:34:51.003" UserId="2654" Text="The specification is very... odd on this point.&#xD;&#xA;&#xD;&#xA;It clearly states that occlusion queries happen after depth *and* stencil tests. However, it also states:&#xD;&#xA;&#xD;&#xA;&gt; Occlusion queries use query objects to track the number of fragments or samples that **pass the depth test**.&#xD;&#xA;&gt;&#xD;&#xA;&gt; When an occlusion query is active, the samples-passed count is incremented **for each fragment that passes the depth test**.&#xD;&#xA;&gt;&#xD;&#xA;&gt; When an occlusion query is started with the target `ANY_SAMPLES_PASSED`,&#xD;&#xA;the samples-boolean state maintained by the GL is set to `FALSE`. While that occlusion query is active, the samples-boolean state is set to `TRUE` if any fragment or sample **passes the depth test**.&#xD;&#xA;&#xD;&#xA;The standard always talks about this in terms of passing the depth test, *never* in terms of a fragment reaching this particular stage in the pipeline.&#xD;&#xA;&#xD;&#xA;By contrast, the Vulkan specification says:&#xD;&#xA;&#xD;&#xA;&gt; The occlusion query sample counter increments by one for each sample with a coverage value of 1 in each fragment that survives *all the per-fragment tests*, including scissor, sample mask, alpha to coverage, stencil, and depth tests.&#xD;&#xA;&#xD;&#xA;So clearly, Vulkan-class OpenGL hardware can use the stencil test in its counter. It's likely that this is just a long-time bug in the specification. But [until there is confirmation on that][1], I cannot change the Wiki article.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/OpenGL-API/issues/19" ContentLicense="CC BY-SA 3.0" />
  <row Id="15537" PostHistoryTypeId="12" PostId="5673" RevisionGUID="843395d9-d42b-4319-baa7-502204febf6d" CreationDate="2017-10-02T15:41:01.453" UserId="2654" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;}]}" />
  <row Id="15540" PostHistoryTypeId="5" PostId="5672" RevisionGUID="998c7b74-704c-4b01-8284-d9f6fb8a1672" CreationDate="2017-10-02T19:09:00.113" UserId="6" Comment="deleted 62 characters in body" Text="In a project where I want to select visible objects using using a screen-aligned polygon and various conditions for what &quot;selected&quot; means with regards to that polygon, I'm basically drawing the polygon into the stencil buffer and then drawing the individual objects with **stencil testing and using occlusion queries** for measuring how much the object and selection polygon overlap in screen space.&#xD;&#xA;&#xD;&#xA;This works pretty well. But imagine my surprise when stumbling over the statement that, [according to the OpenGL Wiki](https://www.khronos.org/opengl/wiki/Query_Object#Occlusion_queries), occlusion queries supposedly don't actually care about the stencil test:&#xD;&#xA;&#xD;&#xA;&gt; They detect whether the scoped drawing commands pass the depth test and if so, how many samples in those triangles passed the Depth Test. Note that the sample count and pass/fail are **based only on the depth test. The Stencil Test, or fragment shader discard is irrelevant** with queries, even though they technically happen after the fragment shader...&#xD;&#xA;&#xD;&#xA;This clearly contradicts my practical experience and made me a little worried/confused. I took a look at the specification (both the newest 4.6 core as well as good old 2.0, which we're actually targetting in our project for compatibility) and it also says that occlusion queries count the number of **samples passing the depth test**. It does however not make such a definite statement as the wiki pertaining to the stencil test. And since the **depth test technically comes *after* the stencil test**, I'm not entirely sure if that maybe already includes the stencil test anyway and the wording of the specification is simply using the last stage for convenience.&#xD;&#xA;&#xD;&#xA;So, my question is, *do* occlusion queries respect the stencil test (or any other earlier per-fragment tests, I'm actually using scissor testing with occlusion queries in another unrelated algorithm)? I see a few possiblities here:&#xD;&#xA;&#xD;&#xA;- They *do definitely* respect all tests and the wording in the spec is just using the last test for convenience reasons. This would mean that **fragments failing earlier tests and thus not even *reaching* the depth test would technically count as *failing* that**. I'm not sure this comes too clearly out of the specification's wording, though, but maybe I'm missing something and people better-versed in the intricacies of specification laywering can shed more light on this. This would also mean the above Wiki article is slightly misleading (or I just misread it).&#xD;&#xA;- They *definitely don't* respect the stencil test and really only care about the depth test. This would mean that a **fragment failing the stencil test would have to still go through depth testing**. It would also mean that what I experience on my specific hardware (it's an nVidia GeForce GTX 1xxx) is clearly a bug.&#xD;&#xA;- Or this might simply not be a well-specified part of the API and it leaves room for interpretation. This might be rather odd, though, as this isn't a particularly rarely used feature I'd suppose.&#xD;&#xA;&#xD;&#xA;(In practice, I could definitely restrucure my algorithm to use depth testing instead, but it is a problem that makes me curious about the theoretic implications and underpinnings nevertheless.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15542" PostHistoryTypeId="5" PostId="5671" RevisionGUID="69ae483e-c0f5-4552-bd45-dcb58d0e0389" CreationDate="2017-10-02T22:24:58.050" UserId="6" Comment="added 151 characters in body" Text="I think I found your misunderstanding, but it's IMHO based on a little inconsistency (or at least lack of clarity) in the book.&#xD;&#xA;&#xD;&#xA;&gt; But, the θ is always zero vector because J+J=I, so θ=0z.&#xD;&#xA;&#xD;&#xA;This is not true, $J^+J$ is not necessarily $I$. $JJ^+=I$ but the **multiplication by the pseudoinverse is *not* commutative**. Let's look at this in more detail:&#xD;&#xA;&#xD;&#xA;$JJ^+ = JJ^T(JJ^T)^{-1}= (JJ^T)(JJ^T)^{-1} = I$&#xD;&#xA;&#xD;&#xA;$J^+J = J^T(JJ^T)^{-1}J = ?$&#xD;&#xA;&#xD;&#xA;The underlying misunderstanding comes from the assumption that the matrices $J^T(JJ^T)^{-1}$ and $(J^TJ)^{-1}J^T$ are equal (since the latter *would* produce $I$ if right-multiplied by $J$), which is *not* true. They are **both pseudoinverses of $J$ but they are not necessarily the same matrices**, in fact they don't necessarily both *exist*.&#xD;&#xA;&#xD;&#xA;As the book says, the $(JJ^T)^{-1}$ only exists if the *rows* of $J$ are linearly independent, and in turn [Wikipedia](https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse#Definition) says that $(J^TJ)^{-1}$ exists if the *columns* of $J$ are linearly independent. However, they can't both exist if the matrix is not square, since one of the dimensions would necessarily have more vectors than the dimension, which can't all be linearly independent. Specifically, for a normal redundant joint system you probably have **more columns than rows, making only the pseudoinverse $J(JJ^T)^{-1}$ exist**.&#xD;&#xA;&#xD;&#xA;We can, however, see that for a square matrix they are indeed the same and actually the real inverse:&#xD;&#xA;&#xD;&#xA;$J^T(JJ^T)^{-1} = J^TJ^{-T}J^{-1} = (J^{-1}J)^TJ^{-1} = I^TJ^{-1} = J^{-1}$&#xD;&#xA;&#xD;&#xA;$(J^TJ)^{-1}J^T = J^{-1}J^{-T}J^T = J^{-1}(JJ^{-1})^T = J^{-1}I^T = J^{-1}$&#xD;&#xA;&#xD;&#xA;(But in that case the system would have a unique solution and there's no point to angle control anyway.) But you cannot resolve the brackets with a non-square matrix, since the **individual matrices aren't square and don't have an actual inverse**. The only situation when **both matrices *exist* are square $J$s** and then they are indeed **equal, but then there's also no point to angle control**.&#xD;&#xA;&#xD;&#xA;But I understand why you are confused and I am a little, too, since Parent actually seems to use the *alleged* identity $J^T(JJ^T)^{-1}=(J^TJ)^{-1}J^T$ in equation 5.20, where he derives the pseudoinverse's relevance for solving the inverse kinematics problem. He computes everything with the *left inverse* but than concludes with using the *right inverse*. I guess that works conceptually because they're both pseudoinverses, even if it doesn't make complete mathematical sense (to me and you at least). He seemed to have used the assumption of a square matrix as a trick for transforming the problem and then used the conclusion for a non-square matrix, which *might* be conceptually correct.&#xD;&#xA;&#xD;&#xA;I guess it simply **doesn't matter *which* of the two pseudoinverses we use, since only *one* of them ever exists** (for a non-square Jacobian) anyway and if the left inverse *would* exist (making your above assumption true), that means you have more constraints than DoF and thus your system is overconstrained and there's no point in angle control." ContentLicense="CC BY-SA 3.0" />
  <row Id="15549" PostHistoryTypeId="5" PostId="5665" RevisionGUID="0a7c3313-4ba7-42e6-97fe-f5a986ebdf76" CreationDate="2017-10-03T13:26:25.517" UserId="6" Comment="added 93 characters in body" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way you can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[-1,1]$ anyway, which you can naturally upscale from the normalized $[0,1]$ range of a common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[256];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 256; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 256.f) * TWO_PI);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_1D, 0, ..., 256, 0, GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[361]`, or maybe less in practice, keep an eye on your implementation's limit on uniform array size) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360)$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int(((angle &lt; 0.0) ? (angle + 360.0) : angle) + 0.5)];" ContentLicense="CC BY-SA 3.0" />
  <row Id="15551" PostHistoryTypeId="2" PostId="5676" RevisionGUID="49b2c677-5c94-4b20-96d9-e00199619c54" CreationDate="2017-10-03T22:55:59.197" UserId="7413" Text="I am creating a 2D CAD drawing generator in C# using .netDXF library. Given a area I want to fill it with rectangles/circles (convex). For example, the regions marked with numbers in below image. This is just an example, the pattern may change.&#xD;&#xA;&#xD;&#xA;I'am not an expert in the area of graphics. What should be my approach to this problem? Is there any algorithm that I can follow? What would be a generalized (not specific to .netDXF) way to fill an irregular region with 2D shapes.&#xD;&#xA;&#xD;&#xA;Any help is appreciated!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gSzNA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15552" PostHistoryTypeId="1" PostId="5676" RevisionGUID="49b2c677-5c94-4b20-96d9-e00199619c54" CreationDate="2017-10-03T22:55:59.197" UserId="7413" Text="Fill an irregular region with 2D shapes" ContentLicense="CC BY-SA 3.0" />
  <row Id="15553" PostHistoryTypeId="3" PostId="5676" RevisionGUID="49b2c677-5c94-4b20-96d9-e00199619c54" CreationDate="2017-10-03T22:55:59.197" UserId="7413" Text="|vector-graphics|polygon|2d-graphics|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15554" PostHistoryTypeId="2" PostId="5677" RevisionGUID="d5d15615-6936-419f-b95d-0ef7013de157" CreationDate="2017-10-04T13:31:46.130" UserId="38" Text="There is no general algorithm for packing problems. Only some of the special cases have known, and optimal, solutions. If you are packing one shape then finding a reasonable solution is possible. Like the known cases of hexagonal packing etc.&#xD;&#xA;&#xD;&#xA;However, if you have multiple diffenently sized objects then easy just flew out of the door. Some heurestics have been developed, since there is a very big demand for such algorithms in manufacturing. But they are not usually very fast (performant?) or simple to implement. Many of them use a genetic algorithm. A free one that you may test can be found at[svgnest.com](http://svgnest.com/) but faster ones and ones working on shaking and collision also exist.&#xD;&#xA;&#xD;&#xA;Anyway your question is sufficiently vague, so i dont actually know if&#xD;&#xA; you want to do packing. I mean it is perfectly possible you mean tiling, which is pretty trivial." ContentLicense="CC BY-SA 3.0" />
  <row Id="15555" PostHistoryTypeId="2" PostId="5678" RevisionGUID="6ca8cb45-8727-433d-9dc5-a418f65758ea" CreationDate="2017-10-04T14:10:51.743" UserId="7107" Text="I recently finished the base implementation of a DX12 rederer and I started to think in ways of improving the performance. I think that one problem that my implementation has, is memory fragmentation, as I mostly perform &quot;single&quot; allocations for my resources. During run-time some resources are deleted and recreated which I guess will cause even more memory frag. There are quite a few articles online about writing system memory managers but I've never encountered something like that for video memory and GPU resources. &#xD;&#xA;&#xD;&#xA;Could anyone explain the basics of a system like this? &#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="15556" PostHistoryTypeId="1" PostId="5678" RevisionGUID="6ca8cb45-8727-433d-9dc5-a418f65758ea" CreationDate="2017-10-04T14:10:51.743" UserId="7107" Text="Handling GPU resource management" ContentLicense="CC BY-SA 3.0" />
  <row Id="15557" PostHistoryTypeId="3" PostId="5678" RevisionGUID="6ca8cb45-8727-433d-9dc5-a418f65758ea" CreationDate="2017-10-04T14:10:51.743" UserId="7107" Text="|gpu|memory|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15558" PostHistoryTypeId="5" PostId="5678" RevisionGUID="26264dcb-4893-4eed-986d-a900a1f0fc05" CreationDate="2017-10-04T14:24:37.373" UserId="7107" Comment="added 180 characters in body" Text="I recently finished the base implementation of a DX12 rederer and I started to think in ways of improving the performance. I think that one problem that my implementation has, is memory fragmentation, as I mostly perform &quot;single&quot; allocations for my resources. During run-time some resources are deleted and recreated which I guess will cause even more memory frag. There are quite a few articles online about writing system memory managers but I've never encountered something like that for video memory and GPU resources. &#xD;&#xA;&#xD;&#xA;Could anyone explain the basics of a system like this? &#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I had this link laying around: https://msdn.microsoft.com/en-us/library/windows/desktop/mt613239(v=vs.85).aspx. That gives some good general information about the topic." ContentLicense="CC BY-SA 3.0" />
  <row Id="15559" PostHistoryTypeId="5" PostId="5656" RevisionGUID="b55cdb51-fd79-4f1d-a13e-656da5125206" CreationDate="2017-10-04T16:38:01.660" UserId="2287" Comment="added 413 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the F, G (or V depending if you factor the foreshortening in the denominator into G) and D:&#xD;&#xA;&#xD;&#xA; - D: Beckmann&#xD;&#xA; - D: Ward-Duer&#xD;&#xA; - D: Blinn-Phong&#xD;&#xA; - D: Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2&#xD;&#xA; - D: Berry a.k.a. GTR1&#xD;&#xA; - G: Implicit&#xD;&#xA; - G: Ward&#xD;&#xA; - G: Neumann&#xD;&#xA; - G: Ashikhmin-Premoze&#xD;&#xA; - G: Kelemann&#xD;&#xA; - G: Cook-Torrance&#xD;&#xA; - G: Smith GGX&#xD;&#xA; - G: Smith Schlick-GGX&#xD;&#xA; - G: Smith Beckmann&#xD;&#xA; - G: Smith Schlick-Beckmann&#xD;&#xA; - F: Schlick&#xD;&#xA; - F: Cook-Torrance&#xD;&#xA;&#xD;&#xA;They all seemed to be used (in the literature, in the animation industry and in the gaming industry) with your **second** option. All the D factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$." ContentLicense="CC BY-SA 3.0" />
  <row Id="15560" PostHistoryTypeId="5" PostId="5656" RevisionGUID="9fd29bfa-a047-4f63-9fd3-e91351fd2802" CreationDate="2017-10-04T16:43:28.887" UserId="2287" Comment="added 413 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the F, G (or V depending if you factor the foreshortening in the denominator into G) and D:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seemed to be used (in the literature, in the animation industry and in the gaming industry) with your **second** option. All the D factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$." ContentLicense="CC BY-SA 3.0" />
  <row Id="15561" PostHistoryTypeId="5" PostId="5656" RevisionGUID="f0847cc5-3284-4654-a669-19438a8156e9" CreationDate="2017-10-04T17:00:02.767" UserId="2287" Comment="added 46 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the **F**, **G** (or **V** depending if you factor the foreshortening in the denominator into **G**) and **D**:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seemed to be used (in the literature, in the animation industry and in the gaming industry) in the format corresponding to your **second** option. All the **D** factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$." ContentLicense="CC BY-SA 3.0" />
  <row Id="15563" PostHistoryTypeId="2" PostId="5679" RevisionGUID="941081f5-b037-4185-aeda-be7c67f46f0d" CreationDate="2017-10-04T17:58:25.343" UserId="2287" Text="**Spotlight**&#xD;&#xA;&#xD;&#xA;My spotlight's intensity is cut off at a distance of 3 and at an angle of $\pi/4$ radians (umbra angle). The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. The spotlight is positioned somewhere above the tree and faces downward to the floor.&#xD;&#xA;&#xD;&#xA;The shadow map of my spotlight has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each spotlight);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DArray` for all, spotlights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow maps.&#xD;&#xA;     @param[in]		p_proj&#xD;&#xA;    				The hit position in light projection space coordinates.&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler,&#xD;&#xA;    	Texture2DArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float4 p_proj) {&#xD;&#xA;    &#xD;&#xA;    	const float  inv_w  = 1.0f / p_proj.w;&#xD;&#xA;    	const float3 p_ndc  = p_proj.xyz * inv_w;&#xD;&#xA;    	const float3 loc    = float3(NDCtoUV(p_ndc.xy), index);&#xD;&#xA;    	&#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light projection space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float4 p_proj = mul(float4(p, 1.0f), light.cview_to_lprojection);&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (*this is not the light contribution of the spotlight*) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This seems to result in the correct behavior (see the shadows of the leaves, pillars and curtains). *The bright border on the first image starts at the position of the spotlight and is due to the near plane distance of 0.1. This border will completely vanish after multiplying the shadow factor with the spotlight's contribution.*&#xD;&#xA;&#xD;&#xA;**Omni light**&#xD;&#xA;&#xD;&#xA;My omni light's intensity is cut off at a distance of 3. The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. This means that one of the six light cameras (after applying some rotations), is completely identical to the spotlight camera above. I double checked this in the code:&#xD;&#xA;&#xD;&#xA;Frame 1: &#xD;&#xA;`world_to_lprojection` (spotlight):&#xD;&#xA;&#xD;&#xA;    1.16532457,  0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` (fourth omni light camera):&#xD;&#xA;&#xD;&#xA;    1.16532457, 0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;So apart from the fact that a spotlight corresponds to one DSV (and is part of one SRV to a `Texture2DArray` for all spotlight shadow maps) and an omni light corresponds to six DSVs (and is part of one SRV to a `Texture2DCubeArray` for all omni light shadow cube maps), the shadow map generation is pretty much the same for both types of lights.&#xD;&#xA;&#xD;&#xA;The shadow map of my omni light has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each omni light);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DCubeArray` for all, omni lights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow cube map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow cube maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow cube maps.&#xD;&#xA;     @param[in]		p_view&#xD;&#xA;    				The hit position in light view space coordinates.&#xD;&#xA;     @param[in]		projection_values&#xD;&#xA;    				The projection values [view_projection22, view_projection32].&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler, &#xD;&#xA;    	TextureCubeArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float3 p_view, float2 projection_values) {&#xD;&#xA;    &#xD;&#xA;    	const float p_view_z = Max(abs(p_view));&#xD;&#xA;    	const float p_ndc_z  = ViewZtoNDCZ(p_view_z, projection_values);&#xD;&#xA;    	const float4 loc     = float4(p_view, index);&#xD;&#xA;    &#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc_z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light view space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float3 p_view = mul(float4(p, 1.0f), light.cview_to_lview).xyz;&#xD;&#xA;&#xD;&#xA;The conversion of the z coordinate to NDC space is done as follows:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Converts the given (linear) view z-coordinate to the (non-linear) NDC &#xD;&#xA;     z-coordinate.&#xD;&#xA;    &#xD;&#xA;     @param[in]     p_view_z&#xD;&#xA;                    The (linear) view z-coordinate.&#xD;&#xA;     @param[in]     projection_values&#xD;&#xA;                    The projection values [view_projection22, view_projection32].&#xD;&#xA;     @return        The (non-linear) NDC z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    float ViewZtoNDCZ(float p_view_z, float2 projection_values) {&#xD;&#xA;        return projection_values.x + projection_values.y / p_view_z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with the following dual C++ method:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Returns the projection values from the given projection matrix to construct &#xD;&#xA;     the NDC position z-coordinate from the view position z-coordinate.&#xD;&#xA;&#xD;&#xA;     @return        The projection values from the given projection matrix to &#xD;&#xA;                    construct the NDC position z-coordinate from the view position &#xD;&#xA;                    z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    inline const XMVECTOR XM_CALLCONV GetNDCZConstructionValues(&#xD;&#xA;        FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;&#xD;&#xA;        //        [ _  0  0  0 ]&#xD;&#xA;        // p_view [ 0  _  0  0 ] = [_, _, p_view.z * X + Y, p_view.z] = p_proj&#xD;&#xA;        //        [ 0  0  X  1 ]&#xD;&#xA;        //        [ 0  0  Y  0 ]&#xD;&#xA;        //&#xD;&#xA;        // p_proj / p_proj.w     = [_, _, X + Y/p_view.z, 1] = p_ndc&#xD;&#xA;        //&#xD;&#xA;        // Construction of p_ndc.z from p_view and projection values&#xD;&#xA;        // p_ndc.z = X + Y/p_view.z&#xD;&#xA;&#xD;&#xA;        const F32 x = XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;        const F32 y = XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;        &#xD;&#xA;        return XMVectorSet(x, y, 0.0f, 0.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (this is not the light contribution of the omni light) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is clearly wrong. All six shadow maps seem kind of **stretched**. Without the stretching, the curtain's shadow would still be in the close vicinity of the curtain itself and the leaves' shadow would be much smaller (equal to the leaves' shadow for the spotlight). Furthermore, the circular shadow at the end of the pillar's shadow is associated to the buckets in front of the curtains.&#xD;&#xA;&#xD;&#xA;Any ideas what goes or could go wrong?&#xD;&#xA;&#xD;&#xA;An other strange observation is that using a depth value of 1.1 for my spotlight's PCF filtering (`SampleCmpLevelZero`) always results in a 0 value as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;whereas for my omni light this is not the case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Even if I use a value equal to 100000.0, I'll notice lit areas?&#xD;&#xA;&#xD;&#xA;**Depth Biasing**&#xD;&#xA;&#xD;&#xA;I use `DepthBias = 100; SlopeScaledDepthBias = 0.0f; DepthBiasClamp = 0.0f;` for all my Rasterizer states.&#xD;&#xA;&#xD;&#xA;**PCF filtering**&#xD;&#xA;&#xD;&#xA;I use the following sampler comparison state for PCF filtering (*my shadow maps have no mipmaps*). &#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC desc = {};&#xD;&#xA;    desc.Filter         = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;&#xD;&#xA;    desc.AddressU       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressV       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressW       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.MaxAnisotropy  = (device-&gt;GetFeatureLevel() &gt; D3D_FEATURE_LEVEL_9_1) &#xD;&#xA;    								? D3D11_MAX_MAXANISOTROPY : 2;&#xD;&#xA;    desc.MaxLOD         = D3D11_FLOAT32_MAX;&#xD;&#xA;    desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Al0D.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DW86m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hQ0sB.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zedO9.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/49GZW.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/9vBBr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15564" PostHistoryTypeId="1" PostId="5679" RevisionGUID="941081f5-b037-4185-aeda-be7c67f46f0d" CreationDate="2017-10-04T17:58:25.343" UserId="2287" Text="Artifacts in omni light shadow mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="15565" PostHistoryTypeId="3" PostId="5679" RevisionGUID="941081f5-b037-4185-aeda-be7c67f46f0d" CreationDate="2017-10-04T17:58:25.343" UserId="2287" Text="|hlsl|shadow-mapping|direct3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15566" PostHistoryTypeId="2" PostId="5680" RevisionGUID="a11b7352-31ce-44ff-bafe-7425268ce0b0" CreationDate="2017-10-04T18:25:19.453" UserId="2287" Text="In the SIGGRAPH course: &#xD;&#xA;&#xD;&#xA;[BURLEY B.: Physically Based Shading at Disney, SIGGRAPH 2012 Course: Practical Physically Based Shading in Film and Game Production, 2012.](https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf)&#xD;&#xA;&#xD;&#xA;it is mentioned that some BRDF models include a diffuse Fresnel factor such as:&#xD;&#xA;&#xD;&#xA;$$(1-F(\theta_l)) (1-F(\theta_d)).$$&#xD;&#xA;&#xD;&#xA;The Disney BRDF itself uses the following diffuse BRDF component (using Sclick's Fresnel approximation):&#xD;&#xA;&#xD;&#xA;$$f_d = \frac{\textrm{c_base}}{\pi} (1 + (F_{\textrm{D90}} - 1)(1-\cos^5\theta_l)) (1 + (F_{\textrm{D90}} - 1)(1-\cos^5\theta_v)),$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$F_{\textrm{D90}} = 0.5 + 2 \text{roughness} \cos^2\theta_d. $$&#xD;&#xA;&#xD;&#xA;Where does this come from? &#xD;&#xA;&#xD;&#xA;My attempt...&#xD;&#xA;&#xD;&#xA;If I evaluate $(1-F(\theta_l)) (1-F(\theta_v))$ (instead of $(1-F(\theta_l)) (1-F(\theta_d))$?) with Schlick's approximation, we get:&#xD;&#xA;&#xD;&#xA;$$\left(1-(F_0 + (1-F_0)(1-\cos^5\theta_l))\right) \left(1-(F_0 + (1-F_0)(1-\cos^5\theta_v))\right)$$&#xD;&#xA;$$\left(1-F_0 + (F_0-1)(1-\cos^5\theta_l)\right) \left(1-F_0 + (F_0-1)(1-\cos^5\theta_v)\right)$$&#xD;&#xA;&#xD;&#xA;If we substitute $F_{\textrm{D90}} = F_0$, we get:&#xD;&#xA;&#xD;&#xA;$$\left(1-F_{\textrm{D90}} + (F_{\textrm{D90}}-1)(1-\cos^5\theta_l)\right) \left(1-F_{\textrm{D90}} + (F_{\textrm{D90}}-1)(1-\cos^5\theta_v)\right)$$&#xD;&#xA;&#xD;&#xA;This looks similar except for the 2x $-F_{\textrm{D90}}$? Is my reasoning completely wrong or where do I make mistakes? Or am I not aware of some further (common) approximations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15567" PostHistoryTypeId="1" PostId="5680" RevisionGUID="a11b7352-31ce-44ff-bafe-7425268ce0b0" CreationDate="2017-10-04T18:25:19.453" UserId="2287" Text="Diffuse BRDF component of the Disney BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="15568" PostHistoryTypeId="3" PostId="5680" RevisionGUID="a11b7352-31ce-44ff-bafe-7425268ce0b0" CreationDate="2017-10-04T18:25:19.453" UserId="2287" Text="|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15569" PostHistoryTypeId="2" PostId="5681" RevisionGUID="9ebafee4-7b26-4644-a8e6-1aee8d0c72d3" CreationDate="2017-10-04T19:59:18.963" UserId="56" Text="Whenever there's too much churn of things being created and destroyed, regardless of the specifics of the situation, a common way to dealing with this is to make free object pools.&#xD;&#xA;&#xD;&#xA;How these work is when you are done using something, instead of actually freeing or destroying it, you put it back into a list or array of &quot;free objects&quot;.&#xD;&#xA;&#xD;&#xA;When you need a new object of a specific type, you check the object pool to see if there's a free one lying around.  If there isn't one there, you create a new one the &quot;expensive&quot; way and use it.  When you are done with it, you put it in the free pool for use in the future.&#xD;&#xA;&#xD;&#xA;A possible issue with free object pools is that you may have a spike in objects for some reason and then you are left with a ton of unused objects sitting in a free pool that will never be needed again.  In situations like this, you can keep track of how long (in number of frames for instance) since an object was last used, and if they get over a certain unused age, free them from the object pool.&#xD;&#xA;&#xD;&#xA;PS - make sure and profile your code to find what the ACTUAL performance bottlenecks are before attempting to solve problems.  Optimizing without profiling before (to find the problem) and after (to verify you improved things, and knowing by how much) won't get you very far (:" ContentLicense="CC BY-SA 3.0" />
  <row Id="15570" PostHistoryTypeId="5" PostId="5656" RevisionGUID="20e95a34-077d-4a0f-8348-546a4447bc1e" CreationDate="2017-10-04T20:37:07.123" UserId="2287" Comment="deleted 2 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the **F**, **G** (or **V** depending if you factor the foreshortening in the denominator into **G**) and **D**:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seem to be used (in the literature, in the animation industry and in the gaming industry) in the format corresponding to your **second** option. All the **D** factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$." ContentLicense="CC BY-SA 3.0" />
  <row Id="15571" PostHistoryTypeId="2" PostId="5682" RevisionGUID="8cdb41ef-c374-4ff7-952c-d13e2f0af00e" CreationDate="2017-10-05T04:00:54.277" UserId="56" Text="I'm trying to generate an image where black dots are arranged in a blue noise distribution on a white background.&#xD;&#xA;&#xD;&#xA;I know that there are other ways to do this, one of the best being &quot;Fast Capacity Constrained Voronoi Tessellation.&quot; [[Hongwei 09][1]], but I'm using Mitchell's best candidate algorithm.&#xD;&#xA;&#xD;&#xA;This algorithm works by generating $N$ random pixel locations as candidates for where the next black pixel should go and chooses the candidate which has the farthest distance to the nearest black pixel.&#xD;&#xA;&#xD;&#xA;I've implemented this and have used it to put 455 black pixels on a 64x64 image, using various candidate counts.  Looking at the DFT (frequency magnitude, not phase) of the results, I'm seeing some unexpected frequency data.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Strangely, I never get that &quot;nice concentric rings&quot; DFT frequency amplitude that i'd expect and see in papers regarding blue noise sample patterns.&#xD;&#xA;&#xD;&#xA;Are these results expected?&#xD;&#xA;&#xD;&#xA;Manually hunting between 100 and 1000 samples, it seems like 400 is pretty near optimal.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] [![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Is there some &quot;sweet spot&quot; for the number of candidates to use based on image size and desired sample (black pixel) count to get the best result?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.microsoft.com/en-us/research/publication/fast-capacity-constrained-voronoi-tessellation/&#xD;&#xA;  [2]: https://i.stack.imgur.com/zCTZO.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NytDe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/mtrOr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15572" PostHistoryTypeId="1" PostId="5682" RevisionGUID="8cdb41ef-c374-4ff7-952c-d13e2f0af00e" CreationDate="2017-10-05T04:00:54.277" UserId="56" Text="Mitchell's Best Candidate Algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="15573" PostHistoryTypeId="3" PostId="5682" RevisionGUID="8cdb41ef-c374-4ff7-952c-d13e2f0af00e" CreationDate="2017-10-05T04:00:54.277" UserId="56" Text="|sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15574" PostHistoryTypeId="2" PostId="5683" RevisionGUID="8b8015ff-c7c9-41af-be3d-1bdacf5c3745" CreationDate="2017-10-05T07:19:55.487" UserId="7425" Text="Another very simple, easy to implement, algorithm to generate a Poisson-disk/blue noise point distribution is the following one [ 1 ]: &#xD;&#xA;&#xD;&#xA; 1. Decide a radius ***r***, and therefore the expected number *N* of samples per area (use the formula for maximum packing density of *k* disks distributed on a toroidal domain see [ 2 ]) &#xD;&#xA; 2. Generate 10~20 x *N* samples in your area using a plain unbiased montecarlo sampling&#xD;&#xA; 3. Until all samples respect poisson disk condition:&#xD;&#xA;   - randomly choose a sample ***p*** &#xD;&#xA;   - remove all the samples at distance lower than ***r*** from ***p***&#xD;&#xA;&#xD;&#xA;Eventually step 3 can be furtherly iterated a small number of times choosing the sample with minimal number of surviving samples within distance r.&#xD;&#xA;&#xD;&#xA;You can find an implementation of this algorithm in MeshLab.&#xD;&#xA;&#xD;&#xA;**References**&#xD;&#xA;&#xD;&#xA;[ 1 ] [**Efficient and Flexible Sampling with Blue Noise Properties of Triangular Meshes**  &#xD;&#xA;*Massimiliano Corsini, Paolo Cignoni, Roberto Scopigno*  &#xD;&#xA;IEEE Transaction on Visualization and Computer Graphics, Volume 18, Number 6, page 914--924 - 2012][1]&#xD;&#xA;&#xD;&#xA;[ 2 ] [**A comparison of methods for generating Poisson disk distributions**  &#xD;&#xA; *Ares Lagae, Philip Dutré,*   &#xD;&#xA;Computer Graphics Forum vol:27 issue:1 , 2008][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://vcg.isti.cnr.it/Publications/2012/CCS12/&#xD;&#xA;  [2]: https://lirias.kuleuven.be/handle/123456789/176251" ContentLicense="CC BY-SA 3.0" />
  <row Id="15576" PostHistoryTypeId="5" PostId="5679" RevisionGUID="5c654769-0023-4ed6-8336-a51f726f30ec" CreationDate="2017-10-05T08:34:33.967" UserId="2287" Comment="added 61 characters in body" Text="**Spotlight**&#xD;&#xA;&#xD;&#xA;My spotlight's intensity is cut off at a distance of 3 and at an angle of $\pi/4$ radians (umbra angle). The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. The spotlight is positioned somewhere above the tree and faces downward to the floor.&#xD;&#xA;&#xD;&#xA;The shadow map of my spotlight has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each spotlight);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DArray` for all, spotlights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow maps.&#xD;&#xA;     @param[in]		p_proj&#xD;&#xA;    				The hit position in light projection space coordinates.&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler,&#xD;&#xA;    	Texture2DArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float4 p_proj) {&#xD;&#xA;    &#xD;&#xA;    	const float  inv_w  = 1.0f / p_proj.w;&#xD;&#xA;    	const float3 p_ndc  = p_proj.xyz * inv_w;&#xD;&#xA;    	const float3 loc    = float3(NDCtoUV(p_ndc.xy), index);&#xD;&#xA;    	&#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light projection space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float4 p_proj = mul(float4(p, 1.0f), light.cview_to_lprojection);&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (*this is not the light contribution of the spotlight*) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This seems to result in the correct behavior (see the shadows of the leaves, pillars and curtains). *The bright border on the first image starts at the position of the spotlight and is due to the near plane distance of 0.1. This border will completely vanish after multiplying the shadow factor with the spotlight's contribution.*&#xD;&#xA;&#xD;&#xA;**Omni light**&#xD;&#xA;&#xD;&#xA;My omni light's intensity is cut off at a distance of 3. The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. This means that one of the six light cameras (after applying some rotations), is completely identical to the spotlight camera above. I double checked this in the code:&#xD;&#xA;&#xD;&#xA;Frame 1: &#xD;&#xA;`world_to_lprojection` (spotlight):&#xD;&#xA;&#xD;&#xA;    1.16532457,  0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` (fourth omni light camera):&#xD;&#xA;&#xD;&#xA;    1.16532457, 0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;So apart from the fact that a spotlight corresponds to one DSV (and is part of one SRV to a `Texture2DArray` for all spotlight shadow maps) and an omni light corresponds to six DSVs (and is part of one SRV to a `Texture2DCubeArray` for all omni light shadow cube maps), the shadow map generation is pretty much the same for both types of lights.&#xD;&#xA;&#xD;&#xA;The shadow map of my omni light has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each omni light);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DCubeArray` for all, omni lights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow cube map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow cube maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow cube maps.&#xD;&#xA;     @param[in]		p_view&#xD;&#xA;    				The hit position in light view space coordinates.&#xD;&#xA;     @param[in]		projection_values&#xD;&#xA;    				The projection values [view_projection22, view_projection32].&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler, &#xD;&#xA;    	TextureCubeArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float3 p_view, float2 projection_values) {&#xD;&#xA;    &#xD;&#xA;    	const float p_view_z = Max(abs(p_view));&#xD;&#xA;    	const float p_ndc_z  = ViewZtoNDCZ(p_view_z, projection_values);&#xD;&#xA;    	const float4 loc     = float4(p_view, index);&#xD;&#xA;    &#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc_z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light view space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float3 p_view = mul(float4(p, 1.0f), light.cview_to_lview).xyz;&#xD;&#xA;&#xD;&#xA;The conversion of the z coordinate to NDC space is done as follows:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Converts the given (linear) view z-coordinate to the (non-linear) NDC &#xD;&#xA;     z-coordinate.&#xD;&#xA;    &#xD;&#xA;     @param[in]     p_view_z&#xD;&#xA;                    The (linear) view z-coordinate.&#xD;&#xA;     @param[in]     projection_values&#xD;&#xA;                    The projection values [view_projection22, view_projection32].&#xD;&#xA;     @return        The (non-linear) NDC z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    float ViewZtoNDCZ(float p_view_z, float2 projection_values) {&#xD;&#xA;        return projection_values.x + projection_values.y / p_view_z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with the following dual C++ method:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Returns the projection values from the given projection matrix to construct &#xD;&#xA;     the NDC position z-coordinate from the view position z-coordinate.&#xD;&#xA;&#xD;&#xA;     @return        The projection values from the given projection matrix to &#xD;&#xA;                    construct the NDC position z-coordinate from the view position &#xD;&#xA;                    z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    inline const XMVECTOR XM_CALLCONV GetNDCZConstructionValues(&#xD;&#xA;        FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;&#xD;&#xA;        //        [ _  0  0  0 ]&#xD;&#xA;        // p_view [ 0  _  0  0 ] = [_, _, p_view.z * X + Y, p_view.z] = p_proj&#xD;&#xA;        //        [ 0  0  X  1 ]&#xD;&#xA;        //        [ 0  0  Y  0 ]&#xD;&#xA;        //&#xD;&#xA;        // p_proj / p_proj.w     = [_, _, X + Y/p_view.z, 1] = p_ndc&#xD;&#xA;        //&#xD;&#xA;        // Construction of p_ndc.z from p_view and projection values&#xD;&#xA;        // p_ndc.z = X + Y/p_view.z&#xD;&#xA;&#xD;&#xA;        const F32 x = XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;        const F32 y = XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;        &#xD;&#xA;        return XMVectorSet(x, y, 0.0f, 0.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (this is not the light contribution of the omni light) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is clearly wrong. All six shadow maps seem kind of **stretched**. Without the stretching, the curtain's shadow would still be in the close vicinity of the curtain itself and the leaves' shadow would be much smaller (equal to the leaves' shadow for the spotlight). Furthermore, the circular shadow at the end of the pillar's shadow is associated to the buckets in front of the curtains.&#xD;&#xA;&#xD;&#xA;Any ideas what goes or could go wrong?&#xD;&#xA;&#xD;&#xA;An other strange observation is that using a depth value of 1.1 for my spotlight's PCF filtering (`SampleCmpLevelZero`) always results in a 0 value as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;whereas for my omni light this is not the case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Even if I use a value equal to 100000.0, I'll notice lit areas?&#xD;&#xA;&#xD;&#xA;**Depth Biasing**&#xD;&#xA;&#xD;&#xA;I use `DepthBias = 100;` (to prevent shadow acne; note that I use 16bit depth maps) `SlopeScaledDepthBias = 0.0f; DepthBiasClamp = 0.0f;` for all my Rasterizer states.&#xD;&#xA;&#xD;&#xA;**PCF filtering**&#xD;&#xA;&#xD;&#xA;I use the following sampler comparison state for PCF filtering (*my shadow maps have no mipmaps*). &#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC desc = {};&#xD;&#xA;    desc.Filter         = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;&#xD;&#xA;    desc.AddressU       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressV       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressW       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.MaxAnisotropy  = (device-&gt;GetFeatureLevel() &gt; D3D_FEATURE_LEVEL_9_1) &#xD;&#xA;    								? D3D11_MAX_MAXANISOTROPY : 2;&#xD;&#xA;    desc.MaxLOD         = D3D11_FLOAT32_MAX;&#xD;&#xA;    desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Al0D.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DW86m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hQ0sB.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zedO9.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/49GZW.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/9vBBr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15577" PostHistoryTypeId="2" PostId="5684" RevisionGUID="b6398d6a-288a-4068-ad35-c9cfd24be09d" CreationDate="2017-10-05T09:51:05.740" UserId="6041" Text="I need to highlight(colour) sun reflections(through the year) off a mirror surface. It was easy having one Sun like in the below image but how about if it is to determine if a ray hits the entire surface that represents sun positions throughout the year. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S7EU4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15578" PostHistoryTypeId="1" PostId="5684" RevisionGUID="b6398d6a-288a-4068-ad35-c9cfd24be09d" CreationDate="2017-10-05T09:51:05.740" UserId="6041" Text="Ray intersection with Sun positions throughout the year" ContentLicense="CC BY-SA 3.0" />
  <row Id="15579" PostHistoryTypeId="3" PostId="5684" RevisionGUID="b6398d6a-288a-4068-ad35-c9cfd24be09d" CreationDate="2017-10-05T09:51:05.740" UserId="6041" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15580" PostHistoryTypeId="2" PostId="5685" RevisionGUID="3a230f3d-d853-4232-a41f-6264d9b021e5" CreationDate="2017-10-05T13:22:25.087" UserId="6207" Text="[This](https://soulsphere.org/apocrypha/bsp/) article says that binary space partitioning divides the map into convex polygons.&#xD;&#xA;&#xD;&#xA;&gt; [...]    &#xD;&#xA;&gt; Before the map can be rendered we must perform a number of&#xD;&#xA;&gt; calculations on it. However, once these calculations are performed&#xD;&#xA;&gt; their results can be used many times. This is one of the advantages of&#xD;&#xA;&gt; BSP — once the calculations are performed they do not need to be done&#xD;&#xA;&gt; again, unless the map is changed. BSP only allows ”static” maps, or&#xD;&#xA;&gt; ones that do not move. If a map has any moving parts then they must be&#xD;&#xA;&gt; rendered separately.&#xD;&#xA;&gt; &#xD;&#xA;&gt; What must be done is to partition, or divide up, **the map into convex&#xD;&#xA;&gt; polygons**.&#xD;&#xA;&#xD;&#xA;Why should non-convex polygons be partitioned into convex polygons? Is there a mathematical basis behind this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15581" PostHistoryTypeId="1" PostId="5685" RevisionGUID="3a230f3d-d853-4232-a41f-6264d9b021e5" CreationDate="2017-10-05T13:22:25.087" UserId="6207" Text="Why do we have to partition non-convex polygons into convex polygons in a map in Binary Space Partitioning?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15582" PostHistoryTypeId="3" PostId="5685" RevisionGUID="3a230f3d-d853-4232-a41f-6264d9b021e5" CreationDate="2017-10-05T13:22:25.087" UserId="6207" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15583" PostHistoryTypeId="2" PostId="5686" RevisionGUID="d3977704-71d3-490c-a4e8-0460fa34d495" CreationDate="2017-10-05T15:18:08.323" UserId="137" Text="Because with 2 non-overlapping convex polygons you can always say that 1 polygon is closer to a point than another.&#xD;&#xA;&#xD;&#xA;If they are not convex then for example with a U surrounding a circle. You cannot say easily which should be drawn first." ContentLicense="CC BY-SA 3.0" />
  <row Id="15584" PostHistoryTypeId="2" PostId="5687" RevisionGUID="0e671f1f-bf9c-4986-b133-9295abd78abd" CreationDate="2017-10-05T19:28:30.110" UserId="56" Text="The problem turned out to be that you don't do the same number of candidates per point, but that if you have $n$ points already, you should generate $m*n$ candidates for the next point.&#xD;&#xA;&#xD;&#xA;$m$ is a tuneable parameter where in general higher values of $m$ will take longer to calculate, but will result in higher quality sampling.&#xD;&#xA;&#xD;&#xA;Values of $m$ that are too high will end up looking like the lower images of the question though, where the randomness is almost completely gone.&#xD;&#xA;&#xD;&#xA;I personally choose to do $m*n+1$ samples to slightly simplify the logic and let it handle the first sample when $n=0$.&#xD;&#xA;&#xD;&#xA;This technique was described in this paper:&#xD;&#xA;&#xD;&#xA;&quot;Spectrally optimal sampling for distribution ray tracing&quot; Mitchell 1991.&#xD;&#xA;https://dl.acm.org/citation.cfm?id=122718.122736&#xD;&#xA;&#xD;&#xA;Below is the same setup as in the question where 455 black pixels are placed in a 64x64 image, showing the result for some values of $m$.  The quality is surprisingly good even for low values of $m$ and the execution time is much, much lower than the process described in the question.&#xD;&#xA;&#xD;&#xA;Note that $m=0$ is equivelant to white noise and just randomly placing the dots.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/blUaK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15585" PostHistoryTypeId="5" PostId="5687" RevisionGUID="150d35dc-0e94-442c-acf6-67d783c0331e" CreationDate="2017-10-05T19:34:35.827" UserId="56" Comment="added 467 characters in body" Text="The problem turned out to be that you don't do the same number of candidates per point, but that if you have $n$ points already, you should generate $m*n$ candidates for the next point.&#xD;&#xA;&#xD;&#xA;$m$ is a tuneable parameter where in general higher values of $m$ will take longer to calculate, but will result in higher quality sampling.&#xD;&#xA;&#xD;&#xA;The reason that the candidate count should scale with the existing sample count is that it keeps statistics about the points constant, so lets you reason about how higher sample counts will look / behave by looking at lower sample counts.&#xD;&#xA;&#xD;&#xA;Values of $m$ that are too high will end up looking like the lower images of the question though, where the randomness is almost completely gone.&#xD;&#xA;&#xD;&#xA;The problem with the high sample counts is that they more fully cover all possible pixel locations, and since the best candidate is chosen, much randomness will go away leaving you with something a lot more deterministic.&#xD;&#xA;&#xD;&#xA;I personally choose to do $m*n+1$ samples to slightly simplify the logic and let it handle the first sample when $n=0$.&#xD;&#xA;&#xD;&#xA;This technique was described in this paper:&#xD;&#xA;&#xD;&#xA;&quot;Spectrally optimal sampling for distribution ray tracing&quot; Mitchell 1991.&#xD;&#xA;https://dl.acm.org/citation.cfm?id=122718.122736&#xD;&#xA;&#xD;&#xA;Below is the same setup as in the question where 455 black pixels are placed in a 64x64 image, showing the result for some values of $m$.  The quality is surprisingly good even for low values of $m$ and the execution time is much, much lower than the process described in the question.&#xD;&#xA;&#xD;&#xA;When $m=0$ is equivelant to white noise and just randomly placing the dots.&#xD;&#xA;&#xD;&#xA;Note that when calculating the distance between two points I am treating the image as if it wraps around, so that dots on opposite edges are treated close  together.  If interested in details of how to calculate distance in wrap around (toroidal) space, check out this blog post:&#xD;&#xA;https://blog.demofox.org/2017/10/01/calculating-the-distance-between-points-in-wrap-around-toroidal-space/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/blUaK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15586" PostHistoryTypeId="5" PostId="5687" RevisionGUID="7480ee83-7392-4465-ad65-3d395df4dfd0" CreationDate="2017-10-05T19:44:09.877" UserId="56" Comment="added 3 characters in body" Text="The problem turned out to be that you don't do the same number of candidates per point, but that if you have $n$ points already, you should generate $m*n$ candidates for the next point.&#xD;&#xA;&#xD;&#xA;$m$ is a tuneable parameter where in general higher values of $m$ will take longer to calculate, but will result in higher quality sampling.&#xD;&#xA;&#xD;&#xA;The reason that the candidate count should scale with the existing sample count is that it keeps statistics about the points constant, so lets you reason about how higher sample counts will look / behave by looking at lower sample counts.&#xD;&#xA;&#xD;&#xA;Values of $m$ that are too high will end up looking like the lower images of the question though, where the randomness is almost completely gone.&#xD;&#xA;&#xD;&#xA;The problem with the high sample counts is that they more fully cover all possible pixel locations, and since the best candidate is chosen, much randomness will go away leaving you with something a lot more deterministic.&#xD;&#xA;&#xD;&#xA;I personally choose to do $m*n+1$ samples to slightly simplify the logic and let it handle the first sample when $n=0$.&#xD;&#xA;&#xD;&#xA;This technique was described in this paper:&#xD;&#xA;&#xD;&#xA;&quot;Spectrally optimal sampling for distribution ray tracing&quot; Mitchell 1991.&#xD;&#xA;https://dl.acm.org/citation.cfm?id=122718.122736&#xD;&#xA;&#xD;&#xA;Below is the same setup as in the question where 455 black pixels are placed in a 64x64 image, showing the result for some values of $m$.  The quality is surprisingly good even for low values of $m$ and the execution time is much, much lower than the process described in the question.&#xD;&#xA;&#xD;&#xA;When $m=0$, it's equivelant to white noise and just randomly placing the dots.&#xD;&#xA;&#xD;&#xA;Note that when calculating the distance between two points I am treating the image as if it wraps around, so that dots on opposite edges are treated close  together.  If interested in details of how to calculate distance in wrap around (toroidal) space, check out this blog post:&#xD;&#xA;https://blog.demofox.org/2017/10/01/calculating-the-distance-between-points-in-wrap-around-toroidal-space/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/blUaK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15587" PostHistoryTypeId="5" PostId="5687" RevisionGUID="53844e50-4cb0-49bc-ac7a-e5d0fdc75437" CreationDate="2017-10-05T20:01:19.357" UserId="56" Comment="added 457 characters in body" Text="The problem turned out to be that you don't do the same number of candidates per point, but that if you have $n$ points already, you should generate $m*n$ candidates for the next point.&#xD;&#xA;&#xD;&#xA;$m$ is a tuneable parameter where in general higher values of $m$ will take longer to calculate, but will result in higher quality sampling.&#xD;&#xA;&#xD;&#xA;The reason that the candidate count should scale with the existing sample count is that it keeps statistics about the points constant, so lets you reason about how higher sample counts will look / behave by looking at lower sample counts.&#xD;&#xA;&#xD;&#xA;Values of $m$ that are too high will end up looking like the lower images of the question though, where the randomness is almost completely gone.&#xD;&#xA;&#xD;&#xA;The problem with the high sample counts is that they more fully cover all possible pixel locations, and since the best candidate is chosen, much randomness will go away leaving you with something a lot more deterministic.&#xD;&#xA;&#xD;&#xA;I personally choose to do $m*n+1$ samples to slightly simplify the logic and let it handle the first sample when $n=0$.&#xD;&#xA;&#xD;&#xA;This technique was described in this paper:&#xD;&#xA;&#xD;&#xA;&quot;Spectrally optimal sampling for distribution ray tracing&quot; Mitchell 1991.&#xD;&#xA;https://dl.acm.org/citation.cfm?id=122718.122736&#xD;&#xA;&#xD;&#xA;Below is the same setup as in the question where 455 black pixels are placed in a 64x64 image, showing the result for some values of $m$.  The quality is surprisingly good even for low values of $m$ and the execution time is much, much lower than the process described in the question.  I'm also limiting the candidate count to be at maximum 1/2 the number of pixels (an arbitrary limit I came up with) in the image to keep the candidate count from going too high for denser samplings in an effort to keep the quality and computation time decent.&#xD;&#xA;&#xD;&#xA;I've heard that storing points in grids can help in accelerating the calculation time of &quot;how far is this candidate from the closest point&quot; and I believe it should, but I haven't tried it yet.&#xD;&#xA;&#xD;&#xA;When $m=0$, it's equivelant to white noise and just randomly placing the dots.&#xD;&#xA;&#xD;&#xA;Note that when calculating the distance between two points I am treating the image as if it wraps around, so that dots on opposite edges are treated close  together.  If interested in details of how to calculate distance in wrap around (toroidal) space, check out this blog post:&#xD;&#xA;https://blog.demofox.org/2017/10/01/calculating-the-distance-between-points-in-wrap-around-toroidal-space/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/blUaK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15588" PostHistoryTypeId="2" PostId="5688" RevisionGUID="81f25812-d4c2-44f2-a7d3-18fc51675b9f" CreationDate="2017-10-05T22:07:55.657" UserId="5703" Text="Well, BSP is an application of a Binary Search Tree (BST)&#xD;&#xA;&#xD;&#xA;BSTs need a criterium to propagate the search through itself. Put simply, the criterium used in BSP is in which side of a partition a point is. Each partition just divides space in two parts. &#xD;&#xA;&#xD;&#xA;It is absolutely imposible to create a concave polygon (or polyhedron) by dividing space in halves. I dare you to try, you will see that it cannot be done" ContentLicense="CC BY-SA 3.0" />
  <row Id="15589" PostHistoryTypeId="2" PostId="5689" RevisionGUID="5c312bdf-ba2f-423b-8cad-4f9bcf716e7b" CreationDate="2017-10-06T05:25:48.573" UserId="3073" Text="Before GPUs were popular we rendered without using Z-Buffers and instead used polygon sorting to make sure things were drawn back-to-front correctly. &#xD;&#xA;&#xD;&#xA;By having a BSP with only convex geometry we guarantee that each leaf node will not have any ordering issues with the polygons contained in them, the BSP traversal algorithm itself can then produce a depth-sorted node list for you.&#xD;&#xA;&#xD;&#xA;These days we have z-buffers so the need for convex leaf nodes isn't really that important, in some ways its better to render front-to-back also to take advantage of early-z optimisations on hardware.&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="15590" PostHistoryTypeId="5" PostId="5684" RevisionGUID="392302f6-da68-4790-9940-dad7dd981fa9" CreationDate="2017-10-06T06:42:48.227" UserId="6041" Comment="added 592 characters in body" Text="I need to highlight(colour) sun reflections(through the year) off a mirror surface. It was easy having one Sun like in the below image but how about if it is to determine if a ray hits the entire surface that represents sun positions throughout the year. &#xD;&#xA; &#xD;&#xA;**Update**:&#xD;&#xA;&#xD;&#xA; Suppose the house surfaces are all mirror, so that from specific angles the viewer might see the reflection of the sun off the house surfaces. this is easy to render an image that simulate this but how about rendering an image that shows the reflection of not just one Sun, in a specific day time, but all the Suns, one for every second throughout the year. It's not efficient to dump in all these Suns into model and intersect them for each surface point. So I need to check if a ray intersects the entire surface that represents the path of the sun throughout the year.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S7EU4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15595" PostHistoryTypeId="2" PostId="5691" RevisionGUID="1984925f-3d7e-492b-a856-064549ca7e6b" CreationDate="2017-10-06T16:44:43.843" UserId="7433" Text="&gt; I have about ~200 bytes worth of data that I expect to be mostly constant. That is, I will change them very infrequently.&#xD;&#xA;&#xD;&#xA;If the data changes infrequently, you can use [Specialization Constants](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#pipelines-specialization-constants). They are set when the pipeline is created, and a new pipeline must be created if you need to change the values. For an infrequent event, like a window resize, this may be an acceptable cost.&#xD;&#xA;&#xD;&#xA;&gt;  what if I have e.g. a float random_seed that I will update every time the shader is run? &#xD;&#xA;&#xD;&#xA;That's a perfect use case for Push Constants. You can keep all the other data in the UBO (or in the Specialization Constants) and change this value with `VkCmdPushConstants`." ContentLicense="CC BY-SA 3.0" />
  <row Id="15598" PostHistoryTypeId="2" PostId="5692" RevisionGUID="ae8abe24-8444-4c56-9666-54d7bb8c8c20" CreationDate="2017-10-07T12:47:13.060" UserId="7434" Text="I have an RGB pixel that I'd like to colorize in my program (I'm using GLSL) very similar to how the GIMP &quot;Colors &gt; Colorize&quot; function works.&#xD;&#xA;&#xD;&#xA;[![GIMP's Colorize][1]][1]&#xD;&#xA;&#xD;&#xA;In my program, I can easily convert between RGB and HSV. I can therefore get:&#xD;&#xA;&#xD;&#xA;pix_h, pix_s, pix_v&#xD;&#xA;&#xD;&#xA;And I also define the inputs of the colorize function as:&#xD;&#xA;&#xD;&#xA;col_h, col_s, col_v&#xD;&#xA;&#xD;&#xA;What calculations can I perform to determine the output pixel hsv?&#xD;&#xA;&#xD;&#xA;I think I can get:&#xD;&#xA;&#xD;&#xA;out_h = col_h&#xD;&#xA;&#xD;&#xA;But I'm a little lost on how to calculate output saturation and value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gDWgl.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15599" PostHistoryTypeId="1" PostId="5692" RevisionGUID="ae8abe24-8444-4c56-9666-54d7bb8c8c20" CreationDate="2017-10-07T12:47:13.060" UserId="7434" Text="How can I implement GIMP's &quot;Colorize&quot; function?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15600" PostHistoryTypeId="3" PostId="5692" RevisionGUID="ae8abe24-8444-4c56-9666-54d7bb8c8c20" CreationDate="2017-10-07T12:47:13.060" UserId="7434" Text="|transformations|glsl|color|2d|pixel-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15601" PostHistoryTypeId="5" PostId="5679" RevisionGUID="6ee1d3d9-7e43-4f8f-bdea-76d658325136" CreationDate="2017-10-07T13:37:40.720" UserId="2287" Comment="added 383 characters in body" Text="**Spotlight**&#xD;&#xA;&#xD;&#xA;My spotlight's intensity is cut off at a distance of 3 and at an angle of $\pi/4$ radians (umbra angle). The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. The spotlight is positioned somewhere above the tree and faces downward to the floor.&#xD;&#xA;&#xD;&#xA;The shadow map of my spotlight has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each spotlight);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DArray` for all, spotlights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow maps.&#xD;&#xA;     @param[in]		p_proj&#xD;&#xA;    				The hit position in light projection space coordinates.&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler,&#xD;&#xA;    	Texture2DArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float4 p_proj) {&#xD;&#xA;    &#xD;&#xA;    	const float  inv_w  = 1.0f / p_proj.w;&#xD;&#xA;    	const float3 p_ndc  = p_proj.xyz * inv_w;&#xD;&#xA;    	const float3 loc    = float3(NDCtoUV(p_ndc.xy), index);&#xD;&#xA;    	&#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light projection space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float4 p_proj = mul(float4(p, 1.0f), light.cview_to_lprojection);&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (*this is not the light contribution of the spotlight*) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This seems to result in the correct behavior (see the shadows of the leaves, pillars and curtains). *The bright border on the first image starts at the position of the spotlight and is due to the near plane distance of 0.1. This border will completely vanish after multiplying the shadow factor with the spotlight's contribution.*&#xD;&#xA;&#xD;&#xA;**Omni light**&#xD;&#xA;&#xD;&#xA;My omni light's intensity is cut off at a distance of 3. The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. This means that one of the six light cameras (after applying some rotations), is completely identical to the spotlight camera above. I double checked this in the code:&#xD;&#xA;&#xD;&#xA;Frame 1: &#xD;&#xA;`world_to_lprojection` (spotlight):&#xD;&#xA;&#xD;&#xA;    1.16532457,  0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` (fourth omni light camera):&#xD;&#xA;&#xD;&#xA;    1.16532457, 0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` represents the world-to-light-projection transformation matrix (*world-to-camera-view-to-world-to-light-view-to-light-projection*). *I go to camera view first to mimic the same multiplications between my depth passes and shading passes to reduce z-fighting (although, this does not result in visual differences so far).*&#xD;&#xA;&#xD;&#xA;So apart from the fact that a spotlight corresponds to one DSV (and is part of one SRV to a `Texture2DArray` for all spotlight shadow maps) and an omni light corresponds to six DSVs (and is part of one SRV to a `Texture2DCubeArray` for all omni light shadow cube maps), the shadow map generation is pretty much the same for both types of lights.&#xD;&#xA;&#xD;&#xA;The shadow map of my omni light has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each omni light);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DCubeArray` for all, omni lights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow cube map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow cube maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow cube maps.&#xD;&#xA;     @param[in]		p_view&#xD;&#xA;    				The hit position in light view space coordinates.&#xD;&#xA;     @param[in]		projection_values&#xD;&#xA;    				The projection values [view_projection22, view_projection32].&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler, &#xD;&#xA;    	TextureCubeArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float3 p_view, float2 projection_values) {&#xD;&#xA;    &#xD;&#xA;    	const float p_view_z = Max(abs(p_view));&#xD;&#xA;    	const float p_ndc_z  = ViewZtoNDCZ(p_view_z, projection_values);&#xD;&#xA;    	const float4 loc     = float4(p_view, index);&#xD;&#xA;    &#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc_z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light view space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float3 p_view = mul(float4(p, 1.0f), light.cview_to_lview).xyz;&#xD;&#xA;&#xD;&#xA;The conversion of the z coordinate to NDC space is done as follows:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Converts the given (linear) view z-coordinate to the (non-linear) NDC &#xD;&#xA;     z-coordinate.&#xD;&#xA;    &#xD;&#xA;     @param[in]     p_view_z&#xD;&#xA;                    The (linear) view z-coordinate.&#xD;&#xA;     @param[in]     projection_values&#xD;&#xA;                    The projection values [view_projection22, view_projection32].&#xD;&#xA;     @return        The (non-linear) NDC z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    float ViewZtoNDCZ(float p_view_z, float2 projection_values) {&#xD;&#xA;        return projection_values.x + projection_values.y / p_view_z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with the following dual C++ method:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Returns the projection values from the given projection matrix to construct &#xD;&#xA;     the NDC position z-coordinate from the view position z-coordinate.&#xD;&#xA;&#xD;&#xA;     @return        The projection values from the given projection matrix to &#xD;&#xA;                    construct the NDC position z-coordinate from the view position &#xD;&#xA;                    z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    inline const XMVECTOR XM_CALLCONV GetNDCZConstructionValues(&#xD;&#xA;        FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;&#xD;&#xA;        //        [ _  0  0  0 ]&#xD;&#xA;        // p_view [ 0  _  0  0 ] = [_, _, p_view.z * X + Y, p_view.z] = p_proj&#xD;&#xA;        //        [ 0  0  X  1 ]&#xD;&#xA;        //        [ 0  0  Y  0 ]&#xD;&#xA;        //&#xD;&#xA;        // p_proj / p_proj.w     = [_, _, X + Y/p_view.z, 1] = p_ndc&#xD;&#xA;        //&#xD;&#xA;        // Construction of p_ndc.z from p_view and projection values&#xD;&#xA;        // p_ndc.z = X + Y/p_view.z&#xD;&#xA;&#xD;&#xA;        const F32 x = XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;        const F32 y = XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;        &#xD;&#xA;        return XMVectorSet(x, y, 0.0f, 0.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (this is not the light contribution of the omni light) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is clearly wrong. All six shadow maps seem kind of **stretched**. Without the stretching, the curtain's shadow would still be in the close vicinity of the curtain itself and the leaves' shadow would be much smaller (equal to the leaves' shadow for the spotlight). Furthermore, the circular shadow at the end of the pillar's shadow is associated to the buckets in front of the curtains.&#xD;&#xA;&#xD;&#xA;Any ideas what goes or could go wrong?&#xD;&#xA;&#xD;&#xA;An other strange observation is that using a depth value of 1.1 for my spotlight's PCF filtering (`SampleCmpLevelZero`) always results in a 0 value as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;whereas for my omni light this is not the case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Even if I use a value equal to 100000.0, I'll notice lit areas?&#xD;&#xA;&#xD;&#xA;**Depth Biasing**&#xD;&#xA;&#xD;&#xA;I use `DepthBias = 100;` (to prevent shadow acne; note that I use 16bit depth maps) `SlopeScaledDepthBias = 0.0f; DepthBiasClamp = 0.0f;` for all my Rasterizer states.&#xD;&#xA;&#xD;&#xA;**PCF filtering**&#xD;&#xA;&#xD;&#xA;I use the following sampler comparison state for PCF filtering (*my shadow maps have no mipmaps*) for both spotlights and omni lights. &#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC desc = {};&#xD;&#xA;    desc.Filter         = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;&#xD;&#xA;    desc.AddressU       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressV       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressW       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.MaxAnisotropy  = (device-&gt;GetFeatureLevel() &gt; D3D_FEATURE_LEVEL_9_1) &#xD;&#xA;    								? D3D11_MAX_MAXANISOTROPY : 2;&#xD;&#xA;    desc.MaxLOD         = D3D11_FLOAT32_MAX;&#xD;&#xA;    desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Al0D.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DW86m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hQ0sB.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zedO9.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/49GZW.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/9vBBr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15602" PostHistoryTypeId="2" PostId="5693" RevisionGUID="1253607f-33bb-4e20-aa2a-f3cbe295be41" CreationDate="2017-10-07T14:40:17.987" UserId="7435" Text="A few days ago I found a video on Twitter showing the Evans &amp; Sutherland CT5 Flight Simulator system. It was labeled as 1981 footage and looked really amazing. The first time I saw similar 3D grahics in computer games was in the late 90s and in ealy 2000s. I wasn't suspisous because it was described as a product made for the military and I thought it's normal the technology to be more advanced.&#xD;&#xA;&#xD;&#xA;Yesterday I showed the video to my colleagues, all of them experienced developers and computer gurus, and they said it's impossible such graphics to be achieved in the 80's. I tried to search for a proof but I found none except a short documentary on YouTube and some forum topics where people were discussing how it was achieved without mentioning anything about the exact year. I found no definitive proof that the year of creation of CT5 system was 1981. No product specifications, no publications in wellknown newspapers and not even a Wikipedia article. I'm amazed how little information is out there about something so astonishing. And this is one of the things that fuel the doubt of my colleagues.&#xD;&#xA;&#xD;&#xA;Was Evans &amp; Sutherland CT5 really created in 1981 or at least from the same decade?&#xD;&#xA;&#xD;&#xA;My colleagues are with a high self esteem and it's hard to change their opinion on something. I'll appreciate any resource that proves or disproves the existance of such advanced graphics in the early 80s as well as some details how it was made.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the link below you can see the two parts of the documentary I mentioned earlier and a short forum discussion about the CT5 and similar technologies. My colleagues don't consider it a sufficient proof.&#xD;&#xA;&#xD;&#xA;[CT5 Evans Sutherland Simulator - How did it work?][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://forum.beyond3d.com/threads/ct5-evans-sutherland-simulator-how-did-it-work.57664/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15603" PostHistoryTypeId="1" PostId="5693" RevisionGUID="1253607f-33bb-4e20-aa2a-f3cbe295be41" CreationDate="2017-10-07T14:40:17.987" UserId="7435" Text="Was Evans &amp; Sutherland CT5 really created in 1981?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15604" PostHistoryTypeId="3" PostId="5693" RevisionGUID="1253607f-33bb-4e20-aa2a-f3cbe295be41" CreationDate="2017-10-07T14:40:17.987" UserId="7435" Text="|3d|image-processing|animation|video|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15605" PostHistoryTypeId="5" PostId="5692" RevisionGUID="7813b692-6df1-4bd4-be82-5ba254f30f41" CreationDate="2017-10-07T17:01:11.023" UserId="7434" Comment="added 294 characters in body" Text="I have an RGB pixel that I'd like to colorize in my program (I'm using GLSL) very similar to how the GIMP &quot;Colors &gt; Colorize&quot; function works.&#xD;&#xA;&#xD;&#xA;[![GIMP's Colorize][1]][1]&#xD;&#xA;&#xD;&#xA;In my program, I can easily convert between RGB and HSV. I can therefore get:&#xD;&#xA;&#xD;&#xA;pix_h, pix_s, pix_v&#xD;&#xA;&#xD;&#xA;And I also define the inputs of the colorize function as:&#xD;&#xA;&#xD;&#xA;col_h, col_s, col_v&#xD;&#xA;&#xD;&#xA;What calculations can I perform to determine the output pixel hsv?&#xD;&#xA;&#xD;&#xA;I think I can get:&#xD;&#xA;&#xD;&#xA;out_h = col_h&#xD;&#xA;&#xD;&#xA;But I'm a little lost on how to calculate output saturation and value.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Where lum is the luminance of the input pixel:&#xD;&#xA;&#xD;&#xA;out_s = clamp( (1 - pix_v) * 2, 0, 1)&#xD;&#xA;&#xD;&#xA;out_v = clamp( pix_v * 2, 0, 1)&#xD;&#xA;&#xD;&#xA;seems to produce good results when colorize inputs S=1 ([0, 1]) and V=.5 ([0, 1]). I'm still struggling to generalize these formulas for when S!=1 and V!=.5.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gDWgl.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15606" PostHistoryTypeId="2" PostId="5694" RevisionGUID="539a517b-ca94-4a55-9f70-c440c6b0eec0" CreationDate="2017-10-07T17:21:21.503" UserId="4908" Text="After some searching on the internet, I am fairly certain that it was made in 1981 or at least the same decade. I have found multiple sources that indicate the CT5 was made in or around the year 1981.&#xD;&#xA;&#xD;&#xA;The first bit is in one of the promotional videos they made. At the very end there is a copyright statement. &quot;(C) November, 1981&quot;. I would already believe this as it looks to be integrated into the video, meaning it would be quite impressive if somebody would have edited it. To me, there seems no reason to put in a false date for the copyright as, I would imagine, it invalidates the copyright statement. It can be found at 3:22 in this video: [https://www.youtube.com/watch?v=7e7_GiCc-HA][1]&#xD;&#xA;&#xD;&#xA;I found a pdf scan from an article, written 24th of April 1982, about the CT5. It can be found here, [https://www.flightglobal.com/FlightPDFArchive/1982/1982%20-%201104.PDF][2].&#xD;&#xA;&#xD;&#xA;I also found a book called &quot;Modeling and Simulation:: Linking Entertainment and Defense&quot;, which has a brief bit about the CT5. It states, &quot;Nevertheless, the E&amp;S CT5 (circa 1983) and the GE Compuscene 4 Computer Image generators were benchmarks by which all interactive computer graphics systems were measured for years.&quot;. This book says that it was around 1983 which does seem to support the claim of 1981, but it might have been a few years later. It can be found here, [https://books.google.nl/books?id=HTkrAAAAYAAJ&amp;pg=PA36&amp;lpg=PA36&amp;dq=e%26s+ct5&amp;source=bl&amp;ots=xka2n-9Uxx&amp;sig=wfscYmgDGXB7AOlq00R9QtxDD60&amp;hl=nl&amp;sa=X&amp;ved=0ahUKEwjustWX8t7WAhWJL1AKHT4wDhQQ6AEIQTAD#v=onepage&amp;q=e%26s%20ct5&amp;f=false][3] &#xD;&#xA;&#xD;&#xA;Then I also found a patent filed by E&amp;S for &quot;Computer graphics system of general surface rendering by exhaustive sampling&quot; in 1985. It has talked about doing rendering surfaces with a z buffer. It can be found here, [https://patents.justia.com/patent/4625289][4]&#xD;&#xA;&#xD;&#xA;Then there is another patent filled in 1982 for &quot;Graphics display system using logic-enhanced pixel memory cells&quot;, which claims it is capable real time. It can be found here, [https://www.google.com/patents/US4590465?dq=EVANS+%26amp;+SUTHERLAND&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwie5K-x-97WAhXKnRoKHduFAWo4ChDoAQgnMAA][5]&#xD;&#xA;&#xD;&#xA;These two patents show that in the 80's they already have the technology for real time graphics.&#xD;&#xA;&#xD;&#xA;The forum discussion had a quote from a Wikipedia article which is from the following article, [https://en.wikipedia.org/wiki/Framebuffer][6]. This is more in case someone wants to know where it came from.&#xD;&#xA;&#xD;&#xA;It does seem like the technology was there and with a big enough budget, you just needed to gather it and make it into something like the CT5. You have 3 different sources that all show that the CT5 was created around 1981, and 2 sources that show the technology was there. Yes, you can still argue about the sources, but honestly then you can argue any fact in a history textbook.&#xD;&#xA;&#xD;&#xA;I hope that this answers your question or at least has informed you about something you might not have known.&#xD;&#xA;&#xD;&#xA;Hope you will have a lovely day and good luck!&#xD;&#xA;&#xD;&#xA;bram0101&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=7e7_GiCc-HA&#xD;&#xA;  [2]: https://www.flightglobal.com/FlightPDFArchive/1982/1982%20-%201104.PDF&#xD;&#xA;  [3]: https://books.google.nl/books?id=HTkrAAAAYAAJ&amp;pg=PA36&amp;lpg=PA36&amp;dq=e%26s%20ct5&amp;source=bl&amp;ots=xka2n-9Uxx&amp;sig=wfscYmgDGXB7AOlq00R9QtxDD60&amp;hl=nl&amp;sa=X&amp;ved=0ahUKEwjustWX8t7WAhWJL1AKHT4wDhQQ6AEIQTAD#v=onepage&amp;q=e%26s%20ct5&amp;f=false&#xD;&#xA;  [4]: https://patents.justia.com/patent/4625289&#xD;&#xA;  [5]: https://www.google.com/patents/US4590465?dq=EVANS%20%26amp;%20SUTHERLAND&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwie5K-x-97WAhXKnRoKHduFAWo4ChDoAQgnMAA&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Framebuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="15607" PostHistoryTypeId="5" PostId="5694" RevisionGUID="0d601240-4eb4-473f-8286-9b980d7023b6" CreationDate="2017-10-08T01:58:12.557" UserId="3003" Comment="Removed personal closing." Text="After some searching on the internet, I am fairly certain that it was made in 1981 or at least the same decade. I have found multiple sources that indicate the CT5 was made in or around the year 1981.&#xD;&#xA;&#xD;&#xA;The first bit is in one of the promotional videos they made. At the very end there is a copyright statement. &quot;(C) November, 1981&quot;. I would already believe this as it looks to be integrated into the video, meaning it would be quite impressive if somebody would have edited it. To me, there seems no reason to put in a false date for the copyright as, I would imagine, it invalidates the copyright statement. It can be found at 3:22 in this video: [https://www.youtube.com/watch?v=7e7_GiCc-HA][1]&#xD;&#xA;&#xD;&#xA;I found a pdf scan from an article, written 24th of April 1982, about the CT5. It can be found here, [https://www.flightglobal.com/FlightPDFArchive/1982/1982%20-%201104.PDF][2].&#xD;&#xA;&#xD;&#xA;I also found a book called &quot;Modeling and Simulation:: Linking Entertainment and Defense&quot;, which has a brief bit about the CT5. It states, &quot;Nevertheless, the E&amp;S CT5 (circa 1983) and the GE Compuscene 4 Computer Image generators were benchmarks by which all interactive computer graphics systems were measured for years.&quot;. This book says that it was around 1983 which does seem to support the claim of 1981, but it might have been a few years later. It can be found here, [https://books.google.nl/books?id=HTkrAAAAYAAJ&amp;pg=PA36&amp;lpg=PA36&amp;dq=e%26s+ct5&amp;source=bl&amp;ots=xka2n-9Uxx&amp;sig=wfscYmgDGXB7AOlq00R9QtxDD60&amp;hl=nl&amp;sa=X&amp;ved=0ahUKEwjustWX8t7WAhWJL1AKHT4wDhQQ6AEIQTAD#v=onepage&amp;q=e%26s%20ct5&amp;f=false][3] &#xD;&#xA;&#xD;&#xA;Then I also found a patent filed by E&amp;S for &quot;Computer graphics system of general surface rendering by exhaustive sampling&quot; in 1985. It has talked about doing rendering surfaces with a z buffer. It can be found here, [https://patents.justia.com/patent/4625289][4]&#xD;&#xA;&#xD;&#xA;Then there is another patent filled in 1982 for &quot;Graphics display system using logic-enhanced pixel memory cells&quot;, which claims it is capable real time. It can be found here, [https://www.google.com/patents/US4590465?dq=EVANS+%26amp;+SUTHERLAND&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwie5K-x-97WAhXKnRoKHduFAWo4ChDoAQgnMAA][5]&#xD;&#xA;&#xD;&#xA;These two patents show that in the 80's they already have the technology for real time graphics.&#xD;&#xA;&#xD;&#xA;The forum discussion had a quote from a Wikipedia article which is from the following article, [https://en.wikipedia.org/wiki/Framebuffer][6]. This is more in case someone wants to know where it came from.&#xD;&#xA;&#xD;&#xA;It does seem like the technology was there and with a big enough budget, you just needed to gather it and make it into something like the CT5. You have 3 different sources that all show that the CT5 was created around 1981, and 2 sources that show the technology was there. Yes, you can still argue about the sources, but honestly then you can argue any fact in a history textbook.&#xD;&#xA;&#xD;&#xA;I hope that this answers your question or at least has informed you about something you might not have known.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=7e7_GiCc-HA&#xD;&#xA;  [2]: https://www.flightglobal.com/FlightPDFArchive/1982/1982%20-%201104.PDF&#xD;&#xA;  [3]: https://books.google.nl/books?id=HTkrAAAAYAAJ&amp;pg=PA36&amp;lpg=PA36&amp;dq=e%26s%20ct5&amp;source=bl&amp;ots=xka2n-9Uxx&amp;sig=wfscYmgDGXB7AOlq00R9QtxDD60&amp;hl=nl&amp;sa=X&amp;ved=0ahUKEwjustWX8t7WAhWJL1AKHT4wDhQQ6AEIQTAD#v=onepage&amp;q=e%26s%20ct5&amp;f=false&#xD;&#xA;  [4]: https://patents.justia.com/patent/4625289&#xD;&#xA;  [5]: https://www.google.com/patents/US4590465?dq=EVANS%20%26amp;%20SUTHERLAND&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwie5K-x-97WAhXKnRoKHduFAWo4ChDoAQgnMAA&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Framebuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="15608" PostHistoryTypeId="2" PostId="5695" RevisionGUID="3017ced7-cbb8-47aa-9336-c94bb338b82f" CreationDate="2017-10-08T02:07:17.910" UserId="3003" Text="It appears to me that in the image, the saturation of the original image is 0 since it is grayscale. (Unless I've misunderstood the question.) When the saturation is 0, the hue is undefined, but it appears that the GIMP is setting the hue to 0. It is then using the sliders from the dialog to modify the HSL. It adds 180° to the hue (so from 0 to 180 which gets you from red to cyan). The saturation is increased by 75 units, and the lightness is kept the same. It may have special protections for black and white, given that the white part of the letter &quot;A&quot; remains white in the final image (although even there, it appears to have an RGB value of (0.99, 1.0, 1.0), whereas on the right, it's fully white (1.0, 1.0, 1.0)).&#xD;&#xA;&#xD;&#xA;You can always look at the [source code](https://www.gimp.org/source/#gimp-source-code) since it's an open source package." ContentLicense="CC BY-SA 3.0" />
  <row Id="15609" PostHistoryTypeId="5" PostId="5679" RevisionGUID="2473da4b-14e9-4a5e-aad8-2dd68eabbdf7" CreationDate="2017-10-08T14:17:24.180" UserId="2287" Comment="added 407 characters in body" Text="**Spotlight**&#xD;&#xA;&#xD;&#xA;My spotlight's intensity is cut off at a distance of 3 and at an angle of $\pi/4$ radians (umbra angle). The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. The spotlight is positioned somewhere above the tree and faces downward to the floor.&#xD;&#xA;&#xD;&#xA;The shadow map of my spotlight has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each spotlight);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DArray` for all, spotlights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow maps.&#xD;&#xA;     @param[in]		p_proj&#xD;&#xA;    				The hit position in light projection space coordinates.&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler,&#xD;&#xA;    	Texture2DArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float4 p_proj) {&#xD;&#xA;    &#xD;&#xA;    	const float  inv_w  = 1.0f / p_proj.w;&#xD;&#xA;    	const float3 p_ndc  = p_proj.xyz * inv_w;&#xD;&#xA;    	const float3 loc    = float3(NDCtoUV(p_ndc.xy), index);&#xD;&#xA;    	&#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light projection space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float4 p_proj = mul(float4(p, 1.0f), light.cview_to_lprojection);&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (*this is not the light contribution of the spotlight*) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This seems to result in the correct behavior (see the shadows of the leaves, pillars and curtains). *The bright border on the first image starts at the position of the spotlight and is due to the near plane distance of 0.1. This border will completely vanish after multiplying the shadow factor with the spotlight's contribution.*&#xD;&#xA;&#xD;&#xA;**Omni light**&#xD;&#xA;&#xD;&#xA;My omni light's intensity is cut off at a distance of 3. The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. This means that one of the six light cameras (after applying some rotations), is completely identical to the spotlight camera above. I double checked this in the code:&#xD;&#xA;&#xD;&#xA;Frame 1: &#xD;&#xA;`world_to_lprojection` (spotlight):&#xD;&#xA;&#xD;&#xA;    1.16532457,  0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` (fourth omni light camera):&#xD;&#xA;&#xD;&#xA;    1.16532457, 0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` represents the world-to-light-projection transformation matrix (*world-to-camera-view-to-world-to-light-view-to-light-projection*). *I go to camera view first to mimic the same multiplications between my depth passes and shading passes to reduce z-fighting (although, this does not result in visual differences so far).*&#xD;&#xA;&#xD;&#xA;So apart from the fact that a spotlight corresponds to one DSV (and is part of one SRV to a `Texture2DArray` for all spotlight shadow maps) and an omni light corresponds to six DSVs (and is part of one SRV to a `Texture2DCubeArray` for all omni light shadow cube maps), the shadow map generation is pretty much the same for both types of lights.&#xD;&#xA;&#xD;&#xA;The shadow map of my omni light has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each omni light);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DCubeArray` for all, omni lights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow cube map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow cube maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow cube maps.&#xD;&#xA;     @param[in]		p_view&#xD;&#xA;    				The hit position in light view space coordinates.&#xD;&#xA;     @param[in]		projection_values&#xD;&#xA;    				The projection values [view_projection22, view_projection32].&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler, &#xD;&#xA;    	TextureCubeArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float3 p_view, float2 projection_values) {&#xD;&#xA;    &#xD;&#xA;    	const float p_view_z = Max(abs(p_view));&#xD;&#xA;    	const float p_ndc_z  = ViewZtoNDCZ(p_view_z, projection_values);&#xD;&#xA;    	const float4 loc     = float4(p_view, index);&#xD;&#xA;    &#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc_z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light view space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float3 p_view = mul(float4(p, 1.0f), light.cview_to_lview).xyz;&#xD;&#xA;&#xD;&#xA;The conversion of the z coordinate to NDC space is done as follows:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Converts the given (linear) view z-coordinate to the (non-linear) NDC &#xD;&#xA;     z-coordinate.&#xD;&#xA;    &#xD;&#xA;     @param[in]     p_view_z&#xD;&#xA;                    The (linear) view z-coordinate.&#xD;&#xA;     @param[in]     projection_values&#xD;&#xA;                    The projection values [view_projection22, view_projection32].&#xD;&#xA;     @return        The (non-linear) NDC z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    float ViewZtoNDCZ(float p_view_z, float2 projection_values) {&#xD;&#xA;        return projection_values.x + projection_values.y / p_view_z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with the following dual C++ method:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Returns the projection values from the given projection matrix to construct &#xD;&#xA;     the NDC position z-coordinate from the view position z-coordinate.&#xD;&#xA;&#xD;&#xA;     @return        The projection values from the given projection matrix to &#xD;&#xA;                    construct the NDC position z-coordinate from the view position &#xD;&#xA;                    z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    inline const XMVECTOR XM_CALLCONV GetNDCZConstructionValues(&#xD;&#xA;        FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;&#xD;&#xA;        //        [ _  0  0  0 ]&#xD;&#xA;        // p_view [ 0  _  0  0 ] = [_, _, p_view.z * X + Y, p_view.z] = p_proj&#xD;&#xA;        //        [ 0  0  X  1 ]&#xD;&#xA;        //        [ 0  0  Y  0 ]&#xD;&#xA;        //&#xD;&#xA;        // p_proj / p_proj.w     = [_, _, X + Y/p_view.z, 1] = p_ndc&#xD;&#xA;        //&#xD;&#xA;        // Construction of p_ndc.z from p_view and projection values&#xD;&#xA;        // p_ndc.z = X + Y/p_view.z&#xD;&#xA;&#xD;&#xA;        const F32 x = XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;        const F32 y = XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;        &#xD;&#xA;        return XMVectorSet(x, y, 0.0f, 0.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (this is not the light contribution of the omni light) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is clearly wrong. All six shadow maps seem kind of **stretched**. Without the stretching, the curtain's shadow would still be in the close vicinity of the curtain itself and the leaves' shadow would be much smaller (equal to the leaves' shadow for the spotlight). Furthermore, the circular shadow at the end of the pillar's shadow is associated to the buckets in front of the curtains.&#xD;&#xA;&#xD;&#xA;Any ideas what goes or could go wrong?&#xD;&#xA;&#xD;&#xA;For clarity, the following two images show the shadow factor of the cube map face corresponding to the spotlight, for the omni light by adding:&#xD;&#xA;&#xD;&#xA;    if (p_view_z != -p_view.y) {&#xD;&#xA;    	return 0.0f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;**SampleCmpLevelZero**&#xD;&#xA;&#xD;&#xA;An other strange observation is that using a depth value of 1.1 for my spotlight's PCF filtering (`SampleCmpLevelZero`) always results in a 0 value as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;whereas for my omni light this is not the case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;Even if I use a value equal to 100000.0, I'll notice lit areas?&#xD;&#xA;&#xD;&#xA;**Depth Biasing**&#xD;&#xA;&#xD;&#xA;I use `DepthBias = 100;` (to prevent shadow acne; note that I use 16bit depth maps) `SlopeScaledDepthBias = 0.0f; DepthBiasClamp = 0.0f;` for all my Rasterizer states.&#xD;&#xA;&#xD;&#xA;**PCF filtering**&#xD;&#xA;&#xD;&#xA;I use the following sampler comparison state for PCF filtering (*my shadow maps have no mipmaps*) for both spotlights and omni lights. &#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC desc = {};&#xD;&#xA;    desc.Filter         = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;&#xD;&#xA;    desc.AddressU       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressV       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressW       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.MaxAnisotropy  = (device-&gt;GetFeatureLevel() &gt; D3D_FEATURE_LEVEL_9_1) &#xD;&#xA;    								? D3D11_MAX_MAXANISOTROPY : 2;&#xD;&#xA;    desc.MaxLOD         = D3D11_FLOAT32_MAX;&#xD;&#xA;    desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Al0D.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DW86m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hQ0sB.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zedO9.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/4B8dZ.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/T4oQV.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/49GZW.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/9vBBr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15610" PostHistoryTypeId="5" PostId="5679" RevisionGUID="e5baa02a-f580-4aac-96ba-80048dc7cec3" CreationDate="2017-10-08T14:47:52.287" UserId="2287" Comment="added 71 characters in body" Text="**Spotlight**&#xD;&#xA;&#xD;&#xA;My spotlight's intensity is cut off at a distance of 3 and at an angle of $\pi/4$ radians (umbra angle). The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. The spotlight is positioned somewhere above the tree and faces downward to the floor.&#xD;&#xA;&#xD;&#xA;The shadow map of my spotlight has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each spotlight);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DArray` for all, spotlights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow maps.&#xD;&#xA;     @param[in]		p_proj&#xD;&#xA;    				The hit position in light projection space coordinates.&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler,&#xD;&#xA;    	Texture2DArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float4 p_proj) {&#xD;&#xA;    &#xD;&#xA;    	const float  inv_w  = 1.0f / p_proj.w;&#xD;&#xA;    	const float3 p_ndc  = p_proj.xyz * inv_w;&#xD;&#xA;    	const float3 loc    = float3(NDCtoUV(p_ndc.xy), index);&#xD;&#xA;    	&#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light projection space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float4 p_proj = mul(float4(p, 1.0f), light.cview_to_lprojection);&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (*this is not the light contribution of the spotlight*) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This seems to result in the correct behavior (see the shadows of the leaves, pillars and curtains). *The bright border on the first image starts at the position of the spotlight and is due to the near plane distance of 0.1. This border will completely vanish after multiplying the shadow factor with the spotlight's contribution.*&#xD;&#xA;&#xD;&#xA;**Omni light**&#xD;&#xA;&#xD;&#xA;My omni light's intensity is cut off at a distance of 3. The corresponding light camera has a near plane at a distance of 0.1, a far plane at a distance of 3, an aspect ratio of 1 and a vertical/horizontal FOV of $\pi/2$. This means that one of the six light cameras (after applying some rotations), is completely identical to the spotlight camera above. I double checked this in the code:&#xD;&#xA;&#xD;&#xA;Frame 1: &#xD;&#xA;`world_to_lprojection` (spotlight):&#xD;&#xA;&#xD;&#xA;    1.16532457,  0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` (fourth omni light camera):&#xD;&#xA;&#xD;&#xA;    1.16532457, 0.000000000, 0.000000000, 0.000000000&#xD;&#xA;    0.000000000, -2.18211127e-07, -1.03448260, -0.999999881&#xD;&#xA;    0.000000000, 1.83048737, -1.23319950e-07, -1.19209290e-07&#xD;&#xA;    0.000000000, 4.36422255e-07, 1.96551692, 1.99999976&#xD;&#xA;&#xD;&#xA;`world_to_lprojection` represents the world-to-light-projection transformation matrix (*world-to-camera-view-to-world-to-light-view-to-light-projection*). *I go to camera view first to mimic the same multiplications between my depth passes and shading passes to reduce z-fighting (although, this does not result in visual differences so far).*&#xD;&#xA;&#xD;&#xA;So apart from the fact that a spotlight corresponds to one DSV (and is part of one SRV to a `Texture2DArray` for all spotlight shadow maps) and an omni light corresponds to six DSVs (and is part of one SRV to a `Texture2DCubeArray` for all omni light shadow cube maps), the shadow map generation is pretty much the same for both types of lights.&#xD;&#xA;&#xD;&#xA;The shadow map of my omni light has a resolution of 512x512. I use the following DXGI formats:&#xD;&#xA;&#xD;&#xA; - `DXGI_FORMAT_R16_TYPELESS`: texture resource;&#xD;&#xA; - `DXGI_FORMAT_D16_UNORM`: DSV (one for each omni light);&#xD;&#xA; - `DXGI_FORMAT_R16_UNORM`: SRV (one `Texture2DCubeArray` for all, omni lights).&#xD;&#xA;&#xD;&#xA;My shadow factor is calculated in HLSL as:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Calculates the shadow factor.&#xD;&#xA;    &#xD;&#xA;     @pre			@a shadow_maps must contain a shadow cube map at index @a index.&#xD;&#xA;     @param[in]		pcf_sampler&#xD;&#xA;    				The PCF sampler comparison state.&#xD;&#xA;     @param[in]		shadow_maps&#xD;&#xA;    				The array of shadow cube maps.&#xD;&#xA;     @param[in]		index&#xD;&#xA;    				The index into the array of shadow cube maps.&#xD;&#xA;     @param[in]		p_view&#xD;&#xA;    				The hit position in light view space coordinates.&#xD;&#xA;     @param[in]		projection_values&#xD;&#xA;    				The projection values [view_projection22, view_projection32].&#xD;&#xA;     */&#xD;&#xA;    float ShadowFactor(SamplerComparisonState pcf_sampler, &#xD;&#xA;    	TextureCubeArray&lt; float &gt; shadow_maps, uint index,&#xD;&#xA;    	float3 p_view, float2 projection_values) {&#xD;&#xA;    &#xD;&#xA;    	const float p_view_z = Max(abs(p_view));&#xD;&#xA;    	const float p_ndc_z  = ViewZtoNDCZ(p_view_z, projection_values);&#xD;&#xA;    	const float4 loc     = float4(p_view, index);&#xD;&#xA;    &#xD;&#xA;    	return shadow_maps.SampleCmpLevelZero(pcf_sampler, loc, p_ndc_z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here, the hit position in light view space coordinates is calculated as follows from the hit position in camera view space coordinates (shading space):&#xD;&#xA;&#xD;&#xA;    const float3 p_view = mul(float4(p, 1.0f), light.cview_to_lview).xyz;&#xD;&#xA;&#xD;&#xA;The conversion of the z coordinate to NDC space is done as follows:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Converts the given (linear) view z-coordinate to the (non-linear) NDC &#xD;&#xA;     z-coordinate.&#xD;&#xA;    &#xD;&#xA;     @param[in]     p_view_z&#xD;&#xA;                    The (linear) view z-coordinate.&#xD;&#xA;     @param[in]     projection_values&#xD;&#xA;                    The projection values [view_projection22, view_projection32].&#xD;&#xA;     @return        The (non-linear) NDC z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    float ViewZtoNDCZ(float p_view_z, float2 projection_values) {&#xD;&#xA;        return projection_values.x + projection_values.y / p_view_z;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with the following dual C++ method:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Returns the projection values from the given projection matrix to construct &#xD;&#xA;     the NDC position z-coordinate from the view position z-coordinate.&#xD;&#xA;&#xD;&#xA;     @return        The projection values from the given projection matrix to &#xD;&#xA;                    construct the NDC position z-coordinate from the view position &#xD;&#xA;                    z-coordinate.&#xD;&#xA;     */&#xD;&#xA;    inline const XMVECTOR XM_CALLCONV GetNDCZConstructionValues(&#xD;&#xA;        FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;&#xD;&#xA;        //        [ _  0  0  0 ]&#xD;&#xA;        // p_view [ 0  _  0  0 ] = [_, _, p_view.z * X + Y, p_view.z] = p_proj&#xD;&#xA;        //        [ 0  0  X  1 ]&#xD;&#xA;        //        [ 0  0  Y  0 ]&#xD;&#xA;        //&#xD;&#xA;        // p_proj / p_proj.w     = [_, _, X + Y/p_view.z, 1] = p_ndc&#xD;&#xA;        //&#xD;&#xA;        // Construction of p_ndc.z from p_view and projection values&#xD;&#xA;        // p_ndc.z = X + Y/p_view.z&#xD;&#xA;&#xD;&#xA;        const F32 x = XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;        const F32 y = XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;        &#xD;&#xA;        return XMVectorSet(x, y, 0.0f, 0.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I obtain the following images after visualizing the shadow factor (this is not the light contribution of the omni light) (and some linear fog as well):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is clearly wrong. All six shadow maps seem kind of **stretched**. Without the stretching, the curtain's shadow would still be in the close vicinity of the curtain itself and the leaves' shadow would be much smaller (equal to the leaves' shadow for the spotlight). Furthermore, the circular shadow at the end of the pillar's shadow is associated to the buckets in front of the curtains.&#xD;&#xA;&#xD;&#xA;Any ideas what goes or could go wrong?&#xD;&#xA;&#xD;&#xA;For clarity, the following two images show the shadow factor of the cube map face corresponding to the spotlight, for the omni light by adding:&#xD;&#xA;&#xD;&#xA;    if (p_view_z != -p_view.y) {&#xD;&#xA;    	return 0.0f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;The lit area seems a bit (how much?) larger than for the spotlight.&#xD;&#xA;&#xD;&#xA;**SampleCmpLevelZero**&#xD;&#xA;&#xD;&#xA;An other strange observation is that using a depth value of 1.1 for my spotlight's PCF filtering (`SampleCmpLevelZero`) always results in a 0 value as expected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;whereas for my omni light this is not the case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;Even if I use a value equal to 100000.0, I'll notice lit areas?&#xD;&#xA;&#xD;&#xA;**Depth Biasing**&#xD;&#xA;&#xD;&#xA;I use `DepthBias = 100;` (to prevent shadow acne; note that I use 16bit depth maps) `SlopeScaledDepthBias = 0.0f; DepthBiasClamp = 0.0f;` for all my Rasterizer states.&#xD;&#xA;&#xD;&#xA;**PCF filtering**&#xD;&#xA;&#xD;&#xA;I use the following sampler comparison state for PCF filtering (*my shadow maps have no mipmaps*) for both spotlights and omni lights. &#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC desc = {};&#xD;&#xA;    desc.Filter         = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;&#xD;&#xA;    desc.AddressU       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressV       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.AddressW       = D3D11_TEXTURE_ADDRESS_BORDER;&#xD;&#xA;    desc.MaxAnisotropy  = (device-&gt;GetFeatureLevel() &gt; D3D_FEATURE_LEVEL_9_1) &#xD;&#xA;    								? D3D11_MAX_MAXANISOTROPY : 2;&#xD;&#xA;    desc.MaxLOD         = D3D11_FLOAT32_MAX;&#xD;&#xA;    desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8Al0D.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DW86m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hQ0sB.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zedO9.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/4B8dZ.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/T4oQV.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/49GZW.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/9vBBr.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15613" PostHistoryTypeId="2" PostId="5696" RevisionGUID="8f8fae63-6c63-45df-8ade-938697430c88" CreationDate="2017-10-09T00:32:56.993" UserId="7438" Text="I performed a quick search on programs that translate natural language to sign language (through a 3D animation character). Here are examples:&#xD;&#xA;&#xD;&#xA; - [IBM SISI][1]&#xD;&#xA; - [ProDeaf][2] (which is an android app)&#xD;&#xA;&#xD;&#xA;My question is:&#xD;&#xA;&#xD;&#xA; - how can I make my own character that uses sign language?&#xD;&#xA; - Which platforms are preferred for 3D-modeling and animation(e.g. blender, maya, unity, ... etc.)?&#xD;&#xA; - Is there specific algorithm(s) to make the character learn the sign language, or it is just a dictionary?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=RarMKnjqzZU&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=fEvvrLpTb0E" ContentLicense="CC BY-SA 3.0" />
  <row Id="15614" PostHistoryTypeId="1" PostId="5696" RevisionGUID="8f8fae63-6c63-45df-8ade-938697430c88" CreationDate="2017-10-09T00:32:56.993" UserId="7438" Text="How can I use 3d animation to create a character that uses sign language?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15615" PostHistoryTypeId="3" PostId="5696" RevisionGUID="8f8fae63-6c63-45df-8ade-938697430c88" CreationDate="2017-10-09T00:32:56.993" UserId="7438" Text="|3d|animation|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15616" PostHistoryTypeId="2" PostId="5697" RevisionGUID="d2a92d32-b953-4f3c-b53b-67ee84ea7980" CreationDate="2017-10-09T07:15:04.703" UserId="5884" Text="I have a triangle that is extended in space and each edge is refracted differently, creating a 5 sided polytope. The initial and final triangles are the view radii segments of a frustum. We need to get the u and v along the triangle and the w depth in between the triangles of a point inside the polytope. " ContentLicense="CC BY-SA 3.0" />
  <row Id="15617" PostHistoryTypeId="1" PostId="5697" RevisionGUID="d2a92d32-b953-4f3c-b53b-67ee84ea7980" CreationDate="2017-10-09T07:15:04.703" UserId="5884" Text="Barycentric coordinates for 5-sided polytope of two triangles and three trapezoids" ContentLicense="CC BY-SA 3.0" />
  <row Id="15618" PostHistoryTypeId="3" PostId="5697" RevisionGUID="d2a92d32-b953-4f3c-b53b-67ee84ea7980" CreationDate="2017-10-09T07:15:04.703" UserId="5884" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15619" PostHistoryTypeId="2" PostId="5698" RevisionGUID="9bb12695-6b07-4a4c-a757-1b1222465a8b" CreationDate="2017-10-09T19:48:20.873" UserId="56" Text="When making sampling locations, there is a lot of information out there on how to do white noise sampling, uniform sampling, uniform+jittered sampling, low discrepancy sequence sampling (eg halton) and blue noise sampling (eg mitchell's best candidate algorithm https://computergraphics.stackexchange.com/questions/5682/mitchells-best-candidate-algorithm).&#xD;&#xA;&#xD;&#xA;For instance these, where each point is a sample location in a 2d quad. (source: https://blog.demofox.org/2017/05/29/when-random-numbers-are-too-random-low-discrepancy-sequences/)&#xD;&#xA;&#xD;&#xA;White Noise:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Uniform:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Uniform + Jitter:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Halton (2,3):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Blue Noise:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;While those are good for sampling (a 2d quad in this case), here is a blue noise texture which is useful for dithering or stippling (src: http://momentsingraphics.de/?p=127)&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Similarly, here is a white noise (random) one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;I've been trying to figure out in this case (a dither / stippling noise texture), if there is an equivalent to uniform sampling, uniform + jitter, or low discrepancy, and if so, what those textures might look like.&#xD;&#xA;&#xD;&#xA;One obvious difference between the first set of the textures and the second is that the first textures take a single scalar value as input (an index) and give a 2d vector as output (a location on the 2d quad).  The second set of textures takes an (x,y) 2d vector location as input, and gives out a scalar value as output.&#xD;&#xA;&#xD;&#xA;It almost looks though like in the blue noise case that maybe you could start with the blue noise sample points, and then color every other pixel based on it's distance from the closest sample point, and that you might come up with the same image.  If that's correct, could you do the same for the other flavors of sample distributions to make the other noise textures?  It seems like white noise (random) wouldn't work for this though, so that doesn't seem correct.&#xD;&#xA;&#xD;&#xA;Lastly, Jorge Jiminez has some &quot;Interleaved Gradient Noise&quot; that looks sort of blue noise-ish but kind of not... so seems a bit low discrepancy sequence. (http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare  and also an image and the math mentioned here https://bartwronski.com/2016/10/30/dithering-part-three-real-world-2d-quantization-dithering/)&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;It makes me wonder if something about that noise shows the secret on how to generalize (low discrepancy) sample points to 2d?&#xD;&#xA;&#xD;&#xA;Does anyone know whether there is a way to translate these sample concepts to noise textures for dithering and stippling?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WLFzs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dHAQQ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4LQlu.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JskHx.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/t71xm.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/YvAjF.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/WkZUp.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/34XJw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15620" PostHistoryTypeId="1" PostId="5698" RevisionGUID="9bb12695-6b07-4a4c-a757-1b1222465a8b" CreationDate="2017-10-09T19:48:20.873" UserId="56" Text="Making low discrepancy sequence noise textures, not LDS sample positions" ContentLicense="CC BY-SA 3.0" />
  <row Id="15621" PostHistoryTypeId="3" PostId="5698" RevisionGUID="9bb12695-6b07-4a4c-a757-1b1222465a8b" CreationDate="2017-10-09T19:48:20.873" UserId="56" Text="|texture|image-processing|sampling|post-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15622" PostHistoryTypeId="2" PostId="5699" RevisionGUID="09a73eb3-876f-4dd7-ad94-d42b1630bdd6" CreationDate="2017-10-09T20:15:46.180" UserId="5884" Text="I think I can do this using trilinear interpolation and treating two vertices on each side as merged and using my own volume calculations. I just need to interpolate some values given by the three points and a z. http://bmia.bmt.tue.nl/People/BRomeny/Courses/8C080/Interpolation.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15626" PostHistoryTypeId="2" PostId="5701" RevisionGUID="d43fccd1-892c-4976-a979-faf30919a205" CreationDate="2017-10-09T21:15:15.793" UserId="7442" Text="In theory, it is possible to stuff every sample distribution into a texture to &quot;pre-bake&quot; it for fast access. The question is whether any of the results might be useful. For blue noise, this makes a lot of sense, as blue noise distributions have global influence and are hard to evaluate at runtime. Uniform random sampling, on the other hand, is so simple precisely because it is not global, but has no influence whatsoever from neighboring samples. So the best you can achieve, as you noticed yourself, is writing uncorrelated white noise to the texture, which gains you very little.&#xD;&#xA;&#xD;&#xA;I think the key property of the blue noise textures that you failed to mention is that they are progressive. If you take, for example, Blue Noise Masks, Forced Random Sampling, or Relaxation Dart Throwing to generate a matrix/texture, you will not get grayscale values, but unique, ascending integer values corresponding to the order of insertion of the samples/texels. This means that you can also re-arrange such textures to a 1D list of width * height elements, where each element is a 2D position within the matrix. I.e., the first element of this list will be the (x, y) of the first sample inserted into the texture upon creation. The second element will be the (x2, y2) of the second sample, which will be quite far away from the first one, because the blue noise texture algorithms try to maximize distances between similar values.&#xD;&#xA;&#xD;&#xA;The list representation is nothing but a sequence accomplishing what 2D low-discrepancy sequences do: giving you a 2D sample position (albeit discrete and in a grid) for a scalar index. You do not lose any information while converting. So applying the reverse conversion to low-discrepancy sequences, it should be possible to write their element indices into a texture for fast lookup. What I don't know is how fast this will degenerate, because sooner or later higher values will end up at the same discretized locations as previously written ones. Low-discrepancy sequences guarantee spatial uniformity on average, but if you want to fill an n² texture and create exactly n² samples, I bet that you will get some of these overlaps while also having some holes. These conflicts can, by design, not occur in blue noise textures, but here you would have to find a strategy. Just discarding the higher values? I don't know how this influences the distribution properties. I assume that results vary between different low-discrepancy sequences. I have only ever worked with Halton and Hammersley, which don't seem like the best fit in this case. Maybe something based on a grid/lattice would help you to reduce/eliminate the overlaps. Not my field of expertise, unfortunately.&#xD;&#xA;&#xD;&#xA;This is the key problem, that low-discrepancy sequences (at least the ones I know) and in general sampling distributions used in computer graphics output nD values in the continuous domain rather than in a discrete grid. The reason blue noise textures work so well is because the discretization is already part of the generation. What you want is a permutation of n² integer values such that the result has special properties. Maximizing distances between similar values would be blue noise. Having no correlation between values would be white noise. And some other magic property could be pink noise, green noise, or a perfect interleaved gradient noise as in your provided picture. Would this be a reasonable approach, to understand your problem as the problem of permuting given values? Instead of continuous sampling? Maybe it simplifies the solution.&#xD;&#xA;&#xD;&#xA;Another point to consider for dithering and related effects is that blue noise textures can usually be tiled seemlessly because the sample domain is taken to be toroidal. You will lose this feature unless you find a way to make your low-discrepancy sequence toroidal, which I think is pretty tough, but would be a great scientific contribution!" ContentLicense="CC BY-SA 3.0" />
  <row Id="15628" PostHistoryTypeId="5" PostId="5701" RevisionGUID="9509fb58-69d6-4271-a3d6-55e1332644bd" CreationDate="2017-10-10T03:33:14.523" UserId="7443" Comment="Wrong algorithm" Text="In theory, it is possible to stuff every sample distribution into a texture to &quot;pre-bake&quot; it for fast access. The question is whether any of the results might be useful. For blue noise, this makes a lot of sense, as blue noise distributions have global influence and are hard to evaluate at runtime. Uniform random sampling, on the other hand, is so simple precisely because it is not global, but has no influence whatsoever from neighboring samples. So the best you can achieve, as you noticed yourself, is writing uncorrelated white noise to the texture, which gains you very little.&#xD;&#xA;&#xD;&#xA;I think the key property of the blue noise textures that you failed to mention is that they are progressive. If you take, for example, Blue Noise Masks, Forced Random Dithering, or Relaxation Dart Throwing to generate a matrix/texture, you will not get grayscale values, but unique, ascending integer values corresponding to the order of insertion of the samples/texels. This means that you can also re-arrange such textures to a 1D list of width * height elements, where each element is a 2D position within the matrix. I.e., the first element of this list will be the (x, y) of the first sample inserted into the texture upon creation. The second element will be the (x2, y2) of the second sample, which will be quite far away from the first one, because the blue noise texture algorithms try to maximize distances between similar values.&#xD;&#xA;&#xD;&#xA;The list representation is nothing but a sequence accomplishing what 2D low-discrepancy sequences do: giving you a 2D sample position (albeit discrete and in a grid) for a scalar index. You do not lose any information while converting. So applying the reverse conversion to low-discrepancy sequences, it should be possible to write their element indices into a texture for fast lookup. What I don't know is how fast this will degenerate, because sooner or later higher values will end up at the same discretized locations as previously written ones. Low-discrepancy sequences guarantee spatial uniformity on average, but if you want to fill an n² texture and create exactly n² samples, I bet that you will get some of these overlaps while also having some holes. These conflicts can, by design, not occur in blue noise textures, but here you would have to find a strategy. Just discarding the higher values? I don't know how this influences the distribution properties. I assume that results vary between different low-discrepancy sequences. I have only ever worked with Halton and Hammersley, which don't seem like the best fit in this case. Maybe something based on a grid/lattice would help you to reduce/eliminate the overlaps. Not my field of expertise, unfortunately.&#xD;&#xA;&#xD;&#xA;This is the key problem, that low-discrepancy sequences (at least the ones I know) and in general sampling distributions used in computer graphics output nD values in the continuous domain rather than in a discrete grid. The reason blue noise textures work so well is because the discretization is already part of the generation. What you want is a permutation of n² integer values such that the result has special properties. Maximizing distances between similar values would be blue noise. Having no correlation between values would be white noise. And some other magic property could be pink noise, green noise, or a perfect interleaved gradient noise as in your provided picture. Would this be a reasonable approach, to understand your problem as the problem of permuting given values? Instead of continuous sampling? Maybe it simplifies the solution.&#xD;&#xA;&#xD;&#xA;Another point to consider for dithering and related effects is that blue noise textures can usually be tiled seemlessly because the sample domain is taken to be toroidal. You will lose this feature unless you find a way to make your low-discrepancy sequence toroidal, which I think is pretty tough, but would be a great scientific contribution!" ContentLicense="CC BY-SA 3.0" />
  <row Id="15629" PostHistoryTypeId="24" PostId="5701" RevisionGUID="9509fb58-69d6-4271-a3d6-55e1332644bd" CreationDate="2017-10-10T03:33:14.523" Comment="Proposed by 7443 approved by 3073, 56 edit id of 275" ContentLicense="CC BY-SA 3.0" />
  <row Id="15632" PostHistoryTypeId="2" PostId="5703" RevisionGUID="38ec126b-7ba3-4863-aef9-e3858fe5fbb5" CreationDate="2017-10-10T12:04:28.857" UserId="2041" Text="This is quite a broad topic, so I can only give a general overview. If you've never done any interactive animation before, this might be too big a challenge to start with, and maybe you should think of something smaller to do first.&#xD;&#xA;&#xD;&#xA;You first need to model and rig your character, or try to find an existing model online that's rigged with enough control over the fingers. You then need to define a &quot;dictionary&quot; of animations or poses for each item of vocabulary in the language. To create the poses, it is probably easiest to use motion-capture technology to record a proficient sign-language speaker.&#xD;&#xA;&#xD;&#xA;All of the above needs to be done in a 3D modelling and animation tool. Maya is very popular for character animation.&#xD;&#xA;&#xD;&#xA;To get natural sign-language, you'll also need to write an algorithm to understand the way places in space are used as pronouns, and a fall-back that spells things out using letters when you don't have a vocab item for them. Based on next to no knowledge of sign language, I'd guess the algorithm will end up a little more complicated than a normal text-to-speech algorithm.&#xD;&#xA;&#xD;&#xA;You've already mentioned Unity 3D in your question, and that might be a good choice for the real-time part of the system (assuming you want to render the character in real-time). If you use that, you can write the algorithm in C#. You would import the animation/pose dictionary into your system in Unity, and have your algorithm compute the transitions from one pose or animation to the next. In Unity itself, you can define the camera and lighting layout for your model and the backdrop to draw it in front of." ContentLicense="CC BY-SA 3.0" />
  <row Id="15633" PostHistoryTypeId="2" PostId="5704" RevisionGUID="c202ab7e-f83b-42f9-8b01-1ecc9474b96c" CreationDate="2017-10-10T15:13:11.773" UserId="6974" Text="Is it possible to create a single kernel which can help us to perform an 2 step image processing ? &#xD;&#xA;&#xD;&#xA;For example, I want to first perform a median filter on my image to remove salt and pepper noise and then perform a sharpen operation on it. &#xD;&#xA;&#xD;&#xA;For this purpose, I have to perform the following operation &#xD;&#xA;&#xD;&#xA;    (image * Median_Kernel) *  sharpening kernel = final_image&#xD;&#xA;&#xD;&#xA;**I want to have a kernel which combines the effect of Median_kernel and sharpening it such that** &#xD;&#xA;&#xD;&#xA;    image * combined_kernel = final_image&#xD;&#xA;&#xD;&#xA;Is this mathematically possible ? If so could someone please explain to me how &#xD;&#xA;to do this mathematically ? &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15634" PostHistoryTypeId="1" PostId="5704" RevisionGUID="c202ab7e-f83b-42f9-8b01-1ecc9474b96c" CreationDate="2017-10-10T15:13:11.773" UserId="6974" Text="How can I combine two filter kernels for image processing to create a single kernel ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15635" PostHistoryTypeId="3" PostId="5704" RevisionGUID="c202ab7e-f83b-42f9-8b01-1ecc9474b96c" CreationDate="2017-10-10T15:13:11.773" UserId="6974" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15636" PostHistoryTypeId="2" PostId="5705" RevisionGUID="5f07f514-e985-41f7-86f7-48b1537897c8" CreationDate="2017-10-10T16:47:15.093" UserId="6041" Text="The function that calculates sun position in the sky takes as input&#xD;&#xA;local latitude, longitude and local date time. The output is a vector &#xD;&#xA;which is sun position:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Inversing the above means using the ray direction(sun position in the sky) and retrieving back the local date time. If the date time is valid then the ray must hit the sun path throughout the year. &#xD;&#xA;&#xD;&#xA;Here is the inverse function of the above:&#xD;&#xA;&#xD;&#xA;      public DateTime GetLocalDatetime(double haSolar, double vaSolar)&#xD;&#xA;            {&#xD;&#xA;                double latitude = Helper.ToRadian(Latitude);&#xD;&#xA;                double longitude = Helper.ToRadian(Longitude);&#xD;&#xA;    &#xD;&#xA;                double zenithTheta = Helper.PiOver2 - vaSolar;&#xD;&#xA;    &#xD;&#xA;                double sinSolarDeclination = (Math.Cos(Math.PI - haSolar) * Math.Cos(latitude) * Math.Sin(zenithTheta)) + Math.Sin(latitude) * Math.Cos(zenithTheta);&#xD;&#xA;                double solarDeclination = Math.Asin(sinSolarDeclination);&#xD;&#xA;    &#xD;&#xA;                double cosH = (Math.Sin(vaSolar) - Math.Sin(latitude) * sinSolarDeclination) / (Math.Cos(latitude) * Math.Cos(solarDeclination));&#xD;&#xA;                if (Math.Abs(cosH) &gt; 1) return DateTime.MinValue;&#xD;&#xA;    &#xD;&#xA;                double H = Math.Acos(cosH);&#xD;&#xA;                if (haSolar &lt; 0) H *= -1;&#xD;&#xA;    &#xD;&#xA;                double declratio = solarDeclination / Helper.ToRadian(23.45);&#xD;&#xA;                if (Math.Abs(declratio) &gt; 1) return DateTime.MinValue;&#xD;&#xA;    &#xD;&#xA;                double beta = Math.Asin(declratio);&#xD;&#xA;                int n = (int)Math.Round(beta / Helper.ToRadian(360d / 365d) + 81d, 1);&#xD;&#xA;    &#xD;&#xA;                DateTime localtime = new DateTime(DateTime.Now.Year, 1, 1).AddDays(n - 1);&#xD;&#xA;                DateTime solartime = new DateTime(localtime.Year, localtime.Month, localtime.Day, 12, 0, 0);&#xD;&#xA;                solartime = solartime.AddMinutes(4 * Helper.ToDegree(H));&#xD;&#xA;    &#xD;&#xA;                double eot = 9.87 * Math.Sin(2d * beta) - 7.53 * Math.Cos(beta) - 1.5 * Math.Sin(beta);&#xD;&#xA;                double deltatimezone = 4d * (longitude - (Timezone * 15d));&#xD;&#xA;                return solartime.AddMinutes(-(eot + deltatimezone));&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And the image where each band represent each month in the year:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OzwCQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XvI8R.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15641" PostHistoryTypeId="2" PostId="5707" RevisionGUID="21813cf8-4fb1-4817-8571-c3f6ad4d8ee2" CreationDate="2017-10-10T17:28:07.050" UserDisplayName="user7450" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel. Also can you tell me about what kind of a kernel you would use for a sharpening operation? Have you looked into how it works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15642" PostHistoryTypeId="5" PostId="5707" RevisionGUID="83a91560-727c-4281-ba93-b05af38d9713" CreationDate="2017-10-10T20:13:33.507" UserDisplayName="user7450" Comment="deleted 126 characters in body" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel." ContentLicense="CC BY-SA 3.0" />
  <row Id="15643" PostHistoryTypeId="8" PostId="5707" RevisionGUID="4c827fc7-c192-48cb-acbe-c443366cdffb" CreationDate="2017-10-10T20:22:05.320" UserDisplayName="user7450" Comment="Rollback to [21813cf8-4fb1-4817-8571-c3f6ad4d8ee2]" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel. Also can you tell me about what kind of a kernel you would use for a sharpening operation? Have you looked into how it works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15644" PostHistoryTypeId="5" PostId="5707" RevisionGUID="7a9d3b9e-e6ad-4d1a-ad5a-a268031c063e" CreationDate="2017-10-10T20:24:10.777" UserDisplayName="user7450" Comment="added 259 characters in body" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel. Also can you tell me about what kind of a &quot;kernel&quot; you would use for a sharpening operation? Have you looked into how it works? I dont know how you could generate a &quot;kernel&quot; for a non-linear filtering operation.&#xD;&#xA;&#xD;&#xA;Maybe a basic refresher in Image Processing is in order? Perhaps even going over basics of Signal Processing / DSP? I would suggest looking over 2D filtering if you can." ContentLicense="CC BY-SA 3.0" />
  <row Id="15652" PostHistoryTypeId="2" PostId="5712" RevisionGUID="0779b7fa-f31e-4644-8bb6-304b38d2c911" CreationDate="2017-10-11T08:31:58.690" UserId="182" Text="In OpenGL the buffer object functions ([`glBufferData`][1], [`glBufferSubData`][2], and probably a few others) have a parameter `usage`, described by the documentation as a hint of the intended usage, likely meant to help the implementation yield better performance.&#xD;&#xA;&#xD;&#xA;&gt; _usage_&#xD;&#xA;&gt;&#xD;&#xA;&gt;    Specifies the expected usage pattern of the data store. The symbolic constant must be `GL_STREAM_DRAW`, `GL_STREAM_READ`, `GL_STREAM_COPY`, `GL_STATIC_DRAW`, `GL_STATIC_READ`, `GL_STATIC_COPY`, `GL_DYNAMIC_DRAW`, `GL_DYNAMIC_READ`, or `GL_DYNAMIC_COPY`.&lt;br/&gt;&#xD;&#xA;&gt; _[...]_&lt;br/&gt;&#xD;&#xA;&gt; usage is a hint to the GL implementation as to how a buffer object's data store will be accessed. This enables the GL implementation to make more intelligent decisions that may significantly impact buffer object performance. It does not, however, constrain the actual usage of the data store.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[The wiki][3] is similarly vague:&#xD;&#xA;&#xD;&#xA;&gt; These are only hints, after all. It is perfectly legal OpenGL code to modify a STATIC buffer after it has been created, or to never modify a STREAM buffer.&lt;br/&gt;&#xD;&#xA;&gt; _[...]_&lt;br/&gt;&#xD;&#xA;&gt;  These are questions that can only be answered with careful profiling. And even then, the answer will only be accurate for that particular driver version from that particular hardware vendor.&#xD;&#xA;&#xD;&#xA;In fine, how relevant is this parameter, if at all? Do drivers actually take it into account, and if they do, in your experience how much does it impact performance in practice? Do you have data to share?&#xD;&#xA;&#xD;&#xA;I have written a thin graphics API abstraction layer meant to be implemented as either of the existing APIs, and it is tempting to just ignore this parameter altogether and hide it from the exposed abstraction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15653" PostHistoryTypeId="1" PostId="5712" RevisionGUID="0779b7fa-f31e-4644-8bb6-304b38d2c911" CreationDate="2017-10-11T08:31:58.690" UserId="182" Text="GL_STATIC_DRAW vs GL_DYNAMIC_DRAW vs GL_STREAM_DRAW: does it matter?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15654" PostHistoryTypeId="3" PostId="5712" RevisionGUID="0779b7fa-f31e-4644-8bb6-304b38d2c911" CreationDate="2017-10-11T08:31:58.690" UserId="182" Text="|opengl|optimisation|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15655" PostHistoryTypeId="2" PostId="5713" RevisionGUID="96839b4a-01ad-49d2-b227-8b1b76effbd2" CreationDate="2017-10-11T08:54:45.903" UserId="137" Text="Functionally they are the same. &#xD;&#xA;&#xD;&#xA;The driver could use them to differentiate how to handle the buffer behind the scenes. Where for example static_draw would be copied to vram as soon as possible and left there but stream_read would have a op to date copy in RAM at all times.&#xD;&#xA;&#xD;&#xA;This vagueness is the reason that [glBufferStorage][1] became a thing. That way you specify what you want to be able to do with the buffer (whether you'll update it through BufferSubData, whether you'll read or write through a map, how coherent the mapping is, whether the mapping can persist across uses) and going outside those boundaries is an error.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://docs.gl/gl4/glBufferStorage" ContentLicense="CC BY-SA 3.0" />
  <row Id="15656" PostHistoryTypeId="2" PostId="5714" RevisionGUID="72cbf50f-f278-4d4b-8f95-2a1e02631cce" CreationDate="2017-10-11T10:00:24.917" UserId="2041" Text="This will vary between implementations, but the driver I worked on did use these, mainly to decide memory layout. The optimizations enabled by these hints are much smaller than you would like, mainly because of the restriction that you *can* do any use whatever hints you give. e.g. it would make cache invalidation a lot cheaper if buffers hinted for read access only could not be written at all, but this optimization is impossible.&#xD;&#xA;&#xD;&#xA;Some notable games which are widely used for benchmark comparisons between GPUs do not use these hints correctly, so GPU vendors have an incentive to make all uses fast even if they doesn't match the hints." ContentLicense="CC BY-SA 3.0" />
  <row Id="15657" PostHistoryTypeId="2" PostId="5715" RevisionGUID="0c3b9c4d-46e8-401b-b4a6-b936d21e62c5" CreationDate="2017-10-11T10:19:24.863" UserId="2287" Text="I finally found the cause of the problem. There appears to be a problem with the shadow map of both the omni light and spotlight. While debugging, I noticed by accident that the light-view-to-light-projection (`lview_to_lprojection`) `00` and `11` matrix entries were not equal. Due to the aspect ratio of 1, both matrix entries must be equal. Furthermore, due to the FOV of $\pi/2$, these matrix entries must be equal to 1 (assuming no floating-point precision issues).&#xD;&#xA;&#xD;&#xA;The constructor of my `PerspectiveCamera` class expects a `width`, `height`, `FOVy`, `near`, `far` order or `aspect ratio`, `FOVy`, `near`, `far` order and correctly handles the creation of the view-to-projection transformation matrix via redirecting to `XMMatrixPerspectiveFovLH` expecting a `FOVy`, `aspect ratio`, `near`, `far` order. Since, I did not want to create a corresponding `PerspectiveCamera` for each light per frame, I bypassed that class by directly providing a member method in my `OmniLight` and `SpotLight` classes redirecting to `XMMatrixPerspectiveFovLH` using the wrong order of arguments. **This explains why the above images are wrong.** &#xD;&#xA;&#xD;&#xA;The generated shadow map of the spotlight is still equal to one of the six shadow maps of the omni light, although both use the same but wrong `world_to_lprojection` transformation matrix (which contains the wrong `lview_to_lprojection` transformation matrix). The HLSL code for the spotlight uses the `cview_to_lprojection` transformation matrix, which includes `lview_to_lprojection`, and thus will perform the &quot;right&quot; mapping. The HLSL code for the omni light uses the `cview_to_lview` transformation matrix, which does not include `lview_to_lprojection`, and thus will not take the non-uniform scaling of the 00 and 11 entries into account, resulting in some non-linear stretching and thus the wrong mapping. **This explains why the above images differ for the omni light and spotlight.** &#xD;&#xA;&#xD;&#xA;After fixing the bug:&#xD;&#xA;&#xD;&#xA;**Omni Light** (6 faces) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (6 faces)][2]][2]&#xD;&#xA;[![Omni Light (6 faces)][3]][3]&#xD;&#xA;&#xD;&#xA;**Omni Light** (1 face) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (1 face)][4]][4]&#xD;&#xA;[![Omni Light (1 face)][5]][5]&#xD;&#xA;&#xD;&#xA;**Spotlight** shadow factor:&#xD;&#xA;&#xD;&#xA;[![Spotlight][6]][6]&#xD;&#xA;[![Spotlight][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RSVpW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7t8ku.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7Hl37.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pV2DZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iXX5r.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/kLBIl.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/dNEB6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15658" PostHistoryTypeId="5" PostId="5715" RevisionGUID="a45d1f57-0f7f-41d3-ba75-38a1982c322a" CreationDate="2017-10-11T10:24:52.173" UserId="2287" Comment="added 46 characters in body" Text="I finally found the cause of the problem. There appears to be a problem with the shadow map of both the omni light and spotlight. While debugging, I noticed by accident that the light-view-to-light-projection (`lview_to_lprojection`) `00` and `11` matrix entries were not equal. Due to the aspect ratio of 1, both matrix entries must be equal. Furthermore, due to the FOV of $\pi/2$, these matrix entries must be equal to 1 (assuming no floating-point precision issues).&#xD;&#xA;&#xD;&#xA;The constructor of my `PerspectiveCamera` class expects a `width`, `height`, `FOVy`, `near`, `far` order or `aspect ratio`, `FOVy`, `near`, `far` order and correctly handles the creation of the view-to-projection transformation matrix via redirecting to `XMMatrixPerspectiveFovLH` expecting a `FOVy`, `aspect ratio`, `near`, `far` order. Since, I did not want to create a corresponding `PerspectiveCamera` for each light per frame, I bypassed that class by directly providing a member method in my `OmniLight` and `SpotLight` classes redirecting to `XMMatrixPerspectiveFovLH` using the wrong order of arguments. **This explains why the above images are wrong.** &#xD;&#xA;&#xD;&#xA;The generated shadow map of the spotlight is still equal to one of the six shadow maps of the omni light, although both use the same but wrong `world_to_lprojection` transformation matrix (which contains the wrong `lview_to_lprojection` transformation matrix). The HLSL code for the spotlight uses the `cview_to_lprojection` transformation matrix, which includes `lview_to_lprojection`, and thus will perform the &quot;right&quot; mapping. The HLSL code for the omni light uses the `cview_to_lview` transformation matrix, which does not include `lview_to_lprojection`, and thus will not take the non-uniform scaling of the 00 and 11 entries into account, resulting in some non-linear stretching and thus the wrong mapping. **This explains why the above images differ for the omni light and spotlight.** &#xD;&#xA;&#xD;&#xA;After fixing the bug:&#xD;&#xA;&#xD;&#xA;**Omni Light** (6 faces) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (6 faces)][2]][2]&#xD;&#xA;[![Omni Light (6 faces)][3]][3]&#xD;&#xA;&#xD;&#xA;**Omni Light** (1 face) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (1 face)][4]][4]&#xD;&#xA;[![Omni Light (1 face)][5]][5]&#xD;&#xA;&#xD;&#xA;**Spotlight** shadow factor:&#xD;&#xA;&#xD;&#xA;[![Spotlight][6]][6]&#xD;&#xA;[![Spotlight][7]][7]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RSVpW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7t8ku.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7Hl37.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pV2DZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iXX5r.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/kLBIl.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/dNEB6.png&#xD;&#xA;&#xD;&#xA;Edit: My images do not show after uploading?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15659" PostHistoryTypeId="5" PostId="5715" RevisionGUID="c61a8991-5d93-43a2-9e46-bfdd25f931fd" CreationDate="2017-10-11T11:27:44.540" UserId="2287" Comment="deleted 48 characters in body" Text="I finally found the cause of the problem. There appears to be a problem with the shadow map of both the omni light and spotlight. While debugging, I noticed by accident that the light-view-to-light-projection (`lview_to_lprojection`) `00` and `11` matrix entries were not equal. Due to the aspect ratio of 1, both matrix entries must be equal. Furthermore, due to the FOV of $\pi/2$, these matrix entries must be equal to 1 (assuming no floating-point precision issues).&#xD;&#xA;&#xD;&#xA;The constructor of my `PerspectiveCamera` class expects a `width`, `height`, `FOVy`, `near`, `far` order or `aspect ratio`, `FOVy`, `near`, `far` order and correctly handles the creation of the view-to-projection transformation matrix via redirecting to `XMMatrixPerspectiveFovLH` expecting a `FOVy`, `aspect ratio`, `near`, `far` order. Since, I did not want to create a corresponding `PerspectiveCamera` for each light per frame, I bypassed that class by directly providing a member method in my `OmniLight` and `SpotLight` classes redirecting to `XMMatrixPerspectiveFovLH` using the wrong order of arguments. **This explains why the above images are wrong.** &#xD;&#xA;&#xD;&#xA;The generated shadow map of the spotlight is still equal to one of the six shadow maps of the omni light, although both use the same but wrong `world_to_lprojection` transformation matrix (which contains the wrong `lview_to_lprojection` transformation matrix). The HLSL code for the spotlight uses the `cview_to_lprojection` transformation matrix, which includes `lview_to_lprojection`, and thus will perform the &quot;right&quot; mapping. The HLSL code for the omni light uses the `cview_to_lview` transformation matrix, which does not include `lview_to_lprojection`, and thus will not take the non-uniform scaling of the 00 and 11 entries into account, resulting in some non-linear stretching and thus the wrong mapping. **This explains why the above images differ for the omni light and spotlight.** &#xD;&#xA;&#xD;&#xA;After fixing the bug:&#xD;&#xA;&#xD;&#xA;**Omni Light** (6 faces) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (6 faces)][2]][2]&#xD;&#xA;[![Omni Light (6 faces)][3]][3]&#xD;&#xA;&#xD;&#xA;**Omni Light** (1 face) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (1 face)][4]][4]&#xD;&#xA;[![Omni Light (1 face)][5]][5]&#xD;&#xA;&#xD;&#xA;**Spotlight** shadow factor:&#xD;&#xA;&#xD;&#xA;[![Spotlight][6]][6]&#xD;&#xA;[![Spotlight][7]][7]&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/7t8ku.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7Hl37.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pV2DZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iXX5r.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/kLBIl.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/dNEB6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15663" PostHistoryTypeId="5" PostId="5707" RevisionGUID="8cd60a2b-c970-4fa6-8703-a66ce61c81f2" CreationDate="2017-10-11T15:18:58.587" UserDisplayName="user7450" Comment="added 95 characters in body" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel. Also can you tell me about what kind of a &quot;kernel&quot; you would use for a sharpening operation? (Maybe it's intermediaries but I dont know how you could talk about a kernel for it directly ) Have you looked into how it works? I dont know how you could generate a &quot;kernel&quot; for a non-linear filtering operation.&#xD;&#xA;&#xD;&#xA;Maybe a basic refresher in Image Processing is in order? Perhaps even going over basics of Signal Processing / DSP? I would suggest looking over 2D filtering if you can." ContentLicense="CC BY-SA 3.0" />
  <row Id="15664" PostHistoryTypeId="5" PostId="5715" RevisionGUID="afd0c253-03b2-4571-b671-b5f237df4660" CreationDate="2017-10-11T17:02:41.413" UserId="2287" Comment="added 549 characters in body" Text="I finally found the cause of the problem. There appears to be a problem with the shadow map of both the omni light and spotlight. While debugging, I noticed by accident that the light-view-to-light-projection (`lview_to_lprojection`) `00` and `11` matrix entries were not equal. Due to the aspect ratio of 1, both matrix entries must be equal. Furthermore, due to the FOV of $\pi/2$, these matrix entries must be equal to 1 (assuming no floating-point precision issues).&#xD;&#xA;&#xD;&#xA;The constructor of my `PerspectiveCamera` class expects a `width`, `height`, `FOVy`, `near`, `far` order or `aspect ratio`, `FOVy`, `near`, `far` order and correctly handles the creation of the view-to-projection transformation matrix via redirecting to `XMMatrixPerspectiveFovLH` expecting a `FOVy`, `aspect ratio`, `near`, `far` order. Since, I did not want to create a corresponding `PerspectiveCamera` for each light per frame, I bypassed that class by directly providing a member method in my `OmniLight` and `SpotLight` classes redirecting to `XMMatrixPerspectiveFovLH` using the wrong order of arguments. **This explains why the above images are wrong.** &#xD;&#xA;&#xD;&#xA;The generated shadow map of the spotlight is still equal to one of the six shadow maps of the omni light, although both use the same but wrong `world_to_lprojection` transformation matrix (which contains the wrong `lview_to_lprojection` transformation matrix). The HLSL code for the spotlight uses the `cview_to_lprojection` transformation matrix, which includes `lview_to_lprojection`, and thus will perform the &quot;right&quot; mapping. The HLSL code for the omni light uses the `cview_to_lview` transformation matrix, which does not include `lview_to_lprojection`, and thus will not take the non-uniform scaling of the 00 and 11 entries into account, resulting in some non-linear stretching and thus the wrong mapping. **This explains why the above images differ for the omni light and spotlight.** &#xD;&#xA;&#xD;&#xA;After fixing the bug:&#xD;&#xA;&#xD;&#xA;**Omni Light** (6 faces) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (6 faces)][2]][2]&#xD;&#xA;[![Omni Light (6 faces)][3]][3]&#xD;&#xA;&#xD;&#xA;**Omni Light** (1 face) shadow factor:&#xD;&#xA;&#xD;&#xA;[![Omni Light (1 face)][4]][4]&#xD;&#xA;[![Omni Light (1 face)][5]][5]&#xD;&#xA;&#xD;&#xA;**Spotlight** shadow factor:&#xD;&#xA;&#xD;&#xA;[![Spotlight][6]][6]&#xD;&#xA;[![Spotlight][7]][7]&#xD;&#xA;&#xD;&#xA;**SampleCmpLevelZero**&#xD;&#xA;&#xD;&#xA;When using this method on a signed-normalized or unsigned-normalized format (which is the case), the comparison value is automatically clamped between 0.0 and 1.0. The two perspective cameras looking along the positive or negative x-axis (along the middle hallway) associated with the omni light, will have &quot;rays&quot; which are not occluded by the scene's geometry due to the far plane at distance 3. Therefore, these pixels (displaying the shadow factor) will always be lit for comparison values larger than or equal to `1.0f` (since all such values are clamped to `1.0f`).&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/7t8ku.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7Hl37.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pV2DZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/iXX5r.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/kLBIl.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/dNEB6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15667" PostHistoryTypeId="2" PostId="5716" RevisionGUID="a7b3618b-65a6-498a-b748-5828a7cc4d3a" CreationDate="2017-10-12T04:05:28.420" UserId="7462" Text="I understand de castlejeau's algorithm and I am familiar although not fully experienced with B-Splines. I am trying to understand the geometric interpretation of B-splines through the algorithm (just like how de castlejeaus algorithm shows the geometric interpretation of bezier curves). Thank you in advance." ContentLicense="CC BY-SA 3.0" />
  <row Id="15668" PostHistoryTypeId="1" PostId="5716" RevisionGUID="a7b3618b-65a6-498a-b748-5828a7cc4d3a" CreationDate="2017-10-12T04:05:28.420" UserId="7462" Text="How does the Lane resienfield algorithm work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15669" PostHistoryTypeId="3" PostId="5716" RevisionGUID="a7b3618b-65a6-498a-b748-5828a7cc4d3a" CreationDate="2017-10-12T04:05:28.420" UserId="7462" Text="|bezier-curve|curve|nurbs|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15674" PostHistoryTypeId="5" PostId="5704" RevisionGUID="3776862a-5146-4a2b-9c81-e2109568c97a" CreationDate="2017-10-12T15:43:27.700" UserId="6" Comment="Fixing formatting and spelling issues." Text="Is it possible to create a single kernel which can help us to perform an 2 step image processing? &#xD;&#xA;&#xD;&#xA;For example, I want to first perform a median filter on my image to remove salt and pepper noise and then perform a sharpen operation on it. &#xD;&#xA;&#xD;&#xA;For this purpose, I have to perform the following operation &#xD;&#xA;&#xD;&#xA;    (image * Median_Kernel) *  sharpening kernel = final_image&#xD;&#xA;&#xD;&#xA;**I want to have a kernel which combines the effect of Median_kernel and sharpening it such that** &#xD;&#xA;&#xD;&#xA;    image * combined_kernel = final_image&#xD;&#xA;&#xD;&#xA;Is this mathematically possible? If so, could someone please explain to me how to do this mathematically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15675" PostHistoryTypeId="4" PostId="5704" RevisionGUID="3776862a-5146-4a2b-9c81-e2109568c97a" CreationDate="2017-10-12T15:43:27.700" UserId="6" Comment="Fixing formatting and spelling issues." Text="How can I combine two filter kernels for image processing to create a single kernel?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15676" PostHistoryTypeId="24" PostId="5704" RevisionGUID="3776862a-5146-4a2b-9c81-e2109568c97a" CreationDate="2017-10-12T15:43:27.700" Comment="Proposed by 6 approved by 2041 edit id of 276" ContentLicense="CC BY-SA 3.0" />
  <row Id="15677" PostHistoryTypeId="2" PostId="5718" RevisionGUID="475631c3-4dd6-42d0-a60a-a2ae0cb96788" CreationDate="2017-10-13T07:19:16.473" UserId="6806" Text="I'm studying spring model. There is a suggested equation (Hook's Law vector form) But, I couldn't understand how to derive that equation. &#xD;&#xA;&#xD;&#xA;I'm reading 'Computer Animation Algorithms and Techniques Third Edition.&#xD;&#xA;In the page 241, (7.88)&#xD;&#xA;The equation is as follows: &#xD;&#xA;&#xD;&#xA;($|v_{1}^* - v_{2}^*|$: the rest length)&#xD;&#xA;&#xD;&#xA;($|v_{1} - v_{2}|$: the current length)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$F_s = (\frac{k_s|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{{|v_{1}^* - v_{2}^*|}})\frac{|v_1 -v_2|}{|v_1 -v_2|}$ // I think the $k_s$ is typo. &#xD;&#xA;&#xD;&#xA;(I referred to http://www2.cs.uregina.ca/~anima/408/Notes/Cloth/Cloth.htm)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, maybe $F_s = k_s(\frac{|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{\color{red}{|v_{1}^* - v_{2}^*|}})\frac{|v_1 -v_2|}{|v_1 -v_2|}$ is correct. &#xD;&#xA;&#xD;&#xA;However, I wonder why the red part divides the equation?&#xD;&#xA;&#xD;&#xA;If I know correctly about Hook's Law, $F=-k_S(current_{lenght} - rest_{length})$.&#xD;&#xA;&#xD;&#xA;It means that the red part should be removed like that $F_s = k_s(|v_1 -v_2| - |v_{1}^* - v_{2}^*|)\frac{|v_1 -v_2|}{|v_1 -v_2|}$.&#xD;&#xA;&#xD;&#xA;Could you explain what I'm wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15678" PostHistoryTypeId="1" PostId="5718" RevisionGUID="475631c3-4dd6-42d0-a60a-a2ae0cb96788" CreationDate="2017-10-13T07:19:16.473" UserId="6806" Text="Hook's Law vector form" ContentLicense="CC BY-SA 3.0" />
  <row Id="15679" PostHistoryTypeId="3" PostId="5718" RevisionGUID="475631c3-4dd6-42d0-a60a-a2ae0cb96788" CreationDate="2017-10-13T07:19:16.473" UserId="6806" Text="|mathematics|physically-based|vector-graphics|physics|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15680" PostHistoryTypeId="2" PostId="5719" RevisionGUID="ba57f991-ba8e-47d1-a4f5-4d997a2b6c5e" CreationDate="2017-10-13T12:34:37.820" UserId="38" Text="If we sidestep your typo (the last term has one absolute too much), both formulations are correct. They just express different things. The $k$ in Hooke's law is for a particular spring. $k_s$ is the siffness for a paricular material. &#xD;&#xA;&#xD;&#xA;Now in the linear portion there is a direct relationship betwen these the material stffness is directly propotional to the spring factor and length of member. So for example when the rest length of a different spring with same material is 2 times as long its 1/2 as stiff." ContentLicense="CC BY-SA 3.0" />
  <row Id="15681" PostHistoryTypeId="2" PostId="5720" RevisionGUID="313c8107-70b4-4f85-aa50-233fe834110b" CreationDate="2017-10-13T13:04:06.417" UserId="7473" Text="I am working on a graphics engine designed to be used in flight simulators.&#xD;&#xA;It therefore has to feature an advanced weather rendering system with clouds you can fly through.&#xD;&#xA;&#xD;&#xA;For this, I implemented a particle system that renders a few hundred thousand billboards scattered in layers and in a 120km radius area.&#xD;&#xA;Until now, these clouds were my only transparent objects and I was relying on sorted alpha blending to get the desired result.&#xD;&#xA;&#xD;&#xA;My engine is making some progress and I now need to be able to render different types of transparent objects. Of course, I cannot rely on sorted alpha blending anymore since these objects are too different to be handled with a uber shader.&#xD;&#xA;&#xD;&#xA;In search for alternatives, I tried to implement a few order independent transparency techniques with inconclusive results :&#xD;&#xA;&#xD;&#xA;- Weighted Blended OIT : not working well with very contrasting objects and almost opaque objects. Hard to find a visibility function that can handle all kind of objects.&#xD;&#xA;&#xD;&#xA;- Linked List OIT / Adaptive transparency : result quality is very good but efficiency depends too much on scene complexity and a cloud rendering system involves way too much layers/overdraw.&#xD;&#xA;&#xD;&#xA;Most OIT techniques are illustrated with simple to moderate complexity scenes.&#xD;&#xA;I feel like I am in a dead-end and I'm looking for new ideas.&#xD;&#xA;&#xD;&#xA;Is there a different OIT technique that I am not aware of and that can be appropriate for such a case ?&#xD;&#xA;&#xD;&#xA;Are there cloud rendering technique or rendering pipeline design that can help to solve this problem ?&#xD;&#xA;&#xD;&#xA;Thank you for your time and help." ContentLicense="CC BY-SA 3.0" />
  <row Id="15682" PostHistoryTypeId="1" PostId="5720" RevisionGUID="313c8107-70b4-4f85-aa50-233fe834110b" CreationDate="2017-10-13T13:04:06.417" UserId="7473" Text="Cloud rendering and transparency order" ContentLicense="CC BY-SA 3.0" />
  <row Id="15683" PostHistoryTypeId="3" PostId="5720" RevisionGUID="313c8107-70b4-4f85-aa50-233fe834110b" CreationDate="2017-10-13T13:04:06.417" UserId="7473" Text="|transparency|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15684" PostHistoryTypeId="5" PostId="5720" RevisionGUID="e284bd49-b799-42eb-821f-7d09347fc401" CreationDate="2017-10-13T13:14:01.350" UserId="7473" Comment="added 2 characters in body" Text="I am working on a graphics engine designed to be used in flight simulators.&#xD;&#xA;It therefore has to feature an advanced weather rendering system with clouds you can fly through.&#xD;&#xA;&#xD;&#xA;For this, I implemented a particle system that renders a few hundred thousand billboards scattered in layers and in a 120km radius area.&#xD;&#xA;Until now, these clouds were my only transparent objects and I was relying on sorted alpha blending to get the desired result.&#xD;&#xA;&#xD;&#xA;My engine is making some progress and I now need to be able to render different types of transparent objects. Of course, I cannot rely on sorted alpha blending anymore since these objects are too different to be handled with a uber shader.&#xD;&#xA;&#xD;&#xA;In search for alternatives, I tried to implement a few order independent transparency techniques with inconclusive results :&#xD;&#xA;&#xD;&#xA;- Weighted Blended OIT : not working well with very contrasting objects and almost opaque objects. Hard to find a visibility function that can handle all kind of objects.&#xD;&#xA;&#xD;&#xA;- Linked List OIT / Adaptive transparency : result quality is very good but efficiency depends too much on scene complexity and a cloud rendering system involves way too much layers/overdraw.&#xD;&#xA;&#xD;&#xA;Most OIT techniques are illustrated with simple to moderate complexity scenes.&#xD;&#xA;I feel like I am in a dead-end and I'm looking for new ideas.&#xD;&#xA;&#xD;&#xA;Is there a different OIT technique that I am not aware of and that can be appropriate for such a case ?&#xD;&#xA;&#xD;&#xA;Are there cloud rendering techniques or rendering pipeline designs that can help to solve this problem ?&#xD;&#xA;&#xD;&#xA;Thank you for your time and help." ContentLicense="CC BY-SA 3.0" />
  <row Id="15685" PostHistoryTypeId="5" PostId="5656" RevisionGUID="3b87d274-fc52-49b8-988a-ef4a1323d5d6" CreationDate="2017-10-13T14:26:15.047" UserId="2287" Comment="added 88 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the **F**, **G** (or **V** depending if you factor the foreshortening in the denominator into **G**) and **D**:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seem to be used (in the literature, in the animation industry and in the gaming industry) in the format corresponding to your **second** option. All the **D** factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$ (See [Equations](http://graphicrants.blogspot.be/2013/08/specular-brdf-reference.html))." ContentLicense="CC BY-SA 3.0" />
  <row Id="15686" PostHistoryTypeId="5" PostId="5718" RevisionGUID="7dec802e-c3c7-4bbf-bdd8-8e698d3620d0" CreationDate="2017-10-13T16:19:26.257" UserId="6806" Comment="added 2 characters in body; edited title" Text="I'm studying spring model. There is a suggested equation (Hooke's Law vector form) But, I couldn't understand how to derive that equation. &#xD;&#xA;&#xD;&#xA;I'm reading 'Computer Animation Algorithms and Techniques Third Edition.&#xD;&#xA;In the page 241, (7.88)&#xD;&#xA;The equation is as follows: &#xD;&#xA;&#xD;&#xA;($|v_{1}^* - v_{2}^*|$: the rest length)&#xD;&#xA;&#xD;&#xA;($|v_{1} - v_{2}|$: the current length)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$F_s = (\frac{k_s|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{{|v_{1}^* - v_{2}^*|}})\frac{|v_1 -v_2|}{|v_1 -v_2|}$ // I think the $k_s$ is typo. &#xD;&#xA;&#xD;&#xA;(I referred to http://www2.cs.uregina.ca/~anima/408/Notes/Cloth/Cloth.htm)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, maybe $F_s = k_s(\frac{|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{\color{red}{|v_{1}^* - v_{2}^*|}})\frac{|v_1 -v_2|}{|v_1 -v_2|}$ is correct. &#xD;&#xA;&#xD;&#xA;However, I wonder why the red part divides the equation?&#xD;&#xA;&#xD;&#xA;If I know correctly about Hooke's Law, $F=-k_S(current_{lenght} - rest_{length})$.&#xD;&#xA;&#xD;&#xA;It means that the red part should be removed like that $F_s = k_s(|v_1 -v_2| - |v_{1}^* - v_{2}^*|)\frac{|v_1 -v_2|}{|v_1 -v_2|}$.&#xD;&#xA;&#xD;&#xA;Could you explain what I'm wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15687" PostHistoryTypeId="4" PostId="5718" RevisionGUID="7dec802e-c3c7-4bbf-bdd8-8e698d3620d0" CreationDate="2017-10-13T16:19:26.257" UserId="6806" Comment="added 2 characters in body; edited title" Text="Hooke's Law vector form" ContentLicense="CC BY-SA 3.0" />
  <row Id="15688" PostHistoryTypeId="5" PostId="5718" RevisionGUID="41813218-b8d6-46a0-89ef-6f5742d531bf" CreationDate="2017-10-13T16:30:01.097" UserId="6806" Comment="edited body" Text="I'm studying spring model. There is a suggested equation (Hooke's Law vector form) But, I couldn't understand how to derive that equation. &#xD;&#xA;&#xD;&#xA;I'm reading 'Computer Animation Algorithms and Techniques Third Edition.&#xD;&#xA;In the page 241, (7.88)&#xD;&#xA;The equation is as follows: &#xD;&#xA;&#xD;&#xA;($|v_{1}^* - v_{2}^*|$: the rest length)&#xD;&#xA;&#xD;&#xA;($|v_{1} - v_{2}|$: the current length)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$F_s = (\frac{k_s|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{{|v_{1}^* - v_{2}^*|}})\frac{(v_1 -v_2)}{|v_1 -v_2|}$ // I think the $k_s$ is typo. &#xD;&#xA;&#xD;&#xA;(I referred to http://www2.cs.uregina.ca/~anima/408/Notes/Cloth/Cloth.htm)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, maybe $F_s = k_s(\frac{|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{\color{red}{|v_{1}^* - v_{2}^*|}})\frac{(v_1 -v_2)}{|v_1 -v_2|}$ is correct. &#xD;&#xA;&#xD;&#xA;However, I wonder why the red part divides the equation?&#xD;&#xA;&#xD;&#xA;If I know correctly about Hooke's Law, $F=-k_S(current_{lenght} - rest_{length})$.&#xD;&#xA;&#xD;&#xA;It means that the red part should be removed like that $F_s = k_s(|v_1 -v_2| - |v_{1}^* - v_{2}^*|)\frac{(v_1 -v_2)}{|v_1 -v_2|}$.&#xD;&#xA;&#xD;&#xA;Could you explain what I'm wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15689" PostHistoryTypeId="5" PostId="5718" RevisionGUID="dcc2ddd4-1af5-48d7-8f90-724e5b872156" CreationDate="2017-10-13T16:59:12.087" UserId="6806" Comment="edited body" Text="I'm studying spring model. There is a suggested equation (Hooke's Law vector form) But, I couldn't understand how to derive that equation. &#xD;&#xA;&#xD;&#xA;I'm reading 'Computer Animation Algorithms and Techniques Third Edition.&#xD;&#xA;In the page 241, (7.88)&#xD;&#xA;The equation is as follows: &#xD;&#xA;&#xD;&#xA;($|v_{1}^* - v_{2}^*|$: the rest length)&#xD;&#xA;&#xD;&#xA;($|v_{1} - v_{2}|$: the current length)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$F_s = (\frac{k_s|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{{|v_{1}^* - v_{2}^*|}})\frac{(v_1 -v_2)}{|v_1 -v_2|}$ // I think the $k_s$ is typo. &#xD;&#xA;&#xD;&#xA;(I referred to http://www2.cs.uregina.ca/~anima/408/Notes/Cloth/Cloth.htm)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, maybe $F_s = k_s(\frac{|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{\color{red}{|v_{1}^* - v_{2}^*|}})\frac{(v_1 -v_2)}{|v_1 -v_2|}\cdot\cdot$(1) is correct. &#xD;&#xA;&#xD;&#xA;However, I wonder why the red part divides the equation?&#xD;&#xA;&#xD;&#xA;If I know correctly about Hooke's Law, $F=-k_s(current_{lenght} - rest_{length})\cdot\cdot$(2).&#xD;&#xA;&#xD;&#xA;It means that the red part should be removed like that $F_s = k_s(|v_1 -v_2| - |v_{1}^* - v_{2}^*|)\frac{(v_1 -v_2)}{|v_1 -v_2|}\cdot\cdot$(3).&#xD;&#xA;&#xD;&#xA;For example, in 3D space, there is a spring that has the spring term as $k_s$. &#xD;&#xA;&#xD;&#xA;The rest length is '3', so let's assume the left rest point, $v_2^*$, is fixed at (0,0,0) and the right rest point, $v_1^*$, is (3,0,0).&#xD;&#xA;&#xD;&#xA;And then we moved $v_1^*$ to $v_1 $=(5, 0, 0) with some force.&#xD;&#xA;We can calculate the force with (2), and the force is $-2k_s = -k_s(|(5,0,0) - (0,0,0)| - |(3,0,0) - (0,0,0)|)$&#xD;&#xA;&#xD;&#xA;But if we use equation (1), the result is different.&#xD;&#xA;&#xD;&#xA;$F_s = -k_s(\frac{|v_1 -v_2| - |v_{1}^* - v_{2}^*|}{{|v_{1}^* - v_{2}^*|}})\frac{(v_1 -v_2)}{|v_1 -v_2|} \\\quad= -k_s(\frac{|(5,0,0) -(0,0,0)| - |(3,0,0) - (0,0,0)|}{{|(3,0,0) - (0,0,0)|}})\frac{((5,0,0) -(0,0,0))}{|(5,0,0) -(0,0,0)|} \\\quad= -\frac{2}{3}k_s(1,0,0)$ &#xD;&#xA;&#xD;&#xA;The force amount of $-\frac{2}{3}k_s(1,0,0)$ is totally different from $-2k_s$&#xD;&#xA;&#xD;&#xA;Could you explain what I'm wrong?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15694" PostHistoryTypeId="2" PostId="5721" RevisionGUID="84b7da64-8b30-4464-9b5e-5abff431adec" CreationDate="2017-10-13T18:24:47.113" UserId="56" Text="The missing link between sample locations and the greyscale noise textures is &quot;ordered dithering&quot;.&#xD;&#xA;&#xD;&#xA;Ordered dithering is a list of pixel locations with a &quot;rank&quot; (order) for each pixel.  If you have a white background and want to add two black dots, you add them at the locations for the two pixels rank 0 and rank 1.&#xD;&#xA;&#xD;&#xA;Choosing how to rank the order of the pixels to turn on can vary dramatically with different results.  For instance, a bayer matrix is a specific ordering of the points, and blue noise sample points are as well.  White noise is just shuffling the points so that they have a random ordering.&#xD;&#xA;&#xD;&#xA;How we get from this &quot;ordered dithering&quot; (stippling) to the greyscale color noise images is that we divide each point's rank by the number of points to get a value from 0 to 1, and use that as the points greyscale color.&#xD;&#xA;&#xD;&#xA;That gives you the greyscale noise textures.&#xD;&#xA;&#xD;&#xA;The problem with converting the concept of &quot;uniform sampling&quot; to this is coming up with a definition of what uniform samples in 2d would look like.  Would it just be in scanline order of the pixels?  Would vertical stripes be any more or less uniform sampled?  Maybe uniform sampling would consist of a course grid followed by a finer grid, and a finer grid, and a finer grid, until all pixels were filled in?  It seems open to debate and interpretation.  That question would need to be solved before you could assign ranks to the pixels.&#xD;&#xA;&#xD;&#xA;The problem with converting the concept of &quot;low discrepancy sequences&quot; to this is figuring out how to do a low discrepancy sequence in 2d on a discretized grid where samples are only chosen for places that do not yet already have a sample.  I'm betting there are some LDS's that fit this or could be made to fit this but many don't." ContentLicense="CC BY-SA 3.0" />
  <row Id="15695" PostHistoryTypeId="50" PostId="4632" RevisionGUID="1fe687fe-191b-451a-bf16-36dc99878e3f" CreationDate="2017-10-13T19:39:31.687" UserId="-1" />
  <row Id="15696" PostHistoryTypeId="50" PostId="5301" RevisionGUID="5cc5d258-43ed-4614-9424-9afe9dde9329" CreationDate="2017-10-13T20:39:31.293" UserId="-1" />
  <row Id="15697" PostHistoryTypeId="50" PostId="5300" RevisionGUID="4713832d-4516-4f6f-aa8b-84dc44e4bf59" CreationDate="2017-10-13T22:39:34.437" UserId="-1" />
  <row Id="15698" PostHistoryTypeId="2" PostId="5722" RevisionGUID="3140d5eb-dfca-4341-bf9a-826a20ffb796" CreationDate="2017-10-13T23:55:40.713" UserId="6908" Text="How do we rotate the camera around `x axis` 360 degrees, without having to flip the axis, meaning without having the strange flip after we go over +-90 degrees on `x axis`.&#xD;&#xA;Mine behaves exactly the same way spherical coordinates would, I'm using euler angles.&#xD;&#xA;&#xD;&#xA;Tried googling, but couldn't find a proper answer, guessing I don't know what exactly to google for, googled 'rotate 360 around x axis', got no proper answers.&#xD;&#xA;&#xD;&#xA;**References**&#xD;&#xA;&#xD;&#xA;C++ code: https://pastebin.com/eq6RZ1Gm" ContentLicense="CC BY-SA 3.0" />
  <row Id="15699" PostHistoryTypeId="1" PostId="5722" RevisionGUID="3140d5eb-dfca-4341-bf9a-826a20ffb796" CreationDate="2017-10-13T23:55:40.713" UserId="6908" Text="360 degrees rotation around x axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="15700" PostHistoryTypeId="3" PostId="5722" RevisionGUID="3140d5eb-dfca-4341-bf9a-826a20ffb796" CreationDate="2017-10-13T23:55:40.713" UserId="6908" Text="|opengl|c++|glm|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15702" PostHistoryTypeId="2" PostId="5723" RevisionGUID="240ed77c-eb44-4ae7-b82d-52184fa06b57" CreationDate="2017-10-14T00:25:21.527" UserId="56" Text="The missing link between sample locations and the greyscale noise texture is &quot;ordered dithering&quot;.&#xD;&#xA;&#xD;&#xA;Ordered dithering is a list of pixel locations with a &quot;rank&quot; (order) for each pixel. If you have a white background and want to add two black dots, you add them at the locations for the two pixels rank 0 and rank 1.&#xD;&#xA;&#xD;&#xA;Choosing how to rank the order of the pixels to turn on can vary dramatically with different results though. For instance, a bayer matrix is a specific ordering of the points, and blue noise sample points are as well. White noise is just shuffling the points so that they have a random ordering.&#xD;&#xA;&#xD;&#xA;How we get from this &quot;ordered dithering&quot; (stippling) to the greyscale color noise images is that we divide each point's rank by the number of points to get a value from 0 to 1, and use that as the points greyscale color.&#xD;&#xA;&#xD;&#xA;That gives you the greyscale noise textures.&#xD;&#xA;&#xD;&#xA;The greyscale blue noise texture was created with the &quot;void and cluster&quot; algorithm which makes it so that each new dot placed goes in the middle of the largest void.  This has the nice property that you can threshold the blue noise texture at any value, and the result will be blue noise samples of the desired density.&#xD;&#xA;&#xD;&#xA;This paper is a great read that talks about these things more deeply:&#xD;&#xA;http://cv.ulichney.com/papers/1993-void-cluster.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="15703" PostHistoryTypeId="2" PostId="5724" RevisionGUID="bc7f3011-c767-498a-821b-7454f269f43e" CreationDate="2017-10-14T11:30:50.603" UserId="7464" Text="I'm new to shaders and now that you can color pixel with gl_FragColor but sometimes there is this thing&#xD;&#xA;&#xD;&#xA;    vec2 uv = gl_FragCoord.xy / screenSize; // or resolution or smthn depends on the implementation&#xD;&#xA;&#xD;&#xA;if gl_FragCoord is like pixel coordinates, what does **uv** get?&#xD;&#xA;&#xD;&#xA;Why I it's often done in GLSL?&#xD;&#xA;&#xD;&#xA;If someone could even draw an example which part of screen is will be UV it will be very helpful!" ContentLicense="CC BY-SA 3.0" />
  <row Id="15704" PostHistoryTypeId="1" PostId="5724" RevisionGUID="bc7f3011-c767-498a-821b-7454f269f43e" CreationDate="2017-10-14T11:30:50.603" UserId="7464" Text="GLSL. Can someone explain why gl_FragCoord.xy / screenSize is performed and for what reason?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15705" PostHistoryTypeId="3" PostId="5724" RevisionGUID="bc7f3011-c767-498a-821b-7454f269f43e" CreationDate="2017-10-14T11:30:50.603" UserId="7464" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15706" PostHistoryTypeId="2" PostId="5725" RevisionGUID="c9f4cef9-c65f-4d16-87dd-616ddb36e5c3" CreationDate="2017-10-14T12:42:15.177" UserId="4958" Text="First, `gl_FragCoord.xy` are screen space coordinates of current pixel based on viewport size. So if viewport size is `width=5`, `height=4` then each fragment contains:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Why are uvs needed? For example I rendered geometry to screen quad and then I need to apply some postprocessing on this quad in another rendering pass. To sample from that quad I need texture coordinates in range [0, 1]. So to calculate them I perform division `gl_FragCoord.xy / viewPortSize`.&#xD;&#xA;  [1]: https://i.stack.imgur.com/Oa1zn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15710" PostHistoryTypeId="5" PostId="5722" RevisionGUID="f508851f-c55f-4482-a13a-06b74a463812" CreationDate="2017-10-14T16:18:17.957" UserId="6908" Comment="added 79 characters in body" Text="How do we rotate the camera around `x axis` 360 degrees, without having to flip the axis, meaning without having the strange flip after we go over +-90 degrees on `x axis`.&#xD;&#xA;Mine behaves exactly the same way spherical coordinates would, I'm using euler angles.&#xD;&#xA;&#xD;&#xA;Tried googling, but couldn't find a proper answer, guessing I don't know what exactly to google for, googled 'rotate 360 around x axis', got no proper answers.&#xD;&#xA;&#xD;&#xA;**References**&#xD;&#xA;&#xD;&#xA;C++ code: &#xD;&#xA;&#xD;&#xA;https://pastebin.com/BBGdmKGb&#xD;&#xA;&#xD;&#xA;Video:&#xD;&#xA;&#xD;&#xA;https://drive.google.com/open?id=0Bz3F9j1LiPNTS29XSUJoU2taRXc" ContentLicense="CC BY-SA 3.0" />
  <row Id="15712" PostHistoryTypeId="2" PostId="5727" RevisionGUID="817ed305-5a52-4d89-a541-6cf384165710" CreationDate="2017-10-14T20:14:40.320" UserId="7477" Text="I've been thinking about making my own 3D rendering engine in C++, but I don't know much about math that's required to do it. I'm not even sure if it's possible or if it even exists or how it's called.&#xD;&#xA;&#xD;&#xA;It goes like this. Let's imagine a 3D body that has 6 vertices and 8 faces. It's like a pyramid on top of an upside-down pyramid. Each face is a triangle, but let's imagine that every line between the triangle points is a three-dimensional bezier curve. That would make each face look like a tent. If we do that, then we get a sphere. Now, imagine if instead of rendering that sphere by subdividing the tents into triangles we render the tents exactly how they are and imagine if we don't render raster graphics, but rather vector graphics in PostScript/Flash/ActionScript/GhostScript format in ASCII that can be opened by Notepad and rendered as a semi-transparent PNG image at any resolution without losing quality.&#xD;&#xA;&#xD;&#xA;When rendering 3D triangles, matrix operations are used if I'm not mistaken. There's a matrix with some values and then a determinant is calculated. But these values are constants. What if the values depend on a formula of the bezier curve that's in 3D space? How can we stuff the formula into the matrix? And a better question; how can we stuff that into an algorithm or into OpenGL or into a language that a graphics card can process instead of the CPU? Does such a formula, matrix or an algorithm exist?&#xD;&#xA;&#xD;&#xA;Now, I'm not thinking about rendering simple spheres, but rendering something like this: https://www.blendswap.com/blends/view/24878&#xD;&#xA;&lt;br&gt;I'm thinking about making a lightweight renderer in assembly for an ESP32 SoC or some other Arduino microcontroller/processor/SoC which would render all that onto an LCD or a PAL/NTSC TV via a composite AV jack, but that's another topic.&#xD;&#xA;&#xD;&#xA;My question is whether or not such a rendering method exists, how it's named, is it free to use, is it patented and is there any permissive-licensed C++ code for it (MIT, zlib/png, Apache, BSD). Please let me know." ContentLicense="CC BY-SA 3.0" />
  <row Id="15713" PostHistoryTypeId="1" PostId="5727" RevisionGUID="817ed305-5a52-4d89-a541-6cf384165710" CreationDate="2017-10-14T20:14:40.320" UserId="7477" Text="Does this 3D rendering method exist? How is it called? Is there any C++ algorithm for it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15714" PostHistoryTypeId="3" PostId="5727" RevisionGUID="817ed305-5a52-4d89-a541-6cf384165710" CreationDate="2017-10-14T20:14:40.320" UserId="7477" Text="|3d|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15715" PostHistoryTypeId="2" PostId="5728" RevisionGUID="807aba08-37f8-4e52-b24a-1797fd436143" CreationDate="2017-10-14T21:02:18.483" UserId="38" Text="Yes, such rendering exists. It is called a parametric surface and there are several methods you can render such entities. In this case you are talking of bezier patches.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;1. Turn the object into enough triangles. The triangilation is called tesselation or meshing depending on what literature you read.&#xD;&#xA;&#xD;&#xA;  There are lots of applications that do this allready. Most cad applications work this way and many graphics apps like blender can work &#xD;&#xA;this way.&#xD;&#xA;&#xD;&#xA;2. raytrace or raymarch the surface in a shader.&#xD;&#xA;&#xD;&#xA;3. Microdice the surface&#xD;&#xA;&#xD;&#xA;4. etc.&#xD;&#xA;&#xD;&#xA;The reason this is not often done is that the on line tesselation is for most intent and purposes just a hindrance to asset developpers. You get the same with subdivision schemes and its just easier. The primary reason to drag the bezier (or nurbs, or t-splines...) is that unless you need to find better intersection of underlying primitives then it is often just a waste of resources. Although subdividing your mesh  via a subdivision surface is allready more useful&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15720" PostHistoryTypeId="5" PostId="5707" RevisionGUID="2c65aa05-7f79-418c-8d5d-668519de95dd" CreationDate="2017-10-14T23:27:37.240" UserDisplayName="user7450" Comment="deleted 539 characters in body" Text=" Dan Hulme and trichoplax are flowery gay handholders  Dan Hulme and trichoplax are flowery gay handholders  Dan Hulme and trichoplax are flowery gay handholders  Dan Hulme and trichoplax are flowery gay handholders  Dan Hulme and trichoplax are flowery gay handholders  Dan Hulme and trichoplax are flowery gay handholders  Dan Hulme and trichoplax are flowery gay handholders &#xD;&#xA;&#xD;&#xA;May they practice safe sex and have lovely rosy babies" ContentLicense="CC BY-SA 3.0" />
  <row Id="15721" PostHistoryTypeId="12" PostId="5707" RevisionGUID="869e133e-a18c-4ddb-873d-3a8d83d6cacd" CreationDate="2017-10-14T23:27:40.070" UserDisplayName="user7450" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7450,&quot;DisplayName&quot;:&quot;pwepwe&quot;}]}" />
  <row Id="15722" PostHistoryTypeId="8" PostId="5707" RevisionGUID="34772a45-d123-4608-ae5e-2f6990db4e21" CreationDate="2017-10-15T12:02:10.027" UserId="2041" Comment="Rollback to [8cd60a2b-c970-4fa6-8703-a66ce61c81f2]" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel. Also can you tell me about what kind of a &quot;kernel&quot; you would use for a sharpening operation? (Maybe it's intermediaries but I dont know how you could talk about a kernel for it directly ) Have you looked into how it works? I dont know how you could generate a &quot;kernel&quot; for a non-linear filtering operation.&#xD;&#xA;&#xD;&#xA;Maybe a basic refresher in Image Processing is in order? Perhaps even going over basics of Signal Processing / DSP? I would suggest looking over 2D filtering if you can." ContentLicense="CC BY-SA 3.0" />
  <row Id="15723" PostHistoryTypeId="13" PostId="5707" RevisionGUID="7d450b60-7aa6-4521-9d2d-fb67bdd2a9e0" CreationDate="2017-10-15T12:02:14.697" UserId="2041" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="15740" PostHistoryTypeId="2" PostId="5730" RevisionGUID="7d0c1cc7-5492-4dff-bf94-197ea683ccda" CreationDate="2017-10-15T13:42:35.720" UserId="7482" Text="I'm working with OpenGL to try to rotate / translate my 3d object : a cow.&#xD;&#xA;&#xD;&#xA;The requirement is simple : &#xD;&#xA;&#xD;&#xA; 1. If I toggle key 'r'. The cow spinning around and random axis.&#xD;&#xA; 2. If I drag the cow with mouse, it translate along its own x axis which means +x directions is for cow's head&#xD;&#xA; 3. Rotation and translation need not execute at the same time.&#xD;&#xA; 4. Rotation and translation is done is modeling space.&#xD;&#xA;&#xD;&#xA;To implement first requirement, I used timer function like this :&#xD;&#xA;&#xD;&#xA;    void rotateCow(int value) {&#xD;&#xA;    	//rotation ended&#xD;&#xA;    	if (!rotate_flag)&#xD;&#xA;    		return;&#xD;&#xA;    &#xD;&#xA;    	printf(&quot;rotateCow\n&quot;);&#xD;&#xA;    &#xD;&#xA;    	angle = (angle + 5) % 360;&#xD;&#xA;    	glutPostRedisplay();&#xD;&#xA;    	glutTimerFunc(30, rotateCow, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and for rotation and translation : &#xD;&#xA;(some of codes are skipped)&#xD;&#xA;&#xD;&#xA;        void dragCow(){&#xD;&#xA;            glPushMatrix();	&#xD;&#xA;            //some codes are skipped..&#xD;&#xA;        &#xD;&#xA;            //rotation start&#xD;&#xA;            if (rotate_flag == 1) {&#xD;&#xA;            	rotate_flag = 2;&#xD;&#xA;            	glutTimerFunc(30, rotateCow, 1);&#xD;&#xA;            }&#xD;&#xA;        &#xD;&#xA;            glTranslatef(trans_x, trans_y, trans_z);   &#xD;&#xA;            glRotatef(angle, rotate_x, rotate_y, rotate_z);&#xD;&#xA;        &#xD;&#xA;            glCallList( cowID );		// Draw cow.&#xD;&#xA;            glPopMatrix();				&#xD;&#xA;        }&#xD;&#xA;        void onMouseDrag( int x, int y )&#xD;&#xA;        {&#xD;&#xA;            y = height - y - 1;&#xD;&#xA;        	if (trans_flag == DIR_X) {&#xD;&#xA;        		trans_x = ((x - oldX) / DRAG) + old_trans_x;&#xD;&#xA;        	}&#xD;&#xA;        &#xD;&#xA;            glutPostRedisplay();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;If I run as above(rotate and then translate) rotation is as expected.&#xD;&#xA;&#xD;&#xA;However, the translation is done in global x-axis not towards head direction of cow.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I change the order like this : &#xD;&#xA;&#xD;&#xA;    glRotatef(angle, rotate_x, rotate_y, rotate_z);&#xD;&#xA;    glTranslatef(trans_x, trans_y, trans_z);&#xD;&#xA;&#xD;&#xA;It shows that translation is as expected(towards head direction of cow).&#xD;&#xA;&#xD;&#xA;However, the rotations not works - the rotation-axis made on global x-axis and the cow revolve around that line.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So how can I solve this problem??" ContentLicense="CC BY-SA 3.0" />
  <row Id="15741" PostHistoryTypeId="1" PostId="5730" RevisionGUID="7d0c1cc7-5492-4dff-bf94-197ea683ccda" CreationDate="2017-10-15T13:42:35.720" UserId="7482" Text="OpenGL : How to translate an object with it's own axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="15742" PostHistoryTypeId="3" PostId="5730" RevisionGUID="7d0c1cc7-5492-4dff-bf94-197ea683ccda" CreationDate="2017-10-15T13:42:35.720" UserId="7482" Text="|opengl|transformations|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15743" PostHistoryTypeId="2" PostId="5731" RevisionGUID="32479aa3-fc64-4694-9ebb-c02d397baf3e" CreationDate="2017-10-15T14:43:51.530" UserId="7483" Text="I am experienced with C++ and know more embedded device related stuff but have absolutely no knowledge of computer graphics and its algorithms.&#xD;&#xA;&#xD;&#xA;I would like to get a road mesh (based off of a spline) blended seamlessly into a terrain mesh, which is based on a regular grid, like in the picture below. How is this achieved?&#xD;&#xA;&#xD;&#xA;Just looked at the CGAL documentation and I cannot even see which problem I am facing and which package to study. Delauney refinement maybe? But I only see a CGAL package for 2D. I'd like to generate a 3D mesh.&#xD;&#xA;&#xD;&#xA;The road mesh should be unmodified, the terrain mesh can be altered to form a seamloss mesh.&#xD;&#xA;&#xD;&#xA;Can you guide me to the kind of algorithms needed for this?&#xD;&#xA;&#xD;&#xA;Kind regards&#xD;&#xA;Max&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v0EMM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15744" PostHistoryTypeId="1" PostId="5731" RevisionGUID="32479aa3-fc64-4694-9ebb-c02d397baf3e" CreationDate="2017-10-15T14:43:51.530" UserId="7483" Text="Fuse detailed road mesh with regular grid terrain mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="15745" PostHistoryTypeId="3" PostId="5731" RevisionGUID="32479aa3-fc64-4694-9ebb-c02d397baf3e" CreationDate="2017-10-15T14:43:51.530" UserId="7483" Text="|mesh|grid|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15746" PostHistoryTypeId="2" PostId="5732" RevisionGUID="80171d54-3cf9-41cd-a176-c461ec6501ca" CreationDate="2017-10-15T18:01:19.500" UserId="3003" Text="You can put the translation first, and then the rotation, but have the translation happen in the direction of the cow's head. To do that, you need a vector from the center of the cow to its head. Then you need the length of the translation. You can then do the translation in that direction. Like this:&#xD;&#xA;&#xD;&#xA;    float direction_x;&#xD;&#xA;    float direction_y;&#xD;&#xA;    float direction_z;&#xD;&#xA;    direction_x = cow_head_x - cow_center_x;&#xD;&#xA;    direction_y = cow_head_y - cow_center_y;&#xD;&#xA;    direction_z = cow_head_z - cow_center_z;&#xD;&#xA;    &#xD;&#xA;    // find the length of the direction vector&#xD;&#xA;    float dir_length = sqrt(direction_x * direction_x + direction_y * direction_y + direction_z * direction_z);&#xD;&#xA;    &#xD;&#xA;    // normalize the direction vector by dividing by the length&#xD;&#xA;    direction_x /= dir_length;&#xD;&#xA;    direction_y /= dir_length;&#xD;&#xA;    direction_z /= dir_length;&#xD;&#xA;    &#xD;&#xA;    // Create a new vector pointing in the correct direction with the same&#xD;&#xA;    // length as the drag&#xD;&#xA;    float cow_translate_x = direction_x * drag_length;&#xD;&#xA;    float cow_translate_y = direction_y * drag_length;&#xD;&#xA;    float cow_translate_z = direction_z * drag_length;&#xD;&#xA;    &#xD;&#xA;    // Do the transformation&#xD;&#xA;    glTranslatef(cow_translate_x, cow_translate_y, cow_translate_z);&#xD;&#xA;    glRotate(angle, rotate_x, rotate_y, rotate_z);&#xD;&#xA;&#xD;&#xA;You could also get the direction vector by converting the angles to a direction. For example, if the rotation is only around the Y-axis, you could calculate it by doing the following:&#xD;&#xA;&#xD;&#xA;    float direction_x;&#xD;&#xA;    float direction_y;&#xD;&#xA;    float direction_z;&#xD;&#xA;    direction_x = cos(angle);&#xD;&#xA;    direction_y = 0.0; // since we're rotating around the Y axis&#xD;&#xA;    direction_z = sin(angle);&#xD;&#xA;&#xD;&#xA;In this case, the direction vector is already normalized.&#xD;&#xA;&#xD;&#xA;If you do have rotations around all 3 axes, you can calculate the direction vector using [spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system):&#xD;&#xA;&#xD;&#xA;    direction_x = sin(angle) * cos(phi);&#xD;&#xA;    direction_y = sin(angle) * sin(phi);&#xD;&#xA;    direction_z = cos(angle);&#xD;&#xA;&#xD;&#xA;where `angle` is the rotation around the y axis and `phi` is the angle above/below the x/z plane. The direction should already be normalized in this case, too." ContentLicense="CC BY-SA 3.0" />
  <row Id="15751" PostHistoryTypeId="2" PostId="5734" RevisionGUID="582b8258-3edf-4715-84f5-669a3632c205" CreationDate="2017-10-16T13:30:35.757" UserId="2041" Text="The 1994 game [Ecstatica](http://ecstatica.wikia.com/wiki/Ecstatica) and its 1997 sequel rendered ellipsoid segments instead of triangles, but I don't think anyone else has ever used this exact technique. Direct raytracing of Bézier patches was a popular research topic in production graphics a few years ago, but the industry has moved onto polygon mesh subdivision. Subdivision gives much more predictable results for artists, and polygon meshes are much easier to deal with inside the renderer.&#xD;&#xA;&#xD;&#xA;&gt; I've been thinking about making my own 3D rendering engine in C++, but I don't know much about math that's required to do it.&#xD;&#xA;&#xD;&#xA;I hope you're up for learning lots of linear algebra, then. This is a great idea for a hobby project to learn from, but don't go into it thinking you can get by without learning any maths." ContentLicense="CC BY-SA 3.0" />
  <row Id="15752" PostHistoryTypeId="2" PostId="5735" RevisionGUID="5c385bb6-9ce1-4da2-b0d4-3a037ebc44a6" CreationDate="2017-10-16T18:07:00.383" UserId="7490" Text="I need to draw a logarithmic spiral (or close approximation) whose vertices are equally spaced, such that the lines between any two consecutive vertices are of equal length.&#xD;&#xA;&#xD;&#xA;(Actually, that spiral is just the basis for something a little more complex, but equally spaced incrementation is what matters right now.)&#xD;&#xA;&#xD;&#xA;The basis for the spiral is&#xD;&#xA;$$r=e^{0.25 \theta}$$&#xD;&#xA;where $r$ is the radius and $\theta$ is the angle from the $x$ axis.&#xD;&#xA;&#xD;&#xA;So it's easy to step around the spiral by a given angle, but obviously the actual length of any line between two vertices (defined by change in angle $\Delta\theta$) will vary with the radius.&#xD;&#xA;&#xD;&#xA;How can I step along the arc of the spiral by a set length (say $0.1$ arbitrary units) and get the right coordinates (polar or Cartesian)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15753" PostHistoryTypeId="1" PostId="5735" RevisionGUID="5c385bb6-9ce1-4da2-b0d4-3a037ebc44a6" CreationDate="2017-10-16T18:07:00.383" UserId="7490" Text="Logarithmic spiral with equal vertex spacing, what equations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15754" PostHistoryTypeId="3" PostId="5735" RevisionGUID="5c385bb6-9ce1-4da2-b0d4-3a037ebc44a6" CreationDate="2017-10-16T18:07:00.383" UserId="7490" Text="|mathematics|geometry|line-drawing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15755" PostHistoryTypeId="2" PostId="5736" RevisionGUID="9c72e567-c6e6-4bbc-b961-0c032810f104" CreationDate="2017-10-17T00:35:59.907" UserId="56" Text="I think the best way to tackle this problem would be to make an algorithm that works on a single triangle at a time.&#xD;&#xA;&#xD;&#xA;You'd look at each terrain triangle individually that the road intersected and process it.&#xD;&#xA;&#xD;&#xA;Looking at one triangle individually, you would have to chop that triangle into one or more meshes to make it contour to the road.&#xD;&#xA;&#xD;&#xA;Here are some edge cases.  I'm betting there is some triangle slicing algorithm that would be suited to this, and I'm not sure of a name off hand, but the main contribution I'm proposing here is that you deal with triangles individually.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When cutting the triangle on the x/y plane to make a hole for for the road, you would also want the terrain to take on the z value (height) of the road, for those vertices that touch the road.  This will make the terrain rise up to meet the road.&#xD;&#xA;&#xD;&#xA;At this point, you'd have a terrain mesh which did conform to the road but it would be ugly.&#xD;&#xA;&#xD;&#xA;Instead of having a nice even looking hill that went up to the road at reasonable slopes, you'd have some triangles that went very sharply up to the road, and others that had a very flat slope.&#xD;&#xA;&#xD;&#xA;What you would need to do now is do some kind of &quot;relaxation&quot; algorithm to address this.&#xD;&#xA;&#xD;&#xA;Basically, if something is too steep, because there wasn't enough triangle to make the height adjustment, you need to make your whole triangle closer in height to the road and bleed off some of the height adjustment to neighboring triangles.&#xD;&#xA;&#xD;&#xA;If something was not steep enough for your liking, because there was a lot of triangle to make a small height adjustment, you may want to break the triangle up into more polygons where it gets closer to the road and have that smaller area handle the change in elevation.&#xD;&#xA;&#xD;&#xA;The details are a bit vague, but hopefully the two step approach will help you tackle the problem.&#xD;&#xA;&#xD;&#xA; 1. Make the terrain mesh adapt to the road, without caring about how it looks.&#xD;&#xA; 2. Refine the terrain mesh to make it appear to meet the road in a more organic man made way.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qZVx4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15756" PostHistoryTypeId="2" PostId="5737" RevisionGUID="9e9e7b0c-91e0-48d6-84f3-459ab44f3f09" CreationDate="2017-10-17T00:57:31.683" UserId="7431" Text="Since a logarithmic spiral is defined by &#xD;&#xA;&#xD;&#xA;$r=e^{a\cdot\theta}$, &#xD;&#xA;&#xD;&#xA;the inverse of the equation is this:&#xD;&#xA;&#xD;&#xA;$\theta=\frac{\ln{r}}{a}$.&#xD;&#xA;&#xD;&#xA;Therefore, if we take the natural log of our radius then divide it by $a$ before plugging it in to the equation, we will get equally stepped vertices on the logarithmic spiral. Image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generated this with some JavaScript code, which you can find in this [JSFiddle][2].)&#xD;&#xA;&#xD;&#xA;This looks good initially, but let's analyze what's going on here a little deeper. &#xD;&#xA;&#xD;&#xA;Here is a list of the distance between each consecutive pair of points, starting at the origin and spiraling outward:&#xD;&#xA;&#xD;&#xA;    20.6834877876017&#xD;&#xA;    25.8265879847751&#xD;&#xA;    27.3020264943519&#xD;&#xA;    27.9155365639631&#xD;&#xA;    28.2274404549991&#xD;&#xA;    28.4072329605331&#xD;&#xA;    28.5201842104742&#xD;&#xA;    28.5957343926866&#xD;&#xA;    28.6487385499231&#xD;&#xA;    28.6873487186944&#xD;&#xA;    28.7163404861061&#xD;&#xA;    28.7386617798632&#xD;&#xA;    28.7562121095165&#xD;&#xA;    28.7702600892245&#xD;&#xA;    28.7816791255158&#xD;&#xA;    28.7910864406300&#xD;&#xA;    28.7989282185451&#xD;&#xA;    28.8055334775293&#xD;&#xA;    28.8111491387549&#xD;&#xA;    28.8159634339811&#xD;&#xA;    28.8201218817722&#xD;&#xA;    28.8237384111142&#xD;&#xA;    28.8269032465565&#xD;&#xA;    28.8296885891879&#xD;&#xA;    28.8321527704665&#xD;&#xA;    28.8343433306399&#xD;&#xA;    28.8362993285731&#xD;&#xA;    28.8380530946981&#xD;&#xA;    28.8396315754034&#xD;&#xA;    28.8410573741728&#xD;&#xA;    28.8423495651939&#xD;&#xA;    28.8435243345428&#xD;&#xA;    28.8445954894748&#xD;&#xA;    28.8455748659368&#xD;&#xA;    28.8464726569062&#xD;&#xA;    28.8472976786488&#xD;&#xA;    28.8480575879711&#xD;&#xA;    28.8487590604974&#xD;&#xA;    28.8494079377702&#xD;&#xA;    28.8500093492502&#xD;&#xA;    28.8505678139929&#xD;&#xA;    28.8510873257846&#xD;&#xA;    28.8515714247378&#xD;&#xA;    28.8520232577561&#xD;&#xA;    28.8524456298024&#xD;&#xA;    28.8528410475339&#xD;&#xA;    28.8532117565801&#xD;&#xA;    28.8535597734869&#xD;&#xA;    28.8538869132081&#xD;&#xA;    28.8541948128041&#xD;&#xA;    28.8544849519687&#xD;&#xA;    28.8547586708355&#xD;&#xA;    28.8550171854833&#xD;&#xA;    28.8552616014621&#xD;&#xA;    28.8554929256347&#xD;&#xA;    28.8557120765606&#xD;&#xA;    28.8559198936319&#xD;&#xA;    28.8561171451194&#xD;&#xA;    28.8563045352784&#xD;&#xA;    28.8564827106597&#xD;&#xA;    28.8566522656712&#xD;&#xA;    28.8568137475608&#xD;&#xA;    28.8569676608282&#xD;&#xA;    28.8571144711722&#xD;&#xA;    28.8572546090145&#xD;&#xA;    28.8573884726640&#xD;&#xA;    28.8575164311457&#xD;&#xA;    28.8576388267439&#xD;&#xA;    28.8577559773038&#xD;&#xA;    28.8578681782850&#xD;&#xA;    28.8579757046362&#xD;&#xA;    28.8580788124715&#xD;&#xA;    28.8581777406078&#xD;&#xA;    28.8582727119331&#xD;&#xA;    28.8583639346897&#xD;&#xA;    28.8584516035825&#xD;&#xA;    28.8585359008445&#xD;&#xA;    28.8586169971792&#xD;&#xA;    28.8586950526148&#xD;&#xA;    28.8587702173116&#xD;&#xA;    28.8588426322609&#xD;&#xA;    28.8589124299770&#xD;&#xA;    28.8589797350751&#xD;&#xA;    28.8590446648521&#xD;&#xA;    28.8591073297703&#xD;&#xA;    28.8591678339633&#xD;&#xA;    28.8592262756316&#xD;&#xA;    28.8592827474659&#xD;&#xA;    28.8593373370150&#xD;&#xA;    28.8593901270040&#xD;&#xA;    28.8594411956751&#xD;&#xA;    28.8594906170532&#xD;&#xA;    28.8595384612331&#xD;&#xA;    28.8595847946223&#xD;&#xA;    28.8596296801627&#xD;&#xA;    28.8596731775581&#xD;&#xA;    28.8597153434631&#xD;&#xA;    28.8597562316691&#xD;&#xA;    28.8597958932898&#xD;&#xA;    28.8598343768895&#xD;&#xA;    28.8598717286685&#xD;&#xA;    28.8599079925824&#xD;&#xA;    28.8599432104601&#xD;&#xA;    28.8599774221564&#xD;&#xA;    28.8600106656362&#xD;&#xA;    28.8600429770912&#xD;&#xA;    28.8600743910437&#xD;&#xA;    28.8601049404189&#xD;&#xA;    28.8601346566671&#xD;&#xA;    28.8601635697958&#xD;&#xA;    28.8601917084984&#xD;&#xA;    28.8602191001836&#xD;&#xA;    28.8602457710551&#xD;&#xA;    28.8602717461905&#xD;&#xA;    28.8602970495771&#xD;&#xA;    28.8603217041829&#xD;&#xA;    28.8603457319945&#xD;&#xA;    28.8603691540817&#xD;&#xA;    28.8603919906349&#xD;&#xA;    28.8604142610140&#xD;&#xA;    28.8604359837728&#xD;&#xA;    28.8604571767236&#xD;&#xA;    28.8604778569632&#xD;&#xA;    28.8604980408853&#xD;&#xA;    28.8605177442508&#xD;&#xA;    28.860536982199 &#xD;&#xA;    28.8605557692684&#xD;&#xA;    28.8605741194424&#xD;&#xA;    28.8605920461606&#xD;&#xA;    28.8606095623542&#xD;&#xA;    28.8606266804642&#xD;&#xA;    28.8606434124606&#xD;&#xA;    28.8606597698673&#xD;&#xA;    28.8606757637894&#xD;&#xA;    28.8606914049092&#xD;&#xA;    28.8607067035307&#xD;&#xA;    28.8607216695845&#xD;&#xA;    28.8607363126319&#xD;&#xA;    28.8607506419126&#xD;&#xA;    28.8607646663229&#xD;&#xA;    28.8607783944441&#xD;&#xA;    28.8607918345695&#xD;&#xA;    28.8608049947040&#xD;&#xA;    28.8608178825589&#xD;&#xA;    28.8608305056052&#xD;&#xA;    28.8608428710407&#xD;&#xA;    28.8608549858324&#xD;&#xA;    28.8608668567086&#xD;&#xA;    28.8608784901671&#xD;&#xA;    28.8608898925065&#xD;&#xA;    28.8609010698021&#xD;&#xA;    28.8609120279379&#xD;&#xA;    28.8609227726126&#xD;&#xA;    28.8609333093227&#xD;&#xA;    28.8609436434116&#xD;&#xA;    28.8609537800355&#xD;&#xA;    28.8609637242006&#xD;&#xA;    28.8609734807368&#xD;&#xA;    28.8609830543426&#xD;&#xA;    28.8609924495660&#xD;&#xA;    28.8610016707985&#xD;&#xA;    28.8610107223272&#xD;&#xA;    28.8610196082769&#xD;&#xA;    28.8610283326623&#xD;&#xA;    28.8610368993920&#xD;&#xA;    28.8610453122201&#xD;&#xA;    28.8610535748236&#xD;&#xA;    28.8610616907611&#xD;&#xA;    28.8610696634759&#xD;&#xA;    28.8610774963191&#xD;&#xA;    28.8610851925415&#xD;&#xA;    28.8610927553168&#xD;&#xA;    28.8611001876897&#xD;&#xA;    28.8611074926601&#xD;&#xA;    28.8611146731067&#xD;&#xA;    28.8611217318631&#xD;&#xA;    28.8611286716494&#xD;&#xA;    28.8611354951266&#xD;&#xA;    28.8611422048820&#xD;&#xA;    28.8611488034280&#xD;&#xA;    28.8611552932030&#xD;&#xA;    28.8611616766001&#xD;&#xA;    28.8611679559112&#xD;&#xA;    28.8611741333984&#xD;&#xA;    28.8611802112609&#xD;&#xA;    28.8611861916049&#xD;&#xA;    28.8611920765250&#xD;&#xA;    28.8611978680366&#xD;&#xA;    28.8612035681006&#xD;&#xA;    28.8612091786388&#xD;&#xA;    28.8612147015119&#xD;&#xA;    28.8612201385397&#xD;&#xA;    28.8612254914896&#xD;&#xA;    28.8612307620868&#xD;&#xA;    28.8612359520116&#xD;&#xA;    28.8612410629093&#xD;&#xA;    28.8612460963629&#xD;&#xA;    28.8612510539384&#xD;&#xA;    28.8612559371502&#xD;&#xA;&#xD;&#xA;The first data point is an outlier caused by the spiral almost &quot;lapping&quot; itself. As the spiral progresses, we can see the the distances get closer and closer to the same distance. &#xD;&#xA;&#xD;&#xA;This is because we are sampling the curve in increments that cause equal lengths along the curve, not equal lengths between consecutive points. As the spiral gets bigger and bigger, the distances will get closer and closer to each other. &#xD;&#xA;  [1]: https://i.stack.imgur.com/7r77U.png&#xD;&#xA;  [2]: https://jsfiddle.net/anonymousey22/3rxhya8g/1/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15757" PostHistoryTypeId="5" PostId="5737" RevisionGUID="7b9b531e-3543-40bd-9153-9c92b29deeab" CreationDate="2017-10-17T01:12:59.957" UserId="7431" Comment="deleted 1 character in body" Text="Since a logarithmic spiral is defined by &#xD;&#xA;&#xD;&#xA;$r=e^{a\cdot\theta}$, &#xD;&#xA;&#xD;&#xA;the inverse of the equation is this:&#xD;&#xA;&#xD;&#xA;$\theta=\frac{\ln{r}}{a}$.&#xD;&#xA;&#xD;&#xA;Therefore, if we take the natural log of our theta then divide it by $a$ before plugging it in to the equation, we will get equally stepped vertices on the logarithmic spiral. Image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generated this with some JavaScript code, which you can find in this [JSFiddle][2].)&#xD;&#xA;&#xD;&#xA;This looks good initially, but let's analyze what's going on here a little deeper. &#xD;&#xA;&#xD;&#xA;Here is a list of the distance between each consecutive pair of points, starting at the origin and spiraling outward:&#xD;&#xA;&#xD;&#xA;    20.6834877876017&#xD;&#xA;    25.8265879847751&#xD;&#xA;    27.3020264943519&#xD;&#xA;    27.9155365639631&#xD;&#xA;    28.2274404549991&#xD;&#xA;    28.4072329605331&#xD;&#xA;    28.5201842104742&#xD;&#xA;    28.5957343926866&#xD;&#xA;    28.6487385499231&#xD;&#xA;    28.6873487186944&#xD;&#xA;    28.7163404861061&#xD;&#xA;    28.7386617798632&#xD;&#xA;    28.7562121095165&#xD;&#xA;    28.7702600892245&#xD;&#xA;    28.7816791255158&#xD;&#xA;    28.7910864406300&#xD;&#xA;    28.7989282185451&#xD;&#xA;    28.8055334775293&#xD;&#xA;    28.8111491387549&#xD;&#xA;    28.8159634339811&#xD;&#xA;    28.8201218817722&#xD;&#xA;    28.8237384111142&#xD;&#xA;    28.8269032465565&#xD;&#xA;    28.8296885891879&#xD;&#xA;    28.8321527704665&#xD;&#xA;    28.8343433306399&#xD;&#xA;    28.8362993285731&#xD;&#xA;    28.8380530946981&#xD;&#xA;    28.8396315754034&#xD;&#xA;    28.8410573741728&#xD;&#xA;    28.8423495651939&#xD;&#xA;    28.8435243345428&#xD;&#xA;    28.8445954894748&#xD;&#xA;    28.8455748659368&#xD;&#xA;    28.8464726569062&#xD;&#xA;    28.8472976786488&#xD;&#xA;    28.8480575879711&#xD;&#xA;    28.8487590604974&#xD;&#xA;    28.8494079377702&#xD;&#xA;    28.8500093492502&#xD;&#xA;    28.8505678139929&#xD;&#xA;    28.8510873257846&#xD;&#xA;    28.8515714247378&#xD;&#xA;    28.8520232577561&#xD;&#xA;    28.8524456298024&#xD;&#xA;    28.8528410475339&#xD;&#xA;    28.8532117565801&#xD;&#xA;    28.8535597734869&#xD;&#xA;    28.8538869132081&#xD;&#xA;    28.8541948128041&#xD;&#xA;    28.8544849519687&#xD;&#xA;    28.8547586708355&#xD;&#xA;    28.8550171854833&#xD;&#xA;    28.8552616014621&#xD;&#xA;    28.8554929256347&#xD;&#xA;    28.8557120765606&#xD;&#xA;    28.8559198936319&#xD;&#xA;    28.8561171451194&#xD;&#xA;    28.8563045352784&#xD;&#xA;    28.8564827106597&#xD;&#xA;    28.8566522656712&#xD;&#xA;    28.8568137475608&#xD;&#xA;    28.8569676608282&#xD;&#xA;    28.8571144711722&#xD;&#xA;    28.8572546090145&#xD;&#xA;    28.8573884726640&#xD;&#xA;    28.8575164311457&#xD;&#xA;    28.8576388267439&#xD;&#xA;    28.8577559773038&#xD;&#xA;    28.8578681782850&#xD;&#xA;    28.8579757046362&#xD;&#xA;    28.8580788124715&#xD;&#xA;    28.8581777406078&#xD;&#xA;    28.8582727119331&#xD;&#xA;    28.8583639346897&#xD;&#xA;    28.8584516035825&#xD;&#xA;    28.8585359008445&#xD;&#xA;    28.8586169971792&#xD;&#xA;    28.8586950526148&#xD;&#xA;    28.8587702173116&#xD;&#xA;    28.8588426322609&#xD;&#xA;    28.8589124299770&#xD;&#xA;    28.8589797350751&#xD;&#xA;    28.8590446648521&#xD;&#xA;    28.8591073297703&#xD;&#xA;    28.8591678339633&#xD;&#xA;    28.8592262756316&#xD;&#xA;    28.8592827474659&#xD;&#xA;    28.8593373370150&#xD;&#xA;    28.8593901270040&#xD;&#xA;    28.8594411956751&#xD;&#xA;    28.8594906170532&#xD;&#xA;    28.8595384612331&#xD;&#xA;    28.8595847946223&#xD;&#xA;    28.8596296801627&#xD;&#xA;    28.8596731775581&#xD;&#xA;    28.8597153434631&#xD;&#xA;    28.8597562316691&#xD;&#xA;    28.8597958932898&#xD;&#xA;    28.8598343768895&#xD;&#xA;    28.8598717286685&#xD;&#xA;    28.8599079925824&#xD;&#xA;    28.8599432104601&#xD;&#xA;    28.8599774221564&#xD;&#xA;    28.8600106656362&#xD;&#xA;    28.8600429770912&#xD;&#xA;    28.8600743910437&#xD;&#xA;    28.8601049404189&#xD;&#xA;    28.8601346566671&#xD;&#xA;    28.8601635697958&#xD;&#xA;    28.8601917084984&#xD;&#xA;    28.8602191001836&#xD;&#xA;    28.8602457710551&#xD;&#xA;    28.8602717461905&#xD;&#xA;    28.8602970495771&#xD;&#xA;    28.8603217041829&#xD;&#xA;    28.8603457319945&#xD;&#xA;    28.8603691540817&#xD;&#xA;    28.8603919906349&#xD;&#xA;    28.8604142610140&#xD;&#xA;    28.8604359837728&#xD;&#xA;    28.8604571767236&#xD;&#xA;    28.8604778569632&#xD;&#xA;    28.8604980408853&#xD;&#xA;    28.8605177442508&#xD;&#xA;    28.860536982199 &#xD;&#xA;    28.8605557692684&#xD;&#xA;    28.8605741194424&#xD;&#xA;    28.8605920461606&#xD;&#xA;    28.8606095623542&#xD;&#xA;    28.8606266804642&#xD;&#xA;    28.8606434124606&#xD;&#xA;    28.8606597698673&#xD;&#xA;    28.8606757637894&#xD;&#xA;    28.8606914049092&#xD;&#xA;    28.8607067035307&#xD;&#xA;    28.8607216695845&#xD;&#xA;    28.8607363126319&#xD;&#xA;    28.8607506419126&#xD;&#xA;    28.8607646663229&#xD;&#xA;    28.8607783944441&#xD;&#xA;    28.8607918345695&#xD;&#xA;    28.8608049947040&#xD;&#xA;    28.8608178825589&#xD;&#xA;    28.8608305056052&#xD;&#xA;    28.8608428710407&#xD;&#xA;    28.8608549858324&#xD;&#xA;    28.8608668567086&#xD;&#xA;    28.8608784901671&#xD;&#xA;    28.8608898925065&#xD;&#xA;    28.8609010698021&#xD;&#xA;    28.8609120279379&#xD;&#xA;    28.8609227726126&#xD;&#xA;    28.8609333093227&#xD;&#xA;    28.8609436434116&#xD;&#xA;    28.8609537800355&#xD;&#xA;    28.8609637242006&#xD;&#xA;    28.8609734807368&#xD;&#xA;    28.8609830543426&#xD;&#xA;    28.8609924495660&#xD;&#xA;    28.8610016707985&#xD;&#xA;    28.8610107223272&#xD;&#xA;    28.8610196082769&#xD;&#xA;    28.8610283326623&#xD;&#xA;    28.8610368993920&#xD;&#xA;    28.8610453122201&#xD;&#xA;    28.8610535748236&#xD;&#xA;    28.8610616907611&#xD;&#xA;    28.8610696634759&#xD;&#xA;    28.8610774963191&#xD;&#xA;    28.8610851925415&#xD;&#xA;    28.8610927553168&#xD;&#xA;    28.8611001876897&#xD;&#xA;    28.8611074926601&#xD;&#xA;    28.8611146731067&#xD;&#xA;    28.8611217318631&#xD;&#xA;    28.8611286716494&#xD;&#xA;    28.8611354951266&#xD;&#xA;    28.8611422048820&#xD;&#xA;    28.8611488034280&#xD;&#xA;    28.8611552932030&#xD;&#xA;    28.8611616766001&#xD;&#xA;    28.8611679559112&#xD;&#xA;    28.8611741333984&#xD;&#xA;    28.8611802112609&#xD;&#xA;    28.8611861916049&#xD;&#xA;    28.8611920765250&#xD;&#xA;    28.8611978680366&#xD;&#xA;    28.8612035681006&#xD;&#xA;    28.8612091786388&#xD;&#xA;    28.8612147015119&#xD;&#xA;    28.8612201385397&#xD;&#xA;    28.8612254914896&#xD;&#xA;    28.8612307620868&#xD;&#xA;    28.8612359520116&#xD;&#xA;    28.8612410629093&#xD;&#xA;    28.8612460963629&#xD;&#xA;    28.8612510539384&#xD;&#xA;    28.8612559371502&#xD;&#xA;&#xD;&#xA;The first data point is an outlier caused by the spiral almost &quot;lapping&quot; itself. As the spiral progresses, we can see the the distances get closer and closer to the same distance. &#xD;&#xA;&#xD;&#xA;This is because we are sampling the curve in increments that cause equal lengths along the curve, not equal lengths between consecutive points. As the spiral gets bigger and bigger, the distances will get closer and closer to each other. &#xD;&#xA;  [1]: https://i.stack.imgur.com/7r77U.png&#xD;&#xA;  [2]: https://jsfiddle.net/anonymousey22/3rxhya8g/1/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15758" PostHistoryTypeId="5" PostId="5737" RevisionGUID="966418d8-82ca-42df-b602-0794d765752b" CreationDate="2017-10-17T03:53:09.703" UserId="7431" Comment="deleted 2 characters in body" Text="Since a logarithmic spiral is defined by &#xD;&#xA;&#xD;&#xA;$r=e^{a\cdot\theta}$, &#xD;&#xA;&#xD;&#xA;the inverse of the equation is this:&#xD;&#xA;&#xD;&#xA;$\theta=\frac{\ln{r}}{a}$.&#xD;&#xA;&#xD;&#xA;Therefore, if we take the natural log of our theta then divide it by $a$ before plugging it in to the equation, we will get equally stepped vertices on the logarithmic spiral. Image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generated this with some JavaScript code, which you can find in this [JSFiddle][2].)&#xD;&#xA;&#xD;&#xA;This looks good initially, but let's analyze what's going on here a little deeper. &#xD;&#xA;&#xD;&#xA;Here is a list of the distance between each consecutive pair of points, starting at the origin and spiraling outward:&#xD;&#xA;&#xD;&#xA;    20.6834877876017&#xD;&#xA;    25.8265879847751&#xD;&#xA;    27.3020264943519&#xD;&#xA;    27.9155365639631&#xD;&#xA;    28.2274404549991&#xD;&#xA;    28.4072329605331&#xD;&#xA;    28.5201842104742&#xD;&#xA;    28.5957343926866&#xD;&#xA;    28.6487385499231&#xD;&#xA;    28.6873487186944&#xD;&#xA;    28.7163404861061&#xD;&#xA;    28.7386617798632&#xD;&#xA;    28.7562121095165&#xD;&#xA;    28.7702600892245&#xD;&#xA;    28.7816791255158&#xD;&#xA;    28.7910864406300&#xD;&#xA;    28.7989282185451&#xD;&#xA;    28.8055334775293&#xD;&#xA;    28.8111491387549&#xD;&#xA;    28.8159634339811&#xD;&#xA;    28.8201218817722&#xD;&#xA;    28.8237384111142&#xD;&#xA;    28.8269032465565&#xD;&#xA;    28.8296885891879&#xD;&#xA;    28.8321527704665&#xD;&#xA;    28.8343433306399&#xD;&#xA;    28.8362993285731&#xD;&#xA;    28.8380530946981&#xD;&#xA;    28.8396315754034&#xD;&#xA;    28.8410573741728&#xD;&#xA;    28.8423495651939&#xD;&#xA;    28.8435243345428&#xD;&#xA;    28.8445954894748&#xD;&#xA;    28.8455748659368&#xD;&#xA;    28.8464726569062&#xD;&#xA;    28.8472976786488&#xD;&#xA;    28.8480575879711&#xD;&#xA;    28.8487590604974&#xD;&#xA;    28.8494079377702&#xD;&#xA;    28.8500093492502&#xD;&#xA;    28.8505678139929&#xD;&#xA;    28.8510873257846&#xD;&#xA;    28.8515714247378&#xD;&#xA;    28.8520232577561&#xD;&#xA;    28.8524456298024&#xD;&#xA;    28.8528410475339&#xD;&#xA;    28.8532117565801&#xD;&#xA;    28.8535597734869&#xD;&#xA;    28.8538869132081&#xD;&#xA;    28.8541948128041&#xD;&#xA;    28.8544849519687&#xD;&#xA;    28.8547586708355&#xD;&#xA;    28.8550171854833&#xD;&#xA;    28.8552616014621&#xD;&#xA;    28.8554929256347&#xD;&#xA;    28.8557120765606&#xD;&#xA;    28.8559198936319&#xD;&#xA;    28.8561171451194&#xD;&#xA;    28.8563045352784&#xD;&#xA;    28.8564827106597&#xD;&#xA;    28.8566522656712&#xD;&#xA;    28.8568137475608&#xD;&#xA;    28.8569676608282&#xD;&#xA;    28.8571144711722&#xD;&#xA;    28.8572546090145&#xD;&#xA;    28.8573884726640&#xD;&#xA;    28.8575164311457&#xD;&#xA;    28.8576388267439&#xD;&#xA;    28.8577559773038&#xD;&#xA;    28.8578681782850&#xD;&#xA;    28.8579757046362&#xD;&#xA;    28.8580788124715&#xD;&#xA;    28.8581777406078&#xD;&#xA;    28.8582727119331&#xD;&#xA;    28.8583639346897&#xD;&#xA;    28.8584516035825&#xD;&#xA;    28.8585359008445&#xD;&#xA;    28.8586169971792&#xD;&#xA;    28.8586950526148&#xD;&#xA;    28.8587702173116&#xD;&#xA;    28.8588426322609&#xD;&#xA;    28.8589124299770&#xD;&#xA;    28.8589797350751&#xD;&#xA;    28.8590446648521&#xD;&#xA;    28.8591073297703&#xD;&#xA;    28.8591678339633&#xD;&#xA;    28.8592262756316&#xD;&#xA;    28.8592827474659&#xD;&#xA;    28.8593373370150&#xD;&#xA;    28.8593901270040&#xD;&#xA;    28.8594411956751&#xD;&#xA;    28.8594906170532&#xD;&#xA;    28.8595384612331&#xD;&#xA;    28.8595847946223&#xD;&#xA;    28.8596296801627&#xD;&#xA;    28.8596731775581&#xD;&#xA;    28.8597153434631&#xD;&#xA;    28.8597562316691&#xD;&#xA;    28.8597958932898&#xD;&#xA;    28.8598343768895&#xD;&#xA;    28.8598717286685&#xD;&#xA;    28.8599079925824&#xD;&#xA;    28.8599432104601&#xD;&#xA;    28.8599774221564&#xD;&#xA;    28.8600106656362&#xD;&#xA;    28.8600429770912&#xD;&#xA;    28.8600743910437&#xD;&#xA;    28.8601049404189&#xD;&#xA;    28.8601346566671&#xD;&#xA;    28.8601635697958&#xD;&#xA;    28.8601917084984&#xD;&#xA;    28.8602191001836&#xD;&#xA;    28.8602457710551&#xD;&#xA;    28.8602717461905&#xD;&#xA;    28.8602970495771&#xD;&#xA;    28.8603217041829&#xD;&#xA;    28.8603457319945&#xD;&#xA;    28.8603691540817&#xD;&#xA;    28.8603919906349&#xD;&#xA;    28.8604142610140&#xD;&#xA;    28.8604359837728&#xD;&#xA;    28.8604571767236&#xD;&#xA;    28.8604778569632&#xD;&#xA;    28.8604980408853&#xD;&#xA;    28.8605177442508&#xD;&#xA;    28.860536982199 &#xD;&#xA;    28.8605557692684&#xD;&#xA;    28.8605741194424&#xD;&#xA;    28.8605920461606&#xD;&#xA;    28.8606095623542&#xD;&#xA;    28.8606266804642&#xD;&#xA;    28.8606434124606&#xD;&#xA;    28.8606597698673&#xD;&#xA;    28.8606757637894&#xD;&#xA;    28.8606914049092&#xD;&#xA;    28.8607067035307&#xD;&#xA;    28.8607216695845&#xD;&#xA;    28.8607363126319&#xD;&#xA;    28.8607506419126&#xD;&#xA;    28.8607646663229&#xD;&#xA;    28.8607783944441&#xD;&#xA;    28.8607918345695&#xD;&#xA;    28.8608049947040&#xD;&#xA;    28.8608178825589&#xD;&#xA;    28.8608305056052&#xD;&#xA;    28.8608428710407&#xD;&#xA;    28.8608549858324&#xD;&#xA;    28.8608668567086&#xD;&#xA;    28.8608784901671&#xD;&#xA;    28.8608898925065&#xD;&#xA;    28.8609010698021&#xD;&#xA;    28.8609120279379&#xD;&#xA;    28.8609227726126&#xD;&#xA;    28.8609333093227&#xD;&#xA;    28.8609436434116&#xD;&#xA;    28.8609537800355&#xD;&#xA;    28.8609637242006&#xD;&#xA;    28.8609734807368&#xD;&#xA;    28.8609830543426&#xD;&#xA;    28.8609924495660&#xD;&#xA;    28.8610016707985&#xD;&#xA;    28.8610107223272&#xD;&#xA;    28.8610196082769&#xD;&#xA;    28.8610283326623&#xD;&#xA;    28.8610368993920&#xD;&#xA;    28.8610453122201&#xD;&#xA;    28.8610535748236&#xD;&#xA;    28.8610616907611&#xD;&#xA;    28.8610696634759&#xD;&#xA;    28.8610774963191&#xD;&#xA;    28.8610851925415&#xD;&#xA;    28.8610927553168&#xD;&#xA;    28.8611001876897&#xD;&#xA;    28.8611074926601&#xD;&#xA;    28.8611146731067&#xD;&#xA;    28.8611217318631&#xD;&#xA;    28.8611286716494&#xD;&#xA;    28.8611354951266&#xD;&#xA;    28.8611422048820&#xD;&#xA;    28.8611488034280&#xD;&#xA;    28.8611552932030&#xD;&#xA;    28.8611616766001&#xD;&#xA;    28.8611679559112&#xD;&#xA;    28.8611741333984&#xD;&#xA;    28.8611802112609&#xD;&#xA;    28.8611861916049&#xD;&#xA;    28.8611920765250&#xD;&#xA;    28.8611978680366&#xD;&#xA;    28.8612035681006&#xD;&#xA;    28.8612091786388&#xD;&#xA;    28.8612147015119&#xD;&#xA;    28.8612201385397&#xD;&#xA;    28.8612254914896&#xD;&#xA;    28.8612307620868&#xD;&#xA;    28.8612359520116&#xD;&#xA;    28.8612410629093&#xD;&#xA;    28.8612460963629&#xD;&#xA;    28.8612510539384&#xD;&#xA;    28.8612559371502&#xD;&#xA;&#xD;&#xA;The first data point is an outlier caused by the spiral almost &quot;lapping&quot; itself. As the spiral progresses, we can see the the distances get closer and closer to the same distance. &#xD;&#xA;&#xD;&#xA;This is because we are sampling the curve in increments that cause equal lengths along the curve, not equal lengths between consecutive points. As the spiral gets bigger and bigger, the distances will get closer and closer to each other. &#xD;&#xA;  [1]: https://i.stack.imgur.com/7r77U.png&#xD;&#xA;  [2]: https://jsfiddle.net/anonymousey22/3rxhya8g/" ContentLicense="CC BY-SA 3.0" />
  <row Id="15759" PostHistoryTypeId="5" PostId="5737" RevisionGUID="18ada932-779b-4884-aa36-7e2c162116e2" CreationDate="2017-10-17T04:44:01.527" UserId="7431" Comment="added 121 characters in body" Text="Since a logarithmic spiral is defined by &#xD;&#xA;&#xD;&#xA;$r=e^{a\cdot\theta}$, &#xD;&#xA;&#xD;&#xA;the inverse of the equation is this:&#xD;&#xA;&#xD;&#xA;$\theta=\frac{\ln{r}}{a}$.&#xD;&#xA;&#xD;&#xA;Therefore, if we take the natural log of our theta then divide it by $a$ before plugging it in to the equation, we will get equally stepped vertices on the logarithmic spiral. Image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generated this with some JavaScript code, which you can find in this [JSFiddle][2].)&#xD;&#xA;&#xD;&#xA;You can also try it out interactively on [Desmos][3].&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;This looks good initially, but let's analyze what's going on here a little deeper. &#xD;&#xA;&#xD;&#xA;Here is a list of the distance between each consecutive pair of points, starting at the origin and spiraling outward:&#xD;&#xA;&#xD;&#xA;    20.6834877876017&#xD;&#xA;    25.8265879847751&#xD;&#xA;    27.3020264943519&#xD;&#xA;    27.9155365639631&#xD;&#xA;    28.2274404549991&#xD;&#xA;    28.4072329605331&#xD;&#xA;    28.5201842104742&#xD;&#xA;    28.5957343926866&#xD;&#xA;    28.6487385499231&#xD;&#xA;    28.6873487186944&#xD;&#xA;    28.7163404861061&#xD;&#xA;    28.7386617798632&#xD;&#xA;    28.7562121095165&#xD;&#xA;    28.7702600892245&#xD;&#xA;    28.7816791255158&#xD;&#xA;    28.7910864406300&#xD;&#xA;    28.7989282185451&#xD;&#xA;    28.8055334775293&#xD;&#xA;    28.8111491387549&#xD;&#xA;    28.8159634339811&#xD;&#xA;    28.8201218817722&#xD;&#xA;    28.8237384111142&#xD;&#xA;    28.8269032465565&#xD;&#xA;    28.8296885891879&#xD;&#xA;    28.8321527704665&#xD;&#xA;    28.8343433306399&#xD;&#xA;    28.8362993285731&#xD;&#xA;    28.8380530946981&#xD;&#xA;    28.8396315754034&#xD;&#xA;    28.8410573741728&#xD;&#xA;    28.8423495651939&#xD;&#xA;    28.8435243345428&#xD;&#xA;    28.8445954894748&#xD;&#xA;    28.8455748659368&#xD;&#xA;    28.8464726569062&#xD;&#xA;    28.8472976786488&#xD;&#xA;    28.8480575879711&#xD;&#xA;    28.8487590604974&#xD;&#xA;    28.8494079377702&#xD;&#xA;    28.8500093492502&#xD;&#xA;    28.8505678139929&#xD;&#xA;    28.8510873257846&#xD;&#xA;    28.8515714247378&#xD;&#xA;    28.8520232577561&#xD;&#xA;    28.8524456298024&#xD;&#xA;    28.8528410475339&#xD;&#xA;    28.8532117565801&#xD;&#xA;    28.8535597734869&#xD;&#xA;    28.8538869132081&#xD;&#xA;    28.8541948128041&#xD;&#xA;    28.8544849519687&#xD;&#xA;    28.8547586708355&#xD;&#xA;    28.8550171854833&#xD;&#xA;    28.8552616014621&#xD;&#xA;    28.8554929256347&#xD;&#xA;    28.8557120765606&#xD;&#xA;    28.8559198936319&#xD;&#xA;    28.8561171451194&#xD;&#xA;    28.8563045352784&#xD;&#xA;    28.8564827106597&#xD;&#xA;    28.8566522656712&#xD;&#xA;    28.8568137475608&#xD;&#xA;    28.8569676608282&#xD;&#xA;    28.8571144711722&#xD;&#xA;    28.8572546090145&#xD;&#xA;    28.8573884726640&#xD;&#xA;    28.8575164311457&#xD;&#xA;    28.8576388267439&#xD;&#xA;    28.8577559773038&#xD;&#xA;    28.8578681782850&#xD;&#xA;    28.8579757046362&#xD;&#xA;    28.8580788124715&#xD;&#xA;    28.8581777406078&#xD;&#xA;    28.8582727119331&#xD;&#xA;    28.8583639346897&#xD;&#xA;    28.8584516035825&#xD;&#xA;    28.8585359008445&#xD;&#xA;    28.8586169971792&#xD;&#xA;    28.8586950526148&#xD;&#xA;    28.8587702173116&#xD;&#xA;    28.8588426322609&#xD;&#xA;    28.8589124299770&#xD;&#xA;    28.8589797350751&#xD;&#xA;    28.8590446648521&#xD;&#xA;    28.8591073297703&#xD;&#xA;    28.8591678339633&#xD;&#xA;    28.8592262756316&#xD;&#xA;    28.8592827474659&#xD;&#xA;    28.8593373370150&#xD;&#xA;    28.8593901270040&#xD;&#xA;    28.8594411956751&#xD;&#xA;    28.8594906170532&#xD;&#xA;    28.8595384612331&#xD;&#xA;    28.8595847946223&#xD;&#xA;    28.8596296801627&#xD;&#xA;    28.8596731775581&#xD;&#xA;    28.8597153434631&#xD;&#xA;    28.8597562316691&#xD;&#xA;    28.8597958932898&#xD;&#xA;    28.8598343768895&#xD;&#xA;    28.8598717286685&#xD;&#xA;    28.8599079925824&#xD;&#xA;    28.8599432104601&#xD;&#xA;    28.8599774221564&#xD;&#xA;    28.8600106656362&#xD;&#xA;    28.8600429770912&#xD;&#xA;    28.8600743910437&#xD;&#xA;    28.8601049404189&#xD;&#xA;    28.8601346566671&#xD;&#xA;    28.8601635697958&#xD;&#xA;    28.8601917084984&#xD;&#xA;    28.8602191001836&#xD;&#xA;    28.8602457710551&#xD;&#xA;    28.8602717461905&#xD;&#xA;    28.8602970495771&#xD;&#xA;    28.8603217041829&#xD;&#xA;    28.8603457319945&#xD;&#xA;    28.8603691540817&#xD;&#xA;    28.8603919906349&#xD;&#xA;    28.8604142610140&#xD;&#xA;    28.8604359837728&#xD;&#xA;    28.8604571767236&#xD;&#xA;    28.8604778569632&#xD;&#xA;    28.8604980408853&#xD;&#xA;    28.8605177442508&#xD;&#xA;    28.860536982199 &#xD;&#xA;    28.8605557692684&#xD;&#xA;    28.8605741194424&#xD;&#xA;    28.8605920461606&#xD;&#xA;    28.8606095623542&#xD;&#xA;    28.8606266804642&#xD;&#xA;    28.8606434124606&#xD;&#xA;    28.8606597698673&#xD;&#xA;    28.8606757637894&#xD;&#xA;    28.8606914049092&#xD;&#xA;    28.8607067035307&#xD;&#xA;    28.8607216695845&#xD;&#xA;    28.8607363126319&#xD;&#xA;    28.8607506419126&#xD;&#xA;    28.8607646663229&#xD;&#xA;    28.8607783944441&#xD;&#xA;    28.8607918345695&#xD;&#xA;    28.8608049947040&#xD;&#xA;    28.8608178825589&#xD;&#xA;    28.8608305056052&#xD;&#xA;    28.8608428710407&#xD;&#xA;    28.8608549858324&#xD;&#xA;    28.8608668567086&#xD;&#xA;    28.8608784901671&#xD;&#xA;    28.8608898925065&#xD;&#xA;    28.8609010698021&#xD;&#xA;    28.8609120279379&#xD;&#xA;    28.8609227726126&#xD;&#xA;    28.8609333093227&#xD;&#xA;    28.8609436434116&#xD;&#xA;    28.8609537800355&#xD;&#xA;    28.8609637242006&#xD;&#xA;    28.8609734807368&#xD;&#xA;    28.8609830543426&#xD;&#xA;    28.8609924495660&#xD;&#xA;    28.8610016707985&#xD;&#xA;    28.8610107223272&#xD;&#xA;    28.8610196082769&#xD;&#xA;    28.8610283326623&#xD;&#xA;    28.8610368993920&#xD;&#xA;    28.8610453122201&#xD;&#xA;    28.8610535748236&#xD;&#xA;    28.8610616907611&#xD;&#xA;    28.8610696634759&#xD;&#xA;    28.8610774963191&#xD;&#xA;    28.8610851925415&#xD;&#xA;    28.8610927553168&#xD;&#xA;    28.8611001876897&#xD;&#xA;    28.8611074926601&#xD;&#xA;    28.8611146731067&#xD;&#xA;    28.8611217318631&#xD;&#xA;    28.8611286716494&#xD;&#xA;    28.8611354951266&#xD;&#xA;    28.8611422048820&#xD;&#xA;    28.8611488034280&#xD;&#xA;    28.8611552932030&#xD;&#xA;    28.8611616766001&#xD;&#xA;    28.8611679559112&#xD;&#xA;    28.8611741333984&#xD;&#xA;    28.8611802112609&#xD;&#xA;    28.8611861916049&#xD;&#xA;    28.8611920765250&#xD;&#xA;    28.8611978680366&#xD;&#xA;    28.8612035681006&#xD;&#xA;    28.8612091786388&#xD;&#xA;    28.8612147015119&#xD;&#xA;    28.8612201385397&#xD;&#xA;    28.8612254914896&#xD;&#xA;    28.8612307620868&#xD;&#xA;    28.8612359520116&#xD;&#xA;    28.8612410629093&#xD;&#xA;    28.8612460963629&#xD;&#xA;    28.8612510539384&#xD;&#xA;    28.8612559371502&#xD;&#xA;&#xD;&#xA;The first data point is an outlier caused by the spiral almost &quot;lapping&quot; itself. As the spiral progresses, we can see the the distances get closer and closer to the same distance. &#xD;&#xA;&#xD;&#xA;This is because we are sampling the curve in increments that cause equal lengths along the curve, not equal lengths between consecutive points. As the spiral gets bigger and bigger, the distances will get closer and closer to each other. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7r77U.png&#xD;&#xA;  [2]: https://jsfiddle.net/anonymousey22/3rxhya8g/&#xD;&#xA;  [3]: https://www.desmos.com/calculator/vhkjktryk6" ContentLicense="CC BY-SA 3.0" />
  <row Id="15760" PostHistoryTypeId="2" PostId="5738" RevisionGUID="f8dfc241-4b89-4f0d-ab80-152064af10dd" CreationDate="2017-10-17T09:02:32.130" UserId="3274" Text="Can you explain me what a nonrigid motion is?&#xD;&#xA;In German it would be a &quot;unbewegliche Bewegung&quot; but I think it has to be translated in a different way.&#xD;&#xA;I could imagine that it means something like the scene window is moving but the elements in the scene are staying in the same position." ContentLicense="CC BY-SA 3.0" />
  <row Id="15761" PostHistoryTypeId="1" PostId="5738" RevisionGUID="f8dfc241-4b89-4f0d-ab80-152064af10dd" CreationDate="2017-10-17T09:02:32.130" UserId="3274" Text="What is a nonrigid motion?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15762" PostHistoryTypeId="3" PostId="5738" RevisionGUID="f8dfc241-4b89-4f0d-ab80-152064af10dd" CreationDate="2017-10-17T09:02:32.130" UserId="3274" Text="|motion|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15763" PostHistoryTypeId="5" PostId="5738" RevisionGUID="25e2f844-194a-4873-b7ba-96896180d0ac" CreationDate="2017-10-17T09:41:48.633" UserId="3274" Comment="added 82 characters in body" Text="Can you explain me what a nonrigid motion is?&#xD;&#xA;In German it would be a &quot;unbewegliche Bewegung&quot; but I think it has to be translated in a different way.&#xD;&#xA;I could imagine that it means something like the scene window is moving but the elements in the scene are staying in the same position.&#xD;&#xA;&#xD;&#xA;I read it in the context of a paper about qunatitative optic flow comparison. " ContentLicense="CC BY-SA 3.0" />
  <row Id="15764" PostHistoryTypeId="5" PostId="5738" RevisionGUID="a413e0c1-fd77-431f-9ed4-190056347eed" CreationDate="2017-10-17T11:38:47.797" UserId="3274" Comment="edited body" Text="Can you explain me what a nonrigid motion is?&#xD;&#xA;In German it would be a &quot;unbewegliche Bewegung&quot; but I think it has to be translated in a different way.&#xD;&#xA;I could imagine that it means something like the scene window is moving but the elements in the scene are staying in the same position.&#xD;&#xA;&#xD;&#xA;I read it in the context of a paper about quantitative optic flow comparison. " ContentLicense="CC BY-SA 3.0" />
  <row Id="15765" PostHistoryTypeId="5" PostId="5736" RevisionGUID="9b9c0668-da08-4a9d-be5d-6fdccf4e1efa" CreationDate="2017-10-17T14:27:56.653" UserId="56" Comment="added 197 characters in body" Text="I think the best way to tackle this problem would be to make an algorithm that works on a single triangle at a time.&#xD;&#xA;&#xD;&#xA;You'd look at each terrain triangle individually that the road intersected and process it.&#xD;&#xA;&#xD;&#xA;Looking at one triangle individually, you would have to chop that triangle into one or more meshes to make it contour to the road.&#xD;&#xA;&#xD;&#xA;Here are some edge cases.  I'm betting there is some triangle slicing algorithm that would be suited to this, and I'm not sure of a name off hand, but the main contribution I'm proposing here is that you deal with triangles individually.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When cutting the triangle on the x/y plane to make a hole for for the road, you would also want the terrain to take on the z value (height) of the road, for those vertices that touch the road.  This will make the terrain rise up to meet the road.&#xD;&#xA;&#xD;&#xA;At this point, you'd have a terrain mesh which did conform to the road but it would be ugly.&#xD;&#xA;&#xD;&#xA;Instead of having a nice even looking hill that went up to the road at reasonable slopes, you'd have some triangles that went very sharply up to the road, and others that had a very flat slope.&#xD;&#xA;&#xD;&#xA;What you would need to do now is do some kind of &quot;relaxation&quot; algorithm to address this.&#xD;&#xA;&#xD;&#xA;Basically, if something is too steep, because there wasn't enough triangle to make the height adjustment, you need to make your whole triangle closer in height to the road and bleed off some of the height adjustment to neighboring triangles.&#xD;&#xA;&#xD;&#xA;If something was not steep enough for your liking, because there was a lot of triangle to make a small height adjustment, you may want to break the triangle up into more polygons where it gets closer to the road and have that smaller area handle the change in elevation.&#xA;&#xA;During this second step, when you added a vertex to an edge between two triangles you would also need to adjust the triangle that shares the edge to prevent cracks from showing up in the terrain.&#xD;&#xA;&#xD;&#xA;The details are a bit vague, but hopefully the two step approach will help you tackle the problem.&#xD;&#xA;&#xD;&#xA; 1. Make the terrain mesh adapt to the road, without caring about how it looks.&#xD;&#xA; 2. Refine the terrain mesh to make it appear to meet the road in a more organic man made way.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qZVx4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15766" PostHistoryTypeId="2" PostId="5739" RevisionGUID="fcd6bd94-bfed-4cf8-aa8e-e6dccd142e6c" CreationDate="2017-10-17T16:34:12.210" UserId="3003" Text="Generally a non-rigid transformation is motion that doesn't preserve the shape of objects. If you look at a typical transformation matrix, rigid transformations would include translation, rotation, and reflection. Things like shear, uniform or non-uniform scale, and perspective would be non-rigid. Shear and scale would fall into the category of affine transformations, and perspective is of course perspective transformation. So there's a hierarchy of types of transformations:&#xD;&#xA;&#xD;&#xA; 1. [Rigid transforms](https://en.wikipedia.org/wiki/Rigid_transformation) - translation, reflection, and rotation. These perserve the distances between every pair of points on objects.&#xD;&#xA; 2. [Affine transforms](https://en.wikipedia.org/wiki/Affine_transformation) - rigid + shear and (possibly non-uniform) scale&#xD;&#xA; 3. [Perspective transforms](https://en.wikipedia.org/wiki/3D_projection) - Affine plus perspective transforms (think of a rectangle rotated around the upward pointing axis - the part closer to the camera/viewer may be larger than the pre-transformed object, and the part farther away may be smaller)&#xD;&#xA;&#xD;&#xA;I haven't done a lot with optical flow, but I would guess that as you figure out the path of motion of various points on an object, you would be able to classify them into one of the above categories. If all the points in an object move in tandem, then you probably have rotation and/or translation only (rigid transforms), but if they don't then you may have an affine or perspective transform between the points." ContentLicense="CC BY-SA 3.0" />
  <row Id="15767" PostHistoryTypeId="2" PostId="5740" RevisionGUID="d0b8d697-f1a4-4c40-bf31-b9e1f59ebf78" CreationDate="2017-10-17T18:32:27.180" UserId="7492" Text="I'm trying to follow along with a tutorial that uses an OpenGL compute shader, but I'm using D3D11. What they do is:&#xD;&#xA;&#xD;&#xA;    layout (std430, binding = 0) buffer indices {&#xD;&#xA;        int j[];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I have no experience with this and very little with directX, but that looks like a buffer of integer arrays. I've looked around and read that the equivalent to this OpenGL buffer in D3D11 is an RWBuffer. Using a compute shader, this is what I've tried. Note, I didn't redefine them in my code as they appear here, I just listed them together here.&#xD;&#xA;&#xD;&#xA;    RWBuffer indices&#xD;&#xA;    {&#xD;&#xA;    	int j[];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    RWBuffer&lt;{int j[];}&gt; indices;&#xD;&#xA;&#xD;&#xA;    struct index&#xD;&#xA;    {&#xD;&#xA;    	//requires explicit length, which is why this doesn't work&#xD;&#xA;    	int j[];&#xD;&#xA;    }&#xD;&#xA;    RWStructuredBuffer&lt;index&gt; indices;&#xD;&#xA;&#xD;&#xA;But, none of those worked. The end goal is to access them like so:&#xD;&#xA;&#xD;&#xA;    //id is SV_DispatchThreadID&#xD;&#xA;    indices.j[int(id.y)]&#xD;&#xA;&#xD;&#xA;This seems like an inappropriately simple question to post, but I wasn't able to find documentation, even on MSDN, on defining buffers and what's allowed and not, etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="15768" PostHistoryTypeId="1" PostId="5740" RevisionGUID="d0b8d697-f1a4-4c40-bf31-b9e1f59ebf78" CreationDate="2017-10-17T18:32:27.180" UserId="7492" Text="Buffer of arrays in HLSL compute shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="15769" PostHistoryTypeId="3" PostId="5740" RevisionGUID="d0b8d697-f1a4-4c40-bf31-b9e1f59ebf78" CreationDate="2017-10-17T18:32:27.180" UserId="7492" Text="|directx11|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15770" PostHistoryTypeId="2" PostId="5741" RevisionGUID="fe212ce5-aa4f-4b57-96c6-7dbecf4ad029" CreationDate="2017-10-17T19:01:59.660" UserId="48" Text="It looks to me like you want a buffer containing a single array of integers (not a buffer containing multiple arrays, whatever that would mean). So, you should be able to just do this:&#xD;&#xA;&#xD;&#xA;    RWBuffer&lt;int&gt; indices;&#xD;&#xA;&#xD;&#xA;then access it like this:&#xD;&#xA;&#xD;&#xA;    indices[int(id.y)]" ContentLicense="CC BY-SA 3.0" />
  <row Id="15771" PostHistoryTypeId="5" PostId="5737" RevisionGUID="d3e15453-385c-4a47-9c05-0b4b70cc115f" CreationDate="2017-10-18T00:09:29.823" UserId="7431" Comment="added scalar explanation; added 28 characters in body" Text="Since a logarithmic spiral is defined by &#xD;&#xA;&#xD;&#xA;$r=e^{a\cdot\theta}$, &#xD;&#xA;&#xD;&#xA;the inverse of the equation is this:&#xD;&#xA;&#xD;&#xA;$\theta=\frac{\ln{r}}{a}$.&#xD;&#xA;&#xD;&#xA;If we want to be able to control our step value, we can multiply it by a scalar ($a\cdot k$) before taking the logarithm, like so:&#xD;&#xA;&#xD;&#xA;$\theta=\frac{\ln (ak\cdot r)}{a}$&#xD;&#xA;&#xD;&#xA;Therefore, if we take the natural log of theta multiplied by the scalar and $a$, then divide the whole thing by $a$ before plugging it in to the equation, we will get equally stepped vertices on the logarithmic spiral. Image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generated this with some JavaScript code, which you can find in this [JSFiddle][2].&#xD;&#xA;&#xD;&#xA;You can also try it out interactively on [Desmos][3].&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;This looks good initially, but let's analyze what's going on here a little deeper. &#xD;&#xA;&#xD;&#xA;Here is a list of the distance between each consecutive pair of points, starting at the origin and spiraling outward:&#xD;&#xA;&#xD;&#xA;    20.6834877876017&#xD;&#xA;    25.8265879847751&#xD;&#xA;    27.3020264943519&#xD;&#xA;    27.9155365639631&#xD;&#xA;    28.2274404549991&#xD;&#xA;    28.4072329605331&#xD;&#xA;    28.5201842104742&#xD;&#xA;    28.5957343926866&#xD;&#xA;    28.6487385499231&#xD;&#xA;    28.6873487186944&#xD;&#xA;    28.7163404861061&#xD;&#xA;    28.7386617798632&#xD;&#xA;    28.7562121095165&#xD;&#xA;    28.7702600892245&#xD;&#xA;    28.7816791255158&#xD;&#xA;    28.7910864406300&#xD;&#xA;    28.7989282185451&#xD;&#xA;    28.8055334775293&#xD;&#xA;    28.8111491387549&#xD;&#xA;    28.8159634339811&#xD;&#xA;    28.8201218817722&#xD;&#xA;    28.8237384111142&#xD;&#xA;    28.8269032465565&#xD;&#xA;    28.8296885891879&#xD;&#xA;    28.8321527704665&#xD;&#xA;    28.8343433306399&#xD;&#xA;    28.8362993285731&#xD;&#xA;    28.8380530946981&#xD;&#xA;    28.8396315754034&#xD;&#xA;    28.8410573741728&#xD;&#xA;    28.8423495651939&#xD;&#xA;    28.8435243345428&#xD;&#xA;    28.8445954894748&#xD;&#xA;    28.8455748659368&#xD;&#xA;    28.8464726569062&#xD;&#xA;    28.8472976786488&#xD;&#xA;    28.8480575879711&#xD;&#xA;    28.8487590604974&#xD;&#xA;    28.8494079377702&#xD;&#xA;    28.8500093492502&#xD;&#xA;    28.8505678139929&#xD;&#xA;    28.8510873257846&#xD;&#xA;    28.8515714247378&#xD;&#xA;    28.8520232577561&#xD;&#xA;    28.8524456298024&#xD;&#xA;    28.8528410475339&#xD;&#xA;    28.8532117565801&#xD;&#xA;    28.8535597734869&#xD;&#xA;    28.8538869132081&#xD;&#xA;    28.8541948128041&#xD;&#xA;    28.8544849519687&#xD;&#xA;    28.8547586708355&#xD;&#xA;    28.8550171854833&#xD;&#xA;    28.8552616014621&#xD;&#xA;    28.8554929256347&#xD;&#xA;    28.8557120765606&#xD;&#xA;    28.8559198936319&#xD;&#xA;    28.8561171451194&#xD;&#xA;    28.8563045352784&#xD;&#xA;    28.8564827106597&#xD;&#xA;    28.8566522656712&#xD;&#xA;    28.8568137475608&#xD;&#xA;    28.8569676608282&#xD;&#xA;    28.8571144711722&#xD;&#xA;    28.8572546090145&#xD;&#xA;    28.8573884726640&#xD;&#xA;    28.8575164311457&#xD;&#xA;    28.8576388267439&#xD;&#xA;    28.8577559773038&#xD;&#xA;    28.8578681782850&#xD;&#xA;    28.8579757046362&#xD;&#xA;    28.8580788124715&#xD;&#xA;    28.8581777406078&#xD;&#xA;    28.8582727119331&#xD;&#xA;    28.8583639346897&#xD;&#xA;    28.8584516035825&#xD;&#xA;    28.8585359008445&#xD;&#xA;    28.8586169971792&#xD;&#xA;    28.8586950526148&#xD;&#xA;    28.8587702173116&#xD;&#xA;    28.8588426322609&#xD;&#xA;    28.8589124299770&#xD;&#xA;    28.8589797350751&#xD;&#xA;    28.8590446648521&#xD;&#xA;    28.8591073297703&#xD;&#xA;    28.8591678339633&#xD;&#xA;    28.8592262756316&#xD;&#xA;    28.8592827474659&#xD;&#xA;    28.8593373370150&#xD;&#xA;    28.8593901270040&#xD;&#xA;    28.8594411956751&#xD;&#xA;    28.8594906170532&#xD;&#xA;    28.8595384612331&#xD;&#xA;    28.8595847946223&#xD;&#xA;    28.8596296801627&#xD;&#xA;    28.8596731775581&#xD;&#xA;    28.8597153434631&#xD;&#xA;    28.8597562316691&#xD;&#xA;    28.8597958932898&#xD;&#xA;    28.8598343768895&#xD;&#xA;    28.8598717286685&#xD;&#xA;    28.8599079925824&#xD;&#xA;    28.8599432104601&#xD;&#xA;    28.8599774221564&#xD;&#xA;    28.8600106656362&#xD;&#xA;    28.8600429770912&#xD;&#xA;    28.8600743910437&#xD;&#xA;    28.8601049404189&#xD;&#xA;    28.8601346566671&#xD;&#xA;    28.8601635697958&#xD;&#xA;    28.8601917084984&#xD;&#xA;    28.8602191001836&#xD;&#xA;    28.8602457710551&#xD;&#xA;    28.8602717461905&#xD;&#xA;    28.8602970495771&#xD;&#xA;    28.8603217041829&#xD;&#xA;    28.8603457319945&#xD;&#xA;    28.8603691540817&#xD;&#xA;    28.8603919906349&#xD;&#xA;    28.8604142610140&#xD;&#xA;    28.8604359837728&#xD;&#xA;    28.8604571767236&#xD;&#xA;    28.8604778569632&#xD;&#xA;    28.8604980408853&#xD;&#xA;    28.8605177442508&#xD;&#xA;    28.860536982199 &#xD;&#xA;    28.8605557692684&#xD;&#xA;    28.8605741194424&#xD;&#xA;    28.8605920461606&#xD;&#xA;    28.8606095623542&#xD;&#xA;    28.8606266804642&#xD;&#xA;    28.8606434124606&#xD;&#xA;    28.8606597698673&#xD;&#xA;    28.8606757637894&#xD;&#xA;    28.8606914049092&#xD;&#xA;    28.8607067035307&#xD;&#xA;    28.8607216695845&#xD;&#xA;    28.8607363126319&#xD;&#xA;    28.8607506419126&#xD;&#xA;    28.8607646663229&#xD;&#xA;    28.8607783944441&#xD;&#xA;    28.8607918345695&#xD;&#xA;    28.8608049947040&#xD;&#xA;    28.8608178825589&#xD;&#xA;    28.8608305056052&#xD;&#xA;    28.8608428710407&#xD;&#xA;    28.8608549858324&#xD;&#xA;    28.8608668567086&#xD;&#xA;    28.8608784901671&#xD;&#xA;    28.8608898925065&#xD;&#xA;    28.8609010698021&#xD;&#xA;    28.8609120279379&#xD;&#xA;    28.8609227726126&#xD;&#xA;    28.8609333093227&#xD;&#xA;    28.8609436434116&#xD;&#xA;    28.8609537800355&#xD;&#xA;    28.8609637242006&#xD;&#xA;    28.8609734807368&#xD;&#xA;    28.8609830543426&#xD;&#xA;    28.8609924495660&#xD;&#xA;    28.8610016707985&#xD;&#xA;    28.8610107223272&#xD;&#xA;    28.8610196082769&#xD;&#xA;    28.8610283326623&#xD;&#xA;    28.8610368993920&#xD;&#xA;    28.8610453122201&#xD;&#xA;    28.8610535748236&#xD;&#xA;    28.8610616907611&#xD;&#xA;    28.8610696634759&#xD;&#xA;    28.8610774963191&#xD;&#xA;    28.8610851925415&#xD;&#xA;    28.8610927553168&#xD;&#xA;    28.8611001876897&#xD;&#xA;    28.8611074926601&#xD;&#xA;    28.8611146731067&#xD;&#xA;    28.8611217318631&#xD;&#xA;    28.8611286716494&#xD;&#xA;    28.8611354951266&#xD;&#xA;    28.8611422048820&#xD;&#xA;    28.8611488034280&#xD;&#xA;    28.8611552932030&#xD;&#xA;    28.8611616766001&#xD;&#xA;    28.8611679559112&#xD;&#xA;    28.8611741333984&#xD;&#xA;    28.8611802112609&#xD;&#xA;    28.8611861916049&#xD;&#xA;    28.8611920765250&#xD;&#xA;    28.8611978680366&#xD;&#xA;    28.8612035681006&#xD;&#xA;    28.8612091786388&#xD;&#xA;    28.8612147015119&#xD;&#xA;    28.8612201385397&#xD;&#xA;    28.8612254914896&#xD;&#xA;    28.8612307620868&#xD;&#xA;    28.8612359520116&#xD;&#xA;    28.8612410629093&#xD;&#xA;    28.8612460963629&#xD;&#xA;    28.8612510539384&#xD;&#xA;    28.8612559371502&#xD;&#xA;&#xD;&#xA;The first data point is an outlier caused by the spiral almost &quot;lapping&quot; itself. As the spiral progresses, we can see the the distances get closer and closer to the same distance. &#xD;&#xA;&#xD;&#xA;This is because we are sampling the curve in increments that cause equal lengths along the curve, not equal lengths between consecutive points. As the spiral gets bigger and bigger, the curve will get shallower and shallower, so the distances will get closer and closer to each other. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7r77U.png&#xD;&#xA;  [2]: https://jsfiddle.net/anonymousey22/3rxhya8g/6/&#xD;&#xA;  [3]: https://www.desmos.com/calculator/qaoovzi6pk" ContentLicense="CC BY-SA 3.0" />
  <row Id="15772" PostHistoryTypeId="2" PostId="5742" RevisionGUID="02cb870f-045b-4e41-8f41-42c0cfffb102" CreationDate="2017-10-18T00:27:37.427" UserId="7497" Text="I have discovered that there is two ways to update the view-port (Might be more, not sure). Currently I am rebuilding the Pipeline when I resize my screen but there is a noticeable stutter as it rebuilds, but i have also found out that you can use vkCmdSetViewport when building/rebuilding your command buffers. But is this the right way to do it? and if I was to use vkCmdSetViewport when what should be put into the VkGraphicsPipelineCreateInfo pViewportState?&#xD;&#xA;&#xD;&#xA;Also If there is a even better way of handling screen resizing please let me know." ContentLicense="CC BY-SA 3.0" />
  <row Id="15773" PostHistoryTypeId="1" PostId="5742" RevisionGUID="02cb870f-045b-4e41-8f41-42c0cfffb102" CreationDate="2017-10-18T00:27:37.427" UserId="7497" Text="Vulkan best way of updating pipeline viewport" ContentLicense="CC BY-SA 3.0" />
  <row Id="15774" PostHistoryTypeId="3" PostId="5742" RevisionGUID="02cb870f-045b-4e41-8f41-42c0cfffb102" CreationDate="2017-10-18T00:27:37.427" UserId="7497" Text="|c++|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15775" PostHistoryTypeId="2" PostId="5743" RevisionGUID="fec43ed0-2ba9-42de-a718-6493e9ed7044" CreationDate="2017-10-18T03:43:39.957" UserId="2707" Text="Both suggested methods are fine, but they should be preferred in certain situations.&#xD;&#xA;&#xD;&#xA;Dynamic state should be preferred in situations where you have many, perhaps thousands of, pipeline objects or you need to change the resolution often (such as in some sort of windowed tool. The downside to this is that it may reduce runtime performance since the driver may not be able apply optimizations for this.&#xD;&#xA;&#xD;&#xA;Having the viewport only defined when building the pipeline objects might be more appropriate for games or simulators where you don't change the resolution often. Of course, when the viewport does change, it hits performance hard during resizing. This also has the drawback of needing to generate new pipeline objects, which could be especially problematic if you cache pipelines in a hash table of something similar." ContentLicense="CC BY-SA 3.0" />
  <row Id="15779" PostHistoryTypeId="5" PostId="5736" RevisionGUID="82b204f9-78fd-41e5-ae01-f98c8d1ebde5" CreationDate="2017-10-18T16:36:39.667" UserId="56" Comment="added 35 characters in body" Text="I think the best way to tackle this problem would be to make an algorithm that works on a single triangle at a time.&#xD;&#xA;&#xD;&#xA;You'd look at each terrain triangle individually that the road intersected and process it.&#xD;&#xA;&#xD;&#xA;Looking at one triangle individually, you would have to chop that triangle into one or more meshes to make it contour to the road.&#xD;&#xA;&#xD;&#xA;Here are some of the cases to consider in the image below.  I'm betting there is some triangle slicing algorithm that would be suited to this, and I'm not sure of a name off hand, but the main contribution I'm proposing here is that you deal with triangles individually.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When cutting the triangle on the x/y plane to make a hole for for the road, you would also want the terrain to take on the z value (height) of the road, for those vertices that touch the road.  This will make the terrain rise up to meet the road.&#xD;&#xA;&#xD;&#xA;At this point, you'd have a terrain mesh which did conform to the road but it would be ugly.&#xD;&#xA;&#xD;&#xA;Instead of having a nice even looking hill that went up to the road at reasonable slopes, you'd have some triangles that went very sharply up to the road, and others that had a very flat slope.&#xD;&#xA;&#xD;&#xA;What you would need to do now is do some kind of &quot;relaxation&quot; algorithm to address this.&#xD;&#xA;&#xD;&#xA;Basically, if something is too steep, because there wasn't enough triangle to make the height adjustment, you need to make your whole triangle closer in height to the road and bleed off some of the height adjustment to neighboring triangles.&#xD;&#xA;&#xD;&#xA;If something was not steep enough for your liking, because there was a lot of triangle to make a small height adjustment, you may want to break the triangle up into more polygons where it gets closer to the road and have that smaller area handle the change in elevation.&#xD;&#xA;&#xD;&#xA;During this second step, when you added a vertex to an edge between two triangles you would also need to adjust the triangle that shares the edge to prevent cracks from showing up in the terrain.&#xD;&#xA;&#xD;&#xA;The details are a bit vague, but hopefully the two step approach will help you tackle the problem.&#xD;&#xA;&#xD;&#xA; 1. Make the terrain mesh adapt to the road, without caring about how it looks.&#xD;&#xA; 2. Refine the terrain mesh to make it appear to meet the road in a more organic man made way.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qZVx4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15780" PostHistoryTypeId="2" PostId="5745" RevisionGUID="c44d9a78-7b2b-48cc-8101-11a742a14ede" CreationDate="2017-10-18T17:17:33.690" UserId="7504" Text="Typically you would search for voxels with specific features, e.g. using thresholding and create your model as an isosurface made of the particles corresponding to those voxels..MRI images are dense 3 dimensional matrices, and without prior anatomical perprocessing or voxel selection you will endup with a dense cube.&#xD;&#xA;&#xD;&#xA;you can check ITK Snap, it is a free tool reading NII and DCM images and using different techniques it would build basic 3D models  " ContentLicense="CC BY-SA 3.0" />
  <row Id="15781" PostHistoryTypeId="2" PostId="5746" RevisionGUID="f02a258d-fdad-4220-a596-dcf5dda732e9" CreationDate="2017-10-18T17:42:55.073" UserId="2287" Text="**Perspective Camera**&#xD;&#xA;&#xD;&#xA;A (row-major) perspective transformation matrix has the following format:&#xD;&#xA;&#xD;&#xA;$$\begin{align} \mathrm{T} &#xD;&#xA;&amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;1 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;0 \end{bmatrix}=\begin{bmatrix} 1/x &amp;0 &amp;0 &amp;0 \\ 0 &amp;1/y &amp;0 &amp;0 \\ 0 &amp;0 &amp;-w &amp;0 \\ 0 &amp;0 &amp;z &amp;0\end{bmatrix}. &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;This transformation matrix is used to transform (*homogeneous*) points from view to projection space, after which the homogeneous divide is applied to transform to NDC (Normalized Device Coordinate) space. (*NDC space is technically a 3D space, but for ease of notation, I use 4D points with a $w=1$*).&#xD;&#xA;&#xD;&#xA;In a deferred renderer, we need to go the other way around while resolving the GBuffer and could use four components ($x$, $y$, $z$, $w$, see above) to transform a point from NDC to view space:&#xD;&#xA;&#xD;&#xA;       /**&#xD;&#xA;    	 Returns the projection values from the given projection matrix to construct &#xD;&#xA;    	 the view position coordinates from the NDC position coordinates.&#xD;&#xA;    	 &#xD;&#xA;         @return		The projection values from the given projection matrix to &#xD;&#xA;    					construct the view position coordinates from the NDC position &#xD;&#xA;    					coordinates.&#xD;&#xA;    	 */&#xD;&#xA;    	inline const XMVECTOR XM_CALLCONV GetViewPositionConstructionValues(&#xD;&#xA;    		FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;    		&#xD;&#xA;    		//        [ 1/X  0   0  0 ]&#xD;&#xA;    		// p_view [  0  1/Y  0  0 ] = [p_view.x 1/X, p_view.y 1/Y, p_view.z (-W) + Z, p_view.z] = p_proj&#xD;&#xA;    		//        [  0   0  -W  1 ]&#xD;&#xA;    		//        [  0   0   Z  0 ]&#xD;&#xA;    		//&#xD;&#xA;    		// p_proj / p_proj.w        = [p_view.x/p_view.z 1/X, p_view.y/p_view.z 1/Y, -W + Z/p_view.z, 1] = p_ndc&#xD;&#xA;    		//&#xD;&#xA;    		// Construction of p_view from p_ndc and projection values&#xD;&#xA;    		// 1) p_ndc.z = -W + Z/p_view.z       &lt;=&gt; p_view.z = Z / (p_ndc.z + W)&#xD;&#xA;    		// 2) p_ndc.x = p_view.x/p_view.z 1/X &lt;=&gt; p_view.x = X * p_ndc.x * p_view.z&#xD;&#xA;    		// 3) p_ndc.y = p_view.y/p_view.z 1/Y &lt;=&gt; p_view.y = Y * p_ndc.y * p_view.z&#xD;&#xA;    &#xD;&#xA;    		const F32 x = 1.0f / XMVectorGetX(projection_matrix.r[0]);&#xD;&#xA;    		const F32 y = 1.0f / XMVectorGetY(projection_matrix.r[1]);&#xD;&#xA;    		const F32 z =  XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;    		const F32 w = -XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;    		&#xD;&#xA;    		return XMVectorSet(x, y, z, w);&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;**Orthographic Camera**&#xD;&#xA;&#xD;&#xA;An (row-major) orthographic transformation matrix has the following format:&#xD;&#xA;&#xD;&#xA;$$\begin{align} \mathrm{T} &#xD;&#xA;&amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;1 \end{bmatrix}=\begin{bmatrix} 1/x &amp;0 &amp;0 &amp;0 \\ 0 &amp;1/y &amp;0 &amp;0 \\ 0 &amp;0 &amp;1/z &amp;0 \\ 0 &amp;0 &amp;-w &amp;0\end{bmatrix}. &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;This transformation matrix is used to transform (*homogeneous*) points from view to projection space, after which the homogeneous divide (no-op) is applied to transform to NDC (= projection) space. (*So basically a non-uniform scaling followed by a translation of the z component*).&#xD;&#xA;&#xD;&#xA;We could similarly use four components ($x$, $y$, $z$, $w$, see above) to transform a point from NDC (= projection) to view space:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;	 Returns the projection values from the given projection matrix to construct &#xD;&#xA;	 the view position coordinates from the NDC position coordinates.&#xD;&#xA;	 &#xD;&#xA;     @return		The projection values from the given projection matrix to &#xD;&#xA;					construct the view position coordinates from the NDC position &#xD;&#xA;					coordinates.&#xD;&#xA;	 */&#xD;&#xA;	inline const XMVECTOR XM_CALLCONV GetViewPositionConstructionValues(&#xD;&#xA;		FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;		&#xD;&#xA;		//        [ 1/X  0   0  0 ]&#xD;&#xA;		// p_view [  0  1/Y  0  0 ] = [p_view.x 1/X, p_view.y 1/Y, p_view.z 1/Z -W, 1] = p_proj = p_ndc&#xD;&#xA;		//        [  0   0  1/Z 1 ]&#xD;&#xA;		//        [  0   0  -W  0 ]&#xD;&#xA;		//&#xD;&#xA;		// Construction of p_view from p_ndc and projection values&#xD;&#xA;		// 1) p_ndc.z = p_view.z/Z -W &lt;=&gt; p_view.z = Z * (p_ndc.z + W)&#xD;&#xA;		// 2) p_ndc.x = p_view.x/X    &lt;=&gt; p_view.x = X * p_ndc.x&#xD;&#xA;		// 3) p_ndc.y = p_view.y/Y    &lt;=&gt; p_view.y = Y * p_ndc.y&#xD;&#xA;&#xD;&#xA;		const F32 x = 1.0f / XMVectorGetX(projection_matrix.r[0]);&#xD;&#xA;		const F32 y = 1.0f / XMVectorGetY(projection_matrix.r[1]);&#xD;&#xA;		const F32 z = 1.0f / XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;		const F32 w = -XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;		&#xD;&#xA;		return XMVectorSet(x, y, z, w);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;How can a deferred renderer support multiple camera types (minimally: perspective and orthographic cameras, ideally: all cameras that a forward renderer could support) without specializing the shaders or specializing in the shaders?&#xD;&#xA;&#xD;&#xA;A straightforward solution is to specify some pre-processor directive in the shader, but this unfortunately results in a multiple of all the shader perturbations used so far for lighting in a deferred pipeline. Another solution is to pass a flag in some constant buffer to specify the used camera type, though I am not a fan of the dynamic branching introduced by this flag. Furthermore, both solutions are not as flexible as is the case for forward rendering which can handle arbitrary view-to-projection matrices.&#xD;&#xA;&#xD;&#xA;Ideally, a (hypothetical) NDC-to-view transformation matrix should handle the transformation. Such a matrix does, however, not generally exist for perspective cameras since the view to NDC transformation reduces a 4D space to a 3D subspace." ContentLicense="CC BY-SA 3.0" />
  <row Id="15782" PostHistoryTypeId="1" PostId="5746" RevisionGUID="f02a258d-fdad-4220-a596-dcf5dda732e9" CreationDate="2017-10-18T17:42:55.073" UserId="2287" Text="Supporting multiple camera types in a deferred renderer without specializing the shaders or in the shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="15783" PostHistoryTypeId="3" PostId="5746" RevisionGUID="f02a258d-fdad-4220-a596-dcf5dda732e9" CreationDate="2017-10-18T17:42:55.073" UserId="2287" Text="|transformations|perspective|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15784" PostHistoryTypeId="2" PostId="5747" RevisionGUID="8c81bfd7-88df-47c2-99a4-2cac4e7e2cd0" CreationDate="2017-10-18T18:15:43.177" UserId="2287" Text="Transparency can be achieved (or actually approximated) by using alpha-to-coverage (in case of MSAA) or basic alpha/transparency blending using the following approach:&#xD;&#xA;&#xD;&#xA;1. Bind a rasterizer state with a Less-Equal comparison function.&#xD;&#xA;2. Bind no blend state.&#xD;&#xA;3. Render opaque geometry.&#xD;&#xA;4. Bind alpha-to-coverage or alpha/transparency blend state.&#xD;&#xA;5. Render transparent geometry.&#xD;&#xA;&#xD;&#xA;Here, the sets of opaque and transparent geometry are mutually exclusive. The benefit of this approach is that geometry is only drawn once and the rasterization state does not need to change. Unfortunately, it could be possible to observe, through the semi-transparent holes of some double-sided object, that object itself. In this case there is no guarantee that fragments of this object would be blended with other fragments of this object, since the order in which the fragments are resolved is and should not be known.&#xD;&#xA;&#xD;&#xA;Another approach:&#xD;&#xA;&#xD;&#xA;1. Bind a rasterizer state with a Less-Equal comparison function.&#xD;&#xA;2. Bind no blend state.&#xD;&#xA;3. Render all geometry and clip transparent fragments&#xD;&#xA;4. Bind a rasterizer state with a Less comparison function.&#xD;&#xA;5. Bind alpha-to-coverage or alpha/transparency blend state.&#xD;&#xA;6. Render transparent geometry.&#xD;&#xA;&#xD;&#xA;Here, all transparent geometry is drawn twice. First, opaque fragments are processed by the pixel shader whereas transparent fragments are clipped inside the pixel shader. Second, opaque fragments will be discarded by the early-z-test of the rasterizer whereas transparent fragments are processed by the pixel shader (and blended afterwards). &#xD;&#xA;&#xD;&#xA;Both approaches have some differences, but the difference that concerns me the most is the latter approach having two variants of the pixel shader: one that clips transparent fragments and one that does not clip transparent fragments. In case of multiple pixel shaders, this approach will always result in a doubling of the number of pixel shaders. Is it possible to have the benefits of the second approach while having only one variant of the pixel shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15785" PostHistoryTypeId="1" PostId="5747" RevisionGUID="8c81bfd7-88df-47c2-99a4-2cac4e7e2cd0" CreationDate="2017-10-18T18:15:43.177" UserId="2287" Text="Avoid having an opaque and transparent variant of each pixel shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="15786" PostHistoryTypeId="3" PostId="5747" RevisionGUID="8c81bfd7-88df-47c2-99a4-2cac4e7e2cd0" CreationDate="2017-10-18T18:15:43.177" UserId="2287" Text="|rendering|rasterizer|transparency|alpha|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15787" PostHistoryTypeId="6" PostId="5746" RevisionGUID="c7c35c9b-754d-4d78-9c1e-b123d0930ea9" CreationDate="2017-10-18T18:16:17.783" UserId="2287" Comment="edited tags" Text="|transformations|perspective|rasterizer|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15788" PostHistoryTypeId="5" PostId="5746" RevisionGUID="58471172-f468-4835-b4ee-bf491a19eb80" CreationDate="2017-10-18T18:41:15.657" UserId="2287" Comment="edited body" Text="**Perspective Camera**&#xD;&#xA;&#xD;&#xA;A (row-major) perspective transformation matrix has the following format:&#xD;&#xA;&#xD;&#xA;$$\begin{align} \mathrm{T} &#xD;&#xA;&amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;1 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;0 \end{bmatrix}=\begin{bmatrix} 1/x &amp;0 &amp;0 &amp;0 \\ 0 &amp;1/y &amp;0 &amp;0 \\ 0 &amp;0 &amp;-w &amp;1 \\ 0 &amp;0 &amp;z &amp;0\end{bmatrix}. &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;This transformation matrix is used to transform (*homogeneous*) points from view to projection space, after which the homogeneous divide is applied to transform to NDC (Normalized Device Coordinate) space. (*NDC space is technically a 3D space, but for ease of notation, I use 4D points with a $w=1$*).&#xD;&#xA;&#xD;&#xA;In a deferred renderer, we need to go the other way around while resolving the GBuffer and could use four components ($x$, $y$, $z$, $w$, see above) to transform a point from NDC to view space:&#xD;&#xA;&#xD;&#xA;       /**&#xD;&#xA;    	 Returns the projection values from the given projection matrix to construct &#xD;&#xA;    	 the view position coordinates from the NDC position coordinates.&#xD;&#xA;    	 &#xD;&#xA;         @return		The projection values from the given projection matrix to &#xD;&#xA;    					construct the view position coordinates from the NDC position &#xD;&#xA;    					coordinates.&#xD;&#xA;    	 */&#xD;&#xA;    	inline const XMVECTOR XM_CALLCONV GetViewPositionConstructionValues(&#xD;&#xA;    		FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;    		&#xD;&#xA;    		//        [ 1/X  0   0  0 ]&#xD;&#xA;    		// p_view [  0  1/Y  0  0 ] = [p_view.x 1/X, p_view.y 1/Y, p_view.z (-W) + Z, p_view.z] = p_proj&#xD;&#xA;    		//        [  0   0  -W  1 ]&#xD;&#xA;    		//        [  0   0   Z  0 ]&#xD;&#xA;    		//&#xD;&#xA;    		// p_proj / p_proj.w        = [p_view.x/p_view.z 1/X, p_view.y/p_view.z 1/Y, -W + Z/p_view.z, 1] = p_ndc&#xD;&#xA;    		//&#xD;&#xA;    		// Construction of p_view from p_ndc and projection values&#xD;&#xA;    		// 1) p_ndc.z = -W + Z/p_view.z       &lt;=&gt; p_view.z = Z / (p_ndc.z + W)&#xD;&#xA;    		// 2) p_ndc.x = p_view.x/p_view.z 1/X &lt;=&gt; p_view.x = X * p_ndc.x * p_view.z&#xD;&#xA;    		// 3) p_ndc.y = p_view.y/p_view.z 1/Y &lt;=&gt; p_view.y = Y * p_ndc.y * p_view.z&#xD;&#xA;    &#xD;&#xA;    		const F32 x = 1.0f / XMVectorGetX(projection_matrix.r[0]);&#xD;&#xA;    		const F32 y = 1.0f / XMVectorGetY(projection_matrix.r[1]);&#xD;&#xA;    		const F32 z =  XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;    		const F32 w = -XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;    		&#xD;&#xA;    		return XMVectorSet(x, y, z, w);&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;**Orthographic Camera**&#xD;&#xA;&#xD;&#xA;An (row-major) orthographic transformation matrix has the following format:&#xD;&#xA;&#xD;&#xA;$$\begin{align} \mathrm{T} &#xD;&#xA;&amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;1 \end{bmatrix}=\begin{bmatrix} 1/x &amp;0 &amp;0 &amp;0 \\ 0 &amp;1/y &amp;0 &amp;0 \\ 0 &amp;0 &amp;1/z &amp;0 \\ 0 &amp;0 &amp;-w &amp;1\end{bmatrix}. &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;This transformation matrix is used to transform (*homogeneous*) points from view to projection space, after which the homogeneous divide (no-op) is applied to transform to NDC (= projection) space. (*So basically a non-uniform scaling followed by a translation of the z component*).&#xD;&#xA;&#xD;&#xA;We could similarly use four components ($x$, $y$, $z$, $w$, see above) to transform a point from NDC (= projection) to view space:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;	 Returns the projection values from the given projection matrix to construct &#xD;&#xA;	 the view position coordinates from the NDC position coordinates.&#xD;&#xA;	 &#xD;&#xA;     @return		The projection values from the given projection matrix to &#xD;&#xA;					construct the view position coordinates from the NDC position &#xD;&#xA;					coordinates.&#xD;&#xA;	 */&#xD;&#xA;	inline const XMVECTOR XM_CALLCONV GetViewPositionConstructionValues(&#xD;&#xA;		FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;		&#xD;&#xA;		//        [ 1/X  0   0  0 ]&#xD;&#xA;		// p_view [  0  1/Y  0  0 ] = [p_view.x 1/X, p_view.y 1/Y, p_view.z 1/Z -W, 1] = p_proj = p_ndc&#xD;&#xA;		//        [  0   0  1/Z 0 ]&#xD;&#xA;		//        [  0   0  -W  1 ]&#xD;&#xA;		//&#xD;&#xA;		// Construction of p_view from p_ndc and projection values&#xD;&#xA;		// 1) p_ndc.z = p_view.z/Z -W &lt;=&gt; p_view.z = Z * (p_ndc.z + W)&#xD;&#xA;		// 2) p_ndc.x = p_view.x/X    &lt;=&gt; p_view.x = X * p_ndc.x&#xD;&#xA;		// 3) p_ndc.y = p_view.y/Y    &lt;=&gt; p_view.y = Y * p_ndc.y&#xD;&#xA;&#xD;&#xA;		const F32 x = 1.0f / XMVectorGetX(projection_matrix.r[0]);&#xD;&#xA;		const F32 y = 1.0f / XMVectorGetY(projection_matrix.r[1]);&#xD;&#xA;		const F32 z = 1.0f / XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;		const F32 w = -XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;		&#xD;&#xA;		return XMVectorSet(x, y, z, w);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;How can a deferred renderer support multiple camera types (minimally: perspective and orthographic cameras, ideally: all cameras that a forward renderer could support) without specializing the shaders or specializing in the shaders?&#xD;&#xA;&#xD;&#xA;A straightforward solution is to specify some pre-processor directive in the shader, but this unfortunately results in a multiple of all the shader perturbations used so far for lighting in a deferred pipeline. Another solution is to pass a flag in some constant buffer to specify the used camera type, though I am not a fan of the dynamic branching introduced by this flag. Furthermore, both solutions are not as flexible as is the case for forward rendering which can handle arbitrary view-to-projection matrices.&#xD;&#xA;&#xD;&#xA;Ideally, a (hypothetical) NDC-to-view transformation matrix should handle the transformation. Such a matrix does, however, not generally exist for perspective cameras since the view to NDC transformation reduces a 4D space to a 3D subspace." ContentLicense="CC BY-SA 3.0" />
  <row Id="15789" PostHistoryTypeId="2" PostId="5748" RevisionGUID="c323fd37-c2e7-4d6a-a38e-fa8ad19a16e1" CreationDate="2017-10-18T19:58:55.687" UserId="48" Text="Projective transformations (represented by 4×4 projection matrices) are invertible. You can go from NDC coordinates back to view space using the inverse of the projection matrix, in the same way that you go from view space to NDC. That is: take your NDC $x, y, z$ coordinates, append $w = 1$ to make a 4D vector, transform by the inverse projection matrix, then divide out $w$ to get back to 3D.&#xD;&#xA;&#xD;&#xA;View space and NDC space are both fundamentally 3D spaces, though with a 4D homogeneous representation, so the transformation between them doesn't throw away a dimension, despite the divide by $w$. (Some information _is_ lost, though: the sign of $w$, which corresponds to whether a point was behind or in front of the camera. However, this isn't usually a concern, since we cull or clip everything behind the camera during rasterization anyway.)&#xD;&#xA;&#xD;&#xA;As for the shader code, it can presumably be simplified according to which components may be nonzero in the inverse projection matrix. You may only need the $x, y$ diagonal elements and the lower-right 2×2 submatrix, as long as you don't need to support off-axis projections (which have additional nonzero components in their matrix)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15790" PostHistoryTypeId="2" PostId="5749" RevisionGUID="20cbfb83-9876-47e0-9360-04d88b29b54a" CreationDate="2017-10-18T20:04:57.427" UserId="48" Text="You can use a threshold set through a constant buffer to clip pixels (ie an alpha test):&#xD;&#xA;&#xD;&#xA;    float threshold; // in constant buffer&#xD;&#xA;&#xD;&#xA;    float4 color = myTexture.Sample(...);&#xD;&#xA;    if (color.a &lt; threshold)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;Set `threshold` to 1.0 to discard all transparent fragments; set it to 0.0 to discard nothing. There will be some minor inefficency in the latter case compared to having a separate pixel shader with the alpha test removed entirely, but it shouldn't be a big deal on most GPUs nowadays." ContentLicense="CC BY-SA 3.0" />
  <row Id="15794" PostHistoryTypeId="2" PostId="5751" RevisionGUID="e30c700d-d7f8-4e2d-b232-6a8ede98a9da" CreationDate="2017-10-19T01:03:48.723" UserId="7462" Text="I am trying to solve a problem in computer graphics but to do it I need to be able to see a comparison of geodesic lines and straigth line projections on the ellipsoid. &#xD;&#xA;&#xD;&#xA;I have not been able to figure out how to fing the mathematical definition of geodesics (linear projections are easy).&#xD;&#xA;&#xD;&#xA;I was wondering if anybody has coded somehting like this already or is aware ofa  tool I could use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15795" PostHistoryTypeId="1" PostId="5751" RevisionGUID="e30c700d-d7f8-4e2d-b232-6a8ede98a9da" CreationDate="2017-10-19T01:03:48.723" UserId="7462" Text="Program to visualize geodesics and linear projection of an ellipsoid simultaneously" ContentLicense="CC BY-SA 3.0" />
  <row Id="15796" PostHistoryTypeId="3" PostId="5751" RevisionGUID="e30c700d-d7f8-4e2d-b232-6a8ede98a9da" CreationDate="2017-10-19T01:03:48.723" UserId="7462" Text="|computational-geometry|geometry|projections|curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15798" PostHistoryTypeId="50" PostId="2076" RevisionGUID="673bf18f-b6c5-43e3-9482-d522af650856" CreationDate="2017-10-19T10:22:51.690" UserId="-1" />
  <row Id="15799" PostHistoryTypeId="2" PostId="5752" RevisionGUID="530a43ab-5278-4829-a939-17b31ad5c4f2" CreationDate="2017-10-19T11:44:45.513" UserId="2287" Text="For completeness (and in addition to Nathan Reed's [answer](https://computergraphics.stackexchange.com/a/5748/2287)), I explicitly add the inverse projection matrices for perspective and orthographic cameras.&#xD;&#xA;&#xD;&#xA;**Perspective Camera**&#xD;&#xA;&#xD;&#xA;$$\begin{align} &#xD;&#xA;\mathrm{T}_{\mathrm{view \rightarrow projection}} &amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;1 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;0 \end{bmatrix} \! , \\&#xD;&#xA;\mathrm{T}_{\mathrm{projection \rightarrow view}} &amp;=\begin{bmatrix} &#xD;&#xA;1/\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;1/\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;0 &amp;1/\mathrm{T}_{32} \\ &#xD;&#xA;0 &amp;0 &amp;1 &amp;-\mathrm{T}_{22}/\mathrm{T}_{32}\end{bmatrix} \! . &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;            /**&#xD;&#xA;    		 Returns the projection-to-view matrix of this perspective camera.&#xD;&#xA;    &#xD;&#xA;    		 @return		The projection-to-view matrix of this perspective &#xD;&#xA;    						camera.&#xD;&#xA;    		 */&#xD;&#xA;    		virtual const XMMATRIX GetProjectionToViewMatrix() const noexcept override {&#xD;&#xA;    			const XMMATRIX view_to_projection = GetViewToProjectionMatrix();&#xD;&#xA;    &#xD;&#xA;    			const F32 m00 = 1.0f / XMVectorGetX(view_to_projection.r[0]);&#xD;&#xA;    			const F32 m11 = 1.0f / XMVectorGetY(view_to_projection.r[1]);&#xD;&#xA;    			const F32 m23 = 1.0f / XMVectorGetZ(view_to_projection.r[3]);&#xD;&#xA;    			const F32 m33 = -XMVectorGetZ(view_to_projection.r[2]) * m23;&#xD;&#xA;    &#xD;&#xA;    			return XMMATRIX {&#xD;&#xA;    				 m00, 0.0f, 0.0f, 0.0f,&#xD;&#xA;    				0.0f,  m11, 0.0f, 0.0f,&#xD;&#xA;    				0.0f, 0.0f, 0.0f,  m23,&#xD;&#xA;    				0.0f, 0.0f, 1.0f,  m33&#xD;&#xA;    			};&#xD;&#xA;    		}&#xD;&#xA;&#xD;&#xA;**Orthographic Camera**&#xD;&#xA;&#xD;&#xA;$$\begin{align} &#xD;&#xA;\mathrm{T}_{\mathrm{view \rightarrow projection}} &amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;1 \end{bmatrix} \! , \\&#xD;&#xA;\mathrm{T}_{\mathrm{projection \rightarrow view}} &amp;=\begin{bmatrix} &#xD;&#xA;1/\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;1/\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;1/\mathrm{T}_{22} &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;-\mathrm{T}_{32}/\mathrm{T}_{22} &amp;1\end{bmatrix} \! . &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;            /**&#xD;&#xA;    		 Returns the projection-to-view matrix of this orthographic camera.&#xD;&#xA;    &#xD;&#xA;    		 @return		The projection-to-view matrix of this orthographic &#xD;&#xA;    						camera.&#xD;&#xA;    		 */&#xD;&#xA;    		virtual const XMMATRIX GetProjectionToViewMatrix() const noexcept override {&#xD;&#xA;    			const XMMATRIX view_to_projection = GetViewToProjectionMatrix();&#xD;&#xA;    &#xD;&#xA;    			const F32 m00 = 1.0f / XMVectorGetX(view_to_projection.r[0]);&#xD;&#xA;    			const F32 m11 = 1.0f / XMVectorGetY(view_to_projection.r[1]);&#xD;&#xA;    			const F32 m22 = 1.0f / XMVectorGetZ(view_to_projection.r[2]);&#xD;&#xA;    			const F32 m32 = -XMVectorGetZ(view_to_projection.r[3]) * m22;&#xD;&#xA;    			&#xD;&#xA;    			return XMMATRIX {&#xD;&#xA;    				 m00, 0.0f, 0.0f, 0.0f,&#xD;&#xA;    				0.0f,  m11, 0.0f, 0.0f,&#xD;&#xA;    				0.0f, 0.0f,  m22, 0.0f,&#xD;&#xA;    				0.0f, 0.0f,  m32, 1.0f&#xD;&#xA;    			};&#xD;&#xA;    		}" ContentLicense="CC BY-SA 3.0" />
  <row Id="15806" PostHistoryTypeId="2" PostId="5754" RevisionGUID="e88a95cf-0ced-4438-8340-acb8a4ab91e8" CreationDate="2017-10-20T02:33:12.553" UserId="7512" Text="I'm trying to render a particle simulation. I want each particle to leave a trace. To achieve this I'm using a framebuffer and two textures. On each frame the algorithm goes like this:&#xD;&#xA;&#xD;&#xA;1. Render to a framebuffer previously rendered screen texture with `opacity * 0.9`;&#xD;&#xA;2. Render current particles at updated positions;&#xD;&#xA;3. Switch to main display and render current content of the framebuffer; &#xD;&#xA;&#xD;&#xA;This works fine, and I get nice looking particle trails:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;# Problem&#xD;&#xA;&#xD;&#xA;I want to let apply pan/zoom transform to this system. Think like in a map interface - user can drag canvas. The panzoom is achieved by applying a transformation matrix to each particle.&#xD;&#xA;&#xD;&#xA;I want to keep particle's state, but I don't want interaction to leave a particle trace:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I'm wondering what is a proper way of achieving this? I got a basic solution working by applying transform to a previous frame's texture, so that it approximately matches what will be rendered in the current frame, but I still see artifacts:&#xD;&#xA;&#xD;&#xA;1. When zooming in, the updated texture seem to have artifacts:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I assume this is because I'm using fixed point size for a particle (regardless of the zoom level), but when we scale texture, we scale rasterized image, and thus all particles rendered on it also get bigger.&#xD;&#xA;&#xD;&#xA;2. When a particle enters the scene (crosses the border of visible area), it is also very likely to leave a trail:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I'm not sure why this one happens. My screen/back textures are the same size, I'm just translating back texture. I thought it might be related to clamp_to_edge setting, but I don't know how to prove or validate this. I've got a workaround by extending canvas beyond visible area (say by 2%) and in the fragment shader I check that if particle is closer than 2% to the border - I give it transparent color. This kind of &quot;fixes&quot; the problem, but I feel uncomfortable not knowing why it's happening.&#xD;&#xA;&#xD;&#xA;3. Finally, if transformation is very-very small (think kinetic movement), I also observe artifacts:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;I'd appreciate if you could explain some of these artifacts, suggest possible solutions, or general practices used to solve this problem.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2WLuA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1O5ZL.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/Wp0hK.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/CPHte.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/fQPVB.gif&#xD;&#xA;  [6]: https://i.stack.imgur.com/h1mpm.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="15807" PostHistoryTypeId="1" PostId="5754" RevisionGUID="e88a95cf-0ced-4438-8340-acb8a4ab91e8" CreationDate="2017-10-20T02:33:12.553" UserId="7512" Text="Fading particles and transition" ContentLicense="CC BY-SA 3.0" />
  <row Id="15808" PostHistoryTypeId="3" PostId="5754" RevisionGUID="e88a95cf-0ced-4438-8340-acb8a4ab91e8" CreationDate="2017-10-20T02:33:12.553" UserId="7512" Text="|opengl|webgl|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15810" PostHistoryTypeId="5" PostId="5754" RevisionGUID="97e30b3f-0504-4e58-a3d6-754c05a54382" CreationDate="2017-10-20T04:47:37.027" UserId="7512" Comment="added 193 characters in body" Text="I'm trying to render a particle simulation. I want each particle to leave a trace. To achieve this I'm using a framebuffer and two textures. On each frame the algorithm goes like this:&#xD;&#xA;&#xD;&#xA;1. Render to a framebuffer previously rendered screen texture with `opacity * 0.9`;&#xD;&#xA;2. Render current particles at updated positions;&#xD;&#xA;3. Switch to main display and render current content of the framebuffer; &#xD;&#xA;&#xD;&#xA;This works fine, and I get nice looking particle trails:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;# Problem&#xD;&#xA;&#xD;&#xA;I want to allow users to pan and zoom canvas with these particles, similar to a map interface. This is achieved by applying a transformation matrix to each particle.&#xD;&#xA;&#xD;&#xA;I want to keep particle's state, but I don't want the pan/zoom to leave a particle trace:&#xD;&#xA;&#xD;&#xA;## Bad&#xD;&#xA;&#xD;&#xA;Here I'm dragging canvas up and down with mouse cursor. See how particles leave a trace?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;## Good&#xD;&#xA;&#xD;&#xA;Here I'm also dragging the canvas up and down, but particles remain on their trajectory, without leaving a pan trace:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I'm wondering what is a proper way of achieving this? I got a basic solution working by applying a transformation to a previous frame's texture, so that it approximately matches what will be rendered in the current frame, but I there still a few artifacts:&#xD;&#xA;&#xD;&#xA;1. When zooming in, the updated texture &quot;explodes&quot;:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I assume this is because I'm using fixed point size for a particle (regardless of the zoom level), but when we scale texture, we scale rasterized image, and thus all particles rendered on it also get bigger.&#xD;&#xA;&#xD;&#xA;2. When a particle enters the scene (crosses the border of visible area), it is also very likely to leave a trail:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I'm not sure why this one happens. My screen/back textures are the same size, I'm just translating back texture. I thought it might be related to clamp_to_edge setting, but I don't know how to prove or validate this. I've got a workaround by extending canvas beyond visible area (say by 2%) and in the fragment shader I check that if particle is closer than 2% to the border - I give it transparent color. This kind of &quot;fixes&quot; the problem, but I feel uncomfortable not knowing why it's happening.&#xD;&#xA;&#xD;&#xA;3. Finally, if transformation is very-very small (think kinetic movement), I also observe artifacts:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;I'd appreciate if you could explain some of these artifacts, suggest possible solutions, or general practices used to solve this problem.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2WLuA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1O5ZL.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/Wp0hK.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/CPHte.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/fQPVB.gif&#xD;&#xA;  [6]: https://i.stack.imgur.com/h1mpm.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="15816" PostHistoryTypeId="2" PostId="5757" RevisionGUID="cf3e1d42-0fd4-44d6-afdc-ccac71d6d135" CreationDate="2017-10-20T08:20:04.227" UserId="2041" Text="I made a visualization a little like yours years ago, and used a similar technique, because it's the natural approach to the problem. After I spent a few years writing drivers for modern GPUs, I wouldn't use this approach at all, because it creates a dependency from one frame to the next, which introduces pipeline stalls and/or false sharing.&#xD;&#xA;&#xD;&#xA;Today, I'd keep the path of the particle as part of its state, and render the whole trail each frame, instead of reusing the old FBO. It's conceptually a little more difficult, and you have to be careful that the way you draw the past path is exactly the same each frame. For example, if you represent the path with some kind of cubic spline, you can't just move the final control point forward, because it'll change the whole curve slightly. A circular buffer of (x, y) positions would be much easier to get right.&#xD;&#xA;&#xD;&#xA;What you get in exchange for this extra complexity is (a) reduced frame time, memory use, and power consumption (which might be important if you're on mobile), and (b) you won't have your current problem at all. Maybe the frame time advantage won't be as big in WebGL, because you'll end up doing extra work in Javascript, which is slow, but memory bandwidth is more of a bottleneck on most systems. Just make sure that the co-ordinates you store are in the space of your simulation, and transform them into screen co-ordinates when you draw them, just like you would with a 3D scene." ContentLicense="CC BY-SA 3.0" />
  <row Id="15821" PostHistoryTypeId="2" PostId="5758" RevisionGUID="3d6d4154-6188-4746-a1ff-2f1e37f4acd4" CreationDate="2017-10-20T12:34:04.483" UserId="7516" Text="I'm wondering about the technique used when sampling a layered material for the next event in a path tracer. I have a material with three layers: a base diffuse, specular and sheen lobes. How does one go about choosing a discrete layer to sample for the next ray direction? Is this just a random selection? If so, are equal weights assigned to the layers or are weights used based on final contribution of a lobe? Thanks for any insight into this stage of sampling.&#xD;&#xA;&#xD;&#xA;~M" ContentLicense="CC BY-SA 3.0" />
  <row Id="15822" PostHistoryTypeId="1" PostId="5758" RevisionGUID="3d6d4154-6188-4746-a1ff-2f1e37f4acd4" CreationDate="2017-10-20T12:34:04.483" UserId="7516" Text="Path Tracing &amp; Materials" ContentLicense="CC BY-SA 3.0" />
  <row Id="15823" PostHistoryTypeId="3" PostId="5758" RevisionGUID="3d6d4154-6188-4746-a1ff-2f1e37f4acd4" CreationDate="2017-10-20T12:34:04.483" UserId="7516" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15824" PostHistoryTypeId="5" PostId="5742" RevisionGUID="73667b10-455e-4c32-b6a0-ba013b8edc66" CreationDate="2017-10-20T16:31:02.093" UserId="2287" Comment="formatting" Text="I have discovered that there are two ways to update the viewport (might be more, but not sure). Currently I am rebuilding the Pipeline when I resize my screen but there is a noticeable stutter as it rebuilds, but I have also found out that you can use `vkCmdSetViewport` when building/rebuilding your command buffers. But is this the right way to do it? And if I used `vkCmdSetViewport`, what should be put into the `VkGraphicsPipelineCreateInfo pViewportState`?&#xD;&#xA;&#xD;&#xA;If there is an even better way of handling screen resizing please let me know." ContentLicense="CC BY-SA 3.0" />
  <row Id="15825" PostHistoryTypeId="24" PostId="5742" RevisionGUID="73667b10-455e-4c32-b6a0-ba013b8edc66" CreationDate="2017-10-20T16:31:02.093" Comment="Proposed by 2287 approved by 209, 56 edit id of 277" ContentLicense="CC BY-SA 3.0" />
  <row Id="15826" PostHistoryTypeId="2" PostId="5759" RevisionGUID="fb82ce65-39c3-481e-8cb0-a06b7e46dd6f" CreationDate="2017-10-20T16:46:53.423" UserId="56" Text="Thinking about it from a physical standpoint, it seems that it would work like a generalized version of diffuse / specular calculation.&#xD;&#xA;&#xD;&#xA;You'd start with the top most layer and use fresnel etc to calculate a percentage of light that reflects vs transmits.  You then use a random number to determine which of these to do for your sample.&#xD;&#xA;&#xD;&#xA;In the case of reflection, you'd do the specular lobe of your top most layer, reflect off the surface and move on.&#xD;&#xA;&#xD;&#xA;In the case of transmission, you'd move to the 2nd layer.&#xD;&#xA;&#xD;&#xA;At this layer, you'd once again calculate the percentage chance to reflect vs transmit.&#xD;&#xA;&#xD;&#xA;In the case of reflection, you'd use the specular lobe of this second layer, do the reflection and move on.&#xD;&#xA;&#xD;&#xA;In the case of transmission, you'd move to the inner layer.&#xD;&#xA;&#xD;&#xA;For this inner most layer you'd once again figure out if you needed to reflect or transmit.&#xD;&#xA;&#xD;&#xA;For reflection you'd use this inner layer's specular lobe.&#xD;&#xA;&#xD;&#xA;For transmission, you'd do your diffuse calculation, or whatever else your inner most surface wants to do for transmitted light (sub surface scattering? refraction? etc).&#xD;&#xA;&#xD;&#xA;I'm uncertain if each layer should do it's own refraction and if technically you should move the ray a tiny bit between layers to get more realistic effects.  For your case it may not make a difference.&#xD;&#xA;&#xD;&#xA;But basically, if you had a sphere with 3 layers on it, it SHOULD behave as if you had 3 different spheres nested in one another that each had a single layer that handled transmission vs reflection.&#xD;&#xA;&#xD;&#xA;Having a layered material is just a more compact way of saying that this is what you want, compared to having the three separate objects." ContentLicense="CC BY-SA 3.0" />
  <row Id="15827" PostHistoryTypeId="2" PostId="5760" RevisionGUID="55b3c8b8-d6f0-425c-a242-096d2b76e459" CreationDate="2017-10-20T22:57:26.113" UserId="6838" Text="I'm re-learning WebGL, and I stumbled upon [gl.vertexAttribPointer][1] and [gl.vertexAttrib][2]. To my knowledge, gl.vertexAttribPointer tells the GPU how the data in the currently binded buffer relates to the vertex attributes. But, I'm confused on what gl.vertexAttrib does. It seems like it also sends data to the GPU, but without the use of a buffer. Can anybody explain it's role to me?&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer &quot;gl.vertexAttribPointer&quot;&#xD;&#xA;  [2]: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttrib &quot;gl.vertexAttrib&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15828" PostHistoryTypeId="1" PostId="5760" RevisionGUID="55b3c8b8-d6f0-425c-a242-096d2b76e459" CreationDate="2017-10-20T22:57:26.113" UserId="6838" Text="Role of gl.vertexAttrib" ContentLicense="CC BY-SA 3.0" />
  <row Id="15829" PostHistoryTypeId="3" PostId="5760" RevisionGUID="55b3c8b8-d6f0-425c-a242-096d2b76e459" CreationDate="2017-10-20T22:57:26.113" UserId="6838" Text="|shader|webgl|vertex-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15831" PostHistoryTypeId="2" PostId="5761" RevisionGUID="e028ffa9-d25d-4673-a447-729428842046" CreationDate="2017-10-21T03:56:19.317" UserDisplayName="user5681" Text="This question is somewhat related to [this one][1].&#xD;&#xA;&#xD;&#xA;As Alan has already said, following the actual path of the light ray through each layer leads to more physically accurate results. I will base my answer on a paper by Andrea Weidlich and Alexander Wilkie ([&quot;Arbitrarily Layered Micro-Facet Surfaces&quot;][2]) that I have read and implemented. In their paper they assume that the distance between two layers is smaller than the radius of a differential area element. This simplifies the implementation because we do not have to calculate intersection points separately for each layer, actually we assume that the intersection points are the same for all layers. &#xD;&#xA;&#xD;&#xA;According to the paper, two problems must be solved in order to render multilayered material. The first one is to properly sample the layers and the second is to find the resulting BSDF generated by the combination of the multiple BSDFs that are found along the sampling path.&#xD;&#xA;&#xD;&#xA;**Sampling**&#xD;&#xA;&#xD;&#xA;In this first stage we will determine the actual light path through the layers. When a light ray is moving from a less dense medium, e.g. air, to a more dense medium, e.g. glass, part of its energy is reflected and the remaining part is transmitted. You can find the amount of energy that is reflected through the [Fresnel reflectance equations][3]. So, for instance, if the Fresnel reflectance of a given dielectric is 0.3, we know that 30% of the energy is reflected and 70% will be transmitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;When the light ray is moving from a more dense to a less dense medium, the same principle described by the Fresnel reflectance applies. However, in this specific case, [total internal reflection][5] (a.k.a TIR) might also happen if the angle of the incident ray is above the critical angle. In the case of TIR, 100% of the energy is reflected back into the material:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;When light hits a conductor or a diffuse surface, it will always be reflected (being the direction of reflection related to the type of the BRDF). In a multilayer material, the resulting light path will be the agregate result of all those possibilities. Thus, in the case of a 3-layer material, assuming that the first and secong layers are dielectrics and the third layer is diffuse, we might end up with the following light path (a tree actually):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;We can simulate this type of interaction using recursion and weighting each light path according to the actual reflectance/transmitance at the corresponding incident point. A problem regarding the use of recursion is that the number of rays increases with the deepness of the recursion, concentrating computational effort on rays that individually might contribute almost nothing to the final result. On the other hand, the aggregate result of those individual rays at deep recursion levels can be significant and should not be discarded. In this case, we can use Russian Roulette (RR) in order to avoid branching and to probabilistic end light paths without losing energy, but at the cost of a higher variance (noisier result). In this case, the result of the Fresnel reflectance, or the TIR, will be used to randomly select which path to follow. For instance:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;As can be seen, TIR or Fresnel reflectance might keep some rays bouncing indefinitely among layers. As far as I know, [Mitsuba][9] implements plastic as a two layer material, and it uses a closed form solution for this specific case that accounts for an infinity number of light bounces among layers. However, Mitsuba also allows for the creation of multilayer materials with an arbitrary number of layers, in which case it imposes a maximum number of internal bounces since no closed form solution seems to exist for the general case. As a side effect, some energy can be lost in the rendering process, making the material look darker than it should be. &#xD;&#xA;&#xD;&#xA;In my current multilayer material implementation I allow for an arbitrary number of internal bounces at the cost of longer rendering times (well... actually, I've implemented only two layers.. one dielectric and one diffuse :).&#xD;&#xA;&#xD;&#xA;An additional option is to mix branching and RR. For instance, the initial rays (lower deep levels) might present substantial contribution to the final image. Thus, one might choose to branch only at the first one or two intersections, using only RR afterwards. This is the case with [smallpt][10].&#xD;&#xA;&#xD;&#xA;An interesting point regarding multilayered materials is that individual reflected/transmitted rays can be importance sampled according to the corresponding BRDFs/BTDFs of the current layer. &#xD;&#xA;&#xD;&#xA;**Evaluating the Final BSDF**&#xD;&#xA;&#xD;&#xA;Considering the following light path computed using RR:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;We can evaluate the total amount of radiance $L_r$ reflected by a multilayer BSDF considering each layer as a individual object and applying the same approach used in ordinary path tracing (i.e. the radiance leaving a layer will be the incident radiance for the next layer). The final estimator can thus be represented by the product of each individual Monte Carlo estimator:&#xD;&#xA;&#xD;&#xA;$$ fr =  \left( \frac{fr_1 \cos \theta_1}{pdf_1}  \left( \frac{fr_2 \cos \theta_2}{pdf_2} \left( \frac{fr_3 \cos \theta_3}{pdf_3} \left( \frac{fr_2 \cos \theta_4}{pdf_2} \left( \frac{L_i fr_1 \cos \theta_5}{pdf_1} \right)\right)\right)\right)\right)$$&#xD;&#xA;&#xD;&#xA;The [paper][2] by Andrea Weidlich and Alexander Wilkie also takes into consideration absorption, i.e. each light ray might be attenuated according to the absorption factor of each transmissive layer and to the distance travelled by the ray within the layer. I've not included absorption into my renderer yet, but is just a real coefficient computed according to the [Beer's Law][12].&#xD;&#xA;&#xD;&#xA;**Alternate approaches**&#xD;&#xA;&#xD;&#xA;The Mitsuba renderer uses an alternate representation for multilayered material based on the &quot;tabulation of reflectance functions in a Fourier basis&quot;. I have not yet dig into it, but might be of interest: &quot;[A Comprehensive Framework for Rendering Layered Materials][13]&quot; by Wenzel Jacob *et al*. There is also an expanded version of this paper.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4611/5681&#xD;&#xA;  [2]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [4]: https://i.stack.imgur.com/S4zHY.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Total_internal_reflection&#xD;&#xA;  [6]: https://i.stack.imgur.com/Li0lu.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/WBz0l.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/t5ewd.png&#xD;&#xA;  [9]: https://www.mitsuba-renderer.org&#xD;&#xA;  [10]: http://www.kevinbeason.com/smallpt&#xD;&#xA;  [11]: https://i.stack.imgur.com/GWv6b.png&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law&#xD;&#xA;  [13]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 3.0" />
  <row Id="15832" PostHistoryTypeId="5" PostId="5761" RevisionGUID="e18118c4-b3c3-456f-ab49-f38692c6184b" CreationDate="2017-10-21T04:01:35.933" UserDisplayName="user5681" Comment="added 1 character in body" Text="This question is somewhat related to [this one][1].&#xD;&#xA;&#xD;&#xA;As Alan has already said, following the actual path of the light ray through each layer leads to more physically accurate results. I will base my answer on a paper by Andrea Weidlich and Alexander Wilkie ([&quot;Arbitrarily Layered Micro-Facet Surfaces&quot;][2]) that I have read and implemented. In their paper they assume that the distance between two layers is smaller than the radius of a differential area element. This simplifies the implementation because we do not have to calculate intersection points separately for each layer, actually we assume that the intersection points are the same for all layers. &#xD;&#xA;&#xD;&#xA;According to the paper, two problems must be solved in order to render multilayered material. The first one is to properly sample the layers and the second is to find the resulting BSDF generated by the combination of the multiple BSDFs that are found along the sampling path.&#xD;&#xA;&#xD;&#xA;**Sampling**&#xD;&#xA;&#xD;&#xA;In this first stage we will determine the actual light path through the layers. When a light ray is moving from a less dense medium, e.g. air, to a more dense medium, e.g. glass, part of its energy is reflected and the remaining part is transmitted. You can find the amount of energy that is reflected through the [Fresnel reflectance equations][3]. So, for instance, if the Fresnel reflectance of a given dielectric is 0.3, we know that 30% of the energy is reflected and 70% will be transmitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;When the light ray is moving from a more dense to a less dense medium, the same principle described by the Fresnel reflectance applies. However, in this specific case, [total internal reflection][5] (a.k.a TIR) might also happen if the angle of the incident ray is above the critical angle. In the case of TIR, 100% of the energy is reflected back into the material:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;When light hits a conductor or a diffuse surface, it will always be reflected (being the direction of reflection related to the type of the BRDF). In a multilayer material, the resulting light path will be the agregate result of all those possibilities. Thus, in the case of a 3-layer material, assuming that the first and secong layers are dielectrics and the third layer is diffuse, we might end up with the following light path (a tree actually):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;We can simulate this type of interaction using recursion and weighting each light path according to the actual reflectance/transmitance at the corresponding incident point. A problem regarding the use of recursion is that the number of rays increases with the deepness of the recursion, concentrating computational effort on rays that individually might contribute almost nothing to the final result. On the other hand, the aggregate result of those individual rays at deep recursion levels can be significant and should not be discarded. In this case, we can use Russian Roulette (RR) in order to avoid branching and to probabilistic end light paths without losing energy, but at the cost of a higher variance (noisier result). In this case, the result of the Fresnel reflectance, or the TIR, will be used to randomly select which path to follow. For instance:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;As can be seen, TIR or Fresnel reflectance might keep some rays bouncing indefinitely among layers. As far as I know, [Mitsuba][9] implements plastic as a two layer material, and it uses a closed form solution for this specific case that accounts for an infinity number of light bounces among layers. However, Mitsuba also allows for the creation of multilayer materials with an arbitrary number of layers, in which case it imposes a maximum number of internal bounces since no closed form solution seems to exist for the general case. As a side effect, some energy can be lost in the rendering process, making the material look darker than it should be. &#xD;&#xA;&#xD;&#xA;In my current multilayer material implementation I allow for an arbitrary number of internal bounces at the cost of longer rendering times (well... actually, I've implemented only two layers.. one dielectric and one diffuse :).&#xD;&#xA;&#xD;&#xA;An additional option is to mix branching and RR. For instance, the initial rays (lower deep levels) might present substantial contribution to the final image. Thus, one might choose to branch only at the first one or two intersections, using only RR afterwards. This is the case with [smallpt][10].&#xD;&#xA;&#xD;&#xA;An interesting point regarding multilayered materials is that individual reflected/transmitted rays can be importance sampled according to the corresponding BRDFs/BTDFs of the current layer. &#xD;&#xA;&#xD;&#xA;**Evaluating the Final BSDF**&#xD;&#xA;&#xD;&#xA;Considering the following light path computed using RR:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;We can evaluate the total amount of radiance $L_r$ reflected by a multilayer BSDF considering each layer as a individual object and applying the same approach used in ordinary path tracing (i.e. the radiance leaving a layer will be the incident radiance for the next layer). The final estimator can thus be represented by the product of each individual Monte Carlo estimator:&#xD;&#xA;&#xD;&#xA;$$ L_r =  \left( \frac{fr_1 \cos \theta_1}{pdf_1}  \left( \frac{fr_2 \cos \theta_2}{pdf_2} \left( \frac{fr_3 \cos \theta_3}{pdf_3} \left( \frac{fr_2 \cos \theta_4}{pdf_2} \left( \frac{L_i fr_1 \cos \theta_5}{pdf_1} \right)\right)\right)\right)\right)$$&#xD;&#xA;&#xD;&#xA;The [paper][2] by Andrea Weidlich and Alexander Wilkie also takes absorption into consideration, i.e. each light ray might be attenuated according to the absorption factor of each transmissive layer and to the distance traveled by the ray within the layer. I've not included absorption into my renderer yet, but it is just a real coefficient computed according to the [Beer's Law][12].&#xD;&#xA;&#xD;&#xA;**Alternate approaches**&#xD;&#xA;&#xD;&#xA;The Mitsuba renderer uses an alternate representation for multilayered material based on the &quot;tabulation of reflectance functions in a Fourier basis&quot;. I have not yet dig into it, but might be of interest: &quot;[A Comprehensive Framework for Rendering Layered Materials][13]&quot; by Wenzel Jacob *et al*. There is also an expanded version of this paper.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4611/5681&#xD;&#xA;  [2]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [4]: https://i.stack.imgur.com/S4zHY.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Total_internal_reflection&#xD;&#xA;  [6]: https://i.stack.imgur.com/Li0lu.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/WBz0l.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/t5ewd.png&#xD;&#xA;  [9]: https://www.mitsuba-renderer.org&#xD;&#xA;  [10]: http://www.kevinbeason.com/smallpt&#xD;&#xA;  [11]: https://i.stack.imgur.com/GWv6b.png&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law&#xD;&#xA;  [13]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 3.0" />
  <row Id="15834" PostHistoryTypeId="2" PostId="5762" RevisionGUID="073448c4-2b6c-433f-b5a6-85cc1d95fd66" CreationDate="2017-10-21T11:00:02.030" UserId="4958" Text="In their [presentation][1] at SIGGRAPH 2015 Electronic Arts presented method of volumetric rendering using 3D texture aligned with view frustum.&#xD;&#xA;&#xD;&#xA;This technique needs two steps:&#xD;&#xA;&#xD;&#xA; - Injection of color and density into 3D texture,&#xD;&#xA; - Integration along Z axis of texture.&#xD;&#xA;&#xD;&#xA;Integration code example is on slide 27. However, it is stated as being wrong. Do anyone can explain what is wrong with that (pretty standard raymarching integration) code?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.slideshare.net/DICEStudio/physically-based-and-unified-volumetric-rendering-in-frostbite" ContentLicense="CC BY-SA 3.0" />
  <row Id="15835" PostHistoryTypeId="1" PostId="5762" RevisionGUID="073448c4-2b6c-433f-b5a6-85cc1d95fd66" CreationDate="2017-10-21T11:00:02.030" UserId="4958" Text="Volumetric integration in Frostbite" ContentLicense="CC BY-SA 3.0" />
  <row Id="15836" PostHistoryTypeId="3" PostId="5762" RevisionGUID="073448c4-2b6c-433f-b5a6-85cc1d95fd66" CreationDate="2017-10-21T11:00:02.030" UserId="4958" Text="|raymarching|3dtexture|volumetric-scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15837" PostHistoryTypeId="2" PostId="5763" RevisionGUID="6ce5fc90-6c97-462f-932f-63b48ffd9051" CreationDate="2017-10-21T16:19:08.130" UserId="48" Text="What is wrong with it seems to be explained on the next two slides: it leads to non-energy-conserving results, where the apparent brightness of the volume changes depending on the scattering coefficient.&#xD;&#xA;&#xD;&#xA;My read of it is that the &quot;wrong&quot; integration code implicitly assumes a constant transmittance over the extent of each voxel. But the trouble is, when the scattering coefficient is high, the transmittance will fall off significantly within a single voxel. For instance, if you have voxels of size 10 cm, but the scattering coefficient is 1 / (5 cm), then the transmittance falls off by exp(10 cm / 5 cm), or about a factor of 7.4 over the length of the voxel!&#xD;&#xA;&#xD;&#xA;Therefore, according to slide 28, a better approach is to explicitly account for the transmittance falloff over the voxel length, while still assuming constant inscattered light. Fortunately the integral has a simple closed-form solution. So, they're saying to evaluate _that_ formula per voxel in the integration loop, in place of the former &quot;wrong&quot; one." ContentLicense="CC BY-SA 3.0" />
  <row Id="15838" PostHistoryTypeId="5" PostId="3606" RevisionGUID="41c66fd2-52fa-4202-b05f-d7dfe70521c2" CreationDate="2017-10-22T05:06:57.687" UserId="2654" Comment="edited body" Text="The counter you want is built in the shader as `gl_VertexID`. &#xD;&#xA;&#xD;&#xA;However you have 16 attributes of 4 components each to work with. Take 2 components for the texture coordinates and you have 62 float values to play with. If you need 6 components per blend shape (3 pos + 3 normal) you get 10 blend shapes to work with per object per frame. If you leave off the normal as static then you get up to 19 shapes.&#xD;&#xA;&#xD;&#xA;Times when you want to blend between more than 10 shapes should be very rare. And even then you can probably get away with making another shape to get the resulting shape you want." ContentLicense="CC BY-SA 3.0" />
  <row Id="15839" PostHistoryTypeId="2" PostId="5764" RevisionGUID="463bf62e-a8ac-4d63-a612-14656c317d81" CreationDate="2017-10-22T07:58:25.637" UserId="5944" Text="Both [Mitsuba][1] and [Tungsten][2] use the **power heuristic** to do multiple importance sampling (MIS).&#xD;&#xA;&#xD;&#xA;Mitsuba:&#xD;&#xA;&#xD;&#xA;    inline Float miWeight(Float pdfA, Float pdfB) const {&#xD;&#xA;        pdfA *= pdfA;&#xD;&#xA;        pdfB *= pdfB;&#xD;&#xA;        return pdfA / (pdfA + pdfB);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Tungsten:&#xD;&#xA;&#xD;&#xA;    static inline float powerHeuristic(float pdf0, float pdf1)&#xD;&#xA;    {&#xD;&#xA;        return (pdf0*pdf0)/(pdf0*pdf0 + pdf1*pdf1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*Advanced Global Illumination* gives the **balance heuristic**:&#xD;&#xA;$$F=\cfrac1N\sum_{i=1}^n\sum_{j=1}^{n_i}\cfrac{f(X_{i,j})}{{\sum\limits_{k=1}^n}\frac{c_k}Np_k(X_{i,j})}$$&#xD;&#xA;&#xD;&#xA;The **power heuristic** may be like this:&#xD;&#xA;$$F=\cfrac1N\sum_{i=1}^n\sum_{j=1}^{n_i}\cfrac{f(X_{i,j})p_i(X_{i,j})}{{\sum\limits_{k=1}^n}\frac{n_k}Np_k^2(X_{i,j})}$$&#xD;&#xA;&#xD;&#xA;I know they are all valid estimators.&#xD;&#xA;&#xD;&#xA;What's the motivation to use the **power heuristic**?&#xD;&#xA;&#xD;&#xA;What about the **cube heuristic**?&#xD;&#xA;$$F=\cfrac1N\sum_{i=1}^n\sum_{j=1}^{n_i}\cfrac{f(X_{i,j})p_i^2(X_{i,j})}{{\sum\limits_{k=1}^n}\frac{n_k}Np_k^3(X_{i,j})}$$&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mitsuba-renderer/mitsuba&#xD;&#xA;  [2]: https://github.com/tunabrain/tungsten" ContentLicense="CC BY-SA 3.0" />
  <row Id="15840" PostHistoryTypeId="1" PostId="5764" RevisionGUID="463bf62e-a8ac-4d63-a612-14656c317d81" CreationDate="2017-10-22T07:58:25.637" UserId="5944" Text="Power heuristic in multiple importance sampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="15841" PostHistoryTypeId="3" PostId="5764" RevisionGUID="463bf62e-a8ac-4d63-a612-14656c317d81" CreationDate="2017-10-22T07:58:25.637" UserId="5944" Text="|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15842" PostHistoryTypeId="5" PostId="5680" RevisionGUID="0fe987ee-e33e-4e5b-9a2c-9fba425c8485" CreationDate="2017-10-22T09:05:12.230" UserId="2287" Comment="exponent typo" Text="In the SIGGRAPH course: &#xD;&#xA;&#xD;&#xA;[BURLEY B.: Physically Based Shading at Disney, SIGGRAPH 2012 Course: Practical Physically Based Shading in Film and Game Production, 2012.](https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf)&#xD;&#xA;&#xD;&#xA;it is mentioned that some BRDF models include a diffuse Fresnel factor such as:&#xD;&#xA;&#xD;&#xA;$$(1-F(\theta_l)) (1-F(\theta_d)).$$&#xD;&#xA;&#xD;&#xA;The Disney BRDF itself uses the following diffuse BRDF component (using Sclick's Fresnel approximation):&#xD;&#xA;&#xD;&#xA;$$f_d = \frac{\textrm{c_base}}{\pi} (1 + (F_{\textrm{D90}} - 1)(1-\cos\theta_l)^5) (1 + (F_{\textrm{D90}} - 1)(1-\cos\theta_v)^5),$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$F_{\textrm{D90}} = 0.5 + 2 \text{roughness} \cos^2\theta_d. $$&#xD;&#xA;&#xD;&#xA;Where does this come from? &#xD;&#xA;&#xD;&#xA;My attempt...&#xD;&#xA;&#xD;&#xA;If I evaluate $(1-F(\theta_l)) (1-F(\theta_v))$ (instead of $(1-F(\theta_l)) (1-F(\theta_d))$?) with Schlick's approximation, we get:&#xD;&#xA;&#xD;&#xA;$$\left(1-(F_0 + (1-F_0)(1-\cos\theta_l)^5)\right) \left(1-(F_0 + (1-F_0)(1-\cos\theta_v)^5)\right)$$&#xD;&#xA;$$\left(1-F_0 + (F_0-1)(1-\cos\theta_l)^5\right) \left(1-F_0 + (F_0-1)(1-\cos\theta_v)^5\right)$$&#xD;&#xA;&#xD;&#xA;If we substitute $F_{\textrm{D90}} = F_0$, we get:&#xD;&#xA;&#xD;&#xA;$$\left(1-F_{\textrm{D90}} + (F_{\textrm{D90}}-1)(1-\cos\theta_l)^5\right) \left(1-F_{\textrm{D90}} + (F_{\textrm{D90}}-1)(1-\cos\theta_v)^5\right)$$&#xD;&#xA;&#xD;&#xA;This looks similar except for the 2x $-F_{\textrm{D90}}$? Is my reasoning completely wrong or where do I make mistakes? Or am I not aware of some further (common) approximations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15843" PostHistoryTypeId="2" PostId="5765" RevisionGUID="5f7d7857-7467-4371-8ea2-75b20c381d96" CreationDate="2017-10-22T10:37:26.660" UserId="5944" Text="*PBRT v3* Page 799:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Veach determined it empirically.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xwuxh.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15845" PostHistoryTypeId="2" PostId="5767" RevisionGUID="210d05ba-4abf-4a1b-a85d-55beb06db6b1" CreationDate="2017-10-22T20:22:43.393" UserId="6838" Text="gl.vertexAttribPointer is used when different vertices should have different values, and gl.vertexAttrib is used when all vertices should have the same values, and you don't want to use a special shader with a uniform." ContentLicense="CC BY-SA 3.0" />
  <row Id="15846" PostHistoryTypeId="5" PostId="5763" RevisionGUID="48b01be5-d05b-4eb8-8e64-277e0f4b9f99" CreationDate="2017-10-22T22:10:35.020" UserId="48" Comment="add code sample" Text="What is wrong with it seems to be explained on the next two slides: it leads to non-energy-conserving results, where the apparent brightness of the volume changes depending on the scattering coefficient.&#xD;&#xA;&#xD;&#xA;My read of it is that the &quot;wrong&quot; integration code implicitly assumes a constant transmittance over the extent of each voxel. But the trouble is, when the scattering coefficient is high, the transmittance will fall off significantly within a single voxel. For instance, if you have voxels of size 10 cm, but the scattering coefficient is 1 / (5 cm), then the transmittance falls off by exp(10 cm / 5 cm), or about a factor of 7.4 over the length of the voxel!&#xD;&#xA;&#xD;&#xA;Therefore, according to slide 28, a better approach is to explicitly account for the transmittance falloff over the voxel length, while still assuming constant inscattered light. Fortunately the integral has a simple closed-form solution. So, they're saying to evaluate _that_ formula per voxel in the integration loop, in place of the former &quot;wrong&quot; one.&#xD;&#xA;&#xD;&#xA;For completeness: in the code from slide 27, replace this line:&#xD;&#xA;&#xD;&#xA;    accumScatteringTransmittance.rgb += scatteringExtinction.rgb *&#xD;&#xA;        accumScatteringTransmittance.a;&#xD;&#xA;&#xD;&#xA;with this:&#xD;&#xA;&#xD;&#xA;    accumScatteringTransmittance.rgb += scatteringExtinction.rgb *&#xD;&#xA;        accumScatteringTransmittance.a *&#xD;&#xA;        ((1.0 - transmittance) / scatteringExtinction.a);&#xD;&#xA;&#xD;&#xA;Here, `accumScatteringTransmittance.a` is the transmittance at the point the ray _enters_ the voxel (i.e. the resultant transmittance of all the voxels in front of it), and then the `((1.0 - transmittance) / scatteringExtinction.a)` factor accounts for the varying transmittance within the voxel." ContentLicense="CC BY-SA 3.0" />
  <row Id="15866" PostHistoryTypeId="2" PostId="5772" RevisionGUID="0ae88f8d-0cf8-47db-8452-9ac7fc72c442" CreationDate="2017-10-24T06:27:41.470" UserId="7462" Text="I have a vertex shader that is used with glDrawElementsInstanced() To draw the visible faces of a set of cubes. There is a unique texture for the cube that is 192*32 pixels big (each 32x32 section is one face) so based on the face (top, left, bottom...) that is currently being drawn, I need to dynamically calculate the texture coordinates.&#xD;&#xA;&#xD;&#xA;This is my current shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex&#xD;&#xA;    layout(location = 1) in vec3 norm; //a 3D vertex representing the normal to teh vertex &#xD;&#xA;    layout(location = 2) in vec2 texture_coordinate;&#xD;&#xA;    &#xD;&#xA;    out vec3 normal; &#xD;&#xA;    out vec3 vertexPos; //projected vertex&#xD;&#xA;    out vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 model = mat4(1); //Position and orientation of the current object&#xD;&#xA;    uniform mat4 view = mat4(1); //Camera orientation and position&#xD;&#xA;    uniform mat4 proj = mat4(1); //the projection parameters (FOV, viewport dimensions)&#xD;&#xA;    &#xD;&#xA;    uniform uint face_type[2048];&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uint orientation=face_type[gl_InstanceID];&#xD;&#xA;        vec2 face_texture = vec2(orientation*(1/6.f),0);&#xD;&#xA;    &#xD;&#xA;        vec2 fml = texture_coordinate + face_texture;&#xD;&#xA;    &#xD;&#xA;        gl_Position = proj*view*model*vec4(position, 1.0);&#xD;&#xA;        normal = vec3(model*vec4(norm,1.0));&#xD;&#xA;        vertexPos = vec3(model*vec4(position, 1.0)); //calculate the transformed pos&#xD;&#xA;        texture_coord = vec2(orientation*(1/6.f),0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So far it seems OpenGL simply doesn't like me trying to calculate the coordinates dynamically, since it constantly throws an error when I try to set the texture coordinates to a uniform value." ContentLicense="CC BY-SA 3.0" />
  <row Id="15867" PostHistoryTypeId="1" PostId="5772" RevisionGUID="0ae88f8d-0cf8-47db-8452-9ac7fc72c442" CreationDate="2017-10-24T06:27:41.470" UserId="7462" Text="How to dynamically calculate texture coordinates in a vertex shader with OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15868" PostHistoryTypeId="3" PostId="5772" RevisionGUID="0ae88f8d-0cf8-47db-8452-9ac7fc72c442" CreationDate="2017-10-24T06:27:41.470" UserId="7462" Text="|opengl|texture|glsl|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15869" PostHistoryTypeId="2" PostId="5773" RevisionGUID="e220e235-2a60-4048-a2b4-8fb82a9224ae" CreationDate="2017-10-24T07:00:35.770" UserId="182" Text="To be able to give a good answer, we need to know what is the compiler error you are referring to.&#xD;&#xA;&#xD;&#xA;At first sight your shader looks ok, although:&#xD;&#xA;&#xD;&#xA;* It always sets `texture_coord.y` to `0`, which might not be what you want.&#xD;&#xA;* I am not entirely sure if strict GLSL allows to multiply a uint with a float (in `orientation*(1/6.f)`); a cast might be necessary.&#xD;&#xA;* You also need to make sure that on the receiving end, the fragment shader is declaring the texture coordinate as needed: `in vec2 texture_coord;`.&#xD;&#xA;&#xD;&#xA;It is fairly common to set texture coordinates dynamically in the vertex shader, so you should be able to do so too." ContentLicense="CC BY-SA 3.0" />
  <row Id="15870" PostHistoryTypeId="5" PostId="5773" RevisionGUID="1597b8a4-ce36-4f97-a9f8-3f384c6e2954" CreationDate="2017-10-24T07:06:02.217" UserId="182" Comment="added 73 characters in body" Text="To be able to give a good answer, we need to know what is the compiler error you are referring to.&#xD;&#xA;&#xD;&#xA;At first sight your shader looks ok, although:&#xD;&#xA;&#xD;&#xA;* It always sets `texture_coord.y` to `0`, which might not be what you want.&#xD;&#xA;* The `.f` notation (in `orientation*(1/6.f)`) doesn't exist in GLSL. It should be `1./6.`. Moreover, I am not entirely sure if strict GLSL allows to multiply a uint with a float; a cast might be necessary.&#xD;&#xA;* You also need to make sure that on the receiving end, the fragment shader is declaring the texture coordinate as needed: `in vec2 texture_coord;`.&#xD;&#xA;&#xD;&#xA;It is fairly common to set texture coordinates dynamically in the vertex shader, so you should be able to do so too." ContentLicense="CC BY-SA 3.0" />
  <row Id="15875" PostHistoryTypeId="5" PostId="5772" RevisionGUID="0db66141-6ebb-461e-a813-a57d00873ac2" CreationDate="2017-10-24T12:16:06.960" UserId="7462" Comment="added 2272 characters in body" Text="I modified my code, and tried to pass a set of integers specifying the face of a cube (top, bottom left...) to the vertex shader in order to draw multiple instances of a cube face.&#xD;&#xA;&#xD;&#xA;I did this by trying to pass them as vertex attributes, but it isn't working as I expected, the value of the int should be between 0 and 5, but it's never a number between 0 and 5, in fact it seems to be much much larger than that.&#xD;&#xA;&#xD;&#xA;This is my current shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926535897932384626433832795&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex&#xD;&#xA;    layout(location = 1) in vec3 norm; //a 3D vertex representing the normal to teh vertex &#xD;&#xA;    layout(location = 2) in vec2 texture_coordinate;&#xD;&#xA;    layout(location = 3) in int face_type;&#xD;&#xA;    &#xD;&#xA;    out vec3 normal; &#xD;&#xA;    out vec3 vertexPos; //projected vertex&#xD;&#xA;    out vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 model = mat4(1); //Position and orientation of the current object&#xD;&#xA;    uniform mat4 view = mat4(1); //Camera orientation and position&#xD;&#xA;    uniform mat4 proj = mat4(1); //the projection parameters (FOV, viewport dimensions)&#xD;&#xA;    &#xD;&#xA;    //Taken from: https://gist.github.com/neilmendoza/4512992&#xD;&#xA;    mat4 rotationMatrix(vec3 axis, float angle)&#xD;&#xA;    {&#xD;&#xA;        axis = normalize(axis);&#xD;&#xA;        float s = sin(angle);&#xD;&#xA;        float c = cos(angle);&#xD;&#xA;        float oc = 1.0 - c;&#xD;&#xA;        &#xD;&#xA;        return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,&#xD;&#xA;                    oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,&#xD;&#xA;                    oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,&#xD;&#xA;                    0.0,                                0.0,                                0.0,                                1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        mat4 rotation = mat4(1);&#xD;&#xA;        switch(face_type)&#xD;&#xA;        {&#xD;&#xA;            case 0:&#xD;&#xA;                rotation = mat4(1);&#xD;&#xA;                break;&#xD;&#xA;            case 1:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), -PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 2:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 3:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), PI);&#xD;&#xA;                break;&#xD;&#xA;            case 4:&#xD;&#xA;                rotation = rotationMatrix(vec3(1,0,0), PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 5:&#xD;&#xA;                rotation = rotationMatrix(vec3(1,0,0), -PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            &#xD;&#xA;            default:&#xD;&#xA;                rotation = mat4(vec4(face_type,0,0,0),&#xD;&#xA;                                vec4(0,1,0,0),&#xD;&#xA;                                vec4(0,0,1,0),&#xD;&#xA;                                vec4(0,0,0,1));&#xD;&#xA;                break;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        /*rotation = mat4(vec4(5,0,0,0),&#xD;&#xA;                        vec4(0,5,0,0),&#xD;&#xA;                        vec4(0,0,5,0),&#xD;&#xA;                        vec4(0,0,0,1));*/&#xD;&#xA;    &#xD;&#xA;        vec4 projection = proj*view*model*rotation*vec4(position, 1.0);&#xD;&#xA;        gl_Position = projection;&#xD;&#xA;    &#xD;&#xA;        normal = vec3(model*vec4(norm,1.0));&#xD;&#xA;        vertexPos = vec3(model*vec4(position, 1.0)); //calculate the transformed pos&#xD;&#xA;        texture_coord = texture_coordinate + vec2(face_type*(1/6.f),0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is how I am passing the face information to the shader:&#xD;&#xA;&#xD;&#xA;     vector&lt;Face&gt; face_types = {Top, Bottom, Left,};&#xD;&#xA;        glEnableVertexAttribArray(3);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, experiment);&#xD;&#xA;        glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, sizeof(Face), (void*)0);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, face_types.size()*sizeof(Face),&#xD;&#xA;            face_types.data(), GL_DYNAMIC_DRAW);&#xD;&#xA;        glVertexAttribDivisor(3, 1);&#xD;&#xA;&#xD;&#xA;Edit: modified the question" ContentLicense="CC BY-SA 3.0" />
  <row Id="15881" PostHistoryTypeId="5" PostId="4979" RevisionGUID="c3d402ad-6356-4b87-81a8-9948c9907ab8" CreationDate="2017-10-25T00:49:46.943" UserId="310" Comment="Minor fixes" Text="What is importance sampling? Every article I read about it mentions 'PDF' what is that as well?&#xD;&#xA;&#xD;&#xA;From what I gather, importance sampling is a technique to only sample areas on a hemisphere that matter more than others. So, ideally, I should sample rays towards light sources to reduce noise and increase speed. Also, some BRDF's at grazing angles have little no difference in the calculation so using importance sampling to avoid that is good? &#xD;&#xA;&#xD;&#xA;If I were to implement importance sampling for a Cook-Torrance BRDF how could I do this? " ContentLicense="CC BY-SA 3.0" />
  <row Id="15886" PostHistoryTypeId="5" PostId="5773" RevisionGUID="105b32db-c9f2-48fd-9420-57afaa3dcec6" CreationDate="2017-10-25T08:57:05.470" UserId="182" Comment="added 2009 characters in body" Text="To be able to give a good answer, we need to know what is the compiler error you are referring to.&#xD;&#xA;&#xD;&#xA;At first sight your shader looks ok, although:&#xD;&#xA;&#xD;&#xA;* It always sets `texture_coord.y` to `0`, which might not be what you want.&#xD;&#xA;* The `.f` notation (in `orientation*(1/6.f)`) doesn't exist in GLSL. It should be `1./6.`. Moreover, I am not entirely sure if strict GLSL allows to multiply a uint with a float; a cast might be necessary.&#xD;&#xA;* You also need to make sure that on the receiving end, the fragment shader is declaring the texture coordinate as needed: `in vec2 texture_coord;`.&#xD;&#xA;&#xD;&#xA;It is fairly common to set texture coordinates dynamically in the vertex shader, so you should be able to do so too.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**Update to your additional questions and details:**&#xD;&#xA;&#xD;&#xA;&gt; OpenGL throws an INVALID_OPERATION error&#xD;&#xA;&#xD;&#xA;OpenGL error handling is quite tricky, since you have to poll for errors yourself, and it uses the same few error codes for wildly different functions. You have to identify exactly which function yielded the error, then refer to the documentation for the list of reasons this error can happen for that function. To make that task easier, the best way I have found so far is to _always_ surround OpenGL calls with a macro doing an error check. You can find an [implementation of a macro like that in the source code of bgfx][1] for example.&#xD;&#xA;&#xD;&#xA;&gt; The error comes from my face type array being too big, but now I don't know how to pass the face type information into the shader, since I know I need 2048 elements at most&#xD;&#xA;&#xD;&#xA;The layout declared in the shader must match the one declared through the OpenGL calls. The number of vertices is irrelevant on the shader side, but it must be consistent on the OpenGL declaration side. Unless you are using different indexes for the vertex attributes, you should have as many positions, normals, texture coordinates and face types.&#xD;&#xA;&#xD;&#xA;The following snippet from your question seems to be declaring face types for only three vertices though:&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, experiment);&#xD;&#xA;    glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, sizeof(Face), (void*)0);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, face_types.size()*sizeof(Face), face_types.data(), GL_DYNAMIC_DRAW);&#xD;&#xA;    glVertexAttribDivisor(3, 1);&#xD;&#xA;&#xD;&#xA;I am not familiar with `glVertexAttribDivisor`, but from what I read, it seems to be limited to instanced rendering.&#xD;&#xA;&#xD;&#xA;You can find a simple [example of binding in the examples of Dear ImGui][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/bkaradzic/bgfx/blob/8d471959eb3cbc16c0e7fdac25efcf842abd2ad1/src/renderer_gl.h#L994&#xD;&#xA;  [2]: https://github.com/ocornut/imgui/blob/50f5be9266ce21391597695dc80b15a4724447cc/examples/opengl3_example/imgui_impl_glfw_gl3.cpp#L270" ContentLicense="CC BY-SA 3.0" />
  <row Id="15887" PostHistoryTypeId="5" PostId="5656" RevisionGUID="9c99d267-bb96-489a-bcd8-e786043a4161" CreationDate="2017-10-25T10:57:51.953" UserId="2287" Comment="added 387 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the **F**, **G** (or **V** depending if you factor the foreshortening in the denominator into **G**) and **D**:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seem to be used (in the literature, in the animation industry and in the gaming industry) in the format corresponding to your **second** option. All the **D** factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$ (See [Equations](http://graphicrants.blogspot.be/2013/08/specular-brdf-reference.html)).&#xD;&#xA;&#xD;&#xA;**Edit 2:** I just found a presentation deriving and explaining the division by $4$ instead of $\pi$:&#xD;&#xA;&#xD;&#xA;[*Earl Hammon: PBR Diffuse Lighting for GGX+Smith Microsurfaces*, GDC 2005.](https://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf)&#xD;&#xA;(*I haven't had time to read this thoroughly yet, but the mystery is clarified in this presentation.*)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15888" PostHistoryTypeId="5" PostId="5656" RevisionGUID="ff713ca2-b69a-41f5-8a92-ddc65277ad67" CreationDate="2017-10-25T11:39:44.813" UserId="2287" Comment="deleted 104 characters in body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the **F**, **G** (or **V** depending if you factor the foreshortening in the denominator into **G**) and **D**:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seem to be used (in the literature, in the animation industry and in the gaming industry) in the format corresponding to your **second** option. All the **D** factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$ (See [Equations](http://graphicrants.blogspot.be/2013/08/specular-brdf-reference.html)).&#xD;&#xA;&#xD;&#xA;**Edit 2:** I just found a presentation deriving and explaining the division by $4$ instead of $\pi$:&#xD;&#xA;&#xD;&#xA;[*Earl Hammon: PBR Diffuse Lighting for GGX+Smith Microsurfaces*, GDC 2005.](https://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15889" PostHistoryTypeId="5" PostId="5656" RevisionGUID="d607f0ce-92ec-4202-a708-d687fb3b9afa" CreationDate="2017-10-25T11:47:19.843" UserId="2287" Comment="edited body" Text="A more recent paper (2005 at least ;) ), has a more concise notation while comparing multiple BRDFs including the **Cook-Torrance BRDF**. Their formula does not include the division by 4.&#xD;&#xA;&#xD;&#xA;[*Addy Ngan, Frédo Durand, Wojciech Matusik: Experimental Analysis of BRDF Models, &#xD;&#xA;Proceedings of the Eurographics Symposium on Rendering 2005.*][1]&#xD;&#xA;&#xD;&#xA;[Project Page][2], [Supplemental][3] (Take a look at the supplemental!)&#xD;&#xA;&#xD;&#xA;Note, however that the **Cook-Torrance BRDF** is not equal and thus not a synonym for the **Torrance-Sparrow BRDF**. The latter includes your division by 4. An interesting reference overview can be found in:&#xD;&#xA;&#xD;&#xA;[*Rosana Montes, Carlos Ureña: An Overview of BRDF Models, Technical Report, 2012.*][4]&#xD;&#xA;&#xD;&#xA;The same **Cook-Torrance BRDF** formula is also present in:&#xD;&#xA;&#xD;&#xA;*Philip Dutré, Kavita Bala, Philippe Bekaert: Advanced Global Illumination, 2nd Edition, 2006.*&#xD;&#xA;&#xD;&#xA;  [1]: http://people.csail.mit.edu/addy/research/ngan05_brdf_eval.pdf&#xD;&#xA;  [2]: http://people.csail.mit.edu/addy/research/brdf/&#xD;&#xA;  [3]: http://people.csail.mit.edu/addy/research/ngan05_brdf_supplemental_doc.pdf&#xD;&#xA;  [4]: http://digibug.ugr.es/bitstream/10481/19751/1/rmontes_LSI-2012-001TR.pdf&#xD;&#xA;&#xD;&#xA;**Edit**: I looked at some (isotropic) implementations of the **F**, **G** (or **V** depending if you factor the foreshortening in the denominator into **G**) and **D**:&#xD;&#xA;&#xD;&#xA; - **D**: Beckmann, Ward-Duer, Blinn-Phong, Trowbridge-Reitz a.k.a. GGX a.k.a. GTR2, Berry a.k.a. GTR1;&#xD;&#xA; - **G**|**V**: Implicit, Ward, Neumann, Ashikhmin-Premoze, Kelemann, Cook-Torrance, Smith GGX, Smith Schlick-GGX, Smith Beckmann, Smith Schlick-Beckmann;&#xD;&#xA; - **F**: Schlick, Cook-Torrance.&#xD;&#xA;&#xD;&#xA;They all seem to be used (in the literature, in the animation industry and in the gaming industry) in the format corresponding to your **second** option. All the **D** factors in my enumeration contain an explicit $\frac{1}{\pi \alpha^2} $ with $\alpha \equiv \text{roughness}^2$ (See [Equations](http://graphicrants.blogspot.be/2013/08/specular-brdf-reference.html)).&#xD;&#xA;&#xD;&#xA;**Edit 2:** A recent presentation deriving and explaining the division by $4$ instead of $\pi$:&#xD;&#xA;&#xD;&#xA;[*Earl Hammon: PBR Diffuse Lighting for GGX+Smith Microsurfaces*, GDC 2017.](https://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf)&#xD;&#xA;&#xD;&#xA;To make a long story shorter, **option 2 is the only correct specular term** (of the three options provided)." ContentLicense="CC BY-SA 3.0" />
  <row Id="15896" PostHistoryTypeId="2" PostId="5778" RevisionGUID="cd0f72d8-c3cb-42c9-a37f-4d1bd4c84204" CreationDate="2017-10-25T20:33:13.310" UserId="2437" Text="I am writing a 2D light casting algorithm with OpenGL compute shaders. The algorithm is simple:&#xD;&#xA;For each light source shoot out light rays from it, the ray begins at the light coordinates, it ends at a pixel in a circle around the light source (the light distance). When calculating the ray sample the pixel underneath it to model light colour/alpha changes. The algorithm works well, but a few pixels are missed, so they stay black causing Moire-like artifacts. The lightrays are calculated in a compute shader parallelly, one thread for each pixel in the light border circle. This means for example for a light with 256 radius, there are 2*256*Pi=1608 threads on the GPU, each calculating a single ray.&#xD;&#xA;&#xD;&#xA;Heres the relevant compute shader code:&#xD;&#xA;&#xD;&#xA;    #define LOCAL_WG_SIZE 128u&#xD;&#xA;    const float PI = 3.1415926535897932384626433832795;&#xD;&#xA;    const float RAY_LENGTH = 256.0f;&#xD;&#xA;    &#xD;&#xA;    // get the number of the current thread (0...1608)&#xD;&#xA;    uint renderNodeNum = local_coords;&#xD;&#xA;    // get the endpoint of the ray, it will be on a circle&#xD;&#xA;    endPoint.x = int(RAY_LENGTH * sin(float(renderNodeNum) * PI / 1024.0f)) + lightPos.x;&#xD;&#xA;    endPoint.y = int(RAY_LENGTH * cos(float(renderNodeNum) * PI / 1024.0f)) + lightPos.y;&#xD;&#xA;    &#xD;&#xA;    // vector approximation. Works, but has moire artifacts.&#xD;&#xA;    // I've also tried Bresenham's line algorithm, but it leaves a cross shape as the light fades which looks ugly.&#xD;&#xA;    vec2 dt = normalize(vec2(endPoint - lightPos));&#xD;&#xA;    vec2 t = vec2(lightPos);&#xD;&#xA;    for (int k = 0; k &lt; RAY_LENGTH; k++) {&#xD;&#xA;        coords.x = int(t.x);&#xD;&#xA;        coords.y = int(t.y);&#xD;&#xA;    &#xD;&#xA;        // calculate transparency&#xD;&#xA;        transpPixel = imageLoad(transpTex, coords);   &#xD;&#xA;        currentAlpha = (transpPixel.b + transpPixel.g * 10.0f + transpPixel.r * 100.0f) / 111.0f;&#xD;&#xA;        // calculate color&#xD;&#xA;        colorPixel = imageLoad(colorTex, coords);&#xD;&#xA;        lightRay.rgb = min(colorPixel.rgb, lightRay.rgb) - (1.0f - currentAlpha) - transmit; &#xD;&#xA;        currentOutPixel = imageLoad(img_output, coords);&#xD;&#xA;        currentOutPixel.rgb = max(currentOutPixel.rgb, lightRay.rgb);&#xD;&#xA;        currentOutPixel.a = lightRay.a;&#xD;&#xA;        // write color&#xD;&#xA;        imageStore(img_output, coords, currentOutPixel);&#xD;&#xA;&#xD;&#xA;        t += dt;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Heres is how it looks:&#xD;&#xA;&#xD;&#xA;[![Moire artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;Another example with coloured background that shows light propagation, with the same artifacts:&#xD;&#xA;&#xD;&#xA;[![same Moire artifacts here too][2]][2]&#xD;&#xA;&#xD;&#xA;So I need a better algorithm to draw these light rays (or any other method that is highly parallellizable on a compute shader) that does not leave out some pixels (the black spots in the pic). I could oversample the lightray (for example shoot twice as many rays), but this would be very expensive, there must be a cheaper solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/h7aHK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/on4OX.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15897" PostHistoryTypeId="1" PostId="5778" RevisionGUID="cd0f72d8-c3cb-42c9-a37f-4d1bd4c84204" CreationDate="2017-10-25T20:33:13.310" UserId="2437" Text="How to prevent moire artifacts in this light casting algorithm?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15898" PostHistoryTypeId="3" PostId="5778" RevisionGUID="cd0f72d8-c3cb-42c9-a37f-4d1bd4c84204" CreationDate="2017-10-25T20:33:13.310" UserId="2437" Text="|raytracing|glsl|2d|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15899" PostHistoryTypeId="2" PostId="5779" RevisionGUID="3db9c0ec-4c39-45c1-a401-3eee1e0709be" CreationDate="2017-10-25T21:11:16.110" UserId="7000" Text="I am trying to pass vertex attributes from my vertex shader -&gt; geometry shader and then to the fragment shader.&#xD;&#xA;&#xD;&#xA;Pretty simple program, here is my vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    uniform mat4 uModelViewMatrix;&#xD;&#xA;    uniform mat4 uProjMatrix;&#xD;&#xA;    &#xD;&#xA;    in vec4 aPosition;&#xD;&#xA;    &#xD;&#xA;    out vec3 modelPosition;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        modelPosition = aPosition.xyz;&#xD;&#xA;        gl_Position = uProjMatrix * uModelViewMatrix * aPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my geometry shader:&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (triangles) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 3) out;&#xD;&#xA;    &#xD;&#xA;    in vec3 modelPosition[];&#xD;&#xA;    &#xD;&#xA;    out vec3 gModelPosition[];&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        for (int i = 0; i &lt; gl_in.length(); i++)&#xD;&#xA;        {&#xD;&#xA;            gl_Position = gl_in[i].gl_Position;&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }&#xD;&#xA;        gModelPosition[0] = modelPosition[0];&#xD;&#xA;        gModelPosition[1] = modelPosition[1];&#xD;&#xA;        gModelPosition[2] = modelPosition[2];&#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here is my fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    in vec3 gModelPosition;&#xD;&#xA;    &#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        fragColor = vec4(gModelPosition, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I get the following error:&#xD;&#xA;&#xD;&#xA;    PROGRAM_LINKING_ERROR: error: &quot;gModelPosition&quot; not declared as input from previous stage&#xD;&#xA;&#xD;&#xA;If I just comment out the last line in the fragment shader, and say `fragColor = vec4(1.0);` it works fine. And I clearly **am** declaring gModelPosition as an input from the previous stage. &#xD;&#xA;&#xD;&#xA;Am I doing something wrong here?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15900" PostHistoryTypeId="1" PostId="5779" RevisionGUID="3db9c0ec-4c39-45c1-a401-3eee1e0709be" CreationDate="2017-10-25T21:11:16.110" UserId="7000" Text="Issue with declaring inputs to geometry shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15901" PostHistoryTypeId="3" PostId="5779" RevisionGUID="3db9c0ec-4c39-45c1-a401-3eee1e0709be" CreationDate="2017-10-25T21:11:16.110" UserId="7000" Text="|opengl|glsl|geometry-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15902" PostHistoryTypeId="12" PostId="5779" RevisionGUID="29c38e41-f37f-4a47-92e3-713cdee14091" CreationDate="2017-10-25T21:16:46.450" UserId="7000" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7000,&quot;DisplayName&quot;:&quot;Startec&quot;}]}" />
  <row Id="15903" PostHistoryTypeId="13" PostId="5779" RevisionGUID="1cfec7dc-5a7c-44e4-8240-406608566ea8" CreationDate="2017-10-25T22:16:11.890" UserId="7000" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7000,&quot;DisplayName&quot;:&quot;Startec&quot;}]}" />
  <row Id="15904" PostHistoryTypeId="2" PostId="5780" RevisionGUID="9f6d30b2-3f43-4db3-8dcd-66d3a658c48b" CreationDate="2017-10-25T22:17:27.853" UserId="7000" Text="The issue was that I declared `out vec3 gModelPosition[]` as an array in my geometry shader.&#xD;&#xA;&#xD;&#xA;It should have only been declared as a `vec3` (i.e. `out vec3 gModelPosition`)" ContentLicense="CC BY-SA 3.0" />
  <row Id="15905" PostHistoryTypeId="2" PostId="5781" RevisionGUID="5ac47cb6-2d90-462c-b846-7fdfa87d8720" CreationDate="2017-10-25T22:26:19.193" UserId="7541" Text="Suppose I took a picture of a whiteboard at an angle. If I could detect where the corners of the whiteboard are, what algorithms and linear projections could I use to convert this slanted view into a &quot;head on&quot; view?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15906" PostHistoryTypeId="1" PostId="5781" RevisionGUID="5ac47cb6-2d90-462c-b846-7fdfa87d8720" CreationDate="2017-10-25T22:26:19.193" UserId="7541" Text="How would I convert a picture of a slanted surface into a straight one?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15907" PostHistoryTypeId="3" PostId="5781" RevisionGUID="5ac47cb6-2d90-462c-b846-7fdfa87d8720" CreationDate="2017-10-25T22:26:19.193" UserId="7541" Text="|physically-based|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15909" PostHistoryTypeId="2" PostId="5782" RevisionGUID="eb022eec-afc8-4602-b81a-e7a949dff125" CreationDate="2017-10-26T05:17:38.033" UserId="1614" Text="In principle you avoid using scatter (casting) behavior with GPU. They have offered random output coordinate write out since only shader model 5 as a need for extreme situations. But you should as general rule write your GPU code in a &quot;gather&quot; fashion.&#xD;&#xA;&#xD;&#xA;The difference: the hardware threads are logically soft-locked to one output position in the render target. The scheduler decides to what rectangle (or cube) in the target buffers, the kicked thread group will output results.&#xD;&#xA;&#xD;&#xA;So you should work around the designated destination, and figure out the start; instead of working from some start and computing a dynamic destination.&#xD;&#xA;&#xD;&#xA;This way not only will you please the hardware by avoiding contention, and race conditions completely; but also you'll avoid holes." ContentLicense="CC BY-SA 3.0" />
  <row Id="15910" PostHistoryTypeId="5" PostId="3594" RevisionGUID="b3fa32fa-e888-424e-9141-01c766ddd940" CreationDate="2017-10-26T10:32:07.660" UserId="506" Comment="fixed GPUGems link" Text="Cone Step Mapping and Relaxed Cone Step Mapping appear to be very decent algorithms. These rely on a bit of preprocessing of the height field to create a 2D map used for more efficient lookups.&#xD;&#xA;&#xD;&#xA;http://www.lonesock.net/files/ConeStepMapping.pdf&#xD;&#xA;https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch18.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="15911" PostHistoryTypeId="24" PostId="3594" RevisionGUID="b3fa32fa-e888-424e-9141-01c766ddd940" CreationDate="2017-10-26T10:32:07.660" Comment="Proposed by 506 approved by 4958, 209 edit id of 280" ContentLicense="CC BY-SA 3.0" />
  <row Id="15912" PostHistoryTypeId="6" PostId="5781" RevisionGUID="e89f0cb8-1328-45f1-8f34-05f973f9acaa" CreationDate="2017-10-26T10:32:18.233" UserId="6" Comment="Fixed tags" Text="|image-processing|projections|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15913" PostHistoryTypeId="24" PostId="5781" RevisionGUID="e89f0cb8-1328-45f1-8f34-05f973f9acaa" CreationDate="2017-10-26T10:32:18.233" Comment="Proposed by 6 approved by 4958, 209 edit id of 281" ContentLicense="CC BY-SA 3.0" />
  <row Id="15915" PostHistoryTypeId="5" PostId="5707" RevisionGUID="b52de8d0-0c27-486e-91da-704e4c759f58" CreationDate="2017-10-27T03:31:07.743" UserId="-1" Comment="Sharpening does have a direct kernel method. https://en.wikipedia.org/wiki/Kernel_(image_processing)" Text="Why not just do them one after the other?&#xD;&#xA;&#xD;&#xA;Img = (Img * median) * sharpen;&#xD;&#xA;&#xD;&#xA;I think you should look into how these filter operations actually work before attempting to use them. It's pretty simple, use wikipedia or even any image processing textbook. Even the Matlab docs have good explanations.&#xD;&#xA;&#xD;&#xA;Median filtering is a **non linear filtering operation** which means that there is no fixed **kernel** function for it. You may define a neighborhood size but other than that, nope, no kernel. Have you looked into how it works? I dont know how you could generate a &quot;kernel&quot; for a non-linear filtering operation.&#xD;&#xA;&#xD;&#xA;Maybe a basic refresher in Image Processing is in order? Perhaps even going over basics of Signal Processing / DSP? I would suggest looking over 2D filtering if you can." ContentLicense="CC BY-SA 3.0" />
  <row Id="15916" PostHistoryTypeId="24" PostId="5707" RevisionGUID="b52de8d0-0c27-486e-91da-704e4c759f58" CreationDate="2017-10-27T03:31:07.743" Comment="Proposed by anonymous approved by 209, 182 edit id of 278" ContentLicense="CC BY-SA 3.0" />
  <row Id="15917" PostHistoryTypeId="5" PostId="41" RevisionGUID="feb265e3-eed0-47c8-b33d-fa2e3d687816" CreationDate="2017-10-27T03:31:26.673" UserId="5108" Comment="fix grammatical errors" Text="In convolution, two mathematical functions are combined to produce a third function. In image processing functions are usually called kernels. A kernel is nothing more than a (square) array of pixels (a small image so to speak). Usually, the values in the kernel add up to one. This is to make sure no energy is added or removed from the image after the operation.&#xD;&#xA;&#xD;&#xA;Specifically, a Gaussian kernel (used for Gaussian blur) is a square array of pixels where the pixel values correspond to the values of a Gaussian curve (in 2D).&#xD;&#xA;&#xD;&#xA;[![Image linked from http://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm][1]][1]&#xD;&#xA;&#xD;&#xA;Each pixel in the image gets multiplied by the Gaussian kernel. This is done by placing the center pixel of the kernel on the image pixel and multiplying the values in the original image with the pixels in the kernel that overlap. The values resulting from these multiplications are added up and that result is used for the value at the destination pixel. Looking at the image, you would multiply the value at (0,0) in the input array by the value at (i) in the kernel array, the value at (1,0) in the input array by the value at (h) in the kernel array, and so on. and then add all these values to get the value for (1,1) at the output image.&#xD;&#xA;&#xD;&#xA;[![Image linked from http://www.songho.ca/dsp/convolution/convolution.html][2]][2]&#xD;&#xA;&#xD;&#xA;To answer your second question first, the larger the kernel, the more expensive the operation. So, the larger the radius of the blur, the longer the operation will take.&#xD;&#xA;&#xD;&#xA;To answer your first question, as explained above, convolution can be done by multiplying each input pixel with the entire kernel. However, if the kernel is symmetrical (which a Gaussian kernel is) you can also multiply each axis (x and y) independently, which will decrease the total number of multiplications. In proper mathematical terms, if a matrix is separable it can be decomposed into (M×1) and (1×N) matrices. For the Gaussian kernel above this means you can also use the following kernels:&#xD;&#xA;&#xD;&#xA;$$\frac1{256}\cdot\begin{bmatrix}&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1\\&#xD;&#xA;4&amp;16&amp;24&amp;16&amp;4\\&#xD;&#xA;6&amp;24&amp;36&amp;24&amp;6\\&#xD;&#xA;4&amp;16&amp;24&amp;16&amp;4\\&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\frac1{256}\cdot\begin{bmatrix}&#xD;&#xA;1\\4\\6\\4\\1&#xD;&#xA;\end{bmatrix}\cdot\begin{bmatrix}&#xD;&#xA;1&amp;4&amp;6&amp;4&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You would now multiply each pixel in the input image with both kernels and add the resulting values to get the value for the output pixel.&#xD;&#xA;&#xD;&#xA;For more information on how to see if a kernel is separable, follow this [link][4].&#xD;&#xA;&#xD;&#xA;Edit: the two kernels shown above use slightly different values. This is because the (sigma) parameter used for the Gaussian curve to create these kernels were slightly different in both cases. For an explanation on which parameters influence the shape of the Gaussian curve and thus the values in the kernel follow this [link][5]&#xD;&#xA;&#xD;&#xA;Edit: in the second image above it says the kernel that is used is flipped. This of course only makes any difference if the kernel you use is not symmetric. The reason why you need to flip the kernel has to do with the mathematical properties of the convolution operation (see [link][6] for a more in depth explanation on convolution). Simply put: if you would not flip the kernel, the result of the convolution operation will be flipped. By flipping the kernel, you get the correct result.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Qc4Mq.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/bRN2c.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UsU96.gif&#xD;&#xA;  [4]: https://stackoverflow.com/questions/5886529/how-can-i-determine-if-my-convolution-is-separable&#xD;&#xA;  [5]: http://dev.theomader.com/gaussian-kernel-calculator/&#xD;&#xA;  [6]: http://songho.ca/dsp/convolution/convolution.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="15918" PostHistoryTypeId="24" PostId="41" RevisionGUID="feb265e3-eed0-47c8-b33d-fa2e3d687816" CreationDate="2017-10-27T03:31:26.673" Comment="Proposed by 5108 approved by 48, 182 edit id of 283" ContentLicense="CC BY-SA 3.0" />
  <row Id="15923" PostHistoryTypeId="5" PostId="39" RevisionGUID="ed81cc79-2fef-4164-9457-3ecdd6c9cc96" CreationDate="2017-10-27T10:08:05.500" UserId="5108" Comment="add more relevant tags" Text="I've read that blur is done in real time graphics by doing it on one axis and then the other.&#xD;&#xA;&#xD;&#xA;I've done a bit of convolution in 1D in the past but I am not super comfortable with it, nor know what to convolve in this case exactly.&#xD;&#xA;&#xD;&#xA;Can anyone explain in plain terms how a 2D Gaussian Blur of an image is done?&#xD;&#xA;&#xD;&#xA;I've also heard that the radius of the Blur can impact the performance. Is that due to having to do a larger convolution?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="15924" PostHistoryTypeId="6" PostId="39" RevisionGUID="ed81cc79-2fef-4164-9457-3ecdd6c9cc96" CreationDate="2017-10-27T10:08:05.500" UserId="5108" Comment="add more relevant tags" Text="|texture|image-processing|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15925" PostHistoryTypeId="24" PostId="39" RevisionGUID="ed81cc79-2fef-4164-9457-3ecdd6c9cc96" CreationDate="2017-10-27T10:08:05.500" Comment="Proposed by 5108 approved by 48, 209 edit id of 282" ContentLicense="CC BY-SA 3.0" />
  <row Id="15926" PostHistoryTypeId="50" PostId="4760" RevisionGUID="8653fa99-312b-406d-a7da-673c205db35d" CreationDate="2017-10-27T13:41:48.040" UserId="-1" />
  <row Id="15927" PostHistoryTypeId="2" PostId="5784" RevisionGUID="ef651aa5-66b0-466d-87e7-d5602056a4e8" CreationDate="2017-10-27T14:17:11.860" UserId="7550" Text="Why do red, green, and blue combinations can create all the visible colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15928" PostHistoryTypeId="1" PostId="5784" RevisionGUID="ef651aa5-66b0-466d-87e7-d5602056a4e8" CreationDate="2017-10-27T14:17:11.860" UserId="7550" Text="Why do red, green, and blue create all the colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15929" PostHistoryTypeId="3" PostId="5784" RevisionGUID="ef651aa5-66b0-466d-87e7-d5602056a4e8" CreationDate="2017-10-27T14:17:11.860" UserId="7550" Text="|color|color-science|color-separation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15930" PostHistoryTypeId="5" PostId="5784" RevisionGUID="f173e6d1-55fb-4730-965e-461e939d98b1" CreationDate="2017-10-27T14:38:54.810" UserId="7550" Comment="added 1 character in body" Text="Why do red, green, and blue combinations can make up all the visible colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15931" PostHistoryTypeId="4" PostId="5784" RevisionGUID="f173e6d1-55fb-4730-965e-461e939d98b1" CreationDate="2017-10-27T14:38:54.810" UserId="7550" Comment="added 1 character in body" Text="Why do red, green, and blue make up all the colors?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15932" PostHistoryTypeId="2" PostId="5785" RevisionGUID="b6eda15c-9cea-4009-8bf2-15da9435e026" CreationDate="2017-10-27T14:55:16.743" UserId="137" Text="Mankind is trichromatic. Which mean we have 3 different kinds of color receptors (better known as [cones cells][1]) each sensitive to a different set of wavelengths: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;image source: [wikipedia][3]&#xD;&#xA;&#xD;&#xA;So it only takes 3 different monochromatic stimuli to fool our eye into thinking it sees a color that is the same as another. Red Green and Blue are good fits to the peaks of the frequency response curves of each type of color receptor.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cone_cell&#xD;&#xA;  [2]: https://i.stack.imgur.com/LucVA.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/File:Cone-fundamentals-with-srgb-spectrum.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15933" PostHistoryTypeId="2" PostId="5786" RevisionGUID="186550a6-83a3-481b-a442-f5f2034faee7" CreationDate="2017-10-27T15:07:10.777" UserId="182" Text="Let's reminds ourselves what light is.&#xD;&#xA;&#xD;&#xA;Radio waves, micro waves, X rays and gamma rays are all [electromagnetic radiation][1] and they only differ by their frequency. It just so happens that the human eye is able to detect electromagnetic radiation between ~400nm and ~800nm, which we perceive as light.&#xD;&#xA;&#xD;&#xA;The 400nm end is perceived as violet and the 800nm end is perceived as red, with the colors of the rainbow in between. A ray of light can be a mix of any of those frequencies, and when light interacts with matter, some frequencies are absorbed while other might not: this is what we perceive as the colors of objects around us.&#xD;&#xA;&#xD;&#xA;The eye is not able to distinguish every single frequency though. While the ear for example, is able to distinguish between a lot of sound frequencies, and we can identify voices and instruments when listening to a song.&#xD;&#xA;&#xD;&#xA;The eye on the opposite, can generally only detect *four* ranges of frequencies. In the retina, [photo-receptors][2] called &quot;[rods][3]&quot; detect most frequencies of the visible light, without being able to tell them apart. They are responsible for our perception of brightness.&#xD;&#xA;Another kind of photo-receptors called &quot;[cones][4]&quot; exist in three specializations. They detect a narrower range of frequencies, and some of them are more sensitive to the frequencies around red, some to the frequencies around green, and the last ones to the frequencies around blue.&#xD;&#xA;&#xD;&#xA;Because they detect a range, they cannot tell the difference between two frequencies within that range, and they cannot tell the difference between a monochromatic light and a mix of frequencies within that range either. The visual system only has the inputs from those three detectors and reconstruct a perception of color with them.&#xD;&#xA;&#xD;&#xA;For this reason, the eye cannot tell the difference between a white light made of all the frequencies of the visible light, and the simple mix of only red green and blue lights.&#xD;&#xA;&#xD;&#xA;By the way, rods are a lot more sensitive than cones, and that's why we don't perceive colors in the night.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Electromagnetic_radiation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photoreceptor_cell&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Rod_cell&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Cone_cell" ContentLicense="CC BY-SA 3.0" />
  <row Id="15934" PostHistoryTypeId="5" PostId="5786" RevisionGUID="8739ed08-691a-4586-87cc-9bde9c63e14e" CreationDate="2017-10-27T15:14:04.300" UserId="182" Comment="added 50 characters in body" Text="Let's reminds ourselves what light is.&#xD;&#xA;&#xD;&#xA;Radio waves, micro waves, X rays and gamma rays are all [electromagnetic radiation][1] and they only differ by their frequency. It just so happens that the human eye is able to detect electromagnetic radiation between ~400nm and ~800nm, which we perceive as light.&#xD;&#xA;&#xD;&#xA;The 400nm end is perceived as violet and the 800nm end is perceived as red, with the colors of the rainbow in between. A ray of light can be a mix of any of those frequencies, and when light interacts with matter, some frequencies are absorbed while other might not: this is what we perceive as the colors of objects around us.&#xD;&#xA;&#xD;&#xA;Unlike the ear though, which is able to distinguish between a lot of sound frequencies (we can identify individual notes, voices and instruments when listening to a song), the eye is not able to distinguish every single frequency. It can generally only detect *four* ranges of frequencies (there are exceptions like daltonism or mutations).&#xD;&#xA;&#xD;&#xA;In the retina, [photo-receptors][2] called &quot;[rods][3]&quot; detect most frequencies of the visible light, without being able to tell them apart. They are responsible for our perception of brightness.&#xD;&#xA;Another kind of photo-receptors called &quot;[cones][4]&quot; exist in three specializations. They detect a narrower range of frequencies, and some of them are more sensitive to the frequencies around red, some to the frequencies around green, and the last ones to the frequencies around blue.&#xD;&#xA;&#xD;&#xA;Because they detect a range, they cannot tell the difference between two frequencies within that range, and they cannot tell the difference between a monochromatic light and a mix of frequencies within that range either. The visual system only has the inputs from those three detectors and reconstruct a perception of color with them.&#xD;&#xA;&#xD;&#xA;For this reason, the eye cannot tell the difference between a white light made of all the frequencies of the visible light, and the simple mix of only red green and blue lights. Thus, with only three colors, we can reconstruct all the colors we can see.&#xD;&#xA;&#xD;&#xA;By the way, rods are a lot more sensitive than cones, and that's why we don't perceive colors in the night.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Electromagnetic_radiation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photoreceptor_cell&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Rod_cell&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Cone_cell" ContentLicense="CC BY-SA 3.0" />
  <row Id="15935" PostHistoryTypeId="2" PostId="5787" RevisionGUID="9fb90bb3-88f5-4659-9788-065ef99a8409" CreationDate="2017-10-27T15:19:35.053" UserId="5256" Text="Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i$) = $G1(w_o)G1(w_i)$&#xD;&#xA;&#xD;&#xA;We can write the masking-shadowing function as the ratio of visible microfacet area to total forward facing microfacet area:&#xD;&#xA;&#xD;&#xA;$G1(w)$ $=$ $\Lambda^+(w) - \Lambda^-(w)\over \Lambda^+(w)$&#xD;&#xA;&#xD;&#xA;Shadow-masking functions are traditionally expressed in terms of auxiliary function $\Lambda(w)$, which measures invisible masked microfacet area per visible microfacet area.&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $\Lambda^-(w)\over \Lambda^+(w)-\Lambda^-(w)$&#xD;&#xA;&#xD;&#xA;The `Lambda()` function computes this. it's implementation is specific to each microfacet distribution. &#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w) = -1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this derived, since it is specific to each NDF? Can explain the derivation and theory step-by-step?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15936" PostHistoryTypeId="1" PostId="5787" RevisionGUID="9fb90bb3-88f5-4659-9788-065ef99a8409" CreationDate="2017-10-27T15:19:35.053" UserId="5256" Text="Trowbridge-Reitz shadow masking auxillary function" ContentLicense="CC BY-SA 3.0" />
  <row Id="15937" PostHistoryTypeId="3" PostId="5787" RevisionGUID="9fb90bb3-88f5-4659-9788-065ef99a8409" CreationDate="2017-10-27T15:19:35.053" UserId="5256" Text="|pbr|ggx|ndf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15938" PostHistoryTypeId="5" PostId="5786" RevisionGUID="ab88e25a-2169-4d63-a5e4-2752c383ef3e" CreationDate="2017-10-27T15:20:41.337" UserId="182" Comment="added 50 characters in body" Text="Let's reminds ourselves what light is.&#xD;&#xA;&#xD;&#xA;Radio waves, micro waves, X rays and gamma rays are all [electromagnetic radiation][1] and they only differ by their frequency. It just so happens that the human eye is able to detect electromagnetic radiation between ~400nm and ~800nm, which we perceive as light. The 400nm end is perceived as violet and the 800nm end is perceived as red, with the colors of the rainbow in between.&#xD;&#xA;&#xD;&#xA;A ray of light can be a mix of any of those frequencies, and when light interacts with matter, some frequencies are absorbed while other might not: this is what we perceive as the colors of objects around us. Unlike the ear though, which is able to distinguish between a lot of sound frequencies (we can identify individual notes, voices and instruments when listening to a song), the eye is not able to distinguish every single frequency. It can generally only detect *four ranges* of frequencies (there are exceptions like daltonism or mutations).&#xD;&#xA;&#xD;&#xA;This happens in the retina, where there are several kinds of [photo-receptors][2]. A first kind, called &quot;[rods][3]&quot;, detects most frequencies of the visible light, without being able to tell them apart. They are responsible for our perception of brightness.&#xD;&#xA;&#xD;&#xA;A second kind of photo-receptors, called &quot;[cones][4]&quot;, exists in three specializations. They detect a narrower range of frequencies, and some of them are more sensitive to the frequencies around red, some to the frequencies around green, and the last ones to the frequencies around blue.&#xD;&#xA;&#xD;&#xA;Because they detect a *range of frequencies*, they cannot tell the difference between two frequencies within that range, and they cannot tell the difference between a monochromatic light and a mix of frequencies within that range either. The visual system only has the inputs from those three detectors and reconstruct a perception of color with them.&#xD;&#xA;&#xD;&#xA;For this reason, the eye cannot tell the difference between a white light made of all the frequencies of the visible light, and the simple mix of only red green and blue lights. Thus, with only three colors, we can reconstruct all the colors we can see.&#xD;&#xA;&#xD;&#xA;By the way, rods are a lot more sensitive than cones, and that's why we don't perceive colors in the night.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Electromagnetic_radiation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photoreceptor_cell&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Rod_cell&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Cone_cell" ContentLicense="CC BY-SA 3.0" />
  <row Id="15939" PostHistoryTypeId="5" PostId="5787" RevisionGUID="b0e6f000-a14c-4828-bfd6-90c9e35e858c" CreationDate="2017-10-27T17:47:25.767" UserId="5256" Comment="added 8 characters in body" Text="Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i$) = $G1(w_o)G1(w_i)$&#xD;&#xA;&#xD;&#xA;We can write the masking-shadowing function as the ratio of visible microfacet area to total forward facing microfacet area:&#xD;&#xA;&#xD;&#xA;$G1(w)$ $=$ $\Lambda^+(w) - \Lambda^-(w)\over \Lambda^+(w)$&#xD;&#xA;&#xD;&#xA;Shadow-masking functions are traditionally expressed in terms of auxiliary function $\Lambda(w)$, which measures invisible masked microfacet area per visible microfacet area.&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $\Lambda^-(w)\over \Lambda^+(w)-\Lambda^-(w)$&#xD;&#xA;&#xD;&#xA;The `Lambda()` function computes this. it's implementation is specific to each microfacet distribution. &#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w) = -1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this derived, since it is specific to each NDF? Can someone explain the derivation and theory step-by-step?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15940" PostHistoryTypeId="5" PostId="5787" RevisionGUID="e8f2b93e-89d9-4252-b2c0-3203e13219ff" CreationDate="2017-10-27T18:03:01.870" UserId="5256" Comment="added 4 characters in body" Text="Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i$) = $G1(w_o)G1(w_i)$&#xD;&#xA;&#xD;&#xA;We can write the masking-shadowing function as the ratio of visible microfacet area to total forward facing microfacet area:&#xD;&#xA;&#xD;&#xA;$G1(w)$ $=$ $\Lambda^+(w) - \Lambda^-(w)\over \Lambda^+(w)$&#xD;&#xA;&#xD;&#xA;Shadow-masking functions are traditionally expressed in terms of auxiliary function $\Lambda(w)$, which measures invisible masked microfacet area per visible microfacet area.&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $\Lambda^-(w)\over \Lambda^+(w)-\Lambda^-(w)$&#xD;&#xA;&#xD;&#xA;The `Lambda()` function computes this. it's implementation is specific to each microfacet distribution. &#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $-1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this derived, since it is specific to each NDF? Can someone explain the derivation and theory step-by-step?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15941" PostHistoryTypeId="4" PostId="5787" RevisionGUID="67c52c4f-a2e6-4d45-9a30-a00fdd0d160f" CreationDate="2017-10-27T18:16:07.467" UserId="5256" Comment="edited title" Text="Trowbridge-Reitz shadow masking function" ContentLicense="CC BY-SA 3.0" />
  <row Id="15942" PostHistoryTypeId="5" PostId="5785" RevisionGUID="d8db943c-53fa-48c5-b2cd-23d6bd25afe7" CreationDate="2017-10-27T21:56:56.383" UserId="48" Comment="grammar, wording" Text="Humans are trichromatic, which means we have 3 different kinds of color receptors (better known as [cone cells][1]), each sensitive to a different set of wavelengths: &#xD;&#xA;&#xD;&#xA;[![frequency responses of different cone cells][2]][2]  &#xD;&#xA;Image source: [wikipedia][3]&#xD;&#xA;&#xD;&#xA;So it only takes 3 different monochromatic stimuli to fool our eye into thinking it sees a color that is the same as another. Red, green, and blue are good fits to the peaks of the frequency response curves of each type of color receptor.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cone_cell&#xD;&#xA;  [2]: https://i.stack.imgur.com/LucVA.png&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/File:Cone-fundamentals-with-srgb-spectrum.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15944" PostHistoryTypeId="5" PostId="2325" RevisionGUID="cafdda36-d40d-4be8-9909-a705cc495a0f" CreationDate="2017-10-28T03:54:50.013" UserId="310" Comment="added 1 character in body" Text="In order to understand Russian Roulette, let's look at a very basic backward path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely mathematically unbiased, bounces *should* go to infinity. But this is unrealistic, and as you noted, not visually necessary; for most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.&#xD;&#xA;&#xD;&#xA;So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.&#xD;&#xA;&#xD;&#xA;That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20. &#xD;&#xA;[![2 Bounces from Disney's Big Hero 6][1]][1]&#xD;&#xA;[![9 Bounces from Disney's Big Hero 6][2]][2]&#xD;&#xA;&#xD;&#xA;If we choose too low, the image will be visibly biased. But if we choose too high, we're wasting computation energy and time.&#xD;&#xA;&#xD;&#xA;One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias. &#xD;&#xA;&#xD;&#xA;Clamping after a threshold, will *work*, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.&#xD;&#xA;&#xD;&#xA;Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;            // Russian Roulette&#xD;&#xA;            // Randomly terminate a path with a probability inversely equal to the throughput&#xD;&#xA;            float p = std::max(throughput.x, std::max(throughput.y, throughput.z));&#xD;&#xA;            if (sampler-&gt;NextFloat() &gt; p) {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            // Add the energy we 'lose' by randomly terminating paths&#xD;&#xA;            throughput *= 1 / p;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So paths with low throughput that won't contribute much to the scene are more likely to be terminated. &#xD;&#xA;&#xD;&#xA;If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To answer your last questions:&#xD;&#xA;&#xD;&#xA; 1. Does Russian Roulette give an unbiased result?&#xD;&#xA;   - Yes&#xD;&#xA; 2. Is Russian Roulette necessary for an unbiased result?&#xD;&#xA;   - Depends on what you mean by unbiased. If you mean mathematically, then yes. However, if you mean visually, then no. You just have to choose you max path depth and cutoff threshold very very carefully. This can be very tedious since it can change from scene to scene.&#xD;&#xA; 3. Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?&#xD;&#xA;   - If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still mathematically biased. To be completely unbiased, it must be random.&#xD;&#xA; 4. If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?&#xD;&#xA;   - Russian Roulette only stops the bouncing. It doesn't remove the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason *not* to use it.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ikXSo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BPiZ7.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15946" PostHistoryTypeId="5" PostId="5786" RevisionGUID="666e7f1b-480f-4c7b-a91b-f1edc3694b5b" CreationDate="2017-10-28T07:37:20.117" UserId="182" Comment="deleted 1 character in body" Text="Let's reminds ourselves what light is.&#xD;&#xA;&#xD;&#xA;Radio waves, micro waves, X rays and gamma rays are all [electromagnetic radiation][1] and they only differ by their frequency. It just so happens that the human eye is able to detect electromagnetic radiation between ~400nm and ~800nm, which we perceive as light. The 400nm end is perceived as violet and the 800nm end is perceived as red, with the colors of the rainbow in between.&#xD;&#xA;&#xD;&#xA;A ray of light can be a mix of any of those frequencies, and when light interacts with matter, some frequencies are absorbed while other might not: this is what we perceive as the colors of objects around us. Unlike the ear though, which is able to distinguish between a lot of sound frequencies (we can identify individual notes, voices and instruments when listening to a song), the eye is not able to distinguish every single frequency. It can generally only detect *four ranges* of frequencies (there are exceptions like daltonism or mutations).&#xD;&#xA;&#xD;&#xA;This happens in the retina, where there are several kinds of [photo-receptors][2]. A first kind, called &quot;[rods][3]&quot;, detects most frequencies of the visible light, without being able to tell them apart. They are responsible for our perception of brightness.&#xD;&#xA;&#xD;&#xA;A second kind of photo-receptors, called &quot;[cones][4]&quot;, exists in three specializations. They detect a narrower range of frequencies, and some of them are more sensitive to the frequencies around red, some to the frequencies around green, and the last ones to the frequencies around blue.&#xD;&#xA;&#xD;&#xA;Because they detect a *range of frequencies*, they cannot tell the difference between two frequencies within that range, and they cannot tell the difference between a monochromatic light and a mix of frequencies within that range either. The visual system only has the inputs from those three detectors and reconstruct a perception of color with them.&#xD;&#xA;&#xD;&#xA;For this reason, the eye cannot tell the difference between a white light made of all the frequencies of the visible light, and the simple mix of only red green and blue lights. Thus, with only three colors, we can reconstruct _most_ colors we can see.&#xD;&#xA;&#xD;&#xA;By the way, rods are a lot more sensitive than cones, and that's why we don't perceive colors in the night.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Electromagnetic_radiation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Photoreceptor_cell&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Rod_cell&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Cone_cell" ContentLicense="CC BY-SA 3.0" />
  <row Id="15950" PostHistoryTypeId="2" PostId="5789" RevisionGUID="259cbc8c-c28c-4c6f-8463-56b15e78a022" CreationDate="2017-10-28T11:47:04.403" UserId="7560" Text="**They don't.**&#xD;&#xA;&#xD;&#xA;The problem with the diagrams representing the RGB gamut is that they're presented on RGB displays. They obviously cannot show you what they cannot show you.&#xD;&#xA;&#xD;&#xA;[![RGB gamut][1]][1]&#xD;&#xA;&#xD;&#xA;The region outside of the triangle cannot be shown on your screen. For example, RGB cannot display a true, deep cyan.&#xD;&#xA;&#xD;&#xA;To see what cyan can look like, you could stare at the white dot on this drawing for at least 30 seconds (2 minutes are recommended) and then slowly move your head towards a white wall:&#xD;&#xA;&#xD;&#xA;[![cyan illusion][2]][2]&#xD;&#xA;&#xD;&#xA;Similarly, RGB displays cannot show deep, saturated oranges or browns.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QIpkW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/upswE.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15951" PostHistoryTypeId="5" PostId="5789" RevisionGUID="d30c95c1-1bc3-415e-ae3e-0b750fd7bd80" CreationDate="2017-10-28T12:27:13.477" UserId="7560" Comment="added 231 characters in body" Text="**They don't.**&#xD;&#xA;&#xD;&#xA;The problem with the diagrams representing the visible and RGB gamuts is that they're presented on RGB displays. They obviously cannot show you what they cannot show you : the area inside the parabola but outside of the triangle.&#xD;&#xA;&#xD;&#xA;[![RGB gamut][1]][1]&#xD;&#xA;&#xD;&#xA;The region outside of the triangle cannot be shown on your screen in a faithful way. For example, RGB cannot display a true, deep cyan. All you see is an approximation using green and blue. Some diagrams don't even try and only show a gray area :&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;To see what cyan can look like, you could stare at the white dot on this drawing for at least 30 seconds (2 minutes are recommended) and then slowly move your head towards a white wall:&#xD;&#xA;&#xD;&#xA;[![cyan illusion][3]][3]&#xD;&#xA;&#xD;&#xA;Similarly, RGB displays cannot show deep, saturated oranges or browns.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QIpkW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DGyOe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/upswE.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="15952" PostHistoryTypeId="2" PostId="5790" RevisionGUID="64ec5198-c2ef-41e9-a942-85b4e194d567" CreationDate="2017-10-28T14:30:44.827" UserId="7564" Text="One more thing: &quot;violet&quot; and &quot;purple&quot; *are not the same color.*  Violet is a pure color around 400 nm; but purple is a combination of red and blue.  To our not-quite-perfect human eyes they look the same.&#xD;&#xA;&#xD;&#xA;If you pass a beam of pure violet through a triangular prism, the light will be bent but not broken up into components.  If you then shine a beam of purple through the same prism, it will be separated into a blue and a red beam, with different amounts of &quot;bend&quot; to them." ContentLicense="CC BY-SA 3.0" />
  <row Id="15954" PostHistoryTypeId="5" PostId="39" RevisionGUID="77b02959-56e4-42e0-bd20-0161cf55f229" CreationDate="2017-10-28T19:17:23.423" UserId="6" Comment="Removing unnecessary chatter. Fixed tags." Text="I've read that blur is done in real time graphics by doing it on one axis and then the other.&#xD;&#xA;&#xD;&#xA;I've done a bit of convolution in 1D in the past but I am not super comfortable with it, nor know what to convolve in this case exactly.&#xD;&#xA;&#xD;&#xA;Can anyone explain in plain terms how a 2D Gaussian Blur of an image is done?&#xD;&#xA;&#xD;&#xA;I've also heard that the radius of the Blur can impact the performance. Is that due to having to do a larger convolution?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15955" PostHistoryTypeId="6" PostId="39" RevisionGUID="77b02959-56e4-42e0-bd20-0161cf55f229" CreationDate="2017-10-28T19:17:23.423" UserId="6" Comment="Removing unnecessary chatter. Fixed tags." Text="|image-processing|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15956" PostHistoryTypeId="24" PostId="39" RevisionGUID="77b02959-56e4-42e0-bd20-0161cf55f229" CreationDate="2017-10-28T19:17:23.423" Comment="Proposed by 6 approved by 4958, 231 edit id of 284" ContentLicense="CC BY-SA 3.0" />
  <row Id="15957" PostHistoryTypeId="2" PostId="5791" RevisionGUID="bbd99417-5bc7-471a-9531-d1cb5de6b996" CreationDate="2017-10-28T21:08:59.327" UserId="3411" Text="They don't. Aside from what others have said about the physical reasons not, from a practical computer graphics standpoint, representing either surface pigments or light sources with RGB color is insufficient to model colored lighting of a scene. For example there is no way to represent a material which is translucent or reflective only in a narrow band; you can only represent translucency or reflectivity of wide bands corresponding roughly to what the red, green, and blue cones in the human eye pick up. This actually matters for a lot of real-world colors in the pink/purple/violet family, which look radically different under different types of light, even different &quot;white&quot; light that looks identical when viewed on a white surface.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15960" PostHistoryTypeId="2" PostId="5792" RevisionGUID="a87bb073-2520-4ab3-bff2-5dc3c90c51ba" CreationDate="2017-10-29T01:47:28.557" UserId="7577" Text="So i am working through the book &quot;Raytracing in one weekend&quot;.&#xD;&#xA;At the point where i am at we want to check if a ray hits a sphere.&#xD;&#xA;For that we have the equation:&#xD;&#xA;&#xD;&#xA;    dot((A + t*B - C),(A + t*B - C)) = R*R&#xD;&#xA;&#xD;&#xA;Where A + t*B is a point on the ray, with A the start, B the direction and t how far along we went on the ray.&#xD;&#xA;&#xD;&#xA;To solve this the author transformed the equation to:&#xD;&#xA;&#xD;&#xA;    t*t*dot(B,B) + 2*t*dot(A-C,A-C) + dot(C,C) - R*R = 0&#xD;&#xA;&#xD;&#xA;Now i just can not understand how this transformation comes about. &#xD;&#xA;Simply multiplying this out seems to give a way different result.&#xD;&#xA;&#xD;&#xA;Is there some kind of vector math i'm missing here?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15961" PostHistoryTypeId="1" PostId="5792" RevisionGUID="a87bb073-2520-4ab3-bff2-5dc3c90c51ba" CreationDate="2017-10-29T01:47:28.557" UserId="7577" Text="Vector Math for Raytracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="15962" PostHistoryTypeId="3" PostId="5792" RevisionGUID="a87bb073-2520-4ab3-bff2-5dc3c90c51ba" CreationDate="2017-10-29T01:47:28.557" UserId="7577" Text="|raytracing|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15964" PostHistoryTypeId="2" PostId="5793" RevisionGUID="c73bc4a7-0664-4488-b14d-cc6c3635d681" CreationDate="2017-10-29T03:11:43.770" UserId="7578" Text="When trying to find the vanishing point of an image, why is it that the line from the center of the camera to the vanishing point is parallel to the original lines? &#xD;&#xA;&#xD;&#xA;What's the mathematical reasoning behind this? &#xD;&#xA;[![Diagram of vanishing point][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aiY3p.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15965" PostHistoryTypeId="1" PostId="5793" RevisionGUID="c73bc4a7-0664-4488-b14d-cc6c3635d681" CreationDate="2017-10-29T03:11:43.770" UserId="7578" Text="Why is the line from the camera to vanishing point parallel to the other parallel lines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15966" PostHistoryTypeId="3" PostId="5793" RevisionGUID="c73bc4a7-0664-4488-b14d-cc6c3635d681" CreationDate="2017-10-29T03:11:43.770" UserId="7578" Text="|image-processing|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15967" PostHistoryTypeId="5" PostId="5793" RevisionGUID="e7479748-7c80-4ffa-a2c7-55cd4d9c3ae4" CreationDate="2017-10-29T04:35:16.803" UserId="7578" Comment="added 15 characters in body" Text="When trying to find the vanishing point of an image, why is it that the vector from the center of the camera to the vanishing point is parallel to the parallel lines of the image? &#xD;&#xA;&#xD;&#xA;What's the mathematical reasoning behind this? &#xD;&#xA;[![Diagram of vanishing point][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aiY3p.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15975" PostHistoryTypeId="2" PostId="5795" RevisionGUID="eb2a463a-4683-4779-a977-2d7ef64b5bcc" CreationDate="2017-10-29T07:03:29.237" UserId="6046" Text="I think there might be a misprinting in the book or you missed a `B` in the middle term. I am getting this&#xD;&#xA;&#xD;&#xA;$((A-C) + tB).((A-C) + tB) = R.R$ &#xD;&#xA;&#xD;&#xA;`Let  A-C = Y`&#xD;&#xA;&#xD;&#xA;$(Y + tB).(Y + tB) = R.R$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$Y.Y + Y.tB + tB.Y + t^2B.B = R.R$&#xD;&#xA;&#xD;&#xA;Substituting back &#xD;&#xA;&#xD;&#xA;$(A-C).(A-C) + 2t * B.(A-C) + t^2B.B = R.R$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15976" PostHistoryTypeId="5" PostId="5795" RevisionGUID="e8c3096a-2dad-4e55-b788-83840996dbcd" CreationDate="2017-10-29T08:25:52.890" UserId="6046" Comment="added 42 characters in body" Text="I think there might be a misprinting in the book. I am getting this&#xD;&#xA;&#xD;&#xA;$((A-C) + tB).((A-C) + tB) = R.R$ &#xD;&#xA;&#xD;&#xA;`Let  A-C = Y`&#xD;&#xA;&#xD;&#xA;$(Y + tB).(Y + tB) = R.R$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$Y.Y + Y.tB + tB.Y + t^2B.B = R.R$&#xD;&#xA;&#xD;&#xA;Substituting back &#xD;&#xA;&#xD;&#xA;$(A-C).(A-C) + 2t * B.(A-C) + t^2B.B = R.R$&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15982" PostHistoryTypeId="2" PostId="5797" RevisionGUID="5c09fd9e-f2f0-43ec-b026-b4ceeaf1b7c1" CreationDate="2017-10-30T03:48:17.477" UserId="7334" Text="I want to do volume rendering using path tracing with a **absorption only** model. And my data is in a 3D grid, which in turned into a voxel medium in my renderer.&#xD;&#xA;&#xD;&#xA;However, I can't seem to be correct implementing the algorithm.&#xD;&#xA;&#xD;&#xA;According to [this note][1] (however pure absorption is not mentioned here), the radiance at point $x$, direction $\omega$, with **emission-absorption** model in a **homogeneous** medium is:&#xD;&#xA;&#xD;&#xA;$L(x,\omega) = \int_{x}^{y} \tau(x,x') \epsilon(x')dx + \tau(x,y)L_e(x,\omega)$&#xD;&#xA;&#xD;&#xA;where $\tau$ is the attenuation, y is a point on surface, and $\epsilon$ is emission at point $x'$.&#xD;&#xA;&#xD;&#xA;So I come up with the **heterogenous**, **absorption-only** equation as:&#xD;&#xA;&#xD;&#xA;$L(x, \omega) = \tau(x,y)L_e(x,\omega)$&#xD;&#xA;&#xD;&#xA;since I think the emission term should be omitted. However this equation seems not correct intuitively and do not give correct image.&#xD;&#xA;&#xD;&#xA;According to this equation, the radiance at every point $x'$ along the ray within the volume is not counted, which is where I think the problem lies.&#xD;&#xA;&#xD;&#xA;So **what is the correct heterogeneous volume path tracing equation?** &#xD;&#xA;&#xD;&#xA;I give more details of my implementation here. The scene is simply a **cornell box** where only a voxel medium is inside the box. I trace a ray from the eye(camera), and the ray go through the medium and intersect a surface(the wall). To simplify the procedure, I set `max_bounce` to **1** which means the path is &#xD;&#xA;`eye -&gt; medium -&gt; surface -&gt; light`.&#xD;&#xA;&#xD;&#xA;So the value of this sample is simply the *throughput of the medium* times *the throughput of the surface* times *direct light at surface intersection*.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;However I got the result image&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/hoK2f.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8Omkw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15983" PostHistoryTypeId="1" PostId="5797" RevisionGUID="5c09fd9e-f2f0-43ec-b026-b4ceeaf1b7c1" CreationDate="2017-10-30T03:48:17.477" UserId="7334" Text="How to do heterogeneous volume absorption using path tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15984" PostHistoryTypeId="3" PostId="5797" RevisionGUID="5c09fd9e-f2f0-43ec-b026-b4ceeaf1b7c1" CreationDate="2017-10-30T03:48:17.477" UserId="7334" Text="|pathtracing|volumetric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="15985" PostHistoryTypeId="5" PostId="5797" RevisionGUID="0be0b6d6-90c4-4f2c-8554-9777676f574d" CreationDate="2017-10-30T03:57:00.493" UserId="7334" Comment="added 40 characters in body" Text="I want to do volume rendering using path tracing with a **absorption only** model. And my data is in a 3D grid, which in turned into a voxel medium in my renderer.&#xD;&#xA;&#xD;&#xA;However, I can't seem to be correct implementing the algorithm.&#xD;&#xA;&#xD;&#xA;According to [this note][1] (however pure absorption is not mentioned here), the radiance at point $x$, direction $\omega$, with **emission-absorption** model in a **homogeneous** medium is:&#xD;&#xA;&#xD;&#xA;$L(x,\omega) = \int_{x}^{y} \tau(x,x') \epsilon(x')dx + \tau(x,y)L_e(x,\omega)$&#xD;&#xA;&#xD;&#xA;where $\tau$ is the attenuation, y is a point on surface, and $\epsilon$ is emission at point $x'$.&#xD;&#xA;&#xD;&#xA;So I come up with the **heterogenous**, **absorption-only** equation as:&#xD;&#xA;&#xD;&#xA;$L(x, \omega) = \tau(x,y)L_e(x,\omega)$&#xD;&#xA;&#xD;&#xA;since I think the emission term should be omitted. However this equation seems not correct intuitively and do not give correct image.&#xD;&#xA;&#xD;&#xA;According to this equation, the radiance at every point $x'$ along the ray within the volume is not counted, which is where I think the problem lies.&#xD;&#xA;&#xD;&#xA;So **what is the correct heterogeneous volume path tracing equation?**&#xD;&#xA;**How to derive the correct equation?**&#xD;&#xA;&#xD;&#xA;I give more details of my implementation here. The scene is simply a **cornell box** where only a voxel medium is inside the box. I trace a ray from the eye(camera), and the ray go through the medium and intersect a surface(the wall). To simplify the procedure, I set `max_bounce` to **1** which means the path is &#xD;&#xA;`eye -&gt; medium -&gt; surface -&gt; light`.&#xD;&#xA;&#xD;&#xA;So the value of this sample is simply the *throughput of the medium* times *the throughput of the surface* times *direct light at surface intersection*.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;However I got the result image&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/hoK2f.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8Omkw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15986" PostHistoryTypeId="5" PostId="5787" RevisionGUID="4b48cd1b-40e5-41b5-872a-b085b51ae90d" CreationDate="2017-10-30T05:16:11.200" UserId="5256" Comment="added 4 characters in body" Text="Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i)$ $=$ $G1(w_o)G1(w_i)$&#xD;&#xA;&#xD;&#xA;We can write the masking-shadowing function as the ratio of visible microfacet area to total forward facing microfacet area:&#xD;&#xA;&#xD;&#xA;$G1(w)$ $=$ $\Lambda^+(w) - \Lambda^-(w)\over \Lambda^+(w)$&#xD;&#xA;&#xD;&#xA;Shadow-masking functions are traditionally expressed in terms of auxiliary function $\Lambda(w)$, which measures invisible masked microfacet area per visible microfacet area.&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $\Lambda^-(w)\over \Lambda^+(w)-\Lambda^-(w)$&#xD;&#xA;&#xD;&#xA;The $\Lambda(w)$ function computes this. Its implementation is specific to each microfacet distribution. &#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $-1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this derived, since it is specific to each NDF? Can someone explain the derivation and theory step-by-step?" ContentLicense="CC BY-SA 3.0" />
  <row Id="15988" PostHistoryTypeId="5" PostId="5797" RevisionGUID="67460574-9c8f-47ad-9d5d-837f9d4e3381" CreationDate="2017-10-30T06:01:15.363" UserId="7334" Comment="edited body" Text="I want to do volume rendering using path tracing with a **absorption only** model. And my data is in a 3D grid, which is turned into a voxel medium in my renderer.&#xD;&#xA;&#xD;&#xA;However, I can't seem to be correct implementing the algorithm.&#xD;&#xA;&#xD;&#xA;According to [this note][1] (however absorption-only heterogeneous case is not mentioned here), the radiance at point $x$, direction $\omega$, with **emission-absorption** model in a **homogeneous** medium is:&#xD;&#xA;&#xD;&#xA;$L(x,\omega) = \int_{x}^{y} \tau(x,x') \epsilon(x')dx + \tau(x,y)L_e(x,\omega)$&#xD;&#xA;&#xD;&#xA;where $\tau$ is the attenuation, y is a point on surface, and $\epsilon$ is emission at point $x'$.&#xD;&#xA;&#xD;&#xA;So I come up with the **heterogenous**, **absorption-only** equation as:&#xD;&#xA;&#xD;&#xA;$L(x, \omega) = \tau(x,y)L_e(x,\omega)$&#xD;&#xA;&#xD;&#xA;since I think the emission term should be omitted. However this equation seems not correct intuitively and do not give correct image.&#xD;&#xA;&#xD;&#xA;According to this equation, the radiance at every point $x'$ along the ray within the volume is not counted, which is where I think the problem lies.&#xD;&#xA;&#xD;&#xA;So **what is the correct heterogeneous volume path tracing equation?**&#xD;&#xA;**How to derive the correct equation?**&#xD;&#xA;&#xD;&#xA;I give more details of my implementation here. The scene is simply a **cornell box** where only a voxel medium is inside the box. I trace a ray from the eye(camera), and the ray go through the medium and intersect a surface(the wall). To simplify the procedure, I set `max_bounce` to **1** which means the path is &#xD;&#xA;`eye -&gt; medium -&gt; surface -&gt; light`.&#xD;&#xA;&#xD;&#xA;So the value of this sample is simply the *throughput of the medium* times *the throughput of the surface* times *direct light at surface intersection*.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;However I got the result image&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/hoK2f.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8Omkw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="15989" PostHistoryTypeId="2" PostId="5798" RevisionGUID="238ca9c9-7972-4986-9acb-d25c66f97001" CreationDate="2017-10-30T10:35:14.210" UserId="137" Text="FYI every set of parallel lines will have their own vanishing point. The reason why there is usually only a single vanishing point (the most obvious one) talked about in an image is due to aesthetic choice.&#xD;&#xA;&#xD;&#xA;A perspective projection can be seen as a point projection of a 3D scene onto a 2D plane. The way to determine where a point in the 3D scene ends up on the 2D plane is to draw a line between the point and the camera (the sight line) and see where it intersects the projection target plane.&#xD;&#xA;&#xD;&#xA;To find the vanishing point of a set of parallel lines you can take a the limit of traveling on that line infinitely far. At the limit the sight line will be parallel to the line. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="15990" PostHistoryTypeId="2" PostId="5799" RevisionGUID="7331c763-3200-4588-aeb4-04e8f6fa1379" CreationDate="2017-10-30T12:45:56.897" UserId="6968" Text="&gt; is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically&#xD;&#xA;&#xD;&#xA;Yes, it's a pipe dream. A bicubic Bezier patch is an algebraic surface of degree 18. To intersect a ray with this surface, you have to find the roots of a polynomial of degree 18. There is no formula for these roots -- you have to find them by numerical methods. In fact, there are mathematical theorems telling us that there can never be formulae for roots of equations beyond degree 4. The math doesn't just say that the formulae not yet been found; it says that they never will be found, because they can't exist." ContentLicense="CC BY-SA 3.0" />
  <row Id="15991" PostHistoryTypeId="5" PostId="5799" RevisionGUID="45242f9d-8f13-4f55-9b0d-996b8a8d02e9" CreationDate="2017-10-30T12:54:24.293" UserId="6968" Comment="added 376 characters in body" Text="&gt; is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically&#xD;&#xA;&#xD;&#xA;Yes, it's a pipe dream. A bicubic Bezier patch is an algebraic surface of degree 18. To intersect a ray with this surface, you have to find the roots of a polynomial of degree 18. There is no formula for these roots -- you have to find them by numerical methods. In fact, there are mathematical theorems telling us that there can never be formulae for roots of equations beyond degree 4. The math doesn't just say that the formulae not yet been found; it says that they never will be found, because they can't exist.&#xD;&#xA;&#xD;&#xA;If you really want to do analytical (algebraic) ray-tracing of curvaceous shapes, you might try using Steiner patches. These have degree 4, so the ray-patch intersection can be computed by finding the roots of a polynomial of degree 4. There are formulae for finding these roots, but they're pretty nasty, and it's hard to write code that implements the formulae reliably." ContentLicense="CC BY-SA 3.0" />
  <row Id="15998" PostHistoryTypeId="5" PostId="5799" RevisionGUID="061e1e64-7373-4263-b2c1-48262a6b851f" CreationDate="2017-10-31T12:00:45.953" UserId="6968" Comment="added 5 characters in body" Text="&gt; is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically&#xD;&#xA;&#xD;&#xA;Yes, it's a pipe dream. A bicubic Bezier patch is an algebraic surface of degree 18. To intersect a ray with this surface, you have to find the roots of a polynomial of degree 18. There is no formula for these roots -- you have to find them by numerical methods. In fact, there are mathematical theorems telling us that there can never be formulae for roots of equations beyond degree 4. The math doesn't just say that the formulae have not yet been found; it says that they never will be found, because they can't exist.&#xD;&#xA;&#xD;&#xA;If you really want to do analytical (algebraic) ray-tracing of curvaceous shapes, you might try using Steiner patches. These have degree 4, so the ray-patch intersection can be computed by finding the roots of a polynomial of degree 4. There are formulae for finding these roots, but they're pretty nasty, and it's hard to write code that implements the formulae reliably." ContentLicense="CC BY-SA 3.0" />
  <row Id="15999" PostHistoryTypeId="2" PostId="5801" RevisionGUID="ea26c392-9c63-4469-ae38-25856cc2e998" CreationDate="2017-10-31T12:09:57.443" UserId="6968" Text="What you're looking for is called de Boor's algorithm. It lets you compute a point on a b-spline curve by doing a series of linear interpolation (LERP) calculations. So, it works very much like the de Casteljau algorithm for Bezier curves. In fact, the de Casteljau algorithm is a special case of de Boor'as algorithm.&#xD;&#xA;&#xD;&#xA;[A link][1]    &#xD;&#xA;[Another one][2]    &#xD;&#xA;[And another][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/De_Boor%27s_algorithm&#xD;&#xA;  [2]: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/de-Boor.html&#xD;&#xA;  [3]: http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node18.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="16000" PostHistoryTypeId="5" PostId="5801" RevisionGUID="6f53841a-9db9-4d6b-8214-be673954b295" CreationDate="2017-10-31T12:15:26.530" UserId="6968" Comment="deleted 1 character in body" Text="What you're looking for is called de Boor's algorithm. It lets you compute a point on a b-spline curve by doing a series of linear interpolation (LERP) calculations. So, it works very much like the de Casteljau algorithm for Bezier curves. In fact, the de Casteljau algorithm is a special case of de Boor's algorithm.&#xD;&#xA;&#xD;&#xA;[A link][1]    &#xD;&#xA;[Another one][2]    &#xD;&#xA;[And another][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/De_Boor%27s_algorithm&#xD;&#xA;  [2]: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/de-Boor.html&#xD;&#xA;  [3]: http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node18.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="16001" PostHistoryTypeId="50" PostId="4651" RevisionGUID="7da58e02-4b96-48d8-8770-241b9c2ce324" CreationDate="2017-10-31T12:43:54.390" UserId="-1" />
  <row Id="16002" PostHistoryTypeId="2" PostId="5802" RevisionGUID="26ca5867-d7da-436a-8aee-ac9c8c8edb65" CreationDate="2017-10-31T12:52:50.163" UserId="6968" Text="I use Powerpoint and various (expensive) CAD packages. I wrote Powerpoint macros (VBA code) to do some special things like draw the control polygons of Bezier curves. Then I use the standard Windows Snipping Tool to grab screen shots. Here are three examples:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BdBcH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wQaEx.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/bpywg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16003" PostHistoryTypeId="5" PostId="5802" RevisionGUID="33d44053-a1df-4556-8509-0b3701ec8cc4" CreationDate="2017-10-31T13:09:11.350" UserId="6968" Comment="added 86 characters in body" Text="I use Powerpoint and various (expensive) CAD packages. I wrote Powerpoint macros (VBA code) to do some special things like draw the control polygons of Bezier curves. Then I use the standard Windows Snipping Tool to grab screen shots. Here are some examples:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BdBcH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wQaEx.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/bpywg.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/EUeLW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16004" PostHistoryTypeId="5" PostId="5802" RevisionGUID="169a4123-bdb6-4aa8-ad79-f751b54e42cb" CreationDate="2017-10-31T13:21:42.220" UserId="6968" Comment="added 637 characters in body" Text="I use Powerpoint and various (expensive) CAD packages. I wrote Powerpoint macros (VBA code) to do some special things like draw the control polygons of Bezier curves. Then I use the standard Windows Snipping Tool to grab screen shots. Here are some examples:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;And some further examples from Math.SE&#xD;&#xA;&#xD;&#xA;[One][5]    &#xD;&#xA;[Two][6]     &#xD;&#xA;[Three][7]     &#xD;&#xA;[Four][8]     &#xD;&#xA;[Five][9]     &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BdBcH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wQaEx.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/bpywg.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/EUeLW.png&#xD;&#xA;  [5]: https://math.stackexchange.com/questions/2230316/ellipse-tangent-to-two-circles&#xD;&#xA;  [6]: https://math.stackexchange.com/questions/2200952/intersection-of-cones-tangent-to-a-common-sphere&#xD;&#xA;  [7]: https://math.stackexchange.com/questions/482063/parabolas-through-three-points&#xD;&#xA;  [8]: https://math.stackexchange.com/questions/1601158/how-can-we-find-geodesics-on-a-one-sheet-hyperboloid/1606820#1606820&#xD;&#xA;  [9]: https://math.stackexchange.com/questions/465782/control-points-of-offset-bezier-curve/467038#467038" ContentLicense="CC BY-SA 3.0" />
  <row Id="16005" PostHistoryTypeId="5" PostId="5799" RevisionGUID="0ea4def2-7171-4603-b288-e40db5eb5b3c" CreationDate="2017-10-31T13:43:51.960" UserId="6968" Comment="added 197 characters in body" Text="&gt; is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically&#xD;&#xA;&#xD;&#xA;Yes, it's a pipe dream. A bicubic Bezier patch is an algebraic surface of degree 18. To intersect a ray with this surface, you have to find the roots of a polynomial of degree 18. There is no formula for these roots -- you have to find them by numerical methods. In fact, there are mathematical results ([the Abel-Ruffini theorem][1]) telling us that there can never be formulae for roots of equations beyond degree 4. The math doesn't just say that the formulae have not yet been found; it says that they never will be found, because they can't exist.&#xD;&#xA;&#xD;&#xA;If you really want to do analytical (algebraic) ray-tracing of curvaceous shapes, you might try using Steiner patches. These have degree 4, so the ray-patch intersection can be computed by finding the [roots of a quartic][2] (i.e. a polynomial of degree 4. There are formulae for finding roots of quartics, but they're pretty nasty, and it's surprisingly hard to write code that implements the formulae reliably.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Quartic_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="16006" PostHistoryTypeId="5" PostId="5799" RevisionGUID="430d1b56-7c43-4e0f-9cf7-4021df9dbc69" CreationDate="2017-10-31T13:49:33.073" UserId="6968" Comment="Added links" Text="&gt; is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically&#xD;&#xA;&#xD;&#xA;Yes, it's a pipe dream. A bicubic Bezier patch is an algebraic surface of degree 18. To intersect a ray with this surface, you have to find the roots of a polynomial of degree 18. There is no formula for these roots -- you have to find them by numerical methods. In fact, there are mathematical results ([the Abel-Ruffini theorem][1]) telling us that there can never be formulae for roots of equations beyond degree 4. The math doesn't just say that the formulae have not yet been found; it says that they never will be found, because they can't exist.&#xD;&#xA;&#xD;&#xA;If you really want to do analytical (algebraic) ray-tracing of curvaceous shapes, you might try using [Steiner patches][2]. These have degree 4, so the ray-patch intersection can be computed by finding the [roots of a quartic][3] (i.e. a polynomial of degree 4. There are formulae for finding roots of quartics, but they're pretty nasty, and it's surprisingly hard to write code that implements the formulae reliably.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem&#xD;&#xA;  [2]: https://www.researchgate.net/publication/234780280_Ray_tracing_of_Steiner_patches&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Quartic_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="16007" PostHistoryTypeId="5" PostId="5787" RevisionGUID="9c93e274-ae2b-44a6-9402-66c78f0597f3" CreationDate="2017-10-31T17:46:59.737" UserId="5256" Comment="deleted 72 characters in body" Text="Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i)$ $=$ $G1(w_o)G1(w_i)$&#xD;&#xA;&#xD;&#xA;We can write the masking-shadowing function as the ratio of visible microfacet area to total forward facing microfacet area:&#xD;&#xA;&#xD;&#xA;$G1(w)$ $=$ $\Lambda^+(w) - \Lambda^-(w)\over \Lambda^+(w)$&#xD;&#xA;&#xD;&#xA;Shadow-masking functions are traditionally expressed in terms of auxiliary function $\Lambda(w)$, which measures invisible masked microfacet area per visible microfacet area.&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $\Lambda^-(w)\over \Lambda^+(w)-\Lambda^-(w)$&#xD;&#xA;&#xD;&#xA;The $\Lambda(w)$ function computes this. Its implementation is specific to each microfacet distribution. &#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $-1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this $\Lambda(w)$ function derived?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16008" PostHistoryTypeId="5" PostId="5795" RevisionGUID="d8674ffc-7ec0-4abb-84db-925c7306ce18" CreationDate="2017-10-31T19:51:54.827" UserId="7431" Comment="MathJAX formatting" Text="I think there might be a misprinting in the book. I am getting this&#xD;&#xA;&#xD;&#xA;$((A-C) + tB)\cdot((A-C) + tB) = R\cdot R$ &#xD;&#xA;&#xD;&#xA;`Let  A-C = Y`&#xD;&#xA;&#xD;&#xA;$(Y + tB)\cdot(Y + tB) = R\cdot R$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$Y\cdot Y + Y\cdot tB + tB\cdot Y + t^2B\cdot B = R\cdot R$&#xD;&#xA;&#xD;&#xA;Substituting back &#xD;&#xA;&#xD;&#xA;$(A-C)\cdot(A-C) + 2t * B\cdot(A-C) + t^2B\cdot B = R\cdot R$" ContentLicense="CC BY-SA 3.0" />
  <row Id="16009" PostHistoryTypeId="24" PostId="5795" RevisionGUID="d8674ffc-7ec0-4abb-84db-925c7306ce18" CreationDate="2017-10-31T19:51:54.827" Comment="Proposed by 7431 approved by 231 edit id of 285" ContentLicense="CC BY-SA 3.0" />
  <row Id="16010" PostHistoryTypeId="2" PostId="5803" RevisionGUID="30f6287f-81b1-443a-b558-1853cdf2e8fa" CreationDate="2017-11-01T06:04:55.013" UserId="2308" Text="As some of you may know drawing line segments between sets of points is really difficult especially when you want wide or variable widths.&#xD;&#xA;&#xD;&#xA;Because I am looking to draw a few hundred of these line segments each frame I am having to go with the cheapest option to achieve a connected segment. So far this has meant that I am using a mitter to foin the two rectangles like so ([described here][1])&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this approach is that the extra length added by the mitter is sometimes quite large especially in the case of acute angles and I would like to have rounded corners where possible.&#xD;&#xA;&#xD;&#xA;I believe is the job for the fragment shader as I dont have enough processing resources to calculate more geometry.&#xD;&#xA;&#xD;&#xA;Here is a diagram showing what might end up happening after the freagment function:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;purple represents the area between the two lines that has aught to be kept the rest should be removed.&#xD;&#xA;&#xD;&#xA;Does anyone know a way to achieve this rounded rectangle in the fragment shader even though texture coords are pretty useless in a scenario where the shape is not a polygon.&#xD;&#xA;&#xD;&#xA;I wish I was allowed to just draw the rounded circle over the disjointed &#xD;&#xA;&#xD;&#xA;Remember, whatever it is it needs to be fast.&#xD;&#xA;&#xD;&#xA;  [1]: https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader&#xD;&#xA;  [2]: https://i.stack.imgur.com/TBAum.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/lHZmR.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xiMsV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16011" PostHistoryTypeId="1" PostId="5803" RevisionGUID="30f6287f-81b1-443a-b558-1853cdf2e8fa" CreationDate="2017-11-01T06:04:55.013" UserId="2308" Text="Rounding the edges in a mittered line segment inside of a fragment shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="16012" PostHistoryTypeId="3" PostId="5803" RevisionGUID="30f6287f-81b1-443a-b558-1853cdf2e8fa" CreationDate="2017-11-01T06:04:55.013" UserId="2308" Text="|geometry|linear-algebra|linear|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16013" PostHistoryTypeId="4" PostId="5787" RevisionGUID="46b5730b-74ae-4a39-af19-8f05aaf7dd91" CreationDate="2017-11-01T06:14:31.780" UserId="5256" Comment="edited title" Text="GGX Smith Geometry" ContentLicense="CC BY-SA 3.0" />
  <row Id="16014" PostHistoryTypeId="50" PostId="4361" RevisionGUID="b1e930c0-80bc-460c-a76d-aaeaaba90515" CreationDate="2017-11-01T10:59:56.150" UserId="-1" />
  <row Id="16015" PostHistoryTypeId="2" PostId="5804" RevisionGUID="13738ce1-e6b3-41fb-8d2c-2839a1875126" CreationDate="2017-11-01T11:27:12.617" UserId="6" Text="First, adressing the concerns of speed and performance, you will always have to make some trade-offs between quality and performance, as you already do. If the first version looks *fine enough* for your use-case and all other versions are much slower, you have to make the decision yourself. You will, however, not get around actually *measuring* any time difference. But since various ways to do this are not too hard to integrate into an existing wide lines renderer, just testing the various approaches in action and getting some time measurements shouldn't be too difficult, especially with OpenGL timer queries (or whatever the Direct3D equivalent).&#xD;&#xA;&#xD;&#xA;So let's get to some *possible* improvements to your situation. It seems from your link and your explanations that you're using a classic geometry shader based approach for wide line rendereing, converting each line into a screen-aligned quad (or two triangles), computing the vertex positions based on the line width you want to achieve. I recently built something similar, too and there's a few ways you can improve the quality.&#xD;&#xA;&#xD;&#xA;- As you said yourself, since you're working on rather arbitrary rounded shapes it's probably best to let the fragment shader figure out the exact pixel-shape rather than trying to approximate the circular middle region in the geometry shader. Though, that idea is not completely off-the table and might give for a nice adjustable quality-speed trade-off by adjusting the number of vertices of that circle-part. But it also, together with your current approach, has the problem that it actually needs to know the line's neighbouring lines in order to compute the middle section, which makes it difficult to just put into an existing shader-agnostic rendering system that just fraws all the lines as vertex pairs (not to speak of line strips/loops), since you need to add the adjacency information for each line.&#xD;&#xA;&#xD;&#xA;- If you just want to let the fragmet shader do the job using simple alpha testing, you generate a screen-aligned rectangle that's a little larger than the line, i.e. it spans half the width across the endpoints and thus covers the circular middle section, too. In the fragment shader you just check each fragment's screen-space distance to the actual line center (whose vertices you transfer from the geometry shader to the fragment shader as varying). And whenever that distance is larger than the line width (or half the line width, to be precise), you `discard` the fragment. This way you will basically render a rounded box for each line.&#xD;&#xA;&#xD;&#xA; To be precise you render your line as three quad-sections (i.e. 6 triangles in a single strip). The middle section between the ednpoints as one rectangle and the two end-caps as rectangles spanning from the endpoint half the width in the direction of the line. You do this separation to give the rightmost 4 vertices their respective endpoint as varying value and the leftmost one their respective endpoint. This way you get smooth interpolation of the line point across the middle section and clamping in the cap sections.&#xD;&#xA;&#xD;&#xA; This distance computation might also be used to antialias the lines, i.e. by using alpha blending (or multisampling with alpha to coverage) and letting alpha go from 1 to 0 along the outermost ~1-pixel thick border of the line.&#xD;&#xA;&#xD;&#xA; But this approach has the disadvantage of drawing the uneccessary grey area from your above picture, *twice* even. This not only causes possibly slowing overdraw (and the explicit discarding inhibits early z-testing), it will also interfere with any possible alpha-based antialiasing as described above.&#xD;&#xA;&#xD;&#xA;- A solution to mitigate this could be to actually just draw the completely uncapped lines as rectangles from one ednpoint to the other (i.e. like your very first picture. And then drawing the connection points as additional circular large points (i.e. using a similar technique of transforming points into screen-aligned quads with the geometry shader and testing for the distance to the actual point center in the fragment shader to get pixel-perfect circles).&#xD;&#xA;&#xD;&#xA; This has the advantage that you can actually use stencil testing to only draw the middle sections in the regions where you haven't draw other parts of the line set before and thus only the violet area, which will tremendously reduce overdraw (at the cost of more complicated rendering and per-fragment operations). This gives very nice results with an alpha-based antialiasing approach as describes above (there are however still some minor areas where there's some tiny artefacts).&#xD;&#xA;&#xD;&#xA; This stencil testing approach might as well be used on the earlier approach where you draw the line section together with its end-caps when you don't perform any kind of antialiasing or blending, but I think to remember that it caused more artefacts than the separate rendering if you do. I haven't spend too many thoughts on this right now, though, and it might be worth some more investigation.&#xD;&#xA;&#xD;&#xA;Those are just a few thoughts that I happened to ponder on just recently and deemed worth sharing. As said, *if* they are appropriate for your use-case has to be evaluated, possible with some timing and quality measurements." ContentLicense="CC BY-SA 3.0" />
  <row Id="16017" PostHistoryTypeId="5" PostId="5799" RevisionGUID="69ea9bc7-d2af-4587-a286-4bdb20f7d244" CreationDate="2017-11-01T12:09:22.133" UserId="6968" Comment="added 1 character in body" Text="&gt; is it a total pipe dream to hope to solve the Ray/Bezier-surface intersection algebraically&#xD;&#xA;&#xD;&#xA;Yes, it's a pipe dream. A bicubic Bezier patch is an algebraic surface of degree 18. To intersect a ray with this surface, you have to find the roots of a polynomial of degree 18. There is no formula for these roots -- you have to find them by numerical methods. In fact, there are mathematical results ([the Abel-Ruffini theorem][1]) telling us that there can never be formulae for roots of equations beyond degree 4. The math doesn't just say that the formulae have not yet been found; it says that they never will be found, because they can't exist.&#xD;&#xA;&#xD;&#xA;If you really want to do analytical (algebraic) ray-tracing of curvaceous shapes, you might try using [Steiner patches][2]. These have degree 4, so the ray-patch intersection can be computed by finding the [roots of a quartic][3] (i.e. a polynomial of degree 4). There are formulae for finding roots of quartics, but they're pretty nasty, and it's surprisingly hard to write code that implements the formulae reliably.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem&#xD;&#xA;  [2]: https://www.researchgate.net/publication/234780280_Ray_tracing_of_Steiner_patches&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Quartic_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="16018" PostHistoryTypeId="5" PostId="5804" RevisionGUID="7d54ca82-9fa7-4a8e-a198-97287de8615d" CreationDate="2017-11-01T12:25:01.413" UserId="6" Comment="added 279 characters in body" Text="First, adressing the concerns of speed and performance, you will always have to make some trade-offs between quality and performance, as you already do. If the first version looks *fine enough* for your use-case and all other versions are much slower, you have to make the decision yourself. You will, however, not get around actually ***measuring* any time difference**. But since various ways to do this are not too hard to integrate into an existing wide lines renderer, just testing the various approaches in action and getting some time measurements shouldn't be too difficult, especially with OpenGL timer queries (or whatever the Direct3D equivalent).&#xD;&#xA;&#xD;&#xA;So let's get to some *possible* improvements to your situation. It seems from your link and your explanations that you're using a classic geometry shader based approach for wide line rendereing, converting each line into a screen-aligned quad (or two triangles), computing the vertex positions based on the line width you want to achieve. I recently built something similar, too and there's a few ways you can improve the quality.&#xD;&#xA;&#xD;&#xA;- As you said yourself, since you're working on rather arbitrary rounded shapes it's probably best to let the fragment shader figure out the exact pixel-shape rather than trying to **approximate the circular middle region in the geometry shader**. Though, that idea is not completely off-the table and might give for a nice adjustable quality-speed trade-off by adjusting the number of vertices of that circle-part. But it also, together with your current approach, has the problem that it actually **needs to know the line's neighbouring lines** in order to compute the middle section, which makes it difficult to just put into an existing shader-agnostic rendering system that just draws all the lines as vertex pairs (not to speak of line strips/loops), since you need to add the adjacency information for each line.&#xD;&#xA;&#xD;&#xA;- If you just want to let the fragmet shader do the job using simple alpha testing, you generate a **screen-aligned rectangle that's a little larger than the line, i.e. it spans half the width across the endpoints** and thus covers the circular end caps, too. In the fragment shader you just check each **fragment's screen-space distance to the nearest point on the actual line** (which you transfer from the geometry shader to the fragment shader as a varying). And whenever that distance is larger than the line width (or half the line width, to be precise), you **`discard` the fragment**. This way you will basically render a rounded box for each line.&#xD;&#xA;&#xD;&#xA; To be precise you render your line as three quad-sections (i.e. 6 triangles in a single strip). The middle section between the ednpoints as one rectangle and the two end-caps as rectangles spanning from the endpoint half the width in the direction of the line. You do this separation to give the rightmost 4 vertices their respective endpoint as varying value and the leftmost one their respective endpoint. This way you get smooth interpolation of the line point across the middle section and clamping in the cap sections.&#xD;&#xA;&#xD;&#xA; This distance computation might also be used to **antialias** the lines, i.e. by using alpha blending (or multisampling with alpha to coverage) and **letting alpha go from 1 to 0 along the outermost ~1-pixel thick border** of the line.&#xD;&#xA;&#xD;&#xA; But this approach has the disadvantage of **drawing the uneccessary grey area from your above picture, *twice* even**. This not only causes possibly slowing overdraw (and the explicit discarding inhibits early z-testing), it will also interfere with any possible alpha-based antialiasing as described above.&#xD;&#xA;&#xD;&#xA;- A solution to mitigate this could be to actually just draw the completely uncapped lines as rectangles from one endpoint to the other (i.e. like your very first picture). And then **drawing the connection points as additional circular large points** (i.e. using a similar technique of transforming points into screen-aligned quads with the geometry shader and testing for the distance to the actual point center in the fragment shader to get pixel-perfect circles).&#xD;&#xA;&#xD;&#xA; This has the advantage that you can actually use **stencil testing to only draw the middle sections in the regions where you haven't drawn other parts of the line set before** and thus only the violet area, which will tremendously reduce overdraw (at the cost of more complicated rendering and per-fragment operations). This gives very nice results with an alpha-based antialiasing approach as described above (there are however still some minor areas where there's some tiny artefacts).&#xD;&#xA;&#xD;&#xA; This stencil testing approach might as well be used on the earlier approach where you draw the line section together with its end-caps when you don't perform any kind of antialiasing or blending, but I think to remember that it caused more artefacts than the separate rendering if you do. I haven't spend too many thoughts on this right now, though, and it might be worth some more investigation. However the seperate solution also has the advantage of **requiring the expensive fragment test and possible discard only in the actual connective regions**, the line middle sections can be rendered with a straight-forward fragment shader.&#xD;&#xA;&#xD;&#xA;Those are just a few thoughts that I happened to ponder on just recently and deemed worth sharing. As said, *if* they are appropriate for your use-case has to be evaluated, possibly with some timing and quality measurements." ContentLicense="CC BY-SA 3.0" />
  <row Id="16019" PostHistoryTypeId="5" PostId="5804" RevisionGUID="a588ef56-d132-4ce5-8407-4e07e96c2748" CreationDate="2017-11-01T12:30:50.333" UserId="6" Comment="added 31 characters in body" Text="First, adressing the concerns of speed and performance, you will always have to make some trade-offs between quality and performance, as you already do. If the first version looks *fine enough* for your use-case and all other versions are much slower, you have to make the decision yourself. You will, however, not get around actually ***measuring* any time difference**. But since various ways to do this are not too hard to integrate into an existing wide lines renderer, just testing the various approaches in action and getting some time measurements shouldn't be too difficult, especially with OpenGL timer queries (or whatever the Direct3D equivalent).&#xD;&#xA;&#xD;&#xA;So let's get to some *possible* improvements to your situation. It seems from your link and your explanations that you're using a classic geometry shader based approach for wide line rendereing, converting each line into a screen-aligned quad (or two triangles), computing the vertex positions based on the line width you want to achieve. I recently built something similar, too and there's a few ways you can improve the quality.&#xD;&#xA;&#xD;&#xA;- As you said yourself, since you're working on rather arbitrary rounded shapes it's probably best to let the fragment shader figure out the exact pixel-shape rather than trying to **approximate the circular middle region in the geometry shader**. Though, that idea is not completely off-the table and might give for a nice adjustable quality-speed trade-off by adjusting the number of vertices of that circle-part. But it also, together with your current approach, has the problem that it actually **needs to know the line's neighbouring lines** in order to compute the middle section, which makes it difficult to just put into an existing shader-agnostic rendering system that just draws all the lines as vertex pairs (not to speak of line strips/loops), since you need to add the adjacency information for each line.&#xD;&#xA;&#xD;&#xA;- If you just want to let the fragmet shader do the job using simple alpha testing, you generate a **screen-aligned rectangle that's a little larger than the line, i.e. it spans half the width across the endpoints** and thus covers the circular end caps, too. In the fragment shader you just check each **fragment's screen-space distance to the nearest point on the actual line** (which you transfer from the geometry shader to the fragment shader as a varying). And whenever that distance is larger than the line width (or half the line width, to be precise), you **`discard` the fragment**. This way you will basically render a rounded box for each line.&#xD;&#xA;&#xD;&#xA; To be precise you render your line as three quad-sections (i.e. 6 triangles in a single strip). The middle section between the ednpoints as one rectangle and the two end-caps as rectangles spanning from the endpoint half the width in the direction of the line. You do this separation to give the rightmost 4 vertices their respective endpoint as varying value and the leftmost one their respective endpoint. This way you get smooth interpolation of the line point across the middle section and clamping in the cap sections.&#xD;&#xA;&#xD;&#xA; This distance computation might also be used to **antialias** the lines, i.e. by using alpha blending (or multisampling with alpha to coverage) and **letting alpha go from 1 to 0 along the outermost ~1-pixel thick border** of the line.&#xD;&#xA;&#xD;&#xA; But this approach has the disadvantage of **drawing the uneccessary grey area from your above picture, *twice* even**. This not only causes possibly slowing overdraw (and the explicit discarding inhibits early z-testing), it will also interfere with any possible alpha-based antialiasing as described above.&#xD;&#xA;&#xD;&#xA;- A solution to mitigate this could be to actually just draw the completely uncapped lines as rectangles from one endpoint to the other (i.e. like your very first picture). And then **drawing the connection points (i.e. the line's vertices) as additional circular large points** (i.e. using a similar technique of transforming points into screen-aligned quads with the geometry shader and testing for the distance to the actual point center in the fragment shader to get pixel-perfect circles).&#xD;&#xA;&#xD;&#xA; This has the advantage that you can actually use **stencil testing to only draw the connective sections in the regions where you haven't drawn other parts of the line set before** and thus only the violet area, which will tremendously reduce overdraw (at the cost of more complicated rendering and per-fragment operations). This gives very nice results with an alpha-based antialiasing approach as described above (there are however still some minor areas where there's some tiny artefacts).&#xD;&#xA;&#xD;&#xA; This stencil testing approach might as well be used on the earlier approach where you draw the line section together with its end-caps when you don't perform any kind of antialiasing or blending, but I think to remember that it caused more artefacts than the separate rendering if you do. I haven't spend too many thoughts on this right now, though, and it might be worth some more investigation. However the seperate solution also has the advantage of **requiring the expensive fragment test and possible discard only in the actual connective regions**, the line middle sections can be rendered with a straight-forward fragment shader.&#xD;&#xA;&#xD;&#xA;Those are just a few thoughts that I happened to ponder on just recently and deemed worth sharing. As said, *if* they are appropriate for your use-case has to be evaluated, possibly with some timing and quality measurements." ContentLicense="CC BY-SA 3.0" />
  <row Id="16020" PostHistoryTypeId="5" PostId="5803" RevisionGUID="e73b61b3-3158-4b4a-8c9d-2e596419cfdc" CreationDate="2017-11-01T14:32:39.647" UserId="6" Comment="Improved formatting and tagging." Text="As some of you may know drawing line segments between sets of points is really difficult especially when you want wide lines or variable widths.&#xD;&#xA;&#xD;&#xA;Because I am looking to draw a few hundred of these line segments each frame I am having to go with the cheapest option to achieve a connected segment. So far this has meant that I am using a mitter to foin the two rectangles like so ([described here][1])&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this approach is that the extra length added by the mitter is sometimes quite large especially in the case of acute angles and I would like to have rounded corners where possible.&#xD;&#xA;&#xD;&#xA;I believe is the job for the fragment shader as I dont have enough processing resources to calculate more geometry.&#xD;&#xA;&#xD;&#xA;Here is a diagram showing what might end up happening after the freagment function:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;purple represents the area between the two lines that has aught to be kept the rest should be removed.&#xD;&#xA;&#xD;&#xA;Does anyone know a way to achieve this rounded rectangle in the fragment shader even though texture coords are pretty useless in a scenario where the shape is not a polygon.&#xD;&#xA;&#xD;&#xA;I wish I was allowed to just draw the rounded circle over the disjointed &#xD;&#xA;&#xD;&#xA;Remember, whatever it is it needs to be fast.&#xD;&#xA;&#xD;&#xA;  [1]: https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader&#xD;&#xA;  [2]: https://i.stack.imgur.com/TBAumm.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/lHZmRm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xiMsV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16021" PostHistoryTypeId="6" PostId="5803" RevisionGUID="e73b61b3-3158-4b4a-8c9d-2e596419cfdc" CreationDate="2017-11-01T14:32:39.647" UserId="6" Comment="Improved formatting and tagging." Text="|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16022" PostHistoryTypeId="24" PostId="5803" RevisionGUID="e73b61b3-3158-4b4a-8c9d-2e596419cfdc" CreationDate="2017-11-01T14:32:39.647" Comment="Proposed by 6 approved by -1 edit id of 286" ContentLicense="CC BY-SA 3.0" />
  <row Id="16023" PostHistoryTypeId="5" PostId="5803" RevisionGUID="53e8f1bb-2919-4dcc-a8f3-fb960e510838" CreationDate="2017-11-01T14:32:39.647" UserId="2041" Comment="Improved spelling, formatting and tagging." Text="As some of you may know drawing line segments between sets of points is really difficult especially when you want wide lines or variable widths.&#xD;&#xA;&#xD;&#xA;Because I am looking to draw a few hundred of these line segments each frame I am having to go with the cheapest option to achieve a connected segment. So far this has meant that I am using a miter to join the two rectangles like so ([described here][1])&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this approach is that the extra length added by the miter is sometimes quite large especially in the case of acute angles and I would like to have rounded corners where possible.&#xD;&#xA;&#xD;&#xA;I believe it is a job for the fragment shader as I don't have enough processing resources to calculate more geometry.&#xD;&#xA;&#xD;&#xA;Here is a diagram showing what might end up happening after the fragment function:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Purple represents the area between the two lines that ought to be kept; the rest should be removed.&#xD;&#xA;&#xD;&#xA;Does anyone know a way to achieve this rounded rectangle in the fragment shader even though texture co-ords are pretty useless in a scenario where the shape is not a polygon.&#xD;&#xA;&#xD;&#xA;I wish I was allowed to just draw the rounded circle over the disjointed &#xD;&#xA;&#xD;&#xA;Remember, whatever it is it needs to be fast.&#xD;&#xA;&#xD;&#xA;  [1]: https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader&#xD;&#xA;  [2]: https://i.stack.imgur.com/TBAumm.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/lHZmRm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/xiMsV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16024" PostHistoryTypeId="4" PostId="5803" RevisionGUID="53e8f1bb-2919-4dcc-a8f3-fb960e510838" CreationDate="2017-11-01T14:32:39.647" UserId="2041" Comment="Improved spelling, formatting and tagging." Text="Rounding the edges in a mitered line segment inside of a fragment shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="16025" PostHistoryTypeId="2" PostId="5805" RevisionGUID="8b510082-49bc-4d1d-9051-0d31e7762f55" CreationDate="2017-11-01T16:13:44.947" UserId="2308" Text="I am trying to wrap my head around how exactly the GPU interpolates texture coords on a quad. I realize to the GPU a quad is two triangles but I find thinking in terms of the whole quad to be easiest.&#xD;&#xA;&#xD;&#xA;If we define texture space as the texture coordinates from X:Y{0-1} and world space as the actual coordinates of the quad how can I given a point p1 that is on the quad figure out what its texture coordinate would be? Given a texture coordinate point p2 how would I figure out its real world coordinates?&#xD;&#xA;&#xD;&#xA;Keep in mind that the quad can be any quadrilateral not necessarily always a parallelogram. &#xD;&#xA;&#xD;&#xA;As an extra note lets define the texture coordinates on the quad so that they are as such&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2wkpm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16026" PostHistoryTypeId="1" PostId="5805" RevisionGUID="8b510082-49bc-4d1d-9051-0d31e7762f55" CreationDate="2017-11-01T16:13:44.947" UserId="2308" Text="The mathematics of two dimensional interpolation on a quad" ContentLicense="CC BY-SA 3.0" />
  <row Id="16027" PostHistoryTypeId="3" PostId="5805" RevisionGUID="8b510082-49bc-4d1d-9051-0d31e7762f55" CreationDate="2017-11-01T16:13:44.947" UserId="2308" Text="|texture|gpu|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16028" PostHistoryTypeId="2" PostId="5806" RevisionGUID="7dfd9017-c8fb-41bf-9be1-e28c7b616d40" CreationDate="2017-11-01T18:08:40.643" UserId="6" Text="(It actually *is* easier to think (and compute) about this with triangles, but for the sake of the answer, let's first stick to your quad example.)&#xD;&#xA;&#xD;&#xA;For this you just have to define the point you're interested in in terms of the quad's (or whatever primitive's) vertices. This is called a [barycentric coordinate system](https://en.wikipedia.org/wiki/Barycentric_coordinate_system). More pracitcally-speaking, you basically give the point $n$ weights, each describing the influence the $n$th vertex of the quad has on the point. Those are the point's barycentric coordinates with respect to that quad.&#xD;&#xA;&#xD;&#xA;So for example the center point of the quad (or &quot;center of mass&quot;) would have the weights $\frac{1}{4}$, $\frac{1}{4}$, $\frac{1}{4}$, and $\frac{1}{4}$. A point in the middle of the left edge would have a weight of $\frac{1}{2}$ for the left two vertices and a weight of $0$ for the right two vertices.&#xD;&#xA;&#xD;&#xA;These barycentric coordinates can then be used to interpolate whatever kind of per-vertex values you want, be that positions or texture coordinates. It all reduces to a simple weighted sum. And even more than that, they can also be quite easily computed by simple vector algebra from any existing per-vertex values if you have the point's values given (comes down to just a few little 2x2 determinants for a triangle, or similarly easy computation). This means if you know the point's screen-space position and those of the vertices, you can compute its barycentric coordinates. These you can then use to compute the point's texture coordinates (or normal, or whatever) from the per-vertex values, or vice versa.&#xD;&#xA;&#xD;&#xA;So much to the theory, there's a few practical considerations to keep in mind, especially when using them for interpolation in a rasterizer, like GPUs do.&#xD;&#xA;&#xD;&#xA;- For anything but triangles the barycentric coordinates don't necessarily have to be uniquely defined for any arbitrary point. That's why thinking about triangles is much easier, especially for the computer.&#xD;&#xA;- Due to the fact that they are negative if and only if the point doesn't actually lie inside the triangle they can also be used for checking *if* the point belongs to the triangle at all and thus are more or less a by-product of the pixel-in-triangle test that the rasterizer already performs to, well, rasterize the triangle.&#xD;&#xA;- When it comes to interpolation in projected space, i.e. when projecting a 3D world onto the plane using perspective distortion, it becomes a little more involved since you have to account for the fact that an line's length in screen-space is not the same as its length in world space, or more precisely its screen-space length doesn't increase linearly when going along a triangle edge in world space. The keyword here is [perspective correct interpolation](https://en.wikipedia.org/wiki/Texture_mapping#Perspective_correctness). But this still uses the point's barycentric coordinates.&#xD;&#xA;- Of course in an actual rasterizer you also have to take account for shared triangle edges and only rasterize a shared edge once, which requires special rules as to which triangle a shared edge belongs and might make the computation of barycentric coordinates a little more complicated, together with using fixed-point coordinates or whatever optimized computations." ContentLicense="CC BY-SA 3.0" />
  <row Id="16029" PostHistoryTypeId="5" PostId="5806" RevisionGUID="f6967878-8873-4875-ba93-8ace1dd2055c" CreationDate="2017-11-01T18:15:38.590" UserId="6" Comment="added 2 characters in body" Text="(It actually *is* easier to think (and compute) about this with triangles, but for the sake of the answer, let's first stick to your quad example.)&#xD;&#xA;&#xD;&#xA;For this you just have to define the point you're interested in in terms of the quad's (or whatever primitive's) vertices. This is called a [barycentric coordinate system](https://en.wikipedia.org/wiki/Barycentric_coordinate_system). More pracitcally-speaking, you basically give the point $n$ weights, each describing the influence the $n$th vertex of the quad has on the point. Those are the point's barycentric coordinates with respect to that quad.&#xD;&#xA;&#xD;&#xA;So for example the center point of the quad (or &quot;center of mass&quot;) would have the weights $\frac{1}{4}$, $\frac{1}{4}$, $\frac{1}{4}$, and $\frac{1}{4}$. A point in the middle of the left edge would have a weight of $\frac{1}{2}$ for the left two vertices and a weight of $0$ for the right two vertices.&#xD;&#xA;&#xD;&#xA;These barycentric coordinates can then be used to interpolate whatever kind of per-vertex values you want, be that positions or texture coordinates. It all reduces to a simple weighted sum. And even more than that, they can also be quite easily computed by simple vector algebra from any existing per-vertex values if you have the point's values given (comes down to just a few little 2x2 determinants for a triangle, or similarly easy computation). This means if you know a pixel's screen-space position and those of the vertices, you can compute its barycentric coordinates. These you can then use to interpolate the pixel's texture coordinates (or normal, or whatever) from the per-vertex values, or vice versa.&#xD;&#xA;&#xD;&#xA;So much to the theory, there's a few practical considerations to keep in mind, especially when using them for interpolation in a rasterizer, like GPUs do.&#xD;&#xA;&#xD;&#xA;- For anything but triangles the barycentric coordinates don't necessarily have to be uniquely defined for any arbitrary point. That's why thinking about triangles is much easier, especially for the computer.&#xD;&#xA;- Due to the fact that they are negative if and only if the point doesn't actually lie inside the triangle they can also be used for checking *if* the point belongs to the triangle at all and thus are more or less a by-product of the pixel-in-triangle test that the rasterizer already performs to, well, rasterize the triangle.&#xD;&#xA;- When it comes to interpolation in projected space, i.e. when projecting a 3D world onto the plane using perspective distortion, it becomes a little more involved since you have to account for the fact that an line's length in screen-space is not the same as its length in world space, or more precisely its screen-space length doesn't increase linearly when going along a triangle edge in world space. The keyword here is [perspective correct interpolation](https://en.wikipedia.org/wiki/Texture_mapping#Perspective_correctness). But this still uses the point's barycentric coordinates.&#xD;&#xA;- Of course in an actual rasterizer you also have to take account for shared triangle edges and only rasterize a shared edge once, which requires special rules as to which triangle a shared edge belongs and might make the computation of barycentric coordinates a little more complicated, together with using fixed-point coordinates or whatever optimized computations." ContentLicense="CC BY-SA 3.0" />
  <row Id="16030" PostHistoryTypeId="5" PostId="5806" RevisionGUID="a7c5cc92-29ce-478e-8d83-41627969e437" CreationDate="2017-11-01T18:22:29.863" UserId="6" Comment="added 228 characters in body" Text="(It actually *is* easier to think (and compute) about this with triangles, but for the sake of the answer, let's first stick to your quad example.)&#xD;&#xA;&#xD;&#xA;For this you just have to define the point you're interested in in terms of the quad's (or whatever primitive's) vertices. This is called a [barycentric coordinate system](https://en.wikipedia.org/wiki/Barycentric_coordinate_system). More practically-speaking, you basically give the point $n$ weights, each describing the influence the $n$th vertex of the quad has on the point. Those are the point's barycentric coordinates with respect to that quad.&#xD;&#xA;&#xD;&#xA;So for example the center point of the quad (or &quot;center of mass&quot;) would have the weights $\frac{1}{4}$, $\frac{1}{4}$, $\frac{1}{4}$, and $\frac{1}{4}$. A point in the middle of the left edge would have a weight of $\frac{1}{2}$ for the left two vertices each and a weight of $0$ for the right two vertices. (Notice how they always sum to $1$?)&#xD;&#xA;&#xD;&#xA;These barycentric coordinates can then be used to interpolate whatever kind of per-vertex values you want, be that positions or texture coordinates. It all reduces to a simple weighted sum. And even more than that, they can also be quite easily computed by simple vector algebra from any existing per-vertex values if you have the point's values given (comes down to just a few little 2x2 determinants for a triangle, or similarly easy computation). This means if you know a pixel's screen space position and those of the vertices, you can compute its barycentric coordinates. These you can then use to interpolate the pixel's texture coordinates (or normal, or whatever) from the per-vertex values, or vice versa.&#xD;&#xA;&#xD;&#xA;So much to the theory, there's a few practical considerations to keep in mind, especially when using them for interpolation in a rasterizer, like GPUs do.&#xD;&#xA;&#xD;&#xA;- For anything but triangles the barycentric coordinates don't necessarily have to be uniquely defined for any arbitrary point. That's why thinking about triangles is much easier, especially for the computer.&#xD;&#xA;- Due to the fact that they are negative if and only if the point doesn't actually lie inside the triangle they can also be used for checking *if* the point belongs to the triangle at all and thus are more or less a by-product of the pixel-in-triangle test that the rasterizer already performs to, well, rasterize the triangle.&#xD;&#xA;- When it comes to interpolation in projected space, i.e. when projecting a 3D world onto the plane using perspective distortion, it becomes a little more involved since you have to account for the fact that a line's length in screen space is not the same as its length in world space, or more precisely its screen space length doesn't increase linearly when going along a triangle edge in world space. The keyword here is [perspective correct interpolation](https://en.wikipedia.org/wiki/Texture_mapping#Perspective_correctness). But this still uses the point's barycentric coordinates.&#xD;&#xA;- Of course in an actual rasterizer you also have to take account for shared triangle edges and only rasterize a shared edge once, which requires special rules as to which triangle a shared edge belongs and might make the computation of barycentric coordinates a little more complicated, together with using fixed-point coordinates or whatever optimized computations.&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;(This is a more general overview of the matter and how it generally works. For specific mathematical as well as technical details, I'd advise for further reading, maybe starting with the above Wikipedia articles.)&lt;/sub&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16031" PostHistoryTypeId="5" PostId="5806" RevisionGUID="dca06818-b10b-4dd2-982c-a68ab0c15cc5" CreationDate="2017-11-01T18:29:48.963" UserId="6" Comment="added 228 characters in body" Text="(It actually *is* easier to think (and compute) about this with triangles, but for the sake of the answer, let's first stick to your quad example.)&#xD;&#xA;&#xD;&#xA;For this you just have to define the point you're interested in in terms of the quad's (or whatever primitive's) vertices. This is called a [**barycentric coordinate system**](https://en.wikipedia.org/wiki/Barycentric_coordinate_system). More practically-speaking, you basically give the point $n$ weights, each describing **the influence the $i$th vertex of the quad has on the point**. Those are the point's barycentric coordinates with respect to that quad.&#xD;&#xA;&#xD;&#xA;So for example the center point of the quad (or &quot;center of mass&quot;) would have the weights $\frac{1}{4}$, $\frac{1}{4}$, $\frac{1}{4}$, and $\frac{1}{4}$. A point in the middle of the left edge would have a weight of $\frac{1}{2}$ for the left two vertices each and a weight of $0$ for the right two vertices. (Notice how they always sum to $1$?)&#xD;&#xA;&#xD;&#xA;These barycentric coordinates can then be used to **interpolate whatever kind of per-vertex values** you want, be that positions or texture coordinates. It all reduces to a simple **weighted sum**. And even more than that, they can also be quite easily computed by simple vector algebra from any **existing per-vertex values if you have the point's values** given (comes down to just a few little 2x2 determinants for a triangle, or similarly easy computation). This means if you know a pixel's screen space position and those of the vertices, you can compute its barycentric coordinates. These you can then use to interpolate the pixel's texture coordinates (or normal, or whatever) from the per-vertex values, or vice versa.&#xD;&#xA;&#xD;&#xA;So much to the theory, there's a few practical considerations to keep in mind, especially when using them for interpolation in a rasterizer, like GPUs do.&#xD;&#xA;&#xD;&#xA;- For anything but triangles the barycentric coordinates don't necessarily have to be uniquely defined for any arbitrary point. That's why **thinking about triangles is much easier**, especially for the computer.&#xD;&#xA;- Due to the fact that they are negative if and only if the point doesn't actually lie inside the triangle they can also be used for **checking *if* the point belongs to the triangle at all** and thus are more or less a by-product of the pixel-in-triangle test that the rasterizer already performs to, well, rasterize the triangle.&#xD;&#xA;- When it comes to interpolation in projected space, i.e. when **projecting a 3D world onto the plane using perspective distortion**, it becomes a little more involved since you have to account for the fact that a line's length in screen space is not the same as its length in world space, or more precisely its screen space length doesn't increase linearly when going along a triangle edge in world space. The keyword here is [**perspective correct interpolation**](https://en.wikipedia.org/wiki/Texture_mapping#Perspective_correctness). But this still uses the point's barycentric coordinates.&#xD;&#xA;- Of course in an actual rasterizer you also have to take account for shared triangle edges and only rasterize a shared edge once, which requires special rules as to which triangle a shared edge belongs and might make the computation of barycentric coordinates a little more complicated, together with using fixed-point coordinates or whatever optimized computations.&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;(This is a more general overview of the matter and how it generally works. For specific mathematical as well as technical details, I'd advise for further reading, maybe starting with the above Wikipedia articles.)&lt;/sub&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16032" PostHistoryTypeId="2" PostId="5807" RevisionGUID="29574540-23c0-49ba-bb49-f2c8d159bf8f" CreationDate="2017-11-01T18:50:48.140" UserId="2750" Text="I've found [VTK](https://www.vtk.org) library and used bindings to Python  3 available from different Anaconda organizations: [anaconda](https://anaconda.org/anaconda/vtk) itself, [conda-forge](https://anaconda.org/conda-forge/vtk), [clinicalgraphics](https://anaconda.org/clinicalgraphics/vtk) and [menpo](https://anaconda.org/menpo/vtk).&#xD;&#xA;Also it can be compiled from sources.&#xD;&#xA;&#xD;&#xA;Works fast (I've rendered a mesh with half a million vertices without any problems) and easier in use than low-level OpenGL shaders with GLUT.&#xD;&#xA;&#xD;&#xA;[menpo](http://www.menpo.org) has its own wrapper for VTK and [mayavi](http://code.enthought.com/projects/mayavi/) called [menpo3d](http://www.menpo.org/menpo3d/).&#xD;&#xA;I have not tried it yet, but examples look very simple." ContentLicense="CC BY-SA 3.0" />
  <row Id="16034" PostHistoryTypeId="2" PostId="5808" RevisionGUID="9e91e133-49ba-46f3-a84f-2fe32d80495f" CreationDate="2017-11-02T00:35:37.813" UserId="159" Text="Just to expand on some of the other answers, the proof that Russian Roulette does not give a biassed result is very simple.&#xD;&#xA;&#xD;&#xA;Suppose that you have some random variable $F$ which is the sum of several terms:&#xD;&#xA;&#xD;&#xA;$$F = F_1 + \cdots + F_N$$&#xD;&#xA;&#xD;&#xA;Replace each term with:&#xD;&#xA;&#xD;&#xA;$$F'_i = \left\{&#xD;&#xA;\begin{array}{ll}&#xD;&#xA;      \frac{1}{p_i} F_i &amp; \hbox{with probability } p_i \\&#xD;&#xA;      0 &amp; \hbox{otherwise}&#xD;&#xA;\end{array} &#xD;&#xA;\right.$$&#xD;&#xA;&#xD;&#xA;Then:&#xD;&#xA;&#xD;&#xA;$$E[F'_i] = p_i \times \frac{1}{p_i}E[F_i] + (1-p_i) \times 0 = E[F_i]$$&#xD;&#xA;&#xD;&#xA;Note that it *doesn't matter* what probabilities you pick for $p_i$. The expected value of the terms, and hence the expected value of $F$, is the same." ContentLicense="CC BY-SA 3.0" />
  <row Id="16035" PostHistoryTypeId="2" PostId="5809" RevisionGUID="2679d966-7d90-49a1-b7df-9ed61bde9c90" CreationDate="2017-11-02T02:49:39.857" UserId="1952" Text="Your equation for the absorption-only model is correct: You multiply the luminance $L_x$ at the surface by the transmittance of the participating media between eye and the surface. For homogeneous media you can calculate this analytically using [Beer-Lambert law][1]:&#xD;&#xA;$$L_y=L_xe^{-\mu|x-y|}$$&#xD;&#xA;For heterogeneous medium you can calculate the transmittance by ray march through the medium using for example Woodcock tracking explained in [the paper you referred][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law&#xD;&#xA;  [2]: http://www.cs.cornell.edu/courses/cs6630/2012sp/notes/09volpath.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16037" PostHistoryTypeId="2" PostId="5810" RevisionGUID="408a3987-540f-4335-a42a-0f9f5af25ced" CreationDate="2017-11-02T04:32:00.937" UserId="7462" Text="I am trying to send rendering information for an instancing rendering using shader buffer objects. My current problem is that I have 2 shader buffer objects, one which works just fine, and another that is not quite working.&#xD;&#xA;&#xD;&#xA;The idea is to render squared faces at different positions in the screen. For this, I create a vector of glm::vec3 that represent the position of each face, put all of them in an std::vector&lt;vec3&gt; and use them as the data for the Shader buffer object.&#xD;&#xA;&#xD;&#xA;In other words I am creating the data as follows:&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Left);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,-10,0));&#xD;&#xA;    visible_faces.push_back(Front);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Back);&#xD;&#xA;&#xD;&#xA;Then updating the buffers as follows:&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, cube_rendering_VBOs[3]);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, visible_faces.size()*sizeof(Face), visible_faces.data(), GL_DYNAMIC_COPY);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, cube_rendering_VBOs[3]);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, cube_rendering_VBOs[4]);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, face_positions.size()*sizeof(vec3), face_positions.data(), GL_DYNAMIC_COPY);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, cube_rendering_VBOs[4]);&#xD;&#xA;&#xD;&#xA;And finally rendering by doing:&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, MESH-&gt;indices-&gt;size(), GL_UNSIGNED_INT, (void*)0, visible_faces.size());&#xD;&#xA;&#xD;&#xA;Obviously there is more code associated with passing the actual mesh geometry used for the instanced rendering and enabling the correct layouts in the vertex shader, but I cannot put my enire code base here and I have more throuroughly tested those, so I beleive the mistake is in how I am passing or reading the shader buffer objects.&#xD;&#xA;&#xD;&#xA;The behaviour is, if you look at the lines:&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Left);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,-10,0));&#xD;&#xA;    visible_faces.push_back(Front);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Back);&#xD;&#xA;&#xD;&#xA;The face_positions() should be the poisitions of the faces.&#xD;&#xA;&#xD;&#xA;However what I have noticed is, the first 3 floats (i.e face_positions[0]) work just as expected. Then one value is skipped (i.e face_positions[1].x) and the next values read are the next 3 (i.e face_positions[1].y face_positions[1].z face_positions[2].x) then once again one value is skipped, and it starts reading the next value (i.e face_positions[2].z).&#xD;&#xA;&#xD;&#xA;So it seems somewhere something is padding the array with 0's to make everything 4 bytes aligned.&#xD;&#xA;&#xD;&#xA;Does anyone ahve any idea of where to start looking?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16038" PostHistoryTypeId="1" PostId="5810" RevisionGUID="408a3987-540f-4335-a42a-0f9f5af25ced" CreationDate="2017-11-02T04:32:00.937" UserId="7462" Text="Shader storage buffer indexing by 4 bytes instead of 3?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16039" PostHistoryTypeId="3" PostId="5810" RevisionGUID="408a3987-540f-4335-a42a-0f9f5af25ced" CreationDate="2017-11-02T04:32:00.937" UserId="7462" Text="|opengl|shader|glsl|uniform-buffer-object|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16040" PostHistoryTypeId="2" PostId="5811" RevisionGUID="e492e416-bcf0-4a90-ac1e-9e9b74ea0f16" CreationDate="2017-11-02T05:29:24.290" UserId="7462" Text="I have a big cube made of smaller cubes, but sometimes, due to the fact that each side of the cube has different colors, I get some ugly colored lines that I qwould like to get rid off. Any advice is appreciated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6T6R9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qGpZs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16041" PostHistoryTypeId="1" PostId="5811" RevisionGUID="e492e416-bcf0-4a90-ac1e-9e9b74ea0f16" CreationDate="2017-11-02T05:29:24.290" UserId="7462" Text="How to eliminate line alaising in an object mabe of cubes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16042" PostHistoryTypeId="3" PostId="5811" RevisionGUID="e492e416-bcf0-4a90-ac1e-9e9b74ea0f16" CreationDate="2017-11-02T05:29:24.290" UserId="7462" Text="|opengl|rendering|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16044" PostHistoryTypeId="2" PostId="5813" RevisionGUID="d61b344d-d3a2-4015-ac73-1742901562c0" CreationDate="2017-11-02T06:59:02.537" UserId="2654" Text="&gt; Does anyone ahve[sic] any idea of where to start looking&#xD;&#xA;&#xD;&#xA;You fell victim to one of the classic blunders. [Never use a `vec3` in a UBO or SSBO.][1]&#xD;&#xA;&#xD;&#xA;While `vec3`s take up 12 bytes, they always have the alignment requirements of a `vec4`. Yes, even under `std430` layout, they always have `vec4` alignment. So if you have an array of `vec3`s in a U/SSBO, what you really have is an array of `vec4`s where one of the elements doesn't get used.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/38172696/should-i-ever-use-a-vec3-inside-of-a-uniform-buffer-or-shader-storage-buffer-o" ContentLicense="CC BY-SA 3.0" />
  <row Id="16045" PostHistoryTypeId="5" PostId="5811" RevisionGUID="291eee03-9771-446a-83ab-1cc96602be71" CreationDate="2017-11-02T14:59:40.770" UserId="209" Comment="Fixed typos" Text="I have a big cube made of smaller cubes, but sometimes, due to the fact that each side of the cube has different colors, I get some ugly colored lines that I would like to get rid off. Any advice is appreciated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6T6R9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qGpZs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16046" PostHistoryTypeId="4" PostId="5811" RevisionGUID="291eee03-9771-446a-83ab-1cc96602be71" CreationDate="2017-11-02T14:59:40.770" UserId="209" Comment="Fixed typos" Text="How to eliminate line aliasing in an object made of cubes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16047" PostHistoryTypeId="5" PostId="5811" RevisionGUID="0c8c7178-ad60-4815-bab1-c3a31321d52e" CreationDate="2017-11-03T01:09:57.970" UserId="7462" Comment="added 389 characters in body" Text="I have a big cube made of smaller cubes, but sometimes, due to the fact that each side of the cube has different colors, I get some ugly colored lines that I would like to get rid off. Any advice is appreciated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;The BLACK lines and arrows are part of a texture, they are not relevant to my question, the focus is the RED line in teh first picture and the red dots in teh second picture. The lines appear mostly because this cube is made of smaller cubes put together side by side, so, depending on camra orientation, the side of a cube gets drawn on top of the front of the neighbouring cube.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6T6R9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qGpZs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16048" PostHistoryTypeId="5" PostId="5810" RevisionGUID="7ca276b5-c337-49ef-b1f0-73c858a70a5b" CreationDate="2017-11-03T01:11:31.053" UserId="7462" Comment="edited body" Text="I am trying to send rendering information for an instancing rendering using shader buffer objects. My current problem is that I have 2 shader buffer objects, one which works just fine, and another that is not quite working.&#xD;&#xA;&#xD;&#xA;The idea is to render squared faces at different positions in the screen. For this, I create a vector of glm::vec3 that represent the position of each face, put all of them in an std::vector&lt;vec3&gt; and use them as the data for the Shader buffer object.&#xD;&#xA;&#xD;&#xA;In other words I am creating the data as follows:&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Left);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,-10,0));&#xD;&#xA;    visible_faces.push_back(Front);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Back);&#xD;&#xA;&#xD;&#xA;Then updating the buffers as follows:&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, cube_rendering_VBOs[3]);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, visible_faces.size()*sizeof(Face), visible_faces.data(), GL_DYNAMIC_COPY);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, cube_rendering_VBOs[3]);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, cube_rendering_VBOs[4]);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, face_positions.size()*sizeof(vec3), face_positions.data(), GL_DYNAMIC_COPY);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, cube_rendering_VBOs[4]);&#xD;&#xA;&#xD;&#xA;And finally rendering by doing:&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, MESH-&gt;indices-&gt;size(), GL_UNSIGNED_INT, (void*)0, visible_faces.size());&#xD;&#xA;&#xD;&#xA;Obviously there is more code associated with passing the actual mesh geometry used for the instanced rendering and enabling the correct layouts in the vertex shader, but I cannot put my enire code base here and I have more throuroughly tested those, so I beleive the mistake is in how I am passing or reading the shader buffer objects.&#xD;&#xA;&#xD;&#xA;The behaviour is, if you look at the lines:&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Left);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,-10,0));&#xD;&#xA;    visible_faces.push_back(Front);&#xD;&#xA;&#xD;&#xA;    face_positions.push_back(vec3(0,0,0));&#xD;&#xA;    visible_faces.push_back(Back);&#xD;&#xA;&#xD;&#xA;The face_positions() should be the poisitions of the faces.&#xD;&#xA;&#xD;&#xA;However what I have noticed is, the first 3 floats (i.e face_positions[0]) work just as expected. Then one value is skipped (i.e face_positions[1].x) and the next values read are the next 3 (i.e face_positions[1].y face_positions[1].z face_positions[2].x) then once again one value is skipped, and it starts reading the next value (i.e face_positions[2].z).&#xD;&#xA;&#xD;&#xA;So it seems somewhere something is padding the array with 0's to make everything 4 bytes aligned.&#xD;&#xA;&#xD;&#xA;Does anyone have any idea of where to start looking?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16049" PostHistoryTypeId="2" PostId="5814" RevisionGUID="16075d44-3eff-4e03-a343-551a832ada87" CreationDate="2017-11-03T02:18:07.130" UserId="7462" Text="Ok so, I keep reading papers about this and non of them have pictures. The lane Riesenfeld algorithm provides a way to subdivide set of points with B-spline conversion.&#xD;&#xA;&#xD;&#xA;The quesiton is simple HOW? If you can give me a set of pictures with the explanation that's be the best explanation, more than the math. &#xD;&#xA;&#xD;&#xA;The first step (i.e duplication of the original vertices) seems clear enough, but I do not fully understand how the mid point averaging works. &#xD;&#xA;&#xD;&#xA;Currently my very, very poor understanding is producing this:&#xD;&#xA;&#xD;&#xA;Starting with the following 4 points&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;We duplicate each point (denoted by the grey area)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;We take all odd points in our new set, and move them to the middle of the line connecting 2 consecutive points:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What do I do now? From here on I am just completely lost&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pOMeL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7Yn07.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/FR93Q.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16050" PostHistoryTypeId="1" PostId="5814" RevisionGUID="16075d44-3eff-4e03-a343-551a832ada87" CreationDate="2017-11-03T02:18:07.130" UserId="7462" Text="Visualizing the Lane-Riesenfeld Algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="16051" PostHistoryTypeId="3" PostId="5814" RevisionGUID="16075d44-3eff-4e03-a343-551a832ada87" CreationDate="2017-11-03T02:18:07.130" UserId="7462" Text="|algorithm|geometry|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16053" PostHistoryTypeId="2" PostId="5815" RevisionGUID="f7da1606-5870-4c4d-a869-23409bf1e875" CreationDate="2017-11-03T06:14:28.530" UserId="5944" Text="What's the meaning of the &quot;dynamic&quot; in &quot;high dynamic range&quot;?&#xD;&#xA;&#xD;&#xA;Why use this word?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16054" PostHistoryTypeId="1" PostId="5815" RevisionGUID="f7da1606-5870-4c4d-a869-23409bf1e875" CreationDate="2017-11-03T06:14:28.530" UserId="5944" Text="What's the meaning of the &quot;dynamic&quot; in &quot;high dynamic range&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16055" PostHistoryTypeId="3" PostId="5815" RevisionGUID="f7da1606-5870-4c4d-a869-23409bf1e875" CreationDate="2017-11-03T06:14:28.530" UserId="5944" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16056" PostHistoryTypeId="5" PostId="5787" RevisionGUID="6383650a-53af-4f58-9b36-0e4d87e42be7" CreationDate="2017-11-03T06:50:12.503" UserId="5256" Comment="added 293 characters in body" Text="In appendix **A** of the paper [Microfacet Models for Refraction through Rough Surfaces][1] there is a derivation provided for $\Lambda(w)$ but the mathematics is very confusing. Could somebody help me by explaining it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i)$ $=$ $G1(w_o)G1(w_i)$&#xD;&#xA;&#xD;&#xA;We can write the masking-shadowing function as the ratio of visible microfacet area to total forward facing microfacet area:&#xD;&#xA;&#xD;&#xA;$G1(w)$ $=$ $\Lambda^+(w) - \Lambda^-(w)\over \Lambda^+(w)$&#xD;&#xA;&#xD;&#xA;Shadow-masking functions are traditionally expressed in terms of auxiliary function $\Lambda(w)$, which measures invisible masked microfacet area per visible microfacet area.&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $\Lambda^-(w)\over \Lambda^+(w)-\Lambda^-(w)$&#xD;&#xA;&#xD;&#xA;The $\Lambda(w)$ function computes this. Its implementation is specific to each microfacet distribution. &#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $-1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this $\Lambda(w)$ function derived?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16057" PostHistoryTypeId="4" PostId="5787" RevisionGUID="6383650a-53af-4f58-9b36-0e4d87e42be7" CreationDate="2017-11-03T06:50:12.503" UserId="5256" Comment="added 293 characters in body" Text="Explanation of math of the Smith G1 term" ContentLicense="CC BY-SA 3.0" />
  <row Id="16058" PostHistoryTypeId="5" PostId="5787" RevisionGUID="cc29a23d-d0fc-4588-a88c-6d398e4b94a2" CreationDate="2017-11-03T07:33:11.523" UserId="5256" Comment="deleted 202 characters in body" Text="In appendix **A** of the paper [Microfacet Models for Refraction through Rough Surfaces][1] there is a derivation provided for $\Lambda(w)$ but the mathematics is very confusing. Could somebody help me by explaining it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i)$ $=$ $G1_{local}(w_o)G1_{dist}(w_i)$&#xD;&#xA;&#xD;&#xA;In the literature, the Smith masking function is often&#xD;&#xA;expressed as a fraction involving a function $\Lambda(w_o)$. This function is expressed&#xD;&#xA;as an integral over the slopes of the microsurface and its form is derived with a raytracing&#xD;&#xA;formulation of the masking probability.&#xD;&#xA;&#xD;&#xA;$G_1(w_o,w_m)$ $=$ $1\over1+\Lambda(w_o)$&#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $-1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this $\Lambda(w)$ function derived?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16059" PostHistoryTypeId="2" PostId="5816" RevisionGUID="9cb0c34e-fa29-4222-9f80-171d544c8fe0" CreationDate="2017-11-03T08:56:40.433" UserId="7622" Text="I have a .obj file with accompanying .mtl file and texture files. I want to extract the coordinates of the seams on my mesh. I then want to plot these seams in a 3D matrix in Python. Is there a fast way to do that?&#xD;&#xA;&#xD;&#xA;Further clarification: I have found a way recreate my mesh in my Python IDE using a library called Pymesh. I now want to plot the seams of my mesh (the ones that will give me the unwrap that I have in my texture files) in a 3D matrix as well. One way I could do this is to write a script that takes the edge points of all my UV islands, and then searches the .obj file for the 3D coordinates that they map to (and translate that into coordinates appropriate for my 3D matrix in Python). &#xD;&#xA;That will take a long time though - is there a faster way?&#xD;&#xA;I also asked this in the Blender StackExchange as I wasn't sure which was more appropriate. &#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16060" PostHistoryTypeId="1" PostId="5816" RevisionGUID="9cb0c34e-fa29-4222-9f80-171d544c8fe0" CreationDate="2017-11-03T08:56:40.433" UserId="7622" Text="Extract 3D seam coordinates from" ContentLicense="CC BY-SA 3.0" />
  <row Id="16061" PostHistoryTypeId="3" PostId="5816" RevisionGUID="9cb0c34e-fa29-4222-9f80-171d544c8fe0" CreationDate="2017-11-03T08:56:40.433" UserId="7622" Text="|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16062" PostHistoryTypeId="5" PostId="5787" RevisionGUID="eb2a7333-b747-4c4e-89c7-063107158159" CreationDate="2017-11-03T09:31:24.537" UserId="5256" Comment="deleted 13 characters in body" Text="In appendix **A** of the paper [Microfacet Models for Refraction through Rough Surfaces][1] there is a derivation provided for $\Lambda(w)$ but the mathematics is very confusing. Could somebody help me by explaining it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Smith's shadow masking function $G1$ gives the fraction of microfacets with normal $w_h$ that are visible from direction $w$. &#xD;&#xA;&#xD;&#xA;$G(w_o, w_i)$ $=$ $G_1(w_o)G_1(w_i)$&#xD;&#xA;&#xD;&#xA;In the literature, the Smith masking function is often&#xD;&#xA;expressed as a fraction involving a function $\Lambda(w_o)$. This function is expressed&#xD;&#xA;as an integral over the slopes of the microsurface and its form is derived with a raytracing&#xD;&#xA;formulation of the masking probability.&#xD;&#xA;&#xD;&#xA;$G_1(w_o,w_m)$ $=$ $1\over1+\Lambda(w_o)$&#xD;&#xA;&#xD;&#xA;For the Trowbridge-Reitz distribution it is quite simple:&#xD;&#xA;&#xD;&#xA;$\Lambda(w)$ $=$ $-1+ \sqrt{1+\alpha^2tan^2\theta}\over 2$&#xD;&#xA;&#xD;&#xA;How is this $\Lambda(w)$ function derived?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16063" PostHistoryTypeId="2" PostId="5817" RevisionGUID="a1f8cbb2-47b1-46bb-b2ec-29ad7c61b385" CreationDate="2017-11-03T09:58:13.187" UserId="137" Text="A seam can be defined as a line along the mesh where the vertices are doubled each with different texture coordinates.&#xD;&#xA;&#xD;&#xA;So that's what you should look for. The set of vertices where there is a twin in the same position with different texture coordinates.&#xD;&#xA;&#xD;&#xA;Depending on how the obj file was built that will be simple if they didn't duplicate the position when a vertex became part of a seam. Or it's not as simple because you need to deduplicate positions again.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16064" PostHistoryTypeId="2" PostId="5818" RevisionGUID="dc6ab42a-6382-4d49-a88f-c51a92641f3a" CreationDate="2017-11-03T13:59:27.610" UserId="2654" Text="&gt; [Dynamic, adjective:][1]&#xD;&#xA;&gt;&#xD;&#xA;&gt; 1: pertaining to or characterized by energy or effective action; vigorously active or forceful; energetic:&#xD;&#xA;&gt;&#xD;&#xA;&gt; ...&#xD;&#xA;&gt; &#xD;&#xA;&gt; 4: of or relating to the range of volume of musical sound.&#xD;&#xA;&#xD;&#xA;HDR allows you to deal with high light energies. And such high energies could be characterized as being &quot;vigorously active or forceful; energetic&quot;.&#xD;&#xA;&#xD;&#xA;But I think the fourth definition is more suitable. Graphics and rendering are forms of signal processing, much like sound. So they share a lot in common. For example, the term &quot;aliasing&quot; originated in digital conversion of sound.&#xD;&#xA;&#xD;&#xA;&quot;High light energies&quot; are the visual equivalent of &quot;volume&quot; in sound. So the &quot;dynamic range&quot; that you can record, the &quot;range of volume&quot; is high, as opposed to low.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.dictionary.com/browse/dynamic" ContentLicense="CC BY-SA 3.0" />
  <row Id="16065" PostHistoryTypeId="50" PostId="5676" RevisionGUID="20ff1d5d-4d7b-4cb0-90de-b8d4c919a060" CreationDate="2017-11-03T14:29:51.890" UserId="-1" />
  <row Id="16066" PostHistoryTypeId="2" PostId="5819" RevisionGUID="8155e39e-5419-44ad-9e87-149ac3b43fe4" CreationDate="2017-11-03T19:11:48.717" UserId="7413" Text="How can I check if a polygon (can also be irregular) can completely contain a circle of a certain radius? I do not want to actually inscribe the circle but just a boolean outcome whether or not it can be inscribed. I need this for an application that I'm developing in Java. &#xD;&#xA;&#xD;&#xA;Could someone share an algorithm or code snippet (any language is fine) or guide me to any relevant resource? Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="16067" PostHistoryTypeId="1" PostId="5819" RevisionGUID="8155e39e-5419-44ad-9e87-149ac3b43fe4" CreationDate="2017-11-03T19:11:48.717" UserId="7413" Text="How can I check if a polygon can completely contain a circle of a certain radius?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16068" PostHistoryTypeId="3" PostId="5819" RevisionGUID="8155e39e-5419-44ad-9e87-149ac3b43fe4" CreationDate="2017-11-03T19:11:48.717" UserId="7413" Text="|computational-geometry|polygon|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16069" PostHistoryTypeId="5" PostId="5819" RevisionGUID="0ac0b043-5387-4742-914a-0755dbc2668d" CreationDate="2017-11-03T19:17:24.513" UserId="7413" Comment="more clarification" Text="How can I check if a polygon (can also be irregular) can completely contain a circle of a certain radius? I do not want to actually draw a circle inside the polygon but just a boolean outcome whether or not it can be fit. I need this for an application that I'm developing in Java. Note that I'm not looking for the inscribed circle, but the largest circle that a polygon can contain. I suppose there can be multiple circles with the same area.&#xD;&#xA;&#xD;&#xA;Could someone share an algorithm or code snippet (any language is fine) or guide me to any relevant resource? Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="16070" PostHistoryTypeId="5" PostId="5811" RevisionGUID="bf775374-56c6-4525-8e25-616646b04b09" CreationDate="2017-11-04T00:14:12.827" UserId="7462" Comment="added 1 character in body" Text="I have a big cube made of smaller cubes, but sometimes, due to the fact that each side of the cube has different colors, I get some ugly colored lines that I would like to get rid off. Any advice is appreciated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;The BLACK lines and arrows are part of a texture, they are not relevant to my question, the focus is the RED line in the first picture and the red dots in the second picture. The lines appear mostly because this cube is made of smaller cubes put together side by side, so, depending on camera orientation, the side of a cube gets drawn on top of the front of the neighbouring cube.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6T6R9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qGpZs.png&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;The solution, at least for now, was to &quot;delete&quot; all faces that are not visible, this, for obvious reasons, eliminated the problem, but I am going to leave this question open in case someone comes up with a solution that does not involve hiding faces." ContentLicense="CC BY-SA 3.0" />
  <row Id="16072" PostHistoryTypeId="2" PostId="5820" RevisionGUID="e963c31c-4dd3-4d0a-9950-5e1eef858993" CreationDate="2017-11-04T13:14:09.480" UserId="4748" Text="This is likely more complicated than you would prefer, but: Compute the medial axis, which immediately yields the largest disks that fit inside the polygon.&#xD;&#xA;&#xD;&#xA;&gt; Chin, Francis, Jack Snoeyink, and Cao An Wang. &quot;Finding the medial axis of a simple polygon in linear time.&quot; Discrete &amp; Computational Geometry 21.3 (1999): 405-420.&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;[![medialax][1]][1]&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;&lt;sup&gt;&#xD;&#xA;(Image from [Alexander Tsvyashchenko](http://endl.ch/content/centerline).)&#xD;&#xA;&lt;/sup&gt;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;See also, [Largest circle inside a non-convex polygon](https://stackoverflow.com/a/4279633/387778) for an ad hoc approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R2ZKK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16073" PostHistoryTypeId="5" PostId="5820" RevisionGUID="b64ce592-4d58-45ed-96f0-5a996b1a6bfe" CreationDate="2017-11-04T13:55:46.393" UserId="4748" Comment="added 87 characters in body" Text="This is likely more complicated than you would prefer, but: Compute the medial axis, which immediately yields the largest disks that fit inside the polygon:&#xD;&#xA;their centers are vertices (degree $\ge 3$) of the axis (see the&#xD;&#xA;figure below).&#xD;&#xA;&#xD;&#xA;&gt; Chin, Francis, Jack Snoeyink, and Cao An Wang. &quot;Finding the medial axis of a simple polygon in linear time.&quot; Discrete &amp; Computational Geometry 21.3 (1999): 405-420.&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;[![medialax][1]][1]&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;&lt;sup&gt;&#xD;&#xA;(Image from [Alexander Tsvyashchenko](http://endl.ch/content/centerline).)&#xD;&#xA;&lt;/sup&gt;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;See also, [Largest circle inside a non-convex polygon](https://stackoverflow.com/a/4279633/387778) for an ad hoc approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R2ZKK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16074" PostHistoryTypeId="5" PostId="5820" RevisionGUID="848864a1-d38c-4eef-979a-446258097591" CreationDate="2017-11-04T15:45:45.487" UserId="4748" Comment="added 51 characters in body" Text="This is likely more complicated than you would prefer, but: Compute the medial axis, which immediately yields the largest disks that fit inside the polygon:&#xD;&#xA;their centers are vertices (degree $\ge 3$) of the axis (see the&#xD;&#xA;figure below).&#xD;&#xA;&#xD;&#xA;&gt; Chin, Francis, Jack Snoeyink, and Cao An Wang. &quot;Finding the medial axis of a simple polygon in linear time.&quot; *Discrete &amp; Computational Geometry* 21.3 (1999): 405-420.&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;[![medialax][1]][1]&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;&lt;sup&gt;&#xD;&#xA;(Image from [Alexander Tsvyashchenko](http://endl.ch/content/centerline).)&#xD;&#xA;&lt;/sup&gt;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;See also, [Largest circle inside a non-convex polygon](https://stackoverflow.com/a/4279633/387778) for an ad hoc approach&#xD;&#xA;(whose correctness I did not attempt to verify).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R2ZKK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16075" PostHistoryTypeId="5" PostId="5820" RevisionGUID="79296010-f9f3-4464-80b8-41f4ee085685" CreationDate="2017-11-04T23:05:19.717" UserId="4748" Comment="added 2 characters in body" Text="This is likely more complicated than you would prefer, but: Compute the medial axis, which immediately yields the largest disks that fit inside the polygon:&#xD;&#xA;their centers are vertices (degree $\ge 3$) of the axis (see the&#xD;&#xA;figure below).&#xD;&#xA;&#xD;&#xA;&gt; Chin, Francis, Jack Snoeyink, and Cao An Wang. &quot;Finding the medial axis of a simple polygon in linear time.&quot; *Discrete &amp; Computational Geometry* 21.3 (1999): 405-420.&#xD;&#xA;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;[![medialax][1]][1]&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;&lt;sup&gt;&#xD;&#xA;(Image from [Alexander Tsvyashchenko](http://endl.ch/content/centerline).)&#xD;&#xA;&lt;/sup&gt;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&#xD;&#xA;See also, [Largest circle inside a non-convex polygon](https://stackoverflow.com/a/4279633/387778) for an *ad hoc* approach&#xD;&#xA;(whose correctness I did not attempt to verify).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R2ZKK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16076" PostHistoryTypeId="5" PostId="5819" RevisionGUID="4b1b4603-d891-4d9d-b058-598e9273075b" CreationDate="2017-11-05T01:50:42.413" UserId="231" Comment="Remove thanks" Text="How can I check if a polygon (can also be irregular) can completely contain a circle of a certain radius? I do not want to actually draw a circle inside the polygon but just a boolean outcome whether or not it can be fit. I need this for an application that I'm developing in Java. Note that I'm not looking for the inscribed circle, but the largest circle that a polygon can contain. I suppose there can be multiple circles with the same area.&#xD;&#xA;&#xD;&#xA;Could someone share an algorithm or code snippet (any language is fine) or guide me to any relevant resource?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16079" PostHistoryTypeId="2" PostId="5821" RevisionGUID="5d560fee-6829-4292-8520-1ed52d9e8beb" CreationDate="2017-11-06T00:53:57.970" UserId="7635" Text="I'd like to develop a system for web animation similar to animated gifs, like [this one](https://www.sublimetext.com/~jps/animated_gifs_the_hard_way.html). I capture a series of screenshots at fixed time intervals, and then I'd like to animate them. I can trivially calculate the pixels which have changed from one frame to another, but I'd then like to calculate a set of rectangles such that blitting those rectangles over the previous frame results in the new one. There's a tradeoff between the number of rectangles and the number of &quot;wasted&quot; pixels, i.e. the number of pixels stored and copied which have not changed between the two frames. Is there a good algorithm for this which would give me control over the tradeoff parameter in some form?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16080" PostHistoryTypeId="1" PostId="5821" RevisionGUID="5d560fee-6829-4292-8520-1ed52d9e8beb" CreationDate="2017-11-06T00:53:57.970" UserId="7635" Text="Calculate set of rectangles covering pixel diffs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16081" PostHistoryTypeId="3" PostId="5821" RevisionGUID="5d560fee-6829-4292-8520-1ed52d9e8beb" CreationDate="2017-11-06T00:53:57.970" UserId="7635" Text="|algorithm|2d|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16082" PostHistoryTypeId="33" PostId="5814" RevisionGUID="0b576d0b-aa92-40f5-8d88-25e456fead2b" CreationDate="2017-11-06T02:42:49.153" UserId="7462" Comment="39" />
  <row Id="16083" PostHistoryTypeId="2" PostId="5822" RevisionGUID="215babf8-2dde-4077-9079-1dcc103055a8" CreationDate="2017-11-06T08:05:31.383" UserId="7000" Text="The [wiki](https://en.wikibooks.org/wiki/OpenGL_Programming/Installation/Linux) says the following about using OpenGL on Linux:&#xD;&#xA;&#xD;&#xA;&gt; Most Linux distributions rely on the Mesa3D project to provide their OpenGL implementation&#xD;&#xA;&#xD;&#xA;But it also says:&#xD;&#xA;&#xD;&#xA;&gt; OpenGL is included in drivers, so you'll have to make sure drivers are properly installed if you want to enjoy programs using OpenGL. Open source drivers actually make use of Mesa's OpenGL implementation.&#xD;&#xA;&#xD;&#xA;So I am a little confused:&#xD;&#xA;&#xD;&#xA;If I have an nVidia graphics card and install the nVidia drivers, do I need to install Mesa?&#xD;&#xA;&#xD;&#xA;What if I have the card but do not install nVidia's drivers?&#xD;&#xA;&#xD;&#xA;What, exactly, is meant by &quot;implementation&quot; in this context?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16084" PostHistoryTypeId="1" PostId="5822" RevisionGUID="215babf8-2dde-4077-9079-1dcc103055a8" CreationDate="2017-11-06T08:05:31.383" UserId="7000" Text="If I have an nVidia graphics card on Linux, do I need Mesa or FreeGLUT or anything like that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16085" PostHistoryTypeId="3" PostId="5822" RevisionGUID="215babf8-2dde-4077-9079-1dcc103055a8" CreationDate="2017-11-06T08:05:31.383" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16086" PostHistoryTypeId="2" PostId="5823" RevisionGUID="a85b5242-6471-4e78-a8eb-3046afbadee6" CreationDate="2017-11-06T08:11:29.510" UserId="2287" Text="Assume that we have voxelized the surroundings of the camera viewpoint in a 3D scene into a regular 3D grid of cubes, storing the average normal, average (diffuse) radiance and some flag indicating whether or not a voxel is empty. Next, the finer levels of the 3D texture (voxels) are downsampled to get coarser levels (&quot;pre-integrated&quot;) that will be stored as MIP levels for that texture. (*I know that some sparser structures can be used instead, but a regular grid is conceptually the most easiest to master first.*)&#xD;&#xA;&#xD;&#xA;Now, given that we have our surface position (and thus also the voxel we are in) and our surface normal, how does voxel cone tracing work and how is it applied?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16087" PostHistoryTypeId="1" PostId="5823" RevisionGUID="a85b5242-6471-4e78-a8eb-3046afbadee6" CreationDate="2017-11-06T08:11:29.510" UserId="2287" Text="How does voxel cone tracing work" ContentLicense="CC BY-SA 3.0" />
  <row Id="16088" PostHistoryTypeId="3" PostId="5823" RevisionGUID="a85b5242-6471-4e78-a8eb-3046afbadee6" CreationDate="2017-11-06T08:11:29.510" UserId="2287" Text="|global-illumination|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16089" PostHistoryTypeId="2" PostId="5824" RevisionGUID="3a8ddd16-aa7a-4dfc-bdeb-6e09525ef98e" CreationDate="2017-11-06T12:15:56.443" UserId="7640" Text="High Dynamic range, somtimes use as a feature in still image or in higher level in rolling image.&#xD;&#xA;It means that your shot has been captured by camera that can hold all information about exposure (at least in 3 modes: Overexpos, Normal and Underexpos).&#xD;&#xA;It is happening in high-end camera and high-end project.&#xD;&#xA;With this feature, you have alot of control in CC step like a pro." ContentLicense="CC BY-SA 3.0" />
  <row Id="16090" PostHistoryTypeId="2" PostId="5825" RevisionGUID="de7bd823-e0e9-47a6-807c-c5b5ab65332e" CreationDate="2017-11-06T12:36:34.677" UserId="7641" Text="Given a png image with an unknown number of green colored _(rgba=0, 65535, 0, 65535)_ regions [![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0nynM.png&#xD;&#xA;&#xD;&#xA;**1- How can I find and put the points of only the separate green boxes to an array like:**&#xD;&#xA;&#xD;&#xA;    [0] = []point{...} // the first box's points&#xD;&#xA;    [1] = []point{...} // the second box's points&#xD;&#xA;    [...] = []point{...} // &#xD;&#xA;    [7] = []point{...} // the last box's points&#xD;&#xA;&#xD;&#xA;**2- Which algorithm(s) should I use?**&#xD;&#xA;&#xD;&#xA;_I tried canny edge detector and my own custom ones but the canny algorithm finds all the regions not only the green ones_." ContentLicense="CC BY-SA 3.0" />
  <row Id="16091" PostHistoryTypeId="1" PostId="5825" RevisionGUID="de7bd823-e0e9-47a6-807c-c5b5ab65332e" CreationDate="2017-11-06T12:36:34.677" UserId="7641" Text="Extracting green-screen regions" ContentLicense="CC BY-SA 3.0" />
  <row Id="16092" PostHistoryTypeId="3" PostId="5825" RevisionGUID="de7bd823-e0e9-47a6-807c-c5b5ab65332e" CreationDate="2017-11-06T12:36:34.677" UserId="7641" Text="|image-processing|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16093" PostHistoryTypeId="5" PostId="5825" RevisionGUID="d7db72cd-d3c4-4d0d-9fca-0782463ccb1a" CreationDate="2017-11-06T12:43:07.863" UserId="7641" Comment="added 18 characters in body" Text="Given a png image with an unknown number of green colored _(rgba=0, 65535, 0, 65535)_ regions [![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0nynM.png&#xD;&#xA;&#xD;&#xA;**1- How can I find and put the points of only the separate green boxes to an array like:**&#xD;&#xA;&#xD;&#xA;    [0] = []point{...} // the first box's points&#xD;&#xA;    [1] = []point{...} // the second box's points&#xD;&#xA;    [...] = []point{...} // &#xD;&#xA;    [7] = []point{...} // the last box's points&#xD;&#xA;&#xD;&#xA;**2- Which algorithm(s) should I use?**&#xD;&#xA;&#xD;&#xA;_I tried canny edge detector and my own custom ones (like flood-fill) but the canny algorithm finds all the regions not only the green ones_." ContentLicense="CC BY-SA 3.0" />
  <row Id="16094" PostHistoryTypeId="2" PostId="5826" RevisionGUID="15cfc67b-0fbe-4f8e-8377-4f1a8031bb9d" CreationDate="2017-11-06T14:04:06.523" UserId="7008" Text="I want to implement a LOD algorithm that reduces the number of objects rather than the number of vertices of the objects.&#xD;&#xA;&#xD;&#xA;Imagine a forest, then close up I want to see all the trees but moving away from it there is no need to display every single tree, so I want to remove random trees (up to a threshold).&#xD;&#xA;&#xD;&#xA;So far I wasn't able to find current algorithms for this, but that may just be due to a lack of terminology: I have been looking for LOD algorithms. Maybe this technique exists under a different name, so I wanted to ask if there are such algorithms out there already?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16095" PostHistoryTypeId="1" PostId="5826" RevisionGUID="15cfc67b-0fbe-4f8e-8377-4f1a8031bb9d" CreationDate="2017-11-06T14:04:06.523" UserId="7008" Text="Are there LOD Algorithms that work through removing objects?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16096" PostHistoryTypeId="3" PostId="5826" RevisionGUID="15cfc67b-0fbe-4f8e-8377-4f1a8031bb9d" CreationDate="2017-11-06T14:04:06.523" UserId="7008" Text="|algorithm|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16097" PostHistoryTypeId="2" PostId="5827" RevisionGUID="544b839b-88ab-43bd-bcbd-a9114bee1cff" CreationDate="2017-11-06T14:58:53.097" UserId="7644" Text="Here's how I'd do it:&#xD;&#xA;&#xD;&#xA;Assign an sequential id to each tree. This can be an implicit id like an index in an array if you have this structure. The important part is that you can create N stable groups of trees that will be removed based on distance.&#xD;&#xA;&#xD;&#xA;Then decide at which distance you want to start removing each group of trees. Each tree group will have a specific distance at which it gets removed from the rendering. You must choose the appropriate granularity based on your use-case.&#xD;&#xA;&#xD;&#xA;Then, for each tree, compute its distance from the viewpoint and compare that with its removal distance to decide if it should be rendered or not. To get a nicer effect, use a fade-out distance over which the trees progressively disappear.&#xD;&#xA;&#xD;&#xA;Essentially the process is to tag trees with some LOD parameters (removal distance, fade distance, etc.) and remove them based on distance from the viewpoint." ContentLicense="CC BY-SA 3.0" />
  <row Id="16098" PostHistoryTypeId="2" PostId="5828" RevisionGUID="a28e1997-296b-430c-bb0e-9bb910874948" CreationDate="2017-11-06T15:07:57.027" UserId="7644" Text="Here is a brute force algorithm. This requires some temporary storage (another image, an array, etc.) to record the visited pixels.&#xD;&#xA;&#xD;&#xA; 1. Start at the first pixel and continue iterating over the image until you find a green pixel. Mark each read pixel as &quot;visited&quot;.&#xD;&#xA; 2. Extract the set of green neighbor pixels and record them. Also tag them as &quot;visited&quot;. The idea is to find all the green pixels connected to the one found in [1].&#xD;&#xA; 3. If any pixels in the source image are left, go back to [1].&#xD;&#xA;&#xD;&#xA;This will give you a set of contiguous green pixel regions where each pixel appears 1 or 0 times." ContentLicense="CC BY-SA 3.0" />
  <row Id="16099" PostHistoryTypeId="2" PostId="5829" RevisionGUID="f186c42b-250a-4e64-8cf3-53fbe8275cae" CreationDate="2017-11-06T15:13:02.983" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="16100" PostHistoryTypeId="1" PostId="5829" RevisionGUID="f186c42b-250a-4e64-8cf3-53fbe8275cae" CreationDate="2017-11-06T15:13:02.983" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="16101" PostHistoryTypeId="2" PostId="5830" RevisionGUID="17422ea7-63fd-44de-b788-1e5a2fc9b348" CreationDate="2017-11-06T15:13:02.983" UserId="-1" Text="" ContentLicense="CC BY-SA 3.0" />
  <row Id="16102" PostHistoryTypeId="1" PostId="5830" RevisionGUID="17422ea7-63fd-44de-b788-1e5a2fc9b348" CreationDate="2017-11-06T15:13:02.983" UserId="-1" ContentLicense="CC BY-SA 3.0" />
  <row Id="16103" PostHistoryTypeId="2" PostId="5831" RevisionGUID="96765bec-4414-4830-8310-9784584baf2a" CreationDate="2017-11-06T15:24:59.837" UserId="7413" Text="How can I find the vertices of a polygon (specifically hexagon) given the radius of the incircle? I want to calculate the vertices of a polygon given the face-to-face distance (inscribed circle radius?)&#xD;&#xA;&#xD;&#xA;I've below code to calculate the vertices from the Circum-circle of a polygon&#xD;&#xA;&#xD;&#xA;(x,y) - Center of the circumcircle&#xD;&#xA;&#xD;&#xA;r - Radius of the circumcircle&#xD;&#xA;&#xD;&#xA;        for (var i = 1; i &lt;= sides; i++)&#xD;&#xA;        {&#xD;&#xA;          var X = x + r * Math.Cos(2 * Math.PI * i / sides);&#xD;&#xA;          var Y = y + r * Math.Sin(2 * Math.PI * i / sides);&#xD;&#xA;        &#xD;&#xA;          vertices.Add(new Tuple(X,Y));&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Alternatively, what is the relation between radius of the in-circle and circum-circle of a polygon? Could you please share a relevant resource or a code snippet (any language is fine).&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="16104" PostHistoryTypeId="1" PostId="5831" RevisionGUID="96765bec-4414-4830-8310-9784584baf2a" CreationDate="2017-11-06T15:24:59.837" UserId="7413" Text="Vertices of a regular polygon given the incircle radius" ContentLicense="CC BY-SA 3.0" />
  <row Id="16105" PostHistoryTypeId="3" PostId="5831" RevisionGUID="96765bec-4414-4830-8310-9784584baf2a" CreationDate="2017-11-06T15:24:59.837" UserId="7413" Text="|computational-geometry|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16106" PostHistoryTypeId="5" PostId="5831" RevisionGUID="1eed6a2c-28c9-4a26-a02f-acefbff946a8" CreationDate="2017-11-06T15:35:16.820" UserId="7413" Comment="added 2 characters in body" Text="How can I find the vertices of a polygon (specifically hexagon) given the radius of the incircle? I want to calculate the vertices of a polygon given the face-to-face distance (inscribed circle diameter?)&#xD;&#xA;&#xD;&#xA;I've below code to calculate the vertices from the Circum-circle of a polygon&#xD;&#xA;&#xD;&#xA;(x,y) - Center of the circumcircle&#xD;&#xA;&#xD;&#xA;r - Radius of the circumcircle&#xD;&#xA;&#xD;&#xA;        for (var i = 1; i &lt;= sides; i++)&#xD;&#xA;        {&#xD;&#xA;          var X = x + r * Math.Cos(2 * Math.PI * i / sides);&#xD;&#xA;          var Y = y + r * Math.Sin(2 * Math.PI * i / sides);&#xD;&#xA;        &#xD;&#xA;          vertices.Add(new Tuple(X,Y));&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Alternatively, what is the relation between radius of the in-circle and circum-circle of a polygon? Could you please share a relevant resource or a code snippet (any language is fine).&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="16110" PostHistoryTypeId="2" PostId="5833" RevisionGUID="5fddc8b0-8bf6-4774-bd1e-c4803eec3af6" CreationDate="2017-11-06T15:56:48.057" UserId="137" Text="&gt; what is the relation between radius of the in-circle and circum-circle of a polygon?&#xD;&#xA;&#xD;&#xA;That is $cos ( \frac{2\pi}{n}*\frac{1}{2} ) = cos ( \frac{\pi}{n})$&#xD;&#xA;&#xD;&#xA;The triangle with edges from the center to the middle of a side, from the center to an adjacent corner and half the side connecting them is a right angle triangle. The angle of the point at the center $ =\frac\pi 2$. &#xD;&#xA;&#xD;&#xA;Then it's simply the cosine to get the ratio between adjacent and hypotenuse." ContentLicense="CC BY-SA 3.0" />
  <row Id="16111" PostHistoryTypeId="5" PostId="5830" RevisionGUID="472a9dc9-c5ad-4e8a-8811-de3c211a4f98" CreationDate="2017-11-06T22:39:42.120" UserId="5778" Comment="added 247 characters in body" Text="This is a special tag that is designed to be used only by the system for questions that have had all of their other tags removed. Do not add this tag to existing questions, it is reserved for use by the system to identify posts with no valid tags." ContentLicense="CC BY-SA 3.0" />
  <row Id="16112" PostHistoryTypeId="24" PostId="5830" RevisionGUID="472a9dc9-c5ad-4e8a-8811-de3c211a4f98" CreationDate="2017-11-06T22:39:42.120" Comment="Proposed by 5778 approved by 231 edit id of 287" ContentLicense="CC BY-SA 3.0" />
  <row Id="16113" PostHistoryTypeId="2" PostId="5834" RevisionGUID="7e5d0399-d3ee-45e6-a59f-12bb90a4777c" CreationDate="2017-11-07T07:43:09.977" UserId="110" Text="From https://en.wikipedia.org/wiki/Dynamic_range&#xD;&#xA;&#xD;&#xA;&gt; Dynamic range, abbreviated DR, DNR, or DYR is the ratio between the&#xD;&#xA;&gt; largest and smallest values that a certain quantity can assume.&#xD;&#xA;&#xD;&#xA;In the case of HDR, this refers to the ratio of the highest/lowest luminance values that can be perceived or represented." ContentLicense="CC BY-SA 3.0" />
  <row Id="16114" PostHistoryTypeId="5" PostId="5825" RevisionGUID="6b5f1738-e132-4572-b168-09229cb6c790" CreationDate="2017-11-07T08:54:40.160" UserId="7641" Comment="added 7 characters in body; edited title" Text="Given a png image with an unknown number of green colored _(rgba=0, 65535, 0, 65535)_ regions [![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0nynM.png&#xD;&#xA;&#xD;&#xA;**1- How can I find and put the border points of only the separate green boxes to an array like:**&#xD;&#xA;&#xD;&#xA;    [0] = []point{...} // the first box's points&#xD;&#xA;    [1] = []point{...} // the second box's points&#xD;&#xA;    [...] = []point{...} // &#xD;&#xA;    [7] = []point{...} // the last box's points&#xD;&#xA;&#xD;&#xA;**2- Which algorithm(s) should I use?**&#xD;&#xA;&#xD;&#xA;_I tried canny edge detector and my own custom ones (like flood-fill) but the canny algorithm finds all the regions not only the green ones_." ContentLicense="CC BY-SA 3.0" />
  <row Id="16115" PostHistoryTypeId="4" PostId="5825" RevisionGUID="6b5f1738-e132-4572-b168-09229cb6c790" CreationDate="2017-11-07T08:54:40.160" UserId="7641" Comment="added 7 characters in body; edited title" Text="Extracting the green-screen region borders" ContentLicense="CC BY-SA 3.0" />
  <row Id="16116" PostHistoryTypeId="2" PostId="5835" RevisionGUID="cd703019-458d-424d-bf9b-6a6a39cb9a63" CreationDate="2017-11-07T10:08:34.453" UserId="7647" Text="The Lane-Riesenfeld algorithm subdivides the control polygon of a B-spline to create a new control polygon with the same limit spline.  It's made up of two steps: first, duplicating all of the control points $P_i$ into $P^\prime_{2i}$ and $P^\prime_{2i+1}$; then, moving each point to the midpoint between it and the next point, so $P^\prime_i \rightarrow \frac{1}{2} P^\prime_i + \frac{1}{2}P^\prime_{i+1}$.  These steps are illustrated in the figure:&#xD;&#xA;&#xD;&#xA;[![One duplication and one movement step][1]][1]&#xD;&#xA;&#xD;&#xA;On the left is an initial control polygon.  In the middle, I've duplicated the vertices.  On the right, the vertices have moved halfway to the next vertex.  Notice that only half of the vertices move in the first movement step: this is because $P^\prime_{2i} = P^\prime_{2i+1},$ but $P^\prime_{2i+1} \neq P^\prime_{2i+2}.$  These eight vertices are a refined control polygon for the linear B-spline defined by the initial four vertices.&#xD;&#xA;&#xD;&#xA;Now, we can do a second movement step (without another duplication):&#xD;&#xA;&#xD;&#xA;[![Second movement step and new polygon][2]][2]&#xD;&#xA;&#xD;&#xA;On the left, we've moved each vertex to the midpoint between it and its neighbour; note that all of the vertices move this time (since none are in the same position).  On the right, we have drawn the polygon with these eight vertices.  This is a refined control polygon for the *quadratic* B-spline defined by the initial four vertices.  You may also recognize this as the same polygon you get by Chaikin corner-cutting, which also gets you the quadratic B-spline.&#xD;&#xA;&#xD;&#xA;Now we can perform more duplicate-move-move steps to further refine the polygon, and thus more closely approximate the quadratic B-spline curve:&#xD;&#xA;&#xD;&#xA;[![Further refinements of the quadratic B-spline control polygon][3]][3]&#xD;&#xA;&#xD;&#xA;If, instead, we do a third movement step without a duplication step (that is, one duplication followed by three successive movements) we get a refined control polygon for the *cubic* B-spline defined by the initial four vertices:&#xD;&#xA;&#xD;&#xA;[![Cubic B-spline refinement by dup-move-move-move steps][4]][4]&#xD;&#xA;&#xD;&#xA;In general, doing $k$ movement steps after each duplicate gives us the refined polygon for the $C^k$ B-spline.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d7Dfn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gjIca.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/AXVhV.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/HaIxE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16121" PostHistoryTypeId="2" PostId="5837" RevisionGUID="f4158272-3df1-48a1-9fa8-d353e11e43db" CreationDate="2017-11-07T19:45:52.777" UserId="7541" Text="I am trying to use a linear transformation to straighten out the camera angle on this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In other words, I want to transform the image into a head-on view of the whiteboard.&#xD;&#xA;&#xD;&#xA;I applied an affine transformation to that image, identifying the top left, top right, and bottom left corners, thinking that it would turn the image into a 1080x720 rectangle. However, here's what I ended up with:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, it is NOT a rectangle, but some sort of misshapen quadrilateral. It's close, but not exactly a head-on view of the whiteboard!&#xD;&#xA;&#xD;&#xA;What exactly happened here? I really thought an affine transformation would work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/03ys6.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/k5UFZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16122" PostHistoryTypeId="1" PostId="5837" RevisionGUID="f4158272-3df1-48a1-9fa8-d353e11e43db" CreationDate="2017-11-07T19:45:52.777" UserId="7541" Text="Why does an affine transform work only on three of the corners?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16123" PostHistoryTypeId="3" PostId="5837" RevisionGUID="f4158272-3df1-48a1-9fa8-d353e11e43db" CreationDate="2017-11-07T19:45:52.777" UserId="7541" Text="|image-processing|affine-transformations|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16125" PostHistoryTypeId="2" PostId="5838" RevisionGUID="316a26eb-b81d-4b1d-af3a-af18802f46a4" CreationDate="2017-11-07T20:54:25.020" UserId="48" Text="An affine transformation doesn't have enough freedom to do what you want. Affine transforms can be constructed to map any triangle to any other triangle, but they can't map any quadrilateral to any other quadrilateral.&#xD;&#xA;&#xD;&#xA;One way to see this is that the matrix for a 2D affine transform has only 6 free coefficients. That's enough to specify what it does to 3 points, but not 4.&#xD;&#xA;&#xD;&#xA;For this task you likely want a projective transformation. A 2D projective transformation has enough freedom to [map any convex quadrilateral to any other](http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/)." ContentLicense="CC BY-SA 3.0" />
  <row Id="16127" PostHistoryTypeId="2" PostId="5839" RevisionGUID="b184d683-e310-4c55-b6f0-7e7b60651618" CreationDate="2017-11-08T05:12:05.033" UserId="7541" Text="As @user1118321 mentioned, as well as @NathanReed in [this answer][1] to another question, you can do a perspective transform to transform [any convex quadrilateral to any other][2].&#xD;&#xA;&#xD;&#xA;[OpenCV][3] has a good library for doing perspective transformations if you don't want to roll your own.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/5838/7541&#xD;&#xA;  [2]: http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/&#xD;&#xA;  [3]: https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#getperspectivetransform" ContentLicense="CC BY-SA 3.0" />
  <row Id="16129" PostHistoryTypeId="2" PostId="5840" RevisionGUID="88de4424-18a2-4cc3-96ad-2bf817af4def" CreationDate="2017-11-08T13:41:36.453" UserId="2041" Text="The Mesa3D project is a software implementation of OpenGL; that is, an implementation that does all the rendering on the CPU with no GPU involvement at all. It's designed in two layers: a backend which renders each frame from some internal state, and a frontend which implements the OpenGL API and sets up the state for the backend to use. Most OpenGL implementations have a similar two-layer architecture, so that the same backend can be used by an OpenGL frontend, an OpenCL frontend, a Direct3D frontend, etc.&#xD;&#xA;&#xD;&#xA;The open-source NVidia drivers (and most open-source drivers) use Mesa's frontend to provide the OpenGL API and a backend specific to that GPU. The OpenGL API is quite complicated to implement, so it makes sense for vendors to share an existing front-end in this way. However, closed-source drivers do not use Mesa's frontend and have their own closed-source frontend.&#xD;&#xA;&#xD;&#xA;If you install and use a closed-source GPU driver, it will include its own libgl, which doesn't use Mesa at all. You don't need to install anything else to run OpenGL applications. (You might need an extra &quot;-dev&quot; package to get the header files needed to *compile* OpenGL applications.)&#xD;&#xA;&#xD;&#xA;If you install and use an open-source GPU driver, it will use Mesa, but the packages in your distribution should have the dependencies set up correctly, so that if an external Mesa package is needed, it will be installed automatically.&#xD;&#xA;&#xD;&#xA;Either way, you shouldn't have to worry about whether the OpenGL implementation you're using is based on Mesa or not." ContentLicense="CC BY-SA 3.0" />
  <row Id="16130" PostHistoryTypeId="2" PostId="5841" RevisionGUID="79022e48-b3d9-45a4-95e8-2cfa46968e2b" CreationDate="2017-11-08T17:41:25.870" UserId="5424" Text="The paper (http://resources.mpi-inf.mpg.de/DeepScreenSpace/) just says that &#xD;&#xA;&#xD;&#xA;&gt; &quot;The ambient occlusion contribution of a surfel to a pixel [..] as&#xD;&#xA;&gt; well as the influence radius [..] are computed using the point-to-disk&#xD;&#xA;&gt; form factor [Wallace et al. 1989]&quot;&#xD;&#xA;&#xD;&#xA;*Wallace et al. 1989, A ray tracing algorithm for progressive radiosity*&#xD;&#xA;&#xD;&#xA;Does that mean that, in order to test for occlusion, rays are shot from a surfel to other surfels within its influence radius?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16131" PostHistoryTypeId="1" PostId="5841" RevisionGUID="79022e48-b3d9-45a4-95e8-2cfa46968e2b" CreationDate="2017-11-08T17:41:25.870" UserId="5424" Text="How is Ambient Occlusion calculated in &quot;Deep Screen Space&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16132" PostHistoryTypeId="3" PostId="5841" RevisionGUID="79022e48-b3d9-45a4-95e8-2cfa46968e2b" CreationDate="2017-11-08T17:41:25.870" UserId="5424" Text="|rendering|real-time|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16133" PostHistoryTypeId="50" PostId="5697" RevisionGUID="3eedba03-0cd7-437c-bd9c-959e079b7308" CreationDate="2017-11-08T20:36:46.107" UserId="-1" />
  <row Id="16135" PostHistoryTypeId="4" PostId="5379" RevisionGUID="1bf74e37-1abf-4770-b378-c1fce51602bc" CreationDate="2017-11-09T09:01:49.107" UserId="7000" Comment="edited title" Text="How do I include all extensions my system supports using GLAD?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16136" PostHistoryTypeId="5" PostId="5835" RevisionGUID="af795708-ddbe-4024-924d-735b82be271d" CreationDate="2017-11-09T12:36:49.520" UserId="7647" Comment="Added animations" Text="The Lane-Riesenfeld algorithm subdivides the control polygon of a B-spline to create a new control polygon with the same limit spline.  It's made up of two steps: first, duplicating all of the control points $P_i$ into $P^\prime_{2i}$ and $P^\prime_{2i+1}$; then, moving each point to the midpoint between it and the next point, so $P^\prime_i \rightarrow \frac{1}{2} P^\prime_i + \frac{1}{2}P^\prime_{i+1}$.  These steps are illustrated in the figure:&#xD;&#xA;&#xD;&#xA;[![One duplication and one movement step][1]][1]&#xD;&#xA;&#xD;&#xA;On the left is an initial control polygon.  In the middle, I've duplicated the vertices.  On the right, the vertices have moved halfway to the next vertex.  Notice that only half of the vertices move in the first movement step: this is because $P^\prime_{2i} = P^\prime_{2i+1},$ but $P^\prime_{2i+1} \neq P^\prime_{2i+2}.$  These eight vertices are a refined control polygon for the linear B-spline defined by the initial four vertices.&#xD;&#xA;&#xD;&#xA;Now, we can do a second movement step (without another duplication):&#xD;&#xA;&#xD;&#xA;[![Second movement step and new polygon][2]][2]&#xD;&#xA;&#xD;&#xA;On the left, we've moved each vertex to the midpoint between it and its neighbour; note that all of the vertices move this time (since none are in the same position).  On the right, we have drawn the polygon with these eight vertices.  This is a refined control polygon for the *quadratic* B-spline defined by the initial four vertices.  You may also recognize this as the same polygon you get by Chaikin corner-cutting, which also gets you the quadratic B-spline.&#xD;&#xA;&#xD;&#xA;Now we can perform more duplicate-move-move steps to further refine the polygon, and thus more closely approximate the quadratic B-spline curve:&#xD;&#xA;&#xD;&#xA;[![Further refinements of the quadratic B-spline control polygon][3]][3]&#xD;&#xA;&#xD;&#xA;Here's an animation of this process:&#xD;&#xA;&#xD;&#xA;[![Animation of LR algorithm creating quadratic B-spline][4]][4]&#xD;&#xA;&#xD;&#xA;If, instead, we do a third movement step without a duplication step (that is, one duplication followed by three successive movements) we get a refined control polygon for the *cubic* B-spline defined by the initial four vertices:&#xD;&#xA;&#xD;&#xA;[![Cubic B-spline refinement by dup-move-move-move steps][5]][5]&#xD;&#xA;&#xD;&#xA;An animation of this process:&#xD;&#xA;&#xD;&#xA;[![Animation of LR algorithm creating cubic B-spline][6]][6]&#xD;&#xA;&#xD;&#xA;In general, doing $k$ movement steps after each duplicate gives us the refined polygon for the $C^k$ B-spline.&#xD;&#xA;&#xD;&#xA;**EDIT**: Added animations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d7Dfn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gjIca.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/AXVhV.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Q29mn.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/HaIxE.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/94Um1.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="16138" PostHistoryTypeId="2" PostId="5842" RevisionGUID="76e2862e-03d3-4552-ad35-fe5af3e60d8b" CreationDate="2017-11-09T21:35:32.930" UserId="7661" Text="I want create some LED-rope text, using some script font. For this I need somewhat estimate the needed lenghth of the LED-rope for the given letter (or combinations of letters).&#xD;&#xA;&#xD;&#xA;Some more info:&#xD;&#xA;&#xD;&#xA;- The font will be TTF or FT2.&#xD;&#xA;- I could manage some programs in perl using the FreeType library, eg. read some properties of the character in the font-file - if this helps.&#xD;&#xA;- Also could install Inkscape (Illustrator  opensource alternative) or even could use Illustrator at my friend - if any of this tools could help.&#xD;&#xA;&#xD;&#xA;Looking for some suggestions how to measure the length of paths in the given font for the particular character (or whole text).&#xD;&#xA;&#xD;&#xA;Of course not need exact precision, (see the purpose above) and looking for the solution _as simple as possible_, but I haven't any idea how even approach this problem. :(&#xD;&#xA;&#xD;&#xA;Ps: I'm not fully sure that this is the right place to ask such question, if not - I will delete it, but please suggest some better place." ContentLicense="CC BY-SA 3.0" />
  <row Id="16139" PostHistoryTypeId="1" PostId="5842" RevisionGUID="76e2862e-03d3-4552-ad35-fe5af3e60d8b" CreationDate="2017-11-09T21:35:32.930" UserId="7661" Text="How to get the length of paths in an given font/character" ContentLicense="CC BY-SA 3.0" />
  <row Id="16140" PostHistoryTypeId="3" PostId="5842" RevisionGUID="76e2862e-03d3-4552-ad35-fe5af3e60d8b" CreationDate="2017-11-09T21:35:32.930" UserId="7661" Text="|transformations|computational-geometry|pathtracing|vector-graphics|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16141" PostHistoryTypeId="5" PostId="5842" RevisionGUID="dab7cde7-a500-491a-821d-7873424406be" CreationDate="2017-11-09T21:57:36.003" UserId="7661" Comment="added 307 characters in body" Text="I wan't create some LED-rope text, using some script font, like the following:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;For this I need somewhat estimate the needed length of the LED-rope for the given letter (or combinations of letters).&#xD;&#xA;&#xD;&#xA;Some more info:&#xD;&#xA;&#xD;&#xA;- The font will be TTF or FT2.&#xD;&#xA;- I could manage some programs in perl using the FreeType library, eg. read some properties of the character in the font-file - if this helps.&#xD;&#xA;- Also could install Inkscape (Illustrator  open-source alternative) or even could use Illustrator at my friend - if any of this tools could help.&#xD;&#xA;&#xD;&#xA;**Looking for some suggestions how to measure the length of paths in the given font for the particular character (or whole text).**&#xD;&#xA;&#xD;&#xA;I don't need exact precision, (see the purpose above) and looking for the solution _as simple as possible_, but I haven't any idea how even approach this problem. :(&#xD;&#xA;&#xD;&#xA;Of course, I always could print the text and buy some inexpensive [curve runner](https://en.wikipedia.org/wiki/Opisometer), but would be better to have some computer-based solution. :)&#xD;&#xA;&#xD;&#xA;Ps: I'm not fully sure that this is the right place to ask such question, if not - I will delete it, but please suggest some better place.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SRt9c.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16143" PostHistoryTypeId="2" PostId="5843" RevisionGUID="69a0236c-9c6b-410f-9261-f7d41474656b" CreationDate="2017-11-09T23:23:17.673" UserId="7462" Text="I am following this tutorial: http://flafla2.github.io/2014/08/09/perlinnoise.html&#xD;&#xA;&#xD;&#xA;To understand Perlin Noise. In particular, right now I am focusing on the following code section:&#xD;&#xA;&#xD;&#xA;        int xi = (int)x &amp; 255;                              // Calculate the &quot;unit cube&quot; that the point asked will be located in&#xD;&#xA;        int yi = (int)y &amp; 255;                              // The left bound is ( |_x_|,|_y_|,|_z_| ) and the right bound is that&#xD;&#xA;        int zi = (int)z &amp; 255;                              // plus 1.  Next we calculate the location (from 0.0 to 1.0) in that cube.&#xD;&#xA;        double xf = x-(int)x;&#xD;&#xA;        double yf = y-(int)y;&#xD;&#xA;        double zf = z-(int)z;&#xD;&#xA;&#xD;&#xA;If I am correct, the first 3 lines of code are calculating a set of 3 coordinates (xi,yi,zi) that range from 0 to 255 inclusive, as integers. This is, in other words, a 255x255x255 3D grid of unit cubes.&#xD;&#xA;&#xD;&#xA;The next 3 lines are calculating the relative 0-1 coordinates inside of the cube in the grid the point (x,y,z) is mapped to.&#xD;&#xA;&#xD;&#xA;My question is:&#xD;&#xA;&#xD;&#xA;Is there any reason for this number to be 255? Or is this simply a number that was chosen because it made the algorithm faster (smaller grid, less numbers, faster hash lookup, caching...) and could easily be extended to any other integer (theoretically).&#xD;&#xA;&#xD;&#xA;In either case, won't this generate a repetitive pattern?&#xD;&#xA;&#xD;&#xA;What I mean by the second question is: If I have a set of (x,y,z) values that extend to &quot;infinity&quot; at regular intervals (let's say they all change at intervals of 1), won't I start seeing a clearly predictable/repetitive pattern emerge after around 255 steps in a given direction? &#xD;&#xA;&#xD;&#xA;Finally, if a repetitive pattern emerges, how can you create more variation while keeping pseudo randomness?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16144" PostHistoryTypeId="1" PostId="5843" RevisionGUID="69a0236c-9c6b-410f-9261-f7d41474656b" CreationDate="2017-11-09T23:23:17.673" UserId="7462" Text="Help understanding Perlin Noise" ContentLicense="CC BY-SA 3.0" />
  <row Id="16145" PostHistoryTypeId="3" PostId="5843" RevisionGUID="69a0236c-9c6b-410f-9261-f7d41474656b" CreationDate="2017-11-09T23:23:17.673" UserId="7462" Text="|algorithm|noise|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16146" PostHistoryTypeId="2" PostId="5844" RevisionGUID="c4e6d135-8d49-465c-8b45-024a42ec0e6f" CreationDate="2017-11-10T03:11:42.277" UserId="48" Text="Yep, you've got that right. In Perlin's reference implementation of &quot;improved noise&quot;, the noise will be periodic, repeating after 256 units along each axis. It's usually not very noticeable even if you have a large extent of noise visible, since there's no large-scale features for the eye to track.&#xD;&#xA;&#xD;&#xA;But there's no particular reason it needs to tile after 256 units; that's pretty much just an arbitrary choice made by Perlin. He uses a permutation table as a hash function to map grid coordinates to gradient vectors, and the hard-coded table is of size 256, so has to be tiled after that.&#xD;&#xA;&#xD;&#xA;However, any other hash function you like could be used as well. It just has to pseudorandomly map the integer parts of the x, y, z coordinates to a gradient vector." ContentLicense="CC BY-SA 3.0" />
  <row Id="16147" PostHistoryTypeId="2" PostId="5845" RevisionGUID="70422e04-62f6-4398-b589-d4d69b9ec10c" CreationDate="2017-11-10T04:37:10.783" UserId="3003" Text="The way I would approach this is to get the outline curves of the font and then break each one down into some fixed number of steps (like, say, 100), and make a series of very small straight lines.&#xD;&#xA;&#xD;&#xA;So if you've got some bezier curve, you loop `t` from 0 to 1 in 100 steps and plug it into the equation:&#xD;&#xA;&#xD;&#xA;    double x = calculateBezier(0.0, c0.x, c1.x, c2.x, c3.x);&#xD;&#xA;    double y = calculateBezier(0.0, c0.y, c1.y, c2.y, c3.y);&#xD;&#xA;    double dist = 0.0;&#xD;&#xA;    for (double t = 0.01; t &lt;= 1.0; t+= 0.01)&#xD;&#xA;    {&#xD;&#xA;        double nextX = calculateBezier(t, c0.x, c1.x, c2.x, c3.x);&#xD;&#xA;        double nextY = calculateBezier(t, c0.y, c1.y, c2.y, c3.y);&#xD;&#xA;        double nextDist = sqrt((nextX - x) * (nextX - x) + (nextY - y) * (nextY - y));&#xD;&#xA;        dist += nextDist;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Where `calculateBezier()` is a function that calculates a point on a bezier curve given the parameter `t` and control points `c0` through `c3`:&#xD;&#xA;&#xD;&#xA;    double calculateBezier(double t, double c0, double c1, double c2, double c3)&#xD;&#xA;    {&#xD;&#xA;        double t1 = 1.0 - t;&#xD;&#xA;&#xD;&#xA;        return (t1 * t1 * t1) * c0 + 3.0 * (t1 * t1) * c1 + &#xD;&#xA;                3.0 * t1 * (t * t) * c2 + (t * t * t) * c3;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And just add the distances of each part of the curve until you're out of curves.&#xD;&#xA;&#xD;&#xA;Note that this assumes cubic bezier curves. For quadratic, the `calculateBezier` function would calculate a quadratic one (like described [here](https://en.wikipedia.org/wiki/Bézier_curve#Quadratic_B.C3.A9zier_curves))." ContentLicense="CC BY-SA 3.0" />
  <row Id="16148" PostHistoryTypeId="2" PostId="5846" RevisionGUID="ad85512c-5f1a-44b7-8d7b-798921969a9c" CreationDate="2017-11-10T06:20:24.977" UserId="7462" Text="I have been playing around for a day with Perlin noise, and I am currently stuck. Most of the modifications I have made to the algorithm produce more or less the following:&#xD;&#xA;&#xD;&#xA;[![Perlin noice][1]][1]&#xD;&#xA;&#xD;&#xA;Now, this is a very good start, but the idea is to generate terrain similar to real life (as close as I can get at least). Rivers and lakes would be nice to have, but that's way ahead in the schedule, right now I would like some help understanding 2 things.&#xD;&#xA;&#xD;&#xA;Let's say that in my image, black is water and grey is land this is quite unlike the earth's shores. On earth continents are large masses of land and if they are cut by watter, it's usually on large areas (Imagine the Mexican gulf or the Mediterranean sea). However my image has a lot of narrow elongated &quot;peninsulas&quot; with patches of water around it. Due to the nature of Perlin noise (the square grid with the underlying random vector field) I am not sure how to create those large clusters of land and water. &#xD;&#xA;&#xD;&#xA;The other problem is vertical, if we see the grey scale as a height map, these islands are too odd. In real life one would have large sections of flat land with elongated mountain ranges cutting through.&#xD;&#xA;&#xD;&#xA;Some options that I have considered are, changing the smoothing/fade function in the improved Perlin noise algorithm for one that extends over multiple squares in the grid, but this adds too much computational complexity. I have also considered changing the vector field generation from pseudo random to one that follows a pattern, but this doesn't seem like it would actually solve the problem given that Perlin noise, as is, doesn't seem able to generate large consistent clusters.&#xD;&#xA;&#xD;&#xA;Thanks in advance&#xD;&#xA;  [1]: https://i.stack.imgur.com/LNK39.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16149" PostHistoryTypeId="1" PostId="5846" RevisionGUID="ad85512c-5f1a-44b7-8d7b-798921969a9c" CreationDate="2017-11-10T06:20:24.977" UserId="7462" Text="How to modify Perlin (not simplex) noise to create continental like terrain generation" ContentLicense="CC BY-SA 3.0" />
  <row Id="16150" PostHistoryTypeId="3" PostId="5846" RevisionGUID="ad85512c-5f1a-44b7-8d7b-798921969a9c" CreationDate="2017-11-10T06:20:24.977" UserId="7462" Text="|algorithm|noise|procedural-generation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16151" PostHistoryTypeId="5" PostId="5846" RevisionGUID="33fdffd6-bdf5-4872-a53f-b3ff43db4625" CreationDate="2017-11-10T07:44:56.277" UserId="7462" Comment="added 670 characters in body" Text="I have been playing around for a day with Perlin noise, and I am currently stuck. Most of the modifications I have made to the algorithm produce more or less the following:&#xD;&#xA;&#xD;&#xA;[![Perlin noice][1]][1]&#xD;&#xA;&#xD;&#xA;Now, this is a very good start, but the idea is to generate terrain similar to real life (as close as I can get at least). Rivers and lakes would be nice to have, but that's way ahead in the schedule, right now I would like some help understanding 2 things.&#xD;&#xA;&#xD;&#xA;Let's say that in my image, black is water and grey is land this is quite unlike the earth's shores. On earth continents are large masses of land and if they are cut by watter, it's usually on large areas (Imagine the Mexican gulf or the Mediterranean sea). However my image has a lot of narrow elongated &quot;peninsulas&quot; with patches of water around it. Due to the nature of Perlin noise (the square grid with the underlying random vector field) I am not sure how to create those large clusters of land and water. &#xD;&#xA;&#xD;&#xA;The other problem is vertical, if we see the grey scale as a height map, these islands are too odd. In real life one would have large sections of flat land with elongated mountain ranges cutting through.&#xD;&#xA;&#xD;&#xA;Some options that I have considered are, changing the smoothing/fade function in the improved Perlin noise algorithm for one that extends over multiple squares in the grid, but this adds too much computational complexity. I have also considered changing the vector field generation from pseudo random to one that follows a pattern, but this doesn't seem like it would actually solve the problem given that Perlin noise, as is, doesn't seem able to generate large consistent clusters.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;I know about octaves, but they have their limitations, re-sampling perlin noise at different frequencies and amplitudes does change the terrain generation and ca give you some good results:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But even this has issues.&#xD;&#xA;For example if I want smooth hills I loose jaggy shores, same as if I try to create more valleys. And doing this also reduces the likelihood of generating islands in the middle of the bodies of water, moreover in terms of topography, the mountains look chaotic, they don't really from mountain ranges, they rather spread semi-chaoticly, which is not exactly what I need. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LNK39.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Wd6Da.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16152" PostHistoryTypeId="2" PostId="5847" RevisionGUID="879d392f-072d-43db-af94-0b16bda43cd0" CreationDate="2017-11-10T08:24:07.170" UserId="182" Text="Perlin noise is just a base block, not very interesting by itself.&#xD;&#xA;&#xD;&#xA;A first step is to combine and filter it. Look at how to make fractal Brownian noise (fBm) with it for example, which uses combines octaves in interesting ways based on few parameters. On his website, [Iñigo Quilez mentions that technique a lot, and also how to fake erosion][1].&#xD;&#xA;&#xD;&#xA;The question of terrain rendering is a difficult one and a topic of active research. Many generated terrains have this artificial and uninteresting look. This is exactly what the paper [&quot;Modeling Real-World Terrain with Exponentially Distributed Noise&quot;][2] tries to address, by proposing a formula based on statistics measured from actual terrain, which yields more convincing shapes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.iquilezles.org/www/articles/morenoise/morenoise.htm&#xD;&#xA;  [2]: http://jcgt.org/published/0004/02/01/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16153" PostHistoryTypeId="5" PostId="5847" RevisionGUID="5edb315b-760b-492b-bb50-29473db23466" CreationDate="2017-11-10T08:32:04.707" UserId="182" Comment="added 104 characters in body" Text="Perlin noise is just a base block, not very interesting by itself. You don't need to modify it, but to combine and filter it in interesting ways. Look at how to make [fractal Brownian motion (fBm)][1] with it for example, which combines octaves based on few parameters to get a richer texture.&#xD;&#xA;&#xD;&#xA;The question of terrain rendering is a difficult one and a topic of active research. Many generated terrains have this artificial and uninteresting look. This is exactly what the paper [&quot;Modeling Real-World Terrain with Exponentially Distributed Noise&quot;][2] tries to address, by proposing a formula based on statistics measured from actual terrain, which yields more convincing shapes.&#xD;&#xA;&#xD;&#xA;Another source of valuable information is [Iñigo Quilez's website][3], where he mentions procedural generation a lot, [including tricks to fake erosion][4].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Fractional_Brownian_motion&#xD;&#xA;  [2]: http://jcgt.org/published/0004/02/01/&#xD;&#xA;  [3]: http://www.iquilezles.org/www/&#xD;&#xA;  [4]: http://www.iquilezles.org/www/articles/morenoise/morenoise.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="16154" PostHistoryTypeId="2" PostId="5848" RevisionGUID="d569bafc-46af-483c-ab47-ee05bde3aa90" CreationDate="2017-11-10T09:11:31.297" UserId="7661" Text="I decided to solve the LED-rope problem using Inkscape as:&#xD;&#xA;&#xD;&#xA;- enter the wanted text into the Inkscape&#xD;&#xA;- set the color of the text to yellow&#xD;&#xA;- add new layer above the text and lock the text layer&#xD;&#xA;- in the new layer, manually draw over the letters my own wanted bezier path(s)&#xD;&#xA;- and finally use the tool in `Extensions -&gt; Visualise Path -&gt; Measure Path...` - this adds the length of the given bezier path into the drawing as text.&#xD;&#xA;&#xD;&#xA;The reason why:&#xD;&#xA;&#xD;&#xA;I studied a bit the ttf-font structure (the whole new world for me). [This blog entry](http://stevehanov.ca/blog/index.php?id=143) and this [Reference manual](https://developer.apple.com/fonts/TrueType-Reference-Manual/) helped a lot understanding the following (rough) basics.&#xD;&#xA;&#xD;&#xA;- the given glyph (character) is composed from many _closed paths_, e.g. the letter `O` is composed from two paths (outer circle and the inner circle).&#xD;&#xA;- the paths are stored in the font file as pairs of x-y coordinates&#xD;&#xA;- so it isn't so hard to calculate the length of _each_ path from the given coordinates.&#xD;&#xA;- _but_ - in such way I will get the lengths of the all _outlines_. Creating the outlines using the LED-rope it could be even interesting and also it is used at many examples, (like bellow), but this isn't what I want - I want a simple path(s) - as in the image in the question.&#xD;&#xA;- getting such _simple path_ from the font's many outlines would need some tracing and approximation and other complicated math, which is definitely outside of my area of interest.&#xD;&#xA;- therefore (for me) would be much easier just manually create the simple path's and measure their length in the Inkscape.&#xD;&#xA;&#xD;&#xA;Also,&#xD;&#xA;&#xD;&#xA;- if someone want the length of the font's outlines, it is easily doable&#xD;&#xA;- just need break apart the text into characters&#xD;&#xA;- transform the (font) objects into the strokes&#xD;&#xA;- and use the `Measure path...` tool&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gk26Z.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16161" PostHistoryTypeId="2" PostId="5850" RevisionGUID="41feb79a-814e-4373-9917-44083f1af603" CreationDate="2017-11-10T16:33:17.410" UserId="7663" Text="I have 2 images, called left and right images. I have some matched points $[c_l,r_l]$ and $[c_r,r_r]$ in both of them (these points are in pixel coordinates). &#xD;&#xA;&#xD;&#xA;For a 3D point in the real world, they are related by:&#xD;&#xA;&#xD;&#xA;$\lambda_l*[c_l , r_l,1]^t = W_l*[X,Y,Z]^t$&#xD;&#xA;&#xD;&#xA;$\lambda_r*[c_r ,r_r,1]^t = W_r*[R|T]*[X,Y,Z,1]^t$&#xD;&#xA;&#xD;&#xA;Here $W_l$ and $W_r$ are the intrinsic parameters of the left and right cameras and $T and R$ are the relative / overall translation and rotation between the cameras.&#xD;&#xA;&#xD;&#xA;I attempted to solve this as:&#xD;&#xA;&#xD;&#xA;$Q*[M,1]^T = 0$&#xD;&#xA;&#xD;&#xA;where Q is &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;        \begin{matrix}&#xD;&#xA;        (k_1 +k_2-k_3*c_r-k_3*r_r) &amp; (tw_x + tw_y -r_r*tw_z - c_r*tw_z) \\&#xD;&#xA;        (w_1 + w_2 - w_3*c_l -w_3*r_l) &amp; 0 \\&#xD;&#xA;        \end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and M is $[X,Y,Z]$&#xD;&#xA;&#xD;&#xA;Here:&#xD;&#xA;&#xD;&#xA; - $k1,k2, k3$ are the rows of the matrix K given by $K = R_r*R$&#xD;&#xA; - $tw$ is the vector formed by $tw = W_r*T$, its elements are&#xD;&#xA;   $[tw_x,tw_y,tw_z]$&#xD;&#xA; - $w1, w2, w3$ are the rows of the matrix $W_l$&#xD;&#xA;&#xD;&#xA;I'm solving this as: &#xD;&#xA;&#xD;&#xA;$Q*[M,1]^t = 0$&#xD;&#xA;&#xD;&#xA;I look for a solution in the null space of $Q$. &#xD;&#xA;&#xD;&#xA;$[M,1]^t$ would be hence be the null vector of Q.&#xD;&#xA;&#xD;&#xA;That is,&#xD;&#xA;&#xD;&#xA;$svd(Q) = [U,S,V]$ and $[M,1]^t$ would be the last column of *V*.&#xD;&#xA;&#xD;&#xA;The result I get would be of form $[mx,my,mz,mk]$ so I simply divide all elements by $mk$ to get something of the form&#xD;&#xA;&#xD;&#xA;$[mx/mk,my/mk,mz/mk,1]$. I consider this to be the value of *X,Y,Z* &#xD;&#xA;&#xD;&#xA;Is there a better way to solve this? Correct me if I'm wrong here but I'm feel this could have been done in a simpler (more accurate) fashion." ContentLicense="CC BY-SA 3.0" />
  <row Id="16162" PostHistoryTypeId="1" PostId="5850" RevisionGUID="41feb79a-814e-4373-9917-44083f1af603" CreationDate="2017-11-10T16:33:17.410" UserId="7663" Text="3D reconstruction using 2D matched points" ContentLicense="CC BY-SA 3.0" />
  <row Id="16163" PostHistoryTypeId="3" PostId="5850" RevisionGUID="41feb79a-814e-4373-9917-44083f1af603" CreationDate="2017-11-10T16:33:17.410" UserId="7663" Text="|image-processing|geometry|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16164" PostHistoryTypeId="33" PostId="5841" RevisionGUID="58ae1fc6-1c56-4bc4-958e-17e32d562b52" CreationDate="2017-11-10T18:21:35.103" UserId="5424" Comment="40" />
  <row Id="16165" PostHistoryTypeId="5" PostId="5841" RevisionGUID="4b188b7e-969d-4a3b-ace8-cd6cb599ee68" CreationDate="2017-11-10T18:23:25.283" UserId="5424" Comment="added 100 characters in body" Text="The paper (http://resources.mpi-inf.mpg.de/DeepScreenSpace/) just says that &#xD;&#xA;&#xD;&#xA;&gt; &quot;The ambient occlusion contribution of a surfel to a pixel [..] as&#xD;&#xA;&gt; well as the influence radius [..] are computed using the point-to-disk&#xD;&#xA;&gt; form factor [Wallace et al. 1989]&quot;&#xD;&#xA;&#xD;&#xA;*Wallace et al. 1989, A ray tracing algorithm for progressive radiosity*&#xD;&#xA;&#xD;&#xA;Does that mean that, in order to test for occlusion, rays are shot from a surfel to other surfels within its influence radius? That's just a speculation. Unfortunately the paper does not really explain how they implemented AO." ContentLicense="CC BY-SA 3.0" />
  <row Id="16171" PostHistoryTypeId="10" PostId="5781" RevisionGUID="b3f889ca-53ea-4ca5-a25c-d68eae263aab" CreationDate="2017-11-10T21:55:24.527" UserId="231" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[3742],&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="16174" PostHistoryTypeId="2" PostId="5852" RevisionGUID="41caa1b9-b017-4a38-9474-79092f2b5ae4" CreationDate="2017-11-11T16:15:30.437" UserId="7482" Text="I have an object(cow).&#xD;&#xA;&#xD;&#xA;This cow was translated and rotated(with arbitrary axis) in the modeling space for several times.&#xD;&#xA;&#xD;&#xA;And I can't know how much cow is translated or rotated.&#xD;&#xA;&#xD;&#xA;Only I can obtain is this cow's current matrix and it's inverse.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In this circumstance, how can I rotate the cow around the x-axis in the viewing space?&#xD;&#xA;&#xD;&#xA;(center of rotation is at the center of modeling space)" ContentLicense="CC BY-SA 3.0" />
  <row Id="16175" PostHistoryTypeId="1" PostId="5852" RevisionGUID="41caa1b9-b017-4a38-9474-79092f2b5ae4" CreationDate="2017-11-11T16:15:30.437" UserId="7482" Text="OpenGL : How to rotate an object around viewing space x-axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="16176" PostHistoryTypeId="3" PostId="5852" RevisionGUID="41caa1b9-b017-4a38-9474-79092f2b5ae4" CreationDate="2017-11-11T16:15:30.437" UserId="7482" Text="|opengl|transformations|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16178" PostHistoryTypeId="2" PostId="5853" RevisionGUID="d4b17bce-222e-4e86-83c8-a55a5773ca21" CreationDate="2017-11-11T20:41:18.200" UserId="7669" Text="[Here’s](https://youtu.be/dZG60_c29EI) a video that talks about a couple different techniques.&#xA;&#xA;One idea mentioned in the video is to take the values from 0.0 to 1.0 you get from the noise and only care about ones within a certain range, (mapping the rest to 0.0). Further, you can map the values in that range to different values, following a curve. For instance if you take the values between 0.25 and 0.75 you can map 0.5 to 1.0 and fill in the values in between with a straight line. &#xA;&#xA;Another technique mentioned is to compose your noise function. Say you have a noise function that takes a 2d vector, you can call `Vec2(Noise(pos), Noise(pos + offset))` to get a vector you can put into the noise function again. This gives an interesting skewed/streaky look. " ContentLicense="CC BY-SA 3.0" />
  <row Id="16179" PostHistoryTypeId="2" PostId="5854" RevisionGUID="8fbf1804-0566-4fb4-a90f-93540b4cde0a" CreationDate="2017-11-12T00:23:49.170" UserId="7000" Text="If I am writing my own function to check shader compile errors, or do anything that interacts with the OpenGL API but ultimately returns as a result of my application code, should I use the C++ `void` or `GLvoid`?&#xD;&#xA;&#xD;&#xA;I.E.&#xD;&#xA;&#xD;&#xA;    GLvoid Shader::check_compile_errors(GLuint ComputeShader, std::string type)&#xD;&#xA;    {&#xD;&#xA;    	const GLint log_length{ 1024 };&#xD;&#xA;    	GLchar info_log[log_length];&#xD;&#xA;    	GLint success;&#xD;&#xA;    &#xD;&#xA;    	if (type == &quot;PROGRAM&quot;)&#xD;&#xA;    	{&#xD;&#xA;    		glGetProgramiv(ComputeShader, GL_LINK_STATUS, &amp;success);&#xD;&#xA;    		if (!success)&#xD;&#xA;    		{&#xD;&#xA;    			glGetProgramInfoLog(ComputeShader, log_length, nullptr, info_log);&#xD;&#xA;    			std::cout &lt;&lt; &quot;ERROR::PROGRAM_LINKING_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; info_log &lt;&lt; &quot;\n ---- &quot; &lt;&lt; std::endl;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;     // Here the return is implicitly void, but from C++ not OpenGL!&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I realize here that `GLvoid` is typedef'd to void but I am wondering if there is any case where using the GL types could cause issues when it it is not explictly clear that the values are coming from OpenGL.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16180" PostHistoryTypeId="1" PostId="5854" RevisionGUID="8fbf1804-0566-4fb4-a90f-93540b4cde0a" CreationDate="2017-11-12T00:23:49.170" UserId="7000" Text="Is there ever a time when I should *not* use the GL* types?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16181" PostHistoryTypeId="3" PostId="5854" RevisionGUID="8fbf1804-0566-4fb4-a90f-93540b4cde0a" CreationDate="2017-11-12T00:23:49.170" UserId="7000" Text="|opengl|types|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16182" PostHistoryTypeId="5" PostId="5854" RevisionGUID="1cddb6ed-0463-4b23-8abb-7fff9fbcd5ba" CreationDate="2017-11-12T01:53:53.330" UserId="7000" Comment="added 208 characters in body" Text="If I am writing my own function to check shader compile errors, or do anything that interacts with the OpenGL API but ultimately returns as a result of my application code, should I use the C++ `void` or `GLvoid`?&#xD;&#xA;&#xD;&#xA;I.E.&#xD;&#xA;&#xD;&#xA;    GLvoid Shader::check_compile_errors(GLuint ComputeShader, std::string type)&#xD;&#xA;    {&#xD;&#xA;    	const GLint log_length{ 1024 };&#xD;&#xA;    	GLchar info_log[log_length];&#xD;&#xA;    	GLint success;&#xD;&#xA;    &#xD;&#xA;    	if (type == &quot;PROGRAM&quot;)&#xD;&#xA;    	{&#xD;&#xA;    		glGetProgramiv(ComputeShader, GL_LINK_STATUS, &amp;success);&#xD;&#xA;    		if (!success)&#xD;&#xA;    		{&#xD;&#xA;    			glGetProgramInfoLog(ComputeShader, log_length, nullptr, info_log);&#xD;&#xA;    			std::cout &lt;&lt; &quot;ERROR::PROGRAM_LINKING_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; info_log &lt;&lt; &quot;\n ---- &quot; &lt;&lt; std::endl;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;     // Here the return is implicitly void, but from C++ not OpenGL!&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I realize here that `GLvoid` is typedef'd to void but I am wondering if there is any case where using the GL types could cause issues when it it is not explictly clear that the values are coming from OpenGL.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another example would be writing an image to a file (from `glReadPixels`). If I am setting fields in the header which normally takes things in the form `unsigned char` should I change that to a `GLuchar`?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16183" PostHistoryTypeId="2" PostId="5855" RevisionGUID="2655fc41-125d-4dff-bac2-9673dcf9f37e" CreationDate="2017-11-12T02:27:15.337" UserId="2654" Text="Yes, there's a time not to use GL types when interacting with OpenGL: `GLvoid`. There is absolutely no reason to use this type.&#xD;&#xA;&#xD;&#xA;With everything else (assuming you're using a &quot;standard&quot; OpenGL loader), you should use OpenGL's types when *talking to OpenGL*. That is, the values you pass to OpenGL functions should be in OpenGL's types. This may mean that a function that talks to OpenGL may need an OpenGL data type in its function parameter list. This should be avoided where possible, to prevent you from creating dependencies between OpenGL code and non-OpenGL code.&#xD;&#xA;&#xD;&#xA;However, if you don't mind having large portions of your application have dependencies on OpenGL, you may use OpenGL's data types throughout your code.&#xD;&#xA;&#xD;&#xA;OpenGL's data types are specified to have a particular bitdepth. As such, they are (conceptually, if not strictly C++-legally) pointer-interconvertible to certain types defined in `&lt;stdint.h&gt;/&lt;cstdint&gt;`. Indeed, many OpenGL headers will check for the existence of this header and use it wherever it is available to define OpenGL's data types. As such, if you want a fixed bitdepth integer, you have a choice besides using OpenGL's data types.&#xD;&#xA;&#xD;&#xA;&gt; I am wondering if there is any case where using the GL types could cause issues when it it is not explictly clear that the values are coming from OpenGL.&#xD;&#xA;&#xD;&#xA;OpenGL is C, not *magic*. A function in C cannot have any control over the return value of the function that calls it. Even a C++ function cannot; at best, it can throw an exception, but this still doesn't have anything to do with its caller's return value." ContentLicense="CC BY-SA 3.0" />
  <row Id="16184" PostHistoryTypeId="5" PostId="5559" RevisionGUID="168ca9cb-c1df-4528-ae8e-f6487f53816f" CreationDate="2017-11-12T02:31:07.540" UserId="2654" Comment="edited body" Text="`glMemoryBarrier` is for when you want to make [writes from one rendering command visible to reads from a subsequent rendering command][1].&#xD;&#xA;&#xD;&#xA;That is, you can do all the atomics you like during a rendering command. But without the barrier, there's no guarantee that any of those atomic actions will be visible to later commands. Yes, they will still be *atomic*, but this only ensures that they will each execute in some order and each operation will fully execute before the next. What they won't ensure is that operations which OpenGL defines has happening &quot;later&quot; will execute before earlier operations.&#xD;&#xA;&#xD;&#xA;Sometimes, you actually don't care about the order of the operations; being atomic may be enough. And sometimes, you *do care*.&#xD;&#xA;&#xD;&#xA;Consider the case of a &quot;linked-list&quot; style blending buffer. Each pixel in the image is an integer that represents one of the items in the list. Each FS invocation will use an atomic increment to get a unique identifier, then swap that identifier with the current value in the image. It writes its pixel data to the entry in an SSBO, along with the identifier it swapped out of the image.&#xD;&#xA;&#xD;&#xA;When doing that atomic increment on the unique identifier, you don't care if FS invocations from two different rendering commands execute out of order. You simply need the operation to be atomic. Similarly, the swap doesn't have to be in order; it just needs to be atomic. As long as they all execute, and the atomic operations do their jobs, then they will be fine.&#xD;&#xA;&#xD;&#xA;Now, when it comes time to do blending based on this data, *that* is when you need to be able to read all of the data that was previously written. And that rendering operation requires `glMemoryBarrier`.&#xD;&#xA;&#xD;&#xA;Of course, you're not necessarily using atomic operations to *read* these values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Memory_Model#Incoherent_memory_access" ContentLicense="CC BY-SA 3.0" />
  <row Id="16192" PostHistoryTypeId="2" PostId="5858" RevisionGUID="a25b1068-f96a-40fc-b0af-ce131ecc3149" CreationDate="2017-11-12T18:20:38.473" UserId="7674" Text="I have some previous experience in OpenGL from a few years back, and recently got myself up to speed on DirectX 11. My current laptop has a fairly old Intel integrated GPU which was good enough for following tutorials and implementing simple techniques using those APIs.&#xD;&#xA;&#xD;&#xA;I am now keen on getting to grips with Vulkan and DirectX 12, as well as performance profiling, and so I am in the market for a new high-end GPU.&#xD;&#xA;&#xD;&#xA;Ignoring the usual price/performance metric for GPUs, is there a pragmatic reason to prefer AMD over Nvidia or vice versa? A cursory search shows that some tools are exclusive to one vendor (e.g. Nvidia Nsight), but is one significantly better than the other or are the differences minor? Will drivers make a difference here also?&#xD;&#xA;&#xD;&#xA;I want to be using the best available tools so I can get to grips quickly and minimise the amount of hair pulling caused by potentially mysterious issues." ContentLicense="CC BY-SA 3.0" />
  <row Id="16193" PostHistoryTypeId="1" PostId="5858" RevisionGUID="a25b1068-f96a-40fc-b0af-ce131ecc3149" CreationDate="2017-11-12T18:20:38.473" UserId="7674" Text="Should I prefer an AMD or Nvidia GPU for studying graphics programming, especially in respect to debugging and profiling tools?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16194" PostHistoryTypeId="3" PostId="5858" RevisionGUID="a25b1068-f96a-40fc-b0af-ce131ecc3149" CreationDate="2017-11-12T18:20:38.473" UserId="7674" Text="|gpu|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16195" PostHistoryTypeId="5" PostId="5858" RevisionGUID="c20d86a5-6735-4105-a125-8fb020824b1e" CreationDate="2017-11-12T20:09:29.047" UserId="7674" Comment="Remove irrelevant info, clarify question." Text="My current laptop has a fairly old Intel integrated GPU which was good enough for following simple tutorials.&#xD;&#xA;&#xD;&#xA;I am now keen on getting to grips with advanced techniques and newer APIs, and so I am looking for a new discrete GPU.&#xD;&#xA;&#xD;&#xA;I want to ignore the usual price/performance metric for GPUs, as I assume that's going to be irrelevant for a hobbyist programmer.&#xD;&#xA;&#xD;&#xA;Is there a pragmatic reason to prefer AMD over Nvidia or vice versa?&#xD;&#xA;&#xD;&#xA;A cursory search shows that some tools are exclusive to one vendor (e.g. Nvidia Nsight), but is one significantly better than the other or are the differences minor?&#xD;&#xA;&#xD;&#xA;Will drivers make a difference here also? And finally will I run into a lot of example code specific to one vendor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16196" PostHistoryTypeId="4" PostId="5858" RevisionGUID="c20d86a5-6735-4105-a125-8fb020824b1e" CreationDate="2017-11-12T20:09:29.047" UserId="7674" Comment="Remove irrelevant info, clarify question." Text="Should I prefer an AMD or Nvidia GPU for studying graphics programming, especially with respect to vendor specific debugging tools and ecosystem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16197" PostHistoryTypeId="50" PostId="4632" RevisionGUID="dc6e56be-2294-4357-9dc7-6f1192dbb5e3" CreationDate="2017-11-12T20:36:14.957" UserId="-1" />
  <row Id="16198" PostHistoryTypeId="2" PostId="5859" RevisionGUID="176173a5-7198-435b-a5e0-6712984c0aca" CreationDate="2017-11-12T20:43:52.890" UserId="6838" Text="I have been recently exploring physically-based rendering (PBR), but there is one part that still confuses me. I don't quite get roughness remapping, as described in the [PBR section][1] on Learn OpenGL. Specifically, scroll down until you find *Geometry function*. This remapping is described in several other papers / courses as well, such as [Disney][2] and [Epic Game's PBR Course][3]. Is this remapping solely artistic, or is there some physical reasoning in it? A quick answer and explanation would be quite appreciated :)&#xD;&#xA;&#xD;&#xA;TL;DR What in the world is roughness remapping for?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/#!PBR/Theory/ &quot;PBR Theory&quot;&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf/ &quot;Disney PBR&quot;&#xD;&#xA;  [3]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf/ &quot;Real Shading in Unreal Engine 4&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16199" PostHistoryTypeId="1" PostId="5859" RevisionGUID="176173a5-7198-435b-a5e0-6712984c0aca" CreationDate="2017-11-12T20:43:52.890" UserId="6838" Text="Roughness Remapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="16200" PostHistoryTypeId="3" PostId="5859" RevisionGUID="176173a5-7198-435b-a5e0-6712984c0aca" CreationDate="2017-11-12T20:43:52.890" UserId="6838" Text="|rendering|lighting|brdf|pbr|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16201" PostHistoryTypeId="50" PostId="5301" RevisionGUID="b14c6c65-1edc-4183-9462-c57e2f7b5c50" CreationDate="2017-11-12T21:36:14.373" UserId="-1" />
  <row Id="16202" PostHistoryTypeId="50" PostId="5300" RevisionGUID="517558da-4215-425f-b0b5-17a3f074559f" CreationDate="2017-11-12T23:36:14.577" UserId="-1" />
  <row Id="16203" PostHistoryTypeId="2" PostId="5860" RevisionGUID="ab216555-c669-4651-af23-3768df59fafe" CreationDate="2017-11-13T01:31:53.133" UserId="7675" Text="I have two columns of data, x(angle) and y(distance), they are my experiment results(figure 1). How can I use these results to make a ‘hotmap diagram’ by matlab? The z axis is the density value of xy dots in the 2D coordinate department, like below figure2. Thank you!&#xA;[![enter image description here][1]][1]&#xA;[![enter image description here][2]][2]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/CVbH8.jpg&#xA;  [2]: https://i.stack.imgur.com/swpBg.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16204" PostHistoryTypeId="1" PostId="5860" RevisionGUID="ab216555-c669-4651-af23-3768df59fafe" CreationDate="2017-11-13T01:31:53.133" UserId="7675" Text="Matlab scatter hotmap" ContentLicense="CC BY-SA 3.0" />
  <row Id="16205" PostHistoryTypeId="3" PostId="5860" RevisionGUID="ab216555-c669-4651-af23-3768df59fafe" CreationDate="2017-11-13T01:31:53.133" UserId="7675" Text="|image-processing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16206" PostHistoryTypeId="2" PostId="5861" RevisionGUID="e9ee1cab-6680-48ec-94ea-cdec04363b1e" CreationDate="2017-11-13T07:51:43.630" UserId="4650" Text="I'm wondering what happens with the framebuffer between the time that the fragment shader is done, and the time when it appears on my screen. &#xD;&#xA;&#xD;&#xA;Is my understanding correct if I assume that the framebuffer is in memory on the GPU, which is then copied back to the CPU side after glDrawX is completed, and then fit to a window somewhere on the screen, and then sent through my HDMI cable (via the GPU again!) to my monitor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16207" PostHistoryTypeId="1" PostId="5861" RevisionGUID="e9ee1cab-6680-48ec-94ea-cdec04363b1e" CreationDate="2017-11-13T07:51:43.630" UserId="4650" Text="What happens with the framebuffer after the fragment shader is done?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16208" PostHistoryTypeId="3" PostId="5861" RevisionGUID="e9ee1cab-6680-48ec-94ea-cdec04363b1e" CreationDate="2017-11-13T07:51:43.630" UserId="4650" Text="|frame-buffer|hardware|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16209" PostHistoryTypeId="2" PostId="5862" RevisionGUID="2bfff02b-8220-438f-9299-174ca0916c01" CreationDate="2017-11-13T08:08:18.760" UserId="6041" Text="How can I plot an input signal as an image, like below ones? &#xD;&#xA;&#xD;&#xA;The images are from [these slides][1] on image processing.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Or this one:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.robots.ox.ac.uk/~az/lectures/ia/lect2.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/4ZhOo.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/LjYJ8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16210" PostHistoryTypeId="1" PostId="5862" RevisionGUID="2bfff02b-8220-438f-9299-174ca0916c01" CreationDate="2017-11-13T08:08:18.760" UserId="6041" Text="How to plot an input signal in image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16211" PostHistoryTypeId="3" PostId="5862" RevisionGUID="2bfff02b-8220-438f-9299-174ca0916c01" CreationDate="2017-11-13T08:08:18.760" UserId="6041" Text="|image-processing|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16212" PostHistoryTypeId="34" PostId="5814" RevisionGUID="6de3bba8-9a16-4be6-83db-2c51f610fba8" CreationDate="2017-11-13T09:13:48.430" UserId="7462" Comment="39" />
  <row Id="16213" PostHistoryTypeId="2" PostId="5863" RevisionGUID="a3e8cf1a-ea9d-4bc6-a839-2696ba4c1b48" CreationDate="2017-11-13T09:42:58.247" UserId="2041" Text="It entirely depends what hardware and OS you're on. It's up to the integration between the windowing system and GL. In the simple case where one application is rendering full-screen directly, the framebuffer is in memory that's accessible by both the GPU and the display controller. After the GPU is finished, and when the display controller gets to a vsync (the time to start drawing a new frame to the screen), the display controller just reads out the framebuffer.&#xD;&#xA;&#xD;&#xA;In a compositing system like modern MS Windows or Android, your app's framebuffer is not used by the display controller directly. After you finish drawing your frame, the compositor runs. On the GPU, it reads in your framebuffer, puts it in the right place on the desktop, and writes the composited desktop into the real framebuffer. The display controller then reads out the desktop framebuffer. There's also an optimization possible using [overlays](https://computergraphics.stackexchange.com/q/5271/20410), which we have another question about.&#xD;&#xA;&#xD;&#xA;Copying completed frames into CPU memory is to be avoided. If you had to do this every frame, your application probably couldn't run at a reasonable frame-rate. Even reading back a single pixel (with `glReadPixels`) is a big slow-down, because the CPU has to wait for the GPU to finish, and they have to invalidate the cache of any shared memory. Reading back a million pixels is extra slow on desktop because the CPU and GPU have separate memory and the path between them is relatively slow. It's very rare that it should be necessary: mainly it's needed for screenshots, or for debugging." ContentLicense="CC BY-SA 3.0" />
  <row Id="16214" PostHistoryTypeId="2" PostId="5864" RevisionGUID="26c26e82-b63a-4456-af53-44323265a616" CreationDate="2017-11-13T09:49:43.823" UserId="2041" Text="If you're using Python, you can use a library such as matplotlib for this. It can take a numpy array and plot it as a standard chart using the function `plot` or as an image using `imshow`. The resulting image/plot can be displayed in an interactive window, or saved to a file, or it shows inline in your Jupyter notebook if you're using that.&#xD;&#xA;&#xD;&#xA;There are other (better?) Python chart plotting libraries but the functionality is basic and IMO matplotlib is easier to get started with (perhaps just because it's older and more established).&#xD;&#xA;&#xD;&#xA;You can also do this using OpenCV, if your input is an OpenCV image. Its plotting functions are named similarly to the matplotlib ones. OpenCV is available in Python, C++, and a handful of other languages." ContentLicense="CC BY-SA 3.0" />
  <row Id="16215" PostHistoryTypeId="5" PostId="5862" RevisionGUID="0ae2b994-1c96-4900-9ddf-e6d98a8cb3e8" CreationDate="2017-11-13T10:32:58.587" UserId="6041" Comment="added 63 characters in body" Text="Given an input signal(ex. sine) how can one go about plotting an image like below ones(the stripped black and white image)? &#xD;&#xA;&#xD;&#xA;The images are from [these slides][1] on image processing.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Or this one:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.robots.ox.ac.uk/~az/lectures/ia/lect2.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/4ZhOo.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/LjYJ8.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16216" PostHistoryTypeId="2" PostId="5865" RevisionGUID="76a1dafb-269e-424c-9328-967a8bffaa0b" CreationDate="2017-11-13T10:38:51.130" UserId="2041" Text="GL's types aren't true types but `typedef`s for platform types. So when you think about `GLuint` *vs.* `unsigned int`, you should consider that in the same way you consider `unsigned int` *vs.* `uint32_t`. If you are only writing for a single platform, you should read your system's `GL/gl.h` and pay attention to the section that looks like this:&#xD;&#xA;&#xD;&#xA;    typedef unsigned int	GLenum;&#xD;&#xA;    typedef unsigned char	GLboolean;&#xD;&#xA;    typedef unsigned int	GLbitfield;&#xD;&#xA;    typedef void		GLvoid;&#xD;&#xA;    typedef signed char	GLbyte;		/* 1-byte signed */&#xD;&#xA;    typedef short		GLshort;	/* 2-byte signed */&#xD;&#xA;    typedef int		GLint;		/* 4-byte signed */&#xD;&#xA;    typedef unsigned char	GLubyte;	/* 1-byte unsigned */&#xD;&#xA;    typedef unsigned short	GLushort;	/* 2-byte unsigned */&#xD;&#xA;    typedef unsigned int	GLuint;		/* 4-byte unsigned */&#xD;&#xA;    typedef int		GLsizei;	/* 4-byte signed */&#xD;&#xA;    typedef float		GLfloat;	/* single precision float */&#xD;&#xA;    typedef float		GLclampf;	/* single precision float in [0,1] */&#xD;&#xA;    typedef double		GLdouble;	/* double precision float */&#xD;&#xA;    typedef double		GLclampd;	/* double precision float in [0,1] */&#xD;&#xA;&#xD;&#xA;If your coding standard says you should always use the old C types instead of the guaranteed-width types like `uint32_t`, and you should avoid unnecessary casts, maybe it makes sense to just use the appropriate native type instead of the GL names. As Nicol Bolas says, it avoids having to include `GL/gl.h`. If your coding standard prefers using the guaranteed-width types, maybe it makes sense to keep using those in your non-GL code, and to think more carefully about when you pass those to functions taking GL type names.&#xD;&#xA;&#xD;&#xA;If you avoid explicit casts wherever possible and you compile with warnings enabled, it'll be much easier to switch to a new platform where the `typedef`s are different, because the compiler will warn you about numeric conversions that might lose information. If you explicitly cast from (say) `GLint` to `int`, but then move to a platform where `int` is 16-bit and `GLint` is a `typedef` for `uint32_t`, then the explicit cast will stop the compiler warning you about the narrowing conversion." ContentLicense="CC BY-SA 3.0" />
  <row Id="16218" PostHistoryTypeId="2" PostId="5867" RevisionGUID="cdfe5509-d1d6-4241-848b-6bd959eefd80" CreationDate="2017-11-13T17:35:59.287" UserId="7678" Text="What is the color of the sky depending on the time?&#xD;&#xA;&#xD;&#xA;I'm looking for a set of colors (HTML-Code), the sky has during sunrise, morning, forenoon, noon, afternoon, evening and sunset. A formula to calculate the color would be awesome.&#xD;&#xA;&#xD;&#xA;Kind Regards and Thank You" ContentLicense="CC BY-SA 3.0" />
  <row Id="16219" PostHistoryTypeId="1" PostId="5867" RevisionGUID="cdfe5509-d1d6-4241-848b-6bd959eefd80" CreationDate="2017-11-13T17:35:59.287" UserId="7678" Text="Color of the Sky" ContentLicense="CC BY-SA 3.0" />
  <row Id="16220" PostHistoryTypeId="3" PostId="5867" RevisionGUID="cdfe5509-d1d6-4241-848b-6bd959eefd80" CreationDate="2017-11-13T17:35:59.287" UserId="7678" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16221" PostHistoryTypeId="2" PostId="5868" RevisionGUID="5fc3407d-a69e-4269-b305-c497804d0d76" CreationDate="2017-11-13T21:16:13.317" UserId="5349" Text="If you want to learn OpenGL X.Y or DirectX A.B then shop for hardware that supports that specification. &#xD;&#xA;&#xD;&#xA;If you're using other software (Blender, Maya, 3DSMax, etc) you'll want to make sure it's supported.&#xD;&#xA;&#xD;&#xA;If your OS has a history of issues with a particular vendor, adjust accordingly.&#xD;&#xA;&#xD;&#xA;Beyond that, it's not going to matter much, especially at the hobbyist level.&#xD;&#xA;Price / performance metrics are still relevant, it's just that the definition of performance is different." ContentLicense="CC BY-SA 3.0" />
  <row Id="16225" PostHistoryTypeId="2" PostId="5869" RevisionGUID="bf8bdf72-59d9-43fb-a51f-c66663426382" CreationDate="2017-11-14T08:54:25.413" UserId="2287" Text="In general, artists like working with a linear roughness value between 0 and 1 (similarly for all other material parameters), since this is easier to work with and to understand compared to directly using the parameters of certain BRDF components as presented in the literature. Disney for instance always uses linear material parameters for their Disney BRDF in the range [0,1] from the perspective of the artists (see their [course notes][1] on page 18). Working with linear values in the range [0,1] also simplifies storing and loading these values in RGB or sRGB textures.&#xD;&#xA;&#xD;&#xA;The actual roughness used in the BRDF equations is non-linear. So one needs to map linear to non-linear roughness in some computationally cheap way that pleases the artists. The most important thing is to be consistent across your renderer and to explicitly specify when a roughness parameter is linear or non-linear.&#xD;&#xA;&#xD;&#xA;It is worth reading [Moving Frostbite to Physically Based Rendering 3.0](https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf). These course notes explicitly use the terminology linear roughness and (non-linear) roughness, both in the text and code samples. Furthermore, it is also worth reading [The Specular BRDF Reference](http://graphicrants.blogspot.be/2013/08/specular-brdf-reference.html) which defines various BRDF components for the Cook-Torrance BRDF using the same non-linear roughness parameter $\alpha$ (defined as the square of the linear roughness $roughness$.&#xD;&#xA;&#xD;&#xA;  [1]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16226" PostHistoryTypeId="5" PostId="5869" RevisionGUID="dd5ce93d-1fba-4863-863a-ad2ef06e1a57" CreationDate="2017-11-14T09:00:32.263" UserId="2287" Comment="added 1 character in body" Text="In general, artists like working with a linear roughness value between 0 and 1 (similarly for all other material parameters), since this is easier to work with and to understand compared to directly using the parameters of certain BRDF components as presented in the literature. Disney for instance always uses linear material parameters for their Disney BRDF in the range [0,1] from the perspective of the artists (see their [course notes][1] on page 18). Working with linear values in the range [0,1] also simplifies storing and loading these values in RGB or sRGB textures.&#xD;&#xA;&#xD;&#xA;The actual roughness used in the BRDF equations is non-linear. So one needs to map linear to non-linear roughness in some computationally cheap way that pleases the artists. The most important thing is to be consistent across your renderer and to explicitly specify when a roughness parameter is linear or non-linear.&#xD;&#xA;&#xD;&#xA;It is worth reading [Moving Frostbite to Physically Based Rendering 3.0](https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf). These course notes explicitly use the terminology linear roughness and (non-linear) roughness, both in the text and code samples. Furthermore, it is also worth reading [The Specular BRDF Reference](http://graphicrants.blogspot.be/2013/08/specular-brdf-reference.html) which defines various BRDF components for the Cook-Torrance BRDF using the same non-linear roughness parameter $\alpha$ (defined as the square of the linear roughness $roughness$).&#xD;&#xA;&#xD;&#xA;  [1]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16228" PostHistoryTypeId="6" PostId="5867" RevisionGUID="62b37581-77d7-4633-b5b0-a0c15533fd49" CreationDate="2017-11-14T11:26:55.923" UserId="506" Comment="added a tag" Text="|color|atmospherics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16229" PostHistoryTypeId="24" PostId="5867" RevisionGUID="62b37581-77d7-4633-b5b0-a0c15533fd49" CreationDate="2017-11-14T11:26:55.923" Comment="Proposed by 506 approved by 48, 209 edit id of 288" ContentLicense="CC BY-SA 3.0" />
  <row Id="16230" PostHistoryTypeId="2" PostId="5871" RevisionGUID="ee240eb8-c4f5-419d-81ee-53d3ad5e0090" CreationDate="2017-11-14T16:58:08.963" UserId="7680" Text="You basically need to plot the scatter map with varying colors for each point&#xA;&#xA;    scatter(x, y, [], c);&#xA;&#xA;The main difficulty is to calculate`c` so that it’s proportional to the density. &#xA;&#xA;To do so you can divide the map into a grid of a certain resolution, say `[res_x, res_y]`. Then count for each grid cell how many points are there. This count is an approximation of the density at that grid cell. Finally you can assign to all points within this grid cell the `c` value equal this count. &#xA;&#xA;Probably you also need to normalize `c` to `[0, 1]`&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16231" PostHistoryTypeId="2" PostId="5872" RevisionGUID="b75c29e6-bdcb-4d15-9335-32775d464ee2" CreationDate="2017-11-14T17:19:54.190" UserId="7680" Text="I would say it’s a [weighted set covering][1] problem.&#xA;&#xA;In specific, the cost for a set of points is the number of extra pixels in the bounding rectangle of this set.&#xA;&#xA;If the number of diff points is small, you can solve this by linear programming. Otherwise, try some approximated algorithms e.g. greedy.&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Set_cover_problem" ContentLicense="CC BY-SA 3.0" />
  <row Id="16233" PostHistoryTypeId="2" PostId="5874" RevisionGUID="78fd47e2-f74b-4ca5-a6c7-c91838148b93" CreationDate="2017-11-14T18:31:59.083" UserId="7693" Text="I’m not sure if I’m posting this question in the right area but, I’m wondering what determines the color gamut of a display?&#xA;&#xA;Is or hardware down to the RGB filter built into a display like a monitor etc or is it software like a different color profile?&#xA;&#xA;Question stems from the curiosity of if one display’s color gamut can be changed or not" ContentLicense="CC BY-SA 3.0" />
  <row Id="16234" PostHistoryTypeId="1" PostId="5874" RevisionGUID="78fd47e2-f74b-4ca5-a6c7-c91838148b93" CreationDate="2017-11-14T18:31:59.083" UserId="7693" Text="What determines the color gamut of a display?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16235" PostHistoryTypeId="3" PostId="5874" RevisionGUID="78fd47e2-f74b-4ca5-a6c7-c91838148b93" CreationDate="2017-11-14T18:31:59.083" UserId="7693" Text="|color|color-science|color-management|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16237" PostHistoryTypeId="2" PostId="5876" RevisionGUID="079aff38-739f-4db3-a5fe-71454dab86da" CreationDate="2017-11-14T18:39:12.280" UserId="7692" Text="Here's my introduction: http://www.gabrielgambetta.com/computer-graphics-from-scratch/raytracing.html It uses the somewhat contrived analogy of making a painting by putting a grid in front of a real landscape, and painting a square of the colour you see through each hole in the grid. A raytracer is essentially that, but with some linear algebra :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="16238" PostHistoryTypeId="50" PostId="5730" RevisionGUID="2ecf1678-c51a-414b-b764-59d5b28430c6" CreationDate="2017-11-14T18:49:12.083" UserId="-1" />
  <row Id="16239" PostHistoryTypeId="2" PostId="5877" RevisionGUID="9b033c77-67f7-4e50-85e3-539aea79542d" CreationDate="2017-11-14T22:55:00.863" UserId="38" Text="The physical imaging elements of your monitor define your gamut. So things like how bright the elements can be as well as the color spectra of the color elements define the gamut. But, thats quite the simplification, its also affected by such things as the screen surface material and background lighting conditions.&#xD;&#xA;&#xD;&#xA;Can the gamut be changed? Sure, if you want a smaller gamut then you can restrict your colors to a subrange of your gamut." ContentLicense="CC BY-SA 3.0" />
  <row Id="16241" PostHistoryTypeId="5" PostId="5855" RevisionGUID="c69bde2f-d182-4738-b711-924e142935ca" CreationDate="2017-11-15T04:40:24.777" UserId="2654" Comment="added 65 characters in body" Text="Yes, there's a time not to use GL types when interacting with OpenGL: `GLvoid`. There is absolutely no reason to use this type.&#xD;&#xA;&#xD;&#xA;With everything else (assuming you're using a &quot;standard&quot; OpenGL loader), you should use OpenGL's types when *talking to OpenGL*. That is, the values you pass to OpenGL functions should be in OpenGL's types. This may mean that a function that talks to OpenGL may need an OpenGL data type in its function parameter list. This should be avoided where possible, to prevent you from creating dependencies between OpenGL code and non-OpenGL code.&#xD;&#xA;&#xD;&#xA;However, if you don't mind having large portions of your application have dependencies on OpenGL, you may use OpenGL's data types throughout your code.&#xD;&#xA;&#xD;&#xA;[OpenGL's data types][1] are specified to have a particular bitdepth. As such, they are (conceptually, if not strictly C++-legally) pointer-interconvertible to certain types defined in `&lt;stdint.h&gt;/&lt;cstdint&gt;`. Indeed, many OpenGL headers will check for the existence of this header and use it wherever it is available to define OpenGL's data types. As such, if you want a fixed bitdepth integer, you have a choice besides using OpenGL's data types.&#xD;&#xA;&#xD;&#xA;&gt; I am wondering if there is any case where using the GL types could cause issues when it it is not explictly clear that the values are coming from OpenGL.&#xD;&#xA;&#xD;&#xA;OpenGL is C, not *magic*. A function in C cannot have any control over the return value of the function that calls it. Even a C++ function cannot; at best, it can throw an exception, but this still doesn't have anything to do with its caller's return value.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/OpenGL_Type" ContentLicense="CC BY-SA 3.0" />
  <row Id="16242" PostHistoryTypeId="2" PostId="5878" RevisionGUID="3fbf55dc-c4a4-4485-a47b-ecca652e7e9c" CreationDate="2017-11-15T06:52:11.777" UserId="7695" Text="First of all, I'm using OpenGL and GLM. Now, I have a square perpendicular to the z-axis and centered around it. Let's say that it has Z-value(offset along the Z-axis) X. Now, I want to set up a projective camera(it's position is (0, 0, Y) looking at (0, 0, 0). The perspective is: viewing angle=45 degrees, far=100, near = 0.1, aspect=1)(I'm using glm::lookat() and glm::perspective()). How can I calculate the value for Y from X(given the parameters I've described)? " ContentLicense="CC BY-SA 3.0" />
  <row Id="16243" PostHistoryTypeId="1" PostId="5878" RevisionGUID="3fbf55dc-c4a4-4485-a47b-ecca652e7e9c" CreationDate="2017-11-15T06:52:11.777" UserId="7695" Text="How to calculate camera distance so that after projective transformation a quad is filling the whole screen" ContentLicense="CC BY-SA 3.0" />
  <row Id="16244" PostHistoryTypeId="3" PostId="5878" RevisionGUID="3fbf55dc-c4a4-4485-a47b-ecca652e7e9c" CreationDate="2017-11-15T06:52:11.777" UserId="7695" Text="|transformations|perspective|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16249" PostHistoryTypeId="2" PostId="5880" RevisionGUID="72ac0d19-a265-48f7-a14c-c445593b8969" CreationDate="2017-11-15T10:43:13.663" UserId="6" Text="Fortunately your scenario is rather simple, your camera is on a line directly perpendicular above and centered on the quad you're concerned about. So what you want is for the quad to fill the whole screen, I assume (more or less) exactly the whole screen, i.e. the size of your projected quad in window space is your entire viewport.&#xD;&#xA;&#xD;&#xA;The mathematics of this are rather easy if you understand how the perspective matrix is actually constructed and what it does and if you know some basic trigonometry. The matrix constructed with `glm::perspective` takes as viewing angle the field of view along the y-axis and is based on goold old [`gluPerspective`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml). And if we take a look at the actual matrix, we can see that it transforms a $1$ high object sitting on the view axis at distance $1$ from the camera to a height of $\cot \frac{\alpha}{2}$ ($\alpha$ being your view angle). If you move it further away it obviously gets smaller and if you increase its height, it gets larger, so it's $\frac{h}{d}\cot\frac{\alpha}{2}$ for camera distance $d$ and object height $h$. We want that height to be equal to $1$ (the height, from the center, of the view plane in NDC space).&#xD;&#xA;&#xD;&#xA;So all you need to know in addition to that is the size of your square in the y-direction. We take half that height (because the square is centered) and multiply that by $\cot\frac{\alpha}{2}$ to get the distance it has to be from the camera. So if your square vertices have the y-coordinate +/-H and given your other values:&#xD;&#xA;&#xD;&#xA;$$Y-X = H\cot22.5°$$&#xD;&#xA;$$Y = X+H\cot22.5°$$&#xD;&#xA;$$Y \approx X+2.41421H$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="16250" PostHistoryTypeId="5" PostId="5878" RevisionGUID="e6ec4c5f-57ec-4c38-9a24-85635dfb2d92" CreationDate="2017-11-15T12:27:04.337" UserId="7457" Comment="Code formatting" Text="First of all, I'm using OpenGL and GLM. &#xD;&#xA;&#xD;&#xA;Now, I have a square perpendicular to the z-axis and centered around it. Let's say that it has Z-value (offset along the Z-axis) X. Now, I want to set up a projective camera, its position is `(0, 0, Y)` looking at `(0, 0, 0)`. The perspective is: viewing `angle=45` degrees, `far=100`, `near = 0.1`, `aspect=1`) I'm using `glm::lookat()` and `glm::perspective()`. &#xD;&#xA;How can I calculate the value for Y from X (given the parameters I've described)? " ContentLicense="CC BY-SA 3.0" />
  <row Id="16251" PostHistoryTypeId="24" PostId="5878" RevisionGUID="e6ec4c5f-57ec-4c38-9a24-85635dfb2d92" CreationDate="2017-11-15T12:27:04.337" Comment="Proposed by 7457 approved by 209, 4958 edit id of 289" ContentLicense="CC BY-SA 3.0" />
  <row Id="16252" PostHistoryTypeId="5" PostId="4360" RevisionGUID="b02d57ce-9633-42a1-8d6b-1606edc9df21" CreationDate="2017-11-15T19:05:23.837" UserId="3233" Comment="deleted 225 characters in body" Text="I have a point $P = (0, y, z)$. I need to determine the $x$ coordinate of its projection $P'$ onto a plane $T$ along the $x$ axis unit vector $\vec{X} = (1, 0, 0)$. The plane $T$ is defined by a point $V$ that lies on $T$ and its normal $\vec{N}$ (see the attached picture).&#xD;&#xA;&#xD;&#xA;[![Projection onto plane along a vector.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NIbgq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16253" PostHistoryTypeId="2" PostId="5881" RevisionGUID="e6d050ef-6f54-4b2a-ae68-6539e20eed09" CreationDate="2017-11-15T22:21:02.393" UserId="7702" Text="We are trying to check some hardware and our 100Hz video card is running at 99.97Hz.  Maybe this is just the natural speed of the chip and it is called 100Hz.  I would have thought, however, that 100Hz is very slow for a computer and that control would closer to the megahertz.  Any insight would be appreciated.  Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="16254" PostHistoryTypeId="1" PostId="5881" RevisionGUID="e6d050ef-6f54-4b2a-ae68-6539e20eed09" CreationDate="2017-11-15T22:21:02.393" UserId="7702" Text="Is 100 Hz really 100 Hz, or is it 99.97Hz" ContentLicense="CC BY-SA 3.0" />
  <row Id="16255" PostHistoryTypeId="3" PostId="5881" RevisionGUID="e6d050ef-6f54-4b2a-ae68-6539e20eed09" CreationDate="2017-11-15T22:21:02.393" UserId="7702" Text="|video|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16256" PostHistoryTypeId="2" PostId="5882" RevisionGUID="6460166a-eee7-4ead-8a1b-2b09915687ac" CreationDate="2017-11-16T09:03:40.417" UserId="7686" Text="I've basically 0-knowledge about augmented reality. For academic purposes I've to study this paper http://ieeexplore.ieee.org/document/8007317/?reload=true&#xD;&#xA;&#xD;&#xA;I'm struggling trying to understand some unclear concepts to me:&#xD;&#xA;&#xD;&#xA; - what's environment mapping in this context?&#xD;&#xA; - what's basically &quot;distance impostor tracing&quot;?&#xD;&#xA;&#xD;&#xA;I've several doubts about the rest of the paper too, maybe someone may have some simple references to make me understand what's the pipeline they present does." ContentLicense="CC BY-SA 3.0" />
  <row Id="16257" PostHistoryTypeId="1" PostId="5882" RevisionGUID="6460166a-eee7-4ead-8a1b-2b09915687ac" CreationDate="2017-11-16T09:03:40.417" UserId="7686" Text="Natural Environment Illumination in Augmented Reality" ContentLicense="CC BY-SA 3.0" />
  <row Id="16258" PostHistoryTypeId="3" PostId="5882" RevisionGUID="6460166a-eee7-4ead-8a1b-2b09915687ac" CreationDate="2017-11-16T09:03:40.417" UserId="7686" Text="|global-illumination|mobile|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16259" PostHistoryTypeId="2" PostId="5883" RevisionGUID="120d8c73-223d-4d22-b038-be0bcc9e5e0b" CreationDate="2017-11-16T10:47:36.510" UserId="7000" Text="I am trying to read an input texture, modify it and then write to an output texture from a very simple compute shader.  &#xD;&#xA;&#xD;&#xA;For some reason I am not able to write to the output image from the compute shader.  &#xD;&#xA;&#xD;&#xA;The screen is black (even though I have a red clear color).&#xD;&#xA;&#xD;&#xA;Here is my application code:&#xD;&#xA;&#xD;&#xA;		// Compute shader&#xD;&#xA;		m_compute_shader.use();&#xD;&#xA;		glBindImageTexture(0, m_color_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;		glBindImageTexture(1, m_temp_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;		glDispatchCompute(m_info.window_width / 32, m_info.window_height / 32, 1);&#xD;&#xA;&#xD;&#xA;		// Full screen quad&#xD;&#xA;		glBindImageTexture(0, m_temp_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;		glDisable(GL_DEPTH_TEST);&#xD;&#xA;		m_full_screen_quad_shader.use();&#xD;&#xA;		glViewport(0, 0, m_info.window_width, m_info.window_height);&#xD;&#xA;		glBindVertexArray(m_full_screen_quad_vao);&#xD;&#xA;		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;&#xD;&#xA;And here is the compute shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (local_size_x = 32, local_size_y = 32) in;&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0, rgba32f) readonly uniform image2D input_image;&#xD;&#xA;    layout (binding = 1, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 texel;&#xD;&#xA;        ivec2 p = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;    &#xD;&#xA;        texel = imageLoad(input_image, p);&#xD;&#xA;        texel = vec4(1.0) - texel;&#xD;&#xA;        imageStore(output_image, p, texel);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I just swap `m_temp_texture` with `m_color_texture` (which is the *input* image )	in the call to `glBindImageTexture(0, m_temp_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);` then I see the image, so I know it is not a problem with the frag shader. (Here is is though anyway):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0) uniform sampler2D input_image;&#xD;&#xA;    &#xD;&#xA;    layout (location = 0) out vec4 fragColor;&#xD;&#xA;    &#xD;&#xA;    //uniform float focal_distance = 50.0;&#xD;&#xA;    //uniform float focal_depth = 30.0;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 color = texelFetch(input_image, ivec2(gl_FragCoord.xy), 0).rgba;&#xD;&#xA;        fragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is there some reason why my compute shader is not being called? Even if I just write `imageStore(output_image, p, vec4(1.0));` in the compute shader, the screen is all black.  I do not know what I am missing.&#xD;&#xA;&#xD;&#xA;`glGetError` does not return anything.&#xD;&#xA;&#xD;&#xA;Any help is appreciated." ContentLicense="CC BY-SA 3.0" />
  <row Id="16260" PostHistoryTypeId="1" PostId="5883" RevisionGUID="120d8c73-223d-4d22-b038-be0bcc9e5e0b" CreationDate="2017-11-16T10:47:36.510" UserId="7000" Text="Issue with image load stores and compute shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="16261" PostHistoryTypeId="3" PostId="5883" RevisionGUID="120d8c73-223d-4d22-b038-be0bcc9e5e0b" CreationDate="2017-11-16T10:47:36.510" UserId="7000" Text="|opengl|compute-shader|image-load-store|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16262" PostHistoryTypeId="2" PostId="5884" RevisionGUID="d56a20ed-77f0-4744-a11a-f80ef5c5e98c" CreationDate="2017-11-16T13:52:47.747" UserId="5846" Text="I don't know the name of this technique, but the idea is to adjust the density and location of identical dots or small objects in order to produce a gray tone image or even a suggestion of three dimensionality. It's better to use these two images below as examples.&#xD;&#xA;&#xD;&#xA;I'd like to do something like this on my own, but by writing relatively simple algorithm rather than a program or package.&#xD;&#xA;&#xD;&#xA;Could someone explain what this is called and share some amount of insight into how it works? I don't need a full-blown derivation, just some idea to get started.&#xD;&#xA;&#xD;&#xA;**In the first image**, the objects (in software) follow the face contour in 3D, but their position (and brightness) is fluid and their separation varies continuously. While they appear to be approximately on a grid, I'm not sure if they are a fixed projected grid (I think I've read somewhere it was done using a Kinect) and move because of the movement of the model, or if they move algorithmically as well.&#xD;&#xA;&#xD;&#xA;**In the second image**, these are pixels on a fixed grid and they are either ON or OFF.&#xD;&#xA;&#xD;&#xA;I'm familliar with something simple like using a random number to decide if the pixel should be on or off depending on the gray value; if it's 0.3, then if a random number (chosen for each pixel, but not necessarily randomized every frame) is below 0.3, the pixel should be ON. But I think there is a lot more going on than that.&#xD;&#xA;&#xD;&#xA;**below:** Cropped screen shot at `11:23` in the short film [*The Final Moments of Karl Brandt*][1]:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**below:** 128x64 pixel OLED display from the [Adafruit][3] website:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=jFotiDbj-D4&#xD;&#xA;  [2]: https://i.stack.imgur.com/FBas6.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/VmHHF.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16263" PostHistoryTypeId="1" PostId="5884" RevisionGUID="d56a20ed-77f0-4744-a11a-f80ef5c5e98c" CreationDate="2017-11-16T13:52:47.747" UserId="5846" Text="What is this technique called and how can I reproduce it algorithmically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16264" PostHistoryTypeId="3" PostId="5884" RevisionGUID="d56a20ed-77f0-4744-a11a-f80ef5c5e98c" CreationDate="2017-11-16T13:52:47.747" UserId="5846" Text="|rendering|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16265" PostHistoryTypeId="5" PostId="5884" RevisionGUID="ffe09647-a457-442b-8fdc-36322ab1d2f4" CreationDate="2017-11-16T13:58:05.530" UserId="5846" Comment="added 264 characters in body" Text="I don't know the name of this technique, but the idea is to adjust the density and location of identical dots or small objects in order to produce a gray tone image or even a suggestion of three dimensionality. It's better to use these two images below as examples.&#xD;&#xA;&#xD;&#xA;I'd like to do something like this on my own, but by writing relatively simple algorithm rather than a program or package.&#xD;&#xA;&#xD;&#xA;Could someone explain what this is called and share some amount of insight into how this works? I don't need a full-blown derivation, just some idea to get started on something simple.&#xD;&#xA;&#xD;&#xA;**In the first image**, the objects (in software) follow the face contour in 3D, but their position (and brightness) is fluid and their separation varies continuously. While they appear to be approximately on a grid, I'm not sure if they are a fixed projected grid (I think I've read somewhere it was done using a Kinect) and move because of the movement of the model, or if they move algorithmically as well.&#xD;&#xA;&#xD;&#xA;**edit:** More info on the Kinect in the Below the Line article [Level 256 VFX Produces The Final Moments of Karl Brant for Nerdist.com][4].&#xD;&#xA;&#xD;&#xA;&gt;“Leveraging the power of open source applications like Processing, Python, and bash scripting, we were able to take the point cloud data from the Kinect, manipulate it, and get it into Nuke for integration with the live-action plates for texture re-projection,” Kleinberg explained. “The process evolved and grew over time, and when we finally saw the fruits of our labor on the screen, we were excited to see Karl Brant fully realized, taking on an expressive life of his own.”&#xD;&#xA;&#xD;&#xA;**In the second image**, these are pixels on a fixed grid and they are either ON or OFF.&#xD;&#xA;&#xD;&#xA;I'm familliar with something simple like using a random number to decide if the pixel should be on or off depending on the gray value; if it's 0.3, then if a random number (chosen for each pixel, but not necessarily randomized every frame) is below 0.3, the pixel should be ON. But I think there is a lot more going on than that.&#xD;&#xA;&#xD;&#xA;**below:** Cropped screen shot at `11:23` in the short film [*The Final Moments of Karl Brandt*][1]:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**below:** 128x64 pixel OLED display from the [Adafruit][3] website (cropped):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=jFotiDbj-D4&#xD;&#xA;  [2]: https://i.stack.imgur.com/FBas6.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/VmHHF.jpg&#xD;&#xA;  [4]: http://www.btlnews.com/crafts/visual-fx/level-256-vfx-produces-the-final-moments-of-karl-brant-for-nerdist-com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16266" PostHistoryTypeId="5" PostId="5884" RevisionGUID="379656f1-5fa4-4d77-bb81-05db88209c8d" CreationDate="2017-11-16T14:30:37.707" UserId="5846" Comment="removed unrelated 2nd image per comments" Text="I don't know the name of this technique, but the idea is to adjust the density and location of identical dots or small objects in order to produce a gray tone image or even a suggestion of three dimensionality. It's better to use these two images below as examples.&#xD;&#xA;&#xD;&#xA;I'd like to do something like this on my own, but by writing relatively simple algorithm rather than a program or package.&#xD;&#xA;&#xD;&#xA;Could someone explain what this is called and share some amount of insight into how this works? I don't need a full-blown derivation, just some idea to get started on something simple.&#xD;&#xA;&#xD;&#xA;**In the screenshot**, the objects (in software) follow the face contour in 3D, but their position (and brightness) is fluid and their separation varies continuously. While they appear to be approximately on a grid, I'm not sure if they are a fixed projected grid (I think I've read somewhere it was done using a Kinect) and move because of the movement of the model, or if they move algorithmically as well.&#xD;&#xA;&#xD;&#xA;**edit:** More info on the Kinect in the Below the Line article [Level 256 VFX Produces The Final Moments of Karl Brant for Nerdist.com][4].&#xD;&#xA;&#xD;&#xA;&gt;“Leveraging the power of open source applications like Processing, Python, and bash scripting, we were able to take the point cloud data from the Kinect, manipulate it, and get it into Nuke for integration with the live-action plates for texture re-projection,” Kleinberg explained. “The process evolved and grew over time, and when we finally saw the fruits of our labor on the screen, we were excited to see Karl Brant fully realized, taking on an expressive life of his own.”&#xD;&#xA;&#xD;&#xA;I'm familliar with something simple like using a random number to decide if the pixel should be on or off depending on the gray value; if it's 0.3, then if a random number (chosen for each pixel, but not necessarily randomized every frame) is below 0.3, the pixel should be ON (seems to be called 1-bit [dithering][6]). But I think there is a lot more going on here than that. &#xD;&#xA;&#xD;&#xA;**below:** Cropped screen shot at `11:23` in the short film [*The Final Moments of Karl Brandt*][1]:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=jFotiDbj-D4&#xD;&#xA;  [2]: https://i.stack.imgur.com/FBas6.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/VmHHF.jpg&#xD;&#xA;  [4]: http://www.btlnews.com/crafts/visual-fx/level-256-vfx-produces-the-final-moments-of-karl-brant-for-nerdist-com/&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Dither" ContentLicense="CC BY-SA 3.0" />
  <row Id="16267" PostHistoryTypeId="5" PostId="5884" RevisionGUID="88b95002-84dc-4e48-ba3d-0bf0a1f44ad5" CreationDate="2017-11-16T14:45:30.840" UserId="5846" Comment="added 187 characters in body" Text="I don't know the name of this technique, but the idea is to adjust the density and location of identical dots or small objects in order to produce a gray tone image or even a suggestion of three dimensionality. It's better to use these two images below as examples.&#xD;&#xA;&#xD;&#xA;I'd like to do something like this on my own, but by writing relatively simple algorithm rather than a program or package. I'll be starting with a 3D representation of an object's surface inside a python script running in  Blender. *My question isn't how to implement, but how to understand what's happening*.&#xD;&#xA;&#xD;&#xA;Could someone explain what this is called and share some amount of insight into how this works? I don't need a full-blown derivation, just some idea to get started on something simple.&#xD;&#xA;&#xD;&#xA;**In the screenshot**, the objects (in software) follow the face contour in 3D, but their position (and brightness) is fluid and their separation varies continuously. While they appear to be approximately on a grid, I'm not sure if they are a fixed projected grid (I think I've read somewhere it was done using a Kinect) and move because of the movement of the model, or if they move algorithmically as well.&#xD;&#xA;&#xD;&#xA;**edit:** More info on the Kinect in the Below the Line article [Level 256 VFX Produces The Final Moments of Karl Brant for Nerdist.com][4].&#xD;&#xA;&#xD;&#xA;&gt;“Leveraging the power of open source applications like Processing, Python, and bash scripting, we were able to take the point cloud data from the Kinect, manipulate it, and get it into Nuke for integration with the live-action plates for texture re-projection,” Kleinberg explained. “The process evolved and grew over time, and when we finally saw the fruits of our labor on the screen, we were excited to see Karl Brant fully realized, taking on an expressive life of his own.”&#xD;&#xA;&#xD;&#xA;I'm familliar with something simple like using a random number to decide if the pixel should be on or off depending on the gray value; if it's 0.3, then if a random number (chosen for each pixel, but not necessarily randomized every frame) is below 0.3, the pixel should be ON (seems to be called 1-bit [dithering][6]). But I think there is a lot more going on here than that. &#xD;&#xA;&#xD;&#xA;**below:** Cropped screen shot at `11:23` in the short film [*The Final Moments of Karl Brandt*][1]:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=jFotiDbj-D4&#xD;&#xA;  [2]: https://i.stack.imgur.com/FBas6.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/VmHHF.jpg&#xD;&#xA;  [4]: http://www.btlnews.com/crafts/visual-fx/level-256-vfx-produces-the-final-moments-of-karl-brant-for-nerdist-com/&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Dither" ContentLicense="CC BY-SA 3.0" />
  <row Id="16268" PostHistoryTypeId="2" PostId="5885" RevisionGUID="4f73f9ae-99b9-45b4-8db5-4314fc70446c" CreationDate="2017-11-16T15:38:58.350" UserId="7680" Text="This probably should go as a comment; however I don't have enough reputations to do so.&#xD;&#xA;&#xD;&#xA;I don't have access to the paper, and probably most of the people here don't either. &#xD;&#xA;&#xD;&#xA;Did you check about the standard concepts in Computer Graphics of [environment mapping][1] and [impostor][2]? Do they make sense in this context or did the authors invent something new for their framework?&#xD;&#xA;&#xD;&#xA;I would say those are common techniques to reduce the scene complexity (which improves the performance of AR/VR systems), while trying to provide some level of reality. &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Reflection_mapping&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Sprite_(computer_graphics)" ContentLicense="CC BY-SA 3.0" />
  <row Id="16269" PostHistoryTypeId="10" PostId="5860" RevisionGUID="b498c1fe-773e-4413-b933-6bc489aa35ff" CreationDate="2017-11-16T21:50:17.697" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="16273" PostHistoryTypeId="2" PostId="5886" RevisionGUID="2b7cfcf0-a7f6-47ab-8c6c-6fb3817251d7" CreationDate="2017-11-17T00:24:38.170" UserId="3003" Text="I've done something similar. The way I did it was by using a height map image to change the positions of vertices in a grid in a vertex shader. I generated a 2D grid of vertices that were evenly spaced on the CPU. I uploaded the vertices and a texture and in the vertex shader, I sampled the texture and used the resulting brightness as the height. So I'd keep the x and y positions of each vertex and change the z based on the image.&#xD;&#xA;&#xD;&#xA;Now there are other ways you could utilize this to get something more like in the video. You could either have a 2D grid of single vertices, or even a grid of small 3D models. Change the z position based on the color of a height map. But additionally, you could upload a small noise texture and vary the x and y positions by a small amount based on the noise, which might vary per frame. I would see if you could vary the x and y by a large enough amount to see, but small enough that no point ever crossed over a neighbor point. That would get you some more movement and randomness." ContentLicense="CC BY-SA 3.0" />
  <row Id="16275" PostHistoryTypeId="5" PostId="5883" RevisionGUID="020d17fb-fd8f-4fa3-81f4-22dae7a4cd33" CreationDate="2017-11-17T09:21:15.890" UserId="7000" Comment="added 272 characters in body" Text="I am trying to read an input texture, modify it and then write to an output texture from a very simple compute shader.  &#xD;&#xA;&#xD;&#xA;For some reason I am not able to write to the output image from the compute shader.  &#xD;&#xA;&#xD;&#xA;The screen is black (even though I have a red clear color).&#xD;&#xA;&#xD;&#xA;Here is my application code:&#xD;&#xA;&#xD;&#xA;		// Compute shader&#xD;&#xA;        (...Code to setup images)&#xD;&#xA;        glTextureStorage2D(m_color_texture, 1, GL_RGB32F, m_src_fbo_size, m_src_fbo_size); // &lt;- Yikes, wrong format!&#xD;&#xA;        glTextureStorage2D(m_temp_texture, 1, GL_RGB32F, m_src_fbo_size, m_src_fbo_size); // &lt;- Yikes, wrong format!&#xD;&#xA;		m_compute_shader.use();&#xD;&#xA;		glBindImageTexture(0, m_color_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;		glBindImageTexture(1, m_temp_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;		glDispatchCompute(m_info.window_width / 32, m_info.window_height / 32, 1);&#xD;&#xA;&#xD;&#xA;		// Full screen quad&#xD;&#xA;		glBindImageTexture(0, m_temp_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;		glDisable(GL_DEPTH_TEST);&#xD;&#xA;		m_full_screen_quad_shader.use();&#xD;&#xA;		glViewport(0, 0, m_info.window_width, m_info.window_height);&#xD;&#xA;		glBindVertexArray(m_full_screen_quad_vao);&#xD;&#xA;		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;&#xD;&#xA;And here is the compute shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (local_size_x = 32, local_size_y = 32) in;&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0, rgba32f) readonly uniform image2D input_image;&#xD;&#xA;    layout (binding = 1, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 texel;&#xD;&#xA;        ivec2 p = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;    &#xD;&#xA;        texel = imageLoad(input_image, p);&#xD;&#xA;        texel = vec4(1.0) - texel;&#xD;&#xA;        imageStore(output_image, p, texel);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I just swap `m_temp_texture` with `m_color_texture` (which is the *input* image )	in the call to `glBindImageTexture(0, m_temp_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);` then I see the image, so I know it is not a problem with the frag shader. (Here is is though anyway):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0) uniform sampler2D input_image;&#xD;&#xA;    &#xD;&#xA;    layout (location = 0) out vec4 fragColor;&#xD;&#xA;    &#xD;&#xA;    //uniform float focal_distance = 50.0;&#xD;&#xA;    //uniform float focal_depth = 30.0;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 color = texelFetch(input_image, ivec2(gl_FragCoord.xy), 0).rgba;&#xD;&#xA;        fragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is there some reason why my compute shader is not being called? Even if I just write `imageStore(output_image, p, vec4(1.0));` in the compute shader, the screen is all black.  I do not know what I am missing.&#xD;&#xA;&#xD;&#xA;`glGetError` does not return anything.&#xD;&#xA;&#xD;&#xA;**EDIT / ANSWER:**&#xD;&#xA;&#xD;&#xA;I originally failed to include the code for the texture creation (the first two lines). I realized that I set the wrong image formats (`GL_RGB32F` instead of `GL_RGBA32F`).&#xD;&#xA;&#xD;&#xA;This error was hard to track down because the format (without alpha) only mattered (in this case) in the compute shader.&#xD;&#xA;&#xD;&#xA;So, this question can be closed.&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="16276" PostHistoryTypeId="2" PostId="5887" RevisionGUID="d079e019-6151-4232-bf76-4f36b5f982ad" CreationDate="2017-11-17T10:42:29.130" UserId="2287" Text="The maximum allowed number of threads per compute shader group is 1024 for Shader Model 5.0. Is it advisable with regard to performance to stay close to this maximum number?&#xD;&#xA;&#xD;&#xA;In order to resolve SSAA and MSAA (down-scaling with appropriate tone mapping), I wrote some compute shaders.&#xD;&#xA;&#xD;&#xA;One general compute shader works in all cases and performs one task without synchronization for each output texel and uses [numthreads(16, 16, 1)] (= 256 threads/group which is a multiple of NVidia's warp size of 32 and AMD's wavefront size of 64). Algorithmically, this does not result in the best performance, since for MSAA $T$x, each task performs $T$ texture loads from the radiance, normal and depth textures, and for SSAA $T$x, each task performs $T \times T$ texture loads from the radiance, normal and depth textures.&#xD;&#xA;&#xD;&#xA;So instead of dispatching jobs in terms of output texels, I have some specialized compute shaders performing tasks with synchronization for each input texel (for SSAA) or for each subsample of an input texel (for MSAA). Here, each task performs $1$ texture load from the radiance, normal and depth textures and stores the results in group shared memory. Next, a `GroupMemoryBarrierWithGroupSync` takes place and only one job per output texel continues to finish the work. This is not ideal in case of many SSAA and MSAA samples, but for few samples such as MSAA 2x, one expects to see some gains. In practice, however, the general compute shader outperforms all the specialized compute shaders for both small and large numbers of samples/ouput texel?&#xD;&#xA;&#xD;&#xA;SSAA 2x [numthreads(4, 16, 16)] = 1024 (multiple of 64): ~655 FPS vs ~577 FPS&#xD;&#xA;&#xD;&#xA;SSAA 3x [numthreads(9, 8, 8)]   =  576 (multiple of 64): ~265 FPS vs ~200 FPS&#xD;&#xA;&#xD;&#xA;SSAA 4x [numthreads(16, 8, 8)]  = 1024 (multiple of 64): ~127 FPS vs  ~75 FPS&#xD;&#xA;&#xD;&#xA;Can this be solely due to dispatching more threads/group? Can this be due to the synchronization of all threads per group (close to the maximum allowed number of threads)? Or is there some performance one needs to sacrifice in case of using a 3D instead of 2D block of threads per group? " ContentLicense="CC BY-SA 3.0" />
  <row Id="16277" PostHistoryTypeId="1" PostId="5887" RevisionGUID="d079e019-6151-4232-bf76-4f36b5f982ad" CreationDate="2017-11-17T10:42:29.130" UserId="2287" Text="Threads per compute shader group" ContentLicense="CC BY-SA 3.0" />
  <row Id="16278" PostHistoryTypeId="3" PostId="5887" RevisionGUID="d079e019-6151-4232-bf76-4f36b5f982ad" CreationDate="2017-11-17T10:42:29.130" UserId="2287" Text="|hlsl|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16279" PostHistoryTypeId="2" PostId="5888" RevisionGUID="8c100de5-c792-483f-b6e4-f625562458b7" CreationDate="2017-11-17T15:45:29.037" UserId="1937" Text="There shouldn't be any performance penalty inherent in using a 3D group over a 2D one, the dimensions are just an aid for programmers to map invocations on to memory locations (since you can read or write wherever you like). &#xD;&#xA;&#xD;&#xA;The group size affects which invocations can access the same block of groupshared memory, so it forces all warps from the same group to run on the same SMP. If you have a shader that needs to move stuff around a lot in its local memory block (e.g. a bitonic sorter), a large group size is preferable, but in your case it shouldn't make much difference. &#xD;&#xA;&#xD;&#xA;I suspect your problem is with the idle threads within your warps. If I understand your question properly, you're using a thread per input texel or sample to do the texture reads, but then only a subset of these threads to do the processing? If so, you're sacrificing a lot of compute power within each warp. Remember, texture reads are done in minimum 2x2 blocks, and the results get cached in a way optimized for locality for the dimension of the texture (see [this question][1]). So although your general purpose shader might seem slow with all the texture reads, a lot of them will be effectively almost free. Also, the GPU does latency-hiding on slow memory reads, swapping in other warps until the result of the read is available. So your general purpose shader actually seems like the smart option here, as it maximizes compute power.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/355/how-does-texture-cache-work-considering-multiple-shader-units" ContentLicense="CC BY-SA 3.0" />
  <row Id="16280" PostHistoryTypeId="2" PostId="5889" RevisionGUID="4442e0a0-eb02-4b87-b640-cd77aa736c74" CreationDate="2017-11-17T18:18:19.923" UserId="7710" Text="Due to perspective foreshortening, the projections of parallel lines (1D geometric objects) meet in their vanishing point (a 0D geometric object). Higher dimensional geometric objects also has higher dimensional vanishing objects. I am interested in vanishing points of the edges of the triangle &#xD;&#xA;&#xD;&#xA;∆(p0, p1, p2) &#xD;&#xA;&#xD;&#xA;if p0T,p1T and p2T are given ? &#xD;&#xA;&#xD;&#xA;Any idea ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16281" PostHistoryTypeId="1" PostId="5889" RevisionGUID="4442e0a0-eb02-4b87-b640-cd77aa736c74" CreationDate="2017-11-17T18:18:19.923" UserId="7710" Text="Determining Vanishing Points of edges of Triangle using given Point" ContentLicense="CC BY-SA 3.0" />
  <row Id="16282" PostHistoryTypeId="3" PostId="5889" RevisionGUID="4442e0a0-eb02-4b87-b640-cd77aa736c74" CreationDate="2017-11-17T18:18:19.923" UserId="7710" Text="|2d|perspective|vector-graphics|2d-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16284" PostHistoryTypeId="2" PostId="5891" RevisionGUID="aef4a50f-4723-42b9-8c61-e77b6c741c05" CreationDate="2017-11-18T00:14:04.307" UserId="48" Text="Vanishing points are &quot;points at infinity&quot; in projective geometry, which are represented by $w = 0$ in homogeneous coordinates. You can construct the vanishing point of a ray or line by taking its $xyz$ direction vector and adjoining $w = 0$. (For a line, use the direction vector and its negation to get vanishing points in both directions.)&#xD;&#xA;&#xD;&#xA;Then you can transform this homogeneous vector by your view/projection matrices as usual, and divide out $w$ from the result to find where the point lies in screen space. (If the result has $w \leq 0$ then it's behind the camera or off to the side.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="16286" PostHistoryTypeId="50" PostId="2076" RevisionGUID="d8508089-196d-449b-8d9c-f92ca1fd5e54" CreationDate="2017-11-18T11:20:08.567" UserId="-1" />
  <row Id="16288" PostHistoryTypeId="2" PostId="5892" RevisionGUID="ce95257b-f316-459d-9ce1-5613f852305e" CreationDate="2017-11-18T18:42:46.277" UserId="3085" Text="I've got a discrete grayscale image (a.k.a. 2D rectangular array of floats). Its continuous representation (whether received via reconstruction with sinc, with a cubic kernel, with a triangle kernel...) is a continous 2D function, so it has isolines. I'm interested in calculating the magnitude of the derivative of the isoline at a given point.&#xD;&#xA;&#xD;&#xA;Pic:&#xD;&#xA;&#xD;&#xA;[![diagram][1]][1]&#xD;&#xA;&#xD;&#xA;Red line is part of an isoline, and green arrows are example derivatives of that isoline at 2 points.&#xD;&#xA;&#xD;&#xA;Here's my approximate solution:&#xD;&#xA;&#xD;&#xA;    void getCurvature(vec2 p) {&#xD;&#xA;        vec2 grad = getBilinear(gradients, p);&#xD;&#xA;        if(grad = vec2(0, 0)) return 0;&#xD;&#xA;        else grad = normalize(grad);&#xD;&#xA;    &#xD;&#xA;    	vec2 gradP = perpendicularLeft(grad);&#xD;&#xA;    					&#xD;&#xA;    	float val = getBilinear(img, p);&#xD;&#xA;    	float valLeft = getBilinear(img, p+gradP);&#xD;&#xA;    	float valRight = getBilinear(img, p-gradP);&#xD;&#xA;    	return (val - (valLeft + valRight) * .5f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It basically computes the second directional derivative in a direction perpendicular to the gradient. It works fine for my purposes, except that it's somewhat slow in the CPU implementation (and I have reasons not to port it to GPU).&#xD;&#xA;&#xD;&#xA;Any faster (and/or more accurate) method?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QErl7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16289" PostHistoryTypeId="1" PostId="5892" RevisionGUID="ce95257b-f316-459d-9ce1-5613f852305e" CreationDate="2017-11-18T18:42:46.277" UserId="3085" Text="How to calculate curvature of isoline of image" ContentLicense="CC BY-SA 3.0" />
  <row Id="16290" PostHistoryTypeId="3" PostId="5892" RevisionGUID="ce95257b-f316-459d-9ce1-5613f852305e" CreationDate="2017-11-18T18:42:46.277" UserId="3085" Text="|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16291" PostHistoryTypeId="5" PostId="5892" RevisionGUID="5719cc28-b480-46d9-a993-616ae3aee8dd" CreationDate="2017-11-18T19:03:18.483" UserId="3085" Comment="added 1 character in body" Text="I've got a discrete grayscale image (a.k.a. 2D rectangular array of floats). Its continuous representation (whether received via reconstruction with sinc, with a cubic kernel, with a triangle kernel...) is a continous 2D function, so it has isolines. I'm interested in calculating the magnitude of the derivative of the isoline at a given point.&#xD;&#xA;&#xD;&#xA;Pic:&#xD;&#xA;&#xD;&#xA;[![diagram][1]][1]&#xD;&#xA;&#xD;&#xA;Red line is part of an isoline, and green arrows are example derivatives of that isoline at 2 points.&#xD;&#xA;&#xD;&#xA;Here's my approximate solution:&#xD;&#xA;&#xD;&#xA;    float getCurvature(vec2 p) {&#xD;&#xA;        vec2 grad = getBilinear(gradients, p);&#xD;&#xA;        if(grad = vec2(0, 0)) return 0;&#xD;&#xA;        else grad = normalize(grad);&#xD;&#xA;    &#xD;&#xA;    	vec2 gradP = perpendicularLeft(grad);&#xD;&#xA;    					&#xD;&#xA;    	float val = getBilinear(img, p);&#xD;&#xA;    	float valLeft = getBilinear(img, p+gradP);&#xD;&#xA;    	float valRight = getBilinear(img, p-gradP);&#xD;&#xA;    	return (val - (valLeft + valRight) * .5f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It basically computes the second directional derivative in a direction perpendicular to the gradient. It works fine for my purposes, except that it's somewhat slow in the CPU implementation (and I have reasons not to port it to GPU).&#xD;&#xA;&#xD;&#xA;Any faster (and/or more accurate) method?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QErl7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16292" PostHistoryTypeId="34" PostId="5841" RevisionGUID="41bb2820-22aa-4aae-a4c9-ec5f6d541d5d" CreationDate="2017-11-18T19:37:53.823" UserId="-1" Comment="40" />
  <row Id="16293" PostHistoryTypeId="5" PostId="5892" RevisionGUID="3ae5eea1-1bfa-46a2-afc5-4b31852dc023" CreationDate="2017-11-18T19:41:34.780" UserId="3085" Comment="added 334 characters in body" Text="I've got a discrete grayscale image (a.k.a. 2D rectangular array of floats). Its continuous representation (whether received via reconstruction with sinc, with a cubic kernel, with a triangle kernel...) is a continous 2D function, so it has isolines. I'm interested in calculating the magnitude of the derivative of the isoline at a given point.&#xD;&#xA;&#xD;&#xA;Pic:&#xD;&#xA;&#xD;&#xA;[![diagram][1]][1]&#xD;&#xA;&#xD;&#xA;Red line is part of an isoline, and green arrows are example derivatives of that isoline at 2 points.&#xD;&#xA;&#xD;&#xA;Here's my approximate solution:&#xD;&#xA;&#xD;&#xA;    float getCurvature(vec2 p) {&#xD;&#xA;        vec2 grad = getBilinear(gradients, p);&#xD;&#xA;        if(grad = vec2(0, 0)) return 0;&#xD;&#xA;        else grad = normalize(grad);&#xD;&#xA;    &#xD;&#xA;    	vec2 gradP = perpendicularLeft(grad);&#xD;&#xA;    					&#xD;&#xA;    	float val = getBilinear(img, p);&#xD;&#xA;    	float valLeft = getBilinear(img, p+gradP);&#xD;&#xA;    	float valRight = getBilinear(img, p-gradP);&#xD;&#xA;    	return (val - (valLeft + valRight) * .5f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It basically computes the second directional derivative in a direction perpendicular to the gradient. It works fine for my purposes, except that it's somewhat slow in the CPU implementation (and I have reasons not to port it to GPU).&#xD;&#xA;&#xD;&#xA;Any faster (and/or more accurate) method?&#xD;&#xA;&#xD;&#xA;**Edit:** I found a twice-faster method, still calculating the second derivative, but in a simpler way. It's equation (5) [on this page](http://mathonline.wikidot.com/higher-order-directional-derivatives). It works, but the result is more crude. I think I should switch to a higher-quality differentiation kernel than [+1, 0, -1].&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QErl7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16301" PostHistoryTypeId="2" PostId="5894" RevisionGUID="c3aebc79-6083-4f18-9951-8e420fdda3aa" CreationDate="2017-11-19T17:08:37.160" UserId="3085" Text="Long story short: downscale using a standard downscaling algorithm. Then multiply the value in each element by `originalArea/scaledArea`. This is what Rahul meant in the comments.&#xD;&#xA;&#xD;&#xA;Why that works:  &#xD;&#xA;You can think of every output pixel as a (weighted or not) average of a neighbourhood of the source pixel. And as we know:&#xD;&#xA;&#xD;&#xA;    average = sum / count&#xD;&#xA;&#xD;&#xA;Now, for the caveats.&#xD;&#xA;&#xD;&#xA;Broadly, there are 3 types of downscaling algorithms:&#xD;&#xA;&#xD;&#xA;1. Ones that simply do resampling with some kernel  &#xD;&#xA;1.1. Ones that lowpass first  &#xD;&#xA;1.2. Ones that don't&#xD;&#xA;2. Pyramid downscaling&#xD;&#xA;3. Algorithms like the one in &quot;Genuine Fractals&quot; which are intended for detail-preserving **up**scaling, but could conceivably be abused for downscaling&#xD;&#xA;&#xD;&#xA;Since &quot;3.&quot; is not intended for downscaling, it's not useful for your case.&#xD;&#xA;&#xD;&#xA;The problem with &quot;1.2.&quot; is that, normally a small (e.g. 5x5) resampling kernel is used, which means that only a few of the source pixels are taken into account. In image resizing applications, this can manifest as aliasing. In your application, it can manifest as inaccuracy.&#xD;&#xA;&#xD;&#xA;This problem with &quot;1.2.&quot; can be fixed by using a big resampling kernel. I believe that's what the ImageMagick library used to do. E.g. taking a good-quality kernel like Lanczos and stretching it by x and y. Or you could go ahead and use a big box kernel like you describe in the question. Which one is appropriate depends on your exact application, but if you're dead set on using a box kernel, use that. The algorithm you described in the question would work fine, and I believe that on a CPU there is no better one (except splitting this one into threads), for the reason that any algorithm would need at least N (number of pixels) operations to take into account all the pixels, and your algorithm does a tiny amount of work for each of these N pixels.&#xD;&#xA;&#xD;&#xA;But on the GPU there is a better algorithm that takes full advantage of the GPU's strong parallelism. It's called &quot;parallel reduction&quot;, you can find info on it based on that. Since it's widely documented, I'll just sketch the algorithm:&#xD;&#xA;&#xD;&#xA;Iteratively downscale the image by a factor of 2 by x and y until you get to your desired size.&#xD;&#xA;&#xD;&#xA;&quot;1.1.&quot; would probably also suit your needs, but I won't comment on it for now, as it's not much better than the other options." ContentLicense="CC BY-SA 3.0" />
  <row Id="16302" PostHistoryTypeId="2" PostId="5895" RevisionGUID="e132e614-d804-4b6c-9998-24d8fee04b13" CreationDate="2017-11-19T22:00:55.527" UserId="7462" Text="Before I get downvoted. I am not asking how to use them, I know how to use them. I am trying to understand what they are. For example, an array is actually a contiguous section of memory, a linked list is actually just a clever way of using memory addresses, a 3D array is actually just a 1D array being used in a clever fashion...&#xD;&#xA;&#xD;&#xA;Under that logic, VBO's are sections of GPU RAM that contain rendering data. They are thus &quot;arrays&quot;. But then what is a VAO? My current understanding is that they are magical &quot;boxes&quot; that somehow store machine state information for a set of VBO's, but what are they actually?&#xD;&#xA;&#xD;&#xA;Because for example, as far as I know, you MUST bind the VBO's under a VAO to get rendering output, if you just bind the VAO you won't get outpt, so what is their purpouse?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16303" PostHistoryTypeId="1" PostId="5895" RevisionGUID="e132e614-d804-4b6c-9998-24d8fee04b13" CreationDate="2017-11-19T22:00:55.527" UserId="7462" Text="What is an OpenGL VAO in a nutshell?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16304" PostHistoryTypeId="3" PostId="5895" RevisionGUID="e132e614-d804-4b6c-9998-24d8fee04b13" CreationDate="2017-11-19T22:00:55.527" UserId="7462" Text="|opengl|vertex-buffer-object|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16306" PostHistoryTypeId="2" PostId="5896" RevisionGUID="f290ea27-ea23-48b1-86ef-479f0e8a3129" CreationDate="2017-11-20T03:16:23.037" UserId="3003" Text="Gradient magnitude and angle can be found using a [Sobel operator](https://en.wikipedia.org/wiki/Sobel_operator). It's more sophisticated than the [1, 0, -1]. This is commonly used either directly for [edge detection](https://en.wikipedia.org/wiki/Edge_detection), or as part of a [more complex algorithm](https://en.wikipedia.org/wiki/Canny_edge_detector).&#xD;&#xA;&#xD;&#xA;Or, if I've misunderstood, and you want only the curvature of the 2D isoline, [this answer on Math Overflow](https://math.stackexchange.com/questions/1122819/numerical-approximation-for-2d-curvature) might be of use." ContentLicense="CC BY-SA 3.0" />
  <row Id="16307" PostHistoryTypeId="2" PostId="5897" RevisionGUID="b0a03eae-502c-44d3-8e6f-a2f3f5d66add" CreationDate="2017-11-20T07:08:19.690" UserId="1937" Text="VAOs are essentially 'plumbing' objects that help get data from your buffers into your vertex shader ready for drawing. On the GPU this is handled by the vertex fetch stage, so a VAO is basically just a bundle of vertex fetch state corresponding to a particular model.&#xD;&#xA;&#xD;&#xA;You can think of it as a bundle of pointers, but with somewhat more complexity than CPU-side pointers. Since OpenGL buffers are just a blob of untyped bytes by default (that's why you get a void* when you map them), the VAO handles type-casting (to vec3 or whatever) when fetching the data. It also deals with the size of the data not necessarily matching the stride between consecutive elements, and makes sure that each data item (position, normal, uv, etc.) is transmitted to the correct 'channel' in the vertex shader input.&#xD;&#xA;&#xD;&#xA;You can render without a VAO in legacy OpenGL, but this is generally more of a PITA, since you need to bind each vertex attribute separately each time you draw the object. Encapsulating all these bindings in a VAO lets you set them up once, then you have a 'plug and play' object that simply needs to be bound before a draw call, and all your vertex data will be ready to go." ContentLicense="CC BY-SA 3.0" />
  <row Id="16312" PostHistoryTypeId="5" PostId="5883" RevisionGUID="d614a6ec-0440-4dcb-9eac-bbfa59ee5a50" CreationDate="2017-11-20T09:20:11.090" UserId="7000" Comment="deleted 207 characters in body" Text="I am trying to read an input texture, modify it and then write to an output texture from a very simple compute shader.  &#xD;&#xA;&#xD;&#xA;For some reason I am not able to write to the output image from the compute shader.  &#xD;&#xA;&#xD;&#xA;The screen is black (even though I have a red clear color).&#xD;&#xA;&#xD;&#xA;Here is my application code:&#xD;&#xA;&#xD;&#xA;		// Compute shader&#xD;&#xA;        (...Code to setup images)&#xD;&#xA;        glTextureStorage2D(m_color_texture, 1, GL_RGB32F, m_src_fbo_size, m_src_fbo_size); // &lt;- Yikes, wrong format!&#xD;&#xA;        glTextureStorage2D(m_temp_texture, 1, GL_RGB32F, m_src_fbo_size, m_src_fbo_size); // &lt;- Yikes, wrong format!&#xD;&#xA;		m_compute_shader.use();&#xD;&#xA;		glBindImageTexture(0, m_color_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;		glBindImageTexture(1, m_temp_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;		glDispatchCompute(m_info.window_width / 32, m_info.window_height / 32, 1);&#xD;&#xA;&#xD;&#xA;		// Full screen quad&#xD;&#xA;		glBindImageTexture(0, m_temp_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;		glDisable(GL_DEPTH_TEST);&#xD;&#xA;		m_full_screen_quad_shader.use();&#xD;&#xA;		glViewport(0, 0, m_info.window_width, m_info.window_height);&#xD;&#xA;		glBindVertexArray(m_full_screen_quad_vao);&#xD;&#xA;		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;&#xD;&#xA;And here is the compute shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (local_size_x = 32, local_size_y = 32) in;&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0, rgba32f) readonly uniform image2D input_image;&#xD;&#xA;    layout (binding = 1, rgba32f) writeonly uniform image2D output_image;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 texel;&#xD;&#xA;        ivec2 p = ivec2(gl_GlobalInvocationID.xy);&#xD;&#xA;    &#xD;&#xA;        texel = imageLoad(input_image, p);&#xD;&#xA;        texel = vec4(1.0) - texel;&#xD;&#xA;        imageStore(output_image, p, texel);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I just swap `m_temp_texture` with `m_color_texture` (which is the *input* image )	in the call to `glBindImageTexture(0, m_temp_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);` then I see the image, so I know it is not a problem with the frag shader. (Here is is though anyway):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0) uniform sampler2D input_image;&#xD;&#xA;    &#xD;&#xA;    layout (location = 0) out vec4 fragColor;&#xD;&#xA;    &#xD;&#xA;    //uniform float focal_distance = 50.0;&#xD;&#xA;    //uniform float focal_depth = 30.0;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 color = texelFetch(input_image, ivec2(gl_FragCoord.xy), 0).rgba;&#xD;&#xA;        fragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is there some reason why my compute shader is not being called? Even if I just write `imageStore(output_image, p, vec4(1.0));` in the compute shader, the screen is all black.  I do not know what I am missing.&#xD;&#xA;&#xD;&#xA;`glGetError` does not return anything.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I originally failed to include the code for the texture creation (the first two lines).  This affects the qustion. Please see the answer below. " ContentLicense="CC BY-SA 3.0" />
  <row Id="16313" PostHistoryTypeId="2" PostId="5899" RevisionGUID="7ea1bdb7-8cff-4b93-a505-8663dfaafdea" CreationDate="2017-11-20T09:21:22.790" UserId="7000" Text="Originally mistmatching image formats (`GL_RGB32F` instead of `GL_RGBA32F`) were used in the creation of textures and the call to `glBindImageTexture`.&#xD;&#xA;&#xD;&#xA;This error was hard to track down because the format (without alpha) only mattered (in this case) in the compute shader.&#xD;&#xA;&#xD;&#xA;Using `GL_RGBA32F`everywhere fixed the issue." ContentLicense="CC BY-SA 3.0" />
  <row Id="16314" PostHistoryTypeId="2" PostId="5900" RevisionGUID="ee980534-bf33-45cf-a30d-90c5a1721102" CreationDate="2017-11-20T10:33:14.170" UserId="137" Text="tl;dr The vao caches the calls to `glVertexAttribPointer` et. al.&#xD;&#xA;&#xD;&#xA;Every call to `glVertexAttribPointer`, `glEnableVertexAttribArray` and the binding of `gl_Element_Array` will store the parameters into the currently bound vao. In the case of `glVertexAttribPointer` it will also store the current binding to `GL_VERTEX_ARRAY` in the vao.&#xD;&#xA;&#xD;&#xA;This is a major help when drawing a lot of meshes because then the render loop turns from&#xD;&#xA;&#xD;&#xA;    void drawMesh(Mesh[] meshes){&#xD;&#xA;        foreach(mesh in meshes){        &#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);&#xD;&#xA;            glVertexAttribPointer(posAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, pos));&#xD;&#xA;            glVertexAttribPointer (normalAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, normal));&#xD;&#xA;            //...&#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);&#xD;&#xA;    &#xD;&#xA;            glDrawElements(GL_TRIANGLES, mesh.vertexCount, GL_UNSIGNED_INT, mesh.indexOffset);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;into &#xD;&#xA;&#xD;&#xA;    //done once per mesh on load&#xD;&#xA;    void prepareMeshForRender(Mesh mesh){&#xD;&#xA;        glBindVertexArray(mesh.vao);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);&#xD;&#xA;        &#xD;&#xA;        glVertexAttribPointer (posAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, pos));//will associate mesh.vbo with the posAttrLoc&#xD;&#xA;        glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;    &#xD;&#xA;        glVertexAttribPointer (normalAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, normal));&#xD;&#xA;        glEnableVertexAttribArray(normalAttrLoc);&#xD;&#xA;&#xD;&#xA;        //...&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); //this binding is also saved.&#xD;&#xA;        glBindVertexArray(0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void drawMesh(Mesh[] meshes){&#xD;&#xA;        foreach(mesh in meshes){        &#xD;&#xA;            glBindVertexArray(mesh.vao);&#xD;&#xA;            glDrawElements(GL_TRIANGLES, mesh.vertexCount, GL_UNSIGNED_INT, mesh.indexOffset);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This means a lot less calls and the driver can do some optimizations because it knows which vertex formats will be used. (some hardware has to do software vertex pulling so suddenly having a new format will require a patch of the vertex shader).&#xD;&#xA;&#xD;&#xA;In version 4.3 (or with extension ARB_separate_attrib_format) there is a new way to bind the vertex attributes where the vao holds the format separately from the buffer binding to help exactly the above mentioned hardware: &#xD;&#xA;&#xD;&#xA;    //accessible constant declarations&#xD;&#xA;    constexpr int vertexBindingPoint = 0;&#xD;&#xA;    constexpr int texBindingPoint = 1;// free to choose, must be less than the GL_MAX_VERTEX_ATTRIB_BINDINGS limit&#xD;&#xA;    &#xD;&#xA;    //during initialization&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));&#xD;&#xA;    // set the details of a single attribute&#xD;&#xA;    glVertexAttribBinding(posAttrLoc, vertexBindingPoint);&#xD;&#xA;    // which buffer binding point it is attached to&#xD;&#xA;    glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));&#xD;&#xA;    glVertexAttribBinding(normalAttrLoc, vertexBindingPoint);&#xD;&#xA;    glEnableVertexAttribArray(normalAttrLoc);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribFormat(texAttrLoc, 2, GL_FLOAT, false, offsetof(Texture, tex));&#xD;&#xA;    glVertexAttribBinding(texAttrLoc, texBindingPoint);&#xD;&#xA;    glEnableVertexAttribArray(texAttrLoc);&#xD;&#xA;&#xD;&#xA;    //...&#xD;&#xA;&#xD;&#xA;Then during draw you keep the vao bound and only change the buffer bindings.&#xD;&#xA;&#xD;&#xA;    void drawMesh(Mesh[] mesh){&#xD;&#xA;        glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;        foreach(mesh in meshes){&#xD;&#xA;            glBindVertexBuffer(vertexBindingPoint, mesh.vbo, mesh.vboOffset, sizeof(Vertex));&#xD;&#xA;            glBindVertexBuffer(texBindingPoint, mesh.texVbo, mesh.texVboOffset, sizeof(Texture));&#xD;&#xA;            // bind the buffers to the binding point&#xD;&#xA;    &#xD;&#xA;            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);&#xD;&#xA;    &#xD;&#xA;            glDrawElements(GL_TRIANGLES, mesh.vertexCount, GL_UNSIGNED_INT, mesh.indexOffset);&#xD;&#xA;            //draw&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;note: code sourced from now defunct docs.SO article on it [cached copy available here][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gist.github.com/ratchetfreak/be5d870396c6e43af3372344001e5339" ContentLicense="CC BY-SA 3.0" />
  <row Id="16315" PostHistoryTypeId="2" PostId="5901" RevisionGUID="a9020d0d-eec4-416c-91be-79748c153c9a" CreationDate="2017-11-20T16:16:00.740" UserId="7725" Text="I stumbled on this:&#xD;&#xA;http://diaryofagraphicsprogrammer.blogspot.com/2014/03/compute-shader-optimizations-for-amd.html&#xD;&#xA;&#xD;&#xA;Given that the tricks that can be done in compute shader (that are specific only to compute shaders) I was curious if parallel reduction on compute shader was faster than on pixel shader. I e-mail'ed the author, Wolf Engel, to ask if he had tried pixel shader. He replied that yes and back when he wrote the blog post the compute shader version was substantially faster than the pixel shader version. He also added that today the differences are even bigger. So apparently there are cases where using compute shader can be of great advantage." ContentLicense="CC BY-SA 3.0" />
  <row Id="16316" PostHistoryTypeId="2" PostId="5902" RevisionGUID="dbb9ee11-cfc5-434b-9337-7ad4c3838a88" CreationDate="2017-11-20T16:19:54.260" UserId="2654" Text="Buffer objects contain your vertex data. Vertex array objects tell OpenGL how to *interpret* that data. Without the VAO, OpenGL just knows that you suck some bytes into some buffers. The VAO says that &quot;in this buffer, at byte offset X, is an array of 4-vector floats, and that data will be fed to attribute index Y.&quot;&#xD;&#xA;&#xD;&#xA;They're state objects. VAOs are no more &quot;magical&quot; than this C++ data structure:&#xD;&#xA;&#xD;&#xA;    struct VertexFormat&#xD;&#xA;    {&#xD;&#xA;      bool enabled = false;&#xD;&#xA;      int attribute_index;&#xD;&#xA;      VertexFormatType data_type; //Is f32, f64, or int32.&#xD;&#xA;      int num_components = 4;&#xD;&#xA;      bool normalized = false;&#xD;&#xA;      GLenum type;&#xD;&#xA;      int binding;    //The `bindings` index this attribute gets its data from.&#xD;&#xA;      intptr_t offset;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VertexBufferBinding&#xD;&#xA;    {&#xD;&#xA;      BufferObject buffer;&#xD;&#xA;      intptr_t offset;&#xD;&#xA;      intptr_t stride;&#xD;&#xA;      int instancing;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VertexArrayObject&#xD;&#xA;    {&#xD;&#xA;      VertexFormat formats[16];&#xD;&#xA;      VertexBufferBinding bindings[16];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;The fields of `VertexFormat` are specified by the `glVertexAttrib*Format` or `glVertexAttrib*Pointer` functions. In the case of the latter, it also specifies the corresponding `VertexBufferBinding` data.&#xD;&#xA;&#xD;&#xA;Note that `VertexBufferBinding` stores a buffer object. That's where that binding point reads its data.&#xD;&#xA;&#xD;&#xA;This structure is not magical; it simply explains how to read vertex data from its associated buffers." ContentLicense="CC BY-SA 3.0" />
  <row Id="16317" PostHistoryTypeId="5" PostId="5901" RevisionGUID="56fa2ecd-c5ce-40cb-947c-64735bf8ab27" CreationDate="2017-11-20T16:26:28.013" UserId="7725" Comment="deleted 9 characters in body" Text="I stumbled on this:&#xD;&#xA;http://diaryofagraphicsprogrammer.blogspot.com/2014/03/compute-shader-optimizations-for-amd.html&#xD;&#xA;&#xD;&#xA;Given what tricks can be done in compute shader (that are specific only to compute shaders) I was curious if parallel reduction on compute shader was faster than on pixel shader. I e-mail'ed the author, Wolf Engel, to ask if he had tried pixel shader. He replied that yes and back when he wrote the blog post the compute shader version was substantially faster than the pixel shader version. He also added that today the differences are even bigger. So apparently there are cases where using compute shader can be of great advantage." ContentLicense="CC BY-SA 3.0" />
  <row Id="16318" PostHistoryTypeId="2" PostId="5903" RevisionGUID="90dfb493-1772-40bc-bc0d-b47ab2acccd0" CreationDate="2017-11-20T21:00:26.293" UserId="7644" Text="John has already written [a great answer][1] so consider this answer an extension of his.&#xD;&#xA;&#xD;&#xA;I'm currently working a lot with compute shaders for different algorithms. In general, I've found that compute shaders can be much faster than their equivalent pixel shader or transform feedback based alternatives.&#xD;&#xA;&#xD;&#xA;Once you wrap your head around how compute shaders work, they also make a lot more sense in many cases. Using pixels shaders to filter an image requires setting up a framebuffer, sending vertices, using multiple shader stages, etc. Why should this be required to filter an image? Being used to rendering full-screen quads for image processing is certainly the only &quot;valid&quot; reason to continue using them in my opinion. I'm convinced that a newcomer to the compute graphics field would find compute shaders a much more natural fit for image processing than rendering to textures.&#xD;&#xA;&#xD;&#xA;Your question refers to image filtering in particular so I won't elaborate too much on other topics. In some of our tests, just setting up a transform feedback or switching framebuffer objects to render to a texture could incur performance costs around 0.2ms. Keep in mind that this excludes any rendering! In one case, we kept the exact same algorithm ported to compute shaders and saw a noticeable performance increase.&#xD;&#xA;&#xD;&#xA;When using compute shaders, more of the silicon on the GPU can be used to do the actual work. All these additional steps are required when using the pixel shader route:&#xD;&#xA;&#xD;&#xA;- Vertex assembly (reading the vertex attributes, vertex divisors, type conversion, expanding them to vec4, etc.)&#xD;&#xA;- The vertex shader needs to be scheduled no matter how minimal it is&#xD;&#xA;- The rasterizer has to compute a list of pixels to shade and interpolate the vertex outputs (probably only texture coords for image processing)&#xD;&#xA;- All the different states (depth test, alpha test, scissor, blending) have to be set and managed&#xD;&#xA;&#xD;&#xA;You could argue that all the previously mentioned performance advantages could be negated by a smart driver. You would be right. Such a driver could identify that you're rendering a full-screen quad without depth testing, etc. and configure a &quot;fast path&quot; that skips all the useless work done to support pixel shaders. I wouldn't be surprised if some drivers do this to accelerate the post-processing passes in some AAA games for their specific GPUs. You can of course forget about any such treatment if you're not working on a AAA game.&#xD;&#xA;&#xD;&#xA;What the driver can't do however is find better parallelism opportunities offered by the compute shader pipeline. Take the classic example of a gaussian filter. Using compute shaders, you can do something like this (separating the filter or not):&#xD;&#xA;&#xD;&#xA;1. For each work group, divide the sampling of the source image across the work group size and store the results to group shared memory.&#xD;&#xA;2. Compute the filter output using the sample results stored in shared memory.&#xD;&#xA;3. Write to the output texture&#xD;&#xA;&#xD;&#xA;Step 1 is the key here. In the pixel shader version, the source image is sampled multiple times per pixel. In the compute shader version, each source texel is read only once inside a work group. Texture reads usually use a tile-based cache, but this cache is still much slower than shared memory.&#xD;&#xA;&#xD;&#xA;The gaussian filter is one of the simpler examples. Other filtering algorithms offer other opportunities to share intermediary results inside work groups using shared memory.&#xD;&#xA;&#xD;&#xA;There is however a catch. Compute shaders require explicit memory barriers to synchronize their output. There are also fewer safeguards to protect against errant memory accesses. For programmers with good parallel programming knowledge, compute shaders offer much more flexibility. This flexibility however means that it is also easier to treat compute shaders like ordinary C++ code and write slow or incorrect code.&#xD;&#xA;&#xD;&#xA;Here are some interesting articles and presentations on proper usage of compute shaders:&#xD;&#xA;&#xD;&#xA;- DirectCompute: Optimizations and Best Practices, Eric Young, NVIDIA Corporation, 2010 [[pdf]][2]&#xD;&#xA;- Efficient Compute Shader Proramming, Bill Bilodeau, AMD, 2011? [[pps]][3]&#xD;&#xA;- DirectCompute for Gaming - Supercharge your Engine with Compute Shaders, Layla Mah &amp; Stephan Hodes, AMD, 2013, [[pps]][4]&#xD;&#xA;- [Compute Shader Optimizations for AMD GPUs: Parallel Reduction, Wolfgang Engel, 2014][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/60/7644&#xD;&#xA;  [2]: http://on-demand.gputechconf.com/gtc/2010/presentations/S12312-DirectCompute-Pre-Conference-Tutorial.pdf&#xD;&#xA;  [3]: http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Efficient%20Compute%20Shader%20Programming.pps&#xD;&#xA;  [4]: http://developer.amd.com/wordpress/media/2013/04/DirectComputeForGaming_SuperchargeYourEngineWithComputeShaders.ppsx&#xD;&#xA;  [5]: http://diaryofagraphicsprogrammer.blogspot.ca/2014/03/compute-shader-optimizations-for-amd.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="16319" PostHistoryTypeId="2" PostId="5904" RevisionGUID="cf664d47-128b-4566-9baa-553f9faddae3" CreationDate="2017-11-21T05:27:08.683" UserId="2306" Text="When reducing color depth and dithering with a 2 bit noise (with n=-0.5 -&gt; 1.5 and output=floor(input*(2^bits-1) + n)), the ends of the value range (inputs 0.0 and 1.0) are noisy. It would be desirable to have them to be solid color.&#xD;&#xA;&#xD;&#xA;Example: https://www.shadertoy.com/view/llsfz4&#xD;&#xA;&#xD;&#xA;The problem can be of course solved by just compressing the value range so that the ends get always rounded to single values. This feels bit of a hack though, and I'm wondering if there's a way to implement this &quot;properly&quot;?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16320" PostHistoryTypeId="1" PostId="5904" RevisionGUID="cf664d47-128b-4566-9baa-553f9faddae3" CreationDate="2017-11-21T05:27:08.683" UserId="2306" Text="What's a proper way to clamp dither noise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16321" PostHistoryTypeId="3" PostId="5904" RevisionGUID="cf664d47-128b-4566-9baa-553f9faddae3" CreationDate="2017-11-21T05:27:08.683" UserId="2306" Text="|image-processing|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16322" PostHistoryTypeId="5" PostId="5904" RevisionGUID="8f67fbf7-98e8-4710-a14a-c1df883461d2" CreationDate="2017-11-21T05:37:42.500" UserId="2306" Comment="changed range syntax" Text="When reducing color depth and dithering with a 2 bit noise (with n=]0.5,1.5[ and output=floor(input*(2^bits-1) + n)), the ends of the value range (inputs 0.0 and 1.0) are noisy. It would be desirable to have them to be solid color.&#xD;&#xA;&#xD;&#xA;Example: https://www.shadertoy.com/view/llsfz4&#xD;&#xA;&#xD;&#xA;The problem can be of course solved by just compressing the value range so that the ends get always rounded to single values. This feels bit of a hack though, and I'm wondering if there's a way to implement this &quot;properly&quot;?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16323" PostHistoryTypeId="2" PostId="5905" RevisionGUID="36a7919e-69cc-4645-989b-c6cb929b3fda" CreationDate="2017-11-21T06:01:41.567" UserId="1937" Text="I know that texture caching on GPU works to optimize locality in 2D (or 3D if using 3D textures). I believe this is done using space-filling curves like Morton or Hilbert curves. &#xD;&#xA;&#xD;&#xA;When passing an array of texture data to the GPU, though, for example using glTextureSubImage2D, the data is specified in scan-line order.&#xD;&#xA;&#xD;&#xA;So how and when does the conversion take place? I can think of a couple of possibilites:&#xD;&#xA;&#xD;&#xA; 1. The texture is laid out linearly in VRAM, and the texture unit&#xD;&#xA;    merges transactions on different areas when loading to cache.&#xD;&#xA; 2. The texture gets swizzled when passed to the GPU, and is stored in VRAM in Morton-coded order (or another space-filling curve).&#xD;&#xA;&#xD;&#xA;So which is it, or is there another possibility I've missed? If it's option 2, is there an option to pass textures 'verbatim' if you already have a Morton-coded version on CPU-side? Or would you have to de-swizzle it before loading to GPU?&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 3.0" />
  <row Id="16324" PostHistoryTypeId="1" PostId="5905" RevisionGUID="36a7919e-69cc-4645-989b-c6cb929b3fda" CreationDate="2017-11-21T06:01:41.567" UserId="1937" Text="Are textures automatically Morton-coded when loaded to VRAM?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16325" PostHistoryTypeId="3" PostId="5905" RevisionGUID="36a7919e-69cc-4645-989b-c6cb929b3fda" CreationDate="2017-11-21T06:01:41.567" UserId="1937" Text="|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16326" PostHistoryTypeId="2" PostId="5906" RevisionGUID="7c5ce541-b457-45af-a4bf-7ad0d88ac688" CreationDate="2017-11-21T09:31:59.037" UserId="209" Text="Possibly &quot;all of the above&quot;. &#xD;&#xA;&#xD;&#xA;I've worked with different generations of the same vendor's hardware which have, variously, required software (either the API/driver or the texture tool) to preorder the texture data into a Morton/tiled layout, and others which, I think, had more &quot;built-in&quot; processing." ContentLicense="CC BY-SA 3.0" />
  <row Id="16327" PostHistoryTypeId="2" PostId="5907" RevisionGUID="58f03bf3-f9fb-4ad1-9b24-c6d339672988" CreationDate="2017-11-21T10:30:46.710" UserId="137" Text="In vulkan, like a lot of other implicit operations, this transition is made explicit. Images can be in one of 2 tiling layouts: optimal and linear. Linear images have a fixed layout while optimal is with implementation-defined space-filling curve. (There is no way currently to figure out which exact curve is used).&#xD;&#xA;&#xD;&#xA;To fill a optimally tiled image you need to copy from another image or from a vkBuffer (which has the data in linear format). The swizzle is done as part of the copy. But with the requirement that the data source must not be changed during the operation. Because other operations are allowed be read from the copy operation's source." ContentLicense="CC BY-SA 3.0" />
  <row Id="16328" PostHistoryTypeId="5" PostId="5903" RevisionGUID="5441f467-4820-42c3-b0b8-3d993768b89a" CreationDate="2017-11-21T13:33:56.480" UserId="7644" Comment="add wiki reference" Text="John has already written [a great answer][1] so consider this answer an extension of his.&#xD;&#xA;&#xD;&#xA;I'm currently working a lot with compute shaders for different algorithms. In general, I've found that compute shaders can be much faster than their equivalent pixel shader or transform feedback based alternatives.&#xD;&#xA;&#xD;&#xA;Once you wrap your head around how compute shaders work, they also make a lot more sense in many cases. Using pixels shaders to filter an image requires setting up a framebuffer, sending vertices, using multiple shader stages, etc. Why should this be required to filter an image? Being used to rendering full-screen quads for image processing is certainly the only &quot;valid&quot; reason to continue using them in my opinion. I'm convinced that a newcomer to the compute graphics field would find compute shaders a much more natural fit for image processing than rendering to textures.&#xD;&#xA;&#xD;&#xA;Your question refers to image filtering in particular so I won't elaborate too much on other topics. In some of our tests, just setting up a transform feedback or switching framebuffer objects to render to a texture could incur performance costs around 0.2ms. Keep in mind that this excludes any rendering! In one case, we kept the exact same algorithm ported to compute shaders and saw a noticeable performance increase.&#xD;&#xA;&#xD;&#xA;When using compute shaders, more of the silicon on the GPU can be used to do the actual work. All these additional steps are required when using the pixel shader route:&#xD;&#xA;&#xD;&#xA;- Vertex assembly (reading the vertex attributes, vertex divisors, type conversion, expanding them to vec4, etc.)&#xD;&#xA;- The vertex shader needs to be scheduled no matter how minimal it is&#xD;&#xA;- The rasterizer has to compute a list of pixels to shade and interpolate the vertex outputs (probably only texture coords for image processing)&#xD;&#xA;- All the different states (depth test, alpha test, scissor, blending) have to be set and managed&#xD;&#xA;&#xD;&#xA;You could argue that all the previously mentioned performance advantages could be negated by a smart driver. You would be right. Such a driver could identify that you're rendering a full-screen quad without depth testing, etc. and configure a &quot;fast path&quot; that skips all the useless work done to support pixel shaders. I wouldn't be surprised if some drivers do this to accelerate the post-processing passes in some AAA games for their specific GPUs. You can of course forget about any such treatment if you're not working on a AAA game.&#xD;&#xA;&#xD;&#xA;What the driver can't do however is find better parallelism opportunities offered by the compute shader pipeline. Take the classic example of a gaussian filter. Using compute shaders, you can do something like this (separating the filter or not):&#xD;&#xA;&#xD;&#xA;1. For each work group, divide the sampling of the source image across the work group size and store the results to group shared memory.&#xD;&#xA;2. Compute the filter output using the sample results stored in shared memory.&#xD;&#xA;3. Write to the output texture&#xD;&#xA;&#xD;&#xA;Step 1 is the key here. In the pixel shader version, the source image is sampled multiple times per pixel. In the compute shader version, each source texel is read only once inside a work group. Texture reads usually use a tile-based cache, but this cache is still much slower than shared memory.&#xD;&#xA;&#xD;&#xA;The gaussian filter is one of the simpler examples. Other filtering algorithms offer other opportunities to share intermediary results inside work groups using shared memory.&#xD;&#xA;&#xD;&#xA;There is however a catch. Compute shaders require explicit memory barriers to synchronize their output. There are also fewer safeguards to protect against errant memory accesses. For programmers with good parallel programming knowledge, compute shaders offer much more flexibility. This flexibility however means that it is also easier to treat compute shaders like ordinary C++ code and write slow or incorrect code.&#xD;&#xA;&#xD;&#xA;## References&#xD;&#xA;&#xD;&#xA;- [OpenGL Compute Shaders wiki page][2]&#xD;&#xA;- DirectCompute: Optimizations and Best Practices, Eric Young, NVIDIA Corporation, 2010 [[pdf]][3]&#xD;&#xA;- Efficient Compute Shader Proramming, Bill Bilodeau, AMD, 2011? [[pps]][4]&#xD;&#xA;- DirectCompute for Gaming - Supercharge your Engine with Compute Shaders, Layla Mah &amp; Stephan Hodes, AMD, 2013, [[pps]][5]&#xD;&#xA;- [Compute Shader Optimizations for AMD GPUs: Parallel Reduction, Wolfgang Engel, 2014][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/60/7644&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Compute_Shader&#xD;&#xA;  [3]: http://on-demand.gputechconf.com/gtc/2010/presentations/S12312-DirectCompute-Pre-Conference-Tutorial.pdf&#xD;&#xA;  [4]: http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Efficient%20Compute%20Shader%20Programming.pps&#xD;&#xA;  [5]: http://developer.amd.com/wordpress/media/2013/04/DirectComputeForGaming_SuperchargeYourEngineWithComputeShaders.ppsx&#xD;&#xA;  [6]: http://diaryofagraphicsprogrammer.blogspot.ca/2014/03/compute-shader-optimizations-for-amd.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="16335" PostHistoryTypeId="5" PostId="2481" RevisionGUID="4f13db58-9bf6-4e3f-adfd-8eacd467f294" CreationDate="2017-11-21T20:24:39.830" UserId="6172" Comment="The link was broken so I fixed it" Text="I would think rendering to a downsampled FBO would be much faster than generating mipmaps.  glGenerateMipmap will generate the complete mipmap pyramid, which seems wasteful:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenerateMipmap.xml&#xD;&#xA;&#xD;&#xA;Besides, only OpenGL ES 3.0 lets you manually select mip level when texturing:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/opengles/sdk/docs/man3/html/textureLod.xhtml&#xD;&#xA;&#xD;&#xA;Artistically, this might not give you the look you want.  In my experience, simply downsampling gives a grainy look.  I would recommend also doing a pair of one-dimensional blurs, as described in this article from GPU Gems:&#xD;&#xA;&#xD;&#xA;http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch21.html&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16336" PostHistoryTypeId="24" PostId="2481" RevisionGUID="4f13db58-9bf6-4e3f-adfd-8eacd467f294" CreationDate="2017-11-21T20:24:39.830" Comment="Proposed by 6172 approved by 209, 231 edit id of 290" ContentLicense="CC BY-SA 3.0" />
  <row Id="16337" PostHistoryTypeId="2" PostId="5910" RevisionGUID="d78daf24-ce99-4173-8e13-87f939cc4b93" CreationDate="2017-11-21T22:12:59.227" UserId="7412" Text="Given a polygon (regular or irregular, convex or concave). I want to round its corner, with radius, let's say 'x'. I have the code to draw an arc given 2 points. but how can I find the start and end points of the arc?&#xD;&#xA;&#xD;&#xA;All I have is a list of points representing each corner of the polygon.&#xD;&#xA;&#xD;&#xA;Here's a simple example, I have a list of vertices of corners of the figure (1). &#xD;&#xA;The figure (2) is what I need so I could draw the arcs to round the corners.&#xD;&#xA;&#xD;&#xA;PS: I'm developing a CAD drawing generator using .netdxf API (https://github.com/haplokuon/netDxf)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jeu7d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16338" PostHistoryTypeId="1" PostId="5910" RevisionGUID="d78daf24-ce99-4173-8e13-87f939cc4b93" CreationDate="2017-11-21T22:12:59.227" UserId="7412" Text="Rounding corners of polygon given vertices of it's corners" ContentLicense="CC BY-SA 3.0" />
  <row Id="16339" PostHistoryTypeId="3" PostId="5910" RevisionGUID="d78daf24-ce99-4173-8e13-87f939cc4b93" CreationDate="2017-11-21T22:12:59.227" UserId="7412" Text="|polygon|2d-graphics|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16340" PostHistoryTypeId="2" PostId="5911" RevisionGUID="935236ae-8a5b-46c8-b2d4-7add9e07baf2" CreationDate="2017-11-21T23:54:37.403" UserId="7644" Text="Since you're working on CAD software, you probably want some precise results. Here an algorithm that could work:&#xD;&#xA;&#xD;&#xA;For each side:&#xD;&#xA;&#xD;&#xA;- Compute the segment's equation.&#xD;&#xA;- Compute each round corner's circle equation.&#xD;&#xA;- Compute the intersections between the segment and each circle.&#xD;&#xA;- The 2 intersection points are the new endpoints for the line segment.&#xD;&#xA;&#xD;&#xA;This doesn't handle the case where a side is smaller than the rounded corner radius. You could reduce the rounded corner's radius in this case based on the segment's length." ContentLicense="CC BY-SA 3.0" />
  <row Id="16341" PostHistoryTypeId="2" PostId="5912" RevisionGUID="fb52d85d-24a7-4384-9a5f-d760c58d188f" CreationDate="2017-11-22T12:38:05.463" UserId="6929" Text="I want to decompose projection matrices into **near**, **far**, **top**, **bottom**, **left** and **right** values to create a bounding box for view frustum. I used the formula described in  this site [Decompose the OpenGL projection matrix][1]. This formula works for perspective which is created with frustum function ([glFrustum][3]). But it does not work for perspective which is created via perspective func ([gluPerspective][1]) &#xD;&#xA;&#xD;&#xA;Frustum and perspective may create same perspective effect but generated matrices seems different. So it seems I can't use single formula to extract perspective parameters. &#xD;&#xA;&#xD;&#xA;1. Is there any proof of that decomposition formula, or does it always work? &#xD;&#xA;2. How do I decompose the matrix generated by perspective function into **near**, **far**, **top**, **bottom**, **left** and **right** values? Is there any formula which is already used in industry?&#xD;&#xA;&#xD;&#xA;My implementations of ortho, frustum and perspetive is here: https://github.com/recp/cglm/blob/master/include/cglm/cam.h&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://lektiondestages.blogspot.com.tr/2013/11/decompose-opengl-projection-matrix.html&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml&#xD;&#xA;  [3]: https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="16342" PostHistoryTypeId="1" PostId="5912" RevisionGUID="fb52d85d-24a7-4384-9a5f-d760c58d188f" CreationDate="2017-11-22T12:38:05.463" UserId="6929" Text="How to decompose projection matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16343" PostHistoryTypeId="3" PostId="5912" RevisionGUID="fb52d85d-24a7-4384-9a5f-d760c58d188f" CreationDate="2017-11-22T12:38:05.463" UserId="6929" Text="|matrix|projections|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16344" PostHistoryTypeId="2" PostId="5913" RevisionGUID="5bbeaa82-ad26-46e5-b95f-d3bab00c123b" CreationDate="2017-11-22T12:50:26.863" UserId="7725" Text="Do you have any &quot;input data&quot; from which you constructed the matrix (like fov, near plane distance, etc.)? Or is the matrix itself *the only* data you have?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16345" PostHistoryTypeId="5" PostId="5913" RevisionGUID="e02aedee-c07f-432b-b280-29d8ae411fce" CreationDate="2017-11-22T13:36:12.673" UserId="7725" Comment="added 941 characters in body" Text="Do you have any &quot;input data&quot; from which you constructed the matrix (like fov, near plane distance, etc.)? Or is the matrix itself *the only* data you have?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Ok, so if you want to know the size of the near plane while you have viewProj matrix available do this:&#xD;&#xA;&#xD;&#xA;**a)** compute viewProj^-1&#xD;&#xA;&#xD;&#xA;**b)** vertices of the near plane in clip-space have coordinates (in OpenGL):&#xD;&#xA;(-1, -1, -1, 1)&#xD;&#xA;(-1,  1, -1, 1)&#xD;&#xA;( 1, -1, -1, 1)&#xD;&#xA;( 1,  1, -1, 1)&#xD;&#xA;&#xD;&#xA;and on the far plane:&#xD;&#xA;(-1, -1, 1, 1)&#xD;&#xA;(-1,  1, 1, 1)&#xD;&#xA;( 1, -1, 1, 1)&#xD;&#xA;( 1,  1, 1, 1)&#xD;&#xA;&#xD;&#xA;It's a unit cube spanning (-1, -1, -1) and (1, 1, 1) coordinates with w=1&#xD;&#xA;&#xD;&#xA;**c)** take each of those vertices, mutiply by viewProj^-1 and finally divide all resulting components by the w-component. That gives you the frustum's vertices in world space. From this you can easily find world space planes constraining the view frustum or the bounding box or whatever you like.&#xD;&#xA;&#xD;&#xA;I think it's not possible to extract left/right/bottom/top/near/far from the matrix directly. But since you can compute the world space coordinates of frustum's corners (as shown above) you can easily find left/right/bottom/top/near/far." ContentLicense="CC BY-SA 3.0" />
  <row Id="16348" PostHistoryTypeId="2" PostId="5915" RevisionGUID="56158039-4581-45f3-990f-838f88051af8" CreationDate="2017-11-23T01:17:21.210" UserId="4839" Text="I am interested in simulating water movement like this:&#xD;&#xA;&#xD;&#xA;1:45 to 3:05 of https://www.youtube.com/watch?v=sbrFIp73tbw&#xD;&#xA;&#xD;&#xA;I have learnt a lot of computer graphics so far, for example:&#xD;&#xA;&#xD;&#xA; 1. Interactive Computer Graphics: A Top-Down Approach with Shader-Based&#xD;&#xA;    OpenGL, 6th Edition, by Edward Angel and Dave Shreiner&#xD;&#xA;    &#xD;&#xA; 2.    Fluid Simulation for Computer Graphics, 2nd Edition, by Robert&#xD;&#xA;    Bridson&#xD;&#xA;&#xD;&#xA;, as well as other math books on e.g. linear algebra and numerical PDE solvers. They are all good books and I learnt lots of foundations of computer graphics from them, but it seems that they are too basic to be useful. So far, I still have no idea how to implement the video clip mentioned above. I know I still have a lot to learn and need to continue to invest vast time and efforts, but I hope my time and efforts devoted are not deviating from what I am aiming at. So, in order for me to implement the above water simulation, what is the shortest but sufficient study path, that is, what books and/or papers I need to read? &#xD;&#xA;&#xD;&#xA;A side note: the video implemented bubbles, but after splashing onto the wall, some water blobs should stick on the wall and flow down slowly, assuming the wall is plastic. This was not implemented. I want to make that effects myself too. &#xD;&#xA;&#xD;&#xA;Thank you for pointing me a correct direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="16349" PostHistoryTypeId="1" PostId="5915" RevisionGUID="56158039-4581-45f3-990f-838f88051af8" CreationDate="2017-11-23T01:17:21.210" UserId="4839" Text="Ask for a study path to simulate water like this" ContentLicense="CC BY-SA 3.0" />
  <row Id="16350" PostHistoryTypeId="3" PostId="5915" RevisionGUID="56158039-4581-45f3-990f-838f88051af8" CreationDate="2017-11-23T01:17:21.210" UserId="4839" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16351" PostHistoryTypeId="2" PostId="5916" RevisionGUID="0be6d619-0e7d-4d56-a303-7f6574cbd786" CreationDate="2017-11-23T02:31:47.267" UserId="5748" Text="The cut length from the vertex is x*ctan(t/2), where t is the angle at this vertex." ContentLicense="CC BY-SA 3.0" />
  <row Id="16352" PostHistoryTypeId="2" PostId="5917" RevisionGUID="55a5e876-5b1d-4b26-b087-86d0ca989366" CreationDate="2017-11-23T09:12:09.580" UserId="7724" Text="You could try [natural neighbour interpolation](https://en.wikipedia.org/wiki/Natural_neighbor_interpolation) or Sibson coordinates for this. These coordinates are based on a Voronoi tessellation of the points.&#xD;&#xA;The coordinates have been extended to approach where the points lie on some surface in [this](https://ac.els-cdn.com/S0925772101000189/1-s2.0-S0925772101000189-main.pdf?_tid=160000a8-d02d-11e7-99c0-00000aab0f27&amp;acdnat=1511427960_98dcfd5f9afa172805cda3bdc267f6ab) publication.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16353" PostHistoryTypeId="2" PostId="5918" RevisionGUID="fa9b01a3-35e5-405d-b7e8-696b222b1a55" CreationDate="2017-11-23T09:27:54.870" UserId="38" Text="Ok, Xenapior and Reynolds together have the right idea. But the explanation is a bit lacking so here is a image to explain it all and some further musings. Ok first let us draw an image (yes i know that is what they say in school for you to do but nobody does it).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;From the image we can see that there are 2 equal right triangles $V_2, A, C$ and $V_1, B, C$. In this triangle we have one unknown tyhat we can define namely rounding radius $r$, also we know right angle is 90&amp;deg;. The angle between the line $V_1-V_2 = \vec a$ and line $V_2-V_3 = \vec b$ is easy to compute with  the formulation fo angle between vectors&#xD;&#xA;&#xD;&#xA; $$\cos(\beta) = \frac{\vec a·\vec b}{ |\vec a|·|\vec b|}$$&#xD;&#xA;&#xD;&#xA;That in turn can be simplified if the vectors allready are normal. Thus three things of the triangle is known, which means all is known. So if you know the rounding radius to use the caclulating the points $A$, $B$ and $C$. So finally:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    a = normalize(V2-V1);&#xD;&#xA;    b = normalize(V2-V3);&#xD;&#xA;    halfang = acos(dot(a, b))/2.;&#xD;&#xA;    // skip center if you iuse splines&#xD;&#xA;    C = V2 - r / sin(halfang) * normalize((a+b)/2);&#xD;&#xA;    A = V2 - r/tan(halfang)*a;&#xD;&#xA;    B = V2 - r/tan(halfang)*b;&#xD;&#xA;&#xD;&#xA;You can simplify this a bit wiyth trigonometric identities. Or if you use rational B spliunes you can skip the calculation of C&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Note**: that this is only one possible formulation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/g55pU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16354" PostHistoryTypeId="5" PostId="5910" RevisionGUID="be771799-b46b-4e91-8752-ea396feb1d5e" CreationDate="2017-11-23T16:05:27.430" UserId="209" Comment="minor improvement to English" Text="Given a polygon (regular or irregular, convex or concave), I want to round its corner, with a given radius; let's say 'x'. I have the code to draw an arc given 2 points, but how can I find the start and end points of the arc?&#xD;&#xA;&#xD;&#xA;All I have is a list of points representing each corner of the polygon.&#xD;&#xA;&#xD;&#xA;Here's a simple example: I have a list of vertices of corners of the figure (1). &#xD;&#xA;The figure (2) is what I need so I could draw the arcs to round the corners.&#xD;&#xA;&#xD;&#xA;PS: I'm developing a CAD drawing generator using .netdxf API (https://github.com/haplokuon/netDxf)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jeu7d.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16355" PostHistoryTypeId="4" PostId="5910" RevisionGUID="be771799-b46b-4e91-8752-ea396feb1d5e" CreationDate="2017-11-23T16:05:27.430" UserId="209" Comment="minor improvement to English" Text="Rounding corners of polygon given vertices of its corners" ContentLicense="CC BY-SA 3.0" />
  <row Id="16357" PostHistoryTypeId="5" PostId="5918" RevisionGUID="94a9d8b0-d474-498c-8819-eccbb2a96d19" CreationDate="2017-11-24T12:42:05.647" UserId="38" Comment="added 6 characters in body" Text="Ok, Xenapior and Reynolds together have the right idea. But the explanation is a bit lacking so here is a image to explain it all and some further musings. First let us  start by drawing an image (yes i know that is what they say in school for you to do but nobody does it).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;From the image we can see that there are 2 equal right triangles $V_2, A, C$ and $V_1, B, C$. In this triangle we have one unknown that we can define namely rounding radius $r$, also we know right angle is 90&amp;deg;. The angle between the line $V_1-V_2 = \vec a$ and line $V_2-V_3 = \vec b$ is easy to compute with  the formulation fo angle between vectors&#xD;&#xA;&#xD;&#xA; $$\cos(\beta) = \frac{\vec a·\vec b}{ |\vec a|·|\vec b|}$$&#xD;&#xA;&#xD;&#xA;That in turn can be simplified if the vectors already are normal. Thus three things of the triangle is known, which means all is known. So if you know the rounding radius to use the calculating the points $A$, $B$ and $C$. So finally:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    a = normalize(V2-V1);&#xD;&#xA;    b = normalize(V2-V3);&#xD;&#xA;    halfang = acos(dot(a, b))/2.;&#xD;&#xA;    // skip center if you iuse splines&#xD;&#xA;    C = V2 - r / sin(halfang) * normalize((a+b)/2);&#xD;&#xA;    A = V2 - r/tan(halfang)*a;&#xD;&#xA;    B = V2 - r/tan(halfang)*b;&#xD;&#xA;&#xD;&#xA;You can simplify this a bit with trigonometric identities. Or if you use rational B-splines you can skip the calculation of C&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Note**: that this is only one possible formulation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/g55pU.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16359" PostHistoryTypeId="5" PostId="5917" RevisionGUID="8c927d50-75df-4e52-a0ca-365272986abc" CreationDate="2017-11-24T15:09:23.990" UserId="7724" Comment="added 3 characters in body" Text="You could try [natural neighbour interpolation](https://en.wikipedia.org/wiki/Natural_neighbor_interpolation) or Sibson coordinates for this. These coordinates are based on a Voronoi tessellation of the points.&#xD;&#xA;The coordinates have been extended to an approach where the points lie on some surface in [this](https://ac.els-cdn.com/S0925772101000189/1-s2.0-S0925772101000189-main.pdf?_tid=160000a8-d02d-11e7-99c0-00000aab0f27&amp;acdnat=1511427960_98dcfd5f9afa172805cda3bdc267f6ab) publication.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16360" PostHistoryTypeId="2" PostId="5919" RevisionGUID="e9e0d507-b112-4d09-8eee-e9b32e615a17" CreationDate="2017-11-25T01:54:49.893" UserId="7462" Text="I am trying to study the texture deformations caused when mapping a rectangle to a sphere, if I had a software that took an image as an input and displayed how it looks like when texture mapped to a sphere, it would allow me to observe and study this deformations better." ContentLicense="CC BY-SA 3.0" />
  <row Id="16361" PostHistoryTypeId="1" PostId="5919" RevisionGUID="e9e0d507-b112-4d09-8eee-e9b32e615a17" CreationDate="2017-11-25T01:54:49.893" UserId="7462" Text="Is there any free software to visualize a texture mapped to a sphere?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16362" PostHistoryTypeId="3" PostId="5919" RevisionGUID="e9e0d507-b112-4d09-8eee-e9b32e615a17" CreationDate="2017-11-25T01:54:49.893" UserId="7462" Text="|texture|mathematics|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16367" PostHistoryTypeId="2" PostId="5921" RevisionGUID="2d72f21d-a50a-4ba3-bc42-73ad681301c4" CreationDate="2017-11-25T10:25:25.337" UserId="209" Text="Although this is borderline &quot;off-topic&quot; for the site, there is perhaps a simple answer:&#xD;&#xA;&#xD;&#xA;Why not use a webgl approach such as this one?&#xD;&#xA;http://learningwebgl.com/lessons/lesson11/index.html&#xD;&#xA;(parent page here: http://learningwebgl.com/blog/?p=1253)&#xD;&#xA;&#xD;&#xA;Just rotate the image of the moon around until you have one of the poles visible and you'll see the typical artefacts you get with mapping a rectangle to a sphere.&#xD;&#xA;Though I've not tried, you could *probably* modify the code (use, say, &quot;view page source&quot; to read it, or save a local copy and edit) to load whatever texture your heart desired." ContentLicense="CC BY-SA 3.0" />
  <row Id="16369" PostHistoryTypeId="2" PostId="5922" RevisionGUID="df95fdb9-9fec-4d02-ab73-4dfdd5f2c06a" CreationDate="2017-11-25T11:47:14.857" UserId="7737" Text="Is there any reason why OpenGL performs primitives' clipping in clip coordinates? Can it be at least theoretically done in normalized device coordinates?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16370" PostHistoryTypeId="1" PostId="5922" RevisionGUID="df95fdb9-9fec-4d02-ab73-4dfdd5f2c06a" CreationDate="2017-11-25T11:47:14.857" UserId="7737" Text="Why does opengl perform clipping in clip coordinates?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16371" PostHistoryTypeId="3" PostId="5922" RevisionGUID="df95fdb9-9fec-4d02-ab73-4dfdd5f2c06a" CreationDate="2017-11-25T11:47:14.857" UserId="7737" Text="|opengl|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16373" PostHistoryTypeId="2" PostId="5923" RevisionGUID="60e5de14-85e6-415d-942f-5017eb3a4939" CreationDate="2017-11-25T18:09:36.357" UserId="7724" Text="Clipping could be done in normalised device coordinates as all primitives with z-coordinates outside -1 to 1 are outside the clipping planes. However, there is no reason not to do it in clip coordinates by considering z-coordinates from -w to w.&#xD;&#xA;&#xD;&#xA;Theoretically it possible. However it seems there is performance increase when doing the clipping in clip coordinates. By first comparing z-coordinates before perspective division it saves time by not computating perspective division for the clipped primitives. This means less division operations. This favourable as floating point division can take a few processing cycles." ContentLicense="CC BY-SA 3.0" />
  <row Id="16374" PostHistoryTypeId="2" PostId="5924" RevisionGUID="90dadea7-cff1-433c-8e67-dc1a30f4dae3" CreationDate="2017-11-25T20:17:32.463" UserId="2654" Text="The space after clip space is normalized device coordinate space, which is obtained by dividing `clip.xyz` by `clip.w`. If W is zero... oops.&#xD;&#xA;&#xD;&#xA;Oh sure, you could put a conditional test to see if W is zero or very close to zero. Or you can just do the clipping math in clip space and never have to worry about it. No post-clipping vertex can have a W of zero, because the clip box for each vertex is based on being in the *closed* range (-W, W). And if W is 0, then the closed range is an empty set, and thus the vertex is not on that range." ContentLicense="CC BY-SA 3.0" />
  <row Id="16375" PostHistoryTypeId="5" PostId="2110" RevisionGUID="50c95a13-1b21-4ebc-9ed7-b99627f70ae9" CreationDate="2017-11-25T21:15:30.373" UserId="2479" Comment="Minor wording improvements" Text="Single-scattering microfacet-based surface models like the original [Torrance-Sparrow BRDF][1] or derived models like [the BSDF for rough dielectric surfaces][2] by Walter et al. neglect inter-reflection of light between microfacets, which results in energy loss causing darkening especially at higher roughness values.&#xD;&#xA;&#xD;&#xA;The problem can be easily demonstrated using the furnace test. The following images show the behaviour of my implementation of a conductive microfacet BRDF using the Smith model and GGX distribution for roughness parameters from 0.2 to 1.0 (the Fresnel coefficient is deliberately set to 1 here to make the problem easier to see):&#xD;&#xA;&#xD;&#xA;[![roughness 0.2][3]][3]&#xD;&#xA;[![roughness 0.4][4]][4]&#xD;&#xA;[![roughness 0.6][5]][5]&#xD;&#xA;[![roughness 0.8][6]][6]&#xD;&#xA;[![roughness 1.0][7]][7]&#xD;&#xA;&#xD;&#xA;Furnace test of rough dielectric (IoR 1.51) BSDF using the Smith model and GGX microfacet distribution for roughness parameters from 0.2 to 1.0:&#xD;&#xA;&#xD;&#xA;[![roughness 0.2][8]][8]&#xD;&#xA;[![roughness 0.4][9]][9]&#xD;&#xA;[![roughness 0.6][10]][10]&#xD;&#xA;[![roughness 0.8][11]][11]&#xD;&#xA;[![roughness 1.0][12]][12]&#xD;&#xA;&#xD;&#xA;Eric Heitz et al. have just recently proposed a [multiple-scattering model][13] which solves the darkening problem by solving the light interaction completely, but there are performance issues due to stochastic nature of its evaluation routine as metioned by Heitz himself in the [LuxRender forum][14].&#xD;&#xA;&#xD;&#xA;Is there a known compensation method for recovering the lost energy of single-scattering models? Not necessarily physically correct, but at least not breaking physical plausibility (Helmholtz reciprocity and energy conservation) too much and, ideally, without the necessity of hand tuning parameters.&#xD;&#xA;&#xD;&#xA;In the [Disney BSDF][15], there is a parametrized component called “sheen” (basically a Fresnel-based glossy lobe) which can be used for compensation of darkening at edges, but as they mention in their [Siggraph 2015 course][16] it is very ad hoc method: &#xD;&#xA;&#xD;&#xA;&gt; “...this is very approximate, and doesn't work as well for other&#xD;&#xA;&gt; roughness values...”&#xD;&#xA;&#xD;&#xA;The [aforementioned comment][14] from Eric Heitz in the LuxRender forum also suggests using some compensation hack, but, unfortunately, doesn't go into any details:&#xD;&#xA;&#xD;&#xA;&gt; To my knowledge, you can use some simpler hacks to improve energy conservation in the single scattering models (like tweaking albedo). However, if you do that, you cannot get a perfectly energy conserving material (for instance perfect white rough glass) without breaking the reciprocity of the BSDF.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.cornell.edu/~westin/pubs/TorranceSparrowJOSA1967.pdf&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZmLm3.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/lIxSc.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/autib.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ij2yS.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/eP5XW.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/EZWNf.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/wtcLq.jpg&#xD;&#xA;  [10]: https://i.stack.imgur.com/YisLW.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/SdaAG.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5PdTb.jpg&#xD;&#xA;  [13]: https://eheitzresearch.wordpress.com/240-2/&#xD;&#xA;  [14]: http://www.luxrender.net/forum/viewtopic.php?f=36&amp;t=12534#p118797&#xD;&#xA;  [15]: http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf&#xD;&#xA;  [16]: http://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16378" PostHistoryTypeId="2" PostId="5925" RevisionGUID="c2fcf4fc-ca3d-45be-9a74-13de206037d0" CreationDate="2017-11-26T04:26:42.733" UserId="7743" Text="A scene can be pre-rendered from a single camera position.&#xD;&#xA;&#xD;&#xA;Can a scene be efficiently rendered for a fixed set of positions and lines that the camera can move through?&#xD;&#xA;&#xD;&#xA;Consider games like escape room games where the camera only assumes fixed locations. Can the transition between those positions also be rendered more efficiently than frame-by-frame?&#xD;&#xA;&#xD;&#xA;Suppose I wanted the player to move freely along a fixed linear (or curved) track, how can I show the maximum render quality?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16379" PostHistoryTypeId="1" PostId="5925" RevisionGUID="c2fcf4fc-ca3d-45be-9a74-13de206037d0" CreationDate="2017-11-26T04:26:42.733" UserId="7743" Text="Can a scene be efficiently pre-rendered and displayed along a fixed camera line?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16380" PostHistoryTypeId="3" PostId="5925" RevisionGUID="c2fcf4fc-ca3d-45be-9a74-13de206037d0" CreationDate="2017-11-26T04:26:42.733" UserId="7743" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16381" PostHistoryTypeId="2" PostId="5926" RevisionGUID="f1b733a3-cc1c-4864-bf42-086e9cff34e4" CreationDate="2017-11-26T07:26:38.583" UserId="7334" Text="I'm trying to render water using path tracing. However, since in path tracing, the light sampling is skipped while the intersection point is perfect specular and thus no direct light would be taken into account.&#xD;&#xA;&#xD;&#xA;So does that mean **all contributions(radiance) are indirect lighting on specular surfaces**(i.e. dirac BSDFs), no direct light should be computed for specular sufaces?&#xD;&#xA;&#xD;&#xA;Say, I have a scene with environment map(infinite sphere) and a water object, represented by a triangle mesh. If the max bounce parameter is set to **1**, then the water surface would not be lit at all.&#xD;&#xA;&#xD;&#xA;And if the max bounce parameter is set to 2, all contributions are from rays reflected and &quot;hit the environment map&quot;. For those reflected rays still hit the water surface, there would be no radiance on that ray.&#xD;&#xA;&#xD;&#xA;The consequence would be for some region on the water appears to be very dark.&#xD;&#xA;&#xD;&#xA;I wonder if my understanding is right, and if not, how do I fix it?&#xD;&#xA;&#xD;&#xA;Here's my demo for one bounce, two bounces and 20 bounces.&#xD;&#xA;&#xD;&#xA;**1 bounce**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**2 bounces**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**20 bounces**&#xD;&#xA;I think the color in the red box is incorrect, it should be brighter.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WooiS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qLU3b.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uUIcG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16382" PostHistoryTypeId="1" PostId="5926" RevisionGUID="f1b733a3-cc1c-4864-bf42-086e9cff34e4" CreationDate="2017-11-26T07:26:38.583" UserId="7334" Text="How does path tracing handle specular surfaces(Dirac BSDFs) such as water?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16383" PostHistoryTypeId="3" PostId="5926" RevisionGUID="f1b733a3-cc1c-4864-bf42-086e9cff34e4" CreationDate="2017-11-26T07:26:38.583" UserId="7334" Text="|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16384" PostHistoryTypeId="12" PostId="5923" RevisionGUID="852af6b6-52e7-4640-81f7-35fa92b8fb9d" CreationDate="2017-11-26T10:50:09.953" UserId="7724" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7724,&quot;DisplayName&quot;:&quot;Reynolds&quot;}]}" />
  <row Id="16385" PostHistoryTypeId="13" PostId="5923" RevisionGUID="d0c2042e-24b4-4196-84ef-6ddd028dc093" CreationDate="2017-11-26T11:05:39.097" UserId="7724" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7724,&quot;DisplayName&quot;:&quot;Reynolds&quot;}]}" />
  <row Id="16386" PostHistoryTypeId="5" PostId="5923" RevisionGUID="d6da4e48-e159-48f6-81ba-6cc6afc7faac" CreationDate="2017-11-26T11:33:36.287" UserId="7724" Comment="deleted 2 characters in body" Text="Clipping could be done in normalised device coordinates as all primitives with z-coordinates outside -1 to 1 are outside the clipping planes. However, there is no reason not to do it in clip coordinates by considering z-coordinates from -w to w.&#xD;&#xA;&#xD;&#xA;Theoretically it possible. However it seems there is performance increase when doing the clipping in clip coordinates. By first comparing z-coordinates before perspective division it saves time by not computing perspective division for the clipped primitives. This means less division operations. This favourable as floating point division can take a few processing cycles.&#xD;&#xA;&#xD;&#xA;Refer also to the answer in [this](https://gamedev.stackexchange.com/questions/65789/why-is-clip-space-always-referred-to-as-homogeneous-clip-space) related question&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16391" PostHistoryTypeId="50" PostId="4760" RevisionGUID="8da90e36-d83b-4ae9-939b-57dbdcdf0bd9" CreationDate="2017-11-26T14:17:11.753" UserId="-1" />
  <row Id="16397" PostHistoryTypeId="5" PostId="5924" RevisionGUID="207a3f8c-fdf7-41f9-b77a-ee9e2e90b74d" CreationDate="2017-11-26T16:30:41.583" UserId="2654" Comment="added 487 characters in body" Text="The space after clip space is normalized device coordinate space, which is obtained by dividing `clip.xyz` by `clip.w`. If W is zero... oops.&#xD;&#xA;&#xD;&#xA;Oh sure, you could put a conditional test to see if W is zero or very close to zero. Or you can just do the clipping math in clip space and never have to worry about it. No post-clipping vertex can have a W of zero, because the clip box for each vertex is based on being in the *closed* range (-W, W). And if W is 0, then the closed range is an empty set, and thus the vertex is not on that range.&#xD;&#xA;&#xD;&#xA;Also, negative values of W are outside of the clipping space. The closed range (-W, W) is inverted where W is negative, but the meaning of the range itself is not. Consider a W of -1; the range becomes (1, -1). There are no numbers that are simultaneously greater than 1 and less than -1. Therefore that space is *empty*.&#xD;&#xA;&#xD;&#xA;And yet, division by a negative W can still land NDC points in the [-1, 1] NDC-space range, where they will not be clipped if you didn't clip them beforehand." ContentLicense="CC BY-SA 3.0" />
  <row Id="16399" PostHistoryTypeId="2" PostId="5929" RevisionGUID="4f819748-6872-4533-b1c2-9f2206534521" CreationDate="2017-11-28T10:42:09.517" UserId="7724" Text="You could calculate the midpoints of the segments between the vertices (atoms) of the icosahedron. These are the positions of the cylinders. You would then need to determine the orientation and scale of the cylinders. This information should then be encoded into a transformation matrix. Doing this for every cylinder would mean multiple transformation matrices.&#xD;&#xA;&#xD;&#xA;An effective way to draw many copies of the same object is to use instanced drawing. Instead of defining the position of the vertices of each cylinder separately, you only define the geometry for one cylinder and send this to a buffer. You can then draw a number of copies of this cylinder and transforming each copy of this cylinder with its respective transformation matrix. &#xD;&#xA;&#xD;&#xA;A couple of things you would need to look up documentation for is [instanced drawing](https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glDrawElementsInstanced.xhtml). Next, would be to investigate [attribute divisors](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml). Attribute divisors regulate the rate for which vertex attributes are read from the buffer. If you upload you transformation matrices for each cylinder with 40 vertices. You would want to have one transformation matrix for each batch of 40 vertices. Therefore, the attribute divisor for the transformation matrix should be set to 1, such that it advances once per batch of vertices.&#xD;&#xA;&#xD;&#xA;Using this approach it is best to define you cylinder as an axis aligned unit length and width cylinder centered at the origin. This will simply the transformations a whole lot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16400" PostHistoryTypeId="5" PostId="5929" RevisionGUID="a0867c3e-14bd-4673-8620-757d22c36c2a" CreationDate="2017-11-28T10:47:30.680" UserId="7724" Comment="added 199 characters in body" Text="You could calculate the midpoints of the segments between the vertices (atoms) of the icosahedron. These are the positions of the cylinders. You would then need to determine the orientation and scale of the cylinders. This information should then be encoded into a transformation matrix. Doing this for every cylinder would mean multiple transformation matrices.&#xD;&#xA;&#xD;&#xA;An effective way to draw many copies of the same object is to use instanced drawing. Instead of defining the position of the vertices of each cylinder separately, you only define the geometry for one cylinder and send this to a buffer. You can then draw a number of copies of this cylinder and transforming each copy of this cylinder with its respective transformation matrix. The matrices should be put into a buffer on the GPU to make it efficient. Alternatively, it is possible to do it with uniforms but this would mean multiple draw calls and no instancing.&#xD;&#xA;&#xD;&#xA;A couple of things you would need to look up documentation for is [instanced drawing](https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glDrawElementsInstanced.xhtml). Next, would be to investigate [attribute divisors](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml). Attribute divisors regulate the rate for which vertex attributes are read from the buffer. If you upload the transformation matrices for each cylinder with 40 vertices to the buffer. You would want to have one transformation matrix for each batch of 40 vertices. Therefore, the attribute divisor for the transformation matrix should be set to 1, such that it advances once per batch of vertices.&#xD;&#xA;&#xD;&#xA;Using this approach it is best to define you cylinder as an axis aligned unit length and width cylinder centered at the origin. This will simply the transformations a whole lot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16401" PostHistoryTypeId="2" PostId="5930" RevisionGUID="1f6040b3-64f3-455b-a10c-40baa60120e4" CreationDate="2017-11-28T11:08:29.487" UserId="209" Text="Would Diego Nehab et al's &quot;Accelerating Real-Time Shading with Reverse Reprojection Caching&quot; be the sort of thing you are looking for? &#xD;&#xA;&#xD;&#xA;[Paper Link][1] and/or [Slide presentation from Graphics Hardware 2007][2]&#xD;&#xA;&#xD;&#xA;IIRC, the idea is to reuse a previous frame's rendered image results in the current frame rather than running a, potentially expensive, shader for every pixel.&#xD;&#xA;&#xD;&#xA;At the conference, I did ask Diego if he'd considered doing 'bidirectional' reuse (i.e. rendering frames out of order somewhat akin to h.264) but I can't recall his answer. I think in your proposed use case it might be of value.&#xD;&#xA;&#xD;&#xA;  [1]: http://gfx.cs.princeton.edu/pubs/Nehab_2007_ARS/NehEtAl07.pdf&#xD;&#xA;  [2]: http://www.graphicshardware.org/previous/www_2007/presentations/nehab-reprojection-gh07.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16402" PostHistoryTypeId="33" PostId="4370" RevisionGUID="2269cfed-aa44-4d69-a678-1f0871791ee8" CreationDate="2017-11-28T11:08:43.790" UserId="18" Comment="41" />
  <row Id="16403" PostHistoryTypeId="5" PostId="5929" RevisionGUID="d151bce9-3f64-4fb4-a4e8-17b218dc48b8" CreationDate="2017-11-28T12:20:27.940" UserId="7724" Comment="added 2 characters in body" Text="You could calculate the midpoints of the segments between the vertices (atoms) of the icosahedron. These are the positions of the cylinders. You would then need to determine the orientation and scale of the cylinders. This information should then be encoded into a transformation matrix. Doing this for every cylinder would mean multiple transformation matrices.&#xD;&#xA;&#xD;&#xA;An effective way to draw many copies of the same object is to use instanced drawing. Instead of defining the position of the vertices of each cylinder separately, you only define the geometry for one cylinder and send this to a buffer. You can then draw a number of copies of this cylinder and transforming each copy of this cylinder with its respective transformation matrix. The matrices should be put into a buffer on the GPU to make it efficient. Alternatively, it is possible to do it with uniforms but this would mean multiple draw calls and no instancing.&#xD;&#xA;&#xD;&#xA;A couple of things you would need to look up documentation for is [instanced drawing](https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glDrawElementsInstanced.xhtml). Next, would be to investigate [attribute divisors](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml). Attribute divisors regulate the rate for which vertex attributes are read from the buffer. If you upload the transformation matrices for each cylinder with 40 vertices to the buffer. You would want to have one transformation matrix for each batch of 40 vertices. Therefore, the attribute divisor for the transformation matrix should be set to 1, such that it advances once per batch of vertices.&#xD;&#xA;&#xD;&#xA;Using this approach it is best to define you cylinder as an axis aligned unit length and width cylinder centered at the origin. This will simplify the transformations a whole lot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16404" PostHistoryTypeId="2" PostId="5931" RevisionGUID="6656c4aa-1eb5-4272-bb7a-83b36442240b" CreationDate="2017-11-28T15:59:05.893" UserId="56" Text="Stencil bits are often used for optimizations, for instance having full screen lighting passes only affect certain pixels.&#xA;&#xA;Does the stencil test mechanism use any acceleration structures of any kind (like maybe dividing the screen into a coarser grid?) or do the perf benefits come solely from having a pre-pixel shader test that can early out waves of shaders?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16405" PostHistoryTypeId="1" PostId="5931" RevisionGUID="6656c4aa-1eb5-4272-bb7a-83b36442240b" CreationDate="2017-11-28T15:59:05.893" UserId="56" Text="Do stencil tests use any acceleration techniques?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16406" PostHistoryTypeId="3" PostId="5931" RevisionGUID="6656c4aa-1eb5-4272-bb7a-83b36442240b" CreationDate="2017-11-28T15:59:05.893" UserId="56" Text="|optimisation|stencil-test|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16407" PostHistoryTypeId="2" PostId="5932" RevisionGUID="055f72e4-d3b9-4589-b211-ec2a69ef1d4d" CreationDate="2017-11-28T19:06:32.767" UserId="7644" Text="I don't have a definite authoritive answer for you but I'm very confident that the answer is &quot;yes&quot;. Here's why:&#xD;&#xA;&#xD;&#xA;When using framebuffer objects, [stencil attachments are usually combined][1] with the depth attachment in a single texture (`GL_DEPTH24_STENCIL8` or `GL_DEPTH32F_STENCIL8`). In fact, until recently, a combined depth and stencil was the only way to get a stencil buffer. It is now possible to create a stencil only attachment for an FBO.&#xD;&#xA;&#xD;&#xA;This [OpenGL wiki article on FBOs][2] states (emphasis mine):&#xD;&#xA;&#xD;&#xA;&gt; These color formats can be combined with a depth attachment with any of the required depth formats. Stencil attachments can also be used, again with the required stencil formats, as well as the combined depth/stencil formats. However, **implementations are only required to support both a depth and stencil attachment simultaneously if both attachments refer to the same image**.&#xD;&#xA;&#xD;&#xA;&gt; This means that if you want stencil with no depth, you can use one of the required stencil formats. If you want depth with no stencil, you can use one of the required depth formats. **But if you want depth and stencil, you must use a depth/stencil format and the same image in that texture must be attached to both the depth and stencil attachments**.&#xD;&#xA;&#xD;&#xA;All this strongly hints towards an accelerated storage format for stencils similar to the one used by depth buffers.&#xD;&#xA;&#xD;&#xA;Also, empirically, over the years many rendering algorithms (e.g. stencil shadows) using the stencil buffer would have been prohibitively slow if stencil buffers did not use some form of accelerated structure.&#xD;&#xA;&#xD;&#xA;The [NV_packed_depth_stencil extension][3] (2001) spec also provides interesting insight:&#xD;&#xA;&#xD;&#xA;&gt; Many OpenGL implementations have chosen to interleave the depth and stencil buffers into one buffer, often with 24 bits of depth precision and 8 bits of stencil data.&#xD;&#xA;&#xD;&#xA;and (emphasis mine)&#xD;&#xA;&#xD;&#xA;&gt; Should the depth/stencil format support other standard types, like GL_FLOAT or GL_UNSIGNED_INT?&#xD;&#xA;&#xD;&#xA;&gt; RESOLVED: No, this extension is designed to be minimalist. Supporting more types gains little because the new types will just require data format conversions.  **Our goal is to match the native format of the buffer**, not add broad new classes of functionality.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Format#Depth_stencil_formats&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Framebuffer_Object&#xD;&#xA;  [3]: https://www.khronos.org/registry/OpenGL/extensions/NV/NV_packed_depth_stencil.txt" ContentLicense="CC BY-SA 3.0" />
  <row Id="16408" PostHistoryTypeId="50" PostId="5793" RevisionGUID="abd6ae2a-03e2-4c15-828a-b23a893954fc" CreationDate="2017-11-29T10:51:24.277" UserId="-1" />
  <row Id="16409" PostHistoryTypeId="5" PostId="4319" RevisionGUID="0dba7ee8-7b21-461e-8d7c-6ed9eb8b4646" CreationDate="2017-11-29T22:03:23.673" UserId="1649" Comment="added 2060 characters in body" Text="While creating a set of glTF models for a tutorial, I also intended to create **THE** minimal glTF file. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Update:** The following referred to glTF 1.0/1.1. See below for an update of this example to glTF 2.0.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;As already mentioned in the [answer by 5chdn](https://computergraphics.stackexchange.com/a/3628/1649), one issue may be the *material*. According to the [Appendix A: Default Material](https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a) of the specification, an asset that does not contain a material should be rendered with a *default* material that simply shows the object in a uniform, 50% gray color. &#xD;&#xA;&#xD;&#xA;Some viewers might not support this, and even if they do, there have been some minor subtleties in the spec regarding this point: In glTF 1.0, it was still necessary to define an &quot;empty&quot; material, because the `mesh.primitive.material` property was not yet optional. But this should be fixed in glTF 1.1. &#xD;&#xA;&#xD;&#xA;So the following should indeed be **THE** minimal possible glTF asset (version 1.1) :&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;      &quot;scenes&quot; : {&#xD;&#xA;        &quot;scene0&quot; : {&#xD;&#xA;          &quot;nodes&quot; : [ &quot;node0&quot; ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;nodes&quot; : {&#xD;&#xA;        &quot;node0&quot; : {&#xD;&#xA;          &quot;meshes&quot; : [ &quot;mesh0&quot; ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;    &#xD;&#xA;      &quot;meshes&quot; : {&#xD;&#xA;        &quot;mesh0&quot; : {&#xD;&#xA;          &quot;primitives&quot; : [ {&#xD;&#xA;            &quot;attributes&quot; : {&#xD;&#xA;              &quot;POSITION&quot; : &quot;positionsAccessor&quot;&#xD;&#xA;            }&#xD;&#xA;          } ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;    &#xD;&#xA;      &quot;buffers&quot; : {&#xD;&#xA;        &quot;buffer0&quot; : {&#xD;&#xA;          &quot;uri&quot; : &quot;data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAA&quot;,&#xD;&#xA;          &quot;byteLength&quot; : 36&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;bufferViews&quot; : {&#xD;&#xA;        &quot;positionsBufferView&quot; : {&#xD;&#xA;          &quot;buffer&quot; : &quot;buffer0&quot;,&#xD;&#xA;          &quot;byteOffset&quot; : 0,&#xD;&#xA;          &quot;byteLength&quot; : 36,&#xD;&#xA;          &quot;target&quot; : 34962&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &quot;accessors&quot; : {&#xD;&#xA;        &quot;positionsAccessor&quot; : {&#xD;&#xA;          &quot;bufferView&quot; : &quot;positionsBufferView&quot;,&#xD;&#xA;          &quot;byteOffset&quot; : 0,&#xD;&#xA;          &quot;componentType&quot; : 5126,&#xD;&#xA;          &quot;count&quot; : 3,&#xD;&#xA;          &quot;type&quot; : &quot;VEC3&quot;,&#xD;&#xA;          &quot;max&quot; : [ 1.0, 1.0, 0.0 ],&#xD;&#xA;          &quot;min&quot; : [ 0.0, 0.0, 0.0 ]&#xD;&#xA;        }&#xD;&#xA;      },&#xD;&#xA;      &#xD;&#xA;      &quot;asset&quot; : {&#xD;&#xA;        &quot;version&quot; : &quot;1.1&quot;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;It also shows a single triangle:&#xD;&#xA;&#xD;&#xA;[![TriangleWithoutIndices][1]][1]&#xD;&#xA;&#xD;&#xA;The version without embedded buffers is available at https://github.com/javagl/gltfTutorialModels , as well as a triangle with indices, at https://github.com/javagl/gltfTutorialModels/tree/master/Triangle &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Update for glTF 2.0:**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The concepts and top-level elements of glTF 2.0 are basically the same as for glTF 1.0. But there still have been some changes in the format. Most importantly (for this small example), the top-level dictionaries are now *arrays*. The following is the same &quot;Triangle&quot; model as above, updated accordingly:&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;       &quot;scenes&quot;:[&#xD;&#xA;          {&#xD;&#xA;             &quot;nodes&quot;:[ 0 ]&#xD;&#xA;          }&#xD;&#xA;       ],&#xD;&#xA;       &quot;nodes&quot;:[&#xD;&#xA;          {&#xD;&#xA;             &quot;mesh&quot;:0&#xD;&#xA;          }&#xD;&#xA;       ],&#xD;&#xA;       &quot;meshes&quot;:[&#xD;&#xA;          {&#xD;&#xA;             &quot;primitives&quot;:[&#xD;&#xA;                {&#xD;&#xA;                   &quot;attributes&quot;:{&#xD;&#xA;                      &quot;POSITION&quot;:1&#xD;&#xA;                   },&#xD;&#xA;                   &quot;indices&quot;:0&#xD;&#xA;                }&#xD;&#xA;             ]&#xD;&#xA;          }&#xD;&#xA;       ],&#xD;&#xA;       &quot;buffers&quot;:[&#xD;&#xA;          {&#xD;&#xA;             &quot;uri&quot;:&quot;data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=&quot;,&#xD;&#xA;             &quot;byteLength&quot;:44&#xD;&#xA;          }&#xD;&#xA;       ],&#xD;&#xA;       &quot;bufferViews&quot;:[&#xD;&#xA;          {&#xD;&#xA;             &quot;buffer&quot;:0,&#xD;&#xA;             &quot;byteOffset&quot;:0,&#xD;&#xA;             &quot;byteLength&quot;:6,&#xD;&#xA;             &quot;target&quot;:34963&#xD;&#xA;          },&#xD;&#xA;          {&#xD;&#xA;             &quot;buffer&quot;:0,&#xD;&#xA;             &quot;byteOffset&quot;:8,&#xD;&#xA;             &quot;byteLength&quot;:36,&#xD;&#xA;             &quot;target&quot;:34962&#xD;&#xA;          }&#xD;&#xA;       ],&#xD;&#xA;       &quot;accessors&quot;:[&#xD;&#xA;          {&#xD;&#xA;             &quot;bufferView&quot;:0,&#xD;&#xA;             &quot;byteOffset&quot;:0,&#xD;&#xA;             &quot;componentType&quot;:5123,&#xD;&#xA;             &quot;count&quot;:3,&#xD;&#xA;             &quot;type&quot;:&quot;SCALAR&quot;,&#xD;&#xA;             &quot;max&quot;:[&#xD;&#xA;                2&#xD;&#xA;             ],&#xD;&#xA;             &quot;min&quot;:[&#xD;&#xA;                0&#xD;&#xA;             ]&#xD;&#xA;          },&#xD;&#xA;          {&#xD;&#xA;             &quot;bufferView&quot;:1,&#xD;&#xA;             &quot;byteOffset&quot;:0,&#xD;&#xA;             &quot;componentType&quot;:5126,&#xD;&#xA;             &quot;count&quot;:3,&#xD;&#xA;             &quot;type&quot;:&quot;VEC3&quot;,&#xD;&#xA;             &quot;max&quot;:[&#xD;&#xA;                1.0,&#xD;&#xA;                1.0,&#xD;&#xA;                0.0&#xD;&#xA;             ],&#xD;&#xA;             &quot;min&quot;:[&#xD;&#xA;                0.0,&#xD;&#xA;                0.0,&#xD;&#xA;                0.0&#xD;&#xA;             ]&#xD;&#xA;          }&#xD;&#xA;       ],&#xD;&#xA;       &quot;asset&quot;:{&#xD;&#xA;          &quot;version&quot;:&quot;2.0&quot;&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This and other glTF sample models can be found in the [glTF sample models repository](https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ElVqk.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16410" PostHistoryTypeId="2" PostId="5933" RevisionGUID="8b7dc224-f45c-49da-8437-ce0f3b854ad1" CreationDate="2017-11-30T00:58:48.183" UserId="5703" Text="I am having my first encounter with the rendering of indirect reflections in the form of screen space reflections in a game engine, but i am struggling to get correct looking results.&#xD;&#xA;&#xD;&#xA;[![taken at low resolution and ray count][1]][1]&#xD;&#xA;&#xD;&#xA;(patterns arise from a bad way of generating noise for montecarlo integration)&#xD;&#xA;&#xD;&#xA;(image taken at low ray count. otherwise the color values end up going to NaN)&#xD;&#xA;&#xD;&#xA;From what i've gathered, a common formulation of the rendering equation is as follows:&#xD;&#xA;&#xD;&#xA;$$L_o(p,\omega_o)=L_e(p,\omega_o)+\int_{\Omega}L_i(p,\omega_i)fr(\omega_i,\omega_o)(n\cdot\omega_i)d\omega_i$$&#xD;&#xA;&#xD;&#xA;which, dropping the $L_e(p,\omega_o)$ term, can be approximated using the following monte carlo estimator:&#xD;&#xA;&#xD;&#xA;$$L_o(p,\omega_o)\approx\frac{1}{N}\sum_{i=1}^{N}\frac{L_i(p,\omega_i)fr(\omega_i,\omega_o)(n\cdot\omega_i)}{p(\omega_i)}$$&#xD;&#xA;&#xD;&#xA;where $n$ is a unit vector perpendicular to the surface.&#xD;&#xA;&#xD;&#xA;for actual computation of values, all of these terms must be specified.&#xD;&#xA;&#xD;&#xA;$L_i(p,\omega_i)$ is found through raymarching in screen space&#xD;&#xA;&#xD;&#xA;$fr(\omega_i,\omega_o)$ is the Cook-Torrance BRDF:$\frac{FGD}{4(n\cdot\omega_i)(n\cdot\omega_o)}$&#xD;&#xA;&#xD;&#xA;if we name the angle between $n$ and $m$ $\theta$, we get that the GGX NDF is:$D=\frac{\alpha^2}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}$&#xD;&#xA;&#xD;&#xA;where $m$ is the microfacet normal $m=\frac{\omega_i+\omega_o}{|\omega_i+\omega_o|}$&#xD;&#xA;&#xD;&#xA;$p(\omega_i)$ Is the PDF that can be derived from the GGX NDF $\frac{\alpha^2\cos(\theta)\sin(\theta)}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}$&#xD;&#xA;&#xD;&#xA;When put all together we get:&#xD;&#xA;&#xD;&#xA;$$L_o(p,\omega_o)\approx\frac{1}{N}\sum_{i=1}^{N} \frac{L_i(p,\omega_i)\frac{FG}{4(n\cdot\omega_i)(n\cdot\omega_o)}\frac{\alpha^2}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}(n\cdot\omega_i)}{\frac{\alpha^2\cos(\theta)\sin(\theta)}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}}$$&#xD;&#xA;&#xD;&#xA;After simplifying, we get:&#xD;&#xA;&#xD;&#xA;$$L_o(p,\omega_o)\approx\frac{1}{N}\sum_{i=1}^{N} \frac{L_i(p,\omega_i)FG}{4(n\cdot\omega_o)\cos(\theta)\sin(\theta)}$$&#xD;&#xA;&#xD;&#xA;This procedure seems correct to me but the images produced by my implementation have over exposed reflections at sharp incidence angles or at low roughness values. However, when i remove the $\sin(\theta)$ factor from the denominator it looks plausible (not sure about correctness though).&#xD;&#xA;&#xD;&#xA;[![taken at low resolution with no denoise solution][2]][2]&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E9xzy.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/eZnaa.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16411" PostHistoryTypeId="1" PostId="5933" RevisionGUID="8b7dc224-f45c-49da-8437-ce0f3b854ad1" CreationDate="2017-11-30T00:58:48.183" UserId="5703" Text="fix over exposure in importance sampling in screen space reflections" ContentLicense="CC BY-SA 3.0" />
  <row Id="16412" PostHistoryTypeId="3" PostId="5933" RevisionGUID="8b7dc224-f45c-49da-8437-ce0f3b854ad1" CreationDate="2017-11-30T00:58:48.183" UserId="5703" Text="|rendering|brdf|real-time|reflection|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16413" PostHistoryTypeId="2" PostId="5934" RevisionGUID="f422d3e0-71a5-4cf0-a3b0-18ca97a8b12c" CreationDate="2017-11-30T06:06:47.610" UserId="5846" Text="These days anti-aliasing uses gray scale pixel values on displays with high pixel counts.&#xD;&#xA;&#xD;&#xA;I'd like to take a step back in time and learn what is available for anti-aliasting or at least improving the quality of curved lines and fonts drawn on bindary (on/off) 1-bit displays, such as these low cost OLED displays shown below.&#xD;&#xA;&#xD;&#xA;I don't know if the procedure would be called anti-aliasing, or something else. Ideally an explanation or a link/reference to a mathematical procedure or algorithm would be most helpful, or if something exists in Python, that would be great as well.&#xD;&#xA;&#xD;&#xA;PIL, the Python Image Library is wonderful but I have a hunch it is mostly useful for gray scale or RGB continuous tone images rather than binary 1-bit images.&#xD;&#xA;&#xD;&#xA;See for example the question [Drawing multilingual text using PIL and saving as 1-bit and 8-bit bitmaps][1], where PIL turned this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;into this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;and similar things would happen if I drew circles in PIL and then converted to 1-bit. The antialiasing is designed for continuous tone display, and so the subsequent thresholding just makes a mess.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Example of a 1-bit binary OLED display (128x64 pixels) cropped from [this image][4] from the AdaFruit Page [Monochrome 0.96&quot; 128x64 OLED graphic display, Product ID: 326][5].&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/q/47545359/3904031&#xD;&#xA;  [2]: https://i.stack.imgur.com/otMYr.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ov0i3.png&#xD;&#xA;  [4]: https://cdn-shop.adafruit.com/1200x900/326-18.jpg&#xD;&#xA;  [5]: https://www.adafruit.com/product/326&#xD;&#xA;  [6]: https://i.stack.imgur.com/THcMR.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16414" PostHistoryTypeId="1" PostId="5934" RevisionGUID="f422d3e0-71a5-4cf0-a3b0-18ca97a8b12c" CreationDate="2017-11-30T06:06:47.610" UserId="5846" Text="Algorithms to anti-alias binary 1-bit drawings and fonts" ContentLicense="CC BY-SA 3.0" />
  <row Id="16415" PostHistoryTypeId="3" PostId="5934" RevisionGUID="f422d3e0-71a5-4cf0-a3b0-18ca97a8b12c" CreationDate="2017-11-30T06:06:47.610" UserId="5846" Text="|antialiasing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16416" PostHistoryTypeId="4" PostId="5934" RevisionGUID="627eec4c-efd1-44e2-b87d-98b19bbe5b65" CreationDate="2017-11-30T06:14:45.877" UserId="5846" Comment="edited title" Text="Algorithms to &quot;anti-alias&quot; (or somehow improve) binary 1-bit drawings and fonts" ContentLicense="CC BY-SA 3.0" />
  <row Id="16417" PostHistoryTypeId="6" PostId="5934" RevisionGUID="627eec4c-efd1-44e2-b87d-98b19bbe5b65" CreationDate="2017-11-30T06:14:45.877" UserId="5846" Comment="edited title" Text="|antialiasing|bitmap-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16418" PostHistoryTypeId="5" PostId="5934" RevisionGUID="627eec4c-efd1-44e2-b87d-98b19bbe5b65" CreationDate="2017-11-30T06:14:45.877" UserId="5846" Comment="edited title" Text="These days anti-aliasing uses gray scale pixel values on displays with high pixel counts.&#xD;&#xA;&#xD;&#xA;I'd like to take a step back in time and learn what is available for anti-aliasting or at least improving the quality of curved lines and fonts drawn on bindary (on/off) 1-bit displays, such as these low cost OLED displays shown below.&#xD;&#xA;&#xD;&#xA;I don't know if the procedure would be called anti-aliasing, or something else. Ideally an explanation or a link/reference to a mathematical procedure or algorithm would be most helpful, or if something exists in Python, that would be great as well.&#xD;&#xA;&#xD;&#xA;PIL, the Python Image Library is wonderful but I have a hunch it is mostly useful for gray scale or RGB continuous tone images rather than binary 1-bit images.&#xD;&#xA;&#xD;&#xA;See for example the question [Drawing multilingual text using PIL and saving as 1-bit and 8-bit bitmaps][1], where PIL turned this gray scale image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;into this 1-bit binary image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;and similar things would happen if I drew circles in PIL and then converted to 1-bit. The antialiasing is designed for continuous tone display, and so the subsequent thresholding just makes a mess.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Example of a 1-bit binary OLED display (128x64 pixels) cropped from [this image][4] from the AdaFruit Page [Monochrome 0.96&quot; 128x64 OLED graphic display, Product ID: 326][5].&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/q/47545359/3904031&#xD;&#xA;  [2]: https://i.stack.imgur.com/otMYr.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ov0i3.png&#xD;&#xA;  [4]: https://cdn-shop.adafruit.com/1200x900/326-18.jpg&#xD;&#xA;  [5]: https://www.adafruit.com/product/326&#xD;&#xA;  [6]: https://i.stack.imgur.com/THcMR.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16419" PostHistoryTypeId="2" PostId="5935" RevisionGUID="58f504d1-8205-4c2d-a2cd-238a684a69a9" CreationDate="2017-11-30T06:34:02.233" UserId="3003" Text="In the olden days, for things like fonts, they didn't do antialiasing. They generally hand made bitmap fonts because it generated the clearest, easiest-to-read results.&#xD;&#xA;&#xD;&#xA;That said, you could look into [error diffusion](https://en.wikipedia.org/wiki/Error_diffusion), [halftoning](https://en.wikipedia.org/wiki/Halftone) or other [dithering](https://en.wikipedia.org/wiki/Dither) techniques for changing continuous-tone images into 1-bit images. These are techniques for reducing the bit depth of images." ContentLicense="CC BY-SA 3.0" />
  <row Id="16420" PostHistoryTypeId="50" PostId="4651" RevisionGUID="e2db4114-203a-491a-bed6-4ee7fa3df476" CreationDate="2017-11-30T13:09:47.300" UserId="-1" />
  <row Id="16421" PostHistoryTypeId="50" PostId="5716" RevisionGUID="2e43c821-7d03-4c67-946f-665ac0755f48" CreationDate="2017-11-30T14:09:33.673" UserId="-1" />
  <row Id="16422" PostHistoryTypeId="2" PostId="5936" RevisionGUID="ca88f65c-1d73-4d45-b35a-baba33ec55fe" CreationDate="2017-11-30T16:08:24.900" UserId="6064" Text="This one I am not getting even one bit.&#xD;&#xA;&#xD;&#xA;I started learning directx11 and using the basic dx initialization i tried a experiment by allowing an option to destroy the window and creating it again initializing direct x again(any key press triggers it).&#xD;&#xA;&#xD;&#xA;but i observe during debugging(also by opening task manager) that memory occupied by dx com objects are not getting released,memory keeps adding up as a new window is created.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #include&quot;windowcreation.h&quot;&#xD;&#xA;    &#xD;&#xA;    #pragma comment(lib, &quot;d3d11.lib&quot;)&#xD;&#xA;    #pragma comment(lib, &quot;d3d10.lib&quot;)&#xD;&#xA;    #pragma comment(lib,&quot;D3dcompiler.lib&quot;)&#xD;&#xA;    &#xD;&#xA;    #include&lt;d3d11_1.h&gt;&#xD;&#xA;    #include&lt;d3d10.h&gt;&#xD;&#xA;    #include &lt;D3Dcompiler.h&gt; &#xD;&#xA;    #include&lt;DirectXMath.h&gt;&#xD;&#xA;    #include&lt;DirectXColors.h&gt;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    #include&lt;stdio.h&gt;&#xD;&#xA;    #include &lt;io.h&gt;&#xD;&#xA;    #include &lt;fcntl.h&gt;&#xD;&#xA;    #include&lt;iostream&gt;&#xD;&#xA;    #include&lt;fstream&gt;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool openglinuse = false;&#xD;&#xA;    bool switchRenderDrivers = false;&#xD;&#xA;    bool switchrendercomsumequitmessage = false;&#xD;&#xA;    bool running = true;&#xD;&#xA;    &#xD;&#xA;    //--------------------------------------------DX Globals--------------------------------------------&#xD;&#xA;    DXWindow window(1920, 1080, &quot;dxandgl&quot;);&#xD;&#xA;    &#xD;&#xA;    //dx data&#xD;&#xA;    struct dxData&#xD;&#xA;    {&#xD;&#xA;    	IDXGISwapChain* SwapChain;&#xD;&#xA;    	ID3D11Device* d3d11Device;&#xD;&#xA;    	ID3D11DeviceContext* d3d11DevCon;&#xD;&#xA;    	ID3D11RenderTargetView* renderTargetView;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    dxData* dxessentials;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    std::ofstream fileone(&quot;logs.txt&quot;);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    //---------------------------------------------functions------------------------------------------------&#xD;&#xA;    bool initdirectx(HINSTANCE hinst);&#xD;&#xA;    bool init();&#xD;&#xA;    void render();&#xD;&#xA;    void update(double);&#xD;&#xA;    void destroy();&#xD;&#xA;    int messageloop(HINSTANCE);&#xD;&#xA;    &#xD;&#xA;    bool initdirectx(HINSTANCE hinst)&#xD;&#xA;    {&#xD;&#xA;    	HRESULT hr;&#xD;&#xA;    &#xD;&#xA;    	dxessentials = new dxData();&#xD;&#xA;    &#xD;&#xA;    	//Describe our Buffer&#xD;&#xA;    	DXGI_MODE_DESC bufferDesc;&#xD;&#xA;    &#xD;&#xA;    	ZeroMemory(&amp;bufferDesc, sizeof(DXGI_MODE_DESC));&#xD;&#xA;    &#xD;&#xA;    	bufferDesc.Width = window.getWidth();&#xD;&#xA;    	bufferDesc.Height = window.getHeight();&#xD;&#xA;    	bufferDesc.RefreshRate.Numerator = 60;&#xD;&#xA;    	bufferDesc.RefreshRate.Denominator = 1;&#xD;&#xA;    	bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;    	bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;&#xD;&#xA;    	bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;&#xD;&#xA;    &#xD;&#xA;    	//Describe our SwapChain&#xD;&#xA;    	DXGI_SWAP_CHAIN_DESC swapChainDesc;&#xD;&#xA;    &#xD;&#xA;    	ZeroMemory(&amp;swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));&#xD;&#xA;    &#xD;&#xA;    	swapChainDesc.BufferDesc = bufferDesc;&#xD;&#xA;    	swapChainDesc.SampleDesc.Count = 1;&#xD;&#xA;    	swapChainDesc.SampleDesc.Quality = 0;&#xD;&#xA;    	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;&#xD;&#xA;    	swapChainDesc.BufferCount = 2;&#xD;&#xA;    	swapChainDesc.OutputWindow = window.getWindowHandle();&#xD;&#xA;    	swapChainDesc.Windowed = TRUE;&#xD;&#xA;    	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	//Create our SwapChain&#xD;&#xA;    	hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &amp;swapChainDesc, &amp;(dxessentials-&gt;SwapChain), &amp;(dxessentials-&gt;d3d11Device), NULL, &amp;(dxessentials-&gt;d3d11DevCon));&#xD;&#xA;    &#xD;&#xA;    	//Create our BackBuffer&#xD;&#xA;    	ID3D11Texture2D* BackBuffer;&#xD;&#xA;    	hr = dxessentials-&gt;SwapChain-&gt;GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&amp;BackBuffer);&#xD;&#xA;    &#xD;&#xA;    	//Create our Render Target&#xD;&#xA;    	hr = dxessentials-&gt;d3d11Device-&gt;CreateRenderTargetView(BackBuffer, NULL, &amp;(dxessentials-&gt;renderTargetView));&#xD;&#xA;    	BackBuffer-&gt;Release();&#xD;&#xA;    &#xD;&#xA;    	//Set our Render Target&#xD;&#xA;    	dxessentials-&gt;d3d11DevCon-&gt;OMSetRenderTargets(1, &amp;(dxessentials-&gt;renderTargetView), NULL);&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int messageloop(HINSTANCE hinst)&#xD;&#xA;    {&#xD;&#xA;    	MSG message;&#xD;&#xA;    	ZeroMemory(&amp;message, sizeof(MSG));&#xD;&#xA;    &#xD;&#xA;    	while (true)&#xD;&#xA;    	{&#xD;&#xA;    		if (PeekMessage(&amp;message, NULL, 0, 0, PM_REMOVE))&#xD;&#xA;    		{&#xD;&#xA;    			if (message.message == WM_QUIT)&#xD;&#xA;    				break;&#xD;&#xA;    			TranslateMessage(&amp;message);&#xD;&#xA;    			DispatchMessage(&amp;message);&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			update(0.0);&#xD;&#xA;    			render();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return (int)message.wParam;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    bool init()&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void update(double delta)&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void render()&#xD;&#xA;    {&#xD;&#xA;    	//Clear our backbuffer to the updated color&#xD;&#xA;    	const float bgColor[] = { 0.0,0.0,0.0, 1.0f };&#xD;&#xA;    &#xD;&#xA;    	dxessentials-&gt;d3d11DevCon-&gt;ClearRenderTargetView(dxessentials-&gt;renderTargetView, bgColor);&#xD;&#xA;    &#xD;&#xA;    	dxessentials-&gt;SwapChain-&gt;Present(0, 0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void destroy()&#xD;&#xA;    {&#xD;&#xA;    	dxessentials-&gt;d3d11DevCon-&gt;OMSetRenderTargets(0,NULL, NULL);&#xD;&#xA;    	dxessentials-&gt;d3d11DevCon-&gt;Flush();&#xD;&#xA;    	fileone &lt;&lt; '\n' &lt;&lt; dxessentials-&gt;renderTargetView-&gt;Release();&#xD;&#xA;    	fileone &lt;&lt; '\n' &lt;&lt; dxessentials-&gt;d3d11DevCon-&gt;Release();&#xD;&#xA;    	fileone &lt;&lt; '\n' &lt;&lt; dxessentials-&gt;SwapChain-&gt;Release();&#xD;&#xA;    	fileone &lt;&lt; '\n' &lt;&lt; dxessentials-&gt;d3d11Device-&gt;Release();&#xD;&#xA;    	&#xD;&#xA;    	delete dxessentials;&#xD;&#xA;    	dxessentials = nullptr;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE previnst, LPSTR cmdparams, int showcmd)&#xD;&#xA;    {&#xD;&#xA;    	window.registerWindow(hinst);&#xD;&#xA;    &#xD;&#xA;    	while(running)&#xD;&#xA;    	{&#xD;&#xA;    		//DX code&#xD;&#xA;    		&#xD;&#xA;    			fileone &lt;&lt; &quot;DX \n&quot;;&#xD;&#xA;    			fileone.flush();&#xD;&#xA;    			if (!window.initializeWindow(hinst, showcmd, true, &quot;DX101&quot;))&#xD;&#xA;    			{&#xD;&#xA;    				MessageBox(0, &quot;Window Initialization - Failed&quot;, &quot;Error&quot;, MB_OK);&#xD;&#xA;    				return 0;&#xD;&#xA;    			}&#xD;&#xA;    			&#xD;&#xA;    			if (!initdirectx(hinst))&#xD;&#xA;    			{&#xD;&#xA;    				MessageBox(0, &quot;direct x Initialization - Failed&quot;, &quot;Error&quot;, MB_OK);&#xD;&#xA;    				return 0;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			&#xD;&#xA;    			if (!init())&#xD;&#xA;    			{&#xD;&#xA;    				MessageBox(0, &quot;Scene Initialization - Failed&quot;, &quot;Error&quot;, MB_OK);&#xD;&#xA;    				return 0;&#xD;&#xA;    			}&#xD;&#xA;    			&#xD;&#xA;    			&#xD;&#xA;    		messageloop(hinst);&#xD;&#xA;    		destroy();&#xD;&#xA;    			&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	fileone &lt;&lt; &quot;\nGoing out\n&quot;;&#xD;&#xA;    	fileone.flush();&#xD;&#xA;    	fileone.close();&#xD;&#xA;    &#xD;&#xA;    	return 0;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)&#xD;&#xA;    {&#xD;&#xA;    	switch (msg)    //Check message&#xD;&#xA;    	{&#xD;&#xA;    &#xD;&#xA;    	case WM_KEYDOWN:    //For a key down&#xD;&#xA;    						//if escape key was pressed, display popup box&#xD;&#xA;    		if (wParam == VK_ESCAPE) {&#xD;&#xA;    			if (MessageBox(0, &quot;Are you sure you want to exit?&quot;,&#xD;&#xA;    				&quot;Really?&quot;, MB_YESNO | MB_ICONQUESTION) == IDYES)&#xD;&#xA;    &#xD;&#xA;    				//Release the windows allocated memory  &#xD;&#xA;    				DestroyWindow(hwnd);&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			switchrendercomsumequitmessage = true;&#xD;&#xA;    			DestroyWindow(hwnd);&#xD;&#xA;    		}&#xD;&#xA;    		return 0;&#xD;&#xA;    &#xD;&#xA;    	case WM_SIZE:&#xD;&#xA;    		return 0;&#xD;&#xA;    &#xD;&#xA;    	case WM_NCDESTROY:    //if x button in top right was pressed&#xD;&#xA;    		if (switchrendercomsumequitmessage)&#xD;&#xA;    			switchrendercomsumequitmessage = false;&#xD;&#xA;    		else&#xD;&#xA;    			running = false;&#xD;&#xA;    &#xD;&#xA;    		PostQuitMessage(0);&#xD;&#xA;    		return 0;&#xD;&#xA;    	}&#xD;&#xA;    	//return the message for windows to handle it&#xD;&#xA;    	return DefWindowProc(hwnd,&#xD;&#xA;    		msg,&#xD;&#xA;    		wParam,&#xD;&#xA;    		lParam);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I tried the following-&#xD;&#xA;&#xD;&#xA; 1. tried doing the same with out dx initialization and it was fine no memory leak.So I guess problem is with dx coms.&#xD;&#xA;&#xD;&#xA; 2. I am sure i am releasing the coms as the output log shows zero references for each object i release.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So could any one explain me what is going wrong and how the memory is leaking.&#xD;&#xA;Also a possible fix if any.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16423" PostHistoryTypeId="1" PostId="5936" RevisionGUID="ca88f65c-1d73-4d45-b35a-baba33ec55fe" CreationDate="2017-11-30T16:08:24.900" UserId="6064" Text="How to properly release directx com objects" ContentLicense="CC BY-SA 3.0" />
  <row Id="16424" PostHistoryTypeId="3" PostId="5936" RevisionGUID="ca88f65c-1d73-4d45-b35a-baba33ec55fe" CreationDate="2017-11-30T16:08:24.900" UserId="6064" Text="|c++|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16425" PostHistoryTypeId="2" PostId="5937" RevisionGUID="b72d2668-879c-44af-bffd-15690887ec17" CreationDate="2017-11-30T16:19:44.550" UserId="7644" Text="I have worked with this specific formula for the OVER operator but not with additive blending. I'll use the paper's nomenclature in the following discussion:&#xD;&#xA;&#xD;&#xA;$$ C_f = \frac{\sum_{i=1}^{n}C_i \cdot w(z_i, \alpha_i)}{\sum_{i=1}^{n}\alpha_i \cdot w(z_i, \alpha_i)}(1 - \prod_{i=1}^{n}(1 - \alpha_i)) +  C_0\prod_{i=1}^{n}(1 - \alpha_i) $$&#xD;&#xA;&#xD;&#xA;This is not explicitly stated in the paper, but the term $$C_i$$ is the premultiplied-alpha color (i.e. `color.rgb * color.a`)&#xD;&#xA;&#xD;&#xA;As described in the paper, the term&#xD;&#xA;$$ C_0\prod_{i=1}^{n}(1 - \alpha_i) $$&#xD;&#xA;provides the &quot;revealage&quot; of the background color. If all the transparent surfaces are transparent, the product will be 1 and the background will be fully visible. The rest of the equation provides an approximation of the result of sorting the transparent surfaces by distance and using the OVER operator with pre-multiplied alpha colors.&#xD;&#xA;&#xD;&#xA;However, the equation for additive blending (using `glBlendFunc(GL_SRC_ALPHA, GL_ONE)` and `glBlendEquation(GL_FUNC_ADD)`) without weights is:&#xD;&#xA;$$ C_f = \sum_{i=1}^{n}\alpha_iRGB_i + C_0 $$&#xD;&#xA;&#xD;&#xA;This equation is already order independent! In order to add weights to the transparent surfaces with a normalization step in the end, the equation can then be simplified to:&#xD;&#xA;&#xD;&#xA;$$ C_f = \frac{\sum_{i=1}^{n}C_i \cdot w(z_i, \alpha_i)}{\sum_{i=1}^{n}w(z_i, \alpha_i)} +  C_0 $$&#xD;&#xA;&#xD;&#xA;If you'd rather keep the same equation as before, you can achieve the same result by changing the shader outputs in listing 3 to:&#xD;&#xA;&#xD;&#xA;	gl_FragData[0] = vec4(Ci, 1) * w(zi, ai);&#xD;&#xA;	gl_FragData[1] = vec4(0);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16426" PostHistoryTypeId="2" PostId="5938" RevisionGUID="eff2367c-48b9-4d77-8787-25cea8bbae60" CreationDate="2017-11-30T16:27:08.630" UserId="7644" Text="Have a look at *Improved Alpha-Tested Magnification for Vector Textures and Special Effects* [Gre07] ([pdf][1]). The gist of their method is to store distance field information in the font texture instead of bitmap glyphs. This information is then used to build much higher quality up-scaled versions of the glyphs. They even describe a rendering path without programmable shading that gives ok results.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16427" PostHistoryTypeId="2" PostId="5939" RevisionGUID="8088eabc-040f-408a-8237-467aed5e11fb" CreationDate="2017-11-30T19:45:13.610" UserId="1764" Text="I'm doing some ray tracing on GPU using a fragment shader...&#xD;&#xA;&#xD;&#xA;How can I calculate texture coordinates partial derivatives with respect to screen coordinates so I could perform filtered texture lookup with `textureGrad` GLSL function?&#xD;&#xA;&#xD;&#xA;Do I need to use ray differentials?&#xD;&#xA;&#xD;&#xA;If yes, then how?&#xD;&#xA;&#xD;&#xA;Example explaining derivatives calculation for ray-plane intersection (ray described using origin and direction normal vector, plane using one point laying on a plane and normal vector) would be nice, although pointers for general case would also be appreciated..." ContentLicense="CC BY-SA 3.0" />
  <row Id="16428" PostHistoryTypeId="1" PostId="5939" RevisionGUID="8088eabc-040f-408a-8237-467aed5e11fb" CreationDate="2017-11-30T19:45:13.610" UserId="1764" Text="Ray tracing - partial derivatives for texture lookup" ContentLicense="CC BY-SA 3.0" />
  <row Id="16429" PostHistoryTypeId="3" PostId="5939" RevisionGUID="8088eabc-040f-408a-8237-467aed5e11fb" CreationDate="2017-11-30T19:45:13.610" UserId="1764" Text="|raytracing|texture|glsl|fragment-shader|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16430" PostHistoryTypeId="2" PostId="5940" RevisionGUID="283af9fd-1d6d-45d5-8341-dd1924e29793" CreationDate="2017-11-30T21:01:13.407" UserId="48" Text="PIL's [`Image.convert`](http://pillow.readthedocs.io/en/4.0.x/reference/Image.html#PIL.Image.Image.convert) function performs dithering by default when you convert the image to 1-bit—not simply thresholding. That's what creates the noise along the edges of the shapes; the antialiasing isn't the problem. Unfortunately, at such a low resolution, the dithering does more harm than good.&#xD;&#xA;&#xD;&#xA;I grabbed your original image from your other question and did a straight threshold at 128, and it comes out looking a lot better:&#xD;&#xA;&#xD;&#xA;![threshold, no dithering][1]&#xD;&#xA;&#xD;&#xA;That's probably about as good as you'll be able to do on a low-resolution 1-bit display, absent a bitmap font that's specifically designed for those circumstances.&#xD;&#xA;&#xD;&#xA;In PIL this operation can be implemented using [`Image.point`](http://pillow.readthedocs.io/en/4.0.x/reference/Image.html#PIL.Image.Image.point), as follows:&#xD;&#xA;&#xD;&#xA;    image1Bit = image8Bit.point(lambda x: 0 if x &lt; 128 else 1, mode='1')&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WAlDF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16431" PostHistoryTypeId="2" PostId="5941" RevisionGUID="dc93b766-66f1-40de-a9ec-92148a811b4b" CreationDate="2017-12-01T04:28:05.280" UserId="5846" Text="This is just a supplementary answer based on the [accepted answer][7], using the original 64x128 pixel images instead of the zoomed-in interpolated screen shot.&#xD;&#xA;&#xD;&#xA;`imtype = &quot;RGB&quot;:` [![enter image description here][1]][1] (true RGB)&#xD;&#xA;&#xD;&#xA;`imtype  =  &quot;L&quot;:` [![enter image description here][2]][2] (grayscale 8-bit)&#xD;&#xA;&#xD;&#xA;`imtype  =  &quot;1&quot;:` [![enter image description here][4]][4] (binary 1-bit, threshold = 128)&#xD;&#xA;&#xD;&#xA;`imtype  =  &quot;1&quot;:` [![enter image description here][3]][3] (binary 1-bit, threshold = 80)&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Here are screenshots zoomed-in for those without their glasses:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5] (screenshot of 1-bit, threshold = 128)&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6] (screenshot of 1-bit, threshold = 80)&#xD;&#xA;&#xD;&#xA;    from PIL import Image, ImageDraw, ImageFont&#xD;&#xA;    w_disp   = 128&#xD;&#xA;    h_disp   =  64&#xD;&#xA;    fontsize =  32&#xD;&#xA;    text     =  u&quot;你好!&quot;&#xD;&#xA;&#xD;&#xA;    imageRGB  = Image.new(&quot;RGB&quot;, (w_disp, h_disp))&#xD;&#xA;    draw      = ImageDraw.Draw(imageRGB)&#xD;&#xA;    font      = ImageFont.truetype(&quot;/Library/Fonts/Arial Unicode.ttf&quot;, fontsize)&#xD;&#xA;    w, h      = draw.textsize(text, font=font)&#xD;&#xA;&#xD;&#xA;    draw.text(((w_disp - w)/2, (h_disp - h)/2), text, font=font)&#xD;&#xA;&#xD;&#xA;    imageRGB.save(&quot;NiHao! &quot; + &quot;RGB&quot; + &quot;.bmp&quot;)&#xD;&#xA;&#xD;&#xA;    image8bit = imageRGB.convert(&quot;L&quot;)&#xD;&#xA;&#xD;&#xA;    image8bit.save(&quot;NiHao! &quot; + &quot;L&quot; + &quot;.bmp&quot;)&#xD;&#xA;&#xD;&#xA;    threshold = 80&#xD;&#xA;    image1bit = image8bit.point(lambda x: 0 if x &lt; threshold else 1, mode='1')&#xD;&#xA;    image1bit.save(&quot;NiHao! &quot; + &quot;1&quot; + &quot; threshold = &quot; + str(threshold) + &quot;.bmp&quot;)&#xD;&#xA;&#xD;&#xA;    threshold = 128&#xD;&#xA;    image1bit = image8bit.point(lambda x: 0 if x &lt; threshold else 1, mode='1')&#xD;&#xA;    image1bit.save(&quot;NiHao! &quot; + &quot;1&quot; + &quot; threshold = &quot; + str(threshold) + &quot;.bmp&quot;)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/x5BOT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IT7Fd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/IBTd7.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BYTgZ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/gdNwt.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Ki3eh.png&#xD;&#xA;  [7]: https://computergraphics.stackexchange.com/a/5940/5846" ContentLicense="CC BY-SA 3.0" />
  <row Id="16432" PostHistoryTypeId="50" PostId="4361" RevisionGUID="35c7246b-42bd-4fdb-a5e3-243c2d9b25b4" CreationDate="2017-12-01T11:20:40.893" UserId="-1" />
  <row Id="16433" PostHistoryTypeId="2" PostId="5942" RevisionGUID="f240151e-50dd-4f85-9451-91a41e3f24a6" CreationDate="2017-12-01T13:44:33.067" UserId="1764" Text="Say I'm generating some texture using perlin noise (or simplex noise, or any similar noise). Then I generate mipmaps to obtain minified versions of that texture...&#xD;&#xA;&#xD;&#xA;My question is if it is possible to directly (and quickly) calculate lower LOD version of said noise at given position, without going through steps of generating high frequency noise first, and then generating mipmaps.&#xD;&#xA;&#xD;&#xA;What about sums of noises at different frequencies and amplitudes that are often used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16434" PostHistoryTypeId="1" PostId="5942" RevisionGUID="f240151e-50dd-4f85-9451-91a41e3f24a6" CreationDate="2017-12-01T13:44:33.067" UserId="1764" Text="Is it possible to directly generate mipmap levels of perlin noise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16435" PostHistoryTypeId="3" PostId="5942" RevisionGUID="f240151e-50dd-4f85-9451-91a41e3f24a6" CreationDate="2017-12-01T13:44:33.067" UserId="1764" Text="|noise|mipmap|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16436" PostHistoryTypeId="5" PostId="5904" RevisionGUID="5dff0c14-c1c1-4530-bc68-6f0732102d5c" CreationDate="2017-12-01T16:01:07.417" UserId="2306" Comment="Added screenshot of the shadertoy" Text="When reducing color depth and dithering with a 2 bit noise (with n=]0.5,1.5[ and output=floor(input*(2^bits-1) + n)), the ends of the value range (inputs 0.0 and 1.0) are noisy. It would be desirable to have them to be solid color.&#xD;&#xA;&#xD;&#xA;Example: https://www.shadertoy.com/view/llsfz4&#xD;&#xA;&#xD;&#xA;[![Noise gradient][1]][1]&#xD;&#xA;(above is screenshot of the shadertoy, picturing a gradient and both ends which _should_ be solid white and black respectively, but are noisy instead)&#xD;&#xA;&#xD;&#xA;The problem can be of course solved by just compressing the value range so that the ends get always rounded to single values. This feels bit of a hack though, and I'm wondering if there's a way to implement this &quot;properly&quot;?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xFMrJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16437" PostHistoryTypeId="10" PostId="5919" RevisionGUID="97795f32-178b-4a42-adb1-e37602595d70" CreationDate="2017-12-01T19:58:01.790" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="16438" PostHistoryTypeId="2" PostId="5943" RevisionGUID="3c423eeb-9646-4611-afc8-eab4c340cf21" CreationDate="2017-12-01T21:05:27.180" UserId="2463" Text="I am not sure I can fully answer your question, but I will add some thoughts and maybe we can arrive at an answer together :)&#xD;&#xA;&#xD;&#xA;First, the foundation of the question is a bit unclear to me: Why do you consider it desirable to have clean black/white when every other color has noise? The ideal result after dithering is your original signal with entirely uniform noise. If black and white are different, your noise becomes signal-dependant (which might be fine though, since it happens where colors are clamped anyway).&#xD;&#xA;&#xD;&#xA;That said, there are situations, where having noise in either whites or blacks does pose an issue (I am not aware of usecases that require both black and white to simultaneously be &quot;clean&quot;): When rendering an additively blended particle as a quad with a texture, you do not want noise added in the entire quad, as that would show outside the texture as well. One solution is to offset the noise, so rather than adding [-0.5;1.5[ you add [-2.0;0.0[ (ie subtract 2bits of noise). This is quite an empirical solution, but I am not aware of a more correct approach. Thinking about it, you likely also want to boost your signal to compensate for the lost intensity...&#xD;&#xA;&#xD;&#xA;Somewhat related, Timothy Lottes did a GDC talk on shaping noise to the parts of the spectrum where it is most needed, reducing noise in the bright end of the spectrum: http://32ipi028l5q82yhj72224m8j-wpengine.netdna-ssl.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16439" PostHistoryTypeId="2" PostId="5944" RevisionGUID="4b0e9b2e-e76e-4362-a7e7-126f286c6c1f" CreationDate="2017-12-02T00:24:30.547" UserId="56" Text="Regarding adding multiple frequencies and amplitudes of noise together (aka multiple octaves of noise), the purpose there is to make both high and low frequency content in the resulting noise.&#xD;&#xA;&#xD;&#xA;The purpose of mip mapping is to remove high frequency content from an image so that it won't alias.&#xD;&#xA;&#xD;&#xA;If in your situation it's acceptable to make perlin noise on the fly, you could just include fewer high frequency noise octaves as the texels got smaller in screen space - using the uv coordinate derivatives to figure out how much detail (high frequency content) you need, just like the texture sampler does." ContentLicense="CC BY-SA 3.0" />
  <row Id="16440" PostHistoryTypeId="12" PostId="5944" RevisionGUID="4c1b8232-bad1-4254-873d-c8eba1150a71" CreationDate="2017-12-02T01:03:26.877" UserId="56" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;}]}" />
  <row Id="16441" PostHistoryTypeId="13" PostId="5944" RevisionGUID="031a6d6b-371d-4545-8024-108f06c51b76" CreationDate="2017-12-02T01:03:36.893" UserId="56" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:56,&quot;DisplayName&quot;:&quot;Alan Wolfe&quot;}]}" />
  <row Id="16442" PostHistoryTypeId="5" PostId="5944" RevisionGUID="2fe3bd4e-0e8e-4a27-ae92-a8b6ff97653a" CreationDate="2017-12-02T01:12:12.893" UserId="56" Comment="complete re-write that addresses the whole question, and does so in a better more detailed way." Text="I would say yes with a small asterisk.&#xD;&#xA;&#xD;&#xA;When generating a perlin noise texture, using multiple of octaves of noise like you are talking about, the point of adding higher octaves (higher frequency lower amplitude) is to add high frequency details to the noise.&#xD;&#xA;&#xD;&#xA;When making mipmaps of a texture, the point is to remove high frequency content that would cause aliasing at the resolution of that mip map level.&#xD;&#xA;&#xD;&#xA;So, when making a specific mip level of a multiple octave perlin noise texture, you could find out which frequency would cause aliasing, and just use all the octaves up to (but not including) that point.&#xD;&#xA;&#xD;&#xA;The result would be that you would have reasonable mips.&#xD;&#xA;&#xD;&#xA;But, there are some reasons for that small asterisk:&#xD;&#xA;&#xD;&#xA; 1. The result you get would not be the same as if you mipped the image that has the highest frequency content.  This might not necessarily be a bad thing, because the usual way to make mips causes some bluring (a blur is a low pass filter) so you wouldn't have the bluring that comes with mips.  However, it's possible that a higher octave happens to add some lower frequency content than you'd expect.  Your lower mips, which could handle this frequency, would have that data missing unfortunately.&#xD;&#xA; 2. It might be that your octaves don't perfectly line up with the frequencies that your various mip levels can handle.  For instance, if an octave is just barely higher than nyquist frequency, you are going to miss out on some of the frequency components that the octave gave you.&#xD;&#xA;&#xD;&#xA;Because of these two points, it might be more correct to process all octaves for each mip level, but to low pass filter the data for the octaves that are above nyquist.&#xD;&#xA;&#xD;&#xA;That would be a lot more expensive than just omiting octaves at a cutoff point though (:" ContentLicense="CC BY-SA 3.0" />
  <row Id="16443" PostHistoryTypeId="2" PostId="5945" RevisionGUID="66322c2f-dda6-4dea-9d5d-3b89ad5a6596" CreationDate="2017-12-02T20:13:24.450" UserId="7814" Text="Sorry If this is not the place to ask such question. I am not sure.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Whenever I make semantic or syntax errors in OpenGL, either I get a black screen or the program crashes. I looked up on internet on how to do error handling in OpenGL and in the documentations I found `glGetError()`. To my understanding, `glGetError()` will return one or more error code(s) if I call it after calling a &quot;normal&quot; OpenGL function, provided I have made some error. Also I have to call it in while loop to get all the errors. &#xD;&#xA;&#xD;&#xA;I have multiple problems with this. One I can't find the line number on which the error has occurred, second it doesn't tell me properly why the error occurred (not a big problem though) and lastly I have to include a while loop after each OpenGL function call. &#xD;&#xA;&#xD;&#xA;Here's an example, &#xD;&#xA;&#xD;&#xA;    unsigned int buffer = 0;&#xD;&#xA;	glGenBuffers(1, &amp;buffer);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW); &#xD;&#xA;&#xD;&#xA;Now if I write it with `glGetError()`, it would look something like&#xD;&#xA;&#xD;&#xA;	unsigned int err = 0;&#xD;&#xA;	glGenBuffers(1, &amp;buffer);&#xD;&#xA;	while( !(err = glGetError()) ){&#xD;&#xA;		std::cout &lt;&lt; err;&#xD;&#xA;	}  &#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;	while( !(err = glGetError()) ){&#xD;&#xA;		std::cout &lt;&lt; err;&#xD;&#xA;	}  &#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW); &#xD;&#xA;    while( !(err = glGetError()) ){&#xD;&#xA;		std::cout &lt;&lt; err;&#xD;&#xA;	}  &#xD;&#xA;&#xD;&#xA;Surely this isn't the way to go, right ? The source code looks so ugly.  &#xD;&#xA; &#xD;&#xA;How do I do proper error handling with OpenGL ?&#xD;&#xA;&#xD;&#xA;My graphics card supports OpenGL 4.4 and I am using C++ . " ContentLicense="CC BY-SA 3.0" />
  <row Id="16444" PostHistoryTypeId="1" PostId="5945" RevisionGUID="66322c2f-dda6-4dea-9d5d-3b89ad5a6596" CreationDate="2017-12-02T20:13:24.450" UserId="7814" Text="How to do error handling with OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16445" PostHistoryTypeId="3" PostId="5945" RevisionGUID="66322c2f-dda6-4dea-9d5d-3b89ad5a6596" CreationDate="2017-12-02T20:13:24.450" UserId="7814" Text="|opengl|debugging|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16446" PostHistoryTypeId="2" PostId="5946" RevisionGUID="09c8c010-f3b0-4045-957b-79a00e632223" CreationDate="2017-12-02T23:17:43.107" UserId="48" Text="Yes, there is a better way!  OpenGL 4.3 and later support the [`glDebugMessageCallback`](http://docs.gl/gl4/glDebugMessageCallback) API, which allows you to specify a function in your app that GL will call to issue a warning or error. In this function you can do whatever you like, such as setting a breakpoint in the debugger, or printing the error to a log file. This way you only need to setup the callback during initialization—much nicer than putting `glGetError` calls everywhere.&#xD;&#xA;&#xD;&#xA;To turn on this functionality your GL context also needs to be a &quot;debug context&quot;, which is specified by setting a flag when you create the context. The details will depend on which OS / windowing system / framework you're using. A debug context might be slower (on the CPU) than a regular context, but that's the price you pay for more detailed debugging info, kinda like turning optimizations off in the compiler.&#xD;&#xA;&#xD;&#xA;See also [this wiki page](https://www.khronos.org/opengl/wiki/Debug_Output) for more information. There's a bunch of other debugging-related functionality. For instance you can give human-readable names to textures, buffers, framebuffers, etc using [`glObjectLabel`](http://docs.gl/gl4/glObjectLabel), which will then (I assume) be used in error messages. There are also APIs for turning off certain messages or categories of messages, in case you get spammed by warnings that you don't care about or some such." ContentLicense="CC BY-SA 3.0" />
  <row Id="16447" PostHistoryTypeId="2" PostId="5947" RevisionGUID="3415c500-99a3-4669-ae62-1dcd4cbd56af" CreationDate="2017-12-03T05:02:15.720" UserId="7817" Text="What does it mean and why is it not well suited for describing colors by human? &#xD;&#xA;&#xD;&#xA;Is CMYK nonlinear also?&#xD;&#xA;&#xD;&#xA;Much appreciated" ContentLicense="CC BY-SA 3.0" />
  <row Id="16448" PostHistoryTypeId="1" PostId="5947" RevisionGUID="3415c500-99a3-4669-ae62-1dcd4cbd56af" CreationDate="2017-12-03T05:02:15.720" UserId="7817" Text="RGB nonlinear, What does it mean" ContentLicense="CC BY-SA 3.0" />
  <row Id="16449" PostHistoryTypeId="3" PostId="5947" RevisionGUID="3415c500-99a3-4669-ae62-1dcd4cbd56af" CreationDate="2017-12-03T05:02:15.720" UserId="7817" Text="|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16450" PostHistoryTypeId="2" PostId="5948" RevisionGUID="3cf500b3-bf50-48c2-b645-2033ded600d2" CreationDate="2017-12-03T07:30:51.530" UserId="3003" Text="In general, non-linear would mean that an increase in a value does not produce a similar increase in perception. (Or in some other non-biological system, an increase in input does not produce a proportion increase or decrease in output.)&#xD;&#xA;&#xD;&#xA;Mathematically, any function that relates one value to another that doesn't follow a straight line is non-linear. So x raised to the power y is a non-linear function.&#xD;&#xA;&#xD;&#xA;This matters for colors because our brains don't perceive light in a linear fashion. If you double the number of photons reaching the retina, the brain doesn't interpret it as twice as bright. We have better perception in the mids and highlights than in the shadows. That is, we can distinguish bright values that are close together more easily than we can distinguish dark values that are equally close together. &#xD;&#xA;&#xD;&#xA;When encoding light values in a computer, we need to choose how precisely to record them without losing too much quality. If we use too many bits, then our hardware becomes more expensive. If we use too few then the image looks bad. Until the last ~10-15 years or so, it was generally considered too expensive to store more than 8 bits per red, green, and blue channel. The problem is that if you encode the light values linearly (where 2x causes your monitor to produce twice as many photons as 1x does), then images stored with only 8 bits per channel will have very obvious banding in bright areas of continuous color.&#xD;&#xA;&#xD;&#xA;But remember above that humans have a harder time seeing in the shadows than in the bright areas? That means that we can use 8 bits per channel, but not use them linearly. If we instead take each 8-bit color channel value and treat it as a value between 0 and 1, if we raise that value to a power then we have more values to use to represent mids and highlights, and fewer to represent shadows. This is called gamma-correction or gamma-encoding. We just have to remember to do the reverse (raise the value to the 1 / x power) when we want to output the values on a display.&#xD;&#xA;&#xD;&#xA;So if you're dealing with non-linear RGB, it is probably gamma encoded. sRGB is a popular encoding that uses a power of ~2.2. (In truth, it's [a little more complicated than just raising it to a power](https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_.28.22gamma.22.29).) So when someone tells you that RGB is non-linear, that's usually what they are referring to. It is entirely possible to store images in linear RGB, so long as you use more than 8 bits per color channel. There are also formats that use a logarithmic encodings, though they are less common outside of film production.&#xD;&#xA;&#xD;&#xA;CMYK is more complicated than RGB. Rather than having only a single thing that is outputting the color (the monitor), with CMYK, you have to deal with the medium you're printing on as well as the inks you are printing with. In a typical scenario, you print onto a white surface (such as a piece of paper). Ideally all visible frequencies of light should be reflected off of the paper and into your eyes or camera. When you add ink, the ink absorbs some frequencies of light and reflects others. (And I believe some passes through the ink, hits the paper and is reflected back as well.) The manner in which an ink reflects light is non-linear. Doubling the amount of ink may not cut in half the number of photons reflected back. So CMYK is also non-linear." ContentLicense="CC BY-SA 3.0" />
  <row Id="16451" PostHistoryTypeId="2" PostId="5949" RevisionGUID="98c6a9f5-1fd2-42f0-90a9-1327e3fcd1f3" CreationDate="2017-12-03T07:43:27.347" UserId="3003" Text="If you can't go to OpenGL 4.3 (or your implementation doesn't support `glDebugMessageCallback`s), you can simplify your code in a number of ways.&#xD;&#xA;&#xD;&#xA;The first is to move the calls to `glGetError()` into a function like this:&#xD;&#xA;&#xD;&#xA;    void checkGLError()&#xD;&#xA;    {&#xD;&#xA;        GLenum err;&#xD;&#xA;        while( !(err = glGetError()) ){&#xD;&#xA;            std::cout &lt;&lt; err;&#xD;&#xA;        }  &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;That reduces your code to:&#xD;&#xA;&#xD;&#xA;    unsigned int buffer = 0;&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    checkGLError();&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;    checkGLError();&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW); &#xD;&#xA;    checkGLError();&#xD;&#xA;&#xD;&#xA;However, calling `glGetError()` frequently can hurt performance, so it's best to conditionalize it so it only gets called in debug builds by doing something like this:&#xD;&#xA;&#xD;&#xA;    #if DEBUG&#xD;&#xA;    #define checkGLError() debugCheckGLError()&#xD;&#xA;    #else&#xD;&#xA;    #define checkGLError()&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;Then name the actual function `debugCheckGLError()`. It will get called in debug builds but not release builds." ContentLicense="CC BY-SA 3.0" />
  <row Id="16452" PostHistoryTypeId="50" PostId="5816" RevisionGUID="9eaee226-dd44-41ef-9f7f-1e098d9b65a9" CreationDate="2017-12-03T10:51:52.370" UserId="-1" />
  <row Id="16453" PostHistoryTypeId="50" PostId="5676" RevisionGUID="d6742f82-5b5e-4cd6-a907-467451f1bfa9" CreationDate="2017-12-03T15:03:01.487" UserId="-1" />
  <row Id="16454" PostHistoryTypeId="5" PostId="5945" RevisionGUID="09117a07-96c6-4158-893b-7f3f8fc84b44" CreationDate="2017-12-03T15:33:45.430" UserId="2654" Comment="deleted 89 characters in body" Text="Whenever I make semantic or syntax errors in OpenGL, either I get a black screen or the program crashes. I looked up on internet on how to do error handling in OpenGL and in the documentations I found `glGetError()`. To my understanding, `glGetError()` will return one or more error code(s) if I call it after calling a &quot;normal&quot; OpenGL function, provided I have made some error. Also I have to call it in while loop to get all the errors. &#xD;&#xA;&#xD;&#xA;I have multiple problems with this. One I can't find the line number on which the error has occurred, second it doesn't tell me properly why the error occurred (not a big problem though) and lastly I have to include a while loop after each OpenGL function call. &#xD;&#xA;&#xD;&#xA;Here's an example, &#xD;&#xA;&#xD;&#xA;    unsigned int buffer = 0;&#xD;&#xA;	glGenBuffers(1, &amp;buffer);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW); &#xD;&#xA;&#xD;&#xA;Now if I write it with `glGetError()`, it would look something like&#xD;&#xA;&#xD;&#xA;	unsigned int err = 0;&#xD;&#xA;	glGenBuffers(1, &amp;buffer);&#xD;&#xA;	while( !(err = glGetError()) ){&#xD;&#xA;		std::cout &lt;&lt; err;&#xD;&#xA;	}  &#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;	while( !(err = glGetError()) ){&#xD;&#xA;		std::cout &lt;&lt; err;&#xD;&#xA;	}  &#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW); &#xD;&#xA;    while( !(err = glGetError()) ){&#xD;&#xA;		std::cout &lt;&lt; err;&#xD;&#xA;	}  &#xD;&#xA;&#xD;&#xA;Surely this isn't the way to go, right ? The source code looks so ugly.  &#xD;&#xA; &#xD;&#xA;How do I do proper error handling with OpenGL ?&#xD;&#xA;&#xD;&#xA;My graphics card supports OpenGL 4.4 and I am using C++ . " ContentLicense="CC BY-SA 3.0" />
  <row Id="16455" PostHistoryTypeId="2" PostId="5950" RevisionGUID="bcad8ed0-fc5c-4bfb-87f3-23f496c8709a" CreationDate="2017-12-03T15:39:50.970" UserId="2654" Text="While [Debug Output][1] is good, and manual `glGetError` usage is adequate, it's often better to employ a more [dedicated tool for finding exactly where OpenGL errors came from][2].&#xD;&#xA;&#xD;&#xA;[RenderDoc][3] is probably the most up-to-date tool for this process, but there are quite a few in various states of functionality. These tools can also give you a detailed log of every OpenGL call you've made.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Debug_Output&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Debugging_Tools&#xD;&#xA;  [3]: https://renderdoc.org/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16456" PostHistoryTypeId="2" PostId="5951" RevisionGUID="7a30d643-4b97-463c-b500-a1ce65b28d48" CreationDate="2017-12-03T21:31:56.190" UserId="523" Text="I'm trying to get an algorithm for intersecting a &quot;tube&quot; (a 3D cubic Bézier curve extruded by a possibly-changing radius) with the following required properties:&#xD;&#xA;&#xD;&#xA;- Computes intersections of ray and a 3D cubic Bézier curve.  Must not become confused, as some numerical algorithms do, by secondary rays, which start from the surface of the curve (i.e. at a zero).&#xD;&#xA;- Must support a varying radius along the curve (a linear function is fine).  The radius may be zero in at-most one point.&#xD;&#xA;- Hit point accuracy should be a function of floating-point precision or solver iterations.  I.e., the geometry must be correct, fully volumetric.&#xD;&#xA;- Some reasonable way of handling endpoints.  I'd prefer spherical caps, but flat ones would be okay too.  A choice would be nice.&#xD;&#xA;&#xD;&#xA;I don't need the fastest-possible algorithm.  The easiest reasonable algorithm is what I'm looking for.&#xD;&#xA;&#xD;&#xA;**Can someone help me find an ray + 3D-cubic-Bézier intersection algorithm satisfying the above?  A paper link, a description, help pinning down references, etc.**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;I've had great difficulty with a literature search on this.  Here are some of the (few) papers I found:&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;- &lt;sup&gt;&quot;[Ray Tracing for Curves Primitive](http://wscg.zcu.cz/wscg2002/Papers_2002/A83.pdf)&quot;.  I implemented this, but the hit depth seems to be incorrect.  I suspect this is because it assumes (erroneously) that the cross section of the curve will be circular, even if at an angle.&lt;/sup&gt;&#xD;&#xA;- &lt;sup&gt;&quot;[Exploiting Budan-Fourier and Vincent's Theorems for Ray Tracing 3D Bézier Curves](http://research.nvidia.com/sites/default/files/pubs/2017-07_Exploiting-Budan-Fourier-and//HPG2017-Budan-Fourier.pdf)&quot;.  Seems over-complex, and doesn't seem to support varying radius.  Looks like it has the same bad assumption, and code isn't available.&lt;/sup&gt;&#xD;&#xA;- &lt;sup&gt;&quot;[High-Quality Curve Rendering using Line Sampled Visibility](http://fileadmin.cs.lth.se/graphics/research/papers/2012/hairy/)&quot;.  Quadratic curves only, rasterizer-based, unclear if meets other criteria.&lt;/sup&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16457" PostHistoryTypeId="1" PostId="5951" RevisionGUID="7a30d643-4b97-463c-b500-a1ce65b28d48" CreationDate="2017-12-03T21:31:56.190" UserId="523" Text="Simple Intersection Algorithm for Ray and 3D Bézier Curves of Varying Thickness" ContentLicense="CC BY-SA 3.0" />
  <row Id="16458" PostHistoryTypeId="3" PostId="5951" RevisionGUID="7a30d643-4b97-463c-b500-a1ce65b28d48" CreationDate="2017-12-03T21:31:56.190" UserId="523" Text="|raytracing|algorithm|bezier-curve|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16459" PostHistoryTypeId="2" PostId="5952" RevisionGUID="b8094cda-81de-42c9-8d36-eb3e55653ffe" CreationDate="2017-12-03T21:47:03.927" UserId="2463" Text="TL;DR: 2*1LSB triangular-pdf dithering breaks in edgecases at 0 and 1 due to clamping. A solution is to lerp to a 1bit uniform dither in those edgecases.&#xD;&#xA;&#xD;&#xA;I am adding a second answer, seeing as this turned out a bit more complicated than I originally thought. It appears this issue has been a &quot;TODO: needs clamping?&quot; in my code since I switched from normalized to triangular dithering... in 2012. Feels good to finally look at it :) Full code for solution / images used throughout the post: https://www.shadertoy.com/view/llXfzS&#xD;&#xA;&#xD;&#xA;First of all, here is the problem we are looking at, when quantizing a signal to 3bits with 2*1LSB triangular-pdf dithering:&#xD;&#xA;&#xD;&#xA; [![outputs][1]][1]&#xD;&#xA; - essentially what hotmultimedia showed.&#xD;&#xA;&#xD;&#xA;Increasing contrast, the effect described in the question becomes apparent: The output does not average to black/white in the edgecases (and actually extends well beyond 0/1 before doing so).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Looking at a graph provides a bit more insight:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;(grey lines mark 0/1, also in grey is the signal we are trying to output, yellow-line is average of dithered/quantized output, red is the error (signal-average)).&#xD;&#xA;&#xD;&#xA;Interestingly, not only is the average output not 0/1 at the limits, it is also not linear (likely due to the triangular pdf of the noise). Looking at the lower end, it makes intuitive sense why the output diverges: As the dithered signal starts to include negative values, the clamping-on-output changes the value of the lower dithered parts of the output (ie the negative values), thereby increasing the value of the average. An illustration appears to be in order (average still in yellow):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Now, if we just use a 1LSB normalized dither, there are no issues at the edges-cases at all, but then of course we lose the nice properties of triangular dithering (see e.g. [this presentation][5]).&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;A (pragmatic, empirical) solution (hack) then, is to revert to [-0.5;0.5[ uniform dithering for the edgecase:&#xD;&#xA;&#xD;&#xA;    float dithertri = (rnd.x + rnd.y - 1.0); //note: symmetric, triangular dither, [-1;1[&#xD;&#xA;    float dithernorm = rnd.x - 0.5; //note: symmetric, uniform dither [-0.5;0.5[&#xD;&#xA;&#xD;&#xA;    float sizt_lo = clamp( v/(0.5/7.0), 0.0, 1.0 );&#xD;&#xA;    float sizt_hi = 1.0 - clamp( (v-6.5/7.0)/(1.0-6.5/7.0), 0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    dither = lerp( dithernorm, dithertri, min(sizt_lo, sizt_hi) );&#xD;&#xA;&#xD;&#xA;Which fixes the edgecases while keeping the triangular dithering intact for the remaining range:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;So to not answer your question: I do not know if there is a more correct mathematically solid solution, and am equally keen to know what Masters of Past have done :) Until then, at least we have this horrific hack to keep our code functioning.&#xD;&#xA;&#xD;&#xA;References&#xD;&#xA;&#xD;&#xA; - https://www.shadertoy.com/view/llXfzS&#xD;&#xA; - http://loopit.dk/rendering_inside.pdf&#xD;&#xA; - http://loopit.dk/banding_in_games.pdf&#xD;&#xA; - http://32ipi028l5q82yhj72224m8j-wpengine.netdna-ssl.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNHuJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cdgag.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Z1Q15.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/IntiM.png&#xD;&#xA;  [5]: http://loopit.dk/rendering_inside.pdf&#xD;&#xA;  [6]: https://i.stack.imgur.com/tHGbs.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/MYr1f.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16460" PostHistoryTypeId="2" PostId="5953" RevisionGUID="960aa244-8409-4799-b651-c44b42d30eee" CreationDate="2017-12-03T22:06:38.167" UserId="56" Text="You say that you don't need the fastest possible algorithm, so instead of solving it analytically, you might try solving it numerically, which in this case could mean ray marching.&#xA;&#xA;How you could do this is take steps down the ray and test if the point is inside or outside of this bezier tube.&#xA;&#xA;You would iterate down the ray until you either find an intersection or leave the bounding box of this shape (or maybe when you take a maximum number of steps, or some other fail case).&#xA;&#xA;The challenge then only becomes &quot;how can I tell if a point is inside or outside of the shape?&quot; which is a lot simpler.  If you had constant thickness you would just find the closest point on the bezier to your point and do a distance comparison.&#xA;&#xA;Some details you might be interested in:&#xA; &#xA; &#xA; - taking smaller steps, and more of them, will give you more accurate results, but will be more expensive computationally. That makes this algorithm tuneable for quality vs speed.&#xA; &#xA; &#xA; - if the step size is too large or the tube is too thin, you may completely miss the tube when there is really a hit.&#xA; &#xA; &#xA; - when/if you do find a hit, you are finding the first point inside the shape. The real answer is somewhere between the last sample and the current sample.  You could refine the hit location with a binary search or some other method if you wanted to.&#xA; &#xA; &#xA; - you can likely increase the step size as you move farther from the camera. Smaller details are harder to see at greater distances.&#xA;&#xA; &#xA; - you might be able to calculate or approximate the gradient of your point vs bezier tube function as you ray march. If so, this gradient can be used to give you a lower bound on the distance from your point to the bezier tube, which would let you take larger steps through empty space.&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16461" PostHistoryTypeId="5" PostId="5953" RevisionGUID="6a6146ad-1f68-4071-a1e9-b441f934d07e" CreationDate="2017-12-03T22:20:36.440" UserId="56" Comment="added 806 characters in body" Text="You say that you don't need the fastest possible algorithm, so instead of solving it analytically, you might try solving it numerically, which in this case could mean ray marching.&#xA;&#xA;How you could do this is take steps down the ray and test if the point is inside or outside of this bezier tube.&#xA;&#xA;You would iterate down the ray until you either find an intersection or leave the bounding box of this shape (or maybe when you take a maximum number of steps, or some other fail case).&#xA;&#xA;The challenge then only becomes &quot;how can I tell if a point is inside or outside of the shape?&quot; which is a lot simpler.  If you had constant thickness you would just find the closest point on the bezier to your point and do a distance comparison.&#xA;&#xA;Some details you might be interested in:&#xA; &#xA; &#xA; - taking smaller steps, and more of them, will give you more accurate results, but will be more expensive computationally. That makes this algorithm tuneable for quality vs speed.&#xA; &#xA; &#xA; - if the step size is too large or the tube is too thin, you may completely miss the tube when there is really a hit.&#xA; &#xA; &#xA; - when/if you do find a hit, you are finding the first point inside the shape. The real answer is somewhere between the last sample and the current sample.  You could refine the hit location with a binary search or some other method if you wanted to.&#xA; &#xA; &#xA; - you can likely increase the step size as you move farther from the camera. Smaller details are harder to see at greater distances.&#xA;&#xA; &#xA; - you might be able to calculate or approximate the gradient of your point vs bezier tube function as you ray march. If so, this gradient can be used to give you a lower bound on the distance from your point to the bezier tube, which would let you take larger steps through empty space.&#xA;&#xA;&#xA;Regarding the &quot;secondary ray&quot; issue you mention like for shadow rays or reflection rays that comes up with both analytical and numerical solutions.  Getting a (probably) less precise answer than a numerical solution does make the problem worse, but there should be ways to get around it.&#xA;&#xA;For instance, after you detect a hit, you could find a point on the surface near the hit even if it isn't where the hit was (like, push the hit point to the surface, in whatever direction is easiest to compute), add an epsilon (needed for analytical solutions anyways) and spawn secondary rays from there.&#xA;&#xA;Another way could be to have every object have an ID and when ray marching / tracing, don't count intersections with the same ID as what you just hit.  This only really works for opaque convex objects though." ContentLicense="CC BY-SA 3.0" />
  <row Id="16462" PostHistoryTypeId="5" PostId="5953" RevisionGUID="4ab6d8ff-0a89-4c74-86a1-a461e24c72e2" CreationDate="2017-12-03T22:35:21.037" UserId="56" Comment="added 14 characters in body" Text="You say that you don't need the fastest possible algorithm, so instead of solving it analytically, you might try considering the numeric alternatives, which in this case could mean ray marching.&#xA;&#xA;How you could do this is take steps down the ray and test if the point is inside or outside of this bezier tube.&#xA;&#xA;You would iterate down the ray until you either find an intersection or leave the bounding box of this shape (or maybe when you take a maximum number of steps, or some other fail case).&#xA;&#xA;The challenge then only becomes &quot;how can I tell if a point is inside or outside of the shape?&quot; which is a lot simpler.  If you had constant thickness you would just find the closest point on the bezier to your point and do a distance comparison.&#xA;&#xA;Some details you might be interested in:&#xA; &#xA; &#xA; - taking smaller steps, and more of them, will give you more accurate results, but will be more expensive computationally. That makes this algorithm tuneable for quality vs speed.&#xA; &#xA; &#xA; - if the step size is too large or the tube is too thin, you may completely miss the tube when there is really a hit.&#xA; &#xA; &#xA; - when/if you do find a hit, you are finding the first point inside the shape. The real answer is somewhere between the last sample and the current sample.  You could refine the hit location with a binary search or some other method if you wanted to.&#xA; &#xA; &#xA; - you can likely increase the step size as you move farther from the camera. Smaller details are harder to see at greater distances.&#xA;&#xA; &#xA; - you might be able to calculate or approximate the gradient of your point vs bezier tube function as you ray march. If so, this gradient can be used to give you a lower bound on the distance from your point to the bezier tube, which would let you take larger steps through empty space.&#xA;&#xA;&#xA;Regarding the &quot;secondary ray&quot; issue you mention like for shadow rays or reflection rays that comes up with both analytical and numerical solutions.  Getting a (probably) less precise answer than a numerical solution does make the problem worse, but there should be ways to get around it.&#xA;&#xA;For instance, after you detect a hit, you could find a point on the surface near the hit even if it isn't where the hit was (like, push the hit point to the surface, in whatever direction is easiest to compute), add an epsilon (needed for analytical solutions anyways) and spawn secondary rays from there.&#xA;&#xA;Another way could be to have every object have an ID and when ray marching / tracing, don't count intersections with the same ID as what you just hit.  This only really works for opaque convex objects though." ContentLicense="CC BY-SA 3.0" />
  <row Id="16464" PostHistoryTypeId="5" PostId="5952" RevisionGUID="804005f8-a135-4d3c-a423-2b085f428e22" CreationDate="2017-12-04T08:04:54.463" UserId="2463" Comment="added 377 characters in body" Text="TL;DR: 2*1LSB triangular-pdf dithering breaks in edgecases at 0 and 1 due to clamping. A solution is to lerp to a 1bit uniform dither in those edgecases.&#xD;&#xA;&#xD;&#xA;I am adding a second answer, seeing as this turned out a bit more complicated than I originally thought. It appears this issue has been a &quot;TODO: needs clamping?&quot; in my code since I switched from normalized to triangular dithering... in 2012. Feels good to finally look at it :) Full code for solution / images used throughout the post: https://www.shadertoy.com/view/llXfzS&#xD;&#xA;&#xD;&#xA;First of all, here is the problem we are looking at, when quantizing a signal to 3bits with 2*1LSB triangular-pdf dithering:&#xD;&#xA;&#xD;&#xA; [![outputs][1]][1]&#xD;&#xA; - essentially what hotmultimedia showed.&#xD;&#xA;&#xD;&#xA;Increasing contrast, the effect described in the question becomes apparent: The output does not average to black/white in the edgecases (and actually extends well beyond 0/1 before doing so).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Looking at a graph provides a bit more insight:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;(grey lines mark 0/1, also in grey is the signal we are trying to output, yellow-line is average of dithered/quantized output, red is the error (signal-average)).&#xD;&#xA;&#xD;&#xA;Interestingly, not only is the average output not 0/1 at the limits, it is also not linear (likely due to the triangular pdf of the noise). Looking at the lower end, it makes intuitive sense why the output diverges: As the dithered signal starts to include negative values, the clamping-on-output changes the value of the lower dithered parts of the output (ie the negative values), thereby increasing the value of the average. An illustration appears to be in order (uniform, symmetric 2LSB dither, average still in yellow):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Now, if we just use a 1LSB normalized dither, there are no issues at the edges-cases at all, but then of course we lose the nice properties of triangular dithering (see e.g. [this presentation][5]).&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;A (pragmatic, empirical) solution (hack) then, is to revert to [-0.5;0.5[ uniform dithering for the edgecase:&#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: c --&gt;&#xD;&#xA;&#xD;&#xA;    float dithertri = (rnd.x + rnd.y - 1.0); //note: symmetric, triangular dither, [-1;1[&#xD;&#xA;    float dithernorm = rnd.x - 0.5; //note: symmetric, uniform dither [-0.5;0.5[&#xD;&#xA;&#xD;&#xA;    float sizt_lo = clamp( v/(0.5/7.0), 0.0, 1.0 );&#xD;&#xA;    float sizt_hi = 1.0 - clamp( (v-6.5/7.0)/(1.0-6.5/7.0), 0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    dither = lerp( dithernorm, dithertri, min(sizt_lo, sizt_hi) );&#xD;&#xA;&#xD;&#xA;Which fixes the edgecases while keeping the triangular dithering intact for the remaining range:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;So to not answer your question: I do not know if there is a more mathematically solid solution, and am equally keen to know what Masters of Past have done :) Until then, at least we have this horrific hack to keep our code functioning.&#xD;&#xA;&#xD;&#xA;EDIT  &#xD;&#xA;I should probably cover the workaround-suggestion given in The Question, on simply compressing the signal. Because the average is not linear in the edgecases, simply compressing the input-signal does not produce a perfect result - though it does fix the endpoints:&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;References&#xD;&#xA;&#xD;&#xA; - https://www.shadertoy.com/view/llXfzS&#xD;&#xA; - http://loopit.dk/rendering_inside.pdf&#xD;&#xA; - http://loopit.dk/banding_in_games.pdf&#xD;&#xA; - http://32ipi028l5q82yhj72224m8j-wpengine.netdna-ssl.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNHuJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cdgag.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Z1Q15.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/IntiM.png&#xD;&#xA;  [5]: http://loopit.dk/rendering_inside.pdf&#xD;&#xA;  [6]: https://i.stack.imgur.com/tHGbs.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/MYr1f.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/DEVJo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16465" PostHistoryTypeId="5" PostId="5952" RevisionGUID="cded10d3-a170-40ab-b272-4594b9a5ddd6" CreationDate="2017-12-04T08:16:35.227" UserId="2463" Comment="added 5 characters in body" Text="TL;DR: 2*1LSB triangular-pdf dithering breaks in edgecases at 0 and 1 due to clamping. A solution is to lerp to a 1bit uniform dither in those edgecases.&#xD;&#xA;&#xD;&#xA;I am adding a second answer, seeing as this turned out a bit more complicated than I originally thought. It appears this issue has been a &quot;TODO: needs clamping?&quot; in my code since I switched from normalized to triangular dithering... in 2012. Feels good to finally look at it :) Full code for solution / images used throughout the post: https://www.shadertoy.com/view/llXfzS&#xD;&#xA;&#xD;&#xA;First of all, here is the problem we are looking at, when quantizing a signal to 3bits with 2*1LSB triangular-pdf dithering:&#xD;&#xA;&#xD;&#xA; [![outputs][1]][1]&#xD;&#xA; - essentially what hotmultimedia showed.&#xD;&#xA;&#xD;&#xA;Increasing contrast, the effect described in the question becomes apparent: The output does not average to black/white in the edgecases (and actually extends well beyond 0/1 before doing so).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Looking at a graph provides a bit more insight:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;(grey lines mark 0/1, also in grey is the signal we are trying to output, yellow-line is average of dithered/quantized output, red is the error (signal-average)).&#xD;&#xA;&#xD;&#xA;Interestingly, not only is the average output not 0/1 at the limits, it is also not linear (likely due to the triangular pdf of the noise). Looking at the lower end, it makes intuitive sense why the output diverges: As the dithered signal starts to include negative values, the clamping-on-output changes the value of the lower dithered parts of the output (ie the negative values), thereby increasing the value of the average. An illustration appears to be in order (uniform, symmetric 2LSB dither, average still in yellow):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Now, if we just use a 1LSB normalized dither, there are no issues at the edges-cases at all, but then of course we lose the nice properties of triangular dithering (see e.g. [this presentation][5]).&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;A (pragmatic, empirical) solution (hack) then, is to revert to [-0.5;0.5[ uniform dithering for the edgecase:&#xD;&#xA;&#xD;&#xA;&lt;!-- language-all: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    float dithertri = (rnd.x + rnd.y - 1.0); //note: symmetric, triangular dither, [-1;1[&#xD;&#xA;    float dithernorm = rnd.x - 0.5; //note: symmetric, uniform dither [-0.5;0.5[&#xD;&#xA;&#xD;&#xA;    float sizt_lo = clamp( v/(0.5/7.0), 0.0, 1.0 );&#xD;&#xA;    float sizt_hi = 1.0 - clamp( (v-6.5/7.0)/(1.0-6.5/7.0), 0.0, 1.0 );&#xD;&#xA;    &#xD;&#xA;    dither = lerp( dithernorm, dithertri, min(sizt_lo, sizt_hi) );&#xD;&#xA;&#xD;&#xA;Which fixes the edgecases while keeping the triangular dithering intact for the remaining range:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;So to not answer your question: I do not know if there is a more mathematically solid solution, and am equally keen to know what Masters of Past have done :) Until then, at least we have this horrific hack to keep our code functioning.&#xD;&#xA;&#xD;&#xA;EDIT  &#xD;&#xA;I should probably cover the workaround-suggestion given in The Question, on simply compressing the signal. Because the average is not linear in the edgecases, simply compressing the input-signal does not produce a perfect result - though it does fix the endpoints:&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;References&#xD;&#xA;&#xD;&#xA; - https://www.shadertoy.com/view/llXfzS&#xD;&#xA; - http://loopit.dk/rendering_inside.pdf&#xD;&#xA; - http://loopit.dk/banding_in_games.pdf&#xD;&#xA; - http://32ipi028l5q82yhj72224m8j-wpengine.netdna-ssl.com/wp-content/uploads/2016/03/GdcVdrLottes.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNHuJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cdgag.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Z1Q15.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/IntiM.png&#xD;&#xA;  [5]: http://loopit.dk/rendering_inside.pdf&#xD;&#xA;  [6]: https://i.stack.imgur.com/tHGbs.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/MYr1f.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/DEVJo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16469" PostHistoryTypeId="2" PostId="5955" RevisionGUID="b31e13a6-a9e8-484c-b50d-55db33f98456" CreationDate="2017-12-05T00:41:56.357" UserId="5703" Text="The GGX NDF, as it appears on the paper where it is presented is:&#xD;&#xA;&#xD;&#xA;$$D(m)=\frac{\alpha_g^2\space\chi^+(m\cdot n)}{\pi\cos^4(\theta_m)(\alpha_g^2+\tan^2(\theta_m))^2}$$&#xD;&#xA;&#xD;&#xA;It is equivalent, in the range $[0,\frac{\pi}{2}]$, to the following formulation (notation simplified by me):&#xD;&#xA;&#xD;&#xA;$$D(m)=\frac{\alpha^2}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}$$&#xD;&#xA;&#xD;&#xA;by finding the derivative of the inverse of the expresions used for importance sampling ($\theta_m=\arctan(\frac{\alpha\sqrt{\xi_1}}{\sqrt{1-\xi_1}})$ and $\phi_m=2\pi\xi_2$) presented in the same paper we can derive the following PDF:&#xD;&#xA;&#xD;&#xA;$$p(m)=\frac{\alpha^2\cos(\theta)\sin(\theta)}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}$$&#xD;&#xA;&#xD;&#xA;When finding the corresponding PDF for, for instance, the Blinn NDF the only difference is a $\sin(\theta)$ in the numerator that comes from the fact that the NDF is a distribution over a hemisphere. So where does the $\cos(\theta)$ factor in the GGX PDF come from? &#xD;&#xA;&#xD;&#xA;I think it is explained after formula (37) in the paper but i don't understand the reasoning behind it.&#xD;&#xA;&#xD;&#xA;PD:here are the Blinn NDF and PDF as i understand them for reference&#xD;&#xA;&#xD;&#xA;NDF: $\frac{n+1}{2\pi}\cos^n(\theta)$  --- PDF: $\frac{n+1}{2\pi}\cos^n(\theta)\sin(\theta)$" ContentLicense="CC BY-SA 3.0" />
  <row Id="16470" PostHistoryTypeId="1" PostId="5955" RevisionGUID="b31e13a6-a9e8-484c-b50d-55db33f98456" CreationDate="2017-12-05T00:41:56.357" UserId="5703" Text="Where does the cosine factor comes from in the GGX PDF?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16471" PostHistoryTypeId="3" PostId="5955" RevisionGUID="b31e13a6-a9e8-484c-b50d-55db33f98456" CreationDate="2017-12-05T00:41:56.357" UserId="5703" Text="|rendering|mathematics|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16477" PostHistoryTypeId="2" PostId="5957" RevisionGUID="e32d3887-5eb5-406a-b353-8341b308c421" CreationDate="2017-12-05T08:05:30.770" UserId="6041" Text="I am trying to apply sinc interpolation on [this data set][1]. The patches in the left image is a snapshot of AutoCAD 3d faces. Lux values are calculated for centre of each patch that are in 0.3m x 0.3m dimension.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The middle is a bitmap image of the above data set. Applying below sinc interpolation method results in the right side image. I was expecting to get smooth gradient in the colours but am not sure if the sinc function is applied correctly.&#xD;&#xA;&#xD;&#xA;Here is the sinc interpolation method&#xD;&#xA;&#xD;&#xA;    public ImageFilm ConvolveWithSinc(ImageFilm fs, float Ts)&#xD;&#xA;            {&#xD;&#xA;                float Ws = 1 / Ts;&#xD;&#xA;                int N = fs.Width;&#xD;&#xA;                int M = fs.Height;&#xD;&#xA;    &#xD;&#xA;                ImageFilm fy = new ImageFilm(N, M);&#xD;&#xA;                Vector zero = Vector.ZERO;&#xD;&#xA;    &#xD;&#xA;                Parallel.For(0, N, x =&gt;&#xD;&#xA;                 {&#xD;&#xA;                     for (int y = 0; y &lt; M; y++)&#xD;&#xA;                     {&#xD;&#xA;                         Vector sum = Vector.ZERO;&#xD;&#xA;    &#xD;&#xA;                         for (int n = 0; n &lt; fs.Width; n++)//= (int)Ts&#xD;&#xA;                         {&#xD;&#xA;                             for (int m = 0; m &lt; fs.Height; m++)//= (int)Ts&#xD;&#xA;                             {&#xD;&#xA;                                 Vector v = fs.GetPixel(n, m);&#xD;&#xA;                                 if (v == zero) continue;&#xD;&#xA;    &#xD;&#xA;                                 sum += v * (Helper.Sinc(Ws * (x - n)) * Helper.Sinc(Ws * (y - m)));&#xD;&#xA;                             }&#xD;&#xA;                         }&#xD;&#xA;    &#xD;&#xA;                         fy.SetPixel(x, y, sum);&#xD;&#xA;                     }&#xD;&#xA;                 });&#xD;&#xA;    &#xD;&#xA;                return fy;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;I understand that the sampling frequency on the above middle image might be below the Nyquist frequency but I wanted to know if this is the case or &#xD;&#xA;I am doing something wrong.&#xD;&#xA;&#xD;&#xA;I have tried the above method on a simpler function sin(16*x*x) and the interpolated image looks similar to the original:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [1]: https://drive.google.com/file/d/0BwxvtmE7yeVKSUlnbWxUbC1VdGM/view?usp=sharing&#xD;&#xA;  [2]: https://i.stack.imgur.com/rwfs3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uJ7Zv.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/SuYWb.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/LiFLH.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16478" PostHistoryTypeId="1" PostId="5957" RevisionGUID="e32d3887-5eb5-406a-b353-8341b308c421" CreationDate="2017-12-05T08:05:30.770" UserId="6041" Text="Sinc interpolation and Ideal reconstruction example" ContentLicense="CC BY-SA 3.0" />
  <row Id="16479" PostHistoryTypeId="3" PostId="5957" RevisionGUID="e32d3887-5eb5-406a-b353-8341b308c421" CreationDate="2017-12-05T08:05:30.770" UserId="6041" Text="|image-processing|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16482" PostHistoryTypeId="5" PostId="5955" RevisionGUID="96a24079-0180-4f65-8ff4-b3386fe98aca" CreationDate="2017-12-05T16:52:22.627" UserId="5703" Comment="added 162 characters in body" Text="The GGX NDF, as it appears on the paper where it is presented is:&#xD;&#xA;&#xD;&#xA;$$D(m)=\frac{\alpha_g^2\space\chi^+(m\cdot n)}{\pi\cos^4(\theta_m)(\alpha_g^2+\tan^2(\theta_m))^2}$$&#xD;&#xA;&#xD;&#xA;It is equivalent, in the range $[0,\frac{\pi}{2}]$, to the following formulation (notation simplified by me):&#xD;&#xA;&#xD;&#xA;$$D(m)=\frac{\alpha^2}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}$$&#xD;&#xA;&#xD;&#xA;by finding the derivative of the inverse of the expresions used for importance sampling ($\theta_m=\arctan(\frac{\alpha\sqrt{\xi_1}}{\sqrt{1-\xi_1}})$ and $\phi_m=2\pi\xi_2$) presented in the same paper we can derive the following PDF:&#xD;&#xA;&#xD;&#xA;$$p(m)=\frac{\alpha^2\cos(\theta)\sin(\theta)}{\pi(\cos^2(\theta)(\alpha^2-1)+1)^2}$$&#xD;&#xA;&#xD;&#xA;When finding the corresponding PDF for, for instance, the Blinn NDF the only difference is a $\sin(\theta)$ in the numerator that comes from the fact that the NDF is a distribution over a hemisphere. So where does the $\cos(\theta)$ factor in the GGX PDF come from? &#xD;&#xA;&#xD;&#xA;I think it is explained after formula (37) in the paper but i don't understand the reasoning behind it.&#xD;&#xA;&#xD;&#xA;PD:here are the Blinn NDF and PDF as i understand them for reference&#xD;&#xA;&#xD;&#xA;NDF: $\frac{n+1}{2\pi}\cos^n(\theta)$  --- PDF: $\frac{n+1}{2\pi}\cos^n(\theta)\sin(\theta)$&#xD;&#xA;&#xD;&#xA;EDIT: here is a [link to the paper][1] in case it makes the question easier to answer&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16483" PostHistoryTypeId="5" PostId="4994" RevisionGUID="6d616686-863d-48a0-8898-09a8f2cfecb3" CreationDate="2017-12-05T18:25:00.863" UserId="310" Comment="Small typo" Text="Short answer:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;**Importance sampling** is a method to reduce variance in Monte Carlo Integration by choosing an estimator close to the shape of the actual function.&#xD;&#xA;&#xD;&#xA;**PDF** is an abbreviation for [Probability Density Function][1]. A $pdf(x)$ gives the probability of a random sample generated being $x$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Long Answer:&#xD;&#xA;=====&#xD;&#xA;&#xD;&#xA;To start, let's review what Monte Carlo Integration is, and what it looks like mathematically. &#xD;&#xA;&#xD;&#xA;Monte Carlo Integration is an technique to estimate the value of an integral. It's typically used when there isn't a closed form solution to the integral. It looks like this:&#xD;&#xA;&#xD;&#xA;$$\int f(x) \, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;In english, this says that you can approximate an integral by averaging successive random samples from the function. As $N$ gets large, the approximation gets closer and closer to the solution. $pdf(x_{i})$ represents the probability density function of each random sample.&#xD;&#xA;&#xD;&#xA;Let's do an example: Calculate the value of the integral $I$.&#xD;&#xA;&#xD;&#xA;$$I = \int_{0}^{2\pi} e^{-x} \sin(x) dx$$&#xD;&#xA;&#xD;&#xA;Let's use Monte Carlo Integration:&#xD;&#xA;&#xD;&#xA;$$I \approx \frac{1}{N} \sum_{i=1}^N \frac{e^{-x} \sin(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;A simple python program to calculate this is:&#xD;&#xA;&#xD;&#xA;    import random&#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    N = 200000&#xD;&#xA;    TwoPi = 2.0 * math.pi&#xD;&#xA;&#xD;&#xA;    sum = 0.0&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;        x = random.uniform(0, TwoPi)&#xD;&#xA;        &#xD;&#xA;        fx = math.exp(-x) * math.sin(x)&#xD;&#xA;        pdf = 1 / (TwoPi - 0.0)&#xD;&#xA;        &#xD;&#xA;        sum += fx / pdf&#xD;&#xA;&#xD;&#xA;    I = (1 / N) * sum&#xD;&#xA;    print(I)&#xD;&#xA;&#xD;&#xA;If we run the program we get $I = 0.4986941$&#xD;&#xA;&#xD;&#xA;Using separation by parts, we can get the exact solution:&#xD;&#xA;&#xD;&#xA;$$I = \frac{1}{2} (1 − e−2π) = 0.4990663$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You'll notice that the Monte Carlo Solution is not quite correct. This is because it is an estimate. That said, as $N$ goes to infinity, the estimate should get closer and closer to the correct answer. Already at $N = 2000$ some runs are almost identical to the correct answer.&#xD;&#xA;&#xD;&#xA;A note about the PDF: In this simple example, we always take a uniform random sample. A uniform random sample means every sample has the exact same probability of being chosen. We sample in the range $[0, 2\pi]$ so, $pdf(x) = 1 / (2\pi - 0)$&#xD;&#xA;&#xD;&#xA;Importance sampling works by *not* uniformly sampling. Instead we try to choose more samples that contribute a lot to the result (important), and less samples that only contribute a little to the result (less important). Hence the name, importance sampling.&#xD;&#xA;&#xD;&#xA;If you choose a sampling function whose pdf very closely matches the shape of $f$, you can greatly reduce the variance, which means you can take less samples. However, if you choose a sampling function whose value is very different from $f$, you can ***increase*** the variance. See the picture below:&#xD;&#xA;[![Comparison of good sampling vs bad sampling][2]][2]&#xD;&#xA;Image from Wojciech Jarosz's [Dissertation Appendix A][3]&#xD;&#xA;&#xD;&#xA;One example of importance sampling in Path Tracing is how to choose the direction of a ray after it hits a surface. If the surface is not perfectly specular (ie. a mirror or glass), the outgoing ray can be anywhere in the hemisphere.&#xD;&#xA;&#xD;&#xA;[![Outgoing rays can go anywhere in the hemisphere][4]][4]&#xD;&#xA;&#xD;&#xA;We ***could*** uniformly sample the hemisphere to generate the new ray. However, we can exploit the fact that the rendering equation has a cosine factor in it:&#xD;&#xA;&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) + \int_{\Omega} f(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}$$&#xD;&#xA;&#xD;&#xA;Specifically, we know that any rays at the horizon will be heavily attenuated (specifically, $\cos(x)$ ). So, rays generated near the horizon will not contribute very much to the final value.&#xD;&#xA;&#xD;&#xA;To combat this, we use importance sampling. If we generate rays according to a cosine weighted hemisphere, we ensure that more rays are generated well above the horizon, and less near the horizon. This will lower variance and reduce noise.&#xD;&#xA;&#xD;&#xA;In your case, you specified that you will be using a Cook-Torrance, microfacet-based BRDF. The common form being:&#xD;&#xA;&#xD;&#xA;$$f(p, \omega_{\text{i}}, \omega_{\text{o}}) = \frac{F(\omega_{\text{i}}, h) G(\omega_{\text{i}}, \omega_{\text{o}}, h) D(h)}{4 \cos(\theta_{i}) \cos(\theta_{o})}$$&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;$$F(\omega_{\text{i}}, h) = \text{Fresnel function} \\&#xD;&#xA;G(\omega_{\text{i}}, \omega_{\text{o}}, h) = \text{Geometry Masking and Shadowing function} \\&#xD;&#xA;D(h) = \text{Normal Distribution Function}$$&#xD;&#xA;&#xD;&#xA;The blog &quot;A Graphic's Guy's Note&quot; has an excellent write up on how to sample Cook-Torrance BRDFs. I will refer you to [his blog post][5]. That said, I will try to create a brief overview below:&#xD;&#xA;&#xD;&#xA;The NDF is generally the dominant portion of the Cook-Torrance BRDF, so if we are going to importance sample, the we should sample based on the NDF.&#xD;&#xA;&#xD;&#xA;Cook-Torrance doesn't specify a specific NDF to use; we are free to choose whichever one suits our fancy. That said, there are a few popular NDFs:&#xD;&#xA;&#xD;&#xA; - GGX&#xD;&#xA; - Beckmann&#xD;&#xA; - Blinn&#xD;&#xA;&#xD;&#xA;Each NDF has it's own formula, thus each must be sampled differently. I am only going to show the final sampling function for each. If you would like to see how the formula is derived, see the blog post.&#xD;&#xA;&#xD;&#xA;**GGX** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{GGX}(m) = \frac{\alpha^2}{\pi((\alpha^2-1) \cos^2(\theta) + 1)^2}$$&#xD;&#xA;&#xD;&#xA;To sample the spherical coordinates angle $\theta$, we can use the formula:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left( \sqrt{\frac{\alpha^2}{\xi_1 (\alpha^2 - 1) + 1}} \right)$$&#xD;&#xA;&#xD;&#xA;where $\xi$ is a uniform random variable.&#xD;&#xA;&#xD;&#xA;We assume that the NDF is isotropic, so we can sample $\phi$ uniformly:&#xD;&#xA;&#xD;&#xA;$$\phi = \xi_{2}$$&#xD;&#xA;&#xD;&#xA;**Beckmann** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Beckmann}(m) = \frac{1}{\pi \alpha^2\cos^4(\theta)} e^{-\frac{\tan^2(\theta)}{\alpha^2}}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\sqrt{\frac{1}{1 = \alpha^2 \ln(1 - \xi_1)}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;Lastly, **Blinn** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Blinn}(m) = \frac{\alpha + 2}{2 \pi} (\cos(\theta))^{\alpha}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\frac{1}{\xi_{1}^{\alpha + 1}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Putting it in Practice&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;Let's look at a basic backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. At each bounce, we have to choose a new direction for the ray. As mentioned above, we ***could*** uniformly sample the hemisphere to generate the new ray. However, the code is smarter; it importance samples the new direction based on the BRDF. (Note: This is the input direction, because we are a backwards path tracer)&#xD;&#xA;&#xD;&#xA;    // Get the new ray direction&#xD;&#xA;    // Choose the direction based on the material&#xD;&#xA;    float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;    float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;Which could be implemented as:&#xD;&#xA;&#xD;&#xA;    void LambertBRDF::Sample(float3 outputDirection, float3 normal, UniformSampler *sampler) {&#xD;&#xA;        float rand = sampler-&gt;NextFloat();&#xD;&#xA;        float r = std::sqrtf(rand) * radius;&#xD;&#xA;        float theta = sampler-&gt;NextFloat() * 2.0f * M_PI;&#xD;&#xA;&#xD;&#xA;        float x = r * std::cosf(theta);&#xD;&#xA;        float y = r * std::sinf(theta);&#xD;&#xA;&#xD;&#xA;        // Project z up to the unit hemisphere&#xD;&#xA;        float z = std::sqrtf(1.0f - x * x - y * y);&#xD;&#xA;&#xD;&#xA;        return normalize(TransformToWorld(x, y, z, normal));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float3a TransformToWorld(float x, float y, float z, float3a &amp;normal) {&#xD;&#xA;        // Find an axis that is not parallel to normal&#xD;&#xA;        float3a majorAxis;&#xD;&#xA;        if (abs(normal.x) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(1, 0, 0);&#xD;&#xA;        } else if (abs(normal.y) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(0, 1, 0);&#xD;&#xA;        } else {&#xD;&#xA;            majorAxis = float3a(0, 0, 1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Use majorAxis to create a coordinate system relative to world space&#xD;&#xA;        float3a u = normalize(cross(normal, majorAxis));&#xD;&#xA;        float3a v = cross(normal, u);&#xD;&#xA;        float3a w = normal;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Transform from local coordinates to world coordinates&#xD;&#xA;        return u * x +&#xD;&#xA;               v * y +&#xD;&#xA;               w * z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float LambertBRDF::Pdf(float3 inputDirection, float3 normal) {&#xD;&#xA;        return dot(inputDirection, normal) * M_1_PI;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After we sample the inputDirection ('wi' in the code), we use that to calculate the value of the BRDF. And then we divide by the pdf as per the Monte Carlo formula:&#xD;&#xA;&#xD;&#xA;    // Accumulate the brdf attenuation&#xD;&#xA;    throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;&#xD;&#xA;Where *Eval()* is just the BRDF function itself (Lambert, Blinn-Phong, Cook-Torrance, etc.):&#xD;&#xA;&#xD;&#xA;    float3 LambertBRDF::Eval(float3 inputDirection, float3 outputDirection, float3 normal) const override {&#xD;&#xA;        return m_albedo * M_1_PI * dot(inputDirection, normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGyXh.png&#xD;&#xA;  [3]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/appendixA.pdf&#xD;&#xA;  [4]: https://i.stack.imgur.com/6crnH.png&#xD;&#xA;  [5]: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16484" PostHistoryTypeId="2" PostId="5958" RevisionGUID="54c2859b-6a46-4fa5-b28e-57c8844c2163" CreationDate="2017-12-05T21:43:20.207" UserId="48" Text="Normal distribution functions are defined a bit differently than you might expect. They're not _strictly_ a probability distribution over solid angle; they have to do with the density of microfacets with respect to macro-surface area. The upshot is that they're normalized with an extra cosine factor:&#xD;&#xA;$$ \int_\Omega D(m) \cos(\theta_m)\, d\omega_m = 1 $$&#xD;&#xA;This cosine factor accounts for the projected area of microfacets onto the macrosurface. When importance-sampling the NDF this cosine factor must be accounted for as well.&#xD;&#xA;&#xD;&#xA;This is actually hinted at in the text of the paper, as it says&#xD;&#xA;&#xD;&#xA;&gt; The equations for sampling $D(m) | m \cdot n |$ are:&#xD;&#xA;&#xD;&#xA;(just above equations 35–36). The $|m \cdot n|$ factor there is equal to $|cos(\theta_m)|$. Then, as you note, the sine shows up as part of the area element for spherical coordinates.&#xD;&#xA;&#xD;&#xA;I wrote [a blog post](http://reedbeta.com/blog/hows-the-ndf-really-defined/) a few years ago that goes into more detail about this." ContentLicense="CC BY-SA 3.0" />
  <row Id="16485" PostHistoryTypeId="5" PostId="5958" RevisionGUID="63bc6a88-1a64-4b8d-bda9-d2c30baf16e5" CreationDate="2017-12-05T21:50:09.517" UserId="48" Comment="added 90 characters in body" Text="Normal distribution functions are defined a bit differently than you might expect. They're not _strictly_ a probability distribution over solid angle; they have to do with the density of microfacets with respect to macro-surface area. The upshot is that they're normalized with an extra cosine factor:&#xD;&#xA;$$ \int_\Omega D(m) \cos(\theta_m)\, d\omega_m = 1 $$&#xD;&#xA;This cosine factor accounts for the projected area of microfacets onto the macrosurface. When importance-sampling the NDF this cosine factor must be accounted for as well.&#xD;&#xA;&#xD;&#xA;This is actually hinted at in the text of the paper, as it says&#xD;&#xA;&#xD;&#xA;&gt; The equations for sampling $D(m) | m \cdot n |$ are:&#xD;&#xA;&#xD;&#xA;(just above equations 35–36). The $|m \cdot n|$ factor there is equal to $|cos(\theta_m)|$. So the quantity being sampled is not just the NDF itself, but includes this extra factor. Then, as you note, the sine shows up as part of the area element for spherical coordinates.&#xD;&#xA;&#xD;&#xA;I wrote [a blog post](http://reedbeta.com/blog/hows-the-ndf-really-defined/) a few years ago that goes into more detail about this." ContentLicense="CC BY-SA 3.0" />
  <row Id="16487" PostHistoryTypeId="34" PostId="4370" RevisionGUID="0abec3cf-f000-4741-b395-d5419d18d87e" CreationDate="2017-12-06T12:54:21.407" UserId="-1" Comment="41" />
  <row Id="16489" PostHistoryTypeId="5" PostId="5947" RevisionGUID="73b1b6d6-fc76-413b-8005-7dd890ea2238" CreationDate="2017-12-07T00:41:04.437" UserId="67" Comment="Various improvements" Text="What does it mean and why is it not well suited for describing colors by human? &#xD;&#xA;&#xD;&#xA;Is CMYK nonlinear also?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16490" PostHistoryTypeId="4" PostId="5947" RevisionGUID="73b1b6d6-fc76-413b-8005-7dd890ea2238" CreationDate="2017-12-07T00:41:04.437" UserId="67" Comment="Various improvements" Text="RGB nonlinear, what does it mean?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16491" PostHistoryTypeId="24" PostId="5947" RevisionGUID="73b1b6d6-fc76-413b-8005-7dd890ea2238" CreationDate="2017-12-07T00:41:04.437" Comment="Proposed by 67 approved by 209, 4958 edit id of 291" ContentLicense="CC BY-SA 3.0" />
  <row Id="16492" PostHistoryTypeId="2" PostId="5959" RevisionGUID="6b882dcc-dec5-47d9-98f9-3cd1d1383774" CreationDate="2017-12-07T05:44:01.390" UserId="7412" Text="I have a bunch of intersecting convex polygons, I want to find vertices of the outer contour of all those polygons. An individual polygon is not self-intersecting.&#xD;&#xA;&#xD;&#xA;Could you please tell What could be a generic way of achieving this? Is there an API to do this?&#xD;&#xA;&#xD;&#xA;PS: I'm developing a CAD drawing generator using .netdxf and C#.&#xD;&#xA;&#xD;&#xA;Below is a simple example&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UT9G4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16493" PostHistoryTypeId="1" PostId="5959" RevisionGUID="6b882dcc-dec5-47d9-98f9-3cd1d1383774" CreationDate="2017-12-07T05:44:01.390" UserId="7412" Text="Finding vertices of the outer contour of intersecting polygons" ContentLicense="CC BY-SA 3.0" />
  <row Id="16494" PostHistoryTypeId="3" PostId="5959" RevisionGUID="6b882dcc-dec5-47d9-98f9-3cd1d1383774" CreationDate="2017-12-07T05:44:01.390" UserId="7412" Text="|polygon|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16495" PostHistoryTypeId="5" PostId="5957" RevisionGUID="90dc4037-83e3-498d-a25e-ee5094a33862" CreationDate="2017-12-07T10:08:08.987" UserId="6041" Comment="added 619 characters in body" Text="I am trying to apply sinc interpolation on [this data set][1]. The patches in the left image is a snapshot of AutoCAD 3d faces. Lux values are calculated for centre of each patch that are in 0.3m x 0.3m dimension.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The middle is a bitmap image of the above data set. Applying below sinc interpolation method results in the right side image. I was expecting to get smooth gradient in the colours but am not sure if the sinc function is applied correctly.&#xD;&#xA;&#xD;&#xA;Here is the sinc interpolation method&#xD;&#xA;&#xD;&#xA;    public ImageFilm ConvolveWithSinc(ImageFilm fs, float Ts)&#xD;&#xA;            {&#xD;&#xA;                float Ws = 1 / Ts;&#xD;&#xA;                int N = fs.Width;&#xD;&#xA;                int M = fs.Height;&#xD;&#xA;    &#xD;&#xA;                ImageFilm fy = new ImageFilm(N, M);&#xD;&#xA;                Vector zero = Vector.ZERO;&#xD;&#xA;    &#xD;&#xA;               for (int x = 0; x &lt; N; x++)&#xD;&#xA;               {&#xD;&#xA;                for (int y = 0; y &lt; M; y++)&#xD;&#xA;                {&#xD;&#xA;                    LightVector sum = LightVector.ZERO;&#xD;&#xA;&#xD;&#xA;                    double sincSum = 0;&#xD;&#xA;&#xD;&#xA;                    for (int n = 0; n &lt; fs.Width; n++)//= (int)Ts&#xD;&#xA;                    {&#xD;&#xA;                        for (int m = 0; m &lt; fs.Height; m++)//= (int)Ts&#xD;&#xA;                        {&#xD;&#xA;                            double sinc = (Helper.Sinc(Ws * (x - n)) * Helper.Sinc(Ws * (y - m)));&#xD;&#xA;                            sincSum += sinc;&#xD;&#xA;&#xD;&#xA;                            LightVector v = fs.GetPixel(n, m);&#xD;&#xA;                            if (v == zero) continue;&#xD;&#xA;                            &#xD;&#xA;                            sum += v * sinc;&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;&#xD;&#xA;                    LightVector c = sum / sincSum;&#xD;&#xA;&#xD;&#xA;                    if (c.X &gt; 255 || c.Y &gt; 255 || c.Z &gt; 255) &#xD;&#xA;                        c = c.Clamp(0, 255);&#xD;&#xA;&#xD;&#xA;                    fy.SetPixel(x, y, c);&#xD;&#xA;                } &#xD;&#xA;              }&#xD;&#xA;    &#xD;&#xA;                return fy;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;I understand that the sampling frequency on the above middle image might be below the Nyquist frequency but I wanted to know if this is the case or &#xD;&#xA;I am doing something wrong.&#xD;&#xA;&#xD;&#xA;I have tried the above method on a simpler function sin(16*x*x) and the interpolated image looks similar to the original:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;Thanks for the comments. I have modified the code to divide the pixel value by the sum of the two sinc functions. Is this the correct way of normilizing it? The image looks better but it is very blurry. &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://drive.google.com/file/d/0BwxvtmE7yeVKSUlnbWxUbC1VdGM/view?usp=sharing&#xD;&#xA;  [2]: https://i.stack.imgur.com/rwfs3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uJ7Zv.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/SuYWb.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/LiFLH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/aZrhE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16503" PostHistoryTypeId="2" PostId="5962" RevisionGUID="42ec01e9-c204-4711-bb2c-ca5b1b18871b" CreationDate="2017-12-07T19:51:33.557" UserId="506" Text="Sounds like you’re looking for a way to do a [Boolean union operation](https://en.wikipedia.org/wiki/Boolean_operations_on_polygons). There’s a couple of algorithms linked from that article that should do the trick." ContentLicense="CC BY-SA 3.0" />
  <row Id="16504" PostHistoryTypeId="2" PostId="5963" RevisionGUID="c6a0cfaa-4aac-4454-b67b-b7ac1dc8422a" CreationDate="2017-12-07T20:31:34.333" UserId="7864" Text="Using an iPhone X, I can get a mesh of the face (using `ARFaceGeometry`), which I can output as an `.obj` file using `Model I/O`.&#xD;&#xA;&#xD;&#xA;Not included in the output file is an image for the face, but I can get the camera image for that frame, as a jpeg.&#xD;&#xA;&#xD;&#xA;When I look at the resulting `.mtl` file in a text editor, I see 5 different materials (&quot;material_1&quot;, &quot;material_2&quot;, etc.), When I look at the `.obj` file in a text editor, there are 5 &quot;groups&quot; of info (each with vertices, normals, texture coordinates, and face elements).&#xD;&#xA;&#xD;&#xA;I want to know about 2 assumptions I am making:&#xD;&#xA;&#xD;&#xA;1. If I erase the last 4 materials in the `.mtl` file, along with the last 4 groups of info in the `.obj` file, the mesh seems to look the same. Is it okay to assume only the first set is sufficient?&#xD;&#xA;&#xD;&#xA;2. Can I replace the texture coordinates in this first group (of the `.obj` file, the set of `vt`s), to reflect the new jpeg image? My goal is to get the image of the face to texture onto the face mesh.&#xD;&#xA;&#xD;&#xA;I'm creating these new texture coordinates by: for each vertex in the mesh, transform to world space, then camera space, then divide by image dimensions to get a value between 0 and 1.&#xD;&#xA;&#xD;&#xA;As you might guess, I'm getting some pretty funky textures on the mesh (though I'm pleased I'm getting some texture!). Does any part of my workflow sound incorrect?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16505" PostHistoryTypeId="1" PostId="5963" RevisionGUID="c6a0cfaa-4aac-4454-b67b-b7ac1dc8422a" CreationDate="2017-12-07T20:31:34.333" UserId="7864" Text="Composition of an .obj file" ContentLicense="CC BY-SA 3.0" />
  <row Id="16506" PostHistoryTypeId="3" PostId="5963" RevisionGUID="c6a0cfaa-4aac-4454-b67b-b7ac1dc8422a" CreationDate="2017-12-07T20:31:34.333" UserId="7864" Text="|texture|3d|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16508" PostHistoryTypeId="5" PostId="5948" RevisionGUID="f5f39fd2-0df0-43b8-b2a8-895c4969ddc3" CreationDate="2017-12-08T06:05:26.387" UserId="3003" Comment="Clarified first paragraph." Text="In general, non-linear function would mean that an increase in an input does not produce a proportional increase or decrease in output. Mathematically, any function that relates one value to another that doesn't follow a straight line is non-linear. So x raised to the power y is a non-linear function.&#xD;&#xA;&#xD;&#xA;This matters for colors because our brains don't perceive light in a linear fashion. If you double the number of photons reaching the retina, the brain doesn't interpret it as twice as bright. We have better perception in the mids and highlights than in the shadows. That is, we can distinguish bright values that are close together more easily than we can distinguish dark values that are equally close together. &#xD;&#xA;&#xD;&#xA;When encoding light values in a computer, we need to choose how precisely to record them without losing too much quality. If we use too many bits, then our hardware becomes more expensive. If we use too few then the image looks bad. Until the last ~10-15 years or so, it was generally considered too expensive to store more than 8 bits per red, green, and blue channel. The problem is that if you encode the light values linearly (where 2x causes your monitor to produce twice as many photons as 1x does), then images stored with only 8 bits per channel will have very obvious banding in bright areas of continuous color.&#xD;&#xA;&#xD;&#xA;But remember above that humans have a harder time seeing in the shadows than in the bright areas? That means that we can use 8 bits per channel, but not use them linearly. If we instead take each 8-bit color channel value and treat it as a value between 0 and 1, if we raise that value to a power then we have more values to use to represent mids and highlights, and fewer to represent shadows. This is called gamma-correction or gamma-encoding. We just have to remember to do the reverse (raise the value to the 1 / x power) when we want to output the values on a display.&#xD;&#xA;&#xD;&#xA;So if you're dealing with non-linear RGB, it is probably gamma encoded. sRGB is a popular encoding that uses a power of ~2.2. (In truth, it's [a little more complicated than just raising it to a power](https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_.28.22gamma.22.29).) So when someone tells you that RGB is non-linear, that's usually what they are referring to. It is entirely possible to store images in linear RGB, so long as you use more than 8 bits per color channel. There are also formats that use a logarithmic encodings, though they are less common outside of film production.&#xD;&#xA;&#xD;&#xA;CMYK is more complicated than RGB. Rather than having only a single thing that is outputting the color (the monitor), with CMYK, you have to deal with the medium you're printing on as well as the inks you are printing with. In a typical scenario, you print onto a white surface (such as a piece of paper). Ideally all visible frequencies of light should be reflected off of the paper and into your eyes or camera. When you add ink, the ink absorbs some frequencies of light and reflects others. (And I believe some passes through the ink, hits the paper and is reflected back as well.) The manner in which an ink reflects light is non-linear. Doubling the amount of ink may not cut in half the number of photons reflected back. So CMYK is also non-linear." ContentLicense="CC BY-SA 3.0" />
  <row Id="16509" PostHistoryTypeId="2" PostId="5964" RevisionGUID="6b3798de-1c5c-414d-87be-5a31743be529" CreationDate="2017-12-08T09:01:41.160" UserId="3024" Text="I'm confused how does the GL_SRC_ALPHA_SATURATE function effect a 32 bit floating point texture attachment in FBO while blending colors. In the [reference][1] the equation is:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here what does kA means for a 32-bit(GL_RGBA32F) texture?&#xD;&#xA;&#xD;&#xA;According to [wiki][3], when blending a floating point texture, the color value does not get normalized. If so then does min(As, ka - Ad) get divided by the kA?&#xD;&#xA;&#xD;&#xA;And lastly, what happens if Ad is negative floating value?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml&#xD;&#xA;  [2]: https://i.stack.imgur.com/EDVYW.png&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Blending#Source.2C_Destination.2C_and_the_buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="16510" PostHistoryTypeId="1" PostId="5964" RevisionGUID="6b3798de-1c5c-414d-87be-5a31743be529" CreationDate="2017-12-08T09:01:41.160" UserId="3024" Text="Blending for Floating Point Texture" ContentLicense="CC BY-SA 3.0" />
  <row Id="16511" PostHistoryTypeId="3" PostId="5964" RevisionGUID="6b3798de-1c5c-414d-87be-5a31743be529" CreationDate="2017-12-08T09:01:41.160" UserId="3024" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16512" PostHistoryTypeId="5" PostId="5964" RevisionGUID="19753f44-b7d9-4a9a-9b67-87493e01a37a" CreationDate="2017-12-08T09:09:01.710" UserId="3024" Comment="added 5 characters in body" Text="I'm confused how does the GL_SRC_ALPHA_SATURATE function effect a 32 bit floating point texture attachment in FBO while blending colors. In the [reference][1] the equation is:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here what is the value of kA for a 32-bit(GL_RGBA32F) texture?&#xD;&#xA;&#xD;&#xA;According to [wiki][3], when blending a floating point texture, the color value does not get normalized. If so then does min(As, ka - Ad) get divided by the kA?&#xD;&#xA;&#xD;&#xA;And lastly, what happens if Ad is negative floating value?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml&#xD;&#xA;  [2]: https://i.stack.imgur.com/EDVYW.png&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Blending#Source.2C_Destination.2C_and_the_buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="16513" PostHistoryTypeId="2" PostId="5965" RevisionGUID="5e51c1f6-45ae-47cb-9fa5-7c4eacdef86a" CreationDate="2017-12-08T12:05:51.657" UserId="7868" Text="Do primary rays conform to the frustum? If they're randomly directed, is the randomness fitted to some distribution (as it would be for a diffuse BRDF? I'm building my existing raymarcher into a monte carlo path tracer and I'm really unsure about how to orient my rays before tracing actually starts." ContentLicense="CC BY-SA 3.0" />
  <row Id="16514" PostHistoryTypeId="1" PostId="5965" RevisionGUID="5e51c1f6-45ae-47cb-9fa5-7c4eacdef86a" CreationDate="2017-12-08T12:05:51.657" UserId="7868" Text="Primary ray directions (MC Path tracer)" ContentLicense="CC BY-SA 3.0" />
  <row Id="16515" PostHistoryTypeId="3" PostId="5965" RevisionGUID="5e51c1f6-45ae-47cb-9fa5-7c4eacdef86a" CreationDate="2017-12-08T12:05:51.657" UserId="7868" Text="|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16516" PostHistoryTypeId="2" PostId="5966" RevisionGUID="1813f0dc-78f3-4420-a9bc-de900ffc2d71" CreationDate="2017-12-08T12:13:33.037" UserId="2041" Text="Yes, in the simple case, primary rays conform to the frustum. If you're doing depth-of-field optically, then the rays don't quite conform to the frustum, because you need to vary the ray origins slightly as well as the directions. How exactly the variation works depends on how closely you're simulating the lens system and aperture.&#xD;&#xA;&#xD;&#xA;I've never done full Monte Carlo for ray sampling; I've always generated the ray directions according to a space-filling curve on the image plane, and then adaptively supersampled once I have an initial image. Sending one ray per pixel but jittering the sample points from that grid is also a popular choice." ContentLicense="CC BY-SA 3.0" />
  <row Id="16517" PostHistoryTypeId="2" PostId="5967" RevisionGUID="ca9ea163-c3d8-4eda-ae2e-1cfc8cea358f" CreationDate="2017-12-08T21:13:57.917" UserId="7644" Text="Section &quot;17.3.8 Blending&quot; of the OpenGL spec states:&#xD;&#xA;&#xD;&#xA;&gt; If the color buffer is fixed-point, the components of the source and destination values and blend factors are each clamped to [0, 1] or [-1, 1] respectively for an unsigned normalized or signed normalized color buffer prior to evaluating the blend equation. **If the color buffer is floating-point, no clamping occurs**. The resulting four values are sent to the next operation.&#xD;&#xA;&#xD;&#xA;So we know that no clamping occurs there. The next section is &quot;17.3.8.1 Blend Equation&quot; and states:&#xD;&#xA;&#xD;&#xA;&gt; Signed or unsigned normalized fixed-point destination (framebuffer) components are represented as described in section 2.3.4. **Constant color components, floating-point destination components, and source (fragment) components are taken to be floating-point values**. If source components are represented internally by the GL as fixed-point values, they are also interpreted according to section 2.3.4.&#xD;&#xA;&#xD;&#xA;Finally, section &quot;17.3.8.2 Blend Functions&quot; refers to table 17.2 which explains that for `GL_SRC_ALPHA_SATURATE`:&#xD;&#xA;&#xD;&#xA;	RGB Blend Factors = (f, f, f)&#xD;&#xA;	Alpha Blend Factor = 1&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$ f = min(A_{s0}, 1 - A_d) $$&#xD;&#xA;&#xD;&#xA;So it seems that the reference documentation is misleading for this particular case. However the specification is clear: there is no clamping or conversion for floating-point color buffers.&#xD;&#xA;&#xD;&#xA;### What if Ad is negative floating value?&#xD;&#xA;&#xD;&#xA;My reading of the spec is that nothing special happens if Ad is negative. The `min()` operation will still produce results, but I don't see how they would be useful.&#xD;&#xA;&#xD;&#xA;I've never used `GL_SRC_ALPHA_SATURATE` myself, but the way I understand it, with `GL_FUNC_ADD`, it is meant to accumulate color values in the color buffer until the accumulated alpha value equals 1. When the alpha value of the color buffer is 1, no further color contribution from new pixels is allowed. This assumes that you use alpha values between 0 and 1 and use an initial alpha value of 0. Otherwise everything falls apart.&#xD;&#xA;&#xD;&#xA;In fact, I think majority of the blending factor mechanisms were designed with alpha values between 0 and 1 in mind and make little sense outside of that range." ContentLicense="CC BY-SA 3.0" />
  <row Id="16518" PostHistoryTypeId="50" PostId="5697" RevisionGUID="efdcc312-4b59-4f1d-99f5-b4cd0b860cff" CreationDate="2017-12-08T21:28:27.550" UserId="-1" />
  <row Id="16519" PostHistoryTypeId="2" PostId="5968" RevisionGUID="20e0ee56-00ea-4902-bb89-98e7ccf4546c" CreationDate="2017-12-09T01:07:53.423" UserId="7871" Text="I'm following [this tutorial][1] where at somepoint the derived PDF for spherical coordinates for a Lambertian surface is&#xD;&#xA;&#xD;&#xA;\begin{array}{l}&#xD;&#xA;p(\theta, \phi) = \dfrac{\sin \theta}{2 \pi}.&#xD;&#xA;\end{array}&#xD;&#xA;&#xD;&#xA;But as soon as they compute a sample, the result is instead divided by $ \dfrac{1}{2\pi} $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Why isn't it divided by $ \frac{\sin \theta}{2 \pi} $ instead?&#xD;&#xA;&#xD;&#xA;If we were using differential steradians over the unit hemisphere, the only possible probability density function integrating to 1 is infact $ \frac{1}{2\pi} $&#xD;&#xA;&#xD;&#xA;But if we separate the integral over the hemisphere traced by spherical coordinates&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;\int_{\phi = 0}^{2\pi} \int_{\theta = 0}^{\frac{\pi}{2}}  \,  \frac{\sin{\theta}}{2\pi}d\theta d\phi= 1. &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The PDF now becomes $ \frac{\sin \theta}{2 \pi} $ yet they still divide by $ \frac{1}{2\pi} $&#xD;&#xA;&#xD;&#xA;As a side question, I'm having a hard time visualizing what the cumulative distribution function of $ \frac{1}{2\pi} $ represents when the integral is made over steradians. As we approach $ 2\pi $ the probability a sample is &quot;lower&quot; than that gets higher, but does this visually means we're picking a bigger and bigger steradian over the hemisphere and estimating what is the probability a differential direction is not contained in this &quot;expanding steradian&quot;?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="16520" PostHistoryTypeId="1" PostId="5968" RevisionGUID="20e0ee56-00ea-4902-bb89-98e7ccf4546c" CreationDate="2017-12-09T01:07:53.423" UserId="7871" Text="Probability density function while using spherical coordinates" ContentLicense="CC BY-SA 3.0" />
  <row Id="16521" PostHistoryTypeId="3" PostId="5968" RevisionGUID="20e0ee56-00ea-4902-bb89-98e7ccf4546c" CreationDate="2017-12-09T01:07:53.423" UserId="7871" Text="|raytracing|pathtracing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16522" PostHistoryTypeId="5" PostId="5966" RevisionGUID="dd54504f-99e8-403a-8673-dd80b90bacc8" CreationDate="2017-12-09T10:24:59.560" UserId="2041" Comment="add a thing about Poisson discs, and restructure the second paragraph" Text="Yes, in the simple case, primary rays conform to the frustum. If you're doing depth-of-field optically, then the rays don't quite conform to the frustum, because you need to vary the ray origins slightly as well as the directions. How exactly the variation works depends on how closely you're simulating the lens system and aperture. You can picture it as sampling from several frustums, one for each pinhole camera you're averaging.&#xD;&#xA;&#xD;&#xA;I've never done full Monte Carlo for ray sampling: generating the rays according to a uniform distribution is bad at distributing them usefully around the image. Popular options include:&#xD;&#xA;&#xD;&#xA;- You can generate the ray directions according to a space-filling curve on the image plane, and then adaptively supersample once you have enough samples to estimate contrast.&#xD;&#xA;- Start with a regular grid that goes through the centre of each pixel, but randomly jitter the directions within each pixel. This was popular for many years but (done naively) it's still slightly biased because you're too likely to sample the corners of pixels.&#xD;&#xA;- Start with a uniform random sampling but use Poisson discs to avoid putting rays too close together. This is closer to a pure random sampling, and it has the advantage you can keep using the technique as you refine/supersample the image by decreasing the disc radius over time." ContentLicense="CC BY-SA 3.0" />
  <row Id="16527" PostHistoryTypeId="5" PostId="5968" RevisionGUID="5c45dd1c-47a7-497b-a5af-221380fb0603" CreationDate="2017-12-11T01:25:09.150" UserId="7871" Comment="added 1015 characters in body" Text="I'm following [this tutorial][1] where at somepoint the derived PDF for spherical coordinates for a Lambertian surface is&#xD;&#xA;&#xD;&#xA;\begin{array}{l}&#xD;&#xA;p(\theta, \phi) = \dfrac{\sin \theta}{2 \pi}.&#xD;&#xA;\end{array}&#xD;&#xA;&#xD;&#xA;But as soon as they compute a sample, the result is instead divided by $ \dfrac{1}{2\pi} $, which as they say is the &quot;pdf of the integral&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Why isn't it divided by $ \frac{\sin \theta}{2 \pi} $ instead?&#xD;&#xA;&#xD;&#xA;If we were using differential steradians over the unit hemisphere, the only possible probability density function integrating to 1 is infact $ \frac{1}{2\pi} $&#xD;&#xA;&#xD;&#xA;But if we separate the integral over the hemisphere traced by spherical coordinates&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;\int_{\phi = 0}^{2\pi} \int_{\theta = 0}^{\frac{\pi}{2}}  \,  \frac{\sin{\theta}}{2\pi}d\theta d\phi= 1. &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The PDF now becomes $ \frac{\sin \theta}{2 \pi} $ yet they still divide by $ \frac{1}{2\pi} $&#xD;&#xA;&#xD;&#xA;EDIT: after carefully reviewing the concept of PDFs and integration over the hemisphere I'm starting to think the article I've linked is making a substantial error, mixing the idea of importance sampling with the pdf of choosing a direction of reflectance from a lambertian surface&#xD;&#xA;&#xD;&#xA;Radiance is defined as&#xD;&#xA;$$ L_{(x,\omega)} = \frac{\mathrm{d}^2\Phi}{\mathrm{d}\omega\ cos\theta\ \mathrm{d}x}  $$&#xD;&#xA;Since it's defined over differential solid angles, we can interpret the result of one sample as if it was the flux density &quot;over a unit steradian&quot;&#xD;&#xA;&#xD;&#xA;If we use monte carlo estimation and find &quot;the average flux density over a single steradian&quot; and multiply the result by $2\pi$, we get irradiance:&#xD;&#xA;&#xD;&#xA;$$ (2\pi) \frac{1}{n}\sum^n L_{(x,\omega)} $$. &#xD;&#xA;But in this particular case, $2\pi$ has nothing to do with pdfs! since it's the integral domain used for the monte carlo estimation!&#xD;&#xA;&#xD;&#xA;Instead, the real pdf is computed for $\theta$ and $\phi$ because that is the probability density function of choosing **one direction over the other, according to the particular properties of a lambertian surface**. A mirror-like surface has a different probability of choosing one direction over the other, but this has nothing to do us with dividing the sample with $\frac{1}{2\pi}$. It would be different if we were using importance sampling, but in this case it seems like we're not&#xD;&#xA;&#xD;&#xA;Is my reasoning correct? If not, what am I missing?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="16532" PostHistoryTypeId="2" PostId="5971" RevisionGUID="86b33e84-5d03-49c7-9788-ea98bc5c5848" CreationDate="2017-12-11T22:13:51.483" UserId="7740" Text="This is more just for curiosity rather than actually wanting to get one, but is there a place where I could buy a printed version of the CIE xy colour space diagram which accurately recreates all of the visible colours outside of the regular printing gamuts?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16533" PostHistoryTypeId="1" PostId="5971" RevisionGUID="86b33e84-5d03-49c7-9788-ea98bc5c5848" CreationDate="2017-12-11T22:13:51.483" UserId="7740" Text="Accurately printed CIE diagram" ContentLicense="CC BY-SA 3.0" />
  <row Id="16534" PostHistoryTypeId="3" PostId="5971" RevisionGUID="86b33e84-5d03-49c7-9788-ea98bc5c5848" CreationDate="2017-12-11T22:13:51.483" UserId="7740" Text="|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16535" PostHistoryTypeId="2" PostId="5972" RevisionGUID="2d3e5991-a476-4a06-b3ac-3ee531721716" CreationDate="2017-12-12T00:22:25.070" UserId="6406" Text="I ran into half-edges as part of the result of a Delaunay Triangulation library, but can't find an actual definition of what one is. &#xA;&#xA;I understand vertices, edges and faces, but can't find a concrete definition of a half-edge." ContentLicense="CC BY-SA 3.0" />
  <row Id="16536" PostHistoryTypeId="1" PostId="5972" RevisionGUID="2d3e5991-a476-4a06-b3ac-3ee531721716" CreationDate="2017-12-12T00:22:25.070" UserId="6406" Text="What is the definition of a Half Edge?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16537" PostHistoryTypeId="3" PostId="5972" RevisionGUID="2d3e5991-a476-4a06-b3ac-3ee531721716" CreationDate="2017-12-12T00:22:25.070" UserId="6406" Text="|triangulation|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16538" PostHistoryTypeId="2" PostId="5973" RevisionGUID="b1ed5937-f29e-4ff2-93fa-86b5bafc8744" CreationDate="2017-12-12T04:09:35.353" UserId="1937" Text="A half-edge is an edge split along its length, and having a directional component, that is, a beginning vertex and an end vertex. Where two polygons share an edge, each polygon gets a single half-edge between the same two vertices, which will have opposite directions if the winding order is consistent. These half-edges will have references to one another as two halves of a pair.&#xD;&#xA;&#xD;&#xA;The full half edge data structure stores for each half-edge:&#xD;&#xA;&#xD;&#xA; - The polygon it belongs to&#xD;&#xA; - Previous and next half edges within the polygon&#xD;&#xA; - Its pair half-edge in a neighbouring polygon&#xD;&#xA; - Its origin vertex&#xD;&#xA;&#xD;&#xA;This structure allows you to extract all sorts of connectivity information from a mesh, such as which edges or polygons lie around a particular vertex, simply by traversing the half-edges. There's a good article explaining it [here][1].&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="16539" PostHistoryTypeId="2" PostId="5974" RevisionGUID="f5f90e65-c1ae-403f-b54f-09dda88dee31" CreationDate="2017-12-12T10:12:11.697" UserId="5748" Text="I think there is no point pursuing &quot;objective accuracy&quot; for colors, because individual perception of colors is different. The current standard is merely a statistical result for human eye perception.&#xA;That is to say, it is possible for someone else to perceive the colors you regard identical as different." ContentLicense="CC BY-SA 3.0" />
  <row Id="16544" PostHistoryTypeId="2" PostId="5976" RevisionGUID="80df41d2-29ed-4d13-b5f9-13d263444819" CreationDate="2017-12-12T14:51:35.527" UserId="7884" Text="I am told that in computer graphics, the screen refreshes in number of times(in this scenario let say that it **renders** **60** times per second). The screen is cleared and drawn to 60 times per second.&#xD;&#xA;&#xD;&#xA;My question is how can I see the **Image** being shown 60 times per second yet I cannot see the **Clear Color** which is also being displayed 60 times per second too?&#xD;&#xA;Or does this have to do with how our eyes see or how our brain interprets things we see?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16545" PostHistoryTypeId="1" PostId="5976" RevisionGUID="80df41d2-29ed-4d13-b5f9-13d263444819" CreationDate="2017-12-12T14:51:35.527" UserId="7884" Text="Render and Clear Color Question?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16546" PostHistoryTypeId="3" PostId="5976" RevisionGUID="80df41d2-29ed-4d13-b5f9-13d263444819" CreationDate="2017-12-12T14:51:35.527" UserId="7884" Text="|rendering|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16547" PostHistoryTypeId="2" PostId="5977" RevisionGUID="8cdaf47e-c4d6-4bc5-89d4-f101ebddbade" CreationDate="2017-12-12T15:07:37.507" UserId="2041" Text="You're confusing the *screen* (the physical display) with the *framebuffer* (the memory which gets read out by the *display controller*). The framebuffer might get cleared at the start of each frame period, but that doesn't change the display. The order of events is as follows:&#xD;&#xA;&#xD;&#xA;* At the start of a new frame, `glClear` or equivalent sets the framebuffer to the clear colour.&#xD;&#xA;* `glDraw` or equivalent calls draw more stuff on top of the clear colour.&#xD;&#xA;* `eglSwapBuffers` or equivalent queues the finished frame to be drawn on the display.&#xD;&#xA;* When the display is ready, [this process](https://computergraphics.stackexchange.com/a/5863/2041) is followed. It reads out the contents of the framebuffer and shows them on the physical screen.&#xD;&#xA;&#xD;&#xA;The framebuffer that's being drawn into is never shown on the screen; only when it's finished can it be shown. Double- or triple-buffering gives you multiple copies of the framebuffer, so the application can be using one while the display is using the other. It's nothing to do with your eyes or brain.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;It's actually a lot more complicated than this, because most GL implementations today are not immediate-mode, so none of the real work happens when you call the functions named above. In fact, clearing the buffer might not even happen at all: if every pixel is drawn to anyway, there's no need to. Back when clearing the framebuffer took significant time, games would go faster by not calling `glClear`. Today it's more important to call `glClear` because it lets the implementation know when the start of the new frame is, but it will probably do something smarter than just writing to every pixel." ContentLicense="CC BY-SA 3.0" />
  <row Id="16549" PostHistoryTypeId="2" PostId="5978" RevisionGUID="64d65739-4c34-40c8-9db7-99952fc0067c" CreationDate="2017-12-12T17:59:57.457" UserId="38" Text="Its not actually possible to do. Because that paper you print on needs to have properties not avalialbe. The color on the edge are very pure and can not be mixed. I dont also see any way they could be reflected either. Also the xy diagram is not the full color space just a slice of it." ContentLicense="CC BY-SA 3.0" />
  <row Id="16550" PostHistoryTypeId="5" PostId="5867" RevisionGUID="b44dba18-327c-415c-bc83-a2df2bb58d7f" CreationDate="2017-12-12T20:00:16.087" UserId="231" Comment="Remove thanks" Text="What is the color of the sky depending on the time?&#xD;&#xA;&#xD;&#xA;I'm looking for a set of colors (HTML-Code), the sky has during sunrise, morning, forenoon, noon, afternoon, evening and sunset. A formula to calculate the color would be awesome." ContentLicense="CC BY-SA 3.0" />
  <row Id="16551" PostHistoryTypeId="10" PostId="5867" RevisionGUID="bf847eff-563c-48fb-8caf-8dd19a7138a2" CreationDate="2017-12-12T20:05:08.377" UserId="231" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:3003,&quot;DisplayName&quot;:&quot;user1118321&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="16552" PostHistoryTypeId="50" PostId="4632" RevisionGUID="9ae4869a-14e0-432d-8b43-a4fb19f46ec2" CreationDate="2017-12-12T20:44:58.590" UserId="-1" />
  <row Id="16553" PostHistoryTypeId="2" PostId="5979" RevisionGUID="aeca85dc-9a04-431e-a42c-08e51d0f4bdd" CreationDate="2017-12-12T20:54:53.310" UserId="7888" Text="I have OSM world data (essentially I processed the XML data into JSON containing arrays of objects (streets, buildings etc.) that each are represented by an array of lat/lon coordinates). Some of these are lines (roads etc.), others are areas that have to be filled (1st and last point close the area). &#xD;&#xA;&#xD;&#xA;Anyhow, I would like to achieve an image similiar to google maps or mapbox but much simpler as I do not require city name labels or anything of the sort. For now all I really need is roads.  &#xD;&#xA;&#xD;&#xA;I need this for a game I am making so the method itself must not be the most elegant one as I probably wont be doing this on the fly but rather prerendering the world to then send the images prerendered to the players. &#xD;&#xA;&#xD;&#xA;My question is merely, where the heck do I start? I have no idea how the rendering of bitmaps is done (or whatever other format is best.)&#xD;&#xA;&#xD;&#xA;I know C# and NodeJS and am not afraid of learning new frameworks or technologies." ContentLicense="CC BY-SA 3.0" />
  <row Id="16554" PostHistoryTypeId="1" PostId="5979" RevisionGUID="aeca85dc-9a04-431e-a42c-08e51d0f4bdd" CreationDate="2017-12-12T20:54:53.310" UserId="7888" Text="I need to build my own map renderer" ContentLicense="CC BY-SA 3.0" />
  <row Id="16555" PostHistoryTypeId="3" PostId="5979" RevisionGUID="aeca85dc-9a04-431e-a42c-08e51d0f4bdd" CreationDate="2017-12-12T20:54:53.310" UserId="7888" Text="|rendering|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16559" PostHistoryTypeId="50" PostId="5301" RevisionGUID="755e3ea8-490d-44a3-8f1c-7255678d66a1" CreationDate="2017-12-12T21:44:58.513" UserId="-1" />
  <row Id="16560" PostHistoryTypeId="2" PostId="5981" RevisionGUID="c578078f-c858-4942-b908-6b9a9cc62bf4" CreationDate="2017-12-13T09:27:14.377" UserId="7008" Text="If you have the prerendered images, you can &quot;simply&quot; render them onto a grid of quads. This is done with texturing, i.e. you upload the image to your GPU as a texture and apply texturecoordinates to quads, such that when you render the quads, the textures are applied correctly to their surfaces.&#xD;&#xA;&#xD;&#xA;You will however need to learn OpenGL (preferrably with GLSL), Direct3D with HLSL or even Vulkan, all of which will take some time. Depneding on where your goals lie, you may be better of going with a preexisting rendering engine and just learning like Unity or Unreal.&#xD;&#xA;&#xD;&#xA;If you do want to learn one of the mentioned Graphics APIs, there are numerous tutorials on the web. For OpenGL I can recommend the [youtube tutorials by ThinMatrix][1], for the other two APIs you'd need to ask someone else. Furthermore, there are splendid books online as well as offline. If you have some money to burn, the basics of rendering are covered in [Real-Time Rendering][2] and [Mathematics for 3d Game Programming and Computer Graphics][3]. In regards to OpenGL, there are the [Online Tutorials of Learn OpenGL][4], as well as offline books in [pdf][5] and [epub][6] version.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=VS8wlS9hF8E&amp;list=PLRIWtICgwaX0u7Rf9zkZhLoLuZVfUksDP&#xD;&#xA;  [2]: https://www.amazon.com/Real-Time-Rendering-Third-Tomas-Akenine-Moller/dp/1568814240&#xD;&#xA;  [3]: https://www.amazon.com/Mathematics-Programming-Computer-Graphics-Third/dp/1435458869/ref=sr_1_1?s=books&amp;ie=UTF8&amp;qid=1513157079&amp;sr=1-1&amp;keywords=mathematics%20for%203d%20game%20programming%20and%20computer%20graphics&#xD;&#xA;  [4]: https://learnopengl.com/#!Introduction&#xD;&#xA;  [5]: https://learnopengl.com/book/learnopengl_book.pdf&#xD;&#xA;  [6]: https://learnopengl.com/book/learnopengl_book.epub" ContentLicense="CC BY-SA 3.0" />
  <row Id="16561" PostHistoryTypeId="2" PostId="5982" RevisionGUID="79357451-c062-43d0-8afb-64dbe43b7691" CreationDate="2017-12-13T09:31:40.473" UserId="4546" Text="Yes, ray differentials are the way to go. The [Paper by Igehy][1] introduces them for the use case of filtered texture lookups. When generating the primary rays, you initialise the differentials to reflect the pixel footprint. As the ray progresses through the scene, you update the differentials at every bounce. When it comes to a texture lookup, you need to project the differentials to your s,t texture space (aka UV), typically by going to surface parameter space as an intermediate.&#xD;&#xA;&#xD;&#xA;The case that you mention, the calculation of derivatives for a ray surface intersection, is implemented in [pbrt][2]:&#xD;&#xA;Here the surface is described by a point p, normal n and two tangent vectors dPdu and dPdv. The resulting dudx, dudy, dvdx and dvdy are the differentials of the u, v parameters of the surface with respect to screen space x and y. Conversion from surface parameters to texture space happens [here][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/trd/trd_jpg.pdf&#xD;&#xA;  [2]: https://github.com/mmp/pbrt-v3/blob/eafd87d4ea3d6beb42f5e31a400a2158c4bee0f8/src/core/interaction.cpp#L103&#xD;&#xA;  [3]: https://github.com/mmp/pbrt-v3/blob/7095acfd8331cdefb03fe0bcae32c2fc9bd95980/src/core/texture.cpp#L93" ContentLicense="CC BY-SA 3.0" />
  <row Id="16562" PostHistoryTypeId="4" PostId="5976" RevisionGUID="5cfa8e41-336f-4209-9d4e-4ec76b295bc7" CreationDate="2017-12-13T10:18:32.047" UserId="2041" Comment="The title should express what the question is, to make it easier to find." Text="Why isn't the clear color visible on the screen between frames?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16568" PostHistoryTypeId="2" PostId="5985" RevisionGUID="5a92b5c1-d450-4ddb-b8da-3938a83de016" CreationDate="2017-12-14T01:11:05.310" UserId="6838" Text="I've been exploring the [Midpoint algorithm][1] for drawing lines and curves, and I have a quick question: How should you determine the **fast direction** for a curve? I've seen that if the shape is simple, you can draw one section and repeat the rest, but what if the shape does not have this property?&#xD;&#xA;&#xD;&#xA;Right now I'm just using the derivative(slope), so I wonder if this is correct or cheaty? :P&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Midpoint_circle_algorithm &quot;Midpoint circle algorithm&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16569" PostHistoryTypeId="1" PostId="5985" RevisionGUID="5a92b5c1-d450-4ddb-b8da-3938a83de016" CreationDate="2017-12-14T01:11:05.310" UserId="6838" Text="Midpoint Algorithm Fast Direction" ContentLicense="CC BY-SA 3.0" />
  <row Id="16570" PostHistoryTypeId="3" PostId="5985" RevisionGUID="5a92b5c1-d450-4ddb-b8da-3938a83de016" CreationDate="2017-12-14T01:11:05.310" UserId="6838" Text="|curve|2d-graphics|midpoint|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16571" PostHistoryTypeId="2" PostId="5986" RevisionGUID="dfe017a7-e1c8-4d84-9a1c-6bf3c9ddb0df" CreationDate="2017-12-14T03:32:46.393" UserId="7740" Text="I have never done this so this is just my best guess. I think you are on the track with the slope but I'm going to expand it little with some calculus. If you parameterize your curve by some variable t:&#xD;&#xA;&#xD;&#xA;x(t) = ...&#xD;&#xA;&#xD;&#xA;y(t) = ...&#xD;&#xA;&#xD;&#xA;Then you can compute dx/dt and dy/dt which is how much x or y changes as you change t. This runs into some problems on a general purpose curve though. For example dx/dt might be a function of t. This means that the rate of change of x itself is changing as you move along the curve. But then you can also find dx/dt^2 (rate of change of the rate of change) and so on. This method is known as forward differencing.&#xD;&#xA;&#xD;&#xA;Then what you can do is have an x, y starting point and draw a pixel there. Then you add the first order difference (dx/dt, dy/dt) to x and y. Then you add the second order difference to the first order difference and so on.&#xD;&#xA;&#xD;&#xA;Here is a link I found on forward differencing:&#xD;&#xA;http://www.nptel.ac.in/courses/122104018/node103.html&#xD;&#xA;&#xD;&#xA;I haven't read it but it looks promising." ContentLicense="CC BY-SA 3.0" />
  <row Id="16575" PostHistoryTypeId="5" PostId="5986" RevisionGUID="40aa2d2d-4841-4689-a5e0-d1883f5230fb" CreationDate="2017-12-14T15:00:26.863" UserId="7740" Comment="added 791 characters in body; added 49 characters in body" Text="I have never done this so this is just my best guess. I think you are on the track with the slope but I'm going to expand it little with some calculus. If you parameterize your curve by some variable t:&#xD;&#xA;&#xD;&#xA;x(t) = ...&#xD;&#xA;&#xD;&#xA;y(t) = ...&#xD;&#xA;&#xD;&#xA;Then you can compute dx/dt and dy/dt which is how much x or y changes as you change t. This runs into some problems on a general purpose curve though. For example dx/dt might be a function of t. This means that the rate of change of x itself is changing as you move along the curve. But then you can also find dx/dt^2 (rate of change of the rate of change) and so on. This method is known as forward differencing.&#xD;&#xA;&#xD;&#xA;Then what you can do is have an x, y starting point and draw a pixel there. Then you add the first order difference (dx/dt, dy/dt) to x and y. Then you add the second order difference to the first order difference and so on.&#xD;&#xA;&#xD;&#xA;Here is a link I found on forward differencing:&#xD;&#xA;http://www.nptel.ac.in/courses/122104018/node103.html&#xD;&#xA;&#xD;&#xA;I haven't read it but it looks promising.&#xD;&#xA;&#xD;&#xA;--edit--&#xD;&#xA;&#xD;&#xA;Here's an example that was derived in my computer graphics class:&#xD;&#xA;Some of the algebra can be tricky so it may or may not be correct.&#xD;&#xA;&#xD;&#xA;    Q(t) = a*t^3 + b*t^2 + c*t + k&#xD;&#xA;    0 &lt; t &lt; 1&#xD;&#xA;    segment size d&#xD;&#xA;    num segments: 1/d&#xD;&#xA;&#xD;&#xA;    Q1(t) = Q(t + d) - Q(t)&#xD;&#xA;    = 3*a*d*t^2 + 3*a*t*d^2 + a*d^3 + 2*b + d + b*d^2 + c*d&#xD;&#xA;&#xD;&#xA;    Q2(t) = Q1(t + d) - Q1(t)&#xD;&#xA;    = b*a*t*d^2 + 6*a*d^3 + 2*b*d^2&#xD;&#xA;&#xD;&#xA;    Q3(t) = Q2(t + d) - Q2(t)&#xD;&#xA;    = b*a*d^3      &lt;==== no longer depends on t!&#xD;&#xA;&#xD;&#xA;Iterate:&#xD;&#xA;&#xD;&#xA;    Q  = Q(0)  = k&#xD;&#xA;    Q1 = Q1(0) = a*d^3 + b*d^2 + c*d&#xD;&#xA;    Q2 = Q2(0) = b*a*d^3 + 2*b*d&#xD;&#xA;    Q3 = Q3(0) = b*a*d^3&#xD;&#xA;&#xD;&#xA;    repeat 1/d times:&#xD;&#xA;        drawLine(Q, Q + Q1)&#xD;&#xA;        Q  += Q1&#xD;&#xA;        Q1 += Q2&#xD;&#xA;        Q2 += Q3&#xD;&#xA;&#xD;&#xA;Q is just for one of the x or y variables. You could also extend this into as many dimensions as you like." ContentLicense="CC BY-SA 3.0" />
  <row Id="16576" PostHistoryTypeId="5" PostId="5986" RevisionGUID="761926da-52cf-4135-942c-5ecbb8716c7f" CreationDate="2017-12-14T15:05:30.660" UserId="7740" Comment="added 791 characters in body; added 49 characters in body" Text="I have never done this so this is just my best guess. I think you are on the track with the slope but I'm going to expand it little with some calculus. If you parameterize your curve by some variable t:&#xD;&#xA;&#xD;&#xA;x(t) = ...&#xD;&#xA;&#xD;&#xA;y(t) = ...&#xD;&#xA;&#xD;&#xA;Then you can compute dx/dt and dy/dt which is how much x or y changes as you change t. This runs into some problems on a general purpose curve though. For example dx/dt might be a function of t. This means that the rate of change of x itself is changing as you move along the curve. But then you can also find dx/dt^2 (rate of change of the rate of change) and so on. This method is known as forward differencing.&#xD;&#xA;&#xD;&#xA;Then what you can do is have an x, y starting point and draw a pixel there. Then you add the first order difference (dx/dt, dy/dt) to x and y. Then you add the second order difference to the first order difference and so on.&#xD;&#xA;&#xD;&#xA;Here is a link I found on forward differencing:&#xD;&#xA;http://www.nptel.ac.in/courses/122104018/node103.html&#xD;&#xA;&#xD;&#xA;I haven't read it but it looks promising.&#xD;&#xA;&#xD;&#xA;--edit--&#xD;&#xA;&#xD;&#xA;Here's an example that was derived in my computer graphics class:&#xD;&#xA;Some of the algebra can be tricky so it may or may not be correct.&#xD;&#xA;&#xD;&#xA;    Q(t) = a*t^3 + b*t^2 + c*t + k&#xD;&#xA;    0 &lt; t &lt; 1&#xD;&#xA;    segment size d&#xD;&#xA;    num segments: 1/d&#xD;&#xA;&#xD;&#xA;    Q1(t) = Q(t + d) - Q(t)&#xD;&#xA;    = 3*a*d*t^2 + 3*a*t*d^2 + a*d^3 + 2*b + d + b*d^2 + c*d&#xD;&#xA;&#xD;&#xA;    Q2(t) = Q1(t + d) - Q1(t)&#xD;&#xA;    = b*a*t*d^2 + 6*a*d^3 + 2*b*d^2&#xD;&#xA;&#xD;&#xA;    Q3(t) = Q2(t + d) - Q2(t)&#xD;&#xA;    = b*a*d^3      &lt;==== no longer depends on t!&#xD;&#xA;&#xD;&#xA;Iterate:&#xD;&#xA;&#xD;&#xA;    init variables:&#xD;&#xA;    Q  = Q(0)  = k&#xD;&#xA;    Q1 = Q1(0) = a*d^3 + b*d^2 + c*d&#xD;&#xA;    Q2 = Q2(0) = b*a*d^3 + 2*b*d&#xD;&#xA;    Q3 = Q3(0) = b*a*d^3&#xD;&#xA;&#xD;&#xA;    repeat 1/d times:&#xD;&#xA;        drawLine(Q, Q + Q1)&#xD;&#xA;        Q  += Q1&#xD;&#xA;        Q1 += Q2&#xD;&#xA;        Q2 += Q3&#xD;&#xA;&#xD;&#xA;Q is just for one of the x or y variables. You could have a QX, QX1, ... and QY, QY1, ... and forward difference them both in the same loop. Then draw using (QX, QY) and (QX + QX1, QY + QY1). You could also extend this into as many dimensions as you like." ContentLicense="CC BY-SA 3.0" />
  <row Id="16578" PostHistoryTypeId="50" PostId="5821" RevisionGUID="58f5dad8-96a4-42d9-a784-8a91f16a99ed" CreationDate="2017-12-14T17:59:46.260" UserId="-1" />
  <row Id="16579" PostHistoryTypeId="50" PostId="5730" RevisionGUID="be4de838-e971-4790-8bd7-c7075b8105c0" CreationDate="2017-12-14T18:59:35.237" UserId="-1" />
  <row Id="16583" PostHistoryTypeId="2" PostId="5988" RevisionGUID="48cf6e31-aeab-44f8-9ec4-d20cd7f5fbac" CreationDate="2017-12-15T11:18:29.250" UserId="6806" Text="I'm doing a project with assimp.&#xD;&#xA;&#xD;&#xA;I got confused with the weird situation for me.&#xD;&#xA;I think the both code are exactly same, but the result is different.&#xD;&#xA;&#xD;&#xA;Why the codes act differently?&#xD;&#xA;&#xD;&#xA; (vertex shader)&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout (location = 0) in vec3 aPos;&#xD;&#xA;    layout (location = 1) in vec3 aNormal;&#xD;&#xA;    layout (location = 2) in vec2 aTexCoords;&#xD;&#xA;&#xD;&#xA;    // declare an interface block; see 'Advanced GLSL' for what these are.&#xD;&#xA;    out VS_OUT {&#xD;&#xA;        vec2 TexCoords;&#xD;&#xA;    } vs_out;&#xD;&#xA;&#xD;&#xA;    out vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	    TexCoords = aTexCoords; ----(1)&#xD;&#xA;	    //vs_out.TexCoords = aTexCoords; ----(2) &#xD;&#xA;	    gl_Position = projection * view * model * vec4(aPos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;(fragment shader)&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;&#xD;&#xA;    in VS_OUT {&#xD;&#xA;        vec2 TexCoords;&#xD;&#xA;    } fs_in;&#xD;&#xA;&#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D texture_diffuse1;&#xD;&#xA;    uniform vec3 lightPos;&#xD;&#xA;    uniform vec3 viewPos;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        FragColor = vec4(texture(texture_diffuse1, TexCoords).rgb, 1.0); ----(1)&#xD;&#xA;	    //FragColor = vec4(texture(texture_diffuse1, fs_in.TexCoords).rgb, 1.0); ----(2)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I use the code above, the result is as follows&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;but, instead of (1) pair, if I use the pair (2), then the result is strange.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/A70UG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OjMQb.png&#xD;&#xA;&#xD;&#xA;Why it happened?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16584" PostHistoryTypeId="1" PostId="5988" RevisionGUID="48cf6e31-aeab-44f8-9ec4-d20cd7f5fbac" CreationDate="2017-12-15T11:18:29.250" UserId="6806" Text="What's the difference between two code in shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16585" PostHistoryTypeId="3" PostId="5988" RevisionGUID="48cf6e31-aeab-44f8-9ec4-d20cd7f5fbac" CreationDate="2017-12-15T11:18:29.250" UserId="6806" Text="|opengl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16586" PostHistoryTypeId="2" PostId="5989" RevisionGUID="3debabbd-8782-45a7-87b1-bed4b4d1ba5c" CreationDate="2017-12-15T11:30:10.510" UserId="7107" Text="*I don't have enough rep to comment :(*&#xD;&#xA;&#xD;&#xA;Hi,&#xD;&#xA;&#xD;&#xA;It looks like with (2), fs_in.TexCoords is == vec2(0.0,0.0). Do you keep both ***in VS_OUT {}/ out VS_OUT {}*** and ***out vec2/in vec2*** ? If so, it's possible that as both have the same name (TexCoords) the compiler is confused. Try using only one of the two options." ContentLicense="CC BY-SA 3.0" />
  <row Id="16588" PostHistoryTypeId="2" PostId="5991" RevisionGUID="43c36d07-9be9-41cd-bb47-e4443bffb1fd" CreationDate="2017-12-15T21:54:40.427" UserId="7906" Text="I am trying to take either a HDR panoramic or HDR cubeMap and from that create a Lambert Irradiance environment map and a Cook-Torrence Specular environment map.&#xD;&#xA;&#xD;&#xA;I am stuck at the proper implementation to get the samples using Hammersley and importance sampling and then placing them on my target image. &#xD;&#xA;&#xD;&#xA;This is essentially a pre-filtering environment maps question in C#" ContentLicense="CC BY-SA 3.0" />
  <row Id="16589" PostHistoryTypeId="1" PostId="5991" RevisionGUID="43c36d07-9be9-41cd-bb47-e4443bffb1fd" CreationDate="2017-12-15T21:54:40.427" UserId="7906" Text="How to make Convolved Diffuse and Specular image in C#" ContentLicense="CC BY-SA 3.0" />
  <row Id="16590" PostHistoryTypeId="3" PostId="5991" RevisionGUID="43c36d07-9be9-41cd-bb47-e4443bffb1fd" CreationDate="2017-12-15T21:54:40.427" UserId="7906" Text="|image-processing|pbr|image|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16592" PostHistoryTypeId="2" PostId="5992" RevisionGUID="fbaf567a-4f9b-40a8-818a-856fce6cb176" CreationDate="2017-12-16T00:40:01.720" UserId="7907" Text="So I have this racing game I'm trying to modify that uses lightmaps that fade to transparency for light sources. An example from the game:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I've been trying to produce a similar effect but with no luck. I've tried blender but that doesn't support transparency off of light sources, if anyone has any program ideas I'd greatly appreciate it! &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9SLZM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/X5i6H.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16593" PostHistoryTypeId="1" PostId="5992" RevisionGUID="fbaf567a-4f9b-40a8-818a-856fce6cb176" CreationDate="2017-12-16T00:40:01.720" UserId="7907" Text="What program can bake transparent light maps?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16594" PostHistoryTypeId="3" PostId="5992" RevisionGUID="fbaf567a-4f9b-40a8-818a-856fce6cb176" CreationDate="2017-12-16T00:40:01.720" UserId="7907" Text="|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16601" PostHistoryTypeId="2" PostId="5994" RevisionGUID="d2a5a4cc-0d6c-4131-812c-21446c7b4f6f" CreationDate="2017-12-16T07:28:26.923" UserId="6938" Text="I am a bit confused in terms of directional light calculation in OpenGL. Generally we care about the direction of the directional light and we use it with the normal and view (toCamera) vector to calculate lighting. Let's say I do my calculation in view-space ... would I need to multiply the direction of the directional light with ViewMatrix (and then normalize) ? I tried both and they don't seem to make a difference ... I'm leaning towards &quot;yes I need to do that&quot;. Is this correct? Here's part of my fragment shader that does lighting for directional light:&#xD;&#xA;&#xD;&#xA;    vec4 calculateDirectionalLightIntensities(in vec3 N, in vec3 V)&#xD;&#xA;    {&#xD;&#xA;    	vec4 result = vec4(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    	for(int i=0; i&lt;DirectionalLightCount; ++i)&#xD;&#xA;    	{&#xD;&#xA;    		//vec3 L = normalize( (ViewMatrix * -vec4(DirectionalLightDirections[i], 0.0)).xyz );&#xD;&#xA;    		vec3 L = normalize(-DirectionalLightDirections[i].xyz);&#xD;&#xA;    		vec4 currentResult = calculateDiffuse(N, L);&#xD;&#xA;    		currentResult += calculateSpecular(N, L, V);&#xD;&#xA;    		currentResult *= DirectionalLightIntensities[i];&#xD;&#xA;    		result += currentResult;&#xD;&#xA;    	}&#xD;&#xA;    	return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Basically N would be the normal vector and V is vector pointing towards camera in view-space and it is calculated as:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	normal = normalize(NormalMatrix * vec4(NORMAL, 0.0)).xyz;		//We use 0 because normals are directional vectors&#xD;&#xA;    	uv0 = TEXCOORD0;&#xD;&#xA;    &#xD;&#xA;    	vec4 viewSpacePosition = ModelViewMatrix * vec4(POSITION, 1.0);&#xD;&#xA;    &#xD;&#xA;    #if defined(BLINN_PHONG_LIGHTING)&#xD;&#xA;    &#xD;&#xA;    	toCamera = -viewSpacePosition.xyz; //CALCULATED HERE&#xD;&#xA;    &#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    	gl_Position = ProjectionMatrix * viewSpacePosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Should I be multiplying my dir of directional light in the vertex shader? If so, is there a performance hit to having multiple lights that results in having array of varying variables being set to the fragment shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16602" PostHistoryTypeId="1" PostId="5994" RevisionGUID="d2a5a4cc-0d6c-4131-812c-21446c7b4f6f" CreationDate="2017-12-16T07:28:26.923" UserId="6938" Text="Directional Light ViewSpace Calculation" ContentLicense="CC BY-SA 3.0" />
  <row Id="16603" PostHistoryTypeId="3" PostId="5994" RevisionGUID="d2a5a4cc-0d6c-4131-812c-21446c7b4f6f" CreationDate="2017-12-16T07:28:26.923" UserId="6938" Text="|opengl|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16604" PostHistoryTypeId="2" PostId="5995" RevisionGUID="9ea9bb30-daaf-4c64-92fd-7dfc57311164" CreationDate="2017-12-16T17:24:03.753" UserId="6202" Text="This is general question.&#xD;&#xA;In the multitude of video-games that are not specialized in scoped warfare (like Sniper Elite), I've noticed that when you zoom in with a scope, the textures and normal maps won't &quot;update&quot;.&#xD;&#xA;&#xD;&#xA;You're standing on coordinate $(0,0,0)$ and the textures will load in full quality to some other $R^3$ coordinate, let's say $(10,10,10)$.    &#xD;&#xA;If you look through a scope from $(0,0,0)$ past the &quot;Max quality&quot; distance, let's say $(10+n,10+n,10+n)$ (where $n$ is the zoom in factor), the zoomed in textures will not updated as if you were standing on the coordinate $(n,n,n)$.    &#xD;&#xA;The best example is the Fallout 4 scope zoom-in.    &#xD;&#xA;If you zoom in anywhere, the distant textures to which you zoom in will look washed out.   &#xD;&#xA;What are the solutions to such problems? Are they engine related? I've just started to dabble in OpenGL and noticed that problem on the multitude of games which share the same game engine." ContentLicense="CC BY-SA 3.0" />
  <row Id="16605" PostHistoryTypeId="1" PostId="5995" RevisionGUID="9ea9bb30-daaf-4c64-92fd-7dfc57311164" CreationDate="2017-12-16T17:24:03.753" UserId="6202" Text="Video-games; Rendering textures on scope zoom-in. Texture compression problem?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16606" PostHistoryTypeId="3" PostId="5995" RevisionGUID="9ea9bb30-daaf-4c64-92fd-7dfc57311164" CreationDate="2017-12-16T17:24:03.753" UserId="6202" Text="|texture|vectors|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16607" PostHistoryTypeId="2" PostId="5996" RevisionGUID="9b18baa6-4bd5-4fbf-9cfc-3d34668f3acd" CreationDate="2017-12-16T18:54:29.433" UserId="7412" Text="I'm developing a CAD drawing generator using C# and netdxf library (https://github.com/haplokuon/netDxf)&#xD;&#xA;&#xD;&#xA;The app first performs boolean operations (specifically - union &amp; subtraction) on polygons and draws the resultant path on .dxf file.&#xD;&#xA;&#xD;&#xA;I'm using Angus johnson's Clipper library (http://www.angusj.com/delphi/clipper.php) for clipping &#xD;&#xA;&#xD;&#xA;Everything works fine for polygons, The problem is when I need to clip circles and polygons, the result is a large list of points (representing the path of the figure to be drawn on dxf)&#xD;&#xA;&#xD;&#xA;So the curved portion of the path is composed of tiny segments, which is a big problem for the CAM software that'd be used later. &#xD;&#xA;&#xD;&#xA;Below is such an image (the result of clipping circle and polygon). The grey portion is full of tiny line segments&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Questions - &#xD;&#xA;&#xD;&#xA;1) How can I convert those tiny line segments to circles/arcs using the list of points?&#xD;&#xA;&#xD;&#xA;2) Can I take a completely different approach to avoid this problem?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NioSC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16608" PostHistoryTypeId="1" PostId="5996" RevisionGUID="9b18baa6-4bd5-4fbf-9cfc-3d34668f3acd" CreationDate="2017-12-16T18:54:29.433" UserId="7412" Text="Clipping circle and polygon and generate a CAD drawing" ContentLicense="CC BY-SA 3.0" />
  <row Id="16609" PostHistoryTypeId="3" PostId="5996" RevisionGUID="9b18baa6-4bd5-4fbf-9cfc-3d34668f3acd" CreationDate="2017-12-16T18:54:29.433" UserId="7412" Text="|polygon|clipping|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16614" PostHistoryTypeId="2" PostId="5998" RevisionGUID="7b5c65f2-25e3-4a60-8803-c2b1175b1cf8" CreationDate="2017-12-17T00:59:28.990" UserId="7740" Text="Well there's no way to know for sure unless you look at the source code but my guess is that they do zooming by lowering the FOV (field of view) of the camera. This is easy to implement and actually sort of represents how a real scope works (in the way that light rays are bent through an optical lens). A zoom effect where you change the actual position of the camera might be more trouble than its worth. What if there is an object between the player and the desired camera position? So as you can see, the camera position has not changed at all and so there is no reason the textures would update when zooming.&#xD;&#xA;&#xD;&#xA;Now you would think that hey maybe they could just scale the distance required to trigger the higher detail textures as the player zooms in but this may or may not be easy depending on how that is implemented in the engine. The game developers may not even be able to change LOD (level of detail) distances dynamically. Like you said, games like sniper elite which are based all around sniping have dealt with this but general purpose game engines might not have this functionality.&#xD;&#xA;&#xD;&#xA;Also you have to consider possible popping effects. If you zoom in to an area and suddenly the textures and meshes update dramatically, this would look very bad. This gets even worse if the zoom effect is gradual or the sight is adjustable. I would even go as far as to say that it might be preferable to have lower quality textures than to have really bad popping." ContentLicense="CC BY-SA 3.0" />
  <row Id="16615" PostHistoryTypeId="2" PostId="5999" RevisionGUID="677c7fcb-9141-413b-9475-c6bdce727837" CreationDate="2017-12-17T01:25:32.843" UserId="6" Text="It just depends on which space your light directions are actually specified in. You compute both your normal and view vector correctly in view space in order to perform your lighting computations in view space. So **you need your normalized light direction in view space**, too.&#xD;&#xA;&#xD;&#xA;So it depends on how you actually transfer your light direction into the shader. Usually it's best to **transform the light direction into view space before uploading it to the shader** (from whatever space it's originally in in the scene, likely some kind of object space local to a certain light source, but in case of a directional light maybe already in world/view space). This has a few advantages:&#xD;&#xA;&#xD;&#xA;- As you realized yourself already, you won't have to perform a tedious matrix transformation for each and every vertex when the light is actiually constant for all vertices of a draw call (it's probably a `uniform` variable). While a matrix multiplication per-vertex doesn't really kill anyone, there's really no need to do that extra work, in contrast to simply transforming the light direction on the CPU once a frame.&#xD;&#xA;&#xD;&#xA;- But there's another problem to transforming it in every shader call. Usually your light direction isn't easily specified in object space at all (or not the local object space of whatever object your currently drawing). If anything, it comes from a local light source that has its *own* model transformation, but that is *not* the one encapsulated in the current modelview matrix, which usually depends on the model you're drawing. So using the modelview matrix you transform your vertices with is most likely the wrong way. You could use the view matrix (as you do) if it is specified in world space already, but as said above, that's usually not necessary.&#xD;&#xA;&#xD;&#xA;So what you do **depends on the space in which your light direction is stored** in the scene. If it is stored in world space (e.g. the sun as the directional light example par-excellence), you just have to transform it into view space (e.g. by multiplying it with the camera/view matrix) right before uploading it into the shader (i.e. likely each frame, since it's view dependent). If it is actually view *independent* (e.g. a kind of &quot;flashlight&quot; always shining straight into the camera direction), you don't really have to transform it at all. And if it's local to some specific scene object (more appropriate for point light sources, though), you transform it by *that object*'s modelview matrix." ContentLicense="CC BY-SA 3.0" />
  <row Id="16616" PostHistoryTypeId="2" PostId="6000" RevisionGUID="79234528-3fed-4e9d-955a-29d3e8936471" CreationDate="2017-12-17T21:59:40.770" UserId="7740" Text="I don't know how the clipping library you are using returns the clipped objects, but if I understand your question, you want a way to represent your circles that does not use much memory? If you are only using perfect circles (and not ellipses) you could represent each arc segment as simply an origin point, a radius, and a start/stop angle.&#xD;&#xA;&#xD;&#xA;This is the part where it would be helpful to know what the clipping library returns. If it returns a chain of points as a separate object for each clipped arc segment, and you already know the radius and center of the circle (from before clipping), you could take the first and last point in the returned chain and compute the angle for each.&#xD;&#xA;&#xD;&#xA;    atan2(x - origin.x, y - origin.y)&#xD;&#xA;&#xD;&#xA;Then when you would like to draw the thing, you can write and algorithm to trace the arc going from the start to stop angle. If you want to do further clipping, you could recreate the arc as a chain of points.&#xD;&#xA;&#xD;&#xA;Be careful about whether the returned segment was clockwise or counterclockwise." ContentLicense="CC BY-SA 3.0" />
  <row Id="16617" PostHistoryTypeId="2" PostId="6001" RevisionGUID="4fe54f33-1752-4151-ba91-bd93c6840efa" CreationDate="2017-12-17T22:08:49.800" UserId="7740" Text="Not sure what sort of lightmaps are produced by blender. Perhaps if you can get it to render a non-transparent lightmap (for example one that has all the colours you want but on a black background), you could then use a program to remove all of the black. I believe GIMP and Photoshop both have a colour to alpha tool. Be sure to pick a background colour that will not be the same colour as any of the lights." ContentLicense="CC BY-SA 3.0" />
  <row Id="16618" PostHistoryTypeId="2" PostId="6002" RevisionGUID="1985d98c-ccab-444a-8c1a-488a809aa8ed" CreationDate="2017-12-18T01:52:36.257" UserId="7915" Text="I'm writing an OpenGL application that runs on a Raspberry Pi, i.e., a quite resource-limited system. Essentially, a few quads with RGBA textures are overlayed/alpha blended on top of each other with individual translation/rotation applied. They are clipped against an unrotated rectangle.&#xD;&#xA;&#xD;&#xA;For this purpose, I currently use the stencil buffer. I.e., when drawing a texture which requires clipping, I clear the stencil buffer, render the clipping quad to the stencil buffer and enable the stencil testing before rendering the translated/rotated object.&#xD;&#xA;&#xD;&#xA;On a Pi, clearing the stencil buffer is a painfully slow process in the order of 20ms, completely ruining performace. I thought about pre-rending the clipping rects to different bits of the stencil buffer, but that would lead to a maximum of 8 clipping regions (I need more).&#xD;&#xA;&#xD;&#xA;Therefore, is there a different way of achieving clipping against a simple rectangle that does not require an expensive operation such as flushing the stencil buffer?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16619" PostHistoryTypeId="1" PostId="6002" RevisionGUID="1985d98c-ccab-444a-8c1a-488a809aa8ed" CreationDate="2017-12-18T01:52:36.257" UserId="7915" Text="Fast clipping without clearing stencil buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="16620" PostHistoryTypeId="3" PostId="6002" RevisionGUID="1985d98c-ccab-444a-8c1a-488a809aa8ed" CreationDate="2017-12-18T01:52:36.257" UserId="7915" Text="|opengl|clipping|legacy-opengl|stencil-test|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16621" PostHistoryTypeId="2" PostId="6003" RevisionGUID="92495af4-ff86-49fc-8b85-1c80cee91b9c" CreationDate="2017-12-18T03:18:07.663" UserId="5183" Text="Suppose we have a volume filled with small surfaces.  If we cast a ray from a given point, the probability that the ray will not hit a surface (is visible to the sky) is given as &#xD;&#xA;&#xD;&#xA;$P(ray\ does\ not\ hit) = exp(-\alpha d/\cos\theta)$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is some decay factor, $d/cos\theta$ is the path length of the ray within the volume.&#xD;&#xA;&#xD;&#xA;How can we compute the expected visibility of a ray if we consider the directions $(\theta, \phi)$, where $0&lt;\theta&lt;\pi/2$ and $0&lt;\phi&lt;2\pi$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16622" PostHistoryTypeId="1" PostId="6003" RevisionGUID="92495af4-ff86-49fc-8b85-1c80cee91b9c" CreationDate="2017-12-18T03:18:07.663" UserId="5183" Text="Expected visibility" ContentLicense="CC BY-SA 3.0" />
  <row Id="16623" PostHistoryTypeId="3" PostId="6003" RevisionGUID="92495af4-ff86-49fc-8b85-1c80cee91b9c" CreationDate="2017-12-18T03:18:07.663" UserId="5183" Text="|ambient-occlusion|ray|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16624" PostHistoryTypeId="2" PostId="6004" RevisionGUID="640e68a4-ce91-494b-b8e3-4018ab396fd8" CreationDate="2017-12-18T05:02:41.307" UserId="1937" Text="It sounds like what you need is a [scissor test][1]. It's specifically designed for clipping against an unrotated rectangle, and should be faster than messing about with the stencil buffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Scissor_Test" ContentLicense="CC BY-SA 3.0" />
  <row Id="16625" PostHistoryTypeId="2" PostId="6005" RevisionGUID="167982f3-3c9c-43f2-819a-36821a821e28" CreationDate="2017-12-18T05:35:40.620" UserId="7740" Text="You could try clipping the polygons in code before you send them off to the renderer. Then you could avoid the stencil buffer entirely. To do this you could clip against all sides of the rectangle one at a time. I can't say for sure if this is faster than what you were doing before but here goes:&#xD;&#xA;&#xD;&#xA;For this algorithm you need to represent a polygon as a list of points&#xD;&#xA;&#xD;&#xA;How to clip against one side:&#xD;&#xA;&#xD;&#xA;    # careful of array out of bounds access&#xD;&#xA;    k = -1&#xD;&#xA;    # find first instance where a vertex is outside followed by one that is inside&#xD;&#xA;    for(i = 0; i &lt; verts.length; ++i)&#xD;&#xA;        if(isOutside(verts[i]) &amp;&amp; !isOutside(verts[i + 1]))&#xD;&#xA;            k = i&#xD;&#xA;    # if no such instance found&#xD;&#xA;    if(k == -1)&#xD;&#xA;        if(isOutside(verts[0])) # entire thing outside&#xD;&#xA;            return empty array&#xD;&#xA;        else # entire thing inside&#xD;&#xA;            return verts # return unchanged&#xD;&#xA;    # if instance was found&#xD;&#xA;    else&#xD;&#xA;        newVerts = empty array&#xD;&#xA;        # add first vertex in new shape&#xD;&#xA;        newVerts.add(intersect(verts[k], verts[k + 1]))&#xD;&#xA;        # walk the part of the polygon that is inside&#xD;&#xA;        while(!isOutside(verts[++k]))&#xD;&#xA;            newVerts.add(verts[k])&#xD;&#xA;        # add last vertex in new shape&#xD;&#xA;        newVerts.add(intersect(verts[k - 1], verts[k]))&#xD;&#xA;        return newVerts&#xD;&#xA;&#xD;&#xA;Then you could do something like:&#xD;&#xA;&#xD;&#xA;    poly = clipLeftEdge(poly)&#xD;&#xA;    poly = clipRightEdge(poly)&#xD;&#xA;    poly = clipTopEdge(poly)&#xD;&#xA;    poly = clipBottomEdge(poly)&#xD;&#xA;&#xD;&#xA;If the the original polygon was convex then the new one should be as well which means you could triangulate it or whatever you need before you draw.&#xD;&#xA;&#xD;&#xA;A line which forms an edge of the clipping rectangle (if you extend it to be infinitely long) splits the entire space into 2 half spaces. You will need to provide a function to check whether a vertex is in the &quot;inside&quot; half space or the &quot;outside&quot; half space. Ex: left edge of rectangle is at x = -15. To check if the point is outside, do (point.x &lt; -15).&#xD;&#xA;&#xD;&#xA;You will also need to provide a function to intersect 2 vertices. You have one vertex on the outside and one on the inside and somewhere in between there is a line that you want to clip against. For example if the left edge of the rectangle is at x = -15:&#xD;&#xA;&#xD;&#xA;    factor = (-15 - p1.x)/(p2.x - p1.x)&#xD;&#xA;    newVertex.x = -15&#xD;&#xA;    newVertex.y = (p2.y - p1.y)*factor + p1.y&#xD;&#xA;&#xD;&#xA;You will also need to linearly interpolate all other attributes you care about (like texture coordinates).&#xD;&#xA;&#xD;&#xA;If you want to be really slick, you can write the clipping algorithm once and provide an appropriate isOutside and intersect function for each run." ContentLicense="CC BY-SA 3.0" />
  <row Id="16627" PostHistoryTypeId="2" PostId="6006" RevisionGUID="d18b4985-c486-40d0-a8b4-fb0e45633419" CreationDate="2017-12-18T08:00:32.367" UserId="5545" Text="In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same &quot;low-poly&quot; lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.&#xD;&#xA;&#xD;&#xA;I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.&#xD;&#xA;&#xD;&#xA;I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the *viewer* is slightly different, depending on where the tri is relative to the viewer.&#xD;&#xA;&#xD;&#xA;A brute force solution would be to store a special &quot;location&quot; for each vertex of each tri, and set &quot;location&quot; to the same value for each of the 4 verices of the two tris forming the square.&#xD;&#xA;&#xD;&#xA;But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any *per vertex* data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have *per tri* data?&#xD;&#xA;&#xD;&#xA;&gt; **EDIT** I currently have *per vertex* normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as *per tri*, since only one tri is provoked by each vertex. I could give the same &quot;location&quot; to both tris in a quad this way. But it's still brute force - is there a better way?&#xD;&#xA;&#xD;&#xA;Or, can you tell which tri of a quad you're in, so you can decide what it's &quot;location&quot; should be?&#xD;&#xA;&#xD;&#xA;It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16628" PostHistoryTypeId="1" PostId="6006" RevisionGUID="d18b4985-c486-40d0-a8b4-fb0e45633419" CreationDate="2017-12-18T08:00:32.367" UserId="5545" Text="Same specular lighting on both tris in a quad (for &quot;low-poly&quot;)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16629" PostHistoryTypeId="3" PostId="6006" RevisionGUID="d18b4985-c486-40d0-a8b4-fb0e45633419" CreationDate="2017-12-18T08:00:32.367" UserId="5545" Text="|shader|mesh|specular|opengl-es|android|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16630" PostHistoryTypeId="2" PostId="6007" RevisionGUID="8bf1396a-ac3a-48f3-9815-d8d924fc9f2f" CreationDate="2017-12-18T09:54:06.533" UserId="209" Text="As per [Russ's answer][1], I'd also suggest using scissor rectangles but, on the off-chance that is also slow, is it possible to use the Z buffer to set the Z to &quot;near&quot; in the regions you don't want drawn? &#xD;&#xA;&#xD;&#xA;BTW, it would be useful to have an example image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/6004/209" ContentLicense="CC BY-SA 3.0" />
  <row Id="16631" PostHistoryTypeId="2" PostId="6008" RevisionGUID="c29c092c-bad9-4486-8adc-cd9fbe0563c4" CreationDate="2017-12-18T10:47:13.770" UserId="7915" Text="I'm rendering fonts using Cairo to surfaces, convert those surfaces to RGBA textures and then display them on GL_QUADS using orthotogonal projection and alpha blending. When I use Cairo to render directly to the window (i.e., without hardware acceleration), fonts look perfect. When I show them through OpenGL, they look &quot;thinned&quot;. Example: https://imgur.com/a/qgyUN&#xD;&#xA;&#xD;&#xA;My textures are powers of two and I do not currently use any scaling (i.e., use the texture coordinates to only show the portion of the texture that actually contains data). I've also tried using the full texture and scaling in the Cairo drawing matrix (i.e., upscaling by Cairo, downloading by OpenGL) which looks even worse.&#xD;&#xA;&#xD;&#xA;I believe this has something to do with GL's interpolation, but cannot seem to figure out why it is. What can I do to make my font textures look more true to their original?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16632" PostHistoryTypeId="1" PostId="6008" RevisionGUID="c29c092c-bad9-4486-8adc-cd9fbe0563c4" CreationDate="2017-12-18T10:47:13.770" UserId="7915" Text="Fonts rendered through textures look thinned" ContentLicense="CC BY-SA 3.0" />
  <row Id="16633" PostHistoryTypeId="3" PostId="6008" RevisionGUID="c29c092c-bad9-4486-8adc-cd9fbe0563c4" CreationDate="2017-12-18T10:47:13.770" UserId="7915" Text="|opengl|legacy-opengl|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16634" PostHistoryTypeId="5" PostId="6008" RevisionGUID="eaf9c589-f127-4620-afe2-493bb65dc64c" CreationDate="2017-12-18T10:54:14.647" UserId="7915" Comment="added 110 characters in body" Text="I'm rendering fonts using Cairo to surfaces, convert those surfaces to RGBA textures and then display them on GL_QUADS using orthotogonal projection and alpha blending. When I use Cairo to render directly to the window (i.e., without hardware acceleration), fonts look perfect. When I show them through OpenGL, they look &quot;thinned&quot;. Example: https://imgur.com/a/qgyUN&#xD;&#xA;&#xD;&#xA;My textures are powers of two and I do not currently use any scaling (i.e., use the texture coordinates to only show the portion of the texture that actually contains data). I've also tried using the full texture and scaling in the Cairo drawing matrix (i.e., upscaling by Cairo, downloading by OpenGL) which looks even worse.&#xD;&#xA;&#xD;&#xA;I believe this has something to do with GL's interpolation, but cannot seem to figure out why it is. When I disable the bilinear GL_LINEAR texture interpolation to GL_NEAREST, they look even worse (and blocky, as if it'd ignore the alpha channel). What can I do to make my font textures look more true to their original?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16635" PostHistoryTypeId="5" PostId="6008" RevisionGUID="66df99bb-69c5-45ed-808e-3cf4f7bb14d3" CreationDate="2017-12-18T11:02:27.317" UserId="7915" Comment="edited body" Text="I'm rendering fonts using Cairo to surfaces, convert those surfaces to RGBA textures and then display them on GL_QUADS using orthotogonal projection and alpha blending. When I use Cairo to render directly to the window (i.e., without hardware acceleration), fonts look perfect. When I show them through OpenGL, they look &quot;thinned&quot;. Example: https://i.stack.imgur.com/DkPbP.jpg&#xD;&#xA;&#xD;&#xA;My textures are powers of two and I do not currently use any scaling (i.e., use the texture coordinates to only show the portion of the texture that actually contains data). I've also tried using the full texture and scaling in the Cairo drawing matrix (i.e., upscaling by Cairo, downloading by OpenGL) which looks even worse.&#xD;&#xA;&#xD;&#xA;I believe this has something to do with GL's interpolation, but cannot seem to figure out why it is. When I disable the bilinear GL_LINEAR texture interpolation to GL_NEAREST, they look even worse (and blocky, as if it'd ignore the alpha channel). What can I do to make my font textures look more true to their original?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16636" PostHistoryTypeId="5" PostId="6008" RevisionGUID="b9503aba-fe3b-4344-be75-754a14878e20" CreationDate="2017-12-18T11:27:28.713" UserId="7915" Comment="added 5 characters in body" Text="I'm rendering fonts using Cairo to surfaces, convert those surfaces to RGBA textures and then display them on GL_QUADS using orthotogonal projection and alpha blending. When I use Cairo to render directly to the window (i.e., without hardware acceleration), fonts look perfect. When I show them through OpenGL, they look &quot;thinned&quot;. Example: https://i.stack.imgur.com/DkPbP.jpg&#xD;&#xA;&#xD;&#xA;My texture sizes are powers of two and I do not currently use any scaling (i.e., use the texture coordinates to only show the portion of the texture that actually contains data). I've also tried using the full texture and scaling in the Cairo drawing matrix (i.e., upscaling by Cairo, downloading by OpenGL) which looks even worse.&#xD;&#xA;&#xD;&#xA;I believe this has something to do with GL's interpolation, but cannot seem to figure out why it is. When I disable the bilinear GL_LINEAR texture interpolation to GL_NEAREST, they look even worse (and blocky, as if it'd ignore the alpha channel). What can I do to make my font textures look more true to their original?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16638" PostHistoryTypeId="2" PostId="6009" RevisionGUID="59953f2e-91db-4a69-ad05-e6f91e5b921f" CreationDate="2017-12-18T18:22:59.053" UserId="213" Text="I convert RGB input to YUV 420 semi-planar output using compute shader.Luma plane is straightforward as it maps 1:1 with RGB dimensions. As we know, [NV12 packs Cb][1] and Cr into one plane, which means the CbCr values must be calculating from downsampled (x4) source.And this is the part I am not completely sure I am doing right. I currently try subsampling with simple bileanar filtering.And it 'almost' looks right.I uses t[his article][2] as reference.It is possible that my code is 100% correct and the aliasing stems from compression losness. &#xD;&#xA;&#xD;&#xA;Here is my part of shader code that samples from RGB texture and writes U and V values:&#xD;&#xA;&#xD;&#xA;           ivec2 itexSize =textureSize(rbga_tex,0); &#xD;&#xA;           vec2 texSize =  vec2(itexSize);&#xD;&#xA;           vec2 texelSize = 1.0 / (texSize / 2.0);&#xD;&#xA;           vec2 pixel = uv * texSize + 0.5;&#xD;&#xA;           pixel = (floor(pixel) / texSize) - vec2(texelSize/2.0);&#xD;&#xA;             &#xD;&#xA;            //bilinear filtering:&#xD;&#xA;                float sc = 4.0;&#xD;&#xA;              vec3 ts = texture(rbga_tex,   pixel ).rgb * 0.25; // center&#xD;&#xA;			  vec3 tr = texture(rbga_tex,   pixel + vec2(texelSize.x * sc, 0.0) ).rgb  * 0.25;  &#xD;&#xA;			  vec3 bl = texture(rbga_tex,   pixel + vec2(0.0, texelSize.y * sc) ).rgb * 0.25; &#xD;&#xA;			  vec3 br = texture(rbga_tex,   pixel + vec2(texelSize.x, texelSize.y) * sc).rgb * 0.25;&#xD;&#xA;			&#xD;&#xA;             vec3 tex1 = (ts + tr + bl + br) ;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;            // calculate and  write U...&#xD;&#xA;           &#xD;&#xA;            // calculate and write V...&#xD;&#xA;            &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the original rgb image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And here is the snapshot of the video frame after the conversion:&#xD;&#xA;&#xD;&#xA; [![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;So here are my questions:&#xD;&#xA;&#xD;&#xA;a)I would like to understand if there is something I am doing wrong, and if possible to get a concise explanation on how subsampling should be done when converting from rbg to yuv420 color space. &#xD;&#xA;&#xD;&#xA;b)If this result is correct, are there ways to get smoother effect while keeping overall sharpness?I understand that using bicubic filter we can get smoother visuals but at cost of image sharpness.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd206750(v=vs.85).aspx&#xD;&#xA;  [2]: https://blog.demofox.org/2015/08/15/resizing-images-with-bicubic-interpolation/&#xD;&#xA;  [3]: https://i.stack.imgur.com/lQ7Og.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/8lm8a.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16639" PostHistoryTypeId="1" PostId="6009" RevisionGUID="59953f2e-91db-4a69-ad05-e6f91e5b921f" CreationDate="2017-12-18T18:22:59.053" UserId="213" Text="YUV (NV12) Chroma subsampling while converting from RGB image" ContentLicense="CC BY-SA 3.0" />
  <row Id="16640" PostHistoryTypeId="3" PostId="6009" RevisionGUID="59953f2e-91db-4a69-ad05-e6f91e5b921f" CreationDate="2017-12-18T18:22:59.053" UserId="213" Text="|texture|gpu|sampling|filtering|video|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16641" PostHistoryTypeId="2" PostId="6010" RevisionGUID="005a922f-76f9-4e81-9e7b-58cad63c7f96" CreationDate="2017-12-18T18:30:18.777" UserId="506" Text="The easiest fix would be to do your light calculations in the fragment shader rather than per-vertex—you’ll avoid the discontinuity you’re currently seeing and your lighting will appear more natural (while still fitting the “low-poly” aesthetic). If that’s not an option, then you’re probably stuck with passing in each quad’s center along with the normals you’re already supplying." ContentLicense="CC BY-SA 3.0" />
  <row Id="16642" PostHistoryTypeId="2" PostId="6011" RevisionGUID="53049e32-a5a7-4e7d-8bd7-0b35e5e46bf8" CreationDate="2017-12-18T20:22:35.983" UserId="7289" Text="You are probably mixing thing up. As I understood from you explanation, you are trying to do Phong shading and you want flat shading. &#xD;&#xA;&#xD;&#xA;Your problem might be happening because you are calculating a specular component that depends on the view/camera direction.&#xD;&#xA;&#xD;&#xA;It would help if you could add pictures explaining what is happening and what you want to happen.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16643" PostHistoryTypeId="2" PostId="6012" RevisionGUID="36e1e1aa-dbcd-42bf-a0f1-7002ba923c8d" CreationDate="2017-12-18T21:08:13.860" UserId="7918" Text="I'm trying to get a 2D screen position so I unproject a point from 3D into 2D screen coordinates by that following function:&#xD;&#xA;&#xD;&#xA;    Ogre::Vector2 SpaceTransformHelper::convertWorldToScreenPosition( const Ogre::Vector3&amp; worldPosition )&#xD;&#xA;    {&#xD;&#xA;        Stages::AStage* currStage = Stages::StageManager::getSingleton()-&gt;getActiveStage();&#xD;&#xA;        Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()-&gt;getScreenResolution();&#xD;&#xA;    &#xD;&#xA;        // Get worldviewprojection from camera.&#xD;&#xA;        Ogre::Matrix4 worldViewProjection = currStage-&gt;getActiveCamera()-&gt;getCameraViewProjectionMatrix();&#xD;&#xA;    &#xD;&#xA;        // Transform world coordinates.&#xD;&#xA;        Ogre::Vector3 transformedWorldPosition = worldViewProjection * worldPosition;&#xD;&#xA;    &#xD;&#xA;        // Calculate screen coordinates from world coordinates.&#xD;&#xA;        Ogre::Vector2 screenPosition;&#xD;&#xA;        screenPosition.x = (int) ( ( ( transformedWorldPosition.x + 1 ) / 2.0 ) * screenRes.width + 0.5 );&#xD;&#xA;        screenPosition.y = (int) ( ( ( 1 - transformedWorldPosition.y ) / 2.0 ) * screenRes.height + 0.5 );&#xD;&#xA;    &#xD;&#xA;        return screenPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now I want to convert that screenPosition into Image space to crop an image:&#xD;&#xA;&#xD;&#xA;    Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()-&gt;getScreenResolution();&#xD;&#xA;    float screenPositionX = (screenPosition.x / screenRes.width) * (pixelBuffer-&gt;getWidth());&#xD;&#xA;    float screenPositionY =  (screenPosition.y / screenRes.height) * (pixelBuffer-&gt;getHeight());&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When I click on the mobile screen on the Green LED I get that cropped image.. but what I want is to only crop that green led.. Is there a problem with the transformation ?&#xD;&#xA;&#xD;&#xA;       float screenPositionX = (screenPosition.x / screenRes.width) * ((int)pixelBuffer-&gt;getWidth());&#xD;&#xA;            float screenPositionY= (screenPosition.y / screenRes.height) * ((int)pixelBuffer-&gt;getHeight());&#xD;&#xA;    &#xD;&#xA;           int  min_x = std::max( 0,(int)screenPosition.x - radius);&#xD;&#xA;           int  min_y = std::max( 0,(int)screenPosition.y - radius);&#xD;&#xA;           int  max_x = std::min( (int)cameraRes.width, (int) screenPosition.x + radius );&#xD;&#xA;           int  max_y = std::min( (int)cameraRes.height, (int) screenPosition.y+ radius );&#xD;&#xA;    &#xD;&#xA;             // Get the pixelbox within the radius.&#xD;&#xA;            pixelBuffer-&gt;lock(Ogre::HardwareBuffer::HBL_READ_ONLY);&#xD;&#xA;            const Ogre::PixelBox &amp;readrefpb = pixelBuffer-&gt;getCurrentLock();&#xD;&#xA;    &#xD;&#xA;            unsigned char *readrefdata = static_cast&lt;unsigned char*&gt;(readrefpb.data);&#xD;&#xA;    &#xD;&#xA;            Ogre::Image img;&#xD;&#xA;            img = img.loadDynamicImage (readrefdata, pixelBuffer-&gt;getWidth(),&#xD;&#xA;                                        pixelBuffer-&gt;getHeight(), pixelBuffer-&gt;getFormat());&#xD;&#xA;    &#xD;&#xA;            Ogre::Image *out = cropImage(img,  min_x, min_y,  max_x,  max_y);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p4c3n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16644" PostHistoryTypeId="1" PostId="6012" RevisionGUID="36e1e1aa-dbcd-42bf-a0f1-7002ba923c8d" CreationDate="2017-12-18T21:08:13.860" UserId="7918" Text="I'm trying to get a 2D screen position so I unproject a point from 3D into 2D screen coordinates by that following function:" ContentLicense="CC BY-SA 3.0" />
  <row Id="16645" PostHistoryTypeId="3" PostId="6012" RevisionGUID="36e1e1aa-dbcd-42bf-a0f1-7002ba923c8d" CreationDate="2017-12-18T21:08:13.860" UserId="7918" Text="|opengl|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16646" PostHistoryTypeId="2" PostId="6013" RevisionGUID="9d69b07b-9d11-43d2-9aa5-fb8516baf7ab" CreationDate="2017-12-18T22:39:35.610" UserId="7740" Text="From what I can see, it looks like screenPosition.x is in some sort of screen space and screenPositionX is in terms of the actual pixel buffer in units of pixels. My guess is that cropImage wants its inputs in units of pixels but when you calculate min_x, min_y, ... you are using screenPosition.x when you should really be using screenPositionX. Also, where does radius come from? Is it in world space, screen space, or pixel buffer space?&#xD;&#xA;&#xD;&#xA;Regardless of whether or not that fixes your problem, try to be more explicit in the future about your variables names to keep track of which space/units you are in. Having a screenPosition.x and a screenPositionX which refer to different things is generally a bad idea." ContentLicense="CC BY-SA 3.0" />
  <row Id="16647" PostHistoryTypeId="5" PostId="6006" RevisionGUID="3b029f13-8e76-4701-8064-ea190cb71389" CreationDate="2017-12-19T03:24:25.093" UserId="5545" Comment="add flat shading para" Text="Here's an example of the [flat shaded](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg) squares I want. But my squares are made of two triangles, and I'm getting flat shading of those *triangles*.&#xD;&#xA;&#xD;&#xA;In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same &quot;low-poly&quot; lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.&#xD;&#xA;&#xD;&#xA;I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.&#xD;&#xA;&#xD;&#xA;I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the *viewer* is slightly different, depending on where the tri is relative to the viewer.&#xD;&#xA;&#xD;&#xA;A brute force solution would be to store a special &quot;location&quot; for each vertex of each tri, and set &quot;location&quot; to the same value for each of the 4 verices of the two tris forming the square.&#xD;&#xA;&#xD;&#xA;But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any *per vertex* data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have *per tri* data?&#xD;&#xA;&#xD;&#xA;&gt; **EDIT** I currently have *per vertex* normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as *per tri*, since only one tri is provoked by each vertex. I could give the same &quot;location&quot; to both tris in a quad this way. But it's still brute force - is there a better way?&#xD;&#xA;&#xD;&#xA;Or, can you tell which tri of a quad you're in, so you can decide what it's &quot;location&quot; should be?&#xD;&#xA;&#xD;&#xA;It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16648" PostHistoryTypeId="4" PostId="6006" RevisionGUID="3b029f13-8e76-4701-8064-ea190cb71389" CreationDate="2017-12-19T03:24:25.093" UserId="5545" Comment="add flat shading para" Text="Same specular lighting on both tris in a quad (for &quot;low-poly&quot; &quot;flat shading&quot; look)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16649" PostHistoryTypeId="2" PostId="6014" RevisionGUID="a295441e-2c82-4bc8-99c5-a13083f8d077" CreationDate="2017-12-19T03:46:27.520" UserId="48" Text="If I understand you correctly, the problem is that the provoking vertex isn't the same vertex between the two triangles in a quad, due to using triangle strips. You could switch to using an indexed triangle list, and set up indices in such a way that the provoking vertex is the same in each quad. For instance, if one quad is vertices {0, 1, 2, 3} (CCW) then you might write {0, 1, 2, 3, 0, 2} in your index buffer so that 2 is the provoking vertex for both triangles. This should still be pretty efficient.&#xD;&#xA;&#xD;&#xA;Another possibility (more involved, but more flexible) is to use the built-in [`gl_VertexID`](http://docs.gl/el3/gl_VertexID) variable in your vertex shader to figure out which quad you're in (eg `int quadID = gl_VertexID / 4`), and use an appropriate shading location for that quad—the centroid of its vertices, for instance. However, for this to work, I think you would have to &quot;un-share&quot; the vertices so that each quad has its own 4 unique vertices (the two triangles in a quad can still share). So you would have to use primitive restarting, or again switch to indexed non-strip draws. You could also have per-quad data in an SSBO that you manually fetch using your computed quad index." ContentLicense="CC BY-SA 3.0" />
  <row Id="16650" PostHistoryTypeId="5" PostId="6006" RevisionGUID="71a3ccff-0858-4f81-ba60-fe28544810d8" CreationDate="2017-12-19T03:53:55.303" UserId="5545" Comment="add flat shading para" Text="Here's an example of the [flat shaded](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg) squares I want. But my squares are made of two triangles, and I'm getting flat shading of those *triangles*.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same &quot;low-poly&quot; lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.&#xD;&#xA;&#xD;&#xA;I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.&#xD;&#xA;&#xD;&#xA;I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the *viewer* is slightly different, depending on where the tri is relative to the viewer.&#xD;&#xA;&#xD;&#xA;[![from ][2]][2]&#xD;&#xA;&#xD;&#xA;This diagram only shows the light from one point, for eyes at different locations, but you can see that light from different points would have a similar effect on an eye at one place.&#xD;&#xA;&#xD;&#xA;A brute force solution would be to store a special &quot;location&quot; for each vertex of each tri, and set &quot;location&quot; to the same value for each of the 4 verices of the two tris forming the square.&#xD;&#xA;&#xD;&#xA;But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any *per vertex* data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have *per tri* data?&#xD;&#xA;&#xD;&#xA;&gt; **EDIT** I currently have *per vertex* normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as *per tri*, since only one tri is provoked by each vertex. I could give the same &quot;location&quot; to both tris in a quad this way. But it's still brute force - is there a better way?&#xD;&#xA;&#xD;&#xA;Or, can you tell which tri of a quad you're in, so you can decide what it's &quot;location&quot; should be?&#xD;&#xA;&#xD;&#xA;It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7UNuF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/X9oGg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16651" PostHistoryTypeId="5" PostId="6006" RevisionGUID="f04db4ff-dc28-46c5-bb46-994cf09ad085" CreationDate="2017-12-19T03:58:56.160" UserId="5545" Comment="add flat shading para" Text="Here's an example of the [flat shaded](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg) squares I want. But my squares are made of two triangles, and I'm getting flat shading of those *triangles*.&#xD;&#xA;&#xD;&#xA;[![from wiki article on phong shading][1]][1]&#xD;&#xA;&#xD;&#xA;In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same &quot;low-poly&quot; lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.&#xD;&#xA;&#xD;&#xA;I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.&#xD;&#xA;&#xD;&#xA;I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the *viewer* is slightly different, depending on where the tri is relative to the viewer.&#xD;&#xA;&#xD;&#xA;[![from [Introduction to Computer Graphics, *David J. Eck*](http://math.hws.edu/graphicsbook/c4/s1.html)][2]][2]&#xD;&#xA;&#xD;&#xA;(This diagram ([*Intro to Computer Graphics*, David J. Eck](http://math.hws.edu/graphicsbook/c4/s1.html)) only shows the light from one point, for observers at different locations, but you can see that light from different points would produce a shifted cone, having a similar effect on an observer at one place.)&#xD;&#xA;&#xD;&#xA;A brute force solution would be to store a special &quot;location&quot; for each vertex of each tri, and set &quot;location&quot; to the same value for each of the 4 verices of the two tris forming the square.&#xD;&#xA;&#xD;&#xA;But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any *per vertex* data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have *per tri* data?&#xD;&#xA;&#xD;&#xA;&gt; **EDIT** I currently have *per vertex* normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as *per tri*, since only one tri is provoked by each vertex. I could give the same &quot;location&quot; to both tris in a quad this way. But it's still brute force - is there a better way?&#xD;&#xA;&#xD;&#xA;Or, can you tell which tri of a quad you're in, so you can decide what it's &quot;location&quot; should be?&#xD;&#xA;&#xD;&#xA;It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7UNuF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/X9oGg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16652" PostHistoryTypeId="5" PostId="6006" RevisionGUID="85eafae0-161a-4006-b4d4-066669d10820" CreationDate="2017-12-19T04:44:56.920" UserId="5545" Comment="deleted 5 characters in body" Text="Here's an example of the [flat shaded](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg) squares I want. But my squares are made of two triangles, and I'm getting flat shading of those *triangles*.&#xD;&#xA;&#xD;&#xA;[![from wiki article on phong shading][1]][1]&#xD;&#xA;&#xD;&#xA;In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same &quot;low-poly&quot; lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.&#xD;&#xA;&#xD;&#xA;I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.&#xD;&#xA;&#xD;&#xA;I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the *viewer* is slightly different, depending on where the tri is relative to the viewer.&#xD;&#xA;&#xD;&#xA;[![[Introduction to Computer Graphics, *David J. Eck*](http://math.hws.edu/graphicsbook/c4/s1.html)][2]][2]&#xD;&#xA;&#xD;&#xA;&gt; This diagram ([*Intro to Computer Graphics*, David J. Eck](http://math.hws.edu/graphicsbook/c4/s1.html)) only shows the light from one point, for observers at different locations, but you can see that light from different points would produce a shifted cone, having a similar effect on an observer at one place.&#xD;&#xA;&#xD;&#xA;A brute force solution would be to store a special &quot;location&quot; for each vertex of each tri, and set &quot;location&quot; to the same value for each of the 4 verices of the two tris forming the square.&#xD;&#xA;&#xD;&#xA;But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any *per vertex* data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have *per tri* data?&#xD;&#xA;&#xD;&#xA;&gt; **EDIT** I currently have *per vertex* normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as *per tri*, since only one tri is provoked by each vertex. I could give the same &quot;location&quot; to both tris in a quad this way. But it's still brute force - is there a better way?&#xD;&#xA;&#xD;&#xA;Or, can you tell which tri of a quad you're in, so you can decide what it's &quot;location&quot; should be?&#xD;&#xA;&#xD;&#xA;It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7UNuF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/X9oGg.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16653" PostHistoryTypeId="5" PostId="6003" RevisionGUID="7cc1a4e0-94af-46b8-bda8-3d8ddbd7f0db" CreationDate="2017-12-19T09:59:15.370" UserId="209" Comment="Incorporating his later comment into the question to, hopefully, make it clearer." Text="I want to extent the following to work on a solid angle:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose we have a volume filled with small surfaces.  If we cast a ray from a given point, the probability that the ray will not hit a surface (i.e. is visible to the sky) is given as &#xD;&#xA;&#xD;&#xA;$P(ray\ does\ not\ hit) = {e}^{-\alpha d/\cos\theta}$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is some decay factor, $d/cos\theta$ is the path length of the ray within the volume.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My question:**  &#xD;&#xA; How can we compute the expected visibility of a ray if we consider the directions $(\theta, \phi)$, where $0&lt;\theta&lt;\pi/2$ and $0&lt;\phi&lt;2\pi$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16654" PostHistoryTypeId="2" PostId="6015" RevisionGUID="1502db9f-7534-43cf-91bd-91110eb31a55" CreationDate="2017-12-19T10:22:52.117" UserId="2372" Text="I am working on a specific blur effect that implies several behaviours. But before I would like to know what you think about those blurring algorithms according to performances and quality :&#xD;&#xA;**Kawase blur**, **Box blur** and **two pass Gaussian blur**.&#xD;&#xA;&#xD;&#xA;Next are the effects I am currently working on and I would be glad to have your thoughts on those on the proper way to achieve this. Here is a schematic view followed by my questions.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; 1. I would like to blur the content of those 4 spheres using the same offset no mater their position. If I apply the same blur on all objects, far object's content will appear more blurry than ones on the foreground and I want to avoid that. I think that the depth make could help but any precision would help me.&#xD;&#xA; 2. If I blur the whole image and apply the result on the sphere, the white background will bleed onto the sphere shape and I want to avoid that. I also don't want that the blue (3) and yellow (4) sphere merges with the red (1) and green (2) ones. But I would like that the green and red ones merges. Again This could be done using the depth but if you have more precision about how to do it it would be interesting.&#xD;&#xA;&#xD;&#xA;Any ideas about those questions would be helpful.&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eCwIX.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16655" PostHistoryTypeId="1" PostId="6015" RevisionGUID="1502db9f-7534-43cf-91bd-91110eb31a55" CreationDate="2017-12-19T10:22:52.117" UserId="2372" Text="Questions about Blur effect" ContentLicense="CC BY-SA 3.0" />
  <row Id="16656" PostHistoryTypeId="3" PostId="6015" RevisionGUID="1502db9f-7534-43cf-91bd-91110eb31a55" CreationDate="2017-12-19T10:22:52.117" UserId="2372" Text="|rendering|shader|gaussian-blur|blur|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16657" PostHistoryTypeId="2" PostId="6016" RevisionGUID="81b80c87-b21e-456a-ba1e-a84f3cf6e4c7" CreationDate="2017-12-19T10:45:50.210" UserId="7008" Text="&#xD;&#xA;&#xD;&#xA;&gt; If I blur the whole image and apply the result on the sphere, the white background will bleed onto the sphere shape and I want to avoid that. I also don't want that the blue (3) and yellow (4) sphere merges with the red (1) and green (2) ones. But I would like that the green and red ones merges. Again This could be done using the depth but if you have more precision about how to do it it would be interesting.&#xD;&#xA;&#xD;&#xA;You will need to blurr in multiple passes to achieve this:&#xD;&#xA;once for the blue and once for the yellow, as well as once for the red and green (together). That is: you need to render to texture, you need three textures in this instance to render to, you need to blur the individual textures and then combine them in another render pass.&#xD;&#xA;If you know beforehand that the green and red spheres may blur together, you can just hardcode it, otherwise you need to come up with a way of determining, which spheres may blur together, and group your spheres to render into the same texture.&#xD;&#xA;&#xD;&#xA;If you do this, keep in mind that for combining the three individual blurred textures, you need z-values for correct visibility determination.&#xD;&#xA;&#xD;&#xA;&gt; I would like to blur the content of those 4 spheres using the same offset no mater their position. If I apply the same blur on all objects, far object's content will appear more blurry than ones on the foreground and I want to avoid that. I think that the depth make could help but any precision would help me.&#xD;&#xA;&#xD;&#xA;Yes, you can scale your blur filter with a depth value (where you should &quot;invert&quot; the value to make the blurriness scale to larger effects on closer proximities, i.e. smaller depths). For a box filter, you take ratios of the pixels neighbourhoods, but you need to make sure that those ratios add up to one. For this, you'd ideally increase the ratio for the center pixel based on the proximity and reduce the ratio for the neighbouring pixels accordingly.&#xD;&#xA;&#xD;&#xA;&gt; performances and quality : Kawase blur, Box blur and two pass Gaussian blur.&#xD;&#xA;&#xD;&#xA;As to performance, I can't say anything about the three. As to quality, the Box Filter is rather simple, but that doesn't mean it doesn't suffice for your specific need. Just test them against each other." ContentLicense="CC BY-SA 3.0" />
  <row Id="16658" PostHistoryTypeId="5" PostId="6012" RevisionGUID="2570a6a3-419c-43ba-aa7f-f9d89cb6cff3" CreationDate="2017-12-19T11:59:20.873" UserId="7918" Comment="added 635 characters in body" Text="I'm trying to get a 2D screen position so I unproject a point from 3D into 2D screen coordinates by that following function:&#xD;&#xA;&#xD;&#xA;    Ogre::Vector2 SpaceTransformHelper::convertWorldToScreenPosition( const Ogre::Vector3&amp; worldPosition )&#xD;&#xA;    {&#xD;&#xA;        Stages::AStage* currStage = Stages::StageManager::getSingleton()-&gt;getActiveStage();&#xD;&#xA;        Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()-&gt;getScreenResolution();&#xD;&#xA;    &#xD;&#xA;        // Get worldviewprojection from camera.&#xD;&#xA;        Ogre::Matrix4 worldViewProjection = currStage-&gt;getActiveCamera()-&gt;getCameraViewProjectionMatrix();&#xD;&#xA;    &#xD;&#xA;        // Transform world coordinates.&#xD;&#xA;        Ogre::Vector3 transformedWorldPosition = worldViewProjection * worldPosition;&#xD;&#xA;    &#xD;&#xA;        // Calculate screen coordinates from world coordinates.&#xD;&#xA;        Ogre::Vector2 screenPosition;&#xD;&#xA;        screenPosition.x = (int) ( ( ( transformedWorldPosition.x + 1 ) / 2.0 ) * screenRes.width + 0.5 );&#xD;&#xA;        screenPosition.y = (int) ( ( ( 1 - transformedWorldPosition.y ) / 2.0 ) * screenRes.height + 0.5 );&#xD;&#xA;    &#xD;&#xA;        return screenPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now I want to convert that screenPosition into Image space to crop an image:&#xD;&#xA;&#xD;&#xA;    Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()-&gt;getScreenResolution();&#xD;&#xA;    float screenPositionX = (screenPosition.x / screenRes.width) * (pixelBuffer-&gt;getWidth());&#xD;&#xA;    float screenPositionY =  (screenPosition.y / screenRes.height) * (pixelBuffer-&gt;getHeight());&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When I click on the mobile screen on the Green LED I get that cropped image.. but what I want is to only crop that green led.. Is there a problem with the transformation ?&#xD;&#xA;&#xD;&#xA;      const Core::Resolution cameraRes = Core::EnvironmentInformation::getSingleton()-&gt;getCameraResolutionUpLoad( plane );&#xD;&#xA;        Ogre::HardwarePixelBufferSharedPtr pixelBuffer = mTexture[plane]-&gt;getBuffer( 0, 0 );&#xD;&#xA;&#xD;&#xA;        viewarassert( screenPosition.x &lt; cameraRes.width || screenPosition.x &gt;= 0 || screenPosition.y &lt; cameraRes.height || screenPosition.y &gt;= 0 );&#xD;&#xA;        &#xD;&#xA;       Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()-&gt;getScreenResolution();&#xD;&#xA;       std::pair&lt; Ogre::Vector2, Ogre::Vector2 &gt; uvBounds = calculateSingleViewTextureCoordinates();&#xD;&#xA;        &#xD;&#xA;        float screenPositionX = cameraRes.height - (screenPosition.x / screenRes.width) * ((int)pixelBuffer-&gt;getHeight());&#xD;&#xA;        float screenPositionY=  cameraRes.width -  (screenPosition.y / screenRes.height) * ((int)pixelBuffer-&gt;getWidth());&#xD;&#xA;        &#xD;&#xA;        int  min_x = std::max( 0,(int)screenPositionX - radius);&#xD;&#xA;        int  min_y = std::max( 0,(int)screenPositionY - radius);&#xD;&#xA;        int  max_x = std::min( (int)cameraRes.width, (int) screenPositionX + radius );&#xD;&#xA;        int  max_y = std::min( (int)cameraRes.height, (int) screenPositionY+ radius );&#xD;&#xA;        &#xD;&#xA;        // Get the pixelbox within the radius.&#xD;&#xA;        pixelBuffer-&gt;lock(Ogre::HardwareBuffer::HBL_READ_ONLY);&#xD;&#xA;        const Ogre::PixelBox &amp;readrefpb = pixelBuffer-&gt;getCurrentLock();&#xD;&#xA;        &#xD;&#xA;        unsigned char *readrefdata = static_cast&lt;unsigned char*&gt;(readrefpb.data);&#xD;&#xA;        &#xD;&#xA;        Ogre::Image img;&#xD;&#xA;        img = img.loadDynamicImage (readrefdata, pixelBuffer-&gt;getWidth(),&#xD;&#xA;                                    pixelBuffer-&gt;getHeight(), pixelBuffer-&gt;getFormat());&#xD;&#xA;        img = img.flipAroundY();&#xD;&#xA;        &#xD;&#xA;        Ogre::Image *out = cropImage(img,  min_x, min_y,  max_x,  max_y);&#xD;&#xA;  [1]: https://i.stack.imgur.com/p4c3n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16662" PostHistoryTypeId="50" PostId="5311" RevisionGUID="7aeced89-66ce-48cb-b684-dabdef1f9024" CreationDate="2017-12-19T17:11:23.127" UserId="-1" />
  <row Id="16663" PostHistoryTypeId="5" PostId="6003" RevisionGUID="8ebeeead-24e9-4c95-84f2-458e158c32b6" CreationDate="2017-12-19T19:31:27.390" UserId="5183" Comment="edited body" Text="I want to extend the following to work on a solid angle:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose we have a volume filled with small surfaces.  If we cast a ray from a given point, the probability that the ray will not hit a surface (i.e. is visible to the sky) is given as &#xD;&#xA;&#xD;&#xA;$P(ray\ does\ not\ hit) = {e}^{-\alpha d/\cos\theta}$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is some decay factor, $d/cos\theta$ is the path length of the ray within the volume.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My question:**  &#xD;&#xA; How can we compute the expected visibility of a ray if we consider the directions $(\theta, \phi)$, where $0&lt;\theta&lt;\pi/2$ and $0&lt;\phi&lt;2\pi$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16666" PostHistoryTypeId="50" PostId="5892" RevisionGUID="c05247a1-e6db-47e4-bfd2-4733636b4dd1" CreationDate="2017-12-20T04:12:05.520" UserId="-1" />
  <row Id="16667" PostHistoryTypeId="2" PostId="6018" RevisionGUID="5e918d8a-41e8-448e-8aca-20ce311e1599" CreationDate="2017-12-20T04:19:18.693" UserId="3073" Text="From looking at your example images this looks like a case of Alpha blending being applied to the RGB channel of the font-atlas texture and then again applied via the A channel when rendering. &#xD;&#xA;&#xD;&#xA;The tell-tale sign of this is usually a feint dark halo surrounding your glyphs which is caused by the unwanted mid-greys present in the texture being multiplied by alpha.&#xD;&#xA;&#xD;&#xA;For font rendering it is typical to have anti-aliasing in the A channel and have your RGB channels a constant colour. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16668" PostHistoryTypeId="2" PostId="6019" RevisionGUID="292c4525-0b4d-42ba-a744-d8fcecf30721" CreationDate="2017-12-20T12:23:04.700" UserId="1937" Text="I wrote a simple Phong shader with two directional lights for a project, and noticed an unpleasant artifact in the lighting. Where both lights are illuminating the same region, dark bands appear at the light terminators where N.L reaches zero. At first I thought it must be a bug in my code, but a quick test revealed the Unity standard shader has the exact same problem.&#xD;&#xA;&#xD;&#xA;[![my shader][1]][1]&#xD;&#xA;[![unity shader][2]][2]&#xD;&#xA;&#xD;&#xA;My best guess is that this is some form of the Mach effect, and our retinas are overshooting where the brightness plateaus. Does anyone know any tricks to mitigate this effect?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RKu8H.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YJesJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16669" PostHistoryTypeId="1" PostId="6019" RevisionGUID="292c4525-0b4d-42ba-a744-d8fcecf30721" CreationDate="2017-12-20T12:23:04.700" UserId="1937" Text="Avoiding Mach band effect when using multiple lights" ContentLicense="CC BY-SA 3.0" />
  <row Id="16670" PostHistoryTypeId="3" PostId="6019" RevisionGUID="292c4525-0b4d-42ba-a744-d8fcecf30721" CreationDate="2017-12-20T12:23:04.700" UserId="1937" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16671" PostHistoryTypeId="2" PostId="6020" RevisionGUID="96fe4993-ba3f-4bb1-8a71-157aa39844b9" CreationDate="2017-12-20T14:12:10.737" UserId="7925" Text="I'm trying to outline a 3D model in WebGL. I've tried using a stencil buffer techique with glLineWidth and glPolygonMode. However, Mozilla's WebGL reference says that the minimum and maximum widths of lines are 1 (therefore can't be modified). I've tried it using it without glLineWidth and just use wireframe mode.&#xD;&#xA;&#xD;&#xA;    for (let i = 0; i &lt; node_to_display.leaves.length; i++) {&#xD;&#xA;&#xD;&#xA;        if (node_to_display.pickable) {&#xD;&#xA;            this.scene.gl.enable(this.scene.gl.STENCIL_TEST);&#xD;&#xA;            this.scene.gl.clearStencil(0);&#xD;&#xA;            this.scene.gl.clear(this.scene.gl.STENCIL_BUFFER_BIT);&#xD;&#xA;            this.scene.gl.stencilFunc(this.scene.gl.ALWAYS, 1, -1);&#xD;&#xA;            this.scene.gl.stencilOp(this.scene.gl.KEEP, this.scene.gl.KEEP, this.scene.gl.REPLACE);&#xD;&#xA;            node_to_display.leaves[i].primitive.primitiveType = this.scene.gl.TRIANGLES;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        node_to_display.leaves[i].display(); //Display leaves&#xD;&#xA;&#xD;&#xA;        if (node_to_display.pickable) {&#xD;&#xA;            this.scene.activeShader.setUniformsValues({ outline_color: [1, 0, 0, 1] });&#xD;&#xA;&#xD;&#xA;            this.scene.gl.stencilFunc(this.scene.gl.NOTEQUAL, 1, -1);&#xD;&#xA;            this.scene.gl.stencilOp(this.scene.gl.KEEP, this.scene.gl.KEEP, this.scene.gl.REPLACE);&#xD;&#xA;            node_to_display.leaves[i].primitive.primitiveType = this.scene.gl.LINES;&#xD;&#xA;            node_to_display.leaves[i].display();  //Display leaves in wireframe&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However this is the result I'm getting:&#xD;&#xA;&#xD;&#xA;[![Model Outline][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ggcAK.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this result is that the wireframe still shows where there is a triangle mesh &quot;behind it&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="16672" PostHistoryTypeId="1" PostId="6020" RevisionGUID="96fe4993-ba3f-4bb1-8a71-157aa39844b9" CreationDate="2017-12-20T14:12:10.737" UserId="7925" Text="3D model outline using stencil buffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="16673" PostHistoryTypeId="3" PostId="6020" RevisionGUID="96fe4993-ba3f-4bb1-8a71-157aa39844b9" CreationDate="2017-12-20T14:12:10.737" UserId="7925" Text="|webgl|javascript|model|stencil-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16674" PostHistoryTypeId="5" PostId="6020" RevisionGUID="59d5e508-3145-4501-a0ed-278bae8c615b" CreationDate="2017-12-20T14:48:31.660" UserId="7925" Comment="added 128 characters in body" Text="I'm trying to outline a 3D model in WebGL. I've tried using a stencil buffer techique with glLineWidth and glPolygonMode. However, Mozilla's WebGL reference says that the minimum and maximum widths of lines are 1 (therefore can't be modified). I've tried it using it without glLineWidth and just use wireframe mode.&#xD;&#xA;&#xD;&#xA;    for (let i = 0; i &lt; node_to_display.leaves.length; i++) {&#xD;&#xA;&#xD;&#xA;        if (node_to_display.pickable) {&#xD;&#xA;            this.scene.gl.enable(this.scene.gl.STENCIL_TEST);&#xD;&#xA;            this.scene.gl.clearStencil(0);&#xD;&#xA;            this.scene.gl.clear(this.scene.gl.STENCIL_BUFFER_BIT);&#xD;&#xA;            this.scene.gl.stencilFunc(this.scene.gl.ALWAYS, 1, -1);&#xD;&#xA;            this.scene.gl.stencilOp(this.scene.gl.KEEP, this.scene.gl.KEEP, this.scene.gl.REPLACE);&#xD;&#xA;            node_to_display.leaves[i].primitive.primitiveType = this.scene.gl.TRIANGLES;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        node_to_display.leaves[i].display(); //Display leaves&#xD;&#xA;&#xD;&#xA;        if (node_to_display.pickable) {&#xD;&#xA;            this.scene.activeShader.setUniformsValues({ outline_color: [1, 0, 0, 1] });&#xD;&#xA;&#xD;&#xA;            this.scene.gl.stencilFunc(this.scene.gl.NOTEQUAL, 1, -1);&#xD;&#xA;            this.scene.gl.stencilOp(this.scene.gl.KEEP, this.scene.gl.KEEP, this.scene.gl.REPLACE);&#xD;&#xA;            node_to_display.leaves[i].primitive.primitiveType = this.scene.gl.LINES;&#xD;&#xA;            node_to_display.leaves[i].display();  //Display leaves in wireframe&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However this is the result I'm getting:&#xD;&#xA;&#xD;&#xA;[![Model Outline][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this result is that the wireframe still shows where there is a triangle mesh &quot;behind it&quot;.&#xD;&#xA;&#xD;&#xA;[EDIT] The result I'm looking for is something like this: &#xD;&#xA;&#xD;&#xA;[![Example][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ggcAK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WApve.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16675" PostHistoryTypeId="2" PostId="6021" RevisionGUID="20e5d2ab-74e3-4b95-96cb-920d4033fcdf" CreationDate="2017-12-20T17:00:32.510" UserId="7929" Text="By default, the eye an the projection reference point PRP are in (0,0,0). I can change the eye position with gluLookAt(), but how can I change the PRP (i.e., the  convergence position for a set of parallel lines) for a perspective projection in OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16676" PostHistoryTypeId="1" PostId="6021" RevisionGUID="20e5d2ab-74e3-4b95-96cb-920d4033fcdf" CreationDate="2017-12-20T17:00:32.510" UserId="7929" Text="Changing the projection reference point in Open GL" ContentLicense="CC BY-SA 3.0" />
  <row Id="16677" PostHistoryTypeId="3" PostId="6021" RevisionGUID="20e5d2ab-74e3-4b95-96cb-920d4033fcdf" CreationDate="2017-12-20T17:00:32.510" UserId="7929" Text="|opengl|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16679" PostHistoryTypeId="2" PostId="6022" RevisionGUID="61885625-fbcc-4c2f-b969-3803d54f580b" CreationDate="2017-12-21T01:01:33.720" UserId="6806" Text="I'am curious about compute shader in OpenGL.&#xD;&#xA;&#xD;&#xA;Let's assume the number of points (vec4) is 900&#xD;&#xA;&#xD;&#xA;and  the work group size(= the number of work items) is 256&#xD;&#xA;&#xD;&#xA;Then, We would have four work groups because 900/256 = 3.xx, so need to plus 1.&#xD;&#xA;&#xD;&#xA;The code is as follows:&#xD;&#xA;&#xD;&#xA;    glDispatchCompute(4, 1, 1);&#xD;&#xA;&#xD;&#xA;and shader is as follows:&#xD;&#xA;&#xD;&#xA;    layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    layout(std430, binding = 0) buffer Particles {&#xD;&#xA;	    vec4 partices[];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In this case, I wonder how to work fourth work group.&#xD;&#xA;In my thought, the fourth work group have overflow problem because the total number of points is 900.&#xD;&#xA;&#xD;&#xA;Do we need to deal exceptional case(overflow)?&#xD;&#xA;&#xD;&#xA;For example, if idex &gt; total num, then 'pass'&#xD;&#xA;&#xD;&#xA;Or&#xD;&#xA;&#xD;&#xA;The Opengl deals this problem automatically? &#xD;&#xA;&#xD;&#xA;(ex, There is no problem situation.)&#xD;&#xA;&#xD;&#xA;I tried to check by myself. Even though I make overflow situation, there was no warning.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16680" PostHistoryTypeId="1" PostId="6022" RevisionGUID="61885625-fbcc-4c2f-b969-3803d54f580b" CreationDate="2017-12-21T01:01:33.720" UserId="6806" Text="Process of compute shader in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="16681" PostHistoryTypeId="3" PostId="6022" RevisionGUID="61885625-fbcc-4c2f-b969-3803d54f580b" CreationDate="2017-12-21T01:01:33.720" UserId="6806" Text="|opengl|shader|gpu|compute-shader|gpgpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16682" PostHistoryTypeId="2" PostId="6023" RevisionGUID="550d3034-eb94-4174-8dff-0d84c0910dea" CreationDate="2017-12-21T03:37:31.990" UserId="1952" Text="Normally $sin(\theta)$ isn't written as part of the pdf, because it's an artifact from using double integral for spherical integration. The double integral does the integration over a rectangular domain (in you case of size $2\pi$ x $\pi/2$), while you want integration over a sphere/hemisphere, so $sin(\theta)$ is added there as a weight function to transform rectangular to spherical integration.&#xD;&#xA;&#xD;&#xA;A common notation is to use integration over solid angle with single integral and differential solid angle $d\omega$ denoting 2D integration over sphere, and you won't see the $sin(\theta)$ term in there." ContentLicense="CC BY-SA 3.0" />
  <row Id="16683" PostHistoryTypeId="2" PostId="6024" RevisionGUID="06ce24f3-b433-4651-9618-54f2e353fb0b" CreationDate="2017-12-21T04:15:02.363" UserId="1952" Text="You need to perform integration of $P$ over the hemisphere to [calculate the solution][1]. There doesn't seem to be closed-form solution as the solution requires [incomplete gamma function][2]:&#xD;&#xA;$$2\pi(e^{-\alpha d}-\alpha d\Gamma(0,\alpha d))$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.wolframalpha.com/input/?i=Integrate%5BExp%5B-alpha%2FCos%5Btheta%5D%5D*sin%5Btheta%5D,%20%7Btheta,%200,%20pi%2F2%7D,%20%7Bphi,%200,%202pi%7D%5D&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Incomplete_gamma_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="16684" PostHistoryTypeId="5" PostId="6019" RevisionGUID="3049e550-5213-4e3e-8ec7-8b7949e4b4ed" CreationDate="2017-12-21T04:43:35.803" UserId="1937" Comment="added 618 characters in body" Text="I wrote a simple Phong shader with two directional lights for a project, and noticed an unpleasant artifact in the lighting. Where both lights are illuminating the same region, dark bands appear at the light terminators where N.L reaches zero. At first I thought it must be a bug in my code, but a quick test revealed the Unity standard shader has the exact same problem.&#xD;&#xA;&#xD;&#xA;[![my shader][1]][1]&#xD;&#xA;[![unity shader][2]][2]&#xD;&#xA;&#xD;&#xA;My best guess is that this is some form of the Mach effect, and our retinas are overshooting where the brightness plateaus. Does anyone know any tricks to mitigate this effect?&#xD;&#xA;&#xD;&#xA;EDIT FOR CLARITY:&#xD;&#xA;&#xD;&#xA;Here are two more images to illustrate the effect better - one with my shader, and one with Unity's diffuse shader, with the lights at 90 degrees and all specular and ambient contributions removed. &#xD;&#xA;&#xD;&#xA;[![mine][3]][3][![unity][4]][4]&#xD;&#xA;&#xD;&#xA;You can clearly see the dark bands around the top right quadrant where one light's terminator intersects the other's area of effect (well, I can anyway, YMMV). I've run an eyedropper over it and confirmed it's a perceptual effect, the pixels do not in fact get darker.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RKu8H.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YJesJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Dyaw5.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/T5PCZ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16688" PostHistoryTypeId="2" PostId="6026" RevisionGUID="71ab7ae3-9b09-4468-a28b-38ee4e4baa72" CreationDate="2017-12-21T15:28:16.737" UserId="2654" Text="&gt; The Opengl deals this problem automatically? &#xD;&#xA;&#xD;&#xA;How could it? At no point do you inform OpenGL that you only want 900 invocations. You have exactly 2 mechanisms to control the number of invocations: the work group size in the shader, and the work group count in the dispatch call. That determines how many invocations there are.&#xD;&#xA;&#xD;&#xA;If you want a variable number of invocations with a fixed work group size, then your shader has to be given the actual maximum number of operations, and you have to explicitly not do anything for invocations beyond that size." ContentLicense="CC BY-SA 3.0" />
  <row Id="16689" PostHistoryTypeId="5" PostId="5344" RevisionGUID="7958af67-08ff-4f4a-b65d-d4ea343d108a" CreationDate="2017-12-22T01:38:11.077" UserId="6968" Comment="edited body" Text="Since we're not told what defintion of &quot;center&quot; to use, we may as well use the easiest. This would be &#xD;&#xA;$$&#xD;&#xA;\text{Center} = \frac14( \mathbf{P}_0 + \mathbf{P}_1 + \mathbf{P}_2 + \mathbf{P}_3)&#xD;&#xA;$$&#xD;&#xA;where $\mathbf{P}_0$, $\mathbf{P}_1$,  $\mathbf{P}_2$,  $\mathbf{P}_3$ are the control points of the curve. " ContentLicense="CC BY-SA 3.0" />
  <row Id="16694" PostHistoryTypeId="5" PostId="6023" RevisionGUID="9972f92e-0c14-4f08-8c15-817a72d79461" CreationDate="2017-12-22T04:43:25.617" UserId="1952" Comment="added 542 characters in body" Text="Normally $sin(\theta)$ isn't written as part of the pdf, because it's an artifact from using double integral for spherical integration. The double integral does the integration over a rectangular domain (in you case of size $2\pi$ x $\pi/2$), while you want integration over a sphere/hemisphere, so $sin(\theta)$ is added there as a weight function to transform rectangular to spherical integration.&#xD;&#xA;&#xD;&#xA;A common notation is to use integration over solid angle with single integral and differential solid angle $d\omega$ denoting 2D integration over sphere, and you won't see the $sin(\theta)$ term in there.&#xD;&#xA;&#xD;&#xA;To clarify, the notation with single integral has constant infinitesimally small solid angle $d\omega$ over the sphere. However, for the double integral over $\theta$ and $\phi$ the solid angle isn't constant (think of [sphere tessellation][1]) but a function of $sin(\theta)$. In case of Monte Carlo integration and even distribution of samples over the sphere, each sample represents solid angle of $2\pi/N$ steradians and there's no $sin(\theta)$ solid angle weighting required.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Sphere#/media/File:Sphere_wireframe_10deg_6r.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16695" PostHistoryTypeId="5" PostId="6023" RevisionGUID="4e35d59f-b0ae-40dc-9fdd-33a68b560b99" CreationDate="2017-12-22T04:51:00.597" UserId="1952" Comment="added 4 characters in body" Text="Normally $sin(\theta)$ isn't written as part of the pdf, because it's an artifact from using double integral for spherical integration. The double integral does the integration over a rectangular domain (in you case of size $2\pi$ x $\pi/2$), while you want integration over a sphere/hemisphere, so $sin(\theta)$ is added there as a weight function to transform rectangular to spherical integration.&#xD;&#xA;&#xD;&#xA;A common notation is to use integration over solid angle with single integral and differential solid angle $d\omega$ denoting 2D integration over sphere, and you won't see the $sin(\theta)$ term in there.&#xD;&#xA;&#xD;&#xA;To clarify, the notation with single integral has constant infinitesimally small solid angle $d\omega$ over the sphere. However, for the double integral over $\theta$ and $\phi$ the solid angle isn't constant (think of [sphere tessellation][1]) but a function of $sin(\theta)$. In case of Monte Carlo integration and even distribution of samples over the hemisphere, each sample represents solid angle of $2\pi/N$ steradians and there's no $sin(\theta)$ solid angle weighting required.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Sphere#/media/File:Sphere_wireframe_10deg_6r.svg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16696" PostHistoryTypeId="2" PostId="6028" RevisionGUID="d2439a74-6b58-4cb5-90bb-8ffc3c1d0fde" CreationDate="2017-12-22T09:34:44.743" UserId="7412" Text="Given shapes like these, which contain just Arcs and lines, I want to round all its corners with certain radius. I know the vertices of the lines &amp; arcs these shapes.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I can round the corners of a polygon (when two lines meet to form a corner), but can't figure out how to round a corner formed by an Arc and a Line.&#xD;&#xA;&#xD;&#xA;I used this post to round the corners of polygon - https://stackoverflow.com/questions/24771828/algorithm-for-creating-rounded-corners-in-a-polygon&#xD;&#xA;&#xD;&#xA;Could you please share a code snippet, or just explain/list the math/algorithm behind achieving this? Thanks!&#xD;&#xA;&#xD;&#xA;PS: I'm developing a CAD drawing generator using C# &amp; .netDxf library&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/F1Hlh.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16697" PostHistoryTypeId="1" PostId="6028" RevisionGUID="d2439a74-6b58-4cb5-90bb-8ffc3c1d0fde" CreationDate="2017-12-22T09:34:44.743" UserId="7412" Text="Rounding a corner formed by Arc and Line" ContentLicense="CC BY-SA 3.0" />
  <row Id="16698" PostHistoryTypeId="3" PostId="6028" RevisionGUID="d2439a74-6b58-4cb5-90bb-8ffc3c1d0fde" CreationDate="2017-12-22T09:34:44.743" UserId="7412" Text="|computational-geometry|geometry|polygon|edge-detection|cad|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16700" PostHistoryTypeId="2" PostId="6029" RevisionGUID="ea65130d-4dc3-43a7-bb87-c3633331c3d0" CreationDate="2017-12-22T10:01:57.720" UserId="2308" Text="I have this GLSL function that I am trying to optimize because it is going to be ran on many pixels of an older devices GPU. There is no room for branching inefficiency. Essentially this function returns a 0 or a 1 based on the variables `actualY` `shouldY` and `state`&#xD;&#xA;&#xD;&#xA;    float val = 0.0;&#xD;&#xA;    if (actualY &lt; shouldY) {&#xD;&#xA;    	val = 1.0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if (state &gt;= 20.0 &amp;&amp; state &lt; 40.0) { //The equal/not equals is VERY important&#xD;&#xA;      return 1.0 - val;&#xD;&#xA;    }&#xD;&#xA;    return val;&#xD;&#xA;&#xD;&#xA;Usually I am fairly good at removing branching from GLSL code but I really don't know what to do with the range check for the state variable." ContentLicense="CC BY-SA 3.0" />
  <row Id="16701" PostHistoryTypeId="1" PostId="6029" RevisionGUID="ea65130d-4dc3-43a7-bb87-c3633331c3d0" CreationDate="2017-12-22T10:01:57.720" UserId="2308" Text="Getting rid of branching to check if a variable is within a range in GLSL" ContentLicense="CC BY-SA 3.0" />
  <row Id="16702" PostHistoryTypeId="3" PostId="6029" RevisionGUID="ea65130d-4dc3-43a7-bb87-c3633331c3d0" CreationDate="2017-12-22T10:01:57.720" UserId="2308" Text="|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16703" PostHistoryTypeId="2" PostId="6030" RevisionGUID="841c66b4-3a2c-478b-a3d8-92b873da52d8" CreationDate="2017-12-22T11:17:55.480" UserId="4958" Text="This could be done that way:&#xD;&#xA;&#xD;&#xA;First condition is `float val = step(ActualY, shouldY);`&#xD;&#xA;&#xD;&#xA;Then, the condition: `state &gt;= 20.0 &amp;&amp; state &lt; 40.0` can be changed to &#xD;&#xA;&#xD;&#xA;`step(20.0, state) - step(40.0, state)`. This equals 0.0 if outside of range and 1.0 if inside.&#xD;&#xA;&#xD;&#xA;Let `a = step(20.0, state) - step(40.0, state)`&#xD;&#xA;&#xD;&#xA;Then we know that mix function:&#xD;&#xA;&#xD;&#xA;    genType mix(genType x,&#xD;&#xA;     	genType y,&#xD;&#xA;     	genType a);&#xD;&#xA;&#xD;&#xA;Is $$x * (1 - a) + y * a  = val * (1 - a) + (1 - val) * a  = val - 2*a*val + a$$&#xD;&#xA;&#xD;&#xA;So final code is:&#xD;&#xA;&#xD;&#xA;    float val = step(ActualY, shouldY);&#xD;&#xA;    float a = step(20.0, state) - step(40.0, state);&#xD;&#xA;    return val - 2.0*a*val + a;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16704" PostHistoryTypeId="5" PostId="6030" RevisionGUID="6c6ffbf8-75c3-4eab-b33c-610a413b5ec5" CreationDate="2017-12-22T12:31:26.967" UserId="4958" Comment="added 4 characters in body" Text="This could be done that way:&#xD;&#xA;&#xD;&#xA;First condition is `float val = 1.0-step(shouldY, ActualY);`&#xD;&#xA;&#xD;&#xA;Then, the condition: `state &gt;= 20.0 &amp;&amp; state &lt; 40.0` can be changed to &#xD;&#xA;&#xD;&#xA;`step(20.0, state) - step(40.0, state)`. This equals 0.0 if outside of range and 1.0 if inside.&#xD;&#xA;&#xD;&#xA;Let `a = step(20.0, state) - step(40.0, state)`&#xD;&#xA;&#xD;&#xA;Then we know that mix function:&#xD;&#xA;&#xD;&#xA;    genType mix(genType x,&#xD;&#xA;     	genType y,&#xD;&#xA;     	genType a);&#xD;&#xA;&#xD;&#xA;Is $$x * (1 - a) + y * a  = val * (1 - a) + (1 - val) * a  = val - 2*a*val + a$$&#xD;&#xA;&#xD;&#xA;So final code is:&#xD;&#xA;&#xD;&#xA;    float val = 1.0-step(shouldY, ActualY);&#xD;&#xA;    float a = step(20.0, state) - step(40.0, state);&#xD;&#xA;    return val - 2.0*a*val + a;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16705" PostHistoryTypeId="2" PostId="6031" RevisionGUID="14d7fd57-68a1-431b-8170-062e06cbe2f4" CreationDate="2017-12-22T14:09:57.817" UserId="7936" Text="I'm trying to tansfert the texture colors to vertices colors to have a .ply file. For this, I tried the &quot;transfer&quot; function of Meshlab. However this did not work. I also tried a Parametrisation and Texture from Raster images, this lead to a texture that is not coherent. Please find the files of the 3D mesh in this link if you want to try https://archive3d.net/?a=download&amp;id=d269a6f8&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="16706" PostHistoryTypeId="1" PostId="6031" RevisionGUID="14d7fd57-68a1-431b-8170-062e06cbe2f4" CreationDate="2017-12-22T14:09:57.817" UserId="7936" Text="Texture Transfert 3D mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="16707" PostHistoryTypeId="3" PostId="6031" RevisionGUID="14d7fd57-68a1-431b-8170-062e06cbe2f4" CreationDate="2017-12-22T14:09:57.817" UserId="7936" Text="|texture|3d|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16708" PostHistoryTypeId="2" PostId="6032" RevisionGUID="66fd5dce-005f-4ce0-b8e0-77bdf3d53e2d" CreationDate="2017-12-22T14:17:50.210" UserId="4652" Text="Eye position, projection reference point PRP, camera center, or projection center are all just different words for the same thing. &#xD;&#xA;&#xD;&#xA;gluLookAt() applied to the GL_MODELVIEW matrix works for both, parallel and perspective projection.&#xD;&#xA;&#xD;&#xA;You can choose between parallel and perspective projection by setting up the GL_PROJECTION matrix. For perspective projection this can be done using the gluPerspective() function.&#xD;&#xA;&#xD;&#xA;http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/graphics_6_1_eng_web.html#19&#xD;&#xA;&#xD;&#xA;I hope this is the answer you are looking for. Or do you maybe mean by &quot;projection reference point&quot; the 2D vanishing points of the camera? " ContentLicense="CC BY-SA 3.0" />
  <row Id="16709" PostHistoryTypeId="10" PostId="6031" RevisionGUID="8f4eb73e-2514-4910-acf9-0629747cdf55" CreationDate="2017-12-22T14:48:32.937" UserId="2041" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="16711" PostHistoryTypeId="2" PostId="6033" RevisionGUID="6b93b10f-aaae-47fd-a435-5adaec835817" CreationDate="2017-12-22T17:02:39.707" UserId="7937" Text=" - simpler formulas&#xD;&#xA; - Fewer special cases&#xD;&#xA; - Unification and &#xD;&#xA; - Duality" ContentLicense="CC BY-SA 3.0" />
  <row Id="16713" PostHistoryTypeId="5" PostId="6031" RevisionGUID="47aac5ab-e91c-4908-9c75-bd2977eabd6b" CreationDate="2017-12-22T17:28:12.107" UserId="7936" Comment="I changed the formulation of my question since some people thought that I'm talking about art graphic.. I'm talking about 3D mesh processing" Text="I have a textured 3D mesh. I want to deduce a 3D mesh without texture, but with an RGB vector color on each node of this 3D mesh. The colors have to be picked from the initial texture. Is there a way to do this ? My question isn't related to art work. It's related to 3D mesh processing.&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="16714" PostHistoryTypeId="2" PostId="6034" RevisionGUID="407eab82-c862-4fdc-91da-90369a43be9b" CreationDate="2017-12-22T20:59:56.793" UserId="7740" Text="Imagine you want to represent transformations using matrices. Points could be stored as $$\begin{bmatrix}x\\y\end{bmatrix}$$ and you could represent a rotation as $$\begin{bmatrix}u\\v\end{bmatrix}=\begin{bmatrix}cos(\theta)&amp;-sin(\theta)\\sin(\theta)&amp;cos(\theta)\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}$$ and scaling as $$\begin{bmatrix}u\\v\end{bmatrix}=\begin{bmatrix}k1&amp;0\\0&amp;k2\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}$$ These are known as linear transformations and they allow us to do transformations as matrix multiplications. But notice that you cannot do translations as a matrix multiplication. Instead you have to do $$\begin{bmatrix}u\\v\end{bmatrix}=\begin{bmatrix}x\\y\end{bmatrix}+\begin{bmatrix}s\\t\end{bmatrix}$$ This is known as an affine transformation. However this is undesirable (computationally).&#xD;&#xA;&#xD;&#xA;Let R and S be rotation and scaling matrices and T be a translation vector. In computer graphics, you may need to do a series of translations to a point. You could imagine how tricky this could get.&#xD;&#xA;&#xD;&#xA;Scale, translate, then rotate and scale, then translate again: $$p'=SR(Sp+T)+T$$&#xD;&#xA;Not too bad but imagine you had do this computation on a million points. What we would like is to represent rotation, scaling, and translation all as matrix multiplications. Then those matrices can be pre multiplied together for a single transformation matrix which is easy to do computations with. &#xD;&#xA;&#xD;&#xA;Scale, translate, then rotate and scale, then translate again:&#xD;&#xA;$$M=TSRTS$$ $$p'=Mp$$&#xD;&#xA;&#xD;&#xA;We can achieve this by adding another coordinate to our points. I'm going to show all this for 2D graphics (3D points) but you could extend all this to 3D graphics (4D points).&#xD;&#xA;$$p=\begin{bmatrix}x\\y\\1\end{bmatrix}$$&#xD;&#xA;Rotation matrix:&#xD;&#xA;$$R=\begin{bmatrix}cos(\theta)&amp;-sin(\theta)&amp;0\\sin(\theta)&amp;cos(\theta)&amp;0\\0&amp;0&amp;1\end{bmatrix}$$&#xD;&#xA;Scale matrix:&#xD;&#xA;$$S=\begin{bmatrix}k1&amp;0&amp;0\\0&amp;k2&amp;0\\0&amp;0&amp;1\end{bmatrix}$$&#xD;&#xA;Translation matrix:&#xD;&#xA;$$T=\begin{bmatrix}1&amp;0&amp;t1\\0&amp;1&amp;t2\\0&amp;0&amp;1\end{bmatrix}$$&#xD;&#xA;You should work out some examples to convince yourself that these do in fact give you the desired transformation and that you can compose a series of transformations by multiplying multiple matrices together.&#xD;&#xA;&#xD;&#xA;You could go further and allow the extra coordinate to take on any value. $$p=\begin{bmatrix}x\\y\\w\end{bmatrix}$$ and say this this homogeneous (x, y, w) coordinate represents the euclidean (x, y) coordinate at (x/w, y/w). Normally you cannot do division using matrix transformations, however by allowing w to be a divisor, you can set w to some value (through a matrix multiplication) and allow it to represent division. This is useful for doing projection because (in 3D) you will need to divide the x and y coordinates by -z (in a right handed coordinate system). You can achieve this by simply setting w to -z using the following projection matrix:&#xD;&#xA;$$Q=\begin{bmatrix}1&amp;0&amp;0&amp;0\\0&amp;1&amp;0&amp;0\\0&amp;0&amp;1&amp;0\\0&amp;0&amp;-1&amp;0\end{bmatrix}$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="16716" PostHistoryTypeId="2" PostId="6035" RevisionGUID="8ff4f805-c8c9-4f97-86bf-8a7860949a60" CreationDate="2017-12-23T07:40:48.327" UserId="5944" Text="In the following two graphs,&#xD;&#xA;&#xD;&#xA;  * the red lines are borders of the perspective-projection frustum,&#xD;&#xA;  * the blue lines are to be rasterized,&#xD;&#xA;  * the green lines are perspective-projection lines, which are wrong.&#xD;&#xA;&#xD;&#xA;How do modern GPU pipelines do such clipping given only a perspective-projection matrix?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/A39Hi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/936y3.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16717" PostHistoryTypeId="1" PostId="6035" RevisionGUID="8ff4f805-c8c9-4f97-86bf-8a7860949a60" CreationDate="2017-12-23T07:40:48.327" UserId="5944" Text="Clipping for perspective projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="16718" PostHistoryTypeId="3" PostId="6035" RevisionGUID="8ff4f805-c8c9-4f97-86bf-8a7860949a60" CreationDate="2017-12-23T07:40:48.327" UserId="5944" Text="|opengl|gpu|rasterizer|clipping|directx|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16719" PostHistoryTypeId="11" PostId="6031" RevisionGUID="cfa20ef4-bf87-4d71-a5fc-8271bb8ff627" CreationDate="2017-12-23T09:38:34.503" UserId="2041" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="16720" PostHistoryTypeId="4" PostId="6031" RevisionGUID="24047fd5-b062-4615-9f4a-7bc47214d883" CreationDate="2017-12-23T09:41:39.407" UserId="2041" Comment="The title should explain what the question is, to make it easier for others to find." Text="How do I replace a mesh's texture with vertex colours?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16721" PostHistoryTypeId="2" PostId="6036" RevisionGUID="b8c2870e-468b-4509-9740-b0b7757b8b98" CreationDate="2017-12-23T22:17:43.320" UserId="3003" Text="You can sample the texture in your vertex shader and set the color appropriately. You don't say what system you're using, but for something like an OpenGL vertex shader, it would look something like this (this is a little old school, so it may need updating for modern GL) :&#xD;&#xA;&#xD;&#xA;    uniform sampler2DRect texture;&#xD;&#xA;    varying vec4 color;&#xD;&#xA;    void main ()&#xD;&#xA;    {&#xD;&#xA;        color  = texture2DRect(texture, gl_MultiTexCoord0.xy);&#xD;&#xA;&#xD;&#xA;        vec4    newVertex   = vec4(gl_Vertex.xyz, 1.0);&#xD;&#xA;&#xD;&#xA;        gl_Position = gl_ModelViewProjectionMatrix * newVertex;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Your fragment shader would then just set the color of the fragment to the interpolated color coming from the vertex shader. Something like this:&#xD;&#xA;&#xD;&#xA;    varying vec4 color;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = color;&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16725" PostHistoryTypeId="5" PostId="6021" RevisionGUID="532a3694-1fa2-4a7e-a3f4-a17e71f41999" CreationDate="2017-12-24T19:34:46.213" UserId="7929" Comment="Figure with elements" Text="By default, the eye an the projection reference point PRP are in (0,0,0). I can change the eye position with gluLookAt(), but how can I change the PRP (i.e., the  convergence position for a set of parallel lines) for a perspective projection in OpenGL?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9QdUj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16730" PostHistoryTypeId="2" PostId="6039" RevisionGUID="27abe693-42c3-4fab-ae54-ddd91e5c6b56" CreationDate="2017-12-25T00:32:25.993" UserId="7943" Text="I hope this is the right group to be able to expose my doubts about the implementation of the algorithm shown in this [article][1]. The question I have is how to do the feature curves, what I do not understand is how to use piecewise Bézier cubic spline to build them. I hope someone can help me with an example please to be able to advance with that algorithm. Any help is welcome, thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pdfs.semanticscholar.org/6a7e/8a731dc35fb6c9d740a9f43eb2e84672cad6.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="16731" PostHistoryTypeId="1" PostId="6039" RevisionGUID="27abe693-42c3-4fab-ae54-ddd91e5c6b56" CreationDate="2017-12-25T00:32:25.993" UserId="7943" Text="how to build the feature curves of this algorithm?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16732" PostHistoryTypeId="3" PostId="6039" RevisionGUID="27abe693-42c3-4fab-ae54-ddd91e5c6b56" CreationDate="2017-12-25T00:32:25.993" UserId="7943" Text="|algorithm|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16733" PostHistoryTypeId="2" PostId="6040" RevisionGUID="282fc97b-3199-466f-aa3a-0d6b5c6e1a12" CreationDate="2017-12-25T01:20:41.573" UserId="7945" Text="This question is a little different to your typical questions but I think this is the best community to ask this in.&#xD;&#xA;&#xD;&#xA;I've been interested in lego technic for most my life and have been trying to come up with a way to quickly and easily represent axles, pins, axle holes and pin holes on computers universally. I decided to  use plain ASCII since it is quicker and works on mobile devices and on desktops.&#xD;&#xA;&#xD;&#xA;I made a good representation of the pins, axles and holes in one axis but the problem is that since ASCII is 2D but lego technic is 3D, so rotating or flipping lego parts is very hard to represent and if the entire building axis changes then so do the part orientations.&#xD;&#xA;&#xD;&#xA;Is there some way I can do this?&#xD;&#xA;&#xD;&#xA;Here is my syntax:&#xD;&#xA;&lt;code&gt;&#xD;&#xA;facing the front:&#xD;&#xA;&#xD;&#xA;+ axle hole&#xD;&#xA;× axle&#xD;&#xA;o pin hole&#xD;&#xA;. pin&#xD;&#xA;&#xD;&#xA;facing the side:&#xD;&#xA;&#xD;&#xA;# axle hole&#xD;&#xA;= axle&#xD;&#xA;% pin hole&#xD;&#xA;- pin&#xD;&#xA;&#xD;&#xA;facing the side rotated 90 degrees:&#xD;&#xA;&#xD;&#xA;[ axle hole&#xD;&#xA;! axle&#xD;&#xA;( pinhole&#xD;&#xA;| pin&#xD;&#xA;&lt;/code&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16734" PostHistoryTypeId="1" PostId="6040" RevisionGUID="282fc97b-3199-466f-aa3a-0d6b5c6e1a12" CreationDate="2017-12-25T01:20:41.573" UserId="7945" Text="Creating 3d model building notation using ASCII" ContentLicense="CC BY-SA 3.0" />
  <row Id="16735" PostHistoryTypeId="3" PostId="6040" RevisionGUID="282fc97b-3199-466f-aa3a-0d6b5c6e1a12" CreationDate="2017-12-25T01:20:41.573" UserId="7945" Text="|diagram|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16736" PostHistoryTypeId="5" PostId="6040" RevisionGUID="32d81c2d-6af1-4877-b125-0f659de68e7e" CreationDate="2017-12-25T01:26:46.450" UserId="7945" Comment="added 64 characters in body" Text="This question is a little different to your typical questions but I think this is the best community to ask this in.&#xD;&#xA;&#xD;&#xA;I've been interested in lego technic for most my life and have been trying to come up with a way to quickly and easily represent axles, pins, axle holes and pin holes on computers universally. I decided to  use plain ASCII since it is quicker and works on mobile devices and on desktops.&#xD;&#xA;&#xD;&#xA;I made a good representation of the pins, axles and holes in one axis but the problem is that since ASCII is 2D but lego technic is 3D, so rotating or flipping lego parts is very hard to represent and if the entire building axis changes then so do the part orientations.&#xD;&#xA;&#xD;&#xA;Is there some way I can do this?&#xD;&#xA;&#xD;&#xA;Here is my syntax:&#xD;&#xA;&#xD;&#xA;    facing the front:&#xD;&#xA;    &#xD;&#xA;    + axle hole&#xD;&#xA;    × axle&#xD;&#xA;    o pin hole&#xD;&#xA;    . pin&#xD;&#xA;    &#xD;&#xA;    facing the side:&#xD;&#xA;   &#xD;&#xA;    ^ axle hole&#xD;&#xA;    = axle&#xD;&#xA;    N pin hole&#xD;&#xA;    - pin&#xD;&#xA;    &#xD;&#xA;    facing the side rotated 90 degrees:&#xD;&#xA;    &#xD;&#xA;    &gt; axle hole&#xD;&#xA;    ! axle&#xD;&#xA;    Z pin hole&#xD;&#xA;    | pin&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16737" PostHistoryTypeId="5" PostId="6040" RevisionGUID="1dfcd0c4-cd08-48d3-842d-d7aca528873f" CreationDate="2017-12-25T01:31:53.500" UserId="7945" Comment="added 64 characters in body" Text="This question is a little different to your typical questions but I think this is the best community to ask this in.&#xD;&#xA;&#xD;&#xA;I've been interested in lego technic for most my life and have been trying to come up with a way to quickly and easily represent axles, pins, axle holes and pin holes on computers universally. I decided to  use plain ASCII since it is quicker and works on mobile devices and on desktops.&#xD;&#xA;&#xD;&#xA;I made a good representation of the pins, axles and holes in one axis but the problem is that since ASCII is 2D but lego technic is 3D, so rotating or flipping lego parts is very hard to represent and if the entire building axis changes then so do the part orientations.&#xD;&#xA;&#xD;&#xA;Is there some way I can do this?&#xD;&#xA;&#xD;&#xA;Here is my syntax:&#xD;&#xA;&#xD;&#xA;    facing the front:&#xD;&#xA;    &#xD;&#xA;    + axle hole&#xD;&#xA;    × axle&#xD;&#xA;    o pin hole&#xD;&#xA;    . pin&#xD;&#xA;    &#xD;&#xA;    facing the side:&#xD;&#xA;   &#xD;&#xA;    ^ axle hole&#xD;&#xA;    = axle&#xD;&#xA;    N pin hole&#xD;&#xA;    - pin&#xD;&#xA;    &#xD;&#xA;    facing the side rotated 90 degrees:&#xD;&#xA;    &#xD;&#xA;    &gt; axle hole&#xD;&#xA;    ! axle&#xD;&#xA;    Z pin hole&#xD;&#xA;    | pin&#xD;&#xA;&#xD;&#xA;if a symbol is underlined it means it is half thickness, if not it is worth 1L&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16738" PostHistoryTypeId="5" PostId="6040" RevisionGUID="448ebcd1-8243-45b1-acbc-1460e8ef07aa" CreationDate="2017-12-25T01:46:43.877" UserId="7945" Comment="edited body" Text="This question is a little different to your typical questions but I think this is the best community to ask this in.&#xD;&#xA;&#xD;&#xA;I've been interested in lego technic for most my life and have been trying to come up with a way to quickly and easily represent axles, pins, axle holes and pin holes on computers universally. I decided to  use plain ASCII since it is quicker and works on mobile devices and on desktops.&#xD;&#xA;&#xD;&#xA;I made a good representation of the pins, axles and holes in one axis but the problem is that since ASCII is 2D but lego technic is 3D, so rotating or flipping lego parts is very hard to represent and if the entire building axis changes then so do the part orientations.&#xD;&#xA;&#xD;&#xA;Is there some way I can do this?&#xD;&#xA;&#xD;&#xA;Here is my syntax:&#xD;&#xA;&#xD;&#xA;    facing the front:&#xD;&#xA;    &#xD;&#xA;    + axle hole&#xD;&#xA;    × axle&#xD;&#xA;    o pin hole&#xD;&#xA;    . pin&#xD;&#xA;    &#xD;&#xA;    facing the side:&#xD;&#xA;   &#xD;&#xA;    &lt; axle hole&#xD;&#xA;    = axle&#xD;&#xA;    Z pin hole&#xD;&#xA;    - pin&#xD;&#xA;    &#xD;&#xA;    facing the side rotated 90 degrees:&#xD;&#xA;    &#xD;&#xA;    V axle hole&#xD;&#xA;    ! axle&#xD;&#xA;    N pin hole&#xD;&#xA;    | pin&#xD;&#xA;&#xD;&#xA;if a symbol is underlined it means it is half thickness, if not it is worth 1L&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16739" PostHistoryTypeId="5" PostId="6040" RevisionGUID="098a51af-206d-42c5-98c9-73f6ff55287a" CreationDate="2017-12-25T01:54:29.090" UserId="7945" Comment="deleted 11 characters in body" Text="This question is a little different to your typical questions but I think this is the best community to ask this in.&#xD;&#xA;&#xD;&#xA;I've been interested in lego technic for most my life and have been trying to come up with a way to quickly and easily represent axles, pins, axle holes and pin holes on computers universally. I decided to  use plain ASCII since it is quicker and works on mobile devices and on desktops.&#xD;&#xA;&#xD;&#xA;I made a good representation of the pins, axles and holes in one axis but the problem is: ASCII is 2D but lego technic is 3D, so rotated or flipped lego parts are very hard to represent and if the entire building axis changes then so do the part orientations.&#xD;&#xA;&#xD;&#xA;Is there some way I can do this?&#xD;&#xA;&#xD;&#xA;Here is my syntax:&#xD;&#xA;&#xD;&#xA;    facing the front:&#xD;&#xA;    &#xD;&#xA;    + axle hole&#xD;&#xA;    × axle&#xD;&#xA;    o pin hole&#xD;&#xA;    . pin&#xD;&#xA;    &#xD;&#xA;    facing the side:&#xD;&#xA;   &#xD;&#xA;    &lt; axle hole&#xD;&#xA;    = axle&#xD;&#xA;    Z pin hole&#xD;&#xA;    - pin&#xD;&#xA;    &#xD;&#xA;    facing the side rotated 90 degrees:&#xD;&#xA;    &#xD;&#xA;    V axle hole&#xD;&#xA;    ! axle&#xD;&#xA;    N pin hole&#xD;&#xA;    | pin&#xD;&#xA;&#xD;&#xA;if a symbol is underlined it means it is half thickness, if not it is worth 1L&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16744" PostHistoryTypeId="36" PostId="6042" RevisionGUID="46dfe551-ab18-4b24-80f1-32c713012fea" CreationDate="2017-12-25T21:05:36.663" UserId="-1" Comment="from https://stackoverflow.com/questions/47971954/how-does-anti-aliasing-work-in-general" />
  <row Id="16745" PostHistoryTypeId="2" PostId="6042" RevisionGUID="d7d51e6a-db21-4d45-a6c5-f1ac0de26d28" CreationDate="2017-12-25T20:51:09.160" UserId="7950" Text="I am working on a raytracing Java program for fun. Here's one rendering: [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see I still have to implement anti-aliasing (and there are huge geometry problems I won't get in to). How would one go about this in a raytracing program, where the renderer doesn't really render lines, but individual pixels? Is it even possible? For example, in a scanline rendering, you could apply anti-aliasing after filling a triangle. But in a raytraced rendering, the program works pixel-by-pixel, and doesn't know where object's edges are, or where to smooth things out.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CSWU3.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="16746" PostHistoryTypeId="1" PostId="6042" RevisionGUID="d7d51e6a-db21-4d45-a6c5-f1ac0de26d28" CreationDate="2017-12-25T20:51:09.160" UserId="7950" Text="How does anti-aliasing work, in general?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16747" PostHistoryTypeId="3" PostId="6042" RevisionGUID="d7d51e6a-db21-4d45-a6c5-f1ac0de26d28" CreationDate="2017-12-25T20:51:09.160" UserId="7950" Text="|3d|antialiasing|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16748" PostHistoryTypeId="4" PostId="6042" RevisionGUID="0107a54a-40ba-4457-a4d5-15512d80a269" CreationDate="2017-12-25T21:18:46.993" UserId="7950" Comment="edited title" Text="How does anti-aliasing work, in general, for raytracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16749" PostHistoryTypeId="10" PostId="6042" RevisionGUID="072598a4-e59c-4a80-baa5-a8dbbf5c13e3" CreationDate="2017-12-25T22:16:46.443" UserId="-1" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[4248],&quot;Voters&quot;:[{&quot;Id&quot;:4958,&quot;DisplayName&quot;:&quot;narthex&quot;},{&quot;Id&quot;:-1,&quot;DisplayName&quot;:&quot;Community&quot;,&quot;BindingReason&quot;:{&quot;DuplicateApprovedByAsker&quot;:&quot;&quot;}}]}" />
  <row Id="16751" PostHistoryTypeId="2" PostId="6043" RevisionGUID="191420ee-aca2-4791-a5c5-6dcbc9e4c3ce" CreationDate="2017-12-26T04:35:56.950" UserId="3003" Text="The way I read it, you have a 2D cubic Bézier that defines the projections of the ridge line (or river bed, or whatever) onto the X/Y plane. In Figure 4, these are the dark purple lines.&#xD;&#xA;&#xD;&#xA;So that gives you the direction that the ridge line moves. Now you have to define the height of the ridge line. This is done by picking some points along the 2D Bézier and setting the following values at each of the chosen points:&#xD;&#xA;&#xD;&#xA;    h = height&#xD;&#xA;    r = radius (this appears more like a width at the ridge line than a curved radius)&#xD;&#xA;    &#xD;&#xA;You can then also set the angle of the terrain as it comes off the radius. These are:&#xD;&#xA;&#xD;&#xA;    `phi` and `theta`&#xD;&#xA;    `a` and `b` are the lengths of the slopes&#xD;&#xA;&#xD;&#xA;Keep in mind that you don't have to set every value for every control point you pick. I assume any you don't set are defaulted to 0, or some reasonable default.&#xD;&#xA;&#xD;&#xA;So for a hill, you would set `h` to the height of the hill at a few point. You would then set `phi` and `theta` to be horizontal, so yes, `pi / 4`. The length of `a` and `b` will decide how quickly the hill falls off as you move away from the ridge line.&#xD;&#xA;&#xD;&#xA;It looks like the above 6 values are turned into another cubic Bézier curve that is perpendicular to the first one for the rasterization step in section 4 of the paper. `h` doesn't factor into the shape of the perpendicular Bézier because it's also perpendicular to it. So `r`, `theta`, `phi`, `a` and `b` are used to make a cubic Bézier. I believe that you can think about like this: the point on the ridge line where you define one of these control points is the link between 2 cubic Bézier segments - one to the left of the point and the other to the right. The images they show only show a single point between 2 Bézier curves, but the way I'm reading it there are actually 2 curves that look something like this:&#xD;&#xA;&#xD;&#xA;[![Beziers][1]][1]&#xD;&#xA;&#xD;&#xA;So I think normally, you'd have 2 Béziers. One on each side of the control point they show in the paper. (Pardon my bad drawing.)  `a` would be the distance between control points 2 and 3 of the left curve. `Theta` would be the angle formed between the vertical and `a` of the left curve. `r` would be the distance between points 3 and 4 of the left curve. I'm unclear on how one would pick control point 1 in this scenario, though.&#xD;&#xA;&#xD;&#xA;`Ai` and `Ri` have to do with the noise parameters and don't appear to me to be related to the Bézier curves at all.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/L6TPF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16752" PostHistoryTypeId="2" PostId="6044" RevisionGUID="e8ffad17-3bed-4e37-b9a9-cca7c0eb20c4" CreationDate="2017-12-26T11:40:51.503" UserId="6046" Text="If you are talking about an oblique perspective projection in which the line joining the eye and center of the projection plane is not perpendicular to the plane like here (upper left),&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This can be generated by the `glFrustum()` call. Normally when you describe perspective projection they set &#xD;&#xA;&#xD;&#xA;`left = -right`&#xD;&#xA;&#xD;&#xA;`bottom = -top`&#xD;&#xA;&#xD;&#xA;so that these are centered around the Z-axis. In order to generate an oblique projection you can use the [above][2] mentioned method which takes input the coordinates for left, right, top, bottom, near and far planes.&#xD;&#xA;&#xD;&#xA;The other way around is to build your own custom projection matrix, and load it directly. The matrix should be stored as an array&#xD;&#xA;&#xD;&#xA;`GLfloat mat[16] = {...}&#xD;&#xA; GlLoadMatrix(mat)`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dJInW.png&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="16753" PostHistoryTypeId="2" PostId="6045" RevisionGUID="4e8f8d77-10c5-4686-b3a2-d363c54eb3d0" CreationDate="2017-12-26T11:50:35.493" UserId="6806" Text="I'm working with OpenGL and facing some difficulties because I'm not familiar with OpenGL. I tried to search related example in Google, but I could not find some useful code.  &#xD;&#xA;&#xD;&#xA;There are five arrays.&#xD;&#xA;I bound and changed the data in compute shahder as follows:&#xD;&#xA;&#xD;&#xA;    computeShader.use();&#xD;&#xA;    int bufferSize = sizeof(vertices) * vertices.size();&#xD;&#xA;	glGenBuffers(1, &amp;vbo_Previous);&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Previous);&#xD;&#xA;	glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vbo_Previous);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;vbo_Current);&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Current);&#xD;&#xA;	glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbo_Current);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;vbo_Next);&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Next);&#xD;&#xA;	glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, vbo_Next);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;vbo_Normal);&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Normal);&#xD;&#xA;	glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;normals[0], GL_STATIC_DRAW);&#xD;&#xA;	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, vbo_Normal);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;vbo_Tangent);&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Tangent);&#xD;&#xA;	glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;tangents[0], GL_STATIC_DRAW);&#xD;&#xA;	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, vbo_Tangent);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;vbo_Binormal);&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Binormal);&#xD;&#xA;	glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;binormals[0], GL_STATIC_DRAW);&#xD;&#xA;	glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, vbo_Binormal);&#xD;&#xA;	computeShader.unUse();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And I want to use the data in vertex shader.&#xD;&#xA;I tried like that, but I doesn't work. &#xD;&#xA;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;	glGenBuffers(1, &amp;ebo);&#xD;&#xA;	glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	int bufferOffset = 0;&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Next);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)(bufferOffset));&#xD;&#xA;&#xD;&#xA;	bufferOffset += sizeof(glm::vec4) * vertices.size();&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Normal);&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;	glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(bufferOffset));&#xD;&#xA;&#xD;&#xA;	bufferOffset += sizeof(glm::vec4) * normals.size();&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Tangent);&#xD;&#xA;	glEnableVertexAttribArray(2);&#xD;&#xA;	glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*)(bufferOffset));&#xD;&#xA;&#xD;&#xA;	bufferOffset += sizeof(glm::vec4) * tangents.size();&#xD;&#xA;	glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Binormal);&#xD;&#xA;	glEnableVertexAttribArray(3);&#xD;&#xA;	glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, (void*)(bufferOffset));&#xD;&#xA;&#xD;&#xA;	//Because the texture coordinate are not changed in compute shader I generated the vbo for texture coordinate data&#xD;&#xA;	bufferOffset += sizeof(glm::vec4) * binormals.size();&#xD;&#xA;	glGenBuffers(1, &amp;vbo);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*texCoords.size(), &amp;texCoords[0], GL_STATIC_DRAW);&#xD;&#xA;	glEnableVertexAttribArray(4);&#xD;&#xA;	glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 0, (void*)(bufferOffset));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope to use the data in vertex shader as follows:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout(location = 0) in vec4 aPos;&#xD;&#xA;    layout(location = 1) in vec4 aNormal;&#xD;&#xA;    layout(location = 2) in vec4 aTangent;&#xD;&#xA;    layout(location = 3) in vec4 aBinormal;&#xD;&#xA;    layout(location = 4) in vec2 aTexCoord;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;How to set vertex object array to use the data?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16754" PostHistoryTypeId="1" PostId="6045" RevisionGUID="4e8f8d77-10c5-4686-b3a2-d363c54eb3d0" CreationDate="2017-12-26T11:50:35.493" UserId="6806" Text="How to use the data manipulated in OpenGL Compute Shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="16755" PostHistoryTypeId="3" PostId="6045" RevisionGUID="4e8f8d77-10c5-4686-b3a2-d363c54eb3d0" CreationDate="2017-12-26T11:50:35.493" UserId="6806" Text="|opengl|shader|compute-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16756" PostHistoryTypeId="2" PostId="6046" RevisionGUID="45e43dd9-b195-47e9-84e8-f07c9a4b9650" CreationDate="2017-12-26T14:48:51.100" UserId="6046" Text="I think you are confusing all the binding targets thingy. From what I see your vertex data is coming from compute shader after some processing and now you want to pass it to the vertex shader.&#xD;&#xA;&#xD;&#xA;You can create a buffer object once, use it as an SSBO for use in a compute shader then use it as a VBO for use in rendering. i.e&#xD;&#xA;&#xD;&#xA;    // Setup SSBO for use in Compute shader&#xD;&#xA;    glGenBuffers(1, &amp;vbo_Current);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbo_Current);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbo_Current);&#xD;&#xA;&#xD;&#xA;    // Setup the same Buffer object as VBO for use in rendering&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo_Current);   &lt;- Note the change in binding target&#xD;&#xA;    GlVertexAttribPointer().......                &lt;- set your vertex data&#xD;&#xA;    &#xD;&#xA;Hence there is no need to generate 1 more buffer object for the texture, just pass the same buffer but change the binding points to `GL_ARRAY_BUFFER`&#xD;&#xA;&#xD;&#xA;However do note that you need to use appropriate Memory barrier calls as SSBO reads and writes are incoherent memory accesses. Don't know much about these but you can find more information [here][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Memory_Model" ContentLicense="CC BY-SA 3.0" />
  <row Id="16758" PostHistoryTypeId="2" PostId="6047" RevisionGUID="45706f54-43d9-40c9-8f83-f3f35a3c177c" CreationDate="2017-12-26T17:42:23.180" UserId="5748" Text="I suppose you want an arc of C0 and C1 continuity between the line and an arc.&#xD;&#xA;[![Rounding corner illustration][1]][1]&#xD;&#xA;&#xD;&#xA;As illustrated above, you already have a vertex A which is the intersection of an edge and an arc of which the center positioned at O and radius equal to R. The question is thus pure mathematical: given A,O,R, edge direction BA, and a corner radius r, find C,B, and T.&#xD;&#xA;For simplicity, here let's assume that the black dotted line has the form of $C_y=kC_x+b$, where k is the same as edge BA while b is easily derived by combining k and rounding radius r. Therefore, three constraint equations can be listed to solve $C_x$:&#xD;&#xA;&#xD;&#xA;1. The distance TC is r: $(T_x-C_x)^2+(T_y-C_y)^2=r^2$&#xD;&#xA;2. The big arc equation: $(T_x-O_x)^2+(T_y-O_y)^2=R^2$&#xD;&#xA;3. Point C is on OT: $\frac{T_y-C_y}{T_x-C_x}=\frac{T_y-O_y}{T_x-O_x}$&#xD;&#xA;&#xD;&#xA;Solve for Cx and you'll obtain four solutions (I used Mathematica):&#xD;&#xA;&#xD;&#xA;$C_x=\frac{-bk+O_x+kO_y\pm\sqrt{-(O_y-kO_x-b)^2+(1+k^2)(R+r)^2}}{1+k^2}$&#xD;&#xA;$C_x=\frac{-bk+O_x+kO_y\pm\sqrt{-(O_y-kO_x-b)^2+(1+k^2)(R-r)^2}}{1+k^2}$&#xD;&#xA;&#xD;&#xA;Given four Cx values, they can be used to derive Cy values to make a candidate list for point C. Pick the correct C using inside/outside check (if you draw the entire line and arcs, you can see that all four candidate points meet the aforementioned constraints, so you have to choose the right one by yourself).&#xD;&#xA;&#xD;&#xA;Now you have the center C of the round corner arc as well as its radius r. It should be relatively easy to determine point B and point T, and draw an arc through the two points.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VC5L4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16759" PostHistoryTypeId="5" PostId="6047" RevisionGUID="939637b4-9955-4ace-9b79-4e4b27ee6f25" CreationDate="2017-12-26T17:58:31.897" UserId="5748" Comment="deleted 111 characters in body; edited body; added 18 characters in body" Text="I suppose you want an arc of C0 and C1 continuity between the line and an arc.&#xD;&#xA;[![Rounding corner illustration][1]][1]&#xD;&#xA;&#xD;&#xA;As illustrated above, you already have a vertex A which is the intersection of an edge and an arc of which the center positioned at O and radius equal to R. The question is thus pure mathematical: given A,O,R, edge direction BA, and a corner radius r, find C,B, and T.&#xD;&#xA;For simplicity, here let's assume that the black dotted line has the form of $C_y=kC_x+b$, where k is the same as edge BA while b is easily derived by combining k and rounding radius r. Therefore, three constraint equations can be listed to solve $C_x$:&#xD;&#xA;&#xD;&#xA;1. The distance TC is r: $(T_x-C_x)^2+(T_y-C_y)^2=r^2$&#xD;&#xA;2. The big arc equation: $(T_x-O_x)^2+(T_y-O_y)^2=R^2$&#xD;&#xA;3. Point C is on OT: $\frac{T_y-C_y}{T_x-C_x}=\frac{T_y-O_y}{T_x-O_x}$&#xD;&#xA;&#xD;&#xA;Solve for Cx and you'll obtain four solutions (I used Mathematica):&#xD;&#xA;&#xD;&#xA;$C_x=\frac{-bk+O_x+kO_y\pm\sqrt{-(O_y-kO_x-b)^2+(1+k^2)(R-r)^2}}{1+k^2}$&#xD;&#xA;$C_x=\frac{-bk+O_x+kO_y\pm\sqrt{-(O_y-kO_x-b)^2+(1+k^2)(R+r)^2}}{1+k^2}$&#xD;&#xA;&#xD;&#xA;The second expression is out of the arc, so you should use the first solutions. Given the two Cx values, they can be used to derive Cy values to make a candidate list for point C. Pick the correct C using manual check.&#xD;&#xA;&#xD;&#xA;Now you have the center C of the round corner arc as well as its radius r. It should be relatively easy to determine point B and point T, and draw an arc through the two points.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VC5L4.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16764" PostHistoryTypeId="2" PostId="6049" RevisionGUID="5f0efff4-05a4-4363-b1ed-f061427e61f0" CreationDate="2017-12-27T06:43:25.317" UserId="1937" Text="I can see a few things wrong here. &#xD;&#xA;&#xD;&#xA;First, you're setting your GL buffer size to `sizeof(vertices) * vertices.size()`&#xD;&#xA;This looks wrong. What is vertices? A std::array of vec4? Then you want `vertices.size() * sizeof(glm::vec4)`, or just `sizeof(vertices)`&#xD;&#xA;&#xD;&#xA;Second, as wandering-warrior said, you want to be binding to `GL_ARRAY_BUFFER` before calling `glVertexAttribPointer`&#xD;&#xA;&#xD;&#xA;Third, I don't know what you're doing with `bufferOffset` in the second part of the code. This is a valid approach if the data is laid out sequentially in one large buffer (vertices then normals then tangents etc. etc.). But in your case you're using a separate buffer for each data set - so each attribute should start reading from the beginning of its own buffer, i.e. `bufferOffset` should always be 0. &#xD;&#xA;&#xD;&#xA;Fourth, you don't seem to be actually *using* your compute shader anywhere. It's not enough to just call `glUseProgram`, you need to call `glDispatchCompute` after you bind your buffers to actually run it.&#xD;&#xA;&#xD;&#xA;Also, it's not common practice to store binormals in an array, since they can be reconstructed in the fragment shader from the tangent and normal using a cross product.&#xD;&#xA;&#xD;&#xA;I would do it something like this (using OpenGL 4.5 with the new Direct State Access functions to save all those buffer bindings).&#xD;&#xA;&#xD;&#xA;    int bufferSize = sizeof(vertices);&#xD;&#xA;&#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Previous);&#xD;&#xA;    glNamedBufferData(vbo_Previous, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vbo_Previous);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Current);&#xD;&#xA;    glNamedBufferData(vbo_Current, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbo_Current);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Next);&#xD;&#xA;    glNamedBufferData(vbo_Next, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, vbo_Next);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Normal);&#xD;&#xA;    glNamedBufferData(vbo_Normal, bufferSize, &amp;normals[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, vbo_Normal);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Tangent);&#xD;&#xA;    glNamedBufferData(vbo_Tangent, bufferSize, &amp;tangents[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, vbo_Tangent);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Texcoords);&#xD;&#xA;    glNamedBufferData(vbo_Texcoords, sizeof(texCoords), &amp;texCoords[0], &#xD;&#xA;    GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glCreateBuffers(1, &amp;ebo);&#xD;&#xA;    glNamedBufferData(ebo, sizeof(elements), &amp;elements[0], GL_STATIC_DRAW);&#xD;&#xA;    //you have element data in an array, right?&#xD;&#xA;    &#xD;&#xA;    glCreateVertexArrays(1, &amp;vao);&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    glBindVertexBuffer(0, vbo_Next, 0, 0);&#xD;&#xA;    glVertexAttribBinding(0,0);&#xD;&#xA;    glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glBindVertexBuffer(1, vbo_Normal, 0, 0);&#xD;&#xA;    glVertexAttribBinding(1,1);&#xD;&#xA;    glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glBindVertexBuffer(2, vbo_Tangent, 0, 0);&#xD;&#xA;    glVertexAttribBinding(2,2);&#xD;&#xA;    glVertexAttribFormat(2, 4, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glBindVertexBuffer(3, vbo_Texcoords, 0, 0);&#xD;&#xA;    glVertexAttribBinding(3,3);&#xD;&#xA;    glVertexAttribFormat(3, 2, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glVertexArrayElementBuffer(vao, ebo);&#xD;&#xA;&#xD;&#xA;    computeShader.use();&#xD;&#xA;    glDispatchCompute (/*number of groups*/)&#xD;&#xA;    computeShader.unUse();&#xD;&#xA;&#xD;&#xA;    glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;    renderShader.use();&#xD;&#xA;    glDrawElements(GL_TRIANGLES, elements.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;    renderShader.unUse();" ContentLicense="CC BY-SA 3.0" />
  <row Id="16773" PostHistoryTypeId="2" PostId="6052" RevisionGUID="62521faf-81a3-4c87-90c5-bcbe1a42ca21" CreationDate="2017-12-28T04:07:40.420" UserId="7957" Text="3D clipping is usually done in clipdpace coordinates, that means the perspective matrix is used for sending the primitives to clipspace before doing the actual perspective projection. You can see the clipspace as a view frustum with the shape of a box. So it is very fast to clip primitives against a AABB. The math is a little involved, but is all explained in this blog post: &#xD;&#xA;&#xD;&#xA;https://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16774" PostHistoryTypeId="2" PostId="6053" RevisionGUID="8e245447-4abf-4959-a047-7504cefeeb8c" CreationDate="2017-12-28T04:17:42.153" UserId="6541" Text="&#xD;&#xA;&#xD;&#xA;![image](https://user-images.githubusercontent.com/16706911/34399964-ae3c684a-eba1-11e7-95f1-2696a37b650c.JPG)&#xD;&#xA;&#xD;&#xA;I used Stencil Buffer for fixing your problem , you need a way for checking [overlapping two or more shapes][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Shader &quot;Custom/SemiTransparent&quot;&#xD;&#xA;    {&#xD;&#xA;        Properties&#xD;&#xA;        {&#xD;&#xA;    		_Color(&quot;Color&quot;,Color) = (0,0,1,0.1)&#xD;&#xA;        }&#xD;&#xA;        SubShader&#xD;&#xA;        {&#xD;&#xA;    Tags {&quot;Queue&quot;=&quot;Transparent&quot; &quot;IgnoreProjector&quot;=&quot;true&quot; &quot;RenderType&quot;=&quot;Transparent&quot;}&#xD;&#xA;    ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off&#xD;&#xA;    &#xD;&#xA;            LOD 100&#xD;&#xA;    &#xD;&#xA;            Pass&#xD;&#xA;            {&#xD;&#xA;                Stencil {&#xD;&#xA;                    Ref 0&#xD;&#xA;                    Comp Equal&#xD;&#xA;                    Pass IncrSat &#xD;&#xA;                    Fail IncrSat &#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                CGPROGRAM&#xD;&#xA;                #pragma vertex vert&#xD;&#xA;                #pragma fragment frag&#xD;&#xA;    &#xD;&#xA;                #include &quot;UnityCG.cginc&quot;&#xD;&#xA;    &#xD;&#xA;    			fixed4 _Color;&#xD;&#xA;    &#xD;&#xA;                struct appdata&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                struct v2f&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : SV_POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                v2f vert (appdata v)&#xD;&#xA;                {&#xD;&#xA;                    v2f o;&#xD;&#xA;                    o.vertex = UnityObjectToClipPos(v.vertex);&#xD;&#xA;                    return o;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                fixed4 frag (v2f i) : SV_Target&#xD;&#xA;                {&#xD;&#xA;                    fixed4 col = _Color;&#xD;&#xA;                    return col;&#xD;&#xA;                }&#xD;&#xA;                ENDCG&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;    		Tags {&quot;Queue&quot;=&quot;Transparent&quot; &quot;IgnoreProjector&quot;=&quot;true&quot; &quot;RenderType&quot;=&quot;Transparent&quot;}&#xD;&#xA;    ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;            Pass&#xD;&#xA;            {&#xD;&#xA;                Stencil {&#xD;&#xA;                    Ref 1&#xD;&#xA;                    Comp Less&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                CGPROGRAM&#xD;&#xA;                #pragma vertex vert&#xD;&#xA;                #pragma fragment frag&#xD;&#xA;    &#xD;&#xA;                #include &quot;UnityCG.cginc&quot;&#xD;&#xA;    &#xD;&#xA;    			fixed4 _OverlapColor;&#xD;&#xA;    &#xD;&#xA;                struct appdata&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                struct v2f&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : SV_POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                v2f vert (appdata v)&#xD;&#xA;                {&#xD;&#xA;                    v2f o;&#xD;&#xA;                    o.vertex = UnityObjectToClipPos(v.vertex);&#xD;&#xA;                    return o;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                fixed4 frag (v2f i) : SV_Target&#xD;&#xA;                {&#xD;&#xA;                    return 0;&#xD;&#xA;                }&#xD;&#xA;                ENDCG&#xD;&#xA;            }&#xD;&#xA;    		&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/35574227/unity-shader-highlighting-overlaps" ContentLicense="CC BY-SA 3.0" />
  <row Id="16775" PostHistoryTypeId="5" PostId="6053" RevisionGUID="effcbff8-5ae0-4085-9a92-1752d6d70a6d" CreationDate="2017-12-28T04:50:05.820" UserId="6541" Comment="deleted 1116 characters in body" Text="&#xD;&#xA;![image](https://user-images.githubusercontent.com/16706911/34399964-ae3c684a-eba1-11e7-95f1-2696a37b650c.JPG)&#xD;&#xA;&#xD;&#xA;I used Stencil Buffer for fixing your problem , you need a way for checking [overlapping two or more shapes][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     Shader &quot;Custom/SemiTransparent&quot;&#xD;&#xA;    {&#xD;&#xA;        Properties&#xD;&#xA;        {&#xD;&#xA;    		_Color(&quot;Color&quot;,Color) = (0,0,1,0.1)&#xD;&#xA;        }&#xD;&#xA;        SubShader&#xD;&#xA;        {&#xD;&#xA;    Tags {&quot;Queue&quot;=&quot;Transparent&quot; &quot;IgnoreProjector&quot;=&quot;true&quot; &quot;RenderType&quot;=&quot;Transparent&quot;}&#xD;&#xA;    ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off&#xD;&#xA;    &#xD;&#xA;            LOD 100&#xD;&#xA;    &#xD;&#xA;            Pass&#xD;&#xA;            {&#xD;&#xA;                Stencil {&#xD;&#xA;                    Ref 0&#xD;&#xA;                    Comp Equal&#xD;&#xA;                    Pass IncrSat &#xD;&#xA;                    Fail IncrSat &#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                CGPROGRAM&#xD;&#xA;                #pragma vertex vert&#xD;&#xA;                #pragma fragment frag&#xD;&#xA;    &#xD;&#xA;                #include &quot;UnityCG.cginc&quot;&#xD;&#xA;    &#xD;&#xA;    			fixed4 _Color;&#xD;&#xA;    &#xD;&#xA;                struct appdata&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                struct v2f&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : SV_POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                v2f vert (appdata v)&#xD;&#xA;                {&#xD;&#xA;                    v2f o;&#xD;&#xA;                    o.vertex = UnityObjectToClipPos(v.vertex);&#xD;&#xA;                    return o;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                fixed4 frag (v2f i) : SV_Target&#xD;&#xA;                {&#xD;&#xA;                    fixed4 col = _Color;&#xD;&#xA;                    return col;&#xD;&#xA;                }&#xD;&#xA;                ENDCG&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/35574227/unity-shader-highlighting-overlaps" ContentLicense="CC BY-SA 3.0" />
  <row Id="16779" PostHistoryTypeId="5" PostId="6052" RevisionGUID="6504d6f5-8b34-484c-a9e1-911e2c9e3354" CreationDate="2017-12-28T10:56:00.453" UserId="7957" Comment="added 10 characters in body" Text="3D clipping is usually done in clipspace coordinates, that means the perspective matrix is used for sending the primitives to clipspace before doing the actual perspective projection. You can visualize the clipspace as a view frustum but with the shape of a box. So it is very fast to clip primitives against a AABB. The math is a little involved, but is all explained in this blog post: &#xD;&#xA;&#xD;&#xA;https://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16780" PostHistoryTypeId="50" PostId="5925" RevisionGUID="85e40cf1-bb30-42b0-90f6-51268ae5f33d" CreationDate="2017-12-28T11:55:24.617" UserId="-1" />
  <row Id="16786" PostHistoryTypeId="2" PostId="6057" RevisionGUID="13a79b96-ad05-4ac9-a888-c9931335d60e" CreationDate="2017-12-28T20:37:57.843" UserId="7957" Text="If you have an oriented triangle mesh (a non oriented surface would be the [Moebius Strip][1] for instance), you can check the triangle inversion by looking at the signed area of triangles. The signed area is positive when the vertices are in CCW order and negative if they are in CW order. If your triangle vertices are all sorted in CCW then all triangles with negative area are inverted.&#xD;&#xA;&#xD;&#xA;Checking self-intersection is more involved. You should actually do Collision Detection of the mesh with itself. Collision detection is fast but need to implement proper data structures such as [AABB Tree][2] for narrow the amount of triangle-triangle intersection tests. Collision Detection is usually performed using very low-poly version of the meshes. In some computer games, the bounding volume hierarchy (spheres, AABBs, etc) that approximate the mesh is the only thing considered for collision, no the mesh itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/M%C3%B6bius_strip&#xD;&#xA;  [2]: https://www.azurefromthetrenches.com/introductory-guide-to-aabb-tree-collision-detection/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16787" PostHistoryTypeId="5" PostId="6057" RevisionGUID="77dfb259-ca11-4782-87ea-9b85bd96795d" CreationDate="2017-12-28T20:47:20.027" UserId="7957" Comment="added 251 characters in body" Text="If you have an oriented triangle mesh (a non oriented surface would be the [Moebius Strip][1] for instance), you can check the triangle inversion by looking at the [signed area of triangles][2]. The signed area is positive when the vertices are in CCW order and negative if they are in CW order. If your triangle vertices are all sorted in CCW then all triangles with negative area are inverted. Fixing that depends on the deformation technique, I don't know your case.&#xD;&#xA;&#xD;&#xA;Checking self-intersection is more involved. You should actually do Collision Detection of the mesh with itself. Collision detection is fast but need to implement proper data structures such as [AABB Tree][3] for narrow the amount of triangle-triangle intersection tests. Collision Detection is usually performed using very low-poly version of the meshes. In some computer games, the bounding volume hierarchy (spheres, AABBs, etc) that approximate the mesh is the only thing considered for collision, no the mesh itself.&#xD;&#xA;&#xD;&#xA;Once a collision is detected, there are several ways to response, applying a  bouncing force for instance, is common.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/M%C3%B6bius_strip&#xD;&#xA;  [2]: http://mathworld.wolfram.com/TriangleArea.html&#xD;&#xA;  [3]: https://www.azurefromthetrenches.com/introductory-guide-to-aabb-tree-collision-detection/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16792" PostHistoryTypeId="2" PostId="6058" RevisionGUID="cdd3c3c8-0b86-40d2-9451-05132bf731e9" CreationDate="2017-12-29T17:18:03.710" UserId="7966" Text="I want to write a program that allows me to simulate the effect of wind on a decorated 3d tree standing outdoors (rocking ornaments and decorations, falling balls, etc.). The program should allow to determine the parameters of the tree, the selection and placement of ornaments and the specification of wind parameters (wind way, average force, gusts, etc.) Does anyone know what libraries or tools I could use I have heard about unity, does anyone have any suggestions?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16793" PostHistoryTypeId="1" PostId="6058" RevisionGUID="cdd3c3c8-0b86-40d2-9451-05132bf731e9" CreationDate="2017-12-29T17:18:03.710" UserId="7966" Text="Technology for specific project 3d in c#?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16794" PostHistoryTypeId="3" PostId="6058" RevisionGUID="cdd3c3c8-0b86-40d2-9451-05132bf731e9" CreationDate="2017-12-29T17:18:03.710" UserId="7966" Text="|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16795" PostHistoryTypeId="50" PostId="5716" RevisionGUID="b7a2e0ee-3f96-46f1-9399-017ba09eea7f" CreationDate="2017-12-30T14:10:40.980" UserId="-1" />
  <row Id="16796" PostHistoryTypeId="50" PostId="4651" RevisionGUID="cb8be88c-8f1a-4f11-a68d-618ebf140ff1" CreationDate="2017-12-30T17:10:40.843" UserId="-1" />
  <row Id="16798" PostHistoryTypeId="2" PostId="6059" RevisionGUID="00931b18-16d5-4283-aaf8-ee001e25d752" CreationDate="2017-12-31T03:39:09.060" UserId="7969" Text="In my naïve raytracer experiment I work internally with RGB values, and after all the tracing has been done, I end up with raw RGB triplets that I need to write down to some image format with a limited gamut, typically sRGB.&#xD;&#xA;&#xD;&#xA;Since bright spots in my image can have values far beyond (1,1,1), I need to clip them. Right now I just limit each channel individually, but that will obviously introduce a shift in hue when one channel clips before another. Here is a typical (enlarged) example from my code where the yellow-green object turns into yellow around the highlight:&#xD;&#xA;&#xD;&#xA;[![Example of hue shift][1]][1]&#xD;&#xA;&#xD;&#xA;I'm now looking for a way to solve this problem, but all the solutions I come up with seems to have the same drawback: eventually you _have_ to discard information. For example, I've thought about working with another colorspace like Lab internally, but even then I would first have to transform it to sRGB for rendering the final image file.&#xD;&#xA;&#xD;&#xA;Before I dig myself into this any further, I would like to see if there is either:&#xD;&#xA;&#xD;&#xA; - An objectively &quot;best&quot; way to solve this problem, or..&#xD;&#xA; - An industry standard way that is used in practice&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V1hMC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16799" PostHistoryTypeId="1" PostId="6059" RevisionGUID="00931b18-16d5-4283-aaf8-ee001e25d752" CreationDate="2017-12-31T03:39:09.060" UserId="7969" Text="How do you deal with clipping when rendering to a limited colorspace?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16800" PostHistoryTypeId="3" PostId="6059" RevisionGUID="00931b18-16d5-4283-aaf8-ee001e25d752" CreationDate="2017-12-31T03:39:09.060" UserId="7969" Text="|raytracing|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16801" PostHistoryTypeId="2" PostId="6060" RevisionGUID="56a3ea3e-508e-4a60-9218-2a7b03538b61" CreationDate="2017-12-31T04:15:09.303" UserId="7957" Text="I have done 3D graphics in c# with Managed DirectX. Nowadays people uses SharpDX and SlimDX instead. I have heard about XNA is easier for doing simple 3D games.&#xD;&#xA;&#xD;&#xA;Unity uses C# as scripting language, the Unity Engine is running the actual simulations. You are mostly configuring and scripting Unity for running your simulation. This is not just a technology to use in your C# project, this is the oposite, a platform for games that uses C# as one technology." ContentLicense="CC BY-SA 3.0" />
  <row Id="16803" PostHistoryTypeId="5" PostId="6060" RevisionGUID="b7b68a0e-88ff-49a3-b870-e3efcf4e96e0" CreationDate="2017-12-31T08:07:22.110" UserId="7957" Comment="added 532 characters in body" Text="I have done 3D graphics in c# with Managed DirectX. Nowadays people uses SharpDX and SlimDX instead. I have heard about XNA is easier for doing simple 3D games. &#xD;&#xA;&#xD;&#xA;You can also use OpenGl since there are several bindings for C#. Some people find OpenGl simpler to understand than DirectX, and is cross platform.&#xD;&#xA;&#xD;&#xA;Unity uses C# as scripting language, the Unity Engine is running the actual simulations. You are mostly configuring and scripting Unity for running your simulation. This is not just a technology to use in your C# project, this is the oposite, a platform for games that uses C# as one technology.&#xD;&#xA;&#xD;&#xA;You can do 2D graphics with all the above technologies. For the simulation, in case you do not use Unity or other game engine capable of doing physics simulations, you would need to find or write a rigid body simulation for animating all your moving objects. For animating the tree you would probably need a spring system which is also simple to simulate along rigid bodies.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16805" PostHistoryTypeId="2" PostId="6062" RevisionGUID="0f437a27-9e75-47f8-89de-c63e05e01e43" CreationDate="2017-12-31T11:11:02.877" UserId="5088" Text="Effectively, before you start to think about clipping/clamping, you'll need a general approach to map the much wider color range you are working in onto the [0,1] triplets you want to output. There are various way to do this, look up **HDR tone mapping** to get a good first impression of what is possible. Simply clipping things to [0,1] will leave you with a very cramped color space to work in, throwing away much of the advantages of raytracying in &quot;high dynamic range&quot; (floats).&#xD;&#xA;&#xD;&#xA;On to the actual problem at hand, to prevent clamped colours from shifting hue, a naive but functional approach is:&#xD;&#xA;&#xD;&#xA; 1. Take the max component *m* from (R, G, B)&#xD;&#xA; 2. If *m* &gt; 1, scale all three components by 1 / *m*.&#xD;&#xA;&#xD;&#xA;This does not take the relative luminance of the color components into account, but if you eventually end up doing something like tone-mapping anyway that would be a better time to tackle that problem." ContentLicense="CC BY-SA 3.0" />
  <row Id="16806" PostHistoryTypeId="50" PostId="4361" RevisionGUID="cd53b023-7289-4e4f-9ea5-c47946d0251f" CreationDate="2017-12-31T11:25:49.953" UserId="-1" />
  <row Id="16811" PostHistoryTypeId="2" PostId="6064" RevisionGUID="dc76cea1-435a-46d5-b815-6a8df53d870e" CreationDate="2017-12-31T20:35:30.410" UserId="7814" Text="Here's a constructor to construct a axis-aligned bounding boxes given two opposite vertices on the bounding box. [Source][1]. &#xD;&#xA; &#xD;&#xA;    BBox(const Point &amp;p1, const Point &amp;p2) {&#xD;&#xA;        pMin = Point(min(p1.x, p2.x), min(p1.y, p2.y), min(p1.z, p2.z));&#xD;&#xA;        pMax = Point(max(p1.x, p2.x), max(p1.y, p2.y), max(p1.z, p2.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't understand why this works; for example if I take $P_1 = (1,2,3)$ and $P_2 = (2,1,4)$, I'll get $\text{pMin} = (1,1,3)$ and $\text{pMax} = (2,2,4)$. The bounding box between $P_1$ and $P_2$ is doesn't look same as bounding box between `pMin` and `pMax`. &#xD;&#xA;&#xD;&#xA;The explanation for this constructor given in the book :&#xD;&#xA;&#xD;&#xA;&gt;If the caller passes two corner points (`p1` and `p2`) to define the box, since `p1` and `p2` are not necessarily chosen so that `p1.x` &lt;= `p2.x`, and so on, the constructor needs to find their component-wise minimum and maximum values.      &#xD;&#xA;&#xD;&#xA;As far as I understand, if `p1.x` is less than `p2.x` then `pMin = p1`. So we should only be checking against `p1.x` and `p2.x`. &#xD;&#xA;&#xD;&#xA;Am I missing something ? The above constructor doesn't feel correct for axis-aligned bounding boxes.&#xD;&#xA;&#xD;&#xA;[1]: https://www.amazon.com/gp/product/0128006455/ref=as_li_tl?ie=UTF8&amp;tag=pharr-20&amp;camp=1789&amp;creative=9325&amp;linkCode=as2&amp;creativeASIN=0128006455&amp;linkId=8d99f0006f611ac309e1c72906f78e17" ContentLicense="CC BY-SA 3.0" />
  <row Id="16812" PostHistoryTypeId="1" PostId="6064" RevisionGUID="dc76cea1-435a-46d5-b815-6a8df53d870e" CreationDate="2017-12-31T20:35:30.410" UserId="7814" Text="AABB bounding boxes" ContentLicense="CC BY-SA 3.0" />
  <row Id="16813" PostHistoryTypeId="3" PostId="6064" RevisionGUID="dc76cea1-435a-46d5-b815-6a8df53d870e" CreationDate="2017-12-31T20:35:30.410" UserId="7814" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16814" PostHistoryTypeId="6" PostId="6064" RevisionGUID="ee5963cc-5e23-4622-b3be-93162c8fbe8c" CreationDate="2017-12-31T20:47:55.757" UserId="7814" Comment="edited tags" Text="|raytracing|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16815" PostHistoryTypeId="5" PostId="6064" RevisionGUID="132f8c1e-b535-4853-a968-9603dd7c269b" CreationDate="2017-12-31T22:49:34.813" UserId="7814" Comment="deleted 2 characters in body" Text="Here's a constructor to construct a axis-aligned bounding box given two opposite vertices on the bounding box. [Source][1]. &#xD;&#xA; &#xD;&#xA;    BBox(const Point &amp;p1, const Point &amp;p2) {&#xD;&#xA;        pMin = Point(min(p1.x, p2.x), min(p1.y, p2.y), min(p1.z, p2.z));&#xD;&#xA;        pMax = Point(max(p1.x, p2.x), max(p1.y, p2.y), max(p1.z, p2.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't understand why this works; for example if I take $P_1 = (1,2,3)$ and $P_2 = (2,1,4)$, I'll get $\text{pMin} = (1,1,3)$ and $\text{pMax} = (2,2,4)$. The bounding box between $P_1$ and $P_2$ is doesn't look same as bounding box between `pMin` and `pMax`. &#xD;&#xA;&#xD;&#xA;The explanation for this constructor given in the book :&#xD;&#xA;&#xD;&#xA;&gt;If the caller passes two corner points (`p1` and `p2`) to define the box, since `p1` and `p2` are not necessarily chosen so that `p1.x` &lt;= `p2.x`, and so on, the constructor needs to find their component-wise minimum and maximum values.      &#xD;&#xA;&#xD;&#xA;As far as I understand, if `p1.x` is less than `p2.x` then `pMin = p1`. So we should only be checking against `p1.x` and `p2.x`. &#xD;&#xA;&#xD;&#xA;Am I missing something ? The above constructor doesn't feel correct for axis-aligned bounding boxes.&#xD;&#xA;&#xD;&#xA;[1]: https://www.amazon.com/gp/product/0128006455/ref=as_li_tl?ie=UTF8&amp;tag=pharr-20&amp;camp=1789&amp;creative=9325&amp;linkCode=as2&amp;creativeASIN=0128006455&amp;linkId=8d99f0006f611ac309e1c72906f78e17" ContentLicense="CC BY-SA 3.0" />
  <row Id="16816" PostHistoryTypeId="5" PostId="6064" RevisionGUID="9d99defa-f809-4f1a-80a9-4bb672a46417" CreationDate="2018-01-01T00:44:36.920" UserId="2041" Comment="Don't make people click through to find out what you're linking to." Text="Here's a constructor to construct a axis-aligned bounding box given two opposite vertices on the bounding box, from [Pharr's *Physically Based Rendering*, Third Edition][1]. &#xD;&#xA; &#xD;&#xA;    BBox(const Point &amp;p1, const Point &amp;p2) {&#xD;&#xA;        pMin = Point(min(p1.x, p2.x), min(p1.y, p2.y), min(p1.z, p2.z));&#xD;&#xA;        pMax = Point(max(p1.x, p2.x), max(p1.y, p2.y), max(p1.z, p2.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't understand why this works; for example if I take $P_1 = (1,2,3)$ and $P_2 = (2,1,4)$, I'll get $\text{pMin} = (1,1,3)$ and $\text{pMax} = (2,2,4)$. The bounding box between $P_1$ and $P_2$ is doesn't look same as bounding box between `pMin` and `pMax`. &#xD;&#xA;&#xD;&#xA;The explanation for this constructor given in the book :&#xD;&#xA;&#xD;&#xA;&gt;If the caller passes two corner points (`p1` and `p2`) to define the box, since `p1` and `p2` are not necessarily chosen so that `p1.x` &lt;= `p2.x`, and so on, the constructor needs to find their component-wise minimum and maximum values.      &#xD;&#xA;&#xD;&#xA;As far as I understand, if `p1.x` is less than `p2.x` then `pMin = p1`. So we should only be checking against `p1.x` and `p2.x`. &#xD;&#xA;&#xD;&#xA;Am I missing something ? The above constructor doesn't feel correct for axis-aligned bounding boxes.&#xD;&#xA;&#xD;&#xA;[1]: https://www.amazon.com/gp/product/0128006455/ref=as_li_tl?ie=UTF8&amp;tag=pharr-20&amp;camp=1789&amp;creative=9325&amp;linkCode=as2&amp;creativeASIN=0128006455&amp;linkId=8d99f0006f611ac309e1c72906f78e17" ContentLicense="CC BY-SA 3.0" />
  <row Id="16817" PostHistoryTypeId="2" PostId="6065" RevisionGUID="078d8d36-e6b6-4f23-974d-3ee33e84a776" CreationDate="2018-01-01T00:55:35.140" UserId="2041" Text="&gt; As far as I understand, if `p1.x` is less than `p2.x` then `pMin = p1`.&#xD;&#xA;&#xD;&#xA;Nope. That would be true if you wanted the caller to only pass the lower-left and upper-right points, but they can be any pair of opposite points. Let's truncate to two dimensions to make it simpler. If $p_1 = (1,2)$ and $p_2 = (2,1)$, they're not the bottom-left and top-right of a rectangle, they're the *other* two corners. The bottom-left corner is $(1,1)$ and the top-right corner is $(2,2)$. It's no different in three dimensions.&#xD;&#xA;&#xD;&#xA;To put it another way, an axis-aligned bounding box is the Cartesian product of three intervals or ranges, one along each axis. It's the set of all points $(x,y,z)$ where $x_{min} &lt; x &lt; x_{max}\ \wedge y_{min} &lt; y &lt; y_{max}\ \wedge z_{min} &lt; z &lt; z_{max}$. You're trying to find the smallest box that contains all of the points you're passed. (In fact, you're only passed two, but it would be the same if you had a whole set of points.) To do that, you find the interval on each axis separately. Just because one of the points you're passed in has the smallest $x$ co-ordinate, that doesn't mean it'll have the smallest $y$ or $z$ co-ordinate, so you take the min and max separately for each axis." ContentLicense="CC BY-SA 3.0" />
  <row Id="16818" PostHistoryTypeId="2" PostId="6066" RevisionGUID="605ea66c-2a02-4cd5-b9d0-e0902b276b7b" CreationDate="2018-01-01T01:00:20.183" UserId="4908" Text="In short; The constructor is correct.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; As far as I understand, if p1.x is less than p2.x then pMin = p1. So we should only be checking against p1.x and p2.x.&#xD;&#xA;&#xD;&#xA;I get where the confusion comes from, but the explanation meant something else. It meant that when $p1$ and $p2$ are given, they are not always ordered so that $p1$ is always $pMin$ and $p2$ is always $pMax$. So we need to find out. However, it could be that when solely looking at the x-axis, $p1$ is $pMin$, but when looking at the y-axis, $p2$ is $pMin$. So, we need to find $pMin$ and $pMax$ for each of their components, seperately.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we look at a two dimensional example, we can see more easily how it works.&#xD;&#xA;&#xD;&#xA;We have $p1=(7, 4)$ and $p2=(2, 6)$.&#xD;&#xA;&#xD;&#xA;[![Graph of p1 and p2][1]][1]&#xD;&#xA;&#xD;&#xA;We want to get $pMin$ and $pMax$. $pMin$ should be the lowest value for all the components. $pMax$ should be the highest value for all the components. That would make calculations a lot easier of course.&#xD;&#xA;&#xD;&#xA;When looking at the graph we can easily find $pMin$ and $pMax$.&#xD;&#xA;&#xD;&#xA;[![pMin and pMax plotted on a graph][2]][2]&#xD;&#xA;&#xD;&#xA;$pMin=(2, 4)$ and $pMax=(7, 6)$&#xD;&#xA;&#xD;&#xA;We can see that for $pMin$, we took the lowest value from $p2$ for the x component and the lowest value from $p1$ for the y component.&#xD;&#xA;For $pMax$, we took the highest value from $p1$ for the x component and the highest value from $p2$ for the y component.&#xD;&#xA;&#xD;&#xA;If we would only look at the x component and determined $pMin$ and $pMax$ from that, we would get $pMin=(2, 6)$ and $pMax=(7, 4)$. This works for the x component, but it makes no sense on the y component, as $pMin$ has the highest y value.&#xD;&#xA;&#xD;&#xA;The bounding boxes are still the same. We still store the same rectangle, we just used different points to store it.&#xD;&#xA;&#xD;&#xA;When going to the third dimension, it is still exactly the same. You just do the same for the z component as you would do for the x and y components.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZkEGn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CHVe3.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16820" PostHistoryTypeId="2" PostId="6067" RevisionGUID="61d773ed-f586-470d-82d8-f9ca2b48060a" CreationDate="2018-01-01T08:56:20.587" UserId="2308" Text="I am starting to think about how I can make my app (currently written in Metal) available on older device that dont have Metal as well as Android. This is a predicament because while I could write two separate rendering classes that use the different frameworks it doesn’t teach me anything about how to code for multiple graphics libraries. I can only get away with this because my rendering code is fairly short and has few states and draw calls. I want to learn for the future.&#xA;&#xA;Writing a renderer that supports multiple frameworks especially becomes difficult when thinking of the two libraries I hope to support — OpenGL and Metal — which are quite different in how they expose the GPU.&#xA;&#xA;I am curious how exactly one usually does design their code for apps that can target multiple graphics languages. Here are my theories of what could be done:&#xA;&#xA; 1. Write two different rendering classes keep the data and simulation stuff in its own area and just vary the renderer.&#xA; 2. Take high level functions like createTexture or copyTextureOnto and have an if statement checking which language the device supports and have a custom implementation for it.&#xA; 3. Coming up with your own graphics objects that are akin to the objects from the framework (such as MTLCommandEncoder or MTLTexture) and use those to build you app and just use the implantation that matches your graphics frameworks. Essentially recode the functions one of your graphics libraries has that you use and just add an if statement to your implementation is called on a OpenGL supporting device.&#xA;&#xA;When you have to code a software to support multiple graphics libraries how do you generally do it? Do you loose any efficiency with the technique you use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16821" PostHistoryTypeId="1" PostId="6067" RevisionGUID="61d773ed-f586-470d-82d8-f9ca2b48060a" CreationDate="2018-01-01T08:56:20.587" UserId="2308" Text="How do you design the code of a graphics engine to target multiple frameworks" ContentLicense="CC BY-SA 3.0" />
  <row Id="16822" PostHistoryTypeId="3" PostId="6067" RevisionGUID="61d773ed-f586-470d-82d8-f9ca2b48060a" CreationDate="2018-01-01T08:56:20.587" UserId="2308" Text="|opengl|metal|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16823" PostHistoryTypeId="2" PostId="6068" RevisionGUID="2f39ade9-9eb1-4eb3-a726-1e36d33cf0c0" CreationDate="2018-01-01T16:55:08.603" UserId="3003" Text="You do it by abstracting away the underlying technology. You know, for example, at a very high level that you'll need to work with images, geometry, and I'm guessing you'll have to write shaders to do your rendering. The textures and geometry can be in the same format for both systems.&#xD;&#xA;&#xD;&#xA;So from that, you can design an interface for rendering. You'll probably have a scene of some sort that has the geometry in it. The geometry will likely have the textures applied to it. When rendering the geometry you'll need to use a shader. Those might be good places to start with your abstraction. You might need a scene object that holds all the different objects you want to render. Each object is made up of geometry and the images that will be applied to the geometry. The scene object, the geometry objects and the images can be the same between OpenGL and Metal because they aren't specific to either. (I'm assuming here that the geometry is just a buffer of floating point coordinates, normals, etc. and the image starts out as a buffer of RGBA pixels on the CPU.)&#xD;&#xA;&#xD;&#xA;Next you need to come up with a way to render those things on the hardware you're currently running on with the framework you wish to use. So you create an abstract interface. Perhaps you have a `Renderer` object. It would have methods that allow you to add a piece of geometry with an image to use as the texture. It would allow you to associate a shader with the geometry. And it would have a method to render the geometry to either a texture or the screen.&#xD;&#xA;&#xD;&#xA;You then either subclass the `Renderer` class (assuming you're using something like C++) or write a new class that implements the `Renderer` protocol (if you're using something like Objective-C or Swift). You have 2 different subclasses or implementations. One that does things using OpenGL and one that does things using Metal. &#xD;&#xA;&#xD;&#xA;So you might have an `OGLRenderer` and a `MTLRenderer`. The `OGLRenderer` class will implement the `addGeometry()` method by creating a Vertex Buffer Object and eventually calling `glBufferData()` to actually upload the geometry to the GPU. In your `MTLRenderer` you'll create a `MTLBuffer` via `-newBufferWithLength:options:`, and then copying the data into the buffer with `memcpy()`. And so on for the other functions.&#xD;&#xA;&#xD;&#xA;So when writing the main code for your application, you'll code to the `Renderer` interface without knowing whether the underlying renderer that you're actually going to use is an OpenGL renderer or a Metal renderer. (In fact, you could even make it so they can be switched at run time if that would help in some way.) You can have a factory that either decides at run time which to use based on the OS you're on, or you can decide at compile time by only including the appropriate subclass." ContentLicense="CC BY-SA 3.0" />
  <row Id="16824" PostHistoryTypeId="50" PostId="5816" RevisionGUID="fc13fb06-6b8d-45e7-b4f4-5b1f44a8c0f5" CreationDate="2018-01-02T10:59:01.680" UserId="-1" />
  <row Id="16829" PostHistoryTypeId="5" PostId="2485" RevisionGUID="1df2c70a-3209-4d2b-a313-25dc78c7f55b" CreationDate="2018-01-03T08:28:59.960" UserId="209" Comment="Fixed winding order of CBD triangle" Text="Sample gaps will occur if you don't do things &quot;properly&quot;. &#xD;&#xA;&#xD;&#xA;In OpenGL or D3D, assuming a consistent winding order, if you have triangles  ABC and CBD, then when a sample point - that is a test during scan conversion to determine if a point (read pixel) is inside a triangle - lies *exactly* on the shared edge BC, then that sample will belong to *exactly one* of those two triangles. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This avoids both gaps *and* double filling. The latter would be problematic with, say, translucency or stencil operations.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16830" PostHistoryTypeId="33" PostId="6033" RevisionGUID="b45db58a-7356-4e50-8558-34dbd1059272" CreationDate="2018-01-03T09:20:24.370" UserId="2041" Comment="42" />
  <row Id="16832" PostHistoryTypeId="2" PostId="6070" RevisionGUID="2232878e-6592-4f33-9437-4d627ea1cd07" CreationDate="2018-01-03T22:14:27.280" UserId="2308" Text="Hello I have a simple application with some bright 2d mono-color shapes I am hoping to make appear emissive with a nice glow around them. To do that I am producing multiple gaussian blurs of varying kernels and resolutions and adding them all together to create a composite glow.&#xD;&#xA;&#xD;&#xA;I have seen many guides mention this and even mention what sizes and kernels they are using to produce their bloom however they never mention the math they used to put them all together. Right now I am assuming it was just regular additive blending.&#xD;&#xA;&#xD;&#xA;I was wondering what tips you might have to put this glow effect together effectively as far as if I should do anything other than just adding pixels together to combine the various maps. Should I do something with the weight on certain textures used in the composite? &#xD;&#xA;&#xD;&#xA;I am just trying to composite everything in an optimal manner.&#xD;&#xA;&#xD;&#xA;My main concern is whether or not I should gamma correct my glow map or if that is accounted with the weights from the gaussian sampling or source material. Should I gamma correct my blurred composite before adding it to the source image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16833" PostHistoryTypeId="1" PostId="6070" RevisionGUID="2232878e-6592-4f33-9437-4d627ea1cd07" CreationDate="2018-01-03T22:14:27.280" UserId="2308" Text="Does a gaussian blur based bloom/glow shader require gamma correction? Any other tips?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16834" PostHistoryTypeId="3" PostId="6070" RevisionGUID="2232878e-6592-4f33-9437-4d627ea1cd07" CreationDate="2018-01-03T22:14:27.280" UserId="2308" Text="|gaussian-blur|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16835" PostHistoryTypeId="2" PostId="6071" RevisionGUID="f6c69884-d1d2-42eb-ba54-ecd315c8f459" CreationDate="2018-01-03T22:34:00.917" UserId="506" Text="You can get fancy with individual weighting on the blur maps if you want to adjust the look, but an equally weighted mix (and yes, it should be additive) will work too. I’m not sure about whether you need to gamma-correct the blurred image before adding it to the source one, but you should definitely get it into linear space before doing the blur; [this article](https://ninedegreesbelow.com/photography/linear-gamma-blur-normal-blend.html) has some good illustrations as to why." ContentLicense="CC BY-SA 3.0" />
  <row Id="16836" PostHistoryTypeId="2" PostId="6072" RevisionGUID="4ad55d99-9a47-4d68-8031-e11c4b03726a" CreationDate="2018-01-03T23:15:48.667" UserId="4908" Text="In short:&#xD;&#xA;---------&#xD;&#xA;You should not gamma correct your glow map. In fact, you should do everything in a **linear color space**. At the very end, when doing any color grading (which is the very last step), you convert the final image to the right color space. The color space include that gamma correction.&#xD;&#xA;&#xD;&#xA;In long:&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;Gamma correction is a step in the encoding of images. It is usually done so that we use more bits to store the shadows and less bits to store the highlights, since we see less detail in the highlights anyway. It is also part of some color spaces. These color spaces make sure the image looks the way it is supposed to. It is the final step, often part of color grading. Just before it is send out to the display, or saved to a file. This means that everything before should be in a linear color space.&#xD;&#xA;&#xD;&#xA;Usually things would look like this:&#xD;&#xA;&#xD;&#xA; 1. Load textures and convert them to a linear space, so you do not double gamma correct..&#xD;&#xA; 2. Render the image.&#xD;&#xA; 3. Do the post effects.&#xD;&#xA; 4. Convert the image to the final color space with color grading. Probably sRGB Gamma. Converting to the color space includes the gamma correcting.&#xD;&#xA;&#xD;&#xA; *Color grading is not necessary, but optional.*&#xD;&#xA;&#xD;&#xA;When having everything at linear and doing the gamma correction at the very end, you will need a high precision for the color. Using floating point framebuffers is recommended. When using the default 8-bit framebuffer the whole way, you end up getting banding effects when gamma correcting.&#xD;&#xA;&#xD;&#xA;This setup is not always done for games, to my knowledge, since most people will barely notice it or even care about it. In the film industry, VFX and animation, using the proper color space is more important.&#xD;&#xA;&#xD;&#xA;When not doing it the 'right' way, the textures are not converted to linear and at the end, there is no gamma correction. Lights are supposed to have a quadratic falloff to be physically correct, but when gamma correcting it with a gamma of 2.0, it becomes a linear falloff. Lights can therefore get a linear falloff and look normal. As Noah Witherspoon pointed out, when blending and blurring you should use a linear color space, however this is not always done either.&#xD;&#xA;&#xD;&#xA;The reasons for not doing it the 'right' way, is probably that it still looks fine. You do not need to do it this way, to end up with good graphics. It is always a matter of what the artist likes the most." ContentLicense="CC BY-SA 3.0" />
  <row Id="16838" PostHistoryTypeId="2" PostId="6073" RevisionGUID="32a15ea4-7f4f-4989-b7de-b0821015b905" CreationDate="2018-01-05T04:53:47.597" UserId="6541" Text="I'm trying to generate random halftone like below image:&#xD;&#xA;&#xD;&#xA;I can't use `for-loop` and use `sin` and `cos` because I need low computing way.&#xD;&#xA;&#xD;&#xA;![2018-01-05_8-16-16](https://user-images.githubusercontent.com/16706911/34595885-b1cf12fa-f1f0-11e7-95ee-4f255f522db8.jpg)&#xD;&#xA;&#xD;&#xA;this is simple halftone that I tried but I need random halftone&#xD;&#xA;&#xD;&#xA;    float PI = 3.14159265359;&#xD;&#xA;        &#xD;&#xA;        void mainImage(out vec4 fragColor, in vec2 fragCoord) {&#xD;&#xA;        	vec2 p = (fragCoord.xy / iResolution.xy - 0.5)/0.5;&#xD;&#xA;        		&#xD;&#xA;                vec3 n = vec3(p, sqrt(dot(p, p)));&#xD;&#xA;                vec2 s = vec2(acos(n.z), atan(n.y, n.x))/PI;&#xD;&#xA;                vec2 uv = fract(s * vec2(30.0, 30.0));&#xD;&#xA;                float r = ceil(s.x * 30.0) / 17.0;&#xD;&#xA;                fragColor =  vec4(1.)*step(length(uv - 0.5),r);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/MljBRw&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16839" PostHistoryTypeId="1" PostId="6073" RevisionGUID="32a15ea4-7f4f-4989-b7de-b0821015b905" CreationDate="2018-01-05T04:53:47.597" UserId="6541" Text="How to generate chaotic halftone pattern?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16840" PostHistoryTypeId="3" PostId="6073" RevisionGUID="32a15ea4-7f4f-4989-b7de-b0821015b905" CreationDate="2018-01-05T04:53:47.597" UserId="6541" Text="|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16844" PostHistoryTypeId="5" PostId="6073" RevisionGUID="acc50989-bc36-47c3-8cf9-7d031c2bb6f0" CreationDate="2018-01-05T09:01:43.587" UserId="6541" Comment="added 39 characters in body" Text="I'm trying to generate random halftone like below image:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![2018-01-05_8-16-16](https://user-images.githubusercontent.com/16706911/34595885-b1cf12fa-f1f0-11e7-95ee-4f255f522db8.jpg)&#xD;&#xA;&#xD;&#xA;this is simple halftone that I tried but I need random halftone&#xD;&#xA;&#xD;&#xA;    float PI = 3.14159265359;&#xD;&#xA;        &#xD;&#xA;        void mainImage(out vec4 fragColor, in vec2 fragCoord) {&#xD;&#xA;        	vec2 p = (fragCoord.xy / iResolution.xy - 0.5)/0.5;&#xD;&#xA;        		&#xD;&#xA;                vec3 n = vec3(p, sqrt(dot(p, p)));&#xD;&#xA;                vec2 s = vec2(acos(n.z), atan(n.y, n.x))/PI;&#xD;&#xA;                vec2 uv = fract(s * vec2(30.0, 30.0));&#xD;&#xA;                float r = ceil(s.x * 30.0) / 17.0;&#xD;&#xA;                fragColor =  vec4(1.)*step(length(uv - 0.5),r);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/MljBRw&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;also I tried with`for-loop` and `sin`,`cos` but I need low computing way because I want generate It In game engine.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16846" PostHistoryTypeId="5" PostId="6021" RevisionGUID="aeee1877-1c2a-4bf4-b0f5-4bd7690ae88c" CreationDate="2018-01-05T11:20:05.580" UserId="7929" Comment="Another figure best illustrating the model" Text="By default, the eye an the projection reference point PRP are in (0,0,0). I can change the eye position with gluLookAt(), but how can I change the PRP (i.e., the  convergence position for a set of parallel lines) for a perspective projection in OpenGL?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9QdUj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VrYBF.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16847" PostHistoryTypeId="2" PostId="6075" RevisionGUID="7ef510c3-eb10-4bff-b540-958497100ae7" CreationDate="2018-01-05T15:49:18.350" UserId="7993" Text="$A_{v}^{-1}$ = $A_{v}^{T}$&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;$A_{v}$ = Allignment matrix that alligns vector v with z axis&lt;br/&gt;&#xD;&#xA;$=$\begin{bmatrix}&#xD;&#xA;    \frac{\lambda}{|v|}       &amp; \frac{-ab}{\lambda|v|} &amp; \frac{-ac}{\lambda|v|} &amp;   0 \\&#xD;&#xA;    0 &amp; \frac{c}{|v|} &amp; \frac{-b}{|v|} &amp;   0 \\&#xD;&#xA;    \frac{a}{|v|}       &amp; \frac{b}{|v|} &amp; \frac{c}{|v|} &amp;   0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&lt;br/&gt;&#xD;&#xA;here, $\lambda = \sqrt{b^2+c^2} $&lt;br/&gt;&#xD;&#xA;$|v| = \sqrt{a^2+b^2+c^2} $&lt;br/&gt;&#xD;&#xA;And vector $v = (a, b, c)$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16848" PostHistoryTypeId="1" PostId="6075" RevisionGUID="7ef510c3-eb10-4bff-b540-958497100ae7" CreationDate="2018-01-05T15:49:18.350" UserId="7993" Text="Why inverse of an allignment matrix is the same as its transpose?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16849" PostHistoryTypeId="3" PostId="6075" RevisionGUID="7ef510c3-eb10-4bff-b540-958497100ae7" CreationDate="2018-01-05T15:49:18.350" UserId="7993" Text="|matrix|vector-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16850" PostHistoryTypeId="2" PostId="6076" RevisionGUID="34645e43-d52c-4dad-af9e-a112a2dd39f1" CreationDate="2018-01-05T16:31:55.403" UserId="4652" Text="A rotation around the x-axis is achieved by this matrix&#xD;&#xA;$$&#xD;&#xA;\mathtt{T}_\mathrm{rot X} = \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \\ 0&amp; \cos \alpha&#xD;&#xA;            &amp; -\sin \alpha&amp; 0 \\ 0 &amp; \sin \alpha &amp; \cos \alpha &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp;1 \\ \end{bmatrix} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In order to rotate around the x-axis in the viewing space, one needs to think about when to apply the above transformation in the chain of transformations that is applied to the 3D model vertices $\mathbf{X}_{\mathrm{3d}}$ in the employed rendering pipeline.&#xD;&#xA;&#xD;&#xA;A typical transformation chain is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{camera\ transform}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Let's split the camera tranformation into its rotational and translational part:&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\underbrace{\mathtt{T}_{\mathrm{cam\ trans}}\,\mathtt{T}_{\mathrm{cam\ rot}}}_{\mathtt{T}_{\mathrm{camera\ transform}}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then we need to apply the x-rotation in-between the camera rotation and translation, because we want to have the rotation of the camera applied beforehand, but not the camera's translation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\underbrace{\mathtt{T}_{\mathrm{cam\ trans}}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}}_{\mathtt{T}_{\mathrm{new\ camera\ transform}}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This would achieve the desired rotation, but typically we do not want to change the camera transformation but the the mesh transformation. This is achieved by&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{cam\ trans}}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}\\&#xD;&#xA;\Leftrightarrow \mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{cam\ trans}}\,(\mathtt{T}_{\mathrm{cam\ rot}}\,\mathtt{T}_{\mathrm{cam\ rot}}^{-1})\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}\\&#xD;&#xA;\Leftrightarrow \mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{camera\ transform}}\,\underbrace{\mathtt{T}_{\mathrm{cam\ rot}}^{-1}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}}_{\mathtt{T}_{\mathrm{new\ mesh\ transform}}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;**Therefore, the short answer to your question is:**&#xD;&#xA; &#xD;&#xA;Left-multiply the current transformation matrix of your model with $\mathtt{T}_{\mathrm{cam\ rot}}^{-1}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have generated an &quot;cow&quot; example scene in the GSN Composer that can be used for interactive testing in a WebGL-capable browser:&#xD;&#xA;&#xD;&#xA;https://www.gsn-lib.org/docs/gallery.php?projectName=CowQuestion&amp;graphName=cow&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/plks2.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16851" PostHistoryTypeId="2" PostId="6077" RevisionGUID="e2439a7c-ae00-422d-82a4-b876fcad927e" CreationDate="2018-01-05T17:20:28.070" UserId="209" Text="If you consider a trivial rotation matrix, e.g. rotation of angle theta around Z axis, then you will see that the inverse matrix, a rotation of -theta, is the transpose,  since sin(-theta)=-sin(theta) and cos(-theta)=cos(theta).&#xD;&#xA;&#xD;&#xA;An arbitrary rotation matrix, R, can be constructed by multiplication of other rotations, e.g R = A * B.  If the inverse of A and B exist, then R^-1 = B^-1 * A^-1.  &#xD;&#xA;Similarly we know  (A*B)^T = (B^T * A^T).&#xD;&#xA;&#xD;&#xA;Put these together and you have your answer." ContentLicense="CC BY-SA 3.0" />
  <row Id="16852" PostHistoryTypeId="5" PostId="6077" RevisionGUID="d3bb7dcb-bda2-4796-8102-1d3b2e125589" CreationDate="2018-01-05T17:26:08.587" UserId="209" Comment="added 45 characters in body" Text="To align vectors, you are applying a rotation.&#xD;&#xA;&#xD;&#xA;If you consider a simple rotation matrix, e.g. rotation of angle $\theta$ around Z axis, then you will trivially see that its inverse matrix, a rotation of $-\theta$, is the transpose,  since $sin(-\theta)=-sin(\theta)$ and $cos(-\theta)=cos(\theta)$.&#xD;&#xA;&#xD;&#xA;An arbitrary rotation matrix, R, can be constructed by multiplication of other rotations, e.g $R = A \cdot B$.  If the inverse of A and B exist, then $R^{-1} = B^{-1} \cdot A^{-1}$.  &#xD;&#xA;Similarly we know  $(A \cdot B)^T = (B^T \cdot A^T)$.&#xD;&#xA;&#xD;&#xA;Put these together and you have your answer." ContentLicense="CC BY-SA 3.0" />
  <row Id="16853" PostHistoryTypeId="2" PostId="6078" RevisionGUID="665a4b09-7ed0-4c23-9f8b-359d728b3612" CreationDate="2018-01-05T17:42:04.120" UserId="2485" Text="I am following the [WebGL2Fundametals tutorial][1]. Using some sample (cube) data I was able to successfully call `gl.drawElements();` using index, normal and geometry data. This are my fragment and vertex shaders:&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es    &#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    in vec3 v_normal;&#xD;&#xA;    in vec3 v_surfaceToLight;&#xD;&#xA;    in vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 u_color;&#xD;&#xA;    uniform float u_shininess;&#xD;&#xA;    uniform vec3 u_lightDirection;&#xD;&#xA;    &#xD;&#xA;    uniform float u_innerLimit; // In dot space&#xD;&#xA;    uniform float u_outerLimit; // In dot space&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      vec3 normal = normalize(v_normal);&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceToLightDirection = normalize(v_surfaceToLight);&#xD;&#xA;      vec3 surfaceToViewDirection = normalize(v_surfaceToView);&#xD;&#xA;      vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);&#xD;&#xA;    &#xD;&#xA;      float dotFromDirection = dot(surfaceToLightDirection, -u_lightDirection);&#xD;&#xA;      float inLight = smoothstep(u_outerLimit, u_innerLimit, dotFromDirection);&#xD;&#xA;      // Using normals for color calculation based on the incidence of light&#xD;&#xA;      float light = inLight * dot(normal, surfaceToLightDirection);&#xD;&#xA;      float specular = inLight * pow(dot(normal, halfVector), u_shininess);&#xD;&#xA;    &#xD;&#xA;      outColor = u_color;&#xD;&#xA;    &#xD;&#xA;      outColor.rgb *= light;&#xD;&#xA;    &#xD;&#xA;      // Add in the specular&#xD;&#xA;      outColor.rgb += specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    in vec4 a_position;&#xD;&#xA;    in vec3 a_normal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 u_world;&#xD;&#xA;    uniform mat4 u_worldViewProjection;&#xD;&#xA;    uniform mat4 u_worldInverseTranspose;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 u_lightWorldPosition;&#xD;&#xA;    uniform vec3 u_viewWorldPosition;&#xD;&#xA;    &#xD;&#xA;    // varying to pass the normal to the fragment shader&#xD;&#xA;    out vec3 v_normal;&#xD;&#xA;    &#xD;&#xA;    out vec3 v_surfaceToLight;&#xD;&#xA;    out vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;      gl_Position = u_worldViewProjection * a_position;&#xD;&#xA;    &#xD;&#xA;      // Orient the normals and pass to the fragment shader&#xD;&#xA;      v_normal = mat3(u_worldInverseTranspose) * a_normal;&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceWorldPosition = (u_world * a_position).xyz;&#xD;&#xA;      v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;&#xD;&#xA;      v_surfaceToView = u_viewWorldPosition - surfaceWorldPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With the following call the cube is successfully rendered:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);&#xD;&#xA;    GLHelper.setUniformValues(this._uniforms, uniformValues);&#xD;&#xA;    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the working cube data:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;            // Front face&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;&#xD;&#xA;            // Back face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;            100, -100, -100,&#xD;&#xA;&#xD;&#xA;            // Top face&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;&#xD;&#xA;            // Bottom face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            100, -100, -100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;&#xD;&#xA;            // Right face&#xD;&#xA;            100, -100, -100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;&#xD;&#xA;            // Left face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;&#xD;&#xA;Normals:&#xD;&#xA;&#xD;&#xA;            // Front&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;&#xD;&#xA;            // Back face&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;&#xD;&#xA;            // Top face&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Bottom face&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Right face&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Left face&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;            0, 1, 2, 0, 2, 3,    // Front face&#xD;&#xA;            4, 5, 6, 4, 6, 7,    // Back face&#xD;&#xA;            8, 9, 10, 8, 10, 11,  // Top face&#xD;&#xA;            12, 13, 14, 12, 14, 15, // Bottom face&#xD;&#xA;            16, 17, 18, 16, 18, 19, // Right face&#xD;&#xA;            20, 21, 22, 20, 22, 23,  // Left face&#xD;&#xA;&#xD;&#xA;If I get it right the normals in this model should look something like the cube's normals in [the very first animation in the &quot;Introducing normals&quot; part](https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html). Now I was trying to create and import a cube using Blender.&#xD;&#xA;&#xD;&#xA;Unfortunately I wasn't able to recreate a cube with the same kind of normals. Blender generates only one (pink) normal per vertex and they also obviously have a totally different angle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[Some sources](https://blender.stackexchange.com/a/14697) suggest that smoothing the faces would fix this issue. It did not for me. Here is the Wavefront file:&#xD;&#xA;&#xD;&#xA;    o Cube&#xD;&#xA;    v 1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 1.000000 -0.999999&#xD;&#xA;    v 0.999999 1.000000 1.000001&#xD;&#xA;    v -1.000000 1.000000 1.000000&#xD;&#xA;    v -1.000000 1.000000 -1.000000&#xD;&#xA;    vn 0.0000 -1.0000 0.0000&#xD;&#xA;    vn 0.0000 1.0000 0.0000&#xD;&#xA;    vn 1.0000 -0.0000 0.0000&#xD;&#xA;    vn 0.0000 -0.0000 1.0000&#xD;&#xA;    vn -1.0000 -0.0000 -0.0000&#xD;&#xA;    vn 0.0000 0.0000 -1.0000&#xD;&#xA;    s off&#xD;&#xA;    f 1//1 3//1 4//1&#xD;&#xA;    f 8//2 6//2 5//2&#xD;&#xA;    f 5//3 2//3 1//3&#xD;&#xA;    f 6//4 3//4 2//4&#xD;&#xA;    f 3//5 8//5 4//5&#xD;&#xA;    f 1//6 8//6 5//6&#xD;&#xA;    f 1//1 2//1 3//1&#xD;&#xA;    f 8//2 7//2 6//2&#xD;&#xA;    f 5//3 6//3 2//3&#xD;&#xA;    f 6//4 7//4 3//4&#xD;&#xA;    f 3//5 7//5 8//5&#xD;&#xA;    f 1//6 4//6 8//6&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I try to import and to render this data using `gl.drawElements(gl.TRIANGLES, 72, gl.UNSIGNED_SHORT, 0);` I get the following output:&#xD;&#xA;&#xD;&#xA;&gt; ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of&#xD;&#xA;&gt; range vertices in attribute 1&#xD;&#xA;&#xD;&#xA;If I use above (.obj) vertex and normal data six time each I do not get any more errors but instead of a cube only a single triangle seems to be rendered.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am pretty sure that `attribute 1` is `in vec3 a_normal;` in my vertex shader. So I am mainly confused about two things here:&#xD;&#xA;&#xD;&#xA;1. How to get Blender to make normals like in the example above?&#xD;&#xA;&#xD;&#xA;2. How to interpret the Blender data correctly?&#xD;&#xA;&#xD;&#xA;3. Why is Blender displaying eight but outputting six vertex normals?&#xD;&#xA;&#xD;&#xA;  [1]: https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/JhiET.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JFspW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16854" PostHistoryTypeId="1" PostId="6078" RevisionGUID="665a4b09-7ed0-4c23-9f8b-359d728b3612" CreationDate="2018-01-05T17:42:04.120" UserId="2485" Text="Unable to render a Waveront model in WebGL2" ContentLicense="CC BY-SA 3.0" />
  <row Id="16855" PostHistoryTypeId="3" PostId="6078" RevisionGUID="665a4b09-7ed0-4c23-9f8b-359d728b3612" CreationDate="2018-01-05T17:42:04.120" UserId="2485" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16856" PostHistoryTypeId="2" PostId="6079" RevisionGUID="04d5c6aa-ca67-4240-9fb0-f7b589a1cb04" CreationDate="2018-01-05T20:04:08.070" UserId="3003" Text="Years ago, Pete Warden wrote either a blog post or perhaps it was an entry in one of the GPGPU Gems books where he described how to generate similar patterns. I believe that when he was at Apple, he implemented this as the &quot;Cellular&quot; generator in Motion. It looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I'm unable to find the original blog post or whatever it was, but if I recall correctly, it was generated like this:&#xD;&#xA;&#xD;&#xA; 1. Generate a list of random locations for the &quot;cells&quot;&#xD;&#xA; 2. At each cell's location, draw a small circle where:&#xD;&#xA;&#xD;&#xA;   2.1. the depth at each pixel is the inverse of the distance to the center (so highest at the center, and lowest at the edges)&#xD;&#xA;&#xD;&#xA;   2.2. the color is a radial gradient (in this case black at the center, white at the edges)&#xD;&#xA;&#xD;&#xA;I think if you further modified this algorithm to make the radius of each cell be related to the luminance of an input image at its location or make its color lighter for higher luminance positions, you could get such a half-tone look.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PcrCm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16857" PostHistoryTypeId="5" PostId="6032" RevisionGUID="f2cec9df-1b1b-4398-89ae-ada0ad29c6ac" CreationDate="2018-01-05T21:54:32.413" UserId="4652" Comment="The question was revised" Text="Eye position, projection reference point PRP, camera center, or projection center are all just different words for the same thing. &#xD;&#xA;&#xD;&#xA;gluLookAt() applied to the GL_MODELVIEW matrix works for both, parallel and perspective projection.&#xD;&#xA;&#xD;&#xA;You can choose between parallel and perspective projection by setting up the GL_PROJECTION matrix. For perspective projection this can be done using the gluPerspective() function.&#xD;&#xA;&#xD;&#xA;http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/graphics_6_1_eng_web.html#19&#xD;&#xA;&#xD;&#xA;**Edit: (after revised question)**&#xD;&#xA;&#xD;&#xA;If the PRP is not at the eye position, you can not use gluPerspective(). Instead you have to create your own GL_PROJECTION matrix. Following the formula that you have now provided, this results in the 4 x 4 matrix:&#xD;&#xA;&#xD;&#xA;$$\mathtt{A} =\begin{bmatrix} z_c-z_{pp} &amp; 0 &amp; -x_c &amp;  x_c \cdot z_{pp}\\ 0  &amp; z_c-z_{pp}  &amp; -y_c &amp; -y_c \cdot z_{pp} \\ 0 &amp; 0 &amp; \frac{\mathrm{far}+\mathrm{near}}{\mathrm{near}-\mathrm{far}} &amp; \frac{2 \cdot \mathrm{far} \cdot \mathrm{near}}{\mathrm{near}-\mathrm{far}} \\ 0 &amp; 0 &amp; -1 &amp; z_c \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I have done a quick OpenGL/WebGL rendering test with the GSN Composer. Follow the link and move the mouse over the render output to change $x_c$ and $y_c$ of the projection reference point $(x_c, y_c, z_c)$:&#xD;&#xA;&#xD;&#xA;https://www.gsn-lib.org/docs/gallery.php?projectName=ProjRefPoint&amp;graphName=ProjectionReferencePoint&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16858" PostHistoryTypeId="2" PostId="6080" RevisionGUID="7cd18f8c-d204-4d34-a885-702e7990ac45" CreationDate="2018-01-05T21:57:29.987" UserId="506" Text="As you’ve found, it’s hard to use a two-dimensional format, even from multiple viewpoints, to represent a 3D structure that’s not axis-aligned. I’m not sure I have a useful suggestion there—there’s a reason most 3D file formats support specifying translation/rotation/scaling of individual parts.&#xD;&#xA;&#xD;&#xA;A different direction you might try would be using the existing work in the [LDraw](https://ldraw.org) project; their [file format](http://www.ldraw.org/article/218) is technically ASCII, and though it’s closer to a standard 3D format in that the fundamental parts (like studs) are built out of lists of vertices / triangles / etc., the higher-level pieces (bricks, plates, etc.) are built out of references to the fundamental ones, which sounds like it’s roughly along the lines of what you’re after. There’s an [assortment](http://www.ldraw.org/downloads-2/third-party-software.html) of third-party design tools that provide GUIs on top of the LDraw parts library; of those, I’m partial to [Bricksmith](http://bricksmith.sourceforge.net/)." ContentLicense="CC BY-SA 3.0" />
  <row Id="16859" PostHistoryTypeId="2" PostId="6081" RevisionGUID="49e5ecbd-ab02-4381-b20a-c9e13b36a7df" CreationDate="2018-01-05T22:14:44.387" UserId="3123" Text="How does `Map()` works? I guess its allocate memory to fit resource size (or range of it) but when bytes are send to `GPU`?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16860" PostHistoryTypeId="1" PostId="6081" RevisionGUID="49e5ecbd-ab02-4381-b20a-c9e13b36a7df" CreationDate="2018-01-05T22:14:44.387" UserId="3123" Text="How does ID3D12Resource::Map works?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16861" PostHistoryTypeId="3" PostId="6081" RevisionGUID="49e5ecbd-ab02-4381-b20a-c9e13b36a7df" CreationDate="2018-01-05T22:14:44.387" UserId="3123" Text="|directx12|synchronization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16862" PostHistoryTypeId="5" PostId="6032" RevisionGUID="6a8a2b66-dec5-443f-b66e-4d41ccb79825" CreationDate="2018-01-05T22:15:11.847" UserId="4652" Comment="Typo in formula" Text="Eye position, projection reference point PRP, camera center, or projection center are all just different words for the same thing. &#xD;&#xA;&#xD;&#xA;gluLookAt() applied to the GL_MODELVIEW matrix works for both, parallel and perspective projection.&#xD;&#xA;&#xD;&#xA;You can choose between parallel and perspective projection by setting up the GL_PROJECTION matrix. For perspective projection this can be done using the gluPerspective() function.&#xD;&#xA;&#xD;&#xA;http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/graphics_6_1_eng_web.html#19&#xD;&#xA;&#xD;&#xA;**Edit: (after revised question)**&#xD;&#xA;&#xD;&#xA;If the PRP is not at the eye position, you can not use gluPerspective(). Instead you have to create your own GL_PROJECTION matrix. Following the formula that you have now provided, this results in the 4 x 4 matrix:&#xD;&#xA;&#xD;&#xA;$$\mathtt{A} =\begin{bmatrix} z_c-z_{pp} &amp; 0 &amp; -x_c &amp;  x_c \cdot z_{pp}\\ 0  &amp; z_c-z_{pp}  &amp; -y_c &amp; y_c \cdot z_{pp} \\ 0 &amp; 0 &amp; \frac{\mathrm{far}+\mathrm{near}}{\mathrm{near}-\mathrm{far}} &amp; \frac{2 \cdot \mathrm{far} \cdot \mathrm{near}}{\mathrm{near}-\mathrm{far}} \\ 0 &amp; 0 &amp; -1 &amp; z_c \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I have done a quick OpenGL/WebGL rendering test with the GSN Composer. Follow the link and move the mouse over the render output to change $x_c$ and $y_c$ of the projection reference point $(x_c, y_c, z_c)$:&#xD;&#xA;&#xD;&#xA;https://www.gsn-lib.org/docs/gallery.php?projectName=ProjRefPoint&amp;graphName=ProjectionReferencePoint&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16863" PostHistoryTypeId="5" PostId="6081" RevisionGUID="c6fe992f-a30c-4053-acce-82ff622fefb1" CreationDate="2018-01-05T22:32:31.453" UserId="506" Comment="fixed grammar in title and body" Text="How does `Map()` work? I would guess that it allocates memory to fit the resource size (or a range of it), but when are the bytes sent to the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16864" PostHistoryTypeId="4" PostId="6081" RevisionGUID="c6fe992f-a30c-4053-acce-82ff622fefb1" CreationDate="2018-01-05T22:32:31.453" UserId="506" Comment="fixed grammar in title and body" Text="How does ID3D12Resource::Map work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16865" PostHistoryTypeId="24" PostId="6081" RevisionGUID="c6fe992f-a30c-4053-acce-82ff622fefb1" CreationDate="2018-01-05T22:32:31.453" Comment="Proposed by 506 approved by 3123 edit id of 293" ContentLicense="CC BY-SA 3.0" />
  <row Id="16867" PostHistoryTypeId="5" PostId="6078" RevisionGUID="41335f87-b418-4ac4-8460-f7e616af5903" CreationDate="2018-01-06T10:47:01.017" UserId="2485" Comment="deleted 106 characters in body" Text="I am following the [WebGL2Fundametals tutorial][1]. Using some sample (cube) data I was able to successfully call `gl.drawElements();` using index, normal and geometry data. This are my fragment and vertex shaders:&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es    &#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    in vec3 v_normal;&#xD;&#xA;    in vec3 v_surfaceToLight;&#xD;&#xA;    in vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 u_color;&#xD;&#xA;    uniform float u_shininess;&#xD;&#xA;    uniform vec3 u_lightDirection;&#xD;&#xA;    &#xD;&#xA;    uniform float u_innerLimit; // In dot space&#xD;&#xA;    uniform float u_outerLimit; // In dot space&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      vec3 normal = normalize(v_normal);&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceToLightDirection = normalize(v_surfaceToLight);&#xD;&#xA;      vec3 surfaceToViewDirection = normalize(v_surfaceToView);&#xD;&#xA;      vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);&#xD;&#xA;    &#xD;&#xA;      float dotFromDirection = dot(surfaceToLightDirection, -u_lightDirection);&#xD;&#xA;      float inLight = smoothstep(u_outerLimit, u_innerLimit, dotFromDirection);&#xD;&#xA;      // Using normals for color calculation based on the incidence of light&#xD;&#xA;      float light = inLight * dot(normal, surfaceToLightDirection);&#xD;&#xA;      float specular = inLight * pow(dot(normal, halfVector), u_shininess);&#xD;&#xA;    &#xD;&#xA;      outColor = u_color;&#xD;&#xA;    &#xD;&#xA;      outColor.rgb *= light;&#xD;&#xA;    &#xD;&#xA;      // Add in the specular&#xD;&#xA;      outColor.rgb += specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    in vec4 a_position;&#xD;&#xA;    in vec3 a_normal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 u_world;&#xD;&#xA;    uniform mat4 u_worldViewProjection;&#xD;&#xA;    uniform mat4 u_worldInverseTranspose;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 u_lightWorldPosition;&#xD;&#xA;    uniform vec3 u_viewWorldPosition;&#xD;&#xA;    &#xD;&#xA;    // varying to pass the normal to the fragment shader&#xD;&#xA;    out vec3 v_normal;&#xD;&#xA;    &#xD;&#xA;    out vec3 v_surfaceToLight;&#xD;&#xA;    out vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;      gl_Position = u_worldViewProjection * a_position;&#xD;&#xA;    &#xD;&#xA;      // Orient the normals and pass to the fragment shader&#xD;&#xA;      v_normal = mat3(u_worldInverseTranspose) * a_normal;&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceWorldPosition = (u_world * a_position).xyz;&#xD;&#xA;      v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;&#xD;&#xA;      v_surfaceToView = u_viewWorldPosition - surfaceWorldPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With the following call the cube is successfully rendered:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);&#xD;&#xA;    GLHelper.setUniformValues(this._uniforms, uniformValues);&#xD;&#xA;    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the working cube data:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;            // Front face&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;&#xD;&#xA;            // Back face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;            100, -100, -100,&#xD;&#xA;&#xD;&#xA;            // Top face&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;&#xD;&#xA;            // Bottom face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            100, -100, -100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;&#xD;&#xA;            // Right face&#xD;&#xA;            100, -100, -100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;&#xD;&#xA;            // Left face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;&#xD;&#xA;Normals:&#xD;&#xA;&#xD;&#xA;            // Front&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;&#xD;&#xA;            // Back face&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;&#xD;&#xA;            // Top face&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Bottom face&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Right face&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Left face&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;            0, 1, 2, 0, 2, 3,    // Front face&#xD;&#xA;            4, 5, 6, 4, 6, 7,    // Back face&#xD;&#xA;            8, 9, 10, 8, 10, 11,  // Top face&#xD;&#xA;            12, 13, 14, 12, 14, 15, // Bottom face&#xD;&#xA;            16, 17, 18, 16, 18, 19, // Right face&#xD;&#xA;            20, 21, 22, 20, 22, 23,  // Left face&#xD;&#xA;&#xD;&#xA;If I get it right the normals in this model should look something like the cube's normals in [the very first animation in the &quot;Introducing normals&quot; part](https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html). Now I was trying to create and import a cube using Blender.&#xD;&#xA;&#xD;&#xA;Unfortunately I wasn't able to recreate a cube with the same kind of normals. Blender generates only one (pink) normal per vertex and they also obviously have a totally different angle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[Some sources](https://blender.stackexchange.com/a/14697) suggest that smoothing the faces would fix this issue. It did not for me. Here is the Wavefront file:&#xD;&#xA;&#xD;&#xA;    o Cube&#xD;&#xA;    v 1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 1.000000 -0.999999&#xD;&#xA;    v 0.999999 1.000000 1.000001&#xD;&#xA;    v -1.000000 1.000000 1.000000&#xD;&#xA;    v -1.000000 1.000000 -1.000000&#xD;&#xA;    vn 0.0000 -1.0000 0.0000&#xD;&#xA;    vn 0.0000 1.0000 0.0000&#xD;&#xA;    vn 1.0000 -0.0000 0.0000&#xD;&#xA;    vn 0.0000 -0.0000 1.0000&#xD;&#xA;    vn -1.0000 -0.0000 -0.0000&#xD;&#xA;    vn 0.0000 0.0000 -1.0000&#xD;&#xA;    s off&#xD;&#xA;    f 1//1 3//1 4//1&#xD;&#xA;    f 8//2 6//2 5//2&#xD;&#xA;    f 5//3 2//3 1//3&#xD;&#xA;    f 6//4 3//4 2//4&#xD;&#xA;    f 3//5 8//5 4//5&#xD;&#xA;    f 1//6 8//6 5//6&#xD;&#xA;    f 1//1 2//1 3//1&#xD;&#xA;    f 8//2 7//2 6//2&#xD;&#xA;    f 5//3 6//3 2//3&#xD;&#xA;    f 6//4 7//4 3//4&#xD;&#xA;    f 3//5 7//5 8//5&#xD;&#xA;    f 1//6 4//6 8//6&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I try to import and to render this data using `gl.drawElements(gl.TRIANGLES, 72, gl.UNSIGNED_SHORT, 0);` I get the following output:&#xD;&#xA;&#xD;&#xA;&gt; ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of&#xD;&#xA;&gt; range vertices in attribute 1&#xD;&#xA;&#xD;&#xA;If I use above (.obj) vertex and normal data six time each I do not get any more errors but instead of a cube only a single triangle seems to be rendered.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am pretty sure that `attribute 1` is `in vec3 a_normal;` in my vertex shader. So I am mainly confused about one thing here:&#xD;&#xA;&#xD;&#xA; - How do I modify my code in order to interpret and render the data&#xD;&#xA;   correctly?&#xD;&#xA;&#xD;&#xA;  [1]: https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/JhiET.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JFspW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16870" PostHistoryTypeId="2" PostId="6082" RevisionGUID="d9aceeaf-a477-4a5c-9a57-07728ad039d4" CreationDate="2018-01-06T12:27:57.693" UserId="7957" Text="To get the axis of rotation you could multiply the x-axis by the inverse of the view matrix:&#xD;&#xA;&#xD;&#xA;$b = V^{-1} e_1$&#xD;&#xA;&#xD;&#xA;Where $b$ is the axis of rotation in world space, $V$ is the view matrix and $e_1$ is the x-axis unit vector.&#xD;&#xA;&#xD;&#xA;Now, to make the object to spin around the axis of rotation $b$, we have to translate the object back to the origin, spin it, and then translate it back to its position in world space.&#xD;&#xA;&#xD;&#xA;Suppose you have a translation matrix $T$ that send the origin point to the object's location. The translated rotation (spin) of the object $M$ would be:&#xD;&#xA;&#xD;&#xA;$M = T R T^{-1}$&#xD;&#xA;&#xD;&#xA;Where $R$ is the rotation matrix around the $b$ axis. The matrix $R$ could be obtained using the Rodrigues formula or from a Quaternion or through some other methods out there.&#xD;&#xA;&#xD;&#xA;Finally you need to multiply the matrix $M$ to the existing transformation matrix of the object $W$. $W' = M W$ and use $W'$ for transforming the object.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16871" PostHistoryTypeId="5" PostId="6078" RevisionGUID="29752809-23da-4f77-a6a3-90a05e4a1989" CreationDate="2018-01-06T16:09:58.317" UserId="2485" Comment="Made images smaller. Added more information regarding the question." Text="I am following the [WebGL2Fundametals tutorial][1]. Using some sample (cube) data I was able to successfully call `gl.drawElements();` using index, normal and geometry data. This are my fragment and vertex shaders:&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es    &#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    in vec3 v_normal;&#xD;&#xA;    in vec3 v_surfaceToLight;&#xD;&#xA;    in vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 u_color;&#xD;&#xA;    uniform float u_shininess;&#xD;&#xA;    uniform vec3 u_lightDirection;&#xD;&#xA;    &#xD;&#xA;    uniform float u_innerLimit; // In dot space&#xD;&#xA;    uniform float u_outerLimit; // In dot space&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      vec3 normal = normalize(v_normal);&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceToLightDirection = normalize(v_surfaceToLight);&#xD;&#xA;      vec3 surfaceToViewDirection = normalize(v_surfaceToView);&#xD;&#xA;      vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);&#xD;&#xA;    &#xD;&#xA;      float dotFromDirection = dot(surfaceToLightDirection, -u_lightDirection);&#xD;&#xA;      float inLight = smoothstep(u_outerLimit, u_innerLimit, dotFromDirection);&#xD;&#xA;      // Using normals for color calculation based on the incidence of light&#xD;&#xA;      float light = inLight * dot(normal, surfaceToLightDirection);&#xD;&#xA;      float specular = inLight * pow(dot(normal, halfVector), u_shininess);&#xD;&#xA;    &#xD;&#xA;      outColor = u_color;&#xD;&#xA;    &#xD;&#xA;      outColor.rgb *= light;&#xD;&#xA;    &#xD;&#xA;      // Add in the specular&#xD;&#xA;      outColor.rgb += specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    in vec4 a_position;&#xD;&#xA;    in vec3 a_normal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 u_world;&#xD;&#xA;    uniform mat4 u_worldViewProjection;&#xD;&#xA;    uniform mat4 u_worldInverseTranspose;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 u_lightWorldPosition;&#xD;&#xA;    uniform vec3 u_viewWorldPosition;&#xD;&#xA;    &#xD;&#xA;    // varying to pass the normal to the fragment shader&#xD;&#xA;    out vec3 v_normal;&#xD;&#xA;    &#xD;&#xA;    out vec3 v_surfaceToLight;&#xD;&#xA;    out vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;      gl_Position = u_worldViewProjection * a_position;&#xD;&#xA;    &#xD;&#xA;      // Orient the normals and pass to the fragment shader&#xD;&#xA;      v_normal = mat3(u_worldInverseTranspose) * a_normal;&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceWorldPosition = (u_world * a_position).xyz;&#xD;&#xA;      v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;&#xD;&#xA;      v_surfaceToView = u_viewWorldPosition - surfaceWorldPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With the following call the cube is successfully rendered:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);&#xD;&#xA;    GLHelper.setUniformValues(this._uniforms, uniformValues);&#xD;&#xA;    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the working cube data:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;            // Front face&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;&#xD;&#xA;            // Back face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;            100, -100, -100,&#xD;&#xA;&#xD;&#xA;            // Top face&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;&#xD;&#xA;            // Bottom face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            100, -100, -100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;&#xD;&#xA;            // Right face&#xD;&#xA;            100, -100, -100,&#xD;&#xA;            100, 100, -100,&#xD;&#xA;            100, 100, 100,&#xD;&#xA;            100, -100, 100,&#xD;&#xA;&#xD;&#xA;            // Left face&#xD;&#xA;            -100, -100, -100,&#xD;&#xA;            -100, -100, 100,&#xD;&#xA;            -100, 100, 100,&#xD;&#xA;            -100, 100, -100,&#xD;&#xA;&#xD;&#xA;Normals:&#xD;&#xA;&#xD;&#xA;            // Front&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;&#xD;&#xA;            // Back face&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;            0.0, 0.0, -1.0,&#xD;&#xA;&#xD;&#xA;            // Top face&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Bottom face&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;            0.0, -1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Right face&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;            // Left face&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;            -1.0, 0.0, 0.0,&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;            0, 1, 2, 0, 2, 3,    // Front face&#xD;&#xA;            4, 5, 6, 4, 6, 7,    // Back face&#xD;&#xA;            8, 9, 10, 8, 10, 11,  // Top face&#xD;&#xA;            12, 13, 14, 12, 14, 15, // Bottom face&#xD;&#xA;            16, 17, 18, 16, 18, 19, // Right face&#xD;&#xA;            20, 21, 22, 20, 22, 23,  // Left face&#xD;&#xA;&#xD;&#xA;If I get it right the normals in this model should look something like the cube's normals in [the very first animation in the &quot;Introducing normals&quot; part](https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html). Now I was trying to create and import a cube using Blender.&#xD;&#xA;&#xD;&#xA;Unfortunately I wasn't able to recreate a cube with the same kind of normals. Blender generates only one (pink) normal per vertex and they also obviously have a totally different angle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[Some sources](https://blender.stackexchange.com/a/14697) suggest that smoothing the faces would fix this issue. It did not for me. Here is the Wavefront file:&#xD;&#xA;&#xD;&#xA;    o Cube&#xD;&#xA;    v 1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 1.000000 -0.999999&#xD;&#xA;    v 0.999999 1.000000 1.000001&#xD;&#xA;    v -1.000000 1.000000 1.000000&#xD;&#xA;    v -1.000000 1.000000 -1.000000&#xD;&#xA;    vn 0.0000 -1.0000 0.0000&#xD;&#xA;    vn 0.0000 1.0000 0.0000&#xD;&#xA;    vn 1.0000 -0.0000 0.0000&#xD;&#xA;    vn 0.0000 -0.0000 1.0000&#xD;&#xA;    vn -1.0000 -0.0000 -0.0000&#xD;&#xA;    vn 0.0000 0.0000 -1.0000&#xD;&#xA;    s off&#xD;&#xA;    f 1//1 3//1 4//1&#xD;&#xA;    f 8//2 6//2 5//2&#xD;&#xA;    f 5//3 2//3 1//3&#xD;&#xA;    f 6//4 3//4 2//4&#xD;&#xA;    f 3//5 8//5 4//5&#xD;&#xA;    f 1//6 8//6 5//6&#xD;&#xA;    f 1//1 2//1 3//1&#xD;&#xA;    f 8//2 7//2 6//2&#xD;&#xA;    f 5//3 6//3 2//3&#xD;&#xA;    f 6//4 7//4 3//4&#xD;&#xA;    f 3//5 7//5 8//5&#xD;&#xA;    f 1//6 4//6 8//6&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I try to import and to render this data using `gl.drawElements(gl.TRIANGLES, 72, gl.UNSIGNED_SHORT, 0);` I get the following output:&#xD;&#xA;&#xD;&#xA;&gt; ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of&#xD;&#xA;&gt; range vertices in attribute 1&#xD;&#xA;&#xD;&#xA;If I use above (.obj) vertex and normal data six time each I do not get any more errors but instead of a cube only a single triangle seems to be rendered.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am pretty sure that `attribute 1` is `in vec3 a_normal;` in my vertex shader. So I am mainly confused about one thing here:&#xD;&#xA;&#xD;&#xA; - How do I modify my code in order to interpret and render the data&#xD;&#xA;   correctly?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;After changing indices to be zero based I do get more than a single triangle, the object still looks wrong.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The result drawn with `gl.LINES`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/JhiETm.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JFspWm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/VpR3l.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/88klr.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="16873" PostHistoryTypeId="2" PostId="6084" RevisionGUID="5259a757-287c-4766-a158-c934e368932d" CreationDate="2018-01-06T18:20:57.127" UserId="6541" Text="I could make it by Worley noise&#xD;&#xA;&#xD;&#xA;&gt;Worley noise is a noise function introduced by Steven Worley in 1996. In computer graphics it is used to create procedural textures,that is textures that are created automatically in arbitrary precision and don't have to be drawn by hand. Worley noise comes close to simulating textures of stone, water, or cell noise.&#xD;&#xA;&#xD;&#xA;https://thebookofshaders.com/12/&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform vec2 u_resolution;&#xD;&#xA;    uniform float u_time;&#xD;&#xA;    &#xD;&#xA;    // Permutation polynomial: (34x^2 + x) mod 289&#xD;&#xA;    vec4 permute(vec4 x) {&#xD;&#xA;      return mod((34.0 * x + 1.0) * x, 289.0);&#xD;&#xA;    }&#xD;&#xA;    vec3 permute(vec3 x) {&#xD;&#xA;      return mod((34.0 * x + 1.0) * x, 289.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Cellular noise, returning F1 and F2 in a vec2.&#xD;&#xA;    // Speeded up by using 2x2x2 search window instead of 3x3x3,&#xD;&#xA;    // at the expense of some pattern artifacts.&#xD;&#xA;    // F2 is often wrong and has sharp discontinuities.&#xD;&#xA;    // If you need a good F2, use the slower 3x3x3 version.&#xD;&#xA;    vec2 cellular2x2x2(vec3 P) {&#xD;&#xA;    	#define K 0.142857142857 // 1/7&#xD;&#xA;    	#define Ko 0.428571428571 // 1/2-K/2&#xD;&#xA;    	#define K2 0.020408163265306 // 1/(7*7)&#xD;&#xA;    	#define Kz 0.166666666667 // 1/6&#xD;&#xA;    	#define Kzo 0.416666666667 // 1/2-1/6*2&#xD;&#xA;    	#define jitter 0.8 // smaller jitter gives less errors in F2&#xD;&#xA;    	vec3 Pi = mod(floor(P), 289.0);&#xD;&#xA;     	vec3 Pf = fract(P);&#xD;&#xA;    	vec4 Pfx = Pf.x + vec4(0.0, -1.0, 0.0, -1.0);&#xD;&#xA;    	vec4 Pfy = Pf.y + vec4(0.0, 0.0, -1.0, -1.0);&#xD;&#xA;    	vec4 p = permute(Pi.x + vec4(0.0, 1.0, 0.0, 1.0));&#xD;&#xA;    	p = permute(p + Pi.y + vec4(0.0, 0.0, 1.0, 1.0));&#xD;&#xA;    	vec4 p1 = permute(p + Pi.z); // z+0&#xD;&#xA;    	vec4 p2 = permute(p + Pi.z + vec4(1.0)); // z+1&#xD;&#xA;    	vec4 ox1 = fract(p1*K) - Ko;&#xD;&#xA;    	vec4 oy1 = mod(floor(p1*K), 7.0)*K - Ko;&#xD;&#xA;    	vec4 oz1 = floor(p1*K2)*Kz - Kzo; // p1 &lt; 289 guaranteed&#xD;&#xA;    	vec4 ox2 = fract(p2*K) - Ko;&#xD;&#xA;    	vec4 oy2 = mod(floor(p2*K), 7.0)*K - Ko;&#xD;&#xA;    	vec4 oz2 = floor(p2*K2)*Kz - Kzo;&#xD;&#xA;    	vec4 dx1 = Pfx + jitter*ox1;&#xD;&#xA;    	vec4 dy1 = Pfy + jitter*oy1;&#xD;&#xA;    	vec4 dz1 = Pf.z + jitter*oz1;&#xD;&#xA;    	vec4 dx2 = Pfx + jitter*ox2;&#xD;&#xA;    	vec4 dy2 = Pfy + jitter*oy2;&#xD;&#xA;    	vec4 dz2 = Pf.z - 1.0 + jitter*oz2;&#xD;&#xA;    	vec4 d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1; // z+0&#xD;&#xA;    	vec4 d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2; // z+1&#xD;&#xA;    &#xD;&#xA;    	// Sort out the two smallest distances (F1, F2)&#xD;&#xA;    #if 0&#xD;&#xA;    	// Cheat and sort out only F1&#xD;&#xA;    	d1 = min(d1, d2);&#xD;&#xA;    	d1.xy = min(d1.xy, d1.wz);&#xD;&#xA;    	d1.x = min(d1.x, d1.y);&#xD;&#xA;    	return sqrt(d1.xx);&#xD;&#xA;    #else&#xD;&#xA;    	// Do it right and sort out both F1 and F2&#xD;&#xA;    	vec4 d = min(d1,d2); // F1 is now in d&#xD;&#xA;    	d2 = max(d1,d2); // Make sure we keep all candidates for F2&#xD;&#xA;    	d.xy = (d.x &lt; d.y) ? d.xy : d.yx; // Swap smallest to d.x&#xD;&#xA;    	d.xz = (d.x &lt; d.z) ? d.xz : d.zx;&#xD;&#xA;    	d.xw = (d.x &lt; d.w) ? d.xw : d.wx; // F1 is now in d.x&#xD;&#xA;    	d.yzw = min(d.yzw, d2.yzw); // F2 now not in d2.yzw&#xD;&#xA;    	d.y = min(d.y, d.z); // nor in d.z&#xD;&#xA;    	d.y = min(d.y, d.w); // nor in d.w&#xD;&#xA;    	d.y = min(d.y, d2.x); // F2 is now in d.y&#xD;&#xA;    	return sqrt(d.xy); // F1 and F2&#xD;&#xA;    #endif&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord ){&#xD;&#xA;    &#xD;&#xA;        vec2 uv = (fragCoord.xy - iResolution.xy*.5)/iResolution.y;&#xD;&#xA;        &#xD;&#xA;        float w = 1. - dot(uv, uv)*3.;&#xD;&#xA;        &#xD;&#xA;        uv *= 48.;    &#xD;&#xA;        vec2 ip = floor(uv);&#xD;&#xA;        vec2 v = cellular2x2x2(vec3(uv, iTime/2.));&#xD;&#xA;        &#xD;&#xA;        float c = v.x; //v.y - v.x&#xD;&#xA;        &#xD;&#xA;        c -= .35*w;&#xD;&#xA;        &#xD;&#xA;        c = smoothstep(0., max(.1/c, 0.), c);&#xD;&#xA;        &#xD;&#xA;        vec3 col = mix(vec3(0), vec3(1), c);&#xD;&#xA;        &#xD;&#xA;        fragColor = vec4(sqrt(max(col, 0.)), 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;you can see this In shadertoy https://www.shadertoy.com/view/XlSBDz" ContentLicense="CC BY-SA 3.0" />
  <row Id="16874" PostHistoryTypeId="2" PostId="6085" RevisionGUID="ffb8f562-2d71-470d-b38c-9d59c1d417b7" CreationDate="2018-01-07T02:37:29.947" UserId="7999" Text="I'm currently making a small 3d renderer and I got stuck in Phong shading.&#xD;&#xA;&#xD;&#xA;My questions are: &#xD;&#xA;&#xD;&#xA;1- in which space the light coordinate should be converted? &#xD;&#xA;&#xD;&#xA;I have my light position at (0,0,0)-&gt; world coordinate.&#xD;&#xA;&#xD;&#xA;I'd like to calculate &quot;phong shading&quot; after converting all the vertices to screen space(viewport). &#xD;&#xA;So Should I convert the light position to screen space too?    &#xD;&#xA;&#xD;&#xA;2- Is there faster way to calculate Phong shading with normal interpolation if camera's position = light's position?&#xD;&#xA;&#xD;&#xA;Thank you! " ContentLicense="CC BY-SA 3.0" />
  <row Id="16875" PostHistoryTypeId="1" PostId="6085" RevisionGUID="ffb8f562-2d71-470d-b38c-9d59c1d417b7" CreationDate="2018-01-07T02:37:29.947" UserId="7999" Text="Light coordinate in Phong shading and Normal interpolation" ContentLicense="CC BY-SA 3.0" />
  <row Id="16876" PostHistoryTypeId="3" PostId="6085" RevisionGUID="ffb8f562-2d71-470d-b38c-9d59c1d417b7" CreationDate="2018-01-07T02:37:29.947" UserId="7999" Text="|rasterizer|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16879" PostHistoryTypeId="2" PostId="6086" RevisionGUID="de8dc858-ab61-4f69-b16b-e974b4c363f5" CreationDate="2018-01-07T04:24:10.463" UserId="2707" Text="Typically, you calculate lighting in either world-space or view-space (or camera-space). The benefit to calculating it in camera-space is the increased precision, although this may involve introduce additional math operations in shaders depending on your setup. So it wouldn't be in screenspace, or you would need to reconstruct the positions (which could happen in deferred shading depending on your G-buffer layout).&#xD;&#xA;&#xD;&#xA;I assume you are talking about a punctual light type (such as a point light). If so, then if your light position equals your camera position, then the view and light angles are the same, which can be factored out in the BRDF that you use, so you save a dot product." ContentLicense="CC BY-SA 3.0" />
  <row Id="16880" PostHistoryTypeId="5" PostId="6086" RevisionGUID="5e7bb0d9-9584-4631-b57d-e7065c6cd202" CreationDate="2018-01-07T04:55:30.677" UserId="2707" Comment="deleted 5 characters in body" Text="Typically, you calculate lighting in either world-space or view-space (or camera-space). The benefit to calculating it in camera-space is the increased precision, although this may involve introduce additional math operations in shaders depending on your setup. So it wouldn't be in screenspace, or you would need to reconstruct the positions (which could happen in deferred shading depending on your G-buffer layout).&#xD;&#xA;&#xD;&#xA;I assume you are talking about a punctual light type (such as a point light). If so, if your light position equals your camera position, then the view and light angles are the same, which can be factored out in the BRDF that you use, so you save a dot product." ContentLicense="CC BY-SA 3.0" />
  <row Id="16881" PostHistoryTypeId="2" PostId="6087" RevisionGUID="2f5f9087-ed99-4259-b098-ecb553ea1ea1" CreationDate="2018-01-07T05:29:13.453" UserId="7999" Text="I'm trying to figure out how to reverse Eye space -&gt; projection -&gt; clip(divide by w) -&gt; screen space conversion.&#xD;&#xA;&#xD;&#xA;Basically, I want to get Screen space (still have z value for z-buffer) -&gt; undivide? by w -&gt; inverse projection. &#xD;&#xA;&#xD;&#xA;I found the inverse matrix for projection but can't figure out how to get the coordinate &quot;undivided&quot; by w.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 3.0" />
  <row Id="16882" PostHistoryTypeId="1" PostId="6087" RevisionGUID="2f5f9087-ed99-4259-b098-ecb553ea1ea1" CreationDate="2018-01-07T05:29:13.453" UserId="7999" Text="Screen space coordinates to Eye space conversion" ContentLicense="CC BY-SA 3.0" />
  <row Id="16883" PostHistoryTypeId="3" PostId="6087" RevisionGUID="2f5f9087-ed99-4259-b098-ecb553ea1ea1" CreationDate="2018-01-07T05:29:13.453" UserId="7999" Text="|matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16884" PostHistoryTypeId="2" PostId="6088" RevisionGUID="1fa0c770-d5f0-44ff-8190-84f3a02ec768" CreationDate="2018-01-07T05:43:47.720" UserId="7868" Text="I recently set up temporal super-sampling in my path-tracer, and now I'm trying to improve early samples with ray jitter. The jitter works *well enough* and hides obvious aliasing artifacts, but it creates tattered edges instead of regular grain (e.g: https://i.stack.imgur.com/gHwaS.jpg). Is there any way to change that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16885" PostHistoryTypeId="1" PostId="6088" RevisionGUID="1fa0c770-d5f0-44ff-8190-84f3a02ec768" CreationDate="2018-01-07T05:43:47.720" UserId="7868" Text="Structural artifacts in ray jitter" ContentLicense="CC BY-SA 3.0" />
  <row Id="16886" PostHistoryTypeId="3" PostId="6088" RevisionGUID="1fa0c770-d5f0-44ff-8190-84f3a02ec768" CreationDate="2018-01-07T05:43:47.720" UserId="7868" Text="|pathtracing|antialiasing|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16887" PostHistoryTypeId="5" PostId="6088" RevisionGUID="bdfaeb02-8c26-48e8-83d5-1bd3e467f9fc" CreationDate="2018-01-07T06:00:24.390" UserId="7868" Comment="Clarified samples/pixel in my example image" Text="I recently set up temporal super-sampling in my path-tracer, and now I'm trying to improve early samples by adding random offsets between -[PIXEL_WIDTH] and +[PIXEL_WIDTH] to each initial ray position. The jitter works *well enough* and hides obvious aliasing artifacts, but it creates tattered edges (e.g: https://i.stack.imgur.com/gHwaS.jpg is my test shape after one sample/pixel) instead of regular grain. Is there any way to change that?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16894" PostHistoryTypeId="5" PostId="6073" RevisionGUID="b1ce8ea9-ddfa-45cc-8c5d-b8015b6f2102" CreationDate="2018-01-07T18:51:38.593" UserDisplayName="user7566" Comment="grammar edit" Text="I'm trying to generate a random halftone like below image:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![2018-01-05_8-16-16](https://user-images.githubusercontent.com/16706911/34595885-b1cf12fa-f1f0-11e7-95ee-4f255f522db8.jpg)&#xD;&#xA;&#xD;&#xA;this is a simple halftone that I tried, but I need a random halftone&#xD;&#xA;&#xD;&#xA;    float PI = 3.14159265359;&#xD;&#xA;        &#xD;&#xA;        void mainImage(out vec4 fragColor, in vec2 fragCoord) {&#xD;&#xA;        	vec2 p = (fragCoord.xy / iResolution.xy - 0.5)/0.5;&#xD;&#xA;        		&#xD;&#xA;                vec3 n = vec3(p, sqrt(dot(p, p)));&#xD;&#xA;                vec2 s = vec2(acos(n.z), atan(n.y, n.x))/PI;&#xD;&#xA;                vec2 uv = fract(s * vec2(30.0, 30.0));&#xD;&#xA;                float r = ceil(s.x * 30.0) / 17.0;&#xD;&#xA;                fragColor =  vec4(1.)*step(length(uv - 0.5),r);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/MljBRw&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I also tried using `for-loop` and `sin`,`cos`, but I need a low computing method because I want generate it in the game engine.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16895" PostHistoryTypeId="24" PostId="6073" RevisionGUID="b1ce8ea9-ddfa-45cc-8c5d-b8015b6f2102" CreationDate="2018-01-07T18:51:38.593" Comment="Proposed by 7566 approved by 6541 edit id of 294" ContentLicense="CC BY-SA 3.0" />
  <row Id="16896" PostHistoryTypeId="2" PostId="6090" RevisionGUID="0a7226b1-c1a6-4754-8b7c-9a0d60ee448b" CreationDate="2018-01-07T20:34:28.977" UserId="2308" Text="At least on iOS every frame you are likely to get a completely new texture that you need to draw to due to the OS switching between a couple textures each frame.&#xD;&#xA;&#xD;&#xA;My question is essentially if the OS feels the need to use multiple textures should we also be using multiple textures for some reason when doing full screen post processing? Is there ever a time where switching between off screen textures can improve performance? " ContentLicense="CC BY-SA 3.0" />
  <row Id="16897" PostHistoryTypeId="1" PostId="6090" RevisionGUID="0a7226b1-c1a6-4754-8b7c-9a0d60ee448b" CreationDate="2018-01-07T20:34:28.977" UserId="2308" Text="If the OS uses a frame-buffer with potentially different textures being displayed each frame why dont we?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16898" PostHistoryTypeId="3" PostId="6090" RevisionGUID="0a7226b1-c1a6-4754-8b7c-9a0d60ee448b" CreationDate="2018-01-07T20:34:28.977" UserId="2308" Text="|texture|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16899" PostHistoryTypeId="50" PostId="5697" RevisionGUID="d276e1ba-6846-4669-95a4-c780a2419089" CreationDate="2018-01-07T21:33:40.740" UserId="-1" />
  <row Id="16900" PostHistoryTypeId="2" PostId="6091" RevisionGUID="e6369c3f-1385-4af8-bf53-fa3494df5685" CreationDate="2018-01-07T23:25:01.763" UserId="2041" Text="The compositor in the OS wants to run at a consistent 60 FPS whatever rate your application runs at. If there were a single framebuffer for your application, then you might end up writing to it at the same time the compositor or overlay hardware wants to read from it to put it into the final frame. This would cause tearing. (Tearing could be avoided with a lock, but then the compositor might get stuck waiting for your frame to finish, which would also stop the user using the system GUI to get out of your slow/hanging app.)&#xD;&#xA;&#xD;&#xA;This is pretty much the same reason double buffering is used when you're drawing to a monitor directly, just earlier in the pipeline.&#xD;&#xA;&#xD;&#xA;This doesn't *usually* apply for processing within your application, because generally everything has to run at the same rate, and you can't run multiple stages in parallel. Say you draw some 3D stuff and then use a full-screen fragment shader to add some film grain and vignetting. It doesn't help if your full-screen shader can run faster than the 3D work, because you'll just be processing the same intermediate frames again.&#xD;&#xA;&#xD;&#xA;I can think of two situations really where it might help. The first is if it's not a post-process but something different, such as if you have a GUI or HUD that you want to run at full frame-rate even if you get frame drops in the main content. (This is the case the OS's window compositor falls into.)&#xD;&#xA;&#xD;&#xA;The second is if you can run the multiple stages of your processing pipeline in parallel, e.g. on multiple GPUs. That way, you can start rendering the next 3D frame while the full-screen shader is vignetting your previous frame. You'd have to know your hardware pretty well to split the work appropriately. On something like a gaming PC or graphics workstation that's using SLI to use multiple GPUs, you might find your parallel processing is slower because the workload is unbalanced and one GPU is idling a lot." ContentLicense="CC BY-SA 3.0" />
  <row Id="16901" PostHistoryTypeId="2" PostId="6092" RevisionGUID="e66da6d5-ce29-4b46-88ba-5978edbbe74e" CreationDate="2018-01-08T08:18:21.850" UserId="7008" Text="&gt; clip(divide by w) -&gt; screen space&#xD;&#xA;&#xD;&#xA;Be careful, if you're really in screen space. My guess is, you're doing picking or deferred rendering, in which case you're probably reading fragments in Normalized Device Space (i.e. x and y in range `[-1, 1]`*).&#xD;&#xA;&#xD;&#xA;If so, you can do it like this:&#xD;&#xA;&#xD;&#xA;Read out Normalized Device Coordinates as `vec4` with depth as z value and `1.0` as w value and bring them into `[0, 1]` range by multiplying by `2` and subtracting `1`.&#xD;&#xA;Convert them into Eye Space with the inverted projection matrix.&#xD;&#xA;Divide your new vector by its `w` coordinate (which is your undivide step). Now you're in Eye Space.&#xD;&#xA;&#xD;&#xA;There are more ways to do this, you can have a look at [Reconstructing Position From Depth][1] to dive further into how.&#xD;&#xA;&#xD;&#xA;*I'm assuming OpenGL, ranges might be different in DirectX&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/" ContentLicense="CC BY-SA 3.0" />
  <row Id="16902" PostHistoryTypeId="2" PostId="6093" RevisionGUID="bd775e3b-7230-4dbb-9f52-142229a6e236" CreationDate="2018-01-08T17:03:19.327" UserId="8009" Text="Object Space → World Space → Eye Space → Clip Space → Normalized Device Space → Window Space&#xD;&#xA;&#xD;&#xA; - You get from Object Space to World Space by multiplying by the &quot;World&#xD;&#xA;   Matrix&quot; (This may actually be multiple matrices depending&#xD;&#xA;   on the parent-child object hierarchy of the scene.  Compose them all together to get a single &quot;World Matrix&quot; for a given object.)&#xD;&#xA; - You get from World Space to Eye Space by multiplying by the &quot;View Matrix&quot;.&#xD;&#xA; - You get from Eye Space to Clip Space by multiplying by the &quot;Projection Matrix&quot;.&#xD;&#xA; - You get from Clip Space to Normalized Device Space by performing the &quot;perspective divide&quot; (divide by w in clip space coordinates).  **This is a non-linear transformation** requiring a divide, and is not represented by a matrix.  **Information can be destroyed in this step.**  If w is divided by w you just get 1, and there's no way to recover the original w.&#xD;&#xA;&#xD;&#xA; [![Divide by w][1]][1]&#xD;&#xA;&#xD;&#xA; - You get from Normalized Device Space to Window Space by performing the Viewport and Depth Range transform. (Simple linear relationship)&#xD;&#xA;&#xD;&#xA; [![Viewport Transform][2]][2]&#xD;&#xA;&#xD;&#xA; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The World Matrix, View Matrix, and Projection Matrix are all just 4x4 matrices and can be inverted to get the reverse transformation.&#xD;&#xA;&#xD;&#xA;So, to go backwards...&#xD;&#xA;&#xD;&#xA; - You get from Window Space to Normalized Device Space by performing the inverse of the Viewport and Depth Range transform.&#xD;&#xA; - You can get from Normalized Device Space to Clip Space by performing the inverse of the perspective divide (multiply by w).  **This is a non-linear transformation** requiring a multiply, and is not represented by a matrix.  In general this operation doesn't magically recover 3D data from 2D data.  You must know something about the depth externally to be able to recover the 3D position of a point on the 2D screen.&#xD;&#xA; - You can get from Clip Space to Eye Space by multiplying by the inverse of the &quot;Projection Matrix&quot;&#xD;&#xA; - You can get from Eye Space to World Space by multiplying by the inverse of the &quot;View Matrix&quot;.&#xD;&#xA; - You can get from World Space to Object Space by multiplying by the inverse of the &quot;World Matrix&quot;.&#xD;&#xA;&#xD;&#xA;May I suggest reading [this explanation of the OpenGL Transformation](http://www.songho.ca/opengl/gl_transform.html).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PqSr6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xGOwn.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vVEX9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16903" PostHistoryTypeId="2" PostId="6094" RevisionGUID="97864446-aad4-487c-8f2d-df045aa772fd" CreationDate="2018-01-08T23:38:21.603" UserId="5965" Text="I want to create a &quot;river biome&quot; where there are rivers cutting to a flat land mass, to start I wrote a little js to generate a random height map (with simplex noise) but that's where I'm stuck.&#xD;&#xA;&#xD;&#xA;this is what it generates:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;as you can see there are clear diagonal lines in there.&#xD;&#xA;I tried looking up how to fix this and on my search I found these:&#xD;&#xA;&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/283/is-all-grid-based-noise-inevitably-anisotropic&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/2447/why-does-my-perlin-noise-look-blocky&#xD;&#xA;&#xD;&#xA;I don't know if this is my problem of if it's something else entirely.&#xD;&#xA;&#xD;&#xA;here's the significant part of my code:&#xD;&#xA;&#xD;&#xA;    for(var y = 0;y &lt; myRivers.height;y++){&#xD;&#xA;        for(var x = 0;x &lt; myRivers.width;x++){&#xD;&#xA;            lightness = simplexnoise(x/50,y/50); // number between -1 and 1&#xD;&#xA;            myRivers.context.fillStyle = lightnessToRgb(lightness); //maps lightness to a color&#xD;&#xA;            myRivers.context.fillRect(x * 4, y * 4, 4, 4); // fills a pixel with the color&#xD;&#xA;        }&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FNwDW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16904" PostHistoryTypeId="1" PostId="6094" RevisionGUID="97864446-aad4-487c-8f2d-df045aa772fd" CreationDate="2018-01-08T23:38:21.603" UserId="5965" Text="unwanted patterns in simplex noise" ContentLicense="CC BY-SA 3.0" />
  <row Id="16905" PostHistoryTypeId="3" PostId="6094" RevisionGUID="97864446-aad4-487c-8f2d-df045aa772fd" CreationDate="2018-01-08T23:38:21.603" UserId="5965" Text="|noise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16907" PostHistoryTypeId="5" PostId="6094" RevisionGUID="a5299db3-ed0d-4740-81fe-5d2720717061" CreationDate="2018-01-08T23:50:01.050" UserId="5965" Comment="added 51 characters in body" Text="I want to create a &quot;river biome&quot; where there are rivers cutting to a flat land mass, to start I wrote a little js to generate a random height map (with simplex noise) but that's where I'm stuck.&#xD;&#xA;&#xD;&#xA;this is what it generates:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;as you can see there are clear diagonal lines in there.&#xD;&#xA;I tried looking up how to fix this and on my search I found these:&#xD;&#xA;&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/283/is-all-grid-based-noise-inevitably-anisotropic&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/2447/why-does-my-perlin-noise-look-blocky&#xD;&#xA;&#xD;&#xA;I don't know if this is my problem of if it's something else entirely.&#xD;&#xA;&#xD;&#xA;here's the significant part of my code:&#xD;&#xA;&#xD;&#xA;    for(var y = 0;y &lt; myRivers.height;y++){&#xD;&#xA;        for(var x = 0;x &lt; myRivers.width;x++){&#xD;&#xA;            lightness = simplexnoise(x/50,y/50); // number between -1 and 1&#xD;&#xA;            myRivers.context.fillStyle = lightnessToRgb(lightness); //maps lightness to a color&#xD;&#xA;            myRivers.context.fillRect(x * 4, y * 4, 4, 4); // fills a pixel with the color&#xD;&#xA;        }&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;a codepen: https://codepen.io/anon/pen/gooyMj&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FNwDW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="16909" PostHistoryTypeId="2" PostId="6095" RevisionGUID="5fe71ca5-2c7d-4554-a952-7732ae7611aa" CreationDate="2018-01-09T12:28:29.443" UserId="7107" Text="First you may want to take a look at [the doc][1]. &#xD;&#xA;&#xD;&#xA;Map basically allows you to retrieve a CPU pointer of a GPU resource. It performs a few operations on the background so the data is up to date. Depending on the type of resource you are mapping, you can perform different tasks like reading data or copying it. As far as I know, Map will only allocate an address not the memory of the resource.&#xD;&#xA;&#xD;&#xA;Hope it helps!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn788712%28v=vs.85%29.aspx?f=255&amp;MSPPError=-2147217396" ContentLicense="CC BY-SA 3.0" />
  <row Id="16910" PostHistoryTypeId="33" PostId="6078" RevisionGUID="30ac864e-b77e-490b-9dad-060a0d7869a8" CreationDate="2018-01-09T19:26:47.383" UserId="2485" Comment="43" />
  <row Id="16911" PostHistoryTypeId="2" PostId="6096" RevisionGUID="2ea0e19c-a475-42ff-830e-31856680a267" CreationDate="2018-01-09T22:00:41.943" UserId="4908" Text="The problem is with how wavefront files and OpenGL work with indices.&#xD;&#xA;&#xD;&#xA;## OpenGL ##&#xD;&#xA;OpenGL allows you to have different buffers, allowing your vertex to have multiple attributes. However, for every vertex in a face, it has only one index.&#xD;&#xA;&#xD;&#xA;Let us say that we have a quad. It consists out of a position buffer and a uv buffer. The positions would look like this&#xD;&#xA;&#xD;&#xA;    1, 1, 0;  -1, 1, 0;  -1, -1, 0;  1, -1, 0;&#xD;&#xA;The uv's would look like this&#xD;&#xA;&#xD;&#xA;    0, 0;     1, 0;      1, 1;       0, 1;&#xD;&#xA;The indices would look like this&#xD;&#xA;&#xD;&#xA;    0, 1, 2, 0, 2, 3&#xD;&#xA;When OpenGL does it's rendering, it looks at the index for the location of the data. If we have the very first vertex of the very first face, with the index of 0. It then picks the position with the index of 0: `(1, 1, 0)`. Then it picks the uv with also the index of zero: `(0, 0)`.&#xD;&#xA;&#xD;&#xA;Using the same index for each attribute means that all data can be sequentially stored in one long buffer. If OpenGL needs the data for a vertex, it only has to load one long strip of data. This is better for the cache than having to go to different parts of the memory to find all the information for just one vertex.&#xD;&#xA;&#xD;&#xA;**OpenGL uses the same index for all vertex attributes. You cannot tell OpenGL to take position number 3 with uv number 1.**&#xD;&#xA;&#xD;&#xA;## Wavefront ##&#xD;&#xA;Wavefront works differently. When doing the indexing, it indexes each attribute separately.&#xD;&#xA;&#xD;&#xA;Here is a declaration of a face&#xD;&#xA;&#xD;&#xA;    f 5//3 2//3 1//3&#xD;&#xA;We see three vertices, separated by a white space. Each vertex has two numbers. The first number is the index for the position. The second number is the index for the normal. They are both different.&#xD;&#xA;&#xD;&#xA;Wavefront does not need to care about caching. It just needs to store the data by using the least amount of memory (if we load everything in to memory. Saving it in plain text is of course not efficient). When looking at your .obj file, we can see that we have 8 positions, but only 6 normals. We have been able to remove 6 floating point numbers in total (2 normals consisting of 3 floats).&#xD;&#xA;&#xD;&#xA;**Wavefront specifies different indices for each vertex attribute. For a vertex, the position could be number 5, but the normal is number 4.**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Conclusion ##&#xD;&#xA;Wavefront and OpenGL use a different way of storing the data. This means that when parsing your wavefront file, you need to re-index the data to what OpenGL wants.&#xD;&#xA;&#xD;&#xA;What happened with you, is that OpenGL thought that the indices for the normals were actually indices for positions and that you had twice as many faces.&#xD;&#xA;&#xD;&#xA;What I would do, is to save all that wavefront data to temporary lists. You create your main vertex buffers. You go through every vertex of every face. You look at the data of that vertex. Then you see if you already have that data combined in your buffers. If so, you use the index of that data, else you add the new data to your buffers and add that index." ContentLicense="CC BY-SA 3.0" />
  <row Id="16912" PostHistoryTypeId="2" PostId="6097" RevisionGUID="132db1e6-bdf3-4e2b-ba86-7b2995a6d685" CreationDate="2018-01-09T23:05:37.227" UserId="48" Text="There are two general ways the graphics driver can implement `Map()`.&#xD;&#xA;&#xD;&#xA;One way is to set up a virtual memory mapping that makes the resource's actual memory (could be system memory or GPU memory) visible as part of the application's address space. If it does happen to be GPU memory, any writes you do would typically be buffered up and sent across the PCIe bus to the GPU, using [write combining](https://en.wikipedia.org/wiki/Write_combining). (Even on a unified-memory system, mapped resource memory probably has some different caching behavior from &quot;regular&quot; memory, since CPU and GPU caches aren't [coherent](https://en.wikipedia.org/wiki/Cache_coherence) with each other.)&#xD;&#xA;&#xD;&#xA;The other way the driver can implement `Map()` is to allocate memory and create a local copy of the resource, let your app edit it, then copy the modified memory back to the resource when `Unmap()` is called. This might need to be done if the actual memory layout of the resource on the GPU is &quot;weird&quot; somehow, like having a nonstandard tiling scheme or some such.&#xD;&#xA;&#xD;&#xA;The copying approach is clearly more expensive due to the extra copies required, so I'd expect the driver to use the memory mapping approach whenever possible." ContentLicense="CC BY-SA 3.0" />
  <row Id="16920" PostHistoryTypeId="2" PostId="6099" RevisionGUID="710293dc-3e15-415a-aa2b-b6f222f09ef7" CreationDate="2018-01-11T19:58:40.987" UserId="228" Text="In [these][1] slides, specifically page 11, the following formula is reported:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^N \frac{L_i(l_k)f(l_k,v)cos(\theta_{l_k})}{p(l_k,v)} \approx \left( \frac{1}{N} \sum_{k=1}^N L_i(l_k) \right) \left( \frac{1}{N} \sum_{k=1}^N  \frac{f(l_k,v)cos(\theta_{l_k})}{p(l_k,v)} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The formula above should be an approximation of the rendering equations. I'm looking for a paper that explains how that formula is derived, I cannot manage to find neither the title of a paper (other than the name &quot;Dimitar&quot; mentioned in the same page I pointed out).&#xD;&#xA;&#xD;&#xA;I've done some research about some possible method that would justify. [This][2] is the closest thing I managed to find, however there's some hypothesis that doesn't seem to me fits.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf&#xD;&#xA;  [2]: https://math.stackexchange.com/questions/337643/split-up-sum-of-products-suma-i-b-i-approx1-n-suma-i-sumb-i-for-uncor" ContentLicense="CC BY-SA 3.0" />
  <row Id="16921" PostHistoryTypeId="1" PostId="6099" RevisionGUID="710293dc-3e15-415a-aa2b-b6f222f09ef7" CreationDate="2018-01-11T19:58:40.987" UserId="228" Text="Paper for the approximation formula provided by Brian Karis" ContentLicense="CC BY-SA 3.0" />
  <row Id="16922" PostHistoryTypeId="3" PostId="6099" RevisionGUID="710293dc-3e15-415a-aa2b-b6f222f09ef7" CreationDate="2018-01-11T19:58:40.987" UserId="228" Text="|mathematics|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16923" PostHistoryTypeId="50" PostId="4632" RevisionGUID="e8520bf7-e51c-4f0d-875f-8494e3cbe577" CreationDate="2018-01-11T21:40:18.067" UserId="-1" />
  <row Id="16924" PostHistoryTypeId="2" PostId="6100" RevisionGUID="3884896d-0b24-4226-95aa-108a0d074f8a" CreationDate="2018-01-11T21:44:28.813" UserId="5703" Text="I do not have a derivation but i can explain the reasoning behind its usage.&#xD;&#xA;&#xD;&#xA;On the left side is a (monte carlo) estimator for the rendering equation. It states the very same thing that the rendering equation states but on a finite number of discrete samples.&#xD;&#xA;&#xD;&#xA;on the right side we have the $L_i(l_k)$ factor separated and &quot;integrated&quot; on its own.&#xD;&#xA;This approximation holds true when $L_i(l_k)$ is a constant, since $\sum_{k}f(k)\times n = n \times\sum_{k}f(k)$ - and, likewise, $\int_{k}f(k)\times n\space dk = n\times\int_{k}f(k)dk$ - when $n$ is a constant.&#xD;&#xA;&#xD;&#xA;$L_i(l_k)$ can be though of the colour of the incoming light and $\int_{k}f(l_k,v)dk$ can be thought of as the intensity of the reflected light. multiplying those together you get that now you can precompute $\int_{k}L_i(l_k)dk$, saving a lot of time in either texture lookups (in the case of sky / environment lighting / screen space ray marching) or raytracing calculations.&#xD;&#xA;&#xD;&#xA;However, since $L_i(l_k)$ is usually not a constant, this integral is not separable. Yet, in some cases (like when dealing with diffuse lighting or, more specifically, diffuse ambient lighting), the information that $f(l_k,v)$ carries is low-frequency enough that it can reasonably be approximated as a constant with respect to the distribution of $L_i(l_k)$. Experimentally, it can be shown that the final result is not too different from what you would expect." ContentLicense="CC BY-SA 3.0" />
  <row Id="16925" PostHistoryTypeId="5" PostId="6099" RevisionGUID="2fce016c-be54-453b-aa6b-0cb0c5bcdaa8" CreationDate="2018-01-11T22:37:12.807" UserId="48" Comment="math formatting tweak" Text="In [these][1] slides, specifically page 11, the following formula is reported:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^N \frac{L_i(l_k)f(l_k,v)\cos(\theta_{l_k})}{p(l_k,v)} \approx \left( \frac{1}{N} \sum_{k=1}^N L_i(l_k) \right) \left( \frac{1}{N} \sum_{k=1}^N  \frac{f(l_k,v)\cos(\theta_{l_k})}{p(l_k,v)} \right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The formula above should be an approximation of the rendering equations. I'm looking for a paper that explains how that formula is derived, I cannot manage to find neither the title of a paper (other than the name &quot;Dimitar&quot; mentioned in the same page I pointed out).&#xD;&#xA;&#xD;&#xA;I've done some research about some possible method that would justify. [This][2] is the closest thing I managed to find, however there's some hypothesis that doesn't seem to me fits.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf&#xD;&#xA;  [2]: https://math.stackexchange.com/questions/337643/split-up-sum-of-products-suma-i-b-i-approx1-n-suma-i-sumb-i-for-uncor" ContentLicense="CC BY-SA 3.0" />
  <row Id="16926" PostHistoryTypeId="50" PostId="5301" RevisionGUID="a4c580b4-24fc-4710-9604-f6c6f952a867" CreationDate="2018-01-11T22:40:18.590" UserId="-1" />
  <row Id="16927" PostHistoryTypeId="2" PostId="6101" RevisionGUID="71ced3df-ed4b-4a9a-a039-5847c86e90a0" CreationDate="2018-01-12T01:51:16.290" UserId="7868" Text="I recently set up a (very basic) ray-marched path-tracer, and I'm getting strange surface patterns on my area light [[link][1]]. I'm using known-valid analytical normals for the light's surface, and the same patterns appear when I use a well-tested gradient estimator anyway.&#xD;&#xA;&#xD;&#xA;Ray bounce directions are calculated with [amietia's diffuse BRDF][2], and regenerated after each bounce. The random numbers in each bounce are uncorrelated (hashed integer versions of the intersecting ray positions) and I'm offsetting ray distances at the start of each bounce by [0.01f] to avoid shadow acne.&#xD;&#xA;&#xD;&#xA;The last time I saw this bug was several months ago, and that time it *was* (probably) caused by shadow acne. What could it be now?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/niQA6.jpg&#xD;&#xA;  [2]: http://www.amietia.com/lambertnotangent.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="16928" PostHistoryTypeId="1" PostId="6101" RevisionGUID="71ced3df-ed4b-4a9a-a039-5847c86e90a0" CreationDate="2018-01-12T01:51:16.290" UserId="7868" Text="Ringlike artifacts produced by rays bouncing off a light source" ContentLicense="CC BY-SA 3.0" />
  <row Id="16929" PostHistoryTypeId="3" PostId="6101" RevisionGUID="71ced3df-ed4b-4a9a-a039-5847c86e90a0" CreationDate="2018-01-12T01:51:16.290" UserId="7868" Text="|lighting|pathtracing|diffuse|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16930" PostHistoryTypeId="2" PostId="6102" RevisionGUID="66666e7c-2aca-4932-bb8d-e55b926eba8c" CreationDate="2018-01-12T04:21:33.133" UserId="7462" Text="So I am facing the following issue. Say I have a minecraft like mesh (i.e I have a bunch of cubes on top of one another).&#xD;&#xA;&#xD;&#xA;I wish to smooth out this mesh in such a way that only the regions where tehre are edges are smotthed out and such that the smoothing concentrates around the edges (e.g if I have a staircase the overall shape of the cubes that make the staircase should still be close to the staircase but instead of hacing straight edges I should have something much smoother). &#xD;&#xA;&#xD;&#xA;I should be able to smooth things out locally, so that if a block is removed from this mesh, I can run the subdivision algorithm only on the newly generated coarse region that is created after the block is removed.&#xD;&#xA;&#xD;&#xA;Does anybody have any ideas as to which algorithm I could use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16931" PostHistoryTypeId="1" PostId="6102" RevisionGUID="66666e7c-2aca-4932-bb8d-e55b926eba8c" CreationDate="2018-01-12T04:21:33.133" UserId="7462" Text="How to smooth out a voxel grid?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16932" PostHistoryTypeId="3" PostId="6102" RevisionGUID="66666e7c-2aca-4932-bb8d-e55b926eba8c" CreationDate="2018-01-12T04:21:33.133" UserId="7462" Text="|algorithm|computational-geometry|voxelization|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16933" PostHistoryTypeId="5" PostId="2484" RevisionGUID="6e718fff-a109-4ae4-9a1d-26dfce7445fe" CreationDate="2018-01-12T04:28:05.290" UserId="3416" Comment="fix broken links" Text="In [this tutorial][1], &#xD;&#xA;&#xD;&#xA;&gt; It is very often the case that triangles are rendered that share&#xD;&#xA;&gt; edges. OpenGL offers a guarantee that, so long as the shared edge&#xD;&#xA;&gt; vertex positions are identical, there will be no sample gaps during&#xD;&#xA;&gt; scan conversion.&#xD;&#xA;&#xD;&#xA;1 What exactly are sample gaps during scan conversion? &#xD;&#xA;&#xD;&#xA;2 Under what circumstances, will it happen? &#xD;&#xA;&#xD;&#xA;3 Does it happen when the line cross the center of the fragment?&#xD;&#xA;  [1]: https://www.roiatalla.com/public/arcsynthesis/Basics/Intro%20Graphics%20and%20Rendering.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="16937" PostHistoryTypeId="2" PostId="6104" RevisionGUID="4fd6cb19-34fb-4258-8589-4b3168db8801" CreationDate="2018-01-12T18:17:42.530" UserId="5703" Text="If you have this data in a 3d array where a block is a 1 and no block is a 0 you can apply a 3d blur and then set all voxels that are left with a value higher than 0.5 to 1 and those that arent to 0. this will smooth out sharp details and leave flats mostly uneffected " ContentLicense="CC BY-SA 3.0" />
  <row Id="16938" PostHistoryTypeId="5" PostId="6102" RevisionGUID="c01f4167-bc85-4948-b023-7bdfcbaa975b" CreationDate="2018-01-12T19:00:10.033" UserId="7462" Comment="edited body" Text="So I am facing the following issue. Say I have a minecraft like mesh (i.e I have a bunch of cubes on top of one another).&#xD;&#xA;&#xD;&#xA;I wish to smooth out this mesh in such a way that only the regions where there are edges are smoothed out and such that the smoothing concentrates around the edges (e.g if I have a staircase the overall shape of the cubes that make the staircase should still be close to the staircase but instead of having straight edges I should have something much smoother). &#xD;&#xA;&#xD;&#xA;I should be able to smooth things out locally, so that if a block is removed from this mesh, I can run the subdivision algorithm only on the newly generated coarse region that is created after the block is removed.&#xD;&#xA;&#xD;&#xA;Does anybody have any ideas as to which algorithm I could use?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16939" PostHistoryTypeId="4" PostId="4632" RevisionGUID="9fbeccf5-5f5b-4727-9924-44642c0eaee5" CreationDate="2018-01-12T21:25:41.877" UserId="5703" Comment="Fixed typo in the title" Text="What is a good approach for handling uniforms in modern OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16940" PostHistoryTypeId="24" PostId="4632" RevisionGUID="9fbeccf5-5f5b-4727-9924-44642c0eaee5" CreationDate="2018-01-12T21:25:41.877" Comment="Proposed by 5703 approved by 209, 231 edit id of 295" ContentLicense="CC BY-SA 3.0" />
  <row Id="16942" PostHistoryTypeId="2" PostId="6105" RevisionGUID="d854a56e-4286-4f3f-91d6-88974622d4b6" CreationDate="2018-01-13T04:34:03.477" UserId="1937" Text="I've been having nightmares at work this week trying to get Unity's Standard shader, and my own custom car paint shader modded from it, to look good on Android. &#xD;&#xA;&#xD;&#xA;The most obvious problem was fractured specular highlights, which I  identified as a float precision issue, and solved by changing all the directional math to use float3 instead of half3. &#xD;&#xA;&#xD;&#xA;It now looks fine on GLES3, but on GLES2, which we want to support, the glossy reflections coming from reflection probes look terrible, with noisy matte areas all over the place.&#xD;&#xA;&#xD;&#xA;I finally tracked this down to the cube map texture lookup itself - different blur levels are stored in different MIP levels, and a textureCubeLod lookup samples the reflection at the right smoothness level. Trouble is, GLES2 doesn't natively support lod texture lookups, so it relies on an extension. If the extension is not found, and it seems most Android devices don't have it, it falls back to a regular texture sample, with the lod parameter becoming a bias. This explains the matte areas - sharp features are causing the tex lookup to be kicked down the mip chain to the rougher maps, and the bias applied from there. From certain angles, a single bit of noise in the normal map is enough to cause the effect. &#xD;&#xA;&#xD;&#xA;What I want to know is, does any workaround exist for this? My first thought was to 'bias the bias' using dfdx, dfdy, but unfortunately these are also GLES3 only. I may just have to kill glossy reflections altogether on older droids otherwise." ContentLicense="CC BY-SA 3.0" />
  <row Id="16943" PostHistoryTypeId="1" PostId="6105" RevisionGUID="d854a56e-4286-4f3f-91d6-88974622d4b6" CreationDate="2018-01-13T04:34:03.477" UserId="1937" Text="Any way to fake textureLod on GLES2?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16944" PostHistoryTypeId="3" PostId="6105" RevisionGUID="d854a56e-4286-4f3f-91d6-88974622d4b6" CreationDate="2018-01-13T04:34:03.477" UserId="1937" Text="|texture|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16945" PostHistoryTypeId="12" PostId="6101" RevisionGUID="446912a4-ede1-443c-85f0-8ea52c5954c8" CreationDate="2018-01-13T05:08:13.437" UserId="7868" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7868,&quot;DisplayName&quot;:&quot;Paul Ferris&quot;}]}" />
  <row Id="16946" PostHistoryTypeId="13" PostId="6101" RevisionGUID="9c1ace87-4853-4d77-aa70-e2d875c5d4f9" CreationDate="2018-01-13T05:08:28.533" UserId="7868" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7868,&quot;DisplayName&quot;:&quot;Paul Ferris&quot;}]}" />
  <row Id="16947" PostHistoryTypeId="2" PostId="6106" RevisionGUID="b0689cb6-018a-459d-abcb-c9394ed33ad2" CreationDate="2018-01-13T05:23:55.747" UserId="7868" Text="Fixed this today.&#xD;&#xA;The artifacts were produced by shadow acne and worsened by dodgy averages (assuming every ray would complete the maximum number of bounces before returning or exiting the scene) + an undersized PRNG state buffer; maybe I was just really tired, but I still don't know why bouncing rays off my light sources by default seemed like a good idea. The *point* of backward path tracing is to trace paths from the camera back to the light source(s) in a scene, and there's no reason to continue following a path (=&gt; evaluate bounces) if rays immediately intersect with a source after leaving the camera." ContentLicense="CC BY-SA 3.0" />
  <row Id="16948" PostHistoryTypeId="2" PostId="6107" RevisionGUID="270ba4fc-e571-4269-899b-c4b17b7a7a3c" CreationDate="2018-01-13T07:04:08.723" UserId="7868" Text="Jitter is *supposed* to make edges more irregular; that's how it masks aliasing in the first place. I didn't realise this when I made the question, but the noise in path tracers comes from undersampled global illumination; because each sample travels in a random direction, it's possible for a visually-significant number of samples to reach unrepresentative areas (e.g. for rays at the bottom of a curve to mostly hit the walls of the curve rather than travel upward towards), and the dissonance between these and the actual image function creates the fuzzy variance you get in path-tracing renderers.&#xD;&#xA;&#xD;&#xA;That sort of noise is completely different to the pseudo-one-dimensional edge variance you expect to get from ray jitter at one sample/pixel. Single-sample ray jitter essentially means pulling edges randomly closer to or further away from their actual tendency in order to hide the high-frequency patterns introduced by aliasing; it looks nothing like &quot;fuzzy&quot; GI noise because (at least at the single-sample scale I was thinking about when I made this question) it's one-dimensional (variance about an edge) rather than two-dimensional (variance over a surface).&#xD;&#xA;&#xD;&#xA;So, this question is invalid. It assumes that jittered edges are supposed to be fuzzy (as in GI noise), but forgets that edges are one-dimensional and that the jitter can't magically expand them to two dimensions and spread them over some domain (at least, not without spreading the aliasing as well (multi-pixel jitter)). Jitter doesn't produce fuzzy noise because it isn't supposed to; *it's only supposed to vary the relative distance of points &quot;on&quot; an edge from the actual edge positions given by the image signal*." ContentLicense="CC BY-SA 3.0" />
  <row Id="16949" PostHistoryTypeId="2" PostId="6108" RevisionGUID="89b77a61-ba1c-49f0-b9de-0a76b5b39331" CreationDate="2018-01-13T09:19:30.973" UserId="8026" Text="I'm trying to create single-channel (no mipmaps) texture initialized with my custom pixel data, but it crashes on glTextureSubImage2D. Any idea why?&#xD;&#xA;&#xD;&#xA;    const std::vector&lt;GLubyte&gt; myData(1025 * 1025, 0);&#xD;&#xA;    GLuint texture;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;texture);&#xD;&#xA;    glTextureStorage2D(texture, 1, GL_R8, 1025, 1025);&#xD;&#xA;    glTextureSubImage2D(texture, 0, 0, 0, 1025, 1025, GL_RED, GL_UNSIGNED_BYTE, &amp;myData[0]);" ContentLicense="CC BY-SA 3.0" />
  <row Id="16950" PostHistoryTypeId="1" PostId="6108" RevisionGUID="89b77a61-ba1c-49f0-b9de-0a76b5b39331" CreationDate="2018-01-13T09:19:30.973" UserId="8026" Text="OpenGL: Why glTextureSubImage2D crashes?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16951" PostHistoryTypeId="3" PostId="6108" RevisionGUID="89b77a61-ba1c-49f0-b9de-0a76b5b39331" CreationDate="2018-01-13T09:19:30.973" UserId="8026" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16952" PostHistoryTypeId="2" PostId="6109" RevisionGUID="086ed69b-d519-4d60-ba0c-33618b363935" CreationDate="2018-01-13T15:42:33.653" UserId="7918" Text="I have been reading this paper http://openaccess.thecvf.com/content_iccv_workshops_2013/W21/papers/Sugiura_3D_Surface_Extraction_2013_ICCV_paper.pdf&#xD;&#xA;&#xD;&#xA;I have already generated a tetrahedra for my mesh and I would like to create a surface mesh. I can't understand the algorithm. From my understanding, there is a camera that generates rays towards to the points of the tetrahedral, and I get the intersections, but how would I eliminate the triangles that are inside or outside ? how would I detect inside or outside polygons ?&#xD;&#xA;&#xD;&#xA;Would someone give a pseudo code of the algorithm ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16953" PostHistoryTypeId="1" PostId="6109" RevisionGUID="086ed69b-d519-4d60-ba0c-33618b363935" CreationDate="2018-01-13T15:42:33.653" UserId="7918" Text="Ray tracing and mesh extraction" ContentLicense="CC BY-SA 3.0" />
  <row Id="16954" PostHistoryTypeId="3" PostId="6109" RevisionGUID="086ed69b-d519-4d60-ba0c-33618b363935" CreationDate="2018-01-13T15:42:33.653" UserId="7918" Text="|computational-geometry|subdivision|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16955" PostHistoryTypeId="2" PostId="6110" RevisionGUID="8832a6d3-16f1-49ff-82b4-5884af96f545" CreationDate="2018-01-13T16:57:47.890" UserId="2654" Text="Pixel transfer operations are governed by more than just your parameters to a pixel transfer function. They are also governed by [parameters passed to the `glPixelStore` functions][1].&#xD;&#xA;&#xD;&#xA;Of particular interest to you is `GL_PACK_ALIGNMENT`. This tells OpenGL what the byte alignment for each row of data is in your array. By default, this value is *four*, not one.&#xD;&#xA;&#xD;&#xA;This means that OpenGL will believe that the second row of your image starts at this address: `&amp;myData[1028]`, since 1025 is not aligned to 4 bytes. And that means it will run off the end of your allocated buffer eventually.&#xD;&#xA;&#xD;&#xA;If you are using data with 1-byte alignment for rows, you must inform OpenGL of this by calling `glPixelStorei(GL_PACK_ALIGNMENT, 1);`. Note that [you should not do this by default; do it only when dealing with byte aligned data][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_transfer_parameters&#xD;&#xA;  [2]: https://stackoverflow.com/a/11045278/734069" ContentLicense="CC BY-SA 3.0" />
  <row Id="16956" PostHistoryTypeId="2" PostId="6111" RevisionGUID="1fc18107-1c39-41d3-bed8-94e603f7caa4" CreationDate="2018-01-13T19:05:01.193" UserId="48" Text="One way would be to break out the mip levels of the cube into a bunch of separate textures, then implement the mip selection and trilinear filtering yourself, by branching based on the LOD value.&#xA;&#xA;That doesn't sound fast, though, given you're targeting older devices. You could speed it up by forgoing trilinear filtering and just using the nearest-neighbor mip level. Gloss values would be effectively quantized to the number of mip levels, but maybe it won't look too bad." ContentLicense="CC BY-SA 3.0" />
  <row Id="16960" PostHistoryTypeId="2" PostId="6113" RevisionGUID="1e3431f0-f806-4a1b-8cff-406c4d2d8ea0" CreationDate="2018-01-13T22:15:49.250" UserId="8027" Text="Suppose I want to perform translate in the following order:&#xD;&#xA;&#xD;&#xA;1. Scale by $S$&#xD;&#xA;2. Rotate by matrix $R_1$&#xD;&#xA;3. Rotate by matrix $R_2$&#xD;&#xA;4. Translate by $T%$.&#xD;&#xA;&#xD;&#xA;When I apply the matrix, should the overall transformation matrix be:&#xD;&#xA;&#xD;&#xA;$M = T \times R_1^{-1} \times R_2^{-1} \times S$&#xD;&#xA;&#xD;&#xA; or &#xD;&#xA;&#xD;&#xA;$M = T \times R_2^{-1} \times R_1^{-1} \times S$&#xD;&#xA;?&#xD;&#xA;&#xD;&#xA;I always thought the transformations should be applied in reverse, so it should be the second case. But I'm told that it's the first case instead. Is there a special need to reverse the order of rotation apart from taking the inverse too?&#xD;&#xA;&#xD;&#xA;By the way, why must I take the inverse matrix for rotation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16961" PostHistoryTypeId="1" PostId="6113" RevisionGUID="1e3431f0-f806-4a1b-8cff-406c4d2d8ea0" CreationDate="2018-01-13T22:15:49.250" UserId="8027" Text="Is this the correct application of model transformation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16962" PostHistoryTypeId="3" PostId="6113" RevisionGUID="1e3431f0-f806-4a1b-8cff-406c4d2d8ea0" CreationDate="2018-01-13T22:15:49.250" UserId="8027" Text="|raytracing|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16963" PostHistoryTypeId="5" PostId="6085" RevisionGUID="53f83684-9170-419c-b00a-97561b6b2bff" CreationDate="2018-01-13T23:31:41.550" UserId="6" Comment="Minor formatting and grammar tweaks." Text="I'm currently making a small 3D renderer and I got stuck in Phong shading.&#xD;&#xA;&#xD;&#xA;My questions are: &#xD;&#xA;&#xD;&#xA;1. Into which space should the light coordinate be converted? &#xD;&#xA;&#xD;&#xA; I have my light position at world coordinates (0,0,0). I'd like to calculate &quot;phong shading&quot; after converting all the vertices to screen space (viewport). &#xD;&#xA;So Should I convert the light position to screen space too?    &#xD;&#xA;&#xD;&#xA;2. Is there a faster way to calculate Phong shading with normal interpolation if the camera's position equals the light's position?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16964" PostHistoryTypeId="24" PostId="6085" RevisionGUID="53f83684-9170-419c-b00a-97561b6b2bff" CreationDate="2018-01-13T23:31:41.550" Comment="Proposed by 6 approved by 7999 edit id of 296" ContentLicense="CC BY-SA 3.0" />
  <row Id="16970" PostHistoryTypeId="2" PostId="6115" RevisionGUID="5961ba2e-9c1e-4ec6-bb8e-fc3c660dd999" CreationDate="2018-01-14T20:47:16.220" UserId="7238" Text="Say I have a model made up of vertices, each with `position`, `normal`, `tangent`, and `texcoord` attributes, where triangles are specified by index triples.&#xD;&#xA;&#xD;&#xA;If we just focus on the vertex attributes, I'm aware of two broad strategies: the structure of arrays, and the array of structures. I've also heard that the array of structures is preferred because it increases the memory locality (and therefore cache locality) of the attributes for a given vertex.&#xD;&#xA;&#xD;&#xA;Is it really the case that this improves performance? The main way I could think that this would come about is by vertex indices that require the rasterizer to acquire vertex data that has long since been evicted from cache. If vertex data access is random like this, then keeping all the attributes for a vertex on the same cache line would certainly make things faster, but is this not an issue that could be mostly mitigated by optimizing the order of triangle specification?&#xD;&#xA;&#xD;&#xA;Furthermore, it's my understanding that modern GPUs may be better at unpacking long vectors of the same type, than vectors of structures of many types. Would it then be possible for a structure-of-arrays layout to consistently outperform an array-of-structures layout of the same vertex data, if the index order is optimized?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16971" PostHistoryTypeId="1" PostId="6115" RevisionGUID="5961ba2e-9c1e-4ec6-bb8e-fc3c660dd999" CreationDate="2018-01-14T20:47:16.220" UserId="7238" Text="The most performant way to organize vertex data on modern GPUs" ContentLicense="CC BY-SA 3.0" />
  <row Id="16972" PostHistoryTypeId="3" PostId="6115" RevisionGUID="5961ba2e-9c1e-4ec6-bb8e-fc3c660dd999" CreationDate="2018-01-14T20:47:16.220" UserId="7238" Text="|gpu|performance|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16974" PostHistoryTypeId="2" PostId="6116" RevisionGUID="6e59290f-c7b5-4f8c-b477-d2b111a64dcc" CreationDate="2018-01-15T16:47:05.340" UserId="8032" Text="EDIT: I indented code 4 spaces, but it's not formatted correctly!!!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a source texture (480x480) that was created with mipmapped set to true (error checking removed to simply this post), and a dest texture (100x100):&#xD;&#xA;    // source texture&#xD;&#xA;    var textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.r8Unorm, width: Int(480), height: Int(480), mipmapped: true)&#xD;&#xA;    textureDescriptor.usage = .unknown // .shaderWrite .shaderRead&#xD;&#xA;    srcTexture = metalDevice!.makeTexture(descriptor: textureDescriptor)&#xD;&#xA;    // Dest texture&#xD;&#xA;    textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.r8Unorm, width: Int(100), height: Int(100), mipmapped: false)&#xD;&#xA;    textureDescriptor.usage = .shaderWrite&#xD;&#xA;    destTexture = metalDevice!.makeTexture(descriptor: textureDescriptor)&#xD;&#xA;&#xD;&#xA;The sampler is defined:&#xD;&#xA;    let samplerDescriptor = MTLSamplerDescriptor()&#xD;&#xA;    samplerDescriptor.magFilter = .linear&#xD;&#xA;    samplerDescriptor.minFilter = .linear&#xD;&#xA;    samplerDescriptor.rAddressMode = .clampToZero&#xD;&#xA;    samplerDescriptor.sAddressMode = .clampToZero&#xD;&#xA;    samplerDescriptor.tAddressMode = .clampToZero&#xD;&#xA;    samplerDescriptor.normalizedCoordinates = true&#xD;&#xA;    textureSampler = metalDevice!.makeSamplerState(descriptor: samplerDescriptor)&#xD;&#xA;&#xD;&#xA;I populated the src texture with an image.&#xD;&#xA;&#xD;&#xA;Then generated the mipmaps:&#xD;&#xA;    let blitEncoder = metalCommandBuffer!.makeBlitCommandEncoder()&#xD;&#xA;    blitEncoder!.pushDebugGroup(&quot;Dispatch mipmap kernel&quot;)&#xD;&#xA;    blitEncoder!.generateMipmaps(for: srcTexture!);&#xD;&#xA;    blitEncoder!.popDebugGroup()&#xD;&#xA;    blitEncoder!.endEncoding()&#xD;&#xA;&#xD;&#xA;And in the same command buffer, ran the resize kernel:&#xD;&#xA;    let computeEncoder = metalCommandBuffer!.makeComputeCommandEncoder()&#xD;&#xA;    computeEncoder!.pushDebugGroup(&quot;Dispatch resize image kernel&quot;)&#xD;&#xA;    computeEncoder!.setComputePipelineState(resizeImagePipeline)&#xD;&#xA;    computeEncoder!.setTexture(srcTexture, index: 0)&#xD;&#xA;    computeEncoder!.setTexture(destTexture, index: 1)&#xD;&#xA;    computeEncoder!.setSamplerState(textureSampler, index: 0)&#xD;&#xA;    let threadGroupCount = MTLSizeMake(20, 10, 1)&#xD;&#xA;    let threadGroups = MTLSizeMake(destTexture!.width / threadGroupCount.width, destTexture!.height / threadGroupCount.height, 1)&#xD;&#xA;    computeEncoder!.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount)&#xD;&#xA;    computeEncoder!.popDebugGroup()&#xD;&#xA;    computeEncoder!.endEncoding()&#xD;&#xA;&#xD;&#xA;The compute kernel is (remember, this is not a fragment shader which would automatically know how to set the mipmap level of detail):&#xD;&#xA;    kernel void resizeImage(&#xD;&#xA;    texture2d&lt;half, access::sample&gt; sourceTexture [[texture(0)]],&#xD;&#xA;    texture2d&lt;half, access::write&gt; destTexture [[texture(1)]],&#xD;&#xA;    sampler samp [[sampler(0)]],&#xD;&#xA;    uint2 gridPosition [[thread_position_in_grid]])&#xD;&#xA;    {&#xD;&#xA;    float2 srcSize = float2(sourceTexture.get_width(0),&#xD;&#xA;    sourceTexture.get_height(0));&#xD;&#xA;    float2 destSize = float2(destTexture.get_width(0),&#xD;&#xA;    destTexture.get_height(0));&#xD;&#xA;    float2 sourceCoords = float2(gridPosition) / destSize;&#xD;&#xA;    /*+ The following attempts all produced a pixelated image&#xD;&#xA;    (no edges smoothed out like a fragment shader would)&#xD;&#xA;    half4 color = sourceTexture.sample(samp, sourceCoords);&#xD;&#xA;    float lod = srcSize.x / destSize.x;&#xD;&#xA;    float lod = 0.0;&#xD;&#xA;    float lod = 1.0;&#xD;&#xA;    float lod = 2.0;&#xD;&#xA;    float lod = 3.0;&#xD;&#xA;    float lod = 4.0;&#xD;&#xA;    float lod = 4.5;&#xD;&#xA;    float lod = 5.0;&#xD;&#xA;    float lod = 5.5;&#xD;&#xA;    */&#xD;&#xA;    float lod = 6.0;&#xD;&#xA;    half4 color = sourceTexture.sample(samp, sourceCoords, level(lod));&#xD;&#xA;    destTexture.write(color, gridPosition);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;No matter what lod is set to, I get the same exact pixelated results. Why won't the mipmapping work?&#xD;&#xA;Thanks for any help you can provide." ContentLicense="CC BY-SA 3.0" />
  <row Id="16975" PostHistoryTypeId="1" PostId="6116" RevisionGUID="6e59290f-c7b5-4f8c-b477-d2b111a64dcc" CreationDate="2018-01-15T16:47:05.340" UserId="8032" Text="Mipmap sampler in Metal compute kernel (not vertex or fragment shader)" ContentLicense="CC BY-SA 3.0" />
  <row Id="16976" PostHistoryTypeId="3" PostId="6116" RevisionGUID="6e59290f-c7b5-4f8c-b477-d2b111a64dcc" CreationDate="2018-01-15T16:47:05.340" UserId="8032" Text="|compute-shader|mipmap|metal|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16977" PostHistoryTypeId="2" PostId="6117" RevisionGUID="cdf11d17-bbb4-43b6-8b52-74300600f19c" CreationDate="2018-01-15T16:47:34.507" UserId="7000" Text="When using an array texture I can call:&#xD;&#xA;&#xD;&#xA;	glTextureStorage3D(m_texture_array, 1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, width, height, m_num_billboards);&#xD;&#xA;    for (int i{}; i &lt; 4; ==i) {&#xD;&#xA;        glTextureSubImage3D(m_texture_array, 0, 0, 0, i, width, height, 1, GL_RGB, GL_UNSIGNED_BYTE, data);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Which results in a compressed image. So when do I need to use `glCompressedTextureSubImage3D` ?&#xD;&#xA;&#xD;&#xA;Furthermore, [the docs][1] say:&#xD;&#xA;&gt; internalformat must be a known compressed image format (such as GL_RGTC) or an extension-specified compressed-texture format&#xD;&#xA;&#xD;&#xA;Why can't it be a generic format?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage3D.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="16978" PostHistoryTypeId="1" PostId="6117" RevisionGUID="cdf11d17-bbb4-43b6-8b52-74300600f19c" CreationDate="2018-01-15T16:47:34.507" UserId="7000" Text="glCompressedTextureSubImage3D Usage" ContentLicense="CC BY-SA 3.0" />
  <row Id="16979" PostHistoryTypeId="3" PostId="6117" RevisionGUID="cdf11d17-bbb4-43b6-8b52-74300600f19c" CreationDate="2018-01-15T16:47:34.507" UserId="7000" Text="|opengl|texture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16980" PostHistoryTypeId="5" PostId="6116" RevisionGUID="fc7722c0-9ca8-4467-8964-4b5af3e67396" CreationDate="2018-01-15T16:57:33.287" UserId="8032" Comment="deleted 53 characters in body" Text="I have a source texture (480x480) that was created with mipmapped set to true (error checking removed to simply this post), and a dest texture (100x100):&#xD;&#xA;&#xD;&#xA;    // source texture&#xD;&#xA;    var textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.r8Unorm, width: Int(480), height: Int(480), mipmapped: true)&#xD;&#xA;    textureDescriptor.usage = .unknown // .shaderWrite .shaderRead&#xD;&#xA;    srcTexture = metalDevice!.makeTexture(descriptor: textureDescriptor)&#xD;&#xA;    // Dest texture&#xD;&#xA;    textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: MTLPixelFormat.r8Unorm, width: Int(100), height: Int(100), mipmapped: false)&#xD;&#xA;    textureDescriptor.usage = .shaderWrite&#xD;&#xA;    destTexture = metalDevice!.makeTexture(descriptor: textureDescriptor)&#xD;&#xA;&#xD;&#xA;The sampler is defined:&#xD;&#xA;&#xD;&#xA;    let samplerDescriptor = MTLSamplerDescriptor()&#xD;&#xA;    samplerDescriptor.magFilter = .linear&#xD;&#xA;    samplerDescriptor.minFilter = .linear&#xD;&#xA;    samplerDescriptor.rAddressMode = .clampToZero&#xD;&#xA;    samplerDescriptor.sAddressMode = .clampToZero&#xD;&#xA;    samplerDescriptor.tAddressMode = .clampToZero&#xD;&#xA;    samplerDescriptor.normalizedCoordinates = true&#xD;&#xA;    textureSampler = metalDevice!.makeSamplerState(descriptor: samplerDescriptor)&#xD;&#xA;&#xD;&#xA;I populated the src texture with an image.&#xD;&#xA;&#xD;&#xA;Then generated the mipmaps:&#xD;&#xA;&#xD;&#xA;    let blitEncoder = metalCommandBuffer!.makeBlitCommandEncoder()&#xD;&#xA;    blitEncoder!.pushDebugGroup(&quot;Dispatch mipmap kernel&quot;)&#xD;&#xA;    blitEncoder!.generateMipmaps(for: srcTexture!);&#xD;&#xA;    blitEncoder!.popDebugGroup()&#xD;&#xA;    blitEncoder!.endEncoding()&#xD;&#xA;&#xD;&#xA;And in the same command buffer, ran the resize kernel:&#xD;&#xA;&#xD;&#xA;    let computeEncoder = metalCommandBuffer!.makeComputeCommandEncoder()&#xD;&#xA;    computeEncoder!.pushDebugGroup(&quot;Dispatch resize image kernel&quot;)&#xD;&#xA;    computeEncoder!.setComputePipelineState(resizeImagePipeline)&#xD;&#xA;    computeEncoder!.setTexture(srcTexture, index: 0)&#xD;&#xA;    computeEncoder!.setTexture(destTexture, index: 1)&#xD;&#xA;    computeEncoder!.setSamplerState(textureSampler, index: 0)&#xD;&#xA;    let threadGroupCount = MTLSizeMake(20, 10, 1)&#xD;&#xA;    let threadGroups = MTLSizeMake(destTexture!.width / threadGroupCount.width, destTexture!.height / threadGroupCount.height, 1)&#xD;&#xA;    computeEncoder!.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount)&#xD;&#xA;    computeEncoder!.popDebugGroup()&#xD;&#xA;    computeEncoder!.endEncoding()&#xD;&#xA;&#xD;&#xA;The compute kernel is (remember, this is not a fragment shader which would automatically know how to set the mipmap level of detail):&#xD;&#xA;&#xD;&#xA;    kernel void resizeImage(&#xD;&#xA;    texture2d&lt;half, access::sample&gt; sourceTexture [[texture(0)]],&#xD;&#xA;    texture2d&lt;half, access::write&gt; destTexture [[texture(1)]],&#xD;&#xA;    sampler samp [[sampler(0)]],&#xD;&#xA;    uint2 gridPosition [[thread_position_in_grid]])&#xD;&#xA;    {&#xD;&#xA;    float2 srcSize = float2(sourceTexture.get_width(0),&#xD;&#xA;    sourceTexture.get_height(0));&#xD;&#xA;    float2 destSize = float2(destTexture.get_width(0),&#xD;&#xA;    destTexture.get_height(0));&#xD;&#xA;    float2 sourceCoords = float2(gridPosition) / destSize;&#xD;&#xA;    /*+ The following attempts all produced a pixelated image&#xD;&#xA;    (no edges smoothed out like a fragment shader would)&#xD;&#xA;    half4 color = sourceTexture.sample(samp, sourceCoords);&#xD;&#xA;    float lod = srcSize.x / destSize.x;&#xD;&#xA;    float lod = 0.0;&#xD;&#xA;    float lod = 1.0;&#xD;&#xA;    float lod = 2.0;&#xD;&#xA;    float lod = 3.0;&#xD;&#xA;    float lod = 4.0;&#xD;&#xA;    float lod = 4.5;&#xD;&#xA;    float lod = 5.0;&#xD;&#xA;    float lod = 5.5;&#xD;&#xA;    */&#xD;&#xA;    float lod = 6.0;&#xD;&#xA;    half4 color = sourceTexture.sample(samp, sourceCoords, level(lod));&#xD;&#xA;    destTexture.write(color, gridPosition);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;No matter what lod is set to, I get the same exact pixelated results. Why won't the mipmapping work?&#xD;&#xA;Thanks for any help you can provide.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16981" PostHistoryTypeId="2" PostId="6118" RevisionGUID="fb6a2683-7e40-4da8-bb39-79c39964f156" CreationDate="2018-01-15T18:02:36.753" UserId="2654" Text="OK, when you call the regular `SubImage` functions, you are passing pixel data. You are [provoking a pixel unpack operation][1], where the implementation will read the pixels from your data in the format specified and convert them to the internal format of the image.&#xD;&#xA;&#xD;&#xA;However, if already have compressed data, you don't *want* that conversion. You just want to pass the compressed data to the GL, and have it use it directly. That's what the `Compressed` functions are for.&#xD;&#xA;&#xD;&#xA;If you want to compress uncompressed data, you use the non-`Compressed` functions. But you really, *really*, shouldn't. Indeed, with ASTC, you *can't* compress the data online. And even for other formats, the quality of the result will be rather sketchy.&#xD;&#xA;&#xD;&#xA;Do you really want to rely on the quality of a compression algorithm written to be fast rather than *good*?&#xD;&#xA;&#xD;&#xA;The [`format`][2] and [`type`][3] transfer parameters describe a single pixel's worth of data, and compressed formats don't generally store data in units of &quot;pixels&quot;. Compressed formats usually use blocks of some size. Regular pixel transfers expect a 1:1 correspondence between a pixel in your data and a pixel in the GL-owned image. That simply isn't the case when dealing with compressed data.&#xD;&#xA;&#xD;&#xA;So you need a new function, which just takes a block of bits of a known size, whose format is defined by the image's format, and jams it into the image.&#xD;&#xA;&#xD;&#xA;The reason why you can't use a generic compressed format with the `Compressed` transfer functions should be obvious by now. These functions are for providing compressed data in a specific format; *by definition*, the generic formats are implementation defined. So there's no way you could possibly know what data to provide for generic compressed transfers.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Pixel_Transfer&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Pixel_Transfer_Format&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Pixel_Transfer_Type" ContentLicense="CC BY-SA 3.0" />
  <row Id="16982" PostHistoryTypeId="2" PostId="6119" RevisionGUID="745158bc-6fcd-4469-a3ce-d36d0a8ed72b" CreationDate="2018-01-15T19:45:02.840" UserId="8033" Text="Whenever you make a part in inventor, the software calculates de properties of the whole body given a constant density. Then, automatically,  it shows the inertial tensor. As you can recall from math, the inertia equation is I_x=ρ∫(y^2+z^2)dV&#xD;&#xA;for the x axis. So, clearing rho, how can I get the right hand of the equation that is been solve in the underlying algorithm without doing any hand calculations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16983" PostHistoryTypeId="1" PostId="6119" RevisionGUID="745158bc-6fcd-4469-a3ce-d36d0a8ed72b" CreationDate="2018-01-15T19:45:02.840" UserId="8033" Text="How to obtain a parametric equation out of a part designed in Autodesk Inventor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16984" PostHistoryTypeId="3" PostId="6119" RevisionGUID="745158bc-6fcd-4469-a3ce-d36d0a8ed72b" CreationDate="2018-01-15T19:45:02.840" UserId="8033" Text="|algorithm|mathematics|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16985" PostHistoryTypeId="2" PostId="6120" RevisionGUID="1d15f7f5-26a4-4d02-b2b1-eb78c5173bc9" CreationDate="2018-01-15T20:19:20.303" UserId="6838" Text="I have two somewhat related questions to ask:&#xD;&#xA;&lt;br&gt;1. What is the most accurate way to get the colors of a spectrum, without having to go deep into physics and simulating the universe? ;) Right now, I'm using [these][1] color matching functions, and simply reading off the XYZ color of a particular wavelength and converting it to sRGB. I know sRGB can't represent most spectral colors, but let's ignore that.&#xD;&#xA;&lt;br&gt;2. If I'm trying to make a color, say white, out of the spectral colors, how should I combine them? Should I add the color in XYZ space, or in RGB space, or is neither sufficient?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://cvrl.ioo.ucl.ac.uk/cmfs.htm &quot;Color matching functions&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16986" PostHistoryTypeId="1" PostId="6120" RevisionGUID="1d15f7f5-26a4-4d02-b2b1-eb78c5173bc9" CreationDate="2018-01-15T20:19:20.303" UserId="6838" Text="Generating and Combining Spectral Colors" ContentLicense="CC BY-SA 3.0" />
  <row Id="16987" PostHistoryTypeId="3" PostId="6120" RevisionGUID="1d15f7f5-26a4-4d02-b2b1-eb78c5173bc9" CreationDate="2018-01-15T20:19:20.303" UserId="6838" Text="|color|color-science|spectral|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16988" PostHistoryTypeId="5" PostId="6120" RevisionGUID="5244aa83-7243-4be1-8786-c279f8301804" CreationDate="2018-01-15T22:35:26.880" UserId="6838" Comment="Clarified question" Text="I have two somewhat related questions to ask:&#xD;&#xA;&lt;br&gt;1. What is the most accurate way to get the colors of a spectrum, without having to go deep into physics and simulating the universe? ;) Right now, I'm using [these][1] color matching functions, and simply reading off the XYZ color of a particular wavelength and converting it to sRGB. I know sRGB can't represent most spectral colors, but let's ignore that.&#xD;&#xA;&lt;br&gt;2. If I'm trying to make a color, say white, out of the spectral colors, how should I combine them? Should I add the color in XYZ space, or in RGB space, or is neither sufficient?&#xD;&#xA;&#xD;&#xA;My plan is to experiment with spectral rendering, so it should be accurate enough to avoid biased renders. It'll most likely be on the GPU, and I need accuracy over speed.&#xD;&#xA;&#xD;&#xA;  [1]: http://cvrl.ioo.ucl.ac.uk/cmfs.htm &quot;Color matching functions&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="16989" PostHistoryTypeId="2" PostId="6121" RevisionGUID="4d726a16-ec7e-407d-84b9-b40c1f1fbf56" CreationDate="2018-01-15T23:48:15.377" UserId="7868" Text="Multiple Importance Sampling (MIS) is a technique used by Veach's VCM technique to balance responses of different surfaces to different types of importance sampling for direct illumination. My understanding is that specular surfaces are best lit without sampling the light at all; instead, you pull a direction from the BRDF and hope that it hits the light source. Diffuse surfaces &quot;spread&quot; light more broadly over their domain, so firing rays towards random points on the area covered by the light produces good results without the wastage produced by sampling over the BRDF.&#xD;&#xA;&#xD;&#xA;I'm still unsure about a few things, though:&#xD;&#xA;&#xD;&#xA;- Veach's demonstration images show flat specular surfaces eventually converging with light sampling; how is this possible? All rays fired towards random points on the light will reach the light (assuming no obstructions), so shouldn't the specular surfaces wash out under all the assumed illumination?&#xD;&#xA;- &quot;**Multiple** Importance Sampling&quot; implies that tracing gather rays towards the light is an importance-sampled technique (which makes sense, it's very difficult to have invalid rays if all rays approximate the direction of light relative to the surface); does this mean I need to be dividing my direct gathers by a PDF? Given that the &quot;direction&quot; of the light could be anywhere on the unit sphere surrounding the lit point, should the PDF be $4\pi$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16990" PostHistoryTypeId="1" PostId="6121" RevisionGUID="4d726a16-ec7e-407d-84b9-b40c1f1fbf56" CreationDate="2018-01-15T23:48:15.377" UserId="7868" Text="Direct illumination, specular surfaces, and MIS" ContentLicense="CC BY-SA 3.0" />
  <row Id="16991" PostHistoryTypeId="3" PostId="6121" RevisionGUID="4d726a16-ec7e-407d-84b9-b40c1f1fbf56" CreationDate="2018-01-15T23:48:15.377" UserId="7868" Text="|specular|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16996" PostHistoryTypeId="2" PostId="6123" RevisionGUID="a4e918e6-a8d5-4bad-b1ae-f0fd20ba20c1" CreationDate="2018-01-16T06:55:49.813" UserId="8035" Text="I have multiple 3D polygons meshes (sketchup format) in the world, for any specified point (x,y,z), how do I get the direct closest polygon face below this point? and how to get the height for the projected intersection point on the face?&#xD;&#xA;&#xD;&#xA;Can someone point me the direction how to get started?" ContentLicense="CC BY-SA 3.0" />
  <row Id="16997" PostHistoryTypeId="1" PostId="6123" RevisionGUID="a4e918e6-a8d5-4bad-b1ae-f0fd20ba20c1" CreationDate="2018-01-16T06:55:49.813" UserId="8035" Text="How to get the nearest polygon face and height of intersection point" ContentLicense="CC BY-SA 3.0" />
  <row Id="16998" PostHistoryTypeId="3" PostId="6123" RevisionGUID="a4e918e6-a8d5-4bad-b1ae-f0fd20ba20c1" CreationDate="2018-01-16T06:55:49.813" UserId="8035" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="16999" PostHistoryTypeId="2" PostId="6124" RevisionGUID="ee063952-48c9-49de-b23b-cc379aae14f3" CreationDate="2018-01-16T07:45:40.977" UserId="7008" Text="To get the height intersection once you have found the polygon, you can build a plane of the polygon and calculate the distance to the plane. For example you can displace the point along the planes normal and calculate the length of the normal for when the point is displaced into the plane. Implicit planes are neat for this, they are build with the normal of the plane (which is the normal of the polygon) and one constant $d$. $d$ can be calculated by arbitrary point on the plane (e.g. one of your polygon vertices). &#xD;&#xA;&#xD;&#xA;$d = -\vec{n} \cdot q$ and $\vec{n} + d = 0$ (where $\vec{n}$ is the normal and $q$ the point/vertex).&#xD;&#xA;&#xD;&#xA;The neat part is: if you calculate the dot product of your point you want the distance of, you have the signed distance toward the plane, i.e. if $p$ is your point and $l$ is the distance between the point and the plane, then&#xD;&#xA;&#xD;&#xA;$l = (\vec{n} + d) \cdot p$ (for this you assume the fourth coordinate of a point as $1$)&#xD;&#xA;&#xD;&#xA;Now that you have the distance to the plane, you need to check, weather the intersection of normal through point with plane also intersects the polygon. You could for example take the vectors $\vec{v}_i = v_i - p$ where $v_i$ are your polygons, and then take the dot product $\vec{n} \cdot \vec{v}$. If they all have the same sign, your intersection doesn't hit the polygon (assuming the polygon to be convex). &#xD;&#xA;&#xD;&#xA;Iff it doesn't hit the vertices you need the distance to the closest two vertices. Since you have already done the dot product test (with the sign) for all polygon vertices, you know that the shortest distance can't be to the edge between the two vertices, and thus it suffices to take the shortest of the two point-&gt;vertex distances.&#xD;&#xA;&#xD;&#xA;As to which polygon is closest, I'm not sure if there is a better trick, but I'd just transform the point into Model Space of the mesh and calculate the distance to any front facing face." ContentLicense="CC BY-SA 3.0" />
  <row Id="17001" PostHistoryTypeId="2" PostId="6125" RevisionGUID="f1a43a22-5b6d-458b-b142-7f0a2911c38e" CreationDate="2018-01-16T15:21:31.213" UserId="7008" Text="Your way of calculating XYZ functions is probably the most efficient way to go about calculating accurate colors from a spectrum. It is standard practice afaik, for examples the books Physically Based Rendering (3rd) and Real-Time Rendering (3rd) both use this method.&#xD;&#xA;&#xD;&#xA;You can add the colors in RGB space, but only if you convert from sRGB to linear RGB first. Otherwise you need to take into account, that sRGB sums will not lead to correct colors. The blogpost [Adventures with Gamma-Correct Rendering][1] by Naty Hoffman is a good read regarding this, topc:&#xD;&#xA;&#xD;&#xA;&gt; Computing shading in sRGB space is like doing math in a world where 1+1=3.&#xD;&#xA;&#xD;&#xA;This is the problem you have when adding colors in sRGB.&#xD;&#xA;&#xD;&#xA;As to whether $XYZ$ can be summed, I think so. If we look at the definition of the coordinates (for $S$ is the spectral function and $x, y, z$ are the CIE functions):&#xD;&#xA;&#xD;&#xA;$X = \frac{1}{\int_\lambda y(\lambda) d\lambda} \int_\lambda S(\lambda) x(\lambda) d\lambda$&#xD;&#xA;&#xD;&#xA;Now two $X$ coordinates $X_1, X_2$ would have the same definition, only the spectrals are different ($S_1, S_2$).&#xD;&#xA;&#xD;&#xA;Thus you have&#xD;&#xA;&#xD;&#xA;$X_1 + X_2 = \frac{1}{\int_\lambda y(\lambda) d\lambda} \int_\lambda S_1(\lambda) x(\lambda) d\lambda + \frac{1}{\int_\lambda y(\lambda) d\lambda} \int_\lambda S_2(\lambda) x(\lambda) d\lambda\\&#xD;&#xA;= \frac{1}{\int_\lambda y(\lambda) d\lambda} \left(\int_\lambda S_1(\lambda) x(\lambda) d\lambda + \int_\lambda S_2(\lambda) x(\lambda) d\lambda\right)\\&#xD;&#xA;= \frac{1}{\int_\lambda y(\lambda) d\lambda}\int_\lambda S_1(\lambda) x(\lambda) + S_2(\lambda) x(\lambda) d\lambda \\&#xD;&#xA;= \frac{1}{\int_\lambda y(\lambda) d\lambda}\int_\lambda (S_1(\lambda)  + S_2(\lambda)) x(\lambda) d\lambda\\&#xD;&#xA;=X$&#xD;&#xA;&#xD;&#xA;The same holds for other coordinates.&#xD;&#xA;&#xD;&#xA;Therefore, your best option is probably to sum your XYZ coordinates and convert them to sRGB space in the end.&#xD;&#xA;&#xD;&#xA;  [1]: http://renderwonk.com/blog/index.php/archive/adventures-with-gamma-correct-rendering/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17002" PostHistoryTypeId="2" PostId="6126" RevisionGUID="41d4748d-43e2-4068-9d9b-e5f6f2845de6" CreationDate="2018-01-16T16:24:40.533" UserId="5717" Text="Specular surfaces which use MIS are not perfectly specular like a mirror. They have a small amount of blur, otherwise there is indeed no point in sampling the light as all the samples will evaluate the BRDF as 0. In fact, you would only need to trace a single reflection ray.&#xD;&#xA;&#xD;&#xA;A small amount of blur means that a given camera ray will see a small area of the lightsource (assuming it hits where the specular highlight is visible). Thus, a small fraction of the light samples will get a BRDF which is not 0 so it will eventually converge. The less blur, the more samples it will take.&#xD;&#xA;&#xD;&#xA;You are correct that such a case will converge faster if you sample only the BRDF. Likewise, a very diffuse BRDF will usually converge faster if you sample only the light. But this is not true if your light is very large and your surface very close to it. Where MIS shines is that it handles those cases as well as the BRDFs which are neither very diffuse nor very specular.&#xD;&#xA;&#xD;&#xA;If you choose to ignore it, what you have to do is a simple integral. There are a few ways to go about it but if you start from MIS equations, just use 0 as the PDF of the BRDF since you're not generating those samples. And be prepared for some cases which won't converge well." ContentLicense="CC BY-SA 3.0" />
  <row Id="17003" PostHistoryTypeId="50" PostId="5996" RevisionGUID="33c4cf80-0a7e-498a-afc0-b572419d235c" CreationDate="2018-01-16T22:07:02.337" UserId="-1" />
  <row Id="17004" PostHistoryTypeId="2" PostId="6127" RevisionGUID="5a79ff21-e9fb-422e-9f4b-491d601d4b4a" CreationDate="2018-01-17T00:10:14.130" UserId="8038" Text="I have some images that I know will be stored with either PVR or ETC compression. I would like to be able to convert these images into uncompressed RGB. However, because of binary size constraints, I would like to do so without adding a dedicated library for the conversion. &#xD;&#xA;&#xD;&#xA;Does there exist any ways to do this? I know functions like glCompressedTexImage2D will let me load the compressed image to GPU. However, I'm having issues reading the decoded version out.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="17005" PostHistoryTypeId="1" PostId="6127" RevisionGUID="5a79ff21-e9fb-422e-9f4b-491d601d4b4a" CreationDate="2018-01-17T00:10:14.130" UserId="8038" Text="Loading compressed image to GPU and reading back decompressed on CPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="17006" PostHistoryTypeId="3" PostId="6127" RevisionGUID="5a79ff21-e9fb-422e-9f4b-491d601d4b4a" CreationDate="2018-01-17T00:10:14.130" UserId="8038" Text="|opengl|opengl-es|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17007" PostHistoryTypeId="5" PostId="6127" RevisionGUID="690fd483-26b4-42b8-bfda-217ffd07c99e" CreationDate="2018-01-17T00:37:34.743" UserId="8038" Comment="added 62 characters in body" Text="I have some images that I know will be stored with either PVR or ETC compression. I would like to be able to convert these images into uncompressed RGB. However, because of binary size constraints, I would like to do so without adding a dedicated library for the conversion. &#xD;&#xA;&#xD;&#xA;Does there exist any ways to do this? I know functions like glCompressedTexImage2D will let me load the compressed image to GPU. However, I'm having issues reading the decoded version out. For extra context, I am trying to do this with OpenGL ES 2.0.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="17008" PostHistoryTypeId="2" PostId="6128" RevisionGUID="4c61fce8-68e8-43e8-8353-720d7a8a871d" CreationDate="2018-01-17T00:51:52.407" UserId="113" Text="Revisiting this question from awhile ago. It turns out this sort of histogram is created by iterating through every pixel value in both the normal image and gradient magnitude image plotting it in the 2d image. (x intensity, y gradient magnitude). The count/occurrences of the 2d histogram are represented by the intensity of the grayscale in figure b. So the brighter a pixel in figure b is, the more pixels with that (intensity, gradient magnitude).&#xD;&#xA;&#xD;&#xA;For volume rendering this is called a 2d transfer function which lets users filter out or assign lower opacities to pixels with large/small gradient magnitudes. This is especially helpful in real time volume rendering with lighting. Real time volume rendering typically uses a BSDF at every point along a ray march as an approximation (Assuming that light reaches every point in the volume). IE: Dot product of the incoming light direction with the gradient as the normal. Using the gradient as the normal means that homogeneous areas are not well represented as they have low gradient magnitudes. Small noise in these areas can easily cause the gradient and normal to flip." ContentLicense="CC BY-SA 3.0" />
  <row Id="17009" PostHistoryTypeId="6" PostId="6127" RevisionGUID="2dabc633-b2ab-4918-8bf9-ec1512660199" CreationDate="2018-01-17T06:06:05.530" UserId="2654" Comment="edited tags" Text="|opengl-es|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17010" PostHistoryTypeId="2" PostId="6129" RevisionGUID="9224b19a-1190-473c-8a2a-62c8a0276d57" CreationDate="2018-01-17T06:11:32.500" UserId="2654" Text="Desktop OpenGL requires implementations to convert pixel data between the internal format of the image and the format you specify in the pixel transfer command.&#xD;&#xA;&#xD;&#xA;OpenGL ES *does not*. Indeed, it is so serious about not allowing this that it actually changes the *meaning* of the parameters to functions like `glTexImage*d`. In ES, you cannot use sized internal formats (well, outside of texture storage calls). Instead, the internal format is kinda there. What really defines the internal format is the pixel format and type parameters.&#xD;&#xA;&#xD;&#xA;That is, when you tell OpenGL ES that the pixel data you're providing looks like X, it requires the implementation to create a texture whose real internal format exactly matches that. And if you're using `glTexSubImage*d` or `glGetTexImage`, you *must* provide pixel transfer parameters that match those you provided to the `glTexImage*d` call.&#xD;&#xA;&#xD;&#xA;So OpenGL ES doesn't allow any of that pixel conversion stuff." ContentLicense="CC BY-SA 3.0" />
  <row Id="17019" PostHistoryTypeId="5" PostId="6126" RevisionGUID="b3207f9f-2959-49fc-a651-62b0df6f1a50" CreationDate="2018-01-17T17:17:50.317" UserId="5717" Comment="attempt to explain why light only sampling is not always best" Text="Specular surfaces which use MIS are not perfectly specular like a mirror. They have a small amount of blur, otherwise there is indeed no point in sampling the light as all the samples will evaluate the BRDF as 0. In fact, you would only need to trace a single reflection ray.&#xD;&#xA;&#xD;&#xA;A small amount of blur means that a given camera ray will see a small area of the lightsource (assuming it hits where the specular highlight is visible). Thus, a small fraction of the light samples will get a BRDF which is not 0 so it will eventually converge. The less blur, the more samples it will take.&#xD;&#xA;&#xD;&#xA;You are correct that such a case will converge faster if you sample only the BRDF. Likewise, a very diffuse BRDF will usually converge faster if you sample only the light. But this is not true if your light is very large and your surface very close to it&lt;sup&gt;1&lt;/sup&gt;. Where MIS shines is that it handles those cases as well as the BRDFs which are neither very diffuse nor very specular.&#xD;&#xA;&#xD;&#xA;If you choose to ignore it, what you have to do is a simple integral. There are a few ways to go about it but if you start from MIS equations, just use 0 as the PDF of the BRDF since you're not generating those samples. And be prepared for some cases which won't converge well.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;1. The assumption is that the light samples all have a similar contribution to the final result. Even with very good sampling of the light, this must assume that the BRDF will be similar for all light samples. At least I don't know of any direct light sampling formula which takes the cosine term of the diffuse surface into account. Pushing this to the extreme, you can build an example where most of the light is behind the surface, so most of the light samples will contribute nothing at all to the final result. BRDF samples are obviously sent only on the front side of the surface so they might converge faster, even if only a small % of them hit the light." ContentLicense="CC BY-SA 3.0" />
  <row Id="17021" PostHistoryTypeId="34" PostId="6078" RevisionGUID="3af129d0-2df2-4ba6-a43b-d8baf52746f3" CreationDate="2018-01-17T21:17:44.790" UserId="-1" Comment="43" />
  <row Id="17025" PostHistoryTypeId="2" PostId="6134" RevisionGUID="4c2e088e-5f0e-478f-88aa-1ab971279615" CreationDate="2018-01-17T22:36:16.387" UserId="8038" Text="The commentary in this thread is correct. OpenGL ES does not have built in support for reading textures directly.&#xD;&#xA;&#xD;&#xA;Best option it seems, given stated constraints, is to draw the compressed texture to a quad then read it back out. (Same as suggested by &quot;Simon F&quot; in the question comment thread above.)&#xD;&#xA;&#xD;&#xA;As reference for people stumbling upon this with the same problem, [this answer to a different, but similar question](https://stackoverflow.com/a/11947751) gives steps for doing the above. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17026" PostHistoryTypeId="2" PostId="6135" RevisionGUID="1539321b-f25f-4363-869d-6d96cd9a7542" CreationDate="2018-01-18T03:54:16.817" UserId="8048" Text="I am trying to implement a path tracer, but I have some problem.The class &quot;Spectrum&quot; is color.I implemented a mirror material lick this :&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;                Spectrum MirrorBSDF::f(const Vector3D&amp; wo, const Vector3D&amp; wi) &#xD;&#xA;                {&#xD;&#xA;    		         return reflectance  * (1.0 / abs_cos_theta(wo));&#xD;&#xA;    	        }&#xD;&#xA;&#xD;&#xA;The reflectance   is a Spectrum variable.And now I want to add a material &quot;Glass&quot; that have reflect and refract.It meets the Fresnel theorem.Can someone teach me how to implement?The function &quot;f&quot; is used like this :           &#xD;&#xA;&#xD;&#xA;                Spectrum light_L = light-&gt;sample_L(hit_p, &amp;dir_to_light, &amp;dist_to_light, &amp;pdf);&#xD;&#xA;    			// convert direction into coordinate space of the surface, where&#xD;&#xA;    			// the surface normal is [0 0 1]&#xD;&#xA;    			Vector3D w_in = w2o * dir_to_light;&#xD;&#xA;                double cos_theta = std::max(0.0, w_in[2]);&#xD;&#xA;                Spectrum f = isect.bsdf-&gt;f(w_out, w_in);&#xD;&#xA;    			// TODO:&#xD;&#xA;    			// Construct a shadow ray and compute whether the intersected surface is&#xD;&#xA;    			// in shadow and accumulate reflected radiance&#xD;&#xA;    			Ray shadow_ray(hit_p + EPS_D * dir_to_light, dir_to_light, dist_to_light - (EPS_D * dir_to_light).norm(), 0);&#xD;&#xA;    			if (!bvh-&gt;intersect(shadow_ray))&#xD;&#xA;    			{&#xD;&#xA;    				L_out += (f * light_L * (cos_theta * scale / pdf));&#xD;&#xA;    			}&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17027" PostHistoryTypeId="1" PostId="6135" RevisionGUID="1539321b-f25f-4363-869d-6d96cd9a7542" CreationDate="2018-01-18T03:54:16.817" UserId="8048" Text="How can I implement this BSDF?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17028" PostHistoryTypeId="3" PostId="6135" RevisionGUID="1539321b-f25f-4363-869d-6d96cd9a7542" CreationDate="2018-01-18T03:54:16.817" UserId="8048" Text="|raytracing|brdf|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17029" PostHistoryTypeId="50" PostId="6012" RevisionGUID="3f61a4a9-a05e-4484-a1d7-ff377d6f293e" CreationDate="2018-01-18T12:24:46.963" UserId="-1" />
  <row Id="17030" PostHistoryTypeId="50" PostId="5311" RevisionGUID="5f9aff55-6b6c-4be4-ae85-54ab4b70080b" CreationDate="2018-01-18T17:29:56.807" UserId="-1" />
  <row Id="17031" PostHistoryTypeId="2" PostId="6136" RevisionGUID="765e6a8b-cbf8-45be-a80f-1b16613a0cdb" CreationDate="2018-01-18T20:07:34.193" UserId="7138" Text="Let's say I have a point on a potential cubic sphere inflated using this:&#xD;&#xA;&#xD;&#xA;        Vector3 v = new Vector3(x, y, z) * 2f / gridSize - Vector3.one;&#xD;&#xA;		float x2 = v.x * v.x;&#xD;&#xA;		float y2 = v.y * v.y;&#xD;&#xA;		float z2 = v.z * v.z;&#xD;&#xA;		Vector3 s;&#xD;&#xA;		s.x = v.x * Mathf.Sqrt(1f - y2 / 2f - z2 / 2f + y2 * z2 / 3f);&#xD;&#xA;		s.y = v.y * Mathf.Sqrt(1f - x2 / 2f - z2 / 2f + x2 * z2 / 3f);&#xD;&#xA;		s.z = v.z * Mathf.Sqrt(1f - x2 / 2f - y2 / 2f + x2 * y2 / 3f);&#xD;&#xA;		normals[i] = s;&#xD;&#xA;		vertices[i] = normals[i] * radius;&#xD;&#xA;from: http://catlikecoding.com/unity/tutorials/cube-sphere/&#xD;&#xA;&#xD;&#xA;After finding the cube face the point belong to, how do I find which spatial hash it belong to, ie which grid cells for any given arbitrary division?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17032" PostHistoryTypeId="1" PostId="6136" RevisionGUID="765e6a8b-cbf8-45be-a80f-1b16613a0cdb" CreationDate="2018-01-18T20:07:34.193" UserId="7138" Text="Hashing a point on cubic sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="17033" PostHistoryTypeId="3" PostId="6136" RevisionGUID="765e6a8b-cbf8-45be-a80f-1b16613a0cdb" CreationDate="2018-01-18T20:07:34.193" UserId="7138" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17034" PostHistoryTypeId="50" PostId="5892" RevisionGUID="057af163-de3a-44fd-803b-7348347ce6bd" CreationDate="2018-01-19T04:31:16.827" UserId="-1" />
  <row Id="17041" PostHistoryTypeId="5" PostId="6120" RevisionGUID="641c87a9-305d-4c32-a354-73aece20b00c" CreationDate="2018-01-20T19:51:57.803" UserId="6" Comment="Improved formatting." Text="I have two somewhat related questions to ask:&#xD;&#xA;&#xD;&#xA;1. What is the most accurate way to get the colors of a spectrum, without having to go deep into physics and simulating the universe? ;) Right now, I'm using [these][1] color matching functions, and simply reading off the XYZ color of a particular wavelength and converting it to sRGB. I know sRGB can't represent most spectral colors, but let's ignore that.&#xD;&#xA;2. If I'm trying to make a color, say white, out of the spectral colors, how should I combine them? Should I add the color in XYZ space, or in RGB space, or is neither sufficient?&#xD;&#xA;&#xD;&#xA;My plan is to experiment with spectral rendering, so it should be accurate enough to avoid biased renders. It'll most likely be on the GPU, and I need accuracy over speed.&#xD;&#xA;&#xD;&#xA;  [1]: http://cvrl.ioo.ucl.ac.uk/cmfs.htm &quot;Color matching functions&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17042" PostHistoryTypeId="24" PostId="6120" RevisionGUID="641c87a9-305d-4c32-a354-73aece20b00c" CreationDate="2018-01-20T19:51:57.803" Comment="Proposed by 6 approved by 6838 edit id of 297" ContentLicense="CC BY-SA 3.0" />
  <row Id="17043" PostHistoryTypeId="2" PostId="6137" RevisionGUID="12b650b6-70e3-415c-bc50-8c1c466623cc" CreationDate="2018-01-21T09:02:09.767" UserId="6806" Text="Supposing a behavior function $C(x_1, \ldots, x_n)$, then we have a scalar potential energy function  &#xD;&#xA;&#xD;&#xA;$E = \frac{k_s}{2}C\cdot C$ where $k_S$ is stiffness constant.&#xD;&#xA;&#xD;&#xA;Hence, the force is as follows $f_i = -\frac{\partial E}{\partial x_i} = -k_sC\frac{\partial C}{\partial x_i}$ &#xD;&#xA;&#xD;&#xA;I caught up so far, but couldn't understand when adding damping.&#xD;&#xA;&#xD;&#xA;The paper read $f_i = (-k_sC - k_d\dot{C})\frac{\partial C}{\partial x_i}$ , where $k_d$ is damping constant and $\dot{C}$ is derivative of $C$.&#xD;&#xA;&#xD;&#xA;How to derive the damping part?&#xD;&#xA;&#xD;&#xA;I know damping equation is $f_d = -k_dv$, &#xD;&#xA;&#xD;&#xA;In detail, supposing there are two end of points in a spirng, called $p_a, p_b$.&#xD;&#xA;&#xD;&#xA;then the damping force $f_d = -k_d\frac{\dot{l}\cdot l}{|l|}\frac{l}{|l|}$ in 3D sapce ($\dot{l}$ is $v_a - v_b$, $l = p_a - p_b$)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, I could not correspond this equation to the above damping part." ContentLicense="CC BY-SA 3.0" />
  <row Id="17044" PostHistoryTypeId="1" PostId="6137" RevisionGUID="12b650b6-70e3-415c-bc50-8c1c466623cc" CreationDate="2018-01-21T09:02:09.767" UserId="6806" Text="Spring damping in Energy Function" ContentLicense="CC BY-SA 3.0" />
  <row Id="17045" PostHistoryTypeId="3" PostId="6137" RevisionGUID="12b650b6-70e3-415c-bc50-8c1c466623cc" CreationDate="2018-01-21T09:02:09.767" UserId="6806" Text="|physics|simulation|particles|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17051" PostHistoryTypeId="2" PostId="6138" RevisionGUID="873778eb-0a91-4470-92ba-e7ba0be719f2" CreationDate="2018-01-21T13:45:00.533" UserId="8043" Text="I am trying and learning to develop low level graphic API.&#xD;&#xA;&#xD;&#xA; - I want to know, how do modern graphic API vendors  manage to communicate with Graphic card Driver(to tackle GPU) so efficiently and optimized manner? &#xD;&#xA; - Which technologies should I understand other than C/C++ ans Assembly?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17052" PostHistoryTypeId="1" PostId="6138" RevisionGUID="873778eb-0a91-4470-92ba-e7ba0be719f2" CreationDate="2018-01-21T13:45:00.533" UserId="8043" Text="What mechanisms are being used by Directx12 and Vulkan APIs in order to communicate with Graphic Card Driver internally?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17053" PostHistoryTypeId="3" PostId="6138" RevisionGUID="873778eb-0a91-4470-92ba-e7ba0be719f2" CreationDate="2018-01-21T13:45:00.533" UserId="8043" Text="|opengl|gpu|directx12|gpgpu|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17054" PostHistoryTypeId="5" PostId="6138" RevisionGUID="dd555d00-3096-49ee-aa63-e1db6796e65c" CreationDate="2018-01-21T13:53:02.273" UserId="6" Comment="Improved spelling and tags." Text="I am trying and learning to develop a low level graphics API.&#xD;&#xA;&#xD;&#xA; - I want to know, how do modern graphics APIs manage to communicate with graphic card drivers (to tackle GPU) so efficiently and in an optimized manner? &#xD;&#xA; - Which technologies should I understand other than C/C++ and Assembly?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17055" PostHistoryTypeId="4" PostId="6138" RevisionGUID="dd555d00-3096-49ee-aa63-e1db6796e65c" CreationDate="2018-01-21T13:53:02.273" UserId="6" Comment="Improved spelling and tags." Text="What mechanisms are being used by Directx12 and Vulkan APIs in order to communicate with graphic card drivers internally?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17056" PostHistoryTypeId="6" PostId="6138" RevisionGUID="dd555d00-3096-49ee-aa63-e1db6796e65c" CreationDate="2018-01-21T13:53:02.273" UserId="6" Comment="Improved spelling and tags." Text="|opengl|gpu|directx12|vulkan|driver|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17057" PostHistoryTypeId="24" PostId="6138" RevisionGUID="dd555d00-3096-49ee-aa63-e1db6796e65c" CreationDate="2018-01-21T13:53:02.273" Comment="Proposed by 6 approved by 8043 edit id of 300" ContentLicense="CC BY-SA 3.0" />
  <row Id="17058" PostHistoryTypeId="2" PostId="6139" RevisionGUID="c5325ece-7f57-4438-8fda-95ec99d7dc44" CreationDate="2018-01-21T15:24:33.440" UserId="3041" Text="I'm finding myself increasingly interested in rendering techniques utilizing multisampling for anti-aliasing (obviously), out-of-order transparency, volumes etc.&#xD;&#xA;&#xD;&#xA;Searching the web for performance numbers of MSAA in the range only gets me to gamer verdicts for this and that game, and even then MSAA is only used for AA, and being compared to screen based post process AA which can hardly be used for anything else than AA.&#xD;&#xA;&#xD;&#xA;Is there any rule of thumb (other than memory consumption) of how much it costs having x2, x4, x8, x16 MSAA? Linear? Logarithmic?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17059" PostHistoryTypeId="1" PostId="6139" RevisionGUID="c5325ece-7f57-4438-8fda-95ec99d7dc44" CreationDate="2018-01-21T15:24:33.440" UserId="3041" Text="How does MSAA performance scale?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17060" PostHistoryTypeId="3" PostId="6139" RevisionGUID="c5325ece-7f57-4438-8fda-95ec99d7dc44" CreationDate="2018-01-21T15:24:33.440" UserId="3041" Text="|performance|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17061" PostHistoryTypeId="2" PostId="6140" RevisionGUID="ba38a71a-6531-4d10-8f25-23751c5d193b" CreationDate="2018-01-21T17:34:00.967" UserId="2041" Text="It's very different between the Khronos standards (including Vulkan) and DirectX.&#xD;&#xA;&#xD;&#xA;In DirectX, Microsoft implements the API, but they publish to GPU vendors a HAL API. There's actually two HALs: one that runs in kernel-mode, to communicate with the card directly; and one that runs in user-space, to do other tasks (like manage memory, set up data structures, and compile shaders).&#xD;&#xA;&#xD;&#xA;In Vulkan, Khronos only publishes the specification and a test suite. It's up to each GPU vendor to ship an implementation of the library. The application's interface to the driver is a normal C API, like any other library. You'll get confused if you try to think of an &quot;API part&quot; communicating with a &quot;graphics card driver&quot;: the driver *is* the API implementation.&#xD;&#xA;&#xD;&#xA;This is why it's very hard for third-parties to make open-source OpenGL (or Vulkan) implementations: you need to know all the details of the GPU hardware to do it. These graphics APIs are defined by industry groups consisting of the same people who design the hardware (at a high level), and deep understanding of the GPU architecture is what you need to design an efficient graphics API." ContentLicense="CC BY-SA 3.0" />
  <row Id="17062" PostHistoryTypeId="5" PostId="6119" RevisionGUID="3d4d45c9-b4ae-4e68-9c31-48a67f4e57b4" CreationDate="2018-01-21T19:03:59.053" UserId="6" Comment="Improved formatting." Text="Whenever you make a part in inventor, the software calculates de properties of the whole body given a constant density. Then, automatically,  it shows the inertial tensor. As you can recall from math, the inertia equation is $I_x= \rho\int(y^2+z^2)dV$&#xD;&#xA;for the x axis. So, clearing rho, how can I get the right hand of the equation that is been solved in the underlying algorithm without doing any hand calculations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17063" PostHistoryTypeId="24" PostId="6119" RevisionGUID="3d4d45c9-b4ae-4e68-9c31-48a67f4e57b4" CreationDate="2018-01-21T19:03:59.053" Comment="Proposed by 6 approved by 8033 edit id of 299" ContentLicense="CC BY-SA 3.0" />
  <row Id="17064" PostHistoryTypeId="5" PostId="6135" RevisionGUID="453fa0b8-ef36-438d-a032-2c708ec30145" CreationDate="2018-01-21T20:52:38.390" UserId="6" Comment="Improved formatting." Text="I am trying to implement a path tracer, but I have some problem. The class `Spectrum` is color. I implemented a mirror material like this:&#xD;&#xA;&#xD;&#xA;    Spectrum MirrorBSDF::f(const Vector3D&amp; wo, const Vector3D&amp; wi) &#xD;&#xA;    {&#xD;&#xA;        return reflectance * (1.0 / abs_cos_theta(wo));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The reflectance is a Spectrum variable. And now I want to add a material &quot;Glass&quot; that can reflect and refract. It meets the Fresnel theorem. Can someone teach me how to implement this? The function `f` is used like this:           &#xD;&#xA;&#xD;&#xA;    Spectrum light_L = light-&gt;sample_L(hit_p, &amp;dir_to_light, &amp;dist_to_light, &amp;pdf);&#xD;&#xA;&#xD;&#xA;    // convert direction into coordinate space of the surface, where surface normal is [0 0 1]&#xD;&#xA;    Vector3D w_in = w2o * dir_to_light;&#xD;&#xA;    double cos_theta = std::max(0.0, w_in[2]);&#xD;&#xA;    Spectrum f = isect.bsdf-&gt;f(w_out, w_in);&#xD;&#xA;&#xD;&#xA;    // TODO: Construct a shadow ray and compute whether the intersected surface is&#xD;&#xA;    // in shadow and accumulate reflected radiance&#xD;&#xA;    Ray shadow_ray(hit_p + EPS_D * dir_to_light, dir_to_light, &#xD;&#xA;                   dist_to_light - (EPS_D * dir_to_light).norm(), 0);&#xD;&#xA;    if (!bvh-&gt;intersect(shadow_ray))&#xD;&#xA;    {&#xD;&#xA;        L_out += (f * light_L * (cos_theta * scale / pdf));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17065" PostHistoryTypeId="24" PostId="6135" RevisionGUID="453fa0b8-ef36-438d-a032-2c708ec30145" CreationDate="2018-01-21T20:52:38.390" Comment="Proposed by 6 approved by 231 edit id of 298" ContentLicense="CC BY-SA 3.0" />
  <row Id="17066" PostHistoryTypeId="2" PostId="6141" RevisionGUID="0d74b560-feee-4200-afc1-ec299d6dac8a" CreationDate="2018-01-21T21:24:38.050" UserId="6546" Text="I'm sending a large number of data to the `vertex shader`. I use `glBufferData` to generate my `VBO`. Later on I have to replace the data in my `VBO` so I do the following:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * models().size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;What I noticed is when I used the above code (I'm assuming) that some of the previous data is left in the `VBO` because I not only draw the new objects I want to but also some of the old ones.&#xD;&#xA;&#xD;&#xA;Therefore I had to change my code to the following:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * models().size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;The reason I don't like the above aproach is because according to [Khronos][1]&#xD;&#xA;&#xD;&#xA;&gt; When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store.&#xD;&#xA;&#xD;&#xA;How do I replace the whole `VBO` with my new data, but if my new data is smaller than the old data then how do I reallocated the `VBO` efficiently.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="17067" PostHistoryTypeId="1" PostId="6141" RevisionGUID="0d74b560-feee-4200-afc1-ec299d6dac8a" CreationDate="2018-01-21T21:24:38.050" UserId="6546" Text="Replacing Vertex Attributes (glBufferData vs glBufferSubData)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17068" PostHistoryTypeId="3" PostId="6141" RevisionGUID="0d74b560-feee-4200-afc1-ec299d6dac8a" CreationDate="2018-01-21T21:24:38.050" UserId="6546" Text="|opengl|vertex-buffer-object|buffers|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17069" PostHistoryTypeId="5" PostId="6141" RevisionGUID="ba1c98d4-515e-4e3d-816c-27840a40aa45" CreationDate="2018-01-21T21:34:00.630" UserId="6546" Comment="added 131 characters in body" Text="I'm sending a large number of data to the `vertex shader`. I use `glBufferData` to generate my `VBO`. Later on I have to replace the data in my `VBO` so I do the following:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * models().size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;What I noticed is when I used the above code (I'm assuming) that some of the previous data is left in the `VBO` because I not only draw the new objects I want to but also some of the old ones.&#xD;&#xA;&#xD;&#xA;Therefore I had to change my code to the following:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * models().size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;The reason I don't like the above aproach is because according to [Khronos][1]&#xD;&#xA;&#xD;&#xA;&gt; When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store.&#xD;&#xA;&#xD;&#xA;How do I replace the whole `VBO` with my new data, but if my new data is smaller than the old data then how do I reallocated the `VBO` efficiently? Or is there something equivalent to a `NULL terminating character` where the graphics card can know not to read any further data? &#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml" ContentLicense="CC BY-SA 3.0" />
  <row Id="17070" PostHistoryTypeId="5" PostId="6141" RevisionGUID="6571d5da-bf14-405c-8245-b02ec5bfd7ec" CreationDate="2018-01-22T04:29:25.860" UserId="6546" Comment="added 725 characters in body" Text="I'm sending a large number of data to the `vertex shader`. I use `glBufferData` to generate my `VBO`. Later on I have to replace the data in my `VBO` so I do the following:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferSubData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * models().size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;What I noticed is when I used the above code (I'm assuming) that some of the previous data is left in the `VBO` because I not only draw the new objects I want to but also some of the old ones.&#xD;&#xA;&#xD;&#xA;Therefore I had to change my code to the following:&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * models().size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;The reason I don't like the above aproach is because according to [Khronos][1]&#xD;&#xA;&#xD;&#xA;&gt; When replacing the entire data store, consider using glBufferSubData rather than completely recreating the data store with glBufferData. This avoids the cost of reallocating the data store.&#xD;&#xA;&#xD;&#xA;How do I replace the whole `VBO` with my new data, but if my new data is smaller than the old data then how do I reallocated the `VBO` efficiently? Or is there something equivalent to a `NULL terminating character` where the graphics card can know not to read any further data?&#xD;&#xA;&#xD;&#xA;The reason I ask this is because from my understanding `glBufferStorage` is like `glBufferData` except that the `data store` generated by `glBufferStorage` is immutable meaning that the size of the `data store` cannot be changed, as stated [on Khronos][2] and on [Stackoverflow][3].&#xD;&#xA;&#xD;&#xA;&gt; glBufferStorage and glNamedBufferStorage create a new immutable data store.&#xD;&#xA;&#xD;&#xA;But if `glBufferData` creates a `data store` which cannot shrink in size then what's the point of it? (Unless I'm misunderstanding its intended use)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferStorage.xhtml&#xD;&#xA;  [3]: https://stackoverflow.com/questions/27810542/what-is-the-difference-between-glbufferstorage-and-glbufferdata" ContentLicense="CC BY-SA 3.0" />
  <row Id="17071" PostHistoryTypeId="2" PostId="6142" RevisionGUID="660bec29-113f-4b52-a0c9-f5ec391c0c43" CreationDate="2018-01-22T07:45:13.940" UserId="7334" Text="I read the corresponding chapter of PBRT-v3, as well as Veach's thesis which introduced BDPT. However I didn't quite understand why we use the measurement equation. It seems that the measurement equation can be further formulated to obtain different light transport algorithms, such as photon map and bdpt. But why?&#xD;&#xA;&#xD;&#xA;I've searched for other literature but didn't find anything really useful. Can anyone give some hint?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17072" PostHistoryTypeId="1" PostId="6142" RevisionGUID="660bec29-113f-4b52-a0c9-f5ec391c0c43" CreationDate="2018-01-22T07:45:13.940" UserId="7334" Text="How should I understand path-space measurement equation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17073" PostHistoryTypeId="3" PostId="6142" RevisionGUID="660bec29-113f-4b52-a0c9-f5ec391c0c43" CreationDate="2018-01-22T07:45:13.940" UserId="7334" Text="|rendering|pathtracing|photon-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17084" PostHistoryTypeId="2" PostId="6144" RevisionGUID="90673d98-aa61-4a28-952b-a4efec39a7df" CreationDate="2018-01-22T14:35:40.417" UserId="7035" Text="My question is about spherical harmonic lightning, in the context of computing the coefficients with an expensive GI algorithm and passing them to the vertex shader&#xD;&#xA;&#xD;&#xA;Another way is to just use an expensive GI algorithm to compute vertex colors and just use them instead.&#xD;&#xA;&#xD;&#xA;What is the advantage of using the former method? I'm thinking that you can't do reflections with the latter method, and also there's rotational symmetry in SH (i don't know much about) that allows you to do some very simple dynamics with your lights and meshes. Is there any more points i'm missing?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17085" PostHistoryTypeId="1" PostId="6144" RevisionGUID="90673d98-aa61-4a28-952b-a4efec39a7df" CreationDate="2018-01-22T14:35:40.417" UserId="7035" Text="Advantages of SHL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17086" PostHistoryTypeId="3" PostId="6144" RevisionGUID="90673d98-aa61-4a28-952b-a4efec39a7df" CreationDate="2018-01-22T14:35:40.417" UserId="7035" Text="|real-time|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17087" PostHistoryTypeId="2" PostId="6145" RevisionGUID="937bd36d-2de5-482a-b5e2-01d730e25d30" CreationDate="2018-01-22T15:22:35.833" UserId="8068" Text="[Metal Best Practices Guide][1] states that &#xD;&#xA;&#xD;&#xA;&gt; The setVertexBytes:length:atIndex: method is the best option for binding a very small amount (less than 4 KB) of dynamic buffer data to a vertex function&#xD;&#xA;&#xD;&#xA;I believe this means that instead storing uniforms in an overly complicated manually memory managed dynamic buffer, it's best to simply update model/view/projection matrices without using any buffer at all, by using `setVertexBytes` and `setFragmentBytes`.&#xD;&#xA;&#xD;&#xA;My question is, that in this case, as there is no dynamic buffer at all (only static vertex data), what are we calling triple buffering?&#xD;&#xA;&#xD;&#xA;Is it simply because we have a semaphore with `value: 3` left now?&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/BufferBindings.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17088" PostHistoryTypeId="1" PostId="6145" RevisionGUID="937bd36d-2de5-482a-b5e2-01d730e25d30" CreationDate="2018-01-22T15:22:35.833" UserId="8068" Text="Triple buffering without buffers?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17089" PostHistoryTypeId="3" PostId="6145" RevisionGUID="937bd36d-2de5-482a-b5e2-01d730e25d30" CreationDate="2018-01-22T15:22:35.833" UserId="8068" Text="|metal|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17090" PostHistoryTypeId="2" PostId="6146" RevisionGUID="f46fc2a3-809f-4239-909c-ec06b81b8fb8" CreationDate="2018-01-22T19:23:56.733" UserId="2654" Text="There is a difference between &quot;can&quot; and &quot;should&quot;.&#xD;&#xA;&#xD;&#xA;You &quot;should&quot; not use `glBufferData` to change the size of an existing non-immutable buffer. You *can* still do so, but don't expect this to be advantageous.&#xD;&#xA;&#xD;&#xA;You &quot;can&quot; *not* change the size of an immutable buffer with any function.&#xD;&#xA;&#xD;&#xA;&gt; How do I replace the whole VBO with my new data, but if my new data is smaller than the old data then how do I reallocated the VBO efficiently?&#xD;&#xA;&#xD;&#xA;Why would you want to? If the size of your data got smaller, then it is entirely possible that a few frames from now it will be *bigger* again. Perhaps bigger than it was before. That extra storage isn't waste; it is extra storage you're keeping around because you intend to use it at some point in the future.&#xD;&#xA;&#xD;&#xA;The cost of *allocating* memory is high; you should avoid it whenever possible. If you need to increase the size of a buffer, then the implementation must allocate new storage for it. You want to avoid that whenever possible.&#xD;&#xA;&#xD;&#xA;What you ought to be doing is figuring out what a reasonable maximum size would be for this data, and then allocate a buffer of *that* size.&#xD;&#xA;&#xD;&#xA;&gt; Or is there something equivalent to a NULL terminating character where the graphics card can know not to read any further data?&#xD;&#xA;&#xD;&#xA;That's up to you. You tell OpenGL exactly how many vertices to read from a vertex buffer. This is determined based on:&#xD;&#xA;&#xD;&#xA;1. The vertex format for each attribute.&#xD;&#xA;2. The offset within the buffer for each attribute.&#xD;&#xA;3. The number of vertices you send in the `glDraw*` command.&#xD;&#xA;&#xD;&#xA;OpenGL doesn't arbitrarily process data; it reads the data you *tell it* to read. If you want it to not read past a certain point, stop telling it to read past that point ;)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17091" PostHistoryTypeId="2" PostId="6147" RevisionGUID="20bc1592-8b0e-4161-9ab9-4bb7c4bcccef" CreationDate="2018-01-22T20:12:54.480" UserId="7868" Text="I recently implemented Mitchell-Netravali filtering in my path-tracer with 16x (4x4) temporal anti-aliasing. PBR's demonstration image shows it *should* give significantly better results than the box filter, but my test pictures barely show any improvement at all (and the sharpening in Mitchell-Netravali actually highlights jaggies that would have been blurred out by the box filter).&#xD;&#xA;&#xD;&#xA;Is this filter designed for a higher sampling rate? My samples are spread over an even sub-pixel grid, and I'm using $B$ and $C$ constants on the line $B + 2C = 1$. I'm also using the implementation recommended by PBR.&#xD;&#xA;&#xD;&#xA;Function for $f(x, y)$:&#xD;&#xA;&#xD;&#xA;    // Small functions returning the Mitchell-Netravali filter coefficient&#xD;&#xA;    // for a given 2D point&#xD;&#xA;    // Mitchell-Netravali interpolates sparse samples much more effectively&#xD;&#xA;    // than naive filtering (=&gt; applying a box filter), allowing for more&#xD;&#xA;    // effective anti-aliasing at lower sampling rates&#xD;&#xA;    &#xD;&#xA;    // Core filter polynomial&#xD;&#xA;    float MitchellNetravaliPerAxis(float filtVal)&#xD;&#xA;    {&#xD;&#xA;        // Mitchell-Netravali parameters&#xD;&#xA;        // Mitchell and Netravali recommend parameters of the&#xD;&#xA;        // form [B + 2C = 1]&#xD;&#xA;        const float B = 0.35f;&#xD;&#xA;        const float C = 0.325f;&#xD;&#xA;&#xD;&#xA;        // Powers of [filtVal] used during the filtering process&#xD;&#xA;        float filtValCub = filtVal * filtVal * filtVal;&#xD;&#xA;        float filtValSqr = filtVal * filtVal;&#xD;&#xA;&#xD;&#xA;        // Polynomial filter application&#xD;&#xA;        if (filtVal &gt; 1.0f)&#xD;&#xA;        {&#xD;&#xA;            // Filtering for values greater-than/equal-to one but less than two&#xD;&#xA;            return ((B * -1.0f) - (6.0f * C)) * filtValCub +&#xD;&#xA;                   ((6.0f * B) + (30.0f * C)) * filtValSqr +&#xD;&#xA;                   ((-12.0f * B) - (48.0f * C)) * filtVal +&#xD;&#xA;                   ((8.0f * B) + (24.0f * C));&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            // Filtering for other possible values (less than one; values greater than&#xD;&#xA;            // two are cancelled out by the division by pixel radius in [MitchellNetravali(...)]&#xD;&#xA;            // (see below))&#xD;&#xA;            return (12.0f - (9.0f * B) - (6.0f * C)) * filtValCub +&#xD;&#xA;                   (-18.0f + (12.0f * B) + (6.0f * C)) * filtValSqr +&#xD;&#xA;                   (6.0f - (2.0f * B));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Wrapper function applying Mitchell-Netravali to the given sampling point within the&#xD;&#xA;    // given sampling radius&#xD;&#xA;    float MitchellNetravali(float2 sampleXY,&#xD;&#xA;                            float sampleRad)&#xD;&#xA;    {&#xD;&#xA;        float2 filtAxes = abs((sampleXY / sampleRad) * 2.0f);&#xD;&#xA;        return (MitchellNetravaliPerAxis(filtAxes.x) *&#xD;&#xA;                MitchellNetravaliPerAxis(filtAxes.y)) / 36.0f; // Dividing by 6 in each filter is equivalent to dividing the product of the filters by thirty-six (since 36 == 6^2)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Temporal integrator:&#xD;&#xA;&#xD;&#xA;    float3 FrameSmoothing(float3 rgb,&#xD;&#xA;                      float filtCoeff,&#xD;&#xA;                      uint linPixID)&#xD;&#xA;    {&#xD;&#xA;        // Cache a local copy of the given pixel's smoothing history&#xD;&#xA;        PixHistory pixHistory = aaBuffer[linPixID];&#xD;&#xA;&#xD;&#xA;        // Update the given pixel's sample count&#xD;&#xA;        uint sampleCount = pixHistory.sampleCount.x + 1;&#xD;&#xA;        uint sampleNdx = pixHistory.sampleCount.x % NUM_AA_SAMPLES;&#xD;&#xA;&#xD;&#xA;        // Update accumulated filter values&#xD;&#xA;        float4 currChanFilt = filtCoeff.xxxx;&#xD;&#xA;        float4 prevChanFilt = pixHistory.filtSet[sampleNdx];&#xD;&#xA;        float4 accumFilt = (pixHistory.filtAccum - prevChanFilt) + filtCoeff.xxxx;&#xD;&#xA;&#xD;&#xA;        // Filter the pixel, update accumulated pixel values&#xD;&#xA;        float4 currChanSample = float4(rgb, 1.0f) * filtCoeff;&#xD;&#xA;        float4 prevChanSample = pixHistory.sampleSet[sampleNdx];&#xD;&#xA;        float4 accumRGB = (pixHistory.sampleAccum - prevChanSample) + currChanSample;&#xD;&#xA;&#xD;&#xA;        // Pass the updated pixel history back into the AA buffer&#xD;&#xA;        // (also update the pixel's sample-set to include the current sample)&#xD;&#xA;        aaBuffer[linPixID].sampleAccum = accumRGB;&#xD;&#xA;        aaBuffer[linPixID].filtAccum = accumFilt;&#xD;&#xA;        aaBuffer[linPixID].sampleSet[sampleNdx] = currChanSample;&#xD;&#xA;        aaBuffer[linPixID].filtSet[sampleNdx] = filtCoeff;&#xD;&#xA;        aaBuffer[linPixID].sampleCount = sampleCount.xxxx;&#xD;&#xA;&#xD;&#xA;        // Return the updated sample&#xD;&#xA;        // Some filter functions can push average values below zero; counter this clamping out negative channels&#xD;&#xA;        // with [max(...)]&#xD;&#xA;        return max(accumRGB.rgb / accumFilt.xxx, 0.0f.xxx);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Mitchell-Netravali, unjittered:&#xD;&#xA;[![Mitchell-Netravali, no jitter][1]][1]&#xD;&#xA;&#xD;&#xA;Mitchell-Netravali, jittered:&#xD;&#xA;[![Mitchell-Netravali, with jitter][2]][2]&#xD;&#xA;&#xD;&#xA;Unjittered/jittered box-filtered images for comparison:&#xD;&#xA;[![Box filter, no jitter][3]][3]&#xD;&#xA;[![Box filter, jittered][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mm0v9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Uwut6.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hVrYR.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/PK0cs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17092" PostHistoryTypeId="1" PostId="6147" RevisionGUID="20bc1592-8b0e-4161-9ab9-4bb7c4bcccef" CreationDate="2018-01-22T20:12:54.480" UserId="7868" Text="Unexpected results from Mitchell-Netravali" ContentLicense="CC BY-SA 3.0" />
  <row Id="17093" PostHistoryTypeId="3" PostId="6147" RevisionGUID="20bc1592-8b0e-4161-9ab9-4bb7c4bcccef" CreationDate="2018-01-22T20:12:54.480" UserId="7868" Text="|antialiasing|hlsl|filtering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17097" PostHistoryTypeId="4" PostId="6144" RevisionGUID="64331e22-0b9a-4cf3-99bb-6e1349c4d2dd" CreationDate="2018-01-23T05:45:39.367" UserId="48" Comment="clearer title" Text="Advantages of spherical harmonics over baked vertex lighting?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17098" PostHistoryTypeId="2" PostId="6148" RevisionGUID="de6908e7-941b-4996-b841-9a18203b3dd2" CreationDate="2018-01-23T05:53:25.353" UserId="6806" Text="Why sending data from gpu to cpu is slower than cpu to gpu?&#xD;&#xA;&#xD;&#xA;I heard the relation is similar to network situation, in detail, the upload is slower than download. However, I could not understand the meaning.&#xD;&#xA;&#xD;&#xA;In my opinion,  the sending operation should be same because the two sending buses (cpu to gpu and gpu to cpu) can be made with the same performance (I mean bendwith). &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17099" PostHistoryTypeId="1" PostId="6148" RevisionGUID="de6908e7-941b-4996-b841-9a18203b3dd2" CreationDate="2018-01-23T05:53:25.353" UserId="6806" Text="Why sending data from gpu to cpu is slower than cpu to gpu?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17100" PostHistoryTypeId="3" PostId="6148" RevisionGUID="de6908e7-941b-4996-b841-9a18203b3dd2" CreationDate="2018-01-23T05:53:25.353" UserId="6806" Text="|gpu|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17101" PostHistoryTypeId="2" PostId="6149" RevisionGUID="9a17524c-4f8d-4c1f-bd28-629b0444dd6f" CreationDate="2018-01-23T06:01:14.710" UserId="48" Text="Mitchell–Netravali has negative lobes, which are generally not recommended for small sample counts from what I understand; you tend to end up with both the positive and negative areas undersampled. Also, negative lobes do produce a sharpening or ringing effect that looks like what you're seeing.&#xD;&#xA;&#xD;&#xA;I'd try a nonnegative filter, such as a cut-off Gaussian or a [Blackman–Harris window](https://en.wikipedia.org/wiki/Window_function#Blackman%E2%80%93Harris_window)." ContentLicense="CC BY-SA 3.0" />
  <row Id="17102" PostHistoryTypeId="2" PostId="6150" RevisionGUID="b4880600-a03a-451a-87a0-847fb130c40f" CreationDate="2018-01-23T09:09:35.907" UserId="1937" Text="Spherical harmonics are generally used for dynamic objects in your scene, while fully-baked lighting is used for static objects. &#xD;&#xA;&#xD;&#xA;A typical game engine will use both. During the GI pass, all surfaces marked as static will have their global lighting fully baked - generally into a lightmap texture rather than per-vertex. At the same time, a bunch of light probes distributed throughout your scene will receive omnidirectional lighting, and this gets converted into SH. Since SH coefficients interpolate nicely, a mesh moving through your scene can pick up the nearest few light probes (generally 4), and use the weighted average to decode a good approximation of the ambient lighting at its current location.&#xD;&#xA;&#xD;&#xA;Another use for SH is to render less-important dynamic lights in a scene with many lights in it. The most important light or two can be rendered fully dynamically per-pixel, then for each renderer, the SH coefficients of the less-important lights are calculated and added to the light probe data. This allows the lights to change in real-time, and be rendered effectively for free per-vertex in the shader, with a small CPU overhead." ContentLicense="CC BY-SA 3.0" />
  <row Id="17103" PostHistoryTypeId="5" PostId="6147" RevisionGUID="4e295851-a99a-4b99-aef2-0d510a6dd5a8" CreationDate="2018-01-23T09:32:36.770" UserId="7868" Comment="Merged a stray character back into the first code block (&quot;function for f(x, y)&quot;)" Text="I recently implemented Mitchell-Netravali filtering in my path-tracer with 16x (4x4) temporal anti-aliasing. PBR's demonstration image shows it *should* give significantly better results than the box filter, but my test pictures barely show any improvement at all (and the sharpening in Mitchell-Netravali actually highlights jaggies that would have been blurred out by the box filter).&#xD;&#xA;&#xD;&#xA;Is this filter designed for a higher sampling rate? My samples are spread over an even sub-pixel grid, and I'm using $B$ and $C$ constants on the line $B + 2C = 1$. I'm also using the implementation recommended by PBR.&#xD;&#xA;&#xD;&#xA;Function for $f(x, y)$:&#xD;&#xA;&#xD;&#xA;    // Small functions returning the Mitchell-Netravali filter coefficient&#xD;&#xA;    // for a given 2D point&#xD;&#xA;    // Mitchell-Netravali interpolates sparse samples much more effectively&#xD;&#xA;    // than naive filtering (=&gt; applying a box filter), allowing for more&#xD;&#xA;    // effective anti-aliasing at lower sampling rates&#xD;&#xA;    &#xD;&#xA;    // Core filter polynomial&#xD;&#xA;    float MitchellNetravaliPerAxis(float filtVal)&#xD;&#xA;    {&#xD;&#xA;        // Mitchell-Netravali parameters&#xD;&#xA;        // Mitchell and Netravali recommend parameters of the&#xD;&#xA;        // form [B + 2C = 1]&#xD;&#xA;        const float B = 0.35f;&#xD;&#xA;        const float C = 0.325f;&#xD;&#xA;&#xD;&#xA;        // Powers of [filtVal] used during the filtering process&#xD;&#xA;        float filtValCub = filtVal * filtVal * filtVal;&#xD;&#xA;        float filtValSqr = filtVal * filtVal;&#xD;&#xA;&#xD;&#xA;        // Polynomial filter application&#xD;&#xA;        if (filtVal &gt; 1.0f)&#xD;&#xA;        {&#xD;&#xA;            // Filtering for values greater-than/equal-to one but less than two&#xD;&#xA;            return ((B * -1.0f) - (6.0f * C)) * filtValCub +&#xD;&#xA;                   ((6.0f * B) + (30.0f * C)) * filtValSqr +&#xD;&#xA;                   ((-12.0f * B) - (48.0f * C)) * filtVal +&#xD;&#xA;                   ((8.0f * B) + (24.0f * C));&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            // Filtering for other possible values (less than one; values greater than&#xD;&#xA;            // two are cancelled out by the division by pixel radius in [MitchellNetravali(...)]&#xD;&#xA;            // (see below))&#xD;&#xA;            return (12.0f - (9.0f * B) - (6.0f * C)) * filtValCub +&#xD;&#xA;                   (-18.0f + (12.0f * B) + (6.0f * C)) * filtValSqr +&#xD;&#xA;                   (6.0f - (2.0f * B));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Wrapper function applying Mitchell-Netravali to the given sampling point within the&#xD;&#xA;    // given sampling radius&#xD;&#xA;    float MitchellNetravali(float2 sampleXY,&#xD;&#xA;                            float sampleRad)&#xD;&#xA;    {&#xD;&#xA;        float2 filtAxes = abs((sampleXY / sampleRad) * 2.0f);&#xD;&#xA;        return (MitchellNetravaliPerAxis(filtAxes.x) *&#xD;&#xA;                MitchellNetravaliPerAxis(filtAxes.y)) / 36.0f; // Dividing by 6 in each filter is equivalent to dividing the product of the filters by thirty-six (since 36 == 6^2)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Temporal integrator:&#xD;&#xA;&#xD;&#xA;    float3 FrameSmoothing(float3 rgb,&#xD;&#xA;                      float filtCoeff,&#xD;&#xA;                      uint linPixID)&#xD;&#xA;    {&#xD;&#xA;        // Cache a local copy of the given pixel's smoothing history&#xD;&#xA;        PixHistory pixHistory = aaBuffer[linPixID];&#xD;&#xA;&#xD;&#xA;        // Update the given pixel's sample count&#xD;&#xA;        uint sampleCount = pixHistory.sampleCount.x + 1;&#xD;&#xA;        uint sampleNdx = pixHistory.sampleCount.x % NUM_AA_SAMPLES;&#xD;&#xA;&#xD;&#xA;        // Update accumulated filter values&#xD;&#xA;        float4 currChanFilt = filtCoeff.xxxx;&#xD;&#xA;        float4 prevChanFilt = pixHistory.filtSet[sampleNdx];&#xD;&#xA;        float4 accumFilt = (pixHistory.filtAccum - prevChanFilt) + filtCoeff.xxxx;&#xD;&#xA;&#xD;&#xA;        // Filter the pixel, update accumulated pixel values&#xD;&#xA;        float4 currChanSample = float4(rgb, 1.0f) * filtCoeff;&#xD;&#xA;        float4 prevChanSample = pixHistory.sampleSet[sampleNdx];&#xD;&#xA;        float4 accumRGB = (pixHistory.sampleAccum - prevChanSample) + currChanSample;&#xD;&#xA;&#xD;&#xA;        // Pass the updated pixel history back into the AA buffer&#xD;&#xA;        // (also update the pixel's sample-set to include the current sample)&#xD;&#xA;        aaBuffer[linPixID].sampleAccum = accumRGB;&#xD;&#xA;        aaBuffer[linPixID].filtAccum = accumFilt;&#xD;&#xA;        aaBuffer[linPixID].sampleSet[sampleNdx] = currChanSample;&#xD;&#xA;        aaBuffer[linPixID].filtSet[sampleNdx] = filtCoeff;&#xD;&#xA;        aaBuffer[linPixID].sampleCount = sampleCount.xxxx;&#xD;&#xA;&#xD;&#xA;        // Return the updated sample&#xD;&#xA;        // Some filter functions can push average values below zero; counter this clamping out negative channels&#xD;&#xA;        // with [max(...)]&#xD;&#xA;        return max(accumRGB.rgb / accumFilt.xxx, 0.0f.xxx);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Mitchell-Netravali, unjittered:&#xD;&#xA;[![Mitchell-Netravali, no jitter][1]][1]&#xD;&#xA;&#xD;&#xA;Mitchell-Netravali, jittered:&#xD;&#xA;[![Mitchell-Netravali, with jitter][2]][2]&#xD;&#xA;&#xD;&#xA;Unjittered/jittered box-filtered images for comparison:&#xD;&#xA;[![Box filter, no jitter][3]][3]&#xD;&#xA;[![Box filter, jittered][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mm0v9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Uwut6.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hVrYR.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/PK0cs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17104" PostHistoryTypeId="2" PostId="6151" RevisionGUID="2f6443e2-4c2a-4e10-a083-21275b2f330f" CreationDate="2018-01-23T12:04:46.377" UserId="137" Text="The actual sending of data is the same. The PICe bus is the same speed in both directions.&#xD;&#xA;&#xD;&#xA;However when programming there is a big difference namely that when you send you can immediately start doing something else (including queuing other operations using that new data) while the actual transfer is going on. But when receiving you need to synchronize on the completion of the transfer before you can use the data that was sent." ContentLicense="CC BY-SA 3.0" />
  <row Id="17110" PostHistoryTypeId="2" PostId="6153" RevisionGUID="03223bf7-e4a8-4cb7-970f-3f3bdb68622e" CreationDate="2018-01-24T09:24:04.060" UserId="6041" Text="Quadrilateral linear basis functions are defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OvNLJ.png&#xD;&#xA;&#xD;&#xA;What are the steps to calculate the above functions?&#xD;&#xA;&#xD;&#xA;Is it possible to obtain basis functions for a 5 sided polygon(pentagon) or in general n-sided polygon? " ContentLicense="CC BY-SA 3.0" />
  <row Id="17111" PostHistoryTypeId="1" PostId="6153" RevisionGUID="03223bf7-e4a8-4cb7-970f-3f3bdb68622e" CreationDate="2018-01-24T09:24:04.060" UserId="6041" Text="How to obtain Linear basis functions for n-sided polygon?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17112" PostHistoryTypeId="3" PostId="6153" RevisionGUID="03223bf7-e4a8-4cb7-970f-3f3bdb68622e" CreationDate="2018-01-24T09:24:04.060" UserId="6041" Text="|transformations|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17113" PostHistoryTypeId="5" PostId="6153" RevisionGUID="27450d3a-d003-4e6c-8757-35a59b7638e9" CreationDate="2018-01-24T11:06:24.627" UserId="6041" Comment="added 37 characters in body; edited title" Text="Quadrilateral linear basis functions(generalized barycentric coordinates) are defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OvNLJ.png&#xD;&#xA;&#xD;&#xA;What are the steps to calculate the above functions?&#xD;&#xA;&#xD;&#xA;Is it possible to obtain basis functions for a 5 sided polygon(pentagon) or in general n-sided polygon? " ContentLicense="CC BY-SA 3.0" />
  <row Id="17114" PostHistoryTypeId="4" PostId="6153" RevisionGUID="27450d3a-d003-4e6c-8757-35a59b7638e9" CreationDate="2018-01-24T11:06:24.627" UserId="6041" Comment="added 37 characters in body; edited title" Text="How to obtain generalized barycentric coordinates for n-sided polygon?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17115" PostHistoryTypeId="2" PostId="6154" RevisionGUID="7bd02e90-6c65-4936-b9f7-b191c30ccba6" CreationDate="2018-01-24T11:56:24.903" UserId="7724" Text="Wachspress coordinates are arguably the simplest generalised barycentric coordinates available and also the fastest to evaluate.&#xD;&#xA;&#xD;&#xA;For a point $p$ on a planar convex polygon defined by vertices $v_1$, $v_n$ in counter clockwise order you can find weights&#xD;&#xA;&#xD;&#xA;$$w_i(p) = \frac{A(v_{i-1}, v_i, v_{i+1})}{A(v_{i-1}, v_i, p)A(v_{i}, v_{i+1}, p)}. $$&#xD;&#xA;&#xD;&#xA;The coordinate functions $\phi_i$ can then be found be normalising the weights $w_i(p)$&#xD;&#xA;&#xD;&#xA;$$\phi_i(p) = \frac{w_i(p)}{\sum_{j=1}^n w_j(p)}.$$&#xD;&#xA;&#xD;&#xA;Now, the coordinate functions correctly parametrise the point $p$&#xD;&#xA;&#xD;&#xA;$$p = \sum_{i=1}^n v_i \phi_i(p).$$ &#xD;&#xA;&#xD;&#xA;For, non-convex polygons you could use [mean value coordinates.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.6059&amp;rep=rep1&amp;type=pdf)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17116" PostHistoryTypeId="5" PostId="6154" RevisionGUID="200c9b2a-c549-48f7-a883-24d20ef7190c" CreationDate="2018-01-24T12:02:16.710" UserId="7724" Comment="added 23 characters in body" Text="Quadrilateral basis functions can be calculated using an outer product of the basis of two linear functions (1-r, r) and (1-s, s). The same thing does not apply for arbitrary $n$-sided domains. For this we use generalised barycentric coordinates. Wachspress coordinates are arguably the simplest generalised barycentric coordinates available, are fast to evaluate and are defined for arbitrary $n$.&#xD;&#xA;&#xD;&#xA;For a point $p$ on a planar convex polygon defined by vertices $v_1$, $v_n$ in counter clockwise order you can find weights&#xD;&#xA;&#xD;&#xA;$$w_i(p) = \frac{A(v_{i-1}, v_i, v_{i+1})}{A(v_{i-1}, v_i, p)A(v_{i}, v_{i+1}, p)}. $$&#xD;&#xA;&#xD;&#xA;The coordinate functions $\phi_i$ can then be found be normalising the weights $w_i(p)$&#xD;&#xA;&#xD;&#xA;$$\phi_i(p) = \frac{w_i(p)}{\sum_{j=1}^n w_j(p)}.$$&#xD;&#xA;&#xD;&#xA;Now, the coordinate functions correctly parametrise the point (linear reproduction property)&#xD;&#xA;&#xD;&#xA;$$p = \sum_{i=1}^n v_i \phi_i(p).$$ &#xD;&#xA;&#xD;&#xA;For, non-convex polygons you could use [mean value coordinates.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.6059&amp;rep=rep1&amp;type=pdf)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17117" PostHistoryTypeId="5" PostId="6154" RevisionGUID="3fc60e17-def1-4ffe-b7e6-2462ab53ef2f" CreationDate="2018-01-24T12:08:26.027" UserId="7724" Comment="added 12 characters in body" Text="Quadrilateral basis functions can be calculated using an outer product of the basis of two linear functions (1-r, r) and (1-s, s). The same thing does not apply for arbitrary $n$-sided domains. For this we use generalised barycentric coordinates. Wachspress coordinates are arguably the simplest generalised barycentric coordinates available, are fast to evaluate and are defined for arbitrary $n$.&#xD;&#xA;&#xD;&#xA;For a point $p$ on a planar convex polygon defined by vertices $v_1, v_2, \ldots, v_n$, ordered counter-clockwise, you can find weights&#xD;&#xA;&#xD;&#xA;$$w_i(p) = \frac{A(v_{i-1}, v_i, v_{i+1})}{A(v_{i-1}, v_i, p)A(v_{i}, v_{i+1}, p)}. $$&#xD;&#xA;&#xD;&#xA;The coordinate functions $\phi_i$ can then be found be normalising the weights $w_i(p)$&#xD;&#xA;&#xD;&#xA;$$\phi_i(p) = \frac{w_i(p)}{\sum_{j=1}^n w_j(p)}.$$&#xD;&#xA;&#xD;&#xA;Now, the coordinate functions correctly parametrise the point (linear reproduction property)&#xD;&#xA;&#xD;&#xA;$$p = \sum_{i=1}^n v_i \phi_i(p).$$ &#xD;&#xA;&#xD;&#xA;For, non-convex polygons you could use [mean value coordinates.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.6059&amp;rep=rep1&amp;type=pdf)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17118" PostHistoryTypeId="5" PostId="6154" RevisionGUID="dbad1c37-ef4f-4bc8-a231-d6ad918e057e" CreationDate="2018-01-24T13:13:13.563" UserId="7724" Comment="added 59 characters in body" Text="Quadrilateral basis functions can be calculated using an outer product of the basis of two linear functions (1-r, r) and (1-s, s). The same thing does not apply for arbitrary $n$-sided domains. For this we use generalised barycentric coordinates. Wachspress coordinates are arguably the simplest generalised barycentric coordinates available, are fast to evaluate and are defined for arbitrary $n$.&#xD;&#xA;&#xD;&#xA;For a point $p$ on a planar convex polygon defined by vertices $v_1, v_2, \ldots, v_n$, ordered counter-clockwise, you can find weights&#xD;&#xA;&#xD;&#xA;$$w_i(p) = \frac{A(v_{i-1}, v_i, v_{i+1})}{A(v_{i-1}, v_i, p)A(v_{i}, v_{i+1}, p)}. $$&#xD;&#xA;&#xD;&#xA;Here, $A(v_1, v_2, v_3)$ denotes the signed triangle area. The coordinate functions $\phi_i$ can then be found be normalising the weights $w_i(p)$&#xD;&#xA;&#xD;&#xA;$$\phi_i(p) = \frac{w_i(p)}{\sum_{j=1}^n w_j(p)}.$$&#xD;&#xA;&#xD;&#xA;Now, the coordinate functions correctly parametrise the point (linear reproduction property)&#xD;&#xA;&#xD;&#xA;$$p = \sum_{i=1}^n v_i \phi_i(p).$$ &#xD;&#xA;&#xD;&#xA;For, non-convex polygons you could use [mean value coordinates.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.6059&amp;rep=rep1&amp;type=pdf)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17119" PostHistoryTypeId="2" PostId="6155" RevisionGUID="44971362-ef61-4619-9ba0-ced911101d49" CreationDate="2018-01-24T14:23:31.153" UserId="8078" Text="Currently I'm trying to reproduce the result by the academic papers ***Sub-pixel Shift Estimation of Image based on the Least Squares Approximation in Phase Region by Fujimoto, Fujisawa and Ikehara*** (Proceedings of 26th European Signal Processing Conference, EUSIPCO '16, pp. 91–95. IEEE, 2016 [PDF][1]). However there's a part that I don't understand, hope you guys could help me out!&#xD;&#xA;&#xD;&#xA;Basically, the author uses phase to determine the subpixel shifting of two images instead the conventional way of fitting the peak POC. The overview of the method is described in this chart:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I got stuck at the subtraction junction. If you refer to the [PDF][1] file I attached, Figure 3 shows the phase over-wrap between `-pi` and `pi`, and the author proposed that the phase can be split into two components, that's the integer shift and decimal shift so that the phase can be smoother out as shown in Fig. 4. This is where I don't understand, according to the *Eqn. 14*, the decimal phase could be obtained via:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This is where things get confused, the subtraction of `(a'k1 + b'k2)` gets me nowhere. The author said that the value of `a'` and `b'` (the slopes) is obtained via the conventional POC (paragraph above Eqn. 14). My question is, how? I could retrieve the integer shift using the cross power spectrum, **but not the slopes**. Hope you guys could help me out! I got stuck for months!&#xD;&#xA;&#xD;&#xA;If the information provided is not adequate, let me know and I'll do my best! Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://mega.nz/#!vp9WFDbb!pEG8pem9n2SaX8IHxbUxnD4JT6ngp0nF608T3zAeiJY&#xD;&#xA;  [2]: https://i.stack.imgur.com/Od10d.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/96yLM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17120" PostHistoryTypeId="1" PostId="6155" RevisionGUID="44971362-ef61-4619-9ba0-ced911101d49" CreationDate="2018-01-24T14:23:31.153" UserId="8078" Text="Sub-pixel image registration using phase" ContentLicense="CC BY-SA 3.0" />
  <row Id="17121" PostHistoryTypeId="3" PostId="6155" RevisionGUID="44971362-ef61-4619-9ba0-ced911101d49" CreationDate="2018-01-24T14:23:31.153" UserId="8078" Text="|image-processing|fourier-transform|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17122" PostHistoryTypeId="2" PostId="6156" RevisionGUID="54459f92-559c-449a-8f1d-95d18f9b716a" CreationDate="2018-01-24T15:54:36.527" UserId="8079" Text="   I was reading &quot;3D Math Primer for Computer Graphics and Game Development&quot; and there was something the author had said that I thought was particularly interesting, he stated &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; It is important to understand that this matrix multiplication is still a&#xD;&#xA;linear transformation. Matrix multiplication cannot represent “translation”&#xD;&#xA;in 4D, and the 4D zero vector will always be transformed back into the 4D&#xD;&#xA;zero vector. The reason this trick works to transform points in 3D is that&#xD;&#xA;we are actually shearing 4D space. (Compare Equation (6.11) with the&#xD;&#xA;shear matrices from Section 5.5.) The 4D hyperplane that corresponds to&#xD;&#xA;physical 3D space does not pass through the origin in 4D. Thus, when we&#xD;&#xA;shear 4D space, we are able to translate in 3D.&#xD;&#xA;&#xD;&#xA;I'm familiar with the shearing transformation, and I can see how a translation matrix in 4D resembles that of a 3D shear. I did not quite understand how this translation in 3D though. So, restating the question I had asked, how does a shear in 4D equate to a translation in 3D space? A geometric visual would also be nice to help me understand this a bit more." ContentLicense="CC BY-SA 3.0" />
  <row Id="17123" PostHistoryTypeId="1" PostId="6156" RevisionGUID="54459f92-559c-449a-8f1d-95d18f9b716a" CreationDate="2018-01-24T15:54:36.527" UserId="8079" Text="why is translating in 3D space the same as shearing in 4D space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17124" PostHistoryTypeId="3" PostId="6156" RevisionGUID="54459f92-559c-449a-8f1d-95d18f9b716a" CreationDate="2018-01-24T15:54:36.527" UserId="8079" Text="|3d|transformations|matrix|affine-transformations|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17125" PostHistoryTypeId="2" PostId="6157" RevisionGUID="1dfc335d-6f0e-48e3-a62b-33fa435e1d50" CreationDate="2018-01-24T16:44:27.910" UserId="3332" Text="I have a scene set up with an orthographic projection with the near / far set from -5000 to 5000.  The model view is centered at 0 in the z-axis.  I am rendering a sphere centered at z=0 with lighting, and the specular component appears as to be calculated as if the eye were infinity far back.  See image below, in which the light only has a red specular component, no diffuse or other parameters.  However, if i render this with a custom shader that implements [blinn][1] lighting, the sphere appears black, because the &quot;viewDir&quot; calculation is negative, since the eye is centered inside the sphere.  How does fixed function get around this?  Does it some how know about the ortho projection and get around it?  Sources I've seen online say lighting is not supposed to take the projection into account.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![fixed function specular with ortho projection][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model%20blinn&#xD;&#xA;  [2]: https://i.stack.imgur.com/ire0b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17126" PostHistoryTypeId="1" PostId="6157" RevisionGUID="1dfc335d-6f0e-48e3-a62b-33fa435e1d50" CreationDate="2018-01-24T16:44:27.910" UserId="3332" Text="How does opengl fixed function pipeline determine specular lighting with an orthographic projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17127" PostHistoryTypeId="3" PostId="6157" RevisionGUID="1dfc335d-6f0e-48e3-a62b-33fa435e1d50" CreationDate="2018-01-24T16:44:27.910" UserId="3332" Text="|opengl|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17131" PostHistoryTypeId="2" PostId="6159" RevisionGUID="315c50ae-ec40-4bab-9388-8bcd69229ce9" CreationDate="2018-01-24T16:51:40.940" UserId="3386" Text="Nvidia discusses their lossless delta color compression is on its fourth generation in Pascal, and that it transparently saves bandwidth behind the scenes for rendering workloads. AMD has a similar technology, discussed in detail here: https://gpuopen.com/dcc-overview/&#xD;&#xA;&#xD;&#xA;Do the same limitations apply to Nvidia's compression? They don't seem to discuss it in context of developer guidance." ContentLicense="CC BY-SA 3.0" />
  <row Id="17132" PostHistoryTypeId="1" PostId="6159" RevisionGUID="315c50ae-ec40-4bab-9388-8bcd69229ce9" CreationDate="2018-01-24T16:51:40.940" UserId="3386" Text="Is Nvidia's delta color compression supported in CUDA, or with DirectX UAVs?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17133" PostHistoryTypeId="3" PostId="6159" RevisionGUID="315c50ae-ec40-4bab-9388-8bcd69229ce9" CreationDate="2018-01-24T16:51:40.940" UserId="3386" Text="|gpu|compression|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17135" PostHistoryTypeId="2" PostId="6160" RevisionGUID="e77ff1fe-24c9-4c51-be0f-0e29a4d6c95c" CreationDate="2018-01-24T17:01:02.543" UserId="3386" Text="You havent' set the `mipFilter` property for your `samplerDescriptor`.  The default value for `mipFilter` is `notMipped` which means the sampler will never access anything other than level 0. Set it to `nearest` or `linear`." ContentLicense="CC BY-SA 3.0" />
  <row Id="17140" PostHistoryTypeId="5" PostId="6154" RevisionGUID="2deda6d3-0f81-4dfc-aaf2-4e9c82bc9dd5" CreationDate="2018-01-24T20:58:42.627" UserId="7724" Comment="added 353 characters in body" Text="Quadrilateral basis functions can be calculated using an outer product of the basis of two linear functions (1-r, r) and (1-s, s). The same thing does not apply for arbitrary $n$-sided domains. For this we use generalised barycentric coordinates. Wachspress coordinates are arguably the simplest generalised barycentric coordinates available, are fast to evaluate and are defined for arbitrary $n$.&#xD;&#xA;&#xD;&#xA;For a point $p$ on a planar convex polygon defined by vertices $v_1, v_2, \ldots, v_n$, ordered counter-clockwise, you can find weights&#xD;&#xA;&#xD;&#xA;$$w_i(p) = \frac{A(v_{i-1}, v_i, v_{i+1})}{A(v_{i-1}, v_i, p)A(v_{i}, v_{i+1}, p)}. $$&#xD;&#xA;&#xD;&#xA;Here, $A(v_1, v_2, v_3)$ denotes the signed triangle area. The coordinate functions $\phi_i$ can then be found be normalising the weights $w_i(p)$&#xD;&#xA;&#xD;&#xA;$$\phi_i(p) = \frac{w_i(p)}{\sum_{j=1}^n w_j(p)}.$$&#xD;&#xA;&#xD;&#xA;Now, the coordinate functions correctly parametrise the point (linear reproduction property)&#xD;&#xA;&#xD;&#xA;$$p = \sum_{i=1}^n v_i \phi_i(p).$$ &#xD;&#xA;&#xD;&#xA;At vertices the coordinates satisfy the Lagrange property $\phi_i(v_j) = \delta_{ij},$ where $\delta_{ij}$ is the Kronecker delta, meaning that the corresponding coordinate function evaluates to 1 at its vertex and linearly interpolate on the edges. It is also important to notice that the coordinate partition unity $\sum_{i=1}^n \phi_i(p) = 1.$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For, non-convex polygons you could use [mean value coordinates.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.104.6059&amp;rep=rep1&amp;type=pdf)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17141" PostHistoryTypeId="2" PostId="6162" RevisionGUID="97e35b8a-eb20-441c-9891-84e994d6bbab" CreationDate="2018-01-25T04:27:55.110" UserId="7868" Text="The diffuse BRDF is defined as $R / \pi$, where the division by $\pi$ is there to maintain conservation of energy. The derivation is provided [here][1].&#xD;&#xA;&#xD;&#xA;The maths makes sense, and I can understand where the BRDF comes from in a mechanical sense. But I'm struggling to understand what it *represents*; how does division by $\pi$ relate to reflectance within the unit hemisphere?&#xD;&#xA;&#xD;&#xA;  [1]: http://rorydriscoll.com/2009/01/25/energy-conservation-in-games/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17142" PostHistoryTypeId="1" PostId="6162" RevisionGUID="97e35b8a-eb20-441c-9891-84e994d6bbab" CreationDate="2018-01-25T04:27:55.110" UserId="7868" Text="Intuitively understanding conservation of energy for the Lambertian BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="17143" PostHistoryTypeId="3" PostId="6162" RevisionGUID="97e35b8a-eb20-441c-9891-84e994d6bbab" CreationDate="2018-01-25T04:27:55.110" UserId="7868" Text="|brdf|diffuse|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17144" PostHistoryTypeId="50" PostId="6039" RevisionGUID="1198c4c9-1af2-4a79-a350-60174f86e89d" CreationDate="2018-01-25T04:55:54.340" UserId="-1" />
  <row Id="17145" PostHistoryTypeId="5" PostId="6162" RevisionGUID="e2109334-cb67-4ea5-9f7a-4b0a18e4042d" CreationDate="2018-01-25T05:35:27.713" UserId="7868" Comment="Small content edit for consistency with the title" Text="The Lambertian BRDF is defined as $R / \pi$, where the division by $\pi$ is there to maintain conservation of energy. The derivation is provided [here][1].&#xD;&#xA;&#xD;&#xA;The maths makes sense, and I can understand where the BRDF comes from in a mechanical sense. But I'm struggling to understand what it *represents*; how does division by $\pi$ relate to reflectance within the unit hemisphere?&#xD;&#xA;&#xD;&#xA;  [1]: http://rorydriscoll.com/2009/01/25/energy-conservation-in-games/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17146" PostHistoryTypeId="2" PostId="6163" RevisionGUID="822448f1-06f0-40f8-a7c5-08868f9aafaf" CreationDate="2018-01-25T06:41:28.923" UserId="1937" Text="A perfect Lambert reflector actually reflects light in a cosine distribution - that is, the amount of light per unit area reflected in any given direction $R$ is proportional to $N.R$. The reason the radiance appears constant for all angles is that as the view direction moves away from the normal, the reflected light per unit area decreases, but the surface area per projected beam area (and hence per pixel) increases by the same amount - the cosine factors cancel out.&#xD;&#xA;&#xD;&#xA;Given this distribution, to be energy conserving, the probability density for the reflected light in all possible directions cannot sum to more than 1. If you integrate the cosine function over the whole hemisphere around the normal, you get $\pi$, so this is the normalization factor you need." ContentLicense="CC BY-SA 3.0" />
  <row Id="17147" PostHistoryTypeId="2" PostId="6164" RevisionGUID="0c92b4d2-8d43-442e-a9b8-86c91d88c3f2" CreationDate="2018-01-25T10:52:33.637" UserId="1937" Text="In a linear transformation system, your origin is always a fixed point, since 0*anything = 0. So imagine you have a cinema screen, and the origin is at the centre of the screen. Using linear transformations, you can rotate, scale or shear the image, what you can't do is move it, since you have a fixed point in the middle.&#xD;&#xA;&#xD;&#xA;Now add a dimension, and move your origin out of the screen through this new dimension. Your origin is now at the projector, at &lt;0, 0, 0&gt;, and the centre of your screen is at &lt;0, 0, 1&gt;. So as well as the image transforms you had available before, you can now effectively move your image, by shearing through the space in between the projector and the screen.&#xD;&#xA;&#xD;&#xA;Add another dimension and you have the 4D -&gt; 3D case." ContentLicense="CC BY-SA 3.0" />
  <row Id="17148" PostHistoryTypeId="2" PostId="6165" RevisionGUID="2dfc7cbd-e052-4861-ad00-4dca8dfa4672" CreationDate="2018-01-25T11:06:29.373" UserId="6" Text="When using [Transform Feedback](https://www.khronos.org/opengl/wiki/Transform_Feedback) to capture the vertices generated by the primtive generation stage, we can use `glDrawTransformFeedback` to directly draw the generated data without the need for querying the number of generated primitives and thus **without CPU-GPU synchronization**, which is especially useful with geometry shaders generating a possibly unknown number of primitives.&#xD;&#xA;&#xD;&#xA;However, in my case I'm not using the generated primitive data per-vertex, but **per-instance** (it's basically a classic GPU-based instance culling scenario). So I need to **supply the number of generated primitives into the instance count parameter of `glDraw...Instanced`**. But the various [Transform Feedback rendering functions](https://www.khronos.org/opengl/wiki/Vertex_Rendering#Transform_feedback_rendering) only ever use the primitive count as vertex count and never as instance count. Now this *does* require me to wait for the transform feedback to finish and get the result of the corresponding query object, thus instroducing a synchronization point.&#xD;&#xA;&#xD;&#xA;I considered that I could also use the quite powerful [Indirect Rendering](https://www.khronos.org/opengl/wiki/Vertex_Rendering#Indirect_rendering) functionality and together with a [Query Buffer Object](https://www.khronos.org/opengl/wiki/Query_Object#Query_buffer_object) route the result of the transform feedback query directly into the instance count field of the draw indirect buffer. But this has the problem that I'm not only drawing just one single object at the various instance locations, but **a multitude of different objects** (with their own states and VBOs as well). So I would actually have to scatter the query result into multiple drawing parameter sets (though, possibly in the same buffer), probably by use of a compute shader. But this just seems like overkill to me.&#xD;&#xA;&#xD;&#xA;So my question is, **is there any other less involved way to just use the number of primitives/vertices generated from transform feedback directly as the instance count in (preferably multiple different) instanced rendering commands without the need to explicitly query that count onto the CPU?** In light of GPU-based scene culling techniques I can't imagine this to be a rare use-case (but maybe in that case you just have to go the way over indirect drawing commands anyway). I'm not afraid of using extensions if available, so maybe there's some obscure little extension that does exactly that? Or I'm just missing something else obvious here." ContentLicense="CC BY-SA 3.0" />
  <row Id="17149" PostHistoryTypeId="1" PostId="6165" RevisionGUID="2dfc7cbd-e052-4861-ad00-4dca8dfa4672" CreationDate="2018-01-25T11:06:29.373" UserId="6" Text="Directly use Transform Feedback primitive count as instance count for drawing" ContentLicense="CC BY-SA 3.0" />
  <row Id="17150" PostHistoryTypeId="3" PostId="6165" RevisionGUID="2dfc7cbd-e052-4861-ad00-4dca8dfa4672" CreationDate="2018-01-25T11:06:29.373" UserId="6" Text="|opengl|synchronization|transform-feedback|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17151" PostHistoryTypeId="2" PostId="6166" RevisionGUID="e3904623-2768-465b-a592-fad78c52061f" CreationDate="2018-01-25T12:41:26.880" UserId="6" Text="This isn't necessarily due to the orthographic projection per se, but rather the classic two-sided lighting problem together with a little optimization that the old OpenGL did. When the eye space origin is inside the object, you are basically **looking at the object from the inside** and it's only the peculiarities of orthographic projection and the near/far planes you chose that makes the outsides appear.&#xD;&#xA;&#xD;&#xA;It depends on how you actually implement your shader. I *assume* though, when you compute your `viewDir`, you just use the vector from the eye space vertex to the origin (or rather the negative normalized eye space vertex position). You are basically trying to **light the backfaces of the sphere** and if you haven't taken account for that, the angle between the view vector and the normal will thus be larger than 90°, usually resulting in a negative or 0-clamped specular term (or whatever other unexpected results).&#xD;&#xA;&#xD;&#xA;A common way to accomodate for that would be to negate the normal vector whenever it is facing away from the camera, or maybe the light, or when dealing with backfacing fragments,... But this depends on your specific use-case.&#xD;&#xA;&#xD;&#xA;Now, **why doesn't this happen in old deprecated OpenGL** when using orthographic projection?&#xD;&#xA;&#xD;&#xA;For this we have to look at the specificities of how it did its lighting computations. There was a function [`glLightModel`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLightModel.xml) which controlled some of the global properties of lighting computations. Specifically, the paramter `GL_LIGHT_MODEL_LOCAL_VIEWER`. This controls an optimization where the specular computation does *not* use the actual vector from the vertex to the camera, but **always just uses the z-axis** instead. i.e. as you said it assumes an infinitely far away viewer along the z-axis. This is the reason why even in perspective projection the specular highlight on an object is always at the same position, even if you move it around in the view. If you change this setting from the default of `GL_FALSE` to `GL_TRUE`, it should perform an actual view vector computation and you should get the same results as with your own shader.&#xD;&#xA;&#xD;&#xA;There was also another option that controls a property related to your general issue, too. `GL_LIGHT_MODEL_TWO_SIDE` enables two-sided lighting, which means that back-facing polygons will be lit like their front faces (however, possibly using different material settings) by using the inverted normal. If you activate this, this still won't change anything in your orthographic scene, since **you *are* seeing the front faces** of the sphere here. But once you change to perspective projection, the lighting should be black, but this time because you're seeing the backfaces, which you can enable lighting for with this option." ContentLicense="CC BY-SA 3.0" />
  <row Id="17152" PostHistoryTypeId="2" PostId="6167" RevisionGUID="e48872ea-d2c0-4f49-91db-fbfc909b6efe" CreationDate="2018-01-25T14:09:04.967" UserId="72" Text="Problem: I'm trying to dynamically texture a mesh of the real world generated by the Hololens over time using photos also captured from the Hololens, perhaps one photo per second. Each of the photos includes positional information of the Hololens from the time when the photo was taken, which allows me to project the images onto the existing mesh and figure out the UV mapping for each image.&#xD;&#xA;&#xD;&#xA;In case of a single image, this seems fairly simple, as it is just standard projective texturing of the mesh. But I will be capturing a potentially endless stream of images over a span of time which will be taken from different positions and orientations. For acceptable performance, I cannot simply store and iterate through all photos and do projective texturing for each.&#xD;&#xA;&#xD;&#xA;How can I perhaps generate a texture atlas &amp; accompanying UV mapping for the real world mesh and update it after each image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17153" PostHistoryTypeId="1" PostId="6167" RevisionGUID="e48872ea-d2c0-4f49-91db-fbfc909b6efe" CreationDate="2018-01-25T14:09:04.967" UserId="72" Text="Projective texturing from many images" ContentLicense="CC BY-SA 3.0" />
  <row Id="17154" PostHistoryTypeId="3" PostId="6167" RevisionGUID="e48872ea-d2c0-4f49-91db-fbfc909b6efe" CreationDate="2018-01-25T14:09:04.967" UserId="72" Text="|texture|projections|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17157" PostHistoryTypeId="2" PostId="6168" RevisionGUID="d8603254-4089-4879-a9cb-4df482b251ce" CreationDate="2018-01-25T15:07:37.197" UserId="2654" Text="How do you know which primitives go into which instances? The complexity of this makes it seem like you don't really want to use transform feedback; you want to use a *compute shader*. Then, through [indirect rendering][1] and [SSBOs][2], you can write whatever vertex commands and vertices you want.&#xD;&#xA;&#xD;&#xA;If multiple CS instances affect the same rendering command, use SSBO atomics to increment the number of vertices/instances for that rendering command.&#xD;&#xA;&#xD;&#xA;Transform feedback is merely an ad-hoc mechanism for something that modern OpenGL allows you to just do directly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Indirect_Rendering&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="17158" PostHistoryTypeId="5" PostId="6165" RevisionGUID="f7ef8df6-7f5a-4257-a07c-85b1cffb8c02" CreationDate="2018-01-25T18:07:07.553" UserId="6" Comment="added 65 characters in body" Text="When using [Transform Feedback](https://www.khronos.org/opengl/wiki/Transform_Feedback) to capture the vertices generated by the primtive generation stage, we can use `glDrawTransformFeedback` to directly draw the generated data without the need for querying the number of generated primitives and thus **without CPU-GPU synchronization**, which is especially useful with geometry shaders generating a possibly unknown number of primitives.&#xD;&#xA;&#xD;&#xA;However, in my case I'm not using the generated primitive data per-vertex, but **per-instance** (it's basically a classic GPU-based instance culling scenario). So I need to **supply the number of generated primitives into the instance count parameter of `glDraw...Instanced`**. But the various [Transform Feedback rendering functions](https://www.khronos.org/opengl/wiki/Vertex_Rendering#Transform_feedback_rendering) only ever use the primitive count as vertex count and never as instance count. Now this *does* require me to wait for the transform feedback to finish and get the result of the corresponding query object, thus instroducing a synchronization point.&#xD;&#xA;&#xD;&#xA;I considered that I could also use the quite powerful [Indirect Rendering](https://www.khronos.org/opengl/wiki/Vertex_Rendering#Indirect_rendering) functionality and together with a [Query Buffer Object](https://www.khronos.org/opengl/wiki/Query_Object#Query_buffer_object) route the result of the transform feedback query directly into the instance count field of the draw indirect buffer. But this has the problem that I'm **not only issuing a single `glDraw...Instanced` call, but multiple different ones** (each with their own state, per-vertex attributes and draw parameters, but all with the same instance count and per-instance attributes). So I would actually have to scatter the query result into multiple drawing parameter sets (though, possibly in the same buffer), probably by use of a compute shader. But this just seems like overkill to me.&#xD;&#xA;&#xD;&#xA;So my question is, **is there any other less involved way to just use the number of primitives/vertices generated from transform feedback directly as the instance count in (preferably multiple different) instanced rendering commands without the need to explicitly query that count onto the CPU?** In light of GPU-based scene culling techniques I can't imagine this to be a rare use-case (but maybe in that case you just have to go the way over indirect drawing commands anyway). I'm not afraid of using extensions if available, so maybe there's some obscure little extension that does exactly that? Or I'm just missing something else obvious here." ContentLicense="CC BY-SA 3.0" />
  <row Id="17159" PostHistoryTypeId="5" PostId="6168" RevisionGUID="6b993949-3abf-42b3-938d-30e4b9ce3a7d" CreationDate="2018-01-25T18:13:29.840" UserId="2654" Comment="added 503 characters in body" Text="The complexity of this makes it seem like you don't really want to use transform feedback; you want to use a *compute shader*. Then, through [indirect rendering][1] and [SSBOs][2], you can write whatever vertex commands data you want.&#xD;&#xA;&#xD;&#xA;The idea is that you have some number of indirect rendering commands (one command per set of instances). And for each instance you create, the CS invocation needs to bump the instance count of each of those commands (atomically, of course).&#xD;&#xA;&#xD;&#xA;Now, because there are state changes between the commands, you wouldn't be able to use a multi-draw indirect command. But by using indirect commands and a CS, you can at least keep all of the data on the GPU, without having to do things like buffer copies to multiple locations.&#xD;&#xA;&#xD;&#xA;Transform feedback is merely an ad-hoc mechanism for something that modern OpenGL allows you to just do directly. If you need to broadcast the &quot;primitive&quot; count to multiple locations (or really, if you're doing anything besides rendering the feedbacked data), then you should be using a compute shader, not TF.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Indirect_Rendering&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 3.0" />
  <row Id="17160" PostHistoryTypeId="2" PostId="6169" RevisionGUID="4b2ce639-e5f5-4d51-b19b-c9de1d4b0789" CreationDate="2018-01-25T23:11:35.143" UserId="7871" Text="According to: https://www.cs.virginia.edu/~jdl/importance.doc&#xD;&#xA;&#xD;&#xA;For a specular sample: (page 4 of the document) $$pdf(\theta_{i}) = \frac{n+1}{2\pi} \cos^n(a)$$  &#xD;&#xA;&#xD;&#xA;And this is how you choose an incoming direction according to a specular sample of the BRDF (page 4 of the document):&#xD;&#xA;$$ \vec{w_{i}} = (\alpha, \phi) = (\arccos(\varepsilon_{1}^{  \frac{1}{n+1}  }), \ \  2\pi\varepsilon_{2})$$&#xD;&#xA;&#xD;&#xA;But according to the figure on page 4, a specular sample has a BRDF favoring a direction which is highly dependent on the incoming ray, but the $ \phi $ angle is decided by uniformly sampling a circle, disregarding completely the incoming direction, which to me makes no sense&#xD;&#xA;&#xD;&#xA;Shouldn't the $ \phi $ angle favor the specular direction, which is dependent on the incoming ray? Why we're not using at all the incoming ray to calculate the sampled direction which is supposedly sampling the brdf?&#xD;&#xA;&#xD;&#xA;No matter where I look for it, I haven't seen an implementation using a BRDF which takes into account the incoming direction, which makes me think I've misunderstood the theory behind it&#xD;&#xA;&#xD;&#xA;Lastly, assuming a standard backward path tracer, is this pseudocode the right way of computing the results?&#xD;&#xA;&#xD;&#xA;    color =  float3(1,1,1)&#xD;&#xA;    ray   =  getRayFromCamera()&#xD;&#xA;    &#xD;&#xA;    for NUM_BOUNCES:&#xD;&#xA;        primitive = world.intersect(ray)    &#xD;&#xA;    &#xD;&#xA;        // assuming primitive is non null, I'm omitting the code where we sample a background&#xD;&#xA;        albedo           = primitive.albedo&#xD;&#xA;        &#xD;&#xA;        // computeOutGoingRay will return a Ray and a PDF&#xD;&#xA;        outgoingRay, pdf = primitive.material.computeOutGoingRay(ray, normal, etc..)&#xD;&#xA;        &#xD;&#xA;        // of the incoming radiance, how much is scattered along the new direction?&#xD;&#xA;        brdf             = primitive.brdf(outgoingRay, ray)&#xD;&#xA;        &#xD;&#xA;        color = (color * albedo * brdf) / pdf&#xD;&#xA;    &#xD;&#xA;        // assigning the new ray to keep our backward recursion&#xD;&#xA;        ray   = outGoingRay" ContentLicense="CC BY-SA 3.0" />
  <row Id="17161" PostHistoryTypeId="1" PostId="6169" RevisionGUID="4b2ce639-e5f5-4d51-b19b-c9de1d4b0789" CreationDate="2018-01-25T23:11:35.143" UserId="7871" Text="Phong Modified BRDF Implementation" ContentLicense="CC BY-SA 3.0" />
  <row Id="17162" PostHistoryTypeId="3" PostId="6169" RevisionGUID="4b2ce639-e5f5-4d51-b19b-c9de1d4b0789" CreationDate="2018-01-25T23:11:35.143" UserId="7871" Text="|pathtracing|brdf|physically-based|monte-carlo|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17173" PostHistoryTypeId="2" PostId="6172" RevisionGUID="4f34a03c-d319-4e43-9d68-fa32fe626daf" CreationDate="2018-01-26T14:32:31.200" UserId="8097" Text="I'm writing a halftone algorithm, which takes standards RGB intensities in the range of $0-255$ and outputs black and white elements with a corresponding size ratio.&#xD;&#xA;&#xD;&#xA;Should I apply a gamma expansion on the input luminance to get the ratio?&#xD;&#xA;&#xD;&#xA;I.e. is it correct to do the following?&#xD;&#xA;&#xD;&#xA;$\frac{w_\text{white}}{w_\text{white}+w_\text{black}} = (0.299 R + 0.587 G + 0.114 B)^{2.2}$&#xD;&#xA;&#xD;&#xA;Should I apply the exponent of $2.2$?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17174" PostHistoryTypeId="1" PostId="6172" RevisionGUID="4f34a03c-d319-4e43-9d68-fa32fe626daf" CreationDate="2018-01-26T14:32:31.200" UserId="8097" Text="Gamma correction and halftone" ContentLicense="CC BY-SA 3.0" />
  <row Id="17175" PostHistoryTypeId="3" PostId="6172" RevisionGUID="4f34a03c-d319-4e43-9d68-fa32fe626daf" CreationDate="2018-01-26T14:32:31.200" UserId="8097" Text="|gamma|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17176" PostHistoryTypeId="2" PostId="6173" RevisionGUID="6d362f32-64f6-4867-be7c-23d182a3da08" CreationDate="2018-01-26T14:32:31.200" UserId="8097" Text="Yes. The RGB values are most likely gamma compressed.&#xD;&#xA;&#xD;&#xA;Consider gamma calibration images like the one below.&#xD;&#xA;&#xD;&#xA;For a well calibrated monitor the gray value should look the same as the pattern of black and white lines.&#xD;&#xA;&#xD;&#xA;If you load in the image you will likely find RGB values of $186$. &#xD;&#xA;&#xD;&#xA;$(186/255)^2.2 \approx 0.5$, which means that a halftone pattern of black and white lines of equal width correspond to RGB values of 186.&#xD;&#xA;&#xD;&#xA;[![gamma calibration image][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HLZNI.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="17177" PostHistoryTypeId="5" PostId="6157" RevisionGUID="05509f41-ade3-4da6-b95b-d98d4bf9af8f" CreationDate="2018-01-26T20:39:09.377" UserId="3332" Comment="bad link" Text="I have a scene set up with an orthographic projection with the near / far set from -5000 to 5000.  The model view is centered at 0 in the z-axis.  I am rendering a sphere centered at z=0 with lighting, and the specular component appears as to be calculated as if the eye were infinity far back.  See image below, in which the light only has a red specular component, no diffuse or other parameters.  However, if i render this with a custom shader that implements [blinn][1] lighting, the sphere appears black, because the &quot;viewDir&quot; calculation is negative, since the eye is centered inside the sphere.  How does fixed function get around this?  Does it some how know about the ortho projection and get around it?  Sources I've seen online say lighting is not supposed to take the projection into account.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![fixed function specular with ortho projection][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model&#xD;&#xA;  [2]: https://i.stack.imgur.com/ire0b.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17178" PostHistoryTypeId="5" PostId="6151" RevisionGUID="a6c31628-3cd4-41e2-9727-86e35b8f5523" CreationDate="2018-01-26T20:56:24.617" UserId="137" Comment="edited body" Text="The actual sending of data is the same. The PCIe bus is the same speed in both directions.&#xD;&#xA;&#xD;&#xA;However when programming there is a big difference namely that when you send you can immediately start doing something else (including queuing other operations using that new data) while the actual transfer is going on. But when receiving you need to synchronize on the completion of the transfer before you can use the data that was sent." ContentLicense="CC BY-SA 3.0" />
  <row Id="17179" PostHistoryTypeId="2" PostId="6174" RevisionGUID="12bcf6d8-dca0-4c42-983e-19dc364589e9" CreationDate="2018-01-26T22:25:05.040" UserId="5703" Text="Consider the following scheme that mimicks the generation of a sample for phong shading. where V is the viewer direction, N is the normal, R is the specular reflection direction and $S_i$ is some sample. This space (commonly called tangent space) uses the normal as one of its basis vectors. you can think of it as the 'Z axis'&#xD;&#xA;&#xD;&#xA;[![tangent space][1]][1]&#xD;&#xA;&#xD;&#xA;Now, when we generate samples for Phong shading wo do not generate them in this space.&#xD;&#xA;&#xD;&#xA;Rather, we use a different reference system where the Specular reflection direction is the 'z axis', thus, our angle $\theta$ is the angle between the reflected direction and the sample direction, and the angle $\phi$ is the angle between some $S_{ix}$ that is the projection of our sample direction onto the plane perpendicular to $R$ and some arbitrary but constant vector perpendicular to our reflected direction&#xD;&#xA;&#xD;&#xA;[![ray space][2]][2]&#xD;&#xA;&#xD;&#xA;$\phi$ is a number that is sampled uniformly in the range $(0,2\pi)$ this means that rays will be generated around the reflected direction with no bias towards any particular direction.&#xD;&#xA;&#xD;&#xA;Generated rays will, however, be biased to have a direction close to $R$ due to the way that $\theta$ is sampled.&#xD;&#xA;&#xD;&#xA;When we generate rays in a backwards pathtracer we use the view direction to get the directions where the light is likely to come from, instead of throwing light around and seeing where it falls. The later technique is closer to photon mapping.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xYz3F.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/MxqAm.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17180" PostHistoryTypeId="2" PostId="6175" RevisionGUID="f05f35bb-0469-4cdd-875c-490c9796589a" CreationDate="2018-01-27T05:47:23.827" UserId="8101" Text="All &quot;scene graphs&quot; I've seen in practice are actually trees, but I have some vague memories about somebody saying a while ago that sometimes they can actually be graphs (technically, trees are already graphs, but you get the point).&#xD;&#xA;&#xD;&#xA;If they can actually be graphs, what are some practical examples?&#xD;&#xA;&#xD;&#xA;If they're always just trees, is there some history behind why it was originally called &quot;scene graph&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17181" PostHistoryTypeId="1" PostId="6175" RevisionGUID="f05f35bb-0469-4cdd-875c-490c9796589a" CreationDate="2018-01-27T05:47:23.827" UserId="8101" Text="is a scene graph actually a tree?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17182" PostHistoryTypeId="3" PostId="6175" RevisionGUID="f05f35bb-0469-4cdd-875c-490c9796589a" CreationDate="2018-01-27T05:47:23.827" UserId="8101" Text="|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17183" PostHistoryTypeId="6" PostId="6175" RevisionGUID="b35d8f88-5e1d-4e75-94e1-2f161f855abc" CreationDate="2018-01-27T05:57:25.307" UserId="8101" Comment="edited tags" Text="|data-structure|scene-graph|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17184" PostHistoryTypeId="2" PostId="6176" RevisionGUID="d448f663-c2ce-4628-bd1d-7d7f8cfec6ba" CreationDate="2018-01-27T06:50:30.843" UserId="3003" Text="Yes, scene graphs can be non-tree graphs. Your question is a little vague, but assuming you're talking about something like the scene graph in rendering a frame of video, for say a feature film, then yes, there are often references between objects. For example, in a compositing application, you might have a piece of footage with an effect applied. The effect may have as one of its inputs another piece of footage which is also in the scene. (It might use the other image for blending, as a reflection map, as a diffuse or specular lighting map, a bump map etc.) So you could have a scene that looks like this:&#xD;&#xA;&#xD;&#xA;    scene contains:&#xD;&#xA;        footage A contains:&#xD;&#xA;            filter &quot;Multiply Blend&quot; which takes input:&#xD;&#xA;                footage B&#xD;&#xA;        footage B&#xD;&#xA;        footage C&#xD;&#xA;&#xD;&#xA;In something like a game, you might objects that refer to other objects that they can collide with:&#xD;&#xA;&#xD;&#xA;    scene contains:&#xD;&#xA;        ground which can collide with:&#xD;&#xA;            player&#xD;&#xA;            ball&#xD;&#xA;            goal&#xD;&#xA;        player which can collide with:&#xD;&#xA;            ground&#xD;&#xA;            ball&#xD;&#xA;            goal&#xD;&#xA;        ball which can collide with:&#xD;&#xA;            player&#xD;&#xA;            ground&#xD;&#xA;            goal&#xD;&#xA;&#xD;&#xA;etc." ContentLicense="CC BY-SA 3.0" />
  <row Id="17185" PostHistoryTypeId="50" PostId="5925" RevisionGUID="a03ed699-1a26-48f4-9ad0-182bdd69d294" CreationDate="2018-01-27T12:17:35.680" UserId="-1" />
  <row Id="17186" PostHistoryTypeId="5" PostId="6173" RevisionGUID="c43cfa10-72a2-4231-9afe-fb8b6019459c" CreationDate="2018-01-27T16:03:33.890" UserId="7008" Comment="corrected a formatting error" Text="Yes. The RGB values are most likely gamma corrected.&#xD;&#xA;&#xD;&#xA;Consider gamma calibration images like the one below.&#xD;&#xA;&#xD;&#xA;For a well calibrated monitor the gray value should look the same as the pattern of black and white lines.&#xD;&#xA;&#xD;&#xA;If you load in the image you will likely find RGB values of $186$. &#xD;&#xA;&#xD;&#xA;$(186/255)^{2.2} \approx 0.5$, which means that a halftone pattern of black and white lines of equal width correspond to RGB values of 186.&#xD;&#xA;&#xD;&#xA;[![gamma calibration image][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HLZNI.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="17187" PostHistoryTypeId="24" PostId="6173" RevisionGUID="c43cfa10-72a2-4231-9afe-fb8b6019459c" CreationDate="2018-01-27T16:03:33.890" Comment="Proposed by 7008 approved by -1 edit id of 301" ContentLicense="CC BY-SA 3.0" />
  <row Id="17188" PostHistoryTypeId="5" PostId="6173" RevisionGUID="26120784-4dfd-4eb8-a9fd-75a718e39563" CreationDate="2018-01-27T16:03:33.890" UserId="8097" Comment="corrected a formatting error" Text="Yes. The RGB values are most likely gamma compressed.&#xD;&#xA;&#xD;&#xA;Consider gamma calibration images like the one below.&#xD;&#xA;&#xD;&#xA;For a well calibrated monitor the gray value should look the same as the pattern of black and white lines.&#xD;&#xA;&#xD;&#xA;If you load in the image you will likely find RGB values of $186$. &#xD;&#xA;&#xD;&#xA;$(186/255)^{2.2} \approx 0.5$, which means that a halftone pattern of black and white lines of equal width correspond to RGB values of 186.&#xD;&#xA;&#xD;&#xA;[![gamma calibration image][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HLZNI.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="17189" PostHistoryTypeId="5" PostId="6173" RevisionGUID="96935cdf-ae66-4980-bbf2-05e7a5905cb2" CreationDate="2018-01-27T16:40:15.027" UserId="8097" Comment="Fix gamma compression formula" Text="Yes and no. The RGB values are most likely gamma compressed.&#xD;&#xA;&#xD;&#xA;Consider gamma calibration images like the one below.&#xD;&#xA;&#xD;&#xA;For a well calibrated monitor the gray value should look the same as the pattern of black and white lines.&#xD;&#xA;&#xD;&#xA;If you load in the image you will likely find RGB values of $186$. &#xD;&#xA;&#xD;&#xA;$(186/255)^{2.2} \approx 0.5$, which means that a halftone pattern of black and white lines of equal width correspond to RGB values of 186.&#xD;&#xA;&#xD;&#xA;[![gamma calibration image][1]][1]&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;However, the gamma compression applied was more likely the sRGB gamma compression than an overall gamma of $2.2$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{w_\text{white}}{w_\text{white}+w_\text{black}} =&#xD;&#xA;\begin{cases}&#xD;&#xA;12.92V  &amp;\text{ if } V \leq 0.0031308 \\&#xD;&#xA;1.055 V^{1/2.4} + 0.055 &amp;\text{ if } V &gt; 0.0031308 &#xD;&#xA;\end{cases}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $V = 0.299R+0.587G+0.114B$&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HLZNI.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="17190" PostHistoryTypeId="2" PostId="6177" RevisionGUID="118ee3f2-94f2-4858-9556-444aa2d4197f" CreationDate="2018-01-27T19:43:47.653" UserId="5183" Text="I want to create a histogram of intensities 0.1, 0.2, .... 0.9, 1, from an image rendered using OpenGL and C++. How can I do this? Can I access the pixel intensities in the framebuffer somehow? Also, I'm not using any glsl shaders, and don't intend to." ContentLicense="CC BY-SA 3.0" />
  <row Id="17191" PostHistoryTypeId="1" PostId="6177" RevisionGUID="118ee3f2-94f2-4858-9556-444aa2d4197f" CreationDate="2018-01-27T19:43:47.653" UserId="5183" Text="Histogram of image intensities" ContentLicense="CC BY-SA 3.0" />
  <row Id="17192" PostHistoryTypeId="3" PostId="6177" RevisionGUID="118ee3f2-94f2-4858-9556-444aa2d4197f" CreationDate="2018-01-27T19:43:47.653" UserId="5183" Text="|opengl|image-processing|c++|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17193" PostHistoryTypeId="5" PostId="6177" RevisionGUID="f1198f9a-f0ea-4f7f-a588-71f3d5c8a1ca" CreationDate="2018-01-27T23:20:22.417" UserId="5183" Comment="added 386 characters in body" Text="I want to create a histogram of intensities 0.1, 0.2, .... 0.9, 1, from an image rendered using OpenGL and C++. How can I do this? Can I access the pixel intensities in the framebuffer somehow? Also, I'm not using any glsl shaders, and don't intend to.&#xD;&#xA;&#xD;&#xA;So far I tried:&#xD;&#xA;&#xD;&#xA;double *framebuffer = frameBuffer = new double[1920*1080 * 4];&#xD;&#xA;&#xD;&#xA;glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);&#xD;&#xA;&#xD;&#xA;for (int j = 0; j&lt;1920*1080 * 4; j += 4){&#xD;&#xA;if(frameBuffer[j] == 0.1) // find pixel with R channel at 0.1: this is where the problem is. I know I have surfaces with this intensity but I never enter the if statement&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17194" PostHistoryTypeId="5" PostId="6177" RevisionGUID="75eb8252-f616-47d2-b110-34e4cae11be2" CreationDate="2018-01-27T23:29:21.167" UserId="3003" Comment="Fixed formatting." Text="I want to create a histogram of intensities 0.1, 0.2, .... 0.9, 1, from an image rendered using OpenGL and C++. How can I do this? Can I access the pixel intensities in the framebuffer somehow? Also, I'm not using any glsl shaders, and don't intend to.&#xD;&#xA;&#xD;&#xA;So far I tried:&#xD;&#xA;&#xD;&#xA;    double *framebuffer = frameBuffer = new double[1920*1080 * 4];&#xD;&#xA;    &#xD;&#xA;    glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);&#xD;&#xA;    &#xD;&#xA;    for (int j = 0; j&lt;1920*1080 * 4; j += 4){&#xD;&#xA;    if(frameBuffer[j] == 0.1) // find pixel with R channel at 0.1: this is where the problem is. I know I have surfaces with this intensity but I never enter the if statement&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17195" PostHistoryTypeId="2" PostId="6178" RevisionGUID="6fa6f0ad-c09c-42d5-9a80-41eb2004964d" CreationDate="2018-01-27T23:30:33.477" UserId="7868" Text="I recently replaced the Lambertian BRDF in my path-tracer with Oren-Nayar, under the assumption that I could adjust it to use the GGX distribution model with appropriate masking/shadowing. &#xD;&#xA;&#xD;&#xA;PBR suggests this is't viable, though - Oren-Nayar is formulated without any clear $D$/$F$/$G$ parameters, and a note under the Torrance-Sparrow model states that &quot;one of the nice things about the Torrance-Sparrow model is that **the derivation doesn't depend on the particular microfacet distribution being used**&quot; (implying this isn't the case for Oren-Nayar).&#xD;&#xA;&#xD;&#xA;If Oren-Nayar *is* extensible, how would I do that? I suspect I could replace my $\sigma$ values with an NDF taking some $\alpha$ parameter (effectively convolving against the implicit Gaussian in the Oren-Nayar definition), and multiply the final Oren-Nayar value&#xD;&#xA;&#xD;&#xA;$a + b * max(0, cos(\phi_i - \phi_o)) * sin(\alpha) * tan(\beta)$&#xD;&#xA;&#xD;&#xA;against $G$ to capture masked segments of $dA$, but won't these changes clash with assumptions made by the derivation? PBR states that the function natively accounts for Gaussian-distributed masking, so applying another function over the top should result in over-darkening...&#xD;&#xA;&#xD;&#xA;If it isn't extensible, can I adjust Torrance-Sparrow instead? Locking $F(\omega_o)$ to $1$ should remove Fresnel effects, and the specular assumption can be negated by extracting the $d\omega_h = \frac{d\omega_o}{4\cos\theta_o}$ relationship to create the modified BRDF $f(\omega_o, \omega_i) = \frac{D(\omega_h)G(\omega_o,\ \omega_i)d\omega_h}{d\omega_o\cos\theta_o}$ " ContentLicense="CC BY-SA 3.0" />
  <row Id="17196" PostHistoryTypeId="1" PostId="6178" RevisionGUID="6fa6f0ad-c09c-42d5-9a80-41eb2004964d" CreationDate="2018-01-27T23:30:33.477" UserId="7868" Text="Microfacet shading for diffuse materials" ContentLicense="CC BY-SA 3.0" />
  <row Id="17197" PostHistoryTypeId="3" PostId="6178" RevisionGUID="6fa6f0ad-c09c-42d5-9a80-41eb2004964d" CreationDate="2018-01-27T23:30:33.477" UserId="7868" Text="|mathematics|brdf|pbr|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17198" PostHistoryTypeId="2" PostId="6179" RevisionGUID="2a4fc51c-b77e-4ef8-ac93-caae3b585f6b" CreationDate="2018-01-27T23:35:46.803" UserId="3003" Text="Due the way floating point values work, you probably don't want to do an exact equality check. You probably want something more like this in your loop:&#xD;&#xA;&#xD;&#xA;    uint32 sums [ 11 ] = { 0 };&#xD;&#xA;    for (int j = 0; j &lt; 1920 * 1080 * 4; j += 4) {&#xD;&#xA;        size_t bucket = static_cast&lt;size_t&gt;(framebuffer [ j ] * 10.0);&#xD;&#xA;        sums [ bucket ]++;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note that there are 11 buckets because the range includes both 0 and 1. If you want only 10 buckets and want to put any pixels that have a value of 1 in them into the top bucket, you could do:&#xD;&#xA;&#xD;&#xA;    uint32 sums [ 10 ] = { 0 };&#xD;&#xA;&#xD;&#xA;and change the bucket index calculation to:&#xD;&#xA;&#xD;&#xA;    size_t bucket = static_cast&lt;size_t&gt;(framebuffer [ j ] * 10.0);&#xD;&#xA;    bucket = std::min(bucket, 9);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17199" PostHistoryTypeId="5" PostId="6178" RevisionGUID="1be0ca77-8bf6-4312-9a68-df63adc9618d" CreationDate="2018-01-27T23:52:51.197" UserId="7868" Comment="Edited Oren-Nayar masking/shadowing proposal for clarity + simplicity" Text="I recently replaced the Lambertian BRDF in my path-tracer with Oren-Nayar, under the assumption that I could adjust it to use the GGX distribution model with appropriate masking/shadowing. &#xD;&#xA;&#xD;&#xA;PBR suggests this is't viable, though - Oren-Nayar is formulated without any clear $D$/$F$/$G$ parameters, and a note under the Torrance-Sparrow model states that &quot;one of the nice things about the Torrance-Sparrow model is that **the derivation doesn't depend on the particular microfacet distribution being used**&quot; (implying this isn't the case for Oren-Nayar).&#xD;&#xA;&#xD;&#xA;If Oren-Nayar *is* extensible, how would I do that? I suspect I could replace my $\sigma$ values with an NDF taking some $\alpha$ parameter (effectively convolving against the implicit Gaussian in the Oren-Nayar definition), and multiply the evaluated Oren-Nayar function against $G$ to capture masked segments of $dA$, but won't this clash with assumptions made by the derivation? PBR states that the function natively accounts for Gaussian-distributed masking, so applying another function over the top should result in over-darkening...&#xD;&#xA;&#xD;&#xA;If it isn't extensible, can I adjust Torrance-Sparrow instead? Locking $F(\omega_o)$ to $1$ should remove Fresnel effects, and the specular assumption can be negated by extracting the $d\omega_h = \frac{d\omega_o}{4\cos\theta_o}$ relationship to create the modified BRDF $f(\omega_o, \omega_i) = \frac{D(\omega_h)G(\omega_o,\ \omega_i)d\omega_h}{d\omega_o\cos\theta_o}$ " ContentLicense="CC BY-SA 3.0" />
  <row Id="17200" PostHistoryTypeId="2" PostId="6180" RevisionGUID="949f9830-f437-44c7-a9e5-973460561b28" CreationDate="2018-01-28T00:36:51.950" UserId="7925" Text="I'm trying to implement a simple Phong shader that supports non-physically-based materials and textures. Even though the material has a texture for each light component I still want the respective material coefficient to have some effect. My doubt is how to handle both of them. Should I mix, multiply or sum them?&#xD;&#xA;Right now I've multiplied them:&#xD;&#xA; &#xD;&#xA;    ambient  = material.ambient_color  * light.ambient  * texture_ambient;&#xD;&#xA;    diffuse  = material.diffuse_color  * light.diffuse  * diffuse_strength  * texture_diffuse;&#xD;&#xA;    specular = material.specular_color * light.specular * specular_strength * texture_specular;&#xD;&#xA;&#xD;&#xA;It seems kinda dark, is this the correct way to combine material coefficients and textures?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17201" PostHistoryTypeId="1" PostId="6180" RevisionGUID="949f9830-f437-44c7-a9e5-973460561b28" CreationDate="2018-01-28T00:36:51.950" UserId="7925" Text="Combine material coefficients and textures in Phong Shading" ContentLicense="CC BY-SA 3.0" />
  <row Id="17202" PostHistoryTypeId="3" PostId="6180" RevisionGUID="949f9830-f437-44c7-a9e5-973460561b28" CreationDate="2018-01-28T00:36:51.950" UserId="7925" Text="|opengl|texture|glsl|shading|material|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17203" PostHistoryTypeId="5" PostId="6177" RevisionGUID="e5937573-616b-4c9d-a50c-eaa845174ae0" CreationDate="2018-01-28T03:16:15.993" UserId="5183" Comment="added 14 characters in body" Text="I want to create a histogram of intensities 0.1, 0.2, .... 0.9, 1, from an image rendered using OpenGL and C++. How can I do this? Can I access the pixel intensities in the framebuffer somehow? Also, I'm not using any glsl shaders, and don't intend to.&#xD;&#xA;&#xD;&#xA;So far I tried:&#xD;&#xA;&#xD;&#xA;    unsigned char *framebuffer = frameBuffer = new unsigned char[1920*1080 * 4];&#xD;&#xA;    &#xD;&#xA;    glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);&#xD;&#xA;    &#xD;&#xA;    for (int j = 0; j&lt;1920*1080 * 4; j += 4){&#xD;&#xA;    if(frameBuffer[j] == 0.1) // find pixel with R channel at 0.1: this is where the problem is. I know I have surfaces with this intensity but I never enter the if statement&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17204" PostHistoryTypeId="2" PostId="6181" RevisionGUID="f9eed100-7d89-48ed-ba64-f25369de66fd" CreationDate="2018-01-29T09:36:56.203" UserId="8107" Text="I'm reading the Loper et al. 2015 paper on the Skinned Multi-Person Linear Model and I came across this:&#xD;&#xA;&#xD;&#xA;&gt;What we would like is a vertex-based model that has the expressive&#xD;&#xA;&gt;power of the triangle deformation models so that it can capture&#xD;&#xA;&gt;a whole range of natural shapes and poses.&#xD;&#xA;&#xD;&#xA;I'm not a Computer Science student, I'm actually a Physics student, so I only have an elementary understanding of these matters. &#xD;&#xA;&#xD;&#xA;What is the difference between a triangle-based and a vertex-based skinning model? &#xD;&#xA;Why is the triangle-based one more &quot;expressive&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17205" PostHistoryTypeId="1" PostId="6181" RevisionGUID="f9eed100-7d89-48ed-ba64-f25369de66fd" CreationDate="2018-01-29T09:36:56.203" UserId="8107" Text="Triangle-based and vertex-based skinning models?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17206" PostHistoryTypeId="3" PostId="6181" RevisionGUID="f9eed100-7d89-48ed-ba64-f25369de66fd" CreationDate="2018-01-29T09:36:56.203" UserId="8107" Text="|3d|mesh|animation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17207" PostHistoryTypeId="2" PostId="6182" RevisionGUID="e6393f8b-8f26-4820-ac1f-614640de4d70" CreationDate="2018-01-29T10:04:27.857" UserId="209" Text="Apologies in advance for the poor quality of this answer, but this sounds a little like what an ex-colleague was doing as part of his PhD. The &quot;Free-Viewpoint video&quot; papers listed at the bottom of https://www.researchgate.net/profile/James_Imber might be useful, or at least a starting point to find related work. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17208" PostHistoryTypeId="2" PostId="6183" RevisionGUID="46718fe9-6414-44ff-8f4f-15701ffae89f" CreationDate="2018-01-29T10:32:17.417" UserId="8108" Text="My professor gave me the following example exam question:&#xD;&#xA;&#xD;&#xA;&gt; Given 4 spheres with diameter = 1. There centers are located on&#xD;&#xA;&gt; coordinates (2,4,0), (4,2,0), (4,6,0) and (6,4,0), as seen in the&#xD;&#xA;&gt; picture below. Three different hierarchies of tightest possible&#xD;&#xA;&gt; axis-aligned bounding volumes (AABB) are given:&#xD;&#xA;&gt; &#xD;&#xA;&gt;  - A single AABB around every sphere&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (4,2,0) and    another around the spheres located at (4,6,0) and (6,4,0).&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (6,4,0) and    another around the spheres located at (4,2,0) and (4,6,0).&#xD;&#xA;&gt; &#xD;&#xA;&gt; For every one of these the all-containing AABB is constructed.&#xD;&#xA;&#xD;&#xA;[![Assignment][1]][1]&#xD;&#xA;&#xD;&#xA;The questions are:&#xD;&#xA;&#xD;&#xA;&gt;  - Rank these 3 structures based on efficiency for intersecting a ray    with these spheres (best to worst)&#xD;&#xA;&gt;  - Does this ranking change if we change the spheres with a (scaled) tea-pot that still fits within the bounding volume?&#xD;&#xA;&gt;  - Can this ranking depend on the position of the camera, when we only    consider visibility rays (so no shadow rays)? You can assume you're   &#xD;&#xA;&gt; working with an orthographic camera.&#xD;&#xA;&#xD;&#xA;He insisted on not giving a 'philosophical' answer (like: 'this depends on ...') but rather actually calculating the cost using the surface are heuristic etc.&#xD;&#xA;&#xD;&#xA;Only, I have no idea how to start. The cost function we have seen is defined as follows&#xD;&#xA;$$Cost(cell) = C_t + \frac{S_L}{S_{Cell}} \times N_L \times t_i + \frac{S_R}{S_{Cell}} \times N_R \times r_i$$&#xD;&#xA;With:&#xD;&#xA;&#xD;&#xA; - $C_t$ the cost of traversal (which is an arbitrary constant, I think)&#xD;&#xA; - $S_L$/$S_R$ the surface area of the left/right child cell&#xD;&#xA; - $S_{cell}$ the surface area of the entire cell&#xD;&#xA; - $N_L$/$N_R$ the number of objects in the left/right child cell&#xD;&#xA; - $t_i$ the cost of object intersection (which is also an arbitrary&#xD;&#xA;   constant)&#xD;&#xA;&#xD;&#xA;However, the first hierarchy has 4 child cells, how would I calculate the cost here? Any tips on how to start this exercise would be very helpful.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IEBNK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17209" PostHistoryTypeId="1" PostId="6183" RevisionGUID="46718fe9-6414-44ff-8f4f-15701ffae89f" CreationDate="2018-01-29T10:32:17.417" UserId="8108" Text="Classify acceleration structure using surface area heuristic" ContentLicense="CC BY-SA 3.0" />
  <row Id="17210" PostHistoryTypeId="3" PostId="6183" RevisionGUID="46718fe9-6414-44ff-8f4f-15701ffae89f" CreationDate="2018-01-29T10:32:17.417" UserId="8108" Text="|raytracing|ray|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17211" PostHistoryTypeId="5" PostId="6183" RevisionGUID="59ca8967-ad2d-492a-84b8-2b491d0b1d2e" CreationDate="2018-01-29T10:55:06.097" UserId="8108" Comment="Tried solving it" Text="My professor gave me the following example exam question:&#xD;&#xA;&#xD;&#xA;&gt; Given 4 spheres with diameter = 1. Their centers are located on&#xD;&#xA;&gt; coordinates (2,4,0), (4,2,0), (4,6,0) and (6,4,0), as seen in the&#xD;&#xA;&gt; picture below. Three different hierarchies of tightest possible&#xD;&#xA;&gt; axis-aligned bounding volumes (AABB) are given:&#xD;&#xA;&gt; &#xD;&#xA;&gt;  - A single AABB around every sphere&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (4,2,0) and    another around the spheres located at (4,6,0) and (6,4,0).&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (6,4,0) and    another around the spheres located at (4,2,0) and (4,6,0).&#xD;&#xA;&gt; &#xD;&#xA;&gt; For every one of these the all-containing AABB is constructed.&#xD;&#xA;&#xD;&#xA;[![Assignment][1]][1]&#xD;&#xA;&#xD;&#xA;The questions are:&#xD;&#xA;&#xD;&#xA;&gt;  - Rank these 3 structures based on efficiency for intersecting a ray    with these spheres (best to worst)&#xD;&#xA;&gt;  - Does this ranking change if we change the spheres with a (scaled) tea-pot that still fits within the bounding volume?&#xD;&#xA;&gt;  - Can this ranking depend on the position of the camera, when we only    consider visibility rays (so no shadow rays, for example)? You can assume you're working with an orthographic camera.&#xD;&#xA;&#xD;&#xA;He insisted on not giving a 'philosophical' answer (like: 'this depends on ...') but rather actually calculating the cost using the surface are heuristic etc.&#xD;&#xA;&#xD;&#xA;Only, I have no idea how to start. The cost function we have seen is defined as follows&#xD;&#xA;$$Cost(cell) = C_t + \frac{S_L}{S_{Cell}} \times N_L \times t_i + \frac{S_R}{S_{Cell}} \times N_R \times r_i$$&#xD;&#xA;With:&#xD;&#xA;&#xD;&#xA; - $C_t$ the cost of traversal (which is an arbitrary constant, I think)&#xD;&#xA; - $S_L$/$S_R$ the surface area of the left/right child cell&#xD;&#xA; - $S_{cell}$ the surface area of the entire cell&#xD;&#xA; - $N_L$/$N_R$ the number of objects in the left/right child cell&#xD;&#xA; - $t_i$ the cost of object intersection (which is also an arbitrary&#xD;&#xA;   constant)&#xD;&#xA;&#xD;&#xA;However, the first hierarchy has 4 child cells, how would I calculate the cost here? Any tips on how to start this exercise would be very helpful.&#xD;&#xA;&#xD;&#xA;EDIT: Okay, so for the second and third setup, is it as simple as filling in the formula? For the second setup, this would lead to (assuming I made no numerical errors :) ):&#xD;&#xA;$$\begin{align*}Cost(cell) &amp;= C_t + \frac{2*3^2 + 4*3*1}{2*5^2 + 4*5*1} * 2 * t_i + \frac{2*3^2 + 4*3*1}{2*5^2 + 4*5*1} * 2 * t_i \\ &amp;= C_t * \frac{120}{70} * t_i \end{align*}$$&#xD;&#xA;&#xD;&#xA;For the third setup this would, analogously, lead to:&#xD;&#xA;$$Cost(cell) = C_t + \frac{88}{70}*t_i$$.&#xD;&#xA;&#xD;&#xA;**So now my question would boil down to: can I just do the same for the first setup, but instead evaluate 4 sub-cells? Also, am I correct in assuming $C_t$ and $t_i$ are fixed constants or do they depend on the setup?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IEBNK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17212" PostHistoryTypeId="5" PostId="6183" RevisionGUID="78aaa715-29f0-4b1e-8e6f-1fd24dfc1a81" CreationDate="2018-01-29T11:02:59.710" UserId="8108" Comment="added 4 characters in body" Text="My professor gave me the following example exam question:&#xD;&#xA;&#xD;&#xA;&gt; Given 4 spheres with diameter = 1. Their centers are located on&#xD;&#xA;&gt; coordinates (2,4,0), (4,2,0), (4,6,0) and (6,4,0), as seen in the&#xD;&#xA;&gt; picture below. Three different hierarchies of tightest possible&#xD;&#xA;&gt; axis-aligned bounding volumes (AABB) are given:&#xD;&#xA;&gt; &#xD;&#xA;&gt;  - A single AABB around every sphere&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (4,2,0) and    another around the spheres located at (4,6,0) and (6,4,0).&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (6,4,0) and    another around the spheres located at (4,2,0) and (4,6,0).&#xD;&#xA;&gt; &#xD;&#xA;&gt; For every one of these the all-containing AABB is constructed.&#xD;&#xA;&#xD;&#xA;[![Assignment][1]][1]&#xD;&#xA;&#xD;&#xA;The questions are:&#xD;&#xA;&#xD;&#xA;&gt;  - Rank these 3 structures based on efficiency for intersecting a ray    with these spheres (best to worst)&#xD;&#xA;&gt;  - Does this ranking change if we change the spheres with a (scaled) tea-pot that still fits within the bounding volume?&#xD;&#xA;&gt;  - Can this ranking depend on the position of the camera, when we only    consider visibility rays (so no shadow rays, for example)? You can assume you're working with an orthographic camera.&#xD;&#xA;&#xD;&#xA;He insisted on not giving a 'philosophical' answer (like: 'this depends on ...') but rather actually calculating the cost using the surface are heuristic etc.&#xD;&#xA;&#xD;&#xA;Only, I have no idea how to start. The cost function we have seen is defined as follows&#xD;&#xA;$$Cost(cell) = C_t + \frac{S_L}{S_{Cell}} \times N_L \times t_i + \frac{S_R}{S_{Cell}} \times N_R \times r_i$$&#xD;&#xA;With:&#xD;&#xA;&#xD;&#xA; - $C_t$ the cost of traversal (which is an arbitrary constant, I think)&#xD;&#xA; - $S_L$/$S_R$ the surface area of the left/right child cell&#xD;&#xA; - $S_{cell}$ the surface area of the entire cell&#xD;&#xA; - $N_L$/$N_R$ the number of objects in the left/right child cell&#xD;&#xA; - $t_i$ the cost of object intersection (which is also an arbitrary&#xD;&#xA;   constant)&#xD;&#xA;&#xD;&#xA;However, the first hierarchy has 4 child cells, how would I calculate the cost here? Any tips on how to start this exercise would be very helpful.&#xD;&#xA;&#xD;&#xA;**EDIT:** Okay, so for the second and third setup, is it as simple as filling in the formula? For the second setup, this would lead to (assuming I made no numerical errors :) ):&#xD;&#xA;$$\begin{align*}Cost(cell) &amp;= C_t + \frac{2*3^2 + 4*3*1}{2*5^2 + 4*5*1} * 2 * t_i + \frac{2*3^2 + 4*3*1}{2*5^2 + 4*5*1} * 2 * t_i \\ &amp;= C_t + \frac{120}{70} * t_i \end{align*}$$&#xD;&#xA;&#xD;&#xA;For the third setup this would, analogously, lead to:&#xD;&#xA;$$Cost(cell) = C_t + \frac{88}{70}*t_i$$.&#xD;&#xA;&#xD;&#xA;**So now my question would boil down to: can I just do the same for the first setup, but instead evaluate 4 sub-cells? Also, am I correct in assuming $C_t$ and $t_i$ are fixed constants or do they depend on the setup?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IEBNK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17213" PostHistoryTypeId="2" PostId="6184" RevisionGUID="ab783515-6f55-4203-9073-c07ce27ef400" CreationDate="2018-01-29T11:45:02.767" UserId="2041" Text="You gave the formula as:&#xD;&#xA;&#xD;&#xA;$$Cost(cell) = C_t + \frac{S_L}{S_{Cell}} \times N_L \times t_i + \frac{S_R}{S_{Cell}} \times N_R \times t_i$$&#xD;&#xA;&#xD;&#xA;(You put $r_i$ at the right-hand end, but I assume that was a typo.) &#xD;&#xA;&#xD;&#xA;There's a more general form of this formula&#xD;&#xA;&#xD;&#xA;$$Cost(cell) = C_t + \sum_{k\ \in\ K} \frac{S_k}{S_{Cell}} \times N_k \times t_i$$&#xD;&#xA;&#xD;&#xA;where $K$ is the set of all child nodes; that is, to get back to the two-children form you started with, $K = \{L, R\}$.&#xD;&#xA;&#xD;&#xA;By generalising the formula like this, you can now calculate the cost for the first possibility the same way as the second two.&#xD;&#xA;&#xD;&#xA;You're right that this is a slightly odd question. In practice, your traversal cost is going to be less for a binary tree than a $(&gt; 2)$-ary tree.&#xD;&#xA;&#xD;&#xA;&gt;  - Does this ranking change if we change the spheres with a (scaled) tea-pot that still fits within the bounding volume?&#xD;&#xA;&#xD;&#xA;To answer this, you'll need to consider how this affects the surface area, and how this changes each score in turn.&#xD;&#xA;&#xD;&#xA;&gt;  - Can this ranking depend on the position of the camera, when we only    consider visibility rays (so no shadow rays, for example)? You can assume you're working with an orthographic camera.&#xD;&#xA;&#xD;&#xA;There's two things to consider here.&#xD;&#xA;&#xD;&#xA;1) Does any part of the heuristic depend on the position of the camera? Can moving the camera change any of the numbers that feed into the score?&#xD;&#xA;&#xD;&#xA;2) Moving the camera can change how the boxes overlap. Remember that rays that pass through the box need to be tested against the box behind, so needless overlaps make the structure worse.&#xD;&#xA;&#xD;&#xA;I think the point is that the heuristic is *only* a general rule. It's not hard to construct an example with two proposals *a* and *b*, where *a* scores much better but *b* is actually a better split for a particular camera, and this last part of the question is trying to get you to think about this." ContentLicense="CC BY-SA 3.0" />
  <row Id="17214" PostHistoryTypeId="5" PostId="6183" RevisionGUID="10c9ffad-09dc-4eb7-9640-c14ee3b3ef11" CreationDate="2018-01-29T19:41:09.203" UserId="8108" Comment="typo" Text="My professor gave me the following example exam question:&#xD;&#xA;&#xD;&#xA;&gt; Given 4 spheres with diameter = 1. Their centers are located on&#xD;&#xA;&gt; coordinates (2,4,0), (4,2,0), (4,6,0) and (6,4,0), as seen in the&#xD;&#xA;&gt; picture below. Three different hierarchies of tightest possible&#xD;&#xA;&gt; axis-aligned bounding volumes (AABB) are given:&#xD;&#xA;&gt; &#xD;&#xA;&gt;  - A single AABB around every sphere&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (4,2,0) and    another around the spheres located at (4,6,0) and (6,4,0).&#xD;&#xA;&gt;  - An AABB around the spheres with center (2,4,0) and (6,4,0) and    another around the spheres located at (4,2,0) and (4,6,0).&#xD;&#xA;&gt; &#xD;&#xA;&gt; For every one of these the all-containing AABB is constructed.&#xD;&#xA;&#xD;&#xA;[![Assignment][1]][1]&#xD;&#xA;&#xD;&#xA;The questions are:&#xD;&#xA;&#xD;&#xA;&gt;  - Rank these 3 structures based on efficiency for intersecting a ray    with these spheres (best to worst)&#xD;&#xA;&gt;  - Does this ranking change if we change the spheres with a (scaled) tea-pot that still fits within the bounding volume?&#xD;&#xA;&gt;  - Can this ranking depend on the position of the camera, when we only    consider visibility rays (so no shadow rays, for example)? You can assume you're working with an orthographic camera.&#xD;&#xA;&#xD;&#xA;He insisted on not giving a 'philosophical' answer (like: 'this depends on ...') but rather actually calculating the cost using the surface are heuristic etc.&#xD;&#xA;&#xD;&#xA;Only, I have no idea how to start. The cost function we have seen is defined as follows&#xD;&#xA;$$Cost(cell) = C_t + \frac{S_L}{S_{Cell}} \times N_L \times t_i + \frac{S_R}{S_{Cell}} \times N_R \times t_i$$&#xD;&#xA;With:&#xD;&#xA;&#xD;&#xA; - $C_t$ the cost of traversal (which is an arbitrary constant, I think)&#xD;&#xA; - $S_L$/$S_R$ the surface area of the left/right child cell&#xD;&#xA; - $S_{cell}$ the surface area of the entire cell&#xD;&#xA; - $N_L$/$N_R$ the number of objects in the left/right child cell&#xD;&#xA; - $t_i$ the cost of object intersection (which is also an arbitrary&#xD;&#xA;   constant)&#xD;&#xA;&#xD;&#xA;However, the first hierarchy has 4 child cells, how would I calculate the cost here? Any tips on how to start this exercise would be very helpful.&#xD;&#xA;&#xD;&#xA;**EDIT:** Okay, so for the second and third setup, is it as simple as filling in the formula? For the second setup, this would lead to (assuming I made no numerical errors :) ):&#xD;&#xA;$$\begin{align*}Cost(cell) &amp;= C_t + \frac{2*3^2 + 4*3*1}{2*5^2 + 4*5*1} * 2 * t_i + \frac{2*3^2 + 4*3*1}{2*5^2 + 4*5*1} * 2 * t_i \\ &amp;= C_t + \frac{120}{70} * t_i \end{align*}$$&#xD;&#xA;&#xD;&#xA;For the third setup this would, analogously, lead to:&#xD;&#xA;$$Cost(cell) = C_t + \frac{88}{70}*t_i$$.&#xD;&#xA;&#xD;&#xA;**So now my question would boil down to: can I just do the same for the first setup, but instead evaluate 4 sub-cells? Also, am I correct in assuming $C_t$ and $t_i$ are fixed constants or do they depend on the setup?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IEBNK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17215" PostHistoryTypeId="2" PostId="6185" RevisionGUID="4e255706-0ffe-4349-a40c-b85007ccb90c" CreationDate="2018-01-30T05:59:28.620" UserId="3003" Text="I've not done this, but it seems like you could keep a store of a single image and update it with each new image you receive. For example, you capture the first image and project it onto the scene. It likely won't cover the entire scene. &#xD;&#xA;&#xD;&#xA;When you capture the next image, assuming it's not from exactly the same place as the previous, you can combine it with the first image by mixing them 50/50. When you get the next image, you want to mix the existing image at 66.666% and the new image at 33.333%, etc.&#xD;&#xA;&#xD;&#xA;So I think you'd need to keep the combined image, and a second image that is the count of how many images have covered each pixel. Then:&#xD;&#xA;&#xD;&#xA;    for each pixel in the output that the new projection covers {&#xD;&#xA;        existing_pixel = current pixel in the existing image&#xD;&#xA;        num_pixels_mixed = current pixel in the image containing the count of images&#xD;&#xA;        new_pixel = current pixel in the newly acquired image&#xD;&#xA;        mix_amount = num_pixels_mixed / (num_pixels_mixed + 1)&#xD;&#xA;        resulting_pixel = mix_amount * existing_pixel + (1 - mix_amount) * new_pixel&#xD;&#xA;        increment the current pixel in the image containing the count of images&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17216" PostHistoryTypeId="2" PostId="6186" RevisionGUID="a62d2f2f-bcb1-4cf8-91eb-9eab2cdd2815" CreationDate="2018-01-30T07:59:20.310" UserId="8115" Text="I guess most of you are familiar with environment maps, they represent distant lighting distribution, and are used to render objects given their BRDF or SVBRDF distribution. Many papers map the spherical environment maps to 2D representation via a octahedron as described by [Spherical parametrization and remeshing (E Praun - ‎2003)](http://hhoppe.com/sphereparam.pdf). Wavelet transform is applied on 2D representation, for the resultant sparsity in representation. Is there a code available for Domain to sphere mapping described in the above paper. If not anyone can help explaining me the implementation. &#xD;&#xA;&#xD;&#xA;Here are few doubts I have about the paper. The mapping from Domain to Sphere according to the paper is done the same way Sphere to Mesh parameterization is done, that is (according to what I have understood), the Domain (octahedron) is reduced to a tetrahedron using a progressive mesh favouring triangles with good aspect ratio (described in section 3.5), then progressively they apply vertex split transformation and optimize the vertex positions around the inserted vertex. This doesn't make sense to me because they could directly fit a octahedron to a sphere ( as it is also an regular polygon) rather than reducing to tetrahedron. &#xD;&#xA;&#xD;&#xA;Another doubt I have is how they calculate the inverse function's Jacobin (mentioned in 3.4). They say that estimate it from the stretch calculated from the planar approximation of circular triangles.&#xD;&#xA;&#xD;&#xA;I think there aught to be an implementation of this spherical parameterization to 2D in internet because alot of people have used to parameterize environment maps.&#xD;&#xA;&#xD;&#xA;Thanks :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17217" PostHistoryTypeId="1" PostId="6186" RevisionGUID="a62d2f2f-bcb1-4cf8-91eb-9eab2cdd2815" CreationDate="2018-01-30T07:59:20.310" UserId="8115" Text="Octahedral mapping for Spherical functions" ContentLicense="CC BY-SA 3.0" />
  <row Id="17218" PostHistoryTypeId="3" PostId="6186" RevisionGUID="a62d2f2f-bcb1-4cf8-91eb-9eab2cdd2815" CreationDate="2018-01-30T07:59:20.310" UserId="8115" Text="|transformations|mesh|global-illumination|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17219" PostHistoryTypeId="50" PostId="4361" RevisionGUID="8495b17b-b6a9-491f-b71c-e0f1586a5864" CreationDate="2018-01-30T11:51:10.117" UserId="-1" />
  <row Id="17220" PostHistoryTypeId="2" PostId="6187" RevisionGUID="11a94976-a93a-4908-bd54-96134a586207" CreationDate="2018-01-30T14:53:45.637" UserId="8116" Text="In my class I often need to work with color map images. I would show the image and try to make inferences/observations about different subjects. Often times I need to actually quantify some aspects, but it is always very approximate and somehow vague because the images are provided &quot;as is&quot; and I do not necessarily know their content a priori.&#xD;&#xA;&#xD;&#xA;Let's imagine I'm working with two images (*). Is it possible to indicate the computer **&quot;learn&quot; the color scale** bar so I can **click at any point** in the map and get the **value of altitude at that point**? Image 1 is a discrete color scale bar, while Image 2 has a continuous color mapping. I included both examples because maybe there are differences in the approach of how to do this.&#xD;&#xA;&#xD;&#xA;So, is there a software/way to do this? Preferably open source. I tried ImageJ and couldn't come up with a decent solution.&#xD;&#xA;&#xD;&#xA;(*) Image 1: https://upload.wikimedia.org/wikipedia/commons/2/24/AYool_topography_15min.png&#xD;&#xA;&#xD;&#xA;(*) Image 2: http://topocreator.com/ned-jpg/city_a/600/co.jpg&#xD;&#xA;&#xD;&#xA;As you can see, the color scale is part of the image in all cases.&#xD;&#xA;&#xD;&#xA;(*) I do not own any of these images, just examples I found online to illustrate my point.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17221" PostHistoryTypeId="1" PostId="6187" RevisionGUID="11a94976-a93a-4908-bd54-96134a586207" CreationDate="2018-01-30T14:53:45.637" UserId="8116" Text="Can I get numeric data from a color map?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17222" PostHistoryTypeId="3" PostId="6187" RevisionGUID="11a94976-a93a-4908-bd54-96134a586207" CreationDate="2018-01-30T14:53:45.637" UserId="8116" Text="|image-processing|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17223" PostHistoryTypeId="2" PostId="6188" RevisionGUID="2ebc6c2f-ebe1-4396-8714-cfa5386e9c83" CreationDate="2018-01-30T16:24:46.963" UserId="7724" Text="I don't know of any software that could do this for you. However, it should be possible to reverse engineer the colour map to create a kind of look-up table structure. &#xD;&#xA;&#xD;&#xA;First, take a one pixel wide column (or row) of the colour map and store this as an array of colour values. Then, create a secondary array, for the data/altitude values, of the same length. Try to mark to the best of you ability the marked values of the colour map on this second array. A simple solution would be to also take a pixel wide column (or row) featuring the markings of the colour map to get the exact one-to-one pixel correspondence. Now you have a secondary array containing the marked off values and the rest of the values can be filled in by figuring out the step size of the colour map. The step size would be the difference in absolute value between subsequent markings divided by the number of pixels between these same markings.&#xD;&#xA;&#xD;&#xA;Now when you read a colour from the mapped figure you can look up the colour in the colour array and use the index of this value to look up the altitude in the secondary array." ContentLicense="CC BY-SA 3.0" />
  <row Id="17224" PostHistoryTypeId="2" PostId="6189" RevisionGUID="1fe97944-660d-4384-9063-c04545106f9b" CreationDate="2018-01-30T18:10:46.643" UserId="6760" Text="I am currently building a pathtracer, which has support for vertex normals and face normals.&#xD;&#xA;&#xD;&#xA;There seems to be an issue when it comes to rendering objects with triangles exported from Blender. Regardless of how I calculate the normal, the result always shows inconsistent shading of triangles. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The shading seems to change per triangle, with the ones more aligned to the camera being correct. It seems to depend on where the objects are in the scene relative to the camera. Below is the intersection algorithm for the triangle.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;    bool Triangle::intersection(Ray &amp;ray, HitInfo &amp;hit)&#xD;&#xA;    {&#xD;&#xA;        float3 edge1 = v1-&gt;pos - v0-&gt;pos;&#xD;&#xA;        float3 edge2 = v2-&gt;pos - v0-&gt;pos;&#xD;&#xA;        &#xD;&#xA;        float3 h = ray.getDirection().cross(edge2);&#xD;&#xA;        float a = edge1.dot(h);&#xD;&#xA;        &#xD;&#xA;        float f = 1.0 / a;&#xD;&#xA;        float3 s = ray.getOrigin() - v0-&gt;pos;&#xD;&#xA;        float u = f * (s.dot(h));&#xD;&#xA;        &#xD;&#xA;        if (u &lt; 0.0 || u &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float3 q = s.cross(edge1);&#xD;&#xA;        float v = f * ray.getDirection().dot(q);&#xD;&#xA;        if (v &lt; 0.0 || u + v &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float t = edge2.dot(q) * f;&#xD;&#xA;        if (t &gt; 1e-9 &amp;&amp; t &lt; ray.tmin)&#xD;&#xA;        {&#xD;&#xA;            hit.t = t;&#xD;&#xA;            float3 temp_normal = unit(edge2.cross(edge1)); //unit(v1-&gt;normal*u + v2-&gt;normal*v + v0-&gt;normal*(1. - u - v));&#xD;&#xA;            if (unit(ray.getDirection()).dot(temp_normal)&lt; 1e-9) temp_normal = temp_normal * (-1);&#xD;&#xA;            hit.normal = temp_normal;&#xD;&#xA;            return true;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            return false;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The intersection algorithm calculate the normal using the cross product of the edges, however using the normals provided by blender does not change much either.&#xD;&#xA;I use the Moller Trumbore intersection algorithm, exporting obj's from Blender (enabling &quot;keep vertex order&quot; doesn't change anything). I have also tried different materials but the problem still persists.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/53xUF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cWBqI.png&#xD;&#xA;&#xD;&#xA;If any more info is needed I will be happy to supply it, as I am completely stumped at this point.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17225" PostHistoryTypeId="1" PostId="6189" RevisionGUID="1fe97944-660d-4384-9063-c04545106f9b" CreationDate="2018-01-30T18:10:46.643" UserId="6760" Text="Inconsistent shading in pathtraced image" ContentLicense="CC BY-SA 3.0" />
  <row Id="17226" PostHistoryTypeId="3" PostId="6189" RevisionGUID="1fe97944-660d-4384-9063-c04545106f9b" CreationDate="2018-01-30T18:10:46.643" UserId="6760" Text="|raytracing|pathtracing|shading|normal-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17227" PostHistoryTypeId="2" PostId="6190" RevisionGUID="51c7f2bd-5d6e-499f-b82b-21b017945dce" CreationDate="2018-01-30T21:24:42.060" UserId="48" Text="Your normal calculation looks backwards: `edge2.cross(edge1)`, but (assuming CCW winding) it should be edge1 × edge2.&#xD;&#xA;&#xD;&#xA;The sign flip for back facing normals is also reversed; the ray direction and triangle normal _should_ be facing in opposite directions, thus should have negative dot product, but it looks like you're flipping it to make the dot product always positive.&#xD;&#xA;&#xD;&#xA;Maybe there's another differing convention elsewhere in your shading code that accounts for this? In any case, I'm not sure this is actually related to your problem, but it jumped out at me as being odd." ContentLicense="CC BY-SA 3.0" />
  <row Id="17229" PostHistoryTypeId="5" PostId="6189" RevisionGUID="81f51a87-24b4-4f2e-86fe-0b9bf4ac60b6" CreationDate="2018-01-31T09:38:16.093" UserId="6760" Comment="added 232 characters in body" Text="I am currently building a pathtracer, which has support for vertex normals and face normals.&#xD;&#xA;&#xD;&#xA;There seems to be an issue when it comes to rendering objects with triangles exported from Blender. Regardless of how I calculate the normal, the result always shows inconsistent shading of triangles. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The shading seems to change per triangle, with the ones more aligned to the camera being correct. It seems to depend on where the objects are in the scene relative to the camera. Below is the intersection algorithm for the triangle.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;    bool Triangle::intersection(Ray &amp;ray, HitInfo &amp;hit)&#xD;&#xA;    {&#xD;&#xA;        float3 edge1 = v1-&gt;pos - v0-&gt;pos;&#xD;&#xA;        float3 edge2 = v2-&gt;pos - v0-&gt;pos;&#xD;&#xA;        &#xD;&#xA;        float3 h = ray.getDirection().cross(edge2);&#xD;&#xA;        float a = edge1.dot(h);&#xD;&#xA;        &#xD;&#xA;        float f = 1.0 / a;&#xD;&#xA;        float3 s = ray.getOrigin() - v0-&gt;pos;&#xD;&#xA;        float u = f * (s.dot(h));&#xD;&#xA;        &#xD;&#xA;        if (u &lt; 0.0 || u &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float3 q = s.cross(edge1);&#xD;&#xA;        float v = f * ray.getDirection().dot(q);&#xD;&#xA;        if (v &lt; 0.0 || u + v &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float t = edge2.dot(q) * f;&#xD;&#xA;        if (t &gt; 1e-9 &amp;&amp; t &lt; ray.tmin)&#xD;&#xA;        {&#xD;&#xA;            hit.t = t;&#xD;&#xA;            float3 temp_normal = unit(edge2.cross(edge1)); //unit(v1-&gt;normal*u + v2-&gt;normal*v + v0-&gt;normal*(1. - u - v));&#xD;&#xA;            if (unit(ray.getDirection()).dot(temp_normal)&lt; 1e-9) temp_normal = temp_normal * (-1);&#xD;&#xA;            hit.normal = temp_normal;&#xD;&#xA;            return true;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            return false;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The intersection algorithm calculate the normal using the cross product of the edges, however using the normals provided by blender does not change much either.&#xD;&#xA;I use the Moller Trumbore intersection algorithm, exporting obj's from Blender (enabling &quot;keep vertex order&quot; doesn't change anything). I have also tried different materials but the problem still persists.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The above image is the normals being rendered with an emissive shader. This is the result I would expect, so I don't think this is the issue.&#xD;&#xA;&#xD;&#xA;If any more info is needed I will be happy to supply it, as I am completely stumped at this point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/53xUF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cWBqI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ckLDl.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17230" PostHistoryTypeId="5" PostId="6189" RevisionGUID="61f4e781-343d-4aa2-b998-b1817a86a6b3" CreationDate="2018-01-31T09:55:38.263" UserId="6760" Comment="edited body" Text="I am currently building a pathtracer, which has support for vertex normals and face normals.&#xD;&#xA;&#xD;&#xA;There seems to be an issue when it comes to rendering objects with triangles exported from Blender. Regardless of how I calculate the normal, the result always shows inconsistent shading of triangles. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The shading seems to change per triangle, with the ones more aligned to the camera being correct. It seems to depend on where the objects are in the scene relative to the camera. Below is the intersection algorithm for the triangle.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;    bool Triangle::intersection(Ray &amp;ray, HitInfo &amp;hit)&#xD;&#xA;    {&#xD;&#xA;        float3 edge1 = v1-&gt;pos - v0-&gt;pos;&#xD;&#xA;        float3 edge2 = v2-&gt;pos - v0-&gt;pos;&#xD;&#xA;        &#xD;&#xA;        float3 h = ray.getDirection().cross(edge2);&#xD;&#xA;        float a = edge1.dot(h);&#xD;&#xA;        &#xD;&#xA;        float f = 1.0 / a;&#xD;&#xA;        float3 s = ray.getOrigin() - v0-&gt;pos;&#xD;&#xA;        float u = f * (s.dot(h));&#xD;&#xA;        &#xD;&#xA;        if (u &lt; 0.0 || u &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float3 q = s.cross(edge1);&#xD;&#xA;        float v = f * ray.getDirection().dot(q);&#xD;&#xA;        if (v &lt; 0.0 || u + v &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float t = edge2.dot(q) * f;&#xD;&#xA;        if (t &gt; 1e-9 &amp;&amp; t &lt; ray.tmin)&#xD;&#xA;        {&#xD;&#xA;            hit.t = t;&#xD;&#xA;            float3 temp_normal = unit(edge2.cross(edge1)); //unit(v1-&gt;normal*u + v2-&gt;normal*v + v0-&gt;normal*(1. - u - v));&#xD;&#xA;            if (unit(ray.getDirection()).dot(temp_normal)&lt; 1e-9) temp_normal = temp_normal * (-1);&#xD;&#xA;            hit.normal = temp_normal;&#xD;&#xA;            return true;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            return false;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The intersection algorithm calculate the normal using the cross product of the edges, however using the normals provided by blender does not change much either.&#xD;&#xA;I use the Moller Trumbore intersection algorithm, exporting obj's from Blender (enabling &quot;keep vertex order&quot; doesn't change anything). I have also tried different materials but the problem still persists.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The above image is the normals being rendered with an emissive shader. This is the result I would expect, so I don't think this is the issue.&#xD;&#xA;&#xD;&#xA;If any more info is needed I will be happy to supply it, as I am completely stumped at this point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/53xUF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cWBqI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PWyxJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17231" PostHistoryTypeId="2" PostId="6191" RevisionGUID="c98e5733-22d2-43ff-b949-0136cfcc6e9f" CreationDate="2018-01-31T15:24:33.433" UserId="8112" Text="I want to insert a logo into an RGB image with proper 3D transformations. I can get the estimated pixel normals of this image using the code here: https://github.com/yindaz/surface_normal. Pixel normals are encoded into RGB channels as described as follows:&#xD;&#xA;&#xD;&#xA;&gt; The estimated normal will be saved in 16-bit PNG format, where 0-65535 in R,G,B channel correspond to [-1, 1] for the X,Y,Z component of the normal vector. We use the camera coordinates defined as - X points to the camera right, Y points to the camera forward, and Z points to the camera upward. For example, right facing wall are very red, floor are very blue, and you rarely see green as it's parallel to the camera viewing direction.&#xD;&#xA;&#xD;&#xA;How can I transform the 2D logo to put it onto a planar surface in the image? I have tried to calculate the rotation angles of the normal to rotate it so that it has the same direction as the camera normal, and rotate the logo according to these angles, but I have no success so far.&#xD;&#xA;&#xD;&#xA;As far as I understand from the quote above, normal of the untransformed logo should be (x:0, y:-1, z:0) and let the pixel normal be (x:a, y:b, z:c) with magnitude M. I rotate the logo around X by arccos(a/M)*180/pi, around Y by arccos(b/M)*180/pi, around Z by arccos(c/M)*180/pi, and if b &lt; 0 rotate around Y by an additional 180 degrees.&#xD;&#xA;&#xD;&#xA;Is there anything reasonable in these? Is it possible that I can do this using the estimated normals?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17232" PostHistoryTypeId="1" PostId="6191" RevisionGUID="c98e5733-22d2-43ff-b949-0136cfcc6e9f" CreationDate="2018-01-31T15:24:33.433" UserId="8112" Text="Image warping using pixel normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="17233" PostHistoryTypeId="3" PostId="6191" RevisionGUID="c98e5733-22d2-43ff-b949-0136cfcc6e9f" CreationDate="2018-01-31T15:24:33.433" UserId="8112" Text="|transformations|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17234" PostHistoryTypeId="5" PostId="6189" RevisionGUID="a61c7359-a15b-4a38-b8e5-705eaf969115" CreationDate="2018-01-31T16:14:53.457" UserId="6760" Comment="added 1001 characters in body" Text="I am currently building a pathtracer, which has support for vertex normals and face normals.&#xD;&#xA;&#xD;&#xA;There seems to be an issue when it comes to rendering objects with triangles exported from Blender. Regardless of how I calculate the normal, the result always shows inconsistent shading of triangles. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The shading seems to change per triangle, with the ones more aligned to the camera being correct. It seems to depend on where the objects are in the scene relative to the camera. Below is the intersection algorithm for the triangle.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;    bool Triangle::intersection(Ray &amp;ray, HitInfo &amp;hit)&#xD;&#xA;    {&#xD;&#xA;        float3 edge1 = v1-&gt;pos - v0-&gt;pos;&#xD;&#xA;        float3 edge2 = v2-&gt;pos - v0-&gt;pos;&#xD;&#xA;        &#xD;&#xA;        float3 h = ray.getDirection().cross(edge2);&#xD;&#xA;        float a = edge1.dot(h);&#xD;&#xA;        &#xD;&#xA;        float f = 1.0 / a;&#xD;&#xA;        float3 s = ray.getOrigin() - v0-&gt;pos;&#xD;&#xA;        float u = f * (s.dot(h));&#xD;&#xA;        &#xD;&#xA;        if (u &lt; 0.0 || u &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float3 q = s.cross(edge1);&#xD;&#xA;        float v = f * ray.getDirection().dot(q);&#xD;&#xA;        if (v &lt; 0.0 || u + v &gt; 1.0)&#xD;&#xA;            return false;&#xD;&#xA;        &#xD;&#xA;        float t = edge2.dot(q) * f;&#xD;&#xA;        if (t &gt; 1e-9 &amp;&amp; t &lt; ray.tmin)&#xD;&#xA;        {&#xD;&#xA;            hit.t = t;&#xD;&#xA;            float3 temp_normal = unit(edge2.cross(edge1)); //unit(v1-&gt;normal*u + v2-&gt;normal*v + v0-&gt;normal*(1. - u - v));&#xD;&#xA;            if (unit(ray.getDirection()).dot(temp_normal)&lt; 1e-9) temp_normal = temp_normal * (-1);&#xD;&#xA;            hit.normal = temp_normal;&#xD;&#xA;            return true;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            return false;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The intersection algorithm calculate the normal using the cross product of the edges, however using the normals provided by blender does not change much either.&#xD;&#xA;I use the Moller Trumbore intersection algorithm, exporting obj's from Blender (enabling &quot;keep vertex order&quot; doesn't change anything). I have also tried different materials but the problem still persists.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The above image is the normals being rendered with an emissive shader. This is the result I would expect, so I don't think this is the issue.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;    float3 cosineSampleHemi(float u1, float u2)&#xD;&#xA;    {&#xD;&#xA;        float z = std::pow(1.0 - u1, 3.0 / 5.0);&#xD;&#xA;        float phi = 2.0 * M_PI * u2;&#xD;&#xA;        float theta = sqrt(std::max(0.0, 1.0 - z * z));&#xD;&#xA;        float x = theta * cos(phi);&#xD;&#xA;        float y = theta * sin(phi);&#xD;&#xA;        &#xD;&#xA;        return float3(x, y, z);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    float3 random_in_unit_sphere() {&#xD;&#xA;        float3 p;&#xD;&#xA;        do {&#xD;&#xA;            p = float3(drand48(),drand48(),drand48())*2.0 - float3(1.0);&#xD;&#xA;        } while (p.dot(p) &gt;= 1.0);&#xD;&#xA;        return p;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The above code is for the sampling, I have tried both functions and it produces similar results. Below is the lambertian scatter function, which uses the hemisphere sampling methods.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    bool Lambertian::scatter(Ray &amp;ray, HitInfo &amp;hit, float3 &amp;attenuation, Ray &amp;new_ray) const&#xD;&#xA;    {&#xD;&#xA;        new_ray = Ray(ray.getHit(hit.t), cosineSampleHemi(drand48(), drand48()));&#xD;&#xA;        attenuation = m_colour;&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If any more info is needed I will be happy to supply it, as I am completely stumped at this point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/53xUF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cWBqI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PWyxJ.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17235" PostHistoryTypeId="2" PostId="6192" RevisionGUID="ec2069e4-9fa0-4e1f-9db3-91564d879f83" CreationDate="2018-01-31T17:35:15.170" UserId="6760" Text="I have managed to fix the error. It turns out the error was never situated in the normal calulation it was the shading algorith. The floating point precision error caused the new ray to be slightly below the surface, which meant it would intersect itself and become darker. This is a problem common in biased raytracers, the phenomenon known as &quot;Shadow acne&quot;.&#xD;&#xA;&#xD;&#xA;To fix it I added the following code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    bool Lambertian::scatter(Ray &amp;ray, HitInfo &amp;hit, float3 &amp;attenuation, Ray &amp;new_ray) const&#xD;&#xA;    {&#xD;&#xA;        float3 offset = hit.normal*(1e-5);&#xD;&#xA;        new_ray = Ray(ray.getHit(hit.t) + offset, cosineSampleHemi(drand48(), drand48()));&#xD;&#xA;        attenuation = m_colour;&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the offset variable moves the ray origin to slightly above the surface by a small amount and that seems to fix the issue." ContentLicense="CC BY-SA 3.0" />
  <row Id="17236" PostHistoryTypeId="2" PostId="6193" RevisionGUID="0cff64bc-3804-42d8-93b3-6bc4ab6a9f8c" CreationDate="2018-01-31T19:54:01.317" UserId="8125" Text="[@notch][1] has recently been posting on an engine he is developing. He claims that it is voxel-based and supports deformable terrain, with a render distance of almost 1000 000 voxels and real-time reflections, [running at 99fps in WebGL][2]. Even with heavy LOD reduction, such a thing sounds too good to be true. He has not published any source code as of now, so does anyone have an idea how this is done? Is it just many small optimizations or could this be a new approach to real time 3D?&#xD;&#xA;&#xD;&#xA;  [1]: https://twitter.com/notch?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor%22@notch%22&#xD;&#xA;  [2]:https://twitter.com/notch/status/952333638028398592" ContentLicense="CC BY-SA 3.0" />
  <row Id="17237" PostHistoryTypeId="1" PostId="6193" RevisionGUID="0cff64bc-3804-42d8-93b3-6bc4ab6a9f8c" CreationDate="2018-01-31T19:54:01.317" UserId="8125" Text="How does notch's new graphics engine work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17238" PostHistoryTypeId="3" PostId="6193" RevisionGUID="0cff64bc-3804-42d8-93b3-6bc4ab6a9f8c" CreationDate="2018-01-31T19:54:01.317" UserId="8125" Text="|webgl|optimisation|reflection|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17239" PostHistoryTypeId="5" PostId="6193" RevisionGUID="815d0047-d42b-43f5-a55c-ac12597755b2" CreationDate="2018-01-31T20:00:37.600" UserId="8125" Comment="added 146 characters in body" Text="[@notch][1] has recently been posting on an engine he is developing. He claims that it is voxel-based and supports deformable terrain, with a render distance of almost 1000 000 voxels and real-time reflections, [running at 99fps in WebGL][2]. Even with heavy LOD reduction, such a thing sounds too good to be true. He has not published any source code as of now, so does anyone have an idea how this is done? Is it just many small optimizations or could this be a new approach to real time 3D?&#xD;&#xA;&#xD;&#xA;EDIT: He also mentions a &quot;[signed density field][3]&quot;. What does that mean exactly?&#xD;&#xA;&#xD;&#xA;  [1]: https://twitter.com/notch?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor%22@notch%22&#xD;&#xA;  [2]:https://twitter.com/notch/status/952333638028398592&#xD;&#xA;  [3]: https://twitter.com/notch/status/952104406157332481" ContentLicense="CC BY-SA 3.0" />
  <row Id="17240" PostHistoryTypeId="2" PostId="6194" RevisionGUID="ffe03984-2cf8-4614-ab90-1402e2693615" CreationDate="2018-01-31T21:43:05.873" UserId="5703" Text="Notch's engine most likely works using volume raymarching in a volume field. This means that you shoot rays that move a certain distance and check whether they are inside and object or not. Once they are, they return the position of the colission and some other data.&#xD;&#xA;&#xD;&#xA;You can either advance rays by a set amount per step until you hit something or refine the final collision position by doing a binary search along the last walked ray segment once you hit something. Both of these aproaches have the problem that they can overshoot, missing small geometry, or take a large amount of steps to traverse empty space where there is no geometry to hit.&#xD;&#xA;&#xD;&#xA;Binary search can add precision and reduce overshoots somewhat but comes at an extra runtime cost for doing a binary search per ray.&#xD;&#xA;&#xD;&#xA;Signed distance fields are essentially 3d arrays  tell you how far away from any surface you are. This allows you to do raymarching with ray step sizes equal to that number and being sure that you wont overshoot, as well as stepping through large empty spaces quite quickly. This greatly enhances performance and reduces overshoots from a regular step size or binary search based approach.&#xD;&#xA;&#xD;&#xA;This last technique trades off runtime speed for precompute time and extra memory. So it is not always adequate for rendering exteriors or large scenes. Its memory usage an runtime speed can be further improved by using a hierachical data structure that gets re built every so often with more detail and data density near the camera and less further away from it.&#xD;&#xA;&#xD;&#xA;EDIT: Oh it seems i misread density for distance" ContentLicense="CC BY-SA 3.0" />
  <row Id="17241" PostHistoryTypeId="5" PostId="6194" RevisionGUID="7eb8c6dc-f562-44ec-b2e8-0698f4b0d811" CreationDate="2018-01-31T22:09:05.220" UserId="5703" Comment="added 279 characters in body" Text="Notch's engine most likely works using volume raymarching in a volume field. This means that you shoot rays that move a certain distance and check whether they are inside and object or not. Once they are, they return the position of the colission and some other data.&#xD;&#xA;&#xD;&#xA;You can either advance rays by a set amount per step until you hit something or refine the final collision position by doing a binary search along the last walked ray segment once you hit something. Both of these aproaches have the problem that they can overshoot, missing small geometry, or take a large amount of steps to traverse empty space where there is no geometry to hit.&#xD;&#xA;&#xD;&#xA;Binary search can add precision and reduce overshoots somewhat but comes at an extra runtime cost for doing a binary search per ray.&#xD;&#xA;&#xD;&#xA;Signed distance fields are essentially 3d arrays  tell you how far away from any surface you are. This allows you to do raymarching with ray step sizes equal to that number and being sure that you wont overshoot, as well as stepping through large empty spaces quite quickly. This greatly enhances performance and reduces overshoots from a regular step size or binary search based approach.&#xD;&#xA;&#xD;&#xA;This last technique trades off runtime speed for precompute time and extra memory. So it is not always adequate for rendering exteriors or large scenes. Its memory usage an runtime speed can be further improved by using a hierachical data structure that gets re built every so often with more detail and data density near the camera and less further away from it.&#xD;&#xA;&#xD;&#xA;EDIT: Oh it seems i misread density for distance&#xD;&#xA;&#xD;&#xA;I really have no idea what a signed density field is. I've never heardthe term before. A quick goolge search throws results that talk about signed distance fields. I would guess it was either a mistake to write that, some obscure tech or something that Notch made up himself." ContentLicense="CC BY-SA 3.0" />
  <row Id="17242" PostHistoryTypeId="2" PostId="6195" RevisionGUID="b5698b45-0d60-4ce9-a41c-f935cd99da28" CreationDate="2018-02-01T01:15:16.627" UserId="7000" Text="I am trying to understand when it makes sense to use the `glDrawRangeElements ` function.&#xD;&#xA;&#xD;&#xA;The OpenGL wiki says:&#xD;&#xA;&gt; for optimization purposes, it is useful for implementations to know the range of indexed rendering data&#xD;&#xA;&#xD;&#xA;So, as I interpret it, if I had one large buffer (containing say, multiple meshes' data) and I was planning to call `glDrawRangeElements` if I instead specify the minimum and maximum index values that this call will use, I could achieve a speedup.&#xD;&#xA;&#xD;&#xA;**Is this a correct use case for `glDrawRangeElements`?**&#xD;&#xA;&#xD;&#xA;It seems like I would almost always know the minimum and maximum index values (because I would know ahead of time what I am going to draw) so it seems like `glDrawRangeElements` should be just a drop in replacement for `glDrawElements`.&#xD;&#xA;&#xD;&#xA;However, [this answer][1] implies that `glDrawRangeElements` might actually be slower.&#xD;&#xA;&#xD;&#xA;So, **what are the pros and cons of using glDrawRangeElements?**&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/a/116838/77716" ContentLicense="CC BY-SA 3.0" />
  <row Id="17243" PostHistoryTypeId="1" PostId="6195" RevisionGUID="b5698b45-0d60-4ce9-a41c-f935cd99da28" CreationDate="2018-02-01T01:15:16.627" UserId="7000" Text="When does it make sense to use drawRangeElements" ContentLicense="CC BY-SA 3.0" />
  <row Id="17244" PostHistoryTypeId="3" PostId="6195" RevisionGUID="b5698b45-0d60-4ce9-a41c-f935cd99da28" CreationDate="2018-02-01T01:15:16.627" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17246" PostHistoryTypeId="2" PostId="6196" RevisionGUID="6958262b-11e6-4c29-8a5d-3c1f7098d1cb" CreationDate="2018-02-01T06:19:35.653" UserId="7008" Text="You can combine Oren-Nayar with GGX, if your normalize the result. A BRDF is defined by two properties: Helmholtz reciprocity and energy conservation&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\begin{itemize}&#xD;&#xA;   \item f(l_i, l,_o) = f(l_o, l_i)&#xD;&#xA;   \item f(l_i, l_o) \leq 1&#xD;&#xA;\end{itemize}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Your Oren-Nayar is the diffuse part $f_d(l_i, l_o)$ and your GGX is your specular part $f_s(l_i, l_o)$. If both are energy conserving, tham bith are at most $1$, but combined they may be $\geq 1$ and here lies your problem. Oren-Nayar has been combined with specular terms before (see for example [The Rendering of Ryze from Crytek][http://www.crytek.com/download/2014_03_25_CRYENGINE_GDC_Schultz.pdf], you should have a look at how others did it. If you combine them, keep in mind, that you need two different roughness values. The one of Oren-Nayar and GGX don't match (which by the looks of it you know already) but neither can you convert from one to the other via an algorithm.&#xD;&#xA;&#xD;&#xA;A better solution imo is to use a different diffuse term. Have a look at the paper [Physically Based Shading at Disney by Brent Burley][https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf] and [PBR diffuse Lighting for GGX+Smith Microsurfaces by Earl Hammon Jr][https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX]. Physically Based Shading discusses several diffuse lighting BRDFs, including Oren-Nayar and then goes on to introduce an own diffuse BRDF which can use the same roughness value as GGX (be careful, as the roughness here is squared before using, iirc, because that was easier to use for artists). This resultinf BRDF is not energy conserving, which was accepted by the author, since&#xD;&#xA;&#xD;&#xA;&gt; This seems to provide a reasonable match to the MERL data and was also found to be artistically pleasing.&#xD;&#xA;&#xD;&#xA;A solution for this was introduced by [Sebastien Lagarde and Charles de Rousiers in Moving Frostbite to Physocally Based Rendering][https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf], they renormalized the entire BRDF.&#xD;&#xA;&#xD;&#xA;PBR diffuse Lighting for GGX+Smith Microsurfaces by Earl Hammon takes a different approach, he calculates an approximation like Oren and Nayar did, only he did it for GGX NDF and Smith shadowing/masking. Both the Disney Diffuse and Hammon's Diffuse BRDF can easily be comvined with the GGX specular term and are cisually more pleasinf than Lambert." ContentLicense="CC BY-SA 3.0" />
  <row Id="17247" PostHistoryTypeId="2" PostId="6197" RevisionGUID="fbfc78e3-13d5-4c98-b4b7-d22116aae4ed" CreationDate="2018-02-01T08:23:23.140" UserId="8130" Text="Maybe you should try to find Virtual Tangent Plane like in [Surface Normal In the Wild][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/abs/1704.02956" ContentLicense="CC BY-SA 3.0" />
  <row Id="17251" PostHistoryTypeId="5" PostId="6191" RevisionGUID="396e06a2-44a5-4ab0-8356-a3bb3b806fa8" CreationDate="2018-02-01T10:38:21.460" UserId="7989" Comment="improved formatting" Text="I want to insert a logo into an RGB image with proper 3D transformations. I can get the estimated pixel normals of this image using the code here: https://github.com/yindaz/surface_normal. Pixel normals are encoded into RGB channels as described as follows:&#xD;&#xA;&#xD;&#xA;&gt; The estimated normal will be saved in 16-bit PNG format, where 0-65535 in R,G,B channel correspond to [-1, 1] for the X,Y,Z component of the normal vector. We use the camera coordinates defined as - X points to the camera right, Y points to the camera forward, and Z points to the camera upward. For example, right facing wall are very red, floor are very blue, and you rarely see green as it's parallel to the camera viewing direction.&#xD;&#xA;&#xD;&#xA;How can I transform the 2D logo to put it onto a planar surface in the image? I have tried to calculate the rotation angles of the normal to rotate it so that it has the same direction as the camera normal, and rotate the logo according to these angles, but I have no success so far.&#xD;&#xA;&#xD;&#xA;As far as I understand from the quote above, normal of the untransformed logo should be $(x:0, y:-1, z:0)$ and let the pixel normal be $(x:a, y:b, z:c)$ with magnitude $M$. I rotate the logo around $X$ by $arccos(a/M)*180/pi$, around $Y$ by $arccos(b/M)*180/pi$, around $Z$ by $arccos(c/M)*180/pi$, and if $b &lt; 0$ rotate around $Y$ by an additional 180 degrees.&#xD;&#xA;&#xD;&#xA;Is there anything reasonable in these? Is it possible that I can do this using the estimated normals?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17252" PostHistoryTypeId="24" PostId="6191" RevisionGUID="396e06a2-44a5-4ab0-8356-a3bb3b806fa8" CreationDate="2018-02-01T10:38:21.460" Comment="Proposed by 7989 approved by 2041 edit id of 303" ContentLicense="CC BY-SA 3.0" />
  <row Id="17253" PostHistoryTypeId="5" PostId="6196" RevisionGUID="7efe5fe2-2daf-4d84-a420-777cf7bc3754" CreationDate="2018-02-01T10:39:19.520" UserId="7989" Comment="improved formatting" Text="You can combine Oren-Nayar with GGX, if your normalize the result. A BRDF is defined by two properties: Helmholtz reciprocity and energy conservation.&#xD;&#xA;&#xD;&#xA;$f(l_i, l,_o) = f(l_o, l_i)$&#xD;&#xA;&#xD;&#xA;$f(l_i, l_o) \leq 1$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your Oren-Nayar is the diffuse part $f_d(l_i, l_o)$ and your GGX is your specular part $f_s(l_i, l_o)$. If both are energy conserving, tham bith are at most $1$, but combined they may be $\geq 1$ and here lies your problem. Oren-Nayar has been combined with specular terms before (see for example [The Rendering of Ryze from Crytek][1], you should have a look at how others did it. If you combine them, keep in mind, that you need two different roughness values. The one of Oren-Nayar and GGX don't match (which by the looks of it you know already) but neither can you convert from one to the other via an algorithm.&#xD;&#xA;&#xD;&#xA;A better solution imo is to use a different diffuse term. Have a look at the paper [Physically Based Shading at Disney by Brent Burley][2] and [PBR diffuse Lighting for GGX+Smith Microsurfaces by Earl Hammon Jr. Physically][3] Based Shading discusses several diffuse lighting BRDFs, including Oren-Nayar and then goes on to introduce an own diffuse BRDF which can use the same roughness value as GGX (be careful, as the roughness here is squared before using, iirc, because that was easier to use for artists). This resultinf BRDF is not energy conserving, which was accepted by the author, since&#xD;&#xA;&#xD;&#xA;&gt; This seems to provide a reasonable match to the MERL data and was also found to be artistically pleasing.&#xD;&#xA;&#xD;&#xA;A solution for this was introduced by [Sebastien Lagarde and Charles de Rousiers in Moving Frostbite to Physocally Based Rendering][4], they renormalized the entire BRDF.&#xD;&#xA;&#xD;&#xA;PBR diffuse Lighting for GGX+Smith Microsurfaces by Earl Hammon takes a different approach, he calculates an approximation like Oren and Nayar did, only he did it for GGX NDF and Smith shadowing/masking. Both the Disney Diffuse and Hammon's Diffuse BRDF can easily be comvined with the GGX specular term and are cisually more pleasinf than Lambert.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.crytek.com/download/2014_03_25_CRYENGINE_GDC_Schultz.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf&#xD;&#xA;  [3]: https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX&#xD;&#xA;  [4]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="17254" PostHistoryTypeId="24" PostId="6196" RevisionGUID="7efe5fe2-2daf-4d84-a420-777cf7bc3754" CreationDate="2018-02-01T10:39:19.520" Comment="Proposed by 7989 approved by 2041 edit id of 302" ContentLicense="CC BY-SA 3.0" />
  <row Id="17255" PostHistoryTypeId="5" PostId="6187" RevisionGUID="613a3b46-0fc0-4497-b833-07a70e8c301a" CreationDate="2018-02-01T10:39:50.340" UserId="7989" Comment="improved formatting" Text="In my class I often need to work with color map images. I would show the image and try to make inferences/observations about different subjects. Often times I need to actually quantify some aspects, but it is always very approximate and somehow vague because the images are provided &quot;as is&quot; and I do not necessarily know their content a priori.&#xD;&#xA;&#xD;&#xA;Let's imagine I'm working with two images (*). Is it possible to indicate the computer **&quot;learn&quot; the color scale** bar so I can **click at any point** in the map and get the **value of altitude at that point**? Image 1 is a discrete color scale bar, while Image 2 has a continuous color mapping. I included both examples because maybe there are differences in the approach of how to do this.&#xD;&#xA;&#xD;&#xA;So, is there a software/way to do this? Preferably open source. I tried `ImageJ` and couldn't come up with a decent solution.&#xD;&#xA;&#xD;&#xA;Image 1:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Image 2:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the color scale is part of the image in all cases.&#xD;&#xA;&#xD;&#xA;(*) I do not own any of these images, just examples I found online to illustrate my point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ARuLS.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/fqCAE.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17256" PostHistoryTypeId="24" PostId="6187" RevisionGUID="613a3b46-0fc0-4497-b833-07a70e8c301a" CreationDate="2018-02-01T10:39:50.340" Comment="Proposed by 7989 approved by 4958, 2041 edit id of 305" ContentLicense="CC BY-SA 3.0" />
  <row Id="17258" PostHistoryTypeId="2" PostId="6199" RevisionGUID="2297efc2-04ba-4750-a541-55a322c8cf04" CreationDate="2018-02-01T15:34:50.167" UserId="2654" Text="The problem `glDrawRangeElements` was invented to fix was effectively removed by the advent of vertex buffers.&#xD;&#xA;&#xD;&#xA;What `glDrawRangeElements` allows the implementation to do is to know exactly what range of values will be used in the vertex arrays. Given that knowledge, they can read that range of values into a separate buffer, and then render from that buffer. Without knowing the range of indices, that wouldn't be possible, since an index list could pick from any index.&#xD;&#xA;&#xD;&#xA;But that's only useful if you're reading from *client memory*. Copying that range out of client memory allows you to render asynchronously. You copy out the values you know you need, issue a rendering command with that, and then return to the caller.&#xD;&#xA;&#xD;&#xA;If you're reading from buffer objects, this isn't a useful thing to do. And since core OpenGL doesn't even allow you the option of using client memory, the `Range` commands are no longer useful." ContentLicense="CC BY-SA 3.0" />
  <row Id="17259" PostHistoryTypeId="2" PostId="6200" RevisionGUID="5cd5ad25-5244-4838-a486-3346b03e54b4" CreationDate="2018-02-01T16:21:10.300" UserId="8118" Text="I'm working on an engine for Win32 exclusively. Can I safely assume that the flag VK_PRESENT_MODE_FIFO_KHR will always generate 2 and only 2 images for the swapchain? " ContentLicense="CC BY-SA 3.0" />
  <row Id="17260" PostHistoryTypeId="1" PostId="6200" RevisionGUID="5cd5ad25-5244-4838-a486-3346b03e54b4" CreationDate="2018-02-01T16:21:10.300" UserId="8118" Text="Vulkan: Swapchain image count with VK_PRESENT_MODE_FIFO_KHR" ContentLicense="CC BY-SA 3.0" />
  <row Id="17261" PostHistoryTypeId="3" PostId="6200" RevisionGUID="5cd5ad25-5244-4838-a486-3346b03e54b4" CreationDate="2018-02-01T16:21:10.300" UserId="8118" Text="|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17262" PostHistoryTypeId="2" PostId="6201" RevisionGUID="605f385c-7eb7-4721-91b7-7ad7ec0c781d" CreationDate="2018-02-01T16:43:15.797" UserId="2654" Text="There is nothing in Vulkan which guarantees or requires this. So even if it were a safe assumption *today* (if it were enforced by Windows in some way), all it would take would be one Windows update to break you.&#xD;&#xA;&#xD;&#xA;It's best to work with what you're given, even if what you're given may be more than you would prefer." ContentLicense="CC BY-SA 3.0" />
  <row Id="17267" PostHistoryTypeId="2" PostId="6203" RevisionGUID="62cc4e7b-c56e-49a0-8939-e533f831b2b6" CreationDate="2018-02-02T07:12:44.040" UserId="110" Text="Roughly speaking, what the Multisample Anti-Aliasing method does is:  &#xD;&#xA;&#xD;&#xA; - For each pixel in the image to render&#xD;&#xA;  - &quot;Split&quot; the pixel of a target image, usually in 2, 4, 8 or 16.   &#xD;&#xA;Actually this step is more: pick 2, 4, 8 or 16 locations (&quot;samples&quot;) inside the pixel  &#xD;&#xA;  - Compute the color that the image will have at each of those locations (sample or &quot;split part&quot;).  &#xD;&#xA;So instead of only computing the color that the image will have in that single pixel, we compute 2x, 4x, 8x or 16x times a similar value  &#xD;&#xA;  - Compute the average of all the 2, 4, 8 or 16 sample colors to decide the final color or the initial pixel&#xD;&#xA;&#xD;&#xA;You can see that Multisampling cost is proportional to the cost of computing one pixel's color in the image. Therefore it depends on the cost of shading.  &#xD;&#xA;It also depends on the number of pixels, i.e the resolution of the image.  &#xD;&#xA;  &#xD;&#xA;In the context of Ray-Tracing applications, this means that 2, 4, 8 or 16 times more rays will have to be computed.  &#xD;&#xA;  &#xD;&#xA;In the context of GPU-accelerated graphics computation, this means that 2, 4, 8 or 16 times more pixel shaders (&quot;fragment programs&quot;) will be executed.  &#xD;&#xA;※ GPU vendors probably implement optimization algorithms that make this cost lower than the theoretical value, however it is hard to find public documentation about these." ContentLicense="CC BY-SA 3.0" />
  <row Id="17269" PostHistoryTypeId="5" PostId="6203" RevisionGUID="04eb17b2-0c3b-47cf-96ff-c3f35c67337a" CreationDate="2018-02-02T09:40:46.430" UserId="110" Comment="added 984 characters in body" Text="Roughly speaking, what the **Supersampling Anti-Aliasing** method does is:  &#xD;&#xA;&#xD;&#xA; - For each pixel in the image to render&#xD;&#xA;  - &quot;Split&quot; the pixel of a target image, usually in 2, 4, 8 or 16.   &#xD;&#xA;Actually this step is more: pick the 2, 4, 8 or 16 locations (&quot;samples&quot;) inside the pixel  &#xD;&#xA;  - Compute the color that the image will have at each of those locations (sample or &quot;split part&quot;).  &#xD;&#xA;So instead of only computing the color that the image will have in that single pixel, we compute 2x, 4x, 8x or 16x times a similar value  &#xD;&#xA;  - Compute the average of all the 2, 4, 8 or 16 sample colors to decide the final color or the initial pixel&#xD;&#xA;&#xD;&#xA;You can see that Super-sampling cost is proportional to the cost of computing one pixel's color in the image. Therefore it depends on the cost of shading.  &#xD;&#xA;It also depends on the number of pixels, i.e the resolution of the image.  &#xD;&#xA;  &#xD;&#xA;In the context of Ray-Tracing applications, this means that 2, 4, 8 or 16 times more rays will have to be computed.  &#xD;&#xA;  &#xD;&#xA;In the context of GPU-accelerated graphics computation, this means that 2, 4, 8 or 16 times more pixel shaders (&quot;fragment programs&quot;) will be executed.  &#xD;&#xA;  &#xD;&#xA;------------------------------------&#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;Now roughly speaking, what the **Multisampling Anti-Aliasing** method does is:  &#xD;&#xA;  &#xD;&#xA; - For each pixel in the image to render&#xD;&#xA;  - Pick 2, 4, 8 or 16 locations (&quot;samples&quot;) inside the pixel     &#xD;&#xA;     - For each primitive (triangle) in the scene (actually, only for those that overlap the pixel):  &#xD;&#xA;         - Determine which of these samples are covered by the current triangle&#xD;&#xA;         - If there is at least one such sample, compute a single color of the contribution of that triangle to the pixel, and store it for each sample covered  &#xD;&#xA;The worse case happens if each sample is overlapped by a different triangle ;  in that case the color must be computed for each triangle&#xD;&#xA;   - Compute the average of all the gathered sample colors to decide the final color or the initial pixel&#xD;&#xA;&#xD;&#xA;You can see that evaluating the performance of Multisampling Anti-Aliasing is more complicated than that of Supersampling, since it also depends on the topology of the scene (the size and shape of the triangles)." ContentLicense="CC BY-SA 3.0" />
  <row Id="17270" PostHistoryTypeId="5" PostId="6199" RevisionGUID="97078041-2d94-45f3-b54f-cdc5d8ea0728" CreationDate="2018-02-02T13:40:46.433" UserId="137" Comment="it's about the index values being limited to a certain range which allows the optimistic copy" Text="The problem `glDrawRangeElements` was invented to fix was effectively removed by the advent of vertex buffers.&#xD;&#xA;&#xD;&#xA;What `glDrawRangeElements` allows the implementation to do is to know exactly what range of values will be used as indices for the vertex arrays. Given that knowledge, they can read that range of values into a separate buffer, and then render from that buffer. Without knowing the range of indices, that wouldn't be possible, since an index list could pick from any index.&#xD;&#xA;&#xD;&#xA;But that's only useful if you're reading from *client memory*. Copying that range out of client memory allows you to render asynchronously. You copy out the values you know you need, issue a rendering command with that, and then return to the caller.&#xD;&#xA;&#xD;&#xA;If you're reading from buffer objects, this isn't a useful thing to do. And since core OpenGL doesn't even allow you the option of using client memory, the `Range` commands are no longer useful." ContentLicense="CC BY-SA 3.0" />
  <row Id="17271" PostHistoryTypeId="2" PostId="6204" RevisionGUID="33e55217-9e56-44ba-9b03-9407da8fb172" CreationDate="2018-02-02T16:31:22.500" UserId="8140" Text="I've implemented a ray tracer that uses kd-trees for acceleration. To help debug kd-tree construction, I also created a crude OpenGL view of the same scene that shows the axis-aligned bounding boxes (AABBs) for each node in the tree (along with the shapes in the scene), and allows the user to highlight a specific node in the tree. &#xD;&#xA;&#xD;&#xA;Here is an example of a scene with a bunch of spheres, their AABBs, and one node selected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can clearly see that the AABB for the highlighted node contains a lot of empty space. In general, this is because, during creation, at node split time, the parent's AABB is split into two by an axis-aligned plane at whatever location is found to be optimal, and each child gets one of the two resulting AABBs.&#xD;&#xA;&#xD;&#xA;I added a step to the splitting procedure that, after the steps above, reduces the size of each child's AABB such that its min/max extents in all axes are reduced to the min/max AABB extents of its shapes. Note that the node's AABB is never expanded, so it's still possible to have shapes partially outside the node's AABB.&#xD;&#xA;&#xD;&#xA;Here is the same node selected with reduction turned on:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I see a slight improvement in performance, since the probability of an arbitrary ray hitting a given node's AABB is now less, since the AABB is smaller. &#xD;&#xA;&#xD;&#xA;My question is, is there any disadvantage to doing this? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/f9Skf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YA8oB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17272" PostHistoryTypeId="1" PostId="6204" RevisionGUID="33e55217-9e56-44ba-9b03-9407da8fb172" CreationDate="2018-02-02T16:31:22.500" UserId="8140" Text="Reduce kd-tree's nodes' bounding box sizes to their shapes' extents?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17273" PostHistoryTypeId="3" PostId="6204" RevisionGUID="33e55217-9e56-44ba-9b03-9407da8fb172" CreationDate="2018-02-02T16:31:22.500" UserId="8140" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17274" PostHistoryTypeId="2" PostId="6205" RevisionGUID="1fa280f3-cab2-4081-a5b6-c178a1923891" CreationDate="2018-02-02T16:40:50.003" UserId="8141" Text="Firstly, I would like to tell this is my first question on stackexchange and I am a senior school student. Please bear with me, if I am not able to express myself clearly.&#xD;&#xA;&#xD;&#xA;I am trying to solve a question based on euler's formula: V - E + F = 2 (1 - G)&#xD;&#xA;&#xD;&#xA;I have been given a closed mesh of a sphere. Number of Edges and Faces and number of Vertices with valence 4 are given.&#xD;&#xA;[![Valence with Vertices and Faces][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BEW7L.png&#xD;&#xA;&#xD;&#xA;Now, I have to compute V, x_1, x_2 and x_3. The vertices for valence 4 are some how not printed in my book and I assume them to be 137 (274/2) relating to table on the right. I know F = 2 V, but 275 = 2V gives a decimal point number which is not possible !&#xD;&#xA;&#xD;&#xA;Pardon for my brevity and correct me if I am not clear :)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17275" PostHistoryTypeId="1" PostId="6205" RevisionGUID="1fa280f3-cab2-4081-a5b6-c178a1923891" CreationDate="2018-02-02T16:40:50.003" UserId="8141" Text="Topology: Polygonal Meshes, Euler's Formula" ContentLicense="CC BY-SA 3.0" />
  <row Id="17276" PostHistoryTypeId="3" PostId="6205" RevisionGUID="1fa280f3-cab2-4081-a5b6-c178a1923891" CreationDate="2018-02-02T16:40:50.003" UserId="8141" Text="|mesh|polygon|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17277" PostHistoryTypeId="5" PostId="6204" RevisionGUID="5a0a0cf5-a588-45ce-8ae9-44549d9fcc63" CreationDate="2018-02-02T16:41:13.597" UserId="8140" Comment="slight correction" Text="I've implemented a ray tracer that uses kd-trees for acceleration. To help debug kd-tree construction, I also created a crude OpenGL view of the same scene that shows the axis-aligned bounding boxes (AABBs) for each node in the tree (along with the shapes in the scene), and allows the user to highlight a specific node in the tree. &#xD;&#xA;&#xD;&#xA;Here is an example of a scene with a bunch of spheres, the tree's nodes' AABBs, and one node selected:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can clearly see that the AABB for the highlighted node contains a lot of empty space. In general, this is because, during creation, at node split time, the parent's AABB is split into two by an axis-aligned plane at whatever location is found to be optimal, and each child gets one of the two resulting AABBs.&#xD;&#xA;&#xD;&#xA;I added a step to the splitting procedure that, after the steps above, reduces the size of each child's AABB such that its min/max extents in all axes are reduced to the min/max AABB extents of its shapes. Note that the node's AABB is never expanded, so it's still possible to have shapes partially outside the node's AABB.&#xD;&#xA;&#xD;&#xA;Here is the same node selected with reduction turned on:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I see a slight improvement in performance, since the probability of an arbitrary ray hitting a given node's AABB is now less, since the AABB is smaller. &#xD;&#xA;&#xD;&#xA;My question is, is there any disadvantage to doing this? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/f9Skf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YA8oB.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17278" PostHistoryTypeId="2" PostId="6206" RevisionGUID="e61bf388-35e9-4246-8bf4-79990c841aa8" CreationDate="2018-02-02T21:27:29.960" UserId="3386" Text="I would say 'no' to the question about normal mapping, it probably isn't worth it. Geological &quot;texture&quot; from local surface orientation seems to have a very minor effect on the appearance of the earth from space. Getting the atmospheric scattering and variations in diffuse albedo (diffuse / specular maps) correct is probably 100x more important. &#xD;&#xA;&#xD;&#xA;The analogy to the apple made by another user, while may be correct, is less relevant than it seems,  since the apple's surface is very shiny and has no atmosphere. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17280" PostHistoryTypeId="2" PostId="6208" RevisionGUID="c150fac6-385a-49c2-acd8-80f725e3b59a" CreationDate="2018-02-02T23:07:07.800" UserId="1981" Text="Let `g` be the number of vertices of valence 4. A closed sphere has `G=0` and we have the equation `V-E+F=2`. Now `V=x1+g+x2` and `F=275`. &#xD;&#xA;&#xD;&#xA;As a first step let us count the edges. If we multiply each face by its valence and sum those up, we get *twice* the number of edges (as each edge is shared by two faces), so:&#xD;&#xA;&#xD;&#xA;    (1)   2*E = (274*4 + x3*1)&#xD;&#xA;&#xD;&#xA;Immediately we can see that `2` divides `x3`.&#xD;&#xA;&#xD;&#xA;Similarly if we multiply each vertex with its valence we get again *twice* the number of edges, as each edge is shared by two vertices, so:&#xD;&#xA;&#xD;&#xA;    (2)   2*E = 3*x1 + 4*g + 5*x2&#xD;&#xA;&#xD;&#xA;And again we see that `x1` and `x2` must have the same parity.&#xD;&#xA;&#xD;&#xA;Plugging the first of this equation (with the very first ones) into `V-E+F=2` we get&#xD;&#xA;&#xD;&#xA;    (3)   2 = V-E+F = x1 + g + x2 - (1096+x3)/2 + 275 = x1 + x2 - x3/2 + g + 548&#xD;&#xA;&#xD;&#xA;Equating the two equations we derived above we get &#xD;&#xA;&#xD;&#xA;    (4)   1096 + x3 = 3*x1 + 4*g + 5*x2&#xD;&#xA;&#xD;&#xA;Now the system of equations `(3)&amp;(4)` has all the information encoded (excluding the parity information), so it appears you don't already have everything you need to know to determine these four unknowns." ContentLicense="CC BY-SA 3.0" />
  <row Id="17281" PostHistoryTypeId="5" PostId="6208" RevisionGUID="d3ff2958-b880-4762-8c58-c47622e4965e" CreationDate="2018-02-02T23:20:08.703" UserId="1981" Comment="added 479 characters in body" Text="Let `g` be the number of vertices of valence 4. A closed sphere has `G=0` and we have the equation `V-E+F=2`. Now `V=x1+g+x2` and `F=275`. &#xD;&#xA;&#xD;&#xA;As a first step let us count the edges. If we multiply each face by its valence and sum those up, we get *twice* the number of edges (as each edge is shared by two faces), so:&#xD;&#xA;&#xD;&#xA;    (1)   2*E = (274*4 + x3*1)&#xD;&#xA;&#xD;&#xA;Immediately we can see that `2` divides `x3`.&#xD;&#xA;&#xD;&#xA;Similarly if we multiply each vertex with its valence we get again *twice* the number of edges, as each edge is shared by two vertices, so:&#xD;&#xA;&#xD;&#xA;    (2)   2*E = 3*x1 + 4*g + 5*x2&#xD;&#xA;&#xD;&#xA;And again we see that `x1` and `x2` must have the same parity.&#xD;&#xA;&#xD;&#xA;Plugging the first of this equation (with the very first ones) into `V-E+F=2` we get&#xD;&#xA;&#xD;&#xA;    (3)   2 = V-E+F = x1 + g + x2 - (1096+x3)/2 + 275 = x1 + x2 - x3/2 + g + 548&#xD;&#xA;&#xD;&#xA;Equating the two equations we derived above we get &#xD;&#xA;&#xD;&#xA;    (4)   1096 + x3 = 3*x1 + 4*g + 5*x2&#xD;&#xA;&#xD;&#xA;Now the system of equations `(3)&amp;(4)` has all the information encoded (excluding the parity information), so it appears you don't already have everything you need to know to determine these four unknowns.&#xD;&#xA;&#xD;&#xA;I made a small Haskell program that does some bruteforcing with these conditions: [Try it online!](https://tio.run/##dZDLCoMwEEX3@YpZdOEjsZrUQqHd9BdciqDUV9BG8VGy6L/biSspOhAYZs69E26djU3RtsvCGGhx5gAP0AG4oLF1ocIXhj7BbeDfrmYukBDOylycde9oTua@L4aoGLJX/exmlSMU@FikxC62dEA1p1rQyoav8biz2Kfc8/51CQUCO4X3jMTzLC3SXH5SbjP82BFeHdD73hzhDWmOMePB4Fi0iWMnj4QQFXXtPMlOjSYL8s6kwqYfpJrgBFPWFLBBoFyWHw &quot;Haskell – Try It Online&quot;)&#xD;&#xA;&#xD;&#xA;The first solution it does get is `(0,732,2564,0) = (x1,x2,x3,g)`" ContentLicense="CC BY-SA 3.0" />
  <row Id="17288" PostHistoryTypeId="2" PostId="6209" RevisionGUID="409a2cc3-e1e4-4b78-b15f-83c5e617888a" CreationDate="2018-02-03T11:47:25.550" UserId="6806" Text="After binding the data to the vertex buffer object as follows, how to modify the buffer data?&#xD;&#xA;&#xD;&#xA;(Each subdata size is 3$*$ data size (three elements per index) &#xD;&#xA;&#xD;&#xA;    glm::vec3 vertex;&#xD;&#xA;    vertex.push_back(glm::vec3(0.0f, 0.0f, 0.0f));&#xD;&#xA;    vertex.push_back(glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;    vertex.push_back(glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;    &#xD;&#xA;    glm::vec3 color;&#xD;&#xA;    color.push_back(glm::vec3(1.0f, 0.0f, 0.0f));&#xD;&#xA;    color.push_back(glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;    color.push_back(glm::vec3(0.0f, 0.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;    glBufferData(GL_ATTRAY_BUFFER, vertex_data_size+color_data_size, NULL, GL_DYNAMIC_DRAW);&#xD;&#xA;    glBufferSubData(GL_ARRAY_BUFFER, 0, vertex_data_size, data);&#xD;&#xA;    glBufferSubData(GL_ARRAY_BUFFER, vertex_data_size, color_data_size, data);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)vertex_data_size);&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In detail, supposing I want to change the second vertex element to (1.0f, 1.0f, 1.0f). I know it with compute shader, but I just wnat to know how to do it without compute shader or OpenCl.&#xD;&#xA;&#xD;&#xA;Is it possible to change the buffer data uploaed directly without uploading the whole data again? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17289" PostHistoryTypeId="1" PostId="6209" RevisionGUID="409a2cc3-e1e4-4b78-b15f-83c5e617888a" CreationDate="2018-02-03T11:47:25.550" UserId="6806" Text="How to modify a part of VBO data without Compute Shader or OpenCL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17290" PostHistoryTypeId="3" PostId="6209" RevisionGUID="409a2cc3-e1e4-4b78-b15f-83c5e617888a" CreationDate="2018-02-03T11:47:25.550" UserId="6806" Text="|opengl|glsl|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17304" PostHistoryTypeId="2" PostId="6211" RevisionGUID="32339cad-4a45-46f1-bbdc-7750b77a1864" CreationDate="2018-02-03T13:57:40.853" UserId="3041" Text="From the OpenGL 4.5 spec, `glDrawRangeElements`:&#xD;&#xA;&#xD;&#xA;&gt; Implementations denote **recommended maximum** amounts of vertex and index&#xD;&#xA;&gt; data, which may be queried by calling GetIntegerv with pnames&#xD;&#xA;&gt; **MAX_ELEMENTS_VERTICES** and **MAX_ELEMENTS_INDICES**. &#xD;&#xA;&gt; &#xD;&#xA;&gt; If end − start + 1 is greater than the value of MAX_ELEMENTS_VERTICES,&#xD;&#xA;&gt; or if count is greater than the value of MAX_ELEMENTS_INDICES, **then&#xD;&#xA;&gt; the call may operate at reduced performance**.&#xD;&#xA;&#xD;&#xA;My interpretation of this is `glDrawElements` **may** perform worse than `glDrawRangeElements` if the index count or implicit range exceed that of the implementation dependent GL_MAX_ELEMENTS_{INDICES|VERTICES}. For platforms where `glDrawElements` is always superior I would expect `glDrawRangeElements` to ignore `start` and `end` all together, and the value of GL_MAX_ELEMENTS_{INDICES|VERTICES} to be &quot;infinite&quot;.&#xD;&#xA;&#xD;&#xA;Correct usage according to spec is therefore whenever `glDrawElements` exceeds GL_MAX_ELEMENTS_{INDICES|VERTICES} and `glDrawRangeElements` does not.&#xD;&#xA;&#xD;&#xA;For reference, on my GTX 970 the value is 1048576 for both." ContentLicense="CC BY-SA 3.0" />
  <row Id="17308" PostHistoryTypeId="2" PostId="6212" RevisionGUID="e7aad11c-fd53-4f96-bc91-95963cb2ee29" CreationDate="2018-02-03T15:47:10.620" UserId="2654" Text="&gt; Is it possible to change the buffer data uploaed directly without uploading the whole data again?&#xD;&#xA;&#xD;&#xA;&quot;Again&quot;? You didn't upload &quot;the whole data&quot; the *first time*:&#xD;&#xA;&#xD;&#xA;&gt;     glBufferSubData(GL_ARRAY_BUFFER, 0, vertex_data_size, data);&#xD;&#xA;&#xD;&#xA;That only affects the first `vertex_data_size` bytes of the buffer. And your second one only affects the data on the byte range [vertex_data_size, color_data_size + vertex_data_size).&#xD;&#xA;&#xD;&#xA;There's no limit on how many bytes you can modify with a `glBufferSubData` call. Or more to the point, there's no limit on how *few* bytes you can modify. If you want to upload 12 bytes worth of data, you can.&#xD;&#xA;&#xD;&#xA;Now, you *shouldn't*. You should avoid making lots of small uploads of data like that.&#xD;&#xA;&#xD;&#xA;If you have access to [persistent mapping][1], it would be better to persistently map the buffer and simply modify the location(s) at the appropriate time (using [proper synchronization and multiple buffering][2]).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object#Persistent_mapping&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#Persistent_mapped_streaming" ContentLicense="CC BY-SA 3.0" />
  <row Id="17309" PostHistoryTypeId="2" PostId="6213" RevisionGUID="dea95c62-2a8e-46a7-a720-0ee246274217" CreationDate="2018-02-03T16:02:25.753" UserId="5717" Text="No disadvantage that I can see but what you have is not a kd-tree if you have axis-aligned bounding boxes in every node.&#xD;&#xA;&#xD;&#xA;A kd-tree only has a splitting plane in every node, so there is no AABB to shrink. The way to deal with empty space in them is to split the node further into an empty node and a smaller node with the same objects as its parent, when justified by whatever heuristic is used. It is just one more possible split to consider when picking how to split a node." ContentLicense="CC BY-SA 3.0" />
  <row Id="17310" PostHistoryTypeId="2" PostId="6214" RevisionGUID="1426f412-6d7f-48c4-a2ed-974b248d9b33" CreationDate="2018-02-04T11:46:06.893" UserId="7107" Text="One of the hardest things for me with the modern closer to the metal graphics APIs is understanding synchronization. I usually try to simplify things in order to understand the concept better.&#xD;&#xA;&#xD;&#xA;In Directx12, we can use a set of &quot;x&quot; fences (x being the number of back buffers) to allow the CPU to work ahead of the GPU. This could be the code we use to wait for a previous fence (https://www.braynzarsoft.net):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;    if (fence[frameIndex]-&gt;GetCompletedValue() &lt; fenceValue[frameIndex])&#xD;&#xA;    {&#xD;&#xA;        hr = fence[frameIndex]-&gt;SetEventOnCompletion(fenceValue[frameIndex], fenceEvent);&#xD;&#xA;        if (FAILED(hr))&#xD;&#xA;        {&#xD;&#xA;            Running = false;&#xD;&#xA;        }&#xD;&#xA;        WaitForSingleObject(fenceEvent, INFINITE);&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;Is there a reason why we can´t just:&#xD;&#xA;&#xD;&#xA;    while(fence[frameIndex]-&gt;GetCompletedValue() &lt; fenceValue[frameIndex])&#xD;&#xA;    {&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="17311" PostHistoryTypeId="1" PostId="6214" RevisionGUID="1426f412-6d7f-48c4-a2ed-974b248d9b33" CreationDate="2018-02-04T11:46:06.893" UserId="7107" Text="Do we really need a fence event?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17312" PostHistoryTypeId="3" PostId="6214" RevisionGUID="1426f412-6d7f-48c4-a2ed-974b248d9b33" CreationDate="2018-02-04T11:46:06.893" UserId="7107" Text="|directx12|synchronization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17316" PostHistoryTypeId="5" PostId="6196" RevisionGUID="0d3f5852-385d-4c04-b72a-12d476946e06" CreationDate="2018-02-05T09:12:31.940" UserId="7008" Comment="corrected typos" Text="You can combine Oren-Nayar with GGX, if your normalize the result. A BRDF is defined by two properties: Helmholtz reciprocity and energy conservation.&#xD;&#xA;&#xD;&#xA;$f(l_i, l,_o) = f(l_o, l_i)$&#xD;&#xA;&#xD;&#xA;$f(l_i, l_o) \leq 1$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your Oren-Nayar is the diffuse part $f_d(l_i, l_o)$ and your GGX is your specular part $f_s(l_i, l_o)$. If both are energy conserving, then both are at most $1$, but combined they may be $\geq 1$ and here lies your problem. Oren-Nayar has been combined with specular terms before (see for example [The Rendering of Ryze from Crytek][1], you should have a look at how others did it. If you combine them, keep in mind that you need two different roughness values. The ones of Oren-Nayar and GGX don't match (which by the looks of it you know already) but neither can you convert from one to the other via an algorithm.&#xD;&#xA;&#xD;&#xA;A better solution imo is to use a different diffuse term. Have a look at the papers [Physically Based Shading at Disney by Brent Burley][2] and [PBR diffuse Lighting for GGX+Smith Microsurfaces by Earl Hammon Jr.][3]. Physically Based Shading discusses several diffuse lighting BRDFs, including Oren-Nayar and then goes on to introduce an own diffuse BRDF which can use the same roughness value as GGX (be careful, as the roughness here is squared before using, iirc, because that was easier to use for artists). This resulting BRDF is not energy conserving, which was accepted by the author, since&#xD;&#xA;&#xD;&#xA;&gt; This seems to provide a reasonable match to the MERL data and was also found to be artistically pleasing.&#xD;&#xA;&#xD;&#xA;A solution for this was introduced by [Sebastien Lagarde and Charles de Rousiers in Moving Frostbite to Physocally Based Rendering][4], they renormalized the entire BRDF.&#xD;&#xA;&#xD;&#xA;PBR diffuse Lighting for GGX+Smith Microsurfaces by Earl Hammon takes a different approach, he calculates an approximation like Oren and Nayar did, only he did it for GGX NDF and Smith shadowing/masking. Both the Disney Diffuse and Hammon's Diffuse BRDF can easily be combined with the GGX specular term and are visually more pleasing than Lambert.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.crytek.com/download/2014_03_25_CRYENGINE_GDC_Schultz.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf&#xD;&#xA;  [3]: https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX&#xD;&#xA;  [4]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="17317" PostHistoryTypeId="2" PostId="6215" RevisionGUID="9558bfbe-0488-4545-a754-99cce23e1ede" CreationDate="2018-02-05T09:37:04.103" UserId="2041" Text="In your first example, the call to `WaitForSingleObject` *blocks* the thread. This puts it into a waiting state, which takes it off the run queue and allows other threads to run on this CPU core. If no threads can run, the CPU will idle. When the `fenceEvent` completes, it wakes up this thread.&#xD;&#xA;&#xD;&#xA;Your proposed replacement is called a *spinlock*. The thread keeps running, using 100% of a core until the fence's completed flag changes. No other code can run on this core, so there's no interleaving of CPU and GPU work. Worse yet, this code has to read from memory to check the flag every time around the loop, so it'll slow down any threads on other cores that are also accessing memory. Finally, because it's keeping the core and the memory bus active, it'll burn more power and generate more heat.&#xD;&#xA;&#xD;&#xA;This is why fences are needed: to enable the CPU to wait efficiently." ContentLicense="CC BY-SA 3.0" />
  <row Id="17318" PostHistoryTypeId="5" PostId="6215" RevisionGUID="20cdce18-7301-4894-ad9e-ce2f2c385c9d" CreationDate="2018-02-05T11:43:05.400" UserId="7107" Comment="Fixed name" Text="In your first example, the call to `WaitForSingleObject` *blocks* the thread. This puts it into a waiting state, which takes it off the run queue and allows other threads to run on this CPU core. If no threads can run, the CPU will idle. When the `fenceEvent` completes, it wakes up this thread.&#xD;&#xA;&#xD;&#xA;Your proposed replacement is called a *spinlock*. The thread keeps running, using 100% of a core until the fence's completed flag changes. No other code can run on this core, so there's no interleaving of CPU and GPU work. Worse yet, this code has to read from memory to check the flag every time around the loop, so it'll slow down any threads on other cores that are also accessing memory. Finally, because it's keeping the core and the memory bus active, it'll burn more power and generate more heat.&#xD;&#xA;&#xD;&#xA;This is why fence events are needed: to enable the CPU to wait efficiently." ContentLicense="CC BY-SA 3.0" />
  <row Id="17319" PostHistoryTypeId="24" PostId="6215" RevisionGUID="20cdce18-7301-4894-ad9e-ce2f2c385c9d" CreationDate="2018-02-05T11:43:05.400" Comment="Proposed by 7107 approved by 209, 2041 edit id of 306" ContentLicense="CC BY-SA 3.0" />
  <row Id="17320" PostHistoryTypeId="50" PostId="5852" RevisionGUID="5ef3c3bb-0e30-4cca-b046-38d20c51364b" CreationDate="2018-02-05T13:18:41.420" UserId="-1" />
  <row Id="17325" PostHistoryTypeId="2" PostId="6217" RevisionGUID="7968390e-85c0-4906-95fe-b0fface0a8f5" CreationDate="2018-02-05T21:39:58.190" UserId="8150" Text="&quot;How does the Shadow of The Colossus™ engine perform its seamless long distance rendering?&quot;&#xD;&#xA;[![SS from http://www.businessinsider.com/shadow-of-the-colossus-remake-playstation-4-video-2017-9][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PIa8J.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17326" PostHistoryTypeId="1" PostId="6217" RevisionGUID="7968390e-85c0-4906-95fe-b0fface0a8f5" CreationDate="2018-02-05T21:39:58.190" UserId="8150" Text="&quot;How does the Shadow of The Colossus's™ proprietary (Sony's) engine perform its seamless long distance rendering?&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17327" PostHistoryTypeId="3" PostId="6217" RevisionGUID="7968390e-85c0-4906-95fe-b0fface0a8f5" CreationDate="2018-02-05T21:39:58.190" UserId="8150" Text="|rendering|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17328" PostHistoryTypeId="2" PostId="6218" RevisionGUID="5440cdbe-902f-46da-9ab8-359d3b489723" CreationDate="2018-02-06T06:17:28.353" UserId="8152" Text="Why is there necessarily a hierarchy in Euler rotations?&#xD;&#xA;&#xD;&#xA;For example I need to decide that I want&#xD;&#xA;&#xD;&#xA;    x to affect y and z&#xD;&#xA;    z to affect y&#xD;&#xA;    y to affect nothing.&#xD;&#xA;&#xD;&#xA;What if I wanted to have something like:&#xD;&#xA;&#xD;&#xA;    x to affect y and z&#xD;&#xA;    z to affect x and y&#xD;&#xA;    y to affect nothing&#xD;&#xA;&#xD;&#xA;(x, y and z refer to rotations about x, y and z)&#xD;&#xA;&#xD;&#xA;I understand for a physical gimbal there is a restriction, but that need not be necessary for a computer graphics system, right?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17329" PostHistoryTypeId="1" PostId="6218" RevisionGUID="5440cdbe-902f-46da-9ab8-359d3b489723" CreationDate="2018-02-06T06:17:28.353" UserId="8152" Text="Heirarchy in Euler rotations" ContentLicense="CC BY-SA 3.0" />
  <row Id="17330" PostHistoryTypeId="3" PostId="6218" RevisionGUID="5440cdbe-902f-46da-9ab8-359d3b489723" CreationDate="2018-02-06T06:17:28.353" UserId="8152" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17331" PostHistoryTypeId="2" PostId="6219" RevisionGUID="b13f5352-df92-4867-bd13-fd6979b773d3" CreationDate="2018-02-06T07:23:22.657" UserId="8153" Text="When a cell phone is used to take a photo or capture video the display continuously displays what a camera can see, does that mean the ccd/cmos device is exposed to light continuously? or is it displayed by some other means(with out involving ccd/cmos)? Is the difference between displaying and capturing a video(or photo) is only storage? Is cellphone continuously taking pictures for displaying, even if you don't take a picture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17332" PostHistoryTypeId="1" PostId="6219" RevisionGUID="b13f5352-df92-4867-bd13-fd6979b773d3" CreationDate="2018-02-06T07:23:22.657" UserId="8153" Text="How does cell phone display image or video even before you start to capture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17333" PostHistoryTypeId="3" PostId="6219" RevisionGUID="b13f5352-df92-4867-bd13-fd6979b773d3" CreationDate="2018-02-06T07:23:22.657" UserId="8153" Text="|rendering|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17334" PostHistoryTypeId="5" PostId="6049" RevisionGUID="c7b3efe7-30c2-4df5-ab62-39d6d8882d3d" CreationDate="2018-02-06T07:57:14.563" UserId="1937" Comment="fixed code sample - forgot to enable vertex arrays" Text="I can see a few things wrong here. &#xD;&#xA;&#xD;&#xA;First, you're setting your GL buffer size to `sizeof(vertices) * vertices.size()`&#xD;&#xA;This looks wrong. What is vertices? A std::array of vec4? Then you want `vertices.size() * sizeof(glm::vec4)`, or just `sizeof(vertices)`&#xD;&#xA;&#xD;&#xA;Second, as wandering-warrior said, you want to be binding to `GL_ARRAY_BUFFER` before calling `glVertexAttribPointer`&#xD;&#xA;&#xD;&#xA;Third, I don't know what you're doing with `bufferOffset` in the second part of the code. This is a valid approach if the data is laid out sequentially in one large buffer (vertices then normals then tangents etc. etc.). But in your case you're using a separate buffer for each data set - so each attribute should start reading from the beginning of its own buffer, i.e. `bufferOffset` should always be 0. &#xD;&#xA;&#xD;&#xA;Fourth, you don't seem to be actually *using* your compute shader anywhere. It's not enough to just call `glUseProgram`, you need to call `glDispatchCompute` after you bind your buffers to actually run it.&#xD;&#xA;&#xD;&#xA;Also, it's not common practice to store binormals in an array, since they can be reconstructed in the fragment shader from the tangent and normal using a cross product.&#xD;&#xA;&#xD;&#xA;I would do it something like this (using OpenGL 4.5 with the new Direct State Access functions to save all those buffer bindings).&#xD;&#xA;&#xD;&#xA;    int bufferSize = sizeof(vertices);&#xD;&#xA;&#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Previous);&#xD;&#xA;    glNamedBufferData(vbo_Previous, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vbo_Previous);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Current);&#xD;&#xA;    glNamedBufferData(vbo_Current, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbo_Current);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Next);&#xD;&#xA;    glNamedBufferData(vbo_Next, bufferSize, &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, vbo_Next);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Normal);&#xD;&#xA;    glNamedBufferData(vbo_Normal, bufferSize, &amp;normals[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, vbo_Normal);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Tangent);&#xD;&#xA;    glNamedBufferData(vbo_Tangent, bufferSize, &amp;tangents[0], GL_STATIC_DRAW);&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, vbo_Tangent);&#xD;&#xA;    &#xD;&#xA;    glCreateBuffers(1, &amp;vbo_Texcoords);&#xD;&#xA;    glNamedBufferData(vbo_Texcoords, sizeof(texCoords), &amp;texCoords[0], &#xD;&#xA;    GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glCreateBuffers(1, &amp;ebo);&#xD;&#xA;    glNamedBufferData(ebo, sizeof(elements), &amp;elements[0], GL_STATIC_DRAW);&#xD;&#xA;    //you have element data in an array, right?&#xD;&#xA;    &#xD;&#xA;    glCreateVertexArrays(1, &amp;vao);&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    glBindVertexBuffer(0, vbo_Next, 0, 0);&#xD;&#xA;    glVertexAttribBinding(0,0);&#xD;&#xA;    glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glBindVertexBuffer(1, vbo_Normal, 0, 0);&#xD;&#xA;    glVertexAttribBinding(1,1);&#xD;&#xA;    glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glBindVertexBuffer(2, vbo_Tangent, 0, 0);&#xD;&#xA;    glVertexAttribBinding(2,2);&#xD;&#xA;    glVertexAttribFormat(2, 4, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glBindVertexBuffer(3, vbo_Texcoords, 0, 0);&#xD;&#xA;    glVertexAttribBinding(3,3);&#xD;&#xA;    glVertexAttribFormat(3, 2, GL_FLOAT, GL_FALSE, 0);&#xD;&#xA;    glVertexArrayElementBuffer(vao, ebo);&#xD;&#xA;    &#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;    glEnableVertexAttribArray(2);&#xD;&#xA;    glEnableVertexAttribArray(3);&#xD;&#xA;&#xD;&#xA;    computeShader.use();&#xD;&#xA;    glDispatchCompute (/*number of groups*/)&#xD;&#xA;    computeShader.unUse();&#xD;&#xA;&#xD;&#xA;    glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;    renderShader.use();&#xD;&#xA;    glDrawElements(GL_TRIANGLES, elements.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;    renderShader.unUse();" ContentLicense="CC BY-SA 3.0" />
  <row Id="17338" PostHistoryTypeId="2" PostId="6221" RevisionGUID="7c5ec308-af86-4ea0-85fc-d5781ebc8687" CreationDate="2018-02-06T10:55:21.930" UserId="228" Text="I'm sorry I'm bringing this topic up again, but I need to expound some of the topics.&#xD;&#xA;&#xD;&#xA;With reference to [this question][1], I was wondering if someone can help me out in expanding some of the details.&#xD;&#xA;&#xD;&#xA;In the answer to that question we have:&#xD;&#xA;&#xD;&#xA;&gt; However, since $L_i(l_k)$ is usually not a constant, this integral is&#xD;&#xA;&gt; not separable. Yet, in some cases (like when dealing with diffuse&#xD;&#xA;&gt; lighting or, more specifically, diffuse ambient lighting), the&#xD;&#xA;&gt; information that $f(l_k,v)$ carries is low-frequency enough that it&#xD;&#xA;&gt; can reasonably be approximated as a constant with respect to the&#xD;&#xA;&gt; distribution of $L_i(l_k)$. Experimentally, it can be shown that the&#xD;&#xA;&gt; final result is not too different from what you would expect.&#xD;&#xA;&#xD;&#xA;I'm not sure I understand the specific bit &quot;the information that $f(l_k,v)$ carries is low-frequency enough&quot; and also the bit &quot;with repsect to the distribution of $L_i(l_k)$&quot;.&#xD;&#xA;&#xD;&#xA;I've been reading something about radiometry lately. The only clue I have is that since $f(l_k,v)$, is also function of the wavelength, which is inverse w.r.t. the frequency, therefore low frequency, means high wavelength, which in turn translates some specific assumption about the colour of both incoming and reflected light I guess. Experimental results are also mentioned, and I'd like to find out those if they've been published.&#xD;&#xA;&#xD;&#xA;Is my intuition correct? If yes, I don't have the intuition of this yet, experimental results are also mentioned, can you point out any paper so I can read about those?&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6099/paper-for-the-approximation-formula-provided-by-brian-karis" ContentLicense="CC BY-SA 3.0" />
  <row Id="17339" PostHistoryTypeId="1" PostId="6221" RevisionGUID="7c5ec308-af86-4ea0-85fc-d5781ebc8687" CreationDate="2018-02-06T10:55:21.930" UserId="228" Text="Why is the approximation valid, in the formula provided by Brian Karis?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17340" PostHistoryTypeId="3" PostId="6221" RevisionGUID="7c5ec308-af86-4ea0-85fc-d5781ebc8687" CreationDate="2018-02-06T10:55:21.930" UserId="228" Text="|mathematics|physically-based|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17341" PostHistoryTypeId="5" PostId="6221" RevisionGUID="a7e2a7af-7b72-419e-bb0d-b1376e925975" CreationDate="2018-02-06T11:04:09.427" UserId="228" Comment="added 35 characters in body" Text="I'm sorry I'm bringing this topic up again, but I need to expound some of the topics.&#xD;&#xA;&#xD;&#xA;With reference to [this question][1], I was wondering if someone can help me out in expanding some of the details.&#xD;&#xA;&#xD;&#xA;In the answer to that question we have:&#xD;&#xA;&#xD;&#xA;&gt; However, since $L_i(l_k)$ is usually not a constant, this integral is&#xD;&#xA;&gt; not separable. Yet, in some cases (like when dealing with diffuse&#xD;&#xA;&gt; lighting or, more specifically, diffuse ambient lighting), the&#xD;&#xA;&gt; information that $f(l_k,v)$ carries is low-frequency enough that it&#xD;&#xA;&gt; can reasonably be approximated as a constant with respect to the&#xD;&#xA;&gt; distribution of $L_i(l_k)$. Experimentally, it can be shown that the&#xD;&#xA;&gt; final result is not too different from what you would expect.&#xD;&#xA;&#xD;&#xA;I'm not sure I understand the specific bit &quot;the information that $f(l_k,v)$ carries is low-frequency enough&quot; and also the bit &quot;with repsect to the distribution of $L_i(l_k)$&quot;.&#xD;&#xA;&#xD;&#xA;I've been reading something about radiometry lately. The only clue I have is that since $f(l_k,v)$ is also function of the wavelength, which is inverse w.r.t. the frequency. Therefore low frequency means high wavelength, which in turn translates some specific assumption about the colour of both incoming and reflected light I guess. Experimental results are also mentioned and I'd like to find out those if they've been published.&#xD;&#xA;&#xD;&#xA;Is my reasoning correct? If yes, I still have the feeling I'm missing something. If not what am I missing yet? Experimental results are also mentioned, can you point out any paper so I can read about those?&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6099/paper-for-the-approximation-formula-provided-by-brian-karis" ContentLicense="CC BY-SA 3.0" />
  <row Id="17342" PostHistoryTypeId="2" PostId="6222" RevisionGUID="218ce5d1-4560-4615-83cf-a169d993b603" CreationDate="2018-02-06T11:40:01.293" UserId="137" Text="&gt; does that mean the ccd/cmos device is exposed to light continuously?&#xD;&#xA;&#xD;&#xA;Unless there is a physical shutter it will be continuously exposed to light.&#xD;&#xA;&#xD;&#xA;&gt; Is the difference between displaying and capturing a video(or photo) is only storage?&#xD;&#xA;&#xD;&#xA;yes. &#xD;&#xA;&#xD;&#xA;&gt; Is cellphone continuously taking pictures for displaying, even if you don't take a picture?&#xD;&#xA;&#xD;&#xA;If the data from the capture chip is not collected then it is lost. The phone will only capture the data when it needs to (either for displaying or storing). It can also cut power to the sensor to save battery." ContentLicense="CC BY-SA 3.0" />
  <row Id="17343" PostHistoryTypeId="2" PostId="6223" RevisionGUID="86a99bce-4eba-4a74-a587-19de08373b47" CreationDate="2018-02-06T14:39:09.160" UserId="8060" Text="Euler rotations work around the axises. this is represented in 3 angles (rot_x, rot_y, rot_z). The order of the rotation needs to be determined. As the order affects the result.&#xD;&#xA;&#xD;&#xA;for example we have a point (1, 0, 0) and we rotate 90 degrees around the Y and then 90 degrees around the Z The result will be&#xD;&#xA;&#xD;&#xA;    v1 = (1,0,0)&#xD;&#xA;    v2 = rotate_y(v1, 90) # v2 = (0,0,1)&#xD;&#xA;    v3 = rotate_z(c2, 90) # v3 = (0,0,1)&#xD;&#xA;&#xD;&#xA;When doing the other order first Z and then Y, the result is different&#xD;&#xA;&#xD;&#xA;    v1 = (1,0,0)&#xD;&#xA;    v2 = rotate_z(v1, 90) # v2 = (0,1,0)&#xD;&#xA;    v3 = rotate_y(c2, 90) # v3 = (0,1,0)&#xD;&#xA;&#xD;&#xA;In computer graphics systems quaternion rotations are used, what allows to rotate around any axis what solves this problems as there will only be a single axis where the point will be rotated around." ContentLicense="CC BY-SA 3.0" />
  <row Id="17344" PostHistoryTypeId="2" PostId="6224" RevisionGUID="3c04601c-1587-47a4-ae60-6458f04d8a19" CreationDate="2018-02-06T15:32:53.880" UserId="2817" Text="In computer graphics, one rarely uses the term &quot;frequency&quot; to refer to the inverse of wavelength of light. Usually, the meaning from **signal theory** is implied instead, i.e. the frequency of signal, or **detail**.&#xD;&#xA;&#xD;&#xA;&quot;Low-frequency information&quot; in this case means that diffuse lighting is usually &quot;blurry,&quot; i.e. it does not carry high-resolution detail, and is approximately the same, or has a smooth gradient, over relatively large regions of space.&#xD;&#xA;&#xD;&#xA;To put it simply, &quot;low frequency with respect to the distribution of $ L_i(l_k) $&quot; intuitively means &quot;the incoming light signal has low detail&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="17345" PostHistoryTypeId="2" PostId="6225" RevisionGUID="740ae905-9ccc-4413-a5aa-6b91156aa4ff" CreationDate="2018-02-06T16:49:13.887" UserId="8158" Text="Suppose I have parallel lines running along the ground (into the horizon). If I have a camera and I know its tilt angle, is there a way to calculate the slopes of the lines as projected to the 2D image plane? What parameters of the camera are needed?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17346" PostHistoryTypeId="1" PostId="6225" RevisionGUID="740ae905-9ccc-4413-a5aa-6b91156aa4ff" CreationDate="2018-02-06T16:49:13.887" UserId="8158" Text="Determining slopes of lines in perspective projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17347" PostHistoryTypeId="3" PostId="6225" RevisionGUID="740ae905-9ccc-4413-a5aa-6b91156aa4ff" CreationDate="2018-02-06T16:49:13.887" UserId="8158" Text="|projections|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17348" PostHistoryTypeId="5" PostId="6225" RevisionGUID="3a7e13ad-7bcc-4a79-8ce8-18efebbb9db0" CreationDate="2018-02-06T16:54:19.687" UserId="8158" Comment="added 183 characters in body" Text="Suppose I have parallel lines running along the ground (into the horizon). If I have a camera and I know its tilt angle, is there a way to calculate the slopes of the lines as projected to the 2D image plane? That is, the green angles:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Is the distance from the lines needed? Also, what parameters of the camera are used in the calculation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SQyPf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17349" PostHistoryTypeId="5" PostId="6225" RevisionGUID="fb1c4212-be2e-4afd-9981-8d2df993d537" CreationDate="2018-02-06T17:00:30.867" UserId="8158" Comment="added 7 characters in body" Text="Suppose I have parallel lines running along the ground (into the horizon). If I have a camera and I know its tilt angle, is there a way to calculate the slopes of the lines as projected to the 2D image plane? That is, the green angles:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, the distance from the lines are not known. What parameters of the camera are used in the calculation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SQyPf.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17350" PostHistoryTypeId="2" PostId="6226" RevisionGUID="797230b9-fefc-41a5-906c-9b951ea4b12f" CreationDate="2018-02-06T17:11:12.747" UserId="5703" Text="&quot;the information that $f(l_k,v)$ carries is low-frequency enough&quot;: As IneQuation explains, low-frequency was used to refer to the detail of the brdf function. I did actually mean that $f_r$ was low frequency though (which is the case with diffuse lighting), not $L_i$.&#xD;&#xA;&#xD;&#xA;&quot;with respect to $L_i$&quot;: what this means it that, since there aren't any large peaks in $f_r$, no part of $L_i$ will be wheighted much more heavily than any other in the integral.&#xD;&#xA;&#xD;&#xA;If each function was, say, reciprocal of the other (meaning in this case that the peaks in each one would cancel out when multiplied by the other) the correct integral would be very different to the separated integral where this cancelation does not occurr. but since the two functions are not correlated (or they shouldn't be) this difference is likely to be fairly small.&#xD;&#xA;&#xD;&#xA;Also, if you use a really high frequency BRDF that takes into acount only incident light around the normal and you separate it, you will get something that's way off. in this example the estimate using separation is 4x larger that the correct result: https://www.desmos.com/calculator/c4zgypthrc&#xD;&#xA;&#xD;&#xA;Experimental results can be generated easily. here is an example: https://www.desmos.com/calculator/poyswojjsa it shows a low frequency brdf $f_r$ and a high frequency incident light $L_i$ function being multiplied before and after integration. the ratio between the correct result and the one obtained using separation is of about 1.6&#xD;&#xA;&#xD;&#xA;Addendum regarding your latest comment on my other answer:&#xD;&#xA;&#xD;&#xA;$$\frac{1}{N}\sum^{N}_{k=1}f(L_k) = \sum^{N}_{k=1}(f(L_k)\cdot \frac{1}{N})$$&#xD;&#xA;&#xD;&#xA;Here we have &quot;moved&quot; or distributed $\frac{1}{N}$ into the sum. This formulation is equivalent but looks a bit more similar to an integral. if we set $\Delta L = \frac{1}{N}$ then, we can get&#xD;&#xA;&#xD;&#xA;$$\sum^{N}_{k=1}f(L_k)\Delta L\approx \int_{L}f(L)dL$$&#xD;&#xA;&#xD;&#xA;keeping in mind that the separation that occurs is, conceptually, separation of integrals, and that every integral &quot;needs&quot; its own $dL$. it follows that every montecarlo estimator needs its own $1/N$&#xD;&#xA;&#xD;&#xA;I hope this helps you understand where the extra$\frac{1}{N}$ comes from" ContentLicense="CC BY-SA 3.0" />
  <row Id="17351" PostHistoryTypeId="2" PostId="6227" RevisionGUID="925a5fb0-e5be-49e9-bc75-f66091a202cf" CreationDate="2018-02-06T19:31:00.137" UserId="8009" Text="You definitely need to know distances and angle of view of the camera.  For example, if you add lines that are slightly further apart, they will be at different angles.  Like a multi-lane highway.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AjNpc.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17352" PostHistoryTypeId="2" PostId="6228" RevisionGUID="389650f3-60f9-4e30-9b9a-4d1ccc582a50" CreationDate="2018-02-06T20:27:00.793" UserId="8009" Text="The answer is: it depends.&#xD;&#xA;&#xD;&#xA;When the preview is active in your camera app, the camera is always taking pictures so that it can provide a live preview image.  The CCD is constantly binning and resetting charge accumulated from photons hitting it.  The phone is also processing the captured image and displaying it - all this requires battery power.  So if the live preview is not active then it will likely not be taking pictures to save on battery.&#xD;&#xA;&#xD;&#xA;However, some phones have a smart sensor where you can unlock it with your face.  It might be taking pictures of your face even though it is not showing you a preview.  Some phones also have a mode where it takes pictures of you to see if you are looking at the screen.  This takes more battery power to leave engaged but it also will not show you a live preview so it saves some processing power there.  It all depends on the mode the camera is in.&#xD;&#xA;&#xD;&#xA;Your phone will also continually adjust other settings though such as sensitivity, exposure time, and focus.&#xD;&#xA;&#xD;&#xA;In a dark environment, the &quot;preview&quot; image that is displayed during live capture will be taken with high sensitivity (high ISO) with a short exposure time.  But when you take a photo, it might switch to a lower sensitivity (low ISO) and use a longer exposure time, which should produce a higher quality image -- provided you can hold the phone still for the entire exposure time.  Some phones will provide &quot;modes&quot; like sports mode or night mode, that will prefer either a short exposure time (to prevent blur - as in sports mode) or a higher quality image (as in night mode).&#xD;&#xA;&#xD;&#xA;Also, in a dark environment in video mode, before you hit record as it displays a live preview, it might use a higher sensitivity and longer exposure time (but effectively lower frame rate - like maybe only 5-10 fps) but then when you hit record, in order to maintain 60fps it could only take pictures with an exposure no more than 16ms, which might make the video appear darker than the live preview was showing, but motion will be smooth.&#xD;&#xA;&#xD;&#xA;Also, when you use a flash, the phone goes through a variety of different settings, switching between live preview, and flash on/off for focus and exposure estimation vs the conditions under which the final exposure are taken.&#xD;&#xA;&#xD;&#xA;There's a lot of tweaking that goes into creating a good camera application.  And the front and back facing cameras can work in concert to provide other features beyond the camera application - and may be active even when not providing a preview image - depending on the application." ContentLicense="CC BY-SA 3.0" />
  <row Id="17353" PostHistoryTypeId="50" PostId="5697" RevisionGUID="09d86f77-f122-435d-865d-14936e54a33b" CreationDate="2018-02-06T21:42:56.533" UserId="-1" />
  <row Id="17354" PostHistoryTypeId="2" PostId="6229" RevisionGUID="4678e568-cba8-45e6-afbe-6058a20d1875" CreationDate="2018-02-06T22:24:04.317" UserId="7462" Text="The three most popular shadowing techniques for real time applications are:&#xD;&#xA;&#xD;&#xA;shadow maps:&#xD;&#xA;&#xD;&#xA;Advantages&#xD;&#xA;&#xD;&#xA; - fast&#xD;&#xA; - &quot;Simple&quot;&#xD;&#xA;&#xD;&#xA;Disadvantages:&#xD;&#xA;&#xD;&#xA; - Numerical limitations lead to artifacts Jaggy shadows &#xD;&#xA; - You only get    the information of the first object hit by the light,&#xD;&#xA;   not the last    (important for more photorealistic effects).&#xD;&#xA;&#xD;&#xA;volume shadows:&#xD;&#xA;&#xD;&#xA;Advantages:&#xD;&#xA;&#xD;&#xA; - -Almost no numerical instability&#xD;&#xA;   &#xD;&#xA; - Hardware built in support through stenciling&#xD;&#xA;&#xD;&#xA;Disadvantages:&#xD;&#xA;&#xD;&#xA; - Slower than shadow maps&#xD;&#xA;   &#xD;&#xA; - Finding the last object that the light hits isn't easy&#xD;&#xA;&#xD;&#xA;Volumetric rendering:&#xD;&#xA;&#xD;&#xA;Advantages:&#xD;&#xA;&#xD;&#xA; - Analytic precission &#xD;&#xA; - Allows for great photeralistic shadows&#xD;&#xA; - FInding the last object hit by the light is trivial.&#xD;&#xA;&#xD;&#xA;Disadcantages:&#xD;&#xA;&#xD;&#xA; - SLOW, VERY SLOW&#xD;&#xA; - Has an awful asymptotic rinning time for ray intersection calculations (linear in teh number of primitives without hashing)&#xD;&#xA;&#xD;&#xA;Are there any new experimental shadowing techniques that can improve onto the advantages of any of these while eliminating some of the disadvantages?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17355" PostHistoryTypeId="1" PostId="6229" RevisionGUID="4678e568-cba8-45e6-afbe-6058a20d1875" CreationDate="2018-02-06T22:24:04.317" UserId="7462" Text="Experiemtnal real time shadowing techniques?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17356" PostHistoryTypeId="3" PostId="6229" RevisionGUID="4678e568-cba8-45e6-afbe-6058a20d1875" CreationDate="2018-02-06T22:24:04.317" UserId="7462" Text="|shader|shadow|shading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17357" PostHistoryTypeId="2" PostId="6230" RevisionGUID="06622843-a8ba-4b71-9a2c-16c0edbc135d" CreationDate="2018-02-06T23:56:58.570" UserId="5349" Text="Taken from [The Making Of &quot;Shadow Of The Colossus&quot;:&#xD;&#xA;](http://www.froyok.fr/documents/making_of_sotc.pdf)&#xD;&#xA;&gt; The rough algorithm is outlined below:&#xD;&#xA;&gt;&#xD;&#xA;&gt; 1. Rendering the distant view, and save it.&#xD;&#xA;&gt; 2. Foreground rendering.&#xD;&#xA;&gt; 3. Composite the distant view and foreground together. It uses the contents of the Z-buffer like a mask pattern (see image 2).&#xD;&#xA;&gt; 4. Again using the Z-buffer, generate a separate image of the mask pattern.&#xD;&#xA;&gt; 5. Reduce this to 64x64 pixels, using a bilinear filter. (This makes it ultra-low resolution.) This gets reused in step (8).&#xD;&#xA;&gt; 6. Blend in the previous frame (from step 7) using a percentage specified in the scene box.&#xD;&#xA;&gt; 7. Store the image for use in step (6). It is used for drawing the next frame.&#xD;&#xA;&gt; 8. Expand step (5) to a suitable resolution, using the bilinear filter. Thus, it becomes the material for the bloom effect where the&#xD;&#xA;&gt; distant view starts bleeding out from the shape of the foreground.&#xD;&#xA;&gt; 9. Blend (7) and (8) using a ratio specified in the scene box.&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&gt; Landscape rendering is divided into 3 stages, the furthest background&#xD;&#xA;&gt; being either a rendered image or a texture, which is stuck on a&#xD;&#xA;&gt; distant polygon. The internal development team nicknamed this &quot;Super&#xD;&#xA;&gt; Low&quot;. &#xD;&#xA;&gt; &#xD;&#xA;&gt; Consequently, most of the medium range which goes from nearby to&#xD;&#xA;&gt; just past the furthest background, is rendered using a low-resolution&#xD;&#xA;&gt; landscape. This is managed in units of 600x600m, and as the player&#xD;&#xA;&gt; approaches it, once he gets nearer than a certain fixed distance, it&#xD;&#xA;&gt; changes to the high-res landscape model for the foreground. This&#xD;&#xA;&gt; switch is designed to blend well so it not obvious. &#xD;&#xA;&gt; &#xD;&#xA;&gt; In addition before&#xD;&#xA;&gt; being combined down into one picture for the Super Low, most of the&#xD;&#xA;&gt; distant scenery being managed in 600x600m chunks has been reduced to&#xD;&#xA;&gt; around 1/30th - 1/100th of the polygons. Because there is little&#xD;&#xA;&gt; memory, we usually try and spread it around the landmark which&#xD;&#xA;&gt; represents that area. The combined image for the most distance scenery&#xD;&#xA;&gt; is done using this low-res model. With this, the low-resolution model&#xD;&#xA;&gt; appears seamlessly out of the Super Low image. By connecting the&#xD;&#xA;&gt; foreground and distant background well, we are able to produce a&#xD;&#xA;&gt; landscape rendering system which seems very natural.&#xD;&#xA;&gt; [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ePJ61.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/UTSjG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17358" PostHistoryTypeId="2" PostId="6231" RevisionGUID="b9b95fdb-14d2-41d2-b49f-79c8097508bb" CreationDate="2018-02-07T12:27:13.780" UserId="228" Text="In relation to [this question][1], in the accepted answer I have a trivial question probably.&#xD;&#xA;&#xD;&#xA;W.r.t. the following integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L(x\rightarrow \Theta) = \int_{\Omega_x} f_r(x,\Psi\rightarrow\Theta)L(x\leftarrow \Psi) cos(N_x,\Psi)d\omega_{\Psi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;in the accepted answer, one of the comments it is stated that $f_r(l,v) = f_r(x,\Psi\rightarrow\Theta)$ and $L_i(l) = L(x\leftarrow \Psi)$ are not correlated. As usual... I wanna understand why... My reference on this subject is [this book][2]. In such book the brdf $f_r(l,v)$ is ***defined*** as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r(x,\Psi \rightarrow \Theta) = \frac{dL(x \rightarrow \Theta)}{dE(x \leftarrow \Psi)} = \frac{dL(x \rightarrow \Theta)}{L(x\leftarrow\Psi)cos(N_x,\Psi) d\omega_\Psi},&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;From the last equation I can see that the two are actually related, unless there's something I'm missing. Why are they not correlated?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6221/why-is-the-approximation-valid-in-the-formula-provided-by-brian-karis?noredirect=1#comment9519_6221&#xD;&#xA;  [2]: https://books.google.co.uk/books?id=TB1jDAAAQBAJ&amp;printsec=frontcover&amp;dq=advanced%20global%20illumination&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwighpjR5JPZAhWJLMAKHbOZC4oQ6AEIKTAA#v=onepage&amp;q=advanced%20global%20illumination&amp;f=false" ContentLicense="CC BY-SA 3.0" />
  <row Id="17359" PostHistoryTypeId="1" PostId="6231" RevisionGUID="b9b95fdb-14d2-41d2-b49f-79c8097508bb" CreationDate="2018-02-07T12:27:13.780" UserId="228" Text="Why are BRDF and the lighting uncorrelated?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17360" PostHistoryTypeId="3" PostId="6231" RevisionGUID="b9b95fdb-14d2-41d2-b49f-79c8097508bb" CreationDate="2018-02-07T12:27:13.780" UserId="228" Text="|mathematics|physically-based|physics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17361" PostHistoryTypeId="2" PostId="6232" RevisionGUID="1d8d8f0c-1ff7-4cba-8779-2cb9e19c8b80" CreationDate="2018-02-07T13:24:08.980" UserId="6929" Text="I'm trying to implement [Weighted, Blended Order-Independent Transparency](http://casual-effects.blogspot.com.tr/2015/03/implemented-weighted-blended-order.html)&#xD;&#xA;&#xD;&#xA;There are three passes:&#xD;&#xA;&#xD;&#xA;1. 3D opaque surfaces to a primary framebuffer&#xD;&#xA;2. 3D transparency accumulation to an off-screen framebuffer&#xD;&#xA;3. 2D compositing transparency over the primary framebuffer&#xD;&#xA;&#xD;&#xA;I need to test transparent objects against default depth buffer. I created a framebuff for transparency pass and also created a depth buffer for maybe I can copy default depth to this buffer if this is the only way. But I don't know how to do that because I created depth buffer with `GL_DEPTH_COMPONENT24` but I don't know default depth format.&#xD;&#xA;&#xD;&#xA;Is it possible to bind default framebuffer's depth buffer to another framebuffer? If not, how can I copy default depth to another depth buff, or what is best way to do this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17362" PostHistoryTypeId="1" PostId="6232" RevisionGUID="1d8d8f0c-1ff7-4cba-8779-2cb9e19c8b80" CreationDate="2018-02-07T13:24:08.980" UserId="6929" Text="using default depth buffer in off-screen framebuffer" ContentLicense="CC BY-SA 3.0" />
  <row Id="17363" PostHistoryTypeId="3" PostId="6232" RevisionGUID="1d8d8f0c-1ff7-4cba-8779-2cb9e19c8b80" CreationDate="2018-02-07T13:24:08.980" UserId="6929" Text="|opengl|transparency|frame-buffer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17364" PostHistoryTypeId="5" PostId="6231" RevisionGUID="b9820a17-a470-4937-96e0-f52bf5c17189" CreationDate="2018-02-07T14:38:03.630" UserId="228" Comment="added 300 characters in body" Text="In relation to [this question][1], in the accepted answer I have a trivial question probably.&#xD;&#xA;&#xD;&#xA;W.r.t. the following integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L(x\rightarrow \Theta) = \int_{\Omega_x} f_r(x,\Psi\rightarrow\Theta)L(x\leftarrow \Psi) cos(N_x,\Psi)d\omega_{\Psi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;in the accepted answer, one of the comments it is stated that $f_r(l,v) = f_r(x,\Psi\rightarrow\Theta)$ and $L_i(l) = L(x\leftarrow \Psi)$ are not correlated. As usual... I wanna understand why... My reference on this subject is [this book][2]. In such book the brdf $f_r(l,v)$ is ***defined*** as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r(x,\Psi \rightarrow \Theta) = \frac{dL(x \rightarrow \Theta)}{dE(x \leftarrow \Psi)} = \frac{dL(x \rightarrow \Theta)}{L(x\leftarrow\Psi)cos(N_x,\Psi) d\omega_\Psi},&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;From the last equation I can see that the two are actually related, unless there's something I'm missing. Why are they not correlated?&#xD;&#xA;&#xD;&#xA;A note about the notation used.&#xD;&#xA;&#xD;&#xA;$L(x\rightarrow\Theta)$ : this is the radiance from $x$ toward direction $\Theta$&#xD;&#xA;$f_r(x,\Psi\rightarrow\Theta)$ is the BRDF coming from direction $\Psi$ in $x$ and exiting in direction $\Theta$&#xD;&#xA;$L(x\leftarrow\Psi)$ : radiance from direction $\Psi$ toward $x$&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6221/why-is-the-approximation-valid-in-the-formula-provided-by-brian-karis?noredirect=1#comment9519_6221&#xD;&#xA;  [2]: https://books.google.co.uk/books?id=TB1jDAAAQBAJ&amp;printsec=frontcover&amp;dq=advanced%20global%20illumination&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwighpjR5JPZAhWJLMAKHbOZC4oQ6AEIKTAA#v=onepage&amp;q=advanced%20global%20illumination&amp;f=false" ContentLicense="CC BY-SA 3.0" />
  <row Id="17365" PostHistoryTypeId="2" PostId="6233" RevisionGUID="c54dbf79-ee55-409e-b820-f9095b29b592" CreationDate="2018-02-07T14:39:55.343" UserId="6046" Text="Already asked this question on mathexchange but didn't got any promising answers so posting it here Since I'm from a CG background.&#xD;&#xA;&#xD;&#xA;I really can't understand how and why gimbal lock occurs using euler angles.&#xD;&#xA;First of all let me clear this &quot;***I know that gimbal lock occurs when 2 gimbals/axes coincide thus losing 1 degree of freedom***&quot; &#xD;&#xA;&#xD;&#xA; However what I'm interested in why the axes are coinciding in the first place when they are supposed to remain perpendicular when we move anyone.&#xD;&#xA;&#xD;&#xA;According to wikipedia [here][1] :&#xD;&#xA;&#xD;&#xA;&gt; The general problem of decomposing a rotation into three composed&#xD;&#xA;&gt; movements about intrinsic axes was studied by P. Davenport, under the&#xD;&#xA;&gt; name &quot;generalized Euler angles&quot;, but later these angles were named&#xD;&#xA;&gt; &quot;Davenport angles&quot; by M. Shuster and L. Markley.&#xD;&#xA;&gt; &#xD;&#xA;&gt; Davenport proved that any orientation can be achieved by composing&#xD;&#xA;&gt; three elemental rotations using ***non-orthogonal axes***.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;That's what I want to hear about more. Why &quot;non-orthogonal&quot; ? I can't see any problems with making the axes orthogonal? What does making the axes non-orthogonal give us?&#xD;&#xA;&#xD;&#xA;2) After the above one has been answered. How is this all tied up to rotational matrices? How can we achieve gimbal lock through the matrices when they only rotate a given point/vector around global axis. For example If i multiply a column vector with a Rotation matrix around X-axis `Rx`  and then with `Ry` It will rotate around the global X-axis first, then global Y-axis second. So how can I achieve the lock situation using matrices?&#xD;&#xA;&#xD;&#xA;EDIT:- &#xD;&#xA;To make it more clear I've also heard about rotation orders like in the order `Y-Z-X` when Y axis rotates then `Z` and `X` rotate with it but when `Z` rotates only `X` rotates with it. thus making the axes non-orthogonal. I am assuming that's what it means by non-orthogonal mentioned in the wiki article. Here is a picture.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see in the Y-Z-X order, the Y axis remains there as in 3rd picture causing the axes to coincide...&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Davenport_chained_rotations&#xD;&#xA;  [2]: https://i.stack.imgur.com/FejAW.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17366" PostHistoryTypeId="1" PostId="6233" RevisionGUID="c54dbf79-ee55-409e-b820-f9095b29b592" CreationDate="2018-02-07T14:39:55.343" UserId="6046" Text="Euler Angles - Gimbal lock, why non-orthogonal axes" ContentLicense="CC BY-SA 3.0" />
  <row Id="17367" PostHistoryTypeId="3" PostId="6233" RevisionGUID="c54dbf79-ee55-409e-b820-f9095b29b592" CreationDate="2018-02-07T14:39:55.343" UserId="6046" Text="|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17368" PostHistoryTypeId="2" PostId="6234" RevisionGUID="46ca37a0-aa38-4520-8978-0b5aa5cbf5ac" CreationDate="2018-02-07T17:47:30.067" UserId="2654" Text="&gt; Is it possible to bind default framebuffer's depth buffer to another framebuffer?&#xD;&#xA;&#xD;&#xA;First, you &quot;attach&quot; images to framebuffers. You &quot;bind&quot; objects to the context; you &quot;attach&quot; objects to other objects.&#xD;&#xA;&#xD;&#xA;Second, no, you cannot attach images of the default framebuffer to anything.&#xD;&#xA;&#xD;&#xA;&gt; If not, how can I copy default depth to another depth buff, or what is best way to do this?&#xD;&#xA;&#xD;&#xA;You render to your own depth buffer entirely. Just copy/render the image data out to the default framebuffer when its time to display it." ContentLicense="CC BY-SA 3.0" />
  <row Id="17369" PostHistoryTypeId="5" PostId="6229" RevisionGUID="cbaafb9f-5bfc-4721-874d-739425eec4a7" CreationDate="2018-02-07T19:16:35.760" UserId="506" Comment="spelling / style cleanup, added a few relevant tags and removed some irrelevant ones" Text="The three most popular shadowing techniques for real time applications are:&#xD;&#xA;&#xD;&#xA;**Shadow maps**&#xD;&#xA;&#xD;&#xA;Advantages:&#xD;&#xA;&#xD;&#xA; - Fast&#xD;&#xA; - &quot;Simple&quot;&#xD;&#xA;&#xD;&#xA;Disadvantages:&#xD;&#xA;&#xD;&#xA; - Numerical limitations lead to artifacts and jaggy shadows &#xD;&#xA; - You only get the information of the first object hit by the light, not the last (important for more photorealistic effects)&#xD;&#xA;&#xD;&#xA;**Volume shadows**&#xD;&#xA;&#xD;&#xA;Advantages:&#xD;&#xA;&#xD;&#xA; - Almost no numerical instability&#xD;&#xA;   &#xD;&#xA; - Hardware built-in support through stenciling&#xD;&#xA;&#xD;&#xA;Disadvantages:&#xD;&#xA;&#xD;&#xA; - Slower than shadow maps&#xD;&#xA;   &#xD;&#xA; - Finding the last object that the light hits isn't easy&#xD;&#xA;&#xD;&#xA;**Volumetric rendering**&#xD;&#xA;&#xD;&#xA;Advantages:&#xD;&#xA;&#xD;&#xA; - Analytic precision &#xD;&#xA; - Allows for great photorealistic shadows&#xD;&#xA; - Finding the last object hit by the light is trivial&#xD;&#xA;&#xD;&#xA;Disadvantages:&#xD;&#xA;&#xD;&#xA; - SLOW, VERY SLOW&#xD;&#xA; - Has an awful asymptotic running time for ray intersection calculations (linear in the number of primitives without hashing)&#xD;&#xA;&#xD;&#xA;Are there any new experimental shadowing techniques that can improve on the advantages of any of these while eliminating some of the disadvantages?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17370" PostHistoryTypeId="6" PostId="6229" RevisionGUID="cbaafb9f-5bfc-4721-874d-739425eec4a7" CreationDate="2018-02-07T19:16:35.760" UserId="506" Comment="spelling / style cleanup, added a few relevant tags and removed some irrelevant ones" Text="|lighting|shadow|volumetric|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17371" PostHistoryTypeId="24" PostId="6229" RevisionGUID="cbaafb9f-5bfc-4721-874d-739425eec4a7" CreationDate="2018-02-07T19:16:35.760" Comment="Proposed by 506 approved by 231 edit id of 307" ContentLicense="CC BY-SA 3.0" />
  <row Id="17372" PostHistoryTypeId="2" PostId="6235" RevisionGUID="5a22d0ce-dc69-4564-94f5-5e2ffdb4e859" CreationDate="2018-02-07T21:03:26.543" UserId="506" Text="There’s an interesting technique that’s been used in demoscene and Shadertoy projects for a while, and an analogue of which recently made it into Unreal Engine 4: using [signed-distance fields](https://en.wikipedia.org/wiki/Signed_distance_function) and raymarching to produce high-quality soft shadows with accurate penumbras.&#xD;&#xA;&#xD;&#xA;![example distance-field shadows in Unreal Engine 4](https://i.stack.imgur.com/M3eET.jpg)&#xD;&#xA;&#xD;&#xA;There’s a good writeup of the idea, with some visual examples, by Íñigo Quílez [here](http://www.iquilezles.org/www/articles/rmshadows/rmshadows.htm)—I’m not sure whether he invented the technique or was just one of the first to write about it:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; The trick is to think what happens when a shadow ray doesn't hit any object, but was just pretty close to do so. Then, perhaps, you want to put that point you are shading under penumbra. Probably, the closest your point was to hit an object, the darker you want to make it. Also, the closest this happened from the point you are shading, the darker too. Well, it happens that as we raymarched our shadow ray, both these distances were available to us! … So, we can simply compute a penumbra factor for every step point in our marching process and take the darkest of all penumbras.&#xD;&#xA;&#xD;&#xA;The documentation on the corresponding Unreal feature is [here](https://docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/RayTracedDistanceFieldShadowing/); their description of the technique is a little vaguer, but still helpful.&#xD;&#xA;&#xD;&#xA;&gt; To calculate shadowing, a ray is traced from the point being shaded through the scene's Signed Distance Fields (SDF) toward each light. The closest distance to an occluding object is used to approximate a cone trace for about the same cost as the ray trace. It allows for high-quality area shadowing from spherical light source shapes.&#xD;&#xA;&#xD;&#xA;The main advantage of this approach is its high visual quality—most other techniques don’t handle varying penumbras well, and it doesn’t suffer as much from the aliasing problems of shadow maps. The main disadvantage is needing a distance-field representation of your scene geometry to trace rays through; unless you built it that way in the first place (there’s a [fascinating talk](https://www.youtube.com/watch?v=u9KNtnCZDMI) about how the team behind “Dreams” did exactly that), you’ll need a way to construct the SDFs out of your mesh geometry, which is an expensive and sometimes error-prone operation.&#xD;&#xA;&#xD;&#xA;UE4 handles the SDF generation by building them offline beforehand and then stamping them into a volume around the camera at runtime (more information on that [here](https://docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/MeshDistanceFields/index.html)), but it’s not a cheap process so UE’s approach is only viable on high-end hardware for now. That said, if you *do* already have your scene geometry in SDF form, it’s quite easy to implement—see [this Shadertoy](https://www.shadertoy.com/view/MsfGz8) for an example." ContentLicense="CC BY-SA 3.0" />
  <row Id="17377" PostHistoryTypeId="4" PostId="6229" RevisionGUID="91526a6a-8017-41fc-82a2-b92491d3f578" CreationDate="2018-02-08T15:56:51.393" UserId="209" Comment="Just fixed the typos in the title." Text="Experimental real-time shadowing techniques?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17378" PostHistoryTypeId="2" PostId="6237" RevisionGUID="f2c70d85-de67-43cf-b2ba-b693e2265d7a" CreationDate="2018-02-08T17:22:02.540" UserId="8171" Text="I wanted to make a little demo for a console with Realm of the Mad God esc graphics to brush up my C and SDL skills.&#xD;&#xA;&#xD;&#xA;[![View of the walls I'm trying to recreate][1]][1] &#xD;&#xA;&#xD;&#xA;One problem I'm running in to is creating the 3D walls. &#xD;&#xA;The console I'm working with does not actually allow for 3D hardware acceleration at this moment of time and thus I can't really use real 3D. &#xD;&#xA;I noticed the perspective looked off in RotMG as well so I figured they must be using fake 3D also.&#xD;&#xA;&#xD;&#xA;Now I have tried layering 2d textures on top of eachother as detailed [here][2] although this didn't quite work out so I modified the algorithm a bit and the blocks looked a lot better. Problem is they wouldn't sit next to eachother convincingly so I figured this is not the right tool for the job.&#xD;&#xA;&#xD;&#xA;What type of algorithm should I use to recreate the 3D walls without actually using GL or other real 3D technologies?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AtTDe.png&#xD;&#xA;  [2]: http://www.like100bears.com/writing/2d-3d-in-gamemaker-studio" ContentLicense="CC BY-SA 3.0" />
  <row Id="17379" PostHistoryTypeId="1" PostId="6237" RevisionGUID="f2c70d85-de67-43cf-b2ba-b693e2265d7a" CreationDate="2018-02-08T17:22:02.540" UserId="8171" Text="What technique would I use to create fake 3d walls as seen in Realm of the Mad God" ContentLicense="CC BY-SA 3.0" />
  <row Id="17380" PostHistoryTypeId="3" PostId="6237" RevisionGUID="f2c70d85-de67-43cf-b2ba-b693e2265d7a" CreationDate="2018-02-08T17:22:02.540" UserId="8171" Text="|3d|transformations|2d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17381" PostHistoryTypeId="2" PostId="6238" RevisionGUID="f1183da2-1a1d-475f-9ef2-45f2249e225e" CreationDate="2018-02-08T22:02:25.857" UserId="8118" Text="What they're using in this game is called an [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection). It is a special type of a projection, which does not bend objects, it does not mean that they are not using 3D. &#xD;&#xA;&#xD;&#xA;Now, of course you can achieve this kind of effect using 2D coordinates only if you want. But it requires some mathematical understanding of the situation, as you need to do 3D calculations in order to calculate the correct 2D coordinates to use. If you do it this way, you can draw points or lines between the points after calculating the positions, and it  will give the effect you want. &#xD;&#xA;&#xD;&#xA;But here in RotMG, they are also doing texture mapping on those walls, which uses information about the actual size of the object in 3D space. This information is lost if you simply calculate the 2D positions of the corners without also doing the texture mapping yourself. &#xD;&#xA;&#xD;&#xA;So here you have two options:&#xD;&#xA;&#xD;&#xA; - You can give up your console and start doing some real 3D stuff (OpenGL, etc...).&#xD;&#xA; - You can become very good at linear algebra, preferably including [homogenous coordinates](https://en.wikipedia.org/wiki/Homogeneous_coordinates), project the points from 3D to 2D space, draw your lines/points in your console, or interpolate the 3D positions with some form of rasterization, if you want to decorate the wall using texture mapping. But once you understand all of that, you won't want to use your limited console anymore. &#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17382" PostHistoryTypeId="5" PostId="6238" RevisionGUID="60afa8d2-e5c5-4e1b-ab7b-a7a2e9d58dd2" CreationDate="2018-02-08T22:09:14.723" UserId="8118" Comment="added 1 character in body" Text="What they're using in this game is called an [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection). It is a special type of a projection, which does not bend objects, it does not mean that they are not using 3D. &#xD;&#xA;&#xD;&#xA;Now, of course you can achieve this kind of effect using 2D coordinates only if you want. But it requires some mathematical understanding of the situation, as you need to do 3D calculations in order to calculate the correct 2D coordinates to use. If you do it this way, you can draw points or lines between the points after calculating the positions, and it  will give the effect you want. &#xD;&#xA;&#xD;&#xA;But here in RotMG, they are also doing texture mapping on those walls, which uses information about the actual size of the surface in 3D space. This information is lost if you simply calculate the 2D positions of the corners without also doing the texture mapping yourself. &#xD;&#xA;&#xD;&#xA;So here you have two options:&#xD;&#xA;&#xD;&#xA; - You can give up your console and start doing some real 3D stuff (OpenGL, etc...).&#xD;&#xA; - You can become very good at linear algebra, preferably including [homogenous coordinates](https://en.wikipedia.org/wiki/Homogeneous_coordinates), project the points from 3D to 2D space, draw your lines/points in your console, or interpolate the 3D positions with some form of rasterization, if you want to decorate the wall using texture mapping. But once you understand all of that, I'm afraid you won't want to use your limited console anymore. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17383" PostHistoryTypeId="2" PostId="6239" RevisionGUID="a557bc9c-e56b-487b-8a15-96544223bba3" CreationDate="2018-02-09T03:07:51.730" UserId="5703" Text="When rendering an image you are trying to find the outgoing light from a point into the camera $L(x \rightarrow \Theta$).&#xA;&#xA;To do this you solve &quot;The rendering equation&quot;, which means you integrate the product of the brdf and the incoming light for every incoming direction.&#xA;&#xA;$$L(x\rightarrow\Theta )=\int_\Omega f_r(x, \omega\rightarrow\Theta)\cdot L(x\leftarrow\omega)d\omega$$&#xA;&#xA;Since you don't have the outgoing light you cannot use the definition of the brdf to calculate it.&#xA;&#xA;$$f_r(x,\omega\rightarrow\Theta )=\frac{L(x\rightarrow\Theta)}{E(x\leftarrow\omega)}$$&#xA;&#xA;Instead, you use a formula to compute $f_r(x,\omega\rightarrow\Theta )$ and some operation to find the incoming light $L(x\leftarrow\omega)$ (a raytrace, a env map sample, etc.), and use those to compute the outgoing light $L(x\rightarrow\Theta)$.&#xA;&#xA;These two calculations are usually done in a completely separate way. So there is no way the incoming light can effect the brdf in any way." ContentLicense="CC BY-SA 3.0" />
  <row Id="17384" PostHistoryTypeId="2" PostId="6240" RevisionGUID="2777a0cb-fdfd-4251-b9bd-9ad90867ff6c" CreationDate="2018-02-09T05:05:43.903" UserId="8009" Text="I took a few days and wrote something to do this.  It was not really as straightforward as I was expecting so I'll share what I learned.&#xD;&#xA;&#xD;&#xA;# What was hard&#xD;&#xA;&#xD;&#xA;Here are the major headaches I encountered.&#xD;&#xA;&#xD;&#xA;### Dealing with JPEG Compression Artifacts&#xD;&#xA;&#xD;&#xA;When sampling the values for the legend, I encountered many JPEG compression artifacts. This required me to apply a median filter.  The media filter width needed to be a parameter of the function (needs different values depending on how big the legend is.)&#xD;&#xA;&#xD;&#xA;### Dealing with &quot;bands&quot; in the legend&#xD;&#xA;&#xD;&#xA;The legend in your first example is divided into discrete sections (bands) and the numeric quantity desired is probably the middle of the range that the colour spans.  For example, the left-most box covers values from -6500 to -6000 and should probably return &quot;-6250&quot; when trying to sample a single colour of that value.  Also, consequently, no pixel will return the value &quot;0&quot;.  There is no colour representation for &quot;0&quot; (in that first map anyway.)&#xD;&#xA;&#xD;&#xA;### Dealing with differences in tone / value.&#xD;&#xA;&#xD;&#xA;Sometimes the exact colour in the map doesn't exist in the legend, especially due to the text labels, so you have to do a &quot;closest&quot; matching algorithm and the hue seems to be more important than the value (black&amp;white-ness) so it was better to evaluate &quot;distance&quot; between colours in a colourspace other than RGB. &#xD;&#xA;&#xD;&#xA;### Text overwrites data&#xD;&#xA;&#xD;&#xA;There are plenty of black pixels in the map due to the labels, but these need to be ignored somehow.  It makes sense to try to infer what the value behind the text is, and only colours that are not in the legend qualify for this kind of inference.&#xD;&#xA;&#xD;&#xA;### Manually selecting points on the legend is not precise&#xD;&#xA;&#xD;&#xA;Each time I eye-balled it and manually found a point that looked like approximately the end-point, I'd choose a slightly different pixel, resulting in slightly different values between attempts.  Perhaps a snapping technique would be better where I could &quot;hint&quot; where the legend is, but it would find the high-contrast edge markings and snap the hint point to the exact point.&#xD;&#xA;&#xD;&#xA;### Most maps don't have continuous legends.&#xD;&#xA;&#xD;&#xA;Most other images that I went searching for with test data had discontinuities in their legend (discrete boxes of colour) as opposed to a nice continuous linear gradient like you provided.  This makes it extra difficult to automatically come up with the mapping from colour to value just by analyzing the positions of the colours in the legend.  I was disappointed when trying to apply it to most maps.&#xD;&#xA;&#xD;&#xA;### Visualization tips&#xD;&#xA;&#xD;&#xA;It was very useful (especially while debugging) to visually show the point on the legend that it thought best corresponded to the colour being picked in the map.&#xD;&#xA;&#xD;&#xA;### Persistence&#xD;&#xA;&#xD;&#xA;It's useful to persist the location of the endpoints of the linear gradient portion of the legend and the values that are associated with them between runs of the application.  Don't underestimate the value of this.  It's annoying to have to specify all that stuff every time.&#xD;&#xA;&#xD;&#xA;# What worked well&#xD;&#xA;&#xD;&#xA;### Represent the legend as all the pixels along a line segment&#xD;&#xA;&#xD;&#xA;Specify two (x,y) locations of the start and end of a linear gradient (the legend) and manually define the values that are associated with them.&#xD;&#xA;&#xD;&#xA;### build up a discrete sample set for the gradient&#xD;&#xA;&#xD;&#xA;Sample all the pixels in between the start and end points to build a linear gradient dataset.&#xD;&#xA;&#xD;&#xA;### Median filter&#xD;&#xA;&#xD;&#xA;Apply a median filter to the linear gradient dataset to filter out JPEG noise.&#xD;&#xA;&#xD;&#xA;### Quantize the dataset to locate centroids&#xD;&#xA;&#xD;&#xA;Optionally filter out bands (long runs of samples in the linear gradient dataset that have approximately the same colour) and replace them with a single sample at the centroid (average position).&#xD;&#xA;&#xD;&#xA;### Use bilinear sampling when picking a pixel&#xD;&#xA;&#xD;&#xA;Pick a pixel in the map and perform a bilinear sample to smooth out pixellation.  This seems to help improve the smoothness and resolution of the map.&#xD;&#xA;&#xD;&#xA;### Linear search is fine&#xD;&#xA;&#xD;&#xA;Linearly search for the data point in the linear gradient for the closest colour.  For an interactive picker working from mouse clicks, you have lots of time to perform a linear search.  No fancy hashing, indexing or optimized searching was required.&#xD;&#xA;&#xD;&#xA;### Hue is important in the colour distance function&#xD;&#xA;&#xD;&#xA;Compare distance between colours using a distance function in a colourspace that tolerates brightness difference more than hue difference.  (like YUV, for example)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17385" PostHistoryTypeId="2" PostId="6241" RevisionGUID="94121f77-7248-4148-9538-922213c04eeb" CreationDate="2018-02-09T07:14:13.500" UserId="8153" Text="What is the process involved in calculating the resolution of image to be displayed when the screen of my phone(android) is rotated? My screen resolution is 1920x1080. It displays some videos only in the center while top and bottom of the video are blacked(when phone is held vertical), where as full screen video is shown when phone is held in horizontal position." ContentLicense="CC BY-SA 3.0" />
  <row Id="17386" PostHistoryTypeId="1" PostId="6241" RevisionGUID="94121f77-7248-4148-9538-922213c04eeb" CreationDate="2018-02-09T07:14:13.500" UserId="8153" Text="How does image resolution change(process involved in calculation), when a screen on phone is rotated?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17387" PostHistoryTypeId="3" PostId="6241" RevisionGUID="94121f77-7248-4148-9538-922213c04eeb" CreationDate="2018-02-09T07:14:13.500" UserId="8153" Text="|rendering|image-processing|computational-geometry|rasterizer|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17389" PostHistoryTypeId="2" PostId="6242" RevisionGUID="074d78a1-a7e0-4e5e-b020-c7034218d768" CreationDate="2018-02-09T09:39:25.283" UserId="2750" Text="I have two aligned meshes: I have exact mapping from each vertex of low poly mesh to surface of a high poly mesh. High poly (~100K vertices) mesh is non-manifold, low poly (~1K vertices) is manifold and allows cylindrical texture mapping and each vertex has a normal.&#xD;&#xA;&#xD;&#xA;Is there a Linux application with text UI that can automatically project supersampled texture (albedo/diffuse and normal maps) from high poly mesh to low poly mesh? Maybe there is a Python/C++/etc. library that has such functionality?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17390" PostHistoryTypeId="1" PostId="6242" RevisionGUID="074d78a1-a7e0-4e5e-b020-c7034218d768" CreationDate="2018-02-09T09:39:25.283" UserId="2750" Text="How to automatically project texture from high poly mesh to low poly mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17391" PostHistoryTypeId="3" PostId="6242" RevisionGUID="074d78a1-a7e0-4e5e-b020-c7034218d768" CreationDate="2018-02-09T09:39:25.283" UserId="2750" Text="|texture|3d|diffuse|3dtexture|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17392" PostHistoryTypeId="2" PostId="6243" RevisionGUID="1534ca13-3d6d-476f-8a63-0325fd733a16" CreationDate="2018-02-09T13:23:33.373" UserId="5430" Text="I want to learn is it good or bad idea.&#xD;&#xA;&#xD;&#xA;Let's assume video RAM is not a problem.&#xD;&#xA;&#xD;&#xA;For source texture create a texture of texels: spherical functions. Spherical functions defined by small arrays of spherical harmonics coefficients up to some reasonable degree (say 3). To gather single sample for particular texel and particular coordinates on sphere (theta, phi) it is needed to integrate over the footprint (here I mean *footprint assembly* method) started from the textel and use this value later when spherical harmonic coefficients are calculated. Phi is exactly polar angle of the footprint on `uv` plane. Theta is length of the footprint up to (and from, as optimization) some reasonable length. I almost sure, that continuity is almost preserved, except bottom of the sphere (and to, where theta begins, if we starts from some threshold minimal length of a footprint).&#xD;&#xA;&#xD;&#xA;There are possible some optimizations when performed backing of a footprints: save value of integrated color in both pixels footprint begins and ends. Calculate values for fixed number of directions and radii (and on power of two proximities). And, maybe others.&#xD;&#xA;&#xD;&#xA;The advantage of the method is possibility to get color of whole screen pixel footprint in single sampling act. The disadvantage is requirement to prepare ($O(N^4) \approx x_{resolution} \cdot y_{resolution} \cdot n_\phi \cdot n_\theta$?) such a texture for every LOD (separately? or bilinear scaling applicable?) and huge amount of memory even for coefficients of spherical harmonics to represent a spherical function of even 3 degree ($3^2 = 9$ RGB values) for better angular and *footprint length* resolution." ContentLicense="CC BY-SA 3.0" />
  <row Id="17393" PostHistoryTypeId="1" PostId="6243" RevisionGUID="1534ca13-3d6d-476f-8a63-0325fd733a16" CreationDate="2018-02-09T13:23:33.373" UserId="5430" Text="Anisotropic filtering using spherical harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="17394" PostHistoryTypeId="3" PostId="6243" RevisionGUID="1534ca13-3d6d-476f-8a63-0325fd733a16" CreationDate="2018-02-09T13:23:33.373" UserId="5430" Text="|antialiasing|filtering|spherical-harmonics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17395" PostHistoryTypeId="4" PostId="6243" RevisionGUID="650992fb-47f2-47e9-bfb5-149a2af42283" CreationDate="2018-02-09T13:32:09.127" UserId="5430" Comment="edited title" Text="Backed anisotropic filtering using spherical harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="17396" PostHistoryTypeId="5" PostId="6231" RevisionGUID="f243b006-16f4-4128-b12d-3f32fcc56946" CreationDate="2018-02-09T13:56:47.887" UserId="228" Comment="added 4 characters in body" Text="In relation to [this question][1], in the accepted answer I have a trivial question probably.&#xD;&#xA;&#xD;&#xA;W.r.t. the following integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(x\rightarrow \Theta) = \int_{\Omega_x} f_r(x,\Psi\rightarrow\Theta)L_i(x\leftarrow \Psi) cos(N_x,\Psi)d\omega_{\Psi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;in the accepted answer, one of the comments it is stated that $f_r(l,v) = f_r(x,\Psi\rightarrow\Theta)$ and $L_i(l) = L(x\leftarrow \Psi)$ are not correlated. As usual... I wanna understand why... My reference on this subject is [this book][2]. In such book the brdf $f_r(l,v)$ is ***defined*** as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r(x,\Psi \rightarrow \Theta) = \frac{dL(x \rightarrow \Theta)}{dE(x \leftarrow \Psi)} = \frac{dL(x \rightarrow \Theta)}{L(x\leftarrow\Psi)cos(N_x,\Psi) d\omega_\Psi},&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;From the last equation I can see that the two are actually related, unless there's something I'm missing. Why are they not correlated?&#xD;&#xA;&#xD;&#xA;A note about the notation used.&#xD;&#xA;&#xD;&#xA;$L(x\rightarrow\Theta)$ : this is the radiance from $x$ toward direction $\Theta$&#xD;&#xA;$f_r(x,\Psi\rightarrow\Theta)$ is the BRDF coming from direction $\Psi$ in $x$ and exiting in direction $\Theta$&#xD;&#xA;$L(x\leftarrow\Psi)$ : radiance from direction $\Psi$ toward $x$&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6221/why-is-the-approximation-valid-in-the-formula-provided-by-brian-karis?noredirect=1#comment9519_6221&#xD;&#xA;  [2]: https://books.google.co.uk/books?id=TB1jDAAAQBAJ&amp;printsec=frontcover&amp;dq=advanced%20global%20illumination&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwighpjR5JPZAhWJLMAKHbOZC4oQ6AEIKTAA#v=onepage&amp;q=advanced%20global%20illumination&amp;f=false" ContentLicense="CC BY-SA 3.0" />
  <row Id="17397" PostHistoryTypeId="5" PostId="6243" RevisionGUID="b17abedd-e891-40cb-98fc-3d62389a7db9" CreationDate="2018-02-09T16:37:36.467" UserId="5430" Comment="added 557 characters in body; edited title" Text="I want to learn is it good or bad idea.&#xD;&#xA;&#xD;&#xA;Let's assume video RAM is not a problem.&#xD;&#xA;&#xD;&#xA;For source texture create a texture of texels: spherical functions. Spherical functions defined by small arrays of spherical harmonics coefficients up to some reasonable degree (say 3). To gather single sample for particular texel and particular coordinates on sphere (theta, phi) it is needed to integrate over the footprint (here I mean *footprint assembly* method) started from the textel and use this value later when spherical harmonic coefficients are calculated. Phi is exactly polar angle of the footprint on `uv` plane. Theta is length of the footprint up to (and from, as optimization) some reasonable length. I almost sure, that continuity is almost preserved, except bottom of the sphere (and to, where theta begins, if we starts from some threshold minimal length of a footprint).&#xD;&#xA;&#xD;&#xA;There are possible some optimizations when performed backing of a footprints: save value of integrated color in both pixels footprint begins and ends. Calculate values for fixed number of directions and radii (and on power of two proximities). And, maybe others.&#xD;&#xA;&#xD;&#xA;The advantage of the method is possibility to get color of whole screen pixel footprint in single sampling act. The disadvantage is requirement to prepare ($O(N^4) \approx x_{resolution} \cdot y_{resolution} \cdot n_\phi \cdot n_\theta$?) such a texture for every LOD (separately? or bilinear scaling applicable?) and huge amount of memory even for coefficients of spherical harmonics to represent a spherical function of even 3 degree ($3^2 = 9$ RGB values) for better angular and *footprint length* resolution.&#xD;&#xA;&#xD;&#xA;###ADDITIONAL&#xD;&#xA;&#xD;&#xA;Now I think there is no need to have mips. All other LODs can be modeled __continuously__ by using different cone angle to make convolution with saved spherical function. It is very smooth.&#xD;&#xA;&#xD;&#xA;It seems also better to save value of color itself, not integral over footprint, because spherical harmonics allow to easily calculate integrals (just a scalar product). Especially with zonal sperical functions like integral into a solid angle inside of arbitrary oriented cone.&#xD;&#xA;&#xD;&#xA;I think this format of textures is best for cartoon industry." ContentLicense="CC BY-SA 3.0" />
  <row Id="17398" PostHistoryTypeId="4" PostId="6243" RevisionGUID="b17abedd-e891-40cb-98fc-3d62389a7db9" CreationDate="2018-02-09T16:37:36.467" UserId="5430" Comment="added 557 characters in body; edited title" Text="Baced anisotropic filtering using spherical harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="17399" PostHistoryTypeId="5" PostId="6242" RevisionGUID="01d4b05a-38dc-4eea-8eca-b115d72d400c" CreationDate="2018-02-09T18:15:32.970" UserId="2750" Comment="Requested algorithm instead of software" Text="I have two aligned meshes: I have exact mapping from each vertex of low poly mesh to surface of a high poly mesh. High poly (~100K vertices) mesh is non-manifold, low poly (~1K vertices) is manifold and allows cylindrical texture mapping and each vertex has a normal.&#xD;&#xA;&#xD;&#xA;What algorithms can I use to project supersampled texture (albedo/diffuse and normal maps) from high poly mesh to low poly mesh? It would be great to have not only a paper, but implementation as well." ContentLicense="CC BY-SA 3.0" />
  <row Id="17402" PostHistoryTypeId="2" PostId="6244" RevisionGUID="acc7a392-372b-4ab1-9ba7-072f2b47a398" CreationDate="2018-02-10T01:10:49.117" UserId="8180" Text="I'm currently taking a graphics course and we've recently covered cross-correlation with regards to using a filter matrix that is applied to a region of pixels in a sort of continual raster-type scan across a larger input image to produce some output image.&#xD;&#xA;&#xD;&#xA;The formula is denoted here:&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;*G is the output image, h is the kernel/box filter matrix, F is the input image*&#xD;&#xA;&#xD;&#xA;The classic one that was introduced is a 3x3 box filter for blurring an input image. The box filter is a 3x3 matrix with each cell value being equally set to 1/9. We've been dealing primarily with grayscale images with values 0 (black) to 255 (white).&#xD;&#xA;&#xD;&#xA;In this case, the largest possible output pixel value would be if the 3x3 input image area contained all white pixels in which case we'd have:&#xD;&#xA;&#xD;&#xA;`[(1/9) * 255 ] * 9 = 255`&#xD;&#xA;&#xD;&#xA;This is fine, but what if our kernel filter matrix instead had 9 cell values all equal to 0.5?&#xD;&#xA;&#xD;&#xA;Then the largest potential output value would be:&#xD;&#xA;&#xD;&#xA;`[0.5 * 255] * 9 = 1147.5`&#xD;&#xA;&#xD;&#xA;Once we've completely finished producing our new output image matrix, how do we handle values above 255 and below 0?&#xD;&#xA;&#xD;&#xA;It seems like there are three possible approaches:&#xD;&#xA;&#xD;&#xA;Capping&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;Cap all output values to 0 and 255. Any value below 0 is capped to 0, any value above 255 is capped to 255.&#xD;&#xA;&#xD;&#xA;Modulo&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;Use modulo. In this case it would be 1147.5 % 255 = 125.5 rounded to 126.&#xD;&#xA;&#xD;&#xA;Scaling&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;Take the highest output value and use it to scale all the values proportionally. If our example output image pixel values were 1147.5, 100, and 255, then we would perform the following operations:&#xD;&#xA;&#xD;&#xA; - `(1147.5 / 1147.5) * 255 = 255`&#xD;&#xA; - `(100 / 1147.5)    * 255 = 22.2 = 22`&#xD;&#xA; - `(255 / 1147.5)    * 255 = 56.6 = 57`&#xD;&#xA;&#xD;&#xA;I just don't get which one of these I'm supposed to be using for common graphics operations. I have the same question when combining images together (such as multiply, divide, screen, etc).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZTbzk.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17403" PostHistoryTypeId="1" PostId="6244" RevisionGUID="acc7a392-372b-4ab1-9ba7-072f2b47a398" CreationDate="2018-02-10T01:10:49.117" UserId="8180" Text="Modulo vs Scaling vs Capping when performing filters" ContentLicense="CC BY-SA 3.0" />
  <row Id="17404" PostHistoryTypeId="3" PostId="6244" RevisionGUID="acc7a392-372b-4ab1-9ba7-072f2b47a398" CreationDate="2018-02-10T01:10:49.117" UserId="8180" Text="|mathematics|matrix|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17405" PostHistoryTypeId="2" PostId="6245" RevisionGUID="24405985-a5cd-43d6-8ecc-e5cfe91a8ac6" CreationDate="2018-02-10T02:26:32.000" UserId="48" Text="When doing a filter operation such as a blur, in many cases the filter itself will be normalized so its values sum to 1.0, precisely to avoid this problem.&#xA;&#xA;In cases where out-of-range outputs do need to be handled, the most common way is what you called capping. In graphics it's more commonly known as clamping or saturating. This is the default behavior if, for instance, you run a pixel shader on a GPU and output out-of-range values.&#xA;&#xA;Renormalizing the output image might be necessary in some special cases depending on what you're doing. I can't think of anytime that I've seen the modulo behavior used—it would be a pretty weird operation to do on a visual image." ContentLicense="CC BY-SA 3.0" />
  <row Id="17406" PostHistoryTypeId="2" PostId="6246" RevisionGUID="db32a46d-56e5-4770-b1fc-c0f52cc3c828" CreationDate="2018-02-10T06:40:20.057" UserId="3003" Text="While clamping or saturating may be the most common way of handling this situation, it's usually not the best. (But wrapping/modulus is one of the worst.) Another way of handling it is to either convert the input to 16 or 32-bit ints or floats and do all calculations in the higher bit depth. You may want to down-convert the final output, if required by your processing tools. Or, if you can choose the output format you can leave it in a higher bit depth. Most professional tools these days do their work in higher bit depths.&#xD;&#xA;&#xD;&#xA;Regarding your question:&#xD;&#xA;&#xD;&#xA;&gt;  is it common to add/multiply images together?&#xD;&#xA;&#xD;&#xA;Yes, it's quite common in tools that allow compositing. In Photoshop, for example, there are blend modes that are even named &quot;Add&quot; and &quot;Multiply&quot; and they do just that. (Though they assume the values are normalized to a 0-1 range.) If you are working with 8-bit per channel images, they will clamp, but if you are working with 32-bit per channel images, they will simply have values greater than 1. If done with linear RGB, this mimics light fairly naturally, and you can apply natural photographic operations to the results, like decreasing the exposure and it will bring those blown-out highlights back into the displayable range. As we move into the era of High Dynamic Range output devices, this type of processing will only become more common and useful." ContentLicense="CC BY-SA 3.0" />
  <row Id="17407" PostHistoryTypeId="2" PostId="6247" RevisionGUID="db60c4f0-49ca-4ead-90cf-174e4e7752b8" CreationDate="2018-02-10T13:26:35.587" UserId="38" Text="OK I think I know what your problem is, gimbal lock does not really lock anything from a mathematical point if view, only for certain operations. See euler suggested that euler angles can define all space angles. And that is true. Its just that euler does not say that the space is uniform. Highly mathematical people also say that the euler space has impossible solutions since some positions are overlapping, but in practice this is not really a problem.&#xD;&#xA;&#xD;&#xA;Now since you can reach any angle, and you can always unwind your angle you can reach any angle in the body. Provided that your ready to unravel the situation and start over for a computer program doing animation and a mathematician this seems reasonable.&#xD;&#xA;&#xD;&#xA;However, this is not what most people are doing. Instead if you try to do some physical things like calculating the distance between 2 positions, the energy needed to rotate, use a external force to move the system or make a delta move in the gimbals space then this non uniformity kicks in. Simply the space is not uniform the same way that a real space is at the poles the distance to a position next to you in real space can be surprisingly far away in Euler rotation space.&#xD;&#xA;&#xD;&#xA;So when somebody is euler locked it does not mean they can not move anywhere they just can not move in the direction they would want to move in that particular orientation of the gimbal, and close to it. Its a bit like living in the suburbs and wanting to reach your neighbors house (that is 100 m away) but being forced to go trough the center of the city (15 km away). Energetically or time wise highly wasteful.&#xD;&#xA;&#xD;&#xA;Now it is possible to construct the gimbal so that the pole does not really happen, just not with the orthogonal axes the space is still not uniform but it does not experience the extreme case. However it might just be easier to use some other formulation like quaternionions instead. (quaternionions aren't really practical if your building a real mechanism though, its possible but very convoluted)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: I would draw an image, its just that drawing something the wraps perfectly upon itself and is a 3d field is a bit difficult to do." ContentLicense="CC BY-SA 3.0" />
  <row Id="17408" PostHistoryTypeId="5" PostId="6247" RevisionGUID="703cd53c-133b-4864-b020-3d99db907e4a" CreationDate="2018-02-10T13:34:01.327" UserId="38" Comment="added 269 characters in body" Text="OK I think I know what your problem is, gimbal lock does not really lock anything from a mathematical point if view, only for certain operations. See euler suggested that euler angles can define all space angles. And that is true. Its just that euler does not say that the space is uniform. Highly mathematical people also say that the euler space has impossible solutions since some positions are overlapping, but in practice this is not really a problem.&#xD;&#xA;&#xD;&#xA;Now since you can reach any angle, and you can always unwind your angle you can reach any angle in the body. Provided that your ready to unravel the situation and start over for a computer program doing animation and a mathematician this seems reasonable.&#xD;&#xA;&#xD;&#xA;However, this is not what most people are doing. Instead if you try to do some physical things like calculating the distance between 2 positions, the energy needed to rotate, use a external force to move the system or make a delta move in the gimbals space then this non uniformity kicks in. Simply the space is not uniform the same way that a real space is at the poles the distance to a position next to you in real space can be surprisingly far away in Euler rotation space.&#xD;&#xA;&#xD;&#xA;So when somebody is euler locked it does not mean they can not move anywhere they just can not move in the direction they would want to move in that particular orientation of the gimbal, and close to it. Its a bit like living in the suburbs and wanting to reach your neighbors house (that is 100 m away) but being forced to go trough the center of the city (15 km away). Energetically or time wise highly wasteful.&#xD;&#xA;&#xD;&#xA;This is a problem in 3D graphics only if you choose to interpolate in Euler angles. But for a control engineer or a mechanical engineer this can be  a nightmare, since you can suddenly have a discrepancy between what your mechanism and your control logic is saying.&#xD;&#xA;&#xD;&#xA;Now it is possible to construct the gimbal so that the pole does not really happen, just not with the orthogonal axes the space is still not uniform but it does not experience the extreme case. However it might just be easier to use some other formulation like quaternionions, or axis angle instead. (quaternionions aren't really practical if your building a real mechanism though, its possible but very convoluted)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: I would draw an image, its just that drawing something the wraps perfectly upon itself and is a 3d field is a bit difficult to do." ContentLicense="CC BY-SA 3.0" />
  <row Id="17409" PostHistoryTypeId="2" PostId="6248" RevisionGUID="685aae3e-7e6c-492f-b919-eff599723dc3" CreationDate="2018-02-10T15:56:50.583" UserId="3003" Text="Usually the resolution of the video is changed on-the-fly to match the size being displayed. So if you have video that has a 16:9 aspect ratio and 1920 x 1080 pixels and you turn your phone into the vertical position, you'll now have a width of 1080 pixels instead of height. So the width changed from 1920 to 1080. Now you have to figure out how to change the height by the same ratio:&#xD;&#xA;&#xD;&#xA;    newHeight = 1080 * (1080 / 1920)&#xD;&#xA;&#xD;&#xA;Or, using the aspect ratio of the footage:&#xD;&#xA;&#xD;&#xA;    newHeight = 1080 * (9 / 16)&#xD;&#xA;&#xD;&#xA;So the new height would be 607.5, but it probably gets rounded up to 608 since that's an even number. So now, when each frame is displayed, it first gets scaled down (probably using the GPU since it's very fast at that) from 1920 x 1080 to 1080 x 608." ContentLicense="CC BY-SA 3.0" />
  <row Id="17410" PostHistoryTypeId="2" PostId="6249" RevisionGUID="0eef6318-66b6-4c1d-a1e9-697d84cf1043" CreationDate="2018-02-10T16:46:28.533" UserId="8032" Text="On the CPU side, I have a structure I want to pass to the compute kernel:&#xD;&#xA;&#xD;&#xA;      private struct BoundingBoxParameters {&#xD;&#xA;        var x: Float = 0&#xD;&#xA;        var y: Float = 0&#xD;&#xA;        var width: Float = 0&#xD;&#xA;        var height: Float = 0&#xD;&#xA;        var levelOfDetail: Float = 1.0&#xD;&#xA;        var dummy: Float = 1.0  // Needed for success&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;Before running the kernel, I pass in the data to the MTLComputeCommandEncoder:&#xD;&#xA;&#xD;&#xA;Option 1 (directly):&#xD;&#xA;&#xD;&#xA;    commandEncoder!.setBytes(&amp;params, length: MemoryLayout&lt;BoundingBoxParameters&gt;.size, index: 0)&#xD;&#xA;&#xD;&#xA;Option 2 (indirectly via MTLBuffer):&#xD;&#xA;&#xD;&#xA;    boundingBoxBuffer.contents().copyBytes(from: &amp;params, count: MemoryLayout&lt;BoundingBoxParameters&gt;.size)&#xD;&#xA;    commandEncoder!.setBuffer(boundingBoxBuffer, offset: 0, index: 0)&#xD;&#xA;&#xD;&#xA;Either option works fine if the 'dummy' variable exists in the structure, but fails if the 'dummy' variable does not exists. The code fails in the call to:&#xD;&#xA;&#xD;&#xA;    commandEncoder!.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount)&#xD;&#xA;&#xD;&#xA;With the error:&#xD;&#xA;&#xD;&#xA;    validateComputeFunctionArguments:820: failed assertion `Compute Function(resizeImage): argument params[0] from buffer(0) with offset(0) and length(20) has space for 20 bytes, but argument has a length(24).'&#xD;&#xA;&#xD;&#xA;On the Metal Kernel Side, here's the relevant code snippets:&#xD;&#xA;&#xD;&#xA;    struct BoundingBoxParameters {&#xD;&#xA;      float2 topLeft;&#xD;&#xA;      float2 size;&#xD;&#xA;      float levelOfDetail;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    kernel void resizeImage(constant BoundingBoxParameters *params [[buffer(0)]],&#xD;&#xA;                            texture2d&lt;half, access::sample&gt; sourceTexture [[texture(0)]],&#xD;&#xA;                            texture2d&lt;half, access::write&gt; destTexture [[texture(1)]],&#xD;&#xA;                            sampler samp [[sampler(0)]],&#xD;&#xA;                            uint2 gridPosition [[thread_position_in_grid]]) {&#xD;&#xA;      float2 destSize = float2(destTexture.get_width(0), destTexture.get_height(0));&#xD;&#xA;      float2 sourceCoords = float2(gridPosition) / destSize;&#xD;&#xA;      sourceCoords *= params-&gt;size;&#xD;&#xA;      sourceCoords += params-&gt;topLeft;&#xD;&#xA;      float lod = params-&gt;levelOfDetail;&#xD;&#xA;      half4 color = sourceTexture.sample(samp, sourceCoords, level(lod));&#xD;&#xA;      destTexture.write(color, gridPosition);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I also get a similar issue when trying to pass in a 3x3 matrix to the compute kernel. It complains that 36 bytes are provided but expecting 48.&#xD;&#xA;&#xD;&#xA;Anyone got any ideas on the issue?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17411" PostHistoryTypeId="1" PostId="6249" RevisionGUID="0eef6318-66b6-4c1d-a1e9-697d84cf1043" CreationDate="2018-02-10T16:46:28.533" UserId="8032" Text="Passing parameters in Metal Compute Kernel using Swift 4" ContentLicense="CC BY-SA 3.0" />
  <row Id="17412" PostHistoryTypeId="3" PostId="6249" RevisionGUID="0eef6318-66b6-4c1d-a1e9-697d84cf1043" CreationDate="2018-02-10T16:46:28.533" UserId="8032" Text="|image-processing|compute-shader|metal|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17416" PostHistoryTypeId="2" PostId="6251" RevisionGUID="f106bbdd-df62-4a57-9b5a-24c3609dfd8c" CreationDate="2018-02-10T17:17:31.187" UserId="6046" Text="So thanks to joojaa I finally got a hint, and I searched on the net further and found [this link][1] which cleared all the doubts and has my answer. Though I am still posting it here as a summary.&#xD;&#xA;&#xD;&#xA;So anyone reading this and who has similar problem to mine here is what I understood. Suppose we are considering the tait-bryan angle order X-Y-Z that is rotate first along X then Y and finally Z. Also to make it clear we are rotating around the &quot;fixed&quot; axes since a rotation matrix always rotates around the fixed axes. The matrix doesn't know anything about the axes moving or anything.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So suppose I have my initial frame like in my picture (original post) leftmost. If I use `Ax` with `angle = 90 degrees` then my `Y` axis becomes `Z` and `Z` becomes `-Y`. However if I now rotate with `Ay` the matrix will still be rotating around the previous/original fixed `Y` axis.&#xD;&#xA;&#xD;&#xA;Now that's clear take this plane as an example. We want to rotate in the order X-Y-Z.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If we rotate around the X-axis we can see that the plane will either roll left or right. Suppose we rotate a little around the X-axis and then rotate around `Y-axis` so that it is pointing straight up like this&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Now we have to rotate around Z as this is the last in the order. But notice that the rotation around `Z` is similar to the previous rotation we performed around `X`. The plane will roll either towards the left or right. This means we lost 1 degree of freedom. I think this is what joojaa was trying to explain to me. So everywhere where people are saying the axis coincide its the local, moving frame coinciding with the original frame. Initially both the local and global frames are coinciding. In this case when we rotated around `Y` by 90 the local moving X-axis collapsed on to the fixed original `Z`- axis causing this gimbal lock &#xD;&#xA;&#xD;&#xA;  [1]: https://matthew-brett.github.io/transforms3d/gimbal_lock.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/agrEP.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/5jGNQ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7cgdo.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17428" PostHistoryTypeId="2" PostId="6254" RevisionGUID="2507d242-e983-4b2b-a651-1ff2dd755f4c" CreationDate="2018-02-11T19:58:23.250" UserId="8191" Text="This has been haunting me for several days now. I want to find the component that makes up of this 4x4 perspective projection matrix, with l(left), r(right), b(bottom), t(top), n(near), f(far) defining the frustum.&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    2n/(r-l),        0,  (r+l)/(r-l),        0,&#xD;&#xA;           0, 2n/(t-b),  (t+b)/(t-b),        0,&#xD;&#xA;           0,        0, -(f+n)/(f-n),-2fn(f-n),&#xD;&#xA;           0,        0,           -1,        0&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;Here's my approach so far. The first matrix component would just copy z over to w coordinate:&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    1, 0,  0, 0,&#xD;&#xA;    0, 1,  0, 0,&#xD;&#xA;    0, 0,  1, 0,&#xD;&#xA;    0, 0, -1, 0&#xD;&#xA;    ]&#xD;&#xA;The second matrix translates the eye (at 0, 0, 0) to ((l+r)/2, (t+b)/2, (n+f)/2), the center of the frustum because canonical coordinate is just a cube of size 2 with its centroid at the origin (0, 0, 0)&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    1, 0, 0, (l+r)/2,&#xD;&#xA;    0, 1, 0, (b+t)/2,&#xD;&#xA;    0, 0, 1, (n+f)/2,&#xD;&#xA;    0, 0, 0,       1&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;The last matrix just scales the thing so that the frustum fits into the cube of size 2.&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    2/(r-l),       0,       0, 0,&#xD;&#xA;          0, 2/(t-b),       0, 0,&#xD;&#xA;          0,       0, 2/(f-n), 0,&#xD;&#xA;          0,       0,       0, 1 &#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;As you can see the multiplication of these 3 matrices isn't equal to the perspective projection matrix. What am I missing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17429" PostHistoryTypeId="1" PostId="6254" RevisionGUID="2507d242-e983-4b2b-a651-1ff2dd755f4c" CreationDate="2018-02-11T19:58:23.250" UserId="8191" Text="How to derive a perspective projection matrix from its components?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17430" PostHistoryTypeId="3" PostId="6254" RevisionGUID="2507d242-e983-4b2b-a651-1ff2dd755f4c" CreationDate="2018-02-11T19:58:23.250" UserId="8191" Text="|3d|matrix|projections|linear-algebra|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17436" PostHistoryTypeId="50" PostId="4632" RevisionGUID="c8d7ed75-90e9-4403-a201-a260bb3df9ca" CreationDate="2018-02-11T21:40:10.663" UserId="-1" />
  <row Id="17441" PostHistoryTypeId="2" PostId="6256" RevisionGUID="369ce4e6-09f0-4bc6-91e8-7ab6500f79e4" CreationDate="2018-02-12T01:46:30.437" UserId="6806" Text="for better accuracy, instead of GLfloat, I bound double data and tried to use the data in shader as follow: (I just tested to draw single triangle.)&#xD;&#xA;&#xD;&#xA;cpp.&#xD;&#xA;&#xD;&#xA;	// xyzw three vertices&#xD;&#xA;	double points[] = { 0.0, 0.0, 0.0, 1.0 , 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0 };&#xD;&#xA;&#xD;&#xA;    glGenVertexArrays(1, VAO);&#xD;&#xA;	glBindVertexArray(VAO);&#xD;&#xA;&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, 96, points, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	int data = 0;&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;	glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, 0, (void*)data);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;shader.&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    layout(location = 0) in dvec4 vPos;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;	    gl_Position = vec4(vPos);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What's worng with me? &#xD;&#xA;&#xD;&#xA;(If I changed the dvec4 in the above shader to vec4, the triangle was drawn, but maybe it's not double anymore. I want to use double in shader.)&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17442" PostHistoryTypeId="1" PostId="6256" RevisionGUID="369ce4e6-09f0-4bc6-91e8-7ab6500f79e4" CreationDate="2018-02-12T01:46:30.437" UserId="6806" Text="Double precision in shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="17443" PostHistoryTypeId="3" PostId="6256" RevisionGUID="369ce4e6-09f0-4bc6-91e8-7ab6500f79e4" CreationDate="2018-02-12T01:46:30.437" UserId="6806" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17444" PostHistoryTypeId="2" PostId="6257" RevisionGUID="baf6f32c-2227-4a7b-92e1-9a2e8c59d13c" CreationDate="2018-02-12T02:03:20.120" UserId="6" Text="The problem is, `glVertexAttribPointer(0, 4, GL_DOUBLE...` doesn't do what you think it does.&#xD;&#xA;&#xD;&#xA;Using actual double-precision vertex attributes and performing double precision computations is a very modern hardware feature (GL4/DX12) and is different from specifying the type `GL_DOUBLE` in the good old `glVertexAttribPointer` call. This always worked and does nothing else than specify the *input* type, i.e. the type of your vertex data in memory. All it does is make the GL convert your doubles into singles and feeding them into a normal single-precision attribute (and failing when there is none), same with other input types like `GL_SHORT` or `GL_UNSIGNED_BYTE`.&#xD;&#xA;&#xD;&#xA;When specifying data for genuine double-precision attributes, you have to use [`glVertexAttribLPointer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml) (note the **L**) instead. The same holds for genuine integer attributes (`ivecX`/`uvecX`), which use `glVertexAttribIPointer`.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;Of course the answer isn't complete without some general advise, that you should really make sure you actually need double precision vertex attributes, or even double precision computation. Even on modern hardware that's still significantly slower and not what those GPUs are really made for, not to speak of the doubled memory consumption for the vertex data. More precision is not always better if it isn't actually necessary and you might be surprised what a lousy little `float` is able to accomplish when used well.&lt;/sub&gt;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17446" PostHistoryTypeId="5" PostId="6254" RevisionGUID="bcaee7ea-243f-4601-a287-344bf5795b49" CreationDate="2018-02-12T04:42:48.427" UserId="8191" Comment="added 4 characters in body" Text="This has been haunting me for several days now. I want to find the component that makes up of this 4x4 perspective projection matrix, with l(left), r(right), b(bottom), t(top), n(near), f(far) defining the frustum.&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    2n/(r-l),        0,  (r+l)/(r-l),         0,&#xD;&#xA;           0, 2n/(t-b),  (t+b)/(t-b),         0,&#xD;&#xA;           0,        0, -(f+n)/(f-n),-2fn/(f-n),&#xD;&#xA;           0,        0,           -1,         0&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;Here's my approach so far. The first matrix component would just copy z over to w coordinate:&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    1, 0,  0, 0,&#xD;&#xA;    0, 1,  0, 0,&#xD;&#xA;    0, 0,  1, 0,&#xD;&#xA;    0, 0, -1, 0&#xD;&#xA;    ]&#xD;&#xA;The second matrix translates the eye (at 0, 0, 0) to ((l+r)/2, (t+b)/2, (n+f)/2), the center of the frustum because canonical coordinate is just a cube of size 2 with its centroid at the origin (0, 0, 0)&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    1, 0, 0, (l+r)/2,&#xD;&#xA;    0, 1, 0, (b+t)/2,&#xD;&#xA;    0, 0, 1, (n+f)/2,&#xD;&#xA;    0, 0, 0,       1&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;The last matrix just scales the thing so that the frustum fits into the cube of size 2.&#xD;&#xA;&#xD;&#xA;    [&#xD;&#xA;    2/(r-l),       0,       0, 0,&#xD;&#xA;          0, 2/(t-b),       0, 0,&#xD;&#xA;          0,       0, 2/(f-n), 0,&#xD;&#xA;          0,       0,       0, 1 &#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;As you can see the multiplication of these 3 matrices isn't equal to the perspective projection matrix. What am I missing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17447" PostHistoryTypeId="2" PostId="6258" RevisionGUID="b0907f55-5dd4-49a8-bc9d-25dd68cbface" CreationDate="2018-02-12T04:47:31.577" UserId="7271" Text="The float2 type in the Metal structure requires an alignment of 8 bytes. The stride of the struct then becomes 24 so every value is aligned properly if you use it in an array.  Your Swift structure only uses float which requires an alignment of 4 bytes, and an overall stride of 20.&#xD;&#xA;&#xD;&#xA;[This presentation by Apple][1] goes into some detail (starting at 30:20 of [the video][2]). The [Metal Shading Language&#xD;&#xA;Specification ][3] lists the alignment of vector and matrix data types in sections 2.2 and 2.3.&#xD;&#xA;&#xD;&#xA;Similarly, float3x3 has a size of 48 and an alignment of 16 in Metal. But an array of 9 floats would only have a size of 36 and an alignment of 4. Using the simd module can provide you data types in Swift with the same size and alignment requirements as those used in Metal.&#xD;&#xA;&#xD;&#xA;As a side note, you should be using MemoryLayout&lt;&gt;.stride instead of MemoryLayout&lt;&gt;.size when you call setBytes.  The following Swift structure has a stride of 24 but a size of only 20.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    struct BoundingBoxParameters {&#xD;&#xA;        var topLeft: float2 = float2(0)   // float2 is from &quot;import simd&quot;&#xD;&#xA;        var size: float2 = float2(0)&#xD;&#xA;        var levelOfDetail: Float = 1.0&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://devstreaming.apple.com/videos/wwdc/2014/604xxg7crkljcr8/604/604_working_with_metal_fundamentals.pdf&#xD;&#xA;  [2]: https://developer.apple.com/videos/play/wwdc2014/604/&#xD;&#xA;  [3]: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="17450" PostHistoryTypeId="2" PostId="6259" RevisionGUID="b1a2180c-fe44-49aa-8411-11816e5cce3c" CreationDate="2018-02-12T09:32:28.407" UserId="7000" Text="The OpenGL [wiki entry][1] for layout qualifiers says:&#xD;&#xA;&#xD;&#xA;&gt; Image uniform variables have qualifiers that define the format that all reading operations will convert the data into...&#xD;&#xA;&#xD;&#xA;When is it a good idea to declare the image format in a shader?&#xD;&#xA;&#xD;&#xA;i.e. `layout (binding = 0, r32f) readonly uniform image2D input_image`&#xD;&#xA;&#xD;&#xA;Wouldn't this shader work just as well if I did not specify the `r32f`?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Image_formats" ContentLicense="CC BY-SA 3.0" />
  <row Id="17451" PostHistoryTypeId="1" PostId="6259" RevisionGUID="b1a2180c-fe44-49aa-8411-11816e5cce3c" CreationDate="2018-02-12T09:32:28.407" UserId="7000" Text="Why would I specify image format in a shader layout qualifier?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17452" PostHistoryTypeId="3" PostId="6259" RevisionGUID="b1a2180c-fe44-49aa-8411-11816e5cce3c" CreationDate="2018-02-12T09:32:28.407" UserId="7000" Text="|opengl|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17455" PostHistoryTypeId="2" PostId="6261" RevisionGUID="4117990e-06f1-40d6-87d9-fefb652743f1" CreationDate="2018-02-12T11:49:27.387" UserId="6046" Text="From the same [wiki][1]&#xD;&#xA;&#xD;&#xA;&gt; Image variables can be declared with a format qualifier; this&#xD;&#xA;&gt; specifies the format for any read operations done on the image.&#xD;&#xA;&gt; **Therefore, a format qualifier is required if you do not declare the&#xD;&#xA;&gt; variable with the writeonly memory qualifier. Write-only variables&#xD;&#xA;&gt; cannot be used as in any reading operations; this includes calling&#xD;&#xA;&gt; load and atomic (read/modify/write) functions. So if you want to read&#xD;&#xA;&gt; from an image, you must declare the format.**&#xD;&#xA;&gt; &#xD;&#xA;&gt; The format defines how the shader interprets the bits of data that it&#xD;&#xA;&gt; reads from the image. It also defines how it converts the data passed&#xD;&#xA;&gt; for write operations when it writes it into the image. This allows the&#xD;&#xA;&gt; actual Image Format of the image to differ between what the shader&#xD;&#xA;&gt; sees and what is stored in the image, sometimes substantially.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store" ContentLicense="CC BY-SA 3.0" />
  <row Id="17456" PostHistoryTypeId="2" PostId="6262" RevisionGUID="a1829bea-925a-4a3c-9054-1aa5f74090d6" CreationDate="2018-02-12T16:54:00.027" UserId="228" Text="In a BRDF $f_r$, assume Cook-Torrance model, we have a microfacets distribution $D$. This microfecets distribution essentially models the rougheness of the material as far as I've understood. Given a direction $v$ it models the amount of microfacets having that orientation.&#xD;&#xA;&#xD;&#xA;Now say we have a material, for each point $p$ in theory we have a 3D function that tell us the orientation in a given direction.&#xD;&#xA;&#xD;&#xA;This explantion (not detailed) makes sense to me, however when I read about the roughness map what I see is that it's a kind of texture where each pixel has values between 0 and 1 (from black to white) I do struggle to understand the relationship between this map and the microfacets distribution.&#xD;&#xA;&#xD;&#xA;Could anyone clarify?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17457" PostHistoryTypeId="1" PostId="6262" RevisionGUID="a1829bea-925a-4a3c-9054-1aa5f74090d6" CreationDate="2018-02-12T16:54:00.027" UserId="228" Text="Relationship between roughness and BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="17458" PostHistoryTypeId="3" PostId="6262" RevisionGUID="a1829bea-925a-4a3c-9054-1aa5f74090d6" CreationDate="2018-02-12T16:54:00.027" UserId="228" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17459" PostHistoryTypeId="5" PostId="6262" RevisionGUID="56e2643d-467b-4b25-9437-067506c0732b" CreationDate="2018-02-12T17:47:09.323" UserId="2479" Comment="Readability, tags" Text="In a BRDF $f_r$, assume Cook-Torrance model, we have a microfacets distribution $D$. This distribution essentially models the rougheness of the material as far as I've understood. Given a direction $v$ it models the amount of microfacets having that orientation.&#xD;&#xA;&#xD;&#xA;Now say we have a material, for each point $p$ in theory we have a 3D function that tell us the orientation in a given direction.&#xD;&#xA;&#xD;&#xA;This explantion (not detailed) makes sense to me, however when I read about the roughness map what I see is that it's a kind of texture where each pixel has values between 0 and 1 (from black to white) I do struggle to understand the relationship between this map and the microfacets distribution.&#xD;&#xA;&#xD;&#xA;Could anyone clarify?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17460" PostHistoryTypeId="6" PostId="6262" RevisionGUID="56e2643d-467b-4b25-9437-067506c0732b" CreationDate="2018-02-12T17:47:09.323" UserId="2479" Comment="Readability, tags" Text="|shader|brdf|distribution|microfacet|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17461" PostHistoryTypeId="24" PostId="6262" RevisionGUID="56e2643d-467b-4b25-9437-067506c0732b" CreationDate="2018-02-12T17:47:09.323" Comment="Proposed by 2479 approved by 228 edit id of 310" ContentLicense="CC BY-SA 3.0" />
  <row Id="17466" PostHistoryTypeId="50" PostId="6085" RevisionGUID="205bc039-0e1b-4d14-915d-141b62a944ce" CreationDate="2018-02-12T23:52:36.070" UserId="-1" />
  <row Id="17467" PostHistoryTypeId="2" PostId="6264" RevisionGUID="fd2cf4c8-4b21-43bb-b712-754a26a0e08d" CreationDate="2018-02-13T06:52:56.020" UserId="5066" Text="I had the exact same question until I learned about Compute shaders &amp; was playing around with it. I think Compute shader is one possible use case where you read/write into an image. This is where specifying these formats is important. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17468" PostHistoryTypeId="2" PostId="6265" RevisionGUID="da23ceec-c6fd-446f-a492-6ddb55d4b0df" CreationDate="2018-02-13T07:34:05.740" UserId="7008" Text="&gt; for each point $p$ in theory we have a 3D function that tells us the orientation in a given direction&#xD;&#xA;&#xD;&#xA;You have missunderstood this. $D$ is a Normal *Distribution* Function (or short NDF), so it doesn't really give you a single normal, but a distribution. In a (specular) BRDF you are always using the normal that is the half vector between the incoming and outgoing light, since via your theory, every microfacet is a perfect mirror and thus every microfacet reflects light exactly along the (micro) surface and that one only.&#xD;&#xA;&#xD;&#xA;You also must not confuse *roughness* with *microfacet normal*. The roughness is a more or less arbitrary value (and a scalar, so a single one at that). The roughness is being used differently, depending on the overall BRDF (e.g. roughness in GGX(/Trowbridge-Reitz) is different from the Roughness in Oren-Nayar) and therefore can have different ranges. Still, if you look at one specific NDF, you will see, how the roughness is used.&#xD;&#xA;&#xD;&#xA;$D(\omega_m) = \frac{\alpha^2}{\pi((\omega_n \cdot \omega_m)^2 (\alpha^2-1)+1)^2}$&#xD;&#xA;&#xD;&#xA;with $\alpha = roughness^2$ (a common remapping), $\omega_m$ is the microfacet normal, $\omega_n$ is the geometry normal.&#xD;&#xA;&#xD;&#xA;You can see here, that the roughness is being treated like a single value. The higher the roughness is, the more random your microfacets (or normals thereof) are distributed. The more that happens, the less your surface will reflect light concentrated into the same direction (i.e. the less highlights you will have). Thus, your material is more diffuse.&#xD;&#xA;&#xD;&#xA;Since now your roughness is a single value, the map makes sense to have only values in $\left[0, 1\right]$ and therefore is a gray scale image." ContentLicense="CC BY-SA 3.0" />
  <row Id="17469" PostHistoryTypeId="2" PostId="6266" RevisionGUID="7050c69f-5b4e-45f7-9639-352671ffa873" CreationDate="2018-02-13T07:36:47.343" UserId="5703" Text="Most normal distribution functions (NDFs) are parametrized by some variable (tipically $m$ or $\alpha$) that determines the &quot;roughness&quot; or &quot;spikiness&quot; of the NDF (this is often meant to be the rms slope of the surface).&#xD;&#xA;&#xD;&#xA;Here is an example of how a roughness parameter effects an NDF: https://www.desmos.com/calculator/kcevxp3wm0&#xD;&#xA;&#xD;&#xA;we can think of the NDF as a function of the direction as well as of the roughness value (as in $D(\theta,\phi,m)$. Here, $\phi$ and $\theta$ were used to represent spherical coordinates for the microsurface normal direction).&#xD;&#xA;&#xD;&#xA;A roughness map can also be thought of as a function: one that returns a value for $m$ for every point $p$ on a surface. Hence, $m(p)$.&#xD;&#xA;&#xD;&#xA;Since $m$ is an argument of the NDF we can write the previous expression like this: $D(\theta,\phi,m(p))$&#xD;&#xA;&#xD;&#xA;And, because $m(p)$ may be different for every $p$ but stays fixed when we only vary $\phi$ and $\theta$, we effectively get a whole different NDF on every point on the surface." ContentLicense="CC BY-SA 3.0" />
  <row Id="17470" PostHistoryTypeId="2" PostId="6267" RevisionGUID="9374246c-f61c-49fb-8fc2-ba19f66f056b" CreationDate="2018-02-13T07:57:56.177" UserId="7008" Text="&gt; The second matrix translates the eye [...]&#xD;&#xA;&#xD;&#xA;You don't do that in a projection matrix. You do that with your view matrix:&#xD;&#xA;&#xD;&#xA; 1. Model (/Object) Matrix transforms an object into World Space&#xD;&#xA; 2. View Matrix transforms all objects from world space to Eye (/Camera) Space (no projection so far!)&#xD;&#xA; 3. Projection Matrix transforms from Eye Space to Clip Space&#xD;&#xA;&#xD;&#xA;Therefore you don't do any matrix multiplications to get to a projection matrix. Those multiplications happen in the shader, where you do $Projection\cdot View \cdot Model$$^1$ Matrix (for example in the vertex shader to specify your position output).&#xD;&#xA;&#xD;&#xA;Also, remember that a perspective projection changes angles (i.e. parallel lines won't be parallel anymore). As far as I can see that is missing in your derivation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;$^1$Assuming you have Column-Major matrices like in OpenGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="17471" PostHistoryTypeId="5" PostId="6254" RevisionGUID="4ab24b2f-7d0f-4c43-99db-c0769966b3c0" CreationDate="2018-02-13T13:21:59.140" UserId="7008" Comment="made the matrices easier readable and homogenized the mathematical writing" Text="This has been haunting me for several days now. I want to find the component that makes up of this 4x4 perspective projection matrix, with $l$(left), $r$(right), $b$(bottom), $t$(top), $n$(near), $f$(far) defining the frustum.&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;\frac{2n}{r-l}&amp;        0&amp;  \frac{r+l}{r-l}&amp;         0\\&#xD;&#xA;0&amp; \frac{2n}{t-b}&amp;  \frac{t+b}{t-b}&amp;         0\\&#xD;&#xA;0&amp;        0&amp; -\frac{f+n}{f-n}&amp;-\frac{2fn}{f-n}\\&#xD;&#xA;0&amp;       0&amp;           -1&amp;         0&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;Here's my approach so far. The first matrix component would just copy $z$ over to $w$ coordinate:&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;    1&amp; 0&amp;  0&amp; 0\\&#xD;&#xA;    0&amp; 1&amp;  0&amp; 0\\&#xD;&#xA;    0&amp; 0&amp;  1&amp; 0\\&#xD;&#xA;    0&amp; 0&amp; -1&amp; 0&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;The second matrix translates the eye ($at = \left(0, 0, 0\right)$) to ($\frac{l+r}{2}$, $\frac{t+b}{2}$, $\frac{n+f}{2}$, the center of the frustum because canonical coordinate is just a cube of size $2$ with its centroid at the origin $\left(0, 0, 0\right)$&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;    1&amp; 0&amp; 0&amp; \frac{l+r}{2}\\&#xD;&#xA;    0&amp; 1&amp; 0&amp; \frac{b+t}{2}\\&#xD;&#xA;    0&amp; 0&amp; 1&amp; \frac{n+f}{2}\\&#xD;&#xA;    0&amp; 0&amp; 0&amp;       1&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;The last matrix just scales the thing so that the frustum fits into the cube of size $2$.&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;    \frac{2}{r-l}&amp;       0&amp;       0&amp; 0\\&#xD;&#xA;          0&amp; \frac{2}{t-b}&amp;       0&amp; 0\\&#xD;&#xA;          0&amp;       0&amp; \frac{2}{f-n}&amp; 0\\&#xD;&#xA;          0&amp;       0&amp;       0&amp; 1 &#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;As you can see the multiplication of these 3 matrices isn't equal to the perspective projection matrix. What am I missing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17472" PostHistoryTypeId="24" PostId="6254" RevisionGUID="4ab24b2f-7d0f-4c43-99db-c0769966b3c0" CreationDate="2018-02-13T13:21:59.140" Comment="Proposed by 7008 approved by 8191 edit id of 311" ContentLicense="CC BY-SA 3.0" />
  <row Id="17473" PostHistoryTypeId="2" PostId="6268" RevisionGUID="905429b6-63bd-4a5b-bf3c-8fcfa26ddf80" CreationDate="2018-02-13T15:05:42.060" UserId="8204" Text="Why don't we just use an hash function to reduce the size of an bitmap,rgb raw image?isn't it more efficient of storage data and it produces lossless image after being decoded?The decoder is also very simple and they would use an universal standard hash code for all images,some private image would have its own hash code.It's an opportunity for us to compress a file to very low capacity without any complicated algorithm and entropy code?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17474" PostHistoryTypeId="1" PostId="6268" RevisionGUID="905429b6-63bd-4a5b-bf3c-8fcfa26ddf80" CreationDate="2018-02-13T15:05:42.060" UserId="8204" Text="why not use hash function image instead of jpeg?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17475" PostHistoryTypeId="3" PostId="6268" RevisionGUID="905429b6-63bd-4a5b-bf3c-8fcfa26ddf80" CreationDate="2018-02-13T15:05:42.060" UserId="8204" Text="|image-processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17476" PostHistoryTypeId="2" PostId="6269" RevisionGUID="8706ae51-0684-4a45-b6ff-e3254d2de1a7" CreationDate="2018-02-13T15:27:03.897" UserId="2041" Text="Unlike a *compression* function, which can be reversed to recover (an approximation to) the original data, a *hash* function is irreversible. You can hash your image, and the hash is a lot smaller than the original image, but you can't get the original image back from the hash.&#xD;&#xA;&#xD;&#xA;A hash function *is* useful for cases where there are only a small number of possible images, which everyone knows about. An example use-case might be something like Telegram or WhatsApp stickers, where there's a fixed set of images, and centrally assigning ID numbers causes distributed systems problems." ContentLicense="CC BY-SA 3.0" />
  <row Id="17477" PostHistoryTypeId="2" PostId="6270" RevisionGUID="3d65793f-5b64-494b-b70b-95033703a04b" CreationDate="2018-02-13T18:16:20.457" UserId="5703" Text="When applying various types of attenuation you are just multiplying by some number smaller than 1.  This is akin to every atom of your material having some probability of absorbing the light that hits it.&#xA;&#xA;Something to note is that these calculations should be performed ( in the context of [gamma correction][1] and colour spaces ) in a linear space.&#xA;&#xA;If you don't perform the calculations in linear space you might end up with overly bright, overly dark, overly saturated or under saturated colours.&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Gamma_correction" ContentLicense="CC BY-SA 3.0" />
  <row Id="17478" PostHistoryTypeId="2" PostId="6271" RevisionGUID="441883c7-463e-41f2-ba15-d4d2a5be1783" CreationDate="2018-02-13T21:13:35.323" UserId="8191" Text="This question perhaps has been asked and answered a thousand times, and yet I haven't found any that satisfy me. The reasons are often these:&#xD;&#xA;&#xD;&#xA;1/ You need a 4 dimensional vector to work with 4x4 matrices.&#xD;&#xA;&#xD;&#xA;2/ You need to have z stored in some way so that you could later use it for z-buffering, etc.&#xD;&#xA;&#xD;&#xA;3/ You need a matrix that is independent of z so that you could multiply matrices together and save computations. Instead of having to multiply each vector with each of the matrix, you could multiply 1 result matrix with each of the vector. &#xD;&#xA;&#xD;&#xA;Here's the problems I have with each of them.&#xD;&#xA;&#xD;&#xA;1. We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w = 1). This is after all Computer Science, not math. &#xD;&#xA;&#xD;&#xA;2. When multiply matrices with vector, we don't need to crush z. Keep it and use it. When drawing, we can pretend that z is already crushed. &#xD;&#xA;&#xD;&#xA;3. You will have to do division by w after projection matrix anyway. Why not divide by z then and get something like [x/z, y/z, z] (I'm not dividing by z because it will be used for z-buffering). Both of them cost 1 computation. &#xD;&#xA;&#xD;&#xA;So why do we need homogenous divide?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17479" PostHistoryTypeId="1" PostId="6271" RevisionGUID="441883c7-463e-41f2-ba15-d4d2a5be1783" CreationDate="2018-02-13T21:13:35.323" UserId="8191" Text="What is the use of homogenous divide?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17480" PostHistoryTypeId="3" PostId="6271" RevisionGUID="441883c7-463e-41f2-ba15-d4d2a5be1783" CreationDate="2018-02-13T21:13:35.323" UserId="8191" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17484" PostHistoryTypeId="2" PostId="6273" RevisionGUID="c0dc6e38-d756-4350-aa0c-bab0fddc4da6" CreationDate="2018-02-13T23:14:24.200" UserId="7462" Text="A long time ago I made an application that used volumetric rendering and I developped some shadowing equations that felt very happy with, since they have pretty good results.&#xD;&#xA;&#xD;&#xA;For these equations to work one needs the closest object that occludes the light (rather than the first)&#xD;&#xA;&#xD;&#xA;However with shadow maps, you invariably get the first point that occludes the light, even if there are points behind it that also occlude the light.&#xD;&#xA;&#xD;&#xA;I had originally intended to use volumetric rendering over shadow maps and use clever hashing for optimization.&#xD;&#xA;&#xD;&#xA;But 800 triangles consume 90% of a GTX 1070's cpus power. In other words, just 800 triangle checks per fragment are enough to lag the entire pipeline.&#xD;&#xA;&#xD;&#xA;I wanted to know if there is a way to get the distance to the closest point occluding the light (from the fragment perspective) using shadow maps. Or if I have to give away with my pretty shadows" ContentLicense="CC BY-SA 3.0" />
  <row Id="17485" PostHistoryTypeId="1" PostId="6273" RevisionGUID="c0dc6e38-d756-4350-aa0c-bab0fddc4da6" CreationDate="2018-02-13T23:14:24.200" UserId="7462" Text="How can you efficiently get the last element occluding light when renderign shadows?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17486" PostHistoryTypeId="3" PostId="6273" RevisionGUID="c0dc6e38-d756-4350-aa0c-bab0fddc4da6" CreationDate="2018-02-13T23:14:24.200" UserId="7462" Text="|shadow|shading|shadow-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17487" PostHistoryTypeId="5" PostId="6273" RevisionGUID="f915b369-829d-44df-98ef-057287536f01" CreationDate="2018-02-14T00:31:02.407" UserId="7462" Comment="added 277 characters in body" Text="A long time ago I made an application that used volumetric rendering and I developped some shadowing equations that felt very happy with, since they have pretty good results.&#xD;&#xA;&#xD;&#xA;For these equations to work one needs the closest object that occludes the light (rather than the first)&#xD;&#xA;&#xD;&#xA;However with shadow maps, you invariably get the first point that occludes the light, even if there are points behind it that also occlude the light.&#xD;&#xA;&#xD;&#xA;I had originally intended to use volumetric rendering over shadow maps and use clever hashing for optimization.&#xD;&#xA;&#xD;&#xA;But 800 triangles consume 90% of a GTX 1070's cpus power. In other words, just 800 triangle checks per fragment are enough to lag the entire pipeline.&#xD;&#xA;&#xD;&#xA;I wanted to know if there is a way to get the distance to the closest point occluding the light (from the fragment perspective) using shadow maps. Or if I have to give away with my pretty shadows&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;When I refer to distance I am speaking about distance from the occluded point tot he light. So if A is a surface and R is the ray from that surface to the light, then the &quot;closest&quot; point is a point right on A and the &quot;farthest&quot; point is a point right on the light.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;As er request, a poorly drawn diagram of what I mean. There are 2 walls occluding the light and one is closer to the shadow point than the other&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4L3u7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17488" PostHistoryTypeId="2" PostId="6274" RevisionGUID="25f50388-28fc-4ec1-857c-9fc6d8e9119e" CreationDate="2018-02-14T08:51:25.613" UserId="209" Text="Some very quick answers:&#xD;&#xA;&#xD;&#xA;&gt; We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w =1). This is after all Computer Science, not math. &#xD;&#xA;&#xD;&#xA;Ahh.. but sometimes in graphics we don't have w=1. Some examples that come to mind are&#xD;&#xA;&#xD;&#xA; 1. Placing a vertex at &quot;infinity&quot;, e.g. for shadow volumes &#xD;&#xA; 1. Representing directions rather than absolute positions&#xD;&#xA; 1. Doing rational curves. e.g. $\frac{Quadratic Bezier()}{Quadratic Bezier()}$ to represent, say, conic sections.&#xD;&#xA;&#xD;&#xA;I'm sorry, I've no idea what you mean by *&quot;to crush z&quot;*, but sometimes, if chosen carefully, after the projection transform you may be able to get by with just 3 terms, e.g. (X/W, Y/W, 1/W) assuming you also have the post-projection texture coordinates, (U/W, V/W).&#xD;&#xA;&#xD;&#xA;&gt;I'm not dividing by z because it will be used for z-buffering&#xD;&#xA;&#xD;&#xA;Typically, despite the name, the Z-buffer contains an interpolated 1/W, 1/Z, or some linear function of one of these.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  -&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17489" PostHistoryTypeId="5" PostId="6267" RevisionGUID="455c08b7-c9a3-4a96-933d-01930997b7ec" CreationDate="2018-02-14T10:23:57.353" UserId="7008" Comment="Added the complete derivation of the projection matrix" Text="&gt; The second matrix translates the eye [...]&#xD;&#xA;&#xD;&#xA;You don't do that in a projection matrix. You do that with your view matrix:&#xD;&#xA;&#xD;&#xA; 1. Model (/Object) Matrix transforms an object into World Space&#xD;&#xA; 2. View Matrix transforms all objects from world space to Eye (/Camera) Space (no projection so far!)&#xD;&#xA; 3. Projection Matrix transforms from Eye Space to Clip Space&#xD;&#xA;&#xD;&#xA;Therefore you don't do any matrix multiplications to get to a projection matrix. Those multiplications happen in the shader, where you do $Projection\cdot View \cdot Model$$^1$ Matrix (for example in the vertex shader to specify your position output).&#xD;&#xA;&#xD;&#xA;Also, remember that a perspective projection changes angles (i.e. parallel lines won't be parallel anymore). As far as I can see that is missing in your derivation.&#xD;&#xA;&#xD;&#xA;***Edit***&#xD;&#xA;&#xD;&#xA;As to how you actually derive it, I'll largely use the explanation by[Etay Meiri][1]. It has some additional information and illustration, so you may want to check it, if something seems unclear.&#xD;&#xA;&#xD;&#xA;First, your camera is (as mentioned earlier) positioned in the origin.&#xD;&#xA;Now assume, you will only project onto a plane of distance $d$ and the plane you project onto is bounded by the aspect ration $ar$ (that is $ar = \frac{window\text{ }width}{window\text{ }height}$ in positive and negative $x$ direction and by $1$ in positive and negative $y$ direction.&#xD;&#xA;&#xD;&#xA;You can now determine $d$ by your vertical field of view $\alpha$ (since looking from the side, your camera, the center at the top of your projection plane and the center of the bottom of your projection plane build a triangle and your vertical field of view is the angle at your camera):&#xD;&#xA;&#xD;&#xA;$\frac{1}{d} = \tan(\frac{\alpha}{2})\\&#xD;&#xA;\implies d = \frac{1}{\tan(\frac{\alpha}{2})}$&#xD;&#xA;&#xD;&#xA;Now you go about calculating projected points. Assume you have an arbitrary point $v = (v_x, v_y, v_z)$, and you want to calculate the point on your plane $p = (p_x, p_y, d)$. Looking at it from the side again, the triangle with your camera, your projection plane top center point and your projected point is similar to the triangle with your camera, your projection plane top center prolonged to have the same z coordinate, as your point $v$ and the point $v$, i.e. they have the same angles$^2$. Therefore, you can now calculate the projected $p_x$ and $p_y$ coordinate:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\frac{p_y}{d} = \frac{v_y}{v_z} \implies p_y = \frac{v_y\cdot d}{v_z} = \frac{v_y}{v_z \cdot \tan(\frac{\alpha}{2})}\\&#xD;&#xA;\frac{p_x}{d} = \frac{v_x}{v_x} \implies p_x = \frac{v_x\cdot d}{v_z} = \frac{v_x}{v_x \cdot \tan(\frac{\alpha}{2})}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;To additionally take into account, that the projection plane ranges from $-ar$ to $ar$ in $x$ direction, you would add $ar$ to the denominator in order to make the projected $x$ range be $\left[-1, 1\right]$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;p_x = \frac{v_x}{ar \cdot v_x \cdot \tan(\frac{\alpha}{2})}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;If you think about applying this to a matrix now, you need to take into account the division by $z$, which is different for any point with differing $z$ value. Therefore, the division by z is deferred until after the projection matrix is applied (and is done without any code of you, i.e. for OpenGL you'd specify the `gl_Position` in Clip Space ($\implies$ after projection) and the division is done for you).&#xD;&#xA;&#xD;&#xA;The depth test (Z-Test) still needs the $z$ value though, so it needs to be &quot;safed&quot; from the $z$ divide. Therefore you copy your $z$ value to the $w$ component (which is what you got right in your assumption) and end up with the following matrix:&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;\frac{1}{ar\cdot\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;\frac{1}{\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;1&amp;0&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;The next step is to not project onto a plane, but into a $z$ range of $\left[-1, 1\right]$ (this range is for correct clipping, as is the same range when handling the $x$ and the $y$ coordinate). To be more specific, you don't want all points to end up in that range, but all points between your near and your far plane, so you map $[n, f]$ to $[-1, 1]$.&#xD;&#xA;The resulting range is $2$, so you first scale your near-to-far range to $2$. Then you move it to be $[-1, 1]$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;f(z) = A\cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And now taking into account that we want to safe the $z$ value from $z$ divide, we get to&#xD;&#xA;&#xD;&#xA;$f(z) = A + \frac{B}{z}$&#xD;&#xA;&#xD;&#xA;Mapping this scaling to $[-1, 1]$ is a little bit of leg work: you know that any point with $z = n$ (on your near plane) will be projected to $p_z = -1$ and any point with $z = f$ (on your far plane) will be projected to $p_z = 1$. This leads to the following equation system:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;A + \frac{B}{n} = -1\\&#xD;&#xA;A + \frac{B}{f} = 1&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Solving this for $A$ and $B$ leads to$^3$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;A = \frac{-n-f}{n-f}\\&#xD;&#xA;B = \frac{2fn}{n-f}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Your third row of the projection matrix must produced the (undivided) $p_z$ (projected) z value. Therefore, you can now choose the individual elements of said row $(\begin{array}{cccc}a&amp;b&amp;c&amp;d\end{array})$ such that the correct $z$ value is produced when multiplying with your point. The correct $p_z$ value is (as established earlier):&#xD;&#xA;$p_z = A\cdot z + B$&#xD;&#xA;&#xD;&#xA;Therefore this must be the right hand side of your multiplication. Assume your point to project is $(x, y, z, w)$, then &#xD;&#xA;you must achieve the following:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;a \cdot x + b \cdot y + c \cdot z + d \cdot w = A \cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Obviously, your point's $x$ and $y$ coordinate should not influence the projected $z$ coordiante, so you can set $a$ and $b$ to $0$.&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;c \cdot z + d \cdot w = A \cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Since you know that $w$ for any point is $1$, you're left with&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;c \cdot z + d = A \cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And thus, you have $c = A$ and $d = B$.&#xD;&#xA;&#xD;&#xA;Now your matrix is complete for projection&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;\frac{1}{ar\cdot\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;\frac{1}{\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;\frac{-n-f}{n-f}&amp;\frac{2fn}{n-f}\\&#xD;&#xA;0&amp;0&amp;1&amp;0&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;Obviously, the tutorial works a little differently in projecting with the vertical field of view, so we can take a look at how you can additionally get to that (with the help of [Eric Lengyel][2]:&#xD;&#xA;&#xD;&#xA;Instead of projecting onto a plane at $z = d$, we will project onto the near plane, and thus get for a point $v = (v_x, v_y, v_z)$ the projected point $p = (p_x, p_y, n)$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;p_x = \frac{v_x \cdot n}{v_z}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Additionally, you want to map any point with $l\leq x \leq r$ to $\left[-1, 1\right]$, as before.&#xD;&#xA;Thus you get &#xD;&#xA;&#xD;&#xA;$f(x) = (x-l) \frac{2}{r-l}-1$&#xD;&#xA;&#xD;&#xA;Combine those two and you achieve&#xD;&#xA;&#xD;&#xA;$p_x = \frac{2n}{r-l}\left(-\frac{v_x}{v_y}\right)- \frac{r+l}{r-l}$&#xD;&#xA;&#xD;&#xA;Now put this (and the term for $y$) into the matrix and you get to the first row, first column being  $\frac{2n}{r-l}$, and the first row, third column being $\frac{r+l}{r-l}$. Since you may assume $r$ and $l$ to be different, here you can see why those two matrices differ. $r$ and $l$ are guaranteed to be the same in the tutorial's matrix and therefore you get $r+l = ar-ar = 0$ in the denominator, making the third row first column (and second column accordingly) $0$.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;$^1$Assuming you have Column-Major matrices like in OpenGL$&#xD;&#xA;&#xD;&#xA;$^2$For the $x$ calculation, you will need to take a different point of your projection plane of course, but the idea is the same&#xD;&#xA;&#xD;&#xA;$^3$The differences of the sign come from how you orient your camera: in your assumption it is along the negative $z$ axis, whereas in the tutorial it is along the positive $z$ axis&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial12/tutorial12.html&#xD;&#xA;  [2]: http://mathfor3dgameprogramming.com/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17490" PostHistoryTypeId="2" PostId="6275" RevisionGUID="ff920a9a-0870-4208-a899-2b5e2758baab" CreationDate="2018-02-14T11:23:27.570" UserId="6046" Text="First of all we need to understand why do we need 4x4 matrices in the first place. With 3x3, we couldn't represent translation as it wasn't a linear transformation (it displaces the origin). So in order to avoid extra work, homogeneous coordinates and affine transformation was introduced. &#xD;&#xA;&#xD;&#xA;Now instead of doing&#xD;&#xA; &#xD;&#xA; $v' = Lv + t$ &#xD;&#xA;&#xD;&#xA;where `L` is a linear transform and `t` is the translation, we can do&#xD;&#xA;&#xD;&#xA;$v' = Av$&#xD;&#xA;&#xD;&#xA;Where `A` is the affine matrix. This makes it cleaner. So 4x4 matrices are a real necessity, we just can't work without them. In order to distinguish between vectors and points we use `w = 1` for points and `w = 0` for vectors. So you are suggesting to make this 4th dimension implicit and don't store it as it'll actually use space/memory.&#xD;&#xA;&#xD;&#xA;&gt; We can pretend that the 3 dimensional vector is 4 dimensional (imaginary w = 1). This is after all Computer Science, not math.&#xD;&#xA;&#xD;&#xA;This works but up-to a certain extent. Using this approach we would have 4x4 matrices and 3 dimensional row/column vectors. But now when doing multiplication we will have to make a check whether it's point or vector and based on that we multiply the elements of the 4th column of the transformation matrix by `0` or `1`.&#xD;&#xA;&#xD;&#xA;This alone starts creating mess, check every time whether it's a point or a vector so why not just use the space for a single float more and get rid of this stupid check.&#xD;&#xA;&#xD;&#xA;That aside most modern CPUs have SIMD registers 128 bits wide perfect to fit 4D vectors. If you are doing your calculations on the GPU, all the more reason to store 4D vectors as branching instructions are much more costly on the GPU.&#xD;&#xA;&#xD;&#xA;If you start feeling the need to use 4D, great. If not then we still have the problem of composing matrix transformations. Instead of multiplying individual transformations with our vector we would like to pre-multiply all of the transformations then do a single vector-matrix multiplication. This can't work with projective transformations where we need to divide by &quot;something&quot;&#xD;&#xA;&#xD;&#xA;Let's come to reason number 3.&#xD;&#xA;&#xD;&#xA;&gt; You will have to do division by w after projection matrix anyway. Why not divide by z then and get something like [x/z, y/z, z]. Both of them cost 1 computation.&#xD;&#xA;&#xD;&#xA;This is the simple case for just a projective transformation. Consider the vector going through 5 or 6 transformations  and in the last comes the projective transformation. If we pre-multiply all these transformation to create a single matrix, you will notice that now when we multiply the vector with this combined transformation matrix the division factor isn't just a simple `-z` value. The 4th row of the matrix won't be `0 0 -1 0` as in the standard projection matrix. It might have changed due to multiplying all the transformations together. Now when you multiply that 4th row with the 4D vector, you will get your `w` value by which you need to divide now. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17496" PostHistoryTypeId="2" PostId="6278" RevisionGUID="a5de4e72-1676-49be-b18f-870eb69e1d66" CreationDate="2018-02-14T18:02:32.777" UserId="7622" Text="I have a quad-based mesh. I want to:&#xD;&#xA;&#xD;&#xA;- remesh it while keeping the shape the same&#xD;&#xA;- the end output should be in quads&#xD;&#xA;- ideally it should have a similar number of verts / polys as the input&#xD;&#xA;- ideally the remeshing would be random, and output mesh would be distinct from the input&#xD;&#xA;&#xD;&#xA;Right now I'm remeshing with Meshlab, which outputs tris. I then use the Tris to Quads function from Blender. The problem is that that function is not perfect, and leaves many tris. &#xD;&#xA;&#xD;&#xA;So ideally there'd be a quad-based random remesh tool, but if anyone knows of a better tri-to-quad tool that would also be helpful?&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="17497" PostHistoryTypeId="1" PostId="6278" RevisionGUID="a5de4e72-1676-49be-b18f-870eb69e1d66" CreationDate="2018-02-14T18:02:32.777" UserId="7622" Text="Best way to remesh a mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17498" PostHistoryTypeId="3" PostId="6278" RevisionGUID="a5de4e72-1676-49be-b18f-870eb69e1d66" CreationDate="2018-02-14T18:02:32.777" UserId="7622" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17499" PostHistoryTypeId="4" PostId="6278" RevisionGUID="25abfca3-dfe6-4c3b-8a1d-10302669c843" CreationDate="2018-02-14T21:31:07.763" UserId="506" Comment="added important detail in title" Text="Best way to remesh a quad mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17500" PostHistoryTypeId="24" PostId="6278" RevisionGUID="25abfca3-dfe6-4c3b-8a1d-10302669c843" CreationDate="2018-02-14T21:31:07.763" Comment="Proposed by 506 approved by 2041 edit id of 313" ContentLicense="CC BY-SA 3.0" />
  <row Id="17501" PostHistoryTypeId="2" PostId="6279" RevisionGUID="037aa170-f584-4634-8756-17abc34a11cf" CreationDate="2018-02-15T04:44:21.353" UserId="5703" Text="After some testing and some research I have found that both the $\sin(\theta)$ and the $\cos(\theta)$ should be removed from the denominator.&#xD;&#xA;&#xD;&#xA;the reasoning is that, since we want a probability function of steradians instead of angles, the $\sin(\theta)$ factor (which is essentially used to convert from steradians on a unit sphere to radians on the two polar axis) should be dropped.&#xD;&#xA;&#xD;&#xA;Also, $\cos(\theta)$ (as Nathan Reed explains in [this][1] blog post) is there to convert from microfacet area to macrosurface area. Since we are generating microsurface samples, this should be removed.&#xD;&#xA;&#xD;&#xA;After these corrections we get the formula&#xD;&#xA;&#xD;&#xA;$$L_o(p,\omega_o)\approx\frac{1}{N}\sum_{i=1}^{N}\frac{L_i(p,\omega_i)FG}{4(n\cdot\omega_o)}$$&#xD;&#xA;&#xD;&#xA;which is free of the artifacts of the formula on the question.&#xD;&#xA;&#xD;&#xA;  [1]: http://reedbeta.com/blog/hows-the-ndf-really-defined/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17502" PostHistoryTypeId="2" PostId="6280" RevisionGUID="6c80a2e3-1f12-4482-a89d-6e421940182f" CreationDate="2018-02-15T06:16:06.530" UserId="5703" Text="When implementing transmission into a path tracer you have to keep in mind that neither BRDF's nor your previous sampling method are gonna cut it. You will need to think about what happens to light on both sides of your surface, which is where BTDF's and, more generally, BSDF's come in (the T and the S stand for Transmittance and Scattering, respectively).&#xD;&#xA;&#xD;&#xA;It can be somewhat non-trivial to implement transmission to a path tracer that currently only supports reflection.&#xD;&#xA;&#xD;&#xA;While i can't offer help with implementation details i can give you a few starting points and things you might want to read while you embarc on implementing this capabilty on your path tracer.&#xD;&#xA;&#xD;&#xA;On refraction.&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;Pure and/or glossy refraction is a very common way of transmission, it is the type of transmission that happens on glass and probably what you are looking to implement.&#xD;&#xA;&#xD;&#xA;[Snell's Law.][1]&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Light directions in refraction follow a simple mathematical law.&#xD;&#xA;&#xD;&#xA;$$n_1\sin(\theta_1)=n_2\sin(\theta_2)$$&#xD;&#xA;&#xD;&#xA;this reads as: the sine of the transmitted angle $\theta_2$ equals the sine of the incoming direction $\theta_1$ times the ratio of the &quot;outside&quot; [index of refraction][2] and the &quot;inside&quot; index of refraction $\frac{n_1}{n_2}$&#xD;&#xA;&#xD;&#xA;[The GGX paper.][3]&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;There is a wonderful paper titled &quot;Microfacet Models for Refraction through Rough Surfaces&quot; that goes over a good piece of the theory behind microfacet models for refraction and presents a really quite good model for it.&#xD;&#xA;&#xD;&#xA;Fresnel and Monte-Carlo.&#xD;&#xA;====&#xD;&#xA;&#xD;&#xA;when rendering a material that has both reflective and transmissive components there are a few different approaches that you can take to mix the two.&#xD;&#xA;&#xD;&#xA;two main ways come to mind&#xD;&#xA;&#xD;&#xA;1. The Monte-Carlo way&#xD;&#xA;----&#xD;&#xA;Do a &quot;coin flip&quot; with probabilities weighted according to the calculated fresnel value for each rendered point. Depending on the result you do transmission or reflection&#xD;&#xA;&#xD;&#xA;2. The recursive branching way&#xD;&#xA;----&#xD;&#xA;Generate a reflected ray and path trace.&#xD;&#xA;Generate a transmitted ray and path trace.&#xD;&#xA;Mix the two found color values according to Fresnel value for every rendered point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really hope this information is of use in solving your issue, and good luck! Great to see new users on the site.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Snell%27s_law&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Refractive_index&#xD;&#xA;  [3]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="17505" PostHistoryTypeId="2" PostId="6281" RevisionGUID="093cd318-e8c0-4140-8e50-e8e00cb05f39" CreationDate="2018-02-15T14:57:45.743" UserId="2372" Text="In my vertex shader I am using a `sin` function to offset vertices. But as I change the frequency of my `sin` function I notice some &quot;flickering&quot; or &quot;jumps&quot;. I guess that this comes from the fact that the phase is not synchronised any more.&#xD;&#xA;&#xD;&#xA;    float s = sin(frequency * _Time);&#xD;&#xA;&#xD;&#xA;Is there a way to avoid those flickering effect while changing the frequency ?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17506" PostHistoryTypeId="1" PostId="6281" RevisionGUID="093cd318-e8c0-4140-8e50-e8e00cb05f39" CreationDate="2018-02-15T14:57:45.743" UserId="2372" Text="Changing sin frequency smoothly in shader" ContentLicense="CC BY-SA 3.0" />
  <row Id="17507" PostHistoryTypeId="3" PostId="6281" RevisionGUID="093cd318-e8c0-4140-8e50-e8e00cb05f39" CreationDate="2018-02-15T14:57:45.743" UserId="2372" Text="|shader|glsl|mathematics|hlsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17511" PostHistoryTypeId="2" PostId="6283" RevisionGUID="f5874536-2e77-4fb7-af61-fde4e83b6eb4" CreationDate="2018-02-15T16:37:13.300" UserId="5703" Text="You could go the calculus way and have an explicit rate of change that is outside your shader&#xA;&#xA;    float frequency = getFrequency();&#xA;    sineTime += frequency * deltaTime;&#xA;&#xA;(`sineTime` could be a float that is scoped right outside of your render loop, so that it retains its value)&#xA;&#xA;And if you pass `sineTime` into your shader you can just do&#xA;&#xA;    float s = sin(sineTime);" ContentLicense="CC BY-SA 3.0" />
  <row Id="17512" PostHistoryTypeId="2" PostId="6284" RevisionGUID="719ae386-19ea-4cfb-a4f1-f2cbd751b340" CreationDate="2018-02-15T18:08:40.973" UserId="6046" Text="So I want to implement a path tracer and I am confused between GPGPU computing or using OpenGL's compute shaders. I've already implemented a raytracer using GL's compute shaders. &#xD;&#xA;&#xD;&#xA;What are the main differences between CUDA/OpenCL and CS? And is it possible to see a significant speed up if I prefer one over the other? Some main differences I already know are that using CS will make it vendor independent so I could run it on PCs having Nvidia/Amd GPUs alike. CUDA supports recursion while openCL/opengl CS don't. &#xD;&#xA;&#xD;&#xA;What are other significant functionalities that would make a person prefer opencl/cuda over CS?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17513" PostHistoryTypeId="1" PostId="6284" RevisionGUID="719ae386-19ea-4cfb-a4f1-f2cbd751b340" CreationDate="2018-02-15T18:08:40.973" UserId="6046" Text="CUDA/OpenCL vs OpenGL compute shader for Path tracer" ContentLicense="CC BY-SA 3.0" />
  <row Id="17514" PostHistoryTypeId="3" PostId="6284" RevisionGUID="719ae386-19ea-4cfb-a4f1-f2cbd751b340" CreationDate="2018-02-15T18:08:40.973" UserId="6046" Text="|compute-shader|opencl|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17515" PostHistoryTypeId="50" PostId="5996" RevisionGUID="daa782c3-dd0c-4ee0-91fa-916f2ad36a6a" CreationDate="2018-02-15T22:42:36.713" UserId="-1" />
  <row Id="17516" PostHistoryTypeId="2" PostId="6285" RevisionGUID="e3676897-61f2-4403-86a3-d27e9916c574" CreationDate="2018-02-16T11:28:38.973" UserId="2372" Text="I am trying to scale and repeat a Cubemap with Latitude-Longitude mapping layout just as you would do with classical UV mapping but without any interesting result. This should be used as a skybox.&#xD;&#xA;&#xD;&#xA;This comes from the fact that the coordinates are in 3D space and we can't apply this simple formula `texcoord.xy * scale.xy + offset.xy`&#xD;&#xA;&#xD;&#xA;How would you handle such features : scaling which involves tiling and offsetting.&#xD;&#xA;&#xD;&#xA;    samplerCUBE _TexCube;&#xD;&#xA;    texCUBE(_TexCube, float3);" ContentLicense="CC BY-SA 3.0" />
  <row Id="17517" PostHistoryTypeId="1" PostId="6285" RevisionGUID="e3676897-61f2-4403-86a3-d27e9916c574" CreationDate="2018-02-16T11:28:38.973" UserId="2372" Text="How to scale and offset a cubemap using sphere mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="17518" PostHistoryTypeId="3" PostId="6285" RevisionGUID="e3676897-61f2-4403-86a3-d27e9916c574" CreationDate="2018-02-16T11:28:38.973" UserId="2372" Text="|texture|shader|glsl|hlsl|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17519" PostHistoryTypeId="2" PostId="6286" RevisionGUID="0551fb4c-9242-499c-b737-d3925d10441e" CreationDate="2018-02-16T12:53:17.267" UserId="2372" Text="This doesn't really answer the question but is a workaround. Beware it's hack time :)&#xD;&#xA;&#xD;&#xA;Instead of using the `texCUBE` and `samplerCube` I'll be using the `tex2D` method and a simple `sampler` to sample the texture.&#xD;&#xA;&#xD;&#xA;As I am using a sphere mesh, I generate 2D UVs like this.&#xD;&#xA;&#xD;&#xA;    float x = atan2(vertex.x, vertex.z) / PI;&#xD;&#xA;    x = x / 2.0 + 0.5; // To remap from 0 to 1&#xD;&#xA;    float y = vertex.y / 2.0 + 0.5; // Also remap from 0 to 1&#xD;&#xA;    float3 color = tex2D(sampler, float2(x, y) * scale.xy + offset.xy);&#xD;&#xA;&#xD;&#xA;It's a bit hacky but using this I have 2D texture coordinates for my texture." ContentLicense="CC BY-SA 3.0" />
  <row Id="17521" PostHistoryTypeId="5" PostId="6273" RevisionGUID="0d0d3333-6be6-48ab-b73f-a30d3792e2f8" CreationDate="2018-02-16T21:25:14.430" UserId="5703" Comment="fixed misspellings and ambiguity." Text="A long time ago I made an application that used volumetric rendering and I developed some shadowing equations that I felt very happy with, since they have pretty good results.&#xD;&#xA;&#xD;&#xA;For these equations to work one needs the object that occludes the light that is closest to the currently-being-shaded fragment (rather than the one closest to the light source)&#xD;&#xA;&#xD;&#xA;However, with shadow maps, you invariably get the first point that occludes the light, even if there are points behind it that also occlude the light.&#xD;&#xA;&#xD;&#xA;I had originally intended to use volumetric rendering over shadow maps and use clever hashing for optimization.&#xD;&#xA;&#xD;&#xA;But 800 triangles consume 90% of a GTX 1070's cpus power. In other words, just 800 triangle checks per fragment are enough to lag the entire pipeline.&#xD;&#xA;&#xD;&#xA;I wanted to know if there is a way to get the distance to the closest point occluding the light (from the fragment perspective) using shadow maps. Or if I have to give away with my pretty shadows&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;When I refer to distance I am speaking about distance from the occluded point to the light. So if A is a surface and R is the ray from that surface to the light, then the &quot;closest&quot; point is a point right on A and the &quot;farthest&quot; point is a point right on the light.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;As per request, a poorly drawn diagram of what I mean. There are 2 walls occluding the light and one is closer to the shadow point than the other&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4L3u7.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17522" PostHistoryTypeId="4" PostId="6273" RevisionGUID="0d0d3333-6be6-48ab-b73f-a30d3792e2f8" CreationDate="2018-02-16T21:25:14.430" UserId="5703" Comment="fixed misspellings and ambiguity." Text="How can you efficiently get the last element occluding light when rendering shadows?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17523" PostHistoryTypeId="24" PostId="6273" RevisionGUID="0d0d3333-6be6-48ab-b73f-a30d3792e2f8" CreationDate="2018-02-16T21:25:14.430" Comment="Proposed by 5703 approved by 4958, 231 edit id of 314" ContentLicense="CC BY-SA 3.0" />
  <row Id="17524" PostHistoryTypeId="2" PostId="6287" RevisionGUID="e85f21af-6a95-4354-9183-d3541d66fc77" CreationDate="2018-02-16T23:31:19.157" UserId="8222" Text="To first clear your confusion around the terms:&#xD;&#xA;&#xD;&#xA;GPGPU stands for **G**eneral **P**urpose computing on GPUs&#xD;&#xA;&#xD;&#xA;**CUDA** is the specific NVIDIA API to perform GPGPU only on their hardware&#xD;&#xA;&#xD;&#xA;**OpenGL** is a graphics specific API and is vendor independent  &#xD;&#xA;**OpenCL** is a parallel programming compute API and is vendor independent&#xD;&#xA;&#xD;&#xA;**Compute Shaders** are a way to perform general purpose computations within  &#xD;&#xA;a rendering system but without being part of a fixed rendering architecture.  &#xD;&#xA;They exist for OpenGL (https://www.khronos.org/opengl/wiki/Compute_Shader)  &#xD;&#xA;but also for other graphics APIs like DirectX (DirectCompute) etc.&#xD;&#xA;&#xD;&#xA;OpenCL is not only built for GPUs and can also be used to write code  &#xD;&#xA;for example to run massive parallel computations on supercomputers. &#xD;&#xA;&#xD;&#xA;NVIDIA develops their own ray tracer based on CUDA and GPU computing.  &#xD;&#xA;The project is called Optix (https://developer.nvidia.com/optix)&#xD;&#xA;&#xD;&#xA;To your performance question. It depends, as always on your setup and use case.  &#xD;&#xA;Some people did already the effort to measure differences. &#xD;&#xA;One paper for example is this:&#xD;&#xA;https://arxiv.org/ftp/arxiv/papers/1005/1005.2581.pdf&#xD;&#xA;&#xD;&#xA;Another one is this:&#xD;&#xA;https://dl.acm.org/citation.cfm?id=2066955&#xD;&#xA;&#xD;&#xA;Or one thesis about it:&#xD;&#xA;https://liu.diva-portal.org/smash/get/diva2:909410/FULLTEXT01.pdf&#xD;&#xA;&#xD;&#xA;In their comparisons did CUDA often show good results. But when they for example used image processing algorithms that can be parallized very efficiently from the GPU then the comparison is nearly worthless compared what you might do in your path tracing code.&#xD;&#xA;&#xD;&#xA;If you do not use any &quot;classic&quot; rendering, which you wanna combine your path traced results, I see not why you should use compute shaders for a pure path tracer. If platform independence is important OpenCL might be interesting for you since you then can take the code and run it on a complete other hardware for comparison. If you will stick to NVIDIA GPUs anyways you will likely get better performance using directly CUDA.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17525" PostHistoryTypeId="50" PostId="6012" RevisionGUID="4bad8158-992d-4f70-a246-73c6c2440d2e" CreationDate="2018-02-17T12:51:30.147" UserId="-1" />
  <row Id="17526" PostHistoryTypeId="2" PostId="6288" RevisionGUID="67937260-ae3c-4139-ab45-fd8768627687" CreationDate="2018-02-17T16:21:31.047" UserId="8118" Text="Not sure if Ogre does it implicitely, but using a 4x4 matrix to transform a 3D point to get the correct 2D coordinates (as it would be rendered with the same matrix),  requires a transition from homogeneous coordinates by dividing the result by w. &#xD;&#xA;&#xD;&#xA;In other words, you must multiply the matrix by a 4-component vector (x,y,z,1.0f) instead of a 3-component vector. And then the resulting vector will look like (X,Y,Z,W) and you need to divide by W to get the position like it would be rendered. &#xD;&#xA;&#xD;&#xA;Like this: &#xD;&#xA;&#xD;&#xA;    // Transform world coordinates.&#xD;&#xA;    Ogre::Vector4 transformedWorldPosition = worldViewProjection * Ogre::Vector4(worldPosition,1.0);&#xD;&#xA;&#xD;&#xA;    //Divide by w &#xD;&#xA;    transformedWorldPosition = transformedWorldPosition / transformedWorldPosition.w; &#xD;&#xA;&#xD;&#xA;    // Calculate screen coordinates from world coordinates.&#xD;&#xA;    Ogre::Vector2 screenPosition;&#xD;&#xA;    screenPosition.x = (int) ( ( ( transformedWorldPosition.x + 1 ) / 2.0 ) * screenRes.width + 0.5 );&#xD;&#xA;    screenPosition.y = (int) ( ( ( 1 - transformedWorldPosition.y ) / 2.0 ) * screenRes.height + 0.5 );&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17527" PostHistoryTypeId="2" PostId="6289" RevisionGUID="028bb323-548a-4004-8319-f5f3eb932860" CreationDate="2018-02-17T20:29:55.617" UserId="8191" Text="I am writing a simple ray tracer. I was working on my camera matrix when I encountered a problem. When I changed the look vector, so that it headed down, the image, which was supposed to go up, actually went down as well. Likewise, if I changed the look vector so that it headed up, the image went with it.&#xD;&#xA;I understand that the camera matrix's job is to change world coordinate into eye coordinate. Since I am using column matrices, here's my camera matrix, with r being right vector, l being lookAt vector and u being up vector&#xD;&#xA;&#xD;&#xA;[&#xD;&#xA;&#xD;&#xA;rx, ux, -lx, 0&#xD;&#xA;&#xD;&#xA;ry, uy, -ly, 0&#xD;&#xA;&#xD;&#xA;rz, uz, -lz, 0&#xD;&#xA;&#xD;&#xA; 0,  0,   0, 1&#xD;&#xA;&#xD;&#xA;]&#xD;&#xA;&#xD;&#xA;This is the transpose of the gluLookAt matrix of openGL. I dont understand why openGL use their matrix though, since they are also using column matrices. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17528" PostHistoryTypeId="1" PostId="6289" RevisionGUID="028bb323-548a-4004-8319-f5f3eb932860" CreationDate="2018-02-17T20:29:55.617" UserId="8191" Text="Is there something wrong with a column camera matrix?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17529" PostHistoryTypeId="3" PostId="6289" RevisionGUID="028bb323-548a-4004-8319-f5f3eb932860" CreationDate="2018-02-17T20:29:55.617" UserId="8191" Text="|3d|transformations|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17530" PostHistoryTypeId="5" PostId="6289" RevisionGUID="4aef4323-3d3c-4ec2-8c65-1c990c4d151a" CreationDate="2018-02-17T23:13:36.213" UserId="48" Comment="math formatting" Text="I am writing a simple ray tracer. I was working on my camera matrix when I encountered a problem. When I changed the look vector, so that it headed down, the image, which was supposed to go up, actually went down as well. Likewise, if I changed the look vector so that it headed up, the image went with it.&#xD;&#xA;I understand that the camera matrix's job is to change world coordinate into eye coordinate. Since I am using column matrices, here's my camera matrix, with $r$ being right vector, $l$ being lookAt vector and $u$ being up vector&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;r_x &amp; u_x &amp; -l_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; -l_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; -l_z &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This is the transpose of the gluLookAt matrix of openGL. I dont understand why openGL use their matrix though, since they are also using column matrices. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17531" PostHistoryTypeId="2" PostId="6290" RevisionGUID="6503b91a-ef41-460e-9651-a2287c6242ab" CreationDate="2018-02-17T23:27:20.947" UserId="48" Text="What you have there is the matrix that goes _from_ eye space (camera space) _to_ world space. You can see this by observing that, for instance, if you apply this matrix to the column vector $[1, 0, 0, 0]^T$, which is the right-vector in eye space, then it will return $[r_x, r_y, r_z, 0]^T$, the right-vector in world space.&#xD;&#xA;&#xD;&#xA;You want the matrix that transforms the other direction, which would be the inverse of this one. And assuming $r, u, l$ form an orthonormal basis, the inverse will simply be the transpose." ContentLicense="CC BY-SA 3.0" />
  <row Id="17532" PostHistoryTypeId="50" PostId="5892" RevisionGUID="3664ba57-c5e6-4ce9-93ad-7f16967a0e0b" CreationDate="2018-02-18T04:55:46.120" UserId="-1" />
  <row Id="17533" PostHistoryTypeId="2" PostId="6291" RevisionGUID="ea5ffb2b-a2e9-4f14-a774-8f939497c4bf" CreationDate="2018-02-18T15:43:14.983" UserId="6929" Text="I'm rendering transparent objects in separate framebuffer then compositing it with opaque one to get final image. &#xD;&#xA;&#xD;&#xA;The transparent pass has additive blending:&#xD;&#xA;&#xD;&#xA;    glBlendFunci(0, GL_ONE,  GL_ONE);&#xD;&#xA;&#xD;&#xA;so transpareny seems work perfect (I used weighted, blended OIT). Now I have problem if I set all surfaces' alpha to **1**. Transparency works if alpha is between 0 and &lt; 1 but not work as expected if alpha = 1. In this case (alpha=1) transparency surface seems opaque on opaque surface[s], but it also appears as semi-transparent on transparent surface[s].&#xD;&#xA;&#xD;&#xA;I think additive blending causes this issue/artifact, how can I fix this? I want to transparent surfaces appear opaque if alpha is set to 1 in fragment shader. I can't disable blending because it will disable whole transparency process. &#xD;&#xA;&#xD;&#xA;What I want to do is control blending in fragment shader or per-fragment blending; is this possible? Overriding old values of some fragments in framebuff e.g. to zero (0,0,0,0) could also help to fix/control blending, because I can put some values in blend equation to get what I want. &#xD;&#xA;&#xD;&#xA;I'm asking this because maybe there is a way to simulate this which I don't know yet. Maybe I can fix this with another rendering passes/targets, I will give a try, any help would be appreciated  " ContentLicense="CC BY-SA 3.0" />
  <row Id="17534" PostHistoryTypeId="1" PostId="6291" RevisionGUID="ea5ffb2b-a2e9-4f14-a774-8f939497c4bf" CreationDate="2018-02-18T15:43:14.983" UserId="6929" Text="Is it possible to override or disable blending per pixel" ContentLicense="CC BY-SA 3.0" />
  <row Id="17535" PostHistoryTypeId="3" PostId="6291" RevisionGUID="ea5ffb2b-a2e9-4f14-a774-8f939497c4bf" CreationDate="2018-02-18T15:43:14.983" UserId="6929" Text="|opengl|transparency|fragment-shader|blending|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17536" PostHistoryTypeId="5" PostId="6291" RevisionGUID="5ef9169b-ad08-477b-bb93-466e5796d8d0" CreationDate="2018-02-18T19:18:06.013" UserId="6929" Comment="additional infos" Text="I'm rendering transparent objects in separate framebuffer then compositing it with opaque one to get final image. &#xD;&#xA;&#xD;&#xA;The transparent pass has additive blending:&#xD;&#xA;&#xD;&#xA;    glBlendFunci(0, GL_ONE,  GL_ONE);&#xD;&#xA;&#xD;&#xA;so transpareny seems work perfect (I used weighted, blended OIT). Now I have problem if I set all surfaces' alpha to **1**. Transparency works if alpha is between 0 and &lt; 1 but not work as expected if alpha = 1. In this case (alpha=1) transparency surface seems opaque on opaque surface[s], but it also appears as semi-transparent on transparent surface[s].&#xD;&#xA;&#xD;&#xA;I think additive blending causes this issue/artifact, how can I fix this? I want to transparent surfaces appear opaque if alpha is set to 1 in fragment shader. I can't disable blending because it will disable whole transparency process. &#xD;&#xA;&#xD;&#xA;What I want to do is control blending in fragment shader or per-fragment blending; is this possible? Overriding old values of some fragments in framebuff e.g. to zero (0,0,0,0) could also help to fix/control blending, because I can put some values in blend equation to get what I want. &#xD;&#xA;&#xD;&#xA;I'm asking this because maybe there is a way to simulate this which I don't know yet. Maybe I can fix this with another rendering passes/targets, I will give a try, any help would be appreciated  &#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;The first image is rendered with alpha = 0.5 and the second one is rendered with alpha = 1.0. As you can see transparency is still active among transparent objects. The pink plane overrides Suzanne mesh and bottom plane but not sphere :( Both sphere and pink plane are rendered in transparency pass.&#xD;&#xA;&#xD;&#xA;[![Alpha = 0.5][1]][1]&#xD;&#xA;[![Alpha = 1.0][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c2uGw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Wa8Kq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17537" PostHistoryTypeId="2" PostId="6292" RevisionGUID="99372381-ceaf-4fb7-b500-205c12b420d4" CreationDate="2018-02-18T23:16:46.410" UserId="2654" Text="You seem to be using additive blending against its purpose. Additive blending is supposed to represent light from multiple sources being combined. It is not physically possible for one source of light to eclipse another.&#xD;&#xA;&#xD;&#xA;Furthermore, even if you hack an alpha of exactly 1 to mean &quot;opaque&quot;, you will get a strange circumstance where an alpha of 0.99 is quite far from &quot;nearly opaque&quot;. So if you're animating &quot;opacity&quot;, then you're going to get a sudden jump from appearing to be transparent to completely opaque.&#xD;&#xA;&#xD;&#xA;Lastly, opacity with blending can *only* be achieved if you render the objects in the correct *order*. So even if you use this hack on the pink square, it will only eclipse the sphere if the sphere is rendered before the square. Using this hack will lose you the order-independency of additive blending.&#xD;&#xA;&#xD;&#xA;That last part makes what you want essentially impossible.&#xD;&#xA;&#xD;&#xA;However, if you wish to persist in this, there is a way to do what you've asked for. You need to use [dual-source blending][1] (which means you can only be rendering to a single render target). This is a technique whereby you output two values from the FS to the same render target:&#xD;&#xA;&#xD;&#xA;    layout(location = 0, index = 0) out vec4 outputColor0;&#xD;&#xA;    layout(location = 0, index = 1) out vec4 outputColor1;&#xD;&#xA;&#xD;&#xA;Both values can be used in the blending equation. This means there are two source colors. The `index` zero source color is the source color used directly in the additive blending equation. The `index` one source color is how you turn off the destination color and achieve opacity:&#xD;&#xA;&#xD;&#xA;    glBlendFunci(0, GL_ONE,  GL_SRC1_ALPHA);&#xD;&#xA;&#xD;&#xA;With this blend function, if you want a fragment shader's output to be opaque, you set `outputColor1.a` to 0. Otherwise you set it to 1. The other components are irrelevant.&#xD;&#xA;&#xD;&#xA;Of course, you must still suffer the limitations of dual-source blending. Namely, that you can only render to a single render target on most hardware.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Dual_Source_Blending" ContentLicense="CC BY-SA 3.0" />
  <row Id="17539" PostHistoryTypeId="2" PostId="6293" RevisionGUID="46cf4d9d-58f6-41e9-96b1-a167f1206317" CreationDate="2018-02-19T09:11:43.233" UserId="6046" Text="It was getting a little big to fit in the comments so posting it as an answer instead. Might not be a solution to your problem but the concept is related.&#xD;&#xA;&#xD;&#xA;People usually forget that whenever you define a transformation matrix by placing respective basis vectors in respective columns, you are specifying that with respect to another basis usually the right-handed or left handed world coordinate space. For example your above matrix&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;r_x &amp; u_x &amp; -l_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; -l_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; -l_z &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Reason why you put `-` sign in the third column is you are working with a right handed coordinate system and the camera is looking in the negative direction (the -Z axis). So all these basis vectors are also with respect to another basis vector.&#xD;&#xA;&#xD;&#xA;Let's make this matrix simple so we can understand what happens when we multiply a matrix with a vector. Let the matrix $M$ be &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;This is your camera initially without any rotation/translation etc. This means your camera space $+Z$ axis maps to world space $-Z$ axis. Now consider a camera space coordinate $[2,3,6,0]^T$. Multiplying this vector by the matrix gives you $[2,3,-6,0]^T$. This is the world space representation of $[2,3,6,0]^T$.&#xD;&#xA;&#xD;&#xA;So as Nathan pointed your matrix transforms from camera space to world space. To do the inverse we just take the inverse of the matrix which is the transpose if the basis is ortho-normal.&#xD;&#xA;&#xD;&#xA;One of the reasons the transformation matrix is built this way is because it's much easier. It's easier to think about the transformed basis vectors of camera or any other space with respect to the world, write the matrix then invert it to go from the world space to that target space." ContentLicense="CC BY-SA 3.0" />
  <row Id="17547" PostHistoryTypeId="2" PostId="6296" RevisionGUID="4f899daf-1348-4bc3-8ed7-dadbe5fb60e0" CreationDate="2018-02-19T16:47:36.650" UserId="8233" Text="I am learning GLSL and want to raytrace a sphere. I am rendering rectangles which sit between the camera and sphere, and do a ray-sphere intersection test in the fragment shader. It almost works:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the rectangles are a little too small. Here is how I calculated them.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Point $C$ is the centre of the rectangle, a distance $R$ from the radius of the sphere. Taking basis vectors $i,j$ I can construct the corners as $C+(\pm i, \pm j)$&#xD;&#xA;&#xD;&#xA;Point $C$ is a fraction $1-\frac{R}{||V||}$ along the vector $V$ from the camera.&#xD;&#xA;&#xD;&#xA;I can direct $i$ and $j$ given the vector $V$ and the &quot;up&quot; vector.&#xD;&#xA;&#xD;&#xA;How long should $i$ and $j$ be? By similar triangles, they should have length $R\times (1-\frac{R}{||V||})$.&#xD;&#xA;&#xD;&#xA;Here is the code (I'm new to GLSL so please ignore bad habits, for now I just want to get the geometry right).&#xD;&#xA;&#xD;&#xA;A vertex array containing four $(\pm 1, \pm 1, 0)$ vectors forms a triangle strip.&#xD;&#xA;&#xD;&#xA;The vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;	in  vec2 position;&#xD;&#xA;	out vec3 vs_fs_position;&#xD;&#xA;&#xD;&#xA;	uniform vec3 i;&#xD;&#xA;	uniform vec3 j;&#xD;&#xA;	uniform vec3 centre;&#xD;&#xA;&#xD;&#xA;	uniform mat4 pvm; // projection * view * model&#xD;&#xA;&#xD;&#xA;	void main ()&#xD;&#xA;	{&#xD;&#xA;		vec3 p = centre + position.x * i + position.y * j;&#xD;&#xA;&#xD;&#xA;		vs_fs_position = p; // world space coordinate sent to fragment&#xD;&#xA;&#xD;&#xA;		gl_Position = pvm * vec4 (p, 1); // to screen space&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The fragment shader&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;	precision mediump float;&#xD;&#xA;	out mediump vec4 out_colour;&#xD;&#xA;	in  mediump vec3 vs_fs_position;&#xD;&#xA;&#xD;&#xA;	uniform mediump vec3 camera_position;&#xD;&#xA;	uniform mediump vec3 camera_to_sphere;&#xD;&#xA;	uniform float radius;&#xD;&#xA;&#xD;&#xA;	void main ()&#xD;&#xA;	{&#xD;&#xA;		vec3 direction = vs_fs_position - camera_position;&#xD;&#xA;&#xD;&#xA;		float A = dot (direction, direction);&#xD;&#xA;		float B = 2.0 * dot (direction, camera_to_sphere);&#xD;&#xA;		float C = dot (camera_to_sphere, camera_to_sphere)&#xD;&#xA;				- radius * radius;&#xD;&#xA;&#xD;&#xA;		float det = B * B - 4.0 * A * C;&#xD;&#xA;&#xD;&#xA;		if (det &lt; 0.0)&#xD;&#xA;			out_colour = vec4 (0.0, 0.0, 0.0, 1.0);&#xD;&#xA;		else&#xD;&#xA;			out_colour = vec4 (0.5, 0.5, 0.5, 1.0);&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Some C++ to draw it&#xD;&#xA;&#xD;&#xA;	shader .camera_position = m_camera_position;&#xD;&#xA;&#xD;&#xA;	const float EPSILON = 0.0;&#xD;&#xA;&#xD;&#xA;	for (auto &amp; s : SPHERES)&#xD;&#xA;	{&#xD;&#xA;		auto R = s .position - m_camera_position;&#xD;&#xA;&#xD;&#xA;		float ratio = 1.0 - (s .radius + EPSILON) / length (R);&#xD;&#xA;&#xD;&#xA;		float width = ratio * s .radius;&#xD;&#xA;&#xD;&#xA;		auto &amp; up = m_camera_up;&#xD;&#xA;&#xD;&#xA;		const float W = width * (1 + EPSILON);&#xD;&#xA;&#xD;&#xA;		glm :: vec3 i = normalize (cross (up, R)) * W;&#xD;&#xA;		glm :: vec3 j = normalize (cross (R,  i)) * W;&#xD;&#xA;&#xD;&#xA;		shader .i = i;&#xD;&#xA;		shader .j = j;&#xD;&#xA;&#xD;&#xA;		shader .centre = s .position;&#xD;&#xA;		shader .radius = s .radius;&#xD;&#xA;&#xD;&#xA;		shader .camera_to_sphere = s .position - m_camera_position;&#xD;&#xA;&#xD;&#xA;		glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;If it runs with `EPSILON=0.5`, I get this output.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Theoretically, I should be able to get a perfect fit with `EPSILON=0`, that way I can be confident it will work at all scales/positions.&#xD;&#xA;&#xD;&#xA;What's wrong with my calculation of the `width` parameter?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/72env.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/L8gJB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/gdFdL.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17548" PostHistoryTypeId="1" PostId="6296" RevisionGUID="4f899daf-1348-4bc3-8ed7-dadbe5fb60e0" CreationDate="2018-02-19T16:47:36.650" UserId="8233" Text="calculating size of rectangle which fully obscures a sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="17549" PostHistoryTypeId="3" PostId="6296" RevisionGUID="4f899daf-1348-4bc3-8ed7-dadbe5fb60e0" CreationDate="2018-02-19T16:47:36.650" UserId="8233" Text="|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17553" PostHistoryTypeId="2" PostId="6298" RevisionGUID="1a7dd962-fd29-49a1-9c74-83fdf3fadaf9" CreationDate="2018-02-19T18:38:55.863" UserId="5717" Text="&gt; How long should $i$ and $j$ be? By similar triangles, they should have length $R\times (1-\frac{R}{||V||})$.&#xD;&#xA;&#xD;&#xA;I believe this is where you went wrong. If you draw the 2D version of this on a sheet of paper, it will be obvious that the edge of your triangle which touches the side of your square goes through the sphere. More so as the camera comes closer.&#xD;&#xA;&#xD;&#xA;That line needs to be tangent to the sphere. So your large similar triangle will have its right angle at the contact point with the sphere, not at the sphere's center as you did. If my trigonometry is not too rusty, this gives&#xD;&#xA;&#xD;&#xA;$\frac{R}{\sqrt{||V||^2-R^2}} \times \left(||V||-R\right)$" ContentLicense="CC BY-SA 3.0" />
  <row Id="17554" PostHistoryTypeId="5" PostId="6298" RevisionGUID="78298b3a-0751-478c-bc99-a0d2e1d2fc79" CreationDate="2018-02-19T20:06:16.347" UserId="5717" Comment="improved MathJax" Text="&gt; How long should $i$ and $j$ be? By similar triangles, they should have length $R\times (1-\frac{R}{\lVert V\rVert})$.&#xD;&#xA;&#xD;&#xA;I believe this is where you went wrong. If you draw the 2D version of this on a sheet of paper, it will be obvious that the edge of your triangle which touches the side of your square goes through the sphere. More so as the camera comes closer.&#xD;&#xA;&#xD;&#xA;That line needs to be tangent to the sphere. So your large similar triangle will have its right angle at the contact point with the sphere, not at the sphere's center as you did. If my trigonometry is not too rusty, this gives&#xD;&#xA;&#xD;&#xA;$\frac{R}{\sqrt{\lVert V\rVert^2-R^2}} \times \left(\lVert V\rVert-R\right)$" ContentLicense="CC BY-SA 3.0" />
  <row Id="17555" PostHistoryTypeId="2" PostId="6299" RevisionGUID="61c219cb-d29d-4add-a133-f0ab592a15a9" CreationDate="2018-02-19T21:10:02.260" UserId="7385" Text="I'm aware that it's technically possible to connect a large number of GPUs to a PC for mining purposes https://www.pcgamer.com/asus-has-a-motherboard-that-supports-up-to-19-gpus/, but how many of these can actually be used simultaneously for graphics output?&#xD;&#xA;&#xD;&#xA;For example, if I wanted to use these all independently for a CAVE https://en.wikipedia.org/wiki/Cave_automatic_virtual_environment like system, where each GPU will render its own independent view to its own monitor. There should be very little interaction between GPUs. Is there some limitation of the OS, or graphics driver that would prevent me from doing this with more than something like four cards?&#xD;&#xA;&#xD;&#xA;To be clear, I'm not interested in anything like SLI here, just using each GPU independently from a single application (think split screen rendering, but each player having their own monitor). I'm currently experimenting with this from Vulkan with two GPUs, but the graphics API isn't important to me if that puts some limit on this. I'm just curious what the upper limit is for this kind of setup.&#xD;&#xA;&#xD;&#xA;Here's an older example of the kind of system I have in mind: https://www.jvrb.org/past-issues/9.2012/3511" ContentLicense="CC BY-SA 3.0" />
  <row Id="17556" PostHistoryTypeId="1" PostId="6299" RevisionGUID="61c219cb-d29d-4add-a133-f0ab592a15a9" CreationDate="2018-02-19T21:10:02.260" UserId="7385" Text="How many GPUs can you simultaneously output from using a single PC?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17557" PostHistoryTypeId="3" PostId="6299" RevisionGUID="61c219cb-d29d-4add-a133-f0ab592a15a9" CreationDate="2018-02-19T21:10:02.260" UserId="7385" Text="|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17558" PostHistoryTypeId="2" PostId="6300" RevisionGUID="0b8eb2c7-52b5-495e-8fd3-83450799e64a" CreationDate="2018-02-19T22:18:17.177" UserId="48" Text="I don't think there are any specific limits. Each GPU can probably drive three or four monitors, and with multiple GPUs in a system, I don't think there's any barrier to hooking up the maximum number of monitors to each GPU. [Here's a video](https://youtu.be/nthOpo5tQDk?t=321), for instance, detailing a 16-monitor machine with 4 GPUs, on Windows.&#xD;&#xA;&#xD;&#xA;Googling around, I did find some people stating that Windows has a 16-monitor or 64-monitor overall limit, but I couldn't verify this from any official documentation. I also saw some claims that Windows has a limit on the overall desktop size that the monitors are virtually placed within, but again could not verify that. In Linux any such limits (if they exist) would naturally be different, and presumably would depend on which window system you're using.&#xD;&#xA;&#xD;&#xA;The other potential limiting factor would be CPU performance and PCIe bus bandwidth for keeping all those GPUs fed with data." ContentLicense="CC BY-SA 3.0" />
  <row Id="17559" PostHistoryTypeId="2" PostId="6301" RevisionGUID="08ab62cf-d4c6-4159-b8d6-43631d669e2c" CreationDate="2018-02-19T22:55:43.323" UserId="8233" Text="I am learning GLSL and trying to raytrace a sphere.&#xD;&#xA;&#xD;&#xA;Here is a fragment shader. It correctly discards fragments which are not on the sphere, but when I try to calculate the point of intersection (and hence, the normal), I get nonsense.&#xD;&#xA;&#xD;&#xA;Here's the fragment shader.&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;	precision mediump float;&#xD;&#xA;	out mediump vec4 out_colour;&#xD;&#xA;&#xD;&#xA;	in  mediump vec3 X;      // intersection of ray with polygon&#xD;&#xA;&#xD;&#xA;	uniform mediump vec3 C;  // camera position&#xD;&#xA;	uniform mediump vec3 CS; // sphere position - camera position&#xD;&#xA;	uniform         float r; // sphere radius&#xD;&#xA;&#xD;&#xA;	void main ()&#xD;&#xA;	{&#xD;&#xA;		vec3 CX = X - C;&#xD;&#xA;&#xD;&#xA;		// |t.CX-CS|=r, CX.CX.t.t - 2.CS.CX.t + CS.CS - r.r = 0&#xD;&#xA;&#xD;&#xA;		float a = dot (CX, CX);&#xD;&#xA;		float b = -2.0 * dot (CX, CS);&#xD;&#xA;		float c = dot (CS, CS) - r * r;&#xD;&#xA;&#xD;&#xA;		float det = b * b - 4.0 * a * c;&#xD;&#xA;&#xD;&#xA;		if (det &lt; 0.0)&#xD;&#xA;			discard;&#xD;&#xA;&#xD;&#xA;		float t = (-b - sqrt (det)) / 2.0 * a;&#xD;&#xA;&#xD;&#xA;		if (t &lt;= 0.0)&#xD;&#xA;			discard;&#xD;&#xA;		&#xD;&#xA;		vec3 N = normalize (t * CX - CS);&#xD;&#xA;&#xD;&#xA;		out_colour = vec4 (N, 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Here's an illustration of the variable names&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I was expecting the normals to be illustrated with a wide-ranging rgb colour across the sphere, but as you can see...&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What went wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m2gPL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XlwR9.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17560" PostHistoryTypeId="1" PostId="6301" RevisionGUID="08ab62cf-d4c6-4159-b8d6-43631d669e2c" CreationDate="2018-02-19T22:55:43.323" UserId="8233" Text="What's wrong with my computation of the intersection of a ray with a sphere" ContentLicense="CC BY-SA 3.0" />
  <row Id="17561" PostHistoryTypeId="3" PostId="6301" RevisionGUID="08ab62cf-d4c6-4159-b8d6-43631d669e2c" CreationDate="2018-02-19T22:55:43.323" UserId="8233" Text="|raytracing|glsl|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17562" PostHistoryTypeId="2" PostId="6302" RevisionGUID="4f4963ff-fd36-451c-a2ac-a83b029718e1" CreationDate="2018-02-20T05:32:56.110" UserId="48" Text="This line doesn't look quite right:&#xD;&#xA;&#xD;&#xA;    float t = (-b - sqrt (det)) / 2.0 * a;&#xD;&#xA;&#xD;&#xA;You're missing parentheses around `(2.0 * a)`. Remember that multiplication and division have equal operator precedence, so the expression as it's currently written means `((-b - sqrt (det)) / 2.0) * a`, putting the `a` in the numerator instead of the denominator." ContentLicense="CC BY-SA 3.0" />
  <row Id="17563" PostHistoryTypeId="5" PostId="6302" RevisionGUID="26481a03-b47d-4970-9319-e43f247a2a2b" CreationDate="2018-02-20T06:10:25.333" UserId="48" Comment="added 108 characters in body" Text="This line doesn't look quite right:&#xD;&#xA;&#xD;&#xA;    float t = (-b - sqrt (det)) / 2.0 * a;&#xD;&#xA;&#xD;&#xA;You're missing parentheses around `(2.0 * a)`. Remember that multiplication and division have equal operator precedence, so the expression as it's currently written means `((-b - sqrt (det)) / 2.0) * a`, putting the `a` in the numerator instead of the denominator.&#xD;&#xA;&#xD;&#xA;(Oh and this is a nitpick, but the thing you named `det` is called a “discriminant”, not a determinant.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17564" PostHistoryTypeId="2" PostId="6303" RevisionGUID="cf498c66-08c6-4a97-b5fc-256c9efa99e6" CreationDate="2018-02-20T15:27:20.117" UserId="8235" Text="I am implementing a water simulation program using OpenGL. However I could not decide which technique to use for reflection and refraction. The water is wavy and there are dynamic objects around the water.&#xD;&#xA;&#xD;&#xA;First, I considered dynamic environment mapping. However, it seems that it is not quite suitable for small environment, because the close objects are not reflected correctly.&#xD;&#xA;&#xD;&#xA;Second, I considered SSR technique, but it does not reflect non visible objects and because realism is more important than performance for this project I gave up on SSR.&#xD;&#xA;&#xD;&#xA;Is there any other good algorithms to do reflection and refraction?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17565" PostHistoryTypeId="1" PostId="6303" RevisionGUID="cf498c66-08c6-4a97-b5fc-256c9efa99e6" CreationDate="2018-02-20T15:27:20.117" UserId="8235" Text="What is a good way to do reflection and refraction in small environment for bumpy planar surface?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17566" PostHistoryTypeId="3" PostId="6303" RevisionGUID="cf498c66-08c6-4a97-b5fc-256c9efa99e6" CreationDate="2018-02-20T15:27:20.117" UserId="8235" Text="|opengl|reflection|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17567" PostHistoryTypeId="2" PostId="6304" RevisionGUID="01130d65-3983-46c4-8b59-7cadf9b01247" CreationDate="2018-02-20T16:17:00.433" UserId="8009" Text="We use projective geometry and homogeneous coordinates so that we can make use of **linear algebra** to do our transformations.&#xD;&#xA;&#xD;&#xA;And by the way, this **is** math.  I think you should read wikipedia's pages about [Projective Geometry](https://en.wikipedia.org/wiki/Projective_geometry), and the clever idea to introduce a [Point at Infinity](https://en.wikipedia.org/wiki/Point_at_infinity), and use [Homogeneous Coordiantes](https://en.wikipedia.org/wiki/Homogeneous_coordinates) to allow you to deal with projective geometry transformations using **linear algebra** as opposed to dealing with the ugly math required to do transformations after the divide (because projections are non-linear).&#xD;&#xA;&#xD;&#xA;At some point, you must divide though, so this technique is a way of deferring that divide to the very end.  All the other transformations can be dealt with in a linear fashion with nice simple matrices and such - even though we are dealing with projection.  In terms of OpenGL (and others) we only divide when we go from _Clip Space_ to _Normalized Device Space_ - long after all the 3D transformations have been applied." ContentLicense="CC BY-SA 3.0" />
  <row Id="17571" PostHistoryTypeId="2" PostId="6305" RevisionGUID="3d509de1-9a95-4b93-b9b8-28c4ab4fa794" CreationDate="2018-02-21T04:22:55.307" UserId="8191" Text="I don't even know where to start. So far, the only progress I have gotten is checking the z value of each vertex of each triangle. If all three vertices' z values &gt; absolute value of far or &lt; absolute value of near, then I dont draw that triangle.  &#xD;&#xA;Im using the right hand rule, if that info is necessary. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17572" PostHistoryTypeId="1" PostId="6305" RevisionGUID="3d509de1-9a95-4b93-b9b8-28c4ab4fa794" CreationDate="2018-02-21T04:22:55.307" UserId="8191" Text="How to do clipping in camera space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17573" PostHistoryTypeId="3" PostId="6305" RevisionGUID="3d509de1-9a95-4b93-b9b8-28c4ab4fa794" CreationDate="2018-02-21T04:22:55.307" UserId="8191" Text="|3d|clipping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17574" PostHistoryTypeId="5" PostId="6305" RevisionGUID="209b4053-96a4-4789-baf4-beb1b14fd1de" CreationDate="2018-02-21T04:34:51.373" UserId="8191" Comment="added 46 characters in body" Text="I don't even know where to start. So far, the only progress I have gotten is checking the z value of each vertex of each triangle. If all three vertices' z values &gt; absolute value of far or &lt; absolute value of near, then I dont draw that triangle. It seems wrong somehow, though I dont get why. &#xD;&#xA;Im using the right hand rule, if that info is necessary. " ContentLicense="CC BY-SA 3.0" />
  <row Id="17578" PostHistoryTypeId="2" PostId="6307" RevisionGUID="9330fe36-f270-4b73-9f10-e050130ebacb" CreationDate="2018-02-21T12:55:28.560" UserId="8242" Text="I am rendering the sun in an image, and the sun comes out white and is basically very unrealistic. I have tried searching for  tone mapping algorithms but I'm very lost. Can someone guide me to do this? or perhaps help me with the pseudo" ContentLicense="CC BY-SA 3.0" />
  <row Id="17579" PostHistoryTypeId="1" PostId="6307" RevisionGUID="9330fe36-f270-4b73-9f10-e050130ebacb" CreationDate="2018-02-21T12:55:28.560" UserId="8242" Text="Tone mapping bright images" ContentLicense="CC BY-SA 3.0" />
  <row Id="17580" PostHistoryTypeId="3" PostId="6307" RevisionGUID="9330fe36-f270-4b73-9f10-e050130ebacb" CreationDate="2018-02-21T12:55:28.560" UserId="8242" Text="|raytracing|rendering|mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17581" PostHistoryTypeId="2" PostId="6308" RevisionGUID="02a8d4f9-a1a7-4efd-8b04-f0796be12675" CreationDate="2018-02-21T14:29:11.357" UserId="8233" Text="I am raytracing in GLSL. My `gl_FragDepth` calculation wasn't right, so I did some hunting and found this solution (`P` is the world-space coordinate of the pixel and `pv` is proj*view):&#xD;&#xA;&#xD;&#xA;		vec4 Pclip = pv * vec4 (P, 1);&#xD;&#xA;	&#xD;&#xA;		float ndc_depth = Pclip.z / Pclip.w;&#xD;&#xA;		&#xD;&#xA;		gl_FragDepth = (&#xD;&#xA;			(gl_DepthRange.diff * ndc_depth) +&#xD;&#xA;			gl_DepthRange.near + gl_DepthRange.far) / 2.0;&#xD;&#xA;&#xD;&#xA;It works. But why?&#xD;&#xA;&#xD;&#xA;Okay, so I need to divide by `w` and scale it to the expected z-range. That makes sense qualitatively, but the calculation surprised me.&#xD;&#xA;&#xD;&#xA;If you told me to &quot;divide by `w` and scale to `gl_DepthRange`&quot; I would have written&#xD;&#xA;&#xD;&#xA;    float ndc_depth = Pclip.z / Pclip.w;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * ndc_depth + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;At this point I'd like to point out that this depth calculation looks correct with the raytraced geometry which is intersecting with my normal triangle models, so I guess OpenGL is performing the same depth-scaling implicitly for those triangles as well.&#xD;&#xA;&#xD;&#xA;Three questions:&#xD;&#xA;&#xD;&#xA;1. Why add `gl_DepthRange.far` to the calculation?&#xD;&#xA;2. Why divide by 2?&#xD;&#xA;3. I set the `pv` matrix in C++ with `glm::perspective(...)*glm::lookAt(...)` so how the hell does `gl_DepthRange` know what the near and far planes are?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17582" PostHistoryTypeId="1" PostId="6308" RevisionGUID="02a8d4f9-a1a7-4efd-8b04-f0796be12675" CreationDate="2018-02-21T14:29:11.357" UserId="8233" Text="Why does this gl_FragDepth calculation work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17583" PostHistoryTypeId="3" PostId="6308" RevisionGUID="02a8d4f9-a1a7-4efd-8b04-f0796be12675" CreationDate="2018-02-21T14:29:11.357" UserId="8233" Text="|opengl|transformations|perspective|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17584" PostHistoryTypeId="2" PostId="6309" RevisionGUID="400a4c14-0e27-47e7-8a2c-662a8973f908" CreationDate="2018-02-21T15:08:41.313" UserId="6" Text="What you are missing is, that in OpenGL's NDC space (i.e. clip space after division by `w`) all 3 coordinates are in the range $[-1,1]$. So **`ndc_depth` is in the range $[-1,1]$**, while your computation assumes a range of $[0,1]$.&#xD;&#xA;&#xD;&#xA;So let's take your computation but add an initial step to map $[-1,1]$ to $[0,1]$:&#xD;&#xA;&#xD;&#xA;    float ndc_depth = Pclip.z / Pclip.w;&#xD;&#xA;    float win_depth = (ndc_depth + 1.0) / 2.0;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * win_depth + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;If we do some transformations (and realizing that `gl_DepthRange.diff` is just convenience for `gl_DepthRange.far - gl_DepthRange.near`), we get&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * (ndc_depth + 1.0) / 2.0 + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff) / 2.0 &#xD;&#xA;                   + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff + &#xD;&#xA;                    2.0 * glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far - gl_DepthRange.near + 2.0 * glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far + glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;So, to answer your specfic questions:&#xD;&#xA;&#xD;&#xA;1. That's just a result from simplifying the calculation based on the fact that [`gl_DepthRange.diff` is nothing else than `gl_DepthRange.far - gl_DepthRange.near`](https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)#Shader_uniforms).&#xD;&#xA;&#xD;&#xA;2. Because the depth range in NDC space is $[-1,1]$, which has a width of $2$.&#xD;&#xA;&#xD;&#xA;3. It doesn't. These values have nothing to do with the near and far values you used to construct your projection matrix, in fact you could use any arbitrary projection matrix (or none at all). They are the depth range values set with [`glDepthRange`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml), which have a totally different meaning (okay, let's say slightly different but related)." ContentLicense="CC BY-SA 3.0" />
  <row Id="17585" PostHistoryTypeId="5" PostId="6309" RevisionGUID="4f2fd85d-2eb0-4417-8207-4433c5139d02" CreationDate="2018-02-21T15:14:44.133" UserId="6" Comment="added 562 characters in body" Text="What you are missing is, that in OpenGL's NDC space (i.e. clip space after division by `w`) all 3 coordinates are in the range $[-1,1]$. So **`ndc_depth` is in the range $[-1,1]$**, while your computation assumes a range of $[0,1]$.&#xD;&#xA;&#xD;&#xA;So let's take your computation but add an initial step to map $[-1,1]$ to $[0,1]$:&#xD;&#xA;&#xD;&#xA;    float ndc_depth = Pclip.z / Pclip.w;&#xD;&#xA;    float win_depth = (ndc_depth + 1.0) / 2.0;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * win_depth + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;If we do some transformations (and realizing that `gl_DepthRange.diff` is just convenience for `gl_DepthRange.far - gl_DepthRange.near`), we get&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * (ndc_depth + 1.0) / 2.0 + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff) / 2.0 &#xD;&#xA;                   + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff + &#xD;&#xA;                    2.0 * glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far - gl_DepthRange.near + 2.0 * glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far + glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;So, to answer your specfic questions:&#xD;&#xA;&#xD;&#xA;1. That's just a result from simplifying the calculation based on the fact that [`gl_DepthRange.diff` is nothing else than `gl_DepthRange.far - gl_DepthRange.near`](https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)#Shader_uniforms).&#xD;&#xA;&#xD;&#xA;2. Because the depth range in NDC space is $[-1,1]$, which has a width of $2$.&#xD;&#xA;&#xD;&#xA;3. It doesn't. These values have nothing to do with the near and far values you used to construct your projection matrix, in fact you could use any arbitrary projection matrix (or none at all). They are the depth range values set with [`glDepthRange`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml), which have a totally different meaning (okay, let's say slightly different but related).&#xD;&#xA;&#xD;&#xA; Basically, and special situations notwithstanding, the projection matrix defines where you near and far clipping planes are in eye-space, i.e. which eye-space range is mapped to the $[-1,1]$ NDC depth range. Then the depth range defines what these NDC near/far values of -1 and 1 are mapped to in the actual depth buffer. So the names &quot;near&quot;/&quot;far&quot; *do* relate to the near and far clipping planes. But both transformations are basically independent of each other, using the general NDC (i.e. the *normalized* device space) as a mediator between both stages." ContentLicense="CC BY-SA 3.0" />
  <row Id="17586" PostHistoryTypeId="2" PostId="6310" RevisionGUID="0b98bce8-6669-48b0-ab6b-eed5ee75d20a" CreationDate="2018-02-21T16:06:42.977" UserId="7215" Text="This is sort of an API design question. Why do vulkan instance/device extensions need to be specifically enabled, in order for their calls to be available?&#xD;&#xA;&#xD;&#xA;Wouldn't it make more sense to have extensions just always “be there” if they're supported in this environment, and then the API user can query which ones are actually available after device creation?&#xD;&#xA;&#xD;&#xA;Another way of phrasing this question might be: Is there any reason *not* to enable every supported extension when creating a vulkan instance/device?&#xD;&#xA;&#xD;&#xA;The reason I'm asking is because I'm specifically worried about vulkan interop between multiple programs. The fact that each program's VkDevice is distinct means you can't just straight up share VkImages. But agreeing on a common VkDevice is tricky because they may have different extensions/features enabled, so the interop API must account for the fact that both users may provide a set of extensions that they want enabled on the resulting VkDevice. This seems needlessly complex - wouldn't it be easier to just create one VkInstance and one VkDevice with everything enabled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17587" PostHistoryTypeId="1" PostId="6310" RevisionGUID="0b98bce8-6669-48b0-ab6b-eed5ee75d20a" CreationDate="2018-02-21T16:06:42.977" UserId="7215" Text="Why do vulkan extensions need to be enabled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17588" PostHistoryTypeId="3" PostId="6310" RevisionGUID="0b98bce8-6669-48b0-ab6b-eed5ee75d20a" CreationDate="2018-02-21T16:06:42.977" UserId="7215" Text="|vulkan|api|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17589" PostHistoryTypeId="2" PostId="6311" RevisionGUID="fa2729c6-8f28-478b-a9d6-d29d3198c3e6" CreationDate="2018-02-21T16:28:07.693" UserId="7215" Text="There are multiple different ways to do tone-mapping, including both local and global methods. I won't discuss local methods (i.e. methods based on using surrounding information as part of the tone mapping process) here. Global methods can be broken down into two components:&#xD;&#xA;&#xD;&#xA;1. A formula for mapping from $[1,\infty)$ to $[0,1]$.&#xD;&#xA;2. A method of applying this to the color.&#xD;&#xA;&#xD;&#xA;The simplest formula out there is just $out = in / (in + 1)$, but the results are also fairly boring. A fancier curve is the filmic tone mapping function developed by John Hable, which is [popular in the video gaming industry](http://frictionalgames.blogspot.de/2012/09/tech-feature-hdr-lightning.html):&#xD;&#xA;&#xD;&#xA;    float hable(float x)&#xD;&#xA;    {&#xD;&#xA;        float A = 0.15;&#xD;&#xA;        float B = 0.50;&#xD;&#xA;        float C = 0.10;&#xD;&#xA;        float D = 0.20;&#xD;&#xA;        float E = 0.02;&#xD;&#xA;        float F = 0.30;&#xD;&#xA;    &#xD;&#xA;        return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can also get even fancier if you can constrain the input domain to a known, fixed peak value.&#xD;&#xA;&#xD;&#xA;As for how to apply this function to an actual color value, there are again multiple techniques. A very simple way is to do it per-channel, i.e. `color.r = map(color.r); color.g = map(color.g); color.b = map(color.b);`. But this has the downside of warping the appearance of bright colors towards white (e.g. orange becomes yellowish under tone-mapping). Some in the movie industry tend to like this look, for whatever reason.&#xD;&#xA;&#xD;&#xA;To do color-preserving tone mapping, you can perform the calculation on a single value only and then apply the same scale to all three channels. A good choice for the value to use is to choose the “brightest” of the three components:&#xD;&#xA;&#xD;&#xA;    float sig = max(color.r, max(color.g, color.b));&#xD;&#xA;    color *= map(sig) / sig;&#xD;&#xA;&#xD;&#xA;However, this approach also has downsides, namely that it takes very bright objects to unnaturally saturated versions of&#xD;&#xA;themselves. For example, a bright sun might suddenly appear various shades of yellow and orange - which also looks unnatural on photographic content.&#xD;&#xA;&#xD;&#xA;So ultimately, what I do is first desaturate the color based on how bright it is, and then apply tone mapping after the fact, leading to an algorithm that looks something like this:&#xD;&#xA;&#xD;&#xA;    // Calculate the desaturation coefficient based on the brightness&#xD;&#xA;    float sig = max(color.r, max(color.g, color.b));&#xD;&#xA;    float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));&#xD;&#xA;    float coeff = max(sig - 0.18, 1e-6) / max(sig, 1e-6);&#xD;&#xA;    coeff = pow(coeff, 20.0);&#xD;&#xA;&#xD;&#xA;    // Update the original color and signal&#xD;&#xA;    color.rgb = mix(color.rgb, vec3(luma), coeff);&#xD;&#xA;    sig = mix(sig, luma, coeff);&#xD;&#xA;&#xD;&#xA;    // Perform tone-mapping&#xD;&#xA;    color *= map(sig)&#xD;&#xA;&#xD;&#xA;But YMMV.&#xD;&#xA;&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA;- https://github.com/haasn/libplacebo/blob/master/src/shaders/colorspace.c#L664&#xD;&#xA;- You can also poke at ITU-R Report BT.2390-2 for some more ideas and guidelines." ContentLicense="CC BY-SA 3.0" />
  <row Id="17590" PostHistoryTypeId="2" PostId="6312" RevisionGUID="e3489848-ccd2-4eff-9c33-636bd8b8d877" CreationDate="2018-02-21T16:33:23.330" UserId="2654" Text="Extensions can change the visible behavior of the implementation, not to mention the implementation of it.&#xD;&#xA;&#xD;&#xA;Consider KHR_external_semaphore and its various sub-extensions. If you don't specify them, then the `VkDevice`'s implementation knows that you're not going to need to be able to turn a VkSemaphore into an externally-accessible mutex and back. So the implementation may be able to use a more efficient `VkSemaphore` implementation.&#xD;&#xA;&#xD;&#xA;If the extension is always on, the device *must* assume that you're going to use it. And thus, any possible efficiency is lost.&#xD;&#xA;&#xD;&#xA;&gt; wouldn't it be easier to just create one VkInstance and one VkDevice with everything enabled?&#xD;&#xA;&#xD;&#xA;How? If you have two `VkDevice`s, unless they are both attached to the same `VkPhysicalDevice`, there's no guarantee that &quot;everything&quot; is the same thing for both devices.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Cross-process Vulkan interop is *not* something external code is expected to define. There are extensions that provide various aspects of such interop." ContentLicense="CC BY-SA 3.0" />
  <row Id="17591" PostHistoryTypeId="5" PostId="6311" RevisionGUID="5587f33d-8a37-417d-b6de-56fe5f8c6a9a" CreationDate="2018-02-21T16:33:53.197" UserId="7215" Comment="Minor corrections" Text="There are multiple different ways to do tone-mapping, including both local and global methods. I won't discuss local methods (i.e. methods based on using surrounding information as part of the tone mapping process) here. Global methods can be broken down into two components:&#xD;&#xA;&#xD;&#xA;1. A formula for mapping from $[0,\infty)$ to $[0,1]$.&#xD;&#xA;2. A method of applying this to the color.&#xD;&#xA;&#xD;&#xA;The simplest formula out there is just $out = in / (in + 1)$, but the results are also fairly boring. A fancier curve is the filmic tone mapping function developed by John Hable, which is [popular in the video gaming industry](http://frictionalgames.blogspot.de/2012/09/tech-feature-hdr-lightning.html):&#xD;&#xA;&#xD;&#xA;    float hable(float x)&#xD;&#xA;    {&#xD;&#xA;        float A = 0.15;&#xD;&#xA;        float B = 0.50;&#xD;&#xA;        float C = 0.10;&#xD;&#xA;        float D = 0.20;&#xD;&#xA;        float E = 0.02;&#xD;&#xA;        float F = 0.30;&#xD;&#xA;    &#xD;&#xA;        return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can also get even fancier if you can constrain the input domain to a known, fixed peak value.&#xD;&#xA;&#xD;&#xA;As for how to apply this function to an actual color value, there are again multiple techniques. A very simple way is to do it per-channel, i.e. `color.r = map(color.r); color.g = map(color.g); color.b = map(color.b);`. But this has the downside of warping the appearance of bright colors towards white (e.g. orange becomes yellowish under tone-mapping). Some in the movie industry tend to like this look, for whatever reason.&#xD;&#xA;&#xD;&#xA;To do color-preserving tone mapping, you can perform the calculation on a single value only and then apply the same scale to all three channels. A good choice for the value to use is to choose the “brightest” of the three components:&#xD;&#xA;&#xD;&#xA;    float sig = max(color.r, max(color.g, color.b));&#xD;&#xA;    color.rgb *= vec3(map(sig) / sig);&#xD;&#xA;&#xD;&#xA;However, this approach also has downsides, namely that it takes very bright objects to unnaturally saturated versions of&#xD;&#xA;themselves. For example, a bright sun might suddenly appear various shades of yellow and orange - which also looks unnatural on photographic content.&#xD;&#xA;&#xD;&#xA;So ultimately, what I do is first desaturate the color based on how bright it is, and then apply tone mapping after the fact, leading to an algorithm that looks something like this:&#xD;&#xA;&#xD;&#xA;    // Calculate the desaturation coefficient based on the brightness&#xD;&#xA;    float sig = max(color.r, max(color.g, color.b));&#xD;&#xA;    float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));&#xD;&#xA;    float coeff = max(sig - 0.18, 1e-6) / max(sig, 1e-6);&#xD;&#xA;    coeff = pow(coeff, 20.0);&#xD;&#xA;&#xD;&#xA;    // Update the original color and signal&#xD;&#xA;    color.rgb = mix(color.rgb, vec3(luma), coeff);&#xD;&#xA;    sig = mix(sig, luma, coeff);&#xD;&#xA;&#xD;&#xA;    // Perform tone-mapping&#xD;&#xA;    color.rgb *= vec3(map(sig) / sig);&#xD;&#xA;&#xD;&#xA;But YMMV.&#xD;&#xA;&#xD;&#xA;References:&#xD;&#xA;&#xD;&#xA;- https://github.com/haasn/libplacebo/blob/master/src/shaders/colorspace.c#L664&#xD;&#xA;- You can also poke at ITU-R Report BT.2390-2 for some more ideas and guidelines.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17594" PostHistoryTypeId="5" PostId="6307" RevisionGUID="6049ec81-8595-4b29-b9e4-585ab1184888" CreationDate="2018-02-21T17:44:16.520" UserId="8242" Comment="added 62 characters in body" Text="[![Sun][1]][1]I am rendering the sun in an image, and the sun comes out white and is basically very unrealistic. I have tried searching for  tone mapping algorithms but I'm very lost. Can someone guide me to do this? or perhaps help me with the pseudo&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IqqlS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17595" PostHistoryTypeId="5" PostId="6307" RevisionGUID="43af81ff-50ba-4781-92a1-f0ff478b49ec" CreationDate="2018-02-21T17:50:28.013" UserId="8242" Comment="edited body" Text="I am rendering the sun in an image, and the sun comes out white and is basically very unrealistic. I have tried searching for  tone mapping algorithms but I'm very lost. Can someone guide me to do this? or perhaps help me with the pseudo&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Sun][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IqqlS.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17597" PostHistoryTypeId="2" PostId="6313" RevisionGUID="40db92ff-a4f5-40ea-83b5-99f12fe96dfb" CreationDate="2018-02-22T01:45:59.690" UserId="8245" Text="I've been hunting around the internet for a while now, and I can't find anything about the specific shadow technique that I'm looking for.&#xD;&#xA;&#xD;&#xA;I can only recall one game in particular that used it, and I know that it happens on the PC port of the game too. The game in question is &quot;Sonic Adventure 2: Battle&quot; for GameCube. I remember it happening on &quot;Super Mario Sunshine&quot;, but I could be mistaken.&#xD;&#xA;&#xD;&#xA;- The shadows are only cast from the main player character.&#xD;&#xA;- It is 100% sharp, no matter the resolution the game is rendered at.&#xD;&#xA;- They are cast perfectly parallel down onto the surface the player stands on.&#xD;&#xA;- Interestingly, if the shadow intersects with a vertical wall, the shadow is drawn all the way up the wall, even higher than the original intersection.&#xD;&#xA;- You can also see the shadow on ceilings directly above the player character, and even on floors above ceilings. It's as if there's a big character-silhouette shaped tube being cast onto surfaces.&#xD;&#xA;&#xD;&#xA;**How does this technique work, and how can I learn more about it?**&#xD;&#xA;&#xD;&#xA;I'm going to hunt for a picture of this particular technique, but I don't have one right now." ContentLicense="CC BY-SA 3.0" />
  <row Id="17598" PostHistoryTypeId="1" PostId="6313" RevisionGUID="40db92ff-a4f5-40ea-83b5-99f12fe96dfb" CreationDate="2018-02-22T01:45:59.690" UserId="8245" Text="How did the hard, accurate shadows, work in early 3d (2000 - 2004) games?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17599" PostHistoryTypeId="3" PostId="6313" RevisionGUID="40db92ff-a4f5-40ea-83b5-99f12fe96dfb" CreationDate="2018-02-22T01:45:59.690" UserId="8245" Text="|rendering|3d|gpu|shadow|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17601" PostHistoryTypeId="2" PostId="6314" RevisionGUID="eebffd34-4a31-42e0-b0f7-30432065fce1" CreationDate="2018-02-22T04:26:18.883" UserId="8246" Text="So I'm working on an assignment where we have to design a simple ray tracer. The program has two objects that it can use, sphere and cube. It can render the cube and spheres, it also does shading on the objects and will cast a shadow of light for the spheres; however, the boxes are not casting shadows. Instead I think it is casting it upon the actual cube instead of &quot;the ground&quot;. Any ideas on how to fix that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    package ray.surface;&#xD;&#xA;&#xD;&#xA;    import ray.Intersections;&#xD;&#xA;    import ray.Ray&#xD;&#xA;    import ray.math.Point3;&#xD;&#xA;    import ray.math.Vector3;&#xD;&#xA;    public class Box extends Surface {    &#xD;&#xA;    /* The corner of the box with the smallest x, y, and z components. */&#xD;&#xA;    protected final Point3 minPt = new Point3();&#xD;&#xA;    public void setMinPt(Point3 minPt) { this.minPt.set(minPt); }&#xD;&#xA;    &#xD;&#xA;    /* The corner of the box with the largest x, y, and z components. */&#xD;&#xA;    protected final Point3 maxPt = new Point3();&#xD;&#xA;    public void setMaxPt(Point3 maxPt) { this.maxPt.set(maxPt); }&#xD;&#xA;    &#xD;&#xA;    /**&#xD;&#xA;     * @param outRecord the output Intersections&#xD;&#xA;     * @param ray the ray to intersect&#xD;&#xA;     * @return true if the surface intersects the ray&#xD;&#xA;     */&#xD;&#xA;    public boolean intersect(Intersections outRecord, Ray rayIn) {&#xD;&#xA;        &#xD;&#xA;        double tNear = 0;&#xD;&#xA;        double tFar = Double.POSITIVE_INFINITY;&#xD;&#xA;&#xD;&#xA;        double x,y,z;&#xD;&#xA;        // Compute the t values &#xD;&#xA;        double txmin;&#xD;&#xA;        double txmax;&#xD;&#xA;        double tymin;&#xD;&#xA;        double tymax;&#xD;&#xA;        double tzmin;&#xD;&#xA;        double tzmax;&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;            txmin = (minPt.x - rayIn.origin.x) / rayIn.direction.x;&#xD;&#xA;            txmax = (maxPt.x - rayIn.origin.x) / rayIn.direction.x;&#xD;&#xA;            x=1;&#xD;&#xA;            if (txmin &gt; txmax) {&#xD;&#xA;                double tmp1 = txmin;&#xD;&#xA;                txmin = txmax;&#xD;&#xA;                txmax = tmp1;&#xD;&#xA;                x=-1;&#xD;&#xA;            }&#xD;&#xA;            if (txmin &gt; tNear)&#xD;&#xA;                tNear = txmin;&#xD;&#xA;            if (txmax &lt; tFar)&#xD;&#xA;                tFar = txmax;&#xD;&#xA;            if (tNear &gt; tFar)&#xD;&#xA;                return false;&#xD;&#xA;            if (tFar &lt; 0)&#xD;&#xA;                return false;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        //ray y direction is parallel to plane&#xD;&#xA;        &#xD;&#xA;            tymin = (minPt.y - rayIn.origin.y) / rayIn.direction.y;&#xD;&#xA;            tymax = (maxPt.y - rayIn.origin.y) / rayIn.direction.y;&#xD;&#xA;            y=1;&#xD;&#xA;&#xD;&#xA;            if (tymin &gt; tymax) {&#xD;&#xA;                double tmp2 = tymin;&#xD;&#xA;                tymin = tymax;&#xD;&#xA;                tymax = tmp2;&#xD;&#xA;                y=-1;&#xD;&#xA;            }&#xD;&#xA;            if (tymin &gt; tNear)&#xD;&#xA;                tNear = tymin;&#xD;&#xA;            if (tymax &lt; tFar)&#xD;&#xA;                tFar = tymax;&#xD;&#xA;            if (tNear &gt; tFar)&#xD;&#xA;                return false;&#xD;&#xA;            if (tFar &lt; 0)&#xD;&#xA;                return false;&#xD;&#xA;            &#xD;&#xA;        &#xD;&#xA;        //ray z direction is parallel to plane&#xD;&#xA;        &#xD;&#xA;            tzmin = (minPt.z - rayIn.origin.z) / rayIn.direction.z;&#xD;&#xA;            tzmax = (maxPt.z - rayIn.origin.z) / rayIn.direction.z;&#xD;&#xA;            z=1;&#xD;&#xA;          &#xD;&#xA;            if (tzmin &gt; tzmax) {&#xD;&#xA;                double tmp3 = tzmin;&#xD;&#xA;                tzmin = tzmax;&#xD;&#xA;                tzmax = tmp3;&#xD;&#xA;                z=-1;&#xD;&#xA;            }&#xD;&#xA;            if (tzmin &gt; tNear)&#xD;&#xA;                tNear = tzmin;&#xD;&#xA;            if (tzmax &lt; tFar)&#xD;&#xA;                tFar = tzmax;&#xD;&#xA;            if (tNear &gt; tFar)&#xD;&#xA;                return false;&#xD;&#xA;            if (tFar &lt; 0)&#xD;&#xA;                return false;&#xD;&#xA;&#xD;&#xA;        double t = Math.min(tNear, tFar);&#xD;&#xA;        // Set the location point.&#xD;&#xA;        &#xD;&#xA;        rayIn.evaluate(outRecord.location, tNear);&#xD;&#xA;        //rayIn.start=0;&#xD;&#xA;        rayIn.end=t;&#xD;&#xA;        &#xD;&#xA;        outRecord.surface=this;&#xD;&#xA;        outRecord.t=t;&#xD;&#xA;        // Set the Normal Vector.&#xD;&#xA;        if(tNear==txmin) {&#xD;&#xA;            outRecord.normal.set(new Vector3(x,0,0));&#xD;&#xA;        } else if (tNear==tymin) {&#xD;&#xA;            outRecord.normal.set(new Vector3(0,y,0));&#xD;&#xA;        } else if (tNear==tzmin) {&#xD;&#xA;            outRecord.normal.set(new Vector3(0,0,z));&#xD;&#xA;        }&#xD;&#xA;        outRecord.normal.normalize();&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    /**&#xD;&#xA;     * @see Object#toString()&#xD;&#xA;     */&#xD;&#xA;    public String toString() {&#xD;&#xA;        return &quot;Box &quot; + minPt + &quot; &quot; + maxPt + &quot; &quot; + shader + &quot; end&quot;;&#xD;&#xA;    }&#xD;&#xA;}" ContentLicense="CC BY-SA 3.0" />
  <row Id="17602" PostHistoryTypeId="1" PostId="6314" RevisionGUID="eebffd34-4a31-42e0-b0f7-30432065fce1" CreationDate="2018-02-22T04:26:18.883" UserId="8246" Text="Ray Tracer Shadowing" ContentLicense="CC BY-SA 3.0" />
  <row Id="17603" PostHistoryTypeId="3" PostId="6314" RevisionGUID="eebffd34-4a31-42e0-b0f7-30432065fce1" CreationDate="2018-02-22T04:26:18.883" UserId="8246" Text="|raytracing|shader|image-processing|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17604" PostHistoryTypeId="5" PostId="6314" RevisionGUID="254fe8f8-ecca-4504-a46d-088b40c398b5" CreationDate="2018-02-22T04:33:39.547" UserId="8246" Comment="added 178 characters in body" Text="So I'm working on an assignment where we have to design a simple ray tracer. The program has two objects that it can use, sphere and cube. It can render the cube and spheres, it also does shading on the objects and will cast a shadow of light for the spheres; however, the boxes are not casting shadows. Instead I think it is casting it upon the actual cube instead of &quot;the ground&quot;. Any ideas on how to fix that?&#xD;&#xA;&#xD;&#xA;Below is my code for the cube and the image it should be vs the image it produces. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    package ray.surface;&#xD;&#xA;&#xD;&#xA;    import ray.Intersections;&#xD;&#xA;    import ray.Ray&#xD;&#xA;    import ray.math.Point3;&#xD;&#xA;    import ray.math.Vector3;&#xD;&#xA;    public class Box extends Surface {    &#xD;&#xA;    /* The corner of the box with the smallest x, y, and z components. */&#xD;&#xA;    protected final Point3 minPt = new Point3();&#xD;&#xA;    public void setMinPt(Point3 minPt) { this.minPt.set(minPt); }&#xD;&#xA;    &#xD;&#xA;    /* The corner of the box with the largest x, y, and z components. */&#xD;&#xA;    protected final Point3 maxPt = new Point3();&#xD;&#xA;    public void setMaxPt(Point3 maxPt) { this.maxPt.set(maxPt); }&#xD;&#xA;    &#xD;&#xA;    /**&#xD;&#xA;     * @param outRecord the output Intersections&#xD;&#xA;     * @param ray the ray to intersect&#xD;&#xA;     * @return true if the surface intersects the ray&#xD;&#xA;     */&#xD;&#xA;    public boolean intersect(Intersections outRecord, Ray rayIn) {&#xD;&#xA;        &#xD;&#xA;        double tNear = 0;&#xD;&#xA;        double tFar = Double.POSITIVE_INFINITY;&#xD;&#xA;&#xD;&#xA;        double x,y,z;&#xD;&#xA;        // Compute the t values &#xD;&#xA;        double txmin;&#xD;&#xA;        double txmax;&#xD;&#xA;        double tymin;&#xD;&#xA;        double tymax;&#xD;&#xA;        double tzmin;&#xD;&#xA;        double tzmax;&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;            txmin = (minPt.x - rayIn.origin.x) / rayIn.direction.x;&#xD;&#xA;            txmax = (maxPt.x - rayIn.origin.x) / rayIn.direction.x;&#xD;&#xA;            x=1;&#xD;&#xA;            if (txmin &gt; txmax) {&#xD;&#xA;                double tmp1 = txmin;&#xD;&#xA;                txmin = txmax;&#xD;&#xA;                txmax = tmp1;&#xD;&#xA;                x=-1;&#xD;&#xA;            }&#xD;&#xA;            if (txmin &gt; tNear)&#xD;&#xA;                tNear = txmin;&#xD;&#xA;            if (txmax &lt; tFar)&#xD;&#xA;                tFar = txmax;&#xD;&#xA;            if (tNear &gt; tFar)&#xD;&#xA;                return false;&#xD;&#xA;            if (tFar &lt; 0)&#xD;&#xA;                return false;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        //ray y direction is parallel to plane&#xD;&#xA;        &#xD;&#xA;            tymin = (minPt.y - rayIn.origin.y) / rayIn.direction.y;&#xD;&#xA;            tymax = (maxPt.y - rayIn.origin.y) / rayIn.direction.y;&#xD;&#xA;            y=1;&#xD;&#xA;&#xD;&#xA;            if (tymin &gt; tymax) {&#xD;&#xA;                double tmp2 = tymin;&#xD;&#xA;                tymin = tymax;&#xD;&#xA;                tymax = tmp2;&#xD;&#xA;                y=-1;&#xD;&#xA;            }&#xD;&#xA;            if (tymin &gt; tNear)&#xD;&#xA;                tNear = tymin;&#xD;&#xA;            if (tymax &lt; tFar)&#xD;&#xA;                tFar = tymax;&#xD;&#xA;            if (tNear &gt; tFar)&#xD;&#xA;                return false;&#xD;&#xA;            if (tFar &lt; 0)&#xD;&#xA;                return false;&#xD;&#xA;            &#xD;&#xA;        &#xD;&#xA;        //ray z direction is parallel to plane&#xD;&#xA;        &#xD;&#xA;            tzmin = (minPt.z - rayIn.origin.z) / rayIn.direction.z;&#xD;&#xA;            tzmax = (maxPt.z - rayIn.origin.z) / rayIn.direction.z;&#xD;&#xA;            z=1;&#xD;&#xA;          &#xD;&#xA;            if (tzmin &gt; tzmax) {&#xD;&#xA;                double tmp3 = tzmin;&#xD;&#xA;                tzmin = tzmax;&#xD;&#xA;                tzmax = tmp3;&#xD;&#xA;                z=-1;&#xD;&#xA;            }&#xD;&#xA;            if (tzmin &gt; tNear)&#xD;&#xA;                tNear = tzmin;&#xD;&#xA;            if (tzmax &lt; tFar)&#xD;&#xA;                tFar = tzmax;&#xD;&#xA;            if (tNear &gt; tFar)&#xD;&#xA;                return false;&#xD;&#xA;            if (tFar &lt; 0)&#xD;&#xA;                return false;&#xD;&#xA;&#xD;&#xA;        double t = Math.min(tNear, tFar);&#xD;&#xA;        // Set the location point.&#xD;&#xA;        &#xD;&#xA;        rayIn.evaluate(outRecord.location, tNear);&#xD;&#xA;        //rayIn.start=0;&#xD;&#xA;        rayIn.end=t;&#xD;&#xA;        &#xD;&#xA;        outRecord.surface=this;&#xD;&#xA;        outRecord.t=t;&#xD;&#xA;        // Set the Normal Vector.&#xD;&#xA;        if(tNear==txmin) {&#xD;&#xA;            outRecord.normal.set(new Vector3(x,0,0));&#xD;&#xA;        } else if (tNear==tymin) {&#xD;&#xA;            outRecord.normal.set(new Vector3(0,y,0));&#xD;&#xA;        } else if (tNear==tzmin) {&#xD;&#xA;            outRecord.normal.set(new Vector3(0,0,z));&#xD;&#xA;        }&#xD;&#xA;        outRecord.normal.normalize();&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    /**&#xD;&#xA;     * @see Object#toString()&#xD;&#xA;     */&#xD;&#xA;    public String toString() {&#xD;&#xA;        return &quot;Box &quot; + minPt + &quot; &quot; + maxPt + &quot; &quot; + shader + &quot; end&quot;;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gLYrp.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/h71Tq.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17608" PostHistoryTypeId="2" PostId="6316" RevisionGUID="53cfe081-2995-4e52-94c7-f8b226cda373" CreationDate="2018-02-22T07:52:03.217" UserId="7462" Text="From the  sources that I have read about deferred rendering they all mention &quot;handling transparency is hard&quot; without much more information.&#xD;&#xA;&#xD;&#xA;However a solution that I see is, handle the scene once without the transparent geometry, once assuming the geometry is fully opaque, then interpolate between the 2 based on the transparency coefficient.&#xD;&#xA;&#xD;&#xA;Is this a bad solution because it's slow due to the additional render pass or is it that there is something else I am not seeing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17609" PostHistoryTypeId="1" PostId="6316" RevisionGUID="53cfe081-2995-4e52-94c7-f8b226cda373" CreationDate="2018-02-22T07:52:03.217" UserId="7462" Text="WHy is this not a proper solution to handling transparency in deferred rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17610" PostHistoryTypeId="3" PostId="6316" RevisionGUID="53cfe081-2995-4e52-94c7-f8b226cda373" CreationDate="2018-02-22T07:52:03.217" UserId="7462" Text="|rendering|transparency|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17611" PostHistoryTypeId="2" PostId="6317" RevisionGUID="0a3a9228-8536-45c3-9de6-340cff72f82f" CreationDate="2018-02-22T08:15:05.907" UserId="7008" Text="PaulHK is right in what he said: you have to consider that there may be more than 2 transparent objects behind each other.&#xD;&#xA;&#xD;&#xA;Also, the idea of deferred shading is to render the geometry only once to be more efficient. If you render the geometries multiple times, you loose (part of) your efficiency. Moreover, the lighting is deferred, thus you'd need to do lighting calculations for all your geometries before you can do the correct color calculations from transparency. So what you're really doing is going back to forward shading.&#xD;&#xA;&#xD;&#xA;That being said, one solution is to first render any opaque geometry with deferred shading and afterwards render the transparent objects with forward shading, so maybe you weren't too far off. Those transparent objects however shouldn't be affected by too many lights to still render frames &quot;fast&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="17616" PostHistoryTypeId="2" PostId="6319" RevisionGUID="4b8872c5-a29f-4087-b944-f5910a58c2b4" CreationDate="2018-02-22T12:19:11.880" UserId="182" Text="A fundamental assumption of deferred shading is that there will be only one surface, and therefore only one depth, at a given pixel.&#xD;&#xA;&#xD;&#xA;An effect that contradicts that assumption will require some sort of special handling in a deferred renderer. Translucency, because it allows to see through multiple layers, is such an effect and therefore will need its own rendering pass, or use some sort of compromise." ContentLicense="CC BY-SA 3.0" />
  <row Id="17620" PostHistoryTypeId="2" PostId="6320" RevisionGUID="87ee85f8-6287-4f7f-b421-85fed30a8340" CreationDate="2018-02-22T13:57:48.367" UserId="8250" Text="I was reading a paper about voxel cone tracing and came across this term. So, what is a Gaussian Lobe or a Lobe in general?&#xD;&#xA;&#xD;&#xA;I am asking in the context of Computer Graphics, BRDF and NDF." ContentLicense="CC BY-SA 3.0" />
  <row Id="17621" PostHistoryTypeId="1" PostId="6320" RevisionGUID="87ee85f8-6287-4f7f-b421-85fed30a8340" CreationDate="2018-02-22T13:57:48.367" UserId="8250" Text="What is a Gaussian Lobe concerning BRDF and NDF?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17622" PostHistoryTypeId="3" PostId="6320" RevisionGUID="87ee85f8-6287-4f7f-b421-85fed30a8340" CreationDate="2018-02-22T13:57:48.367" UserId="8250" Text="|mathematics|brdf|ndf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17623" PostHistoryTypeId="5" PostId="6317" RevisionGUID="a1e32d00-1e7b-4479-906c-55a685353e6a" CreationDate="2018-02-22T14:54:24.150" UserId="209" Comment="Corrected spelling of &quot;lose&quot;" Text="PaulHK is right in what he said: you have to consider that there may be more than 2 transparent objects behind each other.&#xD;&#xA;&#xD;&#xA;Also, the idea of deferred shading is to render the geometry only once to be more efficient. If you render the geometries multiple times, you lose (part of) your efficiency. Moreover, the lighting is deferred, thus you'd need to do lighting calculations for all your geometries before you can do the correct color calculations from transparency. So what you're really doing is going back to forward shading.&#xD;&#xA;&#xD;&#xA;That being said, one solution is to first render any opaque geometry with deferred shading and afterwards render the transparent objects with forward shading, so maybe you weren't too far off. Those transparent objects however shouldn't be affected by too many lights to still render frames &quot;fast&quot;." ContentLicense="CC BY-SA 3.0" />
  <row Id="17624" PostHistoryTypeId="2" PostId="6321" RevisionGUID="34fa0adc-a9eb-4a46-a4aa-fb07c1e21345" CreationDate="2018-02-22T16:49:56.507" UserId="5703" Text="Having a gaussian lobe usually means that your ndf is one or a weighted sum of gaussian distributions. Instead of your ndf, you can define your brdf in the same way.&#xA;&#xA;A [gaussian distribution][1] is a function of the form $$\frac{1}{\sigma\sqrt{2\pi}} e^{\frac{(x-\mu)^2}{2\sigma^2}}$$&#xA;&#xA;It has a hat shape common to many ndfs; this is good because it mimicks how normals align in most real world materials&#xA;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Normal_distribution" ContentLicense="CC BY-SA 3.0" />
  <row Id="17625" PostHistoryTypeId="2" PostId="6322" RevisionGUID="7709d0de-f03a-4389-9de7-97d4d46d330d" CreationDate="2018-02-22T18:22:44.773" UserId="48" Text="In a BRDF or NDF this most likely refers to a [spherical Gaussian](https://mynameismjp.wordpress.com/2016/10/09/sg-series-part-2-spherical-gaussians-101/) distribution, also known as a [von Mises–Fisher distribution](https://en.wikipedia.org/wiki/Von_Mises%E2%80%93Fisher_distribution).&#xD;&#xA;&#xD;&#xA;It's similar to the usual Gaussian, but using the dot product between two unit vectors as a measure of distance to the mean:&#xD;&#xA;&#xD;&#xA;$$ p(\hat v) = a \exp(\lambda(\hat \mu \cdot \hat v))$$&#xD;&#xA;&#xD;&#xA;where $a$ is a normalization factor, $\lambda$ is a number controlling the width of the lobe (roughly corresponds to $1/2\sigma^2$ in the usual Gaussian), $\hat \mu$ is the unit direction vector for the mean of the lobe, and $\hat v$ is the unit direction vector at which we're evaluating the lobe.&#xD;&#xA;&#xD;&#xA;(You'll also sometimes see it defined with $\lambda(\hat \mu \cdot \hat v - 1)$ in the exponent, but the $-1$ term can be pulled out and rolled into the normalization factor.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17626" PostHistoryTypeId="5" PostId="6321" RevisionGUID="db8c1d17-a7af-4ffe-8247-941d13ba6341" CreationDate="2018-02-22T18:25:04.567" UserId="48" Comment="missed minus sign in the exponent :)" Text="Having a gaussian lobe usually means that your ndf is one or a weighted sum of gaussian distributions. Instead of your ndf, you can define your brdf in the same way.&#xD;&#xA;&#xD;&#xA;A [gaussian distribution][1] is a function of the form $$\frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}$$&#xD;&#xA;&#xD;&#xA;It has a hat shape common to many ndfs; this is good because it mimicks how normals align in most real world materials&#xD;&#xA;&#xD;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Normal_distribution" ContentLicense="CC BY-SA 3.0" />
  <row Id="17627" PostHistoryTypeId="2" PostId="6323" RevisionGUID="535c2d8e-f6b8-4147-840a-8dd892d0c9cc" CreationDate="2018-02-22T19:11:35.117" UserId="8191" Text="Obj files give pre-calculated normals which are in model coordinates. So I wonder if they have to be transformed into eye coordinate (where I use them to calculate lighting)? I'm thinking yes because it makes sense, but only rotation and scale because translation doesnt really make sense for free vectors." ContentLicense="CC BY-SA 3.0" />
  <row Id="17628" PostHistoryTypeId="1" PostId="6323" RevisionGUID="535c2d8e-f6b8-4147-840a-8dd892d0c9cc" CreationDate="2018-02-22T19:11:35.117" UserId="8191" Text="Do normals in obj files have to be changed into eye coordinate before being used?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17629" PostHistoryTypeId="3" PostId="6323" RevisionGUID="535c2d8e-f6b8-4147-840a-8dd892d0c9cc" CreationDate="2018-02-22T19:11:35.117" UserId="8191" Text="|3d|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17634" PostHistoryTypeId="2" PostId="6325" RevisionGUID="6190ff9c-af63-4711-b344-0c98e9465f5e" CreationDate="2018-02-22T20:28:11.593" UserId="5717" Text="Having not worked on these games, I can only speculate... but from your description, it sounds like a crude shadow map with orthogonal projection and no depth information. It probably has (or had) a specific name but the way I suspect they did it is:&#xD;&#xA;&#xD;&#xA;* Render the character from above to a binary texture (eg. white there there's nothing, black where the character is), using an orthographic camera.&#xD;&#xA;* When rendering the scene, perform a lookup in that texture and multiply by that color. You would of course exclude your characters from that.&#xD;&#xA;&#xD;&#xA;The calculations involved for the texture lookup would be trivial as everything is 2D, in a plane of the world coordinates. It also does not need programmable shaders which IIRC were not around yet at that time." ContentLicense="CC BY-SA 3.0" />
  <row Id="17635" PostHistoryTypeId="4" PostId="6316" RevisionGUID="6b40ce99-5b83-4333-bd84-1bd17eb1f932" CreationDate="2018-02-22T21:04:19.873" UserId="7462" Comment="edited title" Text="Why is this not a proper solution to handling transparency in deferred rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17636" PostHistoryTypeId="2" PostId="6326" RevisionGUID="6bab113d-6784-4b16-9c8d-65929356421b" CreationDate="2018-02-22T21:35:22.653" UserId="48" Text="Yes, all vectors used for lighting need to be in the same coordinates. If you do lighting in eye space, the normals would need to be transformed to eye space as well. Lighting calculations can also be done in world space, or any other space that's convenient.&#xD;&#xA;&#xD;&#xA;You're right that normal vectors shouldn't receive translation; likewise other vectors that represent directions or displacements rather than points in space. If you represent transformations as 4×4 matrices, it's simple to skip the translation by just leaving off the last column.&#xD;&#xA;&#xD;&#xA;Also, one subtlety that comes up is that if your transformations contain non-uniform scaling (different scale factors along different axes) or shear, then you need to use the **inverse transpose** matrix for normals. This is to ensure that the normals stay perpendicular to the polygons. (The inverse transpose will be the same as the original matrix if neither scaling nor shearing is present.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="17637" PostHistoryTypeId="2" PostId="6327" RevisionGUID="5cd0b8e6-4778-40a1-8b63-4c5dbc362468" CreationDate="2018-02-22T23:25:35.593" UserId="7462" Text="Ok so I am trying to understand how to combine these 2 techniques and I am failing.&#xD;&#xA;&#xD;&#xA;The main goal is to reach the O(lights+fragments) complexity of deferred rendering, instead of O(lights*fragments) of naive/forward rendering.&#xD;&#xA;&#xD;&#xA;This is how I am currently doing things:&#xD;&#xA;&#xD;&#xA;Say we have n lights. Then we generate n shadow maps O(n)&#xD;&#xA;&#xD;&#xA;Now we do one render pass to generate the normal, diffuse color, depth.... information in the geometry buffers.&#xD;&#xA;&#xD;&#xA;Then we check for every fragment whether it is occluded in ALL lights. and shadow it if it is.&#xD;&#xA;&#xD;&#xA;This has an O(Lights*Fragments) complexity, which is wrong, so how can you reach the ideal asymptotic complexity? What should you do?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17638" PostHistoryTypeId="1" PostId="6327" RevisionGUID="5cd0b8e6-4778-40a1-8b63-4c5dbc362468" CreationDate="2018-02-22T23:25:35.593" UserId="7462" Text="How to use shadow mapping and deferred rendering to create a large amount of lights?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17639" PostHistoryTypeId="3" PostId="6327" RevisionGUID="5cd0b8e6-4778-40a1-8b63-4c5dbc362468" CreationDate="2018-02-22T23:25:35.593" UserId="7462" Text="|shadow|shading|shadow-mapping|deferred-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17640" PostHistoryTypeId="2" PostId="6328" RevisionGUID="31d97201-f568-4b8a-9b47-db04f409e9ae" CreationDate="2018-02-23T00:32:40.353" UserId="5703" Text="Deferred rendering does not have an asymptic complexity of O(lights+fragments). It has a complexity of O(fragments+visibleFragments*lights).&#xA;&#xA;What you are doing in deferred rendering is preventing having to calculate lighting for many fragments that cover the same screen pixel. Once you have found which ones are visible, all of those still have to calculate lighting from every light source.&#xA;&#xA;This is faster than forward rendering on the premise that lighting calculations are heavier than geometry calculations and that most fragments are ocluded by other fragments." ContentLicense="CC BY-SA 3.0" />
  <row Id="17644" PostHistoryTypeId="2" PostId="6330" RevisionGUID="85653de2-f444-4ca1-8ea1-de6a93a54b56" CreationDate="2018-02-23T05:18:11.177" UserId="8191" Text="All the books and reference I have read say that the view vector is calculated by subtracting the point where eye is at, from the point where we want to calculate light. But since, eye is at (0, 0, 0) the view vector would be just the negative of the point where eye is at? Is my understanding correct?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17645" PostHistoryTypeId="1" PostId="6330" RevisionGUID="85653de2-f444-4ca1-8ea1-de6a93a54b56" CreationDate="2018-02-23T05:18:11.177" UserId="8191" Text="How to calculate the view vector in Phong Lighting Model?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17646" PostHistoryTypeId="3" PostId="6330" RevisionGUID="85653de2-f444-4ca1-8ea1-de6a93a54b56" CreationDate="2018-02-23T05:18:11.177" UserId="8191" Text="|3d|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17647" PostHistoryTypeId="2" PostId="6331" RevisionGUID="e956b313-3420-4edd-8172-40e796064830" CreationDate="2018-02-23T06:00:08.867" UserId="8191" Text="I'm interpolating normals for Phong lighting models. Since I am calculating in the light of each pixel, I'm doing the interpolating after the viewport transform has been applied. So I save a version of the vertices in eye coordinate in order to do barycentric coordinate on them. &#xD;&#xA;&#xD;&#xA;I get all these weird negative barycentric coordinates though. For example one is (-14928, 18491, -3562). What am I doing wrong?&#xD;&#xA;&#xD;&#xA;    for (int Y = minY; Y &lt;= maxY; Y++) {&#xD;&#xA;	    for (int X = minX; X &lt;= maxX; X++) {&#xD;&#xA;		    float lambda1, lambda2, lambda3;&#xD;&#xA;		    getBarycentricCoordinate(v1, v2, v3, X, Y, &amp;lambda1, &amp;lambda2, &amp;lambda3);&#xD;&#xA;			if ((0.0f &lt;= lambda1 &amp;&amp; 0.0f &lt;= lambda2 &amp;&amp; 0.0f &lt;= lambda3)) {&#xD;&#xA;			    float zValue = lambda1 * zA + lambda2 * zB + lambda3 * zC;&#xD;&#xA;				if (abs(zValue) &lt; abs(raster.zBuffer[Y * rasterWidth + X])) {// If a point is closer to the eye, which is at (0, 0, 0) then draw. zBuffer check&#xD;&#xA;					float lamb1, lamb2, lamb3;&#xD;&#xA;					getBarycentricCoordinate(eyeCoorV1, eyeCoorV2, eyeCoorV3, X, Y, &amp;lamb1, &amp;lamb2, &amp;lamb3);&#xD;&#xA;&#xD;&#xA;					Vector4f incidentPoint = lamb1 * eyeCoorV1 + lamb2 * eyeCoorV2 + lamb3 * eyeCoorV3;&#xD;&#xA;					Vector4f l = lightInEyeCoor - incidentPoint;&#xD;&#xA;                    &#xD;&#xA;                    //transforming normals to eye coordinates&#xD;&#xA;					Vector4f normal1 = modelViewMatrix * objects[k].vertexNormal[vn1Index];&#xD;&#xA;					Vector4f normal2 = modelViewMatrix * objects[k].vertexNormal[vn2Index];&#xD;&#xA;					Vector4f normal3 = modelViewMatrix * objects[k].vertexNormal[vn3Index];&#xD;&#xA;					Vector4f normal = lamb1 * normal1 + lamb2 * normal2 + lamb3 * normal3; // lamb1,lamb2 lamb3 are getting weird results&#xD;&#xA;&#xD;&#xA;					l.normalize();&#xD;&#xA;					normal.normalize();&#xD;&#xA;								&#xD;&#xA;					Colorf color = pointLight.LdLs * objects[k].KaKd * fmaxf(l*normal, 0.0f); // add diffuse color&#xD;&#xA;					color = color + ambientLight * objects[k].KaKd; // add ambient color&#xD;&#xA;					Vector4f r = 2 * (normal * l) * normal - l;&#xD;&#xA;					Vector4f v = -incidentPoint; // because eye is at (0, 0, 0) in eye coordinate, view vector is just negative incidentPoint&#xD;&#xA;					r.normalize();&#xD;&#xA;					v.normalize();&#xD;&#xA;                    //specular lighting &#xD;&#xA;					color = color + pointLight.LdLs * objects[k].Ks * powf(fmax(r*v, 0.0f), objects[k].Ks.A);&#xD;&#xA;					raster.pixels[Y * rasterWidth + X] = floatColorToIntColor(color);&#xD;&#xA;					raster.zBuffer[Y * rasterWidth + X] = zValue;&#xD;&#xA;					}&#xD;&#xA;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;		}" ContentLicense="CC BY-SA 3.0" />
  <row Id="17648" PostHistoryTypeId="1" PostId="6331" RevisionGUID="e956b313-3420-4edd-8172-40e796064830" CreationDate="2018-02-23T06:00:08.867" UserId="8191" Text="How to interpolate vertex normals for Phong lighting when barycentric coordinates are negative?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17649" PostHistoryTypeId="3" PostId="6331" RevisionGUID="e956b313-3420-4edd-8172-40e796064830" CreationDate="2018-02-23T06:00:08.867" UserId="8191" Text="|3d|lighting|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17650" PostHistoryTypeId="2" PostId="6332" RevisionGUID="f235b7f9-eddb-4998-87f6-6914e221db0c" CreationDate="2018-02-23T06:47:13.970" UserId="7008" Text="Calculating a vector $v$ from point $A$ to point $B$ is subtracting the values of $B$ from $A$:&#xD;&#xA;&#xD;&#xA;$v = \left(\begin{array}{c}x\\y\\z\end{array}\right) = B - A = \left(\begin{array}{c}b_x - a_x\\b_y-a_y\\b_z-a_z\end{array}\right)$&#xD;&#xA;&#xD;&#xA;So in your case, you need to subtract the $eye$ point from the point you're calculating light ($pos$) for:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;v = point -eye&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Your $eye$ is the origin, so remaining is only the $point$. Therefore: no, it is not the negative position of the lighted point, but the positive position." ContentLicense="CC BY-SA 3.0" />
  <row Id="17651" PostHistoryTypeId="5" PostId="6332" RevisionGUID="51e4ae1b-93d0-4e88-8c52-c61f3f5bda0f" CreationDate="2018-02-23T07:16:05.573" UserId="7008" Comment="added information about how you would actually calculate light in practice" Text="***EDIT***&#xD;&#xA;&#xD;&#xA;While the basic principle of vector calculation below is correct, as Sebastián Mestre pointed out, in lighting you would use the vector from the lighted fragment to the eye position. Therefore, you would in fact use $v = -(point - eye) = eye - point = -point$, so you were actually correct in your &quot;negative&quot; assumption. Still (what might have been more a typo than a misunderstanding), it is the negative position of the lighted fragment, rather than the negative eye (which would still be the origin).&#xD;&#xA;&#xD;&#xA;As Sebastián also said in a comment to you, you would usually normalize the view vector after you have calculated it. Sebastián is the MVP.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Calculating a vector $v$ from point $A$ to point $B$ is subtracting the values of $B$ from $A$:&#xD;&#xA;&#xD;&#xA;$v = \left(\begin{array}{c}x\\y\\z\end{array}\right) = B - A = \left(\begin{array}{c}b_x - a_x\\b_y-a_y\\b_z-a_z\end{array}\right)$&#xD;&#xA;&#xD;&#xA;So in your case, you need to subtract the $eye$ point from the point you're calculating light ($pos$) for:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;v = point -eye&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Your $eye$ is the origin, so remaining is only the $point$. Therefore: no, it is not the negative position of the lighted point, but the positive position." ContentLicense="CC BY-SA 3.0" />
  <row Id="17652" PostHistoryTypeId="2" PostId="6333" RevisionGUID="4607e9a7-5592-4dce-9b58-ad238213a64b" CreationDate="2018-02-23T09:59:35.340" UserId="2041" Text="It's correct as far as it goes, but there's more. The view vector goes from the shading point to the eye point, but it's normalized (divided by its length so that it has length 1). So if you're shading $p$ and the eye is at the origin, the view vector is $\tfrac{-p}{|-p|}$.&#xD;&#xA;&#xD;&#xA;It's not always this simple, because the &quot;eye&quot; isn't always at the origin. In a scanline rasteriser, you use the view transform to move things to the origin, because that's the only way to make the projection work - but not in a ray-tracer. The camera can be anywhere in a ray-tracer, and when you trace secondary rays (for reflections, refractions, or some other effects), it's definitely not in the same place as the camera.&#xD;&#xA;&#xD;&#xA;In the case you're working on right now, it sounds like you can just normalize $-p$, but you need to remember that it's really the direction from the shading point to the eye point, so that you can do the right thing when the eye point *isn't* the origin." ContentLicense="CC BY-SA 3.0" />
  <row Id="17654" PostHistoryTypeId="5" PostId="6325" RevisionGUID="e418f51a-4587-445e-a654-41a2fff97a30" CreationDate="2018-02-23T14:47:18.880" UserId="5717" Comment="more details about texture lookup and resulting look" Text="Having not worked on these games, I can only speculate... but from your description, it sounds like a crude shadow map with orthogonal projection and no depth information. It probably has (or had) a specific name but the way I suspect they did it is:&#xD;&#xA;&#xD;&#xA;* Render the character from above to a binary texture (eg. white there there's nothing, black where the character is), using an orthographic camera.&#xD;&#xA;* When rendering the scene, perform a lookup in that texture and multiply by that color. You would of course exclude your characters from that.&#xD;&#xA;&#xD;&#xA;The calculations involved for the texture lookup would be trivial as everything is 2D, in a plane of the world coordinates. It also does not need programmable shaders which IIRC were not around yet at that time. What you would need as texture coordinates is simply the (x,z) location of the vertex (assuming y is toward the sky here), along with an offset equal to the (x,z) location of your character. In OpenGL, I believe that could be achieved by `glTexGen` along with a texture transformation matrix.&#xD;&#xA;&#xD;&#xA;The reason for the artifacts is that this really does make a &quot;character-silhouette shaped tube&quot;, as you put it. Looking from above, the shadow is painted on every surface regardless of it being in front of or behind the character (above or below, from the camera's view). It's like you're dropping black ink from the sky inside the outline of the character and it goes through everything." ContentLicense="CC BY-SA 3.0" />
  <row Id="17655" PostHistoryTypeId="5" PostId="6331" RevisionGUID="e73b1b4a-bb29-4415-8e0c-f1b4e0df5716" CreationDate="2018-02-23T15:41:19.687" UserId="8191" Comment="add  barycentric coordinate method" Text="I'm interpolating normals for Phong lighting models. Since I am calculating in the light of each pixel, I'm doing the interpolating after the viewport transform has been applied. So I save a version of the vertices in eye coordinate in order to do barycentric coordinate on them. &#xD;&#xA;&#xD;&#xA;I get all these weird negative barycentric coordinates though. For example one is (-14928, 18491, -3562). What am I doing wrong? This very barycentric coordinate I also use for my texture mapping, and since it gets weird big negative result, it broke the index of my texture map.&#xD;&#xA;&#xD;&#xA;    for (int Y = minY; Y &lt;= maxY; Y++) {&#xD;&#xA;	    for (int X = minX; X &lt;= maxX; X++) {&#xD;&#xA;		    float lambda1, lambda2, lambda3;&#xD;&#xA;		    getBarycentricCoordinate(v1, v2, v3, X, Y, &amp;lambda1, &amp;lambda2, &amp;lambda3);&#xD;&#xA;			if ((0.0f &lt;= lambda1 &amp;&amp; 0.0f &lt;= lambda2 &amp;&amp; 0.0f &lt;= lambda3)) {&#xD;&#xA;			    float zValue = lambda1 * zA + lambda2 * zB + lambda3 * zC;&#xD;&#xA;				if (abs(zValue) &lt; abs(raster.zBuffer[Y * rasterWidth + X])) {// If a point is closer to the eye, which is at (0, 0, 0) then draw. zBuffer check&#xD;&#xA;					float lamb1, lamb2, lamb3;&#xD;&#xA;					getBarycentricCoordinate(eyeCoorV1, eyeCoorV2, eyeCoorV3, X, Y, &amp;lamb1, &amp;lamb2, &amp;lamb3);&#xD;&#xA;&#xD;&#xA;					Vector4f incidentPoint = lamb1 * eyeCoorV1 + lamb2 * eyeCoorV2 + lamb3 * eyeCoorV3;&#xD;&#xA;					Vector4f l = lightInEyeCoor - incidentPoint;&#xD;&#xA;                    &#xD;&#xA;                    //transforming normals to eye coordinates&#xD;&#xA;					Vector4f normal1 = modelViewMatrix * objects[k].vertexNormal[vn1Index];&#xD;&#xA;					Vector4f normal2 = modelViewMatrix * objects[k].vertexNormal[vn2Index];&#xD;&#xA;					Vector4f normal3 = modelViewMatrix * objects[k].vertexNormal[vn3Index];&#xD;&#xA;					Vector4f normal = lamb1 * normal1 + lamb2 * normal2 + lamb3 * normal3; // lamb1,lamb2 lamb3 are getting weird results&#xD;&#xA;&#xD;&#xA;					l.normalize();&#xD;&#xA;					normal.normalize();&#xD;&#xA;								&#xD;&#xA;					Colorf color = pointLight.LdLs * objects[k].KaKd * fmaxf(l*normal, 0.0f); // add diffuse color&#xD;&#xA;					color = color + ambientLight * objects[k].KaKd; // add ambient color&#xD;&#xA;					Vector4f r = 2 * (normal * l) * normal - l;&#xD;&#xA;					Vector4f v = -incidentPoint; // because eye is at (0, 0, 0) in eye coordinate, view vector is just negative incidentPoint&#xD;&#xA;					r.normalize();&#xD;&#xA;					v.normalize();&#xD;&#xA;                    //specular lighting &#xD;&#xA;					color = color + pointLight.LdLs * objects[k].Ks * powf(fmax(r*v, 0.0f), objects[k].Ks.A);&#xD;&#xA;					raster.pixels[Y * rasterWidth + X] = floatColorToIntColor(color);&#xD;&#xA;					raster.zBuffer[Y * rasterWidth + X] = zValue;&#xD;&#xA;					}&#xD;&#xA;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;Below is the code for my barycentric coordinate&#xD;&#xA;&#xD;&#xA;    void getBarycentricCoordinate2D(Vector3f &amp; v1, Vector3f &amp; v2, Vector3f &amp; v3, int X, int Y, float * l1, float * l2, float * l3) {&#xD;&#xA;	    float denonimator = (float)((v2.y - v3.y) * (v1.x - v3.x) + (v3.x - v2.x) * (v1.y - v3.y));&#xD;&#xA;	    float lambda1 = ((v2.y - v3.y)*(X - v3.x) + (v3.x - v2.x)*(Y - v3.y)) / denonimator;&#xD;&#xA;	    float lambda2 = ((v3.y - v1.y)*(X - v3.x) + (v1.x - v3.x)*(Y - v3.y)) / denonimator;&#xD;&#xA;	    *l1 = lambda1;&#xD;&#xA;	    *l2 = lambda2;&#xD;&#xA;	    *l3 = 1 - lambda1 - lambda2;&#xD;&#xA;&#xD;&#xA;}" ContentLicense="CC BY-SA 3.0" />
  <row Id="17665" PostHistoryTypeId="50" PostId="6039" RevisionGUID="a29299b3-1aa9-4caf-9cdc-61890de9d1aa" CreationDate="2018-02-24T05:27:17.993" UserId="-1" />
  <row Id="17667" PostHistoryTypeId="2" PostId="6336" RevisionGUID="cb86b27f-2191-4e3c-bb8e-855d7446e949" CreationDate="2018-02-24T11:44:02.233" UserId="4958" Text="For some time I have been working on UV unwrapper for radiosity computation. The information online about it is very sparse, except how to do it in some high end software. So far I have used triplanar method. The mesh I am testing is Sponza obj file - which consist of 384 objects in single file.&#xD;&#xA;&#xD;&#xA;This method computes normal of each triangle and depending on its direction take into consideration two components of position of model in world space.&#xD;&#xA;&#xD;&#xA;    glm::vec3 faceNormal = glm::normalize( glm::cross( v1-v0, v2-v0 ) );&#xD;&#xA;    float NdotXAxis = std::abs( faceNormal.x );&#xD;&#xA;    float NdotYAxis = std::abs( faceNormal.y );&#xD;&#xA;    float NdotZAxis = std::abs( faceNormal.z );&#xD;&#xA;       &#xD;&#xA;    if (NdotXAxis &gt; NdotYAxis &amp;&amp; NdotXAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.z, v0.y};&#xD;&#xA;    	t.v[1] = {v1.z, v1.y};&#xD;&#xA;    	t.v[2] = {v2.z, v2.y};&#xD;&#xA;    	clustersX[i].triangles.push_back(t);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    else if (NdotYAxis &gt; NdotXAxis &amp;&amp; NdotYAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.z};&#xD;&#xA;    	t.v[1] = {v1.x, v1.z};&#xD;&#xA;    	t.v[2] = {v2.x, v2.z};&#xD;&#xA;    	clustersY[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.y};&#xD;&#xA;    	t.v[1] = {v1.x, v1.y};&#xD;&#xA;    	t.v[2] = {v2.x, v2.y};&#xD;&#xA;    	clustersZ[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Each object has three clusters of triangles in each axis. These clusters have bounding rectangle positions. Then they are packed into single image using recursive rectangle packing algorithm and normalized to $[0, 1]$ range.&#xD;&#xA;&#xD;&#xA;But this creates problems, which exist among triangles in single cluster - if these triangles are coplanar and have similar, for example $z$ and $y$ positions, they will overlap in final texture. &#xD;&#xA;&#xD;&#xA;I tried to detect this and then pack overalapping triangles to different clusters and it works but it is tedious (check every triangle with every other triangle in each cluster) and not very efficient in further packing process. So is there other better method for UV unwrapping or more elegant solution for correction in this method?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17668" PostHistoryTypeId="1" PostId="6336" RevisionGUID="cb86b27f-2191-4e3c-bb8e-855d7446e949" CreationDate="2018-02-24T11:44:02.233" UserId="4958" Text="Triplanar UV unwrapping - overlapping triangles" ContentLicense="CC BY-SA 3.0" />
  <row Id="17669" PostHistoryTypeId="3" PostId="6336" RevisionGUID="cb86b27f-2191-4e3c-bb8e-855d7446e949" CreationDate="2018-02-24T11:44:02.233" UserId="4958" Text="|texture|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17670" PostHistoryTypeId="5" PostId="6336" RevisionGUID="76fb4342-d789-4bbb-938d-a391a4881f09" CreationDate="2018-02-24T12:51:33.887" UserId="4958" Comment="added 9 characters in body" Text="For some time I have been working on UV unwrapper for radiosity computation. The information online about it is very sparse, except how to do it in some high end software. So far I have used triplanar method. The mesh I am testing is Sponza obj file - which consist of 384 objects in single file.&#xD;&#xA;&#xD;&#xA;This method computes normal of each triangle and depending on its direction take into consideration two components of position of model in world space.&#xD;&#xA;&#xD;&#xA;    glm::vec3 faceNormal = glm::normalize( glm::cross( v1-v0, v2-v0 ) );&#xD;&#xA;    float NdotXAxis = std::abs( faceNormal.x );&#xD;&#xA;    float NdotYAxis = std::abs( faceNormal.y );&#xD;&#xA;    float NdotZAxis = std::abs( faceNormal.z );&#xD;&#xA;       &#xD;&#xA;    if (NdotXAxis &gt; NdotYAxis &amp;&amp; NdotXAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.z, v0.y};&#xD;&#xA;    	t.v[1] = {v1.z, v1.y};&#xD;&#xA;    	t.v[2] = {v2.z, v2.y};&#xD;&#xA;    	clustersX[i].triangles.push_back(t);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    else if (NdotYAxis &gt; NdotXAxis &amp;&amp; NdotYAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.z};&#xD;&#xA;    	t.v[1] = {v1.x, v1.z};&#xD;&#xA;    	t.v[2] = {v2.x, v2.z};&#xD;&#xA;    	clustersY[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.y};&#xD;&#xA;    	t.v[1] = {v1.x, v1.y};&#xD;&#xA;    	t.v[2] = {v2.x, v2.y};&#xD;&#xA;    	clustersZ[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Each object has three clusters of triangles in each axis. These clusters have bounding rectangle positions. Then they are packed into single image using recursive rectangle packing algorithm and normalized to $[0, 1]$ range.&#xD;&#xA;&#xD;&#xA;But this creates problems, which exist among triangles in single cluster - if these triangles have same normal direction and similar, for example $z$ and $y$ positions, they will overlap in final texture. &#xD;&#xA;&#xD;&#xA;I tried to detect this and then pack overalapping triangles to different clusters and it works but it is tedious (check every triangle with every other triangle in each cluster) and not very efficient in further packing process. So is there other better method for UV unwrapping or more elegant solution for correction in this method?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17671" PostHistoryTypeId="5" PostId="6336" RevisionGUID="7da09a4d-2f43-4efa-b641-b6c4c162a915" CreationDate="2018-02-24T14:07:49.930" UserId="4958" Comment="added 6 characters in body" Text="For some time I have been working on UV unwrapper for radiosity computation. The information online about it is very sparse, except how to do it in some high end software. So far I have used triplanar method. The mesh I am testing is Sponza obj file - which consist of 384 objects in single file.&#xD;&#xA;&#xD;&#xA;This method computes normal of each triangle and depending on its direction take into consideration two components of position of model in world space.&#xD;&#xA;&#xD;&#xA;    glm::vec3 faceNormal = glm::normalize( glm::cross( v1-v0, v2-v0 ) );&#xD;&#xA;    float NdotXAxis = std::abs( faceNormal.x );&#xD;&#xA;    float NdotYAxis = std::abs( faceNormal.y );&#xD;&#xA;    float NdotZAxis = std::abs( faceNormal.z );&#xD;&#xA;       &#xD;&#xA;    if (NdotXAxis &gt; NdotYAxis &amp;&amp; NdotXAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.z, v0.y};&#xD;&#xA;    	t.v[1] = {v1.z, v1.y};&#xD;&#xA;    	t.v[2] = {v2.z, v2.y};&#xD;&#xA;    	clustersX[i].triangles.push_back(t);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    else if (NdotYAxis &gt; NdotXAxis &amp;&amp; NdotYAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.z};&#xD;&#xA;    	t.v[1] = {v1.x, v1.z};&#xD;&#xA;    	t.v[2] = {v2.x, v2.z};&#xD;&#xA;    	clustersY[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.y};&#xD;&#xA;    	t.v[1] = {v1.x, v1.y};&#xD;&#xA;    	t.v[2] = {v2.x, v2.y};&#xD;&#xA;    	clustersZ[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Each object has three clusters of triangles in each axis. These clusters have bounding rectangle positions. Then they are packed into single image using recursive rectangle packing algorithm and normalized to $[0, 1]$ range.&#xD;&#xA;&#xD;&#xA;But this creates problems, which exist among triangles in single cluster - if these triangles have same biggest axis component and similar, for example $z$ and $y$ positions, they will overlap in final texture. &#xD;&#xA;&#xD;&#xA;I tried to detect this and then pack overalapping triangles to different clusters and it works but it is tedious (check every triangle with every other triangle in each cluster) and not very efficient in further packing process. So is there other better method for UV unwrapping or more elegant solution for correction in this method?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17673" PostHistoryTypeId="5" PostId="6331" RevisionGUID="323628c7-e194-4c31-b6c8-7ccbf2fb6e49" CreationDate="2018-02-24T19:38:20.543" UserId="6" Comment="Fixed formatting." Text="I'm interpolating normals for Phong lighting models. Since I am calculating in the light of each pixel, I'm doing the interpolating after the viewport transform has been applied. So I save a version of the vertices in eye coordinate in order to do barycentric coordinate on them. &#xD;&#xA;&#xD;&#xA;I get all these weird negative barycentric coordinates though. For example one is (-14928, 18491, -3562). What am I doing wrong? This very barycentric coordinate I also use for my texture mapping, and since it gets weird big negative result, it broke the index of my texture map.&#xD;&#xA;&#xD;&#xA;    for (int Y = minY; Y &lt;= maxY; Y++) {&#xD;&#xA;	    for (int X = minX; X &lt;= maxX; X++) {&#xD;&#xA;		    float lambda1, lambda2, lambda3;&#xD;&#xA;		    getBarycentricCoordinate(v1, v2, v3, X, Y, &amp;lambda1, &amp;lambda2, &amp;lambda3);&#xD;&#xA;			if ((0.0f &lt;= lambda1 &amp;&amp; 0.0f &lt;= lambda2 &amp;&amp; 0.0f &lt;= lambda3)) {&#xD;&#xA;			    float zValue = lambda1 * zA + lambda2 * zB + lambda3 * zC;&#xD;&#xA;				if (abs(zValue) &lt; abs(raster.zBuffer[Y * rasterWidth + X])) {// If a point is closer to the eye, which is at (0, 0, 0) then draw. zBuffer check&#xD;&#xA;					float lamb1, lamb2, lamb3;&#xD;&#xA;					getBarycentricCoordinate(eyeCoorV1, eyeCoorV2, eyeCoorV3, X, Y, &amp;lamb1, &amp;lamb2, &amp;lamb3);&#xD;&#xA;&#xD;&#xA;					Vector4f incidentPoint = lamb1 * eyeCoorV1 + lamb2 * eyeCoorV2 + lamb3 * eyeCoorV3;&#xD;&#xA;					Vector4f l = lightInEyeCoor - incidentPoint;&#xD;&#xA;                    &#xD;&#xA;                    //transforming normals to eye coordinates&#xD;&#xA;					Vector4f normal1 = modelViewMatrix * objects[k].vertexNormal[vn1Index];&#xD;&#xA;					Vector4f normal2 = modelViewMatrix * objects[k].vertexNormal[vn2Index];&#xD;&#xA;					Vector4f normal3 = modelViewMatrix * objects[k].vertexNormal[vn3Index];&#xD;&#xA;					Vector4f normal = lamb1 * normal1 + lamb2 * normal2 + lamb3 * normal3; // lamb1,lamb2 lamb3 are getting weird results&#xD;&#xA;&#xD;&#xA;					l.normalize();&#xD;&#xA;					normal.normalize();&#xD;&#xA;								&#xD;&#xA;					Colorf color = pointLight.LdLs * objects[k].KaKd * fmaxf(l*normal, 0.0f); // add diffuse color&#xD;&#xA;					color = color + ambientLight * objects[k].KaKd; // add ambient color&#xD;&#xA;					Vector4f r = 2 * (normal * l) * normal - l;&#xD;&#xA;					Vector4f v = -incidentPoint; // because eye is at (0, 0, 0) in eye coordinate, view vector is just negative incidentPoint&#xD;&#xA;					r.normalize();&#xD;&#xA;					v.normalize();&#xD;&#xA;                    //specular lighting &#xD;&#xA;					color = color + pointLight.LdLs * objects[k].Ks * powf(fmax(r*v, 0.0f), objects[k].Ks.A);&#xD;&#xA;					raster.pixels[Y * rasterWidth + X] = floatColorToIntColor(color);&#xD;&#xA;					raster.zBuffer[Y * rasterWidth + X] = zValue;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Below is the code for my barycentric coordinate&#xD;&#xA;&#xD;&#xA;    void getBarycentricCoordinate2D(Vector3f &amp; v1, Vector3f &amp; v2, Vector3f &amp; v3, int X, int Y, float * l1, float * l2, float * l3) {&#xD;&#xA;	    float denonimator = (float)((v2.y - v3.y) * (v1.x - v3.x) + (v3.x - v2.x) * (v1.y - v3.y));&#xD;&#xA;	    float lambda1 = ((v2.y - v3.y)*(X - v3.x) + (v3.x - v2.x)*(Y - v3.y)) / denonimator;&#xD;&#xA;	    float lambda2 = ((v3.y - v1.y)*(X - v3.x) + (v1.x - v3.x)*(Y - v3.y)) / denonimator;&#xD;&#xA;	    *l1 = lambda1;&#xD;&#xA;	    *l2 = lambda2;&#xD;&#xA;	    *l3 = 1 - lambda1 - lambda2;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="17674" PostHistoryTypeId="24" PostId="6331" RevisionGUID="323628c7-e194-4c31-b6c8-7ccbf2fb6e49" CreationDate="2018-02-24T19:38:20.543" Comment="Proposed by 6 approved by 8191 edit id of 315" ContentLicense="CC BY-SA 3.0" />
  <row Id="17675" PostHistoryTypeId="2" PostId="6337" RevisionGUID="12464eda-5ceb-4eab-b8e0-2920385d7957" CreationDate="2018-02-25T00:38:52.080" UserId="8191" Text="I have figured out the solution to this, and want to share it. What I am doing is I calculate different barycentric coordinate for each of the step I need to do: z-buffer, interpolation of normal, etc. &#xD;&#xA;&#xD;&#xA;The correct way is to use the barycentric coordinate that is calculated when checking z-buffer to test whether a pixel inside a triangle. Because that barycentric coordinate is guaranteed to be inside the [0, 1] range (otherwise the pixel wouldnt have been drawn), it is the correct barycentric coordinate to use.    " ContentLicense="CC BY-SA 3.0" />
  <row Id="17676" PostHistoryTypeId="2" PostId="6338" RevisionGUID="ad8d7ddf-7ab1-4556-bf21-962d51ad78b4" CreationDate="2018-02-25T00:40:11.890" UserId="8268" Text="If I have a rotation, $A$, and a translation, $B$, which I multiply like so&#xD;&#xA;&#xD;&#xA;$C = AB$&#xD;&#xA;&#xD;&#xA;Does the inverse of $C$ not only inverse the magnitudes of $A$ and $B$ but also become the reverse of operations?&#xD;&#xA;&#xD;&#xA;e.g. $C^{-1} = BA$?&#xD;&#xA;&#xD;&#xA;Does the inverse of a matrix also inverse the order of original operations (or am I conflating inverse with reverse)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17677" PostHistoryTypeId="1" PostId="6338" RevisionGUID="ad8d7ddf-7ab1-4556-bf21-962d51ad78b4" CreationDate="2018-02-25T00:40:11.890" UserId="8268" Text="Inverse matrix order of operation" ContentLicense="CC BY-SA 3.0" />
  <row Id="17678" PostHistoryTypeId="3" PostId="6338" RevisionGUID="ad8d7ddf-7ab1-4556-bf21-962d51ad78b4" CreationDate="2018-02-25T00:40:11.890" UserId="8268" Text="|matrix|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17679" PostHistoryTypeId="2" PostId="6339" RevisionGUID="37e6e163-595b-4e48-a4f6-b8c3ad7303a8" CreationDate="2018-02-25T10:59:44.840" UserId="1937" Text="Yes. If you're compounding operations to make a matrix, then the inverse matrix will be the compound of the inverse operations, in the reverse order. So if $C = AB$ then $C^{-1} = B^{-1}A^{-1}$&#xD;&#xA;&#xD;&#xA;Think of it geometrically. Taking a 2D example, if you have an object at the origin, and you want to move it +2 units in X then rotate around the origin by +45 degrees. To undo this transformation, you need to first rotate by -45 degrees then translate by -2 units in X." ContentLicense="CC BY-SA 3.0" />
  <row Id="17684" PostHistoryTypeId="50" PostId="6175" RevisionGUID="18fc2b6b-4f80-4d7e-a920-1cb89a3cf5a0" CreationDate="2018-02-26T06:53:03.133" UserId="-1" />
  <row Id="17685" PostHistoryTypeId="2" PostId="6341" RevisionGUID="a180676c-f225-4327-96d3-4c172ccfa2b9" CreationDate="2018-02-26T08:49:17.900" UserId="8177" Text="I know about the standard methods to pass floats, ints, or vectors. However, I'm curious whether there is an elegant way to pass data from libGDX Java code directly into a shader struct.&#xA;&#xA;I'm looking for a libGDX method to pass a whole structure *or* best practice examples on how to pass structured data in case libGDX does not support this natively." ContentLicense="CC BY-SA 3.0" />
  <row Id="17686" PostHistoryTypeId="1" PostId="6341" RevisionGUID="a180676c-f225-4327-96d3-4c172ccfa2b9" CreationDate="2018-02-26T08:49:17.900" UserId="8177" Text="How to pass *struct*ured data from libGDX to openGL shader?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17687" PostHistoryTypeId="3" PostId="6341" RevisionGUID="a180676c-f225-4327-96d3-4c172ccfa2b9" CreationDate="2018-02-26T08:49:17.900" UserId="8177" Text="|opengl|shader|data-structure|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17690" PostHistoryTypeId="50" PostId="5925" RevisionGUID="d6e09d52-b05a-4f9c-8da6-858e4e0aea46" CreationDate="2018-02-26T12:53:47.793" UserId="-1" />
  <row Id="17691" PostHistoryTypeId="5" PostId="6336" RevisionGUID="fbe4c64f-2ce4-41f3-ba13-ff1634fd8d5c" CreationDate="2018-02-26T13:01:47.097" UserId="4958" Comment="deleted 2 characters in body" Text="For some time I have been working on UV unwrapper for radiosity computation. The information online about it is very sparse, except how to do it in some high end software. So far I have used triplanar method. The mesh I am testing is Sponza obj file - which consist of 384 objects in single file.&#xD;&#xA;&#xD;&#xA;This method computes normal of each triangle and depending on its direction take into consideration two components of position of model in world space.&#xD;&#xA;&#xD;&#xA;    glm::vec3 faceNormal = glm::normalize( glm::cross( v1-v0, v2-v0 ) );&#xD;&#xA;    float NdotXAxis = std::abs( faceNormal.x );&#xD;&#xA;    float NdotYAxis = std::abs( faceNormal.y );&#xD;&#xA;    float NdotZAxis = std::abs( faceNormal.z );&#xD;&#xA;       &#xD;&#xA;    if (NdotXAxis &gt; NdotYAxis &amp;&amp; NdotXAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.z, v0.y};&#xD;&#xA;    	t.v[1] = {v1.z, v1.y};&#xD;&#xA;    	t.v[2] = {v2.z, v2.y};&#xD;&#xA;    	clustersX[i].triangles.push_back(t);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    else if (NdotYAxis &gt; NdotXAxis &amp;&amp; NdotYAxis &gt; NdotZAxis)&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.z};&#xD;&#xA;    	t.v[1] = {v1.x, v1.z};&#xD;&#xA;    	t.v[2] = {v2.x, v2.z};&#xD;&#xA;    	clustersY[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	Triangle t;&#xD;&#xA;    	t.v[0] = {v0.x, v0.y};&#xD;&#xA;    	t.v[1] = {v1.x, v1.y};&#xD;&#xA;    	t.v[2] = {v2.x, v2.y};&#xD;&#xA;    	clustersZ[i].triangles.push_back(t);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Each object has three clusters of triangles in each axis. These clusters have bounding rectangle positions. Then they are packed into single image using recursive rectangle packing algorithm and normalized to $[0, 1]$ range.&#xD;&#xA;&#xD;&#xA;But this creates problems, which exist among triangles in single cluster - if these triangles have, for example, major $x$ axis component and similar $z$ and $y$ positions, they will overlap in final texture. &#xD;&#xA;&#xD;&#xA;I tried to detect this and then pack overalapping triangles to different clusters and it works but it is tedious (check every triangle with every other triangle in each cluster) and not very efficient in further packing process. So is there other better method for UV unwrapping or more elegant solution for correction in this method?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17692" PostHistoryTypeId="50" PostId="6172" RevisionGUID="57f6a641-04cc-4214-b1ca-4ef326c6c8cd" CreationDate="2018-02-26T16:56:33.373" UserId="-1" />
  <row Id="17700" PostHistoryTypeId="2" PostId="6343" RevisionGUID="103026e9-4c61-4fe5-a3b4-38ad88acf3cf" CreationDate="2018-02-27T05:00:21.323" UserId="8283" Text="Don't know the game but hard shadows are usually shadow volumes, often implemented with help of a stencil buffer. You can find a short description of the algorithm on Wikipedia." ContentLicense="CC BY-SA 3.0" />
  <row Id="17707" PostHistoryTypeId="2" PostId="6345" RevisionGUID="119fd926-2a3f-4961-9d64-598c11c8c3ca" CreationDate="2018-02-28T17:15:24.017" UserId="8294" Text="(sorry for my english)  &#xD;&#xA;**The task:**  &#xD;&#xA;A triangle is specified. To realize its motion on the basis of mirror reflection with respect to an arbitrary line ax + by + c = 0, the coefficients of which are entered by the user.  &#xD;&#xA;&#xD;&#xA;**Already done:**  &#xD;&#xA;I read from the fields on the form the coordinates of the three points of the triangle.  &#xD;&#xA;Putting them into objects of class `Point` (`left (x, y)`, `top (x, y)`, `right (x, y)`).  &#xD;&#xA;Make an array of `points` from the points of a triangle:&#xD;&#xA;&#xD;&#xA;    Point[] points = new Point[3] { left, top, right };&#xD;&#xA;&#xD;&#xA;Draw a coordinate system:&#xD;&#xA;&#xD;&#xA;    DrawField();&#xD;&#xA;    DrawCoordinateSystem();&#xD;&#xA;Draw a triangle:&#xD;&#xA;&#xD;&#xA;    graph.FillPolygon(Brushes.ForestGreen, points);&#xD;&#xA;Make a mirror reflection of the triangle:&#xD;&#xA;&#xD;&#xA;    Point[] pointsCopy = (Point[]) points.Clone();   &#xD;&#xA;    for (int i = 0; i  pointsCopy.Length; i++)&#xD;&#xA;        pointsCopy[i].Y = -pointsCopy[i].Y; &#xD;&#xA;    graph.FillPolygon(Brushes.RoyalBlue, pointsCopy);&#xD;&#xA;Read the coefficients (`a`, `b`, `c`) from the fields on the form for the equation `ax + by + c = 0`.  &#xD;&#xA;&#xD;&#xA;[![affine transformations of triangle][1]][1]&#xD;&#xA;&#xD;&#xA;**Question:**  &#xD;&#xA;Tell me how to move it further relative to the line `ax + by + c = 0` ?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/f6tXI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17708" PostHistoryTypeId="1" PostId="6345" RevisionGUID="119fd926-2a3f-4961-9d64-598c11c8c3ca" CreationDate="2018-02-28T17:15:24.017" UserId="8294" Text="How to make a translation relative to the line ax + by + c = 0, affine transformations" ContentLicense="CC BY-SA 3.0" />
  <row Id="17709" PostHistoryTypeId="3" PostId="6345" RevisionGUID="119fd926-2a3f-4961-9d64-598c11c8c3ca" CreationDate="2018-02-28T17:15:24.017" UserId="8294" Text="|vector-graphics|affine-transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17710" PostHistoryTypeId="5" PostId="6278" RevisionGUID="de59b4c9-6b9a-471d-9ac2-6cbd7f2d6d5e" CreationDate="2018-02-28T18:54:59.557" UserId="7622" Comment="added 3 characters in body; edited title" Text="I have a quad-based 3D mesh. I want to:&#xD;&#xA;&#xD;&#xA;- remesh it while keeping the shape the same&#xD;&#xA;- the end output should be in quads&#xD;&#xA;- ideally it should have a similar number of verts / polys as the input&#xD;&#xA;- ideally the remeshing would be random, and output mesh would be distinct from the input&#xD;&#xA;&#xD;&#xA;Right now I'm remeshing with Meshlab, which outputs tris. I then use the Tris to Quads function from Blender. The problem is that that function is not perfect, and leaves many tris. &#xD;&#xA;&#xD;&#xA;So ideally there'd be a quad-based random remesh tool, but if anyone knows of a better tri-to-quad tool that would also be helpful?&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="17711" PostHistoryTypeId="4" PostId="6278" RevisionGUID="de59b4c9-6b9a-471d-9ac2-6cbd7f2d6d5e" CreationDate="2018-02-28T18:54:59.557" UserId="7622" Comment="added 3 characters in body; edited title" Text="Best way to remesh a quad 3D mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17712" PostHistoryTypeId="2" PostId="6346" RevisionGUID="cba2f1a0-dbc4-4318-b087-f4c7b491c641" CreationDate="2018-02-28T19:41:04.990" UserId="5079" Text="To mirror an object in relation to an arbitrary line, you first have to find the coordinates of that object in the frame of reference of that line. For convenience, we will define a frame of reference where the X axis is colinear with the line itself and the Y axis will be perpendicular to the line. Then, we can flip the Y coordinate in that frame of reference to obtain the mirrored point and finally we will reverse the transform from the line coordinate system and back to the global coordinate system.&#xD;&#xA;&#xD;&#xA;To define a coordinate system, we will need to use one point the line passes through as the origin O of that coordinate system. This can be obtained easily by setting x = 0 or y = 0 in the line equation and we end up with the point {-c/a, 0} or {0, -c/b}. Getting the X and Y axis of the new coordinate system is easy. The X axis vector {Xx, Xy} will be computed by normalizing {a, b} from the line equation. Then we need a perpendicular vector for the Y axis direction. This is easily obtained by using either {-Xy, Xx} or {Xy, -Xx} (you can verify that by taking the dot product between X and Y which will be zero).&#xD;&#xA;&#xD;&#xA;Now that you have an origin and a coordinate system, let's find a mirrored point of vector P on that system. First we need to express it in the new coordinate system. This can be done by projecting P - O to the basis vectors X and Y, so the coordinates in the new system will be {dot((P - O), X), dot((P - O), Y)}.&#xD;&#xA;To obtain the mirrored point, we simply flip the Y coordinate. To obtain the final vector in the original space, we simply invert the first transform. The final point should be O + X * dot((P - O), X) - Y * dot((P - O), Y)&#xD;&#xA;&#xD;&#xA;I hope this helps. Probably there's a way to make the notation better in stack overflow but that should do for now." ContentLicense="CC BY-SA 3.0" />
  <row Id="17713" PostHistoryTypeId="5" PostId="6346" RevisionGUID="4571d8d0-4630-4440-8b9f-2f49c5fddfb4" CreationDate="2018-02-28T20:31:27.667" UserId="5703" Comment="Added mathjax" Text="To mirror an object in relation to an arbitrary line, you first have to find the coordinates of that object in the frame of reference of that line. For convenience, we will define a frame of reference where the $X$ axis is colinear with the line itself and the $Y$ axis will be perpendicular to the line. Then, we can flip the Y coordinate in that frame of reference to obtain the mirrored point and finally we will reverse the transform from the line coordinate system and back to the global coordinate system.&#xD;&#xA;&#xD;&#xA;To define a coordinate system, we will need to use one point the line passes through as the origin $O$ of that coordinate system. This can be obtained easily by setting $x = 0$ or $y = 0$ in the line equation and we end up with the point $\{-c/a, 0\}$ or $\{0, -c/b\}$. Getting the $X$ and $Y$ axis of the new coordinate system is easy. The $X$ axis vector $\{X_x, X_y\}$ will be computed by normalizing $\{a, b\}$ from the line equation. Then we need a perpendicular vector for the $Y$ axis direction. This is easily obtained by using either $\{-X_y, X_x\}$ or $\{X_y, -X_x\}$ (you can verify that by taking the dot product between $X$ and $Y$ which will be zero).&#xD;&#xA;&#xD;&#xA;Now that you have an origin and a coordinate system, let's find a mirrored point of vector P on that system. First we need to express it in the new coordinate system. This can be done by projecting $P-O$ to the basis vectors $X$ and $Y$, so the coordinates in the new system will be $\{\langle(P - O), X\rangle, \langle(P - O), Y\rangle\}$.&#xD;&#xA;To obtain the mirrored point, we simply flip the Y coordinate. To obtain the final vector in the original space, we simply invert the first transform. The final point should be $O + X\cdot\langle(P-O), X\rangle - Y\cdot\langle(P-O), Y\rangle$&#xD;&#xA;&#xD;&#xA;A note on notation: $\langle u,v\rangle$ was used for dot product between vectors. $u\cdot k$ was used for product between vector and scalar" ContentLicense="CC BY-SA 3.0" />
  <row Id="17714" PostHistoryTypeId="24" PostId="6346" RevisionGUID="4571d8d0-4630-4440-8b9f-2f49c5fddfb4" CreationDate="2018-02-28T20:31:27.667" Comment="Proposed by 5703 approved by 5079 edit id of 316" ContentLicense="CC BY-SA 3.0" />
  <row Id="17715" PostHistoryTypeId="2" PostId="6347" RevisionGUID="9e6f1c09-3e43-46b8-ae36-623371bf762f" CreationDate="2018-03-01T09:31:29.877" UserId="6046" Text="If I understand correctly, you want to draw 2 objects mirrored with respect to an arbitrary line. Then when you move 1 object you want the other (reflection) to move with respect to that reflected line. &#xD;&#xA;&#xD;&#xA;A more sophisticated way of doing this would be using transformation matrices. That way you wouldn't have to worry about moving the mirrored triangle. You will move the original triangle, apply a transformation matrix to find the position of the mirrored triangle.&#xD;&#xA;&#xD;&#xA;Suppose we have an arbitrary line $ax+by+c = 0$ making an arbitrary angle (measured counter clockwise) with the +X axis. We can easily find slope in the form of $ y = mx + c$ and the angle $\theta = tan^-1(m)$.&#xD;&#xA;&#xD;&#xA;The mirror transformation with respect to this line can be broken in 3 affine transformation.&#xD;&#xA;&#xD;&#xA;1) Rotate the line by  $-\theta$ to coincide it with the X-axis.&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;cos(-theta) &amp; -sin(-theta) &amp; 0\\&#xD;&#xA;sin(-theta) &amp; cos(-theta)  &amp; 0\\&#xD;&#xA;0           &amp; 0            &amp; 1&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2) Reflect about the X-axis.&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;1 &amp; 0  &amp; 0\\&#xD;&#xA;0 &amp; -1 &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;3) Rotate again by $\theta$.&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;cos(theta) &amp; -sin(theta) &amp; 0\\&#xD;&#xA;sin(theta) &amp; cos(theta)  &amp; 0\\&#xD;&#xA;0           &amp; 0            &amp; 1&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Now you concatenate all 3 and you get a matrix that reflects about an arbitrary line.&#xD;&#xA;&#xD;&#xA;Now we only move 1 triangle and find out the other by applying the matrix." ContentLicense="CC BY-SA 3.0" />
  <row Id="17716" PostHistoryTypeId="2" PostId="6348" RevisionGUID="fa66b880-c3b7-4045-b4a5-5b19e982523d" CreationDate="2018-03-01T11:01:32.803" UserId="8297" Text="I currently perform several operations on polyhedra with cgal. These operations include&#xD;&#xA;&#xD;&#xA;- Union of two or more polyhedra&#xD;&#xA;- Difference of two or more polyhedra&#xD;&#xA;- Intersection of two or more polyhedra&#xD;&#xA;- Cutting Plane&#xD;&#xA;- Ray intersection with polyhedra&#xD;&#xA;&#xD;&#xA;and some more.&#xD;&#xA;&#xD;&#xA;The polyhedra are not necessarily convex, but are otherwise simple (i.e. non-selfintersecting)&#xD;&#xA;&#xD;&#xA;I am now trying to find a way to hardware-accelerate these operations for speed efficiency reasons and thought, that GPUs might be capable to handle this task. However, most interfaces (i.e. OpenGL) I have seen focus on rendering.&#xD;&#xA;&#xD;&#xA;Is there a good interface for performing these calculations with GPU support and retrieving the result subsequently?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17717" PostHistoryTypeId="1" PostId="6348" RevisionGUID="fa66b880-c3b7-4045-b4a5-5b19e982523d" CreationDate="2018-03-01T11:01:32.803" UserId="8297" Text="Efficient operations on polyhedra" ContentLicense="CC BY-SA 3.0" />
  <row Id="17718" PostHistoryTypeId="3" PostId="6348" RevisionGUID="fa66b880-c3b7-4045-b4a5-5b19e982523d" CreationDate="2018-03-01T11:01:32.803" UserId="8297" Text="|3d|gpu|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17719" PostHistoryTypeId="50" PostId="4361" RevisionGUID="b3011711-82f2-4257-bd50-34626e16ab11" CreationDate="2018-03-01T12:13:17.790" UserId="-1" />
  <row Id="17720" PostHistoryTypeId="2" PostId="6349" RevisionGUID="1e940ab9-cd59-4381-9a73-d1652f34dd11" CreationDate="2018-03-01T13:09:32.273" UserId="5430" Text="Anisotropic filtering and multisample anti-aliasing both imply supersampling.&#xD;&#xA;&#xD;&#xA;In [EWA](https://www.cs.cmu.edu/~ph/texfund/texfund.pdf) and (derived) [Feline](http://watkins.cs.queensu.ca/~jstewart/454/notes/WRL-99-1.pdf) AF algorithms a non-uniform weighted average is used. But in case of MSAA not. Why this is the case? Isn't it better to use weighted average in case of MSAA?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17721" PostHistoryTypeId="1" PostId="6349" RevisionGUID="1e940ab9-cd59-4381-9a73-d1652f34dd11" CreationDate="2018-03-01T13:09:32.273" UserId="5430" Text="Anisotropic filtering and multisample anti-aliasing" ContentLicense="CC BY-SA 3.0" />
  <row Id="17722" PostHistoryTypeId="3" PostId="6349" RevisionGUID="1e940ab9-cd59-4381-9a73-d1652f34dd11" CreationDate="2018-03-01T13:09:32.273" UserId="5430" Text="|antialiasing|supersampling|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17723" PostHistoryTypeId="2" PostId="6350" RevisionGUID="4e5db409-9d31-4d80-a262-3fb5255fa03c" CreationDate="2018-03-01T14:49:32.047" UserId="8305" Text="I'm playing with a grid-based lighting system, where light is transported and accumulated through a grid. I initially tried attenuation based on `1/(distance*distance)`, but that doesn't work when the distance between each node is 1.&#xD;&#xA;&#xD;&#xA;[![Here's a picture][1]][1]&#xD;&#xA;&#xD;&#xA;I tried hacks like adding an epsilon or clamping the distance, but nothing looks right. I'm sure there's something obvious I'm missing. Any guidance?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pzbdi.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17724" PostHistoryTypeId="1" PostId="6350" RevisionGUID="4e5db409-9d31-4d80-a262-3fb5255fa03c" CreationDate="2018-03-01T14:49:32.047" UserId="8305" Text="Light Falloff through a grid" ContentLicense="CC BY-SA 3.0" />
  <row Id="17725" PostHistoryTypeId="3" PostId="6350" RevisionGUID="4e5db409-9d31-4d80-a262-3fb5255fa03c" CreationDate="2018-03-01T14:49:32.047" UserId="8305" Text="|raytracing|lighting|pathtracing|global-illumination|grid|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17726" PostHistoryTypeId="2" PostId="6351" RevisionGUID="452298ab-ae7e-43f2-bdb0-a995aa2a2ed8" CreationDate="2018-03-01T15:10:09.080" UserId="8303" Text="I am looking for a way to efficiently compute ray-triangle intersections for a large number of rays (~1k) and a large set of triangle-mesh bodies (~100k) with each composed of several hundred faces. My current approach towards optimization consists of &#xD;&#xA;&#xD;&#xA;* thread parallelism for each ray&#xD;&#xA;* pre-select bodies by testing for ray-bounding box intersections&#xD;&#xA;* loop over faces of pre-selected bodies to detect ray-triangle intersections using the Möller-Trumbore algorithm.&#xD;&#xA;&#xD;&#xA;Not impressed with performance so far. (Admittedly using python). Are there alternative solutions ?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17727" PostHistoryTypeId="1" PostId="6351" RevisionGUID="452298ab-ae7e-43f2-bdb0-a995aa2a2ed8" CreationDate="2018-03-01T15:10:09.080" UserId="8303" Text="Rays (~1k) intersecting triangle meshes (~100k) with ca. 100 vertices each" ContentLicense="CC BY-SA 3.0" />
  <row Id="17728" PostHistoryTypeId="3" PostId="6351" RevisionGUID="452298ab-ae7e-43f2-bdb0-a995aa2a2ed8" CreationDate="2018-03-01T15:10:09.080" UserId="8303" Text="|raytracing|optimisation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17733" PostHistoryTypeId="2" PostId="6353" RevisionGUID="e11bec8e-5de8-443e-8635-42d2489f20c4" CreationDate="2018-03-02T06:03:51.793" UserId="1937" Text="It looks to me like you're resetting the distance calculation at each grid intersection? So every time you march another grid cell you're dividing the light intensity by $gridsize^2$ ? That would explain your observed results, since dividing by $1^2$ equals no change. It won't give you the correct result though, since to get the right attenuation you need to track the *total distance* back to the light source and square that. &#xD;&#xA;&#xD;&#xA;Also note that the attenuation term used in rendering is usually a bit more complicated than just $D^2$ - generally it's a quadratic, $aD^2 + bD + c$. While not physically correct, it's more tunable and easier to get visually pleasing results. In your case, for example, using $D^2 + 1$ would prevent the edges immediately surrounding the light from being brighter than the light itself." ContentLicense="CC BY-SA 3.0" />
  <row Id="17734" PostHistoryTypeId="2" PostId="6354" RevisionGUID="e5f2705a-83a8-4673-9732-7835af1314df" CreationDate="2018-03-02T08:59:05.157" UserId="6725" Text="Your procedure could be optimized in two directions:&#xA;&#xA;  1. If your rays are structured you could possibly take advantage of space coherence: if a ray intersects a given triangle, then a nearby rays has high possibility of intersecting the same triangle or an neighboring one. Therefore simple parallelism over the rays may not be optimal, you could at least process them in batches based on adjacency.&#xA;&#xA;  2. If you have adjacency information on the triangles of your meshes, you could possibly exploit it when testing a ray against the mesh: the Möller-Trumbore algorithm can inform you if the intersection point of the ray and the triangle plane lies inside or outside each of the edges, so you may have a hint at which (neighboring) triangle to check next. That said, your meshes are quite small so the extra overhead may not be worth it." ContentLicense="CC BY-SA 3.0" />
  <row Id="17737" PostHistoryTypeId="2" PostId="6356" RevisionGUID="40da62bc-f524-42db-84a2-69562d2ab15a" CreationDate="2018-03-03T03:56:10.963" UserId="5183" Text="I want to write code for a cube rotating 10 degrees back and forth on its y-axis in an OpenGL application. Right now I have this written, however it depends on processor speed, and it may be more complicated than it needs to be. I would like to make the code independent of processor speed.&#xD;&#xA;&#xD;&#xA;    GLfloat rot = 10;&#xD;&#xA;    GLfloat angle = 0, angle2 = 0, angle3 = 0;&#xD;&#xA;&#xD;&#xA;    if (angle &lt; rot){&#xD;&#xA;	   glRotated(angle, 0, 1,0);							      &#xD;&#xA;       angle++;&#xD;&#xA;    }&#xD;&#xA;    else{&#xD;&#xA;	   if (angle2 &lt; rot * 2 ){&#xD;&#xA;		 glRotated(rot - angle2, 0, 1, 0);		&#xD;&#xA;		 angle2++;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	else{&#xD;&#xA;	    if (angle3 &lt; rot ){&#xD;&#xA;		 glRotated(-rot + angle3, 0, 1, 0);		&#xD;&#xA;		 angle3++;&#xD;&#xA;		}&#xD;&#xA;					&#xD;&#xA;    else{ angle = 0, angle2 = 0, angle3 = 0; }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17738" PostHistoryTypeId="1" PostId="6356" RevisionGUID="40da62bc-f524-42db-84a2-69562d2ab15a" CreationDate="2018-03-03T03:56:10.963" UserId="5183" Text="Back and forth rotation on Y-axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="17739" PostHistoryTypeId="3" PostId="6356" RevisionGUID="40da62bc-f524-42db-84a2-69562d2ab15a" CreationDate="2018-03-03T03:56:10.963" UserId="5183" Text="|opengl|transformations|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17740" PostHistoryTypeId="5" PostId="6356" RevisionGUID="6793782b-6beb-4cf8-af55-4cf0647c3ad4" CreationDate="2018-03-03T04:01:56.373" UserId="5183" Comment="added 21 characters in body" Text="I want to write code for a cube rotating 10 degrees back and forth on its y-axis in an OpenGL application. Right now I have this written in my display method, however it depends on processor speed, and it may be more complicated than it needs to be. I would like to make the code independent of processor speed.&#xD;&#xA;&#xD;&#xA;    GLfloat rot = 10;&#xD;&#xA;    GLfloat angle = 0, angle2 = 0, angle3 = 0;&#xD;&#xA;&#xD;&#xA;    if (angle &lt; rot){&#xD;&#xA;	   glRotated(angle, 0, 1,0);							      &#xD;&#xA;       angle++;&#xD;&#xA;    }&#xD;&#xA;    else{&#xD;&#xA;	   if (angle2 &lt; rot * 2 ){&#xD;&#xA;		 glRotated(rot - angle2, 0, 1, 0);		&#xD;&#xA;		 angle2++;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	else{&#xD;&#xA;	    if (angle3 &lt; rot ){&#xD;&#xA;		 glRotated(-rot + angle3, 0, 1, 0);		&#xD;&#xA;		 angle3++;&#xD;&#xA;		}&#xD;&#xA;					&#xD;&#xA;    else{ angle = 0, angle2 = 0, angle3 = 0; }&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17741" PostHistoryTypeId="2" PostId="6357" RevisionGUID="f8d1a317-45df-40dd-9a57-4968a033b4c7" CreationDate="2018-03-03T05:18:42.913" UserId="3003" Text="In order to dissociate the rotation from the CPU speed, you need to use some sort of timing in your function. I recommend passing in a time value of some sort. The easiest thing is to pass in the number of seconds since the app started. How you do that depends on your particular OS, which you didn't specify. &#xD;&#xA;&#xD;&#xA;Once you have a timing constant, you can generate a triangle wave to control the rotation. This formula will oscillate between 0 and 1 over time:&#xD;&#xA;&#xD;&#xA;    double rotation = 2.0 * fabs(fmod(time, 1.0) - 0.5);&#xD;&#xA;&#xD;&#xA;You can make it go from 0 to 10 by multiplying the result by 10:&#xD;&#xA;&#xD;&#xA;    rotation *= 10.0;&#xD;&#xA;&#xD;&#xA;Then you plug that into your `glRotated()` call:&#xD;&#xA;&#xD;&#xA;    glRotated(rotation, 0, 1, 0);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17742" PostHistoryTypeId="5" PostId="6357" RevisionGUID="19080b72-4242-41d6-8be9-f1fccd1a2a77" CreationDate="2018-03-03T05:25:14.560" UserId="3003" Comment="Added sine example which is smoother." Text="In order to dissociate the rotation from the CPU speed, you need to use some sort of timing in your function. I recommend passing in a time value of some sort. The easiest thing is to pass in the number of seconds since the app started. How you do that depends on your particular OS, which you didn't specify. &#xD;&#xA;&#xD;&#xA;Once you have a timing constant, you can generate a triangle wave to control the rotation. This formula will oscillate between 0 and 1 over time:&#xD;&#xA;&#xD;&#xA;    double rotation = 2.0 * fabs(fmod(time, 1.0) - 0.5);&#xD;&#xA;&#xD;&#xA;You can make it go from 0 to 10 by multiplying the result by 10:&#xD;&#xA;&#xD;&#xA;    rotation *= 10.0;&#xD;&#xA;&#xD;&#xA;Then you plug that into your `glRotated()` call:&#xD;&#xA;&#xD;&#xA;    glRotated(rotation, 0, 1, 0);&#xD;&#xA;&#xD;&#xA;If you want to make the motion a little smoother, you could replace the triangle wave with a sine wave, like this:&#xD;&#xA;&#xD;&#xA;    double rotation = 0.5 * (sin(time * 2.0 * M_PI + M_PI / 2.0) + 1.0);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17743" PostHistoryTypeId="5" PostId="6353" RevisionGUID="bd64522d-6d92-4a5d-ba27-c9dfdf7ca832" CreationDate="2018-03-03T16:43:57.903" UserId="3003" Comment="Corrected the formulae to be what the poster apparently actually meant" Text="It looks to me like you're resetting the distance calculation at each grid intersection? So every time you march another grid cell you're dividing the light intensity by $gridsize^2$ ? That would explain your observed results, since dividing by $1^2$ equals no change. It won't give you the correct result though, since to get the right attenuation you need to track the *total distance* back to the light source and square that. &#xD;&#xA;&#xD;&#xA;Also note that the attenuation term used in rendering is usually a bit more complicated than just $1/D^2$ - generally it's a quadratic, $1/(aD^2 + bD + c)$. While not physically correct, it's more tunable and easier to get visually pleasing results. In your case, for example, using $1/(D^2 + 1)$ would prevent the edges immediately surrounding the light from being brighter than the light itself." ContentLicense="CC BY-SA 3.0" />
  <row Id="17745" PostHistoryTypeId="5" PostId="5772" RevisionGUID="330686b0-1d90-4904-a3bf-48fa7bc00dcd" CreationDate="2018-03-03T17:39:54.783" UserDisplayName="user7220" Comment="Corrected indents.." Text="I modified my code, and tried to pass a set of integers specifying the face of a cube (top, bottom left...) to the vertex shader in order to draw multiple instances of a cube face.&#xD;&#xA;&#xD;&#xA;I did this by trying to pass them as vertex attributes, but it isn't working as I expected, the value of the int should be between 0 and 5, but it's never a number between 0 and 5, in fact it seems to be much much larger than that.&#xD;&#xA;&#xD;&#xA;This is my current shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926535897932384626433832795&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex&#xD;&#xA;    layout(location = 1) in vec3 norm; //a 3D vertex representing the normal to teh vertex &#xD;&#xA;    layout(location = 2) in vec2 texture_coordinate;&#xD;&#xA;    layout(location = 3) in int face_type;&#xD;&#xA;    &#xD;&#xA;    out vec3 normal; &#xD;&#xA;    out vec3 vertexPos; //projected vertex&#xD;&#xA;    out vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 model = mat4(1); //Position and orientation of the current object&#xD;&#xA;    uniform mat4 view = mat4(1); //Camera orientation and position&#xD;&#xA;    uniform mat4 proj = mat4(1); //the projection parameters (FOV, viewport dimensions)&#xD;&#xA;    &#xD;&#xA;    //Taken from: https://gist.github.com/neilmendoza/4512992&#xD;&#xA;    mat4 rotationMatrix(vec3 axis, float angle)&#xD;&#xA;    {&#xD;&#xA;        axis = normalize(axis);&#xD;&#xA;        float s = sin(angle);&#xD;&#xA;        float c = cos(angle);&#xD;&#xA;        float oc = 1.0 - c;&#xD;&#xA;        &#xD;&#xA;        return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,&#xD;&#xA;                    oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,&#xD;&#xA;                    oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,&#xD;&#xA;                    0.0,                                0.0,                                0.0,                                1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        mat4 rotation = mat4(1);&#xD;&#xA;        switch(face_type)&#xD;&#xA;        {&#xD;&#xA;            case 0:&#xD;&#xA;                rotation = mat4(1);&#xD;&#xA;                break;&#xD;&#xA;            case 1:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), -PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 2:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 3:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), PI);&#xD;&#xA;                break;&#xD;&#xA;            case 4:&#xD;&#xA;                rotation = rotationMatrix(vec3(1,0,0), PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 5:&#xD;&#xA;                rotation = rotationMatrix(vec3(1,0,0), -PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            &#xD;&#xA;            default:&#xD;&#xA;                rotation = mat4(vec4(face_type,0,0,0),&#xD;&#xA;                                vec4(0,1,0,0),&#xD;&#xA;                                vec4(0,0,1,0),&#xD;&#xA;                                vec4(0,0,0,1));&#xD;&#xA;                break;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        /*rotation = mat4(vec4(5,0,0,0),&#xD;&#xA;                        vec4(0,5,0,0),&#xD;&#xA;                        vec4(0,0,5,0),&#xD;&#xA;                        vec4(0,0,0,1));*/&#xD;&#xA;    &#xD;&#xA;        vec4 projection = proj*view*model*rotation*vec4(position, 1.0);&#xD;&#xA;        gl_Position = projection;&#xD;&#xA;    &#xD;&#xA;        normal = vec3(model*vec4(norm,1.0));&#xD;&#xA;        vertexPos = vec3(model*vec4(position, 1.0)); //calculate the transformed pos&#xD;&#xA;        texture_coord = texture_coordinate + vec2(face_type*(1/6.f),0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is how I am passing the face information to the shader:&#xD;&#xA;&#xD;&#xA;    vector&lt;Face&gt; face_types = {Top, Bottom, Left,};&#xD;&#xA;    glEnableVertexAttribArray(3);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, experiment);&#xD;&#xA;    glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, sizeof(Face), (void*)0);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, face_types.size()*sizeof(Face),&#xD;&#xA;        face_types.data(), GL_DYNAMIC_DRAW);&#xD;&#xA;    glVertexAttribDivisor(3, 1);&#xD;&#xA;&#xD;&#xA;Edit: modified the question" ContentLicense="CC BY-SA 3.0" />
  <row Id="17746" PostHistoryTypeId="24" PostId="5772" RevisionGUID="330686b0-1d90-4904-a3bf-48fa7bc00dcd" CreationDate="2018-03-03T17:39:54.783" Comment="Proposed by 7220 approved by -1 edit id of 318" ContentLicense="CC BY-SA 3.0" />
  <row Id="17747" PostHistoryTypeId="5" PostId="5772" RevisionGUID="baeb1bc5-1218-4a30-b0cb-3e5fb2bf0cbb" CreationDate="2018-03-03T17:39:54.783" UserId="2041" Comment="Corrected indents.." Text="I modified my code, and tried to pass a set of integers specifying the face of a cube (top, bottom left...) to the vertex shader in order to draw multiple instances of a cube face.&#xD;&#xA;&#xD;&#xA;I did this by trying to pass them as vertex attributes, but it isn't working as I expected, the value of the int should be between 0 and 5, but it's never a number between 0 and 5, in fact it seems to be much much larger than that.&#xD;&#xA;&#xD;&#xA;This is my current shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926535897932384626433832795&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex&#xD;&#xA;    layout(location = 1) in vec3 norm; //a 3D vertex representing the normal to teh vertex &#xD;&#xA;    layout(location = 2) in vec2 texture_coordinate;&#xD;&#xA;    layout(location = 3) in int face_type;&#xD;&#xA;    &#xD;&#xA;    out vec3 normal; &#xD;&#xA;    out vec3 vertexPos; //projected vertex&#xD;&#xA;    out vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 model = mat4(1); //Position and orientation of the current object&#xD;&#xA;    uniform mat4 view = mat4(1); //Camera orientation and position&#xD;&#xA;    uniform mat4 proj = mat4(1); //the projection parameters (FOV, viewport dimensions)&#xD;&#xA;    &#xD;&#xA;    //Taken from: https://gist.github.com/neilmendoza/4512992&#xD;&#xA;    mat4 rotationMatrix(vec3 axis, float angle)&#xD;&#xA;    {&#xD;&#xA;        axis = normalize(axis);&#xD;&#xA;        float s = sin(angle);&#xD;&#xA;        float c = cos(angle);&#xD;&#xA;        float oc = 1.0 - c;&#xD;&#xA;        &#xD;&#xA;        return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,&#xD;&#xA;                    oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,&#xD;&#xA;                    oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,&#xD;&#xA;                    0.0,                                0.0,                                0.0,                                1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        mat4 rotation = mat4(1);&#xD;&#xA;        switch(face_type)&#xD;&#xA;        {&#xD;&#xA;            case 0:&#xD;&#xA;                rotation = mat4(1);&#xD;&#xA;                break;&#xD;&#xA;            case 1:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), -PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 2:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 3:&#xD;&#xA;                rotation = rotationMatrix(vec3(0,0,1), PI);&#xD;&#xA;                break;&#xD;&#xA;            case 4:&#xD;&#xA;                rotation = rotationMatrix(vec3(1,0,0), PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            case 5:&#xD;&#xA;                rotation = rotationMatrix(vec3(1,0,0), -PI/2.f);&#xD;&#xA;                break;&#xD;&#xA;            &#xD;&#xA;            default:&#xD;&#xA;                rotation = mat4(vec4(face_type,0,0,0),&#xD;&#xA;                                vec4(0,1,0,0),&#xD;&#xA;                                vec4(0,0,1,0),&#xD;&#xA;                                vec4(0,0,0,1));&#xD;&#xA;                break;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        /*rotation = mat4(vec4(5,0,0,0),&#xD;&#xA;                        vec4(0,5,0,0),&#xD;&#xA;                        vec4(0,0,5,0),&#xD;&#xA;                        vec4(0,0,0,1));*/&#xD;&#xA;    &#xD;&#xA;        vec4 projection = proj*view*model*rotation*vec4(position, 1.0);&#xD;&#xA;        gl_Position = projection;&#xD;&#xA;    &#xD;&#xA;        normal = vec3(model*vec4(norm,1.0));&#xD;&#xA;        vertexPos = vec3(model*vec4(position, 1.0)); //calculate the transformed pos&#xD;&#xA;        texture_coord = texture_coordinate + vec2(face_type*(1/6.f),0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is how I am passing the face information to the shader:&#xD;&#xA;&#xD;&#xA;    vector&lt;Face&gt; face_types = {Top, Bottom, Left,};&#xD;&#xA;    glEnableVertexAttribArray(3);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, experiment);&#xD;&#xA;    glVertexAttribPointer(3, 1, GL_INT, GL_FALSE, sizeof(Face), (void*)0);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, face_types.size()*sizeof(Face),&#xD;&#xA;        face_types.data(), GL_DYNAMIC_DRAW);&#xD;&#xA;    glVertexAttribDivisor(3, 1);" ContentLicense="CC BY-SA 3.0" />
  <row Id="17748" PostHistoryTypeId="5" PostId="5843" RevisionGUID="bb04dfb3-6e13-46cf-9692-0be136f28460" CreationDate="2018-03-03T17:40:08.140" UserDisplayName="user7220" Comment="Corrected indents.. Corrected links.." Text="I am following this tutorial: [Understanding Perlin Noise | Blog][1]&#xD;&#xA;&#xD;&#xA;To understand Perlin Noise. In particular, right now I am focusing on the following code section:&#xD;&#xA;&#xD;&#xA;    int xi = (int)x &amp; 255; // Calculate the &quot;unit cube&quot; that the point asked will be located in&#xD;&#xA;    int yi = (int)y &amp; 255; // The left bound is ( |_x_|,|_y_|,|_z_| ) and the right bound is that&#xD;&#xA;    int zi = (int)z &amp; 255; // plus 1.  Next we calculate the location (from 0.0 to 1.0) in that cube.&#xD;&#xA;    double xf = x-(int)x;&#xD;&#xA;    double yf = y-(int)y;&#xD;&#xA;    double zf = z-(int)z;&#xD;&#xA;&#xD;&#xA;If I am correct, the first 3 lines of code are calculating a set of 3 coordinates (xi,yi,zi) that range from 0 to 255 inclusive, as integers. This is, in other words, a 255x255x255 3D grid of unit cubes.&#xD;&#xA;&#xD;&#xA;The next 3 lines are calculating the relative 0-1 coordinates inside of the cube in the grid the point (x,y,z) is mapped to.&#xD;&#xA;&#xD;&#xA;My question is:&#xD;&#xA;&#xD;&#xA;Is there any reason for this number to be 255? Or is this simply a number that was chosen because it made the algorithm faster (smaller grid, less numbers, faster hash lookup, caching...) and could easily be extended to any other integer (theoretically).&#xD;&#xA;&#xD;&#xA;In either case, won't this generate a repetitive pattern?&#xD;&#xA;&#xD;&#xA;What I mean by the second question is: If I have a set of (x,y,z) values that extend to &quot;infinity&quot; at regular intervals (let's say they all change at intervals of 1), won't I start seeing a clearly predictable/repetitive pattern emerge after around 255 steps in a given direction? &#xD;&#xA;&#xD;&#xA;Finally, if a repetitive pattern emerges, how can you create more variation while keeping pseudo randomness?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://flafla2.github.io/2014/08/09/perlinnoise.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17749" PostHistoryTypeId="24" PostId="5843" RevisionGUID="bb04dfb3-6e13-46cf-9692-0be136f28460" CreationDate="2018-03-03T17:40:08.140" Comment="Proposed by 7220 approved by 2041 edit id of 319" ContentLicense="CC BY-SA 3.0" />
  <row Id="17750" PostHistoryTypeId="5" PostId="4726" RevisionGUID="2bec640f-0093-485a-a036-80a5e67a3b9c" CreationDate="2018-03-03T17:40:16.723" UserDisplayName="user7220" Comment="Corrected indents.." Text="I'm writing a function that reads the number of red pixels on the left and right halves of the screen, it makes adjustments while the difference between the number of red pixels falls outside of a threshold. I'm having trouble with the buffers (back and front) because when I finally swap to the front buffer, it dynamically draws all changes I made in the loop meant for the back buffer but I only want the final one drawn to screen. In pseudocode, &#xD;&#xA;&#xD;&#xA;    do {&#xD;&#xA;        draw scene to back buffer&#xD;&#xA;        read number of left, right red pixels&#xD;&#xA;        if (abs(left-right)&gt;threshold) {&#xD;&#xA;            //some function to jitter objects in the scene&#xD;&#xA;        }&#xD;&#xA;        else done=true,&#xD;&#xA;    }while(!done);&#xD;&#xA;    &#xD;&#xA;    //draw to front buffer&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is some C++/OpenGL code:&#xD;&#xA;    &#xD;&#xA;    do {&#xD;&#xA;        glDrawBuffer(GL_BACK_LEFT);&#xD;&#xA;        display(0);&#xD;&#xA;&#xD;&#xA;        glDrawBuffer(GL_BACK_RIGHT);&#xD;&#xA;        display(1);&#xD;&#xA;&#xD;&#xA;        redsleft = 0;&#xD;&#xA;        redsright = 0;&#xD;&#xA;&#xD;&#xA;        glReadBuffer(GL_BACK_LEFT);&#xD;&#xA;        glReadPixels(0, 0, resolution.first, resolution.second, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);&#xD;&#xA;        for (int j = 0; j &lt; resolution.first*resolution.second * 4; j += 4)&#xD;&#xA;        {&#xD;&#xA;            if (frameBuffer[j]&gt;0 &amp;&amp; frameBuffer[j + 1] == 0 &amp;&amp; frameBuffer[j + 2] == 0 &amp;&amp; frameBuffer[j + 3] &gt; 0)&#xD;&#xA;            {&#xD;&#xA;                if (j % 4 == 0 &amp;&amp; i == 0)&#xD;&#xA;                {&#xD;&#xA;                    int redX = (j / 4) % resolution.first;&#xD;&#xA;                    int redY = j / 4 / resolution.first;&#xD;&#xA;&#xD;&#xA;                    if (redX &lt; resolution.first / 2)&#xD;&#xA;                        redsleft++;&#xD;&#xA;                    else&#xD;&#xA;                        redsright++;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        //if above threshold, call function to adjust &#xD;&#xA;        //else done&#xD;&#xA;    } while (!done);&#xD;&#xA;&#xD;&#xA;    glDrawBuffer(GL_BACK_LEFT);&#xD;&#xA;    display(0);&#xD;&#xA;&#xD;&#xA;    glDrawBuffer(GL_BACK_RIGHT);&#xD;&#xA;    display(1);&#xD;&#xA;&#xD;&#xA;    glutSwapBuffers();&#xD;&#xA;    glutPostRedisplay();&#xD;&#xA;&#xD;&#xA;Any ideas?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17751" PostHistoryTypeId="24" PostId="4726" RevisionGUID="2bec640f-0093-485a-a036-80a5e67a3b9c" CreationDate="2018-03-03T17:40:16.723" Comment="Proposed by 7220 approved by 2041 edit id of 317" ContentLicense="CC BY-SA 3.0" />
  <row Id="17752" PostHistoryTypeId="2" PostId="6358" RevisionGUID="f32a1af7-d02b-490b-991d-38b924e5ee01" CreationDate="2018-03-03T18:45:17.280" UserId="8311" Text="My question is oriented towards the generation of depth map using any of the state of the art [depth sensor][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Structured-light_3D_scanner&#xD;&#xA;&#xD;&#xA;However, each of these method required the presence of an 3-D object in front of the sensor. Is it possible the generate a depth map even if a 2-D image is presented to the sensor?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17753" PostHistoryTypeId="1" PostId="6358" RevisionGUID="f32a1af7-d02b-490b-991d-38b924e5ee01" CreationDate="2018-03-03T18:45:17.280" UserId="8311" Text="Creating depth map from a 2-D image?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17754" PostHistoryTypeId="3" PostId="6358" RevisionGUID="f32a1af7-d02b-490b-991d-38b924e5ee01" CreationDate="2018-03-03T18:45:17.280" UserId="8311" Text="|image-processing|camera|depth-map|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17755" PostHistoryTypeId="5" PostId="5516" RevisionGUID="5922e3e9-bf3f-4123-a986-14395890637d" CreationDate="2018-03-03T20:07:34.817" UserDisplayName="user7220" Comment="Corrected links.." Text="You are correct, when they are talking about taking the inverse-transpose they are talking about the 3x3 part of the affine transformation leaving the translation since it doesn't affect the normal vector.&#xD;&#xA;&#xD;&#xA;Check : [Normal / Transforming Normals | Wikipedia][1]&#xD;&#xA;&#xD;&#xA;About how or why is it the inverse transpose, a simple explanation, that is also given in the book &quot;Essential Mathematics for Games&quot; is&#xD;&#xA;&#xD;&#xA;Suppose we have a Point $P$ and a normal vector $n$ both represented by column matrix. Then we know that&#xD;&#xA;$$&#xD;&#xA;n^T P = 0&#xD;&#xA;$$&#xD;&#xA;This is the same as the dot product.&#xD;&#xA;Now if we apply a transformation matrix $M$ to point $P$, we'll have to apply some sort of transformation matrix $Q$ to $n$ also.&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;(Q n)^T M P &amp; = &amp; 0 \\&#xD;&#xA;n^T Q^T M P &amp; = &amp; 0&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;One solution is&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;Q^T M &amp; = &amp; I \\&#xD;&#xA;Q &amp; = &amp; {M^{-1}}^T&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;Hence the inverse transpose. This stands for any sort of transformation matrix $M$ be it scaling, rotation etc. Also for pure rotation matrix, since they are orthogonal, the matrix transforming the normals is the same as that of the vertices. as ${M^T}^T = M$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Normal_(geometry)#Transforming_normals" ContentLicense="CC BY-SA 3.0" />
  <row Id="17756" PostHistoryTypeId="24" PostId="5516" RevisionGUID="5922e3e9-bf3f-4123-a986-14395890637d" CreationDate="2018-03-03T20:07:34.817" Comment="Proposed by 7220 approved by 6046 edit id of 326" ContentLicense="CC BY-SA 3.0" />
  <row Id="17757" PostHistoryTypeId="2" PostId="6359" RevisionGUID="ffb797a9-46ae-4345-98f0-d9a69d23afc0" CreationDate="2018-03-03T22:58:17.557" UserId="7462" Text="I am trying to fetch a given geotery and through (potentially multiple) render passes create a 3D texture that stores the color value of said geometry into an associated texel.&#xD;&#xA;&#xD;&#xA;In other words there is a 3D box that i am trying to color based on the geometry inside of that box.&#xD;&#xA;&#xD;&#xA;Currently I am attempting to do so with the following vertex shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926535897932384626433832795&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex&#xD;&#xA;    layout(location = 1) in vec3 norm; //a 3D vertex representing the normal to the vertex &#xD;&#xA;    layout(location = 2) in vec2 texture_coordinate; // texture coordinates&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 3) buffer instance_buffer&#xD;&#xA;    {&#xD;&#xA;        vec4 cubes_info[];//first 3 values are position of object &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    out vec3 normalized_pos;&#xD;&#xA;    out vec3 normal; &#xD;&#xA;    out vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    uniform float width = 128;&#xD;&#xA;    uniform float depth = 128;&#xD;&#xA;    uniform float height = 128;&#xD;&#xA;    &#xD;&#xA;    uniform float voxel_size = 1;&#xD;&#xA;    uniform vec3 origin = vec3(0,0,0);&#xD;&#xA;    &#xD;&#xA;    uniform float level=0;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        texture_coord = texture_coordinate; &#xD;&#xA;        vec4 pos = (vec4(position, 1.0) + vec4(vec3(cubes_info[gl_InstanceID]),0));&#xD;&#xA;    &#xD;&#xA;        pos-=vec4(origin, 0);&#xD;&#xA;    &#xD;&#xA;        pos.x = (2.f*pos.x-width)/(width);&#xD;&#xA;        pos.y = (2.f*pos.y-depth)/(depth);&#xD;&#xA;        pos.z = (2.f*pos.z-depth)/(height);&#xD;&#xA;    &#xD;&#xA;        gl_Position = pos;&#xD;&#xA;    &#xD;&#xA;        normalized_pos = vec3(pos);&#xD;&#xA;    &#xD;&#xA;        normal = normalize(norm);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the following fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    in vec3 normalized_pos;&#xD;&#xA;    in vec3 normal;//Normal to the vertex&#xD;&#xA;    in vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;//Final color of the pixel&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D text;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        outColor = vec4(0,1,0,1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;Currently the color is ahrd set to green just to test whether I am doing things in the correct fashion.&#xD;&#xA;&#xD;&#xA;But I seem to have failed.&#xD;&#xA;&#xD;&#xA;How exactly would you design a shading program that voxelizes a 3D grid of a space?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17758" PostHistoryTypeId="1" PostId="6359" RevisionGUID="ffb797a9-46ae-4345-98f0-d9a69d23afc0" CreationDate="2018-03-03T22:58:17.557" UserId="7462" Text="How to voxelize geometry using textures and shaders?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17759" PostHistoryTypeId="3" PostId="6359" RevisionGUID="ffb797a9-46ae-4345-98f0-d9a69d23afc0" CreationDate="2018-03-03T22:58:17.557" UserId="7462" Text="|opengl|shader|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17760" PostHistoryTypeId="5" PostId="5678" RevisionGUID="e1e56c02-53af-45d4-a720-cd32de1de5fc" CreationDate="2018-03-04T00:34:05.677" UserDisplayName="user7220" Comment="Corrected links.." Text="I recently finished the base implementation of a DX12 rederer and I started to think in ways of improving the performance. I think that one problem that my implementation has, is memory fragmentation, as I mostly perform &quot;single&quot; allocations for my resources. During run-time some resources are deleted and recreated which I guess will cause even more memory frag. There are quite a few articles online about writing system memory managers but I've never encountered something like that for video memory and GPU resources. &#xD;&#xA;&#xD;&#xA;Could anyone explain the basics of a system like this? &#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I had this link laying around: [Memory Management in Direct3D 12 | Windows Dev Center][1]. That gives some good general information about the topic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/mt613239(v=vs.85).aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="17761" PostHistoryTypeId="24" PostId="5678" RevisionGUID="e1e56c02-53af-45d4-a720-cd32de1de5fc" CreationDate="2018-03-04T00:34:05.677" Comment="Proposed by 7220 approved by 231 edit id of 328" ContentLicense="CC BY-SA 3.0" />
  <row Id="17762" PostHistoryTypeId="5" PostId="5139" RevisionGUID="3913d6d8-bca1-4267-843b-b15fa405ad36" CreationDate="2018-03-04T00:34:55.497" UserDisplayName="user7220" Comment="Corrected indents.." Text="I implemented [dual paraboloid][1] shadows for point lights. The goal was to reduce the number of shadow passes. Also the target is GLES3.0 so no layered rendering is available. The shadows work, and actually the quality is not bad at all.&#xD;&#xA;&#xD;&#xA;There is one issue though. I store both hemisphere shadow maps into a single atlas during the shadow pass. During the lighting pass I sample from that atlas,from the relevant part based on the direction (forward or backward). When the shadow crosses both maps there is a white seam in the middle. I tried to change the filter mode of the FBO texture, also changed wrapping mode, but nothing helps.&#xD;&#xA;&#xD;&#xA;Here is the screenshot:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The point source is the small white sphere at the top and currently it is located so that the shader samples half from each map in the atlas.It results in the white line in the middle of the shadow.&#xD;&#xA;&#xD;&#xA;Here is the code in the light pass:&#xD;&#xA;&#xD;&#xA;    float Shadow(vec3 viewPos,vec3 lightViewPos,vec3 viewNormal,float bias)&#xD;&#xA;    {&#xD;&#xA;        vec3 vPosDP = vec3(u_lightViewMatrix * v_worldPosition);&#xD;&#xA;        float fLength = length(vPosDP);&#xD;&#xA;        vPosDP /= fLength;&#xD;&#xA;        lightViewPos = (u_viewMatrix * vec4(lightViewPos,1.0)).xyz;&#xD;&#xA;        vec3 L = normalize(lightViewPos - viewPos);&#xD;&#xA;        float NdotL = saturate(dot(L, viewNormal));&#xD;&#xA;        bias =  max(0.01 *(1.0 - NdotL), bias);&#xD;&#xA;        float fDPDepth;&#xD;&#xA;        float fSceneDepth;&#xD;&#xA;&#xD;&#xA;        if(vPosDP.z &gt;=  0.0)&#xD;&#xA;        {&#xD;&#xA;            vec2 vTexFront;&#xD;&#xA;            vTexFront.x =  ((vPosDP.x /  (1.0 + vPosDP.z))  * 0.25  + 0.25 );&#xD;&#xA;            vTexFront.y =  ((vPosDP.y /  (1.0 + vPosDP.z))  * 0.5  + 0.5  );&#xD;&#xA;            fSceneDepth = (fLength - u_nearFarPlanes.x) / (u_nearFarPlanes.y - u_nearFarPlanes.x);&#xD;&#xA;            fDPDepth =   texture(u_shadowMap, vec3(vTexFront,fSceneDepth - bias));&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            // for the back the z has to be inverted        &#xD;&#xA;            vec2 vTexBack;&#xD;&#xA;            vTexBack.x =  ((vPosDP.x /  (1.0 - vPosDP.z)) * 0.25  + 0.75);&#xD;&#xA;            vTexBack.y =  ((vPosDP.y /  (1.0 - vPosDP.z)) * 0.5  + 0.5);&#xD;&#xA;&#xD;&#xA;            fSceneDepth = (fLength - u_nearFarPlanes.x) / (u_nearFarPlanes.y - u_nearFarPlanes.x);&#xD;&#xA;            fDPDepth =   texture(u_shadowMap, vec3(vTexBack,fSceneDepth - bias));&#xD;&#xA;        }&#xD;&#xA;        return  fDPDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I read that this shadow technique has negative effect when low res geometry is involved. Is my issue related to that effect?&#xD;&#xA;&#xD;&#xA;  [1]: http://advancedgraphics.marries.nl/presentationslides/10_dual-paraboloid_shadow_mapping.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/KPiIN.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17763" PostHistoryTypeId="24" PostId="5139" RevisionGUID="3913d6d8-bca1-4267-843b-b15fa405ad36" CreationDate="2018-03-04T00:34:55.497" Comment="Proposed by 7220 approved by 231 edit id of 321" ContentLicense="CC BY-SA 3.0" />
  <row Id="17764" PostHistoryTypeId="5" PostId="5901" RevisionGUID="95ad05b8-a0c7-4352-a09b-24922510f7ac" CreationDate="2018-03-04T00:36:31.087" UserDisplayName="user7220" Comment="Corrected links.." Text="I stumbled on this blog:&#xD;&#xA;[Diary of a Graphics Programmer | Blogger][1]&#xD;&#xA;&#xD;&#xA;Given what tricks can be done in compute shader (that are specific only to compute shaders) I was curious if parallel reduction on compute shader was faster than on pixel shader. I e-mail'ed the author, Wolf Engel, to ask if he had tried pixel shader. He replied that yes and back when he wrote the blog post the compute shader version was substantially faster than the pixel shader version. He also added that today the differences are even bigger. So apparently there are cases where using compute shader can be of great advantage.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://diaryofagraphicsprogrammer.blogspot.com/2014/03/compute-shader-optimizations-for-amd.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17765" PostHistoryTypeId="24" PostId="5901" RevisionGUID="95ad05b8-a0c7-4352-a09b-24922510f7ac" CreationDate="2018-03-04T00:36:31.087" Comment="Proposed by 7220 approved by -1 edit id of 322" ContentLicense="CC BY-SA 3.0" />
  <row Id="17766" PostHistoryTypeId="5" PostId="5901" RevisionGUID="ca0abd6d-fc77-4600-895d-f0ff02691c6a" CreationDate="2018-03-04T00:36:31.087" UserId="231" Comment="Corrected links.." Text="I stumbled on this blog:&#xD;&#xA;[Compute Shader Optimizations for AMD][1]&#xD;&#xA;&#xD;&#xA;Given what tricks can be done in compute shader (that are specific only to compute shaders) I was curious if parallel reduction on compute shader was faster than on pixel shader. I e-mail'ed the author, Wolf Engel, to ask if he had tried pixel shader. He replied that yes and back when he wrote the blog post the compute shader version was substantially faster than the pixel shader version. He also added that today the differences are even bigger. So apparently there are cases where using compute shader can be of great advantage.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://diaryofagraphicsprogrammer.blogspot.com/2014/03/compute-shader-optimizations-for-amd.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17767" PostHistoryTypeId="5" PostId="4510" RevisionGUID="e9ff6033-fd40-4ccc-a5aa-2b3c0abc1991" CreationDate="2018-03-04T00:38:19.650" UserDisplayName="user7220" Comment="Corrected indents.." Text="I have trouble understanding the following Javascript code.&#xD;&#xA;&#xD;&#xA;It calculates, given a mesh described by its vertices `vs` and indices `ind`, the normals for each vertex. The mesh faces are a triangle list, and are oriented counterclockwise.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: javascript --&gt;&#xD;&#xA;&#xD;&#xA;    utilsObject.prototype.calculateNormals = function(vs, ind) {&#xD;&#xA;        var x = 0;&#xD;&#xA;        var y = 1;&#xD;&#xA;        var z = 2;&#xD;&#xA;        var ns = [];&#xD;&#xA;        // for each vertex, initialize normal x, normal y, normal z&#xD;&#xA;        for (var i = 0; i &lt; vs.length; i++) {&#xD;&#xA;            ns[i] = 0.0;&#xD;&#xA;        }&#xD;&#xA;        // we work on triads of vertices to calculate normals so&#xD;&#xA;        // i = i+3 (i = indices index)&#xD;&#xA;        for (var i = 0; i &lt; ind.length; i = i + 3) {&#xD;&#xA;            var v1 = [];&#xD;&#xA;            var v2 = [];&#xD;&#xA;            var normal = [];&#xD;&#xA;            // p1 - p0&#xD;&#xA;            v1[x] = vs[3 * ind[i + 1] + x] - vs[3 * ind[i] + x];&#xD;&#xA;            v1[y] = vs[3 * ind[i + 1] + y] - vs[3 * ind[i] + y];&#xD;&#xA;            v1[z] = vs[3 * ind[i + 1] + z] - vs[3 * ind[i] + z];&#xD;&#xA;            // p0 - p1&#xD;&#xA;            v2[x] = vs[3 * ind[i + 2] + x] - vs[3 * ind[i + 1] + x];&#xD;&#xA;            v2[y] = vs[3 * ind[i + 2] + y] - vs[3 * ind[i + 1] + y];&#xD;&#xA;            v2[z] = vs[3 * ind[i + 2] + z] - vs[3 * ind[i + 1] + z];&#xD;&#xA;            // cross product by Sarrus Rule&#xD;&#xA;            normal[x] = v1[y] * v2[z] - v1[z] * v2[y];&#xD;&#xA;            normal[y] = v1[z] * v2[x] - v1[x] * v2[z];&#xD;&#xA;            normal[z] = v1[x] * v2[y] - v1[y] * v2[x];&#xD;&#xA;            // update the normals of that triangle: sum of vectors&#xD;&#xA;            for (j = 0; j &lt; 3; j++) {&#xD;&#xA;                ns[3 * ind[i + j] + x] = ns[3 * ind[i + j] + x] + normal[x];&#xD;&#xA;                ns[3 * ind[i + j] + y] = ns[3 * ind[i + j] + y] + normal[y];&#xD;&#xA;                ns[3 * ind[i + j] + z] = ns[3 * ind[i + j] + z] + normal[z];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;How does this function work? For example, could you explain the use of indices in the instruction:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: javascript --&gt;&#xD;&#xA;&#xD;&#xA;    v1[x] = vs[3*ind[i+1]+x] - vs[3*ind[i]+x];&#xD;&#xA;&#xD;&#xA;Rather than a high-level explanation, I am interested in the logic of the implementation details." ContentLicense="CC BY-SA 3.0" />
  <row Id="17768" PostHistoryTypeId="24" PostId="4510" RevisionGUID="e9ff6033-fd40-4ccc-a5aa-2b3c0abc1991" CreationDate="2018-03-04T00:38:19.650" Comment="Proposed by 7220 approved by 231 edit id of 327" ContentLicense="CC BY-SA 3.0" />
  <row Id="17769" PostHistoryTypeId="5" PostId="6009" RevisionGUID="afc0bfb0-dc6f-490d-a63e-a5f87ac752b1" CreationDate="2018-03-04T00:38:38.313" UserDisplayName="user7220" Comment="Corrected indents.." Text="I convert RGB input to YUV 420 semi-planar output using compute shader.Luma plane is straightforward as it maps 1:1 with RGB dimensions. As we know, [NV12 packs Cb][1] and Cr into one plane, which means the CbCr values must be calculating from downsampled (x4) source.And this is the part I am not completely sure I am doing right. I currently try subsampling with simple bileanar filtering.And it 'almost' looks right.I uses t[his article][2] as reference.It is possible that my code is 100% correct and the aliasing stems from compression losness. &#xD;&#xA;&#xD;&#xA;Here is my part of shader code that samples from RGB texture and writes U and V values:&#xD;&#xA;&#xD;&#xA;    ivec2 itexSize =textureSize(rbga_tex,0);&#xD;&#xA;    vec2 texSize =  vec2(itexSize);&#xD;&#xA;    vec2 texelSize = 1.0 / (texSize / 2.0);&#xD;&#xA;    vec2 pixel = uv * texSize + 0.5;&#xD;&#xA;    pixel = (floor(pixel) / texSize) - vec2(texelSize/2.0);&#xD;&#xA;&#xD;&#xA;    //bilinear filtering:&#xD;&#xA;    float sc = 4.0;&#xD;&#xA;    vec3 ts = texture(rbga_tex,pixel).rgb * 0.25; // center&#xD;&#xA;    vec3 tr = texture(rbga_tex,pixel + vec2(texelSize.x * sc, 0.0)).rgb  * 0.25;&#xD;&#xA;    vec3 bl = texture(rbga_tex,pixel + vec2(0.0, texelSize.y * sc)).rgb * 0.25;&#xD;&#xA;    vec3 br = texture(rbga_tex,pixel + vec2(texelSize.x,texelSize.y) * sc).rgb * 0.25;&#xD;&#xA;&#xD;&#xA;    vec3 tex1 = (ts + tr + bl + br) ;&#xD;&#xA;    &#xD;&#xA;    // calculate and write U...&#xD;&#xA;&#xD;&#xA;    // calculate and write V...&#xD;&#xA;&#xD;&#xA;Here is the original rgb image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And here is the snapshot of the video frame after the conversion:&#xD;&#xA;&#xD;&#xA; [![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;So here are my questions:&#xD;&#xA;&#xD;&#xA;a)I would like to understand if there is something I am doing wrong, and if possible to get a concise explanation on how subsampling should be done when converting from rbg to yuv420 color space. &#xD;&#xA;&#xD;&#xA;b)If this result is correct, are there ways to get smoother effect while keeping overall sharpness?I understand that using bicubic filter we can get smoother visuals but at cost of image sharpness.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd206750(v=vs.85).aspx&#xD;&#xA;  [2]: https://blog.demofox.org/2015/08/15/resizing-images-with-bicubic-interpolation/&#xD;&#xA;  [3]: https://i.stack.imgur.com/lQ7Og.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/8lm8a.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17770" PostHistoryTypeId="24" PostId="6009" RevisionGUID="afc0bfb0-dc6f-490d-a63e-a5f87ac752b1" CreationDate="2018-03-04T00:38:38.313" Comment="Proposed by 7220 approved by 231 edit id of 320" ContentLicense="CC BY-SA 3.0" />
  <row Id="17771" PostHistoryTypeId="5" PostId="5301" RevisionGUID="23c59428-2b6a-4a29-94fb-d533e3c8a76e" CreationDate="2018-03-04T00:38:57.383" UserDisplayName="user7220" Comment="Corrected indents.." Text="I'm using OpenGL's stencil test to carve out a semicircular hole in a transition frustum with a cylinder oriented perpendicularly. However as one can see below, while this objective is achieved, the cylinder is still visible through the frustum which shouldn't be the case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&lt;p&gt;&#xD;&#xA;&#xD;&#xA;I'm using the following code fragment that I found at&#xD;&#xA;https://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal&#xD;&#xA;&#xD;&#xA;    glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    glEnable(GL_STENCIL_TEST);&#xD;&#xA;    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);&#xD;&#xA;    glDepthMask(GL_FALSE);&#xD;&#xA;    glStencilFunc(GL_NEVER, 1, 0xFF);&#xD;&#xA;    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);  // draw 1s on test fail (always)&#xD;&#xA;&#xD;&#xA;    // draw stencil pattern&#xD;&#xA;    glStencilMask(0xFF);&#xD;&#xA;    glClear(GL_STENCIL_BUFFER_BIT);  // needs mask=0xFF&#xD;&#xA;    DRAW_CYLINDER ();&#xD;&#xA;&#xD;&#xA;    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);&#xD;&#xA;    glDepthMask(GL_TRUE);&#xD;&#xA;    glStencilMask(0x00);&#xD;&#xA;    // draw where stencil's value is 0&#xD;&#xA;    glStencilFunc(GL_EQUAL, 0, 0xFF);&#xD;&#xA;    /* (nothing to draw) */&#xD;&#xA;    // draw only where stencil's value is 1&#xD;&#xA;    glStencilFunc(GL_EQUAL, 1, 0xFF);&#xD;&#xA;&#xD;&#xA;    DRAW_FRUSTUM();&#xD;&#xA;&#xD;&#xA;    glDisable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;Moreover I've found that the results are insensitive to the parameters of the **glStencilOp**  and **DepthMask** commands. &#xD;&#xA;&#xD;&#xA;I seem to vaguely remember from several years ag that a multi-pass rendering may be required. If so, could someone point me to how to accomplish this with the proper set of command parameters?&#xD;&#xA;&#xD;&#xA;thanks in advance.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;This is an example of what I'm expecting - The cylinder should cut a hole through the frustum. I've rendered it here by trimming the black cylinder within the frustum so that it just just out past the frustum surface.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pmWBD.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/vcxON.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17772" PostHistoryTypeId="24" PostId="5301" RevisionGUID="23c59428-2b6a-4a29-94fb-d533e3c8a76e" CreationDate="2018-03-04T00:38:57.383" Comment="Proposed by 7220 approved by 231 edit id of 325" ContentLicense="CC BY-SA 3.0" />
  <row Id="17773" PostHistoryTypeId="5" PostId="4981" RevisionGUID="12843730-5ce9-4370-8483-060268567cc2" CreationDate="2018-03-04T00:39:07.157" UserDisplayName="user7220" Comment="Corrected links.." Text="Take a look at Qt.  Qt is built on opengl and therefore integrates with it pretty easily.&#xD;&#xA;&#xD;&#xA;[Hello GL2 Example | Qt Documentation][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://doc.qt.io/qt-5/qtopengl-hellogl2-example.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17774" PostHistoryTypeId="24" PostId="4981" RevisionGUID="12843730-5ce9-4370-8483-060268567cc2" CreationDate="2018-03-04T00:39:07.157" Comment="Proposed by 7220 approved by 231 edit id of 323" ContentLicense="CC BY-SA 3.0" />
  <row Id="17775" PostHistoryTypeId="5" PostId="4936" RevisionGUID="988eefc2-23ac-4cc3-b4c9-1d402834c42c" CreationDate="2018-03-04T00:39:13.117" UserDisplayName="user7220" Comment="Corrected indents.." Text="I have got a texture ID and would like to retrieve its data. The data should be stored in a `BufferedImage` for future use. I am using the LWJGL library in Java, so if there are some library-specific shortcuts I'd like to use them.&#xD;&#xA;&#xD;&#xA;My naive approach is to first fill a buffer with the image data and then pass it to the image.&#xD;&#xA;&#xD;&#xA;    int id = ...;&#xD;&#xA;    IntBuffer buff = BufferUtils.createIntBuffer(1024*512*4);&#xD;&#xA;    GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);&#xD;&#xA;    System.out.println(buff.remaining());&#xD;&#xA;    GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, buff);&#xD;&#xA;    System.out.println(buff.remaining());&#xD;&#xA;    buff.flip();&#xD;&#xA;    buff.rewind();&#xD;&#xA;    System.out.println(buff.remaining());&#xD;&#xA;    // Somehow create a BufferedImage from buff here&#xD;&#xA;&#xD;&#xA;I don't know why, but the first and to `buff.remaining()` return the same value, indicating that nothing has been written which should not be the case." ContentLicense="CC BY-SA 3.0" />
  <row Id="17776" PostHistoryTypeId="24" PostId="4936" RevisionGUID="988eefc2-23ac-4cc3-b4c9-1d402834c42c" CreationDate="2018-03-04T00:39:13.117" Comment="Proposed by 7220 approved by 231 edit id of 324" ContentLicense="CC BY-SA 3.0" />
  <row Id="17778" PostHistoryTypeId="2" PostId="6360" RevisionGUID="3842fee5-711b-41e2-b58b-c45b9d264447" CreationDate="2018-03-04T04:31:04.867" UserId="7000" Text="The SuperBible [mentions glTextureStorageSubImage2D][1] however a [Google search][2] currently shows no other mention of this function and I can not find any prototype or signature anywhere.&#xD;&#xA;&#xD;&#xA;Does this call actually exist and if so, what are its parameters?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com/books?id=Nwo0CgAAQBAJ&amp;pg=PT981&amp;lpg=PT981&amp;dq=gltexturestoragesubimage2d&amp;source=bl&amp;ots=LpPMWjKtq8&amp;sig=YrK4Hatro5CFcAstr5MSo34C04E&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwj6itGQ59HZAhVE5mMKHaPxCloQ6AEIJzAA&#xD;&#xA;  [2]: https://www.google.com/search?q=gltexturestoragesubimage2d&amp;oq=gltexturestoragesubimage&amp;aqs=chrome.0.69i59j69i57.3359j0j4&amp;sourceid=chrome&amp;ie=UTF-8" ContentLicense="CC BY-SA 3.0" />
  <row Id="17779" PostHistoryTypeId="1" PostId="6360" RevisionGUID="3842fee5-711b-41e2-b58b-c45b9d264447" CreationDate="2018-03-04T04:31:04.867" UserId="7000" Text="Does glTextureStorageSubImage2D exit?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17780" PostHistoryTypeId="3" PostId="6360" RevisionGUID="3842fee5-711b-41e2-b58b-c45b9d264447" CreationDate="2018-03-04T04:31:04.867" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17781" PostHistoryTypeId="5" PostId="6360" RevisionGUID="62663a94-a80b-4f04-8e3b-ef77e2c6ddf4" CreationDate="2018-03-04T05:25:29.133" UserId="48" Comment="typo" Text="The OpenGL SuperBible [mentions glTextureStorageSubImage2D][1]; however, a [Google search][2] currently shows no other mention of this function and I can not find any prototype or signature anywhere.&#xD;&#xA;&#xD;&#xA;Does this call actually exist and if so, what are its parameters?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com/books?id=Nwo0CgAAQBAJ&amp;pg=PT981&amp;lpg=PT981&amp;dq=gltexturestoragesubimage2d&amp;source=bl&amp;ots=LpPMWjKtq8&amp;sig=YrK4Hatro5CFcAstr5MSo34C04E&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwj6itGQ59HZAhVE5mMKHaPxCloQ6AEIJzAA&#xD;&#xA;  [2]: https://www.google.com/search?q=gltexturestoragesubimage2d&amp;oq=gltexturestoragesubimage&amp;aqs=chrome.0.69i59j69i57.3359j0j4&amp;sourceid=chrome&amp;ie=UTF-8" ContentLicense="CC BY-SA 3.0" />
  <row Id="17782" PostHistoryTypeId="4" PostId="6360" RevisionGUID="62663a94-a80b-4f04-8e3b-ef77e2c6ddf4" CreationDate="2018-03-04T05:25:29.133" UserId="48" Comment="typo" Text="Does glTextureStorageSubImage2D exist?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17786" PostHistoryTypeId="2" PostId="6362" RevisionGUID="656444ba-9d6d-4839-b72b-17ec0600b917" CreationDate="2018-03-04T06:40:23.607" UserId="3003" Text="No, it's not. The way many of the 3D sensors work is by projecting an infrared pattern onto the surface and measuring how it distorts. But with a 2D image, the pattern will simply be projected onto the flat 2D image, not onto the objects in the scene. So the 3D sensor will only sense a flat card.&#xD;&#xA;&#xD;&#xA;Other methods work by combining 2 images taken with different cameras at different angles. This will have the same result as above. The 2D photo will be interpreted as a 2D surface by the combination of the 2 cameras.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17787" PostHistoryTypeId="5" PostId="5538" RevisionGUID="ff7cd138-ef49-4eb2-b50a-f58302f5d59e" CreationDate="2018-03-04T07:02:39.423" UserDisplayName="user7220" Comment="deleted 657 characters in body" Text="I have asked this question on [ru.stackoverflow.com][1] and have no valid answers.&#xD;&#xA;&#xD;&#xA;Specification:&#xD;&#xA;&#xD;&#xA;1. [Coordinate system][2]&#xD;&#xA;2. Cube spins around its center on all three axes.&#xD;&#xA;3. Turn angle is not known previously.&#xD;&#xA;4. Parallel projection calculated by:&#xD;&#xA;&gt; x`` = x;&#xD;&#xA;&gt;&#xD;&#xA;&gt; y`` = y + z / 4;&#xD;&#xA;5. Per unit of time only 3 sides, closest to the projection pane, are visible.&#xD;&#xA;&#xD;&#xA;Question:&#xD;&#xA;&#xD;&#xA;**How to determine which are the closest sides?**&#xD;&#xA;&#xD;&#xA;I'am going this way: take pairs of sides left and right, front and back, top and bottom, then determine closest and farthest points in (Z) axis, determine the equation of a line, take second farthest point in (Z) axis, and substitute into this equation - so determine the inclination of the side. Based on this choose which side is closer.&#xD;&#xA;&#xD;&#xA;This code don't work:&#xD;&#xA;&#xD;&#xA;&lt;!-- begin snippet: js hide: true console: true babel: false --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;    // Получаем параллельную проекцию кубика на плоскость экрана&#xD;&#xA;    function getParallelProjection(arr) {&#xD;&#xA;&#xD;&#xA;    var i, j, k;&#xD;&#xA;&#xD;&#xA;    var arr_new = [];&#xD;&#xA;&#xD;&#xA;    // Попарно работаем с гранями&#xD;&#xA;    // Левая и правая&#xD;&#xA;    arr_new[0] = getSideParallelProjection(arr[0], arr[1], arr[6]);&#xD;&#xA;    // Задняя и передняя&#xD;&#xA;    arr_new[1] = getSideParallelProjection(arr[2], arr[3], arr[6]);&#xD;&#xA;    // Верхняя и нижняя&#xD;&#xA;    arr_new[2] = getSideParallelProjection(arr[4], arr[5], arr[6]);&#xD;&#xA;&#xD;&#xA;    return arr_new;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Параллельная проекция грани&#xD;&#xA;    function getSideParallelProjection(side1, side2, cubeCenter) {&#xD;&#xA;&#xD;&#xA;        // Сначала выясним какая пара нам попалась&#xD;&#xA;        var centralProjection1 = getPointParallelProjection(side1[4]);&#xD;&#xA;        var centralProjection2 = getPointParallelProjection(side2[4]);&#xD;&#xA;&#xD;&#xA;        var coordinate = {&#xD;&#xA;            x:Math.abs(side1[4].x - side2[4].x),&#xD;&#xA;            y:Math.abs(side1[4].y - side2[4].y),&#xD;&#xA;            z:Math.abs(side1[4].z - side2[4].z)};&#xD;&#xA;&#xD;&#xA;        var i;&#xD;&#xA;&#xD;&#xA;        // Найдем дальнюю (1) и ближнюю (2) от экрана точки&#xD;&#xA;        // по оси (Z) и посчитаем их проекции&#xD;&#xA;        var point1 = {z:10000},&#xD;&#xA;        point2 = {z:-10000},&#xD;&#xA;        point3 = {z:10000};&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 4; i++) {&#xD;&#xA;            if (point1.z &gt; side1[i].z) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point1.z == side1[i].z&#xD;&#xA;                &amp;&amp; point1.x &gt; side1[i].x) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point1.z == side1[i].z&#xD;&#xA;                &amp;&amp; point1.x == side1[i].x&#xD;&#xA;                &amp;&amp; point1.y &lt; side1[i].y) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z &lt; side1[i].z) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z == side1[i].z&#xD;&#xA;                &amp;&amp; point2.x &lt; side1[i].x) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z == side1[i].z&#xD;&#xA;                &amp;&amp; point2.x == side1[i].x&#xD;&#xA;                &amp;&amp; point2.y &gt; side1[i].y) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 4; i++) {&#xD;&#xA;            if (point3.z &gt; side1[i].z&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point3.z == side1[i].z&#xD;&#xA;                &amp;&amp; point3.x &gt; side1[i].x&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point3.z == side1[i].z&#xD;&#xA;                &amp;&amp; point3.x == side1[i].x&#xD;&#xA;                &amp;&amp; point3.y &lt; side1[i].y&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                      - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;        var projection = [];&#xD;&#xA;&#xD;&#xA;        // (X) Правая и левая грани&#xD;&#xA;        if (coordinate.x &gt; coordinate.y &amp;&amp; coordinate.x &gt; coordinate.z) {&#xD;&#xA;&#xD;&#xA;            point1 = getPointParallelProjection(point1);&#xD;&#xA;            point2 = getPointParallelProjection(point2);&#xD;&#xA;            point3 = getPointParallelProjection(point3);&#xD;&#xA;&#xD;&#xA;            var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                          - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;&#xD;&#xA;            var selected;&#xD;&#xA;&#xD;&#xA;            if (point1.x &gt;= point2.x) {&#xD;&#xA;                if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            } else {&#xD;&#xA;                if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (selected.length &lt; 6) {&#xD;&#xA;                for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                    projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                }&#xD;&#xA;                projection[4] = 'rgb(200,200,0)';&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // (Z) Передняя и задняя грани&#xD;&#xA;        else if (coordinate.z &gt; coordinate.x &amp;&amp; coordinate.z &gt; coordinate.y) {&#xD;&#xA;&#xD;&#xA;            var selected;&#xD;&#xA;&#xD;&#xA;            if (point1.x &gt;= point2.x &amp;&amp; direction &lt; 0) {&#xD;&#xA;                if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            } else {&#xD;&#xA;                if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (selected.length &lt; 6) {&#xD;&#xA;                for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                    projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                }&#xD;&#xA;                projection[4] = 'rgb(200,0,0)';&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // (Y) Верхняя и нижняя грани&#xD;&#xA;        else {&#xD;&#xA;&#xD;&#xA;            var selected;&#xD;&#xA;&#xD;&#xA;            if (point1.y &lt;= point2.y) {&#xD;&#xA;                if (centralProjection1.y &lt;= centralProjection2.y) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            } else {&#xD;&#xA;                if (centralProjection1.y &gt;= centralProjection2.y) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (selected.length &lt; 6) {&#xD;&#xA;                for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                    projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                }&#xD;&#xA;                projection[4] = 'rgb(0,0,0)';&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return projection;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Параллельная проекция точки&#xD;&#xA;    function getPointParallelProjection(point) {&#xD;&#xA;    return {&#xD;&#xA;        x:point.x,&#xD;&#xA;        y:point.y + point.z / 4};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;canvas id=&quot;animation&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&#xD;&#xA;        &lt;p&gt;Your browser does not support Canvas&lt;/p&gt;&#xD;&#xA;    &lt;/canvas&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- end snippet --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://ru.stackoverflow.com/questions/705286/%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D1%82%D0%BE%D1%80%D0%BE%D0%BD-%D0%BA%D1%83%D0%B1%D0%B0-%D0%BE%D1%82-%D0%BF%D0%BB%D0%BE%D1%81%D0%BA%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8&#xD;&#xA;  [2]: https://i.stack.imgur.com/bKXyI.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17794" PostHistoryTypeId="2" PostId="6365" RevisionGUID="18de05aa-bdae-45ba-8b09-1527d1f9baee" CreationDate="2018-03-04T18:29:47.143" UserId="8317" Text="I am a new lever of computer graphics. I'm trying to understand a code I found online and I got stuck in the following formula:&#xD;&#xA;&#xD;&#xA;    topLeft = [-tan(vfov/2)*(output_width/output_height), -tan(vfov/2), 1];&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Source][1]&#xD;&#xA;&#xD;&#xA;looking on the internet I found that the formula is that of the Perspective Matrix. However the formula of the code has:&#xD;&#xA;&#xD;&#xA;`tan(vfov/2)*(output_width/output_height)` instead of&#xD;&#xA;&#xD;&#xA;    1 / tan(vfov/2)*(output_width/output_height)&#xD;&#xA;&#xD;&#xA;Here is the Perspective Matrix I founded online. &#xD;&#xA;&#xD;&#xA;Can you explain to me why I have inverse values?&#xD;&#xA;What does it mean?&#xD;&#xA;Thank you so much&#xD;&#xA;&#xD;&#xA;[![Perspective Matrix][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/rayryeng/equi2cubic/blob/master/equi2cubic.m&#xD;&#xA;  [2]: https://i.stack.imgur.com/C9PST.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17795" PostHistoryTypeId="1" PostId="6365" RevisionGUID="18de05aa-bdae-45ba-8b09-1527d1f9baee" CreationDate="2018-03-04T18:29:47.143" UserId="8317" Text="Inverse value in a Perspective Matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="17796" PostHistoryTypeId="3" PostId="6365" RevisionGUID="18de05aa-bdae-45ba-8b09-1527d1f9baee" CreationDate="2018-03-04T18:29:47.143" UserId="8317" Text="|c++|matrix|perspective|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17797" PostHistoryTypeId="5" PostId="4312" RevisionGUID="b3e39c35-8009-4634-b706-c69ea06c398e" CreationDate="2018-03-04T18:35:42.963" UserDisplayName="user7220" Comment="Corrected links.." Text="The XYZ and xyY models are extremely useful for certain operations such as manipulating RGB colour spaces to another RGB encoded colour space.&#xD;&#xA;&#xD;&#xA;However, XYZ and xyY fail quite quickly in other contexts. For example, consider MacAdams ellipses that describe noticeable differences on the linear xyY scale. You could in fact apply a nonlinear, perceptually uniform transform to the xyY values and you'd likely end up closer to what you are hoping for in your circular interface element.&#xD;&#xA;&#xD;&#xA;With that being said, there are needs for models that extend and build upon xyY / XYZ to tackle the psychophysical aspect of colour for evaluating such things as &quot;colourfulness&quot;. This enters into the domain of *Colour Appearance Models*, which are capable of accurately modelling and predicting various issues surrounding brightness (luminance), lightness, colorfulness, chroma, saturation, and hue. To achieve what you are seeking, you would need to transform your data into a colour appearance model such as CIECAM02.&#xD;&#xA;&#xD;&#xA;The problems cited in the other solution are in fact solved by colour appearance models such as the CIECAM02 model, including psychophysical effects that manifest as optical illusions.&#xD;&#xA;&#xD;&#xA;- [Color appearance model | Wikipedia][1]&#xD;&#xA;- [Color Appearance Models | Mark Fairchild Blog][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_appearance_model&#xD;&#xA;  [2]: http://rit-mcsl.org/fairchild/CAM.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17798" PostHistoryTypeId="24" PostId="4312" RevisionGUID="b3e39c35-8009-4634-b706-c69ea06c398e" CreationDate="2018-03-04T18:35:42.963" Comment="Proposed by 7220 approved by 5556 edit id of 335" ContentLicense="CC BY-SA 3.0" />
  <row Id="17802" PostHistoryTypeId="5" PostId="4959" RevisionGUID="f5376771-65e5-4f25-9e08-f7b2bb603fbc" CreationDate="2018-03-04T19:54:31.750" UserDisplayName="user7220" Comment="Corrected links.." Text="Problem X: I need to provide &quot;compensation&quot; streams for attributes that are not plugged by the mesh data, but the shader requires them.&#xD;&#xA;(In d3d not matching the input layout is a hard error)&#xD;&#xA;&#xD;&#xA;Solution Y: In D3D I've created a 16 bytes buffer initialized with some default color (when the missing semantic is color, let's take this as my typical use case) and specified a stride of zero so that one element is repeated whatever the index in the index buffer, and this way I don't need to clog VRAM with the biggest buffer that's necessary to cover all objects. This works in D3D.&#xD;&#xA;&#xD;&#xA;But looking at [glVertexAttribPointer][1] I see that the API is eating away my stride and makes it automatic when I specify zero.&#xD;&#xA;&#xD;&#xA;Any workaround ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glVertexAttribPointer.xml" ContentLicense="CC BY-SA 3.0" />
  <row Id="17803" PostHistoryTypeId="24" PostId="4959" RevisionGUID="f5376771-65e5-4f25-9e08-f7b2bb603fbc" CreationDate="2018-03-04T19:54:31.750" Comment="Proposed by 7220 approved by 209, 2041 edit id of 336" ContentLicense="CC BY-SA 3.0" />
  <row Id="17804" PostHistoryTypeId="5" PostId="5957" RevisionGUID="8f40d48b-ee97-4281-974f-c083db9606e8" CreationDate="2018-03-04T19:55:01.770" UserDisplayName="user7220" Comment="Corrected indents.." Text="I am trying to apply sinc interpolation on [this data set][1]. The patches in the left image is a snapshot of AutoCAD 3d faces. Lux values are calculated for centre of each patch that are in 0.3m x 0.3m dimension.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The middle is a bitmap image of the above data set. Applying below sinc interpolation method results in the right side image. I was expecting to get smooth gradient in the colours but am not sure if the sinc function is applied correctly.&#xD;&#xA;&#xD;&#xA;Here is the sinc interpolation method&#xD;&#xA;&#xD;&#xA;    public ImageFilm ConvolveWithSinc(ImageFilm fs, float Ts)&#xD;&#xA;    {&#xD;&#xA;        float Ws = 1 / Ts;&#xD;&#xA;        int N = fs.Width;&#xD;&#xA;        int M = fs.Height;&#xD;&#xA;        ImageFilm fy = new ImageFilm(N, M);&#xD;&#xA;        Vector zero = Vector.ZERO;&#xD;&#xA;        for (int x = 0; x &lt; N; x++)&#xD;&#xA;        {&#xD;&#xA;            for (int y = 0; y &lt; M; y++)&#xD;&#xA;            {&#xD;&#xA;                LightVector sum = LightVector.ZERO;&#xD;&#xA;                double sincSum = 0;&#xD;&#xA;                for (int n = 0; n &lt; fs.Width; n++)//= (int)Ts&#xD;&#xA;                {&#xD;&#xA;                    for (int m = 0; m &lt; fs.Height; m++)//= (int)Ts&#xD;&#xA;                    {&#xD;&#xA;                        double sinc = (Helper.Sinc(Ws * (x - n)) *&#xD;&#xA;                            Helper.Sinc(Ws * (y - m)));&#xD;&#xA;&#xD;&#xA;                        sincSum += sinc;&#xD;&#xA;&#xD;&#xA;                        LightVector v = fs.GetPixel(n, m);&#xD;&#xA;                        if (v == zero) continue;&#xD;&#xA;&#xD;&#xA;                        sum += v * sinc;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                LightVector c = sum / sincSum;&#xD;&#xA;                if (c.X &gt; 255 || c.Y &gt; 255 || c.Z &gt; 255)&#xD;&#xA;                    c = c.Clamp(0, 255);&#xD;&#xA;                fy.SetPixel(x, y, c);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return fy;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I understand that the sampling frequency on the above middle image might be below the Nyquist frequency but I wanted to know if this is the case or &#xD;&#xA;I am doing something wrong.&#xD;&#xA;&#xD;&#xA;I have tried the above method on a simpler function sin(16*x*x) and the interpolated image looks similar to the original:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;Thanks for the comments. I have modified the code to divide the pixel value by the sum of the two sinc functions. Is this the correct way of normilizing it? The image looks better but it is very blurry. &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://drive.google.com/file/d/0BwxvtmE7yeVKSUlnbWxUbC1VdGM/view?usp=sharing&#xD;&#xA;  [2]: https://i.stack.imgur.com/rwfs3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uJ7Zv.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/SuYWb.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/LiFLH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/aZrhE.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17805" PostHistoryTypeId="24" PostId="5957" RevisionGUID="8f40d48b-ee97-4281-974f-c083db9606e8" CreationDate="2018-03-04T19:55:01.770" Comment="Proposed by 7220 approved by 209, 2041 edit id of 341" ContentLicense="CC BY-SA 3.0" />
  <row Id="17806" PostHistoryTypeId="5" PostId="5122" RevisionGUID="e04871e0-99d4-4656-8b5e-246b0f4a48d4" CreationDate="2018-03-04T19:55:18.663" UserDisplayName="user7220" Comment="Corrected indents.." Text="I have been working on a ray tracer and I was trying to use multiple threads to maximize the performance. I tried couple of approaches but there's no difference in performance. Here's my shot...&#xD;&#xA;&#xD;&#xA;    void ray_tracer::render()&#xD;&#xA;    {&#xD;&#xA;        #define USE_THREADS&#xD;&#xA;        #ifdef USE_THREADS&#xD;&#xA;            for (int threadIndex = 0; threadIndex &lt; mMaxThreads; ++threadIndex) {&#xD;&#xA;                mThreads[threadIndex] = std::thread(&amp;ray_tracer::put_pixel_with_thread, this, threadIndex);&#xD;&#xA;            }&#xD;&#xA;            for (int threadIndex = 0; threadIndex &lt; mMaxThreads; ++threadIndex) {&#xD;&#xA;                if (mThreads[threadIndex].joinable())&#xD;&#xA;                    mThreads[threadIndex].join();&#xD;&#xA;            }&#xD;&#xA;        #else&#xD;&#xA;            put_pixel(); //uses single thread&#xD;&#xA;        #endif&#xD;&#xA;&#xD;&#xA;        stbi_write_bmp(&quot;result.bmp&quot;,mImageWidth,mImageHeight,3,mFrameBuffer);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here's the put_pixel_with_thread(int)...&#xD;&#xA;&#xD;&#xA;    void ray_tracer::put_pixel_with_thread(int threadIndex)&#xD;&#xA;    {&#xD;&#xA;        for (int row = 0; row &lt;mImageHeight; ++row)&#xD;&#xA;        {&#xD;&#xA;            for (int col = int((threadIndex / mMaxThreads)*mImageWidth);&#xD;&#xA;                col &lt; int(((threadIndex + 1) / mMaxThreads)*mImageWidth);&#xD;&#xA;                ++col)&#xD;&#xA;            {&#xD;&#xA;                int index = ((row * mImageWidth) + col) * 3;&#xD;&#xA;&#xD;&#xA;                mFrameBuffer[index] = 0;&#xD;&#xA;                mFrameBuffer[index + 1] = 0;&#xD;&#xA;                mFrameBuffer[index + 2] = 244;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see in put_pixel_with_threads(int) that I tried to split the row for each thread. I don't know what am i doing wrong. I am working on intel i5 6th gen which has 2 hyper-threaded cores. Please help. &#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="17807" PostHistoryTypeId="24" PostId="5122" RevisionGUID="e04871e0-99d4-4656-8b5e-246b0f4a48d4" CreationDate="2018-03-04T19:55:18.663" Comment="Proposed by 7220 approved by 209, 2041 edit id of 329" ContentLicense="CC BY-SA 3.0" />
  <row Id="17808" PostHistoryTypeId="5" PostId="4897" RevisionGUID="2b51decb-1802-4f19-bd9f-a30d0c434763" CreationDate="2018-03-04T19:55:29.637" UserDisplayName="user7220" Comment="Corrected links.." Text="If you want a real-time solution (no baking), and only need one reflection bounce, you can try to generate (or update) a cubemap of the scene every frame, as described in this [graphics study of GTA5][1]  .&#xD;&#xA;  &#xD;&#xA;This solution should work in general cases (be sure to handle cases when the cubemap probe would be in an object of the scene).  &#xD;&#xA;   &#xD;&#xA;If rendering the six faces of the cube every frame seems too heavy, you can try for example to update only one face at a time. You can then use some kind of average function when updating the faces so that the change between each frame looks smoother.  &#xD;&#xA;  &#xD;&#xA;It is only an idea, there are many other solutions that one can think of.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.adriancourreges.com/blog/2015/11/02/gta-v-graphics-study/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17809" PostHistoryTypeId="24" PostId="4897" RevisionGUID="2b51decb-1802-4f19-bd9f-a30d0c434763" CreationDate="2018-03-04T19:55:29.637" Comment="Proposed by 7220 approved by 2041 edit id of 330" ContentLicense="CC BY-SA 3.0" />
  <row Id="17810" PostHistoryTypeId="5" PostId="4997" RevisionGUID="1445fffa-366b-4a80-89a6-d3c6e0229d28" CreationDate="2018-03-04T19:55:52.017" UserDisplayName="user7220" Comment="Corrected links.." Text="- [envmap.pdf | An Efficient Representation for Irradiance Environment Maps][1]&#xD;&#xA;- [Spherical Harmonics and applications in real time graphics][2]&#xD;&#xA;&#xD;&#xA;I am using Spherical Harmonics to turn reflective(mirror like) cube map to diffuse light cube map.&#xD;&#xA;&#xD;&#xA;From what I understand for an image, I calculate 9 coefficient(for red green blue) that describes the color of the cube map.&#xD;&#xA;&#xD;&#xA;The nine coefficients are this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And when you visualize them they become...&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Then I do something with these coefficients to get color of the cube map.&#xD;&#xA;&#xD;&#xA;The part that I am not understanding is using an image to get that 9 coefficients. All the papers kinda assume that you somehow got that coefficient calculated because it is &quot;easy&quot;.&#xD;&#xA;&#xD;&#xA;I don't know how to do that calculation.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;Update&#xD;&#xA;&#xD;&#xA;So while I were looking at [Spherical Harmonic Lighting | Simon's Tech Blog][5]&#xD;&#xA;&#xD;&#xA;I found this equation...&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;So now I know that the mysterious yellow part of the equation was &quot;solid angle related&quot;. I do know how to do solid angle but I still don't understand how to do it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;  [2]: http://xlgames-inc.github.io/posts/sphericalharmonics0/&#xD;&#xA;  [3]: https://i.stack.imgur.com/kmjyY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/oRvEP.png&#xD;&#xA;  [5]: http://simonstechblog.blogspot.com/2011/12/spherical-harmonic-lighting.html&#xD;&#xA;  [6]: https://i.stack.imgur.com/ViYx1.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17811" PostHistoryTypeId="24" PostId="4997" RevisionGUID="1445fffa-366b-4a80-89a6-d3c6e0229d28" CreationDate="2018-03-04T19:55:52.017" Comment="Proposed by 7220 approved by 209, 2041 edit id of 332" ContentLicense="CC BY-SA 3.0" />
  <row Id="17812" PostHistoryTypeId="5" PostId="5705" RevisionGUID="5909143d-2a00-41ab-a50f-f4462321208f" CreationDate="2018-03-04T19:55:58.710" UserDisplayName="user7220" Comment="Corrected indents.." Text="The function that calculates sun position in the sky takes as input&#xD;&#xA;local latitude, longitude and local date time. The output is a vector &#xD;&#xA;which is sun position:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Inversing the above means using the ray direction(sun position in the sky) and retrieving back the local date time. If the date time is valid then the ray must hit the sun path throughout the year. &#xD;&#xA;&#xD;&#xA;Here is the inverse function of the above:&#xD;&#xA;&#xD;&#xA;    public DateTime GetLocalDatetime(double haSolar, double vaSolar)&#xD;&#xA;    {&#xD;&#xA;        double latitude = Helper.ToRadian(Latitude);&#xD;&#xA;        double longitude = Helper.ToRadian(Longitude);&#xD;&#xA;&#xD;&#xA;        double zenithTheta = Helper.PiOver2 - vaSolar;&#xD;&#xA;&#xD;&#xA;        double sinSolarDeclination = (Math.Cos(Math.PI - haSolar) * Math.Cos(latitude) * Math.Sin(zenithTheta)) + Math.Sin(latitude) * Math.Cos(zenithTheta);&#xD;&#xA;        double solarDeclination = Math.Asin(sinSolarDeclination);&#xD;&#xA;&#xD;&#xA;        double cosH = (Math.Sin(vaSolar) - Math.Sin(latitude) * sinSolarDeclination) / (Math.Cos(latitude) * Math.Cos(solarDeclination));&#xD;&#xA;        if (Math.Abs(cosH) &gt; 1) return DateTime.MinValue;&#xD;&#xA;&#xD;&#xA;        double H = Math.Acos(cosH);&#xD;&#xA;        if (haSolar &lt; 0) H *= -1;&#xD;&#xA;&#xD;&#xA;        double declratio = solarDeclination / Helper.ToRadian(23.45);&#xD;&#xA;        if (Math.Abs(declratio) &gt; 1) return DateTime.MinValue;&#xD;&#xA;&#xD;&#xA;        double beta = Math.Asin(declratio);&#xD;&#xA;        int n = (int)Math.Round(beta / Helper.ToRadian(360d / 365d) + 81d, 1);&#xD;&#xA;&#xD;&#xA;        DateTime localtime = new DateTime(DateTime.Now.Year, 1, 1).AddDays(n - 1);&#xD;&#xA;        DateTime solartime = new DateTime(localtime.Year, localtime.Month, localtime.Day, 12, 0, 0);&#xD;&#xA;        solartime = solartime.AddMinutes(4 * Helper.ToDegree(H));&#xD;&#xA;&#xD;&#xA;        double eot = 9.87 * Math.Sin(2d * beta) - 7.53 * Math.Cos(beta) - 1.5 * Math.Sin(beta);&#xD;&#xA;        double deltatimezone = 4d * (longitude - (Timezone * 15d));&#xD;&#xA;        return solartime.AddMinutes(-(eot + deltatimezone));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the image where each band represent each month in the year:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OzwCQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XvI8R.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17813" PostHistoryTypeId="24" PostId="5705" RevisionGUID="5909143d-2a00-41ab-a50f-f4462321208f" CreationDate="2018-03-04T19:55:58.710" Comment="Proposed by 7220 approved by 209, 2041 edit id of 340" ContentLicense="CC BY-SA 3.0" />
  <row Id="17814" PostHistoryTypeId="5" PostId="5520" RevisionGUID="cccf8d16-66fe-43ae-b319-9b2fdcb33e1b" CreationDate="2018-03-04T19:56:07.270" UserDisplayName="user7220" Comment="Corrected indents.." Text="**Update**&#xD;&#xA;&#xD;&#xA;I am editing and posting this question in a different way; this time from the point of view of [Nishita paper][1].&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Sunlight gets scattered at P and attenuated before reaching Pv. Therefore intensity reaching Pv coming from P can be obtained by multiplying the attenuation by intensity at P:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The intensity reaching Pv therefore can be obtained by integrating light due to air molecules along the ray segment PaPb:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Where &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;If I am to solve this integral by Monte Carlo method and without ray marching approach, What would be the estimator and what are the good choices for pdf and sampling method?&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA; &#xD;&#xA;*********************************************************&#xD;&#xA;I am trying to implement the concept of distributed ray tracing on Rayleigh scatterting to render sky a bit more realistic. The code I use is borrowed from&#xD;&#xA;[this website][7]. It takes 16 samples along the ray and 8 samples for sunlight.&#xD;&#xA;This works fine and I was able to generate this image using only 1 sample per pixel(not sure why the sun is so small, any idea?):&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;I then tried to use Monte Carlo to do this. 1 sample uniformly selected along the ray and 1 sample for sunlight. The only changes I did are on four lines:&#xD;&#xA;&#xD;&#xA;    line 7:  uint32_t numSamples = 1; //16&#xD;&#xA;    line 8:  uint32_t numSamplesLight = 1; //8 &#xD;&#xA;&#xD;&#xA;    //used drand48() instead of 0.5&#xD;&#xA;    line 18: Vec3f samplePosition = orig + (tCurrent+&#xD;&#xA;                                    segmentLength * drand48()) * dir; &#xD;&#xA;    line 32: Vec3f samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                                    segmentLengthLight * drand48) * sunDirection; &#xD;&#xA;&#xD;&#xA;The pdf is 1/segmentLength and the sample is taken uniformly in this distance.&#xD;&#xA;Here is my implementation in c# code:&#xD;&#xA;&#xD;&#xA;    public override void Render(int pxlX, int pxlY, Random rand)&#xD;&#xA;    {&#xD;&#xA;        Vector estimatedColor = new Vector();&#xD;&#xA;&#xD;&#xA;        Ray ray = Scene.Camera.GenerateRay(pxlX + rand.NextDouble(), pxlY + rand.NextDouble(), rand.NextDouble(), rand.NextDouble());&#xD;&#xA;&#xD;&#xA;        ISect isect = Scene.Trace(ray);&#xD;&#xA;        if (ISect.IsNull(isect))&#xD;&#xA;            estimatedColor = Atmosph.ComputeIncidentLight(ray, rand);&#xD;&#xA;        else&#xD;&#xA;            estimatedColor = isect.Thing.Material.Emission +&#xD;&#xA;                    ComputeRadiance(isect, rand, 0);&#xD;&#xA;&#xD;&#xA;        ImageFilm.AddToPixel(pxlX, pxlY, estimatedColor/numPixelSamples);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    public Vector ComputeIncidentLight(Ray r, Random rand)&#xD;&#xA;    {&#xD;&#xA;        r.Start.Z += earthRadius;&#xD;&#xA;&#xD;&#xA;        ISect isect = earth.Intersect(r);&#xD;&#xA;        if (ISect.IsNull(isect)) return Vector.ZERO;&#xD;&#xA;&#xD;&#xA;        int numSamples = 1;&#xD;&#xA;        int numSamplesLight = 1;&#xD;&#xA;        double segmentLength = isect.Dist / numSamples;&#xD;&#xA;        double tCurrent = 0;&#xD;&#xA;        Vector sumR = Vector.ZERO;&#xD;&#xA;        Vector sumM = Vector.ZERO;// mie and rayleigh contribution &#xD;&#xA;        double opticalDepthR = 0, opticalDepthM = 0;&#xD;&#xA;        double mu = r.Dir.Dot(sunDirection); // mu in the paper which is the cosine of the angle between the sun direction and the ray direction &#xD;&#xA;        double phaseR = 3d / (16d * Math.PI) * (1 + mu * mu);&#xD;&#xA;        double g = 0.76f;&#xD;&#xA;        double phaseM = 3d / (8d * Math.PI) * ((1d - g * g) * (1d + mu * mu)) / ((2d + g * g) * Math.Pow(1d + g * g - 2d * g * mu, 1.5d));&#xD;&#xA;        for (int i = 0; i &lt; numSamples; ++i)&#xD;&#xA;        {&#xD;&#xA;            Vector samplePosition = r.Start + r.Dir * (tCurrent + segmentLength * rand.NextDouble());&#xD;&#xA;            double height = samplePosition.Length() - earthRadius;&#xD;&#xA;            // compute optical depth for light&#xD;&#xA;            double hr = Math.Exp(-height / Hr) * segmentLength;&#xD;&#xA;            double hm = Math.Exp(-height / Hm) * segmentLength;&#xD;&#xA;            opticalDepthR += hr;&#xD;&#xA;            opticalDepthM += hm;&#xD;&#xA;            // light optical depth&#xD;&#xA;            ISect isectSun = earth.Intersect(new Ray(samplePosition, sunDirection));&#xD;&#xA;            double segmentLengthLight = isectSun.Dist/ numSamplesLight, tCurrentLight = 0;&#xD;&#xA;            double opticalDepthLightR = 0, opticalDepthLightM = 0;&#xD;&#xA;            int j;&#xD;&#xA;            for (j = 0; j &lt; numSamplesLight; ++j)&#xD;&#xA;            {&#xD;&#xA;                Vector samplePositionLight = samplePosition + sunDirection * (tCurrentLight + segmentLengthLight * rand.NextDouble());&#xD;&#xA;                double heightLight = samplePositionLight.Length() - earthRadius;&#xD;&#xA;                if (heightLight &lt; 0) break;&#xD;&#xA;                opticalDepthLightR += Math.Exp(-heightLight / Hr) * segmentLengthLight;&#xD;&#xA;                opticalDepthLightM += Math.Exp(-heightLight / Hm) * segmentLengthLight;&#xD;&#xA;                tCurrentLight += segmentLengthLight;&#xD;&#xA;            }&#xD;&#xA;            if (j == numSamplesLight)&#xD;&#xA;            {&#xD;&#xA;                Vector tau = betaR * (opticalDepthR + opticalDepthLightR) + betaM * 1.1f * (opticalDepthM + opticalDepthLightM);&#xD;&#xA;                Vector attenuation = new Vector(Math.Exp(-tau.X), Math.Exp(-tau.Y), Math.Exp(-tau.Z));&#xD;&#xA;                sumR += attenuation * hr;&#xD;&#xA;                sumM += attenuation * hm;&#xD;&#xA;            }&#xD;&#xA;            tCurrent += segmentLength;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // We use a magic number here for the intensity of the sun (20). We will make it more&#xD;&#xA;        // scientific in a future revision of this lesson/code&#xD;&#xA;        return (sumR * betaR * phaseR + sumM * betaM * phaseM) * sunIrradiance;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The below image rendered with 400 samples per pixel, however is different from the above:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;Could anyone shed some light where I've got it wrong?&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://nishitalab.org/user/nis/cdrom/sig93_nis.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/JCbNW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/t4OWe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/zEuOL.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bPZsR.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/WHUw0.png&#xD;&#xA;  [7]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;  [8]: https://i.stack.imgur.com/YTuXG.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/9aw6n.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17815" PostHistoryTypeId="24" PostId="5520" RevisionGUID="cccf8d16-66fe-43ae-b319-9b2fdcb33e1b" CreationDate="2018-03-04T19:56:07.270" Comment="Proposed by 7220 approved by 2041 edit id of 342" ContentLicense="CC BY-SA 3.0" />
  <row Id="17816" PostHistoryTypeId="5" PostId="4824" RevisionGUID="c2660652-74ca-4f8f-b534-e5d5e9817695" CreationDate="2018-03-04T19:56:29.633" UserDisplayName="user7220" Comment="Corrected links.." Text="When I download this image:&#xD;&#xA;&#xD;&#xA;[![https://www.ucn.edu.ni/media/2016/03/graduados-ucn-nicaragua.jpg][1]][1] &#xD;&#xA;&#xD;&#xA;then its total size is 341,0 kB.&#xD;&#xA;&#xD;&#xA;The image has a width of 2880 pixels and height of 1100 pixel and 1 X/Y resolution pixel/in.&#xD;&#xA;&#xD;&#xA;I opened the image with gimp and pressed **scale image** and reduced the width to 1920px and auto adjusted height of 733px, and keeped the resolution as it is and used the interpolation cubic. If I now export this as a jpg with 90% quality, then the image size is 546 kB! &#xD;&#xA;&#xD;&#xA;How is that possible and how can I avoid that?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.ucn.edu.ni/media/2016/03/graduados-ucn-nicaragua.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17817" PostHistoryTypeId="24" PostId="4824" RevisionGUID="c2660652-74ca-4f8f-b534-e5d5e9817695" CreationDate="2018-03-04T19:56:29.633" Comment="Proposed by 7220 approved by 209, 2041 edit id of 337" ContentLicense="CC BY-SA 3.0" />
  <row Id="17818" PostHistoryTypeId="5" PostId="16" RevisionGUID="dfae809e-7d63-41b4-a240-69ca5dc05f07" CreationDate="2018-03-04T19:56:47.600" UserDisplayName="user7220" Comment="Corrected links.." Text="&gt; A stencil buffer contains per-pixel integer data which is used to add&#xD;&#xA;&gt; more control over which pixels are rendered.&#xD;&#xA;&gt; &#xD;&#xA;&gt; A stencil buffer operates similarly to a depth buffer. So similarly,&#xD;&#xA;&gt; that stencil data is stored in a depth buffer. While depth data&#xD;&#xA;&gt; determines which pixel is closest to the camera, stencil data can be&#xD;&#xA;&gt; used as a more general purpose per-pixel mask for saving or discarding&#xD;&#xA;&gt; pixels. To create the mask, use a stencil function to compare a&#xD;&#xA;&gt; reference stencil value -- a global value -- to the value in the&#xD;&#xA;&gt; stencil buffer each time a pixel is rendered.&#xD;&#xA;&#xD;&#xA;Source: [What Is a Stencil Buffer? | Microsoft Developer Network][1]&#xD;&#xA;&#xD;&#xA;The general idea is that you can set a value for each pixel and then set the operation (`GREATER`, `SMALLER`, `EQUAL` etc), when this evaluates to true the pixel is shaded and shown.&#xD;&#xA;&#xD;&#xA;One application is realtime reflection, when rendering the reflection texture the stencil buffer is used to create a mask for where the reflection is applied. For example only apply the reflection to the glass material shaded triangles. It can also be used to create arbitrary two dimensional masks for the whole framebuffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/bb976074.aspx" ContentLicense="CC BY-SA 3.0" />
  <row Id="17819" PostHistoryTypeId="24" PostId="16" RevisionGUID="dfae809e-7d63-41b4-a240-69ca5dc05f07" CreationDate="2018-03-04T19:56:47.600" Comment="Proposed by 7220 approved by 209, 2041 edit id of 333" ContentLicense="CC BY-SA 3.0" />
  <row Id="17820" PostHistoryTypeId="5" PostId="4747" RevisionGUID="4426a87f-8695-4a9c-bbe2-eb8845e59752" CreationDate="2018-03-04T19:56:52.873" UserDisplayName="user7220" Comment="Corrected links.." Text="Have you access to the OpenGL utility library? If so, you could use the tesselation functions from that. See this guide : [Polygon Tessellation | OpenGL Programming Guide][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.glprogramming.com/red/chapter11.html#name1" ContentLicense="CC BY-SA 3.0" />
  <row Id="17821" PostHistoryTypeId="24" PostId="4747" RevisionGUID="4426a87f-8695-4a9c-bbe2-eb8845e59752" CreationDate="2018-03-04T19:56:52.873" Comment="Proposed by 7220 approved by 209, 2041 edit id of 339" ContentLicense="CC BY-SA 3.0" />
  <row Id="17822" PostHistoryTypeId="5" PostId="4970" RevisionGUID="e094f90f-0499-4eea-af84-50a0fed57055" CreationDate="2018-03-04T19:56:57.423" UserDisplayName="user7220" Comment="Corrected links.." Text="Link to paper : [Irradiance and Incoming Radiance | lawrence.edu][1]&#xD;&#xA;&#xD;&#xA;&gt; Using a shader to compute En&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&gt; &#xD;&#xA;&gt; Computing En as described above is a very compute intensive operation,&#xD;&#xA;&gt; because we have to compute the integral over the cube map for each new&#xD;&#xA;&gt; direction vector n that we want to work with. At the same time, the&#xD;&#xA;&gt; details for different values of n are highly repetitive. This suggests&#xD;&#xA;&gt; that we should enlist the aid of shaders to compute this mapping for&#xD;&#xA;&gt; us. Here is the outline of a strategy that makes it possible to do&#xD;&#xA;&gt; this.&#xD;&#xA;&gt; &#xD;&#xA;&gt; 1. Use OpenGL to render a two dimensional square centered at the origin&#xD;&#xA;&gt; with sides of length 2. This square represents one of the sides of our&#xD;&#xA;&gt; cubical irradiance map. Given the mapping above we can map any point&#xD;&#xA;&gt; (x , y) on the square to a direction vector n. &#xD;&#xA;2. We render the square to&#xD;&#xA;&gt; a framebuffer with dimensions size by size pixels, where size is the&#xD;&#xA;&gt; desired size of our irradiance cube map texture. &#xD;&#xA;3. In the fragment&#xD;&#xA;&gt; shader, we translate the interpolated fragment positions we are given&#xD;&#xA;&gt; into direction vectors n and construct loops that sum over the six&#xD;&#xA;&gt; faces of the environment map:&#xD;&#xA;&gt; &#xD;&#xA;&gt; &#xD;&#xA;&gt; When rendering is done, we convert the image in the frame buffer to a&#xD;&#xA;&gt; texture for use by our irradiance cube map.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I understand that Li is color at i. ωi is the direction of incoming light.&#xD;&#xA;&#xD;&#xA;However I do not understand what dωi is.&#xD;&#xA;&#xD;&#xA;Paper describes it as...&#xD;&#xA;&#xD;&#xA;&gt; Computing the solid angle dωi subtended by a particular texel is a&#xD;&#xA;&gt; little more involved. Texels near the center of the texture subtend a&#xD;&#xA;&gt; somewhat larger angle, while texels near the corner take up a smaller&#xD;&#xA;&gt; solid angle when we map the cube texture onto a sphere. Here is a&#xD;&#xA;&gt; reference that explains how to compute the solid angle correctly from&#xD;&#xA;&gt; the positions xi and yi.&#xD;&#xA;&#xD;&#xA;However I am not following words to understand what it means.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www2.lawrence.edu/fast/GREGGJ/CMSC420/chapter21/Irradiance.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/FeT3I.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17823" PostHistoryTypeId="24" PostId="4970" RevisionGUID="e094f90f-0499-4eea-af84-50a0fed57055" CreationDate="2018-03-04T19:56:57.423" Comment="Proposed by 7220 approved by 209, 2041 edit id of 331" ContentLicense="CC BY-SA 3.0" />
  <row Id="17824" PostHistoryTypeId="2" PostId="6366" RevisionGUID="bd66b6e5-2991-42ae-b37f-4abe72a84c97" CreationDate="2018-03-04T21:25:19.617" UserId="6046" Text="There is the whole derivation of it but I'll be discussing a brief overview.&#xD;&#xA;This is for the perspective projection  where the line joining the eye and the projection/image plane is perpendicular to it. Like here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As we can easily see, by similar triangles $\triangle ABC$ and $\triangle AEF$ we have&#xD;&#xA;&#xD;&#xA;$Y_p / Y = D/-Z$&#xD;&#xA;&#xD;&#xA;where $Y_p$ is the projected $Y$ coordinate on to the image plane. $AB = D$ is the total distance from eye to the image plane and is usually set to 1.&#xD;&#xA;&#xD;&#xA;Hence we have,&#xD;&#xA;&#xD;&#xA;$Y_p = (Y*D)/-Z$&#xD;&#xA;&#xD;&#xA;Most APIs also set that the camera is facing towards the negative Z axis hence the negative sign. The projection plane is also assumed to be a rectangle instead of a square. It's 2 units long in the $Y$ direction and centered at the origin i.e in the range [-1,1] so it's 1 unit long in the positive Y axis and 1 unit long in the negative. However horizontally, its in the range $[-A, A]$ so when calculating $X_p$ we have to correct for this factor. &#xD;&#xA;&#xD;&#xA;$A = Width\ of\ rectangle/Height\ of\ rectangle$&#xD;&#xA;&#xD;&#xA;Similarly for $X_p$ and $Z_p$ we have,&#xD;&#xA;&#xD;&#xA;$A*X_p = (X*D)/(-Z)$&#xD;&#xA;&#xD;&#xA;$X_p = (X*D)/(-Z*A)$&#xD;&#xA;&#xD;&#xA;$Z_p = D$&#xD;&#xA;&#xD;&#xA;We can easily see see that&#xD;&#xA;&#xD;&#xA;$tan(Y_{fov}/2) = BC/D = 1/D$&#xD;&#xA;&#xD;&#xA;$D = 1/tan(Y_{fov}/2)$&#xD;&#xA;&#xD;&#xA;Here, $Y_{fov}$ is the angle of field of view in the Y axis. Since we are only talking about the upper half its $Y_{fov}/2$.&#xD;&#xA;&#xD;&#xA;Hence one way to write $X_p$ and $Y_p$ is&#xD;&#xA;&#xD;&#xA;$X_p = X * 1/ [-Z*A*tan(Y_{fov}/2)]$&#xD;&#xA;&#xD;&#xA;$Y_p = Y * 1/ [-Z*tan(Y_{fov}/2)]$&#xD;&#xA;&#xD;&#xA;This is what you are seeing in the matrix. The $-Z$ term is accounted for by the $-1$ in the 4th row. This $-Z$ is stored as the $w$ coordinate which is then used in perspective division in which we divide by $w$.&#xD;&#xA;&#xD;&#xA;For more information you can check this site [here][2]&#xD;&#xA;&#xD;&#xA;Note:- Haven't discussed properly about NDC space, perspective divide and about near and far planes in $Z_p$ as that would take too much time. Just wanted to show you that it can be derived.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WmmPi.png&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="17825" PostHistoryTypeId="5" PostId="6366" RevisionGUID="fc867a84-3ea4-4297-b721-d8bfb53c0ada" CreationDate="2018-03-04T21:33:10.390" UserId="6046" Comment="added 115 characters in body" Text="There is the whole derivation of it but I'll be discussing a brief overview.&#xD;&#xA;This is for the perspective projection  where the line joining the eye and the projection/image plane is perpendicular to it. Like here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As we can easily see, by similar triangles $\triangle ABC$ and $\triangle AEF$ we have&#xD;&#xA;&#xD;&#xA;$Y_p / Y = D/-Z$&#xD;&#xA;&#xD;&#xA;where $Y_p$ is the projected $Y$ coordinate on to the image plane. $AB = D$ is the total distance from eye to the image plane and is usually set to 1.&#xD;&#xA;&#xD;&#xA;Hence we have,&#xD;&#xA;&#xD;&#xA;$Y_p = (Y*D)/-Z$&#xD;&#xA;&#xD;&#xA;Most APIs also set that the camera is facing towards the negative Z axis hence the negative sign. The projection plane is also assumed to be a rectangle instead of a square. It's 2 units long in the $Y$ direction and centered at the origin i.e in the range [-1,1] so it's 1 unit long in the positive Y axis and 1 unit long in the negative. However horizontally, its in the range $[-A, A]$ so when calculating $X_p$ we have to correct for this factor. &#xD;&#xA;&#xD;&#xA;$A = Width\ of\ rectangle/Height\ of\ rectangle$&#xD;&#xA;&#xD;&#xA;Similarly for $X_p$ and $Z_p$ we have,&#xD;&#xA;&#xD;&#xA;$A*X_p = (X*D)/(-Z)$&#xD;&#xA;&#xD;&#xA;$X_p = (X*D)/(-Z*A)$&#xD;&#xA;&#xD;&#xA;$Z_p = D$&#xD;&#xA;&#xD;&#xA;We can easily see see that&#xD;&#xA;&#xD;&#xA;$tan(Y_{fov}/2) = BC/D = 1/D$&#xD;&#xA;&#xD;&#xA;$D = 1/tan(Y_{fov}/2)$&#xD;&#xA;&#xD;&#xA;Here, $Y_{fov}$ is the angle of field of view in the Y axis. Since we are only talking about the upper half its $Y_{fov}/2$.&#xD;&#xA;&#xD;&#xA;Hence one way to write $X_p$ and $Y_p$ is&#xD;&#xA;&#xD;&#xA;$X_p = \frac{X}{-Z} * \frac{1}{A*tan(Y_{fov}/2)}$&#xD;&#xA;&#xD;&#xA;$Y_p = \frac{Y}{-Z} * \frac{1}{tan(Y_{fov}/2)}$&#xD;&#xA;&#xD;&#xA;This is what you are seeing in the matrix. The $X$ and $Y$ come from the vector at which the transformation matrix is applied and the $-Z$ term is accounted for by the $-1$ in the 4th row. This $-Z$ is stored as the $w$ coordinate which is then used in perspective division in which we divide by $w$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For more information you can check this site [here][2]&#xD;&#xA;&#xD;&#xA;Note:- Haven't discussed properly about NDC space, perspective divide and about near and far planes in $Z_p$ as that would take too much time. Just wanted to show you that it can be derived.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WmmPi.png&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="17829" PostHistoryTypeId="5" PostId="6366" RevisionGUID="3eda8910-3ed3-41b3-8cee-4020a49522f7" CreationDate="2018-03-05T09:49:05.723" UserId="6046" Comment="added 14 characters in body" Text="There is the whole derivation of it but I'll be discussing a brief overview.&#xD;&#xA;This is for the perspective projection  where the line joining the eye and the center of the projection/image plane is perpendicular to it. Like here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As we can easily see, by similar triangles $\triangle ABC$ and $\triangle AEF$ we have&#xD;&#xA;&#xD;&#xA;$Y_p / Y = D/-Z$&#xD;&#xA;&#xD;&#xA;where $Y_p$ is the projected $Y$ coordinate on to the image plane. $AB = D$ is the total distance from eye to the image plane and is usually set to 1.&#xD;&#xA;&#xD;&#xA;Hence we have,&#xD;&#xA;&#xD;&#xA;$Y_p = (Y*D)/-Z$&#xD;&#xA;&#xD;&#xA;Most APIs also set that the camera is facing towards the negative Z axis following the convention for right handed coordinate system, hence the negative sign. The projection plane is also assumed to be a rectangle instead of a square. It's 2 units long in the $Y$ direction and centered at the origin i.e in the range [-1,1] so it's 1 unit long in the positive Y axis and 1 unit long in the negative. However horizontally, its in the range $[-A, A]$ so when calculating $X_p$ we have to correct for this factor. &#xD;&#xA;&#xD;&#xA;$A = Width\ of\ rectangle/Height\ of\ rectangle$&#xD;&#xA;&#xD;&#xA;Similarly for $X_p$ and $Z_p$ we have,&#xD;&#xA;&#xD;&#xA;$A*X_p = (X*D)/(-Z)$&#xD;&#xA;&#xD;&#xA;$X_p = (X*D)/(-Z*A)$&#xD;&#xA;&#xD;&#xA;$Z_p = D$&#xD;&#xA;&#xD;&#xA;We can easily see see that&#xD;&#xA;&#xD;&#xA;$tan(Y_{fov}/2) = BC/D = 1/D$&#xD;&#xA;&#xD;&#xA;$D = 1/tan(Y_{fov}/2)$&#xD;&#xA;&#xD;&#xA;Here, $Y_{fov}$ is the angle of field of view in the Y axis. Since we are only talking about the upper half its $Y_{fov}/2$.&#xD;&#xA;&#xD;&#xA;Hence one way to write $X_p$ and $Y_p$ is&#xD;&#xA;&#xD;&#xA;$X_p = \frac{X}{-Z} * \frac{1}{A*tan(Y_{fov}/2)}$&#xD;&#xA;&#xD;&#xA;$Y_p = \frac{Y}{-Z} * \frac{1}{tan(Y_{fov}/2)}$&#xD;&#xA;&#xD;&#xA;This is what you are seeing in the matrix. The $X$ and $Y$ come from the vector at which the transformation matrix is applied and the $-Z$ term is accounted for by the $-1$ in the 4th row. This $-Z$ is stored as the $w$ coordinate which is then used in perspective division in which we divide by $w$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For more information you can check this site [here][2]&#xD;&#xA;&#xD;&#xA;Note:- Haven't discussed properly about NDC space, perspective divide and about near and far planes in $Z_p$ as that would take too much time. Just wanted to show you that it can be derived.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WmmPi.png&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix" ContentLicense="CC BY-SA 3.0" />
  <row Id="17830" PostHistoryTypeId="5" PostId="6365" RevisionGUID="668e2e3e-4e08-48db-af4e-88e4975dd169" CreationDate="2018-03-05T11:22:20.213" UserId="209" Comment="minor improvement to English" Text="I am a new leaner of computer graphics. I'm trying to understand a code I found online and I got stuck in the following formula:&#xD;&#xA;&#xD;&#xA;    topLeft = [-tan(vfov/2)*(output_width/output_height), -tan(vfov/2), 1];&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Source][1]&#xD;&#xA;&#xD;&#xA;looking on the internet I found that the formula is that of the Perspective Matrix. However the formula of the code has:&#xD;&#xA;&#xD;&#xA;`tan(vfov/2)*(output_width/output_height)` instead of&#xD;&#xA;&#xD;&#xA;    1 / tan(vfov/2)*(output_width/output_height)&#xD;&#xA;&#xD;&#xA;Here is the Perspective Matrix I found online. &#xD;&#xA;&#xD;&#xA;Can you explain to me why I have inverse values?&#xD;&#xA;What does it mean?&#xD;&#xA;Thank you so much&#xD;&#xA;&#xD;&#xA;[![Perspective Matrix][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/rayryeng/equi2cubic/blob/master/equi2cubic.m&#xD;&#xA;  [2]: https://i.stack.imgur.com/C9PST.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17831" PostHistoryTypeId="33" PostId="6348" RevisionGUID="83d65976-62a7-4486-b1af-6107972c4881" CreationDate="2018-03-05T11:54:56.907" UserId="8297" Comment="44" />
  <row Id="17839" PostHistoryTypeId="5" PostId="4263" RevisionGUID="5d0dab58-bc29-40bc-b77d-53c66d105faa" CreationDate="2018-03-05T20:18:52.287" UserDisplayName="user7220" Comment="Corrected indents.." Text="I've to rasterize a line taking into account not only the background color of the screen, which is white, but also the color of other objects in the scene. In my case, I've just another object, a sphere, which is actually visualized using a ray tracing technique. &#xD;&#xA;&#xD;&#xA;So far the code that I have seems only to consider the white background color of the screen and not also the color of the sphere.&#xD;&#xA;&#xD;&#xA;So here's the code:&#xD;&#xA;&#xD;&#xA;    // ray tracing of the sphere&#xD;&#xA;    // here we initialize the z-buffer's elements to -1.0 zBuffer that you find below&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    //&#xD;&#xA;    // rasterize a line&#xD;&#xA;    //&#xD;&#xA;&#xD;&#xA;    // line from p1 to p2 in LOCAL coordinates&#xD;&#xA;    Point3d p1 (-1.0, 0.0, 0.0);&#xD;&#xA;    Point3d p2 ( 1.0, 0.0, 0.0);&#xD;&#xA;&#xD;&#xA;    // transformations...&#xD;&#xA;    Matrix4d S  = Matrix4d::scaling (5.0, 1.0, 1.0);&#xD;&#xA;    Matrix4d R1 = Matrix4d::rotation (0.5,'z');&#xD;&#xA;    Matrix4d R2 = Matrix4d::rotation (tau,'x');&#xD;&#xA;    Matrix4d T  = Matrix4d::translation (0.0, 0.0, 8.0);&#xD;&#xA;&#xD;&#xA;    Matrix4d M  = T*R2*R1*S;&#xD;&#xA;&#xD;&#xA;    p1 = M*p1;&#xD;&#xA;    p2 = M*p2;&#xD;&#xA;&#xD;&#xA;    // screen coordinates&#xD;&#xA;    double x1 = ( X + p1.x()/p1.z() ) / s - 0.5;&#xD;&#xA;    double y1 = ( Y - p1.y()/p1.z() ) / s - 0.5;&#xD;&#xA;    double x2 = ( X + p2.x()/p2.z() ) / s - 0.5;&#xD;&#xA;    double y2 = ( Y - p2.y()/p2.z() ) / s - 0.5;&#xD;&#xA;&#xD;&#xA;    //&#xD;&#xA;    // line rasterization algorithm with anti-aliasing and z-test&#xD;&#xA;    // (for lines with slope between -1 and 1)&#xD;&#xA;    //&#xD;&#xA;    int x  = round(x1);&#xD;&#xA;    int y  = round(y1);&#xD;&#xA;&#xD;&#xA;    double I0 = 1.0;&#xD;&#xA;    double m = (y2-y1) / (x2-x1);&#xD;&#xA;&#xD;&#xA;    bool up = true;&#xD;&#xA;    if (y2 &lt; y1) {&#xD;&#xA;        m = -m;&#xD;&#xA;        I0 = 0.0;&#xD;&#xA;        up = false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int nextY;&#xD;&#xA;    double z;&#xD;&#xA;    for ( ; x&lt;=x2; x++) {&#xD;&#xA;        if (up)&#xD;&#xA;            nextY = y+1;&#xD;&#xA;        else&#xD;&#xA;            nextY = y-1;&#xD;&#xA;&#xD;&#xA;        // barycentric coordinates of the current point: (1-lambda, lambda),&#xD;&#xA;        // i.e.: x = (1-lambda) x1 + lambda x2&#xD;&#xA;        double lambda = (x-x1) / (x2-x1);&#xD;&#xA;&#xD;&#xA;        // perspectively correct linear interpolation of z-values&#xD;&#xA;        z = p1.z()*p2.z() / ( (1.0-lambda)*p2.z() + lambda*p1.z() );&#xD;&#xA;&#xD;&#xA;        if ( (zBuffer[x+y*w] &lt; 0) || z &lt; zBuffer[x+y*w] ) {&#xD;&#xA;            int I = (int) 255*I0;&#xD;&#xA;            image-&gt;setPixel( x, y,     qRgb( 255-I, 255, 255-I ) );&#xD;&#xA;            image-&gt;setPixel( x, nextY, qRgb(     I, 255,     I ) );&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (m &gt; I0) {&#xD;&#xA;            y  = nextY;&#xD;&#xA;            I0 += 1.0;&#xD;&#xA;        }&#xD;&#xA;        I0 -= m;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // repaint canvas&#xD;&#xA;    repaint();&#xD;&#xA;&#xD;&#xA;Now the output is not as expected, because one of the pixels of the lines on the sphere is coloured white. Of course we notice this immediately! The idea is to make a smoother line that considers not only the colour of the background but also the colour of the sphere.&#xD;&#xA;&#xD;&#xA;I thought I need to interpolate colours, but I'm not sure which ones and how to do it. I know that the basic idea of interpolation is to find an intermediate colour between two (or more) colours ($C_1, C_2$) using a formula as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(1 - \alpha) C_1 + \alpha * C_2$$&#xD;&#xA;&#xD;&#xA;Now the problem is that I don't know what's exactly $\alpha$ and which colours would be $C_1$ and $C_2$.  I thought $\alpha$ could be the `lambda` variable in the code above, but this is more than a guess than a conclusion after a logical reasoning. &#xD;&#xA;&#xD;&#xA;Moreover, I guessed that the colours $C_1$ and $C_2$ are respectively the color of the pixel before the rasterization of the line (i.e. in the ray tracing part), which can also be the color of the sphere, if that pixel is covered by the sphere, or the background color, i.e. white in my case. &#xD;&#xA;&#xD;&#xA;Any help is appreciated.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To give you an idea, this is the wrong output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;and this should be the correct one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note (if you zoom in) that the line in the first picture is not that smooth over the sphere, because one of the pixels (at least) is colored for the background color white.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;After trying to interpolate green and the current background color (as also Nathan Reed suggested), I obtained:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;which is correct in the sense that I think that the interpolation is being done correctly, but at this point I think interpolation is not what we need to do to obtain a smooth line.&#xD;&#xA;&#xD;&#xA;To obtain this I just added a few lines when setting the pixels of the line:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int I = (int)255 * I0;&#xD;&#xA;&#xD;&#xA;    Color3d c = pixels_colors[x + y * w]; &#xD;&#xA;    // pixels_buffer contains the color at pixel x + y * w&#xD;&#xA;    // this color was saved while ray tracing the sphere&#xD;&#xA;&#xD;&#xA;    c.clamped();&#xD;&#xA;&#xD;&#xA;    int red = c.r() * 255;&#xD;&#xA;    int green = c.g() * 255;&#xD;&#xA;    int blue = c.b() * 255;&#xD;&#xA;&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(red - I, green, blue - I));&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(I, green, I));&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Edit 2**&#xD;&#xA;&#xD;&#xA;After the corrections suggested by Nathan Reed, I obtained:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The colors of the pixels of the line over the sphere now really seem to be the product of the interpolation between the color green and the color of the sphere. Here's the code:&#xD;&#xA;&#xD;&#xA;    int I = (int)255 * I0;&#xD;&#xA;&#xD;&#xA;    Color3d background_color = pixels_colors[x + y * w];&#xD;&#xA;    Color3d green(0, 1.0, 0);&#xD;&#xA;&#xD;&#xA;    Color3d color_y = (1 - I0) * background_color + I0 * green;&#xD;&#xA;    Color3d color_next_y = I0 * background_color + (1 - I0) * green;&#xD;&#xA;&#xD;&#xA;    image-&gt;setPixel(x, nextY, qRgb(color_y.r() * 255, color_y.g() * 255, color_y.b() * 255));&#xD;&#xA;    image-&gt;setPixel(x, y, qRgb(color_next_y.r() * 255, color_next_y.g() * 255, color_next_y.b() * 255));&#xD;&#xA;&#xD;&#xA;If this is now correct, the picture still doesn't look as it should. I think we may need to color more pixels?!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q0tnC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TIUz7.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rm0BZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3NSRw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17840" PostHistoryTypeId="24" PostId="4263" RevisionGUID="5d0dab58-bc29-40bc-b77d-53c66d105faa" CreationDate="2018-03-05T20:18:52.287" Comment="Proposed by 7220 approved by 4718 edit id of 344" ContentLicense="CC BY-SA 3.0" />
  <row Id="17843" PostHistoryTypeId="5" PostId="1449" RevisionGUID="3779e307-9aef-4991-bfe5-de2643bfda90" CreationDate="2018-03-05T21:23:07.313" UserDisplayName="user7220" Comment="Corrected links.." Text="Iman already prepared a complete answer but I wish to add something to it&#xD;&#xA;&#xD;&#xA;LOD can be done in two different way&#xD;&#xA;&#xD;&#xA; 1. Continous which is called CLOD and is a polygon mesh optimization&#xD;&#xA; 2. Discrete which almost every other algorithm than polygon mesh optimization, considered to be in this group.&#xD;&#xA;&#xD;&#xA;For example mipmaping is a good,fast but heavy one that belongs to secound group at the above &#xD;&#xA;&#xD;&#xA;here you may find a good explanation to mipmaping and implementation code with OpenGl.&#xD;&#xA;&#xD;&#xA;- [Multiple Levels of Detail][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://people.cs.clemson.edu/~dhouse/courses/405/notes/OpenGL-mipmaps.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="17844" PostHistoryTypeId="24" PostId="1449" RevisionGUID="3779e307-9aef-4991-bfe5-de2643bfda90" CreationDate="2018-03-05T21:23:07.313" Comment="Proposed by 7220 approved by 209, 48 edit id of 338" ContentLicense="CC BY-SA 3.0" />
  <row Id="17845" PostHistoryTypeId="2" PostId="6370" RevisionGUID="32d50c56-4958-42ec-9d7e-62fe551a3b3a" CreationDate="2018-03-05T21:54:01.593" UserId="8323" Text="I'm trying to calculate what the effective pitch, yaw, and roll are for an image.&#xD;&#xA;I have the image's original pitch, yaw, and roll.  Then the image (camera) is rolled at some arbitrary angle.  I want to calculate the new relative pitch, yaw, and roll.&#xD;&#xA;&#xD;&#xA;I know if pitch and yaw are 0, the new roll is just original roll + camera rotation angle. Likewise, if yaw and roll are 0, the new pitch is just the original pitch + camera rotation angle. For an arbitrary angle, I know both pitch and roll are affected. I imagine there is a simple equation for this, but I'm having trouble finding a reference." ContentLicense="CC BY-SA 3.0" />
  <row Id="17846" PostHistoryTypeId="1" PostId="6370" RevisionGUID="32d50c56-4958-42ec-9d7e-62fe551a3b3a" CreationDate="2018-03-05T21:54:01.593" UserId="8323" Text="Camera rotation effect on pitch, yaw, roll" ContentLicense="CC BY-SA 3.0" />
  <row Id="17847" PostHistoryTypeId="3" PostId="6370" RevisionGUID="32d50c56-4958-42ec-9d7e-62fe551a3b3a" CreationDate="2018-03-05T21:54:01.593" UserId="8323" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17848" PostHistoryTypeId="2" PostId="6371" RevisionGUID="90f32f62-e199-4de8-aeaf-47bc7b9fcaed" CreationDate="2018-03-05T23:07:59.583" UserId="8323" Text="Thanks for the suggestion to look up Euler angle rotations.  https://www.learnopencv.com/rotation-matrix-to-euler-angles/ is a good reference to answer this question." ContentLicense="CC BY-SA 3.0" />
  <row Id="17853" PostHistoryTypeId="2" PostId="6373" RevisionGUID="dabd07a9-7837-4adb-a694-58439e5d0c6d" CreationDate="2018-03-06T05:03:47.667" UserId="8325" Text="Given a 3D model, is there a way to [stereographically project][1] it to a 2D image? In particular, I would only need a little more than half the model (the lower half) to be mapped to the plane (mapping the whole 3D model would be impossible, since the stereographic projection is infinite).&#xD;&#xA;&#xD;&#xA;I am only Linux, if that makes any difference.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stereographic_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17854" PostHistoryTypeId="1" PostId="6373" RevisionGUID="dabd07a9-7837-4adb-a694-58439e5d0c6d" CreationDate="2018-03-06T05:03:47.667" UserId="8325" Text="How to generate the stereographic projection of a 3D model" ContentLicense="CC BY-SA 3.0" />
  <row Id="17855" PostHistoryTypeId="3" PostId="6373" RevisionGUID="dabd07a9-7837-4adb-a694-58439e5d0c6d" CreationDate="2018-03-06T05:03:47.667" UserId="8325" Text="|image-processing|projections|raster-image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17856" PostHistoryTypeId="5" PostId="6373" RevisionGUID="a153a2f3-1aaa-4ec3-a672-12d2beb13a38" CreationDate="2018-03-06T05:30:31.543" UserId="8325" Comment="added 101 characters in body" Text="Given a 3D model, is there a way to [stereographically project][1] it to a 2D image? In particular, I would only need a little more than half the model (the lower half) to be mapped to the plane (mapping the whole 3D model would be impossible, since the stereographic projection is infinite).&#xD;&#xA;&#xD;&#xA;I am only Linux, if that makes any difference.&#xD;&#xA;&#xD;&#xA;(Note: If I could increase the viewing angle, I could do this with most any 3D viewing software.)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stereographic_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17857" PostHistoryTypeId="5" PostId="1746" RevisionGUID="098c1aef-3aec-4dc9-b0d3-3796d040e846" CreationDate="2018-03-06T05:35:38.617" UserId="38" Comment="added 14 characters in body" Text="There is unfortunately no good answer to this question. Simply it wont work. There is no good way to define colorful, it this context. Cie is trying to capture the physical measurement. It however does not succeed very well in relating the colors to each other.&#xD;&#xA;&#xD;&#xA;Colors on the very outer arc represent spectral distributions of close to [Dirac delta function](https://en.wikipedia.org/wiki/Dirac_delta_function). So one could construct a model that says that a color is very colorful when it is a Dirac delta. &#xD;&#xA;&#xD;&#xA;There is a unforeseen consequence of this definition though. Namely the magenta colors do not exist as Dirac Deltas. As these colors do not exist in the spectrum. So they consist of mixture of 2 wavelengths only. This would mean they are less colorful than most other colors.&#xD;&#xA;&#xD;&#xA;Other problems&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;Unfortunately, xyY is not perceptually uniform. So a straight line on the xyY does not represent interpolations between 2 color mixtures. Therefore making a polar transformation means you will have different color bases on same coordinates. Also precieved color do not really move over to your model. To do this properly you would need to do a extremely sophisticated transformation.&#xD;&#xA;&#xD;&#xA;There are many problems with converting color to a polar coordinates in that that is exactly contrary how vision works. White is also a bit problematic in this context. The distance to full saturated signal is different for each of the 3 different cones in the eye. Hell, even what is while depends on the surrounding colors and ambient color conditions. So aim afraid your trying to force a worldview that does not exist.&#xD;&#xA;&#xD;&#xA;Finally&#xD;&#xA;-------&#xD;&#xA;&#xD;&#xA;What would this be useful for? " ContentLicense="CC BY-SA 3.0" />
  <row Id="17858" PostHistoryTypeId="5" PostId="6052" RevisionGUID="bc50f0de-1523-4266-ae3f-56e9bb53937f" CreationDate="2018-03-06T08:42:25.230" UserDisplayName="user7220" Comment="Corrected links.." Text="3D clipping is usually done in clipspace coordinates, that means the perspective matrix is used for sending the primitives to clipspace before doing the actual perspective projection. You can visualize the clipspace as a view frustum but with the shape of a box. So it is very fast to clip primitives against a AABB. The math is a little involved, but is all explained in this blog post: &#xD;&#xA;&#xD;&#xA;[Calculating the gluPerspective matrix and other OpenGL matrix maths | Unspecified Behaviour Blog][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17859" PostHistoryTypeId="24" PostId="6052" RevisionGUID="bc50f0de-1523-4266-ae3f-56e9bb53937f" CreationDate="2018-03-06T08:42:25.230" Comment="Proposed by 7220 approved by 48, 7957 edit id of 351" ContentLicense="CC BY-SA 3.0" />
  <row Id="17860" PostHistoryTypeId="5" PostId="4743" RevisionGUID="af20c3cf-3e93-447b-a8b0-2e1d0bb9a1fc" CreationDate="2018-03-06T08:53:57.227" UserId="209" Comment="Defined log* n" Text="If your aim is just to fill the region and since you say you're using opengl, an alternative to Nathan's suggestion of using a triangulation algorithm&lt;sup&gt;++&lt;/sup&gt;, is to use the stencil buffer. &#xD;&#xA;&#xD;&#xA;Assuming you want odd/even fill, clear the stencil buffer, dice up your polygon as before but have your triangles just (IIRC) invert the stencil. When all are sent, draw again but only where the stencil is non-zero. (It's been a while but I think you can clear the stencil buffer at the same time as this second pass to save time on the next complex polygon.)&#xD;&#xA;&#xD;&#xA;The stencil buffer approach should also work with self-intersecting polygons.&#xD;&#xA;&#xD;&#xA;One final thing, I think it is more fill-efficient if you use a triangle strip rather than a fan when you chop up your polygon. You just need to access your vertices in something like  0, 1, N-1, 2, N-2 etc. order&#xD;&#xA;&#xD;&#xA;More information on the stencil buffer can be found in [OpenGL Stencil Tests][1] and in [Drawing Filled, Concave Polygons Using the Stencil Buffer][2]&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;++&lt;/sup&gt; Though, if you do want to use a triangulation algorithm but have a very large number of vertices, you could try Seidel's method as it's 'relatively' easy to implement but has *nearly* O(n) time complexity. &#xD;&#xA;&#xD;&#xA;However if you do a search for Seidel, note that the code in [Narkhede &amp;&#xD;&#xA;Manocha][3] is *not* actually Seidel's method as theirs is only O(n log n) not the faster O(n log* n) you should expect, where, if you're not familiar with it, &#xD;&#xA;$$log^*n =\begin{cases}&#xD;&#xA;1+ log^*(log(n))  &amp; \text{if $n$ &gt; 1} \\&#xD;&#xA;0 &amp; \text{otherwise}&#xD;&#xA;\end{cases}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Stencil_Test&#xD;&#xA;  [2]: http://www.glprogramming.com/red/chapter14.html#name13&#xD;&#xA;  [3]: http://www.cs.unc.edu/%7Edm/CODE/GEM/chapter.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17861" PostHistoryTypeId="5" PostId="5535" RevisionGUID="377cf40a-3cd3-441c-a548-559347246327" CreationDate="2018-03-06T08:54:14.090" UserDisplayName="user7220" Comment="Corrected links.." Text="The problem is that instead of a camera-to-world matrix, a world-to-camera matrix is being made by glm::lookAtRH. &#xD;&#xA;&#xD;&#xA;This is because GLM is a math library made for OpenGL. In OpenGL, you do not move the 'camera' as there is no camera in OpenGL. You move the whole world the other way around, so that it lines up in the frustum. The lookAtRH method returns a matrix that moves the whole world in a way that it seems like you have the camera there.&#xD;&#xA;&#xD;&#xA;Inversing the matrix is a fine way to get the proper camera-to-world matrix.&#xD;&#xA;&#xD;&#xA;Scrathapixel does have an article regarding making your own lookAt function. One thing to note about this article is that they use a row-major notation. It might be that you need to switch it up and use a column-major notation (just swap the x index with the y index).&#xD;&#xA;&#xD;&#xA;[Placing a Camera: the LookAt Function | Scratchapixel][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function/framing-lookat-function" ContentLicense="CC BY-SA 3.0" />
  <row Id="17862" PostHistoryTypeId="24" PostId="5535" RevisionGUID="377cf40a-3cd3-441c-a548-559347246327" CreationDate="2018-03-06T08:54:14.090" Comment="Proposed by 7220 approved by 48, 209 edit id of 347" ContentLicense="CC BY-SA 3.0" />
  <row Id="17863" PostHistoryTypeId="5" PostId="5633" RevisionGUID="d2c44447-4bc7-466c-9ca3-f85a6a6ead1f" CreationDate="2018-03-06T08:54:24.783" UserDisplayName="user7220" Comment="Corrected links.." Text="For an nVidia only solution you can use floating point atomic add intrinsics (like NvInterlockedAddFp32) [Unlocking GPU Intrinsics in HLSL | NVIDIA Developer][1]&#xD;&#xA;&#xD;&#xA;I tried this on 80.000 vertex mesh and it's quite fast (something like 1 or 2 ms on a GTX980M, if I remember correctly)&#xD;&#xA;&#xD;&#xA;Just beware of compiling your shaders in release for the intrinsics to work (due to nvidia bug/limitation)&#xD;&#xA;&#xD;&#xA;Also beware of vertex splits (due to UV discontinuities for example), you'll have to handle them or else you'll have unwanted hard edges at UV seams.&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/unlocking-gpu-intrinsics-hlsl" ContentLicense="CC BY-SA 3.0" />
  <row Id="17864" PostHistoryTypeId="24" PostId="5633" RevisionGUID="d2c44447-4bc7-466c-9ca3-f85a6a6ead1f" CreationDate="2018-03-06T08:54:24.783" Comment="Proposed by 7220 approved by 48, 209 edit id of 346" ContentLicense="CC BY-SA 3.0" />
  <row Id="17865" PostHistoryTypeId="5" PostId="5503" RevisionGUID="f0314add-88e5-4cd7-ad33-cfc24a23d609" CreationDate="2018-03-06T08:54:54.820" UserDisplayName="user7220" Comment="Corrected links.." Text="It's the normalization factor to make sure the BRDF always reflects the same amount of energy regardless of the value of the specular exponent n. Without that factor, changing the specular exponent changes the overall reflectance of the material.&#xD;&#xA;&#xD;&#xA;Further reading: [The Blinn-Phong Normalization Zoo | The Tenth Planet Blog][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.thetenthplanet.de/archives/255" ContentLicense="CC BY-SA 3.0" />
  <row Id="17866" PostHistoryTypeId="24" PostId="5503" RevisionGUID="f0314add-88e5-4cd7-ad33-cfc24a23d609" CreationDate="2018-03-06T08:54:54.820" Comment="Proposed by 7220 approved by 48, 209 edit id of 352" ContentLicense="CC BY-SA 3.0" />
  <row Id="17867" PostHistoryTypeId="5" PostId="6373" RevisionGUID="95ef6c1d-b968-48f0-88a8-3e55642de4a4" CreationDate="2018-03-06T08:55:50.923" UserId="209" Comment="added 1 character in body" Text="Given a 3D model, is there a way to [stereographically project][1] it to a 2D image? In particular, I would only need a little more than half the model (the lower half) to be mapped to the plane (mapping the whole 3D model would be impossible, since the stereographic projection is infinite).&#xD;&#xA;&#xD;&#xA;I am using Linux, if that makes any difference.&#xD;&#xA;&#xD;&#xA;(Note: If I could increase the viewing angle, I could do this with most any 3D viewing software.)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stereographic_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17868" PostHistoryTypeId="5" PostId="6136" RevisionGUID="47efabac-6d36-49cf-912f-28624c3ef677" CreationDate="2018-03-06T08:56:32.670" UserDisplayName="user7220" Comment="Corrected indents.. Corrected links.." Text="Let's say I have a point on a potential cubic sphere inflated using this:&#xD;&#xA;&#xD;&#xA;    Vector3 v = new Vector3(x, y, z) * 2f / gridSize - Vector3.one;&#xD;&#xA;    float x2 = v.x * v.x;&#xD;&#xA;    float y2 = v.y * v.y;&#xD;&#xA;    float z2 = v.z * v.z;&#xD;&#xA;    Vector3 s;&#xD;&#xA;    s.x = v.x * Mathf.Sqrt(1f - y2 / 2f - z2 / 2f + y2 * z2 / 3f);&#xD;&#xA;    s.y = v.y * Mathf.Sqrt(1f - x2 / 2f - z2 / 2f + x2 * z2 / 3f);&#xD;&#xA;    s.z = v.z * Mathf.Sqrt(1f - x2 / 2f - y2 / 2f + x2 * y2 / 3f);&#xD;&#xA;    normals[i] = s;&#xD;&#xA;    vertices[i] = normals[i] * radius;&#xD;&#xA;&#xD;&#xA;from: [Cube Sphere | Unity C# Tutorial][1]&#xD;&#xA;&#xD;&#xA;After finding the cube face the point belong to, how do I find which spatial hash it belong to, ie which grid cells for any given arbitrary division?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://catlikecoding.com/unity/tutorials/cube-sphere/" ContentLicense="CC BY-SA 3.0" />
  <row Id="17869" PostHistoryTypeId="24" PostId="6136" RevisionGUID="47efabac-6d36-49cf-912f-28624c3ef677" CreationDate="2018-03-06T08:56:32.670" Comment="Proposed by 7220 approved by 48, 209 edit id of 343" ContentLicense="CC BY-SA 3.0" />
  <row Id="17870" PostHistoryTypeId="5" PostId="6109" RevisionGUID="86c8b301-f099-4dc8-99b7-f91e4e234d1f" CreationDate="2018-03-06T08:57:34.463" UserDisplayName="user7220" Comment="Corrected links.." Text="I have been reading this paper : [3D Surface Extraction using Incremental Tetrahedra Carving .pdf][1]&#xD;&#xA;&#xD;&#xA;I have already generated a tetrahedra for my mesh and I would like to create a surface mesh. I can't understand the algorithm. From my understanding, there is a camera that generates rays towards to the points of the tetrahedral, and I get the intersections, but how would I eliminate the triangles that are inside or outside ? how would I detect inside or outside polygons ?&#xD;&#xA;&#xD;&#xA;Would someone give a pseudo code of the algorithm ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://openaccess.thecvf.com/content_iccv_workshops_2013/W21/papers/Sugiura_3D_Surface_Extraction_2013_ICCV_paper.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="17871" PostHistoryTypeId="24" PostId="6109" RevisionGUID="86c8b301-f099-4dc8-99b7-f91e4e234d1f" CreationDate="2018-03-06T08:57:34.463" Comment="Proposed by 7220 approved by 48, 209 edit id of 345" ContentLicense="CC BY-SA 3.0" />
  <row Id="17872" PostHistoryTypeId="5" PostId="3746" RevisionGUID="83fd8c2d-8238-4025-9f9b-60eb79f24225" CreationDate="2018-03-06T09:05:57.077" UserDisplayName="user7220" Comment="Corrected indents.." Text="here is my vertex array I am using:&#xD;&#xA;&#xD;&#xA;    vertices = [&#xD;&#xA;        -1.0,  1.0,  0.0,&#xD;&#xA;         0.0,  1.0,  0.0,&#xD;&#xA;        -0.5,  1.0,  0.0,&#xD;&#xA;         0.5,  1.0,  0.0,&#xD;&#xA;         1.0,  1.0,  0.0,&#xD;&#xA;         1.0,  0.5,  0.0,&#xD;&#xA;         0.0,  0.5,  0.0,&#xD;&#xA;         0.5,  0.5,  0.0,&#xD;&#xA;        -0.5,  0.5,  0.0,&#xD;&#xA;        -1.0,  0.5,  0.0,&#xD;&#xA;        &#xD;&#xA;        -1.0,  0.0,  0.0,&#xD;&#xA;        -0.5,  0.0,  0.0,&#xD;&#xA;         0.0,  0.0,  0.0,&#xD;&#xA;         0.5,  0.0,  0.0,&#xD;&#xA;         1.0,  0.0,  0.0,&#xD;&#xA;        &#xD;&#xA;        -1.0, -0.5,  0.0,&#xD;&#xA;         0.0, -0.5,  0.0,&#xD;&#xA;        -0.5, -0.5,  0.0,&#xD;&#xA;         0.5, -0.5,  0.0,&#xD;&#xA;         1.0, -0.5,  0.0,&#xD;&#xA;         1.0, -1.0,  0.0,&#xD;&#xA;         0.0, -1.0,  0.0,&#xD;&#xA;         0.5, -1.0,  0.0,&#xD;&#xA;        -0.5, -1.0,  0.0,&#xD;&#xA;        -1.0, -1.0,  0.0,&#xD;&#xA;    ];&#xD;&#xA;&#xD;&#xA;In a html-select I want to select a rendering mode and use it inmy `drawScene`-method:&#xD;&#xA;&#xD;&#xA;    var renderModeSelector = document.getElementById(&quot;renderModeDropDown&quot;);&#xD;&#xA;    var selectedRenderModeValue = renderModeSelector.options[renderModeSelector.selectedIndex].value;&#xD;&#xA;&#xD;&#xA;    switch (selectedRenderModeValue) {&#xD;&#xA;        case &quot;0&quot;:&#xD;&#xA;            gl.drawArrays(gl.POINTS, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;            break;&#xD;&#xA;        case &quot;1&quot;:&#xD;&#xA;            gl.drawArrays(gl.TRIANGLE_FAN, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;            break;&#xD;&#xA;        case &quot;2&quot;:&#xD;&#xA;            gl.drawArrays(gl.LINE_LOOP, 0, squareVertexPositionBuffer.numItems);&#xD;&#xA;            break;&#xD;&#xA;        default:&#xD;&#xA;            console.log(&quot;No rendering mode selected.&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA; 1. Case '0' is supposed to draw the points which works fine&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; 2. Case '1' should draw a filled rectangle, with the shader below. Unfortunately it is messed up, see also in the picture below.&#xD;&#xA;&#xD;&#xA; Fragment shader:&#xD;&#xA;&#xD;&#xA;        precision mediump float;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_FragColor = vColor;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; Vertex-shader:&#xD;&#xA;&#xD;&#xA;        attribute vec3 aVertexPosition;&#xD;&#xA;        attribute vec4 aVertexColor;&#xD;&#xA;&#xD;&#xA;        uniform mat4 uMVMatrix;&#xD;&#xA;        uniform mat4 uPMatrix;&#xD;&#xA;&#xD;&#xA;        varying vec4 vColor;&#xD;&#xA;&#xD;&#xA;        void main(void) {&#xD;&#xA;        gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);&#xD;&#xA;        vColor = aVertexColor;&#xD;&#xA;        gl_PointSize = 5.0;&#xD;&#xA;        }&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA; 3. And finally in case '2' it is supposed to draw only the outlines, which also does not work as expected, see below.&#xD;&#xA;&#xD;&#xA; [![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So I wonder if it is possible to meet my requirements while using one vertexPositionBuffer. Should I maybe create another vertexPositionBuffer or can I just change mine &quot;on the fly&quot;, before rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZiyIL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vahR1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/23zah.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="17873" PostHistoryTypeId="24" PostId="3746" RevisionGUID="83fd8c2d-8238-4025-9f9b-60eb79f24225" CreationDate="2018-03-06T09:05:57.077" Comment="Proposed by 7220 approved by 48, 100 edit id of 349" ContentLicense="CC BY-SA 3.0" />
  <row Id="17874" PostHistoryTypeId="5" PostId="6078" RevisionGUID="0b0315c6-64f5-477c-a56e-0c1f0c6d7699" CreationDate="2018-03-06T09:06:07.723" UserDisplayName="user7220" Comment="Corrected indents.." Text="I am following the [WebGL2Fundametals tutorial][1]. Using some sample (cube) data I was able to successfully call `gl.drawElements();` using index, normal and geometry data. This are my fragment and vertex shaders:&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es    &#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    in vec3 v_normal;&#xD;&#xA;    in vec3 v_surfaceToLight;&#xD;&#xA;    in vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    uniform vec4 u_color;&#xD;&#xA;    uniform float u_shininess;&#xD;&#xA;    uniform vec3 u_lightDirection;&#xD;&#xA;    &#xD;&#xA;    uniform float u_innerLimit; // In dot space&#xD;&#xA;    uniform float u_outerLimit; // In dot space&#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      vec3 normal = normalize(v_normal);&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceToLightDirection = normalize(v_surfaceToLight);&#xD;&#xA;      vec3 surfaceToViewDirection = normalize(v_surfaceToView);&#xD;&#xA;      vec3 halfVector = normalize(surfaceToLightDirection + surfaceToViewDirection);&#xD;&#xA;    &#xD;&#xA;      float dotFromDirection = dot(surfaceToLightDirection, -u_lightDirection);&#xD;&#xA;      float inLight = smoothstep(u_outerLimit, u_innerLimit, dotFromDirection);&#xD;&#xA;      // Using normals for color calculation based on the incidence of light&#xD;&#xA;      float light = inLight * dot(normal, surfaceToLightDirection);&#xD;&#xA;      float specular = inLight * pow(dot(normal, halfVector), u_shininess);&#xD;&#xA;    &#xD;&#xA;      outColor = u_color;&#xD;&#xA;    &#xD;&#xA;      outColor.rgb *= light;&#xD;&#xA;    &#xD;&#xA;      // Add in the specular&#xD;&#xA;      outColor.rgb += specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    in vec4 a_position;&#xD;&#xA;    in vec3 a_normal;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 u_world;&#xD;&#xA;    uniform mat4 u_worldViewProjection;&#xD;&#xA;    uniform mat4 u_worldInverseTranspose;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 u_lightWorldPosition;&#xD;&#xA;    uniform vec3 u_viewWorldPosition;&#xD;&#xA;    &#xD;&#xA;    // varying to pass the normal to the fragment shader&#xD;&#xA;    out vec3 v_normal;&#xD;&#xA;    &#xD;&#xA;    out vec3 v_surfaceToLight;&#xD;&#xA;    out vec3 v_surfaceToView;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    &#xD;&#xA;      gl_Position = u_worldViewProjection * a_position;&#xD;&#xA;    &#xD;&#xA;      // Orient the normals and pass to the fragment shader&#xD;&#xA;      v_normal = mat3(u_worldInverseTranspose) * a_normal;&#xD;&#xA;    &#xD;&#xA;      vec3 surfaceWorldPosition = (u_world * a_position).xyz;&#xD;&#xA;      v_surfaceToLight = u_lightWorldPosition - surfaceWorldPosition;&#xD;&#xA;      v_surfaceToView = u_viewWorldPosition - surfaceWorldPosition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With the following call the cube is successfully rendered:&#xD;&#xA;&#xD;&#xA;    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);&#xD;&#xA;    GLHelper.setUniformValues(this._uniforms, uniformValues);&#xD;&#xA;    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the working cube data:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;     // Front face&#xD;&#xA;    -100, -100, 100,&#xD;&#xA;     100, -100, 100,&#xD;&#xA;     100,  100, 100,&#xD;&#xA;    -100,  100, 100,&#xD;&#xA;    &#xD;&#xA;     // Back face&#xD;&#xA;    -100, -100, -100,&#xD;&#xA;    -100,  100, -100,&#xD;&#xA;     100,  100, -100,&#xD;&#xA;     100, -100, -100,&#xD;&#xA;    &#xD;&#xA;     // Top face&#xD;&#xA;    -100,  100, -100,&#xD;&#xA;    -100,  100,  100,&#xD;&#xA;     100,  100,  100,&#xD;&#xA;     100,  100, -100,&#xD;&#xA;    &#xD;&#xA;     // Bottom face&#xD;&#xA;    -100, -100, -100,&#xD;&#xA;     100, -100, -100,&#xD;&#xA;     100, -100,  100,&#xD;&#xA;    -100, -100,  100,&#xD;&#xA;    &#xD;&#xA;     // Right face&#xD;&#xA;     100, -100, -100,&#xD;&#xA;     100,  100, -100,&#xD;&#xA;     100,  100,  100,&#xD;&#xA;     100, -100,  100,&#xD;&#xA;    &#xD;&#xA;     // Left face&#xD;&#xA;    -100, -100, -100,&#xD;&#xA;    -100, -100,  100,&#xD;&#xA;    -100,  100,  100,&#xD;&#xA;    -100,  100, -100,&#xD;&#xA;&#xD;&#xA;Normals:&#xD;&#xA;&#xD;&#xA;     // Front&#xD;&#xA;     0.0,  0.0,  1.0,&#xD;&#xA;     0.0,  0.0,  1.0,&#xD;&#xA;     0.0,  0.0,  1.0,&#xD;&#xA;     0.0,  0.0,  1.0,&#xD;&#xA;    &#xD;&#xA;     // Back face&#xD;&#xA;     0.0,  0.0, -1.0,&#xD;&#xA;     0.0,  0.0, -1.0,&#xD;&#xA;     0.0,  0.0, -1.0,&#xD;&#xA;     0.0,  0.0, -1.0,&#xD;&#xA;    &#xD;&#xA;     // Top face&#xD;&#xA;     0.0,  1.0,  0.0,&#xD;&#xA;     0.0,  1.0,  0.0,&#xD;&#xA;     0.0,  1.0,  0.0,&#xD;&#xA;     0.0,  1.0,  0.0,&#xD;&#xA;    &#xD;&#xA;     // Bottom face&#xD;&#xA;     0.0, -1.0,  0.0,&#xD;&#xA;     0.0, -1.0,  0.0,&#xD;&#xA;     0.0, -1.0,  0.0,&#xD;&#xA;     0.0, -1.0,  0.0,&#xD;&#xA;    &#xD;&#xA;     // Right face&#xD;&#xA;     1.0,  0.0,  0.0,&#xD;&#xA;     1.0,  0.0,  0.0,&#xD;&#xA;     1.0,  0.0,  0.0,&#xD;&#xA;     1.0,  0.0,  0.0,&#xD;&#xA;    &#xD;&#xA;     // Left face&#xD;&#xA;    -1.0,  0.0,  0.0,&#xD;&#xA;    -1.0,  0.0,  0.0,&#xD;&#xA;    -1.0,  0.0,  0.0,&#xD;&#xA;    -1.0,  0.0,  0.0,&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;     0,  1,  2,  0,  2,  3, // Front face&#xD;&#xA;     4,  5,  6,  4,  6,  7, // Back face&#xD;&#xA;     8,  9, 10,  8, 10, 11, // Top face&#xD;&#xA;    12, 13, 14, 12, 14, 15, // Bottom face&#xD;&#xA;    16, 17, 18, 16, 18, 19, // Right face&#xD;&#xA;    20, 21, 22, 20, 22, 23, // Left face&#xD;&#xA;&#xD;&#xA;If I get it right the normals in this model should look something like the cube's normals in [the very first animation in the &quot;Introducing normals&quot; part](https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html). Now I was trying to create and import a cube using Blender.&#xD;&#xA;&#xD;&#xA;Unfortunately I wasn't able to recreate a cube with the same kind of normals. Blender generates only one (pink) normal per vertex and they also obviously have a totally different angle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[Some sources](https://blender.stackexchange.com/a/14697) suggest that smoothing the faces would fix this issue. It did not for me. Here is the Wavefront file:&#xD;&#xA;&#xD;&#xA;    o Cube&#xD;&#xA;    v   1.000000 -1.000000 -1.000000&#xD;&#xA;    v   1.000000 -1.000000  1.000000&#xD;&#xA;    v  -1.000000 -1.000000  1.000000&#xD;&#xA;    v  -1.000000 -1.000000 -1.000000&#xD;&#xA;    v   1.000000  1.000000 -0.999999&#xD;&#xA;    v   0.999999  1.000000  1.000001&#xD;&#xA;    v  -1.000000  1.000000  1.000000&#xD;&#xA;    v  -1.000000  1.000000 -1.000000&#xD;&#xA;    vn  0.0000   -1.0000    0.0000&#xD;&#xA;    vn  0.0000    1.0000    0.0000&#xD;&#xA;    vn  1.0000   -0.0000    0.0000&#xD;&#xA;    vn  0.0000   -0.0000    1.0000&#xD;&#xA;    vn -1.0000   -0.0000   -0.0000&#xD;&#xA;    vn  0.0000    0.0000   -1.0000&#xD;&#xA;    s off&#xD;&#xA;    f 1//1 3//1 4//1&#xD;&#xA;    f 8//2 6//2 5//2&#xD;&#xA;    f 5//3 2//3 1//3&#xD;&#xA;    f 6//4 3//4 2//4&#xD;&#xA;    f 3//5 8//5 4//5&#xD;&#xA;    f 1//6 8//6 5//6&#xD;&#xA;    f 1//1 2//1 3//1&#xD;&#xA;    f 8//2 7//2 6//2&#xD;&#xA;    f 5//3 6//3 2//3&#xD;&#xA;    f 6//4 7//4 3//4&#xD;&#xA;    f 3//5 7//5 8//5&#xD;&#xA;    f 1//6 4//6 8//6&#xD;&#xA;&#xD;&#xA;When I try to import and to render this data using `gl.drawElements(gl.TRIANGLES, 72, gl.UNSIGNED_SHORT, 0);` I get the following output:&#xD;&#xA;&#xD;&#xA;&gt; ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of&#xD;&#xA;&gt; range vertices in attribute 1&#xD;&#xA;&#xD;&#xA;If I use above (.obj) vertex and normal data six time each I do not get any more errors but instead of a cube only a single triangle seems to be rendered.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am pretty sure that `attribute 1` is `in vec3 a_normal;` in my vertex shader. So I am mainly confused about one thing here:&#xD;&#xA;&#xD;&#xA; - How do I modify my code in order to interpret and render the data&#xD;&#xA;   correctly?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;After changing indices to be zero based I do get more than a single triangle, the object still looks wrong.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The result drawn with `gl.LINES`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://webgl2fundamentals.org/webgl/lessons/webgl-3d-lighting-directional.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/JhiETm.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JFspWm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/VpR3l.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/88klr.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="17875" PostHistoryTypeId="24" PostId="6078" RevisionGUID="0b0315c6-64f5-477c-a56e-0c1f0c6d7699" CreationDate="2018-03-06T09:06:07.723" Comment="Proposed by 7220 approved by 48, 100 edit id of 348" ContentLicense="CC BY-SA 3.0" />
  <row Id="17876" PostHistoryTypeId="5" PostId="4363" RevisionGUID="a713fc68-8421-4ad9-ae94-09bab44f52f3" CreationDate="2018-03-06T09:06:20.863" UserDisplayName="user7220" Comment="Corrected indents.." Text="I am trying to implement [Blades of Waving Grass][1] and I am still stuck at the point where I need to achieve texture arrangements like in the figure below (the first one).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So my plan is to draw the first texture, then draw the second and rotate it by 30°, then another and rotate it by 60° etc. Drawing the first texture is not a problem but I have some issues rotating the second one. I would expect it to look something like this (view from above):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Instead the actual result looks something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I suspect that this deviation occurs due to the object being rotated around the world-space axes and not around its own.&#xD;&#xA;&#xD;&#xA;Vertex and position data:&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f,&#xD;&#xA;         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,&#xD;&#xA;         0.5f,  0.5f, -0.5f,  1.0f,  1.0f,&#xD;&#xA;         0.5f,  0.5f, -0.5f,  1.0f,  1.0f,&#xD;&#xA;        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,&#xD;&#xA;        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    glm::vec3 texturePositions[] = {&#xD;&#xA;        glm::vec3(0.0f, 0.0f, 0.0f),&#xD;&#xA;        glm::vec3(0.0f, 0.0f, 0.0f)&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Camera/View transformations:&#xD;&#xA;&#xD;&#xA;    // Camera/View transformation&#xD;&#xA;    glm::mat4 view;&#xD;&#xA;    view = camera.GetViewMatrix();&#xD;&#xA;    // Projection&#xD;&#xA;    glm::mat4 projection;&#xD;&#xA;    projection = glm::perspective(glm::radians(camera.Zoom), (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 1000.0f);&#xD;&#xA;    // Get the uniform locations&#xD;&#xA;    GLint modelLoc = glGetUniformLocation(ourShader.Program, &quot;model&quot;);&#xD;&#xA;    GLint viewLoc = glGetUniformLocation(ourShader.Program, &quot;view&quot;);&#xD;&#xA;    GLint projectionLoc = glGetUniformLocation(ourShader.Program, &quot;projection&quot;);&#xD;&#xA;    // Pass the matrices to the shader&#xD;&#xA;    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));&#xD;&#xA;    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;&#xD;&#xA;Drawing the first two textures:&#xD;&#xA;&#xD;&#xA;    //Texture 1&#xD;&#xA;    glm::mat4 model;&#xD;&#xA;    model = glm::translate(model, texturePositions[0]);&#xD;&#xA;    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;    //Texture 2&#xD;&#xA;    GLfloat angle = glm::radians(30.0f);&#xD;&#xA;    model = glm::translate(model, texturePositions[1]);&#xD;&#xA;    model = glm::rotate(model, angle, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;&#xD;&#xA;Online search showed that this might have several reasons:&#xD;&#xA;&#xD;&#xA; 1. Order of the applied transformations are crucial&#xD;&#xA; 2. One solution might be to first move the &quot;object&quot; until its center&#xD;&#xA;    matches the world-space origin, apply the rotation and then move it&#xD;&#xA;    to the desired position.&#xD;&#xA;&#xD;&#xA;As I am still in the very early learning process so I am kind of clueless here.&#xD;&#xA;&#xD;&#xA; 1. I think that the order of transformations for the second texture is fine in my code, isn't it?&#xD;&#xA; 2. Also how would I determine the right position for the object where&#xD;&#xA;    the rotation would be applied correctly? (see above point 2)&#xD;&#xA; 3. Might it be more efficient to apply the rotation in the objects&#xD;&#xA;    local space? Is that possible in my case?&#xD;&#xA;&#xD;&#xA;I do not expect anybody to write code for me (though some snippet would be nice) but I would appreciate some hints or somebody pointing me in the right direction. I think that I have a basic fallacy here.&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA; 1. If I change the rotation axis from `y` to `z` the object rotates&#xD;&#xA;    around its own center just like expected.&#xD;&#xA; 2. I also tried to apply the following solutions (taken from [here][5]&#xD;&#xA;    and [here][6]) where I moved the object to `glm::vec3(-x,-y,-z)`&#xD;&#xA;    rotate it and then moving it back to `glm::vec3(x,y,z)`,&#xD;&#xA;    unfortunately with no success. Which makes sence as the position&#xD;&#xA;    vector is set to (0,0,0) anyway. I also tried to change thisposition&#xD;&#xA;    to something else than the origin also with no success.&#xD;&#xA;&#xD;&#xA;  [1]: http://http.developer.nvidia.com/GPUGems/gpugems_ch07.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/QVbKy.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/7xhvk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7qQrc.png&#xD;&#xA;  [5]: https://gamedev.stackexchange.com/questions/18854/rotating-an-object-in-opengl-about-its-centre&#xD;&#xA;  [6]: https://www.opengl.org/discussion_boards/showthread.php/169200-Rotating-an-Object-around-its-center" ContentLicense="CC BY-SA 3.0" />
  <row Id="17877" PostHistoryTypeId="24" PostId="4363" RevisionGUID="a713fc68-8421-4ad9-ae94-09bab44f52f3" CreationDate="2018-03-06T09:06:20.863" Comment="Proposed by 7220 approved by 48, 100 edit id of 350" ContentLicense="CC BY-SA 3.0" />
  <row Id="17878" PostHistoryTypeId="5" PostId="4743" RevisionGUID="94a69fea-f864-4aa4-a396-7ee67c3851eb" CreationDate="2018-03-06T10:52:19.053" UserId="209" Comment="added 81 characters in body" Text="If your aim is just to fill the region and since you say you're using opengl, an alternative to Nathan's suggestion of using a triangulation algorithm&lt;sup&gt;++&lt;/sup&gt;, is to use the stencil buffer. &#xD;&#xA;&#xD;&#xA;Assuming you want odd/even fill, clear the stencil buffer, dice up your polygon as before but have your triangles just (IIRC) invert the stencil. When all are sent, draw again but only where the stencil is non-zero. (It's been a while but I think you can clear the stencil buffer at the same time as this second pass to save time on the next complex polygon.)&#xD;&#xA;&#xD;&#xA;The stencil buffer approach should also work with self-intersecting polygons.&#xD;&#xA;&#xD;&#xA;One final thing, I think it is more fill-efficient if you use a triangle strip rather than a fan when you chop up your polygon. You just need to access your vertices in something like  0, 1, N-1, 2, N-2 etc. order&#xD;&#xA;&#xD;&#xA;More information on the stencil buffer can be found in [OpenGL Stencil Tests][1] and in [Drawing Filled, Concave Polygons Using the Stencil Buffer][2]&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;++&lt;/sup&gt; Though, if you do want to use a triangulation algorithm but have a very large number of vertices, you could try Seidel's method as it's 'relatively' easy to implement but has *nearly* O(n) time complexity. &#xD;&#xA;&#xD;&#xA;However if you do a search for Seidel, note that the code in [Narkhede &amp;&#xD;&#xA;Manocha][3] is *not* actually Seidel's method as theirs is only O(n log n) not the faster O(n log* n) you should expect, where, if you're not familiar with it, &#xD;&#xA;$$log^*n =\begin{cases}&#xD;&#xA;1+ log^*(log(n))  &amp; \text{if $n$ &gt; 1} \\&#xD;&#xA;0 &amp; \text{otherwise}&#xD;&#xA;\end{cases}$$&#xD;&#xA;&#xD;&#xA;In *practical* terms, you can consider it to be constant as it grows so slowly.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Stencil_Test&#xD;&#xA;  [2]: http://www.glprogramming.com/red/chapter14.html#name13&#xD;&#xA;  [3]: http://www.cs.unc.edu/%7Edm/CODE/GEM/chapter.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17879" PostHistoryTypeId="5" PostId="6135" RevisionGUID="72d9bfd4-6c8c-47e5-aad0-2c2f014f799f" CreationDate="2018-03-06T10:54:58.097" UserId="8048" Comment="added 146 characters in body" Text="I am trying to implement a path tracer, but I have some problem. The class `Spectrum` is color. I implemented a mirror material like this:&#xD;&#xA;&#xD;&#xA;    Spectrum MirrorBSDF::f(const Vector3D&amp; wo, const Vector3D&amp; wi) &#xD;&#xA;    {&#xD;&#xA;        return reflectance * (1.0 / abs_cos_theta(wo));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The reflectance is a Spectrum variable. And now I want to add a material &quot;Glass&quot; that can reflect and refract. It meets the Fresnel theorem. Can someone teach me how to implement this? The function `f` is used like this:           &#xD;&#xA;&#xD;&#xA;    Spectrum light_L = light-&gt;sample_L(hit_p, &amp;dir_to_light, &amp;dist_to_light, &amp;pdf);&#xD;&#xA;&#xD;&#xA;    // convert direction into coordinate space of the surface, where surface normal is [0 0 1]&#xD;&#xA;    Vector3D w_in = w2o * dir_to_light;&#xD;&#xA;    double cos_theta = std::max(0.0, w_in[2]);&#xD;&#xA;    Spectrum f = isect.bsdf-&gt;f(w_out, w_in);&#xD;&#xA;&#xD;&#xA;    // TODO: Construct a shadow ray and compute whether the intersected surface is&#xD;&#xA;    // in shadow and accumulate reflected radiance&#xD;&#xA;    Ray shadow_ray(hit_p + EPS_D * dir_to_light, dir_to_light, &#xD;&#xA;                   dist_to_light - (EPS_D * dir_to_light).norm(), 0);&#xD;&#xA;    if (!bvh-&gt;intersect(shadow_ray))&#xD;&#xA;    {&#xD;&#xA;        L_out += (f * light_L * (cos_theta * scale / pdf));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I implemented it.But something is error.Where is error?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XuvAJ.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17880" PostHistoryTypeId="2" PostId="6374" RevisionGUID="223cd62c-55d0-437d-8d47-89ceff8c891e" CreationDate="2018-03-06T13:42:06.910" UserId="7008" Text="I have just come across [this article about half, snorm and unorm][1], but I don't get some of the points (or why they work).&#xD;&#xA;&#xD;&#xA; 1. According to the article, a `half` is basically a 16 bit float and an `snorm` is a signed float dividied by `65535`. Therefore, they are basically the same, just that the snorm is represented in $[-1, 1]$ whereas the half is in $[-65520; 65520)$ (where did those 32 values go?) but doesn't need another multiplication to get to the &quot;real&quot; value.  Now the article says:&#xD;&#xA;&#xD;&#xA;&gt; Other people prefer 16-bit xNORM variants because they tend to give really good precision and it is evenly distributed.&#xD;&#xA;&#xD;&#xA;Why do they give a &quot;good precision&quot; and are &quot;evenly distributed&quot; (as opposed to the half)?&#xD;&#xA;&#xD;&#xA;2. For `snorm` a division is suggested, by either $64$ or the maximum AABB value. I get the latter, that can be used for more or less any model then, but why use the magic number $64$ if I don't want to calculate it? Is it common to have models that don't exceed this specific value?&#xD;&#xA;&#xD;&#xA;3. If I get good precision with `half` (or `xnorm` respectively) to save bandwidth, but in my application actually need really large position values, can I leverage the better precision of `xnorm` with a multiplication for &quot;full&quot; `float` and save myself from using  `double` variables?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.yosoygames.com.ar/wp/2018/03/vertex-formats-part-1-compression" ContentLicense="CC BY-SA 3.0" />
  <row Id="17881" PostHistoryTypeId="1" PostId="6374" RevisionGUID="223cd62c-55d0-437d-8d47-89ceff8c891e" CreationDate="2018-03-06T13:42:06.910" UserId="7008" Text="How to work with half and snorm" ContentLicense="CC BY-SA 3.0" />
  <row Id="17882" PostHistoryTypeId="3" PostId="6374" RevisionGUID="223cd62c-55d0-437d-8d47-89ceff8c891e" CreationDate="2018-03-06T13:42:06.910" UserId="7008" Text="|float|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17883" PostHistoryTypeId="2" PostId="6375" RevisionGUID="2640870d-3e12-47e4-ba31-c904c8e5133c" CreationDate="2018-03-06T16:43:26.390" UserId="2654" Text="&gt; According to the article, a half is basically a 16 bit float and an snorm is a signed float dividied by 65535. Therefore, they are basically the same&#xD;&#xA;&#xD;&#xA;No, they're not, and you do the article a great disservice by suggesting that it says such a thing.&#xD;&#xA;&#xD;&#xA;Yes, Half-floats are 16-bit floats. But they are *floating point numbers*, as [defined in IEEE-754][1]. Which means that they can express a relatively large range of values.&#xD;&#xA;&#xD;&#xA;[Normalized integers][2] can only directly express values in the range [0, 1] (for unsigned) and [-1, 1] (for signed). Floating-point numbers can extend beyond this range. [16-bit floats][3] can express numbers approximately on the range [-6.55*10&lt;sup&gt;4&lt;/sup&gt;, 6.55*10&lt;sup&gt;4&lt;/sup&gt;], and it can handle decimal values in-between them.&#xD;&#xA;&#xD;&#xA;&gt; Why do they give a &quot;good precision&quot; and are &quot;evenly distributed&quot; (as opposed to the half)?&#xD;&#xA;&#xD;&#xA;Because that's how IEEE-754 works. After all, normalized 16-bit values and 16-bit float values have the same size. 16-bits of storage gives you 65536 different values, no matter how you interpret them. Therefore, to get the range of values outside of [-1, 1], 16-bit floats sacrifice some bits to define additional values.&#xD;&#xA;&#xD;&#xA;16-bit floats give you about 3 decimal digits of precision. Normalized 16-bit values give you approximately 5.&#xD;&#xA;&#xD;&#xA;&gt; why use the magic number 64 if I don't want to calculate it?&#xD;&#xA;&#xD;&#xA;No reason; it's just a made-up number.&#xD;&#xA;&#xD;&#xA;&gt; Is it common to have models that don't exceed this specific value?&#xD;&#xA;&#xD;&#xA;Not particularly.&#xD;&#xA;&#xD;&#xA;&gt; If I get good precision with half (or xnorm respectively) to save bandwidth, but in my application actually need really large position values, can I leverage the better precision of xnorm with a multiplication for &quot;full&quot; float and save myself from using double variables?&#xD;&#xA;&#xD;&#xA;No.&#xD;&#xA;&#xD;&#xA;Generally speaking, model space positions do not *need* &quot;really large position values&quot;. They're in model space, so they're generally expressed relative to a center position that's quite close to them. They don't really have to be in scale with the rest of the world either.&#xD;&#xA;&#xD;&#xA;However, if your model space positions really do need &quot;really large position values&quot;, then you have to use whatever gives you the precision you need. That's pretty much never `double`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/IEEE_754&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Normalized_Integer&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Small_Float_Formats" ContentLicense="CC BY-SA 3.0" />
  <row Id="17884" PostHistoryTypeId="5" PostId="6373" RevisionGUID="c90f8532-32bd-4d26-a2d8-b92b900c22ba" CreationDate="2018-03-06T16:54:20.603" UserId="8325" Comment="added 100 characters in body" Text="Given a 3D model, is there a way to [stereographically project][1] it to a 2D image? In particular, I would only need a little more than half the model (the lower half) to be mapped to the plane (mapping the whole 3D model would be impossible, since the stereographic projection is infinite).&#xD;&#xA;&#xD;&#xA;I am using Linux, if that makes any difference. Also, I would prefer to use free software.&#xD;&#xA;&#xD;&#xA;(Note: If I could increase the viewing angle, I could do this with most any 3D viewing software, since the stereographic projection is just the view from a certain point with a wide viewing angle.)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stereographic_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17885" PostHistoryTypeId="5" PostId="6373" RevisionGUID="6e34576b-bf86-4d07-b6c1-c92a178b982a" CreationDate="2018-03-06T18:18:30.817" UserId="8325" Comment="added 95 characters in body" Text="Given a 3D model, is there a way to [stereographically project][1] it to a 2D image? In particular, I would only need a little more than half the model (the lower half) to be mapped to the plane (mapping the whole 3D model would be impossible, since the stereographic projection is infinite).&#xD;&#xA;&#xD;&#xA;I am using Linux, if that makes any difference. Also, I would prefer to use free software.&#xD;&#xA;&#xD;&#xA;(Note: If I could increase the viewing angle, I could do this with most any 3D viewing software, since the stereographic projection is just the view from a certain point with a wide viewing angle. In particular, I was able to get a small portion of the stereographic projection from meshlab.)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stereographic_projection" ContentLicense="CC BY-SA 3.0" />
  <row Id="17886" PostHistoryTypeId="5" PostId="6375" RevisionGUID="932c6659-5674-40fc-8674-b2cc0c538ba4" CreationDate="2018-03-06T18:57:15.493" UserId="2654" Comment="added 98 characters in body" Text="&gt; According to the article, a half is basically a 16 bit float and an snorm is a signed float dividied by 65535. Therefore, they are basically the same&#xD;&#xA;&#xD;&#xA;No, they're not, and you do the article a great disservice by suggesting that it says such a thing.&#xD;&#xA;&#xD;&#xA;Yes, Half-floats are 16-bit floats. But they are *floating point numbers*, as [defined in IEEE-754][1]. Which means that they can express a relatively large range of values.&#xD;&#xA;&#xD;&#xA;[Normalized integers][2] can only directly express values in the range [0, 1] (for unsigned) and [-1, 1] (for signed). Floating-point numbers can extend beyond this range. [16-bit floats][3] can express numbers approximately on the range [-6.55*10&lt;sup&gt;4&lt;/sup&gt;, 6.55*10&lt;sup&gt;4&lt;/sup&gt;], and it can handle decimal values in-between them.&#xD;&#xA;&#xD;&#xA;&gt; Why do they give a &quot;good precision&quot; and are &quot;evenly distributed&quot; (as opposed to the half)?&#xD;&#xA;&#xD;&#xA;Because that's how IEEE-754 works. After all, normalized 16-bit values and 16-bit float values have the same size. 16-bits of storage gives you 65536 different values, no matter how you interpret them. Therefore, to get the range of values outside of [-1, 1], 16-bit floats sacrifice some bits to define additional values.&#xD;&#xA;&#xD;&#xA;16-bit floats give you about 3 decimal digits of precision. Normalized 16-bit values give you at most 5 (though the closer to zero you get, the fewer significant digits you get, unlike floating-point values).&#xD;&#xA;&#xD;&#xA;&gt; why use the magic number 64 if I don't want to calculate it?&#xD;&#xA;&#xD;&#xA;No reason; it's just a made-up number.&#xD;&#xA;&#xD;&#xA;&gt; Is it common to have models that don't exceed this specific value?&#xD;&#xA;&#xD;&#xA;Not particularly.&#xD;&#xA;&#xD;&#xA;&gt; If I get good precision with half (or xnorm respectively) to save bandwidth, but in my application actually need really large position values, can I leverage the better precision of xnorm with a multiplication for &quot;full&quot; float and save myself from using double variables?&#xD;&#xA;&#xD;&#xA;No.&#xD;&#xA;&#xD;&#xA;Generally speaking, model space positions do not *need* &quot;really large position values&quot;. They're in model space, so they're generally expressed relative to a center position that's quite close to them. They don't really have to be in scale with the rest of the world either.&#xD;&#xA;&#xD;&#xA;However, if your model space positions really do need &quot;really large position values&quot;, then you have to use whatever gives you the precision you need. That's pretty much never `double`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/IEEE_754&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Normalized_Integer&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Small_Float_Formats" ContentLicense="CC BY-SA 3.0" />
  <row Id="17888" PostHistoryTypeId="5" PostId="6177" RevisionGUID="c26dba8c-8039-4344-8416-f2fcf706ad0b" CreationDate="2018-03-06T22:12:10.657" UserDisplayName="user7220" Comment="Corrected indents.. Corrected comments.." Text="I want to create a histogram of intensities 0.1, 0.2, .... 0.9, 1, from an image rendered using OpenGL and C++. How can I do this? Can I access the pixel intensities in the framebuffer somehow? Also, I'm not using any glsl shaders, and don't intend to.&#xD;&#xA;&#xD;&#xA;So far I tried:&#xD;&#xA;&#xD;&#xA;    unsigned char *framebuffer = frameBuffer = new unsigned char[1920*1080 * 4];&#xD;&#xA;&#xD;&#xA;    glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);&#xD;&#xA;&#xD;&#xA;    for (int j = 0; j&lt;1920*1080 * 4; j += 4){&#xD;&#xA;        if(frameBuffer[j] == 0.1)&#xD;&#xA;            // find pixel with R channel at 0.1: this is where the problem is.&#xD;&#xA;            // I know I have surfaces with this intensity but I never enter the if statement&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="17889" PostHistoryTypeId="24" PostId="6177" RevisionGUID="c26dba8c-8039-4344-8416-f2fcf706ad0b" CreationDate="2018-03-06T22:12:10.657" Comment="Proposed by 7220 approved by 48, 5183 edit id of 354" ContentLicense="CC BY-SA 3.0" />
  <row Id="17891" PostHistoryTypeId="5" PostId="5189" RevisionGUID="74d75e30-0efc-407e-bebf-b1fd14199b16" CreationDate="2018-03-07T02:57:52.767" UserDisplayName="user7220" Comment="Corrected links.." Text="This is the complex number version of refraction, were K is the extinction coefficient. This is commonly used for metals.&#xD;&#xA;&#xD;&#xA;You can check the Wikipedia on refraction:  [Complex refractive index | Wikipedia][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Refractive_index#Complex_refractive_index" ContentLicense="CC BY-SA 3.0" />
  <row Id="17892" PostHistoryTypeId="24" PostId="5189" RevisionGUID="74d75e30-0efc-407e-bebf-b1fd14199b16" CreationDate="2018-03-07T02:57:52.767" Comment="Proposed by 7220 approved by 48, 3073 edit id of 359" ContentLicense="CC BY-SA 3.0" />
  <row Id="17893" PostHistoryTypeId="5" PostId="3687" RevisionGUID="87fa006f-2cdf-4331-8fb1-2e6c34637f8b" CreationDate="2018-03-07T02:58:00.457" UserDisplayName="user7220" Comment="Corrected links.." Text="What you probably need is this 4 x 4 matrix:&#xD;&#xA;&#xD;&#xA;$$\mathtt{T} = \begin{bmatrix}1 &amp; 0 &amp; 0 &amp; 0\\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1 \\  \end{bmatrix}$$&#xD;&#xA;which is flipping the z-axis. The inverse of this particular matrix is the matrix itself:&#xD;&#xA;$\mathtt{T}^{-1} = \mathtt{T}$&#xD;&#xA;&#xD;&#xA;For 3D points $\mathbf{x}$ multiply it from the left:&#xD;&#xA;$$\mathbf{x}' = \mathtt{T}\,\, \mathbf{x}$$&#xD;&#xA;and for 3D transformations multiply it from the right:&#xD;&#xA;$$\mathtt{P}' = \mathtt{P} \,\,\mathtt{T}$$&#xD;&#xA;&#xD;&#xA;Thus, you have not changed anything in the projection because:&#xD;&#xA;$$\mathtt{P}'\,\,\mathbf{x}' = \mathtt{P} \,\,\mathtt{T} \, \,\mathtt{T}\,\,  \mathbf{x} =  \mathtt{P} \,\,(\mathtt{T}^{-1} \, \,\mathtt{T})\,\,  \mathbf{x} = \mathtt{P}\,\,\mathbf{x}$$&#xD;&#xA;&#xD;&#xA;Quaternions $q=(s,x,y,z)^\top$ could be convert into &#xD;&#xA;a 3D transformation matrix with:&#xD;&#xA;&#xD;&#xA;$$\mathtt{P} = \begin{bmatrix} 1-2y^2-2z^2 &amp; 2xy-2sz&amp; 2xz+2ys &amp; 0\\ &#xD;&#xA;              2xy+2sz &amp; 1-2x^2-2z^2&amp; 2yz-2sx &amp; 0\\ &#xD;&#xA;              2xz-2sy &amp; 2yz+2sx&amp; 1-2x^2-2y^2 &amp; 0\\  0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}$$&#xD;&#xA;and could then be treated like other 3D transformations.&#xD;&#xA;&#xD;&#xA;However, 3D engines typically apply transformation in a transformation hierarchy. If this is the case, make sure you are only modifying the 3D transformation &quot;closest&quot; to the 3D point in the hierarchy.&#xD;&#xA;&#xD;&#xA;Sources:&#xD;&#xA;[Graphics Programming I - 3D Transformations | Thorsten Thormählen][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/graphics_5_2_eng_web.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="17894" PostHistoryTypeId="24" PostId="3687" RevisionGUID="87fa006f-2cdf-4331-8fb1-2e6c34637f8b" CreationDate="2018-03-07T02:58:00.457" Comment="Proposed by 7220 approved by 48, 3073 edit id of 358" ContentLicense="CC BY-SA 3.0" />
  <row Id="17895" PostHistoryTypeId="5" PostId="6028" RevisionGUID="f4d02900-9d38-42d2-bcc1-bd49bebf4e59" CreationDate="2018-03-07T02:58:04.523" UserDisplayName="user7220" Comment="Corrected links.." Text="Given shapes like these, which contain just Arcs and lines, I want to round all its corners with certain radius. I know the vertices of the lines &amp; arcs these shapes.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I can round the corners of a polygon (when two lines meet to form a corner), but can't figure out how to round a corner formed by an Arc and a Line.&#xD;&#xA;&#xD;&#xA;I used this post to round the corners of polygon:&#xD;&#xA;&#xD;&#xA;[Algorithm for creating rounded corners in a polygon | Stack Overflow][2]&#xD;&#xA;&#xD;&#xA;Could you please share a code snippet, or just explain/list the math/algorithm behind achieving this? Thanks!&#xD;&#xA;&#xD;&#xA;PS: I'm developing a CAD drawing generator using C# &amp; .netDxf library&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/F1Hlh.png&#xD;&#xA;  [2]: https://stackoverflow.com/questions/24771828/algorithm-for-creating-rounded-corners-in-a-polygon" ContentLicense="CC BY-SA 3.0" />
  <row Id="17896" PostHistoryTypeId="24" PostId="6028" RevisionGUID="f4d02900-9d38-42d2-bcc1-bd49bebf4e59" CreationDate="2018-03-07T02:58:04.523" Comment="Proposed by 7220 approved by 48, 3073 edit id of 355" ContentLicense="CC BY-SA 3.0" />
  <row Id="17897" PostHistoryTypeId="2" PostId="6376" RevisionGUID="b5f0771d-6123-4f33-8f56-1cf30d933b73" CreationDate="2018-03-07T05:54:56.653" UserId="2654" Text="There is no such function. Given the context of the text, it is almost certainly referring to `glTextureSubImage*`." ContentLicense="CC BY-SA 3.0" />
  <row Id="17898" PostHistoryTypeId="5" PostId="6374" RevisionGUID="9ebc0f8c-983b-4220-a513-63d22b13d306" CreationDate="2018-03-07T06:52:00.537" UserId="7008" Comment="edited a missleading assumption for future readers" Text="I have just come across [this article about half, snorm and unorm][1], but I don't get some of the points (or why they work).&#xD;&#xA;&#xD;&#xA; 1. According to the article, a `half` is basically a 16 bit float and an `snorm` is a signed &lt;s&gt;float&lt;/s&gt; integer$^1$ dividied by `65535`. Therefore, they are basically the same, just that the snorm is represented in $[-1, 1]$ whereas the half is in $[-65520; 65520)$ (where did those 32 values go?) but doesn't need another multiplication to get to the &quot;real&quot; value.  Now the article says:&#xD;&#xA;&#xD;&#xA;&gt; Other people prefer 16-bit xNORM variants because they tend to give really good precision and it is evenly distributed.&#xD;&#xA;&#xD;&#xA;Why do they give a &quot;good precision&quot; and are &quot;evenly distributed&quot; (as opposed to the half)?&#xD;&#xA;&#xD;&#xA;2. For `snorm` a division is suggested, by either $64$ or the maximum AABB value. I get the latter, that can be used for more or less any model then, but why use the magic number $64$ if I don't want to calculate it? Is it common to have models that don't exceed this specific value?&#xD;&#xA;&#xD;&#xA;3. If I get good precision with `half` (or `xnorm` respectively) to save bandwidth, but in my application actually need really large position values, can I leverage the better precision of `xnorm` with a multiplication for &quot;full&quot; `float` and save myself from using  `double` variables?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA; $^1$ Edit for future readers. I wrongly assumed it was a float.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.yosoygames.com.ar/wp/2018/03/vertex-formats-part-1-compression" ContentLicense="CC BY-SA 3.0" />
  <row Id="17903" PostHistoryTypeId="5" PostId="6076" RevisionGUID="cc399c02-6e4b-4930-8fb8-32efb8a433b7" CreationDate="2018-03-07T11:54:23.580" UserDisplayName="user7220" Comment="Corrected links.." Text="A rotation around the x-axis is achieved by this matrix&#xD;&#xA;$$&#xD;&#xA;\mathtt{T}_\mathrm{rot X} = \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \\ 0&amp; \cos \alpha&#xD;&#xA;            &amp; -\sin \alpha&amp; 0 \\ 0 &amp; \sin \alpha &amp; \cos \alpha &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp;1 \\ \end{bmatrix} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In order to rotate around the x-axis in the viewing space, one needs to think about when to apply the above transformation in the chain of transformations that is applied to the 3D model vertices $\mathbf{X}_{\mathrm{3d}}$ in the employed rendering pipeline.&#xD;&#xA;&#xD;&#xA;A typical transformation chain is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{camera\ transform}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Let's split the camera tranformation into its rotational and translational part:&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\underbrace{\mathtt{T}_{\mathrm{cam\ trans}}\,\mathtt{T}_{\mathrm{cam\ rot}}}_{\mathtt{T}_{\mathrm{camera\ transform}}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then we need to apply the x-rotation in-between the camera rotation and translation, because we want to have the rotation of the camera applied beforehand, but not the camera's translation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\underbrace{\mathtt{T}_{\mathrm{cam\ trans}}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}}_{\mathtt{T}_{\mathrm{new\ camera\ transform}}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This would achieve the desired rotation, but typically we do not want to change the camera transformation but the the mesh transformation. This is achieved by&#xD;&#xA;$$&#xD;&#xA;\mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{cam\ trans}}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}\\&#xD;&#xA;\Leftrightarrow \mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{cam\ trans}}\,(\mathtt{T}_{\mathrm{cam\ rot}}\,\mathtt{T}_{\mathrm{cam\ rot}}^{-1})\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}\,\mathbf{X}_{\mathrm{3d}}\\&#xD;&#xA;\Leftrightarrow \mathbf{X}_{\mathrm{view}} = \mathtt{T}_{\mathrm{projection}} \,\mathtt{T}_{\mathrm{camera\ transform}}\,\underbrace{\mathtt{T}_{\mathrm{cam\ rot}}^{-1}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}\,&#xD;&#xA;\mathtt{T}_{\mathrm{mesh\ transform}}}_{\mathtt{T}_{\mathrm{new\ mesh\ transform}}}\,\mathbf{X}_{\mathrm{3d}}&#xD;&#xA;$$&#xD;&#xA;**Therefore, the short answer to your question is:**&#xD;&#xA; &#xD;&#xA;Left-multiply the current transformation matrix of your model with $\mathtt{T}_{\mathrm{cam\ rot}}^{-1}\,\mathtt{T}_\mathrm{rot X}\,\mathtt{T}_{\mathrm{cam\ rot}}$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have generated an &quot;cow&quot; example scene in the GSN Composer that can be used for interactive testing in a WebGL-capable browser:&#xD;&#xA;&#xD;&#xA;[Example: CowQuestion | GSN Composer][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/plks2.png&#xD;&#xA;  [2]: https://www.gsn-lib.org/docs/gallery.php?projectName=CowQuestion&amp;graphName=cow" ContentLicense="CC BY-SA 3.0" />
  <row Id="17904" PostHistoryTypeId="24" PostId="6076" RevisionGUID="cc399c02-6e4b-4930-8fb8-32efb8a433b7" CreationDate="2018-03-07T11:54:23.580" Comment="Proposed by 7220 approved by 48, 209 edit id of 357" ContentLicense="CC BY-SA 3.0" />
  <row Id="17905" PostHistoryTypeId="5" PostId="6032" RevisionGUID="5ec04f04-72b3-475e-8f5e-25c8ebbee709" CreationDate="2018-03-07T11:54:31.937" UserDisplayName="user7220" Comment="Corrected links.." Text="Eye position, projection reference point PRP, camera center, or projection center are all just different words for the same thing. &#xD;&#xA;&#xD;&#xA;gluLookAt() applied to the GL_MODELVIEW matrix works for both, parallel and perspective projection.&#xD;&#xA;&#xD;&#xA;You can choose between parallel and perspective projection by setting up the GL_PROJECTION matrix. For perspective projection this can be done using the gluPerspective() function.&#xD;&#xA;&#xD;&#xA;[Creating a perspective projection matrix in OpenGL][1]&#xD;&#xA;&#xD;&#xA;**Edit: (after revised question)**&#xD;&#xA;&#xD;&#xA;If the PRP is not at the eye position, you can not use gluPerspective(). Instead you have to create your own GL_PROJECTION matrix. Following the formula that you have now provided, this results in the 4 x 4 matrix:&#xD;&#xA;&#xD;&#xA;$$\mathtt{A} =\begin{bmatrix} z_c-z_{pp} &amp; 0 &amp; -x_c &amp;  x_c \cdot z_{pp}\\ 0  &amp; z_c-z_{pp}  &amp; -y_c &amp; y_c \cdot z_{pp} \\ 0 &amp; 0 &amp; \frac{\mathrm{far}+\mathrm{near}}{\mathrm{near}-\mathrm{far}} &amp; \frac{2 \cdot \mathrm{far} \cdot \mathrm{near}}{\mathrm{near}-\mathrm{far}} \\ 0 &amp; 0 &amp; -1 &amp; z_c \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I have done a quick OpenGL/WebGL rendering test with the GSN Composer. Follow the link and move the mouse over the render output to change $x_c$ and $y_c$ of the projection reference point $(x_c, y_c, z_c)$:&#xD;&#xA;&#xD;&#xA;[Example: ProjectionReferencePoint | GSN Composer][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/graphics_6_1_eng_web.html#19&#xD;&#xA;  [2]: https://www.gsn-lib.org/docs/gallery.php?projectName=ProjRefPoint&amp;graphName=ProjectionReferencePoint" ContentLicense="CC BY-SA 3.0" />
  <row Id="17906" PostHistoryTypeId="24" PostId="6032" RevisionGUID="5ec04f04-72b3-475e-8f5e-25c8ebbee709" CreationDate="2018-03-07T11:54:31.937" Comment="Proposed by 7220 approved by 48, 209 edit id of 356" ContentLicense="CC BY-SA 3.0" />
  <row Id="17907" PostHistoryTypeId="2" PostId="6378" RevisionGUID="cb4c2fd0-f288-4d1f-b577-069d3c0284ac" CreationDate="2018-03-07T11:59:08.563" UserId="8242" Text="I implemented a simulation for the colour of the sky a while ago by following the scratch a pixel tutorial: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky&#xD;&#xA;&#xD;&#xA;I adapted it for the actual sun position and am able to get realistic sky colours during the day. However, I noticed that after sunset/ before sunrise, the colours are greyish when they should be deep blue. After researching about this, I read that this is due to the ozone absorption not being present in my model.&#xD;&#xA;&#xD;&#xA;I used extinction coefficients : (3.426,8.298,0.356) * 0.06e-5 -&gt; found on https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016-pbs-frostbite-sky-clouds-new.pdf&#xD;&#xA;&#xD;&#xA;and also read that since the ozone does not scatter, it should only be added to the transmittance value.&#xD;&#xA;&#xD;&#xA;[![more info about ozone][1]][1] &#xD;&#xA;&#xD;&#xA;Therefore, I modified the code from scratchapixel as follows:&#xD;&#xA;&#xD;&#xA;    		for (uint32_t i = 0; i &lt; numSamples; ++i) {&#xD;&#xA;    			vec3 samplePosition = ray_in2.origin() + (tCurrent + &#xD;&#xA;                segmentLength * 0.5f) * ray_in2.direction();&#xD;&#xA;    			float height = samplePosition.length() - atmosphere.earthRadius;&#xD;&#xA;    			&#xD;&#xA;    			// compute optical depth for light&#xD;&#xA;    			float hr = exp(-height / atmosphere.Hr) * segmentLength;&#xD;&#xA;    			float hm = exp(-height / atmosphere.Hm) * segmentLength;&#xD;&#xA;    			float ho = exp(-height / atmosphere.Hr)* segmentLength*(6e-7);&#xD;&#xA;    			opticalDepthR += hr;&#xD;&#xA;    			opticalDepthM += hm;&#xD;&#xA;    			opticalDepthO += ho;&#xD;&#xA;    &#xD;&#xA;    			// light optical depth&#xD;&#xA;    			float t0Light, t1Light;&#xD;&#xA;    &#xD;&#xA;        			...&#xD;&#xA;    			for (j = 0; j &lt; numSamplesLight; ++j) {&#xD;&#xA;    				vec3 samplePositionLight = samplePosition + (tCurrentLight + &#xD;&#xA;                    segmentLengthLight * 0.5f) * sunDir;&#xD;&#xA;    				float heightLight = samplePositionLight.length() - &#xD;&#xA;                    atmosphere.earthRadius;&#xD;&#xA;    				&#xD;&#xA;    				if (heightLight &lt; 0) break;&#xD;&#xA;    				opticalDepthLightR += exp(-heightLight / atmosphere.Hr) * &#xD;&#xA;                    segmentLengthLight;&#xD;&#xA;    				opticalDepthLightM += exp(-heightLight / atmosphere.Hm) * &#xD;&#xA;                    segmentLengthLight;&#xD;&#xA;    				opticalDepthLightO += exp(-heightLight / atmosphere.Hr) * &#xD;&#xA;                    segmentLengthLight*(6e-7); ;&#xD;&#xA;    				tCurrentLight += segmentLengthLight;&#xD;&#xA;    			}&#xD;&#xA;    			if (j == numSamplesLight) {&#xD;&#xA;    				vec3 tau = (betaR) * (opticalDepthR + opticalDepthLightR) + &#xD;&#xA;                   betaM * 1.1f * (opticalDepthM + opticalDepthLightM)+ betaO*&#xD;&#xA;                  (opticalDepthO + opticalDepthLightO);&#xD;&#xA;    				vec3 attenuation(exp(-tau.x()), exp(-tau.y()), exp(-&#xD;&#xA;                    tau.z()));&#xD;&#xA;		&#xD;&#xA;  summary : &#xD;&#xA;-I added variable opticalDepthO and opticalDepthLightO which are calculated same as the optical depth for Rayleigh, but multiplied by 6e-7. &#xD;&#xA;&#xD;&#xA;-Then, the sum of opticalDepthLightO and opticalDepthO is multiplied by the extiction coefficient for ozone and added to variable tau.&#xD;&#xA;&#xD;&#xA;Problem is, I see no difference in my sky colour before and after adding ozone. Can someone guide me to what it is that I'm doing wrong? Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cAiJu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="17908" PostHistoryTypeId="1" PostId="6378" RevisionGUID="cb4c2fd0-f288-4d1f-b577-069d3c0284ac" CreationDate="2018-03-07T11:59:08.563" UserId="8242" Text="Adding Ozone to my sky simulation" ContentLicense="CC BY-SA 3.0" />
  <row Id="17909" PostHistoryTypeId="3" PostId="6378" RevisionGUID="cb4c2fd0-f288-4d1f-b577-069d3c0284ac" CreationDate="2018-03-07T11:59:08.563" UserId="8242" Text="|c++|scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17910" PostHistoryTypeId="2" PostId="6379" RevisionGUID="c44bcc6a-9ab2-423a-af93-9ba46f9f258c" CreationDate="2018-03-07T15:38:18.230" UserId="8325" Text="Using blender, you can position the camera at the north pole of the sphere you are stereographically projecting, and then set a really wide [field of view][1]. For example, I had to set my focal length to around 5 mm to get a hemisphere in the stereographic projection, but it will depend on the model, of course. Then simply render and you're done!&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.blender.org/manual/en/dev/render/cycles/camera.html#perspective" ContentLicense="CC BY-SA 3.0" />
  <row Id="17914" PostHistoryTypeId="2" PostId="6381" RevisionGUID="48771787-34c4-4892-a322-26a510fa1d24" CreationDate="2018-03-07T22:11:50.263" UserId="8335" Text="The solution that worked for me is compilation of shader code to C++ - as mentioned by Nobody. It prooved very efficient when working on a complex code even though it requires a bit of setup.&#xD;&#xA;&#xD;&#xA;I have been working mostly with HLSL Compute Shaders for which I have developed a proof-of-concept library available here:&#xD;&#xA;&#xD;&#xA;https://github.com/cezbloch/shaderator&#xD;&#xA;&#xD;&#xA;It demonstrates on a Compute Shader from DirectX SDK Samples, how to enable C++ like HLSL debugging and how to setup Unit Tests.&#xD;&#xA;&#xD;&#xA;Compilation of GLSL compute shader to C++ looks easier than HLSL. Mainly due to syntax constructions in HLSL. I have added a trivial example of executable Unit Test on a GLSL ray tracer Compute Shader which you can also find in the Shaderator project's sources under link above." ContentLicense="CC BY-SA 3.0" />
  <row Id="17915" PostHistoryTypeId="2" PostId="6382" RevisionGUID="fdd55c36-ff60-49dd-94c4-104eec4001cf" CreationDate="2018-03-08T01:29:58.833" UserId="7957" Text="If instead of stereographic projection you can use other conformal projection. I would recommend you the &quot;Least Squares Conformal Maps&quot; algorithm. There are several implementations out there, including the prominent CGAL (https://doc.cgal.org/latest/Surface_mesh_parameterization/index.html)." ContentLicense="CC BY-SA 3.0" />
  <row Id="17917" PostHistoryTypeId="2" PostId="6383" RevisionGUID="264874d1-ce61-47ea-9b78-0b8faefe7721" CreationDate="2018-03-08T03:35:33.607" UserId="8191" Text="I am reading a model from an obj file and draw it using glDrawElements. For some reasons, only a small part of it is drawn, even though I dont even have back-face culling turned on. &#xD;&#xA;    &#xD;&#xA;    // vertices &#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;	float * objectGeometry = scene.objects[k].verticesAsFloatArray();&#xD;&#xA;	glVertexAttribPointer(0, 4, GL_FLOAT, 0, 0, objectGeometry);&#xD;&#xA;&#xD;&#xA;    // normals&#xD;&#xA;	glEnableVertexAttribArray(1);&#xD;&#xA;	float * objectNormals = scene.objects[k].normalsAsFloatArray();&#xD;&#xA;	glVertexAttribPointer(1, 3, GL_FLOAT, 0, 0, objectNormals);&#xD;&#xA;    &#xD;&#xA;    // indices&#xD;&#xA;	int * indices = scene.objects[k].facesAsIndiceArray();&#xD;&#xA;	glDrawElements(GL_TRIANGLES, scene.objects[k].vertices.size(), GL_UNSIGNED_INT, indices);" ContentLicense="CC BY-SA 3.0" />
  <row Id="17918" PostHistoryTypeId="1" PostId="6383" RevisionGUID="264874d1-ce61-47ea-9b78-0b8faefe7721" CreationDate="2018-03-08T03:35:33.607" UserId="8191" Text="What is wrong with my glDrawElement code" ContentLicense="CC BY-SA 3.0" />
  <row Id="17919" PostHistoryTypeId="3" PostId="6383" RevisionGUID="264874d1-ce61-47ea-9b78-0b8faefe7721" CreationDate="2018-03-08T03:35:33.607" UserId="8191" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17920" PostHistoryTypeId="6" PostId="6383" RevisionGUID="4f64de10-7bac-4a88-9dd1-09d2d305b1f8" CreationDate="2018-03-08T04:53:50.150" UserId="2654" Comment="edited tags" Text="|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17925" PostHistoryTypeId="2" PostId="6384" RevisionGUID="99ae3457-fa24-4fcc-9ce5-4559b17407bf" CreationDate="2018-03-08T14:38:27.463" UserId="7724" Text="[glDrawElements](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElements.xhtml) specifies the second argument to be the number of elements to be taken from the buffer of indices, not the number of vertices. The correct number would be the number of triangles times three." ContentLicense="CC BY-SA 3.0" />
  <row Id="17926" PostHistoryTypeId="50" PostId="6218" RevisionGUID="b8fd1fc3-184f-42fc-b469-df68e426e7fb" CreationDate="2018-03-08T14:59:22.957" UserId="-1" />
  <row Id="17927" PostHistoryTypeId="2" PostId="6385" RevisionGUID="fcabb272-ed26-4b83-b914-a2cfb80b7f4d" CreationDate="2018-03-08T17:04:57.583" UserId="6541" Text="I drew simple [triangle wave](https://en.wikipedia.org/wiki/Triangle_wave) (that you can see this shape on [graph toy](http://www.iquilezles.org/apps/graphtoy/)).&#xD;&#xA;&#xD;&#xA;![triangle wave](https://user-images.githubusercontent.com/16706911/37163629-80fb47c2-230d-11e8-9210-736648fb74a4.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       f1(x) = frac(x/(PI+5))*(PI+5)&#xD;&#xA;       f2(x) = frac(-x/(PI+5))*(PI+5)&#xD;&#xA;       f3(x) = min(f1(x),f2(x))*1.5&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;I want to change above shape like [Approximating Pi](https://www.desmos.com/calculator/hmcutwfumj) and repeat It periodically along horizontal axis.&#xD;&#xA;&#xD;&#xA;![Approximating Pi](https://user-images.githubusercontent.com/16706911/37164290-167419cc-230f-11e8-9e65-75aca83d33c5.gif)&#xD;&#xA;&#xD;&#xA;then I want to cut negative parts of the vertical axis:&#xD;&#xA;&#xD;&#xA;![image](https://user-images.githubusercontent.com/16706911/36645755-be8cd206-1a82-11e8-9046-dd2923095e16.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17928" PostHistoryTypeId="1" PostId="6385" RevisionGUID="fcabb272-ed26-4b83-b914-a2cfb80b7f4d" CreationDate="2018-03-08T17:04:57.583" UserId="6541" Text="How can I draw periodic Approximating Pi along the horizontal axis?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17929" PostHistoryTypeId="3" PostId="6385" RevisionGUID="fcabb272-ed26-4b83-b914-a2cfb80b7f4d" CreationDate="2018-03-08T17:04:57.583" UserId="6541" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17930" PostHistoryTypeId="2" PostId="6386" RevisionGUID="e85d3175-3a32-463d-b099-9a37c1b5ea18" CreationDate="2018-03-08T18:56:51.097" UserId="8130" Text="My problem is about tangent plane. I have an image (m by n). I obtain surface normal vector using machine learning methods. Then i would like to obtain tangent plane for this surface normal.&#xD;&#xA;&#xD;&#xA;To imagine my problem, you can look this paper; [Surface Normals in the Wild][1]. In this paper, authors find surface normal and draw/find virtual tangent plane around this point (Figure 4 in above paper).&#xD;&#xA;&#xD;&#xA;For this problem, i have really no idea. Any tips or starter idea will be acceptable.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/abs/1704.02956" ContentLicense="CC BY-SA 3.0" />
  <row Id="17931" PostHistoryTypeId="1" PostId="6386" RevisionGUID="e85d3175-3a32-463d-b099-9a37c1b5ea18" CreationDate="2018-03-08T18:56:51.097" UserId="8130" Text="Tanget plane of an image" ContentLicense="CC BY-SA 3.0" />
  <row Id="17932" PostHistoryTypeId="3" PostId="6386" RevisionGUID="e85d3175-3a32-463d-b099-9a37c1b5ea18" CreationDate="2018-03-08T18:56:51.097" UserId="8130" Text="|transformations|image-processing|computational-geometry|geometry|image|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17933" PostHistoryTypeId="50" PostId="6225" RevisionGUID="464ed1b4-e6a4-4a2c-bfab-2fae449a0d7a" CreationDate="2018-03-08T20:03:25.027" UserId="-1" />
  <row Id="17934" PostHistoryTypeId="50" PostId="5697" RevisionGUID="4c5f7256-a2be-4cd8-9ea3-8a8a3e116e80" CreationDate="2018-03-08T22:05:23.770" UserId="-1" />
  <row Id="17935" PostHistoryTypeId="2" PostId="6387" RevisionGUID="6e16459f-2795-40cf-9a51-f91fedb5cb14" CreationDate="2018-03-09T03:11:53.570" UserId="8345" Text="I was looking at the [Mantle API documentation](https://www.amd.com/Documents/Mantle-Programming-Guide-and-API-Reference.pdf) and noticed that everything is prefixed with &quot;gr&quot;, but it's never explained why the functions are prefixed with it and the letters &quot;gr&quot; do not appear anywhere in the name Mantle.&#xD;&#xA;&#xD;&#xA;What does the prefix mean?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17936" PostHistoryTypeId="1" PostId="6387" RevisionGUID="6e16459f-2795-40cf-9a51-f91fedb5cb14" CreationDate="2018-03-09T03:11:53.570" UserId="8345" Text="Why are functions and structs in the Mantle API prefixed with &quot;gr&quot;?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17937" PostHistoryTypeId="3" PostId="6387" RevisionGUID="6e16459f-2795-40cf-9a51-f91fedb5cb14" CreationDate="2018-03-09T03:11:53.570" UserId="8345" Text="|api|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17938" PostHistoryTypeId="2" PostId="6388" RevisionGUID="3cdb3853-2266-48a2-a04e-708462b8b4f0" CreationDate="2018-03-09T03:23:31.073" UserId="3003" Text="You can use the equation of a circle to do this. A circle can be drawn using the equation:&#xD;&#xA;&#xD;&#xA;$r^2 = x^2 + y^2$&#xD;&#xA;&#xD;&#xA;You can solve for the upper half of this by rewriting it in terms of $y$ like this:&#xD;&#xA;&#xD;&#xA;$y^2 = r^2 - x^2$&#xD;&#xA;&#xD;&#xA;so&#xD;&#xA;&#xD;&#xA;$y = ±√(r^2 - x^2)$&#xD;&#xA;&#xD;&#xA;But we only want the positive half. So we say just:&#xD;&#xA;&#xD;&#xA;$y = √(r^2 - x^2)$&#xD;&#xA;&#xD;&#xA;You can then repeat it by using (((x - 2) % 4) - 2) as the input value. In the end the equation is this:&#xD;&#xA;&#xD;&#xA;$y = √(1^2 - (((x - 2) mod 4) - 2)^2)$&#xD;&#xA;&#xD;&#xA;It looks like this:&#xD;&#xA;&#xD;&#xA;[![semicircles][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/A1OgD.png&#xD;&#xA;&#xD;&#xA;In graph toy, it would be:&#xD;&#xA;&#xD;&#xA;    sqrt(1 - pow((((abs(x) - 2) % 4) - 2),2))&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17939" PostHistoryTypeId="5" PostId="6385" RevisionGUID="464f9cef-f854-472b-966d-6acf3a2bf801" CreationDate="2018-03-09T03:40:19.233" UserId="6541" Comment="deleted 4 characters in body" Text="I drew simple [triangle wave](https://en.wikipedia.org/wiki/Triangle_wave) (that you can see It on [graph toy](http://www.iquilezles.org/apps/graphtoy/)).&#xD;&#xA;&#xD;&#xA;![triangle wave](https://user-images.githubusercontent.com/16706911/37163629-80fb47c2-230d-11e8-9210-736648fb74a4.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       f1(x) = frac(x/(PI+5))*(PI+5)&#xD;&#xA;       f2(x) = frac(-x/(PI+5))*(PI+5)&#xD;&#xA;       f3(x) = min(f1(x),f2(x))*1.5&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;I want to change above shape like [Approximating Pi](https://www.desmos.com/calculator/hmcutwfumj) and repeat It periodically along the horizontal axis.&#xD;&#xA;&#xD;&#xA;![Approximating Pi](https://user-images.githubusercontent.com/16706911/37164290-167419cc-230f-11e8-9e65-75aca83d33c5.gif)&#xD;&#xA;&#xD;&#xA;then I want to cut negative parts of the vertical axis:&#xD;&#xA;&#xD;&#xA;![image](https://user-images.githubusercontent.com/16706911/36645755-be8cd206-1a82-11e8-9046-dd2923095e16.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17955" PostHistoryTypeId="2" PostId="6393" RevisionGUID="977f220e-6515-4066-abb7-1bea73e70d5e" CreationDate="2018-03-10T17:37:14.193" UserId="56" Text="These older but informative article talks about how a Kaiser windowed sinc filter is a good way to generate mips.&#xD;&#xA;&#xD;&#xA;http://number-none.com/product/Mipmapping,%20Part%201/index.html&#xD;&#xA;&#xD;&#xA;http://number-none.com/product/Mipmapping,%20Part%202/index.html&#xD;&#xA;&#xD;&#xA;Unfortunately, the source code it mentions isn't anywhere to be found.&#xD;&#xA;&#xD;&#xA;Can anyone explain how a kaiser windowed sinc filter is calculated and/or give the kernel weights to use for convolution?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17956" PostHistoryTypeId="1" PostId="6393" RevisionGUID="977f220e-6515-4066-abb7-1bea73e70d5e" CreationDate="2018-03-10T17:37:14.193" UserId="56" Text="Kaiser windowed sinc filter for mip mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="17957" PostHistoryTypeId="3" PostId="6393" RevisionGUID="977f220e-6515-4066-abb7-1bea73e70d5e" CreationDate="2018-03-10T17:37:14.193" UserId="56" Text="|texture|filtering|mipmap|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17962" PostHistoryTypeId="2" PostId="6395" RevisionGUID="d3bb9fee-67b6-4fc6-9653-1bf298cbd40d" CreationDate="2018-03-11T06:36:55.603" UserId="5048" Text="For example, I have two transform matrix: WVP_Left and WVP_Right.&#xD;&#xA;&#xD;&#xA;Can I render geometry (like a rabbit) using instancing to generate left texture and right texture?&#xD;&#xA;&#xD;&#xA;The left texture should just have only one rabbit with the WVP_Left effect, and the right texture should just have one rabbit with the WVP_Right effect.&#xD;&#xA;&#xD;&#xA;For now, I get two textures which both have 2 rabbit with some overlap part.&#xD;&#xA;&#xD;&#xA;How can I fix it?&#xD;&#xA;&#xD;&#xA;I don't want to render the left and right scene into one texture, and split it to 2 texture in another pass.&#xD;&#xA;&#xD;&#xA;Also, I don't want to use geometry shader and layered rendering to finish the thing, because geometry shader will add the workload of GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="17963" PostHistoryTypeId="1" PostId="6395" RevisionGUID="d3bb9fee-67b6-4fc6-9653-1bf298cbd40d" CreationDate="2018-03-11T06:36:55.603" UserId="5048" Text="How can I use instancing to generate 2 single different texture?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17964" PostHistoryTypeId="3" PostId="6395" RevisionGUID="d3bb9fee-67b6-4fc6-9653-1bf298cbd40d" CreationDate="2018-03-11T06:36:55.603" UserId="5048" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17965" PostHistoryTypeId="2" PostId="6396" RevisionGUID="28d10a57-2992-4ef0-ae4c-506e8fc61c92" CreationDate="2018-03-11T12:01:01.020" UserId="2041" Text="No, this is the opposite of what instancing is for. Instancing lets you have multiple copies of the same geometry in one viewport. In your case, it would let you render into one FBO to have one texture containing multiple rabbits. To generate two separate textures, you need to do two render passes, one for each FBO. If the geometry is the same in both cases and only the transform is different, you don't need to send the geometry to the GPU twice, so it's pretty fast." ContentLicense="CC BY-SA 3.0" />
  <row Id="17966" PostHistoryTypeId="2" PostId="6397" RevisionGUID="cd7ee353-fdea-404a-93c1-42afb8e56ffa" CreationDate="2018-03-11T13:23:33.390" UserId="7334" Text="Where's this algorithm come from? Any references?&#xD;&#xA;&#xD;&#xA;And a specific question, when the authors compute the transformation from world space to ray-triangle intersection coordinate space, what's the **permutation** step for?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17967" PostHistoryTypeId="1" PostId="6397" RevisionGUID="cd7ee353-fdea-404a-93c1-42afb8e56ffa" CreationDate="2018-03-11T13:23:33.390" UserId="7334" Text="What is the algorithm used in pbrt-v3 for triangle intersection?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17968" PostHistoryTypeId="3" PostId="6397" RevisionGUID="cd7ee353-fdea-404a-93c1-42afb8e56ffa" CreationDate="2018-03-11T13:23:33.390" UserId="7334" Text="|raytracing|transformations|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17970" PostHistoryTypeId="5" PostId="6395" RevisionGUID="0e75ea3b-0288-49a5-8194-8c329c9a3198" CreationDate="2018-03-12T00:25:13.447" UserId="5048" Comment="[Edit removed during grace period]" Text="For example, I have two transform matrix: WVP_Left and WVP_Right.&#xD;&#xA;&#xD;&#xA;Can I render geometry (like a rabbit) using instancing to generate left texture and right texture?&#xD;&#xA;&#xD;&#xA;The left texture should just have only one rabbit with the WVP_Left effect, and the right texture should just have one rabbit with the WVP_Right effect.&#xD;&#xA;&#xD;&#xA;For now, I get two textures which both have 2 rabbit with some overlap part.&#xD;&#xA;&#xD;&#xA;How can I fix it?&#xD;&#xA;&#xD;&#xA;I don't want to render the left and right scene into one texture, and split it to 2 texture in another pass.&#xD;&#xA;&#xD;&#xA;Also, I don't want to use geometry shader and layered rendering to finish the thing, because geometry shader will add the workload of GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="17971" PostHistoryTypeId="5" PostId="6395" RevisionGUID="311908f2-fb66-4bee-b86d-87e7936b21ae" CreationDate="2018-03-12T02:20:01.680" UserId="5048" Comment="deleted 22 characters in body" Text="For example, I have two transform matrix: WVP_Left and WVP_Right.&#xD;&#xA;&#xD;&#xA;Can I render geometry (like a rabbit) using instancing to generate left texture and right texture?&#xD;&#xA;&#xD;&#xA;The left texture should just have only one rabbit with the WVP_Left effect, and the right texture should just have one rabbit with the WVP_Right effect.&#xD;&#xA;&#xD;&#xA;For now, I get two textures which both have 2 rabbit with some overlap part.&#xD;&#xA;&#xD;&#xA;How can I fix it?&#xD;&#xA;&#xD;&#xA;I don't want to render the left and right scene into one texture, and split it to 2 texture in another pass.&#xD;&#xA;&#xD;&#xA;Also, I don't want to use geometry shader to finish the thing, because geometry shader will add the workload of GPU" ContentLicense="CC BY-SA 3.0" />
  <row Id="17973" PostHistoryTypeId="4" PostId="6385" RevisionGUID="6f6056b8-71b7-47ee-9c28-d9c77c799c97" CreationDate="2018-03-12T07:02:13.437" UserId="6541" Comment="edited title" Text="How can I draw regular polygon along the horizontal axis?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17974" PostHistoryTypeId="5" PostId="6385" RevisionGUID="02364d55-b845-4066-b1d0-f242a703e5c4" CreationDate="2018-03-12T07:26:59.540" UserId="6541" Comment="edited title" Text="I drew simple [triangle wave](https://en.wikipedia.org/wiki/Triangle_wave) (that you can see It on [graph toy](http://www.iquilezles.org/apps/graphtoy/)).&#xD;&#xA;&#xD;&#xA;![triangle wave](https://user-images.githubusercontent.com/16706911/37163629-80fb47c2-230d-11e8-9210-736648fb74a4.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       f1(x) = frac(x/(PI+5))*(PI+5)&#xD;&#xA;       f2(x) = frac(-x/(PI+5))*(PI+5)&#xD;&#xA;       f3(x) = min(f1(x),f2(x))*1.5&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;I want to change above shape like [Approximating Pi](https://www.desmos.com/calculator/hmcutwfumj) and repeat It periodically along the horizontal axis.&#xD;&#xA;&#xD;&#xA;![Approximating Pi](https://user-images.githubusercontent.com/16706911/37164290-167419cc-230f-11e8-9e65-75aca83d33c5.gif)&#xD;&#xA;&#xD;&#xA;then I want to cut negative parts of the vertical axis:&#xD;&#xA;&#xD;&#xA;![image](https://user-images.githubusercontent.com/16706911/36645755-be8cd206-1a82-11e8-9046-dd2923095e16.png)&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;note that I know how can I draw It by shader In [ShaderToy](https://www.shadertoy.com/view/XsVyzR).I Just need drawing mathematics In desmos or graphtoy,because I want Extract values of wave.I want create polygon [wave form](https://en.wikipedia.org/wiki/Waveform).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17975" PostHistoryTypeId="6" PostId="6385" RevisionGUID="02364d55-b845-4066-b1d0-f242a703e5c4" CreationDate="2018-03-12T07:26:59.540" UserId="6541" Comment="edited title" Text="|glsl|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17976" PostHistoryTypeId="5" PostId="6385" RevisionGUID="187ddf25-cb5a-4fc1-8f35-d3dc5dd8e72d" CreationDate="2018-03-12T07:34:18.177" UserId="6541" Comment="added 135 characters in body" Text="I drew simple [triangle wave](https://en.wikipedia.org/wiki/Triangle_wave) (that you can see It on [graph toy](http://www.iquilezles.org/apps/graphtoy/)).&#xD;&#xA;&#xD;&#xA;![triangle wave](https://user-images.githubusercontent.com/16706911/37163629-80fb47c2-230d-11e8-9210-736648fb74a4.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       f1(x) = frac(x/(PI+5))*(PI+5)&#xD;&#xA;       f2(x) = frac(-x/(PI+5))*(PI+5)&#xD;&#xA;       f3(x) = min(f1(x),f2(x))*1.5&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;I want to change above shape like [Approximating Pi](https://www.desmos.com/calculator/hmcutwfumj) and repeat It periodically along the horizontal axis.&#xD;&#xA;&#xD;&#xA;![Approximating Pi](https://user-images.githubusercontent.com/16706911/37164290-167419cc-230f-11e8-9e65-75aca83d33c5.gif)&#xD;&#xA;&#xD;&#xA;then I want to cut negative parts of the vertical axis:&#xD;&#xA;&#xD;&#xA;![image](https://user-images.githubusercontent.com/16706911/36645755-be8cd206-1a82-11e8-9046-dd2923095e16.png)&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;Note that I know how can I draw It by shader In [ShaderToy](https://www.shadertoy.com/view/XsVyzR).I Just need drawing mathematics In desmos or graphtoy,because I want Extract values of wave.I want to create polygon [wave form](https://en.wikipedia.org/wiki/Waveform).&#xD;&#xA;&#xD;&#xA;I drew Periodic shape that I want to change the number of polygons&#xD;&#xA;[Desoms Link][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/gh7fmcrbys" ContentLicense="CC BY-SA 3.0" />
  <row Id="17977" PostHistoryTypeId="6" PostId="6385" RevisionGUID="187ddf25-cb5a-4fc1-8f35-d3dc5dd8e72d" CreationDate="2018-03-12T07:34:18.177" UserId="6541" Comment="added 135 characters in body" Text="|mathematics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17978" PostHistoryTypeId="4" PostId="6385" RevisionGUID="187ddf25-cb5a-4fc1-8f35-d3dc5dd8e72d" CreationDate="2018-03-12T07:34:18.177" UserId="6541" Comment="added 135 characters in body" Text="How can I draw regular polygons along the horizontal axis?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17979" PostHistoryTypeId="2" PostId="6399" RevisionGUID="87f29f95-61d6-4857-980a-80f476ba3629" CreationDate="2018-03-12T10:42:31.793" UserId="8360" Text="Consider something like the following for webgl (untested but should work):&#xD;&#xA;&#xD;&#xA;    const lookup = new Map();&#xD;&#xA;    const isEqual3fv = (v1, v2) =&gt; {&#xD;&#xA;     return v1[0] === v2[0] &amp;&amp; v1[1] === v2[1] &amp;&amp; v1[2] === v2[2];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const setUniform3fv = (location, value) =&gt; {&#xD;&#xA;      if(!lookup.has(location) || !isEqual3fv(lookup.get(location), value)) {&#xD;&#xA;        gl.uniform3fv(location, value);&#xD;&#xA;        lookup.set(location, value);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Would this be an optimization in most cases? Is caching the values and comparing for equality before setting the uniform generally a worthwhile optimization - or is the difference pretty negligible?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17980" PostHistoryTypeId="1" PostId="6399" RevisionGUID="87f29f95-61d6-4857-980a-80f476ba3629" CreationDate="2018-03-12T10:42:31.793" UserId="8360" Text="Is it worth caching uniform values?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17981" PostHistoryTypeId="3" PostId="6399" RevisionGUID="87f29f95-61d6-4857-980a-80f476ba3629" CreationDate="2018-03-12T10:42:31.793" UserId="8360" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17982" PostHistoryTypeId="2" PostId="6400" RevisionGUID="cead2dd4-4126-4b6a-88af-f4e28dd23ff9" CreationDate="2018-03-12T13:09:41.907" UserId="5717" Text="I was curious so I tried it. I used the [Kaiser Window][1] from Wikipedia: $\frac{I_0\left(\alpha\sqrt{1-x^2}\right)}{I_0\left(\alpha\right)}$&#xD;&#xA;&#xD;&#xA;[This page][2] has a slightly different formulation using $\pi\alpha$ instead of $\alpha$. Given the comments in the page you linked about the Kaiser window being very similar to Lanczos and how they even overlap in the graph, I suspect they also used the former formula. You can see how close they are if you [plot both on Wolfram][3].&#xD;&#xA;&#xD;&#xA;This left me wondering if that's what Mitchell originally meant as it's not &quot;noticably better&quot;. I could not see the difference at all with my test texture (it's there, just not noticeable). However, using the second formula, the difference in the [plots][4] is much more striking. And there is a noticeable difference in the resulting images. Whether it's better is a matter of interpretation and depends on the filter size.&#xD;&#xA;&#xD;&#xA;With $x \in \left[-1,1\right]$ , I used this C++ windowing function:&#xD;&#xA;&#xD;&#xA;    #include &lt;boost/math/special_functions/bessel.hpp&gt;&#xD;&#xA;    float bessel_i0( float x )&#xD;&#xA;    {&#xD;&#xA;        return boost::math::cyl_bessel_i( 0, x );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float window_kaiser( float x )&#xD;&#xA;    {&#xD;&#xA;        const float alpha = 4.0f * M_PI;&#xD;&#xA;        float k =&#xD;&#xA;            bessel_i0( alpha * sqrtf( 1.0f - x * x ) ) /&#xD;&#xA;            bessel_i0( alpha );&#xD;&#xA;        return k;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is the second version. Remove the `M_PI` to get the first version which is more like Lanczos.&#xD;&#xA;&#xD;&#xA;The modified Bessel function of the first kind seems to be a C++17 / boost thing. If you have neither, this quick hack will do:&#xD;&#xA;&#xD;&#xA;    float bessel_i0( float x )&#xD;&#xA;    {&#xD;&#xA;        float r = 1.0f;&#xD;&#xA;        float term = 1.0f;&#xD;&#xA;        for( int k = 1; true; ++k )&#xD;&#xA;        {&#xD;&#xA;            float f = x / float(k);&#xD;&#xA;            term *= 0.25f * f * f;&#xD;&#xA;            float new_r = r + term;&#xD;&#xA;            if( new_r == r )&#xD;&#xA;                break;&#xD;&#xA;            r = new_r;&#xD;&#xA;        }&#xD;&#xA;        return r;&#xD;&#xA;    }&#xD;&#xA;Just don't consider that a general replacement for a proper bessel function. However, it's fine for computing the window as far as I could tell.&#xD;&#xA;&#xD;&#xA;As the second wikipedia page I linked shows, that `window_kaiser` can be used on a filter with $N$ weights by using $x = \frac{2n}{N-1}-1$, where $n$ is $0, 1, 2 \dots N-1$.&#xD;&#xA;&#xD;&#xA;Computing the weights of the sinc filter itself is another thing entirely as it depends on filter size, how much you're resizing, etc. I suggest posting a separate question if you don't know how do to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Kaiser_window&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Window_function#Kaiser_window&#xD;&#xA;  [3]: http://www.wolframalpha.com/input/?i=plot+I_0(4*sqrt(1-x%5E2))%2FI_0(4),+sin(PI*x)%2F(PI*x),+x%3D0+to+1&#xD;&#xA;  [4]: http://www.wolframalpha.com/input/?i=plot%20I_0(PI*4*sqrt(1-x%5E2))%2FI_0(PI*4),%20sin(PI*x)%2F(PI*x),%20x%3D0%20to%201&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17983" PostHistoryTypeId="5" PostId="6400" RevisionGUID="763db114-3661-4790-8078-58ae2cc916c8" CreationDate="2018-03-12T13:14:47.820" UserId="5717" Comment="specified that formula is good for a symmetric filter only" Text="I was curious so I tried it. I used the [Kaiser Window][1] from Wikipedia: $\frac{I_0\left(\alpha\sqrt{1-x^2}\right)}{I_0\left(\alpha\right)}$&#xD;&#xA;&#xD;&#xA;[This page][2] has a slightly different formulation using $\pi\alpha$ instead of $\alpha$. Given the comments in the page you linked about the Kaiser window being very similar to Lanczos and how they even overlap in the graph, I suspect they also used the former formula. You can see how close they are if you [plot both on Wolfram][3].&#xD;&#xA;&#xD;&#xA;This left me wondering if that's what Mitchell originally meant as it's not &quot;noticably better&quot;. I could not see the difference at all with my test texture (it's there, just not noticeable). However, using the second formula, the difference in the [plots][4] is much more striking. And there is a noticeable difference in the resulting images. Whether it's better is a matter of interpretation and depends on the filter size.&#xD;&#xA;&#xD;&#xA;With $x \in \left[-1,1\right]$ , I used this C++ windowing function:&#xD;&#xA;&#xD;&#xA;    #include &lt;boost/math/special_functions/bessel.hpp&gt;&#xD;&#xA;    float bessel_i0( float x )&#xD;&#xA;    {&#xD;&#xA;        return boost::math::cyl_bessel_i( 0, x );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float window_kaiser( float x )&#xD;&#xA;    {&#xD;&#xA;        const float alpha = 4.0f * M_PI;&#xD;&#xA;        float k =&#xD;&#xA;            bessel_i0( alpha * sqrtf( 1.0f - x * x ) ) /&#xD;&#xA;            bessel_i0( alpha );&#xD;&#xA;        return k;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is the second version. Remove the `M_PI` to get the first version which is more like Lanczos.&#xD;&#xA;&#xD;&#xA;The modified Bessel function of the first kind seems to be a C++17 / boost thing. If you have neither, this quick hack will do:&#xD;&#xA;&#xD;&#xA;    float bessel_i0( float x )&#xD;&#xA;    {&#xD;&#xA;        float r = 1.0f;&#xD;&#xA;        float term = 1.0f;&#xD;&#xA;        for( int k = 1; true; ++k )&#xD;&#xA;        {&#xD;&#xA;            float f = x / float(k);&#xD;&#xA;            term *= 0.25f * f * f;&#xD;&#xA;            float new_r = r + term;&#xD;&#xA;            if( new_r == r )&#xD;&#xA;                break;&#xD;&#xA;            r = new_r;&#xD;&#xA;        }&#xD;&#xA;        return r;&#xD;&#xA;    }&#xD;&#xA;Just don't consider that a general replacement for a proper bessel function. However, it's fine for computing the window as far as I could tell.&#xD;&#xA;&#xD;&#xA;As the second wikipedia page I linked shows, that `window_kaiser` can be used on a symmetric filter with $N$ weights by using $x = \frac{2n}{N-1}-1$, where $n$ is $0, 1, 2 \dots N-1$.&#xD;&#xA;&#xD;&#xA;Computing the weights of the sinc filter itself is another thing entirely as it depends on filter size, how much you're resizing, etc. I suggest posting a separate question if you don't know how do to that.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Kaiser_window&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Window_function#Kaiser_window&#xD;&#xA;  [3]: http://www.wolframalpha.com/input/?i=plot+I_0(4*sqrt(1-x%5E2))%2FI_0(4),+sin(PI*x)%2F(PI*x),+x%3D0+to+1&#xD;&#xA;  [4]: http://www.wolframalpha.com/input/?i=plot%20I_0(PI*4*sqrt(1-x%5E2))%2FI_0(PI*4),%20sin(PI*x)%2F(PI*x),%20x%3D0%20to%201&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="17987" PostHistoryTypeId="2" PostId="6402" RevisionGUID="247e267c-f355-42eb-8dfc-30b30116abd1" CreationDate="2018-03-13T00:11:11.723" UserId="7462" Text="I am attempting to code a simple spring mass system simulation in which a sphere pendulus hangs from a string (a spring) by the top and then another sphere (controlled by the user) can move and interact (collide) with this hanging sphere.&#xD;&#xA;&#xD;&#xA;I have already coded the dynamics of the spring part of the simulation, but I do not know enough to add the rigid body dynamics. I would like either an explanation or a source to understand how to algorithmicaly do this simulation." ContentLicense="CC BY-SA 3.0" />
  <row Id="17988" PostHistoryTypeId="1" PostId="6402" RevisionGUID="247e267c-f355-42eb-8dfc-30b30116abd1" CreationDate="2018-03-13T00:11:11.723" UserId="7462" Text="Simplify kinematics and dynamics of a sphere in a spring mass system?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17989" PostHistoryTypeId="3" PostId="6402" RevisionGUID="247e267c-f355-42eb-8dfc-30b30116abd1" CreationDate="2018-03-13T00:11:11.723" UserId="7462" Text="|physically-based|animation|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17990" PostHistoryTypeId="4" PostId="6402" RevisionGUID="1c8579d3-bf47-4914-b0d2-601d44e59d70" CreationDate="2018-03-13T00:16:36.620" UserId="7462" Comment="edited title" Text="kinematics and dynamics of a sphere in a spring mass system?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17991" PostHistoryTypeId="2" PostId="6403" RevisionGUID="1f5b0b5f-de1f-4e2e-baf2-c70d57d9c101" CreationDate="2018-03-13T02:51:10.990" UserId="1614" Text="Can we cut bandwidth by `N` (for `N×MSAA`) if we access only one slice of a multisampled texture in a shader ?&#xD;&#xA;&#xD;&#xA;I'm thinking of doing a manual resolve in a shader, because some targets may make no sense to average. e.g. depth, encoded normals, IDs..  &#xD;&#xA;&#xD;&#xA;Unfortunately, the memory layout may be so that MSAA slices are close in memory which means that a fetch nearby would cache the whole line.&#xD;&#xA;&#xD;&#xA;A solution to get an answer would be to measure the performance difference of accessing all slices vs 1. But I suppose there are no guarantees of repetition across hardware ?" ContentLicense="CC BY-SA 3.0" />
  <row Id="17992" PostHistoryTypeId="1" PostId="6403" RevisionGUID="1f5b0b5f-de1f-4e2e-baf2-c70d57d9c101" CreationDate="2018-03-13T02:51:10.990" UserId="1614" Text="Texture2DMS slice access and bandwidth saving" ContentLicense="CC BY-SA 3.0" />
  <row Id="17993" PostHistoryTypeId="3" PostId="6403" RevisionGUID="1f5b0b5f-de1f-4e2e-baf2-c70d57d9c101" CreationDate="2018-03-13T02:51:10.990" UserId="1614" Text="|directx11|" ContentLicense="CC BY-SA 3.0" />
  <row Id="17994" PostHistoryTypeId="5" PostId="5665" RevisionGUID="5bff1ab6-c35c-4c48-b685-6c7d9a159c15" CreationDate="2018-03-13T10:54:25.730" UserId="6" Comment="edited body" Text="It has been suggested in comments repeatedly, but noone felt the need to give a proper answer, so for the sake of completeness, a straight-forward and common solution to this problem might be to use a **texture as lookup table, specifically a 1D texture that contains all the values of your function for the possible input range** (i.e. $[0,360)$ / $[0,2\pi)$). This has various advantages:&#xD;&#xA;&#xD;&#xA;- It uses normalized coordinates, i.e. you access the texture by mapping your angles from $[0,360]$ to $[0,1]$. This means your **shader doesn't actually have to care about the specific amount of values**. You can adjust its size according to whatever memory/speed vs. quality tradeoff you want (and especially on older/embedded hardware you might want a power of two as texture size anyway).&#xD;&#xA;- You get the additional benefit of not having to do your loop-like interval adjustment (although, you wouldn't need loops anyway and could just use a modulus operation). Just use **`GL_REPEAT` as wrapping mode for the texture and it will automatically start at the beginning again** when accessing with arguments &gt; 1 (and similarly for negative arguments).&#xD;&#xA;- And you also get the benefit of **linearly interpolating between two values in the array** basically for free (or let's say almost free) by using `GL_LINEAR` as texture filter, this way getting values you didn't even store. Of course linear interpolation isn't 100% accurate for trigonometric functions, but it's certainly better than *no* interpolation.&#xD;&#xA;- You can store **more than one value in the texture** by using an RGBA texture (or however many components you need). This way you can get e.g. sin and cos with a single texture lookup.&#xD;&#xA;- For sin and cos you only need to store values in $[-1,1]$ anyway, which you can naturally upscale from the normalized $[0,1]$ range of a common 8-bit fixed-point format. However, that might not be enough precision for your needs. Some people suggested using 16-bit floating point values, as they're more precise than the usual 8-bit normalized fixed point values but less memory intensive than real 32-bit floats. But then again, I also don't know if your implementation supports floating point textures to begin with. If not, then maybe you can use 2 8-bit fixed point components and combine them into a single value with something like `float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;` (or even more components for finer grain). This lets you profit from multi-component textures yet again.&#xD;&#xA;&#xD;&#xA;Of course it still has to be evaluated if this is a better solution, since texture access isn't *entirely* free either, as well as what the best combination of texture size and format would be.&#xD;&#xA;&#xD;&#xA;As to filling the texture with data and adressing one of your comments, you have to consider that texture filtering returns the exact value at the *texel center*, i.e. a texture coordinate off by half the texel size. So yes, you should **generate values at `.5` texels**, i.e. something like this in application code:&#xD;&#xA;&#xD;&#xA;    float texels[256];&#xD;&#xA;    for(unsigned int i = 0; i &lt; 256; ++i)&#xD;&#xA;        texels[i] = sin((i + .5f) / 256.f) * TWO_PI);&#xD;&#xA;    glTexImage1D(GL_TEXTURE_1D, 0, ..., 256, 0, GL_RED, GL_FLOAT, texels);&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;You might, however, still want to compare this approach's performance against an approach using a small uniform array (i.e. `uniform float sinTable[361]`, or maybe less in practice, keep an eye on your implementation's limit on uniform array size) which you just load with the respective values using `glUniform1fv` and access by adjustig your angle to $[0,360)$ using the `mod` function and rounding it to the nearest value:&#xD;&#xA;&#xD;&#xA;    angle = mod(angle, 360.0);&#xD;&#xA;    float value = sinTable[int(((angle &lt; 0.0) ? (angle + 360.0) : angle) + 0.5)];" ContentLicense="CC BY-SA 3.0" />
  <row Id="17995" PostHistoryTypeId="34" PostId="6348" RevisionGUID="7e70d45b-9c7c-44a5-b808-3f3e73ffadf1" CreationDate="2018-03-13T13:21:10.640" UserId="-1" Comment="44" />
  <row Id="17999" PostHistoryTypeId="2" PostId="6405" RevisionGUID="9a480d3b-bc52-4a94-bd6d-1d4bcdcf816c" CreationDate="2018-03-13T17:50:58.540" UserId="120" Text="The permutation is described in section 3.6.2, page 158-159.&#xD;&#xA;&#xD;&#xA;A reason behind this permutation is that a shear matrix (which involves dividing z component of ray direction) is computed to transform from world space to ray triangle intersection coordinate space.&#xD;&#xA;Permuting the coordinates is to avoid divide-by-0 error by mapping nonzero component to +z." ContentLicense="CC BY-SA 3.0" />
  <row Id="18000" PostHistoryTypeId="50" PostId="4632" RevisionGUID="181cdebf-8bf9-4a08-8837-83602c630aca" CreationDate="2018-03-13T22:23:17.953" UserId="-1" />
  <row Id="18001" PostHistoryTypeId="2" PostId="6406" RevisionGUID="56b0fe71-96ed-46af-87ae-65085949abfa" CreationDate="2018-03-13T23:01:17.403" UserId="8369" Text="Good day,&#xD;&#xA;&#xD;&#xA;I need to identify certain topological entities (circular holes) in a given geometry, that is, given the boundary representation of a solid, I need to identify the exact coordinates of all holes in the solid. I have been told to use a topological sweep, yet the information available is not clear to me as in how it fits in the solution of such problem. Does anyone have a recommendation or more information about what exactly is a topological sweep?.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="18002" PostHistoryTypeId="1" PostId="6406" RevisionGUID="56b0fe71-96ed-46af-87ae-65085949abfa" CreationDate="2018-03-13T23:01:17.403" UserId="8369" Text="Topological Sweep" ContentLicense="CC BY-SA 3.0" />
  <row Id="18003" PostHistoryTypeId="3" PostId="6406" RevisionGUID="56b0fe71-96ed-46af-87ae-65085949abfa" CreationDate="2018-03-13T23:01:17.403" UserId="8369" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18004" PostHistoryTypeId="2" PostId="6407" RevisionGUID="0780e032-89f6-4265-a9ec-3cf170dd45bf" CreationDate="2018-03-14T13:58:36.110" UserId="8371" Text="[I asked this on Graphic Design][2] but was unable to get any relevant help from them.&#xD;&#xA;&#xD;&#xA;I'm trying to reverse engineer a blending mode I've seen [on a picture][1]:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/xQnci.jpg&quot; width=&quot;270&quot; height=&quot;160&quot;&gt; &#xD;&#xA;&#xD;&#xA;This image was created by someone else using *Adobe's Scene7* during a *Displacement Map Filter* operation. **I'm only interested in the blending mechanism, not the distortion**. &#xD;&#xA;&#xD;&#xA;Unfortunately, I was unable to reproduce this effect on other raster graphics editors. It almost looks like the images were blended with *Multiply* followed by a recolor operation of some sort. Anyway, I'm trying to figure out the equation used for this type of blending.&#xD;&#xA;&#xD;&#xA;If you look at the top left corner of where the images overlap, you can see just a little bit of the background leaking to the foreground image.&#xD;&#xA;&#xD;&#xA;The original images have the same dimensions and can be found below:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/U4AM4.jpg&quot; width=&quot;180&quot; height=&quot;270&quot;&gt;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KKgjQ.jpg&quot; width=&quot;180&quot; height=&quot;270&quot;&gt;&#xD;&#xA;&#xD;&#xA;Any idea on how to duplicate this effect?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uJS8R.png&#xD;&#xA;  [2]: https://graphicdesign.stackexchange.com/q/106742/116486" ContentLicense="CC BY-SA 3.0" />
  <row Id="18005" PostHistoryTypeId="1" PostId="6407" RevisionGUID="0780e032-89f6-4265-a9ec-3cf170dd45bf" CreationDate="2018-03-14T13:58:36.110" UserId="8371" Text="What blend mode is this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="18006" PostHistoryTypeId="3" PostId="6407" RevisionGUID="0780e032-89f6-4265-a9ec-3cf170dd45bf" CreationDate="2018-03-14T13:58:36.110" UserId="8371" Text="|shader|image-processing|blending|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18007" PostHistoryTypeId="2" PostId="6408" RevisionGUID="acad0f74-81c9-492b-acdf-00ef092055e2" CreationDate="2018-03-14T17:08:41.387" UserId="6406" Text="I've been working on writing functions for 5 and 6 dimensional simplex noise, working off [FastNoise's 4D function](https://github.com/Auburns/FastNoise/blob/master/FastNoise.cpp#L1340) as a base. 2D, 3D and 4D noise all follow a very similar and recognizable pattern which can be easily extended to higher dimensions, however the output isn't looking so great:&#xD;&#xA;&#xD;&#xA;[![5D Simplex Noise with visible artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Visible diagonal areas (lines) where values are all very similar, as well as diamond shapes where values don't blend together. (Does that count as discontinuous?)&#xD;&#xA;&#xD;&#xA;The full 5D Noise function is:&#xD;&#xA;&#xD;&#xA;    static const FN_DECIMAL F5 = (sqrt(FN_DECIMAL(6)) - 1) / 5;&#xD;&#xA;    static const FN_DECIMAL G5 = (6 - sqrt(FN_DECIMAL(6))) / 30;&#xD;&#xA;    &#xD;&#xA;    FN_DECIMAL FastNoise::SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w, FN_DECIMAL v) const&#xD;&#xA;    {&#xD;&#xA;      FN_DECIMAL n0, n1, n2, n3, n4, n5;&#xD;&#xA;      FN_DECIMAL t = (x + y + z + w + v) * F5;&#xD;&#xA;      int i = FastFloor(x + t);&#xD;&#xA;      int j = FastFloor(y + t);&#xD;&#xA;      int k = FastFloor(z + t);&#xD;&#xA;      int l = FastFloor(w + t);&#xD;&#xA;      int h = FastFloor(v + t);&#xD;&#xA;      t = (i + j + k + l + h) * G5;&#xD;&#xA;      FN_DECIMAL X0 = i - t;&#xD;&#xA;      FN_DECIMAL Y0 = j - t;&#xD;&#xA;      FN_DECIMAL Z0 = k - t;&#xD;&#xA;      FN_DECIMAL W0 = l - t;&#xD;&#xA;      FN_DECIMAL V0 = h - t;&#xD;&#xA;      FN_DECIMAL x0 = x - X0;&#xD;&#xA;      FN_DECIMAL y0 = y - Y0;&#xD;&#xA;      FN_DECIMAL z0 = z - Z0;&#xD;&#xA;      FN_DECIMAL w0 = w - W0;&#xD;&#xA;      FN_DECIMAL v0 = v - V0;&#xD;&#xA;    &#xD;&#xA;      int rankx = 0;&#xD;&#xA;      int ranky = 0;&#xD;&#xA;      int rankz = 0;&#xD;&#xA;      int rankw = 0;&#xD;&#xA;      int rankv = 0;&#xD;&#xA;    &#xD;&#xA;      if (x0 &gt; y0) rankx++; else ranky++;&#xD;&#xA;      if (x0 &gt; z0) rankx++; else rankz++;&#xD;&#xA;      if (x0 &gt; w0) rankx++; else rankw++;&#xD;&#xA;      if (x0 &gt; v0) rankx++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      if (y0 &gt; z0) ranky++; else rankz++;&#xD;&#xA;      if (y0 &gt; w0) ranky++; else rankw++;&#xD;&#xA;      if (y0 &gt; v0) ranky++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      if (z0 &gt; w0) rankz++; else rankw++;&#xD;&#xA;      if (z0 &gt; v0) rankz++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      if (w0 &gt; v0) rankw++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      int i1 = rankx &gt;= 4 ? 1 : 0;&#xD;&#xA;      int j1 = ranky &gt;= 4 ? 1 : 0;&#xD;&#xA;      int k1 = rankz &gt;= 4 ? 1 : 0;&#xD;&#xA;      int l1 = rankw &gt;= 4 ? 1 : 0;&#xD;&#xA;      int h1 = rankv &gt;= 4 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      int i2 = rankx &gt;= 3 ? 1 : 0;&#xD;&#xA;      int j2 = ranky &gt;= 3 ? 1 : 0;&#xD;&#xA;      int k2 = rankz &gt;= 3 ? 1 : 0;&#xD;&#xA;      int l2 = rankw &gt;= 3 ? 1 : 0;&#xD;&#xA;      int h2 = rankv &gt;= 3 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      int i3 = rankx &gt;= 2 ? 1 : 0;&#xD;&#xA;      int j3 = ranky &gt;= 2 ? 1 : 0;&#xD;&#xA;      int k3 = rankz &gt;= 2 ? 1 : 0;&#xD;&#xA;      int l3 = rankw &gt;= 2 ? 1 : 0;&#xD;&#xA;      int h3 = rankv &gt;= 2 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      int i4 = rankx &gt;= 1 ? 1 : 0;&#xD;&#xA;      int j4 = ranky &gt;= 1 ? 1 : 0;&#xD;&#xA;      int k4 = rankz &gt;= 1 ? 1 : 0;&#xD;&#xA;      int l4 = rankw &gt;= 1 ? 1 : 0;&#xD;&#xA;      int h4 = rankv &gt;= 1 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x1 = x0 - i1 + G5;&#xD;&#xA;      FN_DECIMAL y1 = y0 - j1 + G5;&#xD;&#xA;      FN_DECIMAL z1 = z0 - k1 + G5;&#xD;&#xA;      FN_DECIMAL w1 = w0 - l1 + G5;&#xD;&#xA;      FN_DECIMAL v1 = v0 - h1 + G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x2 = x0 - i2 + 2*G5;&#xD;&#xA;      FN_DECIMAL y2 = y0 - j2 + 2*G5;&#xD;&#xA;      FN_DECIMAL z2 = z0 - k2 + 2*G5;&#xD;&#xA;      FN_DECIMAL w2 = w0 - l2 + 2*G5;&#xD;&#xA;      FN_DECIMAL v2 = v0 - h2 + 2*G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x3 = x0 - i3 + 3*G5;&#xD;&#xA;      FN_DECIMAL y3 = y0 - j3 + 3*G5;&#xD;&#xA;      FN_DECIMAL z3 = z0 - k3 + 3*G5;&#xD;&#xA;      FN_DECIMAL w3 = w0 - l3 + 3*G5;&#xD;&#xA;      FN_DECIMAL v3 = v0 - h3 + 3*G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x4 = x0 - i4 + 4*G5;&#xD;&#xA;      FN_DECIMAL y4 = y0 - j4 + 4*G5;&#xD;&#xA;      FN_DECIMAL z4 = z0 - k4 + 4*G5;&#xD;&#xA;      FN_DECIMAL w4 = w0 - l4 + 4*G5;&#xD;&#xA;      FN_DECIMAL v4 = v0 - h4 + 4*G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x5 = x0 - 1 + 5*G5;&#xD;&#xA;      FN_DECIMAL y5 = y0 - 1 + 5*G5;&#xD;&#xA;      FN_DECIMAL z5 = z0 - 1 + 5*G5;&#xD;&#xA;      FN_DECIMAL w5 = w0 - 1 + 5*G5;&#xD;&#xA;      FN_DECIMAL v5 = v0 - 1 + 5*G5;&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.5) - x0*x0 - y0*y0 - z0*z0 - w0*w0 - v0*v0;&#xD;&#xA;      if (t &lt; 0) n0 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n0 = t*t * GradCoord5D(offset, i, j, k, l, h, x0, y0, z0, w0, v0);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.5) - x1*x1 - y1*y1 - z1*z1 - w1*w1 - v1*v1;&#xD;&#xA;      if (t &lt; 0) n1 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n1 = t*t * GradCoord5D(offset, i + i1, j + j1, k + k1, l + l1, h + h1, x1, y1, z1, w1, v1);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.5) - x2*x2 - y2*y2 - z2*z2 - w2*w2 - v2*v2;&#xD;&#xA;      if (t &lt; 0) n2 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n2 = t*t * GradCoord5D(offset, i + i2, j + j2, k + k2, l + l2, h + h2, x2, y2, z2, w2, v2);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.5) - x3*x3 - y3*y3 - z3*z3 - w3*w3 - v3*v3;&#xD;&#xA;      if (t &lt; 0) n3 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n3 = t*t * GradCoord5D(offset, i + i3, j + j3, k + k3, l + l3, h + h3, x3, y3, z3, w3, v3);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.5) - x4*x4 - y4*y4 - z4*z4 - w4*w4 - v4*v4;&#xD;&#xA;      if (t &lt; 0) n4 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n4 = t*t * GradCoord5D(offset, i + i4, j + j4, k + k4, l + l4, h + h4, x4, y4, z4, w4, v4);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.5) - x5*x5 - y5*y5 - z5*z5 - w4*w4 - v5*v5;&#xD;&#xA;      if (t &lt; 0) n5 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n5 = t * t * GradCoord5D(offset, i + 1, j + 1, k + 1, l + 1, h + 1, x5, y5, z5, w5, v5);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      return 8 * (n0 + n1 + n2 + n3 + n4 + n5); // TODO: Find value scaler&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;`GradCoord5` consists of:&#xD;&#xA;&#xD;&#xA;    inline FN_DECIMAL FastNoise::GradCoord5D(unsigned char offset, int x, int y, int z, int w, int v, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd, FN_DECIMAL wd, FN_DECIMAL vd) const&#xD;&#xA;    {&#xD;&#xA;      unsigned char lutPos = Index5D_80(offset, x, y, z, w, v) * 5;&#xD;&#xA;    &#xD;&#xA;      return xd * GRAD_5D[lutPos] + yd * GRAD_5D[lutPos + 1] + zd * GRAD_5D[lutPos + 2] + wd * GRAD_5D[lutPos + 3] + vd * GRAD_5D[lutPos + 4];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And `Index5D_80` consists of:&#xD;&#xA;&#xD;&#xA;    unsigned char FastNoise::Index5D_80(unsigned char offset, int x, int y, int z, int w, int v) const&#xD;&#xA;    {&#xD;&#xA;      return m_perm80[(x &amp; 0xff) + m_perm[(y &amp; 0xff) + m_perm[(z &amp; 0xff) + m_perm[(w &amp; 0xff) + m_perm[(v &amp; 0xff) + offset]]]]];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The array `GRAD_5D` is an array 400 items long, each 5 values representing a diagonal vector.&#xD;&#xA;The array `m_perm` is a 512 item long array of permutations, the values 0 to 255, in a random order, the second half of the array the same as the first half.&#xD;&#xA;The array `m_perm80` is also a 512 item long array, but the values of `m_perm` have been modulo'd by 80. (Because there are 80 gradients in `GRAD_5D`)&#xD;&#xA;&#xD;&#xA;Currently I'm not sure if the `FN_DECIMAL(0.5)`s should actually be `FN_DECIMAL(0.6)` as is seen in the 3D &amp; 4D simplex noise functions and [SimplexNoise.java](http://staffwww.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java) by Stefan Gustavson who wrote [Simplex noise demystified](http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf) in which he says the value should be changed to 0.5 (and yet doesn't do it in his own source code?). [Ken Perlin uses 0.6](https://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf) in his paper on Simplex Noise, but it's just a magic number which he doesn't explain the significance or origin of.&#xD;&#xA;&#xD;&#xA;I am also not sure if the `8` used to &quot;normalise&quot; the sum of the n components when returning the final value is correct, though it's doing a reasonable job of keeping the values within a usable range. &#xD;&#xA;&#xD;&#xA;I've puzzled over [this math stackexchange question](https://math.stackexchange.com/questions/474638/radius-and-amplitude-of-kernel-for-simplex-noise/1901116#1901116) which purports that the normalisation value should actually be [67.6953](https://www.wolframalpha.com/input/?i=1%2F((n%2Fsqrt(n%2B1))*(0.5-(n%2F(4*(n%2B1))))%5E4)+where+n%3D5).  That value does make the noise closer to 4D noise in its variation in values but causes some values to go beyond -1 and 1. It also makes the diagonal areas more obvious and the diamond artifacts clearer. &#xD;&#xA;&#xD;&#xA;[![Other normalisation factor, more obvious artifacts][2]][2]&#xD;&#xA;&#xD;&#xA;The normalisation factor doesn't seem to be the issue however, as it just brings the values in the -1 to 1 range.&#xD;&#xA;&#xD;&#xA;Whatever the `FN_DECIMAL(0.5)` value is officially called (I think it might be the spherical kernel radius, I can't find any hard proof), reducing it brings the values closer to 0 (effectively making the image flatter, because it makes it more likely that `t` will be less than 0 and therefore not use the contribution from that vertex). Ken Perlin does mention _&quot;the exact radius and amplitude of the hypersphere-shaped kernel centered at each simplex need to be tuned so as to produce the best visual results for each choice of n&quot;_, and indeed pushing the value up to `0.8` (and bringing the normalisation value down to 6) does produce a more appealing image however it doesn't get rid of the odd diamond shapes and the diagonals can still sort of be seen as the slightly fuzzier areas under the diamond artifacts.&#xD;&#xA;&#xD;&#xA;[![Changed radius, better but still artifacts][3]][3]&#xD;&#xA;&#xD;&#xA;What could be causing these artifacts? Is it an indexing issue perhaps? Something else?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WBMWx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/blPFq.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vph7s.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="18008" PostHistoryTypeId="1" PostId="6408" RevisionGUID="acad0f74-81c9-492b-acdf-00ef092055e2" CreationDate="2018-03-14T17:08:41.387" UserId="6406" Text="What might be causing these artifacts in 5D &amp; 6D simplex noise?" ContentLicense="CC BY-SA 3.0" />
  <row Id="18009" PostHistoryTypeId="3" PostId="6408" RevisionGUID="acad0f74-81c9-492b-acdf-00ef092055e2" CreationDate="2018-03-14T17:08:41.387" UserId="6406" Text="|noise|procedural-generation|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18010" PostHistoryTypeId="2" PostId="6409" RevisionGUID="7161358c-117b-4b2e-ae33-baffcd2da3fa" CreationDate="2018-03-14T18:54:37.533" UserId="8375" Text="I want to write (fragment) shaders in OpenCL rather than GLSL. Is there a standard mechanism for this (from OpenGL, and ideally also from DirectX)? Are there any drawbacks to doing this?&#xD;&#xA;&#xD;&#xA;I also want to write screenspace effects in OpenCL. Is the mechanism the same? Are there any drawbacks?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 3.0" />
  <row Id="18011" PostHistoryTypeId="1" PostId="6409" RevisionGUID="7161358c-117b-4b2e-ae33-baffcd2da3fa" CreationDate="2018-03-14T18:54:37.533" UserId="8375" Text="Writing OpenCL Shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="18012" PostHistoryTypeId="3" PostId="6409" RevisionGUID="7161358c-117b-4b2e-ae33-baffcd2da3fa" CreationDate="2018-03-14T18:54:37.533" UserId="8375" Text="|shader|opencl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18013" PostHistoryTypeId="2" PostId="6410" RevisionGUID="d484371b-dbf3-4ec9-949f-f871d30e5ee3" CreationDate="2018-03-14T22:37:54.450" UserId="2654" Text="&gt; geometry shader will add the workload of GPU&#xD;&#xA;&#xD;&#xA;*Everything* you're trying to do will &quot;add the workload of GPU&quot;. The only question that matters is how much.&#xD;&#xA;&#xD;&#xA;Your choices are:&#xD;&#xA;&#xD;&#xA;1. Redraw everything with different FBOs. You can't just use different `glDrawBuffers` settings, because you also need to change the depth buffers between the two draws.&#xD;&#xA;&#xD;&#xA;2. Use [layered rendering][1]. Your two textures would instead be one texture object with two array layers (the same for the depth texture). There are multiple ways of going about this:&#xD;&#xA;&#xD;&#xA;    1. Render the scene twice, using a `uniform` variable of some kind to determine which layer gets rendered to. This means having to read and execute the VS on all of the vertex data twice.&#xD;&#xA;    2. Render the scene once with [Instanced Rendering][2], using `gl_InstanceID` to determine which layer that particular rendering gets rendered to. This means having to read and execute the VS on all of the vertex data twice.&#xD;&#xA;    3. Render the scene with a Geometry Shader that spits out two triangles for each triangle it gets, one for each layer. This only reads the vertex data and executes the VS on it once.&#xD;&#xA;    4. Render the scene with [Geometry Shader instancing][3]. The GS will be executed twice for each primitive, with a different `gl_InvocationID` value specifying which instance the GS is being executed for. You use that ID to determine which layer to send the primitive to, as well as how to transform it. This only reads the vertex data and executes the VS on it once.&#xD;&#xA;&#xD;&#xA;All of the variations of layered rendering will require either a Geometry Shader or access to the ARB_shader_viewport_layer_array extension or the AMD_vertex_shader_layer/vertex_shader_viewport_index extensions (equivalent to the ARB version). Obviously, since Options 2.3 and 2.4 already require a GS, there's no downside to using them.&#xD;&#xA;&#xD;&#xA;You should profile these options to find out which is faster for your needs. However, despite the fact that GS's are generally not fast things, the fact that 2.3 and 2.4 will eliminate lots of redundant reading and processing of vertex data, it's highly likely that the GS options will be *faster* than using instanced rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layered_Rendering&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Instanced_Rendering&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Instancing" ContentLicense="CC BY-SA 3.0" />
  <row Id="18014" PostHistoryTypeId="2" PostId="6411" RevisionGUID="3380446a-359c-4511-b0af-9b6d581187ef" CreationDate="2018-03-14T23:48:45.950" UserId="5717" Text="That looks like multiplying the front image by the luminance of the shirt behind it.&#xD;&#xA;&#xD;&#xA;There are multiple definitions of luminance but for a start, I think you could assume your data is sRGB and follow the [transformation to CIE][1] to get the CIE Y component.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation" ContentLicense="CC BY-SA 3.0" />
  <row Id="18015" PostHistoryTypeId="2" PostId="6412" RevisionGUID="e19bb6e3-57d8-4a29-91df-daf4edeb3b56" CreationDate="2018-03-15T02:59:23.777" UserId="1937" Text="OpenCL isn't really a drawing API, it's designed for doing compute workloads across different devices, not necessarily GPUs. You can certainly write a kernel that renders to a texture in OpenCL, and have this texture be available to Open GL or D3D. AFAIK, though, you wouldn't have access to the fixed-function hardware like rasterization, attribute interpolation, and fragment blending, so you'd have to implement it yourself (unless you're writing a ray tracer). You'd also likely have to use one of the drawing APIs to present your texture to the screen, by rasterizing a full screen quad and sampling your texture at each pixel. This carries a synchronization penalty - although OpenGL and D3D can interoperate with OpenCL, they can't access the same memory at the same time, so you need to wait for control to transfer from one API to the other.&#xD;&#xA;&#xD;&#xA;Using compute on an already rendered buffer for screenspace effects is a good idea, since you save the fillrate of rasterizing a full screen quad every time you apply a new effect compared to the fragment shader approach. These days though, OpenGL and D3D have compute shaders built-in to handle this kind of use case. Why do you want to use OpenCL exactly? Seems to me you'd be better off using one of the rendering APIs." ContentLicense="CC BY-SA 3.0" />
  <row Id="18017" PostHistoryTypeId="2" PostId="6413" RevisionGUID="71fa712d-2fb6-4655-9949-20c8e7d819c9" CreationDate="2018-03-15T05:26:53.837" UserId="8371" Text="To answer the question definitively, I figured out that the blending used is a combination of **Multiply** and **Hue**.&#xD;&#xA;&#xD;&#xA;After executing a *Multiply* blend on the input images, pass the result as the background for a *Hue* blend while using the same foreground image:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/rKDMg.jpg&quot; width=&quot;292&quot; height=&quot;320&quot;&gt; &lt;img src=&quot;https://i.stack.imgur.com/DRvqw.jpg&quot; width=&quot;292&quot; height=&quot;320&quot;&gt; &#xD;&#xA;&#xD;&#xA;*Background and foreground images for the Hue blend: on the left, the background (generated by a previous Multiply); on the right, the original foreground.*&#xD;&#xA;&#xD;&#xA;The resulting image can be seen [on this JSFiddle][1]. Don't panic! If you see the code you'll notice it is using the *luminosity* blend instead of the *hue* blend. I talked about this problem at the end of [my other answer][2].&#xD;&#xA;&#xD;&#xA;[Equations][3] for [all][4] [these][5] [blending][6] modes can be found on [W3C website][7].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jsfiddle.net/f0akv7yq/9/&#xD;&#xA;  [2]: https://graphicdesign.stackexchange.com/a/106807/116486&#xD;&#xA;  [3]: https://www.w3.org/TR/compositing-1/&#xD;&#xA;  [4]: https://www.w3.org/TR/compositing-1/#blendingmultiply&#xD;&#xA;  [5]: https://www.w3.org/TR/compositing-1/#blendinghue&#xD;&#xA;  [6]: https://www.w3.org/TR/compositing-1/#valdef-blend-mode-luminosity&#xD;&#xA;  [7]: https://www.w3.org" ContentLicense="CC BY-SA 3.0" />
  <row Id="18018" PostHistoryTypeId="5" PostId="6410" RevisionGUID="72e702fe-2287-4c40-b776-de11a5dee6e3" CreationDate="2018-03-15T06:08:25.593" UserId="2654" Comment="added 6 characters in body" Text="&gt; geometry shader will add the workload of GPU&#xD;&#xA;&#xD;&#xA;*Everything* you're trying to do will &quot;add the workload of GPU&quot;. The only question that matters is how much.&#xD;&#xA;&#xD;&#xA;Your choices are:&#xD;&#xA;&#xD;&#xA;1. Redraw everything with different FBOs. You can't just use different `glDrawBuffers` settings, because you also need to change the depth buffers between the two draws.&#xD;&#xA;&#xD;&#xA;2. Use [layered rendering][1]. Your two textures would instead be one texture object with two array layers (the same for the depth texture). There are multiple ways of going about this:&#xD;&#xA;&#xD;&#xA;    1. Render the scene twice, using a `uniform` variable of some kind to determine which layer gets rendered to. This means having to read and execute the VS on all of the vertex data twice.&#xD;&#xA;    2. Render the scene once with [Instanced Rendering][2], using `gl_InstanceID` to determine which layer that particular rendering gets rendered to. This means having to read and execute the VS on all of the vertex data twice.&#xD;&#xA;    3. Render the scene with a Geometry Shader that spits out two triangles for each triangle it gets, one for each layer. This only reads the vertex data and executes the VS on it once.&#xD;&#xA;    4. Render the scene with [Geometry Shader instancing][3]. The GS will be executed twice for each primitive, with a different `gl_InvocationID` value specifying which instance the GS is being executed for. You use that ID to determine which layer to send the primitive to, as well as how to transform it. This only reads the vertex data and executes the VS on it once.&#xD;&#xA;&#xD;&#xA;All of the variations of layered rendering will require either a Geometry Shader or access to the ARB_shader_viewport_layer_array extension or the AMD_vertex_shader_layer &amp; AMD_vertex_shader_viewport_index extensions (equivalent to the ARB version). Obviously, since Options 2.3 and 2.4 already require a GS, there's no downside to using them.&#xD;&#xA;&#xD;&#xA;You should profile these options to find out which is faster for your needs. However, despite the fact that GS's are generally not fast things, the fact that 2.3 and 2.4 will eliminate lots of redundant reading and processing of vertex data, it's highly likely that the GS options will be *faster* than using instanced rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layered_Rendering&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Instanced_Rendering&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Instancing" ContentLicense="CC BY-SA 3.0" />
  <row Id="18019" PostHistoryTypeId="50" PostId="6180" RevisionGUID="1931c785-45bc-4f63-9827-e35d8037e760" CreationDate="2018-03-15T18:29:08.537" UserId="-1" />
  <row Id="18020" PostHistoryTypeId="2" PostId="6414" RevisionGUID="49cae9dc-fcc4-4baf-971e-8ab7fd6e5321" CreationDate="2018-03-16T00:05:07.530" UserId="7462" Text="There are 2 problems i am trying to solve involving rasterization of geometry in 3D.&#xD;&#xA;&#xD;&#xA;The first is, my 3D texture is created with a top down viewd, so triangles that are perfectly orthogonal to the planes represented by the texture are not visible.&#xD;&#xA;&#xD;&#xA;The second is, due to how rasterization in OpenGL works, if a triangle is visible inside of a voxel, but too small to cover the middle of  it, it will be discarded. &#xD;&#xA;&#xD;&#xA;In general I am looking for a method that guarantees that if a voxel contains a triangle or part of a triangle ti will be marked as occupied." ContentLicense="CC BY-SA 3.0" />
  <row Id="18021" PostHistoryTypeId="1" PostId="6414" RevisionGUID="49cae9dc-fcc4-4baf-971e-8ab7fd6e5321" CreationDate="2018-03-16T00:05:07.530" UserId="7462" Text="How to guarantee rasterization of triangles in a voxel representation" ContentLicense="CC BY-SA 3.0" />
  <row Id="18022" PostHistoryTypeId="3" PostId="6414" RevisionGUID="49cae9dc-fcc4-4baf-971e-8ab7fd6e5321" CreationDate="2018-03-16T00:05:07.530" UserId="7462" Text="|opengl|algorithm|rasterizer|voxelization|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18023" PostHistoryTypeId="2" PostId="6415" RevisionGUID="f7deb979-19fd-4ed4-8e5a-e08559954cbf" CreationDate="2018-03-16T01:46:29.680" UserId="8191" Text="So I am doing a simple FPS camera with openGL. I store the camera as 4 vector, a position vector, a lookAt vector, an up vector and a right vector. When the user presses a key, I create a rotation matrix that rotates around the up vector 10 degree then multiply the three vectors that specify the orientation of the camera with it. With these new values I create a new view matrix from glm::lookAt. However, the result I get is very weird. When I press the button to rotate, the object the camera is initially pointing at dissapears, no matter how small I set the rotation.  &#xD;&#xA;I feel like the code is not wrong, but my understanding of the math behind it and therefore the implementation is wrong. Can anyone explain to me this weird behavior? &#xD;&#xA;Below is my code.&#xD;&#xA;&#xD;&#xA;    look = glm::vec3(glm::rotate(theta, axis) * glm::vec4(look, 1.0f)); // theta set at 2 degree&#xD;&#xA;	right = glm::vec3(glm::rotate(theta, axis) * glm::vec4(right, 1.0f));&#xD;&#xA;	up = glm::vec3(glm::rotate(theta, axis) * glm::vec4(up, 1.0f));&#xD;&#xA;    glm::mat4 cameraMat = glm::lookAt(eyePos, eyePos+camera.look, camera.up);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="18024" PostHistoryTypeId="1" PostId="6415" RevisionGUID="f7deb979-19fd-4ed4-8e5a-e08559954cbf" CreationDate="2018-03-16T01:46:29.680" UserId="8191" Text="How to rotate a camera?" ContentLicense="CC BY-SA 3.0" />
  <row Id="18025" PostHistoryTypeId="3" PostId="6415" RevisionGUID="f7deb979-19fd-4ed4-8e5a-e08559954cbf" CreationDate="2018-03-16T01:46:29.680" UserId="8191" Text="|opengl|3d|camera-matrix|camera|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18026" PostHistoryTypeId="5" PostId="6415" RevisionGUID="05e9b12a-23e4-4136-8c74-7ea9da1fda73" CreationDate="2018-03-16T04:14:18.013" UserId="8191" Comment="added 117 characters in body" Text="So I am doing a simple FPS camera with openGL. I store the camera as 4 vector, a position vector, a lookAt vector, an up vector and a right vector. When the user presses a key, I create a rotation matrix that rotates around the up vector 10 degree then multiply the three vectors that specify the orientation of the camera with it. With these new values I create a new view matrix from glm::lookAt. However, the result I get is very weird. When I press the button to rotate, the object the camera is initially pointing at dissapears, no matter how small I set the rotation. After pressing the rotate button several more time, it appears again, then if i press more it dissappears once more.  &#xD;&#xA;I feel like the code is not wrong, but my understanding of the math behind it and therefore the implementation is wrong. Can anyone explain to me this weird behavior? &#xD;&#xA;Below is my code.&#xD;&#xA;&#xD;&#xA;    look = glm::vec3(glm::rotate(theta, axis) * glm::vec4(look, 1.0f)); // theta set at 2 degree&#xD;&#xA;	right = glm::vec3(glm::rotate(theta, axis) * glm::vec4(right, 1.0f));&#xD;&#xA;	up = glm::vec3(glm::rotate(theta, axis) * glm::vec4(up, 1.0f));&#xD;&#xA;    glm::mat4 cameraMat = glm::lookAt(eyePos, eyePos+camera.look, camera.up);&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="18027" PostHistoryTypeId="2" PostId="6416" RevisionGUID="7f2e6465-d820-489e-9b82-d87d985ccfb2" CreationDate="2018-03-16T15:00:30.807" UserId="1937" Text="Promoting my comment into an answer since it identified the problem...&#xD;&#xA;&#xD;&#xA;The issue is confusion between degrees and radians for the angle parameter. GLM, up to version 0.9.5, was very inconsistent in how it dealt with angles, accepting degrees for some functions and radians for others. This behaviour could be overridden with `#define GLM_FORCE_RADIANS` before including the header.&#xD;&#xA;&#xD;&#xA;In version 0.9.6, radians everywhere became the default. Unfortunately, if you Google 'glm rotate' at the time of writing, the top result is the 0.9.4 doc page, which still describes the parameters as taking degrees, so you need to be aware of which version you are using and its default behaviour in this regard. If you still want to use degrees for your angle variables, you can convert them with `glm::radians(angle)` before passing them as arguments." ContentLicense="CC BY-SA 3.0" />
  <row Id="18033" PostHistoryTypeId="2" PostId="6418" RevisionGUID="2c09a019-ec1e-4250-aa54-5f22ad074825" CreationDate="2018-03-17T04:54:13.693" UserId="8356" Text="Oblique meaning not a regular cone; its apex makes an angle to the base. &#xD;&#xA;&#xD;&#xA;An alternate way of visualizing this: consider a sphere centered at the origin. The sphere traces a circle on the XY-plane. Now consider a point A anywhere on the sphere, and another point B on the circle. Now as B traces around the circle, length AB varies. I an trying to draw the solid (or surface) with AB as the generator.&#xD;&#xA;&#xD;&#xA;The pics and video below would give you the final idea of the solid I want to generate:&#xD;&#xA;&#xD;&#xA;[![orthographic view with the sphere][1]][1]&#xD;&#xA;[![View from the top without the sphere for clarity0][2]][2]&#xD;&#xA;&#xD;&#xA;&lt;https://youtu.be/Z8RAn6Dkz7w&gt; - animation&#xD;&#xA;&#xD;&#xA;https://ggbm.at/vrEC7tDs - geogebra worksheet (3d)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UpHAr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TvGlA.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="18034" PostHistoryTypeId="1" PostId="6418" RevisionGUID="2c09a019-ec1e-4250-aa54-5f22ad074825" CreationDate="2018-03-17T04:54:13.693" UserId="8356" Text="What is the technique to generate an oblique 3d cone?" ContentLicense="CC BY-SA 3.0" />
  <row Id="18035" PostHistoryTypeId="3" PostId="6418" RevisionGUID="2c09a019-ec1e-4250-aa54-5f22ad074825" CreationDate="2018-03-17T04:54:13.693" UserId="8356" Text="|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18036" PostHistoryTypeId="2" PostId="6419" RevisionGUID="45073a51-c2c4-4e02-abb2-e58b36182cd2" CreationDate="2018-03-17T05:20:56.420" UserId="56" Text="When doing random sampling, you can get noisy results if you don't use enough samples like in the shadows below.&#xD;&#xA;&#xD;&#xA;I know that if you use blue noise, the noise pattern can be high frequency content only, which can then be low pass filtered (aka blur) to remove the high frequencies and leave just the lower frequency content which would be less noisy.&#xD;&#xA;&#xD;&#xA;Is denoising ALWAYS about doing a low pass filter / blur? Or are there other ideas and techniques for removing noise?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SmLkV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="18037" PostHistoryTypeId="1" PostId="6419" RevisionGUID="45073a51-c2c4-4e02-abb2-e58b36182cd2" CreationDate="2018-03-17T05:20:56.420" UserId="56" Text="What is the basic idea of denoising?" ContentLicense="CC BY-SA 3.0" />
  <row Id="18038" PostHistoryTypeId="3" PostId="6419" RevisionGUID="45073a51-c2c4-4e02-abb2-e58b36182cd2" CreationDate="2018-03-17T05:20:56.420" UserId="56" Text="|noise|denoise|" ContentLicense="CC BY-SA 3.0" />
  <row Id="18039" PostHistoryTypeId="5" PostId="6419" RevisionGUID="1a3ea2a0-7b4a-4abb-947c-ca2527b68687" CreationDate="2018-03-17T05:26:13.497" UserId="56" Comment="added 27 characters in body" Text="When doing random sampling, you can get noisy results if you don't use enough samples like in the shadows below.&#xD;&#xA;&#xD;&#xA;I know that if you use high frequency noise (aka blue noise), the noise pattern can be high frequency content only, which can then be low pass filtered (aka blur) to remove the high frequencies and leave just the lower frequency content which would be less noisy.&#xD;&#xA;&#xD;&#xA;Is denoising ALWAYS about doing a low pass filter / blur? Or are there other ideas and techniques for removing noise?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SmLkV.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="18040" PostHistoryTypeId="2" PostId="6420" RevisionGUID="a3c357e0-cbba-4d98-bd32-35d12f4b4162" CreationDate="2018-03-17T10:02:43.867" UserId="1981" Text="It certainly isn't *always* about low pass filters (see for example [here on WP on &quot;Noise Reduction&quot;](https://en.wikipedia.org/wiki/Noise_reduction#Removal)) *but* you have to keep in mind that in your case the noise will always have a high frequency because you can basically consider each pixel with a independent noise realization. So any way of removing noise in this situation *will* have a low pass effect." ContentLicense="CC BY-SA 3.0" />
  <row Id="18041" PostHistoryTypeId="2" PostId="6421" RevisionGUID="b63a91d5-1c69-4ff8-859f-740779b66bd2" CreationDate="2018-03-17T11:03:53.153" UserId="1981" Text="The general equation for a upright cone with the tip at $Z=0$ is&#xD;&#xA;&#xD;&#xA;$$ 0 = X^2 + Y^2 - Z^2$$&#xD;&#xA;&#xD;&#xA;(Ignoring the points for which $Z&gt;0$). If you consider slices for some constant $Z$ you get circles centered on the line $X=Y=0$. To make an oblique cone with circles along the line $X=aZ,Y=bZ$ we can just shift the coordinates accordingly and get the equation&#xD;&#xA;&#xD;&#xA;$$ 0 = (X-aZ)^2 + (Y-bZ)^2 - Z^2$$&#xD;&#xA;&#xD;&#xA;(again for $Z&lt;0$). You can make it narrower or wider by scaling the $Z$ coordinate. To position the tip at some other point $(x,y,z)$ you can just shift the whole thing using the transform $(X',Y',Z') := (X-x,Y-y,Z-z)$.&#xD;&#xA;&#xD;&#xA;With the same idea you can easily parametrize the (upright) cone by&#xD;&#xA;&#xD;&#xA;$$(u,v) \mapsto (u\cos(v),u\sin(v),u)$$&#xD;&#xA;&#xD;&#xA;or the skewed cone by&#xD;&#xA;&#xD;&#xA;$$(u,v) \mapsto (u\cos(v)-au,u\sin(v)-bu,u)$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="18042" PostHistoryTypeId="2" PostId="6422" RevisionGUID="46e4d68d-2c2c-48db-a02b-eb536ebefbbd" CreationDate="2018-03-17T13:07:21.043" UserId="8394" Text="Im writting a raytracer, for which I want to be able to test intersections with implicit surfaces (in my case spheres). Without applying any transformation it works great, but I would like to upgrade it to test intersections against non-uniform scaled spheres. For such purpose, I have computed the object's local to world matrix, as well as the world to local matrix.&#xD;&#xA;&#xD;&#xA;During the intersection test, I first transform the ray origin and direction to the object local space:&#xD;&#xA;&#xD;&#xA;    	Vector o = ray.getOrigin();&#xD;&#xA;    	Vector l = ray.getDirection();&#xD;&#xA;    &#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    	o = worldToLocalMatrix * o;&#xD;&#xA;    	l = worldToLocalMatrix * Vector(l.x, l.y, l.z, 0.0f);&#xD;&#xA;    	l = l.Normalize();&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;I perform the test, compute the hitted point in object's local space and then transform it back to world space:&#xD;&#xA;&#xD;&#xA;    Vector hitPoint(o + (l * distance));&#xD;&#xA;    		Vector hitNormal((hitPoint - center) / radius);&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    		hitPoint = localToWorldMatrix * hitPoint;&#xD;&#xA;    		hitNormal = localToWorldMatrix * Vector(hitNormal.x, hitNormal.y, hitNormal.z, 0.0f);&#xD;&#xA;    #endif&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I run the raytracer, it works great:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, from some pointo of views (not all), I obtain wrong renders from the dielectric sphere (center in the above image) and the perfect specular (right in the above image), as well as one of the cubes:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pwN09.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dro4c.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I just apply the affine transformations to the object's vertices and normals during start up(in the case of the sphere, I only apply translation since its an implicit surface), the render works flawlessly, so my guess its that the problem comes from the transformations applied to the ray.&#xD;&#xA;&#xD;&#xA;To compute the local to world matrix:&#xD;&#xA;Model = rotation * translation * scale&#xD;&#xA;&#xD;&#xA;To compute the world to local matrix&#xD;&#xA;InvModel = inverse(scale) * inverse(translation) * inverse(rotation)&#xD;&#xA;&#xD;&#xA;Thank you in advance for your time" ContentLicense="CC BY-SA 3.0" />
  <row Id="18043" PostHistoryTypeId="1" PostId="6422" RevisionGUID="46e4d68d-2c2c-48db-a02b-eb536ebefbbd" CreationDate="2018-03-17T13:07:21.043" UserId="8394" Text="Ray tracing: transforming ray to object's local space for intersection test" ContentLicense="CC BY-SA 3.0" />
  <row Id="18044" PostHistoryTypeId="3" PostId="6422" RevisionGUID="46e4d68d-2c2c-48db-a02b-eb536ebefbbd" CreationDate="2018-03-17T13:07:21.043" UserId="8394" Text="|raytracing|transformations|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19045" PostHistoryTypeId="2" PostId="7422" RevisionGUID="d5a1811f-d3c5-477c-8ea7-1e5046a07332" CreationDate="2018-03-17T14:43:24.377" UserId="2041" Text="&gt; Is denoising ALWAYS about doing a low pass filter / blur?&#xD;&#xA;&#xD;&#xA;No, but this is the most obvious technique. A *good* denoiser isn't just a filter that runs on the image, but actually performs the reconstruction; i.e. it's a function from random samples to an image, not a function from an image to an image.&#xD;&#xA;&#xD;&#xA;&gt; Or are there other ideas and techniques for removing noise?&#xD;&#xA;&#xD;&#xA;Yes. For years, the main family of denoise techniques worked in two parts. First, a line detection algorithm would detect the true edges in the image. Then, the output in this would set weights in a filter kernel to perform some kind of guided blur, so that the blur would be strongest (i.e. remove more frequencies) where there are no edges, and weakest (i.e. allow high frequencies) where there were edges. This would remove more noise from gradients while preserving edges.&#xD;&#xA;&#xD;&#xA;Nowadays, deep learning has provided a new family of techniques. Using the same technique that's producing the noise (i.e. path tracing if you want to denoise path-tracer renders), produce lots of image pairs where one has high noise (few samples) and one has low noise (high sample rate). Feed these pairs into a convolutional network, to train it to produce the low-noise images from the high-noise images. Then feed your high-noise image into the trained network, and enjoy the low-noise output. Variations on this technique include having the network produce a filter kernel for each image patch, instead of learning the output image directly; or classifying an image patch according to its structure (what edges are present), so similar patches can be handled similarly. Some networks can even take the raw samples as input and directly produce a denoised image; others can guide your adaptive sampling algorithm." ContentLicense="CC BY-SA 3.0" />
  <row Id="19046" PostHistoryTypeId="5" PostId="6422" RevisionGUID="3e32f3a1-8b6d-4f00-94be-a0eb3d72ab87" CreationDate="2018-03-17T15:28:17.933" UserId="6" Comment="Improved formatting. Removed idle chatter." Text="Im writting a raytracer, for which I want to be able to test intersections with implicit surfaces (in my case spheres). Without applying any transformation it works great, but I would like to upgrade it to test intersections against non-uniform scaled spheres. For such purpose, I have computed the object's local to world matrix, as well as the world to local matrix.&#xD;&#xA;&#xD;&#xA;During the intersection test, I first transform the ray origin and direction to the object local space:&#xD;&#xA;&#xD;&#xA;    	Vector o = ray.getOrigin();&#xD;&#xA;    	Vector l = ray.getDirection();&#xD;&#xA;    &#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    	o = worldToLocalMatrix * o;&#xD;&#xA;    	l = worldToLocalMatrix * Vector(l.x, l.y, l.z, 0.0f);&#xD;&#xA;    	l = l.Normalize();&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;I perform the test, compute the hitted point in object's local space and then transform it back to world space:&#xD;&#xA;&#xD;&#xA;    Vector hitPoint(o + (l * distance));&#xD;&#xA;    		Vector hitNormal((hitPoint - center) / radius);&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    		hitPoint = localToWorldMatrix * hitPoint;&#xD;&#xA;    		hitNormal = localToWorldMatrix * Vector(hitNormal.x, hitNormal.y, hitNormal.z, 0.0f);&#xD;&#xA;    #endif&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I run the raytracer, it works great:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, from some pointo of views (not all), I obtain wrong renders from the dielectric sphere (center in the above image) and the perfect specular (right in the above image), as well as one of the cubes:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pwN09.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dro4c.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I just apply the affine transformations to the object's vertices and normals during start up(in the case of the sphere, I only apply translation since its an implicit surface), the render works flawlessly, so my guess its that the problem comes from the transformations applied to the ray.&#xD;&#xA;&#xD;&#xA;To compute the local to world matrix:&#xD;&#xA;`Model = rotation * translation * scale`&#xD;&#xA;&#xD;&#xA;To compute the world to local matrix:&#xD;&#xA;`InvModel = inverse(scale) * inverse(translation) * inverse(rotation)`" ContentLicense="CC BY-SA 3.0" />
  <row Id="19047" PostHistoryTypeId="24" PostId="6422" RevisionGUID="3e32f3a1-8b6d-4f00-94be-a0eb3d72ab87" CreationDate="2018-03-17T15:28:17.933" Comment="Proposed by 6 approved by 8394 edit id of 362" ContentLicense="CC BY-SA 3.0" />
  <row Id="19048" PostHistoryTypeId="5" PostId="6422" RevisionGUID="b25d35ee-ca59-411d-b7a4-6fd3463da449" CreationDate="2018-03-17T15:38:13.533" UserId="8394" Comment="added 107 characters in body" Text="Im writting a raytracer, for which I want to be able to test intersections with implicit surfaces (in my case spheres). Without applying any transformation it works great, but I would like to upgrade it to test intersections against non-uniform scaled spheres. For such purpose, I have computed the object's local to world matrix, as well as the world to local matrix.&#xD;&#xA;&#xD;&#xA;During the intersection test, I first transform the ray origin and direction to the object local space:&#xD;&#xA;&#xD;&#xA;    	Vector o = ray.getOrigin();&#xD;&#xA;    	Vector l = ray.getDirection();&#xD;&#xA;    &#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    	o = worldToLocalMatrix * o;&#xD;&#xA;    	l = worldToLocalMatrix * Vector(l.x, l.y, l.z, 0.0f);&#xD;&#xA;    	l = l.Normalize();&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;I perform the test, compute the hitted point in object's local space and then transform it back to world space:&#xD;&#xA;&#xD;&#xA;    Vector hitPoint(o + (l * distance));&#xD;&#xA;    		Vector hitNormal((hitPoint - center) / radius);&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    		hitPoint = localToWorldMatrix * hitPoint;&#xD;&#xA;    		hitNormal = localToWorldMatrix * Vector(hitNormal.x, hitNormal.y, hitNormal.z, 0.0f);&#xD;&#xA;    #endif&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I run the raytracer, it works great:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, from some pointo of views (not all), I obtain wrong renders from the dielectric sphere (center in the above image) and the perfect specular (right in the above image), as well as one of the cubes:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pwN09.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dro4c.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I just apply the affine transformations to the object's vertices and normals during start up(in the case of the sphere, I only apply translation since its an implicit surface), the render works flawlessly, so my guess its that the problem comes from the transformations applied to the ray.&#xD;&#xA;&#xD;&#xA;To compute the local to world matrix:&#xD;&#xA;`Model = rotation * translation * scale`&#xD;&#xA;&#xD;&#xA;To compute the world to local matrix:&#xD;&#xA;`InvModel = inverse(scale) * inverse(translation) * inverse(rotation)`&#xD;&#xA;&#xD;&#xA;I would like to know if Im applying the transformation to the ray as well as to the output hit properly" ContentLicense="CC BY-SA 3.0" />
  <row Id="19049" PostHistoryTypeId="2" PostId="7423" RevisionGUID="a774fffc-8db6-489a-b859-d3f460982917" CreationDate="2018-03-17T16:22:03.813" UserId="8394" Text="I figured out the problem. It was not related to the ray / point transformation itself, but to a problem with the camera update after moving it (Up vector wasn't being computed properly).&#xD;&#xA;&#xD;&#xA;I leave the answer in case someone have similar issues." ContentLicense="CC BY-SA 3.0" />
  <row Id="19050" PostHistoryTypeId="5" PostId="6421" RevisionGUID="a6579767-1d25-4c89-8bbc-3e957ae47cbf" CreationDate="2018-03-17T16:41:08.700" UserId="1981" Comment="added 1 character in body" Text="The general equation for a upright cone with the tip at $Z=0$ is&#xD;&#xA;&#xD;&#xA;$$ 0 = X^2 + Y^2 - Z^2$$&#xD;&#xA;&#xD;&#xA;(Ignoring the points for which $Z&gt;0$). If you consider slices for some constant $Z$ you get circles centered on the line $X=Y=0$. To make an oblique cone with circles along the line $X=aZ,Y=bZ$ we can just shift the coordinates accordingly and get the equation&#xD;&#xA;&#xD;&#xA;$$ 0 = (X-aZ)^2 + (Y-bZ)^2 - Z^2$$&#xD;&#xA;&#xD;&#xA;(again for $Z&lt;0$). You can make it narrower or wider by scaling the $Z$ coordinate. To position the tip at some other point $(x,y,z)$ you can just shift the whole thing using the transform $(X',Y',Z') := (X-x,Y-y,Z-z)$.&#xD;&#xA;&#xD;&#xA;With the same idea you can easily parametrize the (upright) cone by&#xD;&#xA;&#xD;&#xA;$$(u,v) \mapsto (u\cos(v),u\sin(v),u)$$&#xD;&#xA;&#xD;&#xA;or the oblique cone by&#xD;&#xA;&#xD;&#xA;$$(u,v) \mapsto (u\cos(v)-au,u\sin(v)-bu,u)$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="19051" PostHistoryTypeId="50" PostId="5996" RevisionGUID="494b6d20-3830-432d-a619-173d42728c40" CreationDate="2018-03-17T23:32:29.327" UserId="-1" />
  <row Id="19052" PostHistoryTypeId="5" PostId="6347" RevisionGUID="c03b50f6-5846-4a43-9c2c-683088790c77" CreationDate="2018-03-18T06:54:33.687" UserId="6046" Comment="added 378 characters in body" Text="If I understand correctly, you want to draw 2 objects mirrored with respect to an arbitrary line. Then when you move 1 object you want the other (reflection) to move with respect to that reflected line. &#xD;&#xA;&#xD;&#xA;A more sophisticated way of doing this would be using transformation matrices. That way you wouldn't have to worry about moving the mirrored triangle. You will move the original triangle, apply a transformation matrix to find the position of the mirrored triangle.&#xD;&#xA;&#xD;&#xA;Suppose we have an arbitrary line $ax+by+c = 0$ making an arbitrary angle (measured counter clockwise) with the +X axis. We can easily find slope in the form of $ y = mx + c$ and the angle $\theta = tan^-1(m)$.&#xD;&#xA;&#xD;&#xA;The mirror transformation with respect to this line can be broken in 3 affine transformation.&#xD;&#xA;&#xD;&#xA;1) Rotate the line by  $-\theta$ to coincide it with the X-axis.&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;cos(-theta) &amp; -sin(-theta) &amp; 0\\&#xD;&#xA;sin(-theta) &amp; cos(-theta)  &amp; 0\\&#xD;&#xA;0           &amp; 0            &amp; 1&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2) Reflect about the X-axis.&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;1 &amp; 0  &amp; 0\\&#xD;&#xA;0 &amp; -1 &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;3) Rotate again by $\theta$.&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;cos(theta) &amp; -sin(theta) &amp; 0\\&#xD;&#xA;sin(theta) &amp; cos(theta)  &amp; 0\\&#xD;&#xA;0           &amp; 0            &amp; 1&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Now you concatenate all 3 and you get a matrix that reflects about an arbitrary line.&#xD;&#xA;&#xD;&#xA;Now we only move 1 triangle and find out the other by applying the matrix.&#xD;&#xA;&#xD;&#xA;EDIT:- **As pointed out by Anthony in the comments this is only for lines passing through the origin. For arbitrary lines first translate them to the origin, then perform all these steps, then translate it back.**&#xD;&#xA;&#xD;&#xA;In order to do this you can find out the x and y intercepts by putting `y=0` and  `x=0` respectively then translate the respective coordinate by that amount." ContentLicense="CC BY-SA 3.0" />
  <row Id="19056" PostHistoryTypeId="2" PostId="7425" RevisionGUID="dab359ef-4c1f-43ba-abba-eb6a6c9ec21f" CreationDate="2018-03-18T10:40:39.580" UserId="6968" Text="Suppose you have a circle in 3D space. It can be described by its radius $r$, its center point $\mathbf{C}$, and two orthogonal unit vectors $\mathbf{A}$ and $\mathbf{B}$ that span the plane parallel to the circle. Then the parametric equations of the circle are:&#xD;&#xA;$$&#xD;&#xA;\mathbf{P}(u) = \mathbf{C} + r\cos(u)\mathbf{A} + r\sin(u)\mathbf{B}&#xD;&#xA;$$&#xD;&#xA;Now suppose you want to form an oblique cone that contains this circle and an apex point $\mathbf{Q}$. The parametric equations of this surface are:&#xD;&#xA;$$&#xD;&#xA;\mathbf{S}(u,v) = (1-v)\mathbf{Q} + v\mathbf{P}(u)&#xD;&#xA;$$&#xD;&#xA;If $v=0$, then $\mathbf{S}(u,v) = \mathbf{Q}$ for all $u$, and if $v=0$, then $\mathbf{S}(u,v) = \mathbf{P}(u)$ is a point on the circle.&#xD;&#xA;&#xD;&#xA;If you fix $u$, then, as $v$ varies, you travel along a straight line through the points $\mathbf{Q}$ and $\mathbf{P}(u)$." ContentLicense="CC BY-SA 3.0" />
  <row Id="19058" PostHistoryTypeId="50" PostId="6012" RevisionGUID="638a8d42-b988-400b-9428-d74037c5dfd5" CreationDate="2018-03-19T16:35:51.687" UserId="-1" />
  <row Id="19059" PostHistoryTypeId="5" PostId="6406" RevisionGUID="d240b036-e0df-418f-a9e4-7640e5b9b9d7" CreationDate="2018-03-19T20:28:07.407" UserId="6" Comment="Removed idle chatter." Text="I need to identify certain topological entities (circular holes) in a given geometry, that is, given the boundary representation of a solid, I need to identify the exact coordinates of all holes in the solid. I have been told to use a topological sweep, yet the information available is not clear to me as in how it fits in the solution of such problem. Does anyone have a recommendation or more information about what exactly is a topological sweep?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19060" PostHistoryTypeId="24" PostId="6406" RevisionGUID="d240b036-e0df-418f-a9e4-7640e5b9b9d7" CreationDate="2018-03-19T20:28:07.407" Comment="Proposed by 6 approved by 209, 231 edit id of 363" ContentLicense="CC BY-SA 3.0" />
  <row Id="19065" PostHistoryTypeId="50" PostId="5892" RevisionGUID="00e560f4-c0fd-4989-9050-3a0f3183cf3e" CreationDate="2018-03-20T05:41:07.777" UserId="-1" />
  <row Id="19067" PostHistoryTypeId="2" PostId="7426" RevisionGUID="d30aa80c-9bf8-478e-80b9-97c44674c024" CreationDate="2018-03-20T10:07:33.523" UserId="4981" Text="I have the parametric model of an ellipsoid like this:&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;x=a_1\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\ = _2\,cos\,\eta\:sin\,\omega \\ z=a_3\,sin \,\omega &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;n_x=\frac{1}{a_1}\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\n_ = \frac{1}{a_2}\,cos\,\eta\:sin\,\omega \\ n_z=\frac{1}{a_3}\,sin \,\omega &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;First of all I do not understand the last system of equation what it represents.&#xD;&#xA; Does  shouldn't  parametrization of ellipsoid be the first system alone?&#xD;&#xA;&#xD;&#xA;I have to create a polygon mesh (in webgl) from parametric model of ellipsoid. I can choose dimensions of semiaxes (namely values of $a_1$ $a_2$ and  $a_3$) and the sampling step of 2 angles (the parameters).  In this way I'm able to create in javascript with a little of code several vertices of ellipsoid. But I can't imagine how to realize the triangolation. Namely given the vertex buffer, I have to create the index buffer but in what way do I choose the indexes of the vertices to tessellate in a correct way ellipsoid surface? Is there a clever,smart way to proceed? " ContentLicense="CC BY-SA 3.0" />
  <row Id="19068" PostHistoryTypeId="1" PostId="7426" RevisionGUID="d30aa80c-9bf8-478e-80b9-97c44674c024" CreationDate="2018-03-20T10:07:33.523" UserId="4981" Text="Triangolation of vertices of an ellipsoid" ContentLicense="CC BY-SA 3.0" />
  <row Id="19069" PostHistoryTypeId="3" PostId="7426" RevisionGUID="d30aa80c-9bf8-478e-80b9-97c44674c024" CreationDate="2018-03-20T10:07:33.523" UserId="4981" Text="|computational-geometry|geometry|mesh|webgl|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19070" PostHistoryTypeId="5" PostId="7426" RevisionGUID="4b3b3559-5f59-4bca-b402-0164158d8cc8" CreationDate="2018-03-20T11:29:29.233" UserId="209" Comment="Minor spelling corrections" Text="I have the parametric model of an ellipsoid like this:&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;x=a_1\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\ = _2\,cos\,\eta\:sin\,\omega \\ z=a_3\,sin \,\omega &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;n_x=\frac{1}{a_1}\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\n_ = \frac{1}{a_2}\,cos\,\eta\:sin\,\omega \\ n_z=\frac{1}{a_3}\,sin \,\omega &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;First of all I do not understand the last system of equation what it represents.&#xD;&#xA; Shouldn't  parameterisation of an ellipsoid be the first system alone?&#xD;&#xA;&#xD;&#xA;I have to create a polygon mesh (in webgl) from parametric model of ellipsoid. I can choose dimensions of semiaxes (namely values of $a_1$ $a_2$ and  $a_3$) and the sampling step of 2 angles (the parameters).  In this way I'm able to create in javascript with a little of code several vertices of ellipsoid. But I can't imagine how to realise the triangulation. Namely given the vertex buffer, I have to create the index buffer but in what way do I choose the indexes of the vertices to tessellate in a correct way ellipsoid surface? Is there a clever/smart way to proceed? " ContentLicense="CC BY-SA 3.0" />
  <row Id="19071" PostHistoryTypeId="4" PostId="7426" RevisionGUID="4b3b3559-5f59-4bca-b402-0164158d8cc8" CreationDate="2018-03-20T11:29:29.233" UserId="209" Comment="Minor spelling corrections" Text="Triangulation of vertices of an ellipsoid" ContentLicense="CC BY-SA 3.0" />
  <row Id="19072" PostHistoryTypeId="2" PostId="7427" RevisionGUID="7cdd9cbf-a18e-44b2-9fd3-418de5b44e8a" CreationDate="2018-03-20T12:08:21.617" UserId="7647" Text="If you sample the two parameters $\eta$ and $\omega$ with steps $d\eta$ and $d\omega$, then you'll get a grid of points $v_{ij}$.  Any four adjacent points will define a quadrilateral.  To get triangles, you just have to split each quad in two by a diagonal.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So in the example, you'd split the quadrilateral $\{v_{00},v_{01},v_{11},v_{10}\}$ into two triangles $\{v_{00},v_{01},v_{10}\}$ and $\{v_{01},v_{11},v_{10}\}$.  You'll want to make sure the points come in the right order so the triangle orientations match (or you'll end up backface-culling half of your triangles.)&#xD;&#xA;&#xD;&#xA;Your second equation, for $n_{xyz}$, is finding the *normal* of each vertex, which you can use for shading.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Fm0tG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19073" PostHistoryTypeId="5" PostId="7426" RevisionGUID="9388f35c-63f2-42d4-97a9-2e9f31c7d815" CreationDate="2018-03-20T13:25:32.770" UserId="4981" Comment="deleted 2 characters in body" Text="I have the parametric model of an ellipsoid like this:&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;x=a_1\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\ = _2\,cos\,\eta\:sin\,\omega \\ z=a_3\,sin \,\eta &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;n_x=\frac{1}{a_1}\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\n_ = \frac{1}{a_2}\,cos\,\eta\:sin\,\omega \\ n_z=\frac{1}{a_3}\,sin \,\eta &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;First of all I do not understand the last system of equation what it represents.&#xD;&#xA; Shouldn't  parameterisation of an ellipsoid be the first system alone?&#xD;&#xA;&#xD;&#xA;I have to create a polygon mesh (in webgl) from parametric model of ellipsoid. I can choose dimensions of semiaxes (namely values of $a_1$ $a_2$ and  $a_3$) and the sampling step of 2 angles (the parameters).  In this way I'm able to create in javascript with a little of code several vertices of ellipsoid. But I can't imagine how to realise the triangulation. Namely given the vertex buffer, I have to create the index buffer but in what way do I choose the indexes of the vertices to tessellate in a correct way ellipsoid surface? Is there a clever/smart way to proceed? " ContentLicense="CC BY-SA 3.0" />
  <row Id="19074" PostHistoryTypeId="2" PostId="7428" RevisionGUID="4db6bb75-6d03-48ae-b521-3616d09d75f5" CreationDate="2018-03-20T15:15:08.173" UserId="2308" Text="Inside of my application I am trying to convert a MTLTexture into a CGImage or CIimage for use in other parts of the app. I am having a difficult time doing so because none of the example code I find seems to work properly.&#xD;&#xA;&#xD;&#xA;For some reason something breaks on each and every one of them. Here are my attempts and why they dont work. If you could give me ideas on why that would be appreciated.&#xD;&#xA;&#xD;&#xA;All of my textures are in brga8Unorm format.&#xD;&#xA;&#xD;&#xA;**Method 1** is to copy the pixels into an unsafe mutable pointer and use that to directly create a CGTexture. It creates a textures of all 0s&#xD;&#xA;&#xD;&#xA;    func toImage() -&gt; NSImage? {&#xD;&#xA;            let texture = self&#xD;&#xA;            let width = texture.width&#xD;&#xA;            let height = texture.height&#xD;&#xA;            let bytesPerRow = width * 4&#xD;&#xA;            &#xD;&#xA;            let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;            defer {&#xD;&#xA;                data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            let region = MTLRegionMake2D(0, 0, width, height)&#xD;&#xA;            texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)&#xD;&#xA;            var buffer = vImage_Buffer(data: data, height: UInt(height), width: UInt(width), rowBytes: bytesPerRow)&#xD;&#xA;            &#xD;&#xA;            let map: [UInt8] = [2, 1, 0, 3]&#xD;&#xA;            vImagePermuteChannels_ARGB8888(&amp;buffer, &amp;buffer, map, 0)&#xD;&#xA;            &#xD;&#xA;            guard let colorSpace = CGColorSpace(name: CGColorSpace.genericRGBLinear) else { return nil }&#xD;&#xA;            guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow,&#xD;&#xA;                                          space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) else { return nil }&#xD;&#xA;            guard let cgImage = context.makeImage() else { return nil }&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            return NSImage(cgImage: cgImage, size: NSSize(width: width, height: height))&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;**Method 2** tries to use CImage to do the job however CImage reports `Cannot render image (with an input Metal texture) using a metal context.` and returns nil&#xD;&#xA;&#xD;&#xA;    extension MTLTexture {&#xD;&#xA;        func toImage() -&gt; CGImage? {&#xD;&#xA;            let context = CIContext()&#xD;&#xA;            let texture = self&#xD;&#xA;            let cImg = CIImage(mtlTexture: texture, options: nil)!&#xD;&#xA;            let cgImg = context.createCGImage(cImg, from: cImg.extent)!&#xD;&#xA;            return cgImg&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**This last method** doesnt even try to convert the image it is just trying to determine if the image is blank (all 0s) or not however even on fully green or even textured images it says they are blank.&#xD;&#xA;&#xD;&#xA;    func anythingHere(_ texture: MTLTexture) -&gt; Bool {&#xD;&#xA;            let width = texture.width&#xD;&#xA;            let height = texture.height&#xD;&#xA;            let bytesPerRow = width * 4&#xD;&#xA;    &#xD;&#xA;            let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;            defer {&#xD;&#xA;                data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            let region = MTLRegionMake2D(0, 0, width, height)&#xD;&#xA;            texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)&#xD;&#xA;            var bind = data.assumingMemoryBound(to: UInt8.self)&#xD;&#xA;    &#xD;&#xA;            var sum:UInt8 = 0;&#xD;&#xA;            for i in 0..&lt;width*height {&#xD;&#xA;                sum += bind.pointee&#xD;&#xA;                bind = bind.advanced(by: 1)&#xD;&#xA;            }&#xD;&#xA;            return sum != 0&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Clearly I am doing something fundamentally wrong as none of these methods are actually producing results. What am I doing wrong? What is the right way to do this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19075" PostHistoryTypeId="1" PostId="7428" RevisionGUID="4db6bb75-6d03-48ae-b521-3616d09d75f5" CreationDate="2018-03-20T15:15:08.173" UserId="2308" Text="MTLTexture getBytes returning blank image" ContentLicense="CC BY-SA 3.0" />
  <row Id="19076" PostHistoryTypeId="3" PostId="7428" RevisionGUID="4db6bb75-6d03-48ae-b521-3616d09d75f5" CreationDate="2018-03-20T15:15:08.173" UserId="2308" Text="|texture|mobile|metal|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19077" PostHistoryTypeId="5" PostId="3862" RevisionGUID="dc7cf9f4-92e0-4fc6-b42f-bb7a0e1ff2c6" CreationDate="2018-03-20T15:55:24.093" UserDisplayName="user7220" Comment="Corrected indents.." Text="I'm trying to render a randomly generated terrain with vertex buffers and OpenGL. I want to use a shader to color the terrain, but it seemms like my shader isn't used. I have used shaders before when drawing triangles manually on the CPU and didn't have any problems there.&#xD;&#xA;&#xD;&#xA;activate and deactivate is just glUseProgram(m_ShaderProgram) and glUseProgram(0);&#xD;&#xA;&#xD;&#xA;This is my draw method: &#xD;&#xA;&#xD;&#xA;    void Terrain::drawTest() {&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);&#xD;&#xA;&#xD;&#xA;        glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;        glEnableClientState(GL_NORMAL_ARRAY);&#xD;&#xA;&#xD;&#xA;        // setup position &amp; normal pointers&#xD;&#xA;        glVertexPointer(3, GL_FLOAT, sizeof(TerrainVertex), BUFFER_OFFSET(0));&#xD;&#xA;        glNormalPointer(GL_FLOAT, sizeof(TerrainVertex), BUFFER_OFFSET(12));&#xD;&#xA;&#xD;&#xA;        m_ShaderProgram.activate();&#xD;&#xA;        glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT, BUFFER_OFFSET(0));&#xD;&#xA;        m_ShaderProgram.deactivate();&#xD;&#xA;&#xD;&#xA;        glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;        glDisableClientState(GL_NORMAL_ARRAY);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And my shaders look like this:&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    varying vec3 Normal;&#xD;&#xA;    varying vec3 Position;&#xD;&#xA;    varying vec2 Texcoord;&#xD;&#xA;&#xD;&#xA;    void main(void) {&#xD;&#xA;	    Position = (gl_ModelViewMatrix * gl_Vertex).xyz;&#xD;&#xA;	    Normal = gl_NormalMatrix * gl_Normal;&#xD;&#xA;	    Texcoord = gl_MultiTexCoord0.xy;&#xD;&#xA;	    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    varying vec3 Normal;&#xD;&#xA;    varying vec3 Position;&#xD;&#xA;    varying vec2 Texcoord;&#xD;&#xA;   &#xD;&#xA;    void main(void) {&#xD;&#xA;	   gl_FragColor = vec4(1.0,1.0,0,0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Result:&#xD;&#xA;[![Terrain][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the fragment shader doesn't seem to do anything and I can't figure out what the problem is.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VzISb.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="19078" PostHistoryTypeId="24" PostId="3862" RevisionGUID="dc7cf9f4-92e0-4fc6-b42f-bb7a0e1ff2c6" CreationDate="2018-03-20T15:55:24.093" Comment="Proposed by 7220 approved by 209, 2041 edit id of 364" ContentLicense="CC BY-SA 3.0" />
  <row Id="19079" PostHistoryTypeId="5" PostId="418" RevisionGUID="20cfb12c-7395-42c7-a072-f79d32b6b520" CreationDate="2018-03-20T15:55:51.140" UserDisplayName="user7220" Comment="Corrected indents.." Text="Personally my choice of poison is Adobe Illustrator. Other apps such as inkscape, Corel Draw, Xara Designer will also do. In a pinch even PowerPoint will work. Though I do not personally recommend PowerPoint due to severe issues with its data model, even tough is possibly worlds most deployed drawing app.&#xD;&#xA;&#xD;&#xA;It can also be a good idea to have a graphing application at hand. I personally use Mathematica for this although many other apps would work too. Or if you want you can use Wolfram alpha that's a free online version of mathematica.&#xD;&#xA;&#xD;&#xA;Disclaimer: Because examples are mine and shameless self endorsement take with a pinch of salt.&#xD;&#xA;&#xD;&#xA;##Illustrator&#xD;&#xA;&#xD;&#xA;The first thing you should do in any vector drawing app is to *enable the snapping grid*. This reduces the tediousness of accurately placing lines. One of the big reasons i do not like to use Inkscape is the inferior way it implements this snapping. PowerPoint actually comes with grid snapping on by default. &#xD;&#xA;&#xD;&#xA;I am not really satisfied by Illustrator as it does not fill all my needs. But no software so far does (Maya used to fill this niche but then autodesk happened).&#xD;&#xA;&#xD;&#xA;The second reason i choose Illustrator is that it understands postscript natively. So if i need to program something i can do so quickly and existing documents update as my code matures Image 3 is done this way.&#xD;&#xA;&#xD;&#xA;* [Resource](https://graphicdesign.stackexchange.com/questions/37998/how-to-create-a-vector-curve-programmatically/38010#38010) showing snap, postscript and java script access to illustrator and links forward.&#xD;&#xA;&#xD;&#xA;Here are  some examples of drawings that I have done across the network with Illustrator, mostly by power of grid snap:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![Circle march][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One of many images i drew in illustrator on this site. Note: I am a quite experienced Illustrator (sometimes commercial) and this is extremely simple by my standards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Circle march image in is fairly simple to do. Just draw a random shape by clicking around. After this disable snap and let the smart guides do your work for you. Draw lines to closest point on the line, make circles to the line and (i deleted the guide lines after i was done). Rinse and repeat. It took me about 3-5 minutes to draw the image once i got my workspace started.&#xD;&#xA;&#xD;&#xA;![Continuation wave][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: GD.SE [Continuation wave](https://graphicdesign.stackexchange.com/questions/45929/what-is-this-design-pattern-called-continuation-wave/45936#45936).&#xD;&#xA;&#xD;&#xA;While this image seems quite more elaborate, its not much more work than the first image. It is more technical so in addition to grid snap I and now using the shift key to constrain lines to 45 degree angles. Hatch fills are easily just assigned to regions with the shape builder tool of illustrator. (example of [shape builder in use](https://graphicdesign.stackexchange.com/a/57267/18306), screen capture)&#xD;&#xA;&#xD;&#xA;![tetra image][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: Sometimes its easier to start from scratch in postscript. Image added to post on [ENG.SE](https://engineering.stackexchange.com/questions/2949/minimum-number-of-tetra-elements-required-to-represent-a-cube).&#xD;&#xA;&#xD;&#xA;Finally a image that really is easier to do by typing the values in postscript. It is relatively easy to do in postscript. Ive still done the typography in illustrator. While drawing this by hand is not a big deal i prefer not to, but i will do it if i must do judgement call by eye.&#xD;&#xA;&#xD;&#xA;## Mathematica&#xD;&#xA;&#xD;&#xA;Mathematica is wonderful if you want to explore things a bit more. The only drawback to Mathematica is that it is NOT cheap. But it can do nearly anything quickly. Ive used Mathematica for some of my pictures on of [nurbs basis](https://computergraphics.stackexchange.com/questions/358/nurbs-knot-multiplicity). &#xD;&#xA;&#xD;&#xA;One of Mathematicas core competencies s that its easy to develop even fairly complex pictures without much hassle. It can also easily animate your simple picture *within you editor*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Graphics[{&#xD;&#xA;        orig = {&#xD;&#xA;            Table[&#xD;&#xA;                GeometricTransformation[&#xD;&#xA;                    Line[{{0, 0}, {50, 0}}],&#xD;&#xA;                RotationTransform[ang]],&#xD;&#xA;                {ang, 0, 3 Pi/2, Pi/2}&#xD;&#xA;            ],&#xD;&#xA;            Line[{{20, 0}, {30, 20}, {40, 0}}]&#xD;&#xA;        },&#xD;&#xA;        Red,&#xD;&#xA;        GeometricTransformation[&#xD;&#xA;            orig,&#xD;&#xA;            RotationTransform[Pi/6]&#xD;&#xA;        ]&#xD;&#xA;    }]&#xD;&#xA;&#xD;&#xA;Results in same picture as others have. Wrapping it inside a table [as per](https://stackoverflow.com/questions/6109786/how-to-generate-animated-gif-of-a-manipulate-8-0-1) results in:&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Animation is simple to do inside the code editor using Mathematica.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]:https://i.stack.imgur.com/dFHFY.png&#xD;&#xA;  [2]:https://i.stack.imgur.com/Wg2jD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xUdRz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/5lcbX.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="19080" PostHistoryTypeId="24" PostId="418" RevisionGUID="20cfb12c-7395-42c7-a072-f79d32b6b520" CreationDate="2018-03-20T15:55:51.140" Comment="Proposed by 7220 approved by 209, 2041 edit id of 365" ContentLicense="CC BY-SA 3.0" />
  <row Id="19081" PostHistoryTypeId="5" PostId="7426" RevisionGUID="0d1ed747-3ea3-4a1f-8aa1-adab6b634460" CreationDate="2018-03-20T16:20:16.407" UserId="4981" Comment="Added code in javascript" Text="I have the parametric model of an ellipsoid like this:&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;x=a_1\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\ = _2\,cos\,\eta\:sin\,\omega \\ z=a_3\,sin \,\eta &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;n_x=\frac{1}{a_1}\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\n_ = \frac{1}{a_2}\,cos\,\eta\:sin\,\omega \\ n_z=\frac{1}{a_3}\,sin \,\eta &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;First of all I do not understand the last system of equation what it represents.&#xD;&#xA; Shouldn't  parameterisation of an ellipsoid be the first system alone?&#xD;&#xA;&#xD;&#xA;I have to create a polygon mesh (in webgl) from parametric model of ellipsoid. I can choose dimensions of semiaxes (namely values of $a_1$ $a_2$ and  $a_3$) and the sampling step of 2 angles (the parameters).  In this way I'm able to create in javascript with a little of code several vertices of ellipsoid. But I can't imagine how to realise the triangulation. Namely given the vertex buffer, I have to create the index buffer but in what way do I choose the indexes of the vertices to tessellate in a correct way ellipsoid surface? Is there a clever/smart way to proceed? &#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I implemented  that myself, in javascript (the code isn't debugged):&#xD;&#xA;&#xD;&#xA;     function calculateVNI()&#xD;&#xA;         {&#xD;&#xA;		 var indices = [];&#xD;&#xA;		 var vertices = [];&#xD;&#xA;		 var normals=[]&#xD;&#xA;		 var a1 =10;&#xD;&#xA;		 var a2 =5;&#xD;&#xA;		 var a3 =7;&#xD;&#xA;		 //var pi = Math.PI;&#xD;&#xA;&#xD;&#xA;		 var step_eta   = 4; //step in degree (choose a divisor of 360)&#xD;&#xA;	         var step_omega = 2; //step in degree (choose a divisor of 180)&#xD;&#xA;                 &#xD;&#xA;&#xD;&#xA;		 var eta,omega;&#xD;&#xA;		 var eta_rad,omega_rad;&#xD;&#xA;		 var index=0;&#xD;&#xA;		 var x=0;&#xD;&#xA;		 var y=1;&#xD;&#xA;		 var z=2;&#xD;&#xA;&#xD;&#xA;		 for(eta = -90 ; eta &lt;= 90 ; eta+=step_eta) //I could do the cycle in rad but I can have problems in condition of termination of the cycle (float value)&#xD;&#xA;	         {&#xD;&#xA;	            eta_rad = degToRad(eta);&#xD;&#xA;&#xD;&#xA;	            for(omega = -180 ; omega &lt;= 180 ; omega +=step_omega , index+=3)&#xD;&#xA;	            {&#xD;&#xA;	               omega_rad = degToRad(omega) &#xD;&#xA;	               vertices[index+x]= a1 * Math.cos(eta_rad) * Math.cos(omega_rad);&#xD;&#xA;	               vertices[index+y]= a2 * Math.cos(eta_rad) * Math.sin(omega_rad);&#xD;&#xA;	               vertices[index+z]= a3 * Math.sin(eta_rad);&#xD;&#xA;&#xD;&#xA;                       normals[index+x]= vertices[index+x] /(Math.pow(a1,2.0)) ;&#xD;&#xA;	               normals[index+y]= vertices[index+y] /(Math.pow(a2,2.0));&#xD;&#xA;	               normals[index+z]= vertices[index+z] /(Math.pow(a3,2.0));&#xD;&#xA;	            }&#xD;&#xA;	         }&#xD;&#xA;&#xD;&#xA;                 //Now triangolation. I believe that it needs a counterclockwise specification of vertices (else I have back-face)&#xD;&#xA;		 //each triangle is specified with 3 indices (gl.TRIANGLES).&#xD;&#xA;&#xD;&#xA;                 var num_samples_omega = 360/step_omega ; //Actually there is another sample that coincides with the first sample.&#xD;&#xA;		 var num_samples_eta   = 180/step_eta +1;&#xD;&#xA;&#xD;&#xA;                 var i,j;&#xD;&#xA;		 for(i=0,index=0 ; i&lt;=num_samples_eta ; i++) //il primo e l'ultimo campionamento coincidono con un solo punto ma va bene uguale&#xD;&#xA;		 {&#xD;&#xA;			 for(j=0 ; j&lt;num_samples_omega ; j++,index+=6)&#xD;&#xA;			 {&#xD;&#xA;	        	//Si definiscono ad ogni ciclo gli indici dei 2 triangoli del poligono formato da 4 campioni (due per ciascuna sezione di ellisse adiacente)&#xD;&#xA;				 indices[index]=i*num_samples_omega +j; //I could use index++ but like this is more clear.&#xD;&#xA;                                 indices[index+1]=(i+1)*num_samples_omega +1+j;&#xD;&#xA;				 indices[index+2]=(i+1)*num_samples_omega +j;&#xD;&#xA;&#xD;&#xA;				 indices[index+3]=i*num_samples_omega +j;&#xD;&#xA;				 indices[index+4]=i*num_samples_omega +1 +j;&#xD;&#xA;				 indices[index+5]=(i+1)*num_samples_omega +1 + j;&#xD;&#xA;			 }&#xD;&#xA;		 }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;         function degToRad(degrees)&#xD;&#xA;         {&#xD;&#xA;            return degrees * Math.PI / 180.0;&#xD;&#xA;         }" ContentLicense="CC BY-SA 3.0" />
  <row Id="19082" PostHistoryTypeId="2" PostId="7429" RevisionGUID="36fe93ab-597f-44db-a1a0-4ffcc769a81d" CreationDate="2018-03-20T17:24:04.687" UserId="3332" Text="I had an application that was originally **single threaded** and worked as follows:&#xD;&#xA;&#xD;&#xA; 1. gather the items to be drawn (occlusion / frustrum culling / sorting into batches)&#xD;&#xA; 2. draw items using an immediate context&#xD;&#xA; 3. present&#xD;&#xA;&#xD;&#xA;I decided to use a deferred context and **parallelize step 2** as follows:&#xD;&#xA;&#xD;&#xA; 1. gather the items to be drawn (occlusion / frustrum culling / sorting into batches)&#xD;&#xA; 2. draw items in parallel used a deferred context &#xD;&#xA; 3. execute the command lists for step 2)&#xD;&#xA; 4. present&#xD;&#xA;&#xD;&#xA;However, I saw almost no performance benefit.  I finally decided move the &quot;execute command lists&quot; after **present**:&#xD;&#xA;&#xD;&#xA; 1. gather the items to be drawn (occlusion / frustrum culling / sorting into batches)&#xD;&#xA; 2. draw items in parallel used a deferred context&#xD;&#xA; 3. present (is actually presenting the previous frame's scene now)&#xD;&#xA; 4. execute the command lists&#xD;&#xA;&#xD;&#xA;I saw a huge increase in performance with this method.  My theory as to why is this worked is that the are basically 3 bottlenecks&#xD;&#xA;&#xD;&#xA;1. graphics card (triggered by present)&#xD;&#xA;2. my app's cpu thread &#xD;&#xA;3. device driver cpu thread (triggered by executing the command lists)&#xD;&#xA;&#xD;&#xA;In my original order, each successive stage was blocked by the previous one to be finished.  However now, I believe that all three are running in parallel:&#xD;&#xA;&#xD;&#xA;1. present with (frame - 2) data&#xD;&#xA;2. device driver thread with (frame - 1) data&#xD;&#xA;3. my cpu thread to run with this frame's data&#xD;&#xA;&#xD;&#xA;My question is, is this a common pattern or is there some better way to achieve maximum parallization while using deffered context rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19083" PostHistoryTypeId="1" PostId="7429" RevisionGUID="36fe93ab-597f-44db-a1a0-4ffcc769a81d" CreationDate="2018-03-20T17:24:04.687" UserId="3332" Text="Drawing &quot;after&quot; Present to achieve better performance" ContentLicense="CC BY-SA 3.0" />
  <row Id="19084" PostHistoryTypeId="3" PostId="7429" RevisionGUID="36fe93ab-597f-44db-a1a0-4ffcc769a81d" CreationDate="2018-03-20T17:24:04.687" UserId="3332" Text="|directx11|directx|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19085" PostHistoryTypeId="5" PostId="7426" RevisionGUID="57695d15-c2ad-4be5-9d1d-6af48c23fa45" CreationDate="2018-03-20T20:49:57.600" UserId="4981" Comment="Debug of the code. The code now works!" Text="I have the parametric model of an ellipsoid like this:&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;x=a_1\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\ = _2\,cos\,\eta\:sin\,\omega \\ z=a_3\,sin \,\eta &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;\begin{cases}&#xD;&#xA;n_x=\frac{1}{a_1}\,cos \,\eta \:cos\,\omega  &amp; -\pi\leq\omega\leq\pi \\n_ = \frac{1}{a_2}\,cos\,\eta\:sin\,\omega \\ n_z=\frac{1}{a_3}\,sin \,\eta &amp; -\frac{\pi}{2}\leq\eta\leq\frac{\pi}{2}&#xD;&#xA;\end{cases}&#xD;&#xA;&#xD;&#xA;First of all I do not understand the last system of equation what it represents.&#xD;&#xA; Shouldn't  parameterisation of an ellipsoid be the first system alone?&#xD;&#xA;&#xD;&#xA;I have to create a polygon mesh (in webgl) from parametric model of ellipsoid. I can choose dimensions of semiaxes (namely values of $a_1$ $a_2$ and  $a_3$) and the sampling step of 2 angles (the parameters).  In this way I'm able to create in javascript with a little of code several vertices of ellipsoid. But I can't imagine how to realise the triangulation. Namely given the vertex buffer, I have to create the index buffer but in what way do I choose the indexes of the vertices to tessellate in a correct way ellipsoid surface? Is there a clever/smart way to proceed? &#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I implemented  that myself, in javascript (the code works):&#xD;&#xA;&#xD;&#xA;     function degToRad(degrees)&#xD;&#xA;         {&#xD;&#xA;            return degrees * Math.PI / 180.0;&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;         function calculateVNI()&#xD;&#xA;         {&#xD;&#xA;		 var indices = [];&#xD;&#xA;		 var vertices = [];&#xD;&#xA;		 var normals=[]&#xD;&#xA;		 var a1 =10;&#xD;&#xA;		 var a2 =5;&#xD;&#xA;		 var a3 =7;&#xD;&#xA;		 //var pi = Math.PI;&#xD;&#xA;&#xD;&#xA;		 var step_eta   = 4; //step in degree (choose a divisor of 360)&#xD;&#xA;	         var step_omega = 2; //step in degree (choose a divisor of 180)&#xD;&#xA;                 &#xD;&#xA;&#xD;&#xA;		 var eta,omega;&#xD;&#xA;		 var eta_rad,omega_rad;&#xD;&#xA;		 var index=0;&#xD;&#xA;		 var x=0;&#xD;&#xA;		 var y=1;&#xD;&#xA;		 var z=2;&#xD;&#xA;&#xD;&#xA;		 for(eta = -90 ; eta &lt;= 90 ; eta+=step_eta) //I could do the cycle in rad but I can have problems in condition of termination of the cycle (float value)&#xD;&#xA;	         {&#xD;&#xA;	            eta_rad = degToRad(eta);&#xD;&#xA;&#xD;&#xA;	            for(omega = -180 ; omega &lt;= 180 ; omega +=step_omega , index+=3)&#xD;&#xA;	            {&#xD;&#xA;	               omega_rad = degToRad(omega) &#xD;&#xA;	               vertices[index+x]= a1 * Math.cos(eta_rad) * Math.cos(omega_rad);&#xD;&#xA;	               vertices[index+y]= a2 * Math.cos(eta_rad) * Math.sin(omega_rad);&#xD;&#xA;	               vertices[index+z]= a3 * Math.sin(eta_rad);&#xD;&#xA;&#xD;&#xA;                       normals[index+x]= vertices[index+x] /(Math.pow(a1,2.0)) ;&#xD;&#xA;	               normals[index+y]= vertices[index+y] /(Math.pow(a2,2.0));&#xD;&#xA;	               normals[index+z]= vertices[index+z] /(Math.pow(a3,2.0));&#xD;&#xA;	            }&#xD;&#xA;	         }&#xD;&#xA;&#xD;&#xA;                 //Now triangolation. I believe that it needs a counterclockwise specification of vertices (else I have back-face)&#xD;&#xA;		 //each triangle is specified with 3 indices (gl.TRIANGLES).&#xD;&#xA;&#xD;&#xA;                 var num_samples_omega = 360/step_omega ;   //Actually there is another sample that coincides with the first sample.&#xD;&#xA;		 var num_samples_eta   = 180/step_eta ;&#xD;&#xA;&#xD;&#xA;                 var i,j;&#xD;&#xA;		 for(i=0,index=0 ; i&lt;num_samples_eta ; i++) //il primo e l'ultimo campionamento coincidono con un solo punto ma va bene uguale&#xD;&#xA;		 {&#xD;&#xA;			 for(j=0 ; j&lt;num_samples_omega ; j++,index+=6)&#xD;&#xA;			 {&#xD;&#xA;	        	//Si definiscono ad ogni ciclo gli indici dei 2 triangoli del poligono formato da 4 campioni (due per ciascuna sezione di ellisse adiacente)&#xD;&#xA;				 indices[index]=i*num_samples_omega +i+j; //I could use index++ but like this is more clear.&#xD;&#xA;                                 indices[index+1]=(i+1)*num_samples_omega +2+i+j;&#xD;&#xA;				 indices[index+2]=(i+1)*num_samples_omega +1+i+j;&#xD;&#xA;&#xD;&#xA;				 indices[index+3]=i*num_samples_omega +i+j;&#xD;&#xA;				 indices[index+4]=i*num_samples_omega +1 +i+j;&#xD;&#xA;				 indices[index+5]=(i+1)*num_samples_omega +2 +i+ j;&#xD;&#xA;			 }&#xD;&#xA;		 }&#xD;&#xA;&#xD;&#xA;      //alert(&quot;num vertici&quot;+vertices.length+&quot;\n&quot;+&quot;indice massimo:&quot;+ indices[index-1])&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;	 }&#xD;&#xA;&#xD;&#xA;	" ContentLicense="CC BY-SA 3.0" />
  <row Id="19086" PostHistoryTypeId="50" PostId="6291" RevisionGUID="65a3e3fc-86a2-481a-a2d5-b29ede136379" CreationDate="2018-03-20T23:44:51.820" UserId="-1" />
  <row Id="19087" PostHistoryTypeId="5" PostId="7429" RevisionGUID="2b64b217-3676-471c-9ffe-2d56a42ace3c" CreationDate="2018-03-21T02:10:18.263" UserId="3332" Comment="Spelling" Text="I had an application that was originally **single threaded** and worked as follows:&#xD;&#xA;&#xD;&#xA; 1. gather the items to be drawn (occlusion / frustrum culling / sorting into batches)&#xD;&#xA; 2. draw items using an immediate context&#xD;&#xA; 3. present&#xD;&#xA;&#xD;&#xA;I decided to use a deferred context and **parallelize step 2** as follows:&#xD;&#xA;&#xD;&#xA; 1. gather the items to be drawn (occlusion / frustrum culling / sorting into batches)&#xD;&#xA; 2. draw items in parallel used a deferred context &#xD;&#xA; 3. execute the command lists for step 2)&#xD;&#xA; 4. present&#xD;&#xA;&#xD;&#xA;However, I saw almost no performance benefit.  I finally decided move the &quot;execute command lists&quot; after **present**:&#xD;&#xA;&#xD;&#xA; 1. gather the items to be drawn (occlusion / frustrum culling / sorting into batches)&#xD;&#xA; 2. draw items in parallel used a deferred context&#xD;&#xA; 3. present (is actually presenting the previous frame's scene now)&#xD;&#xA; 4. execute the command lists&#xD;&#xA;&#xD;&#xA;I saw a huge increase in performance with this method.  My theory as to why is this worked is that the are basically 3 bottlenecks&#xD;&#xA;&#xD;&#xA;1. graphics card (triggered by present)&#xD;&#xA;2. my app's cpu thread &#xD;&#xA;3. device driver cpu thread (triggered by executing the command lists)&#xD;&#xA;&#xD;&#xA;In my original order, each successive stage was blocked by the previous one to be finished.  However now, I believe that all three are running in parallel:&#xD;&#xA;&#xD;&#xA;1. present with (frame - 2) data&#xD;&#xA;2. device driver thread with (frame - 1) data&#xD;&#xA;3. my cpu thread to run with this frame's data&#xD;&#xA;&#xD;&#xA;My question is, is this a common pattern or is there some better way to achieve maximum parallization while using deferred context rendering?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19088" PostHistoryTypeId="5" PostId="7427" RevisionGUID="4271d8b2-b8e9-4e0d-ad40-27ffb17e8bd3" CreationDate="2018-03-21T09:00:21.007" UserId="7647" Comment="Improved formula" Text="If you sample the two parameters $\eta$ and $\omega$ with steps $d\eta$ and $d\omega$, then you'll get a grid of points $v_{ij} = f(i\;d\eta,j\;d\omega)$.  Any four adjacent points will define a quadrilateral.  To get triangles, you just have to split each quad in two by a diagonal.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So in the example, you'd split the quadrilateral $\{v_{00},v_{01},v_{11},v_{10}\}$ into two triangles $\{v_{00},v_{01},v_{10}\}$ and $\{v_{01},v_{11},v_{10}\}$.  You'll want to make sure the points come in the right order so the triangle orientations match (or you'll end up backface-culling half of your triangles.)&#xD;&#xA;&#xD;&#xA;Your second equation, for $n_{xyz}$, is finding the *normal* of each vertex, which you can use for shading.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Fm0tG.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19089" PostHistoryTypeId="2" PostId="7430" RevisionGUID="229a0a64-c286-4482-b106-140e79e01fc1" CreationDate="2018-03-21T14:54:14.850" UserId="7008" Text="Taken from [Wikipedia's article on Cohen-Sutherland][1]:&#xD;&#xA;&#xD;&#xA;&gt; Both endpoints are in different regions: in case of this nontrivial situation the algorithm finds one of the two points that is outside the viewport region (there will be at least one point outside). The intersection of the outpoint and extended viewport border is then calculated (i.e. with the parametric equation for the line), and this new point replaces the outpoint. The algorithm repeats until a trivial accept or reject occurs.&#xD;&#xA;&#xD;&#xA;So yes, since your new first point is inside the viewport, but your second point is outside, the situation is non-trivial (i.e. no &quot;go render it all&quot; or &quot;go discard it all&quot;), it will repeat with the second point. Afterwards, both points will be inside the viewport, therefore it is a trivial draw and no further action is needed.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm" ContentLicense="CC BY-SA 3.0" />
  <row Id="19090" PostHistoryTypeId="2" PostId="7431" RevisionGUID="4db35c66-58e2-4773-b59a-7c1f26e72b43" CreationDate="2018-03-21T15:46:05.993" UserId="8415" Text="[![Picture here][1]][1]&#xD;&#xA;I unwrap UV from sphere mesh to grid and put texture to align with UV grid too. When white and black border of texture fall between UV columns, I get jagged edge like in the picture. This only happens with double-curve mesh. I want to know what cause this to happens?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rRahN.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="19091" PostHistoryTypeId="1" PostId="7431" RevisionGUID="4db35c66-58e2-4773-b59a-7c1f26e72b43" CreationDate="2018-03-21T15:46:05.993" UserId="8415" Text="Jagged texture's edge on perfectly straight UV of sphere mesh(Please see pictures)" ContentLicense="CC BY-SA 3.0" />
  <row Id="19092" PostHistoryTypeId="3" PostId="7431" RevisionGUID="4db35c66-58e2-4773-b59a-7c1f26e72b43" CreationDate="2018-03-21T15:46:05.993" UserId="8415" Text="|texture|shader|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19093" PostHistoryTypeId="2" PostId="7432" RevisionGUID="e9c5bc69-1c0a-424b-9d5d-7f3d0bee63bb" CreationDate="2018-03-21T19:54:33.507" UserId="5717" Text="It looks like distortion because the trapezoids are rendered as two triangles by the GPU. This leads to incorrect UV interpolation.&#xD;&#xA;&#xD;&#xA;Try this: draw a horizontally symmetrical trapezoid with the top being much shorter than the bottom. Then draw one of its diagonals to split it into two triangles. Place a mark at the midpoint of that diagonal. It should be obvious the mark is not at the horizontal center of the trapezoid. Yet that mark is where the middle of the interpolated texture coordinates will be. Your border will go through the mark but also through the center of the top and bottom edges.&#xD;&#xA;&#xD;&#xA;You should not have that problem when producing a final image with any decent renderer." ContentLicense="CC BY-SA 3.0" />
  <row Id="19094" PostHistoryTypeId="4" PostId="7431" RevisionGUID="a8307caa-d8e3-4e3d-9fbc-e71cb409ce13" CreationDate="2018-03-22T06:30:10.683" UserId="506" Comment="removed unnecessary annotation in title" Text="Jagged texture's edge on perfectly straight UV of sphere mesh" ContentLicense="CC BY-SA 3.0" />
  <row Id="19095" PostHistoryTypeId="24" PostId="7431" RevisionGUID="a8307caa-d8e3-4e3d-9fbc-e71cb409ce13" CreationDate="2018-03-22T06:30:10.683" Comment="Proposed by 506 approved by 3003, 8415 edit id of 367" ContentLicense="CC BY-SA 3.0" />
  <row Id="19096" PostHistoryTypeId="5" PostId="6422" RevisionGUID="aca25df9-5033-40c7-9bcd-9bfe494378ab" CreationDate="2018-03-22T12:37:41.187" UserId="209" Comment="Minor improvements to English" Text="Im writting a raytracer, for which I want to be able to test intersections with implicit surfaces (in my case spheres). Without applying any transformation it works great, but I would like to upgrade it to test intersections against non-uniform scaled spheres. For such purpose, I have computed the object's local to world matrix, as well as the world to local matrix.&#xD;&#xA;&#xD;&#xA;During the intersection test, I first transform the ray origin and direction to the object local space:&#xD;&#xA;&#xD;&#xA;    	Vector o = ray.getOrigin();&#xD;&#xA;    	Vector l = ray.getDirection();&#xD;&#xA;    &#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    	o = worldToLocalMatrix * o;&#xD;&#xA;    	l = worldToLocalMatrix * Vector(l.x, l.y, l.z, 0.0f);&#xD;&#xA;    	l = l.Normalize();&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;I perform the test, compute the intersection point in object's local space and then transform it back to world space:&#xD;&#xA;&#xD;&#xA;    Vector hitPoint(o + (l * distance));&#xD;&#xA;    		Vector hitNormal((hitPoint - center) / radius);&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;    #ifdef _RT_TRANSFORM_RAY_TO_LOCAL_SPACE&#xD;&#xA;    		hitPoint = localToWorldMatrix * hitPoint;&#xD;&#xA;    		hitNormal = localToWorldMatrix * Vector(hitNormal.x, hitNormal.y, hitNormal.z, 0.0f);&#xD;&#xA;    #endif&#xD;&#xA;    		hitNormal = hitNormal.Normalize();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I run the raytracer, it works great:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, from some points of view (not all), I obtain wrong renders from the dielectric sphere (center in the above image) and the perfect specular (right in the above image), as well as one of the cubes:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pwN09.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dro4c.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I just apply the affine transformations to the object's vertices and normals during start up(in the case of the sphere, I only apply translation since its an implicit surface), the render works flawlessly, so my guess its that the problem comes from the transformations applied to the ray.&#xD;&#xA;&#xD;&#xA;To compute the local to world matrix:&#xD;&#xA;`Model = rotation * translation * scale`&#xD;&#xA;&#xD;&#xA;To compute the world to local matrix:&#xD;&#xA;`InvModel = inverse(scale) * inverse(translation) * inverse(rotation)`&#xD;&#xA;&#xD;&#xA;I would like to know if I'm applying the transformation to the ray as well as to the output hit properly" ContentLicense="CC BY-SA 3.0" />
  <row Id="19097" PostHistoryTypeId="5" PostId="3833" RevisionGUID="ed9906e1-98c2-44c1-8d6c-e68107a1247b" CreationDate="2018-03-23T08:48:30.360" UserDisplayName="user7220" Comment="Corrected links.." Text="The rough definition of _&quot;MTP&quot;_ is clear. But the exact one is not. You can refer this links:&#xD;&#xA;&#xD;&#xA;- [What is Motion-To-Photon Latency? | chioka.in][1]&#xD;&#xA;- [Motion-to-photon latency | xinreality.com/wiki][2].&#xD;&#xA;&#xD;&#xA;But from different online articles, we get different definitions regarding how the value is measured:&#xD;&#xA;&#xD;&#xA;1. From [Atman Binstock (Oculus) blog][3], we can see:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(time to flip) - T1(Time of PO)`.&lt;br/&gt;&#xD;&#xA;   But, `T2` is just beginning to display the image, not finish displaying.&#xD;&#xA;&#xD;&#xA;2. From [John Carmack (Oculus) blog][4]:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(finish displaying) - T1(Time of PO)`.&#xD;&#xA;&#xD;&#xA;3. From Alex Vlachos (Valve) slides: _Advanced VR Rendering_, GDC 2015:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(finish displaying) - T1(Time of PO)`&#xD;&#xA;&#xD;&#xA;4. From [Qualcomm blog][5] (sorry it is in Chinese):&lt;br/&gt;&#xD;&#xA;  `MTP = T2(half of finish displaying) - T1(Time of PO)`&#xD;&#xA;&#xD;&#xA;I think Qualcomm's explanation is the best. If it is correct, we can relax the rendering time budget. What is your opinion?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.chioka.in/what-is-motion-to-photon-latency&#xD;&#xA;  [2]: http://xinreality.com/wiki/Motion-to-photon_latency&#xD;&#xA;  [3]: https://developer.oculus.com/blog/optimizing-vr-graphics-with-late-latching&#xD;&#xA;  [4]: http://www.chioka.in/what-is-motion-to-photon-latency/&#xD;&#xA;  [5]: http://www.qualcomm.cn/news/blog-2016-07-20" ContentLicense="CC BY-SA 3.0" />
  <row Id="19098" PostHistoryTypeId="24" PostId="3833" RevisionGUID="ed9906e1-98c2-44c1-8d6c-e68107a1247b" CreationDate="2018-03-23T08:48:30.360" Comment="Proposed by 7220 approved by -1 edit id of 370" ContentLicense="CC BY-SA 3.0" />
  <row Id="19099" PostHistoryTypeId="5" PostId="3833" RevisionGUID="88fe4be3-3da7-4060-8e06-ba42c1094448" CreationDate="2018-03-23T08:48:30.360" UserId="209" Comment="Corrected links.." Text="The rough definition of _&quot;MTP&quot;_ is clear. But the exact one is not. You can refer to these links:&#xD;&#xA;&#xD;&#xA;- [What is Motion-To-Photon Latency? | chioka.in][1]&#xD;&#xA;- [Motion-to-photon latency | xinreality.com/wiki][2].&#xD;&#xA;&#xD;&#xA;But from different online articles, we get different definitions regarding how the value is measured:&#xD;&#xA;&#xD;&#xA;1. From [Atman Binstock (Oculus) blog][3], we can see:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(time to flip) - T1(Time of PO)`.&lt;br/&gt;&#xD;&#xA;   But, `T2` is just beginning to display the image, not finish displaying.&#xD;&#xA;&#xD;&#xA;2. From [John Carmack (Oculus) blog][4]:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(finish displaying) - T1(Time of PO)`.&#xD;&#xA;&#xD;&#xA;3. From Alex Vlachos (Valve) slides: _Advanced VR Rendering_, GDC 2015:&lt;br/&gt;&#xD;&#xA;   `MTP = T2(finish displaying) - T1(Time of PO)`&#xD;&#xA;&#xD;&#xA;4. From [Qualcomm blog][5] (sorry it is in Chinese):&lt;br/&gt;&#xD;&#xA;  `MTP = T2(half of finish displaying) - T1(Time of PO)`&#xD;&#xA;&#xD;&#xA;I think Qualcomm's explanation is the best. If it is correct, we can relax the rendering time budget. What is your opinion?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.chioka.in/what-is-motion-to-photon-latency&#xD;&#xA;  [2]: http://xinreality.com/wiki/Motion-to-photon_latency&#xD;&#xA;  [3]: https://developer.oculus.com/blog/optimizing-vr-graphics-with-late-latching&#xD;&#xA;  [4]: http://www.chioka.in/what-is-motion-to-photon-latency/&#xD;&#xA;  [5]: http://www.qualcomm.cn/news/blog-2016-07-20" ContentLicense="CC BY-SA 3.0" />
  <row Id="19100" PostHistoryTypeId="2" PostId="7433" RevisionGUID="336b5970-744f-4259-a542-9ade3012fe39" CreationDate="2018-03-23T12:35:11.467" UserId="8434" Text="Here are its docs: [https://processing.org/reference][1].&#xD;&#xA;Processing is described as a 'language built with the purpose of teaching non-programmers the fundamentals of computer programming in a visual context'.  &#xD;&#xA;&#xD;&#xA;However, **how does this language relate to the real-world computer graphics tools**?  &#xD;&#xA;&#xD;&#xA;For example:  &#xD;&#xA;&#xD;&#xA; - Is it similar to some low-level library maybe?   &#xD;&#xA; - Is the concept of a repeating `draw() { background(255) }` (in order to draw each new frame of an animation) used in real-world libraries? &#xD;&#xA; - Are the same&#xD;&#xA;   methods/concepts used (`pushMatrix`, `popMatrix`, `rotate`,&#xD;&#xA;   `translate`)?&#xD;&#xA;&#xD;&#xA;  [1]: https://processing.org/reference" ContentLicense="CC BY-SA 3.0" />
  <row Id="19101" PostHistoryTypeId="1" PostId="7433" RevisionGUID="336b5970-744f-4259-a542-9ade3012fe39" CreationDate="2018-03-23T12:35:11.467" UserId="8434" Text="How does Processing language relate to the industry standard?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19102" PostHistoryTypeId="3" PostId="7433" RevisionGUID="336b5970-744f-4259-a542-9ade3012fe39" CreationDate="2018-03-23T12:35:11.467" UserId="8434" Text="|processing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19103" PostHistoryTypeId="2" PostId="7434" RevisionGUID="34a4dd05-7ed7-410e-aa42-c677a704d572" CreationDate="2018-03-23T13:37:40.120" UserId="8435" Text="One of my friend got a pretty pretty Chinese hand-writing font. However, the font has no bold version, since it is handwritten. And I would like to help generate a bold one automatically by code.&#xD;&#xA;&#xD;&#xA;I searched the Internet but didn't find any materials about it. My friend told me that his Kindle could &quot;bold&quot; that font automatically by setting &quot;contrast&quot;. So I tried to firstly convert the outline font to bitmap, then change the contrast of the glyphs one by one, and finally output a bitmap &quot;bolded&quot; font. Everything went well except the processed font is aliased, i.e. looks blocky, since that the bitmaps is binary images, i.e. there are no gray pixels. But I can't find a popular font type that supports bitmap plus gray pixels.&#xD;&#xA;&#xD;&#xA;So, is there an algorithm to bold an outline font? What is it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19104" PostHistoryTypeId="1" PostId="7434" RevisionGUID="34a4dd05-7ed7-410e-aa42-c677a704d572" CreationDate="2018-03-23T13:37:40.120" UserId="8435" Text="Is there an algorithm to bold an outline font? What is it?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19105" PostHistoryTypeId="3" PostId="7434" RevisionGUID="34a4dd05-7ed7-410e-aa42-c677a704d572" CreationDate="2018-03-23T13:37:40.120" UserId="8435" Text="|font-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19106" PostHistoryTypeId="2" PostId="7435" RevisionGUID="234ffdc3-ef74-4353-bf23-bb6866fbcd13" CreationDate="2018-03-23T15:46:21.137" UserId="5717" Text="I think [dilation][1] would be close enough to what you want.&#xD;&#xA;&#xD;&#xA;It is likely that font processing software would have more advanced algorithms to avoid rounding all the corners, among other things. Fonts are a whole separate world with a lot of rules about how things should be done to look right. No simple image processing algorithm will respect all those rules.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Dilation_(morphology)" ContentLicense="CC BY-SA 3.0" />
  <row Id="19107" PostHistoryTypeId="5" PostId="7428" RevisionGUID="7f8f3ce8-225f-44af-837f-6c44f468475f" CreationDate="2018-03-23T17:26:10.143" UserDisplayName="user7220" Comment="Corrected indents.." Text="Inside of my application I am trying to convert a MTLTexture into a CGImage or CIimage for use in other parts of the app. I am having a difficult time doing so because none of the example code I find seems to work properly.&#xD;&#xA;&#xD;&#xA;For some reason something breaks on each and every one of them. Here are my attempts and why they dont work. If you could give me ideas on why that would be appreciated.&#xD;&#xA;&#xD;&#xA;All of my textures are in brga8Unorm format.&#xD;&#xA;&#xD;&#xA;**Method 1** is to copy the pixels into an unsafe mutable pointer and use that to directly create a CGTexture. It creates a textures of all 0s&#xD;&#xA;&#xD;&#xA;    func toImage() -&gt; NSImage? {&#xD;&#xA;        let texture = self&#xD;&#xA;        let width = texture.width&#xD;&#xA;        let height = texture.height&#xD;&#xA;        let bytesPerRow = width * 4&#xD;&#xA;        let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;        defer {&#xD;&#xA;            data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        let region = MTLRegionMake2D(0, 0, width, height)&#xD;&#xA;        texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)&#xD;&#xA;        var buffer = vImage_Buffer(data: data, height: UInt(height), width: UInt(width), rowBytes: bytesPerRow)&#xD;&#xA;&#xD;&#xA;        let map: [UInt8] = [2, 1, 0, 3]&#xD;&#xA;        vImagePermuteChannels_ARGB8888(&amp;buffer, &amp;buffer, map, 0)&#xD;&#xA;&#xD;&#xA;        guard let colorSpace = CGColorSpace(name: CGColorSpace.genericRGBLinear) else { return nil }&#xD;&#xA;        guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow,&#xD;&#xA;                space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) else { return nil }&#xD;&#xA;        guard let cgImage = context.makeImage() else { return nil }&#xD;&#xA;&#xD;&#xA;        return NSImage(cgImage: cgImage, size: NSSize(width: width, height: height))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Method 2** tries to use CImage to do the job however CImage reports `Cannot render image (with an input Metal texture) using a metal context.` and returns nil&#xD;&#xA;&#xD;&#xA;    extension MTLTexture {&#xD;&#xA;        func toImage() -&gt; CGImage? {&#xD;&#xA;            let context = CIContext()&#xD;&#xA;            let texture = self&#xD;&#xA;            let cImg = CIImage(mtlTexture: texture, options: nil)!&#xD;&#xA;            let cgImg = context.createCGImage(cImg, from: cImg.extent)!&#xD;&#xA;            return cgImg&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**This last method** doesnt even try to convert the image it is just trying to determine if the image is blank (all 0s) or not however even on fully green or even textured images it says they are blank.&#xD;&#xA;&#xD;&#xA;    func anythingHere(_ texture: MTLTexture) -&gt; Bool {&#xD;&#xA;        let width = texture.width&#xD;&#xA;        let height = texture.height&#xD;&#xA;        let bytesPerRow = width * 4&#xD;&#xA;&#xD;&#xA;        let data = UnsafeMutableRawPointer.allocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;        defer {&#xD;&#xA;            data.deallocate(bytes: bytesPerRow * height, alignedTo: 4)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        let region = MTLRegionMake2D(0, 0, width, height)&#xD;&#xA;        texture.getBytes(data, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)&#xD;&#xA;        var bind = data.assumingMemoryBound(to: UInt8.self)&#xD;&#xA;&#xD;&#xA;        var sum:UInt8 = 0;&#xD;&#xA;        for i in 0..&lt;width*height {&#xD;&#xA;            sum += bind.pointee&#xD;&#xA;            bind = bind.advanced(by: 1)&#xD;&#xA;        }&#xD;&#xA;        return sum != 0&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Clearly I am doing something fundamentally wrong as none of these methods are actually producing results. What am I doing wrong? What is the right way to do this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19108" PostHistoryTypeId="24" PostId="7428" RevisionGUID="7f8f3ce8-225f-44af-837f-6c44f468475f" CreationDate="2018-03-23T17:26:10.143" Comment="Proposed by 7220 approved by 209, 5717 edit id of 366" ContentLicense="CC BY-SA 3.0" />
  <row Id="19109" PostHistoryTypeId="5" PostId="4761" RevisionGUID="95047228-4ed6-4f1c-8a60-617f9e5ea580" CreationDate="2018-03-23T17:29:15.663" UserDisplayName="user7220" Comment="Corrected links.." Text="I often use a 2D Perlin noise texture to displace a grid in the vertex shader (e.g. terrain, ocean).  However, every time I google the method to calculate post-displacement normals there is a slight difference.  For example, the value to place in the Y-component varies depending on the source.  In this example, they place a '1' in the Y-component prior to normalization:&#xD;&#xA;&#xD;&#xA;[Real-Time Parametric Shallow Wave Simulation | Intel® Software][1]&#xD;&#xA;&#xD;&#xA;Whereas in these codes, the value '2' is chosen:&#xD;&#xA;&#xD;&#xA;[Terrains, Normals, and a Heightmap | dian-xiang.com/blog][2]&#xD;&#xA;&#xD;&#xA;What gives?  Is there a definitive source for calculating normals from a height map?  &#xD;&#xA;&#xD;&#xA;Might this be related to unprojecting mouse clicks?  It always bothered me that you could throw a '0.5' in the Z-component, as mrdoob mentioned here:&#xD;&#xA;&#xD;&#xA;[Three.js Projector and Ray objects | Stack Overflow][3]&#xD;&#xA;&#xD;&#xA;Or use a '1' in the Z-component as Anton does here:&#xD;&#xA;&#xD;&#xA;[Mouse Picking with Ray Casting | Anton's OpenGL 4 Notes][4]&#xD;&#xA;&#xD;&#xA;Is there a connection between calculating normals from height maps and unprojecting mouse clicks?&#xD;&#xA;&#xD;&#xA;The second part of my question concerns choosing an epsilon to sample the height map.  Before I learned about height maps, I read about getting the normal from an implicit surface as in this link:&#xD;&#xA;&#xD;&#xA;[Fractals, computer graphics, mathematics, demoscene and more | Inigo Quilez Blog][5]&#xD;&#xA;&#xD;&#xA;It seems like the epsilon number is just made up though.  In my projects, I typically just fudge the value until it looks good.  Is there a definitive source, or at least a good rule of thumb?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://software.intel.com/en-us/articles/real-time-parametric-shallow-wave-simulation&#xD;&#xA;  [2]: http://www.dian-xiang.com/blog/2&#xD;&#xA;  [3]: https://stackoverflow.com/questions/11036106/three-js-projector-and-ray-objects&#xD;&#xA;  [4]: http://antongerdelan.net/opengl/raycasting.html&#xD;&#xA;  [5]: http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm" ContentLicense="CC BY-SA 3.0" />
  <row Id="19110" PostHistoryTypeId="24" PostId="4761" RevisionGUID="95047228-4ed6-4f1c-8a60-617f9e5ea580" CreationDate="2018-03-23T17:29:15.663" Comment="Proposed by 7220 approved by 209, 5717 edit id of 368" ContentLicense="CC BY-SA 3.0" />
  <row Id="19111" PostHistoryTypeId="5" PostId="6393" RevisionGUID="59662911-dfbf-44fb-919d-767a9c1c8639" CreationDate="2018-03-23T17:29:49.200" UserDisplayName="user7220" Comment="Corrected links.." Text="These older but informative article talks about how a Kaiser windowed sinc filter is a good way to generate mips.&#xD;&#xA;&#xD;&#xA;[The Inner Product - Mipmapping - Part 1 | Jonathan Blow][1]&#xD;&#xA;&#xD;&#xA;[The Inner Product - Mipmapping - Part 2 | Jonathan Blow][2]&#xD;&#xA;&#xD;&#xA;Unfortunately, the source code it mentions isn't anywhere to be found.&#xD;&#xA;&#xD;&#xA;Can anyone explain how a kaiser windowed sinc filter is calculated and/or give the kernel weights to use for convolution?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://number-none.com/product/Mipmapping,%20Part%201/index.html&#xD;&#xA;  [2]: http://number-none.com/product/Mipmapping,%20Part%202/index.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19112" PostHistoryTypeId="24" PostId="6393" RevisionGUID="59662911-dfbf-44fb-919d-767a9c1c8639" CreationDate="2018-03-23T17:29:49.200" Comment="Proposed by 7220 approved by 209, 5717 edit id of 369" ContentLicense="CC BY-SA 3.0" />
  <row Id="19113" PostHistoryTypeId="2" PostId="7436" RevisionGUID="f7e5da8d-f644-407d-a78f-e0212c31cca0" CreationDate="2018-03-23T17:47:15.733" UserId="38" Text="It does not relate to low level libraries. Yes, usually each frame is drawn separately, nothing can change if i dont change anything. However the draw loop is often handled by somebody else in for example game engines. So in fact processing is often lower level stuff than what many people would do day to day.&#xD;&#xA;&#xD;&#xA;Pushing matrix state is pretty common, it exists even in graphics languages from 1970's." ContentLicense="CC BY-SA 3.0" />
  <row Id="19114" PostHistoryTypeId="2" PostId="7437" RevisionGUID="f127524b-7237-4dcd-b322-5056100b6def" CreationDate="2018-03-23T18:14:18.193" UserId="8375" Text="New to writing shaders, please forgive any naivety in the question!&#xD;&#xA;&#xD;&#xA;Parallax mapping in any of its ray-marchy variants (e.g. steep parallax, cone step mapping, POM) generates fake geometry on a material, generally nearly indistinguishable from real geometry and at a much higher resolution than is practical using GPU tessellation. However, the geometry created does not extend outside the initial bounds of the triangle being rendered (unlike with GPU tessellation) - so e.g. a parallax mapped sphere still has circular edges.&#xD;&#xA;&#xD;&#xA;I'm want to try adapting a parallax shader (preferably OpenGL, any high quality variation of parallax mapping will do though I gather cone stepping is pretty much the state of the art) to write outside of the poly bounds using gl_FragDepth (and enabling conservative depth output).&#xD;&#xA;&#xD;&#xA;This seems to be theoretically possible (see this Unity example https://forum.unity.com/threads/modifying-depth-when-parallax-mapping.364037/). However that post did not include any shader code and got no responses.&#xD;&#xA;&#xD;&#xA;Is anyone aware of an existing implementation of this (with source available), or else could give me a good idea of how I should proceed with implementing it?&#xD;&#xA;&#xD;&#xA;Many thanks.   " ContentLicense="CC BY-SA 3.0" />
  <row Id="19115" PostHistoryTypeId="1" PostId="7437" RevisionGUID="f127524b-7237-4dcd-b322-5056100b6def" CreationDate="2018-03-23T18:14:18.193" UserId="8375" Text="Parallax/relief mapping with gl_FragDepth and conservative depth" ContentLicense="CC BY-SA 3.0" />
  <row Id="19116" PostHistoryTypeId="3" PostId="7437" RevisionGUID="f127524b-7237-4dcd-b322-5056100b6def" CreationDate="2018-03-23T18:14:18.193" UserId="8375" Text="|shader|raymarching|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19117" PostHistoryTypeId="2" PostId="7438" RevisionGUID="24005325-988c-4acf-9b13-5edbd86c815b" CreationDate="2018-03-23T18:43:14.263" UserId="3041" Text="I have a white line on black background. Because of the pixel geometry the line does not look really white; one edge looks red-isch, the other blue-isch. Other fore- and background yield other sensations. Pixel geometry is striped RGB, DPI is ~90, viewing distance about an arms length.&#xD;&#xA;&#xD;&#xA;Is there any software based solution or maybe visual design that makes this less appearant, assuming we know the screen pixel geometry in advance?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19118" PostHistoryTypeId="1" PostId="7438" RevisionGUID="24005325-988c-4acf-9b13-5edbd86c815b" CreationDate="2018-03-23T18:43:14.263" UserId="3041" Text="What remedies are there for percieved color artifacts due to pixel geometry?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19119" PostHistoryTypeId="3" PostId="7438" RevisionGUID="24005325-988c-4acf-9b13-5edbd86c815b" CreationDate="2018-03-23T18:43:14.263" UserId="3041" Text="|color|artifacts|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19120" PostHistoryTypeId="2" PostId="7439" RevisionGUID="7c2b8c20-7a9f-4a67-8b57-94a0c6623c5b" CreationDate="2018-03-23T18:46:29.013" UserId="8436" Text="In computer typography, the technique for adjusting strokes so that they align with the pixel grid is called [hinting][1].&#xD;&#xA;&#xD;&#xA;The color artifacts you are seeing are due to another technique called [subpixel rendering][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Font_hinting&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Subpixel_rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="19121" PostHistoryTypeId="5" PostId="7436" RevisionGUID="dd55f30f-65c8-4d67-b8e8-4f1c07741852" CreationDate="2018-03-23T18:48:26.047" UserId="38" Comment="added 5 characters in body" Text="It does not relate to low level libraries. Yes, usually each frame is drawn separately, nothing can change if i dont change anything. However the draw loop is often handled by somebody else in for example game engines, etc. So in fact processing is often lower level stuff than what many people would do day to day.&#xD;&#xA;&#xD;&#xA;Pushing matrix state is pretty common, it exists even in graphics languages from 1970's." ContentLicense="CC BY-SA 3.0" />
  <row Id="19122" PostHistoryTypeId="2" PostId="7440" RevisionGUID="bcacff6d-9b3c-4c9c-994e-9ff04d7ba8c6" CreationDate="2018-03-24T03:55:32.083" UserId="3003" Text="The best way to do proper outlines, is unfortunately, also the hardest. It involves calculating an offset curve, usually from the [medial axis](https://en.wikipedia.org/wiki/Medial_axis) or [straight skeletons](https://en.wikipedia.org/wiki/Straight_skeleton), which are non-trivial to calculate. Once you have those, you can calculate the distance of any point from the input object and decide whether to draw the outline or bolding, or not.&#xD;&#xA;&#xD;&#xA;A simpler way to do it, which doesn't look quite as nice, is to use a MinMax filter. This is a sliding 2D box filter that calculates either the minimum or maximum value within the box at each input pixel. If you have black text on a white background, you can use the min filter to generate an outline. Use the max if it's white text on a black background. Other shapes, such as a circular area will produce different results that may be better for some fonts. In most cases, you'll end up either rounding off or squaring off corners as the size of the filter increases." ContentLicense="CC BY-SA 3.0" />
  <row Id="19126" PostHistoryTypeId="50" PostId="6323" RevisionGUID="840ddcaf-8244-4af2-aad4-a1ae50dd6f7a" CreationDate="2018-03-24T22:21:22.817" UserId="-1" />
  <row Id="19127" PostHistoryTypeId="2" PostId="7442" RevisionGUID="c12b7f7c-70fc-427e-80b4-4aab9d6f45fa" CreationDate="2018-03-25T04:04:30.360" UserId="8444" Text="Sense nobody else has provided a more useful and to the point solution, I'll offer some crude theoretical grounds to a solution of a simpler but related problem. The issue of knowing at least if there are holes (let alone describing them). You could use the methods employed to solve Poincaré conjecture but for 3d sphere. &#xD;&#xA;&#xD;&#xA;If the 3d mesh can be suitably represented by a nice enough manifold, Ricci flow can be used. So in theory it is a matter of turning the discrete polygons into curved surfaces, and matching there curvature at boundaries. A suitable algorithm should exist for this, then solving roughly a diffusion differential equation ounce the continuous surface has been correctly parameterized. &#xD;&#xA;&#xD;&#xA;Intuitively I can only wager in cases that the surface is not homeomorphic to a sphere, the solution would be the minimum radius of the hole, thus describing the hole. &#xD;&#xA;&#xD;&#xA;Also I'm not sure that in cases there are more than one whole you would have multiple unique solutions. &#xD;&#xA;&#xD;&#xA;I'm not sure either if there are descretized theorems rather that go the other way and probably are better in terms of performance. " ContentLicense="CC BY-SA 3.0" />
  <row Id="19129" PostHistoryTypeId="5" PostId="1983" RevisionGUID="039d144d-02c8-43d9-a66c-5c7755bba911" CreationDate="2018-03-25T17:22:41.837" UserId="2574" Comment="added 1 character in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. [Instead of using $\epsilon$, which is the ratio  of the *altitude* to $R$, it may be useful to use $\eta$, the ratio of *the pinhole's distance to the Earth's center*, $h+R$, to the Earth's radius: $\eta=(R+h)/R=1+\epsilon$. In terms of $\eta$, we have $\varepsilon=1/\sqrt{\eta^{2}-1}$.]&#xD;&#xA;&#xD;&#xA;The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formulas, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon^{2}) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;The advantage of the canonical form is that it can deal with all conics on an equal footing, including in particular the case of the parabola, $\varepsilon=1$. In the ``standard'' formulation (see below), the case of the parabola can only be dealt with by taking the limit $\varepsilon\to 1$.&#xD;&#xA;&#xD;&#xA;Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(x-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$x_{0}=0$;&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case---note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); and&#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case).&#xD;&#xA;&#xD;&#xA;It is obvious that the parabolic case, $\varepsilon=1$, will create problems; as mentioned above, that case must be dealt with through taking the limit $\varepsilon\to 1$.&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19130" PostHistoryTypeId="5" PostId="1983" RevisionGUID="258c88d4-f1e5-4035-8ba2-3b7f307b17b6" CreationDate="2018-03-25T17:28:29.650" UserId="2574" Comment="added 1 character in body" Text="**What I'm asking for**&#xD;&#xA;&#xD;&#xA;I stress that I am **not asking for the formula**---I know the formula, and how to derive it. Several different versions of it are reproduced near the end of the post. In fact, someone else has not only derived it as well, but also nicely presented one of the derivations [here](https://goo.gl/FJjkHQ). &#xD;&#xA;&#xD;&#xA;What I need is a ***reputable source*** for the formula so that, for example, one could put it on Wikipedia without violating its [ban on reporting original research.](https://en.wikipedia.org/wiki/Wikipedia:No_original_research) [People have [actually tried](https://en.wikipedia.org/wiki/Talk:Horizon#About_the_.22curvature_of_the_horizon.22_section)... But the [relevant article](https://en.wikipedia.org/wiki/Horizon) has some very conscientious editor who deleted the section on the grounds of it being original research... and, well, unfortunately, the editor is correct, so there's not much point in trying to fight it.]&#xD;&#xA;&#xD;&#xA;**The reason I'm posting in Computer Graphics stackexchange**&#xD;&#xA;&#xD;&#xA;Since someone here might have modeled the way the Earth looks form orbit, perhaps he or she might know if this formula (or, more likely, some generalization of it) is published in some book, or journal, or conference proceedings, or class notes, etc.&#xD;&#xA;&#xD;&#xA;**I've done the &quot;due googling&quot;**&#xD;&#xA;&#xD;&#xA;Please understand that I'm not asking anyone to go searching for the answer on my behalf. I've done *lots* of googling already, and am only posting here as a last resort. My (far-fetched) hope is that someone here will simply *know* a reference right off the bat; if not... well, I hope at least you enjoyed the pretty picture below (if I do say so myself, with full awareness I'm talking to people interested in *computer graphics* of all things) before you moved on to bigger and better things.&#xD;&#xA;&#xD;&#xA;**Two sources that come close**&#xD;&#xA;&#xD;&#xA;1. D. K. Lynch, &quot;Visually discerning the curvature of the Earth,&quot; Applied Optics vol. 47, H39 (2008). It is freely available [here](http://thulescientific.com/Lynch%20Curvature%202008.pdf). Unfortunately, instead of doing it the right way (which is not that hard), the author opted for a hack, which (a) I don't completely understand, and (b) which doesn't agree with what I know to be the correct formula.&#xD;&#xA;&#xD;&#xA;2. R. Hartley and A. Zisserman, [*Multiple View Geometry in Computer Vision,*](http://www.amazon.com/Multiple-View-Geometry-Computer-Vision/dp/0521540518/) 2nd ed. (Cambridge University Press, Cambridge UK, 2004). In Sec. 8.3, &quot;Action of a projective camera on quadrics,&quot; we [read](https://goo.gl/IHvX2d):&#xD;&#xA;&#xD;&#xA;&gt; Suppose the quadric is a sphere, then the cone of rays between the&#xD;&#xA;&gt; camera centre and quadric is right-circular, i.e. the contour&#xD;&#xA;&gt; generator is a circle, with the plane of the circle orthogonal to the&#xD;&#xA;&gt; line joining the camera and sphere centres. This can be seen from the&#xD;&#xA;&gt; rotational symmetry of the geometry about this line. The image of the&#xD;&#xA;&gt; sphere is obtained by intersecting the cone with the image plane. It&#xD;&#xA;&gt; is clear that this is a classical conic section, so that the apparent&#xD;&#xA;&gt; contour of a sphere is a conic.&#xD;&#xA;&#xD;&#xA;In principle, this would be exactly what is needed, if only just a bit more information were included---at least an expression for the eccentricity of the conic as a function of the distance to the sphere and the sphere radius (in the case when the image plane is perpendicular to a [generatrix](https://en.wikipedia.org/wiki/Generatrix) of the cone, as is the case when the pinhole camera is directed at a point on the horizon).&#xD;&#xA;&#xD;&#xA;**Details about the formula for which I need a scholarly reference**&#xD;&#xA;&#xD;&#xA;We assume a perfectly spherical, perfectly smooth Earth with no atmosphere. We point an idealized pinhole camera at the horizon, and, using straightforward central projection, compute the shape of the image of the horizon on the back of the camera (i.e. the shape it will have on film---the &quot;film plane&quot;). Here's a graphic (made in [Asymptote](http://asymptote.sourceforge.net/), for those interested) that should make this clearer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As we saw above, the image of the horizon is a portion of a conic section. Let $\varepsilon$ be the eccentricity of the conic; the derivation [I mentioned above](https://goo.gl/FJjkHQ) instead uses a parameter $k$, which is just the inverse eccentricity: $k=1/\varepsilon$. The eccentricity itself is given as $\varepsilon=1/\sqrt{\epsilon(2+\epsilon)}$, where $\epsilon=h/R$ is the ratio of the altitude $h$ of the pinhole above the surface of the Earth and the Earth radius $R$. [Instead of using $\epsilon$, which is the ratio  of the *altitude* to $R$, it may be useful to use $\eta$, the ratio of *the pinhole's distance to the Earth's center*, $h+R$, to the Earth's radius: $\eta=(R+h)/R=1+\epsilon$. In terms of $\eta$, we have $\varepsilon=1/\sqrt{\eta^{2}-1}$.]&#xD;&#xA;&#xD;&#xA;The distance from the pinhole (point $P$ in the graphic) to the film plane is taken to be one unit length.&#xD;&#xA;&#xD;&#xA;The $y$-axis in the film plane is chosen to be parallel to the line joining the center of the Earth $C$ (not shown in the image) and the point on the horizon (labeled $V$ in the image) at which the camera is trained. This choice is well-defined because the line $CV$ must be parallel to the film plane. The reason for this is that both $CV$ and the film plane are perpendicular to the line of sight $PV$ (the line joining $P$ and $V$). And *that* is because 1. the line $PV$ is tangent to the Earth at $V$, thus perpendicular to $CV$, and 2. $PV$ is perpendicular to the film plane because the camera is trained at $V$. The $x$ axis is of course perpendicular to the $y$ axis and lies in the film plane, and the origin is chosen as the projection of the point $V$.&#xD;&#xA;&#xD;&#xA;With these definitions out of the way, we are ready to write down a representation of the conic section that is the image of the Earth's horizon. This can be written in many ways, some of which are given below. ***What I need is a reputable reference for any one of these formulas, or for a formula equivalent to them.***&#xD;&#xA;&#xD;&#xA;**1. The explicit formula given in the derivation mentioned above**&#xD;&#xA;&#xD;&#xA;The derivation [I mentioned above](https://goo.gl/FJjkHQ) gives this as the final version:&#xD;&#xA;&#xD;&#xA;$[\,y\,(1/\varepsilon-\varepsilon)-1\,]^{2}+x^{2}(1/\varepsilon^{2}-1)=1.$&#xD;&#xA;&#xD;&#xA;Let's represent this in a couple of additional ways.&#xD;&#xA;&#xD;&#xA;**2. Expression in terms of the canonical equation of a conic section**&#xD;&#xA;&#xD;&#xA;In this case, the equation takes [the following form](https://goo.gl/wIPjWs):&#xD;&#xA;&#xD;&#xA;$x^2=2\mu y-(1-\varepsilon^{2}) y^2$,&#xD;&#xA;&#xD;&#xA;where, in our case, $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;The advantage of the canonical form is that it can deal with all conics on an equal footing, including in particular the case of the parabola, $\varepsilon=1$. In the ``standard'' formulation (see below), the case of the parabola can only be dealt with by taking the limit $\varepsilon\to 1$.&#xD;&#xA;&#xD;&#xA;Details: the above formula holds in the case of a right circular cone, whose sides subtend an angle of $2\theta$, being intersected---at a distance $d$ from the vertex of the cone---by a plane at an angle $\omega$ relative to the cone axis. (To clarify: $d$ is the distance from the cone vertex to the point on the ellipse that is the closest to the cone vertex; that point is always one of the ends of the major axis of the ellipse). In this general case, the eccentricity is given as $\varepsilon=\cos \omega/\cos \theta$, while $\mu=d(\varepsilon-\cos|\omega+\theta|)$.&#xD;&#xA;&#xD;&#xA;In terms of the above graphic: $d$ is the distance from $P$ to the film plane (i.e., the distance along the dotted red line); $\theta$ is the angle between the dotted red line and the axis of the cone (which is the line joining $P$ and the center of the Earth---the extension of the black line labeled $h$ in the graphic); the angle $\omega$ is the angle between the axis of the cone and the film plane. &#xD;&#xA;&#xD;&#xA;Given that the film plane is perpendicular to the dotted red line, we have $\omega+\theta=\pi/2$; in addition, we take $d=1$, which then together give that $\mu=\varepsilon$. &#xD;&#xA;&#xD;&#xA;**3. Expression in terms of the ``standard form' of a conic section**&#xD;&#xA;&#xD;&#xA;This form is perhaps the most familiar:&#xD;&#xA;&#xD;&#xA;$\frac{(x-x_{0})^{2}}{p^2}+\frac{(y-y_{0})^{2}}{q^2}=1$.&#xD;&#xA;&#xD;&#xA;It is related to the parameters entering the canonical equation (see 2., above) as follows:&#xD;&#xA;&#xD;&#xA;$x_{0}=0$;&#xD;&#xA;&#xD;&#xA;$y_{0}=q=\frac{\mu}{1-\varepsilon^{2}}$ (which is $\frac{\varepsilon}{1-\varepsilon^{2}}$ in our case&amp;mdash;note that $y_{0}=q$ follows from the fact that the ellipse passes through the origin); and&#xD;&#xA;&#xD;&#xA;$p=q\smash[b]{\sqrt{|1-\varepsilon^{2}|}}=\frac{\mu}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ (which is $\frac{\varepsilon}{\smash[b]{\sqrt{|1-\varepsilon^{2}|}}}$ in our case).&#xD;&#xA;&#xD;&#xA;It is obvious that the parabolic case, $\varepsilon=1$, will create problems; as mentioned above, that case must be dealt with through taking the limit $\varepsilon\to 1$.&#xD;&#xA;&#xD;&#xA;**4. Expression in terms of a parametric curve**&#xD;&#xA;&#xD;&#xA;$x=\frac{(\epsilon+1) \cos (\alpha )}{\sin (\alpha )+\epsilon(\epsilon+2)}$&#xD;&#xA;&#xD;&#xA;$y=\frac{\sqrt{\epsilon (\epsilon+2)} (\sin (\alpha )-1)}{\sin (\alpha )+\epsilon (\epsilon+2)},$&#xD;&#xA;&#xD;&#xA;where $\alpha$ is the longitude of a point on the horizon, defined so that $\alpha=\pi/2$ corresponds to the point $V$ in the image above (i.e. to the point at which the pinhole camera is trained).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For how one might use these formulas, see [this](https://i.stack.imgur.com/FMWcM.jpg).&#xD;&#xA;&#xD;&#xA;**In conclusion...**&#xD;&#xA;&#xD;&#xA;Has anyone seen the formulas above in some reputable source, possibly in the context of modeling how the Earth looks from space? If so, could you let me know what this source was?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shaud.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19131" PostHistoryTypeId="2" PostId="7443" RevisionGUID="e229abf4-4aa7-4bfe-9c4e-a30b93984311" CreationDate="2018-03-25T18:41:47.993" UserId="8448" Text="Quite interesting! I'm the author of the valve signed distance paper. Sorry that it's a little sparse on implementation details.&#xD;&#xA;I only included the two channel example as future work - I didn't have a generator. I figured something like generating a high res sdf and then segmenting based upon the angle of the gradient of the sdf would be a reasonable tactic. But never got to it.&#xD;&#xA;Any multichannel scheme has to be weighed against using higher res single channel data of the same memory footprint, for the magnification ratios your app needs." ContentLicense="CC BY-SA 3.0" />
  <row Id="19132" PostHistoryTypeId="2" PostId="7444" RevisionGUID="af29e980-0934-4ce2-a098-0575d9eed9f7" CreationDate="2018-03-25T19:38:04.183" UserId="8449" Text="The Core i3 says it has &quot;integrated graphics&quot; with Intel 630.&#xD;&#xA;&#xD;&#xA;Does this mean it is like a mini GPU?&#xD;&#xA;&#xD;&#xA;In which case can use things like CUDA to speed up C sharp programs?&#xD;&#xA;&#xD;&#xA;Is there much software that takes advantage of integrated graphics? Like does photoshop access the integrated graphics?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19133" PostHistoryTypeId="1" PostId="7444" RevisionGUID="af29e980-0934-4ce2-a098-0575d9eed9f7" CreationDate="2018-03-25T19:38:04.183" UserId="8449" Text="Can you do GPGPU on integrated graphics like Intel HD 630 on Core i3?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19134" PostHistoryTypeId="3" PostId="7444" RevisionGUID="af29e980-0934-4ce2-a098-0575d9eed9f7" CreationDate="2018-03-25T19:38:04.183" UserId="8449" Text="|cuda|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19135" PostHistoryTypeId="2" PostId="7445" RevisionGUID="550450dd-6f36-4d28-b78c-ba8bc770eab3" CreationDate="2018-03-25T20:15:46.217" UserId="8450" Text="CUDA is only available on nvidia cards.&#xD;&#xA;&#xD;&#xA;The open technology is OpenCL: https://es.wikipedia.org/wiki/OpenCL&#xD;&#xA;&#xD;&#xA;GPGPU on non-nVidia GPU must be done with OpenCL." ContentLicense="CC BY-SA 3.0" />
  <row Id="19136" PostHistoryTypeId="50" PostId="6039" RevisionGUID="679453e1-63cb-4dcc-812b-8ea329559b92" CreationDate="2018-03-26T05:28:34.977" UserId="-1" />
  <row Id="19137" PostHistoryTypeId="5" PostId="7442" RevisionGUID="5a2083fa-e45b-41d6-8e9e-d1c5726620ad" CreationDate="2018-03-26T14:32:51.263" UserId="209" Comment="Minor spelling corrections" Text="Since nobody else has provided a more useful and to the point solution, I'll offer some crude theoretical grounds to a solution of a simpler but related problem. The issue of knowing at least if there are holes (let alone describing them). You could use the methods employed to solve Poincaré conjecture but for 3d sphere. &#xD;&#xA;&#xD;&#xA;If the 3d mesh can be suitably represented by a nice enough manifold, Ricci flow can be used. So in theory it is a matter of turning the discrete polygons into curved surfaces, and matching their curvature at boundaries. A suitable algorithm should exist for this, then solving roughly a diffusion differential equation once the continuous surface has been correctly parameterized. &#xD;&#xA;&#xD;&#xA;Intuitively I can only wager in cases that the surface is not homomorphic to a sphere, the solution would be the minimum radius of the hole, thus describing the hole. &#xD;&#xA;&#xD;&#xA;Also I'm not sure that in cases there are more than one whole you would have multiple unique solutions. &#xD;&#xA;&#xD;&#xA;I'm not sure either if there are discretized theorems rather that go the other way and probably are better in terms of performance. " ContentLicense="CC BY-SA 3.0" />
  <row Id="19138" PostHistoryTypeId="2" PostId="7446" RevisionGUID="8ce332ff-03d3-4b39-b1be-ddc54e1c91eb" CreationDate="2018-03-26T15:14:28.467" UserDisplayName="user2500" Text="What improvements and alternatives have been developed since HLBVH was introduced in the 2010 paper “HLBVH: Hierarcihcal LBVH Construction for Real-Time Ray Tracing of Dynamic Geometry” by J. Pantaleoni and D. Luebke (http://research.nvidia.com/publication/hlbvh-hierarchical-lbvh-construction-real-time-ray-tracing)?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19139" PostHistoryTypeId="1" PostId="7446" RevisionGUID="8ce332ff-03d3-4b39-b1be-ddc54e1c91eb" CreationDate="2018-03-26T15:14:28.467" UserDisplayName="user2500" Text="What techniques are used to build ray intersection acceleration structures on the GPU?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19140" PostHistoryTypeId="3" PostId="7446" RevisionGUID="8ce332ff-03d3-4b39-b1be-ddc54e1c91eb" CreationDate="2018-03-26T15:14:28.467" UserDisplayName="user2500" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19141" PostHistoryTypeId="5" PostId="7445" RevisionGUID="97da4093-42da-4224-9b73-babc64ef4962" CreationDate="2018-03-26T15:28:20.163" UserId="310" Comment="added 53 characters in body" Text="CUDA is only available on nvidia cards.&#xD;&#xA;&#xD;&#xA;The open technology is OpenCL: https://es.wikipedia.org/wiki/OpenCL&#xD;&#xA;&#xD;&#xA;Another alternative is to use Compute Shaders. DirectX, OpenGL, and Vulkan all support compute shaders" ContentLicense="CC BY-SA 3.0" />
  <row Id="19146" PostHistoryTypeId="33" PostId="7433" RevisionGUID="f372d7e6-a3cb-474b-94b9-9fd396502577" CreationDate="2018-03-27T03:34:14.280" UserId="8434" Comment="45" />
  <row Id="19147" PostHistoryTypeId="2" PostId="7448" RevisionGUID="2ae79ffc-8470-421c-adbf-7b79e4746840" CreationDate="2018-03-27T14:23:54.927" UserId="8460" Text="The great thing is we can finally predict scan-line exact raster accuracy with no access to a per-scanline query:&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=OZ7Loh830Ec&#xD;&#xA;&#xD;&#xA;I have come up with the exact microsecond-accurate formulas as a VSYNC offset, to predict the position of a tearline.  Tearlines during VSYNC OFF are always raster-exact, so you can steer them out of visibility during strip-level &quot;simulated front-buffer rendering&quot; via repeated VSYNC OFF buffer swapping.&#xD;&#xA;&#xD;&#xA;Pay attention to forum thread -- there is some open source code being continually added -- https://forums.blurbusters.com/viewtopic.php?f=10&amp;p=32002" ContentLicense="CC BY-SA 3.0" />
  <row Id="19148" PostHistoryTypeId="2" PostId="7449" RevisionGUID="0ffc3a80-0029-4d32-af5b-77f845fbbde2" CreationDate="2018-03-27T14:59:41.983" UserId="7107" Text="I'm planning the port of our DX based renderer to OpenGL. The target will be Desktop OpenGL 4.x. For DX we use shader reflection but as far as I know OpenGL just has *glGetProgramInterfaceiv* , *glGetUniform* and frieds. Theres also SPIR-V (I have never worked with it).&#xD;&#xA;&#xD;&#xA;My main concerns right now are:&#xD;&#xA;&#xD;&#xA; - **Using gl*:** it will be done at runtime, so this will be potentially slow as there are a lot of shaders to load (+ the interface is ugly as fuck). *EDIT: I guess this could be done on a prebuild step too (?).*&#xD;&#xA; - **Use SPIR-V:** means that we need to add another build step and I don't see much doc around. &#xD;&#xA;&#xD;&#xA;I would like to hear advice from people with experience with this.&#xD;&#xA;Thanks a lot!" ContentLicense="CC BY-SA 3.0" />
  <row Id="19149" PostHistoryTypeId="1" PostId="7449" RevisionGUID="0ffc3a80-0029-4d32-af5b-77f845fbbde2" CreationDate="2018-03-27T14:59:41.983" UserId="7107" Text="Dealing with GL reflection" ContentLicense="CC BY-SA 3.0" />
  <row Id="19150" PostHistoryTypeId="3" PostId="7449" RevisionGUID="0ffc3a80-0029-4d32-af5b-77f845fbbde2" CreationDate="2018-03-27T14:59:41.983" UserId="7107" Text="|opengl|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19151" PostHistoryTypeId="2" PostId="7450" RevisionGUID="8c4b24b8-8dbf-4ecb-9ed9-d9f024516cff" CreationDate="2018-03-27T19:55:48.717" UserId="56" Text="I'm encountering some issues supersampling in HDR for an SDR result and was curious what the usual method for doing this is.  Notice how pixelated the edge of the white sphere is.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here's how I render the image:&#xD;&#xA;&#xD;&#xA; 1. Get the (linear HDR) shaded color for 4 stratified samples per pixel.&#xD;&#xA; 2. Apply a box blur (average them)&#xD;&#xA; 3. Convert from linear to sRGB&#xD;&#xA; 4. Clamp to [0,1]&#xD;&#xA; 5. Convert from [0,1] to [0,255] and write the result.&#xD;&#xA;&#xD;&#xA;I believe the issue here is that along the edge of the white ssphere, the values are either very low (background color aprox 0.02) or very high (the sphere has a color of 10,10,10), and that combining them makes a number much larger than 1 which ends up getting clamped to 1, completely destroying the blending at the edges.&#xD;&#xA;&#xD;&#xA;That makes sense but now I'm not quite sure how to solve it.&#xD;&#xA;&#xD;&#xA;I tried applying Reinhard tone mapping after step 3, thinking that would help by keeping everything in the [0,1] range, and preserving the smoothness between the colors.  That helped only a very small amount.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My only other ideas for doing this are...&#xD;&#xA;&#xD;&#xA; 1. Blend my samples in sRGB space. This would be incorrect though.&#xD;&#xA; 2. At step 1.5 apply tone mapping to the samples, then at step 2.5, apply inverse tone mapping to the combined result.  This feels like a hack.&#xD;&#xA; 3. Use harmonic mean to combine the colors instead of a regular mean, to make the average favor smaller numbers when present.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IRvHA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/HjhjK.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19152" PostHistoryTypeId="1" PostId="7450" RevisionGUID="8c4b24b8-8dbf-4ecb-9ed9-d9f024516cff" CreationDate="2018-03-27T19:55:48.717" UserId="56" Text="Supersampling HDR" ContentLicense="CC BY-SA 3.0" />
  <row Id="19153" PostHistoryTypeId="3" PostId="7450" RevisionGUID="8c4b24b8-8dbf-4ecb-9ed9-d9f024516cff" CreationDate="2018-03-27T19:55:48.717" UserId="56" Text="|rendering|texture|subpixel-rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19154" PostHistoryTypeId="2" PostId="7451" RevisionGUID="2a55471b-a845-4755-bc5b-bb3ff61c04c6" CreationDate="2018-03-28T08:01:55.717" UserId="209" Text="If it's of interest, the Dreamcast had a &quot;racing the beam&quot; rendering mode, whereby it was able to dedicate a relatively small fraction of memory to framebuffer pixels (e.g.  64 scan lines) and it would render rows of 32 in turn, synchronised to the display update.  This however, was only used to save memory. I doubt anyone was generating &quot;modified&quot; geometry for latter parts of the display." ContentLicense="CC BY-SA 3.0" />
  <row Id="19155" PostHistoryTypeId="2" PostId="7452" RevisionGUID="e4a0468a-bc9d-44b3-8c17-d4795b260214" CreationDate="2018-03-28T08:34:31.547" UserId="137" Text="opengl has several methods that together let you reflect the shader IO.&#xD;&#xA;&#xD;&#xA;However it is much simpler if the shader IO is uniform across all your shaders. IOW have a set of default bindings/locations for everything. Then you only need some meta data for each shader where you deviate from those defaults for some reason.&#xD;&#xA;&#xD;&#xA;You then only need to query that the binding exists to see whether you need to provide the data. This has the added bonus that if an input gets optimized out you'll not waste time giving data it doesn't need." ContentLicense="CC BY-SA 3.0" />
  <row Id="19156" PostHistoryTypeId="2" PostId="7453" RevisionGUID="8b2f3b22-0180-4c7e-a1bd-f24e471e47aa" CreationDate="2018-03-28T13:16:43.943" UserId="3332" Text="I have some OpenGL based software and I would like to set up some automated testing using image comparison, but one problem we always have is that the screenshots we take always have some small differences across machines, usually due to graphics driver difference or something else (?).  &#xD;&#xA;&#xD;&#xA;What strategies are there for getting consistent screenshots across machines with varying hardware and graphics drivers?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19157" PostHistoryTypeId="1" PostId="7453" RevisionGUID="8b2f3b22-0180-4c7e-a1bd-f24e471e47aa" CreationDate="2018-03-28T13:16:43.943" UserId="3332" Text="How to take consistent screenshots across multiple machines?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19158" PostHistoryTypeId="3" PostId="7453" RevisionGUID="8b2f3b22-0180-4c7e-a1bd-f24e471e47aa" CreationDate="2018-03-28T13:16:43.943" UserId="3332" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19159" PostHistoryTypeId="50" PostId="5925" RevisionGUID="9079c98c-b7f0-4c70-b611-d63eafdd64e4" CreationDate="2018-03-28T13:40:22.410" UserId="-1" />
  <row Id="19165" PostHistoryTypeId="2" PostId="7455" RevisionGUID="e67f3b2f-fe34-49dc-823f-f6e7ad6173b6" CreationDate="2018-03-28T14:36:44.767" UserId="8375" Text="I suspect the answer is no, but thought I'd ask anyway.&#xD;&#xA;&#xD;&#xA;It seems that other than using nearest neighbour and bilinear interpolations, there is nothing you can do to determine how two adjacent pixels are interpolated ... such as applying an edge preserving interpolation, or adding some procedural variation. &#xD;&#xA;&#xD;&#xA;I'd love to be wrong! If indeed there is no way to do this, might there be a practical solution which involves creating a higher resolution (maybe much higher) texture (like a &quot;mipmap level -2&quot;) on the fly?&#xD;&#xA;&#xD;&#xA;If done naively I guess it would be very memory-hungry ... perhaps there is some way it could be done to a reusable buffer, or some way ensuring only part of the image would be processed at a time (like an OpenCL/CUDA/Compute Shader workgoup) thus limiting the buffer size. (Perhaps Vulkan could help somehow?)&#xD;&#xA;&#xD;&#xA;Obviously it would be done on a LOD basis ... no need to do it on far away textures.&#xD;&#xA;&#xD;&#xA;Thanks  " ContentLicense="CC BY-SA 3.0" />
  <row Id="19166" PostHistoryTypeId="1" PostId="7455" RevisionGUID="e67f3b2f-fe34-49dc-823f-f6e7ad6173b6" CreationDate="2018-03-28T14:36:44.767" UserId="8375" Text="Is sub-texel shading possible?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19167" PostHistoryTypeId="3" PostId="7455" RevisionGUID="e67f3b2f-fe34-49dc-823f-f6e7ad6173b6" CreationDate="2018-03-28T14:36:44.767" UserId="8375" Text="|shader|glsl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19168" PostHistoryTypeId="2" PostId="7456" RevisionGUID="cfb15b5d-1a01-4bba-8937-5536033cd149" CreationDate="2018-03-28T15:16:58.927" UserId="2654" Text="What you want cannot reasonably be done. No graphics API defines byte-accurate results. Every implementation will have its own variances, which will be visible in the results. OpenGL provides no insurance that you will get invariant results across implementations.&#xD;&#xA;&#xD;&#xA;At the end of the day, you can't do testing in this fashion." ContentLicense="CC BY-SA 3.0" />
  <row Id="19169" PostHistoryTypeId="2" PostId="7457" RevisionGUID="e0998c76-4ef8-49c2-9871-1c13cdd3f3c6" CreationDate="2018-03-28T15:38:56.060" UserId="2041" Text="Nicol Bolas explains why you can't expect pixel-accurate reproductions, but that doesn't mean you can't test with screenshots.&#xD;&#xA;&#xD;&#xA;Don't compare the screenshots byte-for-byte. Instead, use a *perceptual diff* to quantify how different the renders are. You can then set a threshold in your test and have the test fail if the renders are too different. A harsh threshold will let you filter out the rounding differences between platforms, and the slight differences around object silhouettes, but still detect objects in the wrong place or inconsistent texturing. A more forgiving threshold will allow bigger differences in texturing (or even with different shader versions or extensions, if you have different rendering paths for different hardware), and only complain if you have gross differences such as missing lights or a completely different scene being rendered.&#xD;&#xA;&#xD;&#xA;The [pdiff tool](http://pdiff.sourceforge.net/) is commonly used for this task, and I've set up test systems based on it before." ContentLicense="CC BY-SA 3.0" />
  <row Id="19171" PostHistoryTypeId="2" PostId="7458" RevisionGUID="f532459e-1489-4726-ae4b-35049a16a79d" CreationDate="2018-03-28T17:14:12.423" UserId="48" Text="The GPU hardware only supports nearest-neighbor, bilinear, trilinear, and anisotropic texture filtering. However, nothing stops you from implementing your own texture filtering in the pixel shader.&#xD;&#xA;&#xD;&#xA;To do this, you'd use [`textureGather`](http://docs.gl/sl4/textureGather) to grab a 2×2 block of texels around your sample point. Then you'd manually calculate the position of the sample point relative to the texel centers. Armed with the raw texels and the interpolation position, you can then apply whatever interpolation function you like.&#xD;&#xA;&#xD;&#xA;The position calculation would be something like this:&#xD;&#xA;&#xD;&#xA;    vec2 textureSize; // texture's width and height&#xD;&#xA;    vec2 offset = fract(texCoord * textureSize + (-0.5 + 1.0/512.0));&#xD;&#xA;&#xD;&#xA;The 1/512 offset in there is needed as a rounding correction on certain GPUs, to ensure that `fract()`'s output steps from 1 to 0 at the exact same point that `textureGather` switches texels.&#xD;&#xA;&#xD;&#xA;As an example, to re-implement bilinear filtering, you'd do this (assuming a single-channel texture for simplicity):&#xD;&#xA;&#xD;&#xA;    vec4 texels = textureGather(...);&#xD;&#xA;    float result = mix(mix(texels.w, texels.z, offset.x),&#xD;&#xA;                       mix(texels.x, texels.y, offset.x),&#xD;&#xA;                       offset.y);&#xD;&#xA;&#xD;&#xA;But in practice, you'd be replacing the above with your own interpolation logic. This will for sure be slower than using hardware bilinear interpolation, but it may be an acceptable cost for your app.&#xD;&#xA;&#xD;&#xA;If you need more than 2×2 block of texels, you can also use multiple calls to [`textureGatherOffset`](http://docs.gl/sl4/textureGatherOffset) to grab more of the surrounding region, 2×2 at a time.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;As for generating a higher-resolution version of the texture on the fly, that can certainly also be done. It would be an extension of texture streaming techniques that load larger mip levels from disk only when needed. Here, you'd be procedurally generating the larger mip levels instead of loading them, but it's a similar idea. Unfortunately I don't have a good reference handy for how to do this. (It's somewhat related to [virtual texturing](http://mrelusive.com/publications/presentations/2012_siggraph/Virtual_Texturing_in_Software_and_Hardware_final.pdf), but less complicated—for just plain texture streaming, you don't need sparse textures or a page table, etc.)&#xD;&#xA;&#xD;&#xA;However, there is unfortunately no GPU hardware support for doing the thing you suggested of avoiding the extra storage, by processing the texture only a piece at a time. Doing that in hardware (“texel shaders” that would generate texel values on-demand as they are sampled by fragment shaders) is an idea that has been proposed many times but so far has not happened.&#xD;&#xA;&#xD;&#xA;It might be possible to do it in software by having fragment shaders append sample requests into a queue, then switching to a different shader to service those requests, then re-running the fragment shaders with the results...but that would take a lot of work and might not be very fast. It would for sure be a research project. &#xD;&#xA;&#xD;&#xA;Unless you have a good way of determining in advance which texels are likely to be needed, it would be a lot more practical to just generate the entire texture, assuming memory and performance budgets allow for it." ContentLicense="CC BY-SA 3.0" />
  <row Id="19172" PostHistoryTypeId="50" PostId="6172" RevisionGUID="1812cb47-495e-48ef-aa39-9dab733cfd81" CreationDate="2018-03-28T17:40:33.560" UserId="-1" />
  <row Id="19175" PostHistoryTypeId="5" PostId="7446" RevisionGUID="a88279ee-1bd7-4804-bf81-3e3655fe8bc7" CreationDate="2018-03-29T12:08:17.183" UserId="2479" Comment="Inlined link, added tags." Text="What improvements and alternatives have been developed since HLBVH was introduced in the 2010 paper [HLBVH: Hierarcihcal LBVH Construction for Real-Time Ray Tracing of Dynamic Geometry][1] by J. Pantaleoni and D. Luebke?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://research.nvidia.com/publication/hlbvh-hierarchical-lbvh-construction-real-time-ray-tracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="19176" PostHistoryTypeId="6" PostId="7446" RevisionGUID="a88279ee-1bd7-4804-bf81-3e3655fe8bc7" CreationDate="2018-03-29T12:08:17.183" UserId="2479" Comment="Inlined link, added tags." Text="|raytracing|pathtracing|gpu|data-structure|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19177" PostHistoryTypeId="24" PostId="7446" RevisionGUID="a88279ee-1bd7-4804-bf81-3e3655fe8bc7" CreationDate="2018-03-29T12:08:17.183" Comment="Proposed by 2479 approved by 209, 2500 edit id of 371" ContentLicense="CC BY-SA 3.0" />
  <row Id="19180" PostHistoryTypeId="2" PostId="7460" RevisionGUID="53186891-2e0d-4d17-adcc-5f2b193e416f" CreationDate="2018-03-29T22:50:01.100" UserId="7871" Text="I'm receiving a non-energy conserving output while trying to importance sample the GGX Distributionof the Microfacet model, which is generally 3-4 times bigger than the resulting PDF&#xD;&#xA;&#xD;&#xA;I'm following this blog post: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/&#xD;&#xA;&#xD;&#xA;And I'm sampling the $\theta $ angle with the following formula / code:&#xD;&#xA;&#xD;&#xA;$$ \theta = acos(\sqrt{ \frac{1 - \epsilon}{\epsilon(\alpha^2 - 1) +1} }) $$&#xD;&#xA;&#xD;&#xA;    float sampleTheta(float roughness) {&#xD;&#xA;	    float random = rnd();&#xD;&#xA;	    return acos(&#xD;&#xA;		         sqrt(	      		(1.0f - random) /&#xD;&#xA;			    		((roughness * roughness - 1.0f) * random + 1.0f)&#xD;&#xA;		             )&#xD;&#xA;		       );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX Distribution function i'm using is:&#xD;&#xA;&#xD;&#xA;$$  \frac{ \alpha^2 }{\pi((\alpha^2 - 1) cos^2\theta + 1)^2}  $$&#xD;&#xA;&#xD;&#xA;    float MicroFacetMaterial::Distribution(vec3 normal, vec3 halfvector, float alpha) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float alpha2 = alpha * alpha;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    return alpha2 / (M_PI * a1 * a1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, the blog post derived this PDF to use along with the BRDF:&#xD;&#xA;&#xD;&#xA;$$ p_{h}(\theta) = \frac{2\alpha^2 \ cos\theta \ sin\theta}{((\alpha^2 - 1)cos^2\theta + 1 )^2 } \\ \ \\ \ \\ p(\theta) = \frac{p_{h}(\theta)}{ 4 (\omega i \cdot \omega h)} $$&#xD;&#xA;&#xD;&#xA;    float get_pdf(vec3 wo, vec3 normal, vec3 halfvector, float roughness) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float sin = sqrt(1.0f - NoH2);&#xD;&#xA;	    float alpha2 = roughness * roughness;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    float pdf_h = (2.0f * alpha2 * NoH * sin) / (a1 * a1);&#xD;&#xA;&#xD;&#xA;	    return pdf_h / (4.0f * dot(wo, halfvector));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And as a final step I'm calculating incident radiance as follow for a RGB non-recursive path tracer &#xD;&#xA;&#xD;&#xA;      float cosT = clampDot(newdirection, normal);&#xD;&#xA;      vec3 halfVector = HalfwayVector(-ray.d, newdirection);&#xD;&#xA;&#xD;&#xA;	  float pdf = get_pdf(-ray.direction, normal, halfVector, _roughness);&#xD;&#xA;&#xD;&#xA;	  float distribution = Distribution(normal, halfVector, _roughness);&#xD;&#xA;	  vec3 fresnel = FresnelColor(newdirection, halfVector, clampDot(halfVector, -ray.d));&#xD;&#xA;	  float geometry = Geometry(-ray.direction, newdirection, normal, halfVector);&#xD;&#xA;&#xD;&#xA;	  float denominator = 4.0f * clampDot(normal, -ray.direction) * clampDot(normal, newdirection);&#xD;&#xA;&#xD;&#xA;	  vec3 brdf = (distribution * fresnel * geometry) / (denominator);&#xD;&#xA;&#xD;&#xA;      mask = (albedo * brdf * cosT) / pdf;&#xD;&#xA;&#xD;&#xA;The output I'm getting is a model that behaves almost like a lightsource - while debugging, I saw the Distribution term normally is up to 4 times bigger than the respective PDF, I've also decided not to post the Geometry and Fresnel term since at least from the debugging I've done those are not contributing as much as the Distribution term (as expected)&#xD;&#xA;&#xD;&#xA;If anyone can confirm the above looks alright, I'll try to look for the error elsewhere" ContentLicense="CC BY-SA 3.0" />
  <row Id="19181" PostHistoryTypeId="1" PostId="7460" RevisionGUID="53186891-2e0d-4d17-adcc-5f2b193e416f" CreationDate="2018-03-29T22:50:01.100" UserId="7871" Text="Wrong output while implementing GGX importance sampling" ContentLicense="CC BY-SA 3.0" />
  <row Id="19182" PostHistoryTypeId="3" PostId="7460" RevisionGUID="53186891-2e0d-4d17-adcc-5f2b193e416f" CreationDate="2018-03-29T22:50:01.100" UserId="7871" Text="|raytracing|pathtracing|brdf|importance-sampling|microfacet|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19183" PostHistoryTypeId="5" PostId="7460" RevisionGUID="a4b98a4d-e1b8-492e-aa48-0ce9b3823aa6" CreationDate="2018-03-29T22:55:08.103" UserId="7871" Comment="edited body" Text="I'm receiving a non-energy conserving output while trying to importance sample the GGX Distributionof the Microfacet model, which is generally 3-4 times bigger than the resulting PDF&#xD;&#xA;&#xD;&#xA;I'm following this blog post: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/&#xD;&#xA;&#xD;&#xA;And I'm sampling the $\theta $ angle with the following formula / code:&#xD;&#xA;&#xD;&#xA;$$ \theta = acos(\sqrt{ \frac{1 - \epsilon}{\epsilon(\alpha^2 - 1) +1} }) $$&#xD;&#xA;&#xD;&#xA;    float sampleTheta(float roughness) {&#xD;&#xA;	    float random = rnd();&#xD;&#xA;	    return acos(&#xD;&#xA;		         sqrt(	      		(1.0f - random) /&#xD;&#xA;			    		((roughness * roughness - 1.0f) * random + 1.0f)&#xD;&#xA;		             )&#xD;&#xA;		       );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX Distribution function i'm using is:&#xD;&#xA;&#xD;&#xA;$$  \frac{ \alpha^2 }{\pi((\alpha^2 - 1) cos^2\theta + 1)^2}  $$&#xD;&#xA;&#xD;&#xA;    float MicroFacetMaterial::Distribution(vec3 normal, vec3 halfvector, float alpha) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float alpha2 = alpha * alpha;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    return alpha2 / (M_PI * a1 * a1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, the blog post derived this PDF to use along with the BRDF:&#xD;&#xA;&#xD;&#xA;$$ p_{h}(\theta) = \frac{2\alpha^2 \ cos\theta \ sin\theta}{((\alpha^2 - 1)cos^2\theta + 1 )^2 } \\ \ \\ \ \\ p(\theta) = \frac{p_{h}(\theta)}{ 4 (\omega o \cdot \omega h)} $$&#xD;&#xA;&#xD;&#xA;    float get_pdf(vec3 wo, vec3 normal, vec3 halfvector, float roughness) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float sin = sqrt(1.0f - NoH2);&#xD;&#xA;	    float alpha2 = roughness * roughness;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    float pdf_h = (2.0f * alpha2 * NoH * sin) / (a1 * a1);&#xD;&#xA;&#xD;&#xA;	    return pdf_h / (4.0f * dot(wo, halfvector));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And as a final step I'm calculating incident radiance as follow for an RGB non-recursive path tracer &#xD;&#xA;&#xD;&#xA;      float cosT = clampDot(newdirection, normal);&#xD;&#xA;      vec3 halfVector = HalfwayVector(-ray.d, newdirection);&#xD;&#xA;&#xD;&#xA;	  float pdf = get_pdf(-ray.direction, normal, halfVector, _roughness);&#xD;&#xA;&#xD;&#xA;	  float distribution = Distribution(normal, halfVector, _roughness);&#xD;&#xA;	  vec3 fresnel = FresnelColor(newdirection, halfVector, clampDot(halfVector, -ray.d));&#xD;&#xA;	  float geometry = Geometry(-ray.direction, newdirection, normal, halfVector);&#xD;&#xA;&#xD;&#xA;	  float denominator = 4.0f * clampDot(normal, -ray.direction) * clampDot(normal, newdirection);&#xD;&#xA;&#xD;&#xA;	  vec3 brdf = (distribution * fresnel * geometry) / (denominator);&#xD;&#xA;&#xD;&#xA;      mask = (albedo * brdf * cosT) / pdf;&#xD;&#xA;&#xD;&#xA;The output I'm getting is a model that behaves almost like a lightsource - while debugging, I saw the Distribution term normally is up to 4 times bigger than the respective PDF, I've also decided not to post the Geometry and Fresnel term since at least from the debugging I've done those are not contributing as much as the Distribution term (as expected)&#xD;&#xA;&#xD;&#xA;If anyone can confirm the above looks alright, I'll try to look for the error elsewhere" ContentLicense="CC BY-SA 3.0" />
  <row Id="19185" PostHistoryTypeId="2" PostId="7461" RevisionGUID="f64263d0-fd8e-4518-91d6-45884ccb53a9" CreationDate="2018-03-30T19:03:41.637" UserId="5005" Text="I'm trying to implement radiosity normal maps from the old Valve paper:&#xD;&#xA;&#xD;&#xA;http://www.valvesoftware.com/publications/2004/GDC2004_Half-Life2_Shading.pdf&#xD;&#xA;&#xD;&#xA;I've tried generating the light maps using Vray and 3dStudio max, by overriding the normals to point in these three directions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CnS5u.png&#xD;&#xA;&#xD;&#xA;It works to an extent, applying normal maps over walls and such makes them appear like they are light mapped and bumpy. It's when I set the normal map to (128,128,255) that i can't get the same result as if it were a regular light map and i see artifacts. &#xD;&#xA;&#xD;&#xA;I'm not sure if understand at all how the basis is used to capture light, so i omitted the GI part and tried to bake just a directional light. &#xD;&#xA;&#xD;&#xA;If i set a directional light at `(-1,0,0)` in the basis from the picture above, the first dot product (red arrow) will be less than 0, however both the green and the blue will get some value from that light. &#xD;&#xA;&#xD;&#xA;Same way if i set it at `(1,0,0)` there will be some value greater than 0, and two less than.&#xD;&#xA;&#xD;&#xA;This doesn't make sense, the directional light at this angle shouldn't contribute any light to this surface?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19186" PostHistoryTypeId="1" PostId="7461" RevisionGUID="f64263d0-fd8e-4518-91d6-45884ccb53a9" CreationDate="2018-03-30T19:03:41.637" UserId="5005" Text="Radiosity normal map light baking" ContentLicense="CC BY-SA 3.0" />
  <row Id="19187" PostHistoryTypeId="3" PostId="7461" RevisionGUID="f64263d0-fd8e-4518-91d6-45884ccb53a9" CreationDate="2018-03-30T19:03:41.637" UserId="5005" Text="|lighting|real-time|global-illumination|radiosity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19190" PostHistoryTypeId="5" PostId="7449" RevisionGUID="23805f63-ec08-47bb-b15a-98e6e16eb728" CreationDate="2018-03-30T20:08:13.493" UserId="231" Comment="Remove &quot;thanks&quot; and edit marker (the edit history is available for anyone who wants it)" Text="I'm planning the port of our DX based renderer to OpenGL. The target will be Desktop OpenGL 4.x. For DX we use shader reflection but as far as I know OpenGL just has *glGetProgramInterfaceiv* , *glGetUniform* and frieds. Theres also SPIR-V (I have never worked with it).&#xD;&#xA;&#xD;&#xA;My main concerns right now are:&#xD;&#xA;&#xD;&#xA; - **Using gl:** it will be done at runtime, so this will be potentially slow as there are a lot of shaders to load (+ the interface is ugly). *I guess this could be done on a prebuild step too (?).*&#xD;&#xA; - **Use SPIR-V:** means that we need to add another build step and I don't see much doc around. &#xD;&#xA;&#xD;&#xA;I would like to hear advice from people with experience with this." ContentLicense="CC BY-SA 3.0" />
  <row Id="19191" PostHistoryTypeId="5" PostId="7461" RevisionGUID="358dd2a1-324b-4777-8712-8937b7e62bbd" CreationDate="2018-03-31T04:01:39.950" UserId="5005" Comment="added 87 characters in body" Text="I'm trying to implement radiosity normal maps from the old Valve paper:&#xD;&#xA;&#xD;&#xA;http://www.valvesoftware.com/publications/2004/GDC2004_Half-Life2_Shading.pdf&#xD;&#xA;&#xD;&#xA;I've tried generating the light maps using Vray and 3dStudio max, by overriding the normals to point in these three directions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It works to an extent, applying normal maps over walls and such makes them appear like they are light mapped and bumpy. It's when I set the normal map to (128,128,255) that i can't get the same result as if it were a regular light map and i see artifacts. &#xD;&#xA;&#xD;&#xA;I'm not sure if understand at all how the basis is used to capture light, so i omitted the GI part and tried to bake just a directional light. &#xD;&#xA;&#xD;&#xA;If i set a directional light at `(-1,0,0)` in the basis from the picture above, the first dot product (red arrow) will be less than 0, however both the green and the blue will get some value from that light. &#xD;&#xA;&#xD;&#xA;Same way if i set it at `(1,0,0)` there will be some value greater than 0, and two less than.&#xD;&#xA;&#xD;&#xA;This doesn't make sense, the directional light at this angle shouldn't contribute any light to this surface?&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;It feels like it's missing some negative light (?). &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CnS5u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bw1Iv.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19192" PostHistoryTypeId="5" PostId="7461" RevisionGUID="40850da2-da16-4ff1-a986-c4a6019fefb5" CreationDate="2018-03-31T04:07:19.660" UserId="5005" Comment="added 87 characters in body" Text="I'm trying to implement radiosity normal maps from the old Valve paper:&#xD;&#xA;&#xD;&#xA;http://www.valvesoftware.com/publications/2004/GDC2004_Half-Life2_Shading.pdf&#xD;&#xA;&#xD;&#xA;I've tried generating the light maps using Vray and 3dStudio max, by overriding the normals to point in these three directions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It works to an extent, applying normal maps over walls and such makes them appear like they are light mapped and bumpy. It's when I set the normal map to (128,128,255) that i can't get the same result as if it were a regular light map and i see artifacts. &#xD;&#xA;&#xD;&#xA;I'm not sure if understand at all how the basis is used to capture light, so i omitted the GI part and tried to bake just a directional light. &#xD;&#xA;&#xD;&#xA;If i set a directional light at `(-1,0,0)` in the basis from the picture above, the first dot product (red arrow) will be less than 0, however both the green and the blue will get some value from that light. &#xD;&#xA;&#xD;&#xA;Same way if i set it at `(1,0,0)` there will be some value greater than 0, and two less than.&#xD;&#xA;&#xD;&#xA;This doesn't make sense, the directional light at this angle shouldn't contribute any light to this surface?&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The white arrow represents the light dir to be baked. The red one is pretty affected by it, but then scaling it by 1/3 doesn't really help much. &#xD;&#xA;It feels like it's missing some negative light (?). &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CnS5u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bw1Iv.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19193" PostHistoryTypeId="5" PostId="7461" RevisionGUID="ba7bc687-760d-469b-8a8f-8369073e4aed" CreationDate="2018-03-31T04:19:14.910" UserId="5005" Comment="added 129 characters in body" Text="I'm trying to implement radiosity normal maps from the old Valve paper:&#xD;&#xA;&#xD;&#xA;http://www.valvesoftware.com/publications/2004/GDC2004_Half-Life2_Shading.pdf&#xD;&#xA;&#xD;&#xA;I've tried generating the light maps using Vray and 3dStudio max, by overriding the normals to point in these three directions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It works to an extent, applying normal maps over walls and such makes them appear like they are light mapped and bumpy. It's when I set the normal map to (128,128,255) that i can't get the same result as if it were a regular light map and i see artifacts. &#xD;&#xA;&#xD;&#xA;I'm not sure if understand at all how the basis is used to capture light, so i omitted the GI part and tried to bake just a directional light. &#xD;&#xA;&#xD;&#xA;If i set a directional light at `(-1,0,0)` in the basis from the picture above, the first dot product (red arrow) will be less than 0, however both the green and the blue will get some value from that light. &#xD;&#xA;&#xD;&#xA;Same way if i set it at `(1,0,0)` there will be some value greater than 0, and two less than.&#xD;&#xA;&#xD;&#xA;This doesn't make sense, the directional light at this angle shouldn't contribute any light to this surface?&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The white arrow represents the light dir to be baked. The red one is pretty affected by it, but then scaling it by 1/3 doesn't really help much. &#xD;&#xA;It feels like it's missing some negative light (?). &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here it is with (1,1,1) normalized ^&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CnS5u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bw1Iv.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/LrMt0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19195" PostHistoryTypeId="8" PostId="7449" RevisionGUID="d18a7540-78dc-4e4d-b3a5-7b6953852f55" CreationDate="2018-03-31T23:31:14.933" UserId="7107" Comment="Rollback to [0ffc3a80-0029-4d32-af5b-77f845fbbde2]" Text="I'm planning the port of our DX based renderer to OpenGL. The target will be Desktop OpenGL 4.x. For DX we use shader reflection but as far as I know OpenGL just has *glGetProgramInterfaceiv* , *glGetUniform* and frieds. Theres also SPIR-V (I have never worked with it).&#xD;&#xA;&#xD;&#xA;My main concerns right now are:&#xD;&#xA;&#xD;&#xA; - **Using gl*:** it will be done at runtime, so this will be potentially slow as there are a lot of shaders to load (+ the interface is ugly as fuck). *EDIT: I guess this could be done on a prebuild step too (?).*&#xD;&#xA; - **Use SPIR-V:** means that we need to add another build step and I don't see much doc around. &#xD;&#xA;&#xD;&#xA;I would like to hear advice from people with experience with this.&#xD;&#xA;Thanks a lot!" ContentLicense="CC BY-SA 3.0" />
  <row Id="19197" PostHistoryTypeId="5" PostId="7460" RevisionGUID="9971e948-12f3-4f55-9ead-b1bca523bd2e" CreationDate="2018-04-01T00:32:50.697" UserId="7871" Comment="added 16 characters in body" Text="I'm receiving a non-energy conserving output while trying to importance sample the GGX Distributionof the Microfacet model, which is generally 3-4 times bigger than the resulting PDF&#xD;&#xA;&#xD;&#xA;I'm following this blog post: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/&#xD;&#xA;&#xD;&#xA;And I'm sampling the $\theta $ angle with the following formula / code:&#xD;&#xA;&#xD;&#xA;$$ \theta = acos(\sqrt{ \frac{1 - \epsilon}{\epsilon(\alpha^2 - 1) +1} }) $$&#xD;&#xA;&#xD;&#xA;    float sampleTheta(float roughness) {&#xD;&#xA;	    float random = rnd();&#xD;&#xA;	    return acos(&#xD;&#xA;		         sqrt(	      		(1.0f - random) /&#xD;&#xA;			    		((roughness * roughness - 1.0f) * random + 1.0f)&#xD;&#xA;		             )&#xD;&#xA;		       );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX Distribution function i'm using is:&#xD;&#xA;&#xD;&#xA;$$  \frac{ \alpha^2 }{\pi((\alpha^2 - 1) cos^2\theta + 1)^2}  $$&#xD;&#xA;&#xD;&#xA;    float MicroFacetMaterial::Distribution(vec3 normal, vec3 halfvector, float alpha) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float alpha2 = alpha * alpha;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    return alpha2 / (M_PI * a1 * a1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, the blog post derived this PDF to use along with the BRDF:&#xD;&#xA;&#xD;&#xA;$$ p_{h}(\theta) = \frac{2\alpha^2 \ cos\theta \ sin\theta}{((\alpha^2 - 1)cos^2\theta + 1 )^2 } \\ \ \\ \ \\ p(\theta) = \frac{p_{h}(\theta)}{ 4 (\omega o \cdot \omega h)} $$&#xD;&#xA;&#xD;&#xA;    float get_pdf(vec3 wo, vec3 normal, vec3 halfvector, float roughness) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float sin = sqrt(1.0f - NoH2);&#xD;&#xA;	    float alpha2 = roughness * roughness;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    float pdf_h = (2.0f * alpha2 * NoH * sin) / (a1 * a1);&#xD;&#xA;&#xD;&#xA;	    return pdf_h / (4.0f * dot(wo, halfvector));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And as a final step I'm calculating incident radiance as follow for an RGB non-recursive path tracer &#xD;&#xA;&#xD;&#xA;      float cosT = clampDot(newdirection, normal);&#xD;&#xA;      vec3 halfVector = HalfwayVector(-ray.direction, newdirection);&#xD;&#xA;&#xD;&#xA;	  float pdf = get_pdf(-ray.direction, normal, halfVector, _roughness);&#xD;&#xA;&#xD;&#xA;	  float distribution = Distribution(normal, halfVector, _roughness);&#xD;&#xA;	  vec3 fresnel = FresnelColor(newdirection, halfVector, clampDot(halfVector, -ray.direction));&#xD;&#xA;	  float geometry = Geometry(-ray.direction, newdirection, normal, halfVector);&#xD;&#xA;&#xD;&#xA;	  float denominator = 4.0f * clampDot(normal, -ray.direction) * clampDot(normal, newdirection);&#xD;&#xA;&#xD;&#xA;	  vec3 brdf = (distribution * fresnel * geometry) / (denominator);&#xD;&#xA;&#xD;&#xA;      mask = (albedo * brdf * cosT) / pdf;&#xD;&#xA;&#xD;&#xA;The output I'm getting is a model that behaves almost like a lightsource - while debugging, I saw the Distribution term normally is up to 4 times bigger than the respective PDF, I've also decided not to post the Geometry and Fresnel term since at least from the debugging I've done those are not contributing as much as the Distribution term (as expected)&#xD;&#xA;&#xD;&#xA;If anyone can confirm the above looks alright, I'll try to look for the error elsewhere" ContentLicense="CC BY-SA 3.0" />
  <row Id="19198" PostHistoryTypeId="2" PostId="7462" RevisionGUID="f5e7cb2d-dcd5-498a-98df-8185089f44aa" CreationDate="2018-04-01T07:08:29.850" UserId="8487" Text="[![Task][1]][1]&#xD;&#xA;&#xD;&#xA;Hello. How do i calculate angle `C`.&#xD;&#xA;I can only know what angle between vector and x positive vector {1, 0}&#xD;&#xA;&#xD;&#xA;Angle between green and red is 60 degrees&#xD;&#xA;Angle between blue and red is -170 degrees&#xD;&#xA;Shortest angle between green and blue is 130 degrees&#xD;&#xA;&#xD;&#xA;what formula should i use to calculate it?  &#xD;&#xA;it must be positive value&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ldc8H.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19199" PostHistoryTypeId="1" PostId="7462" RevisionGUID="f5e7cb2d-dcd5-498a-98df-8185089f44aa" CreationDate="2018-04-01T07:08:29.850" UserId="8487" Text="Delta angle of two vectors about positive x axis" ContentLicense="CC BY-SA 3.0" />
  <row Id="19200" PostHistoryTypeId="3" PostId="7462" RevisionGUID="f5e7cb2d-dcd5-498a-98df-8185089f44aa" CreationDate="2018-04-01T07:08:29.850" UserId="8487" Text="|mathematics|geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19201" PostHistoryTypeId="5" PostId="7462" RevisionGUID="fbc310f5-e8f8-4696-9363-a860da919fd1" CreationDate="2018-04-01T11:56:57.393" UserId="67" Comment="Punctuation and other fixes" Text="[![Task][1]][1]&#xD;&#xA;&#xD;&#xA;How do I calculate angle `C`?&#xD;&#xA;I can only know what angle between vector and x positive vector {1, 0}&#xD;&#xA;&#xD;&#xA;Angle between green and red is 60 degrees.&#xD;&#xA;Angle between blue and red is -170 degrees.&#xD;&#xA;Shortest angle between green and blue is 130 degrees.&#xD;&#xA;&#xD;&#xA;What formula should I use to calculate it?  &#xD;&#xA;It must be positive value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ldc8H.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19202" PostHistoryTypeId="24" PostId="7462" RevisionGUID="fbc310f5-e8f8-4696-9363-a860da919fd1" CreationDate="2018-04-01T11:56:57.393" Comment="Proposed by 67 approved by 8487 edit id of 372" ContentLicense="CC BY-SA 3.0" />
  <row Id="19203" PostHistoryTypeId="2" PostId="7463" RevisionGUID="287c3b95-7606-46f9-bc40-11ab828aca79" CreationDate="2018-04-01T14:55:12.950" UserId="4908" Text="Generally when wanting the smallest angle between two vectors, the dot product is used.&#xD;&#xA;$$&#xD;&#xA;\vec A \cdot{} \vec B = \cos{\angle \alpha}&#xD;&#xA;$$&#xD;&#xA;Where $\vec A$ and $\vec B$ are vectors with the length of $1.0$.&#xD;&#xA;&#xD;&#xA;However, you do not have access to the actual vectors themselves, if I understand your question correctly. You just have access to the angles between the vectors and a common direction.&#xD;&#xA;&#xD;&#xA;There is a different way you could calculate that angle. You take the absolute value of the difference between the two angles, given that both angles are from a common direction and either both clock-wise or both counter clock-wise.&#xD;&#xA;$$&#xD;&#xA;\angle \phi = |\angle \alpha - \angle \beta|&#xD;&#xA;$$&#xD;&#xA;Where&#xD;&#xA;&#xD;&#xA; - $\angle \phi$ is the smallest positive angle between the two vectors.&#xD;&#xA; - $\angle \alpha$ and $\angle \beta$ are angles in the range from $[0, 360)$, between a common direction and the vector, and either both clock-wise or both counter clock-wise.&#xD;&#xA;&#xD;&#xA;What do I mean with how I defined those angles?  &#xD;&#xA;First off all, that both angles are between a common direction and the vector. In this case it means that the angles should be between the vector and the red vector where the red vector is the common direction. Which is the case for the angles you provided. It is difficult for me to properly explain why they need to share a common direction, but it should be self explanatory.&#xD;&#xA;&#xD;&#xA;What do I mean with that they should be either both clock-wise or both counter clock-wise? When having an angle between two directions, it can either be clock-wise or counter clock-wise. The angle between red and green is 60° and if you start at the red vector (which will be the common direction) you go counter clock-wise with an angle of 60°. The other angle should then also be counter clock-wise. This is the case between red and blue with an angle of -170°. If you look at the red vector, then you go clock-wise. However, the angle is negative, so you go backwards. This means that you actually go counter clock-wise.&#xD;&#xA;&#xD;&#xA;And lastly, the angles should be in the range from $[0, 360)$. This makes the formula work a bit better. It is not needed, but then you would have to do some stuff with $\angle \phi$ instead. Basically, if the angle is larger than 360° you just keep subtracting 360° until it is within the range. If the angle is smaller than 0° you keep adding 360° until it is within the range.&#xD;&#xA;&#xD;&#xA;Let us try this method with your example.&#xD;&#xA;&#xD;&#xA;We have three vectors. $\vec Red$, $\vec Blue$ and $\vec Green$. We now the angles between $\vec Red$ and $\vec Blue$ and between $\vec Red$ and $\vec Green$. &#xD;&#xA;$$\angle RB = -170$$&#xD;&#xA;$$\angle RG = 60$$&#xD;&#xA;&#xD;&#xA;$\angle RG$ is within our range, but $\angle RB$ is not. So we add 360° to $\angle RB$ and we get.&#xD;&#xA;$$\angle RB = 190$$&#xD;&#xA;&#xD;&#xA;They also both have a common direction, $\vec Red$ and are both counter clock-wise.&#xD;&#xA;&#xD;&#xA;When adding them into the formula, we get;&#xD;&#xA;$$\angle \phi = |190-60| = 130$$&#xD;&#xA;&#xD;&#xA;And there we have it. The answer.&#xD;&#xA;&#xD;&#xA;I do not know if this is a formula with a name or something like that. This method is something I just came up with.&#xD;&#xA;&#xD;&#xA;Good luck!" ContentLicense="CC BY-SA 3.0" />
  <row Id="19204" PostHistoryTypeId="2" PostId="7464" RevisionGUID="f7a1b07c-1a45-4b84-a183-9f6486fb6440" CreationDate="2018-04-01T15:48:58.753" UserId="2485" Text="I have implemented a couple of classes which are drawn using shaders where the vertex position is always calculated the same way:&#xD;&#xA;&#xD;&#xA;`gl_Position = u_worldViewProjection * a_position;`&#xD;&#xA;&#xD;&#xA;The `u_worldViewProjection`-uniform is calculated using a `viewProjectionMatrix` which comes from a camera class. This is how I calculate the `viewProjectionMatrix`:&#xD;&#xA;&#xD;&#xA;    const projectionMatrix = mat4.create();&#xD;&#xA;    mat4.perspective(projectionMatrix, this._fieldOfViewRadians, this._aspect, this._zNear, this._zFar);&#xD;&#xA;    mat4.rotateY(projectionMatrix, projectionMatrix, MathHelper.degToRad(this._cameraAngleDeg));&#xD;&#xA;&#xD;&#xA;    // Setup camera&#xD;&#xA;    const cameraMatrix = mat4.create();&#xD;&#xA;    const up = vec3.fromValues(0, 1, 0);&#xD;&#xA;    mat4.lookAt(cameraMatrix, this._cameraPosition, this._viewDirection, up);&#xD;&#xA;&#xD;&#xA;    const viewProjectionMatrix = mat4.create();&#xD;&#xA;    mat4.multiply(viewProjectionMatrix, projectionMatrix, cameraMatrix);&#xD;&#xA;&#xD;&#xA;    return viewProjectionMatrix;&#xD;&#xA;&#xD;&#xA;After that I would draw some component where I would set the `u_worldViewProjection`-uniform something like this:&#xD;&#xA;&#xD;&#xA;protected _calculateMatrixData(viewProjectionMatrix: mat4): void {&#xD;&#xA;&#xD;&#xA;    // Set the world-matrix aka model matrix, position rotation and scaling&#xD;&#xA;    const worldMatrix = mat4.create();&#xD;&#xA;    mat4.translate(worldMatrix, worldMatrix, this.translation);&#xD;&#xA;    mat4.scale(worldMatrix, worldMatrix, vec3.fromValues(this._scale[0], this._scale[1], this._scale[2]));&#xD;&#xA;    mat4.rotateX(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[0]));&#xD;&#xA;    mat4.rotateY(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[1]));&#xD;&#xA;    mat4.rotateZ(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[2]));&#xD;&#xA;&#xD;&#xA;    this._worldMatrixData.value = worldMatrix;&#xD;&#xA;&#xD;&#xA;    // Create worldViewProjection matrix&#xD;&#xA;    const worldViewProjectionMatrix = mat4.create();&#xD;&#xA;    mat4.multiply(worldViewProjectionMatrix, viewProjectionMatrix, worldMatrix);&#xD;&#xA;    // ...&#xD;&#xA;    // set the uniforms some time later&#xD;&#xA;&#xD;&#xA;Until now this worked for every object. Now I introduced a new shader-pair:&#xD;&#xA;&#xD;&#xA;### vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    &#xD;&#xA;    in vec4 a_position;&#xD;&#xA;    uniform mat4 u_worldViewProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      &#xD;&#xA;      gl_PointSize = 10.5;&#xD;&#xA;      gl_Position = u_worldViewProjection * a_position;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;### fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    &#xD;&#xA;    // Set fragment shader's precision to &quot;medium precision&quot;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      outColor = vec4(1, 0, 0.1, 0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Seems simple. The problem is those do not render the component. I did realize that the component is being drawn if I omit the `u_worldViewProjection` in the `gl_Position` calculation.&#xD;&#xA;&#xD;&#xA;`gl_Position = a_position;`&#xD;&#xA;&#xD;&#xA;The above snippet will draw the component, but of course this will not take any changes in account that were made to the camera. Thus I guess that my `u_worldViewProjection` is the source of the false behaviour.&#xD;&#xA;&#xD;&#xA;This is how I calculate the for the above shaders:&#xD;&#xA;&#xD;&#xA;    const worldMatrix = mat4.create();&#xD;&#xA;    mat4.scale(worldMatrix, worldMatrix, vec3.fromValues(1.0, 1.0, 1.0));&#xD;&#xA;&#xD;&#xA;    // Create worldViewProjection matrix&#xD;&#xA;    const worldViewProjectionMatrix = mat4.create();&#xD;&#xA;    mat4.multiply(worldViewProjectionMatrix, viewProjectionMatrix, worldMatrix);&#xD;&#xA;&#xD;&#xA;The resulting matrix is **not** null or undefined.&#xD;&#xA;&#xD;&#xA;I know it is kind of impossible to point out the origin of the problem but maybe there some approach to find the source or maybe I am doing something completely wrong?&#xD;&#xA;&#xD;&#xA;Any help would be appreciated. If there is some other information I should provide please let me know.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19205" PostHistoryTypeId="1" PostId="7464" RevisionGUID="f7a1b07c-1a45-4b84-a183-9f6486fb6440" CreationDate="2018-04-01T15:48:58.753" UserId="2485" Text="`worldViewProjection` doesn't work for a single component" ContentLicense="CC BY-SA 3.0" />
  <row Id="19206" PostHistoryTypeId="3" PostId="7464" RevisionGUID="f7a1b07c-1a45-4b84-a183-9f6486fb6440" CreationDate="2018-04-01T15:48:58.753" UserId="2485" Text="|webgl|camera-matrix|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19207" PostHistoryTypeId="50" PostId="6350" RevisionGUID="4ee6d1f6-bf0d-4858-a366-665638ae36a1" CreationDate="2018-04-02T17:08:23.503" UserId="-1" />
  <row Id="19209" PostHistoryTypeId="2" PostId="7465" RevisionGUID="44a1c798-4580-4898-8eac-3e4e7b39df75" CreationDate="2018-04-02T20:41:03.447" UserId="8494" Text="Im trying to complain the algorithm to calculate the HSL value form a RGB color. I understand the algorithm for the Hue, but im lost with the Lightness and saturation. Someone can explain why?&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**There is the algorithm:**&#xD;&#xA;&#xD;&#xA;R' = R/255&#xD;&#xA;&#xD;&#xA;G' = G/255&#xD;&#xA;&#xD;&#xA;B' = B/255&#xD;&#xA;&#xD;&#xA;Cmax = max(R', G', B')&#xD;&#xA;&#xD;&#xA;Cmin = min(R', G', B')&#xD;&#xA;&#xD;&#xA;Δ = Cmax - Cmin&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Hue Calculation:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Ligthnesscalculation:**&#xD;&#xA;&#xD;&#xA;L = (Cmax + Cmin) / 2&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Saturation calculation:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TmFmv.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/bCGT5.gif" ContentLicense="CC BY-SA 3.0" />
  <row Id="19210" PostHistoryTypeId="1" PostId="7465" RevisionGUID="44a1c798-4580-4898-8eac-3e4e7b39df75" CreationDate="2018-04-02T20:41:03.447" UserId="8494" Text="Can someone explain this formula for parse RGB to HSL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19211" PostHistoryTypeId="3" PostId="7465" RevisionGUID="44a1c798-4580-4898-8eac-3e4e7b39df75" CreationDate="2018-04-02T20:41:03.447" UserId="8494" Text="|algorithm|mathematics|color|color-science|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19215" PostHistoryTypeId="50" PostId="6358" RevisionGUID="fa858f6f-7e99-4d10-a8dc-08dd4f1fe0f5" CreationDate="2018-04-03T07:19:17.723" UserId="-1" />
  <row Id="19216" PostHistoryTypeId="5" PostId="7464" RevisionGUID="32512396-2c25-4a92-beb1-4a5204660561" CreationDate="2018-04-03T10:19:46.147" UserId="7457" Comment="Fixed code formatting and a typo" Text="I have implemented a couple of classes which are drawn using shaders where the vertex position is always calculated the same way:&#xD;&#xA;&#xD;&#xA;`gl_Position = u_worldViewProjection * a_position;`&#xD;&#xA;&#xD;&#xA;The `u_worldViewProjection`-uniform is calculated using a `viewProjectionMatrix` which comes from a camera class. This is how I calculate the `viewProjectionMatrix`:&#xD;&#xA;&#xD;&#xA;    const projectionMatrix = mat4.create();&#xD;&#xA;    mat4.perspective(projectionMatrix, this._fieldOfViewRadians, this._aspect, this._zNear, this._zFar);&#xD;&#xA;    mat4.rotateY(projectionMatrix, projectionMatrix, MathHelper.degToRad(this._cameraAngleDeg));&#xD;&#xA;&#xD;&#xA;    // Setup camera&#xD;&#xA;    const cameraMatrix = mat4.create();&#xD;&#xA;    const up = vec3.fromValues(0, 1, 0);&#xD;&#xA;    mat4.lookAt(cameraMatrix, this._cameraPosition, this._viewDirection, up);&#xD;&#xA;&#xD;&#xA;    const viewProjectionMatrix = mat4.create();&#xD;&#xA;    mat4.multiply(viewProjectionMatrix, projectionMatrix, cameraMatrix);&#xD;&#xA;&#xD;&#xA;    return viewProjectionMatrix;&#xD;&#xA;&#xD;&#xA;After that I would draw some component where I would set the `u_worldViewProjection`-uniform something like this:&#xD;&#xA;&#xD;&#xA;    protected _calculateMatrixData(viewProjectionMatrix: mat4): void {&#xD;&#xA;    // Set the world-matrix aka model matrix, position rotation and scaling&#xD;&#xA;    const worldMatrix = mat4.create();&#xD;&#xA;    mat4.translate(worldMatrix, worldMatrix, this.translation);&#xD;&#xA;    mat4.scale(worldMatrix, worldMatrix, vec3.fromValues(this._scale[0], this._scale[1], this._scale[2]));&#xD;&#xA;    mat4.rotateX(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[0]));&#xD;&#xA;    mat4.rotateY(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[1]));&#xD;&#xA;    mat4.rotateZ(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[2]));&#xD;&#xA;&#xD;&#xA;    this._worldMatrixData.value = worldMatrix;&#xD;&#xA;&#xD;&#xA;    // Create worldViewProjection matrix&#xD;&#xA;    const worldViewProjectionMatrix = mat4.create();&#xD;&#xA;    mat4.multiply(worldViewProjectionMatrix, viewProjectionMatrix, worldMatrix);&#xD;&#xA;    // ...&#xD;&#xA;    // set the uniforms some time later&#xD;&#xA;&#xD;&#xA;Until now this worked for every object. Now I introduced a new shader-pair:&#xD;&#xA;&#xD;&#xA;### vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    &#xD;&#xA;    in vec4 a_position;&#xD;&#xA;    uniform mat4 u_worldViewProjection;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      &#xD;&#xA;      gl_PointSize = 10.5;&#xD;&#xA;      gl_Position = u_worldViewProjection * a_position;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;### fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    &#xD;&#xA;    // Set fragment shader's precision to &quot;medium precision&quot;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      outColor = vec4(1, 0, 0.1, 0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Seems simple. The problem is those do not render the component. I did realize that the component is being drawn if I omit the `u_worldViewProjection` in the `gl_Position` calculation.&#xD;&#xA;&#xD;&#xA;`gl_Position = a_position;`&#xD;&#xA;&#xD;&#xA;The above snippet will draw the component, but of course this will not take any changes in account that were made to the camera. Thus I guess that my `u_worldViewProjection` is the source of the false behaviour.&#xD;&#xA;&#xD;&#xA;This is how I calculate the `worldViewProjectionMatrix` for the above shaders:&#xD;&#xA;&#xD;&#xA;    const worldMatrix = mat4.create();&#xD;&#xA;    mat4.scale(worldMatrix, worldMatrix, vec3.fromValues(1.0, 1.0, 1.0));&#xD;&#xA;&#xD;&#xA;    // Create worldViewProjection matrix&#xD;&#xA;    const worldViewProjectionMatrix = mat4.create();&#xD;&#xA;    mat4.multiply(worldViewProjectionMatrix, viewProjectionMatrix, worldMatrix);&#xD;&#xA;&#xD;&#xA;The resulting matrix is **not** null or undefined.&#xD;&#xA;&#xD;&#xA;I know it is kind of impossible to point out the origin of the problem but maybe there some approach to find the source or maybe I am doing something completely wrong?&#xD;&#xA;&#xD;&#xA;Any help would be appreciated. If there is some other information I should provide please let me know.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19217" PostHistoryTypeId="24" PostId="7464" RevisionGUID="32512396-2c25-4a92-beb1-4a5204660561" CreationDate="2018-04-03T10:19:46.147" Comment="Proposed by 7457 approved by 2041 edit id of 373" ContentLicense="CC BY-SA 3.0" />
  <row Id="19221" PostHistoryTypeId="2" PostId="7467" RevisionGUID="52d7525e-ae3e-44ec-8aa1-e0a8eb982841" CreationDate="2018-04-03T19:02:51.347" UserId="8153" Text="What actually happens inside computer when the text, pdf, jpeg, ms-word or any other document(file) is scrolled? Does it generate a new bitmap image sufficient for the screen to display even for tiny scroll or are does it show part of bit map image for each scroll? Please describe what is the basic idea behind the working of scroll in laymen terms? " ContentLicense="CC BY-SA 3.0" />
  <row Id="19222" PostHistoryTypeId="1" PostId="7467" RevisionGUID="52d7525e-ae3e-44ec-8aa1-e0a8eb982841" CreationDate="2018-04-03T19:02:51.347" UserId="8153" Text="What actually happens in frame buffer when an image or document is scrolled?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19223" PostHistoryTypeId="3" PostId="7467" RevisionGUID="52d7525e-ae3e-44ec-8aa1-e0a8eb982841" CreationDate="2018-04-03T19:02:51.347" UserId="8153" Text="|opengl|rendering|gpu|webgl|pixel-graphics|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19224" PostHistoryTypeId="34" PostId="7433" RevisionGUID="7a6a32c2-146c-4e64-a308-ab247b031dc9" CreationDate="2018-04-04T05:23:02.203" UserId="-1" Comment="45" />
  <row Id="19225" PostHistoryTypeId="6" PostId="7467" RevisionGUID="5d218130-a5d8-498c-94a4-f50132c89fb4" CreationDate="2018-04-04T07:12:11.987" UserId="2041" Comment="Putting a bunch of unrelated tags on your question makes it less likely that interested people will see it and answer" Text="|rendering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19226" PostHistoryTypeId="6" PostId="7467" RevisionGUID="9a6ea1f6-7177-403b-8c4c-89706e659139" CreationDate="2018-04-04T07:38:36.080" UserId="8153" Comment="edited tags" Text="|opengl|rendering|shader|webgl|gui|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19227" PostHistoryTypeId="2" PostId="7468" RevisionGUID="dba2a73f-5d4d-4f29-af6e-5d7b9272d368" CreationDate="2018-04-04T10:08:37.103" UserId="2041" Text="In the olden days of text-mode terminals, the &quot;frame buffer&quot; was a buffer of text, not an image. Scrolling worked in the way you described. The buffer was larger than would fit on the screen, and to &quot;scroll&quot; it would change an offset in the display controller, so it would display different lines. This only makes sense when the whole framebuffer is scrolled at once, which never happens in a windowing system.&#xD;&#xA;&#xD;&#xA;Nowadays, it depends on the application. A word processor will rasterise the text separately each frame: there's no off-screen buffer at all. It wouldn't make sense to store an image of the whole document, because the memory use would be huge, and the whole thing would have to be recreated every time the text changed.&#xD;&#xA;&#xD;&#xA;On the other hand, an image editor will probably store the whole image, possibly as a texture in GPU memory. A program on the GPU copies the visible section of the image to the application's frame buffer, each frame. This can be done by simply having the view parameters (offset and zoom level) as uniforms and updating them as the view is changed. This is actually very fast even though it's essentially a copy, because GPUs are good at drawing textures efficiently.&#xD;&#xA;&#xD;&#xA;A web browser might use either technique, or something more sophisticated. There was a trend in mobile browsers a couple of years ago to render in tiles. The structure of the page would be rasterised to a set of off-screen tiles: enough to more than cover the screen. A program on the GPU draws all the visible tiles into the correct place in the application's framebuffer, clipping the edges. That way, small scrolls or zooms can be performed by changing the offsets of the tiles, without having to rasterise the page again. When you scroll too close to the edge of the tiles, a new row of tiles can be rasterised in a separate thread.&#xD;&#xA;&#xD;&#xA;This tile approach is fast to display, uses a fixed number of fixed-size textures, and allows a trade-off between responsiveness and scroll speed. It also allows lower-resolution tiles to be used if the page is too slow to rasterise during a fast scroll. It does require a lot more sophistication in the way you rasterise the page to the tiles, to know which parts of the page can affect which tiles.&#xD;&#xA;&#xD;&#xA;Whichever technique the application uses for managing off-screen content, it's responsible itself for producing a new frame each time. The windowing system or compositor doesn't give it a way to specify a window of a larger texture to use without copying." ContentLicense="CC BY-SA 3.0" />
  <row Id="19228" PostHistoryTypeId="50" PostId="6365" RevisionGUID="c9225df9-5a95-4139-ba6e-4cc87572b30a" CreationDate="2018-04-04T11:26:27.533" UserId="-1" />
  <row Id="19229" PostHistoryTypeId="2" PostId="7469" RevisionGUID="a1102f9c-5466-4bae-9892-6fc747db735d" CreationDate="2018-04-04T16:47:35.537" UserId="5256" Text="When researchers are developing new BRDFs for certain materials I understand that usually 2 paths can be taken. (this is understood from [Overview of Appearance Models][1].)&#xD;&#xA;&#xD;&#xA; 1. Deriving a mathematical model of how light interacts with that material.&#xD;&#xA; 2. Fitting Models to measured results.&#xD;&#xA;&#xD;&#xA;My question primarily revolves around the first technique. Once the scattering of light within a material is understood how do researchers then decide to create a mathematical representation? What is the process involved in creating a new scattering function? Consider a Hair Fiber or Volumetric Scattering model. &#xD;&#xA;  [1]: http://cseweb.ucsd.edu/~viscomp/classes/cse274/wi18/readings/lect01_revised.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="19230" PostHistoryTypeId="1" PostId="7469" RevisionGUID="a1102f9c-5466-4bae-9892-6fc747db735d" CreationDate="2018-04-04T16:47:35.537" UserId="5256" Text="Creating Scattering Functions" ContentLicense="CC BY-SA 3.0" />
  <row Id="19231" PostHistoryTypeId="3" PostId="7469" RevisionGUID="a1102f9c-5466-4bae-9892-6fc747db735d" CreationDate="2018-04-04T16:47:35.537" UserId="5256" Text="|pathtracing|brdf|pbr|scattering|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19232" PostHistoryTypeId="5" PostId="7469" RevisionGUID="b5cf3e3a-abc3-48f4-af64-9bd8a3673f00" CreationDate="2018-04-04T16:57:54.023" UserId="5256" Comment="deleted 54 characters in body" Text="When researchers are developing new BRDFs for certain materials I understand that usually 2 paths can be taken. (this is understood from [Overview of Appearance Models][1].)&#xD;&#xA;&#xD;&#xA; 1. Deriving a mathematical model of how light interacts with that material.&#xD;&#xA; 2. Fitting Models to measured results.&#xD;&#xA;&#xD;&#xA;My question primarily revolves around the first technique. Once the scattering of light within a material is understood how do researchers then decide to create a mathematical representation? What is the process involved in creating a new scattering function? &#xD;&#xA;  [1]: http://cseweb.ucsd.edu/~viscomp/classes/cse274/wi18/readings/lect01_revised.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="19233" PostHistoryTypeId="2" PostId="7470" RevisionGUID="c2aca160-5ec1-4cca-a1e8-5c0d12c63a58" CreationDate="2018-04-04T19:30:45.687" UserId="6380" Text="So I have a small (8x8 pixel) image in 24-bit color. I want to be able to (quickly) generate a color-quantized version of the image that only has two colors. &#xD;&#xA;&#xD;&#xA;One naive approach is to cluster a luma histogram of the image (1-dimensional clustering is [easier][1] than the 2D or 3D case). The chroma can be generated by averaging the pixels in each cluster. Unfortunately, this technique doesn't really work well if the the image has uniform luma.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/a/11516590/498680" ContentLicense="CC BY-SA 3.0" />
  <row Id="19234" PostHistoryTypeId="1" PostId="7470" RevisionGUID="c2aca160-5ec1-4cca-a1e8-5c0d12c63a58" CreationDate="2018-04-04T19:30:45.687" UserId="6380" Text="Quick 2-color image quantization for small images" ContentLicense="CC BY-SA 3.0" />
  <row Id="19235" PostHistoryTypeId="3" PostId="7470" RevisionGUID="c2aca160-5ec1-4cca-a1e8-5c0d12c63a58" CreationDate="2018-04-04T19:30:45.687" UserId="6380" Text="|algorithm|image-processing|color|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19236" PostHistoryTypeId="4" PostId="7470" RevisionGUID="8ef6cdc1-df85-481d-a250-a9bb88d504d3" CreationDate="2018-04-04T19:40:19.573" UserId="6380" Comment="name fix" Text="Quick 2-color quantization for small images" ContentLicense="CC BY-SA 3.0" />
  <row Id="19237" PostHistoryTypeId="50" PostId="6370" RevisionGUID="ccec9010-a2e8-4841-9ae3-6041672b22dd" CreationDate="2018-04-04T23:26:38.367" UserId="-1" />
  <row Id="19238" PostHistoryTypeId="5" PostId="7469" RevisionGUID="3dbd3694-90cc-483f-a098-2d865a0b0940" CreationDate="2018-04-05T07:15:10.913" UserId="5256" Comment="added 162 characters in body" Text="There are three principal ways to obtain a BRDF. We can &#xD;&#xA;&#xD;&#xA; 1. Derive an analytic formula using physical principles&#xD;&#xA; 2. Use simulation given an assumed or measured model of the surface&#xD;&#xA;    microgeometry&#xD;&#xA; 3. Measure the BRDF based on empirical observation&#xD;&#xA;&#xD;&#xA;A number of analytic formulae have been proposed for BRDFs. Many Formulae have been derived from physical principles. A number of models such as the Torrance-Sparrow model have been derived from the distribution of microfacet orientations. One may postulate a certain microgeometry for the surface, and simulate the resulting BRDF by using a software raytracer. &#xD;&#xA;&#xD;&#xA;Once the scattering of light on a surface is understood how is a mathematical model derived using physical principles? Can anyone recommend any resources on this topic? &#xD;&#xA;  [1]: http://cseweb.ucsd.edu/~viscomp/classes/cse274/wi18/readings/lect01_revised.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="19239" PostHistoryTypeId="5" PostId="7469" RevisionGUID="728951d8-d978-4e8e-a43e-b077c23d950b" CreationDate="2018-04-05T07:21:11.677" UserId="5256" Comment="added 162 characters in body" Text="There are three principal ways to obtain a BRDF. We can &#xD;&#xA;&#xD;&#xA; 1. Derive an analytic formula using physical principles&#xD;&#xA; 2. Use simulation given an assumed or measured model of the surface&#xD;&#xA;    microgeometry&#xD;&#xA; 3. Measure the BRDF based on empirical observation&#xD;&#xA;&#xD;&#xA;A number of analytic formulae have been proposed for BRDFs. Many Formulae have been derived from physical principles. A number of models such as the Torrance-Sparrow model have been derived from the distribution of microfacet orientations. One may postulate a certain microgeometry for the surface, and simulate the resulting BRDF by using a software raytracer. &#xD;&#xA;&#xD;&#xA;Once the scattering of light on a surface is understood how is a reflectance function derived? Can anyone recommend any resources on this topic? &#xD;&#xA;  [1]: http://cseweb.ucsd.edu/~viscomp/classes/cse274/wi18/readings/lect01_revised.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="19240" PostHistoryTypeId="4" PostId="7469" RevisionGUID="728951d8-d978-4e8e-a43e-b077c23d950b" CreationDate="2018-04-05T07:21:11.677" UserId="5256" Comment="added 162 characters in body" Text="Predicting reflectance functions from complex surfaces" ContentLicense="CC BY-SA 3.0" />
  <row Id="19241" PostHistoryTypeId="2" PostId="7471" RevisionGUID="42c6fb86-a303-4755-9957-67b1bf17f6e2" CreationDate="2018-04-05T08:36:43.173" UserId="209" Text="The approach I would use, and indeed have used, would be to&#xD;&#xA;&#xD;&#xA; 1. run principal component analysis on your image data to generate &quot;the&quot; main axis&#xD;&#xA; 2. Project your pixels onto that axis (i.e. compute the dot product of each colour value against the axis)&#xD;&#xA; 3. Using the dot prods, sort the the colour values from smallest to largest and&#xD;&#xA; 4. Find the &quot;partitioning&quot; point, i.e. that splits smaller values in one set, larger in the other, that minimises, say, the mean squared error. i.e. each partition is represented by the average of its members and you compute the total error.&#xD;&#xA;&#xD;&#xA;This last step, i.e. finding the best partition, can be done in linear time by starting with the &quot;least&quot; item in partition &quot;A&quot;, all the rest in partition &quot;B&quot;, and progressively shifting the next smaller over from &quot;B&quot; to &quot;A, one at a time.&#xD;&#xA;&#xD;&#xA;A cheap way to find the principal axis is to first generate the 3x3 covariance matrix and then use the &quot;repeated matrix vector multiplication&quot; trick to find the principal eigenvector (i.e. the principal axis)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19242" PostHistoryTypeId="2" PostId="7472" RevisionGUID="2bda0df4-2152-4267-818b-5bcd11a03411" CreationDate="2018-04-05T10:33:21.667" UserId="8508" Text="I'm looking into a problem that first occured very trivial to me, but i got stuck and it's becoming a major issue right now. I'd like to subdivide a triangle by its given UVs, e.g. if the UVs are going from -n...+m or if they are greater than 1. So for example if i have a U coordinate from -1.5 ... 4 i'd like to subdivide at -1.0, 0.0, 1.0, 2.0, 3.0. Here's a visualization of the polygons that can be generated. Triangulation is trivial of course. &#xD;&#xA;&#xD;&#xA;[![This is how it renders with a UV texture][1]][1]&#xD;&#xA;&#xD;&#xA;My idea was to subdivide each edge separately for U and V and then find intersections and use these intersections to spawn triangles. However, i can't even find the rule how each line is constructed. Maybe someone can shed some light?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/afHHS.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="19243" PostHistoryTypeId="1" PostId="7472" RevisionGUID="2bda0df4-2152-4267-818b-5bcd11a03411" CreationDate="2018-04-05T10:33:21.667" UserId="8508" Text="Subdivide a triangle along its UVs" ContentLicense="CC BY-SA 3.0" />
  <row Id="19244" PostHistoryTypeId="3" PostId="7472" RevisionGUID="2bda0df4-2152-4267-818b-5bcd11a03411" CreationDate="2018-04-05T10:33:21.667" UserId="8508" Text="|geometry|triangulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19252" PostHistoryTypeId="2" PostId="7475" RevisionGUID="50b68ad8-22fb-4c66-9823-1fc34c9c3de2" CreationDate="2018-04-06T04:58:07.457" UserId="8517" Text="hello I dont know how to do this I need help.. my codes looks like the fallowing&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D sampler;&#xD;&#xA;    varying vec2 tex_coords;&#xD;&#xA;    &#xD;&#xA;    void main() {	&#xD;&#xA;         vec2 p = tex_coords;  	 &#xD;&#xA;      	 vec4 red = vec4(1.0,0.0,0.0,1.0);&#xD;&#xA;      	 vec4 green = vec4(0.0,1.0,0.0,1.0);  	 &#xD;&#xA;    	 gl_FragColor = green + red; //I want to display green and red side by side  	 &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am trying to display red and green side by side using two vec4. &#xD;&#xA;any help?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19253" PostHistoryTypeId="1" PostId="7475" RevisionGUID="50b68ad8-22fb-4c66-9823-1fc34c9c3de2" CreationDate="2018-04-06T04:58:07.457" UserId="8517" Text="how to merge two vec4 and display side by side?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19254" PostHistoryTypeId="3" PostId="7475" RevisionGUID="50b68ad8-22fb-4c66-9823-1fc34c9c3de2" CreationDate="2018-04-06T04:58:07.457" UserId="8517" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19255" PostHistoryTypeId="2" PostId="7476" RevisionGUID="3f699a08-0367-4886-bb33-aa37530068fb" CreationDate="2018-04-06T05:54:49.223" UserId="7008" Text="This is not how Shaders work, if you add the colors, you add the final color for the fragment that is being worked on by the fragment shader - if you use this shader for a whole triangle, then all the fragments would end up with &#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;gl\_FragColor = \left(\begin{array}{c}1.0\\1.0\\0.0\\1.0\end{array}\right)&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;i.e. the color vectors are just summed. If you want to display two colors next to each other, you would typically add two objects to your seen next to each other, draw one of them with your shader that only displays red color and the other with your shader that only displays green color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another possibility is to calculate the position of your fragment in Model Space, World Space or another space of your choosing. Once you know that, you set a threshold up to which you color the object red and over which color the object green.&#xD;&#xA;&#xD;&#xA;In your fragment shader you would do something like&#xD;&#xA;&#xD;&#xA;    [...]&#xD;&#xA;    out vec3 vPos_ModelSpace;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        //do all your vertex shader stuff here&#xD;&#xA;&#xD;&#xA;        //I assume your vertex position attribute is called aPosition&#xD;&#xA;        vPos_ModelSpace = aPosition.xyz;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And then in your fragment shader you can go about it like this&#xD;&#xA;&#xD;&#xA;    in vec3 vPos_ModelSpace;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        if(vPos_ModelSpace.x &lt; 0)&#xD;&#xA;        {&#xD;&#xA;            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This assumes of course, that your model has vertices on either side of 0 on the x-axis. You shouldn't generally use `if` statements in shaders, since they are bad for perfomance, but this shader is so simple that it doesn't matter. Also, if you go about it this way, then simply outputting the x coordinate from your model space position suffices, no need really to use the whole `vec3`." ContentLicense="CC BY-SA 3.0" />
  <row Id="19256" PostHistoryTypeId="5" PostId="7476" RevisionGUID="2730a884-dd39-47a3-8932-6f337c090582" CreationDate="2018-04-06T07:26:47.867" UserId="7008" Comment="corrected a spelling mistake, added some structure to better refind parts of the answer" Text="This is not how Shaders work, if you add the colors, you add the final color for the fragment that is being worked on by the fragment shader - if you use this shader for a whole triangle, then all the fragments would end up with &#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;gl\_FragColor = \left(\begin{array}{c}1.0\\1.0\\0.0\\1.0\end{array}\right)&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;i.e. the color vectors are just summed. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you want to display two colors next to each other, you would typically add two objects to your scene next to each other, draw one of them with your shader that only displays red color and the other with your shader that only displays green color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another possibility is to calculate the position of your fragment in Model Space, World Space or another space of your choosing. Once you know that, you set a threshold up to which you color the object red and over which color the object green.&#xD;&#xA;&#xD;&#xA;In your fragment shader you would do something like&#xD;&#xA;&#xD;&#xA;    [...]&#xD;&#xA;    out vec3 vPos_ModelSpace;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        //do all your vertex shader stuff here&#xD;&#xA;&#xD;&#xA;        //I assume your vertex position attribute is called aPosition&#xD;&#xA;        vPos_ModelSpace = aPosition.xyz;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And then in your fragment shader you can go about it like this&#xD;&#xA;&#xD;&#xA;    in vec3 vPos_ModelSpace;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        if(vPos_ModelSpace.x &lt; 0)&#xD;&#xA;        {&#xD;&#xA;            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This assumes of course, that your model has vertices on either side of 0 on the x-axis. You shouldn't generally use `if` statements in shaders, since they are bad for perfomance, but this shader is so simple that it doesn't matter. Also, if you go about it this way, then simply outputting the x coordinate from your model space position suffices, no need really to use the whole `vec3`." ContentLicense="CC BY-SA 3.0" />
  <row Id="19257" PostHistoryTypeId="5" PostId="7471" RevisionGUID="36eedd54-a566-4779-9fef-b6b5c4285333" CreationDate="2018-04-06T08:26:36.770" UserId="209" Comment="added 104 characters in body" Text="The approach I would use, and indeed have used, would be to&#xD;&#xA;&#xD;&#xA; 1. run principal component analysis on your image data to generate &quot;the&quot; main axis&#xD;&#xA; 2. Project your pixels onto that axis (i.e. compute the dot product of each colour value against the axis)&#xD;&#xA; 3. Using the dot prods, sort the the colour values from smallest to largest and&#xD;&#xA; 4. Find the &quot;partitioning&quot; point, i.e. that splits smaller values in one set, larger in the other, that minimises, say, the mean squared error. i.e. each partition is represented by the average of its members and you compute the total error.&#xD;&#xA;&#xD;&#xA;This last step, i.e. finding the best partition, can be done in linear time by starting with the &quot;least&quot; item in partition &quot;A&quot;, all the rest in partition &quot;B&quot;, and progressively shifting the next smaller over from &quot;B&quot; to &quot;A, one at a time. You just need to keep separate sums of the values and sums of squares of the values for each partition.&#xD;&#xA;&#xD;&#xA;A cheap way to find the principal axis is to first generate the 3x3 covariance matrix and then use the &quot;repeated matrix vector multiplication&quot; trick to find the principal eigenvector (i.e. the principal axis)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19258" PostHistoryTypeId="5" PostId="7471" RevisionGUID="e7a0c5b7-f875-4295-a6e5-607eee46da20" CreationDate="2018-04-06T08:35:13.163" UserId="209" Comment="Just added some notes on terminating the search a bit earlier" Text="The approach I would use, and indeed have used, would be to&#xD;&#xA;&#xD;&#xA; 1. run principal component analysis on your image data to generate &quot;the&quot; main axis&#xD;&#xA; 2. Project your pixels onto that axis (i.e. compute the dot product of each colour value against the axis)&#xD;&#xA; 3. Using the dot prods, sort the the colour values from smallest to largest and&#xD;&#xA; 4. Find the &quot;partitioning&quot; point, i.e. that splits smaller values in one set, larger in the other, that minimises, say, the mean squared error. i.e. each partition is represented by the average of its members and you compute the total error.&#xD;&#xA;&#xD;&#xA;This last step, i.e. finding the best partition, can be done in linear time by starting with the &quot;least&quot; item in partition &quot;A&quot;, all the rest in partition &quot;B&quot;, and progressively shifting the next smaller over from &quot;B&quot; to &quot;A, one at a time. You just need to keep separate sums of the values and sums of squares of the values for each partition and then you can compute the total MSE relatively cheaply. &#xD;&#xA;&#xD;&#xA;Note that the function should follow a quadratic curve so it (should) begin decreasing until it reaches the minimum. Once it starts increasing again you can stop the search.&#xD;&#xA;&#xD;&#xA;A cheap way to find the principal axis is to first generate the 3x3 covariance matrix and then use the &quot;repeated matrix vector multiplication&quot; trick to find the principal eigenvector (i.e. the principal axis)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19259" PostHistoryTypeId="2" PostId="7477" RevisionGUID="8fa6ad31-4eba-4e14-abe0-7b8889ce73d2" CreationDate="2018-04-06T16:38:49.477" UserId="2485" Text="This was entirely my fault (who would have thought) I simply forgot to set the uniform locations before rendering!" ContentLicense="CC BY-SA 3.0" />
  <row Id="19263" PostHistoryTypeId="50" PostId="6373" RevisionGUID="7645a8d7-1c81-4e02-a2d7-4b02aa397cb2" CreationDate="2018-04-07T01:47:29.590" UserId="-1" />
  <row Id="19264" PostHistoryTypeId="2" PostId="7478" RevisionGUID="54c81040-931b-475f-9119-ce7608caab48" CreationDate="2018-04-07T08:04:28.363" UserId="7696" Text="You can use barycentric coordinates to calculate points inside the triangle with a determinate value for uv.&#xD;&#xA;&#xD;&#xA;The process is easy =&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Let's say that the UV coordinates of each vertex of the triangle are:&#xD;&#xA;&#xD;&#xA;vertex 0 =&gt; u0,v0&#xD;&#xA;&#xD;&#xA;vertex 1 =&gt; u1,v1&#xD;&#xA;&#xD;&#xA;vertex 2 =&gt; u2,v2&#xD;&#xA;&#xD;&#xA;A point inside the triangle has UV coordinates value expressed in function of its barycentric coordinates:&#xD;&#xA;&#xD;&#xA;u coord = p0 * u0 + p1 * u1 + p2 * u2&#xD;&#xA;&#xD;&#xA;v coord = p0 * v0 + p1 * v1 + p2 * v2&#xD;&#xA;&#xD;&#xA;where p0,p1,p2 are the barycentric coordinates of this point.&#xD;&#xA;&#xD;&#xA;As barycentric coordinates has the property:&#xD;&#xA;&#xD;&#xA;p0 + p1 + p2 = 1&#xD;&#xA;&#xD;&#xA;you can calculate the barycentric coordinates of a point with a specific value for UV just by solving these equations. I mean, for example, you want to know which point inside the triangle has&#xD;&#xA;&#xD;&#xA;UV = (1,2)&#xD;&#xA;&#xD;&#xA;To calculate such a point just do:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;1 = p0 * u0 + p1 * u1 + p2 * u2&#xD;&#xA;&#xD;&#xA;2 = p0 * v0 + p1 * v1 + p2 * v2&#xD;&#xA;&#xD;&#xA;p0 + p1 + p2 = 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;as you know the values for (u0,v0), (u1,v1) and (u2,v2),  you can easily calculate the barycentric coordinates of this point, (p0, p1, p2).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Once you have the barycentric coordinates, you can calculate the coordinates (px,py,pz) of the point:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;(px,py,pz) = p0 * vertex0 coordinates + p1 * vertex 1 coordinates + p2 * vertex 2 coordinates  " ContentLicense="CC BY-SA 3.0" />
  <row Id="19268" PostHistoryTypeId="50" PostId="6218" RevisionGUID="9d735da4-785f-40dc-af53-1c0d83038c63" CreationDate="2018-04-07T15:49:30.863" UserId="-1" />
  <row Id="19269" PostHistoryTypeId="2" PostId="7480" RevisionGUID="279a78b7-8ed4-4068-bf85-7db32f1c5109" CreationDate="2018-04-07T17:32:56.340" UserId="5944" Text="I have ever browsed a website focusing on cloud (cloud in the sky, not cloud computing) simulation.&#xD;&#xA;&#xD;&#xA;That's a company devoted to developing cloud simulation software and offer cloud simultation solution.&#xD;&#xA;&#xD;&#xA;Anyone knows this website or the company?&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19270" PostHistoryTypeId="1" PostId="7480" RevisionGUID="279a78b7-8ed4-4068-bf85-7db32f1c5109" CreationDate="2018-04-07T17:32:56.340" UserId="5944" Text="Cloud simulation software" ContentLicense="CC BY-SA 3.0" />
  <row Id="19271" PostHistoryTypeId="3" PostId="7480" RevisionGUID="279a78b7-8ed4-4068-bf85-7db32f1c5109" CreationDate="2018-04-07T17:32:56.340" UserId="5944" Text="|simulation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19272" PostHistoryTypeId="2" PostId="7481" RevisionGUID="90805a01-c667-4048-af87-5daaa89fe733" CreationDate="2018-04-07T18:54:09.423" UserId="48" Text="There are a couple of companies doing middleware cloud simulation and rendering. It might have been [SilverLining](http://sundog-soft.com/features/real-time-3d-clouds/) by Sundog, or [trueSKY](https://simul.co/truesky/) by Simul." ContentLicense="CC BY-SA 3.0" />
  <row Id="19275" PostHistoryTypeId="50" PostId="6225" RevisionGUID="63aaee65-3c26-438b-82ff-fa8dae7aa048" CreationDate="2018-04-07T20:49:31.890" UserId="-1" />
  <row Id="19276" PostHistoryTypeId="50" PostId="5697" RevisionGUID="526ea92e-3543-420a-a2d8-6c2f817ed6e1" CreationDate="2018-04-07T22:49:44.060" UserId="-1" />
  <row Id="19277" PostHistoryTypeId="5" PostId="3702" RevisionGUID="31a0621f-03ba-466e-a620-0a61ca489597" CreationDate="2018-04-08T18:33:21.340" UserDisplayName="user7220" Comment="Corrected links.." Text="About the fact that there are more games for Windows, some reasons are&#xD;&#xA;&#xD;&#xA; 1. Windows has the majority of the market and in the past to develop cross platform games was more complicated than it is today.&#xD;&#xA; 2. DirectX comes with way better tools for developing (e.g. debugging)&#xD;&#xA; 3. Big innovations are generally first created/implemented in DirectX, and then ported to/implemented in OpenGL. &#xD;&#xA; 4. As for Windows vs Linux, you have to consider that when there is an actual standard due to marketing and historical reasons (for that see [Why do game developers prefer Windows? | Software Engineering][1], as I said in the comments), it has its inertia.&#xD;&#xA;&#xD;&#xA;The inertia thing is very important. If your team develop for DirectX, targeting 90% of the market (well... if you play games on pc you probaly have windows, so... 99% of the market?), why would you want to invest in OpenGL? If you already develop in OpenGL, again targeting 99% of the market, you will stick to it as long as you can. For exampe Id Tech by Id Software is an excellent game engine (powering the DOOM series) that uses OpenGL.&#xD;&#xA;&#xD;&#xA;**About the topic of your discussion, a comment.**&#xD;&#xA;&#xD;&#xA;As of today, there are many many APIs, and a common practice is to use a Game Engine that abstracts over them. For example, consider that&#xD;&#xA; &#xD;&#xA; - On most mobile platform you have to use OpenGl ES.&#xD;&#xA; - On PC you can use both DirectX and OpenGL&#xD;&#xA; - I think on XBOX you have to use DirectX.&#xD;&#xA; - I think that on PS you use their own API. &#xD;&#xA; - With old hardware you use DirectX9 or OpenGL 3, or OpenGL ES 2.&#xD;&#xA; - With more recent hardware you can (and want to) use DirectX 11, OpenGL 4, OpenGL ES 3.&#xD;&#xA;  &#xD;&#xA;Recently, with the advent of the new low overhead APIs - whch is a major turning point for graphical programming - there are DirectX 12 for Windows and XBOX, Metal for iOS and Vulkan (the new OpenGL) for Windows and Linux (including Android and Tizen).&#xD;&#xA;&#xD;&#xA;There still are games that only target Windows and XBOX, but IMHO today that can only be marketing choice.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://softwareengineering.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows" ContentLicense="CC BY-SA 3.0" />
  <row Id="19278" PostHistoryTypeId="24" PostId="3702" RevisionGUID="31a0621f-03ba-466e-a620-0a61ca489597" CreationDate="2018-04-08T18:33:21.340" Comment="Proposed by 7220 approved by 48, 4665 edit id of 381" ContentLicense="CC BY-SA 3.0" />
  <row Id="19279" PostHistoryTypeId="5" PostId="7460" RevisionGUID="1ca43e9c-7073-4016-b2b4-8023205df6d0" CreationDate="2018-04-08T20:37:19.843" UserDisplayName="user7220" Comment="Corrected links.." Text="I'm receiving a non-energy conserving output while trying to importance sample the GGX Distributionof the Microfacet model, which is generally 3-4 times bigger than the resulting PDF&#xD;&#xA;&#xD;&#xA;I'm following this blog post: [Sampling microfacet BRDF | Cao Jiayin Blog][1]&#xD;&#xA;&#xD;&#xA;And I'm sampling the $\theta $ angle with the following formula / code:&#xD;&#xA;&#xD;&#xA;$$ \theta = acos(\sqrt{ \frac{1 - \epsilon}{\epsilon(\alpha^2 - 1) +1} }) $$&#xD;&#xA;&#xD;&#xA;    float sampleTheta(float roughness) {&#xD;&#xA;	    float random = rnd();&#xD;&#xA;	    return acos(&#xD;&#xA;		         sqrt(	      		(1.0f - random) /&#xD;&#xA;			    		((roughness * roughness - 1.0f) * random + 1.0f)&#xD;&#xA;		             )&#xD;&#xA;		       );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX Distribution function i'm using is:&#xD;&#xA;&#xD;&#xA;$$  \frac{ \alpha^2 }{\pi((\alpha^2 - 1) cos^2\theta + 1)^2}  $$&#xD;&#xA;&#xD;&#xA;    float MicroFacetMaterial::Distribution(vec3 normal, vec3 halfvector, float alpha) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float alpha2 = alpha * alpha;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    return alpha2 / (M_PI * a1 * a1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, the blog post derived this PDF to use along with the BRDF:&#xD;&#xA;&#xD;&#xA;$$ p_{h}(\theta) = \frac{2\alpha^2 \ cos\theta \ sin\theta}{((\alpha^2 - 1)cos^2\theta + 1 )^2 } \\ \ \\ \ \\ p(\theta) = \frac{p_{h}(\theta)}{ 4 (\omega o \cdot \omega h)} $$&#xD;&#xA;&#xD;&#xA;    float get_pdf(vec3 wo, vec3 normal, vec3 halfvector, float roughness) {&#xD;&#xA;	    float NoH = dot(normal, halfvector);&#xD;&#xA;	    float NoH2 = NoH * NoH;&#xD;&#xA;	    float sin = sqrt(1.0f - NoH2);&#xD;&#xA;	    float alpha2 = roughness * roughness;&#xD;&#xA;&#xD;&#xA;	    float a1 = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;&#xD;&#xA;	    float pdf_h = (2.0f * alpha2 * NoH * sin) / (a1 * a1);&#xD;&#xA;&#xD;&#xA;	    return pdf_h / (4.0f * dot(wo, halfvector));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And as a final step I'm calculating incident radiance as follow for an RGB non-recursive path tracer &#xD;&#xA;&#xD;&#xA;      float cosT = clampDot(newdirection, normal);&#xD;&#xA;      vec3 halfVector = HalfwayVector(-ray.direction, newdirection);&#xD;&#xA;&#xD;&#xA;	  float pdf = get_pdf(-ray.direction, normal, halfVector, _roughness);&#xD;&#xA;&#xD;&#xA;	  float distribution = Distribution(normal, halfVector, _roughness);&#xD;&#xA;	  vec3 fresnel = FresnelColor(newdirection, halfVector, clampDot(halfVector, -ray.direction));&#xD;&#xA;	  float geometry = Geometry(-ray.direction, newdirection, normal, halfVector);&#xD;&#xA;&#xD;&#xA;	  float denominator = 4.0f * clampDot(normal, -ray.direction) * clampDot(normal, newdirection);&#xD;&#xA;&#xD;&#xA;	  vec3 brdf = (distribution * fresnel * geometry) / (denominator);&#xD;&#xA;&#xD;&#xA;      mask = (albedo * brdf * cosT) / pdf;&#xD;&#xA;&#xD;&#xA;The output I'm getting is a model that behaves almost like a lightsource - while debugging, I saw the Distribution term normally is up to 4 times bigger than the respective PDF, I've also decided not to post the Geometry and Fresnel term since at least from the debugging I've done those are not contributing as much as the Distribution term (as expected)&#xD;&#xA;&#xD;&#xA;If anyone can confirm the above looks alright, I'll try to look for the error elsewhere&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/" ContentLicense="CC BY-SA 3.0" />
  <row Id="19280" PostHistoryTypeId="24" PostId="7460" RevisionGUID="1ca43e9c-7073-4016-b2b4-8023205df6d0" CreationDate="2018-04-08T20:37:19.843" Comment="Proposed by 7220 approved by 48, 7871 edit id of 383" ContentLicense="CC BY-SA 3.0" />
  <row Id="19281" PostHistoryTypeId="5" PostId="7461" RevisionGUID="7e1ee9e9-2bc5-41ea-96d4-a5edbd4957ea" CreationDate="2018-04-08T22:47:54.983" UserDisplayName="user7220" Comment="Corrected links.." Text="I'm trying to implement radiosity normal maps from the old Valve paper:&#xD;&#xA;&#xD;&#xA;[Half-Life® 2 /&#xD;&#xA;Valve Source™ Shading.pdf | valvesoftware.com][1]&#xD;&#xA;&#xD;&#xA;I've tried generating the light maps using Vray and 3dStudio max, by overriding the normals to point in these three directions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It works to an extent, applying normal maps over walls and such makes them appear like they are light mapped and bumpy. It's when I set the normal map to (128,128,255) that i can't get the same result as if it were a regular light map and i see artifacts. &#xD;&#xA;&#xD;&#xA;I'm not sure if understand at all how the basis is used to capture light, so i omitted the GI part and tried to bake just a directional light. &#xD;&#xA;&#xD;&#xA;If i set a directional light at `(-1,0,0)` in the basis from the picture above, the first dot product (red arrow) will be less than 0, however both the green and the blue will get some value from that light. &#xD;&#xA;&#xD;&#xA;Same way if i set it at `(1,0,0)` there will be some value greater than 0, and two less than.&#xD;&#xA;&#xD;&#xA;This doesn't make sense, the directional light at this angle shouldn't contribute any light to this surface?&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The white arrow represents the light dir to be baked. The red one is pretty affected by it, but then scaling it by 1/3 doesn't really help much. &#xD;&#xA;It feels like it's missing some negative light (?). &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Here it is with (1,1,1) normalized ^&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.valvesoftware.com/publications/2004/GDC2004_Half-Life2_Shading.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/CnS5u.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bw1Iv.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/LrMt0.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19282" PostHistoryTypeId="24" PostId="7461" RevisionGUID="7e1ee9e9-2bc5-41ea-96d4-a5edbd4957ea" CreationDate="2018-04-08T22:47:54.983" Comment="Proposed by 7220 approved by 48, 5005 edit id of 382" ContentLicense="CC BY-SA 3.0" />
  <row Id="19283" PostHistoryTypeId="2" PostId="7482" RevisionGUID="5a898afd-e3d2-4c99-a78e-b2adf60f8964" CreationDate="2018-04-09T05:11:32.783" UserId="8532" Text="I'm having some issues with my multi-threaded ray tracing implementation. It seems to only render about half of the image. Here is the picture:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the code:&#xD;&#xA;    &#xD;&#xA;	int max = (nx * ny); //width * height&#xD;&#xA;	volatile std::atomic&lt;int&gt; count(0);&#xD;&#xA;	&#xD;&#xA;	int cores = std::thread::hardware_concurrency();&#xD;&#xA;	cores -= 1;&#xD;&#xA;	vector&lt;future&lt;vector&lt;rgbpacket&gt;&gt;&gt; future_vector;&#xD;&#xA;	cout &lt;&lt; &quot;Threads supported: &quot; &lt;&lt; cores &lt;&lt; &quot;\n&quot;;&#xD;&#xA;	while (cores--) {&#xD;&#xA;		future_vector.emplace_back(&#xD;&#xA;			std::async([=, &amp;world, &amp;cam, &amp;dim, &amp;orth, &amp;count] {&#xD;&#xA;				vector&lt;rgbpacket&gt; stack;&#xD;&#xA;				while (true) {&#xD;&#xA;&#xD;&#xA;					int index = count++;&#xD;&#xA;&#xD;&#xA;					if (index &gt;= max) {&#xD;&#xA;&#xD;&#xA;						return stack;&#xD;&#xA;					} else {&#xD;&#xA;						int k = (index % nx); //mod width to get column&#xD;&#xA;						int j = (index / nx); //divide width to get row&#xD;&#xA;&#xD;&#xA;						rgbpacket curpx = render(j, k, dim, world, cam, orth);&#xD;&#xA;						curpx.k = (unsigned int)k;&#xD;&#xA;						curpx.j = (unsigned int)j;&#xD;&#xA;						stack.push_back(curpx);&#xD;&#xA;&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			})&#xD;&#xA;		);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	//parse the image buffer&#xD;&#xA;	for (unsigned int i = 0; i &lt; future_vector.size(); i++) {&#xD;&#xA;		vector&lt;rgbpacket&gt; stack = future_vector[i].get();&#xD;&#xA;		for (unsigned int k = 0; k &lt; stack.size(); k++) {&#xD;&#xA;			rgbpacket rgb_comp = stack.back();&#xD;&#xA;&#xD;&#xA;			//Using the new compressed packet&#xD;&#xA;			rgbaColor conv;&#xD;&#xA;			conv.r = rgb_comp.r;&#xD;&#xA;			conv.g = rgb_comp.g;&#xD;&#xA;			conv.b = rgb_comp.b;&#xD;&#xA;&#xD;&#xA;			hslaColor pix = rgb2hsl(conv);&#xD;&#xA;			HSLAPixel newpixel(pix.h, pix.s, pix.l);&#xD;&#xA;&#xD;&#xA;			HSLAPixel &amp;imgpx = img.getPixel(rgb_comp.k, rgb_comp.j);&#xD;&#xA;			imgpx = newpixel;&#xD;&#xA;&#xD;&#xA;			stack.pop_back();&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;For some preface, I am calculating the pixel with respect to the position with the **index** variable. Once I calculate it, I store it (along with the position) in the vector. After I calculate all of the pixel values, I parse them into an image buffer and later print that image.&#xD;&#xA;&#xD;&#xA;I've narrowed the issue (I think) to where I am calculating the rendered pixel and storing it in the vector. For some reason, it does not store all of the pixels in the vector and I am not sure why? Any help is appreciated. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kbYe6.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19284" PostHistoryTypeId="1" PostId="7482" RevisionGUID="5a898afd-e3d2-4c99-a78e-b2adf60f8964" CreationDate="2018-04-09T05:11:32.783" UserId="8532" Text="Issues with Multi-threaded Raytracing" ContentLicense="CC BY-SA 3.0" />
  <row Id="19285" PostHistoryTypeId="3" PostId="7482" RevisionGUID="5a898afd-e3d2-4c99-a78e-b2adf60f8964" CreationDate="2018-04-09T05:11:32.783" UserId="8532" Text="|raytracing|c++|multithreading|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19286" PostHistoryTypeId="5" PostId="5450" RevisionGUID="b7fed299-32f3-439c-8d2d-e19f987966a8" CreationDate="2018-04-09T08:58:03.337" UserDisplayName="user7220" Comment="Corrected links.." Text="A close solution would be like [How to detect border vertices of an open mesh 3d model? | Stack Overflow][1]&#xD;&#xA;&#xD;&#xA;For edge, you test in the edge is connected to at least 2 triangles. If it is not the case, the edge is a border under the assumption that the mesh is a manifold.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/11779797/how-to-detect-border-vertices-of-an-open-mesh-3d-model" ContentLicense="CC BY-SA 3.0" />
  <row Id="19287" PostHistoryTypeId="24" PostId="5450" RevisionGUID="b7fed299-32f3-439c-8d2d-e19f987966a8" CreationDate="2018-04-09T08:58:03.337" Comment="Proposed by 7220 approved by 48, 7059 edit id of 376" ContentLicense="CC BY-SA 3.0" />
  <row Id="19288" PostHistoryTypeId="5" PostId="5420" RevisionGUID="d899c466-afef-46de-be8a-c7b6cd5388db" CreationDate="2018-04-09T08:58:15.113" UserDisplayName="user7220" Comment="Corrected links.." Text="&gt; Is there any software which would let me import the existing models,&#xD;&#xA;&gt; define the bone hierarchy and the model which corresponds to each&#xD;&#xA;&gt; bone, and export a single articulated model in T-pose?&#xD;&#xA;&#xD;&#xA;I found that it is relatively easy to create articulations using Blender.&#xD;&#xA;This tutorial might be helpful: [Blender 3D: Noob to Pro/Bones | Wikibooks][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/Bones" ContentLicense="CC BY-SA 3.0" />
  <row Id="19289" PostHistoryTypeId="24" PostId="5420" RevisionGUID="d899c466-afef-46de-be8a-c7b6cd5388db" CreationDate="2018-04-09T08:58:15.113" Comment="Proposed by 7220 approved by 48, 7059 edit id of 377" ContentLicense="CC BY-SA 3.0" />
  <row Id="19290" PostHistoryTypeId="5" PostId="4261" RevisionGUID="ee9590bd-c7e2-4332-b098-cfaceff41a74" CreationDate="2018-04-09T09:41:07.113" UserDisplayName="user7220" Comment="Corrected links.." Text="Not a book, but here's an online write-up about the basics of Monte Carlo path tracing:&#xD;&#xA;[Path Tracing &amp;#8211; Getting Started With Diffuse and Emissive | The blog at the bottom of the sea][1]&#xD;&#xA;&#xD;&#xA;I've also heard good things a out Peter Shirley's books. In particular &quot;Ray Tracing in one Weekend&quot;&#xD;&#xA;[Ray Tracing in One Weekend (Ray Tracing Minibooks Book 1) Kindle Edition | amazon.com][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/&#xD;&#xA;  [2]: https://www.amazon.com/Ray-Tracing-Weekend-Minibooks-Book-ebook/dp/B01B5AODD8" ContentLicense="CC BY-SA 3.0" />
  <row Id="19291" PostHistoryTypeId="24" PostId="4261" RevisionGUID="ee9590bd-c7e2-4332-b098-cfaceff41a74" CreationDate="2018-04-09T09:41:07.113" Comment="Proposed by 7220 approved by 48, 209 edit id of 379" ContentLicense="CC BY-SA 3.0" />
  <row Id="19292" PostHistoryTypeId="5" PostId="3602" RevisionGUID="02924560-8362-4ad1-8db0-2ca48826ec53" CreationDate="2018-04-09T09:41:17.210" UserDisplayName="user7220" Comment="Corrected links.." Text="My understanding is that in 5.4, instancing will use API calls like glDrawElementsInstanced and shaders need to be modified for instance buffers like in this document: [Basic GPU Instancing Support | docs.google.com][1]&#xD;&#xA;&#xD;&#xA;&gt; UNITY_INSTANCING_CBUFFER_START (MyProperties)&#xD;&#xA;&#xD;&#xA;&gt; UNITY_DEFINE_INSTANCED_PROP (float4, _Color)&#xD;&#xA;&#xD;&#xA;&gt; UNITY_INSTANCING_CBUFFER_END&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.google.com/document/d/1RS6cVjE8mBVOKqQUuXbaZcPW3kmw3ZWySJwr-5rDwSs/edit" ContentLicense="CC BY-SA 3.0" />
  <row Id="19293" PostHistoryTypeId="24" PostId="3602" RevisionGUID="02924560-8362-4ad1-8db0-2ca48826ec53" CreationDate="2018-04-09T09:41:17.210" Comment="Proposed by 7220 approved by 48, 209 edit id of 380" ContentLicense="CC BY-SA 3.0" />
  <row Id="19294" PostHistoryTypeId="5" PostId="4967" RevisionGUID="81e2a55f-3af5-4ccd-9498-88d5be2b70c6" CreationDate="2018-04-09T09:41:30.730" UserDisplayName="user7220" Comment="Corrected links.." Text="After some researches and some answers from professionals here is my conclusion.&#xD;&#xA;&#xD;&#xA;**Pros**&#xD;&#xA;&#xD;&#xA; - Don’t require tangents or binormals. Less interpolators.&#xD;&#xA; - Only need two channels. less texture memory.&#xD;&#xA; - Don’t suffer from tangent seams.&#xD;&#xA; - Can be blended using alpha blending, without renormalization.&#xD;&#xA; - Less mesh memory: We don’t need to store a tangent vector.&#xD;&#xA; - Fast implementation.&#xD;&#xA;&#xD;&#xA;**Cons**&#xD;&#xA;&#xD;&#xA; - More ALU&#xD;&#xA; - Less flexible. A normal map can represent any derivative map, but the reverse is not true. As an example, sharp edges can be difficult to represent.&#xD;&#xA;&#xD;&#xA;So, that's a lot of pros compared to cons. But the major problem is that it's not an industry standard.&lt;br&gt;&#xD;&#xA;There are almost no content authoring tools nor artist know-how.&#xD;&#xA;&#xD;&#xA;Here's is a quote from [Bart Wronski][1] that illustrates well the current status of derivative maps :&#xD;&#xA;&#xD;&#xA;&gt; Sadly in life / technology not always best solution wins / not even&#xD;&#xA;&gt; gets deserved attention... It's more about standards and inertia.&#xD;&#xA;&#xD;&#xA;If you are interested in knowing more about derivative maps here are some interesting articles.&#xD;&#xA;&#xD;&#xA; - [Mikkelsen and 3D Graphics: Derivative Maps | Morten Mikkelsen Blog][2]&#xD;&#xA; - [Derivative Maps | CodeItNow][3]&#xD;&#xA; - [Derivative Maps vs Normal Maps | CodeItNow][4]&#xD;&#xA; - [Triplanar Texturing with Derivative Maps | The Robot Seven][5]&#xD;&#xA; - [Derivative Normal Maps - What are they? | polycount.com][6]&#xD;&#xA; - [Derivative Maps | Knald Technologies Documentation][7]&#xD;&#xA;&#xD;&#xA;If I forgot something or if your don't agree feel free to tell in the comments, I would be glad to improve this answer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://twitter.com/BartWronsk&#xD;&#xA;  [2]: http://mmikkelsen3d.blogspot.fr/2011/07/derivative-maps.html&#xD;&#xA;  [3]: http://www.rorydriscoll.com/2012/01/11/derivative-maps/&#xD;&#xA;  [4]: http://www.rorydriscoll.com/2012/01/15/derivative-maps-vs-normal-maps/&#xD;&#xA;  [5]: http://therobotseven.com/devlog/triplanar-texturing-derivative-maps/&#xD;&#xA;  [6]: http://polycount.com/discussion/91605/derivative-normal-maps-what-are-they&#xD;&#xA;  [7]: https://docs.knaldtech.com/doku.php?id=derivative_maps_knald" ContentLicense="CC BY-SA 3.0" />
  <row Id="19295" PostHistoryTypeId="24" PostId="4967" RevisionGUID="81e2a55f-3af5-4ccd-9498-88d5be2b70c6" CreationDate="2018-04-09T09:41:30.730" Comment="Proposed by 7220 approved by 48, 209 edit id of 378" ContentLicense="CC BY-SA 3.0" />
  <row Id="19296" PostHistoryTypeId="5" PostId="5260" RevisionGUID="92de201b-4b5d-4b1a-a01e-9cfbc7fc1399" CreationDate="2018-04-09T09:41:35.750" UserDisplayName="user7220" Comment="Corrected links.." Text="Just to comment on the 0.16*Specular^2 term that was mentioned in the comments by Karim:&#xD;&#xA;&#xD;&#xA;Frostbite only **remaps** the specularity for their internal purpose so that they can pack gemstones specularity into the 8bit channel. They just lose some precision in favor of more variation. The specularity value is the original one when rendering.&#xD;&#xA;&#xD;&#xA;Check the Disney BRDF viewer which is a awesome start for PBR, since it contains the whole BRDF from Disney.&#xD;&#xA;[BRDF Explorer | Walt Disney Animation Studios][1]&#xD;&#xA;&#xD;&#xA;Also, if you are looking at a better Fresnel function than&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH) {&#xD;&#xA;        // Fresnel Schlick&#xD;&#xA;        return Specular + (1-Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Use this instead since it takes roughness/gloss into account:&#xD;&#xA;&#xD;&#xA;    vec3 Light_F(in vec3 Specular, in float VH, in float gloss) &#xD;&#xA;    {&#xD;&#xA;        return Specular + (max(vec3(gloss), Specular) - Specular) * pow(1-VH, 5.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.disneyanimation.com/technology/brdf.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19297" PostHistoryTypeId="24" PostId="5260" RevisionGUID="92de201b-4b5d-4b1a-a01e-9cfbc7fc1399" CreationDate="2018-04-09T09:41:35.750" Comment="Proposed by 7220 approved by 48, 209 edit id of 374" ContentLicense="CC BY-SA 3.0" />
  <row Id="19298" PostHistoryTypeId="5" PostId="7437" RevisionGUID="0187fd77-3ffc-425d-81bf-ec28f1a9b315" CreationDate="2018-04-09T09:41:42.090" UserDisplayName="user7220" Comment="Corrected links.." Text="New to writing shaders, please forgive any naivety in the question!&#xD;&#xA;&#xD;&#xA;Parallax mapping in any of its ray-marchy variants (e.g. steep parallax, cone step mapping, POM) generates fake geometry on a material, generally nearly indistinguishable from real geometry and at a much higher resolution than is practical using GPU tessellation. However, the geometry created does not extend outside the initial bounds of the triangle being rendered (unlike with GPU tessellation) - so e.g. a parallax mapped sphere still has circular edges.&#xD;&#xA;&#xD;&#xA;I'm want to try adapting a parallax shader (preferably OpenGL, any high quality variation of parallax mapping will do though I gather cone stepping is pretty much the state of the art) to write outside of the poly bounds using gl_FragDepth (and enabling conservative depth output).&#xD;&#xA;&#xD;&#xA;This seems to be theoretically possible (see this Unity example [Modifying depth when parallax mapping | Unity Community][1]). However that post did not include any shader code and got no responses.&#xD;&#xA;&#xD;&#xA;Is anyone aware of an existing implementation of this (with source available), or else could give me a good idea of how I should proceed with implementing it?&#xD;&#xA;&#xD;&#xA;Many thanks.   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://forum.unity.com/threads/modifying-depth-when-parallax-mapping.364037/" ContentLicense="CC BY-SA 3.0" />
  <row Id="19299" PostHistoryTypeId="24" PostId="7437" RevisionGUID="0187fd77-3ffc-425d-81bf-ec28f1a9b315" CreationDate="2018-04-09T09:41:42.090" Comment="Proposed by 7220 approved by 48, 209 edit id of 384" ContentLicense="CC BY-SA 3.0" />
  <row Id="19300" PostHistoryTypeId="5" PostId="5418" RevisionGUID="7d197431-be48-4ee1-a7f7-e014e2670764" CreationDate="2018-04-09T09:41:50.900" UserDisplayName="user7220" Comment="Corrected links.." Text="&#xD;&#xA;The documentation quickly sum up the idea with: &#xD;&#xA;&#xD;&#xA;&gt; The idea with image load/store is that the user can bind one of the&#xD;&#xA;&gt; images in a Texture to a number of image binding points (which are&#xD;&#xA;&gt; separate from texture image units). Shaders can read information from&#xD;&#xA;&gt; these images and write information to them, in ways that they cannot&#xD;&#xA;&gt; with textures.&#xD;&#xA;&#xD;&#xA;Aside for the simplicity of usage, from [An introduction to OpenGL 4.2 | Daniel Rákos Blog][1] at the section **ARB_shader_image_load_store** you can perform more complex operations and algorithms in GLSL to a single level of a texture (which is called an image) and from any shader stage.&#xD;&#xA;&#xD;&#xA;I am also curious about the implementation of the example with FBO since I don't understand why you cannot write to a specific pixel coordinate too.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://rastergrid.com/blog/2011/08/an-introduction-to-opengl-4-2/" ContentLicense="CC BY-SA 3.0" />
  <row Id="19301" PostHistoryTypeId="24" PostId="5418" RevisionGUID="7d197431-be48-4ee1-a7f7-e014e2670764" CreationDate="2018-04-09T09:41:50.900" Comment="Proposed by 7220 approved by 48, 209 edit id of 375" ContentLicense="CC BY-SA 3.0" />
  <row Id="19302" PostHistoryTypeId="2" PostId="7483" RevisionGUID="69858562-7ed2-42bc-9cb6-938aa1cbc3bb" CreationDate="2018-04-09T19:19:33.450" UserId="386" Text="I'm reading [DXGI flip model][1] article and some parts are not clear:&#xD;&#xA;&#xD;&#xA; - &#xD;&#xA;&#xD;&#xA;&gt; DirectFlip with panel fitters: Your window client region covers the screen, and your swapchain buffers are within some hardware-dependent scaling factor (e.g. 0.25x to 4x) of the screen. The GPU scanout hardware is used to scale your buffer while sending it to the display.&#xD;&#xA;&#xD;&#xA;    What is this hardware-dependent scaling factor? What it does? Why?&#xD;&#xA;&#xD;&#xA; - &#xD;&#xA;&gt; The traditional pattern for apps in the past has been to provide the user with a list of resolutions to choose from when the user selects exclusive fullscreen mode. With the ability of modern displays to seamlessly begin scaling content, consider providing users with the ability to choose a rendering resolution for performance scaling, independent from an output resolution, and even in windowed mode.&#xD;&#xA;&#xD;&#xA;    I understand what they mean by the *traditional pattern*, it's pretty common - I'm selecting a resolution in the options screen and enjoying fullHD 800*600 picture. But I have no clue what are they describing next - *displays seamlessly scaling content*, *resolution for performance scaling*, *output resolution*. Could someone explain the same with simple words and examples (I bet there are already games out there that uses the technology)?&#xD;&#xA;&#xD;&#xA;  [1]: https://blogs.msdn.microsoft.com/directx/2018/04/09/dxgi-flip-model/" ContentLicense="CC BY-SA 3.0" />
  <row Id="19303" PostHistoryTypeId="1" PostId="7483" RevisionGUID="69858562-7ed2-42bc-9cb6-938aa1cbc3bb" CreationDate="2018-04-09T19:19:33.450" UserId="386" Text="What is a scaling factor of the screen?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19304" PostHistoryTypeId="3" PostId="7483" RevisionGUID="69858562-7ed2-42bc-9cb6-938aa1cbc3bb" CreationDate="2018-04-09T19:19:33.450" UserId="386" Text="|untagged|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19306" PostHistoryTypeId="5" PostId="7475" RevisionGUID="770861f3-1697-451b-b0e6-9fb68f0a563d" CreationDate="2018-04-10T03:17:39.747" UserId="67" Comment="Fixed grammar etc." Text="I don't know how to do this. I need help. My code looks like the following:&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D sampler;&#xD;&#xA;    varying vec2 tex_coords;&#xD;&#xA;    &#xD;&#xA;    void main() {	&#xD;&#xA;         vec2 p = tex_coords;  	 &#xD;&#xA;      	 vec4 red = vec4(1.0,0.0,0.0,1.0);&#xD;&#xA;      	 vec4 green = vec4(0.0,1.0,0.0,1.0);  	 &#xD;&#xA;    	 gl_FragColor = green + red; //I want to display green and red side by side  	 &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am trying to display red and green side by side using two `vec4`s. &#xD;&#xA;Any help?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19307" PostHistoryTypeId="4" PostId="7475" RevisionGUID="770861f3-1697-451b-b0e6-9fb68f0a563d" CreationDate="2018-04-10T03:17:39.747" UserId="67" Comment="Fixed grammar etc." Text="How to merge two vec4s and display side by side?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19308" PostHistoryTypeId="24" PostId="7475" RevisionGUID="770861f3-1697-451b-b0e6-9fb68f0a563d" CreationDate="2018-04-10T03:17:39.747" Comment="Proposed by 67 approved by 8517 edit id of 385" ContentLicense="CC BY-SA 3.0" />
  <row Id="19309" PostHistoryTypeId="2" PostId="7484" RevisionGUID="543642a4-2a70-4484-ad16-d71a1d8f0ade" CreationDate="2018-04-10T04:10:41.130" UserId="48" Text="Unfortunately, `gl_FragDepth` won't enable you to write outside of the rasterized triangle's screen-space bounds. All it enables is to modify the values written to the depth buffer within the triangle, replacing the triangle's true depth with a shader-calculated value.&#xD;&#xA;&#xD;&#xA;What you're seeing in the screenshot in the Unity forum thread you linked to is two intersecting parallax-mapped surfaces, where the depth output enables occlusion between the two surfaces to be correctly resolved in the screen-space region they both cover. But if you look at the right side of the screenshot, you can see the straight-line edge of the bottom brick polygon.&#xD;&#xA;&#xD;&#xA;However! You might still be able to accomplish the goal of getting correct silhouette edges by using `discard` in the fragment shader when the parallax ray gets outside the bounds of the original polygon. This would involve modifying the ray-march code to check if the march has crossed a triangle edge, and exit with `discard` if so, rather than continuing to march.&#xD;&#xA;&#xD;&#xA;You'd have to find a way to get the information about triangle edges into the fragment shader, though, as this isn't provided by OpenGL. Maybe make your vertex/index buffers available via SSBOs; then you can use `gl_PrimitiveID` in the fragment shader to index into them and lookup the vertex data.&#xD;&#xA;&#xD;&#xA;Unfortunately I don't know offhand of any implementation of something like this, although I'm sure someone out there must have tried it before." ContentLicense="CC BY-SA 3.0" />
  <row Id="19311" PostHistoryTypeId="2" PostId="7485" RevisionGUID="6f62c3db-4ac1-4cdd-a51f-317f818a4ecd" CreationDate="2018-04-10T07:25:29.727" UserId="6541" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;[![Tours][1]][1]&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone][2]][2]&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Hexagon][3]][3]&#xD;&#xA;&#xD;&#xA;Hexagonal Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdHexPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Triangle][4]][4]&#xD;&#xA;&#xD;&#xA;Triangular Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTriPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;[![Capsule 2D][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Capsule / Line - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCapsule( vec3 p, vec3 a, vec3 b, float r )&#xD;&#xA;    {&#xD;&#xA;        vec3 pa = p - a, ba = b - a;&#xD;&#xA;        float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;        return length( pa - ba*h ) - r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/bBf5P.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19312" PostHistoryTypeId="1" PostId="7485" RevisionGUID="6f62c3db-4ac1-4cdd-a51f-317f818a4ecd" CreationDate="2018-04-10T07:25:29.727" UserId="6541" Text="shapes signed distance field implementation explanation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19313" PostHistoryTypeId="3" PostId="7485" RevisionGUID="6f62c3db-4ac1-4cdd-a51f-317f818a4ecd" CreationDate="2018-04-10T07:25:29.727" UserId="6541" Text="|glsl|mathematics|signed-distance-field|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19314" PostHistoryTypeId="5" PostId="7485" RevisionGUID="8dc2cd9b-e5a0-49f7-bbb8-73d0418402a3" CreationDate="2018-04-10T07:31:19.047" UserId="6541" Comment="deleted 5 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;[![Tours][1]][1]&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone][2]][2]&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Hexagon][3]][3]&#xD;&#xA;&#xD;&#xA;Hexagonal Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdHexPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Triangle][4]][4]&#xD;&#xA;&#xD;&#xA;Triangular Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTriPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;[![Capsule2D][5]][5]&#xD;&#xA;&#xD;&#xA;Capsule / Line - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCapsule( vec3 p, vec3 a, vec3 b, float r )&#xD;&#xA;    {&#xD;&#xA;        vec3 pa = p - a, ba = b - a;&#xD;&#xA;        float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;        return length( pa - ba*h ) - r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/5FY8W.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19315" PostHistoryTypeId="5" PostId="7485" RevisionGUID="6c7a3965-890f-42c8-9f45-37d57c4c9db0" CreationDate="2018-04-10T07:53:00.853" UserId="6541" Comment="added 368 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Tour 3D][2]][2]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Cone 3D][4]][4]&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Hexagon 2D][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hexagonal Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdHexPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Hexagon 3D][6]][6]&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Triangle 2D][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Triangular Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTriPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Triangle 3D][8]][8]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;[![Capsule 2D][9]][9]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Capsule / Line - signed - exact&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float sdCapsule( vec3 p, vec3 a, vec3 b, float r )&#xD;&#xA;    {&#xD;&#xA;        vec3 pa = p - a, ba = b - a;&#xD;&#xA;        float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;        return length( pa - ba*h ) - r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Capsule 3D][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help to understand this shapes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZiPLs.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/BS2GO.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/HzTWI.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/5FY8W.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/i8VHJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19316" PostHistoryTypeId="5" PostId="7485" RevisionGUID="80a4e7ef-fd36-48fc-bf28-a94516c8d2c7" CreationDate="2018-04-10T08:25:54.280" UserId="6541" Comment="deleted 805 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I can't imagine how drew this shape and I don't know why used two length&#xD;&#xA;&#xD;&#xA;[![Tour 3D][2]][2]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;&#xD;&#xA;[![Cone 3D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZiPLs.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/BS2GO.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/HzTWI.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/5FY8W.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/i8VHJ.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19317" PostHistoryTypeId="4" PostId="7485" RevisionGUID="b068c956-1242-4326-883b-529971e8d326" CreationDate="2018-04-10T08:43:54.290" UserId="6541" Comment="edited title" Text="Explain of the implementation of some shapes by using SDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="19318" PostHistoryTypeId="5" PostId="7485" RevisionGUID="954d5217-6d7f-4ef3-88e2-caab56be9ae6" CreationDate="2018-04-10T08:54:23.330" UserId="6541" Comment="deleted 198 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how drew this shape and I don't know why used two length&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TYiv9.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19319" PostHistoryTypeId="5" PostId="7485" RevisionGUID="9a66daf9-a710-4fef-87e5-f36115b10e0f" CreationDate="2018-04-10T09:03:30.323" UserId="6541" Comment="edited body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how drew this shape and I don't know why used two length&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ehcE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19320" PostHistoryTypeId="5" PostId="7485" RevisionGUID="b0100df4-3edc-418d-ab76-88471e58222f" CreationDate="2018-04-10T09:16:46.880" UserId="6541" Comment="added 6 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how drew this shape and I don't know why used two length&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ehcE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19321" PostHistoryTypeId="2" PostId="7486" RevisionGUID="37dfc6f8-17e2-4a4a-a07d-d3968d14fb2b" CreationDate="2018-04-10T09:40:08.730" UserId="8541" Text="I'm rendering a full screen quad using `gl_VertexID` as `GL_TRIANGLE_STRIP`&#xD;&#xA;&#xD;&#xA;    const vec2 kVertices[4] = vec2[]&#xD;&#xA;    (&#xD;&#xA;     vec2(-1.0,  1.0),&#xD;&#xA;     vec2(-1.0, -1.0),&#xD;&#xA;     vec2( 1.0,  1.0),&#xD;&#xA;     vec2( 1.0, -1.0)&#xD;&#xA;     );&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        gl_Position = vec4(kVertices[gl_VertexID], 1.0, 1.0);&#xD;&#xA;        vs_out.texCoords = gl_Position.xy / 2.0 + 0.5;&#xD;&#xA;        vs_out.instanceID = gl_InstanceID;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Geometry shader just passes coordinates through into the output called `vTexCoords`.&#xD;&#xA;&#xD;&#xA;Then, in fragment shader, I output red and green into 2x2 texture using following code:&#xD;&#xA;&#xD;&#xA;    if (vTexCoords.x &gt;= 0.95) {&#xD;&#xA;        oFragData0 = vec4(0.0, 1.0, 0.0, 1.0);&#xD;&#xA;    } else {&#xD;&#xA;        oFragData0 = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I always assumed texture coordinates (0; 0), (0; 1), (1; 0), (1; 1) would map to the vertices, but the output is completely red, which means X value never reaches 1.0. &#xD;&#xA;Then I'm trying to use 0.75 (`vTexCoords.x &gt;= 0.75`), which is a texel center, and half of the texture becomes green, as expected.&#xD;&#xA;&#xD;&#xA;What am I misunderstanding here?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19322" PostHistoryTypeId="1" PostId="7486" RevisionGUID="37dfc6f8-17e2-4a4a-a07d-d3968d14fb2b" CreationDate="2018-04-10T09:40:08.730" UserId="8541" Text="Full screen quad texture coordinates mapping" ContentLicense="CC BY-SA 3.0" />
  <row Id="19323" PostHistoryTypeId="3" PostId="7486" RevisionGUID="37dfc6f8-17e2-4a4a-a07d-d3968d14fb2b" CreationDate="2018-04-10T09:40:08.730" UserId="8541" Text="|opengl|texture|uv-mapping|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19324" PostHistoryTypeId="5" PostId="3680" RevisionGUID="fe3acf33-646d-4461-812f-d81a61333794" CreationDate="2018-04-10T12:15:20.923" UserId="4647" Comment="Add compatibility with GLSL 1.10" Text="_This is a copy-paste of [my answer](https://stackoverflow.com/a/38039733/673852) to the same [question at StackOverflow](https://stackoverflow.com/q/2508818/673852)_.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;At the bottom of this answer is an example of GLSL code which allows to output the full `float` value as color, encoding IEEE 754 `binary32`. I use it like follows (this snippet gives out `yy` component of modelview matrix):&#xD;&#xA;&#xD;&#xA;&lt;!-- NOTE: setting highlighting language to C since it has similar syntax while GLSL highlighting isn't supported on stackexchange --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);&#xD;&#xA;    if(bool(1)) // put 0 here to get lowest byte instead of three highest&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.rgb,1);&#xD;&#xA;    else&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.a,0,0,1);&#xD;&#xA;&#xD;&#xA;After you get this on screen, you can just take any color picker, format the color as HTML (appending `00` to the `rgb` value if you don't need higher precision, and doing a second pass to get the lower byte if you do), and you get the hexadecimal representation of the `float` as IEEE 754 `binary32`.&#xD;&#xA;&#xD;&#xA;Here's the actual implementation of `toColor()`:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    const int emax=127;&#xD;&#xA;    // Input: x&gt;=0&#xD;&#xA;    // Output: base 2 exponent of x if (x!=0 &amp;&amp; !isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    //         -emax if x==0&#xD;&#xA;    //         emax+1 otherwise&#xD;&#xA;    int floorLog2(float x)&#xD;&#xA;    {&#xD;&#xA;        if(x==0.) return -emax;&#xD;&#xA;        // NOTE: there exist values of x, for which floor(log2(x)) will give wrong&#xD;&#xA;        // (off by one) result as compared to the one calculated with infinite precision.&#xD;&#xA;        // Thus we do it in a brute-force way.&#xD;&#xA;        for(int e=emax;e&gt;=1-emax;--e)&#xD;&#xA;            if(x&gt;=exp2(float(e))) return e;&#xD;&#xA;        // If we are here, x must be infinity or NaN&#xD;&#xA;        return emax+1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x&#xD;&#xA;    // Output: IEEE 754 biased exponent with bias=emax&#xD;&#xA;    int biasedExp(float x) { return emax+floorLog2(abs(x)); }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that (!isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    // Output: significand AKA mantissa of x if !isnan(x) &amp;&amp; !isinf(x)&#xD;&#xA;    //         undefined otherwise&#xD;&#xA;    float significand(float x)&#xD;&#xA;    {&#xD;&#xA;        // converting int to float so that exp2(genType) gets correctly-typed value&#xD;&#xA;        float expo=float(floorLog2(abs(x)));&#xD;&#xA;        return abs(x)/exp2(expo);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: x\in[0,1)&#xD;&#xA;    //        N&gt;=0&#xD;&#xA;    // Output: Nth byte as counted from the highest byte in the fraction&#xD;&#xA;    int part(float x,int N)&#xD;&#xA;    {&#xD;&#xA;        // All comments about exactness here assume that underflow and overflow don't occur&#xD;&#xA;        const float byteShift=256.;&#xD;&#xA;        // Multiplication is exact since it's just an increase of exponent by 8&#xD;&#xA;        for(int n=0;n&lt;N;++n)&#xD;&#xA;            x*=byteShift;&#xD;&#xA;    &#xD;&#xA;        // Cut higher bits away.&#xD;&#xA;        // $q \in [0,1) \cap \mathbb Q'.$&#xD;&#xA;        float q=fract(x);&#xD;&#xA;    &#xD;&#xA;        // Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected&#xD;&#xA;        // results of rounding by the GPU later in the pipeline when transforming to TrueColor&#xD;&#xA;        // the resulting subpixel value.&#xD;&#xA;        // $c \in [0,255] \cap \mathbb Z.$&#xD;&#xA;        // Multiplication is exact since it's just and increase of exponent by 8&#xD;&#xA;        float c=floor(byteShift*q);&#xD;&#xA;        return int(c);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x acceptable to significand()&#xD;&#xA;    // Output: significand of x split to (8,8,8)-bit data vector&#xD;&#xA;    ivec3 significandAsIVec3(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec3 result;&#xD;&#xA;        float sig=significand(x)/2.; // shift all bits to fractional part&#xD;&#xA;        result.x=part(sig,0);&#xD;&#xA;        result.y=part(sig,1);&#xD;&#xA;        result.z=part(sig,2);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that !isnan(x)&#xD;&#xA;    // Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)&#xD;&#xA;    ivec4 packIEEE754binary32(float x)&#xD;&#xA;    {&#xD;&#xA;        int e = biasedExp(x);&#xD;&#xA;        // sign to bit 7&#xD;&#xA;        int s = x&lt;0. ? 128 : 0;&#xD;&#xA;    &#xD;&#xA;        ivec4 binary32;&#xD;&#xA;        binary32.yzw=significandAsIVec3(x);&#xD;&#xA;        // clear the implicit integer bit of significand&#xD;&#xA;        if(binary32.y&gt;=128) binary32.y-=128;&#xD;&#xA;        // put lowest bit of exponent into its position, replacing just cleared integer bit&#xD;&#xA;        binary32.y+=128*int(mod(e,2));&#xD;&#xA;        // prepare high bits of exponent for fitting into their positions&#xD;&#xA;        e/=2;&#xD;&#xA;        // pack highest byte&#xD;&#xA;        binary32.x=e+s;&#xD;&#xA;    &#xD;&#xA;        return binary32;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec4 toColor(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec4 binary32=packIEEE754binary32(x);&#xD;&#xA;        // Transform color components to [0,1] range.&#xD;&#xA;        // Division is inexact, but works reliably for all integers from 0 to 255 if&#xD;&#xA;        // the transformation to TrueColor by GPU uses rounding to nearest or upwards.&#xD;&#xA;        // The result will be multiplied by 255 back when transformed&#xD;&#xA;        // to TrueColor subpixel value by OpenGL.&#xD;&#xA;        return vec4(binary32)/255.;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="19325" PostHistoryTypeId="2" PostId="7487" RevisionGUID="9b932e2f-ad79-4c35-b96a-3508013b9a8a" CreationDate="2018-04-10T15:53:10.130" UserId="8547" Text="I have an .OBJ 3D model with many complex meshes shape.&#xD;&#xA;&#xD;&#xA;The meshes are complex because each of them have multiple internal mesh located in it.&#xD;&#xA;&#xD;&#xA;Meshes with internal geometry is defined as a mesh, which consists of many nested geometry.&#xD;&#xA;For example: a tank in .OBJ file is represented by 1 outer geometry with several nested small geometry in it. Total number of geometry to represent that tank would be 5-7.&#xD;&#xA;&#xD;&#xA;I want to simplify the tank mesh object above to be represented by 1 geometry instead of multiple geometries.&#xD;&#xA;&#xD;&#xA;What tool and what programming language can I use to iterate all the meshes object, remove all internal geometry in .OBJ file?&#xD;&#xA;&#xD;&#xA;Please ask if you need clarification.&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="19326" PostHistoryTypeId="1" PostId="7487" RevisionGUID="9b932e2f-ad79-4c35-b96a-3508013b9a8a" CreationDate="2018-04-10T15:53:10.130" UserId="8547" Text="How to remove internal geometry programmatically in all meshes in .OBJ file?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19327" PostHistoryTypeId="3" PostId="7487" RevisionGUID="9b932e2f-ad79-4c35-b96a-3508013b9a8a" CreationDate="2018-04-10T15:53:10.130" UserId="8547" Text="|3d|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19328" PostHistoryTypeId="2" PostId="7488" RevisionGUID="2462e156-025d-4526-8ca7-51bf13568653" CreationDate="2018-04-10T16:46:34.303" UserId="2041" Text="# Torus&#xD;&#xA;&#xD;&#xA;A torus is defined by two parameters: the major radius, and the minor radius. The major radius (`t.x`) is the radius of the big ring (in red in the diagram), and the minor radius (`t.y`) is the radius of the circular cross-section. The `x` and `y` here are just indices into the vector: they're unrelated to the x and y axes.&#xD;&#xA;&#xD;&#xA;The left side of the diagram shows the xz plane, and the right side shows a cross-section with y going horizontally.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;`p.xz` is the projection of the point onto the plane of the torus, so `length(p.xz)-t.x` gives the distance from that projected point to the inside of the torus. (I've labelled it $r$ on the diagram.) `p.y` is the distance from the point to the plane of the torus, so the length of the vector ($r$, `p.y`) is the distance from the point to the inside of the torus. (Computing the length of a two-element vector is a handy way to use Pythagoras' theorem to find the hypotenuse of the triangle.)&#xD;&#xA;&#xD;&#xA;# Cone&#xD;&#xA;&#xD;&#xA;Like the torus, the cone code uses the fact that the shape is symmetric about an axis: the z axis in this case. The cone is defined by a unit vector `c` that's normal to the surface of the cone, and the apex of the cone is at the origin. Similar to the above, `length(p.xy)` gets the distance from the point to the z axis, so that we can work in the plane where the cone is a triangle. `vec2(q,p.z)` is the projection of `p` into this plane. The dot product projects this vector onto the direction `c`: how far the point is along this direction tells us how far it is from the surface of the triangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pvGwn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/eDKgu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19329" PostHistoryTypeId="2" PostId="7489" RevisionGUID="676922c3-1c96-43e4-a2ed-7453fe43a3f9" CreationDate="2018-04-10T18:24:21.500" UserId="8497" Text="I'm new to OpenGL, and I'm wondering what I need to pay attention to regarding versioning. The things I've been reading have been clear about there being version differences, and needing the appropriate OpenGL version for the functionality you're using. But they've mainly been talking about compiling and running programs on a single machine. For the most part they haven't explicitly dealt with complexities regarding compiling on one machine and running on another. (Specifically, what happens if the computer you're running on has an older version of OpenGL than the one you're compiling on.)&#xD;&#xA;&#xD;&#xA;For example, take [glDrawElementsInstanced](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstanced.xhtml). The Khronos page indicates this is available with OpenGL 3.1 and later. Obviously, if the headers for OpenGL on the machine I'm compiling for are version 3.0 or earlier, I'll get a compiler error. So on the machine I'm compiling on, I'll need to have OpenGL 3.1+ available.&#xD;&#xA;&#xD;&#xA;However, I'm wondering what might happen if the machine I compile for has OpenGL 3.1+ available, but the machine I'm running on only has support for 3.0 or earlier? Will the program that uses glDrawElementsInstanced refuse to load? Will it run but crash once I call the glDrawElementsInstanced() function? Will it work fine because the actual implementation is compiled into my program, and it only uses common back-end functionality? Is the answer different for static versus dynamic linkage? -- And perhaps most importantly, if it wasn't glDrawElementsInstanced but some other function, is there a way I can determine this on my own?&#xD;&#xA;&#xD;&#xA;I'm interested in distributing on Windows, Mac and Linux, so if there's any differences in behavior between the platforms in this regards, I'd be interested in knowing." ContentLicense="CC BY-SA 3.0" />
  <row Id="19330" PostHistoryTypeId="1" PostId="7489" RevisionGUID="676922c3-1c96-43e4-a2ed-7453fe43a3f9" CreationDate="2018-04-10T18:24:21.500" UserId="8497" Text="Dealing with OpenGL versions across multiple computers" ContentLicense="CC BY-SA 3.0" />
  <row Id="19331" PostHistoryTypeId="3" PostId="7489" RevisionGUID="676922c3-1c96-43e4-a2ed-7453fe43a3f9" CreationDate="2018-04-10T18:24:21.500" UserId="8497" Text="|opengl|compatibility|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19335" PostHistoryTypeId="4" PostId="7485" RevisionGUID="ab960acd-a08d-4cf3-8ed1-ab83d32c8bbf" CreationDate="2018-04-10T19:31:52.347" UserId="6541" Comment="edited title" Text="GLSL shapes signed distance field implementation explanation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19336" PostHistoryTypeId="5" PostId="7485" RevisionGUID="ab960acd-a08d-4cf3-8ed1-ab83d32c8bbf" CreationDate="2018-04-10T19:31:52.347" UserId="6541" Comment="edited title" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how this shape drew and I don't know why two length used here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help me to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ehcE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19337" PostHistoryTypeId="5" PostId="7485" RevisionGUID="8523d51b-8dbb-47f8-9dfd-afaaffd9e34f" CreationDate="2018-04-10T19:45:12.073" UserId="6541" Comment="added 1070 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how this shape drew and I don't know why two length used here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;__________&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Hexagon 2D][11]][11]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hexagonal Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdHexPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Hexagon 3D][6]][6]&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Triangle 2D][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Triangular Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTriPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Triangle 3D][8]][8]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Capsule / Line - signed - exact&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float sdCapsule( vec3 p, vec3 a, vec3 b, float r )&#xD;&#xA;    {&#xD;&#xA;        vec3 pa = p - a, ba = b - a;&#xD;&#xA;        float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;        return length( pa - ba*h ) - r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Capsule 3D][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help me to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ehcE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/BS2GO.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/HzTWI.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/5FY8W.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/i8VHJ.png&#xD;&#xA;[11]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19338" PostHistoryTypeId="10" PostId="7480" RevisionGUID="f0305050-f979-484c-9386-3dc11815081b" CreationDate="2018-04-10T21:13:36.840" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="19341" PostHistoryTypeId="2" PostId="7492" RevisionGUID="6a2ed9f8-f93f-41b1-a1e7-31a7fd1843da" CreationDate="2018-04-11T02:30:11.227" UserId="48" Text="I may have misunderstood, but it sounds like the frame buffer you're rendering to is only 2×2 pixels? In that case, the fragment shader will be evaluated at each pixel center, which will be at 0.25 and 0.75 in UV space. So with a threshold of 0.95 you will indeed not get any pixels green.&#xA;&#xA;If you use a larger framebuffer, say 100×100, then the last 5 pixels of each row should come out green." ContentLicense="CC BY-SA 3.0" />
  <row Id="19343" PostHistoryTypeId="5" PostId="7485" RevisionGUID="6e27d39a-c241-48e3-85a4-c46c6cd5ae6e" CreationDate="2018-04-11T02:58:51.703" UserId="6541" Comment="added 213 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how this shape drew and I don't know why two length used here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;_________________&#xD;&#xA;&#xD;&#xA;[![Hexagon 2D][11]][11]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hexagonal Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdHexPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max((q.x*0.866025+q.y*0.5),q.y)-h.x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;How the calculations are done?&#xD;&#xA;why  abs and maximum used ?&#xD;&#xA;&#xD;&#xA;[![Hexagon 3D][6]][6]&#xD;&#xA;_____&#xD;&#xA;&#xD;&#xA;[![Triangle 2D][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Triangular Prism - signed - exact&#xD;&#xA;&#xD;&#xA;    float sdTriPrism( vec3 p, vec2 h )&#xD;&#xA;    {&#xD;&#xA;        vec3 q = abs(p);&#xD;&#xA;        return max(q.z-h.y,max(q.x*0.866025+p.y*0.5,-p.y)-h.x*0.5);&#xD;&#xA;    }&#xD;&#xA;How the calculations are done?&#xD;&#xA;why abs and maximum used ?&#xD;&#xA;&#xD;&#xA;[![Triangle 3D][8]][8]&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Capsule / Line - signed - exact&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float sdCapsule( vec3 p, vec3 a, vec3 b, float r )&#xD;&#xA;    {&#xD;&#xA;        vec3 pa = p - a, ba = b - a;&#xD;&#xA;        float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;        return length( pa - ba*h ) - r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;How the calculations are done? why clamp used here? and why clamp and dot product used here?&#xD;&#xA;&#xD;&#xA;[![Capsule 3D][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help me to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ehcE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/BS2GO.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/HzTWI.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/5FY8W.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/i8VHJ.png&#xD;&#xA;[11]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19345" PostHistoryTypeId="2" PostId="7493" RevisionGUID="bdd2c2a1-28bd-4086-b1fa-e788dfae4e12" CreationDate="2018-04-11T08:59:48.827" UserId="8551" Text="There are no parabolas or hyperbolas formed when slicing a sphere once. There are no ellipses either except for the special case which is a circle.The result is always a circle" ContentLicense="CC BY-SA 3.0" />
  <row Id="19346" PostHistoryTypeId="5" PostId="7493" RevisionGUID="5fa197b2-153a-49ee-b6c6-ff75a5c184a0" CreationDate="2018-04-11T09:18:58.903" UserId="8551" Comment="added 66 characters in body" Text="There are no parabolas or hyperbolas formed when slicing a sphere once. There are no ellipses either except for the special case which is a circle.The result is always a circle. If you project the sphere onto a tilted plane you get an ellipse" ContentLicense="CC BY-SA 3.0" />
  <row Id="19347" PostHistoryTypeId="2" PostId="7494" RevisionGUID="80885fe3-e930-4292-9651-90289d896a1a" CreationDate="2018-04-11T11:34:58.113" UserId="8553" Text="I wonder if there exists any shader prototyping framework where I can debug (on cpu) my shaders, experiment with them and instantly see results and even write unit tests. The framework does not have to emulate rendering pipeline, compute only will do." ContentLicense="CC BY-SA 3.0" />
  <row Id="19348" PostHistoryTypeId="1" PostId="7494" RevisionGUID="80885fe3-e930-4292-9651-90289d896a1a" CreationDate="2018-04-11T11:34:58.113" UserId="8553" Text="Shader Prototyping Frameworks" ContentLicense="CC BY-SA 3.0" />
  <row Id="19349" PostHistoryTypeId="3" PostId="7494" RevisionGUID="80885fe3-e930-4292-9651-90289d896a1a" CreationDate="2018-04-11T11:34:58.113" UserId="8553" Text="|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19350" PostHistoryTypeId="2" PostId="7495" RevisionGUID="4b8a2a44-2fe9-4f4d-be47-8c1db0416eda" CreationDate="2018-04-11T12:41:03.570" UserId="8508" Text="An alternative solution would be to avoid the vertex/geometry shader completely and draw your fullscreen quad with &#xD;&#xA;&#xD;&#xA;    glRecti(-1, -1, 1, 1);&#xD;&#xA;&#xD;&#xA;then just compile a fragment shader and generate your UVs with:&#xD;&#xA;&#xD;&#xA;    vec2 uv = gl_FragCoord.xy / framebufferSize.xy;&#xD;&#xA;&#xD;&#xA;I don't know what you're doing but this could be potentially a fast forward solution for what you require. Maybe you're doing something else and you just broke down your problem to the bare minimum, i think in this case my answer should be still helpful for people seeking help in the problem as summarized in the headline." ContentLicense="CC BY-SA 3.0" />
  <row Id="19351" PostHistoryTypeId="5" PostId="7485" RevisionGUID="e170af7a-a400-41e3-b6c9-ba6a12ca2be8" CreationDate="2018-04-11T13:00:36.237" UserId="6541" Comment="deleted 1013 characters in body" Text="I'm trying to understand all primitives In [this article](http://iquilezles.org/www/articles/distfunctions/distfunctions.htm).After hard work I just learn Sphere and Cube , I wrote description [here](https://stackoverflow.com/questions/35326366/glsl-cube-signed-distance-field-implementation-explanation/49726668#49726668).&#xD;&#xA;&#xD;&#xA;I could draw 2D shapes but I have trouble understanding 3D below codes:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tours 2D][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Torus - signed - exact&#xD;&#xA;&#xD;&#xA;[![Tour 3D][3]][3]&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![Length][2]][2]&#xD;&#xA;&#xD;&#xA;I can't imagine how this shape drew and I don't know why two length used here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;____&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Cone 2D][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Cone - signed - exact&#xD;&#xA;&#xD;&#xA;[![Cone 3D][5]][5]&#xD;&#xA;&#xD;&#xA;    float sdCone( vec3 p, vec2 c )&#xD;&#xA;    {&#xD;&#xA;        // c must be normalized&#xD;&#xA;        float q = length(p.xy);&#xD;&#xA;        return dot(c,vec2(q,p.z));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I don't know why dot product used here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm confused please help me to understand this shapes.I hope someone explain each shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YjRDv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ehcE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o8H2x.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/JDBUy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZiPLs.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/BS2GO.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/1sWc7.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/HzTWI.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/5FY8W.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/i8VHJ.png&#xD;&#xA;[11]: https://i.stack.imgur.com/OMjbo.jpg&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19352" PostHistoryTypeId="2" PostId="7496" RevisionGUID="bed8f217-874d-405f-b4f6-65c3865bcb20" CreationDate="2018-04-11T13:57:34.360" UserId="8547" Text="I have a complex geometry mesh object, which is an irregular shape.&#xD;&#xA;&#xD;&#xA;I want to redraw that complex geometry mesh object using multiple simple primitive shapes.&#xD;&#xA;&#xD;&#xA;For example, I want to use cuboid, sphere and cylinder to represent a complex geometry mesh object.&#xD;&#xA;&#xD;&#xA;I am given only the vertices points, triangular of that complex geometry mesh.&#xD;&#xA;&#xD;&#xA;How do I decompose the geometry shape into cuboid, sphere, cylinder.&#xD;&#xA;&#xD;&#xA;Please ask if you need details.&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 3.0" />
  <row Id="19353" PostHistoryTypeId="1" PostId="7496" RevisionGUID="bed8f217-874d-405f-b4f6-65c3865bcb20" CreationDate="2018-04-11T13:57:34.360" UserId="8547" Text="How to decompose a complex mesh to simple geometry shape programmatically?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19354" PostHistoryTypeId="3" PostId="7496" RevisionGUID="bed8f217-874d-405f-b4f6-65c3865bcb20" CreationDate="2018-04-11T13:57:34.360" UserId="8547" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19355" PostHistoryTypeId="5" PostId="7477" RevisionGUID="4f495a22-b81a-4ffe-a66d-6d34de1f34e1" CreationDate="2018-04-11T16:48:39.747" UserId="2485" Comment="deleted 24 characters in body" Text="This was entirely my fault. I simply forgot to set the uniform locations before rendering!" ContentLicense="CC BY-SA 3.0" />
  <row Id="19356" PostHistoryTypeId="5" PostId="7477" RevisionGUID="93b67fda-bec8-4069-877d-91f6ef21e193" CreationDate="2018-04-11T17:15:00.037" UserId="2485" Comment="Added more information on what the problem exactly was and how I solved it." Text="This was entirely my fault. I simply forgot to set the uniform locations before rendering!&#xD;&#xA;&#xD;&#xA;I implemented a function `setUniformLocations()` which sets the uniform locations passed to it:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    public static setUniformLocations(&#xD;&#xA;        gl: WebGL2RenderingContext, &#xD;&#xA;        uniforms: IUniform[], &#xD;&#xA;        program: WebGLProgram): IUniform[] {&#xD;&#xA;        &#xD;&#xA;        const vao = gl.createVertexArray();&#xD;&#xA;        gl.bindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;        for (const uniform of uniforms) {&#xD;&#xA;            uniforms.find((u) =&gt; u.name === uniform.name).location = gl.getUniformLocation(program, uniform.name);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return uniforms;&#xD;&#xA;    }&#xD;&#xA;I normally call this function in the constructor of the according class.&#xD;&#xA;&#xD;&#xA;    this._uniforms = GLHelper.setUniformLocations(this.gl, this._uniforms, this._program);&#xD;&#xA;&#xD;&#xA;This time I forgot." ContentLicense="CC BY-SA 3.0" />
  <row Id="19357" PostHistoryTypeId="2" PostId="7497" RevisionGUID="f3c33964-8eda-4b10-a16c-c254cf2327b3" CreationDate="2018-04-11T18:35:32.203" UserId="6530" Text="I've been looking [The Real-time Volumetric Cloudscapes of Horizon-Zero Dawn][1], but I'm very confused by a few terms.  &#xD;&#xA;&#xD;&#xA;The presentation mentions &quot;The Henyey-Greenstein phase function&quot; on page 54, however does not mention how it is used nor what parameters are needed for it.  In fact they act like it is a constant, but it doesn't appear as if it is.  I've seen a [couple][2] different [formulations][3] of the same equation, and I don't understand how to use it.  If `theta` corresponds to the scattering angle, I'm not sure what actually constitutes the scattering angle in our rendering.  Is it the initial ray march angle, or light source marching angle? If theta corresponds to the light source march angle, that would be confusing since there isn't just one angle, there are 6 that they randomly select in a cone progressively further out according to page 83. &#xD;&#xA;&#xD;&#xA;Additionally the final equation used on page 77 is `e^(-d*r)*HG*P`.  Where I assume `P` is powder equation `(1.0 - e^(-d *2))`, HG is Henyey-Greenstein, and where `d` corresponds with &quot;depth&quot;, but normally combines both depth and density and where it looks like `r` is &quot;absorption increasing for rain clouds&quot; otherwise it just came out of nowhere. &#xD;&#xA;&#xD;&#xA;I'm further confused by how they use the equations, they seem to sample *alpha* with forward marching, then sample *energy* with the light cone/ light direction marching.  The lack of a separate depth and density coefficient is what is concerning.  &#xD;&#xA;&#xD;&#xA;Going off of the presentation and other sources, my perception of the approach is as follows (ignoring the optimizations of the coarse steps, the fine grained steps, and the cone method for shadow marching): &#xD;&#xA;&#xD;&#xA;* Forward march with a fixed size until you have a non zero density.  &#xD;&#xA;&#xD;&#xA;* Then march in the direction of the light accumulating the density values at each step.&#xD;&#xA;&#xD;&#xA;* plugin this summed density into the equation as `d`,  `e^(-d*r)*HG*(1.0 - e^(-d *2))`&#xD;&#xA;&#xD;&#xA;* multiply this product by our current forward marched density&#xD;&#xA;&#xD;&#xA;* multiply this value by some sort of transmittance value which is a function of how much &quot;stuff&quot; we've gone through in our cloud. &#xD;&#xA;&#xD;&#xA;* return this value of transmittance, and the value of the light intensity as our final result, transmittance will represent our alpha in some form (either as the actual value, or 1.0 - transmittance) with range 0.0 to 1.0. &#xD;&#xA;&#xD;&#xA;**Are these steps correct and what does theta correspond to for this application in Henyey-Greenstein `HG` and which form of the `HG` equation do I need to use?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://advances.realtimerendering.com/s2015/The%20Real-time%20Volumetric%20Cloudscapes%20of%20Horizon%20-%20Zero%20Dawn%20-%20ARTR.pdf&#xD;&#xA;  [2]: http://www.astro.umd.edu/~jph/HG_note.pdf&#xD;&#xA;  [3]: http://glossary.ametsoc.org/wiki/Henyey-greenstein_phase_function" ContentLicense="CC BY-SA 3.0" />
  <row Id="19358" PostHistoryTypeId="1" PostId="7497" RevisionGUID="f3c33964-8eda-4b10-a16c-c254cf2327b3" CreationDate="2018-04-11T18:35:32.203" UserId="6530" Text="Not understanding the lighting equation for volumetric cloud rendering" ContentLicense="CC BY-SA 3.0" />
  <row Id="19359" PostHistoryTypeId="3" PostId="7497" RevisionGUID="f3c33964-8eda-4b10-a16c-c254cf2327b3" CreationDate="2018-04-11T18:35:32.203" UserId="6530" Text="|rendering|shader|lighting|volumetric|raymarching|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19360" PostHistoryTypeId="5" PostId="3680" RevisionGUID="df410afb-0184-469b-ac63-a79604865c2f" CreationDate="2018-04-11T19:25:35.810" UserId="4647" Comment="Fix GLSL 1.10 compliance" Text="_This is a copy-paste of [my answer](https://stackoverflow.com/a/38039733/673852) to the same [question at StackOverflow](https://stackoverflow.com/q/2508818/673852)_.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;At the bottom of this answer is an example of GLSL code which allows to output the full `float` value as color, encoding IEEE 754 `binary32`. I use it like follows (this snippet gives out `yy` component of modelview matrix):&#xD;&#xA;&#xD;&#xA;&lt;!-- NOTE: setting highlighting language to C since it has similar syntax while GLSL highlighting isn't supported on stackexchange --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);&#xD;&#xA;    if(bool(1)) // put 0 here to get lowest byte instead of three highest&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.rgb,1);&#xD;&#xA;    else&#xD;&#xA;        gl_FrontColor=vec4(xAsColor.a,0,0,1);&#xD;&#xA;&#xD;&#xA;After you get this on screen, you can just take any color picker, format the color as HTML (appending `00` to the `rgb` value if you don't need higher precision, and doing a second pass to get the lower byte if you do), and you get the hexadecimal representation of the `float` as IEEE 754 `binary32`.&#xD;&#xA;&#xD;&#xA;Here's the actual implementation of `toColor()`:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    const int emax=127;&#xD;&#xA;    // Input: x&gt;=0&#xD;&#xA;    // Output: base 2 exponent of x if (x!=0 &amp;&amp; !isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    //         -emax if x==0&#xD;&#xA;    //         emax+1 otherwise&#xD;&#xA;    int floorLog2(float x)&#xD;&#xA;    {&#xD;&#xA;        if(x==0.) return -emax;&#xD;&#xA;        // NOTE: there exist values of x, for which floor(log2(x)) will give wrong&#xD;&#xA;        // (off by one) result as compared to the one calculated with infinite precision.&#xD;&#xA;        // Thus we do it in a brute-force way.&#xD;&#xA;        for(int e=emax;e&gt;=1-emax;--e)&#xD;&#xA;            if(x&gt;=exp2(float(e))) return e;&#xD;&#xA;        // If we are here, x must be infinity or NaN&#xD;&#xA;        return emax+1;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x&#xD;&#xA;    // Output: IEEE 754 biased exponent with bias=emax&#xD;&#xA;    int biasedExp(float x) { return emax+floorLog2(abs(x)); }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that (!isnan(x) &amp;&amp; !isinf(x))&#xD;&#xA;    // Output: significand AKA mantissa of x if !isnan(x) &amp;&amp; !isinf(x)&#xD;&#xA;    //         undefined otherwise&#xD;&#xA;    float significand(float x)&#xD;&#xA;    {&#xD;&#xA;        // converting int to float so that exp2(genType) gets correctly-typed value&#xD;&#xA;        float expo=float(floorLog2(abs(x)));&#xD;&#xA;        return abs(x)/exp2(expo);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: x\in[0,1)&#xD;&#xA;    //        N&gt;=0&#xD;&#xA;    // Output: Nth byte as counted from the highest byte in the fraction&#xD;&#xA;    int part(float x,int N)&#xD;&#xA;    {&#xD;&#xA;        // All comments about exactness here assume that underflow and overflow don't occur&#xD;&#xA;        const float byteShift=256.;&#xD;&#xA;        // Multiplication is exact since it's just an increase of exponent by 8&#xD;&#xA;        for(int n=0;n&lt;N;++n)&#xD;&#xA;            x*=byteShift;&#xD;&#xA;    &#xD;&#xA;        // Cut higher bits away.&#xD;&#xA;        // $q \in [0,1) \cap \mathbb Q'.$&#xD;&#xA;        float q=fract(x);&#xD;&#xA;    &#xD;&#xA;        // Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected&#xD;&#xA;        // results of rounding by the GPU later in the pipeline when transforming to TrueColor&#xD;&#xA;        // the resulting subpixel value.&#xD;&#xA;        // $c \in [0,255] \cap \mathbb Z.$&#xD;&#xA;        // Multiplication is exact since it's just and increase of exponent by 8&#xD;&#xA;        float c=floor(byteShift*q);&#xD;&#xA;        return int(c);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x acceptable to significand()&#xD;&#xA;    // Output: significand of x split to (8,8,8)-bit data vector&#xD;&#xA;    ivec3 significandAsIVec3(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec3 result;&#xD;&#xA;        float sig=significand(x)/2.; // shift all bits to fractional part&#xD;&#xA;        result.x=part(sig,0);&#xD;&#xA;        result.y=part(sig,1);&#xD;&#xA;        result.z=part(sig,2);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Input: any x such that !isnan(x)&#xD;&#xA;    // Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)&#xD;&#xA;    ivec4 packIEEE754binary32(float x)&#xD;&#xA;    {&#xD;&#xA;        int e = biasedExp(x);&#xD;&#xA;        // sign to bit 7&#xD;&#xA;        int s = x&lt;0. ? 128 : 0;&#xD;&#xA;    &#xD;&#xA;        ivec4 binary32;&#xD;&#xA;        binary32.yzw=significandAsIVec3(x);&#xD;&#xA;        // clear the implicit integer bit of significand&#xD;&#xA;        if(binary32.y&gt;=128) binary32.y-=128;&#xD;&#xA;        // put lowest bit of exponent into its position, replacing just cleared integer bit&#xD;&#xA;        binary32.y+=128*int(mod(float(e),2.));&#xD;&#xA;        // prepare high bits of exponent for fitting into their positions&#xD;&#xA;        e/=2;&#xD;&#xA;        // pack highest byte&#xD;&#xA;        binary32.x=e+s;&#xD;&#xA;    &#xD;&#xA;        return binary32;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec4 toColor(float x)&#xD;&#xA;    {&#xD;&#xA;        ivec4 binary32=packIEEE754binary32(x);&#xD;&#xA;        // Transform color components to [0,1] range.&#xD;&#xA;        // Division is inexact, but works reliably for all integers from 0 to 255 if&#xD;&#xA;        // the transformation to TrueColor by GPU uses rounding to nearest or upwards.&#xD;&#xA;        // The result will be multiplied by 255 back when transformed&#xD;&#xA;        // to TrueColor subpixel value by OpenGL.&#xD;&#xA;        return vec4(binary32)/255.;&#xD;&#xA;    }" ContentLicense="CC BY-SA 3.0" />
  <row Id="19361" PostHistoryTypeId="2" PostId="7498" RevisionGUID="907bb67c-d478-4f52-a442-09910e1ba471" CreationDate="2018-04-11T23:24:45.870" UserId="8497" Text="After running across [an aside in a tutorial](https://open.gl/context#Onemorething) and doing some further digging, I think I understand this now.&#xD;&#xA;&#xD;&#xA;According to the [OpenGL ABI specification](https://www.khronos.org/registry/OpenGL/ABI/#4), only the functions defined in OpenGL 1.2 need to be present in the `GL/gl.h` header file. (At least for Linux - other platforms may be different. [This answer](https://stackoverflow.com/a/17555881/3022952) indicates that Windows may expose only OpenGL 1.1 functions by default.) Functionality from more recent OpenGL versions (even commonly used functions) may not even be defined in the header files. -- This seems to be the case for glDrawElementsInstanced. In the headers of one Linux version I looked at, by default glDrawElementsInstanced isn't exposed by the the headers, even though OpenGL 4.5 is supported.&#xD;&#xA;&#xD;&#xA;Instead, the functionality from newer OpenGL versions are apparently handled through the OpenGL extension system. (Even if it's not strictly an &quot;extension&quot;, but part of standard functionality.) That is, each individual user is nominally responsible for loading the function address into the appropriate function variable using the appropriate (platform-specific) `*GetProcAddress()` function from the `GL/glext.h` header. [The usage](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXGetProcAddress.xml) is to pass the appropriate string to the function, which will return a function pointer to the appropriate function (if present), or a null pointer if the functionality can't be found. (See the [tutorial section](https://open.gl/context#Onemorething) for more detail on usage.)&#xD;&#xA;&#xD;&#xA;This is, obviously, somewhat less than satisfactory if you're using modern OpenGL features. There is a preprocessor define GL_GLEXT_PROTOTYPES which, when defined prior to including `GL/glext.h`, will enable the definitions of a large number of standard functions. However, this may not work robustly if you're running on a computer which doesn't implement all of those functions which you're using. (You're likely to get missing symbol error during shared library loading.)&#xD;&#xA;&#xD;&#xA;The better way to handle things is to use the [OpenGL Extension Wrangler](http://glew.sourceforge.net/) (GLEW). This hides the heavy lifting of the whole `*GetProcAddress()` process, defining symbols like `glDrawElementsInstanced` directly in the `glew.h` header. So long as you call `glewInit()` after initializing OpenGL but before using any version dependent function, these functions should be initialized appropriately if available, or to a null pointer if not. &#xD;&#xA;&#xD;&#xA;You can either test for the function pointer being non-null, or use the GLEW-provided version test variables like `GLEW_VERSION_3_1`, which are booleans (not compile-time defines) indicating if that OpenGL version is supported on the computer the program is running on. Alternatively, you can [test on a feature-by-feature level](http://glew.sourceforge.net/basic.html) by using `glewIsSupported()`/`glewGetExtension()`. You can look up the respective strings for individual extensions at the [OpenGL Registry](https://www.khronos.org/registry/OpenGL/index_gl.php). It doesn't lend itself to forward searching, but may permit use of features prior to the nominal version of OpenGL in use.&#xD;&#xA;&#xD;&#xA;So why wasn't this clearer to me before? I think it's because most of the tutorials and documentation about OpenGL simply assume that you're using GLEW. Despite its name, GLEW isn't just about extensions, it also abstracts much of the version-to-version compatibility issues. As long as you put use behind version checks and don't actually attempt to call a non-supported function, GLEW hides all the pesky details about functions which aren't actually being implemented." ContentLicense="CC BY-SA 3.0" />
  <row Id="19362" PostHistoryTypeId="2" PostId="7499" RevisionGUID="f1335731-45a6-4868-977a-b62ffa462b13" CreationDate="2018-04-11T23:36:27.537" UserId="8394" Text="It might be a bit of an overkill, but you could use spatial partitioning, such as Octrees. &#xD;&#xA;&#xD;&#xA;Once you have it built, you can start evaluating partitions, given a max depth level of your choice, and form bounding volumes with the vertices inside each partition.&#xD;&#xA;&#xD;&#xA;You can test all of your shapes for each partition and choose the one that approximates the best all vertices you are enclosing in it (you can measure this by, for example, the volume which, while enclosing all vertices, takes up the less volume).&#xD;&#xA;&#xD;&#xA;PS: I've never tried anything like this, is purely theoretical" ContentLicense="CC BY-SA 3.0" />
  <row Id="19363" PostHistoryTypeId="2" PostId="7500" RevisionGUID="749a046a-1d4e-4a66-b16d-6d72d408b201" CreationDate="2018-04-12T09:29:05.083" UserId="5222" Text="&#xD;&#xA;I'm studying Unreal Engine, this chapter is talk about visual effects: Rendering Overview&#xD;&#xA;&#xD;&#xA;Some of them has obvious picture I can see whats the differences. But not all of them. Is there a site can let me input the keyword, like 'bloom', then it shows the description, a image contains 'no bloom' and 'has bloom' both?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19364" PostHistoryTypeId="1" PostId="7500" RevisionGUID="749a046a-1d4e-4a66-b16d-6d72d408b201" CreationDate="2018-04-12T09:29:05.083" UserId="5222" Text="Where can I find those visual effect demonstration?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19365" PostHistoryTypeId="3" PostId="7500" RevisionGUID="749a046a-1d4e-4a66-b16d-6d72d408b201" CreationDate="2018-04-12T09:29:05.083" UserId="5222" Text="|rendering|shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19366" PostHistoryTypeId="2" PostId="7501" RevisionGUID="44c8ad57-d10f-42a2-8e7b-39dd697816b8" CreationDate="2018-04-12T20:56:19.803" UserId="5664" Text="The Unreal Engine documentation has good explanations for their various post-processing effects like Bloom. You can find more information about it here: https://docs.unrealengine.com/en-us/Engine/Rendering/PostProcessEffects/Bloom&#xD;&#xA;&#xD;&#xA;In the case of UE4, bloom becomes observable once color values push beyond the 1.0 value." ContentLicense="CC BY-SA 3.0" />
  <row Id="19367" PostHistoryTypeId="2" PostId="7502" RevisionGUID="93b004a1-0cf7-4738-90a6-ee4420fc24e4" CreationDate="2018-04-12T21:34:46.770" UserId="48" Text="What they're saying is you don't have to _render_ the game at the same resolution that it's displayed. For example you could be in a display mode of 1920×1080, but have the game rendering at only 1280×720, to run faster. The OS and display hardware can automatically upscale the frames to the display resolution under the hood.&#xD;&#xA;&#xD;&#xA;Usually, the OS runs a window compositor, a background process that draws the desktop, all app windows, menus, etc and presents them to the display. In windowed mode, any upscaling needed would be done by the compositor. However if the game's window is covering the whole display ('borderless fullscreen') and nothing else is on top, then the OS can switch off the compositor and let the game present to the display directly.&#xD;&#xA;&#xD;&#xA;But then if the game is at a lower resolution than the display, it still needs to be upscaled. The GPU can do this in hardware (scanout) _as long as_ the scaling factor isn't too big. For instance, there may be a limit of 4x scaling. So, if your rendering resolution is more than 4x smaller than the display, the OS can't use the hardware upscaling and would need to keep using the window compositor instead. All of this stuff happens automatically in Windows 10, without the app needing to know about it or do anything special.&#xD;&#xA;&#xD;&#xA;Given all this, they point out that there's no real reason for the _rendering_ resolution of the game to be limited to the classic display modes like 800×600, 1024×768, 1280×720, etc. You might as well have a continuous resolution slider instead of a fixed set of modes. There's no problem with choosing a &quot;weird&quot; resolution like, say, 1000×562 or something. The upscaler/compositor will just take care of it.&#xD;&#xA;&#xD;&#xA;This what they mean by &quot;consider providing users with the ability to choose a rendering resolution for performance scaling, independent from an output resolution&quot;. In other words, in your game's options screen, you should give the user a slider to control rendering resolution, so they can tune it for performance vs visual quality. But it need not be tied to the actual display resolution." ContentLicense="CC BY-SA 3.0" />
  <row Id="19368" PostHistoryTypeId="50" PostId="4632" RevisionGUID="701c2785-be3a-4b2a-a8e8-3c4b18991648" CreationDate="2018-04-12T22:56:32.250" UserId="-1" />
  <row Id="19370" PostHistoryTypeId="2" PostId="7503" RevisionGUID="ba142b90-8d4d-47b9-9c63-eb963e340703" CreationDate="2018-04-13T17:53:45.510" UserId="8565" Text="Currently I am reading the BRDF section from Real Time Rendering and I am having a hard time to visually understand the definition of this function. BRDF is the ratio between the radiance in outgoing direction and irradiance of incoming direction. I can't visually understand what does irradiance of a certain direction means? And what is the difference with radiance of certain direction? They both represents the power of light. What does irradiance of a certain direction means? Doesn't we associate a direction with radiance? Isn't radiance defined as irradiance in a single direction? I feel like i misunderstand something here. Is E(v) &lt;= L(v) where v is direction?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19371" PostHistoryTypeId="1" PostId="7503" RevisionGUID="ba142b90-8d4d-47b9-9c63-eb963e340703" CreationDate="2018-04-13T17:53:45.510" UserId="8565" Text="What is the difference between radiance and irradiance in BRDF" ContentLicense="CC BY-SA 3.0" />
  <row Id="19372" PostHistoryTypeId="3" PostId="7503" RevisionGUID="ba142b90-8d4d-47b9-9c63-eb963e340703" CreationDate="2018-04-13T17:53:45.510" UserId="8565" Text="|brdf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19373" PostHistoryTypeId="2" PostId="7504" RevisionGUID="84b68880-70b0-4d6a-8af1-22858f6c9503" CreationDate="2018-04-13T18:38:47.533" UserId="8118" Text="I have a memory that is persistently mapped. It is both HOST_VISIBLE and HOST_COHERENT but not DEVICE_LOCAL. (My physical device offers no memory that is exclusively HOST_VISIBLE without also being HOST_COHERENT.)&#xD;&#xA;&#xD;&#xA;This memory contains vertex buffers. I send commands every frame to draw those buffers. Some of those, I change the content every frame, and others more rarely. &#xD;&#xA;&#xD;&#xA;I believe buffers somehow need to be transfered by the driver into the GPU before it can draw them, yes? Here, I never need to invalidate/flush anything because the memory is HOST_COHERENT. How does the driver know what to update/transfer and when? Does it have to a way to detect parts where I change stuff, or does it compulsively retransfer data every frame? " ContentLicense="CC BY-SA 3.0" />
  <row Id="19374" PostHistoryTypeId="1" PostId="7504" RevisionGUID="84b68880-70b0-4d6a-8af1-22858f6c9503" CreationDate="2018-04-13T18:38:47.533" UserId="8118" Text="Vulkan: how does host coherence work?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19375" PostHistoryTypeId="3" PostId="7504" RevisionGUID="84b68880-70b0-4d6a-8af1-22858f6c9503" CreationDate="2018-04-13T18:38:47.533" UserId="8118" Text="|vulkan|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19376" PostHistoryTypeId="2" PostId="7505" RevisionGUID="1136b5ba-62af-4501-b22b-cdb1f2555495" CreationDate="2018-04-13T20:50:19.290" UserId="2817" Text="If you really need this level of debugging (spoiler: you don't, more on that later), AFAIK only NVIDIA's NSight can provide it. However, in order to remain interactive, you probably need two machines - one to actually run your shader, and the other to debug it - because stopping a GPU for debugging will - quite understandably - freeze the display of the computer, making it unusable.&#xD;&#xA;&#xD;&#xA;One step down from that is [RenderDoc](http://www.renderdoc.org/) and its ability to swap shaders in a capture on the fly, as well as step through Direct3D bytecode and inspect its registers (i.e. a virtual machine for the DXBC, it's most often sufficiently detailed to actually find shader bugs).&#xD;&#xA;&#xD;&#xA;And what most graphics programmers do most days is simply what I like to call &quot;your mom's debugger&quot;, which on the CPU means sprinkling your code with print statements with the intention of later reviewing the log; but in shaders, you just stuff your shader outputs with debug values instead and inspect those values. There are also ways to &quot;print text&quot; from shaders (for instance, [this ShaderToy](https://www.shadertoy.com/view/4dtGD2))." ContentLicense="CC BY-SA 3.0" />
  <row Id="19377" PostHistoryTypeId="2" PostId="7506" RevisionGUID="7cb8857d-c9a2-498e-b169-978d64333e18" CreationDate="2018-04-13T21:49:23.310" UserId="48" Text="I don't think this kind of under-the-hood data transfer should happen in low-level APIs like Vulkan. The GPU is capable of reading directly from host memory, via the PCIe interconnect. So when you render from a host memory buffer, it should dynamically &quot;pull&quot; the vertices referenced by the draw call.&#xD;&#xA;&#xD;&#xA;I'm not sure exactly how host coherence works with this, but my guess is the CPU's memory controller is probably smart enough to snoop PCIe read requests, and do the right thing with regard to the CPU caches.&#xD;&#xA;&#xD;&#xA;If you _wanted_ to transfer the data into GPU memory first, I think you would have to implement that yourself, by allocating some device-local memory and doing a copy into it. (For a vertex buffer that's pretty much consumed linearly once per frame, there's probably no benefit to doing that, but it could be worthwhile for a buffer that's updated more rarely, or that has a more random access pattern.)" ContentLicense="CC BY-SA 3.0" />
  <row Id="19379" PostHistoryTypeId="2" PostId="7507" RevisionGUID="577ffa79-dc81-470d-90dd-b3abb828526f" CreationDate="2018-04-14T02:10:19.103" UserId="2654" Text="&gt; How does the driver know what to update/transfer and when?&#xD;&#xA;&#xD;&#xA;It doesn't. There is no transfer or update in that fashion.&#xD;&#xA;&#xD;&#xA;All memory allocated through a Vulkan device represents memory that *some* device operations can read directly. If a Vulkan device advertises that it can use visible/coherent memory as source vertex data for rendering operations, that does not mean that some kind of upload is going on to make this happen. The device is reading that data from the memory you write to. The `vkFlushMappedRange` function merely expunges writes from CPU cache lines, so that they actually reach the memory.&#xD;&#xA;&#xD;&#xA;Memory that is host-coherent and host-visible would represent memory that either:&#xD;&#xA;&#xD;&#xA;1. Is not cached by the CPU, and therefore the GPU sees the memory as it is. This also means that CPU writes and reads tend to be slow.&#xD;&#xA;&#xD;&#xA;2. The GPU can directly access the CPU's caches, to one degree or another.&#xD;&#xA;&#xD;&#xA;Usually, #2 happens when the GPU is on-die with the CPU. Which would also mean that this would be device-local memory. Since you've said that it isn't device-local, odds are good that it is simply not cached. It may use write-combining (which improves the efficiency of sequential writes), but CPU writes otherwise are delivered as they are. Given that the memory does not seem to include &quot;cached&quot; in its description, I'd say #1 is the most likely.&#xD;&#xA;&#xD;&#xA;Note that just because you don't need to explicitly flush memory does not change the fact that you still need a dependency between the CPU operation writing that data and the GPU command(s) that read it. This would generally be some from of event with a memory dependency." ContentLicense="CC BY-SA 3.0" />
  <row Id="19383" PostHistoryTypeId="2" PostId="7509" RevisionGUID="0beb71e7-4ba5-4bc5-a289-0025b7fa32c7" CreationDate="2018-04-14T10:23:22.133" UserId="8570" Text="This would not be perfect but should probably work well enough for your use case - you could render the objects from lots of different angles with a different solid color for each mesh component (without lighting) then remove any meshes that didn't appear in the final image by counting the pixel colours.&#xD;&#xA;If the objects aren't split up into separate meshes then do this by repeatedly merging groups of triangles which share a vertex into the same group, starting with one group per triangle or polygon.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19388" PostHistoryTypeId="2" PostId="7511" RevisionGUID="ce120ad5-ad5f-47bd-9ea0-57fb6f0aa5be" CreationDate="2018-04-14T16:49:34.570" UserId="7008" Text="It is helpful if you always look at the units that a certain physical quantity measures. Since you use Real-Time Rendering, I'll also quote from that (3rd edition). Also, for the sake of completeness, I'll go through all quantities and units related. I will however assume you understand solid angles. The time $t$ is measured in *seconds* $\left[s\right]$ and the solid angles $\omega$ are measured in *steradians* $\left[sr\right]$.&#xD;&#xA;&#xD;&#xA; 1. *radiant energy $Q$* (in *joules*, $\left[J\right]$) measures the energy, i.e. the energy of a photon times the number of photons.&#xD;&#xA;&#xD;&#xA; 2. *radiant flux $\Phi$* (in *watts*, $\left[W]\right]= \left[\frac{J}{s}\right])$ measures the energy per time, e.g. don't just count the number of photons but the number of photons per second. $\Phi = \frac{Q}{t}$&#xD;&#xA;&#xD;&#xA; 3. &#xD;&#xA;  a) *irradiance $E$* (in *watts per square meter*, $\left[\frac{W}{m^2}\right]$) measures the energy per time and surface area, or the flux per surface area. $E = \frac{Q}{t A} = \frac{\Phi}{A}$&#xD;&#xA;&#xD;&#xA;  b) *radiosity $M$* (in some papers also $B$) is the same as irradiance, only it's leaving a surface and not arriving at it&#xD;&#xA;&#xD;&#xA; 4. *radiance $L$* (*watts per sqaure meter per steradian*, $\left[\frac{W}{m^2 sr}\right]$) is the radiant flux per area and solid angle, or the irradiance per solid angle. $L = \frac{\Phi}{A w}$&#xD;&#xA;&#xD;&#xA;Now there is one thing to consider: $E$ is measured with regards to a a surface $A$ that is perpendicular to the light direction (in other words, the normal of the surface is parallel to the light direction). Therefore we project $A$ onto a plane that fullfills this requirement. If the angle between the surface normal and the light direciton is $\theta$, then our projected surface $A_{proj}$ is calculated thus: $A_{proj} = \frac{A}{cos\theta}$[![Surface $A$ is being projected on a plane, the result is $A_{proj}$, from &quot;Parameterbasierte Texturgenerierung und echtzeitfähiges Rendering von nassen und trockenen Straßenoberflächen in kamerabasierten ADAS Tests&quot;, Tim Lobner][1]][1]&#xD;&#xA;&#xD;&#xA;With this, we can of course also further our radiance calculation to $L = \frac{E}{\omega}$&#xD;&#xA;&#xD;&#xA;But still, $E$ only considers the amount of energy per time, not from which direction it comes. Why is this important? Because of the way you usually look at lighting in computer graphics. You calculate how much light is being reflected from a surface to your viewer (/camera), which also means, that you want to know from which light source it originates (seeing as you would like to have the right amount of energy and the correct color). Additionally, you usually use point lights, meaning that you can view the lighting calculation as that of a ray from a single point (the light source) onto a single point on a surface (your pixel/fragment) and then to your viewer. These directions are written in the matter of solid angles, or to make the theory even easier, in differential solid angles. Another point is that your surface may reflect light differently depending on the where it comes from, which also makes important the direction part. &#xD;&#xA;&#xD;&#xA;So to sum this up a bit:&#xD;&#xA;&#xD;&#xA;&gt; I can't visually understand what does irradiance of a certain direction means?&#xD;&#xA;&#xD;&#xA;It basically means photons from a specific light source, not from any place in space.&#xD;&#xA;&#xD;&#xA;&gt; And what is the difference with radiance of certain direction?&#xD;&#xA;&#xD;&#xA;I hope it is clear, that radiance is irradiance from a certain direction. If not, please try to specify which part still bothers you.&#xD;&#xA;&#xD;&#xA;&gt; They both represents the power of light&#xD;&#xA;&#xD;&#xA;Yes they do. In fact, *steradian* is a dimensionless unit, since it is $\left[\frac{m^2}{m^2}\right]$, and therefore it doesn't really add anything. I see how this is confusing. I hope I could clear up why you do this.&#xD;&#xA;&#xD;&#xA;&gt; What does irradiance of a certain direction means? Doesn't we associate a direction with radiance?&#xD;&#xA;&#xD;&#xA;Careful. We don't associate direction (other than considerung only surfaces perpendicular to the light direction) with irradiance. We do however with radiance.&#xD;&#xA;&#xD;&#xA;&gt; Isn't radiance defined as irradiance in a single direction?&#xD;&#xA;&#xD;&#xA;Yes, you can say that.&#xD;&#xA;&#xD;&#xA;&gt; Is E(v) &lt;= L(v) where v is direction?&#xD;&#xA;&#xD;&#xA;I'd say it is the other way round, $L(v) \leq E(v)$, since $E(v)$ would consider any light source emitting light onto a surface, whereas $L(v)$ only considers light form $v$ (if you consider $v$ as the light source to surface direction. In my writing earlier, this is $\omega$ and in Real Time Rendering specifically, this is $\omega$ as well, or $l$ in chapter 5 as well as in the BRDF Theory chapter). Also, remember that these two physical quantities don't have the same units and should not really be compared this way.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aJrFR.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19389" PostHistoryTypeId="50" PostId="6180" RevisionGUID="56b6808d-6bbf-4142-99de-be8df892f816" CreationDate="2018-04-14T19:16:46.027" UserId="-1" />
  <row Id="19391" PostHistoryTypeId="5" PostId="4838" RevisionGUID="c3a513bc-5691-4c64-ac9f-7030128e62fb" CreationDate="2018-04-15T09:57:19.180" UserDisplayName="user7220" Comment="Corrected links.." Text="What formula is for counting aspect ratio of the image as in this site:&#xD;&#xA;&#xD;&#xA;[Aspect ratio calculator (ARC) | NinjaUnits][1]&#xD;&#xA;&#xD;&#xA;For example: &#xD;&#xA;&#xD;&#xA;	 1000x1200 its aspect ratio 5:6 &#xD;&#xA;	 1000x1333 its aspect ratio 3:4&#xD;&#xA;     2592x3888 its aspect ratio 2:3&#xD;&#xA;&#xD;&#xA;I want to determine this by handling an uploaded image so it should be a formula for counting this, but did not figure out this yet.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.ninjaunits.com/calculators/aspect-ratio/" ContentLicense="CC BY-SA 3.0" />
  <row Id="19392" PostHistoryTypeId="24" PostId="4838" RevisionGUID="c3a513bc-5691-4c64-ac9f-7030128e62fb" CreationDate="2018-04-15T09:57:19.180" Comment="Proposed by 7220 approved by 231 edit id of 387" ContentLicense="CC BY-SA 3.0" />
  <row Id="19393" PostHistoryTypeId="5" PostId="2398" RevisionGUID="6542aeb8-cc11-4f7e-82ef-29de3d6d26c9" CreationDate="2018-04-15T10:00:33.150" UserDisplayName="user7220" Comment="Corrected indents.." Text="I implemented the algorithm shown in given link to fit given image to specified quadrilateral but the output is blank. Here is the link to the algorithm&#xD;&#xA;[http://math.ewha.ac.kr/~jylee/SciComp/dip-crane/chapter8/list8_4.c][1]&#xD;&#xA;&#xD;&#xA;I implemented it in C# as follows&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-csharp --&gt;&#xD;&#xA;&#xD;&#xA;    Bitmap inputImage = new Bitmap(&quot;D:\\Image\\A2.jpg&quot;);&#xD;&#xA;    Bitmap outputBitmap = new Bitmap(inputImage.Width, inputImage.Height);&#xD;&#xA;    double a11, a21, a31, a41;&#xD;&#xA;    double a12, a22, a32, a42;&#xD;&#xA;    double first, second;&#xD;&#xA;    double denom;&#xD;&#xA;    int u, v;&#xD;&#xA;    double floatu, floatv;&#xD;&#xA;    int i, j;&#xD;&#xA;    ulong sourcebase; /// this has been replaced by u,v i think its same&#xD;&#xA;    double x, y;&#xD;&#xA;    double A, B, C;&#xD;&#xA;    int x0 = 50, y0 = 100, x1 = 65, y1 = 110, x2 = 55, y2 = 120, x3 = 450, y3 = 110;// fix value quadrilaeral for checking purpose.&#xD;&#xA;    a11 = x0 - x1 - x3 + x2;&#xD;&#xA;    a21 = x1 - x0;&#xD;&#xA;    a31 = x3 - x0;&#xD;&#xA;    a41 = x0;&#xD;&#xA;    a12 = y0 - y1 - y3 + y2;&#xD;&#xA;    a22 = y1 - y0;&#xD;&#xA;    a32 = y3 - y0;&#xD;&#xA;    a42 = y0;&#xD;&#xA;    Console.WriteLine(&quot;inside of here&quot;);&#xD;&#xA;    A = a11 * a22 - a21 * a12;&#xD;&#xA;    if (A == 0)&#xD;&#xA;        A = 0.00001;&#xD;&#xA;    int rows = inputImage.Height, cols = inputImage.Width;&#xD;&#xA;    for (i = 0; i &lt; rows; i++)&#xD;&#xA;    {&#xD;&#xA;        y = Convert.ToDouble(i) / Convert.ToDouble(rows);&#xD;&#xA;        for (j = 0; j &lt; cols; j++)&#xD;&#xA;        {&#xD;&#xA;            x = Convert.ToDouble(j) / Convert.ToDouble(cols);&#xD;&#xA;            B = a12 * x - a11 * y + a11 * a42 - a41 * a12 + a31 * a22 - a21 * a32;&#xD;&#xA;            C = a32 * x - a31 * y + a31 * a42 - a41 * a32;&#xD;&#xA;            first = B * B;&#xD;&#xA;            second = 4.0 * A * C;&#xD;&#xA;            if (first &lt; second)&#xD;&#xA;                floatu = B / (-2.0 * A);&#xD;&#xA;            else&#xD;&#xA;                floatu = (-1.0 * B + Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;            if((floatu &lt; 0.0) | (floatu &gt; 1.0))&#xD;&#xA;            {&#xD;&#xA;                if (first &lt; second)&#xD;&#xA;                    floatu = B / -2.0 * A;&#xD;&#xA;                else&#xD;&#xA;                    floatu = (1.0 * B - Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;            }&#xD;&#xA;            denom = (a11 * floatu + a31);&#xD;&#xA;            if (denom == 0.0)&#xD;&#xA;                denom = 0.000001;&#xD;&#xA;            floatv = (x - a21 * floatu - a41) / denom;&#xD;&#xA;            u = Convert.ToInt32(floatu * cols + 0.5);&#xD;&#xA;            v = Convert.ToInt32(floatv * rows + 0.5);&#xD;&#xA;            Color pixelColor;&#xD;&#xA;            if ((u &gt;= cols) | (u &lt; 0) | (v &gt;= rows) | (v &lt; 0))&#xD;&#xA;            {&#xD;&#xA;                // Console.WriteLine(&quot;escapaed&quot;);&#xD;&#xA;                pixelColor = Color.Black;&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;            else { /// program ne&#xD;&#xA;                Console.WriteLine(&quot;here&quot;);&#xD;&#xA;                //sourcebase = ((ulong)u * (ulong)cols + (ulong)v);&#xD;&#xA;                pixelColor = inputImage.GetPixel((int)u, (int)v);&#xD;&#xA;                outputBitmap.SetPixel(i, j, pixelColor);// =pixelColor;&#xD;&#xA;                // pictureBox1.Image = outputBitmap;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        //  Console.WriteLine(i);&#xD;&#xA;    }&#xD;&#xA;    pictureBox1.Image = outputBitmap;&#xD;&#xA;    outputBitmap.Save(&quot;output.jpg&quot;);&#xD;&#xA;    Console.WriteLine(&quot;Out Of here&quot;);&#xD;&#xA;    pictureBox1.Invalidate();&#xD;&#xA;&#xD;&#xA;  [1]: http://math.ewha.ac.kr/~jylee/SciComp/dip-crane/chapter8/list8_4.c" ContentLicense="CC BY-SA 3.0" />
  <row Id="19394" PostHistoryTypeId="24" PostId="2398" RevisionGUID="6542aeb8-cc11-4f7e-82ef-29de3d6d26c9" CreationDate="2018-04-15T10:00:33.150" Comment="Proposed by 7220 approved by -1 edit id of 389" ContentLicense="CC BY-SA 3.0" />
  <row Id="19395" PostHistoryTypeId="5" PostId="2398" RevisionGUID="a5beae4d-673c-475a-afe2-099f75c74f76" CreationDate="2018-04-15T10:00:33.150" UserId="231" Comment="Corrected indents and covered naked link" Text="I implemented [this algorithm] to fit given image to specified quadrilateral but the output is blank.&#xD;&#xA;&#xD;&#xA;I implemented it in C# as follows&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-csharp --&gt;&#xD;&#xA;&#xD;&#xA;    Bitmap inputImage = new Bitmap(&quot;D:\\Image\\A2.jpg&quot;);&#xD;&#xA;    Bitmap outputBitmap = new Bitmap(inputImage.Width, inputImage.Height);&#xD;&#xA;    double a11, a21, a31, a41;&#xD;&#xA;    double a12, a22, a32, a42;&#xD;&#xA;    double first, second;&#xD;&#xA;    double denom;&#xD;&#xA;    int u, v;&#xD;&#xA;    double floatu, floatv;&#xD;&#xA;    int i, j;&#xD;&#xA;    ulong sourcebase; /// this has been replaced by u,v i think its same&#xD;&#xA;    double x, y;&#xD;&#xA;    double A, B, C;&#xD;&#xA;    int x0 = 50, y0 = 100, x1 = 65, y1 = 110, x2 = 55, y2 = 120, x3 = 450, y3 = 110;// fix value quadrilaeral for checking purpose.&#xD;&#xA;    a11 = x0 - x1 - x3 + x2;&#xD;&#xA;    a21 = x1 - x0;&#xD;&#xA;    a31 = x3 - x0;&#xD;&#xA;    a41 = x0;&#xD;&#xA;    a12 = y0 - y1 - y3 + y2;&#xD;&#xA;    a22 = y1 - y0;&#xD;&#xA;    a32 = y3 - y0;&#xD;&#xA;    a42 = y0;&#xD;&#xA;    Console.WriteLine(&quot;inside of here&quot;);&#xD;&#xA;    A = a11 * a22 - a21 * a12;&#xD;&#xA;    if (A == 0)&#xD;&#xA;        A = 0.00001;&#xD;&#xA;    int rows = inputImage.Height, cols = inputImage.Width;&#xD;&#xA;    for (i = 0; i &lt; rows; i++)&#xD;&#xA;    {&#xD;&#xA;        y = Convert.ToDouble(i) / Convert.ToDouble(rows);&#xD;&#xA;        for (j = 0; j &lt; cols; j++)&#xD;&#xA;        {&#xD;&#xA;            x = Convert.ToDouble(j) / Convert.ToDouble(cols);&#xD;&#xA;            B = a12 * x - a11 * y + a11 * a42 - a41 * a12 + a31 * a22 - a21 * a32;&#xD;&#xA;            C = a32 * x - a31 * y + a31 * a42 - a41 * a32;&#xD;&#xA;            first = B * B;&#xD;&#xA;            second = 4.0 * A * C;&#xD;&#xA;            if (first &lt; second)&#xD;&#xA;                floatu = B / (-2.0 * A);&#xD;&#xA;            else&#xD;&#xA;                floatu = (-1.0 * B + Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;            if((floatu &lt; 0.0) | (floatu &gt; 1.0))&#xD;&#xA;            {&#xD;&#xA;                if (first &lt; second)&#xD;&#xA;                    floatu = B / -2.0 * A;&#xD;&#xA;                else&#xD;&#xA;                    floatu = (1.0 * B - Math.Sqrt(first - second)) / (2.0 * A);&#xD;&#xA;            }&#xD;&#xA;            denom = (a11 * floatu + a31);&#xD;&#xA;            if (denom == 0.0)&#xD;&#xA;                denom = 0.000001;&#xD;&#xA;            floatv = (x - a21 * floatu - a41) / denom;&#xD;&#xA;            u = Convert.ToInt32(floatu * cols + 0.5);&#xD;&#xA;            v = Convert.ToInt32(floatv * rows + 0.5);&#xD;&#xA;            Color pixelColor;&#xD;&#xA;            if ((u &gt;= cols) | (u &lt; 0) | (v &gt;= rows) | (v &lt; 0))&#xD;&#xA;            {&#xD;&#xA;                // Console.WriteLine(&quot;escapaed&quot;);&#xD;&#xA;                pixelColor = Color.Black;&#xD;&#xA;                continue;&#xD;&#xA;            }&#xD;&#xA;            else { /// program ne&#xD;&#xA;                Console.WriteLine(&quot;here&quot;);&#xD;&#xA;                //sourcebase = ((ulong)u * (ulong)cols + (ulong)v);&#xD;&#xA;                pixelColor = inputImage.GetPixel((int)u, (int)v);&#xD;&#xA;                outputBitmap.SetPixel(i, j, pixelColor);// =pixelColor;&#xD;&#xA;                // pictureBox1.Image = outputBitmap;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        //  Console.WriteLine(i);&#xD;&#xA;    }&#xD;&#xA;    pictureBox1.Image = outputBitmap;&#xD;&#xA;    outputBitmap.Save(&quot;output.jpg&quot;);&#xD;&#xA;    Console.WriteLine(&quot;Out Of here&quot;);&#xD;&#xA;    pictureBox1.Invalidate();&#xD;&#xA;&#xD;&#xA;  [this algorithm]: http://math.ewha.ac.kr/~jylee/SciComp/dip-crane/chapter8/list8_4.c" ContentLicense="CC BY-SA 3.0" />
  <row Id="19398" PostHistoryTypeId="5" PostId="2334" RevisionGUID="e52f9550-eb08-4b36-a668-f2de6d410891" CreationDate="2018-04-15T10:01:56.963" UserDisplayName="user7220" Comment="Corrected links.." Text="Assuming you are looking to transform a particular component (r, g or b) of any color, this can be easily done by simple vector/matrix multiplication.&#xD;&#xA;&#xD;&#xA;The introduction on this page (Chapter 6.1) - from the most excellent immersivemath.com site - illustrates this perfectly:&#xD;&#xA;[Chapter 6: The Matrix (Immersive Linear Algebra) | immersivemath.com][1]&#xD;&#xA;&#xD;&#xA;Think of it as the &quot;Channel Mixer&quot; command in PhotoShop.&#xD;&#xA;&#xD;&#xA;**edit**&#xD;&#xA;&#xD;&#xA;What I described above is one of many ways of changing a given color. The PS Color Replacement Tool simply applies that to any pixel that matches certain conditions defined by the user (source color, destination color, tolerance, etc...). The nifty thing they did is put it in the form of a brush tool, allowing the user artistic control over where to apply the color transform.&#xD;&#xA;&#xD;&#xA;Basically it boils down to this: if a pixel under the brush matches the conditions set by the user the color transform is applied. If not, leave the pixel as is.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://immersivemath.com/ila/ch06_matrices/ch06.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19399" PostHistoryTypeId="24" PostId="2334" RevisionGUID="e52f9550-eb08-4b36-a668-f2de6d410891" CreationDate="2018-04-15T10:01:56.963" Comment="Proposed by 7220 approved by 231 edit id of 388" ContentLicense="CC BY-SA 3.0" />
  <row Id="19400" PostHistoryTypeId="5" PostId="4072" RevisionGUID="48e19240-c6e4-4f19-8f08-0116d2e2fe51" CreationDate="2018-04-15T10:08:39.497" UserDisplayName="user7220" Comment="Corrected links.." Text="Let me try to make my comment into a complete answer.&#xD;&#xA;&#xD;&#xA;The general idea is to build a linear system using those 6 point pairs and solve for the desired 12 unknowns.&#xD;&#xA;You may find this paper[1] useful if you want to learn the theoretical background,&#xD;&#xA;and you can find some more details in my blog post[2].&#xD;&#xA;&#xD;&#xA;Here is my solution using Mathematica.&#xD;&#xA;&#xD;&#xA;In the first step I will build a symbolic array which contains all variables.&#xD;&#xA;&#xD;&#xA;    v = Table[Symbol[&quot;m&quot; &lt;&gt; ToString[i]], {i, 0, 15}];&#xD;&#xA;    M = ArrayReshape[v, {4, 4}]&#xD;&#xA;&#xD;&#xA;Next we write down the coordinates for all vertices.&#xD;&#xA;&#xD;&#xA;    k = f/ n;&#xD;&#xA;&#xD;&#xA;    X = {&#xD;&#xA;        {l, t, -n, 1},&#xD;&#xA;        {l, b, -n, 1},&#xD;&#xA;        {r, b, -n, 1},&#xD;&#xA;        {r, t, -n, 1},&#xD;&#xA;        {k l, k t, -f, 1},&#xD;&#xA;        {k l, k b, -f, 1},&#xD;&#xA;        {k r, k b, -f, 1},&#xD;&#xA;        {k r, k t, -f, 1}};&#xD;&#xA;&#xD;&#xA;    U = {&#xD;&#xA;        {-1, 1, -1},&#xD;&#xA;        {-1, -1, -1},&#xD;&#xA;        {1, -1, -1},&#xD;&#xA;        {1, 1, -1},&#xD;&#xA;        {-1, 1, 1},&#xD;&#xA;        {-1, -1, 1},&#xD;&#xA;        {1, -1, 1},&#xD;&#xA;        {1, 1, 1}};&#xD;&#xA;&#xD;&#xA;where `l`,`r`,`b`,`t`,`n`,and `f` denote left, right, bottom, top, near, and far planes respectively,&#xD;&#xA;and 'X' is the coordinates in world space, `U` is the coordinates in NDC.&#xD;&#xA;&#xD;&#xA;Then next we implement a function `Generate` to generate an equation for each pair of coordinates:&#xD;&#xA;&#xD;&#xA;    Generate[{i_, j_}] := M[[j]].X[[i]] - U[[i, j]] M[[4]].X[[i]] == 0;&#xD;&#xA;&#xD;&#xA;Because we do not care about the third row,&#xD;&#xA;we only solve for the unknowns in `partialv`:&#xD;&#xA;&#xD;&#xA;    partialv = {m0, m1, m2, m3, m4, m5, m6, m7, m12, m13, m14, m15};&#xD;&#xA;&#xD;&#xA;Now we can build our linear system and solve it:&#xD;&#xA;&#xD;&#xA;    solve[subset_] := Solve[&#xD;&#xA;        Map[Generate, Table[{i, j}, {i, subset}, {j, 1, 2}], {2}] // Flatten,&#xD;&#xA;        partialv] // Simplify&#xD;&#xA;&#xD;&#xA;Let me explain it a little bit.&#xD;&#xA;&#xD;&#xA;Because only 6 pairs of points are given, we select a `subset` of 6 elements from the 8 pairs of points.&#xD;&#xA;Then we call `Generate` function on this `subset`&#xD;&#xA;and the first two rows of matrix(we do not care about the third row. And the fourth row is the &quot;homogeneous&quot; part, which is also ignored).&#xD;&#xA;&#xD;&#xA;Finally we enumerate all subsets from these 8 pairs of points, and try to find a solution:&#xD;&#xA;&#xD;&#xA;    solutions = Map[solve, Subsets[{1, 2, 3, 4, 5, 6, 7, 8}, {6}]];&#xD;&#xA;&#xD;&#xA;We can view one solution by:&#xD;&#xA;&#xD;&#xA;    MatrixForm[ArrayReshape[v /. solutions[[1]], {4, 4}]]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA; \text{m0} &amp; 0 &amp; \frac{\text{m0} (l+r)}{2 n} &amp; 0 \\&#xD;&#xA; 0 &amp; \frac{\text{m0} (l-r)}{b-t} &amp; \frac{\text{m0} (l-r) (b+t)}{2 n (b-t)} &amp; 0 \\&#xD;&#xA; \text{m8} &amp; \text{m9} &amp; \text{m10} &amp; \text{m11} \\&#xD;&#xA; 0 &amp; 0 &amp; \frac{\text{m0} (l-r)}{2 n} &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The `m0` is the &quot;unknown scalar factor&quot; which is mentioned in problem statement.&#xD;&#xA;&#xD;&#xA;In fact if we let `m0` equals `2 n/(r - l)`,&#xD;&#xA;we would get the conventional projection matrix used in OpenGL:&#xD;&#xA;&#xD;&#xA;    % /. m0 -&gt; 2 n/(r - l)&#xD;&#xA;    % // Simplify // MatrixForm&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA; \frac{2 n}{r-l} &amp; 0 &amp; \frac{l+r}{r-l} &amp; 0 \\&#xD;&#xA; 0 &amp; -\frac{2 n}{b-t} &amp; -\frac{b+t}{b-t} &amp; 0 \\&#xD;&#xA; \text{m8} &amp; \text{m9} &amp; \text{m10} &amp; \text{m11} \\&#xD;&#xA; 0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;[1] Heckbert, Paul S. Fundamentals of texture mapping and image warping. MS thesis. University of California, Berkeley, 1989.&#xD;&#xA;&#xD;&#xA;[2] Inferring projective mappings [Inferring projective mappings | linearconstraints.net][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.linearconstraints.net/2016/02/03/inferring-projective-mappings.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19401" PostHistoryTypeId="24" PostId="4072" RevisionGUID="48e19240-c6e4-4f19-8f08-0116d2e2fe51" CreationDate="2018-04-15T10:08:39.497" Comment="Proposed by 7220 approved by -1 edit id of 391" ContentLicense="CC BY-SA 3.0" />
  <row Id="19402" PostHistoryTypeId="5" PostId="4072" RevisionGUID="d34c2896-6c86-41dd-b9c9-8ca6818e1a6f" CreationDate="2018-04-15T10:08:39.497" UserId="231" Comment="Changed `[1]` to `\[1\]` to avoid being interpreted as markdown link" Text="Let me try to make my comment into a complete answer.&#xD;&#xA;&#xD;&#xA;The general idea is to build a linear system using those 6 point pairs and solve for the desired 12 unknowns. You may find this paper&lt;sup&gt;\[1\]&lt;/sup&gt; useful if you want to learn the theoretical background, and you can find some more details in my blog post&lt;sup&gt;\[2\]&lt;/sup&gt;.&#xD;&#xA;&#xD;&#xA;Here is my solution using Mathematica.&#xD;&#xA;&#xD;&#xA;In the first step I will build a symbolic array which contains all variables.&#xD;&#xA;&#xD;&#xA;    v = Table[Symbol[&quot;m&quot; &lt;&gt; ToString[i]], {i, 0, 15}];&#xD;&#xA;    M = ArrayReshape[v, {4, 4}]&#xD;&#xA;&#xD;&#xA;Next we write down the coordinates for all vertices.&#xD;&#xA;&#xD;&#xA;    k = f/ n;&#xD;&#xA;&#xD;&#xA;    X = {&#xD;&#xA;        {l, t, -n, 1},&#xD;&#xA;        {l, b, -n, 1},&#xD;&#xA;        {r, b, -n, 1},&#xD;&#xA;        {r, t, -n, 1},&#xD;&#xA;        {k l, k t, -f, 1},&#xD;&#xA;        {k l, k b, -f, 1},&#xD;&#xA;        {k r, k b, -f, 1},&#xD;&#xA;        {k r, k t, -f, 1}};&#xD;&#xA;&#xD;&#xA;    U = {&#xD;&#xA;        {-1, 1, -1},&#xD;&#xA;        {-1, -1, -1},&#xD;&#xA;        {1, -1, -1},&#xD;&#xA;        {1, 1, -1},&#xD;&#xA;        {-1, 1, 1},&#xD;&#xA;        {-1, -1, 1},&#xD;&#xA;        {1, -1, 1},&#xD;&#xA;        {1, 1, 1}};&#xD;&#xA;&#xD;&#xA;where `l`,`r`,`b`,`t`,`n`,and `f` denote left, right, bottom, top, near, and far planes respectively,&#xD;&#xA;and 'X' is the coordinates in world space, `U` is the coordinates in NDC.&#xD;&#xA;&#xD;&#xA;Then next we implement a function `Generate` to generate an equation for each pair of coordinates:&#xD;&#xA;&#xD;&#xA;    Generate[{i_, j_}] := M[[j]].X[[i]] - U[[i, j]] M[[4]].X[[i]] == 0;&#xD;&#xA;&#xD;&#xA;Because we do not care about the third row,&#xD;&#xA;we only solve for the unknowns in `partialv`:&#xD;&#xA;&#xD;&#xA;    partialv = {m0, m1, m2, m3, m4, m5, m6, m7, m12, m13, m14, m15};&#xD;&#xA;&#xD;&#xA;Now we can build our linear system and solve it:&#xD;&#xA;&#xD;&#xA;    solve[subset_] := Solve[&#xD;&#xA;        Map[Generate, Table[{i, j}, {i, subset}, {j, 1, 2}], {2}] // Flatten,&#xD;&#xA;        partialv] // Simplify&#xD;&#xA;&#xD;&#xA;Let me explain it a little bit.&#xD;&#xA;&#xD;&#xA;Because only 6 pairs of points are given, we select a `subset` of 6 elements from the 8 pairs of points.&#xD;&#xA;Then we call `Generate` function on this `subset`&#xD;&#xA;and the first two rows of matrix(we do not care about the third row. And the fourth row is the &quot;homogeneous&quot; part, which is also ignored).&#xD;&#xA;&#xD;&#xA;Finally we enumerate all subsets from these 8 pairs of points, and try to find a solution:&#xD;&#xA;&#xD;&#xA;    solutions = Map[solve, Subsets[{1, 2, 3, 4, 5, 6, 7, 8}, {6}]];&#xD;&#xA;&#xD;&#xA;We can view one solution by:&#xD;&#xA;&#xD;&#xA;    MatrixForm[ArrayReshape[v /. solutions[[1]], {4, 4}]]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA; \text{m0} &amp; 0 &amp; \frac{\text{m0} (l+r)}{2 n} &amp; 0 \\&#xD;&#xA; 0 &amp; \frac{\text{m0} (l-r)}{b-t} &amp; \frac{\text{m0} (l-r) (b+t)}{2 n (b-t)} &amp; 0 \\&#xD;&#xA; \text{m8} &amp; \text{m9} &amp; \text{m10} &amp; \text{m11} \\&#xD;&#xA; 0 &amp; 0 &amp; \frac{\text{m0} (l-r)}{2 n} &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The `m0` is the &quot;unknown scalar factor&quot; which is mentioned in problem statement.&#xD;&#xA;&#xD;&#xA;In fact if we let `m0` equals `2 n/(r - l)`,&#xD;&#xA;we would get the conventional projection matrix used in OpenGL:&#xD;&#xA;&#xD;&#xA;    % /. m0 -&gt; 2 n/(r - l)&#xD;&#xA;    % // Simplify // MatrixForm&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA; \frac{2 n}{r-l} &amp; 0 &amp; \frac{l+r}{r-l} &amp; 0 \\&#xD;&#xA; 0 &amp; -\frac{2 n}{b-t} &amp; -\frac{b+t}{b-t} &amp; 0 \\&#xD;&#xA; \text{m8} &amp; \text{m9} &amp; \text{m10} &amp; \text{m11} \\&#xD;&#xA; 0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;\[1\] Heckbert, Paul S. Fundamentals of texture mapping and image warping. MS thesis. University of California, Berkeley, 1989.&#xD;&#xA;&#xD;&#xA;\[2\] Inferring projective mappings [Inferring projective mappings | linearconstraints.net][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://blog.linearconstraints.net/2016/02/03/inferring-projective-mappings.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19405" PostHistoryTypeId="2" PostId="7512" RevisionGUID="588e7012-9380-4a32-9a1c-18a277440f48" CreationDate="2018-04-15T12:58:41.717" UserId="2479" Text="First of all, **irradiance** at certain point of a surface is the density of radiant flux (power) per unit of surface area, while **radiance** at certain point of a surface in a certain direction is the density of radiant flux per unit of surface area and unit of solid angle. Vaguely speaking, irradiance is the amount of light incoming to a certain point from possibly all directions, while radiance is the amount of light incoming to a point from a single directions. Why on Earth do we talk about irradiance from a direction then?&#xD;&#xA;&#xD;&#xA;The thing is that the BRDF definition assumes that there is radiance $L_i\left(\omega_i\right)$ incoming to point $x$ through an infinitesimal cone $\mathrm{d}\omega_{i}$ around the direction $\omega_i$ with solid angle size denoted $\mathrm{d}\sigma\left(\omega_{i}\right)$, which then generates some irradiance on the surface. This &quot;partial&quot; irradiance is then denoted $\mathrm{d}E\left(\omega_{i}\right)$. This incident light can be partially absorbed by the surface and partially scattered in all directions. The out-scattered contribution of $\mathrm{d}E\left(\omega_{i}\right)$ to radiance outgoing in direction $\omega_o$ is denoted as $\mathrm{d}L_{o}\left(\omega_{o}\right)$.&#xD;&#xA;&#xD;&#xA;It can be shown experimentally that the amount of outgoing radiance $\mathrm{d}L_{o}\left(\omega_{o}\right)$ is proportional to the incoming irradiance $\mathrm{d}E\left(\omega_{i}\right)$ and the BRDF is then defined simply as the ratio between the two:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) = \frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{\mathrm{d}E\left(\omega_{i}\right)}&#xD;&#xA;$$" ContentLicense="CC BY-SA 3.0" />
  <row Id="19406" PostHistoryTypeId="2" PostId="7513" RevisionGUID="b61c8097-0b3f-47f8-a57b-6ef2509c824c" CreationDate="2018-04-15T15:07:44.220" UserId="6541" Text="I can easily make models by [Modeling with Distance Functions][1] but I need collision detection so I decide to use voxelizing and make triangles for my [signed distance field tours][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this tours on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![Tours][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_5VBtpVuLQ&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19407" PostHistoryTypeId="1" PostId="7513" RevisionGUID="b61c8097-0b3f-47f8-a57b-6ef2509c824c" CreationDate="2018-04-15T15:07:44.220" UserId="6541" Text="How can I convert signed distance field to a mesh?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19408" PostHistoryTypeId="3" PostId="7513" RevisionGUID="b61c8097-0b3f-47f8-a57b-6ef2509c824c" CreationDate="2018-04-15T15:07:44.220" UserId="6541" Text="|raymarching|unity|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19409" PostHistoryTypeId="5" PostId="7513" RevisionGUID="8b172288-ca10-4f28-8088-91029c403a58" CreationDate="2018-04-15T18:09:13.330" UserId="6541" Comment="edited body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need collision detection so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_5VBtpVuLQ&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19410" PostHistoryTypeId="2" PostId="7514" RevisionGUID="d4f4b4a8-37f4-48d1-8096-129aa4164a2b" CreationDate="2018-04-15T19:48:29.537" UserId="8575" Text="I need to contract(offset) a mesh by a small amount(around 5mm), the mesh itself is quite big (say, 1000mm). The problem is that, I need to contract it based on local mean curvature. That is, for places with higher mean curvature(protruding) less contraction is wanted; and vice versa.&#xD;&#xA;&#xD;&#xA;The best approximation I can find now is CGAL's mesh skeletonization. The skeletonization is done with iterative contraction by mean curvature. So instead of contraction many times, I contract only once, and get what I need.&#xD;&#xA;&#xD;&#xA;The problem with this approach is that the intermediate mesh is not garanteed to be self-intersection free, forbidding further processing. I don't have reliable way to automatically repair intersection.&#xD;&#xA;&#xD;&#xA;I can of course, compute mean curvature at vertices myself and contract accordingly. Problem is I don't know to which direction I should offset a vertex. If I just use the vertex normal, the resulted mesh is very messy(not smooth).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19411" PostHistoryTypeId="1" PostId="7514" RevisionGUID="d4f4b4a8-37f4-48d1-8096-129aa4164a2b" CreationDate="2018-04-15T19:48:29.537" UserId="8575" Text="contract mesh based on mean curvature?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19412" PostHistoryTypeId="3" PostId="7514" RevisionGUID="d4f4b4a8-37f4-48d1-8096-129aa4164a2b" CreationDate="2018-04-15T19:48:29.537" UserId="8575" Text="|mesh|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19413" PostHistoryTypeId="2" PostId="7515" RevisionGUID="751dad79-d6ef-4aaa-a703-94255cc6ec5a" CreationDate="2018-04-15T19:50:22.117" UserId="8575" Text="with CGAL you can generate mesh by implicit function. https://doc.cgal.org/latest/Mesh_3/index.html&#xD;&#xA;&#xD;&#xA;Search for &quot;implicit&quot;. There is an example of generating meshes from the funciton of a sphere." ContentLicense="CC BY-SA 3.0" />
  <row Id="19414" PostHistoryTypeId="5" PostId="7513" RevisionGUID="75d25fed-718e-463d-8b94-6874363e3613" CreationDate="2018-04-16T04:38:45.957" UserId="6541" Comment="edited body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need collision detection so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19415" PostHistoryTypeId="5" PostId="7513" RevisionGUID="4247559b-bce8-496f-9163-fa5ef5ff8bcc" CreationDate="2018-04-16T04:50:40.120" UserId="6541" Comment="added 264 characters in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need collision detection so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher** this is what I want but not released.&#xD;&#xA;&#xD;&#xA;https://www.instagram.com/aiekick/&#xD;&#xA;&#xD;&#xA;https://twitter.com/hashtag/sdfmesher&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;https://sketchfab.com/Aiekick&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19416" PostHistoryTypeId="5" PostId="7513" RevisionGUID="903e4941-f302-49cf-8e82-dd3f418c954b" CreationDate="2018-04-16T05:10:45.710" UserId="6541" Comment="added 63 characters in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need collision detection so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher** this is what I want but not released.&#xD;&#xA;&#xD;&#xA;https://www.instagram.com/aiekick/&#xD;&#xA;&#xD;&#xA;https://twitter.com/hashtag/sdfmesher&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;https://sketchfab.com/Aiekick&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19417" PostHistoryTypeId="5" PostId="7513" RevisionGUID="4ce7aa9c-e59b-4dd0-9dc5-fa092ae00cc0" CreationDate="2018-04-16T05:20:29.843" UserId="6541" Comment="edited body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need collision detection so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher**.this is what I want but not released.&#xD;&#xA;&#xD;&#xA;https://www.instagram.com/aiekick/&#xD;&#xA;&#xD;&#xA;https://twitter.com/hashtag/sdfmesher&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;https://sketchfab.com/Aiekick&#xD;&#xA;&#xD;&#xA;![SDF Mesher](https://user-images.githubusercontent.com/16706911/38791232-cfe1def2-415b-11e8-8961-d93c06dd87d4.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19418" PostHistoryTypeId="5" PostId="7513" RevisionGUID="226de300-06a5-45cd-8522-f3471ffa7fc7" CreationDate="2018-04-16T05:30:27.337" UserId="6541" Comment="deleted 2 characters in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need make mesh from It so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher**.this is what I want but not released.&#xD;&#xA;&#xD;&#xA;https://www.instagram.com/aiekick/&#xD;&#xA;&#xD;&#xA;https://twitter.com/hashtag/sdfmesher&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;https://sketchfab.com/Aiekick&#xD;&#xA;&#xD;&#xA;![SDF Mesher](https://user-images.githubusercontent.com/16706911/38791232-cfe1def2-415b-11e8-8961-d93c06dd87d4.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19419" PostHistoryTypeId="5" PostId="7513" RevisionGUID="a1061455-5311-447c-81e9-83e30fac47bf" CreationDate="2018-04-16T05:36:05.387" UserId="6541" Comment="deleted 2 characters in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need make mesh from It so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher**.this is what I want but not released.&#xD;&#xA;&#xD;&#xA;https://www.instagram.com/aiekick/&#xD;&#xA;&#xD;&#xA;https://twitter.com/hashtag/sdfmesher&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;https://sketchfab.com/Aiekick&#xD;&#xA;&#xD;&#xA;![SDF Mesher](https://user-images.githubusercontent.com/16706911/38791232-cfe1def2-415b-11e8-8961-d93c06dd87d4.gif)&#xD;&#xA;&#xD;&#xA;In short I need a way to convert sdf to mesh.for example this:&#xD;&#xA;&#xD;&#xA;Input : [SDF Model](https://www.shadertoy.com/view/4tc3WB)&#xD;&#xA;&#xD;&#xA;Output : [Mesh](https://sketchfab.com/models/e1ebf9fcd38444d88e45f84204781db9)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19420" PostHistoryTypeId="5" PostId="7513" RevisionGUID="c42992a9-93ec-49f3-a803-c1e80a77996e" CreationDate="2018-04-16T05:41:09.377" UserId="6541" Comment="deleted 2 characters in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need make mesh from It so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;[Snail SDF](https://www.shadertoy.com/view/ld3Gz2)&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher**.this is what I want but not released.&#xD;&#xA;&#xD;&#xA;[aiekick instagram](https://www.instagram.com/aiekick/)&#xD;&#xA;&#xD;&#xA;[aiekick twitter](https://twitter.com/hashtag/sdfmesher)&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;[aiekick sketchfab](https://sketchfab.com/Aiekick)&#xD;&#xA;&#xD;&#xA;![SDF Mesher](https://user-images.githubusercontent.com/16706911/38791232-cfe1def2-415b-11e8-8961-d93c06dd87d4.gif)&#xD;&#xA;&#xD;&#xA;In short I need a way to convert sdf to mesh.for example this:&#xD;&#xA;&#xD;&#xA;Input : [SDF Model](https://www.shadertoy.com/view/4tc3WB)&#xD;&#xA;&#xD;&#xA;Output : [Mesh](https://sketchfab.com/models/e1ebf9fcd38444d88e45f84204781db9)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19421" PostHistoryTypeId="5" PostId="7500" RevisionGUID="ffb21888-a9b0-4255-8e53-5029d0061716" CreationDate="2018-04-16T05:58:29.663" UserId="5222" Comment="added 77 characters in body" Text="I'm studying Unreal Engine, this chapter is talk about visual effects: [Rendering Overview][1]&#xD;&#xA;&#xD;&#xA;Some of them has obvious picture I can see whats the differences. But not all of them. Is there a site can let me input the keyword, like 'bloom', then it shows the description, a image contains 'no bloom' and 'has bloom' both?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unrealengine.com/en-us/Engine/Rendering/Overview" ContentLicense="CC BY-SA 3.0" />
  <row Id="19422" PostHistoryTypeId="6" PostId="7513" RevisionGUID="37bd2135-2142-4552-a258-d084489c968a" CreationDate="2018-04-16T05:58:29.827" UserId="6541" Comment="edited tags" Text="|glsl|mesh|raymarching|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19423" PostHistoryTypeId="2" PostId="7516" RevisionGUID="57872767-3850-4f0a-8e9d-51db33e2ccda" CreationDate="2018-04-16T06:00:59.563" UserId="6541" Text="After many research I figured out how it works:&#xD;&#xA;&#xD;&#xA;he defined three buffer in glsl and i get 3 sampler2D for multipass, in each fbo attachments. the params are (buffer : file : id) file is the targeted shader, here we want the current so no file. id is the fbo attachment (0 to 7).&#xD;&#xA;[![Result][1]][1]&#xD;&#xA;&#xD;&#xA;then he could make the mesh easily:&#xD;&#xA;&#xD;&#xA;![SDF Mesher](https://user-images.githubusercontent.com/16706911/38791232-cfe1def2-415b-11e8-8961-d93c06dd87d4.gif)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/byRkM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19424" PostHistoryTypeId="5" PostId="7513" RevisionGUID="375b85b2-8730-4353-b9c6-f05c9d4c67fe" CreationDate="2018-04-16T06:04:04.413" UserId="6541" Comment="deleted 116 characters in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need make mesh from It so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;______________&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;[Snail SDF](https://www.shadertoy.com/view/ld3Gz2)&#xD;&#xA;&#xD;&#xA;I find a software as **SDF Mesher**.this is what I want but not released.&#xD;&#xA;&#xD;&#xA;[aiekick instagram](https://www.instagram.com/aiekick/),&#xD;&#xA;[aiekick twitter](https://twitter.com/hashtag/sdfmesher)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;[aiekick sketchfab](https://sketchfab.com/Aiekick)&#xD;&#xA;__________________&#xD;&#xA;&#xD;&#xA;In short I need a way to convert sdf to mesh.for example this:&#xD;&#xA;&#xD;&#xA;Input : [SDF Model](https://www.shadertoy.com/view/4tc3WB)&#xD;&#xA;&#xD;&#xA;Output : [Mesh](https://sketchfab.com/models/e1ebf9fcd38444d88e45f84204781db9)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19425" PostHistoryTypeId="5" PostId="7513" RevisionGUID="0e5e2952-1157-4afe-8ea9-73119c9b038d" CreationDate="2018-04-16T14:14:23.897" UserId="6541" Comment="added 1 character in body" Text="I can easily make models by [Modeling with Distance Functions][1] but I need make mesh from It so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xD;&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xD;&#xA;&#xD;&#xA;[![torus][4]][4]&#xD;&#xA;______________&#xD;&#xA;&#xD;&#xA;#Update&#xD;&#xA;&#xD;&#xA;[![Snail IQ][5]][5]&#xD;&#xA;&#xD;&#xA;[Snail SDF](https://www.shadertoy.com/view/ld3Gz2)&#xD;&#xA;&#xD;&#xA;I found a software as **SDF Mesher**.this is what I want but not released.&#xD;&#xA;&#xD;&#xA;[aiekick instagram](https://www.instagram.com/aiekick/),&#xD;&#xA;[aiekick twitter](https://twitter.com/hashtag/sdfmesher)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;he converted shader to mesh?! how could be Implemented!?&#xD;&#xA;&#xD;&#xA;[aiekick sketchfab](https://sketchfab.com/Aiekick)&#xD;&#xA;__________________&#xD;&#xA;&#xD;&#xA;In short I need a way to convert sdf to mesh.for example this:&#xD;&#xA;&#xD;&#xA;Input : [SDF Model](https://www.shadertoy.com/view/4tc3WB)&#xD;&#xA;&#xD;&#xA;Output : [Mesh](https://sketchfab.com/models/e1ebf9fcd38444d88e45f84204781db9)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xD;&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19426" PostHistoryTypeId="2" PostId="7517" RevisionGUID="df31a6e6-4b6c-4146-af1f-a7cc382bce93" CreationDate="2018-04-16T18:08:32.713" UserId="6046" Text="To be honest, terms like these are very confusing as they aren't clear cut and on one side of the border. They are more grayish.&#xD;&#xA;&#xD;&#xA;I'm gonna tell you how I convinced myself, as I too had this confusion as soon as I read your question. But I managed to convince myself through this argument.&#xD;&#xA;&#xD;&#xA;First of all we are gonna clear up 4 terms, Radiance, Irradiance, Differential radiance and Differential Irradiance.&#xD;&#xA;&#xD;&#xA; **&quot;Radiance&quot; is what you say associated with a certain direction. To be more formal and according to wikipedia,**&#xD;&#xA;&#xD;&#xA;&gt;  It's the amount of radiant flux emitted/transmitted/received per unit&#xD;&#xA;&gt; projected area, per unit solid angle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Next is differential radiance. We can think of it as an infinitesimal quantity of radiance emitted or recieved in a very small solid angle $d\omega$.**&#xD;&#xA;&#xD;&#xA;**Next is Irradiance. Irradiance isn't normally associated with a direction. According to Wikipedia it's** &#xD;&#xA;&#xD;&#xA;&gt; Radiant flux received by a surface per unit area&#xD;&#xA;&#xD;&#xA;But more commonly and what makes more sense to me, and to the answer of your question, think of irradiance as the integration of radiances over a set of directions.&#xD;&#xA;&#xD;&#xA;So we can say&#xD;&#xA;&#xD;&#xA;$E = \displaystyle\int_{\Omega} L(\omega)\;  \omega.n \;d\omega\\\omega \in \Omega$&#xD;&#xA;&#xD;&#xA;So if we integrate the radiances from every direction that leads us to the original definition of irradiance where direction isn't of concern. However usually we are concerned with only a subset of all the directions such as the Upper hemisphere or the lower hemisphere. This means for example,&#xD;&#xA;&#xD;&#xA;$\Omega = \{ \omega : \omega.n \geq 0 \}$ &#xD;&#xA;&#xD;&#xA;As we can see here, we have limited the irradiance to a set of directions, the upper hemisphere. This doesn't necessarily change it into radiance which is associated by direction. Instead what this means is, when calculating irradiance we are concerned with the light coming only from these directions, although we haven't incorporated the directional quantity into the formula like with radiance.&#xD;&#xA;&#xD;&#xA;This is the difference between irradiance from a certain direction and radiance. Think of it like this. You are holding a paper and there are 2 light bulbs in front of you. You want to measure the irradiance. Normally it would just be the radiant flux received by both bulbs per unit area. But now let's say I limit the direction so I am only concerned with the first bulb. Note that I am still calculating the &quot;irradiance&quot;. If I move farther away the flux will decrease thus the irradiance even tho I am concerned with a specific direction. However this isn't the case with radiance where moving farther away won't change it since we divide by the solid angle too balancing the change.&#xD;&#xA;&#xD;&#xA;**The last quantity is differential irradiance. I thought of it as a tiny amount of irradiance from a specific direction. (Again direction gets involved)**&#xD;&#xA;&#xD;&#xA;If you think of irradiance as not assosciated with direction at all, even then when you try to think of differential irradiance you are gonna say it's a tiny amount of irradiance from a small range of direction or maybe a specific direction. That's the reason why it's small.&#xD;&#xA;&#xD;&#xA;But if you think of irradiance as the sum of all the radiances over a specific set of directions. You'll see that it makes things clearer and you'll naturally arrive at the conclusion that differential irradiance will then refer to an irradiance from a specific direction.&#xD;&#xA;&#xD;&#xA;So coming back to your question at last, I hope you might have gotten some intuition as to what &quot;irradiance in a direction means&quot;. &#xD;&#xA;&#xD;&#xA;Mathematically proving it is no hard feat tho. The answer [here][1] explains it quite well. I'm just gonna give a brief explanation. We know the rendering equation is given as&#xD;&#xA;&#xD;&#xA;$L_{outgoing} = L_{emission} + \displaystyle\int_{\Omega} L_{incoming} \;f_{BRDF}(\omega_i, \omega_o)\; \omega_i.n \; d\omega_i$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Assuming for the moment that emission part is zero. we end up with,&#xD;&#xA;&#xD;&#xA;$L_{outgoing} = \displaystyle\int_{\Omega} L_{incoming} \;f_{BRDF}(\omega_i, \omega_o)\; \omega_i.n \; d\omega_i$&#xD;&#xA;&#xD;&#xA;Now as I wrote before, if you forget the BRDF for the time being, we are just integrating the radiances over a given set of direction which is the same as irradiance. &#xD;&#xA;&#xD;&#xA;If we look at one instance of this summation/integration, it's gonna be&#xD;&#xA;&#xD;&#xA;$dL_{outgoing} =  L_{incoming} \; \omega_i.n \; d\omega_i \; f_{BRDF}(\omega_i, \omega_o)$&#xD;&#xA;&#xD;&#xA;$dL_{outgoing} =  dE \; f_{BRDF}(\omega_i, \omega_o)$&#xD;&#xA;&#xD;&#xA;We put $d$ with the outgoind radiance and irradiance because it's a very small part (we are looking at just one instance of that summation/integration)&#xD;&#xA;&#xD;&#xA;$f_{BRDF}(\omega_i, \omega_o) = \displaystyle\frac{dL_{outgoing}}{dE} $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Which is the ratio of the outgoing radiance to the incoming irradiance.&#xD;&#xA;&#xD;&#xA;Again this was just the way I convinced myself and might have some mistakes. Though this is the best I came up with.&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/3757/why-isnt-a-brdf-a-ratio-of-radiances" ContentLicense="CC BY-SA 3.0" />
  <row Id="19427" PostHistoryTypeId="50" PostId="5996" RevisionGUID="d21e2361-44b3-4146-b74a-ccda7ed28a74" CreationDate="2018-04-16T23:33:05.333" UserId="-1" />
  <row Id="19428" PostHistoryTypeId="4" PostId="6243" RevisionGUID="cec7381b-cd5a-41f5-b586-3fc435015f20" CreationDate="2018-04-17T07:11:22.197" UserId="5430" Comment="edited title" Text="Baked anisotropic filtering using spherical harmonics" ContentLicense="CC BY-SA 3.0" />
  <row Id="19436" PostHistoryTypeId="2" PostId="7519" RevisionGUID="d62dd042-206a-4d0b-ab92-d75520fccf11" CreationDate="2018-04-17T17:37:57.943" UserId="8587" Text="I've read the reference guide about the file but I am really confused. Why the hell are there &quot;min&quot; and &quot;max&quot; values ?? A single vertex has only one coordinate array not min and max..&#xD;&#xA;&#xD;&#xA;Also in the structure of the meshes why is there an &quot;indices&quot; reference to the &quot;accessors&quot; if we already put the indices to the &quot;attributes&quot; like &quot;NORMAL: 2&quot;? " ContentLicense="CC BY-SA 3.0" />
  <row Id="19437" PostHistoryTypeId="1" PostId="7519" RevisionGUID="d62dd042-206a-4d0b-ab92-d75520fccf11" CreationDate="2018-04-17T17:37:57.943" UserId="8587" Text="How mesh geometry data (vertex coordinates) stored in glTF?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19438" PostHistoryTypeId="3" PostId="7519" RevisionGUID="d62dd042-206a-4d0b-ab92-d75520fccf11" CreationDate="2018-04-17T17:37:57.943" UserId="8587" Text="|gltf|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19439" PostHistoryTypeId="2" PostId="7520" RevisionGUID="0324e082-de7d-402e-b18b-20a244ab6ea0" CreationDate="2018-04-17T19:51:09.247" UserId="1908" Text="The `min` and `max` values provide an outer bounding box for all `POSITION` data within a given accessor.  Accessors typically contain multiple vertices, for example all of the vertices of a particular primitive, and then `min: [x, y, z]` and `max: [x, y, z]` will offer the bounding box for that primitive.&#xD;&#xA;&#xD;&#xA;For your second question, let's look at the mesh structure from [BoxTextured.gltf](https://github.com/KhronosGroup/glTF-Sample-Models/blob/0bc74b12b2de22a1267ccab819efcf8c6a4f3dc8/2.0/BoxTextured/glTF/BoxTextured.gltf#L44-L56):&#xD;&#xA;&#xD;&#xA;    &quot;meshes&quot;: [&#xD;&#xA;        {&#xD;&#xA;            &quot;primitives&quot;: [&#xD;&#xA;                {&#xD;&#xA;                    &quot;attributes&quot;: {&#xD;&#xA;                        &quot;NORMAL&quot;: 1,&#xD;&#xA;                        &quot;POSITION&quot;: 2,&#xD;&#xA;                        &quot;TEXCOORD_0&quot;: 3&#xD;&#xA;                    },&#xD;&#xA;                    &quot;indices&quot;: 0,&#xD;&#xA;                    &quot;mode&quot;: 4,&#xD;&#xA;                    &quot;material&quot;: 0&#xD;&#xA;                }&#xD;&#xA;            ],&#xD;&#xA;            &quot;name&quot;: &quot;Mesh&quot;&#xD;&#xA;        }&#xD;&#xA;    ],&#xD;&#xA;&#xD;&#xA;In the above example, `mode: 4` is an enum, where `4` means `TRIANGLES`.  The `indices` are stored in accessor `0`, and the `POSITION` data is stored in accessor `2`.  So, accessor `2` will contain a list of vertex positions, but each vertex is allowed to be referenced by multiple triangles.  The indices in accessor `0` declare the triangles by indexing into the list of vertices.&#xD;&#xA;&#xD;&#xA;Here's a sample of the start of accessor `0` from this model:&#xD;&#xA;&#xD;&#xA;    0 &#xD;&#xA;    1 &#xD;&#xA;    2 &#xD;&#xA;&#xD;&#xA;    3 &#xD;&#xA;    2 &#xD;&#xA;    1 &#xD;&#xA;&#xD;&#xA;    4 &#xD;&#xA;    5 &#xD;&#xA;    6 &#xD;&#xA;&#xD;&#xA;    7 &#xD;&#xA;    6 &#xD;&#xA;    5 &#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;And this is a sample of the contents from the start of accessor `2` in this model:&#xD;&#xA;&#xD;&#xA;    -0.50000    -0.50000     0.50000 &#xD;&#xA;     0.50000    -0.50000     0.50000 &#xD;&#xA;    -0.50000     0.50000     0.50000 &#xD;&#xA;     0.50000     0.50000     0.50000 &#xD;&#xA;     0.50000     0.50000     0.50000 &#xD;&#xA;     0.50000    -0.50000     0.50000 &#xD;&#xA;     0.50000     0.50000    -0.50000 &#xD;&#xA;     0.50000    -0.50000    -0.50000 &#xD;&#xA;     ...&#xD;&#xA;&#xD;&#xA;In this manner, the sample model builds a cube by winding triangles around vertices at the corners.&#xD;&#xA;&#xD;&#xA;For a more graphical explanation of this, check out the [glTF Overview Card](https://raw.githubusercontent.com/KhronosGroup/glTF/master/specification/2.0/figures/gltfOverview-2.0.0a.png).&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19440" PostHistoryTypeId="2" PostId="7521" RevisionGUID="1cf875fb-0d10-49be-9c3b-cfe69a47b067" CreationDate="2018-04-18T00:37:45.463" UserId="8591" Text="The left bounds are defined as edges where the interior of the polygon is on the right. Think of them as just being the left edge of the shape. You can see from the given polygon that one left edge (the one furthest on the left) starts at P0 and goes to P6. This is the leftmost edge of the polygon. The only other area of the polygon that has an edge on the left side is the part that looks like a devil horn on the right. Its left edge starts at P4 and goes up to P2." ContentLicense="CC BY-SA 3.0" />
  <row Id="19441" PostHistoryTypeId="2" PostId="7522" RevisionGUID="e201ddea-fd4d-459e-a38d-7014c764d51e" CreationDate="2018-04-18T01:38:55.257" UserId="8517" Text="Crossposted here http://forum.lwjgl.org/index.php?topic=6724&#xD;&#xA;&#xD;&#xA;Hello guys I am trying to blur image using fragment shader but it is not smooth.. I search the internet and I found similar problem... some one answer his question but unfortunately I cannot fallow it.. &#xD;&#xA;&#xD;&#xA;The question here are similar to my problem. this one https://stackoverflow.com/questions/33778381/how-to-blur-image-using-glsl-shader-without-squares and this one &#xD;&#xA;https://stackoverflow.com/questions/44829671/smooth-blur-gaussian-in-opengl-es-2-0&#xD;&#xA;&#xD;&#xA;Now I am trying this code but I got error. cannot call a non-function&#xD;&#xA;&#xD;&#xA;    #version 120&#xD;&#xA;     &#xD;&#xA;    uniform sampler2D sampler;&#xD;&#xA;    varying vec2 tex_coords;&#xD;&#xA;     &#xD;&#xA;    vec4 funcBlurTexture() {&#xD;&#xA;        float blur = 1.0/387.; //?? original settings: 2.0/720.; &#xD;&#xA;        //float blur = 1.0/1280.;&#xD;&#xA;          &#xD;&#xA;         vec4 sum = vec4(0.0);&#xD;&#xA;         vec2 tc = tex_coords;&#xD;&#xA;       &#xD;&#xA;         float hstep = tex_coords.x;&#xD;&#xA;         float vstep = tex_coords.y;&#xD;&#xA;         &#xD;&#xA;         float horizontalOffset = 2.0;&#xD;&#xA;         float radius = 2.0;&#xD;&#xA;         float verticalOffset = 2.0;&#xD;&#xA;         float gaussFactorForOffset = 1.0;&#xD;&#xA;         &#xD;&#xA;         //Trying to use this&#xD;&#xA;         for(horizontalOffset = -radius; horizontalOffset&lt;radius; horizontalOffset  += step) {&#xD;&#xA;            for(verticalOffset = -radius; verticalOffset&lt;radius; verticalOffset += step) {&#xD;&#xA;                sum += texture2D(sampler, tex_coords+vec2(horizontalOffset, verticalOffset))*gaussFactorForOffset(sqrt(horizontalOffset*horizontalOffset + verticalOffset*verticalOffset)/radius);&#xD;&#xA;            }&#xD;&#xA;         }&#xD;&#xA;     &#xD;&#xA;         /*&#xD;&#xA;        //Old Code&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x - 4.0*blur*hstep, tc.y)) * 0.0162162162;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x - 3.0*blur*hstep, tc.y)) * 0.0540540541;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x - 2.0*blur*hstep, tc.y)) * 0.1216216216;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x - 1.0*blur*hstep, tc.y)) * 0.1945945946;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x, tc.y)) * 0.2270270270;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x + 1.0*blur*hstep, tc.y)) * 0.1945945946;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x + 2.0*blur*hstep, tc.y)) * 0.1216216216; &#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x + 3.0*blur*hstep, tc.y)) * 0.0540540541;&#xD;&#xA;         sum += texture2D(sampler, vec2(tc.x + 4.0*blur*hstep, tc.y)) * 0.0162162162;&#xD;&#xA;         */&#xD;&#xA;     &#xD;&#xA;            vec4 vColor = texture2D(sampler, tex_coords); &#xD;&#xA;            vec4 bluredTexture = vColor * vec4(sum.rgb, 1.0);&#xD;&#xA;        return bluredTexture;&#xD;&#xA;    }&#xD;&#xA;     &#xD;&#xA;    void main() {&#xD;&#xA;        gl_FragColor = funcBlurTexture();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;How to apply this code in my shader?&#xD;&#xA;&#xD;&#xA;    for(horizontalOffset = -radius; horizontalOffset&lt;radius; horizontalOffset  += step) {&#xD;&#xA;        for(verticalOffset = -radius; verticalOffset&lt;radius; verticalOffset += step) {&#xD;&#xA;            sum += texture2D(texture, textureCoordinate+vec2(horizontalOffset, verticalOffset))*gaussFactorForOffset(sqrt(horizontalOffset*horizontalOffset + verticalOffset*verticalOffset)/radius);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Any Help?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19442" PostHistoryTypeId="1" PostId="7522" RevisionGUID="e201ddea-fd4d-459e-a38d-7014c764d51e" CreationDate="2018-04-18T01:38:55.257" UserId="8517" Text="gaussFactorForOffset cannot call a non-function how to fixed this code?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19443" PostHistoryTypeId="3" PostId="7522" RevisionGUID="e201ddea-fd4d-459e-a38d-7014c764d51e" CreationDate="2018-04-18T01:38:55.257" UserId="8517" Text="|fragment-shader|gaussian-blur|blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19444" PostHistoryTypeId="2" PostId="7523" RevisionGUID="9c715d52-b3b0-4b6f-b74c-43dcf5ca010b" CreationDate="2018-04-18T06:33:36.040" UserId="7008" Text="It would be helpful if you posted some more information about what you're trying to do (rather than problem links) and some screenshots of what is actually happening. Being here I basically see &quot;My code doesn't work, fix it.&quot;, which is not motivating to answer your question...&#xD;&#xA;&#xD;&#xA;That being said, you calculate an offset for reading out from your texture. &#xD;&#xA;&#xD;&#xA;    texture2D(sampler, tex_coords+vec2(horizontalOffset, verticalOffset))&#xD;&#xA;&#xD;&#xA;Texture coordinates are $u, v \in \left[0, 1\right]$, otherwise they will stay on the edge, border, go back to the opposite side or start from the opposide side again (depending on your set up). So this is offset is a problem at the borders in any case, but that is normal. If we now look at your offset&#xD;&#xA;&#xD;&#xA;    float radius = 2.0;&#xD;&#xA;    for(horizontalOffset = -radius; horizontalOffset&lt;radius; horizontalOffset  += step)&#xD;&#xA;&#xD;&#xA;So you start with an offset of `-2.0`, which far exceeds the texture coordinate interval and go up to `2.0` which again exceeds the interval. This is probably the biggest problem you have in your code, calculation wise.&#xD;&#xA;&#xD;&#xA;Furthermore, you use a variable `step` to increase your `horizontalOffset` and your `verticalOffset` variables, but this `step` has never been created. This should not even compile. &#xD;&#xA;&#xD;&#xA;Since your `horizontalOffset` and `verticalOffset`are meant for the gaussian blur, I guess a new variable is needed.&#xD;&#xA;&#xD;&#xA;Your next problem is, that iirc a gaussian blur should offset the texture coordinates, not the color. You multiply the readout color though, with your `gaussFactorForOffset` method, which may be wrong. In any case, you don't even have the method, and it is not a standard [glsl][1] method. Again this should not compile. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;What you need is to think about what your kernel must look like. In a simple box filter, you would sample a texel and every neighbouring texel, giving you 9 values. You add up the 9 values, divide by 9 to normalize and write the output. Your gauss blur can work the same way, only that you have to properly weigh the individual values depending on their position. You can also sample more pixels, than the direct neighbour, say the second neighbour as well - this will give you a nicer blur but will also be a lot slower since you have to do more texture look ups.&#xD;&#xA;&#xD;&#xA;In any case, start with hardcoding that, like you did in your old code. &#xD;&#xA;&#xD;&#xA;In image processing, [they also use these kernels][2], so you can look at them. The linked one would translate to your problem thus:&#xD;&#xA;&#xD;&#xA;    float verticalStep = 1/numberOfVerticalPixels;&#xD;&#xA;    float horizontalsteps = 1/numberOfHorizontalPixels; //these two variables you have to set yourself&#xD;&#xA;    //top row of kernel&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x - horizontalstep, tc.y - verticalStep)) * (1/16);&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x, tc.y - verticalStep)) * (1/8);&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x + horizontalstep, tc.y - verticalStep)) * (1/16);&#xD;&#xA;    //middle row&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x - horizontalstep, tc.y)) * (1/8);&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x, tc.y)) * (1/4);&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x + horizontalstep, tc.y)) * (1/8);&#xD;&#xA;    //bottom row&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x - horizontalstep, tc.y + verticalStep)) * (1/16);&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x, tc.y + verticalStep)) * (1/8);&#xD;&#xA;    sum += texture2D(sampler, vec2(tc.x + horizontalstep, tc.y + verticalStep)) * (1/16);&#xD;&#xA;    return sum;&#xD;&#xA;&#xD;&#xA;Now once you get this to work, then you can start optimizing. and cleaning up your code.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf&#xD;&#xA;  [2]: https://stackoverflow.com/questions/20746172/blur-an-image-using-3x3-gaussian-kernel" ContentLicense="CC BY-SA 3.0" />
  <row Id="19448" PostHistoryTypeId="50" PostId="6012" RevisionGUID="ec6fd979-64aa-44ed-b513-e5b692c51a7c" CreationDate="2018-04-18T16:47:37.467" UserId="-1" />
  <row Id="19449" PostHistoryTypeId="5" PostId="2455" RevisionGUID="0dd72e2c-2360-487f-9cd7-7e4813d553cd" CreationDate="2018-04-18T18:40:59.207" UserId="48" Comment="indentation" Text="I am going through code snippet that reads in a triangular model, calculates &amp; store the normal with each Triangle object and eventually check the consistencies of winding order. Let us define a triangle with the vertices v1, v2 and v3. The face normal of the triangle is calculated as follows:&#xD;&#xA;&#xD;&#xA;    void calculateFaceNormal()&#xD;&#xA;    {&#xD;&#xA;       //vector from v3 to v1&#xD;&#xA;       double dx13, dy13, dz13;&#xD;&#xA;&#xD;&#xA;       //vector from v3 to v2&#xD;&#xA;       double dx23, dy23, dz23;&#xD;&#xA;&#xD;&#xA;		dx13 = v1.x_ - v3.x_;&#xD;&#xA;		dy13 = v1.y_ - v3.y_;&#xD;&#xA;		dz13 = v1.z_ - v3.z_;&#xD;&#xA;&#xD;&#xA;		dx23 = v2.x_ - v3.x_;&#xD;&#xA;		dy23 = v2.y_ - v3.y_;&#xD;&#xA;		dz23 = v2.z_ - v3.z_;&#xD;&#xA;&#xD;&#xA;		// Cross product gives normal.&#xD;&#xA;		x_ = dy13*dz23 - dy23*dz13;&#xD;&#xA;		y_ = dz13*dx23 - dz23*dx13;&#xD;&#xA;		z_ = dx13*dy23 - dx23*dy13;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Each Triangle object store the references of its neighboring triangles as follows:&#xD;&#xA;&#xD;&#xA;    class Triangle()&#xD;&#xA;    {&#xD;&#xA;      public:&#xD;&#xA;        .......&#xD;&#xA;        .......&#xD;&#xA;&#xD;&#xA;        const Triangle *edge12Granne_;&#xD;&#xA;        const Triangle *edge23Granne_;&#xD;&#xA;        const Triangle *edge31Granne_;&#xD;&#xA;&#xD;&#xA;        bool isGranne12NormalConsistent() const;&#xD;&#xA;        bool isGranne23NormalConsistent() const;&#xD;&#xA;        bool isGranne31NormalConsistent() const;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I am writing down only one of the functions whose definition is not clear to me and I believe that if someone could explain the theories behind it,I shall be able to understand the rest of the other two functions.&#xD;&#xA;&#xD;&#xA; 	bool Triangle::isGranne12NormalConsistent() const&#xD;&#xA;	{&#xD;&#xA;		// Find opposing vertex in neighbour.&#xD;&#xA;		if (edge12Granne_-&gt;edge12Granne_ == this)&#xD;&#xA;		{&#xD;&#xA;			/*&#xD;&#xA;			 * two triangle are neighbors to each other by&#xD;&#xA;			 * the adjecent edge that constitutes both the&#xD;&#xA;			 * triangles.&#xD;&#xA;			 * */&#xD;&#xA;&#xD;&#xA;			// v2 | w1&#xD;&#xA;			// v1 | w2&#xD;&#xA;			if (v1_.id_ == edge12Granne_-&gt;v2_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		else if (edge12Granne_-&gt;edge23Granne_ == this)&#xD;&#xA;		{&#xD;&#xA;			// v2 | w2&#xD;&#xA;			// v1 | w3&#xD;&#xA;			if (v1_.id_ == edge12Granne_-&gt;v3_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// v2 | w3&#xD;&#xA;			// v1 | w1&#xD;&#xA;			if (v1_.id_ == edge12Granne_-&gt;v1_.id_)&#xD;&#xA;			{&#xD;&#xA;				// Ok (reversed order compared to this.)&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				// Not ok, same order!&#xD;&#xA;				return false;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19450" PostHistoryTypeId="5" PostId="3768" RevisionGUID="8476e91c-35bd-4c82-9433-f8f5a77d56e1" CreationDate="2018-04-18T18:41:10.557" UserDisplayName="user7220" Comment="Corrected indents.." Text="I am trying to render Blinn Phong as a BRDF model on a surface plane. I assume that every normal in every pixel is perpendicular with the plane.&#xD;&#xA;I know that to do a rendering we have to use 3d programing API such as OpenGL or WebGL and so on.  &#xD;&#xA;My purpose is to render the surface plane without those APIs. The steps that I take are, I create 2 spaces:&#xD;&#xA;&#xD;&#xA; 1. image space: (0,0) is at the top left of the image.&#xD;&#xA; 1. camera space: (0,0) is at the middle of the image.&#xD;&#xA;&#xD;&#xA;For vector computation, I convert every pixel position of image space to camera space then to world space.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    double[] cam=((new double[]{0,0,1}));&#xD;&#xA;    double[] lum=((new double[]{0,0,1}));&#xD;&#xA;    double[] E=new double[3];&#xD;&#xA;    double[] L=new double[3];&#xD;&#xA;    double[] H=new double[3];&#xD;&#xA;    double D2;&#xD;&#xA;    Mat image=new Mat(rows,cols,CvType.CV_8UC3);&#xD;&#xA;    System.out.println(&quot;Start!!&quot;);&#xD;&#xA;    System.out.println(&quot;ok&quot;);&#xD;&#xA;    for(int i=0;i&lt;tileHNumber;i++)&#xD;&#xA;    {&#xD;&#xA;        for(int j=0;j&lt;tileWNumber;j++)&#xD;&#xA;        {&#xD;&#xA;            for(int s=0;s&lt;192;s++)&#xD;&#xA;            {&#xD;&#xA;                for(int t=0;t&lt;192;t++)&#xD;&#xA;                {&#xD;&#xA;                    originS=s+192*i;//ligne&#xD;&#xA;                    originT=t+192*j;//colonne&#xD;&#xA;                    double[] pos=(Image2Cam(new double[]{originT,originS,0}));&#xD;&#xA;                    E=normalize(XY(cam,pos));&#xD;&#xA;                    L=normalize(XY(lum, pos);&#xD;&#xA;                    double[] le=addXY(L,E);&#xD;&#xA;                    H=normalize(le);&#xD;&#xA;                    D2=dot(E,E);&#xD;&#xA;                    double blue=color(blueColor,pos,E,L,H,D2);&#xD;&#xA;                    double green=color(greenColor,pos,E,L,H,D2);&#xD;&#xA;                    double red=color(redColor,pos,E,L,H,D2);&#xD;&#xA;                    image.put(originS, originT, new byte[]{(byte)(blue),(byte)(green),(byte)(red)});&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    public static double color(double col,double[] pos,double[] E,double[] L,double[] H,double D2)&#xD;&#xA;    {&#xD;&#xA;        double value=0;&#xD;&#xA;        double[] N=normalize((new double[]{pos[0],pos[1],1}));&#xD;&#xA;        double diffuse=Math.max(0, dot(N,L));&#xD;&#xA;        double specular=Math.pow(Math.max(0, dot(N,H)),60);&#xD;&#xA;        value=d*diffuse*0.5+0.2*d+specular*255*0.3;&#xD;&#xA;        return value;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The 2 images below show my results: the first one shows diffuse image only. The second one shows specular image only represented by the white color. &#xD;&#xA;&#xD;&#xA;My question is why the lobe specular is not surrounding the center of the image.&#xD;&#xA;&#xD;&#xA;[![Diffuse image][1]][1]&#xD;&#xA;[![Specular image][2]][2]&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7yBBh.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/A1h2s.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="19451" PostHistoryTypeId="24" PostId="3768" RevisionGUID="8476e91c-35bd-4c82-9433-f8f5a77d56e1" CreationDate="2018-04-18T18:41:10.557" Comment="Proposed by 7220 approved by 209, 48 edit id of 392" ContentLicense="CC BY-SA 3.0" />
  <row Id="19452" PostHistoryTypeId="5" PostId="5996" RevisionGUID="4e459f51-95a1-42cc-bc59-cc753b90c625" CreationDate="2018-04-18T18:41:42.127" UserDisplayName="user7220" Comment="Corrected links.." Text="I'm developing a CAD drawing generator using C# and netdxf library (https://github.com/haplokuon/netDxf)&#xD;&#xA;&#xD;&#xA;The app first performs boolean operations (specifically - union &amp; subtraction) on polygons and draws the resultant path on .dxf file.&#xD;&#xA;&#xD;&#xA;I'm using Angus johnson's Clipper library ([Clipper - an open source freeware polygon clipping library | angusj.com][1]) for clipping &#xD;&#xA;&#xD;&#xA;Everything works fine for polygons, The problem is when I need to clip circles and polygons, the result is a large list of points (representing the path of the figure to be drawn on dxf)&#xD;&#xA;&#xD;&#xA;So the curved portion of the path is composed of tiny segments, which is a big problem for the CAM software that'd be used later. &#xD;&#xA;&#xD;&#xA;Below is such an image (the result of clipping circle and polygon). The grey portion is full of tiny line segments&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Questions - &#xD;&#xA;&#xD;&#xA;1) How can I convert those tiny line segments to circles/arcs using the list of points?&#xD;&#xA;&#xD;&#xA;2) Can I take a completely different approach to avoid this problem?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.angusj.com/delphi/clipper.php&#xD;&#xA;  [2]: https://i.stack.imgur.com/NioSC.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19453" PostHistoryTypeId="24" PostId="5996" RevisionGUID="4e459f51-95a1-42cc-bc59-cc753b90c625" CreationDate="2018-04-18T18:41:42.127" Comment="Proposed by 7220 approved by 209, 48 edit id of 393" ContentLicense="CC BY-SA 3.0" />
  <row Id="19454" PostHistoryTypeId="5" PostId="3727" RevisionGUID="fa4c7852-8936-4874-840d-68ff1120dc57" CreationDate="2018-04-18T22:33:49.680" UserDisplayName="user7220" Comment="Corrected links.." Text="**1. Method: Vertex Clustering**&#xD;&#xA;&#xD;&#xA;This is more or less a low-quality method, but depending on your mesh it could work well.  &#xD;&#xA;The basic idea is to partition the space into a regular grid, and then choose one representative for each cell that holds at least one vertex.  &#xD;&#xA;Then calculate the connectivity based on the connectivity of the original vertices.&#xD;&#xA;&#xD;&#xA;[![2D Vertex Clustering][Figure 1]][Figure 1]&#xD;&#xA;&#xD;&#xA;In the image you see a basic 2D clustering. The unreduced mesh on the left, and the reduced on the right with the chosen representatives.  &#xD;&#xA;As you can see, just choosing an existing vertex as representative (by closest to mean, or closest to center, or any other idea you can think of) you get a subset of vertices.&#xD;&#xA;&#xD;&#xA;But you also see the problem, thin parts will degenerate and parts that are close to forming a loop will probably get connected. But as already said, it depends on your mesh if this works.&#xD;&#xA;&#xD;&#xA;**2. Method: Incremental Mesh Decimation with with Half-edge Collapse**&#xD;&#xA;&#xD;&#xA;[![Figure 2][Figure 2 image]][Figure 2 link]&#xD;&#xA;&#xD;&#xA;One vertex gets collapsed into its neighbour. Thereby you get again a subsampling.  &#xD;&#xA;This is a progressive method. You evaluate which collapse will decrease the quality (for example total distance to the original surface, but many more possible) and collapse it. Then you check if your quality has dropped too much for another collapse, and if so you stop. Otherwise you do it again. Until either the quality drops too much or the target size is reached.&#xD;&#xA;&#xD;&#xA;**Method 3: Progressive Mesh Decimation with Vertex Decimation.**&#xD;&#xA;&#xD;&#xA;The same progressive idea as in method 2, but this time instead of a collapse you just delete a vertex and calculate a new triangulation for the hole that this created.&#xD;&#xA;&#xD;&#xA;  [Figure 1]: https://i.stack.imgur.com/ijNC6.png&#xD;&#xA;&#xD;&#xA;  [Figure 2 link]: https://www.researchgate.net/figure/221129055_fig1_Fig-1-Half-edge-collapse-decimation-operation&#xD;&#xA;&#xD;&#xA;  [Figure 2 image]: https://www.researchgate.net/profile/Khaled_Mamou/publication/221129055/figure/fig1/AS:305611066626062@1449874764141/Half-edge-collapse-decimation-operation.png&#xD;&#xA;&#xD;&#xA;&quot;Fig. 1 . Half-edge collapse decimation operation.&amp;nbsp;&quot;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19455" PostHistoryTypeId="24" PostId="3727" RevisionGUID="fa4c7852-8936-4874-840d-68ff1120dc57" CreationDate="2018-04-18T22:33:49.680" Comment="Proposed by 7220 approved by -1 edit id of 395" ContentLicense="CC BY-SA 3.0" />
  <row Id="19456" PostHistoryTypeId="5" PostId="3727" RevisionGUID="6a5dc03a-4a1d-4d29-b339-19c347521866" CreationDate="2018-04-18T22:33:49.680" UserId="48" Comment="embedded image" Text="**1. Method: Vertex Clustering**&#xD;&#xA;&#xD;&#xA;This is more or less a low-quality method, but depending on your mesh it could work well.  &#xD;&#xA;The basic idea is to partition the space into a regular grid, and then choose one representative for each cell that holds at least one vertex.  &#xD;&#xA;Then calculate the connectivity based on the connectivity of the original vertices.&#xD;&#xA;&#xD;&#xA;![2D Vertex Clustering][Figure 1]&#xD;&#xA;&#xD;&#xA;In the image you see a basic 2D clustering. The unreduced mesh on the left, and the reduced on the right with the chosen representatives.  &#xD;&#xA;As you can see, just choosing an existing vertex as representative (by closest to mean, or closest to center, or any other idea you can think of) you get a subset of vertices.&#xD;&#xA;&#xD;&#xA;But you also see the problem, thin parts will degenerate and parts that are close to forming a loop will probably get connected. But as already said, it depends on your mesh if this works.&#xD;&#xA;&#xD;&#xA;**2. Method: Incremental Mesh Decimation with with Half-edge Collapse**&#xD;&#xA;&#xD;&#xA;[![Figure 2][Figure 2 image]][Figure 2 link]&#xD;&#xA;&#xD;&#xA;One vertex gets collapsed into its neighbour. Thereby you get again a subsampling.  &#xD;&#xA;This is a progressive method. You evaluate which collapse will decrease the quality (for example total distance to the original surface, but many more possible) and collapse it. Then you check if your quality has dropped too much for another collapse, and if so you stop. Otherwise you do it again. Until either the quality drops too much or the target size is reached.&#xD;&#xA;&#xD;&#xA;**Method 3: Progressive Mesh Decimation with Vertex Decimation.**&#xD;&#xA;&#xD;&#xA;The same progressive idea as in method 2, but this time instead of a collapse you just delete a vertex and calculate a new triangulation for the hole that this created.&#xD;&#xA;&#xD;&#xA;  [Figure 1]: https://i.stack.imgur.com/ijNC6.png&#xD;&#xA;&#xD;&#xA;  [Figure 2 link]: https://www.researchgate.net/figure/221129055_fig1_Fig-1-Half-edge-collapse-decimation-operation&#xD;&#xA;&#xD;&#xA;  [Figure 2 image]: https://i.stack.imgur.com/vPLlx.png&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19457" PostHistoryTypeId="5" PostId="4044" RevisionGUID="13f88717-48be-4008-a2df-4c9ff02217df" CreationDate="2018-04-19T07:52:09.913" UserDisplayName="user7220" Comment="Corrected links.." Text="Your screen isn't 3D, so how do you display 3D objects on it? You need to map 3D coordinates into 2D space. This also explains why your OpenGL code is not behaving how you're expecting it to. Sorry if parts of this answer are things you already know (just trying to be comprehensive).&#xD;&#xA;&#xD;&#xA;#What do the model view and projection matrices do?&#xD;&#xA;The **model view** matrix is actually two matrices (multiplied together): the model matrix and the view matrix. This is important to understanding because these are two transformations into different spaces.&#xD;&#xA;&#xD;&#xA;The **model** matrix transforms model space into world space. This means that say you have a vertex is at an offset from the center of a model. If you want that vertex to be in world space, it must use the scale, rotation, and position of the model to determine this. The model matrix accomplishes this.&#xD;&#xA;&#xD;&#xA;The **view** matrix transforms the world space into the camera space. Does world move or does the camera move in a 3D application? Well, actually the world moves around the camera. The camera is always at the origin, so the view matrix moves the world to this point.&#xD;&#xA;&#xD;&#xA;The **projection** matrix might be the trickiest to visualize. Screens are 2D (technicalities aside), so how do we show 3D objects here? A projection matrix converts 3D coordinates into 2D coordinates (with depth, so still technically 3D). You end up with Normalized Device Coordinates (NDCs). Each vertex on screen is represented by three values:&#xD;&#xA;* x (horizontal) ranging from [-1, 1]&#xD;&#xA;* y (vertical) ranging from [-1, 1]&#xD;&#xA;* z (depth) ranging from [-1, 1]&#xD;&#xA;&#xD;&#xA;#Why don't you need model-view and projection matrices?&#xD;&#xA;It's not that you don't need them, it's just that you are using as explained in the last step above. Otherwise, you are effectively just rendering 2D graphics. Right now you are drawing a quad.&#xD;&#xA;&#xD;&#xA;Look at the coordinates that you are providing. You are basically treating the vertices as 2D vertices for 2D graphics since you are directly specifying their coordinates in NDC space. Remember, the coordinates you picked are between -1 and 1 for x and y, so you are effectively treating them as NDCs. You directly send them to the rasterizer in your example.&#xD;&#xA;&#xD;&#xA;#Further Reading&#xD;&#xA;* [Tutorial 3 : Matrices | opengl-tutorial.org][1]&#xD;&#xA;* [Coordinate Systems | LearnOpenGL.com][2]&#xD;&#xA;* [OpenGL Projection Matrix | songho.ca][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/&#xD;&#xA;  [2]: http://learnopengl.com/#!Getting-started/Coordinate-Systems&#xD;&#xA;  [3]: http://www.songho.ca/opengl/gl_projectionmatrix.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19458" PostHistoryTypeId="24" PostId="4044" RevisionGUID="13f88717-48be-4008-a2df-4c9ff02217df" CreationDate="2018-04-19T07:52:09.913" Comment="Proposed by 7220 approved by 48, 209 edit id of 396" ContentLicense="CC BY-SA 3.0" />
  <row Id="19459" PostHistoryTypeId="5" PostId="4048" RevisionGUID="28b8d2fc-dc2d-41c0-a50c-514590584115" CreationDate="2018-04-19T07:52:21.520" UserDisplayName="user7220" Comment="Corrected links.." Text="I am trying to create a fog-like effect, similar to that found using perlin noise. I know where I can find information about that effect, but it's harder for me to tell if it's an efficient route for what I want to achieve. A similar effect can be seen here, although I'd imagine what I want is much lower in detail: [Animated perlin noise | youtube.com][1]&#xD;&#xA;&#xD;&#xA;I am currently working in openframeworks. What I have done so far is build a grid of noise values, and have worked towards linearly interpolating in-between those. I feel like I am on the right track, but it very blocky, which makes me wonder if my approach is totally off-mark. This page on Perlin noise has been helpful: [Understanding Perlin Noise | flafla2.github.io][2]&#xD;&#xA;&#xD;&#xA;    for(int x = 0; x &lt; grid.getWidth(); x++){&#xD;&#xA;        if(x % g_size == 0){&#xD;&#xA;            for(int y = 0; y &lt; grid.getHeight(); y++){&#xD;&#xA;                if(y % g_size == 0){&#xD;&#xA;                    noise = ofNoise(x,y,ofGetElapsedTimef());&#xD;&#xA;                    grid.setColor(x,y,ofFloatColor(noise));&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    ofVec2f g1, g2, g3, g4;&#xD;&#xA;    float f1, f2, f3, f4, u, v, t_1, t_2;&#xD;&#xA;    &#xD;&#xA;    for(int x = 0; x &lt; grid.getWidth(); x++){&#xD;&#xA;        for(int y = 0; y &lt; grid.getHeight(); y++){&#xD;&#xA;            //find neigboring grid points&#xD;&#xA;            g1 = ofVec2f(x-(x % g_size),y-(y % g_size));&#xD;&#xA;            g2 = ofVec2f(g1.x + g_size,g1.y);&#xD;&#xA;            g3 = ofVec2f(g1.x,g1.y + g_size);&#xD;&#xA;            g4 = g1 + g_size;&#xD;&#xA;&#xD;&#xA;            //get noise values from the grid neighbors&#xD;&#xA;            f1 = grid.getColor(g1.x,g1.y).r;&#xD;&#xA;            f2 = grid.getColor(g2.x,g2.y).r;&#xD;&#xA;            f3 = grid.getColor(g3.x,g3.y).r;&#xD;&#xA;            f4 = grid.getColor(g4.x,g4.y).r;&#xD;&#xA;  &#xD;&#xA;            u = (float)(x % g_size)/g_size;&#xD;&#xA;            v = (float)(y % g_size)/g_size;&#xD;&#xA; &#xD;&#xA;            t_1 = ofLerp(f1,f2,u);&#xD;&#xA;            t_2 = ofLerp(f3,f4,u);&#xD;&#xA;            &#xD;&#xA;            ofColor average = ofLerp(t_1,t_2,v);&#xD;&#xA;            &#xD;&#xA;            fog.setColor(x,y,average);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=csYzDia5Ckw&#xD;&#xA;  [2]: http://flafla2.github.io/2014/08/09/perlinnoise.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19460" PostHistoryTypeId="24" PostId="4048" RevisionGUID="28b8d2fc-dc2d-41c0-a50c-514590584115" CreationDate="2018-04-19T07:52:21.520" Comment="Proposed by 7220 approved by 48, 209 edit id of 397" ContentLicense="CC BY-SA 3.0" />
  <row Id="19461" PostHistoryTypeId="2" PostId="7525" RevisionGUID="079c68e0-5bb4-4191-b710-635d05acd91a" CreationDate="2018-04-19T09:15:50.597" UserId="8595" Text="Back in the days, MSDN defined a couple of values which in most cases are useless (total crap):&#xD;&#xA;&#xD;&#xA;https://msdn.microsoft.com/en-us/library/windows/desktop/dd144877%28v=vs.85%29.aspx&#xD;&#xA;&#xD;&#xA;    int width_mm = GetDeviceCaps(hdx, HORZSIZE);&#xD;&#xA;    int height_mm = GetDeviceCaps(hdx, VERTSIZE);&#xD;&#xA;&#xD;&#xA;However, there is way to retrieve the information through VESA. Any modern monitor should be able to handle that. Only I have no clue how that's done. Under Linux you have a command called `xrandr` which can be used to find out the info:&#xD;&#xA;&#xD;&#xA;    % xrandr -q&#xD;&#xA;    Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 16384 x 16384&#xD;&#xA;    VGA-0 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 553mm x 311mm&#xD;&#xA;       1920x1080     60.00*+&#xD;&#xA;       1680x1050     59.95  &#xD;&#xA;       1600x1200     60.00  &#xD;&#xA;       1440x900      59.89  &#xD;&#xA;       1280x1024     60.02  &#xD;&#xA;       1280x960      60.00  &#xD;&#xA;       1280x720      60.00  &#xD;&#xA;       1024x768      60.00  &#xD;&#xA;       800x600       60.32  &#xD;&#xA;       640x480       59.94  &#xD;&#xA;    DVI-D-0 disconnected (normal left inverted right x axis y axis)&#xD;&#xA;    HDMI-0 disconnected (normal left inverted right x axis y axis)&#xD;&#xA;&#xD;&#xA;* Note that verified and my monitor dimensions in mm are correct in the output of my `xrandr -q` command.&#xD;&#xA;&#xD;&#xA;I would suggest you look at how that `xrandr` tool does it and you'd get your info right at hand.&#xD;&#xA;&#xD;&#xA;From what I've read over the years, the VESA info can be wrong once in a while, but it's quite reliable now a day, I would think." ContentLicense="CC BY-SA 3.0" />
  <row Id="19462" PostHistoryTypeId="2" PostId="7526" RevisionGUID="733b213a-e2cf-456e-9135-18fce4221158" CreationDate="2018-04-19T09:24:43.877" UserId="8595" Text="I want to create a scene where a room includes a projector and a white screen.&#xD;&#xA;&#xD;&#xA;How is a Ray Tracing environment functioning in such a setup? Is the light from the projector going through a slide and then the color reflecting on the white screen? If so, wouldn't any light ray bounce on that screen creating a mess?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19463" PostHistoryTypeId="1" PostId="7526" RevisionGUID="733b213a-e2cf-456e-9135-18fce4221158" CreationDate="2018-04-19T09:24:43.877" UserId="8595" Text="How is a projector handled in a Ray Tracing environment?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19464" PostHistoryTypeId="3" PostId="7526" RevisionGUID="733b213a-e2cf-456e-9135-18fce4221158" CreationDate="2018-04-19T09:24:43.877" UserId="8595" Text="|raytracing|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19465" PostHistoryTypeId="2" PostId="7527" RevisionGUID="826b3cdd-146b-43db-8445-00be76236df1" CreationDate="2018-04-19T09:32:00.323" UserId="209" Text="Just treat it as a special case of a point light + shadow ray. Whenever a ray hits the screen (or any surface on which you'd like to project the slide), fire another &quot;projector&quot; ray back towards the projector. If it is not obscured, then use the angles (relative to the coordinate system of the projector) to look up a texture map of the slide." ContentLicense="CC BY-SA 3.0" />
  <row Id="19466" PostHistoryTypeId="2" PostId="7528" RevisionGUID="db2935dc-b07f-4434-aa40-f0cc34acb6ac" CreationDate="2018-04-19T09:32:50.317" UserId="137" Text="Graphics is all about cheating when possible.&#xD;&#xA;&#xD;&#xA;The projector can be a spotlight where the color of the light depends on the direction of the light vector.&#xD;&#xA;&#xD;&#xA;It's the same math required for shadow mapping with it.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19467" PostHistoryTypeId="5" PostId="7527" RevisionGUID="d4898bd0-e218-4a86-bc26-f732e4b303f7" CreationDate="2018-04-19T09:51:15.437" UserId="209" Comment="added 8 characters in body" Text="Just treat it as a special case of a point light + shadow ray. Whenever a ray hits the screen (or any surface onto which you'd like to project the slide), fire another &quot;projector&quot; ray back towards the projector. If it is not obscured, then use the X &amp; Y angles (relative to the coordinate system of the projector) to look up a texture map of the slide." ContentLicense="CC BY-SA 3.0" />
  <row Id="19469" PostHistoryTypeId="2" PostId="7529" RevisionGUID="5d0c84c6-948d-4a4e-897a-e9cd43c3c225" CreationDate="2018-04-19T13:01:48.040" UserId="3123" Text="I have a problem with precision on AMD in shaders (`hlsl`). In vertex shader I calculate `UVs` for particle using modulus operator on float. With simple `%` there is a problem on Nvidia and on AMD (e.g. `7 % 7 = 7`) so I have written modulus as:&#xD;&#xA;&#xD;&#xA;    float Mod( float x, float y )    &#xD;&#xA;    {    	&#xD;&#xA;         return x - floor(x / y) * y;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This have fixed the problem on Nvidia but AMD still returns wrong values.&#xD;&#xA;&#xD;&#xA;Any idea what is going on? And how to fixed it?&#xD;&#xA;&#xD;&#xA;I know I can use:&#xD;&#xA;&#xD;&#xA;    float( int( x ) % int( y ) )&#xD;&#xA;&#xD;&#xA;but I think it is slower and I wonder if there is any better way." ContentLicense="CC BY-SA 3.0" />
  <row Id="19470" PostHistoryTypeId="1" PostId="7529" RevisionGUID="5d0c84c6-948d-4a4e-897a-e9cd43c3c225" CreationDate="2018-04-19T13:01:48.040" UserId="3123" Text="Precision problem on AMD" ContentLicense="CC BY-SA 3.0" />
  <row Id="19471" PostHistoryTypeId="3" PostId="7529" RevisionGUID="5d0c84c6-948d-4a4e-897a-e9cd43c3c225" CreationDate="2018-04-19T13:01:48.040" UserId="3123" Text="|hlsl|hardware|float|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19472" PostHistoryTypeId="2" PostId="7530" RevisionGUID="2e889d1f-0198-42c7-a71b-02d54f107bcc" CreationDate="2018-04-19T14:58:20.250" UserId="2041" Text="This is kind-of the same as ratchet freak's answer, but fleshed out a little more.&#xD;&#xA;&#xD;&#xA;The usual way to handle this is with a special projector light type. It's like a spotlight, but (usually) with a square instead of circular fall-off. That is, when you cast a shadow ray to the light, you don't just measure a single angle (or radius) from the light's axis, you measure $(x, y)$ co-ordinates in the light's space. You divide these co-ordinates by the size of the projection (a parameter of the light just like the cone spotlight's angle parameter), and use the result for a texture look-up in the image you want to project.&#xD;&#xA;&#xD;&#xA;&gt; If so, wouldn't any light ray bounce on that screen creating a mess?&#xD;&#xA;&#xD;&#xA;If you're using a GI system, the high-frequency lighting detail that you get from a projector light will create a more challenging GI environment. You can control the badness by making the albedo of the surface you're projecting onto as small as you can get away with. If you don't need accurate GI results, you can use a proxy in the GI system instead of the real projector map. The proxy could have an aggressively blurred image, or even a normal spot-light whose colour is the average of the whole image. The blur technique is very applicable to a path tracer, while a single colour would be simplest for a radiosity or virtual lights implementation." ContentLicense="CC BY-SA 3.0" />
  <row Id="19473" PostHistoryTypeId="2" PostId="7531" RevisionGUID="6f12286d-6efd-4dd6-8f24-6953d9216171" CreationDate="2018-04-19T18:30:58.200" UserId="48" Text="In HLSL, you can use the built-in [`fmod`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb509601(v=vs.85).aspx) function for this.&#xD;&#xA;&#xD;&#xA;I'm not sure what's going wrong with your implementation, though. It looks mathematically correct. It's conceivable you're encountering a precision issue with the subtraction, depending on the inputs.&#xD;&#xA;&#xD;&#xA;BTW, an alternative implementation which avoids the subtraction is:&#xD;&#xA;&#xD;&#xA;	float Mod(float x, float y)&#xD;&#xA;	{&#xD;&#xA;		return frac(x / y) * y;&#xD;&#xA;	}" ContentLicense="CC BY-SA 3.0" />
  <row Id="19477" PostHistoryTypeId="50" PostId="6291" RevisionGUID="3029e99b-cdc2-48c8-afe3-a4b0ad3f856b" CreationDate="2018-04-20T00:03:37.803" UserId="-1" />
  <row Id="19478" PostHistoryTypeId="5" PostId="7525" RevisionGUID="4e16adf3-72a3-4c0c-9fb9-00ad43315267" CreationDate="2018-04-20T01:33:14.760" UserId="8595" Comment="Added missing word" Text="Back in the days, MSDN defined a couple of values which in most cases are useless (total crap):&#xD;&#xA;&#xD;&#xA;https://msdn.microsoft.com/en-us/library/windows/desktop/dd144877%28v=vs.85%29.aspx&#xD;&#xA;&#xD;&#xA;    int width_mm = GetDeviceCaps(hdx, HORZSIZE);&#xD;&#xA;    int height_mm = GetDeviceCaps(hdx, VERTSIZE);&#xD;&#xA;&#xD;&#xA;However, there is way to retrieve the information through VESA. Any modern monitor should be able to handle that. Only I have no clue how that's done. Under Linux you have a command called `xrandr` which can be used to find out the info:&#xD;&#xA;&#xD;&#xA;    % xrandr -q&#xD;&#xA;    Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 16384 x 16384&#xD;&#xA;    VGA-0 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 553mm x 311mm&#xD;&#xA;       1920x1080     60.00*+&#xD;&#xA;       1680x1050     59.95  &#xD;&#xA;       1600x1200     60.00  &#xD;&#xA;       1440x900      59.89  &#xD;&#xA;       1280x1024     60.02  &#xD;&#xA;       1280x960      60.00  &#xD;&#xA;       1280x720      60.00  &#xD;&#xA;       1024x768      60.00  &#xD;&#xA;       800x600       60.32  &#xD;&#xA;       640x480       59.94  &#xD;&#xA;    DVI-D-0 disconnected (normal left inverted right x axis y axis)&#xD;&#xA;    HDMI-0 disconnected (normal left inverted right x axis y axis)&#xD;&#xA;&#xD;&#xA;* Note that I verified and my monitor dimensions in mm are correct in the output of my `xrandr -q` command.&#xD;&#xA;&#xD;&#xA;I would suggest you look at how that `xrandr` tool does it and you'd get your info right at hand.&#xD;&#xA;&#xD;&#xA;From what I've read over the years, the VESA info can be wrong once in a while, but it's quite reliable now a day, I would think." ContentLicense="CC BY-SA 3.0" />
  <row Id="19479" PostHistoryTypeId="2" PostId="7533" RevisionGUID="8d8b0c22-76ed-4dbb-b31d-1c462db1a4a1" CreationDate="2018-04-20T11:47:22.317" UserId="8601" Text="I have a parchment animation at singingdays.co.uk that is a rather large file of about 80mb which obviously is taking a long time to download. I have managed to compress it down to about 60mb using convert and decreasing the colourmap for all the images down to 256 colours, but would like to compress it more without losing the quality. If I could somehow only dispose of part of the background, so that I'm only disposing the part of the background where the parchment is unfurling and keep the top part after the rolled up animation and shadow has passed I think that would help, but must admit that it is boggling my head trying to work it out, if you can even do that with convert, let alone figure it out. If you can do it with convert could you work out the command line and pass it on? If not could you recommend something else? I am working on linux. " ContentLicense="CC BY-SA 3.0" />
  <row Id="19480" PostHistoryTypeId="1" PostId="7533" RevisionGUID="8d8b0c22-76ed-4dbb-b31d-1c462db1a4a1" CreationDate="2018-04-20T11:47:22.317" UserId="8601" Text="compression of gif animation" ContentLicense="CC BY-SA 3.0" />
  <row Id="19481" PostHistoryTypeId="3" PostId="7533" RevisionGUID="8d8b0c22-76ed-4dbb-b31d-1c462db1a4a1" CreationDate="2018-04-20T11:47:22.317" UserId="8601" Text="|animation|compression|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19482" PostHistoryTypeId="2" PostId="7534" RevisionGUID="dbcba2c4-2a81-48ff-a28a-1c7e9a2f6599" CreationDate="2018-04-20T12:45:06.933" UserId="5717" Text="GIF animation compressors normally do this automatically, using transparency in a given frame to avoid storing what has not changed from the previous frame.&#xD;&#xA;&#xD;&#xA;The reason it's not working in your case is that your input is bad. The flat part of the parchment is not really static. It is moving slowly upwards, at a rate of about 1 pixel every 20 frames. Fix your animation so the non moving parts are perfectly identical between frames and you should get a much smaller file.&#xD;&#xA;&#xD;&#xA;You would also get a smaller file if you avoided the noise in the unfurling part (most visible in the shadow). Such noise barely compresses at all. This looks like it came out of some 3D software so crank up the quality settings until the input is noise free.&#xD;&#xA;&#xD;&#xA;If dithering, which is really added noise, is used when producing the images, make sure it does not change from frame to frame. Or just turn it off entirely. You might get a little banding but the file will be smaller. You'll need to decide which you prefer." ContentLicense="CC BY-SA 3.0" />
  <row Id="19483" PostHistoryTypeId="2" PostId="7535" RevisionGUID="d90fc51f-b63c-402e-9790-8c4af0bc9d5e" CreationDate="2018-04-20T15:56:31.030" UserId="8595" Text="OpenGL is always going to be way faster than ray tracing.&#xD;&#xA;&#xD;&#xA;Ray tracing computes pixels one by one using physics (at least a good 90% of the time it's going to be real physics). Although some of it can now be done with a GPU, it is not really helping as much as one would expect. Calculating speculative lightning is not something you can easily do in parallel (ray 1 will bounce from object A to object B, ray 2 will bounce from object A to object C... you can't parallelize the computations on B and C.)&#xD;&#xA;&#xD;&#xA;In comparison, OpenGL is a total fake in comparison. It renders triangles really fast with shades coming from textures and fast gradient computations from your various light sources." ContentLicense="CC BY-SA 3.0" />
  <row Id="19484" PostHistoryTypeId="5" PostId="7525" RevisionGUID="f976cc3c-64e2-4eda-8252-802fd5ef937e" CreationDate="2018-04-20T15:57:51.577" UserId="8595" Comment="Added missing article" Text="Back in the days, MSDN defined a couple of values which in most cases are useless (total crap):&#xD;&#xA;&#xD;&#xA;https://msdn.microsoft.com/en-us/library/windows/desktop/dd144877%28v=vs.85%29.aspx&#xD;&#xA;&#xD;&#xA;    int width_mm = GetDeviceCaps(hdx, HORZSIZE);&#xD;&#xA;    int height_mm = GetDeviceCaps(hdx, VERTSIZE);&#xD;&#xA;&#xD;&#xA;However, there is a way to retrieve the information through VESA. Any modern monitor should be able to handle that. Only I have no clue how that's done. Under Linux you have a command called `xrandr` which can be used to find out the info:&#xD;&#xA;&#xD;&#xA;    % xrandr -q&#xD;&#xA;    Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 16384 x 16384&#xD;&#xA;    VGA-0 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 553mm x 311mm&#xD;&#xA;       1920x1080     60.00*+&#xD;&#xA;       1680x1050     59.95  &#xD;&#xA;       1600x1200     60.00  &#xD;&#xA;       1440x900      59.89  &#xD;&#xA;       1280x1024     60.02  &#xD;&#xA;       1280x960      60.00  &#xD;&#xA;       1280x720      60.00  &#xD;&#xA;       1024x768      60.00  &#xD;&#xA;       800x600       60.32  &#xD;&#xA;       640x480       59.94  &#xD;&#xA;    DVI-D-0 disconnected (normal left inverted right x axis y axis)&#xD;&#xA;    HDMI-0 disconnected (normal left inverted right x axis y axis)&#xD;&#xA;&#xD;&#xA;* Note that I verified and my monitor dimensions in mm are correct in the output of my `xrandr -q` command.&#xD;&#xA;&#xD;&#xA;I would suggest you look at how that `xrandr` tool does it and you'd get your info right at hand.&#xD;&#xA;&#xD;&#xA;From what I've read over the years, the VESA info can be wrong once in a while, but it's quite reliable now a day, I would think." ContentLicense="CC BY-SA 3.0" />
  <row Id="19485" PostHistoryTypeId="5" PostId="7535" RevisionGUID="d209318f-1cb4-4e5c-8f57-82c0e7918986" CreationDate="2018-04-20T16:53:12.957" UserId="8595" Comment="Added &quot;scanline rendering&quot; and GPU/matrix handling." Text="OpenGL (scanline rendering) is always going to be way faster than ray tracing.&#xD;&#xA;&#xD;&#xA;Ray tracing computes pixels one by one using physics (at least a good 90% of the time it's going to be real physics). Although some of it can now be done with a GPU, it is not really helping as much as one would expect. Calculating speculative lightning is not something you can easily do in parallel (ray 1 will bounce from object A to object B, ray 2 will bounce from object A to object C... you can't parallelize the computations on B and C.) The GPU helps with the matrix math, though.&#xD;&#xA;&#xD;&#xA;In comparison, OpenGL is a total fake in comparison. It renders triangles really fast with shades coming from textures and fast gradient computations from your various light sources." ContentLicense="CC BY-SA 3.0" />
  <row Id="19486" PostHistoryTypeId="2" PostId="7536" RevisionGUID="cedae256-2302-46cf-9994-0a385e02d485" CreationDate="2018-04-20T18:27:16.967" UserId="8595" Text="From what I'm reading, it looks like a ray tracer views a pixel as one color and computes that color using the ray starting in the center of that pixel. Yet a pixel has a width and a height.&#xD;&#xA;&#xD;&#xA;Do we ever use the actual square (now a day pixels are considered squares) that the pixel represents to calculate it true color from all possible source within that entire square?&#xD;&#xA;&#xD;&#xA;I am thinking that this is how we come up with colors on edges of shapes in scanline rendering and was wondering whether the same could be applied to ray tracing.&#xD;&#xA;&#xD;&#xA;There is a picture which I hope better represents what I am trying to ask here. Should we only consider the pixels to be single points? Or are we to consider pixels as _large_ areas?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CV39G.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19487" PostHistoryTypeId="1" PostId="7536" RevisionGUID="cedae256-2302-46cf-9994-0a385e02d485" CreationDate="2018-04-20T18:27:16.967" UserId="8595" Text="Do we ever consider the size of the pixel to calculate the color in Ray Tracing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19488" PostHistoryTypeId="3" PostId="7536" RevisionGUID="cedae256-2302-46cf-9994-0a385e02d485" CreationDate="2018-04-20T18:27:16.967" UserId="8595" Text="|raytracing|pixels|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19489" PostHistoryTypeId="2" PostId="7537" RevisionGUID="4c488719-478d-4add-a4ba-e4216d84ccd8" CreationDate="2018-04-21T08:50:52.313" UserId="2041" Text="Yes, and there are several ways this can apply. First off though, we need to fix a misconception in your diagram. Even if pixels really were square, the volume contributing to the pixel gets wider as it gets further away from the image plane, because of perspective. For a square pixel, the volume would be a square pyramid, whose apex is at the camera. It's not quite a *regular* square pyramid, because the apex is not in the centre of the square: the outer pixels are very skewed. But pixels aren't square anyway, they're cone-shaped.&#xD;&#xA;&#xD;&#xA;First off, some people have experimented with *cone tracing*, where instead of a single ray, you trace a cone with a half-angle determined from the area of the image covered. It's not very popular, because when the cone intersects the edge of a polygon, you need special handling for the remainder of the cone - the part that wasn't blocked by the polygon. For a square pyramid, it's a little easier, because you can change the shape of the base as parts of the pyramid are blocked, but it's still tricky and slow.&#xD;&#xA;&#xD;&#xA;You also don't gain much from this technique compared to just *supersampling*. Even if you trace rays, you don't just trace a single ray through the centre of each pixel. You trace many rays across the area of the pixel, and use a *reconstruction filter* to take the shape of the pixel into account. This technique has many possibilities that cone tracing doesn't offer: it works better with volumes, you can jitter your samples to avoid structured artefacts, you can use full path-tracing techniques, etc.&#xD;&#xA;&#xD;&#xA;Another area where the pixel size matters is in texture sampling. If you want to get nice texturing, you don't just take a point sample of the texture, you set some *filter width* according to the area of the texture the sample relates to. This doesn't just make your sampling more efficient by using the right mipmap level: it is required for correct sampling to avoid sampling artefacts. In a GPU fragment shader, you might use the `dFdx` and `dFdy` functions to do this. In a ray-tracer, you might have use a cone-tracing style of carrying the filter width with the ray, initially based on the level of supersampling at the camera, but updated whenever a child ray is spawned." ContentLicense="CC BY-SA 3.0" />
  <row Id="19490" PostHistoryTypeId="50" PostId="6422" RevisionGUID="a7852653-c0f7-4eb3-ad01-f37769fc4cee" CreationDate="2018-04-21T13:25:54.630" UserId="-1" />
  <row Id="19491" PostHistoryTypeId="2" PostId="7538" RevisionGUID="a8543b21-fa95-4b5b-b200-5cad5c14bfb6" CreationDate="2018-04-21T13:57:37.907" UserId="3123" Text="I'm implementing [Real-Time Polygonal-Light Shading with Linearly Transformed Cosines][1] from Siggraph 2016.&#xD;&#xA;&#xD;&#xA;I'm stuck on the texture prefiltering (section **5.3**).&#xD;&#xA;&#xD;&#xA;As I understand they use `Gaussian Blur` on the texture, but clamp and normalize kernel to fragments that intersect the original texture.&#xD;&#xA;&#xD;&#xA;But how do they create the margin? I have tried proper Gaussian with 2D kernel and 2 pass Gaussian but neither seems similar to what is in the paper.&#xD;&#xA;&#xD;&#xA;Also how should weight of Gaussian be chosen? &#xD;&#xA;&#xD;&#xA;Or maybe I'm totally wrong and it is something more than simple Gaussian?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://drive.google.com/file/d/0BzvWIdpUpRx_d09ndGVjNVJzZjA/view" ContentLicense="CC BY-SA 3.0" />
  <row Id="19492" PostHistoryTypeId="1" PostId="7538" RevisionGUID="a8543b21-fa95-4b5b-b200-5cad5c14bfb6" CreationDate="2018-04-21T13:57:37.907" UserId="3123" Text="Texture prefiltering for Linearly Transformed Cosines" ContentLicense="CC BY-SA 3.0" />
  <row Id="19493" PostHistoryTypeId="3" PostId="7538" RevisionGUID="a8543b21-fa95-4b5b-b200-5cad5c14bfb6" CreationDate="2018-04-21T13:57:37.907" UserId="3123" Text="|texture|pbr|filtering|gaussian-blur|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19494" PostHistoryTypeId="2" PostId="7539" RevisionGUID="375a0192-d74d-47cd-ae65-1e07b3f2bc9a" CreationDate="2018-04-21T19:55:59.817" UserId="56" Text="Bilinear interpolation can be achieved by interpolating two values across the x axis, and then interpolating between the results across the y axis, like in the image below (from https://blog.demofox.org/2015/04/30/bilinear-filtering-bilinear-interpolation/)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;A way to write this mathematically is like this:&#xD;&#xA;&#xD;&#xA;$x,y,P_{xy} \in \mathbb{R}$&#xD;&#xA;&#xD;&#xA;$x,y \in [0,1]$&#xD;&#xA;&#xD;&#xA;$z = (P_{00}(1-x) + P_{10}x)(1-y) + (P_{01}(1-x)+P_{11}x)y$&#xD;&#xA;&#xD;&#xA;Doing some algebra, you can get it into a polynomial form:&#xD;&#xA;&#xD;&#xA;$z = (P_{00}-P_{10}-P_{01}+P_{11})xy + (P_{10}-P_{00})x + (P_{01}-P_{00})y + P_{00}$&#xD;&#xA;&#xD;&#xA;I'm trying to find the (geometric?) intuition for this form of bilinear interpolation but the first term doesn't make much sense to me.&#xD;&#xA;&#xD;&#xA;The second term makes some sense because it's saying &quot;add in the difference across the x axis, multiplied by how far you are down the x axis&quot;.  The third term is the same, but for the y axis.&#xD;&#xA;&#xD;&#xA;The last term is just adding the value at the &quot;starting coordinate&quot; that everything else adds to, so that makes sense as well.&#xD;&#xA;&#xD;&#xA;I can't figure out how that first term fits in though, or what exactly it's calculating.  it is the only term that deals with the $P_{11}$ so it is obviously doesn't something meaningful, but I can't quite figure out what it is.&#xD;&#xA;&#xD;&#xA;Can anyone explain bilinear interpolation from this point of view?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lTXtu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19495" PostHistoryTypeId="1" PostId="7539" RevisionGUID="375a0192-d74d-47cd-ae65-1e07b3f2bc9a" CreationDate="2018-04-21T19:55:59.817" UserId="56" Text="Geometric interpretation of this bilinear interpolation equation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19496" PostHistoryTypeId="3" PostId="7539" RevisionGUID="375a0192-d74d-47cd-ae65-1e07b3f2bc9a" CreationDate="2018-04-21T19:55:59.817" UserId="56" Text="|mathematics|interpolation|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19497" PostHistoryTypeId="2" PostId="7540" RevisionGUID="d241da70-bfe6-401b-9407-f06cc1284e31" CreationDate="2018-04-21T20:36:06.580" UserId="286" Text="If we look at the two terms with only x or only y they fully describe what happens when you go right or down from the starting point (assuming P00 in upper-left corner, otheriwse right or up if P00 in lower-left corner).&#xD;&#xA;&#xD;&#xA;The xy-terms does not come into play at all.&#xD;&#xA;&#xD;&#xA;When you want to go &quot;into the square&quot; or along the lower-right (or upper-right depending on where P00 is) then it feels like the xy-term comes into play. It cancels out the x/y-terms and introduce the P11-value that it should obtain in lower-right (or upper-right).&#xD;&#xA;&#xD;&#xA;No full explanation here, just nudging along towards insight!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19498" PostHistoryTypeId="5" PostId="7540" RevisionGUID="a912b84c-63c4-4d64-bc5d-e79f0e437925" CreationDate="2018-04-21T20:44:33.680" UserId="286" Comment="Figure showed that P00 was in lower-left so I made my answer more clear." Text="If we look at the two terms with only x or only y they fully describe what happens when you go right or up from the starting point.&#xD;&#xA;&#xD;&#xA;The xy-terms does not come into play at all.&#xD;&#xA;&#xD;&#xA;When you want to go &quot;into the square&quot; or along the upper-right then the xy-term comes into play. It cancels out the x/y-terms and introduce the P11-value that it should obtain in upper-right.&#xD;&#xA;&#xD;&#xA;No full explanation here, just nudging along towards insight!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19499" PostHistoryTypeId="5" PostId="7540" RevisionGUID="e633ad41-13c1-4f4f-9612-abf3f62046d1" CreationDate="2018-04-21T21:01:05.637" UserId="286" Comment="Clarify." Text="If we look at the two terms with only x or only y they fully describe what happens when you go right or up from the starting point.&#xD;&#xA;&#xD;&#xA;The xy-terms does not come into play at all.&#xD;&#xA;&#xD;&#xA;When you want to go &quot;into the square&quot; or along the upper or the right edge then the xy-term comes into play. It cancels out the x/y-terms and introduce the P11-value that it should obtain in upper-right.&#xD;&#xA;&#xD;&#xA;No full explanation here, just nudging along towards insight!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19500" PostHistoryTypeId="5" PostId="7539" RevisionGUID="6de1c628-1f43-49cb-93eb-4ffced39b974" CreationDate="2018-04-21T21:29:54.220" UserId="56" Comment="helping clarify the meaning of the points" Text="Bilinear interpolation can be achieved by interpolating two values across the x axis, and then interpolating between the results across the y axis, like in the image below (from https://blog.demofox.org/2015/04/30/bilinear-filtering-bilinear-interpolation/)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;A way to write this mathematically is like this:&#xD;&#xA;&#xD;&#xA;$x,y,P_{xy} \in \mathbb{R}$&#xD;&#xA;&#xD;&#xA;$x,y \in [0,1]$&#xD;&#xA;&#xD;&#xA;$z = (P_{00}(1-x) + P_{10}x)(1-y) + (P_{01}(1-x)+P_{11}x)y$&#xD;&#xA;&#xD;&#xA;Doing some algebra, you can get it into a polynomial form:&#xD;&#xA;&#xD;&#xA;$z = (P_{00}-P_{10}-P_{01}+P_{11})xy + (P_{10}-P_{00})x + (P_{01}-P_{00})y + P_{00}$&#xD;&#xA;&#xD;&#xA;I'm trying to find the (geometric?) intuition for this form of bilinear interpolation but the first term doesn't make much sense to me.&#xD;&#xA;&#xD;&#xA;The second term makes some sense because it's saying &quot;add in the difference across the x axis, multiplied by how far you are down the x axis&quot;.  The third term is the same, but for the y axis.&#xD;&#xA;&#xD;&#xA;The last term is just adding the value at the &quot;starting coordinate&quot; that everything else adds to, so that makes sense as well.&#xD;&#xA;&#xD;&#xA;I can't figure out how that first term fits in though, or what exactly it's calculating.  it is the only term that deals with the $P_{11}$ so it is obviously doesn't something meaningful, but I can't quite figure out what it is.&#xD;&#xA;&#xD;&#xA;Can anyone explain bilinear interpolation from this point of view?&#xD;&#xA;&#xD;&#xA;Note: $P_{00}$ is (0,0), $P_{01}$ is (0,1), $P_{10}$ is (1,0) and $P_{11}$ is (1,1).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lTXtu.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19501" PostHistoryTypeId="2" PostId="7541" RevisionGUID="cbd888d7-3e45-4c0f-aed5-8b7f7f5ddaf3" CreationDate="2018-04-21T21:47:55.373" UserId="56" Text="An answer was provided to me via twitter by two people independently.&#xD;&#xA;&#xD;&#xA; 1. https://twitter.com/nothings/status/987797966789341184&#xD;&#xA; 2. https://twitter.com/DarrenMoo/status/987796950274764802&#xD;&#xA;&#xD;&#xA;The intuition is that without the xy term, that equation describes a plane defined by the 3 points involved (all points except $P_{11}$).&#xD;&#xA;&#xD;&#xA;The xy term is there to correct it to be a bilinear surface, which is defined additionally by the point $P_{11}$." ContentLicense="CC BY-SA 3.0" />
  <row Id="19502" PostHistoryTypeId="2" PostId="7542" RevisionGUID="ddd59b4a-b93d-40e7-a749-bb05837ae97f" CreationDate="2018-04-22T10:02:51.093" UserId="7334" Text="I've been thinking about this question for a quite long time.And my implementation seems to be correct for some cases but wrong with few others.&#xD;&#xA;&#xD;&#xA;How can I comprehensive test the algorithm? Is there any provided test cases?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19503" PostHistoryTypeId="1" PostId="7542" RevisionGUID="ddd59b4a-b93d-40e7-a749-bb05837ae97f" CreationDate="2018-04-22T10:02:51.093" UserId="7334" Text="How to test my triangle intersection implementation?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19504" PostHistoryTypeId="3" PostId="7542" RevisionGUID="ddd59b4a-b93d-40e7-a749-bb05837ae97f" CreationDate="2018-04-22T10:02:51.093" UserId="7334" Text="|raytracing|algorithm|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19505" PostHistoryTypeId="5" PostId="5746" RevisionGUID="5bd3fb8f-b949-4762-92c1-356219fd0b4b" CreationDate="2018-04-22T12:10:12.527" UserDisplayName="user7220" Comment="Corrected indents.." Text="**Perspective Camera**&#xD;&#xA;&#xD;&#xA;A (row-major) perspective transformation matrix has the following format:&#xD;&#xA;&#xD;&#xA;$$\begin{align} \mathrm{T} &#xD;&#xA;&amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;1 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;0 \end{bmatrix}=\begin{bmatrix} 1/x &amp;0 &amp;0 &amp;0 \\ 0 &amp;1/y &amp;0 &amp;0 \\ 0 &amp;0 &amp;-w &amp;1 \\ 0 &amp;0 &amp;z &amp;0\end{bmatrix}. &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;This transformation matrix is used to transform (*homogeneous*) points from view to projection space, after which the homogeneous divide is applied to transform to NDC (Normalized Device Coordinate) space. (*NDC space is technically a 3D space, but for ease of notation, I use 4D points with a $w=1$*).&#xD;&#xA;&#xD;&#xA;In a deferred renderer, we need to go the other way around while resolving the GBuffer and could use four components ($x$, $y$, $z$, $w$, see above) to transform a point from NDC to view space:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;     Returns the projection values from the given projection matrix to construct&#xD;&#xA;     the view position coordinates from the NDC position coordinates.&#xD;&#xA;&#xD;&#xA;     @return    The projection values from the given projection matrix to&#xD;&#xA;                construct the view position coordinates from the NDC position&#xD;&#xA;                coordinates.&#xD;&#xA;     */&#xD;&#xA;    inline const XMVECTOR XM_CALLCONV GetViewPositionConstructionValues(&#xD;&#xA;        FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;        //        [ 1/X  0   0  0 ]&#xD;&#xA;        // p_view [  0  1/Y  0  0 ] = [p_view.x 1/X, p_view.y 1/Y, p_view.z (-W) + Z, p_view.z] = p_proj&#xD;&#xA;        //        [  0   0  -W  1 ]&#xD;&#xA;        //        [  0   0   Z  0 ]&#xD;&#xA;        //&#xD;&#xA;        // p_proj / p_proj.w        = [p_view.x/p_view.z 1/X, p_view.y/p_view.z 1/Y, -W + Z/p_view.z, 1] = p_ndc&#xD;&#xA;        //&#xD;&#xA;        // Construction of p_view from p_ndc and projection values&#xD;&#xA;        // 1) p_ndc.z = -W + Z/p_view.z       &lt;=&gt; p_view.z = Z / (p_ndc.z + W)&#xD;&#xA;        // 2) p_ndc.x = p_view.x/p_view.z 1/X &lt;=&gt; p_view.x = X * p_ndc.x * p_view.z&#xD;&#xA;        // 3) p_ndc.y = p_view.y/p_view.z 1/Y &lt;=&gt; p_view.y = Y * p_ndc.y * p_view.z&#xD;&#xA;&#xD;&#xA;        const F32 x = 1.0f / XMVectorGetX(projection_matrix.r[0]);&#xD;&#xA;        const F32 y = 1.0f / XMVectorGetY(projection_matrix.r[1]);&#xD;&#xA;        const F32 z = XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;        const F32 w = -XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;&#xD;&#xA;        return XMVectorSet(x, y, z, w);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Orthographic Camera**&#xD;&#xA;&#xD;&#xA;An (row-major) orthographic transformation matrix has the following format:&#xD;&#xA;&#xD;&#xA;$$\begin{align} \mathrm{T} &#xD;&#xA;&amp;= \begin{bmatrix} &#xD;&#xA;\mathrm{T}_{00} &amp;0 &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;\mathrm{T}_{11} &amp;0 &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{22} &amp;0 \\ &#xD;&#xA;0 &amp;0 &amp;\mathrm{T}_{32} &amp;1 \end{bmatrix}=\begin{bmatrix} 1/x &amp;0 &amp;0 &amp;0 \\ 0 &amp;1/y &amp;0 &amp;0 \\ 0 &amp;0 &amp;1/z &amp;0 \\ 0 &amp;0 &amp;-w &amp;1\end{bmatrix}. &#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;This transformation matrix is used to transform (*homogeneous*) points from view to projection space, after which the homogeneous divide (no-op) is applied to transform to NDC (= projection) space. (*So basically a non-uniform scaling followed by a translation of the z component*).&#xD;&#xA;&#xD;&#xA;We could similarly use four components ($x$, $y$, $z$, $w$, see above) to transform a point from NDC (= projection) to view space:&#xD;&#xA;&#xD;&#xA;    /**&#xD;&#xA;	 Returns the projection values from the given projection matrix to construct &#xD;&#xA;	 the view position coordinates from the NDC position coordinates.&#xD;&#xA;	 &#xD;&#xA;     @return		The projection values from the given projection matrix to &#xD;&#xA;					construct the view position coordinates from the NDC position &#xD;&#xA;					coordinates.&#xD;&#xA;	 */&#xD;&#xA;	inline const XMVECTOR XM_CALLCONV GetViewPositionConstructionValues(&#xD;&#xA;		FXMMATRIX projection_matrix) noexcept {&#xD;&#xA;		&#xD;&#xA;		//        [ 1/X  0   0  0 ]&#xD;&#xA;		// p_view [  0  1/Y  0  0 ] = [p_view.x 1/X, p_view.y 1/Y, p_view.z 1/Z -W, 1] = p_proj = p_ndc&#xD;&#xA;		//        [  0   0  1/Z 0 ]&#xD;&#xA;		//        [  0   0  -W  1 ]&#xD;&#xA;		//&#xD;&#xA;		// Construction of p_view from p_ndc and projection values&#xD;&#xA;		// 1) p_ndc.z = p_view.z/Z -W &lt;=&gt; p_view.z = Z * (p_ndc.z + W)&#xD;&#xA;		// 2) p_ndc.x = p_view.x/X    &lt;=&gt; p_view.x = X * p_ndc.x&#xD;&#xA;		// 3) p_ndc.y = p_view.y/Y    &lt;=&gt; p_view.y = Y * p_ndc.y&#xD;&#xA;&#xD;&#xA;		const F32 x = 1.0f / XMVectorGetX(projection_matrix.r[0]);&#xD;&#xA;		const F32 y = 1.0f / XMVectorGetY(projection_matrix.r[1]);&#xD;&#xA;		const F32 z = 1.0f / XMVectorGetZ(projection_matrix.r[2]);&#xD;&#xA;		const F32 w = -XMVectorGetZ(projection_matrix.r[3]);&#xD;&#xA;		&#xD;&#xA;		return XMVectorSet(x, y, z, w);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;How can a deferred renderer support multiple camera types (minimally: perspective and orthographic cameras, ideally: all cameras that a forward renderer could support) without specializing the shaders or specializing in the shaders?&#xD;&#xA;&#xD;&#xA;A straightforward solution is to specify some pre-processor directive in the shader, but this unfortunately results in a multiple of all the shader perturbations used so far for lighting in a deferred pipeline. Another solution is to pass a flag in some constant buffer to specify the used camera type, though I am not a fan of the dynamic branching introduced by this flag. Furthermore, both solutions are not as flexible as is the case for forward rendering which can handle arbitrary view-to-projection matrices.&#xD;&#xA;&#xD;&#xA;Ideally, a (hypothetical) NDC-to-view transformation matrix should handle the transformation. Such a matrix does, however, not generally exist for perspective cameras since the view to NDC transformation reduces a 4D space to a 3D subspace." ContentLicense="CC BY-SA 3.0" />
  <row Id="19506" PostHistoryTypeId="24" PostId="5746" RevisionGUID="5bd3fb8f-b949-4762-92c1-356219fd0b4b" CreationDate="2018-04-22T12:10:12.527" Comment="Proposed by 7220 approved by 2287 edit id of 399" ContentLicense="CC BY-SA 3.0" />
  <row Id="19510" PostHistoryTypeId="5" PostId="5409" RevisionGUID="90a4eaef-91b4-4226-8422-4678b34e8290" CreationDate="2018-04-22T12:56:38.213" UserDisplayName="user7220" Comment="adjusted indents.." Text="I am trying to implement Beer's law according to [this][1] page in dielectric material but I am not sure have done it correctly as the image does not suggest so.&#xD;&#xA;&#xD;&#xA;The formula is: I(s) = I(0) * pow(e, ln(A)*s)&#xD;&#xA;&#xD;&#xA;'A' is said to be transmission coefficient which I am not clear what this is&#xD;&#xA;and what value I should use for it.&#xD;&#xA;&#xD;&#xA;Below is the code and the image. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Could anyone shed some light if I have gone wrong. Thanks.&#xD;&#xA;&#xD;&#xA;    public override LightVector SampleBrdf(ISect isect, Random rand,&#xD;&#xA;            out LightVector woW, out double pdfDir, out double cosWo)&#xD;&#xA;    {&#xD;&#xA;        woW = LightVector.ZERO;&#xD;&#xA;        cosWo = 0;&#xD;&#xA;        LightVector n = isect.Thing.Normal;&#xD;&#xA;        LightVector tan = isect.Thing.Edge1;&#xD;&#xA;        tan.Normalize();&#xD;&#xA;        LightVector ts = n.Cross(tan);&#xD;&#xA;&#xD;&#xA;        //set wo to be incoming dir&#xD;&#xA;        LightVector wo = MaterialHelper.WorldToLocal(-isect.Ray.Dir, tan, ts, n);dir&#xD;&#xA;        LightVector refracted = LightVector.ZERO;&#xD;&#xA;        LightVector reflected = new LightVector(-wo.X, -wo.Y, wo.Z);&#xD;&#xA;&#xD;&#xA;        double F = Fresnel.Evaluate(rindex1, rindex2, MaterialHelper.CosTheta(wo));&#xD;&#xA;        pdfDir = F;&#xD;&#xA;&#xD;&#xA;        //Figure out which eta is incident and which is transmitted&#xD;&#xA;        double extCoeff = 1;&#xD;&#xA;        double etaI = rindex1;&#xD;&#xA;        double etaT = rindex2;&#xD;&#xA;        LightVector z = new LightVector(0, 0, 1);&#xD;&#xA;        if (MaterialHelper.CosTheta(wo) &lt; 0)//existing&#xD;&#xA;        {&#xD;&#xA;            etaI = rindex2;&#xD;&#xA;            etaT = rindex1;&#xD;&#xA;            z = -z;&#xD;&#xA;            extCoeff = Math.Exp(-Math.Log(A, Math.E) * isect.Dist);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        //Compute ray direction for specular transmission&#xD;&#xA;        if (!MaterialHelper.Refract(wo, z, etaI / etaT, out refracted))&#xD;&#xA;            pdfDir = 1;&#xD;&#xA;&#xD;&#xA;        if (rand.NextDouble() &lt; pdfDir)&#xD;&#xA;        {&#xD;&#xA;            woW = MaterialHelper.LocalToWorld(reflected, tan, ts, n);&#xD;&#xA;            cosWo = MaterialHelper.AbsCosTheta(reflected);&#xD;&#xA;&#xD;&#xA;            return R * (F / cosWo);&#xD;&#xA;        }&#xD;&#xA;        else //refracted&#xD;&#xA;        {&#xD;&#xA;            woW = MaterialHelper.LocalToWorld(refracted, tan, ts, n);&#xD;&#xA;            cosWo = MaterialHelper.AbsCosTheta(refracted);&#xD;&#xA;            pdfDir = 1d - F;&#xD;&#xA;&#xD;&#xA;            return T * (extCoeff * (1d - F) / cosWo);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.eng.utah.edu/~cs6620/beers.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/4jgjp.png&#xD;&#xA;&#xD;&#xA;**Update:**&#xD;&#xA;&#xD;&#xA;I was expecting to see the reflection of the light source at the ceiling on the glass. But it was my mistake in the caller method where the specular bounce contribution was dismissed. &#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 3.0" />
  <row Id="19511" PostHistoryTypeId="24" PostId="5409" RevisionGUID="90a4eaef-91b4-4226-8422-4678b34e8290" CreationDate="2018-04-22T12:56:38.213" Comment="Proposed by 7220 approved by 209, 5717 edit id of 398" ContentLicense="CC BY-SA 3.0" />
  <row Id="19515" PostHistoryTypeId="5" PostId="5140" RevisionGUID="5947523c-d09e-41f3-8a4a-37cf4eabab59" CreationDate="2018-04-22T21:30:20.847" UserDisplayName="user7220" Comment="Corrected links.." Text="I'm currently working on a project where a 3D model gets computed through&#xD;&#xA;an isosurface algorithm. This algorithm outputs single triangles&#xD;&#xA;with vertices and normals, but without indices. So therefore I have&#xD;&#xA;a lot of duplicates which can't be avoided, because of a software&#xD;&#xA;restriction.&#xD;&#xA;&#xD;&#xA;I was asked to write smooth lighting for this model, by sending the proper normals to the visualisation software, which uses OpenGL and runs under Windows. What I tried was to set the normals for duplicated vertices to the same direction but this also results in unsmoothed lighting &#xD;&#xA;&#xD;&#xA;as visible here:&#xD;&#xA;&#xD;&#xA;[![https://i.stack.imgur.com/G8X14.jpg][1]][2] &#xD;&#xA;&#xD;&#xA;Is it possible to have smooth Gouraud shading on a 3D Model&#xD;&#xA;which consists of many single unconnected triangles?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LMQdI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/G8X14.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="19516" PostHistoryTypeId="24" PostId="5140" RevisionGUID="5947523c-d09e-41f3-8a4a-37cf4eabab59" CreationDate="2018-04-22T21:30:20.847" Comment="Proposed by 7220 approved by 2041 edit id of 401" ContentLicense="CC BY-SA 3.0" />
  <row Id="19517" PostHistoryTypeId="5" PostId="5831" RevisionGUID="bfbda7f6-e59e-4708-99b3-212afea0bcf7" CreationDate="2018-04-22T21:30:31.597" UserDisplayName="user7220" Comment="Corrected indents.." Text="How can I find the vertices of a polygon (specifically hexagon) given the radius of the incircle? I want to calculate the vertices of a polygon given the face-to-face distance (inscribed circle diameter?)&#xD;&#xA;&#xD;&#xA;I've below code to calculate the vertices from the Circum-circle of a polygon&#xD;&#xA;&#xD;&#xA;`(x,y)` - Center of the circumcircle&#xD;&#xA;&#xD;&#xA;`r` - Radius of the circumcircle&#xD;&#xA;&#xD;&#xA;    for (var i = 1; i &lt;= sides; i++)&#xD;&#xA;    {&#xD;&#xA;        var X = x + r * Math.Cos(2 * Math.PI * i / sides);&#xD;&#xA;        var Y = y + r * Math.Sin(2 * Math.PI * i / sides);&#xD;&#xA;&#xD;&#xA;        vertices.Add(new Tuple(X,Y));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Alternatively, what is the relation between radius of the in-circle and circum-circle of a polygon? Could you please share a relevant resource or a code snippet (any language is fine).&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 3.0" />
  <row Id="19518" PostHistoryTypeId="24" PostId="5831" RevisionGUID="bfbda7f6-e59e-4708-99b3-212afea0bcf7" CreationDate="2018-04-22T21:30:31.597" Comment="Proposed by 7220 approved by 5717, 2041 edit id of 400" ContentLicense="CC BY-SA 3.0" />
  <row Id="19519" PostHistoryTypeId="5" PostId="3953" RevisionGUID="868f530a-1419-4f08-8750-29ee2ae15590" CreationDate="2018-04-23T07:46:41.127" UserId="209" Comment="added 13 characters in body" Text="Rather than trying to speed up your shader by fiddling with the code, can I suggest you make use of the GPU's inherent ability to rapidly fill polygons? This will allow it to eliminate the vast bulk of the cases where there is no need to even make a decision.&#xD;&#xA;&#xD;&#xA;What I suggest you try is _something_ like the following: Create, say, a heptagon (i.e. the blue dashed outline (*note: it shares some of the boundary with the green but I just noticed this is not particularly obvious in the diagram*)) that starts from the original location and extends to the new position but lies inside the extremes of the new location's circle. &#xD;&#xA;The shader for this is then utterly trivial.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Then there can be one or two cases depending on how much you want to optimise. If the tail extends outside of the end position circle, you draw the green-dashed nonagon with your decision-based shader. This contains vastly fewer pixels. &#xD;&#xA;If the tail doesn't extend outside, then you'll need to mirror this polygon to get the other side of the circle. Alternatively, rather than make the decision, you could always mirror it and let the Z-test eliminate unneeded fills.&#xD;&#xA;&#xD;&#xA;Your examples also have the have the capsules shown as opaque. If this is the case, you can also make gains with, say, TBDR-systems (a blatant PowerVR plug :-) ) or those with early-Z, provided you supply all your opaque &quot;tail&quot; portions first and then follow with all parts requiring decisions.&#xD;&#xA;&#xD;&#xA;The shapes of course were just examples. You may find it's better to use more segments in your outlines in order to reduce the regions requiring the complex shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UXeIn.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19520" PostHistoryTypeId="5" PostId="1551" RevisionGUID="0d0bd123-6d8c-4f37-b991-a9767d400376" CreationDate="2018-04-23T07:55:03.983" UserId="209" Comment="Noticed missing &quot;or&quot; in the S3TC section" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over three decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  A problem with palette textures is that the compression rates for the achieved quality is generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2bpp ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4bpp, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This paper also included a compression algorithm but, for our purposes, we are mainly interested in the resulting compressed data and of the decompression process.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4bpp RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses blocks of either RGB or RGB+1bit Alpha to 4bpp. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts may go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4bpp RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 bpp RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4bpp produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2bpp variant has, naturally, higher error than the 4bpp (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4bpp ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of bpp. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="19524" PostHistoryTypeId="5" PostId="4939" RevisionGUID="c87263f5-0fd3-4461-a1c0-468aa0059f18" CreationDate="2018-04-23T14:06:15.633" UserId="6255" Comment="added 8 characters in body" Text="Silly me, posting all of this hoping to get someone to solve it for me, I managed to find the solution tho, but perhaps more as a result of trial and error, than of actual understanding. Either way, this is the object I'm looking at now:&#xD;&#xA;&#xD;&#xA;[![UV ordering, transpose and crossing in the wrong order][1]][1]&#xD;&#xA;&#xD;&#xA;Looking at my current tangent calculation:&#xD;&#xA;&#xD;&#xA;    vector&lt;vec4&gt;tangentref(texkoordref.size()); //math UV size, w=amount for divide&#xD;&#xA;	vec3 tangentbuf;&#xD;&#xA;&#xD;&#xA;	float f;&#xD;&#xA;	vec3 edge1, edge2;&#xD;&#xA;	vec2 deltaUV1, deltaUV2;&#xD;&#xA;	for (size_t i = 0; i &lt; totalrefs.size(); i += 9)&#xD;&#xA;	{&#xD;&#xA;		//i=vert, i+1=uv, i+2 vn//i+3=vert2,i+4=uv2,i+5=vn2;//i+6=vert3, i+7=uv3, i+8=vn3;&#xD;&#xA;		//get the tangent for each face&#xD;&#xA;		edge1 = verticeref[totalrefs[i + 3] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		edge2 = verticeref[totalrefs[i + 6] - 1] - verticeref[totalrefs[i] - 1];&#xD;&#xA;		deltaUV1 = texkoordref[totalrefs[i + 4] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		deltaUV2 = texkoordref[totalrefs[i + 7] - 1] - texkoordref[totalrefs[i + 1] - 1];&#xD;&#xA;		f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;		tangentbuf = f*vec3(&#xD;&#xA;			(deltaUV2.y * edge1.x - deltaUV1.y * edge2.x),&#xD;&#xA;			(deltaUV2.y * edge1.y - deltaUV1.y * edge2.y),&#xD;&#xA;			(deltaUV2.y * edge1.z - deltaUV1.y * edge2.z));&#xD;&#xA;&#xD;&#xA;		//one tangent per uv coordinate&#xD;&#xA;		tangentref[totalrefs[i+1] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 4] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;		tangentref[totalrefs[i + 7] - 1] += vec4(normalize(tangentbuf), 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	for (auto &amp;x : tangentref)x = normalize(x / x.w); //find average&#xD;&#xA;    //some tutorials say to just normalize these&#xD;&#xA;&#xD;&#xA;I cycle through every face, and totalref[i], is here 9 integers per cycle, that each refer to +0=vert, +1=uv, and +2=vert normal. By populating the tangentref according to each of the UVs, I get a list of tangents that go along with the UV values.&#xD;&#xA;&#xD;&#xA;I think its worth mentioning specifically, the tangents describe not the normal, or the vertex, but the direction of the uv, together with the bitangent, they make out an xy coordinate that describes the UV direction.&#xD;&#xA;&#xD;&#xA;It only makes sense to make tangents according to UVs, and the results are not disagreeing.&#xD;&#xA;&#xD;&#xA;Secondly, I was building the tbn matrix incorrectly.&#xD;&#xA;    &#xD;&#xA;    //in the vert shader&#xD;&#xA;    vec3 bitangent = normalize( cross( n, t ) );&#xD;&#xA;&#xD;&#xA;The bitangent was in the wrong order, and&#xD;&#xA;&#xD;&#xA;    mat3 tbn = transpose(mat3(t,bitangent,n)); //why transpose??&#xD;&#xA;&#xD;&#xA;The tbn was supposed to be transpose. Transpose is cheap (apparently) so thats not a problem, but why exactly this is correct? I'm not sure.&#xD;&#xA;&#xD;&#xA;It works (better) however, so maybe It will make sense later.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cN0vN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FVeYM.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19525" PostHistoryTypeId="50" PostId="6323" RevisionGUID="6b05401c-9905-47b0-906b-65a9c78dfdaa" CreationDate="2018-04-23T22:55:45.283" UserId="-1" />
  <row Id="19526" PostHistoryTypeId="2" PostId="7546" RevisionGUID="56caa3d2-3c1a-4690-a964-0af600d84e9a" CreationDate="2018-04-24T03:52:28.990" UserId="6806" Text="The way of detecting intersection is two steps. (I referred to  http://www-bcf.usc.edu/~jbarbic/cs420-s18/runuscedu/cs420-s18/16-geometric-queries/16-geometric-queries-6up.pdf)&#xD;&#xA;&#xD;&#xA;1. Check intersection between the plane that includes the given triangle and given ray.&#xD;&#xA; &#xD;&#xA;Let's suppose the start point of the ray $R$ is $(x_0, y_0, z_0)$ and direction is $(x_d, y_d, z_d)$,  then $R = (x_0, y_0, z_0) + (x_d, y_d, z_d)t$ , and the plane is $ax + by + cz + d = 0$. &#xD;&#xA;&#xD;&#xA;To check intersection between the ray and plane, calculate the below equation.&#xD;&#xA;&#xD;&#xA;$t = \frac{-(ax_0 + by_0 + cz_0 + d)}{ax_d + by_d + cz+d}$&#xD;&#xA;&#xD;&#xA;If $t \ge 0$, then there is a possibility of intersection, so go second step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;else there is not intersection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;   2. Test the point inside triangle. &#xD;&#xA;&#xD;&#xA;Since $t \ge 0 $, we know the point on the plane.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hnece, we can get the $\alpha, \beta, \gamma$.&#xD;&#xA;&#xD;&#xA;If $0 \le\alpha, \beta, \gamma \le 1$ and $\alpha+ \beta + \gamma = 1$, then there is intersecton.&#xD;&#xA;&#xD;&#xA;else No intersection!.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;(The page 19, 20 is explaining how to calculate the 'Area'. (Actually, we can project the 3D space points to 2D space  for performance, but avoid the perpendicular projection!)  )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xikMu.jpg" ContentLicense="CC BY-SA 3.0" />
  <row Id="19527" PostHistoryTypeId="2" PostId="7547" RevisionGUID="7ea33c31-7363-464d-86ad-500e071e442f" CreationDate="2018-04-24T06:37:36.247" UserId="8532" Text="I fixed it, It was just a coding mistake, there was nothing wrong with the implementation. So the error was in fact in the 2nd for-loop when I was parsing the image buffer. I was reaching for the last pixel in the vector and then popping it off from the back of the stack. &#xD;&#xA;&#xD;&#xA;This means that in the for loop condition, the vector size will be changing but k will still be incrementing the same, so it will effectively only do half of the elements per vector. Because as K is incrementing stack.size() is decrementing so they meet in the middle and the loop is done.&#xD;&#xA;&#xD;&#xA;To fix this, I just used index notation, so:&#xD;&#xA;&#xD;&#xA;    rgbpacket &amp;rgbpixel = stack[index];&#xD;&#xA;&#xD;&#xA;and then I deleted the line where I was popping off from the stack.&#xD;&#xA;&#xD;&#xA;Even though this is a stupid bug,&#xD;&#xA;I hope this helps other people.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19528" PostHistoryTypeId="5" PostId="5730" RevisionGUID="525f4b42-f09c-4329-984a-f54af46eb8ec" CreationDate="2018-04-24T07:44:16.063" UserDisplayName="user7220" Comment="Corrected indents.." Text="I'm working with OpenGL to try to rotate / translate my 3d object : a cow.&#xD;&#xA;&#xD;&#xA;The requirement is simple : &#xD;&#xA;&#xD;&#xA;1. If I toggle key 'r'. The cow spinning around and random axis.&#xD;&#xA;2. If I drag the cow with mouse, it translate along its own x axis which means +x directions is for cow's head&#xD;&#xA;3. Rotation and translation need not execute at the same time.&#xD;&#xA;4. Rotation and translation is done is modeling space.&#xD;&#xA;&#xD;&#xA;To implement first requirement, I used timer function like this :&#xD;&#xA;&#xD;&#xA;    void rotateCow(int value) {&#xD;&#xA;    	//rotation ended&#xD;&#xA;    	if (!rotate_flag)&#xD;&#xA;    		return;&#xD;&#xA;    &#xD;&#xA;    	printf(&quot;rotateCow\n&quot;);&#xD;&#xA;    &#xD;&#xA;    	angle = (angle + 5) % 360;&#xD;&#xA;    	glutPostRedisplay();&#xD;&#xA;    	glutTimerFunc(30, rotateCow, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and for rotation and translation : &#xD;&#xA;(some of codes are skipped)&#xD;&#xA;&#xD;&#xA;    void dragCow() {&#xD;&#xA;        glPushMatrix();&#xD;&#xA;        //some codes are skipped..&#xD;&#xA;&#xD;&#xA;        //rotation start&#xD;&#xA;        if (rotate_flag == 1) {&#xD;&#xA;            rotate_flag = 2;&#xD;&#xA;            glutTimerFunc(30, rotateCow, 1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glTranslatef(trans_x, trans_y, trans_z);&#xD;&#xA;        glRotatef(angle, rotate_x, rotate_y, rotate_z);&#xD;&#xA;&#xD;&#xA;        glCallList( cowID ); // Draw cow.&#xD;&#xA;        glPopMatrix();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void onMouseDrag( int x, int y ) {&#xD;&#xA;        y = height - y - 1;&#xD;&#xA;        if (trans_flag == DIR_X) {&#xD;&#xA;            trans_x = ((x - oldX) / DRAG) + old_trans_x;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glutPostRedisplay();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I run as above(rotate and then translate) rotation is as expected.&#xD;&#xA;&#xD;&#xA;However, the translation is done in global x-axis not towards head direction of cow.&#xD;&#xA;&#xD;&#xA;If I change the order like this : &#xD;&#xA;&#xD;&#xA;    glRotatef(angle, rotate_x, rotate_y, rotate_z);&#xD;&#xA;    glTranslatef(trans_x, trans_y, trans_z);&#xD;&#xA;&#xD;&#xA;It shows that translation is as expected(towards head direction of cow).&#xD;&#xA;&#xD;&#xA;However, the rotations not works - the rotation-axis made on global x-axis and the cow revolve around that line.&#xD;&#xA;&#xD;&#xA;So how can I solve this problem??" ContentLicense="CC BY-SA 3.0" />
  <row Id="19529" PostHistoryTypeId="24" PostId="5730" RevisionGUID="525f4b42-f09c-4329-984a-f54af46eb8ec" CreationDate="2018-04-24T07:44:16.063" Comment="Proposed by 7220 approved by 48, 209 edit id of 403" ContentLicense="CC BY-SA 3.0" />
  <row Id="19530" PostHistoryTypeId="5" PostId="5228" RevisionGUID="a88e492d-3da1-4566-9e33-9ce685ee1fa0" CreationDate="2018-04-24T07:44:27.470" UserDisplayName="user7220" Comment="Corrected links.." Text="As promised but with apologies for the tardiness, here's a GREAT repository of detailed information for using OpenGL with VBA:&#xD;&#xA;&#xD;&#xA;[Découvrez la 3D OpenGL 1.1 en VB6/VBA | arkham46.developpez.com][1]&#xD;&#xA;&#xD;&#xA;It's in French, but translates beautifully. I wa able to get OpenGL up and running in less than 15 mins using this SUPERB tutorial.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://arkham46.developpez.com/articles/office/vbaopengl/?page=page_1" ContentLicense="CC BY-SA 3.0" />
  <row Id="19531" PostHistoryTypeId="24" PostId="5228" RevisionGUID="a88e492d-3da1-4566-9e33-9ce685ee1fa0" CreationDate="2018-04-24T07:44:27.470" Comment="Proposed by 7220 approved by 48, 209 edit id of 408" ContentLicense="CC BY-SA 3.0" />
  <row Id="19532" PostHistoryTypeId="5" PostId="4581" RevisionGUID="87f1001c-983a-4baf-adb2-5cbaabf776bf" CreationDate="2018-04-24T07:44:40.820" UserDisplayName="user7220" Comment="Corrected links.." Text="The triangle spans from one side of the sphere to the other so using straight line equations is very inaccurate.&#xD;&#xA;&#xD;&#xA;I think I can figure it out like so:&#xD;&#xA;&#xD;&#xA;The centroid of a triangle is where its medians intersect:&#xD;&#xA;&#xD;&#xA;[Median of a triangle - math word definition | Math Open Reference][1]&#xD;&#xA;&#xD;&#xA;So use the equations given elsewhere to find the shortest path between two points on a sphere for all the vertices, and get the intersection between two midpoints on those with the opposing vertices to get two curves along the sphere and their point intersection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathopenref.com/trianglemedians.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19533" PostHistoryTypeId="24" PostId="4581" RevisionGUID="87f1001c-983a-4baf-adb2-5cbaabf776bf" CreationDate="2018-04-24T07:44:40.820" Comment="Proposed by 7220 approved by 48, 209 edit id of 409" ContentLicense="CC BY-SA 3.0" />
  <row Id="19534" PostHistoryTypeId="5" PostId="2049" RevisionGUID="c8eb8316-7f86-4114-9acf-4dfe57913a0c" CreationDate="2018-04-24T07:44:55.540" UserDisplayName="user7220" Comment="Corrected links.." Text="I'm looking into the graphics pipeline processes and at the moment in particular, perspective projection matrices.&#xD;&#xA;&#xD;&#xA;After looking in several different sources, and across the breadth of previous questions such as [How does a projection Matrix work? | Stack Overflow][1], I've found that most solutions seem to use the following two matrices;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;    &#xD;&#xA;So far, I've been expecting these matrices to take the view frustum and convert it into a unit sized cube - however this doesn't seem to be happening.&#xD;&#xA;&#xD;&#xA;Taking the left matrix first (which I attempted to use first), I assumed the parameters were as such;&#xD;&#xA;&#xD;&#xA;n/f = **z** value of near and far planes&#xD;&#xA;&#xD;&#xA;r/l = **x** values of left and right planes&#xD;&#xA;&#xD;&#xA;t/b = **y** values of top and bottom planes&#xD;&#xA;&#xD;&#xA;For the right hand matrix, my book is very vague, and the only parameters that seem to fit are&#xD;&#xA;&#xD;&#xA;d/f - distances to near/far planes (but not necessarily the **z** values?)&#xD;&#xA;h - height of the near clip plane.&#xD;&#xA;&#xD;&#xA;My initial method of experimentation has been to plot the vertices of the frustum and using the transforms get a resultant that the X, Y values can be used to display the image in 2D and with Z values that can be used to decide what polygons overlay others.&#xD;&#xA;&#xD;&#xA;However, whilst I've been expecting a cube with dimensions of 1 -&gt; -1 along all axes, instead I've been getting just an inverted frustrum.&#xD;&#xA;&#xD;&#xA;I feel I'm either making an elementary mistake or am missing something key - would appreciate any help in clearing up both my uncertainties in what I need to do to convert my shape from the 3D to the 2D, and what I should be expecting. So far, my results are below. &#xD;&#xA;&#xD;&#xA;The left hand picture shows the shape in a view frustum - and the right shows the original frustum and transformed frustum in green after applying the perspective transform which I believe should be transformed to a unit sized cube and not just a reflected frustum.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I've put my code below, and tried to simplify it as much as possible to make it easier to evaluate!. Thanks very much!&#xD;&#xA;&#xD;&#xA;**Updates**&#xD;&#xA;I've updated my coordinates for view space coordinates - using a different method generates view space coordinates that go 'back' towards negative z values. Not sure if that makes it more correct but I hope it helps (but as per the comment).&#xD;&#xA;&#xD;&#xA;Following the answer below I've added an attempt to perform perspective division. I've added the following code below the main bulk. Any further recommendations would be massively appreciated&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    clc; clear all; close all;&#xD;&#xA;    %======Create View Space (hard-coded values for demo) &amp; Plot  ===========&#xD;&#xA;    ws_fcs = [1,2,4,3,3,1,6,6,6,6,7,7,9,8,8,8,10,10;&#xD;&#xA;        2,4,3,1,4,4,9,8,7,11,9,13,8,12,10,6,11,13;&#xD;&#xA;        5,5,5,5,1,2,7,9,11,10,13,11,13,13,12,10,13,12];&#xD;&#xA;    ws_vtx = [-1.3416,0.4472,-1.3416,0.4472,-1.3416,-0.8944,0,0,0.8944,-0.8944,0,0,0.8944;&#xD;&#xA;              -1.0954,-1.4606,0.7303,0.3651,-1.0954,-0.7303,-0.9129,0,-0.1826,0.1826,0,0.9129,0.7303;&#xD;&#xA;              -4.899,-4.0825,-4.0825,-3.266,-2.4495,-4.4907,-4.0825,-6.1237,-5.7155,-4.0825,-3.6742,-5.7155,-5.3072];&#xD;&#xA;    &#xD;&#xA;    position = [0;0;0;1]; focus = [0;0;-3.6742]; %Transformed set points&#xD;&#xA;    &#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(position(1),position(2),position(3),'s');&#xD;&#xA;    scatter3([position(1); position(1)+focus(1)],[position(2); position(2)+focus(2)],...&#xD;&#xA;        [position(3); position(3)+focus(3)],'s');&#xD;&#xA;    plot3([position(1), focus(1)],[position(2), focus(2)],[position(3), focus(3)],'g');&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx','Facecolor', 'r', 'FaceAlpha', 0.1);&#xD;&#xA;    %====================Create View Volume===========================&#xD;&#xA;    asp_rat = 0.75; %Most displays arent square&#xD;&#xA;    focus = focus/norm(focus); %Normalise focus vector&#xD;&#xA;    nheight = 1; %height of near clip plane&#xD;&#xA;    hoz_angle = 2*pi/3;&#xD;&#xA;    ndistance = 1/tan(hoz_angle/2); %distance of near view plane from origin&#xD;&#xA;    fdistance = 5.5; %Define a far distance&#xD;&#xA;    &#xD;&#xA;    nc = ndistance*focus; %Centre point is focus vector * distance&#xD;&#xA;    ntr = nc + [asp_rat*nheight; nheight; 0]; %Go from centre to TL corner&#xD;&#xA;    nbr = ntr + [0; -2*nheight;0]; %Go down 2* height to bottom&#xD;&#xA;    nbl = nbr + [-2*asp_rat*nheight; 0; 0];&#xD;&#xA;    ntl = nbl + [0; 2*nheight;0];&#xD;&#xA;    nr_plan = [ntr, nbr, nbl, ntl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    fc = fdistance*focus;&#xD;&#xA;    fheight = tan(hoz_angle/2)*fdistance; %Find far plane height by trig&#xD;&#xA;    ftr = fc + [asp_rat*fheight; fheight; 0]; %Go from centre to TL corner&#xD;&#xA;    fbr = ftr + [0; -2*fheight;0]; %Go down 2* height to bottom&#xD;&#xA;    fbl = fbr + [-2*asp_rat*fheight; 0; 0];&#xD;&#xA;    ftl = fbl + [0; 2*fheight;0];&#xD;&#xA;    fr_plan = [ftr, fbr, fbl, ftl]; %Generate near plane points&#xD;&#xA;    &#xD;&#xA;    frust_vtx = horzcat(nr_plan, fr_plan); %Create frustum vertex array&#xD;&#xA;    frust_fcs = [1,8,5,6,4,5;  %Faces defined with normals inwards&#xD;&#xA;                 4,5,1,2,8,8;&#xD;&#xA;                 3,6,2,3,7,4;&#xD;&#xA;                 2,7,6,7,3,1];&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    %=============Create Perspective Matrix ==============================&#xD;&#xA;    figure(); grid on; hold on; xlabel('x'); ylabel('y'); zlabel('z');&#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot orig frustrum &#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx', 'FaceAlpha', 0.05);&#xD;&#xA;    &#xD;&#xA;    left = nc(1) - asp_rat*nheight; %Get values for projection matrix&#xD;&#xA;    right = nc(1) + asp_rat*nheight;&#xD;&#xA;    top = nc(2) + nheight;&#xD;&#xA;    bottom = nc(2) -nheight;&#xD;&#xA;    near = ndistance;&#xD;&#xA;    far = fdistance;&#xD;&#xA;    &#xD;&#xA;    proj_mat = [2*near/(right - left),0,(right + left)/(right - left),0;&#xD;&#xA;        0, 2*near/(top-bottom),(top+bottom)/(top-bottom),0;&#xD;&#xA;        0,0, -(far+near)/(far-near), -2*far*near/(far-near);&#xD;&#xA;        0,0,-1,0];&#xD;&#xA;    %====================Perspective Projection Transformation=============&#xD;&#xA;    frust_vtx = proj_mat*vertcat(frust_vtx,(ones(1,length(frust_vtx)))); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Perspective Division**&#xD;&#xA;&#xD;&#xA;    %========================Perspective Division==========================&#xD;&#xA;    for i = 1:length(frust_vtx) &#xD;&#xA;        frust_vtx(:,i) = frust_vtx(:,i)/frust_vtx(4,i);&#xD;&#xA;    end&#xD;&#xA;    for i = 1:length(ws_vtx) &#xD;&#xA;        ws_vtx(:,i) = ws_vtx(:,i)/ws_vtx(4,i);&#xD;&#xA;    end&#xD;&#xA;    scatter3(ws_vtx(1,:),ws_vtx(2,:),ws_vtx(3,:)); %Plot shape points&#xD;&#xA;    patch('Faces',ws_fcs','Vertices',ws_vtx(1:3,:)','FaceColor','r','FaceAlpha', 0.05); &#xD;&#xA;    scatter3(frust_vtx(1,:),frust_vtx(2,:),frust_vtx(3,:)); %Plot frustrum points&#xD;&#xA;    patch('Faces',frust_fcs','Vertices',frust_vtx(1:3,:)','FaceColor','g','FaceAlpha', 0.05);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/25659623/how-does-a-projection-matrix-work&#xD;&#xA;  [2]: https://i.stack.imgur.com/adExB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/EG3Iu.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/W4xni.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19535" PostHistoryTypeId="24" PostId="2049" RevisionGUID="c8eb8316-7f86-4114-9acf-4dfe57913a0c" CreationDate="2018-04-24T07:44:55.540" Comment="Proposed by 7220 approved by 48, 209 edit id of 404" ContentLicense="CC BY-SA 3.0" />
  <row Id="19536" PostHistoryTypeId="5" PostId="5692" RevisionGUID="4ae0c2e1-b385-4da5-8645-4fa507bbf841" CreationDate="2018-04-24T07:45:23.727" UserDisplayName="user7220" Comment="Corrected indents.." Text="I have an RGB pixel that I'd like to colorize in my program (I'm using GLSL) very similar to how the GIMP &quot;Colors &gt; Colorize&quot; function works.&#xD;&#xA;&#xD;&#xA;[![GIMP's Colorize][1]][1]&#xD;&#xA;&#xD;&#xA;In my program, I can easily convert between RGB and HSV. I can therefore get:&#xD;&#xA;&#xD;&#xA;    pix_h, pix_s, pix_v&#xD;&#xA;&#xD;&#xA;And I also define the inputs of the colorize function as:&#xD;&#xA;&#xD;&#xA;    col_h, col_s, col_v&#xD;&#xA;&#xD;&#xA;What calculations can I perform to determine the output pixel hsv?&#xD;&#xA;&#xD;&#xA;I think I can get:&#xD;&#xA;&#xD;&#xA;    out_h = col_h&#xD;&#xA;&#xD;&#xA;But I'm a little lost on how to calculate output saturation and value.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;Where lum is the luminance of the input pixel:&#xD;&#xA;&#xD;&#xA;    out_s = clamp( (1 - pix_v) * 2, 0, 1)&#xD;&#xA;&#xD;&#xA;    out_v = clamp( pix_v * 2, 0, 1)&#xD;&#xA;&#xD;&#xA;seems to produce good results when colorize inputs S=1 ([0, 1]) and V=.5 ([0, 1]). I'm still struggling to generalize these formulas for when S!=1 and V!=.5.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gDWgl.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19537" PostHistoryTypeId="24" PostId="5692" RevisionGUID="4ae0c2e1-b385-4da5-8645-4fa507bbf841" CreationDate="2018-04-24T07:45:23.727" Comment="Proposed by 7220 approved by 48, 209 edit id of 406" ContentLicense="CC BY-SA 3.0" />
  <row Id="19538" PostHistoryTypeId="5" PostId="5075" RevisionGUID="4fc2f5cc-05a1-4eea-a491-f3b3f3b45962" CreationDate="2018-04-24T07:45:34.880" UserDisplayName="user7220" Comment="Corrected links.." Text="I used `MESA_DEBUG=1` ([Debugging Tips | mesa3d.org][1], [Environment Variables | mesa3d.org][2]) and found out that `glEnable(TEXTURE_2D)` was causing the error.&#xD;&#xA;&#xD;&#xA;I don't know why it only got triggered on the `glDrawArrays` (maybe weird bindings) but when I removed that call it no longer failed with `GL_INVALID_ENUM`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.mesa3d.org/debugging.html&#xD;&#xA;  [2]: https://www.mesa3d.org/envvars.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19539" PostHistoryTypeId="24" PostId="5075" RevisionGUID="4fc2f5cc-05a1-4eea-a491-f3b3f3b45962" CreationDate="2018-04-24T07:45:34.880" Comment="Proposed by 7220 approved by 48, 209 edit id of 405" ContentLicense="CC BY-SA 3.0" />
  <row Id="19540" PostHistoryTypeId="5" PostId="1673" RevisionGUID="0e4e3e2e-b0ca-417c-9f84-25405dd17958" CreationDate="2018-04-24T07:45:54.910" UserDisplayName="user7220" Comment="Corrected indents.." Text="I had posted about this issue in a [previous question](https://computergraphics.stackexchange.com/questions/1663/incorrect-instanced-rendering), however, I thought instancing was causing it, whereas even using normal uniforms or a SSBO (which's what I'm using right now) causes it, which means the problem is elsewhere.&#xD;&#xA;&#xD;&#xA;I've been trying to figure out the cause, and I might've found out something: only the first quad's vertex data seems to be uploaded / used, somehow.&#xD;&#xA;&#xD;&#xA;For example, if I were to place random position and texcoord vectors to my other quads, they would still render somewhat correctly. I said **somewhat** because the output is the following: &#xD;&#xA;&#xD;&#xA;[![middle one is way too stretched and the last one's UV coords are wrong][1]][1]&#xD;&#xA;&#xD;&#xA;The middle one is way too stretched and the last one's UV coords are wrong, since they aren't filling the whole quad, as you can see by the white background. So long as the first quad's were right, and whenever I changed the first quad's vertex data, it was propagated to the other ones as well, leading me to believe the other quads' vertex data are getting ignored and the first quad is being re-used.&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;    // VAO definition&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /*** VBO ***/&#xD;&#xA;    glGenBuffers(1, &amp;VBO);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** Vertex Format ***/&#xD;&#xA;    //Position Vertex&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;    //Normal Vertex&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3)));&#xD;&#xA;    //Texture Coordinate Vertex&#xD;&#xA;    glEnableVertexAttribArray(2);&#xD;&#xA;    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec3) * 2));&#xD;&#xA;    /*** EBO ***/&#xD;&#xA;    glGenBuffers(1, &amp;EBO);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;    /*** SSBO ***/&#xD;&#xA;    glGenBuffers(1, &amp;SSBO);&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // Quad adding function&#xD;&#xA;    auto iter = std::find(quads.begin(), quads.end(), quad);&#xD;&#xA;&#xD;&#xA;    if(iter == quads.end())&#xD;&#xA;    {&#xD;&#xA;        quads.push_back(quad);&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;            vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;&#xD;&#xA;        GLuint start = (indices.empty()) ? 0 : indices[indices.size() - 1] + 1;&#xD;&#xA;&#xD;&#xA;        GLuint newIndices[] = {&#xD;&#xA;            start, start + 1, start + 2,&#xD;&#xA;            start, start + 2, start + 3&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;            indices.push_back(newIndices[i]);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;&#xD;&#xA;        instanceData.push_back(quad-&gt;data);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(RenderingData) * quads.size(), &amp;instanceData[0], GL_DYNAMIC_DRAW);&#xD;&#xA;        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, SSBO, 0, sizeof(RenderingData) * quads.size());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Rendering&#xD;&#xA;    program-&gt;Use();&#xD;&#xA;&#xD;&#xA;    program-&gt;SetStorageBlock(&quot;RenderingData&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY, texture-&gt;GetTexture());&#xD;&#xA;    program-&gt;SetInteger(&quot;diffuseTextureArray&quot;, 0);&#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;&#xD;&#xA;**NOTE:** I also tried to limit the vertex data uploading to the first quad, effectively making it the only one with valid data, a part from the per-instance data (*RenderingData* struct: a model matrix and an uint), which were all fed to the SSBO. This still lead to 3 quads being rendered, which shouldn't be the case under normal circumstances, right?&#xD;&#xA;&#xD;&#xA;**EDIT:** I made a sample code which replicates the problem; it should render a green quad and a red quad, however, it just renders 2 red quads. Also, even if you try to change the second quads' attributes (even like placing all 0s), it'll still just render. Somehow only the first quads' vertices are getting read and used for each subsequent quad.&#xD;&#xA;&#xD;&#xA;**C++ code:**&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    #include &lt;string&gt;&#xD;&#xA;    #include &lt;sstream&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #define GLEW_STATIC&#xD;&#xA;    #include &quot;GL/glew.h&quot;&#xD;&#xA;    #include &quot;GLFW/glfw3.h&quot;&#xD;&#xA;    #include &lt;IL/il.h&gt;&#xD;&#xA;    #include &lt;IL/ilu.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/type_ptr.hpp&gt;&#xD;&#xA;&#xD;&#xA;    struct Vertex{&#xD;&#xA;        glm::vec2 pos, tex;&#xD;&#xA;        glm::vec3 color;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Quad{&#xD;&#xA;        std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;        glm::mat4 model;&#xD;&#xA;    &#xD;&#xA;        Quad(glm::vec2 pos, glm::vec2 size, const std::vector&lt;Vertex&gt; &amp;v){&#xD;&#xA;            vertices = v;&#xD;&#xA;            model = glm::mat4();&#xD;&#xA;            model = glm::translate(model, glm::vec3(pos, 0.f));&#xD;&#xA;            model = glm::scale(model, glm::vec3(size, 1.f));&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    class Renderer{&#xD;&#xA;        private:&#xD;&#xA;            GLuint VAO, VBO, instanceVBO, EBO;&#xD;&#xA;            std::vector&lt;Quad*&gt; quads;&#xD;&#xA;            std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;            std::vector&lt;glm::mat4&gt; models;&#xD;&#xA;            std::vector&lt;GLuint&gt; indices;&#xD;&#xA;    &#xD;&#xA;        public:&#xD;&#xA;            Renderer(){&#xD;&#xA;                /*** VAO ***/&#xD;&#xA;                glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;                glBindVertexArray(VAO);&#xD;&#xA;                /*** Per-vertex VBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;VBO);&#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;                glEnableVertexAttribArray(0);   // Position&#xD;&#xA;                glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);&#xD;&#xA;                glEnableVertexAttribArray(1);   // Tex Coord&#xD;&#xA;                glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec2)));&#xD;&#xA;                glEnableVertexAttribArray(2);   // Color&#xD;&#xA;                glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(glm::vec2) * 2));&#xD;&#xA;                /*** Per-instance VBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;instanceVBO);&#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;                glEnableVertexAttribArray(3);   // Model matrix - row1&#xD;&#xA;                glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), nullptr);&#xD;&#xA;                glVertexAttribDivisor(3, 1);&#xD;&#xA;                glEnableVertexAttribArray(4);   // Model matrix - row2&#xD;&#xA;                glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4)));&#xD;&#xA;                glVertexAttribDivisor(4, 1);&#xD;&#xA;                glEnableVertexAttribArray(5);   // Model matrix - row3&#xD;&#xA;                glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * 2));&#xD;&#xA;                glVertexAttribDivisor(5, 1);&#xD;&#xA;                glEnableVertexAttribArray(6);   // Model matrix - row4&#xD;&#xA;                glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4) * 3));&#xD;&#xA;                glVertexAttribDivisor(6, 1);&#xD;&#xA;                /*** EBO ***/&#xD;&#xA;                glGenBuffers(1, &amp;EBO);&#xD;&#xA;                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;                glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);&#xD;&#xA;            }&#xD;&#xA;            ~Renderer(){&#xD;&#xA;                glDeleteBuffers(1, &amp;VBO);&#xD;&#xA;                glDeleteBuffers(1, &amp;instanceVBO);&#xD;&#xA;                glDeleteBuffers(1, &amp;EBO);&#xD;&#xA;                glDeleteVertexArrays(1, &amp;VAO);&#xD;&#xA;            }&#xD;&#xA;            void AddQuad(Quad *const quad){&#xD;&#xA;                quads.push_back(quad);&#xD;&#xA;    &#xD;&#xA;                for(unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;                    vertices.push_back(quad-&gt;vertices[i]);&#xD;&#xA;    &#xD;&#xA;                models.push_back(quad-&gt;model);&#xD;&#xA;    &#xD;&#xA;                GLuint start = ((indices.empty()) ? 0 : indices[indices.size() - 1] + 1);&#xD;&#xA;    &#xD;&#xA;                GLuint newIndices[] = {&#xD;&#xA;                    start,  start + 1,  start + 2,&#xD;&#xA;                    start,  start + 3,  start + 2&#xD;&#xA;                };&#xD;&#xA;&#xD;&#xA;                for(unsigned int i = 0; i &lt; 6; i++)&#xD;&#xA;                    indices.push_back(newIndices[i]);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &amp;vertices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);&#xD;&#xA;                glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * quads.size(), &amp;models[0], GL_DYNAMIC_DRAW);&#xD;&#xA;    &#xD;&#xA;                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;                glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), &amp;indices[0], GL_DYNAMIC_DRAW);&#xD;&#xA;            }&#xD;&#xA;            void Render(GLuint &amp;program){&#xD;&#xA;                glUseProgram(program);&#xD;&#xA;    &#xD;&#xA;                glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, quads.size());&#xD;&#xA;            }&#xD;&#xA;            void CheckQuads(){&#xD;&#xA;                for(unsigned int i = 0; i &lt; quads.size(); i++)&#xD;&#xA;                {&#xD;&#xA;                    std::cout &lt;&lt; &quot;Quad n.&quot; &lt;&lt; i &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                    for(unsigned int j = 0; j &lt; 4; j++)&#xD;&#xA;                    {&#xD;&#xA;                        std::cout &lt;&lt; &quot;\tVert &quot; &lt;&lt; j &lt;&lt; &quot;:\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].pos.x &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].pos.y &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].tex.x &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].tex.y &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                        std::cout &lt;&lt; &quot;\t&quot; &lt;&lt; quads[i]-&gt;vertices[j].color.r &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].color.g &lt;&lt; &quot; &quot; &lt;&lt; quads[i]-&gt;vertices[j].color.b &lt;&lt; &quot;\n&quot;;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    GLuint GenerateShader(const std::string &amp;filename, GLenum shaderType)&#xD;&#xA;    {&#xD;&#xA;        GLuint shader;&#xD;&#xA;        std::ifstream file(filename.c_str());&#xD;&#xA;        std::stringstream ss;&#xD;&#xA;        ss &lt;&lt; file.rdbuf();&#xD;&#xA;        file.close();&#xD;&#xA;        const GLchar *source = ss.str().c_str();&#xD;&#xA;        shader = glCreateShader(shaderType);&#xD;&#xA;        glShaderSource(shader, 1, &amp;source, nullptr);&#xD;&#xA;        glCompileShader(shader);&#xD;&#xA;        return shader;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        /*** Window + Context ***/&#xD;&#xA;        glfwInit();&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;        GLFWwindow *window = glfwCreateWindow(640, 480, &quot;OpenGL Incorrect Rendering Test&quot;, nullptr, nullptr);&#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;        glewExperimental = GL_TRUE;&#xD;&#xA;        glewInit();&#xD;&#xA;        glViewport(0, 0, 640, 480);&#xD;&#xA;        glClearColor(0.f, 0.f, 0.f, 1.f);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 projection = glm::ortho(0.f, 640.f, 480.f, 0.f, -1.f, 1.f);&#xD;&#xA;    &#xD;&#xA;        /*** Shader Program ***/&#xD;&#xA;        GLuint program = glCreateProgram();&#xD;&#xA;        glAttachShader(program, GenerateShader(&quot;vertex_shader.glsl&quot;, GL_VERTEX_SHADER));&#xD;&#xA;        glAttachShader(program, GenerateShader(&quot;fragment_shader.glsl&quot;, GL_FRAGMENT_SHADER));&#xD;&#xA;        glLinkProgram(program);&#xD;&#xA;    &#xD;&#xA;        glUseProgram(program);&#xD;&#xA;        glUniformMatrix4fv(glGetUniformLocation(program, &quot;projection&quot;), 1, GL_FALSE, glm::value_ptr(projection));&#xD;&#xA;        /*** Renderer ***/&#xD;&#xA;        Renderer *renderer = new Renderer();&#xD;&#xA;        // Quad 1&#xD;&#xA;        Vertex v1 = {glm::vec2(0.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v2 = {glm::vec2(1.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v3 = {glm::vec2(1.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        Vertex v4 = {glm::vec2(0.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(1.f, 0.f, 0.f)};&#xD;&#xA;        renderer-&gt;AddQuad(new Quad(glm::vec2(300, 10), glm::vec2(150, 150), {v1, v2, v3, v4}));&#xD;&#xA;        // Quad 2&#xD;&#xA;        Vertex v5 = {glm::vec2(0.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v6 = {glm::vec2(1.f, 0.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v7 = {glm::vec2(1.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        Vertex v8 = {glm::vec2(0.f, 1.f), glm::vec2(0.f, 0.f), glm::vec3(0.f, 1.f, 0.f)};&#xD;&#xA;        renderer-&gt;AddQuad(new Quad(glm::vec2(30, 10), glm::vec2(150, 150), {v5, v6, v7, v8}));&#xD;&#xA;&#xD;&#xA;        while(!glfwWindowShouldClose(window))&#xD;&#xA;        {&#xD;&#xA;            glfwPollEvents();&#xD;&#xA;    &#xD;&#xA;            if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;                glfwSetWindowShouldClose(window, true);&#xD;&#xA;    &#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;            renderer-&gt;Render(program);&#xD;&#xA;    &#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        delete renderer;&#xD;&#xA;    &#xD;&#xA;        glfwDestroyWindow(window);&#xD;&#xA;        glfwTerminate();&#xD;&#xA;    &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**vertex_shader.glsl:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    layout (location = 0) in vec2 position;&#xD;&#xA;    layout (location = 1) in vec2 texCoord;&#xD;&#xA;    layout (location = 2) in vec3 color;&#xD;&#xA;    layout (location = 3) in mat4 model;&#xD;&#xA;    &#xD;&#xA;    out vec2 uv;&#xD;&#xA;    out vec3 col;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uv = texCoord;&#xD;&#xA;        col = color;&#xD;&#xA;    &#xD;&#xA;        gl_Position = projection * model * vec4(position, 0.f, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**fragment_shader.glsl:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    in vec2 uv;&#xD;&#xA;    in vec3 col;&#xD;&#xA;    out vec4 color;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        color = vec4(col, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ULWbw.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19541" PostHistoryTypeId="24" PostId="1673" RevisionGUID="0e4e3e2e-b0ca-417c-9f84-25405dd17958" CreationDate="2018-04-24T07:45:54.910" Comment="Proposed by 7220 approved by 48, 209 edit id of 407" ContentLicense="CC BY-SA 3.0" />
  <row Id="19542" PostHistoryTypeId="5" PostId="5650" RevisionGUID="4229ccae-1ebb-4e4f-99a3-aeb59e72908b" CreationDate="2018-04-24T07:46:19.220" UserDisplayName="user7220" Comment="Corrected links.." Text="user1118321's suggestion is the correct one but i'll elaborate a bit.&#xD;&#xA;&#xD;&#xA;You run your simulation giving it a fixed time step between frames.  This time step would be 1/30th of a second (33.3333 ms) for instance if you wanted a 30 fps movie.&#xD;&#xA;&#xD;&#xA;You let your simulation calculations and your rendering run, taking as long as they need to, and then write the rendered frame out to disk, with the frame number in the name (like frame0.bmp, frame1.bmp, etc).&#xD;&#xA;&#xD;&#xA;After you have all these frames, you can use ffmpeg to combine them into a video of the desired frame rate.&#xD;&#xA;&#xD;&#xA;If you want audio in your video (like sounds when things collide), you can actually keep an audio timeline (what audio events happened on which frames, or at what points in time) while doing your simulation, and then after your rendering is finished, you can generate the audio stream that goes along with your video, which ffmpeg will gladly combine with your video.&#xD;&#xA;&#xD;&#xA;I've used this on a few projects in times past and it's worked great.  I also wrote up some more details about this process a while back:&#xD;&#xA;&#xD;&#xA;[Recording lagless demo videos of a laggy game | The blog at the bottom of the sea][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://blog.demofox.org/2012/09/09/recording-perfectly-lagless-audio-synchronized-video-of-your-game/" ContentLicense="CC BY-SA 3.0" />
  <row Id="19543" PostHistoryTypeId="24" PostId="5650" RevisionGUID="4229ccae-1ebb-4e4f-99a3-aeb59e72908b" CreationDate="2018-04-24T07:46:19.220" Comment="Proposed by 7220 approved by 48, 209 edit id of 410" ContentLicense="CC BY-SA 3.0" />
  <row Id="19544" PostHistoryTypeId="2" PostId="7548" RevisionGUID="6cbae031-e2d6-4e8b-a81a-261e1d63850a" CreationDate="2018-04-24T09:44:57.420" UserId="8621" Text="I have a CAD model in Solidworks (which can be converted to STL, OBJ, STEP , VRML etc.) that I need to render in an old application, which still uses fixed pipeline.&#xD;&#xA;&#xD;&#xA;Ideally, I would like to convert my model into a series of `glMaterialfv`, `glBegin`, `glVertex3f`, `glEnd` commands that I can compile directly into a C library so that I can avoid loading data from an external file. If this approach will be too painful, however, perhaps someone could alternatively suggest an open-source lightweight fixed pipeline model renderer that I can embed into my code." ContentLicense="CC BY-SA 3.0" />
  <row Id="19545" PostHistoryTypeId="1" PostId="7548" RevisionGUID="6cbae031-e2d6-4e8b-a81a-261e1d63850a" CreationDate="2018-04-24T09:44:57.420" UserId="8621" Text="How to convert a 3D model into an OpenGL fixed pipeline representation" ContentLicense="CC BY-SA 3.0" />
  <row Id="19546" PostHistoryTypeId="3" PostId="7548" RevisionGUID="6cbae031-e2d6-4e8b-a81a-261e1d63850a" CreationDate="2018-04-24T09:44:57.420" UserId="8621" Text="|rendering|legacy-opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19550" PostHistoryTypeId="5" PostId="4884" RevisionGUID="0dfb4d3a-0cc8-4fa9-af01-39e6efcb42d0" CreationDate="2018-04-24T10:13:17.127" UserId="6255" Comment="added 4 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(modelviewmatrix))) //top 3x3 row of model*view&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // *needs to be in view-space* (view*lightpos)&#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldn't the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesn't just come from the wrong spot, but it also doesn't change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesn't come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however.&#xD;&#xA;&#xD;&#xA;So, the diffuse value is calculated by getting the dot(s,n), where s is (lightposition - position), and position is (view * model * vertex_position). But like you can see, the results are not as expected&#xD;&#xA;&#xD;&#xA;Solution: **The math needs to take place in the same space, and here I'm not** placing the lightposition into viewspace, so, it doesn't add up.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19552" PostHistoryTypeId="2" PostId="7550" RevisionGUID="aee3cdc2-5fc4-4d14-8f20-4ccce9b13ab0" CreationDate="2018-04-24T11:01:22.070" UserId="137" Text="You can compile it into a &#xD;&#xA;&#xD;&#xA;    Vertex vertices[] = {{posx, posy, posz, ..}, &#xD;&#xA;                         {posx, posy, posz, ..}, &#xD;&#xA;                         //...&#xD;&#xA;                        }&#xD;&#xA;&#xD;&#xA;and then loop over them:&#xD;&#xA;&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    for (int i = 0; i &lt; arraycount(vertices); i++){&#xD;&#xA;        glColor(...);&#xD;&#xA;        //...&#xD;&#xA;        glVertex3f(vertices[i].posx, vertices[i].posy, vertices[i].posz);&#xD;&#xA;    }&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;Another solution would be to mimic what the modern vertex buffer based solutions do by creating a VertexAttributeLayout struct and setting it up. Then in the loop you interpret the layout struct and interpret the data as needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="19554" PostHistoryTypeId="5" PostId="4884" RevisionGUID="01090760-d5fc-4f6c-94bb-f9768eb6c843" CreationDate="2018-04-24T17:07:01.527" UserId="2654" Comment="deleted 147 characters in body" Text="This is what I'm doing:&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;    &#xD;&#xA;    #version 400&#xD;&#xA;	layout ( location = 0 ) in vec3 vertex_position;&#xD;&#xA;    layout ( location = 1 ) in vec3 vertex_normal;&#xD;&#xA;&#xD;&#xA;    uniform mat4 ModelViewMatrix; //view*model&#xD;&#xA;    uniform mat3 NormalMatrix; //transpose(inverse(modelviewmatrix))) //top 3x3 row of model*view&#xD;&#xA;    uniform mat4 priv_mat; //projection*view*model&#xD;&#xA;&#xD;&#xA;    out vec3 normal;&#xD;&#xA;    out vec3 position;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;	  normal=normalize(NormalMatrix*vertex_normal);&#xD;&#xA;	  position=vec3(ModelViewMatrix*vec4(vertex_position,1.0));&#xD;&#xA;	  gl_Position=priv_mat*vec4(vertex_position,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    in vec3 normal;&#xD;&#xA;    in vec3 position;&#xD;&#xA;&#xD;&#xA;    uniform vec4 LightPosition; // *needs to be in view-space* (view*lightpos)&#xD;&#xA;    uniform vec3 LightIntensity;&#xD;&#xA;&#xD;&#xA;    uniform vec3 Kd;            // Diffuse reflectivity&#xD;&#xA;    uniform vec3 Ka;            // Ambient reflectivity&#xD;&#xA;    uniform vec3 Ks;            // Specular reflectivity&#xD;&#xA;    uniform float Shininess;    // Shininess&#xD;&#xA;&#xD;&#xA;    vec3 ads( ){&#xD;&#xA;	    vec3 n = normal;&#xD;&#xA;	    vec3 s = normalize( vec3(LightPosition) - position ); &#xD;&#xA;	    vec3 v = normalize( vec3(-position)); &#xD;&#xA;	    vec3 r = reflect( -s, n );&#xD;&#xA;	return &#xD;&#xA;        LightIntensity * &#xD;&#xA;        ( Ka + &#xD;&#xA;        Kd * max( dot(s, n), 0.0 ) +  &#xD;&#xA;        Ks * pow( max( dot(r,v), 0.0 ), Shininess ) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;         gl_FragColor = vec4(ads(), 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But when I run it, I get this:&#xD;&#xA;&#xD;&#xA;[![shouldn't the light be correct?][1]][1]&#xD;&#xA;&#xD;&#xA;Where the light doesn't just come from the wrong spot, but it also doesn't change when I move the planet around, like so&#xD;&#xA;&#xD;&#xA;[![I can spin the asteroid, but the light doesn't come from where it should][2]][2]&#xD;&#xA;&#xD;&#xA;Where the diffuse value somehow gets the wrong direction? The math is beyond me however.&#xD;&#xA;&#xD;&#xA;So, the diffuse value is calculated by getting the dot(s,n), where s is (lightposition - position), and position is (view * model * vertex_position). But like you can see, the results are not as expected&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wuyui.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Fb7DY.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19563" PostHistoryTypeId="2" PostId="7552" RevisionGUID="3a3cfbe2-7b21-4aed-94ca-b10f29bc1605" CreationDate="2018-04-25T11:00:23.553" UserId="8629" Text="A `bounding box`, if I understood correctly is a box that frames the box in which we work. It allows to align the box on the left, on the right, in the center.&#xD;&#xA;&#xD;&#xA;Its use can be found in LaTeX package like `pgf/tikz`, `graphicx`, `tcolorbox` and certainly in other LaTeX packages as well as in the `Adobe Post Script` reference manual.&#xD;&#xA;&#xD;&#xA;We do not find this notion, except error of my part in `LaTeX2e` written by L. Lamport.&#xD;&#xA;&#xD;&#xA;From the historical point of view who (or what computer language) introduced this notion?&#xD;&#xA;&#xD;&#xA;Is the concept of `bounding box` equivalent in all LaTeX packages? in all languages?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19564" PostHistoryTypeId="1" PostId="7552" RevisionGUID="3a3cfbe2-7b21-4aed-94ca-b10f29bc1605" CreationDate="2018-04-25T11:00:23.553" UserId="8629" Text="What is the history of the bounding box concept?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19565" PostHistoryTypeId="3" PostId="7552" RevisionGUID="3a3cfbe2-7b21-4aed-94ca-b10f29bc1605" CreationDate="2018-04-25T11:00:23.553" UserId="8629" Text="|computational-geometry|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19566" PostHistoryTypeId="5" PostId="7550" RevisionGUID="9915a293-0f72-4532-88e9-a53929fa8cfb" CreationDate="2018-04-25T11:43:24.877" UserId="137" Comment="added 63 characters in body" Text="You can compile it into a &#xD;&#xA;&#xD;&#xA;    Vertex vertices[] = {{posx, posy, posz, texu, texv, ..}, &#xD;&#xA;                         {posx, posy, posz, texu, texv, ..}, &#xD;&#xA;                         //...&#xD;&#xA;                        }&#xD;&#xA;&#xD;&#xA;and then loop over them:&#xD;&#xA;&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    for (int i = 0; i &lt; arraycount(vertices); i++){&#xD;&#xA;&#xD;&#xA;        glTexCoord2f(vertices[i].texu, vertices[i].texv);&#xD;&#xA;        //... &#xD;&#xA;        glVertex3f(vertices[i].posx, vertices[i].posy, vertices[i].posz);&#xD;&#xA;    }&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;Another solution would be to mimic what the modern vertex buffer based solutions do by creating a VertexAttributeLayout struct and setting it up. Then in the loop you interpret the layout struct and interpret the data as needed." ContentLicense="CC BY-SA 3.0" />
  <row Id="19567" PostHistoryTypeId="50" PostId="6406" RevisionGUID="f6487d61-70ca-480e-abf8-b9ffe129ccb6" CreationDate="2018-04-25T15:01:17.997" UserId="-1" />
  <row Id="19569" PostHistoryTypeId="50" PostId="7433" RevisionGUID="6e0c6cba-875e-49de-b5c2-bab9a81f8bdc" CreationDate="2018-04-26T04:02:18.387" UserId="-1" />
  <row Id="19572" PostHistoryTypeId="2" PostId="7554" RevisionGUID="cabe3b90-e285-4080-a521-d0923d3dee74" CreationDate="2018-04-26T14:01:54.803" UserId="8597" Text="I've found a site that provides an overview of the OpenGL pipeline: &#xD;&#xA;&#xD;&#xA;[Rendering pipeline overview][1]&#xD;&#xA;&#xD;&#xA;Now in the 3th phase (vertex processing) it says that after the transform feedback, there is the primitive clipping. If I am not mistaken, the primitive clipping must occur after that the vertices are multiplied by the projection matrix, otherwise it's impossible to determine if the primitives are inside or outside the view volume defined with *glFrustum()*.&#xD;&#xA;&#xD;&#xA;I know that in a typical GLSL shader you need to apply the modelview matrix to the vertices, so that you obtain a vertex in eye coordinates. So if I am not mistaken, at the end of the vertex shader you don't have vertices defined in clip coordinates yet. But this makes me think: where is the projection matrix applied? it seems like it's missing in this pipeline overview. &#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview" ContentLicense="CC BY-SA 3.0" />
  <row Id="19573" PostHistoryTypeId="1" PostId="7554" RevisionGUID="cabe3b90-e285-4080-a521-d0923d3dee74" CreationDate="2018-04-26T14:01:54.803" UserId="8597" Text="At which stage of the pipeline is the projection transform applied?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19574" PostHistoryTypeId="3" PostId="7554" RevisionGUID="cabe3b90-e285-4080-a521-d0923d3dee74" CreationDate="2018-04-26T14:01:54.803" UserId="8597" Text="|opengl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19575" PostHistoryTypeId="2" PostId="7555" RevisionGUID="1ccae8c7-3e74-45a2-bba4-37d03dee2f56" CreationDate="2018-04-26T14:23:31.700" UserId="7008" Text="&gt; I know that in a typical GLSL shader you need to apply the modelview matrix to the vertices, so that you obtain a vertex in eye coordinates.&#xD;&#xA;&#xD;&#xA;This is not quite correct, you need to apply the modelview*projection* matrix and thus transform your vertices into Clip Space Coordinates. &#xD;&#xA;You can apply the ModelView Matrix in certain instances, e.g. if you want to calculate light in Eye Space. However, the `gl_Position` will then still not use the ModelView but the ModelViewProjection Matrix and your light/whatever- position will use the ModelView Matrix and be transferred to the fragment shader via the `out` variables.&#xD;&#xA;&#xD;&#xA;For a more detailed discussion, you can look into [the comments on this question][1], I had to be corrected about that myself (since not all literature is clear/correct about Normalized Device Space and Clip Space).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/49259363/how-to-get-screen-widget-coordinates-from-world-coordinates/49260694#49260694" ContentLicense="CC BY-SA 3.0" />
  <row Id="19576" PostHistoryTypeId="2" PostId="7556" RevisionGUID="9e63ed31-6283-4f11-9143-6bd573052a53" CreationDate="2018-04-26T17:27:37.120" UserId="228" Text="In PBS context what is the metalness map? Are my interpretation of Normal, Roughness and Albedo map correct?&#xD;&#xA;&#xD;&#xA;I know almost for sure that:&#xD;&#xA;&#xD;&#xA;Normal map : Models the normals per differential region in our material (kind of).&#xD;&#xA;&#xD;&#xA;Roughness map : Together with the normal map allow to define a microfacet distribution in a differential region of our material.&#xD;&#xA;&#xD;&#xA;Albedo map : This models the percentage of light that is diffusely reflected.&#xD;&#xA;&#xD;&#xA;Normal + Roughness allow to define the amount of energy that is specularly reflected.&#xD;&#xA;&#xD;&#xA;I struggle to understand the physical meaning of the metalness though, I understand it's related to have a material look like metal of course, but physically speaking I don't get what it models." ContentLicense="CC BY-SA 3.0" />
  <row Id="19577" PostHistoryTypeId="1" PostId="7556" RevisionGUID="9e63ed31-6283-4f11-9143-6bd573052a53" CreationDate="2018-04-26T17:27:37.120" UserId="228" Text="What is the physical interpretation of Normal, Roughness, Albedo and Metalness map?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19578" PostHistoryTypeId="3" PostId="7556" RevisionGUID="9e63ed31-6283-4f11-9143-6bd573052a53" CreationDate="2018-04-26T17:27:37.120" UserId="228" Text="|rendering|physically-based|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19579" PostHistoryTypeId="2" PostId="7557" RevisionGUID="0d853a31-139e-46f5-9c3d-4c29d9e99d81" CreationDate="2018-04-27T08:48:02.000" UserId="8517" Text="Hello I am trying to move the x y location of the texture using this code but it doest not work.&#xD;&#xA;&#xD;&#xA;    //Fragment shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect texture0;&#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    	//Getting coordinates of the current pixel in texture&#xD;&#xA;    	vec2 pos = gl_TexCoord[0].xy;&#xD;&#xA;    	&#xD;&#xA;    	// pos.x = (pos.x/0.5); //working&#xD;&#xA;    	pos.x += 0.2 //&lt;-- not working how to fixed this?&#xD;&#xA;    &#xD;&#xA;    	//Getting the pixel color from the texture texture0 in pos&#xD;&#xA;    	vec4 color = texture2DRect(texture0, pos);&#xD;&#xA;    &#xD;&#xA;    	//Changing the color - invert red, green, blue components&#xD;&#xA;    	//color.r = 1.0 - color.r;&#xD;&#xA;    	color.g = 1.0 - color.g; //working..&#xD;&#xA;    	//color.b = 1.0 - color.b;&#xD;&#xA;    	&#xD;&#xA;    	//Output the color of shader&#xD;&#xA;    	gl_FragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&#xD;&#xA;    	gl_TexCoord[0] = gl_MultiTexCoord0;&#xD;&#xA;    	gl_FrontColor = gl_Color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;whats wrong with this code?&#xD;&#xA;pos.x += 0.2 //not working how to fixed this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19580" PostHistoryTypeId="1" PostId="7557" RevisionGUID="0d853a31-139e-46f5-9c3d-4c29d9e99d81" CreationDate="2018-04-27T08:48:02.000" UserId="8517" Text="Shader cannot move texture x, y location" ContentLicense="CC BY-SA 3.0" />
  <row Id="19581" PostHistoryTypeId="3" PostId="7557" RevisionGUID="0d853a31-139e-46f5-9c3d-4c29d9e99d81" CreationDate="2018-04-27T08:48:02.000" UserId="8517" Text="|shader|fragment-shader|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19582" PostHistoryTypeId="5" PostId="7557" RevisionGUID="81331b22-c729-4c16-b1cb-b2a10f07a01e" CreationDate="2018-04-27T09:00:21.787" UserId="8517" Comment="added 93 characters in body" Text="Crossposted https://forum.openframeworks.cc/t/shader-cannot-move-texture-x-y-location/29395&#xD;&#xA;Hello I am trying to move the x y location of the texture using this code but it doest not work.&#xD;&#xA;&#xD;&#xA;    //Fragment shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect texture0;&#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    	//Getting coordinates of the current pixel in texture&#xD;&#xA;    	vec2 pos = gl_TexCoord[0].xy;&#xD;&#xA;    	&#xD;&#xA;    	// pos.x = (pos.x/0.5); //working&#xD;&#xA;    	pos.x += 0.2 //&lt;-- not working how to fixed this?&#xD;&#xA;    &#xD;&#xA;    	//Getting the pixel color from the texture texture0 in pos&#xD;&#xA;    	vec4 color = texture2DRect(texture0, pos);&#xD;&#xA;    &#xD;&#xA;    	//Changing the color - invert red, green, blue components&#xD;&#xA;    	//color.r = 1.0 - color.r;&#xD;&#xA;    	color.g = 1.0 - color.g; //working..&#xD;&#xA;    	//color.b = 1.0 - color.b;&#xD;&#xA;    	&#xD;&#xA;    	//Output the color of shader&#xD;&#xA;    	gl_FragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&#xD;&#xA;    	gl_TexCoord[0] = gl_MultiTexCoord0;&#xD;&#xA;    	gl_FrontColor = gl_Color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;whats wrong with this code?&#xD;&#xA;pos.x += 0.2 //not working how to fixed this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19583" PostHistoryTypeId="5" PostId="7557" RevisionGUID="5fe9291c-4946-496d-b488-ee5a64ff8b63" CreationDate="2018-04-27T09:10:50.203" UserId="7008" Comment="separated the fragment from the vertex shader for readability" Text="Crossposted https://forum.openframeworks.cc/t/shader-cannot-move-texture-x-y-location/29395&#xD;&#xA;Hello I am trying to move the x y location of the texture using this code but it doest not work.&#xD;&#xA;&#xD;&#xA;    //Fragment shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect texture0;&#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    	//Getting coordinates of the current pixel in texture&#xD;&#xA;    	vec2 pos = gl_TexCoord[0].xy;&#xD;&#xA;    	&#xD;&#xA;    	// pos.x = (pos.x/0.5); //working&#xD;&#xA;    	pos.x += 0.2 //&lt;-- not working how to fixed this?&#xD;&#xA;    &#xD;&#xA;    	//Getting the pixel color from the texture texture0 in pos&#xD;&#xA;    	vec4 color = texture2DRect(texture0, pos);&#xD;&#xA;    &#xD;&#xA;    	//Changing the color - invert red, green, blue components&#xD;&#xA;    	//color.r = 1.0 - color.r;&#xD;&#xA;    	color.g = 1.0 - color.g; //working..&#xD;&#xA;    	//color.b = 1.0 - color.b;&#xD;&#xA;    	&#xD;&#xA;    	//Output the color of shader&#xD;&#xA;    	gl_FragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&#xD;&#xA;    	gl_TexCoord[0] = gl_MultiTexCoord0;&#xD;&#xA;    	gl_FrontColor = gl_Color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;whats wrong with this code?&#xD;&#xA;pos.x += 0.2 //not working how to fixed this?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19584" PostHistoryTypeId="24" PostId="7557" RevisionGUID="5fe9291c-4946-496d-b488-ee5a64ff8b63" CreationDate="2018-04-27T09:10:50.203" Comment="Proposed by 7008 approved by 8517 edit id of 412" ContentLicense="CC BY-SA 3.0" />
  <row Id="19585" PostHistoryTypeId="2" PostId="7558" RevisionGUID="fadb2b6f-1185-4005-baf3-04fec1dba3f7" CreationDate="2018-04-27T09:25:48.270" UserId="7008" Text="What you do is shifting the texture coordinates. This will move the texture on your polygon, and depending on your settings it will handle the borders which are now probably wrong. however, this will not move your polygon - if you want to move an entire object, you should not do that within the shader. you do that via modifying your model matrix.&#xD;&#xA;&#xD;&#xA;I assume you have a rectangle, and you want to move it by `0.2` along the x axis. Then you would edit the correct element of your model matrix for the rectangle. &#xD;&#xA;&#xD;&#xA;    //depending on your setup, you may need [0][3] rather than [3][0]&#xD;&#xA;    modelMatrix[3][0] += 0.2;&#xD;&#xA;    //now upload the matrix to your shader&#xD;&#xA;    //the entire object will be moved by 0.2 units &#xD;&#xA;&#xD;&#xA;If that is what you wanted, then you need to remove the fragment shader position calculation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On a sidenote: I had problems with using `+=` in a shader the other day, so it might just be that this doesn't compile. Try using `position = position + 0.2;` instead." ContentLicense="CC BY-SA 3.0" />
  <row Id="19586" PostHistoryTypeId="2" PostId="7559" RevisionGUID="c619dec0-5cc0-455b-b8de-e7a8f75d35ba" CreationDate="2018-04-27T09:34:09.723" UserId="4546" Text="Those parameters have no direct physical equivalent. They were chosen to be intuitive and to range from 0-1. See the Burley's [Physically-Based Shading at Disney][1] for the full rationale and derivation of what is now commonly referred to as &quot;PBR&quot;.&#xD;&#xA;&#xD;&#xA;The &quot;metalness&quot; parameter is a simple blend between two models - one dielectric BSDF with a coloured diffuse and white specular, and a metallic BSDF without diffuse and a coloured specular component.&#xD;&#xA;&#xD;&#xA;  [1]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 3.0" />
  <row Id="19587" PostHistoryTypeId="5" PostId="7557" RevisionGUID="36666b6f-c4a3-4c29-887a-23074117eece" CreationDate="2018-04-27T10:05:01.397" UserId="8517" Comment="added 200 characters in body" Text="Crossposted https://forum.openframeworks.cc/t/shader-cannot-move-texture-x-y-location/29395&#xD;&#xA;Hello I am trying to move the x y location of the texture using this code but it doest not work.&#xD;&#xA;&#xD;&#xA;    //Fragment shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    uniform sampler2DRect texture0;&#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;    	//Getting coordinates of the current pixel in texture&#xD;&#xA;    	vec2 pos = gl_TexCoord[0].xy;&#xD;&#xA;    	&#xD;&#xA;    	// pos.x = (pos.x/0.5); //working&#xD;&#xA;    	pos.x += 0.2 //&lt;-- not working how to fixed this?&#xD;&#xA;    &#xD;&#xA;    	//Getting the pixel color from the texture texture0 in pos&#xD;&#xA;    	vec4 color = texture2DRect(texture0, pos);&#xD;&#xA;    &#xD;&#xA;    	//Changing the color - invert red, green, blue components&#xD;&#xA;    	//color.r = 1.0 - color.r;&#xD;&#xA;    	color.g = 1.0 - color.g; //working..&#xD;&#xA;    	//color.b = 1.0 - color.b;&#xD;&#xA;    	&#xD;&#xA;    	//Output the color of shader&#xD;&#xA;    	gl_FragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //Vertex shader&#xD;&#xA;    #version 120&#xD;&#xA;    #extension GL_ARB_texture_rectangle : enable&#xD;&#xA;    #extension GL_EXT_gpu_shader4 : enable&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&#xD;&#xA;    	gl_TexCoord[0] = gl_MultiTexCoord0;&#xD;&#xA;    	gl_FrontColor = gl_Color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;whats wrong with this code?&#xD;&#xA;pos.x += 0.2 //not working how to fixed this?&#xD;&#xA;&#xD;&#xA;////////////////////////////////////////////////////////////////////////&#xD;&#xA;&#xD;&#xA;I found the solution  pos.x += 0.2 already working but it is not visible.&#xD;&#xA;if I tried bigger number like  pos.x += 100 it is clear that the textures moves.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19588" PostHistoryTypeId="2" PostId="7560" RevisionGUID="4293be63-d8b7-4780-bf10-610c3561305d" CreationDate="2018-04-27T12:49:30.413" UserId="8621" Text="As pointed out in the comments, the most straightforward way to do this is to loop over an array of vertices, which is supported by both fixed and programmable pipelines in OpenGL.&#xD;&#xA;&#xD;&#xA;The motivation for requesting a fixed pipeline solution in question is simple: that is what the existing code base uses! At the moment, the code base has no means of importing models and the models that do already exist in the code base have been hand coded using a series of fixed pipeline OpenGL function calls.&#xD;&#xA;&#xD;&#xA;All things considered, I believe the best workflow (and answer to this question) would be as follows:&#xD;&#xA;&#xD;&#xA;1. Export the CAD models to Wavefront OBJ format&#xD;&#xA;2. Integrate the fixed-pipeline rendering implementation of this [open-source OBJ viewer][1] into the code base.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.dhpoware.com/demos/glObjViewer.html" ContentLicense="CC BY-SA 3.0" />
  <row Id="19589" PostHistoryTypeId="50" PostId="5925" RevisionGUID="ca463929-09f1-4c52-9419-d58bf54aee87" CreationDate="2018-04-27T14:02:56.713" UserId="-1" />
  <row Id="19590" PostHistoryTypeId="2" PostId="7561" RevisionGUID="c6affc01-fa7c-45fc-9ae1-c3f41087c4b1" CreationDate="2018-04-28T00:51:45.160" UserId="3003" Text="When you use `GL_TEXTURE_RECTANGLE` in your source code and `texture2DRect()` in your shader, you're telling OpenGL that you want to represent the texture coordinates as 0 to width of texture and 0 to height of texture rather than using normalized (0-1) coordinates in both directions. A shift of 0.2 might be hard to notice on a large texture, as it's less than 1 texel. If you want to move it by 20% of the width, you need to pass in the texture width and height to the shader and calculate it (or just pass in what 20% of the width is)." ContentLicense="CC BY-SA 3.0" />
  <row Id="19591" PostHistoryTypeId="5" PostId="2045" RevisionGUID="a667858b-37f1-48ca-89a7-6a6982f65c0c" CreationDate="2018-04-28T03:07:14.553" UserId="93" Comment="deleted 2 characters in body" Text="You definitely want to check out meticulous half to float and float to half implementations by Fabian Giesen. I don't think there is anything faster than those:&#xD;&#xA;https://gist.github.com/rygorous/2144712&#xD;&#xA;https://gist.github.com/rygorous/2156668&#xD;&#xA;&#xD;&#xA;For other formats you will find an implementation in DirectXMath (part of WindowsSDK), Mesa and similar libraries. For example, R11G11B10_Float conversions are implemented by DirectXMath in [XMFLOAT3PK][1] and by Mesa in [u_format_other.c][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xmfloat3pk(v=vs.85).aspx&#xD;&#xA;  [2]: https://github.com/grate-driver/mesa/blob/master/src/gallium/auxiliary/util/u_format_other.c" ContentLicense="CC BY-SA 3.0" />
  <row Id="19592" PostHistoryTypeId="5" PostId="7561" RevisionGUID="a221dd07-290e-4d09-a17d-455ef2a4f111" CreationDate="2018-04-28T04:01:58.617" UserId="3003" Comment="added 60 characters in body" Text="When you use `GL_TEXTURE_RECTANGLE` in your source code and `texture2DRect()` in your shader, you're telling OpenGL that you want to represent the texture coordinates as 0 to width of texture and 0 to height of texture rather than using normalized (0-1) coordinates in both directions, which you would get with `GL_TEXTURE_2D` and `texture2D()`. A shift of 0.2 might be hard to notice on a large texture, as it's less than 1 texel. If you want to move it by 20% of the width, you need to pass in the texture width and height to the shader and calculate it (or just pass in what 20% of the width is)." ContentLicense="CC BY-SA 3.0" />
  <row Id="19601" PostHistoryTypeId="5" PostId="362" RevisionGUID="fbe81219-f539-4e77-ab9a-a202ceff3d82" CreationDate="2018-04-29T14:50:38.500" UserId="4647" Comment="Fix the link" Text="I've been reading the following article on how to do a parallel scan in CUDA:&#xD;&#xA;&#xD;&#xA;https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch39.html&#xD;&#xA;&#xD;&#xA;In the article, there is an emphasis on making the scan &quot;work efficient&quot;. In other words, a GPU algorithm should perform no more additions than a CPU algorithm, O(n). The authors present two algorithms, one &quot;naive&quot; that does O(nlogn) additions, and one that they consider &quot;work efficient&quot;. However, the work efficient algorithm does twice as many loop iterations.&#xD;&#xA;&#xD;&#xA;From my understanding, GPUs are simply giant SIMD processors and should operate in lock-step. Doing twice as many loops in the &quot;work efficient&quot; algorithm seems to imply that many threads will be idle and decrease performance in the long run. What am I  missing?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19602" PostHistoryTypeId="24" PostId="362" RevisionGUID="fbe81219-f539-4e77-ab9a-a202ceff3d82" CreationDate="2018-04-29T14:50:38.500" Comment="Proposed by 4647 approved by 48, 231 edit id of 413" ContentLicense="CC BY-SA 3.0" />
  <row Id="19604" PostHistoryTypeId="2" PostId="7564" RevisionGUID="708d63c1-97df-4d13-882a-6290f71938e8" CreationDate="2018-04-29T19:33:40.217" UserId="8448" Text="The lightmap representation used in Valve's stuff, like any finite-storage representation of the surfaces response to light, is only approximate, and the error in the approximation is higher or lower in different scenarios.&#xD;&#xA;&#xD;&#xA;Since it doesn't store the light in a direction tangent to the surface (where it would be exactly zero), you don't get an exact zero for this case. However, this isn't that important:&#xD;&#xA;&#xD;&#xA;- Normal maps generated from height maps will never yield a normal vector exactly perpendicular to the geometry, and tend not to be not that steep anyway.&#xD;&#xA;- The 3 generated lightmaps are normalized so that their sum is equal to the light for the &quot;straight up&quot; direction. This reduces directional contrast, but also eliminates light from the tangent direction." ContentLicense="CC BY-SA 3.0" />
  <row Id="19610" PostHistoryTypeId="4" PostId="5558" RevisionGUID="c336b673-0b53-4c5d-8768-d3cb692d2779" CreationDate="2018-04-30T18:38:54.110" UserId="7000" Comment="edited title" Text="Why do I need memory barrier when doing atomic operations?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19611" PostHistoryTypeId="5" PostId="5550" RevisionGUID="0a858779-3900-4cc7-a003-bd3db32d3bc7" CreationDate="2018-04-30T18:40:07.433" UserId="7000" Comment="edited body" Text="In [the documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferStorage.xhtml) I see that the final parameter for `glNamedBufferStorage` is `flags` and that `flags`:&#xD;&#xA;&#xD;&#xA;&gt; Specifies the intended usage of the buffer's data store. Must be a bitwise combination of the following flags. GL_DYNAMIC_STORAGE_BIT, GL_MAP_READ_BIT GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT, GL_MAP_COHERENT_BIT, and GL_CLIENT_STORAGE_BIT.&#xD;&#xA;&#xD;&#xA;However, in the older `glBufferData` we use to specify a `usage` flag which would include things such as `GL_STATIC_DRAW` to specify expected usage patterns.&#xD;&#xA;&#xD;&#xA;Where do we include that with the newer OpenGL?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19612" PostHistoryTypeId="4" PostId="5381" RevisionGUID="00ab44b4-740a-4e36-a983-f14f4c90017c" CreationDate="2018-04-30T18:41:31.870" UserId="7000" Comment="edited title" Text="How to use textures with DSA?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19613" PostHistoryTypeId="4" PostId="5368" RevisionGUID="66d81dc1-cac5-47e9-ae94-d73a877e550b" CreationDate="2018-04-30T18:42:01.773" UserId="7000" Comment="edited title" Text="Different result with DSA (vertexArrayVertexBuffer, vertexArrayAttribBinding) than with glBufferData" ContentLicense="CC BY-SA 3.0" />
  <row Id="19614" PostHistoryTypeId="2" PostId="7565" RevisionGUID="c53be834-6ff3-454d-8282-792546ff04b1" CreationDate="2018-05-01T12:08:34.603" UserId="8651" Text="I have a running particle system which emits particles in a given radius. Now I want to add some gravity to it. The particles and velocities of each particle is saved in a 2D Texture, now I want another 2D Texture, where I can save the gravity, but i'm missing the knowledge to do so.&#xD;&#xA;What's the actual formula on creating some gravitation or how can it be simulated?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19615" PostHistoryTypeId="1" PostId="7565" RevisionGUID="c53be834-6ff3-454d-8282-792546ff04b1" CreationDate="2018-05-01T12:08:34.603" UserId="8651" Text="Gravitational calculation of a particle via GLSL / WebGL" ContentLicense="CC BY-SA 3.0" />
  <row Id="19616" PostHistoryTypeId="3" PostId="7565" RevisionGUID="c53be834-6ff3-454d-8282-792546ff04b1" CreationDate="2018-05-01T12:08:34.603" UserId="8651" Text="|glsl|webgl|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19617" PostHistoryTypeId="5" PostId="7565" RevisionGUID="6b9aaa81-7a36-41ac-85b2-64b6977119f8" CreationDate="2018-05-01T12:15:45.813" UserId="8651" Comment="added 426 characters in body" Text="I have a running particle system which emits particles in a given radius. Now I want to add some gravity to it. The particles and velocities of each particle is saved in a 2D Texture, now I want another 2D Texture, where I can save the gravity, but i'm missing the knowledge to do so.&#xD;&#xA;What's the actual formula on creating some gravitation or how can it be simulated?&#xD;&#xA;&#xD;&#xA;For example to save particle's vel, I have&#xD;&#xA;    `uniform sampler2D pv;`&#xD;&#xA;which is just an image which outputs an image and takes the output as input into the shader. (Kind of transform feedback)&#xD;&#xA;&#xD;&#xA;`uniform float spread;&#xD;&#xA;vec2 vel = ...;&#xD;&#xA;gl_FragColor = vec4(spread*vel, 0.0, 0.0);`&#xD;&#xA;&#xD;&#xA;(Part of my code)&#xD;&#xA;&#xD;&#xA;And now I simply want another `uniform sampler2D pg;` which holds gravity and right here, I'm missing the math...&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19618" PostHistoryTypeId="2" PostId="7566" RevisionGUID="25f95498-4e58-40b0-98ea-37a9c5ce01d1" CreationDate="2018-05-01T18:56:36.970" UserId="6698" Text="I am trying to implement rough dielectrics on my renderer. I compared the results of my renderer and Mitsuba renderer. However, a thin glass plate which is a cube scaled by (0.4, 0.4, 0.01) magnifies the object in front of it in Mitsuba while it does not magnify in my renderer. Do I miss something or does Mitsuba renderer do something wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Result of my renderer][1]][1]&#xD;&#xA;&#xD;&#xA;[![Result of mitsuba][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4r0rF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A6vLt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19619" PostHistoryTypeId="1" PostId="7566" RevisionGUID="25f95498-4e58-40b0-98ea-37a9c5ce01d1" CreationDate="2018-05-01T18:56:36.970" UserId="6698" Text="Can a glass plate act like a lens?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19620" PostHistoryTypeId="3" PostId="7566" RevisionGUID="25f95498-4e58-40b0-98ea-37a9c5ce01d1" CreationDate="2018-05-01T18:56:36.970" UserId="6698" Text="|raytracing|pathtracing|global-illumination|refraction|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19621" PostHistoryTypeId="5" PostId="7566" RevisionGUID="9cf403dd-2de2-43e1-afb2-7ebcfa6eda0b" CreationDate="2018-05-01T19:08:25.637" UserId="6698" Comment="forgot to indicate refractive index of the material" Text="I am trying to implement rough dielectrics on my renderer. I compared the results of my renderer and Mitsuba renderer. However, a thin glass plate which is a cube scaled by (0.4, 0.4, 0.01) magnifies the object in front of it in Mitsuba while it does not magnify in my renderer. Do I miss something or does Mitsuba renderer do something wrong?&#xD;&#xA;&#xD;&#xA;edit: IOR of glass is 1.1 and outside is air.&#xD;&#xA;&#xD;&#xA;Result of my renderer:&#xD;&#xA;[![Result of my renderer][1]][1]&#xD;&#xA;&#xD;&#xA;Result of mitsuba:&#xD;&#xA;[![Result of mitsuba][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4r0rF.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A6vLt.png" ContentLicense="CC BY-SA 3.0" />
  <row Id="19622" PostHistoryTypeId="2" PostId="7567" RevisionGUID="2e91d6f6-5c4d-4cb2-84d9-75bafa70538b" CreationDate="2018-05-01T20:05:48.497" UserId="6046" Text="so I am in the process of making my own GPU path tracer based on OpenCL as part of my bachelor thesis. I have already made a CPU and a GPU ray tracer based on OpenGL compute shaders but all I have ray-traced are simple spheres and planes.&#xD;&#xA;&#xD;&#xA;1) Onto the main question, what do I need to path trace actual models like the teapot/dragon etc. Are there any standard, well known libraries for this purpose? Or do I have to write my own model loader? &#xD;&#xA;&#xD;&#xA;Writing my own loader seems all nice but I won't just have to read the data but maintain a proper data structure for all the triangles (K-d tree or octree perhaps) as well and then pass that structured data onto the GPU. If there is a library that can give me the data structure it'd be nice as I'll have to write the code for traversing it on the GPU only as I have already written one to traverse octrees for my GPU raytracer.&#xD;&#xA;" ContentLicense="CC BY-SA 3.0" />
  <row Id="19623" PostHistoryTypeId="1" PostId="7567" RevisionGUID="2e91d6f6-5c4d-4cb2-84d9-75bafa70538b" CreationDate="2018-05-01T20:05:48.497" UserId="6046" Text="Path Tracer - Model loading Libraries?" ContentLicense="CC BY-SA 3.0" />
  <row Id="19624" PostHistoryTypeId="3" PostId="7567" RevisionGUID="2e91d6f6-5c4d-4cb2-84d9-75bafa70538b" CreationDate="2018-05-01T20:05:48.497" UserId="6046" Text="|pathtracing|geometry|model|" ContentLicense="CC BY-SA 3.0" />
  <row Id="19626" PostHistoryTypeId="2" PostId="7568" RevisionGUID="2d38a9c8-97d2-4694-9b25-860ce4fb9e60" CreationDate="2018-05-02T02:35:24.490" UserId="3073" Text="AssImp library may be a good choice for you, assuming you are using C++ ?. It supports a decent number of model formats.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.assimp.org" ContentLicense="CC BY-SA 4.0" />
  <row Id="19627" PostHistoryTypeId="2" PostId="7569" RevisionGUID="2b4b443d-3600-49f6-8775-1962cb0b7809" CreationDate="2018-05-02T05:47:49.847" UserId="48" Text="The `box.obj` file has no vertex normals, and by default Mitsuba will generate smooth normals for OBJ files that don't specify their own normals. This creates the magnification effect: the box with smooth normals forms a convex lens!&#xD;&#xA;&#xD;&#xA;By adding this line to the box object in the scene file:&#xD;&#xA;&#xD;&#xA;    &lt;boolean name=&quot;faceNormals&quot; value=&quot;true&quot;/&gt;&#xD;&#xA;&#xD;&#xA;I got results that look equivalent to yours:&#xD;&#xA;&#xD;&#xA;![Mitsuba render with face normals][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LNG6X.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19628" PostHistoryTypeId="5" PostId="6053" RevisionGUID="55f4223b-23f1-403a-8da1-3124a2dd3bf7" CreationDate="2018-05-02T13:23:09.923" UserId="6541" Comment="added 48 characters in body" Text="![image](https://user-images.githubusercontent.com/16706911/34399964-ae3c684a-eba1-11e7-95f1-2696a37b650c.JPG)&#xD;&#xA;&#xD;&#xA;I used [Stencil Buffer](https://docs.unity3d.com/Manual/SL-Stencil.html) to fixing your problem , you need a way for checking [overlapping two or more shapes][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     Shader &quot;Custom/SemiTransparent&quot;&#xD;&#xA;    {&#xD;&#xA;        Properties&#xD;&#xA;        {&#xD;&#xA;    		_Color(&quot;Color&quot;,Color) = (0,0,1,0.1)&#xD;&#xA;        }&#xD;&#xA;        SubShader&#xD;&#xA;        {&#xD;&#xA;    Tags {&quot;Queue&quot;=&quot;Transparent&quot; &quot;IgnoreProjector&quot;=&quot;true&quot; &quot;RenderType&quot;=&quot;Transparent&quot;}&#xD;&#xA;    ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off&#xD;&#xA;    &#xD;&#xA;            LOD 100&#xD;&#xA;    &#xD;&#xA;            Pass&#xD;&#xA;            {&#xD;&#xA;                Stencil {&#xD;&#xA;                    Ref 0&#xD;&#xA;                    Comp Equal&#xD;&#xA;                    Pass IncrSat &#xD;&#xA;                    Fail IncrSat &#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                CGPROGRAM&#xD;&#xA;                #pragma vertex vert&#xD;&#xA;                #pragma fragment frag&#xD;&#xA;    &#xD;&#xA;                #include &quot;UnityCG.cginc&quot;&#xD;&#xA;    &#xD;&#xA;    			fixed4 _Color;&#xD;&#xA;    &#xD;&#xA;                struct appdata&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                struct v2f&#xD;&#xA;                {&#xD;&#xA;                    float4 vertex : SV_POSITION;&#xD;&#xA;                };&#xD;&#xA;    &#xD;&#xA;                v2f vert (appdata v)&#xD;&#xA;                {&#xD;&#xA;                    v2f o;&#xD;&#xA;                    o.vertex = UnityObjectToClipPos(v.vertex);&#xD;&#xA;                    return o;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                fixed4 frag (v2f i) : SV_Target&#xD;&#xA;                {&#xD;&#xA;                    fixed4 col = _Color;&#xD;&#xA;                    return col;&#xD;&#xA;                }&#xD;&#xA;                ENDCG&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/35574227/unity-shader-highlighting-overlaps" ContentLicense="CC BY-SA 4.0" />
  <row Id="19629" PostHistoryTypeId="2" PostId="7570" RevisionGUID="8f0636f4-30ba-49d7-90bd-5d0e8f9689d1" CreationDate="2018-05-03T03:56:47.520" UserId="8660" Text="I'd like to understand how the process of building the &quot;tangent space&quot; matrix for [normal mapping][1] works. I'm following several tutorials, and other stackexchange questions, but I'm unfamiliar with the math involved, and a lot of resources seem to be telling me &quot;just do this and it'll work&quot;.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;According to [the LearnOpenGL tutorial][2], you should build your tangent space matrix with the following code:&#xD;&#xA;&#xD;&#xA;    vec3 T = normalize(vec3(model * vec4(aTangent,   0.0)));&#xD;&#xA;    vec3 B = normalize(vec3(model * vec4(aBitangent, 0.0)));&#xD;&#xA;    vec3 N = normalize(vec3(model * vec4(aNormal,    0.0)));&#xD;&#xA;    mat3 TBN = mat3(T, B, N)&#xD;&#xA;&#xD;&#xA;The first three lines are variations of:&#xD;&#xA;&#xD;&#xA;    vec3 worldSpaceVec = normalize(vec3(modelMatrix * vec4(modelSpaceVec, 0)));&#xD;&#xA;&#xD;&#xA;Other implementations I've seen do:&#xD;&#xA;&#xD;&#xA;    vec3 worldSpaceVec = normalize(mat3(modelMatrix) * modelSpaceVec);&#xD;&#xA;&#xD;&#xA;(by the way, I'm not sure I visualize why the LearnOpenGL tutorial doesn't use `vec4(modelSpaceVec, 1)`; I'm not sure what either value would represent or how it would change the results. I assume this just a property of normals that we always represent them with a `w` of 0, but I don't get why it applies to the tangent and bitangent)&#xD;&#xA;&#xD;&#xA;But more importantly, I don't understand the `modelMatrix * ...` part of the equation. According to [this answer][3], normals are bivectors, a different type of data which is represented by a row matrix instead of a column matrix (that is, bivectors are $\begin{bmatrix} x &amp; y &amp; z \end{bmatrix}$ where vectors are$\begin{bmatrix} x \\ y \\ z \end{bmatrix}$).&#xD;&#xA;&#xD;&#xA;If my understanding is correct, then normals are of a different type than regular vectors, just like kilograms and liters are similar but different types; and they need to be treated differently in regard to transformations. So why does the tutorial use:&#xD;&#xA;&#xD;&#xA;    vec3 worldSpaceVec = normalize(vec3(modelMatrix * vec4(modelSpaceVec, 0)));&#xD;&#xA;&#xD;&#xA;and not&#xD;&#xA;&#xD;&#xA;    vec3 worldSpaceVec = inverse(transpose(modelMatrix)) * modelSpaceVec;&#xD;&#xA;&#xD;&#xA;or even&#xD;&#xA;&#xD;&#xA;    vec3 worldSpaceVec = inverse(transpose(mvpMatrix)) * modelSpaceVec;&#xD;&#xA;&#xD;&#xA;?&#xD;&#xA;&#xD;&#xA;In other words, should the tangent and bitangent vectors of a vertex be converted from one space to another using the same transformation matrix as the vertex's normal vector, and if so, why?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Normal_mapping&#xD;&#xA;  [2]: https://learnopengl.com/Advanced-Lighting/Normal-Mapping&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/1506/8660" ContentLicense="CC BY-SA 4.0" />
  <row Id="19630" PostHistoryTypeId="1" PostId="7570" RevisionGUID="8f0636f4-30ba-49d7-90bd-5d0e8f9689d1" CreationDate="2018-05-03T03:56:47.520" UserId="8660" Text="How do I build my tangent space matrix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19631" PostHistoryTypeId="3" PostId="7570" RevisionGUID="8f0636f4-30ba-49d7-90bd-5d0e8f9689d1" CreationDate="2018-05-03T03:56:47.520" UserId="8660" Text="|transformations|matrix|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19632" PostHistoryTypeId="2" PostId="7571" RevisionGUID="b6f8af40-7623-4cad-9362-b319e0fc0dce" CreationDate="2018-05-03T06:52:28.357" UserId="7008" Text="In Normal Mapping, you want to go to &quot;Tangent Space&quot;, that is the space where the center of the coordinate system is your Vertex (/Fragment). Just like you go from Model Space to World Space and from World Space to Eye Space, you can go to Tangent Space with a matrix multiplication.&#xD;&#xA;&#xD;&#xA;In Tangent Space, the vector $n_T=\left(\begin{array}{c}0\\0\\1\end{array}\right)$ is always the Normal - since you read the normal $n_N$ out of the Normal Map in your Fragment Shader, you will obviously not use $n_T$ but $n_N$ for lighting calculations and this choice of $n_N$ rather than $n_T$ brings about the nice effect normal mapping has.&#xD;&#xA;&#xD;&#xA;What's a bit special is that every vertex has its own Tangent Space, which is why you need the tangent, bitangent$^1$ and (geometry) normal of every vertex to construct your TBN matrix.&#xD;&#xA;&#xD;&#xA;So much for theory - since you didn't really ask about that specifically, I assume you understand this (otherwise just edit your question).&#xD;&#xA;&#xD;&#xA;&gt; by the way, I'm not sure I visualize why the LearnOpenGL tutorial doesn't use vec4(modelSpaceVec, 1); I'm not sure what either value would represent or how it would change the results. I assume this just a property of normals that we always represent them with a w of 0, but I don't get why it applies to the tangent and bitangent&#xD;&#xA;&#xD;&#xA;Vectors in general are represented with a $0$ in the $w$ coordinate. If you look into a translation matrix, you will notice that the last row is the one that moves points around. For vectors, this is not a wanted behaviour - a vector is the same, no matter where, since it is a direction. So to avoid &quot;translating&quot; a vector, you set the $w$ coordinate to $0$. Since your tangent and bitangent vectors are vectors, the $w$ coordinate is $0$ here as well. &#xD;&#xA;&#xD;&#xA;&gt; But more importantly, I don't understand the modelMatrix * ... part of the equation.&#xD;&#xA;&#xD;&#xA;Using the the model matrix $M$ at this point is correct in *most* cases - but not all of them. The normal matrix $N$ is (as the answer correctly said) the inverse transpose of the model matrix. But, since normals are vectors, you don't need a 4x4 matrix, a 3x3 matrix is just fine. And if you leave out that translation part, and you scale the same amount in all three coordinates, then the transpose of your model matrix is the same as the inverse of your model matrix. Therefore you get:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;N = (M^{-1})^T = (M^T)^T = M&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And that is why in most cases (i.e. everytime you use the same scaling in every coordinate) the normal matrix is the same as the model matrix.&#xD;&#xA;&#xD;&#xA;&gt; `vec3 worldSpaceVec = inverse(transpose(modelMatrix)) * modelSpaceVec;`&#xD;&#xA;&#xD;&#xA;This is correct, however&#xD;&#xA;&#xD;&#xA;&gt; `vec3 worldSpaceVec = inverse(transpose(mvpMatrix)) * modelSpaceVec;`&#xD;&#xA;&#xD;&#xA;this is not correct. Once you have transformed your normals into world space, you *need to* use the same view and projection matrix as before. Your view matrix brings your viewer into the origin (or rather it moves everything such that your viewer is the origin), inverse transposing this doesn't make sense (and similarly it doesn't make sense for the projection matrix. plus, the order in matrix multiplications is important, which is the next problem... don't do it ;-) )&#xD;&#xA;&#xD;&#xA;Now, since you know that the model matrix *may* be the same as the normal matrix, you can (mathematically correctly) just go with the inverse transpose of the model matrix. Obviously this costs quite a lot of performance, especially inverting a matrix is costly. It is therefore more efficient to just go with the model matrix.&#xD;&#xA;&#xD;&#xA;&gt; In other words, should the tangent and bitangent vectors of a vertex be converted from one space to another using the same transformation matrix as the vertex's normal vector, and if so, why?&#xD;&#xA;&#xD;&#xA;Unlike normals, tangent and bitangent vectors should be transformed with the model matrix, independently of the whether the normal matrix equals the modal matrix. A normal is always supposed to be perpendicular to a surface, and that's why simply taking the model matrix may be incorrect - in some cases the normal matrix would not be perpendicular to the surface anymore. Tangents however are always &quot;lying&quot; on the surface, so if you rotate a surface, the tangent must be rotated the same way to still &quot;lie&quot; on the surface.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;$^1$ Sometimes this is called *binormal*, however Eric Lengyel explains why this is an incorrect term in [Mathematics for 3D Game Programming and Computer Graphics][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathfor3dgameprogramming.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="19633" PostHistoryTypeId="5" PostId="7571" RevisionGUID="931d1e4c-6ae3-44ff-b5b7-bbaecd609f9b" CreationDate="2018-05-03T07:02:19.550" UserId="8660" Comment="Reformulate a sentence for clarity" Text="In Normal Mapping, you want to go to &quot;Tangent Space&quot;, that is the space where the center of the coordinate system is your Vertex (/Fragment). Just like you go from Model Space to World Space and from World Space to Eye Space, you can go to Tangent Space with a matrix multiplication.&#xD;&#xA;&#xD;&#xA;In Tangent Space, the vector $n_T=\left(\begin{array}{c}0\\0\\1\end{array}\right)$ is always the Normal - since you read the normal $n_N$ out of the Normal Map in your Fragment Shader, you will obviously not use $n_T$ but $n_N$ for lighting calculations and this choice of $n_N$ rather than $n_T$ brings about the nice effect normal mapping has.&#xD;&#xA;&#xD;&#xA;What's a bit special is that every vertex has its own Tangent Space, which is why you need the tangent, bitangent$^1$ and (geometry) normal of every vertex to construct your TBN matrix.&#xD;&#xA;&#xD;&#xA;So much for theory - since you didn't really ask about that specifically, I assume you understand this (otherwise just edit your question).&#xD;&#xA;&#xD;&#xA;&gt; by the way, I'm not sure I visualize why the LearnOpenGL tutorial doesn't use vec4(modelSpaceVec, 1); I'm not sure what either value would represent or how it would change the results. I assume this just a property of normals that we always represent them with a w of 0, but I don't get why it applies to the tangent and bitangent&#xD;&#xA;&#xD;&#xA;Vectors in general are represented with a $0$ in the $w$ coordinate. If you look into a translation matrix, you will notice that the last row is the one that moves points around. For vectors, this is not a wanted behaviour - a vector is the same, no matter where, since it is a direction. So to avoid &quot;translating&quot; a vector, you set the $w$ coordinate to $0$. Since your tangent and bitangent vectors are vectors, the $w$ coordinate is $0$ here as well. &#xD;&#xA;&#xD;&#xA;&gt; But more importantly, I don't understand the modelMatrix * ... part of the equation.&#xD;&#xA;&#xD;&#xA;Using the the model matrix $M$ at this point is correct in *most* cases - but not all of them. The normal matrix $N$ is (as the answer you linked correctly said) the inverse transpose of the model matrix. But, since normals are vectors, you don't need a 4x4 matrix, a 3x3 matrix is just fine. And if you leave out that translation part, and you scale the same amount in all three coordinates, then the transpose of your model matrix is the same as the inverse of your model matrix. Therefore you get:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;N = (M^{-1})^T = (M^T)^T = M&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And that is why in most cases (i.e. everytime you use the same scaling in every coordinate) the normal matrix is the same as the model matrix.&#xD;&#xA;&#xD;&#xA;&gt; `vec3 worldSpaceVec = inverse(transpose(modelMatrix)) * modelSpaceVec;`&#xD;&#xA;&#xD;&#xA;This is correct, however&#xD;&#xA;&#xD;&#xA;&gt; `vec3 worldSpaceVec = inverse(transpose(mvpMatrix)) * modelSpaceVec;`&#xD;&#xA;&#xD;&#xA;this is not correct. Once you have transformed your normals into world space, you *need to* use the same view and projection matrix as before. Your view matrix brings your viewer into the origin (or rather it moves everything such that your viewer is the origin), inverse transposing this doesn't make sense (and similarly it doesn't make sense for the projection matrix. plus, the order in matrix multiplications is important, which is the next problem... don't do it ;-) )&#xD;&#xA;&#xD;&#xA;Now, since you know that the model matrix *may* be the same as the normal matrix, you can (mathematically correctly) just go with the inverse transpose of the model matrix. Obviously this costs quite a lot of performance, especially inverting a matrix is costly. It is therefore more efficient to just go with the model matrix.&#xD;&#xA;&#xD;&#xA;&gt; In other words, should the tangent and bitangent vectors of a vertex be converted from one space to another using the same transformation matrix as the vertex's normal vector, and if so, why?&#xD;&#xA;&#xD;&#xA;Unlike normals, tangent and bitangent vectors should be transformed with the model matrix, independently of the whether the normal matrix equals the modal matrix. A normal is always supposed to be perpendicular to a surface, and that's why simply taking the model matrix may be incorrect - in some cases the normal matrix would not be perpendicular to the surface anymore. Tangents however are always &quot;lying&quot; on the surface, so if you rotate a surface, the tangent must be rotated the same way to still &quot;lie&quot; on the surface.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;$^1$ Sometimes this is called *binormal*, however Eric Lengyel explains why this is an incorrect term in [Mathematics for 3D Game Programming and Computer Graphics][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.mathfor3dgameprogramming.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="19634" PostHistoryTypeId="24" PostId="7571" RevisionGUID="931d1e4c-6ae3-44ff-b5b7-bbaecd609f9b" CreationDate="2018-05-03T07:02:19.550" Comment="Proposed by 8660 approved by 7008 edit id of 414" ContentLicense="CC BY-SA 4.0" />
  <row Id="19636" PostHistoryTypeId="2" PostId="7572" RevisionGUID="ca247bde-9912-4202-b442-aa1f352d2d10" CreationDate="2018-05-03T23:48:12.623" UserId="8595" Text="I'm wondering whether some of you would have tested and seen quite a difference in using a compressed texture even when the OpenGL environment does not need saving any memory (i.e. the card has more memory than necessary to support the textures uncompressed.)&#xD;&#xA;&#xD;&#xA;I'm thinking that a compressed texture would use less RAM and thus reading it and decompressing in the GPU would be faster because the number of memory accesses is lower. Whereas, a non-compressed texture would rely more on memory access (GPU I/O) than processing and that is likely slower.&#xD;&#xA;&#xD;&#xA;The main things I've read about texture compression has been about how the compression saves space. Not so much about how it can save execution time with the GPU. (Note that I specifically will be using an nVidia, Pascal for now. But I would hope that it works similarly whatever the GPU.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="19637" PostHistoryTypeId="1" PostId="7572" RevisionGUID="ca247bde-9912-4202-b442-aa1f352d2d10" CreationDate="2018-05-03T23:48:12.623" UserId="8595" Text="If I have more than enough memory, can it still be beneficial to use compressed textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19638" PostHistoryTypeId="3" PostId="7572" RevisionGUID="ca247bde-9912-4202-b442-aa1f352d2d10" CreationDate="2018-05-03T23:48:12.623" UserId="8595" Text="|opengl|texture|gpu|opengl-es|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19642" PostHistoryTypeId="2" PostId="7574" RevisionGUID="65f0b41e-141a-4b8d-ab77-1c76a198ad2a" CreationDate="2018-05-04T05:21:19.980" UserId="3003" Text="Gravity is a form of acceleration. So what I've done in the past is continually add it into the velocity. On each frame, for each particle, I'd do something like this:&#xD;&#xA;&#xD;&#xA;    // Gravitational acceleration, adjust as necessary&#xD;&#xA;    const vec2 gravity = vec2(0.0, -9.8);&#xD;&#xA;    &#xD;&#xA;    // Calculate the new velocity for the particle &#xD;&#xA;    velocity = (particleVelocity + gravity) * timeDelta;&#xD;&#xA;    &#xD;&#xA;    // Calculate the new position given the new velocity&#xD;&#xA;    newParticlePosition = particlePosition + velocity;&#xD;&#xA;    &#xD;&#xA;    // Update our parameters for the next time around&#xD;&#xA;    particleVelocity = velocity / timeDelta;&#xD;&#xA;    particlePosition = newParticlePosition;&#xD;&#xA;&#xD;&#xA;In this case `timeDelta` is the fraction of a second between the previous frame and the current frame. So if you're running your animation at 60 fps, it would be 1.0 / 60.0 = 0.01666…&#xD;&#xA;&#xD;&#xA;I'm not sure that using a texture for the gravity would help you here as gravity is usually a constant when you're close to the surface of the planet, as it sounds like your particles are from the description given." ContentLicense="CC BY-SA 4.0" />
  <row Id="19643" PostHistoryTypeId="2" PostId="7575" RevisionGUID="ecfde280-4b5c-411b-829a-c1c16b6093e3" CreationDate="2018-05-04T07:41:48.027" UserId="8607" Text="Is there a technique for implementing non-point lights (i.e. light that has actual physical dimensions)?&#xD;&#xA;&#xD;&#xA;I can't think of anything except than making a light source out of multiple point lights, but that doesn't seem feasible for real-time rendering." ContentLicense="CC BY-SA 4.0" />
  <row Id="19644" PostHistoryTypeId="1" PostId="7575" RevisionGUID="ecfde280-4b5c-411b-829a-c1c16b6093e3" CreationDate="2018-05-04T07:41:48.027" UserId="8607" Text="Non-point lights" ContentLicense="CC BY-SA 4.0" />
  <row Id="19645" PostHistoryTypeId="3" PostId="7575" RevisionGUID="ecfde280-4b5c-411b-829a-c1c16b6093e3" CreationDate="2018-05-04T07:41:48.027" UserId="8607" Text="|shader|glsl|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19646" PostHistoryTypeId="2" PostId="7576" RevisionGUID="390429f4-dd87-4ca6-ab2f-3f68bf065b47" CreationDate="2018-05-04T08:07:02.187" UserId="7008" Text="Yes, there are other physically based lighting concepts. You can have a look at image based lighting and Area Lights (such as Sphere or Tube lights). &#xD;&#xA;&#xD;&#xA;If you have access, have look into [Physically Based Rendering][1], if i recall correctly, that has a chapter or two about non-point lights.&#xD;&#xA;Free on the internet is for example [Real Shading in Unreal Engine 4][2]. Furthermore, there is the [Physically Based Lighting at Pixar][3] paper, although I am not sure how real-time suitable this is.&#xD;&#xA;&#xD;&#xA;This should give you a starting point into the topic. You should read up on it and then perhaps come back, if you have more detailed questions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbrt.org/&#xD;&#xA;  [2]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [3]: https://graphics.pixar.com/library/PhysicallyBasedLighting/paper.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19647" PostHistoryTypeId="5" PostId="1513" RevisionGUID="6b41c9ad-58a7-49c8-8601-64805c3cdb82" CreationDate="2018-05-04T08:45:36.440" UserId="385" Comment="Fixed typo" Text="The classical way of shading surfaces in real-time computer graphics is a combination of a (Lambertian) diffuse term and a specular term, most likely Phong or Blinn-Phong.&#xD;&#xA;&#xD;&#xA;[![Image from Wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;Now with the trend going towards physically-based rendering and thus material models in engines such as [Frostbite][2], [Unreal Engine][3] or [Unity 3D][3] these BRDFs have changed. For example (a pretty universal one at that), the latest Unreal Engine still uses Lambertian diffuse, but in combination with the Cook-Torrance microfacet model for specular reflection (specifically using GGX/Trowbridge-Reitz and a modified Slick approximation for the Fresnel term). Furthermore, a 'Metalness' value is being used to distinguish between conductor and dielectric.&#xD;&#xA;&#xD;&#xA;For dielectrics, diffuse is colored using the albedo of the material, while specular is always colorless. For metals, diffuse is not used and the specular term is multiplied with the albedo of the material.&#xD;&#xA;&#xD;&#xA;Regarding real-world physical materials, does the strict separation between diffuse and specular exist and if so, where does it come from? Why is one colored while the other is not? Why do conductors behave differently?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VOfxv.png&#xD;&#xA;  [2]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [3]: http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19648" PostHistoryTypeId="2" PostId="7577" RevisionGUID="83e51e1a-6319-49b6-a30d-3913f14613ac" CreationDate="2018-05-04T09:19:52.833" UserId="8547" Text="I am given an irregular geometry shape with its vertices, bounding box information.&#xD;&#xA;&#xD;&#xA;How to draw a smooth mesh equal distance from that irregular geometry shape's bounding box? &#xD;&#xA;&#xD;&#xA;Please refer to the image here:&#xD;&#xA;[![Smooth mesh equal distance from irregular shape][1]][1]&#xD;&#xA;&#xD;&#xA;My attempt:&#xD;&#xA;1) I have tried to create 8 spheres at 8 corners of a bounding box and a box for X, Y, Z direction. The result looks very ugly and not smooth like this:&#xD;&#xA;[![My attempt][2]][2]&#xD;&#xA;&#xD;&#xA;Is there any algorithm or formula I can utilise to draw mesh around a bounding box?&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SraGv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YFkz9.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19649" PostHistoryTypeId="1" PostId="7577" RevisionGUID="83e51e1a-6319-49b6-a30d-3913f14613ac" CreationDate="2018-05-04T09:19:52.833" UserId="8547" Text="how to draw mesh equal distance from irregular shape geometry bounding box" ContentLicense="CC BY-SA 4.0" />
  <row Id="19650" PostHistoryTypeId="3" PostId="7577" RevisionGUID="83e51e1a-6319-49b6-a30d-3913f14613ac" CreationDate="2018-05-04T09:19:52.833" UserId="8547" Text="|3d|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19651" PostHistoryTypeId="2" PostId="7578" RevisionGUID="f9d476a0-32a3-4b25-9031-e7de7ad0e8b0" CreationDate="2018-05-04T11:06:36.973" UserId="8672" Text="I don't understand how to normalize the BRDF.&#xD;&#xA;the constraint is that for each incoming ray, the exitant ray will be 1 at most&#xD;&#xA;ie integral of hemisphere of fr*cos(theta) where fr is the BRDF and theta&#xD;&#xA;is the elevation angle.&#xD;&#xA;the integral over hemisphere is:&#xD;&#xA;0 &lt; phi &lt; 2*pi&#xD;&#xA;0 &lt; theta &lt; pi/2&#xD;&#xA;&#xD;&#xA;for lambertian the brdf is uniform i.e fr = constant&#xD;&#xA;the integral is summed to 2*pi so the constant should be 2*pi.&#xD;&#xA;&#xD;&#xA;However, this is not the case.&#xD;&#xA;&#xD;&#xA;someone knows why?&#xD;&#xA;I saw answer here:&#xD;&#xA;https://computergraphics.stackexchange.com/questions/4322/why-normalise-lambertian-brdf-by-1-pi&#xD;&#xA;&#xD;&#xA;but I didn't understand it, why is it matter what the incoming ray is?&#xD;&#xA;&#xD;&#xA;let's assume the incoming ray comes in theta=0 so the value is 1 and the sum over the hemisphere is again 2*pi instead of pi.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19652" PostHistoryTypeId="1" PostId="7578" RevisionGUID="f9d476a0-32a3-4b25-9031-e7de7ad0e8b0" CreationDate="2018-05-04T11:06:36.973" UserId="8672" Text="BRDF normalization" ContentLicense="CC BY-SA 4.0" />
  <row Id="19653" PostHistoryTypeId="3" PostId="7578" RevisionGUID="f9d476a0-32a3-4b25-9031-e7de7ad0e8b0" CreationDate="2018-05-04T11:06:36.973" UserId="8672" Text="|brdf|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19654" PostHistoryTypeId="50" PostId="6365" RevisionGUID="461ed0ee-1d69-423b-9444-f1998edf6bdf" CreationDate="2018-05-04T11:35:57.417" UserId="-1" />
  <row Id="19658" PostHistoryTypeId="5" PostId="7578" RevisionGUID="8c0fbb90-1bb6-427d-9550-e85a9eb933b4" CreationDate="2018-05-04T12:02:52.727" UserId="7008" Comment="edited the mathematical expressions to be easier readable" Text="I don't understand how to normalize the BRDF.&#xD;&#xA;the constraint is that for each incoming ray, the exitant ray will be $1$ at most&#xD;&#xA;ie integral of hemisphere of $f_r\cdot\cos(\theta)$ where $f_r$ is the BRDF and $\theta$&#xD;&#xA;is the elevation angle.&#xD;&#xA;the integral over hemisphere is:&#xD;&#xA;&#xD;&#xA;$0 &lt; \phi &lt; 2\pi$&#xD;&#xA;&#xD;&#xA;$0 &lt; \theta &lt; \frac{\pi}{2}$&#xD;&#xA;&#xD;&#xA;for lambertian the brdf is uniform i.e $f_r$ = constant&#xD;&#xA;the integral is summed to $2\pi$ so the constant should be $2\pi$.&#xD;&#xA;&#xD;&#xA;However, this is not the case.&#xD;&#xA;&#xD;&#xA;someone knows why?&#xD;&#xA;I saw answer here:&#xD;&#xA;https://computergraphics.stackexchange.com/questions/4322/why-normalise-lambertian-brdf-by-1-pi&#xD;&#xA;&#xD;&#xA;but I didn't understand it, why is it matter what the incoming ray is?&#xD;&#xA;&#xD;&#xA;let's assume the incoming ray comes in $\theta=0$ so the value is $1$ and the sum over the hemisphere is again $2\pi$ instead of $\pi$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19659" PostHistoryTypeId="24" PostId="7578" RevisionGUID="8c0fbb90-1bb6-427d-9550-e85a9eb933b4" CreationDate="2018-05-04T12:02:52.727" Comment="Proposed by 7008 approved by 2041 edit id of 415" ContentLicense="CC BY-SA 4.0" />
  <row Id="19660" PostHistoryTypeId="2" PostId="7579" RevisionGUID="24ffbe67-2401-4441-a3de-c14aacd05b15" CreationDate="2018-05-04T13:57:42.957" UserId="2654" Text="Because memory bandwidth is not free.&#xD;&#xA;&#xD;&#xA;No matter how much RAM you have, it takes less time to read 1024 bytes than it does to read 1024 KB. Compressed textures, relative to 32-bpp, can offer compression ratios of 4:1 or better. That's at least one quarter of the memory bandwidth costs of fetching the texture.&#xD;&#xA;&#xD;&#xA;If your rendering uses lots of textures, reducing bandwidth pressure can improve performance.&#xD;&#xA;&#xD;&#xA;Alternatively, the more memory you have available, the more memory you can *use*. If you consider 1GB to be &quot;plenty of memory&quot;, then using compressed textures allows you to store the equivalent of maybe 2-3GB worth of textures. So now your textures can be larger, more detailed, or more varied, all within the same &quot;plenty of memory&quot; space.&#xD;&#xA;&#xD;&#xA;There's *never* enough memory; there's only a question of how much you're willing/able to use." ContentLicense="CC BY-SA 4.0" />
  <row Id="19661" PostHistoryTypeId="5" PostId="7579" RevisionGUID="e05c5d7a-7860-4293-9794-b63732ed2037" CreationDate="2018-05-04T16:16:49.260" UserId="2654" Comment="added 63 characters in body" Text="Because memory bandwidth is not free.&#xD;&#xA;&#xD;&#xA;No matter how much RAM you have, it takes less time to read 1024 bytes than it does to read 1024 KB. Compressed textures, relative to 32-bpp, can offer compression ratios of 4:1 or better. That's at least one quarter of the memory bandwidth costs of fetching the texture.&#xD;&#xA;&#xD;&#xA;If your rendering uses lots of textures, reducing bandwidth pressure can improve performance.&#xD;&#xA;&#xD;&#xA;Alternatively, the more memory you have available, the more memory you can *use*. If you consider 1GB to be &quot;plenty of memory&quot;, then using compressed textures allows you to store the equivalent of maybe 2-3GB worth of textures. So now your textures can be larger, more detailed, or more varied, all within the same &quot;plenty of memory&quot; space. Or you can use some of that reclaimed storage for more meshes.&#xD;&#xA;&#xD;&#xA;There's *never* enough memory; there's only a question of how much you're willing/able to use." ContentLicense="CC BY-SA 4.0" />
  <row Id="19665" PostHistoryTypeId="50" PostId="6370" RevisionGUID="c1c5adef-a073-4e8a-a8ba-380620afbe0d" CreationDate="2018-05-04T23:36:58.503" UserId="-1" />
  <row Id="19666" PostHistoryTypeId="2" PostId="7581" RevisionGUID="eb6571c4-9141-4f08-9e2b-c8617e045410" CreationDate="2018-05-04T23:42:54.507" UserId="8677" Text="Both the question and its answer is confusing. &#xD;&#xA;&#xD;&#xA;First of all the matrix you have &#xD;&#xA;&#xD;&#xA; [![The Look-At Matrix][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LV0gi.png&#xD;&#xA;&#xD;&#xA;is a column &quot;Look at&quot; view matrix rather than a model matrix. A correct column &quot;Look At&quot; model matrix would be &#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;side_x&amp;side_y&amp;side_z&amp;0\\&#xD;&#xA;up_x&amp;up_y&amp;up_z&amp;0\\&#xD;&#xA;Forward_x&amp;Forward_y&amp;Forward_z&amp;0\\&#xD;&#xA;eye_x&amp;eye_y&amp;eye_z&amp;1&#xD;&#xA;\end{bmatrix}^T$$, which is what the other answer is saying. This means that matrix in the book is the inverse of the matrix given by me and the other answer.&#xD;&#xA;&#xD;&#xA;First matrix will be used to transform the objects in the world space to the view space of the camera. Second matrix will be used to transform the camera from its local space to the world space such that camera is pointing at whatever the &quot;target&quot; vector is.&#xD;&#xA;&#xD;&#xA;There is nothing special about the second matrix, you can use it on a dog to point to food, provided its mouth is along the +z direction in its local space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So in summary, first matrix is a view matrix is used transform objects from world space to view and the second matrix is a regular model matrix which can be applied to any object in the scene to transform it from its local space to the &#xD;&#xA;world space with &quot;eye&quot; as its world position and +z direction looking at &quot;target&quot;.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="19667" PostHistoryTypeId="5" PostId="7581" RevisionGUID="818f3da5-4a5f-41ab-b12d-f24853afdbd2" CreationDate="2018-05-04T23:48:44.257" UserId="8677" Comment="added 114 characters in body" Text="Both the question and its answer is confusing. &#xD;&#xA;&#xD;&#xA;First of all the matrix you have &#xD;&#xA;&#xD;&#xA; [![The Look-At Matrix][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LV0gi.png&#xD;&#xA;&#xD;&#xA;is a column &quot;Look at&quot; view matrix rather than a model matrix. A correct column &quot;Look At&quot; model matrix would be &#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;side_x&amp;side_y&amp;side_z&amp;0\\&#xD;&#xA;up_x&amp;up_y&amp;up_z&amp;0\\&#xD;&#xA;Forward_x&amp;Forward_y&amp;Forward_z&amp;0\\&#xD;&#xA;eye_x&amp;eye_y&amp;eye_z&amp;1&#xD;&#xA;\end{bmatrix}^T$$, which is what the other answer is saying. This means that matrix in the book is the inverse of the matrix given by me and the other answer.&#xD;&#xA;&#xD;&#xA;First matrix will be used to transform the objects in the world space to the view space of the camera. Second matrix will be used to transform the camera from its local space to the world space such that camera is pointing at whatever the &quot;target&quot; vector is.&#xD;&#xA;&#xD;&#xA;There is nothing special about the second matrix, you can use it on a dog to point to food, provided its mouth is along the +z direction in its local space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So in summary, first matrix is a view matrix is used transform objects from world space to view and the second matrix is a regular model matrix which can be applied to any object in the scene to transform it from its local space to the &#xD;&#xA;world space with &quot;eye&quot; as its world position and +z direction looking at &quot;target&quot;.  &#xD;&#xA;&#xD;&#xA;There is nothing wrong with either matrices just that they are used for accomplishing total different tasking." ContentLicense="CC BY-SA 4.0" />
  <row Id="19668" PostHistoryTypeId="2" PostId="7582" RevisionGUID="d0d0416c-2607-4ee5-9fa0-95824ba691f6" CreationDate="2018-05-05T02:55:04.490" UserId="8595" Text="As @Quinchilion mentioned, the calculation is done using three weights applied to the color components:&#xD;&#xA;&#xD;&#xA;    luminance = color.r * r_weight + color.g * g_weight + color.b * b_weight;&#xD;&#xA;&#xD;&#xA;There are many coefficients that can be found on the internet, there are two sample in an old OpenGL note:&#xD;&#xA;&#xD;&#xA;https://www.opengl.org/archives/resources/code/samples/advanced/advanced97/notes/node140.html&#xD;&#xA;&#xD;&#xA;The weights that @Quinchilion presents in his answer are those used in the [JPEG compression][1]. (0.299, 0.587, 0.114) It's often referenced as the Digital standard or BT 601 luma (luminance) because it's used in many places in the computer world.&#xD;&#xA;&#xD;&#xA;The once proposed by SGI are (0.3086, 0.6094, 0.0820). These probably better apply to a CRT monitor.&#xD;&#xA;&#xD;&#xA;As shown in the link proposed by @Quinchilion and mentioned by @troy_s, the BT 709 uses (0.2126, 0.7152, 0.0722). This is what modern HDTV and monitors use. This is a video thing that happens in your video board or your monitor (it depends the type of connector you're using.)&#xD;&#xA;&#xD;&#xA;Older HDTV monitors use (0.212, 0.701, 0.087). I'm not too sure how you can know which one you have, though. They say 1035i. I'm not too sure when that changed, that is.&#xD;&#xA;&#xD;&#xA;So, the JPEG Y component calculation should definitely not be used if you're working on images being displayed on a monitor. And for monitor ones, the BT 709 is certainly the best choice today. If you work on a software that various people will use, having a preference screen where the end user can choose would be best (unless you want to be able to compare what they see and what you see software wise, then stick to one specific set of weights.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/YCbCr" ContentLicense="CC BY-SA 4.0" />
  <row Id="19669" PostHistoryTypeId="5" PostId="7582" RevisionGUID="64d7db17-380a-4dbf-940f-610eaf56796e" CreationDate="2018-05-05T03:54:21.360" UserId="8595" Comment="Fixed the reference to YCrCb  with YPbPr because the JPEG version is shrunk and translated and that's not what I've shown." Text="As @Quinchilion mentioned, the calculation is done using three weights applied to the color components:&#xD;&#xA;&#xD;&#xA;    luminance = color.r * r_weight + color.g * g_weight + color.b * b_weight;&#xD;&#xA;&#xD;&#xA;There are many coefficients that can be found on the internet, there are two sample in an old OpenGL note:&#xD;&#xA;&#xD;&#xA;https://www.opengl.org/archives/resources/code/samples/advanced/advanced97/notes/node140.html&#xD;&#xA;&#xD;&#xA;The weights that @Quinchilion presents in his answer are used in the [Analog YPbPr][1] (0.299, 0.587, 0.114) standard. It's also called BT 601 luma (a.k.a. &quot;luminance&quot;).&#xD;&#xA;&#xD;&#xA;The ones proposed by SGI (link above) are (0.3086, 0.6094, 0.0820). These probably better apply to a nice CRT color monitor.&#xD;&#xA;&#xD;&#xA;As shown in the link proposed by @Quinchilion and mentioned by @troy_s, the BT 709 uses (0.2126, 0.7152, 0.0722). This is what modern HDTV and monitors use. This is a video thing that happens in your video board or your monitor (it depends the type of connector you're using.)&#xD;&#xA;&#xD;&#xA;Older HDTV monitors use (0.212, 0.701, 0.087). I'm not too sure how you can know which one you have, though. They say 1035i is the cutoff.&#xD;&#xA;&#xD;&#xA;So, the analog video Y component calculation should definitely not be used if you're working on images being displayed on a modern 1080p or better monitor. The BT 709 is certainly the best choice today. If you work on a software that various people will use, having a preference screen where the end user can choose would be best (unless you want to be able to compare what they see and what you see software wise, then stick to one specific set of weights.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/YCbCr" ContentLicense="CC BY-SA 4.0" />
  <row Id="19673" PostHistoryTypeId="2" PostId="7584" RevisionGUID="30b57b73-4e0d-4059-a793-619831cb8ebb" CreationDate="2018-05-05T04:35:41.063" UserId="8437" Text="I'm working on a universal shader, and have a function for calculating reflections and a function for textures. When I run the shader, it seems to give up and discard all fragments. The texture and reflection work fine when run independently, however, when I try to calculate both the texture and the reflection at the same time, it gives up. Even if I leave the result of the reflection alone and don't do anything with it, the fragment gets discarded.&#xD;&#xA;&#xD;&#xA;    in vec3 FragPos;&#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;    uniform vec3 ViewPos;&#xD;&#xA;    &#xD;&#xA;    vec3 CalcReflection(vec3 normal, vec3 frag, vec3 view, float shine);&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        // properties&#xD;&#xA;        vec3 norm = normalize(Normal);&#xD;&#xA;&#xD;&#xA;        //Both of these statements work as long as the other isn't called&#xD;&#xA;	    vec4 texColor = texture(texture_diffuse1, TexCoords); &#xD;&#xA;&#xD;&#xA;	    vec3 reflection = CalcReflection(norm, FragPos, ViewPos, mat.shininess);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    FragColor = texColor; //I'm not doing anything with reflection, yet it still discards the fragment&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec3 CalcReflection(vec3 normal, vec3 frag, vec3 view) {&#xD;&#xA;        vec3 I = normalize(frag - view);&#xD;&#xA;        vec3 R = reflect(I, normal);&#xD;&#xA;        return vec3(texture(skybox, R).rgb);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm not too worried about blending the texture and reflection yet, but to start on that I need to know why this doesn't work.&#xD;&#xA;&#xD;&#xA;The answer is probably obvious, but I've been stuck on this for a while and need a fresh perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="19674" PostHistoryTypeId="1" PostId="7584" RevisionGUID="30b57b73-4e0d-4059-a793-619831cb8ebb" CreationDate="2018-05-05T04:35:41.063" UserId="8437" Text="GLSL can't calculate texture and reflection" ContentLicense="CC BY-SA 4.0" />
  <row Id="19675" PostHistoryTypeId="3" PostId="7584" RevisionGUID="30b57b73-4e0d-4059-a793-619831cb8ebb" CreationDate="2018-05-05T04:35:41.063" UserId="8437" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19676" PostHistoryTypeId="5" PostId="7584" RevisionGUID="cb1df4a5-544b-41d6-a9c1-c4de72d9d1d7" CreationDate="2018-05-05T16:29:48.047" UserId="8437" Comment="Added more things from my actual code" Text="I'm working on a universal shader, and have a function for calculating reflections and a function for textures. When I run the shader, it seems to give up and discard all fragments. The texture and reflection work fine when run independently, however, when I try to calculate both the texture and the reflection at the same time, it gives up. Even if I leave the result of the reflection alone and don't do anything with it, the fragment gets discarded.&#xD;&#xA;&#xD;&#xA;    in vec3 FragPos;&#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;    uniform vec3 ViewPos;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D texture_diffuse1;&#xD;&#xA;    uniform samplerCube skybox;&#xD;&#xA;    &#xD;&#xA;    vec3 CalcReflection(vec3 normal, vec3 frag, vec3 view, float shine);&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        // properties&#xD;&#xA;        vec3 norm = normalize(Normal);&#xD;&#xA;&#xD;&#xA;        //Both of these statements work as long as the other isn't called&#xD;&#xA;	    vec4 texColor = vec4(texture(texture_diffuse1, TexCoords).rgb, 1.0); &#xD;&#xA;&#xD;&#xA;	    vec4 reflection = vec4(CalcReflection(norm, FragPos, ViewPos, mat.shininess), 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    FragColor = texColor; //I'm not doing anything with reflection, yet it still discards the fragment&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec3 CalcReflection(vec3 normal, vec3 frag, vec3 view) {&#xD;&#xA;        vec3 I = normalize(frag - view);&#xD;&#xA;        vec3 R = reflect(I, normal);&#xD;&#xA;        return vec3(texture(skybox, R).rgb);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm not too worried about blending the texture and reflection yet, but to start on that I need to know why this doesn't work.&#xD;&#xA;&#xD;&#xA;The answer is probably obvious, but I've been stuck on this for a while and need a fresh perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="19677" PostHistoryTypeId="5" PostId="7584" RevisionGUID="c47f050d-c841-4943-b7bb-b86668d0232b" CreationDate="2018-05-05T16:50:54.883" UserId="8437" Comment="Added more things from my actual code" Text="I'm working on a universal shader, and have a function for calculating reflections and a function for textures. When I run the shader, it seems to give up and discard all fragments. The texture and reflection work fine when run independently, however, when I try to calculate both the texture and the reflection at the same time, it gives up. Even if I leave the result of the reflection alone and don't do anything with it, the fragment gets discarded.&#xD;&#xA;&#xD;&#xA;    in vec3 FragPos;&#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;    uniform vec3 ViewPos;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D texture_diffuse1;&#xD;&#xA;    uniform samplerCube skybox;&#xD;&#xA;    &#xD;&#xA;    vec3 CalcReflection(vec3 normal, vec3 frag, vec3 view, float shine);&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        // properties&#xD;&#xA;        vec3 norm = normalize(Normal);&#xD;&#xA;&#xD;&#xA;        //Both of these statements work as long as the other isn't called&#xD;&#xA;	    vec4 texColor = vec4(texture(texture_diffuse1, TexCoords).rgb, 1.0); &#xD;&#xA;&#xD;&#xA;	    vec4 reflection = vec4(CalcReflection(norm, FragPos, ViewPos, mat.shininess), 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    FragColor = texColor; //I'm not doing anything with reflection, yet it still discards the fragment&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    vec3 CalcReflection(vec3 normal, vec3 frag, vec3 view) {&#xD;&#xA;        vec3 I = normalize(frag - view);&#xD;&#xA;        vec3 R = reflect(I, normal);&#xD;&#xA;        return vec3(texture(skybox, R).rgb);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm not too worried about blending the texture and reflection yet, but to start on that I need to know why this doesn't work.&#xD;&#xA;&#xD;&#xA;The answer is probably obvious, but I've been stuck on this for a while and need a fresh perspective&#xD;&#xA;&#xD;&#xA;Edit: Added more things from my actual code (skybox definition, alpha values)" ContentLicense="CC BY-SA 4.0" />
  <row Id="19681" PostHistoryTypeId="2" PostId="7586" RevisionGUID="bf9485c0-0884-40c2-bce2-9bf798e2f196" CreationDate="2018-05-06T00:19:19.613" UserId="7000" Text="The [docs][1] for `glMapNamedBufferRange` list several optional flags that can be used when a buffer is mapped such as `GL_MAP_INVALIDATE_RANGE_BIT`.&#xD;&#xA;&#xD;&#xA;The docs say:&#xD;&#xA;&gt; The following optional flag bits in access may be used to modify the mapping:&#xD;&#xA;GL_MAP_INVALIDATE_RANGE_BIT indicates that the previous contents of the specified range may be discarded. &#xD;&#xA;&#xD;&#xA;It seems like the right thing to do would be to always specify that flag yet it is optional.  Even if you do not specify `GL_MAP_INVALIDATE_RANGE_BIT` or similar, it does not seem possible to retreive that memory.&#xD;&#xA;&#xD;&#xA;Are there performance reasons (or other reasons) why you would not want to invalidate the data that is in a buffer that you are writing over?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="19682" PostHistoryTypeId="1" PostId="7586" RevisionGUID="bf9485c0-0884-40c2-bce2-9bf798e2f196" CreationDate="2018-05-06T00:19:19.613" UserId="7000" Text="What are the performance implications of the optional flags used when mapping a buffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19683" PostHistoryTypeId="3" PostId="7586" RevisionGUID="bf9485c0-0884-40c2-bce2-9bf798e2f196" CreationDate="2018-05-06T00:19:19.613" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19685" PostHistoryTypeId="5" PostId="7586" RevisionGUID="526b7459-1c2a-4219-8e48-907f6508dbe3" CreationDate="2018-05-06T04:25:32.543" UserId="7000" Comment="added 22 characters in body" Text="The [docs][1] for `glMapNamedBufferRange` list several optional flags that can be used when a buffer is mapped such as `GL_MAP_INVALIDATE_RANGE_BIT`.&#xD;&#xA;&#xD;&#xA;The docs say:&#xD;&#xA;&gt; The following optional flag bits in access may be used to modify the mapping:&#xD;&#xA;GL_MAP_INVALIDATE_RANGE_BIT indicates that the previous contents of the specified range may be discarded. &#xD;&#xA;&#xD;&#xA;It seems like the right thing to do would be to always specify that flag yet it is optional.  Even if you do not specify `GL_MAP_INVALIDATE_RANGE_BIT` or similar I do not see how you could retreive this data or what its value would be.&#xD;&#xA;&#xD;&#xA;Are there performance reasons (or other reasons) why you would not want to invalidate the data that is in a buffer that you are writing over?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="19686" PostHistoryTypeId="2" PostId="7587" RevisionGUID="3c392407-17e2-4ce9-a470-deefad477992" CreationDate="2018-05-06T04:30:12.290" UserId="2654" Text="&gt; It seems like the right thing to do would be to always specify that flag yet it is optional.&#xD;&#xA;&#xD;&#xA;You can map buffers for *reading*; invalidation is negatively useful for that. Also, you can map a buffer and only overwrite part of it. Invalidation is negatively useful for that too.&#xD;&#xA;&#xD;&#xA;`glMapBufferRange` has to be able to work outside of the narrow use case of mapping for overwriting an entire range.&#xD;&#xA;&#xD;&#xA;&gt; Are there performance reasons (or other reasons) why you would not want to invalidate the data that is in a buffer that you are writing over?&#xD;&#xA;&#xD;&#xA;Invalidation is a mechanism to allow the implementation to not delay the act of mapping the buffer (due to prior GPU commands that read from it) if you're going to overwrite all of the area in the buffer. The implementation can allocate a chunk of memory, and you can write to that. Then, it'll schedule the DMA from that chunk into the actual buffer storage when you unmap it, handling the synchronization operations as well. For whole buffer invalidation, it can allocate GPU-accessible memory and completely *replace* the buffer's storage.&#xD;&#xA;&#xD;&#xA;Of course, this only matters if you're mapping frequently. If you're using [persistent mapped buffers][1] for [streaming][2] (and you should be, if you're using DSA), then you don't care about invalidation. You're going to handle synchronization manually.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object#Persistent_mapping&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#Persistent_mapped_streaming" ContentLicense="CC BY-SA 4.0" />
  <row Id="19687" PostHistoryTypeId="5" PostId="7586" RevisionGUID="08ecebc3-de82-4091-ac04-64595e4e40c7" CreationDate="2018-05-06T08:36:45.493" UserId="7000" Comment="added 17 characters in body" Text="The [docs][1] for `glMapNamedBufferRange` list several optional flags that can be used when a buffer is mapped such as `GL_MAP_INVALIDATE_RANGE_BIT`.&#xD;&#xA;&#xD;&#xA;The docs say:&#xD;&#xA;&gt; The following optional flag bits in access may be used to modify the mapping:&#xD;&#xA;GL_MAP_INVALIDATE_RANGE_BIT indicates that the previous contents of the specified range may be discarded. &#xD;&#xA;&#xD;&#xA;It seems like the right thing to do would be to always specify that flag yet it is optional.  Even if you do not specify `GL_MAP_INVALIDATE_RANGE_BIT` or the other, similar flags I do not see how you could retrieve this data or what its value would be.&#xD;&#xA;&#xD;&#xA;Are there performance reasons (or other reasons) why you would not want to invalidate the data that is in a buffer that you are writing over?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="19694" PostHistoryTypeId="50" PostId="6373" RevisionGUID="5b002836-2968-4250-876e-5ff491fd02f7" CreationDate="2018-05-07T02:43:37.397" UserId="-1" />
  <row Id="19695" PostHistoryTypeId="2" PostId="7589" RevisionGUID="b07f8555-34e2-4969-8c2d-fb44f1220bbb" CreationDate="2018-05-07T07:40:38.783" UserId="8677" Text="I have a list of vertices, I want to clip these inside the view frustum. &#xD;&#xA;&#xD;&#xA;Here's what I am planning to do :&#xD;&#xA;&#xD;&#xA; - First I will loop through my list and check vertex $v$ for $|v.x| \le |v.w|$, $|v.y| \le |v.w|$ and $|v.z| \le |v.w|$. &#xD;&#xA;&#xD;&#xA;  - If it fails then I will remove it from the list and add it to a `failedVertex` list. &#xD;&#xA;&#xD;&#xA;   - If it passes the test, then I will set up a inner loop to iterate through `failedVertex` list. For each vertex in `failedVertex`, I will find the intersection of the line between my &quot;passed&quot; vertex and current failed vertex with the view frustum. I will then add the intersection point to my `out` list. &#xD;&#xA;&#xD;&#xA;     - Eg: if $v$ is a passed vertex and $w^i$ is `failedVertex[i]`, then I need the intersection between $r = v + \lambda(v - w^i)$ and my view frustum.     &#xD;&#xA;&#xD;&#xA;    - At the end of the inner loop I will add the passed vertex to my `out` list.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have one problem with this approach, how do I find the intersection between my line and the view frustum ? I don't know the equations of the six planes of my view frustum, I don't really want to calculate the equation of the 6 planes.&#xD;&#xA;&#xD;&#xA;I am not using OpenGL or Direct3D ..." ContentLicense="CC BY-SA 4.0" />
  <row Id="19696" PostHistoryTypeId="1" PostId="7589" RevisionGUID="b07f8555-34e2-4969-8c2d-fb44f1220bbb" CreationDate="2018-05-07T07:40:38.783" UserId="8677" Text="How to do clipping in 3D?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19697" PostHistoryTypeId="3" PostId="7589" RevisionGUID="b07f8555-34e2-4969-8c2d-fb44f1220bbb" CreationDate="2018-05-07T07:40:38.783" UserId="8677" Text="|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19698" PostHistoryTypeId="2" PostId="7590" RevisionGUID="2bf1d95a-80dd-4d1b-917d-f8e508a229fc" CreationDate="2018-05-07T12:32:08.410" UserId="385" Text="Ignoring emission and shadowing for simplicity, the [rendering equation][1] can be stripped down to:&#xD;&#xA;&#xD;&#xA;$$L(x, \, \vec \omega) = \int_{\Omega}{f_r(x, \, \vec \omega^\prime, \, \vec \omega) \, (\vec \omega^\prime \cdot \vec n) \, d\vec \omega^\prime}$$&#xD;&#xA;&#xD;&#xA;where $f_r$ is the BRDF and $(\vec \omega^\prime \cdot \vec n)$ is the cosine of the angle between light and surface normal.&#xD;&#xA;&#xD;&#xA;For the Lambertian diffuse BRDF $\frac{\rho}{\pi}$ this is fine - we're multiplying it with the cosine, seeing Lambert's cosine law in action.&#xD;&#xA;&#xD;&#xA;Now for the specular part of the Phong BRDF, you would commonly calculate a pixel's color like this:&#xD;&#xA;&#xD;&#xA;$$I_{out} = I_{in} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;where $I_{in}$ is the incident light, $k_{specular}$ is the specular reflectivity of the surface, and $\alpha$ is the Phong exponent. Note the absence of $(\vec \omega^\prime \cdot \vec n)$ in this equation.&#xD;&#xA;&#xD;&#xA;To use the rendering equation and end up with the same pixel value as the common Phong equation above, we'd need to write:&#xD;&#xA;&#xD;&#xA;$$f^{Phong}_r(x, \, \vec \omega^\prime, \, \vec \omega) = \frac{1}{(\vec \omega^\prime \cdot \vec n)} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;Note the cosine in the denominator that cancels out the cosine in $L(x, \, \vec \omega)$.&#xD;&#xA;&#xD;&#xA;In his [derivation of the Phong normalization factor][2], Fabian Giesen states:&#xD;&#xA;&#xD;&#xA;&gt; [...] this is the derivation for the original Phong formulation, where the $R \cdot V$ term is not multiplied by $cos \theta$. If you write that version of the Phong model as a BRDF, you end up with a $cos \theta$ in the numerator to cancel out the $cos \theta$ factor in the reflection equation. This numerator is complete nonsense physically, so the modern formulation of the Phong model removes it.&#xD;&#xA;&#xD;&#xA;I don't understand why he speaks about the numerator here, instead of the denominator. Is this a slip in the article, or a misunderstanding on my part?&#xD;&#xA;&#xD;&#xA;What is the 'modern formulation' of Phong? Is cancelling out the cosine really 'complete nonsense', given that Phong is an empirical model to begin with? With the normalization factor, $\frac{\alpha + X}{2 \pi}$ when should you use $X=1$ and when $X=2$?&#xD;&#xA;&#xD;&#xA;Here is a path traced side-by-side comparison of a 65% reflective sphere, Phong exponent 100, $X=2$ for the normalization. The left image has the cosine cancelled out, while the right image includes it, noticably darkening the borders.&#xD;&#xA;&#xD;&#xA;[![With no cosine][4]][4]&#xD;&#xA;[![With cosine][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [2]: http://www.farbrausch.de/~fg/articles/phong.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/8IstAm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/FcNFnm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19699" PostHistoryTypeId="1" PostId="7590" RevisionGUID="2bf1d95a-80dd-4d1b-917d-f8e508a229fc" CreationDate="2018-05-07T12:32:08.410" UserId="385" Text="Phong and the Rendering Equation: What's with the cosine?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19700" PostHistoryTypeId="3" PostId="7590" RevisionGUID="2bf1d95a-80dd-4d1b-917d-f8e508a229fc" CreationDate="2018-05-07T12:32:08.410" UserId="385" Text="|rendering|brdf|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19701" PostHistoryTypeId="5" PostId="7590" RevisionGUID="5403139f-5f22-4bb3-b7d2-bc64d6e34adb" CreationDate="2018-05-07T12:56:44.853" UserId="385" Comment="Made images smaller so they fit side by side" Text="Ignoring emission and shadowing for simplicity, the [rendering equation][1] can be stripped down to:&#xD;&#xA;&#xD;&#xA;$$L(x, \, \vec \omega) = \int_{\Omega}{f_r(x, \, \vec \omega^\prime, \, \vec \omega) \, (\vec \omega^\prime \cdot \vec n) \, d\vec \omega^\prime}$$&#xD;&#xA;&#xD;&#xA;where $f_r$ is the BRDF and $(\vec \omega^\prime \cdot \vec n)$ is the cosine of the angle between light and surface normal.&#xD;&#xA;&#xD;&#xA;For the Lambertian diffuse BRDF $\frac{\rho}{\pi}$ this is fine - we're multiplying it with the cosine, seeing Lambert's cosine law in action.&#xD;&#xA;&#xD;&#xA;Now for the specular part of the Phong BRDF, you would commonly calculate a pixel's color like this:&#xD;&#xA;&#xD;&#xA;$$I_{out} = I_{in} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;where $I_{in}$ is the incident light, $k_{specular}$ is the specular reflectivity of the surface, and $\alpha$ is the Phong exponent. Note the absence of $(\vec \omega^\prime \cdot \vec n)$ in this equation.&#xD;&#xA;&#xD;&#xA;To use the rendering equation and end up with the same pixel value as the common Phong equation above, we'd need to write:&#xD;&#xA;&#xD;&#xA;$$f^{Phong}_r(x, \, \vec \omega^\prime, \, \vec \omega) = \frac{1}{(\vec \omega^\prime \cdot \vec n)} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;Note the cosine in the denominator that cancels out the cosine in $L(x, \, \vec \omega)$.&#xD;&#xA;&#xD;&#xA;In his [derivation of the Phong normalization factor][2], Fabian Giesen states:&#xD;&#xA;&#xD;&#xA;&gt; [...] this is the derivation for the original Phong formulation, where the $R \cdot V$ term is not multiplied by $cos \theta$. If you write that version of the Phong model as a BRDF, you end up with a $cos \theta$ in the numerator to cancel out the $cos \theta$ factor in the reflection equation. This numerator is complete nonsense physically, so the modern formulation of the Phong model removes it.&#xD;&#xA;&#xD;&#xA;I don't understand why he speaks about the numerator here, instead of the denominator. Is this a slip in the article, or a misunderstanding on my part?&#xD;&#xA;&#xD;&#xA;What is the 'modern formulation' of Phong? Is cancelling out the cosine really 'complete nonsense', given that Phong is an empirical model to begin with? With the normalization factor, $\frac{\alpha + X}{2 \pi}$ when should you use $X=1$ and when $X=2$?&#xD;&#xA;&#xD;&#xA;Here is a path traced side-by-side comparison of a 65% reflective sphere, Phong exponent 100, $X=2$ for the normalization. The left image has the cosine cancelled out, while the right image includes it, noticably darkening the borders.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/FcNFnm.png&quot; width=&quot;300&quot; /&gt;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/8IstA.png&quot; width=&quot;300&quot; /&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [2]: http://www.farbrausch.de/~fg/articles/phong.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19702" PostHistoryTypeId="5" PostId="7590" RevisionGUID="21612eb1-314e-4284-bdac-75369fefd09a" CreationDate="2018-05-07T13:17:04.393" UserId="385" Comment="deleted 38 characters in body" Text="Ignoring emission and shadowing for simplicity, the [rendering equation][1] can be stripped down to:&#xD;&#xA;&#xD;&#xA;$$L(x, \, \vec \omega) = \int_{\Omega}{f_r(x, \, \vec \omega^\prime, \, \vec \omega) \, (\vec \omega^\prime \cdot \vec n) \, d\vec \omega^\prime}$$&#xD;&#xA;&#xD;&#xA;where $f_r$ is the BRDF and $(\vec \omega^\prime \cdot \vec n)$ is the cosine of the angle between light and surface normal.&#xD;&#xA;&#xD;&#xA;For the Lambertian diffuse BRDF $\frac{\rho}{\pi}$ this is fine - we're multiplying it with the cosine, seeing Lambert's cosine law in action.&#xD;&#xA;&#xD;&#xA;Now for the specular part of the Phong BRDF, you would commonly calculate a pixel's color like this:&#xD;&#xA;&#xD;&#xA;$$I_{out} = I_{in} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;where $I_{in}$ is the incident light, $k_{specular}$ is the specular reflectivity of the surface, and $\alpha$ is the Phong exponent. Note the absence of $(\vec \omega^\prime \cdot \vec n)$ in this equation.&#xD;&#xA;&#xD;&#xA;To use the rendering equation and end up with the same pixel value as the common Phong equation above, we'd need to write:&#xD;&#xA;&#xD;&#xA;$$f^{Phong}_r(x, \, \vec \omega^\prime, \, \vec \omega) = \frac{1}{(\vec \omega^\prime \cdot \vec n)} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;Note the cosine in the denominator that cancels out the cosine in $L(x, \, \vec \omega)$.&#xD;&#xA;&#xD;&#xA;In his [derivation of the Phong normalization factor][2], Fabian Giesen states:&#xD;&#xA;&#xD;&#xA;&gt; [...] this is the derivation for the original Phong formulation, where the $R \cdot V$ term is not multiplied by $cos \theta$. If you write that version of the Phong model as a BRDF, you end up with a $cos \theta$ in the numerator to cancel out the $cos \theta$ factor in the reflection equation. This numerator is complete nonsense physically, so the modern formulation of the Phong model removes it.&#xD;&#xA;&#xD;&#xA;I don't understand why he speaks about the numerator here, instead of the denominator. Is this a slip in the article, or a misunderstanding on my part?&#xD;&#xA;&#xD;&#xA;What is the 'modern formulation' of Phong? What does it mean that cancelling out is 'complete nonsense physically'? With the normalization factor, $\frac{\alpha + X}{2 \pi}$ when should you use $X=1$ and when $X=2$?&#xD;&#xA;&#xD;&#xA;Here is a path traced side-by-side comparison of a 65% reflective sphere, Phong exponent 100, $X=2$ for the normalization. The left image has the cosine cancelled out, while the right image includes it, noticably darkening the borders.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/FcNFnm.png&quot; width=&quot;300&quot; /&gt;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/8IstA.png&quot; width=&quot;300&quot; /&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [2]: http://www.farbrausch.de/~fg/articles/phong.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19703" PostHistoryTypeId="5" PostId="7590" RevisionGUID="102efcc6-1fa3-4098-b5cf-79b0fd04eabd" CreationDate="2018-05-07T14:14:32.323" UserId="385" Comment="deleted 4 characters in body" Text="Ignoring emission and shadowing for simplicity, the [rendering equation][1] can be stripped down to:&#xD;&#xA;&#xD;&#xA;$$L(x, \, \vec \omega) = \int_{\Omega}{f_r(x, \, \vec \omega^\prime, \, \vec \omega) \, (\vec \omega^\prime \cdot \vec n) \, d\vec \omega^\prime}$$&#xD;&#xA;&#xD;&#xA;where $f_r$ is the BRDF and $(\vec \omega^\prime \cdot \vec n)$ is the cosine of the angle between light and surface normal.&#xD;&#xA;&#xD;&#xA;For the Lambertian diffuse BRDF $\frac{\rho}{\pi}$ this is fine - we're multiplying it with the cosine, seeing Lambert's cosine law in action.&#xD;&#xA;&#xD;&#xA;Now for the specular part of the Phong BRDF, you would commonly calculate a pixel's color like this:&#xD;&#xA;&#xD;&#xA;$$I_{out} = I_{in} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;where $I_{in}$ is the incident light, $k_{specular}$ is the specular reflectivity of the surface, and $\alpha$ is the Phong exponent. Note the absence of $(\vec \omega^\prime \cdot \vec n)$ in this equation.&#xD;&#xA;&#xD;&#xA;To use the rendering equation and end up with the same pixel value as the common Phong equation above, we'd need to write:&#xD;&#xA;&#xD;&#xA;$$f^{Phong}_r(x, \, \vec \omega^\prime, \, \vec \omega) = \frac{1}{(\vec \omega^\prime \cdot \vec n)} \, k_{specular} \, (\vec w \cdot \vec r)^\alpha$$&#xD;&#xA;&#xD;&#xA;Note the cosine in the denominator that cancels out the cosine in $L(x, \, \vec \omega)$.&#xD;&#xA;&#xD;&#xA;In his [derivation of the Phong normalization factor][2], Fabian Giesen states:&#xD;&#xA;&#xD;&#xA;&gt; [...] this is the derivation for the original Phong formulation, where the $R \cdot V$ term is not multiplied by $cos \theta$. If you write that version of the Phong model as a BRDF, you end up with a $cos \theta$ in the numerator to cancel out the $cos \theta$ factor in the reflection equation. This numerator is complete nonsense physically, so the modern formulation of the Phong model removes it.&#xD;&#xA;&#xD;&#xA;I don't understand why he speaks about the numerator here, instead of the denominator. Is this a slip in the article, or a misunderstanding on my part?&#xD;&#xA;&#xD;&#xA;What is the 'modern formulation' of Phong? What does it mean that cancelling out is 'complete nonsense physically'? With the normalization factor, $\frac{\alpha + X}{2 \pi}$ when should you use $X=1$ and when $X=2$?&#xD;&#xA;&#xD;&#xA;Here is a path traced side-by-side comparison of a reflective sphere, Phong exponent 100, $X=2$ for the normalization. The left image has the cosine cancelled out, while the right image includes it, noticably darkening the borders.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/FcNFnm.png&quot; width=&quot;300&quot; /&gt;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/8IstA.png&quot; width=&quot;300&quot; /&gt;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation&#xD;&#xA;  [2]: http://www.farbrausch.de/~fg/articles/phong.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19704" PostHistoryTypeId="50" PostId="6218" RevisionGUID="d854fa4f-5c14-4bd4-b943-1621b2a5c5b9" CreationDate="2018-05-07T16:45:52.293" UserId="-1" />
  <row Id="19705" PostHistoryTypeId="5" PostId="3889" RevisionGUID="a47715cb-3c2c-4bb4-ab1b-4f6c29b17108" CreationDate="2018-05-07T19:37:14.313" UserId="4948" Comment="added 493 characters in body" Text="Solved.  The issue was with V-Ray's global ambient occlusion on the GI tab.  Once that was shut off everything renders fine.  Interestingly, V-RayDirt maps in materials seem to be behaving just fine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;UPDATE: It appears the real root problem is deeper.  This turned out to be caused by units being set to fractions instead of decimals.  This can cause some values that are very small to round off to zero as the system tries to make it a fraction.  In v-ray lights, the shadow bias was getting rounded to zero automatically in some cases.  A zero shadow bias can produce strange results in some cases.  SOLUTION: stop using fractional units and go through and fix lights with zero bias.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19706" PostHistoryTypeId="50" PostId="5697" RevisionGUID="3a2eb95e-49bc-4e58-8ea3-2fdc47c22e6b" CreationDate="2018-05-07T22:50:27.743" UserId="-1" />
  <row Id="19707" PostHistoryTypeId="2" PostId="7591" RevisionGUID="07eebd73-a53e-4b23-af79-ce2797e5301b" CreationDate="2018-05-08T01:04:17.583" UserId="8682" Text="I've read Wikipedia's [article on the topic](https://en.wikipedia.org/wiki/Order-independent_transparency), and a [tutorial](https://trackdancer.deviantart.com/art/MMD-Understanding-MMD-Draw-Order-494465598) on how it affects MikuMikuDance. I tried to read [a patent](https://patents.google.com/patent/US20080316214) on &quot;packing the 3D array with a prefix sum scan, or linearizing&quot;, but I have no idea what &quot;a prefix sum pass on the generated count buffer to calculate locations in a fragment buffer in which to store all the fragments linearly,&quot; means.&#xD;&#xA;&#xD;&#xA;Wikipedia says exact OIT requires &quot;storing all fragments before sorting and compositing&quot;.&#xD;&#xA;&#xD;&#xA;Would the following be compatible with current technology?&#xD;&#xA;&#xD;&#xA;1. find the minimum and maximum Z-depth of each transparent material, or object.&#xD;&#xA;2. order materials that don't collide in Z-depth, and determine which ones do exist at the same Z-depth.&#xD;&#xA;3. blend transparent materials until you reach materials that have the same Z-depth, so draw order is uncertain.&#xD;&#xA;4. store only the fragments for the potentially intersecting materials, whether it's two or more.&#xD;&#xA;5. sort these fragments by depth and blend them.&#xD;&#xA;6. continue on with nearer materials.&#xD;&#xA;&#xD;&#xA;Instead of just Z-depth, could maybe also use X and Y coordinates or even an efficiently-created shape of a different orientation, like a box around a pane of glass to the side of another transparent object. These would reduce the number of times steps 4 and 5 would have to be done, but are steps 5 and 6 compatible with current or potential future GPUs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19708" PostHistoryTypeId="1" PostId="7591" RevisionGUID="07eebd73-a53e-4b23-af79-ce2797e5301b" CreationDate="2018-05-08T01:04:17.583" UserId="8682" Text="Can order-independent transparency sort fragments for a subset of all transparent objects?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19709" PostHistoryTypeId="3" PostId="7591" RevisionGUID="07eebd73-a53e-4b23-af79-ce2797e5301b" CreationDate="2018-05-08T01:04:17.583" UserId="8682" Text="|rendering|transparency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19710" PostHistoryTypeId="2" PostId="7592" RevisionGUID="2af6e671-5060-42f8-ab61-79591b005865" CreationDate="2018-05-08T01:35:04.797" UserId="7000" Text="My GPU supports OpenGL 4.4 but looking at the OpenGL extensions viewer the only part of 4.5 that it does not support is the GLSL version.&#xD;&#xA;&#xD;&#xA;I am able to use all DSA functions without specifying any sort of Extension Prefix.&#xD;&#xA;&#xD;&#xA;Similarly, I have been able to run code that uses DSA on GPUs that only support OpenGL 4.2&#xD;&#xA;&#xD;&#xA;How is this possible?&#xD;&#xA;&#xD;&#xA;I thought that, if my GPU does not support a version of OpenGL I have to use extension prefixes to use those features." ContentLicense="CC BY-SA 4.0" />
  <row Id="19711" PostHistoryTypeId="1" PostId="7592" RevisionGUID="2af6e671-5060-42f8-ab61-79591b005865" CreationDate="2018-05-08T01:35:04.797" UserId="7000" Text="How can DSA functions be used without extension names on lower versions of OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19712" PostHistoryTypeId="3" PostId="7592" RevisionGUID="2af6e671-5060-42f8-ab61-79591b005865" CreationDate="2018-05-08T01:35:04.797" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19713" PostHistoryTypeId="2" PostId="7593" RevisionGUID="37d33012-ec18-4618-8a4d-16ca2cd53d88" CreationDate="2018-05-08T05:34:35.757" UserId="1937" Text="Your GPU does support OpenGL 4.5, basically. Mine shows exactly the same result, all features supported except the GLSL version. This seems to be fairly common, I'm not sure what the delay is in updating the shader language support, or what GLSL 4.5 brings to the table. &#xD;&#xA;&#xD;&#xA;In order to say a GPU fully supports a GL version, it has to support all the features specified by the ARB for that version number, which is why your driver and mine show up as only supporting 4.4 despite having the full 4.5 feature set on the CPU side. In practice, vendors can add part of a feature level to their driver without fully supporting the version number. It's all pretty messy, which is why we need things like GL3W or GLAD in the first place." ContentLicense="CC BY-SA 4.0" />
  <row Id="19714" PostHistoryTypeId="2" PostId="7594" RevisionGUID="073cfe9e-710e-4d29-8785-1bc6a29a1355" CreationDate="2018-05-08T12:23:17.120" UserId="7008" Text="I am new to optimizing shader code. Now that I have written an &quot;optimzation&quot;, I want to make sure that it really speeds things up and is not just an unreadable version of what I intend to do. For this, I wanted to look into the assembly version of my shader, but I couldn't really find out how to do that. &#xD;&#xA;&#xD;&#xA;I use CodeXL and APITrace, but the former doesn't have any Assembly view as far as I could see and the latter didn't work for my program for some reason. Most other debugging tools don't work (properly) because I program using OpenSceneGraph, meaning there is some Legacy OpenGL Code.&#xD;&#xA;&#xD;&#xA;Therefore my question: How would I get to seeing assembly code of my shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19715" PostHistoryTypeId="1" PostId="7594" RevisionGUID="073cfe9e-710e-4d29-8785-1bc6a29a1355" CreationDate="2018-05-08T12:23:17.120" UserId="7008" Text="How to get assembly code from GLSL Shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="19716" PostHistoryTypeId="3" PostId="7594" RevisionGUID="073cfe9e-710e-4d29-8785-1bc6a29a1355" CreationDate="2018-05-08T12:23:17.120" UserId="7008" Text="|glsl|assembly|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19717" PostHistoryTypeId="2" PostId="7595" RevisionGUID="c9319b47-4795-4648-944f-156b38b89535" CreationDate="2018-05-08T15:52:48.687" UserId="6" Text="In unextended OpenGL that's indeed a little difficult, if possible at all. There is really **no actual notion of &quot;GLSL assembly code&quot;, or not one that's remotely vendor-independent**, let alone a way to retrieve that.&#xD;&#xA;&#xD;&#xA;There are a few extensions that might help you get that information, though, albeit in a not entirely intuitive or even platform-dependent way (but well, you're talking about micro-optimizations, so we're firmly in platform-dependent territory anyway).&#xD;&#xA;&#xD;&#xA;First of all, there's **[GL_ARB_get_program_binary](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_get_program_binary.txt) (core since 4.1), which let's you retrieve a platform-dependent binary** version of the program (after linking). At least on NVidia hardware (maybe others, too, but I wouldn't know) this binary blob also contains ASCII assembly listings of all the contained shaders in NVidia-extended ARB syntax (continuously refined in the `GL_NV_gpu_programX` extensions). Those listings are quite easy to find in the binary when opening it with a normal text editor and the syntax is quite straight forward if you know your way around shaders and general assembly programming principles. As said, other vendors *might* offer similar listings inside their binaries.&#xD;&#xA;&#xD;&#xA;Then there's also external programs that might compile your shader into some **intermediate form, the most platform-independent of those being [SPIR-V](https://www.khronos.org/opengl/wiki/SPIR-V)**, for which Khronos-approved external compilers exist. Being an *intermediate* language this is somewhat of a &quot;high-level assembly language&quot; with an &quot;assembly-like&quot; structure but with many high-level abstractions that builds a bit of a compromise between the easy interpretability of assembly and the easy programability and platform-independence of a high-level language (think of Java bytecode).&#xD;&#xA;&#xD;&#xA;With the [GL_ARB_spirv](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_gl_spirv.txt) extension (core since 4.6) you can directly use (externally precompiled) SPIR-V programs in OpenGL in place of GLSL shaders. I don't know if there is currently a way to let your *driver* compile GLSL into SPIR-V and then retrieve that. Otherwise some external SPIR-V module created from a reference compiler would ***not* necessarily be equal to the machine code that your driver's actual GLSL compiler produces**. It might also be that such an intermediate representation might already be **too high-level** for analysing micro-optimizations anyway.&#xD;&#xA;&#xD;&#xA;All in all, and especially if you just want to use it for debugging/analyzing purposes on a dedicated machine, trying to look for a whatever-natured assembly listing in your driver's binary blob retrieved with `glGetProgramBinary` might be the easiest and most &quot;close-to-the metal&quot; way to get some insight into the compiled product. I use it occasionally just out of interest.&#xD;&#xA;&#xD;&#xA;But of course no answer to this question would be complete without a warning that you shouldn't make too much out of it either. As on the CPU, generally trusting your compiler is a good default approach and you **shouldn't let micro-optimizations like this guide your practice too much, let alone rely on any of that guidance being remotely portable** (let alone assume that the assembly listed in the binary is *actually* what's uses as machine code). But if you want to know what your driver *might* make of it, it can be quite interesting and helpful, especially when deciding between two equally meaningful ways to write some function that might have unexpected differences in the &quot;assembly&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="19718" PostHistoryTypeId="2" PostId="7596" RevisionGUID="260497d0-cda1-4fbf-ac71-786b0b7a4529" CreationDate="2018-05-08T16:46:47.147" UserId="2654" Text="&gt; How is this possible?&#xD;&#xA;&#xD;&#xA;Because [ARB_direct_state_access][1] is an extension. Note that the function/enumerator names in that extension lack the ARB suffix. There are dozens of ARB extensions that work like that. [Suffix-less extensions][2] were introduced in OpenGL 3.0 for compatibility purposes. You could write code that could work on OpenGL 3.0 *or* extensions that expose 3.0 functionality, without having to write different function calls.&#xD;&#xA;&#xD;&#xA;The same goes here. You're not using OpenGL 4.5; you're using OpenGL 4.4+some extensions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_direct_state_access.txt&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Core_Extension" ContentLicense="CC BY-SA 4.0" />
  <row Id="19719" PostHistoryTypeId="2" PostId="7597" RevisionGUID="5e448786-90f4-47ef-9879-bc02f259874e" CreationDate="2018-05-08T18:02:05.887" UserId="7462" Text="Assume we have created a program that renders to a texture. Say the declaration is:&#xD;&#xA;&#xD;&#xA;    GLuint shadingProgram;&#xD;&#xA;&#xD;&#xA;Assume the shader has compiled successfully and it makes use of the imageStore() funtion.&#xD;&#xA;&#xD;&#xA;Just like textures we need to bind the target texture we wish to write to to a binding point. But we do not use texture units, we use image binding units. We also have an additional requirement to explicetly call memory barriers to ensure completion of the writing process.&#xD;&#xA;&#xD;&#xA;So what would be a typical minimum example of writing and reading from a texture using load/store operations?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19720" PostHistoryTypeId="1" PostId="7597" RevisionGUID="5e448786-90f4-47ef-9879-bc02f259874e" CreationDate="2018-05-08T18:02:05.887" UserId="7462" Text="What is the typical use case for rendering to an image through imageStore?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19721" PostHistoryTypeId="3" PostId="7597" RevisionGUID="5e448786-90f4-47ef-9879-bc02f259874e" CreationDate="2018-05-08T18:02:05.887" UserId="7462" Text="|opengl|texture|image|memory|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19722" PostHistoryTypeId="2" PostId="7598" RevisionGUID="946356e6-6d98-4bd7-b1a9-fb9fc32dd2df" CreationDate="2018-05-09T02:55:03.437" UserId="8677" Text="I understand the theory behind z buffering - that I have to check for each pixel if its depth value is less than the one on z buffer or not, if yes then draw else not - but I don't understand how would I actually get the z value of each pixel ?&#xD;&#xA;&#xD;&#xA;At first I thought I will use the equation of the plane of the polygon I am drawing, but then I have to call the inverse of viewport transform for every pixel. Isn't this every inefficient ?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19723" PostHistoryTypeId="1" PostId="7598" RevisionGUID="946356e6-6d98-4bd7-b1a9-fb9fc32dd2df" CreationDate="2018-05-09T02:55:03.437" UserId="8677" Text="How to implement Z-buffering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19724" PostHistoryTypeId="3" PostId="7598" RevisionGUID="946356e6-6d98-4bd7-b1a9-fb9fc32dd2df" CreationDate="2018-05-09T02:55:03.437" UserId="8677" Text="|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19725" PostHistoryTypeId="2" PostId="7599" RevisionGUID="9e4eb0d8-56e0-4db7-8a3f-7d63d83d7fb3" CreationDate="2018-05-09T09:11:41.137" UserId="8541" Text="I'm developing a light probe based GI solution and currently dealing with light leaks due to interpolation between probes located on opposite sides of the walls. I want to tackle the problem by incorporating precomputed shadow maps assigned for each probe to determine which ones are occluded and therefore which probes need to be interpolated for the current fragment in the fragment shader. &#xD;&#xA;&#xD;&#xA;The question is, how would I even store tens of thousands of shadow maps and access them in a fragment shader? Maybe store them continuously in a huge buffer texture?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19726" PostHistoryTypeId="1" PostId="7599" RevisionGUID="9e4eb0d8-56e0-4db7-8a3f-7d63d83d7fb3" CreationDate="2018-05-09T09:11:41.137" UserId="8541" Text="How to access several textures from huge amount of textures in a shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19727" PostHistoryTypeId="3" PostId="7599" RevisionGUID="9e4eb0d8-56e0-4db7-8a3f-7d63d83d7fb3" CreationDate="2018-05-09T09:11:41.137" UserId="8541" Text="|opengl|shader|texture|glsl|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19728" PostHistoryTypeId="2" PostId="7600" RevisionGUID="6bf44355-5f58-4761-a896-5d1073245bc1" CreationDate="2018-05-09T09:14:10.157" UserId="1937" Text="The values for each pixel in the Z-buffer are interpolated from the values at the corners of the triangle during rasterization. To make this work, the projection matrix produces depth values that are a function of the reciprocal of the original depth value in camera-space.&#xD;&#xA;&#xD;&#xA;That is, the $Z'$ value in each transformed vertex is of the form $aZ + b$, where $a$ and  $b$ together determine the near and far planes, and the transformed $W'$ value is just the original $Z$. After doing the homogeneous divide by $W'$, the transformed $Z'$ becomes $a + b/Z$. By using the reciprocal of $Z$ in the depth value like this, you can then just interpolate linearly in screen space from the three corners to each pixel to get correct results. Since the last step produces floating point results, and most Z-buffers use unsigned integer values, you'll need to bias, scale and quantize before writing to the  actual buffer. &#xD;&#xA;&#xD;&#xA;I seriously recommend Eric Lengyel's book Mathematics for 3D Game Programming for the nitty-gritty details of all this kind of stuff, he also explains perspective-correct interpolation of vertex attributes and all the other math you'll need to know to write a rasterizer. " ContentLicense="CC BY-SA 4.0" />
  <row Id="19729" PostHistoryTypeId="5" PostId="7599" RevisionGUID="e4f083aa-2d4d-47f2-92cd-c7bab68142d6" CreationDate="2018-05-09T10:42:19.533" UserId="8541" Comment="Adde another suggestion for possible implementation" Text="I'm developing a light probe based GI solution and currently dealing with light leaks due to interpolation between probes located on opposite sides of the walls. I want to tackle the problem by incorporating precomputed shadow maps assigned for each probe to determine which ones are occluded and therefore which probes need to be interpolated for the current fragment in the fragment shader. &#xD;&#xA;&#xD;&#xA;The question is, how would I even store tens of thousands of shadow maps and access them in a fragment shader? &#xD;&#xA;&#xD;&#xA;Maybe store them continuously in a huge buffer texture? Hmm, or maybe pack them to a huge texture atlas? That also makes me wonder which method would provide a better cache behavior.." ContentLicense="CC BY-SA 4.0" />
  <row Id="19730" PostHistoryTypeId="2" PostId="7601" RevisionGUID="50ffc3b9-c391-4e85-9d69-198de2653e80" CreationDate="2018-05-09T11:36:10.280" UserId="137" Text="You can invert the shadow maps. Render a cube shadowmap at each probe. Then you can filter out any probes influence that would come from beyond a wall by comparing where the new point is in relation to the shadow map's depth in that direction.&#xD;&#xA;&#xD;&#xA;Then if the point is beyond the wall you set the interpolation weight for that probe to 0.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19731" PostHistoryTypeId="2" PostId="7602" RevisionGUID="fa33de86-84e8-4f14-9de0-d5232883c281" CreationDate="2018-05-09T13:23:02.783" UserId="2654" Text="Well, it's unlikely that 10,000 cubemaps could fit into memory at all (at 128x128x4-bytes-per-pixel, 10,000 cubemaps would require upwards of 4GB of RAM). But as far as the mechanism to use a large number of such textures, that's pretty easy. You have two options.&#xD;&#xA;&#xD;&#xA;The option that's widely available is to use [cubemap array textures][1]. You allocate the storage for the array cubemap with the number of cubemaps you want * 6. Each set of 6 array layer-faces is a single cubemap. In your shader, you just provide an array index for the cubemap layer (not layer-face) that you want.&#xD;&#xA;&#xD;&#xA;The other option is to employ [bindless textures][2]. You create however many cubemaps you want, then provide them to the shader as an SSBO array of 64-bit integer handles. You index this array as needed and convert the handle into a sampler value before fetching.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Cubemap_Array_Texture&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Bindless_Texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="19732" PostHistoryTypeId="2" PostId="7603" RevisionGUID="0b028c1e-9e1b-4dcd-9d87-58d2242bfc64" CreationDate="2018-05-09T15:25:20.160" UserId="8699" Text="I am trying to do skeletal animation using Assimp and the inverse bind pose matrix just trips me up. I will give a little example to illustrate my point.&#xD;&#xA;&#xD;&#xA;    Root&#xD;&#xA;        Bone A&#xD;&#xA;            Bone B&#xD;&#xA;                Bone C&#xD;&#xA;&#xD;&#xA;Let's say we have a hierarchy like above. To get a vertex in root space into C space, I would have to do (CBA) * v. The inverse bind pose, which is supposed to get a vertex from bone space to root space, should be the inverse of this. Therefore, the way to calculate inverse bind matrix should be (CBA)^-1 or (A^-1)(B^-1)(C^-1). The formula then is (A^-1)(B^-1)(C^-1) * v, which makes sense. However, I am not able to reproduce the result of Assimp's mOffsetMatrix (inverse bind matrix caculated by Assimp) with (CBA)^-1. (ABC)^-1, however, surprisingly produces the correct result, albeit a little marginal error here and there which I attribute to floating point error.&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="19733" PostHistoryTypeId="1" PostId="7603" RevisionGUID="0b028c1e-9e1b-4dcd-9d87-58d2242bfc64" CreationDate="2018-05-09T15:25:20.160" UserId="8699" Text="Confusion about how inverse bind pose is actually calculated and used?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19734" PostHistoryTypeId="3" PostId="7603" RevisionGUID="0b028c1e-9e1b-4dcd-9d87-58d2242bfc64" CreationDate="2018-05-09T15:25:20.160" UserId="8699" Text="|opengl|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19735" PostHistoryTypeId="2" PostId="7604" RevisionGUID="c2bc5260-7153-4add-a53d-59e09d8be660" CreationDate="2018-05-09T15:58:58.557" UserId="6" Text="&gt; To get a vertex in root space into C space, I would have to do (CBA) * v.&#xD;&#xA;&#xD;&#xA;Well, yes. But that's not actually what you want to do in skeletal animation. **You have it reverse.**&#xD;&#xA;&#xD;&#xA;It's the other way around. You assume you have a point in C space and want to compute its position in root/global space, in order to pump it further through the transformation pipeline, which gets **increasingly more global with each transformation** until your point ends up in eye-space (and further). That's why A doesn't transform from root space into A space, it transforms from A space into root space. So $ABC$ transforms from C space into root space.&#xD;&#xA;&#xD;&#xA;Now your mesh vertices already are in root space, that's where the inverse bind pose comes into play, which transforms a point **from root space into C space**. So you basically transform your point from root space to C (or whatever joint) space with the inverse bind matrix that's only dependent on the joint and constant over the whole animation and then from that joint space back into root space with the animation-dependent joint transformation.&#xD;&#xA;&#xD;&#xA;So C's transformation matrix for frame $t$, that transforms a vertex from *unanimated* root space, which is how your mesh is defined, into *animated* (with respect to C's joint angle) root space would be $(A_RB_RC_R)^{-1}A(t)B(t)C(t)$, where $M(t)$ is the *local* joint matrix at animation time $t$ and $M_R$ is the *local* joint matrix corresponding to the rest pose, the pose in which the mesh is defined, and thus $(A_RB_RC_R)^{-1}$ is C's inverse bind pose." ContentLicense="CC BY-SA 4.0" />
  <row Id="19736" PostHistoryTypeId="2" PostId="7605" RevisionGUID="6ea326b9-6b21-4e34-a619-7877a24c6d3d" CreationDate="2018-05-09T16:07:44.197" UserId="4820" Text="So with the idea that I want to load in an object with morph targets and for simplicity sake I know it will have between 1-8 position morph targets. Ultimately I want to do&#xD;&#xA;&#xD;&#xA;    renderedPrimitive.POSITION = primitive.POSITION + &#xD;&#xA;       weights[0] * primitive.targets[0].POSITION +&#xD;&#xA;       ....&#xD;&#xA;       weights[N] * primitive.targets[N].POSITION;&#xD;&#xA;&#xD;&#xA;But being open to load in any model how do you go about knowing the number of vertex input attributes to allocate. Getting the CPU side dynamically is not an issue, but am I wrong that the ONLY way around this is building your shader with some `#define` and compiling during runtime?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19737" PostHistoryTypeId="1" PostId="7605" RevisionGUID="6ea326b9-6b21-4e34-a619-7877a24c6d3d" CreationDate="2018-05-09T16:07:44.197" UserId="4820" Text="Dynamically allocating morph targets in shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="19738" PostHistoryTypeId="3" PostId="7605" RevisionGUID="6ea326b9-6b21-4e34-a619-7877a24c6d3d" CreationDate="2018-05-09T16:07:44.197" UserId="4820" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19739" PostHistoryTypeId="2" PostId="7606" RevisionGUID="a442b153-1dbf-48e8-9866-a322c078d330" CreationDate="2018-05-09T17:37:54.177" UserId="2654" Text="With modern hardware, morph targets probably should not be VS inputs. They should be SSBOs or the D3D equivalent. The vertex shader should fetch from these arrays of positions and act on them appropriately. You can pass the number of targets as a uniform or something." ContentLicense="CC BY-SA 4.0" />
  <row Id="19740" PostHistoryTypeId="2" PostId="7607" RevisionGUID="0212619d-f08e-437d-a03d-244d29dbdd97" CreationDate="2018-05-09T19:00:41.447" UserId="8587" Text="I have a animated cube with 5 keyframes and when I export it to glTF with blender, in the file I can only see 3 keyframes:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ep6Jc.jpg&#xD;&#xA;&#xD;&#xA;But when I viewed the gltf model with viewer all 5 keyframes worked well in the animation. Whats the explanation of this ? &#xD;&#xA;My blend file if you are interested: https://files.fm/u/ujs4w23g" ContentLicense="CC BY-SA 4.0" />
  <row Id="19741" PostHistoryTypeId="1" PostId="7607" RevisionGUID="0212619d-f08e-437d-a03d-244d29dbdd97" CreationDate="2018-05-09T19:00:41.447" UserId="8587" Text="glTF animation keyframe question" ContentLicense="CC BY-SA 4.0" />
  <row Id="19742" PostHistoryTypeId="3" PostId="7607" RevisionGUID="0212619d-f08e-437d-a03d-244d29dbdd97" CreationDate="2018-05-09T19:00:41.447" UserId="8587" Text="|animation|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19743" PostHistoryTypeId="2" PostId="7608" RevisionGUID="903f4f88-481d-4b14-bd67-331166200922" CreationDate="2018-05-09T20:44:57.930" UserId="1908" Text="You're seeing channels and samplers there, not individual keyframes.  In this case, one animation is simultaneously targeting the translation, rotation, and scale channels of the same node, with three separate &quot;samplers&quot; (sets of keyframes per channel).&#xD;&#xA;&#xD;&#xA;Not shown above, your glTF file has a section called `accessors` that tells viewers how to slice out portions of binary data from an associated `.bin` file.  The `.bin` file contains mostly mesh position/normal/UV data, but also contains the keyframe times and values.&#xD;&#xA;&#xD;&#xA;So in the above snippet, that first channel targets the `translation` of node 3 with sampler 0 (the first sampler).  The sampler there asks for `LINEAR` interpolation of keyframes from animation times (`input: 8`) for translation keyframe values (`output: 9`).  In the `accessors` section, accessors 8 and 9 (using zero-based indexing) are references to the keyframe times (in 8) and values (in 9).  They are separate because the data type of the output depends on what's being targeted (rotations are vec4 quaternions for example, while translations and scales are vec3, and the input times are just floats).&#xD;&#xA;&#xD;&#xA;The `accessors` in question (8 and 9 for example) will contain a value `&quot;count&quot;` that effectively tells you the number of keyframes.  If you have 5 keyframes for example, accessor 8 should have `&quot;count&quot;: 5` keyframe times, and accessor 9 will also have `&quot;count&quot;: 5` keyframe values.  The glTF Validator will flag an error if these counts don't match." ContentLicense="CC BY-SA 4.0" />
  <row Id="19744" PostHistoryTypeId="50" PostId="7437" RevisionGUID="33bbb329-b68e-40b2-a8fb-91b34e1ca075" CreationDate="2018-05-10T04:54:47.027" UserId="-1" />
  <row Id="19745" PostHistoryTypeId="5" PostId="7607" RevisionGUID="c8c1dd1b-fd36-4fc8-ae86-57d8b7c13f0a" CreationDate="2018-05-10T05:38:45.670" UserId="8587" Comment="added 1 character in body" Text="I have an animated cube with 5 keyframes and when I export it to glTF with blender, in the file I can only see 3 keyframes:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ep6Jc.jpg&#xD;&#xA;&#xD;&#xA;But when I viewed the gltf model with viewer all 5 keyframes worked well in the animation. Whats the explanation of this ? &#xD;&#xA;My blend file if you are interested: https://files.fm/u/ujs4w23g" ContentLicense="CC BY-SA 4.0" />
  <row Id="19748" PostHistoryTypeId="2" PostId="7611" RevisionGUID="c0604df6-d4d3-4724-ae90-21cc046f1601" CreationDate="2018-05-10T13:51:06.040" UserId="8702" Text="The [Möller–Trumbore intersection algorithm][1] compares the determinant with an epsilon. What is this epsilon and how is its value chosen?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="19749" PostHistoryTypeId="1" PostId="7611" RevisionGUID="c0604df6-d4d3-4724-ae90-21cc046f1601" CreationDate="2018-05-10T13:51:06.040" UserId="8702" Text="What is the use of epislon in the Möller–Trumbore intersection algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19750" PostHistoryTypeId="3" PostId="7611" RevisionGUID="c0604df6-d4d3-4724-ae90-21cc046f1601" CreationDate="2018-05-10T13:51:06.040" UserId="8702" Text="|raytracing|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19751" PostHistoryTypeId="4" PostId="4884" RevisionGUID="6ecdc2a8-d052-4ece-aa20-b58c0bfa1f0a" CreationDate="2018-05-10T14:16:45.280" UserId="6546" Comment="Reworded header" Text="My (ADS) shader doesn't render the light direction correctly" ContentLicense="CC BY-SA 4.0" />
  <row Id="19752" PostHistoryTypeId="6" PostId="4884" RevisionGUID="6ecdc2a8-d052-4ece-aa20-b58c0bfa1f0a" CreationDate="2018-05-10T14:16:45.280" UserId="6546" Comment="Reworded header" Text="|opengl|glsl|c++|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19753" PostHistoryTypeId="24" PostId="4884" RevisionGUID="6ecdc2a8-d052-4ece-aa20-b58c0bfa1f0a" CreationDate="2018-05-10T14:16:45.280" Comment="Proposed by 6546 approved by 209, 2041 edit id of 416" ContentLicense="CC BY-SA 4.0" />
  <row Id="19759" PostHistoryTypeId="5" PostId="3571" RevisionGUID="fc7f3542-5072-4e76-bb63-01da78a2bb76" CreationDate="2018-05-10T20:12:30.460" UserDisplayName="user7220" Comment="Corrected indents.." Text="I am implementing simple rotation but the object is not rotating around the local center instead it is rotating around world origin.&#xD;&#xA;&#xD;&#xA;This is the code:&#xD;&#xA;&#xD;&#xA;    Matrix2D m = Matrix2D.Rotate((float) (Math.PI));&#xD;&#xA;&#xD;&#xA;    Point p =  new Point(new Vector2D(-0.1f,0.7f),this, new PixelData(255, 255, 0, 0));&#xD;&#xA;    Point p2 = new Point(new Vector2D(0,0.8f),this, new PixelData(255, 255, 0, 0));&#xD;&#xA;    Point p3 = new Point(new Vector2D(0.1f,0.7f),this, new PixelData(255, 255, 0, 0));&#xD;&#xA;&#xD;&#xA;    Vector2D v = Matrix2D.MatrixTimesVector2D(m, p.getPosition());&#xD;&#xA;    Vector2D v2 = Matrix2D.MatrixTimesVector2D(m, p2.getPosition());&#xD;&#xA;    Vector2D v3 = Matrix2D.MatrixTimesVector2D(m, p3.getPosition());&#xD;&#xA;&#xD;&#xA;    Point z = new Point(v, this, p.getColour());&#xD;&#xA;    Point z2 = new Point(v2, this, p.getColour());&#xD;&#xA;    Point z3 = new Point(v3, this, p.getColour());&#xD;&#xA;&#xD;&#xA;    new Triangle(z2.Transform(), z.Transform(), z3.Transform(),this).DrawTriangle();&#xD;&#xA;&#xD;&#xA;I checked my matrices and matrix multiplication is correct.&#xD;&#xA; &#xD;&#xA;Result without rotation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And after rotation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Why i am getting this weird rotation ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CcoSg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3eTRX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19760" PostHistoryTypeId="24" PostId="3571" RevisionGUID="fc7f3542-5072-4e76-bb63-01da78a2bb76" CreationDate="2018-05-10T20:12:30.460" Comment="Proposed by 7220 approved by 209, 6 edit id of 411" ContentLicense="CC BY-SA 4.0" />
  <row Id="19761" PostHistoryTypeId="2" PostId="7612" RevisionGUID="17003dc6-8169-406c-99a5-9120f9ae2d9d" CreationDate="2018-05-11T01:25:29.377" UserId="8699" Text="Let's say I have the following hierarchy:&#xD;&#xA;&#xD;&#xA;    Bone A&#xD;&#xA;        Bone B&#xD;&#xA;            Bone C&#xD;&#xA;&#xD;&#xA;Here's how most tutorial is telling me how to calculate the finalMatrix to be sent to shader.&#xD;&#xA;&#xD;&#xA;    bonePoseToWorldPose(Joint * joint, glm::mat4 &amp; parentTransform, glm::mat4 &amp; globalInverseTransform) {&#xD;&#xA;	    joint-&gt;finalTransform = parentTransform * joint-&gt;localTransform; // local transform is the result of interpolating 2 keyframes&#xD;&#xA;        for (int i = 0; i &lt; joint-&gt;children.size(); i++) {&#xD;&#xA;		    bonePoseToWorldPose(joint-&gt;children[i], joint-&gt;finalTransform, globalInverseTransform);&#xD;&#xA;	    }&#xD;&#xA;	    joint-&gt;finalTransform = joint-&gt;finalTransform * joint-&gt;inverseBindTransform;  &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Doing it this way, the final transform in bone C for example, would be localTransformA * localTransformB * localTransformC * jointInverseBindTransform.&#xD;&#xA;&#xD;&#xA;Which does not make sense to me, and none of the tutorial satisfactorily explains that. Let's go back to the example again. the inverse bind transform would bring a vertex V from mesh space to bone space of Bone C. At bone space C, it would be multiplied with the localTransformC (or interpolated transform C), which I guess would set the model to our desired pose. But what are A and B doing there? " ContentLicense="CC BY-SA 4.0" />
  <row Id="19762" PostHistoryTypeId="1" PostId="7612" RevisionGUID="17003dc6-8169-406c-99a5-9120f9ae2d9d" CreationDate="2018-05-11T01:25:29.377" UserId="8699" Text="Skeletal animation: What is the purpose of multiplying interpolated bone matrix with parent's matrix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19763" PostHistoryTypeId="3" PostId="7612" RevisionGUID="17003dc6-8169-406c-99a5-9120f9ae2d9d" CreationDate="2018-05-11T01:25:29.377" UserId="8699" Text="|opengl|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19764" PostHistoryTypeId="2" PostId="7613" RevisionGUID="989a8e2d-e8f4-4f10-87f1-e41327c9c425" CreationDate="2018-05-11T04:26:48.890" UserId="48" Text="The bone transforms are relative to their parent in the hierarchy. That's the point of the hierarchy, i.e. when you move your arm, your hand and fingers go along with it. So when an animation (or whatever) changes the transform of A, then bones B and C are supposed to move along with it.&#xD;&#xA;&#xD;&#xA;This is accomplished by defining bone B relative to A, and C relative to B, and so on.&#xD;&#xA;&#xD;&#xA;Therefore, to get the final transform from bone local space to world space, you have to combine all the transforms from the current bone up the hierarchy to the root.&#xD;&#xA;&#xD;&#xA;To put it another way:&#xD;&#xA;&#xD;&#xA;* The `localTransform` of C takes you to B's local space.&#xD;&#xA;* Then the `localTransform` of B takes you to A's local space.&#xD;&#xA;* Then the `localTransform` of A takes you to world space (since A is the root)." ContentLicense="CC BY-SA 4.0" />
  <row Id="19768" PostHistoryTypeId="2" PostId="7615" RevisionGUID="02547f86-cc04-401d-936f-6a7aa7ad62ca" CreationDate="2018-05-11T07:29:11.860" UserId="7647" Text="The epsilon is there to counter [floating-point accuracy problems][1].  Note that the code checks that the algorithm is between $-\epsilon$ and $\epsilon$; that is, close to zero.  If the determinant is zero, then the ray lies in the plane of the triangle and can be safely said to not intersect it (as the alternative, an edge-on intersection, should be caught by neighbouring triangles in the mesh).&#xD;&#xA;&#xD;&#xA;The Cramer's rule computation of the intersection point then *divides* by the determinant, and here's where the floating-point accuracy comes in.  If the determinant is merely very close to zero, not exactly equal to it, then its reciprocal will be very large.  We multiply the other determinants by this reciprocal, so small floating-point errors in their values will be blown up into significance and make the difference between an intersection and a non-intersection.&#xD;&#xA;&#xD;&#xA;I haven't tested it, but I suspect that leaving out the epsilon will cause intersections on the silhouette of a mesh (i.e. with triangles close to parallel with the ray direction) to become very nondeterministic.  This would result in nearby rays either missing or hitting the triangles unpredictably and giving you speckling.&#xD;&#xA;&#xD;&#xA;The value of the epsilon depends on the floating-point precision you're using. It should be small enough that only very grazing intersections are culled, but large enough that it avoids the speckling problem.  It can be determined by experiment, or by just eyeballing it.  The implementation you linked to uses $\epsilon = 10^{-7}$, which is a reasonable choice for single-precision arithmetic; you may want to use $10^{-9}$ or $10^{-10}$ for double-precision computations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems" ContentLicense="CC BY-SA 4.0" />
  <row Id="19769" PostHistoryTypeId="2" PostId="7616" RevisionGUID="414ec8d9-3eb8-455d-8daf-503238a367a5" CreationDate="2018-05-11T09:22:19.260" UserId="3041" Text="I display text using OpenGL which is aligned with (2D) objects that can have any rotation on display, making the text also appear at any angle on display. So far I've used FreeType to render raster for each supported symbol to file and load the files into OpenGL as textures at application start.&#xD;&#xA;&#xD;&#xA;When the text is rotated (other than 90 degree increments) the hinting goes all bad. My plan so far to remedy the situation is to render a few rotated (transformed) variants of each symbol and linearly interpolate between the two closest variants. As an example I may render variants in 15 degree increments between 0-75 degrees inclusive, and if text is rotated by 5 degrees on display I'd take 1/3 from the 0 degree raster and 2/3 from the 15 degree raster.&#xD;&#xA;&#xD;&#xA;...but this is only a theory of mine. Should work if having small enough increments, but if there are too many of them I'll run out of memory resources and making the shader awfully inefficient. I imagine the increment count depends on the pixel size of each symbol which could turn problematic...&#xD;&#xA;&#xD;&#xA;So I reach out to the expert community: How to render rotated text with proper font hinting in real-time?&#xD;&#xA;&#xD;&#xA;Using OpenGL ES 2.0. Font size ~16pix. If you need more info ask away." ContentLicense="CC BY-SA 4.0" />
  <row Id="19770" PostHistoryTypeId="1" PostId="7616" RevisionGUID="414ec8d9-3eb8-455d-8daf-503238a367a5" CreationDate="2018-05-11T09:22:19.260" UserId="3041" Text="How to rendered arbitrary rotated text with decent hinting in real time?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19771" PostHistoryTypeId="3" PostId="7616" RevisionGUID="414ec8d9-3eb8-455d-8daf-503238a367a5" CreationDate="2018-05-11T09:22:19.260" UserId="3041" Text="|opengl|opengl-es|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19772" PostHistoryTypeId="2" PostId="7617" RevisionGUID="1a63d2ac-089b-4a5b-a4c8-1a64671d9b6c" CreationDate="2018-05-11T09:46:13.190" UserId="8705" Text="Consider a situation where there are 3 different buffers describing a particular mesh piece: ```vBuffer```, ```nBuffer```, ```iBuffer``` (vertices, normals, and indices) which equate to ```totalBufferSize``` in aggregate.&#xD;&#xA;&#xD;&#xA;I want to save these 3 buffers to the same default heap (D3D12_HEAP_TYPE_DEFAULT).  I know I still need to use an upload heap (D3D12_HEAP_TYPE_UPLOAD) as an intermediary but I can't figure out how to eliminate extra copies.&#xD;&#xA;&#xD;&#xA;Currently my code (which works) does the following:&#xD;&#xA;&#xD;&#xA;        const D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);&#xD;&#xA;        const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;        const CD3DX12_RESOURCE_DESC resourceDescV = CD3DX12_RESOURCE_DESC::Buffer(totalBufferSize);&#xD;&#xA;        DX::ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;            &amp;defaultHeapProperties,&#xD;&#xA;            D3D12_HEAP_FLAG_NONE,&#xD;&#xA;            &amp;resourceDescV,&#xD;&#xA;            D3D12_RESOURCE_STATE_COPY_DEST,&#xD;&#xA;            nullptr,&#xD;&#xA;            IID_PPV_ARGS(meshPart.m_mainBuffer.ReleaseAndGetAddressOf())));&#xD;&#xA;&#xD;&#xA;        DX::ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;            &amp;uploadHeapProperties,&#xD;&#xA;            D3D12_HEAP_FLAG_NONE,&#xD;&#xA;            &amp;resourceDescV,&#xD;&#xA;            D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;            nullptr,&#xD;&#xA;            IID_PPV_ARGS(meshPart.m_uploadBuffer.ReleaseAndGetAddressOf())));&#xD;&#xA;&#xD;&#xA;        uint8_t * bufferStart{};&#xD;&#xA;        const CD3DX12_RANGE readRange(0, 0);&#xD;&#xA;        DX::ThrowIfFailed(meshPart.m_uploadBuffer-&gt;Map(0, &amp;readRange, reinterpret_cast&lt;void **&gt;(&amp;bufferStart)));&#xD;&#xA;&#xD;&#xA;        // Can these be eliminated?&#xD;&#xA;        uint32_t offset{};&#xD;&#xA;        std::memcpy(bufferStart, vBuffer.data, vBuffer.totalSize);&#xD;&#xA;        offset += vBuffer.totalSize;&#xD;&#xA;        std::memcpy(bufferStart + offset, nBuffer.data, nBuffer.totalSize);&#xD;&#xA;        offset += nBuffer.totalSize;&#xD;&#xA;        std::memcpy(bufferStart + offset, iBuffer.data, iBuffer.totalSize);&#xD;&#xA;&#xD;&#xA;        D3D12_SUBRESOURCE_DATA bufferData{};&#xD;&#xA;        bufferData.pData = bufferStart;&#xD;&#xA;        bufferData.RowPitch = totalBufferSize;&#xD;&#xA;        bufferData.SlicePitch = totalBufferSize;&#xD;&#xA;&#xD;&#xA;        UpdateSubresources&lt;1&gt;(commandList, meshPart.m_mainBuffer.Get(), meshPart.m_uploadBuffer.Get(), 0, 0, 1, &amp;bufferData);&#xD;&#xA;        CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(meshPart.m_mainBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);&#xD;&#xA;        commandList-&gt;ResourceBarrier(1, &amp;barrier);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, I'm trying to figure out if I can eliminate those std::memcpy calls.   All examples of UpdateSubresources I've seen do not explicitly Map+memcpy into the upload buffer.  They just set ```D3D12_SUBRESOURCE_DATA.pData``` directly.&#xD;&#xA;&#xD;&#xA;I tried calling using ```UpdateSubresources&lt;3&gt;``` and passing in an array of D3D12_SUBRESOURCE_DATA, each pointing to the beginning of my mesh buffers, but the validation layer didn't like that and threw an exception.&#xD;&#xA;&#xD;&#xA;Is it possible to upload all 3 buffers in one step here -- without the explicit Map and memcpy steps?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19773" PostHistoryTypeId="1" PostId="7617" RevisionGUID="1a63d2ac-089b-4a5b-a4c8-1a64671d9b6c" CreationDate="2018-05-11T09:46:13.190" UserId="8705" Text="DirectX 12: Uploading multiple buffers to 1 default heap using the UpdateSubresources API without explicit copies" ContentLicense="CC BY-SA 4.0" />
  <row Id="19774" PostHistoryTypeId="3" PostId="7617" RevisionGUID="1a63d2ac-089b-4a5b-a4c8-1a64671d9b6c" CreationDate="2018-05-11T09:46:13.190" UserId="8705" Text="|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19775" PostHistoryTypeId="2" PostId="7618" RevisionGUID="2f10a15a-04be-4cde-b65d-a103a00b42e7" CreationDate="2018-05-11T10:23:54.413" UserId="3123" Text="`UpdateSubresources` is a helper function. Inside it is another `memcpy`. I would recommend to simply rewrite it - source is in [d3dx12.h][1]. Then you will be able to copy your data no more than necessary.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://code.msdn.microsoft.com/Direct3D-12-UAP-Sample-ecb1779f/sourcecode?fileId=139518&amp;pathId=1775568253" ContentLicense="CC BY-SA 4.0" />
  <row Id="19776" PostHistoryTypeId="5" PostId="7618" RevisionGUID="388a2828-54c7-444f-b287-87ae43469ff2" CreationDate="2018-05-11T10:53:26.590" UserId="3123" Comment="deleted 1 character in body" Text="`UpdateSubresources` is a helper function. Inside it is another `memcpy`. I would recommend simply rewriting it - source is in [d3dx12.h][1]. Then you will be able to copy your data no more than necessary.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://code.msdn.microsoft.com/Direct3D-12-UAP-Sample-ecb1779f/sourcecode?fileId=139518&amp;pathId=1775568253" ContentLicense="CC BY-SA 4.0" />
  <row Id="19781" PostHistoryTypeId="6" PostId="7616" RevisionGUID="577ebe45-085a-4a11-ba18-d0d44c92c2ee" CreationDate="2018-05-11T13:23:09.003" UserId="2654" Comment="edited tags" Text="|opengl-es|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19793" PostHistoryTypeId="50" PostId="7496" RevisionGUID="72921dfa-9f2e-46e8-8e87-f7357aace3f5" CreationDate="2018-05-12T00:08:32.277" UserId="-1" />
  <row Id="19794" PostHistoryTypeId="2" PostId="7623" RevisionGUID="3678803e-7b09-4f06-8488-25c3f081855e" CreationDate="2018-05-12T02:23:24.893" UserId="8719" Text="Given two cuboids in 3D space (8 vertex coordinates each) that are arbitrarily oriented, how can we find the volume of overlap between them in the fastest manner? " ContentLicense="CC BY-SA 4.0" />
  <row Id="19795" PostHistoryTypeId="1" PostId="7623" RevisionGUID="3678803e-7b09-4f06-8488-25c3f081855e" CreationDate="2018-05-12T02:23:24.893" UserId="8719" Text="How to compute volume of intersection of non-axis-aligned cuboids in 3D?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19796" PostHistoryTypeId="3" PostId="7623" RevisionGUID="3678803e-7b09-4f06-8488-25c3f081855e" CreationDate="2018-05-12T02:23:24.893" UserId="8719" Text="|3d|mathematics|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19798" PostHistoryTypeId="2" PostId="7624" RevisionGUID="6d1e6b6d-9dd0-4594-8c72-b57321b0832d" CreationDate="2018-05-12T13:20:58.187" UserId="1952" Text="The cosine term in the rendering equation is to account the amount of light reaching the surface, and leaving it out from the rendering equation is what he refers as &quot;complete nonsense&quot;, which is right. The original Phong model didn't have the cosine term in the rendering equation, so if you want to model the original nonsensical Phong with proper rendering equation, you need to hack it by adding the cosine denominator to the Phong BRDF." ContentLicense="CC BY-SA 4.0" />
  <row Id="19802" PostHistoryTypeId="50" PostId="4632" RevisionGUID="c307bfb0-6af6-48d1-a7ee-ff6c4a4bab15" CreationDate="2018-05-12T23:10:35.113" UserId="-1" />
  <row Id="19806" PostHistoryTypeId="2" PostId="7627" RevisionGUID="4f629840-a1f6-454b-acad-73230c5b4bcd" CreationDate="2018-05-13T07:40:35.490" UserId="8723" Text="I am using the de boors algorithm to generate B splines in python. However I am getting spikes in the final figure. I do not understand why this happens. I am posting my code here for reference &#xD;&#xA;&#xD;&#xA;    def knot_values(n,k):&#xD;&#xA;	      t = np.zeros((1,n+k+1))&#xD;&#xA;	      for i in range(0,n+k+1):&#xD;&#xA;                if i&lt;k:&#xD;&#xA;                   t[0][i] = 0&#xD;&#xA;                if i&gt;=k and i&lt;=n:&#xD;&#xA;                   t[0][i] = i-k+1&#xD;&#xA;                if i&gt;n:&#xD;&#xA;                   t[0][i] = n-k+2&#xD;&#xA;&#xD;&#xA;	      return t&#xD;&#xA;&#xD;&#xA;    def basis_spline(u,t,i,k):&#xD;&#xA;	    if k==1:&#xD;&#xA;		    if u&gt;=t[0][i] and u&lt;=t[0][i+1]:&#xD;&#xA;			     sol = 1&#xD;&#xA;		    else:&#xD;&#xA;			     sol = 0&#xD;&#xA;	    else:&#xD;&#xA;            a = (u - t[0][i])*basis_spline(u,t,i,k-1)&#xD;&#xA;            b = t[0][i+k-1] - t[0][i]&#xD;&#xA;            c = (t[0][i+k] - u)*basis_spline(u,t,i+1,k-1)&#xD;&#xA;            d = t[0][i+k] - t[0][i+1]       &#xD;&#xA;            if b == 0:&#xD;&#xA;                temp1 = 0&#xD;&#xA;            else:&#xD;&#xA;                temp1 = a/b&#xD;&#xA;        &#xD;&#xA;            if d == 0:&#xD;&#xA;                temp2 = 0&#xD;&#xA;            else:&#xD;&#xA;                temp2 = c/d    &#xD;&#xA;            &#xD;&#xA;		&#xD;&#xA;            sol = (temp1) + (temp2)&#xD;&#xA;		&#xD;&#xA;	    return sol&#xD;&#xA;&#xD;&#xA;    def curve_generator(n,k,ctrl_x,ctrl_y):&#xD;&#xA;&#xD;&#xA;        t = knot_values(n,k)&#xD;&#xA;        print(t)&#xD;&#xA;        u = np.arange(t[0][k-1],t[0][n+1],0.001);&#xD;&#xA;        length = u.shape;&#xD;&#xA;&#xD;&#xA;        x = np.zeros((1,length[0]));&#xD;&#xA;        y = np.zeros((1,length[0]));&#xD;&#xA;    &#xD;&#xA;        for i in range(0,n+1):&#xD;&#xA;            for j in range(0,length[0]): &#xD;&#xA;                x[0][j] = x[0][j] + basis_spline(u[j],t,i,k)*ctrl_x[i];&#xD;&#xA;                y[0][j] = y[0][j] + basis_spline(u[j],t,i,k)*ctrl_y[i];&#xD;&#xA;            &#xD;&#xA;        return x,y &#xD;&#xA;&#xD;&#xA;        n = 6&#xD;&#xA;        k = 3&#xD;&#xA;        ctrl_x = np.array([0,3,6,9,10,12,15])&#xD;&#xA;        ctrl_y = np.array([0,4,2,3,7,8,5])&#xD;&#xA;&#xD;&#xA;        [x,y] = curve_generator(n,k,ctrl_x,ctrl_y)&#xD;&#xA;&#xD;&#xA;        n = x.shape&#xD;&#xA;        a = [0]*n[1]&#xD;&#xA;        b = [0]*n[1]&#xD;&#xA;        for i in range(0,n[1]):&#xD;&#xA;            a[i] = x[0][i]&#xD;&#xA;            b[i] = y[0][i]&#xD;&#xA;&#xD;&#xA;        plt.plot(a,b)&#xD;&#xA;        plt.show()[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5ag7U.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="19807" PostHistoryTypeId="1" PostId="7627" RevisionGUID="4f629840-a1f6-454b-acad-73230c5b4bcd" CreationDate="2018-05-13T07:40:35.490" UserId="8723" Text="B spline curve generation in Python" ContentLicense="CC BY-SA 4.0" />
  <row Id="19808" PostHistoryTypeId="3" PostId="7627" RevisionGUID="4f629840-a1f6-454b-acad-73230c5b4bcd" CreationDate="2018-05-13T07:40:35.490" UserId="8723" Text="|bezier-curve|curve|nurbs|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19810" PostHistoryTypeId="5" PostId="7627" RevisionGUID="a4a3f3ca-732e-44b2-a969-1cf9b1b2d9da" CreationDate="2018-05-13T10:02:09.597" UserId="2041" Comment="Your image was inside the code block so it wasn't showing up. Please check for errors like this when you post the question." Text="I am using the de boors algorithm to generate B splines in python. However I am getting spikes in the final figure. I do not understand why this happens. I am posting my code here for reference &#xD;&#xA;&#xD;&#xA;    def knot_values(n,k):&#xD;&#xA;	      t = np.zeros((1,n+k+1))&#xD;&#xA;	      for i in range(0,n+k+1):&#xD;&#xA;                if i&lt;k:&#xD;&#xA;                   t[0][i] = 0&#xD;&#xA;                if i&gt;=k and i&lt;=n:&#xD;&#xA;                   t[0][i] = i-k+1&#xD;&#xA;                if i&gt;n:&#xD;&#xA;                   t[0][i] = n-k+2&#xD;&#xA;&#xD;&#xA;	      return t&#xD;&#xA;&#xD;&#xA;    def basis_spline(u,t,i,k):&#xD;&#xA;	    if k==1:&#xD;&#xA;		    if u&gt;=t[0][i] and u&lt;=t[0][i+1]:&#xD;&#xA;			     sol = 1&#xD;&#xA;		    else:&#xD;&#xA;			     sol = 0&#xD;&#xA;	    else:&#xD;&#xA;            a = (u - t[0][i])*basis_spline(u,t,i,k-1)&#xD;&#xA;            b = t[0][i+k-1] - t[0][i]&#xD;&#xA;            c = (t[0][i+k] - u)*basis_spline(u,t,i+1,k-1)&#xD;&#xA;            d = t[0][i+k] - t[0][i+1]       &#xD;&#xA;            if b == 0:&#xD;&#xA;                temp1 = 0&#xD;&#xA;            else:&#xD;&#xA;                temp1 = a/b&#xD;&#xA;        &#xD;&#xA;            if d == 0:&#xD;&#xA;                temp2 = 0&#xD;&#xA;            else:&#xD;&#xA;                temp2 = c/d    &#xD;&#xA;            &#xD;&#xA;		&#xD;&#xA;            sol = (temp1) + (temp2)&#xD;&#xA;		&#xD;&#xA;	    return sol&#xD;&#xA;&#xD;&#xA;    def curve_generator(n,k,ctrl_x,ctrl_y):&#xD;&#xA;&#xD;&#xA;        t = knot_values(n,k)&#xD;&#xA;        print(t)&#xD;&#xA;        u = np.arange(t[0][k-1],t[0][n+1],0.001);&#xD;&#xA;        length = u.shape;&#xD;&#xA;&#xD;&#xA;        x = np.zeros((1,length[0]));&#xD;&#xA;        y = np.zeros((1,length[0]));&#xD;&#xA;    &#xD;&#xA;        for i in range(0,n+1):&#xD;&#xA;            for j in range(0,length[0]): &#xD;&#xA;                x[0][j] = x[0][j] + basis_spline(u[j],t,i,k)*ctrl_x[i];&#xD;&#xA;                y[0][j] = y[0][j] + basis_spline(u[j],t,i,k)*ctrl_y[i];&#xD;&#xA;            &#xD;&#xA;        return x,y &#xD;&#xA;&#xD;&#xA;        n = 6&#xD;&#xA;        k = 3&#xD;&#xA;        ctrl_x = np.array([0,3,6,9,10,12,15])&#xD;&#xA;        ctrl_y = np.array([0,4,2,3,7,8,5])&#xD;&#xA;&#xD;&#xA;        [x,y] = curve_generator(n,k,ctrl_x,ctrl_y)&#xD;&#xA;&#xD;&#xA;        n = x.shape&#xD;&#xA;        a = [0]*n[1]&#xD;&#xA;        b = [0]*n[1]&#xD;&#xA;        for i in range(0,n[1]):&#xD;&#xA;            a[i] = x[0][i]&#xD;&#xA;            b[i] = y[0][i]&#xD;&#xA;&#xD;&#xA;        plt.plot(a,b)&#xD;&#xA;        plt.show()&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5ag7U.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="19811" PostHistoryTypeId="2" PostId="7628" RevisionGUID="2a2c4935-20db-4250-91be-6224787161f0" CreationDate="2018-05-13T19:13:52.070" UserId="8541" Text="I'm implementing manual interpolation between texels in a 3D texture to be able to discard some of them when needed. Compared to hardware interpolation, this process takes a lot of time. If I simply leverage hardware interpolation using `texture` function, rendering takes ~5ms, but with manual fetch using `texelFetch` it rises to ~13ms (using `texture` to fetch 8 texels manually increases frame time even further - to ~35ms). The multiplication/summing part of the manual lerp does't matter much - I've tried fetching same texel manually 8 times and the performance is close to hardware interpolation. I thought fetching neighboring texels should give me good cache behavior, but maybe that only applies to 2D textures because neighboring layers of 3D tex are not so cache friendly? Don't know what to think here.. It would be nice if there was some way to use hardware interpolation but discard some texels from the process." ContentLicense="CC BY-SA 4.0" />
  <row Id="19812" PostHistoryTypeId="1" PostId="7628" RevisionGUID="2a2c4935-20db-4250-91be-6224787161f0" CreationDate="2018-05-13T19:13:52.070" UserId="8541" Text="Fetching 8 neighboring texels from 3D texture greatly decreases performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="19813" PostHistoryTypeId="3" PostId="7628" RevisionGUID="2a2c4935-20db-4250-91be-6224787161f0" CreationDate="2018-05-13T19:13:52.070" UserId="8541" Text="|opengl|glsl|fragment-shader|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19814" PostHistoryTypeId="5" PostId="7597" RevisionGUID="853db562-7833-42fe-b015-195873a6d71c" CreationDate="2018-05-13T19:24:41.620" UserId="7462" Comment="added 856 characters in body" Text="The typical scenario for using a texture would simply be:&#xD;&#xA;&#xD;&#xA;    //Create texture&#xD;&#xA;    glGenTextures(1, &amp;textureID);&#xD;&#xA;    glBindTexture(target, textureID);&#xD;&#xA;    glTexImage2D(target, 0, color_format, width, height, 0,&#xD;&#xA;        color_format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;	glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;	glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;	glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;	glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;    //load to program&#xD;&#xA;    glActiveTexture(texture_unit);&#xD;&#xA;	glBindTexture(target, textureID);&#xD;&#xA;    //Get the uniform location in the program and attach the texture unit&#xD;&#xA;    GLuint location = /*get_uniform_location*/;&#xD;&#xA;    glUniform1i(location,texture_unit - GL_TEXTURE0);&#xD;&#xA;&#xD;&#xA;    //Draw&#xD;&#xA;    render();&#xD;&#xA;&#xD;&#xA;However image load store are somewhat different. First, they don't use texture units but image units. Second you need to manually set memory barriers yourself to ensure completion of writing stage before reading. Amgon other things.&#xD;&#xA;&#xD;&#xA;I have read the documentation and attempted to implement things myself but It seems I am doing things wrong. I'd rather just forget about what I have tried and understand properly how this needs to be done step by step.&#xD;&#xA;&#xD;&#xA;I want to know what a typical, minimum example use of image load stores qould be.&#xD;&#xA;&#xD;&#xA;So creation of the image, writing to the image, reading from the image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19815" PostHistoryTypeId="33" PostId="7597" RevisionGUID="da38eb8e-ba7f-4124-ba34-d31998f149bb" CreationDate="2018-05-13T19:26:08.583" UserId="7462" Comment="46" />
  <row Id="19816" PostHistoryTypeId="5" PostId="7628" RevisionGUID="30c26cf2-32e7-4f16-956e-54240bbae79e" CreationDate="2018-05-13T19:32:56.823" UserId="8541" Comment="added 110 characters in body" Text="I'm implementing manual interpolation between texels in a 3D texture to be able to discard some of them when needed. Compared to hardware interpolation, this process takes a lot of time. If I simply leverage hardware interpolation using `texture` function, rendering takes ~5ms, but with manual fetch using `texelFetch` it rises to ~13ms (using `texture` to fetch 8 texels manually increases frame time even further - to ~35ms). The multiplication/summing part of the manual lerp does't matter much - I've tried fetching same texel manually 8 times and the performance is close to hardware interpolation. I thought fetching neighboring texels should give me good cache behavior, but maybe that only applies to 2D textures because neighboring layers of 3D tex are not so cache friendly? Don't know what to think here.. It would be nice if there was some way to use hardware interpolation but discard some texels from the process. The absence of a `textureGather` function taking a 3D texture also makes me think I'm missing something here." ContentLicense="CC BY-SA 4.0" />
  <row Id="19817" PostHistoryTypeId="50" PostId="7494" RevisionGUID="3c2f2a5e-992c-457b-a460-3ff227119475" CreationDate="2018-05-13T21:11:23.177" UserId="-1" />
  <row Id="19818" PostHistoryTypeId="2" PostId="7629" RevisionGUID="76e476bb-8c67-474b-b3fd-5123c2a6217c" CreationDate="2018-05-13T21:44:43.470" UserId="8725" Text="I was wondering if anyone could explain how the Painter's algorithm would handle transparent objects? Can the Painter's algorithm handle transparency?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19819" PostHistoryTypeId="1" PostId="7629" RevisionGUID="76e476bb-8c67-474b-b3fd-5123c2a6217c" CreationDate="2018-05-13T21:44:43.470" UserId="8725" Text="How does the Painter's Algorithm handle transparency?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19820" PostHistoryTypeId="3" PostId="7629" RevisionGUID="76e476bb-8c67-474b-b3fd-5123c2a6217c" CreationDate="2018-05-13T21:44:43.470" UserId="8725" Text="|rendering|algorithm|transparency|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19821" PostHistoryTypeId="2" PostId="7630" RevisionGUID="6ac58a81-e2ba-485b-8896-4786d7bdd3a4" CreationDate="2018-05-13T23:49:57.573" UserId="6" Text="The common way to render transparent polygons in a rasterizer is by use of **[Alpha Blending](https://en.wikipedia.org/wiki/Alpha_compositing), which basically combines the colour of the supposedly transparent pixel with the colour of the background at that pixel's position**, this way rendering the pixel transparently onto what was already rendered before. This technique, however, requires your polygons (or at least the transparent ones) to be sorted from back to front, at least in general non-trivial cases, since you can only combine the transparent colour with what has already been rendered behind it.&#xD;&#xA;&#xD;&#xA;But since the **[Painter's Algorithm](https://en.wikipedia.org/wiki/Painter%27s_algorithm) *already* requires ploygons to be sorted from back to front** (which is pretty much the entire essence of the algorithm), this just fits naturally into the rest of the algorithm. Thus, **supporting transparency becomes rather straight forward** by simply doing any variant of alpha blending of the pixel with the background instead of overwriting the background." ContentLicense="CC BY-SA 4.0" />
  <row Id="19822" PostHistoryTypeId="4" PostId="7628" RevisionGUID="ce100919-a88f-430d-91fc-2cf7664c8283" CreationDate="2018-05-14T09:34:37.103" UserId="8541" Comment="Made the title a bit more precise" Text="Manually fetching 8 neighboring texels from 3D texture greatly decreases performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="19823" PostHistoryTypeId="50" PostId="7487" RevisionGUID="22e198bb-f2ee-4e29-b6ee-b951e89757ba" CreationDate="2018-05-14T11:11:25.787" UserId="-1" />
  <row Id="19824" PostHistoryTypeId="2" PostId="7631" RevisionGUID="da4bcb86-d680-40b1-bc5b-92e806805325" CreationDate="2018-05-14T11:23:18.967" UserId="1937" Text="I've used `imageStore` as part of compute shaders doing surface extraction. I've only ever used it in compute shaders, to store the calculated data in a texture to be consumed by another shader - I know it's possible to do `imageStore` in a fragment shader as well but I haven't come across a use case for it yet.&#xD;&#xA;&#xD;&#xA;I also haven't used `imageLoad` at all, since apparently `texelFetch` is often faster (benefits from using the texture cache), and at worst no slower, so I simply bound the same texture to both an image and a texture unit, and used `imageStore` for writes and `texelFetch` for reads.&#xD;&#xA;&#xD;&#xA;The code to get it all working looked something like this (using OpenGL 4.5 and DSA, and assuming `cShdr` holds a compute program that does `imageStore` on channel 0):&#xD;&#xA;&#xD;&#xA;    GLuint tex;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;tex);&#xD;&#xA;    glTextureStorage2D(tex, 1, GL_RGBA32F, 256, 256);&#xD;&#xA;    glBindTextureUnit(0, tex)&#xD;&#xA;    glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;    &#xD;&#xA;    glDispatchCompute(cShdr, numX, numY, numZ);&#xD;&#xA;    glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);&#xD;&#xA;    &#xD;&#xA;    //code that samples the texture&#xD;&#xA;&#xD;&#xA;The first 3 parameters to `glBindImageTexture` are image unit, texture, and mip level. The next two deal with binding arrays of textures, and should just be set to `GL_FALSE, 0` when binding a single texture. The final two are access and format (for stores). &#xD;&#xA;&#xD;&#xA;Note that although I've used the GL 4.5-specific functions for creating textures and binding the texture unit, the `glBindImageTexture` works with every version that supports load/store - 4.2 and above.&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="19825" PostHistoryTypeId="2" PostId="7632" RevisionGUID="58a84791-5fec-4281-ae02-8f1367925e17" CreationDate="2018-05-14T15:31:52.140" UserId="6698" Text="I think this is one of the most important part when you write a physically-based renderer.&#xD;&#xA;&#xD;&#xA;The solution I came up with is to put a sphere to the scene with a constant background radiance. Solve the rendering equation analytically for constant radiance which you have chosen. There will be no recursion in the integral since the rays will not bounce more than one. After that, compare result of the rendered image and the analytic solution. Does this make sense?&#xD;&#xA;&#xD;&#xA;Are there any ways to this more effectively?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19826" PostHistoryTypeId="1" PostId="7632" RevisionGUID="58a84791-5fec-4281-ae02-8f1367925e17" CreationDate="2018-05-14T15:31:52.140" UserId="6698" Text="How to validate whether a reflection model is implemented correctly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19827" PostHistoryTypeId="3" PostId="7632" RevisionGUID="58a84791-5fec-4281-ae02-8f1367925e17" CreationDate="2018-05-14T15:31:52.140" UserId="6698" Text="|pathtracing|brdf|physically-based|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19828" PostHistoryTypeId="50" PostId="6180" RevisionGUID="6c2be1eb-4b16-4579-9831-03d74db00bd3" CreationDate="2018-05-14T20:11:25.787" UserId="-1" />
  <row Id="19829" PostHistoryTypeId="2" PostId="7633" RevisionGUID="6cd79224-bce7-4d97-8e07-715242220287" CreationDate="2018-05-14T23:54:35.233" UserId="4820" Text="I am trying to verify that if I have my `inNormal` and some `N` amount of morph normals that I would want to do something such as&#xD;&#xA;&#xD;&#xA;    outNormal = vec3(inNormal);&#xD;&#xA;    outNormal += morphNormal0 * morphWeight0;&#xD;&#xA;    outNormal += morphNormal1 * morphWeight1;&#xD;&#xA;    ...&#xD;&#xA;    outNormal += morphNormalN * morphWeightN;&#xD;&#xA;&#xD;&#xA;This seems to work for me (don't have a ground truth to compare) so I wanted to test it in Three.js knowing it would have an established method and I see [they use][1]&#xD;&#xA;&#xD;&#xA;	objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];&#xD;&#xA;	objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];&#xD;&#xA;	objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];&#xD;&#xA;	objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];&#xD;&#xA;&#xD;&#xA;So now I am wondering how that math works out as it doesn't work for me. Both methods end up multiplying it by a `normalMatrix`so not sure what would be different.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl" ContentLicense="CC BY-SA 4.0" />
  <row Id="19830" PostHistoryTypeId="1" PostId="7633" RevisionGUID="6cd79224-bce7-4d97-8e07-715242220287" CreationDate="2018-05-14T23:54:35.233" UserId="4820" Text="Morph Targets Normal adding math" ContentLicense="CC BY-SA 4.0" />
  <row Id="19831" PostHistoryTypeId="3" PostId="7633" RevisionGUID="6cd79224-bce7-4d97-8e07-715242220287" CreationDate="2018-05-14T23:54:35.233" UserId="4820" Text="|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19839" PostHistoryTypeId="5" PostId="7633" RevisionGUID="f5707d34-b4e0-43a3-b319-f22f3df733a7" CreationDate="2018-05-15T19:39:35.710" UserId="4820" Comment="added 56 characters in body" Text="I am trying to verify that if I have my `inNormal` and some `N` amount of morph normals that I would want to do something such as&#xD;&#xA;&#xD;&#xA;    outNormal = vec3(inNormal);&#xD;&#xA;    outNormal += morphNormal0 * morphWeight0;&#xD;&#xA;    outNormal += morphNormal1 * morphWeight1;&#xD;&#xA;    ...&#xD;&#xA;    outNormal += morphNormalN * morphWeightN;&#xD;&#xA;&#xD;&#xA;This seems to work for me (don't have a ground truth to compare) so I wanted to test it in Three.js knowing it would have an established method and I see [they use][1]&#xD;&#xA;&#xD;&#xA;	objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];&#xD;&#xA;	objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];&#xD;&#xA;	objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];&#xD;&#xA;	objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];&#xD;&#xA;&#xD;&#xA;So now I am wondering how that math works out as it doesn't work for me. Both methods end up multiplying it by a `normalMatrix`so not sure what would be different.&#xD;&#xA;&#xD;&#xA;**edit**: Assuming both are loading in glTF 2.0 models&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl" ContentLicense="CC BY-SA 4.0" />
  <row Id="19840" PostHistoryTypeId="5" PostId="7631" RevisionGUID="4f64b4a5-8761-46e2-a881-a55fd7c48acc" CreationDate="2018-05-16T04:40:49.207" UserId="1937" Comment="added 712 characters in body" Text="I've used `imageStore` as part of compute shaders doing surface extraction. I've only ever used it in compute shaders, to store the calculated data in a texture to be consumed by another shader - I know it's possible to do `imageStore` in a fragment shader as well but I haven't come across a use case for it yet.&#xD;&#xA;&#xD;&#xA;I also haven't used `imageLoad` at all, since apparently `texelFetch` is often faster (benefits from using the texture cache), and at worst no slower, so I simply bound the same texture to both an image and a texture unit, and used `imageStore` for writes and `texelFetch` for reads.&#xD;&#xA;&#xD;&#xA;The code to get it all working looked something like this (using OpenGL 4.5 and DSA, and assuming `cShdr` holds a compute program that does `imageStore` on channel 0, `cShdr2` is a second compute program that samples the generated texture on channel 0, and `rShdr` is a rendering program that samples the texture on channel 0 - of course, if you don't want to hardcode the texture channel in the shader you can use `glGetUniformLocation`):&#xD;&#xA;&#xD;&#xA;    //setting up texture and binding to image unit 0&#xD;&#xA;    GLuint tex;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;tex);&#xD;&#xA;    glTextureStorage2D(tex, 1, GL_RGBA32F, 256, 256)&#xD;&#xA;    glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;    &#xD;&#xA;    //Dispatch a compute shader to imageStore to the texture&#xD;&#xA;    //wait for completion before allowing sampling&#xD;&#xA;    glDispatchCompute(cShdr, numX, numY, numZ);&#xD;&#xA;    glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);&#xD;&#xA;    &#xD;&#xA;    //code that samples the texture in render loop&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    glBindTextureUnit(0, tex);&#xD;&#xA;    glUseProgram(rShdr);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, numVerts);&#xD;&#xA;&#xD;&#xA;    //or if consuming data in second compute shader using texelFetch&#xD;&#xA;    glBindTextureUnit(0, tex); &#xD;&#xA;    glDispatchCompute(cShdr2, numX, numY, numZ); &#xD;&#xA;&#xD;&#xA;The first 3 parameters to `glBindImageTexture` are image unit, texture, and mip level. The next two deal with binding arrays of textures, and should just be set to `GL_FALSE, 0` when binding a single texture. The final two are access and format (for stores). &#xD;&#xA;&#xD;&#xA;Note that although I've used the GL 4.5-specific functions for creating textures and binding the texture unit, the `glBindImageTexture` works with every version that supports load/store - 4.2 and above.&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="19841" PostHistoryTypeId="2" PostId="7636" RevisionGUID="1bd703b0-4708-40d1-a778-84adc62c6a19" CreationDate="2018-05-16T06:41:51.810" UserId="3434" Text="I'm trying to figure out the correct math to rotate and translate a curve displayed in a fragment shader.&#xD;&#xA;&#xD;&#xA;What I try to accomplish is to define a curve, for example a sine curve, in a local coordinate system, rotate it then translate it. Something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;That was made in MATLAB with the following code:&#xD;&#xA;&#xD;&#xA;    dens = 1080;&#xD;&#xA;    x = linspace(-1.0, 1.0, dens);        &#xD;&#xA;    y = 0.1*sin(25.0*x);&#xD;&#xA;    &#xD;&#xA;    imax = 25;&#xD;&#xA;    for i = 1:imax    &#xD;&#xA;&#xD;&#xA;        %transformation matrix:&#xD;&#xA;        ang = (i/imax)*0.5*3.14;&#xD;&#xA;        c = cos(ang); s = sin(ang);          &#xD;&#xA;        T = [c,-s;s,c];&#xD;&#xA;&#xD;&#xA;        %translation:&#xD;&#xA;        P = [0.5;0.5];&#xD;&#xA;&#xD;&#xA;        %transformed coordinates:&#xD;&#xA;        xt = T(1,:)*[x;y] + P(1);&#xD;&#xA;        yt = T(2,:)*[x;y] + P(2);&#xD;&#xA;        &#xD;&#xA;        plot(xt,yt);&#xD;&#xA;        xlim([0 1.0]); ylim([0 1.0]); drawnow;&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For the GLSL test I'm using the [Book of Shaders Editor][2] with the following code (can also be seen interactively [here][3]): &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #ifdef GL_FRAGMENT_PRECISION_HIGH&#xD;&#xA;    precision highp float;&#xD;&#xA;    #else&#xD;&#xA;    precision mediump float;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    uniform float u_time;&#xD;&#xA;    uniform vec2 u_resolution;&#xD;&#xA;    &#xD;&#xA;    // Plot a line on Y using a value between 0.0-1.0&#xD;&#xA;    float plot(vec2 st, float pct){&#xD;&#xA;      return  smoothstep( pct-0.02, pct, st.y) -&#xD;&#xA;              smoothstep( pct, pct+0.02, st.y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float plotTransformed(vec2 st, float pct, vec2 transl, float ang){&#xD;&#xA;        &#xD;&#xA;        float c = cos(ang); float s = sin(ang);    &#xD;&#xA;        mat2 trans = mat2(c,-s,s,c);    &#xD;&#xA;        st = trans * st;&#xD;&#xA;        &#xD;&#xA;        st -= transl;&#xD;&#xA;        &#xD;&#xA;        return  smoothstep( pct-0.02, pct, st.y) -&#xD;&#xA;              smoothstep( pct, pct+0.02, st.y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main(void) {&#xD;&#xA;        bool use_plot_function = true;&#xD;&#xA;    &#xD;&#xA;        float mx =  max(u_resolution.x, u_resolution.y);&#xD;&#xA;        vec2 uv = gl_FragCoord.xy /mx;&#xD;&#xA;        vec3 color = vec3(0.4,0.4,0.4);&#xD;&#xA;    &#xD;&#xA;        //some screen position:&#xD;&#xA;        vec2 p = vec2(0.5, 0.5);&#xD;&#xA;    &#xD;&#xA;        //the curve:&#xD;&#xA;        vec2 cp = vec2(&#xD;&#xA;            uv.x,&#xD;&#xA;            0.08*sin(uv.x*40.0)&#xD;&#xA;        );&#xD;&#xA;    	&#xD;&#xA;        //the angle to rotate:&#xD;&#xA;        float ang = -0.4 * 3.14 * sin(u_time);&#xD;&#xA;    	&#xD;&#xA;        //Transform coordinates:&#xD;&#xA;        float c = cos(ang); float s = sin(ang);    &#xD;&#xA;        mat2 trans = mat2(c,-s,s,c);    &#xD;&#xA;        vec2 cp_t = trans * cp;    &#xD;&#xA;        cp_t +=p;&#xD;&#xA;        &#xD;&#xA;    	&#xD;&#xA;        &#xD;&#xA;        if(use_plot_function){&#xD;&#xA;            //Attempt 1: plot unrotated original curve translated upwards: &#xD;&#xA;            float curve1 = plot(uv, cp.y + p.y);&#xD;&#xA;            color.g *= curve1;    &#xD;&#xA;    &#xD;&#xA;            //Attemp 2: plot the transformed curve using plotTransformed, rotates first, then translates:&#xD;&#xA;            float curve2 = plotTransformed(uv, cp.y, p, ang);&#xD;&#xA;            color.r *= curve2;&#xD;&#xA;    &#xD;&#xA;            //Attempt 3: curve is transformed first then ploted:&#xD;&#xA;            float curve3 = plot(uv, cp_t.y);&#xD;&#xA;            color.b *= curve3;&#xD;&#xA;        }            &#xD;&#xA;        else{&#xD;&#xA;            float plotThk = 0.02;&#xD;&#xA;            &#xD;&#xA;             //Attempt 1: change color based on distance from unrotated original curve: &#xD;&#xA;            float dist = distance(uv, cp + vec2(0.0, p.y));&#xD;&#xA;            if(dist &lt; plotThk)&#xD;&#xA;            	color.g *= (1.0 -dist)/plotThk;   &#xD;&#xA;    &#xD;&#xA;            //Attempt 2: change color based on distance from transformed coordinates:&#xD;&#xA;    		dist = distance(uv, cp_t);&#xD;&#xA;            if(dist &lt; plotThk)&#xD;&#xA;            	color.r *= (1.0 -dist)/plotThk;   &#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        gl_FragColor = vec4(color,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the code above, there are two modes which can be toggled with `use_plot_function` set to `false` or `true`.&#xD;&#xA;&#xD;&#xA;First mode attempts to plot using the functions `plot(`) &amp; `plotTransformed()`.&#xD;&#xA;Second mode sets a color to a fragment based on the distance from the calculated curve coordinates.&#xD;&#xA;&#xD;&#xA;Result of first mode with `use_plot_function` set to `true`:&#xD;&#xA;&#xD;&#xA;[![Three different attempts with use_plot_function set to true][4]][4]&#xD;&#xA;&#xD;&#xA;Result of second mode with `use_plot_function` set to `false`:&#xD;&#xA;&#xD;&#xA;[![use_plot_function set to false][5]][5]&#xD;&#xA;&#xD;&#xA;Obviously I'm misunderstanding how this should be done in a fragment shader. &#xD;&#xA;&#xD;&#xA;How should I correctly define a transformed curve in GLSL fragment shader?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v5vx0.gif&#xD;&#xA;  [2]: http://editor.thebookofshaders.com&#xD;&#xA;  [3]: http://thebookofshaders.com/edit.php?log=180516060952&#xD;&#xA;  [4]: https://i.stack.imgur.com/Ku8cE.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/W6EAU.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="19842" PostHistoryTypeId="1" PostId="7636" RevisionGUID="1bd703b0-4708-40d1-a778-84adc62c6a19" CreationDate="2018-05-16T06:41:51.810" UserId="3434" Text="Curve rotation in GLSL fragment shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="19843" PostHistoryTypeId="3" PostId="7636" RevisionGUID="1bd703b0-4708-40d1-a778-84adc62c6a19" CreationDate="2018-05-16T06:41:51.810" UserId="3434" Text="|transformations|glsl|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19844" PostHistoryTypeId="2" PostId="7637" RevisionGUID="905f2c45-9765-4730-8dc6-01c32fd79f6b" CreationDate="2018-05-16T06:54:53.010" UserId="77" Text="I have a bunch of meshes in the .X format, which isn't supported by many 3D applications today. Therefore, I would like to convert these to a modern format like fbx or gltf/glb. &#xD;&#xA;&#xD;&#xA;Since these meshes are proprietary, an offline solution would be preferred. What would be an ideal way to achieve this lossless-ly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19845" PostHistoryTypeId="1" PostId="7637" RevisionGUID="905f2c45-9765-4730-8dc6-01c32fd79f6b" CreationDate="2018-05-16T06:54:53.010" UserId="77" Text="Convert a .X mesh to a modern format" ContentLicense="CC BY-SA 4.0" />
  <row Id="19846" PostHistoryTypeId="3" PostId="7637" RevisionGUID="905f2c45-9765-4730-8dc6-01c32fd79f6b" CreationDate="2018-05-16T06:54:53.010" UserId="77" Text="|mesh|gltf|conversion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19847" PostHistoryTypeId="2" PostId="7638" RevisionGUID="81153d9c-082a-4e84-9d53-9682fdc0247e" CreationDate="2018-05-16T14:14:27.710" UserId="1908" Text="Blender appears to have a .X importer.  It's a plugin that ships with Blender, but is disabled by default, so you have to enable it in User Preferences.  See: https://blender.stackexchange.com/a/8749/18161&#xD;&#xA;&#xD;&#xA;Blender also has a glTF exporter.  For now that's a separate download, from here: [glTF-Blender-Exporter](https://github.com/KhronosGroup/glTF-Blender-Exporter)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19848" PostHistoryTypeId="2" PostId="7639" RevisionGUID="7d77efac-1075-4b5b-bd0f-0761c89d548d" CreationDate="2018-05-16T15:56:13.220" UserId="5358" Text="You are doing completely different things in Matlab than in your Fragment Shaders.&#xD;&#xA;&#xD;&#xA;In Matlab you are generating bunch of points that can be drawn **anywhere** on the screen and then you are transforming them. This would be loose equivalent of your Matlab code in Fragment Shader:&#xD;&#xA;&#xD;&#xA;    #define ARRAY_SIZE 256&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        vec2 st = gl_FragCoord.xy / u_resolution.xy;&#xD;&#xA;        st = st * 2.0 - 1.0;&#xD;&#xA;        st.x *= u_resolution.x / u_resolution.y;&#xD;&#xA;        &#xD;&#xA;        //the angle to rotate:&#xD;&#xA;        float ang = u_time * 0.5;&#xD;&#xA;    	&#xD;&#xA;        //Transform coordinates:&#xD;&#xA;        float c = cos(ang); &#xD;&#xA;        float s = sin(ang);    &#xD;&#xA;        mat2 trans = mat2(c, s, -s, c);&#xD;&#xA;      &#xD;&#xA;        // our domain is from -1 to 1 so total length is 2.0&#xD;&#xA;        float xStep = 2.0 / float(ARRAY_SIZE);&#xD;&#xA;        &#xD;&#xA;        // How far we are from current pixel location to the curve&#xD;&#xA;        float minDist = 1e3;&#xD;&#xA;        &#xD;&#xA;        // initialize points&#xD;&#xA;        for (int i = 0; i &lt; ARRAY_SIZE; ++i) {&#xD;&#xA;            float x = -1.0 + float(i) * xStep;&#xD;&#xA;            &#xD;&#xA;            // initialize points&#xD;&#xA;            vec2 cp = vec2(x, 0.08 * sin(x * 40.0));&#xD;&#xA;&#xD;&#xA;            // transform&#xD;&#xA;            cp = trans * cp;&#xD;&#xA;            minDist = min(minDist, distance(st, cp));&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        // Add some contrast:&#xD;&#xA;        float d = pow(minDist, 0.1);&#xD;&#xA;        &#xD;&#xA;        vec3 col = vec3(fract(d));&#xD;&#xA;        gl_FragColor = vec4(col, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;(Here is the live version: http://thebookofshaders.com/edit.php?log=180516153813 ). &#xD;&#xA;&#xD;&#xA;[![Matlab equivalent][1]][1]&#xD;&#xA;For drawing I'm using distance to points because of simplicity, but better way would be to use distance to line segments that the points should be connected by.&#xD;&#xA;&#xD;&#xA;In the other hands, in your fragment shaders you are first calculating something relative to a **fixed** pixel location (gl_FragCoord.xy), then transforming it in a way that it is not valid from the pixel's point of view any more, and then you are hoping that you can calculate proper distance to it.&#xD;&#xA;Unfortunately this won't work.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;(Example of fixed location of a Fragment Shader invocation)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But what you can do is first rotate the domain (and not result of your calculations), and then perform all calculations in it:&#xD;&#xA;&#xD;&#xA;    // Plot a line on Y using a value between 0.0-1.0&#xD;&#xA;    float plot(vec2 st, float pct){&#xD;&#xA;      return  smoothstep( pct-0.02, pct, st.y) -&#xD;&#xA;              smoothstep( pct, pct+0.02, st.y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        vec2 st = gl_FragCoord.xy / u_resolution.xy;&#xD;&#xA;        st = st * 2.0 - 1.0;&#xD;&#xA;        st.x *= u_resolution.x / u_resolution.y;&#xD;&#xA;        &#xD;&#xA;        //the angle to rotate:&#xD;&#xA;        float ang = u_time * 0.5;&#xD;&#xA;        &#xD;&#xA;        //Transform coordinates:&#xD;&#xA;        float c = cos(ang); &#xD;&#xA;        float s = sin(ang);    &#xD;&#xA;        mat2 trans = mat2(c, s, -s, c);&#xD;&#xA;        &#xD;&#xA;    #if 1&#xD;&#xA;       // You need to transform domain first:&#xD;&#xA;       st *= trans;    &#xD;&#xA;        &#xD;&#xA;       // then perform the calculations:&#xD;&#xA;       vec2 cp = vec2(st.x, 0.08 * sin(st.x * 40.0));&#xD;&#xA;    #else    &#xD;&#xA;        // This won't work (your old way):&#xD;&#xA;        vec2 cp = vec2(st.x, 0.08 * sin(st.x * 40.0));&#xD;&#xA;        cp = trans * cp; &#xD;&#xA;    #endif&#xD;&#xA;        &#xD;&#xA;        vec3 col = vec3(fract(distance(st, cp)));&#xD;&#xA;        col.r += plot(st, cp.y);&#xD;&#xA;&#xD;&#xA;        gl_FragColor = vec4(col, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;(Live version: http://thebookofshaders.com/edit.php?log=180516154712 )&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/92JjM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4GSag.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/qINJG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19849" PostHistoryTypeId="2" PostId="7640" RevisionGUID="c436fd06-425c-407d-966b-4320b63e9b00" CreationDate="2018-05-16T22:01:28.303" UserId="3003" Text="What's probably happening is that you're doing indirect texture fetches. Are you doing something like this:&#xD;&#xA;&#xD;&#xA;    vec4 a = texture3D(sampler, coord);&#xD;&#xA;    vec4 b = texture3D(sampler, coord + vec4(0, 0, 1));&#xD;&#xA;    vec4 c = texture3D(sampler, coord + vec4(0, 1, 0));&#xD;&#xA;    vec4 d = texture4D(sampler, coord + vec4(1, 0, 0));&#xD;&#xA;    //...etc.&#xD;&#xA;&#xD;&#xA;If so, that can slow you down. What you can do instead is to pass the texture coordinates for each sampler call into your vertex shader from your CPU code. You'd set it up as if you were doing multi-texturing, but all the texture units would point to the same texture, just sampled at different coordinates. &#xD;&#xA;&#xD;&#xA;Taking the 2D case, instead of passing in a single texture coordinate like this:&#xD;&#xA;&#xD;&#xA;    float2 texCoords[] = { &#xD;&#xA;        { 0, 0 },&#xD;&#xA;        { width, 0 },&#xD;&#xA;        { width, height },&#xD;&#xA;        { 0, height }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;You'd pass in 4 of them:&#xD;&#xA;&#xD;&#xA;    float2 texCoords[] = {&#xD;&#xA;        // texture 0 coords&#xD;&#xA;        { 0, 0 },&#xD;&#xA;        { width, 0 },&#xD;&#xA;        { width, height },&#xD;&#xA;        { 0, height },&#xD;&#xA;&#xD;&#xA;        // texture 1 coords&#xD;&#xA;        { 1, 0 },&#xD;&#xA;        { width + 1, 0 },&#xD;&#xA;        { width + 1, height },&#xD;&#xA;        { 1, height },&#xD;&#xA;&#xD;&#xA;        // Texture 2 coords&#xD;&#xA;        { 0, 1 },&#xD;&#xA;        { width, 1 },&#xD;&#xA;        { width, height + 1 },&#xD;&#xA;        { 0, height + 1 },&#xD;&#xA;        &#xD;&#xA;        // Texture 3 coords&#xD;&#xA;        { 1, 1 },&#xD;&#xA;        { width + 1, 1 },&#xD;&#xA;        { width + 1, height + 1 },&#xD;&#xA;        { 1, height + 1 }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;In your fragment shader, you'd do something like this:&#xD;&#xA;&#xD;&#xA;    vec4 pixel0 = texture2D(sampler0, coord0);&#xD;&#xA;    vec4 pixel1 = texture2D(sampler1, coord1);&#xD;&#xA;    vec4 pixel2 = texture2D(sampler2, coord2);&#xD;&#xA;    vec4 pixel3 = texture2D(sampler3, coord3);&#xD;&#xA;&#xD;&#xA;Now you have the 4 pixels needed for interpolation, but there was no fragment shader math done to get the texture coords, so there are no indirect look-ups which are slower than direct look-ups." ContentLicense="CC BY-SA 4.0" />
  <row Id="19859" PostHistoryTypeId="2" PostId="7643" RevisionGUID="9764ae65-a7a4-43c7-acaa-1948f60a5fc2" CreationDate="2018-05-17T10:51:43.583" UserId="8748" Text="When we convert from canonical space to screen space,&#xD;&#xA;&#xD;&#xA;To map x from -1 to 1 to 0 to width,&#xD;&#xA;&#xD;&#xA;    -1 &lt; x &lt; 1&#xD;&#xA;    0 &lt; x+1 &lt; 2&#xD;&#xA;    0 &lt; x+1/2 &lt; 1&#xD;&#xA;    0 &lt; (x+1)w/2 &lt; w&#xD;&#xA;    0 &lt; xw/2 + w/2 &lt; w&#xD;&#xA;&#xD;&#xA;Similarly for y,&#xD;&#xA;&#xD;&#xA;    -1 &lt; y &lt; 1&#xD;&#xA;    0 &lt; y+1 &lt; 2&#xD;&#xA;    0 &lt; y+1/2 &lt; 1&#xD;&#xA;    0 &lt; (y+1)h/2 &lt; h&#xD;&#xA;    0 &lt; yh/2 + h/2 &lt; h&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What is the reason behind choosing a screen that has (xmin, ymin) = (0.5, 0.5) and (xmax, ymax) = (1920 - 0.5, 1080 - 0.5) where (nx, ny) = (1920, 1080)?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RAs4q.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ePX1x.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19860" PostHistoryTypeId="1" PostId="7643" RevisionGUID="9764ae65-a7a4-43c7-acaa-1948f60a5fc2" CreationDate="2018-05-17T10:51:43.583" UserId="8748" Text="Canonical Space to Screen Space: Why do we have the strange -0.5?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19861" PostHistoryTypeId="3" PostId="7643" RevisionGUID="9764ae65-a7a4-43c7-acaa-1948f60a5fc2" CreationDate="2018-05-17T10:51:43.583" UserId="8748" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19862" PostHistoryTypeId="2" PostId="7644" RevisionGUID="ead75468-801e-412e-bb9a-7ed447d857cc" CreationDate="2018-05-17T13:30:48.573" UserId="8749" Text="In line 15 use the half-open interval, i.e.,&#xD;&#xA;&#xD;&#xA;    if u&gt;=t[0][i] and u&lt;t[0][i+1]:&#xD;&#xA;Otherwise, at knot values, you evaluate two basis functions at the k=1 basis when you only want one. This causes the wrong evaluation of the basis function at the knot values and therefore the spikes.  &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19863" PostHistoryTypeId="2" PostId="7645" RevisionGUID="00894b0c-5652-42e8-9df2-f4358b66496e" CreationDate="2018-05-17T15:34:07.217" UserId="6046" Text="I can't really answer this without the context so post some links where this is done.&#xD;&#xA;&#xD;&#xA;What I can tell you is that the general formula for viewport transformation as done by OpenGL is given as (taken from [wiki][1])&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here `x,y` are the what your picture says `xmin, ymin` and `width, height` is `xmax, ymax`. Now there is no specific reason I can think of why you would wanna do a shift of `-0.5` but the viewport allows us to draw to a specific portion of the screen. &#xD;&#xA;&#xD;&#xA;For example, in video games you would want to draw the minimap on the lower left corner of the screen, hence you could provide the values&#xD;&#xA;&#xD;&#xA;`x = 0, y = 0, width = 200, height = 200` &#xD;&#xA;&#xD;&#xA;This would render a 200x200 minimap in the lower left corner. Your second picture does this but instead it chooses a value of&#xD;&#xA;&#xD;&#xA;`x = -0.5, y = -0.5, width = nx, height = ny`&#xD;&#xA;&#xD;&#xA;If you substitute it in the above matrix you'll get&#xD;&#xA;&#xD;&#xA;$ \frac{nx}{2} * x_{ndc} - \frac{1}{2} + \frac{nx}{2}$&#xD;&#xA;&#xD;&#xA;for the $X$ value. This equals&#xD;&#xA;&#xD;&#xA;$ \frac{nx}{2} * x_{ndc} + \frac{nx - 1}{2}$&#xD;&#xA;&#xD;&#xA;Which is the same as what is done in the picture you posted. Hope it helped somewhat.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Viewport_transform&#xD;&#xA;  [2]: https://i.stack.imgur.com/BWAUb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19864" PostHistoryTypeId="5" PostId="7645" RevisionGUID="e0691300-4059-4899-ba7d-f82ef1611e81" CreationDate="2018-05-17T18:32:58.830" UserId="6046" Comment="added 359 characters in body" Text="I can't really answer this without the context so post some links where this is done.&#xD;&#xA;&#xD;&#xA;What I can tell you is that the general formula for viewport transformation as done by OpenGL is given as (taken from [wiki][1])&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here `x,y` are the what your picture says `xmin, ymin` and `width, height` is `xmax, ymax`. Now there is no specific reason I can think of why you would wanna do a shift of `-0.5` but the viewport allows us to draw to a specific portion of the screen. &#xD;&#xA;&#xD;&#xA;For example, in video games you would want to draw the minimap on the lower left corner of the screen, hence you could provide the values&#xD;&#xA;&#xD;&#xA;`x = 0, y = 0, width = 200, height = 200` &#xD;&#xA;&#xD;&#xA;This would render a 200x200 minimap in the lower left corner. Your second picture does this but instead it chooses a value of&#xD;&#xA;&#xD;&#xA;`x = -0.5, y = -0.5, width = nx, height = ny`&#xD;&#xA;&#xD;&#xA;If you substitute it in the above matrix you'll get&#xD;&#xA;&#xD;&#xA;$ \frac{nx}{2} * x_{ndc} - \frac{1}{2} + \frac{nx}{2}$&#xD;&#xA;&#xD;&#xA;for the $X$ value. This equals&#xD;&#xA;&#xD;&#xA;$ \frac{nx}{2} * x_{ndc} + \frac{nx - 1}{2}$&#xD;&#xA;&#xD;&#xA;Which is the same as what is done in the picture you posted. Hope it helped somewhat.&#xD;&#xA;&#xD;&#xA;EDIT:- `0.5` offset is commonly used to get to the pixel center. See this image as an example.&#xD;&#xA;&#xD;&#xA;Here the pixel `3,5` has the center `3.5, 5.5`. This is the 0.5 offset you are seeing. I was confused when at first when you were talking about an offset of negative 0.5.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Viewport_transform&#xD;&#xA;  [2]: https://i.stack.imgur.com/BWAUb.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kL2i3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19868" PostHistoryTypeId="5" PostId="7645" RevisionGUID="6e5571c0-2c00-4f18-a1d2-ea21032a55b2" CreationDate="2018-05-17T20:00:01.713" UserId="6046" Comment="deleted 5 characters in body" Text="I can't really answer this without the context so post some links where this is done.&#xD;&#xA;&#xD;&#xA;What I can tell you is that the general formula for viewport transformation as done by OpenGL is given as (taken from [wiki][1])&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here `x,y` are the what your picture says `xmin, ymin` and `width, height` is `xmax, ymax`. Now there is no specific reason I can think of why you would wanna do a shift of `-0.5` but the viewport allows us to draw to a specific portion of the screen. &#xD;&#xA;&#xD;&#xA;For example, in video games you would want to draw the minimap on the lower left corner of the screen, hence you could provide the values&#xD;&#xA;&#xD;&#xA;`x = 0, y = 0, width = 200, height = 200` &#xD;&#xA;&#xD;&#xA;This would render a 200x200 minimap in the lower left corner. Your second picture does this but instead it chooses a value of&#xD;&#xA;&#xD;&#xA;`x = -0.5, y = -0.5, width = nx, height = ny`&#xD;&#xA;&#xD;&#xA;If you substitute it in the above matrix you'll get&#xD;&#xA;&#xD;&#xA;$ \frac{nx}{2} * x_{ndc} - \frac{1}{2} + \frac{nx}{2}$&#xD;&#xA;&#xD;&#xA;for the $X$ value. This equals&#xD;&#xA;&#xD;&#xA;$ \frac{nx}{2} * x_{ndc} + \frac{nx - 1}{2}$&#xD;&#xA;&#xD;&#xA;Which is the same as what is done in the picture you posted. Hope it helped somewhat.&#xD;&#xA;&#xD;&#xA;EDIT:- `0.5` offset is commonly used to get to the pixel center. See this image as an example.&#xD;&#xA;&#xD;&#xA;Here the pixel `3,5` has the center `3.5, 5.5`. This is the 0.5 offset you are seeing. I was confused at first when you were talking about an offset of negative 0.5.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Viewport_transform&#xD;&#xA;  [2]: https://i.stack.imgur.com/BWAUb.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kL2i3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19872" PostHistoryTypeId="2" PostId="7647" RevisionGUID="da111a69-32ad-4e11-99a2-521a76790e4d" CreationDate="2018-05-18T14:45:57.627" UserId="8297" Text="I am trying to project a Polyhedron on the xy plane with CGAL, which should result in a (2D) polygon.&#xD;&#xA;&#xD;&#xA;I wonder, if there is an elegant way to achieve it?&#xD;&#xA;&#xD;&#xA;Of course, I can iterate over all surfaces and build 2D-Segments from the 3D-Segments by throwing away the z coordinate and then reassemble the polgon cycles.&#xD;&#xA;&#xD;&#xA;But I feel, that somehow using `Projection_traits_xy_3` it should be possible to solve that task more elegant, however, I couldn't find a way. Is this possible?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19873" PostHistoryTypeId="1" PostId="7647" RevisionGUID="da111a69-32ad-4e11-99a2-521a76790e4d" CreationDate="2018-05-18T14:45:57.627" UserId="8297" Text="Projection of a Polyhedron on xy Plane with CGAL" ContentLicense="CC BY-SA 4.0" />
  <row Id="19874" PostHistoryTypeId="3" PostId="7647" RevisionGUID="da111a69-32ad-4e11-99a2-521a76790e4d" CreationDate="2018-05-18T14:45:57.627" UserId="8297" Text="|computational-geometry|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19875" PostHistoryTypeId="50" PostId="6012" RevisionGUID="ae08c864-8cae-4f44-bedb-33f4c8560c2f" CreationDate="2018-05-18T17:31:56.377" UserId="-1" />
  <row Id="19876" PostHistoryTypeId="50" PostId="5996" RevisionGUID="fac1898b-b223-423b-b861-ed549cc42b53" CreationDate="2018-05-18T19:32:07.347" UserId="-1" />
  <row Id="19878" PostHistoryTypeId="50" PostId="7529" RevisionGUID="119c62f3-0736-4e3e-90de-ae457345463c" CreationDate="2018-05-19T18:48:49.820" UserId="-1" />
  <row Id="19879" PostHistoryTypeId="34" PostId="7597" RevisionGUID="344f4c15-f450-4aeb-a081-ea8b5a3289be" CreationDate="2018-05-19T20:17:07.347" UserId="7462" Comment="46" />
  <row Id="19880" PostHistoryTypeId="50" PostId="6291" RevisionGUID="a9309b5b-bb3a-4d19-9716-a4c0b1ff428c" CreationDate="2018-05-20T00:49:04.683" UserId="-1" />
  <row Id="19881" PostHistoryTypeId="2" PostId="7648" RevisionGUID="faa23350-dc32-4c77-a997-56641056697b" CreationDate="2018-05-20T04:21:33.477" UserId="8680" Text="It would seem that, in the second example, the morphNormals are targets while in in the first they are deltas.&#xD;&#xA;&#xD;&#xA;This explains the difference in math used between the two pieces of code." ContentLicense="CC BY-SA 4.0" />
  <row Id="19882" PostHistoryTypeId="2" PostId="7649" RevisionGUID="b5aa7175-14fa-4042-806c-1a741ab7c85d" CreationDate="2018-05-20T14:30:02.490" UserId="8761" Text="I am trying to implement linear bending of a mesh by following what Alan H. Barr explained in his *Global and local deformations of solid primitives* paper ([link][1], pag.5). The issue I have is that I don't quite understand the formulas involved.&#xD;&#xA;&#xD;&#xA;Given k as the bending rate (and thus 1/k as the radius of curvature), y0 the center of bending and assuming the transformation is applied along the y-axis between ymin and ymax linearly, the author claims that:&#xD;&#xA;&#xD;&#xA;y = y0 **-sin(theta) * (z - 1/k)**&#xD;&#xA;&#xD;&#xA;z = 1/k + **cos(theta) * (z - 1/k)**&#xD;&#xA;&#xD;&#xA;Can somebody explain, possibly with an image, the terms in bold in the formulas above? I guess that I should look for an angle alpha = pi/2 + theta, since cos(alpha) = -sin(theta), sin(alpha) = cos(theta), but I am not able to figure it out. Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=808573" ContentLicense="CC BY-SA 4.0" />
  <row Id="19883" PostHistoryTypeId="1" PostId="7649" RevisionGUID="b5aa7175-14fa-4042-806c-1a741ab7c85d" CreationDate="2018-05-20T14:30:02.490" UserId="8761" Text="Linear bending of a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="19884" PostHistoryTypeId="3" PostId="7649" RevisionGUID="b5aa7175-14fa-4042-806c-1a741ab7c85d" CreationDate="2018-05-20T14:30:02.490" UserId="8761" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19885" PostHistoryTypeId="2" PostId="7650" RevisionGUID="919b45c5-026d-4dab-ad97-0b7fd7362c68" CreationDate="2018-05-20T22:19:42.473" UserId="5180" Text="I'm trying to build a toy path tracer using something similar to Disney's BSDF, where many materials can be represented as combinations of properties like color, metalness, roughness, transmission, ior.&#xD;&#xA;&#xD;&#xA;I'd like to use the [GGX microfacet BSDF][1], but without splitting the ray each time to get &amp; sum the Fr and Ft terms for reflection and transmission. Is it normal/ok to use schlick's approximation to randomly choose between transmission and reflection (Ft vs Fr), and then to just use the BRDF and BTDF formulas separately depending on which path the system chooses?&#xD;&#xA;&#xD;&#xA;For example, roughly:&#xD;&#xA;&#xD;&#xA;    reflect := material.schlick(incident, norm)&#xD;&#xA;    if (reflect) {&#xD;&#xA;        indirect := randDirOnHemisphere(norm)&#xD;&#xA;        return material.brdf(incident, indirect, norm)&#xD;&#xA;    }&#xD;&#xA;    transmit := getThisSomehow(norm)&#xD;&#xA;    return material.bsdf(incident, transmit, norm)&#xD;&#xA;&#xD;&#xA;I also wonder how diffused reflections factor in. For instance, does GGX only provide specular reflection &amp; refraction? In that case, how do you also handle diffusion?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19886" PostHistoryTypeId="1" PostId="7650" RevisionGUID="919b45c5-026d-4dab-ad97-0b7fd7362c68" CreationDate="2018-05-20T22:19:42.473" UserId="5180" Text="Is the microfacet GGX BSDF normally implemented as separate BRDF and BTDFs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19887" PostHistoryTypeId="3" PostId="7650" RevisionGUID="919b45c5-026d-4dab-ad97-0b7fd7362c68" CreationDate="2018-05-20T22:19:42.473" UserId="5180" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19888" PostHistoryTypeId="5" PostId="7650" RevisionGUID="3ec66086-2445-4c6c-8a62-1337caa9c766" CreationDate="2018-05-20T22:48:42.413" UserId="5180" Comment="added 629 characters in body" Text="I'm trying to build a toy path tracer using something similar to Disney's BSDF, where many materials can be represented as combinations of properties like color, metalness, roughness, transmission, ior.&#xD;&#xA;&#xD;&#xA;I'd like to use the [GGX microfacet BSDF][1], but without splitting the ray each time to get &amp; sum the Fr and Ft terms for reflection and transmission. Is it normal/ok to use schlick's approximation to randomly choose between transmission and reflection (Ft vs Fr), and then to just use the BRDF and BTDF formulas separately depending on which path the system chooses?&#xD;&#xA;&#xD;&#xA;For example, roughly:&#xD;&#xA;&#xD;&#xA;    On hit (into)&#xD;&#xA;    - Reflect or Transmit via Schlick(i, o, n)&#xD;&#xA;        - Reflect:&#xD;&#xA;            - Direct (N times):&#xD;&#xA;                - Choose point on disc of random light&#xD;&#xA;                - Calc transmission t via BRDF(i, o, n)&#xD;&#xA;                - Calc pdf by area of cone / area of hemisphere&#xD;&#xA;                - Add light * t / pdf&#xD;&#xA;            - Indirect (1 time):&#xD;&#xA;                - Choose direction o by BRDF.Sample(i, n)&#xD;&#xA;                - Calc transmission t via BRDF(i, o, n)&#xD;&#xA;                - Calc pdf by BRDF.PDF(i, o, n) ??&#xD;&#xA;                - Add trace(o) * t / pdf&#xD;&#xA;        - Transmit:&#xD;&#xA;            - Choose direction o by snell(i, n) + some kind of roughness * offset&#xD;&#xA;            - (how do you apply the BTDF here? Or is it important?)&#xD;&#xA;    On hit (out of)&#xD;&#xA;    	- Choose direction o by snell(i, n) + some kind of roughness * offset&#xD;&#xA;    	- Reduce transmission via beer(distance)&#xD;&#xA;&#xD;&#xA;I also wonder how diffused reflections factor in. For instance, does GGX only provide specular reflection &amp; refraction? In that case, how do you also handle diffusion?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="19889" PostHistoryTypeId="2" PostId="7651" RevisionGUID="cc907a1f-67db-4a9c-a60d-88f518a885a1" CreationDate="2018-05-20T23:39:20.583" UserId="8762" Text="The format of SPIR-V bytecode is probably one of the least documented parts of both OpenGL and Vulkan that I am aware of. I have compiled a very basic fragment shaders into both the OpenGL and Vulkan SPIR-V formats. Looking at the files in a hex editor, I see no obvious differences, but when I hash the files, they give a different result. What are the differences between the OpenGL and Vulkan SPIR-V formats?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19890" PostHistoryTypeId="1" PostId="7651" RevisionGUID="cc907a1f-67db-4a9c-a60d-88f518a885a1" CreationDate="2018-05-20T23:39:20.583" UserId="8762" Text="How different is the SPIR-V accepted by OpenGL (ARB_gl_spirv) from SPIR-V accepted by Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19891" PostHistoryTypeId="3" PostId="7651" RevisionGUID="cc907a1f-67db-4a9c-a60d-88f518a885a1" CreationDate="2018-05-20T23:39:20.583" UserId="8762" Text="|opengl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19892" PostHistoryTypeId="2" PostId="7652" RevisionGUID="133d8156-ca04-48fd-ae4c-453db2806a6c" CreationDate="2018-05-21T05:50:03.010" UserId="2654" Text="Vulkan and OpenGL use different models for their resource bindings. Vulkan uses descriptor sets + binding, while OpenGL uses binding indices. As such, the SPIR-V they consume use different decorations for their resources.&#xD;&#xA;&#xD;&#xA;There are also a number of differences in terms of built-ins that the two APIs provide. For example, Vulkan accepts the `InstanceIndex` built-in, while OpenGL does not. OpenGL uses `InstanceId`, which has a different meaning from `InstanceIndex`.&#xD;&#xA;&#xD;&#xA;The ARB_gl_spirv extension has a pretty exhaustive list of the differences between it and KHR_vulkan_glsl. Many of those are differences that the output SPIR-V will have to expose." ContentLicense="CC BY-SA 4.0" />
  <row Id="19900" PostHistoryTypeId="2" PostId="7654" RevisionGUID="27bef92a-01b4-4bdb-be8f-9fe81d486a31" CreationDate="2018-05-21T10:14:55.670" UserId="8749" Text="A possible way to do this is tracing the [silhouette edges][1] of the polyhedron and projecting them to a 2d polygon only at the end of the process.&#xD;&#xA;&#xD;&#xA;A silhouette edge (in your context) is defined by its neighboring facets having one upwards and one downwards normal (i.e., one positive normal z-coordinate and one negative). This can be checked using Polyhedron_traits_with_normals_3 or you can compute the normals yourself on-the-fly.&#xD;&#xA;&#xD;&#xA;If you only need the outside polygon, you can start with an extreme vertex (e.g., the one with minimal x-coordinate), circulate over its incident halfedges (using Halfedge_around_vertex_circulator), take the one that is a silhouette edge and continue tracing with its next vertex until you close the cycle.&#xD;&#xA;&#xD;&#xA;If you also need inside (hole) polygons, a possible solution can be to gather the silhouette edges from all the polyhedron, and trace the cycles from this set.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Silhouette_edge" ContentLicense="CC BY-SA 4.0" />
  <row Id="19901" PostHistoryTypeId="2" PostId="7655" RevisionGUID="687b58e2-abb1-45a5-b96c-41a9de724840" CreationDate="2018-05-21T13:59:30.817" UserId="8749" Text="You can use CGAL's [half_space_intersection_3][1] or [half_space_intersection_with_construction_3][2] functions, where the half-spaces are defined by the faces of the cuboids.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://doc.cgal.org/latest/Convex_hull_3/group__PkgConvexHull3Functions.html#gade99e8e830ff439ae242b7ab04de06c8&#xD;&#xA;  [2]: https://doc.cgal.org/latest/Convex_hull_3/group__PkgConvexHull3Functions.html#ga7517c4cbbef41338397eda273af75eb1" ContentLicense="CC BY-SA 4.0" />
  <row Id="19902" PostHistoryTypeId="50" PostId="6422" RevisionGUID="7d91bb97-c9a6-40e8-9a75-6489299aa0dd" CreationDate="2018-05-21T14:03:24.967" UserId="-1" />
  <row Id="19903" PostHistoryTypeId="2" PostId="7656" RevisionGUID="179aafa8-d812-4b77-b8c1-9f4926fc2ba7" CreationDate="2018-05-22T06:06:34.220" UserId="5180" Text="I have a renderer where the BxDF interface is Sample(), Probability(), and Radiance(). The Lambertian BRDF is working well, and I believe I have properly implemented Radiance for GGX based on [another user's question][1], but I'm struggling to find a resource I can understand that explains how to generate samples, and then calculate the corresponding PDFs, for a GGX distribution.&#xD;&#xA;&#xD;&#xA;I've found some of the original papers, but unlike Lambert the Sampling and PDF seem based on spherical coordinates (which I don't really understand - 3D Vectors are about the limit of my math).&#xD;&#xA;&#xD;&#xA;For example, here's what I have for Lambert:&#xD;&#xA;&#xD;&#xA;    type Lambert struct {&#xD;&#xA;    	R, G, B float64&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	return normal.RandHemiCos(rnd)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Probability(in, normal geom.Direction) float64 {&#xD;&#xA;    	return 1 / (in.Cos(normal) * math.Pi)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Radiance(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	return rgb.Energy{l.R, l.G, l.B}.Amplified(math.Pi * in.Cos(normal))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my in-progress work for Microfacets:&#xD;&#xA;&#xD;&#xA;    type Microfacet struct {&#xD;&#xA;    	F0        rgb.Energy&#xD;&#xA;    	Roughness float64&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (m Microfacet) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	// ?&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (m Microfacet) Probability(in, normal geom.Direction) float64 {&#xD;&#xA;    	// ?&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;    func (m Microfacet) Radiance(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	F := schlick2(in, normal, m.F0.Average()) // The Fresnel function&#xD;&#xA;    	D := ggx(in, out, normal, m.Roughness)    // The NDF (Normal Distribution Function)&#xD;&#xA;    	G := smithGGX(out, normal, m.Roughness)   // The Geometric Shadowing function&#xD;&#xA;    	r := (F * D * G) / (4 * normal.Cos(in) * normal.Cos(out))&#xD;&#xA;    	return m.F0.Amplified(r)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX BSDF relies on several physics functions I've also implemented:&#xD;&#xA;&#xD;&#xA;    // Schlick's approximation of Fresnel&#xD;&#xA;    func schlick2(in, normal geom.Direction, f0 float64) float64 {&#xD;&#xA;    	return f0 + (1-f0)*math.Pow(1-normal.Cos(in), 5)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // GGX Normal Distribution Function&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func ggx(in, out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	m := in.Half(out)&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nm2 := math.Pow(normal.Cos(m), 2)&#xD;&#xA;    	return (a * a) / (math.Pi * math.Pow(nm2*(a*a-1)+1, 2))&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Smith geometric shadowing for a GGX distribution&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func smithGGX(out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nv := normal.Cos(out)&#xD;&#xA;    	return (2 * nv) / (nv + math.Sqrt(a*a+(1-a*a)*nv*nv))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19904" PostHistoryTypeId="1" PostId="7656" RevisionGUID="179aafa8-d812-4b77-b8c1-9f4926fc2ba7" CreationDate="2018-05-22T06:06:34.220" UserId="5180" Text="Importance sampling microfacet GGX" ContentLicense="CC BY-SA 4.0" />
  <row Id="19905" PostHistoryTypeId="3" PostId="7656" RevisionGUID="179aafa8-d812-4b77-b8c1-9f4926fc2ba7" CreationDate="2018-05-22T06:06:34.220" UserId="5180" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19906" PostHistoryTypeId="5" PostId="7656" RevisionGUID="355fb172-658c-4212-9fb8-b8b7f77daed0" CreationDate="2018-05-22T06:20:04.677" UserId="5180" Comment="Update code examples" Text="I have a renderer where the BxDF interface is Sample(), PDF(), and Eval(). The Lambertian BRDF is working well, and I believe I have properly implemented Eval for GGX based on [another user's question][1], but I'm struggling to find a resource I can understand that explains how to generate samples, and then calculate the corresponding PDFs, for a GGX distribution.&#xD;&#xA;&#xD;&#xA;I've found some of the original papers, but unlike Lambert the Sampling and PDF seem based on spherical coordinates (which I don't really understand - 3D Vectors are about the limit of my math).&#xD;&#xA;&#xD;&#xA;For example, here's what I have for Lambert:&#xD;&#xA;&#xD;&#xA;    type Lambert struct {&#xD;&#xA;    	R, G, B float64&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	return normal.RandHemiCos(rnd)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) PDF(in, normal geom.Direction) float64 {&#xD;&#xA;    	return in.Cos(normal) * math.Pi&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Eval(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	return rgb.Energy{l.R, l.G, l.B}.Amplified(math.Pi * in.Cos(normal))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my in-progress work for Microfacets:&#xD;&#xA;&#xD;&#xA;    func (m Microfacet) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	// ?&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (m Microfacet) PDF(in, normal geom.Direction) float64 {&#xD;&#xA;    	// ?&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;    // https://schuttejoe.github.io/post/ggximportancesamplingpart2/&#xD;&#xA;    func (m Microfacet) Eval(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	F := schlick2(in, normal, m.F0.Average()) // The Fresnel function&#xD;&#xA;    	D := ggx(in, out, normal, m.Roughness)    // The NDF (Normal Distribution Function)&#xD;&#xA;    	G := smithGGX(out, normal, m.Roughness)   // The Geometric Shadowing function&#xD;&#xA;    	r := (F * D * G) / (4 * normal.Cos(in) * normal.Cos(out))&#xD;&#xA;    	return m.F0.Amplified(r)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX BSDF relies on several physics functions I've also implemented:&#xD;&#xA;&#xD;&#xA;    // Schlick's approximation of Fresnel&#xD;&#xA;    func schlick2(in, normal geom.Direction, f0 float64) float64 {&#xD;&#xA;    	return f0 + (1-f0)*math.Pow(1-normal.Cos(in), 5)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // GGX Normal Distribution Function&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func ggx(in, out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	m := in.Half(out)&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nm2 := math.Pow(normal.Cos(m), 2)&#xD;&#xA;    	return (a * a) / (math.Pi * math.Pow(nm2*(a*a-1)+1, 2))&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Smith geometric shadowing for a GGX distribution&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func smithGGX(out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nv := normal.Cos(out)&#xD;&#xA;    	return (2 * nv) / (nv + math.Sqrt(a*a+(1-a*a)*nv*nv))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19907" PostHistoryTypeId="5" PostId="7656" RevisionGUID="657aa436-2329-4920-a518-7aa3c3597598" CreationDate="2018-05-22T07:20:17.067" UserId="5180" Comment="update code examples" Text="I have a renderer where the BxDF interface is Sample(), PDF(), and Eval(). The Lambertian BRDF is working well, and I believe I have properly implemented Eval for GGX based on [another user's question][1], but I'm struggling to find a resource I can understand that explains how to generate samples, and then calculate the corresponding PDFs, for a GGX distribution.&#xD;&#xA;&#xD;&#xA;I've found some of the original papers, but unlike Lambert the Sampling and PDF seem based on spherical coordinates (which I don't really understand - 3D Vectors are about the limit of my math).&#xD;&#xA;&#xD;&#xA;For example, here's what I have for Lambert:&#xD;&#xA;&#xD;&#xA;    type Lambert struct {&#xD;&#xA;    	R, G, B float64&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	return normal.RandHemiCos(rnd)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) PDF(in, normal geom.Direction) float64 {&#xD;&#xA;    	return in.Cos(normal) * math.Pi&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Eval(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	return rgb.Energy{l.R, l.G, l.B}.Amplified(math.Pi * in.Cos(normal))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my in-progress work for Microfacets:&#xD;&#xA;&#xD;&#xA;    func (m Microfacet) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	// TODO: better sampling&#xD;&#xA;    	return normal.RandHemi(rnd)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (m Microfacet) PDF(in, normal geom.Direction) float64 {&#xD;&#xA;    	// TODO: PDF that matches a better sampling distribution&#xD;&#xA;    	return 1 / (2 * math.Pi)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;    // https://schuttejoe.github.io/post/ggximportancesamplingpart2/&#xD;&#xA;    func (m Microfacet) Eval(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	F := schlick2(in, normal, m.F0.Average()) // The Fresnel function&#xD;&#xA;    	D := ggx(in, out, normal, m.Roughness)    // The NDF (Normal Distribution Function)&#xD;&#xA;    	G := smithGGX(out, normal, m.Roughness)   // The Geometric Shadowing function&#xD;&#xA;    	r := (F * D * G) / (4 * normal.Cos(in) * normal.Cos(out))&#xD;&#xA;    	return m.F0.Amplified(r)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX BSDF relies on several physics functions I've also implemented:&#xD;&#xA;&#xD;&#xA;    // Schlick's approximation of Fresnel&#xD;&#xA;    func schlick2(in, normal geom.Direction, f0 float64) float64 {&#xD;&#xA;    	return f0 + (1-f0)*math.Pow(1-normal.Cos(in), 5)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // GGX Normal Distribution Function&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func ggx(in, out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	m := in.Half(out)&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nm2 := math.Pow(normal.Cos(m), 2)&#xD;&#xA;    	return (a * a) / (math.Pi * math.Pow(nm2*(a*a-1)+1, 2))&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Smith geometric shadowing for a GGX distribution&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func smithGGX(out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nv := normal.Cos(out)&#xD;&#xA;    	return (2 * nv) / (nv + math.Sqrt(a*a+(1-a*a)*nv*nv))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19908" PostHistoryTypeId="5" PostId="7656" RevisionGUID="b82e2597-e030-4205-ad25-09e4719e57bd" CreationDate="2018-05-22T08:17:19.897" UserId="5180" Comment="link to paper" Text="I have a renderer where the BxDF interface is Sample(), PDF(), and Eval(). The Lambertian BRDF is working well, and I believe I have properly implemented Eval for GGX based on [another user's question][1], but I'm struggling to find a resource I can understand that explains how to generate samples, and then calculate the corresponding PDFs, for a GGX distribution.&#xD;&#xA;&#xD;&#xA;I've found some of the original papers, but unlike Lambert the Sampling and PDF seem based on spherical coordinates (which I don't really understand - 3D Vectors are about the limit of my math).&#xD;&#xA;&#xD;&#xA;I would really love to know how to translate [&quot;A Simpler and Exact Sampling Routine for the GGX Distribution of Visible Normals&quot;][2] into separate Sample() and PDF() functions.&#xD;&#xA;&#xD;&#xA;Here's what I have for Lambert:&#xD;&#xA;&#xD;&#xA;    type Lambert struct {&#xD;&#xA;    	R, G, B float64&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	return normal.RandHemiCos(rnd)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) PDF(in, normal geom.Direction) float64 {&#xD;&#xA;    	return in.Dot(normal) * math.Pi&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (l Lambert) Eval(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	return rgb.Energy{l.R, l.G, l.B}.Scaled(math.Pi * in.Dot(normal))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's my in-progress work for Microfacets:&#xD;&#xA;&#xD;&#xA;    func (m Microfacet) Sample(out, normal geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	// TODO: better sampling&#xD;&#xA;    	return normal.RandHemi(rnd)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func (m Microfacet) PDF(in, normal geom.Direction) float64 {&#xD;&#xA;    	// TODO: PDF that matches a better sampling distribution&#xD;&#xA;    	return 1 / (2 * math.Pi)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;    // https://schuttejoe.github.io/post/ggximportancesamplingpart2/&#xD;&#xA;    func (m Microfacet) Eval(in, out, normal geom.Direction) rgb.Energy {&#xD;&#xA;    	F := schlick2(in, normal, m.F0.Mean())  // The Fresnel function&#xD;&#xA;    	D := ggx(in, out, normal, m.Roughness)  // The NDF (Normal Distribution Function)&#xD;&#xA;    	G := smithGGX(out, normal, m.Roughness) // The Geometric Shadowing function&#xD;&#xA;    	r := (F * D * G) / (4 * normal.Dot(in) * normal.Dot(out))&#xD;&#xA;    	return m.F0.Scaled(r)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The GGX BSDF relies on several physics functions I've also implemented:&#xD;&#xA;&#xD;&#xA;    // Schlick's approximation of Fresnel&#xD;&#xA;    func schlick2(in, normal geom.Direction, f0 float64) float64 {&#xD;&#xA;    	return f0 + (1-f0)*math.Pow(1-normal.Dot(in), 5)&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // GGX Normal Distribution Function&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func ggx(in, out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	m := in.Half(out)&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nm2 := math.Pow(normal.Dot(m), 2)&#xD;&#xA;    	return (a * a) / (math.Pi * math.Pow(nm2*(a*a-1)+1, 2))&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Smith geometric shadowing for a GGX distribution&#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func smithGGX(out, normal geom.Direction, roughness float64) float64 {&#xD;&#xA;    	a := roughness * roughness&#xD;&#xA;    	nv := normal.Dot(out)&#xD;&#xA;    	return (2 * nv) / (nv + math.Sqrt(a*a+(1-a*a)*nv*nv))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/130/trying-to-implement-microfacet-brdf-but-my-result-images-are-wrong&#xD;&#xA;  [2]: https://hal.archives-ouvertes.fr/hal-01509746/document" ContentLicense="CC BY-SA 4.0" />
  <row Id="19912" PostHistoryTypeId="2" PostId="7658" RevisionGUID="bdd063de-ba29-4273-a900-9fe621ba3363" CreationDate="2018-05-22T19:24:55.317" UserId="8541" Text="I'm struggling with light leaking through meshes (especially thin ones) due to interpolation between probes located on the opposite sides of those. &#xD;&#xA;&#xD;&#xA;First approach I took was mapping all static geometry to 1 lightmap, then generating light probes for each texel center that can be mapped to some triangle. Compute probe world position using barycentric coords of a texel on a corresponding static geometry triangle and then, in fragment shader, bilinearly interpolate between probes using fragment's UV coordinate. Unfortunately, I had to throw all of this away, because automatic UV mapping (all of the tools available in Blender, for example) are absolutely not suitable for this task and the manual UV crafting is just too tedious to be viable. &#xD;&#xA;&#xD;&#xA;Then I saw a Guerrilla Games presentation regarding GI tech in the Killzone which leverages shadow maps (kind of) to store occlusion data for each probe. I thought maybe I could pull off something similar. What I did was ray trace occlusions for each probe and store occlusion distances for respective ray directions in a huge texture atlas, then, in a fragment shader, determine which probes are occluded for the current pixel by comparing distance from probe to pixel with occlusion distance for the nearest ray and set interpolation weights for occluded probes to 0. But, there are 2 serious problems to this approach, which I found only after implementing the algorithm.&#xD;&#xA;&#xD;&#xA;1) Let's consider the case, when distance from the current pixel to the probe is compared to ray 3 (see attached illustration). For pixels located in the range denoted 'l' distance to probe will be greater than occlusion distance for ray 3 and the probe will be considered occluded, but it's not!&#xD;&#xA;&#xD;&#xA;[![First problem][1]][1]&#xD;&#xA;&#xD;&#xA;2) Let's imagine the first problem is solved. Now the problem of a thin mesh arises. For such mesh pixels on the opposite sides of it will have pretty much the same world location and distance tests will result in full interpolation of probes from both sides for both pixels. I guess a solution for this will require pixel's normal, but maybe it will come after the first issue is resolved.&#xD;&#xA;&#xD;&#xA;[![Second problem][2]][2]&#xD;&#xA;&#xD;&#xA;I would greatly appreciate any help in solving there problems. Or maybe someone could point towards more viable algorithm instead?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uLUWk.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/nsiIK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="19913" PostHistoryTypeId="1" PostId="7658" RevisionGUID="bdd063de-ba29-4273-a900-9fe621ba3363" CreationDate="2018-05-22T19:24:55.317" UserId="8541" Text="How to deal with light leaks?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19914" PostHistoryTypeId="3" PostId="7658" RevisionGUID="bdd063de-ba29-4273-a900-9fe621ba3363" CreationDate="2018-05-22T19:24:55.317" UserId="8541" Text="|lighting|interpolation|occlusion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19915" PostHistoryTypeId="2" PostId="7659" RevisionGUID="24a95be9-4c92-4589-8a85-92282dba941f" CreationDate="2018-05-22T19:27:50.823" UserId="8770" Text="When the display hardware is physically rotated 90 degrees, your graphics can still be rendered with the correct side up. Where is this rotation accomplished?&#xD;&#xA;I can imagine a few possibilities:&#xD;&#xA;&#xD;&#xA;A) The code for every low-level graphics primitive contains something to converts its arguments, like&#xD;&#xA;&#xD;&#xA;    if (portrait) {&#xD;&#xA;       swap(x,y);&#xD;&#xA;    }&#xD;&#xA;(or perhaps multiplying every coordinate with a matrix)&#xD;&#xA;&#xD;&#xA;B) The part of the graphics card that continuously scans its memory to create a video signal reads the data in a different order.&#xD;&#xA;&#xD;&#xA;C) The monitor paints the received data column by column instead of row by row&#xD;&#xA;&#xD;&#xA;A and B sounds like they would be inefficient and C means that it would only work on monitors that has special hardware-support for rotation.&#xD;&#xA;Which one is it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19916" PostHistoryTypeId="1" PostId="7659" RevisionGUID="24a95be9-4c92-4589-8a85-92282dba941f" CreationDate="2018-05-22T19:27:50.823" UserId="8770" Text="What part of the graphics chain rotates computer displays when in portrait mode?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19917" PostHistoryTypeId="3" PostId="7659" RevisionGUID="24a95be9-4c92-4589-8a85-92282dba941f" CreationDate="2018-05-22T19:27:50.823" UserId="8770" Text="|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19918" PostHistoryTypeId="2" PostId="7660" RevisionGUID="b483dece-7e82-4fee-b9d2-87bd4ba9342d" CreationDate="2018-05-22T19:43:40.250" UserId="6929" Text="All objects have two AABB (Axis Aligned Bounding Box), one in local space and one another in world space. The box in local space is calculated while importing scene from external source, and the box in world space is transformed version of local one&#xD;&#xA;&#xD;&#xA;The AABB of scene is combined of all child AABB boxes. I'm using the center of scene's AABB as center of scene. This is where my problems begins.&#xD;&#xA;&#xD;&#xA;I'm using the center point to rotate scene using a trackball. After scene is rotated around center of AABB, then new node transforms are applied to each AABB and new AABB for scene is re-computed by combining/joining all AABB boxes. &#xD;&#xA;&#xD;&#xA;**Problem:**&#xD;&#xA;After rotation applied and new AABB is computed, then the new AABB's center is not same as previous one. So after rotation, center and scene is moving a little. &#xD;&#xA;&#xD;&#xA;There is no problem in these cases:&#xD;&#xA;&#xD;&#xA;- If there is only one object in scene then new center is not changing so scene doesn't move after rotation. Everything looks good here. Object/Model/Primitive may have local transform, this doesn't affect the result&#xD;&#xA;- for instance if there are two cube without rotations then center is not moving too, except if one of cube has rotation or there are three cube then center is moving.&#xD;&#xA;&#xD;&#xA;If my rotating-around-object codes are wrong then it wouldn't work for single object too, right? &#xD;&#xA;&#xD;&#xA;Here how I compute center of box, &#xD;&#xA;&#xD;&#xA;    center = (box.min + box.max) * 0.5&#xD;&#xA;&#xD;&#xA;this is not actual code, because I'm using C.&#xD;&#xA;&#xD;&#xA;Is it normal to have moving center after rotation? How do you get center of scene? Using center of AABB like I did?? Any suggestions?&#xD;&#xA;&#xD;&#xA;Maybe it must work and maybe I have a weird bug is some place I don't know, I tried to find it but I had to ask because maybe it is wrong to get center of scene via AABB boxes :(" ContentLicense="CC BY-SA 4.0" />
  <row Id="19919" PostHistoryTypeId="1" PostId="7660" RevisionGUID="b483dece-7e82-4fee-b9d2-87bd4ba9342d" CreationDate="2018-05-22T19:43:40.250" UserId="6929" Text="Rotating scene or complex object using center of AABB" ContentLicense="CC BY-SA 4.0" />
  <row Id="19920" PostHistoryTypeId="3" PostId="7660" RevisionGUID="b483dece-7e82-4fee-b9d2-87bd4ba9342d" CreationDate="2018-05-22T19:43:40.250" UserId="6929" Text="|transformations|scene-graph|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19921" PostHistoryTypeId="2" PostId="7661" RevisionGUID="720f6487-8d7c-47e9-b5e5-1a294ef19704" CreationDate="2018-05-22T20:52:00.797" UserId="48" Text="On typical GPUs today it's option B: monitor rotation is done by the video output hardware (&quot;display engine&quot;) during scan-out. In addition to rotating/flipping, the display engine can also scale the image within certain limits, do simple color/gamma correction, and even composite multiple image layers (&quot;planes&quot;) together, all dynamically during scan-out." ContentLicense="CC BY-SA 4.0" />
  <row Id="19922" PostHistoryTypeId="5" PostId="7649" RevisionGUID="6cb6c810-91bc-4f37-877a-e69d442308c3" CreationDate="2018-05-22T21:47:15.763" UserId="8761" Comment="added link and some more details" Text="I am trying to implement linear bending of a mesh by following what Alan H. Barr explained in his *Global and local deformations of solid primitives* paper ([ACM link][1], [Direct Link hosted on a faculty page][2], pag.5). The issue I have is that I don't quite understand the formulas involved:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![y formula][5]&#xD;&#xA;&#xD;&#xA;![z formula][6]&#xD;&#xA;&#xD;&#xA;Assuming we bend the mesh by an angle ![theta angle][3], where ![y hat][4] is the clamped value of y between some specified ymin and ymax. k is the bending rate expressed in [rad/m] (and thus the radius of curvature is 1/k). The axis of bending is [s, y_0, 1/k]', where s is a free parameter and y0 is the bending center.&#xD;&#xA;&#xD;&#xA;Can somebody explain, possibly with an image, the terms in the formulas above? I guess that I should look for an angle alpha = pi/2 + theta, since cos(alpha) = -sin(theta), sin(alpha) = cos(theta), but I am not able to figure it out. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=808573&#xD;&#xA;  [2]: http://www.cs.drexel.edu/~david/Classes/Papers/p21-barr.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/APqQB.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/gis7s.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/EvNbb.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/qWYeF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19923" PostHistoryTypeId="2" PostId="7662" RevisionGUID="8cf463ba-d5c2-4695-9dd5-95b5047b74ae" CreationDate="2018-05-23T14:09:10.840" UserId="5180" Text="Through help from several people, &amp; referencing and re-referencing the commented urls, I managed to get a sampling scheme with matching PDF that handles everything from perfect mirror surfaces to roughness = 1. Here's the eventual result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    // Cook-Torrance microfacet model&#xD;&#xA;    type Microfacet struct {&#xD;&#xA;    	F0        rgb.Energy&#xD;&#xA;    	Roughness float64&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;    // https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/&#xD;&#xA;    func (m Microfacet) Sample(wo geom.Direction, rnd *rand.Rand) geom.Direction {&#xD;&#xA;    	r0 := rnd.Float64()&#xD;&#xA;    	r1 := rnd.Float64()&#xD;&#xA;    	a := m.Roughness * m.Roughness&#xD;&#xA;    	a2 := a * a&#xD;&#xA;    	theta := math.Acos(math.Sqrt((1 - r0) / ((a2-1)*r0 + 1)))&#xD;&#xA;    	phi := 2 * math.Pi * r1&#xD;&#xA;    	x := math.Sin(theta) * math.Cos(phi)&#xD;&#xA;    	y := math.Cos(theta)&#xD;&#xA;    	z := math.Sin(theta) * math.Sin(phi)&#xD;&#xA;    	wm := geom.Vector3{x, y, z}.Unit()&#xD;&#xA;    	wi := wo.Reflect2(wm)&#xD;&#xA;    	return wi&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;    // https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/&#xD;&#xA;    // https://en.wikipedia.org/wiki/List_of_common_coordinate_transformations#From_Cartesian_coordinates_2&#xD;&#xA;    func (m Microfacet) PDF(wi, wo geom.Direction) float64 {&#xD;&#xA;    	wg := geom.Up&#xD;&#xA;    	wm := wo.Half(wi)&#xD;&#xA;    	a := m.Roughness * m.Roughness&#xD;&#xA;    	a2 := a * a&#xD;&#xA;    	cosTheta := wg.Dot(wm)&#xD;&#xA;    	exp := (a2-1)*cosTheta*cosTheta + 1&#xD;&#xA;    	D := a2 / (math.Pi * exp * exp)&#xD;&#xA;    	return (D * wm.Dot(wg)) / (4 * wo.Dot(wm))&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;    func (m Microfacet) Eval(wi, wo geom.Direction) rgb.Energy {&#xD;&#xA;    	wg := geom.Up&#xD;&#xA;    	wm := wo.Half(wi)&#xD;&#xA;    	if wi.Y &lt;= 0 || wi.Dot(wm) &lt;= 0 {&#xD;&#xA;    		return rgb.Energy{0, 0, 0}&#xD;&#xA;    	}&#xD;&#xA;    	F := fresnelSchlick(wi, wg, m.F0.Mean()) // The Fresnel function&#xD;&#xA;    	D := ggx(wi, wo, wg, m.Roughness)        // The NDF (Normal Distribution Function)&#xD;&#xA;    	G := smithGGX(wo, wg, m.Roughness)       // The Geometric Shadowing function&#xD;&#xA;    	r := (F * D * G) / (4 * wg.Dot(wi) * wg.Dot(wo))&#xD;&#xA;    	return m.F0.Scaled(r)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6mTVc.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="19924" PostHistoryTypeId="2" PostId="7663" RevisionGUID="755a3e82-ffa3-4d55-a0b4-2e6cf32148b2" CreationDate="2018-05-23T14:49:17.707" UserId="8772" Text="This may depend on target hardware and the API you are going to use. Can you provide more info? Here's some (very broad and general) best practices for OpenGL.&#xD;&#xA;https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices&#xD;&#xA;&#xD;&#xA;Also, do you have a performance problem? Or are you just curious. " ContentLicense="CC BY-SA 4.0" />
  <row Id="19932" PostHistoryTypeId="50" PostId="6406" RevisionGUID="30a6e656-2576-457c-83ea-504923e47c3c" CreationDate="2018-05-25T15:22:41.270" UserId="-1" />
  <row Id="19934" PostHistoryTypeId="2" PostId="7665" RevisionGUID="ecc35584-9594-48a6-8f02-e4da63aedb89" CreationDate="2018-05-27T11:45:49.417" UserId="6929" Text="**Solution:**&#xD;&#xA;&#xD;&#xA;Instead of re-calculating center, pre-defined center is used for primitives. The pre-defined center is center of AABB if other value is not supplied. Averaging all center of mesh primitives gives mesh center and averaging all center of meshes gives scene center. After a mesh is transformed, center also gets transformed. &#xD;&#xA;&#xD;&#xA;Now center is not moving after rotations. Using center of scene's AABB seems not good idea. Because each shape of child AABB is changing after transformations. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19935" PostHistoryTypeId="50" PostId="5925" RevisionGUID="b02cc1fe-f476-4f42-8f25-1570c7d7ca59" CreationDate="2018-05-27T14:46:32.173" UserId="-1" />
  <row Id="19936" PostHistoryTypeId="50" PostId="7557" RevisionGUID="02f63518-a728-4c84-959a-48f6cd7cd971" CreationDate="2018-05-28T04:47:54.310" UserId="-1" />
  <row Id="19938" PostHistoryTypeId="2" PostId="7666" RevisionGUID="4ac67953-1440-4abb-9bd5-be939a371176" CreationDate="2018-05-29T01:21:52.573" UserId="1582" Text="I've also spent a good amount of time thinking about a solution for this problem. It seems like one those fundamental mismatches of taking a sparser, lower frequency structure (probe mesh, even if augmented with depth map) and lighting surfaces per pixel which themselves are occluders.&#xD;&#xA;&#xD;&#xA;If you look at the SIGGRAPH'17 Precomputed lighting in CoD:IW (http://advances.realtimerendering.com/s2017/index.html) you'll see they partitioned the precomputed lighting into light maps for large surfaces (which have lots of occlusion) and using a probe mesh for small static objects as well as characters. They take a similar approach of storing an occlusion depth map per tetrahedra face, however because they're not lighting the occluders with the probe mesh, the discontinuities introduced are likely not noticeable.&#xD;&#xA;&#xD;&#xA;Trying to light the occluders with the same map is extremely tricky because the probe mesh faces may not align well with the occluders. I.e. literally &quot;corner&quot; case where 3 planes meet doesn't encode well into a depth map. I have feeling they still get light leaks, but their density is probably fairly high and their evaluation points are distant enough from the pathologically bad cases.&#xD;&#xA;&#xD;&#xA;Sometimes it might be worth asking level artists to not make single sided meshes or thin walls XD, at least for the time being.&#xD;&#xA;&#xD;&#xA;Best of luck, if you find a robust solution to this, you should submit a paper to a conference and be graphics industry famous :D " ContentLicense="CC BY-SA 4.0" />
  <row Id="19939" PostHistoryTypeId="2" PostId="7667" RevisionGUID="982ccf20-7686-439c-9151-1e19dd57e38f" CreationDate="2018-05-29T01:38:14.320" UserId="1582" Text="In current common material models, Diffuse and Specular material properties are handled separately.&#xD;&#xA;&#xD;&#xA;Check out slide 43 on http://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf&#xD;&#xA;&#xD;&#xA;Basically use a diffuse BRDF (lambert, oren nayar) if the material's refraction is scattering is less than 1 pixel. Use refraction and subsurface models if the scattering is larger than a pixel. I.e. in a glass refraction case the light exit is much greater than 1 pixel away from the light entrance.&#xD;&#xA;&#xD;&#xA;You may also be interested in a diffuse parameterization for GGX so that you can use share the same roughness term. https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19940" PostHistoryTypeId="2" PostId="7668" RevisionGUID="3f7a00f4-bd84-4990-ab63-05823598ab42" CreationDate="2018-05-29T06:29:53.157" UserId="8660" Text="Suppose I am making my own C++ 3D engine; I can already load a 3D model using assimp, display it with phong lighting, and I now want to animate it.&#xD;&#xA;&#xD;&#xA;I'd like features in my engine to, say, load a run animation with assimp, and apply it to my human character, preferably on the GPU side. Which techniques do I need to learn to develop this?&#xD;&#xA;&#xD;&#xA;This is a &quot;grocery list&quot; kind of question, where I don't necessarily need a step-by-step explanation, but more of an overview of the techniques involved to know what I need to research. (stuff like &quot;read this OpenGL tutorial&quot; or &quot;learn how X works&quot;)" ContentLicense="CC BY-SA 4.0" />
  <row Id="19941" PostHistoryTypeId="1" PostId="7668" RevisionGUID="3f7a00f4-bd84-4990-ab63-05823598ab42" CreationDate="2018-05-29T06:29:53.157" UserId="8660" Text="Which techniques do I need to animate a 3D model in my homemade engine" ContentLicense="CC BY-SA 4.0" />
  <row Id="19942" PostHistoryTypeId="3" PostId="7668" RevisionGUID="3f7a00f4-bd84-4990-ab63-05823598ab42" CreationDate="2018-05-29T06:29:53.157" UserId="8660" Text="|3d|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19943" PostHistoryTypeId="2" PostId="7669" RevisionGUID="47686f26-de12-45dd-a45c-88ddbd9b673f" CreationDate="2018-05-29T10:03:48.753" UserId="137" Text="First decide how you are going to animate the model.&#xD;&#xA;&#xD;&#xA;The simplest way is to just have a separate mesh per frame of animation. This requires more memory to be dedicated to mesh data more artist time to create them and it locks you into only those poses.&#xD;&#xA;&#xD;&#xA;The next step upwards is interpolating between full meshes (keyword morph targets). This works great for facial expressions especially if you can give different weights for each vertex. It's not that great for full body animation because it's difficult to get proper circular motion into it.&#xD;&#xA;&#xD;&#xA;The most common technique for full body animation is skeletal animation. Instead of full meshes for each frame of animation you instead have a set of model transform per &quot;bone&quot; and each vertex has a set of weights to decide which bones it follows. In the vertex shader you then interpolate the transforms as appropriate and then apply the interpolated transform to the vertex. This has the upside that different meshes can use the same animation data assuming the bones are set up the same." ContentLicense="CC BY-SA 4.0" />
  <row Id="19944" PostHistoryTypeId="2" PostId="7670" RevisionGUID="2240af97-4f5e-44df-8920-af76434cb575" CreationDate="2018-05-29T12:06:26.653" UserId="8758" Text="As per [this][1] resource, there is an easy way to convert from YCbCr to HSV. Saturation is sqrt(Cb^2 + Cr^2). Now here is my issue. If I take pure red (1,0,0), green(0,1,0), and blue(0,0,1) colors, convert them to YCrCb, and then compute saturation, I do not get 1. Infact, all the saturations are different no matter which matrix I use for RGB to YCrCb conversion. Am I missing something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://patents.google.com/patent/WO2006115784A2/en" ContentLicense="CC BY-SA 4.0" />
  <row Id="19945" PostHistoryTypeId="1" PostId="7670" RevisionGUID="2240af97-4f5e-44df-8920-af76434cb575" CreationDate="2018-05-29T12:06:26.653" UserId="8758" Text="YUV to HSV to RGB issues" ContentLicense="CC BY-SA 4.0" />
  <row Id="19946" PostHistoryTypeId="3" PostId="7670" RevisionGUID="2240af97-4f5e-44df-8920-af76434cb575" CreationDate="2018-05-29T12:06:26.653" UserId="8758" Text="|color|color-science|color-management|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19947" PostHistoryTypeId="2" PostId="7671" RevisionGUID="7aec6668-9607-4f6b-a911-a3b31b44be21" CreationDate="2018-05-30T02:06:09.350" UserId="3003" Text="Think about it this way. To calculate YCbCr of (1, 0, 0), you'll end up with Y = 0.299, Cb = -0.16873, Cr = 0.5. If you take the magnitude of the chroma channels (`sqrt(Cb*Cb + Cr*Cr)`), you get ~0.53 for the &quot;saturation&quot;. The YCbCr color space has a different shape than RGB, so it may represent values differently enough that you don't get the exact same answer in both cases. Furthermore, our perception of luminance and saturation is not consistent among colors. &#xD;&#xA;&#xD;&#xA;If all you want is to calculate the saturation of an RGB component, it can be calculated by:&#xD;&#xA;&#xD;&#xA;    float saturation = max(r, g, b) - min(r, g, b);&#xD;&#xA;&#xD;&#xA;Note that if you attempt to calculate perceptually uniform amounts of color saturation you end up with systems like the [Munsell Color System](https://en.wikipedia.org/wiki/Munsell_color_system) where the shape of the color space is highly irregular compared with the cubes and cylinders of other color spaces.&#xD;&#xA;&#xD;&#xA;If you tell us what you're trying to achieve, we might be able to offer an actual solution to whatever the problem is." ContentLicense="CC BY-SA 4.0" />
  <row Id="19948" PostHistoryTypeId="2" PostId="7672" RevisionGUID="f008b512-3901-4a2b-91eb-83c1bb6e7183" CreationDate="2018-05-30T07:06:33.280" UserId="8795" Text="though polygon can be sent in any order but they are still in one plan. And there respective z can be calculated using the formula z=(-Ax-By-D)/C, and if the two polygon surfaces are at same depth then they can have same value of z. &#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="19949" PostHistoryTypeId="2" PostId="7673" RevisionGUID="8f073060-5978-43d8-900a-9ab65707547f" CreationDate="2018-05-30T09:34:37.440" UserId="8796" Text="Perhaps [Assimp][1] will work for you? In particular, it has a [command line tool for converting between formats][2].&#xA;&#xA;&#xA;  [1]: https://github.com/assimp/assimp&#xA;  [2]: https://github.com/assimp/assimp/tree/master/tools/assimp_cmd" ContentLicense="CC BY-SA 4.0" />
  <row Id="19950" PostHistoryTypeId="2" PostId="7674" RevisionGUID="40b902a6-e4ca-4894-9362-65742fd6cbc3" CreationDate="2018-05-30T14:39:00.473" UserId="6530" Text="I'm trying to apply raymarching on top of 3D rasterization, ordering what 3D object gets displayed based on the depth of a rasterization pass and the raymarch depth.   After getting the transform right for *position* I was able to have the position of the raymarched spheres coherent with the rasterized cubes.   I ran into issues however with depth being different at the edges of the screen compared to the middle, despite position never changing.  &#xD;&#xA;&#xD;&#xA;These gifs should show what I'm talking about (StackExchange doesn't let me embed these for what ever reason, they are larger than 2MB but I can't externally link them either...):&#xD;&#xA;&#xD;&#xA;https://ibb.co/ebji0y&#xD;&#xA;&#xD;&#xA;https://ibb.co/dhUGLy&#xD;&#xA;&#xD;&#xA;Something odd is going on with depth, but I don't understand what I'm doing wrong?  Here is my fragment shader for my depth texture render pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    layout(location = 1) out float DepthColor;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;    // texture samplers&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform sampler2D texture1;&#xD;&#xA;    uniform float near;&#xD;&#xA;    uniform float far;&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(float depth)&#xD;&#xA;    {&#xD;&#xA;        float z = depth * 2.0 - 1.0; // back to NDC&#xD;&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        float depth = LinearizeDepth(gl_FragCoord.z);&#xD;&#xA;        DepthColor = depth;&#xD;&#xA;        FragColor = mix(texture(texture0, TexCoord), texture(texture1, TexCoord), 0.3);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here is my shader for the final raymarch pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_screen_texture;&#xD;&#xA;    uniform sampler2D u_depth_texture;&#xD;&#xA;    uniform float u_fov;&#xD;&#xA;    uniform vec3 u_rotation;&#xD;&#xA;    uniform vec3 u_origin;&#xD;&#xA;    uniform vec3 u_resolution;&#xD;&#xA;    &#xD;&#xA;    const float inf = uintBitsToFloat(0x7F800000u);&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecX(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(1, 0, 0,&#xD;&#xA;                           0, cos(theta), -sin(theta),&#xD;&#xA;                           0, sin(theta), cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecY(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(cos(theta), 0, sin(theta),&#xD;&#xA;                           0, 1, 0,&#xD;&#xA;                           -sin(theta), 0, cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 calculateFragementRay(in vec2 fragCoord, in vec3 resolution){&#xD;&#xA;        vec2 uv = fragCoord;&#xD;&#xA;        uv.x = (uv.x * 2.0) - 1.0;&#xD;&#xA;        uv.y = (2.0 * uv.y) - 1.0;&#xD;&#xA;        if(resolution.x &gt;= resolution.y){&#xD;&#xA;            uv.x *= resolution.x/resolution.y;&#xD;&#xA;        }else{&#xD;&#xA;            uv.y *= resolution.y/resolution.x;&#xD;&#xA;        }&#xD;&#xA;        float tan_fov = tan(u_fov/2.0);&#xD;&#xA;        vec2 pxy = uv * tan_fov;&#xD;&#xA;        vec3 ray_dir = normalize(vec3(pxy, 1));&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getRayDirection(in vec2 fragCoord, in vec3 resolution, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;    &#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;        vec3 ray_dir = getRayDirection(fragCoord, resolution, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        return Ray(ray_origin, ray_dir);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct RayMarchSettings{&#xD;&#xA;        int max_steps;&#xD;&#xA;        float max_distance;&#xD;&#xA;        float min_distance;&#xD;&#xA;        float depth_weight;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Sphere{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        float radius;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float signedDistance(vec3 p, in Sphere sphere){&#xD;&#xA;        return (length(p - sphere.origin) - sphere.radius);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const int NULL_ID = -1;&#xD;&#xA;    const int SPHERE_ID = 0;&#xD;&#xA;    const int VSPHERE_ID = 1;&#xD;&#xA;    &#xD;&#xA;    Sphere test_sphere = Sphere(vec3(0.0, 4.0, 4.0),1.0);&#xD;&#xA;    Sphere volume_sphere = Sphere(vec3(0.0, 1.0, 0.0),2.0);&#xD;&#xA;    float signedDistance(vec3 ray_endpoint, out int obj_id){&#xD;&#xA;        float d0 = signedDistance(ray_endpoint, test_sphere);&#xD;&#xA;        float d1 = signedDistance(ray_endpoint, volume_sphere);&#xD;&#xA;        float minval = min(d0, d1);&#xD;&#xA;        obj_id = minval == d0 ? SPHERE_ID : VSPHERE_ID;&#xD;&#xA;        return minval;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool rayMarch(Ray ray, in RayMarchSettings settings, in float rasterized_depth, out float out_depth, out int out_obj_id){&#xD;&#xA;        float depth = 0.0;&#xD;&#xA;        for( int i = 0; i &lt; settings.max_steps; ++i){&#xD;&#xA;            vec3 ray_endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            int obj_id;&#xD;&#xA;            float ray_distance = signedDistance(ray_endpoint, obj_id);&#xD;&#xA;            depth += ray_distance * settings.depth_weight;&#xD;&#xA;    &#xD;&#xA;            if( depth &gt; rasterized_depth){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            if(ray_distance &lt;= settings.min_distance){&#xD;&#xA;                out_depth = depth;&#xD;&#xA;                out_obj_id = obj_id;&#xD;&#xA;                return true;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(depth &gt; settings.max_distance){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        out_depth = inf;&#xD;&#xA;        out_obj_id = NULL_ID;&#xD;&#xA;        return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float checkerBoardTexture(in vec2 uv){&#xD;&#xA;        vec2 q = floor(uv);&#xD;&#xA;        return clamp(mod( q.x+q.y, 2.0 ), 0.25, 1.0);&#xD;&#xA;    }&#xD;&#xA;    float fogify(in float dist){&#xD;&#xA;        return  1.0/ (1.0 + dist*dist * 0.1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RayMarchSettings rm_settings = RayMarchSettings(128, 100000.0, 0.0001, 0.5);&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        vec3 origin = vec3(u_origin.x, u_origin.y, u_origin.z);&#xD;&#xA;        origin = origin.zyx;&#xD;&#xA;        Ray ray = getRay(TexCoords, u_resolution, u_rotation, origin);&#xD;&#xA;        vec3 texture_color = texture(u_screen_texture, TexCoords).rgb;&#xD;&#xA;        float rasterized_depth = texture(u_depth_texture, TexCoords).r;&#xD;&#xA;    &#xD;&#xA;        float depth = inf;&#xD;&#xA;        int obj_id = NULL_ID;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        vec3 color;&#xD;&#xA;        if(rayMarch(ray, rm_settings,rasterized_depth,  depth, obj_id)){&#xD;&#xA;            vec3 endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            float pattern_value = checkerBoardTexture(endpoint.xz * 4.0);&#xD;&#xA;    &#xD;&#xA;            if(obj_id == SPHERE_ID){&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;            if(obj_id == VSPHERE_ID){&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            switch(obj_id){&#xD;&#xA;                case SPHERE_ID:&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                case VSPHERE_ID:&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                default:&#xD;&#xA;                color = vec3(1.0,0.0,1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;         }else{&#xD;&#xA;            float re_rasterized_depth = rasterized_depth == inf ? 0.0 : rasterized_depth;&#xD;&#xA;            color = texture_color +re_rasterized_depth/100.f;&#xD;&#xA;         }&#xD;&#xA;        FragColor = vec4(color, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The `u_depth_texture` is where the depth comes from (and what `DepthColor` corresponds to)  The `u_screen_texture` is just a texture of the rasterization pass information (output of `FragColor`).  " ContentLicense="CC BY-SA 4.0" />
  <row Id="19951" PostHistoryTypeId="1" PostId="7674" RevisionGUID="40b902a6-e4ca-4894-9362-65742fd6cbc3" CreationDate="2018-05-30T14:39:00.473" UserId="6530" Text="How to align Ray Marching on top of traditional 3D rasterization?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19952" PostHistoryTypeId="3" PostId="7674" RevisionGUID="40b902a6-e4ca-4894-9362-65742fd6cbc3" CreationDate="2018-05-30T14:39:00.473" UserId="6530" Text="|opengl|rendering|glsl|rasterizer|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19953" PostHistoryTypeId="2" PostId="7675" RevisionGUID="76e3e34b-d5e1-4046-a1ea-0008a6a50ebb" CreationDate="2018-05-30T18:22:04.123" UserId="1937" Text="The problem, I think, is that you are comparing two different kinds of depth values. For want of better terms, the rasterizer's depth buffer stores 'parallel' depth, whereas raymarching calculates 'true' depth - that is, the rasterizer stores the distance to the plane parallel to the view plane which contains the point, but the raymarcher calculates the *actual* 3D distance from camera to point.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can see from the picture, the relation should be $rasterDepth = rayDepth*cos(A)$&#xD;&#xA;&#xD;&#xA;So try this - in your `getRayDirection` function, *before* you do your view rotation, save your fragment ray's original normalized Z value somewhere, maybe an extra field in your Ray struct. Let's call it `cosA`.&#xD;&#xA;&#xD;&#xA;Then in your `rayMarch` function the relevant code will be&#xD;&#xA;&#xD;&#xA;    if( depth * cosA &gt; rasterized_depth){&#xD;&#xA;            break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Hopefully that should fix the problem.&#xD;&#xA;  [1]: https://i.stack.imgur.com/ad4zF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="19954" PostHistoryTypeId="5" PostId="7674" RevisionGUID="bac9e7c2-8e56-4226-86f7-18b6b9e3b8bb" CreationDate="2018-05-30T19:33:07.230" UserId="6530" Comment="updated changes needed to comply with chosen answer" Text="I'm trying to apply raymarching on top of 3D rasterization, ordering what 3D object gets displayed based on the depth of a rasterization pass and the raymarch depth.   After getting the transform right for *position* I was able to have the position of the raymarched spheres coherent with the rasterized cubes.   I ran into issues however with depth being different at the edges of the screen compared to the middle, despite position never changing.  &#xD;&#xA;&#xD;&#xA;These gifs should show what I'm talking about (StackExchange doesn't let me embed these for what ever reason, they are larger than 2MB but I can't externally link them either...):&#xD;&#xA;&#xD;&#xA;https://ibb.co/ebji0y&#xD;&#xA;&#xD;&#xA;https://ibb.co/dhUGLy&#xD;&#xA;&#xD;&#xA;Something odd is going on with depth, but I don't understand what I'm doing wrong?  Here is my fragment shader for my depth texture render pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    layout(location = 1) out float DepthColor;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;    // texture samplers&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform sampler2D texture1;&#xD;&#xA;    uniform float near;&#xD;&#xA;    uniform float far;&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(float depth)&#xD;&#xA;    {&#xD;&#xA;        float z = depth * 2.0 - 1.0; // back to NDC&#xD;&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        float depth = LinearizeDepth(gl_FragCoord.z);&#xD;&#xA;        DepthColor = depth;&#xD;&#xA;        FragColor = mix(texture(texture0, TexCoord), texture(texture1, TexCoord), 0.3);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here is my shader for the final raymarch pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_screen_texture;&#xD;&#xA;    uniform sampler2D u_depth_texture;&#xD;&#xA;    uniform float u_fov;&#xD;&#xA;    uniform vec3 u_rotation;&#xD;&#xA;    uniform vec3 u_origin;&#xD;&#xA;    uniform vec3 u_resolution;&#xD;&#xA;    &#xD;&#xA;    const float inf = uintBitsToFloat(0x7F800000u);&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecX(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(1, 0, 0,&#xD;&#xA;                           0, cos(theta), -sin(theta),&#xD;&#xA;                           0, sin(theta), cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecY(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(cos(theta), 0, sin(theta),&#xD;&#xA;                           0, 1, 0,&#xD;&#xA;                           -sin(theta), 0, cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 calculateFragementRay(in vec2 fragCoord, in vec3 resolution){&#xD;&#xA;        vec2 uv = fragCoord;&#xD;&#xA;        uv.x = (uv.x * 2.0) - 1.0;&#xD;&#xA;        uv.y = (2.0 * uv.y) - 1.0;&#xD;&#xA;        if(resolution.x &gt;= resolution.y){&#xD;&#xA;            uv.x *= resolution.x/resolution.y;&#xD;&#xA;        }else{&#xD;&#xA;            uv.y *= resolution.y/resolution.x;&#xD;&#xA;        }&#xD;&#xA;        float tan_fov = tan(u_fov/2.0);&#xD;&#xA;        vec2 pxy = uv * tan_fov;&#xD;&#xA;        vec3 ray_dir = normalize(vec3(pxy, 1));&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getRayDirection(in vec2 fragCoord, in vec3 resolution, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;    &#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;        vec3 ray_dir = getRayDirection(fragCoord, resolution, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        return Ray(ray_origin, ray_dir);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct RayMarchSettings{&#xD;&#xA;        int max_steps;&#xD;&#xA;        float max_distance;&#xD;&#xA;        float min_distance;&#xD;&#xA;        float depth_weight;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Sphere{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        float radius;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float signedDistance(vec3 p, in Sphere sphere){&#xD;&#xA;        return (length(p - sphere.origin) - sphere.radius);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const int NULL_ID = -1;&#xD;&#xA;    const int SPHERE_ID = 0;&#xD;&#xA;    const int VSPHERE_ID = 1;&#xD;&#xA;    &#xD;&#xA;    Sphere test_sphere = Sphere(vec3(0.0, 4.0, 4.0),1.0);&#xD;&#xA;    Sphere volume_sphere = Sphere(vec3(0.0, 1.0, 0.0),2.0);&#xD;&#xA;    float signedDistance(vec3 ray_endpoint, out int obj_id){&#xD;&#xA;        float d0 = signedDistance(ray_endpoint, test_sphere);&#xD;&#xA;        float d1 = signedDistance(ray_endpoint, volume_sphere);&#xD;&#xA;        float minval = min(d0, d1);&#xD;&#xA;        obj_id = minval == d0 ? SPHERE_ID : VSPHERE_ID;&#xD;&#xA;        return minval;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool rayMarch(Ray ray, in RayMarchSettings settings, in float rasterized_depth, out float out_depth, out int out_obj_id){&#xD;&#xA;        float depth = 0.0;&#xD;&#xA;        for( int i = 0; i &lt; settings.max_steps; ++i){&#xD;&#xA;            vec3 ray_endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            int obj_id;&#xD;&#xA;            float ray_distance = signedDistance(ray_endpoint, obj_id);&#xD;&#xA;            depth += ray_distance * settings.depth_weight;&#xD;&#xA;    &#xD;&#xA;            if( depth &gt; rasterized_depth){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            if(ray_distance &lt;= settings.min_distance){&#xD;&#xA;                out_depth = depth;&#xD;&#xA;                out_obj_id = obj_id;&#xD;&#xA;                return true;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(depth &gt; settings.max_distance){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        out_depth = inf;&#xD;&#xA;        out_obj_id = NULL_ID;&#xD;&#xA;        return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float checkerBoardTexture(in vec2 uv){&#xD;&#xA;        vec2 q = floor(uv);&#xD;&#xA;        return clamp(mod( q.x+q.y, 2.0 ), 0.25, 1.0);&#xD;&#xA;    }&#xD;&#xA;    float fogify(in float dist){&#xD;&#xA;        return  1.0/ (1.0 + dist*dist * 0.1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RayMarchSettings rm_settings = RayMarchSettings(128, 100000.0, 0.0001, 0.5);&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        vec3 origin = vec3(u_origin.x, u_origin.y, u_origin.z);&#xD;&#xA;        origin = origin.zyx;&#xD;&#xA;        Ray ray = getRay(TexCoords, u_resolution, u_rotation, origin);&#xD;&#xA;        vec3 texture_color = texture(u_screen_texture, TexCoords).rgb;&#xD;&#xA;        float rasterized_depth = texture(u_depth_texture, TexCoords).r;&#xD;&#xA;    &#xD;&#xA;        float depth = inf;&#xD;&#xA;        int obj_id = NULL_ID;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        vec3 color;&#xD;&#xA;        if(rayMarch(ray, rm_settings,rasterized_depth,  depth, obj_id)){&#xD;&#xA;            vec3 endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            float pattern_value = checkerBoardTexture(endpoint.xz * 4.0);&#xD;&#xA;    &#xD;&#xA;            if(obj_id == SPHERE_ID){&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;            if(obj_id == VSPHERE_ID){&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            switch(obj_id){&#xD;&#xA;                case SPHERE_ID:&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                case VSPHERE_ID:&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                default:&#xD;&#xA;                color = vec3(1.0,0.0,1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;         }else{&#xD;&#xA;            float re_rasterized_depth = rasterized_depth == inf ? 0.0 : rasterized_depth;&#xD;&#xA;            color = texture_color +re_rasterized_depth/100.f;&#xD;&#xA;         }&#xD;&#xA;        FragColor = vec4(color, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The `u_depth_texture` is where the depth comes from (and what `DepthColor` corresponds to)  The `u_screen_texture` is just a texture of the rasterization pass information (output of `FragColor`).  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#UPDATE:&#xD;&#xA;&#xD;&#xA;So [this answer][1] outlined exactly my problem.  I had to make the following changes:&#xD;&#xA;&#xD;&#xA;    vec3 getRotatedRayDirection(vec3 ray_dir, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        //vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;        float cosA;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;    &#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        vec3 rot_ray_dir = getRotatedRayDirection(ray_dir, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        float cosA = ray_dir.z/length(ray_dir);&#xD;&#xA;        return Ray(ray_origin, rot_ray_dir, cosA);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Above I basically added cosA as a seperate value onto the ray, as suggested by the linked answer, with the appropriate code changes to avoid re-running `calculateFragmentRay`.  However I needed to figure out which cosine corresponded to the one in thier picture, I knew it was a lateral dimension, it happened to be Z in this case, and I used the standard method of retrieving cosine from a normalized vector.&#xD;&#xA;&#xD;&#xA;After that I did exactly what the linked answer said and made the following change:&#xD;&#xA;&#xD;&#xA;    if( (depth * ray.cosA) &gt; rasterized_depth){&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here are the results! No depth artifacts!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/7675/6530&#xD;&#xA;  [2]: https://i.stack.imgur.com/IptJC.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/kIzIU.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="19955" PostHistoryTypeId="5" PostId="7674" RevisionGUID="af09cac0-fb52-44b6-8248-032aa0a939de" CreationDate="2018-05-30T19:49:00.333" UserId="6530" Comment="compressed original gifs more for better convenience." Text="I'm trying to apply raymarching on top of 3D rasterization, ordering what 3D object gets displayed based on the depth of a rasterization pass and the raymarch depth.   After getting the transform right for *position* I was able to have the position of the raymarched spheres coherent with the rasterized cubes.   I ran into issues however with depth being different at the edges of the screen compared to the middle, despite position never changing.  &#xD;&#xA;&#xD;&#xA;These gifs should show what I'm talking about &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;higher res versions&#xD;&#xA;https://ibb.co/ebji0y&#xD;&#xA;https://ibb.co/dhUGLy&#xD;&#xA;&#xD;&#xA;Something odd is going on with depth, but I don't understand what I'm doing wrong?  Here is my fragment shader for my depth texture render pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    layout(location = 1) out float DepthColor;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;    // texture samplers&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform sampler2D texture1;&#xD;&#xA;    uniform float near;&#xD;&#xA;    uniform float far;&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(float depth)&#xD;&#xA;    {&#xD;&#xA;        float z = depth * 2.0 - 1.0; // back to NDC&#xD;&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        float depth = LinearizeDepth(gl_FragCoord.z);&#xD;&#xA;        DepthColor = depth;&#xD;&#xA;        FragColor = mix(texture(texture0, TexCoord), texture(texture1, TexCoord), 0.3);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here is my shader for the final raymarch pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_screen_texture;&#xD;&#xA;    uniform sampler2D u_depth_texture;&#xD;&#xA;    uniform float u_fov;&#xD;&#xA;    uniform vec3 u_rotation;&#xD;&#xA;    uniform vec3 u_origin;&#xD;&#xA;    uniform vec3 u_resolution;&#xD;&#xA;    &#xD;&#xA;    const float inf = uintBitsToFloat(0x7F800000u);&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecX(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(1, 0, 0,&#xD;&#xA;                           0, cos(theta), -sin(theta),&#xD;&#xA;                           0, sin(theta), cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecY(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(cos(theta), 0, sin(theta),&#xD;&#xA;                           0, 1, 0,&#xD;&#xA;                           -sin(theta), 0, cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 calculateFragementRay(in vec2 fragCoord, in vec3 resolution){&#xD;&#xA;        vec2 uv = fragCoord;&#xD;&#xA;        uv.x = (uv.x * 2.0) - 1.0;&#xD;&#xA;        uv.y = (2.0 * uv.y) - 1.0;&#xD;&#xA;        if(resolution.x &gt;= resolution.y){&#xD;&#xA;            uv.x *= resolution.x/resolution.y;&#xD;&#xA;        }else{&#xD;&#xA;            uv.y *= resolution.y/resolution.x;&#xD;&#xA;        }&#xD;&#xA;        float tan_fov = tan(u_fov/2.0);&#xD;&#xA;        vec2 pxy = uv * tan_fov;&#xD;&#xA;        vec3 ray_dir = normalize(vec3(pxy, 1));&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getRayDirection(in vec2 fragCoord, in vec3 resolution, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;    &#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;        vec3 ray_dir = getRayDirection(fragCoord, resolution, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        return Ray(ray_origin, ray_dir);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct RayMarchSettings{&#xD;&#xA;        int max_steps;&#xD;&#xA;        float max_distance;&#xD;&#xA;        float min_distance;&#xD;&#xA;        float depth_weight;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Sphere{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        float radius;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float signedDistance(vec3 p, in Sphere sphere){&#xD;&#xA;        return (length(p - sphere.origin) - sphere.radius);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const int NULL_ID = -1;&#xD;&#xA;    const int SPHERE_ID = 0;&#xD;&#xA;    const int VSPHERE_ID = 1;&#xD;&#xA;    &#xD;&#xA;    Sphere test_sphere = Sphere(vec3(0.0, 4.0, 4.0),1.0);&#xD;&#xA;    Sphere volume_sphere = Sphere(vec3(0.0, 1.0, 0.0),2.0);&#xD;&#xA;    float signedDistance(vec3 ray_endpoint, out int obj_id){&#xD;&#xA;        float d0 = signedDistance(ray_endpoint, test_sphere);&#xD;&#xA;        float d1 = signedDistance(ray_endpoint, volume_sphere);&#xD;&#xA;        float minval = min(d0, d1);&#xD;&#xA;        obj_id = minval == d0 ? SPHERE_ID : VSPHERE_ID;&#xD;&#xA;        return minval;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool rayMarch(Ray ray, in RayMarchSettings settings, in float rasterized_depth, out float out_depth, out int out_obj_id){&#xD;&#xA;        float depth = 0.0;&#xD;&#xA;        for( int i = 0; i &lt; settings.max_steps; ++i){&#xD;&#xA;            vec3 ray_endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            int obj_id;&#xD;&#xA;            float ray_distance = signedDistance(ray_endpoint, obj_id);&#xD;&#xA;            depth += ray_distance * settings.depth_weight;&#xD;&#xA;    &#xD;&#xA;            if( depth &gt; rasterized_depth){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            if(ray_distance &lt;= settings.min_distance){&#xD;&#xA;                out_depth = depth;&#xD;&#xA;                out_obj_id = obj_id;&#xD;&#xA;                return true;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(depth &gt; settings.max_distance){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        out_depth = inf;&#xD;&#xA;        out_obj_id = NULL_ID;&#xD;&#xA;        return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float checkerBoardTexture(in vec2 uv){&#xD;&#xA;        vec2 q = floor(uv);&#xD;&#xA;        return clamp(mod( q.x+q.y, 2.0 ), 0.25, 1.0);&#xD;&#xA;    }&#xD;&#xA;    float fogify(in float dist){&#xD;&#xA;        return  1.0/ (1.0 + dist*dist * 0.1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RayMarchSettings rm_settings = RayMarchSettings(128, 100000.0, 0.0001, 0.5);&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        vec3 origin = vec3(u_origin.x, u_origin.y, u_origin.z);&#xD;&#xA;        origin = origin.zyx;&#xD;&#xA;        Ray ray = getRay(TexCoords, u_resolution, u_rotation, origin);&#xD;&#xA;        vec3 texture_color = texture(u_screen_texture, TexCoords).rgb;&#xD;&#xA;        float rasterized_depth = texture(u_depth_texture, TexCoords).r;&#xD;&#xA;    &#xD;&#xA;        float depth = inf;&#xD;&#xA;        int obj_id = NULL_ID;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        vec3 color;&#xD;&#xA;        if(rayMarch(ray, rm_settings,rasterized_depth,  depth, obj_id)){&#xD;&#xA;            vec3 endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            float pattern_value = checkerBoardTexture(endpoint.xz * 4.0);&#xD;&#xA;    &#xD;&#xA;            if(obj_id == SPHERE_ID){&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;            if(obj_id == VSPHERE_ID){&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            switch(obj_id){&#xD;&#xA;                case SPHERE_ID:&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                case VSPHERE_ID:&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                default:&#xD;&#xA;                color = vec3(1.0,0.0,1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;         }else{&#xD;&#xA;            float re_rasterized_depth = rasterized_depth == inf ? 0.0 : rasterized_depth;&#xD;&#xA;            color = texture_color +re_rasterized_depth/100.f;&#xD;&#xA;         }&#xD;&#xA;        FragColor = vec4(color, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The `u_depth_texture` is where the depth comes from (and what `DepthColor` corresponds to)  The `u_screen_texture` is just a texture of the rasterization pass information (output of `FragColor`).  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#UPDATE:&#xD;&#xA;&#xD;&#xA;So [this answer][3] outlined exactly my problem.  I had to make the following changes:&#xD;&#xA;&#xD;&#xA;    vec3 getRotatedRayDirection(vec3 ray_dir, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        //vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;        float cosA;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;    &#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        vec3 rot_ray_dir = getRotatedRayDirection(ray_dir, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        float cosA = ray_dir.z/length(ray_dir);&#xD;&#xA;        return Ray(ray_origin, rot_ray_dir, cosA);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Above I basically added cosA as a seperate value onto the ray, as suggested by the linked answer, with the appropriate code changes to avoid re-running `calculateFragmentRay`.  However I needed to figure out which cosine corresponded to the one in thier picture, I knew it was a lateral dimension, it happened to be Z in this case, and I used the standard method of retrieving cosine from a normalized vector.&#xD;&#xA;&#xD;&#xA;After that I did exactly what the linked answer said and made the following change:&#xD;&#xA;&#xD;&#xA;    if( (depth * ray.cosA) &gt; rasterized_depth){&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here are the results! No depth artifacts!&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rZakQ.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4fD5Z.gif&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/7675/6530&#xD;&#xA;  [4]: https://i.stack.imgur.com/IptJC.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/kIzIU.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="19956" PostHistoryTypeId="5" PostId="7674" RevisionGUID="f2d10263-2e0f-4da9-b210-fd9ae0b66bfb" CreationDate="2018-05-30T20:24:45.473" UserId="6530" Comment="added 157 characters in body" Text="I'm trying to apply raymarching on top of 3D rasterization, ordering what 3D object gets displayed based on the depth of a rasterization pass and the raymarch depth.   After getting the transform right for *position* ([using the information here][1]) I was able to have the position of the raymarched spheres coherent with the rasterized cubes.   I ran into issues however with depth being different at the edges of the screen compared to the middle, despite position never changing.  &#xD;&#xA;&#xD;&#xA;These gifs should show what I'm talking about &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;higher res versions&#xD;&#xA;https://ibb.co/ebji0y&#xD;&#xA;https://ibb.co/dhUGLy&#xD;&#xA;&#xD;&#xA;Something odd is going on with depth, but I don't understand what I'm doing wrong?  Here is my fragment shader for my depth texture render pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    layout(location = 1) out float DepthColor;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;    // texture samplers&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform sampler2D texture1;&#xD;&#xA;    uniform float near;&#xD;&#xA;    uniform float far;&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(float depth)&#xD;&#xA;    {&#xD;&#xA;        float z = depth * 2.0 - 1.0; // back to NDC&#xD;&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        float depth = LinearizeDepth(gl_FragCoord.z);&#xD;&#xA;        DepthColor = depth;&#xD;&#xA;        FragColor = mix(texture(texture0, TexCoord), texture(texture1, TexCoord), 0.3);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here is my shader for the final raymarch pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_screen_texture;&#xD;&#xA;    uniform sampler2D u_depth_texture;&#xD;&#xA;    uniform float u_fov;&#xD;&#xA;    uniform vec3 u_rotation;&#xD;&#xA;    uniform vec3 u_origin;&#xD;&#xA;    uniform vec3 u_resolution;&#xD;&#xA;    &#xD;&#xA;    const float inf = uintBitsToFloat(0x7F800000u);&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecX(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(1, 0, 0,&#xD;&#xA;                           0, cos(theta), -sin(theta),&#xD;&#xA;                           0, sin(theta), cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecY(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(cos(theta), 0, sin(theta),&#xD;&#xA;                           0, 1, 0,&#xD;&#xA;                           -sin(theta), 0, cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 calculateFragementRay(in vec2 fragCoord, in vec3 resolution){&#xD;&#xA;        vec2 uv = fragCoord;&#xD;&#xA;        uv.x = (uv.x * 2.0) - 1.0;&#xD;&#xA;        uv.y = (2.0 * uv.y) - 1.0;&#xD;&#xA;        if(resolution.x &gt;= resolution.y){&#xD;&#xA;            uv.x *= resolution.x/resolution.y;&#xD;&#xA;        }else{&#xD;&#xA;            uv.y *= resolution.y/resolution.x;&#xD;&#xA;        }&#xD;&#xA;        float tan_fov = tan(u_fov/2.0);&#xD;&#xA;        vec2 pxy = uv * tan_fov;&#xD;&#xA;        vec3 ray_dir = normalize(vec3(pxy, 1));&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getRayDirection(in vec2 fragCoord, in vec3 resolution, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;    &#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;        vec3 ray_dir = getRayDirection(fragCoord, resolution, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        return Ray(ray_origin, ray_dir);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct RayMarchSettings{&#xD;&#xA;        int max_steps;&#xD;&#xA;        float max_distance;&#xD;&#xA;        float min_distance;&#xD;&#xA;        float depth_weight;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Sphere{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        float radius;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float signedDistance(vec3 p, in Sphere sphere){&#xD;&#xA;        return (length(p - sphere.origin) - sphere.radius);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const int NULL_ID = -1;&#xD;&#xA;    const int SPHERE_ID = 0;&#xD;&#xA;    const int VSPHERE_ID = 1;&#xD;&#xA;    &#xD;&#xA;    Sphere test_sphere = Sphere(vec3(0.0, 4.0, 4.0),1.0);&#xD;&#xA;    Sphere volume_sphere = Sphere(vec3(0.0, 1.0, 0.0),2.0);&#xD;&#xA;    float signedDistance(vec3 ray_endpoint, out int obj_id){&#xD;&#xA;        float d0 = signedDistance(ray_endpoint, test_sphere);&#xD;&#xA;        float d1 = signedDistance(ray_endpoint, volume_sphere);&#xD;&#xA;        float minval = min(d0, d1);&#xD;&#xA;        obj_id = minval == d0 ? SPHERE_ID : VSPHERE_ID;&#xD;&#xA;        return minval;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool rayMarch(Ray ray, in RayMarchSettings settings, in float rasterized_depth, out float out_depth, out int out_obj_id){&#xD;&#xA;        float depth = 0.0;&#xD;&#xA;        for( int i = 0; i &lt; settings.max_steps; ++i){&#xD;&#xA;            vec3 ray_endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            int obj_id;&#xD;&#xA;            float ray_distance = signedDistance(ray_endpoint, obj_id);&#xD;&#xA;            depth += ray_distance * settings.depth_weight;&#xD;&#xA;    &#xD;&#xA;            if( depth &gt; rasterized_depth){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            if(ray_distance &lt;= settings.min_distance){&#xD;&#xA;                out_depth = depth;&#xD;&#xA;                out_obj_id = obj_id;&#xD;&#xA;                return true;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(depth &gt; settings.max_distance){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        out_depth = inf;&#xD;&#xA;        out_obj_id = NULL_ID;&#xD;&#xA;        return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float checkerBoardTexture(in vec2 uv){&#xD;&#xA;        vec2 q = floor(uv);&#xD;&#xA;        return clamp(mod( q.x+q.y, 2.0 ), 0.25, 1.0);&#xD;&#xA;    }&#xD;&#xA;    float fogify(in float dist){&#xD;&#xA;        return  1.0/ (1.0 + dist*dist * 0.1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RayMarchSettings rm_settings = RayMarchSettings(128, 100000.0, 0.0001, 0.5);&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        vec3 origin = vec3(u_origin.x, u_origin.y, u_origin.z);&#xD;&#xA;        origin = origin.zyx;&#xD;&#xA;        Ray ray = getRay(TexCoords, u_resolution, u_rotation, origin);&#xD;&#xA;        vec3 texture_color = texture(u_screen_texture, TexCoords).rgb;&#xD;&#xA;        float rasterized_depth = texture(u_depth_texture, TexCoords).r;&#xD;&#xA;    &#xD;&#xA;        float depth = inf;&#xD;&#xA;        int obj_id = NULL_ID;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        vec3 color;&#xD;&#xA;        if(rayMarch(ray, rm_settings,rasterized_depth,  depth, obj_id)){&#xD;&#xA;            vec3 endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            float pattern_value = checkerBoardTexture(endpoint.xz * 4.0);&#xD;&#xA;    &#xD;&#xA;            if(obj_id == SPHERE_ID){&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;            if(obj_id == VSPHERE_ID){&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            switch(obj_id){&#xD;&#xA;                case SPHERE_ID:&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                case VSPHERE_ID:&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                default:&#xD;&#xA;                color = vec3(1.0,0.0,1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;         }else{&#xD;&#xA;            float re_rasterized_depth = rasterized_depth == inf ? 0.0 : rasterized_depth;&#xD;&#xA;            color = texture_color +re_rasterized_depth/100.f;&#xD;&#xA;         }&#xD;&#xA;        FragColor = vec4(color, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The `u_depth_texture` is where the depth comes from (and what `DepthColor` corresponds to)  The `u_screen_texture` is just a texture of the rasterization pass information (output of `FragColor`).  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#UPDATE:&#xD;&#xA;&#xD;&#xA;So [this answer][4] outlined exactly my problem.  I had to make the following changes:&#xD;&#xA;&#xD;&#xA;    vec3 getRotatedRayDirection(vec3 ray_dir, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        //vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;        float cosA;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;    &#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        vec3 rot_ray_dir = getRotatedRayDirection(ray_dir, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        float cosA = ray_dir.z/length(ray_dir);&#xD;&#xA;        return Ray(ray_origin, rot_ray_dir, cosA);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Above I basically added cosA as a seperate value onto the ray, as suggested by the linked answer, with the appropriate code changes to avoid re-running `calculateFragmentRay`.  However I needed to figure out which cosine corresponded to the one in thier picture, I knew it was a lateral dimension, it happened to be Z in this case, and I used the standard method of retrieving cosine from a normalized vector.&#xD;&#xA;&#xD;&#xA;After that I did exactly what the linked answer said and made the following change:&#xD;&#xA;&#xD;&#xA;    if( (depth * ray.cosA) &gt; rasterized_depth){&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here are the results! No depth artifacts!&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays&#xD;&#xA;  [2]: https://i.stack.imgur.com/rZakQ.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4fD5Z.gif&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/7675/6530&#xD;&#xA;  [5]: https://i.stack.imgur.com/IptJC.gif&#xD;&#xA;  [6]: https://i.stack.imgur.com/kIzIU.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="19957" PostHistoryTypeId="2" PostId="7676" RevisionGUID="294abf51-05cb-4fd9-ac0a-c7a73c7eb33b" CreationDate="2018-05-31T02:25:27.737" UserId="8799" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bY0Kq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/HusjL.png&#xD;&#xA;&#xD;&#xA;The wall on the left of the red ball is perfectly reflective wall. &#xD;&#xA;&#xD;&#xA;In the first image there's a point light that lies on the plane of the reflective wall and in the second image, it's 0.01 units ahead of it. Due to the light being on the reflective wall, I think, I am getting black dots all over my image. &#xD;&#xA;&#xD;&#xA;I would like to know why putting a light on the same plane as the wall causes black dots ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19958" PostHistoryTypeId="1" PostId="7676" RevisionGUID="294abf51-05cb-4fd9-ac0a-c7a73c7eb33b" CreationDate="2018-05-31T02:25:27.737" UserId="8799" Text="Grainy image in my simple ray tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="19959" PostHistoryTypeId="3" PostId="7676" RevisionGUID="294abf51-05cb-4fd9-ac0a-c7a73c7eb33b" CreationDate="2018-05-31T02:25:27.737" UserId="8799" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19960" PostHistoryTypeId="2" PostId="7677" RevisionGUID="57eb61dd-47a8-4dc7-8852-ce75e0f40fa4" CreationDate="2018-05-31T03:19:33.277" UserId="48" Text="It's likely due to shadow rays. When the light source is exactly on the plane of the wall, a shadow ray traced to it may or may not be found to intersect the wall before it reaches the light. The result will depend on arithmetic roundoff error, and may appear as random noise, or stripes or some other artifact.&#xA;&#xA;To fix it, you can either keep the light offset slightly from the plane, or set up the wall object not to cast shadows (assuming it doesn't need to in the scene)." ContentLicense="CC BY-SA 4.0" />
  <row Id="19961" PostHistoryTypeId="5" PostId="7674" RevisionGUID="dea30db0-4d73-40ca-bf66-3feebd05e69d" CreationDate="2018-05-31T04:27:42.973" UserId="6530" Comment="added 43 characters in body" Text="I'm trying to apply raymarching on top of 3D rasterization, ordering what 3D object gets displayed based on the depth of a rasterization pass and the raymarch depth.   After getting the transform right for *position* ([using the information here][1]) I was able to have the position of the raymarched spheres coherent with the rasterized cubes.   I ran into issues however with depth being different at the edges of the screen compared to the middle, despite position never changing.  &#xD;&#xA;&#xD;&#xA;These gifs should show what I'm talking about &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;higher res versions&#xD;&#xA;https://ibb.co/ebji0y&#xD;&#xA;https://ibb.co/dhUGLy&#xD;&#xA;&#xD;&#xA;Something odd is going on with depth, but I don't understand what I'm doing wrong?  Here is my fragment shader for my depth texture render pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    layout(location = 1) out float DepthColor;&#xD;&#xA;    in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;    // texture samplers&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform sampler2D texture1;&#xD;&#xA;    uniform float near;&#xD;&#xA;    uniform float far;&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(float depth)&#xD;&#xA;    {&#xD;&#xA;        float z = depth * 2.0 - 1.0; // back to NDC&#xD;&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        float depth = LinearizeDepth(gl_FragCoord.z);&#xD;&#xA;        DepthColor = depth;&#xD;&#xA;        FragColor = mix(texture(texture0, TexCoord), texture(texture1, TexCoord), 0.3);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here is my shader for the final raymarch pass:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_screen_texture;&#xD;&#xA;    uniform sampler2D u_depth_texture;&#xD;&#xA;    uniform float u_fov;&#xD;&#xA;    uniform vec3 u_rotation;&#xD;&#xA;    uniform vec3 u_origin;&#xD;&#xA;    uniform vec3 u_resolution;&#xD;&#xA;    &#xD;&#xA;    const float inf = uintBitsToFloat(0x7F800000u);&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecX(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(1, 0, 0,&#xD;&#xA;                           0, cos(theta), -sin(theta),&#xD;&#xA;                           0, sin(theta), cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 rotVecY(in vec3 vector, in float theta){&#xD;&#xA;        mat3 rotmat = mat3(cos(theta), 0, sin(theta),&#xD;&#xA;                           0, 1, 0,&#xD;&#xA;                           -sin(theta), 0, cos(theta));&#xD;&#xA;        return vector * rotmat;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 calculateFragementRay(in vec2 fragCoord, in vec3 resolution){&#xD;&#xA;        vec2 uv = fragCoord;&#xD;&#xA;        uv.x = (uv.x * 2.0) - 1.0;&#xD;&#xA;        uv.y = (2.0 * uv.y) - 1.0;&#xD;&#xA;        if(resolution.x &gt;= resolution.y){&#xD;&#xA;            uv.x *= resolution.x/resolution.y;&#xD;&#xA;        }else{&#xD;&#xA;            uv.y *= resolution.y/resolution.x;&#xD;&#xA;        }&#xD;&#xA;        float tan_fov = tan(u_fov/2.0);&#xD;&#xA;        vec2 pxy = uv * tan_fov;&#xD;&#xA;        vec3 ray_dir = normalize(vec3(pxy, 1));&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getRayDirection(in vec2 fragCoord, in vec3 resolution, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;    &#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;        vec3 ray_dir = getRayDirection(fragCoord, resolution, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        return Ray(ray_origin, ray_dir);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct RayMarchSettings{&#xD;&#xA;        int max_steps;&#xD;&#xA;        float max_distance;&#xD;&#xA;        float min_distance;&#xD;&#xA;        float depth_weight;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Sphere{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        float radius;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float signedDistance(vec3 p, in Sphere sphere){&#xD;&#xA;        return (length(p - sphere.origin) - sphere.radius);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const int NULL_ID = -1;&#xD;&#xA;    const int SPHERE_ID = 0;&#xD;&#xA;    const int VSPHERE_ID = 1;&#xD;&#xA;    &#xD;&#xA;    Sphere test_sphere = Sphere(vec3(0.0, 4.0, 4.0),1.0);&#xD;&#xA;    Sphere volume_sphere = Sphere(vec3(0.0, 1.0, 0.0),2.0);&#xD;&#xA;    float signedDistance(vec3 ray_endpoint, out int obj_id){&#xD;&#xA;        float d0 = signedDistance(ray_endpoint, test_sphere);&#xD;&#xA;        float d1 = signedDistance(ray_endpoint, volume_sphere);&#xD;&#xA;        float minval = min(d0, d1);&#xD;&#xA;        obj_id = minval == d0 ? SPHERE_ID : VSPHERE_ID;&#xD;&#xA;        return minval;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool rayMarch(Ray ray, in RayMarchSettings settings, in float rasterized_depth, out float out_depth, out int out_obj_id){&#xD;&#xA;        float depth = 0.0;&#xD;&#xA;        for( int i = 0; i &lt; settings.max_steps; ++i){&#xD;&#xA;            vec3 ray_endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            int obj_id;&#xD;&#xA;            float ray_distance = signedDistance(ray_endpoint, obj_id);&#xD;&#xA;            depth += ray_distance * settings.depth_weight;&#xD;&#xA;    &#xD;&#xA;            if( depth &gt; rasterized_depth){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            if(ray_distance &lt;= settings.min_distance){&#xD;&#xA;                out_depth = depth;&#xD;&#xA;                out_obj_id = obj_id;&#xD;&#xA;                return true;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(depth &gt; settings.max_distance){&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        out_depth = inf;&#xD;&#xA;        out_obj_id = NULL_ID;&#xD;&#xA;        return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float checkerBoardTexture(in vec2 uv){&#xD;&#xA;        vec2 q = floor(uv);&#xD;&#xA;        return clamp(mod( q.x+q.y, 2.0 ), 0.25, 1.0);&#xD;&#xA;    }&#xD;&#xA;    float fogify(in float dist){&#xD;&#xA;        return  1.0/ (1.0 + dist*dist * 0.1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RayMarchSettings rm_settings = RayMarchSettings(128, 100000.0, 0.0001, 0.5);&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;        vec3 origin = vec3(u_origin.x, u_origin.y, u_origin.z);&#xD;&#xA;        origin = origin.zyx;&#xD;&#xA;        Ray ray = getRay(TexCoords, u_resolution, u_rotation, origin);&#xD;&#xA;        vec3 texture_color = texture(u_screen_texture, TexCoords).rgb;&#xD;&#xA;        float rasterized_depth = texture(u_depth_texture, TexCoords).r;&#xD;&#xA;    &#xD;&#xA;        float depth = inf;&#xD;&#xA;        int obj_id = NULL_ID;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        vec3 color;&#xD;&#xA;        if(rayMarch(ray, rm_settings,rasterized_depth,  depth, obj_id)){&#xD;&#xA;            vec3 endpoint = ray.origin + ray.direction * depth;&#xD;&#xA;            float pattern_value = checkerBoardTexture(endpoint.xz * 4.0);&#xD;&#xA;    &#xD;&#xA;            if(obj_id == SPHERE_ID){&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;            if(obj_id == VSPHERE_ID){&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            switch(obj_id){&#xD;&#xA;                case SPHERE_ID:&#xD;&#xA;                color = vec3(1.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                case VSPHERE_ID:&#xD;&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xD;&#xA;                break;&#xD;&#xA;                default:&#xD;&#xA;                color = vec3(1.0,0.0,1.0)*pattern_value;&#xD;&#xA;            }&#xD;&#xA;         }else{&#xD;&#xA;            float re_rasterized_depth = rasterized_depth == inf ? 0.0 : rasterized_depth;&#xD;&#xA;            color = texture_color +re_rasterized_depth/100.f;&#xD;&#xA;         }&#xD;&#xA;        FragColor = vec4(color, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The `u_depth_texture` is where the depth comes from (and what `DepthColor` corresponds to)  The `u_screen_texture` is just a texture of the rasterization pass information (output of `FragColor`).  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#UPDATE:&#xD;&#xA;&#xD;&#xA;So [this answer][4] outlined exactly my problem.  I had to make the following changes:&#xD;&#xA;&#xD;&#xA;    vec3 getRotatedRayDirection(vec3 ray_dir, in vec3 rotation){&#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        //vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xD;&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xD;&#xA;        return ray_dir;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct Ray{&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;        float cosA;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xD;&#xA;    &#xD;&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xD;&#xA;        vec3 rot_ray_dir = getRotatedRayDirection(ray_dir, rotation);&#xD;&#xA;        vec3 ray_origin = origin;&#xD;&#xA;        float cosA = ray_dir.z; // a.z/length(a), already normalized so length(a) == 1.0. &#xD;&#xA;        return Ray(ray_origin, rot_ray_dir, cosA);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Above I basically added cosA as a seperate value onto the ray, as suggested by the linked answer, with the appropriate code changes to avoid re-running `calculateFragmentRay`.  However I needed to figure out which cosine corresponded to the one in thier picture, I knew it was a lateral dimension, it happened to be Z in this case, and I used the standard method of retrieving cosine from a normalized vector.&#xD;&#xA;&#xD;&#xA;After that I did exactly what the linked answer said and made the following change:&#xD;&#xA;&#xD;&#xA;    if( (depth * ray.cosA) &gt; rasterized_depth){&#xD;&#xA;        break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here are the results! No depth artifacts!&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays&#xD;&#xA;  [2]: https://i.stack.imgur.com/rZakQ.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4fD5Z.gif&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/7675/6530&#xD;&#xA;  [5]: https://i.stack.imgur.com/IptJC.gif&#xD;&#xA;  [6]: https://i.stack.imgur.com/kIzIU.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="19962" PostHistoryTypeId="2" PostId="7678" RevisionGUID="364eaddd-1c2c-4a11-a05b-f27d217cb891" CreationDate="2018-05-31T05:55:14.650" UserId="8802" Text="For general fixed-point scaling problem, If I want to scale twice about a fixed point (x, y), I need to first translate the object so that fixed point coincides with the origin, then do the scaling and then translate the object back to its position.&#xD;&#xA;&#xD;&#xA;In the books, the matrix operation for this is given as&#xD;&#xA;&#xD;&#xA;    |1 0 x| |s 0 0| |1 0 -x|&#xD;&#xA;    |0 1 y|*|0 s 0|*|0 1 -y|&#xD;&#xA;    |0 0 1| |0 0 1| |0 0  1|&#xD;&#xA;&#xD;&#xA;and my doubt is, why in the first matrix, we have used x, y? Don't we need -x, -y since we already are at some fixed point x, y and we want to shift that point to 0,0 and so we probably need to translate back by x, y ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19963" PostHistoryTypeId="1" PostId="7678" RevisionGUID="364eaddd-1c2c-4a11-a05b-f27d217cb891" CreationDate="2018-05-31T05:55:14.650" UserId="8802" Text="General fixed-point scaling" ContentLicense="CC BY-SA 4.0" />
  <row Id="19964" PostHistoryTypeId="3" PostId="7678" RevisionGUID="364eaddd-1c2c-4a11-a05b-f27d217cb891" CreationDate="2018-05-31T05:55:14.650" UserId="8802" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19965" PostHistoryTypeId="2" PostId="7679" RevisionGUID="320dd805-6ec3-4196-b25a-bb9dc646b93f" CreationDate="2018-05-31T10:56:45.740" UserId="8541" Text="I'd like to add the approach that worked for me in this particular situation as an answer.&#xD;&#xA;&#xD;&#xA;My &quot;cubemaps&quot; are small, face is only 10x10 pixels and because of that I was able to shove thousands of those cubemaps in one big 2D texture atlas. Faces were laid out sequentially and atlas offsets were computed in fragment shader on the fly." ContentLicense="CC BY-SA 4.0" />
  <row Id="19975" PostHistoryTypeId="2" PostId="7682" RevisionGUID="f4e49913-a373-4b44-b31e-77df8694c936" CreationDate="2018-06-01T08:17:56.800" UserId="1582" Text="I'll throw in another possibility. The Morgan Mcguire light fields probe paper uses a tetrahedron mapping to replace cube maps and claims a 4x bandwidth increase. Basically cubemaps are inefficient in the corners. They also used an atlas layout. Given that you faces are 10x10 though it might not make much of a difference in your case. &#xD;&#xA;&#xD;&#xA;Mcguire &quot;Real-Time Global Illumination using Precomputed Light Field Probes&quot; p.2 (fig. 2)&#xD;&#xA;http://research.nvidia.com/sites/default/files/pubs/2017-02_Real-Time-Global-Illumination/light-field-probes-final.pdf &#xD;&#xA;&#xD;&#xA;Original mapping comes from Cigolle p.9&#xD;&#xA;http://jcgt.org/published/0003/02/01/" ContentLicense="CC BY-SA 4.0" />
  <row Id="19978" PostHistoryTypeId="5" PostId="289" RevisionGUID="b1ab4663-88b7-467a-8eee-ffa742a5d39f" CreationDate="2018-06-01T23:44:06.937" UserId="48" Comment="updated link to gpu gems chapter since the previous link broke" Text="There are two cases I can think of where multiple blurs would be performed in succession on a single image.&#xD;&#xA;&#xD;&#xA;First, when performing a large-radius blur, it may reduce the total computation if you first downsample the image (which is a blur) and then perform a smaller-radius blur on the downsampled image.  For example, downsampling an image by 4x and then performing a 10px-wide Gaussian blur on the result would approximate performing a 40px-wide Gaussian blur on the original&amp;mdash;but is likely to be significantly faster due to improved locality in sampling and fewer samples taken overall.&#xD;&#xA;&#xD;&#xA;![Box approximation of a wide Gaussian][1]&#xD;&#xA;&#xD;&#xA;The initial downsampling filter is often simply a box (as shown above), but it can also itself be something more sophisticated, such as a triangle or bicubic filter, in order to improve the approximation.&#xD;&#xA;&#xD;&#xA;![Mitchell-Netravali approximation of a wide Gaussian][2]&#xD;&#xA;&#xD;&#xA;This is a Mitchell-Netravali (cubic) downsample followed by a Gaussian. Interestingly, it turns out that using a Gaussian for the initial downsampling doesn't make such a great approximation if your goal is to use it to produce a larger Gaussian.&#xD;&#xA;&#xD;&#xA;An initial downsampling step is also frequently used when implementing visual effects like depth of field and motion blur, for similar reasons.&#xD;&#xA;&#xD;&#xA;A second reason to perform multiple Gaussian blurs is to approximate a non-separable filter by blending between various Gaussians of different radii.  This is commonly used in bloom, for example.  The standard bloom effect works by first thresholding to extract bright objects from the image, then creating several blurred copies of the bright objects (usually using the downsample-then-blur technique just discussed), and finally weighting and summing them together.  This allows artists a greater level of control over the final shape and appearance of the bloom.&#xD;&#xA;&#xD;&#xA;![Sum of three Gaussians creates a &quot;heavy-tailed&quot; function][3]&#xD;&#xA;&#xD;&#xA;Here, for example, is a weighted sum of three Gaussians (red line) which produces a shape that's more narrowly peaked and heavier-tailed than a single Gaussian (blue line).  This is a popular sort of configuration to use for bloom, as the combination of a narrow, bright center with a wide, diffuse halo is visually appealing.  But since this kind of filter shape isn't separable, it's cheaper to make it out of a mixture of Gaussians than to try to filter with it directly.&#xD;&#xA;&#xD;&#xA;Another variation on this idea is the concept of a diffusion profile used with subsurface scattering for skin rendering. Different blur radii may be used for the red, green, and blue channels to approximate the way different wavelengths of light scatter differently, as in [GPU Gems 3 skin shading chapter](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch14.html) by Eugene d'Eon and Dave Luebke.  In fact, that paper uses a mixture of seven different Gaussians, with different R, G, and B weights for each, to approximate the complicated non-separable, wavelength-dependent scattering response of human skin.&#xD;&#xA;&#xD;&#xA;[![Diffusion profiles from GPU Gems 3 article on skin shading][4]](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch14.html)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ugYom.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xdbOo.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZzS3i.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YYAga.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="19982" PostHistoryTypeId="2" PostId="7685" RevisionGUID="223c3a57-cffd-4c2f-b496-2af5221d42eb" CreationDate="2018-06-02T09:48:06.060" UserId="8709" Text="I wrote a program that displays points expressed in 3D in a 2D canvas, using perspective projection. The aim is to display a cube. Each face of the cube is drawn by linearly interpolating the points that define it. My cube can be translated, scaled and rotated thanks to transformation matrices.&#xD;&#xA;&#xD;&#xA;For the moment, my program is not paralelized at all and uses CPU to make the various computations (e.g. : projection of 3D points into the 2D canvas using perspective projection, matrices computations, product of a point by a matrix, drawing cube's faces with linear interpolation).&#xD;&#xA;&#xD;&#xA;There is a speed problem. I described it below :&#xD;&#xA;&#xD;&#xA;1. Linear interpolation as I wrote it, which never calculates duplicates, costs a lot of accesses to RAM. Applied to each face, it requires also a lot of computations.&#xD;&#xA;&#xD;&#xA;2. My cube's faces should be drawn thanks to a linear interpolation with a very very small step (e.g. : `0.001`) to be beautiful. However, it's simply a utopia. It would require too many computations and accesses to RAM. My program would freeze.&#xD;&#xA;&#xD;&#xA;3. A given transformation matrice is multiplied by point N°`1`, then by N°`2`, then by N°`k`, then by N°`8`. Obviously, the matrices are not multiplied by the interpolated points ! (it implies a gain in computation speed).&#xD;&#xA;&#xD;&#xA;# Questions&#xD;&#xA;&#xD;&#xA;Without using any API :&#xD;&#xA;&#xD;&#xA;1. Are GPU util to paralelize linear interpolations ? If I remember well my courses, yes. So : ***how could I send my points and my linear interpolation function to GPU ?*** Note that I would be disapointed if I must use linear interpolation program of the GPU (if it exists) instead of mine.&#xD;&#xA;&#xD;&#xA;2. How could I draw beautiful cube's faces without using a linear interpolation's step of `0.001` ?&#xD;&#xA;&#xD;&#xA;3. Less important : is it possible to increase computation speed in making the product of a sequence of points with a matrice ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19983" PostHistoryTypeId="1" PostId="7685" RevisionGUID="223c3a57-cffd-4c2f-b496-2af5221d42eb" CreationDate="2018-06-02T09:48:06.060" UserId="8709" Text="Using GPU instead of CPU in Scala" ContentLicense="CC BY-SA 4.0" />
  <row Id="19984" PostHistoryTypeId="3" PostId="7685" RevisionGUID="223c3a57-cffd-4c2f-b496-2af5221d42eb" CreationDate="2018-06-02T09:48:06.060" UserId="8709" Text="|gpu|performance|perspective|interpolation|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19985" PostHistoryTypeId="2" PostId="7686" RevisionGUID="e2fca64e-b80c-4d34-8015-3267f391cc23" CreationDate="2018-06-03T09:21:53.640" UserId="8823" Text="I ran into this problem while trying to find the paint color of the doors in my house: is it in principe possible to automatically determine the paint color from a photo?&#xD;&#xA;&#xD;&#xA;Different types of colour standards (such as RAL, https://en.wikipedia.org/wiki/List_of_RAL_colors) mention RGB values, but of course lighting conditions, material, camera and probably other factors highly affect the RGB value that is measured.&#xD;&#xA;&#xD;&#xA;Does a solution to this problem already exist?&#xD;&#xA;&#xD;&#xA;An idea I had is to hold an official color reference chart in the photo next to the target object (e.g. my door), so the transformation due to lighting conditions and camera between the known RGB values of the colors on the reference chart and those in the photo could somehow be established. Then the inverse transformation could be applied to the color of the target object and the closest matching paint color could be found.&#xD;&#xA;&#xD;&#xA;Could this idea work and if so, what kind of transformation between reference and measurement could be expected?&#xD;&#xA;&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="19986" PostHistoryTypeId="1" PostId="7686" RevisionGUID="e2fca64e-b80c-4d34-8015-3267f391cc23" CreationDate="2018-06-03T09:21:53.640" UserId="8823" Text="Determine paint color from a photo" ContentLicense="CC BY-SA 4.0" />
  <row Id="19987" PostHistoryTypeId="3" PostId="7686" RevisionGUID="e2fca64e-b80c-4d34-8015-3267f391cc23" CreationDate="2018-06-03T09:21:53.640" UserId="8823" Text="|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19988" PostHistoryTypeId="50" PostId="6365" RevisionGUID="a6af9fc0-088c-4af9-96e9-3939ead3fde8" CreationDate="2018-06-03T12:09:20.087" UserId="-1" />
  <row Id="19990" PostHistoryTypeId="2" PostId="7687" RevisionGUID="24a09628-3874-43d0-82c8-1c9e60637db6" CreationDate="2018-06-03T16:09:25.213" UserId="8826" Text="I have read the OpenGl documentation of texelFetch, which is:&#xD;&#xA;&#xD;&#xA;gvec4 texelFetch(gsampler2D sampler, ivec2 P, int lod).&#xD;&#xA; &#xD;&#xA;I know the first argument &quot;sampler&quot; is just a texture. But I am very confused about the second and third arguments.&#xD;&#xA;&#xD;&#xA;According to the documentation, the second argument &quot;P&quot; is a texture coordinate. But it has the type ivec2, which means that it is a vector of integers. Shouldn't a texture coordinate be in the range [0, 1]? &#xD;&#xA;&#xD;&#xA;And for the third argument &quot;lod&quot;, in the documentation, it said &quot;If present, specifies the level-of-detail within the texture from which the texel will be fetched.&quot; I have no idea how to set this argument...&#xD;&#xA;&#xD;&#xA;Could anyone explain this and give a real example of how to use texelFetch?&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="19991" PostHistoryTypeId="1" PostId="7687" RevisionGUID="24a09628-3874-43d0-82c8-1c9e60637db6" CreationDate="2018-06-03T16:09:25.213" UserId="8826" Text="How to use GLSL texelFetch?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19992" PostHistoryTypeId="3" PostId="7687" RevisionGUID="24a09628-3874-43d0-82c8-1c9e60637db6" CreationDate="2018-06-03T16:09:25.213" UserId="8826" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="19993" PostHistoryTypeId="2" PostId="7688" RevisionGUID="7fc6926b-7387-4c25-85ba-31aa9b98ef51" CreationDate="2018-06-03T17:03:06.140" UserId="3003" Text="In theory yes, but practically speaking, I doubt it would be very easy. First, the color may not be representable by the color space that your camera of choice produces images in. We've recently started seeing wide color gamut (P3) cameras and displays. There are colors these cameras record and displays produce that fall outside of the sRGB color space that most cameras and displays support. Likewise, there are visible colors that are outside of the P3 color space. So the first hurdle is to have a device which records and stores the colors you're dealing with.&#xD;&#xA;&#xD;&#xA;Next you have to do the lighting correction once you get the image into the computer. This is actually not as hard as it sounds. There are products that allow you to do this using a system similar to what you describe. [Here's a video](https://www.youtube.com/watch?v=1fcve4Dp1lo&amp;feature=youtu.be) for one that works with video rather than stills.&#xD;&#xA;&#xD;&#xA;Once you've done all that, you need some way of translating that color from some RGB space into something that your local paint store can understand. I'm not sure how to do that. Most paint store employees are not trained in color science and have to use a limited toolset provided by the paint companies.&#xD;&#xA;&#xD;&#xA;Is there any way you could get a small, inconspicuous piece of the actual object? Most paint stores have a machine that will take a physical object and create a paint that's a fairly close match to that object. Whether their matches are close enough for your needs is something you'd have to determine. I've used them before and found that while they get very close, I'm still able to see the difference between the original and the new paint, unless I can paint up to corners." ContentLicense="CC BY-SA 4.0" />
  <row Id="19994" PostHistoryTypeId="4" PostId="7611" RevisionGUID="fa86d14d-638f-409c-a86b-1595dd30ef8b" CreationDate="2018-06-03T19:22:05.567" UserId="8820" Comment="fixed misspelling of epsilon" Text="What is the use of epsilon in the Möller–Trumbore intersection algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="19995" PostHistoryTypeId="24" PostId="7611" RevisionGUID="fa86d14d-638f-409c-a86b-1595dd30ef8b" CreationDate="2018-06-03T19:22:05.567" Comment="Proposed by 8820 approved by 231 edit id of 418" ContentLicense="CC BY-SA 4.0" />
  <row Id="19996" PostHistoryTypeId="50" PostId="6370" RevisionGUID="f8134c27-bf42-4abb-8687-5f346bba8994" CreationDate="2018-06-04T00:11:52.323" UserId="-1" />
  <row Id="20002" PostHistoryTypeId="5" PostId="7672" RevisionGUID="e5eea1a0-a99c-4979-ac7c-451a9a0d7984" CreationDate="2018-06-04T07:42:53.117" UserId="209" Comment="(Hopefully) conveyed the original author's intended meaning more clearly" Text="Though polygons can be sent in any order some polygons may lie in the same plane. Their respective zs can be calculated using the formula z=(-Ax-By-D)/C, and if the two polygon surfaces are at same depth then they can have same value of z. &#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="20003" PostHistoryTypeId="2" PostId="7690" RevisionGUID="1f6611d2-b762-40dd-b2e9-61c49cde7c3f" CreationDate="2018-06-04T11:19:30.360" UserId="8831" Text="I'm trying to show a 3D model on Facebook and display its edges and lines. I found that I could export a 3D model from Sketchup using glTF Export plugin to a glb file that I can drag and drop in a Facebook post.&#xD;&#xA;&#xD;&#xA;I tried many ways to set material, width, styles on lines in my model but once imported in Facebook the lines don't appear. It's not a Facebook problem since the gtTF viewer has the same display. I also have the same rendering problem by ubloading an stl file to [Sketchfab][1].&#xD;&#xA;&#xD;&#xA; - Is there a missing implementation in glTF format?&#xD;&#xA;&#xD;&#xA; - Is there another freeware to export a 3D model to Facebook (showing edges)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://sketchfab.com&#xD;&#xA;  [2]: https://i.stack.imgur.com/XfWql.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20004" PostHistoryTypeId="1" PostId="7690" RevisionGUID="1f6611d2-b762-40dd-b2e9-61c49cde7c3f" CreationDate="2018-06-04T11:19:30.360" UserId="8831" Text="How to display edges in a 3D file on Facebook" ContentLicense="CC BY-SA 4.0" />
  <row Id="20005" PostHistoryTypeId="3" PostId="7690" RevisionGUID="1f6611d2-b762-40dd-b2e9-61c49cde7c3f" CreationDate="2018-06-04T11:19:30.360" UserId="8831" Text="|rendering|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20006" PostHistoryTypeId="2" PostId="7691" RevisionGUID="eb1c9987-b2fb-4aaf-8ebf-28838ae5c047" CreationDate="2018-06-04T16:53:46.333" UserId="8826" Text="ok, I have figured out this problem.&#xD;&#xA;&#xD;&#xA;For the texture coordinates, there are two kind of texture coordinates. One is normalized texture coordinates, which is in the range [0, 1]. The other is texel space, which is in the range [0, size], where size is the size of the texture. For texelFetch(), the texel space is used.&#xD;&#xA;&#xD;&#xA;For lod, it means the level of detail in the mipmap. We can simply use 0 for the base level (the original size).&#xD;&#xA;&#xD;&#xA;Thus, an example of using texelFetch() should be:&#xD;&#xA;&#xD;&#xA;vec4 texelValue= texelFetch(texture2D, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="20007" PostHistoryTypeId="5" PostId="7691" RevisionGUID="aa06abe5-32d1-499d-af0f-4c4ffcccc10f" CreationDate="2018-06-05T01:23:15.337" UserId="2654" Comment="added 8 characters in body" Text="OK, I have figured out this problem.&#xD;&#xA;&#xD;&#xA;For the texture coordinates, there are two kind of texture coordinates. One is normalized texture coordinates, which is in the range [0, 1]. The other is texel space, which is in the range [0, size), where size is the size of the texture. For texelFetch(), the texel space is used.&#xD;&#xA;&#xD;&#xA;For `lod`, it means the level of detail in the mipmap. We can simply use 0 for the base level (the original size).&#xD;&#xA;&#xD;&#xA;Thus, an example of using `texelFetch()` should be:&#xD;&#xA;&#xD;&#xA;    vec4 texelValue= texelFetch(texture2D, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="20008" PostHistoryTypeId="2" PostId="7692" RevisionGUID="35cef4ae-8e6a-4391-88dc-50e5e54c99bd" CreationDate="2018-06-05T08:15:49.853" UserId="7868" Text="MIS weights for BDPT are calculated with ratios of PDFs for each vertex under different types of light transport (radiance vs. importance). These probabilities are regenerated for frontier vertices during subpath connection, which makes sense - the direction from the $t-1$-th camera vertex to the $s-1$-th light vertex will be different to the direction between the $t-1$-th and $t$th camera vertices.&#xD;&#xA;&#xD;&#xA;PBRT also reccomends updating reverse probabilities for *previous* vertices, though. Why? The probability of tracing a ray from $s-1$ to $s-2$ won't be affected by the probability of tracing a ray between $s-1$ and $t-1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="20009" PostHistoryTypeId="1" PostId="7692" RevisionGUID="35cef4ae-8e6a-4391-88dc-50e5e54c99bd" CreationDate="2018-06-05T08:15:49.853" UserId="7868" Text="Reverse PDF updates for s-2 or t-2 vertices in MIS for BDPT" ContentLicense="CC BY-SA 4.0" />
  <row Id="20010" PostHistoryTypeId="3" PostId="7692" RevisionGUID="35cef4ae-8e6a-4391-88dc-50e5e54c99bd" CreationDate="2018-06-05T08:15:49.853" UserId="7868" Text="|pathtracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20012" PostHistoryTypeId="5" PostId="7691" RevisionGUID="7d89b5d7-eace-482f-b8db-cdd3a754215c" CreationDate="2018-06-05T14:57:46.913" UserId="8826" Comment="edited body" Text="OK, I have figured out this problem.&#xD;&#xA;&#xD;&#xA;For the texture coordinates, there are two kind of texture coordinates. One is normalized texture coordinates, which is in the range [0, 1]. The other is texel space, which is in the range [0, size], where size is the size of the texture. For texelFetch(), the texel space is used.&#xD;&#xA;&#xD;&#xA;For `lod`, it means the level of detail in the mipmap. We can simply use 0 for the base level (the original size).&#xD;&#xA;&#xD;&#xA;Thus, an example of using `texelFetch()` should be:&#xD;&#xA;&#xD;&#xA;    vec4 texelValue= texelFetch(texture2D, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="20013" PostHistoryTypeId="8" PostId="7691" RevisionGUID="7bbd8aa6-3df6-4a69-8ac4-14adcdb5752d" CreationDate="2018-06-05T14:58:52.740" UserId="8826" Comment="Rollback to [aa06abe5-32d1-499d-af0f-4c4ffcccc10f]" Text="OK, I have figured out this problem.&#xD;&#xA;&#xD;&#xA;For the texture coordinates, there are two kind of texture coordinates. One is normalized texture coordinates, which is in the range [0, 1]. The other is texel space, which is in the range [0, size), where size is the size of the texture. For texelFetch(), the texel space is used.&#xD;&#xA;&#xD;&#xA;For `lod`, it means the level of detail in the mipmap. We can simply use 0 for the base level (the original size).&#xD;&#xA;&#xD;&#xA;Thus, an example of using `texelFetch()` should be:&#xD;&#xA;&#xD;&#xA;    vec4 texelValue= texelFetch(texture2D, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="20014" PostHistoryTypeId="8" PostId="7691" RevisionGUID="afd5cc7c-11cb-4295-b1c4-f7ce2ed09f2c" CreationDate="2018-06-05T14:59:05.213" UserId="8826" Comment="Rollback to [7d89b5d7-eace-482f-b8db-cdd3a754215c]" Text="OK, I have figured out this problem.&#xD;&#xA;&#xD;&#xA;For the texture coordinates, there are two kind of texture coordinates. One is normalized texture coordinates, which is in the range [0, 1]. The other is texel space, which is in the range [0, size], where size is the size of the texture. For texelFetch(), the texel space is used.&#xD;&#xA;&#xD;&#xA;For `lod`, it means the level of detail in the mipmap. We can simply use 0 for the base level (the original size).&#xD;&#xA;&#xD;&#xA;Thus, an example of using `texelFetch()` should be:&#xD;&#xA;&#xD;&#xA;    vec4 texelValue= texelFetch(texture2D, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="20015" PostHistoryTypeId="8" PostId="7691" RevisionGUID="72cccf42-d41b-451b-b772-85bcfe402b80" CreationDate="2018-06-05T15:06:35.423" UserId="8826" Comment="Rollback to [aa06abe5-32d1-499d-af0f-4c4ffcccc10f]" Text="OK, I have figured out this problem.&#xD;&#xA;&#xD;&#xA;For the texture coordinates, there are two kind of texture coordinates. One is normalized texture coordinates, which is in the range [0, 1]. The other is texel space, which is in the range [0, size), where size is the size of the texture. For texelFetch(), the texel space is used.&#xD;&#xA;&#xD;&#xA;For `lod`, it means the level of detail in the mipmap. We can simply use 0 for the base level (the original size).&#xD;&#xA;&#xD;&#xA;Thus, an example of using `texelFetch()` should be:&#xD;&#xA;&#xD;&#xA;    vec4 texelValue= texelFetch(texture2D, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="20016" PostHistoryTypeId="2" PostId="7693" RevisionGUID="eb354f49-9ca5-413d-b890-4cb2333fd0cb" CreationDate="2018-06-05T19:42:45.167" UserId="38" Text="3D graphics are not images they are instructions for images. Now the formats that export data beween systems work on lowest common denominator. Geometry is fine, but any effects on top of geometry would require you to agree on a set of instructions to implement. (no such reffort has been made for npr rendering lines).&#xD;&#xA;&#xD;&#xA;The lines are not really part of the model that has been exported trough the gltf pipeline. Simply because the line rendering is a special feature of the sketchup system. There is no generic format that support those, since they need to be generated frame by frame. And there is quite possibly a infinite number of such features that could be implemented, none of these are part of the generally accepted set of things to export.&#xD;&#xA;&#xD;&#xA;Most likely your out of luck the engine in question simply has most likely no way to do this. So there is no solution for your problem.&#xD;&#xA;&#xD;&#xA;PS: This is why it is called an export not save. Although many applications have gone so far as to call even partial implementations save. But you can not just expect all things to go from application to application, especially in 3D" ContentLicense="CC BY-SA 4.0" />
  <row Id="20017" PostHistoryTypeId="5" PostId="7693" RevisionGUID="fc80a53b-a9d8-493c-88f0-ca59c9c9ac40" CreationDate="2018-06-05T19:47:48.483" UserId="38" Comment="added 64 characters in body" Text="3D graphics are not images they are instructions for images. Now the formats that export data beween systems work on lowest common denominator. Geometry is fine, but any effects on top of geometry would require you to agree on a set of instructions to implement. (no such reffort has been made for npr rendering lines).&#xD;&#xA;&#xD;&#xA;The lines are not really part of the model that has been exported trough the gltf pipeline. Simply because the line rendering is a special feature of the sketchup system. There is no generic format that support those, since they need to be generated frame by frame. And there is &#xD;&#xA;quite possibly a infinite number of such features that could be implemented, none of these are part of the generally accepted set of things to export.&#xD;&#xA;&#xD;&#xA;Most likely your out of luck the engine in question simply has no way to do this. So there is no solution for your problem. STL is a even more rudimentary format it only has triangles nothing else.&#xD;&#xA;&#xD;&#xA;PS: This is why it is called an export not save. Although many applications have gone so far as to call even partial implementations save. But you can not just expect all things to go from application to application, especially in 3D" ContentLicense="CC BY-SA 4.0" />
  <row Id="20018" PostHistoryTypeId="50" PostId="6373" RevisionGUID="b8ce9e05-f01d-45a3-b998-2f7176cdb28c" CreationDate="2018-06-06T03:45:35.807" UserId="-1" />
  <row Id="20019" PostHistoryTypeId="2" PostId="7694" RevisionGUID="b7d4159a-e6c8-4ca0-bbe4-88784eb2a09c" CreationDate="2018-06-06T04:23:28.783" UserId="8660" Text="I'm currently trying to create an amateur game engine, and I often run into very basic bugs (eg I change the node hierarchy code and suddenly nothing is displayed). Some of the methods I will use include to track down these bugs include:&#xD;&#xA;&#xD;&#xA;* Use my IDE's debugger and lots of `printf` calls to look at what's in memory.&#xD;&#xA;&#xD;&#xA;* Make lots of tests with different parameters, placing the camera in different positions, to get a better feel of what the code is doing.&#xD;&#xA;&#xD;&#xA;* Just brute force my way through by re-reading each line of code until I find the one that's misbehaving.&#xD;&#xA;&#xD;&#xA;These methods all seem sluggish and inefficient to me. The problem is, that 3D rendering involves a lot of unintuitive operations with not much to visualize except the final &quot;product&quot;; when I'm running into a bug (especially &quot;nothing is displayed&quot; types of bugs), I often feel like I'm fumbling around blindly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So.&#xD;&#xA;&#xD;&#xA;Let's say you're a developer working on Unity, Godot, or some other 3D engine, and you just changed some steps in your rendering pipeline, and now, for whatever reason, the wireframe renderer displays incoherent results when entity batching is activated. The &quot;wires&quot; are crisscrossing all over the screen instead of representing the edges of the batched entity's triangles.&#xD;&#xA;&#xD;&#xA;How do you track down and fix that bug? Do you have a specific workflow? Do you use some kind of GPU analysis tool? Or do you just fumble around blindly?&#xD;&#xA;&#xD;&#xA;In other words, **what methods, tools and best practices can engine developers** (not engine users) **use to analyze the data and behavior** of their 3D graphics code (not just its performance) to efficiently address defects and bugs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20020" PostHistoryTypeId="1" PostId="7694" RevisionGUID="b7d4159a-e6c8-4ca0-bbe4-88784eb2a09c" CreationDate="2018-06-06T04:23:28.783" UserId="8660" Text="How do graphic engine developers debug their 3D graphics code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20021" PostHistoryTypeId="3" PostId="7694" RevisionGUID="b7d4159a-e6c8-4ca0-bbe4-88784eb2a09c" CreationDate="2018-06-06T04:23:28.783" UserId="8660" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20022" PostHistoryTypeId="2" PostId="7695" RevisionGUID="1113c20b-26fd-4811-b62b-6931d37d6c2e" CreationDate="2018-06-06T06:11:15.680" UserId="5066" Text="I usually prefer [RenderDoc][1] to debug a frame. Gives you enough information on particular frame was rendered right from Vertex to Pixel. There are other equally useful tools available like [Nvidia Nsight][2]&#xD;&#xA;&#xD;&#xA;Finally, there is always color coding which can be useful when debugging shaders visually. Decomposing shader outputs into separate colors can be of help too. Not sure though if your case requires this. &#xD;&#xA;&#xD;&#xA;Hope this helps. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://renderdoc.org/&#xD;&#xA;  [2]: http://www.nvidia.com/object/nsight.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="20026" PostHistoryTypeId="2" PostId="7697" RevisionGUID="af8f100a-006c-48cd-a31a-1a44e817e958" CreationDate="2018-06-06T13:59:59.287" UserId="6041" Text="How is the solid angle subtended by a pixel calculated?&#xD;&#xA;both in perspective and fish eye lens.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20027" PostHistoryTypeId="1" PostId="7697" RevisionGUID="af8f100a-006c-48cd-a31a-1a44e817e958" CreationDate="2018-06-06T13:59:59.287" UserId="6041" Text="How to calculate solid angle subtended by a pixel?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20028" PostHistoryTypeId="3" PostId="7697" RevisionGUID="af8f100a-006c-48cd-a31a-1a44e817e958" CreationDate="2018-06-06T13:59:59.287" UserId="6041" Text="|raytracing|pathtracing|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20029" PostHistoryTypeId="50" PostId="6218" RevisionGUID="e8af6b61-6f95-46e8-983d-0ec7a7abadd7" CreationDate="2018-06-06T16:50:43.070" UserId="-1" />
  <row Id="20030" PostHistoryTypeId="2" PostId="7698" RevisionGUID="fd37e25b-9f71-4f87-baf8-751fb815628b" CreationDate="2018-06-06T21:45:06.157" UserId="8841" Text="I have been working with a [file from the USGS][1] that is a heightmap of the Moon. I resized it to 65536 x 32768 px for use as a displacement map in Blender, and turned it into tiles. Then I created tiles from the original image and noticed that they were about a fifth of the file size of the ones from the resized image, even though they have twice the pixels. Image Magick had remapped the image using many tones of gray that weren't present in the original. Presumably this is why the files are now so much bigger.&#xD;&#xA;&#xD;&#xA;Original histogram:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Resized histogram:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Is there any way I can resize this image without the process creating new gray tones?&#xD;&#xA;  [1]: https://astrogeology.usgs.gov/search/map/Moon/LRO/LOLA/Lunar_LRO_LOLA_Global_LDEM_118m_Mar2014&#xD;&#xA;  [2]: https://i.stack.imgur.com/pkN30.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/eYqMu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20031" PostHistoryTypeId="1" PostId="7698" RevisionGUID="fd37e25b-9f71-4f87-baf8-751fb815628b" CreationDate="2018-06-06T21:45:06.157" UserId="8841" Text="Is there a way to resize an image without creating new colors in the output image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20032" PostHistoryTypeId="3" PostId="7698" RevisionGUID="fd37e25b-9f71-4f87-baf8-751fb815628b" CreationDate="2018-06-06T21:45:06.157" UserId="8841" Text="|color-management|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20033" PostHistoryTypeId="2" PostId="7699" RevisionGUID="f5a2dd11-33a6-4d87-9a8f-88190da1ff37" CreationDate="2018-06-06T22:31:20.360" UserId="8796" Text="I'm programming mostly in OpenGL. In this case, the very first thing I do is setting up [KHR_debug][1] extension. It provides a way to subscribe to messages generated by GL drivers - from errors to warnings to detailed information about what the driver is doing. Especially open source Linux drivers (Mesa) generate lots of useful messages.&#xA;&#xA;When it comes to tools, my first choice is usually ApiTrace. It allows you record a trace of all rendering API calls and then replay it and inspect state at any point in time (this includes contents of buffers, render targets, etc.). It also allows you to share a trace with other people, which is useful when working in a team. Then, there are other tools such as RenderDoc, NVIDIA Tegra Graphics Debugger, Xcode's graphics debugger and some others. Whichever you chose, it will improve your work a lot.&#xA;&#xA;Another thing is testing. One thing is building a collection of simple scenes excercising single feature of the engine (such as different material settings, different animation techniques, etc.).&#xA;When a bug is introduced into the codebase, this helps debugging it (since you have simple to analyse test cases readily available) and verifying that a fix doesn't accidentally break something else. I guess it's quite common thing to do; Unity3D developers do it, for example.&#xA;&#xA;You could extend this and automate it by creating test harness, which would build and run all test on regular basis, and verify that no regressions happened. If you have lots of test scenarios, this might be feasible, although obviously requires additional investments into infrastructure. &#xA;&#xA;Then there are more &quot;standard&quot; unit tests. One area I've applied them is node-based material system, which can target different rendering techniques (forward, deferred, whatever) and APIs. I approached it by writing unit tests which generate shader code from material and other settings, compiler it and issues a simple draw calls with given inputs (pixel shader inputs). Outputs are written to a render target and fetched for comparison with expected values. IMHO this is a nice  thing to do when you have complex material system, esp. with shader code generation.&#xA;&#xA;Finally, more &quot;traditional&quot; approaches can be applied to areas which can be separated from rendering. Things like spatial data structures, asset loading and similar can be unit/integration tested, as applicable in specific case.&#xA;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_debug.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="20034" PostHistoryTypeId="50" PostId="5697" RevisionGUID="4aa58c1f-50d7-4986-a2ae-a8b73323c662" CreationDate="2018-06-06T22:55:23.803" UserId="-1" />
  <row Id="20035" PostHistoryTypeId="2" PostId="7700" RevisionGUID="390712f1-f7de-4ecc-b970-8fc25d4f53bc" CreationDate="2018-06-07T01:58:43.927" UserId="5717" Text="A nearest-neighbor resize will do what you ask but I am not certain it will give you much smaller tiles.&#xD;&#xA;&#xD;&#xA;It is quite likely that the tiles made from the original image are smaller simply because they have less high frequency content and thus compress far better.&#xD;&#xA;&#xD;&#xA;You can look at it the other way around: there are more terrain features in the tiles of the resized image so it takes more space to store them. That's a very gross simplification of the truth, of course. And it assumes a reasonably efficient compression algorithm." ContentLicense="CC BY-SA 4.0" />
  <row Id="20036" PostHistoryTypeId="2" PostId="7701" RevisionGUID="3eea64aa-cc76-48b4-85ca-a2596c5fb1fc" CreationDate="2018-06-07T03:18:03.480" UserId="3003" Text="I work mainly on macOS where the OpenGL tools are almost non-existent. (I'm starting to get into Metal where the tools are better.) So I feel your pain. &#xD;&#xA;&#xD;&#xA;The first thing I do is make frequent, small commits of my code to source control. This isn't always possible, but usually it is. If that could disrupt others, work on a branch. That way, if something goes horribly wrong, I can do a quick diff of the current code against HEAD or trunk, and isolate the problem to only the code in the diffs. &#xD;&#xA;&#xD;&#xA;The next thing I do is try to analyze what the problem is. In your example, where geometry that was previously working is suddenly drawing the wrong shapes, I'd think about the situations that can cause that:&#xD;&#xA;&#xD;&#xA; 1. Sending a bogus pointer to `glBufferData()`&#xD;&#xA; 2. Starting on the wrong byte of my buffer by setting an attribute pointer/offset incorrectly&#xD;&#xA;&#xD;&#xA;There are numerous causes of general symptoms like the dreaded black screen. There are a number of techniques that are the graphics equivalent of `printf()`. I start breaking down what's working and what's not. I start with really broad strokes. Is my drawing going to the right FBO? Set the clear color of the FBO to something garish like RGB=(1, 0.5, 0) or (0, 1, 1) and see if the screen turns orange or magenta. You might pick a different debug color for each FBO you normally use so you can tell at a glance which is going to screen on a given render. If that works, I check things like clipping planes - have I clipped all the geometry out? Check lighting - do I have lights on? Am I sending the correct lighting info to the shaders? Are textures correct? It can help to have some test textures with things like grids on them, or if you're dealing with cube maps, textures with face names on them. If you have shader issues, you can do things like simply output the texture coordinates as red and green (and blue if it's a 3D texture) at each point to make sure they're valid. Same with normals - normalize them and output the `x`, `y`, and `z` in the `r`, `g`, and `b` channels.&#xD;&#xA;&#xD;&#xA;As you do more of this you'll learn tricks like these for displaying the data and verifying your assumptions. Being able to roll back quickly and easily is enormously helpful. And of course, don't forget about `glGetError()`. The small numbers of errors it returns is frustrating, but it can often point you in the direction of where a problem is.&#xD;&#xA;&#xD;&#xA;If you can get a tool that shows you what's different from the default OpenGL state, it can also direct where to spend your effort. On macOS there's OpenGL Profiler. You can set a breakpoint on any OpenGL function and examine the entire state machine. It will highlight differences from the defaults, or differences from the last time it stopped, or both." ContentLicense="CC BY-SA 4.0" />
  <row Id="20041" PostHistoryTypeId="5" PostId="7699" RevisionGUID="85ad5a96-5ce0-4208-a70e-fdc81b03b2be" CreationDate="2018-06-07T21:37:49.843" UserId="8796" Comment="added 191 characters in body" Text="I'm programming mostly in OpenGL. In this case, the very first thing I do is setting up [KHR_debug][1] extension. It provides a way to subscribe to messages generated by GL drivers - from errors to warnings to detailed information about what the driver is doing. Especially open source Linux drivers (Mesa) generate lots of useful messages.&#xD;&#xA;&#xD;&#xA;When it comes to tools, my first choice is usually ApiTrace. It allows you record a trace of all rendering API calls and then replay it and inspect state at any point in time (this includes contents of buffers, render targets, etc.). It also allows you to share a trace with other people, which is useful when working in a team. Then, there are other tools such as RenderDoc, NVIDIA Tegra Graphics Debugger, Xcode's graphics debugger and some others. Whichever you chose, it will improve your work a lot.&#xD;&#xA;&#xD;&#xA;Another thing is testing. One thing is building a collection of simple scenes excercising single feature of the engine (such as different material settings, different animation techniques, etc.).&#xD;&#xA;When a bug is introduced into the codebase, this helps debugging it (since you have simple to analyse test cases readily available) and verifying that a fix doesn't accidentally break something else. I guess it's quite common thing to do; Unity3D developers do it, for example.&#xD;&#xA;&#xD;&#xA;You could extend this and automate it by creating test harness, which would build and run all test on regular basis, and verify that no regressions happened. If you have lots of test scenarios, this might be feasible, although obviously requires additional investments into infrastructure. &#xD;&#xA;&#xD;&#xA;Then there are more &quot;standard&quot; unit tests. One area I've applied them is node-based material system, which can target different rendering techniques (forward, deferred, whatever) and APIs. I approached it by writing unit tests which generate shader code from material and other settings, compiler it and issues a simple draw calls with given inputs (pixel shader inputs). Outputs are written to a render target and fetched for comparison with expected values. IMHO this is a nice  thing to do when you have complex material system, esp. with shader code generation.&#xD;&#xA;&#xD;&#xA;Finally, more &quot;traditional&quot; approaches can be applied to areas which can be separated from rendering. Things like spatial data structures, asset loading and similar can be unit/integration tested, as applicable in specific case.&#xD;&#xA;&#xD;&#xA;**Edit:** [Here's a post][2] from Unity3D developer describing how they test graphics code.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_debug.txt&#xD;&#xA;  [2]: https://aras-p.info/blog/2011/06/17/testing-graphics-code-4-years-later/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20043" PostHistoryTypeId="2" PostId="7703" RevisionGUID="5d845d2e-c696-4085-853d-ff7bc9e4d91d" CreationDate="2018-06-08T13:50:10.783" UserId="8709" Text="NB please : executable uses cases are available at the end of this question.&#xD;&#xA;&#xD;&#xA;I want to draw the bottom face of a cube. To do that, I interpolate between the 4 vertices of this face. I use two kinds of interpolation :&#xD;&#xA;&#xD;&#xA;1. Linear&#xD;&#xA;&#xD;&#xA;2. Cosine&#xD;&#xA;&#xD;&#xA;# Results&#xD;&#xA;&#xD;&#xA;Each point of the following both pictures are interpolated between the 4 vertices of the bottom face (except the 8 vertices of my cube).&#xD;&#xA;&#xD;&#xA;## With linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;## With cosine interpolation&#xD;&#xA;&#xD;&#xA;Error. As you can see, there is some weird problem : face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# How do I interpolate between 4 points ?&#xD;&#xA;&#xD;&#xA;I test all the combinations of interpolation's weights and, if the sum of the weights equals 1, I draw the resulting point.&#xD;&#xA;&#xD;&#xA;In other words : the definition of the interpolation between 4 points is : `P = aA + bB + cC + dD`. `a + b + c + d` must equals 1 to draw `P`, otherwise it's not drawn. `(a;b;c;d) \in [0;1]^4` by the way.&#xD;&#xA;&#xD;&#xA;A concrete example is (step = 1) :&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 1d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 1d` is NOT drawn&#xD;&#xA;&#xD;&#xA;etc. (&quot;I test all the combinations&quot;). (Last is : `P = 1a + 1b + 1c + 1d`, which is not drawn).&#xD;&#xA;&#xD;&#xA;To test all these combinations, I iterates on the weights, with a step, using recursion.&#xD;&#xA;&#xD;&#xA;I know this method is not very good (a lot of consumption of CPU and RAM), and there are `P` duplicates. But this problem is (1) secondary and (2) out of the range of this StackOverflow question.&#xD;&#xA;&#xD;&#xA;## Case of the linear interpolation&#xD;&#xA;&#xD;&#xA;The above definition doesn't change : `P = aA + bB + cC + dD`.&#xD;&#xA;&#xD;&#xA;## Case of the cosine interpolation&#xD;&#xA;&#xD;&#xA;The above definition does change : `P = aA + bB + cC + dD` becomes `P = a'A + b'B + c'C + d'D`, with : `a' = 0.5(1 - cos(a * \pi))` and the idea is the same for the three other weights.&#xD;&#xA;&#xD;&#xA;This new definition is not random, I could explain how I found it, but it's out of the range of this topic (in résumé : a simple remap of the cosine function).&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;Why does it works well with the linear interpolation, and not the cosine one ? Indeed, the cosine face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;# By the way : interpolations between two points work well&#xD;&#xA;&#xD;&#xA;Linear and cosine interpolations both work very well when used between two points, as you can see below.&#xD;&#xA;&#xD;&#xA;## Linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;## Cosine interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;# Implementation and Executable&#xD;&#xA;&#xD;&#xA;I wrote the program in Scala. First I show you the functions, then two use cases you can execute along with the given functions.&#xD;&#xA;&#xD;&#xA;## Tests all the combinations of interpolations between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def computeAllPossibleInterpolatedPoints(step : Double, points : Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Seq[Double]] = {&#xD;&#xA;      var returned_object : Seq[Seq[Double]] = Seq.empty[Seq[Double]]&#xD;&#xA;      recursiveInterpolation(0, Seq.empty[Double])&#xD;&#xA;  &#xD;&#xA;      def recursiveInterpolation(current_weight_id : Int, building_weights : Seq[Double]) : Unit = {&#xD;&#xA;  &#xD;&#xA;        (.0 to 1.0 by step).foreach(current_step =&gt; {&#xD;&#xA;          if (current_weight_id &lt; points.size - 1) {&#xD;&#xA;            recursiveInterpolation(current_weight_id + 1, building_weights :+ current_step)&#xD;&#xA;          } else {&#xD;&#xA;            val found_solution = building_weights :+ current_step&#xD;&#xA;            if(BigDecimal(found_solution.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble == 1.0) {&#xD;&#xA;              returned_object = returned_object :+ interpolation(found_solution, points, transform)&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        })&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      returned_object&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolates between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def interpolation(weights: Seq[Double], points: Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Double] = {&#xD;&#xA;      if(BigDecimal(weights.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble != 1) {&#xD;&#xA;        println(&quot;ERROR : `SUM(weights) != 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;      if(weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &lt; 0)&#xD;&#xA;        ||&#xD;&#xA;        weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &gt; 1)) {&#xD;&#xA;        println(&quot;ERROR : `EXISTS(weight) / weight &lt; -1 OR weight &gt; 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      weights.map(transform).zip(points).map(&#xD;&#xA;        weight_point =&gt; weight_point._2.map(coordinate =&gt; weight_point._1 * coordinate)&#xD;&#xA;      ).reduce((point_a : Seq[Double], point_b : Seq[Double]) =&gt; point_a.zip(point_b).map(coordinate_points =&gt; coordinate_points._1 + coordinate_points._2))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolation functions&#xD;&#xA;&#xD;&#xA;    def linear(weight : Double) : Double = {&#xD;&#xA;      weight&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    def cosine(weight : Double) : Double = {&#xD;&#xA;      (1 - Math.cos(weight * Math.PI)) * 0.5&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Two use cases : between 2 points, each made of 2 coordinates (first use case : linear interpolation, second use case : cosine interpolation)&#xD;&#xA;&#xD;&#xA;Note that you can add 2 new points to each of the following functions, to interpolate a face instead of a segment (for now, the below code indeed interpolates points of a segment).&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.linear).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.cosine).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R5ovV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2B5SW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/oq5As.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/rZiyL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20044" PostHistoryTypeId="1" PostId="7703" RevisionGUID="5d845d2e-c696-4085-853d-ff7bc9e4d91d" CreationDate="2018-06-08T13:50:10.783" UserId="8709" Text="Why my cosine interpolation of a cube's face doesn't work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20045" PostHistoryTypeId="3" PostId="7703" RevisionGUID="5d845d2e-c696-4085-853d-ff7bc9e4d91d" CreationDate="2018-06-08T13:50:10.783" UserId="8709" Text="|rendering|3d|interpolation|drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20046" PostHistoryTypeId="5" PostId="7703" RevisionGUID="31df27a9-7415-41f2-a960-b3eab63d8c13" CreationDate="2018-06-08T13:56:55.247" UserId="8709" Comment="added 181 characters in body" Text="NB please : executable use cases are available at the end of this question. I begin this question by showing you the problems of my program, then I explain how the latter works, and finally I end with these both executable uses cases.&#xD;&#xA;&#xD;&#xA;# What I want to do&#xD;&#xA;&#xD;&#xA;I want to draw the bottom face of a cube. To do that, I interpolate between the 4 vertices of this face. I use two kinds of interpolation :&#xD;&#xA;&#xD;&#xA;1. Linear&#xD;&#xA;&#xD;&#xA;2. Cosine&#xD;&#xA;&#xD;&#xA;*I know it's typically the aim of GPUs, but I wanted to implement it myself to learn and try the &quot;deep&quot; mechanisms of 3D rendering.*&#xD;&#xA;&#xD;&#xA;# Results&#xD;&#xA;&#xD;&#xA;Each point of the following both pictures are interpolated between the 4 vertices of the bottom face (except the 8 vertices of my cube).&#xD;&#xA;&#xD;&#xA;## With linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;## With cosine interpolation&#xD;&#xA;&#xD;&#xA;Error. As you can see, there is some weird problem : face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# How do I interpolate between 4 points ?&#xD;&#xA;&#xD;&#xA;I test all the combinations of interpolation's weights and, if the sum of the weights equals 1, I draw the resulting point. *I know this method is not very good (a lot of consumption of CPU and RAM), and there are `P` duplicates. But this problem is (1) secondary and (2) out of the range of this StackOverflow question.*&#xD;&#xA;&#xD;&#xA;In other words : the definition of the interpolation between 4 points is : `P = aA + bB + cC + dD`. `a + b + c + d` must equals 1 to draw `P`, otherwise it's not drawn. `(a;b;c;d) \in [0;1]^4` by the way.&#xD;&#xA;&#xD;&#xA;A concrete example is (step = 1) :&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 1d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 1d` is NOT drawn&#xD;&#xA;&#xD;&#xA;etc. (&quot;I test all the combinations&quot;). (Last is : `P = 1a + 1b + 1c + 1d`, which is not drawn).&#xD;&#xA;&#xD;&#xA;To test all these combinations, I iterates on the weights, with a step, using recursion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Case of the linear interpolation&#xD;&#xA;&#xD;&#xA;The above definition doesn't change : `P = aA + bB + cC + dD`.&#xD;&#xA;&#xD;&#xA;## Case of the cosine interpolation&#xD;&#xA;&#xD;&#xA;The above definition does change : `P = aA + bB + cC + dD` becomes `P = a'A + b'B + c'C + d'D`, with : `a' = 0.5(1 - cos(a * \pi))` and the idea is the same for the three other weights.&#xD;&#xA;&#xD;&#xA;*This new definition is not random, I could explain how I found it, but it's out of the range of this topic (in résumé : a simple remap of the cosine function).*&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;Why does it works well with the linear interpolation, and not the cosine one ? Indeed, the cosine face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;# By the way : interpolations between two points work well&#xD;&#xA;&#xD;&#xA;Linear and cosine interpolations both work very well when used between two points, as you can see below.&#xD;&#xA;&#xD;&#xA;## Linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;## Cosine interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;# Implementation and Executable&#xD;&#xA;&#xD;&#xA;I wrote the program in Scala. First I show you the functions, then two use cases you can execute along with the given functions.&#xD;&#xA;&#xD;&#xA;## Tests all the combinations of interpolations between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def computeAllPossibleInterpolatedPoints(step : Double, points : Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Seq[Double]] = {&#xD;&#xA;      var returned_object : Seq[Seq[Double]] = Seq.empty[Seq[Double]]&#xD;&#xA;      recursiveInterpolation(0, Seq.empty[Double])&#xD;&#xA;  &#xD;&#xA;      def recursiveInterpolation(current_weight_id : Int, building_weights : Seq[Double]) : Unit = {&#xD;&#xA;  &#xD;&#xA;        (.0 to 1.0 by step).foreach(current_step =&gt; {&#xD;&#xA;          if (current_weight_id &lt; points.size - 1) {&#xD;&#xA;            recursiveInterpolation(current_weight_id + 1, building_weights :+ current_step)&#xD;&#xA;          } else {&#xD;&#xA;            val found_solution = building_weights :+ current_step&#xD;&#xA;            if(BigDecimal(found_solution.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble == 1.0) {&#xD;&#xA;              returned_object = returned_object :+ interpolation(found_solution, points, transform)&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        })&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      returned_object&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolates between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def interpolation(weights: Seq[Double], points: Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Double] = {&#xD;&#xA;      if(BigDecimal(weights.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble != 1) {&#xD;&#xA;        println(&quot;ERROR : `SUM(weights) != 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;      if(weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &lt; 0)&#xD;&#xA;        ||&#xD;&#xA;        weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &gt; 1)) {&#xD;&#xA;        println(&quot;ERROR : `EXISTS(weight) / weight &lt; -1 OR weight &gt; 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      weights.map(transform).zip(points).map(&#xD;&#xA;        weight_point =&gt; weight_point._2.map(coordinate =&gt; weight_point._1 * coordinate)&#xD;&#xA;      ).reduce((point_a : Seq[Double], point_b : Seq[Double]) =&gt; point_a.zip(point_b).map(coordinate_points =&gt; coordinate_points._1 + coordinate_points._2))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolation functions&#xD;&#xA;&#xD;&#xA;    def linear(weight : Double) : Double = {&#xD;&#xA;      weight&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    def cosine(weight : Double) : Double = {&#xD;&#xA;      (1 - Math.cos(weight * Math.PI)) * 0.5&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Two use cases : between 2 points, each made of 2 coordinates (first use case : linear interpolation, second use case : cosine interpolation)&#xD;&#xA;&#xD;&#xA;Note that you can add 2 new points to each of the following functions, to interpolate a face instead of a segment (for now, the below code indeed interpolates points of a segment).&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.linear).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.cosine).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R5ovV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2B5SW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/oq5As.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/rZiyL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20047" PostHistoryTypeId="5" PostId="7703" RevisionGUID="9aa8a27f-ab96-4b7c-8e30-e2025c0eb8b0" CreationDate="2018-06-08T14:02:50.327" UserId="8709" Comment="deleted 1 character in body" Text="**NB please :** executable use cases are available at the end of this question. I begin this question by showing you the problems of my program, then I explain how the latter works, and finally I end up with these both executable use cases.&#xD;&#xA;&#xD;&#xA;# What I want to do&#xD;&#xA;&#xD;&#xA;I want to draw the bottom face of a cube. To do that, I interpolate between the 4 vertices of this face. I use two kinds of interpolation :&#xD;&#xA;&#xD;&#xA;1. Linear&#xD;&#xA;&#xD;&#xA;2. Cosine&#xD;&#xA;&#xD;&#xA;*I know it's typically the aim of GPUs, but I wanted to implement it myself to learn and try the &quot;deep&quot; mechanisms of 3D rendering.*&#xD;&#xA;&#xD;&#xA;# Results&#xD;&#xA;&#xD;&#xA;Each point of the following both pictures are interpolated between the 4 vertices of the bottom face (except the 8 vertices of my cube).&#xD;&#xA;&#xD;&#xA;## With linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;## With cosine interpolation&#xD;&#xA;&#xD;&#xA;Error. As you can see, there is some weird problem : face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# How do I interpolate between 4 points ?&#xD;&#xA;&#xD;&#xA;I test all the combinations of interpolation's weights and, if the sum of the weights equals 1, I draw the resulting point. *I know this method is not very good (a lot of consumption of CPU and RAM), and there are `P` duplicates. But this problem is (1) secondary and (2) out of the range of this StackOverflow question.*&#xD;&#xA;&#xD;&#xA;In other words : the definition of the interpolation between 4 points is : `P = aA + bB + cC + dD`. `a + b + c + d` must equals 1 to draw `P`, otherwise it's not drawn. `(a;b;c;d) \in [0;1]^4` by the way.&#xD;&#xA;&#xD;&#xA;A concrete example is (step = 1) :&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 1d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 1d` is NOT drawn&#xD;&#xA;&#xD;&#xA;etc. (&quot;I test all the combinations&quot;). (Last is : `P = 1a + 1b + 1c + 1d`, which is not drawn).&#xD;&#xA;&#xD;&#xA;To test all these combinations, I iterates on the weights, with a step, using recursion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Case of the linear interpolation&#xD;&#xA;&#xD;&#xA;The above definition doesn't change : `P = aA + bB + cC + dD`.&#xD;&#xA;&#xD;&#xA;## Case of the cosine interpolation&#xD;&#xA;&#xD;&#xA;The above definition does change : `P = aA + bB + cC + dD` becomes `P = a'A + b'B + c'C + d'D`, with : `a' = 0.5(1 - cos(a * \pi))` and the idea is the same for the three other weights.&#xD;&#xA;&#xD;&#xA;*This new definition is not random, I could explain how I found it, but it's out of the range of this topic (in résumé : a simple remap of the cosine function).*&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;Why does it works well with the linear interpolation, and not the cosine one ? Indeed, the cosine face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;# By the way : interpolations between two points work well&#xD;&#xA;&#xD;&#xA;Linear and cosine interpolations both work very well when used between two points, as you can see below.&#xD;&#xA;&#xD;&#xA;## Linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;## Cosine interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;# Implementation and Executable&#xD;&#xA;&#xD;&#xA;I wrote the program in Scala. First I show you the functions, then two use cases you can execute along with the given functions.&#xD;&#xA;&#xD;&#xA;## Tests all the combinations of interpolations between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def computeAllPossibleInterpolatedPoints(step : Double, points : Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Seq[Double]] = {&#xD;&#xA;      var returned_object : Seq[Seq[Double]] = Seq.empty[Seq[Double]]&#xD;&#xA;      recursiveInterpolation(0, Seq.empty[Double])&#xD;&#xA;  &#xD;&#xA;      def recursiveInterpolation(current_weight_id : Int, building_weights : Seq[Double]) : Unit = {&#xD;&#xA;  &#xD;&#xA;        (.0 to 1.0 by step).foreach(current_step =&gt; {&#xD;&#xA;          if (current_weight_id &lt; points.size - 1) {&#xD;&#xA;            recursiveInterpolation(current_weight_id + 1, building_weights :+ current_step)&#xD;&#xA;          } else {&#xD;&#xA;            val found_solution = building_weights :+ current_step&#xD;&#xA;            if(BigDecimal(found_solution.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble == 1.0) {&#xD;&#xA;              returned_object = returned_object :+ interpolation(found_solution, points, transform)&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        })&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      returned_object&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolates between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def interpolation(weights: Seq[Double], points: Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Double] = {&#xD;&#xA;      if(BigDecimal(weights.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble != 1) {&#xD;&#xA;        println(&quot;ERROR : `SUM(weights) != 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;      if(weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &lt; 0)&#xD;&#xA;        ||&#xD;&#xA;        weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &gt; 1)) {&#xD;&#xA;        println(&quot;ERROR : `EXISTS(weight) / weight &lt; -1 OR weight &gt; 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      weights.map(transform).zip(points).map(&#xD;&#xA;        weight_point =&gt; weight_point._2.map(coordinate =&gt; weight_point._1 * coordinate)&#xD;&#xA;      ).reduce((point_a : Seq[Double], point_b : Seq[Double]) =&gt; point_a.zip(point_b).map(coordinate_points =&gt; coordinate_points._1 + coordinate_points._2))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolation functions&#xD;&#xA;&#xD;&#xA;    def linear(weight : Double) : Double = {&#xD;&#xA;      weight&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    def cosine(weight : Double) : Double = {&#xD;&#xA;      (1 - Math.cos(weight * Math.PI)) * 0.5&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Two use cases : between 2 points, each made of 2 coordinates (first use case : linear interpolation, second use case : cosine interpolation)&#xD;&#xA;&#xD;&#xA;Note that you can add 2 new points to each of the following functions, to interpolate a face instead of a segment (for now, the below code indeed interpolates points of a segment).&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.linear).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.cosine).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R5ovV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2B5SW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/oq5As.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/rZiyL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20048" PostHistoryTypeId="5" PostId="7703" RevisionGUID="705b1e37-3b36-412c-b8e7-63222720321b" CreationDate="2018-06-08T16:29:21.603" UserId="8709" Comment="added 4 characters in body" Text="**NB please :** executable use cases are available at the end of this question. I begin this question by showing you the problems of my program, then I explain how the latter works, and finally I end up with these both executable use cases.&#xD;&#xA;&#xD;&#xA;# What I want to do&#xD;&#xA;&#xD;&#xA;I want to draw the bottom face of a cube. To do that, I interpolate between the 4 vertices of this face. I use two kinds of interpolation :&#xD;&#xA;&#xD;&#xA;1. Linear&#xD;&#xA;&#xD;&#xA;2. Cosine&#xD;&#xA;&#xD;&#xA;*I know it's typically the aim of GPUs, but I wanted to implement it myself to learn and try the &quot;deep&quot; mechanisms of 3D rendering.*&#xD;&#xA;&#xD;&#xA;# Results&#xD;&#xA;&#xD;&#xA;Each point of the following both pictures are interpolated between the 4 vertices of the bottom face (except the 8 vertices of my cube).&#xD;&#xA;&#xD;&#xA;## With linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;## With cosine interpolation&#xD;&#xA;&#xD;&#xA;Error. As you can see, there is some weird problem : face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# How do I interpolate between 4 points ?&#xD;&#xA;&#xD;&#xA;I test all the combinations of interpolation's weights and, if the sum of the weights equals 1, I draw the resulting point. *I know this method is not very good (a lot of consumption of CPU and RAM), and there are `P` duplicates. But this problem is (1) secondary and (2) out of the range of this StackOverflow question.*&#xD;&#xA;&#xD;&#xA;In other words : the definition of the interpolation between 4 points is : `P = aA + bB + cC + dD`. `a + b + c + d` must equals 1 to draw `P`, otherwise it's not drawn. `(a;b;c;d) \in [0;1]^4` by the way.&#xD;&#xA;&#xD;&#xA;A concrete example is (step = 1) :&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 0d` is NOT drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 0c + 1d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 0d` is drawn&#xD;&#xA;&#xD;&#xA;`P = 0a + 0b + 1c + 1d` is NOT drawn&#xD;&#xA;&#xD;&#xA;etc. (&quot;I test all the combinations&quot;). (Last is : `P = 1a + 1b + 1c + 1d`, which is not drawn).&#xD;&#xA;&#xD;&#xA;To test all these combinations, I iterates on the weights, with a step, using recursion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Case of the linear interpolation&#xD;&#xA;&#xD;&#xA;The above definition doesn't change : `P = aA + bB + cC + dD`.&#xD;&#xA;&#xD;&#xA;## Case of the cosine interpolation&#xD;&#xA;&#xD;&#xA;The above definition does change : `P = aA + bB + cC + dD` becomes `P = a'A + b'B + c'C + d'D`, with : `a' = 0.5(1 - cos(a * \pi))` and the idea is the same for the three other weights.&#xD;&#xA;&#xD;&#xA;*This new definition is not random, I could explain how I found it, but it's out of the range of this topic (in résumé : a simple remap of the cosine function).*&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;Why does it works well with the linear interpolation, and not the cosine one ? Indeed, the cosine face's points are inclined towards left.&#xD;&#xA;&#xD;&#xA;# By the way : interpolations between two points work well&#xD;&#xA;&#xD;&#xA;Linear and cosine interpolations both work very well when used between two points, as you can see below.&#xD;&#xA;&#xD;&#xA;## Linear interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;## Cosine interpolation&#xD;&#xA;&#xD;&#xA;It's OK, no problem.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;# Implementation and Executable&#xD;&#xA;&#xD;&#xA;I wrote the program in Scala. First I show you the functions, then two use cases you can execute along with the given functions.&#xD;&#xA;&#xD;&#xA;## Tests all the combinations of interpolations between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def computeAllPossibleInterpolatedPoints(step : Double, points : Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Seq[Double]] = {&#xD;&#xA;      var returned_object : Seq[Seq[Double]] = Seq.empty[Seq[Double]]&#xD;&#xA;      recursiveInterpolation(0, Seq.empty[Double])&#xD;&#xA;  &#xD;&#xA;      def recursiveInterpolation(current_weight_id : Int, building_weights : Seq[Double]) : Unit = {&#xD;&#xA;  &#xD;&#xA;        (.0 to 1.0 by step).foreach(current_step =&gt; {&#xD;&#xA;          if (current_weight_id &lt; points.size - 1) {&#xD;&#xA;            recursiveInterpolation(current_weight_id + 1, building_weights :+ current_step)&#xD;&#xA;          } else {&#xD;&#xA;            val found_solution = building_weights :+ current_step&#xD;&#xA;            if(BigDecimal(found_solution.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble == 1.0) {&#xD;&#xA;              returned_object = returned_object :+ interpolation(found_solution, points, transform)&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        })&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      returned_object&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolates between `n` points of `k` coordinates&#xD;&#xA;&#xD;&#xA;    def interpolation(weights: Seq[Double], points: Seq[Seq[Double]], transform: (Double) =&gt; Double) : Seq[Double] = {&#xD;&#xA;      if(BigDecimal(weights.sum).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble != 1) {&#xD;&#xA;        println(&quot;ERROR : `SUM(weights) != 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;      if(weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &lt; 0)&#xD;&#xA;        ||&#xD;&#xA;        weights.exists(weight =&gt; BigDecimal(weight).setScale(5, BigDecimal.RoundingMode.HALF_UP).toDouble &gt; 1)) {&#xD;&#xA;        println(&quot;ERROR : `EXISTS(weight) / weight &lt; -1 OR weight &gt; 1`. Returning `null`.&quot;)&#xD;&#xA;        return null&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      weights.map(transform).zip(points).map(&#xD;&#xA;        weight_point =&gt; weight_point._2.map(coordinate =&gt; weight_point._1 * coordinate)&#xD;&#xA;      ).reduce((point_a : Seq[Double], point_b : Seq[Double]) =&gt; point_a.zip(point_b).map(coordinate_points =&gt; coordinate_points._1 + coordinate_points._2))&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Interpolation functions&#xD;&#xA;&#xD;&#xA;    def linear(weight : Double) : Double = {&#xD;&#xA;      weight&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    def cosine(weight : Double) : Double = {&#xD;&#xA;      (1 - Math.cos(weight * Math.PI)) * 0.5&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Two use cases : between 2 points, each made of 2 coordinates (first use case : linear interpolation, second use case : cosine interpolation)&#xD;&#xA;&#xD;&#xA;Note that you can add 2 new points to each of the following functions, to interpolate a face instead of a segment (for now, the below code indeed interpolates points of a segment).&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.linear).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;    val interpolated_points : Seq[Seq[Int]] = interpolator.computeAllPossibleInterpolatedPoints(0.05, Seq(Seq(22, 22), Seq(33, 33)), interpolator.cosine).map(_.map(_.intValue()))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R5ovV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2B5SW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/oq5As.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/rZiyL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20052" PostHistoryTypeId="50" PostId="7513" RevisionGUID="a97423d3-f79f-4315-b46e-8b36131aa261" CreationDate="2018-06-09T12:52:03.963" UserId="-1" />
  <row Id="20054" PostHistoryTypeId="2" PostId="7704" RevisionGUID="79d96ace-9744-4fbf-b18d-8b1a65250bb4" CreationDate="2018-06-10T12:28:41.437" UserId="5098" Text="I was going through the [raytracer in a weekend][1] book by Peter Shirley and the subsequent book [raytracing the next week][2] and I couldn't make out what was the illumination model that was being used here.&#xD;&#xA;&#xD;&#xA;all the previous raytracing samples that I have come across use the Phong shading model in which&#xD;&#xA;&#xD;&#xA; - For a diffuse surface, a shadow ray is generated towards all the light sources and the final color is calculated based on the diffuse color and the non-occluded light intensities&#xD;&#xA; - For reflective materials and dielectrics, reflective and refractive rays are generated which are then recursively projected into the scene&#xD;&#xA;&#xD;&#xA;The method used in the book (very briefly) is as follows (Please do correct me if my understanding is wrong in any way)&#xD;&#xA;&#xD;&#xA; - For diffuse objects, a ray is traced recursively in a random direction biased towards the normal at the hitpoint and the color from the resulting ray is multiplied with the current object's albedo to give the final color&#xD;&#xA; - For reflective and dielectrics, rays are cast using the law of reflection and the Snell's law respectively. &#xD;&#xA; - Lights also scatter rays and also add their emitted parts.&#xD;&#xA;&#xD;&#xA;The major differences I see in this approach are&#xD;&#xA;&#xD;&#xA; - We do not directly sample the light sources.&#xD;&#xA; - Diffuse items also reflect rays (for inter-diffuse reflections)&#xD;&#xA;&#xD;&#xA;What exactly is the illumination model used in this approach? and why does this approach seem so simple and yet produces pretty good results?&#xD;&#xA;&#xD;&#xA;Sorry if I missed something, I am relatively new to raytracing&#xD;&#xA;&#xD;&#xA;  [1]: http://in1weekend.blogspot.com/2016/01/ray-tracing-in-one-weekend.html&#xD;&#xA;  [2]: http://in1weekend.blogspot.com/2016/01/ray-tracing-second-weekend.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="20055" PostHistoryTypeId="1" PostId="7704" RevisionGUID="79d96ace-9744-4fbf-b18d-8b1a65250bb4" CreationDate="2018-06-10T12:28:41.437" UserId="5098" Text="Illumination model used in the &quot;Raytracer in a weekend&quot; series" ContentLicense="CC BY-SA 4.0" />
  <row Id="20056" PostHistoryTypeId="3" PostId="7704" RevisionGUID="79d96ace-9744-4fbf-b18d-8b1a65250bb4" CreationDate="2018-06-10T12:28:41.437" UserId="5098" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20057" PostHistoryTypeId="2" PostId="7705" RevisionGUID="ab27b690-5728-45ff-b6aa-c260f3267fa6" CreationDate="2018-06-10T15:39:11.013" UserId="6046" Text="So I was reading this paper by Lafortune, &quot;Mathematical Models and Monte Carlo algorithms&quot; and in it he writes.&#xD;&#xA;&#xD;&#xA;We have a function or integrand I we want to estimate given as,&#xD;&#xA;&#xD;&#xA;$I = \int f(x) dx$&#xD;&#xA;&#xD;&#xA;We then have a primary estimator for this as,&#xD;&#xA;&#xD;&#xA;$\hat{I_p} = f(\xi)$&#xD;&#xA;&#xD;&#xA;where $\xi$ is a random number generated in the interval of the integrand $I$.&#xD;&#xA;&#xD;&#xA;The secondary estimator is defined as,&#xD;&#xA;&#xD;&#xA;$\hat{I_{sec}} = \frac{1}{N} \sum f(\xi_i)$&#xD;&#xA;&#xD;&#xA;Then there is an explanation that goes to show how the expected value of the secondary estimator is equal to the function/integrand I. i.e,&#xD;&#xA;&#xD;&#xA;$E(\hat{I_{sec}}) = I$&#xD;&#xA;&#xD;&#xA;All fair. The problem comes when he tries to find the variance of this secondary estimator as follows. Im posting a screenshot of the paper here since it's getting a little complex.&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I don't understand how did step 2 follow from step 1 of Equation 3.5 in the variance calculation. Note that he has assumed $PDF = 1$ for now&#xD;&#xA;&#xD;&#xA;I was trying to calculate the variance using a more standard approach and ignoring the multiple integrals. We know the variance of an estimator $\hat{\theta}$ is given as&#xD;&#xA;&#xD;&#xA;$Var(\hat{\theta}) = E[(\hat{\theta} - E(\hat{\theta}))^2]$&#xD;&#xA;&#xD;&#xA;If we apply this to above we get&#xD;&#xA;&#xD;&#xA;$Var(\hat{I_{sec}}) =  E[(\hat{I_{sec}} - E(\hat{I_{sec}}))^2] $&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[(\hat{I_{sec}} - I)^2]$&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[(\hat{I_{sec}})^2 - 2* I *(\hat{I_{sec}}) + I^2 ] $&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[(\hat{I_{sec}})^2] - 2* I *E[\hat{I_{sec}}] + I^2 $&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[(\hat{I_{sec}})^2] - 2* I^2 + I^2$&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[(\hat{I_{sec}})^2] - I^2 $&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[(\frac{1}{N} \sum\limits_{i=1}^{N} f(\xi_i))^2] - I^2$&#xD;&#xA;&#xD;&#xA;Now I am stuck here, I could do this,&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = E[\frac{1}{N^2} \sum\limits_{i=1}^{N} f^2(\xi_i) + \frac{1}{N^2}\sum\limits_{i\neq j}^{N} f(\xi_i) f(\xi_j) ] - I^2  \hspace{10mm} \because &#xD;&#xA;[\sum\limits_{i=1}^{N} f(x_i) ]^2 =  \sum\limits_{i=1}^{N} f^2(x_i) + \sum\limits_{i\neq j}^{N} f(\xi_i) f(\xi_j)$&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = \frac{1}{N^2} \sum\limits_{i=1}^{N} E[f^2(\xi_i)] + \frac{1}{N^2}\sum\limits_{i\neq j}^{N} E[f(\xi_i) f(\xi_j) ] - I^2$&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = \frac{1}{N^2} \sum\limits_{i=1}^{N} \int f^2(x)dx + \frac{1}{N^2}\sum\limits_{i\neq j}^{N} E[f(\xi_i) f(\xi_j) ] - I^2$&#xD;&#xA;&#xD;&#xA;$\hspace{20mm} \because E[f(X)] = \int f(X) p(X) dx$&#xD;&#xA;&#xD;&#xA;Note $p(X) = 1$,&#xD;&#xA;&#xD;&#xA;$\hspace{20mm}      = \frac{1}{N} \int f^2(x)dx + \frac{1}{N^2}\sum\limits_{i\neq j}^{N} E[f(\xi_i) f(\xi_j) ] - I^2$&#xD;&#xA;&#xD;&#xA;Don't know what to do next from here, any tips? Or did I do something wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/56MPu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20058" PostHistoryTypeId="1" PostId="7705" RevisionGUID="ab27b690-5728-45ff-b6aa-c260f3267fa6" CreationDate="2018-06-10T15:39:11.013" UserId="6046" Text="Variance of estimator (Monte Carlo Integration)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20059" PostHistoryTypeId="3" PostId="7705" RevisionGUID="ab27b690-5728-45ff-b6aa-c260f3267fa6" CreationDate="2018-06-10T15:39:11.013" UserId="6046" Text="|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20060" PostHistoryTypeId="2" PostId="7706" RevisionGUID="ce376b39-fd7a-429a-86c0-d46be0be42c2" CreationDate="2018-06-10T16:13:34.033" UserId="6422" Text="It’s a “naive” Monte Carlo sampler so it’s too dumb to send rays toward lights— it shotguns.   But the light is just a hemisphere (like a cloudy day) so you don’t get punished with too much noise.   Cloudy days look pretty good in real life.   But if you try to add a small light it will work but get very very noisy.   The third book in that series uses one method to address this (basically sending more rate where lights are rather than shadow rays per se)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20061" PostHistoryTypeId="2" PostId="7707" RevisionGUID="3c0c4fd6-ba05-49a7-87b2-155d489f7d97" CreationDate="2018-06-10T20:02:25.870" UserId="8709" Text="Consider this course : https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/procedural-patterns-noise-part-1/creating-simple-2D-noise . In sub-part **Introducing the Concept of Permutation** (use CTRL||CMD + F), the author explains Ken Perlin uses the array containing noise values to be interpolated (denoted A) in conjunction with another array, which is the &quot;permutation hash table&quot; (denoted B).&#xD;&#xA;&#xD;&#xA;The idea is : from any input (a point), we get its unique noise value in A, using B. A has always 256 cases (whatever the input point's dimension is) : it allows to gain in RAM consumption. B has 512 cases : the 255 first randomly contain numbers from {0...255}, idem for the last half part of B.&#xD;&#xA;&#xD;&#xA;# How to use the permutation table, according to ScratchAPixel ?&#xD;&#xA;&#xD;&#xA;There are 2 things I didn't understand.&#xD;&#xA;&#xD;&#xA;**First, (1/2) I didn't understand how the hash table is actually used.** The workflow I think I understood is the following :&#xD;&#xA;&#xD;&#xA;1. For an input (coordinate), we find the both nearest pre-defined coordinates (i.e. : those present as indices in A). It's a multiple of 255.&#xD;&#xA;&#xD;&#xA;2. The lower one is used to lookup in B&#xD;&#xA;&#xD;&#xA;3. We get a number between [0;255] that we use to lookup in A &#xD;&#xA;&#xD;&#xA;4. We get a number between [0;1] : the noise.&#xD;&#xA;&#xD;&#xA;But where is the interpolation between the both pre-defined coordinates' noise values ?&#xD;&#xA;&#xD;&#xA;In which way my understanding is wrong ? I believe you should really read this sub-part (**Introducing the Concept of Permutation** (use CTRL||CMD + F), https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/procedural-patterns-noise-part-1/creating-simple-2D-noise), it's very short and maybe your answer would fit my question more than if you were giving me explanations that possibly would be out of the range of those provided by ScratchAPixel. Thus, I would understand your answer better.&#xD;&#xA;&#xD;&#xA;By the way, **(2/2) I didn't understand this paragraph neither** :&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; You may wonder why the permutation array is twice the size of the function period (512 in size instead of 256). If we deal with a 2D noise, we will first do a lookup in the permutation table using the integer value for the x coordinate of our input point (as described). This will return an integer value in the range [0:255]. We will add the result of this lookup to the integer value for the input point y coordinate and use the sum of these two numbers as an index of the permutation table again. Since the result of the first permutation lookup is in the range [0:255] and that the integer value for the point's y coordinate is also in the range [0:255], it means that the range of possible index value for the permutation table is [0:511]. Hence the size of the permutation array (512). &#xD;&#xA;&#xD;&#xA;I'm getting confused by all the different but likely terms (&quot;integer value&quot;, &quot;coordinate&quot;, ...)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20062" PostHistoryTypeId="1" PostId="7707" RevisionGUID="3c0c4fd6-ba05-49a7-87b2-155d489f7d97" CreationDate="2018-06-10T20:02:25.870" UserId="8709" Text="ScratchAPixel : Understanding how to use Perlin's permutations hash table" ContentLicense="CC BY-SA 4.0" />
  <row Id="20063" PostHistoryTypeId="3" PostId="7707" RevisionGUID="3c0c4fd6-ba05-49a7-87b2-155d489f7d97" CreationDate="2018-06-10T20:02:25.870" UserId="8709" Text="|interpolation|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20064" PostHistoryTypeId="50" PostId="7496" RevisionGUID="1bb474cc-695e-4044-a445-39c2fe95778b" CreationDate="2018-06-11T00:41:24.090" UserId="-1" />
  <row Id="20066" PostHistoryTypeId="2" PostId="7708" RevisionGUID="0350e753-6ea7-4ed1-9145-162f399eff83" CreationDate="2018-06-11T08:53:59.417" UserId="7008" Text="When a simulating a camera, I may run into the situation that a black elliptic border is needed (rather than a rectangular image).&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In this case I have the option to discard the fragment in the fragment shader or draw it with a black color. Discarding obviously needs branching, so now I am not sure which option is faster. Generally I assume avoiding branching in shaders is the way to go, but does that hold true for discarding, especially if the branch contains only one call (the discard one)? Or is there no rule of thumb for this case at all and just benchmarking is the way to go?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E09UT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20067" PostHistoryTypeId="1" PostId="7708" RevisionGUID="0350e753-6ea7-4ed1-9145-162f399eff83" CreationDate="2018-06-11T08:53:59.417" UserId="7008" Text="Is a branched discard to be avoided" ContentLicense="CC BY-SA 4.0" />
  <row Id="20068" PostHistoryTypeId="3" PostId="7708" RevisionGUID="0350e753-6ea7-4ed1-9145-162f399eff83" CreationDate="2018-06-11T08:53:59.417" UserId="7008" Text="|glsl|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20069" PostHistoryTypeId="2" PostId="7709" RevisionGUID="68e1276d-6981-4434-937e-62d88f7ff842" CreationDate="2018-06-11T09:13:04.763" UserId="137" Text="You can use a stencil instead, This allows the gpu to do an early out test before the fragment shader even starts.&#xD;&#xA;&#xD;&#xA;You only have to build the stencil once (possibly with a discard in a simple shader) and you can reuse the stencil in future draws." ContentLicense="CC BY-SA 4.0" />
  <row Id="20076" PostHistoryTypeId="50" PostId="4632" RevisionGUID="f1f0b538-727f-46e9-962c-645dba66fbc3" CreationDate="2018-06-12T00:08:17.337" UserId="-1" />
  <row Id="20078" PostHistoryTypeId="50" PostId="7494" RevisionGUID="11e0a653-7c06-49a6-8c76-c19892b8b3af" CreationDate="2018-06-12T21:27:22.277" UserId="-1" />
  <row Id="20079" PostHistoryTypeId="2" PostId="7711" RevisionGUID="1b85c788-111d-4cb1-9c94-cfad3c111649" CreationDate="2018-06-13T08:00:33.657" UserId="6041" Text=" &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Monte Carlo estimator is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And its variance according to the above definition(continuous random variable) would be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b6YMn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/u5uoe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KSMPl.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/UhgvP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20082" PostHistoryTypeId="5" PostId="7711" RevisionGUID="685bf76c-720f-463f-8e3b-ad718e687bc3" CreationDate="2018-06-13T08:24:57.660" UserId="6041" Comment="added 7 characters in body" Text="Quoting from &quot;Advanced global illumination&quot; book:&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Monte Carlo estimator is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And its variance according to the above definition(continuous random variable) would be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ovuh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KSMPl.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/UhgvP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20083" PostHistoryTypeId="5" PostId="7711" RevisionGUID="2a9b0adf-2fac-4f38-994d-fc77f7d602c0" CreationDate="2018-06-13T12:22:44.973" UserId="6041" Comment="added 254 characters in body" Text="Quoting from &quot;Advanced global illumination&quot; book:&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Monte Carlo estimator is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And its variance according to the above definition(continuous random variable) would be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;An example for how the variance of an estimator G is calculate:&#xD;&#xA;See how the summation is written as N times the integrand and is cancelled out later.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ovuh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KSMPl.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/UhgvP.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/eLSml.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20084" PostHistoryTypeId="5" PostId="7711" RevisionGUID="a9476ae2-009c-4e20-815a-274798490f4a" CreationDate="2018-06-13T15:54:42.260" UserId="6041" Comment="added 6 characters in body" Text="Quoting from &quot;Advanced global illumination&quot; book:&#xD;&#xA;&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The Monte Carlo estimator is defined as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And its variance according to the above definition(continuous random variable) would be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;An example for how the variance of an estimator G is calculated:&#xD;&#xA;&#xD;&#xA;(note how the summation is written as N times the integrand and is cancelled out later.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ovuh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KSMPl.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/UhgvP.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/eLSml.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20089" PostHistoryTypeId="2" PostId="7714" RevisionGUID="72e619af-1acc-4894-8edb-bb355da74c23" CreationDate="2018-06-13T17:50:38.483" UserId="506" Text="If you’re comfortable working in Metal, there’s a brand-new shader debugger which does exactly what you’re after—it’ll let you step through your code while showing the values of your variables, as well as edit the code and re-run it. It’s in the Xcode 10 beta; there’s a presentation about how to use it available [here](https://developer.apple.com/videos/play/wwdc2018/608/)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20090" PostHistoryTypeId="50" PostId="6180" RevisionGUID="ef9d4dfe-f3e3-4ac3-ad7d-589ac0a1db5d" CreationDate="2018-06-13T20:43:25.237" UserId="-1" />
  <row Id="20093" PostHistoryTypeId="2" PostId="7716" RevisionGUID="0d1c6df4-30d7-4674-b5ee-535404689fb2" CreationDate="2018-06-14T17:16:47.073" UserId="228" Text="I'm implementing the marching cubes, reference is [this][1]. I managed to get the geometric reconstruction (the mesh) however I do struggle with the normals.&#xD;&#xA;&#xD;&#xA;In section 4 they explain the gradient can be firstly estimated using central difference using 8 cubes sharing the vertex $(i,j,k)$. However consider for example case 1 (figure 3) in the paper assume for example you have 8 cubes with one vertex &quot;on&quot; and all the other &quot;off&quot;. All the central difference (assuming binary values) would give you 0, therefore I wouldn't be able to estimate the normal in the cube vertex, and later linear interpolate.&#xD;&#xA;&#xD;&#xA;Is there some subtlety I'm missing? I wouldn't personally use central difference, but assuming I'm sweeping in a certain direction and then interpolate a point in a cube edge I would use for example forward difference, which to me make more sense, however I'm not 100% sure of the &quot;sense&quot; of this.&#xD;&#xA;&#xD;&#xA;In their scheme they give a good explanation of why their approach make sense.&#xD;&#xA;Not sure I can justify mine. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://academy.cba.mit.edu/classes/scanning_printing/MarchingCubes.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="20094" PostHistoryTypeId="1" PostId="7716" RevisionGUID="0d1c6df4-30d7-4674-b5ee-535404689fb2" CreationDate="2018-06-14T17:16:47.073" UserId="228" Text="Degenerate case of normal computation in marching cubes" ContentLicense="CC BY-SA 4.0" />
  <row Id="20095" PostHistoryTypeId="3" PostId="7716" RevisionGUID="0d1c6df4-30d7-4674-b5ee-535404689fb2" CreationDate="2018-06-14T17:16:47.073" UserId="228" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20096" PostHistoryTypeId="12" PostId="7703" RevisionGUID="9744c72c-d45d-4248-81c3-edf06b85b5d5" CreationDate="2018-06-14T20:04:39.467" UserId="8709" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:8709,&quot;DisplayName&quot;:&quot;JarsOfJam-Scheduler&quot;}]}" />
  <row Id="20097" PostHistoryTypeId="2" PostId="7717" RevisionGUID="f88602d1-49c0-4852-ac53-cf7574fcc29c" CreationDate="2018-06-14T22:37:46.180" UserId="4981" Text="I have to create a orbiting camera. I created the model of sun (a sphere) around (0,0,0) , triangulated and Phong shaded it. I would have a camera that goes around the sun thus an orbiting camera and I would know if my way to proceed is right or not:&#xD;&#xA;In WebGl there isn't a phisical camera. Nevertheless I imagine to place my camera at the center (0,0,0) and I have first to translate it of [0 0 100] ([0 0 100] is the point where early is located the camera) and later I rotate the camera around y ([0 1 0]) of 15 grades for instance.&#xD;&#xA;&#xD;&#xA;Thus cameraMatrix = R(15,[0 1 0])T([0 0 100])&#xD;&#xA;(First translation and later rotation)&#xD;&#xA;&#xD;&#xA;But in WebGl there isn't camera, then I have to move the world with inverse transformation namely:&#xD;&#xA;&#xD;&#xA;ModelViewMatrix = inverse(cameraMatrix);&#xD;&#xA;&#xD;&#xA;Thus&#xD;&#xA;ModelViewMatrix =  inverse{R(15,[0 1 0])T([0 0 100])} = inverse(T([0 0 100]))*inverse(R(15,[0 1 0])= T([0 0 -100])* R(-15,[0 1 0])&#xD;&#xA;&#xD;&#xA;(In the last first rotation and later translation)&#xD;&#xA;&#xD;&#xA;So far is it all right?&#xD;&#xA;Finally in drawScene namely the function of rendering cycle the order of call is inverted namely: &#xD;&#xA;&#xD;&#xA;    mat4.translate(mvMatrix , [0,0,-100.0]);&#xD;&#xA;    mat4.rotate(mvMatrix , degToRad(-15) , [0,1,0]); &#xD;&#xA;&#xD;&#xA;in this order does a rototranslation, namely it occurs first the rotation and later the translation (inverted respect the order of call functions).&#xD;&#xA;&#xD;&#xA;I would confirm if this is right because I'm a neophyte of Computer Graphics and I'm not sure.&#xD;&#xA;(I know that I can use lookAt() or define the values of cameraMatrix by hand but I'm not interested in it).&#xD;&#xA;Thanks in advance " ContentLicense="CC BY-SA 4.0" />
  <row Id="20098" PostHistoryTypeId="1" PostId="7717" RevisionGUID="f88602d1-49c0-4852-ac53-cf7574fcc29c" CreationDate="2018-06-14T22:37:46.180" UserId="4981" Text="Correctness or otherwise of the procedure for generating an orbiting camera in WebGl" ContentLicense="CC BY-SA 4.0" />
  <row Id="20099" PostHistoryTypeId="3" PostId="7717" RevisionGUID="f88602d1-49c0-4852-ac53-cf7574fcc29c" CreationDate="2018-06-14T22:37:46.180" UserId="4981" Text="|rendering|transformations|webgl|matrix|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20100" PostHistoryTypeId="5" PostId="7717" RevisionGUID="89732aad-f65a-492e-a87e-3f90e0ccf4f8" CreationDate="2018-06-14T22:42:54.993" UserId="4981" Comment="Generic angle" Text="I have to create a orbiting camera. I created the model of sun (a sphere) around (0,0,0) , triangulated and Phong shaded it. I would have a camera that goes around the sun thus an orbiting camera and I would know if my way to proceed is right or not:&#xD;&#xA;In WebGl there isn't a phisical camera. Nevertheless I imagine to place my camera at the center (0,0,0) and I have first to translate it of [0 0 100] ([0 0 100] is the point where early is located the camera) and later I rotate the camera around y ([0 1 0]) of some angle (Actually the angle is animated, i.e. the angle increases over time).&#xD;&#xA;&#xD;&#xA;Thus cameraMatrix = R(angle,[0 1 0])T([0 0 100])&#xD;&#xA;(First translation and later rotation)&#xD;&#xA;&#xD;&#xA;But in WebGl there isn't camera, then I have to move the world with inverse transformation namely:&#xD;&#xA;&#xD;&#xA;ModelViewMatrix = inverse(cameraMatrix);&#xD;&#xA;&#xD;&#xA;Thus&#xD;&#xA;ModelViewMatrix =  inverse{R(angle,[0 1 0])T([0 0 100])} = inverse(T([0 0 100]))*inverse(R(angle,[0 1 0])= T([0 0 -100])* R(-angle,[0 1 0])&#xD;&#xA;&#xD;&#xA;(In the last first rotation and later translation)&#xD;&#xA;&#xD;&#xA;So far is it all right?&#xD;&#xA;Finally in drawScene namely the function of rendering cycle the order of call is inverted namely: &#xD;&#xA;&#xD;&#xA;    mat4.translate(mvMatrix , [0,0,-100.0]);&#xD;&#xA;    mat4.rotate(mvMatrix , degToRad(-angle) , [0,1,0]); &#xD;&#xA;&#xD;&#xA;in this order does a rototranslation, namely it occurs first the rotation and later the translation (inverted respect the order of call functions).&#xD;&#xA;&#xD;&#xA;I would confirm if this is right because I'm a neophyte of Computer Graphics and I'm not sure.&#xD;&#xA;(I know that I can use lookAt() or define the values of cameraMatrix by hand but I'm not interested in it).&#xD;&#xA;Thanks in advance " ContentLicense="CC BY-SA 4.0" />
  <row Id="20101" PostHistoryTypeId="2" PostId="7718" RevisionGUID="15bd1110-6fdf-4391-adf5-f8f408c032a2" CreationDate="2018-06-14T23:12:34.117" UserId="4981" Text="I have not read the links but you remember that in the classical ray tracing ,namely Whitted rayTracing,  a single ray is traced from viewpoint to each pixel and alone if a complete diffusive surface is intercepted  the reflected ray (secundary ray) isn't calculated. Practically the contribution of indirect illumination on the specular diffusive surface is multiplied for $K_s$ i.e. the specularity coefficient of material and if diffusive coefficient $K_d$ is very hight $K_s$ will be very low and thus the reflective ray in that point isn't traced thus there will be a threashold to stop recursion. Furthermore the recursion tree is a binary tree because is launched between secundary ray the rifraction ray also.&#xD;&#xA;&#xD;&#xA;In this method there is   subsampling namely aliasing: in the real case more that a ray determines the color of a pixel and in Witthed is like to use a sample(a single ray) for each pixel. Thus we can launch more that a ray for each pixel but not one ray for each equally divided space of the pixel (otherwise supersampling namely aliasing to a bigger frequency) but the rays are sent  in a stochastic way like this they will hit the areas where the color variation is higher (these areas cause aliasing). The Witthed ray Tracing here is rephrased following Kajiha equation of rendering that bring to solve an integral of the BRDF with Montecarlo method choising with importance the samples to estimate the integral using the BRDF or its estime like a probability distribution. &#xD;&#xA;Following these sthocatic approaches there are distributed ray tracing and path ray tracing for instance. " ContentLicense="CC BY-SA 4.0" />
  <row Id="20106" PostHistoryTypeId="50" PostId="7628" RevisionGUID="253df0c8-e8e8-4bfb-9cc7-d17e0272afd1" CreationDate="2018-06-15T22:42:01.380" UserId="-1" />
  <row Id="20107" PostHistoryTypeId="2" PostId="7720" RevisionGUID="fe698f0d-b50f-4c70-b1f3-f550be0e9f78" CreationDate="2018-06-16T07:53:21.813" UserId="1937" Text="Your math looks correct to me. Your terminology is a little off - technically what you are creating here is just the 'view' matrix rather than the 'modelView'. If you're just drawing a single sphere at the origin then it doesn't make a difference, but normally the modelView is unique for each object in a scene - it's the object's model-to-world transform matrix multiplied by the view matrix you describe above." ContentLicense="CC BY-SA 4.0" />
  <row Id="20111" PostHistoryTypeId="50" PostId="7643" RevisionGUID="f93230bb-d0a5-4a48-842b-f30262995f6a" CreationDate="2018-06-16T20:47:02.390" UserId="-1" />
  <row Id="20112" PostHistoryTypeId="2" PostId="7722" RevisionGUID="9f9850b1-ae96-40f1-b27d-572b8681fd75" CreationDate="2018-06-17T06:04:12.177" UserId="8889" Text="I'm not sure this is the best place to post this, but it _definitely_ seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.&#xD;&#xA;&#xD;&#xA;On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.&#xD;&#xA;&#xD;&#xA;P.S. If you want to see the code, it's on github at https://github.com/performous/performous&#xD;&#xA;&#xD;&#xA;Relevant files most likely would be (under game/) `video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh` and the actual shaders that live in `data/shaders`&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win7 PC][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win10 laptop][2]][2]&#xD;&#xA;&#xD;&#xA;[![Expected appearance, on my mac][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fF2Af.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/2X29q.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/G6biw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20113" PostHistoryTypeId="1" PostId="7722" RevisionGUID="9f9850b1-ae96-40f1-b27d-572b8681fd75" CreationDate="2018-06-17T06:04:12.177" UserId="8889" Text="Distorted OpenGL graphics in certain models of Intel GPUs under Windows; possible causes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20114" PostHistoryTypeId="3" PostId="7722" RevisionGUID="9f9850b1-ae96-40f1-b27d-572b8681fd75" CreationDate="2018-06-17T06:04:12.177" UserId="8889" Text="|opengl|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20121" PostHistoryTypeId="50" PostId="6012" RevisionGUID="0428e20c-22e9-47c4-97ed-37d66732a2a6" CreationDate="2018-06-17T18:14:26.270" UserId="-1" />
  <row Id="20122" PostHistoryTypeId="50" PostId="5996" RevisionGUID="e915ec7b-fbd5-4087-8962-09b93f920e96" CreationDate="2018-06-17T20:14:47.323" UserId="-1" />
  <row Id="20123" PostHistoryTypeId="2" PostId="7724" RevisionGUID="5a93cf9f-8bf5-4dca-86e0-21023daaffd4" CreationDate="2018-06-18T00:47:56.717" UserId="6046" Text="So someone at mathstackexchange posted the answer I was satisfied with. Here is the [link][1]&#xD;&#xA;&#xD;&#xA;And here is the quoted answer.&#xD;&#xA;&#xD;&#xA;&gt; This computation really has nothing to do with the Monte Carlo&#xD;&#xA;&gt; integration context. It is a general fact that if $X_i$ are iid random&#xD;&#xA;&gt; variables with variance $\sigma^2$ then $\frac{1}{n} \sum_{i=1}^n X_i$&#xD;&#xA;&gt; has variance $\sigma^2/n$. This is because of two related facts.&#xD;&#xA;&gt; First, if you sum two independent random variables, you add their&#xD;&#xA;&gt; variances. This is because:&#xD;&#xA;&gt; &#xD;&#xA;&gt; $$\sigma_{X+Y}^2=E[(X+Y-\mu_X-\mu_Y)^2] \\=E[((X-\mu_X)+(Y-\mu_Y))^2]&#xD;&#xA;&gt; \\&#xD;&#xA;&gt; =E[(X-\mu_X)^2]+E[(Y-\mu_Y)^2]+2E[(X-\mu_X)(Y-\mu_Y)] \\=\sigma_X^2+\sigma_Y^2.$$&#xD;&#xA;&gt; &#xD;&#xA;&gt; In the last step you use that independent random variables are&#xD;&#xA;&gt; uncorrelated. This follows from the fact that $E[XY]=E[X]E[Y]$ if $X$&#xD;&#xA;&gt; and $Y$ are independent.&#xD;&#xA;&gt; &#xD;&#xA;&gt; Second, if you multiply a random variable by a constant, you multiply&#xD;&#xA;&gt; its variance by the square of that constant. This is obvious from the&#xD;&#xA;&gt; definition and linearity of expectation.&#xD;&#xA;&gt; &#xD;&#xA;&gt; So in the context of $\frac{1}{n} \sum_{i=1}^n X_i$, the summation&#xD;&#xA;&gt; multiplies the variance by $n$ while the division by $n$ multiplies&#xD;&#xA;&gt; the variance by $1/n^2$, giving the result.&#xD;&#xA;&#xD;&#xA;So if we apply this $E[XY]=E[X]E[Y]$, we get the final result.&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/2823164/variance-of-estimator-monte-carlo-integration/2823170#2823170" ContentLicense="CC BY-SA 4.0" />
  <row Id="20124" PostHistoryTypeId="2" PostId="7725" RevisionGUID="17bce336-09e9-4231-9b07-29cb0b8491bf" CreationDate="2018-06-18T11:38:42.487" UserId="8892" Text="I've recently become interested in photorealistic rendering, and I've been looking at the different rendering philosophies. I read this [Disney Research bachelor's thesis][1], which states both the radiative transfer equation (RTE)&#xD;&#xA;&#xD;&#xA;$(\vec{w}\cdot\nabla)L(\vec{x},\vec{\omega}) = -(\sigma_{a}+\sigma_{s})L(\vec{x},\vec{\omega})+Q(\vec{x},\vec{\omega})+\sigma_{s} \int_{\Omega}L(\vec{x},\vec{\omega})\rho(\vec{\omega},\vec{\omega}')d\vec{\omega}'$&#xD;&#xA;&#xD;&#xA;and that &#xD;&#xA;&#xD;&#xA;&gt; Exact BSSRDFs follow trivially from exact solutions to the RTE.&#xD;&#xA;&gt; Unfortunately, closed form solutions of the RTE for general 3D&#xD;&#xA;&gt; geometry, illumination and materials are rare, which motivates&#xD;&#xA;&gt; analysis on simplified, lower dimensional domains.&#xD;&#xA;&#xD;&#xA;But most shaders use BSSRDF's and(/or?) the Rendering Equation instead, even high-end shaders like Disney's Hyperion, even though the [Rendering Equation][2] supposedly doesn't take into account sub-surface scattering, polarization, etc..&#xD;&#xA;&#xD;&#xA;So my two questions are **a)** what is the reason for not using the radiative transfer equation for photorealistic rendering (or an approximation like the skin-shaders used for Big Hero and Moana), and **b)** how are the parameters like the phase functions and coefficients found for different materials like skin, hair, water, metal, glass?&#xD;&#xA;&#xD;&#xA;  [1]: https://benedikt-bitterli.me/bachelor-thesis.pdf&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="20125" PostHistoryTypeId="1" PostId="7725" RevisionGUID="17bce336-09e9-4231-9b07-29cb0b8491bf" CreationDate="2018-06-18T11:38:42.487" UserId="8892" Text="Radiative Transfer Equation for Photorealistic Rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="20126" PostHistoryTypeId="3" PostId="7725" RevisionGUID="17bce336-09e9-4231-9b07-29cb0b8491bf" CreationDate="2018-06-18T11:38:42.487" UserId="8892" Text="|rendering|shader|computational-geometry|brdf|photo-realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20127" PostHistoryTypeId="50" PostId="7529" RevisionGUID="1b7b539d-3e1e-4a2c-9262-968dcf750cb5" CreationDate="2018-06-18T19:26:12.847" UserId="-1" />
  <row Id="20128" PostHistoryTypeId="2" PostId="7726" RevisionGUID="5ea6bc07-08f0-455c-85ce-bd719dcfdbd8" CreationDate="2018-06-18T21:00:29.777" UserId="48" Text="I suspect the answer to (a) is simply performance. Full volumetric path tracing / photon mapping based on the RTE can certainly be done (and I'm sure it sometimes is), but it's very expensive and requires enormous numbers of samples to converge to a noise-free result.&#xD;&#xA;&#xD;&#xA;This is especially true when the scattering medium is very dense, like in human skin and hair, or materials like milk, plastic, marble, or jade. In such materials, the light scatters so quickly that it's essentially isotropic after a couple of millimeters, so a BSSRDF is a very good approximation to the true volumetric scattering, and far cheaper to evaluate. (Performance matters even for offline rendering!) A mixture of volumetric simulations and empirical data might be used to derive and validate the BSSRDF.&#xD;&#xA;&#xD;&#xA;As for how the coefficients are measured, one technique I've read about is to shine a narrow, bright beam of light (like a laser pointer) onto the material, then measure the light scattered back out using photosensors placed at different distances from the incident point. By processing this data you can then get an estimate of the scattering coefficients. [This paper](http://www.merl.com/publications/docs/TR2005-046.pdf) shows a sensor based on this idea being applied to human skin, and [this one](http://gfx.cs.princeton.edu/pubs/Donner_2008_ALH/donner08hskin.pdf) has more details about setting up a sophisticated (multi-layer) BSSRDF based on empirical data." ContentLicense="CC BY-SA 4.0" />
  <row Id="20129" PostHistoryTypeId="50" PostId="6291" RevisionGUID="ca76cfa0-d198-40f4-91bc-dfa6ddc65bf2" CreationDate="2018-06-19T01:28:51.843" UserId="-1" />
  <row Id="20130" PostHistoryTypeId="50" PostId="7633" RevisionGUID="c3f75f9f-00c8-4248-bd00-8d4db048a181" CreationDate="2018-06-19T04:35:38.830" UserId="-1" />
  <row Id="20140" PostHistoryTypeId="2" PostId="7729" RevisionGUID="7b44752c-4d32-45e6-9227-44c525e3c222" CreationDate="2018-06-20T00:42:37.507" UserId="7952" Text="&#xD;&#xA;The paper doesn't say to compute the normals for the 8 &quot;cubes&quot; around the cube in question. It is saying to compute the normals for all the vertices of the cube you are testing. To create those normals the algorithm would need density values from the surrounding cubes but not the normals of the surrounding cubes.&#xD;&#xA;&#xD;&#xA;The paper labels those vertices v1 to v8. So if v1 is the only vertex whose density value is 1 and the density value for all 7 other vertices is zero then v3,v6,v7 and v8 would have normals of zero (assuming the adjacent cubes were empty). But v1,v2,v4 and v5 would have non-zero normals since v1 is guaranteed to have a non-zero density and at least 1 of x,y or z would be non-zero. Interpolating those normals to the triangle with vertices at e1,e4 and e9 should give a normal pointing roughly at v7. &#xD;&#xA;&#xD;&#xA;When reading a paper like this one (ie one that has been used around the world to visualize life saving data, and help countless people) if I think I have found an error I stop and take a long hard look for my mistake instead of looking for the mistake of the authors. Just saying." ContentLicense="CC BY-SA 4.0" />
  <row Id="20146" PostHistoryTypeId="6" PostId="27" RevisionGUID="9d0d0c7a-896f-4530-91f8-f888dc91b639" CreationDate="2018-06-20T09:11:58.230" UserId="137" Comment="edited tags" Text="|vulkan|directx12|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20147" PostHistoryTypeId="50" PostId="7647" RevisionGUID="568ba57a-0a63-4030-9464-ca8860c60788" CreationDate="2018-06-20T10:53:16.917" UserId="-1" />
  <row Id="20148" PostHistoryTypeId="50" PostId="7623" RevisionGUID="b832eae5-8175-4e40-8d6d-7f49399779ef" CreationDate="2018-06-20T14:53:16.893" UserId="-1" />
  <row Id="20150" PostHistoryTypeId="50" PostId="6422" RevisionGUID="564d9908-fd74-4c22-b7d8-30d028f9973d" CreationDate="2018-06-20T15:53:16.873" UserId="-1" />
  <row Id="20151" PostHistoryTypeId="2" PostId="7730" RevisionGUID="62cbd785-a66f-4a77-bcc2-955dcfc6aeac" CreationDate="2018-06-20T18:32:55.793" UserId="2485" Text="I am following [this tutorial][1] on how to implement a first person camera. So far I was able to implement [the entire (C++) class][2] in TypeScript and it works as it is supposed to.&#xD;&#xA;&#xD;&#xA;### Problem&#xD;&#xA;&#xD;&#xA;What I was not able to implement is a system which takes the camera direction only and initially orients the camera based on it. In the tutorial the author does set the camera direction to `(0.0, 0.0, -1.0)` but it is instantly overwritten by calling `_updateCameraVectors()` in the constructor. So as I see it, passing the camera direction to the class will always be ignored. Before looking at the code please note:&#xD;&#xA;&#xD;&#xA;* In the tutorial the author referes to a variable `Front`, which in my case is called `cameraDirection`&#xD;&#xA;* In the tutorial only the view matrix is being calculated by the camera class. I am calculating the view-projection matrix.&#xD;&#xA;&#xD;&#xA;### Code&#xD;&#xA;&#xD;&#xA;Here are the most important parts:&#xD;&#xA;&#xD;&#xA;The constructor initializes all the important stuff, but most importantly calls `_updateCameraVectors()`.&#xD;&#xA;&#xD;&#xA;    constructor(gl: WebGL2RenderingContext, program: WebGLProgram, position: vec3, cameraDirection = vec3.fromValues(0.0, 0.0, -1.0),&#xD;&#xA;        yaw = -90.0, pitch = 0.0,&#xD;&#xA;        aspect = gl.canvas.clientWidth / gl.canvas.clientHeight, zNear = 1, zFar = 2000) {&#xD;&#xA;        this.gl = gl;&#xD;&#xA;        this._program = program;&#xD;&#xA;        this._aspect = aspect;&#xD;&#xA;        this._zNear = zNear;&#xD;&#xA;        this._zFar = zFar;&#xD;&#xA;        this._yaw = yaw;&#xD;&#xA;        this._pitch = pitch;&#xD;&#xA;        this._cameraPosition = position;&#xD;&#xA;        this._cameraDirection = cameraDirection;&#xD;&#xA;&#xD;&#xA;        this._updateCameraVectors();&#xD;&#xA;        GLHelper.setUniformLocations(this.gl, this._unifroms, this._program);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In `_updateCameraVectors()` the camera direction is being recalculated based on yaw and pitch values. Then the `cameraUp` vector is calculated.&#xD;&#xA;&#xD;&#xA;    protected _updateCameraVectors(): void {&#xD;&#xA;        const front = vec3.create();&#xD;&#xA;        front[0] = Math.cos(MathHelper.degToRad(this._yaw)) * Math.cos(MathHelper.degToRad(this._pitch));&#xD;&#xA;        front[1] = Math.sin(MathHelper.degToRad(this._pitch));&#xD;&#xA;        front[2] = Math.sin(MathHelper.degToRad(this._yaw)) * Math.cos(MathHelper.degToRad(this._pitch));&#xD;&#xA;        vec3.normalize(this._cameraDirection, front);&#xD;&#xA;&#xD;&#xA;        const right = vec3.create();&#xD;&#xA;        vec3.cross(right, this._cameraDirection, this._worldUp); // World up is always (0,1,0)&#xD;&#xA;        vec3.normalize(this._cameraRight, right);&#xD;&#xA;        const up = vec3.create();&#xD;&#xA;        vec3.cross(up, this._cameraRight, this._cameraDirection);&#xD;&#xA;        vec3.normalize(this._cameraUp, up);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Based on a `requestAnimationFrame`-loop the `_computeviewProjectionMatrix` simply calculates a view-projection matrix which is later used for rendering.&#xD;&#xA;&#xD;&#xA;    private _computeviewProjectionMatrix(): mat4 {&#xD;&#xA;&#xD;&#xA;        this._aspect = this.gl.canvas.clientWidth / this.gl.canvas.clientHeight;&#xD;&#xA;&#xD;&#xA;        const cameraTarget = vec3.create();&#xD;&#xA;        vec3.add(cameraTarget, this._cameraPosition, this._cameraDirection); // Here the actual camera target is calculated.&#xD;&#xA;&#xD;&#xA;        const view = mat4.create();&#xD;&#xA;        mat4.lookAt(view, this._cameraPosition, cameraTarget, this._cameraUp);&#xD;&#xA;&#xD;&#xA;        const projectionMatrix = mat4.create();&#xD;&#xA;&#xD;&#xA;        mat4.perspective(projectionMatrix, this._fieldOfViewRadians, this._aspect, this._zNear, this._zFar);&#xD;&#xA;&#xD;&#xA;        const viewProjectionMatrix = mat4.create();&#xD;&#xA;        mat4.multiply(viewProjectionMatrix, projectionMatrix, view);&#xD;&#xA;&#xD;&#xA;        return viewProjectionMatrix;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The `_handleMouseMovement` function calls `_updateCameraVectors()` every time the `pitch` and `yaw` values are updated via mouse movement.&#xD;&#xA;&#xD;&#xA;    private _handleMouseMovement = (event: MouseEvent): void =&gt; {&#xD;&#xA;&#xD;&#xA;        if (this._firstMouseMove) {&#xD;&#xA;            this._firstMouseMove = false;&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;		&#xD;&#xA;        let xOffset = event.movementX;&#xD;&#xA;        let yOffset = event.movementY;&#xD;&#xA;&#xD;&#xA;        xOffset *= this._sensitivity;&#xD;&#xA;        yOffset *= this._sensitivity;&#xD;&#xA;&#xD;&#xA;        this._yaw += xOffset;&#xD;&#xA;&#xD;&#xA;        if (!this._inverseY) {&#xD;&#xA;            this._pitch += yOffset;&#xD;&#xA;        } else {&#xD;&#xA;            this._pitch -= yOffset;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (this._pitch &gt; 89) {&#xD;&#xA;            this._pitch = 89;&#xD;&#xA;        }&#xD;&#xA;        if (this._pitch &lt; -89) {&#xD;&#xA;            this._pitch = -89;&#xD;&#xA;        }&#xD;&#xA;		&#xD;&#xA;        this._updateCameraVectors();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Last but not least there is a `_moveCamera` function which updates the camera position based on WASD input. I will post only a excerpt because it is selfexplonatory.&#xD;&#xA;&#xD;&#xA;    private _moveCamera(): void {&#xD;&#xA;        // INFO: 'W' - Move forward&#xD;&#xA;        if (this._keyMap[87] === true) {&#xD;&#xA;            const factor = vec3.create();&#xD;&#xA;            vec3.scale(factor, this._cameraDirection, this._cameraSpeed * this._deltaTime);&#xD;&#xA;            vec3.add(this._cameraPosition, this._cameraPosition, factor);&#xD;&#xA;        }&#xD;&#xA;		&#xD;&#xA;		// ...&#xD;&#xA;		&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;### Question&#xD;&#xA;How would I modify this class to initially &quot;lookAt&quot; a vec3 point passed to the constructor? Note I am not really asking for code only. Suggestion, ideas and any advice would be really helpful.&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Getting-started/Camera&#xD;&#xA;  [2]: https://learnopengl.com/code_viewer_gh.php?code=includes/learnopengl/camera.h" ContentLicense="CC BY-SA 4.0" />
  <row Id="20152" PostHistoryTypeId="1" PostId="7730" RevisionGUID="62cbd785-a66f-4a77-bcc2-955dcfc6aeac" CreationDate="2018-06-20T18:32:55.793" UserId="2485" Text="Computing a lookAt matrix by passing a vec3 to a camera object" ContentLicense="CC BY-SA 4.0" />
  <row Id="20153" PostHistoryTypeId="3" PostId="7730" RevisionGUID="62cbd785-a66f-4a77-bcc2-955dcfc6aeac" CreationDate="2018-06-20T18:32:55.793" UserId="2485" Text="|webgl|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20155" PostHistoryTypeId="2" PostId="7731" RevisionGUID="e612a1a9-87c5-451b-89ad-49b4b6ba2158" CreationDate="2018-06-21T15:56:09.910" UserId="8907" Text="This is kind of a meta-question: We are a neuroscience lab looking for an engineer to develop virtual environments for experiments. Since it's not our usual field of job advertisement we do not know where computer graphics people usually look for job ads. A top-3 list of of places you would frequent to look for jobs would be very much appreciated. " ContentLicense="CC BY-SA 4.0" />
  <row Id="20156" PostHistoryTypeId="1" PostId="7731" RevisionGUID="e612a1a9-87c5-451b-89ad-49b4b6ba2158" CreationDate="2018-06-21T15:56:09.910" UserId="8907" Text="Where do computer graphic engineers look for job ads?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20157" PostHistoryTypeId="3" PostId="7731" RevisionGUID="e612a1a9-87c5-451b-89ad-49b4b6ba2158" CreationDate="2018-06-21T15:56:09.910" UserId="8907" Text="|virtual-reality|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20158" PostHistoryTypeId="2" PostId="7732" RevisionGUID="b1ab0d7d-002f-456e-a642-18d1f417f875" CreationDate="2018-06-21T18:27:10.707" UserId="2817" Text="That's a tough one. This is going to be anecdotal evidence, but in the case of other graphics programmers I know and myself, each of us has a selection of companies we hold in high esteem based on their achievements, and we watch their websites for job postings. Getting on people's &quot;employer wishlists&quot; is difficult for obvious reasons, though, especially if the job isn't &quot;glamourous&quot; like games or film VFX.&#xD;&#xA;&#xD;&#xA;What does work sometimes is approaching candidates on LinkedIn (personally, I've had several instances where approaches led to successful processes and then job offers, and I accepted one of them), but I would strongly suggest being as up-front with the details as possible (preferably in the very first message you send). There's nothing more irritating than a recruiter who &quot;will tell you everything, but only over the phone/after we connect&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="20159" PostHistoryTypeId="2" PostId="7733" RevisionGUID="a8eaee78-a961-405e-b7ed-58783a281efd" CreationDate="2018-06-21T20:54:50.043" UserId="8796" Text="Given that you already use yaw and pitch angles to describe the camera, the simplest solution is to compute yaw and pitch values for the vector (note: it must be a unit vector).&#xD;&#xA;&#xD;&#xA;If you have `front` vector given, you can compute angles:&#xD;&#xA;&#xD;&#xA;    pitch = MathHelper.radToDeg(Math.asin(front[1]));&#xD;&#xA;    yaw = MathHelper.radToDeg(Math.atan2(front[2], front[1]));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20160" PostHistoryTypeId="2" PostId="7734" RevisionGUID="3d8c59d2-6015-4cd7-a0ed-67a80a405d43" CreationDate="2018-06-21T23:56:20.787" UserId="4837" Text="Recently I ran into an odd issue with some of my DirectX11 DirectCompute code &#xD;&#xA;when trying it on an AMD GPU for the first time (specifically a Radeon RX 580, the rest of the development was done on a NVIDIA GeForce GTX 960). The fact that this only appeared on AMD either means that NVIDIA GPUs are more resistant to the issue or perhaps something about them such as a different wavefront size is not triggering the issue, or that it's not even an problem with my code and instead is a bug somewhere along the pipeline (driver, GPU itself, etc) for AMD things.&#xD;&#xA;&#xD;&#xA;The general setup of the issue can be represented by the following pseudocode which I turned into a minimal test application to confirms the problem indeed exists to ensure nothing else in the other much larger codebase was causing the issues:&#xD;&#xA;&#xD;&#xA;    if (condition) {&#xD;&#xA;      globalArray[i].first = value &#xD;&#xA;    } else {&#xD;&#xA;      globalArray[i].second = value&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    InterlockedExchange(globalArray[i].flag, true, oldFlag)&#xD;&#xA;    &#xD;&#xA;    if (!oldFlag) {&#xD;&#xA;      return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if (condition) {&#xD;&#xA;      new_value = globalArray[i].second&#xD;&#xA;    } else {&#xD;&#xA;      new_value = globalArray[i].first&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With this setup, an example of its functionality would be best represented by 2 threads executing this code (the important bit being that they may not be within the same work group, more on this later), one with `condition` set to true and one with it set to false. Next, each thread sets the value they possess into a global buffer (both threads have the same index `i`) in the `first` and `second` slots of a structure. The interlocked exchange operation which follows attempts to set the flag (also stored in global memory) to true, allowing only one of the two threads to proceed (one will see that the flag was not set beforehand, meaning it was the first to set it and return). Finally, the remaining thread can now make the assumption that both `first` and `second` values have been set (as the other now terminated thread has already set the atomic which ensures this), allowing it to read the value written by the other thread to `new_value` (based on the condition once again).&#xD;&#xA;&#xD;&#xA;From a more higher level perspective, this code simply allows two arbitrary threads to combine their information into one which continues on, all through global memory.&#xD;&#xA;&#xD;&#xA;The issue I observed however was that very rarely (only seen in about 1 in a million cases), `new_value` would be set to something uninitialized, implying that the data it read from in the global array was. This however is confusing as the fact that the atomic flag is set should ensure that the value has been written to the proper location by the other thread. I thought perhaps that the atomic operation finished before the full write to the first/second value did for whatever reason and added a `DeviceMemoryBarrier` after the value write but before the atomic exchange, but that also had no effect.&#xD;&#xA;&#xD;&#xA;This behavior leads me to believe that it is something bizarre which is happening so rarely due to unlikely circumstances, such as threads from different wavefronts running into eachother at the exact same time as mentioned previously which should in theory work fine, but something such as caching preventing the writes from being seen properly. This further is strengthened by my testing indicating that issues only seem to arise with locally shuffled work indicies, allowing for more conflicts between wavefronts most likely rather than a large global shuffle which just has different threads writing all over the place without much conflict. Most of that is simply speculation though since I do not know too much about the specifics of how GPU memory hierarchies function. Another possibility is that this kind of behavior simply isn't guaranteed by DirectCompute and I am using it incorrectly, though DirectX's documentation is very lacking on actual in-depth descriptions of functionality for intrinsics like `InterlockedExchange`, so I am not sure what to think. As mentioned before I have also considered it being an issue with something AMD related since it does not appear to happen ever on the NVIDIA card I have.&#xD;&#xA;&#xD;&#xA;Does anyone know why this might happen and what I can do to fix it? If it'd help, I can also make the proof of concept test application I made available to show a more specific example of the problem occurring (since the pseudocode did leave out a lot of &quot;irrelevant&quot; details which may actually be significant)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20161" PostHistoryTypeId="1" PostId="7734" RevisionGUID="3d8c59d2-6015-4cd7-a0ed-67a80a405d43" CreationDate="2018-06-21T23:56:20.787" UserId="4837" Text="Direct3D Global Atomic Issue" ContentLicense="CC BY-SA 4.0" />
  <row Id="20162" PostHistoryTypeId="3" PostId="7734" RevisionGUID="3d8c59d2-6015-4cd7-a0ed-67a80a405d43" CreationDate="2018-06-21T23:56:20.787" UserId="4837" Text="|hlsl|compute-shader|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20163" PostHistoryTypeId="2" PostId="7735" RevisionGUID="e3cfa5fb-6cc8-4e83-a567-bdbbc6986c13" CreationDate="2018-06-22T01:29:06.027" UserId="7462" Text="I am trying to make a particular kind of raytracer, but there is some strange bug occurring when I attempt to [rotate the camera][1].&#xD;&#xA;&#xD;&#xA;As you can see, there is some important distortion ocurring when the voxels are closed to the camera and I am not sure what may be cuasing it.&#xD;&#xA;&#xD;&#xA;This is how I am calculating my ray:&#xD;&#xA;&#xD;&#xA;    vec3 r = (vec3(f_coord.xy,1.f/tan(radians(40)))) //initialize the ray for a field of view of 40, f_coord is the pizel coordinate in OpenGL (-1 to 1);&#xD;&#xA;    r.y /= aspect_ratio // crunch the y direction to fit the aspect ratio;&#xD;&#xA;    vec3 dir = vec3(view_m*vec4(normalize(r),1)); //rotate the ray by the camera's rotation&#xD;&#xA;    r+= camera_pos; //Set the ray at the camera's position&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/YqJKh0ntMr4" ContentLicense="CC BY-SA 4.0" />
  <row Id="20164" PostHistoryTypeId="1" PostId="7735" RevisionGUID="e3cfa5fb-6cc8-4e83-a567-bdbbc6986c13" CreationDate="2018-06-22T01:29:06.027" UserId="7462" Text="How to properly modify a ray in a raytracer to achieve camera rotation" ContentLicense="CC BY-SA 4.0" />
  <row Id="20165" PostHistoryTypeId="3" PostId="7735" RevisionGUID="e3cfa5fb-6cc8-4e83-a567-bdbbc6986c13" CreationDate="2018-06-22T01:29:06.027" UserId="7462" Text="|opengl|raytracing|glsl|voxelization|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20166" PostHistoryTypeId="5" PostId="7734" RevisionGUID="586eac25-02ec-49cf-867d-910273c3057d" CreationDate="2018-06-22T01:31:19.247" UserId="4837" Comment="added 176 characters in body" Text="Recently I ran into an odd issue with some of my DirectX11 DirectCompute code &#xD;&#xA;when trying it on an AMD GPU for the first time (specifically a Radeon RX 580, the rest of the development was done on a NVIDIA GeForce GTX 960). The fact that this only appeared on AMD either means that NVIDIA GPUs are more resistant to the issue or perhaps something about them such as a different wavefront size is not triggering the issue, or that it's not even an problem with my code and instead is a bug somewhere along the pipeline (driver, GPU itself, etc) for AMD things.&#xD;&#xA;&#xD;&#xA;The general setup of the issue can be represented by the following pseudocode which I turned into a minimal test application to confirms the problem indeed exists to ensure nothing else in the other much larger codebase was causing the issues:&#xD;&#xA;&#xD;&#xA;    if (condition) {&#xD;&#xA;      globalArray[i].first = value &#xD;&#xA;    } else {&#xD;&#xA;      globalArray[i].second = value&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    InterlockedExchange(globalArray[i].flag, true, oldFlag)&#xD;&#xA;    &#xD;&#xA;    if (!oldFlag) {&#xD;&#xA;      return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if (condition) {&#xD;&#xA;      new_value = globalArray[i].second&#xD;&#xA;    } else {&#xD;&#xA;      new_value = globalArray[i].first&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With this setup, an example of its functionality would be best represented by 2 threads executing this code (the important bit being that they may not be within the same work group, more on this later), one with `condition` set to true and one with it set to false. Next, each thread sets the value they possess into a global buffer (both threads have the same index `i`) in the `first` and `second` slots of a structure. The interlocked exchange operation which follows attempts to set the flag (also stored in global memory) to true, allowing only one of the two threads to proceed (one will see that the flag was not set beforehand, meaning it was the first to set it and return). Finally, the remaining thread can now make the assumption that both `first` and `second` values have been set (as the other now terminated thread has already set the atomic which ensures this), allowing it to read the value written by the other thread to `new_value` (based on the condition once again).&#xD;&#xA;&#xD;&#xA;From a more higher level perspective, this code simply allows two arbitrary threads to combine their information into one which continues on, all through global memory.&#xD;&#xA;&#xD;&#xA;The issue I observed however was that very rarely (only seen in about 1 in a million cases), `new_value` would be set to something uninitialized, implying that the data it read from in the global array was. This however is confusing as the fact that the atomic flag is set should ensure that the value has been written to the proper location by the other thread. I thought perhaps that the atomic operation finished before the full write to the first/second value did for whatever reason and added a `DeviceMemoryBarrier` after the value write but before the atomic exchange, but that also had no effect.&#xD;&#xA;&#xD;&#xA;This behavior leads me to believe that it is something bizarre which is happening so rarely due to unlikely circumstances, such as threads from different wavefronts running into eachother at the exact same time as mentioned previously which should in theory work fine, but something such as caching preventing the writes from being seen properly. This further is strengthened by my testing which purposely collides threads together from random wavefronts, causing the issue to arise most frequently when the number of values to process is around 100,000 whereas counts too small have no effect and counts well into the millions do not either, likely as fewer threads are colliding at the proper exact time due to it being much more unlikely (even still, it sometimes takes 100+ iterations of the same test repeated to invoke the issue with 100,000 values). Most of that is simply speculation though since I do not know too much about the specifics of how GPU memory hierarchies function. Another possibility is that this kind of behavior simply isn't guaranteed by DirectCompute and I am using it incorrectly, though DirectX's documentation is very lacking on actual in-depth descriptions of functionality for intrinsics like `InterlockedExchange`, so I am not sure what to think. As mentioned before I have also considered it being an issue with something AMD related since it does not appear to happen ever on the NVIDIA card I have.&#xD;&#xA;&#xD;&#xA;Does anyone know why this might happen and what I can do to fix it? If it'd help, I can also make the proof of concept test application I made available to show a more specific example of the problem occurring (since the pseudocode did leave out a lot of &quot;irrelevant&quot; details which may actually be significant)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20167" PostHistoryTypeId="2" PostId="7736" RevisionGUID="2846f16b-638a-42fb-ba78-73cf0340a8af" CreationDate="2018-06-22T06:11:17.060" UserId="7008" Text="There are several major Computer Graphics publications that have a jobs section. Try [Siggraph][1] for example. I'm pretty sure I saw a similar thing for [Eurographics][2], but I can't find it right now.&#xD;&#xA;Furthermore, you can look for applicants at the conferences themselves, if you have the resources to do so.&#xD;&#xA;&#xD;&#xA;If you accept students that just finish university, you should put up an ad there (or tell the computer graphics professor to spread the word - my professor was kind enough to distribute offers to us every now and then).&#xD;&#xA;Apart from that, you'll probably find most graphics programmers in computer games related fields. Gamasutra has a [jobs section][3], although I'm not sure they let non-games related companies advertise there.&#xD;&#xA;&#xD;&#xA;Moreover, Stackoverflow has a job offers section. I never really used it myself, but it's probably worth looking into. I got quite a few computer graphics related offers, so my guess is that you can advertise specifically to people with tags like *OpenGL* and *Rendering* as their favourite tags.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.siggraph.org/job-board&#xD;&#xA;  [2]: https://www.eg.org/wp/&#xD;&#xA;  [3]: http://jobs.gamasutra.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20168" PostHistoryTypeId="36" PostId="7737" RevisionGUID="44b67cf1-063d-41ed-bb5b-f6c53b76b59d" CreationDate="2018-06-22T09:58:18.353" UserId="-1" Comment="from https://stackoverflow.com/questions/50984260/bokeh-from-depth-map" />
  <row Id="20169" PostHistoryTypeId="2" PostId="7737" RevisionGUID="d7b0b3d5-5ca6-4e12-90a5-11568978221f" CreationDate="2018-06-22T08:55:40.817" UserId="8748" Text="How do I generate bokeh that simulates shallow depth of field given a perfect depth map?&#xD;&#xA;&#xD;&#xA;Here's what I tried: &#xD;&#xA;&#xD;&#xA;1. Generated a sample scene using blender and corresponding depth map&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;2. Generated what sigma to use at each pixel for gaussian blurring: This one makes it look like the far end of the pink cube is perfectly focused.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;_black = 0, no blur; white = 255, large blur_&#xD;&#xA;&#xD;&#xA;3. Applied gaussian blurring at every pixel and this is what I got&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Flaws observed: Averaging kernels just near the edges are taking in the pink color nearby hence the pink bleed. **How do I avoid this?**&#xD;&#xA;&#xD;&#xA;Note: It's not completely blurred look closely at the zoomed in image on the right. The pixels that I wanted to remain untouched are still untouched (even though it appears they were blurred as well because of the blurring near the edges)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This [blog](https://ai.googleblog.com/2017/10/portrait-mode-on-pixel-2-and-pixel-2-xl.html?m=1) on Portrait mode on Pixel 2 says, &quot;Actually applying the blur is conceptually the simplest part&quot;, **is there any simpler way of doing it then?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AC8vN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Q25t3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Ll8N6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20170" PostHistoryTypeId="1" PostId="7737" RevisionGUID="d7b0b3d5-5ca6-4e12-90a5-11568978221f" CreationDate="2018-06-22T08:55:40.817" UserId="8748" Text="Bokeh from depth map" ContentLicense="CC BY-SA 4.0" />
  <row Id="20171" PostHistoryTypeId="3" PostId="7737" RevisionGUID="d7b0b3d5-5ca6-4e12-90a5-11568978221f" CreationDate="2018-06-22T08:55:40.817" UserId="8748" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20172" PostHistoryTypeId="2" PostId="7738" RevisionGUID="16ce09ec-08a2-4fda-aae3-54851cddaaa5" CreationDate="2018-06-22T10:42:50.440" UserId="6041" Text="Below is a triangle with its vertices and uv coordinates. These are read from&#xD;&#xA;the input model file. &#xD;&#xA;&#xD;&#xA;I don't understand why the texture comes in different orientation than the image.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;here is the method to calculate uv coordinate for the hit point(ray-triangle code from Moller, Trumbore):&#xD;&#xA;&#xD;&#xA;         public bool GetIntersection(Vector rayOrigin, Vector rayDirection, ref &#xD;&#xA;                  float hitDistance, out Vector uv)&#xD;&#xA;        {&#xD;&#xA;            uv = null;&#xD;&#xA;&#xD;&#xA;            // begin calculating determinant - also used to calculate U parameter&#xD;&#xA;            Vector pvec = rayDirection.Cross(edge2);&#xD;&#xA;&#xD;&#xA;            // if determinant is near zero, ray lies in plane of triangle&#xD;&#xA;            float det = edge1.Dot(pvec);&#xD;&#xA;&#xD;&#xA;            const float EPSILON = 0.000001f;&#xD;&#xA;            if ((det &gt; -EPSILON) &amp;&amp; (det &lt; EPSILON))&#xD;&#xA;                return false;&#xD;&#xA;&#xD;&#xA;            float inv_det = 1.0f / det;&#xD;&#xA;&#xD;&#xA;            // calculate distance from vertex 0 to ray origin&#xD;&#xA;            Vector tvec = rayOrigin - verts[0];&#xD;&#xA;&#xD;&#xA;            // calculate U parameter and test bounds&#xD;&#xA;            float u = tvec.Dot(pvec) * inv_det;&#xD;&#xA;            if ((u &lt; 0.0f) || (u &gt; 1.0f))&#xD;&#xA;                return false;&#xD;&#xA;&#xD;&#xA;            // prepare to test V parameter&#xD;&#xA;            Vector qvec = tvec.Cross(edge1);&#xD;&#xA;&#xD;&#xA;            // calculate V parameter and test bounds&#xD;&#xA;            float v = rayDirection.Dot(qvec) * inv_det;&#xD;&#xA;            if ((v &lt; 0.0f) || (u + v &gt; 1.0f))&#xD;&#xA;                return false;&#xD;&#xA;&#xD;&#xA;            Vector uvHit = uvVectors[0] * u + uvVectors[1] * v + uvVectors[2] * (1 - u - v);&#xD;&#xA;            uv = new Vector(uvHit[0], uvHit[1], 0);&#xD;&#xA;&#xD;&#xA;            // calculate t, ray intersects triangle&#xD;&#xA;            hitDistance = edge2.Dot(qvec) * inv_det;&#xD;&#xA;&#xD;&#xA;            // only allow intersections in the forward ray direction&#xD;&#xA;            return hitDistance &gt;= 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;And here is the method in ImageTexture class to convert the hit point uv coordinate:&#xD;&#xA;&#xD;&#xA;        public Vector Interpolate(Vector uv)&#xD;&#xA;        {&#xD;&#xA;            float u = uv[0] - (float)Math.Floor(uv[0]);&#xD;&#xA;            float v = uv[1] - (float)Math.Floor(uv[1]);&#xD;&#xA;            u *= bmp.Width - 1;&#xD;&#xA;            v *= bmp.Height - 1;&#xD;&#xA;&#xD;&#xA;            Color cuv = bmp.GetPixel((int)u, (int)v);&#xD;&#xA;&#xD;&#xA;            return new Vector(cuv.R, cuv.G, cuv.B);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Also how are the uv coordinates that come from the input model are supposed to be calculated? If this is a big mesh(a terrain) with many triangles how is the uv coordinates for each triangle vertex is calculated?&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GRZtO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XBtzs.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20173" PostHistoryTypeId="1" PostId="7738" RevisionGUID="16ce09ec-08a2-4fda-aae3-54851cddaaa5" CreationDate="2018-06-22T10:42:50.440" UserId="6041" Text="How to assign/calculate triangle texture coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="20174" PostHistoryTypeId="3" PostId="7738" RevisionGUID="16ce09ec-08a2-4fda-aae3-54851cddaaa5" CreationDate="2018-06-22T10:42:50.440" UserId="6041" Text="|raytracing|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20175" PostHistoryTypeId="6" PostId="7737" RevisionGUID="d05d37bf-52c2-420c-a03b-a0e9e9128130" CreationDate="2018-06-22T10:57:26.887" UserId="2041" Comment="Add some relevant tags after the migration" Text="|blur|depth-map|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20176" PostHistoryTypeId="5" PostId="7737" RevisionGUID="c9c6add8-bdd7-4350-8b88-56f72f643b6c" CreationDate="2018-06-22T13:54:37.510" UserId="8748" Comment="added 189 characters in body; edited tags" Text="How do I generate bokeh that simulates shallow depth of field given a perfect depth map?&#xD;&#xA;&#xD;&#xA;Here's what I tried: &#xD;&#xA;&#xD;&#xA;1. Generated a sample scene using blender and corresponding depth map&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;2. Using Python, generated what sigma (standard deviation) to use at each pixel for gaussian blurring: This one makes it look like the far end of the pink cube is perfectly focused.&#xD;&#xA;&#xD;&#xA;        sigma_map = np.array(np.round(abs(np.array(depth, dtype='float32') - preferred_focus_depth)).clip(0,255), dtype='uint8')&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;_black = 0, no blur; white = 255, large blur_&#xD;&#xA;&#xD;&#xA;3. Applied gaussian blurring (using the sigma_map) at every pixel and this is what I got&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Flaws observed: Averaging kernels just near the edges are taking in the pink color nearby hence the pink bleed. **How do I avoid this?**&#xD;&#xA;&#xD;&#xA;Note: It's not completely blurred look closely at the zoomed in image on the right. The pixels that I wanted to remain untouched are still untouched (even though it appears they were blurred as well because of the blurring near the edges)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This [blog](https://ai.googleblog.com/2017/10/portrait-mode-on-pixel-2-and-pixel-2-xl.html?m=1) on Portrait mode on Pixel 2 says, &quot;Actually applying the blur is conceptually the simplest part&quot;, **is there any simpler way of doing it then?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AC8vN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Q25t3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Ll8N6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20177" PostHistoryTypeId="6" PostId="7737" RevisionGUID="c9c6add8-bdd7-4350-8b88-56f72f643b6c" CreationDate="2018-06-22T13:54:37.510" UserId="8748" Comment="added 189 characters in body; edited tags" Text="|gaussian-blur|blur|depth-map|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20178" PostHistoryTypeId="2" PostId="7739" RevisionGUID="53ced212-08b7-4c19-9037-bada80580177" CreationDate="2018-06-22T23:45:07.037" UserId="7462" Text="I have a wavefront loader, however it only works with triangular meshes.&#xD;&#xA;&#xD;&#xA;I have been trying to think how to handle faces with arbitrarily many vertices but I have no idea how they are to be handled as ultimately everything needs to be given to the GPU as triangles and I cannot think fo a way to mape any arbitrary n-gon to triangles.&#xD;&#xA;&#xD;&#xA;Like I know how to converte a quadrilateral to two triangles, but my way won't work for quintalaterals for example." ContentLicense="CC BY-SA 4.0" />
  <row Id="20179" PostHistoryTypeId="1" PostId="7739" RevisionGUID="53ced212-08b7-4c19-9037-bada80580177" CreationDate="2018-06-22T23:45:07.037" UserId="7462" Text="How are non-trianglur wavefront emshes handled?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20180" PostHistoryTypeId="3" PostId="7739" RevisionGUID="53ced212-08b7-4c19-9037-bada80580177" CreationDate="2018-06-22T23:45:07.037" UserId="7462" Text="|algorithm|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20181" PostHistoryTypeId="4" PostId="7739" RevisionGUID="d1a47f3d-8042-472a-a151-8f80f7e8aa84" CreationDate="2018-06-22T23:50:22.000" UserId="7462" Comment="edited title" Text="How are non-triangular wavefront emshes handled?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20185" PostHistoryTypeId="2" PostId="7741" RevisionGUID="eaa23acd-7789-481a-b61f-29babd03943a" CreationDate="2018-06-22T23:56:44.777" UserId="4908" Text="The blog post that you talked about, is not about generating bokeh for a computer generated image. It is instead about generating a believable depth of field effect from an image captured by a smartphone camera, as the effect is desired for portraits to make the subject stand out. It generally works by splitting the image in to two parts. One part is the subject, which should not be blurred. The other part is the background, which should be blurred but the pixels of the subject should have no influence and would thus have a weight of zero. Slightly more sophisticated algorithms may make the blur kernel size variable across an image to create a smoother transition, but the subject's pixels would still be ignored.&#xD;&#xA;&#xD;&#xA;In games and CGI, post process depth of field is done differently. There are multiple ways for it. A simple google search shows multiple. You could do depth of field like you have, and simply ignore the pixels which should not be blurred to remove the ghosting. However, this is not true to how depth of field occurs inside of a camera. So, in order to get a good algorithm to simulate depth of field, I will first try to explain how you get the depth of field effect in an actual camera.&#xD;&#xA;&#xD;&#xA;Let us say, that we have an object, a single lens and an image sensor. We look at them from the side.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Light scatters in many different directions when hitting the object. To simplify we only take one point. From this point, I will show the light that would hit the lens as a gray solid.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;The lens bends the light towards a single point. That is the focal point.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;You can see that the focal point is in front of the sensor. This causes the light from that single point on the object, to fall on a large portion of the sensor. If the focal point is behind the sensor, the same would happen. But, if the focal point lies on the sensor, there would only be one point on the sensor where the light falls on. This area where the light falls on the sensor, is called the circle of confusion (CoC). This is also the cause of the depth of field effect.&#xD;&#xA;&#xD;&#xA;One important thing to know, is that when the point on the object moves around, the focal point also moves around. If the point moves closer to the lens, the focal point moves closer to the lens, which would alter the size of the circle of confusion. This gives you the gradual change in blurriness that you have with depth of field, since the circle of confusion gradually becomes larger when an object moves away from the area in focus.&#xD;&#xA;&#xD;&#xA;If we add in an aperture we simply block out a part of the light, which causes the circle of confusion to be smaller. This allows us to determine how much light to let in (to make the image brighter or darker), and how strong the depth of field effect is.&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;From this, we can conclude a few things on how we should implement depth of field.&#xD;&#xA;&#xD;&#xA; - Every point whose light enters the camera lens, has a circle of confusion.&#xD;&#xA; - The circle of confusion is the area where the light, from that point, falls on.&#xD;&#xA; - The circle of confusion changes size when the point moves closer to or further away from the lens, or when the aperture changes size.&#xD;&#xA; - The area of the circle of confusion has no falloff. Every point inside the circle of confusion has the same weight. This results in a box blur.&#xD;&#xA; - If a point is in focus, its circle of confusion would be either zero or something so small, that it is not noticed.&#xD;&#xA;&#xD;&#xA;The algorithm is quite simple. For each pixel in the image, we use the depth to calculate the circle of confusion. Then, we add the colour of that pixel to all the other pixels that lie in the circle of confusion. However, if that other pixel is closer to the camera (a lower depth value), it would block the light from our pixel, and we should not add the colour of our pixel to the blocking pixel.&#xD;&#xA;&#xD;&#xA;In pseudo code it would look something like this;&#xD;&#xA;&#xD;&#xA;    for(x = 0; x &lt; width; x++){&#xD;&#xA;        for(y = 0; y &lt; height; y++){&#xD;&#xA;            // How much blur? Zero or close to it if it should be in focus.&#xD;&#xA;            float CoCRadius = calcCoCRadius(depth(x, y));&#xD;&#xA;            // Every pixel in the square with the size of CoCRadius.&#xD;&#xA;            for(i = x - CoCRadius; i &lt;= x + CoCRadius; i++){&#xD;&#xA;                for(j = y - CoCRadius; j &lt;= y + CoCRadius; j++){&#xD;&#xA;                    // Discard pixels outside of the shape. Square -&gt; Circle&#xD;&#xA;                    if(isInBokehShape(i - x, j - y)){&#xD;&#xA;                        // Discard pixels that would block it.&#xD;&#xA;                        if(depth(i, j) &gt;= depth(x, y){&#xD;&#xA;                            // Add the colour.&#xD;&#xA;                            newColour[i, j] += colour(x, y);&#xD;&#xA;                            // Add the weight, for normalizing.&#xD;&#xA;                            weight[i, j] += 1.0f;&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    //Normalize the values with the weight.&#xD;&#xA;    for(x = 0; x &lt; width; x++){&#xD;&#xA;        for(y = 0; y &lt; height; y++){&#xD;&#xA;            newColour[x, y] /= weight[x, y];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;This would give you a depth of field effect that is quite true, and does not give you the ghosting effect. $calcCoCRadius$ is a method that calculates the radius in pixels of the circle of confusion. It could be anything, but if you want it as true to an actual camera, then you can use the formula from [this Wikipedia page][5]. $isInBokehShape$ is a method which returns a boolean on whether the point is inside the bokeh shape. With the two for loops we just get a square, but if we want to get a circle shaped bokeh, we need to discard the pixels that would lie outside of the circle. This discarding is also the reason why we keep track of the weights and normalize afterwards with the weight, since we do not know how many pixels we need to discard. The weight is also useful if you do want a falloff in the circle of confusion, for example if you want a gaussian blur.&#xD;&#xA;&#xD;&#xA;Another important thing to know, is that the implementation listed here, is not very optimal. The problem is basically that you write to multiple different pixels. This causes race conditions. Instead, it is better to rework the algorithm so that you only need one write. Basically, you loop through every pixel and you then you check all other pixels (or pixels inside of a maximum CoC radius) whether their CoC radius is large enough that they contribute to the pixel's colour. This way, you can also put the normalizing of the values inside the first loop over all the pixels instead of having to do that later.&#xD;&#xA;&#xD;&#xA;This should be a fairy good way of implementing depth of field as a post processing effect. There are also other ways, but this is one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aud9f.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FK7bL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZD9BY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/sxmta.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Circle_of_confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="20186" PostHistoryTypeId="4" PostId="7739" RevisionGUID="0ca33041-471e-43db-b6b9-a3134539c80d" CreationDate="2018-06-23T00:19:09.657" UserId="7462" Comment="edited title" Text="How are non-triangular wavefront meshes handled?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20187" PostHistoryTypeId="5" PostId="7739" RevisionGUID="0ca33041-471e-43db-b6b9-a3134539c80d" CreationDate="2018-06-23T00:19:09.657" UserId="7462" Comment="edited title" Text="I have a wavefront loader, however it only works with triangular meshes.&#xD;&#xA;&#xD;&#xA;I have been trying to think how to handle faces with arbitrarily many vertices but I have no idea how they are to be handled as ultimately everything needs to be given to the GPU as triangles and I cannot think fo a way to mape any arbitrary n-gon to triangles.&#xD;&#xA;&#xD;&#xA;Like I know how to convert a quadrilateral to two triangles, but my way won't work for quintalaterals for example." ContentLicense="CC BY-SA 4.0" />
  <row Id="20188" PostHistoryTypeId="5" PostId="7734" RevisionGUID="1ae6acaa-d14d-4b2b-8df5-cb2c9ad421d6" CreationDate="2018-06-23T00:31:21.747" UserId="4837" Comment="Add more testing results." Text="Recently I ran into an odd issue with some of my DirectX11 DirectCompute code &#xD;&#xA;when trying it on an AMD GPU for the first time where as on a NVIDIA one it had worked fine all through development. The fact that this only appeared on AMD either means that NVIDIA GPUs are more resistant to the issue or perhaps something about them such as a different wavefront size is not triggering the issue, or that it's not even an problem with my code and instead is a bug somewhere along the pipeline (driver, GPU itself, etc) for AMD things. After further testing however, it did appear to work on another more modern AMD card (the Vega 56), though this may be because it was running on Windows 7, using Feature set 11 instead of 11.1, or because the GCN 5 architecture (or its drivers) somehow fixed this issue.&#xD;&#xA;&#xD;&#xA;A summary of the GPUs tested is as follows:&#xD;&#xA;&#xD;&#xA; - NVIDIA GeForce GTX 960, Feature Set 11.1, Windows 10 (Ok)&#xD;&#xA; - NVIDIA GeForce GTX 1060, Feature Set 11.1, Windows 10 (Ok)&#xD;&#xA; - Radeon RX 580, Feature Set 11.1, Windows 10 (Fail)&#xD;&#xA; - Radeon RX Vega 56, Feature Set 11, Windows 7 (Ok)&#xD;&#xA;&#xD;&#xA;The general setup of the issue can be represented by the following pseudocode which I turned into a minimal test application to confirms the problem indeed exists to ensure nothing else in the other much larger codebase was causing the issues:&#xD;&#xA;&#xD;&#xA;    if (condition) {&#xD;&#xA;      globalArray[i].first = value &#xD;&#xA;    } else {&#xD;&#xA;      globalArray[i].second = value&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    InterlockedExchange(globalArray[i].flag, true, oldFlag)&#xD;&#xA;    &#xD;&#xA;    if (!oldFlag) {&#xD;&#xA;      return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if (condition) {&#xD;&#xA;      new_value = globalArray[i].second&#xD;&#xA;    } else {&#xD;&#xA;      new_value = globalArray[i].first&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With this setup, an example of its functionality would be best represented by 2 threads executing this code (the important bit being that they may not be within the same work group, more on this later), one with `condition` set to true and one with it set to false. Next, each thread sets the value they possess into a global buffer (both threads have the same index `i`) in the `first` and `second` slots of a structure. The interlocked exchange operation which follows attempts to set the flag (also stored in global memory) to true, allowing only one of the two threads to proceed (one will see that the flag was not set beforehand, meaning it was the first to set it and return). Finally, the remaining thread can now make the assumption that both `first` and `second` values have been set (as the other now terminated thread has already set the atomic which ensures this), allowing it to read the value written by the other thread to `new_value` (based on the condition once again).&#xD;&#xA;&#xD;&#xA;From a more higher level perspective, this code simply allows two arbitrary threads to combine their information into one which continues on, all through global memory.&#xD;&#xA;&#xD;&#xA;The issue I observed however was that very rarely (only seen in about 1 in a million cases), `new_value` would be set to something uninitialized, implying that the data it read from in the global array was. This however is confusing as the fact that the atomic flag is set should ensure that the value has been written to the proper location by the other thread. I thought perhaps that the atomic operation finished before the full write to the first/second value did for whatever reason and added a `DeviceMemoryBarrier` after the value write but before the atomic exchange, but that also had no effect.&#xD;&#xA;&#xD;&#xA;This behavior leads me to believe that it is something bizarre which is happening so rarely due to unlikely circumstances, such as threads from different wavefronts running into eachother at the exact same time as mentioned previously which should in theory work fine, but something such as caching preventing the writes from being seen properly. This further is strengthened by my testing which purposely collides threads together from random wavefronts, causing the issue to arise most frequently when the number of values to process is around 100,000 whereas counts too small have no effect and counts well into the millions do not either, likely as fewer threads are colliding at the proper exact time due to it being much more unlikely (even still, it sometimes takes 100+ iterations of the same test repeated to invoke the issue with 100,000 values). Most of that is simply speculation though since I do not know too much about the specifics of how GPU memory hierarchies function. Another possibility is that this kind of behavior simply isn't guaranteed by DirectCompute and I am using it incorrectly, though DirectX's documentation is very lacking on actual in-depth descriptions of functionality for intrinsics like `InterlockedExchange`, so I am not sure what to think.&#xD;&#xA;&#xD;&#xA;Does anyone know why this might happen and what I can do to fix it? If it'd help, I can also make the proof of concept test application I made available to show a more specific example of the problem occurring (since the pseudocode did leave out a lot of &quot;irrelevant&quot; details which may actually be significant)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20189" PostHistoryTypeId="2" PostId="7742" RevisionGUID="016f3151-bf48-44f6-8dbe-6c874ac48eb6" CreationDate="2018-06-23T01:28:20.373" UserId="3003" Text="Does the effect need to be physically accurate? I've implemented this using a cheat before. @bram0101's answer is great. If you need accuracy, then by all means, implement that. I've been able to get something convincing to the eye by simply doing a threshold of the luminance of the image and placing a semi-transparent polygon or circle centered at every point that's above the threshold." ContentLicense="CC BY-SA 4.0" />
  <row Id="20193" PostHistoryTypeId="2" PostId="7744" RevisionGUID="46420114-33d9-48a8-9af7-bc8f8b6ac15b" CreationDate="2018-06-23T15:35:55.327" UserId="8920" Text="I am writing a raytracer in F# using montecarlo sampling&#xD;&#xA;I would like to make my recursive calls tail recursive but I am not sure of this is possible with MC raytracing as one has to evaluate sampled hemisphere before returning.&#xD;&#xA;&#xD;&#xA;The accululator variables are there to facilitate the tail recursion and works for naiive raytracers which just trace along a single ray until it terminates.&#xD;&#xA;At the moment the problem is the for loop.&#xD;&#xA;&#xD;&#xA;Any help / pointers / references I can read would be appreciated&#xD;&#xA;&#xD;&#xA;Currently my code looks as follows:&#xD;&#xA;&#xD;&#xA;            if surfaceGeometry.IntersectionAcceptable realSolution t 1.0f (PointForRay ray t)&#xD;&#xA;            then&#xD;&#xA;                let emittedShading = surface.Emitted&#xD;&#xA;                let e = accEmitted + accScatter*emittedShading &#xD;&#xA;                let mcSamples = surface.SampleCount&#xD;&#xA;                &#xD;&#xA;                //TODO rewrite this to make it tail recursive&#xD;&#xA;                let mutable totalShading = e/surface.MCNormalization&#xD;&#xA;                for _ in 0..mcSamples-1 do&#xD;&#xA;                    let (doesRayContribute,outRay,cosOfIncidence) = surface.Scatter ray t ((int)newTraceDepth)&#xD;&#xA;                    let shading = surface.BRDF*cosOfIncidence / (surface.PDF*surface.MCNormalization)&#xD;&#xA;                    let s = accScatter*shading&#xD;&#xA;                    totalShading &lt;- totalShading + (rayTrace newTraceDepth (outRay , e , s))&#xD;&#xA;                totalShading&#xD;&#xA;            else &#xD;&#xA;               accEmitted + backgroundColor*accScatter&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20194" PostHistoryTypeId="1" PostId="7744" RevisionGUID="46420114-33d9-48a8-9af7-bc8f8b6ac15b" CreationDate="2018-06-23T15:35:55.327" UserId="8920" Text="Tail Recursive Monte Carlo Raytracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="20195" PostHistoryTypeId="3" PostId="7744" RevisionGUID="46420114-33d9-48a8-9af7-bc8f8b6ac15b" CreationDate="2018-06-23T15:35:55.327" UserId="8920" Text="|raytracing|rendering|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20196" PostHistoryTypeId="5" PostId="7742" RevisionGUID="90b9dda0-8992-4600-a7d5-01542fdeb12c" CreationDate="2018-06-23T16:18:00.870" UserId="3003" Comment="Added note about distance from focal plane." Text="Does the effect need to be physically accurate? I've implemented this using a cheat before. @bram0101's answer is great. If you need accuracy, then by all means, implement that. I've been able to get something convincing to the eye by simply doing a threshold of the luminance of the image and placing a semi-transparent polygon or circle centered at every point that's above the threshold.&#xD;&#xA;&#xD;&#xA;You also need to take into account distance from the focal plane. The distance can be used to control the size of the bokeh, with the size being 0 at the focal plane, and some maximum size at some farther distance." ContentLicense="CC BY-SA 4.0" />
  <row Id="20197" PostHistoryTypeId="2" PostId="7745" RevisionGUID="576db688-e560-4cab-b9bb-02bae21e84af" CreationDate="2018-06-23T20:32:13.223" UserId="6046" Text="so I am currently in the middle of implementing a path tracer for my bachelor thesis. And so far I have understood and mapped the general flow of the program except for 2 things. Note that I'm using OpenCL and will be using OpenGL-OpenCL interop for rendering the path traced image to the window created by openGL.&#xD;&#xA;&#xD;&#xA;Ok so here are my questions.&#xD;&#xA;&#xD;&#xA;**1)**  First of all, I know that GPU memory is quite limited as compared to the CPU and it's one of the reasons we don't see GPU path tracers that much in professional industries like Film industry etc. &#xD;&#xA;&#xD;&#xA;What I am interested in, is there any way to know the exact amount of memory available?&#xD;&#xA;&#xD;&#xA;I'll be loading model files and sending this whole model data to the GPU probably in a data structure (K-D tree etc). Now these models will probably contain millions of triangles. **How is the GPU supposed to store that much amount of data? Or is there any other efficient way of doing this?**&#xD;&#xA;&#xD;&#xA;Secondly I also read that accesses to global memory within a work-group can be coalesced/combined if they are done at the same time. So I was thinking to use a memory barrier and once all the work items have reached it, I can copy the whole K-D tree from global to local memory for faster processing ofcourse. &#xD;&#xA;&#xD;&#xA;**Again can the local memory hold such amount of data?**&#xD;&#xA;&#xD;&#xA;**2)** The second part I'm confused with is that, you usually hear that you turn on the path tracer and leave it for a few minutes and the Image gradually starts looking better and better as the samples are increased. &#xD;&#xA;&#xD;&#xA;I don't understand yet, how should I be implementing this feature from coding point of view.&#xD;&#xA;&#xD;&#xA;As far as I have planned out, there will be a single main kernel that will loop over the Image (shared between openGL and openCL) sending out a fixed number of rays (suppose 8) per pixel. After this kernel finish executing I can either blit the opengl FBO to the default or draw the texture on quads whichever is faster.&#xD;&#xA;&#xD;&#xA;**But all of this is just one instance. How can I gradually improve my image by increasing samples (1,2,4,8,16...) and each time blit the FBO to the default FB?**&#xD;&#xA;&#xD;&#xA;The only thing I can think of at this moment is to relaunch the kernel, compute a new color value for a specified pixel and then take the average of this new one and the old one. Is this feasible or is there a better approach? " ContentLicense="CC BY-SA 4.0" />
  <row Id="20198" PostHistoryTypeId="1" PostId="7745" RevisionGUID="576db688-e560-4cab-b9bb-02bae21e84af" CreationDate="2018-06-23T20:32:13.223" UserId="6046" Text="Path Tracer - implementation questions" ContentLicense="CC BY-SA 4.0" />
  <row Id="20199" PostHistoryTypeId="3" PostId="7745" RevisionGUID="576db688-e560-4cab-b9bb-02bae21e84af" CreationDate="2018-06-23T20:32:13.223" UserId="6046" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20200" PostHistoryTypeId="5" PostId="7741" RevisionGUID="f49055b0-5706-4521-8ce8-5c0ba909c5ff" CreationDate="2018-06-23T21:10:21.280" UserId="8748" Comment="depth(x-i, y-j)" Text="The blog post that you talked about, is not about generating bokeh for a computer generated image. It is instead about generating a believable depth of field effect from an image captured by a smartphone camera, as the effect is desired for portraits to make the subject stand out. It generally works by splitting the image in to two parts. One part is the subject, which should not be blurred. The other part is the background, which should be blurred but the pixels of the subject should have no influence and would thus have a weight of zero. Slightly more sophisticated algorithms may make the blur kernel size variable across an image to create a smoother transition, but the subject's pixels would still be ignored.&#xD;&#xA;&#xD;&#xA;In games and CGI, post process depth of field is done differently. There are multiple ways for it. A simple google search shows multiple. You could do depth of field like you have, and simply ignore the pixels which should not be blurred to remove the ghosting. However, this is not true to how depth of field occurs inside of a camera. So, in order to get a good algorithm to simulate depth of field, I will first try to explain how you get the depth of field effect in an actual camera.&#xD;&#xA;&#xD;&#xA;Let us say, that we have an object, a single lens and an image sensor. We look at them from the side.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Light scatters in many different directions when hitting the object. To simplify we only take one point. From this point, I will show the light that would hit the lens as a gray solid.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;The lens bends the light towards a single point. That is the focal point.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;You can see that the focal point is in front of the sensor. This causes the light from that single point on the object, to fall on a large portion of the sensor. If the focal point is behind the sensor, the same would happen. But, if the focal point lies on the sensor, there would only be one point on the sensor where the light falls on. This area where the light falls on the sensor, is called the circle of confusion (CoC). This is also the cause of the depth of field effect.&#xD;&#xA;&#xD;&#xA;One important thing to know, is that when the point on the object moves around, the focal point also moves around. If the point moves closer to the lens, the focal point moves closer to the lens, which would alter the size of the circle of confusion. This gives you the gradual change in blurriness that you have with depth of field, since the circle of confusion gradually becomes larger when an object moves away from the area in focus.&#xD;&#xA;&#xD;&#xA;If we add in an aperture we simply block out a part of the light, which causes the circle of confusion to be smaller. This allows us to determine how much light to let in (to make the image brighter or darker), and how strong the depth of field effect is.&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;From this, we can conclude a few things on how we should implement depth of field.&#xD;&#xA;&#xD;&#xA; - Every point whose light enters the camera lens, has a circle of confusion.&#xD;&#xA; - The circle of confusion is the area where the light, from that point, falls on.&#xD;&#xA; - The circle of confusion changes size when the point moves closer to or further away from the lens, or when the aperture changes size.&#xD;&#xA; - The area of the circle of confusion has no falloff. Every point inside the circle of confusion has the same weight. This results in a box blur.&#xD;&#xA; - If a point is in focus, its circle of confusion would be either zero or something so small, that it is not noticed.&#xD;&#xA;&#xD;&#xA;The algorithm is quite simple. For each pixel in the image, we use the depth to calculate the circle of confusion. Then, we add the colour of that pixel to all the other pixels that lie in the circle of confusion. However, if that other pixel is closer to the camera (a lower depth value), it would block the light from our pixel, and we should not add the colour of our pixel to the blocking pixel.&#xD;&#xA;&#xD;&#xA;In pseudo code it would look something like this;&#xD;&#xA;&#xD;&#xA;    // for each pixel in the all-focus image&#xD;&#xA;    for(x = 0; x &lt; width; x++){&#xD;&#xA;        for(y = 0; y &lt; height; y++){&#xD;&#xA;            // How much blur? Zero or close to it if it should be in focus.&#xD;&#xA;            float CoCRadius = calcCoCRadius(depth(x, y));&#xD;&#xA;&#xD;&#xA;            // For every pixel in the square with the size of CoCRadius.&#xD;&#xA;            for(i = x - CoCRadius; i &lt;= x + CoCRadius; i++){&#xD;&#xA;                for(j = y - CoCRadius; j &lt;= y + CoCRadius; j++){&#xD;&#xA;                    // Discard pixels outside of the shape. Square -&gt; Circle&#xD;&#xA;                    if(isInBokehShape(i - x, j - y)){&#xD;&#xA;                        // Discard pixels that would block it.&#xD;&#xA;                        if(depth(x-i, y-j) &gt;= depth(x, y){&#xD;&#xA;                            // Add the colour.&#xD;&#xA;                            newColour[i, j] += colour(x, y);&#xD;&#xA;                            // Add the weight, for normalizing.&#xD;&#xA;                            weight[i, j] += 1.0f;&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    //Normalize the values with the weight.&#xD;&#xA;    for(x = 0; x &lt; width; x++){&#xD;&#xA;        for(y = 0; y &lt; height; y++){&#xD;&#xA;            newColour[x, y] /= weight[x, y];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;This would give you a depth of field effect that is quite true, and does not give you the ghosting effect. $calcCoCRadius$ is a method that calculates the radius in pixels of the circle of confusion. It could be anything, but if you want it as true to an actual camera, then you can use the formula from [this Wikipedia page][5]. $isInBokehShape$ is a method which returns a boolean on whether the point is inside the bokeh shape. With the two for loops we just get a square, but if we want to get a circle shaped bokeh, we need to discard the pixels that would lie outside of the circle. This discarding is also the reason why we keep track of the weights and normalize afterwards with the weight, since we do not know how many pixels we need to discard. The weight is also useful if you do want a falloff in the circle of confusion, for example if you want a gaussian blur.&#xD;&#xA;&#xD;&#xA;Another important thing to know, is that the implementation listed here, is not very optimal. The problem is basically that you write to multiple different pixels. This causes race conditions. Instead, it is better to rework the algorithm so that you only need one write. Basically, you loop through every pixel and you then you check all other pixels (or pixels inside of a maximum CoC radius) whether their CoC radius is large enough that they contribute to the pixel's colour. This way, you can also put the normalizing of the values inside the first loop over all the pixels instead of having to do that later.&#xD;&#xA;&#xD;&#xA;This should be a fairy good way of implementing depth of field as a post processing effect. There are also other ways, but this is one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aud9f.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FK7bL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZD9BY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/sxmta.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Circle_of_confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="20201" PostHistoryTypeId="24" PostId="7741" RevisionGUID="f49055b0-5706-4521-8ce8-5c0ba909c5ff" CreationDate="2018-06-23T21:10:21.280" Comment="Proposed by 8748 approved by -1 edit id of 421" ContentLicense="CC BY-SA 4.0" />
  <row Id="20202" PostHistoryTypeId="5" PostId="7741" RevisionGUID="2f2daa44-6821-4cc0-a6dd-72ed2e94ba93" CreationDate="2018-06-23T21:10:21.280" UserId="4908" Comment="depth(x-i, y-j) was requested together with other stuff, but depth(x-i, y-j) is wrong since i and j are not relative coordinates but absolute pixel coordinates." Text="The blog post that you talked about, is not about generating bokeh for a computer generated image. It is instead about generating a believable depth of field effect from an image captured by a smartphone camera, as the effect is desired for portraits to make the subject stand out. It generally works by splitting the image in to two parts. One part is the subject, which should not be blurred. The other part is the background, which should be blurred but the pixels of the subject should have no influence and would thus have a weight of zero. Slightly more sophisticated algorithms may make the blur kernel size variable across an image to create a smoother transition, but the subject's pixels would still be ignored.&#xD;&#xA;&#xD;&#xA;In games and CGI, post process depth of field is done differently. There are multiple ways for it. A simple google search shows multiple. You could do depth of field like you have, and simply ignore the pixels which should not be blurred to remove the ghosting. However, this is not true to how depth of field occurs inside of a camera. So, in order to get a good algorithm to simulate depth of field, I will first try to explain how you get the depth of field effect in an actual camera.&#xD;&#xA;&#xD;&#xA;Let us say, that we have an object, a single lens and an image sensor. We look at them from the side.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Light scatters in many different directions when hitting the object. To simplify we only take one point. From this point, I will show the light that would hit the lens as a gray solid.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;The lens bends the light towards a single point. That is the focal point.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;You can see that the focal point is in front of the sensor. This causes the light from that single point on the object, to fall on a large portion of the sensor. If the focal point is behind the sensor, the same would happen. But, if the focal point lies on the sensor, there would only be one point on the sensor where the light falls on. This area where the light falls on the sensor, is called the circle of confusion (CoC). This is also the cause of the depth of field effect.&#xD;&#xA;&#xD;&#xA;One important thing to know, is that when the point on the object moves around, the focal point also moves around. If the point moves closer to the lens, the focal point moves closer to the lens, which would alter the size of the circle of confusion. This gives you the gradual change in blurriness that you have with depth of field, since the circle of confusion gradually becomes larger when an object moves away from the area in focus.&#xD;&#xA;&#xD;&#xA;If we add in an aperture we simply block out a part of the light, which causes the circle of confusion to be smaller. This allows us to determine how much light to let in (to make the image brighter or darker), and how strong the depth of field effect is.&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;From this, we can conclude a few things on how we should implement depth of field.&#xD;&#xA;&#xD;&#xA; - Every point whose light enters the camera lens, has a circle of confusion.&#xD;&#xA; - The circle of confusion is the area where the light, from that point, falls on.&#xD;&#xA; - The circle of confusion changes size when the point moves closer to or further away from the lens, or when the aperture changes size.&#xD;&#xA; - The area of the circle of confusion has no falloff. Every point inside the circle of confusion has the same weight. This results in a box blur.&#xD;&#xA; - If a point is in focus, its circle of confusion would be either zero or something so small, that it is not noticed.&#xD;&#xA;&#xD;&#xA;The algorithm is quite simple. For each pixel in the image, we use the depth to calculate the circle of confusion. Then, we add the colour of that pixel to all the other pixels that lie in the circle of confusion. However, if that other pixel is closer to the camera (a lower depth value), it would block the light from our pixel, and we should not add the colour of our pixel to the blocking pixel.&#xD;&#xA;&#xD;&#xA;In pseudo code it would look something like this;&#xD;&#xA;&#xD;&#xA;    // for each pixel in the all-focus image&#xD;&#xA;    for(x = 0; x &lt; width; x++){&#xD;&#xA;        for(y = 0; y &lt; height; y++){&#xD;&#xA;            // How much blur? Zero or close to it if it should be in focus.&#xD;&#xA;            float CoCRadius = calcCoCRadius(depth(x, y));&#xD;&#xA;&#xD;&#xA;            // For every pixel in the square with the size of CoCRadius.&#xD;&#xA;            for(i = x - CoCRadius; i &lt;= x + CoCRadius; i++){&#xD;&#xA;                for(j = y - CoCRadius; j &lt;= y + CoCRadius; j++){&#xD;&#xA;                    // Discard pixels outside of the shape. Square -&gt; Circle&#xD;&#xA;                    if(isInBokehShape(i - x, j - y)){&#xD;&#xA;                        // Discard pixels that would block it.&#xD;&#xA;                        if(depth(i, j) &gt;= depth(x, y){&#xD;&#xA;                            // Add the colour.&#xD;&#xA;                            newColour[i, j] += colour(x, y);&#xD;&#xA;                            // Add the weight, for normalizing.&#xD;&#xA;                            weight[i, j] += 1.0f;&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    //Normalize the values with the weight.&#xD;&#xA;    for(x = 0; x &lt; width; x++){&#xD;&#xA;        for(y = 0; y &lt; height; y++){&#xD;&#xA;            newColour[x, y] /= weight[x, y];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;This would give you a depth of field effect that is quite true, and does not give you the ghosting effect. $calcCoCRadius$ is a method that calculates the radius in pixels of the circle of confusion. It could be anything, but if you want it as true to an actual camera, then you can use the formula from [this Wikipedia page][5]. $isInBokehShape$ is a method which returns a boolean on whether the point is inside the bokeh shape. With the two for loops we just get a square, but if we want to get a circle shaped bokeh, we need to discard the pixels that would lie outside of the circle. This discarding is also the reason why we keep track of the weights and normalize afterwards with the weight, since we do not know how many pixels we need to discard. The weight is also useful if you do want a falloff in the circle of confusion, for example if you want a gaussian blur.&#xD;&#xA;&#xD;&#xA;Another important thing to know, is that the implementation listed here, is not very optimal. The problem is basically that you write to multiple different pixels. This causes race conditions. Instead, it is better to rework the algorithm so that you only need one write. Basically, you loop through every pixel and you then you check all other pixels (or pixels inside of a maximum CoC radius) whether their CoC radius is large enough that they contribute to the pixel's colour. This way, you can also put the normalizing of the values inside the first loop over all the pixels instead of having to do that later.&#xD;&#xA;&#xD;&#xA;This should be a fairy good way of implementing depth of field as a post processing effect. There are also other ways, but this is one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aud9f.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FK7bL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZD9BY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/sxmta.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Circle_of_confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="20206" PostHistoryTypeId="50" PostId="6406" RevisionGUID="ed2331db-6a15-4949-b3c9-a2a35fc140ce" CreationDate="2018-06-24T15:54:47.990" UserId="-1" />
  <row Id="20210" PostHistoryTypeId="2" PostId="7747" RevisionGUID="7b9b5c17-6931-42c8-90a8-0440fb2c1841" CreationDate="2018-06-25T04:52:25.083" UserId="1937" Text="I'm not an expert on path tracing, maybe someone with more experience can come up with a better answer, but I'll have a go at answering your questions.&#xD;&#xA;&#xD;&#xA;Firstly, for the purposes of a college-project scale path-tracer, VRAM capacity shouldn't really be an issue. A vertex with position, normal, tangent and UV fits in 48 bytes, so with a GB of buffers you can hold ~20 million vertices, not counting the space for your index buffers and kd-trees of course. Even my crappy 5-year-old midrange laptop card has 2GB, and modern cards have significantly more, so i doubt you're gonna exhaust VRAM with model data.&#xD;&#xA;&#xD;&#xA;As for the local memory question, short answer is no. Group shared memory for shader cores is tiny, you shouldn't be allocating more than a few KB per shader group, so there's no way you'd get your acceleration structures in there. &#xD;&#xA;&#xD;&#xA;One of the main issues with path tracing is coherence, which is what makes it difficult to do on GPU. Since ray directions are chosen at random, each group of shaders processing a nearby group of pixels can end up sampling radically different parts of the scene, and hence memory. This can introduce a lot of branching and cache misses if not handled carefully, and negate a lot of the advantages of running on GPU.&#xD;&#xA;&#xD;&#xA;The current state of the art for production path tracers is probably Disney's Hyperion. This is a CPU path tracer that runs on absolutely enormous scenes (think San Fransokyo in Big Hero 6), that are potentially too big to fit into even main RAM, and need to be streamed in from disk on demand ('out-of-core' rendering). They mitigate the coherence problems by first generating rays en-masse, then sorting them into bundles with similar position and direction, so that consecutive ray solves are likely to touch the same part of the scene and utilize the cache. Even so, they're bound by memory and I/O speeds, not compute power. Good write up on it [here][1] including a technical PDF. &#xD;&#xA;&#xD;&#xA;For your second question, that is more or less the way it's done. You just accumulate the light from consecutive passes onto your colour buffer, and divide by the number of passes to normalize - you probably want to use 32-bit float colour channels for this. Naive path tracers (which is probably what you're building to start with) just choose a truly random sample distribution and weight each sample by its probability. Smarter approaches bias the sampling towards the more significant directions then remove the bias when summing the color. For example, for a diffuse surface, you could (a) pick truly random directions in the hemisphere and weight each sample by $N.L$ or (b) sample in a cosine distribution (more samples around the normal and less around the horizon) and apply full weight to each sample. &#xD;&#xA;&#xD;&#xA;If you haven't seen it already, [Ray Tracey's blog][2] has some good tutorials on optimizing path-tracing for GPU. Good luck with your project.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.disneyanimation.com/technology/innovations/hyperion&#xD;&#xA;  [2]: http://raytracey.blogspot.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20211" PostHistoryTypeId="2" PostId="7748" RevisionGUID="ea6072ec-fbf0-460a-8d2b-f9c015efde98" CreationDate="2018-06-25T06:20:25.803" UserId="8930" Text="I've got a new task related to image processing in a website. I am too confused in understanding different terms used with sizing of an image. What is the difference between:&#xD;&#xA;&#xD;&#xA; 1. **Cropping an image**&#xD;&#xA; 2. **Resizing an image**&#xD;&#xA; 3. **Scaling an image**&#xD;&#xA; 4. **Changing Aspect-ratio of an image**&#xD;&#xA;&#xD;&#xA;Especially **Resizing vs Scaling**!!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="20212" PostHistoryTypeId="1" PostId="7748" RevisionGUID="ea6072ec-fbf0-460a-8d2b-f9c015efde98" CreationDate="2018-06-25T06:20:25.803" UserId="8930" Text="Difference between Cropping, Scaling, Resizing &amp; Changing Aspect Ration of an Image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20213" PostHistoryTypeId="3" PostId="7748" RevisionGUID="ea6072ec-fbf0-460a-8d2b-f9c015efde98" CreationDate="2018-06-25T06:20:25.803" UserId="8930" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20214" PostHistoryTypeId="2" PostId="7749" RevisionGUID="119030bf-d312-4b56-81e1-76ae61ab3b40" CreationDate="2018-06-25T11:12:08.577" UserId="182" Text=" 1. **&quot;Cropping an image&quot;** means some part of the image is removed in order for the image to fit a certain size. For example, removing the rightmost part of a rectangular image can result in a square.&#xD;&#xA;&#xD;&#xA; 2. **&quot;Resizing an image&quot;** usually means to stretch and squeeze it as needed so it fits a given size. Width and height are modified independently. If the ratio between them is not the same in the original size and in the final size, the image will appear distorted.&#xD;&#xA;&#xD;&#xA; 3. **&quot;Scaling an image&quot;** usually means resizing, but by the same amount horizontally and vertically. The ratio between the width and height is not modified, therefore the final image is not distorted.&#xD;&#xA;&#xD;&#xA; 4. The **&quot;aspect ratio&quot;** is the ratio between the width and the height. Changing the aspect ratio will perceptually stretch the image either horizontally or vertically.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Resizing might change the aspect ratio, and from the wording of your question I have assumed scaling meant not changing the aspect ratio." ContentLicense="CC BY-SA 4.0" />
  <row Id="20216" PostHistoryTypeId="6" PostId="5652" RevisionGUID="2d1e54ae-9f0f-4206-b36d-fa66e0bf0f9f" CreationDate="2018-06-25T12:39:11.763" UserId="5778" Comment="tags edited" Text="|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20217" PostHistoryTypeId="24" PostId="5652" RevisionGUID="2d1e54ae-9f0f-4206-b36d-fa66e0bf0f9f" CreationDate="2018-06-25T12:39:11.763" Comment="Proposed by 5778 approved by 209, -1 edit id of 419" ContentLicense="CC BY-SA 4.0" />
  <row Id="20218" PostHistoryTypeId="6" PostId="5652" RevisionGUID="b797584b-328b-4fc8-9c1d-41bfe23fb239" CreationDate="2018-06-25T12:39:11.763" UserId="6" Comment="tags edited" Text="|performance|memory|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20219" PostHistoryTypeId="2" PostId="7750" RevisionGUID="25f93608-e8ae-4928-8f23-b0a52c8c299f" CreationDate="2018-06-25T13:05:26.983" UserId="6" Text="While the existing answer adress your question quite well, I'd like to add some general advice, even if you might already be aware of that. Rather than just *wasting* that fourth component on the GPU, you might as well **use it for additional data**.&#xD;&#xA;&#xD;&#xA;It might be an obvious suggestion, but a 4th unused 32-bit word can store a variety of useful data:&#xD;&#xA;&#xD;&#xA;- 8-bit RGBA colour components.&#xD;&#xA;- 2D texture coordinates in either 16-bit half-precision floating point or normalized fixed-point format, depending on your precision and range requirements.&#xD;&#xA;- packed normal data using some of the excellent normal compression formats discussed in [this survey of unit vector representations](http://jcgt.org/published/0003/02/01/).&#xD;&#xA;&#xD;&#xA;This would let you use packed 128-bit SSE copy instructions for uploading data (especially since mapped buffer memory is usally well aligned) after just a bit of (easily SSE-optimizable) packing. Of course the viablity of this highly depends on your data. But if you have e.g. 5 floats for position and texCoord or 6 for position and normal, trying one of these schemes might be a neat consideration.&#xD;&#xA;&#xD;&#xA;And using 4-component vectors for your vertices on the GPU can have additional advantages beyond just SSEability on the CPU.&#xD;&#xA;&#xD;&#xA;- It *might* help your **GPU optimize on-chip memory reads/writes** if your data is well aligned (although, of course it has to be measured individually if there's a practical advantage).&#xD;&#xA;- But even disregarding performance it can make development a little more convenient, too. Speaking from OpenGL experience, [using 3-component vertex data in shader storage buffers (i.e. for advanced memory access and/or compute shaders) is a bit of a hassle](https://computergraphics.stackexchange.com/q/5810/6) because of GLSL's data layout. A buffer filled with **4-component vectors makes for generally cleaner and more streamlined code**." ContentLicense="CC BY-SA 4.0" />
  <row Id="20220" PostHistoryTypeId="2" PostId="7751" RevisionGUID="5e8a3579-2391-425d-ba9d-02e9b31a3967" CreationDate="2018-06-25T23:04:59.637" UserId="8935" Text="i am a beginner to opengl following an online guide, &#xD;&#xA;I am trying to make a simple translation to my triangle.&#xD;&#xA;The triangle did render correctly when i made a float uniform to translate it, but when i multiply a mat4 to translate it, i get a black screen.&#xD;&#xA;Opengl outputs no error, i can't tell where is the problem.&#xD;&#xA;Here is the code:&#xD;&#xA;https://pastebin.com/en2zpPTh&#xD;&#xA;&#xD;&#xA;Thank you for helping me !" ContentLicense="CC BY-SA 4.0" />
  <row Id="20221" PostHistoryTypeId="1" PostId="7751" RevisionGUID="5e8a3579-2391-425d-ba9d-02e9b31a3967" CreationDate="2018-06-25T23:04:59.637" UserId="8935" Text="Opengl black screen for a simple translation" ContentLicense="CC BY-SA 4.0" />
  <row Id="20222" PostHistoryTypeId="3" PostId="7751" RevisionGUID="5e8a3579-2391-425d-ba9d-02e9b31a3967" CreationDate="2018-06-25T23:04:59.637" UserId="8935" Text="|opengl|rendering|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20223" PostHistoryTypeId="5" PostId="7751" RevisionGUID="9ddd1a74-9423-409f-a66b-ae1d07daa3b1" CreationDate="2018-06-26T02:34:57.873" UserId="3003" Comment="Added code" Text="i am a beginner to opengl following an online guide, &#xD;&#xA;I am trying to make a simple translation to my triangle.&#xD;&#xA;The triangle did render correctly when i made a float uniform to translate it, but when i multiply a mat4 to translate it, i get a black screen.&#xD;&#xA;Opengl outputs no error, i can't tell where is the problem.&#xD;&#xA;Here is the code:&#xD;&#xA;https://pastebin.com/en2zpPTh&#xD;&#xA;&#xD;&#xA;Here's my drawing loop:&#xD;&#xA;&#xD;&#xA;    //Loop until window close&#xD;&#xA;    while (!glfwWindowShouldClose(mainWindow))&#xD;&#xA;    {&#xD;&#xA;        //Get + Handle user input events&#xD;&#xA;        glfwPollEvents();&#xD;&#xA; &#xD;&#xA;        if (direction)&#xD;&#xA;        {&#xD;&#xA;            triOffset += triIncrement;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            triOffset -= triIncrement;&#xD;&#xA;        }&#xD;&#xA; &#xD;&#xA;        if (abs(triOffset &gt;= triMaxOffset))&#xD;&#xA;        {&#xD;&#xA;            direction = !direction;&#xD;&#xA;        }&#xD;&#xA; &#xD;&#xA;        //Clear window&#xD;&#xA;        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA; &#xD;&#xA;        //Draw&#xD;&#xA;        glUseProgram(shader);&#xD;&#xA; &#xD;&#xA;        glm::mat4 model;&#xD;&#xA;        /*&#xD;&#xA;        [1,0,0,0]&#xD;&#xA;        [0,1,0,0]&#xD;&#xA;        [0,0,1,0]&#xD;&#xA;        [0,0,0,1]&#xD;&#xA;        */&#xD;&#xA;        model = glm::translate(model, glm::vec3(triOffset, 0.0f, 0.0f));&#xD;&#xA; &#xD;&#xA;        glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));&#xD;&#xA; &#xD;&#xA; &#xD;&#xA;        glBindVertexArray(VAO);&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA; &#xD;&#xA;        glBindVertexArray(0);&#xD;&#xA;        glUseProgram(0);&#xD;&#xA; &#xD;&#xA;        glfwSwapBuffers(mainWindow);&#xD;&#xA;       &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and here's my vertex shader:&#xD;&#xA;&#xD;&#xA;    // Vertex Shader&#xD;&#xA;    static const char* vShader = &quot; \n&quot;&#xD;&#xA;    &quot;#version 330                  \n&quot;&#xD;&#xA;    &quot;layout (location = 0) in vec3 pos;\n&quot;&#xD;&#xA;    &quot;uniform mat4 model;                        \n&quot;&#xD;&#xA;    &quot;void main()\n&quot;&#xD;&#xA;    &quot;{\n&quot;&#xD;&#xA;    &quot;   gl_Position = model * vec4(pos, 1.0);\n&quot;&#xD;&#xA;    &quot;}\n&quot;;&#xD;&#xA;&#xD;&#xA;And fragment shader:&#xD;&#xA;&#xD;&#xA;    //Fragment shader&#xD;&#xA;    static const char* fShader =  &quot; \n&quot;&#xD;&#xA;    &quot;#version 330                  \n&quot;&#xD;&#xA;    &quot;out vec4 color;               \n&quot;&#xD;&#xA;    &quot;void main()\n&quot;&#xD;&#xA;    &quot;{\n&quot;&#xD;&#xA;    &quot;   color = vec4(1.0, 1.0, 0.5, 1.0);\n&quot;&#xD;&#xA;    &quot;}\n&quot;;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20232" PostHistoryTypeId="2" PostId="7753" RevisionGUID="4c64fb17-21a6-4500-b82d-d3e69892f430" CreationDate="2018-06-26T10:08:48.557" UserId="8935" Text="We fixed it ! it was glm::mat4(); no initializing to a identity matrix, glm::mat4(1.0f); works fine, thank you for helping me !" ContentLicense="CC BY-SA 4.0" />
  <row Id="20233" PostHistoryTypeId="2" PostId="7754" RevisionGUID="bd888221-f305-471a-9be5-41c3333c6c54" CreationDate="2018-06-26T13:11:22.913" UserId="8125" Text="Having an HLSL shader like this:&#xD;&#xA;&#xD;&#xA;    struct FragmentIn&#xD;&#xA;    {&#xD;&#xA;        float4 Position : SV_Position;&#xD;&#xA;        float4 Color : COLOR0;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct Oct&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float3 Camera;&#xD;&#xA;    float heading;&#xD;&#xA;    Oct data[9];&#xD;&#xA;    &#xD;&#xA;    float4 FS(FragmentIn input) : SV_Target0&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;... how would one supply the uniforms and execute it directly for all pixels?&#xD;&#xA;&#xD;&#xA;Using the [Veldrid][1] framework.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://mellinoe.github.io/veldrid-docs/index.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="20234" PostHistoryTypeId="1" PostId="7754" RevisionGUID="bd888221-f305-471a-9be5-41c3333c6c54" CreationDate="2018-06-26T13:11:22.913" UserId="8125" Text="Veldrid: Only execute fragment shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="20235" PostHistoryTypeId="3" PostId="7754" RevisionGUID="bd888221-f305-471a-9be5-41c3333c6c54" CreationDate="2018-06-26T13:11:22.913" UserId="8125" Text="|fragment-shader|uniform-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20236" PostHistoryTypeId="50" PostId="5925" RevisionGUID="1519159d-fc4a-4b79-b4ef-dbcfa3040871" CreationDate="2018-06-26T15:07:15.247" UserId="-1" />
  <row Id="20238" PostHistoryTypeId="5" PostId="7734" RevisionGUID="01822461-3a35-4be1-bd8f-4eacdbbe1207" CreationDate="2018-06-27T02:00:22.620" UserId="4837" Comment="added 99 characters in body" Text="Recently I ran into an odd issue with some of my DirectX11 DirectCompute code &#xD;&#xA;when trying it on an AMD GPU for the first time where as on a NVIDIA one it had worked fine all through development. The fact that this only appeared on AMD either means that NVIDIA GPUs are more resistant to the issue or perhaps something about them such as a different wavefront size is not triggering the issue, or that it's not even an problem with my code and instead is a bug somewhere along the pipeline (driver, GPU itself, etc) for AMD things. After further testing however, it did appear to work on another more modern AMD card (the Vega 56), though this may be because it was running on Windows 7, or because the GCN 5 architecture (or its drivers) somehow fixed this issue.&#xD;&#xA;&#xD;&#xA;A summary of the GPUs tested is as follows:&#xD;&#xA;&#xD;&#xA; - NVIDIA GeForce GTX 960, Feature Set 11.0/11.1, Windows 10 (Ok)&#xD;&#xA; - NVIDIA GeForce GTX 1060, Feature Set 11.1, Windows 10 (Ok)&#xD;&#xA; - Radeon RX 580, Feature Set 11.0/11.1, Windows 10 (Fail)&#xD;&#xA; - Radeon RX Vega 56, Feature Set 11.0, Windows 7 (Ok)&#xD;&#xA;&#xD;&#xA;The general setup of the issue can be represented by the following pseudocode which I turned into a minimal test application to confirms the problem indeed exists to ensure nothing else in the other much larger codebase was causing the issues:&#xD;&#xA;&#xD;&#xA;    if (condition) {&#xD;&#xA;      globalArray[i].first = value &#xD;&#xA;    } else {&#xD;&#xA;      globalArray[i].second = value&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    DeviceMemoryBarrier()&#xD;&#xA;    &#xD;&#xA;    InterlockedExchange(globalArray[i].flag, true, oldFlag)&#xD;&#xA;    &#xD;&#xA;    if (!oldFlag) {&#xD;&#xA;      return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if (condition) {&#xD;&#xA;      new_value = globalArray[i].second&#xD;&#xA;    } else {&#xD;&#xA;      new_value = globalArray[i].first&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With this setup, an example of its functionality would be best represented by 2 threads executing this code (the important bit being that they may not be within the same work group, more on this later), one with `condition` set to true and one with it set to false. Next, each thread sets the value they possess into a global buffer (both threads have the same index `i`) in the `first` and `second` slots of a structure. The interlocked exchange operation which follows attempts to set the flag (also stored in global memory) to true, allowing only one of the two threads to proceed (one will see that the flag was not set beforehand, meaning it was the first to set it and return). Finally, the remaining thread can now make the assumption that both `first` and `second` values have been set (as the other now terminated thread has already set the atomic along with the global memory barrier which should ensure this), allowing it to read the value written by the other thread to `new_value` (based on the condition once again).&#xD;&#xA;&#xD;&#xA;From a more higher level perspective, this code simply allows two arbitrary threads to combine their information into one which continues on, all through global memory.&#xD;&#xA;&#xD;&#xA;The issue I observed however was that very rarely (only seen in about 1 in a million cases), `new_value` would be set to something uninitialized, implying that the data it read from in the global array was. This however is confusing as the fact that the atomic flag is set should ensure that the value has been written to the proper location by the other thread. I thought perhaps that the atomic operation finished before the full write to the first/second value did for whatever reason but since there is a `DeviceMemoryBarrier` after the value write but before the atomic exchange, it should be waiting on the write to finish before signaling the atomic.&#xD;&#xA;&#xD;&#xA;This behavior leads me to believe that it is something bizarre which is happening so rarely due to unlikely circumstances, such as threads from different wavefronts running into eachother at the exact same time as mentioned previously which should in theory work fine, but something such as caching preventing the writes from being seen properly. This further is strengthened by my testing which purposely collides threads together from random wavefronts, causing the issue to arise most frequently when the number of values to process is around 100,000 whereas counts too small have no effect and counts well into the millions do not either, likely as fewer threads are colliding at the proper exact time due to it being much more unlikely (even still, it sometimes takes 100+ iterations of the same test repeated to invoke the issue with 100,000 values). Most of that is simply speculation though since I do not know too much about the specifics of how GPU memory hierarchies function. Another possibility is that this kind of behavior simply isn't guaranteed by DirectCompute and I am using it incorrectly, though DirectX's documentation is very lacking on actual in-depth descriptions of functionality for intrinsics like `InterlockedExchange`, so I am not sure what to think.&#xD;&#xA;&#xD;&#xA;Does anyone know why this might happen and what I can do to fix it? If it'd help, I can also make the proof of concept test application I made available to show a more specific example of the problem occurring (since the pseudocode did leave out a lot of &quot;irrelevant&quot; details which may actually be significant)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20239" PostHistoryTypeId="5" PostId="7734" RevisionGUID="6b7e4e39-e58e-4384-b901-b5dac2dafa36" CreationDate="2018-06-27T02:11:18.357" UserId="4837" Comment="added 99 characters in body" Text="Recently I ran into an odd issue with some of my DirectX11 DirectCompute code &#xD;&#xA;when trying it on an AMD GPU for the first time where as on a NVIDIA one it had worked fine all through development. The fact that this only appeared on AMD either means that NVIDIA GPUs are more resistant to the issue or perhaps something about them such as a different wavefront size is not triggering the issue, or that it's not even an problem with my code and instead is a bug somewhere along the pipeline (driver, GPU itself, etc) for AMD things. After further testing however, it did appear to work on another more modern AMD card (the Vega 56), though this may be because it was running on Windows 7, or because the GCN 5 architecture (or its drivers) somehow fixed this issue.&#xD;&#xA;&#xD;&#xA;A summary of the GPUs tested is as follows:&#xD;&#xA;&#xD;&#xA; - NVIDIA GeForce GTX 960, Feature Set 11.0/11.1, Windows 10 (Ok)&#xD;&#xA; - NVIDIA GeForce GTX 1060, Feature Set 11.1, Windows 10 (Ok)&#xD;&#xA; - Radeon RX 580, Feature Set 11.0/11.1, Windows 10 (Fail)&#xD;&#xA; - Radeon RX Vega 56, Feature Set 11.0, Windows 7 (Ok)&#xD;&#xA;&#xD;&#xA;The general setup of the issue can be represented by the following pseudocode which I turned into a minimal test application to confirms the problem indeed exists to ensure nothing else in the other much larger codebase was causing the issues:&#xD;&#xA;&#xD;&#xA;    if (condition) {&#xD;&#xA;      globalArray[i].first = value &#xD;&#xA;    } else {&#xD;&#xA;      globalArray[i].second = value&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    DeviceMemoryBarrier()&#xD;&#xA;    &#xD;&#xA;    InterlockedExchange(globalArray[i].flag, true, oldFlag)&#xD;&#xA;    &#xD;&#xA;    if (!oldFlag) {&#xD;&#xA;      return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if (condition) {&#xD;&#xA;      new_value = globalArray[i].second&#xD;&#xA;    } else {&#xD;&#xA;      new_value = globalArray[i].first&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With this setup, an example of its functionality would be best represented by 2 threads executing this code (the important bit being that they may not be within the same work group, more on this later), one with `condition` set to true and one with it set to false. Next, each thread sets the value they possess into a global buffer (both threads have the same index `i`) in the `first` and `second` slots of a structure. The interlocked exchange operation which follows attempts to set the flag (also stored in global memory) to true, allowing only one of the two threads to proceed (one will see that the flag was not set beforehand, meaning it was the first to set it and return). Finally, the remaining thread can now make the assumption that both `first` and `second` values have been set (as the other now terminated thread has already set the atomic along with the global memory barrier which should ensure this), allowing it to read the value written by the other thread to `new_value` (based on the condition once again).&#xD;&#xA;&#xD;&#xA;From a more higher level perspective, this code simply allows two arbitrary threads to combine their information into one which continues on, all through global memory.&#xD;&#xA;&#xD;&#xA;The issue I observed however was that very rarely (only seen in about 1 in a million cases), `new_value` would be set to something uninitialized, implying that the data it read from in the global array was. This however is confusing as the fact that the atomic flag is set should ensure that the value has been written to the proper location by the other thread. I thought perhaps that the atomic operation finished before the full write to the first/second value did for whatever reason but since there is a `DeviceMemoryBarrier` after the value write but before the atomic exchange, it should be waiting on the write to finish before signaling the atomic.&#xD;&#xA;&#xD;&#xA;This behavior leads me to believe that it is something bizarre which is happening so rarely due to unlikely circumstances, such as threads from different wavefronts running into eachother at the exact same time as mentioned previously which should in theory work fine, but something such as caching preventing the writes from being seen properly. This further is strengthened by my testing which purposely collides threads together from random wavefronts, causing the issue to arise most frequently when the number of values to process is around 100,000 whereas counts too small have no effect and counts well into the millions do not either, likely as fewer threads are colliding at the proper exact time due to it being much more unlikely (even still, it sometimes takes 100+ iterations of the same test repeated to invoke the issue with 100,000 values). Most of that is simply speculation though since I do not know too much about the specifics of how GPU memory hierarchies function. Another possibility is that this kind of behavior simply isn't guaranteed by DirectCompute and I am using it incorrectly, though DirectX's documentation is very lacking on actual in-depth descriptions of functionality for intrinsics like `InterlockedExchange`, so I am not sure what to think.&#xD;&#xA;&#xD;&#xA;Does anyone know why this might happen and what I can do to fix it? If it'd help, I can also make the proof of concept test application I made available to show a more specific example of the problem occurring (since the pseudocode did leave out a lot of &quot;irrelevant&quot; details which may actually be significant).&#xD;&#xA;&#xD;&#xA;### Update: ###&#xD;&#xA;Upon more investigation, I decided to implement this same setup in OpenCL 1.2 to see if the issue persisted there as well. To my surprise, it did not and after much testing I seem to have narrowed down the potential cause. From what I can see, the `mem_fence(CLK_GLOBAL_MEM_FENCE)` operation in OpenCL appears to generate slightly different ISA compared to `DeviceMemoryBarrier()`, specifically both are the same (as far as I can tell, though I am not an expert at reading GPU ISA) except for the presence of a `BUFFER_WBINVL1_VOL` instruction which seems to be consistent with how such a construct is described [here][1].&#xD;&#xA;&#xD;&#xA;Removing the memory fence from the working OpenCL implementation causes it to exhibit the same issue as the DirectCompute implementation which leads me to believe the presence of this instruction is somehow responsible for its success, which does make sense as something relating to cache does seem able to be responsible for such odd and rare behavior. This seems to me that it is an issue with how DXBC is converted to the AMD ISA if such an instruction is indeed required, but that is also just speculation. I will post the full ISA of the test implementations here soon-ish as well in case I have misinterpreted what is going on.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ROCm-Developer-Tools/ROCm-ComputeABI-Doc/blob/master/AMDGPU-ABI.md#memory-fence-constraints" ContentLicense="CC BY-SA 4.0" />
  <row Id="20241" PostHistoryTypeId="50" PostId="7557" RevisionGUID="b6f2bfcf-b637-4f84-92af-7d082a67d262" CreationDate="2018-06-27T05:07:35.980" UserId="-1" />
  <row Id="20242" PostHistoryTypeId="2" PostId="7755" RevisionGUID="542d1a95-5236-451c-b975-47013dd3f1a0" CreationDate="2018-06-27T07:43:02.357" UserId="8749" Text="For a 3D terrain, you can triangulate using the points projected onto the XY-plane. This is easily implemented in CGAL using the [Projection_traits_xy_3][1] class, as in this terrain triangulation [example][2].  &#xD;&#xA;&#xD;&#xA;For the fusion of the road triangulation you can use a [constrained Delaunay triangulation][3]. You constrain the road mesh and insert the regular grid points of the terrain mesh to construct the full triangulation. See this [code][4] for an example of how to use CGAL's constrained Delaunay triangulation.&#xD;&#xA;&#xD;&#xA;This should enable you to solve the problem without going into the details of the triangles.&#xD;&#xA;If the result is not good enough, you can always refine the mesh by inserting additional points in problematic triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://doc.cgal.org/latest/Kernel_23/classCGAL_1_1Projection__traits__xy__3.html&#xD;&#xA;  [2]: https://doc.cgal.org/latest/Triangulation_2/index.html#Subsection_2D_Triangulations_Delaunay_Terrain&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Constrained_Delaunay_triangulation&#xD;&#xA;  [4]: https://doc.cgal.org/latest/Triangulation_2/index.html#Subsection_2D_Triangulations_Polygon_triangulation" ContentLicense="CC BY-SA 4.0" />
  <row Id="20243" PostHistoryTypeId="2" PostId="7756" RevisionGUID="c6c0796c-5fa3-4421-915c-28667c2fdbd0" CreationDate="2018-06-27T13:33:21.860" UserId="8920" Text="I really haven't read the whole thing. But I think what the author means for the second part is that: The position or coordinate is in a continuous space i.e x = 1.2345 , y = 2.3455 (floating point) The integer value of this is just 1 and 2 respectively.&#xD;&#xA;&#xD;&#xA;I hope this helps!" ContentLicense="CC BY-SA 4.0" />
  <row Id="20244" PostHistoryTypeId="2" PostId="7757" RevisionGUID="0d582bd2-130c-4c51-b4f2-be8eb21361ce" CreationDate="2018-06-27T20:18:52.603" UserId="8946" Text="It's easy to find guides to calculating the transmitted direction of light given an incoming direction, the normal, and indexes of refraction. However, I can't find anything about determining the normal, given all the other information. That's understandable because it's a bit of an odd thing to do, but I think I need it in my bidirectional path tracer to correctly weight paths that involve a microfacet surface. Even if it turns out that I don't, at this point I'm curious. I know that it's not possible if both indexes of refraction are the same, but that's fine." ContentLicense="CC BY-SA 4.0" />
  <row Id="20245" PostHistoryTypeId="1" PostId="7757" RevisionGUID="0d582bd2-130c-4c51-b4f2-be8eb21361ce" CreationDate="2018-06-27T20:18:52.603" UserId="8946" Text="Refraction: given an incoming and transmitted direction, how to calculate the normal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20246" PostHistoryTypeId="3" PostId="7757" RevisionGUID="0d582bd2-130c-4c51-b4f2-be8eb21361ce" CreationDate="2018-06-27T20:18:52.603" UserId="8946" Text="|brdf|vectors|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20247" PostHistoryTypeId="2" PostId="7758" RevisionGUID="a9e0e7e1-fc49-46c0-8aa6-9d5c8fd1651d" CreationDate="2018-06-27T20:35:02.033" UserId="8946" Text="UV or barycentric coordinates represent a point on a triangle as a weighted average of the three vertexes. You can use those coordinates to smoothly interpolate any value over the triangle, like texture coordinates or the normal vector. So think of it like a two-step process. We map the world coordinates of the intersection point to uv coordinates in &quot;triangle space&quot;, and then use those to map to another space, in this case &quot;texture space&quot;. Your ray hits triangle ABC and you determine the uv coordinates of the intersection point, let's say (0.3, 0.5, 0.2). Intuitively, we're sort of saying the intersection point is 30% A, 50% B, and 20% C. Each vertex would have a texture coordinate, i.e. a pixel in the texture image, associated with it (that's part of modeling / setting up your scene, not something calculated at runtime). Mix the texture coordinates at A, B and C in that ratio and you'll get the point on the texture image associated with that point on the triangle.&#xD;&#xA;&#xD;&#xA;[This scratchapixel page][1] has some good diagrams and clear explanation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="20248" PostHistoryTypeId="5" PostId="7758" RevisionGUID="7fc30db4-5071-4715-bb6e-189a4a8e608e" CreationDate="2018-06-27T20:45:02.697" UserId="8946" Comment="added 155 characters in body" Text="UV or barycentric coordinates represent a point on a triangle as a weighted average of the three vertexes. You can use those coordinates to smoothly interpolate any value over the triangle, like texture coordinates or the normal vector. So think of it like a two-step process. We map the world coordinates of the intersection point to uv coordinates in &quot;triangle space&quot;, and then use those to map to another space, in this case &quot;texture space&quot;. Your ray hits triangle ABC and you determine the uv coordinates of the intersection point, let's say (0.3, 0.5, 0.2). Intuitively, we're sort of saying the intersection point is 30% A, 50% B, and 20% C. Each vertex would have a texture coordinate, i.e. a pixel in the texture image, associated with it (that's part of modeling / setting up your scene, not something calculated at runtime). Mix the texture coordinates at A, B and C in that ratio and you'll get the point on the texture image associated with that point on the triangle.&#xD;&#xA;&#xD;&#xA;[This scratchapixel page][1] has some good diagrams and clear explanation.&#xD;&#xA;&#xD;&#xA;edit: I'm sorry, I missed the part about how to calculate the coordinates in the first place. The page I linked explains it better than I could anyway.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="20249" PostHistoryTypeId="4" PostId="7757" RevisionGUID="b0f9319f-daef-4eb0-96fc-d4b857acb2e8" CreationDate="2018-06-27T21:03:42.957" UserId="8946" Comment="edited title" Text="Refraction: given an incoming and transmitted direction, can I deduce the normal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20250" PostHistoryTypeId="2" PostId="7759" RevisionGUID="f6bb7a44-1fcb-49b4-9171-00f6ab925386" CreationDate="2018-06-27T21:53:35.727" UserId="8920" Text="It should be possible I think. Take the reflection equation: &#xD;&#xA;&#xD;&#xA;R = 2*Dot(N,I)*N -I, where I is the incidence.&#xD;&#xA;&#xD;&#xA;Make an equation for every component of the vector i.e. x,y,z&#xD;&#xA;&#xD;&#xA;You now have 3 equations and 3 unknowns. However, due to Dot(N,I)*N, I don't think this system is linear. So a unique solution probably wont exist.&#xD;&#xA;&#xD;&#xA;But why do you need this? If you have an intersection point at a surface, you should have the normal for that surface?&#xD;&#xA;&#xD;&#xA;Hope this helps" ContentLicense="CC BY-SA 4.0" />
  <row Id="20251" PostHistoryTypeId="2" PostId="7760" RevisionGUID="aa9c6ab5-7a2a-451a-8d55-7d83ce9c43d8" CreationDate="2018-06-28T07:30:51.393" UserId="6346" Text="I have to do some operations on 2D grayscale images. The &quot;normal&quot; stuff like moving, alpha blending and resizing, but also &quot;3D like&quot; operations: Perspective projection, rotation around any axis (x, y, z).&lt;br&gt;&#xD;&#xA;All this happens in an embedded system, where I can choose from microcontrollers with &quot;2D GPU&quot; (e.g. Vivante GC355), &quot;3D GPU&quot; (Vivante GC3000), &quot;no GPU&quot; (Arm A53).&#xD;&#xA;&#xD;&#xA;Safe approach: Take the 3D GPU and use OpenGL operations (e.g. &quot;Rotate&quot;) to do the jobs.&#xD;&#xA;&#xD;&#xA;But how can I find out the **minimum** requirements?&#xD;&#xA;In case of the &quot;no GPU&quot; approach it's quite easy to estimate the CPU cycles for each operation and extrapolate.&lt;br&gt;&#xD;&#xA;How to do this for a GPU? The specifications say things like &quot;x million pixels per second&quot; - but what can it do to these pixels in that second?&#xD;&#xA;The tutorials I found so far say nothing about it.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20252" PostHistoryTypeId="1" PostId="7760" RevisionGUID="aa9c6ab5-7a2a-451a-8d55-7d83ce9c43d8" CreationDate="2018-06-28T07:30:51.393" UserId="6346" Text="How to estimate what GPU (2D/3D/none at all?) is necessary?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20253" PostHistoryTypeId="3" PostId="7760" RevisionGUID="aa9c6ab5-7a2a-451a-8d55-7d83ce9c43d8" CreationDate="2018-06-28T07:30:51.393" UserId="6346" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20255" PostHistoryTypeId="5" PostId="3742" RevisionGUID="a6dab298-4c7d-4f69-9da4-a8c0167d7344" CreationDate="2018-06-28T08:15:19.787" UserId="4714" Comment="terminology" Text="tl;dr: Math problem in projective geometry: **How does one find some 4x4 camera matrix that gives a projection as illustrated below, such that points A,B,C,D are somewhere on the edges of the unit box (e.g. OpenGL normalized device coordinates), and the corners of the unit box fall somewhere reasonable along the rays EA, EB, EC, ED?**&#xD;&#xA;&#xD;&#xA;(This may be a special case possibly of a homography, a perspectivity, and/or a collineation. Not familiar with the terminology.)&#xD;&#xA;&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;## elaboration&#xD;&#xA;&#xD;&#xA;Given a quadrilateral ABCD within the the viewport, I think there exists a unique(?) transformation that maps it back to a rectangle. As seen in the image below: the quadrilateral ABCD in the viewport acts as a physical 'window', and if we map it back to a rectangle it will appear distorted.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/k5XLm.png&#xD;&#xA;&#xD;&#xA;(the box on the right represents NDC, which I talk about later)&#xD;&#xA;&#xD;&#xA;The goal is to quickly obtain the image on the right. We could raytrace every point to obtain the image (which I've done), but I would prefer to use OpenGL or other projective techniques because I wanted to take advantage of things like blending, primitives, etc.&#xD;&#xA;&#xD;&#xA;## first attempt&#xD;&#xA;&#xD;&#xA;I believe I can solve the problem of finding the 3x4 [camera matrix](https://en.wikipedia.org/wiki/Camera_matrix) that makes the 3+1-dimensional [homogeneous coordinate](https://en.wikipedia.org/wiki/Homogeneous_coordinates) in 3-space (on the left) and projects it down to the 2+1 dimensional homogeneous coordinates in 2-space (on the right). One can solve this using the [direct linear transformation](https://en.wikipedia.org/wiki/Direct_linear_transformation) to get a system of equations `Ba=0` for the unknown entries `a` of the camera matrix, and solving the system using [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) (SVD). I would take the vectors EA, EB, EC, ED (where E is your physical eye or the camera in world-space) as points in the pre-image, and (0,0), (1,0), (1,1), (0,1) or something as the points in the post-image, and each pair of points would give a few linear equations to plug into the SVD. The resulting matrix would map EA-&gt;(0,0) etc. (assuming there are enough degrees of freedom i.e. if the solution is unique, which I'm not sure about, see note[a].)&#xD;&#xA;&#xD;&#xA;But to my chagrin this is not how OpenGL works. OpenGL does not directly project 3d to 2d with a 3x4 matrix. OpenGL requires &quot;normalized device coordinates&quot; (NDC), which are three-dimensional points. After projecting into NDC, everything in the 'unit' box from (-1,-1,-1,1) to (1,1,1,1) is drawn; everything outside is clipped (since we're dealing with homogenerous coordinates: any point (x,y,z,w) will appear only on-screen only if the first three coordinates of (x/w,y/w,z/w,1) are within the unit box from -1 to 1).&#xD;&#xA;&#xD;&#xA;So the question becomes: does there exist some reasonable transformation that maps some weird-looking cuboid in homogeneous coordinates (specifically the cuboid drawn on the left, with ABCD (front points) and A'B'C'D' (back points, hidden behind front points)) to the unit cube, e.g. using a 4x4 matrix? How does one do it?&#xD;&#xA;&#xD;&#xA;## what I've tried&#xD;&#xA;&#xD;&#xA;I've tried something stronger: I made ABCD and A'B'C'D' look like a regular pyramidal frustrum (e.g. gl frustrum) (i.e. in this hypothetical setup, the image on the left would just have a black rectangle superposed on it, not a quadrilateral), and then used the DLT/direct linear transformation to solve for the alleged 4x4 matrix. However when I tried it, there did not seem to be enough degrees of freedom... the resulting 4x4 matrix did not map every input vector to every output vector. While using A,B,C,D,A' (5 pairs of pre-transform and post-transform vectors), I /almost/ get the result I want... the vectors are mapped correctly, but for example B',C',D' are mapping to (3,3,1,1) instead of (-1,-1,1,1) and are clipped away by OpenGL. If I try adding a sixth point (6 pairs of points for the 4x4 matrix to project), my solution seems degenerate (zeroes, infinites). How many degrees of freedom am I dealing with here, and is this possible with a 4x4 matrix mapping the usual 4vectors (3+1-dimensional homogeneous-coordinate vectors) that we know and love?&#xD;&#xA;&#xD;&#xA;## random minor thoughts&#xD;&#xA;&#xD;&#xA;I'm guessing that it's not possible to map any arbitrary cuboid to any arbitrary cuboid with a 4x4 matrix, though I'm confused because I thought it was possible to map any convex quadrilateral to any other convex quadrilateral in 2d with some matrix like in, say, Photoshop?... can/can't this not be done with a projective transform? And how does it generalize to 3d? ...... Also given the failed attempt to find a 4x4 matrix, linear algebra says we should not expect an NxN matrix to map more than N linearly independent points to N target points in the best case, but I feel that somehow homogeneous coordinates cheat this because there is some hidden colinearity going on? I guess not?&#xD;&#xA;&#xD;&#xA;## another solution?&#xD;&#xA;&#xD;&#xA;I guess one could also maybe do the following ugly thing, where you use a typical frustrum camera projection matrix, find the 2d points corresponding to the corners, then perform a 2d perspective distort homography, but if that were to happen after the pixels were rendered (e.g. photoshop) then there would be problems with resolution... maybe hypothetically one could figure out a matrix to perform this transformation on the XY-plane within NDC-space, then compose it with the normal frustrum-based matrix?&#xD;&#xA;&#xD;&#xA;(note [a]: Degree of freedom: ABCD can be further constrained to be the post-image of a projective transformation acting on a rectangle, if that is necessary... that is the black rectangle on the left could be said to be the result of projecting a picture frame clipart model)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20256" PostHistoryTypeId="2" PostId="7761" RevisionGUID="86ca999d-1d4c-442d-aee1-82ca121378d6" CreationDate="2018-06-28T18:28:04.420" UserId="2041" Text="There are really two things you need to know about your application:&#xD;&#xA;&#xD;&#xA;1. How many pixels do you need to push per second?&#xD;&#xA;1. How many cycles do you need to spend on each?&#xD;&#xA;&#xD;&#xA;For the first, you need to sum the size of your output framebuffer and all the intermediates to count the number of pixels written in each frame. Make sure to include overdraw: if you draw a full-screen background, and then draw a foreground that covers half of the frame, you need to multiply by $1.5$. Then just divide that by your frame time (e.g. 33 ms if you need to reach 30 fps) to count the pixels per second.&#xD;&#xA;&#xD;&#xA;To count cycles, you need to know what size of program will be run on each pixel. For a transformation or colour correction, it might just be a couple of multiply-adds. Somebody who would write the shader code (or the Neon code in the no-GPU case) should be able to work this out for you. It'll be easier if you have a prototype running on a desktop GPU already.&#xD;&#xA;&#xD;&#xA;There are also two important properties of the hardware to consider. First is the pixel fill rate, which you've already seen. This tends to be limited by the memory bandwidth of the system-on-chip instead of by the CPU or GPU itself. If you're buying GPU IP and integrating it into the chip itself, you'll need to talk to the vendor's application support people to find out what your design can achieve. If you're buying a whole system-on-chip, just use the value from the spec sheet.&#xD;&#xA;&#xD;&#xA;Second is your cycle budget. This depends on the GPU or FPU itself, not on the memory bandwidth, so it's easier to calculate. You just need to talk to the silicon vendor to determine this. For a GPU it'll be the number of cores times the clock speed divided by the instruction cycles per clock - but more realistically, look at a synthetic benchmark for this chip to see its megaflops.&#xD;&#xA;&#xD;&#xA;Comparing your number of pixels per second with what the system can achieve is easy, but you also need to multiply this by the cycles per pixel you want to spend, to get the total number of cycles per second you need, and compare this with what the compute core offers.&#xD;&#xA;&#xD;&#xA;Don't forget you also need to weigh the difference in BOM cost and software complexity against the risk and cost of a board respin, and multiply your estimate by some fudge factor appropriate to your project risk. We can't help you with that part here :-)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20258" PostHistoryTypeId="2" PostId="7762" RevisionGUID="0a7d6a08-5025-49b7-bc80-881395aea8ec" CreationDate="2018-06-29T19:17:39.573" UserId="8952" Text="i am trying to work through some of the [tutorials for pyopengl][1] and cant seem to get it working.&#xD;&#xA;&#xD;&#xA;the only message i'm getting is a warning:&#xD;&#xA;&#xD;&#xA;`python tutorial4.py`&#xD;&#xA;&#xD;&#xA;`No handlers could be found for logger &quot;OpenGL.arrays.numpymodule&quot;`&#xD;&#xA;&#xD;&#xA;no opengl context/screen pops up. script just exits.&#xD;&#xA;&#xD;&#xA;id love any thoughts or feedback that might help me move forward,&#xD;&#xA;&#xD;&#xA;https://gist.github.com/yvan/f34ad04c1ae32a41482ac1295871fffd&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://pyopengl.sourceforge.net/context/tutorials/shader_4.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="20259" PostHistoryTypeId="1" PostId="7762" RevisionGUID="0a7d6a08-5025-49b7-bc80-881395aea8ec" CreationDate="2018-06-29T19:17:39.573" UserId="8952" Text="Cant seem to get pyopengl tutorial 4 to work" ContentLicense="CC BY-SA 4.0" />
  <row Id="20260" PostHistoryTypeId="3" PostId="7762" RevisionGUID="0a7d6a08-5025-49b7-bc80-881395aea8ec" CreationDate="2018-06-29T19:17:39.573" UserId="8952" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20265" PostHistoryTypeId="2" PostId="7763" RevisionGUID="e70bd4b0-7fd7-4f0d-b5ba-88b1aa2b5f0b" CreationDate="2018-06-30T14:30:04.263" UserId="5828" Text="What is the best way to prove if three points are linear dependent?&#xD;&#xA;&#xD;&#xA;This is my current way to do it:&#xD;&#xA;&#xD;&#xA;$$\mathbf{v_a} = \mathbf{b}-\mathbf{a} \\&#xD;&#xA;\mathbf{v_b} = \mathbf{c}-\mathbf{a} \\&#xD;&#xA;\mathbf{v_c} = \begin{pmatrix} -\mathbf{v_{a,y}} \\ \mathbf{v_{a,x}} \end{pmatrix} \\&#xD;&#xA;\phi = \mathbf{\hat{v}_c} \cdot \mathbf{\hat{v}_b} \\&#xD;&#xA;\phi &lt; 10^{-3}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$\phi$ is the $arccos$ of the real angle between the two vectors. This works good if the polygon or the three points of the polygon have well defined distances. But what if the polygon looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The distance between $P_0$ and $P_1$ is much bigger than between $P_1$ and $P_2$. $P_0$, $P_1$ and $P_2$ are of clearly not linear dependent.&#xD;&#xA;&#xD;&#xA;I'm searching for a scale-independent algorithm for that. &#xD;&#xA;&#xD;&#xA;Do you have any ideas or a reference to a paper I can read about it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SrXqi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20266" PostHistoryTypeId="1" PostId="7763" RevisionGUID="e70bd4b0-7fd7-4f0d-b5ba-88b1aa2b5f0b" CreationDate="2018-06-30T14:30:04.263" UserId="5828" Text="Linear independence of three points" ContentLicense="CC BY-SA 4.0" />
  <row Id="20267" PostHistoryTypeId="3" PostId="7763" RevisionGUID="e70bd4b0-7fd7-4f0d-b5ba-88b1aa2b5f0b" CreationDate="2018-06-30T14:30:04.263" UserId="5828" Text="|mathematics|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20268" PostHistoryTypeId="2" PostId="7764" RevisionGUID="a729da8e-55aa-435a-84ac-b1659c929b77" CreationDate="2018-06-30T23:47:55.377" UserId="5717" Text="Normalize $v_a$ and $v_b$ and your algorithm should no longer depend on the length of the edges, unless you consider numerical stability.&#xD;&#xA;&#xD;&#xA;As for the &quot;best way&quot;, I'm not sure there's a much better algorithm but I would try a better definition of the tolerance. Instead of a fixed value, I would use differentials to compute the change in the angle for a change of the inputs of a few [ulps][1]. If the resulting range overlaps 0, then I think the points are colinear within available precision.&#xD;&#xA;&#xD;&#xA;Whether that complexity is justified depends on what you're doing with this, which you did not specify. A constant could be fine or even the best choice for some uses.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Unit_in_the_last_place" ContentLicense="CC BY-SA 4.0" />
  <row Id="20269" PostHistoryTypeId="2" PostId="7765" RevisionGUID="80893807-7382-407d-9c09-d554374d6356" CreationDate="2018-07-01T03:21:21.590" UserId="5717" Text="See equation (16) in [Microfacet Models for Refraction through Rough Surfaces][1] : $-(\eta_i w_i + \eta_o w_o)$ which you'll probably want to normalize. $\eta$ are the two indices of refraction and $w$ the two vectors (they use $i$ and $o$ in the paper). Also look at the left part of figure 7 on the same page to see where all the vectors are pointing.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="20272" PostHistoryTypeId="2" PostId="7766" RevisionGUID="6494bd0a-7b5f-4a39-8713-14a988cfc20a" CreationDate="2018-07-01T08:48:53.460" UserId="8952" Text="solved:&#xD;&#xA;&#xD;&#xA;i misspelled `glEnableVertexAttribArray` as `glEnableVerexAttribArray`. i'm not sure why opengl fails silently when i misspell the name of my pointer object. shouldn't it throw a name error or something? maybe `verex` is a thing?&#xD;&#xA;&#xD;&#xA;ok well now we know." ContentLicense="CC BY-SA 4.0" />
  <row Id="20273" PostHistoryTypeId="2" PostId="7767" RevisionGUID="4e1d5b95-2209-4aad-86eb-989b36468af1" CreationDate="2018-07-01T23:10:45.130" UserId="5717" Text="The conversion from option A is likely faster than you think. See, for example, [Intel's version][1] which claims to do the round trip at 1.5 cycles per vector with AVX.&#xD;&#xA;&#xD;&#xA;There are also some operations which don't require the conversion at all. For example, if you want to compute a bounding box, you can do it directly with the packed data in chunks of 4 vectors and fix things up once you've gone through the entire array.&#xD;&#xA;&#xD;&#xA;And finally a word of warning: a vector class as presented in the article is not how you write high performance code nor how you generally should use SIMD.&#xD;&#xA;&#xD;&#xA;  [1]: https://software.intel.com/en-us/articles/3d-vector-normalization-using-256-bit-intel-advanced-vector-extensions-intel-avx" ContentLicense="CC BY-SA 4.0" />
  <row Id="20278" PostHistoryTypeId="2" PostId="7769" RevisionGUID="46d420e0-faa9-4ce8-b59f-e914789e46ef" CreationDate="2018-07-03T09:33:20.267" UserId="3123" Text="Is there some algorithm that keeps details when creating mipMaps for SDF?&#xD;&#xA;For example group of 4 pixels when only one is above threshold will lose this pixel with bilinear and creating mipMaps with 'max' of those values will add noise. &#xD;&#xA;When purpose of SDF is keeping the same image in lower resolution what is the best way to downsample this image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20279" PostHistoryTypeId="1" PostId="7769" RevisionGUID="46d420e0-faa9-4ce8-b59f-e914789e46ef" CreationDate="2018-07-03T09:33:20.267" UserId="3123" Text="MipMaps for Signed Distance Field" ContentLicense="CC BY-SA 4.0" />
  <row Id="20280" PostHistoryTypeId="3" PostId="7769" RevisionGUID="46d420e0-faa9-4ce8-b59f-e914789e46ef" CreationDate="2018-07-03T09:33:20.267" UserId="3123" Text="|texture|signed-distance-field|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20281" PostHistoryTypeId="5" PostId="7769" RevisionGUID="7d87ab77-bfd0-41f6-a5b8-1a6dab23b1b9" CreationDate="2018-07-03T09:45:35.677" UserId="3123" Comment="added 95 characters in body" Text="Is there some algorithm that keeps details when creating mipMaps for SDF?&#xD;&#xA;For example group of 4 pixels when only one is above threshold will lose this pixel with bilinear and creating mipMaps with 'max' of those values will add noise. &#xD;&#xA;When purpose of SDF is keeping the same image in lower resolution what is the best way to downsample this image?&#xD;&#xA;&#xD;&#xA;For generating SDF i use [8SSEDT](http://www.codersnotes.com/notes/signed-distance-fields/)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20285" PostHistoryTypeId="50" PostId="6365" RevisionGUID="deb758c2-f1fe-4a45-8a5c-13fae40afd25" CreationDate="2018-07-03T12:34:09.713" UserId="-1" />
  <row Id="20288" PostHistoryTypeId="2" PostId="7771" RevisionGUID="9e6e3288-94c9-4fa6-a91b-d2647a57e069" CreationDate="2018-07-04T19:27:55.407" UserId="7462" Text="Currently I have a naive Mesh data structure to store wavefront files.&#xD;&#xA;&#xD;&#xA;This data has 3 buffers for the vertices, normals and UVs. It works well to the point I can render the sponza scene, despite such a scene having multiple inner meshes.&#xD;&#xA;&#xD;&#xA;The issue is, currently I can onlky render 1 &quot;thing&quot; (I can only have all the mesh associated to a single texture and material properties).&#xD;&#xA;&#xD;&#xA;Since I want to be able to render the sponza scene properly (with all the textures), I need to associate with the vertices different textures and material properties. Based on the information of the associated mtl files.&#xD;&#xA;&#xD;&#xA;What is the proper design to have a Mesh, transform and material objects wrapped in a containing structure such that you can handle complex geometry like the sponza scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20289" PostHistoryTypeId="1" PostId="7771" RevisionGUID="9e6e3288-94c9-4fa6-a91b-d2647a57e069" CreationDate="2018-07-04T19:27:55.407" UserId="7462" Text="Proper design of data structure to store wavefront file information?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20290" PostHistoryTypeId="3" PostId="7771" RevisionGUID="9e6e3288-94c9-4fa6-a91b-d2647a57e069" CreationDate="2018-07-04T19:27:55.407" UserId="7462" Text="|rendering|texture|mesh|material|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20293" PostHistoryTypeId="2" PostId="7772" RevisionGUID="64579d76-634e-4c0d-a514-57b242b32f18" CreationDate="2018-07-05T22:08:20.813" UserId="6844" Text="I have a grid with a variable width/height spacing. Let's say 100 horizontal lines separated by 80 pixels and 100 hundred vertical lines separated by 50 pixels.&#xD;&#xA;&#xD;&#xA;Each cell of the grid in my logic have the same function as a pixel. So each of my pixels will be 50 px width and 100 px height.&#xD;&#xA;&#xD;&#xA;I need to draw a circle filled with a color (let's say black) and without stroke.&#xD;&#xA;&#xD;&#xA;I also need my circle to (as it is made out of filled cells) be with the less rectangles as possible, so certain rectangles are bigger than other ones.&#xD;&#xA;&#xD;&#xA;for example the center of the circle is made out of one big rectangle then as we go closer to the edge the rectangles becomes smaller.&#xD;&#xA;&#xD;&#xA;Any algorithm to do that?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20294" PostHistoryTypeId="1" PostId="7772" RevisionGUID="64579d76-634e-4c0d-a514-57b242b32f18" CreationDate="2018-07-05T22:08:20.813" UserId="6844" Text="How can I draw a filled circle on a grid with the less rectangle as possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20295" PostHistoryTypeId="3" PostId="7772" RevisionGUID="64579d76-634e-4c0d-a514-57b242b32f18" CreationDate="2018-07-05T22:08:20.813" UserId="6844" Text="|algorithm|javascript|pixel-graphics|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20296" PostHistoryTypeId="5" PostId="7772" RevisionGUID="a290b1a3-fabe-42c5-89db-fde1d91f7fa4" CreationDate="2018-07-05T22:18:57.430" UserId="6844" Comment="added an image" Text="I have a grid with a variable width/height spacing. Let's say 100 horizontal lines separated by 80 pixels and 100 hundred vertical lines separated by 50 pixels.&#xD;&#xA;&#xD;&#xA;Each cell of the grid in my logic have the same function as a pixel. So each of my pixels will be 50 px width and 100 px height.&#xD;&#xA;&#xD;&#xA;I need to draw a circle filled with a color (let's say black) and without stroke.&#xD;&#xA;&#xD;&#xA;I also need my circle to (as it is made out of filled cells) be with the less rectangles as possible, so certain rectangles are bigger than other ones.&#xD;&#xA;&#xD;&#xA;for example the center of the circle is made out of one big rectangle then as we go closer to the edge the rectangles becomes smaller.&#xD;&#xA;&#xD;&#xA;for example here I have circle with a grid of same width/height spacing made out of 9 rectangles (sorry for the quality of the image)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Any algorithm to do that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TVQhu.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20297" PostHistoryTypeId="2" PostId="7773" RevisionGUID="7e33e145-9354-4495-822a-8f870b71fc15" CreationDate="2018-07-06T00:25:45.623" UserId="7462" Text="I have been reading the [OpenGL documentation][1] but it is not clear to me how to achieve the following.&#xD;&#xA;&#xD;&#xA;Say we have an array of strings. Each string in the array is a valid relative path to an image file (.png, .jpeg...)&#xD;&#xA;&#xD;&#xA;We have a method that can read and store into a GLubyte array the image information of each file.&#xD;&#xA;&#xD;&#xA;We want to allocate the needed memory for the textures, and save said information into a texture array. However there's no guarantee that the textures are the same dimensions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Array_Texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="20298" PostHistoryTypeId="1" PostId="7773" RevisionGUID="7e33e145-9354-4495-822a-8f870b71fc15" CreationDate="2018-07-06T00:25:45.623" UserId="7462" Text="How do you load multiple textures into an array texture with OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20299" PostHistoryTypeId="3" PostId="7773" RevisionGUID="7e33e145-9354-4495-822a-8f870b71fc15" CreationDate="2018-07-06T00:25:45.623" UserId="7462" Text="|opengl|texture|data-structure|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20300" PostHistoryTypeId="50" PostId="6373" RevisionGUID="90accac4-11df-48e8-9eeb-90d6cb231a7a" CreationDate="2018-07-06T04:04:49.413" UserId="-1" />
  <row Id="20301" PostHistoryTypeId="2" PostId="7774" RevisionGUID="f3d6940f-a960-425a-8ed4-8e1cc7ce2265" CreationDate="2018-07-06T05:24:46.217" UserId="3329" Text="I would like to give you my graphics beginner perspective on the subject. What I realised (in many years working as an engineer in another field) is that the fundamental concepts are the most important part. Once you have a solid understanding of those, learning the last shiny new API is the least difficult part. I don't know if you are a young hobbiest trying to program the new Skyrim or if you are looking for a job in the CG field.&#xD;&#xA;&#xD;&#xA;I tell you what I think it's the best approach **in my opinion** to learn computer graphics &quot;like a pro&quot;.&#xD;&#xA;&#xD;&#xA; 1. Learn Linear Algebra and geometry like a pro. Without this, forget any fancy API or graphics&#xD;&#xA; 2. Buy a good book on computer graphics (e.g. [Fundamentals of computer graphics][1])&#xD;&#xA; 3. While you study the book, set up a programming environment with something that allows you to draw on an image and implement the algorithms!&#xD;&#xA;It can be Java 2D or C++ and SDL or even Python and Pygame for what it matters. At this stage you need to get your spinning textured gears with multiple camera views up and running **before** trying to get 10000 FPS&#xD;&#xA; 4. Now take on OpenGL, Vulkan or DirectX and repeat your fancy example (see above).&#xD;&#xA;&#xD;&#xA;Starting to worry about performance before understanding how to draw a line is like worrying about the aerodynamics of your car before getting the driving license.&#xD;&#xA; &#xD;&#xA;  [1]: https://www.amazon.com/Fundamentals-Computer-Graphics-Fourth-Marschner/dp/1482229390/ref=dp_ob_title_bk?dpID=51T684ZrXgL&amp;preST=_SX218_BO1,204,203,200_QL40_&amp;dpSrc=detail" ContentLicense="CC BY-SA 4.0" />
  <row Id="20307" PostHistoryTypeId="2" PostId="7776" RevisionGUID="376bc006-b25b-48f8-a907-6c9bf668bf64" CreationDate="2018-07-06T14:07:36.593" UserId="6" Text="The memory layout of a (2D) array texture is pretty **similar to a 3D texture, with the individual image layers stored one after the other in a big 3D-array of pixels**. So that's also how you set them. You either load each individual image into a big `GLubyte` array one after the other and set it with `glTex(Sub)Image3D` or you load each image into its own `GLubyte` array and transmit that to the texture with `glTexSubImage3D` one after the other (or any other more complex process involving buffers or whatever, but you get the idea).&#xD;&#xA;&#xD;&#xA;So much to the theory. The problem here is the part where you say&#xD;&#xA;&#xD;&#xA;&gt; However there's no guarantee that the textures are the same dimensions.&#xD;&#xA;&#xD;&#xA;This contradicts with how array textures work. As the corresponding documentation you link to says:&#xD;&#xA;&#xD;&#xA;&gt; An **Array Texture** is a Texture where each mipmap level contains an array of images of the same size.&#xD;&#xA;&#xD;&#xA;So the **individual layers of an array texture *have* to be the same size**. Simplifyingly said, an array texture is really just a 3D texture without filtering along the z-axis. So you can't get different-sized textures into such a regular box of pixels.&#xD;&#xA;&#xD;&#xA;There's a few options you have here, though:&#xD;&#xA;&#xD;&#xA;- You could **scale every image to a common size**, depending on *how* different they really are and what rescaling means to your quality and/or memory demands.&#xD;&#xA;- You could just **drop using array textures** and implement whatever you want to do with normal 2D textures and a likely more complicated process on the CPU side.&#xD;&#xA;- You could use **[Bindless Textures](https://www.khronos.org/opengl/wiki/Bindless_Texture)**. This is a rather modern non-core feature (only usable through extensions yet) that is really flexible and allows you to **access textures in a shader by using a unique GPU handle** (a 64-bit ID, so to say). This allows you to use whatever and how many textures you want in a shader, depending on some arbitrarily input value (even a vertex attribute). In this case you wouldn't just a have access to a continuous array of N textures, rather than the wealth of all the textures you have allocated. Of course this comes with a few limitations and intricacies, too. But more about that in the corresponding documentation." ContentLicense="CC BY-SA 4.0" />
  <row Id="20308" PostHistoryTypeId="5" PostId="7776" RevisionGUID="2aa016dd-825b-40c0-88bb-6a823033135f" CreationDate="2018-07-06T14:15:00.110" UserId="6" Comment="added 131 characters in body" Text="The memory layout of a (2D) array texture is pretty **similar to a 3D texture, with the individual image layers stored one after the other in a big 3D-array of pixels**. So that's also how you set them. You either load each individual image into a big `GLubyte` array one after the other and set it with `glTex(Sub)Image3D` or you load each image into its own `GLubyte` array and transmit that to the texture with `glTexSubImage3D` one after the other (or any other more complex process involving buffers or whatever, but you get the idea).&#xD;&#xA;&#xD;&#xA;So much to the theory. The problem here is the part where you say&#xD;&#xA;&#xD;&#xA;&gt; However there's no guarantee that the textures are the same dimensions.&#xD;&#xA;&#xD;&#xA;This contradicts with how array textures work. As the corresponding documentation you link to says:&#xD;&#xA;&#xD;&#xA;&gt; An **Array Texture** is a Texture where each mipmap level contains an array of images of the same size.&#xD;&#xA;&#xD;&#xA;So the **individual layers of an array texture *have* to be the same size**. Simplifyingly said, an array texture is really just a 3D texture without filtering along the z-axis. So you can't get different-sized textures into such a regular box of pixels.&#xD;&#xA;&#xD;&#xA;There's a few options you have here, though:&#xD;&#xA;&#xD;&#xA;- You could **scale every image to a common size**, depending on *how* different they really are and what rescaling means to your quality and/or memory demands.&#xD;&#xA;- You could just **drop using array textures** and implement whatever you want to do with normal 2D textures and a likely more complicated process on the CPU side.&#xD;&#xA;- You could use **[Bindless Textures](https://www.khronos.org/opengl/wiki/Bindless_Texture)**. This is a rather modern non-core feature (only usable through extensions yet) that is really flexible and allows you to **access textures in a shader by using a unique GPU handle** (a 64-bit ID, so to say). This allows you to use whatever and how many textures you want in a shader, depending on some arbitrarily input value (even a vertex attribute). &#xD;&#xA;&#xD;&#xA; In this case you wouldn't just a have access to a continuous array of N textures, rather than the wealth of all the textures you have allocated. You would just use normal independent 2D textures and use their respective texture handles rather than an array index. Of course this comes with a few limitations and intricacies, too. But more about that in the corresponding documentation." ContentLicense="CC BY-SA 4.0" />
  <row Id="20309" PostHistoryTypeId="50" PostId="6218" RevisionGUID="472b360f-1a21-45e5-8b7c-3ae70e8e9179" CreationDate="2018-07-06T17:20:29.290" UserId="-1" />
  <row Id="20310" PostHistoryTypeId="2" PostId="7777" RevisionGUID="81ffe2e6-291f-416f-9617-ddf0feb02aa3" CreationDate="2018-07-06T22:57:27.447" UserId="7462" Text="The C++ psuedo code to transmit the idea of what I want to do would be:&#xD;&#xA;&#xD;&#xA;    Texture_array tarr = Texture_array(6);&#xD;&#xA;    tarr[0] = texture;&#xD;&#xA;&#xD;&#xA;Which I am attempting to do as follows:&#xD;&#xA;&#xD;&#xA;        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);&#xD;&#xA;        glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 894, 894, 6);&#xD;&#xA;        glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 894, 894, 0, color_format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;        //Set the texture parameters of the image&#xD;&#xA;       	glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;    	glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);&#xD;&#xA;    	glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;    	glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;On the fragment shader I attempt to read the value as:&#xD;&#xA;&#xD;&#xA;    vec3 c = vec3(texture(text, vec3(f_uv.xy,0)));&#xD;&#xA;&#xD;&#xA;However the end result is completely blak, despite data being an array of a valid texture (I have tested it and know data has been properly initialized, it works with normal textures, just not texture arrays)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20311" PostHistoryTypeId="1" PostId="7777" RevisionGUID="81ffe2e6-291f-416f-9617-ddf0feb02aa3" CreationDate="2018-07-06T22:57:27.447" UserId="7462" Text="How to assign a texture to a single entry of a texture array?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20312" PostHistoryTypeId="3" PostId="7777" RevisionGUID="81ffe2e6-291f-416f-9617-ddf0feb02aa3" CreationDate="2018-07-06T22:57:27.447" UserId="7462" Text="|opengl|texture|data-structure|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20313" PostHistoryTypeId="50" PostId="5697" RevisionGUID="03efdd57-4ea4-4955-bd4c-7be80f1e1095" CreationDate="2018-07-06T23:20:32.793" UserId="-1" />
  <row Id="20314" PostHistoryTypeId="2" PostId="7778" RevisionGUID="7fb32638-0c17-4e84-aaaf-1de73bf4ad7c" CreationDate="2018-07-07T02:56:26.683" UserId="2654" Text="&gt;     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 894, 894, 0, color_format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;You're transmitting 3D data. But you told OpenGL that the 3D block of data has a depth of 0. So the number of pixels you're transmitting is... 0.&#xD;&#xA;&#xD;&#xA;I have no idea why OpenGL doesn't provide an error when passing 0 for any of the sizing components (since that means you're not passing data). But that's your problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="20315" PostHistoryTypeId="5" PostId="7778" RevisionGUID="4c42ce88-0eba-4a15-8108-bf5d9c857d84" CreationDate="2018-07-07T13:12:22.163" UserId="2654" Comment="added 85 characters in body" Text="&gt;     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 894, 894, 0, color_format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;You're transmitting 3D data. But you told OpenGL that the 3D block of data has a depth of 0. So the number of pixels you're transmitting is... 0.&#xD;&#xA;&#xD;&#xA;I have no idea why OpenGL doesn't provide an error when passing 0 for any of the sizing components (since that means you're not passing data). But that's your problem. You need to pass 1 for the depth if you're uploading a single 2D slice to the array." ContentLicense="CC BY-SA 4.0" />
  <row Id="20317" PostHistoryTypeId="5" PostId="3884" RevisionGUID="01a9c68c-bf83-4532-9a04-349ff597e65c" CreationDate="2018-07-08T10:27:45.570" UserId="4962" Comment="edited body" Text="As tutors for this year’s programming languages course during our Computer Science studies we’re preparing for the students final project which is the implementation of a ray tracer. We’re implementing one on our own.&#xD;&#xA;&#xD;&#xA;I’m having trouble understanding how the [phong reflection model](https://en.m.wikipedia.org/wiki/Phong_reflection_model) and reflection/refraction ([Reflections and Refractions in Ray Tracing](http://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf), Bram de Greve, 2006) can be used in conjunction.&#xD;&#xA;&#xD;&#xA;Our materials currently have these properties:&#xD;&#xA;&#xD;&#xA;- ka, kd, ks – ambient, diffuse and specular terms defined as RGB colors&#xD;&#xA;- shininess – Controlling specular highlights (0 ≤ shininess)&#xD;&#xA;- reflectivity – Controls degree of reflectivity (0 ≤ shininess ≤ 1, 0 means not reflective)&#xD;&#xA;- refractive index – Defines the refractive index of the material (0 ≤ refractive index)&#xD;&#xA;&#xD;&#xA;How I understand it, ray tracing as per phong reflection model with reflection and refraction works roughly like this:&#xD;&#xA;&#xD;&#xA;1. The material is (semi)reflective and (semi)transparent (is this a word). In this case reflectivity and transmittance can be calculated with Fresnel equations. However then the reflectivity as specified in the material is ignored. The final color is `reflectivity * trace(reflected_ray, depth + 1) + transmittance * trace(refracted_ray, depth + 1)`.&#xD;&#xA;2. The material is (semi)reflective but not transparent. The reflective component is determined by further ray tracing. The other component is calculated via the equation from the Phong reflection model. Our ray tracer currently adds both components as in `(1 - reflectivity) * color + reflectivity * trace(reflected_ray, depth + 1)` where `color` is determined by the Phong equation.&#xD;&#xA;3. The material is not reflective and not transparent. The Phong equation is used solely.&#xD;&#xA;&#xD;&#xA;How do I know whether a material is (semi)transparent? Do I add a boolean property which I use to determine whether I’m in case 1 or 2?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20318" PostHistoryTypeId="2" PostId="7779" RevisionGUID="d3a67314-ce61-4c25-bbbc-232ddb54718f" CreationDate="2018-07-08T11:00:42.953" UserId="1937" Text="I've been making a simple game in OpenGL, and implemented a screen fade-out using the old 'draw a black fullscreen quad and ramp up the alpha' trick. I'm doing all my shaders in linear space and using `GL_FRAMEBUFFER_SRGB` to automatically apply gamma. When fading out the screen I noticed that the alpha blending also becomes nonlinear - to fade to ~25% brightness I need to use an alpha of ~0.95. &#xD;&#xA;&#xD;&#xA;I fired up Unity for comparison, and its alpha blending also seems to work this way - when rendering in linear mode most of the opacity is bunched towards the top of the alpha range. &#xD;&#xA;&#xD;&#xA;Is this expected behaviour? Is it correct from a PBR point of view? It seems very unintuitive. As a workaround, to get more intuitive blending, would it be reasonable to apply gamma correction of 0.45 to the alpha channel before blending?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20319" PostHistoryTypeId="1" PostId="7779" RevisionGUID="d3a67314-ce61-4c25-bbbc-232ddb54718f" CreationDate="2018-07-08T11:00:42.953" UserId="1937" Text="Alpha blending in linear colour space" ContentLicense="CC BY-SA 4.0" />
  <row Id="20320" PostHistoryTypeId="3" PostId="7779" RevisionGUID="d3a67314-ce61-4c25-bbbc-232ddb54718f" CreationDate="2018-07-08T11:00:42.953" UserId="1937" Text="|blending|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20321" PostHistoryTypeId="2" PostId="7780" RevisionGUID="29b79f26-a219-4241-b765-9960ed7599bc" CreationDate="2018-07-08T11:40:49.660" UserId="7868" Text="The BRDF takes two directions, $\omega o$ and $\omega i$. Some sources (e.g. Physically Based Rendering, 3rd ed., figure 5.18) give diagrams with $\omega o$ and $\omega i$ **both** pointing away from an intersection point, but this is sometimes avoided in practice (e.g. [iq's Oren-Nayar example shader][1]) and I've found I get better results in my own renderer with directions following light transport ($\omega i$ points towards the surface, $\omega o$ points towards the lens). Are BRDFs *strictly* defined for rays pointing away from the surface, or am I misreading things and iq's approach is preferred?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/ldBGz3" ContentLicense="CC BY-SA 4.0" />
  <row Id="20322" PostHistoryTypeId="1" PostId="7780" RevisionGUID="29b79f26-a219-4241-b765-9960ed7599bc" CreationDate="2018-07-08T11:40:49.660" UserId="7868" Text="BRDF ray directions" ContentLicense="CC BY-SA 4.0" />
  <row Id="20323" PostHistoryTypeId="3" PostId="7780" RevisionGUID="29b79f26-a219-4241-b765-9960ed7599bc" CreationDate="2018-07-08T11:40:49.660" UserId="7868" Text="|pathtracing|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20325" PostHistoryTypeId="5" PostId="7780" RevisionGUID="e2cbf9b0-5bc1-4959-b41a-0840f3e059ea" CreationDate="2018-07-08T13:25:29.980" UserId="7868" Comment="Realized I didn't really know what I was saying, cut everything back appropriately" Text="The BRDF takes two directions, $\omega o$ and $\omega i$. I've heard that both directions should point away from the surface (one towards the camera, one towards the light), but [iq's Oren-Nayar example shader][1] totally ignores that rule and works flawlessly. Are BRDFs *strictly* defined for rays pointing away from the surface, or am I misreading things and iq's approach is preferred?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/ldBGz3" ContentLicense="CC BY-SA 4.0" />
  <row Id="20326" PostHistoryTypeId="2" PostId="7781" RevisionGUID="b5487af5-c49a-4a9f-8763-71d10cd93521" CreationDate="2018-07-08T15:17:42.233" UserId="8660" Text="As other answers have mentioned, there are multiple competing formats for storing 3D data.&#xD;&#xA;&#xD;&#xA;However, one specific format has appeared since this question was asked, that has many characteristics you'd expect from a &quot;standard&quot;: **the glTF format**.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;glTF is a 3D standard published by the Khronos Group (the organization behind OpenGL and Vulkan), that aims to make up for the flaws in Collada.&#xD;&#xA;&#xD;&#xA;Its main advantages are:&#xD;&#xA;&#xD;&#xA;- It's JSON-based, which makes it very easy to parse, serialize, read, and send over network.&#xD;&#xA;&#xD;&#xA;- There is very little ambiguity or redundancy in the standard (though there is some*). The units, handedness, texture coordinates signs, etc are all standardized; everything is always index-based, which means there is no data redundancy. This makes it really easy to write an importer.&#xD;&#xA;&#xD;&#xA;- The documentation is very clean and exhaustive.&#xD;&#xA;&#xD;&#xA;- The layout of the data is based on the OpenGL/WebGL workflows, which means that imported models can be used as in-engine data with little plumbing.&#xD;&#xA;&#xD;&#xA;- The standard is Open Source, and the specification is hosted on Github. That means the standard will always be available, usable for free, and the development process is visible to everyone. By opposition, the future of closed-source standards is decided by private interests, which is inherently dangerous.&#xD;&#xA;&#xD;&#xA;- glTF is supported by many industry giants through Khronos (Adobe, Google, Microsoft, Mozilla, Unity); it can be exported by Blender (exporting from Maya is still officially unsupported), and imported by Unreal, Unity and Godot.&#xD;&#xA;&#xD;&#xA;See also:&#xD;&#xA;&#xD;&#xA;* [The official glTF overview][2]&#xD;&#xA;&#xD;&#xA;* [Why we should use glTF 2.0 by the Godot Engine team][1]&#xD;&#xA;&#xD;&#xA;\* I'm pretty sure the variable-handedness tangents are pointless.&#xD;&#xA;&#xD;&#xA;  [1]: https://godotengine.org/article/we-should-all-use-gltf-20-export-3d-assets-game-engines&#xD;&#xA;  [2]: https://www.khronos.org/gltf/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20327" PostHistoryTypeId="2" PostId="7782" RevisionGUID="95a7f929-a325-4725-a281-b876bc087f18" CreationDate="2018-07-08T17:38:15.103" UserId="7462" Text="The full explanation of what I was doing wrong is: &#xD;&#xA;&#xD;&#xA;The depth parameter in the `glTexSubimage3D` rfers to the depth of the data being sent. Since I am trying to send a single layer this depth should be 1 not 0 (the depth of an image/layer) (As explained by Nicol Bolas).&#xD;&#xA;&#xD;&#xA;The zoffset parameter in the same function reffers to the offset in layers where the data will be put inside the texture array.&#xD;&#xA;&#xD;&#xA;In other wrods, following the array analogy, this is the value inside of the brackets. &#xD;&#xA;&#xD;&#xA;The correct approach would thus be:&#xD;&#xA;&#xD;&#xA;    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 894, 894, 1, color_format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;Which in C++ pseudo code would be:&#xD;&#xA;&#xD;&#xA;    Texture_Array[2] = texture;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20328" PostHistoryTypeId="2" PostId="7783" RevisionGUID="93ad801b-7fae-42d3-b7ff-7af0850869e1" CreationDate="2018-07-08T20:42:49.387" UserId="3003" Text="To get a proper circle, you can use a transformation matrix to transform your cell coordinates into equally spaced cartesian coordinates. In the case of your 50 x 100 pixel cells, your transformation matrix would probably either double the width or halve the height. So something like this:&#xD;&#xA;&#xD;&#xA;    | 0.5 0.0 |&#xD;&#xA;    | 0.0 1.0 |&#xD;&#xA;&#xD;&#xA;If you want to draw a circle of radius `r` at a center point `(cx, cy)`, you could iterate over the cells from `(cx - r, cy - r)` to `(cx + r, cy + r)` and test if each one is in the circle, and if so, fill it in, otherwise, don't. Something like this pseudocode:&#xD;&#xA;&#xD;&#xA;    double rSquared = r * r;&#xD;&#xA;    for (int row = cy - r; row &lt; cy + r; row++)&#xD;&#xA;    {&#xD;&#xA;        for (int col = cx - r; col &lt; cx + r; col++)&#xD;&#xA;        {&#xD;&#xA;            double x = col * transform[0][0] + row * transform[0][1];&#xD;&#xA;            double y = col * transform[1][0] + row * transform[1][1];&#xD;&#xA;            double distSquared = x * x + y * y;&#xD;&#xA;            if (distSquared &lt;= rSquared)&#xD;&#xA;            {&#xD;&#xA;                // inside the circle, fill in this cell (col, row)&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                // outside the circle, don't fill in this cell (col, row)&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As for drawing rectangles, it's not clear what you're trying to accomplish there. There's no need to use rectangles when drawing a circle." ContentLicense="CC BY-SA 4.0" />
  <row Id="20329" PostHistoryTypeId="2" PostId="7784" RevisionGUID="6407f9bf-ec01-4227-bddb-34d0569c4784" CreationDate="2018-07-09T04:08:52.930" UserId="110" Text="It has often been recommended to avoid branching conditions in shaders.  &#xD;&#xA;Why?  &#xD;&#xA;What happens exactly in modern GPUs in that case?  &#xD;&#xA;Is it still recommended to avoid branching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20330" PostHistoryTypeId="1" PostId="7784" RevisionGUID="6407f9bf-ec01-4227-bddb-34d0569c4784" CreationDate="2018-07-09T04:08:52.930" UserId="110" Text="How do modern GPUs handle branching instructions in shader code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20331" PostHistoryTypeId="3" PostId="7784" RevisionGUID="6407f9bf-ec01-4227-bddb-34d0569c4784" CreationDate="2018-07-09T04:08:52.930" UserId="110" Text="|shader|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20332" PostHistoryTypeId="2" PostId="7785" RevisionGUID="0b19ce86-a7f4-4f35-9a32-a576783d4870" CreationDate="2018-07-09T04:18:45.017" UserId="110" Text="A compute shader defines the number of threads it requires to be executed.  &#xD;&#xA;This number can be called &quot;local size&quot; or &quot;threadgroup size&quot; according to the API, and be factored into 3 separate dimensions X * Y * Z.&#xD;&#xA;If an algorithm only requires at minimum a small number of threads to be executed, is it more performant to define this number as the local size, and let the GPU handle the parallelization of its execution over a large data-set?  &#xD;&#xA;Or is there any benefit in using a bigger local size?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20333" PostHistoryTypeId="1" PostId="7785" RevisionGUID="0b19ce86-a7f4-4f35-9a32-a576783d4870" CreationDate="2018-07-09T04:18:45.017" UserId="110" Text="Is a smaller local-size/threadgroup-size better for compute shader performance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20334" PostHistoryTypeId="3" PostId="7785" RevisionGUID="0b19ce86-a7f4-4f35-9a32-a576783d4870" CreationDate="2018-07-09T04:18:45.017" UserId="110" Text="|performance|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20335" PostHistoryTypeId="33" PostId="7722" RevisionGUID="1eb7aa35-eb9e-4695-8280-9f1e6990b870" CreationDate="2018-07-09T04:20:03.117" UserId="8889" Comment="47" />
  <row Id="20336" PostHistoryTypeId="5" PostId="7782" RevisionGUID="e0d27691-51e0-4fe5-ade9-3c36f4b0eb66" CreationDate="2018-07-09T05:52:47.547" UserId="7462" Comment="edited body" Text="The full explanation of what I was doing wrong is: &#xD;&#xA;&#xD;&#xA;The depth parameter in the `glTexSubimage3D` refers to the depth of the data being sent. Since I am trying to send a single layer this depth should be 1 not 0 (the depth of an image/layer) (As explained by Nicol Bolas).&#xD;&#xA;&#xD;&#xA;The zoffset parameter in the same function refers to the offset in layers where the data will be put inside the texture array.&#xD;&#xA;&#xD;&#xA;In other words, following the array analogy, this is the value inside of the brackets. &#xD;&#xA;&#xD;&#xA;The correct approach would thus be:&#xD;&#xA;&#xD;&#xA;    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 2, 894, 894, 1, color_format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;Which in C++ pseudo code would be:&#xD;&#xA;&#xD;&#xA;    Texture_Array[2] = texture;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20337" PostHistoryTypeId="50" PostId="7513" RevisionGUID="4a75772c-0b36-4938-ba72-7eabcce534fe" CreationDate="2018-07-09T13:43:13.050" UserId="-1" />
  <row Id="20338" PostHistoryTypeId="5" PostId="7722" RevisionGUID="24a1ccb9-75ee-47a5-9424-d9e61af0bcb2" CreationDate="2018-07-09T15:07:26.897" UserId="8889" Comment="added 2300 characters in body" Text="I'm not sure this is the best place to post this, but it _definitely_ seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.&#xD;&#xA;&#xD;&#xA;On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.&#xD;&#xA;&#xD;&#xA;P.S. If you want to see the code, it's on github at https://github.com/performous/performous&#xD;&#xA;&#xD;&#xA;Relevant files most likely would be (under game/) `video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh` and the actual shaders that live in `data/shaders`&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win7 PC][1]][1]&#xD;&#xA;&#xD;&#xA;Edit: actual drawing call, &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void VertexArray::draw(GLint mode) {&#xD;&#xA;	GLErrorChecker glerror(&quot;VertexArray::draw&quot;);&#xD;&#xA;	if (empty()) return;&#xD;&#xA;	unsigned stride = sizeof(VertexInfo);&#xD;&#xA;	GLint program;&#xD;&#xA;	glGetIntegerv(GL_CURRENT_PROGRAM, &amp;program);&#xD;&#xA;	GLint vertPos = glGetAttribLocation(program, &quot;vertPos&quot;);&#xD;&#xA;	GLint vertTexCoord = glGetAttribLocation(program, &quot;vertTexCoord&quot;);&#xD;&#xA;	GLint vertNormal = glGetAttribLocation(program, &quot;vertNormal&quot;);&#xD;&#xA;	GLint vertColor = glGetAttribLocation(program, &quot;vertColor&quot;);&#xD;&#xA;	glerror.check(&quot;program and attribs&quot;);&#xD;&#xA;	glBindVertexArray(m_vao);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, m_vbo);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo) * size(), &amp;m_vertices.front(), GL_STATIC_DRAW);&#xD;&#xA;	glerror.check(&quot;bind&quot;);&#xD;&#xA;	if (vertPos != -1) {&#xD;&#xA;		glEnableVertexAttribArray(vertPos);&#xD;&#xA;		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, position) : &amp;m_vertices[0].position;&#xD;&#xA;		glVertexAttribPointer(vertPos, 3, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;	}&#xD;&#xA;	if (vertTexCoord != -1) {&#xD;&#xA;		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, texCoord) : &amp;m_vertices[0].texCoord;&#xD;&#xA;		glEnableVertexAttribArray(vertTexCoord);&#xD;&#xA;		glVertexAttribPointer(vertTexCoord, 2, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;	}&#xD;&#xA;	if (vertNormal != -1) {&#xD;&#xA;		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, normal) : &amp;m_vertices[0].normal;&#xD;&#xA;		glEnableVertexAttribArray(vertNormal);&#xD;&#xA;		glVertexAttribPointer(vertNormal, 3, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;	}&#xD;&#xA;	if (vertColor != -1) {&#xD;&#xA;		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, color) : &amp;m_vertices[0].color;&#xD;&#xA;		glEnableVertexAttribArray(vertColor);&#xD;&#xA;		glVertexAttribPointer(vertColor, 4, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;	}&#xD;&#xA;	glerror.check(&quot;enable arrays&quot;);&#xD;&#xA;	glDrawArrays(mode, 0, size());&#xD;&#xA;&#xD;&#xA;	if (vertPos != -1) glDisableVertexAttribArray(vertPos);&#xD;&#xA;	if (vertTexCoord != -1) glDisableVertexAttribArray(vertTexCoord);&#xD;&#xA;	if (vertNormal != -1) glDisableVertexAttribArray(vertNormal);&#xD;&#xA;	if (vertColor != -1) glDisableVertexAttribArray(vertColor);&#xD;&#xA;	if (m_vbo) glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Client-side vertex struct:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;	struct VertexInfo {&#xD;&#xA;		glmath::vec3 position{};&#xD;&#xA;		glmath::vec2 texCoord{};&#xD;&#xA;		glmath::vec3 normal{};&#xD;&#xA;		glmath::vec4 color{ 1.0, 1.0, 1.0, 1.0 };&#xD;&#xA;	};&#xD;&#xA;```&#xD;&#xA;[![Distorted graphics on a win10 laptop][2]][2]&#xD;&#xA;&#xD;&#xA;[![Expected appearance, on my mac][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fF2Af.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/2X29q.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/G6biw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20339" PostHistoryTypeId="5" PostId="7722" RevisionGUID="e870aeac-4871-47d3-a791-ea6f29187137" CreationDate="2018-07-09T15:16:03.720" UserId="8889" Comment="added 2300 characters in body; added 132 characters in body" Text="I'm not sure this is the best place to post this, but it _definitely_ seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.&#xD;&#xA;&#xD;&#xA;On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.&#xD;&#xA;&#xD;&#xA;P.S. If you want to see the code, it's on github at https://github.com/performous/performous&#xD;&#xA;&#xD;&#xA;Relevant files most likely would be (under game/) `video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh` and the actual shaders that live in `data/shaders`&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win7 PC][1]][1]&#xD;&#xA;&#xD;&#xA;Edit: actual drawing call, &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;    void VertexArray::draw(GLint mode) {&#xD;&#xA;    	GLErrorChecker glerror(&quot;VertexArray::draw&quot;);&#xD;&#xA;    	if (empty()) return;&#xD;&#xA;    	unsigned stride = sizeof(VertexInfo);&#xD;&#xA;    	GLint program;&#xD;&#xA;    	glGetIntegerv(GL_CURRENT_PROGRAM, &amp;program);&#xD;&#xA;    	GLint vertPos = glGetAttribLocation(program, &quot;vertPos&quot;);&#xD;&#xA;    	GLint vertTexCoord = glGetAttribLocation(program, &quot;vertTexCoord&quot;);&#xD;&#xA;    	GLint vertNormal = glGetAttribLocation(program, &quot;vertNormal&quot;);&#xD;&#xA;    	GLint vertColor = glGetAttribLocation(program, &quot;vertColor&quot;);&#xD;&#xA;    	glerror.check(&quot;program and attribs&quot;);&#xD;&#xA;    	glBindVertexArray(m_vao);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo) * size(), &amp;m_vertices.front(), GL_STATIC_DRAW);&#xD;&#xA;    	glerror.check(&quot;bind&quot;);&#xD;&#xA;    	if (vertPos != -1) {&#xD;&#xA;    		glEnableVertexAttribArray(vertPos);&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, position) : &amp;m_vertices[0].position;&#xD;&#xA;    		glVertexAttribPointer(vertPos, 3, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	if (vertTexCoord != -1) {&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, texCoord) : &amp;m_vertices[0].texCoord;&#xD;&#xA;    		glEnableVertexAttribArray(vertTexCoord);&#xD;&#xA;    		glVertexAttribPointer(vertTexCoord, 2, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	if (vertNormal != -1) {&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, normal) : &amp;m_vertices[0].normal;&#xD;&#xA;    		glEnableVertexAttribArray(vertNormal);&#xD;&#xA;    		glVertexAttribPointer(vertNormal, 3, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	if (vertColor != -1) {&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, color) : &amp;m_vertices[0].color;&#xD;&#xA;    		glEnableVertexAttribArray(vertColor);&#xD;&#xA;    		glVertexAttribPointer(vertColor, 4, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	glerror.check(&quot;enable arrays&quot;);&#xD;&#xA;    	glDrawArrays(mode, 0, size());&#xD;&#xA;    &#xD;&#xA;    	if (vertPos != -1) glDisableVertexAttribArray(vertPos);&#xD;&#xA;    	if (vertTexCoord != -1) glDisableVertexAttribArray(vertTexCoord);&#xD;&#xA;    	if (vertNormal != -1) glDisableVertexAttribArray(vertNormal);&#xD;&#xA;    	if (vertColor != -1) glDisableVertexAttribArray(vertColor);&#xD;&#xA;    	if (m_vbo) glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;    	glBindVertexArray(0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;Client-side vertex struct:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;	struct VertexInfo {&#xD;&#xA;		glmath::vec3 position{};&#xD;&#xA;		glmath::vec2 texCoord{};&#xD;&#xA;		glmath::vec3 normal{};&#xD;&#xA;		glmath::vec4 color{ 1.0, 1.0, 1.0, 1.0 };&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win10 laptop][2]][2]&#xD;&#xA;&#xD;&#xA;[![Expected appearance, on my mac][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fF2Af.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/2X29q.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/G6biw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20340" PostHistoryTypeId="5" PostId="7722" RevisionGUID="a04a1268-5571-4b04-85bb-c76cb24a0f84" CreationDate="2018-07-09T15:22:42.153" UserId="8889" Comment="Fixed code format" Text="I'm not sure this is the best place to post this, but it _definitely_ seemed more appropriate than programming. I'm one of the developers of Performous, essentially a karaoke (and instruments) game. We use mostly 2D graphics in OpenGL, I don't think anything particularly strange.&#xD;&#xA;&#xD;&#xA;On most machines, everything works perfectly. There's a subset of Intel iGPUs (from what I've been able to ascertain, certain models ranging from around the Ivy Bridge generation to somewhere around Broadwell) that render incredibly distorted, on Windows machines. I've seen it happen on Windows 7 and 10 (presumably it also does on Win8)... never in Linux or OSX, I attempted to reproduce it on a mac mini (that should have been affected) running bootcamp, and was unable to.&#xD;&#xA;&#xD;&#xA;P.S. If you want to see the code, it's on github at https://github.com/performous/performous&#xD;&#xA;&#xD;&#xA;Relevant files most likely would be (under game/) `video_driver.cc/hh, surface.cc/hh, glutil.cc/hh, glshader.cc/hh` and the actual shaders that live in `data/shaders`&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win7 PC][1]][1]&#xD;&#xA;&#xD;&#xA;Edit: actual drawing call, &#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    void VertexArray::draw(GLint mode) {&#xD;&#xA;    	GLErrorChecker glerror(&quot;VertexArray::draw&quot;);&#xD;&#xA;    	if (empty()) return;&#xD;&#xA;    	unsigned stride = sizeof(VertexInfo);&#xD;&#xA;    	GLint program;&#xD;&#xA;    	glGetIntegerv(GL_CURRENT_PROGRAM, &amp;program);&#xD;&#xA;    	GLint vertPos = glGetAttribLocation(program, &quot;vertPos&quot;);&#xD;&#xA;    	GLint vertTexCoord = glGetAttribLocation(program, &quot;vertTexCoord&quot;);&#xD;&#xA;    	GLint vertNormal = glGetAttribLocation(program, &quot;vertNormal&quot;);&#xD;&#xA;    	GLint vertColor = glGetAttribLocation(program, &quot;vertColor&quot;);&#xD;&#xA;    	glerror.check(&quot;program and attribs&quot;);&#xD;&#xA;    	glBindVertexArray(m_vao);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, m_vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(VertexInfo) * size(), &amp;m_vertices.front(), GL_STATIC_DRAW);&#xD;&#xA;    	glerror.check(&quot;bind&quot;);&#xD;&#xA;    	if (vertPos != -1) {&#xD;&#xA;    		glEnableVertexAttribArray(vertPos);&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, position) : &amp;m_vertices[0].position;&#xD;&#xA;    		glVertexAttribPointer(vertPos, 3, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	if (vertTexCoord != -1) {&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, texCoord) : &amp;m_vertices[0].texCoord;&#xD;&#xA;    		glEnableVertexAttribArray(vertTexCoord);&#xD;&#xA;    		glVertexAttribPointer(vertTexCoord, 2, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	if (vertNormal != -1) {&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, normal) : &amp;m_vertices[0].normal;&#xD;&#xA;    		glEnableVertexAttribArray(vertNormal);&#xD;&#xA;    		glVertexAttribPointer(vertNormal, 3, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	if (vertColor != -1) {&#xD;&#xA;    		const GLvoid* ptr = m_vbo ? (GLvoid*)offsetof(VertexInfo, color) : &amp;m_vertices[0].color;&#xD;&#xA;    		glEnableVertexAttribArray(vertColor);&#xD;&#xA;    		glVertexAttribPointer(vertColor, 4, GL_FLOAT, GL_FALSE, stride, ptr);&#xD;&#xA;    	}&#xD;&#xA;    	glerror.check(&quot;enable arrays&quot;);&#xD;&#xA;    	glDrawArrays(mode, 0, size());&#xD;&#xA;    &#xD;&#xA;    	if (vertPos != -1) glDisableVertexAttribArray(vertPos);&#xD;&#xA;    	if (vertTexCoord != -1) glDisableVertexAttribArray(vertTexCoord);&#xD;&#xA;    	if (vertNormal != -1) glDisableVertexAttribArray(vertNormal);&#xD;&#xA;    	if (vertColor != -1) glDisableVertexAttribArray(vertColor);&#xD;&#xA;    	if (m_vbo) glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;    	glBindVertexArray(0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;Client-side vertex struct:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;	struct VertexInfo {&#xD;&#xA;		glmath::vec3 position{};&#xD;&#xA;		glmath::vec2 texCoord{};&#xD;&#xA;		glmath::vec3 normal{};&#xD;&#xA;		glmath::vec4 color{ 1.0, 1.0, 1.0, 1.0 };&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;[![Distorted graphics on a win10 laptop][2]][2]&#xD;&#xA;&#xD;&#xA;[![Expected appearance, on my mac][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fF2Af.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/2X29q.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/G6biw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20341" PostHistoryTypeId="6" PostId="7722" RevisionGUID="a04a1268-5571-4b04-85bb-c76cb24a0f84" CreationDate="2018-07-09T15:22:42.153" UserId="8889" Comment="Fixed code format" Text="|opengl|c++|gpu|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20342" PostHistoryTypeId="5" PostId="7779" RevisionGUID="e8a3abb7-fd92-48c3-819b-a25c6cfb835e" CreationDate="2018-07-09T16:29:23.813" UserId="1937" Comment="added 306 characters in body" Text="I've been making a simple game in OpenGL, and implemented a screen fade-out using the old 'draw a black fullscreen quad and ramp up the alpha' trick. I'm doing all my shaders in linear space and using `GL_FRAMEBUFFER_SRGB` to automatically apply gamma. When fading out the screen I noticed that the alpha blending also becomes nonlinear - to fade to ~25% brightness I need to use an alpha of ~0.95. &#xD;&#xA;&#xD;&#xA;I fired up Unity for comparison, and its alpha blending also seems to work this way - when rendering in linear mode most of the opacity is bunched towards the top of the alpha range. &#xD;&#xA;&#xD;&#xA;Is this expected behaviour? Is it correct from a PBR point of view? It seems very unintuitive. As a workaround, to get more intuitive blending, would it be reasonable to apply gamma correction of 0.45 to the alpha channel before blending?&#xD;&#xA;&#xD;&#xA;EDIT: this is the result I get after blending a .95 alpha black quad over a pure white button. It could be bad gamma on my display as Simon F suggested in the comments, but it looks a lot brighter than 5% to me.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M7Ybs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20343" PostHistoryTypeId="2" PostId="7786" RevisionGUID="1294d1ba-9260-45dc-a05f-e9083c5015f7" CreationDate="2018-07-09T21:54:29.177" UserId="4647" Text="Perspective projection (or at least non-orthogonal) is by far the most common in photo-realistic graphics. When we use perspective projection, the (equally thick) slices of volume visualized by each pixel get larger with the distance. But with ray tracing we normally cast cylinder-like rays instead of cones. It seems to me that this must make quite a difference to the results: consider the two fields of view of pixels: cone-like one at the LHS, and cylinder-like one at the RHS, the pixels are at the bottom:&#xD;&#xA;&#xD;&#xA;[![pixels][1]][1]&#xD;&#xA;&#xD;&#xA;The colored lines here represent walls of randomly-distributed light sources with the same density in each wall. If we assume that the intensities of the light sources are the same, so that one of the pixels would &quot;see&quot; white average color, the other must necessarily have a color tint, because the left one samples more red compared to blue than the right one.&#xD;&#xA;&#xD;&#xA;Am I right in this? If so, why does then _ray_ tracing work? Why don't we do &quot;frustum tracing&quot; or &quot;cone tracing&quot; to get the colors/illuminances right? And if I'm wrong, then what is my mistake?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/X8rGB.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20344" PostHistoryTypeId="1" PostId="7786" RevisionGUID="1294d1ba-9260-45dc-a05f-e9083c5015f7" CreationDate="2018-07-09T21:54:29.177" UserId="4647" Text="Why does _ray_ tracing work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20345" PostHistoryTypeId="3" PostId="7786" RevisionGUID="1294d1ba-9260-45dc-a05f-e9083c5015f7" CreationDate="2018-07-09T21:54:29.177" UserId="4647" Text="|raytracing|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20346" PostHistoryTypeId="5" PostId="7784" RevisionGUID="da25360a-abb0-4483-89f8-23607111d3f5" CreationDate="2018-07-09T21:55:17.070" UserId="6" Comment="Fixed formatting." Text="It has often been recommended to avoid branching conditions in shaders.&#xD;&#xA;&#xD;&#xA;Why? What happens exactly in modern GPUs in that case? &#xD;&#xA;Is it still recommended to avoid branching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20350" PostHistoryTypeId="2" PostId="7788" RevisionGUID="39418d75-3208-44bd-89c5-4423bb7f10ed" CreationDate="2018-07-10T04:38:01.433" UserId="7462" Text="Say we've idetified that we have a varying number of textures that are upper capped by 2 parametrs. thus we allocate the maximum amount of memory needed to store all textures as follows:&#xD;&#xA;&#xD;&#xA;    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, max_width, max_height, texture_num);&#xD;&#xA;&#xD;&#xA;One by one we allocate each texture to each layer as follows:&#xD;&#xA;&#xD;&#xA;    glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, file, width, height, 1, color_format,&#xD;&#xA;                GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;Now since for  some textures width &lt; max_width and height &lt; max_height, when sampling, our sample is off as trying to sample at a value of 1 would result in sampling outside of the bounds of the texture.&#xD;&#xA;&#xD;&#xA;One could naively try to solve the issue by multiplying the sampling coordinate by the stretching coefficient.&#xD;&#xA;&#xD;&#xA;    uv*=width/max_width.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;However this only solves the problem for sampling that happens within the (-1,1) rnage. However, any texture that is meant to be tiled will be wrong. Thus we must do floating mod as well. the final calculation is thus:&#xD;&#xA;&#xD;&#xA;    u = (u*width/max_width)%(width/max_width)&#xD;&#xA;    v = (v*height/max_height)%(height/max_height)&#xD;&#xA;&#xD;&#xA;(Each coordinate is differnece since the vertical stretch could be different from the horizontal stretch)&#xD;&#xA;&#xD;&#xA;Thus to do our final rendering we would need to create and store an array of vec2's where the first value is the horizontal stretching coefficient and the second value is the vertical stretching coefficient on teh CPU. Then load that into a uniform buffer or SSBO.&#xD;&#xA;&#xD;&#xA;And read these values on the shader side. &#xD;&#xA;&#xD;&#xA;This seems a little bit cumbersome. Is there a way to instruct OpenGL to handle these varying sizes or is the only way to solve this issue the one I described?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20351" PostHistoryTypeId="1" PostId="7788" RevisionGUID="39418d75-3208-44bd-89c5-4423bb7f10ed" CreationDate="2018-07-10T04:38:01.433" UserId="7462" Text="Handling varying texture sizes in an array texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="20352" PostHistoryTypeId="3" PostId="7788" RevisionGUID="39418d75-3208-44bd-89c5-4423bb7f10ed" CreationDate="2018-07-10T04:38:01.433" UserId="7462" Text="|opengl|texture|c++|uv-mapping|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20353" PostHistoryTypeId="2" PostId="7789" RevisionGUID="f700daff-84f4-48e6-8490-01daa2b2ba2c" CreationDate="2018-07-10T08:36:30.167" UserId="9002" Text="I am getting weird artifacts in my simple ray tracer that I made using the book [Ray Tracing in One Weekend][1] by Peter Shirley. &#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;(circular pattern on the ground and black tint on the spheres.)&#xD;&#xA;&#xD;&#xA;I suspect these artifacts are due to hit point of the primary rays being under or above the surface, which causes secondary rays to intersect with the object itself. &#xD;&#xA;&#xD;&#xA;I tried to fix this by moving the hit point of primary rays along the surface normal at that point. Here's the result :&#xD;&#xA; &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;&#xD;&#xA;The artifacts are gone but that broke the dielectric material (sphere on the left). It is acting as a reflective sphere rather than a transparent one. &#xD;&#xA;&#xD;&#xA;Code for the dielectric material :&#xD;&#xA; &#xD;&#xA;	virtual bool scatter(const Ray &amp;inRay, const HitInfo &amp;hitInfo, Vector3 &amp;attenuation, Ray &amp;scatteredRay) const {&#xD;&#xA;		attenuation = Vector3(1.0f);&#xD;&#xA;		Vector3 normal;&#xD;&#xA;		Vector3 refracted;&#xD;&#xA;		float refractiveIndexRatio; //n1/n2 = sin(a2)/sin(a)&#xD;&#xA;		float cosine = 0.0f;&#xD;&#xA;&#xD;&#xA;		if (hitInfo.hitNormal * inRay.direction() &gt; 0) {&#xD;&#xA;			normal = -hitInfo.hitNormal;&#xD;&#xA;			refractiveIndexRatio = refractiveIndex;&#xD;&#xA;			cosine = hitInfo.hitNormal * inRay.direction();&#xD;&#xA;		}&#xD;&#xA;		else {&#xD;&#xA;			normal = hitInfo.hitNormal;&#xD;&#xA;			refractiveIndexRatio = 1.0f/refractiveIndex;&#xD;&#xA;			cosine = -hitInfo.hitNormal * inRay.direction();&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;&#xD;&#xA;		float reflectProb = 0.0f;&#xD;&#xA;&#xD;&#xA;		if (Vector3::refract(inRay.direction(), normal, refractiveIndexRatio, refracted)) {&#xD;&#xA;			reflectProb = schlickApproximation(cosine, refractiveIndex);&#xD;&#xA;		}&#xD;&#xA;		else {&#xD;&#xA;			reflectProb = 1.0f;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (randomfloatGenerator() &lt; reflectProb) {&#xD;&#xA;			Vector3 reflected(Vector3::reflect(inRay.direction(), normal));&#xD;&#xA;			scatteredRay = Ray(hitInfo.hitPoint + normal * CORRECTION_FACTOR, reflected);&#xD;&#xA;		}&#xD;&#xA;		else {&#xD;&#xA;			scatteredRay = Ray(hitInfo.hitPoint + normal * CORRECTION_FACTOR, refracted);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I changed `hitInfo.hitPoint` to `hitInfo.hitPoint + normal * CORRECTION_FACTOR`, in the `if - else` case at the bottom of the function, to correct those artifacts. (`CORRECTION_FACTOR = 0.0001f`)  &#xD;&#xA;&#xD;&#xA;How can I correct this &quot;self intersection&quot; problem without breaking my materials ?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.amazon.com/Ray-Tracing-Weekend-Minibooks-Book-ebook/dp/B01B5AODD8&#xD;&#xA;  [2]: https://i.stack.imgur.com/3Gl6W.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bjk8e.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20354" PostHistoryTypeId="1" PostId="7789" RevisionGUID="f700daff-84f4-48e6-8490-01daa2b2ba2c" CreationDate="2018-07-10T08:36:30.167" UserId="9002" Text="Weird artifacts in my ray tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="20355" PostHistoryTypeId="3" PostId="7789" RevisionGUID="f700daff-84f4-48e6-8490-01daa2b2ba2c" CreationDate="2018-07-10T08:36:30.167" UserId="9002" Text="|rendering|raytracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20356" PostHistoryTypeId="2" PostId="7790" RevisionGUID="0891ec11-cfee-4d95-a997-da94ca541060" CreationDate="2018-07-10T08:59:04.867" UserId="2041" Text="&gt; But with ray tracing we normally cast cylinder-like rays instead of cones.&#xD;&#xA;&#xD;&#xA;Rays aren't really cylinders: they're infinitely thin. This infinitely thin ray can be an approximation to the cone just as much as it can be an approximation to the cylinder.&#xD;&#xA;&#xD;&#xA;&gt; If we assume that the intensities of the light sources are the same, so that one of the pixels would &quot;see&quot; white average color, the other must necessarily have a color tint ... Am I right in this?&#xD;&#xA;&#xD;&#xA;Sort of. Your left-hand diagram *doesn't* have a colour tint. Although it covers more of the red wall than the blue wall, both of them subtend the same solid angle from the camera's point of view. The same $\tfrac{1}{r^2}$ ratio between the amount of light included in the cone is exactly countered by the $\tfrac{1}{r^2}$ falloff of the light. If the world worked the way you describe, you could make anything brighter by moving it further away from your eye. The right-hand diagram would have a blue colour tint, because the blue light is closer, but this diagram is not how ray-tracing works.&#xD;&#xA;&#xD;&#xA;There has been research in a few variants of *beam tracing*, where instead of tracing an infinitely thin ray, you trace a cylinder, or *cone tracing*, where you trace a cone or frustum as a simple approximation to the irregular solid that contributes to the pixel. The maths (and therefore the algorithm) are somewhat more complex (and therefore slower) than simple ray tracing, and then you have to deal with what happens when the cone partially intersects an object, and you have to use the same shape to approximate the continued path of the cone. These approaches never caught on.&#xD;&#xA;&#xD;&#xA;Instead, supersampling with rays offers the same advantages as cone tracing but with the performance advantage of doing the same simple algorithm many times. You don't supersample by moving the origin of the rays, which would make a cylinder shape, but by varying the directions, which makes a cone shape. Instead of approximating that cone by a single ray along its axis, you're approximating it by (say) 32 rays spread throughout its volume." ContentLicense="CC BY-SA 4.0" />
  <row Id="20357" PostHistoryTypeId="2" PostId="7791" RevisionGUID="7f38bf1a-f68a-455d-9d38-f32e8d114269" CreationDate="2018-07-10T09:32:54.727" UserId="2041" Text="When spawning the refraction/transmission ray, don't adjust the ray origin by adding the normal: adjust it by *subtracting* the normal. This moves the ray origin inside the object, so it won't immediately self-intersect. Your current problem is caused by all your refraction rays immediately hitting the surface.&#xD;&#xA;&#xD;&#xA;Don't forget that for accurate refractions, the ray needs to be able to intersect with the inside or back face of the object as well. If you're intersecting back-facing surfaces, you need to flip the normal before shading or adding/subtracting it to the origin." ContentLicense="CC BY-SA 4.0" />
  <row Id="20358" PostHistoryTypeId="2" PostId="7792" RevisionGUID="d7200bca-a52c-4819-8a9d-66bfee9c989f" CreationDate="2018-07-10T13:09:26.740" UserId="209" Text="*Just turning the comments into a fully-fledged answer as it* may *prove useful to others*.&#xD;&#xA;&#xD;&#xA;IMHO, the alpha channel should always be linear and treated as such.&#xD;&#xA;&#xD;&#xA;You described blending a black quad over a white background using alpha=0.95, and mapping the result back to non-linear space. We'd expect a resulting, physical intensity value of 0.05.&#xD;&#xA;&#xD;&#xA;If the non-linear space is sRGB, then a linear value of &quot;0.05&quot; would correspond to an sRGB value of &quot;0.248&quot; which, when mapped to 8-bit, is around 63 (or hex, 3D)&#xD;&#xA;&#xD;&#xA;If your display is reasonably calibrated, you can verify this by creating, say, a 5x4 black image, setting one pixel to white, and then tiling that to a suitable size, e.g 200x200 pixels. Then draw a, say, 50x50 square in the middle and fill it with 0x3D3D3D. Here's an example:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you take a few steps back from your monitor and squint, the centre grey region and the dithered outer should be almost indistinguishable, demonstrating a correct physical model. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem you are describing appears to be related to the fact that our visual system is non-linear, much as our hearing is too. For example, the analogue volume control on a hifi amplifier will use a [logarithmic potentiometer rather than a linear one][2] . &#xD;&#xA;&#xD;&#xA;You thus 'simply' need to change your per-frame alpha non-linearly to get a *perceptually* even fade out.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cYTA5.png&#xD;&#xA;  [2]: http://electronics.stackexchange.com/questions/101191/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20359" PostHistoryTypeId="5" PostId="7792" RevisionGUID="d59e319e-34cd-451e-b553-b5c8de4a2935" CreationDate="2018-07-10T13:16:35.727" UserId="209" Comment="added 42 characters in body" Text="*Just turning the comments into a fully-fledged answer as it* may *prove useful to others*.&#xD;&#xA;&#xD;&#xA;IMHO, the alpha channel should always be linear and treated as such.&#xD;&#xA;&#xD;&#xA;You described blending a black quad over a white background using alpha=0.95, and mapping the result back to non-linear space. We'd expect a resulting, physical intensity value of 0.05.&#xD;&#xA;&#xD;&#xA;If the non-linear space is sRGB, then a linear value of &quot;0.05&quot; would correspond to an sRGB value of &quot;0.248&quot; which, when mapped to 8-bit, is around 63 (or hex, 3D)&#xD;&#xA;&#xD;&#xA;If your display is reasonably calibrated, you can verify this by creating, say, a 5x4 black image, setting one pixel to white, and then tiling that to a suitable size, e.g 200x200 pixels. Then draw a, say, 50x50 square in the middle and fill it with 0x3D3D3D. Here's an example:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you take a few steps back from your monitor and squint, the centre grey region and the dithered outer should be almost indistinguishable, demonstrating a correct physical model. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem you are describing appears to be related to the fact that our visual system is non-linear, much as our hearing is too (though probably not with the same curve). For example, the analogue volume control on a hifi amplifier will use a [logarithmic potentiometer rather than a linear one][2] . &#xD;&#xA;&#xD;&#xA;You thus 'simply' need to change your per-frame alpha non-linearly to get a *perceptually* even fade out.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cYTA5.png&#xD;&#xA;  [2]: http://electronics.stackexchange.com/questions/101191/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20360" PostHistoryTypeId="2" PostId="7793" RevisionGUID="adb5e871-7fbf-411a-9c24-209dc804e8dc" CreationDate="2018-07-10T13:46:37.680" UserId="9003" Text="https://youtu.be/f-qTGM5wsnM?t=114&#xD;&#xA;&#xD;&#xA;The entire video is a tutorial on how to achieve the desired effect, the snippet [linked][1] is a demo of it.&#xD;&#xA;&#xD;&#xA;In words the image/video is taken, expanded to fill and blurred. Does it have a specific name I can google and read more about ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/f-qTGM5wsnM?t=114" ContentLicense="CC BY-SA 4.0" />
  <row Id="20361" PostHistoryTypeId="1" PostId="7793" RevisionGUID="adb5e871-7fbf-411a-9c24-209dc804e8dc" CreationDate="2018-07-10T13:46:37.680" UserId="9003" Text="Does this blur background effect have a specific name" ContentLicense="CC BY-SA 4.0" />
  <row Id="20362" PostHistoryTypeId="3" PostId="7793" RevisionGUID="adb5e871-7fbf-411a-9c24-209dc804e8dc" CreationDate="2018-07-10T13:46:37.680" UserId="9003" Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20363" PostHistoryTypeId="2" PostId="7794" RevisionGUID="b4b9bce0-44ae-4732-9a06-85492610adfd" CreationDate="2018-07-10T20:05:06.457" UserId="9005" Text="I'm a newbie interms of CG world. I'm  Curious to know about the applications which uses Vulkan API and their performance compared to other APIs.&#xA;&#xA;As I read, Vulkan has more access to the graphic cards which helps in performance. If so whether the current rendering engines uses it? &#xA;&#xA;Solid works, Revit, sketchup, unity, unreal engine, after effects, etc" ContentLicense="CC BY-SA 4.0" />
  <row Id="20364" PostHistoryTypeId="1" PostId="7794" RevisionGUID="b4b9bce0-44ae-4732-9a06-85492610adfd" CreationDate="2018-07-10T20:05:06.457" UserId="9005" Text="Which 3D applications currently uses Vulkan API?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20365" PostHistoryTypeId="3" PostId="7794" RevisionGUID="b4b9bce0-44ae-4732-9a06-85492610adfd" CreationDate="2018-07-10T20:05:06.457" UserId="9005" Text="|opengl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20366" PostHistoryTypeId="5" PostId="7780" RevisionGUID="f05448b9-7683-4f4f-b5d7-dd9523686a80" CreationDate="2018-07-11T01:15:15.773" UserId="2479" Comment="Minor math formatting improvements" Text="The BRDF takes two directions, $\omega_{o}$ and $\omega_{i}$. I've heard that both directions should point away from the surface (one towards the camera, one towards the light), but [iq's Oren-Nayar example shader][1] totally ignores that rule and works flawlessly. Are BRDFs *strictly* defined for rays pointing away from the surface, or am I misreading things and iq's approach is preferred?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/ldBGz3" ContentLicense="CC BY-SA 4.0" />
  <row Id="20367" PostHistoryTypeId="24" PostId="7780" RevisionGUID="f05448b9-7683-4f4f-b5d7-dd9523686a80" CreationDate="2018-07-11T01:15:15.773" Comment="Proposed by 2479 approved by 7868 edit id of 423" ContentLicense="CC BY-SA 4.0" />
  <row Id="20369" PostHistoryTypeId="2" PostId="7795" RevisionGUID="2fe70411-e75d-4df9-8473-e932b161a35f" CreationDate="2018-07-11T07:15:59.230" UserId="5353" Text="&gt; I'm a newbie in terms of CG world. I'm curious to know about the applications that use Vulkan API and their performances compared to other APIs&#xD;&#xA;&#xD;&#xA;There are some popular magazine websites, such as [PCGamer](https://www.pcgamer.com/doom-benchmarks-return-vulkan-vs-opengl/2/) and [AnandTech](https://www.anandtech.com/show/11223/quick-look-vulkan-3dmark-api-overhead) that has some comparison charts between other rendering APIs.&#xD;&#xA;&#xD;&#xA;**PCGamer compares OpenGL vs Vulkan for Doom (2016)**&#xD;&#xA;![](https://i.stack.imgur.com/z8IEz.png)&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**AnandTech compares Vulkan vs DirectX12 API Overhead**&#xD;&#xA;![](https://i.stack.imgur.com/hhVNo.png)&#xD;&#xA;&#xD;&#xA;I would argue that comparisons make sense on the application-level - one API wouldn't necessarily be better on all occasions than the others. It totally depends on how the graphics developers of the software have architected their system to unlock the APIs full potential.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&gt; As I read, Vulkan has more access to the graphic cards which helps in performance. If so, do the current rendering engines use it?&#xD;&#xA;&lt; &#xD;&#xA;&gt; Solidworks, Revit, Sketchup, Unity3D, Unreal Engine, After Effects, etc. ?&#xD;&#xA;&#xD;&#xA;[Wikipedia: Software that supports Vulkan](https://en.wikipedia.org/wiki/Vulkan_(API)#Software_that_supports_Vulkan) page has a list of software that supports Vulkan API. As for your question, quoting from Wiki page:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;  - Unreal Engine 4 – In February 2016, Epic Games announced Unreal Engine 4 support for Vulkan at Samsung's Galaxy S7 Unpacked&#xD;&#xA;&gt; event.[64][65]&#xD;&#xA;&gt;  - Unity – The engine has support for Vulkan since version 5.6.&#xD;&#xA;&#xD;&#xA;There's plenty of others which are also popular, video games and game engines listed in the Wikipedia page, such as:&#xD;&#xA;&#xD;&#xA; - Dota 2&#xD;&#xA; - Doom&#xD;&#xA; - vkQuake&#xD;&#xA; - Star Citizen&#xD;&#xA; - Wolfenstein II&#xD;&#xA; - CryEngine&#xD;&#xA; - Source 2&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20370" PostHistoryTypeId="5" PostId="7794" RevisionGUID="be4a8d66-aa6d-4e00-a239-7a33f50159ce" CreationDate="2018-07-11T15:44:34.700" UserId="5353" Comment="question is not about opengl - removed tag, fixed grammar" Text="I'm a newbie in terms of CG world. I'm curious to know about the applications that use Vulkan API and their performances compared to other APIs.&#xD;&#xA;&#xD;&#xA;As I read, Vulkan has more access to the graphic cards which helps in performance. If so, do the current rendering engines use it? &#xD;&#xA;&#xD;&#xA;Solidworks, Revit, Sketchup, Unity3D, Unreal Engine, After Effects, etc. ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20371" PostHistoryTypeId="6" PostId="7794" RevisionGUID="be4a8d66-aa6d-4e00-a239-7a33f50159ce" CreationDate="2018-07-11T15:44:34.700" UserId="5353" Comment="question is not about opengl - removed tag, fixed grammar" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20372" PostHistoryTypeId="24" PostId="7794" RevisionGUID="be4a8d66-aa6d-4e00-a239-7a33f50159ce" CreationDate="2018-07-11T15:44:34.700" Comment="Proposed by 5353 approved by 2654, 209 edit id of 424" ContentLicense="CC BY-SA 4.0" />
  <row Id="20373" PostHistoryTypeId="2" PostId="7796" RevisionGUID="0135ce2d-6805-464a-ae8b-7c3bc8f6409b" CreationDate="2018-07-11T18:37:33.133" UserId="4647" Text="It's useful to think of rays not as &quot;tubes&quot; or &quot;cones&quot; of vision, but as the units of bookkeeping of radiant power. This notion resembles that of photons: they also are emitted and detected as a whole, and, for a given frequency, light intensity is represented by density of these units, while the energy per unit doesn't change as the unit propagates.&#xD;&#xA;&#xD;&#xA;Consider, for example, the well-known inverse-square law for intensity of light emitted by an isotropic source. Starting with $N$ rays emitted by a surface of area $A$, you'll see that these rays, propagating outwards, have more and more space between them – their density reduces, while number of them, $N$, remains the same (in empty space). Calculate average number of rays per unit surface at distance $r$, and you'll see that it's indeed proportional to $r^{-2}$.&#xD;&#xA;&#xD;&#xA;Now, the above example was about forward ray tracing. Backward ray tracing is actually exactly the same, but the question of each ray is not &quot;what object might absorb me?&quot; – instead, it's &quot;where could this unit of light come from?&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="20374" PostHistoryTypeId="2" PostId="7797" RevisionGUID="ca3b00d2-8a2f-4ca1-882e-a7cb57a924c5" CreationDate="2018-07-11T20:37:05.883" UserId="7462" Text="I am reading this [piece of documentation][1] to understand mtl files&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So far I am stuck trying to understand the difference between ambient, diffuse and specular reflectivity (Ka, Kd, Ks).&#xD;&#xA;&#xD;&#xA;If I am correct specular is &quot;straight line&quot; reflectivity (the kind of reflectivity of mirors), diffuse is the reflectivity of scattered light (the kind of reflectivity of many rough plastics). But then what is ambient reflectivity?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://paulbourke.net/dataformats/mtl/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20375" PostHistoryTypeId="1" PostId="7797" RevisionGUID="ca3b00d2-8a2f-4ca1-882e-a7cb57a924c5" CreationDate="2018-07-11T20:37:05.883" UserId="7462" Text="Understanding material .mtl files" ContentLicense="CC BY-SA 4.0" />
  <row Id="20376" PostHistoryTypeId="3" PostId="7797" RevisionGUID="ca3b00d2-8a2f-4ca1-882e-a7cb57a924c5" CreationDate="2018-07-11T20:37:05.883" UserId="7462" Text="|rendering|color|global-illumination|reflection|material|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20377" PostHistoryTypeId="50" PostId="4632" RevisionGUID="d4bb6628-325c-4ade-b1e9-968bfb3fd75c" CreationDate="2018-07-12T00:56:51.087" UserId="-1" />
  <row Id="20378" PostHistoryTypeId="2" PostId="7798" RevisionGUID="9800c43e-fdc9-440f-b3d1-32549897b122" CreationDate="2018-07-12T04:19:06.543" UserId="5353" Text="![](https://i0.wp.com/upload.wikimedia.org/wikipedia/commons/thumb/e/ed/BRDF_Diagram.svg/800px-BRDF_Diagram.svg.png)&#xD;&#xA;&#xD;&#xA;This diagram is accurate. Let's look at the code:&#xD;&#xA;&#xD;&#xA;    float OrenNayar( in vec3 l, in vec3 n, in vec3 v, float r )&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;        float r2 = r*r;&#xD;&#xA;        float a = 1.0 - 0.5*(r2/(r2+0.57));&#xD;&#xA;        float b = 0.45*(r2/(r2+0.09));&#xD;&#xA;    &#xD;&#xA;        float nl = dot(n, l);&#xD;&#xA;        float nv = dot(n, v);&#xD;&#xA;    &#xD;&#xA;        float ga = dot(v-n*nv,n-n*nl);&#xD;&#xA;    &#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The first three parameters passed in (`l`, `n`, `v`) correspond to `W_i`, `n`, and `W_o` vectors, respectively. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, both `l` and `v` are used in a [`dot` product]() with `n`: This is done for a purpose.&#xD;&#xA;&#xD;&#xA;The dot product gives you the cosine of the angle between the two parameters if both of the parameters are normalized vectors. Otherwise it gives you the cosine of the angle between the vectors, scaled by the product of the length of those vectors &#xD;&#xA;&#xD;&#xA;    dot(l, n) = len(l) * len(n) * cos(theta) &#xD;&#xA;&#xD;&#xA;where `theta` is the angle between `l` and `n`. As we normalize our vectors, we can forget about the length and directly associate the dot product with the `cos(theta)` value.&#xD;&#xA;&#xD;&#xA;The value of the dot product ranges between [-1, +1] since cosine values, by definition, range between [-1, +1]. &#xD;&#xA; - If dot product is 1, it means that both the vectors are pointing in the same direction&#xD;&#xA; - If dot product is 0 (or very close to zero), it means that the vectors are exactly (or almost if its close to 0) perpendicular to each other.&#xD;&#xA; - If dot product is -1, it means that the two vectors point in the opposite direction&#xD;&#xA;&#xD;&#xA;**In other words, dot product kind of measures how similar the vectors are in terms of the direction they point to.**&#xD;&#xA;&#xD;&#xA;Since we compare how similar `n` and `l` is to the `n` vector, we kind of look into where `n` and `l` points to relative to the surface normal. Since the surface normal points away from the surface, the vectors that have a dot product with `n` larger than 0 also point 'away' from the surface.&#xD;&#xA;&#xD;&#xA;Now let's look at the last part of the code:&#xD;&#xA;&#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;&#xD;&#xA;Notice this: **`max(0.0,nl)`** ?&#xD;&#xA;&#xD;&#xA;This expression would evaluate to 0 if the `NdotL` is less than 0. In other words, if the light direction is pointing into the surface we don't take into account the contribution of that light.&#xD;&#xA;&#xD;&#xA;So, the code provided doesn't ignore rule." ContentLicense="CC BY-SA 4.0" />
  <row Id="20379" PostHistoryTypeId="5" PostId="7798" RevisionGUID="300064bb-9eca-455b-b581-816b3b2dae66" CreationDate="2018-07-12T04:24:14.023" UserId="5353" Comment="added 304 characters in body" Text="![](https://i0.wp.com/upload.wikimedia.org/wikipedia/commons/thumb/e/ed/BRDF_Diagram.svg/800px-BRDF_Diagram.svg.png)&#xD;&#xA;&#xD;&#xA;This diagram is accurate. Let's look at the code:&#xD;&#xA;&#xD;&#xA;    float OrenNayar( in vec3 l, in vec3 n, in vec3 v, float r )&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;        float r2 = r*r;&#xD;&#xA;        float a = 1.0 - 0.5*(r2/(r2+0.57));&#xD;&#xA;        float b = 0.45*(r2/(r2+0.09));&#xD;&#xA;    &#xD;&#xA;        float nl = dot(n, l);&#xD;&#xA;        float nv = dot(n, v);&#xD;&#xA;    &#xD;&#xA;        float ga = dot(v-n*nv,n-n*nl);&#xD;&#xA;    &#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The first three parameters passed in (`l`, `n`, `v`) correspond to `W_i`, `n`, and `W_o` vectors, respectively. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, both `l` and `v` are used in a [`dot` product](https://en.wikipedia.org/wiki/Dot_product) with `n`: This is done for a purpose.&#xD;&#xA;&#xD;&#xA;The dot product gives you the cosine of the angle between the two parameters if both of the parameters are normalized vectors. Otherwise, it gives you the cosine of the angle between the vectors, scaled by the product of the length of those vectors &#xD;&#xA;&#xD;&#xA;    dot(l, n) = len(l) * len(n) * cos(theta) &#xD;&#xA;&#xD;&#xA;where `theta` is the angle between `l` and `n`. &#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Zr9wa.png)&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;[image source](https://www.mathsisfun.com/algebra/vectors-dot-product.html)&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;As we normalize our vectors, we can forget about the length and directly associate the dot product with the `cos(theta)` value.&#xD;&#xA;&#xD;&#xA;The value of the dot product ranges between [-1, +1] since cosine values, by definition, range between [-1, +1]. &#xD;&#xA;&#xD;&#xA; - If dot product is 1, it means that both the vectors are pointing in the same direction&#xD;&#xA; - If dot product is 0 (or very close to zero), it means that the vectors are exactly (or almost if its close to 0) perpendicular to each other.&#xD;&#xA; - If dot product is -1, it means that the two vectors point in the opposite direction&#xD;&#xA;&#xD;&#xA;**In other words, dot product kind of measures how similar the vectors are in terms of the direction they point to.**&#xD;&#xA;&#xD;&#xA;Since we compare how similar `n` and `l` is to the `n` vector, we kind of look into where `n` and `l` points to relative to the surface normal. Since the surface normal points away from the surface, the vectors that have a dot product with `n` larger than 0 also point *away* from the surface.&#xD;&#xA;&#xD;&#xA;Now let's look at the last part of the code:&#xD;&#xA;&#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;&#xD;&#xA;Notice this: **`max(0.0,nl)`** ?&#xD;&#xA;&#xD;&#xA;This expression would evaluate to 0 if the `NdotL` is less than 0. In other words, if the light direction is pointing *into* the surface we don't take into account the contribution of that light.&#xD;&#xA;&#xD;&#xA;So, the code provided doesn't ignore the rule: In order for the BRDF to return a positive light contribution value, the light vector should point away from the surface." ContentLicense="CC BY-SA 4.0" />
  <row Id="20380" PostHistoryTypeId="2" PostId="7799" RevisionGUID="a3d6a1d3-ae56-4e30-aea5-eb237ef5a2b5" CreationDate="2018-07-12T04:32:32.467" UserId="5353" Text="@PaulHK explained it very well in the comment section:&#xD;&#xA;&#xD;&#xA; &gt; Ambient is a (rough) approximation of indirect lighting. For example, an outdoor object would be lit by the sun but the surfaces facing away from sun would be black if using only lambert shading, we can use dark gray for the ambient colour to mimic the effect of indirect lighting from the ground and sky&#xD;&#xA;&#xD;&#xA;If you were to visualize this with a shading model, say Phong, the Ka, Kd and Ks values would correspond to the following lighting calculations.&#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/n5SA0.png)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20381" PostHistoryTypeId="5" PostId="7798" RevisionGUID="3fec0cf6-c2ff-4f62-a2c0-e4c1ccb9ccd5" CreationDate="2018-07-12T04:34:25.403" UserId="5353" Comment="fixed incorrect vectors" Text="![](https://i0.wp.com/upload.wikimedia.org/wikipedia/commons/thumb/e/ed/BRDF_Diagram.svg/800px-BRDF_Diagram.svg.png)&#xD;&#xA;&#xD;&#xA;This diagram is accurate. Let's look at the code:&#xD;&#xA;&#xD;&#xA;    float OrenNayar( in vec3 l, in vec3 n, in vec3 v, float r )&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;        float r2 = r*r;&#xD;&#xA;        float a = 1.0 - 0.5*(r2/(r2+0.57));&#xD;&#xA;        float b = 0.45*(r2/(r2+0.09));&#xD;&#xA;    &#xD;&#xA;        float nl = dot(n, l);&#xD;&#xA;        float nv = dot(n, v);&#xD;&#xA;    &#xD;&#xA;        float ga = dot(v-n*nv,n-n*nl);&#xD;&#xA;    &#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The first three parameters passed in (`l`, `n`, `v`) correspond to `W_i`, `n`, and `W_o` vectors, respectively. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, both `l` and `v` are used in a [`dot` product](https://en.wikipedia.org/wiki/Dot_product) with `n`: This is done for a purpose.&#xD;&#xA;&#xD;&#xA;The dot product gives you the cosine of the angle between the two parameters if both of the parameters are normalized vectors. Otherwise, it gives you the cosine of the angle between the vectors, scaled by the product of the length of those vectors &#xD;&#xA;&#xD;&#xA;    dot(l, n) = len(l) * len(n) * cos(theta) &#xD;&#xA;&#xD;&#xA;where `theta` is the angle between `l` and `n`. &#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Zr9wa.png)&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;[image source](https://www.mathsisfun.com/algebra/vectors-dot-product.html)&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;As we normalize our vectors, we can forget about the length and directly associate the dot product with the `cos(theta)` value.&#xD;&#xA;&#xD;&#xA;The value of the dot product ranges between [-1, +1] since cosine values, by definition, range between [-1, +1]. &#xD;&#xA;&#xD;&#xA; - If dot product is 1, it means that both the vectors are pointing in the same direction&#xD;&#xA; - If dot product is 0 (or very close to zero), it means that the vectors are exactly (or almost if its close to 0) perpendicular to each other.&#xD;&#xA; - If dot product is -1, it means that the two vectors point in the opposite direction&#xD;&#xA;&#xD;&#xA;**In other words, dot product kind of measures how similar the vectors are in terms of the direction they point to.**&#xD;&#xA;&#xD;&#xA;Since we compare how similar `v` and `l` is to the `n` vector, we kind of look into where `v` and `l` points to relative to the surface normal. Since the surface normal points away from the surface by definition, the vectors that have a dot product with `n` larger than 0 also point *away* from the surface.&#xD;&#xA;&#xD;&#xA;Now let's look at the last part of the code:&#xD;&#xA;&#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;&#xD;&#xA;Notice this: **`max(0.0,nl)`** ?&#xD;&#xA;&#xD;&#xA;This expression would evaluate to 0 if the `NdotL` is less than 0. In other words, if the light direction is pointing *into* the surface we don't take into account the contribution of that light.&#xD;&#xA;&#xD;&#xA;So, the code provided doesn't ignore the rule: In order for the BRDF to return a positive light contribution value, the light vector should point away from the surface." ContentLicense="CC BY-SA 4.0" />
  <row Id="20382" PostHistoryTypeId="5" PostId="7780" RevisionGUID="7a1f7026-297f-45f0-a0c5-04754d65bb1b" CreationDate="2018-07-12T05:19:16.937" UserId="7868" Comment="Edit for tone and clarity" Text="The BRDF takes two directions, $\omega_{o}$ and $\omega_{i}$. I've heard that both directions should point away from the surface (one towards the camera, one towards the light), but [iq's Oren-Nayar example shader][1] has rays pointing away from the camera and works flawlessly. Are BRDFs *strictly* defined for rays pointing away from the surface, or am I misreading things and iq's approach is preferred?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/ldBGz3" ContentLicense="CC BY-SA 4.0" />
  <row Id="20386" PostHistoryTypeId="5" PostId="6223" RevisionGUID="af1d5741-6fcf-42c6-a0ea-e8a7f23923d5" CreationDate="2018-07-12T13:44:06.660" UserId="209" Comment="Minor improvements to English" Text="Euler rotations work around the axes. This is represented in 3 angles (rot_x, rot_y, rot_z). The order of the rotation needs to be determined as the order affects the result.&#xD;&#xA;&#xD;&#xA;For example, if we have a point (1, 0, 0) and we rotate 90 degrees around the Y and then 90 degrees around the Z, then the result will be&#xD;&#xA;&#xD;&#xA;    v1 = (1,0,0)&#xD;&#xA;    v2 = rotate_y(v1, 90) # v2 = (0,0,1)&#xD;&#xA;    v3 = rotate_z(c2, 90) # v3 = (0,0,1)&#xD;&#xA;&#xD;&#xA;When doing the other order first Z and then Y, the result is different:&#xD;&#xA;&#xD;&#xA;    v1 = (1,0,0)&#xD;&#xA;    v2 = rotate_z(v1, 90) # v2 = (0,1,0)&#xD;&#xA;    v3 = rotate_y(c2, 90) # v3 = (0,1,0)&#xD;&#xA;&#xD;&#xA;In computer graphics systems, quaternion rotations are often used, which allows rotation around any axis. This then solves many of the problems with Euler systems." ContentLicense="CC BY-SA 4.0" />
  <row Id="20394" PostHistoryTypeId="2" PostId="7802" RevisionGUID="968593a9-94c0-47ef-a7cb-39276fe9f55d" CreationDate="2018-07-12T16:22:25.850" UserId="8889" Text="As mentioned on a comment, after talking about it on IRC, they helped me realize the bug was in the geometry shader that was being used for Stereo 3D.&#xD;&#xA;&#xD;&#xA;Due to the way it was conceived (which was apparently a really bad idea), the shader was always compiled and linked if the hardware reported supporting OpenGL3.30 and **GL_arb_viewport_array**.&#xD;&#xA;&#xD;&#xA;When the stereo3d option was disabled, via a very hacky solution, the shader was put into a &quot;pass-through&quot; mode which is supposed to do nothing but (still not sure if it's a bug in the shader itself or a hardware/driver issue) it was sending a lot of undefined values to the fragment shader, instead.&#xD;&#xA;&#xD;&#xA;Here's the offending code:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    #extension GL_ARB_viewport_array : require&#xD;&#xA;    &#xD;&#xA;    uniform float sepFactor;&#xD;&#xA;    uniform float z0;&#xD;&#xA;    &#xD;&#xA;    layout(triangles) in;&#xD;&#xA;    layout(triangle_strip, max_vertices = 6) out;&#xD;&#xA;    &#xD;&#xA;    struct vData {&#xD;&#xA;    	vec3 lightDir;&#xD;&#xA;    	vec2 texCoord;&#xD;&#xA;    	vec3 normal;&#xD;&#xA;    	vec4 color;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    in vData vertex[];&#xD;&#xA;    out vData fragv;&#xD;&#xA;    &#xD;&#xA;    void passthru(int i) {&#xD;&#xA;    	gl_Position = gl_in[i].gl_Position;&#xD;&#xA;    	fragv = vertex[i];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Process all the vertices, applying code to them before emitting (do-while to convince Nvidia of the code getting executed)&#xD;&#xA;    #define PROCESS(code) i = 0; do { passthru(i); code; EmitVertex(); } while (++i &lt; 3); EndPrimitive();&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	int i = 0;&#xD;&#xA;    	if (sepFactor == 0.0) {&#xD;&#xA;    		gl_ViewportIndex = 0; PROCESS(;); // No stereo&#xD;&#xA;    	} else {&#xD;&#xA;    		gl_ViewportIndex = 1; PROCESS(gl_Position.x -= sepFactor * (gl_Position.z - z0));  // Left eye&#xD;&#xA;    		gl_ViewportIndex = 2; PROCESS(gl_Position.x += sepFactor * (gl_Position.z - z0));  // Right eye&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have sort-of solved it by actually recompiling and relinking the shaders to include the geometry shader or not when stereo3d is toggled.&#xD;&#xA;&#xD;&#xA;I've also rewritten the shader to look like this (it still produces skewed geometry but atleast akin to the first screenshot, instead of the second),&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    #extension GL_ARB_viewport_array : require&#xD;&#xA;    &#xD;&#xA;    uniform highp float sepFactor;&#xD;&#xA;    uniform highp float z0;&#xD;&#xA;    &#xD;&#xA;    layout(triangles) in;&#xD;&#xA;    layout(triangle_strip, max_vertices = 6) out;&#xD;&#xA;    &#xD;&#xA;    in vData {&#xD;&#xA;    	highp vec3 lightDir;&#xD;&#xA;    	highp vec2 texCoord;&#xD;&#xA;    	highp vec3 normal;&#xD;&#xA;    	highp vec4 color;&#xD;&#xA;    } vertices[];&#xD;&#xA;    &#xD;&#xA;    out vData {&#xD;&#xA;    	highp vec3 lightDir;&#xD;&#xA;    	highp vec2 texCoord;&#xD;&#xA;    	highp vec3 normal;&#xD;&#xA;    	highp vec4 color;&#xD;&#xA;    } fragv;&#xD;&#xA;    &#xD;&#xA;    void passthru(int vp, int i) {&#xD;&#xA;    		gl_Position = gl_in[i].gl_Position;&#xD;&#xA;    		gl_ViewportIndex = (sepFactor == 0.0) ? 0 : vp;&#xD;&#xA;    		gl_Position.x -= (sepFactor * (gl_Position.z - z0));&#xD;&#xA;    		fragv.lightDir = vertices[i].lightDir;&#xD;&#xA;    		fragv.texCoord = vertices[i].texCoord;&#xD;&#xA;    		fragv.normal = vertices[i].normal;&#xD;&#xA;    		fragv.color = vertices[i].color;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    		// Render the left eye&#xD;&#xA;    	int i = 0;&#xD;&#xA;    	do {&#xD;&#xA;    		passthru(1, i);&#xD;&#xA;    		gl_Position.x -= (sepFactor * (gl_Position.z - z0));&#xD;&#xA;    		EmitVertex();		&#xD;&#xA;    		} while (++i &lt; 3);&#xD;&#xA;    		EndPrimitive();&#xD;&#xA;    	&#xD;&#xA;    	i = 0;&#xD;&#xA;    		// Render the right eye&#xD;&#xA;    	do {&#xD;&#xA;    		passthru(2, i);&#xD;&#xA;    		gl_Position.x += (sepFactor * (gl_Position.z - z0));&#xD;&#xA;    		EmitVertex();		&#xD;&#xA;    		} while (++i &lt; 3);&#xD;&#xA;    		EndPrimitive();&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="20399" PostHistoryTypeId="2" PostId="7804" RevisionGUID="b6949f34-e74d-4945-b191-8190306d4ad5" CreationDate="2018-07-13T10:11:07.267" UserId="9021" Text="I'm writing a CAD program in vulkan. In my current design, I have line paths represented as large vertex buffers for rendering. I would like to implement an algorithm for extruding the path outwards, based off of cross products. Ideally I would like to implement this algorithm within a computer shader, using the vertex buffer in place of a storage buffer. The algorithm would work like this: for each vertex in original path, calculate cross product based off of the two surrounding vertices in the buffer, then normalize and multiply by a scalar. I'm fairly certain that this could be done by copying the vertex buffer to a storage buffer temporarily, but I doubt that's optimal, unless it's not actually physically copied. I don't see why I should move large chunks of data from vram to vram like that. It would probably, be faster to implement this algorithm locally on the CPU in that case. I don't have much experience using compute shaders; any input is appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="20400" PostHistoryTypeId="1" PostId="7804" RevisionGUID="b6949f34-e74d-4945-b191-8190306d4ad5" CreationDate="2018-07-13T10:11:07.267" UserId="9021" Text="Feeding vertex data to a computer shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="20401" PostHistoryTypeId="3" PostId="7804" RevisionGUID="b6949f34-e74d-4945-b191-8190306d4ad5" CreationDate="2018-07-13T10:11:07.267" UserId="9021" Text="|algorithm|compute-shader|vulkan|buffers|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20402" PostHistoryTypeId="4" PostId="7804" RevisionGUID="9312fdea-ea38-40ab-ba43-5e5329d9d9c7" CreationDate="2018-07-13T10:24:49.790" UserId="9022" Comment="Fixed title" Text="Feeding vertex data to a compute shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="20403" PostHistoryTypeId="24" PostId="7804" RevisionGUID="9312fdea-ea38-40ab-ba43-5e5329d9d9c7" CreationDate="2018-07-13T10:24:49.790" Comment="Proposed by 9022 approved by -1 edit id of 427" ContentLicense="CC BY-SA 4.0" />
  <row Id="20404" PostHistoryTypeId="5" PostId="7804" RevisionGUID="5d9ca449-dc73-4b66-8e4d-af8235259e50" CreationDate="2018-07-13T10:24:49.790" UserId="2041" Comment="Fix a typo in a couple of places, and let's split it to two paragraphs to make it look less of a &quot;wall of text&quot;." Text="I'm writing a CAD program in vulkan. In my current design, I have line paths represented as large vertex buffers for rendering. I would like to implement an algorithm for extruding the path outwards, based off of cross products. Ideally I would like to implement this algorithm within a compute shader, using the vertex buffer in place of a storage buffer. The algorithm would work like this: for each vertex in original path, calculate cross product based off of the two surrounding vertices in the buffer, then normalize and multiply by a scalar.&#xD;&#xA;&#xD;&#xA;I'm fairly certain that this could be done by copying the vertex buffer to a storage buffer temporarily, but I doubt that's optimal, unless it's not actually physically copied. I don't see why I should move large chunks of data from VRAM to VRAM like that. It would probably, be faster to implement this algorithm locally on the CPU in that case. I don't have much experience using compute shaders; any input is appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="20405" PostHistoryTypeId="2" PostId="7805" RevisionGUID="ce7cffaf-8215-4356-9878-6edc50c13e77" CreationDate="2018-07-13T11:02:44.917" UserId="137" Text="You will need a new chunk of memory for the new surface anyway, so why not read from the original and store directly in the result.&#xD;&#xA;&#xD;&#xA;Having precomputed normals will reduce a lot of the computation requirements though (especially needing to find&amp;read each neighbour), the user action of the extrusion will probably be interactive so you will have multiple frames with different extrusion amounts but the normals of the original surface won't change. Having the normals be around will likely be helpful for other operations as well. You could make the temporary transformed geometry just a vertex shader trick as well and only commit the result once needed.&#xD;&#xA;&#xD;&#xA;Computing normals is much simpler by going face per face and then summing the the non-normalized normals per vertex and normalizing after.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20408" PostHistoryTypeId="2" PostId="7806" RevisionGUID="5636a4a3-7eb7-4054-945d-4058fdd8008b" CreationDate="2018-07-13T16:40:18.160" UserId="8877" Text="maybe you forget to call MTLBlitCommandEncoder.synchronizeTexture to sync VRAM to system memory.&#xD;&#xA;&#xD;&#xA;please check: &#xD;&#xA;https://forums.developer.apple.com/thread/30488&#xD;&#xA;&#xD;&#xA;and document:&#xD;&#xA;https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400757-synchronize" ContentLicense="CC BY-SA 4.0" />
  <row Id="20409" PostHistoryTypeId="2" PostId="7807" RevisionGUID="bb6f11cf-2452-472e-8354-2f78e88c81de" CreationDate="2018-07-13T17:24:53.467" UserId="9025" Text="I have ported their WebGL demo in DX shader model 4, but I have not implemented such texture preprocessing. Instead, I use some abstract pattern (like a comuflage) that is twice wider and higher. So, in a reflected area only internal part is rendered if roughness is low, and with a greater roughness, mip-map with lower resolution is taken. That spreads pattern in zone of reflection realistically.&#xD;&#xA;It could be some starting point for your implementation.  &#xD;&#xA;&#xD;&#xA;It is possible to make some &quot;texture expansion&quot; like in article, but some special code to do this is needed. This is &quot;special&quot;, it modifies Gaussian. &#xD;&#xA;&#xD;&#xA;But in many cases, reflected pattern could be very simple, and such expansion can be eailly created by artist and mip chain generated. Again -good for start point.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="20410" PostHistoryTypeId="50" PostId="6180" RevisionGUID="5f7d8dad-5a56-485d-b664-79f0de7f5d12" CreationDate="2018-07-13T21:18:30.853" UserId="-1" />
  <row Id="20417" PostHistoryTypeId="2" PostId="7809" RevisionGUID="c9123293-5727-4e6f-8cd7-09b088141c67" CreationDate="2018-07-14T15:23:13.830" UserId="9028" Text="Sorry for repost, my goal wasn't to be on the top of the list xd. I just thought this wasn't the good place for this question but finally, I don't really see where else I could post it if not here. ;)&#xD;&#xA;&#xD;&#xA;I'm new to GPU programming.&#xD;&#xA;  I have played around with CPU assembly programming like Nasm, Tasm or Masm, but I'm really curious to know how GPU works now.&#xD;&#xA;  However, i'm quite confused when I look on internet. I've heard about Cuda and OpenCL, but it is not what I'm looking for.&#xD;&#xA;  I'd like to know how GPUs instructions are in RAM... What are the Nasm and Masm for most GPUs? What is the x86 or Z80 of GPUs (What are the different families of GPU)? Do you know a constructor opcodes reference manual?&#xD;&#xA;  I think I really need something to compare between the two Processing Units to make it clear, because GPU assembly programming seems to be an even harder subject to learn from on internet that CPU asm programming. I've also read that &quot;NVIDIA never released details on the instructions actually understood by their hardware&quot;, but it seems pretty surprising to me. Full post there: https://stackoverflow.com/questions/4660974/how-to-create-or-manipulate-gpu-assembler?newreg=e31519279ce949f087df6322dbf2bf4d&#xD;&#xA;&#xD;&#xA;Thanks for your help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="20418" PostHistoryTypeId="1" PostId="7809" RevisionGUID="c9123293-5727-4e6f-8cd7-09b088141c67" CreationDate="2018-07-14T15:23:13.830" UserId="9028" Text="How does GPU assembly looks like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20419" PostHistoryTypeId="3" PostId="7809" RevisionGUID="c9123293-5727-4e6f-8cd7-09b088141c67" CreationDate="2018-07-14T15:23:13.830" UserId="9028" Text="|gpu|assembly|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20423" PostHistoryTypeId="2" PostId="7811" RevisionGUID="5d9d5487-3d5f-4771-b89f-f32bf65123a6" CreationDate="2018-07-14T22:43:31.310" UserId="7462" Text="I am currently rendering a scne in the most standard fashion possible (triangle projection and blinn-phong for shading)&#xD;&#xA;&#xD;&#xA;However I am getting some artifacts:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the lion head is not rendered properly. Moreover, this artifacts are flickering, but the proportion of how much tehy flicker is proportional to the distance to the lion. That is to say. If you are close to the lion there are no artifacts. But the farther away you go the more artifacts appear. I believe this is due to Z buffer imprecissions. How can I solve this?&#xD;&#xA;  [1]: https://i.stack.imgur.com/n87Fg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20424" PostHistoryTypeId="1" PostId="7811" RevisionGUID="5d9d5487-3d5f-4771-b89f-f32bf65123a6" CreationDate="2018-07-14T22:43:31.310" UserId="7462" Text="How to solve Z buffer artifacts" ContentLicense="CC BY-SA 4.0" />
  <row Id="20425" PostHistoryTypeId="3" PostId="7811" RevisionGUID="5d9d5487-3d5f-4771-b89f-f32bf65123a6" CreationDate="2018-07-14T22:43:31.310" UserId="7462" Text="|opengl|antialiasing|buffers|artifacts|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20434" PostHistoryTypeId="2" PostId="7812" RevisionGUID="71ede331-11b5-4d51-8f28-662c3f438043" CreationDate="2018-07-15T01:51:28.903" UserId="6046" Text="So I'm in the midst of implementing a path-tracer. I have chosen to use Assimp library to load models and scene information.&#xD;&#xA;&#xD;&#xA;According to it, it will provide mesh data and meshes may contain point, line, triangles and polygons primitives. It gives the option to triangulate polygons but I don't know what to do with lines and points. Should I ignore them?&#xD;&#xA;&#xD;&#xA;This leads to a bigger question that came in my mind. Can we ray-trace points and lines? I wanted to use this kind of thing once to show my Bounding boxes in wire frame mode but didn't know how I would trace only the boundaries.&#xD;&#xA;&#xD;&#xA;I'm guessing this has to do with providing a specific line/point width? Else they are too thin for intersection. &#xD;&#xA;&#xD;&#xA;If we can render lines and points, then should I ignore them or not in my path tracer? Will I be missing out on details etc? Don't know what are they used to represent in 3D models as I have only seen triangles/polygons. " ContentLicense="CC BY-SA 4.0" />
  <row Id="20435" PostHistoryTypeId="1" PostId="7812" RevisionGUID="71ede331-11b5-4d51-8f28-662c3f438043" CreationDate="2018-07-15T01:51:28.903" UserId="6046" Text="Pathtracing line and point primitives?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20436" PostHistoryTypeId="3" PostId="7812" RevisionGUID="71ede331-11b5-4d51-8f28-662c3f438043" CreationDate="2018-07-15T01:51:28.903" UserId="6046" Text="|raytracing|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20437" PostHistoryTypeId="2" PostId="7813" RevisionGUID="2959e879-9731-4708-ac45-dfe29c936654" CreationDate="2018-07-15T05:31:39.157" UserId="3003" Text="What you've read is correct. In general, GPU vendors do not release lists of machine instructions for their GPUs. &#xD;&#xA;&#xD;&#xA;That said, you can do something similar to assembly programming on the GPU by using [OpenGL ARB Assembly Language](https://en.wikipedia.org/wiki/ARB_assembly_language). It allows you to program in assembly style, writing 1 opcode and its operands per line. While this is not quite the same as writing assembly language for the CPU, it's as close as your likely to get. I believe it's deprecated in modern OpenGL (though not positive). It still worked as of OpenGL 2.1." ContentLicense="CC BY-SA 4.0" />
  <row Id="20438" PostHistoryTypeId="2" PostId="7814" RevisionGUID="6a59f2e5-9239-4c2c-9a06-89373b1ffada" CreationDate="2018-07-15T08:27:37.640" UserId="2041" Text="You're tilting at windmills trying to learn &quot;GPU assembly&quot;, and it's due to the differences between how CPUs and GPUs are made and sold.&#xD;&#xA;&#xD;&#xA;Each CPU has what's called an *instruction set architecture*, for example x86 or ARMv8. The instruction set is the interface between the user of the CPU (i.e. the programmer) and the chip. The chip designer publishes the details of the instruction set so that compiler vendors can write compilers to target that instruction set. Any CPU that uses that instruction set can run the same binaries. (Extensions like SSE make that slightly untrue, but they only add new instructions: they don't change the structure of the binary.) When the vendor creates a new processor family, it could have completely different *micro-architecture* internally, but the same instruction set.&#xD;&#xA;&#xD;&#xA;GPUs are not like this at all. For best efficiency, the instruction set is usually closely tied to the micro-architecture of the CPU. That means each new family of GPUs has a new instruction set. GPUs can't run binaries made for different GPUs. For this reason, the instruction set usually isn't published: instead, your interface to the GPU is the driver published by the vendor for each graphics API (OpenGL, Vulkan, DirectX, &amp;c.). This is why the graphics APIs have functions to take the source code of a shader and run it: the compiled shader only runs on the same model or family of GPU it was compiled for.&#xD;&#xA;&#xD;&#xA;The closest you get to GPU assembly language is *SPIR-V*. This is an industry-standard intermediate representation, which GPU vendors are starting to support. It's like a GPU equivalent of LLVM's intermediate representation. It allows you to do the parsing and source optimization parts of compilation up-front to get a SPIR-V file, and then the GPU driver only needs to compile that to the GPU's instruction set at load time." ContentLicense="CC BY-SA 4.0" />
  <row Id="20439" PostHistoryTypeId="2" PostId="7815" RevisionGUID="e7dddf10-93f2-4b37-a049-ea973b85e5da" CreationDate="2018-07-15T08:43:07.363" UserId="2041" Text="&gt; I'm guessing this has to do with providing a specific line/point width? Else they are too thin for intersection.&#xD;&#xA;&#xD;&#xA;Exactly. True points and lines have no spatial extent: a point is infinitely small, a line is infinitely thin. You can't intersect those with a ray. But a point with a size is just a sphere, and a line with a size is a cylinder, and those are classic ray-casting primitives, so of course you can intersect them.&#xD;&#xA;&#xD;&#xA;The only difficulty is if your path-tracer currently only has one geometry primitive (the polygon or polygon mesh): adding new primitives might be hard for you, if you've structured it for just one. But even in that case, instead of intersecting the points and lines directly, you can just turn them both into polygon meshes inside the renderer, before casting any rays. If you know how to polygonise a sphere and a cylinder you already know what to do." ContentLicense="CC BY-SA 4.0" />
  <row Id="20441" PostHistoryTypeId="2" PostId="7816" RevisionGUID="b9fd72fc-c513-47bd-9087-66640cd398a9" CreationDate="2018-07-15T16:48:52.890" UserId="6406" Text="As it turns out, what was causing the visible diamond (simplex) shapes was an unfortunate typo. &#xD;&#xA;&#xD;&#xA;The line&#xD;&#xA;&#xD;&#xA;    t = FN_DECIMAL(0.5) - x5*x5 - y5*y5 - z5*z5 - w4*w4 - v5*v5;&#xD;&#xA;&#xD;&#xA;Should have been&#xD;&#xA;&#xD;&#xA;    t = FN_DECIMAL(0.5) - x5*x5 - y5*y5 - z5*z5 - w5*w5 - v5*v5;&#xD;&#xA;&#xD;&#xA;I ran some iterations without a normalising value to find the natural min/max values of the function and used those to calculate a normalising value, and tweaked the falloff function to find a nice point where the output is visually appealing. The final function is:&#xD;&#xA;&#xD;&#xA;    FN_DECIMAL FastNoise::SingleSimplex(unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w, FN_DECIMAL v) const&#xD;&#xA;    {&#xD;&#xA;      static const FN_DECIMAL norm = FN_DECIMAL(10.733025427569862289390260016388);&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL n0, n1, n2, n3, n4, n5;&#xD;&#xA;      FN_DECIMAL t = (x + y + z + w + v) * F5;&#xD;&#xA;      int i = FastFloor(x + t);&#xD;&#xA;      int j = FastFloor(y + t);&#xD;&#xA;      int k = FastFloor(z + t);&#xD;&#xA;      int l = FastFloor(w + t);&#xD;&#xA;      int h = FastFloor(v + t);&#xD;&#xA;      t = (i + j + k + l + h) * G5;&#xD;&#xA;      FN_DECIMAL X0 = i - t;&#xD;&#xA;      FN_DECIMAL Y0 = j - t;&#xD;&#xA;      FN_DECIMAL Z0 = k - t;&#xD;&#xA;      FN_DECIMAL W0 = l - t;&#xD;&#xA;      FN_DECIMAL V0 = h - t;&#xD;&#xA;      FN_DECIMAL x0 = x - X0;&#xD;&#xA;      FN_DECIMAL y0 = y - Y0;&#xD;&#xA;      FN_DECIMAL z0 = z - Z0;&#xD;&#xA;      FN_DECIMAL w0 = w - W0;&#xD;&#xA;      FN_DECIMAL v0 = v - V0;&#xD;&#xA;    &#xD;&#xA;      int rankx = 0;&#xD;&#xA;      int ranky = 0;&#xD;&#xA;      int rankz = 0;&#xD;&#xA;      int rankw = 0;&#xD;&#xA;      int rankv = 0;&#xD;&#xA;    &#xD;&#xA;      if (x0 &gt; y0) rankx++; else ranky++;&#xD;&#xA;      if (x0 &gt; z0) rankx++; else rankz++;&#xD;&#xA;      if (x0 &gt; w0) rankx++; else rankw++;&#xD;&#xA;      if (x0 &gt; v0) rankx++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      if (y0 &gt; z0) ranky++; else rankz++;&#xD;&#xA;      if (y0 &gt; w0) ranky++; else rankw++;&#xD;&#xA;      if (y0 &gt; v0) ranky++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      if (z0 &gt; w0) rankz++; else rankw++;&#xD;&#xA;      if (z0 &gt; v0) rankz++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      if (w0 &gt; v0) rankw++; else rankv++;&#xD;&#xA;    &#xD;&#xA;      int i1 = rankx &gt;= 4 ? 1 : 0;&#xD;&#xA;      int j1 = ranky &gt;= 4 ? 1 : 0;&#xD;&#xA;      int k1 = rankz &gt;= 4 ? 1 : 0;&#xD;&#xA;      int l1 = rankw &gt;= 4 ? 1 : 0;&#xD;&#xA;      int h1 = rankv &gt;= 4 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      int i2 = rankx &gt;= 3 ? 1 : 0;&#xD;&#xA;      int j2 = ranky &gt;= 3 ? 1 : 0;&#xD;&#xA;      int k2 = rankz &gt;= 3 ? 1 : 0;&#xD;&#xA;      int l2 = rankw &gt;= 3 ? 1 : 0;&#xD;&#xA;      int h2 = rankv &gt;= 3 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      int i3 = rankx &gt;= 2 ? 1 : 0;&#xD;&#xA;      int j3 = ranky &gt;= 2 ? 1 : 0;&#xD;&#xA;      int k3 = rankz &gt;= 2 ? 1 : 0;&#xD;&#xA;      int l3 = rankw &gt;= 2 ? 1 : 0;&#xD;&#xA;      int h3 = rankv &gt;= 2 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      int i4 = rankx &gt;= 1 ? 1 : 0;&#xD;&#xA;      int j4 = ranky &gt;= 1 ? 1 : 0;&#xD;&#xA;      int k4 = rankz &gt;= 1 ? 1 : 0;&#xD;&#xA;      int l4 = rankw &gt;= 1 ? 1 : 0;&#xD;&#xA;      int h4 = rankv &gt;= 1 ? 1 : 0;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x1 = x0 - i1 + G5;&#xD;&#xA;      FN_DECIMAL y1 = y0 - j1 + G5;&#xD;&#xA;      FN_DECIMAL z1 = z0 - k1 + G5;&#xD;&#xA;      FN_DECIMAL w1 = w0 - l1 + G5;&#xD;&#xA;      FN_DECIMAL v1 = v0 - h1 + G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x2 = x0 - i2 + 2 * G5;&#xD;&#xA;      FN_DECIMAL y2 = y0 - j2 + 2 * G5;&#xD;&#xA;      FN_DECIMAL z2 = z0 - k2 + 2 * G5;&#xD;&#xA;      FN_DECIMAL w2 = w0 - l2 + 2 * G5;&#xD;&#xA;      FN_DECIMAL v2 = v0 - h2 + 2 * G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x3 = x0 - i3 + 3 * G5;&#xD;&#xA;      FN_DECIMAL y3 = y0 - j3 + 3 * G5;&#xD;&#xA;      FN_DECIMAL z3 = z0 - k3 + 3 * G5;&#xD;&#xA;      FN_DECIMAL w3 = w0 - l3 + 3 * G5;&#xD;&#xA;      FN_DECIMAL v3 = v0 - h3 + 3 * G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x4 = x0 - i4 + 4 * G5;&#xD;&#xA;      FN_DECIMAL y4 = y0 - j4 + 4 * G5;&#xD;&#xA;      FN_DECIMAL z4 = z0 - k4 + 4 * G5;&#xD;&#xA;      FN_DECIMAL w4 = w0 - l4 + 4 * G5;&#xD;&#xA;      FN_DECIMAL v4 = v0 - h4 + 4 * G5;&#xD;&#xA;    &#xD;&#xA;      FN_DECIMAL x5 = x0 - 1 + 5 * G5;&#xD;&#xA;      FN_DECIMAL y5 = y0 - 1 + 5 * G5;&#xD;&#xA;      FN_DECIMAL z5 = z0 - 1 + 5 * G5;&#xD;&#xA;      FN_DECIMAL w5 = w0 - 1 + 5 * G5;&#xD;&#xA;      FN_DECIMAL v5 = v0 - 1 + 5 * G5;&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.7) - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0 - v0 * v0;&#xD;&#xA;      if (t &lt; 0) n0 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n0 = t * t * GradCoord5D(offset, i, j, k, l, h, x0, y0, z0, w0, v0);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.7) - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1 - v1 * v1;&#xD;&#xA;      if (t &lt; 0) n1 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n1 = t * t * GradCoord5D(offset, i + i1, j + j1, k + k1, l + l1, h + h1, x1, y1, z1, w1, v1);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.7) - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2 - v2 * v2;&#xD;&#xA;      if (t &lt; 0) n2 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n2 = t * t * GradCoord5D(offset, i + i2, j + j2, k + k2, l + l2, h + h2, x2, y2, z2, w2, v2);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.7) - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3 - v3 * v3;&#xD;&#xA;      if (t &lt; 0) n3 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n3 = t * t * GradCoord5D(offset, i + i3, j + j3, k + k3, l + l3, h + h3, x3, y3, z3, w3, v3);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.7) - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4 - v4 * v4;&#xD;&#xA;      if (t &lt; 0) n4 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n4 = t * t * GradCoord5D(offset, i + i4, j + j4, k + k4, l + l4, h + h4, x4, y4, z4, w4, v4);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      t = FN_DECIMAL(0.7) - x5 * x5 - y5 * y5 - z5 * z5 - w5 * w5 - v5 * v5;&#xD;&#xA;      if (t &lt; 0) n5 = 0;&#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;        t *= t;&#xD;&#xA;        n5 = t * t * GradCoord5D(offset, i + 1, j + 1, k + 1, l + 1, h + 1, x5, y5, z5, w5, v5);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      return (n0 + n1 + n2 + n3 + n4 + n5) * norm; // TODO: Find value scaler&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="20442" PostHistoryTypeId="50" PostId="7628" RevisionGUID="5cb1e41f-4691-437e-a920-a6853660d96b" CreationDate="2018-07-15T22:43:24.057" UserId="-1" />
  <row Id="20446" PostHistoryTypeId="2" PostId="7817" RevisionGUID="36c3e185-4340-4155-9389-c47b924b5541" CreationDate="2018-07-16T09:46:40.387" UserId="209" Text="As others have said, GPUs expose a higher-level language, which allows multiple different architectures i.e. different vendors and different GPU generations, to all support the same applications.&#xD;&#xA;&#xD;&#xA;If, however, you're still curious, documentation for the PowerVR *Series 6* instruction set is [available][1] - my favourite opcode being &quot;FRED&quot;.&#xD;&#xA;&#xD;&#xA;Note that instructions sets can change from generation to generation so this is mainly for illustrative purposes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.imgtec.com/developers/powervr/documentation/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20447" PostHistoryTypeId="5" PostId="7811" RevisionGUID="983707b0-9ca7-47dc-97a7-8a252f2ad8a5" CreationDate="2018-07-16T09:52:00.103" UserId="209" Comment="Minor spelling corrections" Text="I am currently rendering a scene in the most standard fashion possible (triangle projection and Blinn-Phong for shading)&#xD;&#xA;&#xD;&#xA;However I am getting some artifacts:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see the lion head is not rendered properly. Moreover, the artifacts are flickering, but the proportion of how much they flicker is proportional to the distance to the lion. That is to say. If you are close to the lion there are no artifacts. But the farther away you go the more artifacts appear. I believe this is due to Z buffer imprecision. How can I solve this?&#xD;&#xA;  [1]: https://i.stack.imgur.com/n87Fg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20448" PostHistoryTypeId="50" PostId="7643" RevisionGUID="e1c16aa5-38d6-49d7-8f06-f340c6e83256" CreationDate="2018-07-16T20:47:34.177" UserId="-1" />
  <row Id="20449" PostHistoryTypeId="2" PostId="7818" RevisionGUID="67cee823-c47a-44f8-89d5-8009623dbd63" CreationDate="2018-07-16T22:48:05.637" UserId="7462" Text="The way I learnt to send a texture to a shader is more or less&#xD;&#xA;&#xD;&#xA;    //Use program&#xD;&#xA;    //Bind texture to the texture unit to its appropriate target&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + texture_unit);&#xD;&#xA;	glBindTexture(target, textureID);&#xD;&#xA;    //Get the uniform location in the program and attach the texture unit&#xD;&#xA;    GLuint location = /*get the location somewhow*/;&#xD;&#xA;    glUniform1i(location,texture_unit);&#xD;&#xA;&#xD;&#xA;However when dealing with buffers and SSBOS rather than trying to find a location  through a string anme, the object is declared as:&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer texture_meta_data&#xD;&#xA;&#xD;&#xA;For example. This means that the SSBO is to eb bound at binding point 2&#xD;&#xA;&#xD;&#xA;And then on teh C++ side one does something like&#xD;&#xA;&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, SSBOID);&#xD;&#xA;&#xD;&#xA;To bind the object to tha bidning point.&#xD;&#xA;&#xD;&#xA;How can you do the same with textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20450" PostHistoryTypeId="1" PostId="7818" RevisionGUID="67cee823-c47a-44f8-89d5-8009623dbd63" CreationDate="2018-07-16T22:48:05.637" UserId="7462" Text="Can you avoid querying for a texture location in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20451" PostHistoryTypeId="3" PostId="7818" RevisionGUID="67cee823-c47a-44f8-89d5-8009623dbd63" CreationDate="2018-07-16T22:48:05.637" UserId="7462" Text="|opengl|texture|shader|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20452" PostHistoryTypeId="5" PostId="7802" RevisionGUID="58914ca8-aca1-4c77-91d2-40d42b24c40f" CreationDate="2018-07-17T00:57:14.143" UserId="8889" Comment="added 511 characters in body" Text="As mentioned on a comment, after talking about it on IRC, they helped me realize the bug was in the geometry shader that was being used for Stereo 3D.&#xD;&#xA;&#xD;&#xA;Due to the way it was conceived (which was apparently a really bad idea), the shader was always compiled and linked if the hardware reported supporting OpenGL3.30 and **GL_arb_viewport_array**.&#xD;&#xA;&#xD;&#xA;When the stereo3d option was disabled, via a very hacky solution, the shader was put into a &quot;pass-through&quot; mode which is supposed to do nothing but (still not sure if it's a bug in the shader itself or a hardware/driver issue) it was sending a lot of undefined values to the fragment shader, instead.&#xD;&#xA;&#xD;&#xA;Here's the offending code:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    #extension GL_ARB_viewport_array : require&#xD;&#xA;    &#xD;&#xA;    uniform float sepFactor;&#xD;&#xA;    uniform float z0;&#xD;&#xA;    &#xD;&#xA;    layout(triangles) in;&#xD;&#xA;    layout(triangle_strip, max_vertices = 6) out;&#xD;&#xA;    &#xD;&#xA;    struct vData {&#xD;&#xA;    	vec3 lightDir;&#xD;&#xA;    	vec2 texCoord;&#xD;&#xA;    	vec3 normal;&#xD;&#xA;    	vec4 color;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    in vData vertex[];&#xD;&#xA;    out vData fragv;&#xD;&#xA;    &#xD;&#xA;    void passthru(int i) {&#xD;&#xA;    	gl_Position = gl_in[i].gl_Position;&#xD;&#xA;    	fragv = vertex[i];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Process all the vertices, applying code to them before emitting (do-while to convince Nvidia of the code getting executed)&#xD;&#xA;    #define PROCESS(code) i = 0; do { passthru(i); code; EmitVertex(); } while (++i &lt; 3); EndPrimitive();&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	int i = 0;&#xD;&#xA;    	if (sepFactor == 0.0) {&#xD;&#xA;    		gl_ViewportIndex = 0; PROCESS(;); // No stereo&#xD;&#xA;    	} else {&#xD;&#xA;    		gl_ViewportIndex = 1; PROCESS(gl_Position.x -= sepFactor * (gl_Position.z - z0));  // Left eye&#xD;&#xA;    		gl_ViewportIndex = 2; PROCESS(gl_Position.x += sepFactor * (gl_Position.z - z0));  // Right eye&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have sort-of solved it by actually recompiling and relinking the shaders to include the geometry shader or not when stereo3d is toggled.&#xD;&#xA;&#xD;&#xA;I've also rewritten the shader to look like this (it still produces skewed geometry but atleast akin to the first screenshot, instead of the second),&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    #extension GL_ARB_viewport_array : require&#xD;&#xA;    &#xD;&#xA;    uniform highp float sepFactor;&#xD;&#xA;    uniform highp float z0;&#xD;&#xA;    &#xD;&#xA;    layout(triangles) in;&#xD;&#xA;    layout(triangle_strip, max_vertices = 6) out;&#xD;&#xA;    &#xD;&#xA;    in vData {&#xD;&#xA;    	highp vec3 lightDir;&#xD;&#xA;    	highp vec2 texCoord;&#xD;&#xA;    	highp vec3 normal;&#xD;&#xA;    	highp vec4 color;&#xD;&#xA;    } vertices[];&#xD;&#xA;    &#xD;&#xA;    out vData {&#xD;&#xA;    	highp vec3 lightDir;&#xD;&#xA;    	highp vec2 texCoord;&#xD;&#xA;    	highp vec3 normal;&#xD;&#xA;    	highp vec4 color;&#xD;&#xA;    } fragv;&#xD;&#xA;    &#xD;&#xA;    void passthru(int vp, int i) {&#xD;&#xA;    		gl_Position = gl_in[i].gl_Position;&#xD;&#xA;    		gl_ViewportIndex = (sepFactor == 0.0) ? 0 : vp;&#xD;&#xA;    		gl_Position.x -= (sepFactor * (gl_Position.z - z0));&#xD;&#xA;    		fragv.lightDir = vertices[i].lightDir;&#xD;&#xA;    		fragv.texCoord = vertices[i].texCoord;&#xD;&#xA;    		fragv.normal = vertices[i].normal;&#xD;&#xA;    		fragv.color = vertices[i].color;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    		// Render the left eye&#xD;&#xA;    	int i = 0;&#xD;&#xA;    	do {&#xD;&#xA;    		passthru(1, i);&#xD;&#xA;    		gl_Position.x -= (sepFactor * (gl_Position.z - z0));&#xD;&#xA;    		EmitVertex();		&#xD;&#xA;    		} while (++i &lt; 3);&#xD;&#xA;    		EndPrimitive();&#xD;&#xA;    	&#xD;&#xA;    	i = 0;&#xD;&#xA;    		// Render the right eye&#xD;&#xA;    	do {&#xD;&#xA;    		passthru(2, i);&#xD;&#xA;    		gl_Position.x += (sepFactor * (gl_Position.z - z0));&#xD;&#xA;    		EmitVertex();		&#xD;&#xA;    		} while (++i &lt; 3);&#xD;&#xA;    		EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In order to provide a more complete answer, in case somebody faces the same issue: I finally realized the issue appears to be with the way the loop was written. For some reason, not defining i in the loop itself resulted in trying to access undefined members of ```vertices```&#xD;&#xA;&#xD;&#xA;Rewriting as follows fixed the issue:&#xD;&#xA;&#xD;&#xA;	for (int i=0; i &lt; gl_in.length(); i++) {&#xD;&#xA;		passthru(1, i);&#xD;&#xA;		gl_Position = gl_in[i].gl_Position;&#xD;&#xA;		gl_Position.x -= (sepFactor * (gl_in[i].gl_Position.z - z0));&#xD;&#xA;		EmitVertex();	&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="20453" PostHistoryTypeId="2" PostId="7819" RevisionGUID="f3bd9a70-d76a-4130-96d5-346b5edca8ec" CreationDate="2018-07-17T01:28:02.133" UserId="9036" Text="I'm working on a program which uses Kochanek-Bartels (&quot;TCB&quot;) splines.&#xD;&#xA;&#xD;&#xA;My question is: How do I deal with the first/last points of the spline?&#xD;&#xA;&#xD;&#xA;This type of spline needs a 'previous' and 'next' point at each node to generate the curve tangents, but the first and last points on the curve don't have them. How do graphics programs deal with this problem?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20454" PostHistoryTypeId="1" PostId="7819" RevisionGUID="f3bd9a70-d76a-4130-96d5-346b5edca8ec" CreationDate="2018-07-17T01:28:02.133" UserId="9036" Text="How should I generate Kochanek-Bartels spline endpoints?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20455" PostHistoryTypeId="3" PostId="7819" RevisionGUID="f3bd9a70-d76a-4130-96d5-346b5edca8ec" CreationDate="2018-07-17T01:28:02.133" UserId="9036" Text="|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20456" PostHistoryTypeId="2" PostId="7820" RevisionGUID="97976cd0-dab8-403e-9b33-f382528cb2a5" CreationDate="2018-07-17T01:32:09.820" UserId="9036" Text="Move your near clip plane further away.&#xD;&#xA;&#xD;&#xA;Depth buffer precision is very sensitive to near clip plane distance.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20457" PostHistoryTypeId="5" PostId="7820" RevisionGUID="ed2db2b9-2d68-4efb-a161-8494530187f7" CreationDate="2018-07-17T01:37:22.940" UserId="9036" Comment="added 230 characters in body" Text="Short answer: Move your near clip plane further away.&#xD;&#xA;&#xD;&#xA;Depth buffer precision is very sensitive to the near clip plane distance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Complicated answer: Use different math in your view projection. There are a few techniques that can help, some of them are outlined here:&#xD;&#xA;&#xD;&#xA;https://developer.nvidia.com/content/depth-precision-visualized&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20468" PostHistoryTypeId="34" PostId="7722" RevisionGUID="6a369911-d50b-4b46-85fc-8e9e4609a2e3" CreationDate="2018-07-17T05:47:34.670" UserId="-1" Comment="47" />
  <row Id="20469" PostHistoryTypeId="6" PostId="1755" RevisionGUID="71049845-6856-4cad-92e7-cc09a0d1962d" CreationDate="2018-07-17T06:10:48.847" UserId="5778" Comment="tags edited" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20470" PostHistoryTypeId="24" PostId="1755" RevisionGUID="71049845-6856-4cad-92e7-cc09a0d1962d" CreationDate="2018-07-17T06:10:48.847" Comment="Proposed by 5778 approved by 209, 231 edit id of 426" ContentLicense="CC BY-SA 4.0" />
  <row Id="20471" PostHistoryTypeId="6" PostId="2402" RevisionGUID="9da84a83-c207-498b-81c3-36061a7f2da6" CreationDate="2018-07-17T06:11:36.593" UserId="5778" Comment="tags edited" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20472" PostHistoryTypeId="24" PostId="2402" RevisionGUID="9da84a83-c207-498b-81c3-36061a7f2da6" CreationDate="2018-07-17T06:11:36.593" Comment="Proposed by 5778 approved by 209, 231 edit id of 425" ContentLicense="CC BY-SA 4.0" />
  <row Id="20473" PostHistoryTypeId="5" PostId="7817" RevisionGUID="cb703768-8d88-4f01-bcd8-8141c579fc75" CreationDate="2018-07-17T07:38:15.690" UserId="209" Comment="Made link more obvious" Text="As others have said, GPUs expose a higher-level language, which allows multiple different architectures i.e. different vendors and different GPU generations, to all support the same applications.&#xD;&#xA;&#xD;&#xA;If, however, you're still curious, documentation for the [PowerVR *Series 6* instruction set is available][1] - my favourite opcode being &quot;FRED&quot;.&#xD;&#xA;&#xD;&#xA;Note that instructions sets can change from generation to generation so this is mainly for illustrative purposes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.imgtec.com/developers/powervr/documentation/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20474" PostHistoryTypeId="2" PostId="7821" RevisionGUID="a0f9489c-49bc-420c-b467-c24cfefd9bc9" CreationDate="2018-07-17T08:48:31.993" UserId="6346" Text="For JPG, i can choose the &quot;quality&quot; from 100 to 0, which means that any pixel information is divided by 1 (quality = 100) or a very high number (quality = 0).&#xD;&#xA;&lt;br&gt;This results in less or more &quot;artifacts&quot;, which are regions of the same color. The sizes of that regions depend on the image content and the selected &quot;quality level&quot;.&#xD;&#xA;&lt;br&gt;But there are other compression formats using other algorithms. The common characteristic is that the resulting image has less information than the original uncompressed data. &lt;br&gt;&#xD;&#xA;&#xD;&#xA;Is there any way to specify those losses independently from both the used file format and the image content?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20475" PostHistoryTypeId="1" PostId="7821" RevisionGUID="a0f9489c-49bc-420c-b467-c24cfefd9bc9" CreationDate="2018-07-17T08:48:31.993" UserId="6346" Text="Is there a general way how to specify the &quot;image compression loss&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20476" PostHistoryTypeId="3" PostId="7821" RevisionGUID="a0f9489c-49bc-420c-b467-c24cfefd9bc9" CreationDate="2018-07-17T08:48:31.993" UserId="6346" Text="|image|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20477" PostHistoryTypeId="2" PostId="7822" RevisionGUID="700a5d3a-533d-4c33-88dc-ecc1d77d516d" CreationDate="2018-07-17T10:43:59.080" UserId="2041" Text="First off, it's worth noting that not all artefacts are regions of the same colour. *Artefacts* just means structured errors introduced by the compression, as opposed to noise or blurring. JPEG artefacts include flattened colours as you mention, but also edges introduced at block boundaries, and &quot;ringing&quot; around sharp edges in the image.&#xD;&#xA;&#xD;&#xA;There are two popular metrics for specifying the losses, but they're **not** independent of the image content, and they measure the whole loss, not just structured artefacts. [PSNR](https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio) is most commonly used to quantify the loss of image and video compression algorithms. It's not a very useful measure, because it measures the absolute reconstruction error: it doesn't take into account what kind of artefacts are introduced and how they appear. [Structural similarity (SSIM)](https://en.wikipedia.org/wiki/Structural_similarity) is better because it takes the structure of the image and the errors into account in the measure.&#xD;&#xA;&#xD;&#xA;The measure can't be independent of the image, for several reasons. Different images are easier or harder to reconstruct. For example, a completely flat colour will be perfectly reconstructed even with some very lossy algorithms and parameters. At the opposite end, completely random white noise will suffer some loss in almost any algorithm. Some images just contain more information than others. In addition, different domains have different requirements, so algorithms can be tuned for different kinds of images. JPEG is tuned for photographs, and performs badly on hard-edged synthetic images like diagrams. A texture compression algorithm might be tuned specifically to avoid block artefacts for tileable textures. JBIG2 is tuned for black-and-white document scans. A single generic measure wouldn't help you to understand the performance of the algorithm on the kind of image you're interested in.&#xD;&#xA;&#xD;&#xA;To get a broader measure, it's common for researchers to quote a mean PSNR and/or SSIM measured across a corpus of images. The Kodak PCD0992 corpus has been used for many years, so it's an easy way to compare different papers, but it is waning in popularity now." ContentLicense="CC BY-SA 4.0" />
  <row Id="20478" PostHistoryTypeId="5" PostId="7818" RevisionGUID="030cc6ed-7492-4229-9b79-928557c98109" CreationDate="2018-07-17T15:14:33.103" UserId="2654" Comment="edited body" Text="The way I learned to send a texture to a shader is more or less&#xD;&#xA;&#xD;&#xA;    //Use program&#xD;&#xA;    //Bind texture to the texture unit to its appropriate target&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + texture_unit);&#xD;&#xA;	glBindTexture(target, textureID);&#xD;&#xA;    //Get the uniform location in the program and attach the texture unit&#xD;&#xA;    GLuint location = /*get the location somewhow*/;&#xD;&#xA;    glUniform1i(location,texture_unit);&#xD;&#xA;&#xD;&#xA;However when dealing with buffers and SSBOS rather than trying to find a location through a string name, the object is declared as:&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer texture_meta_data&#xD;&#xA;&#xD;&#xA;For example. This means that the SSBO is to be bound at binding point 2&#xD;&#xA;&#xD;&#xA;And then on the C++ side one does something like&#xD;&#xA;&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, SSBOID);&#xD;&#xA;&#xD;&#xA;To bind the object to the binding point.&#xD;&#xA;&#xD;&#xA;How can you do the same with textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20479" PostHistoryTypeId="2" PostId="7823" RevisionGUID="5e5b120e-abd1-49dd-bec2-01958dc889d1" CreationDate="2018-07-17T15:14:59.503" UserId="2654" Text="By using the [exact same syntax][1] as you did for SSBOs:&#xD;&#xA;&#xD;&#xA;    layout(binding = 0) uniform sampler2D texture_name;&#xD;&#xA;&#xD;&#xA;This is a GL 4.2 feature, so if you can use SSBOs, you can use this.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Version_4.20_binding" ContentLicense="CC BY-SA 4.0" />
  <row Id="20480" PostHistoryTypeId="2" PostId="7824" RevisionGUID="b0ca40df-8bef-4fa0-8ce6-95e337476760" CreationDate="2018-07-17T16:16:15.653" UserId="1615" Text="Are you aware of any sample implementation or demo application of Cem Yuksel's &quot;Mesh Colors&quot; or &quot;Mesh Color Textures&quot; (http://www.cemyuksel.com/research/meshcolors/) ?&#xD;&#xA;&#xD;&#xA;The author does not provide any links or pointers.&#xD;&#xA;&#xD;&#xA;I only saw very few references about these algorithms, but nothing executable to see the results." ContentLicense="CC BY-SA 4.0" />
  <row Id="20481" PostHistoryTypeId="1" PostId="7824" RevisionGUID="b0ca40df-8bef-4fa0-8ce6-95e337476760" CreationDate="2018-07-17T16:16:15.653" UserId="1615" Text="Cem Yuksel's &quot;Mesh colors&quot; implementation/demo?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20482" PostHistoryTypeId="3" PostId="7824" RevisionGUID="b0ca40df-8bef-4fa0-8ce6-95e337476760" CreationDate="2018-07-17T16:16:15.653" UserId="1615" Text="|texture|algorithm|implementation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20483" PostHistoryTypeId="50" PostId="6012" RevisionGUID="39917aea-b904-4544-a64c-efa4e3195675" CreationDate="2018-07-17T18:55:21.700" UserId="-1" />
  <row Id="20484" PostHistoryTypeId="8" PostId="7818" RevisionGUID="e1fa0b79-8e02-4e0e-992f-c52aed964092" CreationDate="2018-07-17T20:09:31.680" UserId="7462" Comment="Rollback to [67cee823-c47a-44f8-89d5-8009623dbd63]" Text="The way I learnt to send a texture to a shader is more or less&#xD;&#xA;&#xD;&#xA;    //Use program&#xD;&#xA;    //Bind texture to the texture unit to its appropriate target&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + texture_unit);&#xD;&#xA;	glBindTexture(target, textureID);&#xD;&#xA;    //Get the uniform location in the program and attach the texture unit&#xD;&#xA;    GLuint location = /*get the location somewhow*/;&#xD;&#xA;    glUniform1i(location,texture_unit);&#xD;&#xA;&#xD;&#xA;However when dealing with buffers and SSBOS rather than trying to find a location  through a string anme, the object is declared as:&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer texture_meta_data&#xD;&#xA;&#xD;&#xA;For example. This means that the SSBO is to eb bound at binding point 2&#xD;&#xA;&#xD;&#xA;And then on teh C++ side one does something like&#xD;&#xA;&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, SSBOID);&#xD;&#xA;&#xD;&#xA;To bind the object to tha bidning point.&#xD;&#xA;&#xD;&#xA;How can you do the same with textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20485" PostHistoryTypeId="5" PostId="7818" RevisionGUID="92403748-da10-4f83-9fe0-b5a61b79098a" CreationDate="2018-07-17T20:10:29.410" UserId="7462" Comment="deleted 1 character in body" Text="The way I learnt to send a texture to a shader is more or less&#xD;&#xA;&#xD;&#xA;    //Use program&#xD;&#xA;    //Bind texture to the texture unit to its appropriate target&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + texture_unit);&#xD;&#xA;	glBindTexture(target, textureID);&#xD;&#xA;    //Get the uniform location in the program and attach the texture unit&#xD;&#xA;    GLuint location = /*get the location somewhow*/;&#xD;&#xA;    glUniform1i(location,texture_unit);&#xD;&#xA;&#xD;&#xA;However when dealing with buffers and SSBOS rather than trying to find a location through a string name, the object is declared as:&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer texture_meta_data&#xD;&#xA;&#xD;&#xA;For example. This means that the SSBO is to be bound at binding point 2&#xD;&#xA;&#xD;&#xA;And then on the C++ side one does something like&#xD;&#xA;&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, SSBOID);&#xD;&#xA;&#xD;&#xA;To bind the object to the binding point.&#xD;&#xA;&#xD;&#xA;How can you do the same with textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20486" PostHistoryTypeId="50" PostId="5996" RevisionGUID="27c4b0b6-be28-4b5e-b44f-e31ac87fefe5" CreationDate="2018-07-17T20:55:25.850" UserId="-1" />
  <row Id="20487" PostHistoryTypeId="2" PostId="7825" RevisionGUID="c40ee84e-0933-487f-aa51-45293244b183" CreationDate="2018-07-17T23:55:16.183" UserId="7462" Text="I am doing a voxel based raytracer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In other words, I virst voxelize the scene using rasterization and I proceed to raytrace the volume in a 3D image to generate a final frame.&#xD;&#xA;&#xD;&#xA;Currently I noticed a circular apttern aliasing and I am not sure what could be causing it.&#xD;&#xA;&#xD;&#xA;This video shows the aliasing (sorry for the awkward camera movement my controls are not good right now). The magenta cube is the light's position.&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=rtFDTQoKX_A&amp;feature=youtu.be" ContentLicense="CC BY-SA 4.0" />
  <row Id="20488" PostHistoryTypeId="1" PostId="7825" RevisionGUID="c40ee84e-0933-487f-aa51-45293244b183" CreationDate="2018-07-17T23:55:16.183" UserId="7462" Text="Circular patter aliasing in voxel ray tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="20489" PostHistoryTypeId="3" PostId="7825" RevisionGUID="c40ee84e-0933-487f-aa51-45293244b183" CreationDate="2018-07-17T23:55:16.183" UserId="7462" Text="|opengl|raytracing|glsl|antialiasing|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20493" PostHistoryTypeId="5" PostId="7798" RevisionGUID="aed6d6fb-1428-4519-90ee-fc6d4de1fbfa" CreationDate="2018-07-18T03:46:18.277" UserId="5353" Comment="added clarification on the other part of the question." Text="![](https://i0.wp.com/upload.wikimedia.org/wikipedia/commons/thumb/e/ed/BRDF_Diagram.svg/800px-BRDF_Diagram.svg.png)&#xD;&#xA;&#xD;&#xA;This diagram is accurate. Let's look at the code:&#xD;&#xA;&#xD;&#xA;    float OrenNayar( in vec3 l, in vec3 n, in vec3 v, float r )&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;        float r2 = r*r;&#xD;&#xA;        float a = 1.0 - 0.5*(r2/(r2+0.57));&#xD;&#xA;        float b = 0.45*(r2/(r2+0.09));&#xD;&#xA;    &#xD;&#xA;        float nl = dot(n, l);&#xD;&#xA;        float nv = dot(n, v);&#xD;&#xA;    &#xD;&#xA;        float ga = dot(v-n*nv,n-n*nl);&#xD;&#xA;    &#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The first three parameters passed in (`l`, `n`, `v`) correspond to `W_i`, `n`, and `W_o` vectors, respectively. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, both `l` and `v` are used in a [`dot` product](https://en.wikipedia.org/wiki/Dot_product) with `n`: This is done for a purpose.&#xD;&#xA;&#xD;&#xA;The dot product gives you the cosine of the angle between the two parameters if both of the parameters are normalized vectors. Otherwise, it gives you the cosine of the angle between the vectors, scaled by the product of the length of those vectors &#xD;&#xA;&#xD;&#xA;    dot(l, n) = len(l) * len(n) * cos(theta) &#xD;&#xA;&#xD;&#xA;where `theta` is the angle between `l` and `n`. &#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/Zr9wa.png)&#xD;&#xA;&#xD;&#xA;&lt;sub&gt;[image source](https://www.mathsisfun.com/algebra/vectors-dot-product.html)&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;As we normalize our vectors, we can forget about the length and directly associate the dot product with the `cos(theta)` value.&#xD;&#xA;&#xD;&#xA;The value of the dot product ranges between [-1, +1] since cosine values, by definition, range between [-1, +1]. &#xD;&#xA;&#xD;&#xA; - If dot product is 1, it means that both the vectors are pointing in the same direction&#xD;&#xA; - If dot product is 0 (or very close to zero), it means that the vectors are exactly (or almost if its close to 0) perpendicular to each other.&#xD;&#xA; - If dot product is -1, it means that the two vectors point in the opposite direction&#xD;&#xA;&#xD;&#xA;**In other words, dot product kind of measures how similar the vectors are in terms of the direction they point to.**&#xD;&#xA;&#xD;&#xA;Since we compare how similar `v` and `l` is to the `n` vector, we kind of look into where `v` and `l` points to relative to the surface normal. Since the surface normal points away from the surface by definition, the vectors that have a dot product with `n` larger than 0 also point *away* from the surface.&#xD;&#xA;&#xD;&#xA;Now let's look at the last part of the code:&#xD;&#xA;&#xD;&#xA;    	return max(0.0,nl) * (a + b*max(0.0,ga) * sqrt((1.0-nv*nv)*(1.0-nl*nl)) / max(nl, nv));&#xD;&#xA;&#xD;&#xA;Notice this: **`max(0.0,nl)`** ?&#xD;&#xA;&#xD;&#xA;This expression would evaluate to 0 if the `NdotL` is less than 0. In other words, if the light direction is pointing *into* the surface we don't take into account the contribution of that light.&#xD;&#xA;&#xD;&#xA;So, the code provided doesn't ignore the rule: In order for the BRDF to return a positive light contribution value, the light vector should point away from the surface.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;As for the view ray part of the question, I think you've spotted a bug. The view vector `v` in the lighting calculation should point into the camera. The `rd` parameter passed in to `OrenNayar()` is a viewRay in world space, pointing away from the camera. &#xD;&#xA;&#xD;&#xA;The correct interpretation of the parameter in this case is `-v` when using the `dot()` product. &#xD;&#xA;&#xD;&#xA;![](https://i.stack.imgur.com/laDkM.png)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20494" PostHistoryTypeId="5" PostId="6309" RevisionGUID="e38a1183-4df4-4714-88b5-b12323e64672" CreationDate="2018-07-18T09:46:37.053" UserId="6" Comment="added 95 characters in body" Text="What you are missing is, that in OpenGL's NDC space (i.e. clip space after division by `w`) all 3 coordinates are in the range $[-1,1]$. So **`ndc_depth` is in the range $[-1,1]$**, while your computation assumes a range of $[0,1]$.&#xD;&#xA;&#xD;&#xA;So let's take your computation but add an initial step to map $[-1,1]$ to $[0,1]$:&#xD;&#xA;&#xD;&#xA;    float ndc_depth = Pclip.z / Pclip.w;&#xD;&#xA;    float win_depth = (ndc_depth + 1.0) / 2.0;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * win_depth + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;If we do some transformations (and realizing that `gl_DepthRange.diff` is just convenience for `gl_DepthRange.far - gl_DepthRange.near`), we get&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * (ndc_depth + 1.0) / 2.0 + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff) / 2.0 &#xD;&#xA;                   + glDepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff + &#xD;&#xA;                    2.0 * glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far - gl_DepthRange.near + 2.0 * glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far + glDepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;So, to answer your specfic questions:&#xD;&#xA;&#xD;&#xA;1. That's just a result from simplifying the calculation based on the fact that [`gl_DepthRange.diff` is nothing else than `gl_DepthRange.far - gl_DepthRange.near`](https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)#Shader_uniforms).&#xD;&#xA;&#xD;&#xA;2. Because the depth range in NDC space is $[-1,1]$, which has a width of $2$.&#xD;&#xA;&#xD;&#xA;3. It doesn't. These values have nothing to do with the near and far values you used to construct your projection matrix, in fact you could use any arbitrary projection matrix (or none at all). They are the depth range values set with [`glDepthRange`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml), which have a totally different meaning (okay, let's say slightly different but related).&#xD;&#xA;&#xD;&#xA; Basically, and special situations notwithstanding, the projection matrix defines where you near and far clipping planes are in eye-space, i.e. which eye-space range is mapped to the $[-1,1]$ NDC depth range. Then the depth range defines what these NDC near/far values of -1 and 1 are mapped to in the actual depth buffer. So the names &quot;near&quot;/&quot;far&quot; *do* relate to the near and far clipping planes. But both transformations are basically independent of each other, using the general NDC (i.e. the *normalized* device space) as a mediator between both stages. This way `glDepthRange` more or less just extends what `glViewport` does onto the z-dimension." ContentLicense="CC BY-SA 4.0" />
  <row Id="20495" PostHistoryTypeId="2" PostId="7826" RevisionGUID="03ebecbe-c5ab-4ca5-b540-76bea0e61bf8" CreationDate="2018-07-18T11:04:21.220" UserId="9042" Text="From the proof of premultiplied alpha blending, there is an assumption that &quot;the operator must respect the associative rule.&quot;&#xD;&#xA;So, it may lead to confusion of the order of process.&#xD;&#xA;&#xD;&#xA;Since this is not the commutative rule, blend(a,b) is not same as blend(b,a).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hence, &#xD;&#xA;blend(blend(a,b),c) returns same value of blend(a,blend(b,c)).&#xD;&#xA;but,&#xD;&#xA;blend(blend(a,b),c) does not return same value of blend(blend(b,a),c) like your example." ContentLicense="CC BY-SA 4.0" />
  <row Id="20496" PostHistoryTypeId="2" PostId="7827" RevisionGUID="f864e6c5-397a-49a8-827a-6f2c368dd4f3" CreationDate="2018-07-18T14:54:28.767" UserId="6844" Text="I'm trying to implement the solution to get the [minimum dissection into rectangles of a rectilinear polygon](https://stackoverflow.com/questions/5919298/algorithm-for-finding-the-fewest-rectangles-to-cover-a-set-of-rectangles-without).&#xD;&#xA;&#xD;&#xA;My shape is made out of pseudo-pixels (different width/height) but for the moment let's say it's only pixels.&#xD;&#xA;&#xD;&#xA;I need to find a way to convert my shape to a vertices loop.&#xD;&#xA;&#xD;&#xA;for example a simple pixel of coordinate `{50, 25}` would give me 4 vertices (to read clockwise) as follow `{{50, 25}{51, 25}{51, 26}{50, 26}}`.&#xD;&#xA;&#xD;&#xA;Imagine now a more complex filled shape with holes in it like this one of 6 pixels height and 24 pixels width. &#xD;&#xA;&#xD;&#xA;       S     &#xD;&#xA;       |¯¯¯¯|    |¯¯¯¯¯¯|&#xD;&#xA;     __|    |____|  __  |__&#xD;&#xA;    |              |__|    |&#xD;&#xA;     ¯¯|    |¯¯¯¯|      |¯¯&#xD;&#xA;       |____|    |______|&#xD;&#xA;&#xD;&#xA;I can't seem to find the logic to parse my shape and convert it to vertices. Only thing I know is I think I will start parsing with pixel of coordinate `S` which is the top-left pixel of the shape.&#xD;&#xA;&#xD;&#xA;Thanks in advance," ContentLicense="CC BY-SA 4.0" />
  <row Id="20497" PostHistoryTypeId="1" PostId="7827" RevisionGUID="f864e6c5-397a-49a8-827a-6f2c368dd4f3" CreationDate="2018-07-18T14:54:28.767" UserId="6844" Text="How can I convert a shape made out of pixels to vertices" ContentLicense="CC BY-SA 4.0" />
  <row Id="20498" PostHistoryTypeId="3" PostId="7827" RevisionGUID="f864e6c5-397a-49a8-827a-6f2c368dd4f3" CreationDate="2018-07-18T14:54:28.767" UserId="6844" Text="|vector-graphics|polygon|javascript|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20499" PostHistoryTypeId="50" PostId="7529" RevisionGUID="018dd5be-5fde-4b33-8a72-74350a93a3db" CreationDate="2018-07-18T19:59:23.627" UserId="-1" />
  <row Id="20506" PostHistoryTypeId="2" PostId="7828" RevisionGUID="269c6c4f-061f-4660-bfdd-d72374adfc64" CreationDate="2018-07-19T04:46:35.307" UserId="6046" Text="So I'm currently reading up on acceleration data structures and so far I've heard there are 2 main schemes. Object Subdivision and Spatial Subdivision.&#xD;&#xA;&#xD;&#xA;The Bounding Volume Hierarchy belongs to the Object Subdivision approach and K-d/Octree belong to the latter. However I'm having trouble distinguishing the two of them as both of them seem almost the same.&#xD;&#xA;&#xD;&#xA;I had implemented a data structure before for my GPU raytracer which I thought was an Octree but I am not sure anymore. This was according to the paper &quot;Ray tracing Complex Scenes&quot; by Kajiya. I'm gonna quote him directly.&#xD;&#xA;&#xD;&#xA;&gt; We could spend additional computer time to construct a better&#xD;&#xA;&gt; hierarchy. A median-cut scheme will help group near objects together&#xD;&#xA;&gt; even if they aren't modeled coherently.&#xD;&#xA;&gt; &#xD;&#xA;&gt; The previous algorithm attempts to group objects based on their&#xD;&#xA;&gt; nearness to each other, but it does so along one dimension at a time.&#xD;&#xA;&gt; It might do better to group objects in along three dimensions at once&#xD;&#xA;&gt; by employing an octree. This preprocessing step would be very similar&#xD;&#xA;&gt; to the one described in [Glassner 84] or [Kaplan 85]. The difference&#xD;&#xA;&gt; is that, if an object straddles two or more octree cells, it is&#xD;&#xA;&gt; arbitrarily placed in exactly one of them. Furthermore, after the&#xD;&#xA;&gt; preprocessing is completed, the octree is used solely to define the&#xD;&#xA;&gt; hierarchy; each object must still be assigned a distinct bounding&#xD;&#xA;&gt; volume.&#xD;&#xA;&#xD;&#xA;So I constructed this structure the same way. First I made an Octree, I inserted spheres into the cells if their center was in that cell. Every time I checked if the leaf nodes consisted of more than 2 spheres. If it did, I had to subdivide the cells again. After the octree was completed, I looped over all the compartments and resized them w.r.t the minimum `x,y,z` and the maximum `x,y,z` of the objects it had. This was done to avoid the case where some portion of a sphere would be outside the cell it's currently in (due to it's center lying in that cell).&#xD;&#xA;&#xD;&#xA;Now according to the paper the above structure is a BVH? But I'm thinking its an octree? What's the difference?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2) Secondly, so far I have only inserted spheres. What's the case with triangles? What should be the maximum threshold for leaf nodes after which I should subdivide i.e. The number of traingles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20507" PostHistoryTypeId="1" PostId="7828" RevisionGUID="269c6c4f-061f-4660-bfdd-d72374adfc64" CreationDate="2018-07-19T04:46:35.307" UserId="6046" Text="Difference between BVH and Octree/K-d trees" ContentLicense="CC BY-SA 4.0" />
  <row Id="20508" PostHistoryTypeId="3" PostId="7828" RevisionGUID="269c6c4f-061f-4660-bfdd-d72374adfc64" CreationDate="2018-07-19T04:46:35.307" UserId="6046" Text="|raytracing|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20509" PostHistoryTypeId="50" PostId="7633" RevisionGUID="cd3bbc4a-113f-464b-9f0e-717eed144da5" CreationDate="2018-07-19T05:04:29.740" UserId="-1" />
  <row Id="20510" PostHistoryTypeId="2" PostId="7829" RevisionGUID="b2452205-5b50-49fd-97e8-f582e5a2017c" CreationDate="2018-07-19T07:30:57.797" UserId="7462" Text="I have 2 shading models right now, one is using voxels the other one is the standard projection absed renderization method.&#xD;&#xA;&#xD;&#xA;Putting them side by side I have noticed that no matter what I do one is mirrored with respect to the other.&#xD;&#xA;&#xD;&#xA;To show what I mean I have a program that renders the scene with both models simultaneously. Supposedly the model loads the same camera parameters to both shading programs, so both should &quot;see&quot; the same thing.&#xD;&#xA;&#xD;&#xA;This is what I mean:&#xD;&#xA;&#xD;&#xA;In this screenshot pay attention to the color pairings. We have:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Left:&#xD;&#xA;green-red at back;&#xD;&#xA;red-blue at front&#xD;&#xA;&#xD;&#xA;Right:&#xD;&#xA;blue-red at back;&#xD;&#xA;red-green at front&#xD;&#xA;&#xD;&#xA;On this image, which corresponds to a 180 rotation however we get:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Left:&#xD;&#xA;blue-red at back;&#xD;&#xA;red-green at front&#xD;&#xA;&#xD;&#xA;Right:&#xD;&#xA;green-red at back;&#xD;&#xA;red-blue at front&#xD;&#xA;&#xD;&#xA;So the image seems to be mirrored. However I have tried inverting the polarity of multiple parameters without success. I tried negating the focal length of the camera. Negating the x value of the ray. Negating both...&#xD;&#xA;&#xD;&#xA;However no matter which combination of parameters I try I get some form of mirroring (no always the same one).&#xD;&#xA;&#xD;&#xA; I calculate the ray in teh raytracer as:&#xD;&#xA;&#xD;&#xA;    vec3 r = (vec3(f_coord.xy,1.f/tan(radians(40))));&#xD;&#xA;    r.y /= aspect_ratio;&#xD;&#xA;    vec3 dir = vec3(view_m*vec4(normalize(r),0));&#xD;&#xA;    dir = normalize(dir);&#xD;&#xA;    r = camera_pos;&#xD;&#xA;&#xD;&#xA;Where f_coord is the normalized -1 to 1 coordinate of the current pixel and &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/s5paD.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ArxN.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20511" PostHistoryTypeId="1" PostId="7829" RevisionGUID="b2452205-5b50-49fd-97e8-f582e5a2017c" CreationDate="2018-07-19T07:30:57.797" UserId="7462" Text="How to ensure that the raytrcing coordinate system is teh same as the projection one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20512" PostHistoryTypeId="3" PostId="7829" RevisionGUID="b2452205-5b50-49fd-97e8-f582e5a2017c" CreationDate="2018-07-19T07:30:57.797" UserId="7462" Text="|opengl|raytracing|image-processing|c++|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20513" PostHistoryTypeId="2" PostId="7830" RevisionGUID="46f6af0e-5a31-4ed7-bf11-4a5ba8266ebf" CreationDate="2018-07-19T14:28:39.320" UserId="9047" Text="So I'm teaching crash-course in CUDA that teaches students how to write good GPU code (CUDA 7.5 in this case). They kernels they will be running will do matrix multiply on 2048x2048 floating point matrices, some kernels involving multiple blocks and shared memory. &#xD;&#xA;&#xD;&#xA;The students will be ssh-ing into servers that have the GPUs where they will compile and run their programmes.&#xD;&#xA;&#xD;&#xA;I haven't a clue on how feasible this is and the only step I can imagine taking to prevent slowdown is to assign groups of students to different GPUs by telling them what value to pass cudaSetDevice()." ContentLicense="CC BY-SA 4.0" />
  <row Id="20514" PostHistoryTypeId="1" PostId="7830" RevisionGUID="46f6af0e-5a31-4ed7-bf11-4a5ba8266ebf" CreationDate="2018-07-19T14:28:39.320" UserId="9047" Text="How to avoid slowdown with 25-30 students running simple GPU kernels on 4 GeForce GTX 650 Ti s?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20515" PostHistoryTypeId="3" PostId="7830" RevisionGUID="46f6af0e-5a31-4ed7-bf11-4a5ba8266ebf" CreationDate="2018-07-19T14:28:39.320" UserId="9047" Text="|gpgpu|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20516" PostHistoryTypeId="5" PostId="7825" RevisionGUID="3c761391-f06f-4cbd-ad7b-92909acdb8da" CreationDate="2018-07-19T18:37:14.873" UserId="7462" Comment="added 4 characters in body" Text="I am doing a voxel based raytracer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In other words, I first voxelize the scene using rasterization and I proceed to raytrace the volume in a 3D image to generate a final frame.&#xD;&#xA;&#xD;&#xA;Currently I noticed a circular pattern aliasing and I am not sure what could be causing it.&#xD;&#xA;&#xD;&#xA;This video shows the aliasing (sorry for the awkward camera movement my controls are not good right now). The magenta cube is the light's position.&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=rtFDTQoKX_A&amp;feature=youtu.be&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20517" PostHistoryTypeId="4" PostId="7825" RevisionGUID="3c761391-f06f-4cbd-ad7b-92909acdb8da" CreationDate="2018-07-19T18:37:14.873" UserId="7462" Comment="added 4 characters in body" Text="Circular pattern aliasing in voxel ray tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="20518" PostHistoryTypeId="50" PostId="7716" RevisionGUID="5f4bc0f1-25b8-44e6-a266-672715361094" CreationDate="2018-07-20T01:04:52.780" UserId="-1" />
  <row Id="20519" PostHistoryTypeId="5" PostId="7825" RevisionGUID="c505c769-4b34-4d49-a2cb-8ffa94b3189d" CreationDate="2018-07-20T01:55:20.923" UserId="3003" Comment="Added a frame from the video" Text="I am doing a voxel based raytracer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In other words, I first voxelize the scene using rasterization and I proceed to raytrace the volume in a 3D image to generate a final frame.&#xD;&#xA;&#xD;&#xA;Currently I noticed a circular pattern aliasing and I am not sure what could be causing it.&#xD;&#xA;&#xD;&#xA;This video shows the aliasing (sorry for the awkward camera movement my controls are not good right now). The magenta cube is the light's position.&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=rtFDTQoKX_A&amp;feature=youtu.be&#xD;&#xA;&#xD;&#xA;Here's a still from the video:&#xD;&#xA;&#xD;&#xA;[![Moire Patterns][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YttRQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20520" PostHistoryTypeId="5" PostId="7825" RevisionGUID="776e16d8-3199-4b8e-b81f-367022b86494" CreationDate="2018-07-20T02:10:16.877" UserId="7462" Comment="added 1442 characters in body" Text="I am doing a voxel based raytracer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In other words, I first voxelize the scene using rasterization and I proceed to raytrace the volume in a 3D image to generate a final frame.&#xD;&#xA;&#xD;&#xA;Currently I noticed a circular pattern aliasing and I am not sure what could be causing it.&#xD;&#xA;&#xD;&#xA;This video shows the aliasing (sorry for the awkward camera movement my controls are not good right now). The magenta cube is the light's position.&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=rtFDTQoKX_A&amp;feature=youtu.be&#xD;&#xA;&#xD;&#xA;Here's a still from the video:&#xD;&#xA;&#xD;&#xA;[![Moire Patterns][1]][1]&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;This is the main function of the fragment shader. I can post more if it;s needed, btu won;t for now because the fragment is quite big and I think most of the function names are slef explanatory:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        float v_size = cube_dim/voxel_resolution;&#xD;&#xA;        vec3 r = -(vec3(f_coord.xy,1.f/tan(radians(40))));&#xD;&#xA;        r.y*=-1;&#xD;&#xA;        r.y /= aspect_ratio;&#xD;&#xA;        vec3 dir = vec3(view_m*vec4(normalize(r),0));&#xD;&#xA;        dir = normalize(dir);&#xD;&#xA;        r = camera_pos;&#xD;&#xA;        r.z*=-1;&#xD;&#xA;    &#xD;&#xA;        float t = boxIntersection(r, dir, -vec3(cube_dim), cube_dim*2);&#xD;&#xA;    &#xD;&#xA;        if(isinf(t))&#xD;&#xA;            discard;&#xD;&#xA;    &#xD;&#xA;        if(!((r.x&gt;=-cube_dim) &amp;&amp; (r.x&lt;=cube_dim) &amp;&amp; (r.y&gt;=-cube_dim) &amp;&amp;&#xD;&#xA;            (r.y&lt;=cube_dim) &amp;&amp; (r.z&gt;=-cube_dim) &amp;&amp; (r.z&lt;=cube_dim)))&#xD;&#xA;            r += dir*t;&#xD;&#xA;    &#xD;&#xA;        vec4 color = vec4(0);&#xD;&#xA;        while(incube(r, cube_dim))&#xD;&#xA;        {&#xD;&#xA;            r += dir*v_size*0.5;&#xD;&#xA;            vec4 val = imageLoad(normal_map, ivec3(((r)*0.5/cube_dim+vec3(0.5))*(voxel_resolution-1)));&#xD;&#xA;            if(val.w &gt; 0)&#xD;&#xA;            {&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        vec4 normal = imageLoad(normal_map, ivec3(((r)*0.5/cube_dim+vec3(0.5))*(voxel_resolution-1)));&#xD;&#xA;        color = imageLoad(diffuse_map, ivec3(((r)*0.5/cube_dim+vec3(0.5))*(voxel_resolution-1)));&#xD;&#xA;    &#xD;&#xA;        fragment_color = blinn_phong(r, vec3(normal), color)*(10.f/log(length(r-light)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YttRQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20525" PostHistoryTypeId="2" PostId="7832" RevisionGUID="b024acfe-ba6d-4912-95e2-84beb3a885af" CreationDate="2018-07-20T15:47:42.000" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="20526" PostHistoryTypeId="1" PostId="7832" RevisionGUID="b024acfe-ba6d-4912-95e2-84beb3a885af" CreationDate="2018-07-20T15:47:42.000" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="20527" PostHistoryTypeId="2" PostId="7833" RevisionGUID="03786e1d-0376-404e-8798-573b81f4f0f7" CreationDate="2018-07-20T15:47:42.000" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="20528" PostHistoryTypeId="1" PostId="7833" RevisionGUID="03786e1d-0376-404e-8798-573b81f4f0f7" CreationDate="2018-07-20T15:47:42.000" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="20529" PostHistoryTypeId="50" PostId="6422" RevisionGUID="125cad1b-ce81-4efd-a67d-41c60a32030f" CreationDate="2018-07-20T16:11:24.350" UserId="-1" />
  <row Id="20530" PostHistoryTypeId="2" PostId="7834" RevisionGUID="5c6b96c1-e7de-4126-a098-df9e6d36dbb6" CreationDate="2018-07-20T20:36:37.807" UserId="9050" Text="When a 3D scene is rendered to a 2D display, the image is distorted near the edges of the display.&#xD;&#xA;&#xD;&#xA;If a 3D scene is rendered onto a hemispherical display, will there still be warping?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20531" PostHistoryTypeId="1" PostId="7834" RevisionGUID="5c6b96c1-e7de-4126-a098-df9e6d36dbb6" CreationDate="2018-07-20T20:36:37.807" UserId="9050" Text="If a 3D scene is rendered onto a hemispherical display, will there still be warping near the edges?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20532" PostHistoryTypeId="3" PostId="7834" RevisionGUID="5c6b96c1-e7de-4126-a098-df9e6d36dbb6" CreationDate="2018-07-20T20:36:37.807" UserId="9050" Text="|3d|projections|hemisphere|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20539" PostHistoryTypeId="2" PostId="7835" RevisionGUID="3b0d1796-b543-408a-9e43-92aef5550c3a" CreationDate="2018-07-21T04:29:57.783" UserId="3073" Text="Assuming each pixel is the same size then each pixel would cover the same viewing angle whether it is in the centre or towards the edge. So no, there would be no distortion. " ContentLicense="CC BY-SA 4.0" />
  <row Id="20540" PostHistoryTypeId="2" PostId="7836" RevisionGUID="36df1083-0a79-45e9-a2d4-e5f760d38e20" CreationDate="2018-07-21T18:44:29.263" UserId="8680" Text="There will be no distortion as long as you project the scene properly onto your virtual camera.&#xD;&#xA;&#xD;&#xA;In traditional raster graphics the scene is projected onto a plane, this makes it so that two equal solid angles to the camera can take up vastly different amounts of space on the screen.&#xD;&#xA;&#xD;&#xA;Thus, the distortion does not come from the screen itself but from the projection used. Now, if you render your scene using a hemisphere projection, you should have no warping whatsoever. However, rendering using such projection might prove to be non trivial or straight up imposible using common methods (an exception to this is ray-tracing/marching/casting where all you need to change is how you generate your camera rays).&#xD;&#xA;&#xD;&#xA;An alternative is to render various views (one facing the front, one facing upwards, etc) rendered in the classic flat projection and then &quot;stitch&quot; those together by mapping them to the screen somehow.&#xD;&#xA;&#xD;&#xA;Here is a github repository of such a thing: https://github.com/shaunlebron/blinky&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**TL;DR** : The display has little to do with how distorted an image appears. It is the projection used by the software that creates warping. Therefore, Even when using a curved display, the image will still appear distorted, unless this is compensated for in software." ContentLicense="CC BY-SA 4.0" />
  <row Id="20541" PostHistoryTypeId="5" PostId="7836" RevisionGUID="8d549ba1-b16e-49ac-ba75-34547c4a5fe7" CreationDate="2018-07-21T18:52:47.007" UserId="8680" Comment="added 145 characters in body" Text="There will be no distortion as long as you project the scene properly onto your virtual camera.&#xD;&#xA;&#xD;&#xA;In traditional raster graphics the scene is projected onto a plane.&#xD;&#xA;&#xD;&#xA;[![Projection][1]][1]&#xD;&#xA;&#xD;&#xA;This makes it so that two equal solid angles to the camera can take up vastly different amounts of space on the screen.&#xD;&#xA;&#xD;&#xA;[![Distortion][2]][2]&#xD;&#xA;&#xD;&#xA;Thus, the distortion does not come from the screen itself but from the projection used. Now, if you render your scene using a hemisphere projection, you should have no warping whatsoever. However, rendering using such projection might prove to be non trivial or straight up imposible using common methods (an exception to this is ray-tracing/marching/casting where all you need to change is how you generate your camera rays).&#xD;&#xA;&#xD;&#xA;An alternative is to render various views (one facing the front, one facing upwards, etc) rendered in the classic flat projection and then &quot;stitch&quot; those together by mapping them to the screen somehow.&#xD;&#xA;&#xD;&#xA;Here is a github repository of such a thing: https://github.com/shaunlebron/blinky&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**TL;DR** : The display has little to do with how distorted an image appears. It is the projection used by the software that creates warping. Therefore, Even when using a curved display, the image will still appear distorted, unless this is compensated for in software.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UfSMS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QPxQH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20542" PostHistoryTypeId="50" PostId="7730" RevisionGUID="77542040-6563-4511-a32a-0fac245e3f00" CreationDate="2018-07-21T21:15:26.980" UserId="-1" />
  <row Id="20546" PostHistoryTypeId="2" PostId="7838" RevisionGUID="2bc27280-dc06-4e4a-9ac6-eef48c99fa08" CreationDate="2018-07-21T22:56:25.773" UserId="5215" Text="Is it possible to force Vulkan to execute a shader on vertices (data) in a semi-consecutive manner?&#xD;&#xA;&#xD;&#xA;For example, if the data passed to the shaders as a binary tree, shader would process it one layer at the time, starting from the root, while allowing multiple nodes to be processed concurrently only if they're on the same layer. I know that synchronicity is a big thing in Vulkan, but I'm unsure if it could be used at this layer of the pipeline. &#xD;&#xA;&#xD;&#xA;A use for it would be in a structure where the results of parents influence the results of their children, while the work on the each element is done with the same code.&#xD;&#xA;&#xD;&#xA;An example would be to calculate the effect of the wind on a tree - if nodes are the branching points of a tree, the location of each point would depend on the force applied to the source branch, but also on the force applied to each and every of it's ancestors, since each branch would bend, but also move with the rest of the tree - the rotations would add up. Doing it the way I described above would greatly speed up the computation for a single tree, possible increasing performance enough to scale the simulation maybe even several orders of magnitude. The benefits are even greater if you do it for all the trees in the scene at once.&#xD;&#xA;&#xD;&#xA;Is this possible with Vulkan? What topics should I look into specifically in order to accomplish this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20547" PostHistoryTypeId="1" PostId="7838" RevisionGUID="2bc27280-dc06-4e4a-9ac6-eef48c99fa08" CreationDate="2018-07-21T22:56:25.773" UserId="5215" Text="Controling order of execution of a (compute) shader on an array of vertices (data) in Vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="20548" PostHistoryTypeId="3" PostId="7838" RevisionGUID="2bc27280-dc06-4e4a-9ac6-eef48c99fa08" CreationDate="2018-07-21T22:56:25.773" UserId="5215" Text="|shader|compute-shader|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20550" PostHistoryTypeId="2" PostId="7839" RevisionGUID="fe88bbe4-b370-454f-aac3-274cf00fbac8" CreationDate="2018-07-22T10:31:14.960" UserId="2041" Text="You need nvidia-docker. If your ssh server is in a Docker instance, you can assign each one to a different GPU. Then just set things up so only one team is sshing into each Docker instance. You don't need to do anything fancy with `cudaSetDevice()`, or risk students using the wrong device and messing things up for others, because each instance looks like it only has one GPU." ContentLicense="CC BY-SA 4.0" />
  <row Id="20558" PostHistoryTypeId="5" PostId="7833" RevisionGUID="ed746b7a-b82c-471b-bb6d-14d67d7fcb50" CreationDate="2018-07-22T18:16:12.057" UserId="5778" Comment="added 90 characters in body" Text="For questions about words, phrases and definitions that are specific to computer graphics." ContentLicense="CC BY-SA 4.0" />
  <row Id="20559" PostHistoryTypeId="24" PostId="7833" RevisionGUID="ed746b7a-b82c-471b-bb6d-14d67d7fcb50" CreationDate="2018-07-22T18:16:12.057" Comment="Proposed by 5778 approved by 231 edit id of 428" ContentLicense="CC BY-SA 4.0" />
  <row Id="20560" PostHistoryTypeId="2" PostId="7842" RevisionGUID="a8401b5b-37ae-4c86-990e-08630eb5be69" CreationDate="2018-07-22T18:56:06.277" UserId="5664" Text="I have a rudimentary understanding of COM and I know that its main purpose is to enable interoperability between programs written in different languages. However I dont understand why that is useful to the DirectX api. Is it because DirectX has to make calls to the windows api which are written in C whereas DirectX is written in C++?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20561" PostHistoryTypeId="1" PostId="7842" RevisionGUID="a8401b5b-37ae-4c86-990e-08630eb5be69" CreationDate="2018-07-22T18:56:06.277" UserId="5664" Text="Why does DirectX use COM pointers and interfaces?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20562" PostHistoryTypeId="3" PostId="7842" RevisionGUID="a8401b5b-37ae-4c86-990e-08630eb5be69" CreationDate="2018-07-22T18:56:06.277" UserId="5664" Text="|c++|directx|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20575" PostHistoryTypeId="5" PostId="5373" RevisionGUID="7b20f5d7-cce5-4e00-86af-84c074c8cb92" CreationDate="2018-07-23T07:49:07.890" UserId="7008" Comment="changed from &quot;prose&quot; variable names to mathematical notation" Text="I am currently working with Earl Hammon Jr's Presentation [PBR Diffuse Lighting for GGX+Smith Microsurfaces][1] (now mentioned as [PBR, p.XYZ] and have read through (among others) Brent Burley's [Physically-Based Shading at Disney][2] (now mentioned as [DIS, p. XYZ] to get a good diffuse BRDF component. I am stuck at combining the two with the Fresnel Term.&#xD;&#xA;&#xD;&#xA;Short introduction for vectors and angles as I use them:&#xD;&#xA;&#xD;&#xA; - $\omega_i$ is the light vector&#xD;&#xA; - $\omega_o$ is the view vector&#xD;&#xA; - $\omega_n$ is the macro geometry normal&#xD;&#xA;&#xD;&#xA; - $\theta_i$ is the angle between $\omega_i$ and $\omega_n$&#xD;&#xA; - $\theta_o$ is the angle between $\omega_o$ and $\omega_n$&#xD;&#xA; - $\theta_h$ is the angle between $\omega_n$ and $\omega_h$&#xD;&#xA; - $\alpha_hi$ is the angle between $\omega_i$ and $\omega_h$ &#xD;&#xA; - $\alpha_ho$ is the angle between $\omega_o$ and $\omega_h$ (this distinction is for clarification)&#xD;&#xA; - $\alpha_h$ is any of the angles $\alpha_hi$, $\alpha_ho$, since they are equal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;now given that rest_spec is the BRDF term of the specular component without the fresnel factor and rest_diff accordingly the term of the diffuse component without the fresnel stuff, the fresnel factor is written as F(angle). &#xD;&#xA;[PBR, p.105] mentions that the diffuse light is transmitted two times, once in and once out. Thus, the Fresnel component has to be multiplied two times. &#xD;&#xA;[PBR, p. 106] goes on to say Fresnel's laws are symmetrix, meaning entering and leaving is direction independent (i.e. it does not matter that once we go into the material from air and once we leave into air). Now I would assume (for $F_1$ is Fresnel for entering and $F_2$ is for Fresnel leaving the material) to use &#xD;&#xA;&#xD;&#xA;$(1-F_1(\alpha_hi))*(1-F_2(\alpha_ho))$&#xD;&#xA;&#xD;&#xA;$F_1$ and $F_2$ are the same function, and $\alpha_hi$ and $\alpha_ho$ are the same angle, therefore&#xD;&#xA;&#xD;&#xA;$(1-F(\alpha_h))^2$&#xD;&#xA;&#xD;&#xA;This would lead to a brdf $f$:&#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * rest_spec + (1-F(\alpha_h))^2 * rest_diff$&#xD;&#xA;&#xD;&#xA;But both [PBR, p.113] and [DIS, p.14] use &#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * rest_spec + (1-F(\theta_i))*(1-F(\theta_o)) * rest_diff$&#xD;&#xA;&#xD;&#xA;as does the original paper to use this kind of calculation by Shirely et al. 1997.&#xD;&#xA;I just don't get this, why do they change from the microfacet angles to the macro angles? The microfacet angles lead to energy conversation&#xD;&#xA;&#xD;&#xA;$F \in [0, 1]$ &#xD;&#xA;$\Rightarrow(1-F) \in [0, 1] $&#xD;&#xA;$\Rightarrow(1-F)^2 \in [0, 1]$ and $(1-F(\alpha_h)) &gt;= (1-F(\alpha_h))^2)$&#xD;&#xA;&#xD;&#xA;it should be reciprocal&#xD;&#xA;&#xD;&#xA;$f(\theta_i, \theta_o) &#xD;&#xA;= F(\alpha_hi) * rest_spec + (1-F(\alpha_hi))*(1-F(\alpha_ho) * rest_diff &#xD;&#xA;= F(\alpha_h) * rest_spec + (1-F(\alpha_h))^2 * rest_diff &#xD;&#xA;= F(\alpha_ho) * rest_spec + (1-F(\alpha_ho))*(1-F(\alpha_hi)) * rest_diff &#xD;&#xA;= f(\theta_o, \theta_i)$&#xD;&#xA;&#xD;&#xA;and thus fulfill BRDF requirements. The microfacet angle is used for the specular term, therefore it is the more sensible thing to interpolate between specular and diffuse component (ignoring the fact of two transmissions for this argument).&#xD;&#xA;Instead, [PBR, p.113] and [DIS, p. 14] put the theta_h into a roughness calculation and leave that rather unexplained.&#xD;&#xA;&#xD;&#xA;Additionally to my confusion about this, in the explanation slides [PBR, p.187] uses the dot product $\omega_h * \omega_o$ (and therefore the alpha_ho angle) and later on [PBR, p. 191] also the dot product $\omega_h *  \omega_i$ ($\Rightarrow\alpha_hi$).&#xD;&#xA;&#xD;&#xA;  [1]: http://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="20576" PostHistoryTypeId="5" PostId="5373" RevisionGUID="a393bdcf-bf99-40d1-b3dd-a9fbc3685490" CreationDate="2018-07-23T07:55:14.833" UserId="7008" Comment="corrected some of the new latex layout errors" Text="I am currently working with Earl Hammon Jr's Presentation [PBR Diffuse Lighting for GGX+Smith Microsurfaces][1] (now mentioned as [PBR, p.XYZ] and have read through (among others) Brent Burley's [Physically-Based Shading at Disney][2] (now mentioned as [DIS, p. XYZ] to get a good diffuse BRDF component. I am stuck at combining the two with the Fresnel Term.&#xD;&#xA;&#xD;&#xA;Short introduction for vectors and angles as I use them:&#xD;&#xA;&#xD;&#xA; - $\omega_i$ is the light vector&#xD;&#xA; - $\omega_o$ is the view vector&#xD;&#xA; - $\omega_n$ is the macro geometry normal&#xD;&#xA;&#xD;&#xA; - $\theta_i$ is the angle between $\omega_i$ and $\omega_n$&#xD;&#xA; - $\theta_o$ is the angle between $\omega_o$ and $\omega_n$&#xD;&#xA; - $\theta_h$ is the angle between $\omega_n$ and $\omega_h$&#xD;&#xA; - $\alpha_hi$ is the angle between $\omega_i$ and $\omega_h$ &#xD;&#xA; - $\alpha_ho$ is the angle between $\omega_o$ and $\omega_h$ (this distinction is for clarification)&#xD;&#xA; - $\alpha_h$ is any of the angles $\alpha_{hi}$, $\alpha_{ho}$, since they are equal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;now given that rest_spec is the BRDF term of the specular component without the fresnel factor and rest_diff accordingly the term of the diffuse component without the fresnel stuff, the fresnel factor is written as F(angle). &#xD;&#xA;[PBR, p.105] mentions that the diffuse light is transmitted two times, once in and once out. Thus, the Fresnel component has to be multiplied two times. &#xD;&#xA;[PBR, p. 106] goes on to say Fresnel's laws are symmetrix, meaning entering and leaving is direction independent (i.e. it does not matter that once we go into the material from air and once we leave into air). Now I would assume (for $F_1$ is Fresnel for entering and $F_2$ is for Fresnel leaving the material) to use &#xD;&#xA;&#xD;&#xA;$(1-F_1(\alpha_{hi}))*(1-F_2(\alpha_{ho}))$&#xD;&#xA;&#xD;&#xA;$F_1$ and $F_2$ are the same function, and $\alpha_{hi}$ and $\alpha_{ho}$ are the same angle, therefore&#xD;&#xA;&#xD;&#xA;$(1-F(\alpha_h))^2$&#xD;&#xA;&#xD;&#xA;This would lead to a brdf $f$ (with $r_s$ is the rest of the specular term and $r_d$ is the rest of the diffuse term):&#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\alpha_h))^2 * r_d$&#xD;&#xA;&#xD;&#xA;But both [PBR, p.113] and [DIS, p.14] use &#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\theta_i))*(1-F(\theta_o)) * r_d$&#xD;&#xA;&#xD;&#xA;as does the original paper to use this kind of calculation by Shirely et al. 1997.&#xD;&#xA;I just don't get this, why do they change from the microfacet angles to the macro angles? The microfacet angles lead to energy conversation&#xD;&#xA;&#xD;&#xA;$F \in [0, 1]$ &#xD;&#xA;$\Rightarrow(1-F) \in [0, 1] $&#xD;&#xA;$\Rightarrow(1-F)^2 \in [0, 1]$ and $(1-F(\alpha_h)) &gt;= (1-F(\alpha_h))^2)$&#xD;&#xA;&#xD;&#xA;it should be reciprocal&#xD;&#xA;&#xD;&#xA;$f(\theta_i, \theta_o) &#xD;&#xA;= F(\alpha_{hi}) * r_s + (1-F(\alpha_{hi}))*(1-F(\alpha_{ho}) * r_d&#xD;&#xA;= F(\alpha_h) * r_s + (1-F(\alpha_h))^2 * r_d&#xD;&#xA;= F(\alpha_{ho}) * r_s + (1-F(\alpha_{ho}))*(1-F(\alpha_{hi})) * r_d&#xD;&#xA;= f(\theta_o, \theta_i)$&#xD;&#xA;&#xD;&#xA;and thus fulfill BRDF requirements. The microfacet angle is used for the specular term, therefore it is the more sensible thing to interpolate between specular and diffuse component (ignoring the fact of two transmissions for this argument).&#xD;&#xA;Instead, [PBR, p.113] and [DIS, p. 14] put the theta_h into a roughness calculation and leave that rather unexplained.&#xD;&#xA;&#xD;&#xA;Additionally to my confusion about this, in the explanation slides [PBR, p.187] uses the dot product $\omega_h * \omega_o$ (and therefore the alpha_ho angle) and later on [PBR, p. 191] also the dot product $\omega_h *  \omega_i$ ($\Rightarrow\alpha_{hi}$).&#xD;&#xA;&#xD;&#xA;  [1]: http://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="20577" PostHistoryTypeId="5" PostId="5395" RevisionGUID="556c2fe3-defd-4835-b2a3-2bfedace8309" CreationDate="2018-07-23T08:09:00.390" UserId="7008" Comment="changed from &quot;prose&quot; variable names to mathematical notation" Text="I finally figured out a flaw in my argumentation to use the half vector for the diffuse part.&#xD;&#xA;&#xD;&#xA;**tl;dr version:**&#xD;&#xA;==================&#xD;&#xA;&#xD;&#xA;$\alpha_{hi}$ and $\alpha_{ho}$ are not equal, this assumption only works for the specular part. Therefore the energyconservation is not given.&#xD;&#xA;&#xD;&#xA;*More correct: Per definition $\alpha_{hi} = \alpha_{ho}$, but you are not allowed to use them in the equation, you need to use the microfacet normals instead of the half vectors. The microfacet normal and the half vector are however not generally equal.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;long version:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffuse BRDF (like the specular one) is an integration over all possible microfacet normals. The generalized BRDF form is:&#xD;&#xA;&#xD;&#xA;**(1)**&#xD;&#xA;&#xD;&#xA;$f = \int_{\Omega} \frac{\rho_m * D * G * \cos(\alpha_{hi}) * \cos(\alpha_{ho})}{ \cos(\theta_i) * \cos(\theta_o)}$&#xD;&#xA;&#xD;&#xA;where $\rho_m$ is the behaviour of light when it reaches a microfacet, $D$ is the normal distribution function, $G$ is the geometry function and the rest is normalization [PBR, p.16-25][HEI, p.61f.]&#xD;&#xA;&#xD;&#xA;Now for the specular BRDF, the behaviour is perfect reflection. This means, only microfacets where the microfacet normal $\omega_m$ equals the half vector omega_h between light ($\omega_i$) and view ($\omega_o$) direction reflect light from the light direction to the view direction. Mathematically, this translates to a Dirac Delta function $\delta(\omega_h)$. The amount of light reflected is determined by Fresnel $F$. With accounting for integration domain changes[PBR, p.31-41], this leads to ($\rho_{m,s}$ being the specular specific reaction of microfacets for the specular part):&#xD;&#xA;&#xD;&#xA;**(2)**&#xD;&#xA;&#xD;&#xA;$\rho_{m,s} = \frac{\delta(\omega_h) * F }{4*\alpha_{hi}*\alpha_{ho}}$&#xD;&#xA;&#xD;&#xA;Plug this into **(1)** and you integrate over any omega_m, but the dirac delta function makes you ignore anything where $\omega_m \neq \omega_h$. This is the nice thing about those dirac delta functions, the &quot;cancel&quot; the integral. Therefore, you come to the known well known BRDF [PBR, p.43]&#xD;&#xA;&#xD;&#xA;**(3)**&#xD;&#xA;&#xD;&#xA;$f_s = \frac{F * D * G}{4 * \cos(\theta_i) * \cos(\theta_o)}$&#xD;&#xA;&#xD;&#xA;and here you can savely assume $\alpha_{hi} = \alpha_{ho}$. The Fresnel part makes this one side of a linear interpolation (seeing as this is the ratio of light being specularly reflected).&#xD;&#xA;&#xD;&#xA;On the other side though, you still have an integral and you can't &quot;cancel&quot; it with anything. Let $\theta_{mi}$ be the angle between the microfacet normal and the light dir, theta_mo between the microfacet normal and the view dir (as opposed to $\alpha_{hi}$ and $\alpha_{ho}$, which specifically are defined for the half angle!).That means 2 important things:&#xD;&#xA;&#xD;&#xA;**(4)**&#xD;&#xA;&#xD;&#xA;$\theta_{mi} \neq \alpha_{hi} = \alpha_h = \alpha_{ho} \neq \theta_{mo} \forall \omega_m \neq \omega_h$&#xD;&#xA;&#xD;&#xA;and $\rho_{m,d}$ (as the diffuse reaction of light when reaching microfacets) is depended upon Fresnel, it can only use non reflected parts, but you cannot just assume EVERY microfacet normal diffusley reflects all the light that was not specularly reflected (i.e. $(1-F(\alpha_h))$).&#xD;&#xA;&#xD;&#xA;So the problem now is, you have one side of that linear interpolation being the analytically solvable specular BRDF without an integral. On the other side, you have the interpolation factor within the integral, and thus you would use it for any microfacet normal. This is not energy conserving anymore, if you model $\rho_{m,d}$ with a lambertian term. &#xD;&#xA;&#xD;&#xA;If you manage to pull the $1-F$ part out of the integral, then and only then can you use the half vector for both specular and diffuse BRDFs, otherwise you need to handle it differently.&#xD;&#xA;&#xD;&#xA;If you still want to use the half vector for the &quot;Fresnelinterpolation&quot;, then you need to normalize.&#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\alpha_h)) * r_d * k$&#xD;&#xA;&#xD;&#xA;With $k$ being chosen, such that&#xD;&#xA;&#xD;&#xA;$r_d * k = 1$&#xD;&#xA;&#xD;&#xA;Note that $r_d$ (the rest of the diffuse term) still includes an integral over all possible microfacet normals.&#xD;&#xA;&#xD;&#xA;Using $\theta_i$ and $\theta_o$&#xD;&#xA;-------------------------&#xD;&#xA;I guess I should add a sentence about the actually used angles, because the question I originally posed was not just &quot;why not $\alpha_h$&quot; but also &quot;why $\theta_i$ and $\theta_o$&quot;. So for the poeple wondering if this is correct: No. It is just an approximation.&#xD;&#xA;&#xD;&#xA;&gt; Instead, we can modify the matte term to be a simple approximation that captures the important qualitative angular behavior[...].&#xD;&#xA;&gt; &#xD;&#xA;&gt; [SHI, p.46]&#xD;&#xA;&#xD;&#xA;Discussion on why this is so hard to figure out&#xD;&#xA;-----------------------------------------------&#xD;&#xA;&#xD;&#xA;Now [DIS, p.14] and [PBR, p.100,184] quoted [SHI] and [ASH] on this, where [ASH] uses [SHI], so it boils down to the model of the latter. And seeing as [DIS] and [PBR] are non-scientific (though pretty well thought through) publications, I can't fault them too much, but really, a better way of quoting papers or an extra explanation might have helped and saved me about 2 weeks of thinking, reading and almost starting a paper on why everybody is (supposedly) wrong. &#xD;&#xA;&#xD;&#xA;Furthermore, neither of them really explains their diffuse approximations, [PBR, p.193] just mentions trying different functions until he saw one he liked.&#xD;&#xA;&#xD;&#xA;Additionally, [SHI, p.46] actually quoted [SCH, p.10f.] who used the linear interpolation between $F(\alpha_h)$ and $1-F(\alpha_h)$. However, [SHI, p.46] quoted him incorrectly, they said he used $F(\theta_i)$ and $1-F(\alpha_h)$. Assuming this, they are of course right in thinking [SCH] is not energy conserving, but this lead me to believe that $F(\alpha_h)$ and $1-F(\alpha_h)$ would be. Their mistake might've come from them using $F(\theta_i)$ themselves, I can't say.&#xD;&#xA;&#xD;&#xA;Literature&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA; - [ASH] An anisotropic phong BRDF model, in Journal of Graphics Tools Vol. 5, No. 2, Michael Ashikhmin and Peter Shirley, 2000&#xD;&#xA; - [SCH] An Inexpsensive BRDF Model for Physically-based Rendering, in Computer Graphics Forum Vol. 13, No. 3, Christophe Schlick, 1994&#xD;&#xA; - [SHI] A Practitioners' Assessment of Light Reflection Models, in The Fifth Pacific Conference on Computer Graphics and Applications, 1997. Proceedings, Peter Shirley,  Helen Hu, Brian Smits and Eric Lafortune, 1997&#xD;&#xA; - [DIS] Physically-Based Shading at Disney, at SIGGRAPH 2012 Course: Physically Based Shading in Film and Game Production, Brent Burley, 2012&#xD;&#xA; - [HEI] Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, in Journal of Computer Graphics Techniques Vol. 3, No. 2, Eric Heitz, 2014&#xD;&#xA; - [PBR] PBR Diffuse Lighting for GGX+Smith Microsurfaces, at GDC2017, Earl Hammon Jr., 2017&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20578" PostHistoryTypeId="5" PostId="5373" RevisionGUID="87895b7d-5a37-437b-a0f8-124b076afcc4" CreationDate="2018-07-23T08:11:37.200" UserId="7008" Comment="corrected the leftover incorrect angles" Text="I am currently working with Earl Hammon Jr's Presentation [PBR Diffuse Lighting for GGX+Smith Microsurfaces][1] (now mentioned as [PBR, p.XYZ] and have read through (among others) Brent Burley's [Physically-Based Shading at Disney][2] (now mentioned as [DIS, p. XYZ] to get a good diffuse BRDF component. I am stuck at combining the two with the Fresnel Term.&#xD;&#xA;&#xD;&#xA;Short introduction for vectors and angles as I use them:&#xD;&#xA;&#xD;&#xA; - $\omega_i$ is the light vector&#xD;&#xA; - $\omega_o$ is the view vector&#xD;&#xA; - $\omega_n$ is the macro geometry normal&#xD;&#xA;&#xD;&#xA; - $\theta_i$ is the angle between $\omega_i$ and $\omega_n$&#xD;&#xA; - $\theta_o$ is the angle between $\omega_o$ and $\omega_n$&#xD;&#xA; - $\theta_h$ is the angle between $\omega_n$ and $\omega_h$&#xD;&#xA; - $\alpha_{hi}$ is the angle between $\omega_i$ and $\omega_h$ &#xD;&#xA; - $\alpha_{ho}$ is the angle between $\omega_o$ and $\omega_h$ (this distinction is for clarification)&#xD;&#xA; - $\alpha_h$ is any of the angles $\alpha_{hi}$, $\alpha_{ho}$, since they are equal&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;now given that $r_s$ is the BRDF term of the specular component without the fresnel factor and $r_d$ accordingly the term of the diffuse component without the fresnel stuff, the fresnel factor is written as $F(angle)$. &#xD;&#xA;[PBR, p.105] mentions that the diffuse light is transmitted two times, once in and once out. Thus, the Fresnel component has to be multiplied two times. &#xD;&#xA;[PBR, p. 106] goes on to say Fresnel's laws are symmetrix, meaning entering and leaving is direction independent (i.e. it does not matter that once we go into the material from air and once we leave into air). Now I would assume (for $F_1$ is Fresnel for entering and $F_2$ is for Fresnel leaving the material) to use &#xD;&#xA;&#xD;&#xA;$(1-F_1(\alpha_{hi}))*(1-F_2(\alpha_{ho}))$&#xD;&#xA;&#xD;&#xA;$F_1$ and $F_2$ are the same function, and $\alpha_{hi}$ and $\alpha_{ho}$ are the same angle, therefore&#xD;&#xA;&#xD;&#xA;$(1-F(\alpha_h))^2$&#xD;&#xA;&#xD;&#xA;This would lead to a brdf $f$:&#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\alpha_h))^2 * r_d$&#xD;&#xA;&#xD;&#xA;But both [PBR, p.113] and [DIS, p.14] use &#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\theta_i))*(1-F(\theta_o)) * r_d$&#xD;&#xA;&#xD;&#xA;as does the original paper to use this kind of calculation by Shirely et al. 1997.&#xD;&#xA;I just don't get this, why do they change from the microfacet angles to the macro angles? The microfacet angles lead to energy conversation&#xD;&#xA;&#xD;&#xA;$F \in [0, 1]$ &#xD;&#xA;$\Rightarrow(1-F) \in [0, 1] $&#xD;&#xA;$\Rightarrow(1-F)^2 \in [0, 1]$ and $(1-F(\alpha_h)) &gt;= (1-F(\alpha_h))^2)$&#xD;&#xA;&#xD;&#xA;it should be reciprocal&#xD;&#xA;&#xD;&#xA;$f(\theta_i, \theta_o) &#xD;&#xA;= F(\alpha_{hi}) * r_s + (1-F(\alpha_{hi}))*(1-F(\alpha_{ho}) * r_d&#xD;&#xA;= F(\alpha_h) * r_s + (1-F(\alpha_h))^2 * r_d&#xD;&#xA;= F(\alpha_{ho}) * r_s + (1-F(\alpha_{ho}))*(1-F(\alpha_{hi})) * r_d&#xD;&#xA;= f(\theta_o, \theta_i)$&#xD;&#xA;&#xD;&#xA;and thus fulfill BRDF requirements. The microfacet angle is used for the specular term, therefore it is the more sensible thing to interpolate between specular and diffuse component (ignoring the fact of two transmissions for this argument).&#xD;&#xA;Instead, [PBR, p.113] and [DIS, p. 14] put the $\theta_h$ into a roughness calculation and leave that rather unexplained.&#xD;&#xA;&#xD;&#xA;Additionally to my confusion about this, in the explanation slides [PBR, p.187] uses the dot product $\omega_h * \omega_o$ (and therefore the $\alpha_{ho}$ angle) and later on [PBR, p. 191] also the dot product $\omega_h *  \omega_i$ ($\Rightarrow\alpha_{hi}$).&#xD;&#xA;&#xD;&#xA;  [1]: http://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf&#xD;&#xA;  [2]: https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="20579" PostHistoryTypeId="5" PostId="5395" RevisionGUID="1bfc4665-2b7f-4c2b-8a03-9d65107266d2" CreationDate="2018-07-23T08:40:10.457" UserId="7008" Comment="added the last two angles in latex syntax, removed an obsolete sentence" Text="I finally figured out a flaw in my argumentation to use the half vector for the diffuse part.&#xD;&#xA;&#xD;&#xA;**tl;dr version:**&#xD;&#xA;==================&#xD;&#xA;&#xD;&#xA;$\alpha_{hi}$ and $\alpha_{ho}$ are not equal, this assumption only works for the specular part. Therefore the energyconservation is not given.&#xD;&#xA;&#xD;&#xA;*More correct: Per definition $\alpha_{hi} = \alpha_{ho}$, but you are not allowed to use them in the equation, you need to use the microfacet normals instead of the half vectors. The microfacet normal and the half vector are however not generally equal.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;long version:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffuse BRDF (like the specular one) is an integration over all possible microfacet normals. The generalized BRDF form is:&#xD;&#xA;&#xD;&#xA;**(1)**&#xD;&#xA;&#xD;&#xA;$f = \int_{\Omega} \frac{\rho_m * D * G * \cos(\alpha_{hi}) * \cos(\alpha_{ho})}{ \cos(\theta_i) * \cos(\theta_o)}$&#xD;&#xA;&#xD;&#xA;where $\rho_m$ is the behaviour of light when it reaches a microfacet, $D$ is the normal distribution function, $G$ is the geometry function and the rest is normalization [PBR, p.16-25][HEI, p.61f.]&#xD;&#xA;&#xD;&#xA;Now for the specular BRDF, the behaviour is perfect reflection. This means, only microfacets where the microfacet normal $\omega_m$ equals the half vector $\omega_h$ between light ($\omega_i$) and view ($\omega_o$) direction reflect light from the light direction to the view direction. Mathematically, this translates to a Dirac Delta function $\delta(\omega_h)$. The amount of light reflected is determined by Fresnel $F$. With accounting for integration domain changes[PBR, p.31-41], this leads to ($\rho_{m,s}$ being the specular specific reaction of microfacets for the specular part):&#xD;&#xA;&#xD;&#xA;**(2)**&#xD;&#xA;&#xD;&#xA;$\rho_{m,s} = \frac{\delta(\omega_h) * F }{4*\alpha_{hi}*\alpha_{ho}}$&#xD;&#xA;&#xD;&#xA;Plug this into **(1)** and you integrate over any $\omega_m$, but the dirac delta function makes you ignore anything where $\omega_m \neq \omega_h$. This is the nice thing about those dirac delta functions, the &quot;cancel&quot; the integral. Therefore, you come to the known well known BRDF [PBR, p.43]&#xD;&#xA;&#xD;&#xA;**(3)**&#xD;&#xA;&#xD;&#xA;$f_s = \frac{F * D * G}{4 * \cos(\theta_i) * \cos(\theta_o)}$&#xD;&#xA;&#xD;&#xA;and here you can savely assume $\alpha_{hi} = \alpha_{ho}$. The Fresnel part makes this one side of a linear interpolation (seeing as this is the ratio of light being specularly reflected).&#xD;&#xA;&#xD;&#xA;On the other side though, you still have an integral and you can't &quot;cancel&quot; it with anything. Let $\theta_{mi}$ be the angle between the microfacet normal and the light dir, theta_mo between the microfacet normal and the view dir (as opposed to $\alpha_{hi}$ and $\alpha_{ho}$, which specifically are defined for the half angle!).That means 2 important things:&#xD;&#xA;&#xD;&#xA;**(4)**&#xD;&#xA;&#xD;&#xA;$\theta_{mi} \neq \alpha_{hi} = \alpha_h = \alpha_{ho} \neq \theta_{mo} \forall \omega_m \neq \omega_h$&#xD;&#xA;&#xD;&#xA;and $\rho_{m,d}$ (as the diffuse reaction of light when reaching microfacets) is depended upon Fresnel, it can only use non reflected parts, but you cannot just assume EVERY microfacet normal diffusley reflects all the light that was not specularly reflected (i.e. $(1-F(\alpha_h))$).&#xD;&#xA;&#xD;&#xA;So the problem now is, you have one side of that linear interpolation being the analytically solvable specular BRDF without an integral. On the other side, you have the interpolation factor within the integral, and thus you would use it for any microfacet normal. This is not energy conserving anymore, if you model $\rho_{m,d}$ with a lambertian term. &#xD;&#xA;&#xD;&#xA;If you manage to pull the $1-F$ part out of the integral, then and only then can you use the half vector for both specular and diffuse BRDFs, otherwise you need to handle it differently.&#xD;&#xA;&#xD;&#xA;If you still want to use the half vector for the &quot;Fresnelinterpolation&quot;, then you need to normalize.&#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\alpha_h)) * r_d * k$&#xD;&#xA;&#xD;&#xA;With $k$ being chosen, such that&#xD;&#xA;&#xD;&#xA;$r_d * k = 1$&#xD;&#xA;&#xD;&#xA;Note that $r_d$ still includes an integral over all possible microfacet normals.&#xD;&#xA;&#xD;&#xA;Using $\theta_i$ and $\theta_o$&#xD;&#xA;-------------------------&#xD;&#xA;I guess I should add a sentence about the actually used angles, because the question I originally posed was not just &quot;why not $\alpha_h$&quot; but also &quot;why $\theta_i$ and $\theta_o$&quot;. So for the poeple wondering if this is correct: No. It is just an approximation.&#xD;&#xA;&#xD;&#xA;&gt; Instead, we can modify the matte term to be a simple approximation that captures the important qualitative angular behavior[...].&#xD;&#xA;&gt; &#xD;&#xA;&gt; [SHI, p.46]&#xD;&#xA;&#xD;&#xA;Discussion on why this is so hard to figure out&#xD;&#xA;-----------------------------------------------&#xD;&#xA;&#xD;&#xA;Now [DIS, p.14] and [PBR, p.100,184] quoted [SHI] and [ASH] on this, where [ASH] uses [SHI], so it boils down to the model of the latter. And seeing as [DIS] and [PBR] are non-scientific (though pretty well thought through) publications, I can't fault them too much, but really, a better way of quoting papers or an extra explanation might have helped and saved me about 2 weeks of thinking, reading and almost starting a paper on why everybody is (supposedly) wrong. &#xD;&#xA;&#xD;&#xA;Furthermore, neither of them really explains their diffuse approximations, [PBR, p.193] just mentions trying different functions until he saw one he liked.&#xD;&#xA;&#xD;&#xA;Additionally, [SHI, p.46] actually quoted [SCH, p.10f.] who used the linear interpolation between $F(\alpha_h)$ and $1-F(\alpha_h)$. However, [SHI, p.46] quoted him incorrectly, they said he used $F(\theta_i)$ and $1-F(\alpha_h)$. Assuming this, they are of course right in thinking [SCH] is not energy conserving, but this lead me to believe that $F(\alpha_h)$ and $1-F(\alpha_h)$ would be. Their mistake might've come from them using $F(\theta_i)$ themselves, I can't say.&#xD;&#xA;&#xD;&#xA;Literature&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA; - [ASH] An anisotropic phong BRDF model, in Journal of Graphics Tools Vol. 5, No. 2, Michael Ashikhmin and Peter Shirley, 2000&#xD;&#xA; - [SCH] An Inexpsensive BRDF Model for Physically-based Rendering, in Computer Graphics Forum Vol. 13, No. 3, Christophe Schlick, 1994&#xD;&#xA; - [SHI] A Practitioners' Assessment of Light Reflection Models, in The Fifth Pacific Conference on Computer Graphics and Applications, 1997. Proceedings, Peter Shirley,  Helen Hu, Brian Smits and Eric Lafortune, 1997&#xD;&#xA; - [DIS] Physically-Based Shading at Disney, at SIGGRAPH 2012 Course: Physically Based Shading in Film and Game Production, Brent Burley, 2012&#xD;&#xA; - [HEI] Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, in Journal of Computer Graphics Techniques Vol. 3, No. 2, Eric Heitz, 2014&#xD;&#xA; - [PBR] PBR Diffuse Lighting for GGX+Smith Microsurfaces, at GDC2017, Earl Hammon Jr., 2017&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20580" PostHistoryTypeId="2" PostId="7844" RevisionGUID="fc8e732d-a95c-4ab6-a158-44e5483af2d8" CreationDate="2018-07-23T10:42:29.853" UserId="2041" Text="C++ has no defined ABI, so C++ programs can't link to libraries that were compiled with a different compiler. In addition, MS's Visual Studio C++ compiler is not ABI-stable, so you don't just have to use the same compiler: you have to use the same version that the library was compiled with.&#xD;&#xA;&#xD;&#xA;This would be a huge problem for a widely-used library like DirectX.&#xD;&#xA;&#xD;&#xA;COM doesn't just enable interoperability between different languages, but also between different C++ compilers. In fact, I'd say this is its main use, and language compatibility is less used. By being a COM library, DirectX can avoid application developers needing to care what compiler it was compiled with. Application developers are free to use a Visual Studio version of their choice, or a completely different C++ compiler." ContentLicense="CC BY-SA 4.0" />
  <row Id="20581" PostHistoryTypeId="2" PostId="7845" RevisionGUID="aed2a470-924f-420e-a84a-1be92baecaf5" CreationDate="2018-07-23T14:49:24.107" UserId="7282" Text="I am writing a procedural terrain renderer for OpenGL. To shade the terrain I use multitexturing, that is 4 material textures and a blend map which distributes them across the terrain (encoded in RGBA).&#xD;&#xA;&#xD;&#xA;Should I decide to split my terrain patch into two, blend map, consequently gets split too. Now there is a seam problem. Because of texture filtering, on the edges, the color &quot;bleeds&quot; from the opposite side of the texture. I recognize this can be fixed by setting texture repeat parameter to GL_MIRRORED_REPEAT or GL_CLAMP_TO_EDGE.&#xD;&#xA;&#xD;&#xA;I believe that glTexParameteri function sets parameters for currently bound texture unit, still I'm unsure if these parameters get saved in texture unit's state, e.g. each texture unit &quot;remembers&quot; its parameters. Moreover, I know these parameters can be set per texture object. In that case whose parameters should take precedence?&#xD;&#xA;&#xD;&#xA;On a more concrete note, I sample blend map from GL_TEXTURE0. So I had an idea to set repeat parameters for GL_TEXTURE0 once before rendering all terrains, but it doesn't work.&#xD;&#xA;&#xD;&#xA;However, if I set this for every terrain rendered (absolutely the same code), it works. I'm inclined to believe that texture units don't &quot;remember&quot; their parameters. Is there something else I'm missing here?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20582" PostHistoryTypeId="1" PostId="7845" RevisionGUID="aed2a470-924f-420e-a84a-1be92baecaf5" CreationDate="2018-07-23T14:49:24.107" UserId="7282" Text="Texture units parameters in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="20583" PostHistoryTypeId="3" PostId="7845" RevisionGUID="aed2a470-924f-420e-a84a-1be92baecaf5" CreationDate="2018-07-23T14:49:24.107" UserId="7282" Text="|opengl|texture|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20584" PostHistoryTypeId="2" PostId="7846" RevisionGUID="13d5ceb7-caad-48fe-b1d3-dbd3378412be" CreationDate="2018-07-23T15:38:44.570" UserId="2654" Text="Your understanding of the behavior of texture units and state is confused. That's to be expected: OpenGL's pre-DSA API is not making it easy to understand this.&#xD;&#xA;&#xD;&#xA;As far as core profile OpenGL is concerned, the *only* texture unit state is what textures are bound to which targets. That's all. Therefore, all `glTexParameter` calls affect the state of the texture *object* bound to the currently active texture unit, not of the texture unit itself.&#xD;&#xA;&#xD;&#xA;So there is no &quot;precedence&quot;. Texture objects have state, which are modified by `glTexParameter` calls. This is made more clear in direct state access APIs, because `glTextureParameter` directly takes a texture object, rather than a bound texture target.&#xD;&#xA;&#xD;&#xA;If you call `glTexParameter` when texture object 0 is bound to the given texture target, then you're setting the parameter of the default texture object for that unit/target. And you shouldn't do that." ContentLicense="CC BY-SA 4.0" />
  <row Id="20589" PostHistoryTypeId="2" PostId="7849" RevisionGUID="b02f366b-89cf-4c98-b15e-2b3aa32843ce" CreationDate="2018-07-23T18:37:11.323" UserId="6046" Text="Well I researched quite a lot after that and this paper helped a lot.&#xD;&#xA;&#xD;&#xA;***&quot;Space Subdivision algorithms&quot; by Macdonald 1988.***&#xD;&#xA;&#xD;&#xA;So just summing what I understood. Some of them are obvious reasons but after reading the paper make much more sense and I'll try to do the same here.&#xD;&#xA;&#xD;&#xA;**1)** In BVH we are subdividing objects into smaller pieces. So for example a model of dragon consisting of thousands of triangles, We first start with a Bounding Volume covering the whole dragon. Then we subdivide again and again until our conditions are met. In BVHs, the leafnodes usually have 1 object in contrast to octrees which can have many. However this isn't clear whether it's referring to an object (sphere) or a single triangle since spheres can contain hundreds of triangles if triangulated. Here is a picture explaining BVH.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In contrast, Octrees/K-d trees and other space subdivision, divide the space recursively. A simple picture of an octree given in the paper.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2)** The above pictures show another difference. That is, in Space subdivisions we have disjoint sets of space regions or voxels or cells whatever you wanna call them. In contrast, BVHs have disjoint sets of objects. &#xD;&#xA;&#xD;&#xA;This means in octrees one object may be assigned to more than 1 voxel. And thus we may have to check for that object again and again though this can be avoided using techniques like mailboxing etc.  In BVHs, however, this isn't the case as an object may be inside only 1 bounding volume at a time, thus it may be checked for intersection only once which is when the ray intersects the bounding volume it's currently in.&#xD;&#xA;&#xD;&#xA;**3)** The other difference the paper mentions is that in Space subdivision traversal algorithms usually calculate the exit point of the ray from the current intersected child node and calculate a new point just past this exit point and from this information the next child node is found. The benefit of this is that traversal may stop as soon as it hits an object.&#xD;&#xA;&#xD;&#xA;On the other hand, BVHs can't do this since in BVHs we may have object overlapping in nodes. In this case we will have to maintain a list of the intersected objects and find which is the closest one. A good example of this is given in &quot;***Raytracing Complex Scenes by Kajiya***&quot; &#xD;&#xA;&#xD;&#xA;As we can see although the ray first intersects the upper BV, the closest object hit is actually inside the lower BV which the upper one has no information of unlike space subdivision structures.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And now on to the part of how I implemented the structure, it seems what Kajiya suggested was to use the octree scheme to define a traversing algorithm for the BVH. In the end when I recalculated the bounding volumes of each cells, this relaxed many voxels boundaries causing several to overlap. After this operation the structure didn't resemble *&quot;Disjoint sets of spaces&quot;* rather it resembled *&quot;disjoint sets of objects&quot;* hence it's essentially a BVH.&#xD;&#xA;&#xD;&#xA;Do note that this operation may sound like somewhat an efficient optimization to the space subdivision structure, that is relaxing the bounds of voxels to avoid having all the voxels keep track of the object that overlaps them. This way we assign 1 object to 1 voxel and relax it bounds. &#xD;&#xA;&#xD;&#xA;But doing so we lose the traversing efficiency of space subdivision structure where we could have stopped after intersecting only 1 object. Other pros may also have been lost. That's what I have understood so far.&#xD;&#xA;&#xD;&#xA;If anybody would like to add some more feel free to do so.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/H0QzQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/t15ok.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/0nPx4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20590" PostHistoryTypeId="2" PostId="7850" RevisionGUID="98de5dbf-7934-4aac-b8db-eba6b8b003f5" CreationDate="2018-07-23T19:20:34.123" UserId="2654" Text="Vulkan is not really suited to at least some of the task you're trying to accomplish. It has no mechanism to declare from within a shader that some additional work should be invoked. Or at least, not directly.&#xD;&#xA;&#xD;&#xA;The most effective way to execute this on the GPU would be to compute each level of *all* of the trees as a distinct dispatch operation. So you process all root nodes first, then the first level for each tree, then the second level, etc. Each compute shader invocation will need to do the processing for its node and store that computed data.&#xD;&#xA;&#xD;&#xA;This also requires that you store your tree data in a fairly scrambled way. All of your trees need to live (on the GPU side) in the same general array, preferably with all nodes for a particular level stored contiguously with one another. This makes processing easier, but it makes adding new nodes harder.&#xD;&#xA;&#xD;&#xA;The biggest performance problem will likely be the dependency issue. Each layer depends on the execution of the previous layer, which means you won't get much parallelism between layers. You're effectively inducing a stall between each set of layers. If you're executing thousands of nodes, you'll saturate your GPU's execution units just fine; it's the first few layers when you have few nodes that will have less performance than they could.&#xD;&#xA;&#xD;&#xA;Now, you may be able to avoid this performance problem by using a different shader for the first couple of layers. Such a shader would have each invocation process, say, the first 3 levels of the tree. On the one hand, this mitigates synchronization costs. But on the other hand, each shader invocation has to read and process a lot more data. And reading/writing a bunch of data from multiple invocations can be expensive, compared to having a more pipelined operation.&#xD;&#xA;&#xD;&#xA;So you should profile it and see what works best.&#xD;&#xA;&#xD;&#xA;Oh, and FYI: OpenGL compute shaders are just as capable of this as Vulkans." ContentLicense="CC BY-SA 4.0" />
  <row Id="20591" PostHistoryTypeId="2" PostId="7851" RevisionGUID="ea9555d8-4096-4cdf-be44-8d0eb5af7d75" CreationDate="2018-07-24T01:09:23.913" UserId="7462" Text="I am developping a voxel raytracer for global illumination. &#xD;&#xA;&#xD;&#xA;I have been successful in multiple aspects but there is a problem I am not sure how to solve.&#xD;&#xA;&#xD;&#xA;The model works as most other Voxelization based algorithms work. We use rasterization to store the scene in a 3D volumetric structure and then we raytrace inside of said 3D structure.&#xD;&#xA;&#xD;&#xA;In the &quot;pure&quot; model (only voxels) I can generate prety decent shadows (ignore the circular artifacts):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However when I try to create a combined scene (normal rendering for colors, voxels for shadows) I sometimes get self intersection based artifacts:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I can improve the image a bit by using an epsilon tolerance (considering that if we are too close to the original starting position we haven't collided with anything yet):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;However doing this creates poor shadows by eliminating certain collissions (look at the archs for example, where the areas too close to the source should be darkened but are instead lightened).&#xD;&#xA;&#xD;&#xA;I want to know if there is a better way to check for self intersection, other than checking the original position?&#xD;&#xA;&#xD;&#xA;i.e I want to be able to get as close to the shadows in the first image as possible.&#xD;&#xA;  [1]: https://i.stack.imgur.com/b76Fa.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sIamK.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/ngtYt.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20592" PostHistoryTypeId="1" PostId="7851" RevisionGUID="ea9555d8-4096-4cdf-be44-8d0eb5af7d75" CreationDate="2018-07-24T01:09:23.913" UserId="7462" Text="Self intersection artifacts in 3D image raytracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="20593" PostHistoryTypeId="3" PostId="7851" RevisionGUID="ea9555d8-4096-4cdf-be44-8d0eb5af7d75" CreationDate="2018-07-24T01:09:23.913" UserId="7462" Text="|opengl|raytracing|antialiasing|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20600" PostHistoryTypeId="2" PostId="7852" RevisionGUID="6be460db-92ee-42bf-9e27-bdbe0e6fa581" CreationDate="2018-07-24T03:18:53.347" UserId="8565" Text="I am currently trying to understand IBL in Unreal Engine, and there are so much things that I don't understand about the formula. Unreal approximate the specular term of shading equation by doing split sum approximation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is how unreal pre-filter the environment map for specular-irradiance term.&#xD;&#xA;&#xD;&#xA;    float3 PrefilterEnvMap(float Roughness, float3 R )&#xD;&#xA;    {&#xD;&#xA;        float3 N = R;&#xD;&#xA;        float3 V = R;&#xD;&#xA;        float3 PrefilteredColor = 0;&#xD;&#xA;        const uint NumSamples = 1024;&#xD;&#xA;        for(uint i = 0; i &lt; NumSamples; i++ )&#xD;&#xA;        {&#xD;&#xA;            float2 Xi = Hammersley( i, NumSamples );&#xD;&#xA;            float3 H = ImportanceSampleGGX( Xi, Roughness, N );&#xD;&#xA;            float3 L = 2 * dot  ( V, H ) * H - V;&#xD;&#xA;            float NoL =saturate( dot  ( N, L ) );&#xD;&#xA;            if ( NoL &gt; 0 )&#xD;&#xA;            {&#xD;&#xA;                PrefilteredColor += EnvMap.SampleLevel( EnvMapSampler, L, 0 ).rgb * NoL;&#xD;&#xA;                TotalWeight += NoL;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return PrefilteredColor / TotalWeight;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My question is why does the total weight is the sum of saturate(dot(N,L)). My understanding on importance sampling is that we should divide our sample with the pdf we use to sample. In this case, from what I read at [here][2] the pdf should be &#xD;&#xA;&#xD;&#xA;$$p_i(wm, wo) = \frac{D(wm)(wm \cdot wg)}{4|wo \cdot wm|}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/77jXZ.png&#xD;&#xA;  [2]: https://schuttejoe.github.io/post/ggximportancesamplingpart1/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20601" PostHistoryTypeId="1" PostId="7852" RevisionGUID="6be460db-92ee-42bf-9e27-bdbe0e6fa581" CreationDate="2018-07-24T03:18:53.347" UserId="8565" Text="Importance Sampling in Unreal Engine Formula Derivation (Irradiance term)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20602" PostHistoryTypeId="3" PostId="7852" RevisionGUID="6be460db-92ee-42bf-9e27-bdbe0e6fa581" CreationDate="2018-07-24T03:18:53.347" UserId="8565" Text="|shader|brdf|real-time|pbr|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20603" PostHistoryTypeId="5" PostId="7852" RevisionGUID="86b4c449-c61f-4a2c-bd42-bf171c85ab97" CreationDate="2018-07-24T03:42:49.327" UserId="8565" Comment="added 219 characters in body" Text="I am currently trying to understand IBL in Unreal Engine, and there are so much things that I don't understand about the formula. Unreal approximate the specular term of shading equation by doing split sum approximation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is how unreal pre-filter the environment map for specular-irradiance term.&#xD;&#xA;&#xD;&#xA;    float3 PrefilterEnvMap(float Roughness, float3 R )&#xD;&#xA;    {&#xD;&#xA;        float3 N = R;&#xD;&#xA;        float3 V = R;&#xD;&#xA;        float3 PrefilteredColor = 0;&#xD;&#xA;        const uint NumSamples = 1024;&#xD;&#xA;        for(uint i = 0; i &lt; NumSamples; i++ )&#xD;&#xA;        {&#xD;&#xA;            float2 Xi = Hammersley( i, NumSamples );&#xD;&#xA;            float3 H = ImportanceSampleGGX( Xi, Roughness, N );&#xD;&#xA;            float3 L = 2 * dot  ( V, H ) * H - V;&#xD;&#xA;            float NoL =saturate( dot  ( N, L ) );&#xD;&#xA;            if ( NoL &gt; 0 )&#xD;&#xA;            {&#xD;&#xA;                PrefilteredColor += EnvMap.SampleLevel( EnvMapSampler, L, 0 ).rgb * NoL;&#xD;&#xA;                TotalWeight += NoL;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return PrefilteredColor / TotalWeight;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My question is why does the total weight is the sum of saturate(dot(N,L)). My understanding on importance sampling is that we should divide our sample with the pdf we use to sample. In this case, from what I read at [here][2] the pdf should be &#xD;&#xA;&#xD;&#xA;$$p_i(wm, wo) = \frac{D(wm)(wm \cdot wg)}{4|wo \cdot wm|}$$&#xD;&#xA;&#xD;&#xA;My reference on pbr in unreal engine is [here][3] and [here][4].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/77jXZ.png&#xD;&#xA;  [2]: https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;  [3]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [4]: https://learnopengl.com/PBR/IBL/Specular-IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="20610" PostHistoryTypeId="2" PostId="7855" RevisionGUID="3237a943-7a45-4939-a843-a656555d252a" CreationDate="2018-07-24T08:08:41.727" UserId="2041" Text="&gt; I want to know if there is a better way to check for self intersection, other than checking the original position?&#xD;&#xA;&#xD;&#xA;Since cubes are convex solids, a self-intersection check shouldn't introduce artefacts in your case, while it would in a more general ray-tracer (see [my answer about the shadow terminator problem](https://computergraphics.stackexchange.com/a/4987/2041) for more about that). In general, it's a good idea for your ray object to have a reference of some kind to the object it came from, as well as the kind of ray it is (primary, shadow, reflection, refraction). Normally the reference should be to the exact polygon, not just the whole object; in your case, it should be the particular cube. You could identify it by the co-ordinates of the cube, if you're using spatial hashing to store your voxel grid.&#xD;&#xA;&#xD;&#xA;Then, in your intersection test, if your ray is a shadow ray, you should check whether the origin cube is the same as the cube being intersected, and discard that intersection if so." ContentLicense="CC BY-SA 4.0" />
  <row Id="20613" PostHistoryTypeId="2" PostId="7856" RevisionGUID="07f84985-835c-4bb4-8524-0c95fc3039c2" CreationDate="2018-07-24T09:09:34.783" UserId="8565" Text="I just read [notes on moving frostbite to pbr][1] and I found the derivation of the method above. So I will just show the derivation here and quote some of the explanation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&gt; One can notice an extra〈n·l〉in the LD term as well as a different&#xD;&#xA;&gt; weighting 1∑Ni&lt;n·l&gt;. These empirical terms have been introduce by&#xD;&#xA;&gt; Karis to allows to improve the reconstructed lighting integral which&#xD;&#xA;&gt; suffers from coarse hypothesis of separability of this integral. &#xD;&#xA;&gt; There is no mathematical derivation for these terms, goal was to have&#xD;&#xA;&gt; an exact match with a constant L(l).&#xD;&#xA;&#xD;&#xA;So it turns out the pdf is weighted on the DFG term. As for dot(N,l), the term is introduced to minimize the error that is caused by split sum approximation. But I am actually still wondering what is the intuition on that empirical term.&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/76tsj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20614" PostHistoryTypeId="5" PostId="7856" RevisionGUID="6a11a307-8dda-47f4-aad8-c86d6c41c86a" CreationDate="2018-07-24T09:15:43.627" UserId="8565" Comment="added 3 characters in body" Text="I just read [notes on moving frostbite to pbr][1] and I found the derivation of the method above. So I will just show the derivation here and quote some of the explanation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&gt; One can notice an extra〈n·l〉in the LD term as well as a different&#xD;&#xA;&gt; weighting 1/(∑Ni〈n·l〉). These empirical terms have been introduce by&#xD;&#xA;&gt; Karis to allows to improve the reconstructed lighting integral which&#xD;&#xA;&gt; suffers from coarse hypothesis of separability of this integral. &#xD;&#xA;&gt; There is no mathematical derivation for these terms, goal was to have&#xD;&#xA;&gt; an exact match with a constant L(l).&#xD;&#xA;&#xD;&#xA;So it turns out the pdf is weighted on the DFG term. As for dot(N,l), the term is introduced to minimize the error that is caused by split sum approximation. But I am actually still wondering what is the intuition on that empirical term.&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/76tsj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20615" PostHistoryTypeId="2" PostId="7857" RevisionGUID="c343a352-e559-4087-98ad-49a3bf1df276" CreationDate="2018-07-25T05:17:31.807" UserId="7868" Text="My path-tracer is generally fine and gives good output for regular test scenes, but I've noticed dense fireflies and dark speckles over fractal surfaces. The noise disappears if I render without light gathers (or zero every gather) and definitely isn't driven by hidden NaNs, so I suspect it's happening because fractals are naturally &quot;rough&quot; while my occlusion tests assume smooth surfaces (with constant shadow-ray offsets).&#xD;&#xA;&#xD;&#xA;Would it be possible to evaluate local distance variance at each intersection and scale my shadow-ray offsets appropriately? Would it have a significant effect if so, or would I be better off writing a denoiser?&#xD;&#xA;&#xD;&#xA;A few different test images with constant shadow offset; explicit light sampling is always performed with MIS (one BXDF sample, one spatial sample).&#xD;&#xA;&#xD;&#xA;[![Explicit light sampling, 4096spp, $2\epsilon$ ray offset][1]][1]&#xD;&#xA;*Explicit light sampling for a fractal surface, 4096spp, $2\epsilon$ ray offset*&#xD;&#xA;&#xD;&#xA;[![Classical path-tracing only, 4096spp, $2\epsilon$ ray offset][3]][3]&#xD;&#xA;*Classical path tracing for a fractal surface, 4096spp, no explicit shadow rays*&#xD;&#xA;&#xD;&#xA;[![Explicit light sampling for a sphere, 4096spp, $2\epsilon$ ray offset][4]][4]&#xD;&#xA;*Explicit light sampling for a sphere, 4096spp, $2\epsilon$ ray offset*&#xD;&#xA;&#xD;&#xA;[![Classical path tracing for a sphere, 4096spp, $2\epsilon$ ray offset][5]][5]&#xD;&#xA;*Classical path tracing for a sphere, 4096spp, no explicit shadow rays*&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1h8gR.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/A92E9.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ubFUd.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/Yc4bn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20616" PostHistoryTypeId="1" PostId="7857" RevisionGUID="c343a352-e559-4087-98ad-49a3bf1df276" CreationDate="2018-07-25T05:17:31.807" UserId="7868" Text="Handling shadow acne for dynamic surfaces" ContentLicense="CC BY-SA 4.0" />
  <row Id="20617" PostHistoryTypeId="3" PostId="7857" RevisionGUID="c343a352-e559-4087-98ad-49a3bf1df276" CreationDate="2018-07-25T05:17:31.807" UserId="7868" Text="|pathtracing|shadow|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20618" PostHistoryTypeId="6" PostId="1954" RevisionGUID="5a56776f-e021-432d-a42c-8ab3d07440ca" CreationDate="2018-07-25T06:09:57.107" UserId="5778" Comment="tags edited" Text="|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20619" PostHistoryTypeId="24" PostId="1954" RevisionGUID="5a56776f-e021-432d-a42c-8ab3d07440ca" CreationDate="2018-07-25T06:09:57.107" Comment="Proposed by 5778 approved by 386 edit id of 429" ContentLicense="CC BY-SA 4.0" />
  <row Id="20627" PostHistoryTypeId="2" PostId="7860" RevisionGUID="3e45c08c-c3ec-4ff9-97ac-bada14b11411" CreationDate="2018-07-26T11:44:02.760" UserId="9068" Text="I am testing the Intel RealSense D435 camera and have been able to create multiple Point Clouds (.ply) of a certain object. Each Point Cloud is taken in a different viewing angle of the object.&#xD;&#xA;&#xD;&#xA;Now I wish to merge all these point clouds into a single, 3D Object. I have tried CloudCompare but this requires manual cropping of outliers and noisy data, as well as translating each Point cloud.&#xD;&#xA;&#xD;&#xA;I wonder if there is a piece of code that can merge point clouds together and remove noisy data in order to have a rough 3D Object?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20628" PostHistoryTypeId="1" PostId="7860" RevisionGUID="3e45c08c-c3ec-4ff9-97ac-bada14b11411" CreationDate="2018-07-26T11:44:02.760" UserId="9068" Text="Merge multiple Point Clouds into a single 3D object" ContentLicense="CC BY-SA 4.0" />
  <row Id="20629" PostHistoryTypeId="3" PostId="7860" RevisionGUID="3e45c08c-c3ec-4ff9-97ac-bada14b11411" CreationDate="2018-07-26T11:44:02.760" UserId="9068" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20631" PostHistoryTypeId="2" PostId="7861" RevisionGUID="99875df8-00ce-471a-a70a-38177d42b45c" CreationDate="2018-07-26T15:39:48.543" UserId="6029" Text="OpenGL is not object-oriented, but more like &quot;switches you turn on&quot;?&#xD;&#xA;&#xD;&#xA;Like&#xD;&#xA;&#xD;&#xA;    glEnable(...);&#xD;&#xA;    list_id = glGenLists(1);&#xD;&#xA;    glNewList(list_id, GL_COMPILE);&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;It seems like one's turning on switches on some machine which is contained somewhere, but it isn't seen as an object in object-oriented sense?&#xD;&#xA;&#xD;&#xA;Is there a name for this kind of programming or library paradigm?&#xD;&#xA;&#xD;&#xA;I'm using it from C++, but perhaps the way it's used is &quot;C-style&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20632" PostHistoryTypeId="1" PostId="7861" RevisionGUID="99875df8-00ce-471a-a70a-38177d42b45c" CreationDate="2018-07-26T15:39:48.543" UserId="6029" Text="What is OpenGL's paradigm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20633" PostHistoryTypeId="3" PostId="7861" RevisionGUID="99875df8-00ce-471a-a70a-38177d42b45c" CreationDate="2018-07-26T15:39:48.543" UserId="6029" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20634" PostHistoryTypeId="2" PostId="7862" RevisionGUID="cdbd9079-95cc-4f20-9da7-810ff1f507c0" CreationDate="2018-07-26T15:59:36.137" UserId="3003" Text="It's generally referred to as a &quot;state machine&quot;. It has, as you noticed, a bunch of switches and parameters. All of them are globally accessible to any code that has access to the current context. Your program sets them and then issues draw calls. Anything you don't change, will remain in that state until you do change it. &#xD;&#xA;&#xD;&#xA;It is also a [Hardware Abstraction](https://en.wikipedia.org/wiki/Hardware_abstraction). The same OpenGL routines should have roughly the same effect regardless of the hardware it's running on. If you upload 3 vertices for a triangle and then draw them, that should produce similar results on an ATI, Nvidia, or Intel GPU, for example. You don't need machine-specific instructions for each one." ContentLicense="CC BY-SA 4.0" />
  <row Id="20635" PostHistoryTypeId="2" PostId="7863" RevisionGUID="30035810-cf84-4512-bb8f-c85e3d9effb0" CreationDate="2018-07-26T17:58:39.993" UserId="6029" Text="How to convert from glBegin() and glEnd() to VBOs (Vertex Buffer Objects)?&#xD;&#xA;&#xD;&#xA;I found a simple example here:&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {...}; // 36 of vertex coords&#xD;&#xA;    ...&#xD;&#xA;    // activate and specify pointer to vertex array&#xD;&#xA;    glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;    glVertexPointer(3, GL_FLOAT, 0, vertices);&#xD;&#xA;    &#xD;&#xA;    // draw a cube&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;    // deactivate vertex arrays after drawing&#xD;&#xA;    glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_vertexarray.html&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So if I have code in very &quot;standard&quot; glBegin() and glEnd() fashion like:&#xD;&#xA;&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    &#xD;&#xA;    	for(int j = 0; j &lt; vecf.size(); j++){&#xD;&#xA;    		glNormal3f(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);&#xD;&#xA;    		glVertex3f(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);&#xD;&#xA;    		glNormal3f(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);&#xD;&#xA;    		glVertex3f(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);&#xD;&#xA;    		glNormal3f(vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);&#xD;&#xA;    		glVertex3f(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;Then how do I convert this to VBOs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20636" PostHistoryTypeId="1" PostId="7863" RevisionGUID="30035810-cf84-4512-bb8f-c85e3d9effb0" CreationDate="2018-07-26T17:58:39.993" UserId="6029" Text="How to convert from glBegin() and glEnd() to VBOs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20637" PostHistoryTypeId="3" PostId="7863" RevisionGUID="30035810-cf84-4512-bb8f-c85e3d9effb0" CreationDate="2018-07-26T17:58:39.993" UserId="6029" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20638" PostHistoryTypeId="5" PostId="7863" RevisionGUID="9ed037dc-db33-4523-a355-49e7848c9631" CreationDate="2018-07-26T21:15:02.133" UserId="6029" Comment="added 189 characters in body" Text="How to convert from glBegin() and glEnd() to VBOs (Vertex Buffer Objects)?&#xD;&#xA;&#xD;&#xA;I found a simple example here:&#xD;&#xA;&#xD;&#xA;    GLfloat vertices[] = {...}; // 36 of vertex coords&#xD;&#xA;    ...&#xD;&#xA;    // activate and specify pointer to vertex array&#xD;&#xA;    glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;    glVertexPointer(3, GL_FLOAT, 0, vertices);&#xD;&#xA;    &#xD;&#xA;    // draw a cube&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, 36);&#xD;&#xA;    &#xD;&#xA;    // deactivate vertex arrays after drawing&#xD;&#xA;    glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_vertexarray.html&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So if I have code in very &quot;standard&quot; glBegin() and glEnd() fashion like:&#xD;&#xA;&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    &#xD;&#xA;    	for(int j = 0; j &lt; vecf.size(); j++){&#xD;&#xA;    		glNormal3f(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);&#xD;&#xA;    		glVertex3f(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);&#xD;&#xA;    		glNormal3f(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);&#xD;&#xA;    		glVertex3f(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);&#xD;&#xA;    		glNormal3f(vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);&#xD;&#xA;    		glVertex3f(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;Then how do I convert this to VBOs?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Particularly, I already know that I need to supply vertices array and normals array, but I seem to confuse the orders of some vecs, because what's drawn becomes out as distorted." ContentLicense="CC BY-SA 4.0" />
  <row Id="20645" PostHistoryTypeId="2" PostId="7866" RevisionGUID="a5b11335-72b1-442e-bd90-71a28feec142" CreationDate="2018-07-26T23:14:39.343" UserId="9086" Text="The proper term for this style is called &quot;imperative programming.&quot; You would be correct in thinking that it is similar to C because C is classified as an imperative programming language.&#xD;&#xA;&#xD;&#xA;For more about the paradigm, you can read about it here: https://en.wikipedia.org/wiki/Imperative_programming" ContentLicense="CC BY-SA 4.0" />
  <row Id="20646" PostHistoryTypeId="2" PostId="7867" RevisionGUID="88728c75-8ff9-455b-9634-18e5a820a015" CreationDate="2018-07-27T05:53:22.263" UserId="7462" Text="Let's assume we have voxelized a scene, and all of our materials have an opacity level of 1. The reuslt would then look like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If we raytraced the final volume that gets generated after rasterization.&#xD;&#xA;&#xD;&#xA;Now, we wish to generate soft shadows, which is done by increasing the LOD sample level as we move further away from the source, sampling at discrete intervals and adding opacity values until we reach an opacity of 1.&#xD;&#xA;&#xD;&#xA;If my understanding is correct that is.&#xD;&#xA;&#xD;&#xA;Could soemone that is familiar with this technique give a better explanation and correct any mistakes I have made? Pictures and diagrams are appreciated too.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NxkZw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20647" PostHistoryTypeId="1" PostId="7867" RevisionGUID="88728c75-8ff9-455b-9634-18e5a820a015" CreationDate="2018-07-27T05:53:22.263" UserId="7462" Text="How exactly do soft shadows get generated using a voxel cone tracing rendering technique?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20648" PostHistoryTypeId="3" PostId="7867" RevisionGUID="88728c75-8ff9-455b-9634-18e5a820a015" CreationDate="2018-07-27T05:53:22.263" UserId="7462" Text="|opengl|raytracing|rendering|global-illumination|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20649" PostHistoryTypeId="2" PostId="7868" RevisionGUID="ecd4d46b-969f-4462-98e2-1acab93144f8" CreationDate="2018-07-27T07:34:32.563" UserId="7462" Text="I am trying to generate soft shadows using voxel cone tracing.&#xD;&#xA;&#xD;&#xA;Which gives me the next images:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In the first image you can see an artifact of a sequence of horizontal shadows alternating with illuminated areas, which looks quite odd.&#xD;&#xA;&#xD;&#xA;On the second image you can see that the left side is shadowed and the right isn't, although both sides are equidistant to the light, so they should be equally illuminated. In addition to that, in the second image you can see that in the columns, the shadows are jaggy and the outline is clear (no soft shadows).&#xD;&#xA;&#xD;&#xA;I am trying to solve these 3 problems.&#xD;&#xA;&#xD;&#xA;The way I am currently generating my shadows from my 3D texture is:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        fragment_color = blinn_phong();&#xD;&#xA;    &#xD;&#xA;    	float v_size = cube_dim/voxel_resolution;&#xD;&#xA;    	vec3 r = f_pos + f_norm*v_size*2;&#xD;&#xA;    	vec3 dir = normalize(light-r);&#xD;&#xA;        vec3 start = r;&#xD;&#xA;    	float l=0;&#xD;&#xA;    	float acc=0;&#xD;&#xA;    	vec4 val;&#xD;&#xA;        while(incube(r, cube_dim) &amp;&amp; (l&lt;=length(start-light)) &amp;&amp; acc&lt;1)&#xD;&#xA;        {&#xD;&#xA;    		l=length(start-r);&#xD;&#xA;            r += dir*v_size*0.5;&#xD;&#xA;    		val = textureLod(normal_map, (r-vec3(0.5))*0.5/cube_dim+vec3(0.5), l*0.0001);&#xD;&#xA;    		acc += val.w;&#xD;&#xA;        }&#xD;&#xA;    	fragment_color *= (1-acc);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qoXFk.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/pAykT.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20650" PostHistoryTypeId="1" PostId="7868" RevisionGUID="ecd4d46b-969f-4462-98e2-1acab93144f8" CreationDate="2018-07-27T07:34:32.563" UserId="7462" Text="Voxel cone tracing artifacts (what causes them and how to solve them)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20651" PostHistoryTypeId="3" PostId="7868" RevisionGUID="ecd4d46b-969f-4462-98e2-1acab93144f8" CreationDate="2018-07-27T07:34:32.563" UserId="7462" Text="|opengl|rendering|shadow|global-illumination|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20652" PostHistoryTypeId="2" PostId="7869" RevisionGUID="9de21031-9ac7-4c7f-8394-482400efef19" CreationDate="2018-07-27T10:18:18.683" UserId="6046" Text="Consider a ray tracer written in OpenGL and using GLFW as a window toolkit. There are basically 2 options to display the ray-traced image.&#xD;&#xA;&#xD;&#xA;**1) Create a `RenderBuffer` with image and blit this to the default framebuffer.**&#xD;&#xA;&#xD;&#xA;**2) Render the scene to a texture and use a full screen quad to display that texture.**&#xD;&#xA;&#xD;&#xA;What if I want to render the scene in a resolution that is different from the window size? How do I handle rescaling of images.&#xD;&#xA;&#xD;&#xA;**Case 1)** Render to high resolution image/texture and display to low resolution window.&#xD;&#xA;&#xD;&#xA;I don't know how should I handle for downscaling the texture/image in both cases. I am particularly interested in the `Renderbuffer` approach though. &#xD;&#xA;&#xD;&#xA;**Case 2)** Render to low resolution image/texture and display to high resolution window.&#xD;&#xA;&#xD;&#xA;I am pretty sure case 2 could be easy to implement through textures by setting the filter to `LINEAR` or `NEAREST` perhaps, the sampling function would automatically upscale it?&#xD;&#xA;&#xD;&#xA;I am not sure what would happen to the renderBuffer approach in either case. I have read though that `Blit` between buffers of different sizes are supported.&#xD;&#xA;&#xD;&#xA;Also in both cases, how would I handle the aspect ratio?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20653" PostHistoryTypeId="1" PostId="7869" RevisionGUID="9de21031-9ac7-4c7f-8394-482400efef19" CreationDate="2018-07-27T10:18:18.683" UserId="6046" Text="OpenGL - Any way to rescale images/textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="20654" PostHistoryTypeId="3" PostId="7869" RevisionGUID="9de21031-9ac7-4c7f-8394-482400efef19" CreationDate="2018-07-27T10:18:18.683" UserId="6046" Text="|opengl|texture|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20655" PostHistoryTypeId="50" PostId="7707" RevisionGUID="a9b694f7-4ff3-4763-b2dc-0f68830fb909" CreationDate="2018-07-27T14:00:51.793" UserId="-1" />
  <row Id="20663" PostHistoryTypeId="2" PostId="7871" RevisionGUID="568c999f-1c32-4664-a5af-8a59962728a6" CreationDate="2018-07-27T21:30:49.750" UserId="7462" Text="I have a scene rendered using texelFetch() and I am trying to modify the shader to use textureLod() instead.&#xD;&#xA;&#xD;&#xA;This is the image generated with texelFetch:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When I try to change the shader to use textureLod instead I get:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So as you can see, areas that should not be darkend are now darkened. This seems like the downscaling to the 0-1 coordinate system was not done properly.&#xD;&#xA;&#xD;&#xA;This is how I generated the first image:&#xD;&#xA;&#xD;&#xA;    fragment_color = blinn_phong();&#xD;&#xA;&#xD;&#xA;	float v_size = cube_dim/voxel_resolution;&#xD;&#xA;	vec3 r = f_pos + f_norm*v_size*2;&#xD;&#xA;	vec3 dir = normalize(light-r);&#xD;&#xA;    vec3 start = r;&#xD;&#xA;	ivec3 first = ivec3(((r)*0.5/(cube_dim)+vec3(0.5))*(voxel_resolution-1));&#xD;&#xA;    float hit = 1.f;&#xD;&#xA;    while(incube(r, cube_dim) &amp;&amp; (length(start-r)&lt;=length(start-light)))&#xD;&#xA;    {&#xD;&#xA;        r += dir*v_size*0.5;&#xD;&#xA;		ivec3 hpos = ivec3(((r)*0.5/cube_dim+vec3(0.5))*(voxel_resolution-1));&#xD;&#xA;        vec4 val = texelFetch(normal_map, hpos, 0);&#xD;&#xA;        if(val.w &gt; 0 &amp;&amp; (first != hpos))&#xD;&#xA;        {&#xD;&#xA;            hit=atan(length(start-r)/200.f)/(PI/2.f)*0.9 + 0.1;&#xD;&#xA;            break;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;	fragment_color *=hit;&#xD;&#xA;&#xD;&#xA;And this is how I generated the second:&#xD;&#xA;&#xD;&#xA;    fragment_color = blinn_phong();&#xD;&#xA;&#xD;&#xA;	float v_size = cube_dim/voxel_resolution;&#xD;&#xA;	vec3 r = f_pos + f_norm*v_size*2;&#xD;&#xA;	vec3 dir = normalize(light-r);&#xD;&#xA;    vec3 start = r;&#xD;&#xA;	ivec3 first = ivec3(((r)*0.5/(cube_dim)+vec3(0.5)));&#xD;&#xA;    float hit = 1.f;&#xD;&#xA;    while(incube(r, cube_dim) &amp;&amp; (length(start-r)&lt;=length(start-light)))&#xD;&#xA;    {&#xD;&#xA;        r += dir*v_size*0.5;&#xD;&#xA;		vec3 hpos = vec3(((r)*0.5/cube_dim+vec3(0.5)));&#xD;&#xA;        vec4 val = textureLod(normal_map, hpos, 0);&#xD;&#xA;        if(val.w &gt; 0 &amp;&amp; (first != hpos))&#xD;&#xA;        {&#xD;&#xA;            hit=atan(length(start-r)/200.f)/(PI/2.f)*0.9 + 0.1;&#xD;&#xA;            break;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;	fragment_color *=hit;&#xD;&#xA;&#xD;&#xA;In other words, the changes consist only on not scaling by the voxel  resolution, which should result in a 0 to 1 coordinate system, instead of the 0 to texture dimensions coordinate system.&#xD;&#xA;&#xD;&#xA;Alas, it would seem that I am downscaling thins wrongly.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9sMuT.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/mDO4r.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20664" PostHistoryTypeId="1" PostId="7871" RevisionGUID="568c999f-1c32-4664-a5af-8a59962728a6" CreationDate="2018-07-27T21:30:49.750" UserId="7462" Text="Changing coordinate system from texelFetch to textureLod is breaking the algebra" ContentLicense="CC BY-SA 4.0" />
  <row Id="20665" PostHistoryTypeId="3" PostId="7871" RevisionGUID="568c999f-1c32-4664-a5af-8a59962728a6" CreationDate="2018-07-27T21:30:49.750" UserId="7462" Text="|opengl|rendering|shader|shadow|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20669" PostHistoryTypeId="5" PostId="7869" RevisionGUID="0d24b644-bc46-4146-bc4a-384382400532" CreationDate="2018-07-28T10:19:11.260" UserId="6046" Comment="added 495 characters in body" Text="Consider a ray tracer written in OpenGL and using GLFW as a window toolkit. There are basically 2 options to display the ray-traced image.&#xD;&#xA;&#xD;&#xA;**1) Create a `RenderBuffer` with image and blit this to the default framebuffer.**&#xD;&#xA;&#xD;&#xA;**2) Render the scene to a texture and use a full screen quad to display that texture.**&#xD;&#xA;&#xD;&#xA;What if I want to render the scene in a resolution that is different from the window size? How do I handle rescaling of images.&#xD;&#xA;&#xD;&#xA;**Case 1)** Render to high resolution image/texture and display to low resolution window.&#xD;&#xA;&#xD;&#xA;I don't know how should I handle for downscaling the texture/image in both cases. I am particularly interested in the `Renderbuffer` approach though. &#xD;&#xA;&#xD;&#xA;**Case 2)** Render to low resolution image/texture and display to high resolution window.&#xD;&#xA;&#xD;&#xA;I am pretty sure case 2 could be easy to implement through textures by setting the filter to `LINEAR` or `NEAREST` perhaps, the sampling function would automatically upscale it?&#xD;&#xA;&#xD;&#xA;I am not sure what would happen to the renderBuffer approach in either case. I have read though that `Blit` between buffers of different sizes are supported.&#xD;&#xA;&#xD;&#xA;Also in both cases, how would I handle the aspect ratio?&#xD;&#xA;&#xD;&#xA;**EDIT**:- What I mean by handling aspect ratio is, to my knowledge there are two ways I could handle it. &#xD;&#xA;&#xD;&#xA;1) Either stretch the whole image to fit the window.&#xD;&#xA; &#xD;&#xA;2) Or make it &quot;fit&quot; to the window like Windows 7 wallpaper setting. This way the original aspect ratio of the Image will be maintained. Any space not covered by the image would be black in the window.&#xD;&#xA;&#xD;&#xA;I want to know if OpenGL provides functions for these sorts of settings or it does some or part of these things automatically. " ContentLicense="CC BY-SA 4.0" />
  <row Id="20670" PostHistoryTypeId="5" PostId="7869" RevisionGUID="7a8a4338-cf65-47b0-9ae5-38a67592ec97" CreationDate="2018-07-28T10:40:55.197" UserId="6046" Comment="added 524 characters in body" Text="Consider a ray tracer written in OpenGL and using GLFW as a window toolkit. There are basically 2 options to display the ray-traced image.&#xD;&#xA;&#xD;&#xA;**1) Create a `RenderBuffer` with image and blit this to the default framebuffer.**&#xD;&#xA;&#xD;&#xA;**2) Render the scene to a texture and use a full screen quad to display that texture.**&#xD;&#xA;&#xD;&#xA;What if I want to render the scene in a resolution that is different from the window size? How do I handle rescaling of images.&#xD;&#xA;&#xD;&#xA;**Case 1)** Render to high resolution image/texture and display to low resolution window.&#xD;&#xA;&#xD;&#xA;I don't know how should I handle for downscaling the texture/image in both cases. I am particularly interested in the `Renderbuffer` approach though. &#xD;&#xA;&#xD;&#xA;**Case 2)** Render to low resolution image/texture and display to high resolution window.&#xD;&#xA;&#xD;&#xA;I am pretty sure case 2 could be easy to implement through textures by setting the filter to `LINEAR` or `NEAREST` perhaps, the sampling function would automatically upscale it?&#xD;&#xA;&#xD;&#xA;I am not sure what would happen to the renderBuffer approach in either case. I have read though that `Blit` between buffers of different sizes are supported.&#xD;&#xA;&#xD;&#xA;Also in both cases, how would I handle the aspect ratio?&#xD;&#xA;&#xD;&#xA;**EDIT**:- What I mean by handling aspect ratio is, to my knowledge there are two ways I could handle it. &#xD;&#xA;&#xD;&#xA;1) Either stretch the whole image to fit the window.&#xD;&#xA; &#xD;&#xA;2) Or make it &quot;fit&quot; to the window like Windows 7 wallpaper setting. This way the original aspect ratio of the Image will be maintained. Any space not covered by the image would be black in the window.&#xD;&#xA;&#xD;&#xA;Here is a crappy painting to show what I mean.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now if the Red window is my RBO/Texture  and Black Window is the actual window ( default framebuffer) opened by GLFW. Left and right show two cases when either the RBO is greater or smaller than the default framebuffer with varying aspect ratio size.&#xD;&#xA;&#xD;&#xA;There are two ways, Either fit or stretch. I want to know if OpenGL provides functions for these sorts of settings or it does some or part of these things automatically. Plus I want to know this thing for both &#xD;&#xA;&#xD;&#xA;Cases 1) RBO &#xD;&#xA;&#xD;&#xA;and &#xD;&#xA;&#xD;&#xA;Case 2) Texture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GvnOF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20671" PostHistoryTypeId="5" PostId="7869" RevisionGUID="d8e38d71-e908-4721-b8ee-067f1de72a51" CreationDate="2018-07-28T11:06:28.813" UserId="6046" Comment="deleted 5 characters in body" Text="Consider a ray tracer written in OpenGL and using GLFW as a window toolkit. There are basically 2 options to display the ray-traced image.&#xD;&#xA;&#xD;&#xA;**1) Create a `RenderBuffer` with image and blit this to the default framebuffer.**&#xD;&#xA;&#xD;&#xA;**2) Render the scene to a texture and use a full screen quad to display that texture.**&#xD;&#xA;&#xD;&#xA;What if I want to render the scene in a resolution that is different from the window size? How do I handle rescaling of images.&#xD;&#xA;&#xD;&#xA;**Case 1)** Render to high resolution image/texture and display to low resolution window.&#xD;&#xA;&#xD;&#xA;I don't know how should I handle for downscaling the texture/image in both cases. I am particularly interested in the `Renderbuffer` approach though. &#xD;&#xA;&#xD;&#xA;**Case 2)** Render to low resolution image/texture and display to high resolution window.&#xD;&#xA;&#xD;&#xA;I am pretty sure case 2 could be easy to implement through textures by setting the filter to `LINEAR` or `NEAREST` perhaps, the sampling function would automatically upscale it?&#xD;&#xA;&#xD;&#xA;I am not sure what would happen to the renderBuffer approach in either case. I have read though that `Blit` between buffers of different sizes are supported.&#xD;&#xA;&#xD;&#xA;Also in both cases, how would I handle the aspect ratio?&#xD;&#xA;&#xD;&#xA;**EDIT**:- What I mean by handling aspect ratio is, to my knowledge there are two ways I could handle it. &#xD;&#xA;&#xD;&#xA;1) Either stretch the whole image to fit the window.&#xD;&#xA; &#xD;&#xA;2) Or make it &quot;fit&quot; to the window like Windows 7 wallpaper setting. This way the original aspect ratio of the Image will be maintained. Any space not covered by the image would be black in the window.&#xD;&#xA;&#xD;&#xA;Here is a crappy painting to show what I mean.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now if the Red window is my RBO/Texture  and Black Window is the actual window ( default framebuffer) opened by GLFW. Left and right show two cases when either the RBO is greater or smaller than the default framebuffer with varying aspect ratio.&#xD;&#xA;&#xD;&#xA;There are two ways, Either fit or stretch. I want to know if OpenGL provides functions for these sorts of settings or it does some or part of these things automatically. Plus I want to know this thing for both &#xD;&#xA;&#xD;&#xA;Case 1) RBO &#xD;&#xA;&#xD;&#xA;and &#xD;&#xA;&#xD;&#xA;Case 2) Texture. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GvnOF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20672" PostHistoryTypeId="4" PostId="7869" RevisionGUID="d8e38d71-e908-4721-b8ee-067f1de72a51" CreationDate="2018-07-28T11:06:28.813" UserId="6046" Comment="deleted 5 characters in body" Text="OpenGL - Fit High/Low Resolution Image/Texture to a particular size Window" ContentLicense="CC BY-SA 4.0" />
  <row Id="20675" PostHistoryTypeId="2" PostId="7873" RevisionGUID="527088a1-1461-4ae8-b433-6f4f3bf4a330" CreationDate="2018-07-28T23:59:40.227" UserId="9041" Text="Looking at the Wikipedia page for Circle of Confusion, and at such posts as [this one][1], I completely understand how to calculate the values for near, far, focal planes and hyperfocal distance. I am also aware of the Zeiss formula for my desired format.&#xD;&#xA;&#xD;&#xA;**What I'm trying to find out is how to take real camera parameters (focal distance, aperture, focal length) and get a *blur radius* or similar usable value to configure a blur with them.**&#xD;&#xA;&#xD;&#xA;Currently, I'm simply using this function:&#xD;&#xA;&#xD;&#xA;`float getBlurSize(float depth, float focusPoint, float focusScale) {&#xD;&#xA;	float coc = clamp((1.0 / focusPoint - 1.0 / depth)*focusScale, -1.0, 1.0);&#xD;&#xA;	return abs(coc) * MAX_BLUR_SIZE;&#xD;&#xA;}`&#xD;&#xA;&#xD;&#xA;All real-world inputs are available to the shader - Aperture f-Number, focal distance, format dimensions (35mm in this case), maximum acceptable CoC from the Zeiss formula, focal length etc., as well as depth and colour. Currently, I am applying the calculations and blur in post.&#xD;&#xA;&#xD;&#xA;  [1]: https://photo.stackexchange.com/questions/24826/is-there-a-formula-to-calculate-dof" ContentLicense="CC BY-SA 4.0" />
  <row Id="20676" PostHistoryTypeId="1" PostId="7873" RevisionGUID="527088a1-1461-4ae8-b433-6f4f3bf4a330" CreationDate="2018-07-28T23:59:40.227" UserId="9041" Text="Deriving blur from real optical formulae" ContentLicense="CC BY-SA 4.0" />
  <row Id="20677" PostHistoryTypeId="3" PostId="7873" RevisionGUID="527088a1-1461-4ae8-b433-6f4f3bf4a330" CreationDate="2018-07-28T23:59:40.227" UserId="9041" Text="|projections|blur|camera|post-processing|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20678" PostHistoryTypeId="2" PostId="7874" RevisionGUID="3dfcad7c-b756-4258-b099-db12e36b5c82" CreationDate="2018-07-29T10:33:19.703" UserId="9096" Text="I am analyzing the hex code for DDS files which are compressed via Nvidia's dds plugin in photoshop.&#xD;&#xA;&#xD;&#xA;I noticed something strange when having a 16 bit float file. This is the dialog: &#xD;&#xA;[![Dialog][1]][1]&#xD;&#xA;&#xD;&#xA;When I look at the header of this file it appears to not follow the DDS spec. According to the DDS docs for the pixel format (https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dds-pixelformat)&#xD;&#xA;the dwFlags of 0x4 indicates a FOURCC but the next 4 bytes, which usually contain the FOURCC like &quot;DXT1&quot; etc contain only a &quot;o&quot;&#xD;&#xA;[![Hex viewl][2]][2]&#xD;&#xA;&#xD;&#xA;AFAIK the for various other formats the locations and FOURCC (when present) are correctly displayed.&#xD;&#xA;Here is a luminance 8 (dwFLags to 0x20000 and no FOURCC)&#xD;&#xA;[![L8][3]][3]&#xD;&#xA;&#xD;&#xA;and here is a DXT1&#xD;&#xA;[![DXT1][4]][4]&#xD;&#xA;&#xD;&#xA;Could somebody hint what happens for 16f here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/J9PiD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QOvKx.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/wU6Vu.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/1MC3r.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20679" PostHistoryTypeId="1" PostId="7874" RevisionGUID="3dfcad7c-b756-4258-b099-db12e36b5c82" CreationDate="2018-07-29T10:33:19.703" UserId="9096" Text="Image saved as DDS with 16f format in photoshop has strange FOURCC text" ContentLicense="CC BY-SA 4.0" />
  <row Id="20680" PostHistoryTypeId="3" PostId="7874" RevisionGUID="3dfcad7c-b756-4258-b099-db12e36b5c82" CreationDate="2018-07-29T10:33:19.703" UserId="9096" Text="|directx|raster-image|direct3d|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20681" PostHistoryTypeId="2" PostId="7875" RevisionGUID="137d559d-ea3f-48aa-a239-d63927630264" CreationDate="2018-07-29T19:03:21.360" UserId="48" Text="The tool seems to be generating an unofficial extended version of DDS in which the FOURCC code is replaced by a value from the [`D3DFORMAT` enum](https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3dformat). The code `0x0000006F` translates to decimal 111, which translates to `D3DFMT_R16F`.&#xD;&#xA;&#xD;&#xA;The Microsoft DDS documentation notes that this is seen sometimes, although not recommended: [DDS Variants](https://docs.microsoft.com/en-us/windows/desktop/direct3ddds/dx-graphics-dds-pguide#dds-variants)&#xD;&#xA;&#xD;&#xA;&gt; There are some common variants in use where the pixel format is set to a DDPF_FOURCC code where dwFourCC is set to a D3DFORMAT or DXGI_FORMAT enumeration value. There is no way to tell if an enumeration value is a D3DFORMAT or a DXGI_FORMAT, so it is highly recommended that the &quot;DX10&quot; extension and DDS_HEADER_DXT10 header is used instead to store the dxgiFormat when the basic DDS_PIXELFORMAT cannot express the format." ContentLicense="CC BY-SA 4.0" />
  <row Id="20682" PostHistoryTypeId="2" PostId="7876" RevisionGUID="b9089e85-f60d-4125-838b-1912e4273dee" CreationDate="2018-07-29T22:35:45.530" UserId="7462" Text="I am generating shadows using a voxel pyrammid (commonly called voxel cone, although I hate that term).&#xD;&#xA;&#xD;&#xA;Some of my shadows come as expected, however some are very strange.&#xD;&#xA;&#xD;&#xA;For example in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you look at the back column at the right, we have a neat soft shadow. However the shadows over the shield are hard, As are the shadows on the other columns.&#xD;&#xA;&#xD;&#xA;I am not sure why or how these hard shadows are being created.&#xD;&#xA;&#xD;&#xA;The way I am making my shadows is the standard shadow pyrammid that increases as the ray advances, sampling at different LOD's&#xD;&#xA;&#xD;&#xA;In other words, this is the shader:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        fragment_color = blinn_phong();&#xD;&#xA;    &#xD;&#xA;    	float v_size = cube_dim/voxel_resolution;&#xD;&#xA;    	vec3 r = f_pos + f_norm*v_size*6;&#xD;&#xA;    	vec3 dir = normalize(light-r);&#xD;&#xA;        vec3 start = r;&#xD;&#xA;    	float l=0;&#xD;&#xA;    	float acc=0;&#xD;&#xA;    	vec4 val1, val2;&#xD;&#xA;        while(incube(r, cube_dim) &amp;&amp; (l&lt;=length(start-light)) &amp;&amp; acc&lt;1)&#xD;&#xA;        {&#xD;&#xA;    		l=length(start-r);&#xD;&#xA;            r += dir*v_size*0.2;&#xD;&#xA;    		float coeff = 0.001;&#xD;&#xA;    		l = min(l, 7*1.f/(coeff));&#xD;&#xA;    		val1 = textureLod(normal_map, (r)*0.5/cube_dim+vec3(0.5), l*coeff);&#xD;&#xA;    		acc += val1.a;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    	acc = min(acc, 1);&#xD;&#xA;    	fragment_color *= (1-acc)*0.8 + 0.2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xGcQD.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20683" PostHistoryTypeId="1" PostId="7876" RevisionGUID="b9089e85-f60d-4125-838b-1912e4273dee" CreationDate="2018-07-29T22:35:45.530" UserId="7462" Text="Hard edges appearing in voxel cone tracing (how to remove them?)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20684" PostHistoryTypeId="3" PostId="7876" RevisionGUID="b9089e85-f60d-4125-838b-1912e4273dee" CreationDate="2018-07-29T22:35:45.530" UserId="7462" Text="|opengl|rendering|global-illumination|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20685" PostHistoryTypeId="2" PostId="7877" RevisionGUID="e8d9fab0-997d-4eec-9fcb-c4804353dadd" CreationDate="2018-07-30T00:59:17.243" UserId="5717" Text="&gt; **First, (1/2) I didn't understand how the hash table is actually used.** The workflow I think I understood is the following :&#xD;&#xA;&gt; &#xD;&#xA;&gt; 1. For an input (coordinate), we find the both nearest pre-defined coordinates (i.e. : those present as indices in A). It's a multiple of&#xD;&#xA;&gt; 255.&#xD;&#xA;&gt; &#xD;&#xA;&gt; 2. The lower one is used to lookup in B&#xD;&#xA;&gt; &#xD;&#xA;&gt; 3. We get a number between [0;255] that we use to lookup in A &#xD;&#xA;&gt; &#xD;&#xA;&gt; 4. We get a number between [0;1] : the noise.&#xD;&#xA;&gt; &#xD;&#xA;&gt; But where is the interpolation between the both pre-defined&#xD;&#xA;&gt; coordinates' noise values ?&#xD;&#xA;&#xD;&#xA;There are 4 of most of what you wrote here, then the interpolation. For example, if your 2D input is (2.7, 6.4):&#xD;&#xA;&#xD;&#xA;1. You would truncate that to (2,6).&#xD;&#xA;2. Then perform the permutation and noise lookup steps for (2,6), (3,6), (2,7), (3,7).&#xD;&#xA;3. And finally perform a 2D interpolation (lerp) of the 4 lookups with the remainder of your input: (0.7, 0.4).&#xD;&#xA;&#xD;&#xA;As for the second part of your question, the table is just a creative way to get a &quot;(int, int) -&gt; int&quot; hashing function to go from input coordinates to an index to pick a value in the random data table. You could use any generic hash function instead. In fact, the method used is fairly obsolete for CPUs as it does not lend itself to SIMD implementation and has horrible memory dependencies. It might still have value for GPUs as they have different behavior. But it will have a visible period of 256 which can cause problems in images. So it is really a poor hash function but for the CPUs back then, it was fast and used little memory which is likely why it was picked." ContentLicense="CC BY-SA 4.0" />
  <row Id="20689" PostHistoryTypeId="2" PostId="7878" RevisionGUID="fda69ee1-7ebe-4ddc-bc0d-cd9b1d56970d" CreationDate="2018-07-30T08:36:09.087" UserId="137" Text="You first need to put all the data into a VBO in the correct order, it's important that each vertex position corresponds with the normal it uses.&#xD;&#xA;&#xD;&#xA;    struct Vertex{&#xD;&#xA;        vec3 pos;&#xD;&#xA;        vec3 normal;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    std::vector&lt;Vertex&gt; vertices;&#xD;&#xA;    vertices.reserve(vecf*3);&#xD;&#xA;    Vertex v;&#xD;&#xA;&#xD;&#xA;    for(int j = 0; j &lt; vecf.size(); j++){&#xD;&#xA;        v.normal = vec3(vecn[vecf.at(j)[2]-1][0], vecn[vecf.at(j)[2]-1][1], vecn[vecf.at(j)[2]-1][2]);&#xD;&#xA;        v.pos = vec3(vecv[vecf.at(j)[0]-1][0], vecv[vecf.at(j)[0]-1][1], vecv[vecf.at(j)[0]-1][2]);&#xD;&#xA;        vertices.push_back(v);&#xD;&#xA;        v.normal = vec3(vecn[vecf.at(j)[5]-1][0], vecn[vecf.at(j)[5]-1][1], vecn[vecf.at(j)[5]-1][2]);&#xD;&#xA;        v.pos = vec3(vecv[vecf.at(j)[3]-1][0], vecv[vecf.at(j)[3]-1][1], vecv[vecf.at(j)[3]-1][2]);&#xD;&#xA;        vertices.push_back(v);&#xD;&#xA;        v.normal = vec3((vecn[vecf.at(j)[8]-1][0], vecn[vecf.at(j)[8]-1][1], vecn[vecf.at(j)[8]-1][2]);&#xD;&#xA;        v.pos = vec3(vecv[vecf.at(j)[6]-1][0], vecv[vecf.at(j)[6]-1][1], vecv[vecf.at(j)[6]-1][2]);&#xD;&#xA;        vertices.push_back(v);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int vbo;&#xD;&#xA;    glGenBuffer(1, &amp;vbo);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), vertices.data(), GL_STATIC_DRAW);&#xD;&#xA;    glVertexAttribPointer(posAttr, 3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, pos));&#xD;&#xA;    glVertexAttribPointer(normalAttr, 3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, normal));&#xD;&#xA;&#xD;&#xA;then you can draw it with `glDrawArrays(GL_TRIANGLES, 0, vertices.size());`" ContentLicense="CC BY-SA 4.0" />
  <row Id="20690" PostHistoryTypeId="5" PostId="7465" RevisionGUID="fc3c298b-be91-44f1-97ee-98d574466156" CreationDate="2018-07-31T05:15:14.167" UserId="7431" Comment="Added Mathjax formatting to formulas." Text="Im trying to complain the algorithm to calculate the HSL value form a RGB color. I understand the algorithm for the Hue, but im lost with the Lightness and saturation. Someone can explain why?&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**There is the algorithm:**&#xD;&#xA;&#xD;&#xA;$$R'=R/255$$&#xD;&#xA;&#xD;&#xA;$$G'=G/255$$&#xD;&#xA;&#xD;&#xA;$$B'=B/255$$&#xD;&#xA;&#xD;&#xA;$$C_{max}=\max\left(R',G',B'\right)$$&#xD;&#xA;&#xD;&#xA;$$C_{min}=\min\left(R',G',B'\right)$$&#xD;&#xA;&#xD;&#xA;$$\Delta=C_{max}-C_{min}$$&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Hue Calculation:**&#xD;&#xA;&#xD;&#xA;$$H = \begin{cases}&#xD;&#xA;0^\circ &amp; ,\Delta=0\\&#xD;&#xA;60^\circ \times \left(\frac{G'-B'}{\Delta}\mod 6\right) &amp; ,C_{max}=R'\\&#xD;&#xA;60^\circ \times \left(\frac{B'-R'}{\Delta}+2\right) &amp; ,C_{max}=G'\\&#xD;&#xA;60^\circ \times \left(\frac{R'-G'}{\Delta}+4\right) &amp; ,C_{max}=B'&#xD;&#xA;\end{cases}$$&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Lightness calculation:**&#xD;&#xA;&#xD;&#xA;$$L=\frac{C_{max} + C_{min}}{2}$$&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Saturation calculation:**&#xD;&#xA;&#xD;&#xA;$$S=\begin{cases}&#xD;&#xA;0 &amp; ,\Delta=0\\&#xD;&#xA;\frac{\Delta}{1-|2L-1|} &amp; ,\Delta &lt;&gt; 0&#xD;&#xA;\end{cases}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="20691" PostHistoryTypeId="24" PostId="7465" RevisionGUID="fc3c298b-be91-44f1-97ee-98d574466156" CreationDate="2018-07-31T05:15:14.167" Comment="Proposed by 7431 approved by 231 edit id of 430" ContentLicense="CC BY-SA 4.0" />
  <row Id="20692" PostHistoryTypeId="2" PostId="7879" RevisionGUID="298833a2-57aa-4ca3-838b-62db56384d64" CreationDate="2018-07-31T06:08:56.077" UserId="3003" Text="First it converts the red, green, and blue values from the 8-bit unsigned integer range to a floating point value between 0 and 1. It then figures out which component is the maximum, which is the minimum and the distance between the minimum and maximum. &#xD;&#xA;&#xD;&#xA;If the min and max are equal, then the saturation is 0, and it makes no sense to calculate a hue. Here they are setting it to 0, but in reality, it's simply undefined. Assuming that no hue equals 0 hue can cause problem if you later manipulate the colors, so be careful with that.&#xD;&#xA;&#xD;&#xA;If the min and max are not equal, the we can calculate a hue. The shape of the HSL color space is a double hexagonal cone. What the next part does is attempt to figure out which segment of the hexagonal cone the hue is in. If the maximum of the red, green, and blue, was the red channel, then it's in the area bounded by -60° to +60°. If green is the max, then the hue is between 60° and 180°, and if blue is the max, then the hue is between 180° and 300° (aka -60°). &#xD;&#xA;&#xD;&#xA;The division in the calculation generates a value between -1 and 1. If red is the maximum component, then green - blue is either the middle value minus the lower value, or it's the lower value minus the middle value. And since the middle and lower value are lower than the maximum, dividing by the delta will always give a value between -1 and 1. Once you have a value between -1 and 1, you multiply it by 60 to get the degrees. For the other 2 cases, you add either 2 or 4 before the multiply in order to rotate it 120° or 240° for the green and blue.&#xD;&#xA;&#xD;&#xA;Next it calculates the lightness by simply averaging the min and max components. (This is a very poor way to represent the perceived brightness of a color, by the way.)&#xD;&#xA;&#xD;&#xA;Finally, it calculates the saturation. If the delta is 0, then saturation is 0. Otherwise it divides the delta by `1 - abs(2 * L - 1)`. Essentially, it's saying that saturation is proportional to the distance between the minimum and the maximum values and inversely proportional to the lightness's distance from 50% lightness. In other words, as you move away from the vertical center of the double hex cone, towards the pointy ends, the distance between the min and max components has a bigger effect on saturation. A difference in the delta of, say, .1 at the center will not show much difference in saturation, but when the lightness is very close to either 0 or 1, it will make a large difference in saturation." ContentLicense="CC BY-SA 4.0" />
  <row Id="20693" PostHistoryTypeId="5" PostId="7873" RevisionGUID="e3b87692-4454-47d2-817f-ec758c936249" CreationDate="2018-07-31T06:45:59.080" UserId="2041" Comment="Formatting this code as a block instead of individual lines of code makes it easier to understand." Text="Looking at the Wikipedia page for Circle of Confusion, and at such posts as [this one][1], I completely understand how to calculate the values for near, far, focal planes and hyperfocal distance. I am also aware of the Zeiss formula for my desired format.&#xD;&#xA;&#xD;&#xA;**What I'm trying to find out is how to take real camera parameters (focal distance, aperture, focal length) and get a *blur radius* or similar usable value to configure a blur with them.**&#xD;&#xA;&#xD;&#xA;Currently, I'm simply using this function:&#xD;&#xA;&#xD;&#xA;    float getBlurSize(float depth, float focusPoint, float focusScale) {&#xD;&#xA;	    float coc = clamp((1.0 / focusPoint - 1.0 / depth)*focusScale, -1.0, 1.0);&#xD;&#xA;    	return abs(coc) * MAX_BLUR_SIZE;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;All real-world inputs are available to the shader - Aperture f-Number, focal distance, format dimensions (35mm in this case), maximum acceptable CoC from the Zeiss formula, focal length etc., as well as depth and colour. Currently, I am applying the calculations and blur in post.&#xD;&#xA;&#xD;&#xA;  [1]: https://photo.stackexchange.com/questions/24826/is-there-a-formula-to-calculate-dof" ContentLicense="CC BY-SA 4.0" />
  <row Id="20694" PostHistoryTypeId="6" PostId="7873" RevisionGUID="e3b87692-4454-47d2-817f-ec758c936249" CreationDate="2018-07-31T06:45:59.080" UserId="2041" Comment="Formatting this code as a block instead of individual lines of code makes it easier to understand." Text="|blur|camera|post-processing|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20695" PostHistoryTypeId="2" PostId="7880" RevisionGUID="51186cec-2c17-4693-a35a-932f5cf855e9" CreationDate="2018-07-31T13:54:43.867" UserId="182" Text="Back when I did the transition from immediate mode to vertex buffer object (VBO) in my own code base, I have found it easier to proceed with these steps:&#xD;&#xA;&#xD;&#xA;# From naive immediate mode code...&#xD;&#xA;&#xD;&#xA;The original code was something like this:&#xD;&#xA;&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    glNormal3f(nx, ny, nz);&#xD;&#xA;    glVertex3f(px, py, pz);&#xD;&#xA;    // [...] arbitrary long sequence of such function calls.&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;# 1. To array based immediate mode code...&#xD;&#xA;&#xD;&#xA;First, keep using the immediate mode, but make sure that all values passed to the vertex functions come from an array. This seems to be already the state of the code described in the question.&#xD;&#xA;&#xD;&#xA;    float vertexData[] = { ... }; // Can be all together, or split by attribute type, as you prefer.&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;    for (int i = 0; i &lt; numberOfVertices; ++i)&#xD;&#xA;    {&#xD;&#xA;        // The indices are going to depend on the data layout.&#xD;&#xA;        glNormal3f(vertexData[0], vertexData[1], vertexData[2]);&#xD;&#xA;        glVertex3f(vertexData[3], vertexData[4], vertexData[5]);&#xD;&#xA;    }&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;# 2. To vertex array version...&#xD;&#xA;&#xD;&#xA;Second, you can replace the loop by a handful of calls with vertex arrays.&#xD;&#xA;&#xD;&#xA;    glEnableClientstate(GL_Vertex_Array);&#xD;&#xA;    glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), vertexData);&#xD;&#xA;    glNormalPointer(GL_FLOAT, 6 * sizeof(float), vertexData + 3);&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);&#xD;&#xA;    glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;&#xD;&#xA;# 3. To vertex buffer version&#xD;&#xA;&#xD;&#xA;Finally from the vertex array based version, the transition to VBO is minimal:&#xD;&#xA;&#xD;&#xA;    // An initialization part will create and populate the vertex buffer:&#xD;&#xA;    GLuint vboId = 0;&#xD;&#xA;    glGenBuffers(1, &amp;VBOid);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOid);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(float), vertexData, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // A draw part will bind the vertex buffer and issue the drawcall.&#xD;&#xA;    // It's almost the same code as before, except:&#xD;&#xA;    // - We bind a VBO&#xD;&#xA;    // - We pass (0+offset) as the last parameter for the gl*pointer().&#xD;&#xA;    glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOId);&#xD;&#xA;&#xD;&#xA;    glEnableClientstate(GL_Vertex_Array);&#xD;&#xA;    glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (void*)(0));&#xD;&#xA;    glNormalPointer(GL_FLOAT, 6 * sizeof(float), (void*)(0 + 3));&#xD;&#xA;    glDrawArrays(GL_TRIANGLES, 0, numberOfVertices);&#xD;&#xA;    glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;&#xD;&#xA;And that's it. Both vertex array and VBO allow to work directly with vertices or with vertex index, so be careful about possible confusion there.&#xD;&#xA;&#xD;&#xA;P.S.: I have written this answer without double checking the code, so it's probably ridden with typos and not meant for copy-pasting. I invite you to read the documentation, understand the API and refer to other examples when you implement it. At first, VBO can be really annoying to get to work properly.&#xD;&#xA;&#xD;&#xA;I have used the same distinction when answering this other [question about performance of VBO](https://computergraphics.stackexchange.com/a/36/182)." ContentLicense="CC BY-SA 4.0" />
  <row Id="20696" PostHistoryTypeId="2" PostId="7881" RevisionGUID="a7537490-6ced-4f3c-b7a2-e8f884403bad" CreationDate="2018-07-31T14:44:33.153" UserId="8598" Text="I pulled a .zip file from https://www.deviantart.com/clairejones/art/Apophysis-Starter-Flames-V-67029474 and the file I was interested was the `.flame` file which contains parameters for several different Fractal Flames.&#xD;&#xA;&#xD;&#xA;One of them looks like this:&#xD;&#xA;&#xD;&#xA;    &lt;flame name=&quot;CJ_Starter_Flame_1&quot; version=&quot;Apophysis 2.06c beta&quot; size=&quot;640 512&quot; center=&quot;0.536884822382779 -0.626382357937026&quot; scale=&quot;764.167485097157&quot; angle=&quot;1.82997772071605&quot; rotate=&quot;-104.85&quot; oversample=&quot;2&quot; filter=&quot;1&quot; quality=&quot;5&quot; background=&quot;0 0 0&quot; brightness=&quot;2&quot; gamma=&quot;5&quot; &gt;&#xD;&#xA;       &lt;xform weight=&quot;0.5&quot; color=&quot;0&quot; linear=&quot;0.98505982500501&quot; spherical=&quot;0.0149401749949902&quot; coefs=&quot;0.047466 -0.574133 0.524841 0.137706 0.620555 -0.116118&quot; /&gt;&#xD;&#xA;       &lt;xform weight=&quot;0.5&quot; color=&quot;1&quot; spherical=&quot;0.17593513103202&quot; bubble=&quot;0.82406486896798&quot; coefs=&quot;0.268823 -0.261644 0.261644 0.268823 0.204257 0.083402&quot; /&gt;&#xD;&#xA;       &lt;palette count=&quot;256&quot; format=&quot;RGB&quot;&gt;&#xD;&#xA;          253625384A3348593D5C664C6E685B7A7260827363938169&#xD;&#xA;    ...&#xD;&#xA;       &lt;/palette&gt;&#xD;&#xA;    &lt;/flame&gt;&#xD;&#xA;&#xD;&#xA;Having read [the original Draves &amp; Reckase paper][1] some of this is obvious.  The `coefs=` probably contains the parameters of the affine transform.  The thing that really confuses me is how a single `xform` clause mentions two variants, e.g. `linear` and `spherical`.  It appears that the values on each attribute sum to 1 so they are probably weights/probabilities.  But why are there two xform clauses?  Are they alternating weighted transform sets?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://flam3.com/flame.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="20697" PostHistoryTypeId="1" PostId="7881" RevisionGUID="a7537490-6ced-4f3c-b7a2-e8f884403bad" CreationDate="2018-07-31T14:44:33.153" UserId="8598" Text="How do I interpret the format of the .flame files used by apophysis?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20698" PostHistoryTypeId="3" PostId="7881" RevisionGUID="a7537490-6ced-4f3c-b7a2-e8f884403bad" CreationDate="2018-07-31T14:44:33.153" UserId="8598" Text="|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20699" PostHistoryTypeId="5" PostId="7879" RevisionGUID="1d6431ed-7235-452d-a805-981e20b0607f" CreationDate="2018-07-31T16:01:54.800" UserId="3003" Comment="Fixed some grammar and spelling" Text="First it converts the red, green, and blue values from the 8-bit unsigned integer range to floating point values between 0 and 1. It then figures out which component is the maximum, which is the minimum and the distance between the minimum and maximum. &#xD;&#xA;&#xD;&#xA;If the min and max are equal, then the saturation is 0, and it makes no sense to calculate a hue. Here they are setting the hue to 0, but in reality, it's simply undefined. Assuming that no hue equals 0 hue can cause problem if you later manipulate the colors, so be careful with that.&#xD;&#xA;&#xD;&#xA;If the min and max are not equal, then we can calculate a hue. The shape of the HSL color space is a double hexagonal cone. What the next part does is attempt to figure out which segment of the hexagonal cone the hue is in. If the maximum of the red, green, and blue, was the red channel, then it's in the area bounded by -60° to +60°. If green is the max, then the hue is between 60° and 180°, and if blue is the max, then the hue is between 180° and 300° (aka -60°). &#xD;&#xA;&#xD;&#xA;The division in the hue calculation generates a value between -1 and 1. If red is the maximum component, then `green - blue` is either the middle value minus the lower value, or it's the lower value minus the middle value. And since the middle and lower value are never greater than the maximum, dividing by the delta will always give a value between -1 and 1. Once you have a value between -1 and 1, you multiply it by 60 to get the degrees. For the other 2 cases, you add either 2 or 4 before the multiply in order to rotate it 120° or 240° for the green and blue.&#xD;&#xA;&#xD;&#xA;Next it calculates the lightness by simply averaging the min and max components. (This is a very poor way to represent the perceived brightness of a color, by the way.)&#xD;&#xA;&#xD;&#xA;Finally, it calculates the saturation. If the delta is 0, then saturation is 0. Otherwise it divides the delta by `1 - abs(2 * L - 1)`. Essentially, it's saying that saturation is proportional to the distance between the minimum and the maximum values and inversely proportional to the lightness's distance from 50% lightness. In other words, as you move away from the vertical center of the double hex cone, towards the pointy ends, the distance between the min and max components has a bigger effect on saturation. A difference in the delta of, say, .1 at the center will not show much difference in saturation, but when the lightness is very close to either 0 or 1, it will make a large difference in saturation." ContentLicense="CC BY-SA 4.0" />
  <row Id="20701" PostHistoryTypeId="5" PostId="7876" RevisionGUID="e9043adb-1de5-4d70-a752-110be2e74081" CreationDate="2018-08-01T22:33:16.560" UserId="7462" Comment="deleted 2 characters in body" Text="I am generating shadows using a voxel pyramid (commonly called voxel cone, although I hate that term).&#xD;&#xA;&#xD;&#xA;Some of my shadows come as expected, however some are very strange.&#xD;&#xA;&#xD;&#xA;For example in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you look at the back column at the right, we have a neat soft shadow. However the shadows over the shield are hard, As are the shadows on the other columns.&#xD;&#xA;&#xD;&#xA;I am not sure why or how these hard shadows are being created.&#xD;&#xA;&#xD;&#xA;The way I am making my shadows is the standard shadow pyramid that increases as the ray advances, sampling at different LOD's&#xD;&#xA;&#xD;&#xA;In other words, this is the shader:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        fragment_color = blinn_phong();&#xD;&#xA;    &#xD;&#xA;    	float v_size = cube_dim/voxel_resolution;&#xD;&#xA;    	vec3 r = f_pos + f_norm*v_size*6;&#xD;&#xA;    	vec3 dir = normalize(light-r);&#xD;&#xA;        vec3 start = r;&#xD;&#xA;    	float l=0;&#xD;&#xA;    	float acc=0;&#xD;&#xA;    	vec4 val1, val2;&#xD;&#xA;        while(incube(r, cube_dim) &amp;&amp; (l&lt;=length(start-light)) &amp;&amp; acc&lt;1)&#xD;&#xA;        {&#xD;&#xA;    		l=length(start-r);&#xD;&#xA;            r += dir*v_size*0.2;&#xD;&#xA;    		float coeff = 0.001;&#xD;&#xA;    		l = min(l, 7*1.f/(coeff));&#xD;&#xA;    		val1 = textureLod(normal_map, (r)*0.5/cube_dim+vec3(0.5), l*coeff);&#xD;&#xA;    		acc += val1.a;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    	acc = min(acc, 1);&#xD;&#xA;    	fragment_color *= (1-acc)*0.8 + 0.2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xGcQD.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20702" PostHistoryTypeId="2" PostId="7882" RevisionGUID="90f86b4f-7e32-48f1-9e51-1de756cec7ba" CreationDate="2018-08-02T04:53:14.720" UserId="9108" Text="[![][1]][1]&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/idwl1.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I want to know how to deal with the color of object,Should i use diffuse reflection on the surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20703" PostHistoryTypeId="1" PostId="7882" RevisionGUID="90f86b4f-7e32-48f1-9e51-1de756cec7ba" CreationDate="2018-08-02T04:53:14.720" UserId="9108" Text="how to render colored glass object?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20704" PostHistoryTypeId="3" PostId="7882" RevisionGUID="90f86b4f-7e32-48f1-9e51-1de756cec7ba" CreationDate="2018-08-02T04:53:14.720" UserId="9108" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20705" PostHistoryTypeId="2" PostId="7883" RevisionGUID="3edd43f1-b68d-475e-898d-c7d3cd2e0ca9" CreationDate="2018-08-02T10:04:07.693" UserId="9113" Text="I wish to draw a plane (A building's floor in this case) over a canvas plane (assume the plane is smooth). The planes are drawn as QUADS.&#xD;&#xA;&#xD;&#xA;The problem is that both plane are located at the same height. This causes a flickering between the images as I zoom in/out. &#xD;&#xA;&#xD;&#xA;I wish for the floor texture / plane to have a higher priority over the base canvas plane. Is it possible? If so, how may I achieve it? &#xD;&#xA;&#xD;&#xA;I've tried putting the floor plane just slightly above the canvas plane, but it doesn't sit right with me considering my use case allows the user to set any building height and he/she may enter a very low value to height, cause a lot of problems. " ContentLicense="CC BY-SA 4.0" />
  <row Id="20706" PostHistoryTypeId="1" PostId="7883" RevisionGUID="3edd43f1-b68d-475e-898d-c7d3cd2e0ca9" CreationDate="2018-08-02T10:04:07.693" UserId="9113" Text="Drawing a plane super-imposing over another plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="20707" PostHistoryTypeId="3" PostId="7883" RevisionGUID="3edd43f1-b68d-475e-898d-c7d3cd2e0ca9" CreationDate="2018-08-02T10:04:07.693" UserId="9113" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20708" PostHistoryTypeId="2" PostId="7884" RevisionGUID="7c6c41dd-0dc8-46d2-bd28-914d70bed079" CreationDate="2018-08-02T12:18:06.197" UserId="4967" Text="Skia 2D's one notable backend in OpenGL, but how does it work under the hood to render?&#xD;&#xA;&#xD;&#xA;Say, we need to draw an anti-aliased circle. Does Skia:&#xD;&#xA;&#xD;&#xA; - make a quad (using 2 triangles) and paint the circle on top of it&#xD;&#xA;   using auto generated shaders?&#xD;&#xA; - Or, makes hundreds of triangles and arrange them into a fan? (plus&#xD;&#xA;   possible tessellation)&#xD;&#xA; - Or, something else?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20709" PostHistoryTypeId="1" PostId="7884" RevisionGUID="7c6c41dd-0dc8-46d2-bd28-914d70bed079" CreationDate="2018-08-02T12:18:06.197" UserId="4967" Text="How Skia uses OpenGL backend?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20710" PostHistoryTypeId="3" PostId="7884" RevisionGUID="7c6c41dd-0dc8-46d2-bd28-914d70bed079" CreationDate="2018-08-02T12:18:06.197" UserId="4967" Text="|opengl|shader|glsl|2d-graphics|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20711" PostHistoryTypeId="2" PostId="7885" RevisionGUID="405f2efa-1445-477e-a5a3-deee74f336dc" CreationDate="2018-08-02T12:22:27.860" UserId="8680" Text="A common interpretation of surfaces for rendering is that of a BSDF (Bidirectional Scattering Distribution Function) made up of a BRDF (R stands for Reflectance) and a BTDF (T stands for Transmittance).&#xD;&#xA;&#xD;&#xA;In such a model, the reflectance part is the light that 'bounces' off the surface, and the transmittance part is the light that penetrates the surface.&#xD;&#xA;&#xD;&#xA;When modeling the latter there are two common looks that we try to replicate. One is that of pure refraction (light goes through and bends at the surface), and the other is that of diffusion (light bounces around within the surface and is re-emitted (this is commonly called diffuse reflection). What determines which one of these happens is the turbidity of the material, which is analogous to the probability of a light ray changing its path while inside the material.&#xD;&#xA;&#xD;&#xA;These two phenomena are opposite ends of a spectrum and therefore there cannot, on real materials, be a blend (e.g. alpha blend) between the two. though one could concieve a model where turbidity of the material is not at either end but somewhere in-between, however that would require taking into account the volume of a 3d model and not only the surfaces (this often called Volume Scatter or Sub Surface Scatter).&#xD;&#xA;&#xD;&#xA;Thus, what you are looking for is probably refraction. There are many ways to aproximate it. One such way that will get you the expected color but not the distortion you might want is multiplicative blending." ContentLicense="CC BY-SA 4.0" />
  <row Id="20715" PostHistoryTypeId="5" PostId="7830" RevisionGUID="9ff3daf9-88af-4ec3-9df3-45cb8d707951" CreationDate="2018-08-02T15:27:00.017" UserId="9047" Comment="added details" Text="So I'm teaching crash-course in CUDA that teaches students how to write good GPU code (CUDA 7.5 in this case). They kernels they will be running will do matrix multiply on 2048x2048 floating point matrices, some kernels involving multiple blocks and shared memory. &#xD;&#xA;&#xD;&#xA;The students will be ssh-ing into servers that have the GPUs where they will compile and run their programmes.&#xD;&#xA;&#xD;&#xA;I haven't a clue on how feasible this is and the only step I can imagine taking to prevent slowdown is to assign groups of students to different GPUs by telling them what value to pass cudaSetDevice().&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit for posterities' sake: &#xD;&#xA;I ended up not taking any precautions and the lab ran smoothly. Wasn't much of test though, since only half (15 or so) students did the lab simultaneously, and we only got to cover really simple hello-world kernels. &#xD;&#xA;Second edit:&#xD;&#xA;There were two servers, with two GeForce GTX 650 Tis per server" ContentLicense="CC BY-SA 4.0" />
  <row Id="20716" PostHistoryTypeId="2" PostId="7887" RevisionGUID="b050b995-9e65-4192-b172-a17f1e3e502d" CreationDate="2018-08-02T21:56:09.690" UserId="4908" Text="The problem that you encounter is called &quot;z-fighting&quot; and it occurs when two objects with the same depth (z value) are rendered. &#xD;&#xA;&#xD;&#xA;In this example, we take two objects called ObjA and ObjB. They are the same, but have different colors. Due to the very small error that you get with fixed precision floating point numbers, ObjA may have a lower fragment depth than ObjB for a given pixel and thus ObjA's color is saved to that pixel, but ObjB could have a lower fragment depth for another given pixel and ObjB's color is then saved to that pixel. Which object will have a lower depth value is quite random and causes that flickering.&#xD;&#xA;&#xD;&#xA;There are two ways to fix this. Which one works best for you, depends on the program.&#xD;&#xA;&#xD;&#xA;### Option #1 ###&#xD;&#xA;Disabling depth testing on the second surface that is being drawn. The first surface obviously draws well, and the problem comes when drawing that second surface. By disabling the depth test, OpenGL just draws every fragment to the framebuffer and you do not have that problem with &quot;which fragment has the lowest depth&quot;. &#xD;&#xA;&#xD;&#xA;If you only disable the depth test for the second surface and enable it again for the other surfaces (and render the second surface after the first surface), then it should work as the first surface still writes the depth values. &#xD;&#xA;&#xD;&#xA;This approach starts to break, when the second surface either does not fully align with the first surface or the second surface is shaped in a way so that it overlaps itself. (When rendering a sphere, for each pixel you always render two fragments, the front side and the back side of the sphere. The back side would then not be culled away.)&#xD;&#xA;&#xD;&#xA;### Option #2 ###&#xD;&#xA;Adding a bias to the depth values of the first surface. The problem is that both surfaces have the same depth value for a given pixel, but if you offset the depth values for one of them, then you do not have that problem.&#xD;&#xA;&#xD;&#xA;Just like `gl_FragColor` which allows you to set the color in the framebuffer, [`gl_FragDepth`][1] allows you to set the depth in the depth buffer. You could get the normal depth value from `gl_FragCoord` (as the documentation says) and add a small amount to it. Doing this, does not actually change anything of the mesh. The mesh does not move around and it does not go further into z-space. The shader simply writes a different depth value to the depth buffer. This depth buffer is only used for depth testing and can thus easily be changed to get the effect we want. This only needs to be done for the first surface and not the second surface or any other surface.&#xD;&#xA;&#xD;&#xA;When the bias is too large, artifacts can visibly show up around intersections with the surface, but when the bias is small it should not be noticeable.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/gl_FragDepth.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="20723" PostHistoryTypeId="50" PostId="6373" RevisionGUID="7a9f9bab-d1c8-462a-85a0-60beae93b789" CreationDate="2018-08-05T05:00:34.683" UserId="-1" />
  <row Id="20724" PostHistoryTypeId="2" PostId="7890" RevisionGUID="3d384b8a-b6e6-4813-ae6c-569183b788b4" CreationDate="2018-08-05T05:39:22.830" UserId="48" Text="First we can calculate the physical diameter of CoC in the image plane, given the lens parameters. This equation is from [Wikipedia – Circle of confusion](https://en.wikipedia.org/wiki/Circle_of_confusion#Determining_a_circle_of_confusion_diameter_from_the_object_field):&#xD;&#xA;$$&#xD;&#xA;c = {|S_2 - S_1| \over S_2} {f^2 \over N(S_1 - f)}&#xD;&#xA;$$&#xD;&#xA;where the variables are:&#xD;&#xA;&#xD;&#xA;* $c$: the physical CoC diameter in the image plane&#xD;&#xA;* $S_1$: focal distance (the distance at which a subject would be in perfect focus)&#xD;&#xA;* $S_2$: actual distance to the subject (the point whose CoC we are calculating)&#xD;&#xA;* $f$: the focal length of the lens&#xD;&#xA;* $N$: the f-number at which the lens aperture is set.&#xD;&#xA;&#xD;&#xA;Then, divide this CoC diameter by the film or sensor frame size to get the blur diameter in texture coordinates. You can additionally multiply it by your rendering resolution to get the blur diameter in pixels if desired.&#xD;&#xA;&#xD;&#xA;As an example calculation, suppose we render a 1920×1080 image, as if through a 85mm lens at f/1.4, on a 35mm camera (frame size 36×24 mm), and focused at 3m while our subject is 5m away. Then we can calculate:&#xD;&#xA;$$&#xD;&#xA;{|5\text{m} - 3\text{m}| \over 5\text{m}} {(85\text{mm})^2 \over 1.4(3\text{m} - 85\text{mm})} {1920\text{px} \over 36\text{mm}}&#xD;&#xA;$$&#xD;&#xA;(Don't forget to convert units, since we are mixing meters and millimeters here!) I get a blur diameter of ~63 px, so the radius would therefore be ~31.5 px." ContentLicense="CC BY-SA 4.0" />
  <row Id="20732" PostHistoryTypeId="50" PostId="5697" RevisionGUID="4cd287b8-db99-430a-bc94-f9d6186ad142" CreationDate="2018-08-06T00:00:31.603" UserId="-1" />
  <row Id="20736" PostHistoryTypeId="2" PostId="7894" RevisionGUID="0ebb9b78-2310-437e-9a5f-4616592e6ec5" CreationDate="2018-08-06T08:14:20.967" UserId="116" Text="I am trying to retrieve OpenGL's color buffer with the following code. My program is crasing in the line that makes the call to **glReadPixels()** apparently `image.data` has not enough memory but how could it be if i'm getting the size from **GL_VIEWPORT** ?&#xD;&#xA;&#xD;&#xA;Am I missing something else? I already checked for errors with **glGetError()** and it returns 0 right before the call to glReadPixels.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;    void GLWidget::readGLBuffer(cv::Mat&amp; image)&#xD;&#xA;    {&#xD;&#xA;    	GLint vp[4];&#xD;&#xA;    	glGetIntegerv(GL_VIEWPORT, vp);&#xD;&#xA;    &#xD;&#xA;    	const GLint&amp; cols = vp[2];&#xD;&#xA;    	const GLint&amp; rows = vp[3];&#xD;&#xA;    &#xD;&#xA;    	if (rows * cols &lt;= 0)&#xD;&#xA;    		return;&#xD;&#xA;    &#xD;&#xA;    	image = cv::Mat(rows, cols, CV_8UC3);&#xD;&#xA;    &#xD;&#xA;    	glReadBuffer(GL_FRONT); // glReadPixels reads the back buffer by default&#xD;&#xA;    	glReadPixels(vp[0], vp[1], cols, rows, GL_RGB, GL_UNSIGNED_BYTE, image.data);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="20737" PostHistoryTypeId="1" PostId="7894" RevisionGUID="0ebb9b78-2310-437e-9a5f-4616592e6ec5" CreationDate="2018-08-06T08:14:20.967" UserId="116" Text="How to compute size of OpenGL's image buffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20738" PostHistoryTypeId="3" PostId="7894" RevisionGUID="0ebb9b78-2310-437e-9a5f-4616592e6ec5" CreationDate="2018-08-06T08:14:20.967" UserId="116" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20740" PostHistoryTypeId="2" PostId="7895" RevisionGUID="d26baafa-37ef-4f5f-9919-d33fb5aa1225" CreationDate="2018-08-06T12:41:58.827" UserId="9133" Text="I'm referring to this section: https://www.w3.org/TR/compositing-1/#simplealphacompositing&#xD;&#xA;&#xD;&#xA;Considering the formula `co = Cs x αs + Cb x αb x (1 - αs)` the docs state then, that `co` is the &#xD;&#xA;&#xD;&#xA;&gt; the premultiplied pixel value after compositing&#xD;&#xA;&#xD;&#xA;I would argue that this is not the case, since in [this article][1] the resulting color is depicted with a capital C and in the case of premultiplied version, the lower case is used (`c`). I'm not really sure if this is the case, it's not too obvious from both docs and the article. So, is the result of  `co = Cs x αs + Cb x αb x (1 - αs)` really a premultiplied value?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0004/02/03/paper.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="20741" PostHistoryTypeId="1" PostId="7895" RevisionGUID="d26baafa-37ef-4f5f-9919-d33fb5aa1225" CreationDate="2018-08-06T12:41:58.827" UserId="9133" Text="Are w3.org docs correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20742" PostHistoryTypeId="3" PostId="7895" RevisionGUID="d26baafa-37ef-4f5f-9919-d33fb5aa1225" CreationDate="2018-08-06T12:41:58.827" UserId="9133" Text="|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20744" PostHistoryTypeId="2" PostId="7896" RevisionGUID="ad5d439f-106c-47ac-a106-29cffd326afa" CreationDate="2018-08-06T18:48:36.140" UserId="48" Text="Yes, the statement in the W3C doc is correct. You can tell because the background term includes premultiplication by the background alpha αb. If it were non-premultiplied, it wouldn't have an αb in it." ContentLicense="CC BY-SA 4.0" />
  <row Id="20745" PostHistoryTypeId="2" PostId="7897" RevisionGUID="d469f389-59be-4de5-b301-2977f270b6d5" CreationDate="2018-08-06T19:15:34.117" UserId="6029" Text="Where should the ray origin be put in perspective camera ray tracing?&#xD;&#xA;&#xD;&#xA;http://www.cs.cornell.edu/courses/cs4620/2011fa/lectures/06raytracingWeb.pdf&#xD;&#xA;&#xD;&#xA;Can it be the zero vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20746" PostHistoryTypeId="1" PostId="7897" RevisionGUID="d469f389-59be-4de5-b301-2977f270b6d5" CreationDate="2018-08-06T19:15:34.117" UserId="6029" Text="Where should the ray origin be put in perspective camera ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20747" PostHistoryTypeId="3" PostId="7897" RevisionGUID="d469f389-59be-4de5-b301-2977f270b6d5" CreationDate="2018-08-06T19:15:34.117" UserId="6029" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20748" PostHistoryTypeId="5" PostId="7897" RevisionGUID="e8924401-57b8-4881-ab66-1326197b0f99" CreationDate="2018-08-06T19:24:05.277" UserId="6029" Comment="added 223 characters in body" Text="Where should the ray origin be put in perspective camera ray tracing?&#xD;&#xA;&#xD;&#xA;The following gives a picture of the ray tracing in the perspective camera setting:&#xD;&#xA;http://www.cs.cornell.edu/courses/cs4620/2011fa/lectures/06raytracingWeb.pdf&#xD;&#xA;&#xD;&#xA;and says that the $e$ is the ray origin, which is the same for all rays. However, I don't understand how is $e$ supposed to be selected.&#xD;&#xA;Can it be the zero vector? Or perhaps it's supposed to be the camera center?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20749" PostHistoryTypeId="2" PostId="7898" RevisionGUID="a7c386c8-e8e7-41be-9341-973a894de638" CreationDate="2018-08-06T19:56:56.080" UserId="6046" Text="I don't get what you don't understand. All rays originate from the camera so It's basically the start of the camera's pyramid or more technically the viewing frustum.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Depends on the system you are using. Maybe your camera is fixed at the origin and only the world rotates/moves. In this case, usually the camera is fixed at the origin looking in either the +Z or -Z direction depending on if it's left or right handed coordinates system. So the ray origins will be fixed at `(0,0,0)`.&#xD;&#xA;&#xD;&#xA;If your camera moves, however, the ray origins  also move to where you place the camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P3Qs3.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20754" PostHistoryTypeId="2" PostId="7900" RevisionGUID="1c1a1405-0d8d-4d70-9236-a4ad8b415572" CreationDate="2018-08-07T04:03:07.437" UserId="2687" Text="I recently learned about Delaunay triangulation algorithm.. This algorithm prevents the generation of skinny triangles.. I haven't really seen any good explanation of why we don't want skinny triangles.. Can anyone explain the reason?&#xD;&#xA;&#xD;&#xA;Thanks.." ContentLicense="CC BY-SA 4.0" />
  <row Id="20755" PostHistoryTypeId="1" PostId="7900" RevisionGUID="1c1a1405-0d8d-4d70-9236-a4ad8b415572" CreationDate="2018-08-07T04:03:07.437" UserId="2687" Text="Why does skinny triangle is avoided in triangulation algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20756" PostHistoryTypeId="3" PostId="7900" RevisionGUID="1c1a1405-0d8d-4d70-9236-a4ad8b415572" CreationDate="2018-08-07T04:03:07.437" UserId="2687" Text="|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20762" PostHistoryTypeId="4" PostId="5524" RevisionGUID="0e7b70e9-07d0-4599-8d78-1ce706fde485" CreationDate="2018-08-07T07:48:14.287" UserId="5406" Comment="shorten the title" Text="What is a common approach to smooth structures in textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20763" PostHistoryTypeId="2" PostId="7903" RevisionGUID="fcc4961e-a1f2-4a36-bc1d-e2e8eabfb849" CreationDate="2018-08-07T11:31:45.853" UserId="9141" Text="I was reading other questions in this topic but I couldn't apply any viable solution to solve my use case.&#xD;&#xA;&#xD;&#xA;I have a crop area described with two dimensions (cropWidth, cropHeight)&#xD;&#xA;I can easly compute center point of this area `C:[cx, cy]`.&#xD;&#xA;At the begining I have perfectly aligned image to the crop area.&#xD;&#xA;We can assume that image width and height are equal to cropWidth and cropHeight (figure below). &#xD;&#xA;We can also calculate `P1,P2,P3,P4` points which corresponds to rectangle (image) vertices.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;I can:&#xD;&#xA;&#xD;&#xA; - scale image (always from center C)&#xD;&#xA; - translate it&#xD;&#xA; - rotate around the C origin&#xD;&#xA;&#xD;&#xA;Let's say that I would like to do everything (translate, scale, rotate) and receive new image position `I1, I2, I3 ,I4`.&#xD;&#xA;I have access to object which describe all translations eg.:&#xD;&#xA;&#xD;&#xA;    const transform = {&#xD;&#xA;        scaleRatio: 1.25,&#xD;&#xA;        tx: 10,&#xD;&#xA;        ty: 20,&#xD;&#xA;        radians: 0.21&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What I'm trying to do is to follow transformation order:&#xD;&#xA;&#xD;&#xA; 1. Move origin&#xD;&#xA; 2. Scale&#xD;&#xA; 3. Rotate&#xD;&#xA; 4. Translate back origin&#xD;&#xA; 5. Translate tx, ty&#xD;&#xA;&#xD;&#xA;How it looks like:&#xD;&#xA;&#xD;&#xA;    const transformations = transform(&#xD;&#xA;        translate(-cx, -cy),&#xD;&#xA;        scale(scaleRatio),&#xD;&#xA;        rotate(radians),&#xD;&#xA;        transalte(cx, cy),&#xD;&#xA;        translate(-tx, -ty)   &#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;where `transform` function is simply matrix multiplication. &#xD;&#xA;&#xD;&#xA;After all transformations my image can look like below:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;No matter what I'm not able to receive correct values of all image vertices. Can someone point me to right approach? &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iTj1I.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IJ4lg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20764" PostHistoryTypeId="1" PostId="7903" RevisionGUID="fcc4961e-a1f2-4a36-bc1d-e2e8eabfb849" CreationDate="2018-08-07T11:31:45.853" UserId="9141" Text="How to apply scale, translate, rotate with different origin and get new rectangle coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="20765" PostHistoryTypeId="3" PostId="7903" RevisionGUID="fcc4961e-a1f2-4a36-bc1d-e2e8eabfb849" CreationDate="2018-08-07T11:31:45.853" UserId="9141" Text="|transformations|computational-geometry|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20767" PostHistoryTypeId="2" PostId="7904" RevisionGUID="56d77cf2-e71b-43a6-a230-76ef1b242f8a" CreationDate="2018-08-07T13:41:02.537" UserId="9143" Text="I'm getting started with graphics and I'm having trouble implementing the Bresenham's algorithm. Now, I know that my implementation is incomplente, but I can't see why it doesn't make horizontal lines(same height(y) values, different width(x values). I get a floating point exception. Here's the algo:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    int draw_line(void *mlx_ptr, void*win_ptr, t_2dpoint *initial_p, t_2dpoint *final_p)&#xD;&#xA;    {&#xD;&#xA;     53     int delta_x;&#xD;&#xA;    &#xD;&#xA;     53     int delta_x;&#xD;&#xA;     54     int y;&#xD;&#xA;     55     int delta_y;&#xD;&#xA;     56&#xD;&#xA;     57     delta_x = final_p-&gt;x - initial_p-&gt;x;&#xD;&#xA;     58     delta_y = final_p-&gt;y - initial_p-&gt;y;&#xD;&#xA;     59&#xD;&#xA;     60     x = initial_p-&gt;x;&#xD;&#xA;     61     y = initial_p-&gt;y;&#xD;&#xA;     62     e = (float)(delta_x / delta_y) - 1.0;&#xD;&#xA;     63&#xD;&#xA;     64     while(x &lt; final_p-&gt;x - 1)&#xD;&#xA;     65     {&#xD;&#xA;     66         mlx_pixel_put(mlx_ptr, win_ptr, x, y, 0XFF00FF);&#xD;&#xA;     67         if ( e &gt;= 0)&#xD;&#xA;     68         {&#xD;&#xA;     69             y += 1;&#xD;&#xA;     70             e -= 1.0;&#xD;&#xA;     71         }&#xD;&#xA;     72         x += 1;&#xD;&#xA;     73         e += (float)delta_x / delta_y;&#xD;&#xA;     74     }&#xD;&#xA;     75     mlx_pixel_put(mlx_ptr, win_ptr, x, y, 0XFF00FF);&#xD;&#xA;     76 }&#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20768" PostHistoryTypeId="1" PostId="7904" RevisionGUID="56d77cf2-e71b-43a6-a230-76ef1b242f8a" CreationDate="2018-08-07T13:41:02.537" UserId="9143" Text="Bresenham's Algorithm not drawing horizontal lines" ContentLicense="CC BY-SA 4.0" />
  <row Id="20769" PostHistoryTypeId="3" PostId="7904" RevisionGUID="56d77cf2-e71b-43a6-a230-76ef1b242f8a" CreationDate="2018-08-07T13:41:02.537" UserId="9143" Text="|vector-graphics|line-drawing|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20770" PostHistoryTypeId="2" PostId="7905" RevisionGUID="c0c54f10-fb14-4673-94b3-c1fee9a4e781" CreationDate="2018-08-07T14:11:50.857" UserId="2041" Text="    e = (float)(delta_x / delta_y) - 1.0;&#xD;&#xA;&#xD;&#xA;    e += (float)delta_x / delta_y;&#xD;&#xA;&#xD;&#xA;Either of these lines will cause a divide-by-zero error when `delta_y` is zero, which is when the line is horizontal (or zero-length). You need to check for this condition and have some special-case code.&#xD;&#xA;&#xD;&#xA;As an aside, I don't know why people still teach Bresenham's algorithm to new CG students. It's a good example of an algorithm but it's not very useful knowledge in itself: you're unlikely to need to know it unless it's for a job interview." ContentLicense="CC BY-SA 4.0" />
  <row Id="20771" PostHistoryTypeId="2" PostId="7906" RevisionGUID="c1b65285-96b2-43ad-ae3e-4ffa97850ffb" CreationDate="2018-08-07T14:28:27.837" UserId="5989" Text="We don't want to avoid skinny triangles as much as we want to avoid really long triangles.&#xD;&#xA;&#xD;&#xA;Long triangles make interpolation of properties less accurate because the points in which the data is stored are farther apart.&#xD;&#xA;&#xD;&#xA;However, the skinnier our triangles are, the longer they have to be in order to cover the same area, unless we use more triangles in total. The former is undesirable because of above mentioned reason. The latter is usually undesirable too since it increases the required memory consumption as well as the computational load on the algorithms that work with them since there are more triangles to loop through. We usually therefore want to avoid skinny triangles." ContentLicense="CC BY-SA 4.0" />
  <row Id="20772" PostHistoryTypeId="5" PostId="7906" RevisionGUID="ba447ddf-2dbf-413c-b927-2d3fe7850e84" CreationDate="2018-08-07T15:26:18.420" UserId="5989" Comment="added 753 characters in body" Text="We don't want to avoid skinny triangles as much as we want to avoid really long triangles.&#xD;&#xA;&#xD;&#xA;Long triangles make interpolation of properties less accurate because the points in which the data is stored are farther apart. This is equivalent to – when using a 2160p (4K UHD) screen – the preference of watching a 1080p video in fullscreen mode to watching the same video but in 720p, also in fullscreen mode. The 720p video is streched 3 times when the image is rescaled to fullscreen while the 1080p video is only streched 2 times; hence the pixels in the 720p video are streched farther apart compared with the pixels in the 1080p video and the interpolation of the colors in the pixels become less acurate (simply because the 720p video [can't contain](https://en.wikipedia.org/wiki/Nyquist_frequency) as fine details as the 1080p video can), which is another way of saying that the 1080p video looks better than the 720p video when viewed in fullscreen on a 2160p screen.&#xD;&#xA;&#xD;&#xA;However, the skinnier our triangles are, the longer they have to be in order to cover the same area, unless we use more triangles in total. The former is undesirable because of above mentioned reason. The latter is usually undesirable too since it increases the required memory consumption as well as the computational load on the algorithms that work with them since there are more triangles to loop through. We usually therefore want to avoid skinny triangles." ContentLicense="CC BY-SA 4.0" />
  <row Id="20776" PostHistoryTypeId="5" PostId="7890" RevisionGUID="b139737b-68a2-4f72-93e9-412dbf89ef79" CreationDate="2018-08-07T18:52:01.080" UserId="48" Comment="updated wrong numbers" Text="First we can calculate the physical diameter of CoC in the image plane, given the lens parameters. This equation is from [Wikipedia – Circle of confusion](https://en.wikipedia.org/wiki/Circle_of_confusion#Determining_a_circle_of_confusion_diameter_from_the_object_field):&#xD;&#xA;$$&#xD;&#xA;c = {|S_2 - S_1| \over S_2} {f^2 \over N(S_1 - f)}&#xD;&#xA;$$&#xD;&#xA;where the variables are:&#xD;&#xA;&#xD;&#xA;* $c$: the physical CoC diameter in the image plane&#xD;&#xA;* $S_1$: focal distance (the distance at which a subject would be in perfect focus)&#xD;&#xA;* $S_2$: actual distance to the subject (the point whose CoC we are calculating)&#xD;&#xA;* $f$: the focal length of the lens&#xD;&#xA;* $N$: the f-number at which the lens aperture is set.&#xD;&#xA;&#xD;&#xA;Then, divide this CoC diameter by the film or sensor frame size to get the blur diameter in texture coordinates. You can additionally multiply it by your rendering resolution to get the blur diameter in pixels if desired.&#xD;&#xA;&#xD;&#xA;As an example calculation, suppose we render a 1920×1080 image, as if through a 85mm lens at f/1.4, on a 35mm camera (frame size 36×24 mm), and focused at 3m while our subject is 5m away. Then we can calculate:&#xD;&#xA;$$&#xD;&#xA;{|5\text{m} - 3\text{m}| \over 5\text{m}} {(85\text{mm})^2 \over 1.4(3\text{m} - 85\text{mm})} {1920\text{px} \over 36\text{mm}}&#xD;&#xA;$$&#xD;&#xA;(Don't forget to convert units, since we are mixing meters and millimeters here!) I get a blur diameter of ~38 px, so the radius would therefore be ~19 px." ContentLicense="CC BY-SA 4.0" />
  <row Id="20777" PostHistoryTypeId="5" PostId="5666" RevisionGUID="846681de-378d-4f75-8d9a-067b9591d2bf" CreationDate="2018-08-08T08:35:00.123" UserId="6" Comment="deleted 1 character in body" Text="It basically **gives *you* control of the semantics of the individual attribute indices**. This mostly pays off in bigger projects, where you have many different shaders which, however, often use rather common attributes, like e.g. positions or texture coordinates. With explicit attribute locations you can establish a semantic for those attributes and enforce that on *all your shaders*, e.g. positions are always in attribute 0, texture coordinates always in attribute 1, ...&#xD;&#xA;&#xD;&#xA;First, this has the advantage of not having to query the attribute index for *every shader*. Of course you could query it once and sotre it in e.g. a map from attribute names/semantics to indices, but establishing this beforehand is even better. And it brings us to a much bigger advantage, without explicit attribute binding you **would have to bind vertex arrays of a model to the individual attribute channels not only for each model, but also *for each shader***, since your position array might go to attribute 0 in one shader and attribute 1 in another one.&#xD;&#xA;&#xD;&#xA;This is not only a huge hassle, but also basically **destroys the advantage of [Vertey Array Objects (VAO)](https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object)**, which are specfically there to capture all the vertex attribute state, including the enabled attribute indices and their buffer sources so that you can draw your object by just binding the VAO and calling a draw function. Without explicit attribute binding you would *still* have to reenable/bind the individual arrays at least for each different shader you use. **With explicit attribute binding you know that your model's positions *always* go into attribute index 0**." ContentLicense="CC BY-SA 4.0" />
  <row Id="20779" PostHistoryTypeId="50" PostId="7513" RevisionGUID="677ea340-e601-4864-b366-b72935ba9798" CreationDate="2018-08-08T14:00:47.520" UserId="-1" />
  <row Id="20782" PostHistoryTypeId="2" PostId="7908" RevisionGUID="8a03ed20-3831-42e8-880e-5b0220569b46" CreationDate="2018-08-09T07:44:12.513" UserId="9150" Text="I'm trying to grasp how NURBS curves work. I think I understand the principle, but I'm unsure about the formula. Here, I base myself on [this course](http://web.cs.wpi.edu/~matt/courses/cs563/talks/nurbs.html).&#xD;&#xA;&#xD;&#xA;From a DXF file, I got the following parameters:&#xD;&#xA;&#xD;&#xA;    knots (7): [0,0,0,0.5,1,1,1]&#xD;&#xA;    degree: 2&#xD;&#xA;    closed: false&#xD;&#xA;    control points (4): [(0,0), (-50,112.5), (150,112.5), (100,0)]&#xD;&#xA;&#xD;&#xA;The knots vector looks good : non-decreasing, length of `#controls + degree + 1`, max multiplicity of `degree+1`.&#xD;&#xA;&#xD;&#xA;Here are the formulas from the course:&#xD;&#xA;&#xD;&#xA;$C(u) = \frac{\sum_{i=0}^n{w_i P_i N_{i,k}(u)}}{\sum_{i=0}^n{w_i P_i}}$&#xD;&#xA;&#xD;&#xA;- $w_i$ : weights&#xD;&#xA;- $P_i$ : control points (vector)&#xD;&#xA;- $N_{i,k}$ : normalized B-spline basis functions of degree k&#xD;&#xA;&#xD;&#xA;and the recursive B-spline basis function:&#xD;&#xA;&#xD;&#xA;$N_{i,k}(u) = \frac{u-t_i}{t_{i+k} - t_i} N_{i,k-1}(u) + \frac{t_{i+k+1}-u}{t_{i+k+1}-t_{i+1}} N_{i+1,k-1}(u)$&#xD;&#xA;&#xD;&#xA;$N_{i,0}(u) = 1$ if $t_i \leq u &lt; t_{i+1}$ or $0$ otherwise.&#xD;&#xA;&#xD;&#xA;**What I don't get is the fraction in the $N_{i,k}(u)$ function.**&#xD;&#xA;&#xD;&#xA;Let's take $i=0$ (calculating the influence of the first control point over the curve, if I understand correctly): because of the multiplicity, I've got $t_{i+k} = t_2 = 0$ and $t_i = t_0 = 0$, which makes me divide by zero ... What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20783" PostHistoryTypeId="1" PostId="7908" RevisionGUID="8a03ed20-3831-42e8-880e-5b0220569b46" CreationDate="2018-08-09T07:44:12.513" UserId="9150" Text="drawing NURBS: knots, multiplicity, divide by zero?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20784" PostHistoryTypeId="3" PostId="7908" RevisionGUID="8a03ed20-3831-42e8-880e-5b0220569b46" CreationDate="2018-08-09T07:44:12.513" UserId="9150" Text="|nurbs|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20785" PostHistoryTypeId="5" PostId="7908" RevisionGUID="dfe2e75a-cfea-4724-b25e-d297c0b707aa" CreationDate="2018-08-09T08:32:48.533" UserId="9150" Comment="[Edit removed during grace period]" Text="I'm trying to grasp how NURBS curves work. I think I understand the principle, but I'm unsure about the formula. Here, I base myself on [this course](http://web.cs.wpi.edu/~matt/courses/cs563/talks/nurbs.html).&#xD;&#xA;&#xD;&#xA;From a DXF file, I got the following parameters:&#xD;&#xA;&#xD;&#xA;    knots (7): [0,0,0,0.5,1,1,1]&#xD;&#xA;    degree: 2&#xD;&#xA;    closed: false&#xD;&#xA;    control points (4): [(0,0), (-50,112.5), (150,112.5), (100,0)]&#xD;&#xA;&#xD;&#xA;The knots vector looks good : non-decreasing, length of `#controls + degree + 1`, max multiplicity of `degree+1`.&#xD;&#xA;&#xD;&#xA;Here are the formulas from the course:&#xD;&#xA;&#xD;&#xA;$C(u) = \frac{\sum_{i=0}^n{w_i P_i N_{i,k}(u)}}{\sum_{i=0}^n{w_i P_i}}$&#xD;&#xA;&#xD;&#xA;- $w_i$ : weights&#xD;&#xA;- $P_i$ : control points (vector)&#xD;&#xA;- $N_{i,k}$ : normalized B-spline basis functions of degree k&#xD;&#xA;&#xD;&#xA;and the recursive B-spline basis function:&#xD;&#xA;&#xD;&#xA;$N_{i,k}(u) = \frac{u-t_i}{t_{i+k} - t_i} N_{i,k-1}(u) + \frac{t_{i+k+1}-u}{t_{i+k+1}-t_{i+1}} N_{i+1,k-1}(u)$&#xD;&#xA;&#xD;&#xA;$N_{i,0}(u) = 1$ if $t_i \leq u &lt; t_{i+1}$ or $0$ otherwise.&#xD;&#xA;&#xD;&#xA;**What I don't get is the fraction in the $N_{i,k}(u)$ function.**&#xD;&#xA;&#xD;&#xA;Let's take $i=0$ (calculating the influence of the first control point over the curve, if I understand correctly): because of the multiplicity, I've got $t_{i+k} = t_2 = 0$ and $t_i = t_0 = 0$, which makes me divide by zero ... What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20790" PostHistoryTypeId="5" PostId="6293" RevisionGUID="2668844f-00f0-4666-bd63-70556e38821b" CreationDate="2018-08-09T15:44:47.723" UserId="6046" Comment="Was wrong about camera space +Z axis maps to world space -Z axis. See edit for more details." Text="It was getting a little big to fit in the comments so posting it as an answer instead. Might not be a solution to your problem but the concept is related.&#xD;&#xA;&#xD;&#xA;People usually forget that whenever you define a transformation matrix by placing respective basis vectors in respective columns, you are specifying that with respect to another basis usually the right-handed or left handed world coordinate space. For example your above matrix&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;r_x &amp; u_x &amp; -l_x &amp; 0 \\&#xD;&#xA;r_y &amp; u_y &amp; -l_y &amp; 0 \\&#xD;&#xA;r_z &amp; u_z &amp; -l_z &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Reason why you put `-` sign in the third column is you are working with a right handed coordinate system and the camera is looking in the negative direction (the -Z axis). So all these basis vectors are also with respect to another basis vector. **This means your camera's Z axis is actually the negative of the viewing direction.** &#xD;&#xA;&#xD;&#xA;Let's make this matrix simple so we can understand what happens when we multiply a matrix with a vector. Let the matrix $M$ be &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;**The above matrix is wrong. The correct one is,**&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;This is your camera initially without any rotation/translation etc. &lt;strike&gt;This means your camera space $+Z$ axis maps to world space $-Z$ axis. Now consider a camera space coordinate $[2,3,6,0]^T$. Multiplying this vector by the matrix gives you $[2,3,-6,0]^T$. This is the world space representation of $[2,3,6,0]^T$.&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**Actually after clearing my concepts a little more, Both the camera space and the world space are aligned for Right handed coordinate systems. This means the `X,Y,Z` axis of world space align with `X,Y,Z` of the camera space.**&#xD;&#xA;&#xD;&#xA;The 3rd column of the matrix actually points to $-V_{dir}$ which basically says &quot;The Z-axis of the camera space is negative of the viewing direction&quot;. Since &#xD;&#xA; &#xD;&#xA;$V_{dir} = [0,0,-1]$&#xD;&#xA;&#xD;&#xA;**The negative of it is simply the positive $Z$ axis. This means, points/vectors in world space remains the same as in camera space (when camera is at initial position)**&#xD;&#xA;&#xD;&#xA;So as Nathan pointed your matrix transforms from camera space to world space. To do the inverse we just take the inverse of the matrix which is the transpose if the basis is ortho-normal.&#xD;&#xA;&#xD;&#xA;One of the reasons the transformation matrix is built this way is because it's much easier. It's easier to think about the transformed basis vectors of camera or any other space with respect to the world, write the matrix then invert it to go from the world space to that target space." ContentLicense="CC BY-SA 4.0" />
  <row Id="20795" PostHistoryTypeId="5" PostId="7908" RevisionGUID="be636e55-c3c3-4312-86fe-6eb04cac8087" CreationDate="2018-08-10T14:01:33.910" UserId="9150" Comment="added 287 characters in body" Text="I'm trying to grasp how NURBS curves work. I think I understand the principle, but I'm unsure about the formula. Here, I base myself on [this course](http://web.cs.wpi.edu/~matt/courses/cs563/talks/nurbs.html).&#xD;&#xA;&#xD;&#xA;From a DXF file, I got the following parameters:&#xD;&#xA;&#xD;&#xA;    knots (7): [0,0,0,0.5,1,1,1]&#xD;&#xA;    degree: 2&#xD;&#xA;    closed: false&#xD;&#xA;    control points (4): [(0,0), (-50,112.5), (150,112.5), (100,0)]&#xD;&#xA;&#xD;&#xA;The knots vector looks good : non-decreasing, length of `#controls + degree + 1`, max multiplicity of `degree+1`.&#xD;&#xA;&#xD;&#xA;Here are the formulas from the course:&#xD;&#xA;&#xD;&#xA;$C(u) = \frac{\sum_{i=0}^n{w_i P_i N_{i,k}(u)}}{\sum_{i=0}^n{w_i P_i}}$&#xD;&#xA;&#xD;&#xA;- $w_i$ : weights&#xD;&#xA;- $P_i$ : control points (vector)&#xD;&#xA;- $N_{i,k}$ : normalized B-spline basis functions of degree k&#xD;&#xA;&#xD;&#xA;and the recursive B-spline basis function:&#xD;&#xA;&#xD;&#xA;$N_{i,k}(u) = \frac{u-t_i}{t_{i+k} - t_i} N_{i,k-1}(u) + \frac{t_{i+k+1}-u}{t_{i+k+1}-t_{i+1}} N_{i+1,k-1}(u)$&#xD;&#xA;&#xD;&#xA;$N_{i,0}(u) = 1$ if $t_i \leq u &lt; t_{i+1}$ or $0$ otherwise.&#xD;&#xA;&#xD;&#xA;**What I don't get is the fraction in the $N_{i,k}(u)$ function.**&#xD;&#xA;&#xD;&#xA;Let's take $i=0$ (calculating the influence of the first control point over the curve, if I understand correctly): because of the multiplicity, I've got $t_{i+k} = t_2 = 0$ and $t_i = t_0 = 0$, which makes me divide by zero ... What am I missing?&#xD;&#xA;&#xD;&#xA;EDIT: As usual, writing down the problem helps to solve it. By re-reading the material linked above, I realized I missed one line: 0/0 fractions should be considered as 0, not NaN. Is this right ? At least on the few toy examples I tried, my drawing matches the original DXF version." ContentLicense="CC BY-SA 4.0" />
  <row Id="20796" PostHistoryTypeId="50" PostId="7794" RevisionGUID="fe952fbd-3247-4ec0-8562-53605fdbc3ea" CreationDate="2018-08-10T16:01:41.330" UserId="-1" />
  <row Id="20800" PostHistoryTypeId="50" PostId="4632" RevisionGUID="10be9690-2c43-45ab-a96f-4de9d56dd2a4" CreationDate="2018-08-11T01:01:16.957" UserId="-1" />
  <row Id="20809" PostHistoryTypeId="50" PostId="7804" RevisionGUID="7c4e1116-d66d-4aca-9a6e-94a2cf9761cb" CreationDate="2018-08-12T12:02:32.713" UserId="-1" />
  <row Id="20810" PostHistoryTypeId="2" PostId="7915" RevisionGUID="be005362-fdd7-40ae-b20c-c9686e2bef2a" CreationDate="2018-08-12T13:54:42.317" UserId="9170" Text="I am using the book *Ray Tracing from the Ground Up* by Kevin Suffern to build my first ray tracers in Java. Based on the theory, I expected that direct illumination and simple path tracers render the same scene equally bright (that is, when the resulting images are more of less converged and the path tracer only allows paths of maximal length 2). However, my implementation for a simple path tracer renders much darker images. Here is a simple example:&#xD;&#xA;&#xD;&#xA;[![Direct illumination][1]][1]&#xD;&#xA;[![Path tracer][2]][2]&#xD;&#xA;&#xD;&#xA;The images on the left and right are respectively the result of direct illumination and path tracing with 225 rays per pixel. After manually changing the sensitivity, the path traced image becomes this:&#xD;&#xA;&#xD;&#xA;[![Lighter version of path tracer][4]][4]&#xD;&#xA;&#xD;&#xA;Of course, the brightened image is not near convergence, but it should at least be clear that the path tracer actually renders the same scene similarly (up to some differentiating things like the abscence of ambient light, which is used for global illumination).&#xD;&#xA;&#xD;&#xA;Is this normal behaviour? If so, could I just pick a larger power for the light source when using a path tracer? If not, I can elaborate my question with some code for my path tracer.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yq766.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/HYiPq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/QTcUP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20811" PostHistoryTypeId="1" PostId="7915" RevisionGUID="be005362-fdd7-40ae-b20c-c9686e2bef2a" CreationDate="2018-08-12T13:54:42.317" UserId="9170" Text="Should direct illumination and path tracers render the same scene equally bright?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20812" PostHistoryTypeId="3" PostId="7915" RevisionGUID="be005362-fdd7-40ae-b20c-c9686e2bef2a" CreationDate="2018-08-12T13:54:42.317" UserId="9170" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20813" PostHistoryTypeId="50" PostId="7428" RevisionGUID="a5ac6cf9-c265-4808-97c4-9e502d5737ad" CreationDate="2018-08-12T17:01:03.603" UserId="-1" />
  <row Id="20814" PostHistoryTypeId="50" PostId="7538" RevisionGUID="4bdf2851-f71a-4df5-89c1-74394ad99a70" CreationDate="2018-08-12T18:02:29.933" UserId="-1" />
  <row Id="20815" PostHistoryTypeId="50" PostId="6180" RevisionGUID="ac708d61-343a-4d82-a2ba-bb8d67cc148e" CreationDate="2018-08-12T22:00:47.743" UserId="-1" />
  <row Id="20816" PostHistoryTypeId="2" PostId="7916" RevisionGUID="9e64acf4-63ad-4ab3-8f95-a4e03625f6ce" CreationDate="2018-08-13T08:34:53.737" UserId="9176" Text="My phone is Sony Xperia XZ1 Compact which has Adreno 540 as gpu. My laptop's gpu is NVIDIA GeForce 940MX 4GB which seems to be much worse than my phone's gpu. My PC's OS is Ubuntu 16.04." ContentLicense="CC BY-SA 4.0" />
  <row Id="20817" PostHistoryTypeId="1" PostId="7916" RevisionGUID="9e64acf4-63ad-4ab3-8f95-a4e03625f6ce" CreationDate="2018-08-13T08:34:53.737" UserId="9176" Text="Can I use my phone's gpu as an external gpu for my laptop?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20818" PostHistoryTypeId="3" PostId="7916" RevisionGUID="9e64acf4-63ad-4ab3-8f95-a4e03625f6ce" CreationDate="2018-08-13T08:34:53.737" UserId="9176" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20819" PostHistoryTypeId="2" PostId="7917" RevisionGUID="0d69ff59-3199-4ef8-b6ba-cb932e05594f" CreationDate="2018-08-13T19:27:50.117" UserId="9180" Text="I'm having problems when using the following statement on different GPUs:&#xD;&#xA;&#xD;&#xA;	glTexSubImage3D(target, 0, 0, 0, 0, width, height, layers, format, type, NULL);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;on NVIDIA cards &quot;format = GL_RGB&quot; throws a fatal error that causes the program to crash, but it works and throws no errors if I use the sized version &quot;format = GL_RGB8&quot;&#xD;&#xA;&#xD;&#xA;on AMD cards &quot;format = GL_RGB&quot; works and throws no errors, &quot;format = GL_RGB8&quot; also works, but throws the error &quot;GL_INVALID_ENUMERATION&quot;&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;I'm currently using GL_RGB8, so it works on both cards, but I wonder if there is a way to do this that throws no errors on either card.&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;Here's the spec for glTexSubImage3D from Khronos.org&#xD;&#xA;&#xD;&#xA;&gt; format&#xD;&#xA;&gt; &#xD;&#xA;&gt; Specifies the format of the pixel data. The following symbolic values are accepted: GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_DEPTH_COMPONENT, and GL_STENCIL_INDEX.&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;I'm using opengl 4.3 core profile, glfw and glew. Here is my texStorage statement called before glTexSubImage3D&#xD;&#xA;&#xD;&#xA;	internalFormat = GL_RGB8;&#xD;&#xA;	glTexStorage3D(target, 1, internalFormat, width, height, layers);&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;Am I using this incorrectly? Is there a way to satisfy both implementations?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20820" PostHistoryTypeId="1" PostId="7917" RevisionGUID="0d69ff59-3199-4ef8-b6ba-cb932e05594f" CreationDate="2018-08-13T19:27:50.117" UserId="9180" Text="glTexSubImage3D throws GL_INVALID_ENUMERATION on NVIDIA" ContentLicense="CC BY-SA 4.0" />
  <row Id="20821" PostHistoryTypeId="3" PostId="7917" RevisionGUID="0d69ff59-3199-4ef8-b6ba-cb932e05594f" CreationDate="2018-08-13T19:27:50.117" UserId="9180" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20822" PostHistoryTypeId="2" PostId="7918" RevisionGUID="38411ac8-b1f7-454c-8891-4a748d1ed288" CreationDate="2018-08-13T21:19:08.323" UserId="2041" Text="No. Your phone's GPU is in one chip with the CPU, some of the memory, and its display controller, and they're all tightly integrated together. Also, there'd be no way to connect it efficiently to the laptop. Only the latest generation of USB and Thunderbolt have enough bandwidth to be even worth considering for external GPUs, and even then, they're only used with dedicated hardware at the GPU end of the link - not a general-purpose processor. Apart from the fundamental problems, there's the very practical issue that your PC doesn't have any drivers for the GPU on the phone.&#xD;&#xA;&#xD;&#xA;I know mobile GPUs are pretty effective, but if your phone's GPU seems faster than the Nvidia chip in your laptop, there's something wrong with your laptop. If you can give more information on the problem to the people at [Ask Ubuntu](//askubuntu.com/), they can probably help with that." ContentLicense="CC BY-SA 4.0" />
  <row Id="20823" PostHistoryTypeId="5" PostId="7917" RevisionGUID="49ff6bc7-73b1-43c6-863c-f115672bd9bc" CreationDate="2018-08-13T21:38:00.743" UserId="9180" Comment="added 171 characters in body" Text="I'm having problems when using the following statement on different GPUs:&#xD;&#xA;&#xD;&#xA;	glTexSubImage3D(target, 0, 0, 0, 0, width, height, layers, format, type, NULL);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;on NVIDIA cards &quot;format = GL_RGBA&quot; throws a fatal error that causes the program to crash, but it works and throws no errors if I use the sized version &quot;format = GL_RGBA8&quot;&#xD;&#xA;&#xD;&#xA;on AMD cards &quot;format = GL_RGBA&quot; works and throws no errors, &quot;format = GL_RGBA8&quot; also works, but throws the error &quot;GL_INVALID_ENUMERATION&quot;&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;I'm currently using GL_RGBA8, so it works on both cards, but I wonder if there is a way to do this that throws no errors on either card.&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;Here's the spec for glTexSubImage3D from Khronos.org&#xD;&#xA;&#xD;&#xA;&gt; format&#xD;&#xA;&gt; &#xD;&#xA;&gt; Specifies the format of the pixel data. The following symbolic values are accepted: GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_DEPTH_COMPONENT, and GL_STENCIL_INDEX.&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;I'm using opengl 4.3 core profile, glfw and glew. Here is my texStorage statement called before glTexSubImage3D&#xD;&#xA;&#xD;&#xA;	internalFormat = GL_RGBA8;&#xD;&#xA;	glTexStorage3D(target, 1, internalFormat, width, height, layers);&#xD;&#xA;&#xD;&#xA;per the comments, the other values are&#xD;&#xA;&#xD;&#xA;	target = GL_TEXTURE_2D;&#xD;&#xA;	width = 4096;&#xD;&#xA;	height = 4096;&#xD;&#xA;	layers = 1;&#xD;&#xA;	format = GL_RGBA8;&#xD;&#xA;	type = GL_UNSIGNED_BYTE;&#xD;&#xA;&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;Am I using this incorrectly? Is there a way to satisfy both implementations?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20824" PostHistoryTypeId="5" PostId="7915" RevisionGUID="ebd4baa1-f58c-407b-88a8-c93adfca8dc4" CreationDate="2018-08-13T22:07:14.317" UserId="9170" Comment="added 1967 characters in body" Text="I am using the book *Ray Tracing from the Ground Up* by Kevin Suffern to build my first ray tracers in Java. Based on the theory, I expected that direct illumination and simple path tracers render the same scene equally bright (that is, when the resulting images are more of less converged and the path tracer only allows paths of maximal length 2). However, my implementation for a simple path tracer renders much darker images. Here is an example:&#xD;&#xA;&#xD;&#xA;[![Direct illumination][1]][1]&#xD;&#xA;[![Path tracer][2]][2]&#xD;&#xA;&#xD;&#xA;The images on the left and right are respectively the result of direct illumination and path tracing with 225 rays per pixel. My path tracer does not use next event estimation; it returns black whenever the path becomes longer than a certain length without reaching the area light. For every pixel, the received radiances are averaged afterwards.&#xD;&#xA;&#xD;&#xA;When I manually change the sensitivity, though, the path traced image becomes this:&#xD;&#xA;&#xD;&#xA;[![Lighter version of path tracer][4]][4]&#xD;&#xA;&#xD;&#xA;Of course, the brightened image is not near convergence, but it should at least be clear that the path tracer actually renders the same scene similarly (up to some differentiating things like the abscence of ambient light, which is used for global illumination).&#xD;&#xA;&#xD;&#xA;Is this normal behaviour? If so, could I just pick a larger power for the light source when using a path tracer? If not, please find some relevant code of my path tracer underneath.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;This is my code for shading an intersection point of a ray and a matte object. It is supposed to shoot an arbitrary ray from the intersection point along a cosine distribution (I have used a branch factor 1 for my images).&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		int factor = tracer.getBranchFactor();&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(factor);&#xD;&#xA;		List&lt;Point&gt; samples = sampler.computeSamples();&#xD;&#xA;		RGBSpectrum L = RGBSpectrum.BLACK;&#xD;&#xA;&#xD;&#xA;		for (Point sample : samples) {&#xD;&#xA;			Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;			Random PRNG = new Random();&#xD;&#xA;			Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble());&#xD;&#xA;			Vector v = r.cross(w).normalize();&#xD;&#xA;			Vector u = v.cross(w);&#xD;&#xA;			Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z)).normalize();&#xD;&#xA;			Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;			L = L.add(tracer.trace(ray, length + 1));&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		L = L.scale(1.0 / factor);&#xD;&#xA;		return shading.getColour().scale(getDiffuseReflection()).multiply(L);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Here is how the cosine distributed samples are computed:&#xD;&#xA;&#xD;&#xA;    public List&lt;Point&gt; computeSamples() {&#xD;&#xA;		List&lt;Point&gt; samples = new ArrayList&lt;&gt;();&#xD;&#xA;		for (int i = 0; i &lt; getSamples(); i++) {&#xD;&#xA;			double phi = 2 * Math.PI * Math.random();&#xD;&#xA;			double cosPhi = Math.cos(phi);&#xD;&#xA;			double sinPhi = Math.sin(phi);&#xD;&#xA;			double cosTheta = Math.sqrt(1 - Math.random());&#xD;&#xA;			double sinTheta = Math.sqrt(1 - cosTheta * cosTheta);&#xD;&#xA;			double pu = sinTheta * cosPhi;&#xD;&#xA;			double pv = sinTheta * sinPhi;&#xD;&#xA;			double pw = cosTheta;&#xD;&#xA;			Point sample = new Point(pu, pv, pw);&#xD;&#xA;			samples.add(sample);&#xD;&#xA;		}&#xD;&#xA;		return samples;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yq766.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/HYiPq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/QTcUP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20825" PostHistoryTypeId="2" PostId="7919" RevisionGUID="92e47afb-4622-4541-8b5b-4bb99460c3df" CreationDate="2018-08-14T06:56:52.010" UserId="6046" Text="So I want to path trace a Cornel Box scene, but I don't understand the values given here in section 2 and 3.&#xD;&#xA;&#xD;&#xA;http://www.graphics.cornell.edu/online/box/data.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;No.2 Lists surface reflectances with respect to different wavelengths but I'm not using wavelengths. I thought this was done in spectral path/ray tracing where we are using photometry instead of radiometry.&#xD;&#xA;&#xD;&#xA;Similarly No.3 lists Light properties though I don't understand what do the values in the `light` column (0, 8, 15.6, 18.4) suggest.&#xD;&#xA;&#xD;&#xA;I was merely expecting the specular and diffuse reflectivity in all 3 channels for each of the colors red, green and white.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20826" PostHistoryTypeId="1" PostId="7919" RevisionGUID="92e47afb-4622-4541-8b5b-4bb99460c3df" CreationDate="2018-08-14T06:56:52.010" UserId="6046" Text="Interpreting Cornell Box data for path tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="20827" PostHistoryTypeId="3" PostId="7919" RevisionGUID="92e47afb-4622-4541-8b5b-4bb99460c3df" CreationDate="2018-08-14T06:56:52.010" UserId="6046" Text="|pathtracing|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20828" PostHistoryTypeId="5" PostId="7915" RevisionGUID="1eb2824e-61a0-4f6d-bb1b-d841956f1693" CreationDate="2018-08-14T12:50:26.090" UserId="9170" Comment="deleted 41 characters in body" Text="I am using the book *Ray Tracing from the Ground Up* by Kevin Suffern to build my first ray tracers in Java. Based on the theory, I expected that direct illumination and simple path tracers render the same scene equally bright (that is, when the resulting images are more of less converged and the path tracer only allows paths of maximal length 2). However, my implementation for a simple path tracer renders much darker images. Here is an example:&#xD;&#xA;&#xD;&#xA;[![Direct illumination][2]][2]&#xD;&#xA;[![Path tracer][3]][3]&#xD;&#xA;&#xD;&#xA;The images on the left and right are respectively the result of direct illumination and path tracing with 225 rays per pixel. My path tracer does not use next event estimation; it returns black whenever the path becomes longer than a certain length without reaching the area light. For every pixel, the received radiances are averaged afterwards.&#xD;&#xA;&#xD;&#xA;When I manually change the sensitivity, though (i.e. a simple post rendering scaling of the colours in the image), the path traced image becomes this:&#xD;&#xA;&#xD;&#xA;[![Lighter version of path tracer][4]][4]&#xD;&#xA;&#xD;&#xA;Of course, the brightened image is not near convergence, but it should at least be clear that the path tracer actually renders the same scene similarly.&#xD;&#xA;&#xD;&#xA;Is this normal behaviour? If so, could I just pick a larger power for the light source when using a path tracer? If not, please find some relevant code of my path tracer underneath.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;This is my code for shading an intersection point of a ray and a matte object. It is supposed to shoot an arbitrary ray from the intersection point along a cosine distribution (I have used a branch factor 1 for my images).&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		int factor = tracer.getBranchFactor();&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(factor);&#xD;&#xA;		List&lt;Point&gt; samples = sampler.computeSamples();&#xD;&#xA;		RGBSpectrum L = RGBSpectrum.BLACK;&#xD;&#xA;&#xD;&#xA;		for (Point sample : samples) {&#xD;&#xA;			Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;			Random PRNG = new Random();&#xD;&#xA;			Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble());&#xD;&#xA;			Vector v = r.cross(w).normalize();&#xD;&#xA;			Vector u = v.cross(w);&#xD;&#xA;			Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z)).normalize();&#xD;&#xA;			Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;			L = L.add(tracer.trace(ray, length + 1));&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		L = L.scale(1.0 / factor);&#xD;&#xA;		return shading.getColour().scale(getDiffuseReflection()).multiply(L);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Here is how the cosine distributed samples are computed:&#xD;&#xA;&#xD;&#xA;    public List&lt;Point&gt; computeSamples() {&#xD;&#xA;		List&lt;Point&gt; samples = new ArrayList&lt;&gt;();&#xD;&#xA;		for (int i = 0; i &lt; getSamples(); i++) {&#xD;&#xA;			double phi = 2 * Math.PI * Math.random();&#xD;&#xA;			double cosPhi = Math.cos(phi);&#xD;&#xA;			double sinPhi = Math.sin(phi);&#xD;&#xA;			double cosTheta = Math.sqrt(1 - Math.random());&#xD;&#xA;			double sinTheta = Math.sqrt(1 - cosTheta * cosTheta);&#xD;&#xA;			double pu = sinTheta * cosPhi;&#xD;&#xA;			double pv = sinTheta * sinPhi;&#xD;&#xA;			double pw = cosTheta;&#xD;&#xA;			Point sample = new Point(pu, pv, pw);&#xD;&#xA;			samples.add(sample);&#xD;&#xA;		}&#xD;&#xA;		return samples;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/RHsO4.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HYiPq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/QTcUP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20829" PostHistoryTypeId="5" PostId="7915" RevisionGUID="0c1ffd74-183a-4f28-b0b0-871fc210ee14" CreationDate="2018-08-14T12:57:09.480" UserId="9170" Comment="added 478 characters in body" Text="I am using the book *Ray Tracing from the Ground Up* by Kevin Suffern to build my first ray tracers in Java. Based on the theory, I expected that direct illumination and simple path tracers render the same scene equally bright (that is, when the resulting images are more of less converged and the path tracer only allows paths of maximal length 2). However, my implementation for a simple path tracer renders much darker images. Here is an example:&#xD;&#xA;&#xD;&#xA;[![Direct illumination][2]][2]&#xD;&#xA;[![Path tracer][3]][3]&#xD;&#xA;&#xD;&#xA;The images on the left and right are respectively the result of direct illumination and path tracing with 225 rays per pixel. My path tracer does not use next event estimation; it returns black whenever the path becomes longer than a certain length without reaching the area light. For every pixel, the received radiances are averaged afterwards.&#xD;&#xA;&#xD;&#xA;When I manually change the sensitivity, though (i.e. a simple post rendering scaling of the colours in the image), the path traced image becomes this:&#xD;&#xA;&#xD;&#xA;[![Lighter version of path tracer][4]][4]&#xD;&#xA;&#xD;&#xA;Of course, the brightened image is not near convergence, but it should at least be clear that the path tracer actually renders the same scene similarly.&#xD;&#xA;&#xD;&#xA;Is this normal behaviour? If so, could I just pick a larger power for the light source when using a path tracer? If not, please find some relevant code of my path tracer underneath.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;This is my code for shading an intersection point of a ray and a matte object. It is supposed to shoot an arbitrary ray from the intersection point along a cosine distribution (I have used a branch factor 1 for my images).&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		int factor = tracer.getBranchFactor();&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(factor);&#xD;&#xA;		List&lt;Point&gt; samples = sampler.computeSamples();&#xD;&#xA;		RGBSpectrum L = RGBSpectrum.BLACK;&#xD;&#xA;&#xD;&#xA;		for (Point sample : samples) {&#xD;&#xA;			Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;			Random PRNG = new Random();&#xD;&#xA;			Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble());&#xD;&#xA;			Vector v = r.cross(w).normalize();&#xD;&#xA;			Vector u = v.cross(w);&#xD;&#xA;			Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z)).normalize();&#xD;&#xA;			Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;			L = L.add(tracer.trace(ray, length + 1));&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		L = L.scale(1.0 / factor);&#xD;&#xA;		return shading.getColour().scale(getDiffuseReflection()).multiply(L);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Here is how the cosine distributed samples are computed:&#xD;&#xA;&#xD;&#xA;    public List&lt;Point&gt; computeSamples() {&#xD;&#xA;		List&lt;Point&gt; samples = new ArrayList&lt;&gt;();&#xD;&#xA;		for (int i = 0; i &lt; getSamples(); i++) {&#xD;&#xA;			double phi = 2 * Math.PI * Math.random();&#xD;&#xA;			double cosPhi = Math.cos(phi);&#xD;&#xA;			double sinPhi = Math.sin(phi);&#xD;&#xA;			double cosTheta = Math.sqrt(1 - Math.random());&#xD;&#xA;			double sinTheta = Math.sqrt(1 - cosTheta * cosTheta);&#xD;&#xA;			double pu = sinTheta * cosPhi;&#xD;&#xA;			double pv = sinTheta * sinPhi;&#xD;&#xA;			double pw = cosTheta;&#xD;&#xA;			Point sample = new Point(pu, pv, pw);&#xD;&#xA;			samples.add(sample);&#xD;&#xA;		}&#xD;&#xA;		return samples;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This is the shading for emissive materials. `showPath` returns `true` by default.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		Ray ray = shading.getRay();&#xD;&#xA;		Vector n = shading.getIntersectionPoint().getNormal();&#xD;&#xA;&#xD;&#xA;		boolean showPath = tracer.getShowOnlyLength() == 0 || length == tracer.getShowOnlyLength();&#xD;&#xA;		if (n.dot(ray.direction) &lt; 0 &amp;&amp; showPath) {&#xD;&#xA;			return getTexture().getColour().scale(getPower());&#xD;&#xA;		} else {&#xD;&#xA;			return RGBSpectrum.BLACK;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/RHsO4.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HYiPq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/QTcUP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20834" PostHistoryTypeId="50" PostId="7628" RevisionGUID="8a65a9ec-e47b-4ce0-a815-c9ec3e52cf60" CreationDate="2018-08-14T23:01:52.157" UserId="-1" />
  <row Id="20837" PostHistoryTypeId="5" PostId="7915" RevisionGUID="6cab6cfe-d54b-40a2-958d-1534678e16c0" CreationDate="2018-08-15T12:58:24.920" UserId="9170" Comment="added 1490 characters in body" Text="I am using the book *Ray Tracing from the Ground Up* by Kevin Suffern to build my first ray tracers in Java. Based on the theory, I expected that direct illumination and simple path tracers render the same scene equally bright (that is, when the resulting images are more of less converged and the path tracer only allows paths of maximal length 2). However, my implementation for a simple path tracer renders much darker images. Here is an example:&#xD;&#xA;&#xD;&#xA;[![Direct illumination][2]][2]&#xD;&#xA;[![Path tracer][3]][3]&#xD;&#xA;&#xD;&#xA;The images on the left and right are respectively the result of direct illumination and path tracing with 225 rays per pixel. My path tracer does not use next event estimation; it returns black whenever the path becomes longer than a certain length without reaching the area light. For every pixel, the received radiances are averaged afterwards.&#xD;&#xA;&#xD;&#xA;When I manually change the sensitivity, though (i.e. a simple post rendering scaling of the colours in the image), the path traced image becomes this:&#xD;&#xA;&#xD;&#xA;[![Lighter version of path tracer][4]][4]&#xD;&#xA;&#xD;&#xA;Of course, the brightened image is not near convergence, but it should at least be clear that the path tracer actually renders the same scene similarly.&#xD;&#xA;&#xD;&#xA;Is this normal behaviour? If so, could I just pick a larger power for the light source when using a path tracer? If not, please find some relevant code of my path tracer underneath.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;This is my code for shading an intersection point of a ray and a matte object. It is supposed to shoot an arbitrary ray from the intersection point along a cosine distribution (I have used a branch factor 1 for my images).&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		int factor = tracer.getBranchFactor();&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(factor);&#xD;&#xA;		List&lt;Point&gt; samples = sampler.computeSamples();&#xD;&#xA;		RGBSpectrum L = RGBSpectrum.BLACK;&#xD;&#xA;&#xD;&#xA;		for (Point sample : samples) {&#xD;&#xA;			Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;			Random PRNG = new Random();&#xD;&#xA;			Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble());&#xD;&#xA;			Vector v = r.cross(w).normalize();&#xD;&#xA;			Vector u = v.cross(w);&#xD;&#xA;			Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z)).normalize();&#xD;&#xA;			Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;			L = L.add(tracer.trace(ray, length + 1));&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		L = L.scale(1.0 / factor);&#xD;&#xA;		return shading.getColour().scale(getDiffuseReflection()).multiply(L);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Here is how the cosine distributed samples are computed:&#xD;&#xA;&#xD;&#xA;    public List&lt;Point&gt; computeSamples() {&#xD;&#xA;		List&lt;Point&gt; samples = new ArrayList&lt;&gt;();&#xD;&#xA;		for (int i = 0; i &lt; getSamples(); i++) {&#xD;&#xA;			double phi = 2 * Math.PI * Math.random();&#xD;&#xA;			double cosPhi = Math.cos(phi);&#xD;&#xA;			double sinPhi = Math.sin(phi);&#xD;&#xA;			double cosTheta = Math.sqrt(1 - Math.random());&#xD;&#xA;			double sinTheta = Math.sqrt(1 - cosTheta * cosTheta);&#xD;&#xA;			double pu = sinTheta * cosPhi;&#xD;&#xA;			double pv = sinTheta * sinPhi;&#xD;&#xA;			double pw = cosTheta;&#xD;&#xA;			Point sample = new Point(pu, pv, pw);&#xD;&#xA;			samples.add(sample);&#xD;&#xA;		}&#xD;&#xA;		return samples;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This is the shading for emissive materials. `showPath` returns `true` by default.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		Ray ray = shading.getRay();&#xD;&#xA;		Vector n = shading.getIntersectionPoint().getNormal();&#xD;&#xA;&#xD;&#xA;		boolean showPath = tracer.getShowOnlyLength() == 0 || length == tracer.getShowOnlyLength();&#xD;&#xA;		if (n.dot(ray.direction) &lt; 0 &amp;&amp; showPath) {&#xD;&#xA;			return getTexture().getColour().scale(getPower());&#xD;&#xA;		} else {&#xD;&#xA;			return RGBSpectrum.BLACK;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Note:** I started to randomly change things in my code as a last desparate attempt to find the cause for my dark images. Funnily enough I found out that averaging over the square root of the number of rays per pixel (i.e. change `n * n` into `n` in the code underneath) seems to result in the correct brightness. Maybe this is a coincidence, because I don't use the number of rays per pixel anywhere else. Or maybe I'm still overlooking something.&#xD;&#xA;&#xD;&#xA;    // iterate over the contents of the tile&#xD;&#xA;    for (int y = tile.yStart; y &lt; tile.yEnd; y++) {&#xD;&#xA;    	for (int x = tile.xStart; x &lt; tile.xEnd; x++) {&#xD;&#xA;    		RGBSpectrum colour = scene.getBackground();&#xD;&#xA;    		Random PRNG = new Random(x * width + y);&#xD;&#xA;    &#xD;&#xA;    		// iterate over the contents of the subtile&#xD;&#xA;    		for (int p = 0; p &lt; n; p++) {&#xD;&#xA;    			for (int q = 0; q &lt; n; q++) {&#xD;&#xA;    				// create a ray through the center of the subtile.&#xD;&#xA;    				Double jitter1 = PRNG.nextDouble();&#xD;&#xA;    				Double jitter2 = PRNG.nextDouble();&#xD;&#xA;    				double rayX = x + (p + jitter1) / n;&#xD;&#xA;    				double rayY = y + (q + jitter2) / n;&#xD;&#xA;    				Ray ray = scene.getCamera().generateRay(new Sample(rayX, rayY));&#xD;&#xA;    &#xD;&#xA;    				// test the scene on intersections&#xD;&#xA;    				colour = colour.add(scene.getTracer().trace(ray));&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		// average the colours&#xD;&#xA;    		colour = colour.scale(1.0 / (n * n));&#xD;&#xA;    &#xD;&#xA;    		// add a color contribution to the pixel&#xD;&#xA;    		buffer.getPixel(x, y).add(colour);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/RHsO4.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HYiPq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/QTcUP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20838" PostHistoryTypeId="33" PostId="7915" RevisionGUID="62ca0a31-3655-4667-abd4-e03e1290a515" CreationDate="2018-08-15T12:58:44.193" UserId="9170" Comment="48" />
  <row Id="20839" PostHistoryTypeId="2" PostId="7922" RevisionGUID="e6738142-19cc-4441-87e5-10602d425847" CreationDate="2018-08-15T15:57:01.463" UserId="4908" Text="The results that you are getting, are not correct. More specifically, your direct illumination ray tracer is not correct. &#xD;&#xA;&#xD;&#xA;When limiting a path tracer's bounces to only allow for any direct illumination (thus only the camera ray and one bounce ray for a total of two rays), its brightness should and will match any ray tracer doing only direct illumination. Once the path tracer's bounces are extended or unlimited, it will produce brighter images since it then recovers partially or all energy that would come in through the bouncing of light.&#xD;&#xA;&#xD;&#xA;If you compare your path tracer to your direct illumination ray tracer, you will notice that in the path tracer on the blue wall, the brightest spot is closer to the light.&#xD;&#xA;[![Compare of his direct illumination ray tracer and path tracer][1]][1]&#xD;&#xA;&#xD;&#xA;Your path tracer here is correct, and it is the direct illumination ray tracer that does not give a correct image. To find out why, let us look at the math behind a path tracer.&#xD;&#xA;&#xD;&#xA;To find out the radiance of a point for a given viewing angle ($w_{o}$), you integrate over the point's hemisphere. We currently ignore the term $L_{e}$ which is the light that the object emits at that point.&#xD;&#xA;$$&#xD;&#xA;L_{o}(x,w_{o})=\int_{\Omega }^{ }f_{r}(x, w_{i}, w_{o})L_{i}(x,w_{i})(w_{i}\cdot n)dw_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA; - $L_{o}$ is the radiance of a point for a given viewing angle. a.k.a what a ray would return when traced.&#xD;&#xA; - $x$ is the point.&#xD;&#xA; - $w_{o}$ is the direction of outgoing light. a.k.a. viewing angle.&#xD;&#xA; - $\int_{\Omega }^{ }$ is the integral over the hemisphere. a.k.a take a bunch of samples.&#xD;&#xA; - $f_{r}$ is the result of the BRDF. a.k.a. the colour of the object.&#xD;&#xA; - $L_{i}$ is the incoming radiance for that angle. a.k.a. what the rays, that you spawn in the shadePath() method, return.&#xD;&#xA; - $w_{i}\cdot n$ is also written as $cos\theta _{i}$ and is used to weaken the incoming radiance due to how light actually works. You already did this by using cosine distributed samples.&#xD;&#xA; - $dw_{i}$ is a part of the integral, and basically averages all the samples.&#xD;&#xA;&#xD;&#xA;If we look at an example in 2D, we have a point with the hemisphere (here just half a circle) and a rectangular light (here just a line).&#xD;&#xA;[![A light covering 30° of a semicircle.][2]][2]&#xD;&#xA;We see that the light takes up 30° of the 180° of the hemisphere (in 3D we would talk in area instead of degrees). If we move the light further back.&#xD;&#xA;[![A light that is covering 12° of a semicircle.][3]][3]&#xD;&#xA;We see that the light now only takes up 12° of the 180° of the hemisphere. The further back a light is, the less it contributes to the final radiance of the point. In 2D this falloff is $1/d$ where $d$ is the distance. In 3D this falloff is $1/d^{2}$.&#xD;&#xA;&#xD;&#xA;With a path tracer, this falloff is already done for you. If the light is further away, less samples would hit it and thus it contributes less.&#xD;&#xA;[![5 samples hitting a light][4]][4]&#xD;&#xA;[![3 samples hitting a light][5]][5]&#xD;&#xA;&#xD;&#xA;However, with a direct illumination ray tracer or next-event-estimation, every sample will always hit the light (unless there is something blocking it). Therefore, we need to add that falloff back in. We do this by multiplying the incoming light from the area light by the falloff $1/d^{2}$.&#xD;&#xA;&#xD;&#xA;If we rotate the area light, we would notice that it would then also take up less area on the hemisphere. This should also be accounted for, and an easy way to approximate it is using the cosine between the normal of the area light and the outgoing direction. Which you already have.&#xD;&#xA;&#xD;&#xA;It is the not having this falloff, that makes your direct illumination ray tracer not give correct results. You would need to make the area light brighter than, because of the falloff.&#xD;&#xA;&#xD;&#xA;If I have not missed anything else, that is all you need.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MCRCi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/kPD72.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/OKHkY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/wsY2L.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/QGH34.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20840" PostHistoryTypeId="5" PostId="7915" RevisionGUID="b937f36f-8318-43b5-9e05-2e428cc10532" CreationDate="2018-08-15T17:13:52.993" UserId="9170" Comment="added 1248 characters in body" Text="I am using the book *Ray Tracing from the Ground Up* by Kevin Suffern to build my first ray tracers in Java. Based on the theory, I expected that direct illumination and simple path tracers render the same scene equally bright (that is, when the resulting images are more of less converged and the path tracer only allows paths of maximal length 2). However, my implementation for a simple path tracer renders much darker images. Here is an example:&#xD;&#xA;&#xD;&#xA;[![Direct illumination][2]][2]&#xD;&#xA;[![Path tracer][3]][3]&#xD;&#xA;&#xD;&#xA;The images on the left and right are respectively the result of direct illumination and path tracing with 225 rays per pixel. My path tracer does not use next event estimation; it returns black whenever the path becomes longer than a certain length without reaching the area light. For every pixel, the received radiances are averaged afterwards.&#xD;&#xA;&#xD;&#xA;When I manually change the sensitivity, though (i.e. a simple post rendering scaling of the colours in the image), the path traced image becomes this:&#xD;&#xA;&#xD;&#xA;[![Lighter version of path tracer][4]][4]&#xD;&#xA;&#xD;&#xA;Of course, the brightened image is not near convergence, but it should at least be clear that the path tracer actually renders the same scene similarly.&#xD;&#xA;&#xD;&#xA;Is this normal behaviour? If so, could I just pick a larger power for the light source when using a path tracer? If not, please find some relevant code of my path tracer underneath.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;This is my code for shading an intersection point of a ray and a matte object. It is supposed to shoot an arbitrary ray from the intersection point along a cosine distribution (I have used a branch factor 1 for my images).&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		int factor = tracer.getBranchFactor();&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(factor);&#xD;&#xA;		List&lt;Point&gt; samples = sampler.computeSamples();&#xD;&#xA;		RGBSpectrum L = RGBSpectrum.BLACK;&#xD;&#xA;&#xD;&#xA;		for (Point sample : samples) {&#xD;&#xA;			Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;			Random PRNG = new Random();&#xD;&#xA;			Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble());&#xD;&#xA;			Vector v = r.cross(w).normalize();&#xD;&#xA;			Vector u = v.cross(w);&#xD;&#xA;			Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z)).normalize();&#xD;&#xA;			Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;			L = L.add(tracer.trace(ray, length + 1));&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		L = L.scale(1.0 / factor);&#xD;&#xA;		return shading.getColour().scale(getDiffuseReflection()).multiply(L);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Here is how the cosine distributed samples are computed:&#xD;&#xA;&#xD;&#xA;    public List&lt;Point&gt; computeSamples() {&#xD;&#xA;		List&lt;Point&gt; samples = new ArrayList&lt;&gt;();&#xD;&#xA;		for (int i = 0; i &lt; getSamples(); i++) {&#xD;&#xA;			double phi = 2 * Math.PI * Math.random();&#xD;&#xA;			double cosPhi = Math.cos(phi);&#xD;&#xA;			double sinPhi = Math.sin(phi);&#xD;&#xA;			double cosTheta = Math.sqrt(1 - Math.random());&#xD;&#xA;			double sinTheta = Math.sqrt(1 - cosTheta * cosTheta);&#xD;&#xA;			double pu = sinTheta * cosPhi;&#xD;&#xA;			double pv = sinTheta * sinPhi;&#xD;&#xA;			double pw = cosTheta;&#xD;&#xA;			Point sample = new Point(pu, pv, pw);&#xD;&#xA;			samples.add(sample);&#xD;&#xA;		}&#xD;&#xA;		return samples;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;This is the shading for emissive materials. `showPath` returns `true` by default.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, BranchPathTracer tracer, int length) {&#xD;&#xA;		Ray ray = shading.getRay();&#xD;&#xA;		Vector n = shading.getIntersectionPoint().getNormal();&#xD;&#xA;&#xD;&#xA;		boolean showPath = tracer.getShowOnlyLength() == 0 || length == tracer.getShowOnlyLength();&#xD;&#xA;		if (n.dot(ray.direction) &lt; 0 &amp;&amp; showPath) {&#xD;&#xA;			return getTexture().getColour().scale(getPower());&#xD;&#xA;		} else {&#xD;&#xA;			return RGBSpectrum.BLACK;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;For reference, here is also my shading function for matte objects under direct illumination.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shade(Shading shading) {&#xD;&#xA;		RGBSpectrum colour = shading.getColour();&#xD;&#xA;		double L = 0;&#xD;&#xA;		final Point intersection = shading.getIntersectionPoint().toPoint(shading.getRay());&#xD;&#xA;&#xD;&#xA;		for (Light light : shading.getScene().getLights()) {&#xD;&#xA;			double l = 0;&#xD;&#xA;&#xD;&#xA;			for (Point sample : light.computeSamples()) {&#xD;&#xA;				Vector wi = sample.subtract(intersection);&#xD;&#xA;				double cos = shading.getIntersectionPoint().getNormal().dot(wi);&#xD;&#xA;&#xD;&#xA;				if (cos &gt; 0) {&#xD;&#xA;					Ray shadowRay = new Ray(intersection, wi);&#xD;&#xA;&#xD;&#xA;					if (!light.inShadow(shadowRay, shading.getScene())) {&#xD;&#xA;						if (light instanceof PointLight) {&#xD;&#xA;							double denom = 4 * Math.PI * wi.lengthSquared();&#xD;&#xA;							l += light.getPower() * cos / denom;&#xD;&#xA;						} else if (light instanceof RectangularLight) {&#xD;&#xA;							Rectangle rectangle = ((RectangularLight) light).getRectangle();&#xD;&#xA;							double cosp = -wi.dot(rectangle.getNormal());&#xD;&#xA;							l += light.getPower() * cos * cosp / (wi.lengthSquared() * rectangle.getArea());&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			L += l / light.getSamplesNumber();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return colour.scale(getAmbientReflection() + L * getDiffuseReflection());&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Note:** I started to randomly change things in my code as a last desparate attempt to find the cause for my dark images. Funnily enough I found out that averaging over the square root of the number of rays per pixel (i.e. change `n * n` into `n` in the code underneath) seems to result in the correct brightness. Maybe this is a coincidence, because I don't use the number of rays per pixel anywhere else. Or maybe I'm still overlooking something.&#xD;&#xA;&#xD;&#xA;    // iterate over the contents of the tile&#xD;&#xA;    for (int y = tile.yStart; y &lt; tile.yEnd; y++) {&#xD;&#xA;    	for (int x = tile.xStart; x &lt; tile.xEnd; x++) {&#xD;&#xA;    		RGBSpectrum colour = scene.getBackground();&#xD;&#xA;    		Random PRNG = new Random(x * width + y);&#xD;&#xA;    &#xD;&#xA;    		// iterate over the contents of the subtile&#xD;&#xA;    		for (int p = 0; p &lt; n; p++) {&#xD;&#xA;    			for (int q = 0; q &lt; n; q++) {&#xD;&#xA;    				// create a ray through the center of the subtile.&#xD;&#xA;    				Double jitter1 = PRNG.nextDouble();&#xD;&#xA;    				Double jitter2 = PRNG.nextDouble();&#xD;&#xA;    				double rayX = x + (p + jitter1) / n;&#xD;&#xA;    				double rayY = y + (q + jitter2) / n;&#xD;&#xA;    				Ray ray = scene.getCamera().generateRay(new Sample(rayX, rayY));&#xD;&#xA;    &#xD;&#xA;    				// test the scene on intersections&#xD;&#xA;    				colour = colour.add(scene.getTracer().trace(ray));&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		// average the colours&#xD;&#xA;    		colour = colour.scale(1.0 / (n * n));&#xD;&#xA;    &#xD;&#xA;    		// add a color contribution to the pixel&#xD;&#xA;    		buffer.getPixel(x, y).add(colour);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/RHsO4.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HYiPq.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/QTcUP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20841" PostHistoryTypeId="5" PostId="7922" RevisionGUID="8d16a150-466a-4896-8c2e-e1979100d327" CreationDate="2018-08-15T19:12:51.530" UserId="4908" Comment="added 2814 characters in body" Text="The results that you are getting, are not correct. More specifically, your direct illumination ray tracer is not correct. &#xD;&#xA;&#xD;&#xA;When limiting a path tracer's bounces to only allow for any direct illumination (thus only the camera ray and one bounce ray for a total of two rays), its brightness should and will match any ray tracer doing only direct illumination. Once the path tracer's bounces are extended or unlimited, it will produce brighter images since it then recovers partially or all energy that would come in through the bouncing of light.&#xD;&#xA;&#xD;&#xA;If you compare your path tracer to your direct illumination ray tracer, you will notice that in the path tracer on the blue wall, the brightest spot is closer to the light.&#xD;&#xA;[![Compare of his direct illumination ray tracer and path tracer][1]][1]&#xD;&#xA;&#xD;&#xA;Your path tracer here is correct, and it is the direct illumination ray tracer that does not give a correct image. To find out why, let us look at the math behind a path tracer.&#xD;&#xA;&#xD;&#xA;To find out the radiance of a point for a given viewing angle ($w_{o}$), you integrate over the point's hemisphere. We currently ignore the term $L_{e}$ which is the light that the object emits at that point.&#xD;&#xA;$$&#xD;&#xA;L_{o}(x,w_{o})=\int_{\Omega }^{ }f_{r}(x, w_{i}, w_{o})L_{i}(x,w_{i})(w_{i}\cdot n)dw_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA; - $L_{o}$ is the radiance of a point for a given viewing angle. a.k.a what a ray would return when traced.&#xD;&#xA; - $x$ is the point.&#xD;&#xA; - $w_{o}$ is the direction of outgoing light. a.k.a. viewing angle.&#xD;&#xA; - $\int_{\Omega }^{ }$ is the integral over the hemisphere. a.k.a take a bunch of samples.&#xD;&#xA; - $f_{r}$ is the result of the BRDF. a.k.a. the colour of the object.&#xD;&#xA; - $L_{i}$ is the incoming radiance for that angle. a.k.a. what the rays, that you spawn in the shadePath() method, return.&#xD;&#xA; - $w_{i}\cdot n$ is also written as $cos\theta _{i}$ and is used to weaken the incoming radiance due to how light actually works. You already did this by using cosine distributed samples.&#xD;&#xA; - $dw_{i}$ is a part of the integral, and basically averages all the samples.&#xD;&#xA;&#xD;&#xA;If we look at an example in 2D, we have a point with the hemisphere (here just half a circle) and a rectangular light (here just a line).&#xD;&#xA;[![A light covering 30° of a semicircle.][2]][2]&#xD;&#xA;We see that the light takes up 30° of the 180° of the hemisphere (in 3D we would talk in area instead of degrees). If we move the light further back.&#xD;&#xA;[![A light that is covering 12° of a semicircle.][3]][3]&#xD;&#xA;We see that the light now only takes up 12° of the 180° of the hemisphere. The further back a light is, the less it contributes to the final radiance of the point. In 2D this falloff is $1/d$ where $d$ is the distance. In 3D this falloff is $1/d^{2}$.&#xD;&#xA;&#xD;&#xA;With a path tracer, this falloff is already done for you. If the light is further away, less samples would hit it and thus it contributes less.&#xD;&#xA;[![5 samples hitting a light][4]][4]&#xD;&#xA;[![3 samples hitting a light][5]][5]&#xD;&#xA;&#xD;&#xA;However, with a direct illumination ray tracer or next-event-estimation, every sample will always hit the light (unless there is something blocking it). Therefore, we need to add that falloff back in. We do this by multiplying the incoming light from the area light by the falloff $1/d^{2}$.&#xD;&#xA;&#xD;&#xA;If we rotate the area light, we would notice that it would then also take up less area on the hemisphere. This should also be accounted for, and an easy way to approximate it is using the cosine between the normal of the area light and the outgoing direction. Which you already have.&#xD;&#xA;&#xD;&#xA;It is the not having this falloff, that makes your direct illumination ray tracer not give correct results. You would need to make the area light brighter than, because of the falloff.&#xD;&#xA;&#xD;&#xA;If I have not missed anything else, that is all you need.&#xD;&#xA;&#xD;&#xA;## EDIT ##&#xD;&#xA;Jeroen added the code for his direct illumination ray tracer later on, and I just noticed why it is giving incorrect results. The above is still correct, yet he already had my suggested fix implemented.&#xD;&#xA;&#xD;&#xA;When looking at his code, there is one thing that he forgot to do a few times, and that was to normalize $w_{i}$ before using it in the dot product. The dot operator only gives the cosine of the angle between the two vectors, when both vectors have a length of 1 (a.k.a. they are normalized). Jeroen forgot to do this and $w_{i}$ had a longer length than 1. Below is the code of his direct illumination ray tracer's shade function where I added some comments to make it easier to understand.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shade(Shading shading) {&#xD;&#xA;        RGBSpectrum colour = shading.getColour();&#xD;&#xA;        double L = 0;&#xD;&#xA;        final Point intersection = shading.getIntersectionPoint().toPoint(shading.getRay());&#xD;&#xA;&#xD;&#xA;        for (Light light : shading.getScene().getLights()) {&#xD;&#xA;            double l = 0;&#xD;&#xA;&#xD;&#xA;            for (Point sample : light.computeSamples()) {&#xD;&#xA;                Vector wi = sample.subtract(intersection);&#xD;&#xA;                // In the line below, you calculate the cosine, &#xD;&#xA;                // yet wi is not normalized. Later on you use wi again &#xD;&#xA;                // to calculate a cosine and still forgot to normalize it. &#xD;&#xA;                // Since you use the lengthSquared() of wi also, &#xD;&#xA;                // I recommend to save that to a variable here, &#xD;&#xA;                // and then you normalize wi. This way you only need to add &#xD;&#xA;                // the following two lines (that I commented out)&#xD;&#xA;                //&#xD;&#xA;                // double lengthSquared = wi.lengthSquared();&#xD;&#xA;                // wi = wi.normalize();&#xD;&#xA;                double cos = shading.getIntersectionPoint().getNormal().dot(wi);&#xD;&#xA;&#xD;&#xA;                if (cos &gt; 0) {&#xD;&#xA;                    Ray shadowRay = new Ray(intersection, wi);&#xD;&#xA;&#xD;&#xA;                    if (!light.inShadow(shadowRay, shading.getScene())) {&#xD;&#xA;                        if (light instanceof PointLight) {&#xD;&#xA;                            double denom = 4 * Math.PI * wi.lengthSquared();&#xD;&#xA;                            l += light.getPower() * cos / denom;&#xD;&#xA;                        } else if (light instanceof RectangularLight) {&#xD;&#xA;                            Rectangle rectangle = ((RectangularLight) light).getRectangle();&#xD;&#xA;                            double cosp = -wi.dot(rectangle.getNormal());&#xD;&#xA;                            l += light.getPower() * cos * cosp / (wi.lengthSquared() * rectangle.getArea());&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            L += l / light.getSamplesNumber();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return colour.scale(getAmbientReflection() + L * getDiffuseReflection());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MCRCi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/kPD72.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/OKHkY.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/wsY2L.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/QGH34.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20845" PostHistoryTypeId="50" PostId="7643" RevisionGUID="f14211a7-d629-4603-8bab-f86bcb42848b" CreationDate="2018-08-15T21:01:57.970" UserId="-1" />
  <row Id="20847" PostHistoryTypeId="2" PostId="7924" RevisionGUID="b1e4e888-97ba-40b8-afc3-b83b5a3fca5e" CreationDate="2018-08-15T23:52:46.633" UserId="9196" Text="I can program, but have only recently started to learn graphics and the related math, so sorry for any ignorance here.&#xD;&#xA;&#xD;&#xA;Imagine a top-down 2D game with a programmable robot that drives around and uses a laser range finder to get the distance to the nearest wall.&#xD;&#xA;&#xD;&#xA;I'm using DDA to draw a line from the robot (in the direction it's facing), then checking each point on the line till it hits something (or runs out of range).&#xD;&#xA;&#xD;&#xA;Whenever the line hits something, the function just returns the number of iterations it took to get to that point (the number of pixels that were checked) as the distance. This avoids calculating the length of the line properly, but how sketchy is this approach?&#xD;&#xA;&#xD;&#xA;If the line is horizontal or vertical, then there's no discrepancy, but how greatly does the number of pixels in a line differ from its real length in the worst case?&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA;- The length of the line is never just a few pixels, say always at least 50px.&#xD;&#xA;- Longer lines obviously have larger discrepancies, but the question is really about relative differences." ContentLicense="CC BY-SA 4.0" />
  <row Id="20848" PostHistoryTypeId="1" PostId="7924" RevisionGUID="b1e4e888-97ba-40b8-afc3-b83b5a3fca5e" CreationDate="2018-08-15T23:52:46.633" UserId="9196" Text="How different can the number of pixels in a straight line be to its real length?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20849" PostHistoryTypeId="3" PostId="7924" RevisionGUID="b1e4e888-97ba-40b8-afc3-b83b5a3fca5e" CreationDate="2018-08-15T23:52:46.633" UserId="9196" Text="|mathematics|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20850" PostHistoryTypeId="5" PostId="7924" RevisionGUID="99029ee4-86f7-4965-97ea-869035dd435b" CreationDate="2018-08-16T00:02:37.553" UserId="9196" Comment="added 58 characters in body" Text="I can program, but have only recently started to learn graphics and the related math, so sorry for any ignorance here.&#xD;&#xA;&#xD;&#xA;Imagine a top-down 2D game with a programmable robot that drives around and uses a laser range finder to get the distance to the nearest wall.&#xD;&#xA;&#xD;&#xA;I'm using a DDA generator function that yields pixel coordinates, going from the robot, along a line in the direction it's facing.&#xD;&#xA;&#xD;&#xA;The range finding function consumes the coordinates for one pixel at a time, checking each until one hits something. At that point, the function just returns the number of iterations it took (the number of pixels that were checked) as the distance. This avoids calculating the length of the line properly, but how sketchy is this approach?&#xD;&#xA;&#xD;&#xA;If the line is horizontal or vertical, then there's no discrepancy, but how greatly does the number of pixels in a line differ from its real length in the worst case?&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA;- The length of the line is never just a few pixels, say always at least 50px.&#xD;&#xA;- Longer lines obviously have larger discrepancies, but the question is really about relative differences." ContentLicense="CC BY-SA 4.0" />
  <row Id="20851" PostHistoryTypeId="5" PostId="7924" RevisionGUID="567fbeb3-b2b7-4581-87b1-8a88d7fca9cc" CreationDate="2018-08-16T00:10:20.817" UserId="9196" Comment="Added a tiny bit of background to help with visualisation. " Text="I'm working on a game with a programmable robot. It uses a laser range finder to get the distance to walls.&#xD;&#xA;&#xD;&#xA;I'm using DDA to generate a line from the robot, going in the direction it is pointing, then checking each pixel along the line to see if it hits anything. At that point, the number of pixels checked so far is used as the range, to save having to calculate the proper length.&#xD;&#xA;&#xD;&#xA;If the line is horizontal or vertical, then there's no discrepancy, but how greatly does the number of pixels in a line differ from its real length in the worst case?&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA;- The length of the line is never just a few pixels, say always at least 50px.&#xD;&#xA;- Longer lines obviously have larger discrepancies, but the question is really about relative differences." ContentLicense="CC BY-SA 4.0" />
  <row Id="20852" PostHistoryTypeId="2" PostId="7925" RevisionGUID="5d2f7745-8723-4763-9a5e-48da8d649739" CreationDate="2018-08-16T00:24:18.400" UserId="48" Text="The worst case is when the line is at a 45-degree angle; then its length (in pixel-sized units) is a factor of $\sqrt{2}$ times the number of pixels, or about 40% longer.&#xD;&#xA;&#xD;&#xA;You can see this if you imagine starting with a vertical line of say 50px, then gradually sliding the endpoint away horizontally. Note that the number of pixels drawn doesn't change! You still have exactly one pixel turned on in each row that the line crosses. The pixels will adjust their horizontal positions but no new pixels will turn on, until the line surpasses 45 degrees from the vertical. The same is true if you start with a horizontal line and slide the endpoint vertically.&#xD;&#xA;&#xD;&#xA;The number of pixels in the line effectively only looks at the vertical or horizontal distance, whichever is larger, and ignores the smaller dimension.&#xD;&#xA;Mathematically, the number of pixels is $\max(|\Delta x|, |\Delta y|)$ while the Euclidean distance is $\sqrt{\Delta x^2 + \Delta y^2}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="20862" PostHistoryTypeId="2" PostId="7928" RevisionGUID="e4fa54d7-1ef6-4e39-a091-c187b035ffb1" CreationDate="2018-08-16T10:39:15.173" UserId="9194" Text="I don't have an exact answer for this, as the answer is far from trivial. I would suggest that you have a look into computational geometry as this clearly is a visibility problem - my guess is that a solution already exist. My own idea would be: for each line segment in polygon find the visible parts of the other line segments and then pick the pair of points that are furthest apart. Inspirational link: [Wikipedia on 'visibility polygon'][1].&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Visibility_polygon" ContentLicense="CC BY-SA 4.0" />
  <row Id="20863" PostHistoryTypeId="2" PostId="7929" RevisionGUID="f120c56b-1fed-4bb4-b8ad-124e0ec524c4" CreationDate="2018-08-16T17:27:40.460" UserId="9170" Text="I am trying to implement a simple path tracer with next-event estimation in Java. The general idea is to trace a ray through the scene as usual (using a cosine distribution to determine the next random direction at every bounce), while also taking the direct illumination into account at every bounce. I think I have most pieces of the puzzle available, but I can't fit them together correctly.&#xD;&#xA;&#xD;&#xA;Here is how I shade matte objects: add the direct illumination to the radiance coming from a random ray (chosen according to a cosine distribution), the latter multiplied by the BRDF.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, HybridPathTracer tracer, int length) {&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(1);&#xD;&#xA;		Point sample = sampler.computeSample();&#xD;&#xA;&#xD;&#xA;		Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;		Random PRNG = new Random();&#xD;&#xA;		Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble()).normalize();&#xD;&#xA;		Vector v = r.cross(w);&#xD;&#xA;		Vector u = v.cross(w);&#xD;&#xA;		Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z));&#xD;&#xA;		Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;		RGBSpectrum reflection = tracer.trace(ray, length + 1);&#xD;&#xA;		RGBSpectrum brdf = shading.getColour().scale(getDiffuseReflection());&#xD;&#xA;		return shade(shading).add(brdf.multiply(reflection));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;When a ray reaches an emissive material, black is returned, unless the path length is equal to 1:&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, HybridPathTracer tracer, int length) {&#xD;&#xA;		Ray ray = shading.getRay();&#xD;&#xA;		Vector n = shading.getIntersectionPoint().getNormal();&#xD;&#xA;&#xD;&#xA;		if (length == 1 &amp;&amp; n.dot(ray.direction) &lt; 0) {&#xD;&#xA;			return getTexture().getColour();&#xD;&#xA;		} else {&#xD;&#xA;			return RGBSpectrum.BLACK;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I read https://computergraphics.stackexchange.com/a/5153/9170 and thought that I was using the same idea in my code, but I must be doing something wrong, because my images are getting too bright when the maximal path length increases (see the examples for maximal length 2, 4 and 6 underneath). What is the problem?&#xD;&#xA;&#xD;&#xA;[![Maximal length 2][1]][1]&#xD;&#xA;[![Maximal length 4][2]][2]&#xD;&#xA;[![Maximal length 6][3]][3]&#xD;&#xA;&#xD;&#xA;**Note:** I know I should also consider some edge cases for specular surfaces, but maybe it's better to ignore those first and focus on matte objects. (I think I have prepared my code for specular surfaces anyway.) My shade function for direct illumination of matte objects should be fine, but here it is for reference:&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shade(Shading shading) {&#xD;&#xA;		RGBSpectrum colour = shading.getColour();&#xD;&#xA;		double L = 0;&#xD;&#xA;		final Point intersection = shading.getIntersectionPoint().toPoint(shading.getRay());&#xD;&#xA;&#xD;&#xA;		for (Light light : shading.getScene().getLights()) {&#xD;&#xA;			double l = 0;&#xD;&#xA;&#xD;&#xA;			for (Point sample : light.computeSamples()) {&#xD;&#xA;				Vector wi = sample.subtract(intersection);&#xD;&#xA;				double lengthSquared = wi.lengthSquared();&#xD;&#xA;				wi = wi.normalize();&#xD;&#xA;				double cos = shading.getIntersectionPoint().getNormal().dot(wi);&#xD;&#xA;&#xD;&#xA;				if (cos &gt; 0) {&#xD;&#xA;					Ray shadowRay = new Ray(intersection, wi);&#xD;&#xA;&#xD;&#xA;					if (!light.inShadow(shadowRay, shading.getScene())) {&#xD;&#xA;						if (light instanceof PointLight) {&#xD;&#xA;							double denom = 4 * Math.PI * lengthSquared;&#xD;&#xA;							l += light.getPower() * cos / denom;&#xD;&#xA;						} else if (light instanceof RectangularLight) {&#xD;&#xA;							Rectangle rectangle = ((RectangularLight) light).getRectangle();&#xD;&#xA;							double cosp = -wi.dot(rectangle.getNormal());&#xD;&#xA;							l += light.getPower() * cos * cosp * rectangle.getArea() / lengthSquared;&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			L += l / light.getSamplesNumber();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return colour.scale(getAmbientReflection() + L * getDiffuseReflection());&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yXEMz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/iodfO.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/3qgye.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20864" PostHistoryTypeId="1" PostId="7929" RevisionGUID="f120c56b-1fed-4bb4-b8ad-124e0ec524c4" CreationDate="2018-08-16T17:27:40.460" UserId="9170" Text="How does a path tracer with next-event estimation work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20865" PostHistoryTypeId="3" PostId="7929" RevisionGUID="f120c56b-1fed-4bb4-b8ad-124e0ec524c4" CreationDate="2018-08-16T17:27:40.460" UserId="9170" Text="|raytracing|pathtracing|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20866" PostHistoryTypeId="50" PostId="6012" RevisionGUID="d277b22f-b9bb-4f6a-8dbf-b7868b610c46" CreationDate="2018-08-16T19:00:00.410" UserId="-1" />
  <row Id="20867" PostHistoryTypeId="2" PostId="7930" RevisionGUID="33e9eeb3-c26f-42f6-86ad-0b1b4118665d" CreationDate="2018-08-16T19:42:25.493" UserId="48" Text="I noticed three potential problems. First, this bit of code looks suspicious:&#xD;&#xA;&#xD;&#xA;    Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble()).normalize();&#xD;&#xA;    Vector v = r.cross(w);&#xD;&#xA;    Vector u = v.cross(w);&#xD;&#xA;    Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z));&#xD;&#xA;&#xD;&#xA;The vectors `v` and `u` are not normalized, so the construction of `wi` will be distorted. (Also, using a random vector `r` to construct the basis is really more work than necessary; you might take a look at [this paper](http://jcgt.org/published/0006/01/01/) for a faster way of doing that.)&#xD;&#xA;&#xD;&#xA;Second, you have a `getAmbientReflection()` in your direct lighting code—that should not be there for path tracing, where &quot;ambient&quot; light is properly calculated by the recursive trace.&#xD;&#xA;&#xD;&#xA;Finally, I think the result of your direct illumination path ought to be scaled by $1/π$. This is because the Lambert BRDF is equal to $c_d/π$ where $c_d$ is the diffuse color. The direct illumination path needs to evaluate the full BRDF, including that $1/π$ factor, using the irradiance sample coming in from the light source.&#xD;&#xA;&#xD;&#xA;However, the cosine-weighted recursive trace does _not_ need a $1/π$, as it is cancelled out by the cosine PDF. That one should just use $c_d$, like you have it.&#xD;&#xA;&#xD;&#xA;You can check that the $1/π$ factors are correct by checking that the average brightness is equal with and without next-event estimation (keeping the path length the same).&#xD;&#xA;&#xD;&#xA;BTW, note that the image getting somewhat brighter as you increase the path length is to be expected, as longer paths = more bounces = more illumination. (Russian-roulette path termination fixes this.) Longer paths will also give stronger global illumination / &quot;color-bleeding&quot; effects. That seems to be what's happening in your images—look at the color of the shadow under the sphere; it gets progressively more influenced by the color of the walls and sphere as you increase the path length.&#xD;&#xA;&#xD;&#xA;If this is undesirable, try reducing the diffuse reflection factors of all the materials in the scene; they might be unrealistically high, and cutting them down will reduce the bounce light and color-bleeding." ContentLicense="CC BY-SA 4.0" />
  <row Id="20868" PostHistoryTypeId="50" PostId="5996" RevisionGUID="ccfdff41-8be8-464f-8ed7-d67c444ee9e3" CreationDate="2018-08-16T21:00:55.407" UserId="-1" />
  <row Id="20869" PostHistoryTypeId="2" PostId="7931" RevisionGUID="49a0c2c2-af37-4cc4-b182-1c89ec88a6ec" CreationDate="2018-08-17T08:22:36.720" UserId="9194" Text="You cannot use Clipper and expect analytical results. Circle arcs will be composed by line segments. That said, you know your boolean operands so it should be possible and fairly easy to map all line segments back to their origin operand and extract the arcs yourself." ContentLicense="CC BY-SA 4.0" />
  <row Id="20870" PostHistoryTypeId="2" PostId="7932" RevisionGUID="1d0a0c6f-ac43-4859-9fd6-bb81097c9534" CreationDate="2018-08-17T09:14:43.320" UserId="9207" Text="I have a scenario where I need rotate a vector ( unit vector) at a point in space by an angle along Z-axis. Is it possible to help me to understand a procedure to achieve this. I'm using vb.net programming to do this programattically. &#xD;&#xA;&#xD;&#xA;Here is the schematics for your understanding:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HvCwq.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20871" PostHistoryTypeId="1" PostId="7932" RevisionGUID="1d0a0c6f-ac43-4859-9fd6-bb81097c9534" CreationDate="2018-08-17T09:14:43.320" UserId="9207" Text="Rotation of a random unit vector at a point in 3D space by an angle" ContentLicense="CC BY-SA 4.0" />
  <row Id="20872" PostHistoryTypeId="3" PostId="7932" RevisionGUID="1d0a0c6f-ac43-4859-9fd6-bb81097c9534" CreationDate="2018-08-17T09:14:43.320" UserId="9207" Text="|transformations|computational-geometry|matrix|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20873" PostHistoryTypeId="2" PostId="7933" RevisionGUID="44d04ea7-e6b8-4002-9ded-51bc01ce49b1" CreationDate="2018-08-17T10:58:45.520" UserId="6046" Text="Suppose my path tracer is shooting 64 rays per pixel (in an 8x8 grid). The confusion is, when accounting for Global illumination, should I shoot additional `X` number of random rays for each of those initial 64 rays? This would equal to shooting `64 * X *number of bounces` rays (all sorts of) which is really large. And since I am making the path tracer on GPU memory is surely a concern.&#xD;&#xA;&#xD;&#xA;OR I just shoot 1 random ray for indirect illumination. This would mean that the total secondary rays cast for GI would equal 64 per pixel.&#xD;&#xA;&#xD;&#xA;**The problem here is, all those 64 rays cast per pixel aren't guaranteed to intersect at the same point albeit close enough. If the intersection positions aren't the same then this would mean I am calculating indirect illumination using just 1 sample which is ofcourse very low.**&#xD;&#xA;&#xD;&#xA;Now this is again for just GI. What about Area light sources? Should I be explicitly sampling X number of rays for Area Light for each of those initial 64 rays? &#xD;&#xA;&#xD;&#xA;I think this is what Cook mentioned in his paper on **Distributed Ray Tracing**. He says&#xD;&#xA;&#xD;&#xA;&gt; Rather than adding more rays for each dimension, the existing rays are&#xD;&#xA;&gt; distributed in each dimension according to the values of the&#xD;&#xA;&gt; corresponding parameter. The key is that no extra rays are needed beyond&#xD;&#xA;those used for oversampling.&#xD;&#xA;&#xD;&#xA;I am confused because mostly I have seen algorithms and code snippets following the second approach. Casting X number of rays for GI.&#xD;&#xA;&#xD;&#xA;**2)** Secondly for direct illumination is the light path explicitly calculated or it's taken from the samples created for GI? The former means if I am sampling 1 ray for GI for each of the 64 rays per pixel, then I am also shooting another ray explicitly for the light path. The random sampled ray, if points to the light source I ignore it.&#xD;&#xA;&#xD;&#xA;The latter means, I sample only 1 ray, if it doesn't hits the light source that's my GI, and if it hits the light source I accumulate it's color as direct lighting." ContentLicense="CC BY-SA 4.0" />
  <row Id="20874" PostHistoryTypeId="1" PostId="7933" RevisionGUID="44d04ea7-e6b8-4002-9ded-51bc01ce49b1" CreationDate="2018-08-17T10:58:45.520" UserId="6046" Text="Path Tracer - sampling dimensions confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="20875" PostHistoryTypeId="3" PostId="7933" RevisionGUID="44d04ea7-e6b8-4002-9ded-51bc01ce49b1" CreationDate="2018-08-17T10:58:45.520" UserId="6046" Text="|pathtracing|sampling|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20876" PostHistoryTypeId="2" PostId="7934" RevisionGUID="9fb480df-ddf4-48db-8a35-6f976455bd21" CreationDate="2018-08-17T11:56:43.567" UserId="9194" Text="Only one path per sample.&#xD;&#xA;&#xD;&#xA;If you had 64 bounces per first hit and 64 per second hit and so forth you'd never get an image.&#xD;&#xA;&#xD;&#xA;Edit: And that's why you need to sample each pixel so many times (easily more than 1024 samples) in order to get it to converge, ie get rid of the noise." ContentLicense="CC BY-SA 4.0" />
  <row Id="20877" PostHistoryTypeId="34" PostId="7915" RevisionGUID="d269bf67-5599-41f5-a7f9-eb25abe27e39" CreationDate="2018-08-17T13:25:56.970" UserId="9170" Comment="48" />
  <row Id="20878" PostHistoryTypeId="50" PostId="7529" RevisionGUID="a29cfb34-3161-4104-becd-110a9ebfac4a" CreationDate="2018-08-17T20:01:35.493" UserId="-1" />
  <row Id="20879" PostHistoryTypeId="50" PostId="7633" RevisionGUID="cd38fc11-8e3a-4ca7-8de1-1b1b4008065b" CreationDate="2018-08-18T06:01:40.433" UserId="-1" />
  <row Id="20884" PostHistoryTypeId="2" PostId="7936" RevisionGUID="3c3e75fd-7e0c-44ae-997d-85bc56d13067" CreationDate="2018-08-18T16:42:57.203" UserId="2287" Text="Kevin Beason's [smallpt](http://www.kevinbeason.com/smallpt/) estimates the pixel radiance by accumulating $2\times2$ subpixel radiance estimates using the following expression:&#xD;&#xA;&#xD;&#xA;    c[i] = c[i] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25;&#xD;&#xA;&#xD;&#xA;Here, `c[i]` represents the radiance estimate of the pixel with flattened index `i`, `r` represents the radiance estimate of one of its four subpixels. As one notices a `clamp` operation is used to clamp the radiance estimate of each subpixel **separately** to the $[0,1]^3$ range **before** accumulation. But this seems wrong from an unbiased path tracing perspective, since this effectively introduces bias to the radiance estimate of each pixel. So I wonder if I am missing something (e.g., clever trick at the cost of bias), given that Kevin Beason's smallpt is already around and known for nearly ten years?&#xD;&#xA;&#xD;&#xA;Apparently, Kevin Beason also added a [presentation](https://drive.google.com/file/d/0B8g97JkuSSBwUENiWTJXeGtTOHFmSm51UC01YWtCZw/view) by David Cline explaining every line. The aforementioned expression is explained as follows:&#xD;&#xA;&#xD;&#xA;&gt; Add the gamma-corrected subpixel color estimate to the Pixel color&#xD;&#xA;&gt; `c[i]`.&#xD;&#xA;&#xD;&#xA;This seems, however, completely unrelated since no gamma correction is involved yet at this stage in the code. And since exponential functions are non-linear transformations.&#xD;&#xA;&#xD;&#xA;**Reference code**:&#xD;&#xA;&#xD;&#xA;    for (int y=0; y&lt;h; y++){                       // Loop over image rows &#xD;&#xA;        fprintf(stderr,&quot;\rRendering (%d spp) %5.2f%%&quot;,samps*4,100.*y/(h-1)); &#xD;&#xA;        for (unsigned short x=0, Xi[3]={0,0,y*y*y}; x&lt;w; x++)   // Loop cols &#xD;&#xA;            for (int sy=0, i=(h-y-1)*w+x; sy&lt;2; sy++)     // 2x2 subpixel rows &#xD;&#xA;                for (int sx=0; sx&lt;2; sx++, r=Vec()){        // 2x2 subpixel cols &#xD;&#xA;                    for (int s=0; s&lt;samps; s++){ &#xD;&#xA;                        double r1=2*erand48(Xi), dx=r1&lt;1 ? sqrt(r1)-1: 1-sqrt(2-r1); &#xD;&#xA;                        double r2=2*erand48(Xi), dy=r2&lt;1 ? sqrt(r2)-1: 1-sqrt(2-r2); &#xD;&#xA;                        Vec d = cx*( ( (sx+.5 + dx)/2 + x)/w - .5) + &#xD;&#xA;                                cy*( ( (sy+.5 + dy)/2 + y)/h - .5) + cam.d; &#xD;&#xA;                        r = r + radiance(Ray(cam.o+d*140,d.norm()),0,Xi)*(1./samps); &#xD;&#xA;                    } // Camera rays are pushed ^^^^^ forward to start in interior &#xD;&#xA;                    c[i] = c[i] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25; &#xD;&#xA;                } &#xD;&#xA;    } " ContentLicense="CC BY-SA 4.0" />
  <row Id="20885" PostHistoryTypeId="1" PostId="7936" RevisionGUID="3c3e75fd-7e0c-44ae-997d-85bc56d13067" CreationDate="2018-08-18T16:42:57.203" UserId="2287" Text="smallpt's early clamping" ContentLicense="CC BY-SA 4.0" />
  <row Id="20886" PostHistoryTypeId="3" PostId="7936" RevisionGUID="3c3e75fd-7e0c-44ae-997d-85bc56d13067" CreationDate="2018-08-18T16:42:57.203" UserId="2287" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20887" PostHistoryTypeId="5" PostId="7936" RevisionGUID="b42c9ac9-fdee-4066-9e6e-30e0d4c02b7b" CreationDate="2018-08-18T16:51:31.573" UserId="2287" Comment="added 76 characters in body" Text="Kevin Beason's [smallpt](http://www.kevinbeason.com/smallpt/) estimates the pixel radiance by accumulating $2\times2$ subpixel radiance estimates using the following expression:&#xD;&#xA;&#xD;&#xA;    c[i] = c[i] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25;&#xD;&#xA;&#xD;&#xA;Here, `c[i]` represents the radiance estimate of the pixel with flattened index `i`, `r` represents the radiance estimate of one of its four subpixels. As one notices a `clamp` operation is used to clamp the radiance estimate of each subpixel **separately** to the $[0,1]^3$ range **before** accumulation. But this seems wrong from an unbiased path tracing perspective, since this effectively introduces bias to the radiance estimate of each pixel. So I wonder if I am missing something (e.g., clever trick at the cost of bias), given that Kevin Beason's smallpt is already around and known for nearly ten years?&#xD;&#xA;&#xD;&#xA;Apparently, Kevin Beason also added a [presentation](https://drive.google.com/file/d/0B8g97JkuSSBwUENiWTJXeGtTOHFmSm51UC01YWtCZw/view) by David Cline explaining every line. The aforementioned expression is explained as follows:&#xD;&#xA;&#xD;&#xA;&gt; Add the gamma-corrected subpixel color estimate to the Pixel color&#xD;&#xA;&gt; `c[i]`.&#xD;&#xA;&#xD;&#xA;This seems, however, completely unrelated since no gamma correction is involved yet at this stage in the code. And since exponential functions are non-linear transformations. (Obviously `clamp` does not involve any exponential functions at all. ;-) )&#xD;&#xA;&#xD;&#xA;**Reference code**:&#xD;&#xA;&#xD;&#xA;    for (int y=0; y&lt;h; y++){                       // Loop over image rows &#xD;&#xA;        fprintf(stderr,&quot;\rRendering (%d spp) %5.2f%%&quot;,samps*4,100.*y/(h-1)); &#xD;&#xA;        for (unsigned short x=0, Xi[3]={0,0,y*y*y}; x&lt;w; x++)   // Loop cols &#xD;&#xA;            for (int sy=0, i=(h-y-1)*w+x; sy&lt;2; sy++)     // 2x2 subpixel rows &#xD;&#xA;                for (int sx=0; sx&lt;2; sx++, r=Vec()){        // 2x2 subpixel cols &#xD;&#xA;                    for (int s=0; s&lt;samps; s++){ &#xD;&#xA;                        double r1=2*erand48(Xi), dx=r1&lt;1 ? sqrt(r1)-1: 1-sqrt(2-r1); &#xD;&#xA;                        double r2=2*erand48(Xi), dy=r2&lt;1 ? sqrt(r2)-1: 1-sqrt(2-r2); &#xD;&#xA;                        Vec d = cx*( ( (sx+.5 + dx)/2 + x)/w - .5) + &#xD;&#xA;                                cy*( ( (sy+.5 + dy)/2 + y)/h - .5) + cam.d; &#xD;&#xA;                        r = r + radiance(Ray(cam.o+d*140,d.norm()),0,Xi)*(1./samps); &#xD;&#xA;                    } // Camera rays are pushed ^^^^^ forward to start in interior &#xD;&#xA;                    c[i] = c[i] + Vec(clamp(r.x),clamp(r.y),clamp(r.z))*.25; &#xD;&#xA;                } &#xD;&#xA;    } " ContentLicense="CC BY-SA 4.0" />
  <row Id="20888" PostHistoryTypeId="5" PostId="5823" RevisionGUID="f69c1ed2-76b1-4289-bc94-6f723d6bcda4" CreationDate="2018-08-18T17:09:24.217" UserId="2287" Comment="deleted 82 characters in body" Text="Assume that we have voxelized a 3D scene into a regular 3D grid of cubes, storing the average (diffuse) radiance and some flag indicating whether or not a voxel is empty. Next, the finer levels of the 3D texture (voxels) are downsampled to get coarser levels (&quot;pre-integrated&quot;) which will be stored as MIP levels for that texture. (*I know that some sparser structures can be used instead, but a regular grid is conceptually the most easiest to master first.*)&#xD;&#xA;&#xD;&#xA;Now, given that we have our surface position (and thus also the voxel we are in), how does voxel cone tracing work and how is it applied?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20889" PostHistoryTypeId="2" PostId="7937" RevisionGUID="d8f5f0a5-4dc4-4be1-b1e8-f1f1c7e4592f" CreationDate="2018-08-18T18:25:09.500" UserId="2287" Text="# Illumination components&#xD;&#xA;&#xD;&#xA;If the scenes only contain point lights (e.g., omni lights, spotlights, etc.) and emissive surfaces, the illumination contributions at a surface position, $x$, are computed as follows:&#xD;&#xA;&#xD;&#xA; 1. The self emission associated with the emissive surface (i.e. 0 bounces/surface interactions) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 2. The direct illumination associated with the point lights (i.e. 1 bounce/surface interaction) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 3. The direct illumination associated with the emissive surface (i.e. 1 bounce/surface interaction) is obtained from the scene's voxelization using voxel cone tracing;&#xD;&#xA; 4. The indirect illumination associated with the point lights (i.e. 2 bounces/surface interactions) is obtained from the scene's voxelization using voxel cone tracing.&#xD;&#xA;&#xD;&#xA;(By computing the diffuse illumination for all the voxels from the scene's voxelization using voxel cone tracing, the diffuse illumination from additional bounces/surface interactions can be accumulated inside the voxels. This requires each voxel to store (an approximation) to the normal distribution of the scene's surfaces as well overlapping those voxels.)&#xD;&#xA;&#xD;&#xA;# Illumination from the scene's voxelization (3)-(4)&#xD;&#xA;&#xD;&#xA;The outgoing radiance obtained from the scene's voxelization (subscript $v$) using ray tracing (subscript $r$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \int_\Omega f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a diffuse BRDF $f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) = f_{r,d}\!\left(x, \hat\omega_o, \hat\omega_i\right) = \frac{k_d}{\pi}$:&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \int_\Omega f_{r,d}\!\left(x, \hat\omega_o, \hat\omega_i\right) L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a partitioning of $\Omega$ in $N$ disjunct subdomains, $\Omega_j$, (e.g., cones) (i.e. $\Omega_1 \cup~...~\cup \Omega_N = \Omega$ with $\Omega_i \cap \Omega_j = \emptyset$ for each $i \ne j$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \sum_{j = 1}^{N} \int_{\Omega_{j}}  L_{v,r}\!\left(x, \hat\omega_{j,i}\right) \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;Relying on a single cone (subscript $c$) with a direction, $\hat\omega_{j}$, instead of individual rays for each subdomain, $\Omega_j$: &#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx \frac{k_d}{\pi} \sum_{j = 1}^{N} L_{v,c}\!\left(x, \hat\omega_{j}\right) \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$W_j = \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$\hat{W}_j = \frac{W_j}{\pi}$$&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx k_d \sum_{j = 1}^{N} \hat{W}_j L_{v,c}\!\left(x, \hat\omega_{j}\right)$$&#xD;&#xA;&#xD;&#xA;We can use for example the following six cones with an aperture of $\frac{\pi}{6}$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The normalized weight of the blue cone about the surface normal is equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{blue}} = \frac{1}{\pi} \int_{0}^{2\pi} \int_{0}^{\frac{\pi}{6}} \cos\!\theta \sin\!\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \frac{1}{4}$$&#xD;&#xA;&#xD;&#xA;The normalized weight of the other cones is approximately equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{purple|red|green|orange|brown}} \approx \frac{1-\hat{W}_{\mathrm{blue}}}{5} = \frac{3}{20}$$&#xD;&#xA;&#xD;&#xA;For a specular BRDF, one typically uses a single cone of with a direction, $2 \left(\hat{n} \cdot \hat\omega_o\right) \hat{n}-\hat\omega_o$ (i.e. reflected direction of $\hat\omega_o$ about $\hat{n}$, and an aperture based on the roughness of the surface material.&#xD;&#xA;&#xD;&#xA;# Voxel Cone Tracing&#xD;&#xA;&#xD;&#xA;$L_{v,c}$ is computed using voxel cone tracing, which can be implemented by marching the 3D voxel texture in UVW texture space.&#xD;&#xA;&#xD;&#xA;Our accumulated radiance (red, green, blue channels) and opacity (alpha channel) are initialized to zero. &#xD;&#xA;&#xD;&#xA;    Lv ← [0, 0, 0, 0]&#xD;&#xA;&#xD;&#xA;Our cone marching distance is initialized to an offset to avoid sampling the self emission associated with the emissive surface and the direct illumination associated with the point lights twice. We need to basically skip the voxel containing the surface position for which the outgoing radiance needs to be estimated.&#xD;&#xA;&#xD;&#xA;    distance ← voxel_offset to avoid sampling the direct illumination twice.&#xD;&#xA;&#xD;&#xA;    while distance &lt; max_distance and Lv.alpha &lt; 1:&#xD;&#xA;    	compute diameter&#xD;&#xA;    	compute mip_level&#xD;&#xA;    	compute position at distance&#xD;&#xA;    	if mip_level &gt;= max_mip_level or position ∉ [0,1]^3&#xD;&#xA;    	    break&#xD;&#xA;    	sample Lv_k(position, mip_level)&#xD;&#xA;    	Lv ← Lv+(1-Lv.alpha) Lv_k       // blend equation&#xD;&#xA;    	distance ← distance + cone_step // marching&#xD;&#xA;    return Lv&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TbALB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dGx7V.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20890" PostHistoryTypeId="5" PostId="7937" RevisionGUID="38846b0e-5c16-4bbc-afb4-681277247a46" CreationDate="2018-08-18T18:30:33.277" UserId="2287" Comment="added 10 characters in body" Text="# Illumination components&#xD;&#xA;&#xD;&#xA;If the scenes only contain point lights (e.g., omni lights, spotlights, etc.) and emissive surfaces, the illumination contributions at a surface position, $x$, are computed as follows:&#xD;&#xA;&#xD;&#xA; 1. The self emission associated with the emissive surface (i.e. 0 bounces/surface interactions) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 2. The direct illumination associated with the point lights (i.e. 1 bounce/surface interaction) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 3. The direct illumination associated with the emissive surface (i.e. 1 bounce/surface interaction) is obtained from the scene's voxelization using voxel cone tracing;&#xD;&#xA; 4. The indirect illumination associated with the point lights (i.e. 2 bounces/surface interactions) is obtained from the scene's voxelization using voxel cone tracing.&#xD;&#xA;&#xD;&#xA;(By computing the diffuse illumination for all the voxels from the scene's voxelization using voxel cone tracing, the diffuse illumination from additional bounces/surface interactions can be accumulated inside the voxels. This requires each voxel to store (an approximation) to the normal distribution of the scene's surfaces as well overlapping those voxels.)&#xD;&#xA;&#xD;&#xA;# Illumination from the scene's voxelization (3)-(4)&#xD;&#xA;&#xD;&#xA;The outgoing radiance obtained from the scene's voxelization (subscript $v$) using ray tracing (subscript $r$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \int_\Omega f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a diffuse BRDF $f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) = \frac{k_d}{\pi}$:&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \int_\Omega L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a partitioning of $\Omega$ in $N$ disjunct subdomains, $\Omega_j$, (e.g., $\approx$ cones) (i.e. $\Omega_1 \cup~...~\cup \Omega_N = \Omega$ with $\Omega_i \cap \Omega_j = \emptyset$ for each $i \ne j$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \sum_{j = 1}^{N} \int_{\Omega_{j}}  L_{v,r}\!\left(x, \hat\omega_{j,i}\right) \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;Relying on a single cone (subscript $c$) with a direction, $\hat\omega_{j}$, instead of individual rays for each subdomain, $\Omega_j$: &#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx \frac{k_d}{\pi} \sum_{j = 1}^{N} L_{v,c}\!\left(x, \hat\omega_{j}\right) \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$W_j = \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$\hat{W}_j = \frac{W_j}{\pi}$$&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx k_d \sum_{j = 1}^{N} \hat{W}_j L_{v,c}\!\left(x, \hat\omega_{j}\right)$$&#xD;&#xA;&#xD;&#xA;We can use for example the following six cones, each with an aperture of $\frac{\pi}{6}$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The normalized weight of the blue cone about the surface normal is equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{blue}} = \frac{1}{\pi} \int_{0}^{2\pi} \int_{0}^{\frac{\pi}{6}} \cos\!\theta \sin\!\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \frac{1}{4}$$&#xD;&#xA;&#xD;&#xA;The normalized weight of the other cones is approximately equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{purple|red|green|orange|brown}} \approx \frac{1-\hat{W}_{\mathrm{blue}}}{5} = \frac{3}{20}$$&#xD;&#xA;&#xD;&#xA;For a specular BRDF, one typically uses a single cone with a direction, $2 \left(\hat{n} \cdot \hat\omega_o\right) \hat{n}-\hat\omega_o$ (i.e. reflected direction of $\hat\omega_o$ about $\hat{n}$, and an aperture based on the roughness of the surface material.&#xD;&#xA;&#xD;&#xA;# Voxel Cone Tracing&#xD;&#xA;&#xD;&#xA;$L_{v,c}$ is computed using voxel cone tracing, which can be implemented by marching the mip-mapped 3D voxel texture in UVW texture space.&#xD;&#xA;&#xD;&#xA;Our accumulated radiance (red, green, blue channels) and opacity (alpha channel) are initialized to zero. &#xD;&#xA;&#xD;&#xA;    Lv ← [0, 0, 0, 0]&#xD;&#xA;&#xD;&#xA;Our cone marching distance is initialized to an offset to avoid sampling the self emission associated with the emissive surface and the direct illumination associated with the point lights twice. We need to basically skip the voxel containing the surface position for which the outgoing radiance needs to be estimated.&#xD;&#xA;&#xD;&#xA;    distance ← voxel_offset to avoid sampling the direct illumination twice.&#xD;&#xA;&#xD;&#xA;    while Lv.alpha &lt; 1:&#xD;&#xA;    	compute diameter&#xD;&#xA;    	compute mip_level&#xD;&#xA;    	compute position at distance&#xD;&#xA;    	if mip_level &gt;= max_mip_level or position ∉ [0,1]^3&#xD;&#xA;    	    break&#xD;&#xA;    	sample Lv_k(position, mip_level)&#xD;&#xA;    	Lv ← Lv+(1-Lv.alpha) Lv_k       // blend equation&#xD;&#xA;    	distance ← distance + cone_step // marching&#xD;&#xA;    return Lv&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TbALB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dGx7V.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20891" PostHistoryTypeId="5" PostId="7937" RevisionGUID="0810c673-e614-4eeb-931e-6fd3b7d57753" CreationDate="2018-08-18T18:37:05.487" UserId="2287" Comment="added 74 characters in body" Text="# Illumination components&#xD;&#xA;&#xD;&#xA;If the scenes only contain point lights (e.g., omni lights, spotlights, etc.) and emissive surfaces, the illumination contributions at a surface position, $x$, are computed as follows:&#xD;&#xA;&#xD;&#xA; 1. The self emission associated with the emissive surface (i.e. 0 bounces/surface interactions) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 2. The direct illumination associated with the point lights (i.e. 1 bounce/surface interaction) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 3. The direct illumination associated with the emissive surface (i.e. 1 bounce/surface interaction) is obtained from the scene's voxelization using voxel cone tracing;&#xD;&#xA; 4. The indirect illumination associated with the point lights (i.e. 2 bounces/surface interactions) is obtained from the scene's voxelization using voxel cone tracing.&#xD;&#xA;&#xD;&#xA;(By computing the diffuse illumination for all the voxels from the scene's voxelization using voxel cone tracing, the diffuse illumination from additional bounces/surface interactions can be accumulated inside the voxels. This requires each voxel to store (an approximation) to the normal distribution of the scene's surfaces as well overlapping those voxels.)&#xD;&#xA;&#xD;&#xA;# Illumination from the scene's voxelization (3)-(4)&#xD;&#xA;&#xD;&#xA;The outgoing radiance obtained from the scene's voxelization (subscript $v$) using ray tracing (subscript $r$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \int_\Omega f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a diffuse BRDF $f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) = \frac{k_d}{\pi}$:&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \int_\Omega L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a partitioning of $\Omega$ in $N$ disjunct subdomains, $\Omega_j$, (e.g., $\approx$ cones) (i.e. $\Omega_1 \cup~...~\cup \Omega_N = \Omega$ with $\Omega_i \cap \Omega_j = \emptyset$ for each $i \ne j$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \sum_{j = 1}^{N} \int_{\Omega_{j}}  L_{v,r}\!\left(x, \hat\omega_{j,i}\right) \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;Relying on a single cone (subscript $c$) with a direction, $\hat\omega_{j}$, instead of individual rays for each subdomain, $\Omega_j$: &#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx \frac{k_d}{\pi} \sum_{j = 1}^{N} L_{v,c}\!\left(x, \hat\omega_{j}\right) \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$W_j = \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$\hat{W}_j = \frac{W_j}{\pi}$$&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx k_d \sum_{j = 1}^{N} \hat{W}_j L_{v,c}\!\left(x, \hat\omega_{j}\right)$$&#xD;&#xA;&#xD;&#xA;We can use for example the following six cones, each with an aperture of $\frac{\pi}{6}$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The normalized weight of the blue cone about the surface normal is equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{blue}} = \frac{1}{\pi} \int_{0}^{2\pi} \int_{0}^{\frac{\pi}{6}} \cos\!\theta \sin\!\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \frac{1}{4}$$&#xD;&#xA;&#xD;&#xA;The normalized weight of the other cones is approximately equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{purple|red|green|orange|brown}} \approx \frac{1-\hat{W}_{\mathrm{blue}}}{5} = \frac{3}{20}$$&#xD;&#xA;&#xD;&#xA;For a specular BRDF, one typically uses a single cone with a direction, $2 \left(\hat{n} \cdot \hat\omega_o\right) \hat{n}-\hat\omega_o$ (i.e. reflected direction of $\hat\omega_o$ about $\hat{n}$, and an aperture based on the roughness of the surface material.&#xD;&#xA;&#xD;&#xA;# Voxel Cone Tracing&#xD;&#xA;&#xD;&#xA;$L_{v,c}$ is computed using voxel cone tracing, which can be implemented by marching the mip-mapped 3D voxel texture in UVW texture space.&#xD;&#xA;&#xD;&#xA;Our accumulated radiance (red, green, blue channels) and opacity (alpha channel) are initialized to zero. &#xD;&#xA;&#xD;&#xA;    Lv ← [0, 0, 0, 0]&#xD;&#xA;&#xD;&#xA;Our cone marching distance is initialized to an offset to avoid sampling the self emission associated with the emissive surface and the direct illumination associated with the point lights twice. We need to basically skip the voxel containing the surface position for which the outgoing radiance needs to be estimated.&#xD;&#xA;&#xD;&#xA;    distance ← voxel_offset to avoid sampling the direct illumination twice.&#xD;&#xA;&#xD;&#xA;Marching continues until we reach an accumulated opacity of 1 or more:&#xD;&#xA;&#xD;&#xA;    while Lv.alpha &lt; 1:&#xD;&#xA;    	compute diameter (i.e. cone voxel footprint)&#xD;&#xA;    	compute mip_level&#xD;&#xA;    	compute position at distance&#xD;&#xA;    	if mip_level &gt;= max_mip_level or position ∉ [0,1]^3&#xD;&#xA;    	    break&#xD;&#xA;    	sample Lv_k(position, mip_level)&#xD;&#xA;    	Lv ← Lv + (1-Lv.alpha) * Lv_k   // blend equation&#xD;&#xA;    	distance ← distance + cone_step // marching -&gt; diameter and mip_level will increase&#xD;&#xA;    return Lv&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TbALB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dGx7V.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20893" PostHistoryTypeId="5" PostId="7929" RevisionGUID="f5245964-c0b9-49bd-b2cf-d3befbeeb2b7" CreationDate="2018-08-18T20:07:36.433" UserDisplayName="user7220" Comment="Corrected links" Text="I am trying to implement a simple path tracer with next-event estimation in Java. The general idea is to trace a ray through the scene as usual (using a cosine distribution to determine the next random direction at every bounce), while also taking the direct illumination into account at every bounce. I think I have most pieces of the puzzle available, but I can't fit them together correctly.&#xD;&#xA;&#xD;&#xA;Here is how I shade matte objects: add the direct illumination to the radiance coming from a random ray (chosen according to a cosine distribution), the latter multiplied by the BRDF.&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, HybridPathTracer tracer, int length) {&#xD;&#xA;		cosinusSampler sampler = new cosinusSampler(1);&#xD;&#xA;		Point sample = sampler.computeSample();&#xD;&#xA;&#xD;&#xA;		Vector w = shading.getIntersectionPoint().getNormal();&#xD;&#xA;		Random PRNG = new Random();&#xD;&#xA;		Vector r = new Vector(PRNG.nextDouble(), PRNG.nextDouble(), PRNG.nextDouble()).normalize();&#xD;&#xA;		Vector v = r.cross(w);&#xD;&#xA;		Vector u = v.cross(w);&#xD;&#xA;		Vector wi = u.scale(sample.x).add(v.scale(sample.y)).add(w.scale(sample.z));&#xD;&#xA;		Ray ray = new Ray(shading.getIntersectionPoint().toPoint(shading.getRay()), wi);&#xD;&#xA;		RGBSpectrum reflection = tracer.trace(ray, length + 1);&#xD;&#xA;		RGBSpectrum brdf = shading.getColour().scale(getDiffuseReflection());&#xD;&#xA;		return shade(shading).add(brdf.multiply(reflection));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;When a ray reaches an emissive material, black is returned, unless the path length is equal to 1:&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shadePath(Shading shading, HybridPathTracer tracer, int length) {&#xD;&#xA;		Ray ray = shading.getRay();&#xD;&#xA;		Vector n = shading.getIntersectionPoint().getNormal();&#xD;&#xA;&#xD;&#xA;		if (length == 1 &amp;&amp; n.dot(ray.direction) &lt; 0) {&#xD;&#xA;			return getTexture().getColour();&#xD;&#xA;		} else {&#xD;&#xA;			return RGBSpectrum.BLACK;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I read [Progressive Path Tracing with Explicit Light Sampling | Computer Graphics][1] and thought that I was using the same idea in my code, but I must be doing something wrong, because my images are getting too bright when the maximal path length increases (see the examples for maximal length 2, 4 and 6 underneath). What is the problem?&#xD;&#xA;&#xD;&#xA;[![Maximal length 2][2]][2]&#xD;&#xA;[![Maximal length 4][3]][3]&#xD;&#xA;[![Maximal length 6][4]][4]&#xD;&#xA;&#xD;&#xA;**Note:** I know I should also consider some edge cases for specular surfaces, but maybe it's better to ignore those first and focus on matte objects. (I think I have prepared my code for specular surfaces anyway.) My shade function for direct illumination of matte objects should be fine, but here it is for reference:&#xD;&#xA;&#xD;&#xA;    public RGBSpectrum shade(Shading shading) {&#xD;&#xA;		RGBSpectrum colour = shading.getColour();&#xD;&#xA;		double L = 0;&#xD;&#xA;		final Point intersection = shading.getIntersectionPoint().toPoint(shading.getRay());&#xD;&#xA;&#xD;&#xA;		for (Light light : shading.getScene().getLights()) {&#xD;&#xA;			double l = 0;&#xD;&#xA;&#xD;&#xA;			for (Point sample : light.computeSamples()) {&#xD;&#xA;				Vector wi = sample.subtract(intersection);&#xD;&#xA;				double lengthSquared = wi.lengthSquared();&#xD;&#xA;				wi = wi.normalize();&#xD;&#xA;				double cos = shading.getIntersectionPoint().getNormal().dot(wi);&#xD;&#xA;&#xD;&#xA;				if (cos &gt; 0) {&#xD;&#xA;					Ray shadowRay = new Ray(intersection, wi);&#xD;&#xA;&#xD;&#xA;					if (!light.inShadow(shadowRay, shading.getScene())) {&#xD;&#xA;						if (light instanceof PointLight) {&#xD;&#xA;							double denom = 4 * Math.PI * lengthSquared;&#xD;&#xA;							l += light.getPower() * cos / denom;&#xD;&#xA;						} else if (light instanceof RectangularLight) {&#xD;&#xA;							Rectangle rectangle = ((RectangularLight) light).getRectangle();&#xD;&#xA;							double cosp = -wi.dot(rectangle.getNormal());&#xD;&#xA;							l += light.getPower() * cos * cosp * rectangle.getArea() / lengthSquared;&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			L += l / light.getSamplesNumber();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return colour.scale(getAmbientReflection() + L * getDiffuseReflection());&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/5153/9170&#xD;&#xA;  [2]: https://i.stack.imgur.com/yXEMz.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/iodfO.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3qgye.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20894" PostHistoryTypeId="24" PostId="7929" RevisionGUID="f5245964-c0b9-49bd-b2cf-d3befbeeb2b7" CreationDate="2018-08-18T20:07:36.433" Comment="Proposed by 7220 approved by 9170 edit id of 431" ContentLicense="CC BY-SA 4.0" />
  <row Id="20895" PostHistoryTypeId="5" PostId="7937" RevisionGUID="b587d039-a69a-4eb3-bb4b-9fc1806f94d0" CreationDate="2018-08-18T20:26:03.723" UserId="2287" Comment="deleted 49 characters in body" Text="# Illumination components&#xD;&#xA;&#xD;&#xA;If the scenes only contain point lights (e.g., omni lights, spotlights, etc.) and emissive surfaces, the illumination contributions at a surface position, $x$, are computed as follows:&#xD;&#xA;&#xD;&#xA; 1. The self emission associated with the emissive surface (i.e. 0 bounces/surface interactions) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 2. The direct illumination associated with the point lights (i.e. 1 bounce/surface interaction) is computed as usual (without using the voxelization; as is the case for adding this contribution to the scene's voxelization);&#xD;&#xA; 3. The direct illumination associated with the emissive surface (i.e. 1 bounce/surface interaction) is obtained from the scene's voxelization using voxel cone tracing;&#xD;&#xA; 4. The indirect illumination associated with the point lights (i.e. 2 bounces/surface interactions) is obtained from the scene's voxelization using voxel cone tracing.&#xD;&#xA;&#xD;&#xA;(By computing the diffuse illumination for all the voxels from the scene's voxelization using voxel cone tracing, the diffuse illumination from additional bounces/surface interactions can be accumulated inside the voxels. This requires each voxel to store (an approximation) to the normal distribution of the scene's surfaces as well overlapping those voxels.)&#xD;&#xA;&#xD;&#xA;# Illumination from the scene's voxelization (3)-(4)&#xD;&#xA;&#xD;&#xA;The outgoing radiance obtained from the scene's voxelization (subscript $v$) using ray tracing (subscript $r$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \int_\Omega f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a diffuse BRDF $f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) = \frac{k_d}{\pi}$:&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \int_\Omega L_{v,r}\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i$$&#xD;&#xA;&#xD;&#xA;For a partitioning of $\Omega$ in $N$ disjunct subdomains, $\Omega_j$, (e.g., $\approx$ cones) (i.e. $\Omega_1 \cup~...~\cup \Omega_N = \Omega$ with $\Omega_i \cap \Omega_j = \emptyset$ for each $i \ne j$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \sum_{j = 1}^{N} \int_{\Omega_{j}}  L_{v,r}\!\left(x, \hat\omega_{j,i}\right) \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;Relying on a single cone (subscript $c$) with a direction, $\hat\omega_{j}$, instead of individual rays for each subdomain, $\Omega_j$: &#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx \frac{k_d}{\pi} \sum_{j = 1}^{N} L_{v,c}\!\left(x, \hat\omega_{j}\right) \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$W_j = \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$\hat{W}_j = \frac{W_j}{\pi}$$&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx k_d \sum_{j = 1}^{N} \hat{W}_j L_{v,c}\!\left(x, \hat\omega_{j}\right)$$&#xD;&#xA;&#xD;&#xA;We can use for example the following six cones, each with an aperture of $\frac{\pi}{6}$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The normalized weight of the blue cone about the surface normal is equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{blue}} = \frac{1}{\pi} \int_{0}^{2\pi} \int_{0}^{\frac{\pi}{6}} \cos\!\theta \sin\!\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \frac{1}{4}$$&#xD;&#xA;&#xD;&#xA;The normalized weight of the other cones is approximately equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{purple|red|green|orange|brown}} \approx \frac{1-\hat{W}_{\mathrm{blue}}}{5} = \frac{3}{20}$$&#xD;&#xA;&#xD;&#xA;For a specular BRDF, one typically uses a single cone with a direction, $2 \left(\hat{n} \cdot \hat\omega_o\right) \hat{n}-\hat\omega_o$ (i.e. reflected direction of $\hat\omega_o$ about $\hat{n}$, and an aperture based on the roughness of the surface material.&#xD;&#xA;&#xD;&#xA;# Voxel Cone Tracing&#xD;&#xA;&#xD;&#xA;$L_{v,c}$ is computed using voxel cone tracing, which can be implemented by marching the mip-mapped 3D voxel texture in UVW texture space.&#xD;&#xA;&#xD;&#xA;Our accumulated radiance (red, green, blue channels) and opacity (alpha channel) are initialized to zero. &#xD;&#xA;&#xD;&#xA;    Lv ← [0, 0, 0, 0]&#xD;&#xA;&#xD;&#xA;Our cone marching distance is initialized to an offset to avoid sampling the self emission associated with the emissive surface and the direct illumination associated with the point lights twice. We need to basically skip the voxel containing the surface position for which the outgoing radiance needs to be estimated.&#xD;&#xA;&#xD;&#xA;    distance ← voxel_offset&#xD;&#xA;&#xD;&#xA;Marching continues until we reach an accumulated opacity of 1 or more:&#xD;&#xA;&#xD;&#xA;    while Lv.alpha &lt; 1:&#xD;&#xA;    	compute diameter (i.e. cone voxel footprint)&#xD;&#xA;    	compute mip_level&#xD;&#xA;    	compute position at distance&#xD;&#xA;    	if mip_level &gt;= max_mip_level or position ∉ [0,1]^3&#xD;&#xA;    	    break&#xD;&#xA;    	sample Lv_k(position, mip_level)&#xD;&#xA;    	Lv ← Lv + (1-Lv.alpha) * Lv_k   // blend equation&#xD;&#xA;    	distance ← distance + cone_step // marching -&gt; diameter and mip_level will increase&#xD;&#xA;    return Lv&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TbALB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dGx7V.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20897" PostHistoryTypeId="2" PostId="7938" RevisionGUID="c6a92a9a-99a4-4a67-b099-d147434e3e6b" CreationDate="2018-08-18T22:51:50.560" UserId="4908" Text="&gt; This seems, however, completely unrelated since no gamma correction is involved yet at this stage in the code.&#xD;&#xA;&#xD;&#xA;The values are indeed not gamma corrected. Earlier in the presentation (On page 32) you have the toInt function which does the gamma correction. This function is called when the image is written to a file.&#xD;&#xA;&#xD;&#xA;Then the clamping itself.&#xD;&#xA;If we have a list of 5 samples.&#xD;&#xA;&#xD;&#xA;    0.1; 0.4; 0.2; 0.8; 0.6&#xD;&#xA;&#xD;&#xA;It averages to $0.42$. However, if one samples becomes very bright.&#xD;&#xA;&#xD;&#xA;    0.1; 0.4; 8.0; 0.8; 0.6&#xD;&#xA;&#xD;&#xA;The average would become $1.98$. That is a lot brighter. Because we take random samples, it could be that these two averages are neighbouring pixels. This would cause a few pixels in the entire image to be much brighter than their neighbours. This is called a **firefly**. These fireflies are often not wanted, as they stick out in the image and make it look a lot more noisy. Therefore we want to try and remove these fireflies.&#xD;&#xA;&#xD;&#xA;An example image of this can be found in [blender's cycles documentation here][1]. The bright pixels are fireflies and are unwanted.[![Image with fireflies][2]][2]&#xD;&#xA;&#xD;&#xA;There are three ways to remove a firefly.&#xD;&#xA;&#xD;&#xA; 1. Add more samples. By adding more samples, you get a truer image and that one bright sample would end up with less influence. This does however take longer to render.&#xD;&#xA; 2. Some sort of denoising algorithm. The algorithm could find these fireflies and remove them. However, it will almost always change other parts of the image which is often unwanted, and there is also no room for it in smallpt.&#xD;&#xA; 3. Discarding the bright sample or similar. This bright sample is the culprit of the problem and we could always decide to just ignore it. However, that bright sample is there for a reason and removing it would most of the times not be the greatest idea (it also makes things more complicated). Clamping however would still allow us to somewhat discard the bright sample without actually discarding it and is very simple and easy to implement. We just make it not have such a big influence on the image.&#xD;&#xA;&#xD;&#xA;Clamping is often the choice for most render engines. If you would look at any commercial render engine, or even hobby path tracers, they allow you to clamp the samples. Normally you clamp the individual samples instead of the sub-pixels and more specifically you clamp indirect samples with its own clamping value, but they have about the same effect.&#xD;&#xA;&#xD;&#xA;This clamping does change the image as it makes some areas or all darker since it removes energy (by clamping the color values) from the scene. This would become unbiased, yet it is often done (and almost always available in unbiased render engines) simply because it produces visually nicer images, because there are no fireflies and fireflies are generally worse than noise. Often you would not notice any artifacts when clamping, other than the removed fireflies.&#xD;&#xA;&#xD;&#xA;In the case of smallpt, clamping it between 0.0 and 1.0 seems to work well for that one scene. However, I do recommend to just tinker with the code and render two images out for yourself, one with clamping and one without.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.blender.org/manual/en/dev/render/cycles/optimizations/reducing_noise.html#clamp-fireflies&#xD;&#xA;  [2]: https://i.stack.imgur.com/DKQnc.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20898" PostHistoryTypeId="50" PostId="7716" RevisionGUID="76da1908-d4e9-4bcc-9833-f9fd8a5edc91" CreationDate="2018-08-19T02:00:35.080" UserId="-1" />
  <row Id="20900" PostHistoryTypeId="5" PostId="7919" RevisionGUID="c9b2e6ca-d9db-4514-94cb-e6d43a9d328e" CreationDate="2018-08-19T06:08:55.873" UserDisplayName="user7220" Comment="Corrected links" Text="So I want to path trace a Cornel Box scene, but I don't understand the values given here in section 2 and 3.&#xD;&#xA;&#xD;&#xA;[Cornell Box Data | Cornell University Program of Computer Graphics][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;No.2 Lists surface reflectances with respect to different wavelengths but I'm not using wavelengths. I thought this was done in spectral path/ray tracing where we are using photometry instead of radiometry.&#xD;&#xA;&#xD;&#xA;Similarly No.3 lists Light properties though I don't understand what do the values in the `light` column (0, 8, 15.6, 18.4) suggest.&#xD;&#xA;&#xD;&#xA;I was merely expecting the specular and diffuse reflectivity in all 3 channels for each of the colors red, green and white.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.graphics.cornell.edu/online/box/data.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="20901" PostHistoryTypeId="24" PostId="7919" RevisionGUID="c9b2e6ca-d9db-4514-94cb-e6d43a9d328e" CreationDate="2018-08-19T06:08:55.873" Comment="Proposed by 7220 approved by 6046 edit id of 432" ContentLicense="CC BY-SA 4.0" />
  <row Id="20902" PostHistoryTypeId="5" PostId="7937" RevisionGUID="2900f108-9606-48e0-b500-79c699790053" CreationDate="2018-08-19T11:33:26.277" UserId="2287" Comment="added 71 characters in body" Text="# Illumination components&#xD;&#xA;&#xD;&#xA;If our scenes only contain point lights (e.g., omni lights, spotlights, etc.) and emissive surfaces, the illumination contributions at a surface position, $x$, are computed as follows:&#xD;&#xA;&#xD;&#xA; 1. The self emission associated with the emissive surface (i.e. 0 bounces/surface interactions) is computed as usual without using the scene's voxelization (as is the case for adding this illumination contribution to the scene's voxelization);&#xD;&#xA; 2. The direct illumination associated with the point lights (i.e. 1 bounce/surface interaction) is computed as usual without using the scene's voxelization (as is the case for adding this illumination contribution to the scene's voxelization);&#xD;&#xA; 3. The direct illumination associated with the emissive surfaces (i.e. 1 bounce/surface interaction) is obtained from the scene's voxelization using voxel cone tracing;&#xD;&#xA; 4. The indirect illumination associated with the point lights (i.e. 2 bounces/surface interactions) is obtained from the scene's voxelization using voxel cone tracing.&#xD;&#xA;&#xD;&#xA;By computing the diffuse illumination for all the voxels from the scene's voxelization using voxel cone tracing, the diffuse illumination from additional bounces/surface interactions can be (optionally) accumulated inside the voxels. This requires each voxel to store (an approximation) to the normal distribution of the scene's surfaces overlapping those voxels as well.&#xD;&#xA;&#xD;&#xA;# Illumination from the scene's voxelization (3)-(4)&#xD;&#xA;&#xD;&#xA;The outgoing radiance obtained from the scene's voxelization ($L_v$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \int_\Omega f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) L_v\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i.$$&#xD;&#xA;&#xD;&#xA;For a **diffuse BRDF** $f_{r}\!\left(x, \hat\omega_o, \hat\omega_i\right) = \frac{k_d}{\pi}$:&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \int_\Omega L_v\!\left(x, \hat\omega_i\right) \left(\hat{n} \cdot \hat\omega_i\right) \mathrm{d}\hat\omega_i.$$&#xD;&#xA;&#xD;&#xA;For a partitioning of $\Omega$ in $N$ disjunct subdomains, $\Omega_j$, (e.g., $\approx$ cones) (i.e. $\Omega_1 \cup~...~\cup \Omega_N = \Omega$ and $\Omega_i \cap \Omega_j = \emptyset$ for each $i \ne j$):&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) = \frac{k_d}{\pi} \sum_{j = 1}^{N} \int_{\Omega_{j}}  L_v\!\left(x, \hat\omega_{j,i}\right) \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}.$$&#xD;&#xA;&#xD;&#xA;Relying on a single cone with a direction, $\hat\omega_{j}$, and an aperture, $\alpha_{j}$, instead of individual rays with a direction, $\hat\omega_{j,i}$, for each subdomain, $\Omega_j$: &#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx \frac{k_d}{\pi} \sum_{j = 1}^{N} L_v\!\left(x, \hat\omega_{j}, \alpha_{j}\right) \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$\hat{W}_j = \frac{1}{\pi} \int_{\Omega_{j}} \left(\hat{n} \cdot \hat\omega_{j,i}\right) \mathrm{d}\hat\omega_{j,i}$$&#xD;&#xA;&#xD;&#xA;$$L_o\!\left(x, \hat\omega_o\right) \approx k_d \sum_{j = 1}^{N} \hat{W}_j L_v\!\left(x, \hat\omega_{j}, \alpha_{j}\right).$$&#xD;&#xA;&#xD;&#xA;We can use for example the following six cones, each with an aperture of $\frac{\pi}{6}$.&#xD;&#xA;&#xD;&#xA;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;https://i.stack.imgur.com/TbALB.png&quot;&gt;&lt;/p&gt;&#xD;&#xA;&#xD;&#xA;The normalized weight of the blue cone about the surface normal is equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{blue}} = \frac{1}{\pi} \int_{0}^{2\pi} \int_{0}^{\frac{\pi}{6}} \cos\!\theta \sin\!\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \frac{1}{4}.$$&#xD;&#xA;&#xD;&#xA;The normalized weight of the other cones is approximately equal to:&#xD;&#xA;&#xD;&#xA;$$\hat{W}_{\mathrm{purple|red|green|orange|brown}} \approx \frac{1-\hat{W}_{\mathrm{blue}}}{5} = \frac{3}{20}.$$&#xD;&#xA;&#xD;&#xA;For a **specular BRDF**, one typically uses a single cone with a direction, $2 \left(\hat{n} \cdot \hat\omega_o\right) \hat{n}-\hat\omega_o$ (i.e. reflected direction of $\hat\omega_o$ about $\hat{n}$), and an aperture based on the roughness of the surface material.&#xD;&#xA;&#xD;&#xA;# Voxel Cone Tracing&#xD;&#xA;&#xD;&#xA;$L_v\!\left(x, \hat\omega_{j}, \alpha_{j}\right)$ is computed using voxel cone tracing, which can be implemented by marching the mip-mapped 3D voxel texture in UVW texture space.&#xD;&#xA;&#xD;&#xA;Our accumulated radiance (red, green, blue channels) and opacity (alpha channel) are initialized to zero. &#xD;&#xA;&#xD;&#xA;    Lv ← [0, 0, 0, 0]&#xD;&#xA;&#xD;&#xA;Our cone marching distance is initialized to an offset to avoid sampling the self emission associated with the emissive surfaces and the direct illumination associated with the point lights twice. We need to basically skip the voxel containing the surface position for which the outgoing radiance needs to be estimated.&#xD;&#xA;&#xD;&#xA;    distance ← voxel_offset&#xD;&#xA;&#xD;&#xA;Marching continues until we reach an accumulated opacity of 1 or more:&#xD;&#xA;&#xD;&#xA;    while Lv.alpha &lt; 1:&#xD;&#xA;    	compute diameter (i.e. cone voxel footprint)&#xD;&#xA;    	compute mip_level&#xD;&#xA;    	compute position at distance&#xD;&#xA;    	if mip_level &gt;= max_mip_level or position ∉ [0,1]^3&#xD;&#xA;    	    break&#xD;&#xA;    	sample Lv_step(position, mip_level)&#xD;&#xA;    	Lv ← Lv + (1-Lv.alpha) * Lv_step // blend equation&#xD;&#xA;    	distance ← distance + cone_step  // marching -&gt; diameter and mip_level will increase&#xD;&#xA;    return Lv&#xD;&#xA;&#xD;&#xA;&lt;p align=&quot;center&quot;&gt;&lt;img src=&quot;https://i.stack.imgur.com/dGx7V.png&quot;&gt;&lt;/p&gt;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20903" PostHistoryTypeId="5" PostId="7938" RevisionGUID="fdb0c2e9-c6bb-4281-8039-0c1f49cbd041" CreationDate="2018-08-19T16:32:11.233" UserId="2287" Comment="formatting" Text="&gt; This seems, however, completely unrelated since no gamma correction is involved yet at this stage in the code.&#xD;&#xA;&#xD;&#xA;The values are indeed not gamma corrected. Earlier in the presentation (On page 32) you have the toInt function which does the gamma correction. This function is called when the image is written to a file.&#xD;&#xA;&#xD;&#xA;Then the clamping itself.&#xD;&#xA;If we have a list of 5 samples.&#xD;&#xA;&#xD;&#xA;    0.1; 0.4; 0.2; 0.8; 0.6&#xD;&#xA;&#xD;&#xA;It averages to 0.42. However, if one samples becomes very bright.&#xD;&#xA;&#xD;&#xA;    0.1; 0.4; 8.0; 0.8; 0.6&#xD;&#xA;&#xD;&#xA;The average would become 1.98. That is a lot brighter. Because we take random samples, it could be that these two averages are neighboring pixels. This would cause a few pixels in the entire image to be much brighter than their neighbors. This is called a **firefly**. These fireflies are often not wanted, as they stick out in the image and make it look a lot more noisy. Therefore we want to try and remove these fireflies.&#xD;&#xA;&#xD;&#xA;An example image of this can be found in [blender's cycles documentation here][1]. The bright pixels are fireflies and are unwanted.[![Image with fireflies][2]][2]&#xD;&#xA;&#xD;&#xA;There are three ways to remove a firefly.&#xD;&#xA;&#xD;&#xA; 1. Add more samples. By adding more samples, you get a truer image and that one bright sample would end up with less influence. This does however take longer to render.&#xD;&#xA; 2. Some sort of denoising algorithm. The algorithm could find these fireflies and remove them. However, it will almost always change other parts of the image which is often unwanted, and there is also no room for it in smallpt.&#xD;&#xA; 3. Discarding the bright sample or similar. This bright sample is the culprit of the problem and we could always decide to just ignore it. However, that bright sample is there for a reason and removing it would most of the times not be the greatest idea (it also makes things more complicated). Clamping however would still allow us to somewhat discard the bright sample without actually discarding it and is very simple and easy to implement. We just make it not have such a big influence on the image.&#xD;&#xA;&#xD;&#xA;Clamping is often the choice for most render engines. If you would look at any commercial render engine, or even hobby path tracers, they allow you to clamp the samples. Normally you clamp the individual samples instead of the sub-pixels and more specifically you clamp indirect samples with its own clamping value, but they have about the same effect.&#xD;&#xA;&#xD;&#xA;This clamping does change the image as it makes some areas or all darker since it removes energy (by clamping the color values) from the scene. This would become unbiased, yet it is often done (and almost always available in unbiased render engines) simply because it produces visually nicer images, because there are no fireflies and fireflies are generally worse than noise. Often you would not notice any artifacts when clamping, other than the removed fireflies.&#xD;&#xA;&#xD;&#xA;In the case of smallpt, clamping it between 0.0 and 1.0 seems to work well for that one scene. However, I do recommend to just tinker with the code and render two images out for yourself, one with clamping and one without.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.blender.org/manual/en/dev/render/cycles/optimizations/reducing_noise.html#clamp-fireflies&#xD;&#xA;  [2]: https://i.stack.imgur.com/DKQnc.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20904" PostHistoryTypeId="24" PostId="7938" RevisionGUID="fdb0c2e9-c6bb-4281-8039-0c1f49cbd041" CreationDate="2018-08-19T16:32:11.233" Comment="Proposed by 2287 approved by 4908 edit id of 433" ContentLicense="CC BY-SA 4.0" />
  <row Id="20905" PostHistoryTypeId="4" PostId="5823" RevisionGUID="22fdd313-31fc-4916-87ee-73dbe164a4b2" CreationDate="2018-08-19T16:55:54.117" UserId="2287" Comment="edited title" Text="How does voxel cone tracing work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20909" PostHistoryTypeId="2" PostId="7940" RevisionGUID="93c1b8e2-1f69-4845-bb4f-78a42730a298" CreationDate="2018-08-19T21:47:37.213" UserId="9218" Text="I have used a library to perform a Constructive Solid Geometry difference operation, which has left me with orphaned geometry as well as imperfections.&#xD;&#xA;&#xD;&#xA;Is there an approach/algorithm that will allow me clean the geometry so all that remains is the two cuboids?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dWM1b.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="20910" PostHistoryTypeId="1" PostId="7940" RevisionGUID="93c1b8e2-1f69-4845-bb4f-78a42730a298" CreationDate="2018-08-19T21:47:37.213" UserId="9218" Text="Remove orphaned geometry after Constructive Solid Geometry operation" ContentLicense="CC BY-SA 4.0" />
  <row Id="20911" PostHistoryTypeId="3" PostId="7940" RevisionGUID="93c1b8e2-1f69-4845-bb4f-78a42730a298" CreationDate="2018-08-19T21:47:37.213" UserId="9218" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20916" PostHistoryTypeId="5" PostId="7934" RevisionGUID="2a3bc2a5-9d0e-49a2-a4b4-6412850c5199" CreationDate="2018-08-20T06:19:07.423" UserId="9194" Comment="Added answer for second question" Text="Only one path per sample.&#xD;&#xA;&#xD;&#xA;If you had 64 bounces per first hit and 64 per second hit and so forth you'd never get an image.&#xD;&#xA;&#xD;&#xA;Edit: And that's why you need to sample each pixel so many times (easily more than 1024 samples) in order to get it to converge, ie get rid of the noise.&#xD;&#xA;&#xD;&#xA;As per 2) (from comment below) The 64 primary rays will not hit the same object in the same spot so you will have to calculate everything for each sample." ContentLicense="CC BY-SA 4.0" />
  <row Id="20917" PostHistoryTypeId="2" PostId="7942" RevisionGUID="afea3fe2-e3fa-4d38-987f-c2fa8e0f75e6" CreationDate="2018-08-20T06:43:40.957" UserId="9194" Text="Iridesence can be seen in several variations: diffraction as seen in CDs and DVDs (see Stam's SIGGRAPH 1999 paper on this), phase shifting and modulation in multi-layered surfaces as you see in oilspills on water, or structural coloration as you see in butterfly wings. (Also there is the related pearlescence). However, it's not trivial in any way, probably worth a paper or two." ContentLicense="CC BY-SA 4.0" />
  <row Id="20921" PostHistoryTypeId="50" PostId="7730" RevisionGUID="ca8ae509-7ad9-42c5-b1f6-923d418290fa" CreationDate="2018-08-20T22:01:25.210" UserId="-1" />
  <row Id="20923" PostHistoryTypeId="5" PostId="2038" RevisionGUID="4d7a9e13-bdc3-4839-922b-950bac9157c4" CreationDate="2018-08-21T09:45:54.990" UserId="209" Comment="Minor spelling corrections" Text="This is called subpixel rendering.&#xD;&#xA;&#xD;&#xA;The different primary colors in your monitor are not stacked on top of each other. Instead they are arranged near each other. Different monitors have different patterns but most commonly they are aligned so that the colors are side by side. &#xD;&#xA;&#xD;&#xA;If you know the physical arrangement, then you can prepare the image so that you have calculated a different sample position for each color channel. In essence your boosting the resolution of your image so that you are treating each individual color as a separate pixel. &#xD;&#xA;&#xD;&#xA;This, of course, means that you need to know the display orientation and have some data that can be shifted. The image wouldn't be all that useful on other monitors with different pixel alignments. So this is reserved for things that are dynamically generated, most often fonts.&#xD;&#xA;&#xD;&#xA;It also means that when zoomed or presented on a medium with different or no subpixels, the effect will register as a blur. So zooming in on the pixels of a subpixel rendered image is not very good idea. For this reason it migth be a good idea to disable the effect if you make images for others to use and the subpixel alignment is unknown." ContentLicense="CC BY-SA 4.0" />
  <row Id="20924" PostHistoryTypeId="2" PostId="7943" RevisionGUID="72bedaf8-83c1-4afc-9309-3bb9a597d4b5" CreationDate="2018-08-21T10:24:21.260" UserId="6046" Text="So I was reading up on how to sample Rectangular Area lights, and the procedure is pretty straightforward. That is, I can get random points using the equation.&#xD;&#xA;&#xD;&#xA;$ p = X_o + \epsilon_1V_1 + \epsilon_2V_2$&#xD;&#xA;&#xD;&#xA;Where $X_o$ is my corner point for the rectangle and $V_1$ and $V_2$ are the 2 vectors spanning it And the epsilons are the uniform random numbers.&#xD;&#xA;&#xD;&#xA;The thing is almost every where I go, they talk about how the PDF of this sampling is $1/A$ (constant) with the exception of 1 place discussed below, and that when calculating the radiance coming from this area light when sampled by this way we should thus multiply the whole thing by the Area of the rectangle. &#xD;&#xA;&#xD;&#xA;However when I check their algorithms, they leave out this Area factor.&#xD;&#xA;&#xD;&#xA;**Compute Graphics Principles and Practice** and **Fundamental of Computer Graphics by Peter Shire;ey** describes the calculation of the radiance returned by sampling a point on the area light, (Notice the black underlined factor describing Area of the jth light source)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jEkzn.png&#xD;&#xA;&#xD;&#xA;However both of these books when describing their pseudocode, leave out this $Area$ factor.&#xD;&#xA;&#xD;&#xA;However when I read Peter Shirley's research paper regarding Direct illumination techniques, He gives the PDF for rectangular Area lights as&#xD;&#xA;&#xD;&#xA;$ 1/ \frac{||V_1 \times V_2||}{2}$&#xD;&#xA;&#xD;&#xA;Which is the area of the triangle not a rectangle.&#xD;&#xA;&#xD;&#xA;So ultimately I have 2 questions.&#xD;&#xA;&#xD;&#xA;**1) What is the correct PDF term for rectangular area lights?&#xD;&#xA;2) Do I need to multiply this term when calculating the radiance emitted from this light source.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="20925" PostHistoryTypeId="1" PostId="7943" RevisionGUID="72bedaf8-83c1-4afc-9309-3bb9a597d4b5" CreationDate="2018-08-21T10:24:21.260" UserId="6046" Text="PDF when sampling from Rectangular Area Lights" ContentLicense="CC BY-SA 4.0" />
  <row Id="20926" PostHistoryTypeId="3" PostId="7943" RevisionGUID="72bedaf8-83c1-4afc-9309-3bb9a597d4b5" CreationDate="2018-08-21T10:24:21.260" UserId="6046" Text="|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20927" PostHistoryTypeId="2" PostId="7944" RevisionGUID="d6b94a4f-3f55-45df-b641-15217aca5c91" CreationDate="2018-08-21T18:09:52.720" UserId="6588" Text="The correct PDF for an area light is indeed $1/A$. The reason why you see the area term at the top is because you are importance sampling the light, meaning you need to divide by its PDF. This is a Monte Carlo estimator with one sample. Shirley simplifies this by simply writing $1/(1/A) = A$.&#xD;&#xA;&#xD;&#xA;I am not sure how he got the $1 / \frac{\|V_1 \times V_2\|}{2}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="20928" PostHistoryTypeId="2" PostId="7945" RevisionGUID="5c7543d4-986e-42cf-8584-cb6dc19b1a43" CreationDate="2018-08-21T20:19:36.113" UserId="6092" Text="I want to calculate the average color+opacity of an image. First I thought about just averaging all ARGB values component-wise, but this got really dark on images with a lot of transparency. I also don't think mixing RGB colors is a good idea in general since they are nonlinear due to Gamma or something. I also had a look at HSV/HSB but this seems a pretty stupid idea.&#xD;&#xA;&#xD;&#xA;**So, what is a reasonably physically correct way to average the color of an ARGB image?** I prefer solutions in Java and using 8 bit per color channel. The solution should also take care that the image may have an arbitrary amount of transparent or semi-transparent pixels." ContentLicense="CC BY-SA 4.0" />
  <row Id="20929" PostHistoryTypeId="1" PostId="7945" RevisionGUID="5c7543d4-986e-42cf-8584-cb6dc19b1a43" CreationDate="2018-08-21T20:19:36.113" UserId="6092" Text="Calculate the average color of an image" ContentLicense="CC BY-SA 4.0" />
  <row Id="20930" PostHistoryTypeId="3" PostId="7945" RevisionGUID="5c7543d4-986e-42cf-8584-cb6dc19b1a43" CreationDate="2018-08-21T20:19:36.113" UserId="6092" Text="|image-processing|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20931" PostHistoryTypeId="2" PostId="7946" RevisionGUID="56fe578a-aca4-4a7e-bff9-5c1cb39bbabc" CreationDate="2018-08-21T21:09:06.010" UserId="9216" Text="I’ve been trying to render a texture on the whole screen in OpenGL 4.1 using the Core profile and followed a few tutorials on the matter, but all I have so far is a blank screen.&#xD;&#xA;&#xD;&#xA;I tried using my texture coordinates as color components and got the result I expected so the vertice data must be in order, but using the dimensions of the texture as color components I determined the size of the texture in my shader is 1x1 when it should be 2x2, so I guess I am doing something wrong when uploading it to the GPU.&#xD;&#xA;&#xD;&#xA;This is my pixel data:&#xD;&#xA;&#xD;&#xA;    const GLubyte pixels[] = {&#xD;&#xA;        255, 255, 255, 255,     0, 0, 0, 255,&#xD;&#xA;        0, 0, 0, 255,           255, 255, 255, 255,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is how I load my texture:&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pixels);&#xD;&#xA;&#xD;&#xA;I also tried using a buffer:&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glGenBuffers(1, &amp;texture_buffer);&#xD;&#xA;    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_buffer);&#xD;&#xA;    glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(pixels), pixels, GL_STATIC_DRAW);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)0);&#xD;&#xA;&#xD;&#xA;And this is how I render:&#xD;&#xA;&#xD;&#xA;    glUseProgram(shader_program);&#xD;&#xA;    // Binding my vba and vbo, uploading vertices.&#xD;&#xA;    glUniform1i(texture_location, 0);&#xD;&#xA;    // Enabling vertex attrib arrays.&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    // Drawing arrays, disabling vertex attrib arrays.&#xD;&#xA;&#xD;&#xA;I have also put the whole source file [on pastebin](https://pastebin.com/gmN50u50), it uses GLFW for windowing and does some basic error checking.&#xD;&#xA;&#xD;&#xA;I’d be really grateful if someone could point out what I am missing here.&#xD;&#xA;&#xD;&#xA;Cheers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="20932" PostHistoryTypeId="1" PostId="7946" RevisionGUID="56fe578a-aca4-4a7e-bff9-5c1cb39bbabc" CreationDate="2018-08-21T21:09:06.010" UserId="9216" Text="Issue with texture upload in OpenGL 4.1 Core profile" ContentLicense="CC BY-SA 4.0" />
  <row Id="20933" PostHistoryTypeId="3" PostId="7946" RevisionGUID="56fe578a-aca4-4a7e-bff9-5c1cb39bbabc" CreationDate="2018-08-21T21:09:06.010" UserId="9216" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20934" PostHistoryTypeId="2" PostId="7947" RevisionGUID="5f039ffd-7fe0-4f77-865c-6ff50e0ef179" CreationDate="2018-08-22T02:20:40.710" UserId="3003" Text="Averaging RGB should be correct assuming you do it in linear RGB. If your images are in sRGB, you can remove the gamma correction by doing something like the following for each of the R, G, and B components:&#xD;&#xA;&#xD;&#xA;    float sRGBToLinear(UInt8 component)&#xD;&#xA;    {&#xD;&#xA;        float tempComponent = (float)component / 255.0;&#xD;&#xA;        if (tempComponent &lt;= 0.04045)&#xD;&#xA;        {&#xD;&#xA;            tempComponent = tempComponent / 12.92;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            tempComponent = pow((tempComponent + 0.055) / (1.055), 2.4);&#xD;&#xA;        }&#xD;&#xA;        return tempComponent;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can then average together all of the red values in the image, all of the green values in the image, and all of the blue values in the image after they've been run through the above conversion. You can then do the opposite conversion to get back to sRGB:&#xD;&#xA;&#xD;&#xA;    UInt8 linearRGBTosRGB(float component)&#xD;&#xA;    {&#xD;&#xA;        float tempComponent =  0.0;&#xD;&#xA;        if (component &lt;= 0.00318308)&#xD;&#xA;        {&#xD;&#xA;            tempComponent = 12.92 * component;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            tempComponent = 1.055 * pow(component, 1.0 / 2.4) - 0.055;&#xD;&#xA;        }&#xD;&#xA;        return (UInt8)(tempComponent * 255.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;(My apologies if I've messed up the syntax. I'm a C/C++ programmer and don't know the intricacies of Java.)&#xD;&#xA;&#xD;&#xA;Note that alpha makes things slightly more complicated. If you're using premultiplied alpha, you'll want to un-pre-multiply (in other words divide out the alpha) before calling the above conversions. Something like this:&#xD;&#xA;&#xD;&#xA;    UInt8 unpremultiply(UInt8 component, UInt8 alpha)&#xD;&#xA;    {&#xD;&#xA;        float fAlpha = (float)alpha / 255.0;&#xD;&#xA;        float fComponent = (float)component / 255.0;&#xD;&#xA;        if (fAlpha == 0.0) // May want to make this be if (fAlpha &lt; 1e-5)&#xD;&#xA;        {&#xD;&#xA;            fComponent = 0.0;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            fComponent = fComponent / fAlpha;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return (UInt8)(fComponent * 255.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="20935" PostHistoryTypeId="5" PostId="7943" RevisionGUID="a8f3588f-dd35-4178-af8d-ec24edd2b72d" CreationDate="2018-08-22T02:30:03.747" UserId="6046" Comment="added 6 characters in body" Text="So I was reading up on how to sample Rectangular Area lights, and the procedure is pretty straightforward. That is, I can get random points using the equation.&#xD;&#xA;&#xD;&#xA;$ p = X_o + \epsilon_1V_1 + \epsilon_2V_2$&#xD;&#xA;&#xD;&#xA;Where $X_o$ is my corner point for the rectangle and $V_1$ and $V_2$ are the 2 vectors spanning it And the epsilons are the uniform random numbers.&#xD;&#xA;&#xD;&#xA;The thing is almost every where I go, they talk about how the PDF of this sampling is $1/A$ (constant) with the exception of 1 place discussed below, and that when calculating the radiance coming from this area light when sampled by this way we should thus multiply the whole thing by the Area of the rectangle. &#xD;&#xA;&#xD;&#xA;However when I check their algorithms, they leave out this Area factor.&#xD;&#xA;&#xD;&#xA;**Compute Graphics Principles and Practice** and **Fundamental of Computer Graphics by Peter Shire;ey** describes the calculation of the radiance returned by sampling a point on the area light, (Notice the black underlined factor describing Area of the jth light source)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jEkzn.png&#xD;&#xA;&#xD;&#xA;However both of these books when describing their pseudocode, leave out this $Area$ factor.&#xD;&#xA;&#xD;&#xA;However when I read Peter Shirley's research paper regarding Direct illumination techniques, He gives the PDF for rectangular Area lights as&#xD;&#xA;&#xD;&#xA;$ 1/ \frac{||V_1 \times V_2||}{2}$&#xD;&#xA;&#xD;&#xA;Which is the area of the triangle not a rectangle.&#xD;&#xA;&#xD;&#xA;So ultimately I have 2 questions.&#xD;&#xA;&#xD;&#xA;**1) What is the correct PDF term for rectangular area lights?**&#xD;&#xA;&#xD;&#xA;**2) Do I need to multiply this term when calculating the radiance emitted from this light source.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="20936" PostHistoryTypeId="2" PostId="7948" RevisionGUID="f01e19d2-c576-4bd7-862d-fabad79e1584" CreationDate="2018-08-22T08:05:29.910" UserId="9194" Text="Sounds like you could be using the sum of all pixels disregarding the transparency for each pixel, and that the image has black pixels where it is transparent which leads to the issue. Instead add the pixels with their alpha value as weight, and divide the result with the total weight. Premultiplied alpha you should handle also as suggested above." ContentLicense="CC BY-SA 4.0" />
  <row Id="20937" PostHistoryTypeId="2" PostId="7949" RevisionGUID="a5aa590d-874e-48a7-8cfe-eba7e0fd1a5e" CreationDate="2018-08-22T09:06:54.760" UserId="209" Text="I've not done CSG per se, but I did work on a, not-unrelated, problem of triangulation of arbitrary, self-intersecting, multi-contoured polygons. If you don't get the implicit intersections correct, all sorts of nasty artefacts can result.&#xD;&#xA;&#xD;&#xA;Initially, I tried using standard, floating-point maths to compute intersections etc, but this is fraught with precision problems and no amount of trickery of ordering etc eliminated these accuracy issues.&#xD;&#xA;&#xD;&#xA;In the end, I replaced all intersection calculations with rational maths (high precision integer numerator and denominators) with sufficient precision that all intersections would be represented *exactly*. Once the process was completed, then these high precision results could be reduced to back to floating point.&#xD;&#xA;&#xD;&#xA;Perhaps a quick way to start would be to use a package such as [GNU's GMP](https://gmplib.org/) which supports arbitrary rational representations." ContentLicense="CC BY-SA 4.0" />
  <row Id="20938" PostHistoryTypeId="2" PostId="7950" RevisionGUID="205db5dc-c06f-41ef-b0a3-070f986ae20a" CreationDate="2018-08-22T09:18:30.670" UserId="2430" Text="Using The DSA Ext with opengl , API calls to guide opengl to the buffer format are :&#xD;&#xA;&#xD;&#xA;    glVertexArrayAttribFormat(	GLuint vaobj,&#xD;&#xA; 	GLuint attribindex,&#xD;&#xA; 	GLint size,&#xD;&#xA; 	GLenum type,&#xD;&#xA; 	GLboolean normalized,&#xD;&#xA; 	GLuint relativeoffset);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and another one is :&#xD;&#xA;&#xD;&#xA;    glVertexArrayVertexBuffer(	GLuint vaobj,&#xD;&#xA; 	GLuint bindingindex,&#xD;&#xA; 	GLuint buffer,&#xD;&#xA; 	GLintptr offset,&#xD;&#xA; 	GLsizei stride);&#xD;&#xA;my question is what's the difference between relativeOffset and the offset in both function calls ? when i set one the results are ok but when you set both your layout will be incorrected and thus the results are wrong." ContentLicense="CC BY-SA 4.0" />
  <row Id="20939" PostHistoryTypeId="1" PostId="7950" RevisionGUID="205db5dc-c06f-41ef-b0a3-070f986ae20a" CreationDate="2018-08-22T09:18:30.670" UserId="2430" Text="Difference between relativeOffset and offset in VAO with Direct Access Ext" ContentLicense="CC BY-SA 4.0" />
  <row Id="20940" PostHistoryTypeId="3" PostId="7950" RevisionGUID="205db5dc-c06f-41ef-b0a3-070f986ae20a" CreationDate="2018-08-22T09:18:30.670" UserId="2430" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20941" PostHistoryTypeId="2" PostId="7951" RevisionGUID="c7707714-2df5-48c5-9dc5-01d5ad3c8035" CreationDate="2018-08-22T11:02:14.317" UserId="137" Text="The offset in `glVertexArrayVertexBuffer` is the common offset for all attributes bound to that buffer. It's where the vbo data starts.&#xD;&#xA;&#xD;&#xA;The offset in `glVertexArrayAttribFormat` is added to that common offset for that attribute. &#xD;&#xA;&#xD;&#xA;This allows you to interleave attributes using a single vbo binding point. and change the vbo binding for those attributes in a single call.&#xD;&#xA;&#xD;&#xA;To make an example: &#xD;&#xA;&#xD;&#xA;    struct Vertex {&#xD;&#xA;        vec3 pos;&#xD;&#xA;        vec3 normal;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));&#xD;&#xA;    glVertexAttribBinding(posAttrLoc, vertexBindingPoint);&#xD;&#xA;    glEnableVertexAttribArray(posAttrLoc);&#xD;&#xA;    &#xD;&#xA;    glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));&#xD;&#xA;    glVertexAttribBinding(normalAttrLoc, vertexBindingPoint);&#xD;&#xA;    glEnableVertexAttribArray(normalAttrLoc);&#xD;&#xA;&#xD;&#xA;then to bind the buffer you pass the offset to where you put in where the data was uploaded to, this is 0 in the basic case.&#xD;&#xA;&#xD;&#xA;    glBindVertexBuffer(vertexBindingPoint, mesh.vbo, mesh.vboOffset, sizeof(Vertex));" ContentLicense="CC BY-SA 4.0" />
  <row Id="20942" PostHistoryTypeId="2" PostId="7952" RevisionGUID="d10ae374-ce6a-4fee-91fa-f57d325ef07f" CreationDate="2018-08-22T12:14:54.933" UserId="5215" Text="I hope I'm not off topic here, but this seemed like a good place to ask something like this.&#xD;&#xA;&#xD;&#xA;I've been hearing about SLI and Crossfire for a long time and how support for it is lacking.&#xD;&#xA;&#xD;&#xA;I never could understand why were the developers ones that needed to support it.&#xD;&#xA;&#xD;&#xA;GPUs are immensely parallel things. They have thousands of cores that run same code at the same time (generally speaking). The game will run with same code on a GPU with 100 cores and with 1000 cores, it will just scale itself differently.&#xD;&#xA;&#xD;&#xA;I want to know what stopped the GPU companies from dealing with this within the drivers.&#xD;&#xA;&#xD;&#xA;Why not have the driver detect two physical GPUs and present them to the system as a one logical GPU? It would then make sure that the workload is evenly distributed, while using the SLI bridge to synchronise and exchange the data across the GPUs as needed.&#xD;&#xA;&#xD;&#xA;If this was really that great as it looks to be, I'm sure they'd be doing it that way, but they aren't. My question is, why not, where does this idea fall apart?&#xD;&#xA;&#xD;&#xA;Only reason I can think of is that the GPUs can't handle both the communication with the CPU and with each other fast enough to make the whole thing feasible, and in order to do so, architectural changes would be need which would not yield any improvements in single GPU systems, but only multi GPU system, which would be far, far rarer.&#xD;&#xA;&#xD;&#xA;What gives?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20943" PostHistoryTypeId="1" PostId="7952" RevisionGUID="d10ae374-ce6a-4fee-91fa-f57d325ef07f" CreationDate="2018-08-22T12:14:54.933" UserId="5215" Text="Why isn't multi-gpu handled by the driver?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20944" PostHistoryTypeId="3" PostId="7952" RevisionGUID="d10ae374-ce6a-4fee-91fa-f57d325ef07f" CreationDate="2018-08-22T12:14:54.933" UserId="5215" Text="|gpu|driver|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20945" PostHistoryTypeId="2" PostId="7953" RevisionGUID="f9513526-823f-4b2d-964f-44642e12fc47" CreationDate="2018-08-22T14:47:29.330" UserId="6530" Text="##Your assumption is wrong&#xD;&#xA;&#xD;&#xA;[It actually *was* this way][1], in fact, things have changed *the other direction*. &#xD;&#xA;&#xD;&#xA;##History&#xD;&#xA;&#xD;&#xA;Currently ([pre nvidia link consumer graphics][2]) you've got to copy the memory over from separate GPUs to render in cross fire and SLI, as global memory transfer speeds will slow down scaling, and as far as I can tell it did not work as a general direct memory acessor, with only 2G/s bandwidth even with the [HB version](https://en.wikipedia.org/wiki/Scalable_Link_Interface), it is only meant to be a framebuffer copier.   You otherwise had to send the same information across all GPUs via PCIE.&#xD;&#xA;&#xD;&#xA;&gt;SLI allows two, three, or four graphics processing units (GPUs) to share the workload when rendering real-time 3D computer graphics. Ideally, identical GPUs are installed on the motherboard that contains enough PCI-Express slots, set up in a master-slave configuration. ***All graphics cards are given an equal workload to render, but the final output of each card is sent to the master card via a connector called the SLI Bridge***. For example, in a two graphics card setup, the master works on the top half of the scene, the slave the bottom half. Once the slave is done, it sends its render to the master to combine into one image before sending it to the monitor.&#xD;&#xA;&#xD;&#xA;(emphasis mine).&#xD;&#xA;&#xD;&#xA;But you didn't typically actually treat this set up as one GPU in the way *you* want in old times because if you wanted to *cooporate* work loads instead of merely *splitting workloads* that required GPU-&gt;GPU communication, which necessarily had to be done VIA pcie, which would be very slow. &#xD;&#xA;&#xD;&#xA;At least for opengl, SLI/Xfire rendering was handled via Driver treating the two as the same. https://stackoverflow.com/a/43812678/2036035 You didn't have the *option* of treating them as separate if they were linked.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;##Modern&#xD;&#xA;&#xD;&#xA;[Today however][3], vulkan and DX12 essentially give **more control**. &#xD;&#xA;&#xD;&#xA;&gt;One feature in particular goes a long way toward filling a Vulkan gap relative to Microsoft's API: explicit multi-GPU support, which allows one program to spread its work across multiple GPUs. ***Unlike SLI and Crossfire of old, where the task of divvying up the rendering between GPUs was largely handled by the driver***, this support gives control to the developer. With the addition, developers can create &quot;device groups&quot; that aggregate multiple physical GPUs into a single virtual device and choose how work is dispatched to the different physical GPUs. ***Resources from one physical GPU can be used by another GPU, different commands can be run on the different GPUs, and one GPU can show rendered images that were created by another GPU***.&#xD;&#xA;&#xD;&#xA;(emphasis mine)&#xD;&#xA;&#xD;&#xA;Today *you can* look at these GPUs separately. &#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/43811699/opengl-multi-gpu-support&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/NVLink&#xD;&#xA;  [3]: https://arstechnica.com/gadgets/2018/03/vulkan-1-1-adds-multi-gpu-directx-compatibility-as-khronos-looks-to-the-future/" ContentLicense="CC BY-SA 4.0" />
  <row Id="20946" PostHistoryTypeId="5" PostId="7947" RevisionGUID="c4ac0c92-56e2-4c5a-843b-a18f8dea79a6" CreationDate="2018-08-22T16:02:19.990" UserId="3003" Comment="Correct un-pre-multiply notes." Text="Averaging RGB should be correct assuming you do it in linear RGB. If your images are in sRGB, you can remove the gamma correction by doing something like the following for each of the R, G, and B components:&#xD;&#xA;&#xD;&#xA;    float sRGBToLinear(UInt8 component)&#xD;&#xA;    {&#xD;&#xA;        float tempComponent = (float)component / 255.0;&#xD;&#xA;        if (tempComponent &lt;= 0.04045)&#xD;&#xA;        {&#xD;&#xA;            tempComponent = tempComponent / 12.92;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            tempComponent = pow((tempComponent + 0.055) / (1.055), 2.4);&#xD;&#xA;        }&#xD;&#xA;        return tempComponent;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can then average together all of the red values in the image, all of the green values in the image, and all of the blue values in the image after they've been run through the above conversion. You can then do the opposite conversion to get back to sRGB:&#xD;&#xA;&#xD;&#xA;    UInt8 linearRGBTosRGB(float component)&#xD;&#xA;    {&#xD;&#xA;        float tempComponent =  0.0;&#xD;&#xA;        if (component &lt;= 0.00318308)&#xD;&#xA;        {&#xD;&#xA;            tempComponent = 12.92 * component;&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            tempComponent = 1.055 * pow(component, 1.0 / 2.4) - 0.055;&#xD;&#xA;        }&#xD;&#xA;        return (UInt8)(tempComponent * 255.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;(My apologies if I've messed up the syntax. I'm a C/C++ programmer and don't know the intricacies of Java.)&#xD;&#xA;&#xD;&#xA;Note that alpha makes things slightly more complicated. If you're using premultiplied alpha, you can simply apply the above calculations for the average. If you're using straight alpha, you'll want to multiply each of the R, G, and B components by the alpha before doing the averaging." ContentLicense="CC BY-SA 4.0" />
  <row Id="20947" PostHistoryTypeId="4" PostId="7946" RevisionGUID="98efcbab-8df7-401a-a0b2-42a93512124f" CreationDate="2018-08-22T20:37:33.837" UserId="9216" Comment="edited title" Text="Issue with loading a texture on the GPU with OpenGL 4.1 Core profile" ContentLicense="CC BY-SA 4.0" />
  <row Id="20948" PostHistoryTypeId="2" PostId="7954" RevisionGUID="e44b032d-9210-4fde-bf34-83489fe8c02d" CreationDate="2018-08-23T02:15:55.240" UserId="9231" Text="I've been working on a new ray tracer recently, but after adding reflections I'm seeing these strange small highlights on my models, particularly on the ear of the silver rabbit below. &#xD;&#xA;&#xD;&#xA;I've read that these can be caused by my reflection rays re-colliding with the object they're reflection from, but I believe I'm properly accounting for this by slightly translating the outgoing rays away from the intersect point. They also seem to consistently occur on the same parts of the model (the ears, and &quot;creases&quot;) regardless of the scene. I am taking 8 random samples per pixel, which seems to help a bit, but not entirely.&#xD;&#xA;&#xD;&#xA;Any thoughts on what could be causing this? is it possible that I'm simply not taking enough samples or structuring them well enough? &#xD;&#xA;&#xD;&#xA;[![Rendering][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eirtt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20949" PostHistoryTypeId="1" PostId="7954" RevisionGUID="e44b032d-9210-4fde-bf34-83489fe8c02d" CreationDate="2018-08-23T02:15:55.240" UserId="9231" Text="Bright artifacts in ray tracer rendering seemingly caused by reflections" ContentLicense="CC BY-SA 4.0" />
  <row Id="20950" PostHistoryTypeId="3" PostId="7954" RevisionGUID="e44b032d-9210-4fde-bf34-83489fe8c02d" CreationDate="2018-08-23T02:15:55.240" UserId="9231" Text="|raytracing|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20951" PostHistoryTypeId="2" PostId="7955" RevisionGUID="fceee219-8481-46af-a416-cd287be666b5" CreationDate="2018-08-23T16:31:35.013" UserId="56" Text="I often hear that tessellation shaders aren't great for performance reasons. Something along the lines that if you try to use a tessellation shader, you'll find that the data you get out isn't sufficient and you'll have to re-do calculations anyways. Or it might have been that this path was less efficient than going another route and wasn't a good use of bandwidth?&#xD;&#xA;&#xD;&#xA;Can anyone explain the details of why tessellation shaders are not advised, and if there are any exception cases where tessellation is a good thing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20952" PostHistoryTypeId="1" PostId="7955" RevisionGUID="fceee219-8481-46af-a416-cd287be666b5" CreationDate="2018-08-23T16:31:35.013" UserId="56" Text="Why are tessellation shaders disliked?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20953" PostHistoryTypeId="3" PostId="7955" RevisionGUID="fceee219-8481-46af-a416-cd287be666b5" CreationDate="2018-08-23T16:31:35.013" UserId="56" Text="|shader|performance|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20954" PostHistoryTypeId="2" PostId="7956" RevisionGUID="93f55639-dbf8-424a-bd36-673b055a4408" CreationDate="2018-08-23T18:04:10.240" UserId="8045" Text="The clamping is done for the otherwise-jagged edge along the bright light. For pixels with the edge of the light in them, the radiance in the direction away from the center of the light is a very strong step function from (12,12,12) down to roughly (0.5,0.5,0.5) as you move across the pixel.&#xD;&#xA;This edge is smoothly anti-aliased as long as your pixel values can go up to (12,12,12), but once you clamp the pixels to (1,1,1) the outline of the light edge becomes very jagged (pixelated).&#xD;&#xA;&#xD;&#xA;Clamping is technically adding bias but it's a limitation of the file format and display output.&#xD;&#xA;&#xD;&#xA;One possible solution that wouldn't introduce bias would be tone-mapping or underexposing the image, such as dividing the radiance values by 12, but that would change the look of the image.&#xD;&#xA;&#xD;&#xA;Clamping prior to averaging (and then averaging) the subpixels is effectively the same as down-sampling the clamped subpixel image with a box filter. The subpixels are unbiased (before clamping), but the pixels written out are down-sampled from them after clamping.&#xD;&#xA;&#xD;&#xA;As for down-sampling, I don't know if it's biasing but it's the same operation one would do to shrink an image to fit a smaller display, for example. It typically makes images look better but smaller.&#xD;&#xA;&#xD;&#xA;You could down-sample before clamping but it would look worse. But either way you will have to clamp when writing the file to PPM format unless you get all the radiance values below 1." ContentLicense="CC BY-SA 4.0" />
  <row Id="20955" PostHistoryTypeId="2" PostId="7957" RevisionGUID="0bb969b5-3dce-4d9c-9232-af3b6cb36301" CreationDate="2018-08-23T19:08:08.787" UserId="4647" Text="You seem to not change `GL_TEXTURE_MIN_FILTER` and not fill all the mipmap layers. This will usually result in the texture not being applied, since by default the filter uses mipmapping." ContentLicense="CC BY-SA 4.0" />
  <row Id="20956" PostHistoryTypeId="2" PostId="7958" RevisionGUID="f832aeea-3f0b-4517-a8a1-b9cf0ff5767c" CreationDate="2018-08-23T21:21:26.117" UserId="56" Text="A summarized answer:&#xD;&#xA;&#xD;&#xA; - It's bad on mobile&#xD;&#xA; - It's bad on AMD / Console&#xD;&#xA; - There is complexity in setting the tessellation factors to give good results &#xD;&#xA; - it sounds like it's difficult not to get too much resolution in some ways (aliasing), and not enough in others (low quality results)&#xD;&#xA; - Tessellation is still used by major games in specific cases though, and terrain does seem to be one usage case&#xD;&#xA; - Intel is good with geometry shaders but nobody else is, due to how the architecture is different&#xD;&#xA; - A bummer about tessellation shaders is that they basically work by sampling discrete sample points (at vertices) so for a better result, you need a denser mesh to start with, which sort of defeats the purpose of dynamic tessellation.  Can be addressed a bit with mipmapping type strategies." ContentLicense="CC BY-SA 4.0" />
  <row Id="20957" PostHistoryTypeId="6" PostId="7955" RevisionGUID="b18c67d8-87ff-4bff-ad3a-539c27fc6eba" CreationDate="2018-08-23T22:10:30.740" UserId="2654" Comment="edited tags" Text="|shader|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20958" PostHistoryTypeId="5" PostId="7954" RevisionGUID="6c7fb463-08e1-4b72-a53b-4f140abd4381" CreationDate="2018-08-23T22:55:46.090" UserId="9231" Comment="Added relevant methods" Text="I've been working on a new ray tracer recently, but after adding reflections I'm seeing these strange small highlights on my models, particularly on the ear of the silver rabbit below. &#xD;&#xA;&#xD;&#xA;I've read that these can be caused by my reflection rays re-colliding with the object they're reflection from, but I believe I'm properly accounting for this by slightly translating the outgoing rays away from the intersect point. They also seem to consistently occur on the same parts of the model (the ears, and &quot;creases&quot;) regardless of the scene. I am taking 8 random samples per pixel, which seems to help a bit, but not entirely.&#xD;&#xA;&#xD;&#xA;Any thoughts on what could be causing this? is it possible that I'm simply not taking enough samples or structuring them well enough? &#xD;&#xA;&#xD;&#xA;[![Rendering][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eirtt.png&#xD;&#xA;&#xD;&#xA;EDIT: &#xD;&#xA;&#xD;&#xA;I've added the code for my recursive coloring/reflectance function and my shadow function below, sorry if it's messy&#xD;&#xA;&#xD;&#xA;    public Color getIntersectColor(Scene theScene, Vector3D theNormal, Vector3D theIntersectPoint, Vector3D theRay, int aDepth)&#xD;&#xA;    {&#xD;&#xA;        // Initialize to ambient colors&#xD;&#xA;        double aRed = myKa * myDiffuseColor.getDecimalRed();&#xD;&#xA;        double aBlue = myKa * myDiffuseColor.getDecimalBlue();&#xD;&#xA;        double aGreen = myKa * myDiffuseColor.getDecimalGreen();&#xD;&#xA;&#xD;&#xA;        final Color aColor = new Color(aRed, aGreen, aBlue);&#xD;&#xA;&#xD;&#xA;        theScene.getLights().parallelStream().forEach(theLight -&gt;&#xD;&#xA;        {&#xD;&#xA;            Vector3D L = theLight.getL(theIntersectPoint);&#xD;&#xA;            Vector3D V = theScene.getCamera().getPosition().subtract(theIntersectPoint).normalize();&#xD;&#xA;            Vector3D H = L.add(V).scale((1.0 / (L.add(V).getLength()))).normalize();&#xD;&#xA;&#xD;&#xA;            Color aLC = theLight.getColor();&#xD;&#xA;            Double aI = Math.abs(theNormal.dot(L));&#xD;&#xA;            Double aR = Math.abs(theNormal.dot(H));&#xD;&#xA;&#xD;&#xA;           double aLightDistance = theLight.getDistance(theIntersectPoint);&#xD;&#xA;&#xD;&#xA;           double aShadow = 1.0;&#xD;&#xA;&#xD;&#xA;           if (hasShadows)&#xD;&#xA;           {&#xD;&#xA;               aShadow = getShadow(theIntersectPoint, L, aLightDistance, theScene);&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;            double aR = aLC.getDecimalRed() * aShadow *&#xD;&#xA;                                      ((myKd * myDiffuseColor.getDecimalRed() * aI) +&#xD;&#xA;                                          (myKs * mySpecularColor.getDecimalRed() * (Math.pow(aR, myShininess)))&#xD;&#xA;                                      );&#xD;&#xA;&#xD;&#xA;            double aG = aLC.getDecimalGreen() * aShadow *&#xD;&#xA;                                        ((myKd * myDiffuseColor.getDecimalGreen() * aI) +&#xD;&#xA;                                            (myKs * mySpecularColor.getDecimalGreen() * (Math.pow(aR, myShininess)))&#xD;&#xA;                                        );&#xD;&#xA;&#xD;&#xA;            double aB = aLC.getDecimalBlue() * aShadow *&#xD;&#xA;                                        ((myKd * myDiffuseColor.getDecimalBlue() * aI) +&#xD;&#xA;                                            (myKs * mySpecularColor.getDecimalBlue() * (Math.pow(aR, myShininess)))&#xD;&#xA;                                        );&#xD;&#xA;&#xD;&#xA;            aColor.setRed(aColor.getDecimalRed() + aR);&#xD;&#xA;            aColor.setBlue(aColor.getDecimalBlue() + aB);&#xD;&#xA;            aColor.setGreen(aColor.getDecimalGreen() + aG);&#xD;&#xA;&#xD;&#xA;            if (isReflective &amp;&amp; aDepth &gt; 0)&#xD;&#xA;            {&#xD;&#xA;                double aReflectionAngle = theRay.dot(theNormal);&#xD;&#xA;&#xD;&#xA;                Vector3D aReflectionVector = theRay.subtract(theNormal.scale(2.0 * aReflectionAngle)).normalize();&#xD;&#xA;&#xD;&#xA;                double F0 = ((myIndexOfRefraction - 1)  /(1 + myIndexOfRefraction)) *&#xD;&#xA;                        ((myIndexOfRefraction - 1) / (1 + myIndexOfRefraction));&#xD;&#xA;&#xD;&#xA;                double FR = F0 + (1 - F0) * ((1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle)) *&#xD;&#xA;                                             (1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle))&#xD;&#xA;                                                * (1 - Math.cos(aReflectionAngle)));&#xD;&#xA;&#xD;&#xA;                Vector3D anAdjustedIntersect = theIntersectPoint.add(aReflectionVector.scale(.00001));&#xD;&#xA;&#xD;&#xA;                Color aRefColor = theScene.getKDFilteredObjects(aReflectionVector, anAdjustedIntersect)&#xD;&#xA;                    .parallelStream()&#xD;&#xA;                    .unordered()&#xD;&#xA;                    .map(thePObject -&gt; new Pair&lt;&gt;(thePObject, thePObject.intersects(aReflectionVector, anAdjustedIntersect)))&#xD;&#xA;                    .filter(thePair -&gt; thePair.getValue() != null)&#xD;&#xA;                    .reduce((thePair, theOtherPair) -&gt; thePair.getValue() &gt;= theOtherPair.getValue() ? theOtherPair : thePair)&#xD;&#xA;                    .map(theIntersect -&gt;&#xD;&#xA;                    {&#xD;&#xA;                        Vector3D aIntersectPoint = theIntersectPoint.add(aReflectionVector.scale(theIntersect.getValue()));&#xD;&#xA;                        return theIntersect.getKey().getMaterial().getIntersectColor(theScene, theIntersect.getKey().getIntersectNormal(aIntersectPoint), aIntersectPoint, aReflectionVector, aDepth - 1);&#xD;&#xA;                    })&#xD;&#xA;                    .orElse(theScene.getBackgroundColor());&#xD;&#xA;&#xD;&#xA;                aColor.setRed(aColor.getDecimalRed() + (FR * aRefColor.getDecimalRed()));&#xD;&#xA;                aColor.setBlue(aColor.getDecimalBlue() + (FR * aRefColor.getDecimalBlue()));&#xD;&#xA;                aColor.setGreen(aColor.getDecimalGreen() + (FR * aRefColor.getDecimalGreen()));&#xD;&#xA;            }&#xD;&#xA;        });&#xD;&#xA;&#xD;&#xA;        return aColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // TODO: factor in opacity&#xD;&#xA;    public double getShadow(Vector3D theOrigin, Vector3D theLightDirection, double theLightDistance, Scene theScene)&#xD;&#xA;    {&#xD;&#xA;        // Avoid self-collision&#xD;&#xA;        Vector3D aAdjustedOrigin = theOrigin.add(theLightDirection.scale(.00001));&#xD;&#xA;&#xD;&#xA;        return theScene.getKDFilteredObjects(theLightDirection, aAdjustedOrigin)&#xD;&#xA;                .parallelStream()&#xD;&#xA;                .unordered()&#xD;&#xA;                .map(theObject -&gt; theObject.intersects(theLightDirection, aAdjustedOrigin))&#xD;&#xA;                .filter(Objects::nonNull)&#xD;&#xA;                .filter(theT -&gt; theT &gt; 0 &amp;&amp; theT &lt; theLightDistance)&#xD;&#xA;                .findAny()&#xD;&#xA;                .map(theT -&gt; 0.0)&#xD;&#xA;                .orElse(1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="20959" PostHistoryTypeId="5" PostId="7954" RevisionGUID="1236b521-5b6e-4c13-82b2-8b2dff0c08fb" CreationDate="2018-08-23T23:07:43.267" UserId="9231" Comment="added 4 characters in body" Text="I've been working on a new ray tracer recently, but after adding reflections I'm seeing these strange small highlights on my models, particularly on the ear of the silver rabbit below. &#xD;&#xA;&#xD;&#xA;I've read that these can be caused by my reflection rays re-colliding with the object they're reflection from, but I believe I'm properly accounting for this by slightly translating the outgoing rays away from the intersect point. They also seem to consistently occur on the same parts of the model (the ears, and &quot;creases&quot;) regardless of the scene. I am taking 8 random samples per pixel, which seems to help a bit, but not entirely.&#xD;&#xA;&#xD;&#xA;Any thoughts on what could be causing this? is it possible that I'm simply not taking enough samples or structuring them well enough? &#xD;&#xA;&#xD;&#xA;[![Rendering][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eirtt.png&#xD;&#xA;&#xD;&#xA;**EDIT:** &#xD;&#xA;&#xD;&#xA;I've added the code for my recursive coloring/reflectance function and my shadow function below, sorry if it's messy&#xD;&#xA;&#xD;&#xA;    public Color getIntersectColor(Scene theScene, Vector3D theNormal, Vector3D theIntersectPoint, Vector3D theRay, int aDepth)&#xD;&#xA;    {&#xD;&#xA;        // Initialize to ambient colors&#xD;&#xA;        double aRed = myKa * myDiffuseColor.getDecimalRed();&#xD;&#xA;        double aBlue = myKa * myDiffuseColor.getDecimalBlue();&#xD;&#xA;        double aGreen = myKa * myDiffuseColor.getDecimalGreen();&#xD;&#xA;&#xD;&#xA;        final Color aColor = new Color(aRed, aGreen, aBlue);&#xD;&#xA;&#xD;&#xA;        theScene.getLights().parallelStream().forEach(theLight -&gt;&#xD;&#xA;        {&#xD;&#xA;            Vector3D L = theLight.getL(theIntersectPoint);&#xD;&#xA;            Vector3D V = theScene.getCamera().getPosition().subtract(theIntersectPoint).normalize();&#xD;&#xA;            Vector3D H = L.add(V).scale((1.0 / (L.add(V).getLength()))).normalize();&#xD;&#xA;&#xD;&#xA;            Color aLC = theLight.getColor();&#xD;&#xA;            Double aI = Math.abs(theNormal.dot(L));&#xD;&#xA;            Double aR = Math.abs(theNormal.dot(H));&#xD;&#xA;&#xD;&#xA;           double aLightDistance = theLight.getDistance(theIntersectPoint);&#xD;&#xA;&#xD;&#xA;           double aShadow = 1.0;&#xD;&#xA;&#xD;&#xA;           if (hasShadows)&#xD;&#xA;           {&#xD;&#xA;               aShadow = getShadow(theIntersectPoint, L, aLightDistance, theScene);&#xD;&#xA;           }&#xD;&#xA;&#xD;&#xA;            double aR = aLC.getDecimalRed() * aShadow *&#xD;&#xA;                                      ((myKd * myDiffuseColor.getDecimalRed() * aI) +&#xD;&#xA;                                          (myKs * mySpecularColor.getDecimalRed() * (Math.pow(aR, myShininess)))&#xD;&#xA;                                      );&#xD;&#xA;&#xD;&#xA;            double aG = aLC.getDecimalGreen() * aShadow *&#xD;&#xA;                                        ((myKd * myDiffuseColor.getDecimalGreen() * aI) +&#xD;&#xA;                                            (myKs * mySpecularColor.getDecimalGreen() * (Math.pow(aR, myShininess)))&#xD;&#xA;                                        );&#xD;&#xA;&#xD;&#xA;            double aB = aLC.getDecimalBlue() * aShadow *&#xD;&#xA;                                        ((myKd * myDiffuseColor.getDecimalBlue() * aI) +&#xD;&#xA;                                            (myKs * mySpecularColor.getDecimalBlue() * (Math.pow(aR, myShininess)))&#xD;&#xA;                                        );&#xD;&#xA;&#xD;&#xA;            aColor.setRed(aColor.getDecimalRed() + aR);&#xD;&#xA;            aColor.setBlue(aColor.getDecimalBlue() + aB);&#xD;&#xA;            aColor.setGreen(aColor.getDecimalGreen() + aG);&#xD;&#xA;&#xD;&#xA;            if (isReflective &amp;&amp; aDepth &gt; 0)&#xD;&#xA;            {&#xD;&#xA;                double aReflectionAngle = theRay.dot(theNormal);&#xD;&#xA;&#xD;&#xA;                Vector3D aReflectionVector = theRay.subtract(theNormal.scale(2.0 * aReflectionAngle)).normalize();&#xD;&#xA;&#xD;&#xA;                double F0 = ((myIndexOfRefraction - 1)  /(1 + myIndexOfRefraction)) *&#xD;&#xA;                        ((myIndexOfRefraction - 1) / (1 + myIndexOfRefraction));&#xD;&#xA;&#xD;&#xA;                double FR = F0 + (1 - F0) * ((1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle)) *&#xD;&#xA;                                             (1 - Math.cos(aReflectionAngle)) * (1 - Math.cos(aReflectionAngle))&#xD;&#xA;                                                * (1 - Math.cos(aReflectionAngle)));&#xD;&#xA;&#xD;&#xA;                Vector3D anAdjustedIntersect = theIntersectPoint.add(aReflectionVector.scale(.00001));&#xD;&#xA;&#xD;&#xA;                Color aRefColor = theScene.getKDFilteredObjects(aReflectionVector, anAdjustedIntersect)&#xD;&#xA;                    .parallelStream()&#xD;&#xA;                    .unordered()&#xD;&#xA;                    .map(thePObject -&gt; new Pair&lt;&gt;(thePObject, thePObject.intersects(aReflectionVector, anAdjustedIntersect)))&#xD;&#xA;                    .filter(thePair -&gt; thePair.getValue() != null)&#xD;&#xA;                    .reduce((thePair, theOtherPair) -&gt; thePair.getValue() &gt;= theOtherPair.getValue() ? theOtherPair : thePair)&#xD;&#xA;                    .map(theIntersect -&gt;&#xD;&#xA;                    {&#xD;&#xA;                        Vector3D aIntersectPoint = theIntersectPoint.add(aReflectionVector.scale(theIntersect.getValue()));&#xD;&#xA;                        return theIntersect.getKey().getMaterial().getIntersectColor(theScene, theIntersect.getKey().getIntersectNormal(aIntersectPoint), aIntersectPoint, aReflectionVector, aDepth - 1);&#xD;&#xA;                    })&#xD;&#xA;                    .orElse(theScene.getBackgroundColor());&#xD;&#xA;&#xD;&#xA;                aColor.setRed(aColor.getDecimalRed() + (FR * aRefColor.getDecimalRed()));&#xD;&#xA;                aColor.setBlue(aColor.getDecimalBlue() + (FR * aRefColor.getDecimalBlue()));&#xD;&#xA;                aColor.setGreen(aColor.getDecimalGreen() + (FR * aRefColor.getDecimalGreen()));&#xD;&#xA;            }&#xD;&#xA;        });&#xD;&#xA;&#xD;&#xA;        return aColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // TODO: factor in opacity&#xD;&#xA;    public double getShadow(Vector3D theOrigin, Vector3D theLightDirection, double theLightDistance, Scene theScene)&#xD;&#xA;    {&#xD;&#xA;        // Avoid self-collision&#xD;&#xA;        Vector3D aAdjustedOrigin = theOrigin.add(theLightDirection.scale(.00001));&#xD;&#xA;&#xD;&#xA;        return theScene.getKDFilteredObjects(theLightDirection, aAdjustedOrigin)&#xD;&#xA;                .parallelStream()&#xD;&#xA;                .unordered()&#xD;&#xA;                .map(theObject -&gt; theObject.intersects(theLightDirection, aAdjustedOrigin))&#xD;&#xA;                .filter(Objects::nonNull)&#xD;&#xA;                .filter(theT -&gt; theT &gt; 0 &amp;&amp; theT &lt; theLightDistance)&#xD;&#xA;                .findAny()&#xD;&#xA;                .map(theT -&gt; 0.0)&#xD;&#xA;                .orElse(1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="20960" PostHistoryTypeId="5" PostId="7946" RevisionGUID="6ead34d6-f35b-4fff-8d8d-d2f9cd367fda" CreationDate="2018-08-24T11:06:39.100" UserId="6" Comment="deleted 11 characters in body" Text="I’ve been trying to render a texture on the whole screen in OpenGL 4.1 using the Core profile and followed a few tutorials on the matter, but all I have so far is a blank screen.&#xD;&#xA;&#xD;&#xA;I tried using my texture coordinates as color components and got the result I expected so the vertice data must be in order, but using the dimensions of the texture as color components I determined the size of the texture in my shader is 1x1 when it should be 2x2, so I guess I am doing something wrong when uploading it to the GPU.&#xD;&#xA;&#xD;&#xA;This is my pixel data:&#xD;&#xA;&#xD;&#xA;    const GLubyte pixels[] = {&#xD;&#xA;        255, 255, 255, 255,     0, 0, 0, 255,&#xD;&#xA;        0, 0, 0, 255,           255, 255, 255, 255,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is how I load my texture:&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pixels);&#xD;&#xA;&#xD;&#xA;I also tried using a buffer:&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;texture);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    glGenBuffers(1, &amp;texture_buffer);&#xD;&#xA;    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_buffer);&#xD;&#xA;    glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(pixels), pixels, GL_STATIC_DRAW);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)0);&#xD;&#xA;&#xD;&#xA;And this is how I render:&#xD;&#xA;&#xD;&#xA;    glUseProgram(shader_program);&#xD;&#xA;    // Binding my vba and vbo, uploading vertices.&#xD;&#xA;    glUniform1i(texture_location, 0);&#xD;&#xA;    // Enabling vertex attrib arrays.&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    // Drawing arrays, disabling vertex attrib arrays.&#xD;&#xA;&#xD;&#xA;I have also put the whole source file [on pastebin](https://pastebin.com/gmN50u50), it uses GLFW for windowing and does some basic error checking.&#xD;&#xA;&#xD;&#xA;I’d be really grateful if someone could point out what I am missing here." ContentLicense="CC BY-SA 4.0" />
  <row Id="20961" PostHistoryTypeId="2" PostId="7959" RevisionGUID="713a6963-f69a-4dde-bb32-42b056c4808c" CreationDate="2018-08-24T13:40:34.333" UserId="9180" Text="https://en.m.wikipedia.org/wiki/Rotation_matrix in section that says &quot;in three dimensions&quot;. It's the first search result when searching about rotating a vector about an axis. Let me know if you have any questions.&#xD;&#xA;&#xD;&#xA;For your specific problem: bring the point P to the origin, then rotate the vector about the Z axis, then bring the point P back to its original location." ContentLicense="CC BY-SA 4.0" />
  <row Id="20962" PostHistoryTypeId="5" PostId="7958" RevisionGUID="b5534b92-3deb-4c98-a6e7-d2a5a1d8aabf" CreationDate="2018-08-24T13:45:46.973" UserId="56" Comment="deleted 100 characters in body" Text="A summarized answer:&#xD;&#xA;&#xD;&#xA; - It's bad on mobile&#xD;&#xA; - It's bad on AMD / Console&#xD;&#xA; - There is complexity in setting the tessellation factors to give good results &#xD;&#xA; - it sounds like it's difficult not to get too much resolution in some ways (aliasing), and not enough in others (low quality results)&#xD;&#xA; - Tessellation is still used by major games in specific cases though, and terrain does seem to be one usage case&#xD;&#xD;&#xA; - A bummer about tessellation shaders is that they basically work by sampling discrete sample points (at vertices) so for a better result, you need a denser mesh to start with, which sort of defeats the purpose of dynamic tessellation.  Can be addressed a bit with mipmapping type strategies." ContentLicense="CC BY-SA 4.0" />
  <row Id="20967" PostHistoryTypeId="2" PostId="7961" RevisionGUID="f7e34497-f66c-4302-bc60-fa03fca8ed28" CreationDate="2018-08-24T15:08:17.033" UserId="8893" Text="I am currently trying to reduce the tessellation levels on front facing triangles, but I also want to keep tessellation levels high on edges (so when the view vector is orthogonal to the triangle normal).&#xD;&#xA;&#xD;&#xA;Some background information. My terrain system tessellates the terrain and displaces the newly created triangles using the heightfield texture. That means that each triangle edge must always have the same tessellation levels as the other triangles that share the same edge, otherwise holes will be created in the terrain.&#xD;&#xA;&#xD;&#xA;I can't find a way to keep the calculations consistent for shared edges.&#xD;&#xA;&#xD;&#xA;edit: I have been trying to sample the heightfield to calculate the normal for the edges. That way regardless of the triangle. The edge tessellation levels will always be the same, but I seem to be having issues." ContentLicense="CC BY-SA 4.0" />
  <row Id="20968" PostHistoryTypeId="1" PostId="7961" RevisionGUID="f7e34497-f66c-4302-bc60-fa03fca8ed28" CreationDate="2018-08-24T15:08:17.033" UserId="8893" Text="Proper way to reduce tessellation on front faces?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20969" PostHistoryTypeId="3" PostId="7961" RevisionGUID="f7e34497-f66c-4302-bc60-fa03fca8ed28" CreationDate="2018-08-24T15:08:17.033" UserId="8893" Text="|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20970" PostHistoryTypeId="5" PostId="7961" RevisionGUID="39bf72a0-482a-4f92-bb96-62d8b8b01603" CreationDate="2018-08-24T15:15:50.380" UserId="8893" Comment="added 28 characters in body" Text="I am currently trying to reduce the tessellation levels on front facing triangles, but I also want to keep tessellation levels high on edges (so when the view vector is orthogonal to the triangle normal).&#xD;&#xA;&#xD;&#xA;Some background information. My terrain system tessellates the terrain and displaces the newly created triangles using the heightfield texture. That means that each triangle edge must always have the same tessellation levels as the other triangles that share the same edge, otherwise holes will be created in the terrain.&#xD;&#xA;&#xD;&#xA;I can't find a way to keep the calculations consistent for shared edges.&#xD;&#xA;&#xD;&#xA;edit: I have been trying to use non-divergent data by sampling the heightfield to calculate the normal for the edges. That way regardless of the triangle. The edge tessellation levels will always be the same, but I seem to be having issues." ContentLicense="CC BY-SA 4.0" />
  <row Id="20971" PostHistoryTypeId="5" PostId="7958" RevisionGUID="181aeed5-04c9-48f4-94d3-2b7f23fbeeef" CreationDate="2018-08-24T21:04:18.447" UserId="56" Comment="some more details" Text="An answer with details gotten elsewhere:&#xD;&#xA;&#xD;&#xA; - It's bad on mobile: ARM doesn't have a tessellation unit so is emulated in software. Tiled based architectures will write vertex data to main memory before pixel shading which is a bandwidth issue. qualcom switches to direct rendering mode if you enable tessellation which isn't cheap.&#xD;&#xA; - It's bad on AMD / Console&#xD;&#xA; - There is complexity in setting the tessellation factors to give good results &#xD;&#xA; - it sounds like it's difficult not to get too much resolution in some ways (aliasing), and not enough in others (low quality results). You essentially need to know screen space derivatives of vertices to calculate good tessellation factors, and this is not easy to get even decent approximations of.&#xD;&#xA; - A bummer about tessellation shaders is that they basically work by sampling discrete sample points (at vertices) so for a better result, you need a denser mesh to start with, which sort of defeats the purpose of dynamic tessellation.  Can be addressed a bit with mipmapping type strategies.&#xD;&#xA; - Tessellation is still used by major games in specific cases though, and terrain does seem to be one usage case" ContentLicense="CC BY-SA 4.0" />
  <row Id="20976" PostHistoryTypeId="2" PostId="7963" RevisionGUID="3aba7401-02cb-46b2-8c3c-c13418681de9" CreationDate="2018-08-25T16:04:30.987" UserId="9248" Text="pretend the images and the monitor have same color profile&#xD;&#xA;&#xD;&#xA;Is every image from the internet commonly got gamma corrected?&#xD;&#xA;Or our monitor is automatically gamma corrected all the image showed up?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20977" PostHistoryTypeId="1" PostId="7963" RevisionGUID="3aba7401-02cb-46b2-8c3c-c13418681de9" CreationDate="2018-08-25T16:04:30.987" UserId="9248" Text="Gamma correction is done in an image or a monitor?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20978" PostHistoryTypeId="3" PostId="7963" RevisionGUID="3aba7401-02cb-46b2-8c3c-c13418681de9" CreationDate="2018-08-25T16:04:30.987" UserId="9248" Text="|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20980" PostHistoryTypeId="2" PostId="7964" RevisionGUID="d251b9ff-b4d7-477c-a9e9-56fad97c6d29" CreationDate="2018-08-25T19:08:55.227" UserId="4908" Text="&gt; Is every image from the internet commonly got gamma corrected?&#xD;&#xA;&#xD;&#xA;Every image is encoded with a color profile. Most color profiles do have a gamma correction, but not every color profile has that (raw for example). Most images on the internet are encoded in sRGB, which is gamma corrected. If you would download a random image from the internet, you will more than likely have an image that is in sRGB and thus gamma corrected.&#xD;&#xA;&#xD;&#xA;&gt; Or our monitor is automatically gamma corrected all the image showed up?&#xD;&#xA;&#xD;&#xA;The monitor receives its image in the color profile of the monitor (let's just say sRGB), it then decodes the image from sRGB to the actual intensity of the pixels and then displays it. Basically, the monitor receives a gamma corrected image and removes the gamma correction just before it displays it.&#xD;&#xA;&#xD;&#xA;Images that are saved to a file or that are sent to the monitor, are generally gamma corrected. This is for a very simple reason. We only have 256 values per RGB component to define the color of a pixel. Our eyes are very good at picking up small differences in dark parts of an image, but relatively terrible at picking up small differences in bright parts.&#xD;&#xA;&#xD;&#xA;If we try to save an image without any gamma correcting as an 8-bit image (thus 256 values per RGB component), we end up with having the same amount of precision for dark parts in the image and bright parts in the image. However, our eyes cannot see small differences in bright parts of the image, so all that precision in the bright parts is simply wasted. Gamma correction fixes this. Before we convert the image to 8 bits, we first gamma correct it so that we allocate more precision to that darker parts of the image than the brighter parts of the image. When displayed, the monitor will remove that gamma correction.&#xD;&#xA;&#xD;&#xA;Left is an image that was gamma corrected before being saved to 8 bits and right is an image that was not gamma corrected before 8 bits. You can clearly see the lack of precision in the darker parts without gamma correction, but not in the bright parts.&#xD;&#xA;[![Gamma correction VS no Gamma Correction][1]][1]&#xD;&#xA;&#xD;&#xA;Gamma correction is a very useful trick to make our images with finite bits, look better.&#xD;&#xA;&#xD;&#xA;If you want to read more about it, [you can do so here.][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PDOqx.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Gamma_correction" ContentLicense="CC BY-SA 4.0" />
  <row Id="20981" PostHistoryTypeId="2" PostId="7965" RevisionGUID="92852674-546c-47f1-87bd-7cfdf7885805" CreationDate="2018-08-26T12:06:34.100" UserId="9254" Text="Metropolis Light Transport is an application of the Metropolis-Hastings algorithm. Its variants differ only in the used &quot;mutation strategy&quot;.&#xD;&#xA;&#xD;&#xA;Is there ongoing research on other Markov Chain Monte Carlo algorithms (with faster convergence rates) for use in ray tracing?&#xD;&#xA;&#xD;&#xA;If so, I'm interested in any paper." ContentLicense="CC BY-SA 4.0" />
  <row Id="20982" PostHistoryTypeId="1" PostId="7965" RevisionGUID="92852674-546c-47f1-87bd-7cfdf7885805" CreationDate="2018-08-26T12:06:34.100" UserId="9254" Text="Is there ongoing research on Markov Chain Monte Carlo algorithms (other than Metropolis-Hastings) for use in ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20983" PostHistoryTypeId="3" PostId="7965" RevisionGUID="92852674-546c-47f1-87bd-7cfdf7885805" CreationDate="2018-08-26T12:06:34.100" UserId="9254" Text="|raytracing|rendering|pathtracing|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20984" PostHistoryTypeId="5" PostId="7965" RevisionGUID="857eb881-797e-4b09-88af-ce0a1f5ce882" CreationDate="2018-08-26T12:14:57.083" UserId="9254" Comment="added 165 characters in body" Text="Metropolis Light Transport is an application of the Metropolis-Hastings algorithm. Its variants differ only in the used &quot;mutation strategy&quot;.&#xD;&#xA;&#xD;&#xA;Is there ongoing research on other Markov Chain Monte Carlo algorithms (with faster convergence rates) for use in ray tracing?&#xD;&#xA;&#xD;&#xA;If so, I'm interested in any paper.&#xD;&#xA;&#xD;&#xA;([Cross-posted](https://cs.stackexchange.com/questions/96638/is-there-ongoing-research-on-markov-chain-monte-carlo-algorithms-other-than-met) on Computer Sciene)" ContentLicense="CC BY-SA 4.0" />
  <row Id="20985" PostHistoryTypeId="2" PostId="7966" RevisionGUID="7003c55e-5dc0-49aa-969d-9a2816c18f72" CreationDate="2018-08-26T14:19:43.260" UserId="6046" Text="So I just completed a naive path tracer that uses explicit direct light sampling.&#xD;&#xA;Problem is the path tracer isn't converging. It's like a raytracer, showing a single image on each pass. More info on how am I doing this is provided below. I am using OpenCL 1.1.&#xD;&#xA;&#xD;&#xA;    __kernel void render(__write_only image2d_t outputImage, __read_only image2d_t inputImage, int reset)&#xD;&#xA;    {&#xD;&#xA;    	for(int i = 0; i &lt; samples_x; i++)&#xD;&#xA;    	{&#xD;&#xA;    		for(int j = 0; j &lt; samples_y; j++)&#xD;&#xA;    		{&#xD;&#xA;    			float4 color;&#xD;&#xA;    			Shoot ray through pixel.&#xD;&#xA;    			Check for intersection.&#xD;&#xA;    			&#xD;&#xA;    			If(!intersects)&#xD;&#xA;    			{&#xD;&#xA;    				color += Background_color&#xD;&#xA;    				continue;&#xD;&#xA;    			}&#xD;&#xA;    			else&#xD;&#xA;    				color += directColor() + IndirectColor();			&#xD;&#xA;    			&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    	color /= (samples_x * samples_y);&#xD;&#xA;    	&#xD;&#xA;    	if ( reset == 1 )&#xD;&#xA;    	{	&#xD;&#xA;    		write_imagef(outputImage, pixel, color);&#xD;&#xA;    	}&#xD;&#xA;    	else&#xD;&#xA;    	{			&#xD;&#xA;    		float4 prev_color = read_imagef(outputImage, sampler, pixel);&#xD;&#xA;    		color += prev_color;&#xD;&#xA;    		color /= 2.0f;&#xD;&#xA;    		write_imagef(outputImage, pixel, color);	&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this is the main outline. When the kernel runs the first time, `reset = 1`. Thus it writes the color directly into the output image. At each iteration, the buffers of `outputImage` and `inputImage`get swapped. After iteration 1, `reset = 0`.&#xD;&#xA;&#xD;&#xA;This means at iteration 2, the kernel reads from the image it wrote to, in iteration 1. It then averages the new color and the previous color. &#xD;&#xA;&#xD;&#xA;I thought taking 64 samples 2 times, and averaging them would be analogous to taking 128 samples once. If this is true then my image should converge, but it isn't. It shows only this image constantly.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mueb5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20986" PostHistoryTypeId="1" PostId="7966" RevisionGUID="7003c55e-5dc0-49aa-969d-9a2816c18f72" CreationDate="2018-08-26T14:19:43.260" UserId="6046" Text="Path tracer isn't converging" ContentLicense="CC BY-SA 4.0" />
  <row Id="20987" PostHistoryTypeId="3" PostId="7966" RevisionGUID="7003c55e-5dc0-49aa-969d-9a2816c18f72" CreationDate="2018-08-26T14:19:43.260" UserId="6046" Text="|pathtracing|global-illumination|sampling|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20988" PostHistoryTypeId="2" PostId="7967" RevisionGUID="e90d46b9-0b3d-4e33-aa7c-2353b96158aa" CreationDate="2018-08-26T14:50:33.180" UserId="9255" Text="I am not an export in 3D nor computer graphics. Please forgive me if I use wrong wording.&#xD;&#xA;&#xD;&#xA;High level problem description: For an online shop, I would like to create mockup images of apparel (t-shirts, tank tops, hoodies) with a print placed on them. There are loads of information how to do this with photoshop, but I would like to have an automated way to handle this. The image manipulation should happen with imagemagick finally.&#xD;&#xA;&#xD;&#xA;The images should be captured on a dummy under a controlled setting. The image creation should include following steps:&#xD;&#xA;&#xD;&#xA; * Capture a image from the front of a white shirt.&#xD;&#xA; * Capture a series of images of the dummy with the shirt as the dummy rotates around itself to create a photogrammetry 3D model of the dummy with the shirt.&#xD;&#xA;&#xD;&#xA;The image taken from the front will be the basis of the product image later on. The 3D model should be used to create analyse the distortion which has to be applied to the design/print on the shirt. This is the step i am interested in.&#xD;&#xA;&#xD;&#xA;The image composition should happen in this steps:&#xD;&#xA;&#xD;&#xA; * use the image from the front as the base.&#xD;&#xA; * Extract the shadows of the image.&#xD;&#xA; * Blend a color layer over the shirt, to get the different product color.&#xD;&#xA; * Map the design (a graphic or a text) over the white shirt using a distortion method to squeeze and pull apart the design following the perspective change created through the shape of the dummy.&#xD;&#xA;&#xD;&#xA;My idea had been to use a 3D method an image of a grid as the design on the 3D model somehow and analyse the the created 2D image for the distortion of the grid to get a model of how to squeeze and pull the design then in the image stacking process.&#xD;&#xA;&#xD;&#xA;Do you have any recommendations how to do this in practical steps? Or can you suggest me an different approach to get the desired result?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="20989" PostHistoryTypeId="1" PostId="7967" RevisionGUID="e90d46b9-0b3d-4e33-aa7c-2353b96158aa" CreationDate="2018-08-26T14:50:33.180" UserId="9255" Text="Possible approach for product mockup creation including distortion created through perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="20990" PostHistoryTypeId="3" PostId="7967" RevisionGUID="e90d46b9-0b3d-4e33-aa7c-2353b96158aa" CreationDate="2018-08-26T14:50:33.180" UserId="9255" Text="|3d|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20991" PostHistoryTypeId="5" PostId="7966" RevisionGUID="05323c06-5cd1-473b-a8cf-52eca0a0c8ee" CreationDate="2018-08-26T15:42:33.550" UserId="6046" Comment="added 1815 characters in body" Text="So I just completed a naive path tracer that uses explicit direct light sampling.&#xD;&#xA;Problem is the path tracer isn't converging. It's like a raytracer, showing a single image on each pass. More info on how am I doing this is provided below. I am using OpenCL 1.1.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;      __kernel void render(__write_only image2d_t outputImage, __read_only image2d_t inputImage, int reset)&#xD;&#xA;    {&#xD;&#xA;    	for(int i = 0; i &lt; samples_x; i++)&#xD;&#xA;    	{&#xD;&#xA;    		for(int j = 0; j &lt; samples_y; j++)&#xD;&#xA;    		{&#xD;&#xA;    			float4 direct_color, indirect_color, total_color; 	// all initalized to black&#xD;&#xA;    			&#xD;&#xA;    			Shoot ray through pixel.&#xD;&#xA;    			&#xD;&#xA;    			HitInfo new_info, old_info;&#xD;&#xA;    			If( !intersects(ray, old_info) )&#xD;&#xA;    			{&#xD;&#xA;    				total_color += Background_color&#xD;&#xA;    				continue;&#xD;&#xA;    			}&#xD;&#xA;    			else&#xD;&#xA;    			{&#xD;&#xA;    				direct_color += computeDirectLighting(old_info);				&#xD;&#xA;    				float4 color_arr[BOUNCES];&#xD;&#xA;    				float cosine_falloff[BOUNCES];&#xD;&#xA;    				for(int i = 0; i &lt; BOUNCES; i++)&#xD;&#xA;    				{		&#xD;&#xA;    					new_ray = sampleHemisphere();&#xD;&#xA;    							&#xD;&#xA;    					if( !intersects(new_ray, new_info) )&#xD;&#xA;    					{&#xD;&#xA;    						color_arr[i] = sky_color;&#xD;&#xA;    						cosine_falloff[i] = max(dot(old_info.normal, new_ray.dir), 0.0f);&#xD;&#xA;    						break;&#xD;&#xA;    					}&#xD;&#xA;    					else if ( intersects light source)&#xD;&#xA;    					{&#xD;&#xA;    						i--;&#xD;&#xA;    						continue;&#xD;&#xA;    						(Sample again)						&#xD;&#xA;    					}&#xD;&#xA;    					&#xD;&#xA;    					color_arr[i] = computeDirectLighting(new_info);&#xD;&#xA;    					cosine_falloff[i] = max(dot(old_info.normal, new_ray.dir), 0.0f);&#xD;&#xA;    					old_info = new_info;&#xD;&#xA;    				}&#xD;&#xA;    				&#xD;&#xA;    				for(i = color_arr.length() - 1; i &gt;= 0; i--)&#xD;&#xA;    				{&#xD;&#xA;    					indirect_color += color_arr[i];&#xD;&#xA;    					indirect_color *= cosine_falloff[i];&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    			&#xD;&#xA;    			total_color += direct_color + indirect_color;&#xD;&#xA;    			&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	}&#xD;&#xA;    	color /= (samples_x * samples_y);&#xD;&#xA;    	&#xD;&#xA;    	if ( reset == 1 )&#xD;&#xA;    	{	&#xD;&#xA;    		write_imagef(outputImage, pixel, color);&#xD;&#xA;    	}&#xD;&#xA;    	else&#xD;&#xA;    	{			&#xD;&#xA;    		float4 prev_color = read_imagef(outputImage, sampler, pixel);&#xD;&#xA;    		color += prev_color;&#xD;&#xA;    		color /= 2.0f;&#xD;&#xA;    		write_imagef(outputImage, pixel, color);	&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this is the main outline. When the kernel runs the first time, `reset = 1`. Thus it writes the color directly into the output image. At each iteration, the buffers of `outputImage` and `inputImage`get swapped. After iteration 1, `reset = 0`.&#xD;&#xA;&#xD;&#xA;This means at iteration 2, the kernel reads from the image it wrote to, in iteration 1. It then averages the new color and the previous color. &#xD;&#xA;&#xD;&#xA;I thought taking 64 samples 2 times, and averaging them would be analogous to taking 128 samples once. If this is true then my image should converge, but it isn't. It shows only this image constantly.&#xD;&#xA;&#xD;&#xA;**EDIT**:- &#xD;&#xA;I think I should clear how I am calculating GI. After the first intersection. I send 1 ray directly to the light source (explicit direct light sampling). Then uniformly sample the hemisphere w.r.t area, and send another ray in this sampled direction. If the new ray hits light source, we sample again. This goes on `bounces times`. Each bounce the program stores the direct color due to explicit direct light sampling at each hit point. The indirect color is the sum of all these direct colors. Added a simple algo of what I did to the code snippet.&#xD;&#xA;&#xD;&#xA;The `cosine_falloff` array holds all the weakening factors that should be multiplied to the respective indirect colors brought by secondary GI rays.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mueb5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20992" PostHistoryTypeId="5" PostId="7966" RevisionGUID="da7c64c6-1aa7-48f6-951b-868d57dd9d28" CreationDate="2018-08-26T15:53:04.640" UserId="6046" Comment="added 3 characters in body" Text="So I just completed a naive path tracer that uses explicit direct light sampling.&#xD;&#xA;Problem is the path tracer isn't converging. It's like a raytracer, showing a single image on each pass. More info on how am I doing this is provided below. I am using OpenCL 1.1.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;      __kernel void render(__write_only image2d_t outputImage, __read_only image2d_t inputImage, int reset)&#xD;&#xA;    {&#xD;&#xA;        float total_color; 	// initalized to black&#xD;&#xA;    	for(int i = 0; i &lt; samples_x; i++)&#xD;&#xA;    	{&#xD;&#xA;    		for(int j = 0; j &lt; samples_y; j++)&#xD;&#xA;    		{		&#xD;&#xA;    			float4 direct_color, indirect_color; initialized black.&#xD;&#xA;    			Shoot ray through pixel.&#xD;&#xA;    			&#xD;&#xA;    			HitInfo new_info, old_info;&#xD;&#xA;    			If( !intersects(ray, old_info) )&#xD;&#xA;    			{&#xD;&#xA;    				total_color += Background_color&#xD;&#xA;    				continue;&#xD;&#xA;    			}&#xD;&#xA;    			else&#xD;&#xA;    			{&#xD;&#xA;    				direct_color = computeDirectLighting(old_info);				&#xD;&#xA;    				float4 color_arr[BOUNCES];&#xD;&#xA;    				float cosine_falloff[BOUNCES];&#xD;&#xA;    				for(int i = 0; i &lt; BOUNCES; i++)&#xD;&#xA;    				{		&#xD;&#xA;    					new_ray = sampleHemisphere();&#xD;&#xA;    							&#xD;&#xA;    					if( !intersects(new_ray, new_info) )&#xD;&#xA;    					{&#xD;&#xA;    						color_arr[i] = sky_color;&#xD;&#xA;    						cosine_falloff[i] = max(dot(old_info.normal, new_ray.dir), 0.0f);&#xD;&#xA;    						break;&#xD;&#xA;    					}&#xD;&#xA;    					else if ( intersects light source)&#xD;&#xA;    					{&#xD;&#xA;    						i--;&#xD;&#xA;    						continue;&#xD;&#xA;    						(Sample again)						&#xD;&#xA;    					}&#xD;&#xA;    					&#xD;&#xA;    					color_arr[i] = computeDirectLighting(new_info);&#xD;&#xA;    					cosine_falloff[i] = max(dot(old_info.normal, new_ray.dir), 0.0f);&#xD;&#xA;    					old_info = new_info;&#xD;&#xA;    				}&#xD;&#xA;    				&#xD;&#xA;    				for(i = color_arr.length() - 1; i &gt;= 0; i--)&#xD;&#xA;    				{&#xD;&#xA;    					indirect_color += color_arr[i];&#xD;&#xA;    					indirect_color *= cosine_falloff[i];&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    			&#xD;&#xA;    			total_color += direct_color + indirect_color;&#xD;&#xA;    			&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	}&#xD;&#xA;    	color /= (samples_x * samples_y);&#xD;&#xA;    	&#xD;&#xA;    	if ( reset == 1 )&#xD;&#xA;    	{	&#xD;&#xA;    		write_imagef(outputImage, pixel, color);&#xD;&#xA;    	}&#xD;&#xA;    	else&#xD;&#xA;    	{			&#xD;&#xA;    		float4 prev_color = read_imagef(outputImage, sampler, pixel);&#xD;&#xA;    		color += prev_color;&#xD;&#xA;    		color /= 2.0f;&#xD;&#xA;    		write_imagef(outputImage, pixel, color);	&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So this is the main outline. When the kernel runs the first time, `reset = 1`. Thus it writes the color directly into the output image. At each iteration, the buffers of `outputImage` and `inputImage`get swapped. After iteration 1, `reset = 0`.&#xD;&#xA;&#xD;&#xA;This means at iteration 2, the kernel reads from the image it wrote to, in iteration 1. It then averages the new color and the previous color. &#xD;&#xA;&#xD;&#xA;I thought taking 64 samples 2 times, and averaging them would be analogous to taking 128 samples once. If this is true then my image should converge, but it isn't. It shows only this image constantly.&#xD;&#xA;&#xD;&#xA;**EDIT**:- &#xD;&#xA;I think I should clear how I am calculating GI. After the first intersection. I send 1 ray directly to the light source (explicit direct light sampling). Then uniformly sample the hemisphere w.r.t area, and send another ray in this sampled direction. If the new ray hits light source, we sample again. This goes on `bounces times`. Each bounce the program stores the direct color due to explicit direct light sampling at each hit point. The indirect color is the sum of all these direct colors. Added a simple algo of what I did to the code snippet.&#xD;&#xA;&#xD;&#xA;The `cosine_falloff` array holds all the weakening factors that should be multiplied to the respective indirect colors brought by secondary GI rays.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mueb5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="20993" PostHistoryTypeId="2" PostId="7968" RevisionGUID="03b049f0-95d9-4b72-bd44-4038746e5bab" CreationDate="2018-08-26T16:51:40.470" UserId="4908" Text="I can find two possible reasons for the image not converging.&#xD;&#xA;&#xD;&#xA;## #1. Every sample is the same ##&#xD;&#xA;For every sample, you generate random rays. You do that when you shoot the ray through a pixel (for anti-aliasing and DoF) and when you sample the hemisphere (for a new indirect bounce). The problem would be if for every sample, it would generate the same direction, then every sample is the exact same colour and you would not be doing any converging.&#xD;&#xA;&#xD;&#xA;Most of the times when generating random numbers on the GPU, we generate them in advance and save them to a texture. When we need a number, we just sample the texture. Of course, for every pixel you want a different random value, and you would then use something like the thread id or the pixel coordinate to sample the texture. Then, every frame must also be different, so you would also use the frame counter to offset the thread id. But, notice how there is nothing to make sure that every sample also has a new random number. If for every sample you generate the same random direction, then every sample is the exact same colour and you would not be doing any converging.&#xD;&#xA;&#xD;&#xA;This can often easily be fixed by keeping track of how many random numbers you &#xD;&#xA;already have generated and use that to offset every lookup. Basically, have a struct that holds the u and v values for the texture lookup. You initialize it with the thread id or pixel coordinate together with either the frame count or just a random number you generate on the CPU and pass it to the kernel as a global offset to the random values. Make sure that the struct is initialized in the very beginning of the kernel (where you initialize total_color). Then when you need a random number, you pass a reference to that struct to the method that generates a random number, it then looks up the random number in the texture and then it offsets the u and v values in the struct so that the next time you will get a different number.&#xD;&#xA;&#xD;&#xA;Of course, I have not seen how you generate the rays (both on shooting a ray through a pixel and sampling a hemisphere), so I cannot say for sure if this is the problem, but it does seem very much like it.&#xD;&#xA;&#xD;&#xA;## #2. Not properly averaging multiple frames ##&#xD;&#xA;&#xD;&#xA;&gt; I thought taking 64 samples 2 times, and averaging them would be analogous to taking 128 samples once.&#xD;&#xA;&#xD;&#xA;This is actually true. You average samples to get an image.&#xD;&#xA;$$IMG1 = \frac{sample1 + sample2 + sample3 + samples4}{4}$$&#xD;&#xA;Which you then do again for the second image.&#xD;&#xA;$$IMG2 = \frac{sample5 + sample6 + sample7 + samples8}{4}$$&#xD;&#xA;Which you then combine.&#xD;&#xA;$$RESULT = \frac{IMG1 + IMG2}{2}=$$&#xD;&#xA;$$\frac{\frac{sample1 + sample2 + sample3 + samples4}{4}+ \frac{sample5 + sample6 + sample7 + samples8}{4}}{2}=$$&#xD;&#xA;$$\frac{\frac{sample1 + sample2 + sample3 + samples4 + sample5 + sample6 + sample7 + samples8}{4}}{2}=$$&#xD;&#xA;$$\frac{sample1 + sample2 + sample3 + samples4 + sample5 + sample6 + sample7 + samples8}{8}$$&#xD;&#xA;As you can see, it would indeed be like sampling twice as much.&#xD;&#xA;&#xD;&#xA;However, your piece of code does not properly combine two images.&#xD;&#xA;&#xD;&#xA;    float4 prev_color = read_imagef(outputImage, sampler, pixel);&#xD;&#xA;    color += prev_color;&#xD;&#xA;    color /= 2.0f;&#xD;&#xA;    write_imagef(outputImage, pixel, color);    &#xD;&#xA;&#xD;&#xA;When we look at what you are doing.&#xD;&#xA;$$outColor = \frac{newColor + oldColor}{2}$$&#xD;&#xA;Where $outColor$ is the colour saved in the image.&#xD;&#xA;$newColor$ is the colour you just calculated.&#xD;&#xA;$oldColor$ is the color of the previous frame.&#xD;&#xA;&#xD;&#xA;We see that it does what it is supposed to do, it averages both frames.&#xD;&#xA;&#xD;&#xA;Of course, when the third frame comes around, $outColor$ becomes $oldColor$ as you swap the buffers of outputImage and inputImage. Thus, we can substitute it.&#xD;&#xA;$$outColor = \frac{newColor + \frac{prevColor + oldColor}{2}}{2}$$&#xD;&#xA;Where $prevColor$ was the color calculated the previous frame.&#xD;&#xA;&#xD;&#xA;Although, this does not seem that good.&#xD;&#xA;$newColor$ contributes **50%**, while $prevColor$ and $oldColor$ only contribute **25%**. This is a problem. You want every frame to contribute equally because then you are just adding up the samples. This means that you need to compensate for this.&#xD;&#xA;&#xD;&#xA;There is an extremely simple solution to this. Multiply $oldColor$ by the amount of frames *excluding the current frame* and to then divide by the amount of frames *including the current frame*. you would then get this.&#xD;&#xA;$$outColor = \frac{newColor + 2*\frac{prevColor + oldColor}{2}}{2 + 1}$$ Which would cancel out the divide and give you.&#xD;&#xA;$$outColor = \frac{newColor + prevColor + oldColor}{3}$$ (The $+1$ is because we multiplied by 2 at the top, basically making it a total of 3 parts, and thus we need to divide by 3.)&#xD;&#xA;&#xD;&#xA;If you would be calculating the fifth frame you would do it like this.&#xD;&#xA;&#xD;&#xA;    float4 prev_color = read_imagef(outputImage, sampler, pixel);&#xD;&#xA;    color += prev_color * 4.0f;&#xD;&#xA;    color /= 5.0f;&#xD;&#xA;    write_imagef(outputImage, pixel, color);  &#xD;&#xA;&#xD;&#xA;If you would be calculating the tenth frame you would do it like this.&#xD;&#xA;&#xD;&#xA;    float4 prev_color = read_imagef(outputImage, sampler, pixel);&#xD;&#xA;    color += prev_color * 9.0f;&#xD;&#xA;    color /= 10.0f;&#xD;&#xA;    write_imagef(outputImage, pixel, color);  &#xD;&#xA;&#xD;&#xA;This does mean that you need to pass through a counter which tells you how many frames you already have calculated. Most progressive or interactive path tracers actually only do one sample per frame (make sure that the ray through the pixel is randomly jittered), since it would take less time to calculate one frame, so that you see changes much earlier and often it is fine if you edit your scene using only one sample since you still get enough information." ContentLicense="CC BY-SA 4.0" />
  <row Id="20994" PostHistoryTypeId="2" PostId="7969" RevisionGUID="fd4f9a90-fe6b-4332-959b-24fc9834815c" CreationDate="2018-08-26T17:27:26.213" UserId="5430" Text="Is it possible to gain performance boost using new 4x4 MAD from NVIDIA'a tensor cores for ray-triangle intersection tests?&#xD;&#xA;&#xD;&#xA;Really there are two questions:&#xD;&#xA; - Is it possible to modify some of the ray-triangle algorithms (say, Möller-Trumbore algorithm) to base it on 4x4 matrix MAD.&#xD;&#xA; - Would it be an performance improvement?" ContentLicense="CC BY-SA 4.0" />
  <row Id="20995" PostHistoryTypeId="1" PostId="7969" RevisionGUID="fd4f9a90-fe6b-4332-959b-24fc9834815c" CreationDate="2018-08-26T17:27:26.213" UserId="5430" Text="Using multiply and accumulate for 4x4 matrices to ray-triangle intersection tests" ContentLicense="CC BY-SA 4.0" />
  <row Id="20996" PostHistoryTypeId="3" PostId="7969" RevisionGUID="fd4f9a90-fe6b-4332-959b-24fc9834815c" CreationDate="2018-08-26T17:27:26.213" UserId="5430" Text="|raytracing|gpu|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="20997" PostHistoryTypeId="2" PostId="7970" RevisionGUID="73620392-e106-4555-ae21-4dd13fd99f8c" CreationDate="2018-08-26T17:51:07.630" UserId="2287" Text="**Path Space representation, MLT (Metropolis Light Transport)**:&#xD;&#xA;&#xD;&#xA; - Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co., pp. 65–76.&#xD;&#xA; - Veach E.: Robust monte carlo methods for light transport simulation. No. 1610. Stanford University PhD thesis, 1997.&#xD;&#xA;&#xD;&#xA;**Primary Sample Space (PSS) representation, PSSMLT**:&#xD;&#xA;&#xD;&#xA; - Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm. 531–540.&#xD;&#xA;&#xD;&#xA;**Extended Primary Sample Space representation, MMLT (Multiplexed MLT)**:&#xD;&#xA;&#xD;&#xA; - Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014), 100:1–100:10.&#xD;&#xA;&#xD;&#xA;**Manifold Exploration (ME) [specific mutation], MEMLT**:&#xD;&#xA;&#xD;&#xA;- Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012), 58:1–58:13.&#xD;&#xA;- Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.&#xD;&#xA;&#xD;&#xA;**Half Vector Space representation, HSLT (Half Vector Space Light Transport)**:&#xD;&#xA;&#xD;&#xA;- Kaplanyan A. S., Hanika J., Dachsbacher C.: The Naturalconstraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014), 102:1–102:13.&#xD;&#xA;- Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library, pp. 65–74.&#xD;&#xA;&#xD;&#xA;**Note** HSLT is a generalization of MEMLT. MEMLT is an optional add-on mutation for MLT, whereas HSLT replaces the complete Path Space.&#xD;&#xA;&#xD;&#xA;**Gradient Domain representation, GDMLT**:&#xD;&#xA;&#xD;&#xA;- Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013), 95:1–95:12.&#xD;&#xA;- Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014), 178:1–178:12.&#xD;&#xA;&#xD;&#xA;**Note** there are variants for path tracing and bidirectional path tracing as well exploiting the Gradient Domain representation.&#xD;&#xA;&#xD;&#xA;**Path Space - Primary Sample Space representations**:&#xD;&#xA;&#xD;&#xA;- **Reversible Jump MLT (RJMLT)**&#xD;&#xA;  - Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 8 2015.&#xD;&#xA;  - Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).&#xD;&#xA;- **Charted MLT (CMLT)**&#xD;&#xA;  - Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans.&#xD;&#xA;Graph. 36, 4 (July 2017), 75:1–75:14.&#xD;&#xA;- **Fusing State Spaces**&#xD;&#xA; - Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017), 74:1–74:10.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20998" PostHistoryTypeId="5" PostId="7970" RevisionGUID="d4736d13-9477-44a8-a77c-66d3bf1eac39" CreationDate="2018-08-26T17:56:41.787" UserId="2287" Comment="added 206 characters in body" Text="Here is an overview of the most used representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the Path Space and the Primary Sample Space by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;**Path Space representation, MLT (Metropolis Light Transport)**:&#xD;&#xA;&#xD;&#xA; - Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co., pp. 65–76.&#xD;&#xA; - Veach E.: Robust monte carlo methods for light transport simulation. No. 1610. Stanford University PhD thesis, 1997.&#xD;&#xA; - Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport, Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017, 55–63.&#xD;&#xA;&#xD;&#xA;**Primary Sample Space (PSS) representation, PSSMLT**:&#xD;&#xA;&#xD;&#xA; - Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm. 531–540.&#xD;&#xA;&#xD;&#xA;**Extended Primary Sample Space representation, MMLT (Multiplexed MLT)**:&#xD;&#xA;&#xD;&#xA; - Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014), 100:1–100:10.&#xD;&#xA;&#xD;&#xA;**Manifold Exploration (ME) [specific mutation], MEMLT**:&#xD;&#xA;&#xD;&#xA;- Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012), 58:1–58:13.&#xD;&#xA;- Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.&#xD;&#xA;&#xD;&#xA;**Half Vector Space representation, HSLT (Half Vector Space Light Transport)**:&#xD;&#xA;&#xD;&#xA;- Kaplanyan A. S., Hanika J., Dachsbacher C.: The Naturalconstraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014), 102:1–102:13.&#xD;&#xA;- Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library, pp. 65–74.&#xD;&#xA;&#xD;&#xA;**Note** HSLT is a generalization of MEMLT. MEMLT is an optional add-on mutation for MLT, whereas HSLT replaces the complete Path Space.&#xD;&#xA;&#xD;&#xA;**Gradient Domain representation, GDMLT**:&#xD;&#xA;&#xD;&#xA;- Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013), 95:1–95:12.&#xD;&#xA;- Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014), 178:1–178:12.&#xD;&#xA;&#xD;&#xA;**Note** there are variants for path tracing and bidirectional path tracing as well exploiting the Gradient Domain representation.&#xD;&#xA;&#xD;&#xA;**Path Space &lt;-&gt; Primary Sample Space representations**:&#xD;&#xA;&#xD;&#xA;- **Reversible Jump MLT (RJMLT)**&#xD;&#xA;  - Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 8 2015.&#xD;&#xA;  - Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).&#xD;&#xA;- **Charted MLT (CMLT)**&#xD;&#xA;  - Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans.&#xD;&#xA;Graph. 36, 4 (July 2017), 75:1–75:14.&#xD;&#xA;- **Fusing State Spaces**&#xD;&#xA; - Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017), 74:1–74:10.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="20999" PostHistoryTypeId="5" PostId="7970" RevisionGUID="b48f597a-690a-45eb-b05f-e3680ccbd0cb" CreationDate="2018-08-26T18:03:11.573" UserId="2287" Comment="added 206 characters in body" Text="Here is an overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the Path Space and the Primary Sample Space by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;**Path Space representation, MLT (Metropolis Light Transport)**:&#xD;&#xA;&#xD;&#xA; - Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co., pp. 65–76.&#xD;&#xA; - Veach E.: Robust monte carlo methods for light transport simulation. No. 1610. Stanford University PhD thesis, 1997.&#xD;&#xA; - Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport, Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017, 55–63.&#xD;&#xA;&#xD;&#xA;**Primary Sample Space (PSS) representation, PSSMLT**:&#xD;&#xA;&#xD;&#xA; - Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm. 531–540.&#xD;&#xA;&#xD;&#xA;**Extended Primary Sample Space representation, MMLT (Multiplexed MLT)**:&#xD;&#xA;&#xD;&#xA; - Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014), 100:1–100:10.&#xD;&#xA;&#xD;&#xA;**Manifold Exploration (ME) [specific mutation], MEMLT**:&#xD;&#xA;&#xD;&#xA;- Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012), 58:1–58:13.&#xD;&#xA;- Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.&#xD;&#xA;&#xD;&#xA;**Half Vector Space representation, HSLT (Half Vector Space Light Transport)**:&#xD;&#xA;&#xD;&#xA;- Kaplanyan A. S., Hanika J., Dachsbacher C.: The Naturalconstraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014), 102:1–102:13.&#xD;&#xA;- Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library, pp. 65–74.&#xD;&#xA;&#xD;&#xA;**Note** HSLT is a generalization of MEMLT. MEMLT is an optional add-on mutation for MLT, whereas HSLT replaces the complete Path Space.&#xD;&#xA;&#xD;&#xA;**Gradient Domain representation, GDMLT**:&#xD;&#xA;&#xD;&#xA;- Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013), 95:1–95:12.&#xD;&#xA;- Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014), 178:1–178:12.&#xD;&#xA;&#xD;&#xA;**Note** there are variants for path tracing and bidirectional path tracing as well exploiting the Gradient Domain representation.&#xD;&#xA;&#xD;&#xA;**Path Space &lt;-&gt; Primary Sample Space representations**:&#xD;&#xA;&#xD;&#xA;- **Reversible Jump MLT (RJMLT)**&#xD;&#xA;  - Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 8 2015.&#xD;&#xA;  - Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).&#xD;&#xA;- **Charted MLT (CMLT)**&#xD;&#xA;  - Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans.&#xD;&#xA;Graph. 36, 4 (July 2017), 75:1–75:14.&#xD;&#xA;- **Fusing State Spaces**&#xD;&#xA; - Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017), 74:1–74:10.&#xD;&#xA;&#xD;&#xA;**Genetic operators in Path Space and Extended Primary Sample Space, GMLT**:&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21000" PostHistoryTypeId="5" PostId="7970" RevisionGUID="9e9f4420-b535-4b8b-8849-3ca254eb5d99" CreationDate="2018-08-26T18:10:33.713" UserId="2287" Comment="added 206 characters in body" Text="Here is an overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the Path Space and the Primary Sample Space by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;**Path Space representation, MLT (Metropolis Light Transport)**:&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;**Primary Sample Space (PSS) representation, PSSMLT**:&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;**Extended Primary Sample Space representation, MMLT (Multiplexed MLT)**:&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;**Manifold Exploration (ME) [specific mutation], MEMLT**:&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;**Half Vector Space representation, HSLT (Half Vector Space Light Transport)**:&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** HSLT is a generalization of MEMLT. MEMLT is an optional add-on mutation for MLT, whereas HSLT replaces the complete Path Space.&#xD;&#xA;&#xD;&#xA;**Gradient Domain representation, GDMLT**:&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** there are variants for path tracing and bidirectional path tracing as well exploiting the Gradient Domain representation.&#xD;&#xA;&#xD;&#xA;**Path Space &lt;-&gt; Primary Sample Space representations**:&#xD;&#xA;&#xD;&#xA;- **Reversible Jump MLT (RJMLT)**&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;- **Charted MLT (CMLT)**&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;- **Fusing State Spaces**&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;**Genetic operators in Path Space and Extended Primary Sample Space, GMLT**:&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21001" PostHistoryTypeId="5" PostId="7970" RevisionGUID="dcfb3f15-5070-4700-b7db-5b3a5a6481b5" CreationDate="2018-08-26T18:16:16.850" UserId="2287" Comment="added 206 characters in body" Text="# Overview&#xD;&#xA;&#xD;&#xA;Here is a short overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the *Path Space* and the *Primary Sample Space* by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;## Path Space (PS) representation, MLT (Metropolis Light Transport)&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;## Primary Sample Space (PSS) representation, PSSMLT&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;## Extended Primary Sample Space representation, MMLT (Multiplexed MLT):&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;## Manifold Exploration (ME), MEMLT:&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;## Half Vector Space representation, HSLT (Half Vector Space Light Transport)&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** HSLT is more general than MEMLT: MEMLT is an *optional* add-on mutation for MLT, whereas HSLT replaces the complete Path Space representation.&#xD;&#xA;&#xD;&#xA;## Gradient Domain representation, GDMLT&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** there are variants for path tracing and bidirectional path tracing exploiting the Gradient Domain representation as well.&#xD;&#xA;&#xD;&#xA;## Path Space &lt;-&gt; Primary Sample Space representations&#xD;&#xA;&#xD;&#xA;### Reversible Jump MLT (RJMLT)&#xD;&#xA;&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;&#xD;&#xA;### Charted MLT (CMLT)&#xD;&#xA;&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;&#xD;&#xA;### Fusing State Spaces&#xD;&#xA;&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;## Genetic operators in Path Space and Extended Primary Sample Space, GMLT&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018." ContentLicense="CC BY-SA 4.0" />
  <row Id="21002" PostHistoryTypeId="5" PostId="7970" RevisionGUID="51d04a07-7c8f-4c64-af54-f73908ceb0d2" CreationDate="2018-08-26T18:21:20.740" UserId="2287" Comment="added 206 characters in body" Text="# Overview&#xD;&#xA;&#xD;&#xA;Here is a short overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the *Path Space* and the *Primary Sample Space* by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;## Path Space (PS) representation, Metropolis Light Transport (MLT)&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;## Primary Sample Space (PSS) representation, PSSMLT&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;## Extended Primary Sample Space representation, Multiplexed MLT (MMLT):&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;## Manifold Exploration (ME), MEMLT:&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;## Half Vector Space representation, Half Vector Space Light Transport (HSLT)&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** HSLT is more general than MEMLT: MEMLT is an *optional* add-on mutation for MLT, whereas HSLT replaces the complete Path Space representation.&#xD;&#xA;&#xD;&#xA;## Gradient Domain representation, GDMLT&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** there are variants for path tracing and bidirectional path tracing exploiting the Gradient Domain representation as well.&#xD;&#xA;&#xD;&#xA;## Path Space &lt;-&gt; Primary Sample Space representations&#xD;&#xA;&#xD;&#xA;### Reversible Jump MLT (RJMLT)&#xD;&#xA;&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;&#xD;&#xA;### Charted MLT (CMLT)&#xD;&#xA;&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;&#xD;&#xA;### Fusing State Spaces&#xD;&#xA;&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;## Genetic operators in Path Space and Extended Primary Sample Space, Genetic MLT (GMLT)&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018." ContentLicense="CC BY-SA 4.0" />
  <row Id="21003" PostHistoryTypeId="5" PostId="7970" RevisionGUID="036d54f7-9310-4a12-becc-9c44752eb131" CreationDate="2018-08-26T18:27:20.500" UserId="2287" Comment="added 206 characters in body" Text="# Overview&#xD;&#xA;&#xD;&#xA;Here is a short overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the *Path Space* and the *Primary Sample Space* by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;## Path Space (PS) representation, Metropolis Light Transport (MLT)&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Primary Sample Space (PSS) representation, PSSMLT&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;## Extended Primary Sample Space representation (EPSS), Multiplexed MLT (MMLT):&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;**Note** that MMLT improves upon PSSMLT. &#xD;&#xA;&#xD;&#xA;[Example implementation available in [pbrt-v3](https://github.com/mmp/pbrt-v3)]&#xD;&#xA;&#xD;&#xA;## Manifold Exploration (ME), MEMLT:&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Half Vector Space representation, Half Vector Space Light Transport (HSLT)&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** that HSLT is more general than MEMLT: MEMLT is an *optional* add-on mutation for MLT, whereas HSLT replaces the complete Path Space representation.&#xD;&#xA;&#xD;&#xA;## Gradient Domain representation, GDMLT&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** that there are variants for path tracing and bidirectional path tracing exploiting the Gradient Domain representation as well.&#xD;&#xA;&#xD;&#xA;## Path Space &lt;-&gt; Primary Sample Space representations&#xD;&#xA;&#xD;&#xA;### Reversible Jump MLT (RJMLT)&#xD;&#xA;&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;&#xD;&#xA;### Charted MLT (CMLT)&#xD;&#xA;&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;&#xD;&#xA;### Fusing State Spaces&#xD;&#xA;&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;## Genetic operators in Path Space and Extended Primary Sample Space, Genetic MLT (GMLT)&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018.&#xD;&#xA;&#xD;&#xA;**Note** that the *Path Space* is represented via 3D path vertex positions instead of directions to facilitate crossovers (compared to MLT)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21004" PostHistoryTypeId="5" PostId="7970" RevisionGUID="ca6efdc5-ddd7-434f-b763-ec71a2917b76" CreationDate="2018-08-26T18:38:09.123" UserId="2287" Comment="added 253 characters in body" Text="# Overview&#xD;&#xA;&#xD;&#xA;Here is a short overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the *Path Space* and the *Primary Sample Space* by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;## Path Space (PS) representation, Metropolis Light Transport (MLT)&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Primary Sample Space (PSS) representation, PSSMLT&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;## Extended Primary Sample Space representation (EPSS), Multiplexed MLT (MMLT):&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;**Note** that MMLT improves upon PSSMLT. &#xD;&#xA;&#xD;&#xA;[Example implementation available in [pbrt-v3](https://github.com/mmp/pbrt-v3)]&#xD;&#xA;&#xD;&#xA;## Manifold Exploration (ME), MEMLT:&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Half Vector Space representation, Half Vector Space Light Transport (HSLT)&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** that HSLT is more general than MEMLT: MEMLT is an *optional* add-on mutation for MLT, whereas HSLT replaces the complete Path Space representation.&#xD;&#xA;&#xD;&#xA;## Gradient Domain representation, GDMLT&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** that there are variants for path tracing and bidirectional path tracing exploiting the Gradient Domain representation as well.&#xD;&#xA;&#xD;&#xA;## Path Space &lt;-&gt; Primary Sample Space representations&#xD;&#xA;&#xD;&#xA;### Reversible Jump MLT (RJMLT)&#xD;&#xA;&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;&#xD;&#xA;### Charted MLT (CMLT)&#xD;&#xA;&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;&#xD;&#xA;### Fusing State Spaces&#xD;&#xA;&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;## Genetic operators in Path Space and Extended Primary Sample Space, Genetic MLT (GMLT)&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018.&#xD;&#xA;&#xD;&#xA;**Note** that the *Path Space* is represented via 3D path vertex positions instead of directions to facilitate crossovers (compared to MLT).&#xD;&#xA;&#xD;&#xA;# PS&#xD;&#xA;&#xD;&#xA;&gt; Its variants differ only in the used &quot;mutation strategy&quot;.&#xD;&#xA;&#xD;&#xA;Different mutation strategies and **space representations** are used. Furthermore, GMLT replaces and extends Markov states representing single paths to complete path populations (Evolutionary Monte Carlo, Evolutionary Markov Chain Monte Carlo &lt;&gt; Markov Chain Monte Carlo)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21005" PostHistoryTypeId="2" PostId="7971" RevisionGUID="efbab399-db87-42b0-9d9b-6cf54d1ed300" CreationDate="2018-08-26T23:20:55.320" UserId="9231" Text="So this does in fact seem to be a self-collision issue. I was able to determine this by giving each triangle/sphere an ID and filtering that ID out when checking collisions. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21006" PostHistoryTypeId="2" PostId="7972" RevisionGUID="cb131854-284d-41c6-974c-b65728aae916" CreationDate="2018-08-27T02:11:46.797" UserId="9260" Text="I am trying to find an equation for a camera.&#xD;&#xA;The situation is as follows.&#xD;&#xA;Our goal is to map the point $P(x_p,y_p,z_p)$ from the world coordinates onto the window coordinates.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Let the position of P on the window be described as $P(x_w, y_w)$.&#xD;&#xA;The eye of viewing is located a distance D from the e1-e2 plane, and in the direction of -e3.&#xD;&#xA;&#xD;&#xA;What is the equation to map P from world coordinates to window coordinates?&#xD;&#xA;$P'(x_w,y_w) = f(\vec{P}, \vec{e1}, \vec{e2}, \vec{e3}, \vec{v}, \vec{c})$&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/odgIq.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/vLTDD.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21007" PostHistoryTypeId="1" PostId="7972" RevisionGUID="cb131854-284d-41c6-974c-b65728aae916" CreationDate="2018-08-27T02:11:46.797" UserId="9260" Text="Equation for camera" ContentLicense="CC BY-SA 4.0" />
  <row Id="21008" PostHistoryTypeId="3" PostId="7972" RevisionGUID="cb131854-284d-41c6-974c-b65728aae916" CreationDate="2018-08-27T02:11:46.797" UserId="9260" Text="|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21009" PostHistoryTypeId="5" PostId="7972" RevisionGUID="a7f3c4f3-7e15-47e2-b42c-369e26292eba" CreationDate="2018-08-27T02:33:35.333" UserId="9260" Comment="added clarification" Text="I am trying to find an equation for a camera projection.&#xD;&#xA;The situation is as follows.&#xD;&#xA;Our goal is to map the point $P(x_p,y_p,z_p)$ from the world coordinates onto the window coordinates.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Let the position of $\vec{P}$ on the window be described as $\vec{P}(x_p, y_p, z_p)$.&#xD;&#xA;The eye of viewing is located a distance D from the $\vec{e_1}$-$\vec{e_2}$ plane, and in the direction of -$\vec{e_3}$.&#xD;&#xA;$\vec{e_1}$, $\vec{e_2}$ and $\vec{e_3}$ are unit vectors.&#xD;&#xA;&#xD;&#xA;What is the equation to map P from world coordinates to window coordinates?&#xD;&#xA;$\vec{Q}(x_q,y_q) = f(\vec{P}, \vec{e1}, \vec{e2}, \vec{e3}, \vec{v}, \vec{c})$&#xD;&#xA;with all the vectors on the right side described in terms of world coordinates, eg&#xD;&#xA;&#xD;&#xA;$\vec{P} = &lt;x_p, y_p, z_p&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{C} = &lt;x_c, y_c, z_c&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{e_1} = &lt;x_{e_1},y_{e_1},z_{e_1}&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{e_2} = &lt;x_{e_2},y_{e_2},z_{e_2}&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{e_3} = &lt;x_{e_3},y_{e_3},z_{e_3}&gt;$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hlTMG.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21010" PostHistoryTypeId="4" PostId="7972" RevisionGUID="a7f3c4f3-7e15-47e2-b42c-369e26292eba" CreationDate="2018-08-27T02:33:35.333" UserId="9260" Comment="added clarification" Text="Equation for camera projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="21011" PostHistoryTypeId="5" PostId="7972" RevisionGUID="329abe8e-a800-468d-a162-2951959e4a91" CreationDate="2018-08-27T02:54:40.057" UserId="9260" Comment="use unit vectors" Text="I am trying to find an equation for a camera projection.&#xD;&#xA;The situation is as follows.&#xD;&#xA;Our goal is to map the point $P(x_p,y_p,z_p)$ from the world coordinates onto the window coordinates.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Let the position of $\vec{P}$ on the window be described as $\vec{P}(x_p, y_p, z_p)$.&#xD;&#xA;The eye of viewing is located a distance D from the $\hat{e_1}$-$\hat{e_2}$ plane, and in the direction of -$\hat{e_3}$.&#xD;&#xA;$\hat{e_1}$, $\hat{e_2}$ and $\hat{e_3}$ are unit vectors.&#xD;&#xA;&#xD;&#xA;What is the equation to map P from world coordinates to window coordinates?&#xD;&#xA;$\vec{Q}(x_q,y_q) = f(\vec{P}, \hat{e_1}, \hat{e_2}, \hat{e_3}, \vec{v}, \vec{c})$&#xD;&#xA;with all the vectors on the right side described in terms of world coordinates, eg&#xD;&#xA;&#xD;&#xA;$\vec{P} = &lt;x_p, y_p, z_p&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{C} = &lt;x_c, y_c, z_c&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{e_1} = &lt;x_{e_1},y_{e_1},z_{e_1}&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{e_2} = &lt;x_{e_2},y_{e_2},z_{e_2}&gt;$&#xD;&#xA;&#xD;&#xA;$\vec{e_3} = &lt;x_{e_3},y_{e_3},z_{e_3}&gt;$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hlTMG.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21012" PostHistoryTypeId="5" PostId="7969" RevisionGUID="6068e76d-6268-4c79-a786-c2359248a51a" CreationDate="2018-08-27T03:40:44.360" UserId="5430" Comment="added 2 characters in body" Text="Is it possible to gain performance boost using new 4x4 MAD from NVIDIA'a tensor cores for ray-triangle intersection tests?&#xD;&#xA;&#xD;&#xA;Really there are two questions:&#xD;&#xA;&#xD;&#xA; - Is it possible to modify some of the ray-triangle algorithms (say, Möller-Trumbore algorithm) to base it on 4x4 matrix MAD.&#xD;&#xA; - Would it be a performance improvement?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21013" PostHistoryTypeId="2" PostId="7973" RevisionGUID="be273bb8-252c-4af0-bf5d-4a1db7539251" CreationDate="2018-08-27T06:33:32.473" UserId="9207" Text="Thank you for the suggestions provided. As @gallickgunner mentioned, I shall rephrase the question will all the possible information which I could provide. I had attached also the schematic to depict my question.&#xD;&#xA;&#xD;&#xA;1)I need to rotate the vector V with the base point P by an angle and find the new vector V'. &#xD;&#xA;2) The rotation axis is say for is about a local y axis at point P (which is parallel to global Y axis)&#xD;&#xA;3) Subsequently, I need to rotate the initial vector V about x axis which is parallel to global Y axis. &#xD;&#xA;The main reason for the rotation is to find the new vector V' at point P. Both the rotations are independent and each of the rotation provides a new V'.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Thank you for the support. Looking forward for an answer at the earliest. &#xD;&#xA;  [1]: https://i.stack.imgur.com/MTiJX.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21014" PostHistoryTypeId="5" PostId="7970" RevisionGUID="aa8d9faa-f986-41b4-b03c-a9622e0793b3" CreationDate="2018-08-27T06:41:11.467" UserId="2287" Comment="deleted 1 character in body" Text="# Overview&#xD;&#xA;&#xD;&#xA;Here is a short overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the *Path Space* and the *Primary Sample Space* by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;## Path Space (PS) representation, Metropolis Light Transport (MLT)&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Primary Sample Space (PSS) representation, PSSMLT&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;## Extended Primary Sample Space (EPSS) representation, Multiplexed MLT (MMLT)&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;**Note** that MMLT improves upon PSSMLT. &#xD;&#xA;&#xD;&#xA;[Example implementation available in [pbrt-v3](https://github.com/mmp/pbrt-v3)]&#xD;&#xA;&#xD;&#xA;## Manifold Exploration MLT (MEMLT)&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Half Vector Space representation, Half Vector Space Light Transport (HSLT)&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** that HSLT is more general than MEMLT: MEMLT is an *optional* add-on mutation for MLT, whereas HSLT replaces the complete Path Space representation.&#xD;&#xA;&#xD;&#xA;## Gradient Domain representation, GDMLT&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** that there are variants for path tracing and bidirectional path tracing exploiting the Gradient Domain representation as well.&#xD;&#xA;&#xD;&#xA;## Path Space &lt;-&gt; Primary Sample Space representations&#xD;&#xA;&#xD;&#xA;### Reversible Jump MLT (RJMLT)&#xD;&#xA;&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;&#xD;&#xA;### Charted MLT (CMLT)&#xD;&#xA;&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;&#xD;&#xA;### Fusing State Spaces&#xD;&#xA;&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;## Genetic operators in Path Space and Extended Primary Sample Space, Genetic MLT (GMLT)&#xD;&#xA;&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018.&#xD;&#xA;&#xD;&#xA;**Note** that the *Path Space* is represented via 3D path vertex positions instead of directions to facilitate crossovers (compared to MLT).&#xD;&#xA;&#xD;&#xA;# PS&#xD;&#xA;&#xD;&#xA;&gt; Its variants differ only in the used &quot;mutation strategy&quot;.&#xD;&#xA;&#xD;&#xA;Different mutation strategies and **space representations** are used. Furthermore, GMLT replaces and extends Markov states representing single paths to complete path populations (Evolutionary Monte Carlo, Evolutionary Markov Chain Monte Carlo &lt;&gt; Markov Chain Monte Carlo)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21015" PostHistoryTypeId="2" PostId="7974" RevisionGUID="f3b12e32-8bd6-43f7-b51d-c3a330e4f9a3" CreationDate="2018-08-27T07:23:47.593" UserId="9194" Text="This is pretty straightforward matrix math and can be found on [Wikipedia][1]. It's quite elaborate, though, if you want to learn the math behind it and the other types of projection that exist. I will encourage you to checkout either [Real-Time Rendering][2] or [Computer Graphics, Principles and Practice][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/3D_projection&#xD;&#xA;  [2]: https://www.amazon.com/Real-Time-Rendering-Third-Tomas-Akenine-Moller/dp/1568814240&#xD;&#xA;  [3]: https://www.amazon.co.uk/Computer-Graphics-Principles-Practice-Practices/dp/0321399528" ContentLicense="CC BY-SA 4.0" />
  <row Id="21016" PostHistoryTypeId="5" PostId="7970" RevisionGUID="765bd01b-85d0-490a-92da-9889d43cf538" CreationDate="2018-08-27T08:04:15.833" UserId="2287" Comment="added 502 characters in body" Text="# Overview&#xD;&#xA;&#xD;&#xA;Here is a short overview of the most used space representations, MLT variants and mutation strategies for these MLT variants. As you can see, there are quite some papers dating back to **2017** (e.g., three papers explore combining the *Path Space* and the *Primary Sample Space* by jumping back and forth between the two).&#xD;&#xA;&#xD;&#xA;## Path Space (PS) representation, Metropolis Light Transport (MLT)&#xD;&#xA;&#xD;&#xA; - [Veach E., Guibas L. J.: Metropolis Light Transport. In Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (New York, NY, USA, 1997), SIGGRAPH ’97, ACM Press/Addison-Wesley Publishing Co.](https://dl.acm.org/citation.cfm?id=258775)&#xD;&#xA; - [Veach E.: Robust monte carlo methods for light transport simulation. Stanford University PhD thesis, 1997.](http://graphics.stanford.edu/papers/veach_thesis/)&#xD;&#xA; - [Van de Woestijne J., Frederickx R., Billen N., Dutré P.: Temporal Coherence for Metropolis Light Transport. Eurographics Symposium on Rendering - Experimental Ideas &amp; Implementations 2017.](http://graphics.cs.kuleuven.be/publications/WFBD2017TCFMLT/)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Primary Sample Space (PSS) representation, PSSMLT&#xD;&#xA;&#xD;&#xA; - [Kelemen C., Szirmay-Kalos L., Antal G., Csonka F.: A Simple and Robust Mutation Strategy for the Metropolis Light Transport Algorithm.](https://onlinelibrary.wiley.com/doi/pdf/10.1111/1467-8659.t01-1-00703)&#xD;&#xA;&#xD;&#xA;## Extended Primary Sample Space (EPSS) representation, Multiplexed MLT (MMLT)&#xD;&#xA;&#xD;&#xA; - [Hachisuka T., Kaplanyan A. S., Dachsbacher C.: Multiplexed Metropolis Light Transport. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601138)&#xD;&#xA;&#xD;&#xA;**Note** that MMLT improves upon PSSMLT. &#xD;&#xA;&#xD;&#xA;[Example implementation available in [pbrt-v3](https://github.com/mmp/pbrt-v3)]&#xD;&#xA;&#xD;&#xA;## Manifold Exploration MLT (MEMLT)&#xD;&#xA;&#xD;&#xA;- [Jakob W., Marschner S.: Manifold Exploration: A Markov Chain Monte Carlo Technique for Rendering Scenes with Difficult Specular Transport. ACM Trans. Graph. 31, 4 (July 2012).](https://dl.acm.org/citation.cfm?id=2185554)&#xD;&#xA;- [Jakob W.: Light Transport On Path-Space Manifolds. Cornell University PhD thesis, 2013.](https://ecommons.cornell.edu/handle/1813/34189)&#xD;&#xA;&#xD;&#xA;[Example implementation available in [Mitsuba](https://github.com/mitsuba-renderer/mitsuba)]&#xD;&#xA;&#xD;&#xA;## Half Vector Space representation, Half Vector Space Light Transport (HSLT)&#xD;&#xA;&#xD;&#xA;- [Kaplanyan A. S., Hanika J., Dachsbacher C.: The Natural-constraint Representation of the Path Space for Efficient Light Transport Simulation. ACM Trans. Graph. 33, 4 (July 2014).](https://dl.acm.org/citation.cfm?id=2601108)&#xD;&#xA;- [Hanika J., Kaplanyan A., Dachsbacher C.: Improved half vector space light transport. In Computer Graphics Forum (2015), vol. 34, Wiley Online Library.](https://dl.acm.org/citation.cfm?id=2853798)&#xD;&#xA;&#xD;&#xA;**Note** that HSLT is more general than MEMLT: MEMLT is an *optional* add-on mutation for MLT, whereas HSLT replaces the complete Path Space representation.&#xD;&#xA;&#xD;&#xA;## Gradient Domain representation, GDMLT&#xD;&#xA;&#xD;&#xA;- [Lehtinen J., Karras T., Laine S., Aittala M., Durand F., Aila T.: Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 32, 4 (July 2013).](https://dl.acm.org/citation.cfm?id=2461943)&#xD;&#xA;- [Manzi M., Rousselle F., Kettunen M., Lehtinen J., Zwicker M.: Improved Sampling for Gradient-domain Metropolis Light Transport. ACM Trans. Graph. 33, 6 (Nov. 2014).](https://dl.acm.org/citation.cfm?id=2661291)&#xD;&#xA;&#xD;&#xA;**Note** that there are variants for path tracing and bidirectional path tracing exploiting the Gradient Domain representation as well.&#xD;&#xA;&#xD;&#xA;## Path Space &lt;-&gt; Primary Sample Space representations&#xD;&#xA;&#xD;&#xA;### Reversible Jump MLT (RJMLT)&#xD;&#xA;&#xD;&#xA;  - [Bitterli B.: Informed Choices In Primary Sample Space. Master’s thesis, Swiss Federal Institute of Technology Zurich, 2015.](https://benedikt-bitterli.me/master-thesis/)&#xD;&#xA;  - [Bitterli B., Jakob W., Novák J., Jarosz W.: Reversible Jump Metropolis Light Transport Using Inverse Mappings. ACM Transactions on Graphics 37, 1 (Oct. 2017).](https://dl.acm.org/citation.cfm?id=3132704)&#xD;&#xA;&#xD;&#xA;### Charted MLT (CMLT)&#xD;&#xA;&#xD;&#xA;  - [Pantaleoni J.: Charted Metropolis Light Transport. ACM Trans. Graph. 36, 4 (July 2017).](https://dl.acm.org/citation.cfm?id=3073677)&#xD;&#xA;&#xD;&#xA;### Fusing State Spaces&#xD;&#xA;&#xD;&#xA; - [Otsu H., Kaplanyan A. S., Hanika J., Dachsbacher C., Hachisuka T.: Fusing State Spaces for Markov Chain Monte Carlo Rendering. ACM Transactions on Graphics (Proc. of SIGGRAPH) 36, 4 (2017).](https://dl.acm.org/citation.cfm?id=3073691)&#xD;&#xA;&#xD;&#xA;## Genetic operators in Path Space and Extended Primary Sample Space, Genetic MLT (GMLT)&#xD;&#xA;  - Delabie M.: Genetic Operators in Metropolis Light Transport. Master’s thesis, KU Leuven, Belgium, 2018.&#xD;&#xA;&#xD;&#xA;**Note** that the *Path Space* is represented via 3D path vertex positions instead of directions to facilitate crossovers (compared to MLT).&#xD;&#xA;&#xD;&#xA;# Post Scriptum&#xD;&#xA;&#xD;&#xA;&gt; Its variants differ only in the used &quot;mutation strategy&quot;.&#xD;&#xA;&#xD;&#xA;Different mutation strategies and **space representations** are used. Furthermore, GMLT replaces and extends Markov states representing single paths to **complete path populations** (*Evolutionary Monte Carlo*, *Evolutionary Markov Chain Monte Carlo* &lt;&gt; *Markov Chain Monte Carlo*).&#xD;&#xA;&#xD;&#xA;Some references to *Evolutionary Monte Carlo*:&#xD;&#xA;&#xD;&#xA;- [Liang F., Wong W. H.: Evolutionary Monte Carlo: Applications to Cp Model Sampling and Change Point Problem. STATISTICA SINICA 10 (2000).](https://www.jstor.org/stable/24306722?seq=1#page_scan_tab_contents)&#xD;&#xA;- [Liang F., Wong W. H.: Real-Parameter Evolutionary Monte Carlo With Applications to Bayesian Mixture Models. Journal of the American Statistical Association 96, 454 (2001).](https://www.jstor.org/stable/2670304?seq=1#page_scan_tab_contents)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21017" PostHistoryTypeId="2" PostId="7975" RevisionGUID="942f213b-2415-4474-8eb6-a00cdaadc942" CreationDate="2018-08-27T08:20:26.167" UserId="2308" Text="Forgive me, I dont really understand the basis of alpha blending. Like I know the formula but when it comes to the terms blending operation, source blend factor, and destination blend factor I am absolutely lost.&#xD;&#xA;&#xD;&#xA;The goal is to do additive blending like in photoshop so black items would be invisible and items with any color would add their color resulting in an effect that pixels with many layers underneath are close to white.&#xD;&#xA;&#xD;&#xA;The problem is I have no clue how to translate this to metal. For example this is how I am currently doing alpha blending (although t[his currently isnt working][1] for whatever reason). What should I be doing for additive blending?&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/52035162/metal-alpha-blending-is-not-working" ContentLicense="CC BY-SA 4.0" />
  <row Id="21018" PostHistoryTypeId="1" PostId="7975" RevisionGUID="942f213b-2415-4474-8eb6-a00cdaadc942" CreationDate="2018-08-27T08:20:26.167" UserId="2308" Text="How to perform additive blending in Metal. What do these terms mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21019" PostHistoryTypeId="3" PostId="7975" RevisionGUID="942f213b-2415-4474-8eb6-a00cdaadc942" CreationDate="2018-08-27T08:20:26.167" UserId="2308" Text="|blending|metal|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21021" PostHistoryTypeId="5" PostId="7965" RevisionGUID="3147ff30-124b-449c-9668-c0a77809deee" CreationDate="2018-08-27T09:50:58.307" UserId="2287" Comment="formatting" Text="Metropolis Light Transport is an application of the Metropolis-Hastings algorithm. Its variants differ only in the used &quot;mutation strategy&quot;.&#xD;&#xA;&#xD;&#xA;Is there ongoing research on other Markov Chain Monte Carlo algorithms (with faster convergence rates) for use in ray tracing?&#xD;&#xA;&#xD;&#xA;If so, I'm interested in any paper." ContentLicense="CC BY-SA 4.0" />
  <row Id="21022" PostHistoryTypeId="24" PostId="7965" RevisionGUID="3147ff30-124b-449c-9668-c0a77809deee" CreationDate="2018-08-27T09:50:58.307" Comment="Proposed by 2287 approved by -1 edit id of 434" ContentLicense="CC BY-SA 4.0" />
  <row Id="21023" PostHistoryTypeId="2" PostId="7976" RevisionGUID="8de7d5c2-657e-4cc6-a47f-f8333403ef9d" CreationDate="2018-08-27T14:22:43.880" UserId="8565" Text="I am currently trying to implement SSAO on my graphics engine. I am following John Chapman's tutorial [here][1]. This is a pretty popular article that is used as reference in many SSAO articles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html&#xD;&#xA;&#xD;&#xA;The part that confuses me is on the generation of rotation vector.&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; noiseSize; ++i) {&#xD;&#xA;       noise[i] = vec3(&#xD;&#xA;          random(-1.0f, 1.0f),&#xD;&#xA;          random(-1.0f, 1.0f),&#xD;&#xA;          0.0f&#xD;&#xA;       );&#xD;&#xA;       noise[i].normalize();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Notice that the z component of the vector is zero. In the article John explain that he want to rotate the sample vector around the z axis. But later when he construct the TBN matrix, he use it as if it is a view space coordinate.&#xD;&#xA;&#xD;&#xA;    vec3 rvec = texture(uTexRandom, vTexcoord * uNoiseScale).xyz * 2.0 - 1.0;&#xD;&#xA;    vec3 tangent = normalize(rvec - normal * dot(rvec, normal));&#xD;&#xA;    vec3 bitangent = cross(normal, tangent);&#xD;&#xA;    mat3 tbn = mat3(tangent, bitangent, normal);&#xD;&#xA;&#xD;&#xA;I don't see any reason why the z vector of the noise vector should be zero. I think that the zero component could be any component. And then what happen if the normal vector is parallel with the noise vector, wouldn't it create a wrong TBN matrix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21024" PostHistoryTypeId="1" PostId="7976" RevisionGUID="8de7d5c2-657e-4cc6-a47f-f8333403ef9d" CreationDate="2018-08-27T14:22:43.880" UserId="8565" Text="SSAO random noise vector generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="21025" PostHistoryTypeId="3" PostId="7976" RevisionGUID="8de7d5c2-657e-4cc6-a47f-f8333403ef9d" CreationDate="2018-08-27T14:22:43.880" UserId="8565" Text="|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21026" PostHistoryTypeId="2" PostId="7977" RevisionGUID="c1b1409e-2516-4c2c-ab59-430b00a007a1" CreationDate="2018-08-27T15:01:04.483" UserId="2287" Text="**Alpha blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Additive blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Note that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21027" PostHistoryTypeId="5" PostId="7972" RevisionGUID="edebf91f-3f75-403c-b7d4-62f10b8adb57" CreationDate="2018-08-27T15:02:37.563" UserId="9260" Comment="used conventional vector notation" Text="I am trying to find an equation for a camera projection.&#xD;&#xA;The goal is to map the point $P(P_x, P_y, P_z)$ from the world coordinates onto the window coordinates $Q(Q_x, Q_y)$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The eye of viewing is located a distance D from the $\hat{e_1}$-$\hat{e_2}$ plane, and in the direction of -$\hat{e_3}$.&#xD;&#xA;$\hat{e_1}$, $\hat{e_2}$ and $\hat{e_3}$ are unit vectors.&#xD;&#xA;&#xD;&#xA;What is the equation to map P from world coordinates to window coordinates?&#xD;&#xA;$\vec{Q}(Q_x, Q_y) = f(\vec{P}, \hat{e_1}, \hat{e_2}, \hat{e_3}, \vec{v}, \vec{c})$&#xD;&#xA;with all the vectors on the right side described in terms of world coordinates, eg&#xD;&#xA;&#xD;&#xA;$\vec{P} = (P_x, P_y, P_z)$&#xD;&#xA;&#xD;&#xA;$\vec{C} = (C_x, C_y, C_z)$&#xD;&#xA;&#xD;&#xA;$\vec{e_1} = ({e_1}_x, {e_1}_y, {e_1}_z)$&#xD;&#xA;&#xD;&#xA;$\vec{e_2} = ({e_2}_x, {e_2}_y, {e_2}_z)$&#xD;&#xA;&#xD;&#xA;$\vec{e_3} = ({e_3}_x, {e_3}_y, {e_3}_z)$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hlTMG.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21028" PostHistoryTypeId="5" PostId="7977" RevisionGUID="8ba422a0-791d-4730-a26d-e94052a322fd" CreationDate="2018-08-27T15:31:08.097" UserId="2287" Comment="added 170 characters in body" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image in the framebuffer.&#xD;&#xA;&#xD;&#xA;# Alpha blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Note** that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21029" PostHistoryTypeId="8" PostId="7977" RevisionGUID="2246bded-c619-4535-85b8-7f04eb77f011" CreationDate="2018-08-27T15:42:13.767" UserId="2287" Comment="Rollback to [c1b1409e-2516-4c2c-ab59-430b00a007a1]" Text="**Alpha blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Additive blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Note that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21030" PostHistoryTypeId="5" PostId="7977" RevisionGUID="6410b5c8-dbf5-4d1e-83a7-d8044e0fb0c2" CreationDate="2018-08-27T15:46:33.730" UserId="2287" Comment="deleted 4 characters in body" Text="**Alpha blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.a        ) + (destination.rgb × (1-source.a))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1          ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Additive blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Note that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21031" PostHistoryTypeId="5" PostId="7977" RevisionGUID="9cf17277-03b2-4487-87c6-36cf7da9b6ff" CreationDate="2018-08-27T15:57:42.810" UserId="2287" Comment="added 227 characters in body" Text="**Alpha blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.a        ) + (destination.rgb × (1-source.a))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1          ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Obviously, you need to sort your fragments in advance (which is not always possible) or need to render your opaque fragments before your transparent fragments when using alpha blending to add a single layer of transparency.&#xD;&#xA;&#xD;&#xA;**Additive blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Note that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21032" PostHistoryTypeId="5" PostId="7977" RevisionGUID="bba18d11-27ff-47f6-af6a-5f97a719aa78" CreationDate="2018-08-27T16:08:10.913" UserId="2287" Comment="added 100 characters in body" Text="**Alpha blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.a        ) + (destination.rgb × (1-source.a))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1          ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Obviously, you need to sort your fragments in advance according to their depth (which is not always possible) or need to render your opaque fragments before your transparent fragments when using alpha blending to add a single layer of transparency.&#xD;&#xA;&#xD;&#xA;It is also important to clear your frame buffer to {r,g,b,1.0f} colors.&#xD;&#xA;&#xD;&#xA;**Additive blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Note that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21033" PostHistoryTypeId="8" PostId="7977" RevisionGUID="230b4c54-b5c4-417a-9c74-d7d369563bce" CreationDate="2018-08-27T16:09:20.893" UserId="2287" Comment="Rollback to [2246bded-c619-4535-85b8-7f04eb77f011]" Text="**Alpha blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Additive blending**&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Note that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21034" PostHistoryTypeId="8" PostId="7977" RevisionGUID="fc0df158-550c-4a53-9467-462c158f4531" CreationDate="2018-08-27T16:09:49.847" UserId="2287" Comment="Rollback to [8ba422a0-791d-4730-a26d-e94052a322fd]" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image in the framebuffer.&#xD;&#xA;&#xD;&#xA;# Alpha blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Note** that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21035" PostHistoryTypeId="5" PostId="7977" RevisionGUID="1867b7df-6bdd-422f-89ca-bb4a19c3edac" CreationDate="2018-08-27T16:10:25.330" UserId="2287" Comment="added 329 characters in body" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image in the framebuffer.&#xD;&#xA;&#xD;&#xA;# Alpha blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Obviously, you need to sort your fragments in advance according to their depth (which is not always possible) or need to render your opaque fragments before your transparent fragments when using alpha blending to add a single layer of transparency.&#xD;&#xA;&#xD;&#xA;It is also important to clear your frame buffer to `{r,g,b,1.0f}` colors.&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Note** that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21036" PostHistoryTypeId="12" PostId="7977" RevisionGUID="aa730f9e-9c70-40a9-b677-ce0bcd9bd069" CreationDate="2018-08-27T16:14:09.493" UserId="2287" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2287,&quot;DisplayName&quot;:&quot;Matthias&quot;}]}" />
  <row Id="21037" PostHistoryTypeId="5" PostId="7967" RevisionGUID="0c6db03e-fb64-410f-9c85-20e11ac12d28" CreationDate="2018-08-27T17:13:21.230" UserId="9255" Comment="edited body" Text="I am not an expert in 3D nor computer graphics. Please forgive me if I use wrong wording.&#xD;&#xA;&#xD;&#xA;High level problem description: For an online shop, I would like to create mockup images of apparel (t-shirts, tank tops, hoodies) with a print placed on them. There are loads of information how to do this with photoshop, but I would like to have an automated way to handle this. The image manipulation should happen with imagemagick finally.&#xD;&#xA;&#xD;&#xA;The images should be captured on a dummy under a controlled setting. The image creation should include following steps:&#xD;&#xA;&#xD;&#xA; * Capture a image from the front of a white shirt.&#xD;&#xA; * Capture a series of images of the dummy with the shirt as the dummy rotates around itself to create a photogrammetry 3D model of the dummy with the shirt.&#xD;&#xA;&#xD;&#xA;The image taken from the front will be the basis of the product image later on. The 3D model should be used to create analyse the distortion which has to be applied to the design/print on the shirt. This is the step i am interested in.&#xD;&#xA;&#xD;&#xA;The image composition should happen in this steps:&#xD;&#xA;&#xD;&#xA; * use the image from the front as the base.&#xD;&#xA; * Extract the shadows of the image.&#xD;&#xA; * Blend a color layer over the shirt, to get the different product color.&#xD;&#xA; * Map the design (a graphic or a text) over the white shirt using a distortion method to squeeze and pull apart the design following the perspective change created through the shape of the dummy.&#xD;&#xA;&#xD;&#xA;My idea had been to use a 3D method an image of a grid as the design on the 3D model somehow and analyse the the created 2D image for the distortion of the grid to get a model of how to squeeze and pull the design then in the image stacking process.&#xD;&#xA;&#xD;&#xA;Do you have any recommendations how to do this in practical steps? Or can you suggest me an different approach to get the desired result?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="21038" PostHistoryTypeId="5" PostId="7977" RevisionGUID="4f4a59a7-bbc7-4673-bf0e-811b760a4edb" CreationDate="2018-08-27T17:28:46.547" UserId="2287" Comment="deleted 1660 characters in body" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image in the framebuffer." ContentLicense="CC BY-SA 4.0" />
  <row Id="21039" PostHistoryTypeId="8" PostId="7977" RevisionGUID="66368e46-b37e-4a85-9dc3-ea2fe18da29d" CreationDate="2018-08-27T17:34:16.703" UserId="2287" Comment="Rollback to [1867b7df-6bdd-422f-89ca-bb4a19c3edac]" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image in the framebuffer.&#xD;&#xA;&#xD;&#xA;# Alpha blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  source.alpha    ) + (destination.rgb × (1-source.alpha))&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   ×  1              ).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorSourceAlpha;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOneMinusSourceAlpha;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Obviously, you need to sort your fragments in advance according to their depth (which is not always possible) or need to render your opaque fragments before your transparent fragments when using alpha blending to add a single layer of transparency.&#xD;&#xA;&#xD;&#xA;It is also important to clear your frame buffer to `{r,g,b,1.0f}` colors.&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb ×  1               ) + (destination.rgb × 1)&#xD;&#xA;    // (source.a   × (1-destination.a)) + (destination.a   × 1).&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOneMinusDestinationAlpha;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Note** that I removed the `descriptor.colorAttachments[0]` prefixes for clarity." ContentLicense="CC BY-SA 4.0" />
  <row Id="21040" PostHistoryTypeId="5" PostId="7977" RevisionGUID="2b29c406-ef40-4d96-970f-b1d2e0e750fe" CreationDate="2018-08-27T17:35:06.577" UserId="2287" Comment="deleted 1078 characters in body" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image in the framebuffer.&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgba × 1) + (destination.rgba × 1)&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOne;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Note** that I removed the `descriptor.colorAttachments[0]` prefixes for clarity.&#xD;&#xA;&#xD;&#xA;If the clear color is equal to `{0.0f,0.0f,0.0f,_}` and we draw `{0.1f,0.1f,0.1f,_}` to the same pixel a couple of times, the pixel color eventually becomes `{1.0f,1.0f,1.0f,_}` (white). Drawing `{0.0f,0.0f,0.0f,_}` (black) has no effect. We do not care about the alphas." ContentLicense="CC BY-SA 4.0" />
  <row Id="21041" PostHistoryTypeId="2" PostId="7978" RevisionGUID="cb2f7520-dd50-4c57-b273-4633494208d5" CreationDate="2018-08-27T17:38:40.370" UserId="506" Text="The “blend factors” are the amount that the specified component is multiplied by while blending. “Destination” is the existing content that’s being blended “on top of”, while “source” is the new content that’s being blended “onto” it. When the blend operation is set to “add”, the final pixel value is calculated like this:&#xD;&#xA;&#xD;&#xA;    value = source * sourceBlendFactor + destination * destinationBlendFactor&#xD;&#xA;&#xD;&#xA;…so a blend factor of “one” means the value is used unchanged (multiplied by 1), “[x]Alpha” means the value is multiplied by the alpha value of x (source or destination), and “oneMinus[x]Alpha” means the value is multiplied by (1 - the alpha value of x).&#xD;&#xA;&#xD;&#xA;For additive blending, you most likely want the following:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;There’s a really helpful tool for visualizing the different options [here](https://www.andersriggelsen.dk/glblendfunc.php)—it’s written for OpenGL, but the Metal stuff works the same way." ContentLicense="CC BY-SA 4.0" />
  <row Id="21042" PostHistoryTypeId="13" PostId="7977" RevisionGUID="10a2fff7-8ad1-41f5-9c0e-356d42487651" CreationDate="2018-08-27T17:38:42.613" UserId="2287" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2287,&quot;DisplayName&quot;:&quot;Matthias&quot;}]}" />
  <row Id="21043" PostHistoryTypeId="5" PostId="7977" RevisionGUID="d1860cdd-4455-4182-ba6b-d16fe3fd9499" CreationDate="2018-08-27T17:41:24.163" UserId="2287" Comment="added 37 characters in body" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image currently in the frame buffer (that will be overridden).&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgba × 1) + (destination.rgba × 1)&#xD;&#xA;&#xD;&#xA;    .blendingEnabled             = YES;&#xD;&#xA;    .rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    .alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    .sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    .sourceAlphaBlendFactor      = MTLBlendFactorOne;&#xD;&#xA;    .destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    .destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;**Note** that I removed the `descriptor.colorAttachments[0]` prefixes for clarity.&#xD;&#xA;&#xD;&#xA;If the clear color is equal to `{0.0f,0.0f,0.0f,_}` and we draw `{0.1f,0.1f,0.1f,_}` to the same pixel a couple of times, the pixel color eventually becomes `{1.0f,1.0f,1.0f,_}` (white). Drawing `{0.0f,0.0f,0.0f,_}` (black) has no effect. We do not care about the alphas." ContentLicense="CC BY-SA 4.0" />
  <row Id="21044" PostHistoryTypeId="5" PostId="7977" RevisionGUID="a74cc096-e66b-422a-8d55-fb7f6cfea995" CreationDate="2018-08-27T18:40:53.603" UserId="2287" Comment="added 365 characters in body" Text="# Terminology&#xD;&#xA;&#xD;&#xA; * The *source* color is the value written by the fragment/pixel shader. &#xD;&#xA; * The *destination* color is the color from the image currently in the frame buffer (that will be overridden).&#xD;&#xA;&#xD;&#xA;# Additive blending&#xD;&#xA;&#xD;&#xA;    // The blend formula is defined as:&#xD;&#xA;    // (source.rgb * sourceRGBBlendFactor  )   rgbBlendOperation (destination.rgb * destinationRGBBlendFactor  ) &#xD;&#xA;    // (source.a   * sourceAlphaBlendFactor) alphaBlendOperation (destination.a   * destinationAlphaBlendFactor)&#xD;&#xA;    // &lt;=&gt;&#xD;&#xA;    // (source.rgba * 1) + (destination.rgba * 1)&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled             = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation           = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation         = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor        = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor      = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor   = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;If the clear color is equal to `{0.0f,0.0f,0.0f,_}` and we draw `{0.1f,0.1f,0.1f,_}` to the same pixel a couple of times, the pixel color eventually becomes `{1.0f,1.0f,1.0f,_}` (white). Drawing `{0.0f,0.0f,0.0f,_}` (black) has no effect. We do not care about the alphas." ContentLicense="CC BY-SA 4.0" />
  <row Id="21045" PostHistoryTypeId="4" PostId="7969" RevisionGUID="6e3333d1-cd8c-47a0-9cad-69ccb0de260b" CreationDate="2018-08-28T03:11:15.460" UserId="5430" Comment="edited title" Text="Using multiply and accumulate of 4x4 matrices for ray-triangle intersection tests" ContentLicense="CC BY-SA 4.0" />
  <row Id="21046" PostHistoryTypeId="2" PostId="7979" RevisionGUID="93e14edb-c84f-448d-b8c5-07a92d9aa16a" CreationDate="2018-08-28T07:26:55.860" UserId="2308" Text="Here is my predicament. I am trying to draw a multitude of dots that leave trails behind them real time. Heres the difficulty, that line fades. Each dot line has a defined z position and the goal would be for everything to blend properly, in real time.&#xD;&#xA;&#xD;&#xA;I am currently doing this geometry with a series of triangles that form a triangle strip (I am not using a triangle strip due to the edge case in the circle buffer and spacial locality). This strip is currently implemented as a sort of circle buffer where old triangles are overridden. Each vertice gets passed in the time it was created and thus it knows how to fade (make transparent) its own color.&#xD;&#xA;&#xD;&#xA;To make things more complicated I am also drawing caps on the ends of the dot so there is essentially a half rectangle at the end with fragments of it discarded to shape it into a circle.&#xD;&#xA;&#xD;&#xA;All of this presents a predicament for alpha testing as alpha testing requires drawing to be sorted in order of depth. Just about all the geometry is transparent in some form. Even if I can get the triangle strip to do this properly getting the half circle working would be quite difficult.&#xD;&#xA;&#xD;&#xA;I set the z position based on the dot's id and use the same value that is used to dim the dot's trail to get the triangle strip to have non-conflicting depth.&#xD;&#xA;&#xD;&#xA;As for the half circle part does this mean I am going to have to do two draw calls per circle? One to render their segment of the triangle buffer and the other to draw the semi-circle?&#xD;&#xA;&#xD;&#xA;Currently I am using the following memory layout:&#xD;&#xA;&#xD;&#xA;    const int MAX_INDEX = 200;&#xD;&#xA;    const int MAX_DOTS = 10000;&#xD;&#xA;    int bufferIndex = (bufferIndex + 1) % MAX_INDEX;&#xD;&#xA;    int dotIndex = 0..&lt;MAX_DOTS&#xD;&#xA;    Rect = triangleStripBuffer[bufferIndex * MAX_DOTS + dotIndex];&#xD;&#xA;You can see that data in there is not naturally sorted by anything other than time but even that cycles and there is no consideration for drawing order.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I suppose I really need ideas on how I can get the geometry to draw in order so that alpha testing can occur. How do I combine these two different drawing goals in a good way? Do I need to k&#xD;&#xA;&#xD;&#xA;I figure this problem is fairly platform agnostic but if it is not I am working with Metal and eventually Vulcan on this." ContentLicense="CC BY-SA 4.0" />
  <row Id="21047" PostHistoryTypeId="1" PostId="7979" RevisionGUID="93e14edb-c84f-448d-b8c5-07a92d9aa16a" CreationDate="2018-08-28T07:26:55.860" UserId="2308" Text="Sorting my geometry for alpha testing" ContentLicense="CC BY-SA 4.0" />
  <row Id="21048" PostHistoryTypeId="3" PostId="7979" RevisionGUID="93e14edb-c84f-448d-b8c5-07a92d9aa16a" CreationDate="2018-08-28T07:26:55.860" UserId="2308" Text="|geometry|depth-map|blending|metal|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21049" PostHistoryTypeId="2" PostId="7980" RevisionGUID="4d58608e-5faf-4d10-aea2-e9ddf3d6d76b" CreationDate="2018-08-28T12:39:32.947" UserId="9266" Text="This picture depicts my current immagination of the coordinate systems involved in ray tracing:&#xD;&#xA;&#xD;&#xA;![my current imagination of the coordinate systems involved](https://i.stack.imgur.com/eyUEh.png)&#xD;&#xA;&#xD;&#xA;**Explanation:**&#xD;&#xA;So the green rectangle is the [-0.5, nx-0.5] x [-0.5, ny-0.5] coordinate system and you can translate that coordinate system to the {u, v, w} coordinate system's coordinates (the world coordinate system) w/ the equations near the green rectangle.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;From the origin of the world coordinate system, you can cast rays into the [l, r] x [b, t] coordinate system w/ the equation near the red rectangle ($s = e + u_{s} * u + v_{s} * v + w_{s} * w$).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The [-0.5, nx-0.5] x [-0.5, ny-0.5] matches a classic windowing systems coordinate sytem while the [l, r] x [b, t] seems to be the &quot;ray tracer's screen&quot;/&quot;ray tracer's view area&quot;.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;Both apparently define the view frustum depicted above. This however is counterintuitive for me since I expect the screen directly in front of the world coordinate system. So the screen I am seeing is the green rectangle, the [-0.5, nx-0.5] x [-0.5, ny-0.5]. That means everything goes backwards.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;**The ray tracer algorithm in my own words (and with my current understanding):**&#xD;&#xA;&#xD;&#xA;&quot;Cause&quot; the world space to shoot a ray so that it goes through each pixel of the window screen [-0.5, nx-0.5] x [-0.5, ny-0.5] and check for an intersection within the frustum along the way. If there is an intersection color it, if not leave it at the background color.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;IOW: I am a &quot;commander&quot; and as I go through each pixel of [-0.5, nx-0.5] x [-0.5, ny-0.5] I cause the world space to shoot/cast a ray so that it goes through the pixel that I am currently at as well while checking for intersections within the frustum.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;With my current understanding I tried to implement a ray tracer on the basis of a set_pixel() function.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;**My implementation attempt (w/ a skewed green sphere as a result):**&#xD;&#xA;&#xD;&#xA;    void game::Engine::run()&#xD;&#xA;{	&#xD;&#xA;&#xD;&#xA;	int nx = window_width; // 1366&#xD;&#xA;	int ny = window_heigth; // 768&#xD;&#xA;	// Construct the &quot;ray tracer window&quot;/&quot;ray tracer screen&quot;&#xD;&#xA;	int left = -200;&#xD;&#xA;	int right = 200;&#xD;&#xA;	int top = 100;&#xD;&#xA;	int bottom = -100;&#xD;&#xA;	int distance = 10;&#xD;&#xA;	// Create the {u, v, w} coordinate system&#xD;&#xA;	Vec3f e{ 0, 0, float(distance) };&#xD;&#xA;	Vec3f u{ 1, 0, 0 };&#xD;&#xA;	Vec3f v{ 0, 1, 0 };&#xD;&#xA;	Vec3f w{ 0, 0, float(distance) };&#xD;&#xA;	// Create the sphere&#xD;&#xA;	Vec3f center{ -50, -20, 11 };&#xD;&#xA;	float radius = 3.0f;&#xD;&#xA;&#xD;&#xA;	// Game loop&#xD;&#xA;	bool running{ true };&#xD;&#xA;	SDL_Event event{};&#xD;&#xA;	while (running)&#xD;&#xA;	{&#xD;&#xA;		// Clear buffer&#xD;&#xA;		SDL_SetRenderDrawColor(renderer, 153, 153, 153, 255);&#xD;&#xA;		SDL_RenderClear(renderer);&#xD;&#xA;&#xD;&#xA;		// Draw&#xD;&#xA;		for (int i = 0; i &lt;= window_width; ++i) {&#xD;&#xA;			for (int j = 0; j &lt; window_heigth; ++j) {&#xD;&#xA;				// Calculate the scalar factors from the pixel position for each axis of the {u, v, w} coordinate system&#xD;&#xA;				float u_s = (left + (right - left) * (i + 0.5)) / nx;&#xD;&#xA;				float v_s = (bottom + (top - bottom) * (j + 0.5)) / ny;&#xD;&#xA;				float w_s = -distance;&#xD;&#xA;				// Cast a ray (in a perspective manner)&#xD;&#xA;				Ray3f s{ e, u * u_s + v * v_s + w * w_s};&#xD;&#xA;				Vec3f co = center - s.origin_vector;&#xD;&#xA;				// Calculate the intersection between the sphere and the ray&#xD;&#xA;				float a = Vec3f::dot_product(s.direction_vector, s.direction_vector);&#xD;&#xA;				float b = 2 * Vec3f::dot_product(co, s.direction_vector);&#xD;&#xA;				float c = Vec3f::dot_product(co, co) - radius * radius;&#xD;&#xA;				float discriminant = b * b - 4 * a * c;&#xD;&#xA;				Vec3f color_vec{ 0, 0, 0 }; // default background color&#xD;&#xA;				if (discriminant &gt; 0)&#xD;&#xA;				{&#xD;&#xA;					// Make the hit sphere green&#xD;&#xA;					color_vec.x = 0;&#xD;&#xA;					color_vec.y = 1;&#xD;&#xA;					color_vec.z = 0;&#xD;&#xA;				}&#xD;&#xA;				set_pixel(renderer, i, j, 255 * color_vec.x, 255 * color_vec.y, 255 * color_vec.z, 255);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		// Swap buffers&#xD;&#xA;		SDL_RenderPresent(renderer);&#xD;&#xA;		// Process event queue&#xD;&#xA;		while (SDL_PollEvent(&amp;event))&#xD;&#xA;		{&#xD;&#xA;			switch (event.type)&#xD;&#xA;			{&#xD;&#xA;			case SDL_QUIT:&#xD;&#xA;				running = false;&#xD;&#xA;				break;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;**The result:**&#xD;&#xA;![result](https://i.stack.imgur.com/791eG.png)&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;**My conclusion:**&#xD;&#xA;I got the coordinate system totaly wrong thus the skewed result.&#xD;&#xA;So the window 1366 x 768 and the ray tracer's screen 400 x 200 as well as the world coordinate system that is spanned with the standard basis in the code doesn't lead to the expected result the sphere beeing on the center of the screen and not looking skewed. Plus, the coordinate system acts weird and seems to be arbitrary.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;Thus something is fundamentally wrong with my current understanding.&#xD;&#xA;&#xD;&#xA;**References:**&#xD;&#xA;&lt;br&gt;&#xD;&#xA;[Lecture on ray tracing][1]&#xD;&#xA;&lt;br&gt;&#xD;&#xA;[Peter Shirley's treatise on ray tracing][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=zQIvR_6IayM&amp;feature=youtu.be&amp;t=27m16s&#xD;&#xA;  [2]: https://www.cs.utah.edu/~shirley/books/fcg2/rt.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="21050" PostHistoryTypeId="1" PostId="7980" RevisionGUID="4d58608e-5faf-4d10-aea2-e9ddf3d6d76b" CreationDate="2018-08-28T12:39:32.947" UserId="9266" Text="Problem of understanding the coordinate systems involved in ray tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="21051" PostHistoryTypeId="3" PostId="7980" RevisionGUID="4d58608e-5faf-4d10-aea2-e9ddf3d6d76b" CreationDate="2018-08-28T12:39:32.947" UserId="9266" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21052" PostHistoryTypeId="2" PostId="7981" RevisionGUID="d502573b-780e-41a5-bc4c-27554b3ceaf8" CreationDate="2018-08-28T13:23:49.310" UserId="6530" Text="Yes, it is possible.  For one however, Möller-Trumbore is not the only algorithm out there for ray triangle intersection, [there exist others][1]. &#xD;&#xA;&#xD;&#xA;However all of these rely on linear algebra vector multiplications and matrix operations.  These can be combined into 4x4 tensor core operations (and each tensor core can do 4x4x4, but there are 8 cuda cores to every tensor core).   You can compute multiple intersections in Möller-Trumbore at a time with tensor cores.  You could say, combine multiple cross products or dot products into a single matrix operation. &#xD;&#xA;&#xD;&#xA;The catches?  Well first, the precision of tensor cores matrix multiplication is **16bit** float.  But don't fret, given decent spatial subdivision of, say, a raytraced environment, that precision should only matter *per spatial block/voxel/subdivision* which is necessary in ray-tracing in order to not test all triangles in the scene. 16 bit for a 10 km area might be a big deal in terms of poor position precision, but for a 2x2 meter area it isn't (mantissa alone will handle 1024 different values). Note the addition part *is* 32bit float. &#xD;&#xA;&#xD;&#xA;Second, [you have to move data around in such a way that tensor cores can actually access it][2], which, because it is unlikely that any of us on this entire site have direct access to a machine with tensorcores, has a yet unknown performance cost.  &#xD;&#xA;&#xD;&#xA;Third, I'm not entirely sure its possible to do *both* tensor core calculations and *scalar* calculations at the same time.  This could end up *slowing* many tasks to the point that any advantage tensor cores gave becomes negligible.  But I could be wrong and we can actually hide things like latency for tensor core memory moves with multiple floating point and tensor core instructions interleaved. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0005/03/03/paper.pdf&#xD;&#xA;  [2]: https://devblogs.nvidia.com/programming-tensor-cores-cuda-9/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21053" PostHistoryTypeId="2" PostId="7982" RevisionGUID="cea487de-0286-4a28-b5b8-3da3f84b6775" CreationDate="2018-08-28T15:13:48.017" UserId="6046" Text="I gave it a quick look and I found several places which need attention. First of all you forgot transforming the view space to NDC space.&#xD;&#xA;&#xD;&#xA;We are working with 3 spaces. &#xD;&#xA;&#xD;&#xA;**1)** The world space, which is the global reference frame. You usually define spheres in this frame. Or if you are reading model data, you might want to multiply by a model matrix to bring them into world space.&#xD;&#xA;&#xD;&#xA;**2)** The camera space. This is the part of the world the camera views. The correct equation for generating rays in the camera space as i mentioned in the comments are given by.&#xD;&#xA;&#xD;&#xA;$ x = l + (r-l)*(pixel_i * 0.5)/Width$&#xD;&#xA;&#xD;&#xA;$ y = b + (t-b)*(pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**3)** The third is the NDC space which is usually in the range $[-1,1]$ Some API's have this range in $[0,1]$ For ray tracing however, we are concerned with $[-1,1]$. The concept here is, imagine your whole image which is $Width \times Height$ to be mapped to a plane which is $2 \times 2$ units wide centered at the origin. However this is for square images. What happens when `width != height`?&#xD;&#xA;&#xD;&#xA;Then we have &#xD;&#xA;&#xD;&#xA;$ x = [-a, a]$&#xD;&#xA;&#xD;&#xA;$ y = [-1, 1]$&#xD;&#xA;&#xD;&#xA;Where $a$ is Aspect Ratio given by. &#xD;&#xA;&#xD;&#xA;$ a = Width/Height $ &#xD;&#xA;&#xD;&#xA;However this assumes the camera is positioned at the origin. How do take into account for camera rotation and position. Normally this is done by the use of a camera matrix which transforms from world space to camera or vice versa. I will not go into details about this one. &#xD;&#xA;&#xD;&#xA;The way you are calculating the rays in camera space, haven't seen much like this but there is a simple fix to get a moving camera and transform it in NDC space. You divide by the width and height of the camera volume. So your equations become.&#xD;&#xA;&#xD;&#xA;$ x = [l + (r-l)*(pixel_i * 0.5)/Width] / (r-l)$&#xD;&#xA;&#xD;&#xA;$\therefore x = l/(r-l) + (pixel_i * 0.5)/Width $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$ y = [b + (t-b)*(pixel_y * 0.5)/Height] / (t-b)$&#xD;&#xA;&#xD;&#xA;$\therefore y = b/(t-b) + (pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;Now you normalize this direction. As for the proper way of intersecting spheres (if you are normalizing direction, which you should, would be)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    co = ray.origin - sphere.center // Note we subtract center FROM origin.&#xD;&#xA;     b = dot(co, ray.dir);&#xD;&#xA;     c = dot(co, co) - sphere.radius * sphere.radius;&#xD;&#xA;     disc = b*b - c;&#xD;&#xA;     if disc &gt;= 0&#xD;&#xA;       t = -b + sqrt(disc)&#xD;&#xA;     if ( t &gt;= 0)&#xD;&#xA;     {&#xD;&#xA;      ray.length = t;       /* you can add a length parameter in ray as &#xD;&#xA;                               direction is normalized&#xD;&#xA;                               Set other parameters such as sphere id, or if &#xD;&#xA;                               there is only 1 sphere, set color here. */&#xD;&#xA;      return true;&#xD;&#xA;     }&#xD;&#xA;     else&#xD;&#xA;      return false;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21054" PostHistoryTypeId="5" PostId="7982" RevisionGUID="f41717a2-412c-4deb-bda0-7d64715f9463" CreationDate="2018-08-28T15:29:25.450" UserId="6046" Comment="added 763 characters in body" Text="I gave it a quick look and I found several places which need attention. First of all you forgot transforming the view space to NDC space.&#xD;&#xA;&#xD;&#xA;We are working with 3 spaces. &#xD;&#xA;&#xD;&#xA;**1)** The world space, which is the global reference frame. You usually define spheres in this frame. Or if you are reading model data, you might want to multiply by a model matrix to bring them into world space.&#xD;&#xA;&#xD;&#xA;**2)** The camera space. This is the part of the world the camera views. The correct equation for generating rays in the camera space as i mentioned in the comments are given by.&#xD;&#xA;&#xD;&#xA;$ x = l + (r-l)*(pixel_i * 0.5)/Width$&#xD;&#xA;&#xD;&#xA;$ y = b + (t-b)*(pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**3)** The third is the NDC space which is usually in the range $[-1,1]$ Some API's have this range in $[0,1]$ For ray tracing however, we are concerned with $[-1,1]$. The concept here is, imagine your whole image which is $Width \times Height$ to be mapped to a plane which is $2 \times 2$ units wide centered at the origin. This is somewhat a generalization. We don't need to mess with the width and height anymore. We introduced an intermediary space where everything is in the range [-1,1]. &#xD;&#xA;&#xD;&#xA;However this is true only for square images. What happens when `width != height`?&#xD;&#xA;&#xD;&#xA;Then we have to account for it by doing,&#xD;&#xA;&#xD;&#xA;$ x = [-a, a]$&#xD;&#xA;&#xD;&#xA;$ y = [-1, 1]$&#xD;&#xA;&#xD;&#xA;Where $a$ is Aspect Ratio given by. &#xD;&#xA;&#xD;&#xA;$ a = Width/Height $ &#xD;&#xA;&#xD;&#xA;The NDC space is usually calcualted as,&#xD;&#xA;&#xD;&#xA;$ x_{ndc} = [ (2 * ( i+ 0.5)/Width) - 1] * Aspect Ratio$&#xD;&#xA;&#xD;&#xA;$ y_{ndc} = [ (2 * ( y+ 0.5)/Width) - 1]$&#xD;&#xA;&#xD;&#xA;Note tho depending on the image coordinates, we might need to flip $y_{ndc}$. The calculation above assumes Image has the origin at the top left corner. If the origin is at the bottom left, we will need to flip.&#xD;&#xA;&#xD;&#xA;However this assumes the camera is positioned at the origin. How do take into account for camera rotation and position. Normally this is done by the use of a camera matrix which transforms from world space to camera or vice versa. You calculate ray direction in the NDC space, multiply it by this matrix and then normalize it. I will not go into details about this one. &#xD;&#xA;&#xD;&#xA;The way you are calculating the rays in camera space, haven't seen much like this but there is a simple fix to get a moving camera and transform it in NDC space. You divide by the width and height of the camera volume. So your equations become. &#xD;&#xA;&#xD;&#xA;$ x = [l + (r-l)*(pixel_i * 0.5)/Width] / (r-l)$&#xD;&#xA;&#xD;&#xA;$\therefore x = l/(r-l) + (pixel_i * 0.5)/Width $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$ y = [b + (t-b)*(pixel_y * 0.5)/Height] / (t-b)$&#xD;&#xA;&#xD;&#xA;$\therefore y = b/(t-b) + (pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;You don't need to account for aspect ratio in this scenario as it's already being done by $l/(r-l)$ and $b/(t-b)$ factors. &#xD;&#xA;&#xD;&#xA;As for the proper way of intersecting spheres (if you are normalizing direction, which you should, would be)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    co = ray.origin - sphere.center // Note we subtract center FROM origin.&#xD;&#xA;     b = dot(co, ray.dir);&#xD;&#xA;     c = dot(co, co) - sphere.radius * sphere.radius;&#xD;&#xA;     disc = b*b - c;&#xD;&#xA;     if disc &gt;= 0&#xD;&#xA;       t = -b + sqrt(disc)&#xD;&#xA;     if ( t &gt;= 0)&#xD;&#xA;     {&#xD;&#xA;      ray.length = t;       /* you can add a length parameter in ray as &#xD;&#xA;                               direction is normalized&#xD;&#xA;                               Set other parameters such as sphere id, or if &#xD;&#xA;                               there is only 1 sphere, set color here. */&#xD;&#xA;      return true;&#xD;&#xA;     }&#xD;&#xA;     else&#xD;&#xA;      return false;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21055" PostHistoryTypeId="5" PostId="7982" RevisionGUID="1e247e1f-0b1f-44fb-9dd0-d582c06a4b12" CreationDate="2018-08-28T16:12:08.583" UserId="6046" Comment="added 127 characters in body" Text="I gave it a quick look and I found several places which need attention. First of all you forgot transforming the view space to NDC space.&#xD;&#xA;&#xD;&#xA;We are working with 3 spaces. &#xD;&#xA;&#xD;&#xA;**1)** The world space, which is the global reference frame. You usually define spheres in this frame. Or if you are reading model data, you might want to multiply by a model matrix to bring them into world space.&#xD;&#xA;&#xD;&#xA;**2)** The camera space. This is the part of the world the camera views. The correct equation for generating rays in the camera space as i mentioned in the comments are given by.&#xD;&#xA;&#xD;&#xA;$ x = l + (r-l)*(pixel_i * 0.5)/Width$&#xD;&#xA;&#xD;&#xA;$ y = b + (t-b)*(pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**3)** The third is the NDC space which is usually in the range $[-1,1]$ Some API's have this range in $[0,1]$ For ray tracing however, we are concerned with $[-1,1]$. The concept here is, imagine your whole image which is $Width \times Height$ to be mapped to a plane which is $2 \times 2$ units wide centered at the origin. This is somewhat a generalization. We don't need to mess with the width and height anymore. We introduced an intermediary space where everything is in the range [-1,1]. &#xD;&#xA;&#xD;&#xA;However this is true only for square images. What happens when `width != height`?&#xD;&#xA;&#xD;&#xA;Then we have to account for it by doing,&#xD;&#xA;&#xD;&#xA;$ x = [-a, a]$&#xD;&#xA;&#xD;&#xA;$ y = [-1, 1]$&#xD;&#xA;&#xD;&#xA;Where $a$ is Aspect Ratio given by. &#xD;&#xA;&#xD;&#xA;$ a = Width/Height $ &#xD;&#xA;&#xD;&#xA;The NDC space is usually calcualted as,&#xD;&#xA;&#xD;&#xA;$ x_{ndc} = [ (2 * ( i+ 0.5)/Width) - 1] * Aspect Ratio$&#xD;&#xA;&#xD;&#xA;$ y_{ndc} = [ (2 * ( y+ 0.5)/Width) - 1]$&#xD;&#xA;&#xD;&#xA;Note tho depending on the image coordinates, we might need to flip $y_{ndc}$. The calculation above assumes Image has the origin at the top left corner. If the origin is at the bottom left, we will need to flip.&#xD;&#xA;&#xD;&#xA;However this assumes the camera is positioned at the origin. How do take into account for camera rotation and position. Normally this is done by the use of a camera matrix which transforms from world space to camera or vice versa. You calculate ray direction in the NDC space, multiply it by this matrix and then normalize it. I will not go into details about this one. &#xD;&#xA;&#xD;&#xA;The way you are calculating the rays in camera space, haven't seen much like this but there is a simple fix to get a moving camera and transform it in NDC space. You divide by the width and height of the camera volume. So your equations become. &#xD;&#xA;&#xD;&#xA;$ x = [l + (r-l)*(pixel_i * 0.5)/Width] / (r-l)$&#xD;&#xA;&#xD;&#xA;$\therefore x = l/(r-l) + (pixel_i * 0.5)/Width $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$ y = [b + (t-b)*(pixel_y * 0.5)/Height] / (t-b)$&#xD;&#xA;&#xD;&#xA;$\therefore y = b/(t-b) + (pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;You don't need to account for aspect ratio in this scenario as it's already being done by $l/(r-l)$ and $b/(t-b)$ factors. &#xD;&#xA;&#xD;&#xA;As for the proper way of intersecting spheres (if you are normalizing direction, which you should, would be)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    co = ray.origin - sphere.center // Note we subtract center FROM origin.&#xD;&#xA;     b = dot(co, ray.dir);&#xD;&#xA;     c = dot(co, co) - sphere.radius * sphere.radius;&#xD;&#xA;     disc = b*b - c;&#xD;&#xA;     if disc &gt;= 0&#xD;&#xA;       t = -b + sqrt(disc)&#xD;&#xA;     if ( t &gt;= 0)&#xD;&#xA;     {&#xD;&#xA;      ray.length = t;       /* you can add a length parameter in ray as &#xD;&#xA;                               direction is normalized&#xD;&#xA;                               Set other parameters such as sphere id, or if &#xD;&#xA;                               there is only 1 sphere, set color here. */&#xD;&#xA;      return true;&#xD;&#xA;     }&#xD;&#xA;     else&#xD;&#xA;      return false;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:- Also forgot to mention your spheres $Z$ coordinates should be negative. Since rays are generating in the $-Z$ direction.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21056" PostHistoryTypeId="5" PostId="7982" RevisionGUID="c5efd237-2b3a-4512-806b-5172313b239b" CreationDate="2018-08-28T17:03:04.280" UserId="6046" Comment="added 19 characters in body" Text="I gave it a quick look and I found several places which need attention. First of all you forgot transforming the view space to NDC space.&#xD;&#xA;&#xD;&#xA;We are working with 3 spaces. &#xD;&#xA;&#xD;&#xA;**1)** The world space, which is the global reference frame. You usually define spheres in this frame. Or if you are reading model data, you might want to multiply by a model matrix to bring them into world space.&#xD;&#xA;&#xD;&#xA;**2)** The camera space. This is the part of the world the camera views. The correct equation for generating rays in the camera space as i mentioned in the comments are given by.&#xD;&#xA;&#xD;&#xA;$ x = l + (r-l)*(pixel_i * 0.5)/Width$&#xD;&#xA;&#xD;&#xA;$ y = b + (t-b)*(pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**3)** The third is the NDC space which is usually in the range $[-1,1]$ Some API's have this range in $[0,1]$ For ray tracing however, we are concerned with $[-1,1]$. The concept here is, imagine your whole image which is $Width \times Height$ to be mapped to a plane which is $2 \times 2$ units wide centered at the origin. This is somewhat a generalization. We don't need to mess with the width and height anymore. We introduced an intermediary space where everything is in the range [-1,1]. &#xD;&#xA;&#xD;&#xA;However this is true only for square images. What happens when `width != height`?&#xD;&#xA;&#xD;&#xA;Then we have to account for it by doing,&#xD;&#xA;&#xD;&#xA;$ x = [-a, a]$&#xD;&#xA;&#xD;&#xA;$ y = [-1, 1]$&#xD;&#xA;&#xD;&#xA;Where $a$ is Aspect Ratio given by. &#xD;&#xA;&#xD;&#xA;$ a = Width/Height $ &#xD;&#xA;&#xD;&#xA;The NDC space is usually calcualted as,&#xD;&#xA;&#xD;&#xA;$ x_{ndc} = [ (2 * ( i+ 0.5)/Width) - 1] * Aspect Ratio$&#xD;&#xA;&#xD;&#xA;$ y_{ndc} = [ (2 * ( y+ 0.5)/Width) - 1]$&#xD;&#xA;&#xD;&#xA;Note tho depending on the image coordinates, we might need to flip $y_{ndc}$. The calculation above assumes Image has the origin at the top left corner. If the origin is at the bottom left, we will need to flip.&#xD;&#xA;&#xD;&#xA;However this assumes the camera is positioned at the origin. How do take into account for camera rotation and position. Normally this is done by the use of a camera matrix which transforms from world space to camera or vice versa. You calculate ray direction in the NDC space, multiply it by this matrix and then normalize it. I will not go into details about this one. &#xD;&#xA;&#xD;&#xA;The way you are calculating the rays in camera space, haven't seen much like this but there is a simple fix to get a moving camera and transform it in NDC space. You divide by the width and height of the camera volume. So your equations become. &#xD;&#xA;&#xD;&#xA;$ x = [l + (r-l)*(pixel_i * 0.5)/Width] / (r-l)$&#xD;&#xA;&#xD;&#xA;$\therefore x = l/(r-l) + (pixel_i * 0.5)/Width $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$ y = [b + (t-b)*(pixel_y * 0.5)/Height] / (t-b)$&#xD;&#xA;&#xD;&#xA;$\therefore y = b/(t-b) + (pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;You don't need to account for aspect ratio in this scenario as it's already being done by $l/(r-l)$ and $b/(t-b)$ factors. &#xD;&#xA;&#xD;&#xA;As for the proper way of intersecting spheres (if you are normalizing direction, which you should, would be)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;     t = -1.0f;&#xD;&#xA;     co = ray.origin - sphere.center // Note we subtract center FROM origin.&#xD;&#xA;     b = dot(co, ray.dir);&#xD;&#xA;     c = dot(co, co) - sphere.radius * sphere.radius;&#xD;&#xA;     disc = b*b - c;&#xD;&#xA;     if disc &gt;= 0&#xD;&#xA;       t = -b + sqrt(disc);&#xD;&#xA;     if ( t &gt;= 0)&#xD;&#xA;     {&#xD;&#xA;      ray.length = t;       /* you can add a length parameter in ray as &#xD;&#xA;                               direction is normalized&#xD;&#xA;                               Set other parameters such as sphere id, or if &#xD;&#xA;                               there is only 1 sphere, set color here. */&#xD;&#xA;      return true;&#xD;&#xA;     }&#xD;&#xA;     else&#xD;&#xA;      return false;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:- Also forgot to mention your spheres $Z$ coordinates should be negative. Since rays are generating in the $-Z$ direction.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21057" PostHistoryTypeId="5" PostId="7969" RevisionGUID="179a73df-496b-401f-8d25-7069fff08c32" CreationDate="2018-08-28T17:05:35.217" UserId="5430" Comment="added 64 characters in body" Text="Is it possible to gain performance boost using new 4x4 MAD from [NVIDIA'a tensor cores](https://devblogs.nvidia.com/programming-tensor-cores-cuda-9/) for ray-triangle intersection tests?&#xD;&#xA;&#xD;&#xA;Really there are two questions:&#xD;&#xA;&#xD;&#xA; - Is it possible to modify some of the ray-triangle algorithms (say, Möller-Trumbore algorithm) to base it on 4x4 matrix MAD.&#xD;&#xA; - Would it be a performance improvement?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21058" PostHistoryTypeId="2" PostId="7983" RevisionGUID="87b08530-1258-428e-b1b8-618e088b6114" CreationDate="2018-08-28T19:34:58.110" UserId="9270" Text="As mentioned [here][1], multiple VAOs can share a single VBO. However, can multiple VAOs share a single EBO?&#xD;&#xA;&#xD;&#xA;For example, I want to create 2 rectangles. So, I do the following:&#xD;&#xA;&#xD;&#xA;    const GLuint indices[6] = {&#xD;&#xA;		0, 1, 2,&#xD;&#xA;		0, 3, 2&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;    // First&#xD;&#xA;    glGenVertexArrays (1, &amp;VAO1);&#xD;&#xA;	glBindVertexArray (VAO1);&#xD;&#xA;	glGenBuffers (1, &amp;EBO1);&#xD;&#xA;	glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO1);&#xD;&#xA;	glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;    // creating VBO, setting attributes etc&#xD;&#xA;    // Second&#xD;&#xA;    glGenVertexArrays (1, &amp;VAO2);&#xD;&#xA;	glBindVertexArray (VAO2);&#xD;&#xA;	glGenBuffers (1, &amp;EBO2);&#xD;&#xA;	glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO2);&#xD;&#xA;	glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;`glBufferData(GL_ELEMENT_ARRAY_BUFFER)` is called twice for different EBOs with same data. As I understand, this leads to double GPU memory consumption and takes twice loading time. &#xD;&#xA;&#xD;&#xA;So, would the following be correct?&#xD;&#xA;&#xD;&#xA;    const GLuint indices[6] = {&#xD;&#xA;		0, 1, 2,&#xD;&#xA;		0, 3, 2&#xD;&#xA;	};&#xD;&#xA;    glGenBuffers (1, &amp;EBO);&#xD;&#xA;	glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;	glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    // First&#xD;&#xA;    glGenVertexArrays (1, &amp;VAO1);&#xD;&#xA;	glBindVertexArray (VAO1);&#xD;&#xA;	glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;    // creating VBO, setting attributes etc&#xD;&#xA;    // Second&#xD;&#xA;    glGenVertexArrays (1, &amp;VAO2);&#xD;&#xA;	glBindVertexArray (VAO2);&#xD;&#xA;	glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4623/multiple-vao-share-a-vbo" ContentLicense="CC BY-SA 4.0" />
  <row Id="21059" PostHistoryTypeId="1" PostId="7983" RevisionGUID="87b08530-1258-428e-b1b8-618e088b6114" CreationDate="2018-08-28T19:34:58.110" UserId="9270" Text="Multiple VAO share a EBO (OpenGL 3.3)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21060" PostHistoryTypeId="3" PostId="7983" RevisionGUID="87b08530-1258-428e-b1b8-618e088b6114" CreationDate="2018-08-28T19:34:58.110" UserId="9270" Text="|opengl|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21061" PostHistoryTypeId="2" PostId="7984" RevisionGUID="ba9dc09d-398b-42a9-b298-49c179e27b99" CreationDate="2018-08-28T19:51:48.443" UserId="2485" Text="I am generating plane vertices where the y values are generated by a heightmap (noise) algorithm. This is how I produce my vertex array:&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; noise.length; row++) {&#xD;&#xA;        for (let col = 0; col &lt; noise[0].length; col++) {&#xD;&#xA;            color = noise[row][col];&#xD;&#xA;            positions.push(row, color, col);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After that I generate index values like this (I know that there is a lot of optimization that can be done here):&#xD;&#xA;&#xD;&#xA;    const height = noise.length + 1;&#xD;&#xA;    const width = noise[0].length + 1;&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; height - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            if (row === height - 2) break;&#xD;&#xA;            for (let col = 0; col &lt; width - 1; col++) {&#xD;&#xA;                indices.push(col + row * (width));&#xD;&#xA;                indices.push(col - 1 + (row + 1) * (width));&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = width - 2; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col - 2 + (row + 1) * (width));&#xD;&#xA;                indices.push(col - 2 + row * (width));&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    indices.pop();&#xD;&#xA;&#xD;&#xA;Finally I draw the plane using:&#xD;&#xA;&#xD;&#xA; `gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);`&#xD;&#xA;&#xD;&#xA;So if I use `POINTS` as mode, the plane seem to look as it should:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Whereas if I am using `TRINGLE_STRIP` the result looks wrong:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;First I thought wrong indices might be the reason but then I checked by scaling to a 3x3 grid/plane and the vertex and index output looked as I would have expected:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;    [-1, -43.89, -1, &#xD;&#xA;    -1,  -82.27,  0, &#xD;&#xA;    -1,  -23.06,  1, &#xD;&#xA;     0,  -43.43, -1, &#xD;&#xA;     0,  -54.85,  0, &#xD;&#xA;     0,  -66.27,  1, &#xD;&#xA;     1,  -61.89, -1, &#xD;&#xA;     1,  -27.43,  0, &#xD;&#xA;     1,  -59.89,  1]&#xD;&#xA;&#xD;&#xA;**Note:** &#xD;&#xA;&#xD;&#xA;&gt; The vertices might not exactly correspond to what you would have&#xD;&#xA;&gt; expected from above loop. That is because I am centering the `mesh`&#xD;&#xA;&gt; around origin after the loop.&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So my guess is that the problem is that I am pushing my triangles counterclockwise, that is why I tried to enable culling and depth testing but that did not help either:&#xD;&#xA;&#xD;&#xA;    gl.enable(gl.DEPTH_TEST);&#xD;&#xA;    gl.enable(gl.CULL_FACE);&#xD;&#xA;    gl.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Any guess what might be the reason for wrong `TRIANGLE_STRIP` rendering?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JVCye.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PbGXw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/IhodK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21062" PostHistoryTypeId="1" PostId="7984" RevisionGUID="ba9dc09d-398b-42a9-b298-49c179e27b99" CreationDate="2018-08-28T19:51:48.443" UserId="2485" Text="Problems rendering a plane via `drawElements`" ContentLicense="CC BY-SA 4.0" />
  <row Id="21063" PostHistoryTypeId="3" PostId="7984" RevisionGUID="ba9dc09d-398b-42a9-b298-49c179e27b99" CreationDate="2018-08-28T19:51:48.443" UserId="2485" Text="|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21064" PostHistoryTypeId="2" PostId="7985" RevisionGUID="a2756796-5ac7-4fbb-8713-4b27aae99633" CreationDate="2018-08-29T07:02:30.167" UserId="9274" Text="So, the german wikipedia states about ambient occlusion:&lt;br&gt;&lt;blockquote&gt;The ambient occlusion method is based on the assumption that an object, a set of objects or an entire scene is surrounded by a unit sphere of light.&lt;/blockquote&gt;&#xD;&#xA;&#xD;&#xA;Now, let's suppose we've got a scene in which the only object is a pipe, closed at one end, at the center of the scene. If I got this right, then to get the ambient occlusion this object would now be evenly light from every direction.&#xD;&#xA;&#xD;&#xA;But wouldn't lighting the object evenly from everywhere mean that for every point in the pipe there would also be a ray of light that would directly reach it, leading to no ambient occlusion at all (no shadows inside the pipe)?&#xD;&#xA;&#xD;&#xA;What did I get wrong here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21065" PostHistoryTypeId="1" PostId="7985" RevisionGUID="a2756796-5ac7-4fbb-8713-4b27aae99633" CreationDate="2018-08-29T07:02:30.167" UserId="9274" Text="Ambient occlusion of a sole object in a scene" ContentLicense="CC BY-SA 4.0" />
  <row Id="21066" PostHistoryTypeId="3" PostId="7985" RevisionGUID="a2756796-5ac7-4fbb-8713-4b27aae99633" CreationDate="2018-08-29T07:02:30.167" UserId="9274" Text="|ambient-occlusion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21067" PostHistoryTypeId="2" PostId="7986" RevisionGUID="c0dfa654-8f50-42fa-8ce1-067e9be92c26" CreationDate="2018-08-29T08:02:06.750" UserId="9194" Text="Ambient occlusion is basically shooting out a large number of rays diffusely from a surface point. In a pipe some of the rays will intersect with the pipe itself, which means that this surface point will not receive as much ambience as points that don't have intersecting rays. The inside of the pipe vs the outside of the pipe will be different." ContentLicense="CC BY-SA 4.0" />
  <row Id="21068" PostHistoryTypeId="2" PostId="7987" RevisionGUID="a49db898-4c6d-45c0-bb73-abcb15306e16" CreationDate="2018-08-29T08:05:56.890" UserId="2041" Text="When you compute ambient occlusion (AO) for a point on an object's surface, you sample multiple directions and measure what fraction of them escape. That is, you're trying to approximate what fraction of the unit hemisphere is visible to that point on the surface. (Note that it's a unit *hemisphere* because half of the unit sphere is on the wrong side of the surface to start with.)&#xD;&#xA;&#xD;&#xA;So in your pipe example, the outside of the pipe is not at all occluded. From every point on the outside, any ray fired in that hemisphere will escape without intersecting the object. All of the outside would be lit with 100% of the ambient light.&#xD;&#xA;&#xD;&#xA;The inside is another matter. The inside of the end cap can only see a small circle of that hemisphere, through the other end of the pipe. The exact fraction depends on the radius and length of the pipe, but call it 10% for the example. 90% of rays fired from a point on the end cap will hit the inside of the cap, and the other 10% will escape along the length of the pipe and out of the other end. These points are 90% occluded, so they'll be lit with 10% of the ambient light.&#xD;&#xA;&#xD;&#xA;Consider a point at the open end of the pipe, but on the inside. This point is 50% occluded. Half of the rays fired from it go into the pipe and intersect with it at some point. The other half go straight out and escape to the unit hemisphere. This point will be lit with 50% of the ambient light, and it's easy to see that the 50% will smoothly decrease to the 10% (or however much is the minimum) as you travel down the inside of the pipe towards the end cap, as less of that hole is visible.&#xD;&#xA;&#xD;&#xA;The important point I think you misunderstood is that you measure or estimate what *fraction* of the unit hemisphere is visible from the point you're shading, not whether it's visible at all. Casting many rays and counting what fraction escape is one way of estimating this." ContentLicense="CC BY-SA 4.0" />
  <row Id="21069" PostHistoryTypeId="2" PostId="7988" RevisionGUID="f0720eb3-1786-43b1-b545-b787895ee3be" CreationDate="2018-08-29T12:38:08.673" UserId="2287" Text="A surface with a Lambertian BRDF has the characteristic that independent of the direction from which one looks at that surface, one receives the same amount of reflected energy. Lets consider a small plane orthogonal to this looking direction: &#xD;&#xA;&#xD;&#xA; - If one looks straight at the surface (i.e. the looking direction is parallel to the surface normal), the projected surface area of that plane onto the surface along the looking direction is **equal** to the surface area of the plane (i.e. orthogonal projection).&#xD;&#xA; - If one looks along a sharp angle at the surface, the projected surface area of that plane onto the surface along the looking direction is **much larger** than the surface area of the plane.&#xD;&#xA;&#xD;&#xA;Assume an isotropic BRDF (i.e. the same reflection factor independent of the looking direction), the following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega 1 \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = 2\pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) \equiv \frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Unfortunately, the differences in projected surface area dependent of the looking direction remain and thus this isotropic BRDF violates the above definition of a Lambertian BRDF.&#xD;&#xA;&#xD;&#xA;To counteract the differences in projected surface area dependent of the looking direction, the reflection factor must compensate and be dependent of the looking direction as well. This compensating factor is $\cos\theta$ (i.e. decreases from orthogonal, $\theta=0$, to glancing, $\theta=\pi/2$ directions). The following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega \cos\theta \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \cos\theta \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \cos\theta \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = \pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) = \mathrm{pdf}\!\left(\theta\right) = \frac{\cos\theta}{\pi}$&#xD;&#xA;&#xD;&#xA;**Alternatively**, one can start reasoning from the amount of incident energy as well: see [this article](https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading), thanks to @Tare.&#xD;&#xA;&#xD;&#xA;**Note** that diffuse is not the same as isotropic:&#xD;&#xA;&#xD;&#xA; - The reflection from a surface with a Lambertian BRDF is diffuse and non-isotropic. &#xD;&#xA; - The brightness perceival from a surface with a Lambertian BRDF is non-diffuse and isotropic.&#xD;&#xA;&#xD;&#xA;(Similar for diffuse area light sources.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21070" PostHistoryTypeId="5" PostId="7988" RevisionGUID="973a72f2-846d-4ae5-90ac-456583637d9e" CreationDate="2018-08-29T12:45:13.957" UserId="2287" Comment="added 51 characters in body" Text="A surface with a Lambertian BRDF has the characteristic that independent of the direction from which one looks at that surface, one receives the same amount of reflected energy. Lets consider a small plane orthogonal to this looking direction: &#xD;&#xA;&#xD;&#xA; - If one looks straight at the surface (i.e. the looking direction is parallel to the surface normal), the projected surface area of that plane onto the surface along the looking direction is **equal** to the surface area of the plane (i.e. orthogonal projection).&#xD;&#xA; - If one looks along a sharp angle at the surface, the projected surface area of that plane onto the surface along the looking direction is **much larger** than the surface area of the plane.&#xD;&#xA;&#xD;&#xA;Assume an isotropic BRDF (i.e. the same reflection factor independent of the looking direction), the following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega 1 \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = 2\pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) \equiv \frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Unfortunately, the differences in projected surface area dependent of the looking direction remain and thus this isotropic BRDF violates the above definition of a Lambertian BRDF.&#xD;&#xA;&#xD;&#xA;To counteract the differences in projected surface area dependent of the looking direction, the reflection factor must compensate and be dependent of the looking direction as well. This compensating factor is $\cos\theta$ (i.e. decreases from orthogonal, $\theta=0$, to glancing, $\theta=\pi/2$ directions). The following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega \cos\theta \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \cos\theta \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \cos\theta \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = \pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) = \mathrm{pdf}\!\left(\theta\right) = \frac{\cos\theta}{\pi}$&#xD;&#xA;&#xD;&#xA;**Alternatively**, one can start reasoning from the amount of incident energy as well: see [this article](https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading), thanks to @Tare.&#xD;&#xA;&#xD;&#xA;**Note** that diffuse is not the same as isotropic:&#xD;&#xA;&#xD;&#xA; - The reflection from a surface with a Lambertian BRDF is diffuse and non-isotropic. &#xD;&#xA; - The brightness perceival from a surface with a Lambertian BRDF is non-diffuse and isotropic (i.e. looks the same from all possible directions).&#xD;&#xA;&#xD;&#xA;(Similar for diffuse area light sources.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21071" PostHistoryTypeId="5" PostId="7988" RevisionGUID="8ca9bb5e-6478-4083-a110-d35b1d4cc737" CreationDate="2018-08-29T12:56:14.663" UserId="2287" Comment="added 75 characters in body" Text="A surface with a Lambertian BRDF has the characteristic that independent of the direction from which one looks at that surface, one receives the same amount of reflected energy (i.e. a diffuse surface point looks the same from all possible directions). Lets consider a small plane orthogonal to this looking direction: &#xD;&#xA;&#xD;&#xA; - If one looks straight at the surface (i.e. the looking direction is parallel to the surface normal), the projected surface area of that plane onto the surface along the looking direction is **equal** to the surface area of the plane (i.e. orthogonal projection).&#xD;&#xA; - If one looks along a sharp angle at the surface, the projected surface area of that plane onto the surface along the looking direction is **much larger** than the surface area of the plane.&#xD;&#xA;&#xD;&#xA;Assume an isotropic BRDF (i.e. the same reflection factor independent of the looking direction), the following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega 1 \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = 2\pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) \equiv \frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Unfortunately, the differences in projected surface area dependent of the looking direction remain and thus this isotropic BRDF violates the above definition of a Lambertian BRDF.&#xD;&#xA;&#xD;&#xA;To counteract the differences in projected surface area dependent of the looking direction, the reflection factor must compensate and be dependent of the looking direction as well. This compensating factor is $\cos\theta$ (i.e. decreases from orthogonal, $\theta=0$, to glancing, $\theta=\pi/2$ directions). The following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega \cos\theta \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \cos\theta \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \cos\theta \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = \pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) = \mathrm{pdf}\!\left(\theta\right) = \frac{\cos\theta}{\pi}$&#xD;&#xA;&#xD;&#xA;**Alternatively**, one can start reasoning from the amount of incident energy as well: see [this article](https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading), thanks to @Tare.&#xD;&#xA;&#xD;&#xA;**Note** that diffuse is not the same as isotropic:&#xD;&#xA;&#xD;&#xA; - The reflection from a surface with a Lambertian BRDF is diffuse and non-isotropic. &#xD;&#xA; - The brightness perceival from a surface with a Lambertian BRDF is non-diffuse and isotropic (i.e. looks the same from all possible directions).&#xD;&#xA;&#xD;&#xA;(Similar for diffuse area light sources.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21072" PostHistoryTypeId="5" PostId="7988" RevisionGUID="3b354a43-8fe4-44f7-abfe-3d2dbf0e3131" CreationDate="2018-08-29T13:02:16.037" UserId="2287" Comment="added 75 characters in body" Text="A surface with a Lambertian BRDF has the characteristic that independent of the direction from which one looks at that surface, one receives the same amount of reflected energy (i.e. a diffuse surface point looks the same from all possible directions). Lets consider a small plane orthogonal to this looking direction: &#xD;&#xA;&#xD;&#xA; - If one looks straight at the surface (i.e. the looking direction is parallel to the surface normal), the projected surface area of that plane onto the surface along the looking direction is **equal** to the surface area of the plane (i.e. orthogonal projection).&#xD;&#xA; - If one looks along a sharp angle at the surface, the projected surface area of that plane onto the surface along the looking direction is **much larger** than the surface area of the plane.&#xD;&#xA;&#xD;&#xA;Assume an isotropic BRDF (i.e. the same reflection factor independent of the looking direction), the following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega 1 \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = 2\pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) \equiv \frac{1}{2\pi}$.&#xD;&#xA;&#xD;&#xA;Unfortunately, the differences in projected surface area dependent of the looking direction remain and thus this isotropic BRDF violates the above definition of a Lambertian BRDF.&#xD;&#xA;&#xD;&#xA;To counteract the differences in projected surface area dependent of the looking direction, the reflection factor must compensate and be dependent of the looking direction as well. This compensating factor is $\cos\theta$ (i.e. decreases from orthogonal, $\theta=0$, to glancing, $\theta=\pi/2$ directions). The following normalization factor and probability density distribution over the hemisphere are obtained:&#xD;&#xA;&#xD;&#xA;$\int_\Omega \cos\theta \, d\omega = \int_{0}^{2\pi} \int_{0}^{\pi/2} \cos\theta \sin\theta \, \mathrm{d}\theta \, \mathrm{d}\phi = \int_{0}^{2\pi} \int_{0}^{1} \cos\theta \, \mathrm{d}\!\left(\cos\theta\right) \, \mathrm{d}\phi = \pi$&#xD;&#xA;&#xD;&#xA;$\mathrm{pdf}\!\left(\theta, \phi\right) = \mathrm{pdf}\!\left(\theta\right) = \frac{\cos\theta}{\pi}$&#xD;&#xA;&#xD;&#xA;**Alternatively**, one can start reasoning from the amount of incident energy as well (dual). **Lambert's cosine law** + **conservation of energy**:&#xD;&#xA;&#xD;&#xA;$\rho_d \int_\Omega \cos\theta \, d\omega = \rho_d \pi \le 1$&#xD;&#xA;&#xD;&#xA;(For more info see [this article](https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading), thanks to @Tare.)&#xD;&#xA;&#xD;&#xA;**Note** that diffuse is not the same as isotropic:&#xD;&#xA;&#xD;&#xA; - The reflection from a surface with a Lambertian BRDF is diffuse and non-isotropic. &#xD;&#xA; - The brightness perceival from a surface with a Lambertian BRDF is non-diffuse and isotropic (i.e. looks the same from all possible directions).&#xD;&#xA;&#xD;&#xA;(Similar for diffuse area light sources.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21073" PostHistoryTypeId="2" PostId="7989" RevisionGUID="558cc35e-5410-40c1-8885-8c3fefb9b217" CreationDate="2018-08-29T13:04:20.890" UserId="7299" Text="I want to put a segment of an image to another image. But to make it realistic I applied poisson blending. But the output is not good at all. &#xD;&#xA;&#xD;&#xA;Output without poisson blending. The kid was cropped from another image.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;With poisson blending&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have no clue what else to try. I though of calculating average value of the image segment where the kid is placed and then scaling the kids color to that average. But it should not work properly if that image segment is very white or black etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0WYFo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/gIWRY.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21074" PostHistoryTypeId="1" PostId="7989" RevisionGUID="558cc35e-5410-40c1-8885-8c3fefb9b217" CreationDate="2018-08-29T13:04:20.890" UserId="7299" Text="How to blend a segment of an image with another image" ContentLicense="CC BY-SA 4.0" />
  <row Id="21075" PostHistoryTypeId="3" PostId="7989" RevisionGUID="558cc35e-5410-40c1-8885-8c3fefb9b217" CreationDate="2018-08-29T13:04:20.890" UserId="7299" Text="|image-processing|color|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21081" PostHistoryTypeId="5" PostId="7980" RevisionGUID="b60df651-2dd6-4aeb-b4cd-25abfbc3b9ae" CreationDate="2018-08-29T15:40:16.370" UserId="9266" Comment="spelling" Text="This picture depicts my current immagination of the coordinate systems involved in ray tracing:&#xD;&#xA;&#xD;&#xA;![my current imagination of the coordinate systems involved](https://i.stack.imgur.com/eyUEh.png)&#xD;&#xA;&#xD;&#xA;**Explanation:**&#xD;&#xA;So the green rectangle is the [-0.5, nx-0.5] x [-0.5, ny-0.5] coordinate system and you can translate that coordinate system to the {u, v, w} coordinate system's coordinates (the world coordinate system) w/ the equations near the green rectangle.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;From the origin of the world coordinate system, you can cast rays into the [l, r] x [b, t] coordinate system w/ the equation near the red rectangle ($s = e + u_{s} * u + v_{s} * v + w_{s} * w$).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The [-0.5, nx-0.5] x [-0.5, ny-0.5] matches a classic windowing systems coordinate sytem while the [l, r] x [b, t] seems to be the &quot;ray tracer's screen&quot;/&quot;ray tracer's view area&quot;.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;Both apparently define the view frustum depicted above. This however is counterintuitive for me since I expect the screen directly in front of the world coordinate system. So the screen I am seeing is the green rectangle, the [-0.5, nx-0.5] x [-0.5, ny-0.5]. That means everything goes backwards.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;**The ray tracer algorithm in my own words (and with my current understanding):**&#xD;&#xA;&#xD;&#xA;&quot;Cause&quot; the world space to shoot a ray so that it goes through each pixel of the window screen [-0.5, nx-0.5] x [-0.5, ny-0.5] and check for an intersection within the frustum along the way. If there is an intersection color it, if not leave it at the background color.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;IOW: I am a &quot;commander&quot; and as I go through each pixel of [-0.5, nx-0.5] x [-0.5, ny-0.5] I cause the world space to shoot/cast a ray so that it goes through the pixel that I am currently at as well while checking for intersections within the frustum.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;With my current understanding I tried to implement a ray tracer on the basis of a set_pixel() function.&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;**My implementation attempt (w/ a skewed green sphere as a result):**&#xD;&#xA;&#xD;&#xA;    void game::Engine::run()&#xD;&#xA;{	&#xD;&#xA;&#xD;&#xA;	int nx = window_width; // 1366&#xD;&#xA;	int ny = window_heigth; // 768&#xD;&#xA;	// Construct the &quot;ray tracer window&quot;/&quot;ray tracer screen&quot;&#xD;&#xA;	int left = -200;&#xD;&#xA;	int right = 200;&#xD;&#xA;	int top = 100;&#xD;&#xA;	int bottom = -100;&#xD;&#xA;	int distance = 10;&#xD;&#xA;	// Create the {u, v, w} coordinate system&#xD;&#xA;	Vec3f e{ 0, 0, float(distance) };&#xD;&#xA;	Vec3f u{ 1, 0, 0 };&#xD;&#xA;	Vec3f v{ 0, 1, 0 };&#xD;&#xA;	Vec3f w{ 0, 0, float(distance) };&#xD;&#xA;	// Create the sphere&#xD;&#xA;	Vec3f center{ -50, -20, 11 };&#xD;&#xA;	float radius = 3.0f;&#xD;&#xA;&#xD;&#xA;	// Game loop&#xD;&#xA;	bool running{ true };&#xD;&#xA;	SDL_Event event{};&#xD;&#xA;	while (running)&#xD;&#xA;	{&#xD;&#xA;		// Clear buffer&#xD;&#xA;		SDL_SetRenderDrawColor(renderer, 153, 153, 153, 255);&#xD;&#xA;		SDL_RenderClear(renderer);&#xD;&#xA;&#xD;&#xA;		// Draw&#xD;&#xA;		for (int i = 0; i &lt;= window_width; ++i) {&#xD;&#xA;			for (int j = 0; j &lt; window_heigth; ++j) {&#xD;&#xA;				// Calculate the scalar factors from the pixel position for each axis of the {u, v, w} coordinate system&#xD;&#xA;				float u_s = (left + (right - left) * (i + 0.5)) / nx;&#xD;&#xA;				float v_s = (bottom + (top - bottom) * (j + 0.5)) / ny;&#xD;&#xA;				float w_s = -distance;&#xD;&#xA;				// Cast a ray (in a perspective manner)&#xD;&#xA;				Ray3f s{ e, u * u_s + v * v_s + w * w_s};&#xD;&#xA;				Vec3f co = center - s.origin_vector;&#xD;&#xA;				// Calculate the intersection between the sphere and the ray&#xD;&#xA;				float a = Vec3f::dot_product(s.direction_vector, s.direction_vector);&#xD;&#xA;				float b = 2 * Vec3f::dot_product(co, s.direction_vector);&#xD;&#xA;				float c = Vec3f::dot_product(co, co) - radius * radius;&#xD;&#xA;				float discriminant = b * b - 4 * a * c;&#xD;&#xA;				Vec3f color_vec{ 0, 0, 0 }; // default background color&#xD;&#xA;				if (discriminant &gt; 0)&#xD;&#xA;				{&#xD;&#xA;					// Make the hit sphere green&#xD;&#xA;					color_vec.x = 0;&#xD;&#xA;					color_vec.y = 1;&#xD;&#xA;					color_vec.z = 0;&#xD;&#xA;				}&#xD;&#xA;				set_pixel(renderer, i, j, 255 * color_vec.x, 255 * color_vec.y, 255 * color_vec.z, 255);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		// Swap buffers&#xD;&#xA;		SDL_RenderPresent(renderer);&#xD;&#xA;		// Process event queue&#xD;&#xA;		while (SDL_PollEvent(&amp;event))&#xD;&#xA;		{&#xD;&#xA;			switch (event.type)&#xD;&#xA;			{&#xD;&#xA;			case SDL_QUIT:&#xD;&#xA;				running = false;&#xD;&#xA;				break;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;**The result:**&#xD;&#xA;![result](https://i.stack.imgur.com/791eG.png)&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;**My conclusion:**&#xD;&#xA;I got the coordinate system totally wrong thus the skewed result.&#xD;&#xA;So the window 1366 x 768 and the ray tracer's screen 400 x 200 as well as the world coordinate system that is spanned with the standard basis in the code doesn't lead to the expected result the sphere beeing on the center of the screen and not looking skewed. Plus, the coordinate system acts weird and seems to be arbitrary.&#xD;&#xA;&lt;br&gt;&#xD;&#xA;Thus something is fundamentally wrong with my current understanding.&#xD;&#xA;&#xD;&#xA;**References:**&#xD;&#xA;&lt;br&gt;&#xD;&#xA;[Lecture on ray tracing][1]&#xD;&#xA;&lt;br&gt;&#xD;&#xA;[Peter Shirley's treatise on ray tracing][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=zQIvR_6IayM&amp;feature=youtu.be&amp;t=27m16s&#xD;&#xA;  [2]: https://www.cs.utah.edu/~shirley/books/fcg2/rt.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="21082" PostHistoryTypeId="2" PostId="7991" RevisionGUID="5ec04bba-7639-48c3-9b59-c23cd4d4197c" CreationDate="2018-08-29T16:08:32.230" UserId="8233" Text="If I calculate the average (mean) hue of a set of colours naively, I will get silly answers sometimes.&#xD;&#xA;&#xD;&#xA;For example, in HSB/HSL, the average of hue=10 (slightly orange red) and hue=350 (slightly blue red) would arithmetically be hue=(10+350)/2=180 (cyan).&#xD;&#xA;&#xD;&#xA;Considering the hue channel only, how should I calculate averages in order to get results which match intuition in these cases?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21083" PostHistoryTypeId="1" PostId="7991" RevisionGUID="5ec04bba-7639-48c3-9b59-c23cd4d4197c" CreationDate="2018-08-29T16:08:32.230" UserId="8233" Text="How do I calculate average hue, since the numbers loop around?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21084" PostHistoryTypeId="3" PostId="7991" RevisionGUID="5ec04bba-7639-48c3-9b59-c23cd4d4197c" CreationDate="2018-08-29T16:08:32.230" UserId="8233" Text="|color|color-science|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21085" PostHistoryTypeId="2" PostId="7992" RevisionGUID="a8ff73d0-4203-4700-8a37-2a64cb3510b7" CreationDate="2018-08-29T16:59:27.003" UserId="2654" Text="Your code is non-functional, but only because (in the core profile) you cannot bind a buffer to `GL_ELEMENT_ARRAY_BUFFER` unless a VAO is also bound. So the part that creates the buffer would need to use a different binding point, which is totally fine:&#xD;&#xA;&#xD;&#xA;    const GLuint indices[6] = {&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        0, 3, 2&#xD;&#xA;    };&#xD;&#xA;    glGenBuffers (1, &amp;EBO);&#xD;&#xA;    glBindBuffer (GL_ARRAY_BUFFER, EBO);&#xD;&#xA;    glBufferData (GL_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;Everything else is perfectly valid." ContentLicense="CC BY-SA 4.0" />
  <row Id="21087" PostHistoryTypeId="5" PostId="7982" RevisionGUID="e5f2b417-5b50-4e75-b65d-46eabb9da309" CreationDate="2018-08-29T17:50:40.427" UserId="6046" Comment="added 2304 characters in body" Text="I gave it a quick look and I found several places which need attention. First of all you forgot transforming the view space to NDC space.&#xD;&#xA;&#xD;&#xA;We are working with 3 spaces. &#xD;&#xA;&#xD;&#xA;**1)** The world space, which is the global reference frame. You usually define spheres in this frame. Or if you are reading model data, you might want to multiply by a model matrix to bring them into world space.&#xD;&#xA;&#xD;&#xA;**2)** The camera space. This is the part of the world the camera views. The correct equation for generating rays in the camera space as i mentioned in the comments are given by.&#xD;&#xA;&#xD;&#xA;$ x = l + (r-l)*(pixel_i * 0.5)/Width$&#xD;&#xA;&#xD;&#xA;$ y = b + (t-b)*(pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**3)** The third is the NDC space which is usually in the range $[-1,1]$ Some API's have this range in $[0,1]$ For ray tracing however, we are concerned with $[-1,1]$. The concept here is, imagine your whole image which is $Width \times Height$ to be mapped to a plane which is $2 \times 2$ units wide centered at the origin. This is somewhat a generalization. We don't need to mess with the width and height anymore. We introduced an intermediary space where everything is in the range [-1,1]. &#xD;&#xA;&#xD;&#xA;However this is true only for square images. What happens when `width != height`?&#xD;&#xA;&#xD;&#xA;Then we have to account for it by doing,&#xD;&#xA;&#xD;&#xA;$ x = [-a, a]$&#xD;&#xA;&#xD;&#xA;$ y = [-1, 1]$&#xD;&#xA;&#xD;&#xA;Where $a$ is Aspect Ratio given by. &#xD;&#xA;&#xD;&#xA;$ a = Width/Height $ &#xD;&#xA;&#xD;&#xA;The NDC space is usually calcualted as,&#xD;&#xA;&#xD;&#xA;$ x_{ndc} = [ (2 * ( i+ 0.5)/Width) - 1] * Aspect Ratio$&#xD;&#xA;&#xD;&#xA;$ y_{ndc} = [ (2 * ( y+ 0.5)/Width) - 1]$&#xD;&#xA;&#xD;&#xA;Note tho depending on the image coordinates, we might need to flip $y_{ndc}$. The calculation above assumes Image has the origin at the top left corner. If the origin is at the bottom left, we will need to flip.&#xD;&#xA;&#xD;&#xA;However this assumes the camera is positioned at the origin. How do take into account for camera rotation and position. Normally this is done by the use of a camera matrix which transforms from world space to camera or vice versa. You calculate ray direction in the NDC space, multiply it by this matrix and then normalize it. I will not go into details about this one. &#xD;&#xA;&#xD;&#xA;The way you are calculating the rays in camera space, haven't seen much like this but there is a simple fix to get a moving camera and transform it in NDC space. You divide by the width and height of the camera volume. So your equations become. &#xD;&#xA;&#xD;&#xA;$ x = [l + (r-l)*(pixel_i * 0.5)/Width] / (r-l)$&#xD;&#xA;&#xD;&#xA;$\therefore x = l/(r-l) + (pixel_i * 0.5)/Width $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$ y = [b + (t-b)*(pixel_y * 0.5)/Height] / (t-b)$&#xD;&#xA;&#xD;&#xA;$\therefore y = b/(t-b) + (pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;You don't need to account for aspect ratio in this scenario as it's already being done by $l/(r-l)$ and $b/(t-b)$ factors. &#xD;&#xA;&#xD;&#xA;As for the proper way of intersecting spheres (if you are normalizing direction, which you should, would be)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;     t = -1.0f;&#xD;&#xA;     co = ray.origin - sphere.center // Note we subtract center FROM origin.&#xD;&#xA;     b = dot(co, ray.dir);&#xD;&#xA;     c = dot(co, co) - sphere.radius * sphere.radius;&#xD;&#xA;     disc = b*b - c;&#xD;&#xA;     if disc &gt;= 0&#xD;&#xA;       t = -b + sqrt(disc); // wrong&#xD;&#xA;       t = -b - sqrt(disc); // correct&#xD;&#xA;     if ( t &gt;= 0)&#xD;&#xA;     {&#xD;&#xA;      ray.length = t;       /* you can add a length parameter in ray as &#xD;&#xA;                               direction is normalized&#xD;&#xA;                               Set other parameters such as sphere id, or if &#xD;&#xA;                               there is only 1 sphere, set color here. */&#xD;&#xA;      return true;&#xD;&#xA;     }&#xD;&#xA;     else&#xD;&#xA;      return false;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also forgot to mention your spheres $Z$ coordinates should be negative. Since rays are generating in the $-Z$ direction.&#xD;&#xA;&#xD;&#xA;EDIT:- I corrected my sphere intersection. There was a mistake. To answer the questions in your comments.&#xD;&#xA;&#xD;&#xA;1) About the spaces, scratchapixel seems to follow RenderMan's coordinate system. Since I'm more from an OpenGL background, I'll talk with that in mind.&#xD;&#xA;When I talk about NDC space that equals scratchapixels's definition of screen space. &#xD;&#xA;&#xD;&#xA;Screen space usually means screen/window coordinates which range from 0 to image width/height and that's why scratchapixel can be confusing sometimes.&#xD;&#xA;&#xD;&#xA;2 and 3) About the sphere intersection and why rays need a length parameter. First of all rays are defined by this formula.&#xD;&#xA;&#xD;&#xA;$ R = e + t*\hat{d}$&#xD;&#xA;&#xD;&#xA;Where $e$ is the origin, $\hat{d}$ is the direction vector of that ray and $t$ is the length of that ray. In raytracing we initialize all our rays to have the length infinity. Then whenever we intersect anything, we set this $t$ parameter if it's less than the previous value. For the first time, the $t$ value is set to the distance to the first object hit. After that whenever we find that the same ray hits another object we compare the $t$ values to see which one is closer.&#xD;&#xA;&#xD;&#xA;We can't directly set color by checking discriminant only because when a Ray interseccts a sphere it can be the case that it intersects at two points (when ray isn't tangent to the sphere). Both of these are given by,&#xD;&#xA;&#xD;&#xA;$ t = -b + sqrt(disc)$&#xD;&#xA;&#xD;&#xA;$ t = -b - sqrt(disc)$&#xD;&#xA;&#xD;&#xA;However in the case for spheres, the closest point is always given by the second one. I mistakenly provided you the first one. &#xD;&#xA;&#xD;&#xA;However this doesn't mean we dont have a view frustum. If we wan't we can define near and far planes to get a closed view frustum and initialize all rays with the `length = distance to far plane`. Then any objects farther than this far plane will not get intersected. In other words, `discriminant` will be greater than zero but the `t` check would fail.&#xD;&#xA;&#xD;&#xA;Also I don't see where you have declared `window_width` in your code but make sure when dividing by `width` or `height` the division should have a float value in it (cast width/height into float if declared as int) other wise aspect ratio would be rounded off to an integer.&#xD;&#xA;&#xD;&#xA;And try placing your sphere further in the -Z direction. Let's say `(0,0, -6)`.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21088" PostHistoryTypeId="5" PostId="7982" RevisionGUID="0d4bb8fa-ad3a-4804-8a78-460e9faa154c" CreationDate="2018-08-29T19:22:14.090" UserId="6046" Comment="deleted 1 character in body" Text="I gave it a quick look and I found several places which need attention. First of all you forgot transforming the view space to NDC space.&#xD;&#xA;&#xD;&#xA;We are working with 3 spaces. &#xD;&#xA;&#xD;&#xA;**1)** The world space, which is the global reference frame. You usually define spheres in this frame. Or if you are reading model data, you might want to multiply by a model matrix to bring them into world space.&#xD;&#xA;&#xD;&#xA;**2)** The camera space. This is the part of the world the camera views. The correct equation for generating rays in the camera space as i mentioned in the comments are given by.&#xD;&#xA;&#xD;&#xA;$ x = l + (r-l)*(pixel_i * 0.5)/Width$&#xD;&#xA;&#xD;&#xA;$ y = b + (t-b)*(pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**3)** The third is the NDC space which is usually in the range $[-1,1]$ Some API's have this range in $[0,1]$ For ray tracing however, we are concerned with $[-1,1]$. The concept here is, imagine your whole image which is $Width \times Height$ to be mapped to a plane which is $2 \times 2$ units wide centered at the origin. This is somewhat a generalization. We don't need to mess with the width and height anymore. We introduced an intermediary space where everything is in the range [-1,1]. &#xD;&#xA;&#xD;&#xA;However this is true only for square images. What happens when `width != height`?&#xD;&#xA;&#xD;&#xA;Then we have to account for it by doing,&#xD;&#xA;&#xD;&#xA;$ x = [-a, a]$&#xD;&#xA;&#xD;&#xA;$ y = [-1, 1]$&#xD;&#xA;&#xD;&#xA;Where $a$ is Aspect Ratio given by. &#xD;&#xA;&#xD;&#xA;$ a = Width/Height $ &#xD;&#xA;&#xD;&#xA;The NDC space is usually calcualted as,&#xD;&#xA;&#xD;&#xA;$ x_{ndc} = [ (2 * ( i+ 0.5)/Width) - 1] * Aspect Ratio$&#xD;&#xA;&#xD;&#xA;$ y_{ndc} = [ (2 * ( y+ 0.5)/Width) - 1]$&#xD;&#xA;&#xD;&#xA;Note tho depending on the image coordinates, we might need to flip $y_{ndc}$. The calculation above assumes Image has the origin at the top left corner. If the origin is at the bottom left, we will need to flip.&#xD;&#xA;&#xD;&#xA;However this assumes the camera is positioned at the origin. How do take into account for camera rotation and position. Normally this is done by the use of a camera matrix which transforms from world space to camera or vice versa. You calculate ray direction in the NDC space, multiply it by this matrix and then normalize it. I will not go into details about this one. &#xD;&#xA;&#xD;&#xA;The way you are calculating the rays in camera space, haven't seen much like this but there is a simple fix to get a moving camera and transform it in NDC space. You divide by the width and height of the camera volume. So your equations become. &#xD;&#xA;&#xD;&#xA;$ x = [l + (r-l)*(pixel_i * 0.5)/Width] / (r-l)$&#xD;&#xA;&#xD;&#xA;$\therefore x = l/(r-l) + (pixel_i * 0.5)/Width $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$ y = [b + (t-b)*(pixel_y * 0.5)/Height] / (t-b)$&#xD;&#xA;&#xD;&#xA;$\therefore y = b/(t-b) + (pixel_y * 0.5)/Height$&#xD;&#xA;&#xD;&#xA;$ z = -View Plane Distance$&#xD;&#xA;&#xD;&#xA;You don't need to account for aspect ratio in this scenario as it's already being done by $l/(r-l)$ and $b/(t-b)$ factors. &#xD;&#xA;&#xD;&#xA;As for the proper way of intersecting spheres (if you are normalizing direction, which you should, would be)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;     t = -1.0f;&#xD;&#xA;     co = ray.origin - sphere.center // Note we subtract center FROM origin.&#xD;&#xA;     b = dot(co, ray.dir);&#xD;&#xA;     c = dot(co, co) - sphere.radius * sphere.radius;&#xD;&#xA;     disc = b*b - c;&#xD;&#xA;     if disc &gt;= 0&#xD;&#xA;       t = -b + sqrt(disc); // wrong&#xD;&#xA;       t = -b - sqrt(disc); // correct&#xD;&#xA;     if ( t &gt;= 0)&#xD;&#xA;     {&#xD;&#xA;      ray.length = t;       /* you can add a length parameter in ray as &#xD;&#xA;                               direction is normalized&#xD;&#xA;                               Set other parameters such as sphere id, or if &#xD;&#xA;                               there is only 1 sphere, set color here. */&#xD;&#xA;      return true;&#xD;&#xA;     }&#xD;&#xA;     else&#xD;&#xA;      return false;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also forgot to mention your spheres $Z$ coordinates should be negative. Since rays are generating in the $-Z$ direction.&#xD;&#xA;&#xD;&#xA;EDIT:- I corrected my sphere intersection. There was a mistake. To answer the questions in your comments.&#xD;&#xA;&#xD;&#xA;1) About the spaces, scratchapixel seems to follow RenderMan's coordinate system. Since I'm more from an OpenGL background, I'll talk with that in mind.&#xD;&#xA;When I talk about NDC space that equals scratchapixels's definition of screen space. &#xD;&#xA;&#xD;&#xA;Screen space usually means screen/window coordinates which range from 0 to image width/height and that's why scratchapixel can be confusing sometimes.&#xD;&#xA;&#xD;&#xA;2 and 3) About the sphere intersection and why rays need a length parameter. First of all rays are defined by this formula.&#xD;&#xA;&#xD;&#xA;$ R = e + t*\hat{d}$&#xD;&#xA;&#xD;&#xA;Where $e$ is the origin, $\hat{d}$ is the direction vector of that ray and $t$ is the length of that ray. In raytracing we initialize all our rays to have the length infinity. Then whenever we intersect anything, we set this $t$ parameter if it's less than the previous value. For the first time, the $t$ value is set to the distance to the first object hit. After that whenever we find that the same ray hits another object we compare the $t$ values to see which one is closer.&#xD;&#xA;&#xD;&#xA;We can't directly set color by checking discriminant only because when a Ray interseccts a sphere it can be the case that it intersects at two points (when ray isn't tangent to the sphere). Both of these are given by,&#xD;&#xA;&#xD;&#xA;$ t = -b + sqrt(disc)$&#xD;&#xA;&#xD;&#xA;$ t = -b - sqrt(disc)$&#xD;&#xA;&#xD;&#xA;However in the case for spheres, the closest point is always given by the second one. I mistakenly provided you the first one. &#xD;&#xA;&#xD;&#xA;However this doesn't mean we dont have a view frustum. If we want we can define near and far planes to get a closed view frustum and initialize all rays with the `length = distance to far plane`. Then any objects farther than this far plane will not get intersected. In other words, `discriminant` will be greater than zero but the `t` check would fail.&#xD;&#xA;&#xD;&#xA;Also I don't see where you have declared `window_width` in your code but make sure when dividing by `width` or `height` the division should have a float value in it (cast width/height into float if declared as int) other wise aspect ratio would be rounded off to an integer.&#xD;&#xA;&#xD;&#xA;And try placing your sphere further in the -Z direction. Let's say `(0,0, -6)`.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21092" PostHistoryTypeId="2" PostId="7994" RevisionGUID="e4f7acb8-bb9a-4ce7-954e-166e219b9478" CreationDate="2018-08-30T05:26:25.997" UserId="2308" Text="So I have a bit of a predicament I am trying to solve. I have 10,000 triangle strips I am trying to draw. Each one has a z-order for the entire strip and within each strip the most recent triangles need to have a higher z order than the older one. So essentially the z order of a triangle is `(stripIndex / 10000) + (age / MAX_AGE)` where MAX_AGE is somewhere around 100 frames. I am not sure about this number yet.&#xD;&#xA;&#xD;&#xA;At start time all of the data to store this is initialized and a ring buffer of some form is used so that the most recent triangle's are in a new position each frame.&#xD;&#xA;&#xD;&#xA;This ring buffer is useful because only 2 triangles will have to be written for each frame per triangle strip so no data has to shift or move. You just over-write the oldest data.&#xD;&#xA;&#xD;&#xA;The trick is I want to do alpha blending between these triangle strips so I need to have the geometry drawn in order from front to back. I am experimenting with different layouts that will allow me to minimize draw calls and CPU stress required. This is an unsolved problem for me but I think I am going to have to do 10001 draw calls. But that is not what this question is about.&#xD;&#xA;&#xD;&#xA;So while trying to do this I ran into an odd GPU phenomenon I cant explain. Right now I am rendering with a simple no-depth additive blending Metal pipeline that looks like this.&#xD;&#xA;&#xD;&#xA;    id&lt;MTLFunction&gt; vertex_f = [MetalCore compileShader:vertex];&#xD;&#xA;    id&lt;MTLFunction&gt; fragment_f = [MetalCore compileShader:fragment];&#xD;&#xA;&#xD;&#xA;    MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];&#xD;&#xA;    descriptor.sampleCount = 1;&#xD;&#xA;    descriptor.fragmentFunction = fragment_f;&#xD;&#xA;    descriptor.vertexFunction = vertex_f;&#xD;&#xA;    descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;As I said at the beginning I create a buffer that holds all of the triangles necessary to draw each of the strips. The buffer is the same size every time and the triangle count is also constant. The buffers do have indices and that is also constant and created at the beginning. The underlying simulation that controls these triangle strips is also constant. However under two different memory layout conditions there are significantly different frame rates even under multiple trials. I cant figure out why. &#xD;&#xA;&#xD;&#xA;From now on I will refer to 10000 as MAX_STRIPS&#xD;&#xA;&#xD;&#xA;Memory configuration 1 has a triangle for the n'th strip in the i'th ring buffer position located in the triangle buffer at `i*MAX_STRIPS*4 + n*4` th position in the buffer. So in memory a single strips triangles are very spread out but a concentrated chunk of memory is updated each frame. &#xD;&#xA;&#xD;&#xA;Memory configuration 2 has a triangle for the n'th strip in the i'th ring buffer position located in the triangle buffer at the `n*MAX_AGE*4 + i*4` th position in the buffer. All of a single triangle strips vertices are close together in memory however writing is more spread out.&#xD;&#xA;&#xD;&#xA;For whatever reason configuration 2 takes significantly longer than configuration 1 to render.&#xD;&#xA;&#xD;&#xA;Now I could understand a small difference in CPU time but what I dont get is this difference in GPU time. Any clue as to why this might be happening.&#xD;&#xA;&#xD;&#xA;The following compares debugging information of these two methods. The left side is memory configuration 1. The right is memory configuration 2. Big difference are highlighted.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the vertex shader for all interested &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    struct VertexOutAlpha {&#xD;&#xA;        float4 position [[ position ]];&#xD;&#xA;        float4 color;&#xD;&#xA;    };&#xD;&#xA;    struct StripVertex {&#xD;&#xA;        float3 data; //z value is the z value for the entire strip. Triangles will have different z positions&#xD;&#xA;        float2 color;//x = color, y = time&#xD;&#xA;    };&#xD;&#xA;    vertex VertexOutAlpha strip_vertex(constant StripVertex * vertexBuffer [[ buffer(0) ]],&#xD;&#xA;                                  indexType vid [[ vertex_id ]],&#xD;&#xA;                                  constant matrix_float3x3* matrix [[buffer(1)]],&#xD;&#xA;                                  constant float* gameTime [[buffer(2)]]) {&#xD;&#xA;        StripVertex vert = vertexBuffer[vid];&#xD;&#xA;        VertexOutAlpha out;&#xD;&#xA;        float dimmer = 1.0 - clamp(((*gameTime - 0.016) - vert.color.y) * 10.0, 0.0, 1.0);&#xD;&#xA;        const float levelSize = 1.0 / (MAX_STRIPS + 0.01);&#xD;&#xA;        out.position = float4((*matrix * float3(vert.data.x, vert.data.y, 1.0)).xy, vert.data.z + (1 - dimmer) * levelSize, 1.0);&#xD;&#xA;        &#xD;&#xA;         out.color = float4(HSVtoRGB(vert.color.x, 1.0, dimmer), 1.0);&#xD;&#xA;        return out;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the generation of the vertex buffer for all interested&#xD;&#xA;&#xD;&#xA;        //triangleStripDataPtr is pre-allocated and alligned to the page size&#xD;&#xA;        triangleStripDataBuffer = [self.device newBufferWithBytesNoCopy:triangleStripDataPtr length:4 * MAX_STRIPS *  MAX_AGE options:MTLResourceStorageModeShared deallocator:nil];&#xD;&#xA;        assert(triangleStripDataBuffer != nil);&#xD;&#xA;&#xD;&#xA;Does anyone have a good explanation for why this is happening?&#xD;&#xA;  [1]: https://i.stack.imgur.com/OFdDU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21093" PostHistoryTypeId="1" PostId="7994" RevisionGUID="e4f7acb8-bb9a-4ce7-954e-166e219b9478" CreationDate="2018-08-30T05:26:25.997" UserId="2308" Text="Same draw call causing extremely different GPU usage under different triangle orders" ContentLicense="CC BY-SA 4.0" />
  <row Id="21094" PostHistoryTypeId="3" PostId="7994" RevisionGUID="e4f7acb8-bb9a-4ce7-954e-166e219b9478" CreationDate="2018-08-30T05:26:25.997" UserId="2308" Text="|gpu|vertex-buffer-object|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21096" PostHistoryTypeId="2" PostId="7995" RevisionGUID="6f286314-3c6d-4063-8b0f-789226b17a3a" CreationDate="2018-08-30T07:46:17.923" UserId="9258" Text="&gt; How do I calculate average hue, since the numbers loop around?&#xD;&#xA;&#xD;&#xA;&gt; I will get silly answers sometimes. For example, in HSB/HSL, the average of hue=10 (slightly orange red) and hue=350 (slightly blue red) would arithmetically be hue=(10+350)/2=180 (cyan).&#xD;&#xA;&#xD;&#xA;- [How to calculate mean and standard deviation for hue values from 0 to 360?&#xD;&#xA;](https://stackoverflow.com/questions/8169654/how-to-calculate-mean-and-standard-deviation-for-hue-values-from-0-to-360) **and** [Averaging circular values (particularly Hues in HSL color scheme)](https://stackoverflow.com/questions/13959276/averaging-circular-values-particularly-hues-in-hsl-color-scheme) which provides C++ source code.&#xD;&#xA;&#xD;&#xA;What if the values were 0° and 180°, then there are two answers: 90° and 270°; the same thing applies whenever the two inputs are opposite, there's two answers and no clear choice.&#xD;&#xA;&#xD;&#xA;- The program &quot;[Image Color Summarizer][1]&quot; (Linux version) has a file called &quot;peravg.pm&quot; which says: &quot;compute the average and median of a periodic data set, like a set of angles or hues&quot;. The [main page][2] offers a Windows version and a webpage image upload along with an API. &#xD;&#xA;&#xD;&#xA;The author explains:&#xD;&#xA;&#xD;&#xA;&gt; The colour summarizer will produce descriptive colour statistics for an image. Reported will be the average, median, minimum and maximum of each component of RGB, HSV, LCH and Lab. Average hues are calculated using [mean of circular quantities][3].&#xD;&#xA;&#xD;&#xA;&gt; Some of the questions the summarizer will answer are:&#xD;&#xA;&#xD;&#xA;&gt; - what is the average color hue, saturation and value in my image?&#xD;&#xA;&gt; - what are the colours that are most representative of the image?&#xD;&#xA;&gt; - what is the image's human readable colour description (e.g. dark pure blue)?&#xD;&#xA;&gt; - what do the RGB, HSV, LCH and Lab histograms look like?&#xD;&#xA;&gt; - what are the RGB, HSV, LCH and Lab pixel values? &#xD;&#xA;&#xD;&#xA;The paper: &quot;[Perceiving the average hue of color arrays][4]&quot; (May 1 2014), by Jacquelyn Webster, Paul Kay, and Michael A. Webster examines the subject from the viewpoint of an observer's perception of color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![HSL][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://mkweb.bcgsc.ca/color-summarizer/?download&#xD;&#xA;  [2]: http://mkweb.bcgsc.ca/color-summarizer/&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Mean_of_circular_quantities&#xD;&#xA;  [4]: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3979548/&#xD;&#xA;  [5]: https://i.stack.imgur.com/Dq2Ch.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21097" PostHistoryTypeId="2" PostId="7996" RevisionGUID="c64d960e-ed68-4b30-a699-b954b549eee2" CreationDate="2018-08-30T08:24:23.253" UserId="9280" Text="I created two ellipses,&lt;br/&gt;$\hspace{150px}$&lt;a href=&quot;https://i.stack.imgur.com/WfzOU.png&quot;&gt;&lt;img src=&quot;https://i.stack.imgur.com/WfzOU.png&quot; width=&quot;300&quot;/&gt;&lt;/a&gt;,&lt;br/&gt;where the red ellipsis is as the blue one, except translated to the right and rotated by ${30}^{\circ} .$ using rotation matrix, &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\phantom{F} {\llap{\textsf{rotation matrix}}} ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    cos(30^{\circ})  &amp;sin(30^{\circ})  \\[2px]&#xD;&#xA;    cos(30^{\circ}) &amp; \phantom{}sin(30)&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Next I tried to calculate deformation gradient by using principal axes, and then I decomposed $\vec{c}$ and $\vec{d}$ vectors,$$&#xD;&#xA;\begin{alignat}{7}&#xD;&#xA;\vec{c} &amp;~~=~~ 1.0021 \, \vec{b} &amp;~&amp;+ &amp;~&amp;0.8654 \, \vec{a} \\[5px]&#xD;&#xA;\vec{d} &amp;~~=~~ 0.8654 \, \vec{b} &amp;&amp;- &amp;&amp;0.2505 \, \vec{a}&#xD;&#xA;\end{alignat}&#xD;&#xA;$$and created the deformation gradient as$$&#xD;&#xA;F ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    \phantom{-} 0.8654  &amp;    1.0021  \\[2px]&#xD;&#xA;             -  0.2505  &amp;    0.8654&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\,.&#xD;&#xA;$$But it is obvious that, this is not the same as the ${30}^{\circ}$ rotation matrix that I had expected it to be,$$&#xD;&#xA;\phantom{F} {\llap{\textsf{rotation matrix}}} ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    0.8660  &amp;            -  0.5000  \\[2px]&#xD;&#xA;    0.5000  &amp;   \phantom{-} 0.8660&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\,.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Question:**  Why aren't the deformation gradient, $F ,$ and and the rotation matrix, $\textsf{rotation matrix} ,$ the same?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21098" PostHistoryTypeId="1" PostId="7996" RevisionGUID="c64d960e-ed68-4b30-a699-b954b549eee2" CreationDate="2018-08-30T08:24:23.253" UserId="9280" Text="What is wrong with my deformation gradient calculation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21099" PostHistoryTypeId="3" PostId="7996" RevisionGUID="c64d960e-ed68-4b30-a699-b954b549eee2" CreationDate="2018-08-30T08:24:23.253" UserId="9280" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21100" PostHistoryTypeId="5" PostId="7995" RevisionGUID="a036a1f6-ed2e-4451-bdfc-2d515d9587b1" CreationDate="2018-08-30T08:26:18.623" UserId="9258" Comment="Changed links to &quot;Share&quot; instead of direct." Text="&gt; How do I calculate average hue, since the numbers loop around?&#xD;&#xA;&#xD;&#xA;&gt; I will get silly answers sometimes. For example, in HSB/HSL, the average of hue=10 (slightly orange red) and hue=350 (slightly blue red) would arithmetically be hue=(10+350)/2=180 (cyan).&#xD;&#xA;&#xD;&#xA;- [How to calculate mean and standard deviation for hue values from 0 to 360?&#xD;&#xA;](https://stackoverflow.com/q/8169654/3648282) **and** [Averaging circular values (particularly Hues in HSL color scheme)](https://stackoverflow.com/q/13959276/3648282) which provides C++ source code.&#xD;&#xA;&#xD;&#xA;What if the values were 0° and 180°, then there are two answers: 90° and 270°; the same thing applies whenever the two inputs are opposite, there's two answers and no clear choice.&#xD;&#xA;&#xD;&#xA;- The program &quot;[Image Color Summarizer][1]&quot; (Linux version) has a file called &quot;peravg.pm&quot; which says: &quot;compute the average and median of a periodic data set, like a set of angles or hues&quot;. The [main page][2] offers a Windows version and a webpage image upload along with an API. &#xD;&#xA;&#xD;&#xA;The author explains:&#xD;&#xA;&#xD;&#xA;&gt; The colour summarizer will produce descriptive colour statistics for an image. Reported will be the average, median, minimum and maximum of each component of RGB, HSV, LCH and Lab. Average hues are calculated using [mean of circular quantities][3].&#xD;&#xA;&#xD;&#xA;&gt; Some of the questions the summarizer will answer are:&#xD;&#xA;&#xD;&#xA;&gt; - what is the average color hue, saturation and value in my image?&#xD;&#xA;&gt; - what are the colours that are most representative of the image?&#xD;&#xA;&gt; - what is the image's human readable colour description (e.g. dark pure blue)?&#xD;&#xA;&gt; - what do the RGB, HSV, LCH and Lab histograms look like?&#xD;&#xA;&gt; - what are the RGB, HSV, LCH and Lab pixel values? &#xD;&#xA;&#xD;&#xA;The paper: &quot;[Perceiving the average hue of color arrays][4]&quot; (May 1 2014), by Jacquelyn Webster, Paul Kay, and Michael A. Webster examines the subject from the viewpoint of an observer's perception of color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![HSL][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://mkweb.bcgsc.ca/color-summarizer/?download&#xD;&#xA;  [2]: http://mkweb.bcgsc.ca/color-summarizer/&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Mean_of_circular_quantities&#xD;&#xA;  [4]: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3979548/&#xD;&#xA;  [5]: https://i.stack.imgur.com/Dq2Ch.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21101" PostHistoryTypeId="5" PostId="7996" RevisionGUID="79044c82-4021-400c-8215-e06e7e68c630" CreationDate="2018-08-30T08:34:27.797" UserId="9280" Comment="added 191 characters in body" Text="I created two ellipses,&lt;br/&gt;$\hspace{150px}$&lt;a href=&quot;https://i.stack.imgur.com/WfzOU.png&quot;&gt;&lt;img src=&quot;https://i.stack.imgur.com/WfzOU.png&quot; width=&quot;300&quot;/&gt;&lt;/a&gt;,&lt;br/&gt;where the red ellipsis is as the blue one, except translated to the right and rotated by ${30}^{\circ} .$ Using rotation matrix, &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    x  \\[2px]&#xD;&#xA;    y   \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;\phantom{F} ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    cos(30^{\circ})  &amp; sin(30^{\circ})  \\[2px]&#xD;&#xA;    cos(30^{\circ}) &amp; \phantom{}sin(30^{\circ})&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;*&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    X  \\[2px]&#xD;&#xA;    Y   \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Next I tried to calculate deformation gradient by using principal axes(a and b for initial ellipsis,c and d for translated one), and then I decomposed $\vec{c}$ and $\vec{d}$ vectors,$$&#xD;&#xA;\begin{alignat}{7}&#xD;&#xA;\vec{c} &amp;~~=~~ 1.0021 \, \vec{b} &amp;~&amp;+ &amp;~&amp;0.8654 \, \vec{a} \\[5px]&#xD;&#xA;\vec{d} &amp;~~=~~ 0.8654 \, \vec{b} &amp;&amp;- &amp;&amp;0.2505 \, \vec{a}&#xD;&#xA;\end{alignat}&#xD;&#xA;$$and created the deformation gradient as$$&#xD;&#xA;F ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    \phantom{-} 0.8654  &amp;    1.0021  \\[2px]&#xD;&#xA;             -  0.2505  &amp;    0.8654&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\,.&#xD;&#xA;$$But it is obvious that, this is not the same as the ${30}^{\circ}$ rotation matrix that I had expected it to be,$$&#xD;&#xA;\phantom{F} {\llap{\textsf{rotation matrix}}} ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    0.8660  &amp;            -  0.5000  \\[2px]&#xD;&#xA;    0.5000  &amp;   \phantom{-} 0.8660&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\,.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Question:**  Why aren't the deformation gradient, $F ,$ and and the rotation matrix, $\textsf{rotation matrix} ,$ the same?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21102" PostHistoryTypeId="5" PostId="7996" RevisionGUID="7a3152bd-995f-41b6-b11b-5aaff62d9099" CreationDate="2018-08-30T09:11:40.277" UserId="9280" Comment="added 1 character in body" Text="I created two ellipses,&lt;br/&gt;$\hspace{150px}$&lt;a href=&quot;https://i.stack.imgur.com/WfzOU.png&quot;&gt;&lt;img src=&quot;https://i.stack.imgur.com/WfzOU.png&quot; width=&quot;300&quot;/&gt;&lt;/a&gt;,&lt;br/&gt;where the red ellipsis is as the blue one, except translated to the right and rotated by ${30}^{\circ} .$ Using rotation matrix, &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    x  \\[2px]&#xD;&#xA;    y   \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;\phantom{F} ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    cos(30^{\circ})  &amp; -sin(30^{\circ})  \\[2px]&#xD;&#xA;    sin(30^{\circ}) &amp; \phantom{}cos(30^{\circ})&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;*&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    X  \\[2px]&#xD;&#xA;    Y   \end{array}&#xD;&#xA;\right]&#xD;&#xA;\&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Next I tried to calculate deformation gradient by using principal axes(a and b for initial ellipsis,c and d for translated one), and then I decomposed $\vec{c}$ and $\vec{d}$ vectors,$$&#xD;&#xA;\begin{alignat}{7}&#xD;&#xA;\vec{c} &amp;~~=~~ 1.0021 \, \vec{b} &amp;~&amp;+ &amp;~&amp;0.8654 \, \vec{a} \\[5px]&#xD;&#xA;\vec{d} &amp;~~=~~ 0.8654 \, \vec{b} &amp;&amp;- &amp;&amp;0.2505 \, \vec{a}&#xD;&#xA;\end{alignat}&#xD;&#xA;$$and created the deformation gradient as$$&#xD;&#xA;F ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    \phantom{-} 0.8654  &amp;    1.0021  \\[2px]&#xD;&#xA;             -  0.2505  &amp;    0.8654&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\,.&#xD;&#xA;$$But it is obvious that, this is not the same as the ${30}^{\circ}$ rotation matrix that I had expected it to be,$$&#xD;&#xA;\phantom{F} {\llap{\textsf{rotation matrix}}} ~=~&#xD;&#xA;\left[&#xD;&#xA;  \begin{array}{cc}&#xD;&#xA;    0.8660  &amp;            -  0.5000  \\[2px]&#xD;&#xA;    0.5000  &amp;   \phantom{-} 0.8660&#xD;&#xA;  \end{array}&#xD;&#xA;\right]&#xD;&#xA;\,.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Question:**  Why aren't the deformation gradient, $F ,$ and and the rotation matrix, $\textsf{rotation matrix} ,$ the same?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21103" PostHistoryTypeId="50" PostId="7863" RevisionGUID="52f7f489-551c-4b08-a521-458c7a17d064" CreationDate="2018-08-30T14:00:50.953" UserId="-1" />
  <row Id="21104" PostHistoryTypeId="2" PostId="7997" RevisionGUID="8d019b5b-0662-447f-b6d4-fb6bd739b4a5" CreationDate="2018-08-30T14:34:33.357" UserId="8699" Text="I am writing a ray tracer using openCL, and following this tutorial http://raytracey.blogspot.com/2016/11/opencl-path-tracing-tutorial-2-path.html&#xD;&#xA;However, I find that the author has two copies of the Sphere code, one in host in c++ and one in device in cl. This causes duplication, which I would like to avoid if possible. &#xD;&#xA;Is there any way to avoid this? If there is, should the code for, say a sphere struct be in host or in device?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21105" PostHistoryTypeId="1" PostId="7997" RevisionGUID="8d019b5b-0662-447f-b6d4-fb6bd739b4a5" CreationDate="2018-08-30T14:34:33.357" UserId="8699" Text="OpenCL ray tracer: which is better, geometry code on device side or on host side?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21106" PostHistoryTypeId="3" PostId="7997" RevisionGUID="8d019b5b-0662-447f-b6d4-fb6bd739b4a5" CreationDate="2018-08-30T14:34:33.357" UserId="8699" Text="|raytracing|opencl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21112" PostHistoryTypeId="2" PostId="7999" RevisionGUID="5aad3a67-382c-482a-b8a7-31b04c78ee33" CreationDate="2018-08-31T07:36:55.160" UserId="6046" Text="In order to pass data to the device side, in OpenCL you must create the sphere structure on the device as well (that is in the kernel). So you first create your structures as classes or structs on the CPU. The variables in the structs should be of `cl_*` datatypes. OpenCL provides typedefs for all primitive data types. Then create these structures on the GPU as well.&#xD;&#xA;&#xD;&#xA;Care should be taken about data alignment when passing structures from CPU to GPU. If you have passed data in OpenGL, you'll know what this is about.&#xD;&#xA;&#xD;&#xA;After you create your structures on the CPU, you encode them in a OpenCL buffer, and pass this buffer to the kernel." ContentLicense="CC BY-SA 4.0" />
  <row Id="21120" PostHistoryTypeId="2" PostId="8003" RevisionGUID="c6f4d904-aeaf-4a97-be2d-cb0210d1706a" CreationDate="2018-09-01T08:21:28.047" UserId="4503" Text="How do I create a vertex shader that allows to choose 3 non aligned direction vectors and then allows to morph all vectors positions such that every vertex is remapped so that two vertices that are parallel to one of the axis, now become parallel to the direction between the vertex and a choosen vanishing points coordinate.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;  - Axis 1 : (1,0,0)&#xD;&#xA;  - Axis 2 : (0,1,0)&#xD;&#xA;  - Axis 3 : (0,0,1)&#xD;&#xA;&#xD;&#xA;Vanishing points:&#xD;&#xA;  - P1 : Axis 1*10000&#xD;&#xA;  - P2 : Axis 2*10000&#xD;&#xA;  - P3 : Axis 3*10000&#xD;&#xA;&#xD;&#xA;Assume then we have 2 points&#xD;&#xA;(3,0,100) and (6,0,100)&#xD;&#xA;&#xD;&#xA;Those are parallel to axis 1 so if i set the vanishing points 1 to (10000,10000,0) I expect  the coordinates of the points to become parallel to the new axe&#xD;&#xA;&#xD;&#xA;(3,3,100) and (6,6,100)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21121" PostHistoryTypeId="1" PostId="8003" RevisionGUID="c6f4d904-aeaf-4a97-be2d-cb0210d1706a" CreationDate="2018-09-01T08:21:28.047" UserId="4503" Text="Simulatori vanishing points shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="21122" PostHistoryTypeId="3" PostId="8003" RevisionGUID="c6f4d904-aeaf-4a97-be2d-cb0210d1706a" CreationDate="2018-09-01T08:21:28.047" UserId="4503" Text="|shader|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21123" PostHistoryTypeId="5" PostId="8003" RevisionGUID="a76c5554-8e58-469d-82dc-e2aaa9a4ca14" CreationDate="2018-09-01T08:28:06.847" UserId="4503" Comment="deleted 8 characters in body" Text="How do I create a vertex shader that allows to choose 3 non aligned direction vectors and then allows to morph all vectors positions such that every vertex is remapped so that two vertices that are parallel to one of the axis, now become parallel to the direction between the vertex and a choosen vanishing points coordinate.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;- Axis 1 : (1,0,0)&#xD;&#xA;- Axis 2 : (0,1,0)&#xD;&#xA;- Axis 3 : (0,0,1)&#xD;&#xA;&#xD;&#xA;Vanishing points:&#xD;&#xA;&#xD;&#xA;- P1 : Axis 1*10000&#xD;&#xA;- P2 : Axis 2*10000&#xD;&#xA;- P3 : Axis 3*10000&#xD;&#xA;&#xD;&#xA;Assume then we have 2 points&#xD;&#xA;(3,0,100) and (6,0,100)&#xD;&#xA;&#xD;&#xA;Those are parallel to axis 1 so if i set the vanishing points 1 to (10000,10000,0) I expect  the coordinates of the points to become parallel to the new axe&#xD;&#xA;&#xD;&#xA;(3,3,100) and (6,6,100).&#xD;&#xA;&#xD;&#xA;Basically I want to choose 3  Axis and rotate Them indipendently around the origin and then the geometry should morph accordingly." ContentLicense="CC BY-SA 4.0" />
  <row Id="21124" PostHistoryTypeId="4" PostId="8003" RevisionGUID="a76c5554-8e58-469d-82dc-e2aaa9a4ca14" CreationDate="2018-09-01T08:28:06.847" UserId="4503" Comment="deleted 8 characters in body" Text="Simulatingi vanishing points shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="21125" PostHistoryTypeId="5" PostId="8003" RevisionGUID="7f16846d-f41e-498d-9d4a-ab13d34404fd" CreationDate="2018-09-01T08:33:38.443" UserId="4503" Comment="deleted 8 characters in body" Text="How do I create a vertex shader that allows to choose 3 non aligned direction vectors and then allows to morph all vectors positions such that every vertex is remapped so that two vertices that are parallel to one of the axis, now become parallel to the direction between the vertex and a choosen vanishing points coordinate.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;- Axis 1 : (1,0,0)&#xD;&#xA;- Axis 2 : (0,1,0)&#xD;&#xA;- Axis 3 : (0,0,1)&#xD;&#xA;&#xD;&#xA;Vanishing points:&#xD;&#xA;&#xD;&#xA;- P1 : Axis 1*10000&#xD;&#xA;- P2 : Axis 2*10000&#xD;&#xA;- P3 : Axis 3*10000&#xD;&#xA;&#xD;&#xA;Assume then we have 2 points&#xD;&#xA;(3,0,100) and (6,0,100)&#xD;&#xA;&#xD;&#xA;Those are parallel to axis 1 so if i set the vanishing points 1 to (10000,10000,0) I expect  the coordinates of the points to become parallel to the new axe&#xD;&#xA;&#xD;&#xA;(3,3,100) and (6,6,100).&#xD;&#xA;&#xD;&#xA;Basically I want to choose 3  Axis and rotate Them indipendently around the origin and then the geometry should morph accordingly. The rotation is performed using &quot;target far away points&quot;.&#xD;&#xA;&#xD;&#xA;It is not necessary to handle huge rotation angles. 45 spherical degrees is more than enough" ContentLicense="CC BY-SA 4.0" />
  <row Id="21126" PostHistoryTypeId="4" PostId="8003" RevisionGUID="7f16846d-f41e-498d-9d4a-ab13d34404fd" CreationDate="2018-09-01T08:33:38.443" UserId="4503" Comment="deleted 8 characters in body" Text="Simulating vanishing points shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="21130" PostHistoryTypeId="5" PostId="7984" RevisionGUID="5d0d67f3-8003-4969-abc6-c04dda799f85" CreationDate="2018-09-02T12:38:39.967" UserId="2485" Comment="Added more information" Text="I am generating plane vertices where the y values are generated by a heightmap (noise) algorithm. This is how I produce my vertex array:&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; noise.length; row++) {&#xD;&#xA;        for (let col = 0; col &lt; noise[0].length; col++) {&#xD;&#xA;            color = noise[row][col];&#xD;&#xA;            positions.push(row, color, col);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After that I generate index values like this (I know that there is a lot of optimization that can be done here):&#xD;&#xA;&#xD;&#xA;    const height = noise.length + 1;&#xD;&#xA;    const width = noise[0].length + 1;&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; height - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            if (row === height - 2) break;&#xD;&#xA;            for (let col = 0; col &lt; width - 1; col++) {&#xD;&#xA;                indices.push(col + row * (width));&#xD;&#xA;                indices.push(col - 1 + (row + 1) * (width));&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = width - 2; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col - 2 + (row + 1) * (width));&#xD;&#xA;                indices.push(col - 2 + row * (width));&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    indices.pop();&#xD;&#xA;&#xD;&#xA;Finally I draw the plane using:&#xD;&#xA;&#xD;&#xA; `gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);`&#xD;&#xA;&#xD;&#xA;So if I use `POINTS` as mode, the plane seem to look as it should:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Whereas if I am using `TRINGLE_STRIP` the result looks wrong:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;First I thought wrong indices might be the reason but then I checked by scaling to a 3x3 grid/plane and the vertex and index output looked as I would have expected:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;    [-1, -43.89, -1, &#xD;&#xA;    -1,  -82.27,  0, &#xD;&#xA;    -1,  -23.06,  1, &#xD;&#xA;     0,  -43.43, -1, &#xD;&#xA;     0,  -54.85,  0, &#xD;&#xA;     0,  -66.27,  1, &#xD;&#xA;     1,  -61.89, -1, &#xD;&#xA;     1,  -27.43,  0, &#xD;&#xA;     1,  -59.89,  1]&#xD;&#xA;&#xD;&#xA;**Note:** &#xD;&#xA;&#xD;&#xA;&gt; The vertices might not exactly correspond to what you would have&#xD;&#xA;&gt; expected from above loop. That is because I am centering the `mesh`&#xD;&#xA;&gt; around origin after the loop.&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So my guess is that the problem is that I am pushing my triangles counterclockwise, that is why I tried to enable culling and depth testing but that did not help either:&#xD;&#xA;&#xD;&#xA;    gl.enable(gl.DEPTH_TEST);&#xD;&#xA;    gl.enable(gl.CULL_FACE);&#xD;&#xA;    gl.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Any guess what might be the reason for wrong `TRIANGLE_STRIP` rendering?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;According to @PaulHK's recommendation I changed my index creation loop to insert the last index of a single strip twice. &#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; rows - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            for (let col = 0; col &lt; cols; col++) {&#xD;&#xA;                indices.push(col + row * cols);&#xD;&#xA;                indices.push(col + (row + 1) * cols);&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = cols - 1; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col + (row) * cols);&#xD;&#xA;                indices.push(col + (row + 1) * cols);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For a 3x3 grid this produces:&#xD;&#xA;&#xD;&#xA;**Vertices:**&#xD;&#xA;&#xD;&#xA;    [-1, -9.6, -1,&#xD;&#xA;     -1, -64.6, 0,&#xD;&#xA;     -1, -11.1, 1,&#xD;&#xA;     0, -38.8, -1,&#xD;&#xA;     0, -32.8, 0,&#xD;&#xA;     0, -26.8, 1,&#xD;&#xA;     1, -37.0, -1,&#xD;&#xA;     1, -1, 0,&#xD;&#xA;     1, -47.5, 1]&#xD;&#xA;&#xD;&#xA;**Indices:**&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Unfortunately the rendered object still looks the same.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JVCye.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PbGXw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/IhodK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21132" PostHistoryTypeId="5" PostId="7984" RevisionGUID="c7e67969-fc9a-4e62-9d42-f1a816b22ff5" CreationDate="2018-09-02T14:34:28.287" UserId="2485" Comment="added Update 2" Text="I am generating plane vertices where the y values are generated by a heightmap (noise) algorithm. This is how I produce my vertex array:&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; noise.length; row++) {&#xD;&#xA;        for (let col = 0; col &lt; noise[0].length; col++) {&#xD;&#xA;            color = noise[row][col];&#xD;&#xA;            positions.push(row, color, col);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After that I generate index values like this (I know that there is a lot of optimization that can be done here):&#xD;&#xA;&#xD;&#xA;    const height = noise.length + 1;&#xD;&#xA;    const width = noise[0].length + 1;&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; height - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            if (row === height - 2) break;&#xD;&#xA;            for (let col = 0; col &lt; width - 1; col++) {&#xD;&#xA;                indices.push(col + row * (width));&#xD;&#xA;                indices.push(col - 1 + (row + 1) * (width));&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = width - 2; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col - 2 + (row + 1) * (width));&#xD;&#xA;                indices.push(col - 2 + row * (width));&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    indices.pop();&#xD;&#xA;&#xD;&#xA;Finally I draw the plane using:&#xD;&#xA;&#xD;&#xA; `gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);`&#xD;&#xA;&#xD;&#xA;So if I use `POINTS` as mode, the plane seem to look as it should:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Whereas if I am using `TRINGLE_STRIP` the result looks wrong:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;First I thought wrong indices might be the reason but then I checked by scaling to a 3x3 grid/plane and the vertex and index output looked as I would have expected:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;    [-1, -43.89, -1, &#xD;&#xA;    -1,  -82.27,  0, &#xD;&#xA;    -1,  -23.06,  1, &#xD;&#xA;     0,  -43.43, -1, &#xD;&#xA;     0,  -54.85,  0, &#xD;&#xA;     0,  -66.27,  1, &#xD;&#xA;     1,  -61.89, -1, &#xD;&#xA;     1,  -27.43,  0, &#xD;&#xA;     1,  -59.89,  1]&#xD;&#xA;&#xD;&#xA;**Note:** &#xD;&#xA;&#xD;&#xA;&gt; The vertices might not exactly correspond to what you would have&#xD;&#xA;&gt; expected from above loop. That is because I am centering the `mesh`&#xD;&#xA;&gt; around origin after the loop.&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So my guess is that the problem is that I am pushing my triangles counterclockwise, that is why I tried to enable culling and depth testing but that did not help either:&#xD;&#xA;&#xD;&#xA;    gl.enable(gl.DEPTH_TEST);&#xD;&#xA;    gl.enable(gl.CULL_FACE);&#xD;&#xA;    gl.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Any guess what might be the reason for wrong `TRIANGLE_STRIP` rendering?&#xD;&#xA;&#xD;&#xA;**Update 1:**&#xD;&#xA;&#xD;&#xA;According to @PaulHK's recommendation I changed my index creation loop to insert the last index of a single strip twice. &#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; rows - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            for (let col = 0; col &lt; cols; col++) {&#xD;&#xA;                indices.push(col + row * cols);&#xD;&#xA;                indices.push(col + (row + 1) * cols);&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = cols - 1; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col + (row) * cols);&#xD;&#xA;                indices.push(col + (row + 1) * cols);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For a 3x3 grid this produces:&#xD;&#xA;&#xD;&#xA;**Vertices:**&#xD;&#xA;&#xD;&#xA;    [-1, -9.6, -1,&#xD;&#xA;     -1, -64.6, 0,&#xD;&#xA;     -1, -11.1, 1,&#xD;&#xA;     0, -38.8, -1,&#xD;&#xA;     0, -32.8, 0,&#xD;&#xA;     0, -26.8, 1,&#xD;&#xA;     1, -37.0, -1,&#xD;&#xA;     1, -1, 0,&#xD;&#xA;     1, -47.5, 1]&#xD;&#xA;&#xD;&#xA;**Indices:**&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Unfortunately the rendered object still looks the same.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Update 2:**&#xD;&#xA;&#xD;&#xA;I use the Diamond-square algorithm to generate the mesh. This requires a grid of size `(2^n) + 1`.&#xD;&#xA;I.e.:&#xD;&#xA;&#xD;&#xA;&gt; 2, 3, 5, 9, 17, 33, 65, 129, 257, 513 ...&#xD;&#xA;&#xD;&#xA;Maybe it's just a coincidence but it seems to me that the grid can be displayed correctly for sizes `3 - 129` with the procedure from **Update 1**. For a size of 257 and above the mesh has errors.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JVCye.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PbGXw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/IhodK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21137" PostHistoryTypeId="2" PostId="8006" RevisionGUID="6b6f848b-23cd-434e-9037-71a5b3577bf4" CreationDate="2018-09-02T20:06:16.873" UserId="9293" Text="Is there any 3d software that supports rendering an artificial scene to a light field image?&#xD;&#xA;&#xD;&#xA;With that I mean an image capturing light from more than one point in a scene, more lika a spherical volume of evenly distributed points.&#xD;&#xA;&#xD;&#xA;There is [research][1] being done by for instance P Debevec for Google VR that does this for physical scenes with an expensive camera rig. I would like to be able to render the same output but from an artificial scene, in for instance 3dsmax. And then preferably use this in for instance Unity 3D.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blog.google/products/google-ar-vr/experimenting-light-fields/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21138" PostHistoryTypeId="1" PostId="8006" RevisionGUID="6b6f848b-23cd-434e-9037-71a5b3577bf4" CreationDate="2018-09-02T20:06:16.873" UserId="9293" Text="Light field rendering for 3d software?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21139" PostHistoryTypeId="3" PostId="8006" RevisionGUID="6b6f848b-23cd-434e-9037-71a5b3577bf4" CreationDate="2018-09-02T20:06:16.873" UserId="9293" Text="|raytracing|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21140" PostHistoryTypeId="2" PostId="8007" RevisionGUID="b88a7a88-62ee-439c-bfa5-86c3161b288a" CreationDate="2018-09-03T03:28:28.203" UserId="9248" Text="in future, will sRGB which is a common standard monitor color space nowadays be taken the place by the wider gamut color spaces?&#xD;&#xA;&#xD;&#xA;since wide gamut monitor keep publishing in the market and may be affordable for anyone one day, will the majority change to use the wider gamut in like coming 20 to 30 years?&#xD;&#xA;&#xD;&#xA;or stay with sRGB and not worth to change." ContentLicense="CC BY-SA 4.0" />
  <row Id="21141" PostHistoryTypeId="1" PostId="8007" RevisionGUID="b88a7a88-62ee-439c-bfa5-86c3161b288a" CreationDate="2018-09-03T03:28:28.203" UserId="9248" Text="Will sRGB color space get replaced by wider gamut" ContentLicense="CC BY-SA 4.0" />
  <row Id="21142" PostHistoryTypeId="3" PostId="8007" RevisionGUID="b88a7a88-62ee-439c-bfa5-86c3161b288a" CreationDate="2018-09-03T03:28:28.203" UserId="9248" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21143" PostHistoryTypeId="33" PostId="7994" RevisionGUID="237364b9-caa8-4283-aa2e-568df9d5e6c5" CreationDate="2018-09-03T03:50:18.223" UserId="2308" Comment="49" />
  <row Id="21144" PostHistoryTypeId="2" PostId="8008" RevisionGUID="98b6e11a-dc4c-4279-815f-c92b65a769d8" CreationDate="2018-09-03T05:08:56.200" UserId="2308" Text="I should preface with currently this question is mostly asking about Metal and iOS GPUs. That being said if this is GPU or OS specific and you can go into detail about other platforms that would be great to as this application will eventually be cross platform.&#xD;&#xA;&#xD;&#xA;I am drawing some geometry in two draw calls.&#xD;&#xA;&#xD;&#xA; 1. Opaque geometry is drawn. Discards happen. No particular triangle draw order. Fragments in this draw call occupy only 5% of the screens pixels.&#xD;&#xA; 2. Transparent geometry is drawn. No discards happen. Triangles are drawn in depth order. Fragments in this call occupy a bulk of the screen pixels.&#xD;&#xA;&#xD;&#xA;The question is essentially should I convert draw call 1 to ordered triangles with alpha=0 where I would generally discard. There will be a cost to ordering the triangles in draw 1 however it will not be two costly.&#xD;&#xA;&#xD;&#xA;The reason I am unsure is that I know the second you call discard on a fragment you remove the possibility of Metal preforming early depth test which is allegedly quite an optimization. What I dont know is if discards disable early depth test on draw call 1 do they also disable the optimization for draw call 2's geometry?&#xD;&#xA;&#xD;&#xA;Does the fragment stage happen after each draw calls vertex phase or after all of them?&#xD;&#xA;&#xD;&#xA;Do you think I should explore sorting the triangles and using alpha blending on draw call 1? Again this would be a negligible CPU cost would it actually help the GPU? " ContentLicense="CC BY-SA 4.0" />
  <row Id="21145" PostHistoryTypeId="1" PostId="8008" RevisionGUID="98b6e11a-dc4c-4279-815f-c92b65a769d8" CreationDate="2018-09-03T05:08:56.200" UserId="2308" Text="Are the benefits of a Metal early depth test limited to one draw call" ContentLicense="CC BY-SA 4.0" />
  <row Id="21146" PostHistoryTypeId="3" PostId="8008" RevisionGUID="98b6e11a-dc4c-4279-815f-c92b65a769d8" CreationDate="2018-09-03T05:08:56.200" UserId="2308" Text="|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21147" PostHistoryTypeId="2" PostId="8009" RevisionGUID="c55f670b-52f9-4c05-9e75-37c0138f10fb" CreationDate="2018-09-03T07:36:01.903" UserId="6496" Text="I am migrating code from CUDA to OpenGL compute shaders.&#xD;&#xA;I could not find a way to set the local workgroup size outside the shader; is there a way to set gl_WorkGroupSize in the calling program like one can do for gl_NumWorkGroups?&#xD;&#xA;Thanks in advance" ContentLicense="CC BY-SA 4.0" />
  <row Id="21148" PostHistoryTypeId="1" PostId="8009" RevisionGUID="c55f670b-52f9-4c05-9e75-37c0138f10fb" CreationDate="2018-09-03T07:36:01.903" UserId="6496" Text="Can gl_WorkGroupSize be set outside the compute shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21149" PostHistoryTypeId="3" PostId="8009" RevisionGUID="c55f670b-52f9-4c05-9e75-37c0138f10fb" CreationDate="2018-09-03T07:36:01.903" UserId="6496" Text="|opengl|compute-shader|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21150" PostHistoryTypeId="2" PostId="8010" RevisionGUID="a2424b27-0586-433e-a501-c59bbeb7e88b" CreationDate="2018-09-03T09:47:57.040" UserId="209" Text="I don't know what Apple have done with Metal per se, but as these are PowerVR-derived GPUs, normally I would think that doing as much opaque-only drawing &quot;up front&quot; would usually be beneficial, but *if*, as in your case, only 5% of the screen is covered by opaque geometry, I'm not sure how much the software overhead will affect things.&#xD;&#xA;&#xD;&#xA;&gt; The reason I am unsure is that I know the second you call discard on a fragment you remove the possibility of Metal preforming early depth test which is allegedly quite an optimization. What I dont know is if discards disable early depth test on draw call 1 do they also disable the optimization for draw call 2's geometry?&#xD;&#xA;&#xD;&#xA;With PowerVR devices, a depth test can &quot;always&quot; be done as the first step in the pipeline, so any geometry that was submitted earlier model *can* cull later things prior to fragment shading. &#xD;&#xA;&#xD;&#xA;With alpha-tested (AKA &quot;punch-though&quot;), the Z-test can thus be done against previous geometry, but there may be a cost of then doing the texturing/shading and feeding that back to update the depths for subsequent geometry.&#xD;&#xA;&#xD;&#xA;If you aren't doing alpha-test/discards, and are doing your own sorting, then this feedback is not required (but obviously there may be more shading/texturing work to perform).&#xD;&#xA;&#xD;&#xA;(Such a pity, though, that we removed the OIT feature from the early PowerVR hardware)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;Does the fragment stage happen after each draw calls vertex phase or after all of them?&#xD;&#xA;&#xD;&#xA;I'm not sure what you are asking, but for a given scene, all the vertex shading (across multiple calls) is performed**, the geometry buffered, and then rendering commences on the entire scene.&#xD;&#xA;&#xD;&#xA;_**There are some caveats here but that probably doesn't affect you_.&#xD;&#xA;&#xD;&#xA;&gt;Do you think I should explore sorting the triangles and using alpha blending on draw call 1? Again this would be a negligible CPU cost would it actually help the GPU? &#xD;&#xA;&#xD;&#xA;Are you asking &quot;should I profile/time the results and see what is best for my use case?&quot;.  Probably &quot;yes&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="21151" PostHistoryTypeId="5" PostId="8010" RevisionGUID="a5ab2c8c-23cb-4515-999d-5cbb75b62c23" CreationDate="2018-09-03T11:41:09.003" UserId="209" Comment="added 11 characters in body" Text="I don't know what Apple have done with Metal per se, but as the iOS devices have PowerVR-derived GPUs, normally I would think that doing as much opaque-only drawing &quot;up front&quot; would usually be beneficial, but *if*, as in your case, only 5% of the screen is covered by opaque geometry, I'm not sure how much the software overhead will affect things.&#xD;&#xA;&#xD;&#xA;&gt; The reason I am unsure is that I know the second you call discard on a fragment you remove the possibility of Metal preforming early depth test which is allegedly quite an optimization. What I dont know is if discards disable early depth test on draw call 1 do they also disable the optimization for draw call 2's geometry?&#xD;&#xA;&#xD;&#xA;With PowerVR devices, a depth test can &quot;always&quot; be done as the first step in the pipeline, so any geometry that was submitted earlier model *can* cull later things prior to fragment shading. &#xD;&#xA;&#xD;&#xA;With alpha-tested (AKA &quot;punch-though&quot;), the Z-test can thus be done against previous geometry, but there may be a cost of then doing the texturing/shading and feeding that back to update the depths for subsequent geometry.&#xD;&#xA;&#xD;&#xA;If you aren't doing alpha-test/discards, and are doing your own sorting, then this feedback is not required (but obviously there may be more shading/texturing work to perform).&#xD;&#xA;&#xD;&#xA;(Such a pity, though, that we removed the OIT feature from the early PowerVR hardware)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;Does the fragment stage happen after each draw calls vertex phase or after all of them?&#xD;&#xA;&#xD;&#xA;I'm not sure what you are asking, but for a given scene, all the vertex shading (across multiple calls) is performed**, the geometry buffered, and then rendering commences on the entire scene.&#xD;&#xA;&#xD;&#xA;_**There are some caveats here but that probably doesn't affect you_.&#xD;&#xA;&#xD;&#xA;&gt;Do you think I should explore sorting the triangles and using alpha blending on draw call 1? Again this would be a negligible CPU cost would it actually help the GPU? &#xD;&#xA;&#xD;&#xA;Are you asking &quot;should I profile/time the results and see what is best for my use case?&quot;.  Probably &quot;yes&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="21152" PostHistoryTypeId="5" PostId="8006" RevisionGUID="2f864caa-1526-4be2-9481-51d185929796" CreationDate="2018-09-03T12:33:57.883" UserId="9293" Comment="added 285 characters in body" Text="Is there any 3d software that supports rendering an artificial scene to a light field image?&#xD;&#xA;&#xD;&#xA;With that I mean an image capturing light from more than one point in a scene, more lika a spherical volume of evenly distributed points.&#xD;&#xA;&#xD;&#xA;There is [research][1] being done by for instance P Debevec for Google VR that does this for physical scenes with an expensive camera rig. I would like to be able to render the same output but from an artificial scene, in for instance 3dsmax. And then preferably use this in for instance Unity 3D.&#xD;&#xA;&#xD;&#xA;Would be awesome for a Myst-like game with high fidelity ray traced graphics instead of crappy real time graphics. But I guess animations would be out almost of the question. It should at least in theory be easier to incorporate animations in cgi-light fields than in real photos.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blog.google/products/google-ar-vr/experimenting-light-fields/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21153" PostHistoryTypeId="2" PostId="8011" RevisionGUID="16227bf5-29c9-4996-9a35-de0a9d878a16" CreationDate="2018-09-03T13:08:08.583" UserDisplayName="user8054" Text="Let's say that I want to render something like [Dimmadome's hat][2], a hat which has the height of infinity.&#xD;&#xA;&#xD;&#xA;A quick answer to this would be to place the top side of the hat high enough for the crown(cylinder) to be cropped(like y=9999999...) half way in the view. I don't like this idea. So what I came up with is using [IEEE 754 infinity][1] in vertices.&#xD;&#xA;&#xD;&#xA;    (-0.5, INF, -0.5)&#xD;&#xA;    (0.5, INF, -0.5)&#xD;&#xA;    (0.5, INF, 0.5)&#xD;&#xA;    (-0.5, INF, 0.5)&#xD;&#xA;&#xD;&#xA;(assuming the crown is a cube)&#xD;&#xA;&#xD;&#xA;The problem is that after multiplying with the transform matrix, the vertices end up being all `(INF, INF, INF)`, making them unrenderable. I just wrote this to give you an idea.&#xD;&#xA;&#xD;&#xA;Is there any technique that can be used to achieve this? rather than using huge number? I wonder how they implemented [this][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/10435253/glsl-infinity-constant&#xD;&#xA;  [2]: http://fairlyoddparents.wikia.com/wiki/File:OddOddWest294.jpg&#xD;&#xA;  [3]: https://steamcommunity.com/sharedfiles/filedetails/?id=628176154&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21154" PostHistoryTypeId="1" PostId="8011" RevisionGUID="16227bf5-29c9-4996-9a35-de0a9d878a16" CreationDate="2018-09-03T13:08:08.583" UserDisplayName="user8054" Text="Infinitely long 3D model" ContentLicense="CC BY-SA 4.0" />
  <row Id="21155" PostHistoryTypeId="3" PostId="8011" RevisionGUID="16227bf5-29c9-4996-9a35-de0a9d878a16" CreationDate="2018-09-03T13:08:08.583" UserDisplayName="user8054" Text="|3d|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21156" PostHistoryTypeId="2" PostId="8012" RevisionGUID="07dece79-6ef2-46cd-aa8f-f811313c6cfd" CreationDate="2018-09-03T17:01:34.620" UserId="2654" Text="Core OpenGL has no mechanism for this. The [ARB_compute_variable_group_size][1] extension provides such a feature. It doesn't allow for indirect compute operations though.&#xD;&#xA;&#xD;&#xA;It [doesn't seem to have much AMD support][2] though (outside of open source Linux drivers). And Intel support is nil.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_compute_variable_group_size.txt&#xD;&#xA;  [2]: http://opengl.gpuinfo.org/listreports.php?extension=GL_ARB_compute_variable_group_size" ContentLicense="CC BY-SA 4.0" />
  <row Id="21157" PostHistoryTypeId="5" PostId="7994" RevisionGUID="3cc9f6ff-1b82-4447-88f2-846fc677c283" CreationDate="2018-09-03T19:51:52.070" UserId="2308" Comment="edited body" Text="So I have a bit of a predicament I am trying to solve. I have 10,000 triangle strips I am trying to draw. Each one has a z-order for the entire strip and within each strip the most recent triangles need to have a higher z order than the older one. So essentially the z order of a triangle is `(stripIndex / 10000) + (age / MAX_AGE)` where MAX_AGE is somewhere around 100 frames. I am not sure about this number yet.&#xD;&#xA;&#xD;&#xA;At start time all of the data to store this is initialized and a ring buffer of some form is used so that the most recent triangle's are in a new position each frame.&#xD;&#xA;&#xD;&#xA;This ring buffer is useful because only 2 triangles will have to be written for each frame per triangle strip so no data has to shift or move. You just over-write the oldest data.&#xD;&#xA;&#xD;&#xA;The trick is I want to do alpha blending between these triangle strips so I need to have the geometry drawn in order from front to back. I am experimenting with different layouts that will allow me to minimize draw calls and CPU stress required. This is an unsolved problem for me but I think I am going to have to do 10001 draw calls. But that is not what this question is about.&#xD;&#xA;&#xD;&#xA;So while trying to do this I ran into an odd GPU phenomenon I cant explain. Right now I am rendering with a simple no-depth additive blending Metal pipeline that looks like this.&#xD;&#xA;&#xD;&#xA;    id&lt;MTLFunction&gt; vertex_f = [MetalCore compileShader:vertex];&#xD;&#xA;    id&lt;MTLFunction&gt; fragment_f = [MetalCore compileShader:fragment];&#xD;&#xA;&#xD;&#xA;    MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];&#xD;&#xA;    descriptor.sampleCount = 1;&#xD;&#xA;    descriptor.fragmentFunction = fragment_f;&#xD;&#xA;    descriptor.vertexFunction = vertex_f;&#xD;&#xA;    descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;As I said at the beginning I create a buffer that holds all of the triangles necessary to draw each of the strips. The buffer is the same size every time and the triangle count is also constant. The buffers do have indices and that is also constant and created at the beginning. The underlying simulation that controls these triangle strips is also constant. However under two different memory layout conditions there are significantly different frame rates even under multiple trials. I cant figure out why. &#xD;&#xA;&#xD;&#xA;From now on I will refer to 10000 as MAX_STRIPS&#xD;&#xA;&#xD;&#xA;Memory configuration 1 has a triangle for the n'th strip in the i'th ring buffer position located in the triangle buffer at `i*MAX_STRIPS*4 + n*4` th position in the buffer. So in memory a single strips triangles are very spread out but a concentrated chunk of memory is updated each frame. &#xD;&#xA;&#xD;&#xA;Memory configuration 2 has a triangle for the n'th strip in the i'th ring buffer position located in the triangle buffer at the `n*MAX_AGE*4 + i*4` th position in the buffer. All of a single triangle strips vertices are close together in memory however writing is more spread out.&#xD;&#xA;&#xD;&#xA;For whatever reason configuration 1 takes significantly longer than configuration 2 to render.&#xD;&#xA;&#xD;&#xA;Now I could understand a small difference in CPU time but what I dont get is this difference in GPU time. Any clue as to why this might be happening.&#xD;&#xA;&#xD;&#xA;The following compares debugging information of these two methods. The left side is memory configuration 1. The right is memory configuration 2. Big difference are highlighted.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the vertex shader for all interested &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    struct VertexOutAlpha {&#xD;&#xA;        float4 position [[ position ]];&#xD;&#xA;        float4 color;&#xD;&#xA;    };&#xD;&#xA;    struct StripVertex {&#xD;&#xA;        float3 data; //z value is the z value for the entire strip. Triangles will have different z positions&#xD;&#xA;        float2 color;//x = color, y = time&#xD;&#xA;    };&#xD;&#xA;    vertex VertexOutAlpha strip_vertex(constant StripVertex * vertexBuffer [[ buffer(0) ]],&#xD;&#xA;                                  indexType vid [[ vertex_id ]],&#xD;&#xA;                                  constant matrix_float3x3* matrix [[buffer(1)]],&#xD;&#xA;                                  constant float* gameTime [[buffer(2)]]) {&#xD;&#xA;        StripVertex vert = vertexBuffer[vid];&#xD;&#xA;        VertexOutAlpha out;&#xD;&#xA;        float dimmer = 1.0 - clamp(((*gameTime - 0.016) - vert.color.y) * 10.0, 0.0, 1.0);&#xD;&#xA;        const float levelSize = 1.0 / (MAX_STRIPS + 0.01);&#xD;&#xA;        out.position = float4((*matrix * float3(vert.data.x, vert.data.y, 1.0)).xy, vert.data.z + (1 - dimmer) * levelSize, 1.0);&#xD;&#xA;        &#xD;&#xA;         out.color = float4(HSVtoRGB(vert.color.x, 1.0, dimmer), 1.0);&#xD;&#xA;        return out;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the generation of the vertex buffer for all interested&#xD;&#xA;&#xD;&#xA;        //triangleStripDataPtr is pre-allocated and alligned to the page size&#xD;&#xA;        triangleStripDataBuffer = [self.device newBufferWithBytesNoCopy:triangleStripDataPtr length:4 * MAX_STRIPS *  MAX_AGE options:MTLResourceStorageModeShared deallocator:nil];&#xD;&#xA;        assert(triangleStripDataBuffer != nil);&#xD;&#xA;&#xD;&#xA;Does anyone have a good explanation for why this is happening?&#xD;&#xA;  [1]: https://i.stack.imgur.com/OFdDU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21158" PostHistoryTypeId="2" PostId="8013" RevisionGUID="bd9a22ee-b115-4271-b763-47df50253b95" CreationDate="2018-09-03T20:07:01.420" UserId="6046" Text="So I am in the midst of writing my own path traced renderer and right now I have only implemented the old Blinn-Phong models where we separately calculated the diffuse and specular components of the material and each object had a specular and a diffuse color. &#xD;&#xA;&#xD;&#xA;Now going towards the more general side I want to be able to render different types of objects wood, polished wood, perfect mirror like reflections etc. However all this information confuses me on how should I implement these BSDFs or in other words how should I choose when to apply a certain BSDF or maybe a combination of two?&#xD;&#xA;&#xD;&#xA;This is usually done using a material approach. The material being diffuse, glossy or perfect specular would define which BSDFs should I use.&#xD;&#xA;&#xD;&#xA;I read PBRT for clues and they break surface reflection into 4 types. Diffuse, Glossy Specular, Specular and retro reflective. Then they implement an `enum` that stores the type corresponding to these reflection.&#xD;&#xA;&#xD;&#xA;The enum has the types&#xD;&#xA;&#xD;&#xA;    BSDF_REFLECTION&#xD;&#xA;    BSDF_TRANSMISSION&#xD;&#xA;    BSDF_DIFFUSE&#xD;&#xA;    BSDF_GLOSSY&#xD;&#xA;    BSDF_SPECULAR&#xD;&#xA;    BSDF_ALL&#xD;&#xA;&#xD;&#xA;**1)** The users are supposed to select a bitwise combination of the first two and the next 3 ones. Where `BSDF_ALL` is a combination of all the flags. This interface seems nice but there is one little confusion. If `BSDF_ALL` combines all flags, then this means the surface can be `diffuse` and `specular`. However this seems odd, a perfectly specular surface can't be diffuse. While `Glossy + Diffuse` make sense (polished wood, paint on a rough wall), `diffuse + specular` and `glossy + specular` don't make sense to me.&#xD;&#xA;&#xD;&#xA;**2)** Assuming we have solved the above problem consider an object that is glossy+diffuse like an orange or lemon skin. How do we calculate the color for this surface? Suppose I am using [Oran-Nayar][1] model (ON) for diffuse surfaces and [Cook-Torrance][2] (CT) for specular ones. &#xD;&#xA;&#xD;&#xA;Should I compute the diffuse component through ON and specular through (CT) then add them together? However both of these models have their own parameters which define the slope distribution for microfacet. For ON that's $\sigma^2$, the variance of the Gaussian distribution and for CT that's $m$, which wiki describes as &quot;RMS slope of microfacets&quot; (check respective links). Which one of these will govern the roughness of the surface?&#xD;&#xA;&#xD;&#xA;**3)** Moving on further there is a more general question. In the older models such as Blinn-Phong we used to have a separate diffuse and specular color. The specular color, from what I understand is nothing more than the Fresnel Reflectance. This is because Fresnel reflectance is dependent on wavelength. In case of Dielectrics this isn't discernable but for metals it usually is (gold gives of a yellowish tint). Hence for dielectrics the specular color would just be the plain old Fresnel reflectance replicated across RGB channels while for metals this would be the color of the tint. &#xD;&#xA;&#xD;&#xA;The thing that confuses me is the lingering concept of diffuse and specular reflectivity. Consider Cook-Torrance's original paper where they describe their model as.&#xD;&#xA;&#xD;&#xA;$R = dR_d + sR_s$&#xD;&#xA;&#xD;&#xA;Where $d$ and $s$ are the coeffecients for diffuse and specular reflectivity respectively and they must hold the condition.&#xD;&#xA;&#xD;&#xA;$d+s \leq 1$&#xD;&#xA;&#xD;&#xA;$R_d$ is any diffuse BRDF (they assume lambertian) while $R_s$ is their new proposed BRDF for specular surfaces.&#xD;&#xA;&#xD;&#xA;That's where my biggest confusion is. I was thinking the diffuse and specular colors as the object's respective reflectivities in each channel. The above equation however separates the color from reflectivity. **Which concept is used in PBR?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Specular_highlight#Cook%E2%80%93Torrance_model" ContentLicense="CC BY-SA 4.0" />
  <row Id="21159" PostHistoryTypeId="1" PostId="8013" RevisionGUID="bd9a22ee-b115-4271-b763-47df50253b95" CreationDate="2018-09-03T20:07:01.420" UserId="6046" Text="PBR - How to handle multiple BSDFs and material type" ContentLicense="CC BY-SA 4.0" />
  <row Id="21160" PostHistoryTypeId="3" PostId="8013" RevisionGUID="bd9a22ee-b115-4271-b763-47df50253b95" CreationDate="2018-09-03T20:07:01.420" UserId="6046" Text="|brdf|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21161" PostHistoryTypeId="2" PostId="8014" RevisionGUID="42a59f26-c62a-4b81-82a2-3eea2e48e91e" CreationDate="2018-09-03T21:10:16.860" UserId="9254" Text="For simplicity, assume we're only dealing with surfaces which have either a Lambertian or perfectly specular material. Morever, assume that the only type of lights are area lights (i.e. surfaces with an emissive material) and we stop tracing at lights.&#xD;&#xA;&#xD;&#xA;In path tracing, we start by tracing a ray from the eye through a random point on the area of the view plane corresponding to the $i$th pixel. Now, depending on the BRDF of the hitted surface, we choose either a uniformly distributed direction on the hemisphere over the normal at the hit point (in the case of a Lambertian surface) or the direction of perfect mirror reflection (in the case of a perfectly specular surface). This process stops, when either no surface or a surface with an emissive material (i.e. an area light) was hit.&#xD;&#xA;&#xD;&#xA;**Quesiton 1**: Now, PSSMLT constructs a sequence $(X_n)_{n\in\mathbb N}\subseteq[0,1]$. Actually, it's even clear to me how this sequence is modified by small step and large step modifications. However, what are the components $X_n$ exactly? Are $(X_1,X_2)$ the (normialized) coordinates of the randomly chosen area of the view plane corresponding to a pixel? If so, which pixel? And what is $(X_3,X_4)$? Maybe randomly chosen points on a unit square which need to be mapped to the hemisphere of the corresponding hit point? If so, we would need to store the normal and the BRDF together with $(X_3,X_4)$, don't we? And what if the surface which was hit has a perfectly specular material? Are then $(X_3,X_4)$ simply ignored?&#xD;&#xA;&#xD;&#xA;**Question 2**: I've read that initial sequence $(X_n)_{n\in\mathbb N}$ is chosen by approximating the &quot;luminance of path contribution&quot; which is said to be independent of the pixel. I don't get that at all. And I have no idea how it is approximated by using path tracing." ContentLicense="CC BY-SA 4.0" />
  <row Id="21162" PostHistoryTypeId="1" PostId="8014" RevisionGUID="42a59f26-c62a-4b81-82a2-3eea2e48e91e" CreationDate="2018-09-03T21:10:16.860" UserId="9254" Text="How does Primary Sample Space Metropolis Light Transport work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21163" PostHistoryTypeId="3" PostId="8014" RevisionGUID="42a59f26-c62a-4b81-82a2-3eea2e48e91e" CreationDate="2018-09-03T21:10:16.860" UserId="9254" Text="|raytracing|rendering|pathtracing|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21164" PostHistoryTypeId="2" PostId="8015" RevisionGUID="94fec46a-94c6-4bbf-93ec-430b4fb43d35" CreationDate="2018-09-03T23:00:41.957" UserId="6588" Text="1. PSSMT operates directly on the space of random numbers that generate valid light paths. As such, mutations in the unit hypercube *lose* their physical interpretation since they do not have direct knowledge of the actual light path constructed. Recent research in rendering has shown that it is possible to bridge the gap between path space (that acts directly on the paths) and primary sample space (that acts on uniform variates) to some extent. See [Bitterli 2018](https://benedikt-bitterli.me/rjmlt/), [Pantaleoni 2017](https://dl.acm.org/citation.cfm?id=3073677) and [Otsu 2017](https://dl.acm.org/citation.cfm?id=3073691) if that interests you.&#xD;&#xA;&#xD;&#xA;2. I am not entirely sure what you mean here, but typically an initial path of length $k$ will be formed using path tracing, and thus random numbers will be used along the way ($k+2$ if you are using BDPT). PSSMLT will mutate this path by acting only on the random numbers. Path throughput is indeed independent of the pixel but you only care about paths actually reaching the eye. At the end of the day, you are importance sampling paths according to their contribution to the final image, and luminance is what is commonly used. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21165" PostHistoryTypeId="2" PostId="8016" RevisionGUID="0528c213-2d8b-4444-b2c3-55944267b683" CreationDate="2018-09-03T23:23:25.243" UserDisplayName="user5681" Text="The original approach of Cook-Torrance was meant for rasterization (it was proposed before the advent of Path Tracing). The original idea of summing weighted diffuse and specular components is not capable of simulating the intricate results that emerge from the interaction between material layers (e.g. refraction, Fresnel for plastics, etc).&#xD;&#xA;&#xD;&#xA;Actually, a better physically based model for material representation would be that of layers. For instance, smooth and rough conductors could be modeled through a unique layer represented by the Cook-Torrance BRDF. Smooth and rough dielectrics could be modeled through a unique BSDF. Plastics, on the other hand, could be modeled through the use two layers: the topmost layer representing a dielectric (a BSDF) and the second layer, underneath the dieletric, representing a diffuse material (e.g. a lambertian or Oren-Nayar BRDF). That two-layer setup for plastics is capable of simulating the Fresnel reflectance of plastics (through the dielectric layer), the plastic color (through the light reflected by the colored diffuse layer underneath the dielectric), the light absorbed by the dielectric (through the implementation of Beer's Law), etc. &#xD;&#xA;&#xD;&#xA;The layer approach approximates quite well what actually happens in real life. I have already written a related answer, with more details, and that may help you (I've included some references in that answer): https://computergraphics.stackexchange.com/a/5761/5681&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21166" PostHistoryTypeId="5" PostId="8016" RevisionGUID="f0dbb9b9-d742-42a3-9dc8-5e5f1047d6db" CreationDate="2018-09-03T23:35:03.833" UserDisplayName="user5681" Comment="added 1071 characters in body" Text="The original approach of Cook-Torrance was meant for rasterization (it was proposed before the advent of Path Tracing). The original idea of summing weighted diffuse and specular components is not capable of simulating the intricate results that emerge from the interaction between material layers (e.g. refraction, Fresnel for plastics, etc).&#xD;&#xA;&#xD;&#xA;Actually, a better physically based model for material representation would be that of layers. For instance, smooth and rough conductors could be modeled through a unique layer represented by the specular term of the Cook-Torrance BRDF. Smooth and rough dielectrics could be modeled through a unique BSDF. Plastics, on the other hand, could be modeled through the use two layers: the topmost layer representing a dielectric (a BSDF) and the second layer, underneath the dieletric, representing a diffuse material (e.g. a lambertian or Oren-Nayar BRDF). That two-layer setup for plastics is capable of simulating the Fresnel reflectance of plastics (through the dielectric layer), the plastic color (through the light reflected by the colored diffuse layer underneath the dielectric), the light absorbed by the dielectric (through the implementation of Beer's Law), etc. &#xD;&#xA;&#xD;&#xA;The layer approach approximates quite well what actually happens in real life. I have already written a related answer, with more details, and that may help you (I've included some references in that answer): https://computergraphics.stackexchange.com/a/5761/5681&#xD;&#xA;&#xD;&#xA;The original Cook-Torrance does not properly conserve energy (I've already posted a question about that [here][1]). In 2007, Walter *et al*. have published the paper [Microfacet Models for Refraction through Rough Surfaces][2], where they propose a Cook-Torrance based model amenable for Path Tracing. &#xD;&#xA;&#xD;&#xA;Regarding layered material, I've implemented the system presented in the paper by Weidlich and Wilkie, &#xD;&#xA;[Arbitrarily layered micro-facet surfaces][3], where a quite general layered material model is presented. After that, more sophisticated layered material models have been proposed. One of them is &#xD;&#xA;[A comprehensive framework for rendering layered materials][4]&#xD;&#xA;, by Wenzel Jakob. There is a new paper (published in 2017, I think), that supports subsurface scattering for top layers (I will add it here when I find it).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [3]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [4]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 4.0" />
  <row Id="21167" PostHistoryTypeId="5" PostId="8016" RevisionGUID="6f16ae5b-82ab-431d-a341-527ec231dd97" CreationDate="2018-09-03T23:41:59.273" UserDisplayName="user5681" Comment="added 12 characters in body" Text="The original approach of Cook-Torrance was meant for rasterization (it was proposed before the advent of Path Tracing). The original idea of summing weighted diffuse and specular components is not capable of simulating the intricate results that emerge from the interaction between material layers (e.g. refraction, Fresnel for plastics, etc).&#xD;&#xA;&#xD;&#xA;Actually, a better physically based model for material representation would be that of layers. For instance, smooth and rough conductors could be modeled through a unique layer represented by the specular term of the Cook-Torrance BRDF. Smooth and rough dielectrics could be modeled through a unique BSDF. Plastics, on the other hand, could be modeled through the use two layers: the topmost layer representing a dielectric (a BSDF) and the second layer, underneath the dieletric, representing a diffuse material (e.g. a lambertian or Oren-Nayar BRDF). That two-layer setup for plastics is capable of simulating the Fresnel reflectance of plastics (through the dielectric layer), the plastic color (through the light reflected by the colored diffuse layer underneath the dielectric), the light absorbed by the dielectric (through the implementation of Beer's Law), etc. &#xD;&#xA;&#xD;&#xA;The layer-based material model approximates quite well what actually happens in real life. I have already written a related answer, with more details, and that may help you (I've included some references in that answer): https://computergraphics.stackexchange.com/a/5761/5681&#xD;&#xA;&#xD;&#xA;The original Cook-Torrance does not properly conserve energy (I've already posted a question about that [here][1]). In 2007, Walter *et al*. have published the paper [Microfacet Models for Refraction through Rough Surfaces][2], where they propose a Cook-Torrance based model amenable for Path Tracing. &#xD;&#xA;&#xD;&#xA;Regarding layered material, I've implemented the system presented in the paper by Weidlich and Wilkie, &#xD;&#xA;[Arbitrarily layered micro-facet surfaces][3], where a quite general layered material model is presented. After that, more sophisticated layered material models have been proposed. One of them is &#xD;&#xA;[A comprehensive framework for rendering layered materials][4]&#xD;&#xA;, by Wenzel Jakob. There is a new paper (published in 2017, I think), that supports subsurface scattering for top layers (I will add it here when I find it).&#xD;&#xA;&#xD;&#xA;I think that PBRT uses layer-based materials too, but I do not know how they have actually implemented it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [3]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [4]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 4.0" />
  <row Id="21168" PostHistoryTypeId="2" PostId="8017" RevisionGUID="2b992549-3710-406e-ae1c-d832218ed8b9" CreationDate="2018-09-04T00:01:22.947" UserId="504" Text="*Background:*  &#xD;&#xA;I found that it is very easy to use a linear depth buffer, using only a slight modification to the canonical vertex transformation. The simplest method is found at the bottom of https://www.mvps.org/directx/articles/linear_z/linearz.htm.&#xD;&#xA;&#xD;&#xA;However, the caveat is that it only works for triangles that don't need to be clipped. &#xD;&#xA;&#xD;&#xA;Because clipping requires linear interpolation to work across all four clip space coordinates, I think it's impossible to work with linear depth, using  only a vertex shader. But the reason for that is all down to Z being divided by W.&#xD;&#xA;&#xD;&#xA;Why is that done? X and Y need to be divided by distance from the camera, but the Z coordinate does not, to fit perfectly into the NDC box." ContentLicense="CC BY-SA 4.0" />
  <row Id="21169" PostHistoryTypeId="1" PostId="8017" RevisionGUID="2b992549-3710-406e-ae1c-d832218ed8b9" CreationDate="2018-09-04T00:01:22.947" UserId="504" Text="Why do GPUs divide clip space Z by W?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21170" PostHistoryTypeId="3" PostId="8017" RevisionGUID="2b992549-3710-406e-ae1c-d832218ed8b9" CreationDate="2018-09-04T00:01:22.947" UserId="504" Text="|projections|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21171" PostHistoryTypeId="2" PostId="8018" RevisionGUID="8e0dd5bf-cb10-40d1-b65b-419700bd20bf" CreationDate="2018-09-04T00:40:34.907" UserId="9298" Text="I have a two different codes with a little difference  &#xD;&#xA;&#xD;&#xA;Case 1. I used a + operator before _myColor.&#xD;&#xA;&#xD;&#xA;` void surf(Input IN, inout SurfaceOutput o) {&#xD;&#xA;       o.Albedo = (tex2D(_myTexture, IN.uv_myTexture) + _myColor).rgb;&#xD;&#xA;	}`&#xD;&#xA;&#xD;&#xA;Case 2. I used a * operator before _myColor.&#xD;&#xA;&#xD;&#xA;` void surf(Input IN, inout SurfaceOutput o) {&#xD;&#xA;       o.Albedo = (tex2D(_myTexture, IN.uv_myTexture) * _myColor).rgb;&#xD;&#xA;	}`&#xD;&#xA;&#xD;&#xA;In first case It gives bright color.&#xD;&#xA;&#xD;&#xA;[![Case 1][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But in second case it gives very dark color. &#xD;&#xA;&#xD;&#xA;[![Case 2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QaAmi.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VzObL.png&#xD;&#xA;&#xD;&#xA;My question is why and how this is happening? " ContentLicense="CC BY-SA 4.0" />
  <row Id="21172" PostHistoryTypeId="1" PostId="8018" RevisionGUID="8e0dd5bf-cb10-40d1-b65b-419700bd20bf" CreationDate="2018-09-04T00:40:34.907" UserId="9298" Text="Difference between using + and * operator after tex2D to add albedo color?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21173" PostHistoryTypeId="3" PostId="8018" RevisionGUID="8e0dd5bf-cb10-40d1-b65b-419700bd20bf" CreationDate="2018-09-04T00:40:34.907" UserId="9298" Text="|shader|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21174" PostHistoryTypeId="2" PostId="8019" RevisionGUID="c716fd8a-54db-4eff-82f0-1ebb368033c1" CreationDate="2018-09-04T01:20:59.480" UserId="196" Text="I think you're seeing cache effects. The GPU will begin vertex processing for each strip in sequential order, and in configuration 1 the GPU will fetch a different chunk of memory for each triangle in the strip (since, as you said, the strips themselves are not contiguous in memory in this configuration).&#xD;&#xA;&#xD;&#xA;If I understand correctly, each entry in the ring buffer you are referring to is a triangle, so you will have at least 3 vertices adjacent to each other (in configuration 1). This has decent [spatial locality][1], but fetching this memory will probably also pull in memory for adjacent vertices, which won't be immediately useful (since it belongs to a different strip).&#xD;&#xA;&#xD;&#xA;In configuration 2, the adjacent vertices *will* be immediately useful, since they're the next vertices the GPU will need to render for the current triangle strip. The result is, probably, less total memory traffic.&#xD;&#xA;&#xD;&#xA;This is a somewhat simplified explanation (for example, it brushes over the parallelism occurring on the GPU), but it seems to match what you're observing. One way to justify the choice of configuration 2 over configuration 1 is that you're making it easier on the GPU at the cost of the CPU—however, the CPU has 1/MAX_AGE of the work to do as the GPU each frame, so optimizing for CPU updating (&quot;a concentrated chunk of memory is updated each frame&quot;) will be less valuable.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Locality_of_reference" ContentLicense="CC BY-SA 4.0" />
  <row Id="21175" PostHistoryTypeId="5" PostId="8017" RevisionGUID="f7125a3a-8d44-4077-b791-3fe9e8131d8e" CreationDate="2018-09-04T01:44:40.520" UserId="504" Comment="added 180 characters in body" Text="*Background:*  &#xD;&#xA;I found that it is very easy to use a linear depth buffer, using only a slight modification to the canonical vertex transformation. The simplest method is found at the bottom of https://www.mvps.org/directx/articles/linear_z/linearz.htm.&#xD;&#xA;&#xD;&#xA;However, the caveat is that it only works for triangles that don't need to be clipped against the near or far planes. (And an alternate solution, of dividing the perspective divide in the vertex shader, will yield a similar problem for the other four frustum planes.)&#xD;&#xA;&#xD;&#xA;Because clipping requires linear interpolation to work across all four clip space coordinates, I think it's impossible to work with linear depth, using  only a vertex shader. But the reason for that is all down to Z being divided by W.&#xD;&#xA;&#xD;&#xA;Why is that done? X and Y need to be divided by distance from the camera, but the Z coordinate does not, to fit perfectly into the NDC box." ContentLicense="CC BY-SA 4.0" />
  <row Id="21176" PostHistoryTypeId="2" PostId="8020" RevisionGUID="7d398b75-1621-48dd-80c1-e0ba79f9f970" CreationDate="2018-09-04T03:11:59.103" UserId="3003" Text="In a shader, colors in the viewable range are assumed to be in the range 0 to 1. If you take a value that's between 0 and 1 and add a positive value to it, it will get brighter. However, if you take a value between 0 and 1 and multiply it by a value between 0 and 1, it will get darker. To understand, think about multiplying 0.5 by 0.5. The result is 0.25.&#xD;&#xA;&#xD;&#xA;More generally, any value between 0 and 1 can be thought of as a percentage. 0.05 = 5%. 0.25  = 25%. So multiply any value between 0 and 1 by a percentage between 0 and 1, and it will be less than the original value. (50% of 50% is 25% in the earlier example.)&#xD;&#xA;&#xD;&#xA;If you have a photo editing application like Photoshop or GIMP, you can see the difference between the 2 by creating 2 layers with image data in them, and setting the blend mode of the top layer to either Add or Multiply. It's particularly revealing if you use a left-to-right gradient of black to white over the same gradient rotated 90°. You'll see how all the values react to the current blend mode." ContentLicense="CC BY-SA 4.0" />
  <row Id="21180" PostHistoryTypeId="50" PostId="6373" RevisionGUID="3e848431-cd8c-4c33-9052-0c326149259a" CreationDate="2018-09-04T05:00:45.353" UserId="-1" />
  <row Id="21181" PostHistoryTypeId="5" PostId="8010" RevisionGUID="3f60bf3f-a5c1-4350-a03b-5fd09b4080fd" CreationDate="2018-09-04T08:33:02.747" UserId="209" Comment="Minor improvements to English" Text="I don't know what Apple have done with Metal per se, but as the iOS devices have PowerVR-derived GPUs, normally I would think that doing as much opaque-only drawing &quot;up front&quot; would usually be beneficial, but *if*, as in your case, only 5% of the screen is covered by opaque geometry, I'm not sure how much the software overhead will affect things.&#xD;&#xA;&#xD;&#xA;&gt; The reason I am unsure is that I know the second you call discard on a fragment you remove the possibility of Metal preforming early depth test which is allegedly quite an optimization. What I dont know is if discards disable early depth test on draw call 1 do they also disable the optimization for draw call 2's geometry?&#xD;&#xA;&#xD;&#xA;With PowerVR devices, a depth test can &quot;always&quot; be done as the first step in the pipeline, so any geometry that was submitted earlier in the scene *can* cull later things prior to fragment shading. &#xD;&#xA;&#xD;&#xA;With alpha-tested (AKA &quot;punch-though&quot;), the Z-test can thus be done against previous geometry, but there may be a cost of then doing the texturing/shading and feeding that back to update the depths for subsequent geometry.&#xD;&#xA;&#xD;&#xA;If you aren't doing alpha-test/discards, and are doing your own sorting, then this feedback is not required (but obviously there may be more shading/texturing work to perform).&#xD;&#xA;&#xD;&#xA;(Such a pity, though, that we removed the OIT feature from the early PowerVR hardware)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;Does the fragment stage happen after each draw calls vertex phase or after all of them?&#xD;&#xA;&#xD;&#xA;I'm not sure what you are asking, but for a given scene, all the vertex shading (across multiple calls) is performed**, the geometry buffered, and only then rendering commences on the entire scene.&#xD;&#xA;&#xD;&#xA;_**There are some caveats here but that probably doesn't affect you_.&#xD;&#xA;&#xD;&#xA;&gt;Do you think I should explore sorting the triangles and using alpha blending on draw call 1? Again this would be a negligible CPU cost would it actually help the GPU? &#xD;&#xA;&#xD;&#xA;Are you asking &quot;should I profile/time the results and see what is best for my use case?&quot;.  Probably &quot;yes&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="21183" PostHistoryTypeId="2" PostId="8022" RevisionGUID="f7f47371-4e3d-4fb8-8aa4-93bb8dd1f5ce" CreationDate="2018-09-04T12:25:06.293" UserId="209" Text="If you are doing a perspective image and your model has implicit intersections, then those intersections will appear in the wrong places. *(I'm currently trying to find an illustration I did ~20 years ago to explain the problem, but had no luck so far)*&#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles which pierce the ground plane and recede into the distance. The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with 1/Z, when the projected vertices have been computed with perspective, then it will look incorrect." ContentLicense="CC BY-SA 4.0" />
  <row Id="21184" PostHistoryTypeId="5" PostId="8022" RevisionGUID="9535a65e-94f3-4b0e-b284-f5ae093c388a" CreationDate="2018-09-04T12:56:31.907" UserId="209" Comment="Added images" Text="If you are doing a perspective image and your model has implicit intersections, then those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles which pierce the ground plane and recede into the distance. The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with 1/Z, when the projected vertices have been computed with perspective, then it will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologies for the non-aesthetic quality of these illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first shows the required rendering effect (Note that the blue &quot;pylons2 go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this is the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc so I've not idea what has happened.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are quite wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21185" PostHistoryTypeId="2" PostId="8023" RevisionGUID="77c4d9d4-4015-4a77-b944-eac5add12681" CreationDate="2018-09-04T13:03:35.783" UserId="6" Text="In addition to the more direct existing answer, there *is* a way to work around this in unextended OpenGL to some degree, feeding from the fact that in contrast to CUDA OpenGL compute shaders are *not* pre-compiled with application build (well, they *can* nowadays, but aren't by default). Instead you *usually* compile your compute shaders at some point during application runtime.&#xD;&#xA;&#xD;&#xA;So a way to achieve a somewhat customizable workgroup size is to use a **macro for it and then redefine this dynamically during application runtime but *before* shader compile time**.&#xD;&#xA;&#xD;&#xA;    layout(local_size_x = BLOCKSIZE) in;&#xD;&#xA;&#xD;&#xA;And in the application all you have to do is prepend a `&quot;#define BLOCKSIZE &lt;whatever&gt;\n&quot;` to the shader source string you feed into `glCompileShader`. Of course in practice you have to care about stuff like the `#version` directive being the first line in a shader. You could as well have the define in the shader code already (maybe with a meaningful default size) and do a text replacement instead. But you get the idea.&#xD;&#xA;&#xD;&#xA;Of course this means **recompiling your compute shader for each and every workgroup size** you're using. It's practically not much different from just having different shaders for each workgroup size. But at least it's a way to dynamically select the workgroup size during runtime while maintaining a single shader source." ContentLicense="CC BY-SA 4.0" />
  <row Id="21186" PostHistoryTypeId="5" PostId="8022" RevisionGUID="92a3f279-1f7a-4680-924a-efb79d2e96fc" CreationDate="2018-09-04T16:09:37.427" UserId="3003" Comment="Fixed a few minor typos" Text="If you are doing a perspective image and your model has implicit intersections, then those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles which pierce the ground plane and recede into the distance. The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with `1/Z`, when the projected vertices have been computed with perspective, then it will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologies for the non-aesthetic quality of these illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first shows the required rendering effect (Note that the blue &quot;pylons&quot; go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this is the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc so I've no idea what has happened.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are quite wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21187" PostHistoryTypeId="2" PostId="8024" RevisionGUID="193081d3-c56c-4252-9f17-387f5bdc3eb0" CreationDate="2018-09-04T16:21:06.593" UserId="3003" Text="Displays are already moving towards wider gamuts. I believe that newer iPhones, for example, are all P3 displays. So there is no doubt that sRGB usage will be replaced by wider gamuts in the future.&#xD;&#xA;&#xD;&#xA;There are really 2 important questions here:&#xD;&#xA;&#xD;&#xA; 1. Which gamuts will people end up using?&#xD;&#xA; 2. When can/should we move our apps to using wider gamuts?&#xD;&#xA;&#xD;&#xA;The answer to the first question will depend on the market. People have been pretty happy with sRGB for a few decades. P3 is better, but most consumers probably can't tell the difference. There are much wider gamuts like ACEScg, Rec. 2020, etc. Will it be affordable to move to those? If it is, will consumers care?&#xD;&#xA;&#xD;&#xA;The answer to the second question depends entirely on what your target audience is using. If you can guarantee they're using devices with P3 displays (say, if you require the iPhone X's IR sensor), then you should move to P3. If your users are high-end users creating output for professional use, it's probably wise to move to P3. If your users need to create content that looks reasonably good on end-user devices like web pages rendered on aging machines, then it is probably a waste of effort to move away from sRGB.&#xD;&#xA;&#xD;&#xA;Note that there is a cost to moving to a wider gamut. You will need to do significantly more work to ensure that all of your processing is done in the right color space because input images to your app will likely come in a variety of gamuts and you now have to convert them all to your working space, process them, and  then convert to the output space. That's not cheap to do and not easy to get right." ContentLicense="CC BY-SA 4.0" />
  <row Id="21188" PostHistoryTypeId="33" PostId="7984" RevisionGUID="27e0f70a-42dc-4a9b-9080-04778bbb296a" CreationDate="2018-09-04T17:18:16.020" UserId="2485" Comment="50" />
  <row Id="21189" PostHistoryTypeId="5" PostId="8013" RevisionGUID="092befec-17a2-4da2-aea1-238dd5680dcb" CreationDate="2018-09-04T18:00:58.423" UserId="6046" Comment="added 227 characters in body" Text="So I am in the midst of writing my own path traced renderer and right now I have only implemented the old Blinn-Phong models where we separately calculated the diffuse and specular components of the material and each object had a specular and a diffuse color. &#xD;&#xA;&#xD;&#xA;Now going towards the more general side I want to be able to render different types of objects wood, polished wood, perfect mirror like reflections etc. However all this information confuses me on how should I implement these BSDFs or in other words how should I choose when to apply a certain BSDF or maybe a combination of two?&#xD;&#xA;&#xD;&#xA;This is usually done using a material approach. The material being diffuse, glossy or perfect specular would define which BSDFs should I use.&#xD;&#xA;&#xD;&#xA;I read PBRT for clues and they break surface reflection into 4 types. Diffuse, Glossy Specular, Specular and retro reflective. Then they implement an `enum` that stores the type corresponding to these reflection.&#xD;&#xA;&#xD;&#xA;The enum has the types&#xD;&#xA;&#xD;&#xA;    BSDF_REFLECTION&#xD;&#xA;    BSDF_TRANSMISSION&#xD;&#xA;    BSDF_DIFFUSE&#xD;&#xA;    BSDF_GLOSSY&#xD;&#xA;    BSDF_SPECULAR&#xD;&#xA;    BSDF_ALL&#xD;&#xA;&#xD;&#xA; 1. The users are supposed to select a bitwise combination of the first two and &#xD;&#xA;    the next 3 ones. Where `BSDF_ALL` is a combination of&#xD;&#xA;    all the flags. This interface seems nice but there is one little&#xD;&#xA;    confusion. If `BSDF_ALL` combines all flags, then this means the&#xD;&#xA;    surface can be `diffuse` and `specular`. However this seems odd, a&#xD;&#xA;    perfectly specular surface can't be diffuse. While `Glossy + Diffuse` make &#xD;&#xA;    sense (polished wood, paint on a rough wall), `diffuse + specular` and &#xD;&#xA;    `glossy + specular` don't make sense to me.&#xD;&#xA;    &#xD;&#xA; &#xD;&#xA; 2. Assuming we have solved the above problem consider an object that is &#xD;&#xA;    glossy+diffuse like an orange or lemon skin. How do we&#xD;&#xA;    calculate the color for this surface? Suppose I am using&#xD;&#xA;    [Oran-Nayar][1] model (ON) for diffuse surfaces and&#xD;&#xA;    [Cook-Torrance][2] (CT) for specular ones. &#xD;&#xA;    &#xD;&#xA;    Should I compute the diffuse component through ON and specular&#xD;&#xA;    through (CT) then add them together? However both of these models&#xD;&#xA;    have their own parameters which define the slope distribution for&#xD;&#xA;    microfacet. For ON that's $\sigma^2$, the variance of the Gaussian&#xD;&#xA;    distribution and for CT that's $m$, which wiki describes as &quot;RMS&#xD;&#xA;    slope of microfacets&quot; (check respective links). Which one of these&#xD;&#xA;    will govern the roughness of the surface?&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA; 3. Moving on further there is a more general question. In the older models such &#xD;&#xA;    as Blinn-Phong we used to have a separate diffuse and specular color. The &#xD;&#xA;    specular color, from what I understand is nothing more than the Fresnel &#xD;&#xA;    Reflectance. This is because Fresnel&#xD;&#xA;    reflectance is dependent on wavelength. In case of Dielectrics this&#xD;&#xA;    isn't discernable but for metals it usually is (gold gives of a&#xD;&#xA;    yellowish tint). Hence for dielectrics the specular color would just&#xD;&#xA;    be the plain old Fresnel reflectance replicated across RGB channels&#xD;&#xA;    while for metals this would be the color of the tint. &#xD;&#xA;    &#xD;&#xA;    The thing that confuses me is the lingering concept of diffuse and&#xD;&#xA;    specular reflectivity. Consider Cook-Torrance's original paper where&#xD;&#xA;    they describe their model as.&#xD;&#xA;    &#xD;&#xA;    $R = dR_d + sR_s$&#xD;&#xA;    &#xD;&#xA;    Where $d$ and $s$ are the coeffecients for diffuse and specular&#xD;&#xA;    reflectivity respectively and they must hold the condition.&#xD;&#xA;    &#xD;&#xA;    $d+s \leq 1$&#xD;&#xA;    &#xD;&#xA;    $R_d$ is any diffuse BRDF (they assume lambertian) while $R_s$ is&#xD;&#xA;    their new proposed BRDF for specular surfaces.&#xD;&#xA;    &#xD;&#xA;    That's where my biggest confusion is. I was thinking the diffuse and&#xD;&#xA;    specular colors as the object's respective reflectivities in each&#xD;&#xA;    channel. The above equation however separates the color from&#xD;&#xA;    reflectivity. **Which concept is used in PBR?**&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Specular_highlight#Cook%E2%80%93Torrance_model" ContentLicense="CC BY-SA 4.0" />
  <row Id="21193" PostHistoryTypeId="5" PostId="8016" RevisionGUID="e74419d2-03c7-4792-ad28-48288ad7b1fc" CreationDate="2018-09-04T18:54:22.293" UserDisplayName="user5681" Comment="added 59 characters in body" Text="Although the specular term of the Cook-Torrance BRDF is widely used in Path Tracing, it was meant initially for rasterization (it was proposed before the advent of Path Tracing). The original idea of summing weighted diffuse and specular components (*i.e.* $R=dR_d+sR_s, d + s \leq 1$) is not capable of representing the complex results that may emerge from the interaction between diffuse and specular material elements (e.g. refraction, Fresnel for plastics, etc).&#xD;&#xA;&#xD;&#xA;Actually, a better physically based model for material representation would be that of layers. For instance, smooth and rough conductors could be modeled through a unique layer represented by the specular term of the Cook-Torrance BRDF. Smooth and rough dielectrics could be modeled through a unique BSDF. Plastics, on the other hand, could be modeled through the use two layers: the topmost layer representing a dielectric (a BSDF) and the second layer, underneath the dieletric, representing a diffuse material (e.g. a lambertian or Oren-Nayar BRDF). That two-layer setup for plastics is capable of simulating the Fresnel reflectance of plastics (through the dielectric layer), the plastic color (through the light reflected by the colored diffuse layer underneath the dielectric), the light absorbed by the dielectric (through the implementation of Beer's Law), etc. &#xD;&#xA;&#xD;&#xA;The layer-based material model approximates quite well what actually happens in real life. I have already written a related answer, with more details, and that may help you (I've included some references in that answer): https://computergraphics.stackexchange.com/a/5761/5681&#xD;&#xA;&#xD;&#xA;The original Cook-Torrance does not properly conserve energy (I've already posted a question about that [here][1]). In 2007, Walter *et al*. have published the paper [Microfacet Models for Refraction through Rough Surfaces][2], where they propose a Cook-Torrance based model amenable for Path Tracing. &#xD;&#xA;&#xD;&#xA;Regarding layered material, I've implemented the system presented in the paper by Weidlich and Wilkie, &#xD;&#xA;[Arbitrarily layered micro-facet surfaces][3], where a quite general layered material model is presented. After that, more sophisticated layered material models have been proposed. One of them is &#xD;&#xA;[A comprehensive framework for rendering layered materials][4]&#xD;&#xA;, by Wenzel Jakob. There is a new paper (published in 2017, I think), that supports subsurface scattering for top layers (I will add it here when I find it).&#xD;&#xA;&#xD;&#xA;I think that PBRT uses layer-based materials too, but I do not know how they have actually implemented it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [3]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [4]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 4.0" />
  <row Id="21194" PostHistoryTypeId="5" PostId="8016" RevisionGUID="acad2025-cd13-4ee3-880b-b39b57719b77" CreationDate="2018-09-04T20:20:28.243" UserDisplayName="user5681" Comment="added 6 characters in body" Text="Although the specular term of the Cook-Torrance BRDF is widely used in Path Tracing, the original BRDF was meant initially for rasterization (it was proposed before the advent of Path Tracing). The idea of summing weighted diffuse and specular components (*i.e.* $R=dR_d+sR_s, d + s \leq 1$) is not capable of representing the complex results that may emerge from the interaction between diffuse and specular material elements (e.g. refraction, Fresnel for plastics, etc).&#xD;&#xA;&#xD;&#xA;Actually, a better physically based model for material representation would be that of layers. For instance, smooth and rough conductors could be modeled through a unique layer represented by the specular term of the Cook-Torrance BRDF. Smooth and rough dielectrics could be modeled through a unique BSDF. Plastics, on the other hand, could be modeled through the use two layers: the topmost layer representing a dielectric (a BSDF) and the second layer, underneath the dieletric, representing a diffuse material (e.g. a lambertian or Oren-Nayar BRDF). That two-layer setup for plastics is capable of simulating the Fresnel reflectance of plastics (through the dielectric layer), the plastic color (through the light reflected by the colored diffuse layer underneath the dielectric), the light absorbed by the dielectric (through the implementation of Beer's Law), etc. &#xD;&#xA;&#xD;&#xA;The layer-based material model approximates quite well what actually happens in real life. I have already written a related answer, with more details, and that may help you (I've included some references in that answer): https://computergraphics.stackexchange.com/a/5761/5681&#xD;&#xA;&#xD;&#xA;The original Cook-Torrance does not properly conserve energy (I've already posted a question about that [here][1]). In 2007, Walter *et al*. have published the paper [Microfacet Models for Refraction through Rough Surfaces][2], where they propose a Cook-Torrance based model amenable for Path Tracing. &#xD;&#xA;&#xD;&#xA;Regarding layered material, I've implemented the system presented in the paper by Weidlich and Wilkie, &#xD;&#xA;[Arbitrarily layered micro-facet surfaces][3], where a quite general layered material model is presented. After that, more sophisticated layered material models have been proposed. One of them is &#xD;&#xA;[A comprehensive framework for rendering layered materials][4]&#xD;&#xA;, by Wenzel Jakob. There is a new paper (published in 2017, I think), that supports subsurface scattering for top layers (I will add it here when I find it).&#xD;&#xA;&#xD;&#xA;I think that PBRT uses layer-based materials too, but I do not know how they have actually implemented it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4394/5681&#xD;&#xA;  [2]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html&#xD;&#xA;  [3]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [4]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 4.0" />
  <row Id="21198" PostHistoryTypeId="2" PostId="8027" RevisionGUID="3d6d6250-4a47-4505-87bb-dfb726368e94" CreationDate="2018-09-04T23:46:36.673" UserId="9258" Text="&gt; Is there any 3D software that supports rendering an artificial scene to a light field image?&#xD;&#xA;&#xD;&#xA;I took a look at Myst and [realMyst][1], and found this YouTube video: &quot;[LightField synthesis &amp; realtime render in Unity - sneak preview (raw footage)][2]&quot; with accompanying background [introductory information from Frooxius on Reddit][3]. You can see the pipeline he used to convert lightfields, though copying it may be a challenge. He has obtained pretty good results.&#xD;&#xA;&#xD;&#xA;So the answer is yes.&#xD;&#xA;&#xD;&#xA;&gt; I guess animations would be out almost of the question. It should at least in theory be easier to incorporate animations in cgi-light fields than in real photos.&#xD;&#xA;&#xD;&#xA;It's an interesting experiment but the scene is baked, adding characters or new objects will kind of look like cutting out one photograph and pasting onto another - thus what you hoped to gain in speed is lost trying to smooth the two scenes together.&#xD;&#xA;&#xD;&#xA;To walk into a scene and see a moving object you essentially need to create a dynamic 'lightfield movie' so the moving object can move normally and then you simply walk/look around the dynamic lightfield. That will be somewhat computationally intensive but most of all it will take a lot of memory.&#xD;&#xA;&#xD;&#xA;Check out Frooxius' video and let me know if that's the *look* you were hoping for.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/m2kKsFjZwx8?t=5m16s&#xD;&#xA;  [2]: https://youtu.be/e18brgSS_F0&#xD;&#xA;  [3]: https://www.reddit.com/r/oculus/comments/2qjqr3/i_got_lightfield_synthesis_and_rendering_working/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21199" PostHistoryTypeId="50" PostId="5697" RevisionGUID="3dd896cb-383a-40da-9e8d-b7a683eab877" CreationDate="2018-09-05T00:01:36.400" UserId="-1" />
  <row Id="21200" PostHistoryTypeId="5" PostId="8017" RevisionGUID="352cc7e2-d8c1-48f0-a072-b8abc2423dd6" CreationDate="2018-09-05T02:48:00.790" UserId="504" Comment="added 2 characters in body" Text="*Background:*  &#xD;&#xA;I found that it is very easy to use a linear depth buffer, using only a slight modification to the canonical vertex transformation. The simplest method is found at the bottom of https://www.mvps.org/directx/articles/linear_z/linearz.htm.&#xD;&#xA;&#xD;&#xA;However, the caveat is that it only works for triangles that don't need to be clipped against the near or far planes. (And an alternate solution, of performing the perspective divide in the vertex shader, will yield a similar problem for the other four frustum planes.)&#xD;&#xA;&#xD;&#xA;Because clipping requires linear interpolation to work across all four clip space coordinates, I think it's impossible to work with linear depth, using  only a vertex shader. But the reason for that is all down to Z being divided by W.&#xD;&#xA;&#xD;&#xA;Why is that done? X and Y need to be divided by distance from the camera, but the Z coordinate does not, to fit perfectly into the NDC box." ContentLicense="CC BY-SA 4.0" />
  <row Id="21202" PostHistoryTypeId="6" PostId="7976" RevisionGUID="ae697d20-1c3d-43a7-aae6-0443551fd542" CreationDate="2018-09-05T05:56:56.113" UserId="2287" Comment="glsl tag added for syntax highlighting" Text="|glsl|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21203" PostHistoryTypeId="24" PostId="7976" RevisionGUID="ae697d20-1c3d-43a7-aae6-0443551fd542" CreationDate="2018-09-05T05:56:56.113" Comment="Proposed by 2287 approved by 209, 2041 edit id of 435" ContentLicense="CC BY-SA 4.0" />
  <row Id="21204" PostHistoryTypeId="10" PostId="8007" RevisionGUID="6d787af6-57b2-48f8-a659-c35087fa7016" CreationDate="2018-09-05T05:58:12.567" UserId="2041" Comment="105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="21205" PostHistoryTypeId="2" PostId="8028" RevisionGUID="5c362877-38d9-4a75-934c-20de802ce914" CreationDate="2018-09-05T07:35:56.257" UserId="9258" Text="In the paper you referenced $f$ refers to the fraction of water covered by foam that modifies optical properties on the water’s surface. It is explained on page 256 in: &quot;[Oceanic Whitecaps: Their Role in Air Sea Exchange Processes][1]&quot; (1986), by E. Monahan and G. MacNiocaill.&#xD;&#xA;&#xD;&#xA;&gt; How could I generate the waves for a water body with whitecaps &amp; foam and variable intensity of the waves? &#xD;&#xA;&#xD;&#xA;There are more techniques for rendering oceans than there are oceans to render. Some are based on speed (with reasonable results) and some are based on accuracy. On the fourth page of &quot;[Deep Water Animation and Rendering][2]&quot; is a discussion of rendering foam, with the prior pages covering other calculations.&#xD;&#xA;&#xD;&#xA;Maya has a number of preset demos that can be altered or you can start from scratch. See this YouTube tutorial &quot;[Crafting the Wave: How to Render an Ocean in Maya][3]&quot;.&#xD;&#xA;&#xD;&#xA;Which of those references is more applicable depends on: if you simply want to understand more about it, if you are writing your own software, or if you want to render realistic oceans without necessarily knowing all the calculations behind it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.ca/books?id=WqDsCAAAQBAJ&amp;pg=PA256&amp;source=gbs_toc_r&amp;cad=4#v=onepage&amp;q=foam&amp;f=false&#xD;&#xA;  [2]: https://www.gamasutra.com/view/feature/131445/deep_water_animation_and_rendering.php?page=5&#xD;&#xA;  [3]: https://youtu.be/GixnCnb2mJI" ContentLicense="CC BY-SA 4.0" />
  <row Id="21207" PostHistoryTypeId="5" PostId="8006" RevisionGUID="7a78e6c5-2778-4e0e-84c4-188530a491cd" CreationDate="2018-09-05T10:48:51.963" UserId="9293" Comment="added 5 characters in body" Text="Is there any 3d software that supports rendering an artificial scene to a light field image?&#xD;&#xA;&#xD;&#xA;With that I mean an image capturing light from more than one point in a scene, more lika a spherical volume of evenly distributed points.&#xD;&#xA;&#xD;&#xA;There is [research][1] being done by for instance P Debevec for Google VR that does this for physical scenes with an expensive camera rig. I would like to be able to render the same output but from an artificial scene, in for instance 3dsmax. And then preferably use this in for instance Unity 3D.&#xD;&#xA;&#xD;&#xA;Would be awesome for a Myst-like game with high fidelity ray traced graphics instead of low-poly rasterized real time graphics. But I guess animations would be almost out of the question. It should at least in theory be easier to incorporate animations in cgi-light fields than in real photos.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blog.google/products/google-ar-vr/experimenting-light-fields/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21208" PostHistoryTypeId="5" PostId="8022" RevisionGUID="8562e446-8e1c-4251-a46e-3dfd63d3a8f2" CreationDate="2018-09-05T12:34:20.117" UserId="209" Comment="Addressed question in comment" Text="If you are doing a perspective image and your model has implicit intersections, then those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles which pierce the ground plane and recede into the distance. The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with `1/Z`, when the projected vertices have been computed with perspective, then it will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologies for the non-aesthetic quality of these illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first shows the required rendering effect (Note that the blue &quot;pylons&quot; go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this is the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc so I've no idea what has happened with the scaling.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are quite wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;Re your later comment:&#xD;&#xA;&gt; “if those are not interpolated with 1/Z” that I don’t understand. What interpolation is that?&#xD;&#xA;&#xD;&#xA;The first thing to note is that, with a standard perspective projection, straight lines in world space remain straight lines in perspective space. Distances/lengths, however, are not preserved.&#xD;&#xA;&#xD;&#xA;For simplicity, let us assume a trivial perspective transform is used to project the vertices, i.e.&#xD;&#xA;$$X_{Screen} = \frac{X_{World}}{Z_{World}}$$&#xD;&#xA;$$Y_{Screen} = \frac{Y_{World}}{Z_{World}}$$&#xD;&#xA;We *should* also compute a reciprocal screen-space depth, e.g. $$Z_{Screen} = \frac{1}{Z_{World}}$$ but a linear Z would in the depth buffer would, to me, imply something like: $$Z_{Screen} = scale*Z_{World}$$ *(We can assume here that scale=1)*&#xD;&#xA;&#xD;&#xA;Let's assume we have a line with world space end points$$&#xD;&#xA;  \begin{matrix} \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and &#xD;&#xA;   \begin{bmatrix}&#xD;&#xA;    200 \\&#xD;&#xA;    0   \\&#xD;&#xA;    10  \\&#xD;&#xA;    \end{bmatrix}\\&#xD;&#xA;  \end{matrix}&#xD;&#xA;$$&#xD;&#xA;With the perspective mapping these map to screen space coordinates&#xD;&#xA; $$ \begin{matrix}   \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and \begin{bmatrix}&#xD;&#xA;    20 \\&#xD;&#xA;    0  \\&#xD;&#xA;    0.1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; \end{matrix}$$&#xD;&#xA;&#xD;&#xA;The rendering system/hardware will linearly interpolate the screen space z, so at the 1/2 way point of the line, as it appears on-screen, i.e. at pixel (10, 0), we would get a projected (inverse) Z value of 0.55, which corresponds to to a world space Z value value of ~1.818. Given the starting and end Z values, this is about 20% along the length of the line.&#xD;&#xA;&#xD;&#xA;If instead, we tried to interpolate using the original Z values, we'd end up with Z corresponding to a world space value of 5.5. As long as nothing intersects, you might be ok (I've not thought about it too thoroughly) but anything with implicit intersections *will* be incorrect.&#xD;&#xA;&#xD;&#xA;What I haven't mentioned is that once you introduce perspective correct texturing (or even perspective correct shading), you must do per-pixel interpolation of 1/w and, additionally, also compute, per pixel, the reciprocal of that interpolated value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21209" PostHistoryTypeId="2" PostId="8029" RevisionGUID="fc043c6a-7c21-4dfa-9320-793dcfedba78" CreationDate="2018-09-05T13:43:58.493" UserId="56" Text="Let's say I have a cube map that has a resolution of 256x256 for each face and I want to generate mip maps for it using a box filter.&#xD;&#xA;&#xD;&#xA;It's tempting to just mip each face individually, cutting the resolution of each face in half for each mip, by averaging each 2x2 group of pixels.&#xD;&#xA;&#xD;&#xA;Doing this, information never crosses the boundary of a cube map face though, which feels like it might be incorrect.&#xD;&#xA;&#xD;&#xA;What is the correct way to generate mips for a cube map?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21210" PostHistoryTypeId="1" PostId="8029" RevisionGUID="fc043c6a-7c21-4dfa-9320-793dcfedba78" CreationDate="2018-09-05T13:43:58.493" UserId="56" Text="Generating Mip Maps From A cube Map" ContentLicense="CC BY-SA 4.0" />
  <row Id="21211" PostHistoryTypeId="3" PostId="8029" RevisionGUID="fc043c6a-7c21-4dfa-9320-793dcfedba78" CreationDate="2018-09-05T13:43:58.493" UserId="56" Text="|texture|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21212" PostHistoryTypeId="4" PostId="8029" RevisionGUID="64e647e2-6309-4d07-af78-0aba26c2d25e" CreationDate="2018-09-05T13:52:07.010" UserId="56" Comment="edited title" Text="Generating Mip Maps For A Cube Map" ContentLicense="CC BY-SA 4.0" />
  <row Id="21213" PostHistoryTypeId="2" PostId="8030" RevisionGUID="dbdb08b3-6a07-472c-add0-6275f57b872c" CreationDate="2018-09-05T13:58:46.110" UserId="9157" Text="So I have a framebuffer image which later acts as input to a compute shader, and some frames there is geometry drawn to the framebuffer, but some frames this is not necessary.&#xD;&#xA;&#xD;&#xA;The thing is, in my current process, when I don't draw anything to that framebuffer, the image contents are undefined which leads to incorrect output of my compute shader.  So on frames where there is no geometry drawn, I would like to simply clear the framebuffer.&#xD;&#xA;&#xD;&#xA;In OpenGL this would be easy: `glClearColor(...)` but so far I have not been able to get it working on Vulkan.&#xD;&#xA;&#xD;&#xA;I have tried just doing an empty renderpass: i.e: `vkCmdBeginRenderPass`/`vkCmdEndRenderpass` with the correct clear values defined in the `VkRenderPassBeginInfo` struct.&#xD;&#xA;&#xD;&#xA;I have also tried doing a renderpass with only `vkCmdClearAttachments` between the bein/end commands.&#xD;&#xA;&#xD;&#xA;So far I haven't had any luck.  What's the best way to accomplish this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21214" PostHistoryTypeId="1" PostId="8030" RevisionGUID="dbdb08b3-6a07-472c-add0-6275f57b872c" CreationDate="2018-09-05T13:58:46.110" UserId="9157" Text="Best way to clear a framebuffer image without drawing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21215" PostHistoryTypeId="3" PostId="8030" RevisionGUID="dbdb08b3-6a07-472c-add0-6275f57b872c" CreationDate="2018-09-05T13:58:46.110" UserId="9157" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21216" PostHistoryTypeId="2" PostId="8031" RevisionGUID="44da8ec3-110a-4ea9-beb5-2a33687d96c2" CreationDate="2018-09-05T14:23:46.173" UserId="137" Text="You are looking for [`vkCmdClearColorImage`,][1] &#xD;&#xA;&#xD;&#xA;It does exactly what it says on the tin, it clears an image to a specified color. This command uses the Transfer stage as far as barriers are concerned.&#xD;&#xA;&#xD;&#xA;There is also a `vkCmdClearDepthStencilImage` if you need it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#clears-outside" ContentLicense="CC BY-SA 4.0" />
  <row Id="21218" PostHistoryTypeId="5" PostId="8031" RevisionGUID="237a9cbd-e6ec-4b9a-b845-94a7f0631239" CreationDate="2018-09-05T16:13:01.913" UserId="137" Comment="added 68 characters in body" Text="You are looking for [`vkCmdClearColorImage`,][1] &#xD;&#xA;&#xD;&#xA;It does exactly what it says on the tin, it clears an image to a specified color. This command uses the Transfer stage as far as barriers are concerned. You will need to add one between the clear and the `vkCmdDispatch`.&#xD;&#xA;&#xD;&#xA;There is also a `vkCmdClearDepthStencilImage` if you need it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#clears-outside" ContentLicense="CC BY-SA 4.0" />
  <row Id="21219" PostHistoryTypeId="2" PostId="8032" RevisionGUID="b4e5eaea-0280-4585-8a19-54b0936aad57" CreationDate="2018-09-05T16:29:06.800" UserId="9254" Text="In Chapter 14.5.3 of *Physically Based Rendering - From Theory to Implementation* (3rd edition), the authors claim that a probability density $p_\omega$ according to solid angle can be converted to a density $p_A$ according to area by $$p_A=p_\omega\frac{\left|\cos\theta_i\right|}{\left|p_i-p_{i+1}\right|^2},\tag1$$ where $\theta_i$ is the angle between the surface normal at $p_{i+1}$ and the vector to $p_i$.&#xD;&#xA;&#xD;&#xA;&gt; The problem is: $(1)$ doesn't make sense. If $p_\omega$ is a density with respect to the surface measure on the upper unit hemisphere $\Omega_{p_i}$ over $p_i$, then $p_\omega$ is by definition a function $\Omega_{p_i}\to[0,\infty]$. Analogously, if $p_A$ is supposed to be a density with respect to the surface measure on the manifold $M$ build by all surfaces in the scene, then $p_A$ is by definition a function $M\to[0,\infty]$.&#xD;&#xA;&gt;&#xD;&#xA;&gt; So, there's at least an argument transformation missing. I would really appreciate, if anybody could clarify." ContentLicense="CC BY-SA 4.0" />
  <row Id="21220" PostHistoryTypeId="1" PostId="8032" RevisionGUID="b4e5eaea-0280-4585-8a19-54b0936aad57" CreationDate="2018-09-05T16:29:06.800" UserId="9254" Text="How can we convert a probability density according to solid angle to a density according to area?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21221" PostHistoryTypeId="3" PostId="8032" RevisionGUID="b4e5eaea-0280-4585-8a19-54b0936aad57" CreationDate="2018-09-05T16:29:06.800" UserId="9254" Text="|raytracing|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21222" PostHistoryTypeId="5" PostId="7984" RevisionGUID="f67a77b1-cc4e-4345-9de8-3f638e5d0e52" CreationDate="2018-09-05T18:15:16.210" UserId="2485" Comment="added 338 characters in body" Text="I am generating plane vertices where the y values are generated by a heightmap (noise) algorithm. This is how I produce my vertex array:&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; noise.length; row++) {&#xD;&#xA;        for (let col = 0; col &lt; noise[0].length; col++) {&#xD;&#xA;            color = noise[row][col];&#xD;&#xA;            positions.push(row, color, col);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After that I generate index values like this (I know that there is a lot of optimization that can be done here):&#xD;&#xA;&#xD;&#xA;    const height = noise.length + 1;&#xD;&#xA;    const width = noise[0].length + 1;&#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; height - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            if (row === height - 2) break;&#xD;&#xA;            for (let col = 0; col &lt; width - 1; col++) {&#xD;&#xA;                indices.push(col + row * (width));&#xD;&#xA;                indices.push(col - 1 + (row + 1) * (width));&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = width - 2; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col - 2 + (row + 1) * (width));&#xD;&#xA;                indices.push(col - 2 + row * (width));&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    indices.pop();&#xD;&#xA;&#xD;&#xA;Finally I draw the plane using:&#xD;&#xA;&#xD;&#xA; `gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);`&#xD;&#xA;&#xD;&#xA;So if I use `POINTS` as mode, the plane seem to look as it should:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Whereas if I am using `TRINGLE_STRIP` the result looks wrong:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;First I thought wrong indices might be the reason but then I checked by scaling to a 3x3 grid/plane and the vertex and index output looked as I would have expected:&#xD;&#xA;&#xD;&#xA;Vertices:&#xD;&#xA;&#xD;&#xA;    [-1, -43.89, -1, &#xD;&#xA;    -1,  -82.27,  0, &#xD;&#xA;    -1,  -23.06,  1, &#xD;&#xA;     0,  -43.43, -1, &#xD;&#xA;     0,  -54.85,  0, &#xD;&#xA;     0,  -66.27,  1, &#xD;&#xA;     1,  -61.89, -1, &#xD;&#xA;     1,  -27.43,  0, &#xD;&#xA;     1,  -59.89,  1]&#xD;&#xA;&#xD;&#xA;**Note:** &#xD;&#xA;&#xD;&#xA;&gt; The vertices might not exactly correspond to what you would have&#xD;&#xA;&gt; expected from above loop. That is because I am centering the `mesh`&#xD;&#xA;&gt; around origin after the loop.&#xD;&#xA;&#xD;&#xA;Indices:&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So my guess is that the problem is that I am pushing my triangles counterclockwise, that is why I tried to enable culling and depth testing but that did not help either:&#xD;&#xA;&#xD;&#xA;    gl.enable(gl.DEPTH_TEST);&#xD;&#xA;    gl.enable(gl.CULL_FACE);&#xD;&#xA;    gl.cullFace(gl.FRONT);&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Any guess what might be the reason for wrong `TRIANGLE_STRIP` rendering?&#xD;&#xA;&#xD;&#xA;**Update 1:**&#xD;&#xA;&#xD;&#xA;According to @PaulHK's recommendation I changed my index creation loop to insert the last index of a single strip twice. &#xD;&#xA;&#xD;&#xA;    for (let row = 0; row &lt; rows - 1; row++) {&#xD;&#xA;        if (row % 2 === 0) {&#xD;&#xA;            for (let col = 0; col &lt; cols; col++) {&#xD;&#xA;                indices.push(col + row * cols);&#xD;&#xA;                indices.push(col + (row + 1) * cols);&#xD;&#xA;            }&#xD;&#xA;        } else {&#xD;&#xA;            for (let col = cols - 1; col &gt;= 0; col--) {&#xD;&#xA;                indices.push(col + (row) * cols);&#xD;&#xA;                indices.push(col + (row + 1) * cols);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For a 3x3 grid this produces:&#xD;&#xA;&#xD;&#xA;**Vertices:**&#xD;&#xA;&#xD;&#xA;    [-1, -9.6, -1,&#xD;&#xA;     -1, -64.6, 0,&#xD;&#xA;     -1, -11.1, 1,&#xD;&#xA;     0, -38.8, -1,&#xD;&#xA;     0, -32.8, 0,&#xD;&#xA;     0, -26.8, 1,&#xD;&#xA;     1, -37.0, -1,&#xD;&#xA;     1, -1, 0,&#xD;&#xA;     1, -47.5, 1]&#xD;&#xA;&#xD;&#xA;**Indices:**&#xD;&#xA;&#xD;&#xA;    [0, 3, 1, 4, 2, 5, 5, 8, 4, 7, 3, 6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Unfortunately the rendered object still looks the same.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Update 2:**&#xD;&#xA;&#xD;&#xA;I use the Diamond-square algorithm to generate the mesh. This requires a grid of size `(2^n) + 1`.&#xD;&#xA;I.e.:&#xD;&#xA;&#xD;&#xA;&gt; 2, 3, 5, 9, 17, 33, 65, 129, 257, 513 ...&#xD;&#xA;&#xD;&#xA;Maybe it's just a coincidence but it seems to me that the grid can be displayed correctly for sizes `3 - 129` with the procedure from **Update 1**. For a size of 257 and above the mesh has errors.&#xD;&#xA;&#xD;&#xA;**3x3 looks fine:**&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**129x129 looks fine:**&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**257x257 seems wrong:**&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JVCye.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PbGXw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/IhodK.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/KQNSfm.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/kK8wom.gif&#xD;&#xA;  [6]: https://i.stack.imgur.com/cRGdom.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="21223" PostHistoryTypeId="50" PostId="7897" RevisionGUID="fd404c78-ae09-4c50-90ce-653521cb7def" CreationDate="2018-09-05T20:01:29.187" UserId="-1" />
  <row Id="21224" PostHistoryTypeId="2" PostId="8033" RevisionGUID="78037f8d-2420-4ef7-8423-ab5c7376a700" CreationDate="2018-09-05T21:16:50.217" UserId="9307" Text="I made an audio visualizer using Unity3D (you can see it [here][1]) but I am not satisfied on the video quality, as the compression destroys the graphics. I recorded the screen during a real-time rendering. I tried many screen recorders, but always the same disappointment. &#xD;&#xA;&#xD;&#xA;I want to try another approach, using non real-time rendering. I know Unity is made for real time rendering, but do you know if such a thing is possible ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=s8ORkq8ZR3Q &quot;here&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21225" PostHistoryTypeId="1" PostId="8033" RevisionGUID="78037f8d-2420-4ef7-8423-ab5c7376a700" CreationDate="2018-09-05T21:16:50.217" UserId="9307" Text="Non real-time rendering on Unity3D" ContentLicense="CC BY-SA 4.0" />
  <row Id="21226" PostHistoryTypeId="3" PostId="8033" RevisionGUID="78037f8d-2420-4ef7-8423-ab5c7376a700" CreationDate="2018-09-05T21:16:50.217" UserId="9307" Text="|rendering|unity|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21227" PostHistoryTypeId="5" PostId="8027" RevisionGUID="ca65f9aa-61cb-47db-8fea-eff76f1245df" CreationDate="2018-09-06T09:08:10.780" UserId="9258" Comment="Added link to OTOY's Octane." Text="&gt; Is there any 3D software that supports rendering an artificial scene to a light field image?&#xD;&#xA;&#xD;&#xA;I took a look at Myst and [realMyst][1], and found this YouTube video: &quot;[LightField synthesis &amp; realtime render in Unity - sneak preview (raw footage)][2]&quot; with accompanying background [introductory information from Frooxius on Reddit][3]. You can see the pipeline he used to convert lightfields, though copying it may be a challenge. He has obtained pretty good results.&#xD;&#xA;&#xD;&#xA;So the answer is yes.&#xD;&#xA;&#xD;&#xA;&gt; I guess animations would be out almost of the question. It should at least in theory be easier to incorporate animations in cgi-light fields than in real photos.&#xD;&#xA;&#xD;&#xA;It's an interesting experiment but the scene is baked, adding characters or new objects will kind of look like cutting out one photograph and pasting onto another - thus what you hoped to gain in speed is lost trying to smooth the two scenes together.&#xD;&#xA;&#xD;&#xA;To walk into a scene and see a moving object you essentially need to create a dynamic 'lightfield movie' so the moving object can move normally and then you simply walk/look around the dynamic lightfield. That will be somewhat computationally intensive but most of all it will take a lot of memory.&#xD;&#xA;&#xD;&#xA;Check out Frooxius' video and let me know if that's the *look* you were hoping for.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This webpage: &quot;[Light fields – the future of VR-AR-MR][4]&quot; by Mike Seymour (May 26, 2015) says:&#xD;&#xA;&#xD;&#xA;&gt; &quot;The Octane renderer has plugins for a range of products from 3DsMax to Maya and even Nuke.&quot;.&#xD;&#xA;&#xD;&#xA;There's mention of OTOY and on their website the latest announced is: &quot;[OTOY and Epic announce OctaneRender® 2019 for UnrealEngine 4][5]&quot;, their [DEMO version][6] is free, the least expensive paid version is U$400.&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/m2kKsFjZwx8?t=5m16s&#xD;&#xA;  [2]: https://youtu.be/e18brgSS_F0&#xD;&#xA;  [3]: https://www.reddit.com/r/oculus/comments/2qjqr3/i_got_lightfield_synthesis_and_rendering_working/&#xD;&#xA;  [4]: https://www.fxguide.com/featured/light-fields-the-future-of-vr-ar-mr/&#xD;&#xA;  [5]: https://home.otoy.com/unreal-engine-announcement-siggraph/&#xD;&#xA;  [6]: https://home.otoy.com/render/octane-render/demo/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21228" PostHistoryTypeId="2" PostId="8034" RevisionGUID="a8b48371-9c49-4546-ae70-8fae7bdbc5c8" CreationDate="2018-09-06T09:43:28.607" UserId="9309" Text="I have created a quite large point cloud with about 800M RGB points. The exported .ply file is about 12GB large.&#xD;&#xA;The commercial software I used to create it can render the cloud very fluently on my Ryzen 1800X/64GB/Geforce 1080Ti.&#xD;&#xA;&#xD;&#xA;Now, I would like to work with this point cloud - programmatically put trajectories into it, combine multiple clouds, have more control over the point size ...&#xD;&#xA;Expectedly, using PyntCloud in a Jupyter Notebook failed miserably :)&#xD;&#xA;&#xD;&#xA;Before I start learning something like Unity, are there any better suggestions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21229" PostHistoryTypeId="1" PostId="8034" RevisionGUID="a8b48371-9c49-4546-ae70-8fae7bdbc5c8" CreationDate="2018-09-06T09:43:28.607" UserId="9309" Text="How to visualize and programmatically work with huge point cloud" ContentLicense="CC BY-SA 4.0" />
  <row Id="21230" PostHistoryTypeId="3" PostId="8034" RevisionGUID="a8b48371-9c49-4546-ae70-8fae7bdbc5c8" CreationDate="2018-09-06T09:43:28.607" UserId="9309" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21231" PostHistoryTypeId="5" PostId="8034" RevisionGUID="72817379-dd46-4bb9-aa6d-0e8b6bf3af3c" CreationDate="2018-09-06T09:48:46.020" UserId="9309" Comment="edited body" Text="I have created a quite large point cloud with about 800M RGB points. The exported .ply file is about 12GB large.&#xD;&#xA;The commercial software I used to create it can render the cloud very smoothly on my Ryzen 1800X/64GB/Geforce 1080Ti.&#xD;&#xA;&#xD;&#xA;Now, I would like to work with this point cloud - programmatically put trajectories into it, combine multiple clouds, have more control over the point size ...&#xD;&#xA;Expectedly, using PyntCloud in a Jupyter Notebook failed miserably :)&#xD;&#xA;&#xD;&#xA;Before I start learning something like Unity, are there any better suggestions? Potree maybe?&#xD;&#xA;Due to my lack of experience, I cannot judge yet where I would have which possibilities for working with the data." ContentLicense="CC BY-SA 4.0" />
  <row Id="21232" PostHistoryTypeId="50" PostId="7904" RevisionGUID="a205c339-27fc-4bf6-91d8-4c93850d610f" CreationDate="2018-09-06T15:01:49.807" UserId="-1" />
  <row Id="21236" PostHistoryTypeId="5" PostId="8022" RevisionGUID="52f79926-85a6-4cc2-82ba-2535e133a57b" CreationDate="2018-09-07T08:06:47.043" UserId="209" Comment="minor additional note for clarity" Text="If you are doing a perspective image and your model has implicit intersections then, if you use &quot;linear Z&quot;, those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles which pierce the ground plane and recede into the distance. The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with `1/Z`, when the projected vertices have been computed with perspective, then it will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologies for the non-aesthetic quality of these illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first shows the required rendering effect (Note that the blue &quot;pylons&quot; go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this is the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc so I've no idea what has happened with the scaling.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are quite wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;Re your later comment:&#xD;&#xA;&gt; “if those are not interpolated with 1/Z” that I don’t understand. What interpolation is that?&#xD;&#xA;&#xD;&#xA;The first thing to note is that, with a standard perspective projection, straight lines in world space remain straight lines in perspective space. Distances/lengths, however, are not preserved.&#xD;&#xA;&#xD;&#xA;For simplicity, let us assume a trivial perspective transform is used to project the vertices, i.e.&#xD;&#xA;$$X_{Screen} = \frac{X_{World}}{Z_{World}}$$&#xD;&#xA;$$Y_{Screen} = \frac{Y_{World}}{Z_{World}}$$&#xD;&#xA;We *should* also compute a reciprocal screen-space depth, e.g. $$Z_{Screen} = \frac{1}{Z_{World}}$$ but a linear Z would in the depth buffer would, to me, imply something like: $$Z_{Screen} = scale*Z_{World}$$ *(We can assume here that scale=1)*&#xD;&#xA;&#xD;&#xA;Let's assume we have a line with world space end points$$&#xD;&#xA;  \begin{matrix} \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and &#xD;&#xA;   \begin{bmatrix}&#xD;&#xA;    200 \\&#xD;&#xA;    0   \\&#xD;&#xA;    10  \\&#xD;&#xA;    \end{bmatrix}\\&#xD;&#xA;  \end{matrix}&#xD;&#xA;$$&#xD;&#xA;With the perspective mapping these map to screen space coordinates&#xD;&#xA; $$ \begin{matrix}   \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and \begin{bmatrix}&#xD;&#xA;    20 \\&#xD;&#xA;    0  \\&#xD;&#xA;    0.1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; \end{matrix}$$&#xD;&#xA;&#xD;&#xA;The rendering system/hardware will linearly interpolate the screen space z, so at the 1/2 way point of the line, as it appears on-screen, i.e. at pixel (10, 0), we would get a projected (inverse) Z value of 0.55, which corresponds to to a world space Z value value of ~1.818. Given the starting and end Z values, this is about 20% along the length of the line.&#xD;&#xA;&#xD;&#xA;If instead, we tried to interpolate using the original Z values, we'd end up with Z corresponding to a world space value of 5.5. As long as nothing intersects, you might be ok (I've not thought about it too thoroughly) but anything with implicit intersections *will* be incorrect.&#xD;&#xA;&#xD;&#xA;What I haven't mentioned is that once you introduce perspective correct texturing (or even perspective correct shading), you must do per-pixel interpolation of 1/w and, additionally, also compute, per pixel, the reciprocal of that interpolated value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21237" PostHistoryTypeId="2" PostId="8036" RevisionGUID="62eebcfc-8657-43fa-9a73-32a78533ac48" CreationDate="2018-09-07T08:20:45.620" UserId="2041" Text="Yes, there's a better approach than using a screen recorder. You can capture frames directly inside Unity, using [`ScreenCapture.CaptureScreenshot`](https://docs.unity3d.com/ScriptReference/ScreenCapture.CaptureScreenshot.html). There's a choice of formats to save as, and you can use PNG so that, when you later assemble the frames into a video (using ffmpeg or another tool), you have full control over how much compression to use.&#xD;&#xA;&#xD;&#xA;This function is very slow, because it reads back the framebuffer, encodes the image, and writes it to disk, all in the main thread. You may want to use it in combination with setting the [`Time.captureFramerate`](https://docs.unity3d.com/ScriptReference/Time-captureFramerate.html) value. This setting lets you slow down Unity by completely disconnecting the in-game frame rate from real time. That is, if you set it to 30, the game will run at 30 fps as measured by `Time.deltaTime` and the calls to `Update` on your components, regardless of whether a frame takes a millisecond or a minute as measured by wall-clock time." ContentLicense="CC BY-SA 4.0" />
  <row Id="21239" PostHistoryTypeId="50" PostId="7513" RevisionGUID="5014b5b7-5986-4be4-bbdc-a2c34562323d" CreationDate="2018-09-07T15:00:27.583" UserId="-1" />
  <row Id="21241" PostHistoryTypeId="2" PostId="8037" RevisionGUID="83072db4-2177-41de-aec2-16cba8d190e4" CreationDate="2018-09-07T16:24:49.147" UserId="6092" Text="I have two RGBA colors in linear [0..1] space, `src` and `dst` and I want to alpha blender `src` over/under `dst` n times. Of course, I could call the respective operation n times using the result from the previous one (which is what I am currently doing), but I want to optimize it into a single operation. I think just calculating the correct alpha on `src` should be sufficient, but I may be wrong. Here's what I currently use:&#xD;&#xA;&#xD;&#xA;	public static final Color alphaOver(Color dst, Color src) {&#xD;&#xA;		float src1A = 1 - src.a;&#xD;&#xA;		float outA = src.a + dst.a * src1A;&#xD;&#xA;&#xD;&#xA;		if (outA == 0)&#xD;&#xA;			return Color.TRANSPARENT;&#xD;&#xA;		return new Color(&#xD;&#xA;				outA,&#xD;&#xA;				(src.r * src.a + dst.r * dst.a * src1A) / outA,&#xD;&#xA;				(src.g * src.a + dst.g * dst.a * src1A) / outA,&#xD;&#xA;				(src.b * src.a + dst.b * dst.a * src1A) / outA);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	public static final Color alphaUnder(Color dst, Color src) {&#xD;&#xA;		return alphaOver(src, dst);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public static final Color alphaOver(Color dst, Color src, int times) {&#xD;&#xA;		Color ret = dst;&#xD;&#xA;		for (int i = 0; i &lt; times; i++)&#xD;&#xA;			ret = alphaOver(ret, src);&#xD;&#xA;		return ret;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public static final Color alphaUnder(Color dst, Color src, int times) {&#xD;&#xA;		Color ret = dst;&#xD;&#xA;		for (int i = 0; i &lt; times; i++)&#xD;&#xA;			ret = alphaUnder(ret, src);&#xD;&#xA;		return ret;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;How can I optimize the last two functions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21242" PostHistoryTypeId="1" PostId="8037" RevisionGUID="83072db4-2177-41de-aec2-16cba8d190e4" CreationDate="2018-09-07T16:24:49.147" UserId="6092" Text="Repeating alpha over/under operation multiple times" ContentLicense="CC BY-SA 4.0" />
  <row Id="21243" PostHistoryTypeId="3" PostId="8037" RevisionGUID="83072db4-2177-41de-aec2-16cba8d190e4" CreationDate="2018-09-07T16:24:49.147" UserId="6092" Text="|color|blending|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21245" PostHistoryTypeId="2" PostId="8038" RevisionGUID="aab92719-184e-4860-970a-840cf7bf9233" CreationDate="2018-09-07T20:28:32.237" UserId="3003" Text="So taking source over as an example, the math works out to:&#xD;&#xA;&#xD;&#xA;&gt; a * src + (1 - a) * dst&#xD;&#xA;&#xD;&#xA;This can be algebraically rewritten as:&#xD;&#xA;&#xD;&#xA;&gt; a * (src - dst) + dst&#xD;&#xA;&#xD;&#xA;If we take that and plug it into the first equation again as the `src`, you get:&#xD;&#xA;&#xD;&#xA;&gt; a * (a * (src - dst) +  dst) + (1 - a) * dst&#xD;&#xA;&#xD;&#xA;That simplifies to:&#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;2&lt;/sup&gt; * src - a&lt;sup&gt;2&lt;/sup&gt; * dst + a * dst + dst - a* dst&#xD;&#xA;&#xD;&#xA;which further simplifies to:&#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;2&lt;/sup&gt; * src - a&lt;sup&gt;2&lt;/sup&gt; * dst + dst&#xD;&#xA;&#xD;&#xA;If you plug that into the original equation as `src`, you end up seeing the pattern is:&#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;n&lt;/sup&gt; * src - a&lt;sup&gt;n&lt;/sup&gt; * dst + dst&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;n&lt;/sup&gt; (src - dst) + dst" ContentLicense="CC BY-SA 4.0" />
  <row Id="21246" PostHistoryTypeId="4" PostId="8017" RevisionGUID="09e1687f-be1c-4804-95d6-8c5e58a1b600" CreationDate="2018-09-08T00:27:07.297" UserId="504" Comment="edited title" Text="Why do GPUs divide clip space Z by W, for position?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21247" PostHistoryTypeId="5" PostId="8038" RevisionGUID="7147c232-6255-49cc-8837-6a6661d85477" CreationDate="2018-09-08T00:56:39.670" UserId="3003" Comment="Added example of replacing dst each round" Text="So taking source over as an example, the math works out to:&#xD;&#xA;&#xD;&#xA;&gt; a * src + (1 - a) * dst&#xD;&#xA;&#xD;&#xA;This can be algebraically rewritten as:&#xD;&#xA;&#xD;&#xA;&gt; a * (src - dst) + dst&#xD;&#xA;&#xD;&#xA;If we take that and plug it into the first equation again as the `src`, you get:&#xD;&#xA;&#xD;&#xA;&gt; a * (a * (src - dst) +  dst) + (1 - a) * dst&#xD;&#xA;&#xD;&#xA;That simplifies to:&#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;2&lt;/sup&gt; * src - a&lt;sup&gt;2&lt;/sup&gt; * dst + a * dst + dst - a* dst&#xD;&#xA;&#xD;&#xA;which further simplifies to:&#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;2&lt;/sup&gt; * src - a&lt;sup&gt;2&lt;/sup&gt; * dst + dst&#xD;&#xA;&#xD;&#xA;If you plug that into the original equation as `src`, you end up seeing the pattern is:&#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;n&lt;/sup&gt; * src - a&lt;sup&gt;n&lt;/sup&gt; * dst + dst&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;&gt; a&lt;sup&gt;n&lt;/sup&gt; (src - dst) + dst&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;On the other hand, if you want to replace the `dst` parameter instead of the `src`, it gets a little more complex. The series goes something like this:&#xD;&#xA;&#xD;&#xA;first round:&#xD;&#xA;&gt; dst = a * src + (1 - a) * dst&#xD;&#xA;&#xD;&#xA;second round:&#xD;&#xA;&gt; dst = a&lt;sup&gt;2&lt;/sup&gt; (-src + dst) + 2a (src - dst) + dst&#xD;&#xA;&#xD;&#xA;third round:&#xD;&#xA;&gt; dst = a&lt;sup&gt;3&lt;/sup&gt; (src - dst) - 3 a&lt;sup&gt;2&lt;/sup&gt; (src + dst) + 3 a (src - dst) + dst&#xD;&#xA;&#xD;&#xA;fourth round:&#xD;&#xA;&gt; dst = a&lt;sup&gt;4&lt;/sup&gt; (-src + dst) + 4a&lt;sup&gt;3&lt;/sup&gt;(src - dst) + 6a&lt;sup&gt;2&lt;/sup&gt;(-src + dst) + 4a(src - dst) + dst&#xD;&#xA;&#xD;&#xA;fifth round:&#xD;&#xA;&gt; dst = &#xD;&#xA;a&lt;sup&gt;5&lt;/sup&gt; (src - dst) - 5 a&lt;sup&gt;4&lt;/sup&gt; (src + dst) + 10 a&lt;sup&gt;3&lt;/sup&gt; (src - dst) - 10 a&lt;sup&gt;2&lt;/sup&gt; (src + dst) + 5 a (src - dst) + dst&#xD;&#xA;&#xD;&#xA;etc.&#xD;&#xA;&#xD;&#xA;What you find is that the exponents increase with each round. The coefficients form a [Pascal's Triangle](https://en.wikipedia.org/wiki/Pascal's_triangle),  with alternating signs on the odd rounds. The `src` and `dst` multipliers follow this pattern:&#xD;&#xA;&#xD;&#xA;&gt;                                     (+1 -1) (0 +1)&#xD;&#xA;&gt;                             (-1 +1) (+1 -1) (0 +1)&#xD;&#xA;&gt;                     (+1 -1) (+1 +1) (+1 -1) (0 +1)&#xD;&#xA;&gt;             (-1 +1) (+1 -1) (-1 +1) (+1 -1) (0 +1)&#xD;&#xA;&gt;     (+1 -1) (+1 +1) (+1 -1) (+1 +1) (+1 -1) (0 +1) &#xD;&#xA;etc.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21248" PostHistoryTypeId="5" PostId="8038" RevisionGUID="92089976-7d46-44d7-a1e9-523b636efb5d" CreationDate="2018-09-08T05:28:58.053" UserId="3003" Comment="Rewrote the derivation" Text="So taking source over as an example, the math works out to:&#xD;&#xA;&#xD;&#xA;&gt; dst = a * src + (1 - a) * dst&#xD;&#xA;&#xD;&#xA;Taking Nathan Reed's suggestion of replacing `(1 - a)` with `b`, that gives us:&#xD;&#xA;&#xD;&#xA;&gt; dst = a * src + b * dst&#xD;&#xA;&#xD;&#xA;If we perform the next iteration, it becomes:&#xD;&#xA;&#xD;&#xA;&gt; dst = a * src + ab * src + b^2 * dst&#xD;&#xA;&#xD;&#xA;Doing it again, we get:&#xD;&#xA;&#xD;&#xA;&gt; dst = a * src + ab * src + ab^2 * src + b^3 * dst&#xD;&#xA;&#xD;&#xA;And then:&#xD;&#xA;&#xD;&#xA;&gt; dst = a * src + ab * src + ab^2 * src + ab^3 * src + b^4 * dst&#xD;&#xA;&#xD;&#xA;The pattern appears to be:&#xD;&#xA;&#xD;&#xA;    int exponent;&#xD;&#xA;    for (exponent = 0; exponent &lt; numIterations; exponent++)&#xD;&#xA;    {&#xD;&#xA;        newDst += a * pow(b, exponent) * src;&#xD;&#xA;    }&#xD;&#xA;    newDst += pow(b, exponent) * dst;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21249" PostHistoryTypeId="4" PostId="7969" RevisionGUID="182ec6a5-9b67-4215-9035-c3e7aa31061e" CreationDate="2018-09-08T14:36:22.337" UserId="5430" Comment="edited title" Text="Using multiply and accumulate of 4x4 matrices for ray-triangle intersection tests on GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="21250" PostHistoryTypeId="2" PostId="8039" RevisionGUID="f12bf5a9-8634-4d8d-9066-e6e2b2d26a89" CreationDate="2018-09-08T16:15:33.160" UserId="6046" Text="I don't understand what's the problem. We want to make a change of variables so that instead of integrating over the range of directions $d\omega_i$ in the upper hemisphere we integrate over patches of area $dA$ of a region $R$.&#xD;&#xA;&#xD;&#xA;This whole thing is given in section 5.5 as Hubble said but let me post it again.&#xD;&#xA;&#xD;&#xA;We know by definition that,&#xD;&#xA;   &#xD;&#xA;$\omega = A *  cos(\theta)/r^2$  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now if you differentiate this, you get&#xD;&#xA;&#xD;&#xA;$d\omega = dA * cos(\theta) / r^2$ &#xD;&#xA;&#xD;&#xA;where,&#xD;&#xA;&#xD;&#xA;$Jacobian = cos(\theta) / r^2$&#xD;&#xA;&#xD;&#xA;as Hubble said. I don't know what are you trying to do by calculating Jacobian through determinant but as far as I know, that Jacobian determinant is for multi-variables and involves partial derivatives. For change of variables involving a single variable the Jacobian can be gotten by simply derivating as I did.&#xD;&#xA;&#xD;&#xA;Now this might seem the inverse but wait a moment. What you posted in the question is a relation between the PDFs.&#xD;&#xA;&#xD;&#xA;Consider a single sample of the rendering equation integrated over the domain of $\omega_i$&#xD;&#xA;&#xD;&#xA;$L_s = BRDF * L_f * (\omega_i . n) / p(\omega)  $&#xD;&#xA;&#xD;&#xA;After changing the domain by above equations this would become&#xD;&#xA;&#xD;&#xA;$L_s = BRDF * L_f * (\omega_i . n) (\omega_i . n_r)\, / \,  (p(A) * r^2)  $&#xD;&#xA;&#xD;&#xA;$L_s = BRDF * L_f * (\omega_i . n) * JN\, / \,  p(A) $  &#xD;&#xA;where $Jacobian = JN$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This means, &#xD;&#xA;$ 1 / p(\omega) =  JN/p(A)$&#xD;&#xA;&#xD;&#xA;$ p(A) = p(\omega) * JN$&#xD;&#xA;&#xD;&#xA;$ p(A) = p(\omega) * cos(\theta)/r^2$&#xD;&#xA;&#xD;&#xA;This is what you see above. Simple as ****." ContentLicense="CC BY-SA 4.0" />
  <row Id="21251" PostHistoryTypeId="2" PostId="8040" RevisionGUID="2d90c26e-c166-41b8-842f-7db344934125" CreationDate="2018-09-09T02:19:40.630" UserId="7012" Text="Depends how 'deep' you want to go.&#xD;&#xA;&#xD;&#xA;With Unity/Unreal doesn't have to be 'programatically' - they do have GUI, you can just load your data with few button clicks. Potentially you could parse/convert your data to readable format [obj might be easiest][1] with for eg. python.&#xD;&#xA;&#xD;&#xA;So not sure what programming language you have in mind but as you are mentioning some python modules I guess python.&#xD;&#xA;&#xD;&#xA;Then you could display it in many different ways.&#xD;&#xA;&#xD;&#xA;- [OpenGL][2] (there are many Python bindings over the internet, check them out and choose one that suits you best)&#xD;&#xA;&#xD;&#xA;- [Matplot][3], [pygraph][4] and similar also have an ability to plot in 3D&#xD;&#xA;&#xD;&#xA;- explore [pandas][5] as it is a great python library to deal with this types of datas&#xD;&#xA;&#xD;&#xA;And for eg. you could put it all together inside a [QT][6]&#xD;&#xA;&#xD;&#xA;  [1]: https://programminglinuxgames.blogspot.com/2010/09/parsing-wavefront-obj-file-format-using.html&#xD;&#xA;  [2]: https://pypi.org/project/PyOpenGL/&#xD;&#xA;  [3]: https://matplotlib.org/&#xD;&#xA;  [4]: https://github.com/pyqtgraph/pyqtgraph&#xD;&#xA;  [5]: https://pandas.pydata.org/&#xD;&#xA;  [6]: https://pythonspot.com/pyqt5/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21254" PostHistoryTypeId="2" PostId="8041" RevisionGUID="efba10d4-44ae-4379-81a0-de9370294570" CreationDate="2018-09-09T04:49:52.037" UserId="48" Text="Using Z/W for the depth buffer goes deeper than just clipping against the near and far planes. As Simon alluded to, this has to do with interpolation between the vertices of a triangle, during rasterization.&#xD;&#xA;&#xD;&#xA;Z/W is the unique option that allows NDC depth values to be correctly calculated for points in the interior of the triangle, by simply linearly interpolating the NDC depth values from the vertices, _in screen space_. In principle, we could use any function we like to map camera-space Z to the depth buffer value—but any other choice than Z/W would require more complicated math to be done per pixel, which would be slower, and more difficult to build in hardware.&#xD;&#xA;&#xD;&#xA;Note that if you use a linear depth buffer, then of course linearly interpolating depth values will be correct in _world_ space...but not, in general, in screen space! And it is screen space that matters for rasterization, as we need to be able to generate perspective-correct depth values (and other attribute values, like UVs) for each pixel center, or other sample point, within the screen-space bounds of a triangle being rasterized." ContentLicense="CC BY-SA 4.0" />
  <row Id="21260" PostHistoryTypeId="50" PostId="7794" RevisionGUID="5f565ef6-d793-4d88-af09-7f2197d42e25" CreationDate="2018-09-09T17:00:58.923" UserId="-1" />
  <row Id="21261" PostHistoryTypeId="50" PostId="4632" RevisionGUID="54cbd092-6c96-4b65-9000-c68363785460" CreationDate="2018-09-10T01:01:19.107" UserId="-1" />
  <row Id="21262" PostHistoryTypeId="2" PostId="8043" RevisionGUID="145fe20d-6798-491b-8aea-cc2e2e8bd311" CreationDate="2018-09-10T02:11:35.150" UserId="3073" Text="This looks like a case of 16bit overflow in your indice buffer. For a 257x257 grid you will be addressing more than 65536 vertices so you will need to use a 32bit indice buffer.&#xD;&#xA;&#xD;&#xA;    gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;change to :&#xD;&#xA;&#xD;&#xA;    gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;Also change you buffer allocation code to match this type.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21263" PostHistoryTypeId="2" PostId="8044" RevisionGUID="5991578b-4982-4ddf-aa0d-2ab14085c6bd" CreationDate="2018-09-10T10:55:04.877" UserId="9322" Text="I've spent about 2 days trying to understand this piece of code (from [here](https://github.com/nilx/megawave/blob/master/src/image/domain/fproj.c)) that applies an affine/projective transformation to an image. I will link bits of the code that I'm struggling to understand and add comments on what I think it's trying to do. In particular, the author's original comments I'll label as `//`. &#xD;&#xA; &#xD;&#xA;    //      COMPUTE NEW BASIS&#xD;&#xA;    // X1, Y1 : upleft corner&#xD;&#xA;    // X2, Y2 : upright corner&#xD;&#xA;    // X3, Y3 : downleft corner &#xD;&#xA;    // sx     : x-size of output image&#xD;&#xA;    // sy     : y-size of output image&#xD;&#xA;    x12 = (X2-X1)/(float)(*sx); &#xD;&#xA;    y12 = (Y2-Y1)/(float)(*sx);&#xD;&#xA;    x13 = (X3-X1)/(float)(*sy);&#xD;&#xA;    y13 = (Y3-Y1)/(float)(*sy);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Q1. I can see that this part as the comment says, finds a new normalized basis but I'm unsure exactly why we need to find one to model an affine transformation?&#xD;&#xA;&#xD;&#xA;    // x4, y4 : downright corner (for projective transform)&#xD;&#xA;&#xD;&#xA;    if (y4) &#xD;&#xA;    { &#xD;&#xA;        xx=((x4-X1)*(Y3-Y1)-(y4-Y1)*(X3-X1))/((X2-X1)*(Y3-Y1)-(Y2-Y1)*(X3-X1));&#xD;&#xA;        yy=((x4-X1)*(Y2-Y1)-(y4-Y1)*(X2-X1))/((X3-X1)*(Y2-Y1)-(Y3-Y1)*(X2-X1));&#xD;&#xA;        a = (yy-1.0)/(1.0-xx-yy);&#xD;&#xA;        b = (xx-1.0)/(1.0-xx-yy);&#xD;&#xA;    } &#xD;&#xA;    else &#xD;&#xA;    {&#xD;&#xA;        a=b=0.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After doing some internet search, I manage to find equations from [here](http://paulbourke.net/geometry/pointlineplane/) that the `xx` and `yy` equations solve for the &quot;intersection point of two line segments in 2 dimensions&quot;. An image will be linked below.&#xD;&#xA;&#xD;&#xA;**START IMAGE.**&#xD;&#xA;[![Intersection of two lines][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**END IMAGE.**&#xD;&#xA;&#xD;&#xA;Q2. I don't understand how he uses the `xx` and `yy` equations to solve for a &amp; b? &#xD;&#xA;&#xD;&#xA;Q3. I am unsure of what `a` and `b` are. My best guess is that they are the bottom row of a projective transformation matrix shown below:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11} &amp; a_{12} &amp; a_{13} \\&#xD;&#xA;a_{21} &amp; a_{22} &amp; a_{23} \\&#xD;&#xA;a &amp; b &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This is because the code sets `a = b = 0.0` if we're not doing a projective transform, which should then make it an affine transformation matrix.&#xD;&#xA;&#xD;&#xA;Now is where the main loop happens:&#xD;&#xA;&#xD;&#xA;    for (x=0;x&lt;sx;x++) &#xD;&#xA;        for (y=0;y&lt;sy;y++) {&#xD;&#xA;	        fx = (float)x + 0.5;&#xD;&#xA;	        fy = (float)y + 0.5;&#xD;&#xA;	        d = a*fx/(float)(*sx)+b*fy/(float)(*sy)+1.0;&#xD;&#xA;	        xx = (a+1.0)*fx/d;&#xD;&#xA;	        yy = (b+1.0)*fy/d;&#xD;&#xA;	        xp = X1 + xx*x12 + yy*x13;&#xD;&#xA;	        yp = Y1 + xx*y12 + yy*y13;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Q4. Why does he add 0.5 to the original x and y coordinate? My best guess is that the code's trying to map the centre of each pixel rather than the edge to the new image:&#xD;&#xA;&#xD;&#xA;[![Pixels][2]][2]&#xD;&#xA;&#xD;&#xA;Q5. In &#xD;&#xA;&#xD;&#xA;    d = a*fx/(float)(*sx)+b*fy/(float)(*sy)+1.0;&#xD;&#xA;	xx = (a+1.0)*fx/d;&#xD;&#xA;	yy = (b+1.0)*fy/d;&#xD;&#xA;&#xD;&#xA;what are they trying to accomplish here? My best guess is that `d` is the third component of the output homogeneous coordinate:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xx\\&#xD;&#xA;yy\\&#xD;&#xA;d\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;calculated from the dot product of the third row of the (now normalised) transformation matrix from earlier and the input homogeneous vector:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\frac{a}{sx} &amp; \frac{b}{sy} &amp; 1 \\    &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;fx\\&#xD;&#xA;fy\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;a*fx/sx+b*fy/sy+1.0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then the division&#xD;&#xA;&#xD;&#xA;	xx = (a+1.0)*fx/d;&#xD;&#xA;	yy = (b+1.0)*fy/d;&#xD;&#xA;&#xD;&#xA;would just transform the homogeneous coordinates back to Euclidean coordinates, corresponding to the output image pixel location. I noted that if `a=b=0.0` (so not projective), then `(a+1.0)=(b+1.0)=d=1.0`. But again, I do not know if I'm on the right track or not as I do not have anyone to help me with this code.&#xD;&#xA;&#xD;&#xA;Q7. The final operation&#xD;&#xA;&#xD;&#xA;    xp = X1 + xx*x12 + yy*x13;&#xD;&#xA;	yp = Y1 + xx*y12 + yy*y13;&#xD;&#xA;&#xD;&#xA;I suppose is literally the dot product of the first two rows of the transformation matrix with the Euclidean coordinates as so:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x12 &amp; x13 &amp; X_{1} \\ &#xD;&#xA;y12 &amp; y13 &amp; Y_{1}  &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xx\\&#xD;&#xA;yy\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xp\\&#xD;&#xA;yp\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which brings me to my question, how does this achieve an affine transformation? &#xD;&#xA;&#xD;&#xA;I suspect my lack of formal training could be why I'm not understanding how the code models an affine transformation. I'd appreciate some light shed on this piece of code!&#xD;&#xA;&#xD;&#xA;Cheers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ANCv2m.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vnPXU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21264" PostHistoryTypeId="1" PostId="8044" RevisionGUID="5991578b-4982-4ddf-aa0d-2ab14085c6bd" CreationDate="2018-09-10T10:55:04.877" UserId="9322" Text="Deciphering Affine/Projective Transformation Code" ContentLicense="CC BY-SA 4.0" />
  <row Id="21265" PostHistoryTypeId="3" PostId="8044" RevisionGUID="5991578b-4982-4ddf-aa0d-2ab14085c6bd" CreationDate="2018-09-10T10:55:04.877" UserId="9322" Text="|transformations|algorithm|affine-transformations|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21267" PostHistoryTypeId="2" PostId="8045" RevisionGUID="c1122e2b-8e4f-4212-92f4-8b2fe0caffae" CreationDate="2018-09-10T12:13:39.607" UserId="9254" Text="In Metropolis Light Transport, we need to approximate the integral of the measurement contribution function. I've read that this can be done using a traditional approach like path tracing. However, how exactly do we need to implement this approximation?&#xD;&#xA;&#xD;&#xA;Are we selecting random points on the view plane, shoot rays from the eye through these points and calculate the contribution of the resulting path to a light source? This would yield the contribution of a single path. Maybe we create `N` paths in this way and average their contributions.&#xD;&#xA;&#xD;&#xA;I've read the explanation in PBR3, but I still don't understand how this approximation is done exactly." ContentLicense="CC BY-SA 4.0" />
  <row Id="21268" PostHistoryTypeId="1" PostId="8045" RevisionGUID="c1122e2b-8e4f-4212-92f4-8b2fe0caffae" CreationDate="2018-09-10T12:13:39.607" UserId="9254" Text="How do we approximate the integral of the measurement contribution function in Metropolis Light Transport?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21269" PostHistoryTypeId="3" PostId="8045" RevisionGUID="c1122e2b-8e4f-4212-92f4-8b2fe0caffae" CreationDate="2018-09-10T12:13:39.607" UserId="9254" Text="|raytracing|rendering|pathtracing|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21270" PostHistoryTypeId="5" PostId="8044" RevisionGUID="eb88344e-6ee9-469f-9a44-470818b78a2e" CreationDate="2018-09-10T12:42:31.090" UserId="9322" Comment="[Edit removed during grace period]" Text="I've spent about 2 days trying to understand this piece of code (from [here](https://github.com/nilx/megawave/blob/master/src/image/domain/fproj.c)) that applies an affine/projective transformation to an image. I will link bits of the code that I'm struggling to understand and add comments on what I think it's trying to do. In particular, the author's original comments I'll label as `//`. &#xD;&#xA; &#xD;&#xA;    //      COMPUTE NEW BASIS&#xD;&#xA;    // X1, Y1 : upleft corner&#xD;&#xA;    // X2, Y2 : upright corner&#xD;&#xA;    // X3, Y3 : downleft corner &#xD;&#xA;    // sx     : x-size of output image&#xD;&#xA;    // sy     : y-size of output image&#xD;&#xA;    x12 = (X2-X1)/(float)(*sx); &#xD;&#xA;    y12 = (Y2-Y1)/(float)(*sx);&#xD;&#xA;    x13 = (X3-X1)/(float)(*sy);&#xD;&#xA;    y13 = (Y3-Y1)/(float)(*sy);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Q1. I can see that this part as the comment says, finds a new normalized basis but I'm unsure exactly why we need to find one to model an affine transformation?&#xD;&#xA;&#xD;&#xA;    // x4, y4 : downright corner (for projective transform)&#xD;&#xA;&#xD;&#xA;    if (y4) &#xD;&#xA;    { &#xD;&#xA;        xx=((x4-X1)*(Y3-Y1)-(y4-Y1)*(X3-X1))/((X2-X1)*(Y3-Y1)-(Y2-Y1)*(X3-X1));&#xD;&#xA;        yy=((x4-X1)*(Y2-Y1)-(y4-Y1)*(X2-X1))/((X3-X1)*(Y2-Y1)-(Y3-Y1)*(X2-X1));&#xD;&#xA;        a = (yy-1.0)/(1.0-xx-yy);&#xD;&#xA;        b = (xx-1.0)/(1.0-xx-yy);&#xD;&#xA;    } &#xD;&#xA;    else &#xD;&#xA;    {&#xD;&#xA;        a=b=0.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After doing some internet search, I manage to find equations from [here](http://paulbourke.net/geometry/pointlineplane/) that the `xx` and `yy` equations solve for the &quot;intersection point of two line segments in 2 dimensions&quot;. An image will be linked below.&#xD;&#xA;&#xD;&#xA;**START IMAGE.**&#xD;&#xA;[![Intersection of two lines][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**END IMAGE.**&#xD;&#xA;&#xD;&#xA;Q2. I don't understand how he uses the `xx` and `yy` equations to solve for a &amp; b? &#xD;&#xA;&#xD;&#xA;Q3. I am unsure of what `a` and `b` are. My best guess is that they are the bottom row of a projective transformation matrix shown below:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11} &amp; a_{12} &amp; a_{13} \\&#xD;&#xA;a_{21} &amp; a_{22} &amp; a_{23} \\&#xD;&#xA;a &amp; b &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This is because the code sets `a = b = 0.0` if we're not doing a projective transform, which should then make it an affine transformation matrix.&#xD;&#xA;&#xD;&#xA;Now is where the main loop happens:&#xD;&#xA;&#xD;&#xA;    for (x=0;x&lt;sx;x++) &#xD;&#xA;        for (y=0;y&lt;sy;y++) {&#xD;&#xA;	        fx = (float)x + 0.5;&#xD;&#xA;	        fy = (float)y + 0.5;&#xD;&#xA;	        d = a*fx/(float)(*sx)+b*fy/(float)(*sy)+1.0;&#xD;&#xA;	        xx = (a+1.0)*fx/d;&#xD;&#xA;	        yy = (b+1.0)*fy/d;&#xD;&#xA;	        xp = X1 + xx*x12 + yy*x13;&#xD;&#xA;	        yp = Y1 + xx*y12 + yy*y13;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Q4. Why does he add 0.5 to the original x and y coordinate? My best guess is that the code's trying to map the centre of each pixel rather than the edge to the new image:&#xD;&#xA;&#xD;&#xA;[![Pixels][2]][2]&#xD;&#xA;&#xD;&#xA;Q5. In &#xD;&#xA;&#xD;&#xA;    d = a*fx/(float)(*sx)+b*fy/(float)(*sy)+1.0;&#xD;&#xA;	xx = (a+1.0)*fx/d;&#xD;&#xA;	yy = (b+1.0)*fy/d;&#xD;&#xA;&#xD;&#xA;what are they trying to accomplish here? My best guess is that `d` is the third component of the output homogeneous coordinate:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xx\\&#xD;&#xA;yy\\&#xD;&#xA;d\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;calculated from the dot product of the third row of the (now normalised) transformation matrix from earlier and the input homogeneous vector:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\frac{a}{sx} &amp; \frac{b}{sy} &amp; 1 \\    &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;fx\\&#xD;&#xA;fy\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;a*fx/sx+b*fy/sy+1.0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then the division&#xD;&#xA;&#xD;&#xA;	xx = (a+1.0)*fx/d;&#xD;&#xA;	yy = (b+1.0)*fy/d;&#xD;&#xA;&#xD;&#xA;would just transform the homogeneous coordinates back to Euclidean coordinates, corresponding to the output image pixel location. I noted that if `a=b=0.0` (so not projective), then `(a+1.0)=(b+1.0)=d=1.0`. But again, I do not know if I'm on the right track or not as I do not have anyone to help me with this code.&#xD;&#xA;&#xD;&#xA;Q7. The final operation&#xD;&#xA;&#xD;&#xA;    xp = X1 + xx*x12 + yy*x13;&#xD;&#xA;	yp = Y1 + xx*y12 + yy*y13;&#xD;&#xA;&#xD;&#xA;I suppose is literally the dot product of the first two rows of the transformation matrix with the Euclidean coordinates as so:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x12 &amp; x13 &amp; X_{1} \\ &#xD;&#xA;y12 &amp; y13 &amp; Y_{1}  &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xx\\&#xD;&#xA;yy\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xp\\&#xD;&#xA;yp\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which brings me to my question, how does this achieve an affine transformation? &#xD;&#xA;&#xD;&#xA;I suspect my lack of formal training could be why I'm not understanding how the code models an affine transformation. I'd appreciate some light shed on this piece of code!&#xD;&#xA;&#xD;&#xA;Cheers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ANCv2m.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vnPXU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21271" PostHistoryTypeId="5" PostId="8044" RevisionGUID="ba88252c-21b2-4732-9b54-ffa32812c028" CreationDate="2018-09-10T12:59:28.803" UserId="9322" Comment="Clarified a question." Text="I've spent about 2 days trying to understand this piece of code (from [here](https://github.com/nilx/megawave/blob/master/src/image/domain/fproj.c)) that applies an affine/projective transformation to an image. I will link bits of the code that I'm struggling to understand and add comments on what I think it's trying to do. In particular, the author's original comments I'll label as `//`. &#xD;&#xA; &#xD;&#xA;    //      COMPUTE NEW BASIS&#xD;&#xA;    // X1, Y1 : upleft corner&#xD;&#xA;    // X2, Y2 : upright corner&#xD;&#xA;    // X3, Y3 : downleft corner &#xD;&#xA;    // sx     : x-size of output image&#xD;&#xA;    // sy     : y-size of output image&#xD;&#xA;    x12 = (X2-X1)/(float)(*sx); &#xD;&#xA;    y12 = (Y2-Y1)/(float)(*sx);&#xD;&#xA;    x13 = (X3-X1)/(float)(*sy);&#xD;&#xA;    y13 = (Y3-Y1)/(float)(*sy);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Q1. I can see that this part as the comment says, finds a new normalized basis but I'm unsure exactly why we need to find one to model an affine transformation?&#xD;&#xA;&#xD;&#xA;    // x4, y4 : downright corner (for projective transform)&#xD;&#xA;&#xD;&#xA;    if (y4) &#xD;&#xA;    { &#xD;&#xA;        xx=((x4-X1)*(Y3-Y1)-(y4-Y1)*(X3-X1))/((X2-X1)*(Y3-Y1)-(Y2-Y1)*(X3-X1));&#xD;&#xA;        yy=((x4-X1)*(Y2-Y1)-(y4-Y1)*(X2-X1))/((X3-X1)*(Y2-Y1)-(Y3-Y1)*(X2-X1));&#xD;&#xA;        a = (yy-1.0)/(1.0-xx-yy);&#xD;&#xA;        b = (xx-1.0)/(1.0-xx-yy);&#xD;&#xA;    } &#xD;&#xA;    else &#xD;&#xA;    {&#xD;&#xA;        a=b=0.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After doing some internet search, I manage to find equations from [here](http://paulbourke.net/geometry/pointlineplane/) that the `xx` and `yy` equations solve for the &quot;intersection point of two line segments in 2 dimensions&quot;. An image will be linked below.&#xD;&#xA;&#xD;&#xA;**START IMAGE.**&#xD;&#xA;[![Intersection of two lines][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**END IMAGE.**&#xD;&#xA;&#xD;&#xA;Q2. I don't understand how he uses the `xx` and `yy` equations to solve for a &amp; b? &#xD;&#xA;&#xD;&#xA;Q3. I am unsure of what `a` and `b` are. My best guess is that they are the bottom row of a projective transformation matrix shown below:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11} &amp; a_{12} &amp; a_{13} \\&#xD;&#xA;a_{21} &amp; a_{22} &amp; a_{23} \\&#xD;&#xA;a &amp; b &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This is because the code sets `a = b = 0.0` if we're not doing a projective transform, which should then make it an affine transformation matrix.&#xD;&#xA;&#xD;&#xA;Now is where the main loop happens:&#xD;&#xA;&#xD;&#xA;    for (x=0;x&lt;sx;x++) &#xD;&#xA;        for (y=0;y&lt;sy;y++) {&#xD;&#xA;	        fx = (float)x + 0.5;&#xD;&#xA;	        fy = (float)y + 0.5;&#xD;&#xA;	        d = a*fx/(float)(*sx)+b*fy/(float)(*sy)+1.0;&#xD;&#xA;	        xx = (a+1.0)*fx/d;&#xD;&#xA;	        yy = (b+1.0)*fy/d;&#xD;&#xA;	        xp = X1 + xx*x12 + yy*x13;&#xD;&#xA;	        yp = Y1 + xx*y12 + yy*y13;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Q4. Why does he add 0.5 to the original x and y coordinate? My best guess is that the code's trying to map the centre of each pixel rather than the edge to the new image:&#xD;&#xA;&#xD;&#xA;[![Pixels][2]][2]&#xD;&#xA;&#xD;&#xA;Q5. In &#xD;&#xA;&#xD;&#xA;    d = a*fx/(float)(*sx)+b*fy/(float)(*sy)+1.0;&#xD;&#xA;	xx = (a+1.0)*fx/d;&#xD;&#xA;	yy = (b+1.0)*fy/d;&#xD;&#xA;&#xD;&#xA;what are they trying to accomplish here? My best guess is that `d` is the third component of the output homogeneous coordinate:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xx\\&#xD;&#xA;yy\\&#xD;&#xA;d\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;calculated from the dot product of the third row of the (now normalised) transformation matrix from earlier and the input homogeneous vector:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\frac{a}{sx} &amp; \frac{b}{sy} &amp; 1 \\    &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;fx\\&#xD;&#xA;fy\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;a*fx/sx+b*fy/sy+1.0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Then the division&#xD;&#xA;&#xD;&#xA;	xx = (a+1.0)*fx/d;&#xD;&#xA;	yy = (b+1.0)*fy/d;&#xD;&#xA;&#xD;&#xA;would just transform the homogeneous coordinates back to Euclidean coordinates, corresponding to the output image pixel location. I noted that if `a=b=0.0` (so not projective), then `(a+1.0)=(b+1.0)=d=1.0`. I'm however not sure about why we have to multiply by `(a+1.0)` or `(b+1.0)`. But again, I do not know if I'm on the right track or not as I do not have anyone to help me with this code.&#xD;&#xA;&#xD;&#xA;Q7. The final operation&#xD;&#xA;&#xD;&#xA;    xp = X1 + xx*x12 + yy*x13;&#xD;&#xA;	yp = Y1 + xx*y12 + yy*y13;&#xD;&#xA;&#xD;&#xA;I suppose is literally the dot product of the first two rows of the transformation matrix with the Euclidean coordinates as so:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x12 &amp; x13 &amp; X_{1} \\ &#xD;&#xA;y12 &amp; y13 &amp; Y_{1}  &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xx\\&#xD;&#xA;yy\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;xp\\&#xD;&#xA;yp\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which brings me to my question, how does this achieve an affine transformation? &#xD;&#xA;&#xD;&#xA;I suspect my lack of formal training could be why I'm not understanding how the code models an affine transformation. I'd appreciate some light shed on this piece of code!&#xD;&#xA;&#xD;&#xA;Cheers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ANCv2m.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vnPXU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21272" PostHistoryTypeId="2" PostId="8046" RevisionGUID="b1ac6305-3c06-4839-9177-943cf4f267c7" CreationDate="2018-09-10T13:28:39.117" UserId="9325" Text="More of a question about what's possible in DX.&#xD;&#xA;&#xD;&#xA;Some people have reported that when running games on higher settings they get less CPU load but when dropping the settings the CPU load increases.&#xD;&#xA;&#xD;&#xA;What would be causing increased CPU load in these cases? &#xD;&#xA;&#xD;&#xA;Someone suggested that the DirectX API falls back to software when certain features are turned off, but is this something that can happen - can DirectX do a mixed render where some stuff in the render pipeline is pushed through the CPU and the rest goes to the GPU?&#xD;&#xA;&#xD;&#xA;My thoughts were texture quality and downsampling and potentially physics processing not being offloaded but does anyone actually know what the cause might be?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21273" PostHistoryTypeId="1" PostId="8046" RevisionGUID="b1ac6305-3c06-4839-9177-943cf4f267c7" CreationDate="2018-09-10T13:28:39.117" UserId="9325" Text="CPU load in games - what is the GPU/DirectX doing to make CPU load higher?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21274" PostHistoryTypeId="3" PostId="8046" RevisionGUID="b1ac6305-3c06-4839-9177-943cf4f267c7" CreationDate="2018-09-10T13:28:39.117" UserId="9325" Text="|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21275" PostHistoryTypeId="2" PostId="8047" RevisionGUID="ee7bae85-6070-4138-b31b-ad0cbf2e4f0e" CreationDate="2018-09-10T13:56:58.903" UserId="2041" Text="The most likely explanation is that the game is GPU-bounded and not running at a fixed frame rate. If reducing the quality in the settings allows the game to reach a higher frame rate, the GPU load will be the same, but the CPU load will increase: the CPU is doing the same amount of work per frame (or possibly less), but there are more frames per second, so the total amount of CPU work per second increases. If the game does some non-graphics work per frame as well (for example, if physics updates are at the same rate, or if input is polled once per frame), the effect will be even greater.&#xD;&#xA;&#xD;&#xA;Forcing rendering to a fixed frame-rate would allow a controlled comparison.&#xD;&#xA;&#xD;&#xA;Your hypothesis about software emulation of features may apply to some features in some games. A particular hardware feature might be exposed as an option because it's slow on some GPUs, and turning the feature off uses a CPU implementation in the game instead. If you have more specific questions about that, be sure to ask a new question which includes the source code you're working on and the benchmark results." ContentLicense="CC BY-SA 4.0" />
  <row Id="21276" PostHistoryTypeId="2" PostId="8048" RevisionGUID="88b014b3-b8d5-415f-9b71-5c6c0bb5c7ba" CreationDate="2018-09-10T15:59:17.943" UserId="6588" Text="This approximation is typically done by running a bidirectional path tracer with a modest amount of samples per pixel. This means multiple paths per pixel to approximate $f_j$, the measurement contribution function. [Veach's original MLT paper](https://graphics.stanford.edu/papers/metro/metro.pdf) explains how it can be done in a way that eliminates start-up bias (see Section 5.1)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21277" PostHistoryTypeId="5" PostId="8048" RevisionGUID="4e17e54b-9b20-4ae1-bf68-311b5afe6840" CreationDate="2018-09-10T20:40:33.350" UserId="6588" Comment="added 16 characters in body" Text="This approximation is typically done by running a bidirectional path tracer with a modest amount of samples per pixel. This means multiple paths per pixel to approximate the integral of $f_j$, the measurement contribution function. [Veach's original MLT paper](https://graphics.stanford.edu/papers/metro/metro.pdf) explains how it can be done in a way that eliminates start-up bias (see Section 5.1)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21278" PostHistoryTypeId="5" PostId="8043" RevisionGUID="a3b30e12-2e70-45bd-800a-3019d27c3843" CreationDate="2018-09-11T02:59:56.690" UserId="3073" Comment="added 45 characters in body" Text="This looks like a case of 16bit truncation in your indice buffer. For a 257x257 grid you will be addressing more than 65536 vertices so you will need to use a 32bit indice buffer.&#xD;&#xA;&#xD;&#xA;    gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;change to :&#xD;&#xA;&#xD;&#xA;    gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;Also change your buffer allocation code to match this type (Uint16Array -&gt; Uint32Array for Javascript).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21280" PostHistoryTypeId="34" PostId="7994" RevisionGUID="0d79b8e3-2510-450a-bb0e-e86715ca9f2b" CreationDate="2018-09-11T05:00:45.363" UserId="-1" Comment="49" />
  <row Id="21282" PostHistoryTypeId="50" PostId="7804" RevisionGUID="457e2440-e0d1-4c01-adce-cfb2e4bc14fb" CreationDate="2018-09-11T13:00:51.933" UserId="-1" />
  <row Id="21283" PostHistoryTypeId="2" PostId="8049" RevisionGUID="b3467850-c55f-4b92-9619-01d105dc04f8" CreationDate="2018-09-11T16:03:36.047" UserId="8826" Text="I am reading the percentage closer filtering (PCF) paper by Reeves, W. et al. (https://graphics.pixar.com/library/ShadowMaps/paper.pdf).&#xD;&#xA;&#xD;&#xA;At at section 3.2, it mentioned that &quot;each shading calculation represents some region on a surface&quot;. And &quot;each region to be shaded is mapped to a region in the shadow map&quot;.&#xD;&#xA;&#xD;&#xA;For my understanding, using Opengl fragment shader, for each shading calculation, we just operate on each pixel. We do the shadow calculation on each pixel in the camera image.&#xD;&#xA;&#xD;&#xA;Can anyone explain what does that &quot;region to be shaded&quot; mean? Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="21284" PostHistoryTypeId="1" PostId="8049" RevisionGUID="b3467850-c55f-4b92-9619-01d105dc04f8" CreationDate="2018-09-11T16:03:36.047" UserId="8826" Text="What does &quot;region to be shaded&quot; mean in the PCF paper?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21285" PostHistoryTypeId="3" PostId="8049" RevisionGUID="b3467850-c55f-4b92-9619-01d105dc04f8" CreationDate="2018-09-11T16:03:36.047" UserId="8826" Text="|opengl|shading|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21286" PostHistoryTypeId="5" PostId="8045" RevisionGUID="c5428113-9cef-4784-a812-863b1053f9b1" CreationDate="2018-09-11T18:00:35.210" UserId="9254" Comment="added 823 characters in body" Text="In Metropolis Light Transport, we need to approximate the integral of the measurement contribution function. I've read that this can be done using a traditional approach like path tracing. However, how exactly do we need to implement this approximation?&#xD;&#xA;&#xD;&#xA;I've read the explanation in PBR3, but I still don't understand how this approximation is done exactly.&#xD;&#xA;&#xD;&#xA;More precisely, let's make the following definitions (ignoring rigor): Let $M\subseteq\mathbb R^3$ denote the scene surfaces, $\sigma_M$ denote the surface measure on $M$, $$\Omega_n:=\left\{x\in M^{\mathbb N_0}:x_i\ne x_j\text{ for all }0\le i&lt;j\le n\text{ and }x_N=x_n\text{ for all }N\ge n\right\}$$ $$\iota_n:\Omega_n\to M^{\left\{0,\:\ldots\:,\:n\right\}}\;,\;\;\;x\mapsto(x_0,\ldots,x_n)$$ $$\mu_n(A):=\sigma_M^{\otimes\left\{0,\:\ldots\:,\:n\right\}}(\iota_n(A))\;\;\;\text{for }A\subseteq\Omega_n$$ $$\Omega:=\biguplus_{n\in\mathbb N}\Omega_n$$ $$\mu(A):=\sum_{n=1}^\infty\mu_n(A\cap\Omega_n)\;\;\;\text{for }A\subseteq\Omega$$ Moreover, with the usual notation, let $$T(x_0,\ldots,x_n):=\prod_{i=1}^{n-1}f_r(x_{i+1}\to x_i\to x_{i-1})G(x_i\leftrightarrow x_{i+1})$$ $$f(x):=L_e(x_n\to x_{n-1})T(x_0,\ldots,x_n)\;,\;\;\;\text{if }x\in\Omega_n$$ $$h_j(x):=G(x_0\leftrightarrow x_1)W_e^{(j)}(x_0\to x_1)$$ Then, the measurement $I_j$ of the $j$th pixel is $$I_j=\int fh_j\:{\rm d}\mu.$$&#xD;&#xA;&#xD;&#xA;Now, the question is: How exactly is $$b:=\int f\:{\rm d}\mu$$ approximated using (unidirectional) path tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21287" PostHistoryTypeId="50" PostId="7428" RevisionGUID="d706da68-af24-499a-a423-aca7d4a25495" CreationDate="2018-09-11T18:01:55.047" UserId="-1" />
  <row Id="21291" PostHistoryTypeId="50" PostId="7538" RevisionGUID="0db1a9d2-2f55-49c7-9182-e1ba747c9f4f" CreationDate="2018-09-11T19:01:15.507" UserId="-1" />
  <row Id="21292" PostHistoryTypeId="50" PostId="6180" RevisionGUID="4c4e8f0f-0f22-45fc-85eb-613fd6cf1616" CreationDate="2018-09-11T22:00:54.947" UserId="-1" />
  <row Id="21293" PostHistoryTypeId="2" PostId="8051" RevisionGUID="e3d480de-0d06-4264-b4bf-bcc0dc35c932" CreationDate="2018-09-11T22:34:39.573" UserId="9258" Text="You have a background color and the color of your line, an antialiased line has additional lines drawn on either side of the first that are simply part way between the color and brightness of your origonal line and the background. &#xD;&#xA;&#xD;&#xA;If the line you are drawing is horizontal or vertical the additional antialiasing lines (however many, depending upon the intended resulting line thickness) should be closer in color and brightness to the intended color - there is absolutely minimal antialiasing on such lines, that there is a tiny amount is due to offset [subpixel rendering][1] on ***some*** but not all matrixes.&#xD;&#xA;&#xD;&#xA;This shows the difficulty:&#xD;&#xA;&#xD;&#xA;[![Subpixels Matrix][2]][2]&#xD;&#xA;&#xD;&#xA;When the lines are not horizontal or vertical it gets more complicated ...&#xD;&#xA;&#xD;&#xA;If the additional lines drawn on each side of your line are drawn:&#xD;&#xA;&#xD;&#xA;- with color and brightness more **closely matching the background's color** then your **line remains sharper** and the **background color near your line is fuzzier**.&#xD;&#xA;&#xD;&#xA; or&#xD;&#xA;&#xD;&#xA;- with color and brightness more **closely matching your line's color** then your **line becomes fuzzier** (wider) and the **background color near your line remains sharper**.&#xD;&#xA;&#xD;&#xA;&lt;!-- --&gt;&#xD;&#xA;&#xD;&#xA;1. That means that if you intend to draw a thin line, a single pixel wide line, you would use the first option. (Make the result skinny).&#xD;&#xA;&#xD;&#xA;2. If you want a two pixel wide line you would choose the second option but weigh the color of the background more towards the background's color and brightness. (Make the result not as skinny as a single line, with each of the two additional lines forming almost ~50% of the total width).&#xD;&#xA;&#xD;&#xA;3. If you want a three pixel wide line you still use the second option but would instead weigh the color of the background more towards the line's color and brightness. (Make the result clearly much fatter than a single line).&#xD;&#xA;&#xD;&#xA;4. For a four pixel wide line go back to the first method where you draw two lines of the intended color and brightness surrounded by two lines using the second method, making the two lines wider. (Sort of a blending of the first and second methods)&#xD;&#xA;&#xD;&#xA;5. For five pixel wide lines the center is exactly your intended color, the two nearest surrounding line are very close to the color and brightness of the center line, with the outer two fairly close to the color of the center line (but less than the ones immediately next to the center line)&#xD;&#xA;&#xD;&#xA;6. For a six pixel wide line there are two central lines of the intended drawing color and brightness, surrounded by two very similar lines, surrounded by another two less similar to the central two's color and brightness; but still very different from (lighter or darker) than the background color.&#xD;&#xA;&#xD;&#xA;7. A seven pixel line or greater follows number 5 or 6 above.&#xD;&#xA;&#xD;&#xA;The weighing of the additional lines more towards the intended color gives a sharper line, if you thought of it from a sideview analogy it would be top hat shaped. If you weighed additional lines more towards the background color the  (impossible) sideview analogy is that the profile of the 2D line would be rounded or triangular. If you are drawing 2D shapes it is in your interest to weigh towards the intended color. If you are rendering a 3D shape on a 2D screen then favoring the background color blends towards subsequent lines of a different Z depth.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A **simplistic** but effective algorithm with good speed is the [Xiaolin Wu][3] improvement to Bresenham's line drawing [algorithm to implement antialiasing][4].&#xD;&#xA;&#xD;&#xA;    // Pascal&#xD;&#xA;    function plot(x, y, c) is&#xD;&#xA;        plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1)&#xD;&#xA;    &#xD;&#xA;    // integer part of x&#xD;&#xA;    function ipart(x) is&#xD;&#xA;        return floor(x)&#xD;&#xA;    &#xD;&#xA;    function round(x) is&#xD;&#xA;        return ipart(x + 0.5)&#xD;&#xA;    &#xD;&#xA;    // fractional part of x&#xD;&#xA;    function fpart(x) is&#xD;&#xA;        return x - floor(x)&#xD;&#xA;    &#xD;&#xA;    function rfpart(x) is&#xD;&#xA;        return 1 - fpart(x)&#xD;&#xA;    &#xD;&#xA;    function drawLine(x0,y0,x1,y1) is&#xD;&#xA;        boolean steep := abs(y1 - y0) &gt; abs(x1 - x0)&#xD;&#xA;        &#xD;&#xA;        if steep then&#xD;&#xA;            swap(x0, y0)&#xD;&#xA;            swap(x1, y1)&#xD;&#xA;        end if&#xD;&#xA;        if x0 &gt; x1 then&#xD;&#xA;            swap(x0, x1)&#xD;&#xA;            swap(y0, y1)&#xD;&#xA;        end if&#xD;&#xA;        &#xD;&#xA;        dx := x1 - x0&#xD;&#xA;        dy := y1 - y0&#xD;&#xA;        gradient := dy / dx&#xD;&#xA;        if dx == 0.0 then&#xD;&#xA;            gradient := 1.0&#xD;&#xA;        end if&#xD;&#xA;    &#xD;&#xA;        // handle first endpoint&#xD;&#xA;        xend := round(x0)&#xD;&#xA;        yend := y0 + gradient * (xend - x0)&#xD;&#xA;        xgap := rfpart(x0 + 0.5)&#xD;&#xA;        xpxl1 := xend // this will be used in the main loop&#xD;&#xA;        ypxl1 := ipart(yend)&#xD;&#xA;        if steep then&#xD;&#xA;            plot(ypxl1,   xpxl1, rfpart(yend) * xgap)&#xD;&#xA;            plot(ypxl1+1, xpxl1,  fpart(yend) * xgap)&#xD;&#xA;        else&#xD;&#xA;            plot(xpxl1, ypxl1  , rfpart(yend) * xgap)&#xD;&#xA;            plot(xpxl1, ypxl1+1,  fpart(yend) * xgap)&#xD;&#xA;        end if&#xD;&#xA;        intery := yend + gradient // first y-intersection for the main loop&#xD;&#xA;        &#xD;&#xA;        // handle second endpoint&#xD;&#xA;        xend := round(x1)&#xD;&#xA;        yend := y1 + gradient * (xend - x1)&#xD;&#xA;        xgap := fpart(x1 + 0.5)&#xD;&#xA;        xpxl2 := xend //this will be used in the main loop&#xD;&#xA;        ypxl2 := ipart(yend)&#xD;&#xA;        if steep then&#xD;&#xA;            plot(ypxl2  , xpxl2, rfpart(yend) * xgap)&#xD;&#xA;            plot(ypxl2+1, xpxl2,  fpart(yend) * xgap)&#xD;&#xA;        else&#xD;&#xA;            plot(xpxl2, ypxl2,  rfpart(yend) * xgap)&#xD;&#xA;            plot(xpxl2, ypxl2+1, fpart(yend) * xgap)&#xD;&#xA;        end if&#xD;&#xA;        &#xD;&#xA;        // main loop&#xD;&#xA;        if steep then&#xD;&#xA;            for x from xpxl1 + 1 to xpxl2 - 1 do&#xD;&#xA;               begin&#xD;&#xA;                    plot(ipart(intery)  , x, rfpart(intery))&#xD;&#xA;                    plot(ipart(intery)+1, x,  fpart(intery))&#xD;&#xA;                    intery := intery + gradient&#xD;&#xA;               end&#xD;&#xA;        else&#xD;&#xA;            for x from xpxl1 + 1 to xpxl2 - 1 do&#xD;&#xA;               begin&#xD;&#xA;                    plot(x, ipart(intery),  rfpart(intery))&#xD;&#xA;                    plot(x, ipart(intery)+1, fpart(intery))&#xD;&#xA;                    intery := intery + gradient&#xD;&#xA;               end&#xD;&#xA;        end if&#xD;&#xA;    end function&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Subpixel_rendering&#xD;&#xA;  [2]: https://i.stack.imgur.com/iBhZr.jpg&#xD;&#xA;  [3]: http://www.ece.mcmaster.ca/~xwu/&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="21294" PostHistoryTypeId="2" PostId="8052" RevisionGUID="fe3f873f-2043-4c22-92ce-7b69373dab48" CreationDate="2018-09-12T02:21:51.167" UserId="9334" Text="For example, Filament's documentation at https://google.github.io/filament/Filament.md.html uses the term &quot;dielectrics&quot; when contrasting nonconductors to conductors, which it calls &quot;metallics&quot;. And here on stackexchange, https://computergraphics.stackexchange.com/search?page=2&amp;tab=Relevance&amp;q=dielectric also produces many hits for &quot;dielectric&quot;. I would have normally expected the word &quot;insulator&quot; in these instances. Does &quot;dielectric&quot; stem from some historical source, or is it the accurate term to use?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21295" PostHistoryTypeId="1" PostId="8052" RevisionGUID="fe3f873f-2043-4c22-92ce-7b69373dab48" CreationDate="2018-09-12T02:21:51.167" UserId="9334" Text="Why does graphics speak of &quot;dielectrics&quot; rather than insulators?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21296" PostHistoryTypeId="3" PostId="8052" RevisionGUID="fe3f873f-2043-4c22-92ce-7b69373dab48" CreationDate="2018-09-12T02:21:51.167" UserId="9334" Text="|material|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21301" PostHistoryTypeId="2" PostId="8054" RevisionGUID="96418c08-2f94-4a85-b818-4e1a383024d0" CreationDate="2018-09-12T06:47:09.490" UserId="48" Text="Strictly speaking, dielectrics are not necessarily insulators. For example, salt water is a reasonable conductor but also a dielectric.&#xD;&#xA;&#xD;&#xA;The term &quot;dielectric&quot; tends to show up in discussion of the [Fresnel effect](http://www.graphics.cornell.edu/~westin/misc/fresnel.html)—how reflectance and transmittance vary with angle. Dielectric materials (i.e. nonmetals) are contrasted with metallic materials as they have different Fresnel behavior, which can be traced back to how the materials react on a microscopic scale to the electromagnetic field of an incident light wave.&#xD;&#xA;&#xD;&#xA;So, for computer graphics purposes, the axis &quot;dielectric/metallic&quot; is more relevant than that of &quot;insulator/conductor&quot;, since the former directly affects the appearance of materials." ContentLicense="CC BY-SA 4.0" />
  <row Id="21304" PostHistoryTypeId="2" PostId="8055" RevisionGUID="5ac8df36-ea4a-4d73-b0e8-3e9084b606a5" CreationDate="2018-09-12T14:01:15.550" UserId="9339" Text="I was studying the DDA Algorithm and learnt that initially we calculate both the **x-difference** and the **y-difference** between the start and the end points of the given line, and **if dx &gt; dy**, we choose **xIncrement as 1** and get the successive y- values, **opposite happens when dy &gt; dx**, in that case we choose yIncrement as 1 and **get the successive x-values** using slope of the line, Why do we do that ?&#xD;&#xA;&#xD;&#xA;Is it just that if there are more number of steps, then we get higher accuracy and more definition in our line that is drawn on a Raster display." ContentLicense="CC BY-SA 4.0" />
  <row Id="21305" PostHistoryTypeId="1" PostId="8055" RevisionGUID="5ac8df36-ea4a-4d73-b0e8-3e9084b606a5" CreationDate="2018-09-12T14:01:15.550" UserId="9339" Text="Why the interval for which there are more number of steps is chosen while implementing DDA Algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21306" PostHistoryTypeId="3" PostId="8055" RevisionGUID="5ac8df36-ea4a-4d73-b0e8-3e9084b606a5" CreationDate="2018-09-12T14:01:15.550" UserId="9339" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21308" PostHistoryTypeId="2" PostId="8056" RevisionGUID="2c13f975-f8b9-4712-b0b7-8f998063d2f2" CreationDate="2018-09-12T17:42:20.953" UserId="2654" Text="Texture mapping is the process of providing a mapping from the surface to a location on the texture. That is, given a particular point on a surface, you can find a specific point in a texture that corresponds to it. Giving positions a UV texture coordinate is a common means of defining a texture mapping, but you can use a function of arbitrary complexity.&#xD;&#xA;&#xD;&#xA;Texture mapping is at least theoretically reversible. That is, given a particular texel, you can use the texture mapping to determine where on an object that texel appears. Of course, not every texture mapping *is* reversible. Some mapping cause a texel to be used in multiple locations on a surface, and not every mapping uses every texel in the texture.&#xD;&#xA;&#xD;&#xA;But the important part of the reverse mapping operation is this: a texel maps to some *area* of the surface, not a single point.&#xD;&#xA;&#xD;&#xA;Shadow mapping is a form of texture mapping. It defines a mapping from the scene to a texture by performing perspective projection of the points in the scene onto the surface of a texture, based on a light position.&#xD;&#xA;&#xD;&#xA;If you reverse this mapping, a texel in the shadow map maps to an *area* in the scene. This is the &quot;region in the scene&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="21310" PostHistoryTypeId="2" PostId="8057" RevisionGUID="d7f1dc46-f189-4579-b1f5-3cf1dd4709cb" CreationDate="2018-09-12T18:19:39.690" UserId="56" Text="If you have a dielectric (non metallic) sphere with a large roughness value (say, 0.95), and put it in a lighting environment that has a constant onmidirectional lighting value (such as 0.5) Cook-Torrance ggx PBR renderers seem to be missing a darkening at glancing angles.&#xD;&#xA;&#xD;&#xA;I thought this was a bug in my PBR implementation at first when comparing vs a mitsuba ggx render, but I've found the same issue in google filament (https://github.com/google/filament) as well as in substance.&#xD;&#xA;&#xD;&#xA;For instance, below is the iray version from substance. 0 metalness, 1 roughness, omnidirectional ibl of 0.5, albedo of (1,1,1).&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here is the opengl version:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a known limitation of cook-torrance ggx based PBR? Can anyone explain why this limitation is here, and the reason for the difference?&#xD;&#xA;&#xD;&#xA;I've noticed that it's much closer to the path traced &quot;ground truth&quot; at lower roughness values (like up to around 0.5-0.75), and that the most commonly interesting roughness values are near the lower end of roughness. 0.5 even looks almost &quot;completely rough&quot; for instance.  Is the issue that the approximations used don't really try to make these less important higher roughness values look correct?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RHE6A.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OlZJO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21311" PostHistoryTypeId="1" PostId="8057" RevisionGUID="d7f1dc46-f189-4579-b1f5-3cf1dd4709cb" CreationDate="2018-09-12T18:19:39.690" UserId="56" Text="PBR missing rim darkening on non metallic rough surfaces" ContentLicense="CC BY-SA 4.0" />
  <row Id="21312" PostHistoryTypeId="3" PostId="8057" RevisionGUID="d7f1dc46-f189-4579-b1f5-3cf1dd4709cb" CreationDate="2018-09-12T18:19:39.690" UserId="56" Text="|lighting|shading|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21316" PostHistoryTypeId="5" PostId="8057" RevisionGUID="d3b07e5e-3f0a-4523-baf8-3d64749026ac" CreationDate="2018-09-12T18:26:48.027" UserId="56" Comment="deleted 70 characters in body" Text="If you have a dielectric (non metallic) sphere with a large roughness value (say, 0.95), and put it in a lighting environment that has a constant onmidirectional lighting value (such as 0.5) Cook-Torrance ggx PBR renderers seem to be missing a darkening at glancing angles.&#xD;&#xA;&#xD;&#xA;I thought this was a bug in my PBR implementation at first when comparing vs a mitsuba ggx render, but I've found the same issue in google filament (https://github.com/google/filament) as well as in substance.&#xD;&#xA;&#xD;&#xA;For instance, below is the iray version from substance compared to the opengl version from substance. 0 metalness, 1 roughness, omnidirectional ibl of 0.5, albedo of (1,1,1).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Is this a known limitation of cook-torrance ggx based PBR? Can anyone explain why this limitation is here, and the reason for the difference?&#xD;&#xA;&#xD;&#xA;I've noticed that it's much closer to the path traced &quot;ground truth&quot; at lower roughness values (like up to around 0.5-0.75), and that the most commonly interesting roughness values are near the lower end of roughness. 0.5 even looks almost &quot;completely rough&quot; for instance.  Is the issue that the approximations used don't really try to make these less important higher roughness values look correct?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jMt7C.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21317" PostHistoryTypeId="2" PostId="8059" RevisionGUID="21221842-7260-4ed2-ab0e-6d7139acef7a" CreationDate="2018-09-12T18:44:25.757" UserId="56" Text="The problem is in the diffuse term, which can be seen by making the specular portion of IBL not be added into the result.  The diffuse only render will not have the darkening, and of course, the specular can't make the diffuse darker. (Note, fresnel vs no fresnel is not the issue here).&#xD;&#xA;&#xD;&#xA;The core problem is that lambertian diffuse is being used, which is view independent. There are other view independent diffuse terms which give results closer to the ground truth.&#xD;&#xA;&#xD;&#xA;Two example diffuse terms are Burley (Disney) and Oren-Nayar.&#xD;&#xA;&#xD;&#xA;Burley is talked about here: https://google.github.io/filament/Filament.md.html#toc4.5&#xD;&#xA;&#xD;&#xA;An approach used in Titanfall is described here:&#xD;&#xA;https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX" ContentLicense="CC BY-SA 4.0" />
  <row Id="21318" PostHistoryTypeId="34" PostId="7984" RevisionGUID="2cd4df38-4644-4447-894a-7c3ecf7f6a0c" CreationDate="2018-09-12T19:03:18.210" UserId="-1" Comment="50" />
  <row Id="21319" PostHistoryTypeId="2" PostId="8060" RevisionGUID="ea49c6e1-4524-4f61-89f7-ac2e8aa576e6" CreationDate="2018-09-12T21:03:11.910" UserId="286" Text="This is not related to the edge but in https://eheitzresearch.wordpress.com/240-2/ you can clearly see that energy is lost for the microfacet stuff when roughness is increased. The issue is that the rougher the surface is, the more occlusion you get from the shadowing function.&#xD;&#xA;&#xD;&#xA;There are a few &quot;hacks&quot; to boost the energy. One can be found in http://www.cs.cornell.edu/projects/layered-sg14/ section 5.3. Maybe the rasterized version uses one of these &quot;hacks&quot; and doesn't have that issue.&#xD;&#xA;&#xD;&#xA;Also see 5.1 here https://blog.selfshadow.com/publications/s2015-shading-course/burley/s2015_pbs_disney_bsdf_notes.pdf." ContentLicense="CC BY-SA 4.0" />
  <row Id="21320" PostHistoryTypeId="5" PostId="3969" RevisionGUID="2b6efdd6-2771-4453-9436-c4ba0322a9eb" CreationDate="2018-09-12T22:10:05.627" UserId="4647" Comment="Add a ruler to the spectrum image" Text="I'm trying to get the correct representation of visible spectrum to render on the screen. My current progress is with using CIE 1931 standard observer color matching functions analytically approximated by the equations given in [this paper](http://jcgt.org/published/0002/02/01/). Current image is like this:&#xD;&#xA;&#xD;&#xA;[![current image I could generate][1]][1]&#xD;&#xA;&#xD;&#xA;Here the background is not ideally black to make it possible to introduce the negative contributions from the color matching functions:&#xD;&#xA;&#xD;&#xA;[![color matching functions][2]][2]&#xD;&#xA;&#xD;&#xA;But the problem with it is that the image seems to have a dip in intensity somewhere around 490 nm. I guess that this is related to the sum of the three functions having a minimum there. See the sum plotted against wavelength:&#xD;&#xA;&#xD;&#xA;[![sum of three color matching functions][3]][3]&#xD;&#xA;&#xD;&#xA;So my question is now: how do I fix the intensity of the image? Is there any standard for taking spectral sensitivity into account when converting wavelength to RGB/XYZ representation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/owUVn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/NctGH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/sbazx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21321" PostHistoryTypeId="2" PostId="8061" RevisionGUID="34e9d43a-5f1e-4c19-9327-61c71dfe831d" CreationDate="2018-09-13T10:04:21.327" UserId="9298" Text="I am learning about normal mapping I understood that RGB values converted into XYZ,but my question is **how it is converted, and why the normal map is blue and purple in color ?** " ContentLicense="CC BY-SA 4.0" />
  <row Id="21322" PostHistoryTypeId="1" PostId="8061" RevisionGUID="34e9d43a-5f1e-4c19-9327-61c71dfe831d" CreationDate="2018-09-13T10:04:21.327" UserId="9298" Text="Why normal map is blue and purple in color?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21323" PostHistoryTypeId="3" PostId="8061" RevisionGUID="34e9d43a-5f1e-4c19-9327-61c71dfe831d" CreationDate="2018-09-13T10:04:21.327" UserId="9298" Text="|shader|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21324" PostHistoryTypeId="2" PostId="8062" RevisionGUID="229501fa-8bff-4324-8f0a-46720604b8f9" CreationDate="2018-09-13T10:17:45.383" UserId="3073" Text="Because a normal map is covering vectors from -1 to 1 it makes sense to stretch this range into 0-&gt;1 so all of it can be fit inside the range of RGB.&#xD;&#xA;&#xD;&#xA;So usually we apply a transform on the normal to convert it into something we can see.&#xD;&#xA;&#xD;&#xA;    vec3 colour = vec3(0.5) + normal * 0.5;&#xD;&#xA;&#xD;&#xA;The blue colour  is because normal maps are supposed to be used relative to the primitive (triangle/etc) normal with a default (0,0,1) direction to indicate no deviation from the triangle normal. Usually the fragment shader needs to rotate this normal in relation to the current per-pixel normal at runtime." ContentLicense="CC BY-SA 4.0" />
  <row Id="21325" PostHistoryTypeId="2" PostId="8063" RevisionGUID="bacc3a1d-000a-47f6-b67d-30f14c86d00c" CreationDate="2018-09-13T11:34:35.320" UserId="3331" Text="Only tangent space normal maps are primarily blue. This is because the colour blue represents a normal of (0,0,1) which would be an unchanged normal when the triangle lies in the plane x and y, i.e. perpendicular to the surface. The tangent, x and bi-tangent, y (also referred to as bi-normal) are encoded in the red and green channels and these form to create the a tangent space normal for a point on the surface of the triangle. &#xD;&#xA;&#xD;&#xA;If a tangent space normal map was to encode a colour only in red (1.0, 0.0, 0.0) this would generate a tangent-space normal parallel to the triangle surface. This is never seen because it would mean that the triangle would only ever be lit at 90degrees from the surface and view vector at which point you wouldn't be able to see the triangle anyway.&#xD;&#xA;&#xD;&#xA;World space normal maps encode the unit normal over a sphere so can be primarily different colours once encoded from [-1, 1] to [0, 1] per channel.&#xD;&#xA;&#xD;&#xA;A comparison can be seen here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In practise normal maps are usually encoded in a 2 channel format such as [BC5][2] which actually only stores the x and y with the z being reconstructed as we know it's a unit vector. This allows you to maintain higher precision with more bits without increasing the file size. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mfunv.png&#xD;&#xA;  [2]: http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/#bc2-bc3-and-bc5" ContentLicense="CC BY-SA 4.0" />
  <row Id="21330" PostHistoryTypeId="2" PostId="8065" RevisionGUID="68931286-8e0c-4397-a1ae-04047ea04812" CreationDate="2018-09-13T21:11:54.653" UserId="4647" Text="&gt; I guess that this is related to the sum of the three functions having a minimum there. See the sum plotted against wavelength&#xD;&#xA;&#xD;&#xA;This is actually a wrong way to sum these functions: sRGB model specifies that to get luminosity one must weigh the RGB components with appropriate weights. Then luminosity, unsurprisingly, will become equal to the Y component of the XYZ representation.&#xD;&#xA;&#xD;&#xA;&gt; the problem with it is that the image seems to have a dip in intensity somewhere around 490 nm&#xD;&#xA;&#xD;&#xA;I can actually see the dip not only near 490 nm, but also near 570 nm. Most likely this perception is due to a combination of:&#xD;&#xA;&#xD;&#xA;1. Uncalibrated monitor. After I coarsely calibrated my monitor, the picture seems to have become a bit better to the eye (might be placebo effect though).&#xD;&#xA;2. Being used to fully saturated cyan and yellow representable by the monitor (i.e. `#00ffff` and `#ffff00`). This explains the perception of the dip near 570 nm, where the pure yellow should be and appears instead &quot;dirty yellow&quot;. Similarly, the dip near 490 nm corresponds to the place where pure cyan is expected and instead &quot;dirty cyan&quot;, almost cyanish-gray is observed.&#xD;&#xA;3. Individual deviation from the standard observer. After observing a real spectrum from an incandescent bulb I'm under an impression that the blue dip is also present there. This may be simply wishful thinking though.&#xD;&#xA;&#xD;&#xA;Overall, it seems that the most important of these factors is the 2: dirtiness of cyan and yellow as compared to what I've used to with my monitor. This is corroborated by the fact that both dips I perceive are exactly at the positions where GB/RG components are equal." ContentLicense="CC BY-SA 4.0" />
  <row Id="21332" PostHistoryTypeId="50" PostId="7628" RevisionGUID="d3113209-c26f-4175-9158-6c6e6f26adc4" CreationDate="2018-09-14T00:01:18.653" UserId="-1" />
  <row Id="21339" PostHistoryTypeId="2" PostId="8067" RevisionGUID="61d00508-8897-4a1f-8caf-3281e403c303" CreationDate="2018-09-14T14:53:43.573" UserId="1810" Text="It is not especially related to graphics but physics, and especially, interaction between electromagnetic waves (like light) and matter, i.e. microphysics of optics.&#xD;&#xA;&#xD;&#xA;Metals have free electrons, and thus it's quite a sea of almost free moving charges that are interacting with the EM field. Ideally, it would be totally reflected.&#xD;&#xA;&#xD;&#xA;In dielectrics the electrons are not free, but still the atoms and molecules behave as a non-neutral set of central positive charges (the nucleus) and peripheral negatives charges (the electrons), smoothly locked in position by forces (you might see that as springs), thus the dielectric term (or dipolar in simplest configurations). So, the whole thing reacts to EM waves by distorting, and when restoring (+oscillating) also causes an EM wave emission (since moving charges). Note that it is the interference of these direct and reactive fields that makes the &quot;EM field in the material&quot; with characteristic light velocity, and thus tilt the propagation angle at material border (also named &quot;refraction).&#xD;&#xA;&#xD;&#xA;Thus, the behavior to light is quite different in both cases." ContentLicense="CC BY-SA 4.0" />
  <row Id="21340" PostHistoryTypeId="2" PostId="8068" RevisionGUID="856ae0b3-987c-4608-a197-b9b2636c6781" CreationDate="2018-09-14T14:54:57.093" UserId="9359" Text="Given point-cloud data :&#xD;&#xA;&#xD;&#xA;For example. &#xD;&#xA;position + color and normal.&#xD;&#xA;&#xD;&#xA;What will you use to generate mesh of this data &#xD;&#xA;and keep reasonable quality for real time cases ? &#xD;&#xA;&#xD;&#xA;Any inputs are welcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="21341" PostHistoryTypeId="1" PostId="8068" RevisionGUID="856ae0b3-987c-4608-a197-b9b2636c6781" CreationDate="2018-09-14T14:54:57.093" UserId="9359" Text="Generate mesh from pointcloud data" ContentLicense="CC BY-SA 4.0" />
  <row Id="21342" PostHistoryTypeId="3" PostId="8068" RevisionGUID="856ae0b3-987c-4608-a197-b9b2636c6781" CreationDate="2018-09-14T14:54:57.093" UserId="9359" Text="|3d|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21343" PostHistoryTypeId="2" PostId="8069" RevisionGUID="d1aa13a8-77f6-4ef9-816c-d2efa8c3174b" CreationDate="2018-09-14T15:11:34.273" UserId="8394" Text="Because you are working on screen space, the view ray points towards the eye (being Z the camera space depth). In order to create an orthonormal base, the vectors must be perpendicular to each other. To do this, you set the coordinate z to 0 for the tangents and bitangets, which ensures these vectors will live in the plane perpendicular to the view ray. &#xD;&#xA;&#xD;&#xA;Lastly, you need to make the tangent and bitangent perpendicular to each other, which is accomplished with this&#xD;&#xA;&#xD;&#xA;    vec3 tangent = normalize(rvec - normal * dot(rvec, normal));&#xD;&#xA;    vec3 bitangent = cross(normal, tangent);" ContentLicense="CC BY-SA 4.0" />
  <row Id="21344" PostHistoryTypeId="5" PostId="8068" RevisionGUID="388e1bc3-9668-4487-a5c3-572c12859a28" CreationDate="2018-09-14T15:37:10.400" UserId="9359" Comment="added 205 characters in body" Text="Given point-cloud data :&#xD;&#xA;For example. &#xD;&#xA;position + color and normal.&#xD;&#xA;&#xD;&#xA;What will you use to generate mesh of this data &#xD;&#xA;and keep reasonable quality for real time cases ? &#xD;&#xA;&#xD;&#xA;Additional info to consider:&#xD;&#xA;&#xD;&#xA; 1. In some cases given also&#xD;&#xA;    3D cameras transforms which generated the PCL.&#xD;&#xA;&#xD;&#xA; 2. Number of input vertices : ~50k and up to millions .&#xD;&#xA;&#xD;&#xA; 3. Target latency from input to output : &lt; 40ms&#xD;&#xA;&#xD;&#xA; 4. Output triangle mesh (preferably not a must) &#xD;&#xA;&#xD;&#xA;Any inputs are welcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="21345" PostHistoryTypeId="5" PostId="8068" RevisionGUID="894dedd5-dbac-4a17-a92d-590f4dcff59a" CreationDate="2018-09-14T15:55:42.540" UserId="9359" Comment="added 6 characters in body" Text="Given point-cloud data :&#xD;&#xA;For example. &#xD;&#xA;position + color and normal.&#xD;&#xA;&#xD;&#xA;What will you use to generate mesh of this data &#xD;&#xA;and keep reasonable quality for real time cases ? &#xD;&#xA;&#xD;&#xA;Additional info to consider:&#xD;&#xA;&#xD;&#xA; 1. In some cases given also&#xD;&#xA;    3D cameras world transforms which generated the PCL.&#xD;&#xA;&#xD;&#xA; 2. Number of input vertices : ~50k and up to millions .&#xD;&#xA;&#xD;&#xA; 3. Target latency from input to output : &lt; 40ms&#xD;&#xA;&#xD;&#xA; 4. Output triangle mesh (preferably not a must) &#xD;&#xA;&#xD;&#xA;Any inputs are welcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="21346" PostHistoryTypeId="50" PostId="7643" RevisionGUID="b660d69b-e866-4c0a-9518-e51cf2df329f" CreationDate="2018-09-14T22:00:39.880" UserId="-1" />
  <row Id="21348" PostHistoryTypeId="2" PostId="8070" RevisionGUID="7d5249bd-4a7f-4c97-9231-a54e23c4f27a" CreationDate="2018-09-15T00:11:56.263" UserId="8394" Text="You can render with a raymarcher and using distance fields. For the hat you would define the center and radius of the cylinder, and would draw any march which falls within such circle, no matter what &quot;height&quot; you are in, it will be infinite. You can also add a restriction, like y &gt; 0 to put a beginning to your hat." ContentLicense="CC BY-SA 4.0" />
  <row Id="21349" PostHistoryTypeId="5" PostId="8055" RevisionGUID="52e44b64-c1e0-4ca8-8c50-676bd0568864" CreationDate="2018-09-15T12:41:06.050" UserId="6" Comment="added 6 characters in body" Text="I was studying the DDA Algorithm and learnt that initially we calculate both the **x-difference** and the **y-difference** between the start and the end points of the given line, and **if dx &gt; dy**, we choose **xIncrement as 1** and get the successive y-values. The **opposite happens when dy &gt; dx**, in that case we choose yIncrement as 1 and **get the successive x-values** using the slope of the line. Why do we do that?&#xD;&#xA;&#xD;&#xA;Is it just that if there are more number of steps, then we get higher accuracy and more definition in our line that is drawn on a raster display?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21350" PostHistoryTypeId="5" PostId="4632" RevisionGUID="0d99966d-fa03-4adb-a41a-080e16d36b4e" CreationDate="2018-09-15T12:48:25.543" UserId="2287" Comment="formatting" Text="I'm creating a renderer using modern OpenGL (3.1 and up) and now I'm trying to create an efficient but flexible way of handling uniforms. I've been reading up on uniform buffer objects and on what a 'common' approach is to using these (the latter unfortunately didn't give me as many results as I had hoped).&#xD;&#xA;&#xD;&#xA;In order to reduce OpenGL API calls and storing data in contiguous memory, I'm considering creating multiple large buffers for each data structure that should be uploaded to the GPU. Each buffer has a maximum size of 16kb (as from what I understand this much is guaranteed to be available for an UBO). When an object wants to be able to upload uniforms to the GPU it fetches the first buffer of the to-be-uploaded-type that isn't full yet and gets the next available index in that buffer. When the object is drawn it binds the UBO (if not bound yet) and uploads the element index of the UBO.&#xD;&#xA;&#xD;&#xA;This results in something like this:&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform ModelData { &#xD;&#xA;        mat4 model_matrix[kNumInstancesPerModelUbo]; &#xD;&#xA;    }&#xD;&#xA;    uniform int u_ModelDataIndex;&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform SkeletonData { &#xD;&#xA;        mat4 bone_transforms[kNumInstancesPerSkeletonUbo][kMaxBones]; &#xD;&#xA;    }&#xD;&#xA;    uniform int u_SkeletonDataIndex;&#xD;&#xA;&#xD;&#xA;However I'm also considering the following:&#xD;&#xA;&#xD;&#xA;    layout(std140) uniform MeshData {&#xD;&#xA;        mat4 model_matrix[kNumInstancesPerMeshUbo];&#xD;&#xA;        mat4 bone_transforms[kNumInstancesPerMeshUbo][kMaxBones];&#xD;&#xA;    }&#xD;&#xA;    uniform int u_MeshDataIndex;&#xD;&#xA;&#xD;&#xA;In some ways this feels a lot cleaner in that it takes a single index to access all data related to the mesh to be uploaded. On the other hand this could get out of hand (buffer size larger than 16kb, handles to irrelevant data (e.g. a mesh with no skeleton) or even synchronization issues as you're not allowed access to say the bones while uploading the model matrices) and I'm not sure how this would affect the memory layout on the GPU either.&#xD;&#xA;&#xD;&#xA;Frankly it feels like I'm stuck here and I can't find a good concrete example of how you'd go about handling UBO's fast and flexible. &#xD;&#xA;&#xD;&#xA;Do you have any advice or resources for me that could help me out here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21351" PostHistoryTypeId="24" PostId="4632" RevisionGUID="0d99966d-fa03-4adb-a41a-080e16d36b4e" CreationDate="2018-09-15T12:48:25.543" Comment="Proposed by 2287 approved by 209, 6 edit id of 438" ContentLicense="CC BY-SA 4.0" />
  <row Id="21352" PostHistoryTypeId="5" PostId="8068" RevisionGUID="c23d232e-7d9e-434e-a97a-f1f3c069ace1" CreationDate="2018-09-15T17:08:59.167" UserId="9359" Comment="added 152 characters in body" Text="Given point-cloud data :&#xD;&#xA;For example. &#xD;&#xA;position + color and normal.&#xD;&#xA;&#xD;&#xA;What will you use to generate mesh of this data &#xD;&#xA;and keep reasonable quality for real time cases ? &#xD;&#xA;&#xD;&#xA;Additional info to consider:&#xD;&#xA;&#xD;&#xA; 1. In some cases given also&#xD;&#xA;    3D cameras world transforms which generated the PCL.&#xD;&#xA;&#xD;&#xA; 2. Number of input vertices : ~50k and up to millions .&#xD;&#xA;&#xD;&#xA; 3. Target latency from input to output : &lt; 40ms&#xD;&#xA;&#xD;&#xA; 4. Output triangle mesh (preferably not a must) &#xD;&#xA;&#xD;&#xA;Any inputs are welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;FAQ:&#xD;&#xA;&#xD;&#xA;How the data look like ?&#xD;&#xA;&#xD;&#xA; - Float* Position  [x1,y1,z1,x2,y2,z2...]&#xD;&#xA; - Float* Normal    [nx1,ny1,nz1,nx2,ny2,nz2...]&#xD;&#xA; - float or int8 for the color." ContentLicense="CC BY-SA 4.0" />
  <row Id="21353" PostHistoryTypeId="5" PostId="8068" RevisionGUID="fadaacba-9898-4419-b329-66c86a19c972" CreationDate="2018-09-15T17:21:52.297" UserId="9359" Comment="added 93 characters in body" Text="Given point-cloud data :&#xD;&#xA;For example. &#xD;&#xA;position + color and normal.&#xD;&#xA;&#xD;&#xA;What will you use to generate mesh of this data &#xD;&#xA;and keep reasonable quality for real time cases ? &#xD;&#xA;&#xD;&#xA;Additional info to consider:&#xD;&#xA;&#xD;&#xA; 1. In some cases given also&#xD;&#xA;    3D cameras world transforms which generated the PCL.&#xD;&#xA;&#xD;&#xA; 2. Number of input vertices : ~50k and up to millions .&#xD;&#xA;&#xD;&#xA; 3. Target latency from input to output : &lt; 40ms&#xD;&#xA;&#xD;&#xA; 4. Output triangle mesh (preferably not a must) &#xD;&#xA;&#xD;&#xA; 5. More info about mesh reconstruction  &#xD;&#xA;    http://www.cs.utah.edu/~bergerm/recon_bench/&#xD;&#xA;&#xD;&#xA;Any inputs are welcome.  &#xD;&#xA;FAQ:&#xD;&#xA;&#xD;&#xA;How the data look like ?&#xD;&#xA;&#xD;&#xA; - Float* Position  [x1,y1,z1,x2,y2,z2...]&#xD;&#xA; - Float* Normal    [nx1,ny1,nz1,nx2,ny2,nz2...]&#xD;&#xA; - float or int8 for the color." ContentLicense="CC BY-SA 4.0" />
  <row Id="21354" PostHistoryTypeId="50" PostId="6012" RevisionGUID="8ffdede8-4a56-4744-997d-a40450d9537a" CreationDate="2018-09-15T19:00:13.127" UserId="-1" />
  <row Id="21355" PostHistoryTypeId="2" PostId="8071" RevisionGUID="7f3246c5-6496-4966-a1ae-c872217a4f80" CreationDate="2018-09-16T06:14:58.727" UserId="9366" Text="1. one popular Real time surface reconstruction method is TSDF (Truncated Signed Distance Function) used by Microsoft for the Kinect. It is based on the VRIP method but it is faster. It is based on depth maps from different (known) camera positions. &#xD;&#xA;you can read more:&#xD;&#xA;    https://cs.nyu.edu/courses/fall12/CSCI-GA.2945-001/dl/jiakai-slides.pdf&#xD;&#xA;    file:///C:/Users/chaim.dryzun/Downloads/kinectfusion.pdf&#xD;&#xA;&#xD;&#xA;2. From the methods in the reference you gave the fastest is Wavelet based surface reconstruction. If the overall point cloud is good and regular (uniform point density) and without holes and the normals are correct than it gives a very good mesh in a short time.&#xD;&#xA;&#xD;&#xA;3. A more robust and popular method is the Poisson based surface reconstruction. You will need the normals. It gives very good mesh although it takes more time.&#xD;&#xA;&#xD;&#xA;4. Another good method is the PowerCrust surface reconstruction method. It gives very good and accurate mesh, and it does not need the normals. This method produces a polygonal mesh and not triangular mesh, but it is very easy to transform it to triangular. The original code is very slow, but as it is based on calculating Voronoi cells - you can easily re-write it so it will run much faster.&#xD;&#xA;You can read more: &#xD;&#xA;    http://web.cs.ucdavis.edu/~amenta/powercrust.html&#xD;&#xA;&#xD;&#xA;5. Regarding the time, working with million of points will take much more than 40 ms, no matter which method you choose (except maybe TSDF). You will have to downsample the point cloud before meshing.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21356" PostHistoryTypeId="50" PostId="5996" RevisionGUID="67ce674f-b0c7-445f-8e8d-81eca6430d49" CreationDate="2018-09-16T09:00:49.507" UserId="-1" />
  <row Id="21357" PostHistoryTypeId="50" PostId="7529" RevisionGUID="4ad6614f-e1fd-419b-9ff1-cabaab48fd7e" CreationDate="2018-09-16T21:00:49.750" UserId="-1" />
  <row Id="21359" PostHistoryTypeId="50" PostId="7633" RevisionGUID="90a6b448-cce9-4559-be40-511e41d9412a" CreationDate="2018-09-17T07:00:05.297" UserId="-1" />
  <row Id="21361" PostHistoryTypeId="2" PostId="8072" RevisionGUID="23d40a48-76bf-4d89-8879-c57a96441333" CreationDate="2018-09-17T13:05:18.060" UserId="6046" Text="This isn't a pure CG question but it's more of a programming one related to CG. &#xD;&#xA;&#xD;&#xA;The main problem that occurs is both the GUI and the rendered scene need to be drawn regularly by swapping buffers. If the rendering of the scene takes much longer say 5 or 6 FPS, then if the GUI is drawn together with this scene it wouldn't be responsive and lag a lot.&#xD;&#xA;&#xD;&#xA;In order to overcome this problem we could make the path tracer render an image in a separate thread and the GUI in the main one. However this still doesn't solve the problem since we only have 1 window, we need to `swapbuffers` in order to display both the GUI as well as the rendered scene. Let's say we swapbuffers in the main thread using this logic...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    render_thread.start();  // render thread sets a flag when it finishes generating an image. This flag is accessible to the main gui thread.&#xD;&#xA;    while(window_open)&#xD;&#xA;    {&#xD;&#xA;       glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;       if(image_generated)  // flag set by the render thread.&#xD;&#xA;           draw_image();&#xD;&#xA;       draw_GUI();&#xD;&#xA;       swapbuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However here the `glClear()` call will clear our rendered scene if the render_thread doesn't finish in time. So basically we need a form of a layered framebuffer where we can clear and draw the top layer separately. Afaik this maybe done through overlay planes but i think those are platform specific?&#xD;&#xA;&#xD;&#xA;So I have 2 or 3 solutions in mind but I don't know what's the standard people or most softwares follow. If anybody can guide me I'd appreciate it.&#xD;&#xA;&#xD;&#xA; 1.  You use multiple windows, possibly the render window being embedded into the GUI window as a subset. The GUI window would be transparent everywhere except the GUI widgets (menu bars etc) leaving the space for the render window to display whatever.&#xD;&#xA;&#xD;&#xA; 2.  You use the same window but use Scissor tests to clear only the part of the window covered by the menu and redraw the menu again. This sounds nice but provides problem when for example a dropbox covers the rendered scene or when using transparent Widgets.&#xD;&#xA;&#xD;&#xA; 3. You save your rendered scene in a texture. Re-draw this texture and&#xD;&#xA;    then the GUI over the top until the render thread gives us a new&#xD;&#xA;    image. The snipped above then would look like,&#xD;&#xA;    &#xD;&#xA;        render_thread.start();  // render thread sets a flag when it finishes generating an image. This flag is accessible to the main gui thread.&#xD;&#xA;        while(window_open)&#xD;&#xA;        {&#xD;&#xA;           glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;           if(image_generated)  // flag set by the render thread.&#xD;&#xA;           {&#xD;&#xA;               draw_image();&#xD;&#xA;               save image in a texture;&#xD;&#xA;           }&#xD;&#xA;           else&#xD;&#xA;              Re-draw the saved texture;&#xD;&#xA;           draw_GUI();&#xD;&#xA;           swapbuffers();&#xD;&#xA;           sleep(33.33ms) // sleep for 33ms which equals 30FPS. If the render thread finishes in less than 33ms (&gt; 30FPS) than we don't need to re-draw the saved texture.&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; 4. Option 3 could be done through blitting as well. Since I'm using an&#xD;&#xA;    FBO and two RBOs (will explain later why). The snippet would look&#xD;&#xA;    like this.&#xD;&#xA;    &#xD;&#xA;        render_thread.start();  // render thread sets a flag when it finishes generating an image. This flag is accessible to the main gui thread.&#xD;&#xA;        while(window_open)&#xD;&#xA;        {&#xD;&#xA;           glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;           if(image_generated)  // flag set by the render thread.&#xD;&#xA;           {&#xD;&#xA;               draw_image();&#xD;&#xA;               save handle to RBO that has the image.&#xD;&#xA;           }&#xD;&#xA;           else&#xD;&#xA;             Blit from the saved RBO to default framebuffer.&#xD;&#xA;           draw_GUI();&#xD;&#xA;           swapbuffers();&#xD;&#xA;           sleep(33.33ms) // sleep for 33ms which equals 30FPS. If the render thread finishes in less than 33ms (&gt; 30FPS) than we don't need to blit again.&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Options 3 and 4 seem to do the job. Is there any other method it's done?&#xD;&#xA;&#xD;&#xA;As for why am I using 2 RBOs, I'm actually using OpenCL-OpenGL interop. So in OpenCL 1.1, need two Image objects (since we can't read/write to 1) for taking average with the previous frame (that's how it will converge). These two Image objects are wrapped around OpenGL's RBOs. Hence in option 4. when the render thread has finished I will save the handle to the RBO which currently has the image. For details on what libraries I'm using, (GLFW for windowing and nanogui for widgets).&#xD;&#xA;&#xD;&#xA;For more details on how the path tracer is setup you can read this problem which I was having earlier.&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/7966/path-tracer-isnt-converging" ContentLicense="CC BY-SA 4.0" />
  <row Id="21362" PostHistoryTypeId="1" PostId="8072" RevisionGUID="23d40a48-76bf-4d89-8879-c57a96441333" CreationDate="2018-09-17T13:05:18.060" UserId="6046" Text="How to handle GUI in a path traced renderer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21363" PostHistoryTypeId="3" PostId="8072" RevisionGUID="23d40a48-76bf-4d89-8879-c57a96441333" CreationDate="2018-09-17T13:05:18.060" UserId="6046" Text="|pathtracing|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21364" PostHistoryTypeId="5" PostId="8072" RevisionGUID="5b3df8ba-3266-4449-9be7-1c4db05badae" CreationDate="2018-09-17T13:48:26.260" UserId="6046" Comment="added 140 characters in body" Text="This isn't a pure CG question but it's more of a programming one related to CG. &#xD;&#xA;&#xD;&#xA;The main problem that occurs is both the GUI and the rendered scene need to be drawn regularly by swapping buffers. If the rendering of the scene takes much longer say 5 or 6 FPS, then if the GUI is drawn together with this scene it wouldn't be responsive and lag a lot.&#xD;&#xA;&#xD;&#xA;In order to overcome this problem we could make the path tracer render an image in a separate thread and the GUI in the main one. However this still doesn't solve the problem since we only have 1 window, we need to `swapbuffers` in order to display both the GUI as well as the rendered scene. Let's say we swapbuffers in the main thread using this logic...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    render_thread.start();  // render thread sets a flag when it finishes generating an image. This flag is accessible to the main gui thread.&#xD;&#xA;    while(window_open)&#xD;&#xA;    {&#xD;&#xA;       glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;       if(image_generated)  // flag set by the render thread.&#xD;&#xA;           draw_image();&#xD;&#xA;       draw_GUI();&#xD;&#xA;       swapbuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However here the `glClear()` call will clear our rendered scene if the render_thread doesn't finish in time. So basically we need a form of a layered framebuffer where we can clear and draw the top layer separately. Afaik this maybe done through overlay planes but i think those are platform specific?&#xD;&#xA;&#xD;&#xA;So I have 2 or 3 solutions in mind but I don't know what's the standard people or most softwares follow. If anybody can guide me I'd appreciate it.&#xD;&#xA;&#xD;&#xA; 1.  You use multiple windows, possibly the render window being embedded into the GUI window as a subset. The GUI window would be transparent everywhere except the GUI widgets (menu bars etc) leaving the space for the render window to display whatever.&#xD;&#xA;&#xD;&#xA; 2.  You use the same window but use Scissor tests to clear only the part of the window covered by the menu and redraw the menu again. This sounds nice but provides problem when for example a dropbox covers the rendered scene or when using transparent Widgets.&#xD;&#xA;&#xD;&#xA; 3. You save your rendered scene in a texture. Re-draw this texture and&#xD;&#xA;    then the GUI over the top until the render thread gives us a new&#xD;&#xA;    image. The snipped above then would look like,&#xD;&#xA;    &#xD;&#xA;        render_thread.start();  // render thread sets a flag when it finishes generating an image. This flag is accessible to the main gui thread.&#xD;&#xA;        while(window_open)&#xD;&#xA;        {&#xD;&#xA;           glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;           if(image_generated)  // flag set by the render thread.&#xD;&#xA;           {&#xD;&#xA;               draw_image();&#xD;&#xA;               save image in a texture;&#xD;&#xA;           }&#xD;&#xA;           else&#xD;&#xA;              Re-draw the saved texture;&#xD;&#xA;           draw_GUI();&#xD;&#xA;           swapbuffers();&#xD;&#xA;           sleep(33.33ms) or until render_thread finishes // sleep either for 33ms which equals 30FPS or till render thread finishes. If the render thread finishes in less than 33ms (&gt; 30FPS) than we don't need to re-draw the saved texture.&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; 4. Option 3 could be done through blitting as well. Since I'm using an&#xD;&#xA;    FBO and two RBOs (will explain later why). The snippet would look&#xD;&#xA;    like this.&#xD;&#xA;    &#xD;&#xA;        render_thread.start();  // render thread sets a flag when it finishes generating an image. This flag is accessible to the main gui thread.&#xD;&#xA;        while(window_open)&#xD;&#xA;        {&#xD;&#xA;           glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;           if(image_generated)  // flag set by the render thread.&#xD;&#xA;           {&#xD;&#xA;               draw_image();&#xD;&#xA;               save handle to RBO that has the image.&#xD;&#xA;           }&#xD;&#xA;           else&#xD;&#xA;             Blit from the saved RBO to default framebuffer.&#xD;&#xA;           draw_GUI();&#xD;&#xA;           swapbuffers();&#xD;&#xA;           sleep(33.33ms) or until render_thread finishes // sleep either for 33ms which equals 30FPS or till render thread finishes. If the render thread finishes in less than 33ms (&gt; 30FPS) than we don't need to blit again.&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Options 3 and 4 seem to do the job. Is there any other method it's done?&#xD;&#xA;&#xD;&#xA;As for why am I using 2 RBOs, I'm actually using OpenCL-OpenGL interop. So in OpenCL 1.1, need two Image objects (since we can't read/write to 1) for taking average with the previous frame (that's how it will converge). These two Image objects are wrapped around OpenGL's RBOs. Hence in option 4. when the render thread has finished I will save the handle to the RBO which currently has the image. For details on what libraries I'm using, (GLFW for windowing and nanogui for widgets).&#xD;&#xA;&#xD;&#xA;For more details on how the path tracer is setup you can read this problem which I was having earlier.&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/7966/path-tracer-isnt-converging" ContentLicense="CC BY-SA 4.0" />
  <row Id="21365" PostHistoryTypeId="2" PostId="8073" RevisionGUID="b8484f72-08d4-4396-a704-923f20de2b5f" CreationDate="2018-09-17T14:20:29.150" UserId="7013" Text="[![Sample scenario][1]][1]&#xD;&#xA;&#xD;&#xA;Given point sets $Y$ and $M$, I'd like to register articulated $M$ to $Y$ without changing the edge distances of $M$. The point correspondences between $Y$ and $M$ are known and points have a fixed connectivity map.&#xD;&#xA;&#xD;&#xA;As you can see from the above sample, the edge distances of $Y$ are corrupted, and I'd like to correct them using $M$ while sacrificing some localization precision.&#xD;&#xA;&#xD;&#xA;I know ICP and RANSAC algorithms, but none of them solve the articulation problem. I'm looking for any kind of algorithms that can solve this articulated body registration problem.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PHONR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21366" PostHistoryTypeId="1" PostId="8073" RevisionGUID="b8484f72-08d4-4396-a704-923f20de2b5f" CreationDate="2018-09-17T14:20:29.150" UserId="7013" Text="How can I register an articulated model to noisy predictions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21367" PostHistoryTypeId="3" PostId="8073" RevisionGUID="b8484f72-08d4-4396-a704-923f20de2b5f" CreationDate="2018-09-17T14:20:29.150" UserId="7013" Text="|transformations|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21368" PostHistoryTypeId="2" PostId="8074" RevisionGUID="c1896367-3452-4917-b4b0-4ca7f761874f" CreationDate="2018-09-17T14:24:44.067" UserId="8826" Text="This is a simple question.&#xD;&#xA;&#xD;&#xA;I know that in OpenGL or other graphics API, the values stored in the depth buffer are automatically clamped to (0,1).&#xD;&#xA;&#xD;&#xA;I just want to know why people do this instead of just keeping the actual depth values as float. Is that just because of the non-linear depth equation which makes the closer depth values more precise and the further depth values less precies?&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="21369" PostHistoryTypeId="1" PostId="8074" RevisionGUID="c1896367-3452-4917-b4b0-4ca7f761874f" CreationDate="2018-09-17T14:24:44.067" UserId="8826" Text="Why the depth values are clamped to (0, 1)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21370" PostHistoryTypeId="3" PostId="8074" RevisionGUID="c1896367-3452-4917-b4b0-4ca7f761874f" CreationDate="2018-09-17T14:24:44.067" UserId="8826" Text="|opengl|shader|depth-map|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21371" PostHistoryTypeId="2" PostId="8075" RevisionGUID="02ab982d-5799-418b-a12e-30bd7b174bb5" CreationDate="2018-09-17T22:13:52.920" UserId="9372" Text="A few years ago I started creating a procedural planet engine/renderer for a game in Unity, which after a couple of years I had to stop developing due to lack of time. At the time i didn't know too much about shaders so I did everything on the CPU. Now that I have plenty of time and am more aware of what shaders can do I'd like to resume development with the GPU in mind.&#xD;&#xA;&#xD;&#xA;For the terrain mesh I'm using a cubed-sphere and chunked LODs. The way I calculate heights is rather complex since it's based on a noise tree, which is created from an artist/designer-provided XML for each main planet/asteroid. Leaf nodes in the tree would be noise generators like Simplex, Value, Sine, Voronoi, etc. while branch nodes would be filters and modifiers (FBM, abs, neg, sum, ridged, billow, blender, selectors, etc). &#xD;&#xA;&#xD;&#xA;To calculate the heights for a mesh you'd call void CalcHeights( Vector3[] meshVertices, out float[] heights ) on the noise's root node, somewhere in the game code.&#xD;&#xA;&#xD;&#xA;This approach offers a lot of flexibility but also introduces a lot of load in the CPU. The first obvious thing to do would be (I guess) to move all generators to the GPU via compute shaders, then do the same for the rest of the filters. But, depending on the complexity of the noise tree, a single call to CalcHeights could potentially cause dozens of calls back and forth between the CPU and GPU, which I'm not sure it's a good thing.&#xD;&#xA;&#xD;&#xA;How should I go about this?&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="21372" PostHistoryTypeId="1" PostId="8075" RevisionGUID="02ab982d-5799-418b-a12e-30bd7b174bb5" CreationDate="2018-09-17T22:13:52.920" UserId="9372" Text="Procedural terrain: What's the best approach to calculate noise in the GPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21373" PostHistoryTypeId="3" PostId="8075" RevisionGUID="02ab982d-5799-418b-a12e-30bd7b174bb5" CreationDate="2018-09-17T22:13:52.920" UserId="9372" Text="|gpu|compute-shader|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21374" PostHistoryTypeId="5" PostId="8075" RevisionGUID="635e59da-d267-44c9-aad0-709ddbfe5693" CreationDate="2018-09-18T07:51:32.623" UserId="9372" Comment="added 84 characters in body" Text="A few years ago I started creating a procedural planet engine/renderer for a game in Unity, which after a couple of years I had to stop developing due to lack of time. At the time i didn't know too much about shaders so I did everything on the CPU. Now that I have plenty of time and am more aware of what shaders can do I'd like to resume development with the GPU in mind.&#xD;&#xA;&#xD;&#xA;For the terrain mesh I'm using a cubed-sphere and chunked LODs. Since terrain never changes, heights for each chunk need to be calculated just once.The way I calculate heights is rather complex since it's based on a noise tree, which is created from an artist/designer-provided XML for each main planet/asteroid. Leaf nodes in the tree would be noise generators like Simplex, Value, Sine, Voronoi, etc. while branch nodes would be filters and modifiers (FBM, abs, neg, sum, ridged, billow, blender, selectors, etc). &#xD;&#xA;&#xD;&#xA;To calculate the heights for a mesh you'd call void CalcHeights( Vector3[] meshVertices, out float[] heights ) on the noise's root node, somewhere in the game code.&#xD;&#xA;&#xD;&#xA;This approach offers a lot of flexibility but also introduces a lot of load in the CPU. The first obvious thing to do would be (I guess) to move all generators to the GPU via compute shaders, then do the same for the rest of the filters. But, depending on the complexity of the noise tree, a single call to CalcHeights could potentially cause dozens of calls back and forth between the CPU and GPU, which I'm not sure it's a good thing.&#xD;&#xA;&#xD;&#xA;How should I go about this?&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="21375" PostHistoryTypeId="2" PostId="8076" RevisionGUID="9fb795a8-e14a-4851-8a70-f7704e38fd85" CreationDate="2018-09-18T08:36:03.673" UserId="209" Text="(Just converting comment into an answer)&#xD;&#xA;It seems you might be asking one of two possible questions.&#xD;&#xA;&#xD;&#xA;If you meant *&quot;Why doesn't the Depth buffer contain camera space Z&quot;*&#xD;&#xA;&lt;br&gt;then it's perhaps worth reading https://computergraphics.stackexchange.com/questions/8017/why-do-gpus-divide-clip-space-z-by-w-for-position] &#xD;&#xA;&#xD;&#xA;If, OTOH, you just meant *&quot;why is it restricted to [0,1)?&quot;*, then that's *probably* because old systems represented the Z-buffer depth with fixed point numbers, hence a natural [0,1) range.&lt;br&gt;&lt;br&gt;&#xD;&#xA; Of course, later hardware arrived that could use floating-point depths; IIRC Dreamcast's depth representation was an arbitrary positive float." ContentLicense="CC BY-SA 4.0" />
  <row Id="21376" PostHistoryTypeId="5" PostId="8076" RevisionGUID="61cb2937-10a4-4bf8-a7a6-628643f2f5b7" CreationDate="2018-09-18T09:41:27.240" UserId="209" Comment="added 27 characters in body" Text="(Just converting comment into an answer)&#xD;&#xA;It seems you might be asking one of two possible questions.&#xD;&#xA;&#xD;&#xA;If you meant *&quot;Why doesn't the Depth buffer contain camera space Z&quot;*&#xD;&#xA;&lt;br&gt;then it's perhaps worth reading https://computergraphics.stackexchange.com/questions/8017/why-do-gpus-divide-clip-space-z-by-w-for-position] &#xD;&#xA;&#xD;&#xA;If, OTOH, you just meant *&quot;why is it restricted to [0,1)?&quot;*, then that's *probably* because old systems represented the Z-buffer depth with fixed point numbers, hence a natural [0,1) range.&lt;br&gt;&lt;br&gt;&#xD;&#xA; Of course, later hardware arrived that could use floating-point depths; IIRC Dreamcast's depth representation was an arbitrary positive float representing $\frac{1}{w}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="21377" PostHistoryTypeId="4" PostId="8074" RevisionGUID="f5f6cfec-22b3-4f0d-bd3d-d45e1df4d7ac" CreationDate="2018-09-18T09:45:54.190" UserId="209" Comment="Tried to make question a little clearer" Text="Why are depth buffer values clamped to (0, 1)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21378" PostHistoryTypeId="2" PostId="8077" RevisionGUID="65bbe0d3-6ad5-4d39-b983-c18b7f2d2b09" CreationDate="2018-09-18T15:10:42.047" UserId="6046" Text="Turns out I was an effin idiot. I didn't need to use multithreading or whatsoever. Since the main path tracer work is executing in the kernel, I don't need to wait for the kernel to finish right after call to `EnqueueKernel` by using `clFinish()` instead, I can tell opencl to set the flag when kernel finishes. &#xD;&#xA;&#xD;&#xA;In other words, the main time extensive work is done on the GPU while on the CPU side we draw the GUI regularly. Once the kernel finishes we can check through `clGetEventInfo()` and draw the rendered scene then. No need to wait for the kernel to finish." ContentLicense="CC BY-SA 4.0" />
  <row Id="21379" PostHistoryTypeId="2" PostId="8078" RevisionGUID="475ef594-86f4-4d9d-be78-143cf07dc579" CreationDate="2018-09-18T15:44:00.640" UserId="9258" Text="1. Move the child down slightly so the right foot is behind the shoulder.&#xD;&#xA;&#xD;&#xA;2. Reduce their size almost 50%.&#xD;&#xA;&#xD;&#xA;3. Blend only the outline of the child with the background, at most a few pixels.&#xD;&#xA;&#xD;&#xA;4. The men appear to be standing straight while the child appears to be leaned forward slightly - rotate the top of the inserted image backwards ~5°.&#xD;&#xA;&#xD;&#xA;5. Reduce the brightness of the child slightly.&#xD;&#xA;&#xD;&#xA;Doing the above should result in a realistic result." ContentLicense="CC BY-SA 4.0" />
  <row Id="21380" PostHistoryTypeId="2" PostId="8079" RevisionGUID="14139833-480c-4b16-ae42-be0919366bea" CreationDate="2018-09-18T19:28:52.547" UserId="9258" Text="There is some information about the [XML file format][1] used for .flame files. There are a number of forks of this program written in different languages, the [original site][2] is by definition the place to go for answers; unless you are using a fork - the original  seems to have been abandoned years ago.&#xD;&#xA;&#xD;&#xA;Coefs is 6 floats which defines the coefficients for the affine part of the function, in row order (a d b e c f). Xform has an **interpolation_type** which is a string describing the method for interpolation of xform positions: options are &quot;log&quot;, &quot;linear&quot;, &quot;old&quot;, etc. (a [list of a few dozen options is here][3]). There can be multiple xforms, each applies a transformation to the previous state.&#xD;&#xA;&#xD;&#xA;The spherical transform is complex, there's a 19 page .docx tutorial with 9 pages of examples at: &quot;[Understanding Spherical Transforms: Apophysis Tut][4]&quot; by UniversalKinase (direct link to [.ZIP][5] file). Another tutorial is &quot;[Apo-Tuto Sphericals][6]&quot; by Fiery-Fire.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/scottdraves/flam3/wiki/XML-File-Format&#xD;&#xA;  [2]: https://sourceforge.net/projects/apophysis/&#xD;&#xA;  [3]: https://github.com/mebigfatguy/apophysis-j/tree/master/src/org/apophysis/variations&#xD;&#xA;  [4]: https://www.deviantart.com/universalkinase/art/Understanding-Spherical-Transforms-Apophysis-Tut-506110933&#xD;&#xA;  [5]: https://www.deviantart.com/download/506110933/understanding_spherical_transforms__apophysis_tut_by_universalkinase-d8dbpp1.zip?token=e603ea5d429e198913d7f60f3aaddc4620d78399&amp;ts=1537297719&#xD;&#xA;  [6]: https://www.deviantart.com/fiery-fire/art/Apo-Tuto-Sphericals-146647576" ContentLicense="CC BY-SA 4.0" />
  <row Id="21381" PostHistoryTypeId="5" PostId="8077" RevisionGUID="8e316ef3-bbde-4e84-b915-026cbfdb06fe" CreationDate="2018-09-18T20:35:23.923" UserId="6046" Comment="edited body" Text="Turns out I was an effin idiot. I didn't need to use multithreading or whatsoever. Since the main path tracer work is executing in the kernel, I don't need to wait for the kernel to finish right after call to `EnqueueKernel` by using `clFinish()` ,instead I can tell opencl to set the flag when kernel finishes. &#xD;&#xA;&#xD;&#xA;In other words, the main time extensive work is done on the GPU while on the CPU side we draw the GUI regularly. Once the kernel finishes we can check through `clGetEventInfo()` and draw the rendered scene then. No need to wait for the kernel to finish." ContentLicense="CC BY-SA 4.0" />
  <row Id="21382" PostHistoryTypeId="2" PostId="8080" RevisionGUID="7400dd17-c6e1-4377-aa57-2f08131adf90" CreationDate="2018-09-19T04:14:12.783" UserId="9258" Text="&gt; I was wondering, given a model, which transformations I should apply to get the different projections needed to produce this effect?&#xD;&#xA;&#xD;&#xA;There are at least 2 types of videos and many ways to produce them. It is technically correct to call this effect [Pepper's ghost][1] but you will obtain more relevant search results by searching for: &quot;[Smartphone 3D Hologram][2]&quot; (over 2 million hits).&#xD;&#xA;&#xD;&#xA;To make the projector you'll need: graph paper, CD case, marker or pen, pair of scissors, Cellotape and/or superglue, craft knife or glass cutter, and a smartphone or computer monitor.&#xD;&#xA;&#xD;&#xA;1. Draw one side of a square [frustum][3] on graph paper and cut out 4 shapes from a CD case.&#xD;&#xA;&#xD;&#xA;2. Tape and/or glue them together and place it top down on the center of your cellphone screen.&#xD;&#xA;&#xD;&#xA;[![Holographic Smartphone Projector][4]][4]&#xD;&#xA;&#xD;&#xA;To make videos there are two kinds to choose from, one image rotated 90° and repeated, or four different images representing each side of the image. Whichever style is chosen each image is placed in a quadrant around the center of the screen.&#xD;&#xA;&#xD;&#xA;Use this for a template:&#xD;&#xA;&#xD;&#xA;[![Holographic Template][5]][5]&#xD;&#xA;&#xD;&#xA;To make the simple rotated image use a program such as [AVISynth][6] or PowerDirector, load the video into the Timeline, add a grid, duplicate the track 3 times, rotate each track 90° and place it in one of the quadrants.&#xD;&#xA;&#xD;&#xA;[![4 Videos, rotated 90°][7]][7]&#xD;&#xA;&#xD;&#xA;The second type of video is produced from 4 seperate images each rotated 90°, this provides a different view from each side. It's difficult to produce a live video of this type, align everything perfectly, and not get the opposing cameras in each other's shot. It's easier to create an animation for this purpose. It should look like this:&#xD;&#xA;&#xD;&#xA;[![Dancing Girl][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Pepper%27s_ghost&#xD;&#xA;  [2]: https://www.google.com/search?ei=OLGhW9ScGtq50PEP0LWyiAY&amp;q=Smartphone%203D%20Hologram&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Frustum&#xD;&#xA;  [4]: https://i.stack.imgur.com/pHNay.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/NuZ2P.jpg&#xD;&#xA;  [6]: http://www.avs-plus.net/&#xD;&#xA;  [7]: https://i.stack.imgur.com/dOJ3t.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/mySpZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21383" PostHistoryTypeId="2" PostId="8081" RevisionGUID="eb3cf697-fb9a-41c9-9b79-7c3608093aa9" CreationDate="2018-09-19T09:14:05.137" UserId="7647" Text=" r a similar problem (a tree of combined noise functions, evaluated on the GPU), I found a good method is to generate a shader from the expression tree.  Each predefined node corresponds to a single shader function, e.g.&#xD;&#xA;&#xD;&#xA;    float simplexNode(vec3 pos) {&#xD;&#xA;      // ... implementation of simplex noise&#xD;&#xA;    }&#xD;&#xA;or&#xD;&#xA;&#xD;&#xA;    float sumNode(float val1, float val2) {&#xD;&#xA;      return val1 + val2;  // ... possibly clipped or whatever&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You'd then create a shader like&#xD;&#xA;&#xD;&#xA;    #version 300 core&#xD;&#xA;    // ... include node definitions here&#xD;&#xA;    in vec3 vertexPos;&#xD;&#xA;    out float vertexHeight;&#xD;&#xA;    void main() {&#xD;&#xA;      float f1 = simplexNode(vertexPos);&#xD;&#xA;      float f2 = worleyNode(vertexPos);&#xD;&#xA;      float f3 = sumNode(f1,f2);&#xD;&#xA;      // .. a bunch more&#xD;&#xA;      vertexHeight = f76;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Constant parameters could either be `uniform`s, or just pasted straight into the code.&#xD;&#xA;&#xD;&#xA;One limitation of this method is that the noise functions and methods have to be local, i.e. the evaluation can be done pointwise.  In my case, some nodes were blends and convolutions, so I had to evaluate pieces of the expression tree into textures, blend or convolve the textures into new textures, then use these textures as leaves for the rest of the expression tree.  All of the combinators you mentioned seem to be local, so this may not be a problem for you." ContentLicense="CC BY-SA 4.0" />
  <row Id="21384" PostHistoryTypeId="5" PostId="8077" RevisionGUID="64f44b5d-79e6-47d7-b541-a0d00feae542" CreationDate="2018-09-19T09:15:00.197" UserId="6046" Comment="added 771 characters in body" Text="Turns out I was an effin idiot. I didn't need to use multithreading or whatsoever. Since the main path tracer work is executing in the kernel, I don't need to wait for the kernel to finish right after call to `EnqueueKernel` by using `clFinish()` ,instead I can tell opencl to set the flag when kernel finishes. &#xD;&#xA;&#xD;&#xA;In other words, the main time extensive work is done on the GPU while on the CPU side we draw the GUI regularly. Once the kernel finishes we can check through `clGetEventInfo()` and draw the rendered scene then. No need to wait for the kernel to finish.&#xD;&#xA;&#xD;&#xA;EDIT:- Although I don't need to use multi threading, I still need to use 1 of the above options, that is if the kernel takes much longer to finish I will have to redraw the previous scene, hence I'm doing this through option 4 i.e. by blitting the previously drawn image.&#xD;&#xA;&#xD;&#xA;If anybody thinks this can be done more efficiently I'm all ears. The only problem with option 3/4 is that, since both my RBO's are being used by OpenCL, so if OpenCL takes much longer to render a frame, in order to draw the previously drawn image I need to blit from the previously written RBO to the default framebuffer. However this is being used by the OpenCL currently for reading purposes. Hence I need to keep a copy of this costing an additional `blit` each time the kernel completes." ContentLicense="CC BY-SA 4.0" />
  <row Id="21389" PostHistoryTypeId="50" PostId="7730" RevisionGUID="7a142afd-b55f-47a6-ba80-373fbe4608d5" CreationDate="2018-09-19T23:01:03.047" UserId="-1" />
  <row Id="21390" PostHistoryTypeId="36" PostId="8083" RevisionGUID="8fae04b9-2494-402a-b7b4-adf8013fc567" CreationDate="2018-09-20T14:00:58.593" UserId="-1" Comment="from https://english.stackexchange.com/questions/464867/is-generative-art-the-best-term-for-describing-graphical-techniques-like-ascii" />
  <row Id="21391" PostHistoryTypeId="36" PostId="8084" RevisionGUID="a59c3975-4092-481e-bc37-0c47d8088312" CreationDate="2018-09-20T14:00:58.593" UserId="-1" Comment="from https://english.stackexchange.com/questions/464867/is-generative-art-the-best-term-for-describing-graphical-techniques-like-ascii/464898#464898" />
  <row Id="21392" PostHistoryTypeId="2" PostId="8084" RevisionGUID="966f08a7-c0b3-4350-9023-692e6d9672de" CreationDate="2018-09-19T05:55:27.887" UserId="9380" UserDisplayName="Chris H" Text="[Generative art (Wikipedia)](https://en.m.wikipedia.org/wiki/Generative_art) doesn't necessarily start with an image as the input, and [ASCII art](https://en.wikipedia.org/wiki/ASCII_art) can be drawn/typed by hand (in a text editor) especially for ASCII line art (which I've often used for diagrams) or &quot;oldskool&quot; ASCII art.&#xD;&#xA;&#xD;&#xA;While there may be overlap, *generative art* is neither a synonym nor a hypernym for *ASCII art*.  Note that your pen-plotter example is different again in that the computer-controlled physical output (e.g. choice of pen or even brush on similar devices) is a crucial part of the process but a human is likely to do a fair bit of image manipulation first.  ASCII art and photo-mosaics are essentially the same on screen or printed.&#xD;&#xA;&#xD;&#xA;Sticking with Wikipedia, [algorithmic art](https://en.wikipedia.org/wiki/Algorithmic_art) seems closer, if you exclude hand-typed ASCII art, but this still doesn't fit the robotic drawing of your second example (*not* [robotic art](https://en.wikipedia.org/wiki/Robotic_art), which is art consisting of robots rather than made by robots).&#xD;&#xA;&#xD;&#xA;What you're looking for is actually quite broad, and [computer art](https://en.wikipedia.org/wiki/Computer_art) may be as close as you're going to get, though *computer art* includes things like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] (example borrowed from [a previous answer of mine](https://english.stackexchange.com/a/437597/48571))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6psnD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21393" PostHistoryTypeId="2" PostId="8083" RevisionGUID="5cc2c561-5b05-4a92-9747-0e1f758b0648" CreationDate="2018-09-18T23:56:17.667" UserDisplayName="Matt Phillips" Text="I'm researching generative art using computers, and I'm looking to see if there's a more specific term for types of image manipulation techniques like ascii-art or photo mosaics that can narrow down my search. Basically it's anything that uses a real image as input and outputs something other than individual pixels from the image. Some examples would be [![this photo mosaic][1]][1] or this [plotter print of a woman][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zK9XH.png&#xD;&#xA;  [2]: https://twitter.com/i/status/1040608438236143616&#xD;&#xA;&#xD;&#xA;My sense is that &quot;generative art&quot; is a phrase that properly describes what these techniques do. However, there are other generative art techniques that dont rely on images for input and have a more abstract art look to them when final images come out, so I feel like the term is more broad than the techniques I'm describing." ContentLicense="CC BY-SA 4.0" />
  <row Id="21394" PostHistoryTypeId="1" PostId="8083" RevisionGUID="5cc2c561-5b05-4a92-9747-0e1f758b0648" CreationDate="2018-09-18T23:56:17.667" UserDisplayName="Matt Phillips" Text="Is &quot;generative art&quot; the best term for describing graphical techniques like ascii art or photo mosaics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21395" PostHistoryTypeId="3" PostId="8083" RevisionGUID="5cc2c561-5b05-4a92-9747-0e1f758b0648" CreationDate="2018-09-18T23:56:17.667" UserDisplayName="Matt Phillips" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21396" PostHistoryTypeId="2" PostId="8085" RevisionGUID="eed2d337-6acd-4d12-87a9-f82fb86a2f38" CreationDate="2018-09-20T17:54:34.457" UserId="9382" Text="I'm trying to figure out how to calculate the color of a sample when it is not taken from the center of the subpixel. For example, we have 4 subpixels, where the blue circle is the center of the subpixel, and the red circle is the sample position.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to find information about sample calculation, but got nothing. I assume that I need to calculate sample color using 4 neighboring subpixels and apply bilinear interpolation to them to find the color.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is my guess true, or does it have to somehow calculate the color of the sample in a different way?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2XIXR.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XRwq5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21397" PostHistoryTypeId="1" PostId="8085" RevisionGUID="eed2d337-6acd-4d12-87a9-f82fb86a2f38" CreationDate="2018-09-20T17:54:34.457" UserId="9382" Text="Sample color calculation in rotated grid supersampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="21398" PostHistoryTypeId="3" PostId="8085" RevisionGUID="eed2d337-6acd-4d12-87a9-f82fb86a2f38" CreationDate="2018-09-20T17:54:34.457" UserId="9382" Text="|antialiasing|subpixel-rendering|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21399" PostHistoryTypeId="2" PostId="8086" RevisionGUID="de6186db-7477-464d-966c-044782988acb" CreationDate="2018-09-20T23:35:32.560" UserId="9372" Text="I'm trying to add some details like grass, rocks, trees, etc. to my little procedurally-generated planet. The meshes for the terrain are created from a spherified cube which is split in chunks (chunked LOD).&#xD;&#xA;&#xD;&#xA;To do this I've wrote a geometry shader that takes a mesh as input and uses its vertex positions as locations where the patches of grass will be placed (as textured quads).&#xD;&#xA;&#xD;&#xA;For an infinite flat world (not spherical) I'd use the terrain mesh as input to the geometry shader, but I've found that this won't work well on a sphere, since the vertex density is not homogeneous across the surface.&#xD;&#xA;&#xD;&#xA;So the main question would be: How to create a point cloud for each terrain chunk whose points were equally distributed across the chunk? &#xD;&#xA;&#xD;&#xA;Note: I've seen some examples where these points are calculated from intersecting a massive rain of totally random perpendicular rays from above... but I found this solution overkill, to say the least.&#xD;&#xA;&#xD;&#xA;Another related question would be: Is there something better/faster than the geometry shader approach, maybe using compute shaders and instancing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21400" PostHistoryTypeId="1" PostId="8086" RevisionGUID="de6186db-7477-464d-966c-044782988acb" CreationDate="2018-09-20T23:35:32.560" UserId="9372" Text="Evenly distributed point cloud for a grass renderer on a sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="21401" PostHistoryTypeId="3" PostId="8086" RevisionGUID="de6186db-7477-464d-966c-044782988acb" CreationDate="2018-09-20T23:35:32.560" UserId="9372" Text="|shader|gpu|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21402" PostHistoryTypeId="50" PostId="7943" RevisionGUID="eec2e9fc-54fa-4d52-bf55-dd8bd7bb3e71" CreationDate="2018-09-21T03:01:23.487" UserId="-1" />
  <row Id="21404" PostHistoryTypeId="5" PostId="7943" RevisionGUID="2b61d1de-151d-48f6-9c87-01c24140bd5a" CreationDate="2018-09-21T09:18:09.103" UserId="6046" Comment="deleted 1 character in body" Text="So I was reading up on how to sample Rectangular Area lights, and the procedure is pretty straightforward. That is, I can get random points using the equation.&#xD;&#xA;&#xD;&#xA;$ p = X_o + \epsilon_1V_1 + \epsilon_2V_2$&#xD;&#xA;&#xD;&#xA;Where $X_o$ is my corner point for the rectangle and $V_1$ and $V_2$ are the 2 vectors spanning it And the epsilons are the uniform random numbers.&#xD;&#xA;&#xD;&#xA;The thing is almost every where I go, they talk about how the PDF of this sampling is $1/A$ (constant) with the exception of 1 place discussed below, and that when calculating the radiance coming from this area light when sampled by this way we should thus multiply the whole thing by the Area of the rectangle. &#xD;&#xA;&#xD;&#xA;However when I check their algorithms, they leave out this Area factor.&#xD;&#xA;&#xD;&#xA;**Compute Graphics Principles and Practice** and **Fundamental of Computer Graphics by Peter Shirley** describes the calculation of the radiance returned by sampling a point on the area light, (Notice the black underlined factor describing Area of the jth light source)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jEkzn.png&#xD;&#xA;&#xD;&#xA;However both of these books when describing their pseudocode, leave out this $Area$ factor.&#xD;&#xA;&#xD;&#xA;However when I read Peter Shirley's research paper regarding Direct illumination techniques, He gives the PDF for rectangular Area lights as&#xD;&#xA;&#xD;&#xA;$ 1/ \frac{||V_1 \times V_2||}{2}$&#xD;&#xA;&#xD;&#xA;Which is the area of the triangle not a rectangle.&#xD;&#xA;&#xD;&#xA;So ultimately I have 2 questions.&#xD;&#xA;&#xD;&#xA;**1) What is the correct PDF term for rectangular area lights?**&#xD;&#xA;&#xD;&#xA;**2) Do I need to multiply this term when calculating the radiance emitted from this light source.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="21405" PostHistoryTypeId="5" PostId="8085" RevisionGUID="8ce63538-09b0-4fba-97f1-dd059f499304" CreationDate="2018-09-21T09:25:34.333" UserId="9382" Comment="added 145 characters in body" Text="I'm rendering a scene using scanline method. In order to get rid of aliasing we need to render a scene with higher resolution (2x, for example). I'm trying to figure out how to calculate the color of a sample when it is not taken from the center of the subpixel. For example, we have 4 subpixels, where the blue circle is the center of the subpixel, and the red circle is the sample position.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to find information about sample calculation, but got nothing. I assume that I need to calculate sample color using 4 neighboring subpixels and apply bilinear interpolation to them to find the color.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is my guess true, or does it have to somehow calculate the color of the sample in a different way?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2XIXR.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XRwq5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21406" PostHistoryTypeId="5" PostId="8085" RevisionGUID="9680760d-a1d7-47f0-9877-db16b44022e9" CreationDate="2018-09-21T09:45:39.043" UserId="9382" Comment="added 12 characters in body" Text="I'm rendering a scene using scanline method. In order to get rid of aliasing we need to render a scene with higher resolution (2x, for example). I'm trying to figure out how to calculate the color of a sample when it is not taken from the center of the subpixel. For example, we have 4 subpixels per 1 pixel, where the blue circle is the center of the subpixel, and the red circle is the sample position.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried to find information about sample calculation, but got nothing. I assume that I need to calculate sample color using 4 neighboring subpixels and apply bilinear interpolation to them to find the color.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is my guess true, or does it have to somehow calculate the color of the sample in a different way?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2XIXR.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XRwq5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21407" PostHistoryTypeId="5" PostId="8022" RevisionGUID="d1836771-4eb5-455d-aa9f-6a68ddb1011b" CreationDate="2018-09-21T11:35:58.107" UserId="209" Comment="fixed some English" Text="If you are doing a perspective image and your model has implicit intersections then, if you use &quot;linear Z&quot;, those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles, receding into the distance,  which pierce the ground and . The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with `1/Z`, then when the projected vertices have been computed with perspective, the image will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologise for the non-aesthetic quality of the following illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first image shows the required rendering effect. (Note that the blue &quot;pylons&quot; go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This second image shows the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc and I've no idea what has happened with the scaling.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are incorrect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;Re your later comment:&#xD;&#xA;&gt; “if those are not interpolated with 1/Z” that I don’t understand. What interpolation is that?&#xD;&#xA;&#xD;&#xA;The first thing to note is that, with a standard perspective projection, straight lines in world space remain straight lines in perspective space. Distances/lengths, however, are not preserved.&#xD;&#xA;&#xD;&#xA;For simplicity, let us assume a trivial perspective transform is used to project the vertices, i.e.&#xD;&#xA;$$X_{Screen} = \frac{X_{World}}{Z_{World}}$$&#xD;&#xA;$$Y_{Screen} = \frac{Y_{World}}{Z_{World}}$$&#xD;&#xA;We *should* also compute a reciprocal screen-space depth, e.g. $$Z_{Screen} = \frac{1}{Z_{World}}$$ but a linear Z would in the depth buffer would, to me, imply something like: $$Z_{Screen} = scale*Z_{World}$$ *(We can assume here that scale=1)*&#xD;&#xA;&#xD;&#xA;Let's assume we have a line with world space end points$$&#xD;&#xA;  \begin{matrix} \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and &#xD;&#xA;   \begin{bmatrix}&#xD;&#xA;    200 \\&#xD;&#xA;    0   \\&#xD;&#xA;    10  \\&#xD;&#xA;    \end{bmatrix}\\&#xD;&#xA;  \end{matrix}&#xD;&#xA;$$&#xD;&#xA;With the perspective mapping these map to screen space coordinates&#xD;&#xA; $$ \begin{matrix}   \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and \begin{bmatrix}&#xD;&#xA;    20 \\&#xD;&#xA;    0  \\&#xD;&#xA;    0.1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; \end{matrix}$$&#xD;&#xA;&#xD;&#xA;The rendering system/hardware will linearly interpolate the screen space z, so at the 1/2 way point of the line, as it appears on-screen, i.e. at pixel (10, 0), we would get a projected (inverse) Z value of 0.55, which corresponds to to a world space Z value value of ~1.818. Given the starting and end Z values, this is about 20% along the length of the line.&#xD;&#xA;&#xD;&#xA;If instead, we tried to interpolate using the original Z values, we'd end up with Z corresponding to a world space value of 5.5. As long as nothing intersects, you might be ok (I've not thought about it too thoroughly) but anything with implicit intersections *will* be incorrect.&#xD;&#xA;&#xD;&#xA;What I haven't mentioned is that once you introduce perspective correct texturing (or even perspective correct shading), you must do per-pixel interpolation of 1/w and, additionally, also compute, per pixel, the reciprocal of that interpolated value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21408" PostHistoryTypeId="2" PostId="8088" RevisionGUID="444a32ac-a560-4daf-beb5-33ac53cf3a1b" CreationDate="2018-09-21T19:08:48.283" UserId="9348" Text="I would need to translate a vtkCellLocator, without rebuilding it entirely. I suppose that it should be possible to apply an offset to all the buckets in the octree. Do you know if is it possible to do this (or to apply a translation to any other cell locator structure) with the tools already provided by vtk?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;Federico" ContentLicense="CC BY-SA 4.0" />
  <row Id="21409" PostHistoryTypeId="1" PostId="8088" RevisionGUID="444a32ac-a560-4daf-beb5-33ac53cf3a1b" CreationDate="2018-09-21T19:08:48.283" UserId="9348" Text="Translate vtkCellLocator" ContentLicense="CC BY-SA 4.0" />
  <row Id="21410" PostHistoryTypeId="3" PostId="8088" RevisionGUID="444a32ac-a560-4daf-beb5-33ac53cf3a1b" CreationDate="2018-09-21T19:08:48.283" UserId="9348" Text="|space-partitioning|vtk|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21411" PostHistoryTypeId="2" PostId="8089" RevisionGUID="8a60c865-a8fa-4982-84e2-51dae56358ff" CreationDate="2018-09-21T21:12:50.113" UserId="9393" Text="It sounds crazy, but I've been doing a lot of reading on exactly why WoW **performs like a turd**, even on a 1080Ti / 8700k OC'd and overall, a high-end machine.&#xD;&#xA;&#xD;&#xA;Overclocking the CPU yielded great results, but after ~4.7Ghz, my returns were, at best, minimal, as such, running at 5.0Ghz makes no difference.&#xD;&#xA;&#xD;&#xA;So I was thinking:&#xD;&#xA;&#xD;&#xA;The server issues data to the CPU. The CPU issues draw calls to my GPU. My GPU can be downclocked by ~40-50%, it still won't affect FPS. My CPU is clearly hit its ceiling.&#xD;&#xA;&#xD;&#xA;So, then, could it very well be that, say, on a ~80-90ms connection, my FPS would be limited due to how much it could output, since the GPU is basically waiting?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21412" PostHistoryTypeId="1" PostId="8089" RevisionGUID="8a60c865-a8fa-4982-84e2-51dae56358ff" CreationDate="2018-09-21T21:12:50.113" UserId="9393" Text="Are MMORPG, specifically WoW, limited by their latency in terms of FPS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21413" PostHistoryTypeId="3" PostId="8089" RevisionGUID="8a60c865-a8fa-4982-84e2-51dae56358ff" CreationDate="2018-09-21T21:12:50.113" UserId="9393" Text="|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21419" PostHistoryTypeId="2" PostId="8091" RevisionGUID="cedaffdc-28b8-4b49-a1fe-8e08a9ffdc8c" CreationDate="2018-09-22T08:25:57.660" UserId="9254" Text="In [section 16.1.1 of *Physically Based Rendering*](https://books.google.de/books?id=iNMVBQAAQBAJ&amp;pg=PA950&amp;lpg=PA950&amp;dq=%22for+pinhole+apertures,+we+compute%22&amp;source=bl&amp;ots=ivwhEhZqRF&amp;sig=yCpEAaOMpYlA9Vj-LykM5_VHnoQ&amp;hl=de&amp;sa=X&amp;ved=2ahUKEwjvirbRlM7dAhXFzaQKHW2KB3EQ6AEwAHoECAAQAQ#v=onepage&amp;q=%22for%20pinhole%20apertures%2C%20we%20compute%22&amp;f=false) the authors describe how we can check, if a given ray $r$ corresponds to one starting from the film area.&#xD;&#xA;&#xD;&#xA;They implement this check such that it works for cameras with finite and pinhole apertures. They assume that $r$ has origin $p$ and direction $\omega$. Maybe I didn't get it, but are they assuming that $p$ is a point on the lens? That seems to be the case from Figure 16.1.&#xD;&#xA;&#xD;&#xA;Now they want to find the point on the film that $r$ corresponds to. Let $w$ denote the camera viewing direction $(0,0,1)$ in world coordinates. Then they compute the cosine of the angle $\theta$ between $\omega$ and $w$, $$\cos(\theta)=\langle\omega,w\rangle.$$ Assuming we're dealing with a pinhole aperture, why do we find the point on the film by intersecting the ray with a plane arbitrary set at $z=1$? And why is this intersection at $p+t\omega$, where $t=1/\cos(\theta)$? Shouldn't the intersection be at $t=\frac{\langle w-p,w\rangle}{\langle\omega,w\rangle}$?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21420" PostHistoryTypeId="1" PostId="8091" RevisionGUID="cedaffdc-28b8-4b49-a1fe-8e08a9ffdc8c" CreationDate="2018-09-22T08:25:57.660" UserId="9254" Text="Check if a given ray corresponds to one starting from the film area" ContentLicense="CC BY-SA 4.0" />
  <row Id="21421" PostHistoryTypeId="3" PostId="8091" RevisionGUID="cedaffdc-28b8-4b49-a1fe-8e08a9ffdc8c" CreationDate="2018-09-22T08:25:57.660" UserId="9254" Text="|raytracing|physically-based|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21422" PostHistoryTypeId="2" PostId="8092" RevisionGUID="f0c70c0b-b7d2-42e2-a1ce-4099f25e74d0" CreationDate="2018-09-22T09:14:35.757" UserId="2041" Text="Online games do not work the way you describe. The server doesn't give the client one frame's worth of data every frame. That would be awful. Instead, every client has its own copy of the game state, and the rendering happens as if it were an offline game: every frame, the game state is updated locally. That means your inputs such as moving the mouse to control the view take effect immediately. Things that aren't under players' control (such as the movement of projectiles in flight) are also updated locally. Many games also have some kind of motion prediction for other players' characters - in the simplest case, just updating the state as if they kept going in the same direction.&#xD;&#xA;&#xD;&#xA;These state updates are performed by the CPU on its scene-graph, and they result in some update to GPU state too. The frame is then rendered by the GPU, usually in parallel with the CPU starting work on the next frame's updates.&#xD;&#xA;&#xD;&#xA;When an update arrives from the server, this also updates the state on the CPU. This update will include new projectiles, replacements for the predicted motions of other player characters, and replacements for the motions of the local player's character (e.g. if they bumped into another player or were hit by some unpredicted projectiles).&#xD;&#xA;&#xD;&#xA;Resolving conflicts between the predicted state on the client and the new state from the server, and applying the lag to the server state before applying it, are important parts of the game's architecture that really determine how the game feels to play and what lag looks like. Applying the updates from the server is done within one frame update on the client, so if an update takes too long to apply, it'll cause some frames to be much slower, but the age of the update doesn't really affect that.&#xD;&#xA;&#xD;&#xA;##Summary&#xD;&#xA;&#xD;&#xA;Client-server latency doesn't usually increase the frame time, because the client doesn't wait for a server round-trip each frame." ContentLicense="CC BY-SA 4.0" />
  <row Id="21423" PostHistoryTypeId="4" PostId="8091" RevisionGUID="a748ab7c-6d22-49ad-92c6-ba1652a6c2e8" CreationDate="2018-09-22T10:13:34.600" UserId="9254" Comment="edited title" Text="Compute emitted importance of a pinhole camera" ContentLicense="CC BY-SA 4.0" />
  <row Id="21426" PostHistoryTypeId="5" PostId="8091" RevisionGUID="39513fb5-00a9-4662-957e-30d48884f01e" CreationDate="2018-09-22T11:54:12.973" UserId="9254" Comment="added 76 characters in body" Text="In [section 16.1.1 of *Physically Based Rendering*](https://books.google.de/books?id=iNMVBQAAQBAJ&amp;pg=PA950&amp;lpg=PA950&amp;dq=%22for+pinhole+apertures,+we+compute%22&amp;source=bl&amp;ots=ivwhEhZqRF&amp;sig=yCpEAaOMpYlA9Vj-LykM5_VHnoQ&amp;hl=de&amp;sa=X&amp;ved=2ahUKEwjvirbRlM7dAhXFzaQKHW2KB3EQ6AEwAHoECAAQAQ#v=onepage&amp;q=%22for%20pinhole%20apertures%2C%20we%20compute%22&amp;f=false) the authors describe how we can check, if a given ray $r$ corresponds to one starting from the film area.&#xD;&#xA;&#xD;&#xA;They implement this check such that it works for cameras with finite and pinhole apertures. They assume that $r$ has origin $p$ and direction $\omega$. Maybe I didn't get it, but are they assuming that $p$ is a point on the lens? That seems to be the case from Figure 16.1.&#xD;&#xA;&#xD;&#xA;Now they want to find the point on the film that $r$ corresponds to. Let $w$ denote the camera viewing direction $(0,0,1)$ in world coordinates. Then they compute the cosine of the angle $\theta$ between $\omega$ and $w$, $$\cos(\theta)=\langle\omega,w\rangle.$$ Assuming we're dealing with a pinhole aperture, why do we find the point on the film by intersecting the ray with a plane arbitrary set at $z=1$? And why is this intersection at $p+t\omega$, where $t=1/\cos(\theta)$? Shouldn't the intersection be at $t=\frac{\langle w-p,w\rangle}{\langle\omega,w\rangle}$?&#xD;&#xA;&#xD;&#xA;And anyway, doesn't $p$ need to be equal to the eye point of the camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21427" PostHistoryTypeId="2" PostId="8093" RevisionGUID="ebecf2d9-c1b1-45de-8cb2-e1a4cac5f7af" CreationDate="2018-09-22T12:01:25.687" UserId="9120" Text="I'm making a project about how to represent ovaloids with ray-marching. I have ovaloids defined with an implicit equation and for shading, I need to calculate the normal of the surface.&#xD;&#xA;&#xD;&#xA;How can I calculate this normal from the implicit equation? How is it done in real-world systems? Can you give an explanation of the methods used and ideally point me some implementations that exists?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21428" PostHistoryTypeId="1" PostId="8093" RevisionGUID="ebecf2d9-c1b1-45de-8cb2-e1a4cac5f7af" CreationDate="2018-09-22T12:01:25.687" UserId="9120" Text="Normal of surface from implicit equation for ray-marching algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="21429" PostHistoryTypeId="3" PostId="8093" RevisionGUID="ebecf2d9-c1b1-45de-8cb2-e1a4cac5f7af" CreationDate="2018-09-22T12:01:25.687" UserId="9120" Text="|shading|normal-mapping|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21430" PostHistoryTypeId="5" PostId="8088" RevisionGUID="dc45f2f8-c485-4e23-a991-a245bbf2e7dd" CreationDate="2018-09-22T15:17:37.217" UserId="6" Comment="Removed idle chatter." Text="I would need to translate a vtkCellLocator, without rebuilding it entirely. I suppose that it should be possible to apply an offset to all the buckets in the octree. Do you know if is it possible to do this (or to apply a translation to any other cell locator structure) with the tools already provided by vtk?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21431" PostHistoryTypeId="5" PostId="8075" RevisionGUID="007ae36f-37de-412f-8182-621bde2c59a4" CreationDate="2018-09-22T15:19:04.913" UserId="6" Comment="Improved formatting. Removed idle chatter." Text="A few years ago I started creating a procedural planet engine/renderer for a game in Unity, which after a couple of years I had to stop developing due to lack of time. At the time i didn't know too much about shaders so I did everything on the CPU. Now that I have plenty of time and am more aware of what shaders can do I'd like to resume development with the GPU in mind.&#xD;&#xA;&#xD;&#xA;For the terrain mesh I'm using a cubed-sphere and chunked LODs. Since terrain never changes, heights for each chunk need to be calculated just once.The way I calculate heights is rather complex since it's based on a noise tree, which is created from an artist/designer-provided XML for each main planet/asteroid. Leaf nodes in the tree would be noise generators like Simplex, Value, Sine, Voronoi, etc. while branch nodes would be filters and modifiers (FBM, abs, neg, sum, ridged, billow, blender, selectors, etc). &#xD;&#xA;&#xD;&#xA;To calculate the heights for a mesh you'd call `void CalcHeights( Vector3[] meshVertices, out float[] heights )` on the noise's root node, somewhere in the game code.&#xD;&#xA;&#xD;&#xA;This approach offers a lot of flexibility but also introduces a lot of load in the CPU. The first obvious thing to do would be (I guess) to move all generators to the GPU via compute shaders, then do the same for the rest of the filters. But, depending on the complexity of the noise tree, a single call to CalcHeights could potentially cause dozens of calls back and forth between the CPU and GPU, which I'm not sure it's a good thing.&#xD;&#xA;&#xD;&#xA;How should I go about this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21434" PostHistoryTypeId="5" PostId="8083" RevisionGUID="e54372b4-86f0-416b-b210-d60353879a2f" CreationDate="2018-09-23T10:34:54.037" UserId="3304" Comment="Copy edited." Text="I'm researching generative art using computers, and I'm looking to see if there's a more specific term for types of image manipulation techniques like ASCII art or photo mosaics that can narrow down my search. Basically it's anything that uses a real image as input and outputs something other than individual pixels from the image. Some examples would be [![this photo mosaic][1]][1] or this [plotter print of a woman][2].&#xD;&#xA;&#xD;&#xA;My sense is that &quot;generative art&quot; is a phrase that properly describes what these techniques do. However, there are other generative art techniques that don't rely on images for input and have a more abstract art look to them when final images come out, so I feel like the term is more broad than the techniques I'm describing.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zK9XH.png&#xD;&#xA;  [2]: https://twitter.com/i/status/1040608438236143616&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21435" PostHistoryTypeId="4" PostId="8083" RevisionGUID="e54372b4-86f0-416b-b210-d60353879a2f" CreationDate="2018-09-23T10:34:54.037" UserId="3304" Comment="Copy edited." Text="Is &quot;generative art&quot; the best term for describing graphical techniques like ASCII art or photo mosaics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21436" PostHistoryTypeId="6" PostId="8083" RevisionGUID="e54372b4-86f0-416b-b210-d60353879a2f" CreationDate="2018-09-23T10:34:54.037" UserId="3304" Comment="Copy edited." Text="|photo-realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21437" PostHistoryTypeId="24" PostId="8083" RevisionGUID="e54372b4-86f0-416b-b210-d60353879a2f" CreationDate="2018-09-23T10:34:54.037" Comment="Proposed by 3304 approved by -1 edit id of 441" ContentLicense="CC BY-SA 4.0" />
  <row Id="21438" PostHistoryTypeId="6" PostId="8083" RevisionGUID="019b8508-b41f-46b6-8df2-2d69cf6d8121" CreationDate="2018-09-23T10:34:54.037" UserId="231" Comment="Copy edited." Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21439" PostHistoryTypeId="5" PostId="8093" RevisionGUID="25d7e420-4edb-474b-9c84-a63f5821a935" CreationDate="2018-09-23T10:35:25.530" UserId="9120" Comment="added 264 characters in body; edited title" Text="I want to represent ovaloids with ray-marching. I have ovaloids defined with an implicit equation. &#xD;&#xA;&#xD;&#xA;For instance, we can consider the equation of an ellipsoid given as: $$ \frac{x^2}{a^2} + \frac{y^2}{b^2} + \frac{z^2}{c^2} -1 = 0, $$ where $a, b, c$ are constant. &#xD;&#xA;&#xD;&#xA;Given this equation I need to caculate the normal for the shading of the suface.&#xD;&#xA;&#xD;&#xA;* How can I calculate this normal from the implicit equation? &#xD;&#xA;* How is it done in real-world systems? &#xD;&#xA;* Can you give an explanation of the methods used and ideally point me some implementations that exist?&#xD;&#xA;&#xD;&#xA;Please, answer in full generality and not only considering the example given above. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21440" PostHistoryTypeId="4" PostId="8093" RevisionGUID="25d7e420-4edb-474b-9c84-a63f5821a935" CreationDate="2018-09-23T10:35:25.530" UserId="9120" Comment="added 264 characters in body; edited title" Text="How to compute normal of surface from implicit equation for ray-marching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21441" PostHistoryTypeId="5" PostId="8089" RevisionGUID="27f47b90-6d2b-4281-8012-59e5b1085c4b" CreationDate="2018-09-23T10:36:59.643" UserId="3304" Comment="Copy edited (e.g. ref. &lt;http://en.wikipedia.org/wiki/Hertz#SI_multiples&gt;)." Text="It sounds crazy, but I've been doing a lot of reading on exactly why WoW **performs like a turd**, even on a 1080Ti / 8700k OC'd and overall, a high-end machine.&#xD;&#xA;&#xD;&#xA;Overclocking the CPU yielded great results, but after ~4.7&amp;nbsp;GHz, my returns were, at best, minimal, as such, running at 5.0&amp;nbsp;GHz makes no difference.&#xD;&#xA;&#xD;&#xA;So I was thinking:&#xD;&#xA;&#xD;&#xA;The server issues data to the CPU. The CPU issues draw calls to my GPU. My GPU can be downclocked by ~40-50%, and it still won't affect FPS. My CPU is clearly hitting its ceiling.&#xD;&#xA;&#xD;&#xA;So, then, could it very well be that, say, on a ~80-90&amp;nbsp;ms connection, my FPS would be limited due to how much it could output, since the GPU is basically waiting?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21442" PostHistoryTypeId="4" PostId="8089" RevisionGUID="27f47b90-6d2b-4281-8012-59e5b1085c4b" CreationDate="2018-09-23T10:36:59.643" UserId="3304" Comment="Copy edited (e.g. ref. &lt;http://en.wikipedia.org/wiki/Hertz#SI_multiples&gt;)." Text="Are MMORPGs, specifically WoW, limited by their latency in terms of FPS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21443" PostHistoryTypeId="24" PostId="8089" RevisionGUID="27f47b90-6d2b-4281-8012-59e5b1085c4b" CreationDate="2018-09-23T10:36:59.643" Comment="Proposed by 3304 approved by 6, 231 edit id of 439" ContentLicense="CC BY-SA 4.0" />
  <row Id="21444" PostHistoryTypeId="5" PostId="8093" RevisionGUID="92ea7cf8-7e04-4067-80c3-2657889455ab" CreationDate="2018-09-23T11:00:02.493" UserId="9120" Comment="added 285 characters in body" Text="I want to represent ovaloids with ray-marching. I have ovaloids defined with an implicit equation. &#xD;&#xA;&#xD;&#xA;For instance, we can consider the equation of an ellipsoid given as: $$ \frac{x^2}{a^2} + \frac{y^2}{b^2} + \frac{z^2}{c^2} -1 = 0, $$ where $a, b, c$ are constant. &#xD;&#xA;&#xD;&#xA;Given this equation I need to caculate the normal for the shading of the suface. In an standard course of Curves and Surfaces I would take $f(x,y,z) = \frac{x^2}{a^2} + \frac{y^2}{b^2} + \frac{z^2}{c^2} -1 $ and compute $N(p) = \frac{\nabla f(p)}{|\nabla f(p)|}$ as the normal of the surface. &#xD;&#xA;&#xD;&#xA;Here I have to check that $0$ is a regular value of $f$ and that $f  $ is differentiable. However, the second check is not automate.&#xD;&#xA;&#xD;&#xA;* How is it done in real-world systems? &#xD;&#xA;* Can you give an explanation of the methods used and ideally point me some implementations that exist?&#xD;&#xA;&#xD;&#xA;Please, answer in full generality and not only considering the example given above. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21445" PostHistoryTypeId="2" PostId="8094" RevisionGUID="38a8967b-22ba-4303-a285-11308b638f6e" CreationDate="2018-09-23T17:46:17.997" UserId="9399" Text="This is more a comment than an answer, but since I'm new here with no reputation, I can't comment.&#xD;&#xA;&#xD;&#xA;I was trying to use your method 2 to read a metal texture (having hit problems with your other methods, too, as well as half a dozen other methods from other threads).  I used a .waitUntilCompleted method, so figured my problem didn't have to deal with flushing.  My shader is a toy example:&#xD;&#xA;&#xD;&#xA;    kernel void compute_main(&#xD;&#xA;                         texture2d&lt;float, access::read&gt; inTexture [[texture(0)]],&#xD;&#xA;                         texture2d&lt;float, access::write&gt; outTexture [[texture(1)]],  // this doesn't work&#xD;&#xA;                         //texture2d&lt;float, access::read_write&gt; outTexture [[texture(1)]],  // this does&#xD;&#xA;                         uint2 gid [[thread_position_in_grid]])&#xD;&#xA;    {&#xD;&#xA;        float4 inColor = inTexture.read(gid);&#xD;&#xA;        float4 outColor (inColor.g, inColor.r, inColor.b, inColor.a);&#xD;&#xA;        outTexture.write(outColor, gid);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I initially was getting this error:&#xD;&#xA;&#xD;&#xA;validateComputeFunctionArguments:857: failed assertion `Compute Function(ciKernelMain): reads texture ([1]) whose usage (0x02) doesn't specify MTLTextureUsageShaderRead (0x01)'&#xD;&#xA;&#xD;&#xA;I realize it isn't the same error you were getting, but maybe something has changed in metal/swift/xcode.  I'm running Xcode 9.4.1&#xD;&#xA;&#xD;&#xA;After changing the output texture to read_write (the commented line in the code above), and setting up the texture descriptor appropriately,&#xD;&#xA;&#xD;&#xA;    //textureDescriptor.usage = MTLTextureUsage.shaderWrite // not this&#xD;&#xA;    textureDescriptor.usage = [.shaderWrite, .shaderRead] // this works&#xD;&#xA;&#xD;&#xA;it worked.  Seems the CI library for this uses metal (I'm guessing from the error) and it reads the texture I thought I only needed to write to.  Not obvious until you run it and get the error.  I'm not sure if our situations were different or what, but in mine, at least I got an error message that was useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="21446" PostHistoryTypeId="2" PostId="8095" RevisionGUID="a047c450-67de-4c92-916e-ffbb8b6923f6" CreationDate="2018-09-23T18:15:52.493" UserId="9398" Text="1. If I have an image of x/y resolution and display it on a monitor, does this mean that between a 15-inch monitor and a 42-inch, the same amount of pixels (x/y) will be displayed, only that each pixel will be of different size?&#xD;&#xA;&#xD;&#xA;2. In relation to my first question, if I connect a 25-inch monitor or a 13-inch monitor to a computer, will the GPU/CPU work harder when connected to the 25 inch one? Could there be more lags on the bigger screen, or is it simply a matter of pixels' stretching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21447" PostHistoryTypeId="1" PostId="8095" RevisionGUID="a047c450-67de-4c92-916e-ffbb8b6923f6" CreationDate="2018-09-23T18:15:52.493" UserId="9398" Text="Difference in pixels between different monitors' sizes" ContentLicense="CC BY-SA 4.0" />
  <row Id="21448" PostHistoryTypeId="3" PostId="8095" RevisionGUID="a047c450-67de-4c92-916e-ffbb8b6923f6" CreationDate="2018-09-23T18:15:52.493" UserId="9398" Text="|rendering|gpu|pixel-graphics|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21449" PostHistoryTypeId="2" PostId="8096" RevisionGUID="5f9253f0-4334-4be1-ace0-d1f1024f2886" CreationDate="2018-09-24T07:55:58.750" UserId="2041" Text="The answer to both your questions is the same: the physical size of the monitor makes no difference at all. If your screen is 1920x1080 pixels, and you display a 960x540 image without any scaling, the image will stake up a quarter of the screen, and it won't take any more GPU time to display on a larger monitor.&#xD;&#xA;&#xD;&#xA;The only caveat is that most OSes have some kind of pixel scaling method now, so that icons, buttons, and text aren't unusably small on modern high-resolution displays. In Windows the option is called &quot;Change the size of text, apps and other items&quot;. If this setting isn't set to 100%, most things on the screen are scaled up even if the program isn't scaling them. This is more likely to be set high on a small, high-resolution screen than on a large, high-resolution screen. If you try to test displaying the same image on different-sized monitors, and they are using different values for this setting, the image probably won't be the same number of pixels on the monitors, because it's being scaled up according to this setting." ContentLicense="CC BY-SA 4.0" />
  <row Id="21450" PostHistoryTypeId="5" PostId="8089" RevisionGUID="608e29bf-425c-4e4d-9ca3-13b89ad39064" CreationDate="2018-09-24T08:22:41.650" UserId="209" Comment="Replaced colourful colloquial exrpression with something that is easier for others to understand." Text="It sounds crazy, but I've been doing a lot of reading on exactly why WoW **performs very poorly**, even on a 1080Ti / 8700k OC'd and overall, a high-end machine.&#xD;&#xA;&#xD;&#xA;Overclocking the CPU yielded great results, but after ~4.7&amp;nbsp;GHz, my returns were, at best, minimal, as such, running at 5.0&amp;nbsp;GHz makes no difference.&#xD;&#xA;&#xD;&#xA;So I was thinking:&#xD;&#xA;&#xD;&#xA;The server issues data to the CPU. The CPU issues draw calls to my GPU. My GPU can be downclocked by ~40-50%, and it still won't affect FPS. My CPU is clearly hitting its ceiling.&#xD;&#xA;&#xD;&#xA;So, then, could it very well be that, say, on a ~80-90&amp;nbsp;ms connection, my FPS would be limited due to how much it could output, since the GPU is basically waiting?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21451" PostHistoryTypeId="2" PostId="8097" RevisionGUID="4660e992-9291-4dc9-a522-b0d5a25c06bd" CreationDate="2018-09-24T18:41:23.123" UserId="506" Text="The usual way of doing this with raymarching is to define your surface as a [signed-distance field](https://en.wikipedia.org/wiki/Signed_distance_function) and use [finite differences](https://en.wikipedia.org/wiki/Finite_difference#Relation_with_derivatives) to get the gradient of the distance function at the point you’re sampling. In other words, if you have a function `map(p)` that returns the signed distance value at a point `p`, the normal at `p` is given by:&#xD;&#xA;&#xD;&#xA;    float epsilon = 0.001; // arbitrary — should be smaller than any surface detail in your distance function, but not so small as to get lost in float precision&#xD;&#xA;    float centerDistance = map(p);&#xD;&#xA;    float xDistance = map(p + float3(epsilon, 0, 0));&#xD;&#xA;    float yDistance = map(p + float3(0, epsilon, 0));&#xD;&#xA;    float zDistance = map(p + float3(0, 0, epsilon));&#xD;&#xA;    float3 normal = (float3(xDistance, yDistance, zDistance) - centerDistance) / epsilon;&#xD;&#xA;&#xD;&#xA;Note that you can improve the accuracy by taking an extra 3 samples on the other “side” of the center position and subtracting those from the first three, then dividing by 2× the epsilon value, but if your distance function is complicated then that can be a lot of additional work for not much visible benefit.&#xD;&#xA;&#xD;&#xA;The sample function you provide isn’t a signed-distance function as-is, and I don’t know of a straightforward way to convert it into one, but there’s an article by Íñigo Quílez (kind of a legend in this field) [here](https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm) with various functions you can make use of, including one for an ellipsoid. There’s also a lot of reference material available on [Shadertoy](https://shadertoy.com)—search for “raymarching” and you’ll find plenty of examples." ContentLicense="CC BY-SA 4.0" />
  <row Id="21452" PostHistoryTypeId="2" PostId="8098" RevisionGUID="792ad965-dded-4e5f-a22f-0c669b7beca6" CreationDate="2018-09-25T00:34:20.640" UserId="9405" Text="In order to translate a vtkCellLocator, you have only to translate a bounding box of root octant. However this bounding box cannot be publicly accessible. So it is necessary to create a new class inheriting from a vtkCellLocator and provide access functions to get and set it directly. The following is a simple example.&#xD;&#xA;&#xD;&#xA;    #include &lt;vtkTransform.h&gt;&#xD;&#xA;    #include &lt;vtkTransformPolyDataFilter.h&gt;&#xD;&#xA;    #include &lt;vtkSmartPointer.h&gt;&#xD;&#xA;    #include &lt;vtkSphereSource.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &lt;vtkCellLocator.h&gt;&#xD;&#xA;    #include &lt;vtkObjectFactory.h&gt;&#xD;&#xA;    &#xD;&#xA;    class vtkMyCellLocator : public vtkCellLocator&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;      static vtkMyCellLocator *New();&#xD;&#xA;    &#xD;&#xA;      vtkSetVectorMacro(Bounds,double,6);&#xD;&#xA;      vtkGetVectorMacro(Bounds,double,6);&#xD;&#xA;    };&#xD;&#xA;    vtkStandardNewMacro(vtkMyCellLocator);&#xD;&#xA;    &#xD;&#xA;    int main(int, char *[])&#xD;&#xA;    {&#xD;&#xA;      auto sphereSource = vtkSmartPointer&lt;vtkSphereSource&gt;::New();&#xD;&#xA;      sphereSource-&gt;Update();&#xD;&#xA;    &#xD;&#xA;      // Create the tree&#xD;&#xA;      auto cellLocator = vtkSmartPointer&lt;vtkMyCellLocator&gt;::New();&#xD;&#xA;      cellLocator-&gt;SetDataSet(sphereSource-&gt;GetOutput());&#xD;&#xA;      cellLocator-&gt;BuildLocator();&#xD;&#xA;    &#xD;&#xA;      double translate[3] = {10.0, 0, 0};&#xD;&#xA;      auto transform = vtkSmartPointer&lt;vtkTransform&gt;::New();&#xD;&#xA;      transform-&gt;Translate(translate);&#xD;&#xA;    &#xD;&#xA;      auto transformFilter = vtkSmartPointer&lt;vtkTransformPolyDataFilter&gt;::New();&#xD;&#xA;      transformFilter-&gt;SetTransform(transform);&#xD;&#xA;      transformFilter-&gt;SetInputConnection(sphereSource-&gt;GetOutputPort());&#xD;&#xA;      transformFilter-&gt;Update();&#xD;&#xA;      cellLocator-&gt;SetDataSet(transformFilter-&gt;GetOutput());&#xD;&#xA;    &#xD;&#xA;      double bounds[6];&#xD;&#xA;      cellLocator-&gt;GetBounds(bounds);&#xD;&#xA;      for (int i = 0; i &lt; 3; ++i)&#xD;&#xA;      {&#xD;&#xA;        bounds[2*i] += translate[i];&#xD;&#xA;        bounds[2*i+1] += translate[i];&#xD;&#xA;      }&#xD;&#xA;      cellLocator-&gt;SetBounds(bounds);&#xD;&#xA;    &#xD;&#xA;      double testPoint[3] = {2.0, 0.0, 0.0};&#xD;&#xA;    &#xD;&#xA;      //Find the closest points to TestPoint&#xD;&#xA;      double closestPoint[3];//the coordinates of the closest point will be returned here&#xD;&#xA;      double closestPointDist2; //the squared distance to the closest point will be returned here&#xD;&#xA;      vtkIdType cellId; //the cell id of the cell containing the closest point will be returned here&#xD;&#xA;      int subId; //this is rarely used (in triangle strips only, I believe)&#xD;&#xA;      cellLocator-&gt;FindClosestPoint(testPoint, closestPoint, cellId, subId, closestPointDist2);&#xD;&#xA;    &#xD;&#xA;      std::cout &lt;&lt; &quot;Coordinates of closest point: &quot; &lt;&lt; closestPoint[0] &lt;&lt; &quot; &quot; &lt;&lt; closestPoint[1] &lt;&lt; &quot; &quot; &lt;&lt; closestPoint[2] &lt;&lt; std::endl;&#xD;&#xA;      std::cout &lt;&lt; &quot;Squared distance to closest point: &quot; &lt;&lt; closestPointDist2 &lt;&lt; std::endl;&#xD;&#xA;      std::cout &lt;&lt; &quot;CellId: &quot; &lt;&lt; cellId &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;      return EXIT_SUCCESS;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21453" PostHistoryTypeId="2" PostId="8099" RevisionGUID="6f6ca7be-872c-4103-a9ef-dd709278e327" CreationDate="2018-09-25T12:54:15.490" UserId="9408" Text="For research purpose, I have to implement z-buffering algorithm to render 3D face models. But I got a problem that the triangles are too small to be rendered (i.e. there is no pixel covered completely  by a triangle in the given triangle list).&#xD;&#xA;&#xD;&#xA;I've tried to increase the resolution of the output image (so that the triangles get bigger) but it's $10,000 \times 10,000$ now (I think it's pretty high) and my computer can't suffer from higher resolutions.&#xD;&#xA;&#xD;&#xA;Does anybody know how to render 3D models quickly with z-buffering algorithm ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21454" PostHistoryTypeId="1" PostId="8099" RevisionGUID="6f6ca7be-872c-4103-a9ef-dd709278e327" CreationDate="2018-09-25T12:54:15.490" UserId="9408" Text="Z-buffering implementation with small triangles" ContentLicense="CC BY-SA 4.0" />
  <row Id="21455" PostHistoryTypeId="3" PostId="8099" RevisionGUID="6f6ca7be-872c-4103-a9ef-dd709278e327" CreationDate="2018-09-25T12:54:15.490" UserId="9408" Text="|rendering|3d|z-buffer|implementation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21456" PostHistoryTypeId="5" PostId="8099" RevisionGUID="d7a44b7a-d1ff-4a1f-b40f-9bd3c78ddf2d" CreationDate="2018-09-25T13:01:27.160" UserId="9408" Comment="deleted 8 characters in body" Text="For research purpose, I have to implement z-buffering algorithm to render 3D face models. But I got a problem that the triangles are too small to be rendered (i.e. there is no pixel covered completely  by any of the triangles).&#xD;&#xA;&#xD;&#xA;I've tried to increase the resolution of the output image (so that the triangles get bigger) but it's been $10,000 \times 10,000$ so far (I think it's pretty high) and my computer can't suffer from higher resolutions.&#xD;&#xA;&#xD;&#xA;Can you give me some solution for this problem ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21457" PostHistoryTypeId="2" PostId="8100" RevisionGUID="03d73121-e60b-4c9f-b24f-ef2254f01541" CreationDate="2018-09-25T13:07:07.380" UserId="209" Text="Assuming the small triangle form continuous surfaces, although many of the small triangles &quot;fall through the gaps&quot; (so to speak), some should still cover the samples. If on the other hand, they are separate/independent triangles then it will alias very badly.&#xD;&#xA;&#xD;&#xA;One possible alternative to just doing higher resolutions would be to simulate an [Accumulation Buffer][1]. In essence, do *N* XxY pixel renders, but for every render, offset the X&amp;Y screen coordinates by a sub-pixel amounts. &#xD;&#xA;&#xD;&#xA;You can then combine the *N* images, (perhaps initially with a simple box filter, but a Gaussian would be better) to produce your final XxY image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cse.msu.edu/~cse872/tutorial5.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="21458" PostHistoryTypeId="5" PostId="5761" RevisionGUID="8dffefa4-80cd-4285-a1a0-b61c7afadc26" CreationDate="2018-09-25T17:41:16.400" UserDisplayName="user5681" Comment="added 612 characters in body" Text="This question is somewhat related to [this one][1].&#xD;&#xA;&#xD;&#xA;As Alan has already said, following the actual path of the light ray through each layer leads to more physically accurate results. I will base my answer on a paper by Andrea Weidlich and Alexander Wilkie ([&quot;Arbitrarily Layered Micro-Facet Surfaces&quot;][2]) that I have read and partially implemented. In their paper they assume that the distance between two layers is smaller than the radius of a differential area element. This simplifies the implementation because we do not have to calculate intersection points separately for each layer, actually we assume that the intersection points are the same for all layers. &#xD;&#xA;&#xD;&#xA;According to the paper, two problems must be solved in order to render multilayered material. The first one is to properly sample the layers and the second is to find the resulting BSDF generated by the combination of the multiple BSDFs that are found along the sampling path. &#xD;&#xA;&#xD;&#xA;**UPDATE:** Actually I have adopted a different method to implement the evaluation of this layered model. While I have kept the idea of considering the intersection points to be just the same point along the layers, I have computed the sampling and the final BRDF differently: for sampling, I have used ordinary ray tracing, but through the layers (using Russian Roulette to select between reflection/refraction when that's the case); for the final BRDF evaluation, I just multiply each BRDF traversed by the ray path (weighting the incident radiances according to the cosine of the incident ray).&#xD;&#xA;&#xD;&#xA;**Sampling**&#xD;&#xA;&#xD;&#xA;In this first stage we will determine the actual light path through the layers. When a light ray is moving from a less dense medium, e.g. air, to a more dense medium, e.g. glass, part of its energy is reflected and the remaining part is transmitted. You can find the amount of energy that is reflected through the [Fresnel reflectance equations][3]. So, for instance, if the Fresnel reflectance of a given dielectric is 0.3, we know that 30% of the energy is reflected and 70% will be transmitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;When the light ray is moving from a more dense to a less dense medium, the same principle described by the Fresnel reflectance applies. However, in this specific case, [total internal reflection][5] (a.k.a TIR) might also happen if the angle of the incident ray is above the critical angle. In the case of TIR, 100% of the energy is reflected back into the material:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;When light hits a conductor or a diffuse surface, it will always be reflected (being the direction of reflection related to the type of the BRDF). In a multilayer material, the resulting light path will be the agregate result of all those possibilities. Thus, in the case of a 3-layer material, assuming that the first and secong layers are dielectrics and the third layer is diffuse, we might end up with the following light path (a tree actually):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;We can simulate this type of interaction using recursion and weighting each light path according to the actual reflectance/transmitance at the corresponding incident point. A problem regarding the use of recursion is that the number of rays increases with the deepness of the recursion, concentrating computational effort on rays that individually might contribute almost nothing to the final result. On the other hand, the aggregate result of those individual rays at deep recursion levels can be significant and should not be discarded. In this case, we can use Russian Roulette (RR) in order to avoid branching and to probabilistic end light paths without losing energy, but at the cost of a higher variance (noisier result). In this case, the result of the Fresnel reflectance, or the TIR, will be used to randomly select which path to follow. For instance:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;As can be seen, TIR or Fresnel reflectance might keep some rays bouncing indefinitely among layers. As far as I know, [Mitsuba][9] implements plastic as a two layer material, and it uses a closed form solution for this specific case that accounts for an infinity number of light bounces among layers. However, Mitsuba also allows for the creation of multilayer materials with an arbitrary number of layers, in which case it imposes a maximum number of internal bounces since no closed form solution seems to exist for the general case. As a side effect, some energy can be lost in the rendering process, making the material look darker than it should be. &#xD;&#xA;&#xD;&#xA;In my current multilayer material implementation I allow for an arbitrary number of internal bounces at the cost of longer rendering times (well... actually, I've implemented only two layers.. one dielectric and one diffuse :).&#xD;&#xA;&#xD;&#xA;An additional option is to mix branching and RR. For instance, the initial rays (lower deep levels) might present substantial contribution to the final image. Thus, one might choose to branch only at the first one or two intersections, using only RR afterwards. This is the case with [smallpt][10].&#xD;&#xA;&#xD;&#xA;An interesting point regarding multilayered materials is that individual reflected/transmitted rays can be importance sampled according to the corresponding BRDFs/BTDFs of the current layer. &#xD;&#xA;&#xD;&#xA;**Evaluating the Final BSDF**&#xD;&#xA;&#xD;&#xA;Considering the following light path computed using RR:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;We can evaluate the total amount of radiance $L_r$ reflected by a multilayer BSDF considering each layer as a individual object and applying the same approach used in ordinary path tracing (i.e. the radiance leaving a layer will be the incident radiance for the next layer). The final estimator can thus be represented by the product of each individual Monte Carlo estimator:&#xD;&#xA;&#xD;&#xA;$$ L_r =  \left( \frac{fr_1 \cos \theta_1}{pdf_1}  \left( \frac{fr_2 \cos \theta_2}{pdf_2} \left( \frac{fr_3 \cos \theta_3}{pdf_3} \left( \frac{fr_2 \cos \theta_4}{pdf_2} \left( \frac{L_i fr_1 \cos \theta_5}{pdf_1} \right)\right)\right)\right)\right)$$&#xD;&#xA;&#xD;&#xA;The [paper][2] by Andrea Weidlich and Alexander Wilkie also takes absorption into consideration, i.e. each light ray might be attenuated according to the absorption factor of each transmissive layer and to the distance traveled by the ray within the layer. I've not included absorption into my renderer yet, but it is just a real coefficient computed according to the [Beer's Law][12].&#xD;&#xA;&#xD;&#xA;**Alternate approaches**&#xD;&#xA;&#xD;&#xA;The Mitsuba renderer uses an alternate representation for multilayered material based on the &quot;tabulation of reflectance functions in a Fourier basis&quot;. I have not yet dig into it, but might be of interest: &quot;[A Comprehensive Framework for Rendering Layered Materials][13]&quot; by Wenzel Jacob *et al*. There is also an expanded version of this paper.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4611/5681&#xD;&#xA;  [2]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [4]: https://i.stack.imgur.com/S4zHY.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Total_internal_reflection&#xD;&#xA;  [6]: https://i.stack.imgur.com/Li0lu.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/WBz0l.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/t5ewd.png&#xD;&#xA;  [9]: https://www.mitsuba-renderer.org&#xD;&#xA;  [10]: http://www.kevinbeason.com/smallpt&#xD;&#xA;  [11]: https://i.stack.imgur.com/GWv6b.png&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law&#xD;&#xA;  [13]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 4.0" />
  <row Id="21459" PostHistoryTypeId="2" PostId="8101" RevisionGUID="d6b36b5f-7dc7-43b3-b880-4f19bf9a36e0" CreationDate="2018-09-25T17:56:37.497" UserId="38" Text="Current mainstream technology does not really model the density functions very well. Yeah, we can use volumetric grids, FEM, voxel representations and particle clouds that define densities. But these files dont scale, worse theres no practical way to model the distributions effectively. &#xD;&#xA;&#xD;&#xA;But we are, slowly but surely, entering a new age of manufacturing where it is not enough to know just what the surface looks like, but know what is inside the structure, not just that its one material. But rather some amalgamation of properties that can change smoothly or abruptly depending on your need. &#xD;&#xA;&#xD;&#xA;But how would we handle this in a way that is still editable? Is anybody aware of any methods that might eventually lead us to next level of model definition? The best i have so far seen is some general implicit density representations like extended meta balls but its till not accurate enough for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="21460" PostHistoryTypeId="1" PostId="8101" RevisionGUID="d6b36b5f-7dc7-43b3-b880-4f19bf9a36e0" CreationDate="2018-09-25T17:56:37.497" UserId="38" Text="Has anybody extended parametric surfaces to volume density representations usefully?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21461" PostHistoryTypeId="3" PostId="8101" RevisionGUID="d6b36b5f-7dc7-43b3-b880-4f19bf9a36e0" CreationDate="2018-09-25T17:56:37.497" UserId="38" Text="|model|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21462" PostHistoryTypeId="5" PostId="8101" RevisionGUID="653c0dc7-3d01-4490-a7d3-779d942b0ef7" CreationDate="2018-09-25T18:15:37.067" UserId="38" Comment="added 12 characters in body" Text="Current mainstream technology does not really model the density functions very well. Yeah, we can use volumetric grids, FEM, voxel representations and particle clouds that define densities. But these files dont scale, worse theres no practical way to model the distributions effectively. &#xD;&#xA;&#xD;&#xA;But we are, slowly but surely, entering a new age of manufacturing where it is not enough to know just what the surface looks like, but know what is inside the structure, not just that its one material. But rather some amalgamation of properties that can change smoothly or abruptly depending on your need. &#xD;&#xA;&#xD;&#xA;But how would we handle this in a way that is still editable? Is anybody aware of any methods that might eventually lead us to next level of model definition? The best i have so far seen is some general implicit density representations like extended meta balls but its still not accurate enough, or usable for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="21463" PostHistoryTypeId="2" PostId="8102" RevisionGUID="fe148398-24c7-4950-a896-a07e22cd0ca0" CreationDate="2018-09-25T22:55:19.760" UserId="8893" Text="I have been following LearnOpenGL.com 's tutorials on PBR. Everything makes sense and I wrote up a shader for my physically based renderer.&#xD;&#xA;&#xD;&#xA;I noticed that the results look great, however all of my metal objects have such a strong specular on the edges thanks to my Fresnel calculation, and it is producing specular aliasing.&#xD;&#xA;See image: https://i.stack.imgur.com/Rreid.jpg&#xD;&#xA;&#xD;&#xA;I can't seem to figure out why, or how to fix this. I also uploaded a simplified version of my PBR fragment shader. If someone could take a look, I would really appreciate it.&#xD;&#xA;&#xD;&#xA;Simplified PBR fragment shader: https://textuploader.com/dv3h1&#xD;&#xA;&#xD;&#xA;Here is the tutorial I am following: https://learnopengl.com/PBR/Lighting&#xD;&#xA;It doesn't seem to have any of these specular aliasing issues.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="21464" PostHistoryTypeId="1" PostId="8102" RevisionGUID="fe148398-24c7-4950-a896-a07e22cd0ca0" CreationDate="2018-09-25T22:55:19.760" UserId="8893" Text="PBR and Specular Aliasing" ContentLicense="CC BY-SA 4.0" />
  <row Id="21465" PostHistoryTypeId="3" PostId="8102" RevisionGUID="fe148398-24c7-4950-a896-a07e22cd0ca0" CreationDate="2018-09-25T22:55:19.760" UserId="8893" Text="|physically-based|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21466" PostHistoryTypeId="50" PostId="7932" RevisionGUID="e3cf40ab-9e7a-47ec-a412-b9606c2df5d4" CreationDate="2018-09-26T07:00:50.833" UserId="-1" />
  <row Id="21467" PostHistoryTypeId="5" PostId="8022" RevisionGUID="aa4212d5-41f5-4782-ab1d-b6f719c92065" CreationDate="2018-09-26T07:44:01.433" UserId="209" Comment="fixed an orphaned &quot;and..&quot;" Text="If you are doing a perspective image and your model has implicit intersections then, if you use &quot;linear Z&quot;, those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles, receding into the distance,  which pierce the ground (and continue below). The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with `1/Z`, then when the projected vertices have been computed with perspective, the image will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologise for the non-aesthetic quality of the following illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first image shows the required rendering effect. (Note that the blue &quot;pylons&quot; go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This second image shows the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc and I've no idea what has happened with the scaling.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are incorrect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;Re your later comment:&#xD;&#xA;&gt; “if those are not interpolated with 1/Z” that I don’t understand. What interpolation is that?&#xD;&#xA;&#xD;&#xA;The first thing to note is that, with a standard perspective projection, straight lines in world space remain straight lines in perspective space. Distances/lengths, however, are not preserved.&#xD;&#xA;&#xD;&#xA;For simplicity, let us assume a trivial perspective transform is used to project the vertices, i.e.&#xD;&#xA;$$X_{Screen} = \frac{X_{World}}{Z_{World}}$$&#xD;&#xA;$$Y_{Screen} = \frac{Y_{World}}{Z_{World}}$$&#xD;&#xA;We *should* also compute a reciprocal screen-space depth, e.g. $$Z_{Screen} = \frac{1}{Z_{World}}$$ but a linear Z would in the depth buffer would, to me, imply something like: $$Z_{Screen} = scale*Z_{World}$$ *(We can assume here that scale=1)*&#xD;&#xA;&#xD;&#xA;Let's assume we have a line with world space end points$$&#xD;&#xA;  \begin{matrix} \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and &#xD;&#xA;   \begin{bmatrix}&#xD;&#xA;    200 \\&#xD;&#xA;    0   \\&#xD;&#xA;    10  \\&#xD;&#xA;    \end{bmatrix}\\&#xD;&#xA;  \end{matrix}&#xD;&#xA;$$&#xD;&#xA;With the perspective mapping these map to screen space coordinates&#xD;&#xA; $$ \begin{matrix}   \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and \begin{bmatrix}&#xD;&#xA;    20 \\&#xD;&#xA;    0  \\&#xD;&#xA;    0.1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; \end{matrix}$$&#xD;&#xA;&#xD;&#xA;The rendering system/hardware will linearly interpolate the screen space z, so at the 1/2 way point of the line, as it appears on-screen, i.e. at pixel (10, 0), we would get a projected (inverse) Z value of 0.55, which corresponds to to a world space Z value value of ~1.818. Given the starting and end Z values, this is about 20% along the length of the line.&#xD;&#xA;&#xD;&#xA;If instead, we tried to interpolate using the original Z values, we'd end up with Z corresponding to a world space value of 5.5. As long as nothing intersects, you might be ok (I've not thought about it too thoroughly) but anything with implicit intersections *will* be incorrect.&#xD;&#xA;&#xD;&#xA;What I haven't mentioned is that once you introduce perspective correct texturing (or even perspective correct shading), you must do per-pixel interpolation of 1/w and, additionally, also compute, per pixel, the reciprocal of that interpolated value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21468" PostHistoryTypeId="5" PostId="8100" RevisionGUID="bc2313d3-245b-4a00-ac53-6dca15162225" CreationDate="2018-09-26T10:54:06.310" UserId="209" Comment="Added response to OP's comment" Text="Assuming the small triangle form continuous surfaces, although many of the small triangles &quot;fall through the gaps&quot; (so to speak), some should still cover the samples. If on the other hand, they are separate/independent triangles then it will alias very badly.&#xD;&#xA;&#xD;&#xA;One possible alternative to just doing higher resolutions would be to simulate an [Accumulation Buffer][1]. In essence, do *N* XxY pixel renders, but for every render, offset the X&amp;Y screen coordinates by a sub-pixel amounts. &#xD;&#xA;&#xD;&#xA;You can then combine the *N* images, (perhaps initially with a simple box filter, but a Gaussian would be better) to produce your final XxY image.&#xD;&#xA;&#xD;&#xA;&gt;Can you explain what does &quot;offset the X&amp;Y screen coordinates by a sub-pixel amounts.&quot; mean ?&#xD;&#xA;&#xD;&#xA;Perhaps it'd be a good idea to read  [Haeberli and Akeley's original paper][2] but I'll try to put in a bit of an explanation on how I would try to do the XY shifts.&#xD;&#xA;&#xD;&#xA;Let's assume we want to shift the image by $(x_{offset}, y_{offset})$ in pixels where, *probably*, $|x_{offset}| &lt; 0.5$ and $|y_{offset}|&lt;0.5$.&#xD;&#xA;&#xD;&#xA;We want to add this offset to each vertex *after* it's been projected into screen coordinates. Now since we don't have much control of the pipeline post clipping and projection, we'll need to do that by adjusting the projection matrix. If we assume our default projection matrix, P, does something of the following:&#xD;&#xA;$$(X_{world}, Y_{world}, Z_{world}, 1).P=(X_{clip},Y_{clip},Z_{clip}, W_{clip})$$&#xD;&#xA;i.e. maps from world space to clip space, then to shift the points in image space we'll need an additional &quot;matrix&quot; adjustment which, off the top of my head, will be *something* like...&#xD;&#xA;$$Adjust= \begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0&amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp;1&amp; 0 \\&#xD;&#xA;    scaledX_{offset} &amp; scaledY_{offset} &amp;0&amp; 1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;The &quot;scaling&quot; should take into account the resolution of the target image. &#xD;&#xA;&#xD;&#xA;Create a new, per offset, projection matrix from $P.Adjust$ for each &quot;offset&quot; image you want to accumulate.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cse.msu.edu/~cse872/tutorial5.html&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/haeberli-akeley-accumulation-buffer-sig90.pdf &quot;The Accumulation Buffer&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21469" PostHistoryTypeId="5" PostId="8100" RevisionGUID="809d24e8-3685-484c-b01a-3ce4e9dd66bd" CreationDate="2018-09-26T11:02:17.860" UserId="209" Comment="added 88 characters in body" Text="Assuming the small triangle form continuous surfaces, although many of the small triangles &quot;fall through the gaps&quot; (so to speak), some should still cover the samples. If on the other hand, they are separate/independent triangles then it will alias very badly.&#xD;&#xA;&#xD;&#xA;One possible alternative to just doing higher resolutions would be to simulate an [Accumulation Buffer][1]. In essence, do *N* XxY pixel renders, but for every render, offset the X&amp;Y screen coordinates by a sub-pixel amounts. &#xD;&#xA;&#xD;&#xA;You can then combine the *N* images, (perhaps initially with a simple box filter, but a Gaussian would be better) to produce your final XxY image.&#xD;&#xA;&#xD;&#xA;&gt;Can you explain what does &quot;offset the X&amp;Y screen coordinates by a sub-pixel amounts.&quot; mean ?&#xD;&#xA;&#xD;&#xA;Perhaps it'd be a good idea to read  [Haeberli and Akeley's original paper][2] but I'll try to put in a bit of an explanation on how I would try to do the XY shifts. (*I apologise in advance if I've made some fundamental flaw in the following logic...*)&#xD;&#xA;&#xD;&#xA;Let's assume we want to shift the image by $(x_{offset}, y_{offset})$ in pixels where, *probably*, $|x_{offset}| &lt; 0.5$ and $|y_{offset}|&lt;0.5$.&#xD;&#xA;&#xD;&#xA;We want to add this offset to each vertex *after* it's been projected into screen coordinates. Now since we don't have much control of the pipeline post clipping and projection, we'll need to do that by adjusting the projection matrix. If we assume our default projection matrix, P, does something of the following:&#xD;&#xA;$$(X_{world}, Y_{world}, Z_{world}, 1).P=(X_{clip},Y_{clip},Z_{clip}, W_{clip})$$&#xD;&#xA;i.e. maps from world space to clip space, then to shift the points in image space we'll need an additional &quot;matrix&quot; adjustment which, off the top of my head, will be *something* like...&#xD;&#xA;$$Adjust= \begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0&amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp;1&amp; 0 \\&#xD;&#xA;    scaledX_{offset} &amp; scaledY_{offset} &amp;0&amp; 1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;The &quot;scaling&quot; should take into account the resolution of the target image. &#xD;&#xA;&#xD;&#xA;Create a new, per offset, projection matrix from $P.Adjust$ for each &quot;offset&quot; image you want to accumulate.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cse.msu.edu/~cse872/tutorial5.html&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/haeberli-akeley-accumulation-buffer-sig90.pdf &quot;The Accumulation Buffer&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21470" PostHistoryTypeId="5" PostId="8100" RevisionGUID="6e347d6f-a6ce-4942-b022-fae5682a0535" CreationDate="2018-09-26T12:03:15.117" UserId="209" Comment="more fixes to my appalling English" Text="Assuming the small triangles form continuous surfaces, although many of the small triangles &quot;fall through the gaps&quot; (so to speak), some should still cover the samples. If on the other hand, they are separate/independent triangles then it will alias very badly.&#xD;&#xA;&#xD;&#xA;One possible alternative to just doing higher resolutions would be to simulate an [Accumulation Buffer][1]. In essence, do *N* XxY pixel renders, but for every render, offset the X&amp;Y screen coordinates by a sub-pixel amounts. &#xD;&#xA;&#xD;&#xA;You can then combine the *N* images, (perhaps initially with a simple box filter, but a Gaussian would be better) to produce your final XxY image.&#xD;&#xA;&#xD;&#xA;&gt;Can you explain what does &quot;offset the X&amp;Y screen coordinates by a sub-pixel amounts.&quot; mean ?&#xD;&#xA;&#xD;&#xA;Perhaps it'd be a good idea to read  [Haeberli and Akeley's original paper][2] but I'll try to put in a bit of an explanation on how I would try to do the XY shifts. (*I apologise in advance if I've made some fundamental flaw in the following logic...*)&#xD;&#xA;&#xD;&#xA;Let's assume we want to shift the image by $(x_{offset}, y_{offset})$ in pixels where, *probably*, $|x_{offset}| &lt; 0.5$ and $|y_{offset}|&lt;0.5$.&#xD;&#xA;&#xD;&#xA;We want to add this offset to each vertex *after* it's been projected into screen coordinates. Now since we don't have much control of the pipeline post clipping and projection, we'll need to do that by adjusting the projection matrix. If we assume our default projection matrix, P, does something of the following:&#xD;&#xA;$$(X_{world}, Y_{world}, Z_{world}, 1).P=(X_{clip},Y_{clip},Z_{clip}, W_{clip})$$&#xD;&#xA;i.e. maps from world space to clip space, then to shift the points in image space we'll need an additional &quot;matrix&quot; adjustment which, off the top of my head, will be *something* like...&#xD;&#xA;$$Adjust= \begin{bmatrix}&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; 0&amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp;1&amp; 0 \\&#xD;&#xA;    scaledX_{offset} &amp; scaledY_{offset} &amp;0&amp; 1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;The &quot;scaling&quot; should take into account the resolution of the target image. &#xD;&#xA;&#xD;&#xA;Create a new, per offset, projection matrix from $P.Adjust$ for each &quot;offset&quot; image you want to accumulate.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cse.msu.edu/~cse872/tutorial5.html&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/haeberli-akeley-accumulation-buffer-sig90.pdf &quot;The Accumulation Buffer&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21485" PostHistoryTypeId="2" PostId="8105" RevisionGUID="cbe2ed91-c771-4a88-8c1b-eaf6a4916c1a" CreationDate="2018-09-30T01:23:13.883" UserId="9429" Text="I've watched the [Pixar In A Box, Maths of Rendering Tutorial][1] on Khan Academy. I've started writing a raytracing program and have come to the point where I must solve for `t` (the parameter for the parametric ray through the camera and a point on the view plane). &#xD;&#xA;&#xD;&#xA;In the tutorial, this is done through simply substituting each the parametric formula for each `x`, `y`, and `z` into the equation of the plane that the triangle lies on. This leaves a single unknown (`t`).&#xD;&#xA;&#xD;&#xA;However, in all the examples and exercises that are given by the tutorial the camera is located at [0,0,0]. As I'm sure you'll understand, this is in many cases unrealistic. Because the camera is at 0, they simplify as follows:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?i=\frac{1}{t}C&amp;plus;tP&quot; title=&quot;i=\frac{1}{t}C+tP&quot; /&gt;&#xD;&#xA;&#xD;&#xA;becomes simply:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?tP&quot; title=&quot;tP&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Which makes for an easy solve. My question is when the camera is not at [0,0,0] should I:&#xD;&#xA;&#xD;&#xA; 1. Calculate the coordinates of the plane relative to the camera. (So the camera acts as if it is [0,0,0]&#xD;&#xA; 2. Solve the equation as a quadratic. I'm still confused a bit about why this is a quadratic in the first place. Could someone explain this? And which solution do I use?&#xD;&#xA;&#xD;&#xA;Of the two options, which is more acceptable for use in this community? Why? Is one more computationally efficient?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khanacademy.org/partner-content/pixar/rendering/rendering-2/a/rendering-lesson-brief" ContentLicense="CC BY-SA 4.0" />
  <row Id="21486" PostHistoryTypeId="1" PostId="8105" RevisionGUID="cbe2ed91-c771-4a88-8c1b-eaf6a4916c1a" CreationDate="2018-09-30T01:23:13.883" UserId="9429" Text="How to raytrace triangular faces when camera is not at origin?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21487" PostHistoryTypeId="3" PostId="8105" RevisionGUID="cbe2ed91-c771-4a88-8c1b-eaf6a4916c1a" CreationDate="2018-09-30T01:23:13.883" UserId="9429" Text="|raytracing|3d|pixel-graphics|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21488" PostHistoryTypeId="5" PostId="8105" RevisionGUID="bc8dae9e-f2df-4d6e-ba96-99cb63affc75" CreationDate="2018-09-30T02:16:41.880" UserId="9429" Comment="learnt important information" Text="I've watched the [Pixar In A Box, Maths of Rendering Tutorial][1] on Khan Academy. I've started writing a raytracing program and have come to the point where I must solve for `t` (the parameter for the parametric ray through the camera and a point on the view plane). &#xD;&#xA;&#xD;&#xA;In the tutorial, this is done through simply substituting each the parametric formula for each `x`, `y`, and `z` into the equation of the plane that the triangle lies on. This leaves a single unknown (`t`).&#xD;&#xA;&#xD;&#xA;However, in all the examples and exercises that are given by the tutorial the camera is located at [0,0,0]. As I'm sure you'll understand, this is in many cases unrealistic. Because the camera is at 0, they simplify as follows:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?i=\frac{1}{t}C&amp;plus;tP&quot; title=&quot;i=\frac{1}{t}C+tP&quot; /&gt;&#xD;&#xA;&#xD;&#xA;becomes simply:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?tP&quot; title=&quot;tP&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Which makes for an easy solve. My question is when the camera is not at [0,0,0] should I:&#xD;&#xA;&#xD;&#xA; 1. Calculate the coordinates of the plane relative to the camera. (So the camera acts as if it is [0,0,0]&#xD;&#xA; 2. Solve the equation as a quadratic. I'm still confused a bit about why this is a quadratic in the first place. Could someone explain this? And which solution do I use?&#xD;&#xA;&#xD;&#xA;Of the two options, which is more acceptable for use in this community? Why? Is one more computationally efficient?&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;I think I have found a solution as follows:&#xD;&#xA;The parametric equation (which is effectively just a weighted average) is represented like this in the tutorial:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?x(t)&amp;space;=&amp;space;\frac{1}{t}C_{x}&amp;plus;tP_{x}&quot; title=&quot;x(t) = \frac{1}{t}C_{x}+tP_{x}&quot; /&gt;&#xD;&#xA;&#xD;&#xA;But I realize now that is the same as:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?x(t)&amp;space;=C_{x}&amp;space;&amp;plus;t(P_{x}-C_{x})&quot; title=&quot;x(t) =C_{x} +t(P_{x}-C_{x})&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Which is dramatically easier to solve. &#xD;&#xA;&#xD;&#xA;So my final question is, which of the three is the most acceptable way to solve for t? I'm assuming the third one.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khanacademy.org/partner-content/pixar/rendering/rendering-2/a/rendering-lesson-brief" ContentLicense="CC BY-SA 4.0" />
  <row Id="21489" PostHistoryTypeId="12" PostId="8105" RevisionGUID="a1953a57-e1cc-4d91-b2d0-a46817fef276" CreationDate="2018-09-30T04:31:50.727" UserId="9429" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:9429,&quot;DisplayName&quot;:&quot;PolymorphismPrince&quot;}]}" />
  <row Id="21490" PostHistoryTypeId="13" PostId="8105" RevisionGUID="a4318bce-974d-489a-a189-7b57850d8814" CreationDate="2018-09-30T04:32:00.193" UserId="9429" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:9429,&quot;DisplayName&quot;:&quot;PolymorphismPrince&quot;}]}" />
  <row Id="21491" PostHistoryTypeId="2" PostId="8106" RevisionGUID="fbad9873-4996-4b41-8769-2e2bf86a5a35" CreationDate="2018-09-30T04:33:23.613" UserId="9429" Text="Wow I'm stupid, the whole problem was I thought it was `1/t` and it is actually `1/t` in parametric form. Hope this helps someone anyway." ContentLicense="CC BY-SA 4.0" />
  <row Id="21492" PostHistoryTypeId="50" PostId="7997" RevisionGUID="f77d99ad-52a4-4e8d-a7fa-6715540c6960" CreationDate="2018-09-30T08:01:03.560" UserId="-1" />
  <row Id="21494" PostHistoryTypeId="2" PostId="8107" RevisionGUID="3615dcd0-67fd-481a-8e61-e4139bd31cb7" CreationDate="2018-10-01T17:24:11.883" UserDisplayName="user9436" Text="I don't think there is much to explain here, since the question is pretty much in the title, but i'll try to explain myself better:&#xD;&#xA;&#xD;&#xA;My current laptop's gpu does not support Vulkan, so i was wondering if it was possible to do something like d3d12 does, where if a specific function is not able to be performed by the gpu, it can be emulated by the cpu, while maintaing the program running and functioning, at the obvious cost of performance.&#xD;&#xA;&#xD;&#xA;Can I achive something like that using Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21495" PostHistoryTypeId="1" PostId="8107" RevisionGUID="3615dcd0-67fd-481a-8e61-e4139bd31cb7" CreationDate="2018-10-01T17:24:11.883" UserDisplayName="user9436" Text="Is it possible to emulate Vulkan on a non Vulkan compatible gpu?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21496" PostHistoryTypeId="3" PostId="8107" RevisionGUID="3615dcd0-67fd-481a-8e61-e4139bd31cb7" CreationDate="2018-10-01T17:24:11.883" UserDisplayName="user9436" Text="|rendering|gpu|vulkan|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21497" PostHistoryTypeId="2" PostId="8108" RevisionGUID="68374cbd-6844-4790-8b04-3e446b6086e0" CreationDate="2018-10-01T18:56:56.767" UserId="9306" Text="It's possible to emulate Vulkan on a sufficiently capable non-Vulkan API.  This is the point of the Vulkan Portability Initiative.  Indeed, there is already a Vulkan implementation on top of the Apple proprietary API Metal, and there is work being done to implement Vulkan on top of D3D12.  &#xD;&#xA;&#xD;&#xA;It probably _would_ be possible to implement a version of Vulkan that ran partially on a GPU (to which you had some other API access) and partially in software on the CPU, but unless you're working with some kind of mobile device with integrated memory, the performance of such a system would probably be utter garbage.  &#xD;&#xA;&#xD;&#xA;If your goal is to better understand and develop for Vulkan, I'd suggest you investigate some of the existing efforts at creating a fully software Vulkan implementation.&#xD;&#xA;&#xD;&#xA;If you're just trying to get some game to run better, I suggest you get a better laptop." ContentLicense="CC BY-SA 4.0" />
  <row Id="21498" PostHistoryTypeId="2" PostId="8109" RevisionGUID="43a2d8b4-1a98-416f-9026-f9293fde736a" CreationDate="2018-10-01T20:49:34.253" UserId="9438" Text="Yes this is exactly what [Mesa][1] does. Also note that many older GPU's (prior to 2015, when Vulkan got released) support Vulkan (approx 2012, both nVidia and AMD), although this isn't the case for the Laptop variants. ymmv.&#xD;&#xA;&#xD;&#xA;[1]: https://en.wikipedia.org/wiki/Mesa_(computer_graphics)" ContentLicense="CC BY-SA 4.0" />
  <row Id="21499" PostHistoryTypeId="2" PostId="8110" RevisionGUID="67404164-8551-416f-acdb-c674dd43de3e" CreationDate="2018-10-01T21:23:18.093" UserId="1992" Text="I have multiple separate shapes for which I have generated signed distance fields by merging and clipping them against each other. **Is there a generic analytical solution for merge and clip operations of signed distance fields?**&#xD;&#xA;&#xD;&#xA;For example, the result of clipping a horizontal and vertical edge, producing the convex corner (green), the MAX operation results in a correct shape interior, but incorrect exterior. The points in the bottom-right quadrant of the image have values closer than they should.  This is the result of the formerly-closest points no longer being present in the post-clipped image.&#xD;&#xA;&#xD;&#xA;[![Incorrect Clip Result][1]][1]&#xD;&#xA;&#xD;&#xA;The correct SDF should look like this, with the bottom-right quadrant being a conic/radial shape, as for all points in that quadrant, their closest point is the shape corner itself.&#xD;&#xA;&#xD;&#xA;[![Correct Clip Result][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KtnVS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SSm0a.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21500" PostHistoryTypeId="1" PostId="8110" RevisionGUID="67404164-8551-416f-acdb-c674dd43de3e" CreationDate="2018-10-01T21:23:18.093" UserId="1992" Text="Merging/Clipping Signed Distance Fields" ContentLicense="CC BY-SA 4.0" />
  <row Id="21501" PostHistoryTypeId="3" PostId="8110" RevisionGUID="67404164-8551-416f-acdb-c674dd43de3e" CreationDate="2018-10-01T21:23:18.093" UserId="1992" Text="|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21502" PostHistoryTypeId="2" PostId="8111" RevisionGUID="877b551d-a37c-4bbf-9cd1-e74302d1842f" CreationDate="2018-10-02T05:43:19.687" UserDisplayName="user9436" Text="I'm making a cross-platform application, and i need my shaders to be compiled to SPIR-V for both Opengl and Vulkan. It seems that the only way to do so is to call a separate program, called &quot;glslangValidator.exe/.deb/.dmg&quot;. This sort of makes it cross-platform, but it requires me to change the command that calls the program on each platform (and that's not ideal to me). Can i embed some code or use something else to compile shaders directly from my application?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21503" PostHistoryTypeId="1" PostId="8111" RevisionGUID="877b551d-a37c-4bbf-9cd1-e74302d1842f" CreationDate="2018-10-02T05:43:19.687" UserDisplayName="user9436" Text="Can i compile my shaders to SPIR-V without using glslangValidator?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21504" PostHistoryTypeId="3" PostId="8111" RevisionGUID="877b551d-a37c-4bbf-9cd1-e74302d1842f" CreationDate="2018-10-02T05:43:19.687" UserDisplayName="user9436" Text="|shader|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21505" PostHistoryTypeId="2" PostId="8112" RevisionGUID="2ac9f61a-2de5-4edb-8b05-b795705c95ad" CreationDate="2018-10-02T08:36:18.160" UserId="9306" Text="Typically compiling GLSL to SPIRV would be something you do as part of the build process, so that you end up distributing SPIRV instead of GLSL.  Then you don't need to compile it at runtime.  Assuming you're using the Vulkan SDK, the binary for glslangValidator (or a shell script to build it) should be part of the installed SDK.  &#xD;&#xA;&#xD;&#xA;That said, if you want to compile GLSL to SPIRV at runtime, you can link against the glslang library and do that.  Take a look at the _Programatic Interface_ section in the [readme](https://github.com/KhronosGroup/glslang/blob/master/README.md).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21506" PostHistoryTypeId="2" PostId="8113" RevisionGUID="cccbec2e-e90b-4694-9bf8-2078bacef638" CreationDate="2018-10-03T21:01:44.997" UserId="7462" Text="I have the following image and depth map from a CV paper:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I want to know if there is an existing way to apply screen space rendering to a pre-existing image.&#xD;&#xA;&#xD;&#xA;Before someone yells ate me saying &quot;Why render over a literal picture when you can only make it worse!&quot;&#xD;&#xA;&#xD;&#xA;I have a program that changes multiple aspects of the original image, (color of certain objects and re-texturing of some surfaces).&#xD;&#xA;&#xD;&#xA;So the original colors are wrong with respect to the modified image.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QsXCt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21507" PostHistoryTypeId="1" PostId="8113" RevisionGUID="cccbec2e-e90b-4694-9bf8-2078bacef638" CreationDate="2018-10-03T21:01:44.997" UserId="7462" Text="How to apply SSRT to an existing image with associated depth map?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21508" PostHistoryTypeId="3" PostId="8113" RevisionGUID="cccbec2e-e90b-4694-9bf8-2078bacef638" CreationDate="2018-10-03T21:01:44.997" UserId="7462" Text="|rendering|human-vision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21509" PostHistoryTypeId="5" PostId="8106" RevisionGUID="47f2a757-307c-4ee0-a93b-da1c30db87db" CreationDate="2018-10-03T21:50:00.827" UserId="9429" Comment="edited body" Text="Wow I'm stupid, the whole problem was I thought it was `1/t` and it is actually `1-t` in parametric form. Hope this helps someone anyway." ContentLicense="CC BY-SA 4.0" />
  <row Id="21510" PostHistoryTypeId="50" PostId="8014" RevisionGUID="96a2bd31-d361-491a-a2ec-45702ae64854" CreationDate="2018-10-04T00:00:19.610" UserId="-1" />
  <row Id="21511" PostHistoryTypeId="50" PostId="6373" RevisionGUID="c22370e9-d53c-4fe7-a418-ae0cbbecbd23" CreationDate="2018-10-04T06:00:34.237" UserId="-1" />
  <row Id="21512" PostHistoryTypeId="2" PostId="8114" RevisionGUID="38a72ba5-2925-45d5-957c-66eb1acd1ee7" CreationDate="2018-10-04T20:21:49.400" UserId="9448" Text="I'd like to simulate a rubber-like material. This material if deformed would experience a restoring force to its original shape, a bit like a school rubber ereaser. &#xD;&#xA;&#xD;&#xA;I tried with a spring-mass system but the system become quickly instable, moreover it's computational expansive.&#xD;&#xA;&#xD;&#xA;Doing some research I found out I could simulate this behaviour through finite element method If I understood well. The problem is I haven't got the right mathematical tools to understand this method.&#xD;&#xA;&#xD;&#xA;So how would you face up to this problem?&#xD;&#xA;Resources, links, tutorials, papers are welcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="21513" PostHistoryTypeId="1" PostId="8114" RevisionGUID="38a72ba5-2925-45d5-957c-66eb1acd1ee7" CreationDate="2018-10-04T20:21:49.400" UserId="9448" Text="How to simulate elastic material with restoring shape" ContentLicense="CC BY-SA 4.0" />
  <row Id="21514" PostHistoryTypeId="3" PostId="8114" RevisionGUID="38a72ba5-2925-45d5-957c-66eb1acd1ee7" CreationDate="2018-10-04T20:21:49.400" UserId="9448" Text="|mathematics|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21515" PostHistoryTypeId="2" PostId="8115" RevisionGUID="7f64d416-a823-41fa-8a6c-135dfeb094bc" CreationDate="2018-10-04T21:13:49.600" UserId="3416" Text="Assume eye position e, gaze direction g, view-up vector t, right-handed base.   &#xD;&#xA;$w=-\frac{g}{||g||}$  &#xD;&#xA;$u=\frac{t\times w}{||t\times w||}$  &#xD;&#xA;$v=w\times u$&#xD;&#xA;&#xD;&#xA;I am really confused about the 2nd equation $u=\frac{t\times w}{||t\times w||}$.  &#xD;&#xA;What if the camera rotate around its gaze direction?   &#xD;&#xA;Then the vector t will not in the plane that w and u lies in which means the second equation is wrong.&#xD;&#xA;&#xD;&#xA;I know I have something misunderstood.   &#xD;&#xA;Could someone please give me some clues?    &#xD;&#xA;&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="21516" PostHistoryTypeId="1" PostId="8115" RevisionGUID="7f64d416-a823-41fa-8a6c-135dfeb094bc" CreationDate="2018-10-04T21:13:49.600" UserId="3416" Text="Understanding of Camera Up Vector" ContentLicense="CC BY-SA 4.0" />
  <row Id="21517" PostHistoryTypeId="3" PostId="8115" RevisionGUID="7f64d416-a823-41fa-8a6c-135dfeb094bc" CreationDate="2018-10-04T21:13:49.600" UserId="3416" Text="|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21518" PostHistoryTypeId="50" PostId="5697" RevisionGUID="75dccbc4-d0bc-4abd-9e2b-fd4f5e61904e" CreationDate="2018-10-05T01:00:13.170" UserId="-1" />
  <row Id="21519" PostHistoryTypeId="5" PostId="8115" RevisionGUID="e7d741c1-f11b-45c4-bb2a-6ff7554f83d0" CreationDate="2018-10-05T01:58:25.693" UserId="3416" Comment="edited body" Text="Assume eye position e, gaze direction g, view-up vector t, right-handed base.   &#xD;&#xA;$w=-\frac{g}{||g||}$  &#xD;&#xA;$u=\frac{t\times w}{||t\times w||}$  &#xD;&#xA;$v=w\times u$&#xD;&#xA;&#xD;&#xA;I am really confused about the 2nd equation $u=\frac{t\times w}{||t\times w||}$.  &#xD;&#xA;What if the camera rotate around its gaze direction? The v rotates while the t stays the same.  &#xD;&#xA;Then the vector t will not in the plane that w and v lies in which means the second equation is wrong.&#xD;&#xA;&#xD;&#xA;I know I have something misunderstood.   &#xD;&#xA;Could someone please give me some clues?    &#xD;&#xA;&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="21520" PostHistoryTypeId="5" PostId="8115" RevisionGUID="c3934fee-c0c4-42c2-ab63-30b33304071c" CreationDate="2018-10-05T02:12:04.243" UserId="3416" Comment="added 119 characters in body" Text="Assume eye position e, gaze direction g, view-up vector t, right-handed base. As the graphs shows:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;&#xD;&#xA;$w=-\frac{g}{||g||}$  &#xD;&#xA;$u=\frac{t\times w}{||t\times w||}$  &#xD;&#xA;$v=w\times u$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am really confused about the 2nd equation $u=\frac{t\times w}{||t\times w||}$.  &#xD;&#xA;What if the camera rotate around its gaze direction? The v rotates while the t stays the same.  &#xD;&#xA;Then the vector t will not in the plane that w and v lies in which means the second equation is wrong.&#xD;&#xA;&#xD;&#xA;I know I have something misunderstood.   &#xD;&#xA;Could someone please give me some clues?  &#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/G3CWy.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fDzVi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21521" PostHistoryTypeId="2" PostId="8116" RevisionGUID="f39f6b42-49a0-4c87-8421-21b7e94f3df4" CreationDate="2018-10-05T02:58:54.803" UserId="2654" Text="&gt; What if the camera rotate around its gaze direction? The v rotates while the t stays the same.&#xD;&#xA;&#xD;&#xA;The camera's orientation is defined by two directions: **g** and **t**. If the camera &quot;rotates around its gaze direction&quot;, **g** will not be changing; that is what it means to &quot;rotate around its gaze direction&quot;. If **g** isn't changing, and the camera's orientation is defined by two directions, then you can only get a different orientation if **t** is changing.&#xD;&#xA;&#xD;&#xA;Therefore, your second statement is a contradiction of the first. Changing **t** is *precisely how* you cause the camera to &quot;rotate around its gaze direction&quot;.&#xD;&#xA;&#xD;&#xA;To put it a different way, there are changes to **t** which will *not* affect the values of **u**, **v**, or **w**. However, none of those changes will cause the camera to &quot;rotate around its gaze direction&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="21526" PostHistoryTypeId="2" PostId="8118" RevisionGUID="c8a4b8e5-c670-45ad-8ac5-4515f8a2e308" CreationDate="2018-10-05T10:39:29.090" UserDisplayName="user106" Text="A good introduction to finite element methods for deformable body animation is Sifakis and Barbič's course *[FEM Simulation of 3D Deformable Solids](http://www.femdefo.org/)* from SIGGRAPH 2012.&#xD;&#xA;&#xD;&#xA;However, since you say&#xD;&#xA;&#xD;&#xA;&gt; I tried with a spring-mass system but the system become quickly instable, moreover it's computational expansive.&#xD;&#xA;&#xD;&#xA;you should know that a finite element model is usually *more* expensive than a mass-spring system. If you're having problems with instability, you should try doing implicit integration on your mass-spring system first; see the &quot;Implicit Methods&quot; chapter of the [Witkin and Baraff notes](https://www.pixar.com/assets/pbm2001/index.html).&#xD;&#xA;&#xD;&#xA;You can also consider [position-based dynamics](http://www.interactive-graphics.de/index.php/research/108-a-survey-on-position-based-dynamics-2017) or [projective dynamics](https://www.projectivedynamics.org/Projective_Dynamics/index.html), which are fast, stable, and easier to implement than FEM. They may be good enough for your needs, unless you require high accuracy or nonlinear material models." ContentLicense="CC BY-SA 4.0" />
  <row Id="21527" PostHistoryTypeId="2" PostId="8119" RevisionGUID="9e1e00b6-9432-4e54-a0d8-bf8378a15ff2" CreationDate="2018-10-05T17:21:43.630" UserId="9444" Text="**What is the fastest known method for bucketing triangles into an unbounded regular 3D grid?**&#xD;&#xA;&#xD;&#xA;Specifically, I need an array of buckets. Random queries (which bucket is here) are not necessary, as this is not for ray-tracing (though I will include the tag because of algorithm similarity). The triangles form a closed 2-manifold mesh.&#xD;&#xA;&#xD;&#xA;Currently, I'm inserting into grid cells that intersect the bounding box of the triangle (in my case, triangles are smaller than cells, so this is ok). I'm using a hash table for my grid.&#xD;&#xA;&#xD;&#xA;I've also tried outputting a list of (bucket-position, triangle-index) pairs and sorting them lexicographically, which has comparable performance.&#xD;&#xA;&#xD;&#xA;Thus far, I've only tried CPU approaches. I'm thinking a faster method would be to produce the pairs on the GPU, then sort on the GPU.&#xD;&#xA;&#xD;&#xA;I'm having trouble finding directly relevant research papers (though it's easy to find papers on GPU sorting)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21528" PostHistoryTypeId="1" PostId="8119" RevisionGUID="9e1e00b6-9432-4e54-a0d8-bf8378a15ff2" CreationDate="2018-10-05T17:21:43.630" UserId="9444" Text="fastest way to bucket triangles into a grid?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21529" PostHistoryTypeId="3" PostId="8119" RevisionGUID="9e1e00b6-9432-4e54-a0d8-bf8378a15ff2" CreationDate="2018-10-05T17:21:43.630" UserId="9444" Text="|raytracing|mesh|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21530" PostHistoryTypeId="2" PostId="8120" RevisionGUID="2deaff1a-9eba-42b2-bf04-db58ede764db" CreationDate="2018-10-05T17:57:53.560" UserId="9444" Text="I'd recommend using [OpenVDB](http://www.openvdb.org). It's quite battle-tested.&#xD;&#xA;&#xD;&#xA;Use `meshToVolume` to voxelize the mesh. Then use `volumeToMesh` to produce a high-quality quad mesh.&#xD;&#xA;&#xD;&#xA;`meshToVolume` voxelizes the mesh into a [SDF](https://en.wikipedia.org/wiki/Signed_distance_function). `volumeToMesh` seems to use dual contouring / SurfaceNets." ContentLicense="CC BY-SA 4.0" />
  <row Id="21531" PostHistoryTypeId="50" PostId="7897" RevisionGUID="b0a8e834-2bd6-4e6b-9829-00f93c03381d" CreationDate="2018-10-05T21:00:20.603" UserId="-1" />
  <row Id="21533" PostHistoryTypeId="2" PostId="8121" RevisionGUID="0fa27de4-3d21-4971-9ab5-aabacbf8b07d" CreationDate="2018-10-06T04:50:33.630" UserId="8288" Text="A well-known property of Perlin noise (with FBM) is that if you take a slice of it, the result is still Perlin noise.  So, by taking successive slices of 4D  noise, you get smoothly shifting 3D noise, like a cloud or a lava lamp.&#xD;&#xA;&#xD;&#xA;What other noises have this property?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21534" PostHistoryTypeId="1" PostId="8121" RevisionGUID="0fa27de4-3d21-4971-9ab5-aabacbf8b07d" CreationDate="2018-10-06T04:50:33.630" UserId="8288" Text="What noises can be sliced?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21535" PostHistoryTypeId="3" PostId="8121" RevisionGUID="0fa27de4-3d21-4971-9ab5-aabacbf8b07d" CreationDate="2018-10-06T04:50:33.630" UserId="8288" Text="|animation|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21538" PostHistoryTypeId="2" PostId="8122" RevisionGUID="c45534e9-5836-4ff5-b10f-d5756eb208cf" CreationDate="2018-10-07T03:35:18.103" UserId="8699" Text="To give context to the question, I am reading Peter Shirley's Ray Tracing in one weekend. In his code for sphere/ray intersection, when the quadratic formula returns only 1 solution, he discards it, which strikes me as odd. Is there any graphics theory that support it or is it just his personal preference?&#xD;&#xA;&#xD;&#xA;Here is the link to the code I am talking about on github.&#xD;&#xA;https://github.com/petershirley/raytracinginoneweekend/blob/master/sphere.h" ContentLicense="CC BY-SA 4.0" />
  <row Id="21539" PostHistoryTypeId="1" PostId="8122" RevisionGUID="c45534e9-5836-4ff5-b10f-d5756eb208cf" CreationDate="2018-10-07T03:35:18.103" UserId="8699" Text="why doesn't a ray hitting a sphere at only 1 point count as a hit in sphere/ray intersection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21540" PostHistoryTypeId="3" PostId="8122" RevisionGUID="c45534e9-5836-4ff5-b10f-d5756eb208cf" CreationDate="2018-10-07T03:35:18.103" UserId="8699" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21547" PostHistoryTypeId="2" PostId="8124" RevisionGUID="36548676-d3f0-4769-b935-7eb8a05764e6" CreationDate="2018-10-07T17:36:59.567" UserId="4908" Text="It is mainly personal preference, but it does have some logic behind it which would make it a better option. It should not have any big impact on your final image, though.&#xD;&#xA;&#xD;&#xA;When the discriminant is 0, then that means that there is only one solution. For a sphere, when there is only one solution, that means that the ray is tangent to the sphere. When a line or ray is tangent to a sphere, that means that there is a 90° angle between the line/ray and the normal of the sphere at the intersection. When comparing that situation to ray-triangle and ray-plane intersections, they always ignore the hit when it has an angle of 90° with the normal. This is because the ray would then not really be able to hit it, and in real life you cannot see an infinitely thin plane or triangle that is perfectly parallel to your viewing direction.&#xD;&#xA;&#xD;&#xA;Discarding hits when the angle is 90° could also help with shading. Depending on the shader, a 90° angle might always return black or start giving funky results, while when the angle is less than 90° it is just perfectly fine. Also as @Rahul has said, if you would calculate a reflected ray, it would end up in the same direction as your original ray and with most shaders that reflection ray would contribute to 100% of the ray's colour and not be coloured, so it would give the exact same colour as if you just discarded the ray.&#xD;&#xA;&#xD;&#xA;The thing that makes this basically personal preference, is the fact that it would practically not happen that a ray would hit the sphere perfectly tangent, in an average render engine (as Rahul has also said). When looking at a sphere from a certain point, there would be a single circle with an infinitely small thickness that could create the occurrence of the discriminant being 0.&#xD;&#xA;&#xD;&#xA;In short, it basically does not matter a single bit if you discard those hits or not. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21548" PostHistoryTypeId="2" PostId="8125" RevisionGUID="6452e8e3-272a-4d3e-833e-bc7ee4c422ec" CreationDate="2018-10-07T23:09:49.020" UserId="9467" Text="I'm currently taking a Computer Graphics class at university, and have been given an assignment which involves loading an obj file and manipulating it with keyboard and mouse controls (eg. arrow keys translate, mouse wheel for zoom, hold mouse and drag for rotation).&#xD;&#xA;&#xD;&#xA;Being new to OpenGL, I'm a bit overwhelmed by the project on hand, and would really appreciate if anyone could give me some tips regarding implementation of this project. Our previous (and first) project involved creating a clock based on system time, which was relatively straightforward, using simple rotation/translation techniques on OpenGL primitive objects created within the draw() function. I was able to easily figure out and understand this.&#xD;&#xA;&#xD;&#xA;The main questions I have are:&#xD;&#xA;&#xD;&#xA;- Within the draw() function, how do I take the changes made by the keyboard/mouse and apply them to the object? More specifically, what exactly should be going on here in relation to the input methods?&#xD;&#xA;&#xD;&#xA;        void Draw() &#xD;&#xA;        {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear The Screen And The Depth Buffer&#xD;&#xA;    &#xD;&#xA;    	// Write your own code below (Hint:Translation Rotation &amp; Scaling)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Write your own code above&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;        if (obj_data != NULL)&#xD;&#xA;    		obj_data-&gt;Draw();&#xD;&#xA;        else&#xD;&#xA;            glutSolidTeapot(1.0);	//draw a teapot when no argument is provided&#xD;&#xA;    &#xD;&#xA;        glFlush();&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    	&#xD;&#xA;    	// Write your own code below (Hint:reset translate and scale value)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Write your own code above&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;- How does the mouseMotion() method work? More specifically, how might I go about getting the coordinates of the mouse location and use them within the program?&#xD;&#xA;&#xD;&#xA;        void mouseMotion(int x, int y)&#xD;&#xA;        {&#xD;&#xA;        //code here&#xD;&#xA;    	glutPostRedisplay();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I know this may be a vague and/or ambiguous question, but I really do not know where to start on this. My professor has not given much information as to how to implement this, and any pointers or tips that may guide me in the right direction would be incredibly appreciated!&#xD;&#xA;&#xD;&#xA;Just so you know, I'm not posting this here for an easy answer so I can copy/paste. I'm mainly looking for a greater understanding of how OpenGL works, especially in relation to user input!&#xD;&#xA;&#xD;&#xA;PS: The full source code for the project can be found [here.][1] There is also an objLoader.cpp file as well used to load a predrawn object into the workspace.&#xD;&#xA;&#xD;&#xA;Let me know if more clarification is required. I've tried my best to consolidate this into smaller questions that might help me understand the project as a whole.&#xD;&#xA;&#xD;&#xA;Thanks again!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pastebin.com/fKEH9zkm" ContentLicense="CC BY-SA 4.0" />
  <row Id="21549" PostHistoryTypeId="1" PostId="8125" RevisionGUID="6452e8e3-272a-4d3e-833e-bc7ee4c422ec" CreationDate="2018-10-07T23:09:49.020" UserId="9467" Text="Relatively new to OpenGL, need guidance/tips on an assignment with interactive user input" ContentLicense="CC BY-SA 4.0" />
  <row Id="21550" PostHistoryTypeId="3" PostId="8125" RevisionGUID="6452e8e3-272a-4d3e-833e-bc7ee4c422ec" CreationDate="2018-10-07T23:09:49.020" UserId="9467" Text="|opengl|3d|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21551" PostHistoryTypeId="2" PostId="8126" RevisionGUID="79c99060-ba00-47a6-a63c-9237e4896397" CreationDate="2018-10-08T07:44:21.030" UserId="8288" Text="OpenGL itself is purely a graphics library.  It doesn't give you access to keyboard input.&#xD;&#xA;&#xD;&#xA;*However,* if you're using OpenGL, you're also probably using a cross-platform [context/window toolkit](https://www.khronos.org/opengl/wiki/Related_toolkits_and_APIs#Context.2FWindow_Toolkits) to create a desktop window and set up an OpenGL context for drawing into that window.  These toolkits usually also give you basic keyboard and mouse input.  (The idea is, I guess, if they're abstracting platform-specific window creation, they may as well abstract platform-specific window input at the same time.)&#xD;&#xA;&#xD;&#xA;Your context toolkit looks to be FreeGLUT, so you should refer to the [FreeGLUT documentation](http://freeglut.sourceforge.net/docs/api.php) for details." ContentLicense="CC BY-SA 4.0" />
  <row Id="21559" PostHistoryTypeId="2" PostId="8130" RevisionGUID="9cb417c8-3dde-4cd0-877b-82bc9e558365" CreationDate="2018-10-09T00:34:25.087" UserId="8699" Text="I'm following Peter Shirley book, Ray tracing in one weekend. In the last chapter, he talks about how to make defocus blur by using thin len approximation. His camera class accepts a parameter called focus_dist, which he then uses to compute the distance to the image plane. &#xD;&#xA;&#xD;&#xA;    lower_left_corner = origin  - half_width*focus_dist*u -half_height*focus_dist*v - focus_dist*w; // lower_left_corner of image plane&#xD;&#xA;    &#xD;&#xA;This subject was new to me, so I went searching around online. From what i understand, the distance to the image plane is governed by the equation 1/f = 1/d + 1/d prime with f being focal length and d being the focus distance. d prime will be the answer. The lack of this equation in Peter Shirley's code and the fact that he seems to be putting the image plane at the focus distance makes me completely lost. Can anyone explain it to me?&#xD;&#xA;&#xD;&#xA;Here's the link to the code I talked about. &#xD;&#xA;https://github.com/petershirley/raytracinginoneweekend/blob/master/camera.h" ContentLicense="CC BY-SA 4.0" />
  <row Id="21560" PostHistoryTypeId="1" PostId="8130" RevisionGUID="9cb417c8-3dde-4cd0-877b-82bc9e558365" CreationDate="2018-10-09T00:34:25.087" UserId="8699" Text="Defocus blur: Computing the length" ContentLicense="CC BY-SA 4.0" />
  <row Id="21561" PostHistoryTypeId="3" PostId="8130" RevisionGUID="9cb417c8-3dde-4cd0-877b-82bc9e558365" CreationDate="2018-10-09T00:34:25.087" UserId="8699" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21562" PostHistoryTypeId="4" PostId="8130" RevisionGUID="62d5eedc-535b-4f35-8fb3-4d78a69d909f" CreationDate="2018-10-09T00:42:01.767" UserId="8699" Comment="edited title" Text="Defocus blur: Computing the pixel plane distance" ContentLicense="CC BY-SA 4.0" />
  <row Id="21563" PostHistoryTypeId="50" PostId="8034" RevisionGUID="021ec00b-44ae-46ac-a2cf-dd387ff0c4db" CreationDate="2018-10-09T03:00:25.187" UserId="-1" />
  <row Id="21564" PostHistoryTypeId="2" PostId="8131" RevisionGUID="05ce7d22-4745-4393-86b2-c2d89b163f68" CreationDate="2018-10-09T05:19:14.777" UserId="8893" Text="I am currently experiencing a very obvious artifact that only occur when I use normal maps. However it only occurs when looking at surfaces on very grazing angles.&#xD;&#xA;&#xD;&#xA;Here is a picture of the artifact:&#xD;&#xA;https://imgur.com/a/Vahn7pM&#xD;&#xA;&#xD;&#xA;And here is an image of the normals:&#xD;&#xA;https://imgur.com/a/GwA5TkT&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I will also post the vertex and fragment shader code for unpacking normals maps:&#xD;&#xA;&#xD;&#xA;Vertex Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 T = normalize(normalMatrix * tangent);&#xD;&#xA;    vec3 B = normalize(normalMatrix * bitangent);&#xD;&#xA;    vec3 N = normalize(normalMatrix * normal);&#xD;&#xA;    TBN = mat3(T, B, N);&#xD;&#xA;&#xD;&#xA;Fragment Shader Snippet:&#xD;&#xA;&#xD;&#xA;    normal = normalize(normal * 2.0f - 1.0f);&#xD;&#xA;	normal = normalize(TBN * normal);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I would really appreciate if anyone has ever experiences this kind of artifact. Is it my BRDF, is it my normal calculations? I am not sure.. I would appreciate any insight people have!&#xD;&#xA;&#xD;&#xA;If you want to see my fragment shader and my BRDF you can find the code here:&#xD;&#xA;&#xD;&#xA;https://github.com/Ershany/Arcane-Engine/blob/WIP_PBR/Arcane%20Engine%20Core/src/shaders/pbr_model.frag&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="21565" PostHistoryTypeId="1" PostId="8131" RevisionGUID="05ce7d22-4745-4393-86b2-c2d89b163f68" CreationDate="2018-10-09T05:19:14.777" UserId="8893" Text="Normal Artifacts On Grazing Angles" ContentLicense="CC BY-SA 4.0" />
  <row Id="21566" PostHistoryTypeId="3" PostId="8131" RevisionGUID="05ce7d22-4745-4393-86b2-c2d89b163f68" CreationDate="2018-10-09T05:19:14.777" UserId="8893" Text="|normal-mapping|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21568" PostHistoryTypeId="2" PostId="8132" RevisionGUID="8c3bd202-87c1-4ea2-850e-b7b047ceef1c" CreationDate="2018-10-09T09:42:34.980" UserDisplayName="user9436" Text="OpenGL is  is a cross-language, cross-platform application programming interface (API), and it acts as a bridge between your CPU and your GPU. &#xD;&#xA;&#xD;&#xA;It's not an input handling library, since that is something that is OS specific (on Windows for instance you would use DirectInput) and that has nothing to do with the GPU.&#xD;&#xA;&#xD;&#xA;Now, as stated by the other answers, you are probably using a framework to handle context creation, setting up the pixelFormatDescriptor and creating the OS window (you would use the Win32 api on Windows), like Freeglut.&#xD;&#xA;&#xD;&#xA;Freeglut at this point in time, is quite outdated (and probably not even supported anymore, i can't remember correctly). &#xD;&#xA;GLFW on the other hand, is a very well maintained and documented library for both input and window handling (that also includes context creation). &#xD;&#xA;In addition to that, the brand new Vulkan API is also avaiable for use.&#xD;&#xA;Input and Window handling is done through callbacks with a very intuitive API.&#xD;&#xA;&#xD;&#xA;GLFW is written in C and licenced under the z-lib licence. you can read more about it here: https://www.glfw.org" ContentLicense="CC BY-SA 4.0" />
  <row Id="21569" PostHistoryTypeId="5" PostId="8132" RevisionGUID="6c3340bb-4f71-4f35-ac18-530ff6699736" CreationDate="2018-10-09T09:48:24.337" UserDisplayName="user9436" Comment="deleted 22 characters in body" Text="OpenGL is  is a cross-language, cross-platform application programming interface (API), and it acts as a bridge between your CPU and your GPU. &#xD;&#xA;&#xD;&#xA;It's not an input handling library, since that is something that is OS specific (on Windows for instance you would use DirectInput) and that has nothing to do with the GPU.&#xD;&#xA;&#xD;&#xA;Now, as stated by the other answers, you are probably using a framework to handle context creation, setting up the pixelFormatDescriptor and creating the OS window (you would use the Win32 api on Windows), like Freeglut.&#xD;&#xA;&#xD;&#xA;Freeglut at this point in time, is quite outdated (and probably not even supported anymore, i can't remember correctly). &#xD;&#xA;GLFW on the other hand, is a very well maintained and documented library for both input and window handling (that also includes context creation). &#xD;&#xA;In addition to that, the brand new Vulkan API is also avaiable for use.&#xD;&#xA;Input and Window handling is done through callbacks with a very intuitive API.&#xD;&#xA;&#xD;&#xA;[GLFW][1] is written in C and licenced under the z-lib licence.&#xD;&#xA;[1]: https://www.glfw.org" ContentLicense="CC BY-SA 4.0" />
  <row Id="21570" PostHistoryTypeId="50" PostId="7794" RevisionGUID="9ec3324b-6e39-459f-8cd0-698302c1af05" CreationDate="2018-10-09T18:00:35.487" UserId="-1" />
  <row Id="21571" PostHistoryTypeId="5" PostId="8065" RevisionGUID="f77847ea-50cd-4c59-b065-09ae2908224d" CreationDate="2018-10-09T20:24:40.690" UserId="4647" Comment="added 664 characters in body" Text="&gt; I guess that this is related to the sum of the three functions having a minimum there. See the sum plotted against wavelength&#xD;&#xA;&#xD;&#xA;This is actually a wrong way to sum these functions: sRGB model specifies that to get luminosity one must weigh the RGB components with appropriate weights. Then luminosity, unsurprisingly, will become equal to the Y component of the XYZ representation.&#xD;&#xA;&#xD;&#xA;&gt; the problem with it is that the image seems to have a dip in intensity somewhere around 490 nm&#xD;&#xA;&#xD;&#xA;I can actually see the dip not only near 490 nm, but also a smaller one near 570 nm.&#xD;&#xA;&#xD;&#xA;Anyway, I think I've found the reason for this. First of all, let's plot the desaturated colors used in the rendering on the chromaticity diagram:&#xD;&#xA;&#xD;&#xA;[![chromaticity diagram with the desaturated spectrum inside][1]][1]&#xD;&#xA;&#xD;&#xA;The dashed triangle is the sRGB gamut, and the cusp formed by the lower two lines of the green curve corresponds to the D65 white (gray) point. Notice that there are three &quot;bumps&quot; away from the white point, corresponding to violet, bluish-green and red. Or, that there is a large dip in saturation in the direction of 490 nm and a moderate decrease in the direction of around 570 nm. Let's characterize this graphically, plotting the norm of difference of the rendered points from white point:&#xD;&#xA;&#xD;&#xA;[![plot of a saturation measure][2]][2]&#xD;&#xA;&#xD;&#xA;This is **exactly** what I perceive visually in the image in terms of saturation and thus blending with the background.&#xD;&#xA;&#xD;&#xA;Where does this strange shape come from, you may wonder. And the answer is, from the spectral locus in full XYZ space. See the following figure: the blue curve is the spectral locus, and the orange is its projection onto a plane normal to vector `{1,1,1}`.&#xD;&#xA;&#xD;&#xA;[![spectral locus in XYZ space][3]][3]&#xD;&#xA;&#xD;&#xA;So, the shape we got on the chromaticity diagram is something like a planar unfolding of the spectral locus.&#xD;&#xA;&#xD;&#xA;As to realism of this rendering, I'm reasonably sure that if we try projecting real spectrum onto a gray non-fluorescent surface, we'll also see these two &quot;strange&quot; dips. And they will become less noticeable as you increase brightness of the spectrum relative to the brightness of the surface.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eJ8kx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/89eU3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Ov2gQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21573" PostHistoryTypeId="2" PostId="8133" RevisionGUID="f07faee8-6123-4e29-8feb-9388edbaf458" CreationDate="2018-10-10T03:59:43.720" UserId="9482" Text="If I had two right handed frames where one has vectors [i, j, k] and another with corresponding vectors [u v w], how would I derive the transform M[i j k] &lt;-- [u v w] when applied to any point P in [u v w] we get its representation in [i j k] ?&#xD;&#xA;&#xD;&#xA;They noted that for every unit we move in the [i j k] frame we move 2 units in the [u v w] frame and the origin of the [u v w] frame can be represented as [4i 6j 2k]&#xD;&#xA;&#xD;&#xA;Can someone help me derive this? I'm fairly new to computer graphics and need some help in detail." ContentLicense="CC BY-SA 4.0" />
  <row Id="21574" PostHistoryTypeId="1" PostId="8133" RevisionGUID="f07faee8-6123-4e29-8feb-9388edbaf458" CreationDate="2018-10-10T03:59:43.720" UserId="9482" Text="How do I derive this transformation" ContentLicense="CC BY-SA 4.0" />
  <row Id="21575" PostHistoryTypeId="3" PostId="8133" RevisionGUID="f07faee8-6123-4e29-8feb-9388edbaf458" CreationDate="2018-10-10T03:59:43.720" UserId="9482" Text="|transformations|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21576" PostHistoryTypeId="5" PostId="8118" RevisionGUID="9bd2a495-7079-4560-9ffe-ec4dc493c1ec" CreationDate="2018-10-10T08:14:48.547" UserDisplayName="user106" Comment="added 39 characters in body" Text="A good introduction to finite element methods for deformable body animation is Sifakis and Barbič's course *[FEM Simulation of 3D Deformable Solids](http://www.femdefo.org/)* from SIGGRAPH 2012.&#xD;&#xA;&#xD;&#xA;However, since you say&#xD;&#xA;&#xD;&#xA;&gt; I tried with a spring-mass system but the system become quickly instable, moreover it's computational expansive.&#xD;&#xA;&#xD;&#xA;you should know that a finite element model is usually *more* expensive than a mass-spring system. If you're having problems with instability, you should try keeping your mass-spring system but (i) reducing the time step, or (ii) doing implicit integration; see the &quot;Implicit Methods&quot; chapter of the [Witkin and Baraff notes](https://www.pixar.com/assets/pbm2001/index.html).&#xD;&#xA;&#xD;&#xA;You can also consider [position-based dynamics](http://www.interactive-graphics.de/index.php/research/108-a-survey-on-position-based-dynamics-2017) or [projective dynamics](https://www.projectivedynamics.org/Projective_Dynamics/index.html), which are fast, stable, and easier to implement than FEM. They may be good enough for your needs, unless you require high accuracy or nonlinear material models." ContentLicense="CC BY-SA 4.0" />
  <row Id="21579" PostHistoryTypeId="2" PostId="8135" RevisionGUID="dfe8b08c-dac3-4c05-a566-ea4ffd1a62ce" CreationDate="2018-10-10T10:21:22.357" UserId="6046" Text="I'm not going to dive into much details about affine transformations and such, you are better off reading up on these concepts from good graphics books.&#xD;&#xA;&#xD;&#xA;I think The matrix you need is this. &#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;0.5 &amp; 0 &amp; 0 &amp; 4\\&#xD;&#xA;0 &amp; 0.5 &amp; 0 &amp; 6\\&#xD;&#xA;0 &amp; 0 &amp; 0.5 &amp; 2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;The reason why we need 4x4 matrices is because of affine transformations. For more details on why we have 4x4 matrices and why are we using 4D representation you can check my answer [here][1]. Briefly speaking, Vectors representing direction have an extra `0` at the end since translations don't affect these sort of vectors and Vectors representing points have an extra `1` at the end. This makes our vectors 4D so we can apply 4x4 transformation matrices. Since here we are concerned with points we will append an extra `1` to each vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Let's begin by how did I derive it. First of all we can see that they provided the origin of the $UVW$ frame in terms of $IJK$ frame. This is $[4i, 6j, 2k]$. In other words the vector $[0,0,0]$ in $UVW$ frame must correspond to $[4i, 6j, 2k]$ in $IJK$ frame. Let's forget the 0.5's in the diagonal for now. We have,&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 4\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 6\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;* &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0\\&#xD;&#xA;0\\&#xD;&#xA;0\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;4\\&#xD;&#xA;6\\&#xD;&#xA;2\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix} $&#xD;&#xA;&#xD;&#xA;Next the condition is if we move 1 unit in $IJK$ we move 2 units in $UVW$ or in other words if we move 1 unit in $UVW$ we move 0.5 units in $IJK$. This means if we move from origin to $[1,1,1]$ in $UVW$ we moved half a unit in the $IJK$ frame in each of the axis. Testing the original matrix now we have,&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;0.5 &amp; 0 &amp; 0 &amp; 4\\&#xD;&#xA;0 &amp; 0.5 &amp; 0 &amp; 6\\&#xD;&#xA;0 &amp; 0 &amp; 0.5 &amp; 2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;* &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;4.5\\&#xD;&#xA;6.5\\&#xD;&#xA;2.5\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix} $&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When constructing matrices this way, you want the translation factor in the last column. This factor is given to you by telling you the origin of the $UVW$ frame in terms of $IJK$ frame. This means the $UVW$ frame is that much displaced/translated when viewed from $IJK$ frame.&#xD;&#xA;&#xD;&#xA;Secondly any scaling factor goes along the diagonal like above. This factor was given to you by telling you &quot;If you move $X$ units in 1 frame, you move $Y$ units in the other&quot;.&#xD;&#xA;Which is what we want I guess. Is that what you need?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6271/what-is-the-use-of-homogenous-divide/6275#6275" ContentLicense="CC BY-SA 4.0" />
  <row Id="21580" PostHistoryTypeId="2" PostId="8136" RevisionGUID="86e96d9f-0e75-4f03-b60e-70481838f810" CreationDate="2018-10-10T15:49:56.947" UserDisplayName="user9485" Text="I am trying to render implicit surfaces given by a polynomial equation $F(x,y,z) = 0$ using [Sturm's theorem](https://en.wikipedia.org/wiki/Sturm%27s_theorem).&#xD;&#xA;&#xD;&#xA;Plugging the parametric ray equation $r(t) = o + td$, where $o\in\mathbb{R}^3$ is the ray origin and $d\in\mathbb{R}^3\backslash\{0\}$ is the ray direction,  into $F$ yields a polynomial equation $p(t) = 0$ for the intersections of the ray with the surface. I noticed that the straightforward implementation of calculating a Sturm sequence as&#xD;&#xA;&#xD;&#xA;$$p_0 = p, \\ p_1 = p', \\ p_{i} = -\text{rem}(p_{i-2},p_{i-1}) \quad\forall i\ge2$$&#xD;&#xA;&#xD;&#xA;is numerically unstable. When rendering a torus for example, the equation for one particular ray in my program was&#xD;&#xA;&#xD;&#xA;$$p(x) := x^4 + 0.00329589844x^2 - 660.766052x + 9627.17676 = 0.$$&#xD;&#xA;&#xD;&#xA;In single precision, the associated Sturm sequence is computed as&#xD;&#xA;&#xD;&#xA;$$p_0(x) = x^4 + 0.00329589844x^2 - 660.766052x + 9627.17676 = 0,\\&#xD;&#xA;  p_1(x) = 4x^3+0.00659179688x-660.766052,\\&#xD;&#xA;  p_2(x) = -0.001647949220x^2+495.5745390x-9627.17676,\\&#xD;&#xA;  p_3(x) = -3.617114498*10^{11}x+7.027166964*10^{12},\\&#xD;&#xA;  p_4(x) = 0,$$&#xD;&#xA;&#xD;&#xA;which indicates that (up to multiplicity) $p$ has exactly one real root. But in fact $p$ has no real roots, which can easily be verified with a computer algebra system. If the same computation is done with higher precision, it turns out that $p_4(x)\approx 0.000039&gt;0$. In this case the correct number of roots is calculated.&#xD;&#xA;&#xD;&#xA;Is there anything that can be done to avoid this problem when calculating a Sturm sequence?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21581" PostHistoryTypeId="1" PostId="8136" RevisionGUID="86e96d9f-0e75-4f03-b60e-70481838f810" CreationDate="2018-10-10T15:49:56.947" UserDisplayName="user9485" Text="Ray tracing implicit surfaces using Sturm's theorem" ContentLicense="CC BY-SA 4.0" />
  <row Id="21582" PostHistoryTypeId="3" PostId="8136" RevisionGUID="86e96d9f-0e75-4f03-b60e-70481838f810" CreationDate="2018-10-10T15:49:56.947" UserDisplayName="user9485" Text="|raytracing|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21583" PostHistoryTypeId="5" PostId="8131" RevisionGUID="33156834-a982-4c26-8417-72b6cb3ffdd8" CreationDate="2018-10-10T16:51:20.230" UserId="8893" Comment="added 68 characters in body" Text="I am currently experiencing a very obvious artifact that only occur when I use normal maps. However it only occurs when looking at surfaces on very grazing angles.&#xD;&#xA;&#xD;&#xA;Here is a picture of the artifact:&#xD;&#xA;https://imgur.com/a/Vahn7pM&#xD;&#xA;&#xD;&#xA;And here is an image of the normals:&#xD;&#xA;https://imgur.com/a/GwA5TkT&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I will also post the vertex and fragment shader code for unpacking normals maps:&#xD;&#xA;&#xD;&#xA;Vertex Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 T = normalize(normalMatrix * tangent);&#xD;&#xA;    vec3 B = normalize(normalMatrix * bitangent);&#xD;&#xA;    vec3 N = normalize(normalMatrix * normal);&#xD;&#xA;    TBN = mat3(T, B, N);&#xD;&#xA;&#xD;&#xA;Fragment Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 normal = texture(material.texture_normal, TexCoords).rgb;&#xD;&#xA;    normal = normalize(normal * 2.0f - 1.0f);&#xD;&#xA;	normal = normalize(TBN * normal);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I would really appreciate if anyone has ever experiences this kind of artifact. Is it my BRDF, is it my normal calculations? I am not sure.. I would appreciate any insight people have!&#xD;&#xA;&#xD;&#xA;If you want to see my fragment shader and my BRDF you can find the code here:&#xD;&#xA;&#xD;&#xA;https://github.com/Ershany/Arcane-Engine/blob/WIP_PBR/Arcane%20Engine%20Core/src/shaders/pbr_model.frag&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="21584" PostHistoryTypeId="5" PostId="8136" RevisionGUID="be1fe8d0-ab4f-4a49-b435-f101bb5eb76d" CreationDate="2018-10-10T20:50:35.320" UserDisplayName="user9485" Comment="added 6 characters in body" Text="I am trying to render implicit surfaces given by a polynomial equation $F(x,y,z) = 0$ using [Sturm's theorem](https://en.wikipedia.org/wiki/Sturm%27s_theorem).&#xD;&#xA;&#xD;&#xA;Plugging the parametric ray equation $r(t) = o + td$, where $o\in\mathbb{R}^3$ is the ray origin and $d\in\mathbb{R}^3\backslash\{0\}$ is the ray direction,  into $F$ yields a polynomial equation $p(t) = 0$ for the intersections of the ray with the surface. I noticed that the straightforward implementation of calculating a Sturm sequence as&#xD;&#xA;&#xD;&#xA;$$p_0 = p, \\ p_1 = p', \\ p_{i} = -\text{rem}(p_{i-2},p_{i-1}) \quad\forall i\ge2$$&#xD;&#xA;&#xD;&#xA;is numerically unstable. When rendering a torus for example, the equation for one particular ray in my program was&#xD;&#xA;&#xD;&#xA;$$p(t) := t^4 + 0.00329589844t^2 - 660.766052t + 9627.17676 = 0.$$&#xD;&#xA;&#xD;&#xA;In single precision, the associated Sturm sequence is computed as&#xD;&#xA;&#xD;&#xA;$$p_0(t) = t^4 + 0.00329589844t^2 - 660.766052t + 9627.17676,\\&#xD;&#xA;  p_1(t) = 4t^3+0.00659179688t-660.766052,\\&#xD;&#xA;  p_2(t) = -0.001647949220t^2+495.5745390t-9627.17676,\\&#xD;&#xA;  p_3(t) = -3.617114498\cdot 10^{11}t+7.027166964\cdot 10^{12},\\&#xD;&#xA;  p_4(t) = 0,$$&#xD;&#xA;&#xD;&#xA;which indicates that (up to multiplicity) $p$ has exactly one real root. But in fact $p$ has no real roots, which can easily be verified with a computer algebra system. If the same computation is done with higher precision, it turns out that $p_4(x)\approx 0.000039&gt;0$. In this case the correct number of roots is calculated.&#xD;&#xA;&#xD;&#xA;Is there anything that can be done to avoid this problem when calculating a Sturm sequence?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21585" PostHistoryTypeId="5" PostId="8136" RevisionGUID="4c95da9c-79d3-4bbd-81c5-dfe75067b10a" CreationDate="2018-10-10T21:56:12.820" UserDisplayName="user9485" Comment="edited body" Text="I am trying to render implicit surfaces given by a polynomial equation $F(x,y,z) = 0$ using [Sturm's theorem](https://en.wikipedia.org/wiki/Sturm%27s_theorem).&#xD;&#xA;&#xD;&#xA;Plugging the parametric ray equation $r(t) = o + td$, where $o\in\mathbb{R}^3$ is the ray origin and $d\in\mathbb{R}^3\backslash\{0\}$ is the ray direction,  into $F$ yields a polynomial equation $p(t) = 0$ for the intersections of the ray with the surface. I noticed that the straightforward implementation of calculating a Sturm sequence as&#xD;&#xA;&#xD;&#xA;$$p_0 = p, \\ p_1 = p', \\ p_{i} = -\text{rem}(p_{i-2},p_{i-1}) \quad\forall i\ge2$$&#xD;&#xA;&#xD;&#xA;is numerically unstable. When rendering a torus for example, the equation for one particular ray in my program was&#xD;&#xA;&#xD;&#xA;$$p(t) := t^4 + 0.00329589844t^2 - 660.766052t + 9627.17676 = 0.$$&#xD;&#xA;&#xD;&#xA;In single precision, the associated Sturm sequence is computed as&#xD;&#xA;&#xD;&#xA;$$p_0(t) = t^4 + 0.00329589844t^2 - 660.766052t + 9627.17676,\\&#xD;&#xA;  p_1(t) = 4t^3+0.00659179688t-660.766052,\\&#xD;&#xA;  p_2(t) = -0.001647949220t^2+495.5745390t-9627.17676,\\&#xD;&#xA;  p_3(t) = -3.617114498\cdot 10^{11}t+7.027166964\cdot 10^{12},\\&#xD;&#xA;  p_4(t) = 0,$$&#xD;&#xA;&#xD;&#xA;which indicates that (up to multiplicity) $p$ has exactly one real root. But in fact $p$ has no real roots, which can easily be verified with a computer algebra system. If the same computation is done with higher precision, it turns out that $p_4(t)\approx 0.000039&gt;0$. In this case the correct number of roots is calculated.&#xD;&#xA;&#xD;&#xA;Is there anything that can be done to avoid this problem when calculating a Sturm sequence?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21586" PostHistoryTypeId="2" PostId="8137" RevisionGUID="2f573095-1d0b-46d1-862e-920e49fbecb5" CreationDate="2018-10-11T04:59:29.623" UserId="8484" Text="You can use CloudCompare or MeshLab to generate a mesh from a point cloud using many algorithms. In my experience, marching-cube method results in accurate meshes." ContentLicense="CC BY-SA 4.0" />
  <row Id="21587" PostHistoryTypeId="2" PostId="8138" RevisionGUID="bbb00b4f-4d19-4d41-804b-9581a1638fda" CreationDate="2018-10-11T11:15:56.943" UserId="7724" Text="[Worley noise][1], also known as [cellular noise][2], has the same property. It just as easily implemented as Perlin noise and easily extends to higher dimensions. Thus the slicing of 4D Worley noise will produce a 3D Worley noise. However, it is not necessarily a noise function but rather a texture function, producing cellular-like characteristics. With FBM applied to to Worley noise some interesting patterns can be created.&#xD;&#xA;&#xD;&#xA;You can find additional types of procedural noise functions in [this][3] survey paper. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.rhythmiccanvas.com/research/papers/worley.pdf&#xD;&#xA;  [2]: https://thebookofshaders.com/12/&#xD;&#xA;  [3]: http://graphics.cs.kuleuven.be/publications/LLCDDELPZ10STARPNF/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21588" PostHistoryTypeId="5" PostId="8138" RevisionGUID="2766bb41-3d5c-4a46-a236-bf3b29af3b18" CreationDate="2018-10-11T11:46:55.943" UserId="7724" Comment="deleted 3 characters in body" Text="[Worley noise][1], also known as [cellular noise][2], has the same property. It just as easily implemented as Perlin noise and easily extends to higher dimensions. Thus the slicing of 4D Worley noise will produce a 3D Worley noise. However, it is not necessarily a noise function but rather a texture function, producing cellular-like characteristics. With FBM applied to Worley noise some interesting patterns can be created.&#xD;&#xA;&#xD;&#xA;You can find additional types of procedural noise functions in [this][3] survey paper. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.rhythmiccanvas.com/research/papers/worley.pdf&#xD;&#xA;  [2]: https://thebookofshaders.com/12/&#xD;&#xA;  [3]: http://graphics.cs.kuleuven.be/publications/LLCDDELPZ10STARPNF/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21589" PostHistoryTypeId="50" PostId="7804" RevisionGUID="316c9be5-fcf7-439a-982c-c450bb794c12" CreationDate="2018-10-11T14:01:12.170" UserId="-1" />
  <row Id="21590" PostHistoryTypeId="2" PostId="8139" RevisionGUID="669dfc44-1701-4fe7-ac62-8c898a9124e5" CreationDate="2018-10-11T15:06:22.740" UserId="8484" Text="CloudCompare has SOR (statistical outlier removal) function that can eliminate all lonely points for you. I would filter each *.ply first and then try to carry out a cloud to cloud registration. For registration, you can use MeshLab or use 30 trails of commercially available software such as Faro Scene. Scene won't accept *.ply file though, so you need to convert your files to *.e57 first. Good luck. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21591" PostHistoryTypeId="2" PostId="8140" RevisionGUID="c781ca3d-1999-4550-a258-7a3e7182f038" CreationDate="2018-10-11T17:39:41.710" UserId="9495" Text="I need to store user-drawn images from an online whiteboard. The amount of data gets huge quickly which is obviously not good. What I need is to store something drawn through a tablet for example in as little space as possible without too much of accuracy loss as for example letters should be distiniguishable. Bonus points for a solution with the ability to determine when what was drawn." ContentLicense="CC BY-SA 4.0" />
  <row Id="21592" PostHistoryTypeId="1" PostId="8140" RevisionGUID="c781ca3d-1999-4550-a258-7a3e7182f038" CreationDate="2018-10-11T17:39:41.710" UserId="9495" Text="Compression of user-drawn &quot;whiteboard&quot; image" ContentLicense="CC BY-SA 4.0" />
  <row Id="21593" PostHistoryTypeId="3" PostId="8140" RevisionGUID="c781ca3d-1999-4550-a258-7a3e7182f038" CreationDate="2018-10-11T17:39:41.710" UserId="9495" Text="|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21594" PostHistoryTypeId="50" PostId="7538" RevisionGUID="7237e090-c5f5-4c32-86a4-4a13bffea692" CreationDate="2018-10-11T20:00:47.223" UserId="-1" />
  <row Id="21595" PostHistoryTypeId="2" PostId="8141" RevisionGUID="7e68c25a-88a8-4028-97bd-da939bd88b10" CreationDate="2018-10-12T10:04:49.380" UserId="137" Text="Don't store the rasterized image instead store the drawn strokes as vector graphics. Those should compress pretty well.&#xD;&#xA;&#xD;&#xA;Adding timestamps to each stroke should then be very simple.&#xD;&#xA;&#xD;&#xA;You can caching the rasterized image during execution to avoid needing to rerender every stroke every frame." ContentLicense="CC BY-SA 4.0" />
  <row Id="21600" PostHistoryTypeId="12" PostId="8126" RevisionGUID="fb3d086b-656d-4542-99fd-e92fd6b6bc66" CreationDate="2018-10-12T17:14:54.650" UserId="231" Comment="Converted to Comment" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="21603" PostHistoryTypeId="13" PostId="8126" RevisionGUID="da52ed3f-6ec8-46cc-91c3-ee37fc230da0" CreationDate="2018-10-12T17:16:54.890" UserId="231" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="21604" PostHistoryTypeId="5" PostId="8139" RevisionGUID="c9850719-fb4e-4996-9d09-3c5e11266ad8" CreationDate="2018-10-12T18:32:30.837" UserId="8484" Comment="added 5 characters in body" Text="CloudCompare has SOR (statistical outlier removal) function that can eliminate all lonely points for you. I would filter each *.ply first and then try to carry out a cloud to cloud registration. For registration, you can use MeshLab or use 30 days trails of commercially available software such as Faro Scene. Scene won't accept *.ply file though, so you need to convert your files to *.e57 first. Good luck. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21606" PostHistoryTypeId="2" PostId="8144" RevisionGUID="f7e41291-30a0-4fdb-b7c3-69e5892d5b94" CreationDate="2018-10-12T19:14:00.353" UserId="8484" Text="One other solution is to identify the vector's endpoint with respect to the point P. Then, rotate the endpoint as desired and recompute the new vector based on the rotated endpoint and the point P." ContentLicense="CC BY-SA 4.0" />
  <row Id="21607" PostHistoryTypeId="5" PostId="8139" RevisionGUID="74f0c4b5-c27a-4d38-a512-22201be416d6" CreationDate="2018-10-12T19:16:54.960" UserId="8484" Comment="added 7 characters in body" Text="CloudCompare has statistical outlier removal (called SOR) function that can eliminate all lonely points for you. I would filter each *.ply first and then try to carry out a cloud to cloud registration. For registration, you can use MeshLab or use 30 days trails of commercially available software such as Faro Scene. Scene won't accept *.ply file though, so you need to convert your files to *.e57 first. Good luck. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21608" PostHistoryTypeId="2" PostId="8145" RevisionGUID="4077cde6-e5fc-4b9b-996b-2f8f94040369" CreationDate="2018-10-13T10:53:22.290" UserDisplayName="user9485" Text="One way to visualize an object's bounding box would be like this:&#xD;&#xA;&#xD;&#xA;$\hskip2.5in$[![Bounding box][1]][1]&#xD;&#xA;&#xD;&#xA;As Rahul mentioned in a comment, you can achieve this by adding a total of 12 cylinders at the edges of the bounding box, connecting the spheres at the corners.&#xD;&#xA;&#xD;&#xA;If you want to render the bounding box transparently, I don't see an easy way to hide the intersections of the spheres and cylinders without knowing what program you are using. You could try to use partial spheres for the corners and see if that helps, i.e.&#xD;&#xA;&#xD;&#xA;$\hskip2.5in$[![Partial sphere][2]][2]&#xD;&#xA;&#xD;&#xA;Maybe this is already sufficient for your purpose. (This is exactly 1/8th of a full sphere.)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hhNw4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/c3sAn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21609" PostHistoryTypeId="2" PostId="8146" RevisionGUID="dbe7b766-7e76-40d0-a802-6940b68a3be7" CreationDate="2018-10-13T20:58:34.520" UserId="9505" Text="For what it's worth, I think this camera space formulation of a thin lens makes it easier to understand the concept:&#xD;&#xA;&#xD;&#xA;    float fov = 2.0f * atan((sensorWidth / (2.0f * focal_length))); // in radians&#xD;&#xA;    float tan_fov = tanf(fov / 2.0f);&#xD;&#xA;&#xD;&#xA;    // create point on lens, screen space samples are in [-1, 1] domain&#xD;&#xA;    vec3 p(screen_space_sample_x * tan_fov, screen_space_sample_y * tan_fov, 1.0);&#xD;&#xA;    &#xD;&#xA;    // calculate direction vector from origin to point on lens&#xD;&#xA;    dir = normalize(p - origin);&#xD;&#xA;    &#xD;&#xA;    // get uniformly distributed points on the unit disk&#xD;&#xA;    vec2 lens(0.0, 0.0);&#xD;&#xA;    concentricDiskSample(random1, random2, &amp;lens);&#xD;&#xA;    &#xD;&#xA;    // scale points in [-1, 1] domain to actual aperture radius&#xD;&#xA;    lens *= apertureRadius;&#xD;&#xA;    &#xD;&#xA;    // new origin is these points on the lens&#xD;&#xA;    origin.x = lens.x;&#xD;&#xA;    origin.y = lens.y;&#xD;&#xA;    origin.z = 0.0;&#xD;&#xA;    &#xD;&#xA;    // Compute point on plane of focus, intersection on z axis&#xD;&#xA;    float intersection = std::abs(focus_distance / dir.z);&#xD;&#xA;    vec3 focusPoint = dir * intersection;&#xD;&#xA;    dir = normalize(focusPoint - origin);&#xD;&#xA;    &#xD;&#xA;    // now looking down -Z (optional depending on your coordinate system)&#xD;&#xA;    dir.z *= -1.0;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21610" PostHistoryTypeId="5" PostId="8146" RevisionGUID="58e3c2fe-4366-45f8-8b32-7f495b2716c8" CreationDate="2018-10-13T21:05:33.067" UserId="9505" Comment="deleted 3 characters in body" Text="For what it's worth, I think a camera space formulation of a thin lens makes it easier to understand the concept:&#xD;&#xA;&#xD;&#xA;    float fov = 2.0f * atan((sensorWidth / (2.0f * focal_length))); // in radians&#xD;&#xA;    float tan_fov = tanf(fov / 2.0f);&#xD;&#xA;&#xD;&#xA;    // create point on lens, screen space samples are in [-1, 1] domain&#xD;&#xA;    vec3 p(screen_space_sample_x * tan_fov, screen_space_sample_y * tan_fov, 1.0);&#xD;&#xA;    &#xD;&#xA;    // calculate direction vector from origin to point on lens&#xD;&#xA;    dir = normalize(p - origin);&#xD;&#xA;    &#xD;&#xA;    // get uniformly distributed points on the unit disk&#xD;&#xA;    vec2 lens(0.0, 0.0);&#xD;&#xA;    concentricDiskSample(random1, random2, &amp;lens);&#xD;&#xA;    &#xD;&#xA;    // scale points in [-1, 1] domain to actual aperture radius&#xD;&#xA;    lens *= apertureRadius;&#xD;&#xA;    &#xD;&#xA;    // new origin is these points on the lens&#xD;&#xA;    origin.x = lens.x;&#xD;&#xA;    origin.y = lens.y;&#xD;&#xA;    origin.z = 0.0;&#xD;&#xA;    &#xD;&#xA;    // Compute point on plane of focus, intersection on z axis&#xD;&#xA;    float intersection = std::abs(focus_distance / dir.z);&#xD;&#xA;    vec3 focusPoint = dir * intersection;&#xD;&#xA;    dir = normalize(focusPoint - origin);&#xD;&#xA;    &#xD;&#xA;    // now looking down -Z (optional depending on your coordinate system)&#xD;&#xA;    dir.z *= -1.0;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21611" PostHistoryTypeId="5" PostId="8146" RevisionGUID="b2bf1753-6889-4aaa-b76d-6ff2f79a86a8" CreationDate="2018-10-13T21:18:01.693" UserId="9505" Comment="added 240 characters in body" Text="You don't need that equation.&#xD;&#xA;&#xD;&#xA;You know your focus point (point on y-axis with focus_distance as z component) and the ray origin. All that needs to be done then is to compute the ray direction from the origin through that focus point.&#xD;&#xA;&#xD;&#xA;For what it's worth, I think a camera space formulation of a thin lens makes it easier to understand the concept:&#xD;&#xA;&#xD;&#xA;    float fov = 2.0f * atan((sensorWidth / (2.0f * focal_length))); // in radians&#xD;&#xA;    float tan_fov = tanf(fov / 2.0f);&#xD;&#xA;&#xD;&#xA;    // create point on lens, screen space samples are in [-1, 1] domain&#xD;&#xA;    vec3 p(screen_space_sample_x * tan_fov, screen_space_sample_y * tan_fov, 1.0);&#xD;&#xA;    &#xD;&#xA;    // calculate direction vector from origin to point on lens&#xD;&#xA;    dir = normalize(p - origin);&#xD;&#xA;    &#xD;&#xA;    // get uniformly distributed points on the unit disk&#xD;&#xA;    vec2 lens(0.0, 0.0);&#xD;&#xA;    concentricDiskSample(random1, random2, &amp;lens);&#xD;&#xA;    &#xD;&#xA;    // scale points in [-1, 1] domain to actual aperture radius&#xD;&#xA;    lens *= apertureRadius;&#xD;&#xA;    &#xD;&#xA;    // new origin is these points on the lens&#xD;&#xA;    origin.x = lens.x;&#xD;&#xA;    origin.y = lens.y;&#xD;&#xA;    origin.z = 0.0;&#xD;&#xA;    &#xD;&#xA;    // Compute point on plane of focus, intersection on z axis&#xD;&#xA;    float intersection = std::abs(focus_distance / dir.z);&#xD;&#xA;    vec3 focusPoint = dir * intersection;&#xD;&#xA;    dir = normalize(focusPoint - origin);&#xD;&#xA;    &#xD;&#xA;    // now looking down -Z (optional depending on your coordinate system)&#xD;&#xA;    dir.z *= -1.0;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21613" PostHistoryTypeId="2" PostId="8147" RevisionGUID="052ccde7-d3e5-4fbc-9022-48f59da81bf3" CreationDate="2018-10-14T12:37:19.387" UserId="7868" Text="I'm caching distances for SDF functions in volume textures for faster rendering, and I'd like to use trilinear interpolation for smoother edges. I know that I'll need distance values at each corner; can I blend adjacent voxels, or will I need to store eight separate distances in each sample?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21614" PostHistoryTypeId="1" PostId="8147" RevisionGUID="052ccde7-d3e5-4fbc-9022-48f59da81bf3" CreationDate="2018-10-14T12:37:19.387" UserId="7868" Text="Corner values for trilinear interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="21615" PostHistoryTypeId="3" PostId="8147" RevisionGUID="052ccde7-d3e5-4fbc-9022-48f59da81bf3" CreationDate="2018-10-14T12:37:19.387" UserId="7868" Text="|interpolation|sampling|hlsl|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21616" PostHistoryTypeId="4" PostId="8147" RevisionGUID="03057877-f97d-4baa-ac86-1621b0ccf3dd" CreationDate="2018-10-14T12:45:18.263" UserId="7868" Comment="clarified title" Text="Choosing corner values for trilinear interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="21617" PostHistoryTypeId="2" PostId="8148" RevisionGUID="0d701496-4a58-432f-a79c-de4f57ac2c60" CreationDate="2018-10-14T17:01:41.520" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="21618" PostHistoryTypeId="1" PostId="8148" RevisionGUID="0d701496-4a58-432f-a79c-de4f57ac2c60" CreationDate="2018-10-14T17:01:41.520" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="21619" PostHistoryTypeId="2" PostId="8149" RevisionGUID="110c292c-6188-416e-8292-eadccdbcc7b9" CreationDate="2018-10-14T17:01:41.520" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="21620" PostHistoryTypeId="1" PostId="8149" RevisionGUID="110c292c-6188-416e-8292-eadccdbcc7b9" CreationDate="2018-10-14T17:01:41.520" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="21621" PostHistoryTypeId="5" PostId="8068" RevisionGUID="0c17c010-e9f6-4527-8a30-7ec03d553a66" CreationDate="2018-10-14T18:28:37.547" UserDisplayName="user7220" Comment="Corrected links" Text="Given point-cloud data :&#xD;&#xA;For example. &#xD;&#xA;position + color and normal.&#xD;&#xA;&#xD;&#xA;What will you use to generate mesh of this data &#xD;&#xA;and keep reasonable quality for real time cases ? &#xD;&#xA;&#xD;&#xA;Additional info to consider:&#xD;&#xA;&#xD;&#xA; 1. In some cases given also&#xD;&#xA;    3D cameras world transforms which generated the PCL.&#xD;&#xA;&#xD;&#xA; 2. Number of input vertices : ~50k and up to millions .&#xD;&#xA;&#xD;&#xA; 3. Target latency from input to output : &lt; 40ms&#xD;&#xA;&#xD;&#xA; 4. Output triangle mesh (preferably not a must) &#xD;&#xA;&#xD;&#xA; 5. More info about mesh reconstruction  &#xD;&#xA;    [A Benchmark for Surface Reconstruction][1]&#xD;&#xA;&#xD;&#xA;Any inputs are welcome.  &#xD;&#xA;FAQ:&#xD;&#xA;&#xD;&#xA;How the data look like ?&#xD;&#xA;&#xD;&#xA; - Float* Position  [x1,y1,z1,x2,y2,z2...]&#xD;&#xA; - Float* Normal    [nx1,ny1,nz1,nx2,ny2,nz2...]&#xD;&#xA; - float or int8 for the color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.utah.edu/~bergerm/recon_bench/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21622" PostHistoryTypeId="24" PostId="8068" RevisionGUID="0c17c010-e9f6-4527-8a30-7ec03d553a66" CreationDate="2018-10-14T18:28:37.547" Comment="Proposed by 7220 approved by 4908, 231 edit id of 443" ContentLicense="CC BY-SA 4.0" />
  <row Id="21623" PostHistoryTypeId="5" PostId="8149" RevisionGUID="4857e5d8-6559-48cc-9bd8-b1943e1a2ed0" CreationDate="2018-10-14T18:30:28.897" UserDisplayName="user7220" Comment="added 198 characters in body" Text="OpenCL (Open Computing Language) is a framework for writing programs that execute across heterogeneous platforms consisting of CPUs, GPUs, DSPs, FPGAs and other processors or hardware accelerators. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21624" PostHistoryTypeId="24" PostId="8149" RevisionGUID="4857e5d8-6559-48cc-9bd8-b1943e1a2ed0" CreationDate="2018-10-14T18:30:28.897" Comment="Proposed by 7220 approved by 231 edit id of 444" ContentLicense="CC BY-SA 4.0" />
  <row Id="21625" PostHistoryTypeId="5" PostId="7959" RevisionGUID="a3ae1648-a40d-4cbb-ab68-5c3cf72a42a3" CreationDate="2018-10-14T18:31:15.790" UserDisplayName="user7220" Comment="Corrected links" Text="[Rotation matrix | wikipedia.org][1] in section that says &quot;in three dimensions&quot;. It's the first search result when searching about rotating a vector about an axis. Let me know if you have any questions.&#xD;&#xA;&#xD;&#xA;For your specific problem: bring the point P to the origin, then rotate the vector about the Z axis, then bring the point P back to its original location.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="21626" PostHistoryTypeId="24" PostId="7959" RevisionGUID="a3ae1648-a40d-4cbb-ab68-5c3cf72a42a3" CreationDate="2018-10-14T18:31:15.790" Comment="Proposed by 7220 approved by 4908, 231 edit id of 442" ContentLicense="CC BY-SA 4.0" />
  <row Id="21627" PostHistoryTypeId="10" PostId="7860" RevisionGUID="5fd49165-9c2e-490f-86dc-88bf7a38404f" CreationDate="2018-10-14T18:32:21.250" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="21628" PostHistoryTypeId="6" PostId="8147" RevisionGUID="bc742ea6-5e50-4148-a488-21438c7a0160" CreationDate="2018-10-14T22:48:36.847" UserId="7868" Comment="Adjusted tags" Text="|interpolation|sampling|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21629" PostHistoryTypeId="50" PostId="7643" RevisionGUID="84728621-cbd2-418b-88be-eae95fb6e6ce" CreationDate="2018-10-14T23:00:20.953" UserId="-1" />
  <row Id="21630" PostHistoryTypeId="50" PostId="4632" RevisionGUID="33a7ab32-5e08-4698-8431-204457278415" CreationDate="2018-10-15T13:00:03.880" UserId="-1" />
  <row Id="21631" PostHistoryTypeId="5" PostId="8131" RevisionGUID="c425f976-0840-46d4-8a1a-aa11489b2f13" CreationDate="2018-10-15T16:14:41.823" UserId="7644" Comment="add images" Text="I am currently experiencing a very obvious artifact that only occur when I use normal maps. However it only occurs when looking at surfaces on very grazing angles.&#xD;&#xA;&#xD;&#xA;Here is a picture of the artifact:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here is an image of the normals:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I will also post the vertex and fragment shader code for unpacking normals maps:&#xD;&#xA;&#xD;&#xA;Vertex Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 T = normalize(normalMatrix * tangent);&#xD;&#xA;    vec3 B = normalize(normalMatrix * bitangent);&#xD;&#xA;    vec3 N = normalize(normalMatrix * normal);&#xD;&#xA;    TBN = mat3(T, B, N);&#xD;&#xA;&#xD;&#xA;Fragment Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 normal = texture(material.texture_normal, TexCoords).rgb;&#xD;&#xA;    normal = normalize(normal * 2.0f - 1.0f);&#xD;&#xA;	normal = normalize(TBN * normal);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I would really appreciate if anyone has ever experiences this kind of artifact. Is it my BRDF, is it my normal calculations? I am not sure.. I would appreciate any insight people have!&#xD;&#xA;&#xD;&#xA;If you want to see my fragment shader and my BRDF you can find the code here:&#xD;&#xA;&#xD;&#xA;https://github.com/Ershany/Arcane-Engine/blob/WIP_PBR/Arcane%20Engine%20Core/src/shaders/pbr_model.frag&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZNQL3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pxxSt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21632" PostHistoryTypeId="24" PostId="8131" RevisionGUID="c425f976-0840-46d4-8a1a-aa11489b2f13" CreationDate="2018-10-15T16:14:41.823" Comment="Proposed by 7644 approved by 8893 edit id of 445" ContentLicense="CC BY-SA 4.0" />
  <row Id="21633" PostHistoryTypeId="5" PostId="8131" RevisionGUID="900156f6-2ab5-4c41-8d8e-c0d2ac281120" CreationDate="2018-10-15T16:15:24.850" UserId="8893" Comment="deleted 34 characters in body" Text="I am currently experiencing a very obvious artifact that only occur when I use normal maps. However it only occurs when looking at surfaces on very grazing angles.&#xD;&#xA;&#xD;&#xA;Here is a picture of the artifact:&#xD;&#xA;[![normal artifact][1]][1]&#xD;&#xA;&#xD;&#xA;And here is an image of the normals:&#xD;&#xA;[![normals][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I will also post the vertex and fragment shader code for unpacking normals maps:&#xD;&#xA;&#xD;&#xA;Vertex Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 T = normalize(normalMatrix * tangent);&#xD;&#xA;    vec3 B = normalize(normalMatrix * bitangent);&#xD;&#xA;    vec3 N = normalize(normalMatrix * normal);&#xD;&#xA;    TBN = mat3(T, B, N);&#xD;&#xA;&#xD;&#xA;Fragment Shader Snippet:&#xD;&#xA;&#xD;&#xA;    vec3 normal = texture(material.texture_normal, TexCoords).rgb;&#xD;&#xA;    normal = normalize(normal * 2.0f - 1.0f);&#xD;&#xA;	normal = normalize(TBN * normal);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I would really appreciate if anyone has ever experiences this kind of artifact. Is it my BRDF, is it my normal calculations? I am not sure.. I would appreciate any insight people have!&#xD;&#xA;&#xD;&#xA;If you want to see my fragment shader and my BRDF you can find the code here:&#xD;&#xA;&#xD;&#xA;https://github.com/Ershany/Arcane-Engine/blob/WIP_PBR/Arcane%20Engine%20Core/src/shaders/pbr_model.frag&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZNQL3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pxxSt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21634" PostHistoryTypeId="50" PostId="6012" RevisionGUID="b3306486-e257-4816-830b-03dfee29bb30" CreationDate="2018-10-15T19:00:31.637" UserId="-1" />
  <row Id="21635" PostHistoryTypeId="2" PostId="8150" RevisionGUID="8e4ee392-5b97-44fb-97f2-b86bb85f4945" CreationDate="2018-10-15T19:14:03.233" UserId="506" Text="As a rule, SDFs do much better under interpolation than regular images do—it’s why you can mostly get away with using tiny textures for e.g. font data. You should be fine interpolating neighboring voxels." ContentLicense="CC BY-SA 4.0" />
  <row Id="21637" PostHistoryTypeId="2" PostId="8151" RevisionGUID="eab8fb4c-79e2-4731-8c11-965e198308df" CreationDate="2018-10-16T06:00:28.530" UserId="9513" Text="I wish to understand the specific application of Multiple Importance Sampling (MIS) to weighting BSDF sampling and light sampling together.&#xD;&#xA;Refer to the following diagram from [these Stanford course notes](https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter9.pdf):&#xD;&#xA;&#xD;&#xA;[![Multiple Importance Sampling][1]][1]&#xD;&#xA;&#xD;&#xA;I understand the source of noise in the left diagram **(a)**, but not in the right **(b)**, and I think this stems from understanding what &quot;sampling the BSDF&quot; means, but not understanding what &quot;sampling the light sources&quot; means.&#xD;&#xA;&#xD;&#xA;To confirm my understanding I'm going to grossly simplify the general path tracing procedure, and specialize it to a single bounce in this scene, to get the point across:&#xD;&#xA;&#xD;&#xA;BSDF sampling (diagram **(a)**) procedure:&#xD;&#xA;------------------------------------------&#xD;&#xA;&#xD;&#xA; - Cast a ray from the camera for a given pixel.&#xD;&#xA; - Upon hitting the glossy surface, sample the surface's BSDF, then continue along the newly sampled ray.&#xD;&#xA; - Hopefully, you hit the light, in which case you contribute energy to the given pixel.&#xD;&#xA;&#xD;&#xA;This will obviously yield the noise profile we see in diagram **(a)**; the noise goes down as the surface gets glossier (sharpening the distribution of the BSDF) and as the light gets bigger (making the target easier to hit by chance).&#xD;&#xA;&#xD;&#xA;However, I don't understand the nature of the noise in diagram **(b)**, and I therefore clearly don't understand what &quot;sampling the light source&quot; means. My guess would be a procedure like:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Light source sampling (diagram **(b)**) procedure(???):&#xD;&#xA;------------------------------------------&#xD;&#xA;&#xD;&#xA; - Cast a ray from the camera for a given pixel.&#xD;&#xA; - Upon hitting the glossy surface, uniformly sample the solid angle that subtends the light source (i.e., a &quot;shadow ray&quot;), then continue along the newly sampled ray.&#xD;&#xA; - If you hit the light (i.e., no obstructions) contribute energy to the given pixel, weighted inversely by the BSDF of the glossy surface evaluated at the shadow ray, (and probably also multiplied by some other weight representing the fraction of our total solid angle that the light takes up, as in regular importance sampling).&#xD;&#xA;&#xD;&#xA;(Again, I have grossly simplified, and have reduced the problem to a single bounce in this particular scene for illustrative purposes.)&#xD;&#xA;&#xD;&#xA;However, the procedure I have described above cannot possibly be what is meant by &quot;light source sampling&quot; in the linked paper, because then it wouldn't result in more noise with larger area lights.&#xD;&#xA;&#xD;&#xA;What's going on in diagram **(b)**?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UnvBZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21638" PostHistoryTypeId="1" PostId="8151" RevisionGUID="eab8fb4c-79e2-4731-8c11-965e198308df" CreationDate="2018-10-16T06:00:28.530" UserId="9513" Text="BSDF sampling versus light sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="21639" PostHistoryTypeId="3" PostId="8151" RevisionGUID="eab8fb4c-79e2-4731-8c11-965e198308df" CreationDate="2018-10-16T06:00:28.530" UserId="9513" Text="|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21640" PostHistoryTypeId="5" PostId="8151" RevisionGUID="16a3085a-5c16-4227-a58f-05682dd87556" CreationDate="2018-10-16T06:24:14.723" UserId="9513" Comment="added 521 characters in body" Text="I wish to understand the specific application of Multiple Importance Sampling (MIS) to weighting BSDF sampling and light sampling together.&#xD;&#xA;Refer to the following diagram from [these Stanford course notes](https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter9.pdf):&#xD;&#xA;&#xD;&#xA;[![Multiple Importance Sampling][1]][1]&#xD;&#xA;&#xD;&#xA;I understand the source of noise in the left diagram **(a)**, but not in the right **(b)**, and I think this stems from understanding what &quot;sampling the BSDF&quot; means, but not understanding what &quot;sampling the light sources&quot; means.&#xD;&#xA;&#xD;&#xA;To confirm my understanding I'm going to grossly simplify the general path tracing procedure, and specialize it to a single bounce in this scene, to get the point across:&#xD;&#xA;&#xD;&#xA;BSDF sampling (diagram **(a)**) procedure:&#xD;&#xA;------------------------------------------&#xD;&#xA;&#xD;&#xA; - Cast a ray from the camera for a given pixel.&#xD;&#xA; - Upon hitting the glossy surface, sample the surface's BSDF, then continue along the newly sampled ray.&#xD;&#xA; - Hopefully, you hit the light, in which case you contribute energy to the given pixel.&#xD;&#xA;&#xD;&#xA;This will obviously yield the noise profile we see in diagram **(a)**; the noise goes down as the surface gets glossier (sharpening the distribution of the BSDF) and as the light gets bigger (making the target easier to hit by chance).&#xD;&#xA;&#xD;&#xA;However, I don't understand the nature of the noise in diagram **(b)**, and I therefore clearly don't understand what &quot;sampling the light source&quot; means. My guess would be a procedure like:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Light source sampling (diagram **(b)**) procedure(???):&#xD;&#xA;------------------------------------------&#xD;&#xA;&#xD;&#xA; - Cast a ray from the camera for a given pixel.&#xD;&#xA; - Upon hitting the glossy surface, uniformly sample the solid angle that subtends the light source (i.e., a &quot;shadow ray&quot;), then continue along the newly sampled ray.&#xD;&#xA; - If you hit the light (i.e., no obstructions) contribute energy to the given pixel, weighted inversely by the BSDF of the glossy surface evaluated at the shadow ray, (and probably also multiplied by some other weight representing the fraction of our total solid angle that the light takes up, as in regular importance sampling).&#xD;&#xA;&#xD;&#xA;(Again, I have grossly simplified, and have reduced the problem to a single bounce in this particular scene for illustrative purposes.)&#xD;&#xA;&#xD;&#xA;However, the procedure I have described above cannot possibly be what is meant by &quot;light source sampling&quot; in the linked paper, because then it wouldn't result in more noise with larger area lights.&#xD;&#xA;&#xD;&#xA;What's going on in diagram **(b)**?&#xD;&#xA;&#xD;&#xA;**Edit:** I suddenly understood the issue. The noise in the top right corner of **(b)** is because it's struggling to find the tiny fraction of angles in which the BSDF is not extremely close to zero. My assertion &quot;... because then it wouldn't result in more noise with larger area lights&quot; is precisely wrong, because larger area lights correspond to sampling over a larger fraction of the solid angle, and thus sampling the inverse BSDF weights with higher variance.&#xD;&#xA;&#xD;&#xA;I'm now looking for how to delete my question.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UnvBZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21641" PostHistoryTypeId="5" PostId="8151" RevisionGUID="4adc728e-9dd7-4035-8e5a-98b1e1ef11eb" CreationDate="2018-10-16T06:35:03.390" UserId="9513" Comment="added 96 characters in body" Text="I wish to understand the specific application of Multiple Importance Sampling (MIS) to weighting BSDF sampling and light sampling together.&#xD;&#xA;Refer to the following diagram from [these Stanford course notes](https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter9.pdf):&#xD;&#xA;&#xD;&#xA;[![Multiple Importance Sampling][1]][1]&#xD;&#xA;&#xD;&#xA;I understand the source of noise in the left diagram **(a)**, but not in the right **(b)**, and I think this stems from understanding what &quot;sampling the BSDF&quot; means, but not understanding what &quot;sampling the light sources&quot; means.&#xD;&#xA;&#xD;&#xA;To confirm my understanding I'm going to grossly simplify the general path tracing procedure, and specialize it to a single bounce in this scene, to get the point across:&#xD;&#xA;&#xD;&#xA;BSDF sampling (diagram **(a)**) procedure:&#xD;&#xA;------------------------------------------&#xD;&#xA;&#xD;&#xA; - Cast a ray from the camera for a given pixel.&#xD;&#xA; - Upon hitting the glossy surface, sample the surface's BSDF, then continue along the newly sampled ray.&#xD;&#xA; - Hopefully, you hit the light, in which case you contribute energy to the given pixel.&#xD;&#xA;&#xD;&#xA;This will obviously yield the noise profile we see in diagram **(a)**; the noise goes down as the surface gets glossier (sharpening the distribution of the BSDF) and as the light gets bigger (making the target easier to hit by chance).&#xD;&#xA;&#xD;&#xA;However, I don't understand the nature of the noise in diagram **(b)**, and I therefore clearly don't understand what &quot;sampling the light source&quot; means. My guess would be a procedure like:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Light source sampling (diagram **(b)**) procedure(???):&#xD;&#xA;------------------------------------------&#xD;&#xA;&#xD;&#xA; - Cast a ray from the camera for a given pixel.&#xD;&#xA; - Upon hitting the glossy surface, uniformly sample the solid angle that subtends the light source (i.e., a &quot;shadow ray&quot;), then continue along the newly sampled ray.&#xD;&#xA; - If you hit the light (i.e., no obstructions) contribute energy to the given pixel, weighted inversely by the BSDF of the glossy surface evaluated at the shadow ray, (and probably also multiplied by some other weight representing the fraction of our total solid angle that the light takes up, as in regular importance sampling).&#xD;&#xA;&#xD;&#xA;(Again, I have grossly simplified, and have reduced the problem to a single bounce in this particular scene for illustrative purposes.)&#xD;&#xA;&#xD;&#xA;However, the procedure I have described above cannot possibly be what is meant by &quot;light source sampling&quot; in the linked paper, because then it wouldn't result in more noise with larger area lights.&#xD;&#xA;&#xD;&#xA;What's going on in diagram **(b)**?&#xD;&#xA;&#xD;&#xA;**Edit:** I suddenly understood the issue. The noise in the top right corner of **(b)** is because it's struggling to find the tiny fraction of angles in which the BSDF is not extremely close to zero. My assertion &quot;... because then it wouldn't result in more noise with larger area lights&quot; is precisely wrong, because larger area lights correspond to sampling over a larger fraction of the solid angle, and thus sampling the inverse BSDF weights with higher variance.&#xD;&#xA;&#xD;&#xA;I'm now looking for how to delete my question. Hitting the &quot;flag&quot; button just sends me to the top of the page, and doesn't do anything else...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UnvBZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21642" PostHistoryTypeId="2" PostId="8152" RevisionGUID="385bea99-b007-4a96-9e60-a67c5e8c3c08" CreationDate="2018-10-16T08:27:04.653" UserId="8288" Text="sRGB is often contrasted with &quot;linear RGB.&quot;&#xD;&#xA;&#xD;&#xA; - Images are stored on disk and passed to displays in **sRGB,** which is approximately perceptually uniform in intensity.&#xD;&#xA; - Shader math is done in **linear RGB,** which is physically uniform in intensity.&#xD;&#xA; - Gamma correction can be applied to convert between the two.&#xD;&#xA;&#xD;&#xA;Now, sRGB has a standard that colorimetrically specifies its gamut, saying exactly where pure red, green, blue and white lie.  But there is no corresponding standard for just &quot;linear RGB.&quot;  *Any* triangle on a chromaticity diagram could be said to be linear, and, indeed, there are several well known gamuts to choose from:&#xD;&#xA;&#xD;&#xA;[![RGB gamuts][1]][1]&#xD;&#xA;&#xD;&#xA;In practice, when we say &quot;linear RGB,&quot; we mean &quot;sRGB without the gamma correction.&quot;  (This is implicitly what we're doing when we apply sRGB gamma correction as a final post-processing step but ignore color spaces for the rest of the rendering pipeline.)&#xD;&#xA;&#xD;&#xA;But why is *that* RGB gamut the correct one to use for interpolation and lighting calculations?  It seems arbitrary.  If anything, wouldn't we want to use the largest possible gamut for internal calculations, and then clip or scale colors to the output device's gamut at the very end?&#xD;&#xA;&#xD;&#xA;Is it that RGB lighting is going to be approximate no matter what, so it doesn't matter which gamut we pick, and we may as well pick the one closest to what the display natively supports?  Is it just negligence?  Or do calculations in these different gamuts actually yield the exact same results, somehow?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gJHM8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21643" PostHistoryTypeId="1" PostId="8152" RevisionGUID="385bea99-b007-4a96-9e60-a67c5e8c3c08" CreationDate="2018-10-16T08:27:04.653" UserId="8288" Text="For shader math, why should linear RGB keep the gamut of sRGB?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21644" PostHistoryTypeId="3" PostId="8152" RevisionGUID="385bea99-b007-4a96-9e60-a67c5e8c3c08" CreationDate="2018-10-16T08:27:04.653" UserId="8288" Text="|rendering|lighting|color|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21645" PostHistoryTypeId="50" PostId="5996" RevisionGUID="5dc863d1-f2b7-44ad-a716-ce9d67a2b534" CreationDate="2018-10-16T10:00:20.483" UserId="-1" />
  <row Id="21646" PostHistoryTypeId="2" PostId="8153" RevisionGUID="f435b203-ec64-4c0c-a001-cd047304f91a" CreationDate="2018-10-16T16:13:27.120" UserId="9515" Text="I am building an algorithm which takes a bitmap image as input and render the image as an embroidery design. &#xD;&#xA;&#xD;&#xA;The different steps are : &#xD;&#xA;&#xD;&#xA;  - Vectorize the image, I keep only 5 colors  (Done) &#xD;&#xA;  - Generate&#xD;&#xA;   stitches lines (Done) &#xD;&#xA;  - Apply wire embroidery texture to the lines,&#xD;&#xA;   add lights and show a realistic rendering ( It's this step that I am&#xD;&#xA;   having trouble with)&#xD;&#xA;&#xD;&#xA;Let's take an example.&#xD;&#xA;The original image is : &#xD;&#xA;&#xD;&#xA;![Original image](https://i.stack.imgur.com/ETD2t.png)&#xD;&#xA;&#xD;&#xA;From there, I vectorize the image and obtain an SVG file.&#xD;&#xA;&#xD;&#xA;After that, I generate stitches lines automatically which you can find here (svg file): https://www.dropbox.com/s/jmi6rz1ixgkjjpb/flowers_fill_0.7_vLongShort_space_randomLength.svg?dl=0&#xD;&#xA;&#xD;&#xA;When you zoom in, it looks like this : &#xD;&#xA;&#xD;&#xA;![stitches](https://i.stack.imgur.com/MwAwL.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I export the svg as png, I get : &#xD;&#xA;&#xD;&#xA;![ExportPng](https://i.stack.imgur.com/QdxRV.png)&#xD;&#xA;&#xD;&#xA;As you can see; having this result is not enough to render realistically the embroidery design. &#xD;&#xA;&#xD;&#xA;I am looking to have a texture more like this : &#xD;&#xA;&#xD;&#xA;![Real](https://s3.amazonaws.com/threadsmagazine.s3.tauntoncloud.com/app/uploads/4411/86/11133110/86-machine-embroidery-03.jpg)&#xD;&#xA;&#xD;&#xA;I tried generating a normal map and the use it adds some depth, but again, the result looks very plastic ... : &#xD;&#xA;&#xD;&#xA;![Rendering with normal map](https://i.stack.imgur.com/IZSit.png)&#xD;&#xA;&#xD;&#xA;I don't know what I should do now to have a realistic rendering ...&#xD;&#xA;At first, it wasn't supposed to be a computer graphic problem so I am not a specialist in the area, but I think using webgl or opengl is the best choice. &#xD;&#xA;&#xD;&#xA;However, I don't know how to give the rights textures to the lines ...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21647" PostHistoryTypeId="1" PostId="8153" RevisionGUID="f435b203-ec64-4c0c-a001-cd047304f91a" CreationDate="2018-10-16T16:13:27.120" UserId="9515" Text="How to apply wire texture for realistic rendering of embroidery?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21648" PostHistoryTypeId="3" PostId="8153" RevisionGUID="f435b203-ec64-4c0c-a001-cd047304f91a" CreationDate="2018-10-16T16:13:27.120" UserId="9515" Text="|opengl|texture|2d-graphics|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21649" PostHistoryTypeId="2" PostId="8154" RevisionGUID="95ac7581-d849-4b0e-8fa7-59647d38bb9e" CreationDate="2018-10-16T16:13:36.600" UserId="2654" Text="&gt; In practice, when we say &quot;linear RGB,&quot; we mean &quot;sRGB without the gamma correction.&quot;&#xD;&#xA;&#xD;&#xA;It would be more correct to say that there is the &quot;sRGB colorspace&quot; and the &quot;linearized sRGB colorspace&quot;, with the sRGB specification definition the conversion from one to another.&#xD;&#xA;&#xD;&#xA;Yes, there are infinitely many &quot;linear RGB&quot; color spaces. But the thing that all of these &quot;linear RGB&quot; colorspaces have in common is that they are *linear*. This means that, if you double the value of any component, you double the intensity of the light that the component represents. That's essentially what it means to be &quot;linear&quot;: there is a linear mapping between color values and the resulting intensity of that light color.&#xD;&#xA;&#xD;&#xA;This is important because lighting equations don't work if the color values do not linearly map to light intensities. But the equations don't care *which* linear colorspace you use; you just have to pick one.&#xD;&#xA;&#xD;&#xA;So the linearized sRGB colorspace is not more correct than a linearized Adobe RGB colorspace or a linearized SWOP CMYK colorspace. What matters is precisely two things:&#xD;&#xA;&#xD;&#xA;1. The colorspace represents a linear mapping of values to light intensities.&#xD;&#xA;2. The colorspace chosen is *consistently* used in the lighting equation. That is, all colors used in the lighting equation come from the same (linear) colorspace.&#xD;&#xA;&#xD;&#xA;&gt; Is it that RGB lighting is going to be approximate no matter what, so it doesn't matter which gamut we pick, and we may as well pick the one closest to what the display natively supports?&#xD;&#xA;&#xD;&#xA;That, and the fact that sRGB conversion is built into hardware these days, while other colorspace conversion frequently is not. So if you want to use linearized Adobe RGB colorspace, you have to do a lot of work in your shaders to linearize the texel values and perform bilinear/trilinear interpolation on them correctly (which needs to be done after linearization) before you can even apply them to the lighting equation. And then you have to do the conversion from linearized Adobe RGB to linearized sRGB, so that you can write to an sRGB framebuffer image for display.&#xD;&#xA;&#xD;&#xA;Or you can just use linearized sRGB everywhere and have performance. The latter tends to win out." ContentLicense="CC BY-SA 4.0" />
  <row Id="21650" PostHistoryTypeId="6" PostId="8153" RevisionGUID="f76ee6c0-942b-4f17-996e-b5cbe9019358" CreationDate="2018-10-16T16:30:21.083" UserId="9515" Comment="edited tags" Text="|opengl|rendering|texture|2d-graphics|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21651" PostHistoryTypeId="50" PostId="7529" RevisionGUID="a3181a03-f395-42af-8b4e-07c3b7a7b64d" CreationDate="2018-10-16T22:00:34.767" UserId="-1" />
  <row Id="21655" PostHistoryTypeId="50" PostId="7633" RevisionGUID="51cc3fc5-ad86-46e6-a3de-c0c7114a8676" CreationDate="2018-10-17T07:00:33.207" UserId="-1" />
  <row Id="21657" PostHistoryTypeId="2" PostId="8156" RevisionGUID="100728e5-2211-4129-b78c-81e018942b57" CreationDate="2018-10-17T17:15:37.017" UserId="7462" Text="Assume the screen is axis aligned with origin at 0 and there is absolutely no view transformation.&#xD;&#xA;&#xD;&#xA;in other words we will simply try to project the model onto the screen  plane following perspective. Say our FOV is 60 degrees, so the focal length is tan(30).&#xD;&#xA;&#xD;&#xA;I am given a vertex $V=(x,y,z)$&#xD;&#xA;&#xD;&#xA;is the projected vertex $V_p = V/(z*tan(30))$ or $V_p = V/(z/tan(30))$" ContentLicense="CC BY-SA 4.0" />
  <row Id="21658" PostHistoryTypeId="1" PostId="8156" RevisionGUID="100728e5-2211-4129-b78c-81e018942b57" CreationDate="2018-10-17T17:15:37.017" UserId="7462" Text="Computing perspective directly" ContentLicense="CC BY-SA 4.0" />
  <row Id="21659" PostHistoryTypeId="3" PostId="8156" RevisionGUID="100728e5-2211-4129-b78c-81e018942b57" CreationDate="2018-10-17T17:15:37.017" UserId="7462" Text="|rendering|geometry|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21660" PostHistoryTypeId="2" PostId="8157" RevisionGUID="9a6e3856-944f-4877-b871-a9758c1c2f96" CreationDate="2018-10-18T16:54:45.563" UserId="228" Text="I'm reading through [Polygon Mesh Processing][1], section 4.3 (Surface fairing).&#xD;&#xA;It is my understanding that everything boils down to solve a problem of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta^k x = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $x = x(u,v)$ is our surface. If we descretize to a mesh the equation above might be rewritten as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L^k x = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $L^k$ is the $k^{th}$ power of the Laplacian matrix, and $L$ itself is defined using the Discrete Laplace Beltrami operator, which is something like&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta x = \frac{1}{2A_T} \sum_{j} (cotg (\alpha_{i,j}) + cotg (\beta_{i,j}))(x_j - x_i)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However despite the fact it might be very simple to understand in principle at least I'm trying to figure how this would be implemented.&#xD;&#xA;&#xD;&#xA;This is because to me the angles depends from the mesh vertices and therefore the system isn't actually linear. The other approach I was thinking is to use a gradient flow (diffusion) approach of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{\partial x}{\partial t} = -\Delta^k x&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;the above, in principle can be discretized as follows&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x(t + h) = x(t) - h L^k x(t)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And $L$ might be computed on the current known state of the surface $x(t)$, however the above is an explicit integrator which might lead to instability, and solving the issue would be done by solving&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(id + h L^k) x(t + h) = x(t)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But in such case there's the problem of $L$ which would depend from the unknown state $x(t+h)$, so the problem I'm having here is actually similar to the first one I exposed...&#xD;&#xA;&#xD;&#xA;So the actual question is:&#xD;&#xA;&#xD;&#xA;If the mesh $x$ is unknown so is the discretization of $\Delta^k$, how is this operator constructed then?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books?id=8zX-2VRqBAkC&amp;printsec=frontcover&amp;dq=polygon%20mesh%20processing&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwip4tz8t5DeAhUrL8AKHZHQCcsQ6AEIKTAA#v=onepage&amp;q=polygon%20mesh%20processing&amp;f=false" ContentLicense="CC BY-SA 4.0" />
  <row Id="21661" PostHistoryTypeId="1" PostId="8157" RevisionGUID="9a6e3856-944f-4877-b871-a9758c1c2f96" CreationDate="2018-10-18T16:54:45.563" UserId="228" Text="Surface fairing, implementation detail" ContentLicense="CC BY-SA 4.0" />
  <row Id="21662" PostHistoryTypeId="3" PostId="8157" RevisionGUID="9a6e3856-944f-4877-b871-a9758c1c2f96" CreationDate="2018-10-18T16:54:45.563" UserId="228" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21663" PostHistoryTypeId="2" PostId="8158" RevisionGUID="6a37c895-3c80-46af-8921-9506329cb45e" CreationDate="2018-10-18T20:36:49.783" UserId="7674" Text="I am involved in a project that had been modified to run on Apple and Linux computers, when it was originally Windows only. Specifically, Metal and Vulkan renderers have been written alongside the Direct3D one.&#xD;&#xA;&#xD;&#xA;Something I have noticed is that there is a static startup image for 3-4 mins with the text &quot;warming shaders&quot;, which is not there in the Windows version. This screen is not present after the first launch.&#xD;&#xA;&#xD;&#xA;Searching online did not give me any results that shed light on this. The one SO question asked about &quot;background prewarming&quot; which I presume could be used to avoid a long load screen? In any case, it doesn't explain what it IS.&#xD;&#xA;&#xD;&#xA;Simply put, what is shader warming, and why does Metal and Vulkan seem to require it? I have experience with OpenGL from many years ago where shaders were compiled from source at runtime. Is this a related concept? As I understand it, both Metal and Vulkan use binary/bytecode shaders, so compiling shouldn't be necessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="21664" PostHistoryTypeId="1" PostId="8158" RevisionGUID="6a37c895-3c80-46af-8921-9506329cb45e" CreationDate="2018-10-18T20:36:49.783" UserId="7674" Text="What is shader warming, and why does Direct3D seem to avoid it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21665" PostHistoryTypeId="3" PostId="8158" RevisionGUID="6a37c895-3c80-46af-8921-9506329cb45e" CreationDate="2018-10-18T20:36:49.783" UserId="7674" Text="|shader|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21666" PostHistoryTypeId="2" PostId="8159" RevisionGUID="e0e722f3-ff07-4e93-b1a3-ee0780ea8efc" CreationDate="2018-10-18T21:17:53.863" UserId="48" Text="I hadn't heard the phrase 'shader warming' before, but from some googling around, it seems that some games/engines use this term for a method of forcing the shaders to be fully compiled during level load, [as explained in this answer](https://computergraphics.stackexchange.com/a/1634/48), to avoid hitches during gameplay.&#xD;&#xA;&#xD;&#xA;In Metal/Vulkan/D3D12, it's true that shaders are precompiled to a bytecode form, but this is hardware-independent bytecode; the shaders still need to be _further_ compiled to the GPU-specific machine code, which (in those APIs) is done by the graphics driver when a pipeline state object is created. If there are a lot of shaders, that can potentially take awhile. The fully compiled shaders can also be cached, so this only needs to be done the first time you run the app (at least until you update the driver, which could invalidate the cached results).&#xD;&#xA;&#xD;&#xA;So my guess about what's going on in your app is that the Metal/Vulkan renderers are calling it 'shader warming' when they go through and create all the pipeline state objects they're going to need—which entails compiling all the shaders. Meanwhile, in the Windows renderer, assuming it's D3D11 or earlier (not D3D12), perhaps the app is relying on the driver to compile shaders in the background, which lets it appear to load faster—at the cost of potentially having hitches a bit later if it tries to use a shader that's not finished compiling yet." ContentLicense="CC BY-SA 4.0" />
  <row Id="21667" PostHistoryTypeId="2" PostId="8160" RevisionGUID="ba20ef9d-ff09-41c0-a71d-718570bf8832" CreationDate="2018-10-19T06:18:35.227" UserId="9528" Text="I have just started implementing a fluid simulator based on the navier stokes equation.&#xD;&#xA;I am following Jos Stam's paper to do so.&#xD;&#xA;In this paper, it says that the velocity field must be mass conserving. Which I understand as, the velocity that flows into a cell should be the same the velocity that flows out.&#xD;&#xA;To get this mass conserving field, the hodge decomposition is used, and the text says:&#xD;&#xA;&#xD;&#xA;    &quot;every vector field is the sum of a mass conserving field and a gradient field.&quot; &#xD;&#xA;    Velocity field = mass conserving field + gradient field&#xD;&#xA;&#xD;&#xA;1) Is there a intuitive way to understand why this statement above is true? Maybe I have to read more on Hodge decomposition to understand this.&#xD;&#xA;&#xD;&#xA;2) The text also says that the gradient field can be computed by solving the poisson equation, Is there a simple explantion of why the poisson equation can be used to approximate this field? I'm wondering what else could be used instead. &#xD;&#xA;&#xD;&#xA;Could you point me to some resources that help understand my two questions intuitively, before delving into all the math?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21668" PostHistoryTypeId="1" PostId="8160" RevisionGUID="ba20ef9d-ff09-41c0-a71d-718570bf8832" CreationDate="2018-10-19T06:18:35.227" UserId="9528" Text="Hodge Decomposition in fluid simulations" ContentLicense="CC BY-SA 4.0" />
  <row Id="21669" PostHistoryTypeId="3" PostId="8160" RevisionGUID="ba20ef9d-ff09-41c0-a71d-718570bf8832" CreationDate="2018-10-19T06:18:35.227" UserId="9528" Text="|fluid-sim|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21670" PostHistoryTypeId="5" PostId="8157" RevisionGUID="30c30a71-644f-4387-ae9e-30bd3ed0696d" CreationDate="2018-10-19T09:26:17.750" UserId="228" Comment="added 1257 characters in body" Text="I'm reading through [Polygon Mesh Processing][1], section 4.3 (Surface fairing).&#xD;&#xA;&#xD;&#xA;The reference I mentioned defined defines &quot;Surface Fairing&quot; as&#xD;&#xA;&#xD;&#xA;&gt; The goal of surface fairing is to compute shapes that are as smooth as possible... in general fair surface should follow the principle of simplest shapes, the surfaces should be free by any unnecessary details or oscillation&quot;.&#xD;&#xA;&#xD;&#xA;It continues...&#xD;&#xA;&#xD;&#xA;&gt; This can be modeled by a suitable energy that penalizes unaesthetic behavior of the surface. A minimization of this fairness energy - subject to user defined constraints - eventually yields to the desired shape.&#xD;&#xA;&#xD;&#xA;The energy defined is function of a surface $x : \Omega \to \mathcal{S}$ and the form is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;E_M(x) = \int_{\Omega} \sqrt{det(\bf{I})}dudv&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $\bf{I}$ is the first fundamental form, however instead of this the dirichlet energy&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\tilde{E}_M(x) = \int_{\Omega} \lVert x_u \rVert^2 + \lVert x_v \rVert^2 dudv&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Is the one usually used. Higher order energies are also used, depending on how smooth is the shape we're looking for. Using the Euler-Lagrange equation (in a continuous setting) we end up with the simple PDE&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta x = 0,&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;subject to suitable boundary conditions. Discretazion to meshes is done by means of the Laplace-beltrami operator which I'll define below.&#xD;&#xA;&#xD;&#xA;In general it is my understanding that everything boils down to solve a problem of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta^k x = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $x = x(u,v)$ is our surface. If we descretize to a mesh the equation above might be rewritten as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L^k x = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $L^k$ is the $k^{th}$ power of the Laplacian matrix, and $L$ itself is defined using the Discrete Laplace Beltrami operator, which is something like&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta x = \frac{1}{2A_T} \sum_{j} (cotg (\alpha_{i,j}) + cotg (\beta_{i,j}))(x_j - x_i)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However despite the fact it might be very simple to understand in principle at least I'm trying to figure how this would be implemented.&#xD;&#xA;&#xD;&#xA;This is because to me the angles depends from the mesh vertices and therefore the system isn't actually linear. The other approach I was thinking is to use a gradient flow (diffusion) approach of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{\partial x}{\partial t} = -\Delta^k x&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;the above, in principle can be discretized as follows&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x(t + h) = x(t) - h L^k x(t)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And $L$ might be computed on the current known state of the surface $x(t)$, however the above is an explicit integrator which might lead to instability, and solving the issue would be done by solving&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(id + h L^k) x(t + h) = x(t)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But in such case there's the problem of $L$ which would depend from the unknown state $x(t+h)$, so the problem I'm having here is actually similar to the first one I exposed...&#xD;&#xA;&#xD;&#xA;So the actual question is:&#xD;&#xA;&#xD;&#xA;If the mesh $x$ is unknown so is the discretization of $\Delta^k$, how is this operator constructed then?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books?id=8zX-2VRqBAkC&amp;printsec=frontcover&amp;dq=polygon%20mesh%20processing&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwip4tz8t5DeAhUrL8AKHZHQCcsQ6AEIKTAA#v=onepage&amp;q=polygon%20mesh%20processing&amp;f=false" ContentLicense="CC BY-SA 4.0" />
  <row Id="21671" PostHistoryTypeId="2" PostId="8161" RevisionGUID="28a4c250-25d7-421b-81e4-c760fd172ea0" CreationDate="2018-10-19T12:22:48.717" UserId="7647" Text="Suppose I have a fluid which, like water, is incompressible; that is, its density is constant. I can find out how this fluid is flowing; let's say I inject dye at various points and follow how the dye particles move. I can estimate a velocity at each point, a velocity field $\mathbf{w}$. But water is incompressible; this means that the true velocity field $\mathbf{u}$ has to be mass-conserving. I want to &quot;correct&quot; my estimate $\mathbf{w}$ to find the closest mass-conserving velocity field.&#xD;&#xA;&#xD;&#xA;The local accumulation or depletion of the fluid is computed with the *divergence* of the vector field, $\operatorname{div}\mathbf{w}$. (Stam writes the divergence of $\mathbf{w}$ as $\nabla\cdot\mathbf{w}$.) The divergence is a *derivative*, which is important here because that means it's *linear*; the divergence of the sum of two vector fields is the sum of their divergences:&#xD;&#xA;$$ \operatorname{div}(\mathbf{u} + \mathbf{v}) = \operatorname{div}\mathbf{u} + \operatorname{div}\mathbf{v}. $$&#xD;&#xA;We want to find a mass-conserving field; that is, we want to find a field with *zero divergence*. That means that we want to construct a field $\mathbf{v}$ with the same divergence as $\mathbf{w}$; then&#xD;&#xA;$$ \operatorname{div}\mathbf{w} - \operatorname{div}\mathbf{v} = \operatorname{div}(\mathbf{w} - \mathbf{v}) = 0 $$&#xD;&#xA;so we can get our mass-conserving field $\mathbf{u} = \mathbf{w} - \mathbf{v}$.&#xD;&#xA;&#xD;&#xA;The only question is how we construct a field with a given divergence. For reasons I'll explain a few paragraphs down, we say that $\mathbf{v}$ is the gradient of some scalar field $q$, $\mathbf{v} = \operatorname{grad}q$. (Stam writes this as $\nabla q$.) Then we have&#xD;&#xA;$$ \operatorname{div}\mathbf{w} = \operatorname{div}\mathbf{v} =&#xD;&#xA;\operatorname{div}\operatorname{grad}q.$$&#xD;&#xA;It's worth looking at what this says. The divergence of a vector field is a scalar field; at each point, it gives the local accumulation or depletion of the fluid. Both the divergence and the gradient are derivatives (which is why they can also both be written with $\nabla$). The equation is thus saying that the scalar field (the divergence of $\mathbf{w}$) is a particular second derivative of the scalar field $q$. This derivative is called the *Laplacian* (Stam writes it as $\nabla^2 q$). The differential equation relating scalar fields $q$ and $a$&#xD;&#xA;$$ \operatorname{div}\mathrm{grad}\ q = a $$&#xD;&#xA;is the *Poisson equation*. It's not so much that you use it to *estimate* $q$ as that it's the actual *definition* of $q$.&#xD;&#xA;&#xD;&#xA;So, to &quot;correct&quot; our estimate $\mathbf{w}$, we can compute its divergence (a scalar field)&#xD;&#xA;$$ f = \operatorname{div}\mathbf{w}, $$&#xD;&#xA;solve the Poisson equation to find the scalar field $q$&#xD;&#xA;$$ \operatorname{div}\operatorname{grad} q = f, $$&#xD;&#xA;then subtract $\operatorname{grad}q$ from $\mathbf{w}$ to find our mass-conserving velocity field&#xD;&#xA;$$ \mathbf{u} = \mathbf{w} - \operatorname{grad}q. $$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Above we just assumed that $\mathbf{v} = \operatorname{grad}q$ for some $q$. What we actually want is to find a field $\mathbf{v}$ that is in some sense the &quot;smallest&quot; field with the given divergence, so we can find the &quot;closest&quot; mass-conserving field $\mathbf{u} = \mathbf{w} - \mathbf{v}$; here I'll explain how the gradient of a scalar field satisfies this requirement.&#xD;&#xA;&#xD;&#xA;We have a fixed amount of fluid moving through our space. &#xD;&#xA;If our flow is mass-conserving, then we have a conserved amount of fluid, without local accumulation or depletion. If we have any motion at all, then, the fluid must move in *cycles*. In the same way as we measure the local accumulation with the divergence operator, we can measure the local cyclic behaviour of the flow by using another vector operator, the *curl* (which can be written $\nabla\times\mathbf{v}$). The curl at a point gives, broadly speaking, the axis about which the flow is circling near that point.&#xD;&#xA;&#xD;&#xA;Now, consider the gradient of a scalar field, $\operatorname{grad} q$. (For instance, $q(x,y) = \sin x \cos y$.) The potential can be drawn as a height field:&#xD;&#xA;[![plot of z = sin(x)*cos(y)][1]][1]&#xD;&#xA;Then the gradient of this field puts at each point a vector pointing in the steepest uphill direction:&#xD;&#xA;[![vector field grad(sin(x) * cos(y))][2]][2]&#xD;&#xA;But since you're always going &quot;uphill&quot; as quickly as you can, I think it's clear that there's *no circulation* in this vector field! In fact, for *any* scalar potential $q$,&#xD;&#xA;$$ \operatorname{curl}\operatorname{grad}q = 0 ! $$&#xD;&#xA;&#xD;&#xA;There's also a second similar identity: $\operatorname{div}\operatorname{curl}\mathbf{v} = 0$; unfortunately, I can't think of a good intuition for that one. (But look at [this Math.SX answer](https://math.stackexchange.com/a/27010/152310) for a more mathematical explanation.) We can use these two identities to explicitly write the Hodge decomposition: $\mathbf{w} = \mathbf{v} + \mathbf{u}$, where $\mathbf{v}$ has no curl, and $\mathbf{u}$ has no divergence, or&#xD;&#xA;$$ \mathbf{w} = \operatorname{grad}q + \operatorname{curl}\mathbf{\nu},¹ $$&#xD;&#xA;for some scalar field $q$ and vector field $\mathbf{\nu}$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;¹The Hodge decomposition is actually more complicated if your space isn't simple, i.e. finite and ball-like; on more complicated spaces, like say the surface of a torus, we have curl-free fields which aren't the gradient of anything, and divergence-free fields which aren't the curl of anything. For most fluid modelling in CG, though, this isn't usually an issue.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sVzgE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Okc02.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21672" PostHistoryTypeId="2" PostId="8162" RevisionGUID="40c0f078-4805-4e7e-b473-753f7b02ca95" CreationDate="2018-10-19T19:42:02.563" UserId="6596" Text="Picking up from step 2, where you generated line segments to represent individual stitches, I would first suggest that you apply rounded ends to each segment, rather than square ends.&#xD;&#xA;&#xD;&#xA;I would then convert each segment to an **outline**, (i.e. each rounded stitch becomes an separate poly-line representing the outer boundary.) &#xD;&#xA;&#xD;&#xA;Next, I would **triangulate** each polyline into faces, (See the orange area in the included picture,) while *retaining the start- &amp; end-points of the original segment* (the green line) by encoding them into the shape as **vertex attributes*. &#xD;&#xA;&#xD;&#xA;Next, send these faces to be rendered by the **GPU**, applying a **vertex shader** which sets a ***vec2** varying variable* (sounds redundant, but it's not) indicating the vertex position relative to the original line segment (which we have included as *vertex attributes*) &#xD;&#xA;&#xD;&#xA;Now, we move on to the **fragment shader**, where we use the varying variable created in the vertex shader to derive a **normal**.&#xD;&#xA;&#xD;&#xA;Let's say that &quot;linePos&quot; is the position along the line segment, (i.e. the x-value, if the line is horizontal. y-value if it is vertical, etc.) &#xD;&#xA;&#xD;&#xA;Furthermore, let's say &quot;lineDist&quot; is the distance from the central line segment, e.g. -2 if it's 2 units to the left of the line (purple arrows) or +5 if it's on the right (blue arrows).&#xD;&#xA;&#xD;&#xA;We can use these two values, derived from the varying variable, to create a normal for the point on the thread. &#xD;&#xA;&#xD;&#xA;A bit of this code might be:&#xD;&#xA;&#xD;&#xA;    abs(sin(linePos+lineDist))&#xD;&#xA;&#xD;&#xA;but there's a fair bit more than that to write.&#xD;&#xA;I can't go through and write the entire program for you here &amp; now, but hopefully these ideas &amp; diagram will shine some light in the right direction.&#xD;&#xA;&#xD;&#xA;Best of luck.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;[![embroidery geometry diagram][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0nXwY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21673" PostHistoryTypeId="50" PostId="7730" RevisionGUID="5c720c59-35dc-4c97-97d9-075d51012b53" CreationDate="2018-10-20T00:00:00.037" UserId="-1" />
  <row Id="21674" PostHistoryTypeId="5" PostId="8162" RevisionGUID="f741de94-6bd9-4e0c-bb8b-9b68282f7618" CreationDate="2018-10-20T07:57:00.750" UserId="6596" Comment="added 711 characters in body" Text="Picking up from step 2, where you generated line segments to represent individual stitches, I would first suggest that you apply rounded ends to each segment, rather than square ends.&#xD;&#xA;&#xD;&#xA;I would then convert each segment to an **outline**, (i.e. each rounded stitch becomes an separate poly-line representing the outer boundary.)&#xD;&#xA;&#xD;&#xA;For example, suppose you start with point A &amp; point B, representing a single stitch in line segment form. We can derive the rounded outline of thus segment with the following Javascript code using **THREE.js**:&#xD;&#xA;&#xD;&#xA;		function outlineSegment (Ax, Ay, Bx, By, radius){&#xD;&#xA;			var radius = radius || 0.5; //millimeters?&#xD;&#xA;			var A = new THREE.Vector2(Ax, Ay);&#xD;&#xA;			var B = new THREE.Vector2(Bx, By);&#xD;&#xA;			var C = B.clone().sub(A).normalize().multiplyScalar(radius);&#xD;&#xA;			var angle = C.angle();&#xD;&#xA;			var outline = new THREE.Shape();&#xD;&#xA;			outline.moveTo( B.x + C.y, B.y - C.x );&#xD;&#xA;			outline.absarc(B.x, B.y, radius, angle-Math.PI/2, angle+Math.PI/2);&#xD;&#xA;			outline.lineTo(A.x - C.y, A.y + C.x);&#xD;&#xA;			outline.absarc(A.x, A.y, radius, angle+Math.PI/2, angle+Math.PI*3/2);&#xD;&#xA;			outline.autoClose = true;&#xD;&#xA;			return new THREE.ShapeGeometry(outline);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;The above function finishes by **triangulating** the polyline into faces, (See the orange area in the included picture.)&#xD;&#xA;&#xD;&#xA;Next, send these faces to be rendered by the **GPU**, applying a **vertex shader** which sets a ***vec2** varying variable* (sounds redundant, but it's not) indicating the vertex position relative to the original line segment (which we have included as *vertex attributes*) &#xD;&#xA;&#xD;&#xA;Now, we move on to the **fragment shader**, where we use the varying variable created in the vertex shader to derive a **normal**.&#xD;&#xA;&#xD;&#xA;Let's say that &quot;linePos&quot; is the position along the line segment, (i.e. the x-value, if the line is horizontal. y-value if it is vertical, etc.) &#xD;&#xA;&#xD;&#xA;Furthermore, let's say &quot;lineDist&quot; is the distance from the central line segment, e.g. -2 if it's 2 units to the left of the line (purple arrows) or +5 if it's on the right (blue arrows).&#xD;&#xA;&#xD;&#xA;We can use these two values, derived from the varying variable, to create a normal for the point on the thread. &#xD;&#xA;&#xD;&#xA;A bit of this code might be:&#xD;&#xA;&#xD;&#xA;    abs(sin(linePos+lineDist))&#xD;&#xA;&#xD;&#xA;but there's a fair bit more than that to write.&#xD;&#xA;I can't go through and write the entire program for you here &amp; now, but hopefully these ideas &amp; diagram will shine some light in the right direction.&#xD;&#xA;&#xD;&#xA;Best of luck.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;[![embroidery geometry diagram][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0nXwY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21675" PostHistoryTypeId="2" PostId="8163" RevisionGUID="bb3379c1-b41a-4928-ba8c-5fec22e8762e" CreationDate="2018-10-20T07:58:52.687" UserId="9533" Text="Talking about *Linear RGB* must be avoided because it does not tell you anything about the RGB colourspace intrinsics, i.e., Primaries, Whitepoint and Colour Component Transfer Functions. A few years ago, assuming it was sRGB was middling but nowadays with DCI-P3 and BT.2020 being very common, it must be ruled out.&#xD;&#xA;&#xD;&#xA;The ideal gamut for rendering is the one that will minimize errors in respect to a real-world reference or more conveniently a ground truth spectral render. The first takeaway from this sentence is that the various RGB colourspaces are not equivalent and will not produce similar results.&#xD;&#xA;&#xD;&#xA;One might think that performing two renders with the same base colours but one where they are encoded with sRGB/BT.709 and the other one where they are encoded with DCI-P3 and then converting the two resulting images to for example ACES2065-1 will yield the same images but it is not the case. Some mathematical operations because of the nature of linear algebra and matrices are dependent on the given RGB colourspace primaries, i.e., on the colourspaces basis. The same operations performed in different RGB colourspace will yield different tristimulus values once converted back to CIE XYZ color space. For example multiplication, division and power operations are RGB colourspace primaries dependent while addition and subtraction are not.&#xD;&#xA;&#xD;&#xA;[![RGB Colourspaces and Exponentiation][1]][1]&#xD;&#xA;&#xD;&#xA;This image illustrates the effect of multiplying various colours by themselves into different RGB colourspaces: the resulting colours are different. The various samples are generated as follows: 3 random sRGB colourspace values are picked and converted to the three studied RGB colourspaces, they are exponentiated, converted back to sRGB colourspace, plotted in the CIE 1931 Chromaticity Diagram on the left and displayed as swatches on the right.&#xD;&#xA;&#xD;&#xA;Tests and research conducted by [Ward and Eydelberg-Vileshin (2002)][2], [Langlands and Mansencal (2014)][3] and [Mansencal (2014)][4] showed that gamuts with primaries closest to the spectral locus, i.e. spectrally sharp primaries, tend to minimize the errors compared to spectral ground truth renders.&#xD;&#xA;&#xD;&#xA;Here is an image I recently rendered with Mitsuba to re-validate our findings with Anders:&#xD;&#xA;&#xD;&#xA;[![Rendering Colourspaces][5]][5]&#xD;&#xA;&#xD;&#xA;Those are renders of the same scene using BT.709 primaries (first row), 47 spectral bins (second row), BT.2020 primaries (third row), spectral minus BT.709 primaries renders residuals (fourth row), spectral minus BT.2020 primaries renders residuals (fifth row). The last row showcases composite images assembled with three vertical stripes of respectively the BT.709 primaries, spectral and, BT.2020 primaries renders. Direct illumination tends to match between the renders. Areas that show the effect of multiple light bounces, i.e., the ceiling, in the BT.709 and BT.2020 primaries renders tend to exhibit increased saturation, especially in the BT.709 primaries render or slight loss of energy, especially in the BT.2020 render. Excluding outliers, e.g., the visible light source, the RMSE with the spectral render are **0.0083** and **0.0116** for respectively the BT.2020 primaries and BT.709 primaries renders.&#xD;&#xA;&#xD;&#xA;Now it does not mean they will always perform better, and one might be able to produce examples that will exhibit a bias toward BT.709/sRGB. The main takeaway is that RGB renders cannot match spectral renders and sharp wide gamuts tend to perform better. As for choosing a rendering colourspace, I would pick one with a wide gamut that encompasses Pointer's Gamut and DCI-P3, **BT.2020** or **ACEScg** are excellent candidates for that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SQRJ.png&#xD;&#xA;  [2]: http://diglib.eg.org/handle/10.2312/EGWR.EGWR02.117-124&#xD;&#xA;  [3]: https://www.colour-science.org/anders-langlands/&#xD;&#xA;  [4]: https://www.colour-science.org/posts/about-rgb-colourspace-models-performance/&#xD;&#xA;  [5]: https://i.stack.imgur.com/7GseL.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21676" PostHistoryTypeId="5" PostId="8162" RevisionGUID="8b9971e0-a086-4f9d-89af-d4e5b6706e5a" CreationDate="2018-10-20T16:06:47.707" UserId="6596" Comment="edited body" Text="Picking up from step 2, where you generated line segments to represent individual stitches, I would first suggest that you apply rounded ends to each segment, rather than square ends.&#xD;&#xA;&#xD;&#xA;I would then convert each segment to an **outline**, (i.e. each rounded stitch becomes an separate poly-line representing the outer boundary.)&#xD;&#xA;&#xD;&#xA;For example, suppose you start with point A &amp; point B, representing a single stitch in line segment form. We can derive the rounded outline of this segment with the following Javascript code using **THREE.js**:&#xD;&#xA;&#xD;&#xA;		function outlineSegment (Ax, Ay, Bx, By, radius){&#xD;&#xA;			var radius = radius || 0.5; //millimeters?&#xD;&#xA;			var A = new THREE.Vector2(Ax, Ay);&#xD;&#xA;			var B = new THREE.Vector2(Bx, By);&#xD;&#xA;			var C = B.clone().sub(A).normalize().multiplyScalar(radius);&#xD;&#xA;			var angle = C.angle();&#xD;&#xA;			var outline = new THREE.Shape();&#xD;&#xA;			outline.moveTo( B.x + C.y, B.y - C.x );&#xD;&#xA;			outline.absarc(B.x, B.y, radius, angle-Math.PI/2, angle+Math.PI/2);&#xD;&#xA;			outline.lineTo(A.x - C.y, A.y + C.x);&#xD;&#xA;			outline.absarc(A.x, A.y, radius, angle+Math.PI/2, angle+Math.PI*3/2);&#xD;&#xA;			outline.autoClose = true;&#xD;&#xA;			return new THREE.ShapeGeometry(outline);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;The above function finishes by **triangulating** the polyline into faces, (See the orange area in the included picture.)&#xD;&#xA;&#xD;&#xA;Next, send these faces to be rendered by the **GPU**, applying a **vertex shader** which sets a ***vec2** varying variable* (sounds redundant, but it's not) indicating the vertex position relative to the original line segment (which we have included as *vertex attributes*) &#xD;&#xA;&#xD;&#xA;Now, we move on to the **fragment shader**, where we use the varying variable created in the vertex shader to derive a **normal**.&#xD;&#xA;&#xD;&#xA;Let's say that &quot;linePos&quot; is the position along the line segment, (i.e. the x-value, if the line is horizontal. y-value if it is vertical, etc.) &#xD;&#xA;&#xD;&#xA;Furthermore, let's say &quot;lineDist&quot; is the distance from the central line segment, e.g. -2 if it's 2 units to the left of the line (purple arrows) or +5 if it's on the right (blue arrows).&#xD;&#xA;&#xD;&#xA;We can use these two values, derived from the varying variable, to create a normal for the point on the thread. &#xD;&#xA;&#xD;&#xA;A bit of this code might be:&#xD;&#xA;&#xD;&#xA;    abs(sin(linePos+lineDist))&#xD;&#xA;&#xD;&#xA;but there's a fair bit more than that to write.&#xD;&#xA;I can't go through and write the entire program for you here &amp; now, but hopefully these ideas &amp; diagram will shine some light in the right direction.&#xD;&#xA;&#xD;&#xA;Best of luck.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;[![embroidery geometry diagram][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0nXwY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21677" PostHistoryTypeId="2" PostId="8164" RevisionGUID="dd0272af-bf27-4bb2-8913-e2458c9c103f" CreationDate="2018-10-20T16:57:28.040" UserId="2173" Text="I would like to know the magic behind this tiny fractal shader; I didn't really understand the code and the mentioned thread...&#xD;&#xA;&#xD;&#xA;Is there an accessible explaination?&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/4ttBWM" ContentLicense="CC BY-SA 4.0" />
  <row Id="21678" PostHistoryTypeId="1" PostId="8164" RevisionGUID="dd0272af-bf27-4bb2-8913-e2458c9c103f" CreationDate="2018-10-20T16:57:28.040" UserId="2173" Text="How does this small fractal shader work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21679" PostHistoryTypeId="3" PostId="8164" RevisionGUID="dd0272af-bf27-4bb2-8913-e2458c9c103f" CreationDate="2018-10-20T16:57:28.040" UserId="2173" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21680" PostHistoryTypeId="2" PostId="8165" RevisionGUID="534f7a29-2640-4fb7-b3a2-5c083e902dff" CreationDate="2018-10-20T19:37:52.150" UserId="8233" Text="[glDispatchCompute](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDispatchCompute.xhtml) has the number of work groups as arguments.&#xD;&#xA;&#xD;&#xA;What is the point of having work groups? How are they useful, compared to just having NxM independent pixel calculations with a known (x,y) input parameter in the shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21681" PostHistoryTypeId="1" PostId="8165" RevisionGUID="534f7a29-2640-4fb7-b3a2-5c083e902dff" CreationDate="2018-10-20T19:37:52.150" UserId="8233" Text="What's the point of &quot;work groups&quot; for OpenGL compute shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21682" PostHistoryTypeId="3" PostId="8165" RevisionGUID="534f7a29-2640-4fb7-b3a2-5c083e902dff" CreationDate="2018-10-20T19:37:52.150" UserId="8233" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21684" PostHistoryTypeId="2" PostId="8166" RevisionGUID="8be79c78-9761-4ef3-94de-596a78fe5b10" CreationDate="2018-10-21T02:33:26.677" UserId="9535" Text="There are two sides to why sRGB particularly. For input non-HDR images, it is claimed that those should be assumed to be compressed to sRGB (whether this claim is accurate is a different story). Hence, before you can do any linear math operation on them, you need to decompress them from sRGB. It is also possible that an image was captured and compresssd to a different representation that is not sRGB, in which case you need to decompress that specific representation.&#xD;&#xA;&#xD;&#xA;The other side is the display. If you have an image and you need to display it, so you encode it in a representation that the display device requires. CRTs chose sRGB, then LCDs emulated that, so sRGB compression for monitor display has been the common choice for the last decades.&#xD;&#xA;&#xD;&#xA;I think the basis for the claim that human-made images are sRGB-encoded is because those images were assumed to have been authored on sRGB displays.&#xD;&#xA;&#xD;&#xA;So now you can probably see better why sRGB in particular was supported in hardware for shader math input and image display. It is the common case. Plus, it has good merits for reducing perceptual color banding artifacts, so it is a good way to compress colors in 8 bits and keep them looking plausible to humans." ContentLicense="CC BY-SA 4.0" />
  <row Id="21685" PostHistoryTypeId="5" PostId="8166" RevisionGUID="445b5b37-f3d1-4f71-a02d-ba8d5d52593f" CreationDate="2018-10-21T02:52:10.677" UserId="9535" Comment="Rephrased to better match the question title" Text="There are two sides to why sRGB particularly. For input non-HDR images, it is claimed that those should be assumed to be compressed to sRGB (whether this claim is accurate is a different story). Hence, before you can do any linear math operation on them, you need to decompress them from sRGB. It is also possible that an image was captured and compresssd to a different representation that is not sRGB, in which case you need to decompress that specific representation. In any case, the encoding implies a certain gamut that the input image will never escape, but your shader math doesn't have to stay in that gamut after the input image is decompressed. But in the end you have to consider the display.&#xD;&#xA;&#xD;&#xA;If you have an image and it is time to display it, you encode it in a representation that the display device requires. CRTs chose sRGB, then LCDs emulated that, so sRGB compression for monitor display has been the common choice for the last decades, and that restricted the output to stick within sRGB gamut, or else clipping will occur. Wider-range displays don't have to stick to that exact gamut.&#xD;&#xA;&#xD;&#xA;(I think the basis for the claim that human-made images are sRGB-encoded is because those images were assumed to have been authored on sRGB displays)&#xD;&#xA;&#xD;&#xA;So now you can probably see better why sRGB in particular was supported in hardware for shader math input and image display. It is the common case. Plus, it has good merits for reducing perceptual color banding artifacts, so it is a good way to compress colors in 8 bits and keep them looking plausible to humans." ContentLicense="CC BY-SA 4.0" />
  <row Id="21686" PostHistoryTypeId="5" PostId="8166" RevisionGUID="a93f3fc2-a252-4571-8b52-57ce28facb45" CreationDate="2018-10-21T02:58:38.967" UserId="9535" Comment="Bits" Text="There are two sides to why sRGB particularly. For input non-HDR images, it is claimed that those should be assumed to be compressed to sRGB (whether this claim is accurate is a different story). Hence, before you can do any linear math operation on them, you need to decompress them from sRGB. It is also possible that an image was captured and compresssd to a different representation that is not sRGB, in which case you need to decompress that specific representation. In any case, the encoding implies a certain gamut that the input image will never escape (because sRGB-stored images are typically truncated to 8-bits per channel), but your shader math doesn't have to stay in that gamut after the input image is decompressed. But in the end you have to consider the display.&#xD;&#xA;&#xD;&#xA;If you have an image and it is time to display it, you encode it in a representation that the display device requires. CRTs chose sRGB, then LCDs emulated that, so sRGB compression for monitor display has been the common choice for the last decades, and that restricted the output to stick within sRGB gamut, or else clipping will occur. Wider-range displays don't have to stick to that exact gamut.&#xD;&#xA;&#xD;&#xA;(I think the basis for the claim that human-made images are sRGB-encoded is because those images were assumed to have been authored on sRGB displays)&#xD;&#xA;&#xD;&#xA;So now you can probably see better why sRGB in particular was supported in hardware for shader math input and image display. It is the common case. Plus, it has good merits for reducing perceptual color banding artifacts, so it is a good way to compress colors in 8 bits and keep them looking plausible to humans." ContentLicense="CC BY-SA 4.0" />
  <row Id="21687" PostHistoryTypeId="2" PostId="8167" RevisionGUID="7fdc37dd-9662-404a-addf-e6de46faa03a" CreationDate="2018-10-21T04:49:23.513" UserId="9537" Text="If you allow values outside the 0..1 range, then even with sRGB's fairly limited primaries, you can still address the entire human visual gamut. So for storing floating point  light color values it shouldn't matter too much which primaries you use. &#xD;&#xA;However, doing any kind of multiplicative math gets a bit funky though, as the arbitrary coordinates of the primaries act as the scaling 'pivot'.&#xD;&#xA;sRGB primaries are generally used because traditionally your input data is sRGB encoded and out output display is sRGB or rec709... With rec2020, half of that has changed, but for now, most of your input data is still probably sRGB encoded, so using the same primaries as your storage is just the easiest option. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21688" PostHistoryTypeId="2" PostId="8168" RevisionGUID="9e2af254-21aa-4a61-9947-39b7f103542c" CreationDate="2018-10-21T06:14:08.330" UserId="9539" Text="Work groups share resources. The most notable resources they share are barriers and LDS (Local Data Storage aka shared memory in GL lingo, aka Thread Group Shared Memory).&#xD;&#xA;&#xD;&#xA;See [Efficient Compute Shader Programming][1] for an example where LDS/TGSM is used to accelerate a simple gaussian blur.&#xD;&#xA;&#xD;&#xA;It is an interesting thought exercise of how a simple algorithm (weight average N values and output the result) can be rewritten to better leverage the hardware. Basically with a kernel radius of 5, Pixel A will load pixels [A; E] to average them, pixel B loads pixels [A; F] to average, pixel C loads pixels [A; G], and so on until we hit pixel F which will load pixels [B; J] to average them. So the paper asks the question: why do we load pixels A through F from main RAM so many times? (note: GPUs DO have caches, but if multiple threads are requesting all the same regions is likely many of these loads will not go through the cache or have bank conflicts) and instead tries to load A through F ONCE and store it into TGSM memory which is much faster (and can also be accessed directly by the HW). It's basically very similar to manual cache management.&#xD;&#xA;&#xD;&#xA;Also if the workgroup happens to be &lt;= than the GPU's native workgroup size, barriers are much cheaper.&#xD;&#xA;&#xD;&#xA;Note not all GPUs are created equal. For example current Mali's GPU do not have LDS, and shared memory is &quot;emulated&quot; via RAM fetches, thus trying to use LDS like a cache is only going to hurt performance.&#xD;&#xA;&#xD;&#xA;[1]: http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Efficient%20Compute%20Shader%20Programming.pps" ContentLicense="CC BY-SA 4.0" />
  <row Id="21689" PostHistoryTypeId="5" PostId="8168" RevisionGUID="b82921e8-2c10-40ca-aaf4-b562bf6dafa8" CreationDate="2018-10-21T06:19:25.227" UserId="9539" Comment="added 25 characters in body" Text="Work groups share resources. The most notable resources they share are barriers and LDS (Local Data Storage aka shared memory in GL lingo, aka Thread Group Shared Memory).&#xD;&#xA;&#xD;&#xA;See [Efficient Compute Shader Programming][1] for an example where LDS/TGSM is used to accelerate a simple gaussian blur.&#xD;&#xA;&#xD;&#xA;It is an interesting thought exercise of how a simple algorithm (weight average N values and output the result) can be rewritten to better leverage the hardware. Basically with a kernel radius of 5, Pixel A will load pixels [A; E] to average them, pixel B loads pixels [A; F] to average, pixel C loads pixels [A; G], and so on until we hit pixel F which will load pixels [B; J] to average them. So the paper asks the question: why do we load pixels A through F from main RAM so many times? (note: GPUs DO have caches, but if multiple threads are requesting all the same regions is likely many of these loads will miss the cache or have bank conflicts) and instead tries to load A through F ONCE (each thread loads only one pixel) and store it into TGSM memory which is much faster (and can also be accessed directly by the HW). It's basically very similar to manual cache management.&#xD;&#xA;&#xD;&#xA;Also if the workgroup happens to be &lt;= than the GPU's native workgroup size, barriers are much cheaper.&#xD;&#xA;&#xD;&#xA;Note not all GPUs are created equal. For example current Mali's GPU do not have LDS, and shared memory is &quot;emulated&quot; via RAM fetches, thus trying to use LDS like a cache is only going to hurt performance.&#xD;&#xA;&#xD;&#xA;[1]: http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Efficient%20Compute%20Shader%20Programming.pps" ContentLicense="CC BY-SA 4.0" />
  <row Id="21690" PostHistoryTypeId="2" PostId="8169" RevisionGUID="3352248d-d785-4935-8db3-6981d4fc775f" CreationDate="2018-10-21T07:20:53.663" UserId="6046" Text="I won't be discussing the usefulness of workgroups here as you can find it pretty much anywhere. However I am going to touch up on GPU architecture to understand why do we have workgroups in the first place. Most GPUs are designed in such a way that the concept of workgroup is useful. I won't go into details but give a brief overview as to how the mainstream GPUs are designed (AMD/NVIDIA).&#xD;&#xA;&#xD;&#xA;So basically both AMD and NVIDIA have hundreds of thousands of cores inside them. AMD groups these cores into what is called compute unit (CU) While NVIDIA groups them to call them a streaming multiprocessor (SM). Here is a picture from AMD architecture as I am more used to it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;As you can see GPU device consists of CU or SM in NVIDIA's case. These then further contain the actual processing elements. AMD has 64 of them for the GCN architecture.&#xD;&#xA;Now you are gonna say &quot;so what?&quot; Why do we still have workgroups why don't we use these individual &quot;processing elements&quot; or &quot;cores&quot; by themselves and ditch the concept of workgroup.&#xD;&#xA;&#xD;&#xA;Well the thing is, as Matias told above, the compute unit doesn't consist of only these cores, it has much more. The processing elements are just ALUs and they can't do anything on their own. The actual logic that tells them what to do such as the &quot;Branch Unit&quot; the &quot;Instruction Decoding Logic&quot;, &quot;Cache&quot; etc are present inside the Compute Unit. Here is another picture for the Compute Unit of GCN Architecture.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;So as you see this looks more like a miniature CPU processor with the instruction register and other stuff built in. Here comes the concept of workgroup. In programmer's terms a Workgroup equals or you can say gets assigned to a Compute Unit or thread block equals a Streaming Multiprocessor (in NVIDIA's terms). There are subtle differences such as hardware and software threads which leads to wavefronts and warps but I am not going to touch them here.&#xD;&#xA;&#xD;&#xA;So this is somewhat the general architecture how work gets assigned to a GPU. Hence workgroups are necessary. The idea of shared memory and everything Matias said above stems from the underlying GPU architecture.&#xD;&#xA;&#xD;&#xA;So when working with images we usually divide it into smaller 2D blocks called workgroups and hand these blocks to get processed by the underlying Compute Units/SMs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/g3HeG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/AHVfr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21691" PostHistoryTypeId="50" PostId="7943" RevisionGUID="a28c71d9-d3bd-47e3-a2c9-e904f61097cb" CreationDate="2018-10-21T10:00:16.557" UserId="-1" />
  <row Id="21692" PostHistoryTypeId="5" PostId="8157" RevisionGUID="c41a236c-f31a-4519-940d-8fa260c1b89e" CreationDate="2018-10-22T09:36:24.773" UserId="228" Comment="added 937 characters in body" Text="I'm reading through [Polygon Mesh Processing][1], section 4.3 (Surface fairing).&#xD;&#xA;&#xD;&#xA;The reference I mentioned defined defines &quot;Surface Fairing&quot; as&#xD;&#xA;&#xD;&#xA;&gt; The goal of surface fairing is to compute shapes that are as smooth as possible... in general fair surface should follow the principle of simplest shapes, the surfaces should be free by any unnecessary details or oscillation&quot;.&#xD;&#xA;&#xD;&#xA;It continues...&#xD;&#xA;&#xD;&#xA;&gt; This can be modeled by a suitable energy that penalizes unaesthetic behavior of the surface. A minimization of this fairness energy - subject to user defined constraints - eventually yields to the desired shape.&#xD;&#xA;&#xD;&#xA;The energy defined is function of a surface $x : \Omega \to \mathcal{S}$ and the form is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;E_M(x) = \int_{\Omega} \sqrt{det(\bf{I})}dudv&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $\bf{I}$ is the first fundamental form, however instead of this the dirichlet energy&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\tilde{E}_M(x) = \int_{\Omega} \lVert x_u \rVert^2 + \lVert x_v \rVert^2 dudv&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Is the one usually used. Higher order energies are also used, depending on how smooth is the shape we're looking for. Using the Euler-Lagrange equation (in a continuous setting) we end up with the simple PDE&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta x = 0,&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;subject to suitable boundary conditions. Discretazion to meshes is done by means of the Laplace-beltrami operator which I'll define below.&#xD;&#xA;&#xD;&#xA;In general it is my understanding that everything boils down to solve a problem of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta^k x = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $x = x(u,v)$ is our surface. If we descretize to a mesh the equation above might be rewritten as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L^k x = 0&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $L^k$ is the $k^{th}$ power of the Laplacian matrix, and $L$ itself is defined using the Discrete Laplace Beltrami operator, which is something like&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta x = \frac{1}{2A_T} \sum_{j} (cotg (\alpha_{i,j}) + cotg (\beta_{i,j}))(x_j - x_i)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However despite the fact it might be very simple to understand in principle at least I'm trying to figure how this would be implemented.&#xD;&#xA;&#xD;&#xA;This is because to me the angles depends from the mesh vertices and therefore the system isn't actually linear. The other approach I was thinking is to use a gradient flow (diffusion) approach of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{\partial x}{\partial t} = -\Delta^k x&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;the above, in principle can be discretized as follows&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x(t + h) = x(t) - h L^k x(t)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And $L$ might be computed on the current known state of the surface $x(t)$, however the above is an explicit integrator which might lead to instability, and solving the issue would be done by solving&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;(id + h L^k) x(t + h) = x(t)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But in such case there's the problem of $L$ which would depend from the unknown state $x(t+h)$, so the problem I'm having here is actually similar to the first one I exposed...&#xD;&#xA;&#xD;&#xA;So the actual question is:&#xD;&#xA;&#xD;&#xA;If the mesh $x$ is unknown so is the discretization of $\Delta^k$, how is this operator constructed then?&#xD;&#xA;&#xD;&#xA;**Update**&#xD;&#xA;&#xD;&#xA;I believe I've found the [original paper][2], and I quote the bit I find interesting for my question:&#xD;&#xA;&#xD;&#xA;From section 5.4.:&#xD;&#xA;&gt; We can however proceed in exactly the same way, as the changes induced in a time step will be small. We simply compute the non-zero coefficients of the matrix:&#xD;&#xA;$I - \lambda dt K$&#xD;&#xA;where $K$ represents the matrix of the curvature normals...&#xD;&#xA;&#xD;&#xA;So I guess the idea is actually what has been suggested already in one of the comments, we compute the matrix $I - \lambda dt K$ for the current iteration (say $i$) and we keep the very same matrix for a small number of iterations $n$ after such number of iterations we update again the matrix.&#xD;&#xA;&#xD;&#xA;However in the paper the autors confirm that the Laplace-Beltrami operator isn't linear and therefore the system isn't in general linear.&#xD;&#xA;&#xD;&#xA;Could anyone confirm if my understanding is correct?&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books?id=8zX-2VRqBAkC&amp;printsec=frontcover&amp;dq=polygon%20mesh%20processing&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwip4tz8t5DeAhUrL8AKHZHQCcsQ6AEIKTAA#v=onepage&amp;q=polygon%20mesh%20processing&amp;f=false&#xD;&#xA;  [2]: http://multires.caltech.edu/pubs/ImplicitFairing.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="21693" PostHistoryTypeId="2" PostId="8170" RevisionGUID="d37cd683-b2ef-4ea5-8bd4-24b8a1817fab" CreationDate="2018-10-22T11:09:49.407" UserDisplayName="user9436" Text="When creating a VkInstance, you need to setup the API's extensions that are going to be used by your application (for example you need an extension to interface with the window system on desktop platforms).&#xD;&#xA;&#xD;&#xA;What are these extensions? What do they rappresent? Are they just a way to tell Vulkan to use a certain feature implemented by a driver?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21694" PostHistoryTypeId="1" PostId="8170" RevisionGUID="d37cd683-b2ef-4ea5-8bd4-24b8a1817fab" CreationDate="2018-10-22T11:09:49.407" UserDisplayName="user9436" Text="What is a &quot;Vulkan Extension&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21695" PostHistoryTypeId="3" PostId="8170" RevisionGUID="d37cd683-b2ef-4ea5-8bd4-24b8a1817fab" CreationDate="2018-10-22T11:09:49.407" UserDisplayName="user9436" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21696" PostHistoryTypeId="2" PostId="8171" RevisionGUID="ea555a3e-258b-45e8-b2c6-8639db5d22fc" CreationDate="2018-10-22T13:59:13.807" UserId="2654" Text="&gt; Are they just a way to tell Vulkan to use a certain feature implemented by a driver?&#xD;&#xA;&#xD;&#xA;Well... yes. Vulkan extensions are simply additional features that Vulkan implementations *may* provide if they so choose to. They add new functions, structs, and valid enumerators to the API, and they can change some of the behavior of existing functions.&#xD;&#xA;&#xD;&#xA;You have to detect whether the implementation supports these extensions before creating an instance/device. And you have to explicitly ask for such extensions when you create the instance/device." ContentLicense="CC BY-SA 4.0" />
  <row Id="21697" PostHistoryTypeId="5" PostId="8170" RevisionGUID="79c62c22-958f-4221-b26c-cef613aee5b8" CreationDate="2018-10-22T14:01:05.450" UserId="2654" Comment="deleted 1 character in body" Text="When creating a VkInstance, you need to setup the API's extensions that are going to be used by your application (for example you need an extension to interface with the window system on desktop platforms).&#xD;&#xA;&#xD;&#xA;What are these extensions? What do they represent? Are they just a way to tell Vulkan to use a certain feature implemented by a driver?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21698" PostHistoryTypeId="2" PostId="8172" RevisionGUID="f3df9862-a59a-4dcb-a2f8-4e1018c7f4c0" CreationDate="2018-10-22T23:06:56.127" UserId="9551" Text="I have a question that I am stuck on, I am wondering what style is this image considered? And what program do people generally use to create this?&#xD;&#xA;&#xD;&#xA;[![Image in question][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RbTEv.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21699" PostHistoryTypeId="1" PostId="8172" RevisionGUID="f3df9862-a59a-4dcb-a2f8-4e1018c7f4c0" CreationDate="2018-10-22T23:06:56.127" UserId="9551" Text="Confused about graphic art and what software is used to create the environment of it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21700" PostHistoryTypeId="3" PostId="8172" RevisionGUID="f3df9862-a59a-4dcb-a2f8-4e1018c7f4c0" CreationDate="2018-10-22T23:06:56.127" UserId="9551" Text="|vector-graphics|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21701" PostHistoryTypeId="2" PostId="8173" RevisionGUID="60210af5-ae22-4adc-84b1-83b4db96761d" CreationDate="2018-10-23T02:00:34.493" UserId="110" Text="I have seen in some computer graphics software's code bases that sometimes the higher bits of RGB565-format image data are replicated into the lower bits when converting to higher-bit-depth format RGBA8888.  &#xD;&#xA;  &#xD;&#xA;I have found for example the comment by user &quot;eq&quot; in [this gamedev.net thread][1]:&#xD;&#xA;&#xD;&#xA;&gt; I prefer to replicate the higher bits into the undefined lower bits:  &#xD;&#xA;&gt; R8 = (R5 &lt;&lt; 3) | (R5 &gt;&gt; 2);&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;However I do not understand the reason behind.  &#xD;&#xA;  &#xD;&#xA;What use the purpose of replicating those bits into the converted data?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gamedev.net/forums/topic/385638-rgb8888-to-rgb565-pixel-format-conversion/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21702" PostHistoryTypeId="1" PostId="8173" RevisionGUID="60210af5-ae22-4adc-84b1-83b4db96761d" CreationDate="2018-10-23T02:00:34.493" UserId="110" Text="Why replicating the higher bits of RGB565 when converting to RGBA8888?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21703" PostHistoryTypeId="3" PostId="8173" RevisionGUID="60210af5-ae22-4adc-84b1-83b4db96761d" CreationDate="2018-10-23T02:00:34.493" UserId="110" Text="|color-management|conversion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21704" PostHistoryTypeId="2" PostId="8174" RevisionGUID="02cfcc6e-ec1f-4789-a4b1-3ba281bab882" CreationDate="2018-10-23T05:16:01.320" UserId="6407" Text="I'm reading the [chapter 8](http://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter08.html) of the Cg tutorial and I could not understand 8.4.1 :&#xD;&#xA;&#xD;&#xA;&gt; Because all these coordinates lie in the plane of the same triangle, it is possible to derive plane equations for x, y, and z in terms of s and t:&#xD;&#xA;&#xD;&#xA;&gt; A_0 x + B_0 s + C_0 t + D_0 = 0&#xD;&#xA;&#xD;&#xA;&gt; A_1 y + B_1 s + C_1 t + D_1 = 0&#xD;&#xA;&#xD;&#xA;&gt; A_2 z + B_2 s + C_2 t + D_2 = 0&#xD;&#xA;&#xD;&#xA;How are these equations derived? How could we express 3D coords (x, y, z) via 2D (s, t)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21705" PostHistoryTypeId="1" PostId="8174" RevisionGUID="02cfcc6e-ec1f-4789-a4b1-3ba281bab882" CreationDate="2018-10-23T05:16:01.320" UserId="6407" Text="How could express object space coordinates via texture space coordinates in the NVIDIA's CG Tutorial?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21706" PostHistoryTypeId="3" PostId="8174" RevisionGUID="02cfcc6e-ec1f-4789-a4b1-3ba281bab882" CreationDate="2018-10-23T05:16:01.320" UserId="6407" Text="|3d|mathematics|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21707" PostHistoryTypeId="5" PostId="8174" RevisionGUID="4ab9a1e8-34b0-48e1-b0cc-b0cbcf6c633f" CreationDate="2018-10-23T05:33:44.740" UserId="6407" Comment="correct title" Text="I'm reading the [chapter 8](http://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter08.html) of the Cg tutorial and I could not understand 8.4.1 :&#xD;&#xA;&#xD;&#xA;&gt; Because all these coordinates lie in the plane of the same triangle, it is possible to derive plane equations for x, y, and z in terms of s and t:&#xD;&#xA;&#xD;&#xA;&gt; A_0 x + B_0 s + C_0 t + D_0 = 0&#xD;&#xA;&#xD;&#xA;&gt; A_1 y + B_1 s + C_1 t + D_1 = 0&#xD;&#xA;&#xD;&#xA;&gt; A_2 z + B_2 s + C_2 t + D_2 = 0&#xD;&#xA;&#xD;&#xA;How are these equations derived? " ContentLicense="CC BY-SA 4.0" />
  <row Id="21708" PostHistoryTypeId="4" PostId="8174" RevisionGUID="4ab9a1e8-34b0-48e1-b0cc-b0cbcf6c633f" CreationDate="2018-10-23T05:33:44.740" UserId="6407" Comment="correct title" Text="How are the three plane equations derived in the NVIDIA's CG Tutorial chapter 8?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21709" PostHistoryTypeId="2" PostId="8175" RevisionGUID="72b1e586-1002-482a-8403-840e91e2ca51" CreationDate="2018-10-23T08:46:51.917" UserId="9553" Text="I have somewhat generalized version of this question: https://stackoverflow.com/questions/52475104/how-to-show-visible-part-of-planar-world-rendered-with-3d-perspective-on-topside -‎ I would also like to know which part(s) of a given plane (not necessarily infinite) is visible to the camera, but I would like the solution to also consider objects in front of the plane that may be obstructing it's visibility.&#xD;&#xA;&#xD;&#xA;Since that may be very hard problem to solve analyticaly (if at all in OpenGL) I would be happy also with solution based on &quot;rasterisation&quot;. The problem would then be restated as: How to map rendered pixels of a plane back to it's 3D representation. Or in other (maybe too naive) words - how to transform rendered visible area of a plane to it's texture.&#xD;&#xA;&#xD;&#xA;I'm a beginner in computer graphics so I would be glad even for pointing out the right study materials." ContentLicense="CC BY-SA 4.0" />
  <row Id="21710" PostHistoryTypeId="1" PostId="8175" RevisionGUID="72b1e586-1002-482a-8403-840e91e2ca51" CreationDate="2018-10-23T08:46:51.917" UserId="9553" Text="Identification of visible area of a plane in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="21711" PostHistoryTypeId="3" PostId="8175" RevisionGUID="72b1e586-1002-482a-8403-840e91e2ca51" CreationDate="2018-10-23T08:46:51.917" UserId="9553" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21712" PostHistoryTypeId="2" PostId="8176" RevisionGUID="91d6202a-d59c-40c6-82cf-239c5051ef11" CreationDate="2018-10-23T10:55:57.840" UserId="4908" Text="This would be considered [**isometric**][1]. Isometric graphics were originally used to give a 3D look, when computers could not handle actual 3D graphics.&#xD;&#xA;&#xD;&#xA;The creation of this image, however, is different than described in the Wikipedia article. The creator started by making the scene in 3D. This means, doing normal three dimensional modeling. After the scene is modeled and shaded, the creator simply created an orthographic camera. The orthographic camera is probably rotated to a yaw of 45° and a pitch of 45° downwards, although I am not sure about that.&#xD;&#xA;&#xD;&#xA;That is quite simply it. The scene is a normal 3D scene, but the difference is that the creator used an orthographic camera, placed in such a way that you get an isometric-looking image.&#xD;&#xA;&#xD;&#xA;So, when it comes to what program people use, simply any somewhat feature rich modeling software (Blender, 3Ds Max, Autodesk Maya (LT version is generally for games), Cinema 4D). Most 3D game engines also support orthographic cameras and can thus also be used.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Isometric_video_game_graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="21713" PostHistoryTypeId="2" PostId="8177" RevisionGUID="9c28cd73-b34c-4a46-8630-0b9edd795ef6" CreationDate="2018-10-23T11:06:55.367" UserDisplayName="user9485" Text="In this context, deriving the plane equations does not refer to the equations themselves, but to the coefficients $A$, $B$, $C$ and $D$.&#xD;&#xA;&#xD;&#xA;The equations are simply plane equations for a plane defined by three points, where the first plane is defined by the three points $(x,s,t)$, the second plane is defined by $(y,s,t)$ and the third plane by $(z,s,t)$. They can be seen as auxiliary objects in deriving equations for $x$, $y$ and $z$ in terms of $s$ and $t$.&#xD;&#xA;&#xD;&#xA;Side note: In general it is *not* possible to derive plane equations as it is done here, even if the triangle is non-degenerate in $(s,t)$-space and in $(x,y,z)$-space. Just because the points $x,y,z$ are non-collinear and $s,t$ are non-collinear does not mean that for example the three points $x,s,t$ are non-collinear." ContentLicense="CC BY-SA 4.0" />
  <row Id="21714" PostHistoryTypeId="5" PostId="8177" RevisionGUID="b96aa1f8-6d4d-4215-bb4b-d291362793d3" CreationDate="2018-10-23T12:01:35.050" UserDisplayName="user9485" Comment="deleted 325 characters in body; added 45 characters in body" Text="In this context, deriving the plane equations does not refer to the equations themselves, but to the coefficients $A$, $B$, $C$ and $D$.&#xD;&#xA;&#xD;&#xA;The equations are simply plane equations for a plane defined by three points, where the first plane is defined by the three points $(x_i,s_i,t_i)_{i=1..3}$, the second plane is defined by $(y_i,s_i,t_i)_{i=1..3}$ and the third plane by $(z_i,s_i,t_i)_{i=1..3}$. They can be seen as auxiliary objects in deriving equations for $x$, $y$ and $z$ in terms of $s$ and $t$." ContentLicense="CC BY-SA 4.0" />
  <row Id="21715" PostHistoryTypeId="2" PostId="8178" RevisionGUID="2fcd1c9f-2353-438d-b55a-eaf1c2bb34d3" CreationDate="2018-10-23T13:08:33.107" UserId="9557" Text="It seems that every image format (jpeg, png, tiff, bmp, jp2000...) doesn't place there origin at the same angle.&#xD;&#xA;&#xD;&#xA;Do you know where I could find some info about this differences?&#xD;&#xA;&#xD;&#xA;I can only say that PNG and JPEG are different." ContentLicense="CC BY-SA 4.0" />
  <row Id="21716" PostHistoryTypeId="1" PostId="8178" RevisionGUID="2fcd1c9f-2353-438d-b55a-eaf1c2bb34d3" CreationDate="2018-10-23T13:08:33.107" UserId="9557" Text="Corner of origin in different image formats" ContentLicense="CC BY-SA 4.0" />
  <row Id="21717" PostHistoryTypeId="3" PostId="8178" RevisionGUID="2fcd1c9f-2353-438d-b55a-eaf1c2bb34d3" CreationDate="2018-10-23T13:08:33.107" UserId="9557" Text="|2d|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21718" PostHistoryTypeId="2" PostId="8179" RevisionGUID="1a43967a-e962-4561-85f4-d3fdf540019b" CreationDate="2018-10-23T13:27:41.900" UserId="209" Text="Note that the n-bit string, $N$, actually represents the value $\frac{N}{2^n-1}$ and we want to produce the m-bit string, $M$, where $n&lt;m$ and&#xD;&#xA;$$\frac{N}{2^n-1}\approx\frac{M}{2^m-1}$$&#xD;&#xA;&#xD;&#xA;We scale numerator and denominator with&#xD;&#xA;$$\frac{N.(2^n+1)}{(2^n-1)(2^n+1)}\approx \frac{M}{2^m-1}$$&#xD;&#xA;and this simplifies to &#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n}-1}\approx \frac{M}{2^m-1}$$&#xD;&#xA;&#xD;&#xA;In your case, you have n and m are 5 and 8 respectively and we can &quot;stop&quot; here. (but the process can be repeated if m &gt;&gt; n)&#xD;&#xA;&#xD;&#xA;We next make the approximation:&#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n}}\approx \frac{M}{2^m}$$ which simplifies to &#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n-m}}\approx M $$&#xD;&#xA;&#xD;&#xA;Note that $N.(2^n+1)$ is equivalent to repeating the n-bit string, to create a 2n-bit string, and the division, shifts off the $2n-m$ LBS to leave an M bit result. &#xD;&#xA;&#xD;&#xA;QED&#xD;&#xA;&#xD;&#xA;Of course, the  'correct' calculation is $\lfloor(\frac{(2^M-1) N}{2^n-1}+\frac{1}{2}\rfloor$ but this approximation, in general, works *most* of the time. Of course there are times when it's inaccurate, but IIRC only by one bit and relatively infrequently.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21719" PostHistoryTypeId="5" PostId="8179" RevisionGUID="d06f0cdd-defa-4a3a-b48b-7d10efed9da7" CreationDate="2018-10-23T13:36:44.527" UserId="209" Comment="Fixed last expression" Text="There's actually a reasonably good mathematical reason for doing bit replication:&#xD;&#xA;&#xD;&#xA;First note that the n-bit string, $N$, actually represents the value $\frac{N}{2^n-1}$ and we want to produce the m-bit string, $M$, where $n&lt;m$ and&#xD;&#xA;$$\frac{N}{2^n-1}\approx\frac{M}{2^m-1}$$&#xD;&#xA;&#xD;&#xA;We first scale numerator and denominator with&#xD;&#xA;$$\frac{N.(2^n+1)}{(2^n-1)(2^n+1)}\approx \frac{M}{2^m-1}$$&#xD;&#xA;and this simplifies to &#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n}-1}\approx \frac{M}{2^m-1}$$&#xD;&#xA;&#xD;&#xA;In your case, $n$ and $m$ are 5 and 8 respectively and we can &quot;stop&quot; here (but the process can be repeated, ad nauseum, if m &gt;&gt; n).&#xD;&#xA;&#xD;&#xA;We next make the approximation:&#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n}}\approx \frac{M}{2^m}$$ which simplifies to &#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n-m}}\approx M $$&#xD;&#xA;&#xD;&#xA;Note that $N.(2^n+1)$ is equivalent to repeating the n-bit string, to create a 2n-bit string, and the division, shifts off the $2n-m$ LBS to leave an M bit result. &#xD;&#xA;&#xD;&#xA;QED&#xD;&#xA;&#xD;&#xA;Of course, the  'correct' calculation is $M=\lfloor(\frac{(2^m-1) N}{2^n-1}+\frac{1}{2}\rfloor$ but this approximation, in general, works *most* of the time. Of course there are times when it's inaccurate, but IIRC only by one bit and relatively infrequently.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21720" PostHistoryTypeId="33" PostId="8164" RevisionGUID="dfb74615-4a33-4d4f-8c91-cfc35779d940" CreationDate="2018-10-23T14:03:14.950" UserId="2173" Comment="51" />
  <row Id="21722" PostHistoryTypeId="2" PostId="8181" RevisionGUID="19fb6ef3-5058-4a44-b5b0-9f8fd76d7220" CreationDate="2018-10-23T19:34:27.590" UserId="9561" Text="Here is a line by line breakdown of my shader:&#xD;&#xA;&#xD;&#xA;    #define mainImage(o,p)\&#xD;&#xA;        for( vec2 r = iResolution.xy, q = 2.*(p+p-r)/r.y; o.a++ &lt; 30.; )\&#xD;&#xA;            o += length( q = abs(q)/dot(q,q) - iMouse.xy/r) / 2e2&#xD;&#xA;&#xD;&#xA;First, it is important to know that the “\” at the end of the first two lines do not count towards the character count and merely serve to make the code more readable by splitting it onto multiple lines.&#xD;&#xA;&#xD;&#xA;    #define mainImage(o,p)&#xD;&#xA;Begins the definition of the function which would normally be written&#xD;&#xA;void mainImage(out fragColor, in fragCoord){...}&#xD;&#xA;This saves a few characters.&#xD;&#xA;&#xD;&#xA;The first part of the loop:&#xD;&#xA;&#xD;&#xA;    vec2 r = iResolution.xy, q = 2.*(p+p-r)/r.y;&#xD;&#xA;&#xD;&#xA;Establishes two variables of type Vector2:&#xD;&#xA;&#xD;&#xA;r is the resolution which allows me to refer to iResolution several times later in fewer characters.&#xD;&#xA;&#xD;&#xA;q is the coordinate in the fractal which is calculated from the fragCoord p and is then iterated in each loop.&#xD;&#xA;&#xD;&#xA;Instead of fragCoord starting at (0,0) in the bottom left corner and extending to the (r.x,r.y) in the top right, (p+p-r) transforms each fragCoord so that the center of the screen is (0,0). This doubles the fragCoord value and then subtracts the resolution of the window.&#xD;&#xA;The division by r.y fits the coordinates such that the top has a y value of 1 and the bottom has a y value of -1. With this, the x is scaled accordingly without stretching.&#xD;&#xA;Finally, the multiplication by 2 just zooms out by a factor of 2.&#xD;&#xA;&#xD;&#xA;Then for the iterator, I use o.a (the alpha channel of o).&#xD;&#xA;o is the output color which is a vec4. As defined by Shadertoy, o begins with the value vec4(0,0,0,1). I use this so that I do not need to use characters declaring a new float as an iterator. o.a++&lt;30 combines the test expression and the iterator in the for loop.&#xD;&#xA;&#xD;&#xA;The content of the loop is one line where a number gets added to each channel of the output color. This line:&#xD;&#xA;&#xD;&#xA;    o += length( q = abs(q)/dot(q,q) - iMouse.xy/r) / 2e2&#xD;&#xA;&#xD;&#xA;Can be broken down into a few parts.&#xD;&#xA;Each iteration of the coordinates in the fractal occurs here:&#xD;&#xA;&#xD;&#xA;    q = abs(q)/dot(q,q) - iMouse.xy/r&#xD;&#xA;&#xD;&#xA;Where iMouse.xy/r is a way to transform mouse coordinates from pixel to the range (0,0) to (1,1)&#xD;&#xA;&#xD;&#xA;Each iteration of this function changes the value of q to be used.&#xD;&#xA;&#xD;&#xA;What produces this fractal is the idea that some initial values for q will escape to infinity and others will converge or cycle around a few small values. Each iteration I increase the lightness of the pixel based how far q is from (0,0). This length of q is then divided by the constant 2e2 (200) which is to prevent o.rgb from increasing too rapidly.&#xD;&#xA;&#xD;&#xA;The contents of the loop could be understood as two steps:&#xD;&#xA;&#xD;&#xA;    q = abs(q)/dot(q,q) - iMouse.xy/r;&#xD;&#xA;    o += length(q) / 2e2;&#xD;&#xA;&#xD;&#xA;In the end, even if o contains a value in one of its channels that is greater than 1, it gets clamped by Shadertoy automatically, and a trailing semi-colon is not needed on the last line." ContentLicense="CC BY-SA 4.0" />
  <row Id="21724" PostHistoryTypeId="5" PostId="8179" RevisionGUID="e4821f9c-6321-4d31-81e4-6d665d543052" CreationDate="2018-10-24T08:16:38.870" UserId="209" Comment="Corrected a few typos" Text="There's actually a reasonably good mathematical reason for doing bit replication:&#xD;&#xA;&#xD;&#xA;First note that the n-bit string, $N$, actually represents the value $\frac{N}{2^n-1}$ and we want to produce the m-bit string, $M$, where $n&lt;m$ and&#xD;&#xA;$$\frac{N}{2^n-1}\approx\frac{M}{2^m-1}$$&#xD;&#xA;&#xD;&#xA;We first scale numerator and denominator with&#xD;&#xA;$$\frac{N.(2^n+1)}{(2^n-1)(2^n+1)}\approx \frac{M}{2^m-1}$$&#xD;&#xA;and this simplifies to &#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n}-1}\approx \frac{M}{2^m-1}$$&#xD;&#xA;&#xD;&#xA;In your case, $n\in \{5,6\}$ and $m=8$ and we can &quot;stop&quot; here, but but the process can be repeated, (ad nauseum), if m &gt;&gt; n.&#xD;&#xA;&#xD;&#xA;We next make the approximation...&#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n}}\approx \frac{M}{2^m}$$ which simplifies to &#xD;&#xA;$$\frac{N.(2^n+1)}{2^{2n-m}}\approx M $$&#xD;&#xA;&#xD;&#xA;Note that $N.(2^n+1)$ is equivalent to repeating the n-bit string, to create a 2n-bit string, and the division shifts off the $2n-m$ LSBs to leave an M bit result. &#xD;&#xA;&#xD;&#xA;QED&#xD;&#xA;&#xD;&#xA;Of course, the  'correct' calculation is $M=\lfloor(\frac{(2^m-1) N}{2^n-1}+\frac{1}{2}\rfloor$ but this approximation, in general, works *most* of the time. Of course there are times when it's inaccurate, but IIRC only by one bit and relatively infrequently.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21725" PostHistoryTypeId="5" PostId="8178" RevisionGUID="e1f9d245-d5b6-40d6-a12e-4a75c739194a" CreationDate="2018-10-24T10:22:15.450" UserId="9557" Comment="added 1 character in body; edited title" Text="It seems that every image format (jpeg, png, tiff, bmp, jp2000...) doesn't place their origin at the same corner.&#xD;&#xA;&#xD;&#xA;Do you know where I could find some info about this differences?&#xD;&#xA;&#xD;&#xA;I can only say that PNG and JPEG are different." ContentLicense="CC BY-SA 4.0" />
  <row Id="21726" PostHistoryTypeId="4" PostId="8178" RevisionGUID="e1f9d245-d5b6-40d6-a12e-4a75c739194a" CreationDate="2018-10-24T10:22:15.450" UserId="9557" Comment="added 1 character in body; edited title" Text="Why is pixel 0,0 at the top left of some formats and bottom left of others?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21730" PostHistoryTypeId="2" PostId="8183" RevisionGUID="003cd8e7-356b-404a-8b0a-b8d6d5585dc7" CreationDate="2018-10-24T14:50:19.370" UserId="9566" Text="I can't say for certain, but I was interested in this myself and trying to look it up (with little success). I did analyze the many macro photos you can find on the web of these kinds of displays, though.&#xD;&#xA;&#xD;&#xA;    RGB pixels      Pentile Subpixels (RGBG Layout)&#xD;&#xA;&#xD;&#xA;    --+---+--           --+---+--&#xD;&#xA;    X | X | X           G r G b G&#xD;&#xA;    --+---+--   --&gt;     --+---+--&#xD;&#xA;    X | X | X           G b G r G&#xD;&#xA;    --+---+--           --+---+--&#xD;&#xA;&#xD;&#xA;As far as I can tell, it looks like the green subpixels' locations exactly match the framebuffer pixel locations (X) and the intensity is transferred 1:1. The red and blue subpixels are shared between the *two* neighbouring pixels *horizontally* and their intensity seems to be the average of the red/blue channels of the two neighbouring framebuffer pixels left and right, effectively halving the horizontal resolution of R and B.&#xD;&#xA;&#xD;&#xA;This strategy seems to carry over to the diamond Pentile layout even though the the red and blue subpixels are shifted downwards by half a pixel:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RGB Pixels       Diamond Pentile subpixels&#xD;&#xA;                             _________&#xD;&#xA;    X   X   X                G | G | G&#xD;&#xA;                  --&gt;        __r___b__ &#xD;&#xA;    X   X   X                G | G | G&#xD;&#xA;                             __b___r__&#xD;&#xA;&#xD;&#xA;Due to the additional half pixel vertical shift for red and blue of this layout that isn't accounted for in driving the red and blue subpixels, you might be able to notice that a horizonal edge between black on the top and white at the bottom appears greenish while the reverse--white on top and black at the bottom--appears in a magenta tone. You can see this effect in macro photos of diamond Pentile subpixel matrices rendering text.&#xD;&#xA;&#xD;&#xA;So, yes, you can easily control all subpixels of a Pentile display. Each color channel value in your frame buffer is used exactly once and for only one pixel. It's just that for the red and blue subpixels two frame buffer pixels' red and blue values are averaged.&#xD;&#xA;&#xD;&#xA;Knowing this, you could try to do a more sophisticated subpixel rendering. But keep in mind that your typical color space like sRGB is nonlinear. The filtering should be done in a linear domain. For example, a checker board of alternating 0 and 255 will have the same brightness as a flat area with value around 185 (if I remember correctly) instead of 128.&#xD;&#xA;&#xD;&#xA;And finally, I want to point out that it's possible to come up with anti-alias filters for non-rectangular sampling lattices. For example, for this checkerboard sampling lattice you have for the red and blue subpixels, the ideal lowpass filter would have a pass band in form of a diamond shape in the spectral domain. If you tried to reduce the resolution by dropping every 2nd sample in a checkerboard fashion, reasonable anti-alias filters would be these 5x5 and 3x3 kernels while the 5x5 version retains more detail:&#xD;&#xA;&#xD;&#xA;     0   -1    0   -1    0&#xD;&#xA;    -1    0   10    0   -1              0  1  0&#xD;&#xA;     0   10   32   10    0              1  4  1&#xD;&#xA;    -1    0   10    0   -1              0  1  0&#xD;&#xA;     0   -1    0   -1    0&#xD;&#xA;&#xD;&#xA;These can be applied in-place due to the zeros' locations.&#xD;&#xA;&#xD;&#xA;You might also want to include a half-pixel shift for one or two dimensions in there to account for the relative positioning of the red blue and green subpixels. For example, for the diamond pentile layout you might want to use one of these filters:&#xD;&#xA;&#xD;&#xA;      3    0    0    0    0    3&#xD;&#xA;      0  -25    0    0  -25    0          -1   0   0  -1&#xD;&#xA;      0    0  150  150    0    0           0   9   9   0&#xD;&#xA;      0    0  150  150    0    0           0   9   9   0&#xD;&#xA;      0  -25    0    0  -25    0          -1   0   0  -1&#xD;&#xA;      3    0    0    0    0    3&#xD;&#xA;&#xD;&#xA;to come up with the right red/blue subpixels instead of just averaging four values.&#xD;&#xA;&#xD;&#xA;The RGBG (non-diamond) Pentile pattern would require only a half-pixel shift horizontally, leading to a filter like this:&#xD;&#xA;&#xD;&#xA;     -3   3   3  -3&#xD;&#xA;      2  30  30   2&#xD;&#xA;     -3   3   3  -3&#xD;&#xA;&#xD;&#xA;Some care must be taken with clipping due to the negative filter coefficients. For example, you could try to redistribute the residual to surrounding pixels to keep the average brightness." ContentLicense="CC BY-SA 4.0" />
  <row Id="21734" PostHistoryTypeId="2" PostId="8185" RevisionGUID="3aef4d84-f66d-4132-8333-da88431c262e" CreationDate="2018-10-24T18:04:55.973" UserId="9567" Text="I keep coming across the terms 'Metal' and 'Vulcan' on this site.&#xD;&#xA;Guessing this to be some CG software, I'm interested to know what these are exactly and what the intended and most common usage is.&#xD;&#xA;&#xD;&#xA;A quick search shows me a video about why metal in cg looks fake: https://www.youtube.com/watch?v=NjbLYFXrfFU&#xD;&#xA;&#xD;&#xA;Obviously not the answer, most answers talk about compute kernels. I'm familiar with kernal inversion in machine learning but not like android kernels and the such. Hope you can help me out. Your input would be most valuable." ContentLicense="CC BY-SA 4.0" />
  <row Id="21735" PostHistoryTypeId="1" PostId="8185" RevisionGUID="3aef4d84-f66d-4132-8333-da88431c262e" CreationDate="2018-10-24T18:04:55.973" UserId="9567" Text="What are Metal and Vulcan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21736" PostHistoryTypeId="3" PostId="8185" RevisionGUID="3aef4d84-f66d-4132-8333-da88431c262e" CreationDate="2018-10-24T18:04:55.973" UserId="9567" Text="|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21737" PostHistoryTypeId="6" PostId="8185" RevisionGUID="7cf6c5a6-a882-493f-9232-c9ad1179c4fc" CreationDate="2018-10-24T18:48:21.640" UserId="2654" Comment="edited tags" Text="|vulkan|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21738" PostHistoryTypeId="2" PostId="8186" RevisionGUID="a9e05385-a4ec-4e80-9665-f40c1edca956" CreationDate="2018-10-24T18:54:13.723" UserId="2654" Text="Metal and Vulkan are low-level 3D graphics APIs, in much the same way that OpenGL and Direct3D are 3D graphics APIs. Metal is Apple's API, usable on iOS and MacOS. Vulkan was developed by the Khronos Group, who also oversees the various forms of OpenGL. Vulkan is directly usable on all non-Apple platforms, and there is the MoltenVK project which provides a translation layer from Vulkan to Metal (since the APIs are not *that* different), thus allowing Vulkan applications to run even on Apple platforms.&#xD;&#xA;&#xD;&#xA;Metal, Vulkan, and Direct3D v12 represent a dramatic departure API-wise from prior low-level graphics APIs. They use a command-buffer-based interface, where you record rendering commands into a command buffer object, then execute those commands at some later period. The more immediate style of APIs like OpenGL and D3D-pre-12 have no intermediary command buffer. When you call a rendering function, it is given to the GPU &quot;right then&quot; and that's the end of it.&#xD;&#xA;&#xD;&#xA;These styles of API are important because they allow threaded creation of rendering commands. In the immediate APIs, you can only effectively have one thread issuing rendering commands. In command-buffer APIs, multiple threads can build multiple CBs simultaneously, and then one thread submits them all as a single bunch of work. This allows better utilization of CPU resources for CPUs with lots of cores." ContentLicense="CC BY-SA 4.0" />
  <row Id="21740" PostHistoryTypeId="10" PostId="8172" RevisionGUID="fb441512-7678-485f-bff6-16344f03d30a" CreationDate="2018-10-24T21:26:12.327" UserId="231" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="21744" PostHistoryTypeId="2" PostId="8187" RevisionGUID="e67979fb-45f6-4135-a07d-4ce73274a884" CreationDate="2018-10-25T02:03:36.403" UserId="3073" Text="Without replicating the bits the LSBs will be 0, so for the maximum value of 0x1f (max for 5 bits) it would expand to 0xf8 when converted to 8 bit. What you want is 0xff so the range of 0x00-&gt;0x1f will be mapped to 0x00-&gt;0xff instead of 0x00-&gt;0xf8. Without merging the LSB you would not be able to convert 0x1f,0x1f,0x1f to white (0xff,0xff,0xff).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Example: &#xD;&#xA;    &#xD;&#xA;    left shift only (&lt;&lt; 3)&#xD;&#xA;    %00000001 -&gt; %00001000     (0x01 -&gt; 0x08)&#xD;&#xA;    %00010000 -&gt; %10000000     (0x10 -&gt; 0x80)&#xD;&#xA;    %00011111 -&gt; %11111000     (0x1f -&gt; 0xf8)&#xD;&#xA;    &#xD;&#xA;    merging MSB to LSB &#xD;&#xA;    %00000001 -&gt; %00001000     (0x01 -&gt; 0x08)&#xD;&#xA;    %00010000 -&gt; %10000100     (0x10 -&gt; 0x84)&#xD;&#xA;    $00011111 -&gt; %11111111     (0x1f -&gt; 0xff)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21745" PostHistoryTypeId="5" PostId="8187" RevisionGUID="6068d883-f867-43d5-99d7-317f4a597372" CreationDate="2018-10-25T02:11:08.100" UserId="3073" Comment="edited body" Text="Without replicating the bits the LSBs will be 0, so for the maximum value of 0x1f (max for 5 bits) it would expand to 0xf8 when converted to 8 bit. What you want is 0xff so the range of 0x00-&gt;0x1f will be mapped to 0x00-&gt;0xff instead of 0x00-&gt;0xf8. Without merging the LSB you would not be able to convert 0x1f,0x1f,0x1f to white (0xff,0xff,0xff).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Example: &#xD;&#xA;    &#xD;&#xA;    left shift only (&lt;&lt; 3)&#xD;&#xA;    %---00001 -&gt; %00001000     (0x01 -&gt; 0x08)&#xD;&#xA;    %---10000 -&gt; %10000000     (0x10 -&gt; 0x80)&#xD;&#xA;    %---11111 -&gt; %11111000     (0x1f -&gt; 0xf8)&#xD;&#xA;    &#xD;&#xA;    merging MSB to LSB &#xD;&#xA;    %---00001 -&gt; %00001000     (0x01 -&gt; 0x08)&#xD;&#xA;    %---10000 -&gt; %10000100     (0x10 -&gt; 0x84)&#xD;&#xA;    $---11111 -&gt; %11111111     (0x1f -&gt; 0xff)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21746" PostHistoryTypeId="34" PostId="8164" RevisionGUID="484f762f-c5ab-44a4-b16b-1a0e7821eaee" CreationDate="2018-10-25T07:06:02.527" UserId="2173" Comment="51" />
  <row Id="21747" PostHistoryTypeId="5" PostId="8183" RevisionGUID="703c564f-5ae6-40c6-9541-7a43d8179b8a" CreationDate="2018-10-25T09:25:50.903" UserId="9566" Comment="added comment about different diamond pentipe behaviors w.r.t. direction of half-pixel shift of red and blue" Text="I can't say for certain, but I was interested in this myself and trying to look it up (with little success). I did analyze the many macro photos you can find on the web of these kinds of displays, though.&#xD;&#xA;&#xD;&#xA;    RGB pixels      Pentile Subpixels (RGBG Layout)&#xD;&#xA;&#xD;&#xA;    --+---+--           --+---+--&#xD;&#xA;    X | X | X           G r G b G&#xD;&#xA;    --+---+--   --&gt;     --+---+--&#xD;&#xA;    X | X | X           G b G r G&#xD;&#xA;    --+---+--           --+---+--&#xD;&#xA;&#xD;&#xA;As far as I can tell, it looks like the green subpixels' locations exactly match the framebuffer pixel locations (X) and the intensity is transferred 1:1. The red and blue subpixels are shared between the *two* neighbouring pixels *horizontally* and their intensity seems to be the average of the red/blue channels of the two neighbouring framebuffer pixels left and right, effectively halving the horizontal resolution of R and B.&#xD;&#xA;&#xD;&#xA;This strategy seems to carry over to the diamond Pentile layout even though the the red and blue subpixels are shifted downwards (or upwards) by half a pixel:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RGB Pixels       Diamond Pentile subpixels&#xD;&#xA;                             _________&#xD;&#xA;    X   X   X                G | G | G&#xD;&#xA;                  --&gt;        __r___b__ &#xD;&#xA;    X   X   X                G | G | G&#xD;&#xA;                             __b___r__&#xD;&#xA;&#xD;&#xA;Due to the additional half pixel vertical shift for red and blue of this layout that isn't accounted for in driving the red and blue subpixels, you might be able to notice that a horizonal edge between a black area and a white area might appear green or magenta. You can see this effect in macro photos of diamond Pentile subpixel matrices rendering text. But there is actually no consistent shift. In some photos it's downwards and in others it's upwards.  I don't know if the displays were manufactured differently or just installed upside-down in some devices.&#xD;&#xA;&#xD;&#xA;So, yes, you can easily control all subpixels of a Pentile display. Each color channel value in your frame buffer is used exactly once and for only one pixel. It's just that for the red and blue subpixels two frame buffer pixels' red and blue values are averaged.&#xD;&#xA;&#xD;&#xA;Knowing this, you could try to do a more sophisticated subpixel rendering. But keep in mind that your typical color space like sRGB is nonlinear. The filtering should be done in a linear domain. For example, a checker board of alternating 0 and 255 will have the same brightness as a flat area with value around 185 (if I remember correctly) instead of 128.&#xD;&#xA;&#xD;&#xA;And finally, I want to point out that it's possible to come up with anti-alias filters for non-rectangular sampling lattices. For example, for this checkerboard sampling lattice you have for the red and blue subpixels, the ideal lowpass filter would have a pass band in form of a diamond shape in the spectral domain. If you tried to reduce the resolution by dropping every 2nd sample in a checkerboard fashion, reasonable anti-alias filters would be these 5x5 and 3x3 kernels while the 5x5 version retains more detail:&#xD;&#xA;&#xD;&#xA;     0   -1    0   -1    0&#xD;&#xA;    -1    0   10    0   -1              0  1  0&#xD;&#xA;     0   10   32   10    0              1  4  1&#xD;&#xA;    -1    0   10    0   -1              0  1  0&#xD;&#xA;     0   -1    0   -1    0&#xD;&#xA;&#xD;&#xA;These can be applied in-place due to the zeros' locations.&#xD;&#xA;&#xD;&#xA;You might also want to include a half-pixel shift for one or two dimensions in there to account for the relative positioning of the red blue and green subpixels. For example, for the diamond pentile layout you might want to use one of these filters:&#xD;&#xA;&#xD;&#xA;      3    0    0    0    0    3&#xD;&#xA;      0  -25    0    0  -25    0          -1   0   0  -1&#xD;&#xA;      0    0  150  150    0    0           0   9   9   0&#xD;&#xA;      0    0  150  150    0    0           0   9   9   0&#xD;&#xA;      0  -25    0    0  -25    0          -1   0   0  -1&#xD;&#xA;      3    0    0    0    0    3&#xD;&#xA;&#xD;&#xA;to come up with the right red/blue subpixels instead of just averaging four values.&#xD;&#xA;&#xD;&#xA;The RGBG (non-diamond) Pentile pattern would require only a half-pixel shift horizontally, leading to a filter like this:&#xD;&#xA;&#xD;&#xA;     -3   3   3  -3&#xD;&#xA;      2  30  30   2&#xD;&#xA;     -3   3   3  -3&#xD;&#xA;&#xD;&#xA;Some care must be taken with clipping due to the negative filter coefficients. For example, you could try to redistribute the residual to surrounding pixels to keep the average brightness." ContentLicense="CC BY-SA 4.0" />
  <row Id="21748" PostHistoryTypeId="5" PostId="8187" RevisionGUID="fb6659b2-d108-466c-8160-d004f8e525e0" CreationDate="2018-10-25T09:33:36.313" UserId="3073" Comment="added 50 characters in body" Text="Without replicating the bits the LSBs will be 0, so for the maximum value of 0x1f (max for 5 bits) it would expand to 0xf8 when converted to 8 bit. What you want is 0xff so the range of 0x00-&gt;0x1f will be mapped to 0x00-&gt;0xff instead of 0x00-&gt;0xf8. Without merging the LSB you would not be able to convert 0x1f,0x1f,0x1f to white (0xff,0xff,0xff). Incidentally this is the same as N*0xff/0x1f.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Example: &#xD;&#xA;    &#xD;&#xA;    left shift only (&lt;&lt; 3)&#xD;&#xA;    %---00001 -&gt; %00001000     (0x01 -&gt; 0x08)&#xD;&#xA;    %---10000 -&gt; %10000000     (0x10 -&gt; 0x80)&#xD;&#xA;    %---11111 -&gt; %11111000     (0x1f -&gt; 0xf8)&#xD;&#xA;    &#xD;&#xA;    merging MSB to LSB &#xD;&#xA;    %---00001 -&gt; %00001000     (0x01 -&gt; 0x08)&#xD;&#xA;    %---10000 -&gt; %10000100     (0x10 -&gt; 0x84)&#xD;&#xA;    $---11111 -&gt; %11111111     (0x1f -&gt; 0xff)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21749" PostHistoryTypeId="2" PostId="8188" RevisionGUID="a4407479-516d-4823-a391-4fc62ebfc4a0" CreationDate="2018-10-25T18:02:18.193" UserId="2041" Text="It comes down to history. The original interfaces for drawing stuff on the screen were for text, not images. Since the people who designed those early computers spoke languages that are read left-to-right, top-to-bottom, it made sense for the first glyph to be the top-left one. This also works conveniently with how the image was transmitted to the display. TV signals also start in the top-left, so those CRT displays also started displaying a frame with the top-left pixel. When computers added &quot;graphics modes&quot; to their &quot;text modes&quot;, it made sense for the origin to stay in the same place. &#xD;&#xA;&#xD;&#xA;This all changed with packages specifically designed for mathematical and scientific computing. Charts are usually drawn with (0,0) at the bottom-left, so scientists wanted their co-ordinate system to work that way.&#xD;&#xA;&#xD;&#xA;This is why we have two common options. Generally for an image format, it depends on the use-case the format was originally designed to satisfy, and what kind of people worked on it. Image formats are usually designed by engineers with experience of low-level graphics implementation, so top-down is more popular, but some formats support both for flexibility." ContentLicense="CC BY-SA 4.0" />
  <row Id="21750" PostHistoryTypeId="2" PostId="8189" RevisionGUID="cc93d882-f6f0-4a2f-8c63-3dc2ea723db6" CreationDate="2018-10-27T01:33:20.423" UserId="9577" Text="I'm working on an image processing app which uses WebGL to apply shaders to a bunch of input photos. At one point in the algorithm, I need to create some [image pyramids][1] where I downscale the input photos by a factor of two each time, until I reach the smallest possible level.&#xD;&#xA;&#xD;&#xA;For my downscaling routine, I'm using a really simple process:&#xD;&#xA;&#xD;&#xA; 1. Create a new, blank texture using `texImage2D` which is half the size of the original.&#xD;&#xA; 2. Attach this texture to a frame buffer and use it as a render target (`bindFrameBuffer`). I also set the viewport to match the new texture's size.&#xD;&#xA; 3. Draw a flat quad whose vertices cover the screen-space coordinates (-1 -&gt; 1) using a 'copy-paste' shader which samples the original (full-size) texture. *Note that the texture parameters are always NEAREST and CLAMP_TO_EDGE.*&#xD;&#xA;&#xD;&#xA;Here's the source code for my fragment shader:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_inputImage;  // Original full-size texture&#xD;&#xA;    &#xD;&#xA;    varying vec2 v_texCoords;&#xD;&#xA;          &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(texture2D(u_inputImage, v_texCoords).rgb, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result looks sensible, but the quality of the downscaled texture is pretty poor. In the following example, you can see how it looks jagged compared to the original, particularly along the edges of the table on the bottom-right. There are also some glitchy pixels on the top of the chair, and under the door handle:&#xD;&#xA;&#xD;&#xA;[![Original][2]][2]&#xD;&#xA;&#xD;&#xA;[![Downsampled][3]][3]&#xD;&#xA;&#xD;&#xA;Does anyone know why this simple method doesn't seem to work? Is there a better way of creating a downsampled texture using WebGL/OpenGL?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Pyramid_(image_processing)&#xD;&#xA;  [2]: https://i.stack.imgur.com/7Tpr9.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/a3UHF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21751" PostHistoryTypeId="1" PostId="8189" RevisionGUID="cc93d882-f6f0-4a2f-8c63-3dc2ea723db6" CreationDate="2018-10-27T01:33:20.423" UserId="9577" Text="WebGL - issues doing a simple texture downsample" ContentLicense="CC BY-SA 4.0" />
  <row Id="21752" PostHistoryTypeId="3" PostId="8189" RevisionGUID="cc93d882-f6f0-4a2f-8c63-3dc2ea723db6" CreationDate="2018-10-27T01:33:20.423" UserId="9577" Text="|opengl|texture|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21753" PostHistoryTypeId="6" PostId="8189" RevisionGUID="dddcd0f9-4f8d-42fa-b42c-bcc430784722" CreationDate="2018-10-27T01:54:26.340" UserId="2654" Comment="edited tags" Text="|texture|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21754" PostHistoryTypeId="2" PostId="8190" RevisionGUID="cd00753a-ddd7-4120-9fa5-57930852d68e" CreationDate="2018-10-27T19:53:57.320" UserId="9581" Text="I am pretty new to Quaternions so please bear with me. I want to draw random Quaternion samples so that their Euler angle equivalent would range within `[-30, +30]` degrees on each axis. Currently, I know how to sample Quaternions from the full range (`[-180, +180]`) using the Python code below but I don't know how to modify the code so that I can get samples within the range `[-30, +30]`. Can anyone help me with that? &#xD;&#xA;&#xD;&#xA;I'm not sure if this is helpful to answer this question but here's a piece of information: I eventually want to convert the sampled Quaternion to Euler angles an apply the Euler rotation in some 3D shapes. The order of rotation in the software I'm using to do this is `XYZ` meaning that it first rotates the 3D shape along the `X` axis, then `Y` axis and then `Z` axis.&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    def sample_Quaternion():&#xD;&#xA;        r = np.random.uniform(0, 1 - 0.001, 3)&#xD;&#xA;	    while np.linalg.norm(r) &gt; 1:&#xD;&#xA;	   	    r = np.random.uniform(0, 1 - 0.001, 3) # Just to keep the L2 norm within [0, 1.0)&#xD;&#xA;        return r" ContentLicense="CC BY-SA 4.0" />
  <row Id="21755" PostHistoryTypeId="1" PostId="8190" RevisionGUID="cd00753a-ddd7-4120-9fa5-57930852d68e" CreationDate="2018-10-27T19:53:57.320" UserId="9581" Text="How to randomly draw Quaternions within a specific range of Euler angles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21756" PostHistoryTypeId="3" PostId="8190" RevisionGUID="cd00753a-ddd7-4120-9fa5-57930852d68e" CreationDate="2018-10-27T19:53:57.320" UserId="9581" Text="|3d|mathematics|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21757" PostHistoryTypeId="4" PostId="8190" RevisionGUID="572f6685-5c48-4d13-9a0c-c4de9a25f92c" CreationDate="2018-10-27T20:12:52.243" UserId="9581" Comment="edited title" Text="How to randomly draw Quaternions within a specific range of Euler angles for rotation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21758" PostHistoryTypeId="5" PostId="8190" RevisionGUID="509f3ade-e456-41ad-9f84-7253e9872011" CreationDate="2018-10-27T20:38:06.113" UserId="9581" Comment="added 74 characters in body" Text="I am pretty new to Quaternions so please bear with me. I want to draw random Quaternion samples so that their Euler angle equivalent would range within `[-30, +30]` degrees on each axis. Currently, I know how to sample Quaternions from the full range (`[-180, +180]`) using the code below but I don't know how to modify the code so that I can get samples within the range `[-30, +30]`. Can anyone help me with that? &#xD;&#xA;&#xD;&#xA;I'm not sure if this is helpful to answer this question but here's a piece of information: I eventually want to convert the sampled Quaternion to Euler angles an apply the Euler rotation in some 3D shapes. The order of rotation in the software I'm using to do this is `XYZ` meaning that it first rotates the 3D shape along the `X` axis, then `Y` axis and then `Z` axis.&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    def sample_Quaternion():&#xD;&#xA;        r = np.random.uniform(0, 1 - 0.001, 3)&#xD;&#xA;	    while np.linalg.norm(r) &gt; 1:&#xD;&#xA;	   	    r = np.random.uniform(0, 1 - 0.001, 3) # Just to keep the L2 norm within [0, 1.0)&#xD;&#xA;        w = [np.sqrt(1 - (r[0]*r[0] + r[1]*r[1] + r[2]*r[2]))]&#xD;&#xA;        r = np.concatenate(r, w) # the output of this would represent (x, y, z, w)&#xD;&#xA;        return r" ContentLicense="CC BY-SA 4.0" />
  <row Id="21759" PostHistoryTypeId="2" PostId="8191" RevisionGUID="25128476-a64b-4654-b24d-9afc4ff1b962" CreationDate="2018-10-27T21:51:47.480" UserId="6041" Text="I am following [Nvidia's DXR tutorial: D3D12HelloTriangle][1]. I call below code before creating device and it returns **true** &#xD;&#xA;&#xD;&#xA;    UUID experimentalFeatures[] = { D3D12RaytracingPrototype };&#xD;&#xA;    HRESULT hr = D3D12EnableExperimentalFeatures(1, experimentalFeatures, NULL, NULL);&#xD;&#xA;&#xD;&#xA;But this causes later for `D3D12CreateDevice` to fail. I am using Nvidia Geforce GTX 1050  : &#xD;&#xA;&#xD;&#xA;     Card name: NVIDIA GeForce GTX 1050&#xD;&#xA;           Chip type: GeForce GTX 1050&#xD;&#xA;            DAC type: Integrated RAMDAC&#xD;&#xA;         Device Type: Full Device&#xD;&#xA;          Device Key: Enum\PCI\VEN_10DE&amp;DEV_1C8D&amp;SUBSYS_12651025&amp;REV_A1&#xD;&#xA;       Device Status: 0180200A [DN_DRIVER_LOADED|DN_STARTED|DN_DISABLEABLE|DN_NT_ENUMERATOR|DN_NT_DRIVER] &#xD;&#xA;      Driver Version: 23.21.13.8873&#xD;&#xA;         DDI Version: 12&#xD;&#xA;      Feature Levels: 12_1,12_0,11_1,11_0,10_1,10_0,9_3,9_2,9_1&#xD;&#xA;        Driver Model: WDDM 2.3&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/rtx/raytracing/dxr/DX12-Raytracing-tutorial-Part-1&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21760" PostHistoryTypeId="1" PostId="8191" RevisionGUID="25128476-a64b-4654-b24d-9afc4ff1b962" CreationDate="2018-10-27T21:51:47.480" UserId="6041" Text="D3D12EnableExperimentalFeatures causes D3D12CreateDevice to fail" ContentLicense="CC BY-SA 4.0" />
  <row Id="21761" PostHistoryTypeId="3" PostId="8191" RevisionGUID="25128476-a64b-4654-b24d-9afc4ff1b962" CreationDate="2018-10-27T21:51:47.480" UserId="6041" Text="|directx12|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21762" PostHistoryTypeId="2" PostId="8192" RevisionGUID="61955e2b-26a0-4cf1-825a-cae4f9ff2cbb" CreationDate="2018-10-27T22:23:47.460" UserId="9506" Text="I'm implementing basic volumetric lighting using deferred shading (gbuffer + render to screen quad) and basic shadow mapping. So,  I am sending the position texture and shadow map to a separate shader, applying ray-marching for every position and computing the scattering accumulation when is not in shadow. The question is , how do I know I am getting the right results? is it just by rendering the volumetric lighting texture to quad and look for colored patches in the scene? these are my results:&#xD;&#xA;&#xD;&#xA;Original Scene&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Volumetric Light buffer&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is the code of my volumetric fragment shader:&#xD;&#xA;&#xD;&#xA;    uniform sampler2D positionMap; &#xD;&#xA;    uniform sampler2D shadowMap;&#xD;&#xA;    float NB_STEPS = 3.0f;&#xD;&#xA;    int NB_STEPS_INT = 3;&#xD;&#xA;    float G_SCATTERING = 0.7f;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    { &#xD;&#xA;	&#xD;&#xA;	vec2 texCoord = vec2(gl_FragCoord.x/width,gl_FragCoord.y/height);&#xD;&#xA;    vec3 worldPosition = texture2D(positionMap,texCoord).xyz;&#xD;&#xA;	vec3 startPosition = ViewPos;&#xD;&#xA;&#xD;&#xA;	vec3 rayVector = worldPosition.xyz- startPosition;&#xD;&#xA;	float rayLength = length(rayVector);&#xD;&#xA;	vec3 rayDirection = normalize(rayVector);&#xD;&#xA;	float stepLength = rayLength / NB_STEPS;&#xD;&#xA;	vec3 step = rayDirection * stepLength;&#xD;&#xA;&#xD;&#xA;	vec3 currentPosition = startPosition;&#xD;&#xA;&#xD;&#xA;	vec3 accumFog = vec3(0.0f);&#xD;&#xA;	for(int i = 0;  i &lt; NB_STEPS_INT; i++)&#xD;&#xA;	{&#xD;&#xA;	  bool shadow = ShadowCalculation(currentPosition);&#xD;&#xA;	  if(!shadow)&#xD;&#xA;	  {&#xD;&#xA;		accumFog += ComputeScattering(dot(rayDirection, light.position)) * light.diffuse;&#xD;&#xA;		//accumFog +=  light.diffuse;&#xD;&#xA;	  }&#xD;&#xA;	  currentPosition += step;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	accumFog /= NB_STEPS;&#xD;&#xA;&#xD;&#xA;	fragColor = vec4(accumFog, 1);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am computing the scattering factor like this:&#xD;&#xA;&#xD;&#xA;    float ComputeScattering(float lightDotView)&#xD;&#xA;    {&#xD;&#xA;      float result = 1.0f - G_SCATTERING * G_SCATTERING;&#xD;&#xA;      result /=  (4.0f * PI * pow(1.0f + G_SCATTERING * G_SCATTERING - (2.0f * G_SCATTERING) *    lightDotView, 1.5f));&#xD;&#xA;      return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At the end should I just blend the volumetric light buffer with the deferred shading final buffer?&#xD;&#xA;&#xD;&#xA;I appreciate the help.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2FrTy.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M1pmp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21763" PostHistoryTypeId="1" PostId="8192" RevisionGUID="61955e2b-26a0-4cf1-825a-cae4f9ff2cbb" CreationDate="2018-10-27T22:23:47.460" UserId="9506" Text="GLSL Debugging Volumetric light" ContentLicense="CC BY-SA 4.0" />
  <row Id="21764" PostHistoryTypeId="3" PostId="8192" RevisionGUID="61955e2b-26a0-4cf1-825a-cae4f9ff2cbb" CreationDate="2018-10-27T22:23:47.460" UserId="9506" Text="|glsl|deferred-rendering|volumetric-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21765" PostHistoryTypeId="2" PostId="8193" RevisionGUID="33eae3e7-c6a9-479f-8155-695a17c08887" CreationDate="2018-10-27T22:31:41.873" UserId="1937" Text="The simplest way to do this would be to generate the Euler angles randomly, then use them to create the quaternion. Most existing quaternion implementations in game engines and 3D math libraries will have a `FromEuler ( Vector3 )` function. &#xD;&#xA;&#xD;&#xA;Since you seem to be rolling your own quaternions rather than using a library, here's the [conversion formula][1].&#xD;&#xA;&#xD;&#xA;As a small optimization, since quaternions use half-angles, you could generate random values in the range ±15 degrees (pi/12) and feed these to the sin and cos functions directly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Euler_Angles_to_Quaternion_Conversion" ContentLicense="CC BY-SA 4.0" />
  <row Id="21766" PostHistoryTypeId="2" PostId="8194" RevisionGUID="caf74015-deeb-4160-a851-858881ce794b" CreationDate="2018-10-28T12:56:40.047" UserId="7868" Text="I've been using standard 32-bit Xorshift in my GPU path-tracer for a while, following Nathan Reed's approach with hashed seeds and decorrelated state. I (finally) discovered today that Xorshift is considered obsolete and I should use a 64-bit+ PRNG instead for better-distributed values, but I obviously can't fake the operations needed for PCG and modern Xorshift without expensive software arithmetic.&#xD;&#xA;&#xD;&#xA;So, I've been considering the MRG32k3a hash by Pierre L'Ecuyer. It uses doubles instead of uint64s, it's included in Intel's Math Kernel Library, and [some authors][1] claim it has good statistical performance. It's also nearly twenty years old, though, and the paper linked above is dated from 2011.&#xD;&#xA;&#xD;&#xA;Is MRG32k3a still considered an effective PRNG? Is it an effective alternative to PCG and modern Xorshift?&#xD;&#xA;&#xD;&#xA;If not, what else should I use? Philox seems [interesting][2], but it's another old technique (published 2011) and I'm not sure if it's been superseded in the meantime.&#xD;&#xA;&#xD;&#xA;- MRG32k3a MKL [entry][3]&#xD;&#xA;- [Example][4] implementation from L'Ecuyer's paper&#xD;&#xA;- The [paper][5] itself&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.thesalmons.org/john/random123/papers/random123sc11.pdf&#xD;&#xA;  [2]: https://www.shadertoy.com/view/XslBR4&#xD;&#xA;  [3]: https://software.intel.com/en-us/mkl-vsnotes-mrg32k3a&#xD;&#xA;  [4]: http://simul.iro.umontreal.ca/rng/MRG32k3a.c&#xD;&#xA;  [5]: https://www.researchgate.net/publication/261858547_Good_Parameters_and_Implementations_for_Combined_Multiple_Recursive_Random_Number_Generators" ContentLicense="CC BY-SA 4.0" />
  <row Id="21767" PostHistoryTypeId="1" PostId="8194" RevisionGUID="caf74015-deeb-4160-a851-858881ce794b" CreationDate="2018-10-28T12:56:40.047" UserId="7868" Text="Does MRG32k3a compare well with PCG and Xorshift256*?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21768" PostHistoryTypeId="3" PostId="8194" RevisionGUID="caf74015-deeb-4160-a851-858881ce794b" CreationDate="2018-10-28T12:56:40.047" UserId="7868" Text="|pathtracing|gpu|sampling|noise|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21769" PostHistoryTypeId="2" PostId="8195" RevisionGUID="42df871b-caa7-4e60-9134-1fedf3c7cfdd" CreationDate="2018-10-28T16:43:46.143" UserId="9581" Text="I am rotating an 3D shape using Euler angles in the order of XYZ meaning that the object is first rotated along the `X` axis, then `Y` and then `Z`. I want to convert the Euler rotation to Quaternion and then get the same Euler rotation back from the Quaternion using some [preferably] Python code. Below, I have some code that converts Euler rotation to Quaternion and then converts the Quaternion to get Euler rotations. However, this does not give me the same Euler rotations.&#xD;&#xA;&#xD;&#xA;I think the problem is I don't know how to associate *yaw, pitch and roll* to X, Y an Z axes. Also, I don't know how to change order of conversions in the code to correctly convert the Euler rotation to Quaternion and then convert the Quaternion to Euler rotation so that I am able to get the same Euler rotation back. Can someone help me with this?&#xD;&#xA;&#xD;&#xA;And here's the code I used:&#xD;&#xA;&#xD;&#xA;This function converts Euler rotations to Quaternions:&#xD;&#xA;&#xD;&#xA;    def euler_to_quaternion(yaw, pitch, roll):&#xD;&#xA;    &#xD;&#xA;    		qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)&#xD;&#xA;    		qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    &#xD;&#xA;    		return [qx, qy, qz, qw]&#xD;&#xA;&#xD;&#xA;And this converts Quaternions to Euler rotations:&#xD;&#xA;&#xD;&#xA;    def quaternion_to_euler(x, y, z, w):&#xD;&#xA;    &#xD;&#xA;    		import math&#xD;&#xA;    		t0 = +2.0 * (w * x + y * z)&#xD;&#xA;    		t1 = +1.0 - 2.0 * (x * x + y * y)&#xD;&#xA;    		X = math.degrees(math.atan2(t0, t1))&#xD;&#xA;    		&#xD;&#xA;    		t2 = +2.0 * (w * y - z * x)&#xD;&#xA;    		t2 = +1.0 if t2 &gt; +1.0 else t2&#xD;&#xA;    		t2 = -1.0 if t2 &lt; -1.0 else t2&#xD;&#xA;    		Y = math.degrees(math.asin(t2))&#xD;&#xA;    		&#xD;&#xA;    		t3 = +2.0 * (w * z + x * y)&#xD;&#xA;    		t4 = +1.0 - 2.0 * (y * y + z * z)&#xD;&#xA;    		Z = math.degrees(math.atan2(t3, t4))&#xD;&#xA;    		&#xD;&#xA;    		return X, Y, Z&#xD;&#xA;&#xD;&#xA;And I use them as follow:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    euler_Original = (np.random.random(3) * 360).tolist() # some random XYZ rotation&#xD;&#xA;    quat = euler_to_quaternion(euler_Original[0], euler_Original[1], euler_Original[2])&#xD;&#xA;    newEulerRot = quaternion_to_euler(quat[0], quat[1], quat[2], quat[3])&#xD;&#xA;    &#xD;&#xA;    print (euler_Original)&#xD;&#xA;    print (newEulerRot)&#xD;&#xA;&#xD;&#xA;The print statements print different numbers for `euler_Original` and `newEulerRot` which I don't want to be the case. How can I fix this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21770" PostHistoryTypeId="1" PostId="8195" RevisionGUID="42df871b-caa7-4e60-9134-1fedf3c7cfdd" CreationDate="2018-10-28T16:43:46.143" UserId="9581" Text="How to convert Euler rotation to Quaternions and get the same Euler rotation back?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21771" PostHistoryTypeId="3" PostId="8195" RevisionGUID="42df871b-caa7-4e60-9134-1fedf3c7cfdd" CreationDate="2018-10-28T16:43:46.143" UserId="9581" Text="|3d|mathematics|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21772" PostHistoryTypeId="5" PostId="8195" RevisionGUID="ec88de13-2f7d-4557-b43a-a1b2ef13e03a" CreationDate="2018-10-28T16:52:05.293" UserId="9581" Comment="deleted 22 characters in body; edited title" Text="I am rotating an 3D shape using Euler angles in the order of XYZ meaning that the object is first rotated along the `X` axis, then `Y` and then `Z`. I want to convert the Euler angle to Quaternion and then get the same Euler angles back from the Quaternion using some [preferably] Python code. Below, I have some code that converts Euler angle to Quaternion and then converts the Quaternion to get Euler angles. However, this does not give me the same Euler angles.&#xD;&#xA;&#xD;&#xA;I think the problem is I don't know how to associate *yaw, pitch and roll* to X, Y an Z axes. Also, I don't know how to change order of conversions in the code to correctly convert the Euler angles to Quaternion and then convert the Quaternion to Euler angle so that I am able to get the same Euler angle back. Can someone help me with this?&#xD;&#xA;&#xD;&#xA;And here's the code I used:&#xD;&#xA;&#xD;&#xA;This function converts Euler angles to Quaternions:&#xD;&#xA;&#xD;&#xA;    def euler_to_quaternion(yaw, pitch, roll):&#xD;&#xA;    &#xD;&#xA;    		qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)&#xD;&#xA;    		qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    &#xD;&#xA;    		return [qx, qy, qz, qw]&#xD;&#xA;&#xD;&#xA;And this converts Quaternions to Euler angles:&#xD;&#xA;&#xD;&#xA;    def quaternion_to_euler(x, y, z, w):&#xD;&#xA;    &#xD;&#xA;    		import math&#xD;&#xA;    		t0 = +2.0 * (w * x + y * z)&#xD;&#xA;    		t1 = +1.0 - 2.0 * (x * x + y * y)&#xD;&#xA;    		X = math.degrees(math.atan2(t0, t1))&#xD;&#xA;    		&#xD;&#xA;    		t2 = +2.0 * (w * y - z * x)&#xD;&#xA;    		t2 = +1.0 if t2 &gt; +1.0 else t2&#xD;&#xA;    		t2 = -1.0 if t2 &lt; -1.0 else t2&#xD;&#xA;    		Y = math.degrees(math.asin(t2))&#xD;&#xA;    		&#xD;&#xA;    		t3 = +2.0 * (w * z + x * y)&#xD;&#xA;    		t4 = +1.0 - 2.0 * (y * y + z * z)&#xD;&#xA;    		Z = math.degrees(math.atan2(t3, t4))&#xD;&#xA;    		&#xD;&#xA;    		return X, Y, Z&#xD;&#xA;&#xD;&#xA;And I use them as follow:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    euler_Original = (np.random.random(3) * 360).tolist() # random rotation angles for XYZ&#xD;&#xA;    quat = euler_to_quaternion(euler_Original[0], euler_Original[1], euler_Original[2])&#xD;&#xA;    newEulerRot = quaternion_to_euler(quat[0], quat[1], quat[2], quat[3])&#xD;&#xA;    &#xD;&#xA;    print (euler_Original)&#xD;&#xA;    print (newEulerRot)&#xD;&#xA;&#xD;&#xA;The print statements print different numbers for `euler_Original` and `newEulerRot` which I don't want to be the case. How can I fix this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21773" PostHistoryTypeId="4" PostId="8195" RevisionGUID="ec88de13-2f7d-4557-b43a-a1b2ef13e03a" CreationDate="2018-10-28T16:52:05.293" UserId="9581" Comment="deleted 22 characters in body; edited title" Text="How to convert Euler angles to Quaternions and get the same Euler angles back?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21774" PostHistoryTypeId="2" PostId="8196" RevisionGUID="e953adaf-4b50-481b-8b64-b641b17d43d2" CreationDate="2018-10-28T17:10:34.150" UserId="9582" Text="&#xD;&#xA;I currently have a 4K monitor and want to buy a new graphics card. My choice would either be the RTX 2080 or the RTX 2080 Ti. Now I need to know which one I really need. The Ti variant has 12 GB of GDDR6 instead of just 8 GB (and more shader cores of course, which makes the card faster)&#xD;&#xA;&#xD;&#xA;My question is, what elements do actually get loaded into the GDDR6 memory? Is it only the textures or is there other stuff that needs to be loaded into the GPU memory? Does the memory consumption differ when comparing 1080p(HD) and 2160p(4K)? What if you would run a game at 4320p (8K)? People say that you need more GPU memory if you have a higher resolution, is this really true? And what things do you need to take into account when calculating the rough memory usage?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21775" PostHistoryTypeId="1" PostId="8196" RevisionGUID="e953adaf-4b50-481b-8b64-b641b17d43d2" CreationDate="2018-10-28T17:10:34.150" UserId="9582" Text="What objects do get loaded into GDDR?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21776" PostHistoryTypeId="3" PostId="8196" RevisionGUID="e953adaf-4b50-481b-8b64-b641b17d43d2" CreationDate="2018-10-28T17:10:34.150" UserId="9582" Text="|gpu|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21777" PostHistoryTypeId="4" PostId="8195" RevisionGUID="2061526a-58a8-4b3a-b567-e5421af3890c" CreationDate="2018-10-28T19:10:08.597" UserId="9581" Comment="edited title" Text="How to convert Euler angles to Quaternions so that I can get the same Euler angles back?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21778" PostHistoryTypeId="4" PostId="8195" RevisionGUID="a363305e-4247-41b2-8dbd-c767f021d37c" CreationDate="2018-10-28T19:22:57.983" UserId="9581" Comment="edited title" Text="How to convert Euler angles to Quaternions and get the same Euler angles back from Quaternions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21779" PostHistoryTypeId="5" PostId="8195" RevisionGUID="9583821a-6eba-4977-85f4-5ac2ea45bef7" CreationDate="2018-10-28T19:28:14.453" UserId="9581" Comment="added 367 characters in body" Text="I am rotating n 3D shape using Euler angles in the order of XYZ meaning that the object is first rotated along the `X` axis, then `Y` and then `Z`. I want to convert the Euler angle to Quaternion and then get the same Euler angles back from the Quaternion using some [preferably] Python code or just some pseudocode or algorithm. Below, I have some code that converts Euler angle to Quaternion and then converts the Quaternion to get Euler angles. However, this does not give me the same Euler angles.&#xD;&#xA;&#xD;&#xA;I think the problem is I don't know how to associate *yaw, pitch and roll* to X, Y an Z axes. Also, I don't know how to change order of conversions in the code to correctly convert the Euler angles to Quaternion and then convert the Quaternion to Euler angle so that I am able to get the same Euler angle back. Can someone help me with this?&#xD;&#xA;&#xD;&#xA;And here's the code I used:&#xD;&#xA;&#xD;&#xA;This function converts Euler angles to Quaternions:&#xD;&#xA;&#xD;&#xA;    def euler_to_quaternion(yaw, pitch, roll):&#xD;&#xA;    &#xD;&#xA;    		qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)&#xD;&#xA;    		qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    &#xD;&#xA;    		return [qx, qy, qz, qw]&#xD;&#xA;&#xD;&#xA;And this converts Quaternions to Euler angles:&#xD;&#xA;&#xD;&#xA;    def quaternion_to_euler(x, y, z, w):&#xD;&#xA;    &#xD;&#xA;    		import math&#xD;&#xA;    		t0 = +2.0 * (w * x + y * z)&#xD;&#xA;    		t1 = +1.0 - 2.0 * (x * x + y * y)&#xD;&#xA;    		X = math.degrees(math.atan2(t0, t1))&#xD;&#xA;    		&#xD;&#xA;    		t2 = +2.0 * (w * y - z * x)&#xD;&#xA;    		t2 = +1.0 if t2 &gt; +1.0 else t2&#xD;&#xA;    		t2 = -1.0 if t2 &lt; -1.0 else t2&#xD;&#xA;    		Y = math.degrees(math.asin(t2))&#xD;&#xA;    		&#xD;&#xA;    		t3 = +2.0 * (w * z + x * y)&#xD;&#xA;    		t4 = +1.0 - 2.0 * (y * y + z * z)&#xD;&#xA;    		Z = math.degrees(math.atan2(t3, t4))&#xD;&#xA;    		&#xD;&#xA;    		return X, Y, Z&#xD;&#xA;&#xD;&#xA;And I use them as follow:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    euler_Original = np.random.random(3) * 360).tolist() # Generate random rotation angles for XYZ within the range [0, 360)&#xD;&#xA;    quat = euler_to_quaternion(euler_Original[0], euler_Original[1], euler_Original[2]) # Convert to Quaternion&#xD;&#xA;    newEulerRot = quaternion_to_euler(quat[0], quat[1], quat[2], quat[3]) #Convert the Quaternion to Euler angles&#xD;&#xA;    &#xD;&#xA;    print (euler_Original)&#xD;&#xA;    print (newEulerRot)&#xD;&#xA;&#xD;&#xA;The print statements print different numbers for `euler_Original` and `newEulerRot` which I don't want to be the case. For example if `euler_original` contains numbers like (25.2, 150.12, 2.31) I get this Quaternion --&gt; `(0.866, -0.104, 0.316, 0.370)` and converting the Quaternion to Euler angles gives me this --&gt; `(132.35, -38.75, 3.85)`. I wonder how I can fix this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21780" PostHistoryTypeId="5" PostId="8195" RevisionGUID="150f988c-38e3-405d-aa3c-801c6aed5450" CreationDate="2018-10-28T19:37:59.487" UserId="9581" Comment="added 22 characters in body" Text="I am rotating n 3D shape using Euler angles in the order of XYZ meaning that the object is first rotated along the `X` axis, then `Y` and then `Z`. I want to convert the Euler angle to Quaternion and then get the same Euler angles back from the Quaternion using some [preferably] Python code or just some pseudocode or algorithm. Below, I have some code that converts Euler angle to Quaternion and then converts the Quaternion to get Euler angles. However, this does not give me the same Euler angles.&#xD;&#xA;&#xD;&#xA;I think the problem is I don't know how to associate *yaw, pitch and roll* to X, Y an Z axes. Also, I don't know how to change order of conversions in the code to correctly convert the Euler angles to Quaternion and then convert the Quaternion to Euler angle so that I am able to get the same Euler angle back. Can someone help me with this?&#xD;&#xA;&#xD;&#xA;And here's the code I used:&#xD;&#xA;&#xD;&#xA;This function converts Euler angles to Quaternions:&#xD;&#xA;&#xD;&#xA;    def euler_to_quaternion(yaw, pitch, roll):&#xD;&#xA;    &#xD;&#xA;    		qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)&#xD;&#xA;    		qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    &#xD;&#xA;    		return [qx, qy, qz, qw]&#xD;&#xA;&#xD;&#xA;And this converts Quaternions to Euler angles:&#xD;&#xA;&#xD;&#xA;    def quaternion_to_euler(x, y, z, w):&#xD;&#xA;    &#xD;&#xA;    		import math&#xD;&#xA;    		t0 = +2.0 * (w * x + y * z)&#xD;&#xA;    		t1 = +1.0 - 2.0 * (x * x + y * y)&#xD;&#xA;    		X = math.degrees(math.atan2(t0, t1))&#xD;&#xA;    		&#xD;&#xA;    		t2 = +2.0 * (w * y - z * x)&#xD;&#xA;    		t2 = +1.0 if t2 &gt; +1.0 else t2&#xD;&#xA;    		t2 = -1.0 if t2 &lt; -1.0 else t2&#xD;&#xA;    		Y = math.degrees(math.asin(t2))&#xD;&#xA;    		&#xD;&#xA;    		t3 = +2.0 * (w * z + x * y)&#xD;&#xA;    		t4 = +1.0 - 2.0 * (y * y + z * z)&#xD;&#xA;    		Z = math.degrees(math.atan2(t3, t4))&#xD;&#xA;    		&#xD;&#xA;    		return X, Y, Z&#xD;&#xA;&#xD;&#xA;And I use them as follow:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    euler_Original = np.random.random(3) * 360).tolist() # Generate random rotation angles for XYZ within the range [0, 360)&#xD;&#xA;    quat = euler_to_quaternion(euler_Original[0], euler_Original[1], euler_Original[2]) # Convert to Quaternion&#xD;&#xA;    newEulerRot = quaternion_to_euler(quat[0], quat[1], quat[2], quat[3]) #Convert the Quaternion to Euler angles&#xD;&#xA;    &#xD;&#xA;    print (euler_Original)&#xD;&#xA;    print (newEulerRot)&#xD;&#xA;&#xD;&#xA;The print statements print different numbers for `euler_Original` and `newEulerRot` which I don't want to be the case. For example if `euler_original` contains numbers like `(25.2, 150.12, 2.31)` I get this Quaternion --&gt; `(0.866, -0.104, 0.316, 0.370)` and converting the Quaternion to Euler angles gives me this --&gt; `(132.35, -38.75, 3.85)` which is very wrong. I wonder how I can fix this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21781" PostHistoryTypeId="5" PostId="8195" RevisionGUID="3d119b05-2d95-41c2-af0b-b3b7b232367d" CreationDate="2018-10-28T20:28:59.110" UserId="9581" Comment="added 303 characters in body" Text="I am rotating n 3D shape using Euler angles in the order of XYZ meaning that the object is first rotated along the `X` axis, then `Y` and then `Z`. I want to convert the Euler angle to Quaternion and then get the same Euler angles back from the Quaternion using some [preferably] Python code or just some pseudocode or algorithm. Below, I have some code that converts Euler angle to Quaternion and then converts the Quaternion to get Euler angles. However, this does not give me the same Euler angles.&#xD;&#xA;&#xD;&#xA;I think the problem is I don't know how to associate *yaw, pitch and roll* to X, Y an Z axes. Also, I don't know how to change order of conversions in the code to correctly convert the Euler angles to Quaternion and then convert the Quaternion to Euler angle so that I am able to get the same Euler angle back. Can someone help me with this?&#xD;&#xA;&#xD;&#xA;And here's the code I used:&#xD;&#xA;&#xD;&#xA;This function converts Euler angles to Quaternions:&#xD;&#xA;&#xD;&#xA;    def euler_to_quaternion(yaw, pitch, roll):&#xD;&#xA;    &#xD;&#xA;    		qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    		qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)&#xD;&#xA;    		qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    &#xD;&#xA;    		return [qx, qy, qz, qw]&#xD;&#xA;&#xD;&#xA;And this converts Quaternions to Euler angles:&#xD;&#xA;&#xD;&#xA;    def quaternion_to_euler(x, y, z, w):&#xD;&#xA;    &#xD;&#xA;    		import math&#xD;&#xA;    		t0 = +2.0 * (w * x + y * z)&#xD;&#xA;    		t1 = +1.0 - 2.0 * (x * x + y * y)&#xD;&#xA;    		X = math.degrees(math.atan2(t0, t1))&#xD;&#xA;    		&#xD;&#xA;    		t2 = +2.0 * (w * y - z * x)&#xD;&#xA;    		t2 = +1.0 if t2 &gt; +1.0 else t2&#xD;&#xA;    		t2 = -1.0 if t2 &lt; -1.0 else t2&#xD;&#xA;    		Y = math.degrees(math.asin(t2))&#xD;&#xA;    		&#xD;&#xA;    		t3 = +2.0 * (w * z + x * y)&#xD;&#xA;    		t4 = +1.0 - 2.0 * (y * y + z * z)&#xD;&#xA;    		Z = math.degrees(math.atan2(t3, t4))&#xD;&#xA;    		&#xD;&#xA;    		return X, Y, Z&#xD;&#xA;&#xD;&#xA;And I use them as follow:&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    euler_Original = np.random.random(3) * 360).tolist() # Generate random rotation angles for XYZ within the range [0, 360)&#xD;&#xA;    quat = euler_to_quaternion(euler_Original[0], euler_Original[1], euler_Original[2]) # Convert to Quaternion&#xD;&#xA;    newEulerRot = quaternion_to_euler(quat[0], quat[1], quat[2], quat[3]) #Convert the Quaternion to Euler angles&#xD;&#xA;    &#xD;&#xA;    print (euler_Original)&#xD;&#xA;    print (newEulerRot)&#xD;&#xA;&#xD;&#xA;The print statements print different numbers for `euler_Original` and `newEulerRot` which I don't want to be the case. For example if `euler_original` contains numbers like `(0.2, 1.12, 2.31)` in radians I get this Quaternion --&gt; `[0.749, 0.290, -0.449, 0.389]` and converting the Quaternion to Euler angles gives me this --&gt; `(132.35, 64.17, 11.45)` which is pretty wrong. I wonder how I can fix this?&#xD;&#xA;&#xD;&#xA;Although I'm interested in getting the above code to work by making changes to it but, I would rather learn how to set up the equations correctly. This way I would know how I can get the correct Quaternions even if the order of rotations (XYZ --&gt; YZX etc) for applying Euler angles is changed." ContentLicense="CC BY-SA 4.0" />
  <row Id="21782" PostHistoryTypeId="2" PostId="8197" RevisionGUID="d4579c52-049c-46c8-9ae3-f14f294e8c25" CreationDate="2018-10-29T08:24:50.503" UserId="182" Text="This question is a bit too broad to answer, but I'll try.&#xD;&#xA;&#xD;&#xA;Right now you have a screenshot and you are not really sure whether it's correct or not, and if it turns out it is not, it will be difficult to know what is incorrect about it. I would recommend to split your problem into smaller, isolated, problems that can be validated separately.&#xD;&#xA;&#xD;&#xA;For example, is the lighting information correct at each point? Are the coordinates (screen space vs world space) correct? To answer these questions you could maybe represent the distance from the light at each point, with something like the following, and check that the visual result is consistent with your scene.&#xD;&#xA;&#xD;&#xA;    color = fract(length(light.position - currentPosition));&#xD;&#xA;&#xD;&#xA;Similarly, is the shadowing correct? This problem is unrelated to scattering so you can check that it  is correct by just having a constant light contribution (your commented code seems to indicate that you have tried so already). You will see quickly if a volumetric shadow is properly cast from occluding geometry.&#xD;&#xA;&#xD;&#xA;    if (!shadow)&#xD;&#xA;    {&#xD;&#xA;        accumFog += light.diffuse;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Finally you can test the scattering without any shadow, and make sure it behaves as expected. For example, you should get the same fog color when changing the number of steps. Moreover, the scattering contribution should be less noticeable when there is geometry close to the camera (make sure you stop marching when you reach the scene depth).&#xD;&#xA;&#xD;&#xA;Once you are confident the separate parts are working, you can combine them until you reach the final result. I have suggested a few points to check, but you might check other points as well, as you see fit.&#xD;&#xA;&#xD;&#xA;&gt; At the end should I just blend the volumetric light buffer with the deferred shading final buffer?&#xD;&#xA;&#xD;&#xA;Since the lighting is additive, you just need to do an additive blend of the resulting buffer on your scene. However if you later decide to also handle distance fog (contrast fading in the distance), then a different blending will be necessary.&#xD;&#xA;&#xD;&#xA;P.S.: I happen to have written [about volumetric lighting in this article][1] (see part &quot;Volumetric lighting&quot;). It doesn't go into details, but maybe it will be helpful nonetheless.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.ctrl-alt-test.fr/2018/a-dive-into-the-making-of-immersion/" ContentLicense="CC BY-SA 4.0" />
  <row Id="21793" PostHistoryTypeId="2" PostId="8201" RevisionGUID="18907ce7-4f9e-4986-ac0c-1a124bbad8f6" CreationDate="2018-10-29T16:58:10.443" UserId="9594" Text="Wonder if anyone has experienced this. When generating png image icons for macos. its recommended at 19x19 pixels. However, based on that, the icon (shield) that is generated is pixellated compared with the next in line. I have tried using 38x38, which effectively doubles the pixels. It looks much finer in preview but when attached, it because a large icon cropped off the bottom. Are there are specifics to generating a retina compatible icon for mac status bar?&#xD;&#xA;&#xD;&#xA;[![screenshot of status bar][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/658Ge.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21794" PostHistoryTypeId="1" PostId="8201" RevisionGUID="18907ce7-4f9e-4986-ac0c-1a124bbad8f6" CreationDate="2018-10-29T16:58:10.443" UserId="9594" Text="Resolution issue of generating a PNG icon for Mac OS X status bar" ContentLicense="CC BY-SA 4.0" />
  <row Id="21795" PostHistoryTypeId="3" PostId="8201" RevisionGUID="18907ce7-4f9e-4986-ac0c-1a124bbad8f6" CreationDate="2018-10-29T16:58:10.443" UserId="9594" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21797" PostHistoryTypeId="2" PostId="8202" RevisionGUID="177b71d9-07e2-462a-9e30-f21b51251d53" CreationDate="2018-10-30T02:01:59.900" UserId="3073" Text="Typically you will need VRAM to store your frame buffer (memory used for display and rendering). This would usually be 4 bytes per pixel so a 1080p frame buffer is 1920x1080x4 bytes (1 byte each for R,G,B components + 1 padding byte). Your card is going to use 2 of these for double buffering so it can use one for display output and the other for constructing the next frame. Any increase in resolution will require an increase in VRAM usage. Certain types of post-processing special effects may also need additional rendering buffers which are some division of the screen resolution so will consequently use more VRAM if using a higher resolution.&#xD;&#xA;&#xD;&#xA;After that the rest of VRAM is going to be allocated for textures which for a typical game is by far the biggest user of VRAM. Then mesh data needs storing in VRAM which usually consists of vertices and arrays of matrices if you're instancing a lot of meshes. Finally compiled shaders will need to occupy VRAM but they should be low down on memory usage compared to textures.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21798" PostHistoryTypeId="5" PostId="8202" RevisionGUID="3cf840e2-fdca-4f05-b280-4b18fc177f95" CreationDate="2018-10-30T02:59:58.440" UserId="3073" Comment="added 33 characters in body" Text="Typically you will need VRAM to store your frame buffer (memory used to store pixels for use with the display and for rendering). This would usually be 4 bytes per pixel so a 1080p frame buffer is 1920x1080x4 bytes (1 byte each for R,G,B components + 1 padding byte). Your card is going to use 2 of these for double buffering so it can use one for display output and the other for constructing the next frame. Any increase in resolution will require an increase in VRAM usage. If HDR is used then you're looking at 16 bytes per pixel so you can use floating point accuracy. Certain types of post-processing special effects may also need additional rendering buffers which are some division of the screen resolution so will consequently use more VRAM if using a higher resolution.&#xD;&#xA;&#xD;&#xA;After that the majority of VRAM is going to be allocated for textures which for a typical game is the biggest user of VRAM. Then mesh data needs storing in VRAM which usually consists of vertices storing information like geometry position/normals/colours/etc and arrays of matrices if you're instancing a lot of meshes. Finally compiled shaders will need to occupy VRAM but they should be low down on memory usage compared to textures. There will be other uses for VRAM too depending on how the game was engineered so this is not an exhaustive list of what VRAM is used for." ContentLicense="CC BY-SA 4.0" />
  <row Id="21799" PostHistoryTypeId="5" PostId="8202" RevisionGUID="c95aa5d5-5fee-4275-9bdb-708bb7486da5" CreationDate="2018-10-30T08:42:50.557" UserId="3073" Comment="deleted 22 characters in body" Text="Typically you will need VRAM to store your frame buffer (memory used to store pixels for use with the display and for rendering). This would usually be 4 bytes per pixel so a 1080p frame buffer is 1920x1080x4 bytes (1 byte each for R,G,B components + 1 padding byte). Your card is going to use 2 of these for double buffering so it can use one for display output and the other for constructing the next frame. Any increase in resolution will require an increase in VRAM usage. If HDR is used then you're looking at 16 bytes per pixel so you can use floating point accuracy. Certain types of post-processing special effects may also need additional rendering buffers which are some division of the screen resolution so will consequently use more VRAM if using a higher resolution.&#xD;&#xA;&#xD;&#xA;After that the majority of VRAM is going to be allocated for textures which for a typical game is the biggest user of VRAM. Then mesh data needs storing in VRAM which usually consists of vertices storing information like geometry position/normals/colours/transformation matrices/etc. Finally compiled shaders will need to occupy VRAM but they should be low down on memory usage compared to textures and mesh data. There will be other uses for VRAM too depending on how the game was engineered so this is not an exhaustive list of what VRAM is used for." ContentLicense="CC BY-SA 4.0" />
  <row Id="21800" PostHistoryTypeId="50" PostId="7997" RevisionGUID="f9855f34-a602-457f-bcba-1ae0fd2f6795" CreationDate="2018-10-30T09:00:48.817" UserId="-1" />
  <row Id="21804" PostHistoryTypeId="5" PostId="8202" RevisionGUID="970e7cac-22db-491a-bc67-d96fae0ebd4d" CreationDate="2018-10-30T09:42:00.020" UserId="3073" Comment="summary added" Text="Typically you will need VRAM to store your frame buffer (memory used to store pixels for use with the display and for rendering). This would usually be 4 bytes per pixel so a 1080p frame buffer is 1920x1080x4 bytes (1 byte each for R,G,B components + 1 padding byte). Your card is going to use 2 of these for double buffering so it can use one for display output and the other for constructing the next frame. Any increase in resolution will require an increase in VRAM usage. If HDR is used then you're looking at 16 bytes per pixel so you can use floating point accuracy. Certain types of post-processing special effects may also need additional rendering buffers which are some division of the screen resolution so will consequently use more VRAM if using a higher resolution.&#xD;&#xA;&#xD;&#xA;After that the majority of VRAM is going to be allocated for textures which for a typical game is the biggest user of VRAM. Then mesh data needs storing in VRAM which usually consists of vertices storing information like geometry position/normals/colours/transformation matrices/etc. Finally compiled shaders will need to occupy VRAM but they should be low down on memory usage compared to textures and mesh data. There will be other uses for VRAM too depending on how the game was engineered so this is not an exhaustive list of what VRAM is used for.&#xD;&#xA;&#xD;&#xA;In short: Display resolution will change the amount of VRAM required but not by a large amount. For a video game most VRAM is from textures which are usually defined by the quality settings of the game and are not affected by display resolution. The 12gb card you mentioned will allow higher texture resolution but with your choice of 1080p or 4k display resolution making little difference in VRAM usage. However for 4k it makes sense to use the highest texture quality." ContentLicense="CC BY-SA 4.0" />
  <row Id="21806" PostHistoryTypeId="2" PostId="8205" RevisionGUID="a98f968a-08c8-4714-bbe7-9b547c65bb6a" CreationDate="2018-10-30T11:01:34.277" UserId="9603" Text="Does anyone know what software was used in many old scientific papers (please see attached example). I love the clean look of the graph and the typeface.&#xD;&#xA;Thanks.&#xD;&#xA;[Graph example][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uLABG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21807" PostHistoryTypeId="1" PostId="8205" RevisionGUID="a98f968a-08c8-4714-bbe7-9b547c65bb6a" CreationDate="2018-10-30T11:01:34.277" UserId="9603" Text="Plotting software used in old scientific papers" ContentLicense="CC BY-SA 4.0" />
  <row Id="21808" PostHistoryTypeId="3" PostId="8205" RevisionGUID="a98f968a-08c8-4714-bbe7-9b547c65bb6a" CreationDate="2018-10-30T11:01:34.277" UserId="9603" Text="|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21809" PostHistoryTypeId="2" PostId="8206" RevisionGUID="a637372b-432f-4e15-9d72-15bff5d331f0" CreationDate="2018-10-30T11:20:32.910" UserId="7644" Text="The downscaled picture is not smooth because you use &quot;nearest&quot; filtering.&#xD;&#xA;&#xD;&#xA;Each block of 2x2 pixels in the original image is transformed into a single pixel in the downscaled image. Put another way, each pixel in the downscaled image represents the contents of 4 original pixels. Your current solution considers just one of those 4 pixels and ignores the others. This is what produces blockiness in the downscaled picture.&#xD;&#xA;&#xD;&#xA;To fix this, each downscaled pixel must contain information from more than one original pixel. The simplest way to do this is by using a &quot;box filter&quot; where each downscaled pixel is computed as the mean of the 4 original pixels it covers. This can be achieved in a single texture fetch with linear filtering and the proper sampling position:&#xD;&#xA;&#xD;&#xA;	+---+---+&#xD;&#xA;	| A | B |  // ABCD =&gt; original pixels&#xD;&#xA;	+---X---+  // X =&gt; sample position in the middle of the 4 pixels (texels)&#xD;&#xA;	| C | D |&#xD;&#xA;	+---+---+&#xD;&#xA;&#xD;&#xA;Linear filtering sampled at position `0` will give `(A+B+C+D) / 4` or the average value.&#xD;&#xA;&#xD;&#xA;Another computer graphic term for what you're doing is &quot;mipmap generation&quot;. There are other filters which give better quality than the simple box filter I described." ContentLicense="CC BY-SA 4.0" />
  <row Id="21810" PostHistoryTypeId="5" PostId="4434" RevisionGUID="8998352b-07c3-4ca3-a777-548e64bda042" CreationDate="2018-10-30T11:21:07.900" UserId="6442" Comment="Added mention of VkEvent" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Overall both APIs are surprisingly similar. Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary greatly between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         n/a&#xD;&#xA;    VkEvent                             n/a&#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;&#xD;&#xA;General queue behavior is pretty similar between both. There's a bit of idiosyncrasy when submitting from multiple threads. &#xD;&#xA;&#xD;&#xA;Will try to update as I remember more stuff...&#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - but the actual behavior is pretty similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools. You can also begin recording immediately after submitting the command buffer/list on both.&#xD;&#xA;&#xD;&#xA;DX12 command list are created in an open state. I find this a bit annoying since I'm used to Vulkan. DX12 also requires and explicit reset of the command allocator and command list. This is an optional behavior in Vulkan.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;VkDescriptorPool and ID3D12DescriptorHeaps are sort of similar (thanks Nicolas) in that they both manage allocation of the descriptors themselves. &#xD;&#xA;&#xD;&#xA;It should be noted that DX12 only supports at most two descriptor heaps bound to a command list at any given time. One CBVSRVUAV and one sampler. You can have as many descriptor tables as you want referencing these heaps. &#xD;&#xA;&#xD;&#xA;On the Vulkan side, there is a hard limit to the max number of descriptor sets that you tell the descriptor pool. On both you have to do a bit of manual accounting on the number of descriptors per type the pool/heap can have. Vulkan is also more explicit with the type of descriptors. Whereas on DX12 descriptors are either CBVSRVUAV or sampler. &#xD;&#xA;&#xD;&#xA;DX12 also has a feature where you can sort of bind a CBV on the fly using SetGraphicsRootConstantBufferView. However, the SRV version of this, SetGraphicsRootShaderResourceView, does not work on textures. It's in the docs - but may also take you a couple of hours to figure this out if you're not a careful reader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;*** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, but have similar net result.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        n/a&#xD;&#xA;    VkFramebuffer                       collection of ID3D12Resource&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. &#xD;&#xA;&#xD;&#xA;There's not a direct equivalence between VkFramebuffer and any objects in DX12. A collection of ID3D12Resource that map to RTVs is a loose similarity.&#xD;&#xA;&#xD;&#xA;VkFramebuffer acts more or less like an attachment pool that VkRenderPass references using an index. Subpasses within a VkRenderPass can reference any of the attachments in a VkFramebuffer assuming the same attachment isn't referenced more than once per subpass. Max number of color attachments used at once is limited to VkPhysicalDeviceLimits.maxColorAttachments.&#xD;&#xA;&#xD;&#xA;DX12's render targets are just RTVs that are backed by an ID3D12Resource objects. Max number of color attachments used at once is limited to D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT (8).&#xD;&#xA;&#xD;&#xA;Both APIs require you to specify the render targets/passes at the creation of the pipeline objects. However, Vulkan allows you to use compatible render passes, so you're not locked into the ones you specify during the pipline creation. I haven't tested it on DX12, but I would guess since it's just an RTV, this is also true on DX12." ContentLicense="CC BY-SA 4.0" />
  <row Id="21811" PostHistoryTypeId="24" PostId="4434" RevisionGUID="8998352b-07c3-4ca3-a777-548e64bda042" CreationDate="2018-10-30T11:21:07.900" Comment="Proposed by 6442 approved by 209, 2041 edit id of 446" ContentLicense="CC BY-SA 4.0" />
  <row Id="21821" PostHistoryTypeId="2" PostId="8209" RevisionGUID="402c3e0a-ba9e-473c-ad7a-3671787b1605" CreationDate="2018-10-31T12:20:17.933" UserId="9462" Text="I'm a newbie and I want to open .off file and view the content 3d model using libQGLViewer , qt-creator&#xD;&#xA;&#xD;&#xA;I don't know how to display the 3d model after opening it's .off file &#xD;&#xA;&#xD;&#xA;  QString fileName = QFileDialog::getOpenFileName(this,tr(&quot;Open .off model&quot;), &quot;/home&quot;, tr(&quot;*.off&quot;));&#xD;&#xA;&#xD;&#xA;any help , please" ContentLicense="CC BY-SA 4.0" />
  <row Id="21822" PostHistoryTypeId="1" PostId="8209" RevisionGUID="402c3e0a-ba9e-473c-ad7a-3671787b1605" CreationDate="2018-10-31T12:20:17.933" UserId="9462" Text="qt - view geomview (.off ) file" ContentLicense="CC BY-SA 4.0" />
  <row Id="21823" PostHistoryTypeId="3" PostId="8209" RevisionGUID="402c3e0a-ba9e-473c-ad7a-3671787b1605" CreationDate="2018-10-31T12:20:17.933" UserId="9462" Text="|3d|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21824" PostHistoryTypeId="2" PostId="8210" RevisionGUID="f87ad6a9-77e9-4d47-b3f0-c66940d943e0" CreationDate="2018-10-31T12:57:14.707" UserId="137" Text="From a quick gander through the examples it looks like QGLViewer is a thin wrapper around a opengl window using the legacy api. &#xD;&#xA;&#xD;&#xA;So what you really need is a way to load a .off file to render in legacy opengl. [it looks like a very simple format](https://en.wikipedia.org/wiki/OFF_(file_format)), even simpler than .obj. So simple that IMO it is worth it for you to figure out on your own." ContentLicense="CC BY-SA 4.0" />
  <row Id="21825" PostHistoryTypeId="5" PostId="8201" RevisionGUID="4366cc74-67a2-4d72-a03c-c1c31ee370c4" CreationDate="2018-11-01T05:06:42.807" UserId="3003" Comment="Switch terminology to be correct" Text="Wonder if anyone has experienced this. When generating png image icons for macos. its recommended at 19x19 pixels. However, based on that, the icon (shield) that is generated is pixellated compared with the next in line. I have tried using 38x38, which effectively doubles the pixels. It looks much finer in preview but when attached, it because a large icon cropped off the bottom. Are there are specifics to generating a retina compatible icon for mac status bar?&#xD;&#xA;&#xD;&#xA;[![screenshot of menu bar][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/658Ge.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21826" PostHistoryTypeId="4" PostId="8201" RevisionGUID="4366cc74-67a2-4d72-a03c-c1c31ee370c4" CreationDate="2018-11-01T05:06:42.807" UserId="3003" Comment="Switch terminology to be correct" Text="Resolution issue of generating a PNG icon for macOS menu bar" ContentLicense="CC BY-SA 4.0" />
  <row Id="21831" PostHistoryTypeId="2" PostId="8212" RevisionGUID="d568c6b4-2d1a-424b-886b-70f12e117401" CreationDate="2018-11-01T20:54:22.970" UserId="506" Text="The issue is the difference between pixel and point sizes. On macOS and other Apple platforms, the user interface is measured in points, which don’t necessarily map one-to-one to pixels; on a Retina screen like the one you’re using, 1 point is 2 pixels. Since there’s no way for the system to know whether your image’s scale is the same as the screen’s, it’s assuming that each pixel in your larger image is meant to be one point.&#xD;&#xA;&#xD;&#xA;One way to resolve this would be to explicitly set the [`size`](https://developer.apple.com/documentation/appkit/nsimage/1519987-size) property on your NSImage to the point size your image is supposed to be drawn at, i.e. 19×19; you’d have to handle loading different images for 1x and 2x screens on your own, though, which is inconvenient. A better way would be to use an [asset catalog](https://developer.apple.com/library/archive/documentation/ToolsLanguages/Conceptual/Xcode_Overview/AddingImages.html) in your project, which will let you specify assets for 1x and 2x screens and allow you to load the appropriate image by name.&#xD;&#xA;&#xD;&#xA;As Simon F pointed out, future questions in this vein probably belong on [Stack Overflow](https://stackoverflow.com)—it’s more about API usage than graphics concepts." ContentLicense="CC BY-SA 4.0" />
  <row Id="21832" PostHistoryTypeId="2" PostId="8213" RevisionGUID="760d3250-6972-4193-88d5-d25e57d31fd8" CreationDate="2018-11-02T05:19:58.200" UserId="8699" Text="[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Some context. Above are the code and the resulting image for it in Peter Shirley's Raytracing in one weekend's book. As you can see from the code, he adds in some spheres. And yet in the final image there are 2 ellipsoids side by side. I just can't fathom why it is so, no matter how many time I looked at the code. Can anyone explain to me? Here's the link to the source code.&#xD;&#xA;https://github.com/petershirley/raytracinginoneweekend&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FEEVq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/yBUh2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21833" PostHistoryTypeId="1" PostId="8213" RevisionGUID="760d3250-6972-4193-88d5-d25e57d31fd8" CreationDate="2018-11-02T05:19:58.200" UserId="8699" Text="Raytracing: why are the spheres in the image below appear stretched?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21834" PostHistoryTypeId="3" PostId="8213" RevisionGUID="760d3250-6972-4193-88d5-d25e57d31fd8" CreationDate="2018-11-02T05:19:58.200" UserId="8699" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21835" PostHistoryTypeId="2" PostId="8214" RevisionGUID="4bdc86ee-b10f-4e24-8f47-aad1e1d39689" CreationDate="2018-11-02T07:07:36.833" UserId="182" Text="Shapes appearing stretched in the periphery is a consequence of perspective projection. The wider the field of view (FOV) is, the stronger the stretching effect gets.&#xD;&#xA;&#xD;&#xA;This is especially noticeable with wide FOV, like 90° and above." ContentLicense="CC BY-SA 4.0" />
  <row Id="21838" PostHistoryTypeId="5" PostId="8214" RevisionGUID="92fd1110-b73a-42af-8133-4083acd38f7e" CreationDate="2018-11-02T07:50:54.963" UserId="182" Comment="Added an example and pictures to illustrate." Text="Shapes appearing stretched in the periphery is a consequence of perspective projection. The wider the field of view (FOV) is, the stronger the stretching effect gets.&#xD;&#xA;&#xD;&#xA;To demonstrate the effect I wrote a quick example on ShaderToy: https://www.shadertoy.com/view/MltBW2&#xD;&#xA;&#xD;&#xA;As you can see on the images below (corresponding to FOV of 40, 80 and 120; if I didn't make any mistake), this becomes especially noticeable with wide FOV, like 90° and above.&#xD;&#xA;&#xD;&#xA;[![FOV 40°][1]][4]&#xD;&#xA;[![FOV 80°][2]][4]&#xD;&#xA;[![FOV 120°][3]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/99bS1.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/pSDlz.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/K2fI7.png&#xD;&#xA;  [4]: https://www.shadertoy.com/view/MltBW2" ContentLicense="CC BY-SA 4.0" />
  <row Id="21841" PostHistoryTypeId="2" PostId="8216" RevisionGUID="29776d20-4ddd-46f5-84d0-9eae1ab8b3bd" CreationDate="2018-11-02T21:08:20.193" UserId="9628" Text="The Flurry screensaver written by Calum Robinson is available as a part of the XScreenSaver package. You can download its source code from https://www.jwz.org/xscreensaver/download.html&#xD;&#xA;&#xD;&#xA;The flurry* files are in the hacks/glx directory. It's not an easy job to reverse engineer the algorithm from the source code, but debugging might help." ContentLicense="CC BY-SA 4.0" />
  <row Id="21842" PostHistoryTypeId="50" PostId="8014" RevisionGUID="fba9af45-0ce8-40d0-a28d-c69604ec05d0" CreationDate="2018-11-03T00:01:45.747" UserId="-1" />
  <row Id="21844" PostHistoryTypeId="50" PostId="6373" RevisionGUID="7c0ba7cc-2314-4128-b62c-db01fbc31f25" CreationDate="2018-11-03T06:00:39.260" UserId="-1" />
  <row Id="21845" PostHistoryTypeId="2" PostId="8217" RevisionGUID="61b563f6-6e0f-4a3d-9126-cf6600a7e10a" CreationDate="2018-11-03T11:05:30.260" UserId="9631" Text="I am well aware that there are several ways to find the tangents to a Bezier curve. However, I choose to just substitute the result of differentiating the Bezier curve equation.&#xD;&#xA;&#xD;&#xA;So, given four control points, `ptOne`, `ptTwo`, `ptThree` and `ptFour`:&#xD;&#xA;&#xD;&#xA;    // Differentiate x with respect to t&#xD;&#xA;    float dxdt = -3*(1 - t)*(1 - t)*ptOne.x&#xD;&#xA;    + 3*(1 - 4*t + 3*t*t)*ptTwo.x&#xD;&#xA;    + 3*(2*t - 3*t*t)*ptThree.x&#xD;&#xA;    + 3*t*t*ptFour.x;&#xD;&#xA;    &#xD;&#xA;    // Differentiate y with respect to t&#xD;&#xA;    float dydt = -3*(1 - t)*(1 - t)*ptOne.y&#xD;&#xA;    + 3*(1 - 4*t + 3*t*t)*ptTwo.y&#xD;&#xA;    + 3*(2*t - 3*t*t)*ptThree.y&#xD;&#xA;    + 3*t*t*ptFour.y;&#xD;&#xA;    &#xD;&#xA;    // Find the tangent, dy/dx&#xD;&#xA;    float dydx = dydt * (1/dxdt);&#xD;&#xA;&#xD;&#xA;    // Find the rotation angle in degrees&#xD;&#xA;    float angle = atan(dydx) * 180/M_PI;&#xD;&#xA;&#xD;&#xA;The strange thing is that this does not seem to be working for all kinds of curve. For example, if I draw a curve like this, with the first control point being the second leftmost point and then in a clockwise direction:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;and attempt to draw the tangents:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;You can see that some tangents (in particular, the first two and very last one) are not oriented in the right direction. Why might this be happening? I triple checked my differentiation and can't find anything wrong...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eSfoL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/i0Kdk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21846" PostHistoryTypeId="1" PostId="8217" RevisionGUID="61b563f6-6e0f-4a3d-9126-cf6600a7e10a" CreationDate="2018-11-03T11:05:30.260" UserId="9631" Text="Wrong tangential directions for cubic bezier curve" ContentLicense="CC BY-SA 4.0" />
  <row Id="21847" PostHistoryTypeId="3" PostId="8217" RevisionGUID="61b563f6-6e0f-4a3d-9126-cf6600a7e10a" CreationDate="2018-11-03T11:05:30.260" UserId="9631" Text="|opengl|mathematics|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21848" PostHistoryTypeId="6" PostId="8217" RevisionGUID="5df93864-90fb-4818-8c98-2db95276b4da" CreationDate="2018-11-03T13:49:02.847" UserId="2654" Comment="edited tags" Text="|mathematics|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21850" PostHistoryTypeId="50" PostId="5697" RevisionGUID="aa6f9423-4143-4c8c-b7d7-90b31733f07a" CreationDate="2018-11-04T01:00:23.160" UserId="-1" />
  <row Id="21851" PostHistoryTypeId="2" PostId="8218" RevisionGUID="7a34bf67-d711-44b9-9c72-119731325d73" CreationDate="2018-11-04T08:16:36.350" UserId="1613" Text="Yes, your understanding it correct. The Laplace-Beltrami depends on the current state $x$ and you have to recompute $L$ if $x$ changes. Therefore you cannot write matix of $\Delta$ without knowing the state $x$." ContentLicense="CC BY-SA 4.0" />
  <row Id="21852" PostHistoryTypeId="5" PostId="8218" RevisionGUID="80677776-ebd6-4b8f-b8c6-59ad7af81610" CreationDate="2018-11-04T13:15:15.707" UserId="1613" Comment="added 1613 characters in body" Text="Yes, your understanding it correct. The Laplace-Beltrami depends on the current state $x$ and you have to recompute $L$ if $x$ changes. Therefore you cannot write matix of $\Delta$ without knowing the state $x$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To expand on solving $\frac{\partial x}{\partial t} = -\Delta x$:&#xD;&#xA;&#xD;&#xA;Discretization in space turns $\Delta$ to $L$, discretization in time turns $\frac{\partial x}{\partial t}$ to $\frac{x_{n+1} - x_n}{h}$ and decide if we evaluate the right hand side at time $t_n$ or $t_{n+1}$&#xD;&#xA;&#xD;&#xA;**Option 1 = Forward Euler**:&#xD;&#xA;$$&#xD;&#xA;x_{n+1} - x_n = h L_n x_n&#xD;&#xA;$$&#xD;&#xA;where $L_n = L(x_n)$, $L$ is considered as a function of the state $x$. As you have mentioned this method can be unstable if we take too big step $h$. Therefore, we often resort to the second option.&#xD;&#xA;&#xD;&#xA;**Option 2 = Backward Euler**:&#xD;&#xA;$$&#xD;&#xA;x_{n+1} - x_n = h L_{n+1} x_{n+1}&#xD;&#xA;$$&#xD;&#xA;Because $L_{n+1}$ depends on $x_{n+1}$ the above equation is non-linear system, we cannot solve it with a simple linear solve.&#xD;&#xA;&#xD;&#xA;The common approach is to Taylor expand $L$ around the point $x_n$, general Taylor expansion around point $x$ is&#xD;&#xA;$$&#xD;&#xA;L(x + \Delta x) = L(x) + \nabla L(x) \cdot \Delta x + \dots&#xD;&#xA;$$&#xD;&#xA;therefore for $x= x_n$ and $\Delta x = x_{n+1} - x_n$ we get&#xD;&#xA;$$&#xD;&#xA;L_{n+1} = L(x_{n+1}) = L(x_n + \Delta x) = L(x_n) + \nabla L(x_n) \cdot \Delta x + \dots&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The simplest thing to do is to take just the first term of the Taylor expansion, i.e. we replace $L_{n+1}$ with $L_n$. This way, we end up with a linear problem&#xD;&#xA;$$&#xD;&#xA;x_{n+1} - x_n = h L_{n} x_{n+1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You can take higher order terms or solve the Backward Euler equation with non-linear solver. However, in your case that is probably unnecessary and the headache of computing the gradient of $L$ is not worth it(I might be wrong here, I do not have hands on experience with solving this equation). " ContentLicense="CC BY-SA 4.0" />
  <row Id="21853" PostHistoryTypeId="2" PostId="8219" RevisionGUID="abacf763-1e9d-4328-b94c-981cfbfbd70d" CreationDate="2018-11-04T20:18:11.737" UserId="4650" Text="I'm trying to compute a projection matrix to transform from view space to NDC with a near clip plane at -1 and far plane at +1. The general form of this matrix (disregarding aspect ratio and focal length) should be&#xD;&#xA;&#xD;&#xA; $\begin{bmatrix}1&amp;0&amp;0&amp;0\\0&amp;1&amp;0&amp;0\\0&amp;0&amp;A&amp;B\\0&amp;0&amp;-1&amp;0\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;I followed SongHo's guide at http://www.songho.ca/opengl/gl_projectionmatrix.html which sets $A=-(f+n)/(f-n)$ and $B=-2fn/(f-n)$. &#xD;&#xA;&#xD;&#xA;However, setting the near clip plane at $n=-1$ and $f=-10$ (in view space) and using these $A$ and $B$, I get points with $z$ values on the interval $[-1, -10]$ transformed to $[3.04, 1.04]$ (after homogenisation). &#xD;&#xA;&#xD;&#xA;When I do the derivations myself, I'd like to set $A=(n+f)/(n-f)$ and $B=(-2fn)/(n-f)$ instead, which indeed transforms to $[-1,1]$ instead.&#xD;&#xA;&#xD;&#xA;Am I doing something wrong?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21854" PostHistoryTypeId="1" PostId="8219" RevisionGUID="abacf763-1e9d-4328-b94c-981cfbfbd70d" CreationDate="2018-11-04T20:18:11.737" UserId="4650" Text="How to compute A and B in projection matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="21855" PostHistoryTypeId="3" PostId="8219" RevisionGUID="abacf763-1e9d-4328-b94c-981cfbfbd70d" CreationDate="2018-11-04T20:18:11.737" UserId="4650" Text="|3d|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21856" PostHistoryTypeId="50" PostId="7897" RevisionGUID="613d930e-5acd-457a-bedd-0c31c48ff902" CreationDate="2018-11-04T21:00:39.570" UserId="-1" />
  <row Id="21857" PostHistoryTypeId="2" PostId="8220" RevisionGUID="a9e519d0-b57b-47b0-a9f3-912dfafb5a30" CreationDate="2018-11-04T21:01:35.200" UserId="9637" Text="Note: I'll be using column vector notation (eg. $Ax=y$), thus if you are using row notation, transpose the matrix and multiply from the left instead of the right. (eg. $y=x^TA^T$)&#xD;&#xA;&#xD;&#xA;A perspective transformation matrix transforms a view frustum into a rectangular view volume. Note that the resulting view volume is **not** centered at 0, and might not be a cube.&#xD;&#xA;&#xD;&#xA;One *example* of a perspective transformation matrix. There are **many more**, and yours is included.&#xD;&#xA;&#xD;&#xA;Let $l=left,\\ r = right,\\ b = bottom,\\ t = top,\\ n = near,\\ f = far$&#xD;&#xA;&#xD;&#xA;$M_{persp}=\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Since the resulting view volume is not the canonical view volume, we need to apply another matrix.&#xD;&#xA;&#xD;&#xA;A orthographic transformation matrix transforms a rectangular view volume into a cubic view volume with two corners at (-1, -1, -1) and (1, 1, 1), which happens to be the canonical view volume.&#xD;&#xA;&#xD;&#xA;Intuitively it will need one translation and one scaling.&#xD;&#xA;&#xD;&#xA;$\text{T}_{ortho} = S\left(\frac{2}{r-l},\frac{2}{t-b},\frac{2}{n-f}\right)T\left(\frac{-(l+r)}{2},\frac{-(b+t)}{2}\frac{-(n+f)}{2}\right)$&#xD;&#xA;&#xD;&#xA;$M_{ortho} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    1 &amp; &amp; &amp; \frac{-(l+r)}{2} \\&#xD;&#xA;    &amp; 1 &amp; &amp; \frac{-(b+t)}{2} \\&#xD;&#xA;    &amp; &amp; 1 &amp; \frac{-(n+f)}{2} \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Now you can combine them together to form a **perspective projection** matrix.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}$&#xD;&#xA;&#xD;&#xA;$M_{proj} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    1 &amp; &amp; &amp; \frac{-(l+r)}{2} \\&#xD;&#xA;    &amp; 1 &amp; &amp; \frac{-(b+t)}{2} \\&#xD;&#xA;    &amp; &amp; 1 &amp; \frac{-(n+f)}{2} \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;If you have a free-moving camera you will need a camera matrix too, thus the final projection matrix centered on the camera is.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}M_{camera}$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21858" PostHistoryTypeId="5" PostId="8220" RevisionGUID="f0de9481-062b-49ea-ae82-bf8d52000175" CreationDate="2018-11-04T21:07:43.100" UserId="9637" Comment="added 9 characters in body" Text="Note: I'll be using column vector notation (eg. $Ax=y$), thus if you are using row notation, transpose the matrix and multiply from the left instead of the right. (eg. $y=x^TA^T$)&#xD;&#xA;&#xD;&#xA;A perspective transformation matrix transforms a view frustum into a rectangular view volume. Note that the resulting view volume might **not** be a cube and might **not** be centered at 0.&#xD;&#xA;&#xD;&#xA;One *example* of a perspective transformation matrix. There are **many more**, and yours is included.&#xD;&#xA;&#xD;&#xA;Let $l=left,\\ r = right,\\ b = bottom,\\ t = top,\\ n = near,\\ f = far$&#xD;&#xA;&#xD;&#xA;$M_{persp}=\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Since the resulting view volume is not the canonical view volume, we need to apply another matrix.&#xD;&#xA;&#xD;&#xA;A orthographic transformation matrix transforms a rectangular view volume into a cubic view volume with two corners at (-1, -1, -1) and (1, 1, 1), which happens to be the canonical view volume.&#xD;&#xA;&#xD;&#xA;Intuitively it will need one translation and one scaling.&#xD;&#xA;&#xD;&#xA;$\text{T}_{ortho} = S\left(\frac{2}{r-l},\frac{2}{t-b},\frac{2}{n-f}\right)T\left(\frac{-(l+r)}{2},\frac{-(b+t)}{2}\frac{-(n+f)}{2}\right)$&#xD;&#xA;&#xD;&#xA;$M_{ortho} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    1 &amp; &amp; &amp; \frac{-(l+r)}{2} \\&#xD;&#xA;    &amp; 1 &amp; &amp; \frac{-(b+t)}{2} \\&#xD;&#xA;    &amp; &amp; 1 &amp; \frac{-(n+f)}{2} \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Now you can combine them together to form a **perspective projection** matrix.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}$&#xD;&#xA;&#xD;&#xA;$M_{proj} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    1 &amp; &amp; &amp; \frac{-(l+r)}{2} \\&#xD;&#xA;    &amp; 1 &amp; &amp; \frac{-(b+t)}{2} \\&#xD;&#xA;    &amp; &amp; 1 &amp; \frac{-(n+f)}{2} \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;If you have a free-moving camera you will need a camera matrix too, thus the final projection matrix centered on the camera is.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}M_{camera}$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21859" PostHistoryTypeId="5" PostId="8220" RevisionGUID="3b2594c8-4337-48ef-a624-bb5648b01af2" CreationDate="2018-11-04T21:21:39.103" UserId="9637" Comment="added 9 characters in body" Text="The matrix you have given looks like a **perspective transformation** matrix, not a **projection matrix**. This answer might help you derive the full projection matrix.&#xD;&#xA;&#xD;&#xA;Note: I'll be using column vector notation (eg. $Ax=y$), thus if you are using row notation, transpose the matrix and multiply from the left instead of the right. (eg. $y=x^TA^T$)&#xD;&#xA;&#xD;&#xA;A perspective transformation matrix transforms a view frustum into a rectangular view volume. Note that the resulting view volume might **not** be a cube and might **not** be centered at 0.&#xD;&#xA;&#xD;&#xA;One *example* of a perspective transformation matrix. There are **many more**, and yours is included.&#xD;&#xA;&#xD;&#xA;Let $l=left,\\ r = right,\\ b = bottom,\\ t = top,\\ n = near,\\ f = far$&#xD;&#xA;&#xD;&#xA;$M_{persp}=\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Since the resulting view volume is not the canonical view volume, we need to apply another matrix.&#xD;&#xA;&#xD;&#xA;A orthographic transformation matrix transforms a rectangular view volume into a cubic view volume with two corners at (-1, -1, -1) and (1, 1, 1), which happens to be the canonical view volume.&#xD;&#xA;&#xD;&#xA;Intuitively it will need one translation and one scaling.&#xD;&#xA;&#xD;&#xA;$\text{T}_{ortho} = S\left(\frac{2}{r-l},\frac{2}{t-b},\frac{2}{n-f}\right)T\left(\frac{-(l+r)}{2},\frac{-(b+t)}{2}\frac{-(n+f)}{2}\right)$&#xD;&#xA;&#xD;&#xA;$M_{ortho} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    1 &amp; &amp; &amp; \frac{-(l+r)}{2} \\&#xD;&#xA;    &amp; 1 &amp; &amp; \frac{-(b+t)}{2} \\&#xD;&#xA;    &amp; &amp; 1 &amp; \frac{-(n+f)}{2} \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;$M_{ortho} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; -\frac{l+r}{r-l} \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; -\frac{t+b}{t-b} \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; -\frac{n+f}{n-f}\\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Now you can combine them together to form a **perspective projection** matrix.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}$&#xD;&#xA;&#xD;&#xA;$M_{proj} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; -\frac{l+r}{r-l} \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; -\frac{t+b}{t-b} \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; -\frac{n+f}{n-f}\\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;$M_{proj} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2n}{r-l}&amp; &amp; \frac{l+r}{l-r} &amp; \\&#xD;&#xA;    &amp; \frac{2n}{t-b} &amp; \frac{b+t}{b-t} &amp; \\&#xD;&#xA;    &amp; &amp; \frac{n+f}{n-f} &amp; \frac{2fn}{f-n}\\&#xD;&#xA;    &amp; &amp; 1 &amp;&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;If you have a free-moving camera you will need a camera matrix too, thus the final projection matrix centered on the camera is.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}M_{camera}$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21860" PostHistoryTypeId="5" PostId="8220" RevisionGUID="47137e7b-b6ef-4c70-be50-35849a4e748e" CreationDate="2018-11-04T21:40:54.783" UserId="9637" Comment="deleted 172 characters in body" Text="Note: I'll be using column vector notation (eg. $Ax=y$), thus if you are using row notation, transpose the matrix and multiply from the left instead of the right. (eg. $y=x^TA^T$)&#xD;&#xA;&#xD;&#xA;A perspective transformation matrix transforms a view frustum into a rectangular view volume. Note that the resulting view volume might **not** be a cube and might **not** be centered at 0.&#xD;&#xA;&#xD;&#xA;One *example* of a perspective transformation matrix. There are **many more**, and yours is included.&#xD;&#xA;&#xD;&#xA;Let $l=left,\\ r = right,\\ b = bottom,\\ t = top,\\ n = near,\\ f = far$&#xD;&#xA;&#xD;&#xA;$M_{persp}=\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Since the resulting view volume is not the canonical view volume, we need to apply another matrix.&#xD;&#xA;&#xD;&#xA;A orthographic transformation matrix transforms a rectangular view volume into a cubic view volume with two corners at (-1, -1, -1) and (1, 1, 1), which happens to be the canonical view volume.&#xD;&#xA;&#xD;&#xA;Intuitively it will need one translation and one scaling.&#xD;&#xA;&#xD;&#xA;$\text{T}_{ortho} = S\left(\frac{2}{r-l},\frac{2}{t-b},\frac{2}{n-f}\right)T\left(\frac{-(l+r)}{2},\frac{-(b+t)}{2}\frac{-(n+f)}{2}\right)$&#xD;&#xA;&#xD;&#xA;$M_{ortho} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    1 &amp; &amp; &amp; \frac{-(l+r)}{2} \\&#xD;&#xA;    &amp; 1 &amp; &amp; \frac{-(b+t)}{2} \\&#xD;&#xA;    &amp; &amp; 1 &amp; \frac{-(n+f)}{2} \\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;$M_{ortho} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; -\frac{l+r}{r-l} \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; -\frac{t+b}{t-b} \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; -\frac{n+f}{n-f}\\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Now you can combine them together to form a **perspective projection** matrix.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}$&#xD;&#xA;&#xD;&#xA;$M_{proj} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2}{r-l}&amp; &amp; &amp; -\frac{l+r}{r-l} \\&#xD;&#xA;    &amp; \frac{2}{t-b} &amp; &amp; -\frac{t+b}{t-b} \\&#xD;&#xA;    &amp; &amp; \frac{2}{n-f} &amp; -\frac{n+f}{n-f}\\&#xD;&#xA;    &amp; &amp; &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1&amp; &amp; &amp; \\&#xD;&#xA; &amp;1&amp; &amp; \\&#xD;&#xA; &amp; &amp;\frac{n+f}{n}&amp;-f\\&#xD;&#xA; &amp; &amp;\frac{1}{n}&amp; &#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;$M_{proj} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;    \frac{2n}{r-l}&amp; &amp; \frac{l+r}{l-r} &amp; \\&#xD;&#xA;    &amp; \frac{2n}{t-b} &amp; \frac{b+t}{b-t} &amp; \\&#xD;&#xA;    &amp; &amp; \frac{n+f}{n-f} &amp; \frac{2fn}{f-n}\\&#xD;&#xA;    &amp; &amp; 1 &amp;&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;If you have a free-moving camera you will need a camera matrix too, thus the final projection matrix centered on the camera is.&#xD;&#xA;&#xD;&#xA;$M_{proj} = M_{ortho}M_{persp}M_{camera}$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21861" PostHistoryTypeId="2" PostId="8221" RevisionGUID="1e099d77-f83d-4e03-8054-a98a1bad27af" CreationDate="2018-11-05T05:26:49.550" UserId="9631" Text="Using what Rahul kindly suggested in the comments, I realised that my tangent can be rotated in the opposite direction for two cases:&#xD;&#xA;&#xD;&#xA;1. if `dy/dt` and `dx/dt` are both negative, yet `dy/dx` ends up being positive&#xD;&#xA;2. if `dy/dt` is negative and `dx/dt` is positive, so the overall `dy/dx` is negative&#xD;&#xA;&#xD;&#xA;This is because my angle calculation, which is done by `float angle = atan(dydx) * 180/M_PI;` will only calculate acute angles from the horizontal, and hence miss out the opposite cases.&#xD;&#xA;&#xD;&#xA;Thanks a bunch!" ContentLicense="CC BY-SA 4.0" />
  <row Id="21865" PostHistoryTypeId="5" PostId="8209" RevisionGUID="fc5dbfde-77f2-47ae-9b28-02c216aba928" CreationDate="2018-11-05T20:09:53.327" UserId="231" Comment="Tidying and removing &quot;newbie&quot; and &quot;thanks&quot; comments" Text="I want to open a .off file and view the content 3d model using libQGLViewer, qt-creator.&#xD;&#xA;&#xD;&#xA;I don't know how to display the 3d model after opening its .off file.&#xD;&#xA;&#xD;&#xA;    QString fileName = QFileDialog::getOpenFileName(this,tr(&quot;Open .off model&quot;), &quot;/home&quot;, tr(&quot;*.off&quot;));" ContentLicense="CC BY-SA 4.0" />
  <row Id="21866" PostHistoryTypeId="2" PostId="8223" RevisionGUID="fb96ba0b-8972-41ce-bbc3-b6a92690f3fe" CreationDate="2018-11-06T01:47:24.333" UserId="110" Text="I understand that HDR files are images encoded with a higher precision in order to keep more details.  &#xD;&#xA;When loading such images in real-time rendering applications using common Graphics APIs (DirectX, OpenGL, Vulkan), which are the &quot;HDR texture formats&quot; that ensure details will be preserved?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21867" PostHistoryTypeId="1" PostId="8223" RevisionGUID="fb96ba0b-8972-41ce-bbc3-b6a92690f3fe" CreationDate="2018-11-06T01:47:24.333" UserId="110" Text="Which graphics APIs texture formats are HDR texture formats?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21868" PostHistoryTypeId="3" PostId="8223" RevisionGUID="fb96ba0b-8972-41ce-bbc3-b6a92690f3fe" CreationDate="2018-11-06T01:47:24.333" UserId="110" Text="|texture|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21869" PostHistoryTypeId="2" PostId="8224" RevisionGUID="995829f2-8154-415e-a6e7-33d47eeb34a4" CreationDate="2018-11-06T03:53:38.973" UserId="3003" Text="In general, using floating point textures will help preserve HDR values. They can be 16-bit or 32-bit floats for the color channels, usually. In OpenGL you could choose the type to be `GL_FLOAT` for 32-bits per channel or `GL_HALF_FLOAT` for 16-bits per channel. In my experience, for image processing, 16-bits is usually enough and is half as much data." ContentLicense="CC BY-SA 4.0" />
  <row Id="21870" PostHistoryTypeId="2" PostId="8225" RevisionGUID="194c4104-1152-484c-a0da-68e7e61ad329" CreationDate="2018-11-06T09:50:54.360" UserId="9647" Text="I have a scene with camera facing billboards drawn with depth write off so they appear on top of other objects. I would like to draw each sprite so that any  obscured pixels are drawn with a very low opacity. So that obscured portions of each sprite are visible but very faint.&#xD;&#xA;&#xD;&#xA;Could anyone point me in the direction of a solution? I am using Threejs but I imagine the solution will be shader (glsl) based. I already have the depth texture for the scene available.&#xD;&#xA;&#xD;&#xA;[![Diagram showing desired effect][1]][1]&#xD;&#xA;&#xD;&#xA;Sketchfab implements this with its annotations, which is the effect I would like to acheive.&#xD;&#xA;&#xD;&#xA;[![Sketchfab example of desired effect][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2iJbr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jItdi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21871" PostHistoryTypeId="1" PostId="8225" RevisionGUID="194c4104-1152-484c-a0da-68e7e61ad329" CreationDate="2018-11-06T09:50:54.360" UserId="9647" Text="Using depth texture to mask local pixels" ContentLicense="CC BY-SA 4.0" />
  <row Id="21872" PostHistoryTypeId="3" PostId="8225" RevisionGUID="194c4104-1152-484c-a0da-68e7e61ad329" CreationDate="2018-11-06T09:50:54.360" UserId="9647" Text="|glsl|webgl|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21873" PostHistoryTypeId="2" PostId="8226" RevisionGUID="f22df5c6-8c0f-4f17-adaa-80892825d2ba" CreationDate="2018-11-06T14:18:57.807" UserId="9581" Text="I import a mesh in NVIDIA's FleX, rotate it and store it on disk; I call this mesh `X`. I also import the mesh in Blender and rotate it the same amount; I call this mesh `Y`. After I imported `X` in Blender I realized that `X` has a different rotation which means that FleX is either using a different global axes (I think it's `-Y` forward and `Z` up) or it applies the rotations in a different order or a combination of both. So I am pretty confused now. I do not want to change anything on the FleX side. However, I want to rotate `Y` in a way that it matches with what FleX exports (`X`) after rotation. I also tried with Quaternions but I'm still unable to figure out the way FleX is transforming the object. The only thing that I've been able to figure out empirically is that the value for `rx` rotation is applied the same way for both FleX and Blender. This means that objects `X` and `Y` would overlap completely if imported in on scene in Blender. &#xD;&#xA;&#xD;&#xA;My goal is to rotate the object in FleX so that object `Y`'s rotation matches exactly with object `X` when I import it in Blender. Can someone help me figure out how the rotations are applied in FleX for `ry` and `rz`?&#xD;&#xA;&#xD;&#xA;**Note** that I am not changing the rotation order in Blender and I'm using the default `XYZ` rotation.&#xD;&#xA;&#xD;&#xA;Here I are some images of the visual differences between FleX and Blender for such transformations:&#xD;&#xA;&#xD;&#xA;Euler rotation vector: `[0, 89.9, 0]` in for object `X` in Blender.&#xD;&#xA;&#xD;&#xA;After applying the rotation in Blender (object `X`):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After applying the same rotation (`[0, 89.9, 0]`) in FleX and importing the object `Y` in Blender:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Euler rotation vector: `[0, 0, 89.9]` for object `X` in Blender.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;After applying the same rotation (`[0, 0, 89.9]`) in FleX and importing the object `Y` in Blender:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;It might look it is easy to guess from the images that FleX swaps the `ry` and `rz` rotation to do the rotation. If I also swap the rotations in Blender then both `X` and `Y` totally overlap with each other. However, if the rotation vector is `[-43.964176, 20.641195, -1.2689421]` `X` and `Y` do not overlap anymore and discrepancies start to show up:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The discrepancies are more visible if I put a cloth on `Y` in FleX, import the cloth and `X` in Blender and rotate `X` by [-43.964176, -1.2689421, 20.641195]` (notice that I've swapped `ry` and `rz`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Note that if I import `Y` here, the cloth would be perfectly covering it while touching it on the surface:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Although you might need more information to figure out exactly what's going out but below I post the code that is used in FleX to compute its rotation matrices. The top one is used when Euler angles are used and the second one is used when Quaternions are input:&#xD;&#xA;&#xD;&#xA;    // generate a rotation matrix around an axis, from PBRT p74&#xD;&#xA;    inline Mat44 RotationMatrix(float angle, const Vec3&amp; axis)&#xD;&#xA;    {&#xD;&#xA;    	Vec3 a = Normalize(axis);&#xD;&#xA;    	float s = sinf(angle);&#xD;&#xA;    	float c = cosf(angle);&#xD;&#xA;    &#xD;&#xA;    	float m[4][4];&#xD;&#xA;    &#xD;&#xA;    	m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;&#xD;&#xA;    	m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;&#xD;&#xA;    	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;&#xD;&#xA;    	m[0][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;&#xD;&#xA;    	m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;&#xD;&#xA;    	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;&#xD;&#xA;    	m[1][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;&#xD;&#xA;    	m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;&#xD;&#xA;    	m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;&#xD;&#xA;    	m[2][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[3][0] = 0.0f;&#xD;&#xA;    	m[3][1] = 0.0f;&#xD;&#xA;    	m[3][2] = 0.0f;&#xD;&#xA;    	m[3][3] = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return Mat44(&amp;m[0][0]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    inline Mat44 RotationMatrix(Quat q)&#xD;&#xA;    {&#xD;&#xA;    	Matrix33 rotation(q);&#xD;&#xA;    &#xD;&#xA;    	Matrix44 m;&#xD;&#xA;    	m.SetAxis(0, rotation.cols[0]);&#xD;&#xA;    	m.SetAxis(1, rotation.cols[1]);&#xD;&#xA;    	m.SetAxis(2, rotation.cols[2]);&#xD;&#xA;    	m.SetTranslation(Point3(0.0f));&#xD;&#xA;    &#xD;&#xA;    	return m;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's how I apply the Euler rotation vector:&#xD;&#xA;&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));&#xD;&#xA;&#xD;&#xA;And I think this should be how `Transform()` is defined:&#xD;&#xA;&#xD;&#xA;    void Mesh::Transform(const Matrix44&amp; m)&#xD;&#xA;    {&#xD;&#xA;        for (uint32_t i=0; i &lt; m_positions.size(); ++i)&#xD;&#xA;        {&#xD;&#xA;            m_positions[i] = m*m_positions[i];&#xD;&#xA;            m_normals[i] = m*m_normals[i];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BoZEo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FDQIH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HJYPn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/lU597.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/27rIH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/DxlAh.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/hhzeO.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="21874" PostHistoryTypeId="1" PostId="8226" RevisionGUID="f22df5c6-8c0f-4f17-adaa-80892825d2ba" CreationDate="2018-11-06T14:18:57.807" UserId="9581" Text="How to rotate a shape in another 3D software so that the rotation matches with the rotation in Blender?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21875" PostHistoryTypeId="3" PostId="8226" RevisionGUID="f22df5c6-8c0f-4f17-adaa-80892825d2ba" CreationDate="2018-11-06T14:18:57.807" UserId="9581" Text="|3d|transformations|mathematics|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21877" PostHistoryTypeId="2" PostId="8228" RevisionGUID="6b893668-4958-443e-ade2-2773857db5d3" CreationDate="2018-11-06T14:43:46.397" UserId="8394" Text="Use the depth texture you mentioned, comparing it to the fragment's current depth to apply an alpha factor to your color. Remember to enable blending on the host. You can also upload the color texture and apply a more controlled blending on the shader.&#xD;&#xA;&#xD;&#xA;The shader code involved would look like this:&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    out vec4 finalColor;&#xD;&#xA;    &#xD;&#xA;    ...&#xD;&#xA;    &#xD;&#xA;    in vec2 screenUV;&#xD;&#xA;    &#xD;&#xA;    ...&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D depthTexture;&#xD;&#xA;    &#xD;&#xA;    ...&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	float texDepth = texture(depthTexture, screenUV).r;&#xD;&#xA;    	float alpha = texDepth &lt; gl_FragDepth? 0.5 : 1.0;&#xD;&#xA;    &#xD;&#xA;    	...&#xD;&#xA;    &#xD;&#xA;    	finalColor = vec4(..., alpha);&#xD;&#xA;    	&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="21880" PostHistoryTypeId="2" PostId="8229" RevisionGUID="a641be81-ce5f-42af-9aa7-a0f8e936af94" CreationDate="2018-11-06T16:40:43.313" UserId="9581" Text="I had to change the order of inputs to `def euler_to_quaternion` as follow and have to convert the inputs to radians:&#xD;&#xA;&#xD;&#xA;    def euler_to_quaternion(roll, pitch, yaw):&#xD;&#xA;&#xD;&#xA;            qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;            qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)&#xD;&#xA;            qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)&#xD;&#xA;            qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)&#xD;&#xA;    &#xD;&#xA;            return [qx, qy, qz, qw]&#xD;&#xA;&#xD;&#xA;Also, quaternion_to_euler was returning degrees and I had to change it to radians:&#xD;&#xA;&#xD;&#xA;    def quaternion_to_euler(x, y, z, w):&#xD;&#xA;    &#xD;&#xA;        t0 = +2.0 * (w * x + y * z)&#xD;&#xA;        t1 = +1.0 - 2.0 * (x * x + y * y)&#xD;&#xA;        roll = math.atan2(t0, t1)&#xD;&#xA;        t2 = +2.0 * (w * y - z * x)&#xD;&#xA;        t2 = +1.0 if t2 &gt; +1.0 else t2&#xD;&#xA;        t2 = -1.0 if t2 &lt; -1.0 else t2&#xD;&#xA;        pitch = math.asin(t2)&#xD;&#xA;        t3 = +2.0 * (w * z + x * y)&#xD;&#xA;        t4 = +1.0 - 2.0 * (y * y + z * z)&#xD;&#xA;        yaw = math.atan2(t3, t4)&#xD;&#xA;        return [yaw, pitch, roll]" ContentLicense="CC BY-SA 4.0" />
  <row Id="21881" PostHistoryTypeId="6" PostId="8226" RevisionGUID="d76863f8-ee8f-4ee7-ae5c-e8f2e6fb042e" CreationDate="2018-11-06T18:52:22.893" UserId="9581" Comment="edited tags" Text="|3d|transformations|mathematics|geometry|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21885" PostHistoryTypeId="5" PostId="8226" RevisionGUID="4efce1bf-0264-468e-bcf1-2f82350a959e" CreationDate="2018-11-07T04:07:56.773" UserId="9581" Comment="added 1827 characters in body" Text="I import a mesh in Blender, export it with setting `axis_forward='-Z', axis_up='Y'`, import in NVIDIA's FleX, rotate it and store it on disk; I call this mesh `X`. I also import the mesh in Blender and rotate it the same amount; I call this mesh `Y`. After I imported `X` in Blender I realized that `X` has a different rotation which means that FleX is either using a different global axes (I think it's `-Y` forward and `Z` up) or it applies the rotations in a different order or a combination of both. So I am pretty confused now. I do not want to change anything on the FleX side. However, I want to rotate `Y` in a way that it matches with what FleX exports (`X`) after rotation. I also tried with Quaternions but I'm still unable to figure out the way FleX is transforming the object. The only thing that I've been able to figure out empirically is that the value for `rx` rotation is applied the same way for both FleX and Blender. This means that objects `X` and `Y` would overlap completely if imported in on scene in Blender. &#xD;&#xA;&#xD;&#xA;**My goal** is to rotate the object in FleX so that object `Y`'s rotation matches exactly with object `X` when I import `Y` in Blender. For instance, I want FleX rotate the object the same way as Blender rotates it with the Euler rotation vector of `[rx, ry, rz]`. How can I achieve this?&#xD;&#xA;&#xD;&#xA;**Note** that I am not changing the rotation order in Blender and I'm using the default `XYZ` rotation.&#xD;&#xA;&#xD;&#xA;Here I are some images of the visual differences between FleX and Blender for such transformations:&#xD;&#xA;&#xD;&#xA;Euler rotation vector: `[0, 89.9, 0]` in for object `X` in Blender.&#xD;&#xA;&#xD;&#xA;After applying the rotation in Blender (object `X`):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After applying the same rotation (`[0, 89.9, 0]`) in FleX and importing the object `Y` in Blender:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Euler rotation vector: `[0, 0, 89.9]` for object `X` in Blender.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;After applying the same rotation (`[0, 0, 89.9]`) in FleX and importing the object `Y` in Blender:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;It might look it is easy to guess from the images that FleX swaps the `ry` and `rz` when applying the rotation. If I also swap `ry` and `rz` when applying the rotations in Blender then both `X` and `Y` overlap. However, this only works if all components of the rotation vector are zero except one of them. If the rotation vector is something like `[-43.964176, 20.641195, -1.2689421]` `X` and `Y` do not overlap anymore and discrepancies start to show up as shown below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The discrepancies are more visible if I put a cloth on `Y` in FleX, import the cloth and `X` in Blender and rotate `X` by `[-43.964176, -1.2689421, 20.641195]` (notice that I've swapped `ry` and `rz` when applying the rotation in Blender, not in FleX):&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Note that if I import `Y` here, the cloth would be perfectly covering it while touching it on the surface:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;After doing some hacking for the last example, I noticed that if I apply the rotation vector `[-43.964176, 1.2689421, 20.641195]` (rx, -rz, ry) the objects overlap almost perfectly:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;For another example, I want to apply the rotation `[87.68034, 79.94778, 82.697876]` in Blender which should **ideally** give me something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;However, FleX is giving me the following (no swapping before passing the rotation vector to FleX):&#xD;&#xA;&#xD;&#xA;[![enter image description here][10]][10]&#xD;&#xA;&#xD;&#xA;I was thinking maybe applying the rotation in order of `(rx, -rz, ry)` in Blender would give me the perfectly overlapping result that I got for the previous example, but instead I got very weird results for another as shown below. Note that I wanted to rotate the object by [87.68034, 79.94778, 82.697876]`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;By manually rotating the object in Blender I could eventually get it as close as possible to `Y` (exported from FleX). Surprisingly, the rotation vector that overlaps `X` and `Y` is way different than `[87.68034, 79.94778, 82.697876]` in `(rx, ry, rz)` or `[87.68034 -82.697876, 79.94778]` in `(rx, -rz, ry)`. It is something around `[5.38, -10.1, 88.6]` in `(rx, ry, rz) as shown below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][12]][12]&#xD;&#xA;&#xD;&#xA;Although you might need more information to figure out exactly what's going out but below I post the code that is used in FleX to compute its rotation matrices. The top one is used when Euler angles are used and the second one is used when Quaternions are input:&#xD;&#xA;&#xD;&#xA;    // generate a rotation matrix around an axis, from PBRT p74&#xD;&#xA;    inline Mat44 RotationMatrix(float angle, const Vec3&amp; axis)&#xD;&#xA;    {&#xD;&#xA;    	Vec3 a = Normalize(axis);&#xD;&#xA;    	float s = sinf(angle);&#xD;&#xA;    	float c = cosf(angle);&#xD;&#xA;    &#xD;&#xA;    	float m[4][4];&#xD;&#xA;    &#xD;&#xA;    	m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;&#xD;&#xA;    	m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;&#xD;&#xA;    	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;&#xD;&#xA;    	m[0][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;&#xD;&#xA;    	m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;&#xD;&#xA;    	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;&#xD;&#xA;    	m[1][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;&#xD;&#xA;    	m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;&#xD;&#xA;    	m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;&#xD;&#xA;    	m[2][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[3][0] = 0.0f;&#xD;&#xA;    	m[3][1] = 0.0f;&#xD;&#xA;    	m[3][2] = 0.0f;&#xD;&#xA;    	m[3][3] = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return Mat44(&amp;m[0][0]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    inline Mat44 RotationMatrix(Quat q)&#xD;&#xA;    {&#xD;&#xA;    	Matrix33 rotation(q);&#xD;&#xA;    &#xD;&#xA;    	Matrix44 m;&#xD;&#xA;    	m.SetAxis(0, rotation.cols[0]);&#xD;&#xA;    	m.SetAxis(1, rotation.cols[1]);&#xD;&#xA;    	m.SetAxis(2, rotation.cols[2]);&#xD;&#xA;    	m.SetTranslation(Point3(0.0f));&#xD;&#xA;    &#xD;&#xA;    	return m;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's how I apply the Euler rotation vector:&#xD;&#xA;&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));&#xD;&#xA;&#xD;&#xA;And I think this should be how `Transform()` is defined:&#xD;&#xA;&#xD;&#xA;    void Mesh::Transform(const Matrix44&amp; m)&#xD;&#xA;    {&#xD;&#xA;        for (uint32_t i=0; i &lt; m_positions.size(); ++i)&#xD;&#xA;        {&#xD;&#xA;            m_positions[i] = m*m_positions[i];&#xD;&#xA;            m_normals[i] = m*m_normals[i];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BoZEo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FDQIH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HJYPn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/lU597.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/27rIH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/DxlAh.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/hhzeO.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/TfeI5.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/eSJ3o.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/ZfScD.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/P01F0.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/Jm2jS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21886" PostHistoryTypeId="5" PostId="5388" RevisionGUID="632a47aa-51c2-4a87-8a3e-dee7c2bc09ab" CreationDate="2018-11-07T04:30:57.190" UserId="7000" Comment="added 2 characters in body" Text="In this [github issue][1] the GLAD author offers the following way to correctly check if there is an extension is available at runtime:&#xD;&#xA;&#xD;&#xA;&gt; The defines just allow you to check at compile time which extensions&#xD;&#xA;&gt; (and opengl versions) are potentially available. After&#xD;&#xA;&gt; loading/initilaizing glad you can check with GLAD_&lt;name of extension&gt;&#xD;&#xA;&gt; if the extension is available at runtime (= supported by the driver&#xD;&#xA;&gt; and loaded).&#xD;&#xA;&gt;&#xD;&#xA;&gt;     // [initialize glad] // ...&#xD;&#xA;&gt;     if (!GLAD_GL_EXT_memory_object) {&#xD;&#xA;&gt;         die(&quot;GL_EXT_memory_object not supported!&quot;); &#xD;&#xA;&gt;     }&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;[1]: https://github.com/Dav1dde/glad/issues/97&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21887" PostHistoryTypeId="2" PostId="8231" RevisionGUID="3459b245-8398-4bed-98bb-44caf2dab3d6" CreationDate="2018-11-07T04:52:08.323" UserId="7000" Text="I have a modern OpenGL project hosted publicly.  I want to create the easiest experience so someone can just clone the entire project and be ready to go with my project.&#xD;&#xA;&#xD;&#xA;So far, I have included (as git submodules) the window creation library GLFW and the image loading library which is header only.&#xD;&#xA;&#xD;&#xA;The only other part I have to handle is the OpenGL function loading part.  During development I have been using the webservice offered by [glad](https://github.com/Dav1dde/glad)&#xD;&#xA;&#xD;&#xA;The two files I need from GLAD are roughly ~10k lines each.&#xD;&#xA;&#xD;&#xA;Other than asking a user to downloading these files  and place them in the correct folder themselves, is there any way to get around including these files directly in my project?&#xD;&#xA;&#xD;&#xA;Are there any other drawbacks to included the function loading code directly in my project?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21888" PostHistoryTypeId="1" PostId="8231" RevisionGUID="3459b245-8398-4bed-98bb-44caf2dab3d6" CreationDate="2018-11-07T04:52:08.323" UserId="7000" Text="How to include OpenGL extension loader in my project" ContentLicense="CC BY-SA 4.0" />
  <row Id="21889" PostHistoryTypeId="3" PostId="8231" RevisionGUID="3459b245-8398-4bed-98bb-44caf2dab3d6" CreationDate="2018-11-07T04:52:08.323" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21890" PostHistoryTypeId="5" PostId="8231" RevisionGUID="d5f713a7-4d1a-4da1-b3ef-5de095b0ff8f" CreationDate="2018-11-07T05:43:01.827" UserId="7000" Comment="deleted 23 characters in body" Text="I have a modern OpenGL project hosted publicly.  I want to create the easiest experience so someone can just clone the repo and have it just work.&#xD;&#xA;&#xD;&#xA;So far, I have included (as git submodules) the window creation library GLFW and the image loading library which is header only.&#xD;&#xA;&#xD;&#xA;The only other part I have to handle is the OpenGL function loading part.  During development I have been using the webservice offered by [glad](https://github.com/Dav1dde/glad)&#xD;&#xA;&#xD;&#xA;The two files I need from GLAD are roughly ~10k lines each.&#xD;&#xA;&#xD;&#xA;Other than asking a user to downloading these files  and place them in the correct folder themselves, is there any way to get around including these files directly in my project?&#xD;&#xA;&#xD;&#xA;Are there any other drawbacks to included the function loading code directly in my project?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21891" PostHistoryTypeId="5" PostId="8226" RevisionGUID="ac0ba204-1dc7-401f-8541-9bb627557969" CreationDate="2018-11-07T11:46:44.210" UserId="9581" Comment="added 43 characters in body" Text="I import a mesh in Blender, export it with setting `axis_forward='-Z', axis_up='Y'`, import in NVIDIA's FleX, rotate it and store it on disk; I call this mesh `X`. I also import the mesh in Blender and rotate it the same amount; I call this mesh `Y`. After I imported `X` in Blender (setting `axis_forward='-Z', axis_up='Y'`) I realized that `X` has a different rotation which means that FleX is either using a different global axes (I think it's `-Y` forward and `Z` up) or it applies the rotations in a different order or a combination of both. So I am pretty confused now. I do not want to change anything on the FleX side. However, I want to rotate `Y` in a way that it matches with what FleX exports (`X`) after rotation. I also tried with Quaternions but I'm still unable to figure out the way FleX is transforming the object. The only thing that I've been able to figure out empirically is that the value for `rx` rotation is applied the same way for both FleX and Blender. This means that objects `X` and `Y` would overlap completely if imported in on scene in Blender. &#xD;&#xA;&#xD;&#xA;**My goal** is to rotate the object in FleX so that object `Y`'s rotation matches exactly with object `X` when I import `X` in Blender. For instance, I want FleX rotate the object the same way as Blender rotates it with the Euler rotation vector of `[rx, ry, rz]`. How can I achieve this?&#xD;&#xA;&#xD;&#xA;**Note** that I am not changing the rotation order in Blender and I'm using the default `XYZ` rotation.&#xD;&#xA;&#xD;&#xA;Here I are some images of the visual differences between FleX and Blender for such transformations:&#xD;&#xA;&#xD;&#xA;Euler rotation vector: `[0, 89.9, 0]` in for object `Y` in Blender.&#xD;&#xA;&#xD;&#xA;After applying the rotation in Blender (object `Y`):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After applying the same rotation (`[0, 89.9, 0]`) in FleX and importing the object `X` in Blender:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Euler rotation vector: `[0, 0, 89.9]` for object `Y` in Blender.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;After applying the same rotation (`[0, 0, 89.9]`) in FleX and importing the object `X` in Blender:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;It might look it is easy to guess from the images that FleX swaps the `ry` and `rz` when applying the rotation. If I also swap `ry` and `rz` when applying the rotations in Blender then both `X` and `Y` overlap. However, this only works if all components of the rotation vector are zero except one of them. If the rotation vector is something like `[-43.964176, 20.641195, -1.2689421]` `X` and `Y` do not overlap anymore and discrepancies start to show up as shown below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The discrepancies are more visible if I put a cloth on `X` in FleX, import the cloth and `Y` in Blender and rotate `Y` by `[-43.964176, -1.2689421, 20.641195]` (notice that I've swapped `ry` and `rz` when applying the rotation in Blender, not in FleX):&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Note that if I import `X` here, the cloth would be perfectly covering it while touching it on the surface:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;After doing some hacking for the last example, I noticed that if I apply the rotation vector `[-43.964176, 1.2689421, 20.641195]` (rx, -rz, ry) the objects overlap almost perfectly:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;For another example, I want to apply the rotation `[87.68034, 79.94778, 82.697876]` in Blender which should **ideally** give me something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;However, FleX is giving me the following (no swapping before passing the rotation vector to FleX):&#xD;&#xA;&#xD;&#xA;[![enter image description here][10]][10]&#xD;&#xA;&#xD;&#xA;I was thinking maybe applying the rotation in order of `(rx, -rz, ry)` in Blender would give me the perfectly overlapping result that I got for the previous example, but instead I got very weird results for another as shown below. Note that I wanted to rotate the object by [87.68034, 79.94778, 82.697876]`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;By manually rotating the object in Blender I could eventually get it as close as possible to `Y` (exported from FleX). Surprisingly, the rotation vector that overlaps `X` and `Y` is way different than `[87.68034, 79.94778, 82.697876]` in `(rx, ry, rz)` or `[87.68034 -82.697876, 79.94778]` in `(rx, -rz, ry)`. It is something around `[5.38, -10.1, 88.6]` in `(rx, ry, rz) as shown below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][12]][12]&#xD;&#xA;&#xD;&#xA;Although you might need more information to figure out exactly what's going out but below I post the code that is used in FleX to compute its rotation matrices. The top one is used when Euler angles are used and the second one is used when Quaternions are input:&#xD;&#xA;&#xD;&#xA;    // generate a rotation matrix around an axis, from PBRT p74&#xD;&#xA;    inline Mat44 RotationMatrix(float angle, const Vec3&amp; axis)&#xD;&#xA;    {&#xD;&#xA;    	Vec3 a = Normalize(axis);&#xD;&#xA;    	float s = sinf(angle);&#xD;&#xA;    	float c = cosf(angle);&#xD;&#xA;    &#xD;&#xA;    	float m[4][4];&#xD;&#xA;    &#xD;&#xA;    	m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;&#xD;&#xA;    	m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;&#xD;&#xA;    	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;&#xD;&#xA;    	m[0][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;&#xD;&#xA;    	m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;&#xD;&#xA;    	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;&#xD;&#xA;    	m[1][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;&#xD;&#xA;    	m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;&#xD;&#xA;    	m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;&#xD;&#xA;    	m[2][3] = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	m[3][0] = 0.0f;&#xD;&#xA;    	m[3][1] = 0.0f;&#xD;&#xA;    	m[3][2] = 0.0f;&#xD;&#xA;    	m[3][3] = 1.0f;&#xD;&#xA;    &#xD;&#xA;    	return Mat44(&amp;m[0][0]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    inline Mat44 RotationMatrix(Quat q)&#xD;&#xA;    {&#xD;&#xA;    	Matrix33 rotation(q);&#xD;&#xA;    &#xD;&#xA;    	Matrix44 m;&#xD;&#xA;    	m.SetAxis(0, rotation.cols[0]);&#xD;&#xA;    	m.SetAxis(1, rotation.cols[1]);&#xD;&#xA;    	m.SetAxis(2, rotation.cols[2]);&#xD;&#xA;    	m.SetTranslation(Point3(0.0f));&#xD;&#xA;    &#xD;&#xA;    	return m;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here's how I apply the Euler rotation vector:&#xD;&#xA;&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));&#xD;&#xA;&#xD;&#xA;And I think this should be how `Transform()` is defined:&#xD;&#xA;&#xD;&#xA;    void Mesh::Transform(const Matrix44&amp; m)&#xD;&#xA;    {&#xD;&#xA;        for (uint32_t i=0; i &lt; m_positions.size(); ++i)&#xD;&#xA;        {&#xD;&#xA;            m_positions[i] = m*m_positions[i];&#xD;&#xA;            m_normals[i] = m*m_normals[i];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BoZEo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FDQIH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HJYPn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/lU597.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/27rIH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/DxlAh.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/hhzeO.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/TfeI5.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/eSJ3o.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/ZfScD.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/P01F0.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/Jm2jS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21892" PostHistoryTypeId="2" PostId="8232" RevisionGUID="437d9859-f14f-47ff-ba3b-8448820fad33" CreationDate="2018-11-07T15:43:31.950" UserId="2654" Text="GLAD is *designed* around you simply including it directly in your project. That's the point of it; it is easy to use because you don't have to deal with any external dependencies. No messy libraries or DLLs to generate. It's just another source/header file in your build process.&#xD;&#xA;&#xD;&#xA;Furthermore, your code will (presumably) be written to expect GLAD generation with a specific OpenGL version and set of extensions. If you require the user to use GLAD to generate the file, you also have to tell them what version+extensions to use, or else your code won't compile. If you just ship the GLAD-generated files with your program, there's no chance of breakage (or at least, you could detect the breakage because your own build doesn't work anymore)." ContentLicense="CC BY-SA 4.0" />
  <row Id="21893" PostHistoryTypeId="2" PostId="8233" RevisionGUID="4c9c3e78-4298-4273-954d-1e45bb0a5ca6" CreationDate="2018-11-07T21:13:01.410" UserId="9581" Text="I have to load a mesh in Blender (which uses `Z` and `Y` as *up* and *forward* axes), modify it and export it (with setting *up* and *forward* axes to `Y` and `-Z`) and import it into another software which uses a coordinate system with `Y` up and `-Z` forward. Later on I export the mesh from this software and import it in Blender for rendering. Since I wanted to get the same rotation in the other software that I get in Blender, I changed the rotation matrix of the other software from Identity to the following:&#xD;&#xA;&#xD;&#xA;    [1.0, 0.0, 0.0;&#xD;&#xA;    0.0, 0.0, -1.0;&#xD;&#xA;    0.0, 1.0, 0.0]&#xD;&#xA;&#xD;&#xA;Now I get the same exact rotation in that software that I get in Blender when using Euler angles. However, I have to actually use Quaternions and I realized that Quaternions do not have a rotation matrix. I wonder, what is the equivalent version of rotation matrix for Quaternions? Also, how can I change that equivalent-rotation-matrix of Quaternions so that I get the same rotation that I get in Blender?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21894" PostHistoryTypeId="1" PostId="8233" RevisionGUID="4c9c3e78-4298-4273-954d-1e45bb0a5ca6" CreationDate="2018-11-07T21:13:01.410" UserId="9581" Text="What is the equivalent of rotation matrix in Euler angle space for Quaternions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21895" PostHistoryTypeId="3" PostId="8233" RevisionGUID="4c9c3e78-4298-4273-954d-1e45bb0a5ca6" CreationDate="2018-11-07T21:13:01.410" UserId="9581" Text="|3d|transformations|mathematics|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21896" PostHistoryTypeId="2" PostId="8234" RevisionGUID="d6b136ab-4f7a-45f6-94aa-169c349d50e3" CreationDate="2018-11-07T23:41:10.797" UserId="7000" Text="I have a server and my only monitor is plugged into its graphics card.&#xD;&#xA;&#xD;&#xA;My question is - do all programs (Windows explorer, Excel whatever) draw their output using the graphics card and more specifically an API such as OpenGL?&#xD;&#xA;&#xD;&#xA;The output is coming from the graphics card so I do not see how it could not be but it seems like that would require anyone who is using a server to have a GPU to any visual output." ContentLicense="CC BY-SA 4.0" />
  <row Id="21897" PostHistoryTypeId="1" PostId="8234" RevisionGUID="d6b136ab-4f7a-45f6-94aa-169c349d50e3" CreationDate="2018-11-07T23:41:10.797" UserId="7000" Text="Do operating programs such as Microsoft Office or Windows Explorer use OpenGL to draw?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21898" PostHistoryTypeId="3" PostId="8234" RevisionGUID="d6b136ab-4f7a-45f6-94aa-169c349d50e3" CreationDate="2018-11-07T23:41:10.797" UserId="7000" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21899" PostHistoryTypeId="2" PostId="8235" RevisionGUID="604820a1-d94d-40fa-97f6-edab5766b255" CreationDate="2018-11-08T00:40:51.257" UserId="1937" Text="It's not true to say quaternions don't have a rotation matrix. They are both ways of completely describing a rotation in 3D, so they are freely convertible. Each quaternion corresponds to exactly one rotation matrix, and each rotation matrix corresponds to one quaternion and its negative. Quaternions are just more compact and easier to interpolate.&#xD;&#xA;&#xD;&#xA;To work out the rotation matrix for a quaternion, you need to take the effect of the quaternion, $q = (w, x, y, z) = (w, \textbf{v}) $ on some point $\textbf{p}$, that is, $(w, \textbf{v}) * (0, \textbf{p}) * (w, \textbf{-v}) $, and express this formula as a matrix operating on $\textbf{p}$.&#xD;&#xA;&#xD;&#xA;Multiplying out using the rules of quaternions gives us $(w^2 - \textbf{v.v})\textbf{p} + 2( w\textbf{v}\times \textbf{p} + \textbf{(v.p)v})  $&#xD;&#xA;&#xD;&#xA;This can be rearranged into 3 matrix terms - the first part is just a constant value down the diagonal, the second part with the cross product has values everywhere *except* the diagonal, and the third one is simply $\textbf{v}_m *  \textbf{v}_n $ for rows m and columns n.&#xD;&#xA;&#xD;&#xA;Adding these 3 matrices together gives you &#xD;&#xA;&#xD;&#xA;$\begin{bmatrix} 1-2(y^2+z^2) &amp;2(xy-zw) &amp; 2(xz+yw)\\2(xy + zw)&amp;1-2(x^2+z^2) &amp; 2(yz-xw)\\2(xz-yw) &amp; 2(yz + xw) &amp; 1 - 2(x^2+y^2)\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;which is the conversion you need.&#xD;&#xA;&#xD;&#xA;In your particular use case, though, you are just doing a simple rotate-x through 90 degrees, which simplifies things a lot. Remember a quaternion is $ ( cos(\theta/ 2) , sin(\theta/ 2)\textbf{a})$   where $\textbf{a}$  is your normalized axis of rotation. So the quaternion representing ±90 degrees rotation around x will be $( \frac{1}{\sqrt{2}},±\frac{1}{\sqrt{2}},0,0)$" ContentLicense="CC BY-SA 4.0" />
  <row Id="21901" PostHistoryTypeId="2" PostId="8236" RevisionGUID="92359bcb-627e-415a-8081-23e747bfcb7b" CreationDate="2018-11-08T03:35:16.917" UserId="3003" Text="In general, no. Most applications, unless they are games, or 3D applications like CAD or animation software, will use OS APIs to do their drawing. On Windows, this can be things like [GDI or GDI+](https://docs.microsoft.com/en-us/windows/desktop/gdiplus/-gdiplus-gdi-start). On macOS you would usually use CoreGraphics or one of its derivatives. &#xD;&#xA;&#xD;&#xA;At a lower level than the application level, the operating system talks to the graphics driver to tell  it to draw things on the screen. They may do so using OpenGL or a proprietary API that's not usually exposed directly to applications. (For example on older macOS versions, the Window Server used OpenGL directly to do its compositing. I believe it uses Metal now.) Additionally, some drawing may not be done by the graphics card at all, but the results may be sent to the graphics card for display. For example, the original Windows GDI did its drawing using the CPU, as hardware accelerated graphics were not included on every machine.&#xD;&#xA;&#xD;&#xA;So really, there are a variety of ways for applications to do their drawing. They rarely use OpenGL, DirectX, etc. directly unless they have heavy graphics requirements. However, under the hood, the OS may be using those technologies or something similar, or something even lower-level." ContentLicense="CC BY-SA 4.0" />
  <row Id="21902" PostHistoryTypeId="2" PostId="8237" RevisionGUID="dcc836c0-6181-4b73-af36-50ffcf31b021" CreationDate="2018-11-08T11:26:06.593" UserId="9655" Text="Assume a color X with alpha 1 and RGB 255,230,210.&#xD;&#xA;&#xD;&#xA;How can i find another color ( or an array of colors ) that blended with a background of color Y ( e.g 255,255,255 ) would produce the original color with alpha c ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21903" PostHistoryTypeId="1" PostId="8237" RevisionGUID="dcc836c0-6181-4b73-af36-50ffcf31b021" CreationDate="2018-11-08T11:26:06.593" UserId="9655" Text="Converting color to equivalent with opacity" ContentLicense="CC BY-SA 4.0" />
  <row Id="21904" PostHistoryTypeId="3" PostId="8237" RevisionGUID="dcc836c0-6181-4b73-af36-50ffcf31b021" CreationDate="2018-11-08T11:26:06.593" UserId="9655" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21905" PostHistoryTypeId="5" PostId="8237" RevisionGUID="6b267bfc-9cfc-4ffe-8c6d-72ac38fc89db" CreationDate="2018-11-08T11:34:43.327" UserId="9655" Comment="added 1 character in body" Text="Assume a color X with alpha 1 and RGB 255,230,210.&#xD;&#xA;&#xD;&#xA;How can i find another color with alpha A ( or an array of colors ) that blended with a background of color Y ( e.g 255,255,255 ) would produce the original color  ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21906" PostHistoryTypeId="2" PostId="8238" RevisionGUID="eea25772-88c4-4ed3-8497-a805b7c2aab9" CreationDate="2018-11-08T12:48:49.557" UserId="7008" Text="This depends on what function you're blending with. Since you don't say where you're doing this, I'll just take OpenGL as an example.&#xD;&#xA;&#xD;&#xA;As you can see in the [API][1], there are several ways of blending two colours (or rather how to interpret these two colours for a given blend function). &#xD;&#xA;&#xD;&#xA;You speak of a colour and a background colour, so let's say your result is $c_r$, your object in the foreground has colour $c_s$ (for Source, the new colour value being &quot;added&quot; someway) and your background has colour $c_d$ (for Destination, the old colour value that has been in the buffer already). &#xD;&#xA;&#xD;&#xA;Let $c_s = \left(\begin{array}{c} R_s\\G_s\\B_s\\A_s \end{array}\right)$ (and analogously for $c_r$ and $c_d$).&#xD;&#xA;&#xD;&#xA;&gt; To determine the blended RGBA values of a pixel, the system uses the following equations:&#xD;&#xA;$R_d = min(k_{R'}, R_s s_R + R_d d_R) \ G_d = min(k_{G'}, G_s S_G + G_d d_G) \ B_d = min(k_{B'}, B_s s_B + B_d d_B) A_d = min(k_{A'}, A_s s_A + A_d d_A)$&#xD;&#xA;&#xD;&#xA;A bit confusing with the doubled $R_d$ and so forth, so I'll rewrite it to the denomination I defined earlier:&#xD;&#xA;&#xD;&#xA;$R_r = min(k_{R'}, R_s s_R + R_d d_R) \ G_r = min(k_{G'}, G_s S_G + G_d d_G) \ B_r = min(k_{B'}, B_s s_B + B_d d_B) A_r = min(k_{A'}, A_s s_A + A_d d_A)$&#xD;&#xA;&#xD;&#xA;The min function is there for not going above a certain constant (and $k_{R'},\ k_{G'},\ k_{B'},\ k_{A'}$ are simply constants). For our purposes, let's just assume that we don't surpass this threshold, so we end up with&#xD;&#xA;&#xD;&#xA;$R_r = R_s s_R + R_d d_R$ (and of course the same for the other channels).&#xD;&#xA;&#xD;&#xA;The rest of the components $s_R$ and $d_R$ which are some scaling factors for combining the two colours.&#xD;&#xA;&#xD;&#xA;&gt; Transparency is best implemented using blend function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) with primitives sorted from farthest to nearest.&#xD;&#xA;&#xD;&#xA;This helps, because now we know what the factors $s_R$ and $d_R$ actually are: the alpha values of the **Source**.&#xD;&#xA;&#xD;&#xA;This leaves us with &#xD;&#xA;&#xD;&#xA;$R_r = R_s A_s + (1 - R_d A_d)$&#xD;&#xA;&#xD;&#xA;Therefore, to come back to your example, we have (for the green channel, since that is not $255$):&#xD;&#xA;&#xD;&#xA;$G_r = 230$, an undefined $\alpha$ value for the source, the background green $G_d = 255$ and probably a solid background, meaning $A_d = 255$. We need the values to be in $\left[0, 1\right]$, therefore we get $G_r = \frac{230}{255} = 0.90196078431$, $G_d = 1$ and $A_d = 1$.&#xD;&#xA;&#xD;&#xA;Filling this in we get:&#xD;&#xA;&#xD;&#xA;$0.90196078431 = G_s A_s + (1 - 1 \cdot A_s)$&#xD;&#xA;&#xD;&#xA;Your question lets me believe, that you know $A_s$, thus only $G_s$ (and of course the same for the other colour channels) is missing. This can then be calculated by isolating the respective colour component.&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="21911" PostHistoryTypeId="2" PostId="8239" RevisionGUID="a69f9481-9b6c-4fa7-b6a3-de4ff0cb37ad" CreationDate="2018-11-08T14:11:14.990" UserId="8893" Text="I am currently experiencing a very obvious artifact that occurs when looking at objects on very grazing angles&#xD;&#xA;&#xD;&#xA;Here is a picture of the artifact:&#xD;&#xA;[![artifact][1]][1]&#xD;&#xA;&#xD;&#xA;I noticed that the issue was coming from my implementation of Cook-Torrance's Specular BRDF. &#xD;&#xA;&#xD;&#xA;Here is the equation for the Cook-Torrance Specular BRDF: &#xD;&#xA;[![Cook-Torrance Specular BRDF][2]][2]&#xD;&#xA;&#xD;&#xA;More specifically, calculating the denominator is causing the issue:&#xD;&#xA;&#xD;&#xA;    float denominator = 4 * max(dot(viewDir, normal), 0.0) * max(dot(lightDir, normal), 0.0) + 0.001;  // Prevents any division by zero&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I change the calculation of dot(viewDir, normal) to dot(halfway, normal), the artifact disappears:&#xD;&#xA;&#xD;&#xA;    float denominator = 4 * max(dot(halfway, normal), 0.0) * max(dot(lightDir, normal), 0.0) + 0.001;  // Prevents any division by zero&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But this equation is no longer correct. I was wondering if anyone knows why my implementation causes these artifacts?&#xD;&#xA;&#xD;&#xA;If you want to see my fragment shader you can find the code here:&#xD;&#xA;&#xD;&#xA;https://github.com/Ershany/Arcane-Engine/blob/WIP_PBR/Arcane%20Engine%20Core/src/shaders/pbr_model.frag&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZNQL3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/0wcIZ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21912" PostHistoryTypeId="1" PostId="8239" RevisionGUID="a69f9481-9b6c-4fa7-b6a3-de4ff0cb37ad" CreationDate="2018-11-08T14:11:14.990" UserId="8893" Text="Cook-Torrance Specular BRDF Artifact" ContentLicense="CC BY-SA 4.0" />
  <row Id="21913" PostHistoryTypeId="3" PostId="8239" RevisionGUID="a69f9481-9b6c-4fa7-b6a3-de4ff0cb37ad" CreationDate="2018-11-08T14:11:14.990" UserId="8893" Text="|brdf|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21914" PostHistoryTypeId="36" PostId="8240" RevisionGUID="d27b4454-5ae8-4041-a315-6529d9304b49" CreationDate="2018-11-08T17:48:09.663" UserId="-1" Comment="from https://cs.stackexchange.com/questions/99746/3d-scene-construction-and-change-of-coordinates" />
  <row Id="21915" PostHistoryTypeId="2" PostId="8240" RevisionGUID="dcdc5a7b-2683-47b3-98b4-803aecbe3839" CreationDate="2018-11-08T12:08:22.940" UserDisplayName="mathmaniage" Text="My book says, &quot;After a scene has been constructed we transfer object descriptions to the viewing-coordinate reference frame. This conversion of object descriptions is equivalent to a sequence of transformations that superimposes the viewing reference frame onto the world frame, so we translate  the  view reference frame onto the origin and  rotate by an angle to align the view to the world&quot;.&#xD;&#xA;  &#xD;&#xA;So,  my confusion is: If we're transferring object descriptions from the world to view, shouldn't we superimpose the world onto the view,   and hence take the inverse  of  the above transformation? Why is my book saying things the other way around?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21916" PostHistoryTypeId="1" PostId="8240" RevisionGUID="dcdc5a7b-2683-47b3-98b4-803aecbe3839" CreationDate="2018-11-08T12:08:22.940" UserDisplayName="mathmaniage" Text="3D scene construction and change of coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="21917" PostHistoryTypeId="3" PostId="8240" RevisionGUID="dcdc5a7b-2683-47b3-98b4-803aecbe3839" CreationDate="2018-11-08T12:08:22.940" UserDisplayName="mathmaniage" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21921" PostHistoryTypeId="50" PostId="7794" RevisionGUID="61d34934-bf58-40a2-b79f-c5292758833b" CreationDate="2018-11-08T18:01:50.317" UserId="-1" />
  <row Id="21924" PostHistoryTypeId="5" PostId="8131" RevisionGUID="dcf1428b-7d39-43f2-93cc-6df993c51777" CreationDate="2018-11-08T19:44:54.610" UserId="8893" Comment="deleted 16 characters in body" Text="I am currently experiencing a very obvious artifact that occurs when looking at objects on very grazing angles&#xD;&#xA;&#xD;&#xA;Here is a picture of the artifact:&#xD;&#xA;[![artifact][1]][1]&#xD;&#xA;&#xD;&#xA;I noticed that the issue was coming from my implementation of Cook-Torrance's Specular BRDF. &#xD;&#xA;&#xD;&#xA;Here is the equation for the Cook-Torrance Specular BRDF: &#xD;&#xA;[![Cook-Torrance Specular BRDF][2]][2]&#xD;&#xA;&#xD;&#xA;More specifically, calculating the denominator is causing the issue:&#xD;&#xA;&#xD;&#xA;    float denominator = 4 * max(dot(viewDir, normal), 0.0) * max(dot(lightDir, normal), 0.0) + 0.001;  // Prevents any division by zero&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I change the calculation of dot(viewDir, normal) to dot(halfway, normal), the artifact disappears:&#xD;&#xA;&#xD;&#xA;    float denominator = 4 * max(dot(halfway, normal), 0.0) * max(dot(lightDir, normal), 0.0) + 0.001;  // Prevents any division by zero&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But this equation is no longer correct. I was wondering if anyone knows why my implementation causes these artifacts?&#xD;&#xA;&#xD;&#xA;If you want to see my fragment shader you can find the code here:&#xD;&#xA;&#xD;&#xA;https://github.com/Ershany/Arcane-Engine/blob/WIP_PBR/Arcane%20Engine%20Core/src/shaders/pbr_model.frag&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZNQL3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/0wcIZ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21925" PostHistoryTypeId="6" PostId="8131" RevisionGUID="dcf1428b-7d39-43f2-93cc-6df993c51777" CreationDate="2018-11-08T19:44:54.610" UserId="8893" Comment="deleted 16 characters in body" Text="|brdf|specular|normal-mapping|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21926" PostHistoryTypeId="10" PostId="8239" RevisionGUID="977b3189-4906-4756-b861-997db42f1f8b" CreationDate="2018-11-08T21:18:47.393" UserId="231" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[8131],&quot;Voters&quot;:[{&quot;Id&quot;:182,&quot;DisplayName&quot;:&quot;Julien Guertault&quot;},{&quot;Id&quot;:231,&quot;DisplayName&quot;:&quot;trichoplax&quot;}]}" />
  <row Id="21927" PostHistoryTypeId="2" PostId="8242" RevisionGUID="f51e6ea1-96c6-492f-a485-b3fae10a648b" CreationDate="2018-11-08T22:57:07.020" UserId="9659" Text="Line strips and triangle strips are drawing modes supported across 3D graphics APIs, such as OpenGL, Direct3D, and Vulkan. When using indices to control drawing, a more recent feature is &quot;strip cutting&quot;, also called &quot;primitive restart&quot;, whereby a special index value can be inserted to indicate that the current strip has finished, and any following indices are part of a new strip.&#xD;&#xA;&#xD;&#xA;On OpenGL, you can enable strip cutting by calling `glEnable(GL_PRIMITIVE_RESTART)` and disable it by calling `glDisable(GL_PRIMITIVE_RESTART)`. In Vulkan, you control this feature by setting the `primitiveRestartEnable` boolean field of the `VkPipelineInputAssemblyStateCreateInfo` structure. In Direct3D 12 you can use the `IBStripCutValue` member of the `D3D12_GRAPHICS_PIPELINE_STATE_DESC` structure to enable or disable strip cutting. Under Direct3D 11, this feature is on by default.&#xD;&#xA;&#xD;&#xA;My question is, under Direct3D 11, can you turn this feature off in any way? [The documentation][1] on this is very brief, and indicates no way to disable it. Is there some magic setting lurking in the API somewhere that I've missed?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/direct3d11/d3d10-graphics-programming-guide-primitive-topologies#generating-multiple-strips" ContentLicense="CC BY-SA 4.0" />
  <row Id="21928" PostHistoryTypeId="1" PostId="8242" RevisionGUID="f51e6ea1-96c6-492f-a485-b3fae10a648b" CreationDate="2018-11-08T22:57:07.020" UserId="9659" Text="Can you disable strip cutting (AKA primitive restart) on Direct3D 11?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21929" PostHistoryTypeId="3" PostId="8242" RevisionGUID="f51e6ea1-96c6-492f-a485-b3fae10a648b" CreationDate="2018-11-08T22:57:07.020" UserId="9659" Text="|directx11|line-drawing|direct3d|drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21930" PostHistoryTypeId="2" PostId="8243" RevisionGUID="779e7f9b-a876-4a27-9f03-8a3a8972e4e5" CreationDate="2018-11-09T01:55:10.900" UserId="9581" Text="I just had to make the following changes to [manually] change the coordinate system of FleX to the one that Blender uses:&#xD;&#xA;&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 0.0f, -1.0f)))&#xD;&#xA;    obj-&gt;Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 1.0f, 0.0f)));&#xD;&#xA;&#xD;&#xA;The way I figured this was I generated three rotation vectors `[90, 0, 0]`, `[0, 90, 0]` and `[0, 0, 90]` and rotated the shapes in FleX. Then I loaded the shapes in Blender and empirically figured rotation on which axis in Blender matches to the shape imported from FleX. I learned that when I rotate the shape on the `Y`axis by 90 degrees in Blender, it matches the 90-degree rotation on the `Z` axis in FleX. Also, I learned that rotating the object by -90 degrees on the `Z` axis in Blender matches with the 90-degree rotation on the `Y` axis in FleX." ContentLicense="CC BY-SA 4.0" />
  <row Id="21933" PostHistoryTypeId="50" PostId="8133" RevisionGUID="f3d54415-4f8e-4ed9-89bd-c8fb432521da" CreationDate="2018-11-09T11:02:00.390" UserId="-1" />
  <row Id="21941" PostHistoryTypeId="2" PostId="8246" RevisionGUID="b2174e02-6460-4b7e-85ca-196848c87826" CreationDate="2018-11-09T22:22:32.290" UserId="5978" Text="Is it possible to add vbos to vbos after their creation? For example (pseudo-code):&#xD;&#xA;&#xD;&#xA;    glGenVertexArrays(1, &amp;_vao);&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    // do init stuff&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;    &#xD;&#xA;    // Much much later in a galaxy far away&#xD;&#xA;    glBindVertexArray(_vao);&#xD;&#xA;    glGenBuffers(1, &amp;_instance_vbo);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, _instance_vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(blee), blee, GL_STATIC_DRAW);&#xD;&#xA;    glEnableVertexAttribArray(_vpos_att);&#xD;&#xA;    glVertexAttribPointer(_vpos_att, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;    &#xD;&#xA;    // Draw&#xD;&#xA;&#xD;&#xA;So far it hasn't really worked. Looking at the bound vbos to my vao (using `GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING`) shows no buffers bound. Though that may be another problem altogether." ContentLicense="CC BY-SA 4.0" />
  <row Id="21942" PostHistoryTypeId="1" PostId="8246" RevisionGUID="b2174e02-6460-4b7e-85ca-196848c87826" CreationDate="2018-11-09T22:22:32.290" UserId="5978" Text="Adding vbos to a vao once it has been created" ContentLicense="CC BY-SA 4.0" />
  <row Id="21943" PostHistoryTypeId="3" PostId="8246" RevisionGUID="b2174e02-6460-4b7e-85ca-196848c87826" CreationDate="2018-11-09T22:22:32.290" UserId="5978" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21945" PostHistoryTypeId="2" PostId="8247" RevisionGUID="b3159071-ccbc-41c5-8505-2db5eb68ef9e" CreationDate="2018-11-10T00:11:38.013" UserId="9668" Text="I'm trying to write code (in any language) to render this 3D grid, matching the look and colors as closely as possible:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/4vTSd.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21946" PostHistoryTypeId="1" PostId="8247" RevisionGUID="b3159071-ccbc-41c5-8505-2db5eb68ef9e" CreationDate="2018-11-10T00:11:38.013" UserId="9668" Text="How can I draw this style of grid?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21947" PostHistoryTypeId="3" PostId="8247" RevisionGUID="b3159071-ccbc-41c5-8505-2db5eb68ef9e" CreationDate="2018-11-10T00:11:38.013" UserId="9668" Text="|opengl|shader|3d|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21948" PostHistoryTypeId="2" PostId="8248" RevisionGUID="adf6f832-b79c-43cd-af06-5d55dbc8e7de" CreationDate="2018-11-10T00:37:34.167" UserId="5978" Text="So after debugging some more, I've found that yes it is possible. You cam add buffers later on but they will need to point to their own attributes.&#xD;&#xA;&#xD;&#xA;My issues came from thinking I could have multiple vbos contributing to a single attribute. That doesn't work. You need multiple vaos for that scenario." ContentLicense="CC BY-SA 4.0" />
  <row Id="21949" PostHistoryTypeId="2" PostId="8249" RevisionGUID="92102eb7-6e0e-446e-9ded-4503ccdea5df" CreationDate="2018-11-10T03:45:15.613" UserId="4839" Text="Attached is page 34 of &quot;Advanced Global Illumination&quot;, 2nd edition, by Dutre et al. I don't understand how (2.22) is derived from (2.21) and the given incident radiance distribution $L(x\leftarrow\Psi)=L_{in}\delta(\Psi-\Theta)$. Could you please give me a detailed derivation? Thanks a lot!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bytVm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21950" PostHistoryTypeId="1" PostId="8249" RevisionGUID="92102eb7-6e0e-446e-9ded-4503ccdea5df" CreationDate="2018-11-10T03:45:15.613" UserId="4839" Text="Ask for detailed derivation of a formula in &quot;Advanced Global Illumination&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21951" PostHistoryTypeId="3" PostId="8249" RevisionGUID="92102eb7-6e0e-446e-9ded-4503ccdea5df" CreationDate="2018-11-10T03:45:15.613" UserId="4839" Text="|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21952" PostHistoryTypeId="2" PostId="8250" RevisionGUID="e2f4ecf5-22e2-4d11-ad0b-743724c685f4" CreationDate="2018-11-10T12:05:06.943" UserDisplayName="user9485" Text="The only thing you really need to know in order to derive (2.22) from (2.21) is that the $\delta$-distribution satisfies&#xD;&#xA;&#xD;&#xA;$$ \int \delta(x) f(x)\,\text{d}x = f(0). $$&#xD;&#xA;&#xD;&#xA;(The $\delta$-distribution is not a function in the common sense, so the above integral is merely a useful notation and not to be read as e.g. a Lebesgue or Riemann integral.)&#xD;&#xA;&#xD;&#xA;Unfortunately, the notation that the authors use for the substitution of the incident radiance distribution is misleading. The $\Theta$ in $L(x\leftarrow\Psi) = L_{in}\delta(\Psi-\Theta)$ is completely unrelated to the integration variable $\omega_\Theta$, so I chose to denote it by $\tilde\Theta$ instead.&#xD;&#xA;&#xD;&#xA;Here is the derivation of (2.22) from (2.21):&#xD;&#xA;&#xD;&#xA;1. Substitute $L(x\leftarrow\Psi) = L_{in}\delta(\Psi-\tilde\Theta)$:&#xD;&#xA;&#xD;&#xA;$$\frac{\int_{\Omega_x} \int_{\Omega_x} f_r(x, \Psi \rightarrow \Theta) L_{in}\delta(\Psi-\tilde\Theta)\cos(N_x,\Theta)\cos(N_x,\Psi)\,\text{d}\omega_\Psi\,\text{d}\omega_\Theta}{\int_{\Omega_x}L_{in}\delta(\Psi-\tilde\Theta)\cos(N_x,\Psi)\,\text{d}\omega_\Psi}$$&#xD;&#xA;&#xD;&#xA;2. Substitute $\Psi$ with $\Psi+\tilde\Theta$:&#xD;&#xA;&#xD;&#xA;$$\frac{\int_{\Omega_x} \int_{\Omega_x-\tilde\Theta} f_r(x, \Psi+\tilde\Theta \rightarrow \Theta) L_{in}\delta(\Psi)\cos(N_x,\Theta)\cos(N_x,\Psi+\tilde\Theta)\,\text{d}\omega_\Psi\,\text{d}\omega_\Theta}{\int_{\Omega_x-\tilde\Theta}L_{in}\delta(\Psi)\cos(N_x,\Psi+\tilde\Theta)\,\text{d}\omega_\Psi}$$&#xD;&#xA;&#xD;&#xA;3. Use the above property of the $\delta$-distribution:&#xD;&#xA;&#xD;&#xA;$$\frac{\int_{\Omega_x} f_r(x, \tilde\Theta \rightarrow \Theta) L_{in}\cos(N_x,\Theta)\cos(N_x,\tilde\Theta)\,\text{d}\omega_\Theta}{L_{in}\cos(N_x,\tilde\Theta)}$$&#xD;&#xA;&#xD;&#xA;4. Simplify:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega_x} f_r(x, \tilde\Theta \rightarrow \Theta) \cos(N_x,\Theta)\,\text{d}\omega_\Theta$$&#xD;&#xA;&#xD;&#xA;Now you only need to notice that we want equation (2.22) to be true for all such &quot;test functions&quot; $L_{in}\delta(\Psi-\tilde\Theta)$ for the incident radiance, i.e. for all possible values of $\tilde\Theta$. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21953" PostHistoryTypeId="5" PostId="8250" RevisionGUID="762f464e-f7b7-4d48-8411-c9ca76da37f7" CreationDate="2018-11-10T12:36:01.930" UserDisplayName="user9485" Comment="deleted 32 characters in body" Text="The only thing you really need to know in order to derive (2.22) from (2.21) is that the $\delta$-distribution satisfies&#xD;&#xA;&#xD;&#xA;$$ \int \delta(x) f(x)\,\text{d}x = f(0). $$&#xD;&#xA;&#xD;&#xA;(The $\delta$-distribution is not a function in the common sense, so the above integral is merely a useful notation and not to be read as e.g. a Lebesgue or Riemann integral.)&#xD;&#xA;&#xD;&#xA;Unfortunately, the notation that the authors use for the substitution of the incident radiance distribution is misleading. The $\Theta$ in $L(x\leftarrow\Psi) = L_{in}\delta(\Psi-\Theta)$ is completely unrelated to the integration variable $\omega_\Theta$, so I chose to denote it by $\tilde\Psi$ instead.&#xD;&#xA;&#xD;&#xA;Here is the derivation of (2.22) from (2.21):&#xD;&#xA;&#xD;&#xA;1. Substitute $L(x\leftarrow\Psi) = L_{in}\delta(\Psi-\tilde\Psi)$:&#xD;&#xA;&#xD;&#xA;$$\frac{\int_{\Omega_x} \int_{\Omega_x} f_r(x, \Psi \rightarrow \Theta) L_{in}\delta(\Psi-\tilde\Psi)\cos(N_x,\Theta)\cos(N_x,\Psi)\,\text{d}\omega_\Psi\,\text{d}\omega_\Theta}{\int_{\Omega_x}L_{in}\delta(\Psi-\tilde\Psi)\cos(N_x,\Psi)\,\text{d}\omega_\Psi}$$&#xD;&#xA;&#xD;&#xA;2. Substitute $\Psi$ with $\Psi+\tilde\Psi$:&#xD;&#xA;&#xD;&#xA;$$\frac{\int_{\Omega_x} \int_{\Omega_x-\tilde\Psi} f_r(x, \Psi+\tilde\Psi \rightarrow \Theta) L_{in}\delta(\Psi)\cos(N_x,\Theta)\cos(N_x,\Psi+\tilde\Psi)\,\text{d}\omega_\Psi\,\text{d}\omega_\Theta}{\int_{\Omega_x-\tilde\Psi}L_{in}\delta(\Psi)\cos(N_x,\Psi+\tilde\Psi)\,\text{d}\omega_\Psi}$$&#xD;&#xA;&#xD;&#xA;3. Use the above property of the $\delta$-distribution:&#xD;&#xA;&#xD;&#xA;$$\frac{\int_{\Omega_x} f_r(x, \tilde\Psi \rightarrow \Theta) L_{in}\cos(N_x,\Theta)\cos(N_x,\tilde\Psi)\,\text{d}\omega_\Theta}{L_{in}\cos(N_x,\tilde\Psi)}$$&#xD;&#xA;&#xD;&#xA;4. Simplify:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega_x} f_r(x, \tilde\Psi \rightarrow \Theta) \cos(N_x,\Theta)\,\text{d}\omega_\Theta$$&#xD;&#xA;&#xD;&#xA;Now you only need to notice that we want equation (2.21) to be true for all such &quot;test functions&quot; $L_{in}\delta(\Psi-\tilde\Psi)$ for the incident radiance, i.e. for all possible values of $\tilde\Psi$. " ContentLicense="CC BY-SA 4.0" />
  <row Id="21954" PostHistoryTypeId="50" PostId="7804" RevisionGUID="c76b4b1b-7e6c-4c00-bdd8-5c13f21b2c11" CreationDate="2018-11-10T14:02:00.373" UserId="-1" />
  <row Id="21956" PostHistoryTypeId="50" PostId="7538" RevisionGUID="50b42c63-3e56-4695-b3ac-cd0af9df0cad" CreationDate="2018-11-10T20:02:10.400" UserId="-1" />
  <row Id="21957" PostHistoryTypeId="2" PostId="8251" RevisionGUID="0765432b-55a1-44d7-a93f-bd4316605774" CreationDate="2018-11-10T21:04:05.953" UserId="7334" Text="I'm building a software renderer but I think there might be some problem with my ray-triangle intersection accuracy.&#xD;&#xA;&#xD;&#xA;I implemented the algorithm referring to `pbrt-v3` without some components which I think have little influence on the intersection test.&#xD;&#xA;&#xD;&#xA;Below is the code perform intersection test:&#xD;&#xA;&#xD;&#xA;	bool Triangle::intersectP(const Ray &amp;r, Point3f p0, Point3f p1, Point3f p2) const {&#xD;&#xA;        // translate&#xD;&#xA;        Point3f p0_ = p0 - r._o;&#xD;&#xA;        Point3f p1_ = p1 - r._o;&#xD;&#xA;        Point3f p2_ = p2 - r._o;&#xD;&#xA;&#xD;&#xA;        // permute, to make sure z-dimension is not zero&#xD;&#xA;		// permutation is just like to circular move right/left until z is largest dimemsion.&#xD;&#xA;        int kz = r._d.maxDim();&#xD;&#xA;        int kx = kz+1; if (kx == 3) kx = 0;&#xD;&#xA;        int ky = kx+1; if (ky == 3) ky = 0;&#xD;&#xA;&#xD;&#xA;        // swap coord&#xD;&#xA;        Vec3f d_ = r._d.permute(kx, ky, kz);&#xD;&#xA;        p0_ = p0_.permute(kx, ky, kz);&#xD;&#xA;        p1_ = p1_.permute(kx, ky, kz);&#xD;&#xA;        p2_ = p2_.permute(kx, ky, kz);&#xD;&#xA;        // shear&#xD;&#xA;        float Sx = -d_.x()/d_.z();&#xD;&#xA;        float Sy = -d_.y()/d_.z();&#xD;&#xA;        float Sz = 1.0f/d_.z();&#xD;&#xA;&#xD;&#xA;        // perform transform (p.z doesn't matter now)&#xD;&#xA;        p0_[0] += Sx*p0_[2];&#xD;&#xA;        p0_[1] += Sy*p0_[2];&#xD;&#xA;        p1_[0] += Sx*p1_[2];&#xD;&#xA;        p1_[1] += Sy*p1_[2];&#xD;&#xA;        p2_[0] += Sx*p2_[2];&#xD;&#xA;        p2_[1] += Sy*p2_[2];&#xD;&#xA;&#xD;&#xA;        // signed edge function to judge whether origin's projection in projected triangle&#xD;&#xA;        float e0 = p1_.x()*p2_.y() - p2_.x()*p1_.y();   // p1 -&gt; p2&#xD;&#xA;        float e1 = p2_.x()*p0_.y() - p0_.x()*p2_.y();   // p2 -&gt; p0&#xD;&#xA;        float e2 = p0_.x()*p1_.y() - p1_.x()*p0_.y();   // p0 -&gt; p1&#xD;&#xA;&#xD;&#xA;        // perform high-precision at edges&#xD;&#xA;        if (e0 == 0.0f || e1 == 0.0f || e2 == 0.0f) {&#xD;&#xA;            double p0xp1y = (double)p0_.x() * (double)p1_.y();&#xD;&#xA;            double p1xp0y = (double)p1_.x() * (double)p0_.y();&#xD;&#xA;            e2 = (float)(p0xp1y - p1xp0y);&#xD;&#xA;            double p1xp2y = (double)p1_.x() * (double)p2_.y();&#xD;&#xA;            double p2xp1y = (double)p2_.x() * (double)p1_.y();&#xD;&#xA;            e0 = (float)(p1xp2y - p2xp1y);&#xD;&#xA;            double p2xp0y = (double)p2_.x() * (double)p0_.y();&#xD;&#xA;            double p0xp2y = (double)p0_.x() * p2_.y();&#xD;&#xA;            e1 = (float)(p2xp0y - p0xp2y);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // edge detection&#xD;&#xA;        if ( (e0 &lt; 0 || e1 &lt; 0 ||  e2 &lt; 0) &amp;&amp; (e0 &gt; 0 || e2 &gt; 0 || e1 &gt; 0) )&#xD;&#xA;            return false;&#xD;&#xA;&#xD;&#xA;        float det = e0 + e1 + e2;&#xD;&#xA;        if (det == 0)	// on edge&#xD;&#xA;			return false;&#xD;&#xA;&#xD;&#xA;        // compute z value (i.e. t)&#xD;&#xA;        p0_[2] *= Sz;&#xD;&#xA;        p1_[2] *= Sz;&#xD;&#xA;        p2_[2] *= Sz;&#xD;&#xA;&#xD;&#xA;        float tScaled = e0*p0_.z() + e1*p1_.z() + e2*p2_.z();&#xD;&#xA;        if (det &lt; 0 &amp;&amp; (tScaled &gt;= 0 || tScaled &lt; r._tmax*det) ) return false;&#xD;&#xA;        else if (det &gt; 0 &amp;&amp; (tScaled &lt;= 0 || tScaled &gt; r._tmax*det) ) return false;&#xD;&#xA;&#xD;&#xA;        return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Unlike pbrt, my implement use right-hand coordinate and row-major matrices, but I think this do not influence the correctness of this piece of code.&#xD;&#xA;&#xD;&#xA;Most of the time, this function works fine. However, artifacts appears when I do occlusion test to the light sources, where `r._tmax` has a specific value (the distance between intersection point and light sample point).&#xD;&#xA;&#xD;&#xA;I tested the algorithm with a plane and a point light above it, however just use the position of the light, radiance is not computed, and this is why I think the problem is caused by intersection implementation.&#xD;&#xA;If unoccluded, a value is returned as radiance, otherwise zero.&#xD;&#xA;&#xD;&#xA;	Vec3f PointEmitter::evalDirect(std::shared_ptr&lt;Scene&gt; scene, const IntersectInfo &amp;isect_info, const Point2f &amp;u) const {&#xD;&#xA;		Vec3f wi;&#xD;&#xA;		float light_pdf;&#xD;&#xA;		VisibilityTester vt;&#xD;&#xA;		Vec3f Li_sampled = sample_Li(isect_info, wi, light_pdf, vt, u);&#xD;&#xA;		Vec3f f = isect_info._bsdf-&gt;f(isect_info._wo, wi)*std::abs(isect_info._shading._n.dot(wi));&#xD;&#xA;&#xD;&#xA;		return (scene-&gt;intersectP(IntersectInfo(_p).spawnRayTo(isect_info))) *100;&#xD;&#xA;	}&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And another open box-like polygon, with same light:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;There's a circle-like region obviously stands out on the surface.&#xD;&#xA;&#xD;&#xA;I consider this comes from the float point error when comparing `r_tmax` and the distance. But the code already uses double-precision. Can anyone help?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dFLQd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/8EziQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21958" PostHistoryTypeId="1" PostId="8251" RevisionGUID="0765432b-55a1-44d7-a93f-bd4316605774" CreationDate="2018-11-10T21:04:05.953" UserId="7334" Text="ray-triangle intersection precision - c++" ContentLicense="CC BY-SA 4.0" />
  <row Id="21959" PostHistoryTypeId="3" PostId="8251" RevisionGUID="0765432b-55a1-44d7-a93f-bd4316605774" CreationDate="2018-11-10T21:04:05.953" UserId="7334" Text="|raytracing|c++|geometry|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21960" PostHistoryTypeId="2" PostId="8252" RevisionGUID="6d660208-6669-4b8a-ad08-a195fef3fa87" CreationDate="2018-11-11T07:22:41.867" UserId="4943" Text="Ad 1) Yes, if both monitors have the same resolution but different screen sizes, this means the pixels of the larger monitor are bigger. It could also mean the space between the pixels is different. &#xD;&#xA;&#xD;&#xA;Ad 2) No, the physical size of a monitor makes no difference for the GPU. It only cares about the resolution, for example 1920x1080 vs 3840x2160. The latter has 4 times the number of pixels, so it requires 4x the amount of memory and a simple operation like `glClear` might take 4 times longer to complete. More complex operations might even be slower than that, due to their implementation details.&#xD;&#xA;&#xD;&#xA;Regarding lag: I believe the time it takes to send the color information for each pixel is determined by a hardware standard and should be the same for each monitor. However, the monitor's chipset, which consumes that signal, may be faster or slower than a monitor of a different make or model. Same goes for the panel technology (e.g. TN, IPS, etc.), which might have a different refresh rate. But the hardware specifics have no effect on the GPU with one important exception: *vertical sync*. If vertical sync is enabled, your GPU will wait for a signal from your display before it starts sending the latest color frame. This **will** introduce latency, which can be pretty severe. There are solutions to that, but that's outside the scope of this answer. I recommend you to watch [this video](https://youtu.be/seyAzw9zEoY) about it." ContentLicense="CC BY-SA 4.0" />
  <row Id="21965" PostHistoryTypeId="2" PostId="8254" RevisionGUID="07156602-45a6-41a5-bb41-60bffdbe549b" CreationDate="2018-11-12T02:31:59.727" UserId="9661" Text="In one text,  the  derivation for  perspective  projection  goes like  this:   [![image1][1]][1]&#xD;&#xA;&#xD;&#xA;If $x',y',z'$ represent any point along  the  projection line,and $x_{prp},y_{prp},z_{prp}$ are the projection reference point, then:&#xD;&#xA;&#xD;&#xA;$$x'=x-(x-x_{prp})u$$  &#xD;&#xA; $$y'=y-(y-y_{prp})u$$&#xD;&#xA;$$z'=z-(z-z_{prp})u$$&#xD;&#xA;where $0\le u \le 1$  &#xD;&#xA;  &#xD;&#xA;Now,   finding the value of u from the third equation above and  replacing in the first and  second  equations,   we get at  $z_vp$:&#xD;&#xA;&#xD;&#xA;$$ x_p=x'= x.\frac{z_{vp}-z_{prp}}{z-z_prp}+x_{prp}.\frac{z-z_{vp}}{z-z_{prp}}$$&#xD;&#xA;$$ y_p=y'= y.\frac{z_{vp}-z_{prp}}{z-z_prp}+y_{prp}.\frac{z-z_{vp}}{z-z_{prp}}$$&#xD;&#xA;  &#xD;&#xA;and there is no projection transformation matrix  given.  &#xD;&#xA;  &#xD;&#xA;In the second text,  the  derivation is using  similar triangles:  &#xD;&#xA;[![image2][2]][2]   &#xD;&#xA;comparing the  similar triangles  we  get:&#xD;&#xA;$$x_p=\frac{-x_c}{\frac{z_c}{d}}$$&#xD;&#xA;$$y_p=\frac{y_c}{\frac{z_c}{d}}$$&#xD;&#xA;&#xD;&#xA;and  the projection transformation for  homogeneous coordinates x,y,z is  given by:&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;-1&amp;&amp;0&amp;&amp;0&amp;&amp;0\\&#xD;&#xA;0&amp;&amp;1&amp;&amp;0&amp;&amp;0\\&#xD;&#xA;0&amp;&amp;0&amp;&amp;1&amp;&amp;0\\&#xD;&#xA;0&amp;&amp;0&amp;&amp;\frac{1}{d}&amp;&amp;0&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$    &#xD;&#xA;  &#xD;&#xA;**so,  my questions are:**&#xD;&#xA;&#xD;&#xA; - How do I find the projection matrix of coordinates as found from &#xD;&#xA;   derivation 1?&#xD;&#xA; - Both are given in the perspective projection area of&#xD;&#xA;   these different texts,  are both transformations the  same? If not, &#xD;&#xA;   how  are  they different?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZHCE0.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/SakPQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21966" PostHistoryTypeId="1" PostId="8254" RevisionGUID="07156602-45a6-41a5-bb41-60bffdbe549b" CreationDate="2018-11-12T02:31:59.727" UserId="9661" Text="perspective projection transformation matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="21967" PostHistoryTypeId="3" PostId="8254" RevisionGUID="07156602-45a6-41a5-bb41-60bffdbe549b" CreationDate="2018-11-12T02:31:59.727" UserId="9661" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21968" PostHistoryTypeId="2" PostId="8255" RevisionGUID="ae1d71b4-2e81-4b33-b9b5-6ae54754ea15" CreationDate="2018-11-12T05:41:57.470" UserId="9661" Text="I found the derivation for two point and three point perspective [here on this site][1],  even though it says review on one point perspective,  it  doesn't give a link to previous pages, but I'd like to know how the matrix for one  point perspective was derived. If possible please give me a detailed derivation for this projection matrix.&#xD;&#xA;&#xD;&#xA;  [1]: https://people.eecs.berkeley.edu/~barsky/perspective.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="21969" PostHistoryTypeId="1" PostId="8255" RevisionGUID="ae1d71b4-2e81-4b33-b9b5-6ae54754ea15" CreationDate="2018-11-12T05:41:57.470" UserId="9661" Text="finding the projection matrix for one point perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="21970" PostHistoryTypeId="3" PostId="8255" RevisionGUID="ae1d71b4-2e81-4b33-b9b5-6ae54754ea15" CreationDate="2018-11-12T05:41:57.470" UserId="9661" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21971" PostHistoryTypeId="5" PostId="2516" RevisionGUID="f475bd06-6931-4ceb-97ef-c7c0f687eb10" CreationDate="2018-11-12T09:50:09.613" UserId="537" Comment="added 1 character in body; edited title" Text="I am writing a software and I need to represent an graph in a orthogonal manner from topological data (vector of edges,vertices and their connectivity data)&#xD;&#xA;&#xD;&#xA;**Graphs** consist of a set of **vertices** and a set of **edges**, each connecting two vertices.A vertex may have any number of connected edges so it makes the problem a lot more complicated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have read some articles and its looks like that the **Kandinsky model** is the post popular one. However I just don't know the algorithm, any other solution (algorithm) that solve the problem is also very welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Added after edit**&#xD;&#xA;&#xD;&#xA;The following picture shows a real world example for an electricity network which should be considered as raw data, in order to create a graph from this network, some preliminary tasks must be done. &#xD;&#xA;&#xD;&#xA;Input Data:&#xD;&#xA;&#xD;&#xA;[![Input Data][1]][1]&#xD;&#xA;&#xD;&#xA;The result I am looking for is something like below, &#xD;&#xA;there are some characteristics if you take a look much closer : &#xD;&#xA;&#xD;&#xA;The Red Polygon in the middle of the above picture(input data) represents an electricity substation which is a node itself and can be connected to more than 4 edges.&#xD;&#xA;There are more red polygons but only one can be fit into the above picture however as you may see, the following picture could cover much more than a red polygon that means it can map a bigger area, so the following picture is much more denser.&#xD;&#xA;&#xD;&#xA;In Schematics diagrams, red polygons (Substations) usually maintain their position against each other relatively so if we manage to see beyond the extents of the above map by zooming out for example, we should almost see a triangle that is obviously can be seen at the below while having the left one at the left, the down one at the down ..... (this is not a rule, but I thought it could be a head start for desired algorithm)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Orthogonal Diagram:&#xD;&#xA;&#xD;&#xA;[![Orthogonal Schematic][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pJofq.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5gffC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21972" PostHistoryTypeId="4" PostId="2516" RevisionGUID="f475bd06-6931-4ceb-97ef-c7c0f687eb10" CreationDate="2018-11-12T09:50:09.613" UserId="537" Comment="added 1 character in body; edited title" Text="How to draw an orthogonal graph from its edges and vertices data?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21974" PostHistoryTypeId="2" PostId="8257" RevisionGUID="4edcf856-8344-4186-8f84-e91d5783d7cd" CreationDate="2018-11-12T11:06:11.270" UserId="4943" Text="I assume the term *object description* refers to the set of 3D vertices a mesh is made of. And I also assume *reference frame* actually means *coordinate space*. For a book on computer graphics, it sure uses some very uncommon words. &#xD;&#xA;&#xD;&#xA;In computer graphics, we often have to transform a set of vertices from one coordinate space to another. For example, an artist may have modelled a rubber ducky, aligned in such a way that it looks down the positive x-axis and it uses centimeters for its units. &#xD;&#xA;&#xD;&#xA;When we place the ducky in our world (let's say it uses *meters* as the primary unit), we scale, rotate and translate it so that it neatly floats on the water in a bath tub.&#xD;&#xA;&#xD;&#xA;Then we have our camera, which can move freely around in our scene with its own translation and rotation parameters. And finally there is the notion of *projection*, which takes into account the field of view and the aspect ratio of our frame to project the 3D point onto a 2D image.&#xD;&#xA;&#xD;&#xA;Our job is to calculate exactly where in our 2D image the 3D vertex ends up, if at all. And for this, we will have to go through the sequence of all our coordinate spaces: from object to world to camera (a.k.a. view) to projection.&#xD;&#xA;&#xD;&#xA;So that's how most graphics programmers visualise this process and hence why the book also follows this sequence: it takes the object and follows it through its transformations until it ends up in our 2D image.&#xD;&#xA;&#xD;&#xA;It seems you prefer it the other way around: you take the camera as a fixed object and rotate the world around it. But you have to admit this isn't very logical, as the camera sure isn't fixed and the world does not revolve around it.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="21975" PostHistoryTypeId="2" PostId="8258" RevisionGUID="afbe5e4d-dbfc-498f-9d11-81723672a191" CreationDate="2018-11-12T14:41:25.110" UserId="9678" Text="I recently learnt about the binary representation of Pascal's triangle. Here is what it looks like[![enter image description here][1]][1]&#xD;&#xA;I am a java learner. Is there a way for me to find the java source code to graph this binary representation?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j2D4J.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21976" PostHistoryTypeId="1" PostId="8258" RevisionGUID="afbe5e4d-dbfc-498f-9d11-81723672a191" CreationDate="2018-11-12T14:41:25.110" UserId="9678" Text="Binary representation of Pascal's triangle" ContentLicense="CC BY-SA 4.0" />
  <row Id="21977" PostHistoryTypeId="3" PostId="8258" RevisionGUID="afbe5e4d-dbfc-498f-9d11-81723672a191" CreationDate="2018-11-12T14:41:25.110" UserId="9678" Text="|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21979" PostHistoryTypeId="2" PostId="8259" RevisionGUID="79ab51ca-a705-41be-a730-3b690a2a7ba4" CreationDate="2018-11-12T20:40:40.417" UserId="7334" Text="I'm testing my path tracer for specular surfaces. Images rendered with my own code have very noisy appearance, and I think they look like variance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I use point light and the bunny is of mirror material, walls are matte. If it is the problem with sampling, how should I modify the program. To my understanding, point lights are specially handled and thus the sampling results should be a constant value. So I don't think the noise is caused by light sampling. So could there be any bugs?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When only matte material exists in the scene, there are also variance, but not that bad, and global illumination effects are visible. So what could the problem?&#xD;&#xA;&#xD;&#xA;&gt;specular bunny:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&gt; matte bunny:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;For the specular bunny image, spp is 4. Since it is a point light, wi is directly set to the vector between point light and intersection point when calculating direct illumination, so there is actually no &quot;sampling&quot;. When computing scattering directions, BRDF is matte when intersecting the wall, and BRDF is specular reflection when the ray hit the bunny.&#xD;&#xA;&#xD;&#xA;Matte BRDF is cosine weighted sampled, while specular reflection just use the perfect reflection direction.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PLlZu.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LH2Ei.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21980" PostHistoryTypeId="1" PostId="8259" RevisionGUID="79ab51ca-a705-41be-a730-3b690a2a7ba4" CreationDate="2018-11-12T20:40:40.417" UserId="7334" Text="High variance in path tracing specular objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="21981" PostHistoryTypeId="3" PostId="8259" RevisionGUID="79ab51ca-a705-41be-a730-3b690a2a7ba4" CreationDate="2018-11-12T20:40:40.417" UserId="7334" Text="|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21982" PostHistoryTypeId="50" PostId="8130" RevisionGUID="2de8433c-cc04-46ba-9505-92870bd58955" CreationDate="2018-11-12T22:01:05.163" UserId="-1" />
  <row Id="21984" PostHistoryTypeId="6" PostId="8259" RevisionGUID="59c6becd-060c-4d92-934c-e1e0a079eb6c" CreationDate="2018-11-13T00:26:12.687" UserId="7334" Comment="edited tags" Text="|raytracing|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21985" PostHistoryTypeId="2" PostId="8260" RevisionGUID="cfbc3dd9-bf9c-4aa0-afe6-bde3fd13b327" CreationDate="2018-11-13T13:00:28.957" UserId="9684" Text="I'm trying to re-implement Blenders ([libmv][1]) [polynomal lens distortion model](https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66) with [shadertoy](https://www.shadertoy.com/), in order to apply the lens distortion in another application ideally by generating a STMap for that. I think I'm close, but when passing the same values `k1=0.1 k2=0.0 k3=0.0` the resulting distortion is still too heavy in comparison to the distorted image out of Blender.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Based on: &#xD;&#xA;    // https://www.shadertoy.com/view/lslGRN&#xD;&#xA;    // https://www.shadertoy.com/view/XdfGzH&#xD;&#xA;    &#xD;&#xA;    vec3 color = vec3(0.4,0.4,0.4);&#xD;&#xA;    float lens = 24.0; &#xD;&#xA;    &#xD;&#xA;    //note: period of 2, [-1;1]=/\ &#xD;&#xA;    float sawtooth( float t ) &#xD;&#xA;    {&#xD;&#xA;    	return abs(mod(abs(t), 2.0)-1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec2 BarrelDistort(vec2 p)&#xD;&#xA;    {&#xD;&#xA;        float theta  = atan(p.y, p.x);&#xD;&#xA;        float radius = length(p);&#xD;&#xA;        radius = pow(radius, 1.2);&#xD;&#xA;        p.x = radius * cos(theta);&#xD;&#xA;        p.y = radius * sin(theta);&#xD;&#xA;        return (1.0 * (p));&#xD;&#xA;    }   &#xD;&#xA;    &#xD;&#xA;    vec2 BlenderDistort(vec2 p)&#xD;&#xA;    {&#xD;&#xA;        // https://en.wikipedia.org/wiki/Distortion_(optics)&#xD;&#xA;        // https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66&#xD;&#xA;        float x = p.x;&#xD;&#xA;    	float y = p.y;&#xD;&#xA;        &#xD;&#xA;        float k1 = .1/2.0;&#xD;&#xA;        float k2 = .0;&#xD;&#xA;        float k3 = .0;&#xD;&#xA;        &#xD;&#xA;        float p1 = .0;&#xD;&#xA;        float p2 = .0;&#xD;&#xA;        &#xD;&#xA;        float r2 = x*x + y*y;&#xD;&#xA;        float r4 = r2 * r2;&#xD;&#xA;        float r6 = r4 * r2;&#xD;&#xA;        //float r_coeff = (T(1) + k1*r2 + k2*r4 + k3*r6);&#xD;&#xA;        float r_coeff = (1.0 + k1*r2 + k2*r4 + k3*r6);&#xD;&#xA;        //float xd = x * r_coeff + T(2)*p1*x*y + p2*(r2 + T(2)*x*x);&#xD;&#xA;        float xd = x * r_coeff + 2.0*p1*x*y + p2*(r2 + 2.0*x*x);&#xD;&#xA;        float yd = y * r_coeff + 2.0*p2*x*y + p1*(r2 + 2.0*y*y);&#xD;&#xA;    	&#xD;&#xA;    	return vec2(xd, yd);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;    	vec2 uv = fragCoord.xy / iResolution.xy;    &#xD;&#xA;        vec2 normalizedUV = (fragCoord.xy/(iResolution.xy/2.0))-1.0;&#xD;&#xA;            &#xD;&#xA;    	vec2 dist = BlenderDistort(normalizedUV);	&#xD;&#xA;        vec2 uv_transform = vec2(.5)+vec2(.5)*dist;&#xD;&#xA;        &#xD;&#xA;    	vec3 outcol = vec3(0.0);&#xD;&#xA;    	//outcol += texture( iChannel0, vec2(0,1)+vec2(1,-1)*uv ).rgb;&#xD;&#xA;        outcol += texture( iChannel0, uv_transform ).rgb;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        // Draw Lines&#xD;&#xA;    	vec2 div = 30.0 * vec2(1.0, iResolution.y / iResolution.x );&#xD;&#xA;    	float lines = 0.0;&#xD;&#xA;    	lines += smoothstep( 0.2, 0.0, sawtooth( dist.x*2.0*div.x ) );&#xD;&#xA;    	lines += smoothstep( 0.2, 0.0, sawtooth( dist.y*2.0*div.y ) );&#xD;&#xA;    	lines = clamp( lines, 0.0, 1.0 );&#xD;&#xA;        &#xD;&#xA;        //outcol *= vec3(1.0-lines); //black&#xD;&#xA;    	//outcol += vec3(lines); //white&#xD;&#xA;    &#xD;&#xA;    	//note: force black outside valid range	&#xD;&#xA;    	vec2 valid = step( vec2(-1.0), dist ) * step( dist, vec2(1.0) );&#xD;&#xA;    	outcol *= valid.x*valid.y;&#xD;&#xA;    	&#xD;&#xA;    	fragColor = vec4( outcol,1.0 );&#xD;&#xA;    &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*Test image undistorted*&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;*Test image distorted in Blender k1=0.1 k2=0.0 k3=0.0*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Q:** What I'm missing in order to match Blender's polynomal lens distortion model?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/libmv/libmv&#xD;&#xA;  [2]: https://i.stack.imgur.com/s2evX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hPh8I.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21986" PostHistoryTypeId="1" PostId="8260" RevisionGUID="cfbc3dd9-bf9c-4aa0-afe6-bde3fd13b327" CreationDate="2018-11-13T13:00:28.957" UserId="9684" Text="How to match Blenders polynomal lens distortion model with GLSL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21987" PostHistoryTypeId="3" PostId="8260" RevisionGUID="cfbc3dd9-bf9c-4aa0-afe6-bde3fd13b327" CreationDate="2018-11-13T13:00:28.957" UserId="9684" Text="|shader|mathematics|fragment-shader|camera|distortion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21988" PostHistoryTypeId="5" PostId="8260" RevisionGUID="79dd7160-55a1-45b0-923c-1b17024c9dfc" CreationDate="2018-11-13T16:07:32.140" UserId="9684" Comment="spelling" Text="I'm trying to re-implement Blenders ([libmv][1]) [polynomial lens distortion model](https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66) using [shadertoy](https://www.shadertoy.com/), in order to apply the lens distortion in another application ideally by generating a STMap for that. I think I'm close, but when passing the same values `k1=0.1 k2=0.0 k3=0.0` the resulting distortion is still too heavy in comparison to the distorted image out of Blender.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Based on: &#xD;&#xA;    // https://www.shadertoy.com/view/lslGRN&#xD;&#xA;    // https://www.shadertoy.com/view/XdfGzH&#xD;&#xA;    &#xD;&#xA;    vec3 color = vec3(0.4,0.4,0.4);&#xD;&#xA;    float lens = 24.0; &#xD;&#xA;    &#xD;&#xA;    //note: period of 2, [-1;1]=/\ &#xD;&#xA;    float sawtooth( float t ) &#xD;&#xA;    {&#xD;&#xA;    	return abs(mod(abs(t), 2.0)-1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec2 BarrelDistort(vec2 p)&#xD;&#xA;    {&#xD;&#xA;        float theta  = atan(p.y, p.x);&#xD;&#xA;        float radius = length(p);&#xD;&#xA;        radius = pow(radius, 1.2);&#xD;&#xA;        p.x = radius * cos(theta);&#xD;&#xA;        p.y = radius * sin(theta);&#xD;&#xA;        return (1.0 * (p));&#xD;&#xA;    }   &#xD;&#xA;    &#xD;&#xA;    vec2 BlenderDistort(vec2 p)&#xD;&#xA;    {&#xD;&#xA;        // https://en.wikipedia.org/wiki/Distortion_(optics)&#xD;&#xA;        // https://github.com/sobotka/blender/blob/master/intern/libmv/libmv/simple_pipeline/distortion_models.h#L66&#xD;&#xA;        float x = p.x;&#xD;&#xA;    	float y = p.y;&#xD;&#xA;        &#xD;&#xA;        float k1 = .1/2.0;&#xD;&#xA;        float k2 = .0;&#xD;&#xA;        float k3 = .0;&#xD;&#xA;        &#xD;&#xA;        float p1 = .0;&#xD;&#xA;        float p2 = .0;&#xD;&#xA;        &#xD;&#xA;        float r2 = x*x + y*y;&#xD;&#xA;        float r4 = r2 * r2;&#xD;&#xA;        float r6 = r4 * r2;&#xD;&#xA;        //float r_coeff = (T(1) + k1*r2 + k2*r4 + k3*r6);&#xD;&#xA;        float r_coeff = (1.0 + k1*r2 + k2*r4 + k3*r6);&#xD;&#xA;        //float xd = x * r_coeff + T(2)*p1*x*y + p2*(r2 + T(2)*x*x);&#xD;&#xA;        float xd = x * r_coeff + 2.0*p1*x*y + p2*(r2 + 2.0*x*x);&#xD;&#xA;        float yd = y * r_coeff + 2.0*p2*x*y + p1*(r2 + 2.0*y*y);&#xD;&#xA;    	&#xD;&#xA;    	return vec2(xd, yd);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;    	vec2 uv = fragCoord.xy / iResolution.xy;    &#xD;&#xA;        vec2 normalizedUV = (fragCoord.xy/(iResolution.xy/2.0))-1.0;&#xD;&#xA;            &#xD;&#xA;    	vec2 dist = BlenderDistort(normalizedUV);	&#xD;&#xA;        vec2 uv_transform = vec2(.5)+vec2(.5)*dist;&#xD;&#xA;        &#xD;&#xA;    	vec3 outcol = vec3(0.0);&#xD;&#xA;    	//outcol += texture( iChannel0, vec2(0,1)+vec2(1,-1)*uv ).rgb;&#xD;&#xA;        outcol += texture( iChannel0, uv_transform ).rgb;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        // Draw Lines&#xD;&#xA;    	vec2 div = 30.0 * vec2(1.0, iResolution.y / iResolution.x );&#xD;&#xA;    	float lines = 0.0;&#xD;&#xA;    	lines += smoothstep( 0.2, 0.0, sawtooth( dist.x*2.0*div.x ) );&#xD;&#xA;    	lines += smoothstep( 0.2, 0.0, sawtooth( dist.y*2.0*div.y ) );&#xD;&#xA;    	lines = clamp( lines, 0.0, 1.0 );&#xD;&#xA;        &#xD;&#xA;        //outcol *= vec3(1.0-lines); //black&#xD;&#xA;    	//outcol += vec3(lines); //white&#xD;&#xA;    &#xD;&#xA;    	//note: force black outside valid range	&#xD;&#xA;    	vec2 valid = step( vec2(-1.0), dist ) * step( dist, vec2(1.0) );&#xD;&#xA;    	outcol *= valid.x*valid.y;&#xD;&#xA;    	&#xD;&#xA;    	fragColor = vec4( outcol,1.0 );&#xD;&#xA;    &#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;*Test image undistorted*&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;*Test image distorted in Blender k1=0.1 k2=0.0 k3=0.0*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Q:** What I'm missing in order to match Blender's polynomial lens distortion model?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/libmv/libmv&#xD;&#xA;  [2]: https://i.stack.imgur.com/s2evX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hPh8I.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="21989" PostHistoryTypeId="4" PostId="8260" RevisionGUID="79dd7160-55a1-45b0-923c-1b17024c9dfc" CreationDate="2018-11-13T16:07:32.140" UserId="9684" Comment="spelling" Text="How to match Blenders polynomial lens distortion model with GLSL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21990" PostHistoryTypeId="2" PostId="8261" RevisionGUID="76576c60-e339-403c-b365-c167c95e2d7f" CreationDate="2018-11-13T21:26:08.210" UserId="4768" Text="When reading on transformation matrices over a range of distinct source material, there are some main concepts that you must understand, which are as follows.&#xD;&#xA;&#xD;&#xA;Column vs Row Notation&#xD;&#xA;----------------------&#xD;&#xA;&#xD;&#xA;Some authors write vectors as a single row matrix (1x3), while others write them as a single column matrix (3x1). The latter seems to be the preferred representation in most modern books on computer graphics. The main difference between the two notations is that when using the former, matrices will be multiplied on the right side of the vector, and when using the latter they will be multiplied on the left. When dealing with linear transformations, such as rotation matrices, in a particular notation, they are represented as the transposed matrix in the other notation. For instance, the rotation of point $p=(1, 1)$ for an angle $\theta$ in the plane is show below. As you can easily see, $Row(x)^T = Column(x)$, i.e., one notation is the transpose of the other.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;Row(p) =&amp; &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; sin(\theta)\\&#xD;&#xA;\text{-}sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;Column(p) =&amp; &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; \text{-}\sin(\theta)\\&#xD;&#xA;\sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The [website you linked][1] uses **row** notation. This is important because if you read about the perspective matrix in other sources, you may see the result written as the transpose matrix if the author used column notation.&#xD;&#xA;&#xD;&#xA;Basis Orientation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[In the website][1], the camera basis vectors $X_1$, $Y_1$, and $Z_1$ form a left-handed coordinate system, because $X_1 \times Y_1 = - Z_1$. This is important as well, as you may notice some sign changes in the perspective matrix if the system was right-handed. You can read more about handedness in [Wikipedia][2]. As with row notation, this is another arbitrary decision that the author has taken.&#xD;&#xA;&#xD;&#xA;Perspective Projection&#xD;&#xA;----------------------&#xD;&#xA;&#xD;&#xA;Given the appropriate basis, and a projection plane at a distance d from the origin, perspective projection is a simple exercise in similar triangles, as shown below.&#xD;&#xA;&#xD;&#xA;[![Perspective Projection Diagram)][3]][3]&#xD;&#xA;&#xD;&#xA;The point $\mathbf{P} = (x,y,z)$ when projected onto the plane gives another point $\mathbf{p} = (x_p, y_p, z_p)$ that can be written as (in row notation) &#xD;&#xA;$$\mathbf{p} = \begin{bmatrix}&#xD;&#xA; d \displaystyle \frac{x}{z} &amp; d \displaystyle \frac{y}{z} &amp; d&#xD;&#xA;\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Now we just need to put this formula into matrix form (again, in row notation).&#xD;&#xA;&#xD;&#xA;Homogeneous/Projective Coordinates&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If we just use the raw 3D coordinates of $\bf P$ there is no way to represent the formula for $\bf p$ as a matrix multiplication. The use of [homogeneous coordinates][4] allows us exactly to do that. We start by augmenting $\bf P$ onto the fourth dimension, by defining it as $\mathbf{P} = (x, y, z, 1)$, and we use 4x4 homogeneous matrices instead of 3x3 matrices to represent transformations. I strongly urge you to read on [projective spaces][5], as otherwise the following explanation will look like too much hand-waving as I am not going to dwell on mathematical formalities.&#xD;&#xA;&#xD;&#xA;Now, in this new space every point with coordinates $(wx,wy,wz,w)$ can be mapped onto the point $(x,y,z,1)$ by a simple division by w. We can use this property in our advantage to fill-out a matrix in such a way that after the division by w is made, we get exactly the perspective projection formula for our point.     &#xD;&#xA; &#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; y &amp; z &amp; \displaystyle\frac{z}{d}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; y &amp; z &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; \displaystyle \frac{1}{d}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now if we take the point $(x, y, z, \frac{z}{d})$ and we divide it by its last coordinate, we get $(d\displaystyle\frac{x}{z}, d\displaystyle\frac{y}{z}, d, 1)$, which are exactly the coordinates of our projected point if we just ignore the augmentation onto fourth dimensional space that we did (i.e., discard the last coordinate).&#xD;&#xA;&#xD;&#xA;As you can see, the &quot;perspective matrix&quot; does not actually do any perspective transformation, it just &quot;prepares&quot; the transformation by coding a specific value in the last coordinate, such that after all coordinates are divided by it, we get the true projection.&#xD;&#xA;&#xD;&#xA;  [1]: https://people.eecs.berkeley.edu/~barsky/perspective.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Orientation_%28vector_space%29&#xD;&#xA;  [3]: https://i.stack.imgur.com/Eh4rc.jpg&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Homogeneous_coordinates&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="21991" PostHistoryTypeId="50" PostId="7643" RevisionGUID="721d5cea-9066-4647-8e0f-d389df56f7b7" CreationDate="2018-11-13T23:02:30.470" UserId="-1" />
  <row Id="21992" PostHistoryTypeId="2" PostId="8262" RevisionGUID="f02bdfa0-0d08-4163-83c3-394edeeba6d5" CreationDate="2018-11-14T02:20:22.877" UserId="9661" Text="Consider this figure for projection.  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;There are two equations that give value for the xp and yp coordinates:&#xD;&#xA;&#xD;&#xA;- $x_p=x.\frac{(z_{vp}-z_{prp})}{h}+ x_{prp}.\frac{(z-z_{vp})}{h}$ and&#xD;&#xA;- $y_p=y.\frac{(z_{vp}-z_{prp})}{h}+ y_{prp}.\frac{(z-z_{vp})}{h}$&#xD;&#xA;&#xD;&#xA;and then it explains in a paragraph: &quot;Setting up matrix elements for obtaining the homogeneous-coordinate $x_h$ and $y_h$ values in the given equations is straightforward, but we must also structure the matrix to preserve depth (z-value) information. Otherwise, the z coordinates are distorted by the homogeneous-division parameter h. We can do this by setting up the matrix elements for the z transformation so as to normalize the perspective-projection $z_p$ coordinates. There are various ways that we could choose the matrix elements to produce the homogeneous coordinates  and the normalized $z_p$ value for spatial position (x, y, z).&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, I have some questions regarding this:  &#xD;&#xA;&#xD;&#xA;- What does it mean to preserve depth(z-values)?&#xD;&#xA;- What does it mean to normalize the perspective-projection zp coordinates?&#xD;&#xA;- How to perform this normalization?&#xD;&#xA;- How does this normalization preserve z-values?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qmXdM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="21993" PostHistoryTypeId="1" PostId="8262" RevisionGUID="f02bdfa0-0d08-4163-83c3-394edeeba6d5" CreationDate="2018-11-14T02:20:22.877" UserId="9661" Text="preserving z-values during projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="21994" PostHistoryTypeId="3" PostId="8262" RevisionGUID="f02bdfa0-0d08-4163-83c3-394edeeba6d5" CreationDate="2018-11-14T02:20:22.877" UserId="9661" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="21995" PostHistoryTypeId="5" PostId="8261" RevisionGUID="c1b7a1f6-3d4c-40f0-b8bc-1dfddc6c389a" CreationDate="2018-11-14T03:27:01.687" UserId="4768" Comment="Fixed a typing error in the perspective matrix" Text="When reading on transformation matrices over a range of distinct source material, there are some main concepts that you must understand, which are as follows.&#xD;&#xA;&#xD;&#xA;Column vs Row Notation&#xD;&#xA;----------------------&#xD;&#xA;&#xD;&#xA;Some authors write vectors as a single row matrix (1x3), while others write them as a single column matrix (3x1). The latter seems to be the preferred representation in most modern books on computer graphics. The main difference between the two notations is that when using the former, matrices will be multiplied on the right side of the vector, and when using the latter they will be multiplied on the left. When dealing with linear transformations, such as rotation matrices, in a particular notation, they are represented as the transposed matrix in the other notation. For instance, the rotation of point $p=(1, 1)$ for an angle $\theta$ in the plane is show below. As you can easily see, $Row(x)^T = Column(x)$, i.e., one notation is the transpose of the other.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;Row(p) =&amp; &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; sin(\theta)\\&#xD;&#xA;\text{-}sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;Column(p) =&amp; &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; \text{-}\sin(\theta)\\&#xD;&#xA;\sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The [website you linked][1] uses **row** notation. This is important because if you read about the perspective matrix in other sources, you may see the result written as the transpose matrix if the author used column notation.&#xD;&#xA;&#xD;&#xA;Basis Orientation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[In the website][1], the camera basis vectors $X_1$, $Y_1$, and $Z_1$ form a left-handed coordinate system, because $X_1 \times Y_1 = - Z_1$. This is important as well, as you may notice some sign changes in the perspective matrix if the system was right-handed. You can read more about handedness in [Wikipedia][2]. As with row notation, this is another arbitrary decision that the author has taken.&#xD;&#xA;&#xD;&#xA;Perspective Projection&#xD;&#xA;----------------------&#xD;&#xA;&#xD;&#xA;Given the appropriate basis, and a projection plane at a distance d from the origin, perspective projection is a simple exercise in similar triangles, as shown below.&#xD;&#xA;&#xD;&#xA;[![Perspective Projection Diagram)][3]][3]&#xD;&#xA;&#xD;&#xA;The point $\mathbf{P} = (x,y,z)$ when projected onto the plane gives another point $\mathbf{p} = (x_p, y_p, z_p)$ that can be written as (in row notation) &#xD;&#xA;$$\mathbf{p} = \begin{bmatrix}&#xD;&#xA; d \displaystyle \frac{x}{z} &amp; d \displaystyle \frac{y}{z} &amp; d&#xD;&#xA;\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Now we just need to put this formula into matrix form (again, in row notation).&#xD;&#xA;&#xD;&#xA;Homogeneous/Projective Coordinates&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If we just use the raw 3D coordinates of $\bf P$ there is no way to represent the formula for $\bf p$ as a matrix multiplication. The use of [homogeneous coordinates][4] allows us exactly to do that. We start by augmenting $\bf P$ onto the fourth dimension, by defining it as $\mathbf{P} = (x, y, z, 1)$, and we use 4x4 homogeneous matrices instead of 3x3 matrices to represent transformations. I strongly urge you to read on [projective spaces][5], as otherwise the following explanation will look like too much hand-waving as I am not going to dwell on mathematical formalities.&#xD;&#xA;&#xD;&#xA;Now, in this new space every point with coordinates $(wx,wy,wz,w)$ can be mapped onto the point $(x,y,z,1)$ by a simple division by w. We can use this property in our advantage to fill-out a matrix in such a way that after the division by w is made, we get exactly the perspective projection formula for our point.     &#xD;&#xA; &#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; y &amp; z &amp; \displaystyle\frac{z}{d}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; y &amp; z &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; \displaystyle \frac{1}{d}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 0&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now if we take the point $(x, y, z, \frac{z}{d})$ and we divide it by its last coordinate, we get $(d\displaystyle\frac{x}{z}, d\displaystyle\frac{y}{z}, d, 1)$, which are exactly the coordinates of our projected point if we just ignore the augmentation onto fourth dimensional space that we did (i.e., discard the last coordinate).&#xD;&#xA;&#xD;&#xA;As you can see, the &quot;perspective matrix&quot; does not actually do any perspective transformation, it just &quot;prepares&quot; the transformation by coding a specific value in the last coordinate, such that after all coordinates are divided by it, we get the true projection.&#xD;&#xA;&#xD;&#xA;  [1]: https://people.eecs.berkeley.edu/~barsky/perspective.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Orientation_%28vector_space%29&#xD;&#xA;  [3]: https://i.stack.imgur.com/Eh4rc.jpg&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Homogeneous_coordinates&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="22002" PostHistoryTypeId="10" PostId="8258" RevisionGUID="3947accf-24a9-44bc-8d2a-38800dbfa5eb" CreationDate="2018-11-14T12:45:52.340" UserId="2041" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:3003,&quot;DisplayName&quot;:&quot;user1118321&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="22003" PostHistoryTypeId="50" PostId="4632" RevisionGUID="6d068ad4-5028-4ff4-98bc-95f9926b3c04" CreationDate="2018-11-14T14:03:00.630" UserId="-1" />
  <row Id="22008" PostHistoryTypeId="2" PostId="8265" RevisionGUID="cd7f10f7-0623-45e2-908d-e607827b02c9" CreationDate="2018-11-14T16:40:37.993" UserId="4768" Text="Given your equations (which i just assume are correct):&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;x_p &amp;= x \frac{z_{vp}-z_{prp}}{z-z_{prp}}+x_{prp} \frac{z-z_{vp}}{z-z_{prp}}\\&#xD;&#xA;y_p &amp;= y \frac{z_{vp}-z_{prp}}{z-z_{prp}}+y_{prp} \frac{z-z_{vp}}{z-z_{prp}}&#xD;&#xA;\end{align},&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;if we take $(x_{prp}, y_{prp}, z_{prp}) = (0, 0, 0)$, then we have&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;x_p &amp;= x\frac{z_{vp}}{z}\\&#xD;&#xA;y_p &amp;= y\frac{z_{vp}}{z}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Assuming the projection plane is at distance $d$ from the origin, and, by your drawing, that the projection plane is on the negative side of the Z axis, we have $z_{vp} = -d$, which leads to&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;x_p &amp;= - x\frac{d}{z}\\&#xD;&#xA;y_p &amp;= - y\frac{d}{z}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now we can follow the same reasoning (homogeneous coordinates) as [in my answer to your other question][1] (using column notation) to write&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x\\y\\z\\ \frac{-z}{d}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1&amp;0&amp;0&amp;0\\&#xD;&#xA;0&amp;1&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;1&amp;0\\&#xD;&#xA;0&amp;0&amp;\frac{-1}{d}&amp;0&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x\\y\\z\\1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;which after the division by the last coordinate will give the projected point. Notice that because we are writing it in column notation, the perspective matrix is the transpose of the matrix in your [other question][1]. Also, the negative sign is because the camera reference frame is a right-handed one.&#xD;&#xA; &#xD;&#xA;As for the second textbook that you are reading, I cannot understand why you would have a negative sign only in the x axis without knowing more about the camera reference frame. By the diagram you posted, there should not be a negative sign.&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/8255/finding-the-projection-matrix-for-one-point-perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="22009" PostHistoryTypeId="2" PostId="8266" RevisionGUID="4f25d801-8905-4bd0-98b9-2ac2a7190305" CreationDate="2018-11-14T17:58:25.930" UserId="87" Text="Suballocating from a larger buffer is absolutely the way to go, with caveats. I'm coming more from a DirectX/Vulkan side of things, but this should apply equally to OpenGL (I just won't have direct API calls here in this answer). The things to consider are the following:&#xD;&#xA;&#xD;&#xA;- Do you need to index into the larger buffer, or are you OK with binding the resource to the offset each time?&#xD;&#xA;- Have you taken care of any/all alignment restrictions for your uniforms that are packed together (256 byte alignment is common)?&#xD;&#xA;&#xD;&#xA;Newer graphics APIs have a &quot;dynamic offset&quot; you can specify with the draw command which is a pretty fast way to indirectly access a subregion of a buffer. However, assuming you are triple-buffering data that's mutable, there should be little to no contention in the driver for binding the data (just some fixed overhead).&#xD;&#xA;&#xD;&#xA;In summary, yes, allocating larger regions of memory/buffers and subleasing those regions is considered best practice. This applies even to objects with different shaders (if your allocator can handle it)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22010" PostHistoryTypeId="2" PostId="8267" RevisionGUID="8888ffb5-5444-478c-baf5-a1f9658dd711" CreationDate="2018-11-14T20:07:59.903" UserId="1940" Text="I have a bunch of points that are the control vertices of a cubic catmull-rom spline. I would like to convert these to the control vertices of a cubic bspline.&#xD;&#xA;&#xD;&#xA;I believe I can do this using this following relation:&#xD;&#xA;$\boldsymbol{t} * \boldsymbol{B}_{\text{catmull}} * \boldsymbol{V}_{\text{catmull}} = \boldsymbol{t} * \boldsymbol{B}_{\text{bspline}} * \boldsymbol{V}_{\text{bspline}}$&#xD;&#xA;&#xD;&#xA;where $\boldsymbol{B}$ is the basis matrix and $\boldsymbol{V}$ is a vector of the control vertices. To get the control vertices of the bspline, the formula just becomes:&#xD;&#xA;&#xD;&#xA;$\boldsymbol{V}_{\text{bspline}} = \boldsymbol{B}^{-1}_{\text{bspline}} * \boldsymbol{B}_{\text{catmull}} * \boldsymbol{V}_{\text{catmull}}$&#xD;&#xA;&#xD;&#xA;My question is once I process say 4 control vertices of the catmull rom spline, to get 4 vertices of the bspline, how do I process other vertices (i.e the order). If a catmull-rom spline has n-vertices with cubic segments, then we have at the most $n-3$ segments. So if we have say 5 vertices, $v_0, v_1, v_2, v_3$ gives us 4 vertices for bspline. How would I go about computing the other curve segment in the bspline?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22011" PostHistoryTypeId="1" PostId="8267" RevisionGUID="8888ffb5-5444-478c-baf5-a1f9658dd711" CreationDate="2018-11-14T20:07:59.903" UserId="1940" Text="Conversion from cubic catmull-rom spline to cubic b-spline" ContentLicense="CC BY-SA 4.0" />
  <row Id="22012" PostHistoryTypeId="3" PostId="8267" RevisionGUID="8888ffb5-5444-478c-baf5-a1f9658dd711" CreationDate="2018-11-14T20:07:59.903" UserId="1940" Text="|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22013" PostHistoryTypeId="5" PostId="8261" RevisionGUID="37ed7fae-76ec-4c81-b96a-9f348553664b" CreationDate="2018-11-15T03:23:45.957" UserId="4768" Comment="fixed typo" Text="When reading on transformation matrices over a range of distinct source material, there are some main concepts that you must understand, which are as follows.&#xD;&#xA;&#xD;&#xA;Column vs Row Notation&#xD;&#xA;----------------------&#xD;&#xA;&#xD;&#xA;Some authors write vectors as a single row matrix (1x3), while others write them as a single column matrix (3x1). The latter seems to be the preferred representation in most modern books on computer graphics. The main difference between the two notations is that when using the former, matrices will be multiplied on the right side of the vector, and when using the latter they will be multiplied on the left. When dealing with linear transformations, such as rotation matrices, in a particular notation, they are represented as the transposed matrix in the other notation. For instance, the rotation of point $p=(1, 1)$ for an angle $\theta$ in the plane is shown below. As you can easily see, $Row(x)^T = Column(x)$, i.e., one notation is the transpose of the other.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;Row(p) =&amp; &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; sin(\theta)\\&#xD;&#xA;\text{-}sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;Column(p) =&amp; &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos(\theta) &amp; \text{-}\sin(\theta)\\&#xD;&#xA;\sin(\theta) &amp; \cos(\theta)&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The [website you linked][1] uses **row** notation. This is important because if you read about the perspective matrix in other sources, you may see the result written as the transpose matrix if the author used column notation.&#xD;&#xA;&#xD;&#xA;Basis Orientation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[In the website][1], the camera basis vectors $X_1$, $Y_1$, and $Z_1$ form a left-handed coordinate system, because $X_1 \times Y_1 = - Z_1$. This is important as well, as you may notice some sign changes in the perspective matrix if the system was right-handed. You can read more about handedness in [Wikipedia][2]. As with row notation, this is another arbitrary decision that the author has taken.&#xD;&#xA;&#xD;&#xA;Perspective Projection&#xD;&#xA;----------------------&#xD;&#xA;&#xD;&#xA;Given the appropriate basis, and a projection plane at a distance d from the origin, perspective projection is a simple exercise in similar triangles, as shown below.&#xD;&#xA;&#xD;&#xA;[![Perspective Projection Diagram)][3]][3]&#xD;&#xA;&#xD;&#xA;The point $\mathbf{P} = (x,y,z)$ when projected onto the plane gives another point $\mathbf{p} = (x_p, y_p, z_p)$ that can be written as (in row notation) &#xD;&#xA;$$\mathbf{p} = \begin{bmatrix}&#xD;&#xA; d \displaystyle \frac{x}{z} &amp; d \displaystyle \frac{y}{z} &amp; d&#xD;&#xA;\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Now we just need to put this formula into matrix form (again, in row notation).&#xD;&#xA;&#xD;&#xA;Homogeneous/Projective Coordinates&#xD;&#xA;----------------------------------&#xD;&#xA;&#xD;&#xA;If we just use the raw 3D coordinates of $\bf P$ there is no way to represent the formula for $\bf p$ as a matrix multiplication. The use of [homogeneous coordinates][4] allows us exactly to do that. We start by augmenting $\bf P$ onto the fourth dimension, by defining it as $\mathbf{P} = (x, y, z, 1)$, and we use 4x4 homogeneous matrices instead of 3x3 matrices to represent transformations. I strongly urge you to read on [projective spaces][5], as otherwise the following explanation will look like too much hand-waving as I am not going to dwell on mathematical formalities.&#xD;&#xA;&#xD;&#xA;Now, in this new space every point with coordinates $(wx,wy,wz,w)$ can be mapped onto the point $(x,y,z,1)$ by a simple division by w. We can use this property in our advantage to fill-out a matrix in such a way that after the division by w is made, we get exactly the perspective projection formula for our point.     &#xD;&#xA; &#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; y &amp; z &amp; \displaystyle\frac{z}{d}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; y &amp; z &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; \displaystyle \frac{1}{d}\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 0&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now if we take the point $(x, y, z, \frac{z}{d})$ and we divide it by its last coordinate, we get $(d\displaystyle\frac{x}{z}, d\displaystyle\frac{y}{z}, d, 1)$, which are exactly the coordinates of our projected point if we just ignore the augmentation onto fourth dimensional space that we did (i.e., discard the last coordinate).&#xD;&#xA;&#xD;&#xA;As you can see, the &quot;perspective matrix&quot; does not actually do any perspective transformation, it just &quot;prepares&quot; the transformation by coding a specific value in the last coordinate, such that after all coordinates are divided by it, we get the true projection.&#xD;&#xA;&#xD;&#xA;  [1]: https://people.eecs.berkeley.edu/~barsky/perspective.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Orientation_%28vector_space%29&#xD;&#xA;  [3]: https://i.stack.imgur.com/Eh4rc.jpg&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Homogeneous_coordinates&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="22014" PostHistoryTypeId="2" PostId="8268" RevisionGUID="0e308e25-2ea3-4ec4-809d-cc546dddc95e" CreationDate="2018-11-15T03:42:40.713" UserId="1940" Text="If your bunny is purely specular, then sampling the light directly at the shade point would give no contribution since the specular BSDF is a delta BSDF. It generally evaluates to zero for any direction other than the mirror direction. If it was a glossy BSDF, then it might be possible that the pdf value could be very small so that the monte-carlo estimator $\frac{f(X)}{P(X)}$ just explodes (which is generally the source of fireflies i.e having a very small pdf and the function is large).&#xD;&#xA;&#xD;&#xA;If it was a mirror direction, then you should just see a black bunny for direct illumination and just the reflection of the surrounding scene for multiple bounces. Multiple bounces from the specular bunny should not be cause fireflies, because if you're sampling based on cosine term at the matte surface, the estimator becomes $\frac{L_i(X)f_r(X)\cos(\theta_i)}{\text{pdf}(\theta_i)}$, where $\theta_i$ is the sampled direction using BSDF sampling at the matte surface. The pdf and the $\cos(\theta_i)$ should cancel out each other perfectly. However since you're using a point light, you can never sample from the BSDF since the light is a delta light and needs an explicit connection. Hence the pdf for the estimator would be 1 all the time. The only way for large values to creep up are in the numerator. So I would suggest you to check the values by increasing bounce one by one to see when the problems start creeping in." ContentLicense="CC BY-SA 4.0" />
  <row Id="22015" PostHistoryTypeId="2" PostId="8269" RevisionGUID="2dceba43-58ab-48f2-a82d-7b749a02120e" CreationDate="2018-11-15T05:49:46.203" UserId="3024" Text="I am trying to implement the Loop-Blinn cubic curve in java using the following source codes [GPU-Curve-Rendering][1] and [WebCore][2]. Both of them are showing few arteffects and i cannot figure out why. Here are my source code:&#xD;&#xA;&#xD;&#xA;    public class CubicBezier {&#xD;&#xA;	public enum CurveType {&#xD;&#xA;		UNKNOWN, SERPENTINE, LOOP, CUSP, QUADRATIC, LINE&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	private FloatArray klm;&#xD;&#xA;	public boolean drawAdditionalTri;&#xD;&#xA;	public Array&lt;Vertex&gt; tris;&#xD;&#xA;	public Array&lt;Vertex&gt; plainTris;&#xD;&#xA;	public final float M_EPS = .00001f;&#xD;&#xA;&#xD;&#xA;	public Vector2 start;&#xD;&#xA;	public Vector2 ctrl1;&#xD;&#xA;	public Vector2 ctrl2;&#xD;&#xA;	public Vector2 end;&#xD;&#xA;	&#xD;&#xA;	boolean once = true;&#xD;&#xA;&#xD;&#xA;	public CubicBezier(Vector2 start, Vector2 ctrl1, Vector2 ctrl2, Vector2 end) {&#xD;&#xA;		this.start = start;&#xD;&#xA;		this.ctrl1 = ctrl1;&#xD;&#xA;		this.ctrl2 = ctrl2;&#xD;&#xA;		this.end = end;&#xD;&#xA;		drawAdditionalTri = false;&#xD;&#xA;		tris = new Array&lt;Vertex&gt;();&#xD;&#xA;		plainTris = new Array&lt;Vertex&gt;();&#xD;&#xA;&#xD;&#xA;		compute(start.x, start.y, ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y, -1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public void compute() {&#xD;&#xA;		tris.clear();&#xD;&#xA;		plainTris.clear();&#xD;&#xA;		drawAdditionalTri = false;&#xD;&#xA;		compute(start.x, start.y, ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y, -1);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	boolean flipSerpent = false;&#xD;&#xA;	public void compute(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3,&#xD;&#xA;			int recursiveType) {&#xD;&#xA;		Float fd1 = new Float();&#xD;&#xA;		Float fd2 = new Float();&#xD;&#xA;		Float fd3 = new Float();&#xD;&#xA;		CurveType curve_type = determineType(fd1, fd2, fd3);&#xD;&#xA;		float d1 = fd1.value, d2 = fd2.value, d3 = fd3.value;&#xD;&#xA;		System.out.println(curve_type);&#xD;&#xA;		plainTris.clear();&#xD;&#xA;		&#xD;&#xA;		float OneThird = 1.0f / 3.0f;&#xD;&#xA;		float TwoThirds = 2.0f / 3.0f;&#xD;&#xA;&#xD;&#xA;		float t1;&#xD;&#xA;		float ls;&#xD;&#xA;		float lt;&#xD;&#xA;		float ms;&#xD;&#xA;		float mt;&#xD;&#xA;&#xD;&#xA;		float ltMinusLs;&#xD;&#xA;		float mtMinusMs;&#xD;&#xA;		float lsMinusLt;&#xD;&#xA;		float ql;&#xD;&#xA;		float qm;&#xD;&#xA;&#xD;&#xA;		// bool flip&#xD;&#xA;		boolean flip = false;&#xD;&#xA;&#xD;&#xA;		// artifact on loop&#xD;&#xA;		int errorLoop = -1;&#xD;&#xA;		float splitParam = 0;&#xD;&#xA;&#xD;&#xA;		klm = new FloatArray(12);&#xD;&#xA;		for (int i = 0; i &lt; 12; i++) {&#xD;&#xA;			klm.add(0);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		switch (curve_type) {&#xD;&#xA;		case UNKNOWN:&#xD;&#xA;			break;&#xD;&#xA;		case SERPENTINE:&#xD;&#xA;			t1 = (float) Math.sqrt(9.0f * d2 * d2 - 12 * d1 * d3);&#xD;&#xA;			ls = 3.0f * d2 - t1;&#xD;&#xA;			lt = 6.0f * d1;&#xD;&#xA;			ms = 3.0f * d2 + t1;&#xD;&#xA;			mt = lt;&#xD;&#xA;			ltMinusLs = lt - ls;&#xD;&#xA;			mtMinusMs = mt - ms;&#xD;&#xA;&#xD;&#xA;			klm.set(0, ls * ms);&#xD;&#xA;			klm.set(1, ls * ls * ls);&#xD;&#xA;			klm.set(2, ms * ms * ms);&#xD;&#xA;&#xD;&#xA;			klm.set(3, OneThird * (3.0f * ls * ms - ls * mt - lt * ms));&#xD;&#xA;			klm.set(4, ls * ls * (ls - lt));&#xD;&#xA;			klm.set(5, ms * ms * (ms - mt));&#xD;&#xA;&#xD;&#xA;			klm.set(6, OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)));&#xD;&#xA;			klm.set(7, ltMinusLs * ltMinusLs * ls);&#xD;&#xA;			klm.set(8, mtMinusMs * mtMinusMs * ms);&#xD;&#xA;&#xD;&#xA;			klm.set(9, ltMinusLs * mtMinusMs);&#xD;&#xA;			klm.set(10, -(ltMinusLs * ltMinusLs * ltMinusLs));&#xD;&#xA;			klm.set(11, -(mtMinusMs * mtMinusMs * mtMinusMs));&#xD;&#xA;			System.out.println(&quot;d1 &quot; + d1);&#xD;&#xA;			for (int i = 0; i &lt; 12; i++) {&#xD;&#xA;				System.out.println(i+&quot;: &quot;+klm.get(i));&#xD;&#xA;			}&#xD;&#xA;			if (d1 &lt; 0.0f) {&#xD;&#xA;				flip = true;&#xD;&#xA;				flipSerpent = true;&#xD;&#xA;			}&#xD;&#xA;			break;&#xD;&#xA;		case LOOP:&#xD;&#xA;			t1 = (float) Math.sqrt(4.0f * d1 * d3 - 3.0f * d2 * d2);&#xD;&#xA;			ls = d2 - t1;&#xD;&#xA;			lt = 2.0f * d1;&#xD;&#xA;			ms = d2 + t1;&#xD;&#xA;			mt = lt;&#xD;&#xA;&#xD;&#xA;			// Figure out whether there is a rendering artifact requiring&#xD;&#xA;			// the curve to be subdivided by the caller.&#xD;&#xA;			ql = ls / lt;&#xD;&#xA;			qm = ms / mt;&#xD;&#xA;			if (0.0f &lt; ql &amp;&amp; ql &lt; 1.0f) {&#xD;&#xA;				errorLoop = 1;&#xD;&#xA;				splitParam = ql;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			if (0.0f &lt; qm &amp;&amp; qm &lt; 1.0f) {&#xD;&#xA;				errorLoop = 2;&#xD;&#xA;				splitParam = qm;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			ltMinusLs = lt - ls;&#xD;&#xA;			mtMinusMs = mt - ms;&#xD;&#xA;			&#xD;&#xA;			System.out.println(d1);&#xD;&#xA;&#xD;&#xA;			klm.set(0, ls * ms);&#xD;&#xA;			klm.set(1, ls * ls * ms);&#xD;&#xA;			klm.set(2, ls * ms * ms);&#xD;&#xA;			klm.set(3, OneThird * (-ls * mt - lt * ms + 3.0f * ls * ms));&#xD;&#xA;			klm.set(4, -OneThird * ls * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));&#xD;&#xA;			klm.set(5, -OneThird * ms * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));&#xD;&#xA;			klm.set(6, OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)));&#xD;&#xA;			klm.set(7, OneThird * (lt - ls) * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));&#xD;&#xA;			klm.set(8, OneThird * (mt - ms) * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));&#xD;&#xA;			klm.set(9, ltMinusLs * mtMinusMs);&#xD;&#xA;			klm.set(10, -(ltMinusLs * ltMinusLs) * mtMinusMs);&#xD;&#xA;			klm.set(11, -ltMinusLs * mtMinusMs * mtMinusMs);&#xD;&#xA;			&#xD;&#xA;			if (recursiveType == -1)&#xD;&#xA;				flip = ((d1 &gt; 0.0f &amp;&amp; klm.get(0) &lt; 0.0f) || (d1 &lt; 0.0f &amp;&amp; klm.get(0) &gt; 0.0f));&#xD;&#xA;			break;&#xD;&#xA;&#xD;&#xA;		case CUSP:&#xD;&#xA;			ls = d3;&#xD;&#xA;			lt = 3.0f * d2;&#xD;&#xA;			lsMinusLt = ls - lt;&#xD;&#xA;			klm.set(0, ls);&#xD;&#xA;			klm.set(1, ls * ls * ls);&#xD;&#xA;			klm.set(2, 1.0f);&#xD;&#xA;			klm.set(3, ls - OneThird * lt);&#xD;&#xA;			klm.set(4, ls * ls * lsMinusLt);&#xD;&#xA;			klm.set(5, 1.0f);&#xD;&#xA;			klm.set(6, ls - TwoThirds * lt);&#xD;&#xA;			klm.set(7, lsMinusLt * lsMinusLt * ls);&#xD;&#xA;			klm.set(8, 1.0f);&#xD;&#xA;			klm.set(9, lsMinusLt);&#xD;&#xA;			klm.set(10, lsMinusLt * lsMinusLt * lsMinusLt);&#xD;&#xA;			klm.set(11, 1.0f);&#xD;&#xA;			break;&#xD;&#xA;&#xD;&#xA;		case QUADRATIC:&#xD;&#xA;			klm.set(0, 0);&#xD;&#xA;			klm.set(1, 0);&#xD;&#xA;			klm.set(2, 0);&#xD;&#xA;			klm.set(3, OneThird);&#xD;&#xA;			klm.set(4, 0);&#xD;&#xA;			klm.set(5, OneThird);&#xD;&#xA;			klm.set(6, TwoThirds);&#xD;&#xA;			klm.set(7, OneThird);&#xD;&#xA;			klm.set(8, TwoThirds);&#xD;&#xA;			klm.set(9, 1);&#xD;&#xA;			klm.set(10, 1);&#xD;&#xA;			klm.set(11, 1);&#xD;&#xA;			if (d3 &lt; 0)&#xD;&#xA;				flip = true;&#xD;&#xA;			break;&#xD;&#xA;		case LINE:&#xD;&#xA;			break;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (errorLoop != -1 &amp;&amp; recursiveType == -1) {&#xD;&#xA;			System.out.println(&quot;error&quot;);&#xD;&#xA;			float x01 = (x1 - x0) * splitParam + x0;&#xD;&#xA;			float x12 = (x2 - x1) * splitParam + x1;&#xD;&#xA;			float x23 = (x3 - x2) * splitParam + x2;&#xD;&#xA;			float y01 = (y1 - y0) * splitParam + y0;&#xD;&#xA;			float y12 = (y2 - y1) * splitParam + y1;&#xD;&#xA;			float y23 = (y3 - y2) * splitParam + y2;&#xD;&#xA;&#xD;&#xA;			float x012 = (x12 - x01) * splitParam + x01;&#xD;&#xA;			float x123 = (x23 - x12) * splitParam + x12;&#xD;&#xA;			float y012 = (y12 - y01) * splitParam + y01;&#xD;&#xA;			float y123 = (y23 - y12) * splitParam + y12;&#xD;&#xA;&#xD;&#xA;			float x0123 = (x123 - x012) * splitParam + x012;&#xD;&#xA;			float y0123 = (y123 - y012) * splitParam + y012;&#xD;&#xA;&#xD;&#xA;			drawAdditionalTri = true;&#xD;&#xA;			plainTris.add(new Vertex(x0, y0));&#xD;&#xA;			plainTris.add(new Vertex(x0123, y0123));&#xD;&#xA;			plainTris.add(new Vertex(x3, y3));&#xD;&#xA;&#xD;&#xA;			if (errorLoop == 1) // flip second&#xD;&#xA;			{&#xD;&#xA;				compute(start.x, start.y, x01, y01, x012, y012, x0123, y0123, 0);&#xD;&#xA;				compute(x0123, y0123, x123, y123, x23, y23, end.x, end.y, 1);&#xD;&#xA;			} else if (errorLoop == 2) // flip first&#xD;&#xA;			{&#xD;&#xA;				compute(start.x, start.y, x01, y01, x012, y012, x0123, y0123, 1);&#xD;&#xA;				compute(x0123, y0123, x123, y123, x23, y23, end.x, end.y, 0);&#xD;&#xA;			}&#xD;&#xA;			 &#xD;&#xA;			return;&#xD;&#xA;		} else if (errorLoop == -1 &amp;&amp; recursiveType == -1) {&#xD;&#xA;			drawAdditionalTri = false;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (recursiveType == 1)&#xD;&#xA;			flip = !flip;&#xD;&#xA;&#xD;&#xA;		if (flip) {&#xD;&#xA;			klm.set(0, -klm.get(0));&#xD;&#xA;			klm.set(1, -klm.get(1));&#xD;&#xA;			klm.set(3, -klm.get(3));&#xD;&#xA;			klm.set(4, -klm.get(4));&#xD;&#xA;			klm.set(6, -klm.get(6));&#xD;&#xA;			klm.set(7, -klm.get(7));&#xD;&#xA;			klm.set(9, -klm.get(9));&#xD;&#xA;			klm.set(10, -klm.get(10));&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;		Triangulation(x0, y0, x1, y1, x2, y2, x3, y3, klm.toArray());&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public CurveType determineType(Float fd1, Float fd2, Float fd3) {&#xD;&#xA;		float d1 = 0, d2 = 0, d3 = 0;&#xD;&#xA;		Vector3 b0 = new Vector3(start.x, start.y, 1f);&#xD;&#xA;		Vector3 b1 = new Vector3(ctrl1.x, ctrl1.y, 1f);&#xD;&#xA;		Vector3 b2 = new Vector3(ctrl2.x, ctrl2.y, 1f);&#xD;&#xA;		Vector3 b3 = new Vector3(end.x, end.y, 1f);&#xD;&#xA;&#xD;&#xA;		float a1 = b0.dot(b3.cpy().crs(b2).cpy());&#xD;&#xA;		float a2 = b1.dot(b0.cpy().crs(b3).cpy());&#xD;&#xA;		float a3 = b2.dot(b1.cpy().crs(b0).cpy());&#xD;&#xA;&#xD;&#xA;		d1 = a1 - 2 * a2 + 3 * a3;&#xD;&#xA;		d2 = -a2 + 3 * a3;&#xD;&#xA;		d3 = 3 * a3;&#xD;&#xA;&#xD;&#xA;		Vector3 d = new Vector3(d1, d2, d3);&#xD;&#xA;		d.nor();&#xD;&#xA;		d1 = d.x;&#xD;&#xA;	    d2 = d.y;&#xD;&#xA;	    d3 = d.z;&#xD;&#xA;	    System.out.println(&quot;a1 &quot;+ d1);&#xD;&#xA;	    fd1.value = d1;&#xD;&#xA;	    fd2.value = d2;&#xD;&#xA;	    fd3.value = d3;&#xD;&#xA;		&#xD;&#xA;		float D = 3.0f * d2 * d2 - 4.0f * d1 * d3;&#xD;&#xA;		float disc = d1 * d1 * D;&#xD;&#xA;&#xD;&#xA;		if(disc == 0) {&#xD;&#xA;			if (d1 == 0 &amp;&amp; d2 == 0) {&#xD;&#xA;				if(d3 == 0)&#xD;&#xA;					return CurveType.LINE;&#xD;&#xA;			return CurveType.QUADRATIC;&#xD;&#xA;			}&#xD;&#xA;			if(d1 == 0)&#xD;&#xA;				return CurveType.CUSP;&#xD;&#xA;			if(D &lt; 0)&#xD;&#xA;				return CurveType.LOOP;&#xD;&#xA;		}&#xD;&#xA;		if (disc &gt; 0)&#xD;&#xA;			return CurveType.SERPENTINE;&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;		return CurveType.LOOP;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public void Triangulation(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float[] klm) {&#xD;&#xA;&#xD;&#xA;		Vertex[] vertices = new Vertex[4];&#xD;&#xA;		vertices[0] = new Vertex(x0, y0, klm[0], klm[1], klm[2]);&#xD;&#xA;		vertices[1] = new Vertex(x1, y1, klm[3], klm[4], klm[5]);&#xD;&#xA;		vertices[2] = new Vertex(x2, y2, klm[6], klm[7], klm[8]);&#xD;&#xA;		vertices[3] = new Vertex(x3, y3, klm[9], klm[10], klm[11]);&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;		for (int i = 0; i &lt; 4; ++i) {&#xD;&#xA;			for (int j = i + 1; j &lt; 4; ++j) {&#xD;&#xA;				if (approxEqual(vertices[i].xy, vertices[j].xy)) {&#xD;&#xA;					int indices[] = { 0, 0, 0 };&#xD;&#xA;					int index = 0;&#xD;&#xA;					for (int k = 0; k &lt; 4; ++k)&#xD;&#xA;						if (k != j)&#xD;&#xA;							indices[index++] = k;&#xD;&#xA;&#xD;&#xA;					tris.add(vertices[indices[0]]);&#xD;&#xA;					tris.add(vertices[indices[1]]);&#xD;&#xA;					tris.add(vertices[indices[2]]);&#xD;&#xA;&#xD;&#xA;					return;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		for (int i = 0; i &lt; 4; ++i) {&#xD;&#xA;			int indices[] = { 0, 0, 0 };&#xD;&#xA;			int index = 0;&#xD;&#xA;			for (int j = 0; j &lt; 4; ++j)&#xD;&#xA;				if (i != j)&#xD;&#xA;					indices[index++] = j;&#xD;&#xA;&#xD;&#xA;			if (pointInTriangle(vertices[i].xy, vertices[indices[0]].xy, vertices[indices[1]].xy,&#xD;&#xA;					vertices[indices[2]].xy)) {&#xD;&#xA;				tris.add(vertices[indices[0 % 3]].print());&#xD;&#xA;				tris.add(vertices[indices[(0 + 1) % 3]].print());&#xD;&#xA;				tris.add(vertices[i].print());&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[indices[1 % 3]].print());&#xD;&#xA;				tris.add(vertices[indices[(1 + 1) % 3]].print());&#xD;&#xA;				tris.add(vertices[i].print());&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[indices[2 % 3]].print());&#xD;&#xA;				tris.add(vertices[indices[(2 + 1) % 3]].print());&#xD;&#xA;				tris.add(vertices[i].print());&#xD;&#xA;				System.out.println(&quot;insude triangle&quot;);&#xD;&#xA;				return;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (intersect(vertices[0].xy, vertices[2].xy, vertices[1].xy, vertices[3].xy)) {&#xD;&#xA;			if ((vertices[2].xy.cpy().sub(vertices[0].xy)).len2() &lt; (vertices[3].xy.cpy().sub(vertices[1].xy)).len2()) {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;			} else {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		else if (intersect(vertices[0].xy, vertices[3].xy, vertices[1].xy, vertices[2].xy)) {&#xD;&#xA;			if ((vertices[3].xy.cpy().sub(vertices[0].xy)).len2() &lt; (vertices[2].xy.cpy().sub(vertices[1].xy)).len2()) {&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[1].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;				&#xD;&#xA;				System.out.println(&quot;true&quot;);&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;				tris.add(vertices[2].print());&#xD;&#xA;			} else {&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[1].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[2].print());&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;			}&#xD;&#xA;		} else {&#xD;&#xA;			if ((vertices[1].xy.cpy().sub(vertices[0].xy)).len2() &lt; (vertices[3].xy.cpy().sub(vertices[2].xy)).len2()) {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;			} else {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public boolean approxEqual(Vector2 v0, Vector2 v1) {&#xD;&#xA;		return (v0.cpy().sub(v1)).len2() &lt; M_EPS * M_EPS;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public boolean pointInTriangle(Vector2 point, Vector2 a, Vector2 b, Vector2 c) {&#xD;&#xA;		float x0 = c.x - a.x;&#xD;&#xA;		float y0 = c.y - a.y;&#xD;&#xA;		float x1 = b.x - a.x;&#xD;&#xA;		float y1 = b.y - a.y;&#xD;&#xA;		float x2 = point.x - a.x;&#xD;&#xA;		float y2 = point.y - a.y;&#xD;&#xA;&#xD;&#xA;		float dot00 = x0 * x0 + y0 * y0;&#xD;&#xA;		float dot01 = x0 * x1 + y0 * y1;&#xD;&#xA;		float dot02 = x0 * x2 + y0 * y2;&#xD;&#xA;		float dot11 = x1 * x1 + y1 * y1;&#xD;&#xA;		float dot12 = x1 * x2 + y1 * y2;&#xD;&#xA;		float denominator = dot00 * dot11 - dot01 * dot01;&#xD;&#xA;		if (denominator == 0)&#xD;&#xA;			return false;&#xD;&#xA;&#xD;&#xA;		float inverseDenominator = 1.0f / denominator;&#xD;&#xA;		float u = (dot11 * dot02 - dot01 * dot12) * inverseDenominator;&#xD;&#xA;		float v = (dot00 * dot12 - dot01 * dot02) * inverseDenominator;&#xD;&#xA;&#xD;&#xA;		return (u &gt; 0.0f) &amp;&amp; (v &gt; 0.0f) &amp;&amp; (u + v &lt; 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public int orientation(Vector2 p1, Vector2 p2, Vector2 p3) {&#xD;&#xA;		float crossProduct = (p2.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p2.x - p1.x);&#xD;&#xA;		return (crossProduct &lt; 0.0f) ? -1 : ((crossProduct &gt; 0.0f) ? 1 : 0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public boolean intersect(Vector2 p1, Vector2 q1, Vector2 p2, Vector2 q2) {&#xD;&#xA;		return (orientation(p1, q1, p2) != orientation(p1, q1, q2)&#xD;&#xA;				&amp;&amp; orientation(p2, q2, p1) != orientation(p2, q2, q1));&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;&#xD;&#xA;    attribute vec3 a_position;&#xD;&#xA;    attribute vec3 a_texCoord;&#xD;&#xA;    uniform mat4 u_projTrans;&#xD;&#xA;    varying vec3 tex;&#xD;&#xA;    void main() {&#xD;&#xA;	    tex = a_texCoord;&#xD;&#xA;	    gl_Position =  u_projTrans * vec4(a_position.xy, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    uniform vec4 u_color;&#xD;&#xA;    varying vec3 tex;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;	    vec3 uv = tex;&#xD;&#xA;	    float val = pow(uv.x, 3) - uv.y * uv.z;&#xD;&#xA;&#xD;&#xA;	    vec4 mycol = vec4(u_color.xyz, 1.0);&#xD;&#xA;&#xD;&#xA;	    if(val &lt; 0.0 )  mycol = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;        gl_FragColor = mycol;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;here are few screenshot of the problems:&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is an executable [jar file][5] of the application.&#xD;&#xA;&#xD;&#xA;Can anyone tell me how to fix this issue? i'm pulling my hair for few weeks now.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/azer89/GPU-Curve-Rendering&#xD;&#xA;  [2]: https://opensource.apple.com/source/WebCore/WebCore-1298.39/platform/graphics/gpu/&#xD;&#xA;  [3]: https://i.stack.imgur.com/CZLsp.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/iORNX.png&#xD;&#xA;  [5]: https://drive.google.com/open?id=1_kBPPsNSs6L_NURDYLm9Rxs2lAr5SWlE" ContentLicense="CC BY-SA 4.0" />
  <row Id="22016" PostHistoryTypeId="1" PostId="8269" RevisionGUID="2dceba43-58ab-48f2-a82d-7b749a02120e" CreationDate="2018-11-15T05:49:46.203" UserId="3024" Text="LoopBlinn Cubic Curve Rendering - Serpentine arteffect" ContentLicense="CC BY-SA 4.0" />
  <row Id="22017" PostHistoryTypeId="3" PostId="8269" RevisionGUID="2dceba43-58ab-48f2-a82d-7b749a02120e" CreationDate="2018-11-15T05:49:46.203" UserId="3024" Text="|opengl|shader|vector-graphics|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22018" PostHistoryTypeId="2" PostId="8270" RevisionGUID="adb1e1d5-1367-4e82-8e64-58f4ecc363c2" CreationDate="2018-11-15T09:04:10.937" UserId="209" Text="**Doh!.. coffee not cut in - eyes saw catmull rom but brain read Bezier! **&#xD;&#xA;&#xD;&#xA;It's a bit complicated - you can easily go from a sequence of *n* control points of a cubic (uniform) B-spline to form n-3 sets of cubic Beziers, i.e. a total of (n-3) sets of 4 control points, where the end control points of each set is shared with a neighbour, but you can't always go the other way.&#xD;&#xA;&#xD;&#xA;Certainly each individual Bezier can be converted to a single uniform B-spline but you can't guarantee you can share the control points between neighbours." ContentLicense="CC BY-SA 4.0" />
  <row Id="22019" PostHistoryTypeId="12" PostId="8270" RevisionGUID="f0516067-bc0d-409b-9699-da8ffafe944a" CreationDate="2018-11-15T09:06:18.563" UserId="209" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;}]}" />
  <row Id="22020" PostHistoryTypeId="50" PostId="5996" RevisionGUID="06bf627d-717e-450b-8800-631a8f78c9c9" CreationDate="2018-11-15T10:02:50.527" UserId="-1" />
  <row Id="22021" PostHistoryTypeId="5" PostId="8269" RevisionGUID="aed41e92-9a78-45ac-9912-9ed05e8dce1f" CreationDate="2018-11-15T21:39:13.600" UserId="3024" Comment="added 116 characters in body" Text="I am trying to implement the Loop-Blinn cubic curve in java using the following source codes [GPU-Curve-Rendering][1] and [WebCore][2]. Both of them are showing few arteffects and i cannot figure out why. Here are my source code:&#xD;&#xA;&#xD;&#xA;    public class CubicBezier {&#xD;&#xA;	public enum CurveType {&#xD;&#xA;		UNKNOWN, SERPENTINE, LOOP, CUSP, QUADRATIC, LINE&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	private FloatArray klm;&#xD;&#xA;	public boolean drawAdditionalTri;&#xD;&#xA;	public Array&lt;Vertex&gt; tris;&#xD;&#xA;	public Array&lt;Vertex&gt; plainTris;&#xD;&#xA;	public final float M_EPS = .00001f;&#xD;&#xA;&#xD;&#xA;	public Vector2 start;&#xD;&#xA;	public Vector2 ctrl1;&#xD;&#xA;	public Vector2 ctrl2;&#xD;&#xA;	public Vector2 end;&#xD;&#xA;	&#xD;&#xA;	boolean once = true;&#xD;&#xA;&#xD;&#xA;	public CubicBezier(Vector2 start, Vector2 ctrl1, Vector2 ctrl2, Vector2 end) {&#xD;&#xA;		this.start = start;&#xD;&#xA;		this.ctrl1 = ctrl1;&#xD;&#xA;		this.ctrl2 = ctrl2;&#xD;&#xA;		this.end = end;&#xD;&#xA;		drawAdditionalTri = false;&#xD;&#xA;		tris = new Array&lt;Vertex&gt;();&#xD;&#xA;		plainTris = new Array&lt;Vertex&gt;();&#xD;&#xA;&#xD;&#xA;		compute(start.x, start.y, ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y, -1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public void compute() {&#xD;&#xA;		tris.clear();&#xD;&#xA;		plainTris.clear();&#xD;&#xA;		drawAdditionalTri = false;&#xD;&#xA;		compute(start.x, start.y, ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, end.x, end.y, -1);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	boolean flipSerpent = false;&#xD;&#xA;	public void compute(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3,&#xD;&#xA;			int recursiveType) {&#xD;&#xA;		Float fd1 = new Float();&#xD;&#xA;		Float fd2 = new Float();&#xD;&#xA;		Float fd3 = new Float();&#xD;&#xA;		CurveType curve_type = determineType(fd1, fd2, fd3);&#xD;&#xA;		float d1 = fd1.value, d2 = fd2.value, d3 = fd3.value;&#xD;&#xA;		System.out.println(curve_type);&#xD;&#xA;		plainTris.clear();&#xD;&#xA;		&#xD;&#xA;		float OneThird = 1.0f / 3.0f;&#xD;&#xA;		float TwoThirds = 2.0f / 3.0f;&#xD;&#xA;&#xD;&#xA;		float t1;&#xD;&#xA;		float ls;&#xD;&#xA;		float lt;&#xD;&#xA;		float ms;&#xD;&#xA;		float mt;&#xD;&#xA;&#xD;&#xA;		float ltMinusLs;&#xD;&#xA;		float mtMinusMs;&#xD;&#xA;		float lsMinusLt;&#xD;&#xA;		float ql;&#xD;&#xA;		float qm;&#xD;&#xA;&#xD;&#xA;		// bool flip&#xD;&#xA;		boolean flip = false;&#xD;&#xA;&#xD;&#xA;		// artifact on loop&#xD;&#xA;		int errorLoop = -1;&#xD;&#xA;		float splitParam = 0;&#xD;&#xA;&#xD;&#xA;		klm = new FloatArray(12);&#xD;&#xA;		for (int i = 0; i &lt; 12; i++) {&#xD;&#xA;			klm.add(0);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		switch (curve_type) {&#xD;&#xA;		case UNKNOWN:&#xD;&#xA;			break;&#xD;&#xA;		case SERPENTINE:&#xD;&#xA;			t1 = (float) Math.sqrt(9.0f * d2 * d2 - 12 * d1 * d3);&#xD;&#xA;			ls = 3.0f * d2 - t1;&#xD;&#xA;			lt = 6.0f * d1;&#xD;&#xA;			ms = 3.0f * d2 + t1;&#xD;&#xA;			mt = lt;&#xD;&#xA;			ltMinusLs = lt - ls;&#xD;&#xA;			mtMinusMs = mt - ms;&#xD;&#xA;&#xD;&#xA;			klm.set(0, ls * ms);&#xD;&#xA;			klm.set(1, ls * ls * ls);&#xD;&#xA;			klm.set(2, ms * ms * ms);&#xD;&#xA;&#xD;&#xA;			klm.set(3, OneThird * (3.0f * ls * ms - ls * mt - lt * ms));&#xD;&#xA;			klm.set(4, ls * ls * (ls - lt));&#xD;&#xA;			klm.set(5, ms * ms * (ms - mt));&#xD;&#xA;&#xD;&#xA;			klm.set(6, OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)));&#xD;&#xA;			klm.set(7, ltMinusLs * ltMinusLs * ls);&#xD;&#xA;			klm.set(8, mtMinusMs * mtMinusMs * ms);&#xD;&#xA;&#xD;&#xA;			klm.set(9, ltMinusLs * mtMinusMs);&#xD;&#xA;			klm.set(10, -(ltMinusLs * ltMinusLs * ltMinusLs));&#xD;&#xA;			klm.set(11, -(mtMinusMs * mtMinusMs * mtMinusMs));&#xD;&#xA;			System.out.println(&quot;d1 &quot; + d1);&#xD;&#xA;			for (int i = 0; i &lt; 12; i++) {&#xD;&#xA;				System.out.println(i+&quot;: &quot;+klm.get(i));&#xD;&#xA;			}&#xD;&#xA;			if (d1 &lt; 0.0f) {&#xD;&#xA;				flip = true;&#xD;&#xA;				flipSerpent = true;&#xD;&#xA;			}&#xD;&#xA;			break;&#xD;&#xA;		case LOOP:&#xD;&#xA;			t1 = (float) Math.sqrt(4.0f * d1 * d3 - 3.0f * d2 * d2);&#xD;&#xA;			ls = d2 - t1;&#xD;&#xA;			lt = 2.0f * d1;&#xD;&#xA;			ms = d2 + t1;&#xD;&#xA;			mt = lt;&#xD;&#xA;&#xD;&#xA;			// Figure out whether there is a rendering artifact requiring&#xD;&#xA;			// the curve to be subdivided by the caller.&#xD;&#xA;			ql = ls / lt;&#xD;&#xA;			qm = ms / mt;&#xD;&#xA;			if (0.0f &lt; ql &amp;&amp; ql &lt; 1.0f) {&#xD;&#xA;				errorLoop = 1;&#xD;&#xA;				splitParam = ql;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			if (0.0f &lt; qm &amp;&amp; qm &lt; 1.0f) {&#xD;&#xA;				errorLoop = 2;&#xD;&#xA;				splitParam = qm;&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			ltMinusLs = lt - ls;&#xD;&#xA;			mtMinusMs = mt - ms;&#xD;&#xA;			&#xD;&#xA;			System.out.println(d1);&#xD;&#xA;&#xD;&#xA;			klm.set(0, ls * ms);&#xD;&#xA;			klm.set(1, ls * ls * ms);&#xD;&#xA;			klm.set(2, ls * ms * ms);&#xD;&#xA;			klm.set(3, OneThird * (-ls * mt - lt * ms + 3.0f * ls * ms));&#xD;&#xA;			klm.set(4, -OneThird * ls * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));&#xD;&#xA;			klm.set(5, -OneThird * ms * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));&#xD;&#xA;			klm.set(6, OneThird * (lt * (mt - 2.0f * ms) + ls * (3.0f * ms - 2.0f * mt)));&#xD;&#xA;			klm.set(7, OneThird * (lt - ls) * (ls * (2.0f * mt - 3.0f * ms) + lt * ms));&#xD;&#xA;			klm.set(8, OneThird * (mt - ms) * (ls * (mt - 3.0f * ms) + 2.0f * lt * ms));&#xD;&#xA;			klm.set(9, ltMinusLs * mtMinusMs);&#xD;&#xA;			klm.set(10, -(ltMinusLs * ltMinusLs) * mtMinusMs);&#xD;&#xA;			klm.set(11, -ltMinusLs * mtMinusMs * mtMinusMs);&#xD;&#xA;			&#xD;&#xA;			if (recursiveType == -1)&#xD;&#xA;				flip = ((d1 &gt; 0.0f &amp;&amp; klm.get(0) &lt; 0.0f) || (d1 &lt; 0.0f &amp;&amp; klm.get(0) &gt; 0.0f));&#xD;&#xA;			break;&#xD;&#xA;&#xD;&#xA;		case CUSP:&#xD;&#xA;			ls = d3;&#xD;&#xA;			lt = 3.0f * d2;&#xD;&#xA;			lsMinusLt = ls - lt;&#xD;&#xA;			klm.set(0, ls);&#xD;&#xA;			klm.set(1, ls * ls * ls);&#xD;&#xA;			klm.set(2, 1.0f);&#xD;&#xA;			klm.set(3, ls - OneThird * lt);&#xD;&#xA;			klm.set(4, ls * ls * lsMinusLt);&#xD;&#xA;			klm.set(5, 1.0f);&#xD;&#xA;			klm.set(6, ls - TwoThirds * lt);&#xD;&#xA;			klm.set(7, lsMinusLt * lsMinusLt * ls);&#xD;&#xA;			klm.set(8, 1.0f);&#xD;&#xA;			klm.set(9, lsMinusLt);&#xD;&#xA;			klm.set(10, lsMinusLt * lsMinusLt * lsMinusLt);&#xD;&#xA;			klm.set(11, 1.0f);&#xD;&#xA;			break;&#xD;&#xA;&#xD;&#xA;		case QUADRATIC:&#xD;&#xA;			klm.set(0, 0);&#xD;&#xA;			klm.set(1, 0);&#xD;&#xA;			klm.set(2, 0);&#xD;&#xA;			klm.set(3, OneThird);&#xD;&#xA;			klm.set(4, 0);&#xD;&#xA;			klm.set(5, OneThird);&#xD;&#xA;			klm.set(6, TwoThirds);&#xD;&#xA;			klm.set(7, OneThird);&#xD;&#xA;			klm.set(8, TwoThirds);&#xD;&#xA;			klm.set(9, 1);&#xD;&#xA;			klm.set(10, 1);&#xD;&#xA;			klm.set(11, 1);&#xD;&#xA;			if (d3 &lt; 0)&#xD;&#xA;				flip = true;&#xD;&#xA;			break;&#xD;&#xA;		case LINE:&#xD;&#xA;			break;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (errorLoop != -1 &amp;&amp; recursiveType == -1) {&#xD;&#xA;			System.out.println(&quot;error&quot;);&#xD;&#xA;			float x01 = (x1 - x0) * splitParam + x0;&#xD;&#xA;			float x12 = (x2 - x1) * splitParam + x1;&#xD;&#xA;			float x23 = (x3 - x2) * splitParam + x2;&#xD;&#xA;			float y01 = (y1 - y0) * splitParam + y0;&#xD;&#xA;			float y12 = (y2 - y1) * splitParam + y1;&#xD;&#xA;			float y23 = (y3 - y2) * splitParam + y2;&#xD;&#xA;&#xD;&#xA;			float x012 = (x12 - x01) * splitParam + x01;&#xD;&#xA;			float x123 = (x23 - x12) * splitParam + x12;&#xD;&#xA;			float y012 = (y12 - y01) * splitParam + y01;&#xD;&#xA;			float y123 = (y23 - y12) * splitParam + y12;&#xD;&#xA;&#xD;&#xA;			float x0123 = (x123 - x012) * splitParam + x012;&#xD;&#xA;			float y0123 = (y123 - y012) * splitParam + y012;&#xD;&#xA;&#xD;&#xA;			drawAdditionalTri = true;&#xD;&#xA;			plainTris.add(new Vertex(x0, y0));&#xD;&#xA;			plainTris.add(new Vertex(x0123, y0123));&#xD;&#xA;			plainTris.add(new Vertex(x3, y3));&#xD;&#xA;&#xD;&#xA;			if (errorLoop == 1) // flip second&#xD;&#xA;			{&#xD;&#xA;				compute(start.x, start.y, x01, y01, x012, y012, x0123, y0123, 0);&#xD;&#xA;				compute(x0123, y0123, x123, y123, x23, y23, end.x, end.y, 1);&#xD;&#xA;			} else if (errorLoop == 2) // flip first&#xD;&#xA;			{&#xD;&#xA;				compute(start.x, start.y, x01, y01, x012, y012, x0123, y0123, 1);&#xD;&#xA;				compute(x0123, y0123, x123, y123, x23, y23, end.x, end.y, 0);&#xD;&#xA;			}&#xD;&#xA;			 &#xD;&#xA;			return;&#xD;&#xA;		} else if (errorLoop == -1 &amp;&amp; recursiveType == -1) {&#xD;&#xA;			drawAdditionalTri = false;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (recursiveType == 1)&#xD;&#xA;			flip = !flip;&#xD;&#xA;&#xD;&#xA;		if (flip) {&#xD;&#xA;			klm.set(0, -klm.get(0));&#xD;&#xA;			klm.set(1, -klm.get(1));&#xD;&#xA;			klm.set(3, -klm.get(3));&#xD;&#xA;			klm.set(4, -klm.get(4));&#xD;&#xA;			klm.set(6, -klm.get(6));&#xD;&#xA;			klm.set(7, -klm.get(7));&#xD;&#xA;			klm.set(9, -klm.get(9));&#xD;&#xA;			klm.set(10, -klm.get(10));&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;		Triangulation(x0, y0, x1, y1, x2, y2, x3, y3, klm.toArray());&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public CurveType determineType(Float fd1, Float fd2, Float fd3) {&#xD;&#xA;		float d1 = 0, d2 = 0, d3 = 0;&#xD;&#xA;		Vector3 b0 = new Vector3(start.x, start.y, 1f);&#xD;&#xA;		Vector3 b1 = new Vector3(ctrl1.x, ctrl1.y, 1f);&#xD;&#xA;		Vector3 b2 = new Vector3(ctrl2.x, ctrl2.y, 1f);&#xD;&#xA;		Vector3 b3 = new Vector3(end.x, end.y, 1f);&#xD;&#xA;&#xD;&#xA;		float a1 = b0.dot(b3.cpy().crs(b2).cpy());&#xD;&#xA;		float a2 = b1.dot(b0.cpy().crs(b3).cpy());&#xD;&#xA;		float a3 = b2.dot(b1.cpy().crs(b0).cpy());&#xD;&#xA;&#xD;&#xA;		d1 = a1 - 2 * a2 + 3 * a3;&#xD;&#xA;		d2 = -a2 + 3 * a3;&#xD;&#xA;		d3 = 3 * a3;&#xD;&#xA;&#xD;&#xA;		Vector3 d = new Vector3(d1, d2, d3);&#xD;&#xA;		d.nor();&#xD;&#xA;		d1 = d.x;&#xD;&#xA;	    d2 = d.y;&#xD;&#xA;	    d3 = d.z;&#xD;&#xA;	    System.out.println(&quot;a1 &quot;+ d1);&#xD;&#xA;	    fd1.value = d1;&#xD;&#xA;	    fd2.value = d2;&#xD;&#xA;	    fd3.value = d3;&#xD;&#xA;		&#xD;&#xA;		float D = 3.0f * d2 * d2 - 4.0f * d1 * d3;&#xD;&#xA;		float disc = d1 * d1 * D;&#xD;&#xA;&#xD;&#xA;		if(disc == 0) {&#xD;&#xA;			if (d1 == 0 &amp;&amp; d2 == 0) {&#xD;&#xA;				if(d3 == 0)&#xD;&#xA;					return CurveType.LINE;&#xD;&#xA;			return CurveType.QUADRATIC;&#xD;&#xA;			}&#xD;&#xA;			if(d1 == 0)&#xD;&#xA;				return CurveType.CUSP;&#xD;&#xA;			if(D &lt; 0)&#xD;&#xA;				return CurveType.LOOP;&#xD;&#xA;		}&#xD;&#xA;		if (disc &gt; 0)&#xD;&#xA;			return CurveType.SERPENTINE;&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;		return CurveType.LOOP;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public void Triangulation(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float[] klm) {&#xD;&#xA;&#xD;&#xA;		Vertex[] vertices = new Vertex[4];&#xD;&#xA;		vertices[0] = new Vertex(x0, y0, klm[0], klm[1], klm[2]);&#xD;&#xA;		vertices[1] = new Vertex(x1, y1, klm[3], klm[4], klm[5]);&#xD;&#xA;		vertices[2] = new Vertex(x2, y2, klm[6], klm[7], klm[8]);&#xD;&#xA;		vertices[3] = new Vertex(x3, y3, klm[9], klm[10], klm[11]);&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;		for (int i = 0; i &lt; 4; ++i) {&#xD;&#xA;			for (int j = i + 1; j &lt; 4; ++j) {&#xD;&#xA;				if (approxEqual(vertices[i].xy, vertices[j].xy)) {&#xD;&#xA;					int indices[] = { 0, 0, 0 };&#xD;&#xA;					int index = 0;&#xD;&#xA;					for (int k = 0; k &lt; 4; ++k)&#xD;&#xA;						if (k != j)&#xD;&#xA;							indices[index++] = k;&#xD;&#xA;&#xD;&#xA;					tris.add(vertices[indices[0]]);&#xD;&#xA;					tris.add(vertices[indices[1]]);&#xD;&#xA;					tris.add(vertices[indices[2]]);&#xD;&#xA;&#xD;&#xA;					return;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		for (int i = 0; i &lt; 4; ++i) {&#xD;&#xA;			int indices[] = { 0, 0, 0 };&#xD;&#xA;			int index = 0;&#xD;&#xA;			for (int j = 0; j &lt; 4; ++j)&#xD;&#xA;				if (i != j)&#xD;&#xA;					indices[index++] = j;&#xD;&#xA;&#xD;&#xA;			if (pointInTriangle(vertices[i].xy, vertices[indices[0]].xy, vertices[indices[1]].xy,&#xD;&#xA;					vertices[indices[2]].xy)) {&#xD;&#xA;				tris.add(vertices[indices[0 % 3]].print());&#xD;&#xA;				tris.add(vertices[indices[(0 + 1) % 3]].print());&#xD;&#xA;				tris.add(vertices[i].print());&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[indices[1 % 3]].print());&#xD;&#xA;				tris.add(vertices[indices[(1 + 1) % 3]].print());&#xD;&#xA;				tris.add(vertices[i].print());&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[indices[2 % 3]].print());&#xD;&#xA;				tris.add(vertices[indices[(2 + 1) % 3]].print());&#xD;&#xA;				tris.add(vertices[i].print());&#xD;&#xA;				System.out.println(&quot;insude triangle&quot;);&#xD;&#xA;				return;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		if (intersect(vertices[0].xy, vertices[2].xy, vertices[1].xy, vertices[3].xy)) {&#xD;&#xA;			if ((vertices[2].xy.cpy().sub(vertices[0].xy)).len2() &lt; (vertices[3].xy.cpy().sub(vertices[1].xy)).len2()) {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;			} else {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		else if (intersect(vertices[0].xy, vertices[3].xy, vertices[1].xy, vertices[2].xy)) {&#xD;&#xA;			if ((vertices[3].xy.cpy().sub(vertices[0].xy)).len2() &lt; (vertices[2].xy.cpy().sub(vertices[1].xy)).len2()) {&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[1].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;				&#xD;&#xA;				System.out.println(&quot;true&quot;);&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;				tris.add(vertices[2].print());&#xD;&#xA;			} else {&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[1].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[2].print());&#xD;&#xA;				tris.add(vertices[0].print());&#xD;&#xA;				tris.add(vertices[3].print());&#xD;&#xA;			}&#xD;&#xA;		} else {&#xD;&#xA;			if ((vertices[1].xy.cpy().sub(vertices[0].xy)).len2() &lt; (vertices[3].xy.cpy().sub(vertices[2].xy)).len2()) {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;			} else {&#xD;&#xA;				tris.add(vertices[0]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;				&#xD;&#xA;				tris.add(vertices[3]);&#xD;&#xA;				tris.add(vertices[2]);&#xD;&#xA;				tris.add(vertices[1]);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public boolean approxEqual(Vector2 v0, Vector2 v1) {&#xD;&#xA;		return (v0.cpy().sub(v1)).len2() &lt; M_EPS * M_EPS;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public boolean pointInTriangle(Vector2 point, Vector2 a, Vector2 b, Vector2 c) {&#xD;&#xA;		float x0 = c.x - a.x;&#xD;&#xA;		float y0 = c.y - a.y;&#xD;&#xA;		float x1 = b.x - a.x;&#xD;&#xA;		float y1 = b.y - a.y;&#xD;&#xA;		float x2 = point.x - a.x;&#xD;&#xA;		float y2 = point.y - a.y;&#xD;&#xA;&#xD;&#xA;		float dot00 = x0 * x0 + y0 * y0;&#xD;&#xA;		float dot01 = x0 * x1 + y0 * y1;&#xD;&#xA;		float dot02 = x0 * x2 + y0 * y2;&#xD;&#xA;		float dot11 = x1 * x1 + y1 * y1;&#xD;&#xA;		float dot12 = x1 * x2 + y1 * y2;&#xD;&#xA;		float denominator = dot00 * dot11 - dot01 * dot01;&#xD;&#xA;		if (denominator == 0)&#xD;&#xA;			return false;&#xD;&#xA;&#xD;&#xA;		float inverseDenominator = 1.0f / denominator;&#xD;&#xA;		float u = (dot11 * dot02 - dot01 * dot12) * inverseDenominator;&#xD;&#xA;		float v = (dot00 * dot12 - dot01 * dot02) * inverseDenominator;&#xD;&#xA;&#xD;&#xA;		return (u &gt; 0.0f) &amp;&amp; (v &gt; 0.0f) &amp;&amp; (u + v &lt; 1.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public int orientation(Vector2 p1, Vector2 p2, Vector2 p3) {&#xD;&#xA;		float crossProduct = (p2.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p2.x - p1.x);&#xD;&#xA;		return (crossProduct &lt; 0.0f) ? -1 : ((crossProduct &gt; 0.0f) ? 1 : 0);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	public boolean intersect(Vector2 p1, Vector2 q1, Vector2 p2, Vector2 q2) {&#xD;&#xA;		return (orientation(p1, q1, p2) != orientation(p1, q1, q2)&#xD;&#xA;				&amp;&amp; orientation(p2, q2, p1) != orientation(p2, q2, q1));&#xD;&#xA;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vertex shader:&#xD;&#xA;&#xD;&#xA;    attribute vec3 a_position;&#xD;&#xA;    attribute vec3 a_texCoord;&#xD;&#xA;    uniform mat4 u_projTrans;&#xD;&#xA;    varying vec3 tex;&#xD;&#xA;    void main() {&#xD;&#xA;	    tex = a_texCoord;&#xD;&#xA;	    gl_Position =  u_projTrans * vec4(a_position.xy, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;fragment shader:&#xD;&#xA;&#xD;&#xA;    uniform vec4 u_color;&#xD;&#xA;    varying vec3 tex;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;	    vec3 uv = tex;&#xD;&#xA;	    float val = pow(uv.x, 3) - uv.y * uv.z;&#xD;&#xA;&#xD;&#xA;	    vec4 mycol = vec4(u_color.xyz, 1.0);&#xD;&#xA;&#xD;&#xA;	    if(val &lt; 0.0 )  mycol = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;        gl_FragColor = mycol;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;here are few screenshot of the problems:&#xD;&#xA;[![enter image description here][3]][3][![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;They suppose to be like these&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;This is an executable [jar file][6] of the application.&#xD;&#xA;&#xD;&#xA;Can anyone tell me how to fix this issue? i'm pulling my hair for few weeks now.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/azer89/GPU-Curve-Rendering&#xD;&#xA;  [2]: https://opensource.apple.com/source/WebCore/WebCore-1298.39/platform/graphics/gpu/&#xD;&#xA;  [3]: https://i.stack.imgur.com/CZLsp.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/iORNX.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/4Ny1x.png&#xD;&#xA;  [6]: https://drive.google.com/open?id=1_kBPPsNSs6L_NURDYLm9Rxs2lAr5SWlE" ContentLicense="CC BY-SA 4.0" />
  <row Id="22022" PostHistoryTypeId="50" PostId="7529" RevisionGUID="d487a28c-96e9-4c89-802f-00bf07fa667c" CreationDate="2018-11-15T22:03:20.727" UserId="-1" />
  <row Id="22024" PostHistoryTypeId="2" PostId="8272" RevisionGUID="d5a13d61-a1a9-4737-89c6-9da15d747f74" CreationDate="2018-11-16T07:16:17.220" UserId="87" Text="Make a tiling texture of a cross. When this texture repeats in all dimensions, it will make a grid-like pattern. Next render a ground plane as above and unwrap the texture on it with the appropriate tiling rate. Change the intensity of the color based on the dot product of the ground plane normal and the view direction to get the lighting/fade effect (you can experiment with different falloff functions and ranges)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22025" PostHistoryTypeId="33" PostId="8260" RevisionGUID="11acb115-75de-4312-92e1-245b7d58f326" CreationDate="2018-11-16T08:52:04.607" UserId="9684" Comment="52" />
  <row Id="22026" PostHistoryTypeId="2" PostId="8273" RevisionGUID="a143393b-a19e-49b0-b551-156b50cdb121" CreationDate="2018-11-16T10:46:46.913" UserId="8957" Text="I am working on a texture mapping problem. I use vtk C++ library for my work. I have a very dense mesh with lots of vertices. I want to apply image texture to this mesh. Should I set texture coordinates for every vertex ? Or can I skip few vertices and setup the texture coordinates and still expect the texture to be set properly? Please see the image attached. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If A,B,C,D, E, F are the vertices of 4 faces in a mesh, can I set the texture coordinates only to A,C,F,D ? Will the texture drape the faces stretching equally?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ux0Z6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22027" PostHistoryTypeId="1" PostId="8273" RevisionGUID="a143393b-a19e-49b0-b551-156b50cdb121" CreationDate="2018-11-16T10:46:46.913" UserId="8957" Text="In texture mapping, should we apply texture coordinate to every vertex or can I skip vertices in between?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22028" PostHistoryTypeId="3" PostId="8273" RevisionGUID="a143393b-a19e-49b0-b551-156b50cdb121" CreationDate="2018-11-16T10:46:46.913" UserId="8957" Text="|texture|uv-mapping|vtk|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22029" PostHistoryTypeId="4" PostId="8273" RevisionGUID="f93461b4-b321-4652-970b-977b5f5dc6a9" CreationDate="2018-11-16T12:07:36.843" UserId="8957" Comment="edited title" Text="In texture mapping, should we set texture coordinate to every vertex or can I skip vertices in between?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22030" PostHistoryTypeId="2" PostId="8274" RevisionGUID="1b1f9f23-e354-4e99-ac03-df36ddb94cb0" CreationDate="2018-11-16T14:52:17.820" UserId="7724" Text="Typically, texture coordinates are interpolated from the vertices of a triangle during rendering. This can be seen in two ways. evaluating your texture at vertices and the interpolating the result or interpolating the texture coordinates and evaluating your texture at the fragment level. &#xD;&#xA;&#xD;&#xA;If you do not supply vertices with corresponding texture coordinates then there is no guarantee that the interpolated texture coordinates or colours for the fragments of the rendered triangle will behave nicely. By skipping a few vertices, the vertices would need some default texture coordinate such as $(0,0)$, which would show up as a weird artefact in your rendering. The vertices B and E in your example are required to have texture coordinates in order to have a continuous set of interpolated texture coordinates or colour values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22031" PostHistoryTypeId="2" PostId="8275" RevisionGUID="456c6c34-1b27-43d2-9acc-f44d7a931d73" CreationDate="2018-11-16T17:08:20.320" UserId="4958" Text="You can do it by only rendering a flat plane and then making a grid in fragment shader. This is actually a nice exercise. &#xD;&#xA;&#xD;&#xA;To get these two color values, you can use color selector, which is available in any graphic software for example MS Paint&#xD;&#xA;&#xD;&#xA;Some code hints:&#xD;&#xA;&#xD;&#xA;    vec2 coord = worldPos.xz / stepSize; //square size in world space&#xD;&#xA;    vec2 frac = fract(coord); //fractional parts of squares&#xD;&#xA;    //interpolation, grad is smoothness of line gradients&#xD;&#xA;    vec2 mult = smoothstep(0.0, grad, frac) - smoothstep(1.0-grad, 1.0, frac);&#xD;&#xA;    vec3 col = mix(col1, col2, mult.x * mult.y);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22032" PostHistoryTypeId="2" PostId="8276" RevisionGUID="4954c12b-4453-4fa5-8dae-023e5458b7db" CreationDate="2018-11-16T22:43:30.033" UserId="9505" Text="Not sure what's wrong with your implementation, but it looks like the blender's distortion model is not proportional to the image aspect ratio, producing equal curvature in both axis..&#xD;&#xA;&#xD;&#xA;Can you compare the input coordinates between the two implementations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22047" PostHistoryTypeId="2" PostId="8280" RevisionGUID="7112a668-d375-45ed-9ef3-4c17424bba13" CreationDate="2018-11-17T14:14:05.963" UserId="3024" Text="Found the answer [here][1]. A solution i posted a year ago. I forgot :P &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/azer89/GPU-Curve-Rendering/issues/2" ContentLicense="CC BY-SA 4.0" />
  <row Id="22049" PostHistoryTypeId="2" PostId="8281" RevisionGUID="d55cd801-6937-4a91-a1f7-8e0c0ff96185" CreationDate="2018-11-17T16:23:10.853" UserId="4958" Text="I achieved similar result to theirs. First, the target texture for mip generation is base texture size + two margins, each equals 0.25 of base size.&#xD;&#xA;&#xD;&#xA;Then during generation of base mip level, there are two cases:&#xD;&#xA;&#xD;&#xA; - inside the square, then just sample original texture&#xD;&#xA; - beyond the central square, then blur the original texture with varying sigma, which depends on distance of current fragCoord from central square borders.&#xD;&#xA;&#xD;&#xA;How to compute distance: https://gamedev.stackexchange.com/a/44496/91268&#xD;&#xA;&#xD;&#xA;Gaussian one pass blur I used: https://www.shadertoy.com/view/XdfGDH&#xD;&#xA;&#xD;&#xA;Here are code fragments:&#xD;&#xA;&#xD;&#xA;    vec2 coord = gl_FragCoord.xy;&#xD;&#xA;    vec2 minCorner = margin;&#xD;&#xA;    vec2 maxCorner = filteredMipRes - margin;&#xD;&#xA;    if(insideBox(coord, minCorner, maxCorner) &gt; 0.5)&#xD;&#xA;    {&#xD;&#xA;    	fragColor = textureLod(sourceTexture, tc, 0.0).rgb;&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	vec2 center = filteredMipRes / 2.0;&#xD;&#xA;    	vec2 d = max(abs(coord - center) - baseTextureRes / 2.0, vec2(0.0));&#xD;&#xA;    	float dist = sqrt(d.x * d.x + d.y * d.y);&#xD;&#xA;    	sigma = max(dist*2.0, 0.5);&#xD;&#xA;    	fragColor = blur(sigma);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Rest of mipmaps are just equally gaussian blurred, each based on one level higher mip." ContentLicense="CC BY-SA 4.0" />
  <row Id="22050" PostHistoryTypeId="5" PostId="8281" RevisionGUID="0285b0b9-060c-44a7-8a2f-3cf4fad86d19" CreationDate="2018-11-17T16:32:42.160" UserId="4958" Comment="added 63 characters in body" Text="I achieved similar result to theirs. First, the target texture for mip generation is base texture size + two margins, each equals 0.25 of base size.&#xD;&#xA;&#xD;&#xA;Then during generation of base mip level, there are two cases:&#xD;&#xA;&#xD;&#xA; - inside the square, then just sample original texture,&#xD;&#xA; - beyond the central square, then blur the original texture with varying sigma, which depends on distance of current fragCoord from central square borders. While blurring texcoord is clamped to central square borders.&#xD;&#xA;&#xD;&#xA;How to compute distance: https://gamedev.stackexchange.com/a/44496/91268&#xD;&#xA;&#xD;&#xA;Gaussian one pass blur I used: https://www.shadertoy.com/view/XdfGDH&#xD;&#xA;&#xD;&#xA;Here are code fragments:&#xD;&#xA;&#xD;&#xA;    vec2 coord = gl_FragCoord.xy;&#xD;&#xA;    vec2 minCorner = margin;&#xD;&#xA;    vec2 maxCorner = filteredMipRes - margin;&#xD;&#xA;    if(insideBox(coord, minCorner, maxCorner) &gt; 0.5)&#xD;&#xA;    {&#xD;&#xA;    	fragColor = textureLod(sourceTexture, tc, 0.0).rgb;&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	vec2 center = filteredMipRes / 2.0;&#xD;&#xA;    	vec2 d = max(abs(coord - center) - baseTextureRes / 2.0, vec2(0.0));&#xD;&#xA;    	float dist = sqrt(d.x * d.x + d.y * d.y);&#xD;&#xA;    	sigma = max(dist*2.0, 0.5);&#xD;&#xA;    	fragColor = blur(sigma);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Rest of mipmaps are just equally gaussian blurred, each based on one level higher mip." ContentLicense="CC BY-SA 4.0" />
  <row Id="22051" PostHistoryTypeId="5" PostId="8281" RevisionGUID="c498e481-ca11-489a-9be5-66c57d3f6f22" CreationDate="2018-11-17T16:38:56.010" UserId="4958" Comment="added 1 character in body" Text="I achieved similar result to theirs. First, the target texture for mip generation is base texture size + two margins, each equals 0.125 of base size.&#xD;&#xA;&#xD;&#xA;Then during generation of base mip level, there are two cases:&#xD;&#xA;&#xD;&#xA; - inside the square, then just sample original texture,&#xD;&#xA; - beyond the central square, then blur the original texture with varying sigma, which depends on distance of current fragCoord from central square borders. While blurring texcoord is clamped to central square borders.&#xD;&#xA;&#xD;&#xA;How to compute distance: https://gamedev.stackexchange.com/a/44496/91268&#xD;&#xA;&#xD;&#xA;Gaussian one pass blur I used: https://www.shadertoy.com/view/XdfGDH&#xD;&#xA;&#xD;&#xA;Here are code fragments:&#xD;&#xA;&#xD;&#xA;    vec2 coord = gl_FragCoord.xy;&#xD;&#xA;    vec2 minCorner = margin;&#xD;&#xA;    vec2 maxCorner = filteredMipRes - margin;&#xD;&#xA;    if(insideBox(coord, minCorner, maxCorner) &gt; 0.5)&#xD;&#xA;    {&#xD;&#xA;    	fragColor = textureLod(sourceTexture, tc, 0.0).rgb;&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;    	vec2 center = filteredMipRes / 2.0;&#xD;&#xA;    	vec2 d = max(abs(coord - center) - baseTextureRes / 2.0, vec2(0.0));&#xD;&#xA;    	float dist = sqrt(d.x * d.x + d.y * d.y);&#xD;&#xA;    	sigma = max(dist*2.0, 0.5);&#xD;&#xA;    	fragColor = blur(sigma);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Rest of mipmaps are just equally gaussian blurred, each based on one level higher mip." ContentLicense="CC BY-SA 4.0" />
  <row Id="22052" PostHistoryTypeId="5" PostId="8270" RevisionGUID="21677c2f-8d84-44db-9bf2-5c3b928984af" CreationDate="2018-11-17T18:07:02.057" UserId="209" Comment="added 2254 characters in body" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; 2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;2 &amp; 5 &amp; -4 &amp; 7\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;Beginning by trying to go from BSpline to CR, I was thinking that if we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;If we invert that matrix, one should then be able to map the other way: This gives a matrix of repeated rows which, if we ignore the smaller terms, suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="22053" PostHistoryTypeId="13" PostId="8270" RevisionGUID="22ee1168-754e-4ff6-bcc5-200f17941f81" CreationDate="2018-11-17T18:07:10.950" UserId="209" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;}]}" />
  <row Id="22054" PostHistoryTypeId="5" PostId="8270" RevisionGUID="a5101c05-9f12-4d74-adec-9065418ac14c" CreationDate="2018-11-17T18:17:53.243" UserId="209" Comment="note on normalising" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; 2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;2 &amp; 5 &amp; -4 &amp; 7\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;Beginning by trying to go from BSpline to CR, I was thinking that if we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;If we invert that matrix, one should then be able to map the other way: This gives a matrix of repeated rows which, if we ignore the smaller terms, suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;.&#xD;&#xA;&#xD;&#xA;*Update* Those weights don't *quite* sum to 1.0 - you'll need to normalise them slightly.&#xD;&#xA;&#xD;&#xA;Obviously, this has assumed the curve is a loop. It's probably possible to adjust the weights for the end points but I'll leave that as an exercise for the reader." ContentLicense="CC BY-SA 4.0" />
  <row Id="22055" PostHistoryTypeId="5" PostId="8270" RevisionGUID="f21f23e6-51ba-4a10-8f84-50862a91b339" CreationDate="2018-11-17T18:53:43.410" UserId="209" Comment="added 8 characters in body" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the correct matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; 2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;2 &amp; 5 &amp; -4 &amp; 7\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;Beginning by trying to go from BSpline to CR, I was thinking that if we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;If we invert that matrix, one should then be able to map the other way: This gives a matrix of repeated rows which, if we ignore the smaller terms, suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;.&#xD;&#xA;&#xD;&#xA;*Update* Those weights don't *quite* sum to 1.0 - you'll need to normalise them slightly.&#xD;&#xA;&#xD;&#xA;Obviously, this has assumed the curve is a loop. It's probably possible to adjust the weights for the end points but I'll leave that as an exercise for the reader." ContentLicense="CC BY-SA 4.0" />
  <row Id="22065" PostHistoryTypeId="2" PostId="8284" RevisionGUID="6644d115-ab07-4496-b134-52daaa96080c" CreationDate="2018-11-18T08:50:41.157" UserId="1582" Text="Also consider these alternatives for reducing bandwidth in comparison to R16G16B16A16.&#xD;&#xA;&#xD;&#xA;DXGI_FORMAT_BC6H_UF16 is block compressed fp16 (half) RGB.&#xD;&#xA;&gt; https://docs.microsoft.com/en-us/windows/desktop/direct3d11/bc6h-format&#xD;&#xA;&#xD;&#xA;DXGI_FORMAT_R11G11B10 unsigned small float&#xD;&#xA;&gt; https://bartwronski.com/2017/04/02/small-float-formats-r11g11b10f-precision/&#xD;&#xA;&#xD;&#xA;Common image file formats for HDR are exrs or dds. They're pretty trivially encoded as 32-bit or 16-bit per channel floats." ContentLicense="CC BY-SA 4.0" />
  <row Id="22066" PostHistoryTypeId="2" PostId="8285" RevisionGUID="abfe6497-9ce9-48d3-a6c4-7cc786f3d75e" CreationDate="2018-11-18T09:14:21.967" UserId="1582" Text="I'll point out that even if you did implement it correctly, at 1 sample per pixel with low roughness materials you'll still see heavy specular aliasing. It's not uncommon to see the firefly pattern on edges on low roughness materials.&#xD;&#xA;&#xD;&#xA;For reference see the Infiltrator demo without TAA&#xD;&#xA;&gt; http://advances.realtimerendering.com/s2014/epic/TemporalAA_Compare.mov &#xD;&#xA;&#xD;&#xA;&gt; http://advances.realtimerendering.com/s2014/index.html#_HIGH-QUALITY_TEMPORAL_SUPERSAMPLING" ContentLicense="CC BY-SA 4.0" />
  <row Id="22068" PostHistoryTypeId="2" PostId="8286" RevisionGUID="4b8a8f1a-0c5d-4e46-afa0-6040c2e6c468" CreationDate="2018-11-18T09:55:48.450" UserId="9722" Text="I'm trying to render thick cubic Bezier curve using whole OpenGL 4.5 pipeline.  &#xD;&#xA;**a)** I render patch with 4 control points.  &#xD;&#xA;**b)** Vertex shader is simply pass-through to tessellation control shader.  &#xD;&#xA;**c)** TCS - sendng 4 vertices to tessalator with *gl_TessLevelOuter[1] = 10*  &#xD;&#xA;**d)** TES - calculating position for every of those 10 tessellated isoline points using Bezier curve equation  &#xD;&#xA;**e)** Geometry shader - making quads out of every line it receives extruding vertices along line's normal vector.&#xD;&#xA;&#xD;&#xA;So far so good but this will obviously lead to cracks between adjacent quads. To solve this problem I would need to know position of adjacent lines in TES or GS to correct edges. Is this information available? &#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="22069" PostHistoryTypeId="1" PostId="8286" RevisionGUID="4b8a8f1a-0c5d-4e46-afa0-6040c2e6c468" CreationDate="2018-11-18T09:55:48.450" UserId="9722" Text="Is it possible to access adjacent vertex data in tessellation evaluation shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22070" PostHistoryTypeId="3" PostId="8286" RevisionGUID="4b8a8f1a-0c5d-4e46-afa0-6040c2e6c468" CreationDate="2018-11-18T09:55:48.450" UserId="9722" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22071" PostHistoryTypeId="2" PostId="8287" RevisionGUID="c5946174-001e-432c-96a3-7be9a19127d4" CreationDate="2018-11-18T12:20:54.077" UserId="9723" Text="I am working on a simple graph viewer with OpenGL. My problem with is directed edges. I tried to draw arrow endings with GL_TRIANGLES but somehow my calculations are off. I've used direction cosine vector to calculate triangle position.&#xD;&#xA;&#xD;&#xA;Actually triangle positions are almost correct but angles are a bit off for some triangles. Here is a screenshot:&#xD;&#xA;&#xD;&#xA;[![screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NjBhk.pngm&#xD;&#xA;&#xD;&#xA;and here is my code to draw arrow endings:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c# --&gt;&#xD;&#xA;&#xD;&#xA;    foreach (Edge e in m_graph.EdgeList.Values)&#xD;&#xA;	{&#xD;&#xA;		if (e.Source == e.Target)&#xD;&#xA;		{&#xD;&#xA;			//TO DO: loops&#xD;&#xA;		}&#xD;&#xA;		if (e.Directed)&#xD;&#xA;		{&#xD;&#xA;			GL.Begin(PrimitiveType.Triangles);&#xD;&#xA;	&#xD;&#xA;			Vector2 p1, p2;&#xD;&#xA;			e.Source.GetAttribute(&quot;pos&quot;, out p1);&#xD;&#xA;			e.Target.GetAttribute(&quot;pos&quot;, out p2);&#xD;&#xA;	&#xD;&#xA;			Vector2 direction = p2 - p1;&#xD;&#xA;			direction.Normalize();&#xD;&#xA;	&#xD;&#xA;			Vector2 perpendicular = (Vector2)direction.Clone();&#xD;&#xA;			perpendicular.Perpendicu();&#xD;&#xA;	&#xD;&#xA;			Vector2 c_pt = p2 - direction * VERTICLE_SIZE * 3;&#xD;&#xA;			Vector2 pt1 = c_pt - perpendicular * VERTICLE_SIZE;&#xD;&#xA;			Vector2 pt2 = c_pt + perpendicular * VERTICLE_SIZE;&#xD;&#xA;	&#xD;&#xA;			GL.Vertex2(p2.X, p2.Y);&#xD;&#xA;			GL.Vertex2(pt1.X, pt1.Y);&#xD;&#xA;			GL.Vertex2(pt2.X, pt2.Y);&#xD;&#xA;	&#xD;&#xA;			GL.End();&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;also Normalize and Perpendicu methods from Vector2 class:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c# --&gt;&#xD;&#xA;&#xD;&#xA;        /// &lt;summary&gt;&#xD;&#xA;        /// Normalizes the vector&#xD;&#xA;        /// &lt;/summary&gt;&#xD;&#xA;        public void Normalize()&#xD;&#xA;        {&#xD;&#xA;            m_x /= this.Length;&#xD;&#xA;            m_y /= this.Length;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        /// &lt;summary&gt;&#xD;&#xA;        /// Perpedicus the vector&#xD;&#xA;        /// &lt;/summary&gt;&#xD;&#xA;        public void Perpendicu()&#xD;&#xA;        {&#xD;&#xA;            float _x = m_x;&#xD;&#xA;            m_x = -m_y;&#xD;&#xA;            m_y = _x;&#xD;&#xA;        }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22072" PostHistoryTypeId="1" PostId="8287" RevisionGUID="c5946174-001e-432c-96a3-7be9a19127d4" CreationDate="2018-11-18T12:20:54.077" UserId="9723" Text="Drawing Directed Lines (with arrow endings)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22073" PostHistoryTypeId="3" PostId="8287" RevisionGUID="c5946174-001e-432c-96a3-7be9a19127d4" CreationDate="2018-11-18T12:20:54.077" UserId="9723" Text="|opengl|line-drawing|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22074" PostHistoryTypeId="2" PostId="8288" RevisionGUID="6ffb88ad-6c08-443d-a34a-d378f89e6955" CreationDate="2018-11-18T16:01:32.003" UserDisplayName="user9485" Text="I don't see anything wrong with your code except for possibly the normalization of the direction. If the length of the vector gets updated automatically, it will change after the division of the x coordinate by the length. What you probably want is&#xD;&#xA;&#xD;&#xA;    public void Normalize()&#xD;&#xA;    {&#xD;&#xA;        float len = this.Length;&#xD;&#xA;        m_x /= len;&#xD;&#xA;        m_y /= len;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;instead. This would also explain why the arrow endings look more off for horizontal directions than for vertical directions. If the x component of the direction is small, then a division of m_x by the length only leads to a small change in the length of the direction. (Try to change the order of the two divisions in your Normalize function; then it should be the other way around.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22075" PostHistoryTypeId="2" PostId="8289" RevisionGUID="c90f271d-e4d5-4f90-954a-8c349adfa54b" CreationDate="2018-11-18T16:22:55.583" UserId="2654" Text="If you want to prevent cracks between the tessellated lines in a single curve, what you need to know is how to [miter the quads][1] correctly. Your GS's extrusion is presumably based on taking the 2D perpendicular to the line direction and extending the quad in that direction. Well, don't do that.&#xD;&#xA;&#xD;&#xA;Instead, have the TES compute the perpendicular direction for each vertex in the tessellation. You can compute this by taking the first derivative of the Bezier curve (its tangent), which can be computed exactly, and then finding the perpendicular of that. Each vertex will have its own perpendicular value.&#xD;&#xA;&#xD;&#xA;It should be this perpendicular which you feed to the GS to do the quad extrusion. And you should be guaranteed to have invariant results. The TES's computation of the position and perpendicular will be based solely on the positions of the control points and the tessellation coordinates. The control points are fixed for all invocations of a TES over a patch, and the tessellator guarantees the invariance of `gl_TessCoord` for the &quot;same vertex&quot;.&#xD;&#xA;&#xD;&#xA;Invariance *between* patches will be something of a problem. That is, invariance between the end of one set of 4 control points and the beginning of an attached one. The tessellation system only guarantees invariance at edges between patches if the computations that lead to the positions of the vertices are all based *solely* on data that is binary identical between the two edge vertices. And that's not generally the case for bezier curves; you achieve C1 continuity by ensuring that the slope between boundary control points is the same. And that slope is *not* passed as a parameter; it is computed. And thus, two edge vertices on different patches could have slightly different slope computations, which leads to different vertices, which leads to invariance.&#xD;&#xA;&#xD;&#xA;The only way to handle this is to have your Bezier spline defined by *six* control points rather than four. You pass as the first and last control points the previous/next control points for the Bezier spline (you'll have to make something up at the edges). This allows your computations to be invariant, since at the edges, you will be doing computations based on the exact same data.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Miter_joint" ContentLicense="CC BY-SA 4.0" />
  <row Id="22076" PostHistoryTypeId="2" PostId="8290" RevisionGUID="c4346398-a7da-4da4-9928-7df0fba87e0a" CreationDate="2018-11-18T18:29:31.287" UserId="9726" Text="What I have:&#xD;&#xA;&#xD;&#xA;- a plane given by its normal$\ n $ and a point on the plane$\ p $.&#xD;&#xA;- a 3D-point$\ v $.&#xD;&#xA;- a direction$\ d$.&#xD;&#xA;&#xD;&#xA;What I need:&#xD;&#xA;&#xD;&#xA;- the projection of$\ v$ along$\ d$ onto the plane.&#xD;&#xA;&#xD;&#xA;How can I calculate this? Thank you!&#xD;&#xA;&#xD;&#xA;P.S.: I need to implement that in GLSL, in case this is of any information. I would be fine with the formula so that I can work out the implementation myself, anyways. :-)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22077" PostHistoryTypeId="1" PostId="8290" RevisionGUID="c4346398-a7da-4da4-9928-7df0fba87e0a" CreationDate="2018-11-18T18:29:31.287" UserId="9726" Text="Project vertex onto plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="22078" PostHistoryTypeId="3" PostId="8290" RevisionGUID="c4346398-a7da-4da4-9928-7df0fba87e0a" CreationDate="2018-11-18T18:29:31.287" UserId="9726" Text="|opengl|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22079" PostHistoryTypeId="2" PostId="8291" RevisionGUID="2f2ca955-a4e8-448c-885e-5e402ed84d44" CreationDate="2018-11-18T19:23:52.167" UserId="9727" Text="This problem is giving me a really hard time.&#xD;&#xA;&#xD;&#xA;I'm always looking at the origin and have a camera that moves around it in an arcball mode. &#xD;&#xA;&#xD;&#xA;That part works beautifully:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4cEd5.png&#xD;&#xA;&#xD;&#xA;I'm calculating the camera position as follows:&#xD;&#xA;&#xD;&#xA;    camera.pos.x = origin.x + distance (arrow) * cos(angleX)&#xD;&#xA;    camera.pos.z = origin.z + distance * sin(angleX)&#xD;&#xA;    camera.pos.y : Float = origin.y + distance * sin(angleY)&#xD;&#xA;&#xD;&#xA; But now I also want to be able to shift the position of the camera laterally, i.e. on (or parallel to) the tangent plane to the sphere between the origin and the camera position. (That tangent plane being the screen plane.)&#xD;&#xA;&#xD;&#xA;I.e. I want to shift the view matrix to the left/right and upwards/downwards, so that the camera is shifted laterally. (I need this for features such as moving the view on a touchscreen [two-finger gesture] or texture projection).&#xD;&#xA;&#xD;&#xA;How should I go about this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22080" PostHistoryTypeId="1" PostId="8291" RevisionGUID="2f2ca955-a4e8-448c-885e-5e402ed84d44" CreationDate="2018-11-18T19:23:52.167" UserId="9727" Text="Translate an arcball camera upwards or left-right" ContentLicense="CC BY-SA 4.0" />
  <row Id="22081" PostHistoryTypeId="3" PostId="8291" RevisionGUID="2f2ca955-a4e8-448c-885e-5e402ed84d44" CreationDate="2018-11-18T19:23:52.167" UserId="9727" Text="|opengl|matrix|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22082" PostHistoryTypeId="6" PostId="8291" RevisionGUID="0d5eed61-903e-4e83-bd17-ff2357ea0e60" CreationDate="2018-11-18T19:34:32.417" UserId="9727" Comment="edited tags" Text="|opengl|mathematics|matrix|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22083" PostHistoryTypeId="2" PostId="8292" RevisionGUID="8d3243ff-75fb-4959-ac37-47aff421ac7c" CreationDate="2018-11-18T21:05:15.733" UserId="1582" Text="&gt; Edit: I suddenly understood the issue. The noise in the top right corner of (b) is because it's struggling to find the tiny fraction of angles in which the BSDF is not extremely close to zero. &#xD;&#xA;&#xD;&#xA;Yes your reasoning here is correct. &#xD;&#xA;&#xD;&#xA;Taken to the extreme if the top most surface was perfectly mirror (dirac delta BRDF), then it would never* sample the right ray from the light source that was perfectly aligned with the camera's view direction. For such a BRDF $\omega_i$ must equal $\omega_o$. " ContentLicense="CC BY-SA 4.0" />
  <row Id="22084" PostHistoryTypeId="5" PostId="8280" RevisionGUID="6c730b20-fdd1-4456-aca4-32a626ac55bf" CreationDate="2018-11-18T21:51:54.920" UserId="3024" Comment="added 258 characters in body" Text="found the problem, it was the shader. I am using following shader, that works fine&#xD;&#xA;&#xD;&#xA;    // Cubic.fsh&#xD;&#xA;    uniform vec4 insideColor;&#xD;&#xA;    varying vec4 v_textCoord;&#xD;&#xA;&#xD;&#xA;    void main(void) {&#xD;&#xA;        vec3 v_klm = v_textCoord.xyz;&#xD;&#xA;        float t = v_klm.x * v_klm.x * v_klm.x - v_klm.y * v_klm.z;&#xD;&#xA;        float alpha = clamp(sign(t), 0.0, 1.0);&#xD;&#xA;        gl_FragColor = insideColor * alpha;&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="22085" PostHistoryTypeId="50" PostId="7730" RevisionGUID="c5a6735e-75e6-4232-a175-ed330d392d4f" CreationDate="2018-11-19T00:01:30.267" UserId="-1" />
  <row Id="22091" PostHistoryTypeId="2" PostId="8294" RevisionGUID="c4eacf8f-13b5-4042-8cf7-0bc6b26b2643" CreationDate="2018-11-19T07:15:46.407" UserId="182" Text="To answer your question we just need to write it as linear algebra equations and solve them. Although your question doesn't state it, I assume that $v$ and $d$ are unit vectors. Let's call the projected point $x$.&#xD;&#xA;&#xD;&#xA;First, because the projected point is in the direction $d$, we can write:&#xD;&#xA;$$\vec{vx} = \lVert\vec{vx}\rVert d $$&#xD;&#xA;&#xD;&#xA;Second, because $p$ and $x$ are on the plane and $n$ is the plane normal, we can write:&#xD;&#xA;$$\vec{vx}\cdot n = \vec{vp}\cdot n$$&#xD;&#xA;&#xD;&#xA;We can now work on the equation until we get a definition for $\vec{vx}$:&#xD;&#xA;$$\begin{align}&#xD;&#xA;\vec{vx}\cdot n &amp; = \vec{vp}\cdot n \\&#xD;&#xA;\lVert\vec{vx}\rVert d\cdot n &amp; = \vec{vp}\cdot n \\&#xD;&#xA;\lVert\vec{vx}\rVert &amp; = \frac{\vec{vp}\cdot n}{d\cdot n} \\&#xD;&#xA;\vec{vx} &amp; = \frac{\vec{vp}\cdot n}{d\cdot n}d \\&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Or written differently:&#xD;&#xA;$$x = v + \frac{(p-v)\cdot n}{d\cdot n}d$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="22092" PostHistoryTypeId="6" PostId="8290" RevisionGUID="16f47f6f-9c90-44c2-8a9d-371f58a38e70" CreationDate="2018-11-19T07:16:51.843" UserId="182" Comment="edited tags" Text="|opengl|projections|shading|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22093" PostHistoryTypeId="2" PostId="8295" RevisionGUID="2863aab9-d462-42c2-b262-c5ab6969e69b" CreationDate="2018-11-19T08:34:52.877" UserId="8565" Text="I am currently building a graphics engine. I have a slight confusion on the imaging pipeline of computer screen. My question is how does computer transform the colour in the final frame buffer to radiance on the screen. My assumption is that the final colour in the render target should be proportional to luminance instead of radiance. Then, there is some function in the pipeline that will apply transform inverse of the photometric curve of this value to get the radiance of each RGB value. Am I correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22094" PostHistoryTypeId="1" PostId="8295" RevisionGUID="2863aab9-d462-42c2-b262-c5ab6969e69b" CreationDate="2018-11-19T08:34:52.877" UserId="8565" Text="Luminance and Radiance in computer screen" ContentLicense="CC BY-SA 4.0" />
  <row Id="22095" PostHistoryTypeId="3" PostId="8295" RevisionGUID="2863aab9-d462-42c2-b262-c5ab6969e69b" CreationDate="2018-11-19T08:34:52.877" UserId="8565" Text="|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22096" PostHistoryTypeId="5" PostId="8270" RevisionGUID="a6f2ef8a-82a0-4361-8142-367394980a49" CreationDate="2018-11-19T08:53:20.667" UserId="209" Comment="added 202 characters in body" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the correct matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; 2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;2 &amp; 5 &amp; -4 &amp; 7\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;Beginning by trying to go from BSpline to CR, I was thinking that if we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\begin{bmatrix}CR_0\\CR_1\\ ...\\CR_{n-1} \end{bmatrix} = M_{NxBtoCR}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;M_{NxBtoCR}= \frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;If we invert that matrix to get $M_{NxBtoCR}^{-1}$, one should then be able to map the other way. Each row of $M_{NxBtoCR}^{-1}$ consists of the same set of values, all non-zero, but  progressively offset in each row. If we ignore the smaller terms, it suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;.&#xD;&#xA;&#xD;&#xA;*Update* Those weights don't *quite* sum to 1.0 - you'll need to normalise them slightly.&#xD;&#xA;&#xD;&#xA;Obviously, this has assumed the curve is a loop. It's probably possible to adjust the weights for the end points but I'll leave that as an exercise for the reader." ContentLicense="CC BY-SA 4.0" />
  <row Id="22097" PostHistoryTypeId="5" PostId="8294" RevisionGUID="a86b2a6b-446c-43f6-ab9c-d20f5eff77ca" CreationDate="2018-11-19T16:41:26.647" UserId="182" Comment="Detailed the division by zero." Text="To answer your question we just need to write it as linear algebra equations and solve them. Although your question doesn't state it, I assume that $v$ and $d$ are unit vectors. Let's call the projected point $x$.&#xD;&#xA;&#xD;&#xA;First, because the projected point is in the direction $d$, we can write:&#xD;&#xA;$$\vec{vx} = \lVert\vec{vx}\rVert d $$&#xD;&#xA;&#xD;&#xA;Second, because $p$ and $x$ are on the plane and $n$ is the plane normal, we can write:&#xD;&#xA;$$\vec{vx}\cdot n = \vec{vp}\cdot n$$&#xD;&#xA;&#xD;&#xA;We can now work on the equation until we get a definition for $\vec{vx}$:&#xD;&#xA;$$\begin{align}&#xD;&#xA;\vec{vx}\cdot n &amp; = \vec{vp}\cdot n \\&#xD;&#xA;\lVert\vec{vx}\rVert d\cdot n &amp; = \vec{vp}\cdot n \\&#xD;&#xA;\lVert\vec{vx}\rVert &amp; = \frac{\vec{vp}\cdot n}{d\cdot n} \\&#xD;&#xA;\vec{vx} &amp; = \frac{\vec{vp}\cdot n}{d\cdot n}d \\&#xD;&#xA;\end{align}$$&#xD;&#xA;&#xD;&#xA;Or written differently:&#xD;&#xA;$$x = v + \frac{(p-v)\cdot n}{d\cdot n}d$$&#xD;&#xA;&#xD;&#xA;_The result is undefined when the scalar product $d \cdot v$ is $0$, which happens when $d$ and $n$ are orthogonal, when $d=0$, or when $n=0$. The first case means $d$ is parallel to the plane and the projection doesn't have a point solution, and the two other cases mean that either the plane or the projection are not defined._" ContentLicense="CC BY-SA 4.0" />
  <row Id="22098" PostHistoryTypeId="2" PostId="8296" RevisionGUID="b1ac406b-204b-4d45-b532-5fc9694e7e72" CreationDate="2018-11-19T22:37:18.153" UserId="7334" Text="I've been implementing a path tracer, referring pbrt-v3. However, I'm a bit confused about its implementation. Code is [here][1].&#xD;&#xA;&#xD;&#xA;It seems when we sample to do transmission, it tests if it meets a total internal reflection, but it doesn't assign a proper value to the `pdf`, instead, after the function returns `Vec3f(0,0,0)` as BTDF value, it then tests if `pdf` is 0, if 0 then directly jumps out of the tracing loop.&#xD;&#xA;&#xD;&#xA;I don't think this make sense since there should be radiance value if this ray continues to trace and does out of the specular object and hit a surface which is illuminated. But this implementation seems to leave out all such kind of radiance, and rely on the `sample_f` function to sample a reflection.&#xD;&#xA;&#xD;&#xA;So how to properly compute the `pdf` of total internal reflection?&#xD;&#xA;&#xD;&#xA;            // Account for the indirect subsurface scattering component&#xD;&#xA;            Spectrum f = pi.bsdf-&gt;Sample_f(pi.wo, &amp;wi, sampler.Get2D(), &amp;pdf,&#xD;&#xA;                                           BSDF_ALL, &amp;flags);&#xD;&#xA;            if (f.IsBlack() || pdf == 0) break;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mmp/pbrt-v3/blob/9f717d847a807793fa966cf0eaa366852efef167/src/core/reflection.cpp#L477" ContentLicense="CC BY-SA 4.0" />
  <row Id="22099" PostHistoryTypeId="1" PostId="8296" RevisionGUID="b1ac406b-204b-4d45-b532-5fc9694e7e72" CreationDate="2018-11-19T22:37:18.153" UserId="7334" Text="total internal reflection implementation in pbrt-v3" ContentLicense="CC BY-SA 4.0" />
  <row Id="22100" PostHistoryTypeId="3" PostId="8296" RevisionGUID="b1ac406b-204b-4d45-b532-5fc9694e7e72" CreationDate="2018-11-19T22:37:18.153" UserId="7334" Text="|pathtracing|brdf|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22101" PostHistoryTypeId="2" PostId="8297" RevisionGUID="534227f4-0611-4100-a2c1-0495ed6cdea4" CreationDate="2018-11-20T00:46:11.523" UserId="9256" Text="&#xD;&#xA;&#xD;&#xA;What algorithm can I use to rearm a broken image?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wmwt6.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any technique? algorithm? Can I use graphs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22102" PostHistoryTypeId="1" PostId="8297" RevisionGUID="534227f4-0611-4100-a2c1-0495ed6cdea4" CreationDate="2018-11-20T00:46:11.523" UserId="9256" Text="What algorithm to broken image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22103" PostHistoryTypeId="3" PostId="8297" RevisionGUID="534227f4-0611-4100-a2c1-0495ed6cdea4" CreationDate="2018-11-20T00:46:11.523" UserId="9256" Text="|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22104" PostHistoryTypeId="5" PostId="8297" RevisionGUID="2a8a2102-f861-4056-b8b9-108e9c50956f" CreationDate="2018-11-20T01:07:30.657" UserId="9256" Comment="deleted 2 characters in body; edited title" Text="&#xD;&#xA;What algorithm can I use to rearm a broken image?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wmwt6.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any technique? algorithm? Can I use graphs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22105" PostHistoryTypeId="4" PostId="8297" RevisionGUID="2a8a2102-f861-4056-b8b9-108e9c50956f" CreationDate="2018-11-20T01:07:30.657" UserId="9256" Comment="deleted 2 characters in body; edited title" Text="What algorithm to rearm a broken image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22109" PostHistoryTypeId="5" PostId="8297" RevisionGUID="82b54230-0922-402d-b54a-84df7e16343e" CreationDate="2018-11-20T02:53:25.287" UserId="9256" Comment="added 35 characters in body" Text="What algorithm can I use to rearm a broken image?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wmwt6.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any technique? algorithm? Can I use graphs? machine learning? computer graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22110" PostHistoryTypeId="6" PostId="8296" RevisionGUID="f80b6c3c-50ca-4ea6-befd-67a1cb98e0d7" CreationDate="2018-11-20T04:12:49.440" UserId="182" Comment="edited tags" Text="|pathtracing|brdf|physically-based|specular|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22111" PostHistoryTypeId="5" PostId="8102" RevisionGUID="ff4b000a-df99-40b4-84d2-3c286142462f" CreationDate="2018-11-20T04:23:19.393" UserId="182" Comment="Inserted the illustration image provided by OP in the question." Text="I have been following [LearnOpenGL.com][1]'s tutorials on PBR. Everything makes sense and I wrote up a shader for my physically based renderer.&#xD;&#xA;&#xD;&#xA;I noticed that the results look great, however all of my metal objects have such a strong specular on the edges thanks to my Fresnel calculation, and it is producing specular aliasing.&#xD;&#xA;&#xD;&#xA;See image:&#xD;&#xA;&#xD;&#xA;[![Illustration of shading aliasing][2]][3]&#xD;&#xA;&#xD;&#xA;I can't seem to figure out why, or how to fix this. I also uploaded a simplified version of my PBR fragment shader. If someone could take a look, I would really appreciate it.&#xD;&#xA;&#xD;&#xA;Simplified PBR fragment shader: https://textuploader.com/dv3h1&#xD;&#xA;&#xD;&#xA;Here is the tutorial I am following: https://learnopengl.com/PBR/Lighting&#xD;&#xA;It doesn't seem to have any of these specular aliasing issues.&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/Bnvvf.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Rreid.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="22112" PostHistoryTypeId="6" PostId="8102" RevisionGUID="ff4b000a-df99-40b4-84d2-3c286142462f" CreationDate="2018-11-20T04:23:19.393" UserId="182" Comment="Inserted the illustration image provided by OP in the question." Text="|physically-based|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22114" PostHistoryTypeId="50" PostId="7943" RevisionGUID="bd1e7f1a-87e6-4990-bd1d-b47ffd17f4f1" CreationDate="2018-11-20T10:00:36.427" UserId="-1" />
  <row Id="22115" PostHistoryTypeId="2" PostId="8299" RevisionGUID="03ba0a80-cfb0-4303-9988-6b89b9605f41" CreationDate="2018-11-20T11:07:20.470" UserId="9364" Text="so I am not new to interactive graphics programming, but I wanted to try out advanced techniques. Currently I am struggling to understand how the author of the 2011 paper &quot;Interactive Indirect Illumination Using Voxel Cone Tracing&quot; (Crassin et al) manages to solve the rendering equation. Specifically in section 6 he claims that the hemisphere can be partitioned into a sum of integrals. I know about the Riemann sum, but this doesn't look like it.&#xD;&#xA;So my question:&#xD;&#xA;How does cone tracing as explained in the paper solve the rendering equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22116" PostHistoryTypeId="1" PostId="8299" RevisionGUID="03ba0a80-cfb0-4303-9988-6b89b9605f41" CreationDate="2018-11-20T11:07:20.470" UserId="9364" Text="How does Voxel Cone Tracing solve the rendering equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22117" PostHistoryTypeId="3" PostId="8299" RevisionGUID="03ba0a80-cfb0-4303-9988-6b89b9605f41" CreationDate="2018-11-20T11:07:20.470" UserId="9364" Text="|global-illumination|voxelization|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22118" PostHistoryTypeId="5" PostId="8286" RevisionGUID="d8e3ade3-bf63-4407-b970-526dd634ed37" CreationDate="2018-11-20T13:56:54.210" UserId="6" Comment="deleted 15 characters in body; edited tags" Text="I'm trying to render thick cubic Bezier curves using the whole OpenGL 4.5 pipeline:&#xD;&#xA;&#xD;&#xA;1. I render a patch with 4 control points.  &#xD;&#xA;2. Vertex shader is simply pass-through to tessellation control shader.  &#xD;&#xA;3. TCS - sendng 4 vertices to tessalator with `gl_TessLevelOuter[1] = 10` &#xD;&#xA;4. TES - calculating position for every of those 10 tessellated isoline points using Bezier curve equation  &#xD;&#xA;5. Geometry shader - making quads out of every line it receives extruding vertices along line's normal vector.&#xD;&#xA;&#xD;&#xA;So far so good but this will obviously lead to cracks between adjacent quads. To solve this problem I would need to know the position of adjacent lines in TES or GS to correct edges. Is this information available?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22119" PostHistoryTypeId="6" PostId="8286" RevisionGUID="d8e3ade3-bf63-4407-b970-526dd634ed37" CreationDate="2018-11-20T13:56:54.210" UserId="6" Comment="deleted 15 characters in body; edited tags" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22120" PostHistoryTypeId="2" PostId="8300" RevisionGUID="c1618193-0612-4ba2-8872-598269d90727" CreationDate="2018-11-20T14:33:17.420" UserId="9194" Text="If the pieces are fairly close to where they were, [ICP][1] could be of help (under the assumption that the pieces are planar polygons).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Iterative_closest_point" ContentLicense="CC BY-SA 4.0" />
  <row Id="22121" PostHistoryTypeId="5" PostId="4401" RevisionGUID="d455b733-534b-4352-93d7-6284c807044a" CreationDate="2018-11-21T10:47:15.080" UserId="4958" Comment="added 1278 characters in body" Text="Shadow mapping with acceptable quality is quite a journey. So you implemented first step - basic shadow map that encompass whole scene statically. This means that shadow map texel size in light view space to texel size of rendered scene in camera view space ratio is quite big, resulting in aliasing. To reduce this ratio closer to 1:1 there are techniques you mentioned like:&#xD;&#xA;&#xD;&#xA; - the easiest way is increasing size of your shadow map, to find the value with still optimal performance,&#xD;&#xA; - align shadow map with camera view frustum. Then shadow map encompass smaller part of the scene, so it reduces aliasing,&#xD;&#xA; - this can be improved to CSM, which does the same but you need to render scene for each of cascade with different center position of light view matrix based on center point of each slice of frustum.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some of the basic techniques of smoothing the edge of shadow:&#xD;&#xA;&#xD;&#xA; - obviously PCF, but is it recommended to combine your PCF implementiation with built in hardware PCF (in Opengl - using `sampler2DShadow`). This would result in less loop iterations from your side and cheaper PCF,&#xD;&#xA; - blockiness of edges can be exchanged for noise using rotated Poisson Disk. Samples used to sample from shadow map are rotated randomly with each iteration of PCF loop.&#xD;&#xA;&#xD;&#xA;You can also research the edge smoothing techniques like:&#xD;&#xA;&#xD;&#xA; - rendering shadow map to MSAA applied framebuffer,&#xD;&#xA; - further enhancing PCF by [interpolation][1],&#xD;&#xA; - increasing number of samples with [temporal blend][2].&#xD;&#xA;&#xD;&#xA;PCF basic technique suffers from shadow acne which can be fixed by applying some offset in shadow test. Calculating the size of this offset is also area of [research][3].&#xD;&#xA;&#xD;&#xA;Other more advanced shadow map methods include:&#xD;&#xA;&#xD;&#xA; - [Exponential Shadow Maps][4] and [Variance Shadow Maps][5] - in most cases do not suffer from shadow acne and offer smooth edges without blockiness, but in cost of some light leaking situations,&#xD;&#xA; - Exponential Variance Shadow Maps - probably most advanced technique of 2D depth map shadow mapping, combines great smoothness of VSM and resolves light leaks, in a cost of memory usage doubling,&#xD;&#xA; - [Percentage Closer Soft Shadows][6] - basic technique of enhancing traditional shadow maps with varying penumbra size,&#xD;&#xA; - [Multiview Shadow Maps][7] - multiple shadow maps of some technique, arranged on area light, for computing realistic soft shadows with varying penumbra size,&#xD;&#xA; - [Deep Shadow Maps][8] - for enhancing volumetric scattering with shadows,&#xD;&#xA; - Real time ray traced shadows - probably the future.&#xD;&#xA;&#xD;&#xA;You didn't fail with PCF, it looks like that:)&#xD;&#xA;&#xD;&#xA;I wish there was a way to apply gaussian blur on shadow map in camera view space, but it doesn't work as expected.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://codeflow.org/entries/2013/feb/15/soft-shadow-mapping/#pcf-and-interpolation&#xD;&#xA;  [2]: https://pdfs.semanticscholar.org/3d73/8241631af1aece833e0944faff308be8ccb8.pdf&#xD;&#xA;  [3]: http://jcgt.org/published/0003/04/08/&#xD;&#xA;  [4]: http://jankautz.com/publications/esm_gi08.pdf&#xD;&#xA;  [5]: http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/VarianceShadowMapping/Doc/VarianceShadowMapping.pdf&#xD;&#xA;  [6]: http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf&#xD;&#xA;  [7]: http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/MultiViewSoftShadows.pdf&#xD;&#xA;  [8]: http://graphics.stanford.edu/papers/deepshadows/" ContentLicense="CC BY-SA 4.0" />
  <row Id="22125" PostHistoryTypeId="2" PostId="8302" RevisionGUID="e582175c-d9a7-4715-aaca-17be2e213f0c" CreationDate="2018-11-21T22:51:29.940" UserId="9742" Text="I have a flood-fill algorithm ([Flood-fill][1]) to fill a 24x24 matrix as follows (matrix is 24x24 here but will be much bigger in production):  &#xD;&#xA;&#xD;&#xA;    Main code:&#xD;&#xA;&#xD;&#xA;      var cspots,    // number of spots per group&#xD;&#xA;          gArr=[];   // global array which contains all group spots&#xD;&#xA;&#xD;&#xA;      var tArr = new Array(gArr.length);   // touch array for flood-fill&#xD;&#xA;      for(var spot in inArr) {&#xD;&#xA;        for (var tspot in tArr)  // initialise touch array &#xD;&#xA;          tArr[tspot]=0;&#xD;&#xA;        for(gspot in gArr) {     // find lowest open y*24+x ordinal&#xD;&#xA;          if (gArr[gspot][0] == 0) &#xD;&#xA;            break;&#xD;&#xA;          tArr[gspot]=1;&#xD;&#xA;        }&#xD;&#xA;        cspots = inArr[spot].GD;&#xD;&#xA;        userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;    function userFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, qt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if ((x &gt;= 0) &amp;&amp; (x &lt;= 23) &amp;&amp; (y &gt;= 0) &amp;&amp; (y &lt;= 23)) {&#xD;&#xA;        gord = y*24 + x;&#xD;&#xA;        if (gArr[gord][0] != 0 || tArr[gord]) &#xD;&#xA;          return;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        --cspots;&#xD;&#xA;        userFill(x+1,y,elem,tArr);&#xD;&#xA;        userFill(x-1,y,elem,tArr);&#xD;&#xA;        // before the y-change we need to see if there are any open spots on this line&#xD;&#xA;        for(gord=y*24; gord&lt;=(y*24)+23; gord++) {&#xD;&#xA;          if (gArr[gord][0] == 0) {&#xD;&#xA;            qt=1;&#xD;&#xA;            break;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if (!qt) {&#xD;&#xA;          userFill(x,y+1,elem,tArr);&#xD;&#xA;          userFill(x,y-1,elem,tArr);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is a standard flood-fill recursive algorithm (with an accompanying touch array to mark any touches) with the additional code that I check if all x-values are set to non-zero on each x-plane before changing the y-value. This produces a matrix like this:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is that it doesn't look very good (imo) as most of the areas are strung-out along the x-plane. What I want is each different group area to be in the shape of a square as much as I can. Sort-of like this example (using letters to indicate the different group areas):&#xD;&#xA;&#xD;&#xA;    V V V W W W W X X X X X&#xD;&#xA;    V V Y W W W W X X X X Z&#xD;&#xA;    Y Y Y W W W W Z Z Z Z Z&#xD;&#xA;    Y Y   W W W W Z Z Z Z Z&#xD;&#xA;    ... and so on&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I have changed the userFill to look at a boxX variable which is just the (sqrt of each area)+1, which hopefully I can use to limit each area to make a square-shape. And a preX variable to store the anchor point from each group area so I know how many spots have been added. Here's the new userFill:&#xD;&#xA;&#xD;&#xA;    Main code:&#xD;&#xA;&#xD;&#xA;      var tArr = new Array(gArr.length);&#xD;&#xA;      for(var spot in inArr) {&#xD;&#xA;        for (var tspot in tArr)  // initialise touch array &#xD;&#xA;          tArr[tspot]=0;&#xD;&#xA;        for(gspot in gArr) {     // find lowest open y*24+x ordinal&#xD;&#xA;          if (gArr[gspot][0] == 0) &#xD;&#xA;            break;&#xD;&#xA;          tArr[gspot]=1;&#xD;&#xA;        }&#xD;&#xA;        cspots = inArr[spot].GD;&#xD;&#xA;        boxX = Math.ceil(Math.sqrt(cspots));&#xD;&#xA;        preX = gArr[gspot][1];&#xD;&#xA;        userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;    function userFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, qt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if ((x &gt;= 0) &amp;&amp; (x &lt;= 23) &amp;&amp; (y &gt;= 0) &amp;&amp; (y &lt;= 23)) {&#xD;&#xA;        gord = y*24 + x;&#xD;&#xA;        if (gArr[gord][0] != 0 || tArr[gord]) &#xD;&#xA;          return;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        --cspots;&#xD;&#xA;        // before the x-change we need to see if we have done a boxX number of changes to maintain square-shape&#xD;&#xA;        if (Math.abs(x-preX) == boxX) {&#xD;&#xA;          userFill(preX,y+1,elem,tArr);&#xD;&#xA;          userFill(preX,y-1,elem,tArr);&#xD;&#xA;          return;&#xD;&#xA;        }&#xD;&#xA;        userFill(x+1,y,elem,tArr);&#xD;&#xA;        userFill(x-1,y,elem,tArr);&#xD;&#xA;        // before the y-change we need to see if there are any open spots on this line&#xD;&#xA;        for(gord=y*24; gord&lt;=(y*24)+boxX; gord++) {&#xD;&#xA;          if (gArr[gord][0] == 0) {&#xD;&#xA;            qt=1;&#xD;&#xA;            break;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if (!qt) {&#xD;&#xA;          userFill(x,y+1,elem,tArr);&#xD;&#xA;          userFill(x,y-1,elem,tArr);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;The only difference is that I check if boxX spots have been added and then call userFill recursively to change the y-plane.&#xD;&#xA;&#xD;&#xA;Here's the output and it looks better as most areas are square-like but obviously it needs work (missing most of the spots, pale-blue group area is very oddly-shaped and not square-like at all), but I wonder if there is a better algorithm out there that changes a flood-fill from line-based to square based.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Flood_fill&#xD;&#xA;  [2]: https://i.stack.imgur.com/8FjCF.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HL3gn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22126" PostHistoryTypeId="1" PostId="8302" RevisionGUID="e582175c-d9a7-4715-aaca-17be2e213f0c" CreationDate="2018-11-21T22:51:29.940" UserId="9742" Text="Flood-Fill and scanLine algorithms are line-based floods but I want square based floods" ContentLicense="CC BY-SA 4.0" />
  <row Id="22127" PostHistoryTypeId="3" PostId="8302" RevisionGUID="e582175c-d9a7-4715-aaca-17be2e213f0c" CreationDate="2018-11-21T22:51:29.940" UserId="9742" Text="|algorithm|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22128" PostHistoryTypeId="5" PostId="8302" RevisionGUID="021dc129-fba4-4d15-8966-0316289d0381" CreationDate="2018-11-22T01:14:51.133" UserId="9742" Comment="added 1222 characters in body" Text="I have a flood-fill algorithm ([Flood-fill][1]) to fill a 24x24 matrix as follows (matrix is 24x24 here but will be much bigger in production):  &#xD;&#xA;&#xD;&#xA;    Main code:&#xD;&#xA;&#xD;&#xA;      var cspots,    // number of spots per group&#xD;&#xA;          gArr=[];   // global array which contains all group spots&#xD;&#xA;&#xD;&#xA;      var tArr = new Array(gArr.length);   // touch array for flood-fill&#xD;&#xA;      for(var spot in inArr) {&#xD;&#xA;        for (var tspot in tArr)  // initialise touch array &#xD;&#xA;          tArr[tspot]=0;&#xD;&#xA;        for(gspot in gArr) {     // find lowest open y*24+x ordinal&#xD;&#xA;          if (gArr[gspot][0] == 0) &#xD;&#xA;            break;&#xD;&#xA;          tArr[gspot]=1;&#xD;&#xA;        }&#xD;&#xA;        cspots = inArr[spot].GD;&#xD;&#xA;        userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;    function userFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, qt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if ((x &gt;= 0) &amp;&amp; (x &lt;= 23) &amp;&amp; (y &gt;= 0) &amp;&amp; (y &lt;= 23)) {&#xD;&#xA;        gord = y*24 + x;&#xD;&#xA;        if (gArr[gord][0] != 0 || tArr[gord]) &#xD;&#xA;          return;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        --cspots;&#xD;&#xA;        userFill(x+1,y,elem,tArr);&#xD;&#xA;        userFill(x-1,y,elem,tArr);&#xD;&#xA;        // before the y-change we need to see if there are any open spots on this line&#xD;&#xA;        for(gord=y*24; gord&lt;=(y*24)+23; gord++) {&#xD;&#xA;          if (gArr[gord][0] == 0) {&#xD;&#xA;            qt=1;&#xD;&#xA;            break;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if (!qt) {&#xD;&#xA;          userFill(x,y+1,elem,tArr);&#xD;&#xA;          userFill(x,y-1,elem,tArr);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is a standard flood-fill recursive algorithm (with an accompanying touch array to mark any touches) with the additional code that I check if all x-values are set to non-zero on each x-plane before changing the y-value. This produces a matrix like this:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is that it doesn't look very good (imo) as most of the areas are strung-out along the x-plane. What I want is each different group area to be in the shape of a square as much as I can. Sort-of like this example (using letters to indicate the different group areas):&#xD;&#xA;&#xD;&#xA;    V V V W W W W X X X X X&#xD;&#xA;    V V Y W W W W X X X X Z&#xD;&#xA;    Y Y Y W W W W Z Z Z Z Z&#xD;&#xA;    Y Y   W W W W Z Z Z Z Z&#xD;&#xA;    ... and so on&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I have changed the userFill to look at a boxX variable which is just the (sqrt of each area)+1, which hopefully I can use to limit each area to make a square-shape. And a preX variable to store the anchor point from each group area so I know how many spots have been added. Here's the new userFill:&#xD;&#xA;&#xD;&#xA;    Main code:&#xD;&#xA;&#xD;&#xA;      var tArr = new Array(gArr.length);&#xD;&#xA;      for(var spot in inArr) {&#xD;&#xA;        for (var tspot in tArr)  // initialise touch array &#xD;&#xA;          tArr[tspot]=0;&#xD;&#xA;        for(gspot in gArr) {     // find lowest open y*24+x ordinal&#xD;&#xA;          if (gArr[gspot][0] == 0) &#xD;&#xA;            break;&#xD;&#xA;          tArr[gspot]=1;&#xD;&#xA;        }&#xD;&#xA;        cspots = inArr[spot].GD;&#xD;&#xA;        boxX = Math.ceil(Math.sqrt(cspots));&#xD;&#xA;        preX = gArr[gspot][1];&#xD;&#xA;        userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;    function userFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, qt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if ((x &gt;= 0) &amp;&amp; (x &lt;= 23) &amp;&amp; (y &gt;= 0) &amp;&amp; (y &lt;= 23)) {&#xD;&#xA;        gord = y*24 + x;&#xD;&#xA;        if (gArr[gord][0] != 0 || tArr[gord]) &#xD;&#xA;          return;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        --cspots;&#xD;&#xA;        // before the x-change we need to see if we have done a boxX number of changes to maintain square-shape&#xD;&#xA;        if (Math.abs(x-preX) == boxX) {&#xD;&#xA;          userFill(preX,y+1,elem,tArr);&#xD;&#xA;          userFill(preX,y-1,elem,tArr);&#xD;&#xA;          return;&#xD;&#xA;        }&#xD;&#xA;        userFill(x+1,y,elem,tArr);&#xD;&#xA;        userFill(x-1,y,elem,tArr);&#xD;&#xA;        // before the y-change we need to see if there are any open spots on this line&#xD;&#xA;        for(gord=y*24; gord&lt;=(y*24)+boxX; gord++) {&#xD;&#xA;          if (gArr[gord][0] == 0) {&#xD;&#xA;            qt=1;&#xD;&#xA;            break;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if (!qt) {&#xD;&#xA;          userFill(x,y+1,elem,tArr);&#xD;&#xA;          userFill(x,y-1,elem,tArr);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;The only difference is that I check if boxX spots have been added and then call userFill recursively to change the y-plane.&#xD;&#xA;&#xD;&#xA;Here's the output and it looks better as most areas are square-like but obviously it needs work (missing most of the spots, pale-blue group area is very oddly-shaped and not square-like at all), but I wonder if there is a better algorithm out there that changes a flood-fill from line-based to square based.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;I think I figured out an algorithm. You start with a single point at the lowest point in the matrix. You then add a surrounding square of points around that point followed by a larger square until cspots is exhausted. So:&#xD;&#xA;&#xD;&#xA;    0     (first spot in matrix (0,0))&#xD;&#xA;&#xD;&#xA;    1 1&#xD;&#xA;    0 1   (add 3 spots to make it a 2x2 square)&#xD;&#xA;&#xD;&#xA;    2 2 2&#xD;&#xA;    1 1 2&#xD;&#xA;    0 1 2   (add 5 spots to make it a 3x3 square)&#xD;&#xA;&#xD;&#xA;    and so on&#xD;&#xA;&#xD;&#xA;This can be done even if a number of squares are drawn and you are building on top of other squares. For example (X and Y are preexisting squares):&#xD;&#xA;&#xD;&#xA;      X&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;Place first spot of new group in the lowest point in matrix (0,2)&#xD;&#xA;&#xD;&#xA;    0 X&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;Try and build 1st level square  (an 'X' will be blocking one of the 1-level spots)&#xD;&#xA;&#xD;&#xA;    1 1&#xD;&#xA;    0 X&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;Try to build 2nd level square&#xD;&#xA;&#xD;&#xA;    2 2 2&#xD;&#xA;    1 1 2&#xD;&#xA;    0 X 2&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;3rd level&#xD;&#xA;&#xD;&#xA;    3 3 3 3&#xD;&#xA;    2 2 2 3&#xD;&#xA;    1 1 2 3&#xD;&#xA;    0 X 2 3&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;4th level&#xD;&#xA;&#xD;&#xA;    4 4 4 4 4&#xD;&#xA;    3 3 3 3 4&#xD;&#xA;    2 2 2 3 4&#xD;&#xA;    1 1 2 3 4&#xD;&#xA;    0 X 2 3 4&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;.. and so on. I just need to find the implementation now.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Flood_fill&#xD;&#xA;  [2]: https://i.stack.imgur.com/8FjCF.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HL3gn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22129" PostHistoryTypeId="2" PostId="8303" RevisionGUID="5f1a044d-4b12-4df3-a526-31d88d3c5a8a" CreationDate="2018-11-22T01:16:32.930" UserId="8680" Text="&#xD;&#xA;Your code, as seen on your post at the time of posting this answer, looks sort of like this (the following was thrown together rather quickly and may or may not work) :&#xD;&#xA;&#xD;&#xA;    function fill ( x, y, touched, elem ) {&#xD;&#xA;        if ( count &lt;= 0 ) return;&#xD;&#xA;        if ( isOutOfBounds(x,y) ) return;&#xD;&#xA;        &#xD;&#xA;        const idx = y*24 + x;&#xD;&#xA;        &#xD;&#xA;        if ( gArr[idx][0] != 0 || touched[idx] ) return;&#xD;&#xA;&#xD;&#xA;        touched[idx] = true;&#xD;&#xA;        gArr[idx][0] = elem;&#xD;&#xA;        count--;&#xD;&#xA;&#xD;&#xA;        fill(x+1, y, touched, elem);&#xD;&#xA;        fill(x-1, y, touched, elem);&#xD;&#xA;        fill(x, y+1, touched, elem);&#xD;&#xA;        fill(x, y-1, touched, elem);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the problem with this style of writing a flood fill is that it always takes the path to the right before considering the other 3 paths it can take. This leads the program to use up its spots by moving only to the right. Such a search is called a [Depth-First Search (DFS)][1]&#xD;&#xA;&#xD;&#xA;Instead, it would be nice if we could move around our grid starting from a point and growing out instead of blindly following the first path we find. A well known algorithm that does such a thing exists and it is called [Breadth-First Search (BFS)][2]. It goes roughly as follows (once again, this code probably wouldn't work, even if you implemented the missing bits):&#xD;&#xA;&#xD;&#xA;    function fill ( starting_point, count, elem ) {&#xD;&#xA;        if ( count &lt;= 0 ) return;&#xD;&#xA;        if ( isOutOfBounds(starting_point) ) return;&#xD;&#xA;        &#xD;&#xA;        let touched = Array(gArr.length).fill(false);&#xD;&#xA;        let queue = [starting_point];&#xD;&#xA;    &#xD;&#xA;        while ( count &gt; 0 &amp;&amp; queue.length &gt; 0 ) {&#xD;&#xA;            let p = queue.shift();&#xD;&#xA;&#xD;&#xA;            touched[p.idx] = true;&#xD;&#xA;            gArr[p.idx][0] = elem;&#xD;&#xA;    &#xD;&#xA;            for ( let neighbor of neighbors(p) )&#xD;&#xA;                if ( !isOutOfBounds( neighbor ) )&#xD;&#xA;                    if ( !touched[ neigbor.idx ] &amp;&amp; gArr[ neigbor.idx ][0] == 0 )&#xD;&#xA;                        queue.push(neighbor);&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What this is does is that it puts points to be painted in a queue and then looks at them in the same order that they were put in.&#xD;&#xA;&#xD;&#xA;Naturally, the first set of points that are added into the queue are the neighbors of the starting point of your flood fill, then the neighbors of those points, and so on. Effectively building a square of increasing size.&#xD;&#xA;&#xD;&#xA;Hope this helps! &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Depth-first_search&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Breadth-first_search" ContentLicense="CC BY-SA 4.0" />
  <row Id="22130" PostHistoryTypeId="5" PostId="8302" RevisionGUID="7a9c9bf2-859c-4de1-a19e-3807bcfbd262" CreationDate="2018-11-22T05:13:43.710" UserId="9742" Comment="added 1234 characters in body" Text="I have a flood-fill algorithm ([Flood-fill][1]) to fill a 24x24 matrix as follows (matrix is 24x24 here but will be much bigger in production):  &#xD;&#xA;&#xD;&#xA;    Main code:&#xD;&#xA;&#xD;&#xA;      var cspots,    // number of spots per group&#xD;&#xA;          gArr=[];   // global array which contains all group spots&#xD;&#xA;&#xD;&#xA;      var tArr = new Array(gArr.length);   // touch array for flood-fill&#xD;&#xA;      for(var spot in inArr) {&#xD;&#xA;        for (var tspot in tArr)  // initialise touch array &#xD;&#xA;          tArr[tspot]=0;&#xD;&#xA;        for(gspot in gArr) {     // find lowest open y*24+x ordinal&#xD;&#xA;          if (gArr[gspot][0] == 0) &#xD;&#xA;            break;&#xD;&#xA;          tArr[gspot]=1;&#xD;&#xA;        }&#xD;&#xA;        cspots = inArr[spot].GD;&#xD;&#xA;        userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;    function userFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, qt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if ((x &gt;= 0) &amp;&amp; (x &lt;= 23) &amp;&amp; (y &gt;= 0) &amp;&amp; (y &lt;= 23)) {&#xD;&#xA;        gord = y*24 + x;&#xD;&#xA;        if (gArr[gord][0] != 0 || tArr[gord]) &#xD;&#xA;          return;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        --cspots;&#xD;&#xA;        userFill(x+1,y,elem,tArr);&#xD;&#xA;        userFill(x-1,y,elem,tArr);&#xD;&#xA;        // before the y-change we need to see if there are any open spots on this line&#xD;&#xA;        for(gord=y*24; gord&lt;=(y*24)+23; gord++) {&#xD;&#xA;          if (gArr[gord][0] == 0) {&#xD;&#xA;            qt=1;&#xD;&#xA;            break;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if (!qt) {&#xD;&#xA;          userFill(x,y+1,elem,tArr);&#xD;&#xA;          userFill(x,y-1,elem,tArr);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is a standard flood-fill recursive algorithm (with an accompanying touch array to mark any touches) with the additional code that I check if all x-values are set to non-zero on each x-plane before changing the y-value. This produces a matrix like this:&#xD;&#xA;&#xD;&#xA;   [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is that it doesn't look very good (imo) as most of the areas are strung-out along the x-plane. What I want is each different group area to be in the shape of a square as much as I can. Sort-of like this example (using letters to indicate the different group areas):&#xD;&#xA;&#xD;&#xA;    V V V W W W W X X X X X&#xD;&#xA;    V V Y W W W W X X X X Z&#xD;&#xA;    Y Y Y W W W W Z Z Z Z Z&#xD;&#xA;    Y Y   W W W W Z Z Z Z Z&#xD;&#xA;    ... and so on&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I have changed the userFill to look at a boxX variable which is just the (sqrt of each area)+1, which hopefully I can use to limit each area to make a square-shape. And a preX variable to store the anchor point from each group area so I know how many spots have been added. Here's the new userFill:&#xD;&#xA;&#xD;&#xA;    Main code:&#xD;&#xA;&#xD;&#xA;      var tArr = new Array(gArr.length);&#xD;&#xA;      for(var spot in inArr) {&#xD;&#xA;        for (var tspot in tArr)  // initialise touch array &#xD;&#xA;          tArr[tspot]=0;&#xD;&#xA;        for(gspot in gArr) {     // find lowest open y*24+x ordinal&#xD;&#xA;          if (gArr[gspot][0] == 0) &#xD;&#xA;            break;&#xD;&#xA;          tArr[gspot]=1;&#xD;&#xA;        }&#xD;&#xA;        cspots = inArr[spot].GD;&#xD;&#xA;        boxX = Math.ceil(Math.sqrt(cspots));&#xD;&#xA;        preX = gArr[gspot][1];&#xD;&#xA;        userFill(gArr[gspot][1],gArr[gspot][2],inArr[spot].KY,tArr);&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;    function userFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, qt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if ((x &gt;= 0) &amp;&amp; (x &lt;= 23) &amp;&amp; (y &gt;= 0) &amp;&amp; (y &lt;= 23)) {&#xD;&#xA;        gord = y*24 + x;&#xD;&#xA;        if (gArr[gord][0] != 0 || tArr[gord]) &#xD;&#xA;          return;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        --cspots;&#xD;&#xA;        // before the x-change we need to see if we have done a boxX number of changes to maintain square-shape&#xD;&#xA;        if (Math.abs(x-preX) == boxX) {&#xD;&#xA;          userFill(preX,y+1,elem,tArr);&#xD;&#xA;          userFill(preX,y-1,elem,tArr);&#xD;&#xA;          return;&#xD;&#xA;        }&#xD;&#xA;        userFill(x+1,y,elem,tArr);&#xD;&#xA;        userFill(x-1,y,elem,tArr);&#xD;&#xA;        // before the y-change we need to see if there are any open spots on this line&#xD;&#xA;        for(gord=y*24; gord&lt;=(y*24)+boxX; gord++) {&#xD;&#xA;          if (gArr[gord][0] == 0) {&#xD;&#xA;            qt=1;&#xD;&#xA;            break;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if (!qt) {&#xD;&#xA;          userFill(x,y+1,elem,tArr);&#xD;&#xA;          userFill(x,y-1,elem,tArr);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;The only difference is that I check if boxX spots have been added and then call userFill recursively to change the y-plane.&#xD;&#xA;&#xD;&#xA;Here's the output and it looks better as most areas are square-like but obviously it needs work (missing most of the spots, pale-blue group area is very oddly-shaped and not square-like at all), but I wonder if there is a better algorithm out there that changes a flood-fill from line-based to square based.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;I think I figured out an algorithm. You start with a single point at the lowest point in the matrix. You then add a surrounding square of points around that point followed by a larger square until cspots is exhausted. So:&#xD;&#xA;&#xD;&#xA;    0     (first spot in matrix (0,0))&#xD;&#xA;&#xD;&#xA;    1 1&#xD;&#xA;    0 1   (add 3 spots to make it a 2x2 square)&#xD;&#xA;&#xD;&#xA;    2 2 2&#xD;&#xA;    1 1 2&#xD;&#xA;    0 1 2   (add 5 spots to make it a 3x3 square)&#xD;&#xA;&#xD;&#xA;    and so on&#xD;&#xA;&#xD;&#xA;This can be done even if a number of squares are drawn and you are building on top of other squares. For example (X and Y are preexisting squares):&#xD;&#xA;&#xD;&#xA;      X&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;Place first spot of new group in the lowest point in matrix (0,2)&#xD;&#xA;&#xD;&#xA;    0 X&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;Try and build 1st level square  (an 'X' will be blocking one of the 1-level spots)&#xD;&#xA;&#xD;&#xA;    1 1&#xD;&#xA;    0 X&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;Try to build 2nd level square&#xD;&#xA;&#xD;&#xA;    2 2 2&#xD;&#xA;    1 1 2&#xD;&#xA;    0 X 2&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;3rd level&#xD;&#xA;&#xD;&#xA;    3 3 3 3&#xD;&#xA;    2 2 2 3&#xD;&#xA;    1 1 2 3&#xD;&#xA;    0 X 2 3&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;4th level&#xD;&#xA;&#xD;&#xA;    4 4 4 4 4&#xD;&#xA;    3 3 3 3 4&#xD;&#xA;    2 2 2 3 4&#xD;&#xA;    1 1 2 3 4&#xD;&#xA;    0 X 2 3 4&#xD;&#xA;    X X Y Y&#xD;&#xA;    X X Y Y&#xD;&#xA;&#xD;&#xA;.. and so on. I just need to find the implementation now.&#xD;&#xA;&#xD;&#xA;**UPDATE 2**&#xD;&#xA;&#xD;&#xA;I have created the breadth-first algorithm as suggested below and it works much better. Here's the code and the image produced (which is very square-like for each of the 10 groups).&#xD;&#xA;&#xD;&#xA;    function bfsFill(x,y,elem,tArr) {&#xD;&#xA;      var gord, i=0, pt, queue=[], cnt=0;&#xD;&#xA;      if (!cspots) return;&#xD;&#xA;      if (isOutOfBounds(x,y)) return;&#xD;&#xA;      queue.push([x,y]);&#xD;&#xA;      while(cspots&gt;0 &amp;&amp; queue.length&gt;0) {&#xD;&#xA;        pt = queue.shift(); &#xD;&#xA;        gord = pt[1]*24 + pt[0];&#xD;&#xA;        tArr[gord] = 1;&#xD;&#xA;        gArr[gord][0] = elem;&#xD;&#xA;        --cspots;&#xD;&#xA;        var rArr = neighbours(pt);&#xD;&#xA;        async.eachSeries(rArr, function(el, cb2) {&#xD;&#xA;          if (!isOutOfBounds(el[0],el[1])) {&#xD;&#xA;            gord = el[1]*24 + el[0];&#xD;&#xA;            if (tArr[gord] == 0 &amp;&amp; gArr[gord][0] == 0) {&#xD;&#xA;              for(var qi in queue) {&#xD;&#xA;                if (queue[qi][0] == el[0] &amp;&amp; queue[qi][1]==el[1]) {&#xD;&#xA;                  cb2();&#xD;&#xA;                  return;&#xD;&#xA;                }&#xD;&#xA;              }&#xD;&#xA;              queue.push(el);&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          cb2();&#xD;&#xA;        }, function(err) {&#xD;&#xA;        });&#xD;&#xA;      }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Image file produced:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Flood_fill&#xD;&#xA;  [2]: https://i.stack.imgur.com/8FjCF.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HL3gn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ylMKg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22132" PostHistoryTypeId="2" PostId="8304" RevisionGUID="55788cf2-7a61-4f46-9752-787982584f8e" CreationDate="2018-11-22T08:12:27.827" UserId="113" Text="Here's a basic camera with panning (some parts removed for brevity). It's not arcball but should get the idea across. Basically it just transforms some directions of a plane in view space to one that is in world space.&#xD;&#xA;&#xD;&#xA;rotate and pan are called on mouse move with the change in mouse position.&#xD;&#xA;&#xD;&#xA;    // Updates the view matrix based on parameters&#xD;&#xA;	void updateCam()&#xD;&#xA;	{&#xD;&#xA;		// Calc eye position on sphere&#xD;&#xA;		glm::vec3 eyePos = glm::vec3(&#xD;&#xA;			rho * sin(phi) * cos(theta),&#xD;&#xA;			rho * cos(phi),&#xD;&#xA;			rho * sin(phi) * sin(theta));&#xD;&#xA;&#xD;&#xA;		setEyePos(eyePos + focalPt);&#xD;&#xA;		setFocalPt(focalPt);&#xD;&#xA;		updateLookAt(); // Uses eyePos and focalPt to calculate a view matrix&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// Input is a change in position lik&#xD;&#xA;	void rotate(glm::vec2 diff)&#xD;&#xA;	{&#xD;&#xA;		theta += diff.x * rotateSpeed;&#xD;&#xA;		phi -= diff.y * rotateSpeed;&#xD;&#xA;&#xD;&#xA;		// Clamp to prevent user flipping camera at the top optionally could just reverse up direction&#xD;&#xA;		phi = clamp(phi, 0.01f, 3.14f);&#xD;&#xA;		updateCam();&#xD;&#xA;	}&#xD;&#xA;	void pan(glm::vec2 diff)&#xD;&#xA;	{&#xD;&#xA;		// Up and right are the directions to pan when camera is facing forward&#xD;&#xA;		glm::mat3 invView = glm::inverse(view);&#xD;&#xA;		glm::vec3 dx = invView * glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;		glm::vec3 dy = invView * glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;		// Scale shift with scale so shift is relative to how far you are zoomed out&#xD;&#xA;		focalPt += (dy * diff.y - dx * diff.x) * shiftSpeed;&#xD;&#xA;		updateCam();&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="22133" PostHistoryTypeId="5" PostId="8303" RevisionGUID="d2fa3db0-f87c-4633-a094-e273db6f30b5" CreationDate="2018-11-22T09:41:30.903" UserId="8680" Comment="added 115 characters in body" Text="Your code, as seen on your post at the time of posting this answer, looks sort of like this (the following was thrown together rather quickly and may or may not work) :&#xD;&#xA;&#xD;&#xA;    function fill ( x, y, touched, elem ) {&#xD;&#xA;        if ( count &lt;= 0 ) return;&#xD;&#xA;        if ( isOutOfBounds(x,y) ) return;&#xD;&#xA;        &#xD;&#xA;        const idx = y*24 + x;&#xD;&#xA;        &#xD;&#xA;        if ( gArr[idx][0] != 0 || touched[idx] ) return;&#xD;&#xA;&#xD;&#xA;        touched[idx] = true;&#xD;&#xA;        gArr[idx][0] = elem;&#xD;&#xA;        count--;&#xD;&#xA;&#xD;&#xA;        fill(x+1, y, touched, elem);&#xD;&#xA;        fill(x-1, y, touched, elem);&#xD;&#xA;        fill(x, y+1, touched, elem);&#xD;&#xA;        fill(x, y-1, touched, elem);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the problem with this style of writing a flood fill is that it always takes the path to the right before considering the other 3 paths it can take. This leads the program to use up its spots by moving only to the right. Such a search is called a [Depth-First Search (DFS)][1]&#xD;&#xA;&#xD;&#xA;Instead, it would be nice if we could move around our grid starting from a point and growing out instead of blindly following the first path we find. A well known algorithm that does such a thing exists and it is called [Breadth-First Search (BFS)][2]. It goes roughly as follows (once again, this code probably wouldn't work, even if you implemented the missing bits):&#xD;&#xA;&#xD;&#xA;    function fill ( starting_point, count, elem ) {&#xD;&#xA;        if ( count &lt;= 0 ) return;&#xD;&#xA;        if ( isOutOfBounds(starting_point) ) return;&#xD;&#xA;        &#xD;&#xA;        let touched = Array(gArr.length).fill(false);&#xD;&#xA;        let queue = [starting_point];&#xD;&#xA;    &#xD;&#xA;        while ( count &gt; 0 &amp;&amp; queue.length &gt; 0 ) {&#xD;&#xA;            let p = queue.shift();&#xD;&#xA;&#xD;&#xA;            touched[p.idx] = true;&#xD;&#xA;            gArr[p.idx][0] = elem;&#xD;&#xA;    &#xD;&#xA;            for ( let neighbor of neighbors(p) ) {&#xD;&#xA;                if ( !isOutOfBounds( neighbor ) ) {&#xD;&#xA;                    if ( !touched[ neigbor.idx ] &amp;&amp; gArr[ neigbor.idx ][0] == 0 ){&#xD;&#xA;                        touched[ neighbor.idx ] = true;&#xD;&#xA;                        queue.push(neighbor);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What this is does is that it puts points to be painted in a queue and then looks at them in the same order that they were put in.&#xD;&#xA;&#xD;&#xA;Naturally, the first set of points that are added into the queue are the neighbors of the starting point of your flood fill, then the neighbors of those points, and so on. Effectively building a square of increasing size.&#xD;&#xA;&#xD;&#xA;Hope this helps! &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Depth-first_search&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Breadth-first_search" ContentLicense="CC BY-SA 4.0" />
  <row Id="22137" PostHistoryTypeId="5" PostId="8304" RevisionGUID="d2e54b82-0e5e-4e99-ad36-bf2f4a35b71b" CreationDate="2018-11-22T22:38:02.137" UserId="113" Comment="deleted 41 characters in body" Text="Here's a basic camera with panning (some parts removed for brevity). It's not arcball but should get the idea across. Basically it just transforms some directions of a plane in view space to one that is in world space.&#xD;&#xA;&#xD;&#xA;rotate and pan are called on mouse move with the change in mouse position.&#xD;&#xA;&#xD;&#xA;    // Updates the view matrix based on parameters&#xD;&#xA;	void updateCam()&#xD;&#xA;	{&#xD;&#xA;		// Calc eye position on sphere&#xD;&#xA;		glm::vec3 eyePos = glm::vec3(&#xD;&#xA;			rho * sin(phi) * cos(theta),&#xD;&#xA;			rho * cos(phi),&#xD;&#xA;			rho * sin(phi) * sin(theta));&#xD;&#xA;&#xD;&#xA;		setEyePos(eyePos + focalPt);&#xD;&#xA;		setFocalPt(focalPt);&#xD;&#xA;		updateLookAt(); // Uses eyePos and focalPt to calculate a view matrix&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// Input is a change in position&#xD;&#xA;	void rotate(glm::vec2 diff)&#xD;&#xA;	{&#xD;&#xA;		theta += diff.x * rotateSpeed;&#xD;&#xA;		phi -= diff.y * rotateSpeed;&#xD;&#xA;&#xD;&#xA;		// Clamp to prevent user flipping camera at top of sphere&#xD;&#xA;		phi = clamp(phi, 0.01f, 3.14f);&#xD;&#xA;		updateCam();&#xD;&#xA;	}&#xD;&#xA;	void pan(glm::vec2 diff)&#xD;&#xA;	{&#xD;&#xA;		// Up and right are the directions to pan when camera is facing forward&#xD;&#xA;		glm::mat3 invView = glm::inverse(view);&#xD;&#xA;		glm::vec3 dx = invView * glm::vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;		glm::vec3 dy = invView * glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;		// Scale shift with scale so shift is relative to how far you are zoomed out&#xD;&#xA;		focalPt += (dy * diff.y - dx * diff.x) * shiftSpeed;&#xD;&#xA;		updateCam();&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="22145" PostHistoryTypeId="2" PostId="8307" RevisionGUID="66c2d843-ab3a-460c-8344-c0e63600700f" CreationDate="2018-11-24T03:51:09.333" UserId="7743" Text="To simplify, assume faces and corners of the square are labeled and the camera lens if whatever makes this simplest (a 90 degree field of view projection?)&#xD;&#xA;&#xD;&#xA;The application: using a known and labeled unit square to assist an AR app." ContentLicense="CC BY-SA 4.0" />
  <row Id="22146" PostHistoryTypeId="1" PostId="8307" RevisionGUID="66c2d843-ab3a-460c-8344-c0e63600700f" CreationDate="2018-11-24T03:51:09.333" UserId="7743" Text="Given a picture of a unit square at an arbitrary angle, how can I reconstruct the distance and orientation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22147" PostHistoryTypeId="3" PostId="8307" RevisionGUID="66c2d843-ab3a-460c-8344-c0e63600700f" CreationDate="2018-11-24T03:51:09.333" UserId="7743" Text="|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22148" PostHistoryTypeId="5" PostId="8307" RevisionGUID="7ac5a71a-9578-4218-868b-f11d907ccba9" CreationDate="2018-11-24T04:02:32.567" UserId="7743" Comment="added 340 characters in body; edited title" Text="To simplify, assume faces and corners of the square are labeled and the camera lens if whatever makes this simplest (a 90 degree field of view projection?)&#xD;&#xA;&#xD;&#xA;The application: using a known and labeled unit square to assist an AR app.&#xD;&#xA;&#xD;&#xA;For the case of a perfectly centered rotated on one axis, we can use the estimated distance from the axis the square was rotated around plus the ratio of sizes of the distorted sides.&#xD;&#xA;&#xD;&#xA;But for an arbitrary view, the problem becomes much much harder.&#xD;&#xA;&#xD;&#xA;Links to the general case of this problem in projective geometry also appreciated" ContentLicense="CC BY-SA 4.0" />
  <row Id="22149" PostHistoryTypeId="4" PostId="8307" RevisionGUID="7ac5a71a-9578-4218-868b-f11d907ccba9" CreationDate="2018-11-24T04:02:32.567" UserId="7743" Comment="added 340 characters in body; edited title" Text="Given a picture of a unit square at an arbitrary angle and position, how can I reconstruct the distance and orientation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22150" PostHistoryTypeId="34" PostId="8260" RevisionGUID="f1204fcd-af1c-4169-aad1-d6c64ec4808b" CreationDate="2018-11-24T10:02:00.373" UserId="-1" Comment="52" />
  <row Id="22151" PostHistoryTypeId="5" PostId="8297" RevisionGUID="682581c7-877a-4cac-9a6a-c48e5ed3131a" CreationDate="2018-11-24T17:02:57.397" UserId="3003" Comment="Changed wording to be more understandable to naive speakers." Text="What algorithm can I use to reassemble a broken image?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wmwt6.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there any technique? algorithm? Can I use graphs? machine learning? computer graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22152" PostHistoryTypeId="4" PostId="8297" RevisionGUID="682581c7-877a-4cac-9a6a-c48e5ed3131a" CreationDate="2018-11-24T17:02:57.397" UserId="3003" Comment="Changed wording to be more understandable to naive speakers." Text="What algorithm to reassemble a broken image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22153" PostHistoryTypeId="2" PostId="8308" RevisionGUID="03c5876b-d3ca-4036-9892-cd3dfb79ece7" CreationDate="2018-11-25T19:04:24.730" UserId="9753" Text="I'm hoping to port my existing toy raytracer to a window so that I can see samples accumulate over time. And then port over to Pixar's pmj02:&#xD;&#xA;https://graphics.pixar.com/library/ProgressiveMultiJitteredSampling/paper.pdf&#xD;&#xA;&#xD;&#xA;I'm working within DX12 because the idea is to begin porting elements of the raytracer slowly into DX compute (or DXR), which I'm already familiar with.&#xD;&#xA;&#xD;&#xA;I have a simple quad fragment shader that samples a single Texture2D and writes to a quad on screen. At the moment, I am only writing data on startup, so that I can prove that copying over arbitrary 2D data to a texture2D is possible. However, I can only seem to write a black quad. I've flipped the sampler in hlsl with&#xD;&#xA;&#xD;&#xA;    return 1.0f - g_WindowTexture.Sample(g_SamLinearWrap, pin.TexCoordF) &#xD;&#xA;&#xD;&#xA;and the quad went white, so the texture definitely has zeros for data. This leads me to believe that I'm not correctly copying data over to the GPU resource.&#xD;&#xA;&#xD;&#xA;The window build code:&#xD;&#xA;&#xD;&#xA;    m_windowQuad.Initialize(m_D3dDevice, m_CommandList);&#xD;&#xA;&#xD;&#xA;	D3D12_DESCRIPTOR_HEAP_DESC SrvHeapDesc = {};&#xD;&#xA;	SrvHeapDesc.NumDescriptors = 1;&#xD;&#xA;	SrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;	SrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;	ThrowIfFailed(m_D3dDevice-&gt;CreateDescriptorHeap(&amp;SrvHeapDesc, IID_PPV_ARGS(&amp;m_SrvDescriptorHeap)));&#xD;&#xA;&#xD;&#xA;	// Fill heap with actual descriptor&#xD;&#xA;	CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(&#xD;&#xA;		m_SrvDescriptorHeap-&gt;GetCPUDescriptorHandleForHeapStart());&#xD;&#xA;&#xD;&#xA;	// Load initial texture&#xD;&#xA;	auto texture = std::make_unique&lt;ImageTexture&gt;();&#xD;&#xA;	// texture data&#xD;&#xA;	const uint width = 16;&#xD;&#xA;	const uint pitch = 16 * sizeof(u8) * 4;&#xD;&#xA;	const uint height = 16;&#xD;&#xA;	char colors[width * height * 4];&#xD;&#xA;	DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;	for (int i = 0; i &lt; height*width * 4; i++)&#xD;&#xA;		colors[i] = i % 256;&#xD;&#xA;&#xD;&#xA;	D3D12_RESOURCE_DESC texDesc = {};&#xD;&#xA;	texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;&#xD;&#xA;	texDesc.Width = width;&#xD;&#xA;	texDesc.Height = height;&#xD;&#xA;	texDesc.DepthOrArraySize = 1;&#xD;&#xA;	texDesc.MipLevels = 1;&#xD;&#xA;	texDesc.Format = format;&#xD;&#xA;	texDesc.SampleDesc.Count = 1;&#xD;&#xA;	texDesc.SampleDesc.Quality = 0;&#xD;&#xA;	texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;&#xD;&#xA;&#xD;&#xA;	CD3DX12_HEAP_PROPERTIES HeapProperties(D3D12_HEAP_TYPE_DEFAULT);&#xD;&#xA;&#xD;&#xA;	ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(&amp;HeapProperties, D3D12_HEAP_FLAG_NONE, &amp;texDesc, &#xD;&#xA;        D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(texture-&gt;Resource.ReleaseAndGetAddressOf())));&#xD;&#xA;	&#xD;&#xA;	D3D12_SUBRESOURCE_DATA texResource;&#xD;&#xA;	texResource.pData = colors;&#xD;&#xA;	texResource.RowPitch = (pitch + (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1)) &amp; ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1);&#xD;&#xA;	texResource.SlicePitch = texResource.RowPitch * height;&#xD;&#xA;&#xD;&#xA;	D3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = { };&#xD;&#xA;	SrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;&#xD;&#xA;	SrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;	SrvDesc.Texture2D.MostDetailedMip = 0;&#xD;&#xA;	SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;&#xD;&#xA;	SrvDesc.Format = texture-&gt;Resource-&gt;GetDesc().Format;&#xD;&#xA;	SrvDesc.Texture2D.MipLevels = texture-&gt;Resource-&gt;GetDesc().MipLevels;&#xD;&#xA;	SrvDesc.Texture2D.MostDetailedMip = 0;&#xD;&#xA;	SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;&#xD;&#xA;&#xD;&#xA;	Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; IntResource;&#xD;&#xA;	ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;		&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),&#xD;&#xA;		D3D12_HEAP_FLAG_NONE,&#xD;&#xA;		&amp;CD3DX12_RESOURCE_DESC::Buffer(texResource.SlicePitch * 16),&#xD;&#xA;		D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;		nullptr,&#xD;&#xA;		IID_PPV_ARGS(IntResource.ReleaseAndGetAddressOf())));&#xD;&#xA;&#xD;&#xA;	m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture-&gt;Resource.Get(),&#xD;&#xA;		D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));&#xD;&#xA;	UpdateSubresources(m_CommandList.Get(), texture-&gt;Resource.Get(), IntResource.Get(), 0, 0, 1, &amp;texResource);&#xD;&#xA;	m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture-&gt;Resource.Get(),&#xD;&#xA;		D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));&#xD;&#xA;	&#xD;&#xA;	m_D3dDevice-&gt;CreateShaderResourceView(texture-&gt;Resource.Get(), &amp;SrvDesc, hDescriptor);&#xD;&#xA;	texture-&gt;SRVHeapIndex = 0;&#xD;&#xA;	m_Textures[&quot;quad&quot;] = std::move(texture);&#xD;&#xA;&#xD;&#xA;And then per frame the following draw calls are made:&#xD;&#xA;&#xD;&#xA;    void PBRApp::DrawWindowQuad(ID3D12GraphicsCommandList* cmdList)&#xD;&#xA;    {&#xD;&#xA;	    cmdList-&gt;IASetVertexBuffers(0, 1, &amp;m_windowQuad.VertexBufferView());&#xD;&#xA;	    cmdList-&gt;IASetIndexBuffer(&amp;m_windowQuad.IndexBufferView());&#xD;&#xA;	    cmdList-&gt;IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);&#xD;&#xA;&#xD;&#xA;	    CD3DX12_GPU_DESCRIPTOR_HANDLE Tex(m_SrvDescriptorHeap-&gt;GetGPUDescriptorHandleForHeapStart());&#xD;&#xA;	    Tex.Offset(0, m_cbvSrvDescriptorSize);&#xD;&#xA;&#xD;&#xA;	    cmdList-&gt;SetGraphicsRootDescriptorTable(0, Tex);&#xD;&#xA;	    cmdList-&gt;DrawIndexedInstanced(m_windowQuad.IndexCount, 1, &#xD;&#xA;		    m_windowQuad.StartIndexLocation, m_windowQuad.BaseVertexLocation, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So, I'm fairly confident in my root signature, PSO, and draw calls.&#xD;&#xA;But I can't figure out why I keep getting a black quad (possibly empty data) drawn to the screen.&#xD;&#xA;&#xD;&#xA;Am I just going about this the wrong way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22154" PostHistoryTypeId="1" PostId="8308" RevisionGUID="03c5876b-d3ca-4036-9892-cd3dfb79ece7" CreationDate="2018-11-25T19:04:24.730" UserId="9753" Text="Writing data to a shader resource at runtime in DX12" ContentLicense="CC BY-SA 4.0" />
  <row Id="22155" PostHistoryTypeId="3" PostId="8308" RevisionGUID="03c5876b-d3ca-4036-9892-cd3dfb79ece7" CreationDate="2018-11-25T19:04:24.730" UserId="9753" Text="|raytracing|fragment-shader|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22156" PostHistoryTypeId="2" PostId="8309" RevisionGUID="88c91f1a-8ea9-4aa3-afa4-3ad80887edf0" CreationDate="2018-11-26T07:39:31.013" UserId="9577" Text="Thanks for the input everyone. The problem turned out to be an issue with texture coordinates. I was sampling right on the edge of each pixel in the full-size image, causing causing it to shift to the next pixel in line. To fix this, I translated the texture coordinates left/up by half a pixel and I get the intended result." ContentLicense="CC BY-SA 4.0" />
  <row Id="22157" PostHistoryTypeId="2" PostId="8310" RevisionGUID="ccc2f9eb-7cc4-4d10-ad4e-3350c33a8941" CreationDate="2018-11-26T08:42:56.740" UserId="7868" Text="Resource Views are read-only in DirectX. Have you tried using an unordered-access view instead?&#xD;&#xA;&#xD;&#xA;I can't see your shader, but I assume you declared something like&#xD;&#xA;&#xD;&#xA; `Texture2D&lt;float4&gt; tex : register(t0)`&#xD;&#xA;&#xD;&#xA;This is a good and correct for read-only resources working with standard resource views, but you want write-allowed resources (and thus UAVs); supporting them will mean using&#xD;&#xA; &#xD;&#xA;`RWTexture2D&lt;float4&gt; tex : register(u0)` &#xD;&#xA;&#xD;&#xA;instead.&#xD;&#xA;&#xD;&#xA;I haven't programmed in DX12, but in DX11 the setup for UAVs is almost the same as for SRVs; I don't see why that should have changed between versions.&#xD;&#xA;&#xD;&#xA;https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc&#xD;&#xA;&#xD;&#xA;https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createunorderedaccessview" ContentLicense="CC BY-SA 4.0" />
  <row Id="22158" PostHistoryTypeId="5" PostId="8310" RevisionGUID="8c899fa3-b536-4612-856e-43aa3a9ff1d7" CreationDate="2018-11-26T10:24:26.023" UserId="7868" Comment="Minor clean-up, reorganization, clarified cpu-side and gpu-side changes." Text="Resource Views are read-only in DirectX. Have you tried using an unordered-access view instead?&#xD;&#xA;&#xD;&#xA;The CPU-side setup for these is similar to standard resource views (at least in DX11, I haven't used DX12), just with more detail and slightly different objects:&#xD;&#xA;&#xD;&#xA;https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc&#xD;&#xA;&#xD;&#xA;https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createunorderedaccessview&#xD;&#xA;&#xD;&#xA;On the GPU side:&#xD;&#xA;&#xD;&#xA;I can't see your shader, but I assume you declared something like&#xD;&#xA;&#xD;&#xA; `Texture2D&lt;float4&gt; tex : register(t0)`&#xD;&#xA;&#xD;&#xA;If so you'll need to change the binding for `tex` into a write-allowed unordered-access texture, which would be:&#xD;&#xA; &#xD;&#xA;`RWTexture2D&lt;float4&gt; tex : register(u0)` &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22159" PostHistoryTypeId="5" PostId="8310" RevisionGUID="dca48c23-b440-4f95-8720-18055613856c" CreationDate="2018-11-26T10:34:11.823" UserId="7868" Comment="Small style/grammar update" Text="Resource Views are read-only in DirectX. Have you tried using an unordered-access view instead?&#xD;&#xA;&#xD;&#xA;The CPU-side setup for these is similar to standard resource views (at least in DX11, I haven't used DX12), just with more detail and slightly different objects:&#xD;&#xA;&#xD;&#xA;https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc&#xD;&#xA;&#xD;&#xA;https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createunorderedaccessview&#xD;&#xA;&#xD;&#xA;On the GPU side:&#xD;&#xA;&#xD;&#xA;I can't see your shader, but I assume you've declared something like&#xD;&#xA;&#xD;&#xA; `Texture2D&lt;float4&gt; tex : register(t0)`&#xD;&#xA;&#xD;&#xA;If so you'll need to change the binding for `tex` into a write-allowed unordered-access texture, which would be:&#xD;&#xA; &#xD;&#xA;`RWTexture2D&lt;float4&gt; tex : register(u0)` &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22160" PostHistoryTypeId="2" PostId="8311" RevisionGUID="cf14f694-69c0-42e8-8e36-c4dd17131f90" CreationDate="2018-11-26T15:50:55.633" UserDisplayName="user9436" Text="I am aware of libraries that already do this (like GLFW), but I would actually prefer do all of the window and context creation by myself." ContentLicense="CC BY-SA 4.0" />
  <row Id="22161" PostHistoryTypeId="1" PostId="8311" RevisionGUID="cf14f694-69c0-42e8-8e36-c4dd17131f90" CreationDate="2018-11-26T15:50:55.633" UserDisplayName="user9436" Text="How do I create a Win32 window with a Vulkan context?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22162" PostHistoryTypeId="3" PostId="8311" RevisionGUID="cf14f694-69c0-42e8-8e36-c4dd17131f90" CreationDate="2018-11-26T15:50:55.633" UserDisplayName="user9436" Text="|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22163" PostHistoryTypeId="2" PostId="8312" RevisionGUID="5c18caa1-3235-4227-b4ff-9b6834ae07c9" CreationDate="2018-11-26T17:04:58.103" UserId="9753" Text="So, I figured it out.&#xD;&#xA;&#xD;&#xA;While UAV will be necessary when I start manipulating data in Compute Shaders, for the time being, SRV works fine provided the resource is read-only from the fragment shader.&#xD;&#xA;&#xD;&#xA;The two big problems were&#xD;&#xA;&#xD;&#xA;1. Creating an ImageTexture that was receiving the data. Note that the data copy was occurring just fine, but the texture was never used in the rest of the code. The correct place was to copy the code into the resource within m_WindowQuad.&#xD;&#xA;&#xD;&#xA;2. Creating the ImageTexture (later m_WindowQuad) resource as&#xD;&#xA;&#xD;&#xA;`D3D12_RESOURCE_STATE_COPY_DEST`&#xD;&#xA;&#xD;&#xA;when it should have been defined as&#xD;&#xA;&#xD;&#xA;`D3D12_RESOURCE_STATE_COMMON`&#xD;&#xA;&#xD;&#xA;Near as I can tell, those two were the bulk of the problems.&#xD;&#xA;The code rewritten, now functional:&#xD;&#xA;&#xD;&#xA;	m_windowQuad.Initialize(m_D3dDevice, m_CommandList);&#xD;&#xA;	&#xD;&#xA;	D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = {};&#xD;&#xA;	HeapDesc.NumDescriptors = 1;&#xD;&#xA;	HeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;	HeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;	ThrowIfFailed(m_D3dDevice-&gt;CreateDescriptorHeap(&amp;HeapDesc, IID_PPV_ARGS(&amp;m_DescriptorHeap)));&#xD;&#xA;	&#xD;&#xA;	// Fill heap with actual descriptor&#xD;&#xA;	CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(&#xD;&#xA;		m_DescriptorHeap-&gt;GetCPUDescriptorHandleForHeapStart());&#xD;&#xA;&#xD;&#xA;	// texture data&#xD;&#xA;	const uint width = 16;&#xD;&#xA;	const uint pitch = 16 * sizeof(u8) * 4;&#xD;&#xA;	const uint height = 16;&#xD;&#xA;	char colors[width * height * 4];&#xD;&#xA;	DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;	for (int i = 0; i &lt; height*width * 4; i++)&#xD;&#xA;		colors[i] = i % 256;&#xD;&#xA;&#xD;&#xA;	D3D12_RESOURCE_DESC texDesc = {};&#xD;&#xA;	texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;&#xD;&#xA;	texDesc.Width = width;&#xD;&#xA;	texDesc.Height = height;&#xD;&#xA;	texDesc.DepthOrArraySize = 1;&#xD;&#xA;	texDesc.MipLevels = 1;&#xD;&#xA;	texDesc.Format = format;&#xD;&#xA;	texDesc.SampleDesc.Count = 1;&#xD;&#xA;	texDesc.SampleDesc.Quality = 0;&#xD;&#xA;	texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;&#xD;&#xA;&#xD;&#xA;	D3D12_SUBRESOURCE_DATA texResource;&#xD;&#xA;	texResource.pData = colors;&#xD;&#xA;	texResource.RowPitch = pitch;&#xD;&#xA;	texResource.SlicePitch = texResource.RowPitch * height;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;		&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),&#xD;&#xA;		D3D12_HEAP_FLAG_NONE, &#xD;&#xA;		&amp;texDesc,&#xD;&#xA;		D3D12_RESOURCE_STATE_COMMON,&#xD;&#xA;		nullptr, &#xD;&#xA;		IID_PPV_ARGS(m_windowQuad.Texture.ReleaseAndGetAddressOf())));&#xD;&#xA;	m_windowQuad.Texture-&gt;SetName(L&quot;Window Texture&quot;);&#xD;&#xA;&#xD;&#xA;	ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(&#xD;&#xA;		&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),&#xD;&#xA;		D3D12_HEAP_FLAG_NONE,&#xD;&#xA;		&amp;CD3DX12_RESOURCE_DESC::Buffer(texResource.SlicePitch * 16),&#xD;&#xA;		D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;		nullptr,&#xD;&#xA;		IID_PPV_ARGS(m_windowQuad.TextureUploader.ReleaseAndGetAddressOf())));&#xD;&#xA;	m_windowQuad.TextureUploader-&gt;SetName(L&quot;Window Texture Uploader&quot;);&#xD;&#xA;&#xD;&#xA;	D3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = { };&#xD;&#xA;	SrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;&#xD;&#xA;	SrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;	SrvDesc.Texture2D.MostDetailedMip = 0;&#xD;&#xA;	SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;&#xD;&#xA;	SrvDesc.Format = m_windowQuad.Texture-&gt;GetDesc().Format;&#xD;&#xA;	SrvDesc.Texture2D.MipLevels = m_windowQuad.Texture-&gt;GetDesc().MipLevels;&#xD;&#xA;	SrvDesc.Texture2D.MostDetailedMip = 0;&#xD;&#xA;	SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;&#xD;&#xA;&#xD;&#xA;	m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(m_windowQuad.Texture.Get(),&#xD;&#xA;		D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));&#xD;&#xA;	UpdateSubresources(m_CommandList.Get(), m_windowQuad.Texture.Get(), m_windowQuad.TextureUploader.Get(), 0, 0, 1, &amp;texResource);&#xD;&#xA;	m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(m_windowQuad.Texture.Get(),&#xD;&#xA;		D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));&#xD;&#xA;&#xD;&#xA;	m_D3dDevice-&gt;CreateShaderResourceView(m_windowQuad.Texture.Get(), &amp;SrvDesc, hDescriptor);" ContentLicense="CC BY-SA 4.0" />
  <row Id="22164" PostHistoryTypeId="2" PostId="8313" RevisionGUID="2479e1a7-07ce-4da8-8bdd-d705ddac9b02" CreationDate="2018-11-26T17:28:36.993" UserId="9562" Text="What is the method used in overlaying a grid (agonostic of the grid type) on to a height map? It seems it's some sort of projection, but what are the technical details in how to implement it?&#xD;&#xA;&#xD;&#xA;An example here is a hexagon grid overlayed onto the map in Civ5 that nicely handles spatial distance regardless of how high the height map is at a position - &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yN0HQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="22165" PostHistoryTypeId="1" PostId="8313" RevisionGUID="2479e1a7-07ce-4da8-8bdd-d705ddac9b02" CreationDate="2018-11-26T17:28:36.993" UserId="9562" Text="Overlaying a grid on to a height map" ContentLicense="CC BY-SA 4.0" />
  <row Id="22166" PostHistoryTypeId="3" PostId="8313" RevisionGUID="2479e1a7-07ce-4da8-8bdd-d705ddac9b02" CreationDate="2018-11-26T17:28:36.993" UserId="9562" Text="|3d|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22167" PostHistoryTypeId="2" PostId="8314" RevisionGUID="c2a1254e-b56f-4011-94fe-3864e1b3d20d" CreationDate="2018-11-26T22:07:50.050" UserId="9306" Text="There's no such thing as a Vulkan _context_, the way there is with OpenGL.  There are a number of things that _kind of_ correspond to an OpenGL context.  &#xD;&#xA;&#xD;&#xA;There's a `VkInstance`.  This encapsulates access to the Vulkan libraries on the system, including the extensions.  &#xD;&#xA;&#xD;&#xA;There's a physical device `VkPhysicalDevice` and a `Device`.  The former encapsulates all the information about a piece of hardware, typically your GPU.  The latter is a handle that lets you actually interact with it.  &#xD;&#xA;&#xD;&#xA;However, since you're focused on windows, what you're probably interested in is `VkSurfaceKHR`.  This encapsulates interaction with a windowing system.  On Windows, to interact with a window, you need to have an existing `VkInstance`, and you need to call [`vkCreateWin32SurfaceKHR`](https://vulkan.lunarg.com/doc/view/1.0.33.0/linux/vkspec.chunked/ch29s02.html) and pass it a structure containing an `HWND` and an `HINSTANCE`.  If it succeeds then you have a surface to which you can then present images.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22169" PostHistoryTypeId="2" PostId="8315" RevisionGUID="45f7dcbb-bee0-4699-9183-c8f9d3dfbaa4" CreationDate="2018-11-27T11:08:41.650" UserId="1981" Text="This problem is known as *camera calibration*. The goal is estimating the various parameters of a &quot;camera&quot;:&#xD;&#xA;&#xD;&#xA;* The intrinsic parameters: Things like focal length, distortion of the lens, sensor parameters etc.&#xD;&#xA;* Extrinsic parameters: Orientation of position of the camera.&#xD;&#xA;&#xD;&#xA;To robustly determine those from an image that contains labelled points you usually need more than one image. A typical way to do this is recording many images of a chessboard pattern. But as soon as you have determined all the intrinsic parameters, you could save those for future applications as they do not have to be estimated over and over again. &#xD;&#xA;&#xD;&#xA;I recommend reading the introduction to camera calibration of openCV: &#xD;&#xA;&#xD;&#xA;https://docs.opencv.org/3.1.0/dc/dbb/tutorial_py_calibration.html&#xD;&#xA;&#xD;&#xA;https://docs.opencv.org/3.1.0/d9/db7/tutorial_py_table_of_contents_calib3d.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22171" PostHistoryTypeId="2" PostId="8316" RevisionGUID="37add77c-1cff-4830-b779-f58a422bf2ab" CreationDate="2018-11-27T19:21:02.320" UserId="9505" Text="While implementing the &quot;Artist Friendly Metallic Fresnel&quot; paper by Ole Gulbrandsen (http://jcgt.org/published/0003/04/03/paper.pdf), I read that it is fully reversible:&#xD;&#xA;&#xD;&#xA;&gt;  (section 2.3.2): for all r,g ∈ (0,1), the map from (n, k) to (r,g) is a bijection&#xD;&#xA;&#xD;&#xA;However, this doesn't seem to be the case? When converting (r, g) to (n, k) and back to (r, g), I do not get a matching output to my initial parameters. **Is this expected?**&#xD;&#xA;&#xD;&#xA;    r: 0.7 0.55 0.075&#xD;&#xA;    g: 0.8 0.65 0.35&#xD;&#xA;    n: 2.39006 2.5479 1.44145&#xD;&#xA;    k: 4.98834 3.604 0.537046&#xD;&#xA;    r_check: 0.737183 0.601524 0.0773389&#xD;&#xA;    g_check: 0.827686 0.699977 0.35995&#xD;&#xA;&#xD;&#xA;Here is the implementation to verify, note that I only implemented `get_k()`, the other functions were already supplied by the paper. `get_k()` is derived from the following formula in the paper:&#xD;&#xA;&#xD;&#xA;$$k(r, n(r,g)) = \sqrt{ \frac {1}{1-r}(r(n(r,g)+1)^2 - (n(r,g) -1)^2)}$$&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;&#xD;&#xA;    float n_min(float r) {&#xD;&#xA;      return (1.0-r)/(1.0+r);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float n_max(float r) {&#xD;&#xA;      return (1.0 + std::sqrt(r))/(1.0-std::sqrt(r));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float get_n(float r, float g) {&#xD;&#xA;      return g*n_min(r) + (1.0-g)*n_max(r);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float get_k(float r, float n) {&#xD;&#xA;      return std::sqrt( (1.0/(1.0-r)) * (r * std::pow(n+1.0, 2)) - std::pow(n-1.0, 2) );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //float get_k2(float r, float n) {&#xD;&#xA;    //  float nr = (n+1.0)*(n+1.0)*r-(n-1.0)*(n-1.0);&#xD;&#xA;    //  return nr/(1.0-r);&#xD;&#xA;    //}&#xD;&#xA;&#xD;&#xA;    float get_r(float n, float k) {&#xD;&#xA;      return (std::pow(n-1.0, 2)+std::pow(k, 2)) / (std::pow(n+1.0, 2)+std::pow(k, 2));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float get_g(float n, float k) {&#xD;&#xA;      float r = get_r(n, k);&#xD;&#xA;      return (n_max(r)-n)/(n_max(r)-n_min(r));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int main() {&#xD;&#xA;      std::vector&lt;float&gt; r = {0.7, 0.55, 0.075};&#xD;&#xA;      std::vector&lt;float&gt; g = {0.8, 0.65, 0.35};&#xD;&#xA;      std::cout &lt;&lt; &quot;r: &quot; &lt;&lt; r[0] &lt;&lt; &quot; &quot; &lt;&lt; r[1] &lt;&lt; &quot; &quot; &lt;&lt; r[2] &lt;&lt; std::endl;&#xD;&#xA;      std::cout &lt;&lt; &quot;g: &quot; &lt;&lt; g[0] &lt;&lt; &quot; &quot; &lt;&lt; g[1] &lt;&lt; &quot; &quot; &lt;&lt; g[2] &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      std::vector&lt;float&gt; n(3);&#xD;&#xA;      std::vector&lt;float&gt; k(3);&#xD;&#xA;      for (int i = 0; i&lt;3; i++) {&#xD;&#xA;        n[i] = get_n(r[i], g[i]);&#xD;&#xA;        k[i] = get_k(r[i], n[i]);&#xD;&#xA;      }&#xD;&#xA;      std::cout &lt;&lt; &quot;n: &quot; &lt;&lt; n[0] &lt;&lt; &quot; &quot; &lt;&lt; n[1] &lt;&lt; &quot; &quot; &lt;&lt; n[2] &lt;&lt; std::endl;&#xD;&#xA;      std::cout &lt;&lt; &quot;k: &quot; &lt;&lt; k[0] &lt;&lt; &quot; &quot; &lt;&lt; k[1] &lt;&lt; &quot; &quot; &lt;&lt; k[2] &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;      std::vector&lt;float&gt; r_check(3);&#xD;&#xA;      std::vector&lt;float&gt; g_check(3);&#xD;&#xA;      for (int i = 0; i&lt;3; i++) {&#xD;&#xA;        r_check[i] = get_r(n[i], k[i]);&#xD;&#xA;        g_check[i] = get_g(n[i], k[i]);&#xD;&#xA;      }&#xD;&#xA;      std::cout &lt;&lt; &quot;r_check: &quot; &lt;&lt; r_check[0] &lt;&lt; &quot; &quot; &lt;&lt; r_check[1] &lt;&lt; &quot; &quot; &lt;&lt; r_check[2] &lt;&lt; std::endl;&#xD;&#xA;      std::cout &lt;&lt; &quot;g_check: &quot; &lt;&lt; g_check[0] &lt;&lt; &quot; &quot; &lt;&lt; g_check[1] &lt;&lt; &quot; &quot; &lt;&lt; g_check[2] &lt;&lt; std::endl;&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="22172" PostHistoryTypeId="1" PostId="8316" RevisionGUID="37add77c-1cff-4830-b779-f58a422bf2ab" CreationDate="2018-11-27T19:21:02.320" UserId="9505" Text="&quot;Artist Friendly Metallic Fresnel&quot; reversible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22173" PostHistoryTypeId="3" PostId="8316" RevisionGUID="37add77c-1cff-4830-b779-f58a422bf2ab" CreationDate="2018-11-27T19:21:02.320" UserId="9505" Text="|raytracing|brdf|shading|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22174" PostHistoryTypeId="2" PostId="8317" RevisionGUID="761559f6-feb0-456c-9dbb-9bd3bb309fbd" CreationDate="2018-11-27T23:28:19.873" UserId="6496" Text="What measurement/monitoring tools could I use to get the FPS values for a simple Vulkan app?&#xD;&#xA;&#xD;&#xA;Thanks in advance&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22175" PostHistoryTypeId="1" PostId="8317" RevisionGUID="761559f6-feb0-456c-9dbb-9bd3bb309fbd" CreationDate="2018-11-27T23:28:19.873" UserId="6496" Text="FPS counter for a simple Vulkan app" ContentLicense="CC BY-SA 4.0" />
  <row Id="22176" PostHistoryTypeId="3" PostId="8317" RevisionGUID="761559f6-feb0-456c-9dbb-9bd3bb309fbd" CreationDate="2018-11-27T23:28:19.873" UserId="6496" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22177" PostHistoryTypeId="2" PostId="8318" RevisionGUID="3ef2aeb6-b1fb-4130-bd7f-5fc6477d51ca" CreationDate="2018-11-27T23:52:37.397" UserId="9762" Text="You might want to try the VK_LAYER_LUNARG_monitor layer from the LunarG Vulkan SDK." ContentLicense="CC BY-SA 4.0" />
  <row Id="22179" PostHistoryTypeId="2" PostId="8319" RevisionGUID="281ab19e-5eb3-44c8-87f9-89282e7dba65" CreationDate="2018-11-28T03:08:19.023" UserId="9763" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. In the GL code that I am porting, it frequently switches shader programs with glUseProgram.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets` when changing shader programs.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to using a single shader program and single pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler and uniforms for transforming the output from texture lookups. When I want to draw flat colored objects, I would presumably set the color in the vertex and bind a 2x2 white sampler and when I want to render images I bind a proper image sampler. Note: I also use a matrix to transform textureColor as this allows me to configure the uniform for single channel alpha textures (`texture(tex, vtexcoord).r`) vs 4 channel RGBA textures (`texture(tex, vtexcoord).rgba`). For text rendering where the sampler has one channel, the color transform matrix can be set to just accumulate the red color channel into the resulting color vector. Color layout is bound with `VK_FORMAT_R8G8B8A8_UNORM` to only consume 4 bytes in the vertex (I don't need to support HDR). I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout only performing uniform updates and this common albeit slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines, and two of three sets of shaders and two vertex formats. i.e. where is the best balance between these two concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct with just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;I guess I could benchmark this but wondering if someone already has data to compare these approaches in Vulkan. I am aware of Ubershaders however this is hardly an Ubershader (see below). The question concerns the ratio of program switch cost overhead versus the overhead of a 2x2 NOP texture lookup and texture color transform matrix for the alpha versus RGBA versus no texture case. I am assuming the 2x2 sampler is cached.&#xD;&#xA;&#xD;&#xA;With multiple shaders the program switches are likely to be in the order of 100's or even 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally RGBA images, typically just using the vertex alpha value and all currently using orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Would a 2x2 NOP texture with a single layout and a single program the most efficient approach? or for ultimate performance should I continue to switch programs and layouts to keep the smallest vertex buffer size and least fragment shader operations? I couldn't find any data to drive this decision. Does someone have benchmarks for something similar to this? i.e. shader program switch overhead vs redundant shader ops and vertex buffer elements. Code maintenance and code commonality are also factors that are slightly more opinionated but will influence my decision.&#xD;&#xA;&#xD;&#xA;I read that 2x2 is required because 1x1 pixel samplers have different behaviors, but I haven't found any data on program/pipeline binds vs just uniform binds and programs with redundant ops to allow the use of common shaders. I have no idea where the break-even point is for either approach.&#xD;&#xA;&#xD;&#xA;For the shared model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 0) uniform UBO&#xD;&#xA;	{&#xD;&#xA;    	mat4 modelViewProjection;&#xD;&#xA;    	mat4 texColorTransform;&#xD;&#xA;	} ubo;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	vec4 texColor = texture(tex, vtexcoord);&#xD;&#xA;    	vec4 transformedColor = texColor * ubo.texColorTransform;&#xD;&#xA;    	outColor = vcolor * transformedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;        mat4 texColorTransform;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="22180" PostHistoryTypeId="1" PostId="8319" RevisionGUID="281ab19e-5eb3-44c8-87f9-89282e7dba65" CreationDate="2018-11-28T03:08:19.023" UserId="9763" Text="Is a single shader and 2x2 white sampler more efficient than frequent switching between sampler vs no smapler shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22181" PostHistoryTypeId="3" PostId="8319" RevisionGUID="281ab19e-5eb3-44c8-87f9-89282e7dba65" CreationDate="2018-11-28T03:08:19.023" UserId="9763" Text="|opengl|shader|texture|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22182" PostHistoryTypeId="4" PostId="8319" RevisionGUID="29a89de5-e63a-439e-a6c4-506b831ce1a8" CreationDate="2018-11-28T06:33:40.440" UserId="9763" Comment="Fixed typo in question title" Text="Is a single shader and 2x2 white sampler more efficient than frequent switching between sampler vs no sampler shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22183" PostHistoryTypeId="2" PostId="8320" RevisionGUID="ef83a48a-5b06-4533-b420-91a420429819" CreationDate="2018-11-28T06:58:19.127" UserId="4839" Text="Although I have tried for a long time, I cannot understand Eq.(11) of paper &quot;Microfacet Models for Refraction through Rough Surfaces&quot; written by Bruce Walter, Stephen Marschner, Hongsong Li and Kenneth Torrance, Eurographics Symposium on Rendering(2007). My knowledge of change of variable is no more than what are described in this webpage: http://tutorial.math.lamar.edu/Classes/CalcIII/ChangeOfVariables.aspx. Because I am not a smart people, can you please help me understand how this equation is derived based on the knowledge of that webpage and in a way that a common human can follow? Specifically, one of the questions I cannot answer is: what is the variable to be changed and changed to, $\mathbf{i}$, $\mathbf{o}$ or $\mathbf{m}$? The paper is famous so it can be easily found from Google search. For your convenience, I copied the pertaining page here. Thank you for your help.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UN5Uu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22184" PostHistoryTypeId="1" PostId="8320" RevisionGUID="ef83a48a-5b06-4533-b420-91a420429819" CreationDate="2018-11-28T06:58:19.127" UserId="4839" Text="Ask for help on understanding a formula related to change of variable" ContentLicense="CC BY-SA 4.0" />
  <row Id="22185" PostHistoryTypeId="3" PostId="8320" RevisionGUID="ef83a48a-5b06-4533-b420-91a420429819" CreationDate="2018-11-28T06:58:19.127" UserId="4839" Text="|brdf|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22186" PostHistoryTypeId="4" PostId="8319" RevisionGUID="9f0c1df9-1d63-4aff-8513-cea86882e21c" CreationDate="2018-11-28T07:25:32.327" UserId="9763" Comment="Changed 2x2 to 1x1 pixel and modified question for clarity with respect to shaders with and without samplers" Text="Is a single shader and 1x1 pixel white sampler more efficient than frequent switching between shaders with and without samplers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22187" PostHistoryTypeId="2" PostId="8321" RevisionGUID="af57cb81-2af2-40e0-a91c-c6b71847864f" CreationDate="2018-11-28T07:40:19.993" UserId="4839" Text="I cannot understand an algorithm which combines stratified sampling and importance sampling of Monte Carlo. It is introduced in Page 73 of a textbook &quot;Advanced Global Illumination&quot;, 2nd edition, written by Philip Dutre, Philippe Bekaert and Kavita Bala. The text gives almost no explanation on the algorithm so I got stuck at the line $N_i=\lfloor Pn+u\rfloor-N_{sum}$. I tried my best but I think I'm at my wit's end to figure out how this line or the whole psudo-code works. I just don't have any understanding. I read the text again and again and stared at Fig 3.9 above the algorithm for a long time but could not find any clue. Could you please give me an explanation of this algorithm in a way a common human can follow? For your convenience, I copied this section as follows. I know there is [another question thread][1] but that question has not been answered and I think my post is more detailed so please do not merge mine to his.&#xD;&#xA;&#xD;&#xA;Thanks a lot for your help.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/5480/an-example-of-combining-stratified-sampling-and-importance-sampling-in-agi&#xD;&#xA;  [2]: https://i.stack.imgur.com/ydkVN.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/oDB4P.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22188" PostHistoryTypeId="1" PostId="8321" RevisionGUID="af57cb81-2af2-40e0-a91c-c6b71847864f" CreationDate="2018-11-28T07:40:19.993" UserId="4839" Text="Ask for help on understand an algorithm which combines stratified sampling and importance sampling of Monte Carlo" ContentLicense="CC BY-SA 4.0" />
  <row Id="22189" PostHistoryTypeId="3" PostId="8321" RevisionGUID="af57cb81-2af2-40e0-a91c-c6b71847864f" CreationDate="2018-11-28T07:40:19.993" UserId="4839" Text="|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22190" PostHistoryTypeId="50" PostId="8192" RevisionGUID="38c94b5d-c73b-420d-9868-a16ef8820c00" CreationDate="2018-11-28T09:01:15.687" UserId="-1" />
  <row Id="22191" PostHistoryTypeId="2" PostId="8322" RevisionGUID="558195ab-f321-4ee3-a678-5cb989e1bd6c" CreationDate="2018-11-28T09:53:33.253" UserId="9755" Text="Short answer: yes, it SHOULD, it would be nice. But the technology currently used does not make that possible.&#xD;&#xA;&#xD;&#xA;The long answer: it's complicated. First, the signal that your computer sends to the screen is an electric. To make it easy to understand, take a look at this [post about the old VGA connector][1].&#xD;&#xA;&#xD;&#xA;The signal still contains R G and B channels, that's what lights your pixels in a given color. So to try to answer your question: the conversion from RGB electric signal to light (meaning radiance) depends on the screen, not on your PC. Different screens and brands behave differently, that's why they don't all look the same. The technology used for the pixels also matters: LED, LCD, cathodic, OLED, plasma... all behave in different ways.&#xD;&#xA;&#xD;&#xA;The signal coming from your computer tells the screen the color and the intensity of each pixel. The intensity is transmitted using a [pulse][2] (the leds blink fast enough so the human eye can't see it and the % of time it's on determines how bright it looks... to human eye). &#xD;&#xA;&#xD;&#xA;Even if that was not the case, and the pixels were analogic, you would still send an electric signal: some ampères at a given voltage, in other words some watts. And that's why it's all about radiance: it's a [radiometric measure][3]. &#xD;&#xA;&#xD;&#xA;In simple words, your computer sends current to pixels. The way the current is transformed into light (meaning luminance) is related to the pixels technology, quality, age, heat: there are too many factors that are not under the screen's control. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://electronics.stackexchange.com/questions/93078/soldering-a-vga-cable-number-of-wires-doesnt-match&#xD;&#xA;  [2]: https://www.researchgate.net/figure/Two-measures-of-electrical-power-signals-for-LED-control-with-D-Type-flip-flop-register_fig6_224222964&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiance" ContentLicense="CC BY-SA 4.0" />
  <row Id="22192" PostHistoryTypeId="5" PostId="8322" RevisionGUID="fe4a4725-cae4-409e-a389-25a45ae6d5ca" CreationDate="2018-11-28T13:09:11.300" UserId="9755" Comment="added 7 characters in body" Text="Short answer: yes, it SHOULD, it would be nice. But the technology currently used does not make that possible.&#xD;&#xA;&#xD;&#xA;The long answer: it's complicated. First, the signal that your computer sends to the screen is an electric signal. To make it easy to understand, take a look at this [post about the old VGA connector][1].&#xD;&#xA;&#xD;&#xA;The signal still contains R G and B channels, that's what lights your pixels in a given color. So to try to answer your question: the conversion from RGB electric signal to light (meaning radiance) depends on the screen, not on your PC. Different screens and brands behave differently, that's why they don't all look the same. The technology used for the pixels also matters: LED, LCD, cathodic, OLED, plasma... all behave in different ways.&#xD;&#xA;&#xD;&#xA;The signal coming from your computer tells the screen the color and the intensity of each pixel. The intensity is transmitted using a [pulse][2] (the leds blink fast enough so the human eye can't see it and the % of time it's on determines how bright it looks... to human eye). &#xD;&#xA;&#xD;&#xA;Even if that was not the case, and the pixels were analogic, you would still send an electric signal: some ampères at a given voltage, in other words some watts. And that's why it's all about radiance: it's a [radiometric measure][3]. &#xD;&#xA;&#xD;&#xA;In simple words, your computer sends current to pixels. The way the current is transformed into light (meaning luminance) is related to the pixels technology, quality, age, heat: there are too many factors that are not under the screen's control. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://electronics.stackexchange.com/questions/93078/soldering-a-vga-cable-number-of-wires-doesnt-match&#xD;&#xA;  [2]: https://www.researchgate.net/figure/Two-measures-of-electrical-power-signals-for-LED-control-with-D-Type-flip-flop-register_fig6_224222964&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiance" ContentLicense="CC BY-SA 4.0" />
  <row Id="22193" PostHistoryTypeId="2" PostId="8323" RevisionGUID="a3fca140-13be-4528-be70-db35e6b3dab6" CreationDate="2018-11-28T18:59:14.363" UserId="48" Text="Try AMD's [OCAT](https://github.com/GPUOpen-Tools/OCAT) tool. It can overlay an FPS counter on a Vulkan or D3D12 app, similar to how FRAPS works for D3D11/OpenGL. (It should work on all Vulkan-supporting GPUs, btw, not just AMD ones.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22200" PostHistoryTypeId="5" PostId="8319" RevisionGUID="54facf52-0d6b-49e3-9d2b-fde087e74e4c" CreationDate="2018-11-28T22:28:46.320" UserId="9763" Comment="Removed last erroneous reference to 2x2 pixel" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. In the GL code that I am porting, it frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets` when changing shader programs.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to using a single shader program and single pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler and uniforms for transforming the output from texture lookups. When I want to draw flat colored objects, I would presumably set the color in the vertex and bind a 2x2 white sampler and when I want to render images I bind a proper image sampler. Note: I also use a matrix to transform textureColor as this allows me to configure the uniform for single channel alpha textures (`texture(tex, vtexcoord).r`) vs 4 channel RGBA textures (`texture(tex, vtexcoord).rgba`). For text rendering where the sampler has one channel, the color transform matrix can be set to just accumulate the red color channel into the resulting color vector. Color layout is bound with `VK_FORMAT_R8G8B8A8_UNORM` to only consume 4 bytes in the vertex (I don't need to support HDR). I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout only performing uniform updates and this common albeit slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines, and two of three sets of shaders and two vertex formats. i.e. where is the best balance between these two concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct with just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wondering if someone already has data to compare these approaches in Vulkan. I am aware of Ubershaders however this is hardly an Ubershader (see below). The question concerns the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookup and texture color transform matrix for the alpha versus RGBA versus no texture case. I am assuming the 1x1 sampler is cached and thus is trivial in complexity.&#xD;&#xA;&#xD;&#xA;With multiple shaders the program switches are likely to be in the order of 100's or even 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally RGBA images, typically just using the vertex alpha value and all currently using orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Would a 1x1 NOP texture with a single layout and a single program the most efficient approach? or for ultimate performance should I continue to switch programs and layouts to keep the smallest vertex buffer size and least fragment shader operations? I couldn't find any data to drive this decision. Does someone have benchmarks for something similar to this? i.e. shader program switch overhead vs redundant shader ops and vertex buffer elements. Code maintenance and code commonality are also factors that are slightly more opinionated but will influence my decision.&#xD;&#xA;&#xD;&#xA;For the shared model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 0) uniform UBO&#xD;&#xA;	{&#xD;&#xA;    	mat4 modelViewProjection;&#xD;&#xA;    	mat4 texColorTransform;&#xD;&#xA;	} ubo;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	vec4 texColor = texture(tex, vtexcoord);&#xD;&#xA;    	vec4 transformedColor = texColor * ubo.texColorTransform;&#xD;&#xA;    	outColor = vcolor * transformedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;        mat4 texColorTransform;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="22201" PostHistoryTypeId="5" PostId="8319" RevisionGUID="3b7c7643-0f2c-4817-9d64-11de63ba44a5" CreationDate="2018-11-28T23:27:37.507" UserId="9763" Comment="added 722 characters in body" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. In the GL code that I am porting, it frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets` when changing shader programs.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to using a single shader program and single pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler and uniforms for transforming the output from texture lookups. When I want to draw flat colored objects, I would presumably set the color in the vertex and bind a 2x2 white sampler and when I want to render images I bind a proper image sampler. Note: I also use a matrix to transform textureColor as this allows me to configure the uniform for single channel alpha textures (`texture(tex, vtexcoord).r`) vs 4 channel RGBA textures (`texture(tex, vtexcoord).rgba`). For text rendering where the sampler has one channel, the color transform matrix can be set to just accumulate the red color channel into the resulting color vector. Color layout is bound with `VK_FORMAT_R8G8B8A8_UNORM` to only consume 4 bytes in the vertex (I don't need to support HDR). I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout only performing uniform updates and this common albeit slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines, and two of three sets of shaders and two vertex formats. i.e. where is the best balance between these two concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct with just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wondering if someone already has data to compare these approaches in Vulkan. I am aware of Ubershaders however this is hardly an Ubershader (see below). The question concerns the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookup and texture color transform matrix for the alpha versus RGBA versus no texture case. I am assuming the 1x1 sampler is cached and thus is trivial in complexity.&#xD;&#xA;&#xD;&#xA;With multiple shaders the program switches are likely to be in the order of 100's or even 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally RGBA images, typically just using the vertex alpha value and all currently using orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Would a 1x1 NOP texture with a single layout and a single program the most efficient approach? or for ultimate performance should I continue to switch programs and layouts to keep the smallest vertex buffer size and least fragment shader operations? I couldn't find any data to drive this decision. Does someone have benchmarks for something similar to this? i.e. shader program switch overhead vs redundant shader ops and vertex buffer elements. Code maintenance and code commonality are also factors that are slightly more opinionated but will influence my decision.&#xD;&#xA;&#xD;&#xA;For the shared model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 0) uniform UBO&#xD;&#xA;	{&#xD;&#xA;    	mat4 modelViewProjection;&#xD;&#xA;    	mat4 texColorTransform;&#xD;&#xA;	} ubo;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	vec4 texColor = texture(tex, vtexcoord);&#xD;&#xA;    	vec4 transformedColor = texColor * ubo.texColorTransform;&#xD;&#xA;    	outColor = vcolor * transformedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;        mat4 texColorTransform;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: as pointed out in the comments, swizzle masks can be used to translate the color channels versus the `texColorTransform` uniform 4x4 matrix. The use of a matrix allows rotation and affine transforms on colors such as translation and scaling (hue, brightness, contrast). It can be omitted if swizzle-masks are sufficient.&#xD;&#xA;&#xD;&#xA;`GL_TEXTURE_SWIZZLE_RGBA` in OpenGL:&#xD;&#xA;&#xD;&#xA;    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,&#xD;&#xA;        (GLint[]) { GL_RED, GL_RED, GL_RED, GL_RED } );&#xD;&#xA;&#xD;&#xA;or `VKImageView.components` in Vulkan:&#xD;&#xA;&#xD;&#xA;    VkImageView iv;&#xD;&#xA;    iv.components = {&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22202" PostHistoryTypeId="5" PostId="8319" RevisionGUID="02269e40-296c-412b-9276-2e56872b4af7" CreationDate="2018-11-28T23:50:52.580" UserId="9763" Comment="Fix reference to VKImageViewCreateInfo" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. In the GL code that I am porting, it frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets` when changing shader programs.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to using a single shader program and single pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler and uniforms for transforming the output from texture lookups. When I want to draw flat colored objects, I would presumably set the color in the vertex and bind a 2x2 white sampler and when I want to render images I bind a proper image sampler. Note: I also use a matrix to transform textureColor as this allows me to configure the uniform for single channel alpha textures (`texture(tex, vtexcoord).r`) vs 4 channel RGBA textures (`texture(tex, vtexcoord).rgba`). For text rendering where the sampler has one channel, the color transform matrix can be set to just accumulate the red color channel into the resulting color vector. Color layout is bound with `VK_FORMAT_R8G8B8A8_UNORM` to only consume 4 bytes in the vertex (I don't need to support HDR). I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout only performing uniform updates and this common albeit slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines, and two of three sets of shaders and two vertex formats. i.e. where is the best balance between these two concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct with just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wondering if someone already has data to compare these approaches in Vulkan. I am aware of Ubershaders however this is hardly an Ubershader (see below). The question concerns the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookup and texture color transform matrix for the alpha versus RGBA versus no texture case. I am assuming the 1x1 sampler is cached and thus is trivial in complexity.&#xD;&#xA;&#xD;&#xA;With multiple shaders the program switches are likely to be in the order of 100's or even 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally RGBA images, typically just using the vertex alpha value and all currently using orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Would a 1x1 NOP texture with a single layout and a single program the most efficient approach? or for ultimate performance should I continue to switch programs and layouts to keep the smallest vertex buffer size and least fragment shader operations? I couldn't find any data to drive this decision. Does someone have benchmarks for something similar to this? i.e. shader program switch overhead vs redundant shader ops and vertex buffer elements. Code maintenance and code commonality are also factors that are slightly more opinionated but will influence my decision.&#xD;&#xA;&#xD;&#xA;For the shared model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 0) uniform UBO&#xD;&#xA;	{&#xD;&#xA;    	mat4 modelViewProjection;&#xD;&#xA;    	mat4 texColorTransform;&#xD;&#xA;	} ubo;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	vec4 texColor = texture(tex, vtexcoord);&#xD;&#xA;    	vec4 transformedColor = texColor * ubo.texColorTransform;&#xD;&#xA;    	outColor = vcolor * transformedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;        mat4 texColorTransform;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: as pointed out in the comments, swizzle masks can be used to translate the color channels versus the `texColorTransform` uniform 4x4 matrix. The use of a matrix allows rotation and affine transforms on colors such as translation and scaling (hue, brightness, contrast). It can be omitted if swizzle-masks are sufficient.&#xD;&#xA;&#xD;&#xA;To broadcast the first color channel to all elements in OpenGL:&#xD;&#xA;&#xD;&#xA;    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,&#xD;&#xA;        (GLint[]) { GL_RED, GL_RED, GL_RED, GL_RED } );&#xD;&#xA;&#xD;&#xA;and for Vulkan, use the `VkImageViewCreateInfo` `components` field:&#xD;&#xA;&#xD;&#xA;    VkImageViewCreateInfo imageViewInfo;&#xD;&#xA;    imageViewInfo.components = {&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22203" PostHistoryTypeId="5" PostId="8319" RevisionGUID="5252f622-62bf-444b-9b68-6ec9fd1ee4a1" CreationDate="2018-11-29T00:07:02.190" UserId="9763" Comment="Improve question grammar and remove some redundancy" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. The GL code that I am porting, it frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and later bound with `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets`, thus changing shader programs equates program switches with graphic pipeline reconfiguration.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to a single shader program and hence a single graphics pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler. When I want to draw flat colored objects, the code would set the color in the vertex and bind a 1x1 white sampler and when I want to render images the code can bind a full image. I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout and only performing uniform updates and have a slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines, and two of three sets of shaders and vertex formats. i.e. where is the best balance between these concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct and just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wonder if someone already has data to compare these approaches. I am aware of Ubershaders however this is hardly an Ubershader (see below). The question concerns the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookup and texture color versus switching to a shader with no texture lookups.&#xD;&#xA;&#xD;&#xA;With multiple shaders the program switches are likely to be in the order of 100's or even 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally RGBA images, typically just using the vertex alpha value and all currently using orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Would a 1x1 NOP texture with a single layout and a single program be the most efficient approach? or for ultimate performance should I continue to switch programs and layouts to keep the smallest vertex buffer size and least fragment shader operations? I couldn't find any data to drive this decision. Does someone have benchmarks for something similar to this? i.e. shader program switch overhead vs redundant shader ops and vertex buffer elements. Code maintenance and code commonality are also factors that are slightly more opinionated but will influence my decision.&#xD;&#xA;&#xD;&#xA;For the shared program model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 0) uniform UBO&#xD;&#xA;	{&#xD;&#xA;    	mat4 modelViewProjection;&#xD;&#xA;    	mat4 texColorTransform;&#xD;&#xA;	} ubo;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	vec4 texColor = texture(tex, vtexcoord);&#xD;&#xA;    	vec4 transformedColor = texColor * ubo.texColorTransform;&#xD;&#xA;    	outColor = vcolor * transformedColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;        mat4 texColorTransform; /* alternatively can use swizzle masks */&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: as pointed out in the comments, swizzle masks can be used to translate the color channels versus the `texColorTransform` uniform 4x4 matrix. The color transform matrix allows rotation and affine transforms such as translation and scaling (hue, brightness, contrast). It can be omitted if swizzle-masks are sufficient.&#xD;&#xA;&#xD;&#xA;To broadcast the first color channel to all elements in OpenGL:&#xD;&#xA;&#xD;&#xA;    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,&#xD;&#xA;        (GLint[]) { GL_RED, GL_RED, GL_RED, GL_RED } );&#xD;&#xA;&#xD;&#xA;and for Vulkan, use the `VkImageViewCreateInfo` `components` field:&#xD;&#xA;&#xD;&#xA;    VkImageViewCreateInfo imageViewInfo;&#xD;&#xA;    imageViewInfo.components = {&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22204" PostHistoryTypeId="5" PostId="8319" RevisionGUID="31f644cb-a230-4ed8-a5bb-356d39c7d385" CreationDate="2018-11-29T00:24:16.407" UserId="9763" Comment="Remove colorTransform matrix as it is unnecessary with swizzle masks" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. The GL code that I am porting, it frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and later bound with `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets`, thus changing shader programs equates program switches with graphic pipeline reconfiguration.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to a single shader program and hence a single graphics pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler. When I want to draw flat colored objects, the code would set the color in the vertex and bind a 1x1 white sampler and when I want to render images the code can bind a full image. I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout and only performing uniform updates and have a slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines, and two of three sets of shaders and vertex formats. i.e. where is the best balance between these concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct and just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wonder if someone already has data to compare these approaches. I am aware of Ubershaders however this is hardly an Ubershader (see below). The question concerns the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookup and texture color versus switching to a shader with no texture lookups.&#xD;&#xA;&#xD;&#xA;With multiple shaders the program switches are likely to be in the order of 100's or even 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally RGBA images, typically just using the vertex alpha value and all currently using orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Would a 1x1 NOP texture with a single layout and a single program be the most efficient approach? or for ultimate performance should I continue to switch programs and layouts to keep the smallest vertex buffer size and least fragment shader operations? I couldn't find any data to drive this decision. Does someone have benchmarks for something similar to this? i.e. shader program switch overhead vs redundant shader ops and vertex buffer elements. Code maintenance and code commonality are also factors that are slightly more opinionated but will influence my decision.&#xD;&#xA;&#xD;&#xA;For the shared program model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	outColor = vcolor * texture(tex, vtexcoord);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: as pointed out in the comments, swizzle masks in `VKImageInfo` can be used to translate the color channels instead of having shader programs tied to the number of image channels.&#xD;&#xA;&#xD;&#xA;To broadcast the first color channel to all elements in OpenGL:&#xD;&#xA;&#xD;&#xA;    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,&#xD;&#xA;        (GLint[]) { GL_RED, GL_RED, GL_RED, GL_RED } );&#xD;&#xA;&#xD;&#xA;and for Vulkan, use the `VkImageViewCreateInfo` `components` field:&#xD;&#xA;&#xD;&#xA;    VkImageViewCreateInfo imageViewInfo;&#xD;&#xA;    imageViewInfo.components = {&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22206" PostHistoryTypeId="5" PostId="8319" RevisionGUID="ef37fa2d-a511-40f5-a991-4e9041f11290" CreationDate="2018-11-29T04:03:40.333" UserId="9763" Comment="Trimmed som redundant text from the question." Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. The GL code that I am porting frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and later bound with `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets`, thus changing shader programs equates program switches with graphic pipeline reconfiguration.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to a single shader program and hence a single graphics pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler. When I want to draw flat colored objects, the code would set the color in the vertex and bind a 1x1 white sampler and when I want to render images the code can bind a full image. I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout and only performing uniform updates and have a slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines and two of three sets of shaders and different vertex formats. i.e. where is the best balance between these concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct and just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wonder if someone already has data to compare these approaches. I am aware of Ubershaders however this is hardly an Ubershader (see below) rather concerns any data on the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookups and texture color versus switching to a shader with no texture lookups.&#xD;&#xA;&#xD;&#xA;With multiple shaders, the required program switches are likely to be in the order of 100's or possibly 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally, RGBA images, typically just using the vertex alpha value and all currently using an orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Ideally, I would like data on pipeline/program switch cost versus descriptor set switch cost.&#xD;&#xA;&#xD;&#xA;For the shared program model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	outColor = vcolor * texture(tex, vtexcoord);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: as pointed out in the comments, swizzle masks in `VKImageInfo` can be used to translate the color channels instead of having shader programs tied to the number of image channels.&#xD;&#xA;&#xD;&#xA;To broadcast the first color channel to all elements in OpenGL:&#xD;&#xA;&#xD;&#xA;    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,&#xD;&#xA;        (GLint[]) { GL_RED, GL_RED, GL_RED, GL_RED } );&#xD;&#xA;&#xD;&#xA;and for Vulkan, use the `VkImageViewCreateInfo` `components` field:&#xD;&#xA;&#xD;&#xA;    VkImageViewCreateInfo imageViewInfo;&#xD;&#xA;    imageViewInfo.components = {&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22211" PostHistoryTypeId="50" PostId="7997" RevisionGUID="1051df7c-6a02-4326-b802-62ca5b306dbf" CreationDate="2018-11-29T09:02:40.493" UserId="-1" />
  <row Id="22212" PostHistoryTypeId="5" PostId="8322" RevisionGUID="728291c3-37a4-49fa-b18a-13f404b0daee" CreationDate="2018-11-29T14:17:48.923" UserId="9755" Comment="added 1737 characters in body" Text="**About screens:**&#xD;&#xA;&#xD;&#xA;Short answer: yes, it SHOULD, it would be nice. But the technology currently used does not make that possible.&#xD;&#xA;&#xD;&#xA;The long answer: it's complicated. First, the signal that your computer sends to the screen is an electric signal. To make it easy to understand, take a look at this [post about the old VGA connector][1].&#xD;&#xA;&#xD;&#xA;The signal still contains R G and B channels, that's what lights your pixels in a given color. So to try to answer your question: the conversion from RGB electric signal to light (meaning radiance) depends on the screen, not on your PC. Different screens and brands behave differently, that's why they don't all look the same. The technology used for the pixels also matters: LED, LCD, cathodic, OLED, plasma... all behave in different ways.&#xD;&#xA;&#xD;&#xA;The signal coming from your computer tells the screen the color and the intensity of each pixel. The intensity is transmitted using a [pulse][2] (the leds blink fast enough so the human eye can't see it and the % of time it's on determines how bright it looks... to human eye). &#xD;&#xA;&#xD;&#xA;Even if that was not the case, and the pixels were analogic, you would still send an electric signal: some ampères at a given voltage, in other words some watts. And that's why it's all about radiance: it's a [radiometric measure][3]. &#xD;&#xA;&#xD;&#xA;In simple words, your computer sends current to pixels. The way the current is transformed into light (meaning luminance) is related to the pixels technology, quality, age, heat: there are too many factors that are not under the screen's control. &#xD;&#xA;&#xD;&#xA;**Luminance vs Radiance:**&#xD;&#xA;&#xD;&#xA;(following your comment)&#xD;&#xA;&#xD;&#xA;The difference is that when you speak about luminance, you need to take into consideration the spectrum of the light. RGB is not a good discretisation of the full spectrum, it's just 3 channels for the visible light and 0 for non-visible. When you speak about radiance, you're working with watts (energy): as shown f.ex. on this [page][4] &quot;short wavelenghts carry more energy&quot;. In other words, if you wanted to convert luminance to radiance you would need to know the light spectrum (a slope) and convert it into watts (a quantity - energy has no color, so to speak). But it is not feasible at the time of writing to render light sources that have a spectrum, all you can get is RGB... also because RGB is what screens are able to display.&#xD;&#xA;&#xD;&#xA;The screens are calibrated so that (1,1,1) appears white, (x,x,x) appears as a gray shade and so on. This somehow compensates the fact that short wavelengths *have* more energy.&#xD;&#xA;&#xD;&#xA;You probably understood: it's quite a mess. You can only get as near to physically based as the technology allows you (as pointed by Wyck in his comment). To do so, I can suggest you to read ***&quot;Physically based rendering - From theory to implementation&quot; by M. Pharr and G. Humphreys*** (The second edition ISBN: 978-0-12-375079-2 , I think there's also a third edition). It is unfortunately not feasible to go through all the aspects of the problem in an answer on StackExchange (moreover because I won't rewrite the 1000 pages with my words, sorry).&#xD;&#xA;&#xD;&#xA;Last, but not least, in your comment you spoke about &quot;perceived light&quot;: you probably also want to read something about [tonemapping][5] (a.k.a. the methods/algorithms to mimic the human eye perception of luminance). It really depends if you're trying to display lumiance or human perceived brightness.&#xD;&#xA;&#xD;&#xA;I hope this helps you seeing how deep the rabbit hole is... up to you to decide how deed you want to go into it!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://electronics.stackexchange.com/questions/93078/soldering-a-vga-cable-number-of-wires-doesnt-match&#xD;&#xA;  [2]: https://www.researchgate.net/figure/Two-measures-of-electrical-power-signals-for-LED-control-with-D-Type-flip-flop-register_fig6_224222964&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiance&#xD;&#xA;  [4]: https://socratic.org/questions/5348556b02bf347bedff8fed&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Tone_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22213" PostHistoryTypeId="5" PostId="8322" RevisionGUID="11cf12a9-64e7-4ebd-98bf-1de2bdc2c2a0" CreationDate="2018-11-29T14:22:53.010" UserId="9755" Comment="added 1737 characters in body" Text="**About screens:**&#xD;&#xA;&#xD;&#xA;Short answer: yes, it SHOULD, it would be nice. But the technology currently used does not make that possible.&#xD;&#xA;&#xD;&#xA;The long answer: it's complicated. First, the signal that your computer sends to the screen is an electric signal. To make it easy to understand, take a look at this [post about the old VGA connector][1].&#xD;&#xA;&#xD;&#xA;The signal still contains R G and B channels, that's what lights your pixels in a given color. So to try to answer your question: the conversion from RGB electric signal to light (meaning radiance) depends on the screen, not on your PC. Different screens and brands behave differently, that's why they don't all look the same. The technology used for the pixels also matters: LED, LCD, cathodic, OLED, plasma... all behave in different ways.&#xD;&#xA;&#xD;&#xA;The signal coming from your computer tells the screen the color and the intensity of each pixel. The intensity is transmitted using a [pulse][2] (the leds blink fast enough so the human eye can't see it and the % of time it's on determines how bright it looks... to human eye). &#xD;&#xA;&#xD;&#xA;Even if that was not the case, and the pixels were analogic, you would still send an electric signal: some ampères at a given voltage, in other words some watts. And that's why it's all about radiance: it's a [radiometric measure][3]. &#xD;&#xA;&#xD;&#xA;In simple words, your computer sends current to pixels. The way the current is transformed into light (meaning luminance) is related to the pixels technology, quality, age, heat: there are too many factors that are not under the screen's control. &#xD;&#xA;&#xD;&#xA;**Luminance vs Radiance:**&#xD;&#xA;&#xD;&#xA;(following your comment)&#xD;&#xA;&#xD;&#xA;The difference is that when you speak about luminance, you need to take into consideration the spectrum of the light. RGB is not a good discretisation of the full spectrum, it's just 3 channels for the visible light and 0 for non-visible. When you speak about radiance, you're working with watts (energy): as shown f.ex. on this [page][4] &quot;short wavelenghts carry more energy&quot;. In other words, if you wanted to convert luminance to radiance you would need to know the light spectrum (a slope) and convert it into watts (a quantity - energy has no color, so to speak). But it is not feasible at the time of writing to render light sources that have a spectrum, all you can get is RGB... also because RGB is what screens are able to display.&#xD;&#xA;&#xD;&#xA;The screens are calibrated so that (1,1,1) appears white, (x,x,x) appears as a gray shade and so on. This somehow compensates the fact that short wavelengths *have* more energy.&#xD;&#xA;&#xD;&#xA;You probably understood: it's quite a mess. You can only get as near to physically based as the technology allows you (as pointed by Wyck in his comment). To do so, I can suggest you to read ***&quot;Physically based rendering - From theory to implementation&quot; by M. Pharr and G. Humphreys*** (The second edition ISBN: 978-0-12-375079-2 , I think there's also a third edition). It is unfortunately not feasible to go through all the aspects of the problem in an answer on StackExchange (moreover because I won't rewrite the 1000 pages with my own words, sorry). The book is definitely worth reading.&#xD;&#xA;&#xD;&#xA;Last, but not least, in your comment you spoke about &quot;perceived light&quot;: you probably also want to read something about [tonemapping][5] (a.k.a. the methods/algorithms to mimic the human eye perception of luminance). It really depends if you're trying to display lumiance or human perceived brightness.&#xD;&#xA;&#xD;&#xA;I hope this helps you seeing how deep the rabbit hole is... up to you to decide how deep you want to go into it!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://electronics.stackexchange.com/questions/93078/soldering-a-vga-cable-number-of-wires-doesnt-match&#xD;&#xA;  [2]: https://www.researchgate.net/figure/Two-measures-of-electrical-power-signals-for-LED-control-with-D-Type-flip-flop-register_fig6_224222964&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Radiance&#xD;&#xA;  [4]: https://socratic.org/questions/5348556b02bf347bedff8fed&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Tone_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22217" PostHistoryTypeId="5" PostId="8318" RevisionGUID="ac9f984a-b7c7-477f-b74f-3fbc513db3d5" CreationDate="2018-11-30T14:30:29.783" UserId="9762" Comment="Added link and usage info" Text="You might want to try the VK_LAYER_LUNARG_monitor layer from the LunarG Vulkan SDK.&#xD;&#xA;&#xD;&#xA;Download the SDK from the LunarXchange [site][1].&#xD;&#xA;&#xD;&#xA;After SDK installation, you can activate the layer by setting this environment variable:&#xD;&#xA;&#xD;&#xA;    VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_monitor&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The monitor layer displays the FPS value in the application window's title bar.&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan.lunarg.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="22218" PostHistoryTypeId="2" PostId="8328" RevisionGUID="be0918fd-c0e5-4a84-ba83-3f250b0ae1a9" CreationDate="2018-11-30T20:24:47.210" UserId="9778" Text="I'm new to computer graphics so I just wanted to find out for sure how GLSL code gets loaded and compiled. &#xD;&#xA;&#xD;&#xA;Does the g++ compiler do it? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22219" PostHistoryTypeId="1" PostId="8328" RevisionGUID="be0918fd-c0e5-4a84-ba83-3f250b0ae1a9" CreationDate="2018-11-30T20:24:47.210" UserId="9778" Text="How does GLSL code get “loaded” and “compiled”?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22220" PostHistoryTypeId="3" PostId="8328" RevisionGUID="be0918fd-c0e5-4a84-ba83-3f250b0ae1a9" CreationDate="2018-11-30T20:24:47.210" UserId="9778" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22221" PostHistoryTypeId="2" PostId="8329" RevisionGUID="09fcfaae-6fd6-44c7-8223-d2b920e5e06f" CreationDate="2018-11-30T22:56:30.067" UserId="48" Text="No, g++/gcc are not involved.&#xD;&#xA;&#xD;&#xA;In OpenGL (prior to Vulkan), GLSL code is submitted to the driver as source code strings via a [`glShaderSource`](http://docs.gl/gl4/glShaderSource) call. The driver is fully responsible for compilation, i.e. the driver must provide a built-in GLSL compiler for that GPU architecture. This would typically happen on startup of an app, or during level loading for a game.&#xD;&#xA;&#xD;&#xA;With Vulkan, [SPIR-V](https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation) was introduced, which is a device-independent bytecode for shaders (vaguely based on [LLVM IR](https://en.wikipedia.org/wiki/LLVM#Intermediate_representation)). Now, GLSL code can be pre-compiled to SPIR-V offline using the [shaderc](https://github.com/google/shaderc) toolchain. The developers would do this ahead of time and ship the SPIR-V bytecode with their app. Then at runtime the SPIR-V gets submitted to the Vulkan driver and compiled the rest of the way to GPU machine code.&#xD;&#xA;&#xD;&#xA;It's also possible to compile other languages to SPIR-V; for instance, Microsoft's [dxc](https://github.com/Microsoft/DirectXShaderCompiler) compiler for HLSL can optionally output SPIR-V, so you can use this to write Vulkan shaders in HLSL. Also, SPIR-V support has been backported to OpenGL 4.6, so you can now also [load precompiled SPIR-V shaders in OpenGL](https://www.khronos.org/opengl/wiki/SPIR-V)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22239" PostHistoryTypeId="2" PostId="8333" RevisionGUID="483ae9be-1de0-4e33-b7ab-d17f6a0671b2" CreationDate="2018-12-01T20:32:05.020" UserId="9778" Text="I'm new to computer graphics and just wanted a solid understanding of why?&#xD;&#xA;&#xD;&#xA;Why is it so important that polygons you push through the pipeline be &quot;**simple**&quot; and &quot;**convex**&quot;? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22240" PostHistoryTypeId="1" PostId="8333" RevisionGUID="483ae9be-1de0-4e33-b7ab-d17f6a0671b2" CreationDate="2018-12-01T20:32:05.020" UserId="9778" Text="Why do polygons have to be &quot;simple&quot; and &quot;convex&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22241" PostHistoryTypeId="3" PostId="8333" RevisionGUID="483ae9be-1de0-4e33-b7ab-d17f6a0671b2" CreationDate="2018-12-01T20:32:05.020" UserId="9778" Text="|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22246" PostHistoryTypeId="2" PostId="8335" RevisionGUID="370f5a63-290a-477e-ba87-0e74d886f0bd" CreationDate="2018-12-02T02:26:05.830" UserId="1582" Text="It's difficult to parse, but here's my best understanding.&#xD;&#xA;&#xD;&#xA;In this case the goal is determine number of $N_i$ out of $n$ samples to distribute to each strata with probability given by the discrete pdf in $\{p_0, ..., p_n\}$&#xD;&#xA;&#xD;&#xA;The summation of $P$ += $p_i$ is computing the CDF for $i$.&#xD;&#xA;&#xD;&#xA;I believe &quot;sample the ith term $N_i$ times&quot; means to take a jittered sample within that strata using new random variables.&#xD;&#xA;&#xD;&#xA;Let's take a small example where we have the pdf with 4 elements.&#xD;&#xA;$$&#xD;&#xA;PDF = \{0.2, 0.1, 0.6, 0.1\}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And it's corresponding cdf, each element corresponds to $P$ in the ith iteration in the pseudo code.&#xD;&#xA;$$&#xD;&#xA;CDF = \{0.2, 0.3, 0.9, 1.0\}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now given $\left \lfloor{P*n + u}\right \rfloor$ we can illustrate for a few example cases.&#xD;&#xA;&#xD;&#xA;With $u = 0$&#xD;&#xA;$$&#xD;&#xA;\left \lfloor{P*n + u}\right \rfloor = \{0, 1, 3, 4\}&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;N_i = {0, 1, 2, 1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;With $u = 0.5$&#xD;&#xA;$$&#xD;&#xA;\left \lfloor{P*n + u}\right \rfloor = \{1, 1, 4, 4\}&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;N_i = {1, 0, 3, 0}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;With $u = 0.99$&#xD;&#xA;$$&#xD;&#xA;\left \lfloor{P*n + u}\right \rfloor = \{1, 2, 4, 4\}&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;N_i = {1, 1, 2, 0}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Notice how for example $N_3$ corresponds to a higher number of samples. When we now sample the 3rd element $N_3$ times we are weighting that strata in proportion to its pdf.&#xD;&#xA;&#xD;&#xA;Also, I don't see any reason that the sample count has to be the same $n$ as the # of discrete elements in the pdf." ContentLicense="CC BY-SA 4.0" />
  <row Id="22247" PostHistoryTypeId="2" PostId="8336" RevisionGUID="6481d13c-17c7-4152-bace-3d9ad9943255" CreationDate="2018-12-02T02:40:51.407" UserId="1582" Text="This is a really hardware dependent question. But in general the best way to think about this bottlenecks.&#xD;&#xA;&#xD;&#xA;You mentioned:&#xD;&#xA;&#xD;&#xA;&gt; one set of shaders, one **slightly** larger vertex struct and just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;The slightly larger vertex struct doesn't seem like it will be the more likely bottleneck compared to:&#xD;&#xA;&#xD;&#xA;&gt;With multiple shaders, the required program switches are likely to be in the order of 100's or possibly 1000's &#xD;&#xA;&#xD;&#xA;On modern desktop/console hardware each graphics pipe might have single digit # of active contexts. Switching the state too frequently is sometimes to referred to as a context roll stall. &#xD;&#xA;&#xD;&#xA;In this case whether you hit that stall case is also dependent on how fast your shader and blend operations complete to make the context available. Given that you're going to do a lot of alpha blending, you might be bound by blending operations.&#xD;&#xA;&#xD;&#xA;By the way modern gpus are much better at dynamic branching, and skipping over fetches is possible with a shader uniform is possible so you don't need to pay the additional memory reads. That said, a 1x1 dummy texture is going to be texture cache anyway so again probably doesn't matter.&#xD;&#xA;&#xD;&#xA;I'd say try using a single shader first before you introduce new shader permutations. And in general, do the easiest implementation first, measure on your target hardware, then optimize :) " ContentLicense="CC BY-SA 4.0" />
  <row Id="22248" PostHistoryTypeId="2" PostId="8337" RevisionGUID="35b51c71-cb35-4e4e-8797-fe04eac9b6f8" CreationDate="2018-12-02T03:33:50.673" UserId="1582" Text="&gt;1, 1, 1, the output value is white. If this represents radiance than the output should be green, because when the signal radiance is the same, the pixel should be perceived as green. Am I correct?&#xD;&#xA;&#xD;&#xA;This is not correct. Your frame buffer most likely contains sRGB values. Of which 1,1,1 is used to represent white. Standard displays do not use spectral radiance values in the frame buffer. sRGB does not map directly or make any guarantees about the spectral power distribution (SPD) of the display. So &quot;G&quot; of 1 does not guarantee some sort of wavelength W⋅sr−1⋅m−2 centered on the 550nm. Part of the problem is that different type of displays have different SPDs that map to the same perceived color. &#xD;&#xA;&#xD;&#xA;[Evaluation of an organic light-emitting diode display for precise visual stimulation, Ito et. al]&#xD;&#xA;(https://jov.arvojournals.org/article.aspx?articleid=2121657)&#xD;&#xA;[![SPDs for different display types][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GD4E2.jpg&#xD;&#xA;&#xD;&#xA;Now if you want to physically accurate rendering, you could store all of your lighting values as Radiance with SPDs. As L.C. mentioned, Physically Based Rendering describes that this is done with piece-wise linear functions with like 16+ channels per color. However even if you can get this to be performant, good luck converting all your RGB data into SPDs (there's an infinite # of SPDs for a given RGB value).&#xD;&#xA;&#xD;&#xA;Instead what most renderers try to do is to treat the RGB as pseudo-radiance values for the purposes of lighting calculation. This isn't accurate, hence your lighting result changes if you are using Rec.709 or Rec.2020 primaries for instance (if you notice they have different values for mapping to luminance), but it's good enough for real time and even offline in most cases. At this point you can convert RGB Rec709 and Rec2020 values to a single scalar luminance using the Y values of it's primaries.&#xD;&#xA;&#xD;&#xA;The Y values of the RGB primaries for Rec709 are:&#xD;&#xA;&#xD;&#xA;        R       G       B&#xD;&#xA;    Y	0.2126	0.7152	0.0722&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/SRGB&#xD;&#xA;&#xD;&#xA;Thus Rec709 Linear has the following nits conversion:&#xD;&#xA;&#xD;&#xA;    nits = dot(linear709Rgb, float3(0.2126, 0.7152,0.0722));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Probably one of the results of doing our calculations in RGB is that G and B add at equal weights, so it's likely to get some color shifting. There was a presentation at SIGGRAPH 2015 from Weta digital that had some examples, but it doesn't seem like the slides are available. As far as I know they are the only ones using a spectral renderer." ContentLicense="CC BY-SA 4.0" />
  <row Id="22249" PostHistoryTypeId="2" PostId="8338" RevisionGUID="e168ed03-b6ca-4c1a-a47c-01b12ad7782b" CreationDate="2018-12-02T04:12:48.333" UserId="1582" Text="Compute queues in general don't necessarily mean you can now do 2x dispatches in parallel. A single queue that fully saturates the compute units will have better throughput. Multiple queues are useful if one queue consumes less resources (shared memory or registers), then secondary queues can then overlap on the same compute unit. &#xD;&#xA;&#xD;&#xA;For real-time rendering this is especially the case with things like shadow rendering that are very light on compute/shaders but heavy on fixed function hardware, thus freeing the GPU scheduler to run the secondary queue async.&#xD;&#xA;&#xD;&#xA;Also found this in the release notes. Don't know if it's the same issue, but could just be that CodeXL is not great. I would expect that it might have not have the best instrumentation for which dispatches are in flight.&#xD;&#xA;&#xD;&#xA;https://developer.amd.com/wordpress/media/2013/02/AMD_CodeXL_Release_Notes.pdf&#xD;&#xA;&gt;For an application that performs simultaneous asynchronous data transfer and kernel execution,&#xD;&#xA;the timeline shown in the Application Trace session view will not show these operations being&#xD;&#xA;overlapped. This is because the driver and hardware force these operations to be synchronous&#xD;&#xA;while profiling. (333981)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22250" PostHistoryTypeId="2" PostId="8339" RevisionGUID="7453c91f-71c4-4491-8a83-772adc3e3c9a" CreationDate="2018-12-02T04:19:34.877" UserId="9778" Text="I'm new to this forum and topic but wanted to figure out specifically how are normals assigned to vertices in **flat shading, gouraud shading, and phong shading**? &#xD;&#xA;&#xD;&#xA;Is there a difference between any? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22251" PostHistoryTypeId="1" PostId="8339" RevisionGUID="7453c91f-71c4-4491-8a83-772adc3e3c9a" CreationDate="2018-12-02T04:19:34.877" UserId="9778" Text="How are normals assigned to vertices in different types of shading?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22252" PostHistoryTypeId="3" PostId="8339" RevisionGUID="7453c91f-71c4-4491-8a83-772adc3e3c9a" CreationDate="2018-12-02T04:19:34.877" UserId="9778" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22253" PostHistoryTypeId="2" PostId="8340" RevisionGUID="a71491a7-e3e6-48d7-b3d5-cd014351b28b" CreationDate="2018-12-02T04:22:03.387" UserId="1582" Text="Deferred decals are a common way to achieve this without re-rendering the same geometry. It also allows you to change the appearance, i.e. add some gap or smooth out the details.&#xD;&#xA;&#xD;&#xA;The algorithm:&#xD;&#xA;&#xD;&#xA; 1. Draw a box around your height field, the size should be as tight as possible to avoid over draw. &#xD;&#xA; 2. sample the depth buffer to get the world-space position of the current pixel (the height field / other geo)&#xD;&#xA; 3. Project your box down in world space&#xD;&#xA; 4. Use the projected box coordinate to sample from your overlay texture.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22254" PostHistoryTypeId="2" PostId="8341" RevisionGUID="235138e4-5f5d-41c7-ae3d-10ed7542a6f0" CreationDate="2018-12-02T04:36:05.500" UserId="1582" Text="The code does seem a bit ugly since it doesn't assign pdf and instead returns 0.&#xD;&#xA;&#xD;&#xA;By returning 0 it's basically saying the same thing as pdf = 0 because `f.IsBlack()` returns true.&#xD;&#xA;&#xD;&#xA;This is acceptable, it's basically saying the BSDF doesn't allow light go through at the given $w_o$" ContentLicense="CC BY-SA 4.0" />
  <row Id="22255" PostHistoryTypeId="2" PostId="8342" RevisionGUID="3deaa2c8-80fc-4910-9cf9-4b4abd22570e" CreationDate="2018-12-02T04:55:26.397" UserId="1582" Text="A fragment shader executes for a 2D rasterized position. When you output the normalized position it's still being projected onto the 2D xy image plane onto a render target. The render target is 2D, so you can't use the fragment shader output to achieve this.&#xD;&#xA;&#xD;&#xA;You need to bind a 3D texture as a read/write texture in order to store values. &#xD;&#xA;&#xD;&#xA;The other thing is how you're expecting to voxelize the geometry, are you trying to voxelize the surfaces? If so you can use a pixel shader but you need to render all faces (disable back face culling)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22256" PostHistoryTypeId="2" PostId="8343" RevisionGUID="730423e1-1368-4ad0-99e6-4d46ff473238" CreationDate="2018-12-02T06:32:29.193" UserId="9778" Text="In hidden surface removal, how does the Z-buffer algorithm work vs. painter's algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22257" PostHistoryTypeId="1" PostId="8343" RevisionGUID="730423e1-1368-4ad0-99e6-4d46ff473238" CreationDate="2018-12-02T06:32:29.193" UserId="9778" Text="Z-Buffer algorithm vs Painter's algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22258" PostHistoryTypeId="3" PostId="8343" RevisionGUID="730423e1-1368-4ad0-99e6-4d46ff473238" CreationDate="2018-12-02T06:32:29.193" UserId="9778" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22259" PostHistoryTypeId="2" PostId="8344" RevisionGUID="539ecbd2-2877-457f-bd49-eb3a169701f5" CreationDate="2018-12-02T07:45:10.007" UserId="1582" Text="In short painter's algorithm can't deal with intersecting geometry.&#xD;&#xA;&#xD;&#xA;Suppose that you draw a plane angled away from the camera, and a plane angled towards the camera. The planes intersect in an 'X' shape.&#xD;&#xA;&#xD;&#xA;    Camera ------&gt; X&#xD;&#xA;&#xD;&#xA;With painter's algorithm no such ordering exists that will render the shape exactly. You would only see whichever plane you decided to draw last.&#xD;&#xA;&#xD;&#xA;The Z-Buffer or Depth-Buffer stores the nearest depth per each pixel relative from the camera. If another triangle is rasterized and has a depth less than the current depth buffer value it is accepted, if it's depth is greater, it is rejected. This is called a depth test." ContentLicense="CC BY-SA 4.0" />
  <row Id="22260" PostHistoryTypeId="2" PostId="8345" RevisionGUID="ffb2a7cd-4655-4a57-8bcc-ec37a0905b4b" CreationDate="2018-12-02T07:59:55.460" UserId="1582" Text="Flat shading uses the same normal for each vertex of the triangle. In this case the normal is constant, and one color is evaluated for the triangle.&#xD;&#xA;&#xD;&#xA;For Gouraud and Phong shading normals are different per vertex and can represent a curved surface (even though the face is flat). &#xD;&#xA;&#xD;&#xA;However, for Gouraud shading is evaluated per vertex, and the resulting color is interpolated. For Phong, the normals are interpolated first and the shading is evaluated per pixel.&#xD;&#xA;&#xD;&#xA;Also note there's a bit of an overloaded term between the Phong Lighting/Reflection model and Phong Interpolation, Per-pixel shading which is what you're referring to here.&#xD;&#xA;&#xD;&#xA;Given these 3 shading types, the next logical step is actually normal maps shading. This is basically where the normal is provided per pixel, and shading is evaluated per pixel.&#xD;&#xA;&#xD;&#xA;And so you have the trend of doing more calculation at finer details / higher resolution.&#xD;&#xA;&#xD;&#xA;Here's a table!&#xD;&#xA;&#xD;&#xA;                     Normal         |   Lighting&#xD;&#xA;    Flat:            Per Triangle   |   Per Triangle&#xD;&#xA;    Gouraud:         Per Vertex     |   Per Vertex&#xD;&#xA;    Phong:           Per Vertex     |   Per Pixel&#xD;&#xA;    Normal Mapping:  Per Pixel      |   Per Pixel" ContentLicense="CC BY-SA 4.0" />
  <row Id="22269" PostHistoryTypeId="2" PostId="8348" RevisionGUID="a6a0ae5f-100b-4abc-b095-9a93488122e5" CreationDate="2018-12-03T00:14:48.707" UserId="9778" Text="Relatively new to this forum and topic and wanted to ask in detail, a mapping question.&#xD;&#xA;&#xD;&#xA;I know OpenGL likes the texel resolution of textures be some power of 2 in each direction because of **mipmapping**. (They say that this is not a totally stringent condition, but it is preferred)&#xD;&#xA;&#xD;&#xA;Can someone explain what is mipmapping and what is it for?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22270" PostHistoryTypeId="1" PostId="8348" RevisionGUID="a6a0ae5f-100b-4abc-b095-9a93488122e5" CreationDate="2018-12-03T00:14:48.707" UserId="9778" Text="What is mipmapping?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22271" PostHistoryTypeId="3" PostId="8348" RevisionGUID="a6a0ae5f-100b-4abc-b095-9a93488122e5" CreationDate="2018-12-03T00:14:48.707" UserId="9778" Text="|mapping|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22272" PostHistoryTypeId="2" PostId="8349" RevisionGUID="ea0d1501-e388-4272-80ba-8b22e1b35389" CreationDate="2018-12-03T03:27:59.867" UserId="9778" Text="Can someone please explain what are the 3 types of light reflection from surfaces in the Phong Lighting Model? &#xD;&#xA;&#xD;&#xA;Maybe possibly using a diagram to help me understand it better? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22273" PostHistoryTypeId="1" PostId="8349" RevisionGUID="ea0d1501-e388-4272-80ba-8b22e1b35389" CreationDate="2018-12-03T03:27:59.867" UserId="9778" Text="What are the 3 types of light reflection from surfaces in the Phong Lighting Model?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22274" PostHistoryTypeId="3" PostId="8349" RevisionGUID="ea0d1501-e388-4272-80ba-8b22e1b35389" CreationDate="2018-12-03T03:27:59.867" UserId="9778" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22275" PostHistoryTypeId="2" PostId="8350" RevisionGUID="ebc00366-8870-488c-891a-c9f9c28d0e68" CreationDate="2018-12-03T07:11:01.317" UserId="7008" Text="The three types you are referring to are specular, diffuse and ambient reflection.&#xD;&#xA;I find the [example image on wikipedia][1] to show the individual parts quite nicely:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;First the ambient light is showing. This is not really a reflection, but more of a way to make up for global illumination in a cheap way. You simply assume that a small portion of light is always reaching every point on your object, no matter where that object is or how its positioned. Even when standing on the ground, the parts that touch the ground are lighted here. Because the light is the same everywhere, you can't even tell if it is a 3D object or just a drawing.&#xD;&#xA;&#xD;&#xA;Next is the diffuse reflection. This is an approximation of light that enters your object, bounces around a bit and leaves the object again. Naturally, more light reaches surfaces that are angled &quot;towards&quot; the light, this is why in the image you can see shadows in the left pointing parts but increasingly more light on the right pointing parts. Due to the bouncing within the object, the exit direction of the light is somewhat random, therefore no concentrated highlights are created.&#xD;&#xA;&#xD;&#xA;Highlights you can see are the specular reflection in the third image. Specular reflection is that part of light, that reaches the object and immedeately bounces of it again. Thereby it keeps most of the light (from the same light source) directed into more or less the same direction, thus the highlights.&#xD;&#xA;&#xD;&#xA;The last part of the image is everything combined, giving you a nice and cheap approximation of real light.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://upload.wikimedia.org/wikipedia/commons/6/6b/Phong_components_version_4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CZEvi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22279" PostHistoryTypeId="2" PostId="8352" RevisionGUID="9f018c6a-1b05-4c0a-9e69-2c3fa1a6b705" CreationDate="2018-12-03T16:53:31.577" UserId="2654" Text="Polygon rasterization (the conversion of the analogy polygon data into a [raster image][1]) is a key operation in rasterization-based rendering. As such, performing this operation fast, and with predictable performance, is key to the performance of graphics rendering.&#xD;&#xA;&#xD;&#xA;It is possible to rasterize any arbitrary polygon. But rasterizing triangles is extremely simple to code and offers numerous efficiency improvements over general polygon rasterization.&#xD;&#xA;&#xD;&#xA;Triangle rasterization is done by something called &quot;scan conversion&quot;: you break the triangle up into a series of horizontal scan-lines (one pixel tall) of a length determined by the sides of the triangle. Building these scan-lines and getting their lengths is something you can do through basic integer math involving only additions and multiplications. Furthermore, each scan-line can be constructed *independently* of the others, so highly threaded hardware can be employed to perform this process efficiently.&#xD;&#xA;&#xD;&#xA;None of this is true for arbitrary polygons. Concave polygons in particular require much more complex math. A concave polygon can have multiple lines in the same horizontal row.&#xD;&#xA;&#xD;&#xA;Furthermore, interpolation of values across the surface of a triangle can be done by relatively simple math. For each scanline, you can compute a gradient that represents how much each value changes from one end of the line to the other. So given a starting value at one line, you can easily compute the interpolated position at any point on the scanline simply by multiplication and addition. If you're computing them in sequence, you don't even need the multiplication; successive addition is adequate.&#xD;&#xA;&#xD;&#xA;Interpolation of values across an arbitrary polygonal surface is much more complicated.&#xD;&#xA;&#xD;&#xA;Given all of these advantages, and the fact that you can use a series of triangles to build any arbitrary polygon, there's really no reason to rasterize any more complex shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Raster_graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="22280" PostHistoryTypeId="5" PostId="8348" RevisionGUID="0fef3a31-54d3-4f20-9fab-8ce9f9bdbd5d" CreationDate="2018-12-03T16:53:54.570" UserId="2654" Comment="deleted 91 characters in body" Text="I know OpenGL likes the texel resolution of textures be some power of 2 in each direction because of **mipmapping**. (They say that this is not a totally stringent condition, but it is preferred)&#xD;&#xA;&#xD;&#xA;Can someone explain what is mipmapping and what is it for?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22281" PostHistoryTypeId="5" PostId="8328" RevisionGUID="b3749b10-42ee-4afd-9165-288755271abd" CreationDate="2018-12-03T16:56:04.370" UserId="2654" Comment="deleted 32 characters in body" Text="I just wanted to find out for sure how GLSL code gets loaded and compiled. &#xD;&#xA;&#xD;&#xA;Does the g++ compiler do it? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22282" PostHistoryTypeId="2" PostId="8353" RevisionGUID="9fe96ab0-d216-40a7-828c-3e6dc8b92aa4" CreationDate="2018-12-03T17:52:54.367" UserId="9778" Text="How does the Modified Phong lighting model also known as the Blinn-Phong differ from the Phong Lighting Model? &#xD;&#xA;&#xD;&#xA;How can I distinguish the two?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22283" PostHistoryTypeId="1" PostId="8353" RevisionGUID="9fe96ab0-d216-40a7-828c-3e6dc8b92aa4" CreationDate="2018-12-03T17:52:54.367" UserId="9778" Text="How does the Modified Phong Lighting Model from the Phong Lighting Model?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22284" PostHistoryTypeId="3" PostId="8353" RevisionGUID="9fe96ab0-d216-40a7-828c-3e6dc8b92aa4" CreationDate="2018-12-03T17:52:54.367" UserId="9778" Text="|lighting|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22285" PostHistoryTypeId="2" PostId="8354" RevisionGUID="bb5880c0-9408-4d78-b0be-85afcb6dd244" CreationDate="2018-12-03T18:02:02.823" UserId="9789" Text="If I try to read the screen with `glreadpixels` and then draw the same thing again using `gldrawpixels` it works, BUT if and only if I use anything else to draw than `gldrawarrays` and `gldrawelements` (`gluSphere/gluCylinder` work just fine). I'm trying to draw an object to the screen and save the pixels in an array. &#xD;&#xA;&#xD;&#xA;I tried reading/writing to front/back buffers, reading after I swap buffers, all to no avail.&#xD;&#xA;&#xD;&#xA;here is the code that I use to draw the object: (please note that I do not use any kind of buffers outside of this scope).&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;     void CCssample5View::DrawCylinder(Model obj)&#xD;&#xA;        {&#xD;&#xA;    	GLuint VertexArrayID;&#xD;&#xA;    	glGenVertexArrays(1, &amp;VertexArrayID);&#xD;&#xA;    	glBindVertexArray(VertexArrayID);&#xD;&#xA;    &#xD;&#xA;    	Shader castingShader(&quot;casting.vs&quot;, &quot;casting.fs&quot;);&#xD;&#xA;    	Shader lightShader(&quot;light.vs&quot;, &quot;light.fs&quot;);&#xD;&#xA;    &#xD;&#xA;    	GLuint MatrixID = glGetUniformLocation(castingShader.ID, &quot;MVP&quot;);&#xD;&#xA;    	GLuint ViewMatrixID = glGetUniformLocation(castingShader.ID, &quot;V&quot;);&#xD;&#xA;    	GLuint ModelMatrixID = glGetUniformLocation(castingShader.ID, &quot;M&quot;);&#xD;&#xA;    &#xD;&#xA;    	GLuint textur = loadBMP_custom(&quot;flower.bmp&quot;);&#xD;&#xA;    	GLuint TextureID = glGetUniformLocation(castingShader.ID , &quot;myTextureSampler&quot;);&#xD;&#xA;   &#xD;&#xA;    &#xD;&#xA;    	indexVBO(obj.vertices, obj.uvs, obj.normals, obj.indices, obj.indexed_vertices, obj.indexed_uvs, obj.indexed_normals);&#xD;&#xA;    &#xD;&#xA;    	GLuint vertexbuffer;&#xD;&#xA;    	glGenBuffers(1, &amp;vertexbuffer);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, obj.indexed_vertices.size() * sizeof(glm::vec3), &amp;obj.indexed_vertices[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint uvbuffer;&#xD;&#xA;    	glGenBuffers(1, &amp;uvbuffer);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, obj.indexed_uvs.size() * sizeof(glm::vec2), &amp;obj.indexed_uvs[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint normalbuffer;&#xD;&#xA;    	glGenBuffers(1, &amp;normalbuffer);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, obj.indexed_normals.size() * sizeof(glm::vec3), &amp;obj.indexed_normals[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint elementbuffer;&#xD;&#xA;    	glGenBuffers(1, &amp;elementbuffer);&#xD;&#xA;    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);&#xD;&#xA;    	glBufferData(GL_ELEMENT_ARRAY_BUFFER, obj.indices.size() * sizeof(unsigned short), &amp;obj.indices[0], GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;   &#xD;&#xA;    &#xD;&#xA;    	castingShader.use();&#xD;&#xA;    &#xD;&#xA;    	GLuint LightID = glGetUniformLocation(castingShader.ID, &quot;LightPosition_worldspace&quot;);&#xD;&#xA;    	computeMatricesFromInputs();&#xD;&#xA;    	GLfloat gProjectionMatrix[16];&#xD;&#xA;    	glGetFloatv(GL_PROJECTION_MATRIX, gProjectionMatrix);&#xD;&#xA;    	glm::mat4 ProjectionMatrix = glm::make_mat4(gProjectionMatrix);// = glm::mat4(gProjectionMatrix);	&#xD;&#xA;    	&#xD;&#xA;    	GLfloat gViewMatrix[16];&#xD;&#xA;    	glGetFloatv(GL_MODELVIEW_MATRIX, gViewMatrix);&#xD;&#xA;    	glm::mat4 ViewMatrix = glm::make_mat4(gViewMatrix);// = glm::mat4(gProjectionMatrix);&#xD;&#xA;    	&#xD;&#xA;    	glm::vec3 lightPos = glm::vec3(4, 4, 4);&#xD;&#xA;    	glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);&#xD;&#xA;    	glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &amp;ViewMatrix[0][0]);&#xD;&#xA;    &#xD;&#xA;    	glm::mat4 ModelMatrix1 = glm::mat4(1.0);&#xD;&#xA;    	glm::mat4 MVP1 = ProjectionMatrix * ViewMatrix * ModelMatrix1;&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    	glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    	glBindTexture(GL_TEXTURE_2D, textur);&#xD;&#xA;    	&#xD;&#xA;    	glUniform1i(TextureID, 0);&#xD;&#xA;    	// Send our transformation to the currently bound shader, &#xD;&#xA;    	// in the &quot;MVP&quot; uniform&#xD;&#xA;    	glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &amp;MVP1[0][0]);&#xD;&#xA;    	glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &amp;ModelMatrix1[0][0]);&#xD;&#xA;    	glEnableVertexAttribArray(0);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);&#xD;&#xA;    	glVertexAttribPointer(&#xD;&#xA;    		0,                  // attribute&#xD;&#xA;    		3,                  // size&#xD;&#xA;    		GL_FLOAT,           // type&#xD;&#xA;    		GL_FALSE,           // normalized?&#xD;&#xA;    		0,                  // stride&#xD;&#xA;    		(void*)0            // array buffer offset&#xD;&#xA;    	);&#xD;&#xA;    &#xD;&#xA;    	// 2nd attribute buffer : UVs&#xD;&#xA;    	glEnableVertexAttribArray(1);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);&#xD;&#xA;    	glVertexAttribPointer(&#xD;&#xA;    		1,                                // attribute&#xD;&#xA;    		2,                                // size&#xD;&#xA;    		GL_FLOAT,                         // type&#xD;&#xA;    		GL_FALSE,                         // normalized?&#xD;&#xA;    		0,                                // stride&#xD;&#xA;    		(void*)0                          // array buffer offset&#xD;&#xA;    	);&#xD;&#xA;    &#xD;&#xA;    	// 3rd attribute buffer : normals&#xD;&#xA;    	glEnableVertexAttribArray(2);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);&#xD;&#xA;    	glVertexAttribPointer(&#xD;&#xA;    		2,                                // attribute&#xD;&#xA;    		3,                                // size&#xD;&#xA;    		GL_FLOAT,                         // type&#xD;&#xA;    		GL_FALSE,                         // normalized?&#xD;&#xA;    		0,                                // stride&#xD;&#xA;    		(void*)0                          // array buffer offset&#xD;&#xA;    	);&#xD;&#xA;    &#xD;&#xA;    	// Index buffer&#xD;&#xA;    	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);&#xD;&#xA;    &#xD;&#xA;    	// Draw the triangles !&#xD;&#xA;    	glDrawElements(&#xD;&#xA;    		GL_TRIANGLES,      // mode&#xD;&#xA;    		obj.indices.size(),    // count&#xD;&#xA;    		GL_UNSIGNED_SHORT,   // type&#xD;&#xA;    		(void*)0           // element array buffer offset&#xD;&#xA;    	);&#xD;&#xA;    	&#xD;&#xA;    	//glFlush(); glFinish(); readScreen(screen, GL_RGB, true);&#xD;&#xA;    &#xD;&#xA;    	glDisableVertexAttribArray(0);&#xD;&#xA;    	glDisableVertexAttribArray(1);&#xD;&#xA;    	glDisableVertexAttribArray(2);&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(1, &amp;vertexbuffer);&#xD;&#xA;    	glDeleteBuffers(1, &amp;uvbuffer);&#xD;&#xA;    	glDeleteBuffers(1, &amp;normalbuffer);&#xD;&#xA;    	glDeleteBuffers(1, &amp;elementbuffer);&#xD;&#xA;    	glDeleteProgram(castingShader.ID);&#xD;&#xA;    	glDeleteTextures(1, &amp;textur);&#xD;&#xA;    	glDeleteVertexArrays(1, &amp;VertexArrayID);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;These are my read and draw screen functions:&#xD;&#xA;&#xD;&#xA;    void CCssample5View::readScreen(GLubyte* screen, GLenum format, bool back)&#xD;&#xA;    {&#xD;&#xA;    	check();&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	if (format == GL_RGB) {&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    		check();&#xD;&#xA;    		if (back) {&#xD;&#xA;    			glReadBuffer(GL_BACK);&#xD;&#xA;    			check();&#xD;&#xA;    		}&#xD;&#xA;    		else {&#xD;&#xA;    			glReadBuffer(GL_FRONT);&#xD;&#xA;    			check();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    	}&#xD;&#xA;    	//glRasterPos2i(00, 00);&#xD;&#xA;    	//glDisable(GL_DEPTH_TEST);&#xD;&#xA;    	glPixelStorei(GL_PACK_ALIGNMENT, 1);&#xD;&#xA;    	glReadPixels(0, 0, w, h, format, GL_UNSIGNED_BYTE, screen);&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    	glFlush();&#xD;&#xA;    	glFinish();&#xD;&#xA;    	bool found = false;&#xD;&#xA;    	for (size_t u = 0; u &lt;= w * h * 4; u++) {&#xD;&#xA;    		if (screen[u] != 0) {&#xD;&#xA;    			found = true;&#xD;&#xA;    			break;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    	assert(found);&#xD;&#xA;    	check();&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    void CCssample5View::drawScreen(GLubyte *screen, GLenum format, bool back)&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    	glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    	//glGetIntegerv(GL_CURRENT_RASTER_POSITION, rasterpos);&#xD;&#xA;    	if (back) {&#xD;&#xA;    		glDrawBuffer(GL_BACK);&#xD;&#xA;    	}&#xD;&#xA;    	else {&#xD;&#xA;    		glDrawBuffer(GL_FRONT);&#xD;&#xA;    	}	 &#xD;&#xA;    	&#xD;&#xA;    	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);&#xD;&#xA;    	glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, screen);&#xD;&#xA;    	check();&#xD;&#xA;    &#xD;&#xA;    	glFlush();&#xD;&#xA;    	glFinish();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Can not seem to figure out whats wrong when the drawing is perfect except the reading screen part.." ContentLicense="CC BY-SA 4.0" />
  <row Id="22286" PostHistoryTypeId="1" PostId="8354" RevisionGUID="bb5880c0-9408-4d78-b0be-85afcb6dd244" CreationDate="2018-12-03T18:02:02.823" UserId="9789" Text="Why is glreadpixels only working in certain cases?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22287" PostHistoryTypeId="3" PostId="8354" RevisionGUID="bb5880c0-9408-4d78-b0be-85afcb6dd244" CreationDate="2018-12-03T18:02:02.823" UserId="9789" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22288" PostHistoryTypeId="2" PostId="8355" RevisionGUID="a38ac93a-a254-4eba-b71e-6f947d591dc4" CreationDate="2018-12-03T18:36:23.487" UserId="1940" Text="The Phong lighting model computes the specular response as the dot product between the mirror reflection direction and the viewing direction, raised to a power.&#xD;&#xA;&#xD;&#xA;For example, if $\vec{V}$ is the viewing direction, $\vec{L}$ the incoming light direction and $\vec{R}$ the perfect specular reflection direction for $\vec{L}$, then the specular response is $\text{max}(\vec{V}.\vec{R},0)^p$, where $p$ is the exponent that controls the fall-off of the specular response. &#xD;&#xA;&#xD;&#xA;The Blinn-Phong model uses a half vector $\vec{H}$, which is computed as $\vec{H} = \frac{\vec{L}+\vec{V}}{|\vec{L}+\vec{V}|}$, which is then used to compute the specular response as $\text{max}(\vec{H}.\vec{N},0)^p$, where $\vec{N}$ is the surface normal. The idea is that when the eye vector $\vec{V}$ is aligned perfectly with the perfect mirror direction $\vec{R}$, the half vector $\vec{H}$ would be exactly aligned with the surface normal $\vec{N}$. Hence the Blinn-Phong can get away with computing an expensive mirror direction $\vec{R}$ everytime by using the half vector which can model the specular response." ContentLicense="CC BY-SA 4.0" />
  <row Id="22289" PostHistoryTypeId="5" PostId="8319" RevisionGUID="373a8ff2-403c-4554-92d6-7f8b230d0246" CreationDate="2018-12-03T19:55:43.970" UserId="9763" Comment="Note swizzle mask in VkImageViewCreateInfo components field used to create VkImageView" Text="I have some existing OpenGL code that I am porting to Vulkan. The question is somewhat relevant to both OpenGL and Vulkan.&#xD;&#xA;&#xD;&#xA;I am rendering some primitives using textures, some single channel, others RGBA, as well as flat colored primitives with per-vertex colors. The GL code that I am porting frequently switches shader programs with `glUseProgram`.&#xD;&#xA;&#xD;&#xA;In Vulkan, using two distinct sets of shaders requires two pipelines created with `vkCreateGraphicsPipelines` and later bound with `vkCmdBindPipeline` plus `vkCmdBindDescriptorSets`, thus changing shader programs equates program switches with graphics pipeline reconfiguration.&#xD;&#xA;&#xD;&#xA;I am wondering whether it is efficient to switch to a single shader program and hence a single graphics pipeline with a vertex layout that contains texture coordinates, a color, and texture sampler. When I want to draw flat colored objects, the code would set the color in the vertex and bind a 1x1 white sampler and when I want to render images the code can bind a full image. I currently render the following:&#xD;&#xA;&#xD;&#xA;- flat color using color from vertex&#xD;&#xA;- alpha from sampler and color from vertex&#xD;&#xA;- RGBA from sampler and alpha from vertex &#xD;&#xA;&#xD;&#xA;The question is from a hardware, driver/performance perspective, is it more efficient to use a single pipeline and descriptor layout and only performing uniform updates and have a slightly larger Vertex, or is switching pipelines low enough cost to warrant two or three pipelines and two of three sets of shaders and different vertex formats. i.e. where is the best balance between these concerns?&#xD;&#xA;&#xD;&#xA;- three sets of shaders, three small vertex structs; program, uniform, and sampler switches&#xD;&#xA;- one set of shaders, one slightly larger vertex struct and just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;We could benchmark this but wonder if someone already has data to compare these approaches. I am aware of Ubershaders however this is hardly an Ubershader (see below) rather concerns any data on the ratio of program switch cost overhead versus the overhead of a 1x1 NOP texture lookups and texture color versus switching to a shader with no texture lookups.&#xD;&#xA;&#xD;&#xA;With multiple shaders, the required program switches are likely to be in the order of 100's or possibly 1000's because of transparent content that requires a specific rendering order. In my case, it is for a _mostly_ 2D app with a mix of line/block/bezier art, fonts using single alpha channel texture atlas plus vertex color and finally, RGBA images, typically just using the vertex alpha value and all currently using an orthographic projection with no lighting.&#xD;&#xA;&#xD;&#xA;Ideally, I would like data on pipeline/program switch cost versus descriptor set switch cost.&#xD;&#xA;&#xD;&#xA;For the shared program model, I am thinking about using the following:&#xD;&#xA;&#xD;&#xA;This is the vertex struct:&#xD;&#xA;&#xD;&#xA;	struct Vertex {&#xD;&#xA;		glm::vec3 vertex;&#xD;&#xA;		glm::vec2 texcoord;&#xD;&#xA;		uint32_t color;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;and this is the vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;	layout (location = 0) in vec4 vcolor;&#xD;&#xA;	layout (location = 1) in vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;	layout (binding = 1) uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;	layout (location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;    	outColor = vcolor * texture(tex, vtexcoord);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;&#xD;&#xA;    layout (location = 0) in vec3 vertex;&#xD;&#xA;    layout (location = 1) in vec2 texcoord;&#xD;&#xA;    layout (location = 2) in vec4 color;&#xD;&#xA;&#xD;&#xA;    layout (binding = 0) uniform UBO &#xD;&#xA;    {&#xD;&#xA;        mat4 modelViewProjection;&#xD;&#xA;    } ubo;&#xD;&#xA;&#xD;&#xA;    layout (location = 0) out vec4 vcolor;&#xD;&#xA;    layout (location = 1) out vec2 vtexcoord;&#xD;&#xA;&#xD;&#xA;    out gl_PerVertex &#xD;&#xA;    {&#xD;&#xA;	    vec4 gl_Position;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vcolor = color;&#xD;&#xA;        vtexcoord = texcoord;&#xD;&#xA;        gl_Position = ubo.modelViewProjection * vec4(vertex.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: as pointed out in the comments, swizzle masks in `VkImageViewCreateInfo` `components` field can be used to create `VkImageView` that translates the color and alpha channels instead of tieing shader code to the number of image channels in the sampler.&#xD;&#xA;&#xD;&#xA;To broadcast the first color channel to all elements in OpenGL:&#xD;&#xA;&#xD;&#xA;    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA,&#xD;&#xA;        (GLint[]) { GL_RED, GL_RED, GL_RED, GL_RED } );&#xD;&#xA;&#xD;&#xA;and for Vulkan, use the `VkImageViewCreateInfo` `components` field:&#xD;&#xA;&#xD;&#xA;    VkImageViewCreateInfo imageViewInfo;&#xD;&#xA;    imageViewInfo.components = {&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R,&#xD;&#xA;        VK_COMPONENT_SWIZZLE_R&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22290" PostHistoryTypeId="5" PostId="8336" RevisionGUID="e45f3022-1952-4cad-bb75-11d24d26ca4c" CreationDate="2018-12-03T23:10:26.130" UserId="506" Comment="fixed a few missing words" Text="This is a really hardware-dependent question. But in general the best way to think about this is bottlenecks.&#xD;&#xA;&#xD;&#xA;You mentioned:&#xD;&#xA;&#xD;&#xA;&gt; one set of shaders, one **slightly** larger vertex struct and just uniform, and sampler switches&#xD;&#xA;&#xD;&#xA;The slightly larger vertex struct doesn't seem like it will be the more likely bottleneck compared to:&#xD;&#xA;&#xD;&#xA;&gt;With multiple shaders, the required program switches are likely to be in the order of 100's or possibly 1000's &#xD;&#xA;&#xD;&#xA;On modern desktop/console hardware each graphics pipe might have a single-digit # of active contexts. Switching the state too frequently is sometimes to referred to as a context roll stall.&#xD;&#xA;&#xD;&#xA;In this case whether you hit that stall case is also dependent on how fast your shader and blend operations complete to make the context available. Given that you're going to do a lot of alpha blending, you might be bound by blending operations.&#xD;&#xA;&#xD;&#xA;By the way modern GPUs are much better at dynamic branching, and skipping over fetches with a shader uniform is possible so you don't need to pay the additional memory reads. That said, a 1x1 dummy texture is going to be in the texture cache anyway so again it probably doesn't matter.&#xD;&#xA;&#xD;&#xA;I'd say try using a single shader first before you introduce new shader permutations. And in general, do the easiest implementation first, measure on your target hardware, then optimize :) " ContentLicense="CC BY-SA 4.0" />
  <row Id="22291" PostHistoryTypeId="50" PostId="5697" RevisionGUID="e137773a-ac22-458c-81e4-d96cdca1f29d" CreationDate="2018-12-04T01:02:50.593" UserId="-1" />
  <row Id="22292" PostHistoryTypeId="5" PostId="8337" RevisionGUID="972aa522-ed71-4fc8-b80f-aa484a0afb64" CreationDate="2018-12-04T07:44:53.527" UserId="1582" Comment="added 7 characters in body" Text="&gt;1, 1, 1, the output value is white. If this represents radiance than the output should be green, because when the signal radiance is the same, the pixel should be perceived as green. Am I correct?&#xD;&#xA;&#xD;&#xA;This is not correct. Your frame buffer most likely contains sRGB values. Of which 1,1,1 is used to represent white. Standard displays do not use spectral radiance values in the frame buffer. sRGB does not map directly or make any guarantees about the spectral power distribution (SPD) of the display. So &quot;G&quot; of 1 does not guarantee some wave with amplitude using W⋅sr−1⋅m−2 centered on the 550nm. Part of the problem is that different type of displays have different SPDs that map to the same perceived color. &#xD;&#xA;&#xD;&#xA;[Evaluation of an organic light-emitting diode display for precise visual stimulation, Ito et. al]&#xD;&#xA;(https://jov.arvojournals.org/article.aspx?articleid=2121657)&#xD;&#xA;[![SPDs for different display types][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GD4E2.jpg&#xD;&#xA;&#xD;&#xA;Now if you want to physically accurate rendering, you could store all of your lighting values as Radiance with SPDs. As L.C. mentioned, Physically Based Rendering describes that this is done with piece-wise linear functions with like 16+ channels per color. However even if you can get this to be performant, good luck converting all your RGB data into SPDs (there's an infinite # of SPDs for a given RGB value).&#xD;&#xA;&#xD;&#xA;Instead what most renderers try to do is to treat the RGB as pseudo-radiance values for the purposes of lighting calculation. This isn't accurate, hence your lighting result changes if you are using Rec.709 or Rec.2020 primaries for instance (if you notice they have different values for mapping to luminance), but it's good enough for real time and even offline in most cases. At this point you can convert RGB Rec709 and Rec2020 values to a single scalar luminance using the Y values of it's primaries.&#xD;&#xA;&#xD;&#xA;The Y values of the RGB primaries for Rec709 are:&#xD;&#xA;&#xD;&#xA;        R       G       B&#xD;&#xA;    Y	0.2126	0.7152	0.0722&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/SRGB&#xD;&#xA;&#xD;&#xA;Thus Rec709 Linear has the following nits conversion:&#xD;&#xA;&#xD;&#xA;    nits = dot(linear709Rgb, float3(0.2126, 0.7152,0.0722));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Probably one of the results of doing our calculations in RGB is that G and B add at equal weights, so it's likely to get some color shifting. There was a presentation at SIGGRAPH 2015 from Weta digital that had some examples, but it doesn't seem like the slides are available. As far as I know they are the only ones using a spectral renderer." ContentLicense="CC BY-SA 4.0" />
  <row Id="22293" PostHistoryTypeId="2" PostId="8356" RevisionGUID="8411695a-9faa-40c9-a35a-a61629646522" CreationDate="2018-12-04T08:50:18.510" UserId="9194" Text="Mipmapping is a pre-computed texture scheme that tries to solve the problem of texturemap aliasing. When a screen pixel from a textured polygon covers many texture pixels, the pixel should be sampled more than only once (nearest neighbor or bilinearly) to get a &quot;correct&quot; average color. So instead of having a regular texture a mipmap is created. The mipmap level is chosen from the objects distance to the camera, and can be per pixel, per object, bi- or trilinearly interpolated, etc. Mipmapping in its nature does not take perspective projection into account.&#xD;&#xA;&#xD;&#xA;The 1-channel mipmap texture usually is divided into four parts, holding Red, Green, Blue in the first three, while the last is divided into four parts, holding the downsampled 2x2 average of R, G and B, and so on recursively until a pres-elected depth. I'm sure google has pictures of this." ContentLicense="CC BY-SA 4.0" />
  <row Id="22299" PostHistoryTypeId="2" PostId="8358" RevisionGUID="1d5dc453-cb86-4009-8ab8-5310beb213e0" CreationDate="2018-12-04T14:50:13.060" UserId="7008" Text="I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.&#xD;&#xA;&#xD;&#xA;In the latter case I store tex coords, meaning that for my texture coordinate $(u_d, v_d)$ in the shader I read out the texture coordinate $(u, v)$ and thus have a distortion from the original point $(u, v)$ to my distorted point $(u_d, v_d)$. &#xD;&#xA;&#xD;&#xA;I can set up my distortion to have no distortion at all (i.e. $(u, v) = (u_d, v_d)$). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that &quot;distortion&quot;, I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).&#xD;&#xA;&#xD;&#xA;Here is the same excerpt from my results, first with the shader calculated distortion:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And then with the precalculated distortion and blurry result:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.&#xD;&#xA;&#xD;&#xA;The texture is using `GL_FLOAT` as the data type and `GL_RG32F` as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to `GL_LINEAR` as well as set to `GL_NEAREST`.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ty5aj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M3IkC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22300" PostHistoryTypeId="1" PostId="8358" RevisionGUID="1d5dc453-cb86-4009-8ab8-5310beb213e0" CreationDate="2018-12-04T14:50:13.060" UserId="7008" Text="Why is precalculating a distortion different from calculating it in the shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22301" PostHistoryTypeId="3" PostId="8358" RevisionGUID="1d5dc453-cb86-4009-8ab8-5310beb213e0" CreationDate="2018-12-04T14:50:13.060" UserId="7008" Text="|texture|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22302" PostHistoryTypeId="2" PostId="8359" RevisionGUID="f7faa920-8374-4c17-8908-da1189d1ac42" CreationDate="2018-12-04T16:47:36.467" UserId="3123" Text="Does anyone know any method to remove ghosting in volumetric lighting? &#xD;&#xA;&#xD;&#xA;When light move it leaves trail behind, i would like to remove it.&#xD;&#xA;Volumetrics are Bart Wronski style (in frustum) with exponential temporal accumulation.&#xD;&#xA;&#xD;&#xA;I have tried neighborhood clamp, Karis and variance clipping, both remove ghosting but also introduce other artifacts.&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="22303" PostHistoryTypeId="1" PostId="8359" RevisionGUID="f7faa920-8374-4c17-8908-da1189d1ac42" CreationDate="2018-12-04T16:47:36.467" UserId="3123" Text="Ghosting in volumetric lighting" ContentLicense="CC BY-SA 4.0" />
  <row Id="22304" PostHistoryTypeId="3" PostId="8359" RevisionGUID="f7faa920-8374-4c17-8908-da1189d1ac42" CreationDate="2018-12-04T16:47:36.467" UserId="3123" Text="|lighting|artifacts|volumetric|fog|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22305" PostHistoryTypeId="2" PostId="8360" RevisionGUID="6920b74a-ffb6-4d2b-adaa-ac81ae1ba2de" CreationDate="2018-12-04T18:22:55.713" UserId="5385" Text="Temporal by definition will ghost. I’d limit past frame sampling, apply weight &lt; 0.5, limit movement etc. " ContentLicense="CC BY-SA 4.0" />
  <row Id="22306" PostHistoryTypeId="2" PostId="8361" RevisionGUID="8e0877aa-33b6-420e-abae-98237c2799f5" CreationDate="2018-12-04T19:54:07.357" UserId="9800" Text="I wasn't really expecting that, no. The formula in the paper is not the most elegant - there's quite a few parentheses in there. In this case I think it's just a matter of shuffling the parentheses around a little in the get_k implementation - both terms should be divided by `(1-r)`:&#xD;&#xA;&#xD;&#xA;        float get_k(float r, float n) {&#xD;&#xA;            return std::sqrt( 1.0/(1.0-r) * ( r*std::pow(n+1.0, 2) - std::pow(n-1.0, 2) ));&#xD;&#xA;        }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22307" PostHistoryTypeId="50" PostId="7897" RevisionGUID="eaf7de06-7db7-4547-b6f9-05150fe8f3c4" CreationDate="2018-12-04T21:01:45.293" UserId="-1" />
  <row Id="22309" PostHistoryTypeId="5" PostId="8240" RevisionGUID="235b73ab-c601-4612-874e-3e602b46b73b" CreationDate="2018-12-05T09:00:06.087" UserId="5778" Comment="tags edited. formatting" Text="My book says:&#xD;&#xA;&#xD;&#xA;&gt; After a scene has been constructed we transfer object descriptions to the viewing-coordinate reference frame. This conversion of object descriptions is equivalent to a sequence of transformations that superimposes the viewing reference frame onto the world frame, so we translate  the  view reference frame onto the origin and  rotate by an angle to align the view to the world.&#xD;&#xA;  &#xD;&#xA;So, my confusion is: if we're transferring object descriptions from the world to view, shouldn't we superimpose the world onto the view,   and hence take the inverse  of  the above transformation? Why is my book saying things the other way around?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22310" PostHistoryTypeId="6" PostId="8240" RevisionGUID="235b73ab-c601-4612-874e-3e602b46b73b" CreationDate="2018-12-05T09:00:06.087" UserId="5778" Comment="tags edited. formatting" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22311" PostHistoryTypeId="24" PostId="8240" RevisionGUID="235b73ab-c601-4612-874e-3e602b46b73b" CreationDate="2018-12-05T09:00:06.087" Comment="Proposed by 5778 approved by 506, 4908 edit id of 447" ContentLicense="CC BY-SA 4.0" />
  <row Id="22312" PostHistoryTypeId="6" PostId="7483" RevisionGUID="2b6fb2f2-0fe2-4a9d-9d17-2850d2f52926" CreationDate="2018-12-05T09:02:20.457" UserId="5778" Comment="tags edited" Text="|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22313" PostHistoryTypeId="24" PostId="7483" RevisionGUID="2b6fb2f2-0fe2-4a9d-9d17-2850d2f52926" CreationDate="2018-12-05T09:02:20.457" Comment="Proposed by 5778 approved by 4908, 209 edit id of 448" ContentLicense="CC BY-SA 4.0" />
  <row Id="22314" PostHistoryTypeId="2" PostId="8362" RevisionGUID="1995e626-dbdb-4155-bac4-92dfaccd11ba" CreationDate="2018-12-05T11:23:09.617" UserId="7644" Text="It's a bit hard to tell with the images, but I assume the whole viewport is distorted?&#xD;&#xA;&#xD;&#xA;My first thought is that there is a difference between the 2 distortion computation methods which might not be obvious. A good first debugging step would be to output only $(u_d, v_d)$ as a color with the two methods. This will allow isolating (or not) the problem to this computation since this is likely where the problem is. If this is the problem, it will be much easier to reason about and debug with all other factors removed from the final image.&#xD;&#xA;&#xD;&#xA;Could you add a (simplified) version of your distortion computation shader and the matching texture generation code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22315" PostHistoryTypeId="5" PostId="8358" RevisionGUID="fc1b827a-a637-4b55-8f7b-046c4fcc29b3" CreationDate="2018-12-05T11:46:14.530" UserId="7008" Comment="added code of the old and new version upon request" Text="I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.&#xD;&#xA;&#xD;&#xA;In the latter case I store tex coords, meaning that for my texture coordinate $(u_d, v_d)$ in the shader I read out the texture coordinate $(u, v)$ and thus have a distortion from the original point $(u, v)$ to my distorted point $(u_d, v_d)$. &#xD;&#xA;&#xD;&#xA;I can set up my distortion to have no distortion at all (i.e. $(u, v) = (u_d, v_d)$). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that &quot;distortion&quot;, I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).&#xD;&#xA;&#xD;&#xA;Here is the same excerpt from my results, first with the shader calculated distortion:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And then with the precalculated distortion and blurry result:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.&#xD;&#xA;&#xD;&#xA;The texture is using `GL_FLOAT` as the data type and `GL_RG32F` as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to `GL_LINEAR` as well as set to `GL_NEAREST`.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ty5aj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M3IkC.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;***Edit***&#xD;&#xA;Per request, first the distortion calculation within the shader:&#xD;&#xA;&#xD;&#xA;    vec2 getDistortedTexCoords(vec2 texCoords)&#xD;&#xA;    {&#xD;&#xA;        //uCamintrinsic stores (0.5, 0.5, f, f) where f is the focal length of the camera in pixels as unit&#xD;&#xA;	    vec2 principal = uCamIntrinsics.xy;&#xD;&#xA;&#xD;&#xA;	    principal.x *= uWidth;&#xD;&#xA;	    principal.y *= uHeight;&#xD;&#xA;	&#xD;&#xA;	    float u_d = texCoords.x * uWidth;&#xD;&#xA;	    float x_d = (u_d - principal.x) / uCamIntrinsics.z;	&#xD;&#xA;        float x_d2 = x_d * x_d;&#xD;&#xA;    	&#xD;&#xA;    	float v_d = texCoords.y * uHeight;&#xD;&#xA;    	float y_d = (v_d - principal.y) / uCamIntrinsics.w;	&#xD;&#xA;    	float y_d2 = y_d * y_d;&#xD;&#xA;    	&#xD;&#xA;    	float r_d = sqrt(x_d2 + y_d2);&#xD;&#xA;    	  	&#xD;&#xA;    	//the LuT stores values where the coordinate to read at is scaled by 1/uDiagonal (due to normalized texture coordinates)&#xD;&#xA;    	r_d /= uDiagonal;&#xD;&#xA;    	float r = texture(uDistortionLut, r_d).r;&#xD;&#xA;    	float r2 = r * r;&#xD;&#xA;    	float r4 = r2 * r2;&#xD;&#xA;    	float r6 = r4 * r2;&#xD;&#xA;    	&#xD;&#xA;    	float k1 = uChromGreenCoeffs.x;&#xD;&#xA;    	float k2 = uChromGreenCoeffs.y;&#xD;&#xA;    	float k3 = uChromGreenCoeffs.z;&#xD;&#xA;    	&#xD;&#xA;    	float pol = (k1 * r2 + k2 * r4 + k3 * r6);&#xD;&#xA;    	float denominator = 1 + pol;&#xD;&#xA;    	&#xD;&#xA;    	float u = (u_d + principal.x * pol)/denominator;&#xD;&#xA;    	float v = (v_d + principal.y * pol)/denominator;&#xD;&#xA;    	&#xD;&#xA;        //uWidth and uHeight are the resolution in pixels&#xD;&#xA;    	return vec2(u / uWidth, v / uHeight);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The texcoord texture for the second image was calculated with the following code (this is in OpenSceneGraph)&#xD;&#xA;&#xD;&#xA;    for (int u_d = 0; u_d &lt; res.x(); u_d++)&#xD;&#xA;	{&#xD;&#xA;		for (int v_d = 0; v_d &lt; res.y(); v_d++)&#xD;&#xA;		{&#xD;&#xA;			//within the shader we can't change position. that means we are at a distorted point already and need to read the undistorted coordinate&#xD;&#xA;			//for this distorted point to actually achieve the correct distortion. that means, we need to calculate the uv coordinate (i.e. pixel coordinate!)&#xD;&#xA;			osg::Vec2 uv, uv_d(u_d, v_d);&#xD;&#xA;&#xD;&#xA;            //principal is (0.5, 0.5)&#xD;&#xA;            //f is the same focal length as stored in uCamIntrinsics in the shader version&#xD;&#xA;			double x_d = (u_d - principal.x()) / f;&#xD;&#xA;			double y_d = (v_d - principal.y()) / f;&#xD;&#xA;&#xD;&#xA;			double r_d = sqrt(x_d*x_d + y_d*y_d);&#xD;&#xA;			//the distortionRadiusLut stores r_d-&gt;r&#xD;&#xA;			//it is however unlikely, that we hit an exact r_d value, therefore interpolate between the nearest two&#xD;&#xA;            //this Lut is the same that is uploaded to the shader as a texture1D in the shader version&#xD;&#xA;			double r = getInterpolatedValue(distortionRadiusLut, r_d);&#xD;&#xA;			double r2 = r * r;&#xD;&#xA;			double r4 = r2 * r2;&#xD;&#xA;			double r6 = r4 * r2;&#xD;&#xA;&#xD;&#xA;            //k1, k2 and k3 have the same values as they did in the shader version&#xD;&#xA;			double polynomialPart = k_1 * r2 + k_2 * r4 + k_3 * r6;&#xD;&#xA;&#xD;&#xA;			uv = uv_d + principal * polynomialPart;&#xD;&#xA;			uv /= (1 + polynomialPart);&#xD;&#xA;			&#xD;&#xA;			for (int k = 0; k &lt; numComponents; k++)&#xD;&#xA;			{&#xD;&#xA;                //data is the image buffer, accessed as a float array&#xD;&#xA;                //res stores the resolution width and height&#xD;&#xA;                //numComponents is 2 in this case, since it is an RG32F texture&#xD;&#xA;				data[v_d * (int)res.x() * numComponents + u_d * numComponents + k] = uv[k]/res[k];&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With this precalculation, the shader turns simply into the following, with `texCoords` being the original texture coordinates for the screen quad and `uTexCoordLut` being the 2D texture that stores the precalculated texture coordinates:&#xD;&#xA;&#xD;&#xA;    vec2 texCoordsGreenLut = texture(uTexCoordLut, texCoords).rg;&#xD;&#xA;    color.rgb = texture(uRenderedImage, texCoordsGreenLut).rgb;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22316" PostHistoryTypeId="5" PostId="8358" RevisionGUID="33fe53ec-865d-4079-bcf4-67604466a8f1" CreationDate="2018-12-05T12:19:37.437" UserId="7008" Comment="removed distortion code and added minimal example code" Text="I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.&#xD;&#xA;&#xD;&#xA;In the latter case I store tex coords, meaning that for my texture coordinate $(u_d, v_d)$ in the shader I read out the texture coordinate $(u, v)$ and thus have a distortion from the original point $(u, v)$ to my distorted point $(u_d, v_d)$. &#xD;&#xA;&#xD;&#xA;I can set up my distortion to have no distortion at all (i.e. $(u, v) = (u_d, v_d)$). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that &quot;distortion&quot;, I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).&#xD;&#xA;&#xD;&#xA;Here is the same excerpt from my results, first with the shader calculated distortion:&#xD;&#xA;&#xD;&#xA;[![Distortion calculation done in the shader][1]][1]&#xD;&#xA;&#xD;&#xA;And then with the precalculated distortion and blurry result:&#xD;&#xA;[![Distortion precalculated and new texture coordinates read in the shader][2]][2]&#xD;&#xA;&#xD;&#xA;I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.&#xD;&#xA;&#xD;&#xA;The texture is using `GL_FLOAT` as the data type and `GL_RG32F` as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to `GL_LINEAR` as well as set to `GL_NEAREST`.&#xD;&#xA;&#xD;&#xA;***Edit2&#xD;&#xA;I have managed to reproduce the problem in a more minimal example, excluding any distortion calculations.&#xD;&#xA;That is, in OpenSceneGraph I have two cameras, one (`rttCamera`) rendering a scene into a texture and one (`displayCamera`) rendering this texture to the framebuffer. I precalculate a texture which stores texture coordinates, but basically they should return the same texture coordinates at every pixel as the geometry of the screen quad does:&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; res[0]; i++)&#xD;&#xA;	{&#xD;&#xA;		for (int j = 0; j &lt; res[1]; j++)&#xD;&#xA;		{&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0];&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1];&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`img-&gt;data` is the buffer for the texture, `i, j` are the pixel coordinates, `res` stores the resolution (1920 * 1080 in this case). The texture itself is again `GL_RG32F` with data type `GL_FLOAT`.&#xD;&#xA;&#xD;&#xA;The fragment shader code for the `displayCamera`is the following:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D uRenderedImage;&#xD;&#xA;    uniform sampler2D uTexCoordLut;&#xD;&#xA;    &#xD;&#xA;    uniform bool uIsLutUsed;&#xD;&#xA;    &#xD;&#xA;    in vec2 vTexCoord;&#xD;&#xA;    out vec4 gl_FragColor;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	vec2 texCoord = texture(uTexCoordLut, vTexCoord).rg;&#xD;&#xA;    	// gl_FragColor = vec4(texCoord, 0, 1);&#xD;&#xA;    	gl_FragColor = texture(uRenderedImage, vTexCoord);&#xD;&#xA;    	if(uIsLutUsed)&#xD;&#xA;    	{&#xD;&#xA;    		gl_FragColor = texture(uRenderedImage, texCoord);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;where the boolean uniform is for me to switch between the geometry texcoord version and my precalculated texcoord version.&#xD;&#xA;&#xD;&#xA;The resulting images are the following (again cropped), first the version without the precalculated texture coordinates&#xD;&#xA;&#xD;&#xA;[![Using the geometry texture coordinates][3]][3]&#xD;&#xA;&#xD;&#xA;and then the version with precalculated texture coordinates&#xD;&#xA;&#xD;&#xA;[![Using the precalculated texture coordinates][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ty5aj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M3IkC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/F4db8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/czNSb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22317" PostHistoryTypeId="5" PostId="8358" RevisionGUID="20fd34ea-1567-49c1-a701-21c915f4c190" CreationDate="2018-12-05T12:31:37.280" UserId="7008" Comment="corrected a layouting error" Text="I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.&#xD;&#xA;&#xD;&#xA;In the latter case I store tex coords, meaning that for my texture coordinate $(u_d, v_d)$ in the shader I read out the texture coordinate $(u, v)$ and thus have a distortion from the original point $(u, v)$ to my distorted point $(u_d, v_d)$. &#xD;&#xA;&#xD;&#xA;I can set up my distortion to have no distortion at all (i.e. $(u, v) = (u_d, v_d)$). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that &quot;distortion&quot;, I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).&#xD;&#xA;&#xD;&#xA;Here is the same excerpt from my results, first with the shader calculated distortion:&#xD;&#xA;&#xD;&#xA;[![Distortion calculation done in the shader][1]][1]&#xD;&#xA;&#xD;&#xA;And then with the precalculated distortion and blurry result:&#xD;&#xA;[![Distortion precalculated and new texture coordinates read in the shader][2]][2]&#xD;&#xA;&#xD;&#xA;I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.&#xD;&#xA;&#xD;&#xA;The texture is using `GL_FLOAT` as the data type and `GL_RG32F` as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to `GL_LINEAR` as well as set to `GL_NEAREST`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;***Edit2***&#xD;&#xA;&#xD;&#xA;I have managed to reproduce the problem in a more minimal example, excluding any distortion calculations.&#xD;&#xA;That is, in OpenSceneGraph I have two cameras, one (`rttCamera`) rendering a scene into a texture and one (`displayCamera`) rendering this texture to the framebuffer. I precalculate a texture which stores texture coordinates, but basically they should return the same texture coordinates at every pixel as the geometry of the screen quad does:&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; res[0]; i++)&#xD;&#xA;	{&#xD;&#xA;		for (int j = 0; j &lt; res[1]; j++)&#xD;&#xA;		{&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0];&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1];&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`img-&gt;data` is the buffer for the texture, `i, j` are the pixel coordinates, `res` stores the resolution (1920 * 1080 in this case). The texture itself is again `GL_RG32F` with data type `GL_FLOAT`.&#xD;&#xA;&#xD;&#xA;The fragment shader code for the `displayCamera`is the following:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D uRenderedImage;&#xD;&#xA;    uniform sampler2D uTexCoordLut;&#xD;&#xA;    &#xD;&#xA;    uniform bool uIsLutUsed;&#xD;&#xA;    &#xD;&#xA;    in vec2 vTexCoord;&#xD;&#xA;    out vec4 gl_FragColor;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	vec2 texCoord = texture(uTexCoordLut, vTexCoord).rg;&#xD;&#xA;    	// gl_FragColor = vec4(texCoord, 0, 1);&#xD;&#xA;    	gl_FragColor = texture(uRenderedImage, vTexCoord);&#xD;&#xA;    	if(uIsLutUsed)&#xD;&#xA;    	{&#xD;&#xA;    		gl_FragColor = texture(uRenderedImage, texCoord);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;where the boolean uniform is for me to switch between the geometry texcoord version and my precalculated texcoord version.&#xD;&#xA;&#xD;&#xA;The resulting images are the following (again cropped), first the version without the precalculated texture coordinates&#xD;&#xA;&#xD;&#xA;[![Using the geometry texture coordinates][3]][3]&#xD;&#xA;&#xD;&#xA;and then the version with precalculated texture coordinates&#xD;&#xA;&#xD;&#xA;[![Using the precalculated texture coordinates][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ty5aj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M3IkC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/F4db8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/czNSb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22318" PostHistoryTypeId="5" PostId="8358" RevisionGUID="76cccef1-93ec-4e79-8876-ef8364950492" CreationDate="2018-12-05T13:22:31.863" UserId="7008" Comment="added new information about a workaround" Text="I have an application where I simulate a camera distortion. There are two ways to go about it: calculate the distortion per pixel in the shader or precalculate the distortion and store the distortion as a 2D texture. In either case I first render the undistorted image, then calculate different texture coordinates in a new render pass for every pixel and thus read from the original image at a different position.&#xD;&#xA;&#xD;&#xA;In the latter case I store tex coords, meaning that for my texture coordinate $(u_d, v_d)$ in the shader I read out the texture coordinate $(u, v)$ and thus have a distortion from the original point $(u, v)$ to my distorted point $(u_d, v_d)$. &#xD;&#xA;&#xD;&#xA;I can set up my distortion to have no distortion at all (i.e. $(u, v) = (u_d, v_d)$). This works fine when I calculate the distortion in the shader, but if I precalculate the distortion and store my new tex coords, read them out in the shader and then apply that &quot;distortion&quot;, I get a somewhat blurry image. I have checked my texture with the new texture coordinates, but they seem to store exactly what I want them to (basically their own position).&#xD;&#xA;&#xD;&#xA;Here is the same excerpt from my results, first with the shader calculated distortion:&#xD;&#xA;&#xD;&#xA;[![Distortion calculation done in the shader][1]][1]&#xD;&#xA;&#xD;&#xA;And then with the precalculated distortion and blurry result:&#xD;&#xA;[![Distortion precalculated and new texture coordinates read in the shader][2]][2]&#xD;&#xA;&#xD;&#xA;I'm a bit at a loss as to why I get this blurry image now, especially when there is actually no offset between the original and the distorted tex coords.&#xD;&#xA;&#xD;&#xA;The texture is using `GL_FLOAT` as the data type and `GL_RG32F` as the internal format, I don't use mip mapping and the image is usually non power of 2 and non square (e.g. in this case 1920*1079), the prerendered image has the same size as my precalculated texture coordinate texture. This effect occurs with filtering set to `GL_LINEAR` as well as set to `GL_NEAREST`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;***Edit2***&#xD;&#xA;&#xD;&#xA;I have managed to reproduce the problem in a more minimal example, excluding any distortion calculations.&#xD;&#xA;That is, in OpenSceneGraph I have two cameras, one (`rttCamera`) rendering a scene into a texture and one (`displayCamera`) rendering this texture to the framebuffer. I precalculate a texture which stores texture coordinates, but basically they should return the same texture coordinates at every pixel as the geometry of the screen quad does:&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; res[0]; i++)&#xD;&#xA;	{&#xD;&#xA;		for (int j = 0; j &lt; res[1]; j++)&#xD;&#xA;		{&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0];&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1];&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;`img-&gt;data` is the buffer for the texture, `i, j` are the pixel coordinates, `res` stores the resolution (1920 * 1080 in this case). The texture itself is again `GL_RG32F` with data type `GL_FLOAT`.&#xD;&#xA;&#xD;&#xA;The fragment shader code for the `displayCamera`is the following:&#xD;&#xA;&#xD;&#xA;    #version 400&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D uRenderedImage;&#xD;&#xA;    uniform sampler2D uTexCoordLut;&#xD;&#xA;    &#xD;&#xA;    uniform bool uIsLutUsed;&#xD;&#xA;    &#xD;&#xA;    in vec2 vTexCoord;&#xD;&#xA;    out vec4 gl_FragColor;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	vec2 texCoord = texture(uTexCoordLut, vTexCoord).rg;&#xD;&#xA;    	// gl_FragColor = vec4(texCoord, 0, 1);&#xD;&#xA;    	gl_FragColor = texture(uRenderedImage, vTexCoord);&#xD;&#xA;    	if(uIsLutUsed)&#xD;&#xA;    	{&#xD;&#xA;    		gl_FragColor = texture(uRenderedImage, texCoord);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;where the boolean uniform is for me to switch between the geometry texcoord version and my precalculated texcoord version.&#xD;&#xA;&#xD;&#xA;The resulting images are the following (again cropped), first the version without the precalculated texture coordinates&#xD;&#xA;&#xD;&#xA;[![Using the geometry texture coordinates][3]][3]&#xD;&#xA;&#xD;&#xA;and then the version with precalculated texture coordinates&#xD;&#xA;&#xD;&#xA;[![Using the precalculated texture coordinates][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;***Edit3***&#xD;&#xA;&#xD;&#xA;I tried around a bit, and I found one solution (although that doesn't answer my question of 'why').&#xD;&#xA;Currently my prerendered image and my 2D texture that stores my new texture coordinates both have the same resolution. However, in my minimal example from Edit2, if keep the prerendered image at 1920*1080 pixel and increase the texture with my precalculated coordinates to 10000*10000, the difference between precalculated texture coordinates and geoemtry texture coordinates (or the rendered image with said coordinates) is minimal, barely noticable at all.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ty5aj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M3IkC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/F4db8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/czNSb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22319" PostHistoryTypeId="2" PostId="8363" RevisionGUID="2cd094ff-ad08-4e94-8e6d-ad0871e579cc" CreationDate="2018-12-05T14:39:41.607" UserId="7008" Text="I finally found the problem.&#xD;&#xA;&#xD;&#xA;My precalculation was done with pixel coordinates from `0` to `res[0] - 1` (i.e. the resolution width):&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; res[0]; i++)&#xD;&#xA;    {&#xD;&#xA;        for (int j = 0; j &lt; res[1]; j++)&#xD;&#xA;        {&#xD;&#xA;            reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0];&#xD;&#xA;            reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, pixels in OpenGL are accessed via their center, as can be read [in another SO answer][1] or [in Real-Time Rendering (3rd and 4th Edition, p.21)][2]. Meaning, that if I have a pixel with 0 as its left border and 0.1 as its right border, then 0.05 is its center.&#xD;&#xA;That means in my case, I have to offset the precalculated texture coordinate by half a pixel to read out of my prerendered image:&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; res[0]; i++)&#xD;&#xA;	{&#xD;&#xA;		for (int j = 0; j &lt; res[1]; j++)&#xD;&#xA;		{&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[0] = i / res[0] + 0.5 * pixelWidth;&#xD;&#xA;			reinterpret_cast&lt;float*&gt;(img-&gt;data(i, j))[1] = j / res[1] + 0.5 * pixelHeight;&#xD;&#xA;		}&#xD;&#xA;	} &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/5879403/opengl-texture-coordinates-in-pixel-space&#xD;&#xA;  [2]: http://www.realtimerendering.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="22320" PostHistoryTypeId="2" PostId="8364" RevisionGUID="cffd3ff0-92c1-42bb-a74f-249a752eae2b" CreationDate="2018-12-05T18:27:17.267" UserId="7462" Text="When reading papers I commonly find Oct tree implementations of geometry representations to sort the data. However whenever I think about the problem hash tables seem better overall.&#xD;&#xA;&#xD;&#xA;Hash tables have a better average and worse case scenarios for most applications:&#xD;&#xA;&#xD;&#xA;For example for ray tracing an oct tree, near misses will cause you to iterate through a binary tree substructure, which is O(nlogn) whereas the hash table is O(n).&#xD;&#xA;&#xD;&#xA;Hash tables are easier to generate in the GPU, as they do not require any logical position in memory other than their hash position.&#xD;&#xA;&#xD;&#xA;Most advantages tree structures have over hash tables do not seem to hold on the GPU either.&#xD;&#xA;&#xD;&#xA;In graphics we don't like re-allocating memory so we usually over allocate memory in VRAM just to be able to reuse a data structure. So the property binary trees have (being memory efficient) doesn't seem very relevant for GPU applications.&#xD;&#xA;&#xD;&#xA;Data coherence for caching doesn't seem to hold either. For a GPU generated tree, asynchronicity makes it very difficult to guarantee that logically close values also get stored close to one another in the underlying memory. So you will end up jumping around pointers anyway.&#xD;&#xA;&#xD;&#xA;It is also much easier to enforce certain GPU friendly heuristics in a hash table than in a tree. For example limiting the number of hash lookups to a fixed number, say 20 and using the same logic to prevent warps from executing different branch code. in essence you can always check the 20 potential collisions and just interpolate the result with the cell containing the key. In a tree the traversal through the data structure is a lot more dependent on the data itself and less on the data structure.&#xD;&#xA;&#xD;&#xA;So why are oct trees used so much more than hash tables?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22321" PostHistoryTypeId="1" PostId="8364" RevisionGUID="cffd3ff0-92c1-42bb-a74f-249a752eae2b" CreationDate="2018-12-05T18:27:17.267" UserId="7462" Text="Why are oct trees so much more common than hash tables?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22322" PostHistoryTypeId="3" PostId="8364" RevisionGUID="cffd3ff0-92c1-42bb-a74f-249a752eae2b" CreationDate="2018-12-05T18:27:17.267" UserId="7462" Text="|shader|algorithm|gpu|geometry|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22324" PostHistoryTypeId="5" PostId="8352" RevisionGUID="2fe22f46-c189-42c2-a2f2-b913a87870f4" CreationDate="2018-12-05T19:00:08.230" UserId="2654" Comment="deleted 1 character in body" Text="Polygon rasterization (the conversion of the analog polygon data into a [raster image][1]) is a key operation in rasterization-based rendering. As such, performing this operation fast, and with predictable performance, is key to the performance of graphics rendering.&#xD;&#xA;&#xD;&#xA;It is possible to rasterize any arbitrary polygon. But rasterizing triangles is extremely simple to code and offers numerous efficiency improvements over general polygon rasterization.&#xD;&#xA;&#xD;&#xA;Triangle rasterization is done by something called &quot;scan conversion&quot;: you break the triangle up into a series of horizontal scan-lines (one pixel tall) of a length determined by the sides of the triangle. Building these scan-lines and getting their lengths is something you can do through basic integer math involving only additions and multiplications. Furthermore, each scan-line can be constructed *independently* of the others, so highly threaded hardware can be employed to perform this process efficiently.&#xD;&#xA;&#xD;&#xA;None of this is true for arbitrary polygons. Concave polygons in particular require much more complex math. A concave polygon can have multiple lines in the same horizontal row.&#xD;&#xA;&#xD;&#xA;Furthermore, interpolation of values across the surface of a triangle can be done by relatively simple math. For each scanline, you can compute a gradient that represents how much each value changes from one end of the line to the other. So given a starting value at one line, you can easily compute the interpolated position at any point on the scanline simply by multiplication and addition. If you're computing them in sequence, you don't even need the multiplication; successive addition is adequate.&#xD;&#xA;&#xD;&#xA;Interpolation of values across an arbitrary polygonal surface is much more complicated.&#xD;&#xA;&#xD;&#xA;Given all of these advantages, and the fact that you can use a series of triangles to build any arbitrary polygon, there's really no reason to rasterize any more complex shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Raster_graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="22328" PostHistoryTypeId="50" PostId="8209" RevisionGUID="bd98fb00-bc97-40dc-98c2-e028243f0035" CreationDate="2018-12-05T21:03:15.793" UserId="-1" />
  <row Id="22329" PostHistoryTypeId="6" PostId="6019" RevisionGUID="eaa1942b-2ce2-4a13-8be9-8843c2b8b83b" CreationDate="2018-12-05T21:41:28.770" UserId="5778" Comment="tags edited" Text="|shader|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22330" PostHistoryTypeId="24" PostId="6019" RevisionGUID="eaa1942b-2ce2-4a13-8be9-8843c2b8b83b" CreationDate="2018-12-05T21:41:28.770" Comment="Proposed by 5778 approved by 209, 1937 edit id of 449" ContentLicense="CC BY-SA 4.0" />
  <row Id="22332" PostHistoryTypeId="2" PostId="8367" RevisionGUID="3ae40274-f2c9-4bbd-af26-c7330d5fad8f" CreationDate="2018-12-05T23:28:46.143" UserId="9809" Text="Lots of things here.&#xD;&#xA;&#xD;&#xA;- &quot;When reading papers&quot;. What papers? If the topic of the paper is about something other than the spatial partitioning structure, it could be fair to use whatever knowing that the basic ideas will translate to other structures. Or not, hard to say.&#xD;&#xA;&#xD;&#xA;- &quot;For example for ray tracing an oct tree, near misses will cause you to iterate through a binary tree substructure, which is O(nlogn) whereas the hash table is O(n)&quot;. Big O notation means nothing at all in this context. You are dealing with a particular technology at a particular scale when you talk about things that depend on implementation details. An O(nlogn) algorithm might be much slower than an O(n) one for the &quot;n&quot; that is realistic today, it happens all the times. And while you might say, in 10 years that might change, sure, that might be the case, but in the same 10 years your GPU might look completely different and thus the state of the art algorithms need to change regardless. That's common, if you look at GPU algorithms (and GPUs specifically are still evolving quite a bit)&#xD;&#xA;&#xD;&#xA;- What octree? What hash table? There are lots of choices there. For example &quot;...as they do not require any logical position in memory other than their hash position&quot;. That's true only if you have no hash collisions, yes? If you have collisions then whatever strategy you use (probing or linked lists) you'll need to synchronize between threads, so the build is not so easy to implement on a GPU. Conversely, for octrees if you wanted to &quot;overallocate&quot; as you suggest then you could allocate a full tree, and indexing would then be equally only dependent on position. In fact, if you do some math you can see that in such cases octrees become just a way to swizzle a grid (e.g. compare the van Ende Boas layout with a grid in Morton order... nice exercise).&#xD;&#xA;&#xD;&#xA;There are lots of other things I could say, but let me cut to the chase here.&#xD;&#xA;&#xD;&#xA;- For raytracing specifically, neither Octrees nor Hash tables are -that- popular. BVHs of AABBs are the way to go.&#xD;&#xA;&#xD;&#xA;- The main benefit of Octrees over hashed grid is that your cell resolution adapts to the geometry. Grids won't, you have to chose a cell size and that might be too small in certain parts of the scene and too big in certain others.&#xD;&#xA;&#xD;&#xA;- There are a -lot- of variants and a -lot- of implementation details. Naive octrees should probably never be used in practice as they are too deep / not wide enough. If you make an octree &quot;larger&quot; by having say, a 4x4x4 grid with 4x4x4 grids nested in each non-empty cells, you create what it's called a hierarchical grid. So grids and octrees exist on a spectrum, where octrees are the most &quot;deep&quot;, grids are the most &quot;shallow&quot; (just one level, a single grid globally in the scene), and hierarchical grids can trade between the two&#xD;&#xA;&#xD;&#xA;- This might help! http://www.realtimerendering.com/Real-Time_Rendering_4th-Real-Time_Ray_Tracing.pdf ;)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22334" PostHistoryTypeId="2" PostId="8368" RevisionGUID="c0b7b852-2681-4564-beac-3d30c57cf8ae" CreationDate="2018-12-06T03:45:37.850" UserId="9778" Text="In Cohen-Sutherland clipping, it assigns outcodes to the points on lines that are drawn to specify their orientation relative to the clipping window. &#xD;&#xA;&#xD;&#xA;In the diagram below, I'm confused on what outcodes that would be assigned to p1, p2, p3, p4? Can someone explain?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7oXm7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22335" PostHistoryTypeId="1" PostId="8368" RevisionGUID="c0b7b852-2681-4564-beac-3d30c57cf8ae" CreationDate="2018-12-06T03:45:37.850" UserId="9778" Text="What are the outcodes that would be assigned to these points?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22336" PostHistoryTypeId="3" PostId="8368" RevisionGUID="c0b7b852-2681-4564-beac-3d30c57cf8ae" CreationDate="2018-12-06T03:45:37.850" UserId="9778" Text="|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22337" PostHistoryTypeId="2" PostId="8369" RevisionGUID="f9f389e2-a639-4542-b029-1ecef0c88ccf" CreationDate="2018-12-06T06:43:25.410" UserId="3003" Text="The diagram on the [Wikipedia entry for Cohen-Sutherland Clipping](https://en.wikipedia.org/wiki/Cohen–Sutherland_algorithm) explains it pretty well:&#xD;&#xA;&#xD;&#xA;        	left	central	right&#xD;&#xA;    top		1001	1000	1010&#xD;&#xA;    central	0001	0000	0010&#xD;&#xA;    bottom	0101	0100	0110&#xD;&#xA;&#xD;&#xA;So in your example, `p1` would be left, central, so its code  would be 0001.&#xD;&#xA;&#xD;&#xA;`p2` would be central, bottom, so 0100&#xD;&#xA;&#xD;&#xA;`p3` would  be  central, central, so 0000&#xD;&#xA;&#xD;&#xA;`p4` would be central, top, so 1000" ContentLicense="CC BY-SA 4.0" />
  <row Id="22338" PostHistoryTypeId="2" PostId="8370" RevisionGUID="82cfbc28-ebfc-47f4-8078-37709ee8d696" CreationDate="2018-12-06T17:09:57.663" UserId="9789" Text="I figured it out. All I had to do was add `glUseProgram(0)` at the very end of the draw cylinder function. After more than 3 weeks of looking into this.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22339" PostHistoryTypeId="2" PostId="8371" RevisionGUID="35eecfcd-4d7c-4672-8662-7729fafd12ce" CreationDate="2018-12-07T06:22:43.013" UserId="9778" Text="In line drawing, bresenham's algorithm was explicitly derived for lines with slopes between 0 and 1 in the first octant from point P1 to point P2, where the x value of P1 is less than that for P2.&#xD;&#xA;&#xD;&#xA;In the incremental version of this algorithm, once a pixel is drawn, we need to choose the next pixel to draw. &#xD;&#xA;&#xD;&#xA;What are the choices? How do we go about choosing which pixel to draw next? (assuming a line width of 1 pixel)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22340" PostHistoryTypeId="1" PostId="8371" RevisionGUID="35eecfcd-4d7c-4672-8662-7729fafd12ce" CreationDate="2018-12-07T06:22:43.013" UserId="9778" Text="Bresenham's algorithm next pixel?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22341" PostHistoryTypeId="3" PostId="8371" RevisionGUID="35eecfcd-4d7c-4672-8662-7729fafd12ce" CreationDate="2018-12-07T06:22:43.013" UserId="9778" Text="|algorithm|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22342" PostHistoryTypeId="2" PostId="8372" RevisionGUID="7925c4ec-837c-4bed-ae57-c177f2e44f72" CreationDate="2018-12-07T08:07:09.833" UserId="9194" Text="Well, for the first octant you can either step EAST or NORTH-EAST. Depending on the distance to the actual line you choose the appropriate. In many integer [implementations][1], this is done with regard to the sign of D.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="22344" PostHistoryTypeId="2" PostId="8373" RevisionGUID="ddcb9c7d-590b-4f38-aaa6-fc0d963651d9" CreationDate="2018-12-07T12:39:54.153" UserId="8454" Text="I was following this tutorial on Vulkan https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer and I decided to do this bit:&#xD;&#xA;&#xD;&#xA;&gt; If you like a challenge, then you can still try to use a different queue family specifically for transfer operations. It will require you to make the following modifications to your program:&#xD;&#xA;&#xD;&#xA;&gt; - Modify QueueFamilyIndices and findQueueFamilies to explicitly look for a queue family with the VK_QUEUE_TRANSFER bit, but not the VK_QUEUE_GRAPHICS_BIT.&#xD;&#xA;&gt; - Modify createLogicalDevice to request a handle to the transfer queue&#xD;&#xA;&gt; - Create a second command pool for command buffers that are submitted on the transfer queue family&#xD;&#xA;&gt; - Change the sharingMode of resources to be VK_SHARING_MODE_CONCURRENT and specify both the graphics and transfer queue families&#xD;&#xA;&gt; - Submit any transfer commands like vkCmdCopyBuffer (which we'll be using in this chapter) to the transfer queue instead of the graphics queue&#xD;&#xA;&#xD;&#xA;&gt; It's a bit of work, but it'll teach you a lot about how resources are shared between queue families.&#xD;&#xA;&#xD;&#xA;The problem is that I can't create the Device :&#xD;&#xA;&#xD;&#xA;	VkDevice createDevice(PhysicalDeviceQueues queues, std::vector&lt;const char*&gt; layers, VkPhysicalDevice physical_device)&#xD;&#xA;	{&#xD;&#xA;		float queue_priority = 1.0f;&#xD;&#xA;&#xD;&#xA;		// Graphics queue&#xD;&#xA;		VkDeviceQueueCreateInfo graphics_queue_info;&#xD;&#xA;		graphics_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;&#xD;&#xA;		graphics_queue_info.queueFamilyIndex = queues.graphics_idx.value();&#xD;&#xA;		graphics_queue_info.queueCount = 1;&#xD;&#xA;		graphics_queue_info.pQueuePriorities = &amp;queue_priority;&#xD;&#xA;&#xD;&#xA;		// Transfer queue&#xD;&#xA;		VkDeviceQueueCreateInfo transfer_queue_info;&#xD;&#xA;		transfer_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;&#xD;&#xA;		transfer_queue_info.queueFamilyIndex = queues.transfer_idx.value();&#xD;&#xA;		transfer_queue_info.queueCount = 1;&#xD;&#xA;		transfer_queue_info.pQueuePriorities = &amp;queue_priority;&#xD;&#xA;&#xD;&#xA;		std::array&lt;VkDeviceQueueCreateInfo, 2&gt; queues_info = {graphics_queue_info, transfer_queue_info };&#xD;&#xA;&#xD;&#xA;		VkDeviceCreateInfo device_info = {};&#xD;&#xA;		device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;&#xD;&#xA;		device_info.queueCreateInfoCount = static_cast&lt;uint32_t&gt;(queues_info.size());&#xD;&#xA;		device_info.pQueueCreateInfos = queues_info.data();&#xD;&#xA;		device_info.enabledLayerCount = static_cast&lt;uint32_t&gt;(layers.size());&#xD;&#xA;		device_info.ppEnabledLayerNames = layers.data();&#xD;&#xA;&#xD;&#xA;		const std::array&lt;const char*, 2&gt; device_extensions = {&#xD;&#xA;			VK_KHR_SWAPCHAIN_EXTENSION_NAME&#xD;&#xA;		};&#xD;&#xA;		device_info.enabledExtensionCount = static_cast&lt;uint32_t&gt;(device_extensions.size());&#xD;&#xA;		device_info.ppEnabledExtensionNames = device_extensions.data();&#xD;&#xA;		device_info.pEnabledFeatures = NULL;&#xD;&#xA;&#xD;&#xA;		VkDevice device;&#xD;&#xA;		if (vkCreateDevice(physical_device, &amp;device_info, NULL, &amp;device) != VK_SUCCESS) {&#xD;&#xA;			std::cout &lt;&lt; DBG_IOS_WHERE &lt;&lt; &quot;failed to create device&quot; &lt;&lt; std::endl;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return device;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Both my graphics queue family index and transfer queue family index are the same and the Vulkan spec states :&#xD;&#xA;&gt; The queueFamilyIndex member of each element of pQueueCreateInfos must be unique within pQueueCreateInfos&#xD;&#xA;&#xD;&#xA;Is creating a separate transfer queue useless if a have already a working graphics queue ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22345" PostHistoryTypeId="1" PostId="8373" RevisionGUID="ddcb9c7d-590b-4f38-aaa6-fc0d963651d9" CreationDate="2018-12-07T12:39:54.153" UserId="8454" Text="Do I need separate Graphics and Transfer commands?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22346" PostHistoryTypeId="3" PostId="8373" RevisionGUID="ddcb9c7d-590b-4f38-aaa6-fc0d963651d9" CreationDate="2018-12-07T12:39:54.153" UserId="8454" Text="|c++|gpu|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22347" PostHistoryTypeId="2" PostId="8374" RevisionGUID="da32db77-bc32-4d78-b5a6-ce1113810889" CreationDate="2018-12-07T14:55:20.440" UserId="7462" Text="I have seen people using either vertices or triangles as a quick heuristic to estimate mesh memory usage and mesh rendering time.&#xD;&#xA;&#xD;&#xA;I always thought vertices were better, because the number of vertices processed in the vertex shader is known, whereas the number of fragments rendered varies depending on depth complexity, distance to the screen, area of the triangles....&#xD;&#xA;&#xD;&#xA;However it seems triangles are used just as often as vertices, if you need one to do a naive estimation, which one is better?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22348" PostHistoryTypeId="1" PostId="8374" RevisionGUID="da32db77-bc32-4d78-b5a6-ce1113810889" CreationDate="2018-12-07T14:55:20.440" UserId="7462" Text="Should you measure mesh complexity in triangles or vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22349" PostHistoryTypeId="3" PostId="8374" RevisionGUID="da32db77-bc32-4d78-b5a6-ce1113810889" CreationDate="2018-12-07T14:55:20.440" UserId="7462" Text="|geometry|mesh|performance|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22350" PostHistoryTypeId="2" PostId="8375" RevisionGUID="3812f268-1d9b-438f-8ea5-0453a2e9f033" CreationDate="2018-12-07T15:09:39.367" UserId="2654" Text="Your question seems... very confused. The &quot;challenge&quot; you tried to do specifically stated to &quot;use a different queue family specifically for transfer operations&quot;. But that's not what your code is trying to do; you used the same queue family.&#xD;&#xA;&#xD;&#xA;The point of creating a &quot;transfer queue&quot; is to allow you to perform transfer operations without having to submit them as part of another batch. `vkQueueSubmit` cannot be called on the same queue from multiple threads. So if one thread builds some transfer work, but the other thread is doing some graphics work, if you only have one queue then the two threads *must* have some communication mechanism to submit that work.&#xD;&#xA;&#xD;&#xA;If you have a transfer queue, that inter-thread communication is no longer necessary. Or at least, it is no longer necessary for the basic submission action. Obviously whichever batch of work that uses the results of the transfer commands will have to receive a semaphore to wait on from the thread that submitted the transfer work. But that is usually a less contentious inter-thread communication path, which can easily be done with a lockless queue of some kind.&#xD;&#xA;&#xD;&#xA;The challenge in question is specifically talking about a queue family that only has the `VK_QUEUE_TRANSFER_BIT` flag set (or more specifically, does not have graphics or compute capabilities). Such transfer-only queues are usually tied to specialized hardware that (potentially) perform transfers faster than a graphics queue, but likely with extra limitations (as defined in `VkQueueFamilyProperties::minImageTransferGranularity` and other properties).&#xD;&#xA;&#xD;&#xA;So basically, you're doing the challenge wrong.&#xD;&#xA;&#xD;&#xA;Do keep in mind that Vulkan does not require implementations to provide a transfer-only queue. So if you want to take advantage of the presence of such a queue, you also have to take into account the possibility that no such queue exists.&#xD;&#xA;&#xD;&#xA;Now, here's the thing: the term &quot;queue family&quot; is used because you can potentially get *multiple* queues from the same family. `VkQueueFamilyProperties::queueCount` tells you how many queues a particular family allows you to get.&#xD;&#xA;&#xD;&#xA;So if a GPU does not provide a dedicated transfer-only queue, but you still want the asynchronous benefits of submitting transfer operations outside of non-transfer work, you can create a second graphics queue.&#xD;&#xA;&#xD;&#xA;Of course, Vulkan *also* doesn't require implementations to provide more than one graphics or compute queue. So again, you have to have a synchronous fallback plan in case the hardware only provides you with one queue." ContentLicense="CC BY-SA 4.0" />
  <row Id="22351" PostHistoryTypeId="2" PostId="8376" RevisionGUID="2c64772f-a457-4d78-bb73-659024fc5795" CreationDate="2018-12-07T16:10:31.380" UserId="2654" Text="Vertex count may be more accurate of a measurement of &quot;mesh memory usage and mesh rendering time&quot;, but vertex count is not nearly as easily *measured*.&#xD;&#xA;&#xD;&#xA;Yes, given a specific mesh with all of its attributes, it's easy to tell how many vertices are in it. But how many modelling tools can tell an artist how many vertices a given mesh will produce?&#xD;&#xA;&#xD;&#xA;After all, the vertex count is usually based on the *topology* of the various attributes of a mesh. That topology changes when new positions are added or removed. That topology changes when texture coordinate vertices are added or removed. When smoothing groups are modified to create sharp edges. And so forth.&#xD;&#xA;&#xD;&#xA;Furthermore, most modelling tools can't really give an accurate vertex count anyway, since they usually don't store vertices in the fashion that the rendering application will use them in. They tend to store the vertices as individual arrays with individual array indices, which is typically not how the renderer will see them. So most modelling packages cannot tell the user what the vertex count is, outside of writing a plugin to provide that information.&#xD;&#xA;&#xD;&#xA;So if you're trying to communicate a limitation to artists, the easiest way to give them an approximation of what they have to work with is to provide a triangle count. Yes, the hard limit is the number of vertices, and the asset conditioning pipeline should certainly reject meshes/whatever that are too big for the available memory.&#xD;&#xA;&#xD;&#xA;But triangle count is more useful as a &quot;quick heuristic&quot; than vertex count." ContentLicense="CC BY-SA 4.0" />
  <row Id="22352" PostHistoryTypeId="2" PostId="8377" RevisionGUID="4d0a0021-be4b-4f32-b3e7-fa5da30964ed" CreationDate="2018-12-07T16:15:10.033" UserId="9812" Text="Since you're talking about &quot;vertex shaders&quot; and &quot;fragments&quot;, I assume that your question is to be interpreted in the context of real-time rendering using the graphics pipeline on a modern GPU through some modern graphics API. Even if we narrow down the question like that, I don't think a general answer can be given to what you're asking. It depends a lot on what kind of meshes/scenes/application you're dealing with. In general, it's not even clear what &quot;number of vertices&quot; or &quot;number of triangles&quot; should mean exactly. There isn't really *the* number of vertices and *the* number of triangles. If you're rendering a non-indexed triangle strip, then there's a direct relation between the number of vertices and the number of triangles. If you're rendering an indexed triangle list, then do we count the number of vertices that were referenced, the number of vertices that were shaded, or do we count the number of indices that were used to form triangles? If you're rendering patches with tessellation, then is the number of vertices the number of control points or is it the number of vertices produced by the tessellation? What if I have a geometry shader that eats a few points, and turns them into loads of overlapping triangles? What if my geometry shading streams the odd triangle to a stream output buffer but doesn't send anything to the rasterizer at all!? The point is, there's a great many different kinds of what one could call a &quot;vertex&quot; or a &quot;triangle&quot; that can pop up in different places in a graphics pipeline.&#xD;&#xA;&#xD;&#xA;In a typical triangle mesh that is supposed to represent the boundary surface of some physical object, there will be a [direct relationship][1] between the numbers of vertices and triangles (technically, you'd have to know two of either the number of vertices or edges or triangles, or the genus of the object). In such cases, either number of vertices or number of triangles is arguably as good a measure as the other when it comes to giving an estimate of mesh complexity.&#xD;&#xA;&#xD;&#xA;But then, what exactly &quot;complexity&quot; means is also not clearly defined. Complexity in terms of storage required can basically be estimated from either number of vertices or triangles as explained above. Complexity in terms of rendering time is a whole different story. Depending on your application, it could be that neither the number of triangles nor the number of vertices is a good predictor of performance, e.g, because your bottleneck is rasterization, fragment processing, or the framebuffer. In these cases, you'll be more interested, for example, in the number of fragments or depth complexity…&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/425968/eulers-formula-for-triangle-mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="22353" PostHistoryTypeId="5" PostId="8377" RevisionGUID="7938e91e-b47f-457e-b2b8-af55c901e88d" CreationDate="2018-12-07T16:23:20.117" UserId="9812" Comment="added 16 characters in body" Text="Since you're talking about &quot;vertex shaders&quot; and &quot;fragments&quot;, I assume that your question is to be interpreted in the context of real-time rendering using the graphics pipeline on a modern GPU through some modern graphics API. Even if we narrow down the question like that, I don't think a general answer can be given to what you're asking. It depends a lot on what kind of meshes/scenes/application you're dealing with. In general, it's not even clear what &quot;number of vertices&quot; or &quot;number of triangles&quot; should mean exactly. There isn't really *the* number of vertices and *the* number of triangles. If you're rendering a non-indexed triangle strip, then there's a direct relation between the number of vertices and the number of triangles. If you're rendering an indexed triangle list, then do we count the number of vertices that were referenced, the number of vertices that were shaded, or do we count the number of indices that were used to form triangles? If you're rendering patches with tessellation, then is the number of vertices the number of control points or is it the number of vertices produced by the tessellation? What if I have a geometry shader that eats a few points, and turns them into loads of overlapping triangles? What if my geometry shading streams the odd triangle to a stream output buffer but doesn't send anything to the rasterizer at all!? The point is, there's a great many different places in a graphics pipeline where something that one might call a &quot;vertex&quot; or a &quot;triangle&quot; could pop up…&#xD;&#xA;&#xD;&#xA;In a typical triangle mesh that is supposed to represent the boundary surface of some physical object, there will be a [direct relationship][1] between the numbers of vertices and triangles. In such cases, either number of vertices or number of triangles is arguably as good a measure as the other when it comes to giving an estimate of mesh complexity. But then, what exactly &quot;complexity&quot; means is also not clearly defined. Complexity in terms of storage required can basically be estimated from either number of vertices or triangles as explained above. Complexity in terms of rendering time is a whole different story. Depending on your application, it could be that neither the number of triangles nor the number of vertices is a good predictor of performance, e.g, because your bottleneck is rasterization, fragment processing, or the framebuffer. In these cases, you'll be more interested, for example, in the number of fragments or depth complexity…&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/425968/eulers-formula-for-triangle-mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="22354" PostHistoryTypeId="5" PostId="8377" RevisionGUID="d9ca06e4-89d5-47b1-9a25-8d0b979d86da" CreationDate="2018-12-07T16:30:31.920" UserId="9812" Comment="added 16 characters in body" Text="Since you're talking about &quot;vertex shaders&quot; and &quot;fragments&quot;, I assume that your question is to be interpreted in the context of real-time rendering using the graphics pipeline on a modern GPU through some modern graphics API. Even if we narrow down the question like that, I don't think a general answer can be given to what you're asking. It depends a lot on what kind of meshes/scenes/application you're dealing with. In general, it's not even clear what &quot;number of vertices&quot; or &quot;number of triangles&quot; should mean exactly. There isn't really *the* number of vertices and *the* number of triangles. If you're rendering a non-indexed triangle strip, then there's a direct relation between the number of vertices and the number of triangles. If you're rendering an indexed triangle list, then do we count the number of vertices that were referenced, the number of vertices that were shaded, or do we count the number of indices that were used to form triangles? If you're rendering patches with tessellation, then is the number of vertices the number of control points or is it the number of vertices produced by the tessellation? What if I have a geometry shader that eats a few points, and turns them into loads of overlapping triangles? What if my geometry shading streams the odd triangle to a stream output buffer but doesn't send anything to the rasterizer at all!? The point is, there's a great many different places in a graphics pipeline where something that one might call a &quot;vertex&quot; or a &quot;triangle&quot; could pop up…&#xD;&#xA;&#xD;&#xA;In a typical triangle mesh that is supposed to represent the boundary surface of some physical object, there will be a [direct relationship][1] between the numbers of vertices and triangles. In such cases, either the number of vertices or the number of triangles is arguably as good a measure as the other when it comes to giving an estimate of mesh complexity. But then, what &quot;complexity&quot; are we talking about exactly? Complexity in terms of storage can probably be estimated from either number of vertices or triangles as explained above. Complexity in terms of rendering time is a whole different story. Depending on your application, it might be that neither the number of triangles nor the number of vertices is a good predictor for performance at all. For example, because your bottleneck is rasterization, fragment processing, or the framebuffer. In such a case, you'd probably be more interested in the number of fragments produced, or the depth complexity…&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/425968/eulers-formula-for-triangle-mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="22355" PostHistoryTypeId="5" PostId="8377" RevisionGUID="09c6d0ca-60cc-420b-99b2-6f4662985917" CreationDate="2018-12-07T16:36:44.947" UserId="9812" Comment="added 16 characters in body" Text="Since you're talking about &quot;vertex shaders&quot; and &quot;fragments&quot;, I assume that your question is to be interpreted in the context of real-time rendering using the graphics pipeline on a modern GPU through some modern graphics API. Even if we narrow down the question like that, I don't think a general answer can be given to what you're asking. It depends a lot on what kind of meshes/scenes/application you're dealing with. In general, it's not even clear what &quot;number of vertices&quot; or &quot;number of triangles&quot; should mean exactly. There isn't really *the* number of vertices and *the* number of triangles. If you're rendering a non-indexed triangle strip, then there's a direct relation between the number of vertices and the number of triangles. If you're rendering an indexed triangle list, then do we count the number of vertices that were referenced, the number of vertices that were shaded, or do we count the number of indices that were used to form triangles? If you're rendering patches with tessellation, then is the number of vertices the number of control points or is it the number of vertices produced by the tessellation? What if I have a geometry shader that eats a few points, and turns them into loads of overlapping triangles? What if my geometry shading streams the odd triangle to a stream output buffer but doesn't send anything to the rasterizer at all!? The point is, there's a great many different places in a graphics pipeline where something that one might call a &quot;vertex&quot; or a &quot;triangle&quot; could pop up…&#xD;&#xA;&#xD;&#xA;In a typical triangle mesh that is supposed to represent the boundary surface of some physical object, there will be a [direct relationship][1] between the numbers of vertices and triangles. In such cases, either the number of vertices or the number of triangles is arguably as good a measure as the other when it comes to giving an estimate of mesh complexity. But then, what &quot;complexity&quot; are we talking about exactly? Complexity in terms of storage can probably be estimated from either number of vertices or triangles as explained above. Complexity in terms of rendering time is a whole different story. Depending on your application, it might be that neither the number of triangles nor the number of vertices is a good predictor for performance at all. It's actually trivial to write a program that makes even the latest and greatest graphics card sweat by rendering only a single triangle using no vertex buffer. For example, because your bottleneck is rasterization, fragment processing, or the framebuffer. In such a case, you'd probably be more interested in the number of fragments produced, or the depth complexity…&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/425968/eulers-formula-for-triangle-mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="22356" PostHistoryTypeId="5" PostId="8373" RevisionGUID="33d01f85-ef6b-463e-8333-03cbdd015b46" CreationDate="2018-12-07T20:01:06.580" UserId="8454" Comment="deleted 1657 characters in body" Text="I was following this tutorial on Vulkan https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer and I decided to do this bit:&#xD;&#xA;&#xD;&#xA;&gt; The buffer copy command requires a queue family that supports transfer operations, which is indicated using VK_QUEUE_TRANSFER_BIT. The good news is that any queue family with VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT capabilities already implicitly support VK_QUEUE_TRANSFER_BIT operations.&#xD;&#xA;&#xD;&#xA;&gt; The implementation is not required to explicitly list it in queueFlags in those cases.&#xD;&#xA;&gt; If you like a challenge, then you can still try to use a different queue family specifically for transfer operations. It will require you to make the following modifications to your program:&#xD;&#xA;&#xD;&#xA;&gt; - Modify QueueFamilyIndices and findQueueFamilies to explicitly look for a queue family with the VK_QUEUE_TRANSFER bit, but not the VK_QUEUE_GRAPHICS_BIT.&#xD;&#xA;&gt; - Modify createLogicalDevice to request a handle to the transfer queue&#xD;&#xA;&gt; - Create a second command pool for command buffers that are submitted on the transfer queue family&#xD;&#xA;&gt; - Change the sharingMode of resources to be VK_SHARING_MODE_CONCURRENT and specify both the graphics and transfer queue families&#xD;&#xA;&gt; - Submit any transfer commands like vkCmdCopyBuffer (which we'll be using in this chapter) to the transfer queue instead of the graphics queue&#xD;&#xA;&#xD;&#xA;&gt; It's a bit of work, but it'll teach you a lot about how resources are shared between queue families.&#xD;&#xA;&#xD;&#xA;Are there any benefits of using a second queue only for transfer operations ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22357" PostHistoryTypeId="2" PostId="8378" RevisionGUID="dcc657f1-a88e-45bc-b37f-60465447d1b8" CreationDate="2018-12-07T20:37:16.447" UserId="9778" Text="In what way is a &quot;cheat&quot; when using smooth shading on a sphere approximation? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Y3eQ0.png&#xD;&#xA;&#xD;&#xA;I'm not understanding how it's a cheat to use smooth shading on this?&#xD;&#xA;&#xD;&#xA;Other questions that are lead after this may be: &#xD;&#xA;Why does it look better than the Gouraud Shaded Model and why is this not necessary generally applicable to any surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22358" PostHistoryTypeId="1" PostId="8378" RevisionGUID="dcc657f1-a88e-45bc-b37f-60465447d1b8" CreationDate="2018-12-07T20:37:16.447" UserId="9778" Text="Smooth shading on sphere approximation" ContentLicense="CC BY-SA 4.0" />
  <row Id="22359" PostHistoryTypeId="3" PostId="8378" RevisionGUID="dcc657f1-a88e-45bc-b37f-60465447d1b8" CreationDate="2018-12-07T20:37:16.447" UserId="9778" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22366" PostHistoryTypeId="2" PostId="8380" RevisionGUID="1bcf9578-b9a7-4c0d-a34c-e8b6de87bd71" CreationDate="2018-12-08T09:29:41.833" UserId="113" Text="Sphere's don't have edges like the ones in that picture. The &quot;silhouette&quot; should be a circle. This is because the sphere was rendered as triangles and rasterized. Triangles can only approximate a sphere.&#xD;&#xA;&#xD;&#xA;Compare this to ray casting for instance. Where we can directly test the intersection between a sphere and ray thus no need to approximate a sphere with other primitives.&#xD;&#xA;&#xD;&#xA;What smooth shading lets us do is interpolate values across the face of a triangle to cheat and make something appear smoother. In reality a sphere (a uv sphere) would look like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;There are two common ways to make the above sphere look smooth without adding anymore geometry. Both of which involve interpolating values across the face of a triangle. Like barycentric interpolation. With barycentric interpolation, given values at 3 points (on a triangle) and a point we want to know the value for we can calculate a mix between the 3 values at the corners such that it smoothly varies across the face of the triangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In rasterization there are two popular ways to smooth shade. The later being used more often.&#xD;&#xA;&#xD;&#xA;Gouraud: We calculate the post-lighting (shaded) color at each vertex and interpolate the color across the face of the triangle.&#xD;&#xA;&#xD;&#xA;Phong: We calculate the shaded color at every pixel across the triangle, interpolating things like normals across the triangle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e3mf0.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/vqX5e.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22368" PostHistoryTypeId="10" PostId="8299" RevisionGUID="6e225ff6-7ea4-4e53-9c80-39dca59822db" CreationDate="2018-12-08T10:15:57.740" UserId="2041" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[5823],&quot;Voters&quot;:[{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="22371" PostHistoryTypeId="5" PostId="4753" RevisionGUID="bfea318f-f9f8-4563-872a-f0818f0931d2" CreationDate="2018-12-08T18:12:51.800" UserId="1831" Comment="Symbols now the classical ones in computer graphics, moved &quot;dot&quot; near word." Text="As far as I understand, radiance is a measure of the &quot;intensity&quot; of light in a direction defined as a differential cone . It's measure is Flux per solid angle per projected area.  $L = \frac{d\Phi}{d\omega dA^\perp} = \frac{d\Phi}{d\omega dAcos(\theta)} $. Using this definition, it seems like as the $\theta$ angle increases, radiance increases, thus light is somehow more &quot;intense&quot; in a direction nearly perpendicular to the normal at point p. This contradicts my intuition.  &#xD;&#xA;Where am I interpreting this wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22379" PostHistoryTypeId="2" PostId="8381" RevisionGUID="6efa8a6c-00e7-415c-b371-29817fcc771e" CreationDate="2018-12-09T11:48:44.637" UserDisplayName="user9436" Text="I was recently told [here](https://computergraphics.stackexchange.com/questions/8311/how-do-i-create-a-win32-window-with-a-vulkan-context) how to manage the integration between Vulkan and Win32.&#xD;&#xA;&#xD;&#xA;Usually when dealing with graphics APIs, you would tipically have a `SwapBuffers(Window)` function that switches between 2 or 3 buffers when the back buffers are ready to be presented.&#xD;&#xA;&#xD;&#xA;I am writing a windowing library like &quot;GLFW&quot;, that is only going to support Vulkan; I have now come to the point where I need to implement such function; I have tried to reverse engineer Glfw's `glfwSwapBuffers(GLFWWindow*)` function without success, and I was wondering how to do the same in my setup.&#xD;&#xA;&#xD;&#xA;P.S: The library is written in C" ContentLicense="CC BY-SA 4.0" />
  <row Id="22380" PostHistoryTypeId="1" PostId="8381" RevisionGUID="6efa8a6c-00e7-415c-b371-29817fcc771e" CreationDate="2018-12-09T11:48:44.637" UserDisplayName="user9436" Text="How do I swap the buffers when using a Win32 window with Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22381" PostHistoryTypeId="3" PostId="8381" RevisionGUID="6efa8a6c-00e7-415c-b371-29817fcc771e" CreationDate="2018-12-09T11:48:44.637" UserDisplayName="user9436" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22382" PostHistoryTypeId="5" PostId="8381" RevisionGUID="22420439-945f-4928-ae5e-32d3936c4b40" CreationDate="2018-12-09T13:00:30.603" UserDisplayName="user9436" Comment="deleted 89 characters in body" Text="I was recently told [here](https://computergraphics.stackexchange.com/questions/8311/how-do-i-create-a-win32-window-with-a-vulkan-context) how to manage the integration between Vulkan and Win32.&#xD;&#xA;&#xD;&#xA;I am writing a windowing library like &quot;GLFW&quot;, that is only going to support Vulkan; I have now come to the point where I need to implement `SwapBuffers(Window)` type of function; I have tried to reverse engineer Glfw's `glfwSwapBuffers(GLFWWindow*)` function to see how they implemented it in their framework, but I wasn't able to understand it fully.&#xD;&#xA;&#xD;&#xA;How do I &quot;swap the buffers&quot; in a Win32 window?&#xD;&#xA;&#xD;&#xA;P.S: The library is written in C" ContentLicense="CC BY-SA 4.0" />
  <row Id="22383" PostHistoryTypeId="5" PostId="8377" RevisionGUID="71614805-6c63-4c4a-b327-8075d373464e" CreationDate="2018-12-09T13:07:03.310" UserId="9812" Comment="edited body" Text="Since you're talking about &quot;vertex shaders&quot; and &quot;fragments&quot;, I assume that your question is to be interpreted in the context of real-time rendering using the graphics pipeline on a modern GPU through some modern graphics API. Even if we narrow down the question like that, I don't think a general answer can be given to what you're asking. It depends a lot on what kind of meshes/scenes/application you're dealing with. In general, it's not even clear what &quot;number of vertices&quot; or &quot;number of triangles&quot; should mean exactly. There isn't really *the* number of vertices and *the* number of triangles. If you're rendering a non-indexed triangle strip, then there's a direct relation between the number of vertices and the number of triangles. If you're rendering an indexed triangle list, then do we count the number of vertices that were referenced, the number of vertices that were shaded, or do we count the number of indices that were used to form triangles? If you're rendering patches with tessellation, then is the number of vertices the number of control points or is it the number of vertices produced by the tessellation? What if I have a geometry shader that eats a few points, and turns them into loads of overlapping triangles? What if my geometry shading streams the odd triangle to a stream output buffer but doesn't send anything to the rasterizer at all!? The point is, there's a great many different places in a graphics pipeline where something that one might call a &quot;vertex&quot; or a &quot;triangle&quot; could pop up…&#xD;&#xA;&#xD;&#xA;In a typical triangle mesh that is supposed to represent the boundary surface of some physical object, there will be a [direct relationship][1] between the numbers of vertices and triangles. In such cases, either the number of vertices or the number of triangles is arguably as good a measure as the other when it comes to giving an estimate of mesh complexity. But then, what &quot;complexity&quot; are we talking about exactly? Complexity in terms of storage can probably be estimated from either number of vertices or triangles as explained above. Complexity in terms of rendering time is a whole different story. Depending on your application, it might be that neither the number of triangles nor the number of vertices is a good predictor for performance at all. It's actually trivial to write a program that makes even the latest and greatest graphics card sweat by rendering only a single triangle using no vertex buffer. Because your bottleneck is rasterization, fragment processing, or the framebuffer, for example. In such a case, you'd probably be more interested in the number of fragments produced, or the depth complexity…&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/425968/eulers-formula-for-triangle-mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="22384" PostHistoryTypeId="2" PostId="8382" RevisionGUID="fe69456d-4cac-4842-9aea-dea04f8153d0" CreationDate="2018-12-09T13:34:20.380" UserId="9820" Text="I am trying to convert a ray hit on an infinite plane, defined by an origin and a normal vector, into UV coordinates, so I can find the appropriate texel at that point.&#xD;&#xA;&#xD;&#xA;Code I have is close to functional, however, when the plane has a normal of (0, 0, -1) the result is a plain white plane.&#xD;&#xA;&#xD;&#xA;The code that calculates the UV coordinates is pasted below:&#xD;&#xA;&#xD;&#xA;    // Calculate UV coordinates for the texture&#xD;&#xA;	vec3 u = vec3( normal.y, -normal.x, 0 ).normalized();&#xD;&#xA;	vec3 v = normal.cross( u );&#xD;&#xA;&#xD;&#xA;	h.u = u.dot( h.coordinates );&#xD;&#xA;	h.v = v.dot( h.coordinates );&#xD;&#xA;&#xD;&#xA;h is a Hit struct that stores relevant data from a ray-primitive intersection, coordinates is the vec3 where the intersection occurred.&#xD;&#xA;&#xD;&#xA;The current situation is shown in the following image; The floor plane properly shows the texture, however, the back wall does not.&#xD;&#xA;&#xD;&#xA;[![Example of current situation][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, when I change the normal of the back wall ever so slightly, the texture appears&#xD;&#xA;&#xD;&#xA;[![Situation with slightly changed normal][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mhRdL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IH1kH.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In image 1 the normal of the back plane was (0, 0, -1), while it was (0.0001, 0, -1) in the second image.&#xD;&#xA;&#xD;&#xA;I have been trying to figure this one out, but I am hitting a dead end." ContentLicense="CC BY-SA 4.0" />
  <row Id="22385" PostHistoryTypeId="1" PostId="8382" RevisionGUID="fe69456d-4cac-4842-9aea-dea04f8153d0" CreationDate="2018-12-09T13:34:20.380" UserId="9820" Text="How do I convert a hit on an infinite plane to UV coordinates for texturing in a Raytracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22386" PostHistoryTypeId="3" PostId="8382" RevisionGUID="fe69456d-4cac-4842-9aea-dea04f8153d0" CreationDate="2018-12-09T13:34:20.380" UserId="9820" Text="|raytracing|texture|uv-mapping|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22387" PostHistoryTypeId="2" PostId="8383" RevisionGUID="df43f278-ab5f-42c8-8b58-2bcdd8dfb89d" CreationDate="2018-12-09T14:46:35.987" UserId="2654" Text="&gt; I have now come to the point where I need to implement SwapBuffers(Window) type of function&#xD;&#xA;&#xD;&#xA;Then stop doing that. You need that function in OpenGL because the windowing code is explicitly not part of OpenGL, so to write cross-platform GL code, you need an encapsulation layer.&#xD;&#xA;&#xD;&#xA;That is *not* the case for Vulkan. While you still need a layer to *create* the window, handling the display, swap-chain images, and so forth is all *part* of the Vulkan API. The user's code should have complete and total control over this stuff; your abstraction layer need not be involved.&#xD;&#xA;&#xD;&#xA;Indeed, since Vulkan has no concept of a &quot;default framebuffer&quot;, there's no way for you to abstract away presentable images without user support. Just do what GLFW3 does in [its Vulkan support][1]: provide a cross-platform way for the user to create a Vulkan surface.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.glfw.org/docs/latest/group__vulkan.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22388" PostHistoryTypeId="2" PostId="8384" RevisionGUID="fa9fa55a-c876-483b-9b12-55130eebb138" CreationDate="2018-12-09T16:45:50.090" UserId="9812" Text="If your plane has a normal of $\begin{pmatrix}0 &amp; 0 &amp; z\end{pmatrix}^T$, then your computation&#xD;&#xA;&#xD;&#xA;    vec3 u = vec3( normal.y, -normal.x, 0 ).normalized();&#xD;&#xA;    vec3 v = normal.cross( u );&#xD;&#xA;&#xD;&#xA;will result in `u` and `v` both being $\begin{pmatrix}0 &amp; 0 &amp; 0\end{pmatrix}^T$.&#xD;&#xA;&#xD;&#xA;A more general approach would be, for example, to compute the cross product of your normal with each of the three base vectors and use whichever result happens to be the longest as your direction for `u`:&#xD;&#xA;&#xD;&#xA;    vec3 computePrimaryTexDir(vec3 normal)&#xD;&#xA;    {&#xD;&#xA;    	vec3 a = cross(normal, vec3(1, 0, 0));&#xD;&#xA;    	vec3 b = cross(normal, vec3(0, 1, 0));&#xD;&#xA;    &#xD;&#xA;    	vec3 min_ab = dot(b, b) &lt; dot(a, a) ? b : a;&#xD;&#xA;    &#xD;&#xA;    	vec3 c = cross(normal, vec3(0, 0, 1));&#xD;&#xA;    &#xD;&#xA;    	return normalize(dot(c, c) &lt; dot(min_ab, min_ab) ? c : min_ab);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    …&#xD;&#xA;&#xD;&#xA;        vec3 u = computePrimaryTexDir(normal);&#xD;&#xA;        vec3 v = cross(n, u);&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22389" PostHistoryTypeId="5" PostId="8384" RevisionGUID="54ec656b-592a-4e0f-8193-b20225e71b9c" CreationDate="2018-12-09T16:59:28.967" UserId="9812" Comment="added 2 characters in body" Text="If your plane has a normal of $\begin{pmatrix}0 &amp; 0 &amp; z\end{pmatrix}^T$, then your computation&#xD;&#xA;&#xD;&#xA;    vec3 u = vec3( normal.y, -normal.x, 0 ).normalized();&#xD;&#xA;    vec3 v = normal.cross( u );&#xD;&#xA;&#xD;&#xA;will result in `u` and `v` both being $\begin{pmatrix}0 &amp; 0 &amp; 0\end{pmatrix}^T$.&#xD;&#xA;&#xD;&#xA;A more general approach would be, for example, to compute the cross product of your normal with each of the three base vectors and use whichever result happens to be the longest as your direction for `u`:&#xD;&#xA;&#xD;&#xA;    vec3 computePrimaryTexDir(vec3 normal)&#xD;&#xA;    {&#xD;&#xA;    	vec3 a = cross(normal, vec3(1, 0, 0));&#xD;&#xA;    	vec3 b = cross(normal, vec3(0, 1, 0));&#xD;&#xA;    &#xD;&#xA;    	vec3 max_ab = dot(a, a) &lt; dot(b, b) ? b : a;&#xD;&#xA;    &#xD;&#xA;    	vec3 c = cross(normal, vec3(0, 0, 1));&#xD;&#xA;    &#xD;&#xA;    	return normalize(dot(max_ab, max_ab) &lt; dot(c, c) ? c : max_ab);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;      …&#xD;&#xA;&#xD;&#xA;        vec3 u = computePrimaryTexDir(normal);&#xD;&#xA;        vec3 v = cross(n, u);&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22390" PostHistoryTypeId="2" PostId="8385" RevisionGUID="c015695e-f4c7-4115-9171-3e98c3c0d511" CreationDate="2018-12-09T23:01:43.887" UserId="9697" Text="I'm looking for a way to make my surface semitransparent, and for now i ended up using this configuration:&#xD;&#xA;&#xD;&#xA;    eglChooseConfig(eglDisplay, new int[] {&#xD;&#xA;                EGL10.EGL_ALPHA_SIZE,   8,&#xD;&#xA;                EGL10.EGL_RED_SIZE,     8,&#xD;&#xA;                EGL10.EGL_GREEN_SIZE,   8,&#xD;&#xA;                EGL10.EGL_BLUE_SIZE,    8,&#xD;&#xA;                EGL10.EGL_NONE&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My default configuration was:&#xD;&#xA;&#xD;&#xA;    eglChooseConfig(eglDisplay, new int[] {&#xD;&#xA;                EGL10.EGL_RED_SIZE,     8,&#xD;&#xA;                EGL10.EGL_GREEN_SIZE,   8,&#xD;&#xA;                EGL10.EGL_BLUE_SIZE,    8,&#xD;&#xA;                EGL10.EGL_DEPTH_SIZE    16,&#xD;&#xA;                EGL10.EGL_NONE&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see, i added EGL_ALPHA_SIZE attribute and removed EGL_DEPTH_SIZE, since my application is a simple 2D drawing on a surface and it doesn't need a depth buffer. It works, but for some reason results in somewhat unexpected results for this simple fragment shader:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    uniform sampler2D uSampler;&#xD;&#xA;    varying vec2 vTextureCoord;&#xD;&#xA;    void main() {&#xD;&#xA;        vec4 originalColor = texture2D(uSampler, vTextureCoord);&#xD;&#xA;        gl_FragColor = originalColor + vec4(0, 0, 0, -0.5);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The alpha component seems to be affecting rest of the parts of the color and changes it at some extent. The first image below is the original one, second is what I have, and the last one is what I want to achieve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Original image][1]][1]&#xD;&#xA;[![What i have][2]][2]&#xD;&#xA;[![What i want to achieve][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any advice is appreciated, thanks!&#xD;&#xA;&#xD;&#xA;### For the sake of clarity&#xD;&#xA;OpenGL ES Version: 2.0&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FigTB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A6Pmq.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/WQwMt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22391" PostHistoryTypeId="1" PostId="8385" RevisionGUID="c015695e-f4c7-4115-9171-3e98c3c0d511" CreationDate="2018-12-09T23:01:43.887" UserId="9697" Text="Alpha component in color buffer affects RGB components?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22392" PostHistoryTypeId="3" PostId="8385" RevisionGUID="c015695e-f4c7-4115-9171-3e98c3c0d511" CreationDate="2018-12-09T23:01:43.887" UserId="9697" Text="|glsl|opengl-es|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22393" PostHistoryTypeId="50" PostId="8246" RevisionGUID="c9b43251-ab0b-4d0e-99fa-3fa6bac7b37b" CreationDate="2018-12-10T01:01:15.253" UserId="-1" />
  <row Id="22395" PostHistoryTypeId="5" PostId="8380" RevisionGUID="794963f1-3635-4104-b0b4-c2204c7baa31" CreationDate="2018-12-10T04:45:48.070" UserId="113" Comment="added 510 characters in body" Text="Sphere's don't have edges like the ones in that picture. The &quot;silhouette&quot; should be a circle. This is because the sphere was rendered as triangles and rasterized. Triangles can only approximate a sphere.&#xD;&#xA;&#xD;&#xA;Compare this to ray casting for instance. Where we can directly test the intersection between a sphere and ray thus no need to approximate a sphere with other primitives.&#xD;&#xA;&#xD;&#xA;What smooth shading lets us do is interpolate values across the face of a triangle to cheat and make something appear smoother. In reality a sphere (a uv sphere) would look like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;There are two common ways to make the above sphere look smooth without adding anymore geometry. Both of which involve linearly interpolating values across the face of a triangle. Like barycentric interpolation. With barycentric interpolation, given values at 3 points (on a triangle) and a point we want to know the value for we can calculate a mix between the 3 values at the corners such that it smoothly varies across the face of the triangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In rasterization there are two popular ways to smooth shade. The later being used more often.&#xD;&#xA;&#xD;&#xA;Gouraud: We calculate the post-lighting (shaded) color at each vertex and interpolate the color across the face of the triangle.&#xD;&#xA;&#xD;&#xA;Phong: We calculate the shaded color at every pixel across the triangle, interpolating things like normals across the triangle.&#xD;&#xA;&#xD;&#xA;EDIT: The difference between gouraud and phong is that gouraud assumes the color and light intensity change linearly with the normal. Whereas phong does not. For a simple light intensity = dot(normal, lightDir) = cos(angle between normal and lightDir) we can see the relationship between intensity and the normal is nonlinear. This can be well illustrated with the below image (see the seams on the specular highlight. This is the consequence of our linear interpolation):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e3mf0.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/vqX5e.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/2qmpn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22396" PostHistoryTypeId="2" PostId="8386" RevisionGUID="1357ee6e-bd84-4f91-a628-6c8c60704283" CreationDate="2018-12-10T06:28:04.183" UserId="3003" Text="It looks like you're drawing with pre-multiplied alpha. This means that the red, green, and blue channels have been multiplied by the alpha channel. So your shader should look more like this:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;    uniform sampler2D uSampler;&#xD;&#xA;    varying vec2 vTextureCoord;&#xD;&#xA;    void main() {&#xD;&#xA;        vec4 originalColor = texture2D(uSampler, vTextureCoord);&#xD;&#xA;        vec4 tempColor = originalColor + vec4(0, 0, 0, -0.5);&#xD;&#xA;        tempColor.rgb *=  tempColor.a;&#xD;&#xA;        gl_FragColor = tempColor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I believe you also need to set `glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)` to get the correct blending (and of course, `glEnable(GL_BLEND)`)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22397" PostHistoryTypeId="2" PostId="8387" RevisionGUID="c91672fd-05b4-4255-93e5-5e3e9687e75a" CreationDate="2018-12-10T07:31:16.820" UserId="9822" Text="I've read about Lagrangian and Eulerian fluid simulations and here's what I take from their methods:&#xD;&#xA;&#xD;&#xA;1. Lagrangian - Simulating fluid particles by calculating displacement for each particle&#xD;&#xA;2. Eulerian - Simulating fluid particles by calculating interactions between finite spaces containing group of fluid particles.&#xD;&#xA;&#xD;&#xA;(?) Do each method have different rendering technique suitable for it?&#xD;&#xA;&#xD;&#xA;My guess is that you can take the finite space or 'voxel' data for Eulerian simulation, but I would like an expert's say in my hypothesis.&#xD;&#xA;&#xD;&#xA;(?) Also regarding MPM (Material Point Method) which is a hybrid of both worlds, if Lagrangian and Eulerian sims **does** have different rendering technique, does it mean that I can use either techniques? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22398" PostHistoryTypeId="1" PostId="8387" RevisionGUID="c91672fd-05b4-4255-93e5-5e3e9687e75a" CreationDate="2018-12-10T07:31:16.820" UserId="9822" Text="Rendering Fluid Simulations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22399" PostHistoryTypeId="3" PostId="8387" RevisionGUID="c91672fd-05b4-4255-93e5-5e3e9687e75a" CreationDate="2018-12-10T07:31:16.820" UserId="9822" Text="|rendering|3d|fluid-sim|theory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22401" PostHistoryTypeId="50" PostId="7804" RevisionGUID="1a7ac23f-f621-4119-8809-edfbbe124389" CreationDate="2018-12-10T14:02:25.483" UserId="-1" />
  <row Id="22405" PostHistoryTypeId="2" PostId="8389" RevisionGUID="7a3bf57f-7612-4f03-8c03-73275c402db9" CreationDate="2018-12-10T19:43:14.067" UserId="9825" Text="I'd like to create a GUI in my first Unity-game (2D). I want my GUI appear sharp in all resolutions (e.g. 1920x1200 or 3840x2160).&#xD;&#xA;&#xD;&#xA;The problem I am facing now is that I don't know if I should save my bitmap-images of my GUI in the highest resolution (so that it scales down when my game is played with a lower resolution) or should I use SVGs instead.&#xD;&#xA;&#xD;&#xA;This may be a stupid question but it's the first time that I create a GUI in Unity and I'm really struggling with this kind of problem..." ContentLicense="CC BY-SA 4.0" />
  <row Id="22406" PostHistoryTypeId="1" PostId="8389" RevisionGUID="7a3bf57f-7612-4f03-8c03-73275c402db9" CreationDate="2018-12-10T19:43:14.067" UserId="9825" Text="Bitmap-images or SVG" ContentLicense="CC BY-SA 4.0" />
  <row Id="22407" PostHistoryTypeId="3" PostId="8389" RevisionGUID="7a3bf57f-7612-4f03-8c03-73275c402db9" CreationDate="2018-12-10T19:43:14.067" UserId="9825" Text="|image|unity|bitmap-graphics|gui|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22408" PostHistoryTypeId="2" PostId="8390" RevisionGUID="4e152047-3d74-4f73-aacb-dfc90032d0c2" CreationDate="2018-12-10T20:46:33.053" UserId="2041" Text="Neither of your suggestions is a solution for crisp 2D graphics at all resolutions. SVGs are great and infinitely scalable, but since you don't know where the pixel boundaries will lie in the final render, you can't get crisp edges at all resolutions. For example, say your GUI is a red box on a green background. If the edge between the red and the green falls in the middle of a pixel, and the SVG renderer does anti-aliasing, you'll get a row or column of half-red, half-green pixels, which will look like mush. If the renderer doesn't anti-alias, you instead get the edge in the wrong place, which might be fine for a single rectangle, but for a repeating pattern each instance of the pattern might come out a different width, which is just as noticeable.&#xD;&#xA;&#xD;&#xA;Downscaling a bitmap to the display resolution is just as bad. Again, imagine your green-red edge is on a pixel boundary that will not be a pixel boundary in the downscaled bitmap. You're again going to get a row or column of pixels that are a mushy red-green mix. The lowest resolutions are the most important to have crisp edges, but they're going to be the worst-affected.&#xD;&#xA;&#xD;&#xA;You can make either one of these techniques work somewhat, if you can accept a restriction: instead of handling *any* resolution, you're willing to handle a set of resolutions, ideally powers of two apart (e.g. icon sizes of 512x512, 256x256, 128x128, etc.) When you're designing your UI, draw a large bitmap (512x512) or a vector image, but use guides in your editor to show the minimum size (e.g. 64x64). Make sure all your important edges line up with those guides, but you can still use curves, gradients etc. That way, you know you won't get the blurry mush at low resolutions, but you can still get the benefit of smooth diagonals and curves at high resolutions. This is a quick way to design scalable UI.&#xD;&#xA;&#xD;&#xA;Mobile OSes (which are designed for a range of screen dpis) use a similar technique, but with two differences. First, they &quot;bucket&quot; the screen's actual dpi to the nearest &quot;standard&quot; dpi. This means a UI might show slightly larger or smaller on different screens, but you know exactly how many pixels will be in each icon or widget. To make this work out, they don't limit the resolutions to powers of two, but have some intermediate ones as well.&#xD;&#xA;&#xD;&#xA;Second, they let designers specify a different bitmap for each resolution. This means that you can make a higher-detail design for a higher-dpi screen, without it being too busy on a low-dpi screen. (For example, you can use a fine checkerboard or ruler pattern, and have it show up correctly at each resolution.) You could consider doing this too, but it makes designing and managing the bitmap assets a little more time-consuming.&#xD;&#xA;&#xD;&#xA;If your buckets are powers of two apart, you can use mipmaps to store the images (instead of using the built-in mipmap generation), whether you're creating different images for each resolution or just downscaling. That way you avoid the runtime memory bandwidth cost of downscaling." ContentLicense="CC BY-SA 4.0" />
  <row Id="22413" PostHistoryTypeId="2" PostId="8392" RevisionGUID="bd9acbb3-e254-4ca6-9881-c1f32c264c92" CreationDate="2018-12-11T16:58:24.220" UserId="7462" Text="I have created a closed 3D mesh using a parametric function. The shape is constructed by taking an arbitrary closed b-spline and scaling it based on one of the parameters (similar idea to a parametric sphere, except that rather than drawing circles it's a b-spline)&#xD;&#xA;&#xD;&#xA;My current problem is, although I can generate the geometry of the shape just fine, it often results in thin triangles for many shapes. And these thin triangles in turn lead to numerical errors when trying to compute the normal to the triangles that make up the shape.&#xD;&#xA;&#xD;&#xA;An easy way to avoid having thing triangles is just to just decrease the number of samples you do along the parameters.&#xD;&#xA;&#xD;&#xA;e.g you can do 20 calculation steps along both u and v, or you can do 100.&#xD;&#xA;&#xD;&#xA;More samples usually leads to thicker triangles in almost every parametric shape.&#xD;&#xA;The issue of doing it this way is that I also increase the triangle and vertex count.&#xD;&#xA;&#xD;&#xA;Assuming I cannot modify the mesh once it is generated, is there a way to sample the parametrization such that I can get thicker triangles with few samples?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22414" PostHistoryTypeId="1" PostId="8392" RevisionGUID="bd9acbb3-e254-4ca6-9881-c1f32c264c92" CreationDate="2018-12-11T16:58:24.220" UserId="7462" Text="How can you avoid thin triangles in a parametric shape in a smart way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22415" PostHistoryTypeId="3" PostId="8392" RevisionGUID="bd9acbb3-e254-4ca6-9881-c1f32c264c92" CreationDate="2018-12-11T16:58:24.220" UserId="7462" Text="|mathematics|geometry|computational-geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22420" PostHistoryTypeId="5" PostId="8392" RevisionGUID="3bebe36d-62d0-4649-a06b-b963f830198c" CreationDate="2018-12-12T15:35:39.527" UserId="7462" Comment="deleted 1 character in body" Text="I have created a closed 3D mesh using a parametric function. The shape is constructed by taking an arbitrary closed b-spline and scaling it based on one of the parameters (similar idea to a parametric sphere, except that rather than drawing circles it's a b-spline)&#xD;&#xA;&#xD;&#xA;My current problem is, although I can generate the geometry of the shape just fine, it often results in thin triangles for many shapes. And these thin triangles in turn lead to numerical errors when trying to compute the normal to the triangles that make up the shape.&#xD;&#xA;&#xD;&#xA;An easy way to avoid having thin triangles is just to just increase the number of samples you do along the parameters.&#xD;&#xA;&#xD;&#xA;e.g you can do 20 calculation steps along both u and v, or you can do 100.&#xD;&#xA;&#xD;&#xA;More samples usually leads to thicker triangles in almost every parametric shape.&#xD;&#xA;The issue of doing it this way is that I also increase the triangle and vertex count.&#xD;&#xA;&#xD;&#xA;Assuming I cannot modify the mesh once it is generated, is there a way to sample the parametrization such that I can get thicker triangles with few samples?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22421" PostHistoryTypeId="2" PostId="8395" RevisionGUID="247a0873-7944-45b2-a476-46dfebd5c072" CreationDate="2018-12-13T13:22:47.690" UserId="9844" Text="I have to draw cubes with faces of different colors (each per face), but I don't know how to accomplish this task: I draw cubes using CPU and GPU meshes (no vertexBuffer or three.js &quot;style&quot;) and I don't know how to assign to each vertex different colors (I don't even know if this is possible).&#xD;&#xA;I can upload my code to GitHub if my problem isn't clear enough, let me know.&#xD;&#xA;All of this is coded in JavaScript and WebGL." ContentLicense="CC BY-SA 4.0" />
  <row Id="22422" PostHistoryTypeId="1" PostId="8395" RevisionGUID="247a0873-7944-45b2-a476-46dfebd5c072" CreationDate="2018-12-13T13:22:47.690" UserId="9844" Text="How can I make a cube with faces of different colors? Webgl" ContentLicense="CC BY-SA 4.0" />
  <row Id="22423" PostHistoryTypeId="3" PostId="8395" RevisionGUID="247a0873-7944-45b2-a476-46dfebd5c072" CreationDate="2018-12-13T13:22:47.690" UserId="9844" Text="|webgl|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22424" PostHistoryTypeId="2" PostId="8396" RevisionGUID="3472683e-df5a-42b2-8af0-4ca1d1af7324" CreationDate="2018-12-14T09:26:59.430" UserId="9194" Text="There are many tutorials covering this - Google is your friend. Maybe [this][1] covers your demands?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jameshfisher.com/2017/10/21/webgl-cube.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22425" PostHistoryTypeId="2" PostId="8397" RevisionGUID="fa11578a-e50b-453b-9574-dd6521211d11" CreationDate="2018-12-14T21:13:45.380" UserId="9853" Text="My 2 cents from writting the Chipmunk2D physics engine is that spatial hashing is great when you have a lot of objects that are all the same size. I had a demo 10 years ago that ran with 20k interacting particles on a Core 2 Duo in real time. The spatial hash worked great for that *if you tuned it*.&#xD;&#xA;&#xD;&#xA;I've since replaced the spatial hash with a binary AABB tree as the the default structure. It's far from perfect, but it was faster than the spatial hash in the average case *with no tuning*. It also was easier to add a temporal component to it so I could incrementally update a set of potential collisions. With all of that in place, the *only* test I had that ran faster with the spatial hash were the ones with thousands of particles and no static geometry.&#xD;&#xA;&#xD;&#xA;As for octrees... Meh, I never use them. Basic quad/octrees don't rarely real data as well as the plethora of other BVHs you can use. Basic AABB trees are nearly as simple, and *way* more effective." ContentLicense="CC BY-SA 4.0" />
  <row Id="22426" PostHistoryTypeId="50" PostId="5996" RevisionGUID="aad6749f-8b5a-4475-9cb9-ddbaa4f847b1" CreationDate="2018-12-15T10:03:40.757" UserId="-1" />
  <row Id="22427" PostHistoryTypeId="2" PostId="8398" RevisionGUID="26674234-b077-453d-823c-155d39aed72c" CreationDate="2018-12-15T15:27:51.600" UserId="9855" Text="I had a z-fighting/z-clipping issue with a scene containing some very large objects yesterday in 3ds max. It can be seen in the image below:&#xD;&#xA;[![z-fighting issue][1]][1]&#xD;&#xA;&#xD;&#xA;For some reason downscaling the scene significantly (a factor of 100 approx) resolves the z-fighting issues... **Please help me understand how reducing scene scale could resolve this issue and why this issue only occurs with very large scenes/objects.**&#xD;&#xA;&#xD;&#xA;From what i understand z-fighting occurs in this case because the near and far planes are very far apart compared to the minimum and maximum distance of the rendered object(s) relative to the viewport. &#xD;&#xA;&#xD;&#xA;Please correct me if I'm wrong, **my basic understanding of the z-buffer is as follows:**&#xD;&#xA;&#xD;&#xA;**1)** The distance of each rendered pixel of the object(s) is compared to a standard value stored in the z-buffer. &#xD;&#xA;&#xD;&#xA;**2)** if the depth of the current pixel is smaller than the currently stored value for this pixel location in this image...the value for this pixel in the z-buffer is overwritten with the new and lower value.&#xD;&#xA;&#xD;&#xA;**3)** before the z-depth value is stored in the z-buffer it is divided by a certain value (floating point type value), not sure why the number is devided. perhaps to reduce memory usage by storing smaller values...&#xD;&#xA;&#xD;&#xA;I managed to fix the z-fighting in the viewports by increasing the near plane (in viewport settings) from 0.1 ish to a larger value. &#xD;&#xA;&#xD;&#xA;Please take a look at the image below:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;The red planes are the camera's near and far planes. The green planes I have drawn myself and they indicate the minimum distance of the object relative to the camera and the maximum distance of the object relative to the camera. When scaling the scene by a factor x **the ratio between the variables A,B,C,D** (please see the dimensions drawn in the image) **should stay approximately the same** (as in the ratios A/B , A/C, A/D, B/A etc. should be approximately equal before and after the scaling process takes place).&#xD;&#xA;Therefore the max and min depth relative to the near and far viewport planes should be approximately equal. And as a result the depth precision of the object should not change when scaling (I think). &#xD;&#xA;My understanding is clearly incorrect since the z-fighting disappears when downscaling. **Why is it that scaling has any effect on the z-fighting?** Does 3ds max automatically adjust the far and near plane distances relative to the viewport when scaling the object/scene?&#xD;&#xA;&#xD;&#xA;I've read about something called depth precision (https://developer.nvidia.com/content/depth-precision-visualized). Assuming this  (objects(their pixels) that are closer to the camera being stored more accurately in the z-buffer) is true in 3ds max it makes sense that when zooming in really close to the object in the viewport...the z-fighting disappears. however, when I zoom out quite a lot in the viewport, the z-fighting also isn't visible anymore even though it should in my mind get worse since the precision of the depth info stored in the z-buffer is lower for objects further away from the camera. Am I missing something ?&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;PS: the viewport clipping distances are set to the default in the image below and the first image of this post.&#xD;&#xA;&#xD;&#xA;If I have been unclear or incomplete about anything please let me know and I will try my best to explain/elaborate. Any help will be greatly appreciated. Thank you very much!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/byoar.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bqUux.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4hCPb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22428" PostHistoryTypeId="1" PostId="8398" RevisionGUID="26674234-b077-453d-823c-155d39aed72c" CreationDate="2018-12-15T15:27:51.600" UserId="9855" Text="3ds max: Z-fighting when working with Large Objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="22429" PostHistoryTypeId="3" PostId="8398" RevisionGUID="26674234-b077-453d-823c-155d39aed72c" CreationDate="2018-12-15T15:27:51.600" UserId="9855" Text="|3d|projections|shading|depth-map|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22433" PostHistoryTypeId="50" PostId="7529" RevisionGUID="05bbc7a5-0296-4bbe-89b8-41fafa400552" CreationDate="2018-12-15T23:03:40.700" UserId="-1" />
  <row Id="22439" PostHistoryTypeId="50" PostId="8260" RevisionGUID="a807bf3a-cb39-4a67-90d9-62478201dbe2" CreationDate="2018-12-16T23:02:20.520" UserId="-1" />
  <row Id="22440" PostHistoryTypeId="33" PostId="8297" RevisionGUID="51001bb1-1392-4e63-b502-183d4fcfcb9f" CreationDate="2018-12-17T04:03:21.507" UserId="9256" Comment="53" />
  <row Id="22441" PostHistoryTypeId="2" PostId="8400" RevisionGUID="2872e13c-8fd9-40bc-a694-e3ec1265fac2" CreationDate="2018-12-17T09:49:35.697" UserId="113" Text="Here's a more complete answer from the extent of my knowledge. A sort of brief overview you can google more about. I'm sure I didn't cover all the different techniques but most branch off the mentioned ones. Note: if it's a liquid we are more concerned with getting an accurate surface representation.&#xD;&#xA;&#xD;&#xA; - Surface Extraction Methods: The most common way would be to rasterize the particles into a 3d image/grid using a basis function, unless they're already in a grid. Then extract the polygonal surface from the image using marching cubes or some variant of it. Then render that polygon. There are some methods to extract polygonal surfaces directly from particles without rasterizing.&#xD;&#xA;&#xD;&#xA; - Ray Marching with an Implicit Surface: Again we rasterize the particles into an image but quickly convert into an implicit surface in our 3d image then ray march render the implicit surface, very fast.&#xD;&#xA;&#xD;&#xA; - Splat Volume Rendering (doing it in screen space): Splatting is good for visualizing extremely large datasets and used to be used a lot for volume rendering because of how fast it is. Basic idea is to rasterize all or most points as discs from the volume. You can do many effects, lighting, etc. Nvidia's screen space fluids is a form of this (SSF). Simple, fast, quality is acceptable for many cases.&#xD;&#xA;&#xD;&#xA; - Slicing/Texture Based Volume Rendering: Here we overlay 2d semi transparent images. You can just overlay some precomputed textures on various particles or compute a series of sliced 2d images a set distance apart in the 3d image/volume given the camera angle. More expensive. Gives better results than splatting.&#xD;&#xA;&#xD;&#xA; - Ray cast Volume Rendering: Similar to ray marching, we march along the ray from every pixel but instead of looking for an implicitly defined surface we sample the volume directly and map it too color and transparency then composite it back along the ray. For lighting we can do it similar to surface based rendering but use the gradient of the image as the normal. There are many other tricks.&#xD;&#xA;&#xD;&#xA; - Ray traced Volume Rendering: Basically the same as the ray casting but we bounce the rays around inside of the volume. They're distributed according to a phase function. I'm sure all the clouds in your favorite animated movies were rendered this way. Disney did this for their MPM simulated Snow in Frozen. The ray tracing approach is the most expensive of all of them, more expensive then surface based ray tracing. Not for real time as of writing this.&#xD;&#xA;&#xD;&#xA;Note: The first two methods aren't for gasses. The last 3 are best for gasses due to they're lack of surface representation.&#xD;&#xA; &#xD;&#xA;I think it's also worth noting the value of having a stored representation for post processing effects. For manual deformations or effects by an artist. Procedural effects like spray, foam, bubbles, etc. Or just some extra geometric processing (smoothing or whatever)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22442" PostHistoryTypeId="2" PostId="8401" RevisionGUID="6eee9f21-b394-476a-a63a-389fec73b1e6" CreationDate="2018-12-17T10:36:46.737" UserId="9864" Text="This might sound stupid for you but I really don't know how it works in the domain of 3d animation and motion capture, but I need to work with ASF/AMC files at the moment and I find it a little bit complex to understand (being a non-native english speaker does not help).&#xD;&#xA;&#xD;&#xA;So the question is, why motion captures main file types don't use simple joint coordinates for the skeleton? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22443" PostHistoryTypeId="1" PostId="8401" RevisionGUID="6eee9f21-b394-476a-a63a-389fec73b1e6" CreationDate="2018-12-17T10:36:46.737" UserId="9864" Text="Why MOCAP data don't use simple point coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22444" PostHistoryTypeId="3" PostId="8401" RevisionGUID="6eee9f21-b394-476a-a63a-389fec73b1e6" CreationDate="2018-12-17T10:36:46.737" UserId="9864" Text="|motion|capture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22445" PostHistoryTypeId="2" PostId="8402" RevisionGUID="d768367c-cf6d-48e0-b993-1287b5eceabd" CreationDate="2018-12-17T18:14:33.213" UserId="5664" Text="Considering the fact that Vulkan and DX12 delegate most of the memory management / work scheduling tasks to the application itself, how much do drivers affect performance?&#xD;&#xA;&#xD;&#xA;To put my question into context, people on the internet talk a lot about NVIDIA drivers being more finely tuned and optimized (especially for the most popular games) compared to AMD drivers. Now that DX12/Vulkan are becoming more common, is it safe to assume that AMD video cards will become more competitive even if they have less optimized drivers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22446" PostHistoryTypeId="1" PostId="8402" RevisionGUID="d768367c-cf6d-48e0-b993-1287b5eceabd" CreationDate="2018-12-17T18:14:33.213" UserId="5664" Text="How much does driver quality affect Vulkan and DX12 compared to OpenGL and DX11?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22447" PostHistoryTypeId="3" PostId="8402" RevisionGUID="d768367c-cf6d-48e0-b993-1287b5eceabd" CreationDate="2018-12-17T18:14:33.213" UserId="5664" Text="|gpu|vulkan|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22448" PostHistoryTypeId="2" PostId="8403" RevisionGUID="1a992550-19ca-47ee-8502-bf73b2542cb7" CreationDate="2018-12-17T19:49:14.200" UserId="9306" Text="TL;DR:  There's some room for optimization in Vulkan drivers, but not nearly to the degree that there is in GL / DX11 drivers.&#xD;&#xA;&#xD;&#xA;&gt; how much do drivers affect performance?&#xD;&#xA;&#xD;&#xA;It depends a great deal on how the application is written and the hardware.  Specifically it depends on whether you're using features where there are large opportunities for optimization on the driver side. &#xD;&#xA;&#xD;&#xA;For example, if an application is written to take full advantage of renderpass subpasses and properly specifies the subpass dependencies and properly sets up transient attachments for intermediate work, then the difference between an extremely naive Vulkan driver and a well written one could easily be an order of magnitude.  But at the same time, this is basically the difference between naive client code and well written code both running on a well written driver.  &#xD;&#xA;&#xD;&#xA;&gt; people on the internet talk a lot about NVIDIA drivers being more finely tuned and optimized (especially for the most popular games) &#xD;&#xA;&#xD;&#xA;This isn't just a matter of driver tuning.  It's arguably a form of cheating.  It's pretty well known that in the case of certain AAA games, nVidia will actually swap out functionality from the game with baked functionality from it's own drivers, doing things like swapping out shaders that were bundled in the game with their own customized shaders, or toggling internal flags that conventional developers have no access to.  &#xD;&#xA;&#xD;&#xA;The problem is that DX11 and GL are both very old APIs with lots of legacy functionality.  Their very design in some places is at odds with modern GPU hardware, especially in the area of bundling individual commands together before actually sending them to be executed.  This is why all modern APIs like Metal, Vulkan and DX12 have the concept of a command buffer or batch.  So that the developer can actually be involved in the process of bundling lots of small bind and draw commands together in a logical way.  Older API's like OpenGL have to guess at where the command buffer boundaries should be and (one assumes) drivers tend to have a variety of strategies for doing this depending on how the client application is calling functions.  &#xD;&#xA;&#xD;&#xA;This is where the driver level optimizations come in, where nVidia or AMD can look at how a given game is calling functions and decide that strategy A is better than the strategy B (the one that driver version X is using), and so they release driver X + 1, and it forces the use of strategy A, or even a new strategy C that they came up with for this specific game.&#xD;&#xA;&#xD;&#xA;The end result is that OpenGL (and I assume DX &lt; 12) drivers end up being _monstrously_ complex, not just because of the enormous amount of legacy functionality they have to support, but also because of this per-game baggage that they accumulate (although I suspect that such per-game baggage has some kind of finite lifetime.... no one is going to be benchmarking a RTX 2080 with Battlefield 1942).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22449" PostHistoryTypeId="2" PostId="8404" RevisionGUID="70343ae4-71c4-428d-9bc5-1a50b83525f7" CreationDate="2018-12-17T22:31:10.937" UserId="9869" Text="With GPU isolation : multiple processes use the single GPU will be serialized, cause OOM easily" ContentLicense="CC BY-SA 4.0" />
  <row Id="22450" PostHistoryTypeId="1" PostId="8404" RevisionGUID="70343ae4-71c4-428d-9bc5-1a50b83525f7" CreationDate="2018-12-17T22:31:10.937" UserId="9869" Text="What does GPU serialized mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22451" PostHistoryTypeId="3" PostId="8404" RevisionGUID="70343ae4-71c4-428d-9bc5-1a50b83525f7" CreationDate="2018-12-17T22:31:10.937" UserId="9869" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22452" PostHistoryTypeId="5" PostId="8404" RevisionGUID="9fa36c4f-c061-4a64-aebf-d78cf5571cf7" CreationDate="2018-12-17T23:27:26.600" UserId="9869" Comment="added 131 characters in body; added 16 characters in body" Text="With GPU isolation : multiple processes use the single GPU will be serialized, cause OOM easily&#xA;link&#xA;https://www.slideshare.net/mobile/Hadoop_Summit/deep-learning-on-yarn-running-distributed-tensorflow-etc-on-hadoop-cluster-v3&#xA;slide number 17" ContentLicense="CC BY-SA 4.0" />
  <row Id="22458" PostHistoryTypeId="5" PostId="8400" RevisionGUID="a000c9a7-6924-4939-bb09-70976fb09b89" CreationDate="2018-12-18T08:01:33.587" UserId="113" Comment="deleted 2 characters in body" Text="Here's a more complete answer from the extent of my knowledge. A sort of brief overview you can google more about. I'm sure I didn't cover all the different techniques but most branch off the mentioned ones. Note: if it's a liquid we are more concerned with getting an accurate surface representation.&#xD;&#xA;&#xD;&#xA; - Surface Extraction Methods: The most common way would be to rasterize the particles into a 3d image/grid using a basis function, unless they're already in a grid. Then extract the polygonal surface from the image using marching cubes or some variant of it. Then render that polygon. There are some methods to extract polygonal surfaces directly from particles without rasterizing.&#xD;&#xA;&#xD;&#xA; - Ray Marching with an Implicit Surface: Again we rasterize the particles into an image but quickly convert into an implicit surface in our 3d image then ray march render the implicit surface, very fast.&#xD;&#xA;&#xD;&#xA; - Splat Volume Rendering (doing it in screen space): Splatting is good for visualizing extremely large datasets and used to be used a lot for volume rendering because of how fast it is. Basic idea is to rasterize all or most points as discs from the volume. You can do many effects, lighting, etc. Nvidia's screen space fluids is a form of this (SSF). Simple, fast, quality is acceptable for many cases.&#xD;&#xA;&#xD;&#xA; - Slicing/Texture Based Volume Rendering: Here we overlay 2d semi transparent images. You can just overlay some precomputed textures on various particles or compute a series of sliced 2d images a set distance apart in the 3d image/volume given the camera angle. More expensive. Gives better results than splatting.&#xD;&#xA;&#xD;&#xA; - Ray cast Volume Rendering: Similar to ray marching, we march along the ray from every pixel but instead of looking for an implicitly defined surface we sample the volume directly and map it too color and transparency then composite it back along the ray. For lighting we can do it similar to surface based rendering but use the gradient of the image as the normal. There are many other tricks.&#xD;&#xA;&#xD;&#xA; - Ray traced Volume Rendering: Basically the same as the ray casting but we bounce the rays around inside of the volume. They're distributed according to a phase function. I'm sure all the clouds in your favorite animated movies were rendered this way. Disney did this for their MPM simulated Snow in Frozen. The ray tracing approach is the most expensive of all of them, more expensive then surface based ray tracing. Not for real time as of writing this.&#xD;&#xA;&#xD;&#xA;Note: The first two methods aren't for gasses. The last 3 are best for gasses due to their lack of surface representation.&#xD;&#xA; &#xD;&#xA;I think it's also worth noting the value of having a stored representation for post processing effects. For manual deformations or effects by an artist. Procedural effects like spray, foam, bubbles, etc. Or just some extra geometric processing (smoothing or whatever)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22459" PostHistoryTypeId="2" PostId="8406" RevisionGUID="83315f69-d15b-4b9a-b590-6bdc1b0fc51a" CreationDate="2018-12-18T08:33:28.627" UserId="3003" Text="It's saying that if you're using a single GPU, the multiple processes attempting to use the GPU will be queued up and run one at a time rather than some or all being run in parallel. If you have multiple GPUs some of the processes can be run at the same time." ContentLicense="CC BY-SA 4.0" />
  <row Id="22461" PostHistoryTypeId="5" PostId="8401" RevisionGUID="69d0d78e-49cd-4aab-85da-334668a0b2b8" CreationDate="2018-12-18T16:16:34.870" UserId="9864" Comment="added 403 characters in body" Text="This might sound stupid for you but I really don't know how it works in the domain of 3d animation and motion capture, but I need to work with ASF/AMC files at the moment and I find it a little bit complex to understand (being a non-native english speaker does not help).&#xD;&#xA;&#xD;&#xA;So the question is, why motion captures main file types don't use simple joint coordinates for the skeleton? &#xD;&#xA;&#xD;&#xA;Edit: I am particularly thinking about Acclaim ASF/AMC format mainly because I need to use it with an imlementation of an algorithm that use joint vertex positions and deltas from initial position for the motion part. Having looked at how the data are represented it makes more sense to me to represent skeletons as joint vertex and motion as deltas between the intial skeleton and the new moved one. " ContentLicense="CC BY-SA 4.0" />
  <row Id="22462" PostHistoryTypeId="2" PostId="8407" RevisionGUID="395bf3f1-9135-4731-8236-bed9d2799bc3" CreationDate="2018-12-18T16:32:13.363" UserId="7644" Text="Unfortunately, I don't know how 3ds max handles its Z-buffer or its near and far planes so I can't give a definite answer. There are many ways the software could handle this.&#xD;&#xA;&#xD;&#xA;However, you are on the right track. Z-fighting occurs when there is not enough numerical precision to distinguish two &quot;objects&quot; from the scene rendered at the same pixel. In such cases, the two pixels &quot;fight&quot; one another over which one is closest to the camera and flickering occurs.&#xD;&#xA;&#xD;&#xA;These factors influence how a scene is susceptible to Z-fighting:&#xD;&#xA;&#xD;&#xA; - Number of bits used by the depth buffer (typically 24 or 32).&#xD;&#xA; - Whether the depth buffer uses float values or integers.&#xD;&#xA; - Whether the Z value `0` is used for the near or far plane (inverted depth buffer).&#xD;&#xA; - How close objects are to each other.&#xD;&#xA; - The size of the range between the near and far planes.&#xD;&#xA;&#xD;&#xA;Of these, you really only have control over the near and far planes from what you say.  It looks like your model is too big for the default way 3ds max handles this so I suggest making the near plane value bigger. An increase of the near plane from `0.1` to `1.0` (`*10`) will give the same precision increase as dividing the far plane by 10.&#xD;&#xA;&#xD;&#xA;For your other question, you usually get less Z-fighting when an object is closer because there is more precision in the depth buffer closer to the near plane.&#xD;&#xA;&#xD;&#xA;Also, for your other question: https://computergraphics.stackexchange.com/questions/8017/why-do-gpus-divide-clip-space-z-by-w-for-position?rq=1&#xD;&#xA;&#xD;&#xA;A nice Z precision visualizer: http://dev.theomader.com/depth-precision/" ContentLicense="CC BY-SA 4.0" />
  <row Id="22464" PostHistoryTypeId="50" PostId="8151" RevisionGUID="6e72c084-5755-4c59-b2e2-21b823ff2fde" CreationDate="2018-12-18T22:02:25.550" UserId="-1" />
  <row Id="22470" PostHistoryTypeId="2" PostId="8409" RevisionGUID="efcda5b1-7b00-4bc4-bcb9-495e8fe64847" CreationDate="2018-12-18T23:35:50.493" UserId="9880" Text="I am developing a MacOS program using MacOS MetalKit and ModelIO. The ultimate goal is to use the 3D model to analyze the acoustic properties of a performance space. Initially I'm just creating a visual image of the space (stage, walls, seating, etc). I create a wavefront file (.obj and accompanying .mtl file).&#xD;&#xA;&#xD;&#xA;I can define the vertex color for every vertex in the .obj file. But I would like to use the Kd properties of the mtl file to set the color so that specific colors are associated with specific named materials in the mtl file.&#xD;&#xA;&#xD;&#xA;I use ModelIO to create an asset and then extract both the modelio mesh and metal mesh. Here is the bit of Swift code:&#xD;&#xA;&#xD;&#xA;    // Extract both the MetalKit meshes and the original ModelIO meshes&#xD;&#xA;        var meshes: (modelIOMeshes: [MDLMesh], metalKitMeshes: [MTKMesh])&#xD;&#xA;        meshes = try MTKMesh.newMeshes(asset: asset, device: device)&#xD;&#xA;&#xD;&#xA;I see all of the mtl properties for all of the 147 submeshes in the imported modelio data.&#xD;&#xA;&#xD;&#xA;If I specify the vertex colors in the obj file then I see all of those colors in the 147 metalKitMeshes submeshes. But if I do not specify all of the vertex colors in the obj file then all colors in the metalKitMeshes submeshes are Black (0,0,0). The colors specified in the mtl file are ignored.&#xD;&#xA;&#xD;&#xA;**The primary question: Is there a way to use the material colors in the mtl file to automatically set the metal submesh colors?**&#xD;&#xA;&#xD;&#xA;**Secondary question: In the more general case, what is the best way to convey all of the material parameters from the modelio data to the shader?**&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;I asked this on the Apple Developer forum, but got no response.&#xD;&#xA;I also asked on StackOverflow but then realized that this may be a more appropriate forum.&#xD;&#xA;&#xD;&#xA;I can import my wavefront file into Blender and all of the objects in the scene are rendered with the correct colors from the materials file. So the structures of my .obj and .mtl files seem to be correct.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22471" PostHistoryTypeId="1" PostId="8409" RevisionGUID="efcda5b1-7b00-4bc4-bcb9-495e8fe64847" CreationDate="2018-12-18T23:35:50.493" UserId="9880" Text="What is best way to use wavefront material file color parameter Kd to set vertex color in MetalKit submeshes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22472" PostHistoryTypeId="3" PostId="8409" RevisionGUID="efcda5b1-7b00-4bc4-bcb9-495e8fe64847" CreationDate="2018-12-18T23:35:50.493" UserId="9880" Text="|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22473" PostHistoryTypeId="50" PostId="7730" RevisionGUID="821fc9cc-f1c6-4ef3-aa91-5ca3ad1cb1d8" CreationDate="2018-12-19T00:01:40.853" UserId="-1" />
  <row Id="22476" PostHistoryTypeId="2" PostId="8410" RevisionGUID="ed47d570-59b3-455a-aacc-3f9afbb27c6c" CreationDate="2018-12-19T23:07:45.653" UserId="9886" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a matrix-math problem.  How do I transform the camera or objects being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view source code in github.com&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22477" PostHistoryTypeId="1" PostId="8410" RevisionGUID="ed47d570-59b3-455a-aacc-3f9afbb27c6c" CreationDate="2018-12-19T23:07:45.653" UserId="9886" Text="How do I correctly rotate a model or a view with mouse dragging input?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22478" PostHistoryTypeId="3" PostId="8410" RevisionGUID="ed47d570-59b3-455a-aacc-3f9afbb27c6c" CreationDate="2018-12-19T23:07:45.653" UserId="9886" Text="|transformations|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22479" PostHistoryTypeId="4" PostId="8410" RevisionGUID="299c8ed6-ee7a-4e7a-816d-67f2e74afc14" CreationDate="2018-12-19T23:13:05.457" UserId="9886" Comment="edited title" Text="How do I correctly rotate a model or a view with mouse input?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22480" PostHistoryTypeId="5" PostId="8410" RevisionGUID="cacc8fb3-311a-47d8-b639-a88a241ff64d" CreationDate="2018-12-19T23:19:07.083" UserId="9886" Comment="edited title" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a transformation problem.  How do I rotate the orientation of the camera or models being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view source code of a concise demo in github.com&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22481" PostHistoryTypeId="4" PostId="8410" RevisionGUID="cacc8fb3-311a-47d8-b639-a88a241ff64d" CreationDate="2018-12-19T23:19:07.083" UserId="9886" Comment="edited title" Text="Rotate a model or a view with mouse input to produce intuitive results" ContentLicense="CC BY-SA 4.0" />
  <row Id="22482" PostHistoryTypeId="5" PostId="8410" RevisionGUID="ccf67162-fc40-4865-93b4-e9de05b82f9b" CreationDate="2018-12-20T04:14:14.043" UserId="9886" Comment="added 813 characters in body" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a transformation problem.  How do I rotate the orientation of the camera or models being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view the full source code of a concise demo in github.com&#xD;&#xA;&#xD;&#xA;But, here is the method where I'm certain the problem and solution will be found:&#xD;&#xA;&#xD;&#xA;    @Override public boolean touchDragged( int screenX, int screenY, int pointer )&#xD;&#xA;	{&#xD;&#xA;		lastX = screenX-lastX;&#xD;&#xA;		lastY = screenY-lastY;&#xD;&#xA;&#xD;&#xA;		// distance of mouse movement&#xD;&#xA;		screenAng = (float) Math.sqrt( lastX*lastX + lastY*lastY );&#xD;&#xA;		// direction vector of the AOR&#xD;&#xA;		screenAOR.set( lastY/screenAng, lastX/screenAng, 0f );&#xD;&#xA;		if ( touchedButton == 0 )&#xD;&#xA;		{&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( screenAOR, screenAng );&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			camera.rotateAround( Vector3.Zero, screenAOR, -screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		lastX = screenX;&#xD;&#xA;		lastY = screenY;&#xD;&#xA;		Gdx.graphics.requestRendering();&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22483" PostHistoryTypeId="50" PostId="8102" RevisionGUID="cc7fd146-dfb0-4276-a826-4c83655a0152" CreationDate="2018-12-20T05:01:00.677" UserId="-1" />
  <row Id="22484" PostHistoryTypeId="5" PostId="8410" RevisionGUID="1eeabd79-cd4b-4e2b-bc7d-a5e088e5438d" CreationDate="2018-12-20T06:09:02.910" UserId="9886" Comment="added 609 characters in body" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a transformation problem.  How do I rotate the orientation of the camera or models being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view the full source code of a concise demo in github.com&#xD;&#xA;&#xD;&#xA;But, here is the method where I'm certain the problem and solution will be found:&#xD;&#xA;&#xD;&#xA;    @Override public boolean touchDragged( int screenX, int screenY, int pointer )&#xD;&#xA;	{&#xD;&#xA;		lastX = screenX-lastX;&#xD;&#xA;		lastY = screenY-lastY;&#xD;&#xA;&#xD;&#xA;		// distance of mouse movement&#xD;&#xA;		screenAng = (float) Math.sqrt( lastX*lastX + lastY*lastY );&#xD;&#xA;		// direction vector of the AOR&#xD;&#xA;		screenAOR.set( lastY/screenAng, lastX/screenAng, 0f );&#xD;&#xA;		if ( touchedButton == 0 )&#xD;&#xA;		{&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( screenAOR, screenAng );&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			camera.rotateAround( Vector3.Zero, screenAOR, -screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		lastX = screenX;&#xD;&#xA;		lastY = screenY;&#xD;&#xA;		Gdx.graphics.requestRendering();&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;EDIT: Thanks to Andrew Wilson for his comment below.  I edited the camera section and it works properly now.  Still working on the model section...&#xD;&#xA;&#xD;&#xA;        {&#xD;&#xA;			// get the camera transformation matrix&#xD;&#xA;			tempMat = new Matrix4( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;			worldAOR = transformThings( tempMat, screenAOR, new Vector3() ).nor();&#xD;&#xA;			&#xD;&#xA;			// apply the rotation of the angle about the world AOR to the camera&#xD;&#xA;			camera.rotateAround( Vector3.Zero, worldAOR, screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22485" PostHistoryTypeId="2" PostId="8411" RevisionGUID="46b86230-37b1-447f-be02-bf437da6df6d" CreationDate="2018-12-20T12:59:08.370" UserId="6046" Text="Copying this from another thread where i posted this as the answer but as Wyck suggested, the correct answer is the first one.&#xD;&#xA;&#xD;&#xA;There is the whole derivation of it but I'll be discussing a brief overview.&#xD;&#xA;This is for the perspective projection  where the line joining the eye and the center of the projection/image plane is perpendicular to it. Like here&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As we can easily see, by similar triangles $\triangle ABC$ and $\triangle AEF$ we have&#xD;&#xA;&#xD;&#xA;$Y_p / Y = D/-Z$&#xD;&#xA;&#xD;&#xA;where $Y_p$ is the projected $Y$ coordinate on to the image plane. $AB = D$ is the total distance from eye to the image plane and is usually set to 1.&#xD;&#xA;&#xD;&#xA;Hence we have,&#xD;&#xA;&#xD;&#xA;$Y_p = (Y*D)/-Z$&#xD;&#xA;&#xD;&#xA;We  can easily ee from here that,&#xD;&#xA;&#xD;&#xA;$tan(\theta_{fov}/2) = 1/AB$ &#xD;&#xA;&#xD;&#xA;$tan(\theta_{fov}/2) = 1/D$&#xD;&#xA;&#xD;&#xA;$D = 1 /tan(\theta_{fov}/2)$&#xD;&#xA;&#xD;&#xA;Hence we have,&#xD;&#xA;$Y_p = \frac{Y}{-Z*tan(\theta_{fov}/2)}$&#xD;&#xA;&#xD;&#xA;For more details check the complete answer [here][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WmmPi.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/6365/inverse-value-in-a-perspective-matrix/6366#6366" ContentLicense="CC BY-SA 4.0" />
  <row Id="22486" PostHistoryTypeId="5" PostId="8410" RevisionGUID="65e0d4a2-9caa-40b9-bd85-0401d1e00553" CreationDate="2018-12-20T14:53:31.797" UserId="9886" Comment="[Edit removed during grace period]" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a transformation problem.  How do I rotate the orientation of the camera or models being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view the full source code of a concise demo in github.com&#xD;&#xA;&#xD;&#xA;But, here is the method where I'm certain the problem and solution will be found:&#xD;&#xA;&#xD;&#xA;    @Override public boolean touchDragged( int screenX, int screenY, int pointer )&#xD;&#xA;	{&#xD;&#xA;		lastX = screenX-lastX;&#xD;&#xA;		lastY = screenY-lastY;&#xD;&#xA;&#xD;&#xA;		// distance of mouse movement&#xD;&#xA;		screenAng = (float) Math.sqrt( lastX*lastX + lastY*lastY );&#xD;&#xA;		// direction vector of the AOR&#xD;&#xA;		screenAOR.set( lastY/screenAng, lastX/screenAng, 0f );&#xD;&#xA;		if ( touchedButton == 0 )&#xD;&#xA;		{&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( screenAOR, screenAng );&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			camera.rotateAround( Vector3.Zero, screenAOR, -screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		lastX = screenX;&#xD;&#xA;		lastY = screenY;&#xD;&#xA;		Gdx.graphics.requestRendering();&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;EDIT: Thanks to Andrew Wilson for his comment below.  I edited the camera section and it works properly now.  Still working on the model section...&#xD;&#xA;&#xD;&#xA;        {&#xD;&#xA;			// get the camera transformation matrix&#xD;&#xA;			tempMat = new Matrix4( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;			worldAOR = transformThings( tempMat, screenAOR, new Vector3() ).nor();&#xD;&#xA;			&#xD;&#xA;			// apply the rotation of the angle about the world AOR to the camera&#xD;&#xA;			camera.rotateAround( Vector3.Zero, worldAOR, screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22487" PostHistoryTypeId="2" PostId="8412" RevisionGUID="7a927c04-239d-48c7-b25c-4bf634de7b2c" CreationDate="2018-12-21T07:44:32.520" UserDisplayName="user106" Text="Joint coordinates alone don't give you enough information about rotation.&#xD;&#xA;&#xD;&#xA;For example, hold out your arm to your side. Notice that you still have one degree of freedom to twist the arm without affecting the positions of your elbow or wrist. Thus, if you had a motion capture format that stored only those coordinates, you would not be able to distinguish these poses." ContentLicense="CC BY-SA 4.0" />
  <row Id="22488" PostHistoryTypeId="2" PostId="8413" RevisionGUID="f9cb1af4-d2fe-4f15-870c-96ef50d1248e" CreationDate="2018-12-21T09:18:32.913" UserId="7644" Text="I'm not familiar with different motion capture file formats and exactly what they contain, but I have done some work on animating skeletons of life forms so here's my take on it.&#xD;&#xA;&#xD;&#xA;When you draw something using a skeleton to animate it, you start with a &quot;root&quot; bone which will obviously have a position as can be seen in this [example walk.asf file][1]:&#xD;&#xA;&#xD;&#xA;	:root&#xD;&#xA;	   axis XYZ&#xD;&#xA;	   order TX TY TZ RZ RY RX&#xD;&#xA;	   position 0.0 0.0 0.0&#xD;&#xA;	   orientation 0.0 0.0 0.0&#xD;&#xA;&#xD;&#xA;The next `bonedata` section defines all the bones:&#xD;&#xA;&#xD;&#xA;	:bonedata&#xD;&#xA;	begin&#xD;&#xA;	   id 1&#xD;&#xA;	   name hips&#xD;&#xA;	   direction 0.000000 1.000000 0.000000&#xD;&#xA;	   length 0.000000&#xD;&#xA;	   axis 0.00000 0.00000 0.00000 XYZ&#xD;&#xA;	   dof rx ry rz&#xD;&#xA;	   limits (-180.0 180.0)&#xD;&#xA;		  (-180.0 180.0)&#xD;&#xA;		  (-180.0 180.0)&#xD;&#xA;	end&#xD;&#xA;	# other bone definitions follow&#xD;&#xA;&#xD;&#xA;There is then a hierarchy of bones starting from this root bone:&#xD;&#xA;&#xD;&#xA;	begin&#xD;&#xA;	   root hips&#xD;&#xA;	   hips hips1 hips2 hips3&#xD;&#xA;	   hips1 chest&#xD;&#xA;	   chest chest1 chest2 chest3&#xD;&#xA;	   chest1 neck&#xD;&#xA;	   # ...&#xD;&#xA;	   hips2 leftupleg&#xD;&#xA;	   # ...&#xD;&#xA;	   hips3 rightupleg&#xD;&#xA;	end&#xD;&#xA;&#xD;&#xA;(by the way, this is the kind of information I asked for in my comments and that you should have provided for a clearer question.)&#xD;&#xA;&#xD;&#xA;Each &quot;child&quot; bone is connected to the endpoint of its parent and it defines its own orientation relative to that parent. This picture helps (taken from [Autodesk Motionbuilder's doc][2])&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;To position any given bone, you need to go up the bone hierarchy to the root bone and combine all their transformation matrices together. For example, to position bone `chest`, the following sequence is used: `root -&gt; hips -&gt; hips1 -&gt; chest`. Each of these bones has its own transformation (rotation, stretch) based on the motion capture data which affects the position of its children. The `root` bone is a special case that has no parents and represents the position and orientation of the whole model.&#xD;&#xA;&#xD;&#xA;Motion capture data cannot contain only bone positions because rotation in the axis of the bone cannot be expressed otherwise. Finally, it makes more sense to have motion capture data in terms of rotation and stretch because these values can be interpolated more easily than position and it's what is used anyway to render the skeleton.&#xD;&#xA;&#xD;&#xA;  [1]: http://research.cs.wisc.edu/graphics/Courses/cs-838-1999/Jeff/walk.asf&#xD;&#xA;  [2]: http://help.autodesk.com/view/MOBPRO/2017/ENU/?guid=GUID-C42E4E6A-5149-4128-873C-08B2353A44B9&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZqUhU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22490" PostHistoryTypeId="5" PostId="8410" RevisionGUID="4b1d8cf0-df00-45db-907a-af9649ed1da7" CreationDate="2018-12-22T05:24:43.557" UserId="9886" Comment="added 1016 characters in body" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a transformation problem.  How do I rotate the orientation of the camera or models being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view the full source code of a concise demo in github.com&#xD;&#xA;&#xD;&#xA;But, here is the method where I'm certain the problem and solution will be found:&#xD;&#xA;&#xD;&#xA;    @Override public boolean touchDragged( int screenX, int screenY, int pointer )&#xD;&#xA;	{&#xD;&#xA;		lastX = screenX-lastX;&#xD;&#xA;		lastY = screenY-lastY;&#xD;&#xA;&#xD;&#xA;		// distance of mouse movement&#xD;&#xA;		screenAng = (float) Math.sqrt( lastX*lastX + lastY*lastY );&#xD;&#xA;		// direction vector of the AOR&#xD;&#xA;		screenAOR.set( lastY/screenAng, lastX/screenAng, 0f );&#xD;&#xA;		if ( touchedButton == 0 )&#xD;&#xA;		{&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( screenAOR, screenAng );&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			camera.rotateAround( Vector3.Zero, screenAOR, -screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		lastX = screenX;&#xD;&#xA;		lastY = screenY;&#xD;&#xA;		Gdx.graphics.requestRendering();&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;EDIT: Thanks to Andrew Wilson for his comment below.  I edited the camera section and it works properly now.  Still working on the model section...&#xD;&#xA;&#xD;&#xA;        {&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;&#xD;&#xA;			// get the camera transformation matrix&#xD;&#xA;			tempMat = new Matrix4( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;			worldAOR = transformThings( tempMat, screenAOR, new Vector3() ).nor();&#xD;&#xA;			&#xD;&#xA;			// apply the rotation of the angle about the world AOR to the camera&#xD;&#xA;			camera.rotateAround( Vector3.Zero, worldAOR, screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;EDIT: I edited the model section and it still is giving me some grief - it looks like it's orbiting the world origin instead of rotating around the model origin.  Here's what it looks like so far:&#xD;&#xA;&#xD;&#xA;    	{&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a model AOR&#xD;&#xA;			&#xD;&#xA;			// get inverse of the camera transformation matrix&#xD;&#xA;			tempMat.set( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// get inverse of the model transformation matrix&#xD;&#xA;			Vector3 tempPos = cubes[ selectedCube ].position;&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.translate( tempPos.cpy().scl( -1 ) );&#xD;&#xA;			tempMat2.set( cubes[ selectedCube ].modelInstance.transform );&#xD;&#xA;			tempMat2.inv();&#xD;&#xA;&#xD;&#xA;			tempMat.mul( tempMat2 );&#xD;&#xA;			&#xD;&#xA;			modelAOR = transform( tempMat, screenAOR, modelAOR ).nor();&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( modelAOR, -screenAng );&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.translate( tempPos );&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22491" PostHistoryTypeId="5" PostId="8410" RevisionGUID="9a0539fb-74b0-442b-9ff2-028d21ea15d0" CreationDate="2018-12-22T05:31:11.440" UserId="9886" Comment="added 1016 characters in body" Text="I am writing 3D graphics software in Java using the LibGDX framework (which is a front-end for OpenGL), and am baffled by a transformation problem.  How do I rotate the orientation of the camera or models being displayed by the dx and dy inputs from a mouse?&#xD;&#xA;&#xD;&#xA;[Click here][1] to view the full source code of a concise demo in github.com&#xD;&#xA;&#xD;&#xA;But, here is the method where I'm certain the problem and solution will be found:&#xD;&#xA;&#xD;&#xA;    @Override public boolean touchDragged( int screenX, int screenY, int pointer )&#xD;&#xA;	{&#xD;&#xA;		lastX = screenX-lastX;&#xD;&#xA;		lastY = screenY-lastY;&#xD;&#xA;&#xD;&#xA;		// distance of mouse movement&#xD;&#xA;		screenAng = (float) Math.sqrt( lastX*lastX + lastY*lastY );&#xD;&#xA;		// direction vector of the AOR&#xD;&#xA;		screenAOR.set( lastY/screenAng, lastX/screenAng, 0f );&#xD;&#xA;		if ( touchedButton == 0 )&#xD;&#xA;		{&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( screenAOR, screenAng );&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			camera.rotateAround( Vector3.Zero, screenAOR, -screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		lastX = screenX;&#xD;&#xA;		lastY = screenY;&#xD;&#xA;		Gdx.graphics.requestRendering();&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;EDIT: Thanks to Andrew Wilson for his comment below.  I edited the camera section and it works properly now.  Still working on the model section...&#xD;&#xA;&#xD;&#xA;        {&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;&#xD;&#xA;			// get the camera transformation matrix&#xD;&#xA;			tempMat = new Matrix4( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;			worldAOR = transformThings( tempMat, screenAOR, new Vector3() ).nor();&#xD;&#xA;			&#xD;&#xA;			// apply the rotation of the angle about the world AOR to the camera&#xD;&#xA;			camera.rotateAround( Vector3.Zero, worldAOR, screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;EDIT: I edited the model section and it still is giving me some grief - it looks like it's orbiting the world origin instead of rotating around the model origin.  Here's what it looks like so far:&#xD;&#xA;&#xD;&#xA;    	{&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a model AOR&#xD;&#xA;			&#xD;&#xA;			// get inverse of the camera transformation matrix&#xD;&#xA;			tempMat.set( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// get inverse of the model transformation matrix&#xD;&#xA;			Vector3 tempPos = cubes[ selectedCube ].position;&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.translate( tempPos.cpy().scl( -1 ) );&#xD;&#xA;			tempMat2.set( cubes[ selectedCube ].modelInstance.transform );&#xD;&#xA;			tempMat2.inv();&#xD;&#xA;&#xD;&#xA;			// multiply the camera and model matrices together&#xD;&#xA;			tempMat.mul( tempMat2 );&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a model AOR&#xD;&#xA;			modelAOR = transformThings( tempMat, screenAOR, modelAOR ).nor();&#xD;&#xA;			&#xD;&#xA;			// apply the rotation of the angle about the model AOR to the model&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.rotate( modelAOR, -screenAng );&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.translate( tempPos );&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is an image that the demonstrates the problem:&#xD;&#xA;&#xD;&#xA;[![results of wonky math][2]][2]&#xD;&#xA;&#xD;&#xA;I want the object to rotate in the direction it is dragged by the mouse, no matter which direction it happens to be orientated at the time. As it is now, when I first drag the mouse to the right, the object rotates to the right about the screen Y axis as expected; but then when I drag the mouse upward I want the object to rotate upward about the screen X axis, but instead it spins to the left about the screen Z axis. Think of it like a floating ball in a bowl of water - whichever way you swipe at it, it ought to rotate in that direction.&#xD;&#xA;&#xD;&#xA;It seems to me that the mouse movement is transforming the objects directly in their local coordinate system; but instead I think I need to transform the axis of rotation itself from the Screen Coordinate System into the Object Coordinate System before applying it to the object. I just can't figure out how to do it.&#xD;&#xA;&#xD;&#xA;I would really appreciate any insight or help to resolve this; I'm running out of hair to pull out... Thanks in advance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mbrown85209/Space/blob/master/Space.java&#xD;&#xA;  [2]: https://i.stack.imgur.com/i3fNL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22496" PostHistoryTypeId="2" PostId="8415" RevisionGUID="ceedb27a-6bbc-4793-93c8-695361c62218" CreationDate="2018-12-23T05:08:00.953" UserId="9896" Text="I’m a weaver and textile maker with no prior coding or programming experience. In researching and reading through posts on this and other message boards, I was able to find a lot of useful information, but nothing that I could clearly map on what it is I’m trying to do. I’m hoping someone can steer me in the right direction. &#xD;&#xA;&#xD;&#xA;I’m working with a set of 18x18 (324px), 8 bit RGB color PNGs which will ultimately be converted into weave structures. I am interested in implementing a script which will allow me to change the value of all pixels of a particular color channel. I’m seeing a number of posts describing how to change the color values of specific pixels, but little about making global changes to the color channels themselves.&#xD;&#xA;&#xD;&#xA;I want to be able to manipulate each color channel separately. For example, I'd like to be able to edit all RED pixels in an image such that all R pixel values increase by, say, 2, while pixels containing no R remain unchanged. Additionally, I want to be able to specify a limit, e.g. if the maximum R value in the image is 178, all R pixel values equaling 178 will remain unchanged, while all pixels with R values less than 178 will increase in value by 2. &#xD;&#xA;&#xD;&#xA;I hope to be able to specify the channel (e.g. RED), amount of change (e.g. 2, 1, etc.), type of change (e.g. increase/decrease), and limit (e.g. n = 178, n = 0, n = 255, etc.) as those variables will need to be adjusted to satisfy different color palettes and weave structures.&#xD;&#xA;&#xD;&#xA;I've tried achieving this in Photoshop and other graphics editors, but outside of selecting like pixels and adjusting their values manually, I haven't had luck in finding an effective solution for this.&#xD;&#xA; &#xD;&#xA;I’m wondering - 1) how feasible this is, 2) what program (e.g. Gimp, ImageMagick, etc.) and/or programming language might provide the most straightforward, expedient solution and 3) if anybody has any tips about how go about a script like this, as this is all quite new to me.&#xD;&#xA;&#xD;&#xA;Thanks in advance for your help,&#xD;&#xA;TF &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22497" PostHistoryTypeId="1" PostId="8415" RevisionGUID="ceedb27a-6bbc-4793-93c8-695361c62218" CreationDate="2018-12-23T05:08:00.953" UserId="9896" Text="Shifting color values of a single RGB channel" ContentLicense="CC BY-SA 4.0" />
  <row Id="22498" PostHistoryTypeId="3" PostId="8415" RevisionGUID="ceedb27a-6bbc-4793-93c8-695361c62218" CreationDate="2018-12-23T05:08:00.953" UserId="9896" Text="|algorithm|image-processing|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22499" PostHistoryTypeId="5" PostId="8415" RevisionGUID="ac683b1c-e349-48ef-a52f-a5aa28f587b9" CreationDate="2018-12-23T05:22:37.307" UserId="9896" Comment="added 8 characters in body; edited title" Text="I’m a weaver and textile maker with no prior coding or programming experience. In researching and reading through posts on this and other message boards, I was able to find a lot of useful information, but nothing that I could clearly map on what it is I’m trying to do. I’m hoping someone can steer me in the right direction. &#xD;&#xA;&#xD;&#xA;I’m working with a set of 18x18 (324px), 8 bit RGB color PNGs which will ultimately be converted into weave structures. I am interested in implementing a script which will allow me to change the value of all pixels of a particular color channel. I’m seeing a number of posts describing how to change the color values of specific pixels, but little about making global changes to the color channels themselves.&#xD;&#xA;&#xD;&#xA;I want to be able to manipulate each color channel separately. For example, I'd like to be able to edit all RED pixels in an image such that all R pixel values increase by, say, 2, while pixels containing no R remain unchanged. Additionally, I want to be able to specify a limit, e.g. if the maximum R value in the image is 178, all R pixel values equaling 178 will remain unchanged, while all pixels with R values less than 178 will increase in value by 2. &#xD;&#xA;&#xD;&#xA;I hope to be able to specify the channel (e.g. RED), amount of change (e.g. 2, 1, etc.), type of change (e.g. increase/decrease), and limit (e.g. n = 178, n = 0, n = 255, etc.) as those variables will need to be adjusted to satisfy different color palettes and weave structures.&#xD;&#xA;&#xD;&#xA;I've tried achieving this in Photoshop and other graphics editors, but outside of selecting like pixels and adjusting their values manually, I haven't had luck in finding an effective solution for this.&#xD;&#xA; &#xD;&#xA;I’m wondering - 1) how feasible this is, 2) what program (e.g. Gimp, ImageMagick, etc.) and/or programming language might provide the most straightforward, expedient solution and 3) if anybody has any tips about how go about writing a script like this, as this is all quite new to me.&#xD;&#xA;&#xD;&#xA;Thanks in advance for your help,&#xD;&#xA;TF &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22500" PostHistoryTypeId="4" PostId="8415" RevisionGUID="ac683b1c-e349-48ef-a52f-a5aa28f587b9" CreationDate="2018-12-23T05:22:37.307" UserId="9896" Comment="added 8 characters in body; edited title" Text="How to shift color values of a single RGB channel" ContentLicense="CC BY-SA 4.0" />
  <row Id="22501" PostHistoryTypeId="2" PostId="8416" RevisionGUID="32af869f-1143-494a-bd79-534b1ec33bc2" CreationDate="2018-12-23T05:58:48.093" UserId="113" Text="Here's a more complete answer from my comment. The end product we want is:&#xD;&#xA;&#xD;&#xA;    Projection * ViewTranslate * Model * ViewRotate&#xD;&#xA;&#xD;&#xA;All are 4x4 matrices. Where model is your models transformations. To implement you can just separate out the view's translate and rotate during your draw.&#xD;&#xA;&#xD;&#xA;If you're using an abstraction that requires you to use Proj * View * Model. Or you just really don't want to ruin your own abstraction that follows that pattern. You'll need to modify model to cancel out views rotational part and put it on the right side:&#xD;&#xA;&#xD;&#xA;    Model = ModelTranslate * View^-1 * ViewTranslate * ModelRotate * ViewRotate &#xD;&#xA;          = ModelTranslate * ViewRotate^-1 * ModelRotate * ViewRotate&#xD;&#xA;&#xD;&#xA;Here's some of my code that does the above. It does not matter if model or view is translated, objects will still rotate around their local origins:&#xD;&#xA;&#xD;&#xA;	glm::vec2 diff = (prevMousePos - mousePos) * rotSpeed;&#xD;&#xA;	glm::mat4 rotX = MathHelp::matrixRotateY(diff.x);&#xD;&#xA;	glm::mat4 rotY = MathHelp::matrixRotateX(diff.y);&#xD;&#xA;&#xD;&#xA;	// Decompose the translate and rotate part of view&#xD;&#xA;	glm::mat4 viewT, viewR;&#xD;&#xA;	Decompose(cam-&gt;view, viewT, viewR);&#xD;&#xA;&#xD;&#xA;	// Decompose the translate and rotate part of model&#xD;&#xA;	glm::mat4 modelT, modelR;&#xD;&#xA;	Decompose(exampleObj-&gt;model, modelT, modelR);&#xD;&#xA;&#xD;&#xA;	exampleObj-&gt;model = modelT * glm::inverse(viewR) * rotX * rotY * viewR * modelR;&#xD;&#xA;&#xD;&#xA;This preserves the existing rotation and translation in exampleObj-&gt;model as the function gets called continually applying small rotations. And assumes you'll be using Proj * View * Model.&#xD;&#xA;&#xD;&#xA;Lastly decompose just separates out the 3x3 rotation/scaling from the translational part:&#xD;&#xA;&#xD;&#xA;    void Decompose(glm::mat4 m, glm::mat4&amp; t, glm::mat4&amp; r)&#xD;&#xA;    {&#xD;&#xA;        glm::mat4 I4 = glm::mat4(1.0f); // Identity&#xD;&#xA;	    for (unsigned int i = 0; i &lt; 4; i++)&#xD;&#xA;	    {&#xD;&#xA;		    for (unsigned int j = 0; j &lt; 4; j++)&#xD;&#xA;		    {&#xD;&#xA;			    if (i == 3 || j == 3)&#xD;&#xA;			    {&#xD;&#xA;				    r[i][j] = I4[i][j];&#xD;&#xA;				    t[i][j] = m[i][j];&#xD;&#xA;			    }&#xD;&#xA;			    else&#xD;&#xA;			    {&#xD;&#xA;				    r[i][j] = m[i][j];&#xD;&#xA;				    t[i][j] = I4[i][j];&#xD;&#xA;			    }&#xD;&#xA;		    }&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22502" PostHistoryTypeId="2" PostId="8417" RevisionGUID="f026450f-3ad0-46fc-acfc-20cdca2684bb" CreationDate="2018-12-23T09:23:51.470" UserId="9901" Text="I want to use PCF shadow map on my d3d11 app. My shadow map is an R16_FLOAT texture. When I use SampleCmpLevelZero it didn't give a correct result. After enabling debug layer, it shows &quot;The Shader Resource View in slot 1 of the Pixel Shader unit is using the Format (R16_FLOAT). This format does not support 'SampleCmp' or 'SampleCmpLevelZero', at least one of which is being used on the Resource by the shader. This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching).&quot; &#xD;&#xA;&#xD;&#xA;But when I query whether the format support SampleCmp using the code below, it returns 0 which means succeed. Can someone explain why? Thanks!&#xD;&#xA;&#xD;&#xA;    bool Renderer::InitRenderer(HWND hwnd)&#xD;&#xA;    {&#xD;&#xA;    	if (!InitD3D11App(hwnd)) return false;&#xD;&#xA;    	InitViewport();&#xD;&#xA;    &#xD;&#xA;    	UINT formatSupport = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;&#xD;&#xA;    	printf(&quot;Support?\n&quot;);&#xD;&#xA;    	HRESULT hr = d3d11Device-&gt;CheckFormatSupport(DXGI_FORMAT_R16_FLOAT, &amp;formatSupport);&#xD;&#xA;    	printf(&quot;result: %d\n&quot;, hr);&#xD;&#xA;    	if (!SUCCEEDED(hr))&#xD;&#xA;    	{&#xD;&#xA;    		printf(&quot;Nope!\n&quot;);&#xD;&#xA;    		return false;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22503" PostHistoryTypeId="1" PostId="8417" RevisionGUID="f026450f-3ad0-46fc-acfc-20cdca2684bb" CreationDate="2018-12-23T09:23:51.470" UserId="9901" Text="R16_FLOAT, SampleCmp and CheckFormatSupport" ContentLicense="CC BY-SA 4.0" />
  <row Id="22504" PostHistoryTypeId="3" PostId="8417" RevisionGUID="f026450f-3ad0-46fc-acfc-20cdca2684bb" CreationDate="2018-12-23T09:23:51.470" UserId="9901" Text="|shadow|hlsl|directx11|shadow-mapping|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22505" PostHistoryTypeId="5" PostId="8415" RevisionGUID="db3eab45-8348-4ea5-97ee-4966d850dcae" CreationDate="2018-12-23T13:34:18.497" UserId="6" Comment="deleted 43 characters in body" Text="I’m a weaver and textile maker with no prior coding or programming experience. In researching and reading through posts on this and other message boards, I was able to find a lot of useful information, but nothing that I could clearly map on what it is I’m trying to do. I’m hoping someone can steer me in the right direction. &#xD;&#xA;&#xD;&#xA;I’m working with a set of 18x18 (324px), 8 bit RGB color PNGs which will ultimately be converted into weave structures. I am interested in implementing a script which will allow me to change the value of all pixels of a particular color channel. I’m seeing a number of posts describing how to change the color values of specific pixels, but little about making global changes to the color channels themselves.&#xD;&#xA;&#xD;&#xA;I want to be able to manipulate each color channel separately. For example, I'd like to be able to edit all RED pixels in an image such that all R pixel values increase by, say, 2, while pixels containing no R remain unchanged. Additionally, I want to be able to specify a limit, e.g. if the maximum R value in the image is 178, all R pixel values equaling 178 will remain unchanged, while all pixels with R values less than 178 will increase in value by 2. &#xD;&#xA;&#xD;&#xA;I hope to be able to specify the channel (e.g. RED), amount of change (e.g. 2, 1, etc.), type of change (e.g. increase/decrease), and limit (e.g. n = 178, n = 0, n = 255, etc.) as those variables will need to be adjusted to satisfy different color palettes and weave structures.&#xD;&#xA;&#xD;&#xA;I've tried achieving this in Photoshop and other graphics editors, but outside of selecting like pixels and adjusting their values manually, I haven't had luck in finding an effective solution for this.&#xD;&#xA; &#xD;&#xA;I’m wondering - 1) how feasible this is, 2) what program (e.g. Gimp, ImageMagick, etc.) and/or programming language might provide the most straightforward, expedient solution and 3) if anybody has any tips about how go about writing a script like this, as this is all quite new to me." ContentLicense="CC BY-SA 4.0" />
  <row Id="22506" PostHistoryTypeId="5" PostId="8417" RevisionGUID="e2d5243d-f279-4012-b330-a07ecc1233dd" CreationDate="2018-12-23T13:36:01.863" UserId="6" Comment="deleted 5 characters in body" Text="I want to use PCF shadow map on my d3d11 app. My shadow map is an R16_FLOAT texture. When I use SampleCmpLevelZero it didn't give a correct result. After enabling debug layer, it shows:&#xD;&#xA;&#xD;&#xA;&gt; The Shader Resource View in slot 1 of the Pixel Shader unit is using the Format (R16_FLOAT). This format does not support 'SampleCmp' or 'SampleCmpLevelZero', at least one of which is being used on the Resource by the shader. This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching).&#xD;&#xA;&#xD;&#xA;But when I query whether the format support SampleCmp using the code below, it returns 0 which means success. Can someone explain why?&#xD;&#xA;&#xD;&#xA;    bool Renderer::InitRenderer(HWND hwnd)&#xD;&#xA;    {&#xD;&#xA;    	if (!InitD3D11App(hwnd)) return false;&#xD;&#xA;    	InitViewport();&#xD;&#xA;    &#xD;&#xA;    	UINT formatSupport = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;&#xD;&#xA;    	printf(&quot;Support?\n&quot;);&#xD;&#xA;    	HRESULT hr = d3d11Device-&gt;CheckFormatSupport(DXGI_FORMAT_R16_FLOAT, &amp;formatSupport);&#xD;&#xA;    	printf(&quot;result: %d\n&quot;, hr);&#xD;&#xA;    	if (!SUCCEEDED(hr))&#xD;&#xA;    	{&#xD;&#xA;    		printf(&quot;Nope!\n&quot;);&#xD;&#xA;    		return false;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22507" PostHistoryTypeId="2" PostId="8418" RevisionGUID="0a05bee6-ce2e-4600-af84-902433961aa5" CreationDate="2018-12-23T16:32:24.447" UserId="9256" Text="I have a class Ray and Square&#xD;&#xA;&#xD;&#xA;    Ray {&#xD;&#xA;    &#xD;&#xA;       X,Y,Z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Square{&#xD;&#xA;    X,Y,Widht, height;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;i need intersection between this two, how?&#xD;&#xA;&#xD;&#xA;my code crossProduct in java is &#xD;&#xA;&#xD;&#xA;    public static Vector productoCruz(Vector a, Vector b) {&#xD;&#xA;            return new Vector(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;to apply the product point you need two vectors, and I only have 1 (the ray vector), where do I get the other vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22508" PostHistoryTypeId="1" PostId="8418" RevisionGUID="0a05bee6-ce2e-4600-af84-902433961aa5" CreationDate="2018-12-23T16:32:24.447" UserId="9256" Text="Get intersection Ray with square" ContentLicense="CC BY-SA 4.0" />
  <row Id="22509" PostHistoryTypeId="3" PostId="8418" RevisionGUID="0a05bee6-ce2e-4600-af84-902433961aa5" CreationDate="2018-12-23T16:32:24.447" UserId="9256" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22510" PostHistoryTypeId="2" PostId="8419" RevisionGUID="2d346601-a1db-4ec6-b9a0-c78a301db3a1" CreationDate="2018-12-23T18:00:50.500" UserId="9901" Text="Because I was using the CheckFormatSupport wrong. The second parameter is supposed to be an input.&#xD;&#xA;&#xD;&#xA;Here is what it should be like.&#xD;&#xA;&#xD;&#xA;    bool Renderer::InitRenderer(HWND hwnd)&#xD;&#xA;    {&#xD;&#xA;    	if (!InitD3D11App(hwnd)) return false;&#xD;&#xA;    	InitViewport();&#xD;&#xA;    &#xD;&#xA;    	UINT formatSupport;&#xD;&#xA;    	HRESULT hr = d3d11Device-&gt;CheckFormatSupport(DXGI_FORMAT_R16_FLOAT, &amp;formatSupport);&#xD;&#xA;    	if (!SUCCEEDED(hr) || !(formatSupport &amp; D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON))&#xD;&#xA;    	{&#xD;&#xA;    		printf(&quot;Not supported!\n&quot;);&#xD;&#xA;    		return false;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;https://www.gamedev.net/forums/topic/700419-r16_float-samplecmp-and-checkformatsupport/?tab=comments#comment-5397459" ContentLicense="CC BY-SA 4.0" />
  <row Id="22511" PostHistoryTypeId="2" PostId="8420" RevisionGUID="4ab9d8a7-9d77-43eb-966f-41cc541761b7" CreationDate="2018-12-23T18:05:51.967" UserId="6046" Text="The best algorithm depends on the condition like whether or not the square is axis aligned for example. I'm gonna discuss the more general case which can find find intersection for any arbitrary oriented square. The algorithm works by first checking the intersection of ray with the plane containing the square or rectangle etc. Then check if the ray is within bounds of the square.&#xD;&#xA;&#xD;&#xA;For this you require the following information&#xD;&#xA;&#xD;&#xA;Ray's in the form $R =e+td $ where $e$ is the origin or eye point and $d$ is the direction vector.&#xD;&#xA;&#xD;&#xA;Secondly you need to define your square by using the following information  &#xD;&#xA;&#xD;&#xA; 1. **Poisition** - This might be the vector to the center or any corner of the square. The algorithm I'm describing assumes it is one of the corners.&#xD;&#xA; 2. **Normal** - Self explanatory.&#xD;&#xA; 3. **Width** and **Height** not as scalars but as vectors. These can be called the two edge vectors. I will denote them as $e1$ and $e2$. *Note that both edge vectors need to grow outward from the corner of the square chosen in point 1.*&#xD;&#xA;&#xD;&#xA;After you have the following information you first need to compute Ray - plane intersection. The plane being where your square lies. This is done as follows. We know the point normal form of a plane as,&#xD;&#xA;&#xD;&#xA;$(p-p1).n= 0$&#xD;&#xA;&#xD;&#xA;If we suppose $p$ is our ray here and $p1 = position$, then we will have,&#xD;&#xA;&#xD;&#xA;$(e+td - p1).n=0$  &#xD;&#xA;$(e+td - p1).n=0$  &#xD;&#xA;$e.n + td.n - p1.n = 0$  &#xD;&#xA;$t = p1.n - e.n/d.n$  &#xD;&#xA;$t = (p1-e).n/d.n$&#xD;&#xA;&#xD;&#xA;If $t \geq 0$ then we have an intersection. Now all we need to do is check whether the ray lies inside the square or anywhere else on the plane. This is easy to do. Note this part assumes that the position is from the origin to the lower left corner&#xD;&#xA;&#xD;&#xA;$intersect\_point = e + td$  &#xD;&#xA;$v = intersect\_point - p1$&#xD;&#xA;&#xD;&#xA;$proj1 = v.e1$  &#xD;&#xA;$proj2 = v.e2$  &#xD;&#xA;$width = ||e1||$  &#xD;&#xA;$height = ||e2||$&#xD;&#xA;&#xD;&#xA;$if((proj1 &lt; width \;\&amp;\&amp;\; proj1 &gt; 0) \;\&amp;\&amp;\; (proj2  &lt; height \;\&amp;\&amp;\; proj2 &gt; 0) )$  &#xD;&#xA;$return \, true$&#xD;&#xA;&#xD;&#xA;Note that the above assumes that the edge vectors grow outward from the corner. Else,&#xD;&#xA;&#xD;&#xA;$v = intersect\_point - p1$&#xD;&#xA;&#xD;&#xA;may give us a vector pointing in the opposite direction. The less than and greater than signs in the if check may then get swapped." ContentLicense="CC BY-SA 4.0" />
  <row Id="22512" PostHistoryTypeId="5" PostId="8418" RevisionGUID="16d14da2-db81-4ac8-9f06-45d20e5c3596" CreationDate="2018-12-23T21:41:33.207" UserId="9256" Comment="deleted 3 characters in body" Text="I have a class Ray and Square&#xD;&#xA;&#xD;&#xA;    Ray {&#xD;&#xA;    &#xD;&#xA;       X,Y,Z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Square{&#xD;&#xA;    X,Y,Widht, height;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I need intersection between this two, how? my code crossProduct in java is &#xD;&#xA;&#xD;&#xA;    public static Vector productoCruz(Vector a, Vector b) {&#xD;&#xA;            return new Vector(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;To apply the product point you need two vectors, and I only have 1 (the ray vector), where do I get the other vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22519" PostHistoryTypeId="36" PostId="8422" RevisionGUID="7326ca77-2460-4f92-bd58-951cd7330d33" CreationDate="2018-12-24T09:24:07.527" UserId="-1" Comment="from https://stackoverflow.com/questions/53803063/rendering-equation-for-photons-carrying-flux" />
  <row Id="22520" PostHistoryTypeId="2" PostId="8422" RevisionGUID="e513fd5f-5f9f-4d2c-8c11-bbeaced9d165" CreationDate="2018-12-16T14:24:52.203" UserDisplayName="CygnusX1" Text="I am trying to understand the mathematical/physical foundations of photon mapping better.&#xD;&#xA;&#xD;&#xA;In the forward photon tracing step it is established, that the rays are carrying portions of total power (flux) rather than radiance as it is typically done in other types of ray-tracing algorithms.&#xD;&#xA;&#xD;&#xA;However, in all articles and tutorials I could never find a precise explanation how such flux-carrying path interacts with materials? In other words - what is the rendering equation for interaction between flux-path and a surface?&#xD;&#xA;&#xD;&#xA;What I typically found is an algorithm, based on Russian Roulette, for building a light path. But not a foundation equation that lead to that algorithm.&#xD;&#xA;&#xD;&#xA;In particular, I am interested in:&#xD;&#xA;&#xD;&#xA;* Should the equation include the cosine of the incident angle or not? I suspect it shouldn't be there, as the power remains constant, but it is spread over a bigger area (thus reducing the radiance at each point, but not total flux).&#xD;&#xA;&#xD;&#xA;* Should the BRDF function be somehow (re)normalized? For example, for a perfect diffusive material, the BRDF is a constant not greater than 1/pi, so that it is energy conserving. But for a flux-based equation, assuming it is different, energy conservation may set a different maximum value.&#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;Note, the very similar question:&#xD;&#xA;&#xD;&#xA;https://stackoverflow.com/questions/13713580/rendering-equation-for-photon-mapping&#xD;&#xA;&#xD;&#xA;refers to a different step of the photon mapping algorithm. It asks for the rendering equation where the radiance is being estimated based on the nearest stored photons. Instead, I am asking for the flux-surface interaction in an earlier stage of the algorithm, when photons are being generated and propagated." ContentLicense="CC BY-SA 4.0" />
  <row Id="22521" PostHistoryTypeId="1" PostId="8422" RevisionGUID="e513fd5f-5f9f-4d2c-8c11-bbeaced9d165" CreationDate="2018-12-16T14:24:52.203" UserDisplayName="CygnusX1" Text="Rendering Equation for photons carrying flux" ContentLicense="CC BY-SA 4.0" />
  <row Id="22522" PostHistoryTypeId="3" PostId="8422" RevisionGUID="e513fd5f-5f9f-4d2c-8c11-bbeaced9d165" CreationDate="2018-12-16T14:24:52.203" UserDisplayName="CygnusX1" Text="|rendering|physics|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22523" PostHistoryTypeId="36" PostId="8423" RevisionGUID="ea5d7aa9-eaa1-47b5-a6c4-6f0765d9e764" CreationDate="2018-12-24T09:24:07.527" UserId="-1" Comment="from https://stackoverflow.com/questions/53803063/rendering-equation-for-photons-carrying-flux/53846528#53846528" />
  <row Id="22524" PostHistoryTypeId="2" PostId="8423" RevisionGUID="a71e6755-5e71-4b5d-8fea-b6b4283dd5d5" CreationDate="2018-12-19T07:34:36.780" UserId="6046" Text="It'd be hell a lot easier if this were on graphicsexchange, since I can't use latex here but anyways.&#xD;&#xA;&#xD;&#xA;In the first pass of Photon Mapping you don't need to use the Flux form of rendering equation. You just divide the original flux coming from the light source among the N photons, then for each photon you use Russian Roulette to determine whether it reflects, transmits or gets absorbed and store the incoming flux.&#xD;&#xA;&#xD;&#xA;In the second pass you need to find radiance but you have information in Flux form. The rendering equation can be simply transformed. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So all you need to do is divide the flux stored for each photon by the area. Note that the Area is often denoted as `A= pi r^2` Since we are concerned with a hemisphere and the underlying area is just a circle.&#xD;&#xA;&#xD;&#xA;About your 2nd point, I don't think the BRDF needs to be re-normalized or whatsoever since the equation is essentially the same. Note that the second term in the last equation is still a radiance written in flux form. (BRDF has units of inverse solid angle thus making the whole term radiance).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qrXgH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/firlX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DqmCY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22525" PostHistoryTypeId="2" PostId="8424" RevisionGUID="b8563fc3-f246-498b-9d36-60710a5f90a9" CreationDate="2018-12-24T10:51:55.420" UserId="182" Text="The simplest solution would be just a multiplication, which would give black edges:&#xD;&#xA;&#xD;&#xA;    combinedColor = sceneColor * edgeRGB.r;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For more control I would suggest something very similar to what @PaulHK proposed in the comments:&#xD;&#xA;&#xD;&#xA;    float opacity = maxEdgeOpacity * (1. - edgeRGB.r);&#xD;&#xA;    combinedColor = mix(sceneColor, edgeColor, opacity);&#xD;&#xA;&#xD;&#xA;`edgeColor` is the desired edge color and `maxEdgeOpacity` is meant to be a parameter between 0 (no edges at all) and 1 (opaque edges), that you both choose to your liking." ContentLicense="CC BY-SA 4.0" />
  <row Id="22529" PostHistoryTypeId="5" PostId="8418" RevisionGUID="040a8d5d-a8a7-4b8b-be23-a71714d4f7cb" CreationDate="2018-12-24T14:29:43.153" UserId="9256" Comment="added 582 characters in body" Text="I have a class Ray and Square&#xD;&#xA;&#xD;&#xA;   public class Rayo {&#xD;&#xA;&#xD;&#xA;    public Point origen;&#xD;&#xA;    public Vector direction;&#xD;&#xA;    &#xD;&#xA;    Square{&#xD;&#xA;    X,Y,Widht, height;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I need intersection between this two, how? my code crossProduct in java is &#xD;&#xA;&#xD;&#xA;    public static Vector productoCruz(Vector a, Vector b) {&#xD;&#xA;            return new Vector(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;To apply the product point you need two vectors, and I only have 1 (the ray vector), where do I get the other vector?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;to the esphera i make this:&#xD;&#xA;&#xD;&#xA;    public double intersection(Ray ray) {&#xD;&#xA;            rayo.direction.normalize();&#xD;&#xA;            Vector v = Vector.subtractPoints(ray.origin, centerSphere);&#xD;&#xA;          &#xD;&#xA;            double b = 2 * Vector.productoDot(ray.direction, v);&#xD;&#xA;            double c = Vector.productoDot(v, v) - radio * radio;&#xD;&#xA;            double d = b * b - 4 * c;&#xD;&#xA;            if (d &gt; 0) {&#xD;&#xA;                double x1 = (-b - sqrt(d)) / 2;&#xD;&#xA;                double x2 = (-b + sqrt(d)) / 2;&#xD;&#xA;                return Math.min(x1, x2);&#xD;&#xA;            }&#xD;&#xA;            return -1;&#xD;&#xA;        }" ContentLicense="CC BY-SA 4.0" />
  <row Id="22530" PostHistoryTypeId="5" PostId="8418" RevisionGUID="516d5a90-0c74-48bc-a0ef-03e3ead88049" CreationDate="2018-12-24T15:14:46.053" UserId="9256" Comment="deleted 587 characters in body" Text="I have a class Ray and Square&#xD;&#xA;&#xD;&#xA;   public class Rayo {&#xD;&#xA;&#xD;&#xA;    public Point origen;&#xD;&#xA;    public Vector direction;&#xD;&#xA;    &#xD;&#xA;    Square{&#xD;&#xA;    X,Y,Widht, height;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I need intersection between this two, how? my code crossProduct in java is &#xD;&#xA;&#xD;&#xA;    public static Vector productoCruz(Vector a, Vector b) {&#xD;&#xA;            return new Vector(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;To apply the product point you need two vectors, and I only have 1 (the ray vector), where do I get the other vector?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22531" PostHistoryTypeId="34" PostId="8297" RevisionGUID="a80b0e5c-d377-424b-a545-ebb287884cfb" CreationDate="2018-12-25T06:03:05.610" UserId="-1" Comment="53" />
  <row Id="22532" PostHistoryTypeId="2" PostId="8426" RevisionGUID="45f94133-874e-45f0-963e-ca6eec822c7e" CreationDate="2018-12-25T14:00:53.963" UserId="9909" Text="Say I have a scene graph, and each node has a scale, rotation, and translation. Can I combine these into a single scale, rotation, and translation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22533" PostHistoryTypeId="1" PostId="8426" RevisionGUID="45f94133-874e-45f0-963e-ca6eec822c7e" CreationDate="2018-12-25T14:00:53.963" UserId="9909" Text="Composition of decomposed transformations" ContentLicense="CC BY-SA 4.0" />
  <row Id="22534" PostHistoryTypeId="3" PostId="8426" RevisionGUID="45f94133-874e-45f0-963e-ca6eec822c7e" CreationDate="2018-12-25T14:00:53.963" UserId="9909" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22535" PostHistoryTypeId="2" PostId="8427" RevisionGUID="395ba54e-20e8-4117-9459-9699a3fffe9f" CreationDate="2018-12-25T17:52:23.550" UserId="7644" Text="I don't have any direct experience doing this so I might be missing an obvious solution or tool. That said, what you describe is in programming terms comparatively easy to achieve. The basic structure of such a custom processing would be:&#xD;&#xA;&#xD;&#xA;1. Open the image file and get access to the array of pixels it contains.&#xD;&#xA;2. Iterate over all the pixels and inspect/transform however you want.&#xD;&#xA;3. Write out the resulting modified image in the desired format.&#xD;&#xA;&#xD;&#xA;Both Gimp ([1][1], [2][2]) and Photoshop ([tutorial][3]) provide *scripting or plugins support* which will allow you to provide custom logic for step 2 and handle the rest for you. I don't have any experience with either, but from a very quick overview, I recommend that you use Javascript, Python or another scripting language which will be much more accessible as a new programmer than a language like C.&#xD;&#xA;&#xD;&#xA;Another option I found outside of an image editor that looks good is the Python Imaging Library. Here is a very relevant other question on SO: https://stackoverflow.com/questions/36468530/changing-pixel-color-value-in-pil&#xD;&#xA;&#xD;&#xA;From it, I was able to write the following Python script that does what you asked:&#xD;&#xA;&#xD;&#xA;	from PIL import Image&#xD;&#xA;&#xD;&#xA;	img = Image.open(&quot;input.png&quot;)&#xD;&#xA;	pixels = img.load() # create the pixel map&#xD;&#xA;&#xD;&#xA;	# configuration&#xD;&#xA;	channel = 0 # 0 = red, 1 = green, 2 = blue&#xD;&#xA;	change_amount = 2 # can be -2 for decrease&#xD;&#xA;	limit = 178&#xD;&#xA;&#xD;&#xA;	for i in range(img.size[0]): # for every pixel (in 2D):&#xD;&#xA;		for j in range(img.size[1]):&#xD;&#xA;			if pixels[i,j][channel] &lt; limit:&#xD;&#xA;				# Only modify pixels below the set limit.&#xD;&#xA;				# The following &quot;strange&quot; code is used because Python tuples can't be modified&#xD;&#xA;				# directly. The tuple is transformed into a (mutable) list and moved back again&#xD;&#xA;				# to a tuple afterwards. You can safely ignore this and concentrate on the&#xD;&#xA;				# second line that actually modifies a channel's value.&#xD;&#xA;				color = list(pixels[i,j])&#xD;&#xA;				# Increase (or decrease for a negative change_amount value) the chosen channel.&#xD;&#xA;				color[channel] += change_amount&#xD;&#xA;				pixels[i,j] = tuple(color)&#xD;&#xA;&#xD;&#xA;	img.save(&quot;out.png&quot;)&#xD;&#xA;&#xD;&#xA;This is untested code, but it shows how to translate what you want into code. You already described what you wanted in a very programmer-friendly manner so the translation is almost direct. The sky is the limit then as to what you can do with pixels once you load them in a custom program to manipulate them.&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.gimp.org/plug-ins.html&#xD;&#xA;  [2]: https://www.gimp.org/docs/python/index.html&#xD;&#xA;  [3]: https://www.photoshoptutorials.ws/photoshop-tutorials/basics/manipulate-an-image-with-scripting/?doing_wp_cron=1545753669.9555869102478027343750" ContentLicense="CC BY-SA 4.0" />
  <row Id="22536" PostHistoryTypeId="6" PostId="8422" RevisionGUID="85bebfbb-9a43-4551-82fa-9170e0df8150" CreationDate="2018-12-25T19:29:47.877" UserId="9911" Comment="added tags" Text="|raytracing|rendering|physically-based|physics|photon-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22537" PostHistoryTypeId="2" PostId="8428" RevisionGUID="81b4c8bc-6532-4f6f-9a8a-793d50df2aae" CreationDate="2018-12-25T21:26:40.780" UserId="48" Text="Yes you can, provided that all the nodes' scales are only _uniform_ scaling—the same scaling factor along all three axes. If there is nonuniform scaling (different factors along different axes) then things get more complicated, and the composed transformation generally can't be decomposed cleanly into scale, rotation, and translation.&#xD;&#xA;&#xD;&#xA;One way to accomplish this is to convert all the individual nodes' transforms into 4×4 matrix form, multiply the matrices down the tree from root to leaf, then decompose the resulting matrix (see [this answer](https://computergraphics.stackexchange.com/a/4282/48) for how to do the decomposition).&#xD;&#xA;&#xD;&#xA;However, if you have all the transforms in TRS form (translate, rotate, scale—assuming column vector convention) and you want the final transform in TRS form, you can also combine them directly.&#xD;&#xA;&#xD;&#xA;1. The final scale is just the product of all the individual nodes' scales&#xD;&#xA;2. The final rotation is just the composition of all the individual nodes' rotations (in quaternion form for example)&#xD;&#xA;3. The final translation is made by summing the translation vectors, but transforming each vector by the composite scale and rotation of all the nodes above it in the tree. For example if you have a transformation $T_1 R_1 S_1 T_2 R_2 S_2 T_3 R_3 S_3$ (numbering from the root down to the leaf), then the final translation is $t_1 + (R_1 S_1) t_2 + (R_1 S_1 R_2 S_2) t_3$." ContentLicense="CC BY-SA 4.0" />
  <row Id="22550" PostHistoryTypeId="2" PostId="8431" RevisionGUID="cec33228-4ea3-4142-9b04-cefd9251f104" CreationDate="2018-12-28T05:26:55.727" UserId="9922" Text="(Note that as far as attempts go, I can't find anything that helps me)&#xD;&#xA;&#xD;&#xA;I have a 3D polygon, and for simplicity's sake it's going to be the one below:&#xD;&#xA;&#xD;&#xA;[![Basic Textured Polygon][1]][1]&#xD;&#xA;&#xD;&#xA;It is textured using the UV map below:&#xD;&#xA;&#xD;&#xA;[![Basic Texture UV][2]][2]&#xD;&#xA;&#xD;&#xA;*Side Note: I just found the texture on Google. It is not being used in any manner other than solely to demonstrate my question.*&#xD;&#xA;&#xD;&#xA;I plan on 3D printing the polygon. Since I suck at painting, I want to print the textures for each face so I can glue/decal them onto the correct faces.&#xD;&#xA;&#xD;&#xA;My question is: How can I go from a UV texture map to individual polygon faces (and 1 texture per face) that is correctly scaled to fit the face. I want something like below:&#xD;&#xA;&#xD;&#xA;[![Desired Outcome][3]][3]&#xD;&#xA;&#xD;&#xA;Is there **any** way to do this? I don't care about width * height as I can manage that on my own, but I need the textures to be distorted just like how they are on the corresponding face of the polygon.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KQ8Ct.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/UaFcs.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/s8hCn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22551" PostHistoryTypeId="1" PostId="8431" RevisionGUID="cec33228-4ea3-4142-9b04-cefd9251f104" CreationDate="2018-12-28T05:26:55.727" UserId="9922" Text="Export Distorted Polygon Textures Per Face" ContentLicense="CC BY-SA 4.0" />
  <row Id="22552" PostHistoryTypeId="3" PostId="8431" RevisionGUID="cec33228-4ea3-4142-9b04-cefd9251f104" CreationDate="2018-12-28T05:26:55.727" UserId="9922" Text="|texture|3d|uv-mapping|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22554" PostHistoryTypeId="4" PostId="8431" RevisionGUID="762b1bd8-39ad-46ff-80b9-42723f9464bb" CreationDate="2018-12-28T14:40:04.470" UserId="9922" Comment="edited title" Text="Export Model Textures Per Face" ContentLicense="CC BY-SA 4.0" />
  <row Id="22560" PostHistoryTypeId="50" PostId="7997" RevisionGUID="b3fcb900-38b2-47e0-880e-71edbe2d639d" CreationDate="2018-12-29T09:03:05.663" UserId="-1" />
  <row Id="22563" PostHistoryTypeId="2" PostId="8433" RevisionGUID="1951246f-26cf-4272-9aaa-192df7da52af" CreationDate="2018-12-29T22:51:16.180" UserId="7644" Text="UV mapping assigns fixed positions in the texture to each vertex. You'll have to distort the image so that it maps to a constant area in &quot;model size&quot; so to speak. I found the following other question that will probably give you a solution: https://blender.stackexchange.com/questions/22872/unwrap-uv-map-proportionally-to-object-size&#xD;&#xA;&#xD;&#xA;It won't give disjointed parts like in your image, but I think it will still provide what you're looking for.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22564" PostHistoryTypeId="2" PostId="8434" RevisionGUID="763f5389-eb7e-49ea-91ac-7cb27f272b96" CreationDate="2018-12-30T07:39:13.133" UserId="9886" Text="Here is the change to the code that made the whole thing work correctly:&#xD;&#xA;&#xD;&#xA;   	@Override public boolean touchDragged( int screenX, int screenY, int pointer )&#xD;&#xA;    {&#xD;&#xA;		lastX -= screenX;&#xD;&#xA;		lastY -= screenY;&#xD;&#xA;&#xD;&#xA;		// distance of mouse movement&#xD;&#xA;		screenAng = Vector3.len( lastX, lastY, 0f );&#xD;&#xA;		// direction vector of the AOR&#xD;&#xA;		screenAOR.set( lastY/screenAng, lastX/screenAng, 0f );&#xD;&#xA;&#xD;&#xA;		if ( touchedButton == 0 )&#xD;&#xA;		{	// rotate the part&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a model rotation&#xD;&#xA;			&#xD;&#xA;			Matrix4 camT, camR, camRi, modT, modR;&#xD;&#xA;			camT = new Matrix4();&#xD;&#xA;			camR = new Matrix4();&#xD;&#xA;			modT = new Matrix4();&#xD;&#xA;			modR = new Matrix4();&#xD;&#xA;			&#xD;&#xA;			decompose( camera.view, camT, camR );&#xD;&#xA;			camRi = camR.cpy().inv();&#xD;&#xA;		&#xD;&#xA;			decompose( cubes[ selectedCube ].modelInstance.transform, modT, modR );&#xD;&#xA;			&#xD;&#xA;			tempMat.idt()&#xD;&#xA;					.mul( modT )&#xD;&#xA;					.mul( camRi )&#xD;&#xA;					.rotate( screenAOR, -screenAng )&#xD;&#xA;					.mul( camR )&#xD;&#xA;					.mul( modR );&#xD;&#xA;			&#xD;&#xA;			cubes[ selectedCube ].modelInstance.transform.set( tempMat );&#xD;&#xA;		}&#xD;&#xA;		else if ( touchedButton == 1 )&#xD;&#xA;		{	// rotate the camera&#xD;&#xA;			&#xD;&#xA;			// transform the AOR from screen CS to camera CS&#xD;&#xA;			&#xD;&#xA;			// get the camera transformation matrix&#xD;&#xA;			tempMat.set( camera.view );&#xD;&#xA;			tempMat.translate( camera.position );&#xD;&#xA;			tempMat.inv();&#xD;&#xA;			&#xD;&#xA;			// transform the screen AOR to a world AOR&#xD;&#xA;			worldAOR = transform( tempMat, screenAOR, worldAOR ).nor();&#xD;&#xA;			&#xD;&#xA;			// apply the rotation of the angle about the world AOR to the camera&#xD;&#xA;			camera.rotateAround( Vector3.Zero, worldAOR, screenAng/5.5f );&#xD;&#xA;			camera.update();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		lastX = screenX;&#xD;&#xA;		lastY = screenY;&#xD;&#xA;		Gdx.graphics.requestRendering();&#xD;&#xA;		return true;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// --------------------------------------------------------------------- //&#xD;&#xA;	Vector3 transform( Matrix4 mat, Vector3 from, Vector3 to )&#xD;&#xA;	{&#xD;&#xA;		// transform a vector according to a transformation matrix&#xD;&#xA;		&#xD;&#xA;		to.x = from.dot( mat.val[ Matrix4.M00 ], mat.val[ Matrix4.M01 ],&#xD;&#xA;				mat.val[ Matrix4.M02 ] )+mat.val[ Matrix4.M03 ];&#xD;&#xA;		to.y = from.dot( mat.val[ Matrix4.M10 ], mat.val[ Matrix4.M11 ],&#xD;&#xA;				mat.val[ Matrix4.M12 ] )+mat.val[ Matrix4.M13 ];&#xD;&#xA;		to.z = from.dot( mat.val[ Matrix4.M20 ], mat.val[ Matrix4.M21 ],&#xD;&#xA;				mat.val[ Matrix4.M22 ] )+mat.val[ Matrix4.M23 ];&#xD;&#xA;		return to;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// --------------------------------------------------------------------- //&#xD;&#xA;	void decompose( Matrix4 m, Matrix4 t, Matrix4 r )&#xD;&#xA;	{&#xD;&#xA;		Matrix4 I4 = new Matrix4(); // Identity&#xD;&#xA;	    for ( int i = 0; i &lt; 4; i++ )&#xD;&#xA;	    {&#xD;&#xA;	        for ( int j = 0; j &lt; 4; j++ )&#xD;&#xA;	        {&#xD;&#xA;	            if (i == 3 || j == 3)&#xD;&#xA;	            {&#xD;&#xA;	                r.val[ i*4+j ] = I4.val[ i*4+j ];&#xD;&#xA;	                t.val[ i*4+j ] = m.val[ i*4+j ];&#xD;&#xA;	            }&#xD;&#xA;	            else&#xD;&#xA;	            {&#xD;&#xA;	                r.val[ i*4+j ] = m.val[ i*4+j ];&#xD;&#xA;	                t.val[ i*4+j ] = I4.val[ i*4+j ];&#xD;&#xA;	            }&#xD;&#xA;	        }&#xD;&#xA;	    }&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22565" PostHistoryTypeId="2" PostId="8435" RevisionGUID="1f1b3711-a151-4da3-b5bf-10225a5d332f" CreationDate="2018-12-30T15:24:24.067" UserId="8565" Text="I am trying to implement conservative voxelization as part of real time GI in my hobby rendering engine. I find this [article][1] by NVIDIA. I am stuck at understanding the second algorithm. The problem that I have is that I don't understand this section of the article&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&gt; We describe both algorithms in window space, for clarity, but in&#xD;&#xA;&gt; practice it is impossible to work in window space, because the vertex&#xD;&#xA;&gt; program is executed before the clipping and perspective projection.&#xD;&#xA;&gt; Fortunately, our reasoning maps very simply to clip space. For the&#xD;&#xA;&gt; moment, let us ignore the z component of the vertices (which is used&#xD;&#xA;&gt; only to interpolate a depth-buffer value). Doing so allows us to&#xD;&#xA;&gt; describe a line through each edge of the input triangle as a plane in&#xD;&#xA;&gt; homogeneous (x c , y c , w c )-space. The plane is defined by the two&#xD;&#xA;&gt; vertices on the edge of the input triangle, as well as the position of&#xD;&#xA;&gt; the viewer, which is the origin, (0, 0, 0). Because all of the planes&#xD;&#xA;&gt; pass through the origin, we get plane equations of the form&#xD;&#xA;&gt; &#xD;&#xA;&gt; ax c + by c + cw c = 0  a(xw c ) + b (yw c ) + cw c ) + cw c = 0  ax +&#xD;&#xA;&gt; by + c = 0&#xD;&#xA;&gt; &#xD;&#xA;&gt; The planes are equivalent to lines in two dimensions. In many of our&#xD;&#xA;&gt; computations, we use the normal of an edge, which is defined by (a, b)&#xD;&#xA;&gt; from the plane equation.&#xD;&#xA;&#xD;&#xA;First, I don't understand how to visualize a plane that use w value as one of this coordinates and what is the meaning of this plane. And then later in the article, they calculate this plane by doing a cross product like this&#xD;&#xA;&#xD;&#xA;    // Compute equations of the planes through the two edges&#xD;&#xA;    &#xD;&#xA;    float3 plane[2];&#xD;&#xA;    &#xD;&#xA;    plane[0] = cross(currentPos.xyw - prevPos.xyw, prevPos.xyw);&#xD;&#xA;    &#xD;&#xA;    plane[1] = cross(nextPos.xyw - currentPos.xyw, currentPos.xyw);&#xD;&#xA;&#xD;&#xA;Again, I still don't understand why this is true. Can someone please explain in more detail or provide me some visualization of this algorithm ?&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22566" PostHistoryTypeId="1" PostId="8435" RevisionGUID="1f1b3711-a151-4da3-b5bf-10225a5d332f" CreationDate="2018-12-30T15:24:24.067" UserId="8565" Text="Comprehensive explanation of conservative rasterization algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="22567" PostHistoryTypeId="3" PostId="8435" RevisionGUID="1f1b3711-a151-4da3-b5bf-10225a5d332f" CreationDate="2018-12-30T15:24:24.067" UserId="8565" Text="|global-illumination|rasterizer|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22569" PostHistoryTypeId="5" PostId="1770" RevisionGUID="a148be3f-98bd-4410-9bdf-84f6a1f949b5" CreationDate="2018-12-30T21:49:30.093" UserId="5778" Comment="image fixed (inlining HTTP images doesn't work anymore); for more info, see https://gist.github.com/Glorfindel83/9d954d34385d2ac2597bbe864466259f" Text="Virtual Texturing is the logical extreme of texture atlases.&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;A texture atlas is a single giant texture that contains textures for individual meshes inside it:&#xD;&#xA;&#xD;&#xA;![Texture Atlas Example][1]&#xD;&#xA;&#xD;&#xA;Texture atlases became popular due to the fact that changing textures causes a full pipeline flush on the GPU. When creating the meshes, the UVs are compressed/shifted so that they represent the correct 'portion' of the whole texture atlas. &#xD;&#xA;&#xD;&#xA;As @nathan-reed mentioned in the comments, one of the main drawbacks of texture atlases is losing wrap modes such as repeat, clamp, border, etc. In addition, if the textures don't have enough border around them, you can accidentally sample from an adjacent texture when doing filtering. This can lead to bleeding artifacts.&#xD;&#xA;&#xD;&#xA;Texture Atlases do have one major limitation: size. Graphics APIs place a soft limit on how big a texture can be. That said, graphics memory is only so big. So there is also a hard limit on texture size, given by the size of your v-ram. Virtual textures solve this problem, by borrowing concepts from [virtual memory][2]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Virtual textures exploit the fact that in most scenes, you only see a small portion of all the textures. So, only that subset of textures need to be in vram. The rest can be in main RAM, or on disk.&#xD;&#xA;&#xD;&#xA;There are a few ways to implement it, but I will explain the implementation described by Sean Barrett in his [GDC talk][3]. (which I highly recommend watching)&#xD;&#xA;&#xD;&#xA;We have three main elements: the virtual texture, the physical texture, and the lookup table.&#xD;&#xA;&#xD;&#xA;![Virtual Texture][4]&#xD;&#xA;&#xD;&#xA;The virtual texture represents the theoretical mega atlas we would have if we had enough vram to fit everything. It doesn't actually exist in memory anywhere. The physical texture represents what pixel data we actually have in vram. The lookup table is the mapping between the two. For convenience, we break all three elements into equal sized tiles, or pages. &#xD;&#xA;&#xD;&#xA;The lookup table stores the location of the top-left corner of the tile in the physical texture. So, given a UV to the entire virtual texture, how do we get the corresponding UV for the physical texture?&#xD;&#xA;&#xD;&#xA;First, we need to find the location of the page within the physical texture. Then we need to calculate the location of the UV within the page. Finally we can add these two offsets together to get the location of the UV within the physical texture&#xD;&#xA;&#xD;&#xA;    float2 pageLocInPhysicalTex = ...&#xD;&#xA;    float2 inPageLocation = ...&#xD;&#xA;    float2 physicalTexUV = pageLocationInPhysicalTex + inPageLocation;&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**Calculating pageLocInPhysicalTex** &#xD;&#xA;&#xD;&#xA;If we make the lookup table the same size as the number of tiles in the virtual texture, we can just sample the lookup table with nearest neighbor sampling and we will get the location of the top-left corner of the page within the physical texture.&#xD;&#xA;&#xD;&#xA;    float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);&#xD;&#xA;&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;**Calculating inPageLocation**&#xD;&#xA;&#xD;&#xA;inPageLocation is a UV coordinate that is relative to the top-left of the page, rather than to the top-left of the whole texture. &#xD;&#xA;&#xD;&#xA;One way to calculate this is by subtracting off the UV of the top left of the page, then scaling to the size of the page. However, this is quite a bit of math. Instead, we can exploit how IEEE floating point is represented. IEEE floating point stores the fractional part of a number by a series of base 2 fractions.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;In this example, the number is:&#xD;&#xA;&#xD;&#xA;    number = 0 + (1/2) + (1/8) + (1/16) = 0.6875&#xD;&#xA;&#xD;&#xA;Now lets look at a simplified version of the virtual texture:&#xD;&#xA;&#xD;&#xA;![Simple Virtual Texture][6]&#xD;&#xA;&#xD;&#xA;The 1/2 bit tells us if we're in the left half of the texture or the right. The 1/4 bit tells us which quarter of the half we're in. In this example, since the texture is split into 16, or 4 to a side, these first two bits tell us what page we're in. The remaining bits tell us the location inside the page.&#xD;&#xA;&#xD;&#xA;We can get the remaining bits by shifting the float with exp2() and stripping them out with fract()&#xD;&#xA;&#xD;&#xA;    float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));&#xD;&#xA;    inPageLocation = fract(inPageLocation);&#xD;&#xA;&#xD;&#xA;Where numTiles is a int2 giving the number of tiles per side of the texture. In our example, this would be (4, 4)&#xD;&#xA;&#xD;&#xA;So let's calculate the inPageLocation for the green point, (x,y) = (0.6875, 0.375)&#xD;&#xA;&#xD;&#xA;    inPageLocation = float2(0.6875, 0.375) * exp2(sqrt(int2(4, 4));&#xD;&#xA;                   = float2(0.6875, 0.375) * int2(2, 2);&#xD;&#xA;                   = float2(1.375, 0.75);&#xD;&#xA;    &#xD;&#xA;    inPageLocation = fract(float2(1.375, 0.75));&#xD;&#xA;                   = float2(0.375, 0.75);&#xD;&#xA;&#xD;&#xA;One last thing to do before we're done. Currently, inPageLocation is a UV coordinate in the virtual texture 'space'. However, we want a UV coordinate in the physical texture 'space'. To do this we just have to scale inPageLocation by the ratio of virtual texture size to physical texture size&#xD;&#xA;&#xD;&#xA;    inPageLocation *= physicalTextureSize / virtualTextureSize;&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So the finished function is:&#xD;&#xA;&#xD;&#xA;    float2 CalculatePhysicalTexUV(float2 virtTexUV, Texture2D&lt;float2&gt; lookupTable, uint2 physicalTexSize, uint2 virtualTexSize, uint2 numTiles) {&#xD;&#xA;        float2 pageLocInPhysicalTex = lookupTable.Sample(virtTexUV, nearestNeighborSampler);&#xD;&#xA;        &#xD;&#xA;        float2 inPageLocation = virtTexUV * exp2(sqrt(numTiles));&#xD;&#xA;        inPageLocation = fract(inPageLocation);&#xD;&#xA;        inPageLocation *= physicalTexSize / virtualTexSize;&#xD;&#xA;        &#xD;&#xA;        return pageLocInPhysicalTex + inPageLocation;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2h1hm.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Virtual_memory&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=MejJL87yNgI&#xD;&#xA;  [4]: https://i.stack.imgur.com/SFNvJ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/48VfH.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Jj8K9.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22570" PostHistoryTypeId="24" PostId="1770" RevisionGUID="a148be3f-98bd-4410-9bdf-84f6a1f949b5" CreationDate="2018-12-30T21:49:30.093" Comment="Proposed by 5778 approved by 310 edit id of 451" ContentLicense="CC BY-SA 4.0" />
  <row Id="22571" PostHistoryTypeId="2" PostId="8436" RevisionGUID="c5b055ce-1c1b-4806-833a-1c6424998fd2" CreationDate="2018-12-30T22:44:41.340" UserId="9934" Text="I'm not sure what exactly you mean by &#xD;&#xA;&#xD;&#xA;&gt; how to visualize a plane that use w value as one of this coordinates&#xD;&#xA;&#xD;&#xA;but here's a sketch that will, hopefully, clarify this sentence:&#xD;&#xA;&#xD;&#xA;&gt;a line through each edge of the input triangle as a plane in homogeneous (x c , y c , w c )-space&#xD;&#xA;&#xD;&#xA;I've used uppercase letters for clip-space, and lowercase letters for window space.&#xD;&#xA;&#xD;&#xA;[![plane through 3D points that project onto a 2D screen][1]][1]&#xD;&#xA;&#xD;&#xA;Let's say AB is an edge of your original triangle.&#xD;&#xA;It projects to an edge ab in window coordinates.&#xD;&#xA;Point A is defined using [X&lt;sub&gt;A&lt;/sub&gt;, Y&lt;sub&gt;A&lt;/sub&gt;, Z&lt;sub&gt;A&lt;/sub&gt;, W&lt;sub&gt;A&lt;/sub&gt;] coordinates. After projection it will have coordinates [x&lt;sub&gt;A&lt;/sub&gt;, y&lt;sub&gt;A&lt;/sub&gt;] = [X&lt;sub&gt;A&lt;/sub&gt;/W&lt;sub&gt;A&lt;/sub&gt;, Y&lt;sub&gt;A&lt;/sub&gt;/W&lt;sub&gt;A&lt;/sub&gt;] and the value Z&lt;sub&gt;A&lt;/sub&gt;/W&lt;sub&gt;A&lt;/sub&gt; will be used to determine which object is closer to the camera at this point.&#xD;&#xA;So your [X, Y, Z, W] always turns into a [X/W, Y/W] in the end. You can see that Z doesn't play any role in where the point is going to end up on the screen. So we just throw it away for now and interpret the remaining [X, Y, W] as 3D coordinates of the points.&#xD;&#xA;&#xD;&#xA;Now we have point A = [X&lt;sub&gt;A&lt;/sub&gt;, Y&lt;sub&gt;A&lt;/sub&gt;, W&lt;sub&gt;A&lt;/sub&gt;] and B = [X&lt;sub&gt;B&lt;/sub&gt;, Y&lt;sub&gt;B&lt;/sub&gt;, W&lt;sub&gt;B&lt;/sub&gt;].&#xD;&#xA;&#xD;&#xA;The projected point **a** will lie on the line that connects [0, 0, 0] and A.&#xD;&#xA;Point **b** will lie on the line [0, 0, 0] and B. Three points define a plane, and a normal to the plane defined by 3 points can be found as a cross product of two vectors in this plane (OA and OB, for example). &#xD;&#xA;&quot;For a convex polygon (such as a triangle), a surface normal can be calculated as the vector cross product of two (non-parallel) edges of the polygon.&quot;&#xD;&#xA;More on why in Wikipedia [here](https://en.wikipedia.org/wiki/Normal_(geometry)) and [here](https://en.wikipedia.org/wiki/Cross_product).&#xD;&#xA;&#xD;&#xA;The thing you need to remember is that W is your 3'rd coordinate, not Z! I know, it's very counter-intuitive, but it is what it is, Z only carries depth information, it does not affect position of objects on the screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope I cleared it up for you a bit.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SHOvp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22572" PostHistoryTypeId="5" PostId="8436" RevisionGUID="ca22c137-d68e-46d2-b626-ac3ebd005df2" CreationDate="2018-12-30T23:45:28.957" UserId="9934" Comment="added 279 characters in body" Text="I'm not sure what exactly you mean by &#xD;&#xA;&#xD;&#xA;&gt; how to visualize a plane that use w value as one of this coordinates&#xD;&#xA;&#xD;&#xA;but here's a sketch that will, hopefully, clarify this sentence:&#xD;&#xA;&#xD;&#xA;&gt;a line through each edge of the input triangle as a plane in homogeneous (x c , y c , w c )-space&#xD;&#xA;&#xD;&#xA;I've used uppercase letters for clip-space, and lowercase letters for window space.&#xD;&#xA;&#xD;&#xA;[![plane through 3D points that project onto a 2D screen][1]][1]&#xD;&#xA;&#xD;&#xA;Let's say AB is an edge of your original triangle.&#xD;&#xA;It projects to an edge ab in window coordinates.&#xD;&#xA;Point A is defined using [X&lt;sub&gt;A&lt;/sub&gt;, Y&lt;sub&gt;A&lt;/sub&gt;, Z&lt;sub&gt;A&lt;/sub&gt;, W&lt;sub&gt;A&lt;/sub&gt;] coordinates. After projection it will have coordinates [x&lt;sub&gt;A&lt;/sub&gt;, y&lt;sub&gt;A&lt;/sub&gt;] = [X&lt;sub&gt;A&lt;/sub&gt;/W&lt;sub&gt;A&lt;/sub&gt;, Y&lt;sub&gt;A&lt;/sub&gt;/W&lt;sub&gt;A&lt;/sub&gt;] and the value Z&lt;sub&gt;A&lt;/sub&gt;/W&lt;sub&gt;A&lt;/sub&gt; will be used to determine which object is closer to the camera at this point.&#xD;&#xA;So your [X, Y, Z, W] always turns into a [X/W, Y/W] in the end. You can see that Z doesn't play any role in where the point is going to end up on the screen. So we just throw it away for now and interpret the remaining [X, Y, W] as 3D coordinates of the points.&#xD;&#xA;&#xD;&#xA;Now we have point A = [X&lt;sub&gt;A&lt;/sub&gt;, Y&lt;sub&gt;A&lt;/sub&gt;, W&lt;sub&gt;A&lt;/sub&gt;] and B = [X&lt;sub&gt;B&lt;/sub&gt;, Y&lt;sub&gt;B&lt;/sub&gt;, W&lt;sub&gt;B&lt;/sub&gt;].&#xD;&#xA;&#xD;&#xA;The projected point **a** will lie on the line that connects [0, 0, 0] and A.&#xD;&#xA;Point **b** will lie on the line [0, 0, 0] and B. Three points define a plane, and a normal to the plane defined by 3 points can be found as a cross product of two vectors in this plane (OA and OB, for example). &#xD;&#xA;&quot;For a convex polygon (such as a triangle), a surface normal can be calculated as the vector cross product of two (non-parallel) edges of the polygon.&quot;&#xD;&#xA;More on why in Wikipedia [here](https://en.wikipedia.org/wiki/Normal_(geometry)) and [here](https://en.wikipedia.org/wiki/Cross_product).&#xD;&#xA;&#xD;&#xA;Generally this moves your problem from 2D domain in the projected coordinates into a 3D domain of not-yet-projected points. The 2D and 3D are &quot;dual&quot; to each other. For example, if a point lies in the plane of OAB, it for sure lies on the line through **ab** (and vice versa).&#xD;&#xA;&#xD;&#xA;The thing you need to remember is that W is your 3'rd coordinate, not Z! I know, it's very counter-intuitive, but it is what it is, Z only carries depth information, it does not affect position of objects on the screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope I cleared it up for you a bit.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SHOvp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22573" PostHistoryTypeId="5" PostId="8435" RevisionGUID="bb3ce7c2-8765-4e87-9210-3b20ca1f3a59" CreationDate="2018-12-31T02:45:44.980" UserId="8565" Comment="added 742 characters in body" Text="I am trying to implement conservative voxelization as part of real time GI in my hobby rendering engine. I find this [article][1] by NVIDIA. I am stuck at understanding the second algorithm. The problem that I have is that I don't understand this section of the article&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&gt; We describe both algorithms in window space, for clarity, but in&#xD;&#xA;&gt; practice it is impossible to work in window space, because the vertex&#xD;&#xA;&gt; program is executed before the clipping and perspective projection.&#xD;&#xA;&gt; Fortunately, our reasoning maps very simply to clip space. For the&#xD;&#xA;&gt; moment, let us ignore the z component of the vertices (which is used&#xD;&#xA;&gt; only to interpolate a depth-buffer value). Doing so allows us to&#xD;&#xA;&gt; describe a line through each edge of the input triangle as a plane in&#xD;&#xA;&gt; homogeneous (x c , y c , w c )-space. The plane is defined by the two&#xD;&#xA;&gt; vertices on the edge of the input triangle, as well as the position of&#xD;&#xA;&gt; the viewer, which is the origin, (0, 0, 0). Because all of the planes&#xD;&#xA;&gt; pass through the origin, we get plane equations of the form&#xD;&#xA;&gt; &#xD;&#xA;&gt; ax c + by c + cw c = 0  a(xw c ) + b (yw c ) + cw c ) + cw c = 0  ax +&#xD;&#xA;&gt; by + c = 0&#xD;&#xA;&gt; &#xD;&#xA;&gt; The planes are equivalent to lines in two dimensions. In many of our&#xD;&#xA;&gt; computations, we use the normal of an edge, which is defined by (a, b)&#xD;&#xA;&gt; from the plane equation.&#xD;&#xA;&#xD;&#xA;First, I don't understand how to visualize a plane that use w value as one of this coordinates and what is the meaning of this plane. And then later in the article, they calculate this plane by doing a cross product like this&#xD;&#xA;&#xD;&#xA;    // Compute equations of the planes through the two edges&#xD;&#xA;    &#xD;&#xA;    float3 plane[2];&#xD;&#xA;    &#xD;&#xA;    plane[0] = cross(currentPos.xyw - prevPos.xyw, prevPos.xyw);&#xD;&#xA;    &#xD;&#xA;    plane[1] = cross(nextPos.xyw - currentPos.xyw, currentPos.xyw);&#xD;&#xA;&#xD;&#xA;Again, I still don't understand why this is true. &#xD;&#xA;&#xD;&#xA;Is there any relation between the plane normal with the line normal because in the next part, the algorithm use this normal xy value to move the line outwards by substracting the z value of this plane.&#xD;&#xA;&#xD;&#xA;    // Move the planes by the appropriate semidiagonal&#xD;&#xA;    &#xD;&#xA;    plane[0].z -= dot(hPixel.xy, abs(plane[0].xy));&#xD;&#xA;    &#xD;&#xA;    plane[1].z -= dot(hPixel.xy, abs(plane[1].xy));&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Compute the intersection point of the planes.&#xD;&#xA;    &#xD;&#xA;    float4 finalPos;&#xD;&#xA;    &#xD;&#xA;    finalPos.xyw = cross(plane[0], plane[1]);&#xD;&#xA;&#xD;&#xA;I can understand it if the xy component of the plane's normal is actually the normal of the line as well and the z value of the plane's normal represent the line distance from point (0, 0)&#xD;&#xA;&#xD;&#xA;Can someone please explain in more detail or provide me some visualization of this algorithm ?&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22574" PostHistoryTypeId="50" PostId="8321" RevisionGUID="d5bb0528-e96e-4e49-8b8d-3cc177531497" CreationDate="2019-01-01T03:02:30.613" UserId="-1" />
  <row Id="22575" PostHistoryTypeId="2" PostId="8437" RevisionGUID="53ba9a37-a45c-4187-b775-6074ecb1dbdd" CreationDate="2019-01-01T04:35:46.590" UserId="5846" Text="In [this question](https://retrocomputing.stackexchange.com/q/8627/7118) I generated the images below to explain why I can't use TTFs for that 1-bit display application.&#xD;&#xA;&#xD;&#xA;But now I would like to understand *from the perspective of a non-expert*, why is some black-on-white text on my screen made from gray pixels, while other text is made from color pixels?&#xD;&#xA;&#xD;&#xA;Gray on left is a screenshot from the SE question editor window, color on right is from a Finder window in MacOS.&#xD;&#xA;&#xD;&#xA;The &quot;Why?&quot; should have two elements, one might be &quot;because Apple does it that way&quot; but the other would hopefully help me understand *why Apple does it that way* if that is in fact the case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4] [![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [4]: https://i.stack.imgur.com/wAiuH.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/IyBx3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22576" PostHistoryTypeId="1" PostId="8437" RevisionGUID="53ba9a37-a45c-4187-b775-6074ecb1dbdd" CreationDate="2019-01-01T04:35:46.590" UserId="5846" Text="Why does some text on my laptop have gray-scale pixels and some have color pixels?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22577" PostHistoryTypeId="3" PostId="8437" RevisionGUID="53ba9a37-a45c-4187-b775-6074ecb1dbdd" CreationDate="2019-01-01T04:35:46.590" UserId="5846" Text="|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22578" PostHistoryTypeId="50" PostId="6359" RevisionGUID="8c85fd94-ea71-4a5b-bdf1-e7b133442ddc" CreationDate="2019-01-01T05:00:19.710" UserId="-1" />
  <row Id="22579" PostHistoryTypeId="5" PostId="8437" RevisionGUID="c5ac64a2-709c-4163-839c-e5bd0237227e" CreationDate="2019-01-01T05:04:41.767" UserId="5846" Comment="added 293 characters in body" Text="In [this question](https://retrocomputing.stackexchange.com/q/8627/7118) I generated the images below to explain why I can't use TTFs for that 1-bit display application.&#xD;&#xA;&#xD;&#xA;But now I would like to understand *from the perspective of a non-expert*, why is some black-on-white text on my screen made from gray pixels, while other text is made from color pixels?&#xD;&#xA;&#xD;&#xA;Gray on left is a screenshot from the SE question editor window, color on right is from a Finder window in MacOS.&#xD;&#xA;&#xD;&#xA;The &quot;Why?&quot; should have two elements, one might be &quot;because Apple does it that way&quot; but the other would hopefully help me understand *why Apple does it that way* if that is in fact the case.&#xD;&#xA;&#xD;&#xA;**update:** The answer to [why does black text have orange and blue pixels](https://computergraphics.stackexchange.com/q/2034/5846) names this as &quot;sub-pixel rendering&quot; but I still do not understand why it is in color in some places, gray in others, and if and why the color is used at all.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4] [![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [4]: https://i.stack.imgur.com/wAiuH.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/IyBx3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22580" PostHistoryTypeId="50" PostId="8296" RevisionGUID="063bc7d7-f82c-44b4-becd-29e4d1297d9e" CreationDate="2019-01-01T06:02:45.553" UserId="-1" />
  <row Id="22581" PostHistoryTypeId="5" PostId="8437" RevisionGUID="db185881-df08-4320-96dc-cc4f4e2f621d" CreationDate="2019-01-01T07:17:45.490" UserId="5846" Comment="added 249 characters in body" Text="In [this question](https://retrocomputing.stackexchange.com/q/8627/7118) I generated the images below to explain why I can't use TTFs for that 1-bit display application.&#xD;&#xA;&#xD;&#xA;But now I would like to understand *from the perspective of a non-expert*, why is some black-on-white text on my screen made from gray pixels, while other text is made from color pixels?&#xD;&#xA;&#xD;&#xA;Gray on left is a screenshot from the SE question editor window, color on right is from a Finder window in MacOS.&#xD;&#xA;&#xD;&#xA;The &quot;Why?&quot; should have two elements, one might be &quot;because Apple does it that way&quot; but the other would hopefully help me understand *why Apple does it that way* if that is in fact the case.&#xD;&#xA;&#xD;&#xA;**update:** The answer to [why does black text have orange and blue pixels](https://computergraphics.stackexchange.com/q/2034/5846) names this as &quot;sub-pixel rendering&quot; but I still do not understand why it is in color in some places, gray in others, and if and why the color is used at all.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I've done a rough analysis of the colors used in hopes that it might teach me something, but I can't really gain any insight beyond &quot;its a red-blue thing&quot;. &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wAiuH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IyBx3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bTMCk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22582" PostHistoryTypeId="2" PostId="8438" RevisionGUID="05121d33-34a8-4167-8355-912abe7caa11" CreationDate="2019-01-01T12:34:28.337" UserId="7555" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read).&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCDs. The colors are simply the result of the screen having R, G and B pixels to make up the picture. If you want to use indivisual subpixels rather than full pixels as with antialising, you will have color fringe inevitably." ContentLicense="CC BY-SA 4.0" />
  <row Id="22583" PostHistoryTypeId="5" PostId="8438" RevisionGUID="86ef9370-3320-4b6c-b18d-6978439685f2" CreationDate="2019-01-01T12:54:02.070" UserId="7555" Comment="added 547 characters in body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read).&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCDs. The colors are simply the result of the screen having R, G and B subpixels to make up each single pixel. If you want to use indivisual subpixels rather than full pixels as with antialising, you will have color fringe inevitably because these subpixels are physically colored.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain that differences in color. So, even if it introduces color variations (which is absolutely not the intention but and inevitable consequence of the subpixels being colored), what we really see are the intensity differences." ContentLicense="CC BY-SA 4.0" />
  <row Id="22584" PostHistoryTypeId="5" PostId="8438" RevisionGUID="955d4098-8857-494a-b308-5af106a5f881" CreationDate="2019-01-01T13:06:28.253" UserId="7555" Comment="added 731 characters in body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read).&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCDs. The colors are simply the result of the screen having R, G and B subpixels to make up each single pixel. If you want to use indivisual subpixels rather than full pixels as with antialising, you will have color fringe inevitably because these subpixels are physically colored.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain that differences in color. So, even if it introduces color variations (which is absolutely not the intention but and inevitable consequence of the subpixels being colored), what we really see are the intensity differences.&#xD;&#xA;&#xD;&#xA;What you actually see in the screenshot is that the actually intended display is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off. In Windows or Linux, where the hardware selection is much broaded and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different." ContentLicense="CC BY-SA 4.0" />
  <row Id="22585" PostHistoryTypeId="5" PostId="8438" RevisionGUID="c374b9e5-8b5d-4f1e-be9a-0596591de385" CreationDate="2019-01-01T13:08:06.793" UserId="7555" Comment="added 731 characters in body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read).&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCDs. The colors are simply the result of the screen having R, G and B subpixels to make up each single pixel. If you want to use indivisual subpixels rather than full pixels as with antialising, you will have color fringe inevitably because these subpixels are physically colored.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain than differences in color. So, even if it introduces color variations (which is absolutely not the intention but an inevitable consequence of the subpixels being colored), what we really see are the intensity differences.&#xD;&#xA;&#xD;&#xA;What you can see in the screenshot is that the display sent to the monitor is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off in their user interface (although there is a way to select from a limited list of three various settings using the Terminal app and appropriate commands).&#xD;&#xA;&#xD;&#xA;In Windows or Linux, where the hardware selection is much broaded and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different." ContentLicense="CC BY-SA 4.0" />
  <row Id="22586" PostHistoryTypeId="5" PostId="8438" RevisionGUID="49fb9ae9-2a68-497d-a61a-5bc1a9ac4ae5" CreationDate="2019-01-01T13:18:50.190" UserId="7555" Comment="edited body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read).&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCDs. The colors are simply the result of the screen having R, G and B subpixels to make up each single pixel. If you want to use indivisual subpixels rather than full pixels as with antialising, you will have color fringe inevitably because these subpixels are physically colored.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain than differences in color. So, even if it introduces color variations (which is absolutely not the intention but an inevitable consequence of the subpixels being colored), what we really see are the intensity differences.&#xD;&#xA;&#xD;&#xA;What you can see in the screenshot is that the display sent to the monitor is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off in their user interface (although there is a way to select from a limited list of three various settings using the Terminal app and appropriate commands).&#xD;&#xA;&#xD;&#xA;In Windows or Linux, where the hardware selection is much broader and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different." ContentLicense="CC BY-SA 4.0" />
  <row Id="22587" PostHistoryTypeId="5" PostId="8438" RevisionGUID="88adcebb-1104-443d-b7b2-2b659efd8afe" CreationDate="2019-01-01T13:34:10.220" UserId="7555" Comment="edited body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read.&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCD where the RGB components making up a pixel are much more uniform. Very simply put, we treat our monitors as having thrice as many pixels horizontally than they actually do. When we render a character glyph, the body will be black, so no difference there. But if we calculate to need just a subpixel more to the left of a complete pixel, we will use that extra subpixel. Similarly, if we need to go just a subpixel to the right, we will use that.&#xD;&#xA;&#xD;&#xA;But, using these individual subpixels rather than full pixels as with antialising, we will have color fringe inevitably because these subpixels are physically colored. Just look at your sample: all left edges have the same color fringe, yes, because that's the color of the last subpixel of the previous pixel. And right edges, similarly, have the color of the first subpixel of the next pixel.&#xD;&#xA;&#xD;&#xA;What you can see in the screenshot is that the display sent to the monitor is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly. Pixel colors are modified so that when they light up on the monitor screen, only those subpixels will be lit that are required by the calculations.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off in their user interface (although there is a way to select from a limited list of three various settings using the Terminal app and appropriate commands).&#xD;&#xA;&#xD;&#xA;In Windows or Linux, where the hardware selection is much broader and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain than differences in color. So, even if it introduces color variations (which is absolutely not the intention but an inevitable consequence of the subpixels being colored), what we really see are the intensity differences. In simpler words, most of us will only perceive at that resolution and physical viewing distances that there is an extra subpixel, not that it has a different color." ContentLicense="CC BY-SA 4.0" />
  <row Id="22588" PostHistoryTypeId="5" PostId="8438" RevisionGUID="295d209b-9735-4ce2-8f24-9c46e7e95ac0" CreationDate="2019-01-01T13:40:48.370" UserId="7555" Comment="added 2 characters in body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read.&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCD where the RGB components making up a pixel are much more uniform. Very simply put, we treat our monitors as having thrice as many pixels horizontally than they actually do. When we render a character glyph, the body will be black, so no difference there. But if we calculate to need just a subpixel more to the left of a complete pixel, we will use that extra subpixel. Similarly, if we need to go just a subpixel to the right, we will use that.&#xD;&#xA;&#xD;&#xA;But, using these individual subpixels rather than full pixels as with antialising, we will have color fringe inevitably because these subpixels are physically colored. Just look at your sample: all left edges have the same color fringe, yes, because that's the color of the last subpixel of the previous pixel. And right edges, similarly, have the color of the first subpixel of the next pixel.&#xD;&#xA;&#xD;&#xA;What you can see in the screenshot is that the display sent to the monitor is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly. Pixel colors are modified so that when they light up on the monitor screen, only those subpixels will be lit that are required by the calculations.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off in their user interface (although there is a way to select from a limited list of three different settings using the Terminal app and appropriate commands).&#xD;&#xA;&#xD;&#xA;In Windows or Linux, where the hardware selection is much broader and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to display text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain than differences in color. So, even if it introduces color variations (which is absolutely not the intention but an inevitable consequence of the subpixels being colored), what we really see are the intensity differences. In simpler words, most of us will only perceive at that resolution and physical viewing distances that there is an extra subpixel, not that it has a different color." ContentLicense="CC BY-SA 4.0" />
  <row Id="22589" PostHistoryTypeId="5" PostId="8438" RevisionGUID="4d567f39-8b1f-4081-9062-b382abfae059" CreationDate="2019-01-01T13:50:56.923" UserId="7555" Comment="added 483 characters in body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read.&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCD where the RGB components making up a pixel are much more uniform. Very simply put, we treat our monitors as having thrice as many pixels horizontally than they actually do. When we render a character glyph, the body will be black, so no difference there. But if we calculate to need just a subpixel more to the left of a complete pixel, we will use that extra subpixel. Similarly, if we need to go just a subpixel to the right, we will use that.&#xD;&#xA;&#xD;&#xA;But, using these individual subpixels rather than full pixels as with antialising, we will have color fringe inevitably because these subpixels are physically colored. Just look at your sample: all left edges have the same color fringe, yes, because that's the color of the last subpixel of the previous pixel. And right edges, similarly, have the color of the first subpixel of the next pixel.&#xD;&#xA;&#xD;&#xA;What you can see in the screenshot is that the display sent to the monitor is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly. Pixel colors are modified so that when they light up on the monitor screen, only those subpixels will be lit that are required by the calculations.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off in their user interface (although there is a way to select from a limited list of three different settings using the Terminal app and appropriate commands).&#xD;&#xA;&#xD;&#xA;In Windows or Linux, where the hardware selection is much broader and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to display text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain than differences in color. So, even if it introduces color variations (which is absolutely not the intention but an inevitable consequence of the subpixels being colored), what we really see are the intensity differences. In simpler words, most of us will only perceive at that resolution and physical viewing distances that there is an extra subpixel, not that it has a different color.&#xD;&#xA;&#xD;&#xA;And as to the final question of why gray in some places and colored in others, it's very probably a software issue. The browser you mentioned might have its own graphics rendering engine that simply works differently from what you normally have in the operating system. It's quite possible that it doesn't use the operating systems services to render text but renders everything by itself, pictures and texts as well, as a complete image and uses its own settings and techniques." ContentLicense="CC BY-SA 4.0" />
  <row Id="22590" PostHistoryTypeId="5" PostId="8438" RevisionGUID="381a4b76-2483-486d-9e65-c8f63e72fefe" CreationDate="2019-01-01T13:53:50.913" UserId="7555" Comment="added 16 characters in body" Text="It's called subpixel rendering (there are different solutions on different platforms). Microsoft's one is called ClearType, just google for it, Wikipedia has a nice description.&#xD;&#xA;&#xD;&#xA;Earlier, simple edge smoothing was used, antialising, that resulted in gray pixels added to the jagged lines to mask them, and although it technically created a more blurred outline, due to the way our brain works, we perceived the resulting forms more pleasing, more natural, easier to read.&#xD;&#xA;&#xD;&#xA;Colored subpixels arrived when monitor technology moved from CRT screens to LCD where the RGB components making up a pixel are much more uniform. Very simply put, we treat our monitors as having thrice as many pixels horizontally than they actually do. When we render a character glyph, the body will be black, so no difference there. But if we calculate to need just a subpixel more to the left of a complete pixel, we will use that extra subpixel. Similarly, if we need to go just a subpixel to the right, we will use that.&#xD;&#xA;&#xD;&#xA;But, using these individual subpixels rather than full pixels as with antialising, we will have color fringe inevitably because these subpixels are physically colored. Just look at your sample: all left edges have the same color fringe, yes, because that's the color of the last subpixel of the previous pixel. And right edges, similarly, have the color of the first subpixel of the next pixel.&#xD;&#xA;&#xD;&#xA;What you can see in the screenshot is that the display sent to the monitor is pre-manipulated with the anticipation of the colored subpixels and displayed accordingly. Pixel colors are modified so that when they light up on the monitor screen, only those subpixels will be lit that are required by the calculations.&#xD;&#xA;&#xD;&#xA;Monitors might be different and, more importantly, individual sensitivity to this effect is different from person to person. Apple, using only their own monitors and in line with their usual stance of &quot;we tell you how to use it&quot;, only offers a way to switch this effect on or off in their user interface (although there is a way to select from a limited list of three different settings using the Terminal app and appropriate commands).&#xD;&#xA;&#xD;&#xA;In Windows or Linux, where the hardware selection is much broader and people don't normally accept to be allowed only a single way, ClearType can be adjusted to your individual needs. Depending on the settings you selected, the actual color fringes will be very different.&#xD;&#xA;&#xD;&#xA;This is just a compromise. In order to display text to be more legible, we sacrifice chrominance for luminance. Differences in intensity are more noticeable to the human brain than differences in color. So, even if it introduces color variations (which is absolutely not the intention but an inevitable consequence of the subpixels being colored), what we really see are the intensity differences. In simpler words, most of us will only perceive at that resolution and physical viewing distances that there is an extra subpixel, not that it has a different color.&#xD;&#xA;&#xD;&#xA;And as to the final question of why gray in some places and colored in others, it's very probably a software issue. The browser you mentioned might have its own graphics rendering engine that simply works differently from what you normally have in the operating system. It's quite possible that it doesn't use the operating system's services to render text but renders everything by itself, pictures and texts as well, as a complete image and uses its own settings and techniques in the process." ContentLicense="CC BY-SA 4.0" />
  <row Id="22603" PostHistoryTypeId="50" PostId="5697" RevisionGUID="3f27c4ed-4dd2-401f-bc29-e17fae1dc894" CreationDate="2019-01-03T02:00:30.877" UserId="-1" />
  <row Id="22610" PostHistoryTypeId="50" PostId="8359" RevisionGUID="b70c6726-0ec1-4fa8-89fd-4b59743cdc18" CreationDate="2019-01-03T19:03:10.600" UserId="-1" />
  <row Id="22611" PostHistoryTypeId="2" PostId="8442" RevisionGUID="99f2de9b-6adc-4d4e-be90-f7a61fef09b2" CreationDate="2019-01-03T20:11:39.860" UserId="9952" Text="I am rendering an infinite plane as described in the following answers:&#xD;&#xA;&#xD;&#xA;1. https://stackoverflow.com/questions/12965161/rendering-infinitely-large-plane&#xD;&#xA;2. https://stackoverflow.com/questions/7380250/how-to-render-a-plane-of-seemingly-infinite-size&#xD;&#xA;&#xD;&#xA;Specifically, I am rendering an &quot;infinite&quot; XZ plane using the following five 4D vertices:&#xD;&#xA;$$(0, 0, 0, 1)\quad(1, 0, 0, 0)\quad(0, 0, 1, 0)\quad(-1, 0, 0, 0)\quad(0, 0, -1, 0)$$&#xD;&#xA;&#xD;&#xA;In my engine, this is displayed as a ground plane at origin.&#xD;&#xA;&#xD;&#xA;What I would like to do is texture this plane. For now, it would be nice to just have a checkered grid. In my fragment shader, I am doing this via the varying $x$ and $z$ positions. This works fine for other &quot;non-infinite&quot; meshes, but for the infinite plane, it is incorrect. This is because the interpolated positions that are passed to the fragment shader don't really make sense in world space, as far as I can tell.&#xD;&#xA;&#xD;&#xA;How can I compute the world-space coordinates in my fragment shader?&#xD;&#xA;Is it possible to compute them from the vertex positions, since they represent points at infinity?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22612" PostHistoryTypeId="1" PostId="8442" RevisionGUID="99f2de9b-6adc-4d4e-be90-f7a61fef09b2" CreationDate="2019-01-03T20:11:39.860" UserId="9952" Text="Texturing an &quot;infinite&quot; plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="22613" PostHistoryTypeId="3" PostId="8442" RevisionGUID="99f2de9b-6adc-4d4e-be90-f7a61fef09b2" CreationDate="2019-01-03T20:11:39.860" UserId="9952" Text="|rendering|shader|texture|geometry|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22614" PostHistoryTypeId="5" PostId="8442" RevisionGUID="c614db8f-5506-4a28-90a9-463cdd8663bf" CreationDate="2019-01-03T20:17:48.927" UserId="9952" Comment="added 209 characters in body" Text="I am rendering an infinite plane as described in the following answers:&#xD;&#xA;&#xD;&#xA;1. https://stackoverflow.com/questions/12965161/rendering-infinitely-large-plane&#xD;&#xA;2. https://stackoverflow.com/questions/7380250/how-to-render-a-plane-of-seemingly-infinite-size&#xD;&#xA;&#xD;&#xA;Specifically, I am rendering an &quot;infinite&quot; XZ plane using the following five 4D vertices:&#xD;&#xA;$$(0, 0, 0, 1)\quad(1, 0, 0, 0)\quad(0, 0, 1, 0)\quad(-1, 0, 0, 0)\quad(0, 0, -1, 0)$$&#xD;&#xA;&#xD;&#xA;In my engine, this is displayed as a ground plane at origin.&#xD;&#xA;&#xD;&#xA;What I would like to do is texture this plane. For now, it would be nice to just have a checkered grid. In my fragment shader, I am doing this via the varying $x$ and $z$ positions. This works fine for other &quot;non-infinite&quot; meshes, but for the infinite plane, it is incorrect. This is because the interpolated positions that are passed to the fragment shader don't really make sense in world space, as far as I can tell.&#xD;&#xA;&#xD;&#xA;How can I compute the world-space position coordinates in my fragment shader?&#xD;&#xA;Is it possible to compute them from the vertex positions, since they represent points at infinity?&#xD;&#xA;&#xD;&#xA;The next step would be UV coordinates, but as I understand that might not be possible. I am interested more in being able to easily procedurally texture the plane rather than apply an image to it." ContentLicense="CC BY-SA 4.0" />
  <row Id="22615" PostHistoryTypeId="2" PostId="8443" RevisionGUID="904187dd-3059-4af7-87c8-c333aaa7f8d5" CreationDate="2019-01-03T21:30:47.527" UserId="9812" Text="$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;If you have the screen-space x and y coordinates as well as the depth of your fragment, you can directly compute the coordinates of the corresponding point on the plane in world-space. To do so, first compute the clip-space coordinates of your fragment:&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p'' = \mvec{&#xD;&#xA;		2\cdot\frac{x}{r_x} - 1 \\&#xD;&#xA;		2\cdot\frac{y}{r_y} - 1 \\&#xD;&#xA;		2 \cdot z - 1 \\&#xD;&#xA;		1&#xD;&#xA;	}&#xD;&#xA;\end{equation}&#xD;&#xA;where $x$ and $y$ are the screen-space (pixel) coordinates of the fragment, $z$ is the fragment depth, and $r_x$ and $r_y$ are the width and height (resolution) of the viewport. The above computation is assuming that you're using OpenGL with the default depth range. If you're using Direct3D, use $z$ directly without applying a scaling and offset. If you're using a depth range different from the default, apply whatever is the the appropriate inverse transformation in your case to get from screen-space to clip-space $z$.&#xD;&#xA;&#xD;&#xA;Once you have the clip-space coordinates of your fragment, you can simply unproject the fragment by transforming with the inverse view-projection matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p' = \mat M^{-1} \vec p''&#xD;&#xA;\end{equation}&#xD;&#xA;where $\mat M$ would be your view-projection matrix.&#xD;&#xA;&#xD;&#xA;The final step is then to homogenize the coordinates to get the world-space coordinates of the point&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p = \frac{1}{p'_w} \cdot \mvec{&#xD;&#xA;		p'_x \\&#xD;&#xA;		p'_y \\&#xD;&#xA;		p'_z&#xD;&#xA;	}.&#xD;&#xA;\end{equation}" ContentLicense="CC BY-SA 4.0" />
  <row Id="22616" PostHistoryTypeId="5" PostId="8443" RevisionGUID="fff412aa-a7b7-4011-afba-7de8ccac0f44" CreationDate="2019-01-03T21:37:09.193" UserId="9812" Comment="added 234 characters in body" Text="$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;If you have the screen-space x and y coordinates as well as the depth of your fragment, you can directly compute the coordinates of the corresponding point on the plane in world-space. To do so, first compute the clip-space coordinates of your fragment&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p'' = \mvec{&#xD;&#xA;		2\cdot\frac{x}{r_x} - 1 \\&#xD;&#xA;		2\cdot\frac{y}{r_y} - 1 \\&#xD;&#xA;		2 \cdot z - 1 \\&#xD;&#xA;		1&#xD;&#xA;	}&#xD;&#xA;\end{equation}&#xD;&#xA;where $x$ and $y$ are the screen-space (pixel) coordinates of the fragment, $z$ is the fragment depth, and $r_x$ and $r_y$ are the width and height (resolution) of the viewport. The above computation is assuming that you're using OpenGL with the default depth range. If you're using Direct3D, use $z$ directly without applying a scaling and offset. If you're using a depth range different from the default, apply whatever is the the appropriate inverse transformation in your case to get from screen-space to clip-space $z$.&#xD;&#xA;&#xD;&#xA;Once you have the clip-space coordinates of your fragment, you can simply unproject the fragment by transforming with the inverse view-projection matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p' = \mat M^{-1} \vec p''&#xD;&#xA;\end{equation}&#xD;&#xA;where $\mat M$ would be your view-projection matrix. (Note: you will most likely want to pass the inverse view-projection matrix to the shader as a uniform as inverting the view-projection matrix in the shader for every fragment would most likely introduce quite some unnecessary overhead.)&#xD;&#xA;&#xD;&#xA;The final step is then to homogenize to get the world-space coordinates of the point&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p = \frac{1}{p'_w} \cdot \mvec{&#xD;&#xA;		p'_x \\&#xD;&#xA;		p'_y \\&#xD;&#xA;		p'_z&#xD;&#xA;	}.&#xD;&#xA;\end{equation}" ContentLicense="CC BY-SA 4.0" />
  <row Id="22617" PostHistoryTypeId="5" PostId="8443" RevisionGUID="e5102e9c-58e0-4b83-8fe9-d4f0e40b5a32" CreationDate="2019-01-03T21:43:36.713" UserId="9812" Comment="added 234 characters in body" Text="$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;If you have the screen-space x and y coordinates as well as the depth of your fragment, you can directly compute the coordinates of the corresponding point on the plane in world-space. To do so, first compute the clip-space coordinates of your fragment&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p'' = \mvec{&#xD;&#xA;		2\cdot\frac{x}{r_x} - 1 \\&#xD;&#xA;		2\cdot\frac{y}{r_y} - 1 \\&#xD;&#xA;		2 \cdot z - 1 \\&#xD;&#xA;		1&#xD;&#xA;	}&#xD;&#xA;\end{equation}&#xD;&#xA;where $x$ and $y$ are the screen-space (pixel) coordinates of the fragment, $z$ is the fragment depth, and $r_x$ and $r_y$ are the width and height (resolution) of the viewport. The above computation is assuming that you're using OpenGL with the default depth range. If you're using Direct3D, use $z$ directly without applying a scaling and offset. If you're using a depth range different from the default, apply whatever is the the appropriate inverse transformation in your case to get from screen-space to clip-space $z$.&#xD;&#xA;&#xD;&#xA;Once you have the clip-space coordinates of your fragment, you can simply unproject the fragment by transforming with the inverse view-projection matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p' = \mat M^{-1} \vec p''&#xD;&#xA;\end{equation}&#xD;&#xA;where $\mat M$ would be your view-projection matrix. (Note: you will most likely want to pass the inverse view-projection matrix to the shader as a uniform as inverting the view-projection matrix in the shader for every fragment would most likely introduce quite some unnecessary overhead.)&#xD;&#xA;&#xD;&#xA;The final step is then to homogenize to get the world-space coordinates of the point&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p = \frac{1}{p'_w} \cdot \mvec{&#xD;&#xA;		p'_x \\&#xD;&#xA;		p'_y \\&#xD;&#xA;		p'_z&#xD;&#xA;	}.&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;By the way: It would seem to me that rendering this &quot;infinite plane&quot; should be possible using just a single triangle with all corners at infinity in different directions instead of four triangles. Since the boundary of your polygon is pushed to infinity, it shouldn't matter how many edges it has&amp;hellip;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22622" PostHistoryTypeId="2" PostId="8444" RevisionGUID="4a2b9137-c92d-4eec-ace4-9b46356f4921" CreationDate="2019-01-04T02:20:28.277" UserId="6046" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation. The simple code looks like this&#xD;&#xA;&#xD;&#xA;    //Direct Light Sampling&#xD;&#xA;	int j = sampleLights(hit_info, &amp;geometry_term, &amp;light_pdf, &amp;w_i);  //j is the index in light array&#xD;&#xA;	if(j == -1)&#xD;&#xA;		return light_sample;  // black since no ray hits any light source&#xD;&#xA;	&#xD;&#xA;	Ray shadow_ray&#xD;&#xA;	HitInfo shadow_hitinfo;	&#xD;&#xA;	if(!traceRay(&amp;shadow_ray, &amp;shadow_hitinfo) )&#xD;&#xA;	{&#xD;&#xA;        //traceRay returns false which means light source is visible&#xD;&#xA;		mis_weight =  light_pdf;&#xD;&#xA;		brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI; //cosine weighted&#xD;&#xA;		powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);		&#xD;&#xA;		light_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;	&#xD;&#xA;		light_sample *=  mis_weight/light_pdf;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// BRDF Sampling&#xD;&#xA;	Ray brdf_sample_ray;&#xD;&#xA;	sampleHemisphere(&amp;brdf_sample_ray, hit_info);&#xD;&#xA;    if(traceRay(&amp;brdf_sample_ray, &amp;new_hitinfo) &amp;&amp; new_hitinfo.lightID &lt; 0)&#xD;&#xA;	   return light_sample;                //if Light ID &lt; 0, no lights were hit&#xD;&#xA;	&#xD;&#xA;	light_pdf = getLightPdf(new_hitinfo.lightID);&#xD;&#xA;	brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI;	&#xD;&#xA;    mis_weight = brdf_pdf;&#xD;&#xA;	powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);&#xD;&#xA;	&#xD;&#xA;	brdf_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;&#xD;&#xA;	brdf_sample *=  mis_weight / brdf_pdf;&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22623" PostHistoryTypeId="1" PostId="8444" RevisionGUID="4a2b9137-c92d-4eec-ace4-9b46356f4921" CreationDate="2019-01-04T02:20:28.277" UserId="6046" Text="Multiple Importance Sampling in Path tracer produces Dark Images" ContentLicense="CC BY-SA 4.0" />
  <row Id="22624" PostHistoryTypeId="3" PostId="8444" RevisionGUID="4a2b9137-c92d-4eec-ace4-9b46356f4921" CreationDate="2019-01-04T02:20:28.277" UserId="6046" Text="|rendering|pathtracing|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22626" PostHistoryTypeId="5" PostId="8444" RevisionGUID="b6ada128-7bd4-47da-abbc-2368f2150e85" CreationDate="2019-01-04T10:54:58.537" UserId="6046" Comment="added 59 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation. The simple code looks like this&#xD;&#xA;&#xD;&#xA;    //Direct Light Sampling&#xD;&#xA;	int j = sampleLights(hit_info, &amp;geometry_term, &amp;light_pdf, &amp;w_i);  //j is the index in light array&#xD;&#xA;	if(j == -1)&#xD;&#xA;		return light_sample;  // black since no ray hits any light source&#xD;&#xA;	&#xD;&#xA;	Ray shadow_ray&#xD;&#xA;	HitInfo shadow_hitinfo;	&#xD;&#xA;	if(!traceRay(&amp;shadow_ray, &amp;shadow_hitinfo) )&#xD;&#xA;	{&#xD;&#xA;        //traceRay returns false which means light source is visible&#xD;&#xA;		mis_weight =  light_pdf;&#xD;&#xA;		brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI; //cosine weighted&#xD;&#xA;		powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);		&#xD;&#xA;		light_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;	&#xD;&#xA;		light_sample *=  mis_weight/light_pdf;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// BRDF Sampling&#xD;&#xA;	Ray brdf_sample_ray;&#xD;&#xA;	sampleHemisphere(&amp;brdf_sample_ray, hit_info);&#xD;&#xA;    if(traceRay(&amp;brdf_sample_ray, &amp;new_hitinfo) &amp;&amp; new_hitinfo.lightID &lt; 0)&#xD;&#xA;	   return light_sample;                //if Light ID &lt; 0, no lights were hit&#xD;&#xA;	&#xD;&#xA;	light_pdf = getLightPdf(new_hitinfo.lightID);&#xD;&#xA;	brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI;	&#xD;&#xA;    mis_weight = brdf_pdf;&#xD;&#xA;	powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);&#xD;&#xA;	&#xD;&#xA;	brdf_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;&#xD;&#xA;	brdf_sample *=  mis_weight / brdf_pdf;&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22627" PostHistoryTypeId="5" PostId="8443" RevisionGUID="ec74d070-4177-4a87-971f-abc84f0db717" CreationDate="2019-01-04T13:53:13.523" UserId="9812" Comment="deleted 13 characters in body" Text="$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;If you have the screen-space x and y coordinates as well as the depth of your fragment, you can directly compute the coordinates of the corresponding point in world-space. To do so, first compute the clip-space coordinates of your fragment&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p'' = \mvec{&#xD;&#xA;		2\cdot\frac{x}{r_x} - 1 \\&#xD;&#xA;		2\cdot\frac{y}{r_y} - 1 \\&#xD;&#xA;		2 \cdot z - 1 \\&#xD;&#xA;		1&#xD;&#xA;	}&#xD;&#xA;\end{equation}&#xD;&#xA;where $x$ and $y$ are the screen-space (pixel) coordinates of the fragment, $z$ is the fragment depth, and $r_x$ and $r_y$ are the width and height (resolution) of the viewport. The above computation is assuming that you're using OpenGL with the default depth range. If you're using Direct3D, use $z$ directly without applying a scaling and offset. If you're using a depth range different from the default, apply whatever is the the appropriate inverse transformation in your case to get from screen-space to clip-space $z$.&#xD;&#xA;&#xD;&#xA;Once you have the clip-space coordinates of your fragment, you can simply unproject the fragment by transforming with the inverse view-projection matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p' = \mat M^{-1} \vec p''&#xD;&#xA;\end{equation}&#xD;&#xA;where $\mat M$ would be your view-projection matrix. (Note: you will most likely want to pass the inverse view-projection matrix to the shader as a uniform as inverting the view-projection matrix in the shader for every fragment would most likely introduce quite some unnecessary overhead.)&#xD;&#xA;&#xD;&#xA;The final step is then to homogenize to get the world-space coordinates of the point&#xD;&#xA;\begin{equation}&#xD;&#xA;	\vec p = \frac{1}{p'_w} \cdot \mvec{&#xD;&#xA;		p'_x \\&#xD;&#xA;		p'_y \\&#xD;&#xA;		p'_z&#xD;&#xA;	}.&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;By the way: It would seem to me that rendering this &quot;infinite plane&quot; should be possible using just a single triangle with all corners at infinity in different directions instead of four triangles. Since the boundary of your polygon is pushed to infinity, it shouldn't matter how many edges it has&amp;hellip;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22628" PostHistoryTypeId="50" PostId="8209" RevisionGUID="a8633a3c-3052-418a-afc9-543286b95c72" CreationDate="2019-01-04T22:01:00.170" UserId="-1" />
  <row Id="22629" PostHistoryTypeId="5" PostId="8444" RevisionGUID="509aedd7-9451-4cd2-8ba7-5ffb7d96ae61" CreationDate="2019-01-05T16:25:24.083" UserId="6046" Comment="added 69 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation. The simple code looks like this&#xD;&#xA;&#xD;&#xA;    //Direct Light Sampling&#xD;&#xA;	int j = sampleLights(hit_info, &amp;geometry_term, &amp;light_pdf, &amp;w_i);  //j is the index in light array&#xD;&#xA;	if(j == -1)&#xD;&#xA;		return light_sample;  // black since no ray hits any light source&#xD;&#xA;	&#xD;&#xA;	Ray shadow_ray = {hit_info.hit_point + w_i * RAYBUMP_EPSILON, w_i, INFINITY, true};&#xD;&#xA;	HitInfo shadow_hitinfo;	&#xD;&#xA;	if(!traceRay(&amp;shadow_ray, &amp;shadow_hitinfo) )&#xD;&#xA;	{&#xD;&#xA;        //traceRay returns false which means light source is visible&#xD;&#xA;		mis_weight =  light_pdf;&#xD;&#xA;		brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI; //cosine weighted&#xD;&#xA;		powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);		&#xD;&#xA;		light_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;	&#xD;&#xA;		light_sample *=  mis_weight/light_pdf;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// BRDF Sampling&#xD;&#xA;	Ray brdf_sample_ray;&#xD;&#xA;	sampleHemisphere(&amp;brdf_sample_ray, hit_info);&#xD;&#xA;    if(traceRay(&amp;brdf_sample_ray, &amp;new_hitinfo) &amp;&amp; new_hitinfo.lightID &lt; 0)&#xD;&#xA;	   return light_sample;                //if Light ID &lt; 0, no lights were hit&#xD;&#xA;	&#xD;&#xA;	light_pdf = getLightPdf(new_hitinfo.lightID);&#xD;&#xA;	brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI;	&#xD;&#xA;    mis_weight = brdf_pdf;&#xD;&#xA;	powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);&#xD;&#xA;	&#xD;&#xA;	brdf_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;&#xD;&#xA;	brdf_sample *=  mis_weight / brdf_pdf;&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22630" PostHistoryTypeId="5" PostId="8444" RevisionGUID="5832e2b5-92d8-41a9-bd6b-4546c2089e45" CreationDate="2019-01-05T16:38:29.450" UserId="6046" Comment="added 348 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation. The simple code looks like this&#xD;&#xA;&#xD;&#xA;    //Direct Light Sampling&#xD;&#xA;	int j = sampleLights(hit_info, &amp;geometry_term, &amp;light_pdf, &amp;w_i);  //j is the index in light array&#xD;&#xA;	if(j == -1)&#xD;&#xA;		return light_sample;  // black since no ray hits any light source&#xD;&#xA;	&#xD;&#xA;	Ray shadow_ray = {hit_info.hit_point + w_i * RAYBUMP_EPSILON, w_i, INFINITY, true};&#xD;&#xA;	HitInfo shadow_hitinfo;	&#xD;&#xA;	if(!traceRay(&amp;shadow_ray, &amp;shadow_hitinfo) )&#xD;&#xA;	{&#xD;&#xA;        //traceRay returns false which means light source is visible&#xD;&#xA;		mis_weight =  light_pdf;&#xD;&#xA;		brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI; //cosine weighted&#xD;&#xA;		powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);		&#xD;&#xA;		light_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;	&#xD;&#xA;		light_sample *=  mis_weight/light_pdf;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// BRDF Sampling&#xD;&#xA;	Ray brdf_sample_ray;&#xD;&#xA;	sampleHemisphere(&amp;brdf_sample_ray, hit_info);&#xD;&#xA;    if(traceRay(&amp;brdf_sample_ray, &amp;new_hitinfo) &amp;&amp; new_hitinfo.lightID &lt; 0)&#xD;&#xA;	   return light_sample;                //if Light ID &lt; 0, no lights were hit&#xD;&#xA;	&#xD;&#xA;	light_pdf = getLightPdf(new_hitinfo.lightID);&#xD;&#xA;	brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI;	&#xD;&#xA;    mis_weight = brdf_pdf;&#xD;&#xA;	powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);&#xD;&#xA;	&#xD;&#xA;	brdf_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;&#xD;&#xA;	brdf_sample *=  mis_weight / brdf_pdf;&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;EDIT:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22632" PostHistoryTypeId="2" PostId="8445" RevisionGUID="f52e2086-bf3d-423a-8bb7-33c01ca1d0c9" CreationDate="2019-01-06T07:04:02.643" UserId="9962" Text="To be clear, I'm talking about behavior like https://www.khronos.org/opengl/wiki/Texture#Swizzle_mask, not &quot;normal&quot; `myColorVariable.rbgr` swizzling in a shader.&#xD;&#xA;&#xD;&#xA;I really did start missing this feature after switching from OpenGL to Direct3D11, and ended up implementing a poor man's version in HLSL. Initially, I just assumed this was another &quot;feature&quot; of OpenGL that didn't actually exist on any hardware and was just being emulated by every driver, but then I noticed that Vulkan supports it as well. &#xD;&#xA;&#xD;&#xA;My understanding is that the Vulkan specification is not supposed to include &quot;extras&quot; that aren't supported by hardware, so what gives? Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22633" PostHistoryTypeId="1" PostId="8445" RevisionGUID="f52e2086-bf3d-423a-8bb7-33c01ca1d0c9" CreationDate="2019-01-06T07:04:02.643" UserId="9962" Text="Why don't Direct3D/Metal support texture swizzles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22634" PostHistoryTypeId="3" PostId="8445" RevisionGUID="f52e2086-bf3d-423a-8bb7-33c01ca1d0c9" CreationDate="2019-01-06T07:04:02.643" UserId="9962" Text="|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22636" PostHistoryTypeId="2" PostId="8446" RevisionGUID="c99570d3-4089-4039-85df-e9113c2eadd6" CreationDate="2019-01-06T09:32:47.383" UserId="9963" Text="What would be the best way to make a texture a clickable button? Suppose I have a Room (respresented by a 2D texture), where there are buttons. &#xD;&#xA;&#xD;&#xA;Would I in the main loop:&#xD;&#xA;&#xD;&#xA;- check when the mouse is clicked if it is in any region of a button? ($\mathcal{O}(n_{Button})$)&#xD;&#xA;&#xD;&#xA;- Do something entirely different that I can't think of?&#xD;&#xA;&#xD;&#xA;I may be overthinking this, maybe this isn't a problem at all, but somehow, what I came up with sounds way to &quot;stupid&quot; to me to be the right solution. It sounds like a hack to me, but maybe this is the way to do it? In 3D Games, would the check than be just radial coordinates ($r,\phi,\theta$)?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22637" PostHistoryTypeId="1" PostId="8446" RevisionGUID="c99570d3-4089-4039-85df-e9113c2eadd6" CreationDate="2019-01-06T09:32:47.383" UserId="9963" Text="Make a texture a clickable Button" ContentLicense="CC BY-SA 4.0" />
  <row Id="22638" PostHistoryTypeId="3" PostId="8446" RevisionGUID="c99570d3-4089-4039-85df-e9113c2eadd6" CreationDate="2019-01-06T09:32:47.383" UserId="9963" Text="|texture|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22639" PostHistoryTypeId="2" PostId="8447" RevisionGUID="eded5c34-8d0d-454f-85b4-50f97587ae02" CreationDate="2019-01-06T15:04:24.507" UserId="9812" Text="Note that this feature was introduced with OpenGL 4.6 which came *after* Vulkan was released. Direct3D 11 is much older and does not have support for something like the texture swizzle mask. Direct3D 12, however, does allow you to specify a [shader component mapping][1] when creating a resource view, which is effectively exactly the same thing&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22640" PostHistoryTypeId="5" PostId="8447" RevisionGUID="dad0df7f-05f6-4d97-a5b6-a558200568bf" CreationDate="2019-01-06T15:13:51.020" UserId="9812" Comment="added 17 characters in body" Text="Note that this feature was introduced with OpenGL 4.6 which came more than a year *after* Vulkan was released. Direct3D 11 is *much* older and does not have support for something like the texture swizzle mask. I don't know about Metal, but Direct3D 12 does allow you to specify a [shader component mapping][1] when creating a resource view (and has been doing so since long before Vulkan or OpenGL 4.6 ), which is effectively exactly the same thing&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22641" PostHistoryTypeId="12" PostId="8447" RevisionGUID="accecfed-ce91-4990-ae75-69d99dc31229" CreationDate="2019-01-06T15:18:03.747" UserId="9812" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:9812,&quot;DisplayName&quot;:&quot;Michael Kenzel&quot;}]}" />
  <row Id="22642" PostHistoryTypeId="5" PostId="8447" RevisionGUID="11b8a4f1-bf93-41c9-bfc9-560f3003b81a" CreationDate="2019-01-06T15:31:03.747" UserId="9812" Comment="added 319 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an OpenGL extension specification for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have!?), it's hard to say why feature X *is not* present in some other API. You would have to talk to whoever are the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][1] when creating a resource view, which is effectively exactly the same thing&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22643" PostHistoryTypeId="13" PostId="8447" RevisionGUID="f6fa54af-4ed6-4b9e-9f2a-65f997ce70d8" CreationDate="2019-01-06T15:31:06.840" UserId="9812" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:9812,&quot;DisplayName&quot;:&quot;Michael Kenzel&quot;}]}" />
  <row Id="22644" PostHistoryTypeId="5" PostId="8447" RevisionGUID="d5c2b6a6-429d-42f5-acbb-cf4de06b810e" CreationDate="2019-01-06T15:38:22.353" UserId="9812" Comment="added 319 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an OpenGL extension specification for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. You would have to talk to whoever are the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!?&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][1] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22645" PostHistoryTypeId="5" PostId="8447" RevisionGUID="7c0007aa-633a-48ea-8782-81b43faaf01e" CreationDate="2019-01-06T15:57:36.250" UserId="9812" Comment="added 319 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an OpenGL extension specification for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. You would have to talk to whoever are the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!? If you think about it, texture sampling hardware already has to support *lots* of different formats (floating point, signed integer, unsigned integer, normalized signed integer, normalized unsigned integer, all for different component sizes, sRGB versions for some, &amp;hellip;) with different numbers of components, including some where the order of components is different on the output side from what it is on the input side (BGRA). Adding a few bits to the texture descriptor to control which components go where in the output is probably not a big deal. I'm not a hardware engineer, but it would seem to me that it probably even makes the hardware simpler because it reduces the number of special cases. So I'd say chances are that hardware was already using a swizzle mask internally long before it was exposed on the API side anyways&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][1] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22646" PostHistoryTypeId="5" PostId="8447" RevisionGUID="b97bae17-ecdc-4946-ac5e-3f041090493a" CreationDate="2019-01-06T16:04:16.323" UserId="9812" Comment="deleted 8 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an [OpenGL extension specification][1] for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. You would have to talk to whoever are the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!? If you think about it, texture sampling hardware already has to support *lots* of different formats (floating point, signed integer, unsigned integer, normalized signed integer, normalized unsigned integer, all for different component sizes, sRGB versions for some, &amp;hellip;) with different numbers of components, including some where the order of components is different on the output side from what it is on the input side (BGRA). Adding a few bits to the texture descriptor to control which components go where in the output is probably not a big deal. I'm not a hardware engineer, but it would seem to me that it probably even makes the hardware simpler because it reduces the number of special cases. So I'd say chances are that hardware was already using a swizzle mask internally long before it was exposed on the API side&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][2] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_swizzle.txt&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22647" PostHistoryTypeId="5" PostId="8447" RevisionGUID="bb163fc7-ed18-47b4-a335-2b162c69a87f" CreationDate="2019-01-06T17:08:35.050" UserId="9812" Comment="added 42 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an [OpenGL extension specification][1] for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. There's a wide range of possible reasons. You would have to talk to whoever are the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!? If you think about it, texture sampling hardware already has to support *lots* of different formats (floating point, signed integer, unsigned integer, normalized signed integer, normalized unsigned integer, all for different component sizes, sRGB versions for some, &amp;hellip;) with different numbers of components, including some where the order of components is different on the output side from what it is on the input side (BGRA). Adding a few bits to the texture descriptor to control which components go where in the output is probably not a big deal. I'm not a hardware engineer, but it would seem to me that it probably even makes the hardware simpler because it reduces the number of special cases that need to be implemented. So I'd say chances are that hardware was already using a swizzle mask internally long before it was exposed on the API side&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][2] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_swizzle.txt&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22648" PostHistoryTypeId="2" PostId="8448" RevisionGUID="9aaaac82-505f-4de3-b0cf-474e60e0a1aa" CreationDate="2019-01-06T17:15:20.493" UserId="3003" Text="In games and other 3D scenes, generally when the user clicks the mouse, a ray is cast into the scene in the direction the camera is facing, and a check is done to see what geometry in the scene it intersects. If it intersects nothing, it is ignored. If it intersects a single object, then the application processes a click on that object (at the location of the intersection). If more than one object is intersected, then usually the front-most object is assumed to be the on the user wanted to click on, so that is processed.&#xD;&#xA;&#xD;&#xA;In general, geometry is stored using x,y,z coordinates rather than spherical coordinates, as the GPU hardware works in cartesian coordinates." ContentLicense="CC BY-SA 4.0" />
  <row Id="22649" PostHistoryTypeId="5" PostId="8447" RevisionGUID="48291a0b-aac5-43c8-abc2-ed760401da00" CreationDate="2019-01-06T17:24:55.540" UserId="9812" Comment="deleted 28 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an [OpenGL extension specification][1] for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. There's a wide range of possible reasons. You would have to talk to whoever are the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!? If you think about it, texture sampling hardware already has to support *lots* of different formats (floating point, signed integer, unsigned integer, normalized signed integer, normalized unsigned integer, all for different component sizes, sRGB versions for some, &amp;hellip;) with different numbers of components, including some where the order of components is different on the output side from what it is on the input side (BGRA). Adding a few bits to the texture descriptor to control which components go where in the output is probably not a big deal. I'm not a hardware engineer, but it would seem to me that it probably even makes the hardware simpler because it reduces the number of special cases. So I'd say chances are that hardware was already using a swizzle mask internally long before it was exposed on the API side&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][2] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_swizzle.txt&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22650" PostHistoryTypeId="5" PostId="8447" RevisionGUID="77f544ed-3bf5-466f-850c-7c360759d2d7" CreationDate="2019-01-06T17:36:12.017" UserId="9812" Comment="added 1 character in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an [OpenGL extension specification][1] for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. There's a wide range of possible reasons. You would have to talk to whoever were the people responsible for the design of the API in question at the time&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!? If you think about it, texture sampling hardware already has to support *lots* of different formats (floating point, signed integer, unsigned integer, normalized signed integer, normalized unsigned integer, all for different numbers of components, component sizes, sRGB versions for some, compressed formats, &amp;hellip;) including some where the order of components is different on the output side from what it is on the input side (e.g., BGRA). Adding a few bits to the texture descriptor to control which components go where in the output is probably not a big deal. I'm not a hardware engineer, but it would seem to me that it probably even makes the hardware simpler because it reduces the number of special cases. So I'd say chances are that hardware was already using a swizzle mask internally long before it was exposed on the API side&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][2] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_swizzle.txt&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22651" PostHistoryTypeId="5" PostId="8447" RevisionGUID="bea5cdf7-64c9-430c-9548-ef456e3ee812" CreationDate="2019-01-06T18:20:40.817" UserId="9812" Comment="added 12 characters in body" Text="&gt; Why is this feature present in OpenGL/Vulkan and not Direct3D/Metal?&#xD;&#xA;&#xD;&#xA;It's present in OpenGL because someone thought it would be a good idea, wrote an [OpenGL extension specification][1] for it, released and supported the extension in their drivers, and the extension was eventually adopted into core profile. While it's usually pretty obvious why feature X *is* present in some API (because it's a thing that makes sense to have), it's generally hard to say why feature X *is not* present in some other API. There's a wide range of possible reasons. You would have to talk to whoever were the people responsible for the design of the API in question at the time to find out&amp;hellip;&#xD;&#xA;&#xD;&#xA;Concerning hardware support: In case of doubt, you can simply convince yourself by comparing rendering times with and without using a texture swizzle. You would notice if you were hitting a software path there. The fact that the extension was introduced by NVIDIA would lead me to the conclusion that there's at least one hardware vendor that is able to support this on their hardware; otherwise, why would they introduce it!? If you think about it: Texture sampling hardware already has to support *lots* of different formats (floating point, signed integer, unsigned integer, normalized signed integer, normalized unsigned integer, all for different numbers of components, component sizes, sRGB versions for some, compressed formats, &amp;hellip;) including some where the order of components is different on the output side from what it is on the input side (e.g., BGRA). Adding a few bits to the texture descriptor to control which components go where in the output is probably not a big deal. I'm not a hardware engineer, but it would seem to me that it probably even makes the hardware simpler because it reduces the number of special cases. So I'd say chances are that hardware was already using a swizzle mask internally long before it was exposed on the API side&amp;hellip;&#xD;&#xA;&#xD;&#xA;Apart from that, while I don't know about Metal, Direct3D 12 does allow you to specify a [shader component mapping][2] when creating a resource view, which is effectively exactly the same thing as the OpenGL texture swizzle mask&amp;hellip;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_swizzle.txt&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_shader_component_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22652" PostHistoryTypeId="2" PostId="8449" RevisionGUID="ff8a7713-6826-44c6-85a9-34f0a6c1d1f0" CreationDate="2019-01-06T18:49:10.817" UserId="9966" Text="I'm reading up on coordinate systems and geometric trasformations but the change of basis topic still confuses me. I found this exercise but honestly I wouldn't know how to begin. &quot;Given a world coordinate system in which the camera is at (3,3,0) and pointed at the origin (0,0,0) write an orthonormal  set (**e_1, e_2, e_3**) with an axis oriented like the camera axis and the matrix for the change of coordinates from world frame to camera frame (**O, e_1, e_2, e_3**).&quot; Do I need to use homogeneous coordinates or not? Currently, I'm using this book here (https://www.pearson.com/us/higher-education/product/Angel-Interactive-Computer-Graphics-A-Top-Down-Approach-with-Shader-Based-Open-GL-6th-Edition/9780132545235.html). If anyone could suggest a better alternative I'd be grateful. " ContentLicense="CC BY-SA 4.0" />
  <row Id="22653" PostHistoryTypeId="1" PostId="8449" RevisionGUID="ff8a7713-6826-44c6-85a9-34f0a6c1d1f0" CreationDate="2019-01-06T18:49:10.817" UserId="9966" Text="Need help with change of basis (world to camera frame)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22654" PostHistoryTypeId="3" PostId="8449" RevisionGUID="ff8a7713-6826-44c6-85a9-34f0a6c1d1f0" CreationDate="2019-01-06T18:49:10.817" UserId="9966" Text="|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22659" PostHistoryTypeId="2" PostId="8451" RevisionGUID="586dbe09-d1de-4573-a559-3b6475cd87cf" CreationDate="2019-01-07T06:22:09.143" UserId="3416" Text="In Cg tuts, [Diffuse Section][1]&#xD;&#xA;&gt;  Surfaces that face away from the light will produce negative dot-product values, so the max(N · L, 0) in the equation ensures that these surfaces show no diffuse lighting.&#xD;&#xA;&#xD;&#xA;My question is why not just leave it be negative? IMO, both the negative and zero will make the color be black. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter05.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22660" PostHistoryTypeId="1" PostId="8451" RevisionGUID="586dbe09-d1de-4573-a559-3b6475cd87cf" CreationDate="2019-01-07T06:22:09.143" UserId="3416" Text="Why Diffuse Light use max(N · H, 0) instead of just letting it be negative?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22661" PostHistoryTypeId="3" PostId="8451" RevisionGUID="586dbe09-d1de-4573-a559-3b6475cd87cf" CreationDate="2019-01-07T06:22:09.143" UserId="3416" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22662" PostHistoryTypeId="2" PostId="8452" RevisionGUID="2a5f667c-a9bf-4295-955f-58dd330f4d79" CreationDate="2019-01-07T06:30:08.520" UserId="6588" Text="Because negative shading values are undefined and don't play well with tonemapping. It is preferable to use values in $[0,1]$ for low-dynamic-range or $[0,+\infty)$ for high-dynamic-range images." ContentLicense="CC BY-SA 4.0" />
  <row Id="22663" PostHistoryTypeId="2" PostId="8453" RevisionGUID="e7d3b846-b914-4ab4-b7d8-0b8fb01b5f03" CreationDate="2019-01-07T07:13:41.747" UserId="56" Text="If lighting with multiple lights, they add together to make the final lighting value. A negative light would darken other lights, which is incorrect.  This is also true if you add in specular reflections, emissive lighting, or other sources of lighting. The negative lighting from one source of lighting would darken some other source of non negative lighting.&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22664" PostHistoryTypeId="5" PostId="8449" RevisionGUID="0eb44399-61f1-4906-9add-b14ec08b6169" CreationDate="2019-01-07T11:29:34.837" UserId="9812" Comment="improved formatting, fixed typos" Text="I'm reading up on coordinate systems and geometric transformations but the change of basis topic still confuses me. I found this exercise but, honestly, I wouldn't know how to begin:&#xD;&#xA;&#xD;&#xA;&gt; Given a world coordinate system in which the camera is at $(3,3,0)$ and pointed at the origin $(0,0,0)$ write an orthonormal set $(e_1, e_2, e_3)$ with an axis oriented like the camera axis and the matrix for the change of coordinates from world frame to camera frame $(O, e_1, e_2, e_3)$.&#xD;&#xA;&#xD;&#xA;Do I need to use homogeneous coordinates or not? Currently, I'm using the book [*Interactive Computer Graphics: A Top-Down Approach with Shader-Based OpenGL*][1]. If anyone could suggest a better alternative I'd be grateful. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.pearson.com/us/higher-education/product/Angel-Interactive-Computer-Graphics-A-Top-Down-Approach-with-Shader-Based-Open-GL-6th-Edition/9780132545235.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22665" PostHistoryTypeId="24" PostId="8449" RevisionGUID="0eb44399-61f1-4906-9add-b14ec08b6169" CreationDate="2019-01-07T11:29:34.837" Comment="Proposed by 9812 approved by 9966 edit id of 452" ContentLicense="CC BY-SA 4.0" />
  <row Id="22666" PostHistoryTypeId="2" PostId="8454" RevisionGUID="67f96274-c813-4a6d-91e0-06dcbc9a6e89" CreationDate="2019-01-07T14:57:56.453" UserId="9812" Text="Since the transformation that is asked for includes a translation (the camera is located at a position other than the origin), you will indeed have to use homogeneous coordinates to describe this transformation in matrix form.&#xD;&#xA;&#xD;&#xA;There are basically two ways to get to the matrix you're looking for. You can either set up the matrix that would transform from camera coordinates to world-space and then take the inverse of that, or you can build the matrix directly. The first approach is what is typically done and what the exercise seems to be aiming for since it explicitly asks for the base vectors of the camera system as seen from world-space, which is the first step in that process. The advantage of this approach is that it is arguably a bit more intuitive since what you're essentially doing is treat the camera as just another object that you place in world-space by setting up a matrix. Just that once you have that matrix, you invert it because you didn't actually want to get from camera-local coordinates to world coordinates but rather the other way around. I'll explain both approaches below using the concrete example given in your exercise. At least for now, I'll leave the generalization of the ideas presented below as an exercise to the reader (so that at least some of the fun remains for you ).&#xD;&#xA;&#xD;&#xA;Let's look at a sketch of the whole situation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/NnAhM.png&quot; width=&quot;320&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Your camera is located a $\vec o = \mvec{3 &amp; 3 &amp; 0}^T$ and is supposed to be looking at the origin.&#xD;&#xA;&#xD;&#xA;## Approach 1&#xD;&#xA;&#xD;&#xA;From the above sketch, is it immediately apparent that the coordinates of $\vec e_3$ have to be&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_3 = \frac{1}{\sqrt{3^2 + 3^2 + 0}} \mvec{3 \\ 3 \\ 0} = \frac{1}{\sqrt{2\cdot3^2}} \mvec{3 \\ 3 \\ 0} = \mvec{\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0}.&#xD;&#xA;\end{equation}&#xD;&#xA;The base vector $\vec e_2$ is just $\vec e_3$ rotated by $90°$:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_2 = \mvec{-\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0}.&#xD;&#xA;\end{equation}&#xD;&#xA;And $\vec e_1$ just points in the direction opposite of the world-space z-axis:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_1 = \mvec{0 \\ 0 \\ -1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Using the world-space base vectors of the camera frame, we can write down a matrix that transforms from camera-space to world-space. The camera matrix that transforms from camera to world coordinates is then simply the inverse of that matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mmat{\vec e_1 &amp; \vec e_2 &amp; \vec e_3 &amp; \vec o \\ 0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;         = \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since the camera frame has an [orthonormal base][1] just offset by $\vec o$, this matrix is composed of just the rotation defined by the orthonormal base vectors followed by a translation:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mat T \mat R&#xD;&#xA;\end{equation}&#xD;&#xA;where&#xD;&#xA;\begin{align}&#xD;&#xA;  \mat R &amp;= \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} &amp; &#xD;&#xA;  \mat T &amp;= \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{align}&#xD;&#xA;You can convince yourself that this is true by simply performing the multiplication. Knowing this, we can compute the camera matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam} = (\mat T \mat R)^{-1} = \mat R^{-1} \mat T^{-1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since $\mat R$ is composed of orthonormal base vectors, it is an orthogonal matrix, which means that its inverse is just its transpose. $\mat T$ is just a translation, its inverse is a translation in the opposite direction. Therefore,&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \cdot \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \\&#xD;&#xA;    &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;  \end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Approach 2&#xD;&#xA;&#xD;&#xA;An alternative to the approach above is to just directly compute the coordinates of the world-space base vectors as seen from the perspective of the camera. Given these coordinates, we can, again, just write down a matrix that applies the corresponding transformation from world to camera space.&#xD;&#xA;&#xD;&#xA;Looking at the figure again, we see that the coordinates of the world-space x-axis as seen from camera space are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec x' = \mvec{0 \\ -\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}}.&#xD;&#xA;\end{equation}&#xD;&#xA;Analogously, we find the camera-space coordinates of the world-space y- and z-axes:&#xD;&#xA;\begin{align}&#xD;&#xA;  \vec y' &amp;= \mvec{0 \\ \frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}} &amp; &#xD;&#xA;  \vec z' &amp;= \mvec{-1 \\ 0 \\ 0}.&#xD;&#xA;\end{align}&#xD;&#xA;Also looking at the figure, we note that the world-space origin as seen from the camera is simply located at a distance of $\sqrt{3^2 + 3^2} = 3\sqrt{2}$ units along the negative $\vec e_3$ axis. Therefore, the camera-space coordinates of the world origin are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec o' = \mvec{0 \\ 0 \\ -3\sqrt{2}}.&#xD;&#xA;\end{equation} and we can, once again, write down the matrix&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;  \end{split},&#xD;&#xA;\end{equation}&#xD;&#xA;and sleep well tonight because both ways did indeed lead to the same result…&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orthonormality" ContentLicense="CC BY-SA 4.0" />
  <row Id="22667" PostHistoryTypeId="2" PostId="8455" RevisionGUID="d54f1ee9-6b8a-43d3-9ecc-a76701fa334c" CreationDate="2019-01-07T16:59:58.463" UserId="9976" Text="$N \cdot L &lt; 0$ implies that the light is directed in the direction opposite the normal to the visible surface of the polygon. This means that the light is coming from behind and striking the back face of the polygon. In the analogous situation in real life, light striking one face of an opaque surface does not affect the illumination of a second face. Shining light on the back of a book (or other opaque object) does make the front of the book darker (that is it does not apply negative lighting): it simply has no effect on the front face of the book. This is the reason for the max() function.&#xD;&#xA;&#xD;&#xA;Applying negative illumination to a surface where $N \cdot L &lt; 0$ doesn't make sense physically. In geometric optics with incoherent light sources there is no such thing as negative illumination." ContentLicense="CC BY-SA 4.0" />
  <row Id="22668" PostHistoryTypeId="5" PostId="8454" RevisionGUID="7932a1bf-d9d2-43f6-a5b6-2d86a237578d" CreationDate="2019-01-07T17:57:20.517" UserId="9812" Comment="added 1 character in body" Text="Since the transformation that is asked for includes a translation (the camera is located at a position other than the origin), you will indeed have to use homogeneous coordinates to describe this transformation in matrix form.&#xD;&#xA;&#xD;&#xA;There are basically two ways to get to the matrix you're looking for. You can either set up the matrix that would transform from camera coordinates to world-space and then take the inverse of that, or you can build the matrix directly. The first approach is what is typically done and what the exercise seems to be aiming for since it explicitly asks for the base vectors of the camera system as seen from world-space, which is the first step in that process. The advantage of this approach is that it is arguably a bit more intuitive since what you're essentially doing is treat the camera as just another object that you place in world-space by setting up a matrix. Just that once you have that matrix, you invert it because you didn't actually want to get from camera-local coordinates to world coordinates but rather the other way around. I'll explain both approaches below using the concrete example given in your exercise. At least for now, I'll leave the generalization of the ideas presented below as an exercise to the reader (so that at least some of the fun remains for you ).&#xD;&#xA;&#xD;&#xA;Let's look at a sketch of the whole situation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/NnAhM.png&quot; width=&quot;320&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Your camera is located at $\vec o = \mvec{3 &amp; 3 &amp; 0}^T$ and is supposed to be looking at the origin.&#xD;&#xA;&#xD;&#xA;## Approach 1&#xD;&#xA;&#xD;&#xA;From the above sketch, is it immediately apparent that the coordinates of $\vec e_3$ have to be&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_3 = \frac{1}{\sqrt{3^2 + 3^2 + 0}} \mvec{3 \\ 3 \\ 0} = \frac{1}{\sqrt{2\cdot3^2}} \mvec{3 \\ 3 \\ 0} = \mvec{\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0}.&#xD;&#xA;\end{equation}&#xD;&#xA;The base vector $\vec e_2$ is just $\vec e_3$ rotated by $90°$:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_2 = \mvec{-\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0}.&#xD;&#xA;\end{equation}&#xD;&#xA;And $\vec e_1$ just points in the direction opposite of the world-space z-axis:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_1 = \mvec{0 \\ 0 \\ -1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Using the world-space base vectors of the camera frame, we can write down a matrix that transforms from camera-space to world-space. The camera matrix that transforms from camera to world coordinates is then simply the inverse of that matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mmat{\vec e_1 &amp; \vec e_2 &amp; \vec e_3 &amp; \vec o \\ 0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;         = \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since the camera frame has an [orthonormal base][1] just offset by $\vec o$, this matrix is composed of just the rotation defined by the orthonormal base vectors followed by a translation:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mat T \mat R&#xD;&#xA;\end{equation}&#xD;&#xA;where&#xD;&#xA;\begin{align}&#xD;&#xA;  \mat R &amp;= \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} &amp; &#xD;&#xA;  \mat T &amp;= \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{align}&#xD;&#xA;You can convince yourself that this is true by simply performing the multiplication. Knowing this, we can compute the camera matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam} = (\mat T \mat R)^{-1} = \mat R^{-1} \mat T^{-1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since $\mat R$ is composed of orthonormal base vectors, it is an orthogonal matrix, which means that its inverse is just its transpose. $\mat T$ is just a translation, its inverse is a translation in the opposite direction. Therefore,&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \cdot \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \\&#xD;&#xA;    &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;  \end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Approach 2&#xD;&#xA;&#xD;&#xA;An alternative to the approach above is to just directly compute the coordinates of the world-space base vectors as seen from the perspective of the camera. Given these coordinates, we can, again, just write down a matrix that applies the corresponding transformation from world to camera space.&#xD;&#xA;&#xD;&#xA;Looking at the figure again, we see that the coordinates of the world-space x-axis as seen from camera space are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec x' = \mvec{0 \\ -\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}}.&#xD;&#xA;\end{equation}&#xD;&#xA;Analogously, we find the camera-space coordinates of the world-space y- and z-axes:&#xD;&#xA;\begin{align}&#xD;&#xA;  \vec y' &amp;= \mvec{0 \\ \frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}} &amp; &#xD;&#xA;  \vec z' &amp;= \mvec{-1 \\ 0 \\ 0}.&#xD;&#xA;\end{align}&#xD;&#xA;Also looking at the figure, we note that the world-space origin as seen from the camera is simply located at a distance of $\sqrt{3^2 + 3^2} = 3\sqrt{2}$ units along the negative $\vec e_3$ axis. Therefore, the camera-space coordinates of the world origin are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec o' = \mvec{0 \\ 0 \\ -3\sqrt{2}}.&#xD;&#xA;\end{equation} and we can, once again, write down the matrix&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;  \end{split},&#xD;&#xA;\end{equation}&#xD;&#xA;and sleep well tonight because both ways did indeed lead to the same result…&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orthonormality" ContentLicense="CC BY-SA 4.0" />
  <row Id="22669" PostHistoryTypeId="2" PostId="8456" RevisionGUID="cbf11c4c-71bb-46e0-bb50-b4027ddaf694" CreationDate="2019-01-08T05:17:53.997" UserId="8565" Text="I am in the middle of implementing stochastic screen space reflection based on frostbite presentation [here][1]. On page number 39, it is stated that we need to reproject the ray intersection location instead of the reflected surface location. I don't really get what's the difference between the two. Isn't ray intersection location the same as the reflected surface location. Can someone explain this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cse.chalmers.se/edu/course/TDA361/Advanced%20Computer%20Graphics/Screen-space%20reflections.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22670" PostHistoryTypeId="1" PostId="8456" RevisionGUID="cbf11c4c-71bb-46e0-bb50-b4027ddaf694" CreationDate="2019-01-08T05:17:53.997" UserId="8565" Text="What to reproject when doing temporal filtering in stochastic screen space reflection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22671" PostHistoryTypeId="3" PostId="8456" RevisionGUID="cbf11c4c-71bb-46e0-bb50-b4027ddaf694" CreationDate="2019-01-08T05:17:53.997" UserId="8565" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22672" PostHistoryTypeId="5" PostId="8456" RevisionGUID="80fce023-d941-4c21-aee8-cbdbdce0cea9" CreationDate="2019-01-08T05:39:33.567" UserId="8565" Comment="added 803 characters in body" Text="I am in the middle of implementing stochastic screen space reflection based on frostbite presentation [here][1]. On page number 39, it is stated that we need to reproject the ray intersection location instead of the reflected surface location. I don't really get what's the difference between the two. Isn't ray intersection location the same as the reflected surface location. Can someone explain this?&#xD;&#xA;&#xD;&#xA;And then in another [ppt][2], they mention that&#xD;&#xA;&#xD;&#xA;&gt; I mentioned temporal reprojection, so let’s have a quick look at it&#xD;&#xA;&gt; now. The idea is simple: given a pixel’s 3D coordinate, check where it&#xD;&#xA;&gt; was in the previous frame, project it, and we have the texcoord to&#xD;&#xA;&gt; sample.&#xD;&#xA;&gt; &#xD;&#xA;&gt; … except when we move the viewport, reflections exhibit parallax. That&#xD;&#xA;&gt; is, the reflected objects move according to their depth, not the depth&#xD;&#xA;&gt; of the surface which reflects them. Attempting to reproject&#xD;&#xA;&gt; reflections using the closer depth results in smearing. So we&#xD;&#xA;&gt; calculate the average depth of the reflected objects, and reproject&#xD;&#xA;&gt; using that. This results in much reduced smearing.&#xD;&#xA;&#xD;&#xA;Again I don't understand this at all.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cse.chalmers.se/edu/course/TDA361/Advanced%20Computer%20Graphics/Screen-space%20reflections.pdf&#xD;&#xA;  [2]: https://www.ea.com/frostbite/news/stochastic-screen-space-reflections" ContentLicense="CC BY-SA 4.0" />
  <row Id="22673" PostHistoryTypeId="5" PostId="343" RevisionGUID="4c17d4a8-d309-432a-9c38-87e4cbd7e1f4" CreationDate="2019-01-08T09:08:00.950" UserId="209" Comment="minor spelling correction" Text="B-Splines and Beziers are parallel inventions of more or less the same thing. Where Beziers try to start from the idea of fitting tangents. B-Splines start with the idea of basis functions. NURB Splines (or the rational part in fact) are just generalizations of B-Splines so you can describe accurate conic sections\*, as they are of special interest in engineering.&#xD;&#xA;&#xD;&#xA;First let us start with a simple NURB Spline terminology. The rationale of these curves is a bit different than for Beziers. First there is the concept of a span. A span would roughly be equivalent to a whole Bezier spline except in nurbs you can have any number of spans. &#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: One cubic NURBS span. This is a bit atypical in formulation&#xD;&#xA;&#xD;&#xA;Each span is formed by the curve degree + 1  control points\*\*. Each curve can consist of any number of points. Each consecutive span reuses the points form previous span by dropping one point and taking one point more in the list. So making more complex curves is as easy as just appending more points to the curve.&#xD;&#xA;&#xD;&#xA;**NOTE**: The images curves are a bit atypically parametrized, ill explain what this means in the next section. When i take the concept of knots up. This is just a easier way to explain how the curves glue together.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![enter image description here][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: 2 cubic spans after each other, each span uses 4 points. together they form one curve. They share most points with each other.&#xD;&#xA;&#xD;&#xA;By now we have probably answered the 2 question about adding complexity. But I would like to add that this scheme ensures better continuity than a bezier curve. Additionally you can make the point array that forms the hull cyclic. Forming a closed curve.&#xD;&#xA;&#xD;&#xA;![enter image description here][3]&#xD;&#xA;&#xD;&#xA;**Image 3**: A closed cubic NURBS surface has as many spans as it has points. Each color is one span.&#xD;&#xA;&#xD;&#xA;### Parametrization&#xD;&#xA;&#xD;&#xA;Up until this point one could just say that the stringing together the spans is a trick just as &quot;sewing&quot; the Bezier curves. But there is a difference. The curve is parametrisized along its length. So the curves are not separate they do not interpolate form 0 to 1 on each span like Beziers do. Instead the underlying curve has a cusomizable parameter range. The parameter is stored in something called a knot, and each knot can have a arbitrary increasing value in the sequence. So you can parametrize the entire curves u range to 0 - 1 or 0 to 12. The parametrization also does not have to be uniform.&#xD;&#xA;&#xD;&#xA;This parametrization changes how the curve is shaped. Why would this be useful? Well you can adjust the tension along the curve for one. Or you could encode the length of the curve into to the U parameter. One peculiar use is to make the NURBS curve act like a Bezier curve either fully or just partially (bezier like in the ends but not in the middle for example).&#xD;&#xA;&#xD;&#xA;![enter image description here][4]&#xD;&#xA;&#xD;&#xA;**Image 4**: Same points different knot sequences. The green NURBS curve corresponds to a Bezier curve that has a parameter range of 0-2 instead of 0-1&#xD;&#xA;&#xD;&#xA;**Ok so what are the knots?** They are simply the ranges of the basis functions. Since the cubic b-spline with 4 points has 4 interpolating functions it needs 8 knots. Only areas where 3 functions overlap and sum up to 1.0 can a line be drawn.&#xD;&#xA;&#xD;&#xA;![enter image description here][5]&#xD;&#xA;&#xD;&#xA;**Image 5**: 2 different basis functions, a bezier like and a uniform segment parametrisation, spread to 0-1 range. &#xD;&#xA;&#xD;&#xA;And now we have mostly described the answer to question 1. The range is not defined you can stretch the basis functions as you see fit. And finally the knot vector simply produces the parameter ranges for the basis functions. Theres still one more thing that governs the shape of the curve and that is the weight vector. But that another story to be told elsewhere.&#xD;&#xA;&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;\* This rational in this case means that a NURBS curve does not have to be a polynomial, as you cant describe a circle with polynomials. &#xD;&#xA;&#xD;&#xA;\*\* One can define other types of points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mHFPu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PzKKi.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rolEZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/w7sHM.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/GnJeM.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="22678" PostHistoryTypeId="2" PostId="8458" RevisionGUID="855a4b28-0f48-4652-9ed8-9169c5b89590" CreationDate="2019-01-08T12:44:42.460" UserId="9982" Text="I'm a newbie with OpenGl and I'm stuck in following the tutoriasl. &#xD;&#xA;I found [this tutorial][1] with these shaders&#xD;&#xA;&#xD;&#xA;    // Shader sources&#xD;&#xA;    const GLchar* vertexSource = R&quot;glsl(&#xD;&#xA;        #version 150 core&#xD;&#xA;        in vec2 position;&#xD;&#xA;        in vec3 color;&#xD;&#xA;        in vec2 texcoord;&#xD;&#xA;        out vec3 Color;&#xD;&#xA;        out vec2 Texcoord;&#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;            Color = color;&#xD;&#xA;            Texcoord = texcoord;&#xD;&#xA;            gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 150 core&#xD;&#xA;        in vec3 Color;&#xD;&#xA;        in vec2 Texcoord;&#xD;&#xA;        out vec4 outColor;&#xD;&#xA;        uniform sampler2D tex0;&#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;            outColor = texture(tex0, Texcoord) * vec4(Color, 1.0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;I noticed that the proposed shaders couldn't compile in my computer, since my GLsl version is 1.30, but changing the version declaration into&#xD;&#xA;&#xD;&#xA;    #version 130 core&#xD;&#xA;the ouput of this instruction is `glGetShaderInfoLog(vertexShader, 512, NULL, infoLog)`;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; 0:2(10): error: illegal text following version number&#xD;&#xA;&#xD;&#xA;I wuould like to understand what is wrong in this shader (in version 1.30) or at least where to find enough information to &quot;repair&quot; this situation.&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://open.gl/textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="22679" PostHistoryTypeId="1" PostId="8458" RevisionGUID="855a4b28-0f48-4652-9ed8-9169c5b89590" CreationDate="2019-01-08T12:44:42.460" UserId="9982" Text="Convert shader from GLsl 1.50 to 1.30" ContentLicense="CC BY-SA 4.0" />
  <row Id="22680" PostHistoryTypeId="3" PostId="8458" RevisionGUID="855a4b28-0f48-4652-9ed8-9169c5b89590" CreationDate="2019-01-08T12:44:42.460" UserId="9982" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22681" PostHistoryTypeId="2" PostId="8459" RevisionGUID="e2a4a729-97bb-40ec-b19d-9eeb01c50961" CreationDate="2019-01-08T14:31:07.597" UserId="9812" Text="There is no such thing as a core profile in GLSL 1.30. The concept of API profiles was introduced with OpenGL 3.2 which happened after GLSL 1.30 was released. The syntax for the version specification in [GLSL 1.30][1] is &#xD;&#xA;&#xD;&#xA;    #version &lt;number&gt;&#xD;&#xA;&#xD;&#xA;Apart from that, I highly recommend that you check to confirm that GLSL 1.30 *really* is the maximum version you're supposed to be able to use on your system. It seems likely that you just don't have a proper OpenGL driver installed. Even software implementations like MESA support more recent versions than that these days…&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.30.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22682" PostHistoryTypeId="5" PostId="8459" RevisionGUID="8a1463e3-a5c2-4139-8f9c-be1d01959441" CreationDate="2019-01-08T14:36:41.007" UserId="9812" Comment="added 5 characters in body" Text="There is no such thing as a core profile in GLSL 1.30. The concept of API profiles was introduced with OpenGL 3.2 which happened after GLSL 1.30 was released. The syntax for the version specification in [GLSL 1.30][1] is &#xD;&#xA;&#xD;&#xA;    #version &lt;number&gt;&#xD;&#xA;&#xD;&#xA;Apart from that, I highly recommend that you check to confirm that GLSL 1.30 *really* is the maximum version you're supposed to be able to use on your system. It seems no unlikely that you just don't have a proper OpenGL driver installed. Even software implementations like MESA support more recent versions than that these days…&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.30.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22683" PostHistoryTypeId="2" PostId="8460" RevisionGUID="81128ad4-c735-4265-8760-2f7a296db466" CreationDate="2019-01-08T14:46:33.790" UserId="1940" Text="One of the first things that many people get wrong with MIS of direct lighting is that you have to always consider the same light source for both light sampling and BSDF sampling. For example, if you sampled Light $L_i$ during light sampling and the ray spawned from BSDF sampling hit $L_j$, you cannot mix them together since the probabilities cannot be used together for weights. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22687" PostHistoryTypeId="2" PostId="8462" RevisionGUID="7f6fb1b4-bf6d-4964-a281-6ce080aafc76" CreationDate="2019-01-08T22:09:11.980" UserId="9983" Text="I am working with an atlas shader that steps through various sprite tiles within a single png atlas page to playback an animation with sampler2D.  Looking at the shader code, I would expect to have to define a lower left and upper right point for each image area on the atlas image that I want to use for that frame.  However, it simply uses a Vec2 which is just a single x,y value.  How is this possible?  How is a single vec2 defining both position and range of the sampled area?  In a more broad sense how are these UV vec2s from varying UVs being interpreted in GLSL in general?  To me, you can't define an image area from just a vec2 so I am really confused???" ContentLicense="CC BY-SA 4.0" />
  <row Id="22688" PostHistoryTypeId="1" PostId="8462" RevisionGUID="7f6fb1b4-bf6d-4964-a281-6ce080aafc76" CreationDate="2019-01-08T22:09:11.980" UserId="9983" Text="How does a GLSL Sampler2D read a Vec2 UV coordinate to determine UV range" ContentLicense="CC BY-SA 4.0" />
  <row Id="22689" PostHistoryTypeId="3" PostId="8462" RevisionGUID="7f6fb1b4-bf6d-4964-a281-6ce080aafc76" CreationDate="2019-01-08T22:09:11.980" UserId="9983" Text="|shader|glsl|uv-mapping|image|tile-based-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22690" PostHistoryTypeId="5" PostId="8459" RevisionGUID="69edcfb5-3307-43d5-8626-3538a27b8dac" CreationDate="2019-01-09T00:08:49.577" UserId="9812" Comment="added 1 character in body" Text="There is no such thing as a core profile in GLSL 1.30. The concept of API profiles was introduced with OpenGL 3.2 which happened after GLSL 1.30 was released. The syntax for the version specification in [GLSL 1.30][1] is &#xD;&#xA;&#xD;&#xA;    #version &lt;number&gt;&#xD;&#xA;&#xD;&#xA;Apart from that, I highly recommend that you check to confirm that GLSL 1.30 *really* is the maximum version you're supposed to be able to use on your system. It seems not unlikely that you just don't have a proper OpenGL driver installed. Even software implementations like MESA support more recent versions than that these days…&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.30.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22691" PostHistoryTypeId="2" PostId="8463" RevisionGUID="6e43f852-4214-40ea-ad9f-1df47907af07" CreationDate="2019-01-09T08:39:49.520" UserId="7644" Text="It's hard to say without seeing the shader in question. My guess is that every animation frame in the atlas has the same size. This fixed size allows mapping any UV coordinates to the proper animation frame's UV extents.&#xD;&#xA;&#xD;&#xA;For example, with 16 frames in a texture:&#xD;&#xA;&#xD;&#xA;    0 0.25 0.5 0.75 1.0&#xD;&#xA;	\  \   |   /  _/&#xD;&#xA;	 +--+--+--+--+&#xD;&#xA;	 | 0| 1| 2| 3|&#xD;&#xA;	 +--+--+--+--+ 0.25&#xD;&#xA;	 | 4| 5| 6| 7|&#xD;&#xA;	 +--+--+--+--+ 0.5&#xD;&#xA;	 | 8| 9|10|11|&#xD;&#xA;	 +--+--+--+--+ 0.75&#xD;&#xA;	 |12|13|14|15|&#xD;&#xA;	 +--+--+--+--+ 1.0&#xD;&#xA;&#xD;&#xA;This code should do the trick to convert UV coordinates (range [0, 1]) to a given frame's UV extents:&#xD;&#xA;&#xD;&#xA;	vec2 uv = ...&#xD;&#xA;	uint frameId = ... // [0, 15]&#xD;&#xA;	const uint rowFrameCount = 4; // implies frameUVWidth = 1 / 4 = 0.25&#xD;&#xA;	const vec2 frameUVSize = vec2(1.0 / rowFrameCount, 0.25);&#xD;&#xA;&#xD;&#xA;	// Find the column and row offset&#xD;&#xA;	uvec2 frameOffset = uvec2(frameId % rowFrameCount, frameId / rowFrameCount);&#xD;&#xA;&#xD;&#xA;	// Offset to the proper column&#xD;&#xA;	uv += frameOffset;&#xD;&#xA;&#xD;&#xA;	// Scale the coordinates in the range of a single frame (here [f_0, f_0 + 0.25])&#xD;&#xA;	uv *= frameUVSize;&#xD;&#xA;&#xD;&#xA;Some results:&#xD;&#xA;&#xD;&#xA;	uv = vec2(0, 1); frameId = 0; uv_out = vec2(0, 0.25);&#xD;&#xA;	uv = vec2(0, 0.5); frameId = 3; uv_out = vec2(0.75, 0.125);&#xD;&#xA;	uv = vec2(0.5, 0.5); frameId = 14; uv_out = vec2(0.625, 0.875);&#xD;&#xA;&#xD;&#xA;In truth however, this kind of texture trickery is less useful these days since [array textures][1] are now widely available with better results and simpler indexing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Array_Texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="22696" PostHistoryTypeId="5" PostId="8458" RevisionGUID="183603ef-44d7-4e86-8072-c300e5d6393f" CreationDate="2019-01-09T13:57:16.580" UserId="9982" Comment="update new version of code" Text="I'm a newbie with OpenGl and I'm stuck in following the tutorial. &#xD;&#xA;I found [this tutorial][1] with these shaders&#xD;&#xA;&#xD;&#xA;    // Shader sources&#xD;&#xA;    const GLchar* vertexSource = R&quot;glsl(&#xD;&#xA;        #version 150 core&#xD;&#xA;        in vec2 position;&#xD;&#xA;        in vec3 color;&#xD;&#xA;        in vec2 texcoord;&#xD;&#xA;        out vec3 Color;&#xD;&#xA;        out vec2 Texcoord;&#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;            Color = color;&#xD;&#xA;            Texcoord = texcoord;&#xD;&#xA;            gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 150 core&#xD;&#xA;        in vec3 Color;&#xD;&#xA;        in vec2 Texcoord;&#xD;&#xA;        out vec4 outColor;&#xD;&#xA;        uniform sampler2D tex0;&#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;            outColor = texture(tex0, Texcoord) * vec4(Color, 1.0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;I noticed that the proposed shaders couldn't compile in my computer, since my GLsl version is 1.30, but changing the version declaration into&#xD;&#xA;&#xD;&#xA;    #version 130 core&#xD;&#xA;the ouput of this instruction is `glGetShaderInfoLog(vertexShader, 512, NULL, infoLog)`;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; 0:2(10): error: illegal text following version number&#xD;&#xA;&#xD;&#xA;I wuould like to understand what is wrong in this shader (in version 1.30) or at least where to find enough information to &quot;repair&quot; this situation.&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;**#UPDATE 1**&#xD;&#xA;I managed to have compiling shaders with no errors, but still the program does not work.&#xD;&#xA;&#xD;&#xA;    // Shader sources&#xD;&#xA;    //in --&gt; attribute&#xD;&#xA;    //out --&gt; varying&#xD;&#xA;    const GLchar* vertexSource = R&quot;glsl(&#xD;&#xA;        #version 130&#xD;&#xA;        attribute vec2 position;&#xD;&#xA;        attribute vec3 color;&#xD;&#xA;        attribute vec2 texcoord;&#xD;&#xA;        varying vec3 Color;&#xD;&#xA;        varying vec2 Texcoord;&#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;            Color = color;&#xD;&#xA;            Texcoord = texcoord;&#xD;&#xA;            gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    //in --&gt; varying&#xD;&#xA;    //out --&gt; (delete)&#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 130&#xD;&#xA;        varying vec3 Color;&#xD;&#xA;        varying vec2 Texcoord;&#xD;&#xA;        uniform sampler2D tex0;&#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;           gl_FragColor = texture2D(tex0, Texcoord) * vec4(Color, 1.0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;I used some functions like this to confirm that shaders are successfully compiled and linked&#xD;&#xA;&#xD;&#xA;    int success; char infoLog[512];&#xD;&#xA;    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;success); &#xD;&#xA;    //can also use GL_LINK_STATUS flag&#xD;&#xA;    if(!success)&#xD;&#xA;    {&#xD;&#xA;        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);&#xD;&#xA;        std::cout &lt;&lt; &quot;ERROR::SHADER::VERTEX::COMPILATION_FAILED\n&quot; &lt;&lt; infoLog &lt;&lt; std::endl;&#xD;&#xA;        std::cout &lt;&lt;  glGetString(GL_SHADING_LANGUAGE_VERSION) &lt;&lt; std::endl;&#xD;&#xA;        std::cout &lt;&lt;  success &lt;&lt; std::endl;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://open.gl/textures&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22697" PostHistoryTypeId="2" PostId="8465" RevisionGUID="7aa7e2a4-90e1-44ab-8176-a400c7c9cdfc" CreationDate="2019-01-10T03:11:58.123" UserId="9987" Text="I've read many articles relating to importance sampling of GGX. However, I still feel confused.&#xD;&#xA;&#xD;&#xA;The formula of GGX is :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And many article says we should use this formula to sample:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In the formula, theta is the angle between the normal and the halfvector. So what the formula shows is how to sample a angle between normal and halfvector? But, in the article https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;it says &quot;To importance sample D(ω^m) we will use the inverse of the CDF of D(ω^m) to generate a microfacet normal ω^m. If you are familar with using GGX in game rendering this can be thought of as creating a half vector in tangent space.&quot; How is theta related to microfacet normal? How can I sample a Li based on the theta?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jFUh6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ecrsO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22698" PostHistoryTypeId="1" PostId="8465" RevisionGUID="7aa7e2a4-90e1-44ab-8176-a400c7c9cdfc" CreationDate="2019-01-10T03:11:58.123" UserId="9987" Text="Can't understand the Importance sampling GGX" ContentLicense="CC BY-SA 4.0" />
  <row Id="22699" PostHistoryTypeId="3" PostId="8465" RevisionGUID="7aa7e2a4-90e1-44ab-8176-a400c7c9cdfc" CreationDate="2019-01-10T03:11:58.123" UserId="9987" Text="|pbr|importance-sampling|microfacet|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22700" PostHistoryTypeId="2" PostId="8466" RevisionGUID="220c09d6-76d0-4cb7-81a2-d452ec9395dc" CreationDate="2019-01-10T07:36:57.330" UserId="48" Text="In microfacet BRDFs, the half-vector is the same as the microfacet normal. The half-vector is exactly the required normal for a microfacet to reflect light from the incident ray to the outgoing ray, by the law of reflection. So, for given incident and outgoing directions, only those microfacets whose normals are aligned with the half-vector are &quot;active&quot;.&#xD;&#xA;&#xD;&#xA;Conversely, when importance-sampling a microfacet distribution, we wish to select a random microfacet normal, then reflect the incident ray through this normal to produce the outgoing ray. The incident and outgoing rays will then have the chosen microfacet normal as their half-vector.&#xD;&#xA;&#xD;&#xA;For an isotropic BRDF, you will sample theta from the inverse CDF, and you must also sample phi, the azimuth angle about the normal, uniformly between 0 and 2π; then convert those into a unit vector using the usual spherical coordinates (as mentioned in the linked blog post), combined with a tangent-to-world transformation. For an anisotropic BRDF, both theta and phi would be supplied by sampling an inverse CDF." ContentLicense="CC BY-SA 4.0" />
  <row Id="22701" PostHistoryTypeId="5" PostId="8444" RevisionGUID="435026d6-e49d-4bc7-8652-a98ae0d7c1eb" CreationDate="2019-01-10T10:18:00.630" UserId="6046" Comment="deleted 1 character in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation. The simple code looks like this&#xD;&#xA;&#xD;&#xA;    //Direct Light Sampling&#xD;&#xA;	int j = sampleLights(hit_info, &amp;geometry_term, &amp;light_pdf, &amp;w_i);  //j is the index in light array&#xD;&#xA;	if(j == -1)&#xD;&#xA;		return light_sample;  // black since no ray hits any light source&#xD;&#xA;	&#xD;&#xA;	Ray shadow_ray = {hit_info.hit_point + w_i * RAYBUMP_EPSILON, w_i, INFINITY, true};&#xD;&#xA;	HitInfo shadow_hitinfo;	&#xD;&#xA;	if(!traceRay(&amp;shadow_ray, &amp;shadow_hitinfo) )&#xD;&#xA;	{&#xD;&#xA;        //traceRay returns false which means light source is visible&#xD;&#xA;		mis_weight =  light_pdf;&#xD;&#xA;		brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI; //cosine weighted&#xD;&#xA;		powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);		&#xD;&#xA;		light_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;	&#xD;&#xA;		light_sample *=  mis_weight/light_pdf;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// BRDF Sampling&#xD;&#xA;	Ray brdf_sample_ray;&#xD;&#xA;	sampleHemisphere(&amp;brdf_sample_ray, hit_info);&#xD;&#xA;    if(traceRay(&amp;brdf_sample_ray, &amp;new_hitinfo) &amp;&amp; new_hitinfo.lightID &lt; 0)&#xD;&#xA;	   return light_sample;                //if Light ID &lt; 0, no lights were hit&#xD;&#xA;	&#xD;&#xA;	light_pdf = getLightPdf(new_hitinfo.lightID);&#xD;&#xA;	brdf_pdf = max(dot(w_i, hit_info.normal), 0.0f) * INV_PI;	&#xD;&#xA;    mis_weight = brdf_pdf;&#xD;&#xA;	powerHeuristic(&amp;mis_weight, light_pdf, brdf_pdf, 2);&#xD;&#xA;	&#xD;&#xA;	brdf_sample =  evaluateBRDF(w_i, -ray.dir, hit_info) * light_sources[j].emissive_col * geometry_term;&#xD;&#xA;	brdf_sample *=  mis_weight / brdf_pdf;&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;EDIT:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22706" PostHistoryTypeId="2" PostId="8468" RevisionGUID="69204306-f5df-4e65-a6fa-50f4fc1a10de" CreationDate="2019-01-10T18:05:53.947" UserId="9990" Text="Be careful, using a single frustum for culling only works if the combined field of view of the eyes is less than 180 degrees. There are now VR headsets with a larger field of view around 200 degrees, i.e. the [Pimax 5k+](https://pimaxvr.com/products/pimax-5k-series) and [StarVR](https://www.starvr.com/products/). It's impossible to construct a traditional view frustum or single projection matrix for a field of view over 180 degrees.&#xD;&#xA;&#xD;&#xA;These headsets use angled screens, so the projection planes and the forward vectors in view space are not parallel. The equations from the other answers here assume that they are parallel, and would produce incorrect results when that assumption is wrong.&#xD;&#xA;&#xD;&#xA;A single combined view frustum can still be useful, but your code should be prepared to deal with cases where this can't be constructed to ensure that it's future proof. Alternatively, consider doing culling per eye view, or switch to angle-based culling which can express a larger-than-180-degree FOV." ContentLicense="CC BY-SA 4.0" />
  <row Id="22707" PostHistoryTypeId="2" PostId="8469" RevisionGUID="d4c31562-9ee9-4c4c-8686-0d9b16dfab03" CreationDate="2019-01-11T17:45:40.243" UserId="6046" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So I just thought of comparing the resutls from a Naive Path tracer and one using Next Event Estimation aka Explicit Direct Light Sampling. However the resutls from the Naive PT are very dark.&#xD;&#xA;&#xD;&#xA;Is this expected? The one with next event estimation produces brighter images like in my [previous][2] question which was related to MIS&#xD;&#xA;&#xD;&#xA;I thought that a Naive PT would produce images with the same brightness but more noise and it would take longer to converge. The main reason for dark images is because I'm averaging the colors obtained from the previous run with the next run. On each run I shoot 1 sample per pixel. &#xD;&#xA;&#xD;&#xA;This means if I take 20 samples (20 passes) and only 2 samples ($S_1$ and $S_2$) are useful (hit the light in the end) and 18 return 0 since they don't hit the light, I'd be doing, &#xD;&#xA; &#xD;&#xA;$\displaystyle{\frac{S_1 + S_2 + 0*18}{20}}$&#xD;&#xA;&#xD;&#xA;The brighter colors will surely get averaged out. Moreover they won't converge or in other words they won't get brighter since the number of useless samples surely outweight the number of useuful samples. However in every implementation I could find over the net, people averaged it simply like I did. So is that actually a problem or is it expected?&#xD;&#xA;&#xD;&#xA;I stumbled upon [this][3] question which is pretty much the same thing OP is asking but in the end they find problem with the raytracer and not the path tracer. I don't understand.&#xD;&#xA;&#xD;&#xA;If you guys are interested in the code, [here][4] is my kernel. The main functions to look for are `shading()` which contains the whole bouncing around portion. `EvaluateBRDF` simply evaluates the blinn phong model. The averaging out is done in the main kernel `evaluatePixelRadiance` in the end.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Jyt1Z.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/8444/multiple-importance-sampling-in-path-tracer-produces-dark-images&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/7915/should-direct-illumination-and-path-tracers-render-the-same-scene-equally-bright?rq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/naivept.cl" ContentLicense="CC BY-SA 4.0" />
  <row Id="22708" PostHistoryTypeId="1" PostId="8469" RevisionGUID="d4c31562-9ee9-4c4c-8686-0d9b16dfab03" CreationDate="2019-01-11T17:45:40.243" UserId="6046" Text="Naive Path tracer produces much darker images than Explicit light sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="22709" PostHistoryTypeId="3" PostId="8469" RevisionGUID="d4c31562-9ee9-4c4c-8686-0d9b16dfab03" CreationDate="2019-01-11T17:45:40.243" UserId="6046" Text="|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22710" PostHistoryTypeId="5" PostId="8469" RevisionGUID="47b288f3-0715-4540-ae57-b2d1bc4bfbab" CreationDate="2019-01-11T17:50:44.407" UserId="6046" Comment="deleted 1 character in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So I just thought of comparing the resutls from a Naive Path tracer and one using Next Event Estimation aka Explicit Direct Light Sampling. However the resutls from the Naive PT are very dark.&#xD;&#xA;&#xD;&#xA;Is this expected? The one with next event estimation produces brighter images like in my [previous][2] question which was related to MIS&#xD;&#xA;&#xD;&#xA;I thought that a Naive PT would produce images with the same brightness but more noise and it would take longer to converge. The main reason for dark images is because I'm averaging the colors obtained from the previous run with the next run. On each run I shoot 1 sample per pixel. &#xD;&#xA;&#xD;&#xA;This means if I take 20 samples (20 passes) and only 2 samples ($S_1$ and $S_2$) are useful (hit the light in the end) and 18 return 0 since they don't hit the light, I'd be doing, &#xD;&#xA; &#xD;&#xA;$\displaystyle{\frac{S_1 + S_2 + 0*18}{20}}$&#xD;&#xA;&#xD;&#xA;The brighter colors will surely get averaged out. Moreover they won't converge or in other words they won't get brighter since the number of useless samples surely outweigh the number of useuful samples. However in every implementation I could find over the net, people averaged it simply like I did. So is that actually a problem or is it expected?&#xD;&#xA;&#xD;&#xA;I stumbled upon [this][3] question which is pretty much the same thing OP is asking but in the end they find problem with the raytracer and not the path tracer. I don't understand.&#xD;&#xA;&#xD;&#xA;If you guys are interested in the code, [here][4] is my kernel. The main functions to look for are `shading()` which contains the whole bouncing around portion. `EvaluateBRDF` simply evaluates the blinn phong model. The averaging out is done in the main kernel `evaluatePixelRadiance` in the end.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Jyt1Z.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/8444/multiple-importance-sampling-in-path-tracer-produces-dark-images&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/7915/should-direct-illumination-and-path-tracers-render-the-same-scene-equally-bright?rq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/naivept.cl" ContentLicense="CC BY-SA 4.0" />
  <row Id="22711" PostHistoryTypeId="2" PostId="8470" RevisionGUID="81ef6b9a-4287-48ee-92cd-80ffe944f6d7" CreationDate="2019-01-11T18:33:23.003" UserId="9994" Text="I have a 3D triangular mesh(vertices, indices, uv coords) that I'm rendering to the screen. Let's assume that the UV mapping is one-to-one. I'm trying to find a way to find the 3D position of the point with UV coordinates equal to (0,0). I searched the internet but I only find answers that I don't find convincing. &#xD;&#xA;The solution that I found: &#xD;&#xA;&#xD;&#xA;- Find, in UV space, the triangle that contains (0,0).. let's call it T &#xD;&#xA;- Calculate barycentric coordinates for (0,0) with respect to T &#xD;&#xA;- interpolate the 3D positions of T's vertices using barycentric coords to get the result. &#xD;&#xA;&#xD;&#xA;this seems wrong to me. Here's why: &#xD;&#xA;Let M be the mapping between 3D space and UV space that associates UV coords for every vertex. &#xD;&#xA;Let A,B and C be the vertices of T. &#xD;&#xA;Let P be the origin of UV space ( P = (0,0) ). &#xD;&#xA;&#xD;&#xA;We have P = alpha*A + beta * B + gamma*C (alpha,beta and gamma are the barycentric coords of P with respect to T). &#xD;&#xA;We assumed the UV mapping to be one-to-one, so let M° be the inverse of M. &#xD;&#xA;We have : &#xD;&#xA;&#xD;&#xA;M°(P) = M°(alpha*A + beta * B + gamma*C)&#xD;&#xA;&#xD;&#xA;The solution in question assumes that M° is linear.. if that was the case you can have: &#xD;&#xA;&#xD;&#xA;M°(P) = alpha*M°(A) + beta * M°(B) + gamma*M°(C)&#xD;&#xA;&#xD;&#xA;But that is not the case (correct me if I'm wrong). &#xD;&#xA;&#xD;&#xA;So is there a way to find the 3D position of a point with specific UV coords? &#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="22712" PostHistoryTypeId="1" PostId="8470" RevisionGUID="81ef6b9a-4287-48ee-92cd-80ffe944f6d7" CreationDate="2019-01-11T18:33:23.003" UserId="9994" Text="How to get the 3D position for the point with (0,0) UV coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22713" PostHistoryTypeId="3" PostId="8470" RevisionGUID="81ef6b9a-4287-48ee-92cd-80ffe944f6d7" CreationDate="2019-01-11T18:33:23.003" UserId="9994" Text="|3d|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22714" PostHistoryTypeId="2" PostId="8471" RevisionGUID="b8412384-58e5-42c4-a109-c1230385ec01" CreationDate="2019-01-11T20:04:39.607" UserId="4546" Text="It looks like you're clamping all your samples to 0-1 in line 215. Apply clamping only when displaying the image, not when accumulating samples." ContentLicense="CC BY-SA 4.0" />
  <row Id="22715" PostHistoryTypeId="2" PostId="8472" RevisionGUID="db4103c9-e96c-407a-a1db-1a9f1bd024e7" CreationDate="2019-01-11T20:25:47.640" UserId="9812" Text="$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In general, the $u$ and $v$ coordinates for a point on a triangle with affine coordinates $\lambda_1$ and $\lambda_2$ are&#xD;&#xA;\begin{align}&#xD;&#xA;  u &amp;= u_1 + \lambda_1 (u_2 - u_1) + \lambda_2 (u_3 - u_1) \\&#xD;&#xA;  v &amp;= v_1 + \lambda_1 (v_2 - v_1) + \lambda_2 (v_3 - v_1)&#xD;&#xA;\end{align}&#xD;&#xA;where $u_i$, $v_i$ are the $u$, $v$ coordinates at vertex $i$. We can rewrite this as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  } \cdot \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Knowing $u_i$ and $v_i$ at each vertex of a given triangle, we can compute&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M = \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;We can then find the affine coordinates corresponding to the point with whatever $u$, $v$ coordinates we want:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = &#xD;&#xA;  \mat M^{-1} \cdot \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Note that these affine coordinates always exist as long as $\mat M^{-1}$ exists (which makes sense; there will always be exactly one point somewhere in the plane of the triangle where $u$ and $v$ reach whatever value you may be looking for as long as $u$ and $v$ vary independently). However, they will not necessarily fall inside the triangle.&#xD;&#xA;&#xD;&#xA;So one way to find the point you're looking for would be to iterate over all triangles of the mesh and, for each triangle, compute $\mat M^{-1}$, and $\lambda_1$ and $\lambda_2$ for $u = 0$ and $v = 0$, and check whether&#xD;&#xA;\begin{align}&#xD;&#xA;  \lambda_1 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_2 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_1 + \lambda_2 &amp;\leq 1.&#xD;&#xA;\end{align}&#xD;&#xA;If this is the case, you have found a triangle that contains a point at which $u = 0$ and $v = 0$. You can then compute the coordinates of that point as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec p = \vec v_1 + \lambda_1 \vec v_2 + \lambda_2 \vec v_3&#xD;&#xA;\end{equation}&#xD;&#xA;where $\vec v_1$, $\vec v_2$, and $\vec v_3$ are the coordinates of the respective triangle vertices." ContentLicense="CC BY-SA 4.0" />
  <row Id="22716" PostHistoryTypeId="5" PostId="8472" RevisionGUID="5ddaf225-3041-44e4-8daa-ed66f8008441" CreationDate="2019-01-11T20:34:00.337" UserId="9812" Comment="added 15 characters in body" Text="$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In general, the $u$ and $v$ coordinates at a point on a triangle's plane given by the affine coordinates $\lambda_1$ and $\lambda_2$ are&#xD;&#xA;\begin{align}&#xD;&#xA;  u &amp;= u_1 + \lambda_1 (u_2 - u_1) + \lambda_2 (u_3 - u_1) \\&#xD;&#xA;  v &amp;= v_1 + \lambda_1 (v_2 - v_1) + \lambda_2 (v_3 - v_1)&#xD;&#xA;\end{align}&#xD;&#xA;where $u_i$, $v_i$ are the $u$, $v$ coordinates at vertex $i$. We can rewrite this as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  } \cdot \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Knowing $u_i$ and $v_i$ at each vertex of a given triangle, we can compute&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M = \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;We can then find the affine coordinates corresponding to the point with whatever $u$, $v$ coordinates we want:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = &#xD;&#xA;  \mat M^{-1} \cdot \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Note that these affine coordinates always exist as long as $\mat M^{-1}$ exists (which makes sense; there will always be exactly one point somewhere in the plane of the triangle where $u$ and $v$ reach whatever value you may be looking for as long as $u$ and $v$ vary independently). However, they will not necessarily fall inside the triangle.&#xD;&#xA;&#xD;&#xA;So one way to find the point you're looking for would be to iterate over all triangles of the mesh and, for each triangle, compute $\mat M^{-1}$, and $\lambda_1$ and $\lambda_2$ for $u = 0$ and $v = 0$, and check whether&#xD;&#xA;\begin{align}&#xD;&#xA;  \lambda_1 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_2 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_1 + \lambda_2 &amp;\leq 1.&#xD;&#xA;\end{align}&#xD;&#xA;If this is the case, you have found a triangle that contains a point at which $u = 0$ and $v = 0$. You can then compute the coordinates of that point as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec p = \vec v_1 + \lambda_1 \vec v_2 + \lambda_2 \vec v_3&#xD;&#xA;\end{equation}&#xD;&#xA;where $\vec v_1$, $\vec v_2$, and $\vec v_3$ are the coordinates of the respective triangle vertices." ContentLicense="CC BY-SA 4.0" />
  <row Id="22717" PostHistoryTypeId="5" PostId="8472" RevisionGUID="696d315d-a430-405b-8322-17724c3191c7" CreationDate="2019-01-11T21:08:45.217" UserId="9812" Comment="added 617 characters in body" Text="I realize that the solution I'm giving further below is basically exactly the one you mentioned in your question. So lets begin by addressing this:&#xD;&#xA;&#xD;&#xA;&gt; The solution in question assumes that M° is linear.. if that was the case you can have:&#xD;&#xA;&gt; &#xD;&#xA;&gt; M°(P) = alpha*M°(A) + beta * M°(B) + gamma*M°(C)&#xD;&#xA;&gt; &#xD;&#xA;&gt; But that is not the case (correct me if I'm wrong). &#xD;&#xA;&#xD;&#xA;The solution in question works directly in UV space. I don't see where it would make any assumptions concerning the nature or even existence of a &quot;mapping from 3D to UV space&quot;!? All it does assume is that UV coordinates vary linearly across each triangle (note: each triangle, not the entire mesh)&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In general, the $u$ and $v$ coordinates at a point on a triangle's plane given by the affine coordinates $\lambda_1$ and $\lambda_2$ are&#xD;&#xA;\begin{align}&#xD;&#xA;  u &amp;= u_1 + \lambda_1 (u_2 - u_1) + \lambda_2 (u_3 - u_1) \\&#xD;&#xA;  v &amp;= v_1 + \lambda_1 (v_2 - v_1) + \lambda_2 (v_3 - v_1)&#xD;&#xA;\end{align}&#xD;&#xA;where $u_i$, $v_i$ are the $u$, $v$ coordinates at vertex $i$. We can rewrite this as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  } \cdot \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Knowing $u_i$ and $v_i$ at each vertex of a given triangle, we can compute&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M = \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;We can then find the affine coordinates corresponding to the point with whatever $u$, $v$ coordinates we want:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = &#xD;&#xA;  \mat M^{-1} \cdot \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Note that these affine coordinates always exist as long as $\mat M^{-1}$ exists (which makes sense; there will always be exactly one point somewhere in the plane of the triangle where $u$ and $v$ reach whatever value you may be looking for as long as $u$ and $v$ vary independently). However, they will not necessarily fall inside the triangle.&#xD;&#xA;&#xD;&#xA;So one way to find the point you're looking for would be to iterate over all triangles of the mesh and, for each triangle, compute $\mat M^{-1}$, and $\lambda_1$ and $\lambda_2$ for $u = 0$ and $v = 0$, and check whether&#xD;&#xA;\begin{align}&#xD;&#xA;  \lambda_1 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_2 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_1 + \lambda_2 &amp;\leq 1.&#xD;&#xA;\end{align}&#xD;&#xA;If this is the case, you have found a triangle that contains a point at which $u = 0$ and $v = 0$. You can then compute the coordinates of that point as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec p = \vec v_1 + \lambda_1 \vec v_2 + \lambda_2 \vec v_3&#xD;&#xA;\end{equation}&#xD;&#xA;where $\vec v_1$, $\vec v_2$, and $\vec v_3$ are the coordinates of the respective triangle vertices.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22718" PostHistoryTypeId="5" PostId="8472" RevisionGUID="d185787a-b66f-4032-8f7c-94b84cebd506" CreationDate="2019-01-11T21:14:38.577" UserId="9812" Comment="added 9 characters in body" Text="I realize that the solution I'm giving further below is basically the one you mentioned in your question. So let's begin by addressing this:&#xD;&#xA;&#xD;&#xA;&gt; The solution in question assumes that M° is linear.. if that was the case you can have:&#xD;&#xA;&gt; &#xD;&#xA;&gt; M°(P) = alpha*M°(A) + beta * M°(B) + gamma*M°(C)&#xD;&#xA;&gt; &#xD;&#xA;&gt; But that is not the case (correct me if I'm wrong). &#xD;&#xA;&#xD;&#xA;The solution in question works directly in UV space. I don't see where it would make any assumptions concerning the nature or even existence of a &quot;mapping from 3D to UV space&quot;!? All it does assume is that UV coordinates vary linearly across each triangle (note: each triangle, not the entire mesh)&amp;hellip;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In general, the $u$ and $v$ coordinates at a point on a triangle's plane given by the affine coordinates $\lambda_1$ and $\lambda_2$ are&#xD;&#xA;\begin{align}&#xD;&#xA;  u &amp;= u_1 + \lambda_1 (u_2 - u_1) + \lambda_2 (u_3 - u_1) \\&#xD;&#xA;  v &amp;= v_1 + \lambda_1 (v_2 - v_1) + \lambda_2 (v_3 - v_1)&#xD;&#xA;\end{align}&#xD;&#xA;where $u_i$, $v_i$ are the $u$, $v$ coordinates at vertex $i$. We can rewrite this as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  } \cdot \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Knowing $u_i$ and $v_i$ at each vertex of a given triangle, we can compute&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M = \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;We can then find the affine coordinates corresponding to the point with whatever $u$, $v$ coordinates we want:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = &#xD;&#xA;  \mat M^{-1} \cdot \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Note that these affine coordinates always exist as long as $\mat M^{-1}$ exists (which makes sense; there will always be exactly one point somewhere in the plane of the triangle where $u$ and $v$ reach whatever value you may be looking for as long as $u$ and $v$ vary independently). However, they will not necessarily fall inside the triangle.&#xD;&#xA;&#xD;&#xA;So one way to find the point you're looking for would be to iterate over all triangles of the mesh and, for each triangle, compute $\mat M^{-1}$, and $\lambda_1$ and $\lambda_2$ for $u = 0$ and $v = 0$, and check whether&#xD;&#xA;\begin{align}&#xD;&#xA;  \lambda_1 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_2 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_1 + \lambda_2 &amp;\leq 1.&#xD;&#xA;\end{align}&#xD;&#xA;If this is the case, you have found a triangle that contains a point at which $u = 0$ and $v = 0$. You can then compute the coordinates of that point as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec p = \vec v_1 + \lambda_1 \vec v_2 + \lambda_2 \vec v_3&#xD;&#xA;\end{equation}&#xD;&#xA;where $\vec v_1$, $\vec v_2$, and $\vec v_3$ are the coordinates of the respective triangle vertices.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22719" PostHistoryTypeId="5" PostId="8472" RevisionGUID="8d8fcd3e-637d-4c04-afd8-ce2697e86d93" CreationDate="2019-01-11T21:35:10.153" UserId="9812" Comment="added 247 characters in body" Text="I realize that the solution I'm giving further below is basically the one you mentioned in your question. So let's begin by addressing this:&#xD;&#xA;&#xD;&#xA;&gt; The solution in question assumes that M° is linear.. if that was the case you can have:&#xD;&#xA;&gt; &#xD;&#xA;&gt; M°(P) = alpha*M°(A) + beta * M°(B) + gamma*M°(C)&#xD;&#xA;&gt; &#xD;&#xA;&gt; But that is not the case (correct me if I'm wrong). &#xD;&#xA;&#xD;&#xA;The solution in question works directly in UV space. I don't see where it would make any assumptions concerning the nature or even existence of a &quot;mapping from 3D to UV space&quot;!? All it does assume is that UV coordinates vary linearly across each triangle (note: each triangle, not the entire mesh)&amp;hellip;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In general, the $u$ and $v$ coordinates at a point on a triangle's plane given by the affine coordinates $\lambda_1$ and $\lambda_2$ are&#xD;&#xA;\begin{align}&#xD;&#xA;  u &amp;= u_1 + \lambda_1 (u_2 - u_1) + \lambda_2 (u_3 - u_1) \\&#xD;&#xA;  v &amp;= v_1 + \lambda_1 (v_2 - v_1) + \lambda_2 (v_3 - v_1)&#xD;&#xA;\end{align}&#xD;&#xA;where $u_i$, $v_i$ are the $u$, $v$ coordinates at vertex $i$. We can rewrite this as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  } \cdot \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Knowing $u_i$ and $v_i$ at each vertex of a given triangle, we can compute&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M = \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;We can then find the affine coordinates corresponding to the point with whatever $u$, $v$ coordinates we want:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = &#xD;&#xA;  \mat M^{-1} \cdot \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Note that these affine coordinates always exist as long as $\mat M^{-1}$ exists (which makes sense; there will always be exactly one point somewhere in the plane of the triangle where $u$ and $v$ reach whatever value you may be looking for as long as $u$ and $v$ vary independently). However, they will not necessarily fall inside the triangle.&#xD;&#xA;&#xD;&#xA;So one way to find the point you're looking for would be to iterate over all triangles of the mesh and, for each triangle, compute $\mat M^{-1}$, and $\lambda_1$ and $\lambda_2$ for $u = 0$ and $v = 0$, and check whether&#xD;&#xA;\begin{align}&#xD;&#xA;  \lambda_1 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_2 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_1 + \lambda_2 &amp;\leq 1.&#xD;&#xA;\end{align}&#xD;&#xA;If this is the case, you have found a triangle that contains a point at which $u = 0$ and $v = 0$. You can then compute the coordinates of that point as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec p = \vec v_1 + \lambda_1 \vec v_2 + \lambda_2 \vec v_3&#xD;&#xA;\end{equation}&#xD;&#xA;where $\vec v_1$, $\vec v_2$, and $\vec v_3$ are the coordinates of the respective triangle vertices.&#xD;&#xA;&#xD;&#xA;It may make sense to, for example, use an initial check against a given triangle's bounding rectangle in UV space and/or other methods to quickly rule out triangles that cannot contain the coordinates of interest to speed up the search&amp;hellip;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22722" PostHistoryTypeId="5" PostId="8469" RevisionGUID="317010ea-e226-48e7-8aff-c4a3770678e5" CreationDate="2019-01-13T09:51:55.827" UserId="231" Comment="Typos" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So I just thought of comparing the results from a Naive Path tracer and one using Next Event Estimation aka Explicit Direct Light Sampling. However the results from the Naive PT are very dark.&#xD;&#xA;&#xD;&#xA;Is this expected? The one with next event estimation produces brighter images like in my [previous][2] question which was related to MIS&#xD;&#xA;&#xD;&#xA;I thought that a Naive PT would produce images with the same brightness but more noise and it would take longer to converge. The main reason for dark images is because I'm averaging the colors obtained from the previous run with the next run. On each run I shoot 1 sample per pixel. &#xD;&#xA;&#xD;&#xA;This means if I take 20 samples (20 passes) and only 2 samples ($S_1$ and $S_2$) are useful (hit the light in the end) and 18 return 0 since they don't hit the light, I'd be doing, &#xD;&#xA; &#xD;&#xA;$\displaystyle{\frac{S_1 + S_2 + 0*18}{20}}$&#xD;&#xA;&#xD;&#xA;The brighter colors will surely get averaged out. Moreover they won't converge or in other words they won't get brighter since the number of useless samples surely outweigh the number of useful samples. However in every implementation I could find over the net, people averaged it simply like I did. So is that actually a problem or is it expected?&#xD;&#xA;&#xD;&#xA;I stumbled upon [this][3] question which is pretty much the same thing OP is asking but in the end they find problem with the raytracer and not the path tracer. I don't understand.&#xD;&#xA;&#xD;&#xA;If you guys are interested in the code, [here][4] is my kernel. The main functions to look for are `shading()` which contains the whole bouncing around portion. `EvaluateBRDF` simply evaluates the blinn phong model. The averaging out is done in the main kernel `evaluatePixelRadiance` in the end.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Jyt1Z.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/8444/multiple-importance-sampling-in-path-tracer-produces-dark-images&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/7915/should-direct-illumination-and-path-tracers-render-the-same-scene-equally-bright?rq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/naivept.cl" ContentLicense="CC BY-SA 4.0" />
  <row Id="22723" PostHistoryTypeId="5" PostId="8469" RevisionGUID="19fd6179-3194-40ba-a006-760d6ea0e30a" CreationDate="2019-01-13T12:07:40.103" UserId="6046" Comment="added 375 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So I just thought of comparing the results from a Naive Path tracer and one using Next Event Estimation aka Explicit Direct Light Sampling. However the results from the Naive PT are very dark.&#xD;&#xA;&#xD;&#xA;Is this expected? The one with next event estimation produces brighter images like in my [previous][2] question which was related to MIS&#xD;&#xA;&#xD;&#xA;I thought that a Naive PT would produce images with the same brightness but more noise and it would take longer to converge. The main reason for dark images is because I'm averaging the colors obtained from the previous run with the next run. On each run I shoot 1 sample per pixel. &#xD;&#xA;&#xD;&#xA;This means if I take 20 samples (20 passes) and only 2 samples ($S_1$ and $S_2$) are useful (hit the light in the end) and 18 return 0 since they don't hit the light, I'd be doing, &#xD;&#xA; &#xD;&#xA;$\displaystyle{\frac{S_1 + S_2 + 0*18}{20}}$&#xD;&#xA;&#xD;&#xA;The brighter colors will surely get averaged out. Moreover they won't converge or in other words they won't get brighter since the number of useless samples surely outweigh the number of useful samples. However in every implementation I could find over the net, people averaged it simply like I did. So is that actually a problem or is it expected?&#xD;&#xA;&#xD;&#xA;I stumbled upon [this][3] question which is pretty much the same thing OP is asking but in the end they find problem with the raytracer and not the path tracer. I don't understand.&#xD;&#xA;&#xD;&#xA;If you guys are interested in the code, [here][4] is my kernel. The main functions to look for are `shading()` which contains the whole bouncing around portion. `EvaluateBRDF` simply evaluates the blinn phong model. The averaging out is done in the main kernel `evaluatePixelRadiance` in the end.&#xD;&#xA;&#xD;&#xA;UPDATE:- So I corrected what Stefan pointed out and removed color clamping. I was using an 8bit depth default framebuffer and RBO of 32 bit floating points. So I guess the data gets clamped automatically when blitting to the default framebuffer. And it seems to have solved the issue. I'll update the results shortly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Jyt1Z.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/8444/multiple-importance-sampling-in-path-tracer-produces-dark-images&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/7915/should-direct-illumination-and-path-tracers-render-the-same-scene-equally-bright?rq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/naivept.cl" ContentLicense="CC BY-SA 4.0" />
  <row Id="22724" PostHistoryTypeId="5" PostId="8469" RevisionGUID="f6ee953a-4c70-49a4-8e47-d499b80948c3" CreationDate="2019-01-13T13:11:50.303" UserId="6046" Comment="added 346 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So I just thought of comparing the results from a Naive Path tracer and one using Next Event Estimation aka Explicit Direct Light Sampling. However the results from the Naive PT are very dark.&#xD;&#xA;&#xD;&#xA;Is this expected? The one with next event estimation produces brighter images like in my [previous][2] question which was related to MIS&#xD;&#xA;&#xD;&#xA;I thought that a Naive PT would produce images with the same brightness but more noise and it would take longer to converge. The main reason for dark images I think is because I'm averaging the colors obtained from the previous run with the next run. On each run I shoot 1 sample per pixel. &#xD;&#xA;&#xD;&#xA;This means if I take 20 samples (20 passes) and only 2 samples ($S_1$ and $S_2$) are useful (hit the light in the end) and 18 return 0 since they don't hit the light, I'd be doing, &#xD;&#xA; &#xD;&#xA;$\displaystyle{\frac{S_1 + S_2 + 0*18}{20}}$&#xD;&#xA;&#xD;&#xA;The brighter colors will surely get averaged out. Moreover they won't converge or in other words they won't get brighter since the number of useless samples surely outweigh the number of useful samples. However in every implementation I could find over the net, people averaged it simply like I did. So is that actually a problem or is it expected?&#xD;&#xA;&#xD;&#xA;I stumbled upon [this][3] question which is pretty much the same thing OP is asking but in the end they find problem with the raytracer and not the path tracer. I don't understand.&#xD;&#xA;&#xD;&#xA;If you guys are interested in the code, [here][4] is my kernel. The main functions to look for are `shading()` which contains the whole bouncing around portion. `EvaluateBRDF` simply evaluates the blinn phong model. The averaging out is done in the main kernel `evaluatePixelRadiance` in the end.&#xD;&#xA;&#xD;&#xA;UPDATE:- So I corrected what Stefan pointed out and removed color clamping. I was using an 8bit depth default framebuffer and RBO of 32 bit floating points. So I guess the data gets clamped automatically when blitting to the default framebuffer. And it seems to have solved the issue. I'll update the results shortly.&#xD;&#xA;&#xD;&#xA;I think this solved my MIS issue as well, will share results on MIS post soon. Here is the one for naive-PT, 5000 samples in around 10 seconds. And it seems I was not getting fireflies since i was clamping radiance as expected. Good to learn new things :)&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Jyt1Z.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/8444/multiple-importance-sampling-in-path-tracer-produces-dark-images&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/7915/should-direct-illumination-and-path-tracers-render-the-same-scene-equally-bright?rq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/naivept.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/HVXUg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22725" PostHistoryTypeId="2" PostId="8473" RevisionGUID="69eea100-297d-40b0-a2cd-3339476f93be" CreationDate="2019-01-13T14:22:06.560" UserId="2041" Text="Michael Kenzel's answer gives a good general algorithm, but here's a &quot;20% of the effort, 80% of the value&quot; answer. Because $(u,v) \in [0,1]$ space is a square being filled with convex polygons, $(0,0)$ can only be mapped in one of two conditions:&#xD;&#xA;&#xD;&#xA;1. $(0,0)$ is at a vertex; or&#xD;&#xA;2. Some vertices have negative co-ordinates.&#xD;&#xA;&#xD;&#xA;Generally 2 is avoided when unwrapping your mesh unless you're using a texture in wrapped mode, which is quite unusual because it makes the seams on your mesh look bad. It's also ruled out by the condition in your question that &quot;the UV mapping is one-to-one&quot;. So most of the time, if $(0,0)$ is present at all, it's at a vertex. That makes your algorithm very simple: just look through your vertices until you find one with those exact texture co-ordinates, and then read out the object-space position of that vertex.&#xD;&#xA;&#xD;&#xA;It's actually more common for $(0,0)$ to not be present at all, (a) because you need to take special care with texture filtering when going up to the edge of the texture, and (b) unwrapping a shape into a mesh doesn't usually give you a convenient corner to place there. [The examples on this Google Image search](https://www.google.com/search?q=uv+unwrap&amp;tbm=isch) are a good illustration: of a few dozen examples on the first few pages, I only found a couple of UV maps where the net touched any of the corners." ContentLicense="CC BY-SA 4.0" />
  <row Id="22726" PostHistoryTypeId="6" PostId="5447" RevisionGUID="7e43eb7d-5fa8-4103-8997-52cfa007544b" CreationDate="2019-01-13T15:04:09.617" UserId="5778" Comment="tags edited" Text="|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22727" PostHistoryTypeId="24" PostId="5447" RevisionGUID="7e43eb7d-5fa8-4103-8997-52cfa007544b" CreationDate="2019-01-13T15:04:09.617" Comment="Proposed by 5778 approved by 231 edit id of 453" ContentLicense="CC BY-SA 4.0" />
  <row Id="22728" PostHistoryTypeId="5" PostId="8472" RevisionGUID="9846b4a9-847a-42b6-bbf7-8050fa77c924" CreationDate="2019-01-13T21:49:36.183" UserId="9812" Comment="added 28 characters in body" Text="I realize that the solution I'm giving further below is basically the one you mentioned in your question. So let's begin by addressing this:&#xD;&#xA;&#xD;&#xA;&gt; The solution in question assumes that M° is linear.. if that was the case you can have:&#xD;&#xA;&gt; &#xD;&#xA;&gt; M°(P) = alpha*M°(A) + beta * M°(B) + gamma*M°(C)&#xD;&#xA;&gt; &#xD;&#xA;&gt; But that is not the case (correct me if I'm wrong). &#xD;&#xA;&#xD;&#xA;The solution in question works directly in UV space. I don't see where it would make any assumptions concerning the nature or even existence of a &quot;mapping from 3D to UV space&quot;!? All it does assume is that UV coordinates vary linearly across each triangle (note: each triangle, not the entire mesh)&amp;hellip;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In general, the $u$ and $v$ coordinates at a point on a triangle's plane given by the affine coordinates $\lambda_1$ and $\lambda_2$ are&#xD;&#xA;\begin{align}&#xD;&#xA;  u &amp;= u_1 + \lambda_1 (u_2 - u_1) + \lambda_2 (u_3 - u_1) \\&#xD;&#xA;  v &amp;= v_1 + \lambda_1 (v_2 - v_1) + \lambda_2 (v_3 - v_1)&#xD;&#xA;\end{align}&#xD;&#xA;where $u_i$, $v_i$ are the $u$, $v$ coordinates at vertex $i$. We can rewrite this as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  } \cdot \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Knowing $u_i$ and $v_i$ at each vertex of a given triangle, we can compute&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M = \mmat{&#xD;&#xA;    u_2 - u_1 &amp; u_3 - u_1 \\&#xD;&#xA;    v_2 - v_1 &amp; v_3 - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;We can then find the affine coordinates corresponding to the point with whatever $u$, $v$ coordinates we want:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mvec{&#xD;&#xA;    \lambda_1 \\&#xD;&#xA;    \lambda_2&#xD;&#xA;  } = &#xD;&#xA;  \mat M^{-1} \cdot \mvec{&#xD;&#xA;    u - u_1 \\&#xD;&#xA;    v - v_1&#xD;&#xA;  }.&#xD;&#xA;\end{equation}&#xD;&#xA;Note that these affine coordinates always exist as long as $\mat M^{-1}$ exists (which makes sense; there will always be exactly one point somewhere in the plane of the triangle where $u$ and $v$ reach whatever value you may be looking for as long as $u$ and $v$ vary independently). However, they will not necessarily fall inside the triangle.&#xD;&#xA;&#xD;&#xA;So one way to find the point you're looking for would be to iterate over all triangles of the mesh and, for each triangle, compute $\mat M^{-1}$, and $\lambda_1$ and $\lambda_2$ for $u = 0$ and $v = 0$, and check whether&#xD;&#xA;\begin{align}&#xD;&#xA;  \lambda_1 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_2 &amp;\geq 0 &amp; &amp;\land &amp; \lambda_1 + \lambda_2 &amp;\leq 1.&#xD;&#xA;\end{align}&#xD;&#xA;If this is the case, you have found a triangle that contains a point at which $u = 0$ and $v = 0$. You can then compute the coordinates of that point as&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec p = (1 - \lambda_1 - \lambda_2) \vec v_1 + \lambda_1 \vec v_2 + \lambda_2 \vec v_3&#xD;&#xA;\end{equation}&#xD;&#xA;where $\vec v_1$, $\vec v_2$, and $\vec v_3$ are the coordinates of the respective triangle vertices.&#xD;&#xA;&#xD;&#xA;It may make sense to, for example, use an initial check against a given triangle's bounding rectangle in UV space and/or other methods to quickly rule out triangles that cannot contain the coordinates of interest to speed up the search&amp;hellip;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22729" PostHistoryTypeId="5" PostId="8454" RevisionGUID="f79ffeeb-5cf2-44e3-8cd3-006f66b4287f" CreationDate="2019-01-14T08:34:53.210" UserId="9812" Comment="added 1247 characters in body" Text="Since the transformation that is asked for includes a translation (the camera is located at a position other than the origin), you will indeed have to use homogeneous coordinates to describe this transformation in matrix form.&#xD;&#xA;&#xD;&#xA;There are basically two ways to get to the matrix you're looking for. You can either set up the matrix that would transform from camera coordinates to world-space and then take the inverse of that, or you can build the matrix directly. The first approach is what is typically done and what the exercise seems to be aiming for since it explicitly asks for the base vectors of the camera system as seen from world-space, which is the first step in that process. The advantage of this approach is that it is arguably a bit more intuitive since what you're essentially doing is treat the camera as just another object that you place in world-space by setting up a matrix. Just that once you have that matrix, you invert it because you didn't actually want to get from camera-local coordinates to world coordinates but rather the other way around. I'll explain both approaches below using the concrete example given in your exercise. At least for now, I'll leave the generalization of the ideas presented below as an exercise to the reader (so that at least some of the fun remains for you ).&#xD;&#xA;&#xD;&#xA;Let's look at a sketch of the whole situation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/NnAhM.png&quot; width=&quot;320&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Your camera is located at $\vec o = \mvec{3 &amp; 3 &amp; 0}^T$ and is supposed to be looking at the origin. By general convention, the camera is set up to be looking along the line of the z-axis of its local coordinate frame, while the local x-axis points right and the local y-axis points up. Therefore, we know that $\vec e_3$ should be pointing either at or away from the origin. Since you're talking about OpenGL, I assumed right-handed world and camera coordinate systems as is typically done in OpenGL-land. To get a right-handed coordinate frame where the local x points to the right, local y points up, and local z lines up with the viewing direction, $\vec e_3$ can only to be pointing in the direction away from the point at which the camera is looking. Once we have fixed $\vec e_3$, we have to define the remaining two base vectors. Note that no matter what we choose for $\vec e_1$ and $\vec e_2$, our camera will be looking at the origin. Our choice of $\vec e_1$ and $\vec e_2$ basically just fixes the rotation of the camera around the viewing direction, which is set by $\vec e_3$. Generally, one choses $e_1$ such that it is orthogonal to both, $\vec e_3$, and a general &quot;up&quot; direction. $\vec e_2$ is then simply computed to be orthogonal to both, $\vec e_1$ and $\vec e_3$.&#xD;&#xA;&#xD;&#xA;## Approach 1&#xD;&#xA;&#xD;&#xA;From the above sketch, is it immediately apparent that the coordinates of $\vec e_3$ have to be&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_3 = \frac{1}{\sqrt{3^2 + 3^2 + 0}} \mvec{3 \\ 3 \\ 0} = \frac{1}{\sqrt{2\cdot3^2}} \mvec{3 \\ 3 \\ 0} = \mvec{\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since our camera is located in the x-y-plane in this example, the base vector $\vec e_2$ is just $\vec e_3$ rotated by $90°$:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_2 = \mvec{-\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0},&#xD;&#xA;\end{equation}&#xD;&#xA;and $\vec e_1$ just points in the direction opposite of the world-space z-axis:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_1 = \mvec{0 \\ 0 \\ -1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Using the world-space base vectors of the camera frame, we can write down a matrix that transforms from camera-space to world-space. The camera matrix that transforms from camera to world coordinates is then simply the inverse of that matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mmat{\vec e_1 &amp; \vec e_2 &amp; \vec e_3 &amp; \vec o \\ 0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;         = \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since the camera frame has an [orthonormal base][1] just offset by $\vec o$, this matrix is composed of just the rotation defined by the orthonormal base vectors followed by a translation:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mat T \mat R&#xD;&#xA;\end{equation}&#xD;&#xA;where&#xD;&#xA;\begin{align}&#xD;&#xA;  \mat R &amp;= \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} &amp; &#xD;&#xA;  \mat T &amp;= \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{align}&#xD;&#xA;You can convince yourself that this is true by simply performing the multiplication. Knowing this, we can compute the camera matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam} = (\mat T \mat R)^{-1} = \mat R^{-1} \mat T^{-1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since $\mat R$ is composed of orthonormal base vectors, it is an orthogonal matrix, which means that its inverse is just its transpose. $\mat T$ is just a translation, its inverse is a translation in the opposite direction. Therefore,&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \cdot \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \\&#xD;&#xA;    &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;  \end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Approach 2&#xD;&#xA;&#xD;&#xA;An alternative to the approach above is to just directly compute the coordinates of the world-space base vectors as seen from the perspective of the camera. Given these coordinates, we can, again, just write down a matrix that applies the corresponding transformation from world to camera space.&#xD;&#xA;&#xD;&#xA;Looking at the figure again, we see that the coordinates of the world-space x-axis as seen from camera space are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec x' = \mvec{0 \\ -\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}}.&#xD;&#xA;\end{equation}&#xD;&#xA;Analogously, we find the camera-space coordinates of the world-space y- and z-axes:&#xD;&#xA;\begin{align}&#xD;&#xA;  \vec y' &amp;= \mvec{0 \\ \frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}} &amp; &#xD;&#xA;  \vec z' &amp;= \mvec{-1 \\ 0 \\ 0}.&#xD;&#xA;\end{align}&#xD;&#xA;Also looking at the figure, we note that the world-space origin as seen from the camera is simply located at a distance of $\sqrt{3^2 + 3^2} = 3\sqrt{2}$ units along the negative $\vec e_3$ axis. Therefore, the camera-space coordinates of the world origin are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec o' = \mvec{0 \\ 0 \\ -3\sqrt{2}}.&#xD;&#xA;\end{equation} and we can, once again, write down the matrix&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;  \end{split},&#xD;&#xA;\end{equation}&#xD;&#xA;and sleep well tonight because both ways did indeed lead to the same result…&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orthonormality" ContentLicense="CC BY-SA 4.0" />
  <row Id="22730" PostHistoryTypeId="5" PostId="8454" RevisionGUID="16d4a28e-cb40-46eb-a044-5bdc4d69af86" CreationDate="2019-01-14T08:57:39.057" UserId="9812" Comment="edited body" Text="Since the transformation that is asked for includes a translation (the camera is located at a position other than the origin), you will indeed have to use homogeneous coordinates to describe this transformation in matrix form.&#xD;&#xA;&#xD;&#xA;There are basically two ways to get to the matrix you're looking for. You can either set up the matrix that would transform from camera coordinates to world-space and then take the inverse of that, or you can build the matrix directly. The first approach is what is typically done and what the exercise seems to be aiming for since it explicitly asks for the base vectors of the camera system as seen from world-space, which is the first step in that process. The advantage of this approach is that it is arguably a bit more intuitive since what you're essentially doing is treat the camera as just another object that you place in world-space by setting up a matrix. Just that once you have that matrix, you invert it because you didn't actually want to get from camera-local coordinates to world coordinates but rather the other way around. I'll explain both approaches below using the concrete example given in your exercise. At least for now, I'll leave the generalization of the ideas presented below as an exercise to the reader (so that at least some of the fun remains for you ).&#xD;&#xA;&#xD;&#xA;Let's look at a sketch of the whole situation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\def\mvec#1{\begin{pmatrix}#1\end{pmatrix}}&#xD;&#xA;\def\ivec#1{\left(\begin{smallmatrix}#1\end{smallmatrix}\right)}&#xD;&#xA;\def\mmat#1{\begin{bmatrix}#1\end{bmatrix}}&#xD;&#xA;\def\vec#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;\def\mat#1{\mathrm{\mathbf{#1}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/NnAhM.png&quot; width=&quot;320&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Your camera is located at $\vec o = \mvec{3 &amp; 3 &amp; 0}^T$ and is supposed to be looking at the origin. By general convention, the camera is set up to be looking along the line of the z-axis of its local coordinate frame, while the local x-axis points right and the local y-axis points up. Therefore, we know that $\vec e_3$ should be pointing either at or away from the origin. Since you're talking about OpenGL, I assumed right-handed world and camera coordinate systems as is typically done in OpenGL-land. To get a right-handed coordinate frame where the local x points to the right, local y points up, and local z lines up with the viewing direction, $\vec e_3$ can only to be pointing in the direction away from the point at which the camera is looking. Once we have fixed $\vec e_3$, we have to define the remaining two base vectors. Note that no matter what we choose for $\vec e_1$ and $\vec e_2$, our camera will be looking at the origin. Our choice of $\vec e_1$ and $\vec e_2$ basically just fixes the rotation of the camera around the viewing direction, which is set by $\vec e_3$. Generally, one choses $\vec e_1$ such that it is orthogonal to both, $\vec e_3$, and a general &quot;up&quot; direction. $\vec e_2$ is then simply computed to be orthogonal to both, $\vec e_1$ and $\vec e_3$.&#xD;&#xA;&#xD;&#xA;## Approach 1&#xD;&#xA;&#xD;&#xA;From the above sketch, it is immediately apparent that the coordinates of $\vec e_3$ have to be&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_3 = \frac{1}{\sqrt{3^2 + 3^2 + 0}} \mvec{3 \\ 3 \\ 0} = \frac{1}{\sqrt{2\cdot3^2}} \mvec{3 \\ 3 \\ 0} = \mvec{\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since our camera is located in the x-y-plane in this example, the base vector $\vec e_2$ is just $\vec e_3$ rotated by $90°$:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_2 = \mvec{-\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2} \\ 0},&#xD;&#xA;\end{equation}&#xD;&#xA;and $\vec e_1$ just points in the direction opposite of the world-space z-axis:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec e_1 = \mvec{0 \\ 0 \\ -1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Using the world-space base vectors of the camera frame, we can write down a matrix that transforms from camera-space to world-space. The camera matrix that transforms from camera to world coordinates is then simply the inverse of that matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mmat{\vec e_1 &amp; \vec e_2 &amp; \vec e_3 &amp; \vec o \\ 0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;         = \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 3 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since the camera frame has an [orthonormal base][1] just offset by $\vec o$, this matrix is composed of just the rotation defined by the orthonormal base vectors followed by a translation:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam}^{-1} = \mat T \mat R&#xD;&#xA;\end{equation}&#xD;&#xA;where&#xD;&#xA;\begin{align}&#xD;&#xA;  \mat R &amp;= \mmat{&#xD;&#xA;    0 &amp; -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    0 &amp; \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 \\&#xD;&#xA;    -1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} &amp; &#xD;&#xA;  \mat T &amp;= \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; 3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;\end{align}&#xD;&#xA;You can convince yourself that this is true by simply performing the multiplication. Knowing this, we can compute the camera matrix:&#xD;&#xA;\begin{equation}&#xD;&#xA;  \mat M_{cam} = (\mat T \mat R)^{-1} = \mat R^{-1} \mat T^{-1}.&#xD;&#xA;\end{equation}&#xD;&#xA;Since $\mat R$ is composed of orthonormal base vectors, it is an orthogonal matrix, which means that its inverse is just its transpose. $\mat T$ is just a translation, its inverse is a translation in the opposite direction. Therefore,&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \cdot \mmat{&#xD;&#xA;    1 &amp; 0 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 &amp; -3 \\&#xD;&#xA;    0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1} \\&#xD;&#xA;    &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}.&#xD;&#xA;  \end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Approach 2&#xD;&#xA;&#xD;&#xA;An alternative to the approach above is to just directly compute the coordinates of the world-space base vectors as seen from the perspective of the camera. Given these coordinates, we can, again, just write down a matrix that applies the corresponding transformation from world to camera space.&#xD;&#xA;&#xD;&#xA;Looking at the figure again, we see that the coordinates of the world-space x-axis as seen from camera space are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec x' = \mvec{0 \\ -\frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}}.&#xD;&#xA;\end{equation}&#xD;&#xA;Analogously, we find the camera-space coordinates of the world-space y- and z-axes:&#xD;&#xA;\begin{align}&#xD;&#xA;  \vec y' &amp;= \mvec{0 \\ \frac{1}{\sqrt2} \\ \frac{1}{\sqrt2}} &amp; &#xD;&#xA;  \vec z' &amp;= \mvec{-1 \\ 0 \\ 0}.&#xD;&#xA;\end{align}&#xD;&#xA;Also looking at the figure, we note that the world-space origin as seen from the camera is simply located at a distance of $\sqrt{3^2 + 3^2} = 3\sqrt{2}$ units along the negative $\vec e_3$ axis. Therefore, the camera-space coordinates of the world origin are&#xD;&#xA;\begin{equation}&#xD;&#xA;  \vec o' = \mvec{0 \\ 0 \\ -3\sqrt{2}}.&#xD;&#xA;\end{equation} and we can, once again, write down the matrix&#xD;&#xA;\begin{equation}&#xD;&#xA;  \begin{split}&#xD;&#xA;  \mat M_{cam} &amp;= \mmat{&#xD;&#xA;    0 &amp; 0 &amp; -1 &amp; 0 \\&#xD;&#xA;    -\frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; 0 \\&#xD;&#xA;    \frac{1}{\sqrt2} &amp; \frac{1}{\sqrt2} &amp; 0 &amp; -3\sqrt2 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1}&#xD;&#xA;  \end{split},&#xD;&#xA;\end{equation}&#xD;&#xA;and sleep well tonight because both ways did indeed lead to the same result…&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Orthonormality" ContentLicense="CC BY-SA 4.0" />
  <row Id="22731" PostHistoryTypeId="2" PostId="8474" RevisionGUID="0f6616aa-3985-4a92-b029-49e4f6b70487" CreationDate="2019-01-14T08:59:49.830" UserId="10006" Text="For the purpose of mapping caves, we survey new passages so that we take main polygon (survey from point A to point B) and on each &quot;node&quot; (survey station A in example), we shoot multiple &quot;splay shots&quot; around the passage (in more or less random directions), so we obtain more information which can later be used to draw a map of the cave.&#xD;&#xA;&#xD;&#xA;Doing this, we get a polygon with a &quot;cloud&quot; of points around the main line. My question is, whether is there a way to create a convex hull around this main line, using those &quot;splay shots&quot;. This would be a great way to visualize cave passages.&#xD;&#xA;&#xD;&#xA;Each survey leg has information about direction, inclination and length, with which we are able to get the 3d coordinate in space of each node." ContentLicense="CC BY-SA 4.0" />
  <row Id="22732" PostHistoryTypeId="1" PostId="8474" RevisionGUID="0f6616aa-3985-4a92-b029-49e4f6b70487" CreationDate="2019-01-14T08:59:49.830" UserId="10006" Text="Convex hull around polygon for cave mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="22733" PostHistoryTypeId="3" PostId="8474" RevisionGUID="0f6616aa-3985-4a92-b029-49e4f6b70487" CreationDate="2019-01-14T08:59:49.830" UserId="10006" Text="|3d|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22734" PostHistoryTypeId="5" PostId="8444" RevisionGUID="98f40e12-9288-4bdc-a746-b089a31fed58" CreationDate="2019-01-14T09:08:54.510" UserId="6046" Comment="deleted 404 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS however now I'm getting more fireflies and I think I read that MIS reduces fireflies?. Anyways, I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Both images are at 1500spp. Darker one is with MIS.&#xD;&#xA;&#xD;&#xA;Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;[![With MIS][5]][5]&#xD;&#xA;&#xD;&#xA;[![Without MIS][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/QUY6H.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4suBT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22735" PostHistoryTypeId="5" PostId="8444" RevisionGUID="065e6f09-d038-4b97-a908-3f60dfbbd703" CreationDate="2019-01-14T09:46:23.067" UserId="6046" Comment="added 364 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS however now I'm getting more fireflies and I think I read that MIS reduces fireflies?. Anyways, I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`.&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter but the fireflies still remain. Note the reflection is harder to converge although its 2500spp while the one below is 1500 spp.&#xD;&#xA;&#xD;&#xA;Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;[![with MIS ][5]][5]&#xD;&#xA;[![Without MIS][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Helion-Render/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/GYYP1.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/4suBT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22739" PostHistoryTypeId="6" PostId="5408" RevisionGUID="30a1f9ba-1e4a-43c6-bde0-2338b768adb8" CreationDate="2019-01-14T22:30:32.987" UserId="5778" Comment="tags edited" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22740" PostHistoryTypeId="24" PostId="5408" RevisionGUID="30a1f9ba-1e4a-43c6-bde0-2338b768adb8" CreationDate="2019-01-14T22:30:32.987" Comment="Proposed by 5778 approved by 209, 231 edit id of 454" ContentLicense="CC BY-SA 4.0" />
  <row Id="22760" PostHistoryTypeId="2" PostId="8479" RevisionGUID="c38b4bff-51b5-486f-817c-a3e7b66b4d36" CreationDate="2019-01-16T18:08:30.683" UserId="9881" Text="In [ray-tracing][1] technique critical point is to calculate rays which came out from eye $E$ to target $T$ through pixel $P_{ij}$ on viewport. The &quot;viewport&quot; is represented as rectangle divided to square pixels - this rectangle is perpendicular to line which go through points $E$, $C$ (viewport center) and $T$. The ray (red line on image) is represented by point $E$ and unit  vector $r_{ij}$ (not shown in picture but it lay on red line) - below is picture which show &quot;geometry&quot; - but what are the formulas to calculate $r_{ij}$? &#xD;&#xA;&#xD;&#xA;The given input values are: &#xD;&#xA;&#xD;&#xA;* eye position $E$, &#xD;&#xA;* target position $T$, &#xD;&#xA;* field of view $\theta$ (angle, for human eye $\approx 90^\circ$), &#xD;&#xA;* number of square pixels $k$ (horizontal direction) and $m$ (vertical direction). &#xD;&#xA;* we also know vertical $w$ vector usually equal to $w=[wx,wy,wz]=[0,1,0]$ (not shown on picture) which indicate where is up and where is down &#xD;&#xA;&#xD;&#xA;The orthogonal vectors $v$ and $b$  (and $t$) on picture are determined by $w$ and $t=T-E$ and maybe will useful in $r_{ij}$ calculations. The $d$ and pixel size is arbitrary and don't change the result because of fixed $\theta$. &#xD;&#xA;&#xD;&#xA;**Question**: How to calculate unit vector $r_{ij}$ knowing input values described above?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&#xD;&#xA;  [2]: https://i.stack.imgur.com/PKrBi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22761" PostHistoryTypeId="1" PostId="8479" RevisionGUID="c38b4bff-51b5-486f-817c-a3e7b66b4d36" CreationDate="2019-01-16T18:08:30.683" UserId="9881" Text="How to calculate ray" ContentLicense="CC BY-SA 4.0" />
  <row Id="22762" PostHistoryTypeId="3" PostId="8479" RevisionGUID="c38b4bff-51b5-486f-817c-a3e7b66b4d36" CreationDate="2019-01-16T18:08:30.683" UserId="9881" Text="|raytracing|mathematics|linear-algebra|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22768" PostHistoryTypeId="2" PostId="8481" RevisionGUID="1c331405-c43d-461c-a5cb-ac0c8b438ef1" CreationDate="2019-01-16T22:41:59.697" UserId="10022" Text="I'm currently trying to understand how works perspective correction texture mapping. I saw that actually it works by interpolating the z value of the three point of the triangle which the current rendered pixel is in, then, it divide the u and v affine texture coordinates by the interpolated z value in order to get the perspective corrected values of u and v.&#xD;&#xA;I really can't wrap my head around this division by z to do perspective correction. Can someone explain me the point and the math behind it which makes it do the job ?&#xD;&#xA;&#xD;&#xA;Thanks guys !" ContentLicense="CC BY-SA 4.0" />
  <row Id="22769" PostHistoryTypeId="1" PostId="8481" RevisionGUID="1c331405-c43d-461c-a5cb-ac0c8b438ef1" CreationDate="2019-01-16T22:41:59.697" UserId="10022" Text="Why do perspective correction based texture mapping do depth division" ContentLicense="CC BY-SA 4.0" />
  <row Id="22770" PostHistoryTypeId="3" PostId="8481" RevisionGUID="1c331405-c43d-461c-a5cb-ac0c8b438ef1" CreationDate="2019-01-16T22:41:59.697" UserId="10022" Text="|texture|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22772" PostHistoryTypeId="2" PostId="8482" RevisionGUID="479aecd0-b67e-417c-8561-7c9acb1d4bf9" CreationDate="2019-01-17T05:21:12.647" UserId="8632" Text="It sounds like [Subdivision Surfaces](http://graphics.stanford.edu/courses/cs468-12-spring/LectureSlides/10_Subdivision.pdf) are better than NURBS but not as good as T-splines. I would like to know some of the disadvantages of Subdivision Surfaces, what they can't do or what they do inefficiently.&#xD;&#xA;&#xD;&#xA;I am considering what type of system to use. Whether it be B-splines, NURBS, subdivision surfaces, or T-splines, or something else. Here I am mainly wondering how good subdivision surfaces are." ContentLicense="CC BY-SA 4.0" />
  <row Id="22773" PostHistoryTypeId="1" PostId="8482" RevisionGUID="479aecd0-b67e-417c-8561-7c9acb1d4bf9" CreationDate="2019-01-17T05:21:12.647" UserId="8632" Text="Problems with Subdivision Surfaces" ContentLicense="CC BY-SA 4.0" />
  <row Id="22774" PostHistoryTypeId="3" PostId="8482" RevisionGUID="479aecd0-b67e-417c-8561-7c9acb1d4bf9" CreationDate="2019-01-17T05:21:12.647" UserId="8632" Text="|3d|2d|nurbs|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22775" PostHistoryTypeId="2" PostId="8483" RevisionGUID="05cc7e19-7dc5-4669-ac97-cc58f404f52a" CreationDate="2019-01-17T11:52:22.427" UserId="7724" Text="Both T-splines and subdivision surfaces are capable of handling an arbitrary topology input mesh, whereas NURBS can only handle meshes with regular topology. &#xD;&#xA;&#xD;&#xA;Complex NURBS objects are therefore made out of multiple regular meshes. These meshes are trimmed and fit together to form a single complex object. However, along the trimming lines of the mesh discontinuities can occur. This is because the boundary curve of a trimmed NURBS patch is not in general a NURBS curve. This complicates the joining of several NURBS patches, potentially sacrificing water tightness.&#xD;&#xA;&#xD;&#xA;Subdivision surfaces are able to handle meshes with arbitrary topology. This means your mesh can contain extraordinary faces (faces with more than four sides) and extraordinary vertices (vertices with a valency higher than 4). The generated surfaces are in general curvature continuous in regular regions and tangent plane continuous at extraordinary vertices. The evaluation of a subdivision surface is an iterative process. Although regular regions can be converted to B-spline patches problems occur when rendering the irregular regions as an infinite number of B-spline patches will be generated. The [OpenSubDiv][2] library by Pixar is a good start for speedy subdivision as it calculates many things on the GPU.&#xD;&#xA;&#xD;&#xA;Most subdivision surfaces are based on uniform subdivision and some work has been done to handle [non-uniform and rational subdivision][1], but it is quite extensive and has some limitations. &#xD;&#xA;&#xD;&#xA;T-splines can do everything NURBS can do as well. The most striking feature of T-splines is the ability to handle T-junctions, as well as arbitrary topology, without sacrificing in surface continuity. This allows the designer to insert more detail in some places without it effecting the mesh in other regions. In this way it is possible for a very organic design process. Take for instance this [video][3]. A downside of T-splines is that it is a patented technology.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-773.pdf&#xD;&#xA;  [2]: http://graphics.pixar.com/opensubdiv/docs/intro.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4nbC6__gZfg&amp;t=656s" ContentLicense="CC BY-SA 4.0" />
  <row Id="22776" PostHistoryTypeId="5" PostId="8483" RevisionGUID="21643092-12e0-4ab7-843b-ee5b536e4f70" CreationDate="2019-01-17T12:22:40.237" UserId="7724" Comment="added 7 characters in body" Text="Both T-splines and subdivision surfaces are capable of handling an arbitrary topology input mesh, whereas NURBS can only handle meshes with regular topology. &#xD;&#xA;&#xD;&#xA;Complex NURBS objects are therefore made out of multiple regular meshes. These meshes are trimmed and fit together to form a single complex object. However, along the trimming lines of the mesh discontinuities can occur. This is because the boundary curve of a trimmed NURBS patch is not in general a NURBS curve. This complicates the joining of several NURBS patches, potentially sacrificing water tightness.&#xD;&#xA;&#xD;&#xA;Subdivision surfaces are able to handle meshes with arbitrary topology. This means your mesh can contain extraordinary faces (faces with more or less than four sides) and extraordinary vertices (vertices with a valency other than 4). The generated surfaces are in general curvature continuous in regular regions and tangent plane continuous at extraordinary vertices. The evaluation of a subdivision surface is an iterative process. Although regular regions can be converted to B-spline patches problems occur when rendering the irregular regions as an infinite number of B-spline patches will be generated. The [OpenSubDiv][2] library by Pixar is a good start for speedy subdivision as it calculates many things on the GPU.&#xD;&#xA;&#xD;&#xA;Most subdivision surfaces are based on uniform subdivision and some work has been done to handle [non-uniform and rational subdivision][1], but it is quite extensive and has some limitations. &#xD;&#xA;&#xD;&#xA;T-splines can do everything NURBS can do as well. The most striking feature of T-splines is the ability to handle T-junctions, as well as arbitrary topology, without sacrificing in surface continuity. This allows the designer to insert more detail in some places without it effecting the mesh in other regions. In this way it is possible for a very organic design process. Take for instance this [video][3]. A downside of T-splines is that it is a patented technology.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-773.pdf&#xD;&#xA;  [2]: http://graphics.pixar.com/opensubdiv/docs/intro.html&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=4nbC6__gZfg&amp;t=656s" ContentLicense="CC BY-SA 4.0" />
  <row Id="22780" PostHistoryTypeId="5" PostId="8481" RevisionGUID="dbe22c12-798a-4560-83cc-114073f8d73a" CreationDate="2019-01-17T16:24:43.677" UserId="10022" Comment="added 1346 characters in body" Text="I'm currently trying to understand how works perspective correction texture mapping. I saw that actually it works by interpolating the z value of the three point of the triangle which the current rendered pixel is in, then, it divide the u and v affine texture coordinates by the interpolated z value in order to get the perspective corrected values of u and v.&#xD;&#xA;I really can't wrap my head around this division by z to do perspective correction. Can someone explain me the point and the math behind it which makes it do the job ?&#xD;&#xA;&#xD;&#xA;Thanks guys !&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Okay, after reading your adives guys, i dived into perspective correction algorithm.&#xD;&#xA;I think i have understood what is done, but i want to expose it to you in order to see if it the right way to think.&#xD;&#xA;When rendering pixels on screen you're in raster space, if you interpolate u and v values you will get affine texturing cause it does not take into account depth of the vertices.&#xD;&#xA;The solution is to do so :&#xD;&#xA;working in a &quot;specific space&quot; of three dimensions : (u,v,z). Each vertices can be represented in this space cause it have u and v tex coordinates and a z coordinate.&#xD;&#xA;The idea is the following : you divide each u and v component of the vertices by z. The effect will be a perspective projection on the plane defined by the equation 0*x + 0*y + 1*z = 1. Doing so makes us able to do interpolation into raster space. Then, when we want to get the perspective corrected texel for a specific pixel of the current renderer triangle in raster space, we just have to multiply the interpolated u/z and v/z by interplated z (actually the algorithm divide u/z and v/z by interpolated 1/z which leads exacly to a multiplication by z). But this multiplication by z can be viewed as a scalar which multiplies the interpolated vector (u/z, v/z, 1) which will put the vector to the original three dimensions space made of u v and z.&#xD;&#xA;Am i right ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22781" PostHistoryTypeId="5" PostId="8481" RevisionGUID="6c86e2ab-e657-42bd-9e3d-0e5c54e415f1" CreationDate="2019-01-17T16:30:28.970" UserId="10022" Comment="added 1 character in body" Text="I'm currently trying to understand how works perspective correction texture mapping. I saw that actually it works by interpolating the z value of the three point of the triangle which the current rendered pixel is in, then, it divide the u and v affine texture coordinates by the interpolated z value in order to get the perspective corrected values of u and v.&#xD;&#xA;I really can't wrap my head around this division by z to do perspective correction. Can someone explain me the point and the math behind it which makes it do the job ?&#xD;&#xA;&#xD;&#xA;Thanks guys !&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Okay, after reading your advices guys, i dived into perspective correction algorithm.&#xD;&#xA;I think i have understood what is done, but i want to expose it to you in order to see if it the right way to think.&#xD;&#xA;When rendering pixels on screen you're in raster space, if you interpolate u and v values you will get affine texturing cause it does not take into account depth of the vertices.&#xD;&#xA;The solution is to do so :&#xD;&#xA;working in a &quot;specific space&quot; of three dimensions : (u,v,z). Each vertices can be represented in this space cause it have u and v tex coordinates and a z coordinate.&#xD;&#xA;The idea is the following : you divide each u and v component of the vertices by z. The effect will be a perspective projection on the plane defined by the equation 0*u + 0*v + 1*z = 1. Doing so makes us able to do interpolation into raster space. Then, when we want to get the perspective corrected texel for a specific pixel of the current renderer triangle in raster space, we just have to multiply the interpolated u/z and v/z by interplated z (actually the algorithm divide u/z and v/z by interpolated 1/z which leads exacly to a multiplication by z). But this multiplication by z can be viewed as a scalar which multiplies the interpolated vector (u/z, v/z, 1) which will put back the vector from the plane at z=1 to the right place into the original three dimensions space made of u v and z.&#xD;&#xA;Am i right ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22782" PostHistoryTypeId="5" PostId="8481" RevisionGUID="6e530367-0291-45af-8a78-66dad48dce1c" CreationDate="2019-01-17T16:38:09.483" UserId="10022" Comment="added 188 characters in body" Text="I'm currently trying to understand how works perspective correction texture mapping. I saw that actually it works by interpolating the z value of the three point of the triangle which the current rendered pixel is in, then, it divide the u and v affine texture coordinates by the interpolated z value in order to get the perspective corrected values of u and v.&#xD;&#xA;I really can't wrap my head around this division by z to do perspective correction. Can someone explain me the point and the math behind it which makes it do the job ?&#xD;&#xA;&#xD;&#xA;Thanks guys !&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Okay, after reading your advices guys, i dived into perspective correction algorithm.&#xD;&#xA;I think i have understood what is done, but i want to expose it to you in order to see if it the right way to think.&#xD;&#xA;When rendering pixels on screen you're in raster space, if you interpolate u and v values you will get affine texturing cause it does not take into account depth of the vertices.&#xD;&#xA;The solution is to do so :&#xD;&#xA;working in a &quot;specific space&quot; of three dimensions : (u,v,z). Each vertices can be represented in this space cause it have u and v tex coordinates and a z coordinate.&#xD;&#xA;The idea is the following : you divide each u and v component of the vertices by z. The effect will be a perspective projection on the plane defined by the equation 0*u + 0*v + 1*z = 1. Doing so makes us able to do interpolation into raster space. Then, when we want to get the perspective corrected texel for a specific pixel of the current renderer triangle in raster space, we just have to multiply the interpolated u/z and v/z by interplated z (actually the algorithm divide u/z and v/z by interpolated 1/z which leads exacly to a multiplication by interpolated z). But this multiplication by interpolated z can be viewed as a scalar which multiplies the interpolated vector (u/z, v/z, 1) which will put back the vector from the plane at z=1 to the right place into the original three dimensions space giving us the u and v coordinates interpolated into the three dimension space, taking into account the z coordinates and leading to a correct perspective corrected texture mapping.&#xD;&#xA;Am i right ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22787" PostHistoryTypeId="2" PostId="8486" RevisionGUID="80cb5f48-53e1-4342-a09d-4b364ae2f1cd" CreationDate="2019-01-17T23:38:06.093" UserId="10028" Text="Is there a name for this type of effect where many area sizes are increased/decreased in relation to each other? I'm looking for some type of algorithm, formula, logic, etc. for recreating this. Here is the effect (which I believe was created in After Effects):&#xD;&#xA;&#xD;&#xA;[![The Tatami Galaxy (Yojouhan Shinwa Taikei / 四畳半神話大系) - Clear END][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Source: [The Tatami Galaxy (Yojouhan Shinwa Taikei / 四畳半神話大系) - Clear END][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3cYuP.gif&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=ewICfFjc4CI" ContentLicense="CC BY-SA 4.0" />
  <row Id="22788" PostHistoryTypeId="1" PostId="8486" RevisionGUID="80cb5f48-53e1-4342-a09d-4b364ae2f1cd" CreationDate="2019-01-17T23:38:06.093" UserId="10028" Text="What algorithm is used in this animation from Tatami Galaxy?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22789" PostHistoryTypeId="3" PostId="8486" RevisionGUID="80cb5f48-53e1-4342-a09d-4b364ae2f1cd" CreationDate="2019-01-17T23:38:06.093" UserId="10028" Text="|algorithm|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22791" PostHistoryTypeId="2" PostId="8487" RevisionGUID="06b1b14e-acf5-4df1-80bf-aefcc4637dec" CreationDate="2019-01-18T07:12:06.727" UserId="9908" Text="It looks like a [voronoi diagram](https://en.wikipedia.org/wiki/Voronoi_diagram) with a non-Euclidean distance metric. Probably not [Manhattan L1](https://en.wikipedia.org/wiki/Taxicab_geometry) but something close related, but maybe [Mahalanobis](https://en.wikipedia.org/wiki/Mahalanobis_distance) with some kind of restriction on seed point generation and movement.&#xD;&#xA;&#xD;&#xA;A similar result may be calculated with [Weight-proportional Space Partitioning Using Adaptive Voronoi Diagrams](https://link.springer.com/article/10.1007/s10707-006-0006-8) when reducing spatial resolution of the domain. &#xD;&#xA;&#xD;&#xA;I guess yo'll find similar examples in [ShaderToy](https://www.shadertoy.com/) if you look for voronoi examples, which code you could study, and could be much simpler than the algorithm in the paper. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22792" PostHistoryTypeId="2" PostId="8488" RevisionGUID="cc655c87-2fad-4c0b-8075-b1fc658c2db2" CreationDate="2019-01-18T07:13:57.957" UserId="7644" Text="The last time I wanted to go from window coordinates (pixels) to eye coordinates, I followed the steps outlined here in the [OpenGL wiki][1]. Once you have the eye coordinates, you can just normalize the vector to obtain $r_{ij}$.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Compute_eye_space_from_window_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="22793" PostHistoryTypeId="5" PostId="8479" RevisionGUID="9f3ccd55-dacb-4b83-9149-502dca96e7be" CreationDate="2019-01-18T09:39:26.253" UserId="9881" Comment="added 92 characters in body" Text="In [ray-tracing][1] technique critical point is to calculate rays which came out from eye $E$ to target $T$ through pixel $P_{ij}$ on viewport. The &quot;viewport&quot; is represented as rectangle divided to square pixels - this rectangle is perpendicular to line which go through points $E$, $C$ (viewport center) and $T$. The ray (red line on image) is represented by point $E$ and unit  vector $r_{ij}$ (not shown in picture but it lay on red line) - below is picture which show &quot;geometry&quot; - but what are the formulas to calculate $r_{ij}$? &#xD;&#xA;&#xD;&#xA;The given input values are: &#xD;&#xA;&#xD;&#xA;* eye position $E$, &#xD;&#xA;* target position $T$, &#xD;&#xA;* field of view $\theta$ (angle, for human eye $\approx 90^\circ$), &#xD;&#xA;* number of square pixels $k$ (horizontal direction) and $m$ (vertical direction).&#xD;&#xA;* $i,j$ processed pixel coordinates ($P_{ij}$) where $1\leq i\leq k$ and $1\leq j\leq m$   &#xD;&#xA;* we also know vertical $w$ vector usually equal to $w=[wx,wy,wz]=[0,1,0]$ (not shown on picture) which indicate where is up and where is down &#xD;&#xA;&#xD;&#xA;The orthogonal vectors $v$ and $b$  (and $t$) on picture are determined by $w$ and $t=T-E$ and maybe will useful in $r_{ij}$ calculations. The $d$ and pixel size is arbitrary and don't change the result because of fixed $\theta$. &#xD;&#xA;&#xD;&#xA;**Question**: How to calculate unit vector $r_{ij}$ knowing input values described above?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&#xD;&#xA;  [2]: https://i.stack.imgur.com/PKrBi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22794" PostHistoryTypeId="5" PostId="8488" RevisionGUID="f89dc876-27bd-42d6-b7aa-4cd784cec6ce" CreationDate="2019-01-18T12:23:05.723" UserId="7644" Comment="added 808 characters in body" Text="First, the viewport size:&#xD;&#xA;$$h_x = 2*d*tan(\theta_x/2)$$&#xD;&#xA;$$h_y = 2*d*tan(\theta_y/2)$$&#xD;&#xA;&#xD;&#xA;Each pixel (from your diagram) has the following size in the eye coordinate system:&#xD;&#xA;$$W = h_x / (k-1)$$&#xD;&#xA;$$H = h_y / (m-1)$$&#xD;&#xA;&#xD;&#xA;Note that usually the field of view encompasses whole pixels and doesn't stop at the center of the edge pixels like your diagram shows.&#xD;&#xA;&#xD;&#xA;If $P_c$ is the viewport center in pixel coordinates, let:&#xD;&#xA;&#xD;&#xA;$$\vec {P'_{ij}} = P_{ij} - P_c$$&#xD;&#xA;&#xD;&#xA;Therefore, $P_{ij}$ in eye space becomes:&#xD;&#xA;$$&#xD;&#xA;[P_{ij}]_e =&#xD;&#xA;    \begin{pmatrix}&#xD;&#xA;    (W, 0) * \vec {P'_{ij}} \\&#xD;&#xA;    (0, H) * \vec {P'_{ij}} \\&#xD;&#xA;    d \\&#xD;&#xA;    \end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and in the standard base:&#xD;&#xA;$$[P_{ij}]_{std} = (\vec b, \vec v, \vec t) * [P_{ij}]_e$$&#xD;&#xA;&#xD;&#xA;Normalize the one in the base you want to get $r_{ij}$.&#xD;&#xA;&#xD;&#xA;# Original answer&#xD;&#xA;&#xD;&#xA;The last time I wanted to go from window coordinates (pixels) to eye coordinates, I followed the steps outlined here in the [OpenGL wiki][1]. Once you have the eye coordinates, you can just normalize the vector to obtain $r_{ij}$.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Compute_eye_space_from_window_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="22795" PostHistoryTypeId="2" PostId="8489" RevisionGUID="da3d45f9-07e9-4f6a-9c9c-013e9f8687b8" CreationDate="2019-01-18T13:36:26.443" UserId="8632" Text="I've seen how subdivision surfaces are good for 3D curves/modeling, but haven't seen anything on if it's good, or even usable, in 2D.&#xD;&#xA;&#xD;&#xA;My question is just that, if (a) you can even use subdivision surfaces in 2D, and (b) if you can use it for 2D, if it's a good solution for modeling curves in 2D, or if not, what a good solution for modeling curves in 2D might be (if it's just bezier curves, or ideally something better / more powerful).&#xD;&#xA;&#xD;&#xA;[Here](https://www.cl.cam.ac.uk/teaching/1617/AdvGraph/6.%20Subdivision%20surfaces.pdf) it suggests subdivision surfaces could be used in 2D, but not sure if they would be considered good for it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CpFQz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22796" PostHistoryTypeId="1" PostId="8489" RevisionGUID="da3d45f9-07e9-4f6a-9c9c-013e9f8687b8" CreationDate="2019-01-18T13:36:26.443" UserId="8632" Text="If you can use subdivision surfaces for 2D curves" ContentLicense="CC BY-SA 4.0" />
  <row Id="22797" PostHistoryTypeId="3" PostId="8489" RevisionGUID="da3d45f9-07e9-4f6a-9c9c-013e9f8687b8" CreationDate="2019-01-18T13:36:26.443" UserId="8632" Text="|3d|2d|curve|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22798" PostHistoryTypeId="5" PostId="8479" RevisionGUID="e997fcd1-1381-43f4-af54-e8612430b6fb" CreationDate="2019-01-18T13:44:38.060" UserId="9881" Comment="deleted 5 characters in body" Text="In [ray-tracing][1] technique critical point is to calculate rays which came out from eye $E$ to target $T$ through pixel $P_{ij}$ on viewport. The &quot;viewport&quot; is represented as rectangle divided to square pixels - this rectangle is perpendicular to line which go through points $E$, $C$ (viewport center) and $T$. The ray (red line on image) is represented by point $E$ and unit  vector $r_{ij}$ (not shown in picture but it lay on red line) - below is picture which show &quot;geometry&quot; - but what are the formulas to calculate $r_{ij}$? &#xD;&#xA;&#xD;&#xA;The given input values are: &#xD;&#xA;&#xD;&#xA;* eye position $E$, &#xD;&#xA;* target position $T$, &#xD;&#xA;* field of view $\theta$ (angle, for human eye $\approx 90^\circ$), &#xD;&#xA;* number of square pixels $k$ (horizontal direction) and $m$ (vertical direction).&#xD;&#xA;* $i,j$ processed pixel numbers ($P_{ij}$) where $1\leq i\leq k$ and $1\leq j\leq m$   &#xD;&#xA;* we also know vertical $w$ vector usually equal to $w=[wx,wy,wz]=[0,1,0]$ (not shown on picture) which indicate where is up and where is down &#xD;&#xA;&#xD;&#xA;The orthogonal vectors $v$ and $b$  (and $t$) on picture are determined by $w$ and $t=T-E$ and maybe will useful in $r_{ij}$ calculations. The $d$ and pixel size is arbitrary and don't change the result because of fixed $\theta$. &#xD;&#xA;&#xD;&#xA;**Question**: How to calculate unit vector $r_{ij}$ knowing input values described above?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&#xD;&#xA;  [2]: https://i.stack.imgur.com/PKrBi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22802" PostHistoryTypeId="2" PostId="8491" RevisionGUID="b1a8ce2b-6ee2-4fe4-88a2-bb127f316c10" CreationDate="2019-01-18T15:45:39.420" UserId="6046" Text="Read up on the basics for ray-tracing [here][1],&#xD;&#xA;&#xD;&#xA;Usually we don't mess up with viewports and stuff in raytracing, So I'm just telling you for the case where viewport equals the Image Width and Height.&#xD;&#xA;&#xD;&#xA;There are two cases when the field of view changes. Either you move the image plane back and forth or you increase the size. We choose to change $d$ ( former approach). &#xD;&#xA;&#xD;&#xA;Calculating ray is simple when the camera is aligned with the world, all you have to do is&#xD;&#xA;&#xD;&#xA;$d = 1/tan(\theta_{fov}/2))$&#xD;&#xA;&#xD;&#xA;$P_x = P_x + 0.5$  &#xD;&#xA;$P_y = P_y + 0.5$&#xD;&#xA;&#xD;&#xA;$aspect\_ratio = width/height$&#xD;&#xA;&#xD;&#xA;$ray.dir.x = aspect\_ratio *(2*P_x/width) -1$&#xD;&#xA;&#xD;&#xA;$ray.dir.y = (2*P_y/height) - 1$&#xD;&#xA;&#xD;&#xA;$ray.dir.z = d$&#xD;&#xA;&#xD;&#xA;The $Z$ coordinate should be negative or positive depending on whether you are using a right handed or left handed coordinate system. $P_x$ and $P_y$ are pixel coordinates offset by $0.5$ to get the center of the pixel.&#xD;&#xA;&#xD;&#xA;The process is simple. You first map your image to NDC space (-1, 1). However to account for non-square images we scale the $X$ coordinate by Aspect ratio so it's $[-a, a]$ in $X$ and $[-1,1]$ in Y. The ray's direction through the pixel is then given by above formulas. You might have to flip the $Y$ coordinate if the image coordinate's origin is top left instead of bottom left.&#xD;&#xA;&#xD;&#xA;Note however the link bases all their coordinate systems and space names on RenderMan which is quite different from OpenGL.&#xD;&#xA;  [1]: http://www.scratchapixel.com/index.php?redirect" ContentLicense="CC BY-SA 4.0" />
  <row Id="22803" PostHistoryTypeId="2" PostId="8492" RevisionGUID="26d4d531-abe8-4979-a8d1-0f42ece33747" CreationDate="2019-01-18T16:39:19.807" UserDisplayName="user9851" Text="I was able to write the following working code to draw any number of &quot;sprites&quot; (defined as 2 tringles, 6 vertices)&#xD;&#xA;&#xD;&#xA;		Matrix.setIdentityM(mModelMatrix, 0);&#xD;&#xA;&#xD;&#xA;		Matrix.multiplyMM(mMVPMatrix, 0, getCamera().mViewMatrix, 0, mModelMatrix, 0);&#xD;&#xA;		GLES20.glUniformMatrix4fv(mShader.getMVMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;&#xD;&#xA;		Matrix.multiplyMM(mMVPMatrix, 0, getCamera().projMatrix, 0, mMVPMatrix, 0);&#xD;&#xA;		GLES20.glUniformMatrix4fv(mShader.getMVPMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;&#xD;&#xA;		mPositions.position(0);&#xD;&#xA;		mColors.position(0);&#xD;&#xA;		mNormals.position(0);&#xD;&#xA;		mTextureCoordinates.position(0);&#xD;&#xA;&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getPositionHandle(), mPositionDataSize, GLES20.GL_FLOAT, false, 0, mPositions);&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getColorHandle(), mColorDataSize, GLES20.GL_FLOAT, false, 0, mColors);&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getNormalHandle(), mNormalDataSize, GLES20.GL_FLOAT, false, 0, mNormals);&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getTextureCoordinateHandle(), mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mTextureCoordinates);&#xD;&#xA;&#xD;&#xA;		GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6*numSprites);&#xD;&#xA;&#xD;&#xA;Using a sprite atlas this code displays many different sprite textures in one fell swoop, which is very fast.&#xD;&#xA;&#xD;&#xA;However, I would also like to draw multiple copies of a 3D `.obj` file. Now I've loaded in the necessary `FloatBuffers` of positions, normals, texture coordinates, etc., so I can easily add these buffers to the `mPositions`, `mTextureCoordinates` buffers above, etc., no problem.&#xD;&#xA;&#xD;&#xA;But these instances of the `.obj` model I'm trying to display need to be in different x/y locations.&#xD;&#xA;&#xD;&#xA;**Is there an efficient way this can be achieved in OpenGL?** Maybe one of the following:&#xD;&#xA;&#xD;&#xA;1. I could displace the `.obj` files `_positions` buffer before adding to the  global `mPositions` buffer to draw, but this seems rather inefficient.&#xD;&#xA;&#xD;&#xA;2. One solution is to run a separate instance of the above code for each `.obj` 3D object, including an OpenGL translation for each instance. But I've heard this is costly if you have many 3D objects. (This is the reason I use a sprite atlas for 2D sprites in the above code)&#xD;&#xA;&#xD;&#xA;3. &quot;Another&quot; approach that seems to work is to add the following example code, where `_positions` etc are the buffers for the `.obj. file, and I draw 5 of the same object file in a row using a translation. It's very similar to (2) but without having to repeat the OpenGL initialisation code every time.&#xD;&#xA;&#xD;&#xA;        for (int c1 = 0; c1 &lt; 5; c1++) {&#xD;&#xA;&#xD;&#xA;            _positions.position(0);&#xD;&#xA;            _normals.position(0);&#xD;&#xA;            _textureCoordinates.position(0);&#xD;&#xA;&#xD;&#xA;            Matrix.setIdentityM(mModelMatrix, 0);&#xD;&#xA;            Matrix.translateM(mModelMatrix, 0, cx + dx * c1 * 4, cy, 0);&#xD;&#xA;            Matrix.scaleM(mModelMatrix, 0, 0.1f, 0.1f, 0.03f);&#xD;&#xA;            Matrix.rotateM(mModelMatrix, 0, -90, 1, 0, 0);&#xD;&#xA;&#xD;&#xA;            Matrix.multiplyMM(mMVPMatrix, 0, getCamera().mViewMatrix, 0, mModelMatrix, 0);&#xD;&#xA;&#xD;&#xA;            GLES20.glUniformMatrix4fv(mShader.getMVMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;            Matrix.multiplyMM(mMVPMatrix, 0, getCamera().projMatrix, 0, mMVPMatrix, 0);&#xD;&#xA;            GLES20.glUniformMatrix4fv(mShader.getMVPMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, numFaces);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;But I'm not sure if this isn't just as inefficient as the (2) ?&#xD;&#xA;&#xD;&#xA;4. Maybe there's no way round it? Perhaps (2)/(3) is the only way and I'm just being over cautious because of my &quot;bad&quot; experience without using a sprite atlas for 2D sprites? After all, I was originally drawing 1000's of 2D sprites using method (1) originally, but I will only be drawing around 10-20 3D objects. In the 2D case, switching to a sprite atlas greatly speeded things up !" ContentLicense="CC BY-SA 4.0" />
  <row Id="22804" PostHistoryTypeId="1" PostId="8492" RevisionGUID="26d4d531-abe8-4979-a8d1-0f42ece33747" CreationDate="2019-01-18T16:39:19.807" UserDisplayName="user9851" Text="Efficiently drawing multiple instances of 3D objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="22805" PostHistoryTypeId="3" PostId="8492" RevisionGUID="26d4d531-abe8-4979-a8d1-0f42ece33747" CreationDate="2019-01-18T16:39:19.807" UserDisplayName="user9851" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22806" PostHistoryTypeId="2" PostId="8493" RevisionGUID="ccb96414-677d-49f4-996d-0ea15d912656" CreationDate="2019-01-18T16:45:04.917" UserId="7724" Text="Subdivision can be used for curves in 2D just as easily as for surfaces in 3D. Usually the subdivision algorithms applied to 2D are called subdivision curves. Subdivision curves do not suffer from the problem that subdivision surfaces have around extraordinary points and therefore all subdivision surfaces can easily be converted to (uniform) B-splines. This means that it equal to working with Bézier curves in most cases. This latter representation might be more advantageous as it possesses a closed form representation such that curves can be evaluated easily at arbitrary parameter values.&#xD;&#xA;&#xD;&#xA;A simple subdivision algorithm for curves is the following. Consider a polyline consisting out of $n$ points. Than for every iteration do the following steps:&#xD;&#xA;&#xD;&#xA;Every exisiting position $P_i =&gt; (P_{i-1} + 6 P_{i} + P_{i+1})/8$ then add new positions on every edge between existing points using $(4 P_i + 4 P_{i+1})/8$. In the limit this procedure will converge to uniform cubic B-splines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some useful extensions for subdivison curves exists such as [(semi-sharp) creases and boundary conditions][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.rug.nl/research/portal/files/50538260/Creases_and_boundary_conditions.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22807" PostHistoryTypeId="5" PostId="8493" RevisionGUID="760e788c-c110-4598-b0d5-db39c369ba1c" CreationDate="2019-01-18T16:50:37.967" UserId="7724" Comment="added 35 characters in body" Text="Subdivision can be used for curves in 2D just as easily as for surfaces in 3D. Usually the subdivision algorithms applied to 2D are called subdivision curves. Subdivision curves do not suffer from the problem that subdivision surfaces have around extraordinary points and therefore all subdivision surfaces can easily be converted to (uniform) B-splines. This means that it equals to working with Bézier curves in most cases. This latter representation might be more advantageous as it possesses a closed form representation, such that curves can be evaluated easily at arbitrary parameter values.&#xD;&#xA;&#xD;&#xA;A simple subdivision algorithm for curves is the following. Consider a polyline consisting out of $n$ points $P_0 \ldots $P_{n-1}$. Than for every iteration do the following steps:&#xD;&#xA;&#xD;&#xA;Every exisiting position $P_i =&gt; (P_{i-1} + 6 P_{i} + P_{i+1})/8$ then add new positions on every edge between existing points using $(4 P_i + 4 P_{i+1})/8$ and repeat/ In the limit this procedure will converge to uniform cubic B-splines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some useful extensions for subdivison curves exists such as [(semi-sharp) creases and boundary conditions][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.rug.nl/research/portal/files/50538260/Creases_and_boundary_conditions.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22808" PostHistoryTypeId="2" PostId="8494" RevisionGUID="5816b353-cc26-42af-874f-fb32c90df040" CreationDate="2019-01-18T16:59:09.813" UserId="7724" Text="What you are looking for here is [instanced rendering][1]. Instanced rendering coupled with [attribute divisors][2] is a very powerful tool to render multiple copies of the same object using only one drawing call. &#xD;&#xA;&#xD;&#xA;Using instanced rendering you only have to specify the geometry of an object once on the GPU. Then, you could pass along an additional buffer of matrices, one matrix for each instance of the object you are rendering. Using attribute divisors you can tell the GPU that you will only need one single matrix per a number of vertices. Attribute divisors tell the GPU when and how to advance an index in a attribute buffer. This allows you to only define a single matrix per instance instead of passing along a single matrix for every vertex in a single model.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Here][3], is an excellent tutorial on using instanced rendering and attribute divisors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArraysInstanced.xhtml&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml&#xD;&#xA;  [3]: http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22809" PostHistoryTypeId="2" PostId="8495" RevisionGUID="8be2df75-e706-4637-8bd7-f73f28b5c383" CreationDate="2019-01-18T18:21:59.740" UserId="10033" Text="I'm trying to add bump mapping to my ray tracer, and I'm currently struggling to add bump mapping to it, as I don't seem to get the transformations from texture space to world space correctly.&#xD;&#xA;&#xD;&#xA;I have an arbitary Triangle in world-Space defined by it's vertices.&#xD;&#xA;Each of the vertices store a normalized UV-Coordinate to interpolate the position on the height map for an Intersection Point.&#xD;&#xA;The height map is a gray-Scale Image&#xD;&#xA;So when I intersect with the Triangle, I calculate the x and y derivatives of the height map at the corresponding uv-coordinate, transform the x and y unit Vectors (of the Texture) to world-Space, and calculate the changed normal. This currently looks like this:&#xD;&#xA;            &#xD;&#xA;            Point p = lerpbar(uv_vert1, uv_vert2, uv_vert3, &#xD;&#xA;                   intersection.barycentric.u, intersection.barycentric.v);&#xD;&#xA;            float gx = this-&gt;_bmap-&gt;getColorDX(p);&#xD;&#xA;            float gy = this-&gt;_bmap-&gt;getColorDY(p);&#xD;&#xA;            Vector wx = (To_World_Matrix * Vector(1, 0, 0))).normalize();&#xD;&#xA;            Vector wy = (To_World_Matrix * Vector(0, 1, 0))).normalize();&#xD;&#xA;            Vector n = intersection.normal();&#xD;&#xA;            return n + (gx * cross(n, wy) - gy * cross(n, wx));&#xD;&#xA;However, I just can't figure out what Matrix I'd need to use so this produces correct results, as I just don't really understand how to map from unit Vectors to World-Space Vectors when I only know how arbitay Triangle Edges relate to arbitay Vectors in Texture Space.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22810" PostHistoryTypeId="1" PostId="8495" RevisionGUID="8be2df75-e706-4637-8bd7-f73f28b5c383" CreationDate="2019-01-18T18:21:59.740" UserId="10033" Text="Bump mapping with triangles and heigt maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="22811" PostHistoryTypeId="3" PostId="8495" RevisionGUID="8be2df75-e706-4637-8bd7-f73f28b5c383" CreationDate="2019-01-18T18:21:59.740" UserId="10033" Text="|raytracing|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22812" PostHistoryTypeId="5" PostId="8492" RevisionGUID="66cceb44-3749-4f89-a545-44c0ef956d95" CreationDate="2019-01-18T21:01:42.223" UserDisplayName="user9851" Comment="added 47 characters in body" Text="I was able to write the following working code to draw any number of &quot;sprites&quot; (defined as 2 tringles, 6 vertices)&#xD;&#xA;&#xD;&#xA;		Matrix.setIdentityM(mModelMatrix, 0);&#xD;&#xA;&#xD;&#xA;		Matrix.multiplyMM(mMVPMatrix, 0, getCamera().mViewMatrix, 0, mModelMatrix, 0);&#xD;&#xA;		GLES20.glUniformMatrix4fv(mShader.getMVMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;&#xD;&#xA;		Matrix.multiplyMM(mMVPMatrix, 0, getCamera().projMatrix, 0, mMVPMatrix, 0);&#xD;&#xA;		GLES20.glUniformMatrix4fv(mShader.getMVPMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;&#xD;&#xA;		mPositions.position(0);&#xD;&#xA;		mColors.position(0);&#xD;&#xA;		mNormals.position(0);&#xD;&#xA;		mTextureCoordinates.position(0);&#xD;&#xA;&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getPositionHandle(), mPositionDataSize, GLES20.GL_FLOAT, false, 0, mPositions);&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getColorHandle(), mColorDataSize, GLES20.GL_FLOAT, false, 0, mColors);&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getNormalHandle(), mNormalDataSize, GLES20.GL_FLOAT, false, 0, mNormals);&#xD;&#xA;		GLES20.glVertexAttribPointer(mShader.getTextureCoordinateHandle(), mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mTextureCoordinates);&#xD;&#xA;&#xD;&#xA;		GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6*numSprites);&#xD;&#xA;&#xD;&#xA;Using a sprite atlas this code displays many different sprite textures in one fell swoop, which is very fast.&#xD;&#xA;&#xD;&#xA;However, I would also like to draw multiple copies of a 3D `.obj` file. Now I've loaded in the necessary `FloatBuffers` of positions, normals, texture coordinates, etc., so I can easily add these buffers to the `mPositions`, `mTextureCoordinates` buffers above, etc., no problem.&#xD;&#xA;&#xD;&#xA;But these instances of the `.obj` model I'm trying to display need to be in different x/y locations.&#xD;&#xA;&#xD;&#xA;**Is there an efficient way this can be achieved in OpenGL?** Maybe one of the following:&#xD;&#xA;&#xD;&#xA;1. I could displace the `.obj` files `_positions` buffer before adding to the  global `mPositions` buffer to draw, but this seems rather inefficient.&#xD;&#xA;&#xD;&#xA;2. One solution is to run a separate instance of the above code for each `.obj` 3D object, including an OpenGL translation for each instance. But I've heard this is costly if you have many 3D objects. (This is the reason I use a sprite atlas for 2D sprites in the above code)&#xD;&#xA;&#xD;&#xA;3. &quot;Another&quot; approach that seems to work is to add the following example code, where `_positions` etc are the buffers for the `.obj. file, and I draw 5 of the same object file in a row using a translation. It's very similar to (2) but without having to repeat the OpenGL initialisation code every time.&#xD;&#xA;&#xD;&#xA;        for (int c1 = 0; c1 &lt; 5; c1++) {&#xD;&#xA;&#xD;&#xA;            _positions.position(0);&#xD;&#xA;            _normals.position(0);&#xD;&#xA;            _textureCoordinates.position(0);&#xD;&#xA;&#xD;&#xA;            Matrix.setIdentityM(mModelMatrix, 0);&#xD;&#xA;            Matrix.translateM(mModelMatrix, 0, cx + dx * c1 * 4, cy, 0);&#xD;&#xA;            Matrix.scaleM(mModelMatrix, 0, 0.1f, 0.1f, 0.03f);&#xD;&#xA;            Matrix.rotateM(mModelMatrix, 0, -90, 1, 0, 0);&#xD;&#xA;&#xD;&#xA;            Matrix.multiplyMM(mMVPMatrix, 0, getCamera().mViewMatrix, 0, mModelMatrix, 0);&#xD;&#xA;&#xD;&#xA;            GLES20.glUniformMatrix4fv(mShader.getMVMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;            Matrix.multiplyMM(mMVPMatrix, 0, getCamera().projMatrix, 0, mMVPMatrix, 0);&#xD;&#xA;            GLES20.glUniformMatrix4fv(mShader.getMVPMatrixHandle(), 1, false, mMVPMatrix, 0);&#xD;&#xA;            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, numFaces);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;But I'm not sure if this isn't just as inefficient as the (2) ?&#xD;&#xA;&#xD;&#xA;4. Maybe there's no way round it? Perhaps (2)/(3) is the only way and I'm just being over cautious because of my &quot;bad&quot; experience without using a sprite atlas for 2D sprites? After all, I was originally drawing 1000's of 2D sprites using method (1) originally, but I will only be drawing around 10-20 3D objects. In the 2D case, switching to a sprite atlas greatly speeded things up !&#xD;&#xA;&#xD;&#xA;(I'm interested in OpenGL ES 2.0 primarily)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22819" PostHistoryTypeId="5" PostId="8491" RevisionGUID="d2d89c6b-fdb0-4154-834d-e75f9ad0e10d" CreationDate="2019-01-19T09:27:42.660" UserId="6046" Comment="added 143 characters in body" Text="Read up on the basics for ray-tracing [here][1],&#xD;&#xA;&#xD;&#xA;Usually we don't mess up with viewports and stuff in raytracing, So I'm just telling you for the case where viewport equals the Image Width and Height.&#xD;&#xA;&#xD;&#xA;There are two cases when the field of view changes. Either you move the image plane back and forth or you increase the size. We choose to change $d$ ( former approach). &#xD;&#xA;&#xD;&#xA;Calculating ray is simple when the camera is aligned with the world, all you have to do is&#xD;&#xA;&#xD;&#xA;$d = 1/tan(\theta_{fov}/2))$&#xD;&#xA;&#xD;&#xA;$P_x = P_x + 0.5$  &#xD;&#xA;$P_y = P_y + 0.5$&#xD;&#xA;&#xD;&#xA;$aspect\_ratio = width/height$&#xD;&#xA;&#xD;&#xA;$ray.dir.x = aspect\_ratio *(2*P_x/width) -1$&#xD;&#xA;&#xD;&#xA;$ray.dir.y = (2*P_y/height) - 1$&#xD;&#xA;&#xD;&#xA;$ray.dir.z = d$&#xD;&#xA;&#xD;&#xA;The $Z$ coordinate should be negative or positive depending on whether you are using a right handed or left handed coordinate system. $P_x$ and $P_y$ are pixel coordinates offset by $0.5$ to get the center of the pixel.&#xD;&#xA;&#xD;&#xA;The process is simple. You first map your image to NDC space (-1, 1). However to account for non-square images we scale the $X$ coordinate by Aspect ratio so it's $[-a, a]$ in $X$ and $[-1,1]$ in Y. The ray's direction through the pixel is then given by above formulas. You might have to flip the $Y$ coordinate if the image coordinate's origin is top left instead of bottom left.&#xD;&#xA;&#xD;&#xA;Note however the link bases all their coordinate systems and space names on RenderMan which is quite different from OpenGL. For camera that isn't aligned with the world coordinate you have to multiply by the transformation matrix as described by bernie in his answer&#xD;&#xA;  [1]: http://www.scratchapixel.com/index.php?redirect" ContentLicense="CC BY-SA 4.0" />
  <row Id="22820" PostHistoryTypeId="5" PostId="8444" RevisionGUID="d3395652-d120-46c5-b034-0eb6c163bbfa" CreationDate="2019-01-19T22:00:36.357" UserId="6046" Comment="deleted 9 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS however now I'm getting more fireflies and I think I read that MIS reduces fireflies?. Anyways, I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`.&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter but the fireflies still remain. Note the reflection is harder to converge although its 2500spp while the one below is 1500 spp.&#xD;&#xA;&#xD;&#xA;Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;[![with MIS ][5]][5]&#xD;&#xA;[![Without MIS][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/GYYP1.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/4suBT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22824" PostHistoryTypeId="2" PostId="8498" RevisionGUID="4128c827-f807-41c0-970c-caea0301be97" CreationDate="2019-01-20T01:07:48.487" UserId="9987" Text="I am reading a paper about layered materials. However, I am confused on the implementation of this paper. The following picture describe the layered material. [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CTUZR.png&#xD;&#xA;&#xD;&#xA;r_ab is a complex reflection coeffcient when going from medium a to medium b. &#xD;&#xA;&#xD;&#xA;And in the code, there is:&#xD;&#xA;&#xD;&#xA;    		float2 R12, phi12;&#xD;&#xA;			fresnelDielectric(LdotH, 1.0, eta_2, R12, phi12);&#xD;&#xA;			float2 R21 = R12;&#xD;&#xA;&#xD;&#xA;I don't understand why is r_12 equal to r_21?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22825" PostHistoryTypeId="1" PostId="8498" RevisionGUID="4128c827-f807-41c0-970c-caea0301be97" CreationDate="2019-01-20T01:07:48.487" UserId="9987" Text="Confused on reflection coeffcient of Fresnel equations" ContentLicense="CC BY-SA 4.0" />
  <row Id="22826" PostHistoryTypeId="3" PostId="8498" RevisionGUID="4128c827-f807-41c0-970c-caea0301be97" CreationDate="2019-01-20T01:07:48.487" UserId="9987" Text="|pbr|material|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22827" PostHistoryTypeId="2" PostId="8499" RevisionGUID="1024ea44-9417-4617-8f03-7a724cd22332" CreationDate="2019-01-20T04:10:57.577" UserId="48" Text="We have $t_{12} = t_{21}$, by reciprocity. Also, $$r_{12} + t_{12} = 1\\r_{21} + t_{21} = 1$$&#xD;&#xA;It follows that $r_{12} = r_{21}$ as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="22828" PostHistoryTypeId="2" PostId="8500" RevisionGUID="6832f978-79bf-4651-abde-587cf9824e48" CreationDate="2019-01-20T07:25:13.420" UserId="10039" Text="Given a perspective projection matrix. How can one from it derive a set of matrices representing &quot;chunks&quot; of the viewport? So that the rendered chunks can be &quot;stiched&quot; &#xD;&#xA;to form an image &quot;chunk times higher&quot; resolution than the viewport. &#xD;&#xA;&#xD;&#xA;Here's an image (drawn in ms paint, ik) describing what a chunk of the frustum would look like: &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm planning on using this for a camera mod library to take images in &quot;super-resolution&quot;, in reality the chunks should overlap a little, to allow for exposure compensation and the blending of effects like lens flare. Most linear algebra in this project is done with a [header-only library called linalg][2] , so it'd be nice if any examples shown used that library. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SOuZS.png&#xD;&#xA;  [2]: https://github.com/sgorsten/linalg" ContentLicense="CC BY-SA 4.0" />
  <row Id="22829" PostHistoryTypeId="1" PostId="8500" RevisionGUID="6832f978-79bf-4651-abde-587cf9824e48" CreationDate="2019-01-20T07:25:13.420" UserId="10039" Text="Modify camera matrix so that it renders a &quot;chunk&quot; of the frustum" ContentLicense="CC BY-SA 4.0" />
  <row Id="22830" PostHistoryTypeId="3" PostId="8500" RevisionGUID="6832f978-79bf-4651-abde-587cf9824e48" CreationDate="2019-01-20T07:25:13.420" UserId="10039" Text="|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22831" PostHistoryTypeId="2" PostId="8501" RevisionGUID="f836945c-6a43-4e1e-a376-47e98b02c887" CreationDate="2019-01-20T08:02:13.293" UserId="7644" Text="The normal of a given point on the height map is perpendicular to the 2 vectors defined by `gx` and `gy`. The original surface normal is not relevant to this. So in tangent space, the normal is:&#xD;&#xA;&#xD;&#xA;    Vector tangent = Vector(1, 0, gx);&#xD;&#xA;    Vector bitangent = Vector(0, 1, gy);&#xD;&#xA;    Vector normal = normalize(cross(tangent, bitangent));&#xD;&#xA;&#xD;&#xA;You then need to convert the normal from tangent space to world space. For this you need the so-called &quot;TBN matrix&quot; (tangent, bitangent, normal matrix). There are plenty of [articles][1] [around][2] explaining this. But the gist is:&#xD;&#xA;&#xD;&#xA;    Vector T = normalize(To_World_Matrix * intersection.tangent());&#xD;&#xA;    Vector B = normalize(To_World_Matrix * cross(intersection.tangent(), intersection.normal()));&#xD;&#xA;    Vector N = normalize(To_World_Matrix * intersection.normal());&#xD;&#xA;    mat3 TBN = mat3(T, B, N); // GLSL syntax&#xD;&#xA;&#xD;&#xA;The last thing is to do a change of basis to move the normal from tangent space to world space:&#xD;&#xA;&#xD;&#xA;    Vector normal_world_space = normalize(TBN * normal);&#xD;&#xA;&#xD;&#xA;Keep in mind that the order of some cross-products might be inverted in what I wrote if you get normals pointing inside the surface.&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Advanced-Lighting/Normal-Mapping&#xD;&#xA;  [2]: https://www.gamasutra.com/blogs/RobertBasler/20131122/205462/Three_Normal_Mapping_Techniques_Explained_For_the_Mathematically_Uninclined.php" ContentLicense="CC BY-SA 4.0" />
  <row Id="22832" PostHistoryTypeId="2" PostId="8502" RevisionGUID="1f279333-eb1f-4015-aa6c-0ab06050f254" CreationDate="2019-01-20T12:30:09.450" UserId="6" Text="It depends a little how you construct the matrix. I assume that you use the function `perspective_matrix` from your library, which actually works pretty much like good old [`gluPerspective`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml)). But what this actually does is nothing else than use the more general function `frustum_matrix`, which in turn creates a common arbitrary view frustum matrix, like good old [`glFrustum`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml) did (from the (simplified) *linalg* source code):&#xD;&#xA;&#xD;&#xA;    mat4 perspective_matrix(T fovy, T aspect, T n, T f)&#xD;&#xA;    {&#xD;&#xA;        T y = n*std::tan(fovy / 2), x = y*aspect;&#xD;&#xA;        return frustum_matrix(-x, x, -y, y, n, f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this **general frustum matrix function is actually all you need for creating arbitrary assymmetrical frustum matrices**, like the ones you want. The paramters it takes are exactly the left, right, bottom, and top boundaries of the near plane, i.e. the x and y boundaries of the frustum *on* the z = `near` (or `-near`) plane. So all you actually need to do is **take these left/right/bottom/top parameters and cut those ranges into whatever sub-intervals you need**.&#xD;&#xA;&#xD;&#xA;It depends a little on what information you actually have. If you have the parameters you construct your perspective matrix from (i.e. the `fovY` and the `aspect`) you can just replace the above procedure with something more elaborate that computes the frustum parameters from these two and then scale-biases them into the corresponding intervals.&#xD;&#xA;&#xD;&#xA;If all you have is an already constructed perspective matrix, you might have to retrieve the parameters from that matrix first, which shouldn't be too difficult when looking at how the matrix is constructed. If you *already* have a general assymmetric frustum matrix, it might get a little more elaborate. But it always really all just comes down to **tweaking the $M_{11}, M_{13}, M_{22}, M_{23}$ elements of the matrix** a little with some scaling and offseting that I'm sure you can figure out when looking at how these matrices are constructed. The rest can stay as they are (provided you don't need chunking in the z-direction either, which would be used for different techniques than what you are trying to do)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22833" PostHistoryTypeId="2" PostId="8503" RevisionGUID="9db5f736-d0b7-4b69-81a2-84ce5ea16867" CreationDate="2019-01-20T16:00:53.367" UserId="6496" Text="Greetings &amp; Salutations,&#xD;&#xA;&#xD;&#xA;I departed slightly from the Vulkan tutorial I was following and decided to draw a wireframe instead of a solid triangle.&#xD;&#xA;&#xD;&#xA;As soon as I call vkCreateGraphicsPipelines(), I get the following message from Validation Layer even though the call finishes with VK_SUCCESS.&#xD;&#xA;&gt;*vkCreateGraphicsPipelines parameter, VkPolygonMode pCreateInfos-&gt; pRasterizationState-&gt;polygonMode cannot be VK_POLYGON_MODE_POINT or VK_POLYGON_MODE_LINE if VkPhysicalDeviceFeatures-&gt;fillModeNonSolid is false.*&#xD;&#xA;&#xD;&#xA;For good measure I check the VkPhysicalDeviceFeatures right after I call vkCreateGraphicsPipelines() and fillModeNonSolid is VK_TRUE.&#xD;&#xA;&#xD;&#xA;The output is a wireframe triangle as expected but the message got me worried if I am missing something.&#xD;&#xA; &#xD;&#xA;I am using Nvidia GeForce GTX 1050Ti (driver 417.22), Vulkan 1.1.82.1 on Windows 10(64-bit).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22834" PostHistoryTypeId="1" PostId="8503" RevisionGUID="9db5f736-d0b7-4b69-81a2-84ce5ea16867" CreationDate="2019-01-20T16:00:53.367" UserId="6496" Text="Inconsistent behavior involving VkPhysicalDeviceFeatures-&gt;fillModeNonSolid" ContentLicense="CC BY-SA 4.0" />
  <row Id="22835" PostHistoryTypeId="3" PostId="8503" RevisionGUID="9db5f736-d0b7-4b69-81a2-84ce5ea16867" CreationDate="2019-01-20T16:00:53.367" UserId="6496" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22836" PostHistoryTypeId="4" PostId="8503" RevisionGUID="ad77f6dc-d41d-4314-ae06-d96bc9a4b3cd" CreationDate="2019-01-20T16:13:07.817" UserId="6496" Comment="edited title" Text="Inconsistent behavior involving VkPhysicalDeviceFeatures.fillModeNonSolid" ContentLicense="CC BY-SA 4.0" />
  <row Id="22837" PostHistoryTypeId="5" PostId="8503" RevisionGUID="c804cbf9-8ad8-48c0-9db7-a94bf4a3a64d" CreationDate="2019-01-20T17:57:19.567" UserId="2654" Comment="deleted 7 characters in body" Text="I departed slightly from the Vulkan tutorial I was following and decided to draw a wireframe instead of a solid triangle.&#xD;&#xA;&#xD;&#xA;As soon as I call `vkCreateGraphicsPipelines()`, I get the following message from Validation Layer even though the call finishes with `VK_SUCCESS`.&#xD;&#xA;&gt; `vkCreateGraphicsPipelines` parameter, `VkPolygonMode` `pCreateInfos-&gt; pRasterizationState-&gt;polygonMode` cannot be `VK_POLYGON_MODE_POINT` or `VK_POLYGON_MODE_LINE` if `VkPhysicalDeviceFeatures-&gt;fillModeNonSolid` is false.&#xD;&#xA;&#xD;&#xA;For good measure I check the `VkPhysicalDeviceFeatures` right after I call `vkCreateGraphicsPipelines()` and `fillModeNonSolid` is VK_TRUE.&#xD;&#xA;&#xD;&#xA;The output is a wireframe triangle as expected but the message got me worried if I am missing something.&#xD;&#xA; &#xD;&#xA;I am using Nvidia GeForce GTX 1050Ti (driver 417.22), Vulkan 1.1.82.1 on Windows 10(64-bit).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22838" PostHistoryTypeId="5" PostId="8503" RevisionGUID="ea41e615-ad6b-4f59-aa39-20107486163b" CreationDate="2019-01-20T17:58:57.710" UserId="6496" Comment="added 2 characters in body" Text="I departed slightly from the Vulkan tutorial I was following and decided to draw a wireframe instead of a solid triangle.&#xD;&#xA;&#xD;&#xA;As soon as I call `vkCreateGraphicsPipelines()`, I get the following message from Validation Layer even though the call finishes with `VK_SUCCESS`.&#xD;&#xA;&gt; `vkCreateGraphicsPipelines` parameter, `VkPolygonMode` `pCreateInfos-&gt; pRasterizationState-&gt;polygonMode` cannot be `VK_POLYGON_MODE_POINT` or `VK_POLYGON_MODE_LINE` if `VkPhysicalDeviceFeatures-&gt;fillModeNonSolid` is false.&#xD;&#xA;&#xD;&#xA;For good measure I check the `VkPhysicalDeviceFeatures` right after I call `vkCreateGraphicsPipelines()` and `fillModeNonSolid` is `VK_TRUE`.&#xD;&#xA;&#xD;&#xA;The output is a wireframe triangle as expected but the message got me worried if I am missing something.&#xD;&#xA; &#xD;&#xA;I am using Nvidia GeForce GTX 1050Ti (driver 417.22), Vulkan 1.1.82.1 on Windows 10(64-bit).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22839" PostHistoryTypeId="5" PostId="8503" RevisionGUID="d0defc1d-acce-49a1-87cc-2401b6fc7e2e" CreationDate="2019-01-20T19:15:48.213" UserId="6496" Comment="added 175 characters in body" Text="I departed slightly from the Vulkan tutorial I was following and decided to draw a wireframe instead of a solid triangle.&#xD;&#xA;&#xD;&#xA;As soon as I call `vkCreateGraphicsPipelines()`, I get the following message from Validation Layer even though the call finishes with `VK_SUCCESS`.&#xD;&#xA;&gt; `vkCreateGraphicsPipelines` parameter, `VkPolygonMode` `pCreateInfos-&gt; pRasterizationState-&gt;polygonMode` cannot be `VK_POLYGON_MODE_POINT` or `VK_POLYGON_MODE_LINE` if `VkPhysicalDeviceFeatures-&gt;fillModeNonSolid` is false.&#xD;&#xA;&#xD;&#xA;For good measure I check the `VkPhysicalDeviceFeatures` right after I call `vkCreateGraphicsPipelines()` and `fillModeNonSolid` is `VK_TRUE`.&#xD;&#xA;&#xD;&#xA;The output is a wireframe triangle as expected but the message got me worried if I am missing something.&#xD;&#xA; &#xD;&#xA;I am using Nvidia GeForce GTX 1050Ti (driver 417.22), Vulkan 1.1.82.1 on Windows 10(64-bit).&#xD;&#xA;&#xD;&#xA;PS: I am experiencing similar problem with wideLines feature as well:`VkPhysicalDeviceFeatures` has `wideLines` as `VK_TRUE` but Validation Layer thinks it is set to false&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="22840" PostHistoryTypeId="5" PostId="8444" RevisionGUID="8de3fd83-75d1-4eec-b748-9fffdfb4869d" CreationDate="2019-01-21T00:32:22.050" UserId="6046" Comment="added 9 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS however now I'm getting more fireflies and I think I read that MIS reduces fireflies?. Anyways, I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`.&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter but the fireflies still remain. Note the reflection is harder to converge although its 2500spp while the one below is 1500 spp.&#xD;&#xA;&#xD;&#xA;Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;[![with MIS ][5]][5]&#xD;&#xA;[![Without MIS][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT-MISdebug.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/GYYP1.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/4suBT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22841" PostHistoryTypeId="5" PostId="8499" RevisionGUID="5d7d972b-cc98-435b-afdd-2b439a2ff6b2" CreationDate="2019-01-21T05:35:53.683" UserId="48" Comment="added 96 characters in body" Text="We have $t_{12} = t_{21}$, by [the law of reciprocity](https://computergraphics.stackexchange.com/questions/5286/the-reciprocity-of-brdf). Also, $$r_{12} + t_{12} = 1\\r_{21} + t_{21} = 1$$&#xD;&#xA;It follows that $r_{12} = r_{21}$ as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="22842" PostHistoryTypeId="4" PostId="8495" RevisionGUID="6888dadd-d4c0-46fa-9dae-a699beef1653" CreationDate="2019-01-21T08:48:52.040" UserId="209" Comment="minor spelling correction" Text="Bump mapping with triangles and height maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="22843" PostHistoryTypeId="5" PostId="8479" RevisionGUID="d4cace2e-209e-4403-a350-94413e21e2c0" CreationDate="2019-01-21T08:52:08.780" UserId="9881" Comment="deleted 11 characters in body" Text="In [ray-tracing][1] technique critical point is to calculate rays which came out from eye $E$ to target $T$ through pixel $P_{ij}$ on viewport. The &quot;viewport&quot; is represented as rectangle divided to square pixels - this rectangle is perpendicular to line which go through points $E$, $C$ (viewport center) and $T$. The ray (red line on image) is represented by point $E$ and unit  vector $r_{ij}$ (not shown in picture but it lay on red line) - below is picture which show &quot;geometry&quot; - but what are the formulas to calculate $r_{ij}$? &#xD;&#xA;&#xD;&#xA;The given input values are: &#xD;&#xA;&#xD;&#xA;* eye position $E$, &#xD;&#xA;* target position $T$, &#xD;&#xA;* field of view $\theta$ (angle, for human eye $\approx 90^\circ$), &#xD;&#xA;* number of square pixels $k$ (horizontal direction) and $m$ (vertical direction).&#xD;&#xA;* $i,j$ processed pixel indexes where $1\leq i\leq k$ and $1\leq j\leq m$   &#xD;&#xA;* we also know vertical $w$ vector usually equal to $w=[wx,wy,wz]=[0,1,0]$ (not shown on picture) which indicate where is up and where is down &#xD;&#xA;&#xD;&#xA;The orthogonal vectors $v$ and $b$  (and $t$) on picture are determined by $w$ and $t=T-E$ and maybe will useful in $r_{ij}$ calculations. The $d$ and pixel size is arbitrary and don't change the result because of fixed $\theta$. &#xD;&#xA;&#xD;&#xA;**Question**: How to calculate unit vector $r_{ij}$ knowing input values described above?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&#xD;&#xA;  [2]: https://i.stack.imgur.com/PKrBi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22844" PostHistoryTypeId="5" PostId="8491" RevisionGUID="563e1d19-3ad2-45ce-8078-db042ccbdcdd" CreationDate="2019-01-21T11:03:30.923" UserId="6046" Comment="added 1836 characters in body" Text="Read up on the basics for ray-tracing [here][1],&#xD;&#xA;&#xD;&#xA;Usually we don't mess up with viewports and stuff in raytracing, So I'm just telling you for the case where viewport equals the Image Width and Height.&#xD;&#xA;&#xD;&#xA;There are two cases when the field of view changes. Either you move the image plane back and forth or you increase the size. We choose to change $d$ ( former approach). &#xD;&#xA;&#xD;&#xA;Calculating ray is simple when the camera is aligned with the world, all you have to do is&#xD;&#xA;&#xD;&#xA;$d = 1/tan(\theta_{fov}/2))$&#xD;&#xA;&#xD;&#xA;$P_x = P_x + 0.5$  &#xD;&#xA;$P_y = P_y + 0.5$&#xD;&#xA;&#xD;&#xA;$aspect\_ratio = width/height$&#xD;&#xA;&#xD;&#xA;$ray.dir.x = aspect\_ratio *(2*P_x/width) -1$&#xD;&#xA;&#xD;&#xA;$ray.dir.y = (2*P_y/height) - 1$&#xD;&#xA;&#xD;&#xA;$ray.dir.z = d$&#xD;&#xA;&#xD;&#xA;The $Z$ coordinate should be negative or positive depending on whether you are using a right handed or left handed coordinate system. $P_x$ and $P_y$ are pixel coordinates offset by $0.5$ to get the center of the pixel.&#xD;&#xA;&#xD;&#xA;The process is simple. You first map your image to NDC space (-1, 1). However to account for non-square images we scale the $X$ coordinate by Aspect ratio so it's $[-a, a]$ in $X$ and $[-1,1]$ in Y. The ray's direction through the pixel is then given by above formulas. You might have to flip the $Y$ coordinate if the image coordinate's origin is top left instead of bottom left.&#xD;&#xA;&#xD;&#xA;Note however the link bases all their coordinate systems and space names on RenderMan which is quite different from OpenGL. For camera that isn't aligned with the world coordinate you have to multiply by the transformation matrix as described by bernie in his answer&#xD;&#xA;&#xD;&#xA;EDIT:-&#xD;&#xA;&#xD;&#xA;First of all let's clear up on -ve and +ve $d$. For right handed coordinate systems you always set $ray.dir.z = -d$ and for left handed $ray.dir.z = d$ This is because in camera space there is no concept of half rays having -ve Z and half +ve, that happens in world space. When you multiply by the transformation matrix it takes care of these cases for you since the transformation matrix is designed keeping in mind whether you are working on a left handed or right handed system. I know i said that you always set it to +ve $d$ but i was wrong in the comments, sorry.&#xD;&#xA;&#xD;&#xA;Now coming to your other question. You need the vectors $b,v,t$ and $E$ for creating a transformation matrix. Usually in raytracing you create your camera and initialize its transformation matrix to the standard case (aligned with world space) Then when you move your mouse or something you create a respective rotation matrix and transform the original camera matrix to keep up with these changes. Then when calculating the ray you multiply it as I said above to get ray direction easily. So you probably need to manage your own Camera first.&#xD;&#xA;&#xD;&#xA;Since you aren't managing in this case you explicitly need to find these vectors. You mention you have the $w$ vector which is global up. $t$ is easy to find as you say&#xD;&#xA;&#xD;&#xA;$t = T-E$&#xD;&#xA;&#xD;&#xA;However remember this is the viewing direction not the basis vector. For right handed coordinate systems, the basis vector for $Z$ is $-V_{dir}$&#xD;&#xA;&#xD;&#xA;For $b$ which is Camera's right vector. You do,&#xD;&#xA;$ w \times t = b$&#xD;&#xA;&#xD;&#xA;This gets you the Camera's up vector. Then you do,&#xD;&#xA;&#xD;&#xA;$ t \times b = v$&#xD;&#xA;&#xD;&#xA;to get the Camera's up vector. This works as long as $t$ doesn't equal $w$ which is the global up.&#xD;&#xA;&#xD;&#xA;So after you have these you can create a camera transformation matrix with $c_1, c_2, c_3, c_4 = b, v, t, E$ respectively.&#xD;&#xA;  [1]: http://www.scratchapixel.com/index.php?redirect" ContentLicense="CC BY-SA 4.0" />
  <row Id="22845" PostHistoryTypeId="5" PostId="8491" RevisionGUID="cea5610b-9e59-4184-916e-007769fd4d0e" CreationDate="2019-01-21T11:18:34.597" UserId="6046" Comment="added 356 characters in body" Text="Read up on the basics for ray-tracing [here][1],&#xD;&#xA;&#xD;&#xA;Usually we don't mess up with viewports and stuff in raytracing, So I'm just telling you for the case where viewport equals the Image Width and Height.&#xD;&#xA;&#xD;&#xA;There are two cases when the field of view changes. Either you move the image plane back and forth or you increase the size. We choose to change $d$ ( former approach). &#xD;&#xA;&#xD;&#xA;Calculating ray is simple when the camera is aligned with the world, all you have to do is&#xD;&#xA;&#xD;&#xA;$d = 1/tan(\theta_{fov}/2))$&#xD;&#xA;&#xD;&#xA;$P_x = P_x + 0.5$  &#xD;&#xA;$P_y = P_y + 0.5$&#xD;&#xA;&#xD;&#xA;$aspect\_ratio = width/height$&#xD;&#xA;&#xD;&#xA;$ray.dir.x = aspect\_ratio *(2*P_x/width) -1$&#xD;&#xA;&#xD;&#xA;$ray.dir.y = (2*P_y/height) - 1$&#xD;&#xA;&#xD;&#xA;$ray.dir.z = d$&#xD;&#xA;&#xD;&#xA;The $Z$ coordinate should be negative or positive depending on whether you are using a right handed or left handed coordinate system. $P_x$ and $P_y$ are pixel coordinates offset by $0.5$ to get the center of the pixel.&#xD;&#xA;&#xD;&#xA;The process is simple. You first map your image to NDC space (-1, 1). However to account for non-square images we scale the $X$ coordinate by Aspect ratio so it's $[-a, a]$ in $X$ and $[-1,1]$ in Y. The ray's direction through the pixel is then given by above formulas. You might have to flip the $Y$ coordinate if the image coordinate's origin is top left instead of bottom left.&#xD;&#xA;&#xD;&#xA;Note however the link bases all their coordinate systems and space names on RenderMan which is quite different from OpenGL. For camera that isn't aligned with the world coordinate you have to multiply by the transformation matrix as described by bernie in his answer&#xD;&#xA;&#xD;&#xA;EDIT:-&#xD;&#xA;&#xD;&#xA;First of all let's clear up on -ve and +ve $d$. For right handed coordinate systems you always set $ray.dir.z = -d$ and for left handed $ray.dir.z = d$ This is because in camera space there is no concept of half rays having -ve Z and half +ve, that happens in world space. When you multiply by the transformation matrix it takes care of these cases for you since the transformation matrix is designed keeping in mind whether you are working on a left handed or right handed system. I know i said that you always set it to +ve $d$ but i was wrong in the comments, sorry.&#xD;&#xA;&#xD;&#xA;Now coming to your other question. You need the vectors $b,v,t$ and $E$ for creating a transformation matrix. Usually in raytracing you create your camera and initialize its transformation matrix to the standard case (aligned with world space) Then when you move your mouse or something you create a respective rotation matrix and transform the original camera matrix to keep up with these changes. Then when calculating the ray you multiply it as I said above to get ray direction easily. So you probably need to manage your own Camera first.&#xD;&#xA;&#xD;&#xA;Since you aren't managing in this case you explicitly need to find these vectors. You mention you have the $w$ vector which is global up. $t$ is easy to find as you say&#xD;&#xA;&#xD;&#xA;$t = T-E$&#xD;&#xA;&#xD;&#xA;However remember this is the viewing direction not the basis vector. For right handed coordinate systems, the basis vector for $Z$ is $-V_{dir}$&#xD;&#xA;&#xD;&#xA;For $b$ which is Camera's right vector. You do,&#xD;&#xA;$ w \times t = b$&#xD;&#xA;&#xD;&#xA;This gets you the Camera's up vector. Then you do,&#xD;&#xA;&#xD;&#xA;$ t \times b = v$&#xD;&#xA;&#xD;&#xA;to get the Camera's up vector. This works as long as $t$ doesn't equal $w$ which is the global up.&#xD;&#xA;&#xD;&#xA;So after you have these you can create a camera transformation matrix with $c_1, c_2, c_3, c_4 = b, v, t, E$ respectively.&#xD;&#xA;&#xD;&#xA;EDIT2:-&#xD;&#xA;Instead of following above approach you can also do Gram-Schmidt orthogonalization which is more standard in this case. Using this you get the Camera's up vector $v$ as&#xD;&#xA;&#xD;&#xA;$v = w - (t.w)\hat{t}$&#xD;&#xA;&#xD;&#xA;Then side vector as,&#xD;&#xA;&#xD;&#xA;$b = v \times t$ &#xD;&#xA;&#xD;&#xA;For right handed systems. For left handed systems you need to change the ordering of cross products.&#xD;&#xA;  [1]: http://www.scratchapixel.com/index.php?redirect" ContentLicense="CC BY-SA 4.0" />
  <row Id="22846" PostHistoryTypeId="2" PostId="8504" RevisionGUID="1894672b-3e25-40ad-beee-a908b62c591c" CreationDate="2019-01-21T12:37:59.227" UserId="9881" Text="**Idea**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**Assumption**: $d=1$ which simplify calculations but not change the result (viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**Precalculations**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} = \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ p = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Final calculations**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + p(i-1) + q(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/8491/9881" ContentLicense="CC BY-SA 4.0" />
  <row Id="22847" PostHistoryTypeId="5" PostId="8504" RevisionGUID="c477db0e-dc5b-420b-a434-50c2136bd39b" CreationDate="2019-01-21T12:52:50.070" UserId="9881" Comment="added 1 character in body" Text="**Idea**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**Assumption**: $d=1$ which simplify calculations but not change the result (viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**Precalculations**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2}\frac{1}{d} = \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2}\frac{1}{d} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ p = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Final calculations**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + p(i-1) + q(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/8491/9881" ContentLicense="CC BY-SA 4.0" />
  <row Id="22849" PostHistoryTypeId="5" PostId="8504" RevisionGUID="e83fa400-ecc4-4bd5-81e1-74b24b901875" CreationDate="2019-01-21T12:59:39.203" UserId="9881" Comment="deleted 21 characters in body" Text="**Idea**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**Assumption**: $d=1$ which simplify calculations but not change the result (viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**Precalculations**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ p = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Final calculations**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + p(i-1) + q(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/8491/9881" ContentLicense="CC BY-SA 4.0" />
  <row Id="22850" PostHistoryTypeId="5" PostId="8504" RevisionGUID="c3413407-917c-42b4-9000-d05543ac3a4a" CreationDate="2019-01-21T13:14:00.620" UserId="9881" Comment="added 79 characters in body" Text="**Idea**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**Assumption**: $d=1$ which simplify calculations but not change the result (viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**Precalculations**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ p = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Final calculations**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + p(i-1) + q(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**Test**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22851" PostHistoryTypeId="2" PostId="8505" RevisionGUID="c14acc25-f9d7-4241-9a6c-b4cf4192495e" CreationDate="2019-01-21T13:20:04.613" UserId="2960" Text="I'm trying to write my own spectral path tracer and a bit stuck with converting computed SPDs to LDR RGB values. What I'm doing right now is convert SPDs to XYZ using CIE 1931 color matching functions, then XYZ to xyY (i.e. chromaticity and luminance), normalise luminance to be in [0, 1] range across the whole image (for now by dividing my max luminance just to keep it simple, tried Reinhard tone mapping to the same result), then back to XYZ, than to linear RGB (wia [this][1] transform). After that I still get RGB values outside of [0..1]. What am I doing wrong? It seems that &quot;max&quot; luminance should depend on chromaticities of the color. Are there an algorithm to account for that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_(CIE_XYZ_to_sRGB)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22852" PostHistoryTypeId="1" PostId="8505" RevisionGUID="c14acc25-f9d7-4241-9a6c-b4cf4192495e" CreationDate="2019-01-21T13:20:04.613" UserId="2960" Text="Computing sRGB color from SPDs" ContentLicense="CC BY-SA 4.0" />
  <row Id="22853" PostHistoryTypeId="3" PostId="8505" RevisionGUID="c14acc25-f9d7-4241-9a6c-b4cf4192495e" CreationDate="2019-01-21T13:20:04.613" UserId="2960" Text="|color|spectral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22854" PostHistoryTypeId="5" PostId="8493" RevisionGUID="bf6bacd3-59b3-43e1-914a-d6d3c1885a83" CreationDate="2019-01-21T13:43:30.953" UserId="7724" Comment="edited body" Text="Subdivision can be used for curves in 2D just as easily as for surfaces in 3D. Usually the subdivision algorithms applied to 2D are called subdivision curves. Subdivision curves do not suffer from the problem that subdivision surfaces have around extraordinary points and therefore all subdivision surfaces can easily be converted to (uniform) B-splines. This means that it equals to working with Bézier curves in most cases. This latter representation might be more advantageous as it possesses a closed form representation, such that curves can be evaluated easily at arbitrary parameter values.&#xD;&#xA;&#xD;&#xA;A simple subdivision algorithm for curves is the following. Consider a polyline consisting out of $n$ points $P_0 \ldots P_{n-1}$. Than for every iteration do the following steps:&#xD;&#xA;&#xD;&#xA;Every exisiting position $P_i =&gt; (P_{i-1} + 6 P_{i} + P_{i+1})/8$ then add new positions on every edge between existing points using $(4 P_i + 4 P_{i+1})/8$ and repeat. In the limit this procedure will converge to uniform cubic B-splines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some useful extensions for subdivison curves exists such as [(semi-sharp) creases and boundary conditions][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.rug.nl/research/portal/files/50538260/Creases_and_boundary_conditions.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="22855" PostHistoryTypeId="5" PostId="8504" RevisionGUID="e59a2650-fc73-4fd7-9cfc-00e76a30d659" CreationDate="2019-01-21T13:48:14.117" UserId="9881" Comment="added 35 characters in body" Text="**Idea**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**Assumption**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**Precalculations**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ p = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Final calculations**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + p(i-1) + q(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**Test**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22856" PostHistoryTypeId="5" PostId="8504" RevisionGUID="8d418bb8-a6f2-40f5-b959-03d2145d455c" CreationDate="2019-01-21T13:59:56.630" UserId="9881" Comment="added 8 characters in body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convinient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{11}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22857" PostHistoryTypeId="5" PostId="8504" RevisionGUID="971535d6-5f89-41a9-b169-5cacf0049080" CreationDate="2019-01-21T14:04:57.750" UserId="9881" Comment="added 8 characters in body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = b_n\times t_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n + g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{11}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22861" PostHistoryTypeId="2" PostId="8507" RevisionGUID="d77a57eb-ca48-4390-96b3-ca0d69ee2aef" CreationDate="2019-01-21T18:17:43.947" UserId="9793" Text="I have a SVG with group of independent arcs that move around common origin.&#xD;&#xA;On user event those arcs can change both their radii and start/end angles.&#xD;&#xA;On other user event the user can change view from 2d to fake 3d (orthographic?) via following css transform, as described [here][1]:&#xD;&#xA;&#xD;&#xA;    translate(0px, ${t*5 - i*t*40}px)&#xD;&#xA;    rotateX(${t*60}deg)&#xD;&#xA;    rotateZ(${t*-30}deg)&#xD;&#xA;    scale(1.0)&#xD;&#xA;&#xD;&#xA;`t` is a boolean flag telling if perspective view is on or off, if flag = 0 then no actual transformation is made.&#xD;&#xA;&#xD;&#xA;My code that illustrate the example can be viewed here: &#xD;&#xA;https://codepen.io/stopyransky/pen/MZPbjg&#xD;&#xA;&#xD;&#xA;Once you click button to trigger perspective view it changes correctly, but arc transitions (radii/angle) are now messed up. &#xD;&#xA;&#xD;&#xA;My question is how to fix so the transitions of arcs will remain correct? &#xD;&#xA;I assume I need to modify the functions that change how arc is build in `tweenAngles` and `tweenRadii` but I have no clue what those transitions should be. I tried to reverse transitions when flag is 0 but it does not help.&#xD;&#xA;&#xD;&#xA;  [1]: https://beta.observablehq.com/d/190a4518cada1873" ContentLicense="CC BY-SA 4.0" />
  <row Id="22862" PostHistoryTypeId="1" PostId="8507" RevisionGUID="d77a57eb-ca48-4390-96b3-ca0d69ee2aef" CreationDate="2019-01-21T18:17:43.947" UserId="9793" Text="Transforming arcs and perspective change" ContentLicense="CC BY-SA 4.0" />
  <row Id="22863" PostHistoryTypeId="3" PostId="8507" RevisionGUID="d77a57eb-ca48-4390-96b3-ca0d69ee2aef" CreationDate="2019-01-21T18:17:43.947" UserId="9793" Text="|transformations|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22871" PostHistoryTypeId="50" PostId="8417" RevisionGUID="910d6330-ec30-4546-b5b2-e486b58ff848" CreationDate="2019-01-22T18:01:11.247" UserId="-1" />
  <row Id="22872" PostHistoryTypeId="2" PostId="8510" RevisionGUID="02ec7a91-9aee-425c-b657-dddaa78bd04e" CreationDate="2019-01-23T02:45:43.430" UserId="110" Text="The Unity Engine manual page [Best Practice: Setting up the Lighting Pipeline][1] has a section &quot;Render pipelines&quot; with an illustration of Tile Rendering and Cluster Rendering:  &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The section then mentions:  &#xD;&#xA;&#xD;&#xA;&gt; Opaque objects will most likely be shaded using the tile system,&#xD;&#xA;&gt; whereas transparent ones will rely on the cluster system.&#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;What is the benefit of using Clustered Shading with transparent objects? Is it related to performance, or are transparent objects not supported by Tiled Shading?  &#xD;&#xA;&#xD;&#xA;Why opaque objects will &quot;not likely&quot; be rendered with Clustered Shading?&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unity3d.com/Manual/BestPracticeLightingPipelines.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/tpMCt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22873" PostHistoryTypeId="1" PostId="8510" RevisionGUID="02ec7a91-9aee-425c-b657-dddaa78bd04e" CreationDate="2019-01-23T02:45:43.430" UserId="110" Text="Benefits of Clustered Shading vs Tiled Shading?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22874" PostHistoryTypeId="3" PostId="8510" RevisionGUID="02ec7a91-9aee-425c-b657-dddaa78bd04e" CreationDate="2019-01-23T02:45:43.430" UserId="110" Text="|real-time|transparency|unity|tile-based-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22875" PostHistoryTypeId="2" PostId="8511" RevisionGUID="a2e30acc-3aa5-4963-87c5-39b42fad6704" CreationDate="2019-01-23T09:52:13.957" UserId="7644" Text="Both Unity's &quot;[Deferred shading rendering path][1]&quot; and &quot;[Legacy Deferred Lighting Rendering Path][2]&quot; work only for opaque surfaces. They both rely on a very similar set of passes:&#xD;&#xA;&#xD;&#xA;1. Render the opaque objects' lighting parameters to a number of render targets. This is referred to as the &quot;G-Buffer pass&quot; or &quot;base pass&quot;.&#xD;&#xA;2. Lighting is then computed in screen-space using the buffers of the first pass to compute lighting. The main benefit is that the cost of lighting is independent of scene complexity. This allows for much more complicated lighting equations with a greater number of lights.&#xD;&#xA;3. Full-screen pass to resolve all these buffers to a final color.&#xD;&#xA;&#xD;&#xA;The reason this doesn't work for transparent objects is that they must be rendered back to front *completely shaded* (lighting and all). If transparent object A is in front of transparent object B, B must be completely shaded when A blends its color with B. We need that final shaded color because the lighting parameters accumulated in G-Buffers cannot be blended.&#xD;&#xA;&#xD;&#xA;So, if you can use it (there are downsides), deferred shading has some very nice properties that produce very good results with good performance. That is why opaque objects will &quot;likely&quot; use deferred shading.&#xD;&#xA;&#xD;&#xA;I wasn't able to find much information about Unity's clustered rendering. From what I gather it's an optimization technique for forward rendering, but it's still fundamentally the same process. Here's a very nice write-up of [how it works in Doom][3] (go to the &quot;Clustered-Forward-Rendering of Opaque Objects&quot; section).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unity3d.com/Manual/RenderTech-DeferredShading.html&#xD;&#xA;  [2]: https://docs.unity3d.com/Manual/RenderTech-DeferredLighting.html&#xD;&#xA;  [3]: http://www.adriancourreges.com/blog/2016/09/09/doom-2016-graphics-study/" ContentLicense="CC BY-SA 4.0" />
  <row Id="22877" PostHistoryTypeId="5" PostId="8511" RevisionGUID="5ed6e8ce-64fd-4416-98e5-7dbafc07b945" CreationDate="2019-01-23T12:27:42.260" UserId="7644" Comment="Add quote" Text="Both Unity's &quot;[Deferred shading rendering path][1]&quot; and &quot;[Legacy Deferred Lighting Rendering Path][2]&quot; work only for opaque surfaces. They both rely on a very similar set of passes:&#xD;&#xA;&#xD;&#xA;1. Render the opaque objects' lighting parameters to a number of render targets. This is referred to as the &quot;G-Buffer pass&quot; or &quot;base pass&quot;.&#xD;&#xA;2. Lighting is then computed in screen-space using the buffers of the first pass to compute lighting. The main benefit is that the cost of lighting is independent of scene complexity. This allows for much more complicated lighting equations with a greater number of lights.&#xD;&#xA;3. Full-screen pass to resolve all these buffers to a final color.&#xD;&#xA;&#xD;&#xA;The reason this doesn't work for transparent objects is that they must be rendered back to front *completely shaded* (lighting and all). If transparent object A is in front of transparent object B, B must be completely shaded when A blends its color with B. We need that final shaded color because the lighting parameters accumulated in G-Buffers cannot be blended.&#xD;&#xA;&#xD;&#xA;So, if you can use it (there are downsides), deferred shading has some very nice properties that produce very good results with good performance. That is why opaque objects will &quot;likely&quot; use deferred shading. Quoting from Unity doc:&#xD;&#xA;&#xD;&#xA;&gt; When using deferred shading, there is no limit on the number of lights that can affect a GameObject. All lights are evaluated per-pixel, which means that they all interact correctly with normal maps, etc. Additionally, all lights can have cookies and shadows.&#xD;&#xA;&gt; &#xD;&#xA;&gt; Deferred shading has the advantage that the processing overhead of lighting is proportional to the number of pixels the light shines on. This is determined by the size of the light volume in the Scene regardless of how many GameObjects it illuminates. Therefore, performance can be improved by keeping lights small. Deferred shading also has highly consistent and predictable behaviour. The effect of each light is computed per-pixel, so there are no lighting computations that break down on large triangles.&#xD;&#xA;&#xD;&#xA;I wasn't able to find much information about Unity's clustered rendering. From what I gather it's an optimization technique for forward rendering, but it's still fundamentally the same process. Here's a very nice write-up of [how it works in Doom][3] (go to the &quot;Clustered-Forward-Rendering of Opaque Objects&quot; section).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unity3d.com/Manual/RenderTech-DeferredShading.html&#xD;&#xA;  [2]: https://docs.unity3d.com/Manual/RenderTech-DeferredLighting.html&#xD;&#xA;  [3]: http://www.adriancourreges.com/blog/2016/09/09/doom-2016-graphics-study/" ContentLicense="CC BY-SA 4.0" />
  <row Id="22878" PostHistoryTypeId="5" PostId="8505" RevisionGUID="56778cd3-259f-4b20-b413-93a780d3468c" CreationDate="2019-01-23T12:32:48.840" UserId="2960" Comment="deleted 1 character in body" Text="I'm trying to write my own spectral path tracer and a bit stuck with converting computed SPDs to LDR RGB values. What I'm doing right now is convert SPDs to XYZ using CIE 1931 color matching functions, then XYZ to xyY (i.e. chromaticity and luminance), normalise luminance to be in [0, 1] range across the whole image (for now by dividing my max luminance just to keep it simple, tried Reinhard tone mapping to the same result), then back to XYZ, than to linear RGB (wia [this][1] transform). After that I still get RGB values outside of [0..1]. What am I doing wrong? It seems that &quot;max&quot; luminance should depend on chromaticities of the color. Is there an algorithm to account for that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_(CIE_XYZ_to_sRGB)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22879" PostHistoryTypeId="5" PostId="8479" RevisionGUID="d8a20cf5-ebfd-462f-b742-ae2169cd84e9" CreationDate="2019-01-23T12:44:21.030" UserId="9881" Comment="edited body" Text="In [ray-tracing][1] technique critical point is to calculate rays which came out from eye $E$ to target $T$ through pixel $P_{ij}$ on viewport. The &quot;viewport&quot; is represented as rectangle divided to square pixels - this rectangle is perpendicular to line which go through points $E$, $C$ (viewport center) and $T$. The ray (red line on image) is represented by point $E$ and unit  vector $r_{ij}$ (not shown in picture but it lay on red line) - below is picture which show &quot;geometry&quot; - but what are the formulas to calculate $r_{ij}$? &#xD;&#xA;&#xD;&#xA;The given input values are: &#xD;&#xA;&#xD;&#xA;* eye position $E$, &#xD;&#xA;* target position $T$, &#xD;&#xA;* field of view $\theta$ (angle, for human eye $\approx 90^\circ$), &#xD;&#xA;* number of square pixels $k$ (horizontal direction) and $m$ (vertical direction).&#xD;&#xA;* $i,j$ processed pixel indexes where $1\leq i\leq k$ and $1\leq j\leq m$   &#xD;&#xA;* we also know vertical $w$ vector usually equal to $w=[wx,wy,wz]=[0,1,0]$ (not shown on picture) which indicate where is up and where is down &#xD;&#xA;&#xD;&#xA;The orthogonal vectors $v$ and $b$  (and $t$) on picture are determined by $w$ and $t=T-E$ and maybe will useful in $r_{ij}$ calculations. The $d$ and pixel size is arbitrary and don't change the result because of fixed $\theta$. &#xD;&#xA;&#xD;&#xA;**Question**: How to calculate unit vector $r_{ij}$ knowing input values described above?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)&#xD;&#xA;  [2]: https://i.stack.imgur.com/aUdHD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22880" PostHistoryTypeId="5" PostId="8504" RevisionGUID="03b202cf-c56c-4919-b091-de4d19fba6e5" CreationDate="2019-01-23T12:45:02.297" UserId="9881" Comment="edited body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_n$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{11}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22881" PostHistoryTypeId="5" PostId="8504" RevisionGUID="1a58ce1c-ebfb-4cdf-a6bb-35915b946ef4" CreationDate="2019-01-23T14:52:11.740" UserId="9881" Comment="added 2 characters in body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{11}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{11} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{11} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{11}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22882" PostHistoryTypeId="5" PostId="8504" RevisionGUID="72cd0982-b47e-4cd3-820d-f2f56506ce17" CreationDate="2019-01-23T16:59:45.790" UserId="9881" Comment="edited body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{1m}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $p,q$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{1m} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{1m} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{11}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22884" PostHistoryTypeId="5" PostId="8504" RevisionGUID="ba687278-73ab-45e5-b5ec-39638ac597e5" CreationDate="2019-01-23T17:26:13.693" UserId="9881" Comment="added 4 characters in body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{1m}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $q_x,q_y$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{1m} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{1m} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{11}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22885" PostHistoryTypeId="5" PostId="8504" RevisionGUID="bd74c12a-1c5f-4cc0-942e-26d3c8b5e60a" CreationDate="2019-01-23T20:42:52.373" UserId="9881" Comment="edited body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{1m}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: $d=1$ which simplify calculations but not change the result (because $r_{ij}$ is normalized and viewport size is determined by $k,m$ and $\theta$) &#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $q_x,q_y$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{1m} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{1m} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{1m}$&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="22894" PostHistoryTypeId="5" PostId="8504" RevisionGUID="b5adc530-ce8a-4de9-b65a-1dbe96f285ca" CreationDate="2019-01-24T10:29:50.660" UserId="9881" Comment="added 120 characters in body" Text="**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{1m}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: Below we introduce formulas which includes distance $d$ between eye and viewport however this value will be reduced during ray $r_{ij}$ normalization (so you might as well accept that $d=1$ and remove it from calculations).&#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $q_x,q_y$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{1m} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{1m} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [here][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{1m}$. Wiki [here][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)#Calculate_rays_for_rectangular_viewport" ContentLicense="CC BY-SA 4.0" />
  <row Id="22895" PostHistoryTypeId="5" PostId="8505" RevisionGUID="90d0c29e-4ab6-4e0c-987d-2018703df09f" CreationDate="2019-01-24T10:52:13.563" UserId="2960" Comment="Added a bunch of code to clarify what I've tried so far." Text="I'm trying to write my own spectral path tracer and a bit stuck with converting computed SPDs to LDR RGB values. What I'm doing right now is convert sampled SPDs (in `W/m^-1`) to XYZ using CIE 1931 color matching functions:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;Vec3 xyz(0, 0, 0);&#xD;&#xA;float norm = 0;&#xD;&#xA;&#xD;&#xA;for (int i = 0; i &lt; SPD_SAMPLE_COUNT; ++i) {&#xD;&#xA;    const float wavelength =&#xD;&#xA;        lerp(MIN_WAVELENGTH, MAX_WAVELENGTH, i / SPD_SAMPLE_COUNT);&#xD;&#xA;    const Vec3 cieMatchingFunctionValue = cie1931(wavelength);&#xD;&#xA;    xyz += cieMatchingFunctionValue * spd[i];&#xD;&#xA;    norm += cieMatchingFunctionValue.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;xyz /= norm;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here implementation of `cie1931` is an anylitic approximation from [Wyman et al][1].&#xD;&#xA;&#xD;&#xA;Then XYZ to xyY (i.e. chromaticity and luminance), normalise luminance to be in [0, 1] range across the whole image (for now by dividing my max luminance just to keep it simple):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float maxLuminance = 0;&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    maxLuminance = std::max(maxLuminance, xyz.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    Vec2 chromaticity = Vec2(xyz.x, xyz.y) / (xyz.x + xyz.y + xyz.z);&#xD;&#xA;    float luminance = xyz.y / maxLuminance;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Also I've tried Reinhard tone mapping operator:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float logSum = 0;&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    logSum += std::log(xyz.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float logAvgLuminance = std::exp(logSum / image.size());&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    Vec2 chromaticity = Vec2(xyz.x, xyz.y) / (xyz.x + xyz.y + xyz.z);&#xD;&#xA;    const float a = 0.18; // constant from Reinhard's paper.&#xD;&#xA;    float luminance = a * xyz.y / logAvgLuminance;&#xD;&#xA;    luminance /= luminance + 1;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then back to XYZ, than to linear RGB (wia [this][2] transform):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;Vec3 scaledXyz(&#xD;&#xA;    chromaticity.x * luminance / chromaticity.y,&#xD;&#xA;    luminance,&#xD;&#xA;    (1 - chromaticity.x - chromaticity.y) * luminance / chromaticity.y&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;float r = dot(Vec3( 3.2406, -1.5372, -0.4986), scaledXyz);&#xD;&#xA;float g = dot(Vec3(-0.9689,  1.8758,  0.0415), scaledXyz);&#xD;&#xA;float b = dot(Vec3( 0.0557, -0.2040,  1.0570), scaledXyz);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;After that I still get RGB values outside of [0..1]. What am I doing wrong? It seems that &quot;max&quot; luminance should depend on chromaticities of the color. Is there an algorithm to account for that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0002/02/01/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_(CIE_XYZ_to_sRGB)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22896" PostHistoryTypeId="50" PostId="8422" RevisionGUID="f100a33a-11d4-4afd-9cc5-960e9aa95a78" CreationDate="2019-01-24T20:01:15.220" UserId="-1" />
  <row Id="22898" PostHistoryTypeId="2" PostId="8515" RevisionGUID="65337a55-23c6-4e78-9510-fd8f8f292b67" CreationDate="2019-01-25T10:54:30.140" UserId="6046" Text="So I wanted to know how do Game Engines like Unity3D and Unreal do lighting. I'm familiar with Ray-tracing, pathtracing based renderers etc. But not much with rasterization based engines. I do know a general overview of OpenGL's pipeline and things like vertex and fragment shaders but I don't know how exactly the color is computed. &#xD;&#xA;&#xD;&#xA;I'm guessing Rasterization based pipelines use the same procedure for shading i.e. A ray is shot from the pixel and then from the triangle that got projected on that pixel to the light source?&#xD;&#xA;&#xD;&#xA;For indirect lighting they use things like ambient occlusion I guess. Am I correct?&#xD;&#xA;&#xD;&#xA;If this is true then the only difference between rasterization and pathtracing would be the procedure for Visible Surface Determination and Indirect Illumination. Direct Illumination would be calculated the same way in both techniques?&#xD;&#xA;&#xD;&#xA;If you can provide a brief overview of the current state of the art techniques used in these engines for things like reflection/shadows etc it'd be appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="22899" PostHistoryTypeId="1" PostId="8515" RevisionGUID="65337a55-23c6-4e78-9510-fd8f8f292b67" CreationDate="2019-01-25T10:54:30.140" UserId="6046" Text="How is lighting done in Rasterization based pipeline?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22900" PostHistoryTypeId="3" PostId="8515" RevisionGUID="65337a55-23c6-4e78-9510-fd8f8f292b67" CreationDate="2019-01-25T10:54:30.140" UserId="6046" Text="|lighting|shading|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22902" PostHistoryTypeId="5" PostId="8505" RevisionGUID="3fe75b33-b990-4c54-8cbb-76a676eefd63" CreationDate="2019-01-25T12:19:38.787" UserId="2960" Comment="Tried to clarify the code a little bit more" Text="I'm trying to write my own spectral path tracer and a bit stuck with converting computed SPDs to LDR RGB values. What I'm doing right now is convert sampled SPDs (in `W/m^-1`) to XYZ using CIE 1931 color matching functions:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;Vec3 xyz(0, 0, 0);&#xD;&#xA;float norm = 0;&#xD;&#xA;&#xD;&#xA;for (int i = 0; i &lt; SPD_SAMPLE_COUNT; ++i) {&#xD;&#xA;    const float wavelength =&#xD;&#xA;        lerp(MIN_WAVELENGTH, MAX_WAVELENGTH, i / SPD_SAMPLE_COUNT);&#xD;&#xA;    const Vec3 cieMatchingFunctionValue = cie1931(wavelength);&#xD;&#xA;    xyz += cieMatchingFunctionValue * spd[i];&#xD;&#xA;    norm += cieMatchingFunctionValue.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;xyz /= norm;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here implementation of `cie1931` is an anylitic approximation from [Wyman et al][1].&#xD;&#xA;&#xD;&#xA;Then XYZ to xyY (i.e. chromaticity and luminance), normalise luminance to be in [0, 1] range across the whole image (for now by dividing my max luminance just to keep it simple):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float maxLuminance = 0;&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    maxLuminance = std::max(maxLuminance, xyz.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    Vec2 chromaticity = Vec2(xyz.x, xyz.y) / (xyz.x + xyz.y + xyz.z);&#xD;&#xA;    float luminance = xyz.y / maxLuminance;&#xD;&#xA;&#xD;&#xA;    // then to &quot;scaled&quot; XYZ and RGB, see below&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Also I've tried Reinhard tone mapping operator:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float logSum = 0;&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    logSum += std::log(xyz.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float logAvgLuminance = std::exp(logSum / image.size());&#xD;&#xA;&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    Vec2 chromaticity = Vec2(xyz.x, xyz.y) / (xyz.x + xyz.y + xyz.z);&#xD;&#xA;    const float a = 0.18; // constant from Reinhard's paper.&#xD;&#xA;    float luminance = a * xyz.y / logAvgLuminance;&#xD;&#xA;    luminance /= luminance + 1;&#xD;&#xA;&#xD;&#xA;    // then to &quot;scaled&quot; XYZ and RGB, see below&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then back to XYZ, than to linear RGB (wia [this][2] transform):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;for (auto &amp;xyz : image) {&#xD;&#xA;    // XYZ to chromaticity and &quot;scaled luminance&quot;, see above&#xD;&#xA;&#xD;&#xA;    Vec3 scaledXyz(&#xD;&#xA;        chromaticity.x * luminance / chromaticity.y,&#xD;&#xA;        luminance,&#xD;&#xA;        (1 - chromaticity.x - chromaticity.y) * luminance / chromaticity.y&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    float r = dot(Vec3( 3.2406, -1.5372, -0.4986), scaledXyz);&#xD;&#xA;    float g = dot(Vec3(-0.9689,  1.8758,  0.0415), scaledXyz);&#xD;&#xA;    float b = dot(Vec3( 0.0557, -0.2040,  1.0570), scaledXyz);&#xD;&#xA;&#xD;&#xA;    // Output RGB, i.e. std::cout &lt;&lt; Vec3(r, g, b);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;After that I still get RGB values outside of [0..1]. What am I doing wrong? It seems that &quot;max&quot; luminance should depend on chromaticities of the color. Is there an algorithm to account for that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://jcgt.org/published/0002/02/01/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_(CIE_XYZ_to_sRGB)" ContentLicense="CC BY-SA 4.0" />
  <row Id="22904" PostHistoryTypeId="2" PostId="8517" RevisionGUID="28ccc625-d33b-45e1-81db-1579cdf5182f" CreationDate="2019-01-25T20:01:20.003" UserId="2041" Text="&gt; I'm guessing Rasterization based pipelines use the same procedure for shading i.e. A ray is shot from the pixel and then from the triangle that got projected on that pixel to the light source?&#xD;&#xA;&#xD;&#xA;Close, but not quite. There's no actual tracing of rays but the underlying linear algebra is the same. It sounds like you already understand the first part of rasterisation, as far as getting some fragments which need to be shaded. Each fragment knows the attributes of the triangle it came from (the world position, normal, etc.). In traditional forward shading, the fragment shader runs once per light, and it also knows the attributes of the light, including the world-space direction from the shading point to the light: the direction you would trace a shadow ray.&#xD;&#xA;&#xD;&#xA;Although no shadow ray is traced, the actual lighting calculation is exactly the same: you use the view and light directions and the surface normal in whatever BRDF you want. You just repeat the process for each light and sum the results. At the end, you have the same result that you'd get from a very simple ray-tracer, without any shadows, reflections, refractions, or indirect lighting.&#xD;&#xA;&#xD;&#xA;How to add those missing features? Well, there are several possible techniques for each, but I'll briefly go over the simplest. A simple way of getting shadows is using shadow maps. Before you render your main scene, you do a render into an off-screen buffer, but using the light as a camera. (The projection and shape depend on the light, e.g. orthogonal projection for a directional/cylindrical light.) The trick is, you don't render all the colours: you only draw into the depth buffer. What you get is a picture of the distance from the light to the closest thing in each direction. Later on, when you're shading for that light's contribution in the fragment shader, you calculate the distance from the light to the shading point, and compare it to the value in the depth buffer. That tells you whether the shading point is the closest thing to the light along that ray, without having to run an intersection test.&#xD;&#xA;&#xD;&#xA;Planar reflections and refractions are pretty simple too: just render the scene but with the camera transformed to produce the reflection or refraction image. For example, for a planar reflection in a lake or floor, you reflect the camera position about that plane to draw the whole scene upside-down. When you draw the real scene around it, any transparency shows that reflection." ContentLicense="CC BY-SA 4.0" />
  <row Id="22923" PostHistoryTypeId="6" PostId="1626" RevisionGUID="6dc5a6bb-9ca2-4410-9a1a-97fef9e60c8f" CreationDate="2019-01-26T19:46:45.933" UserDisplayName="user246" Comment="real tag instead of untagged" Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22924" PostHistoryTypeId="24" PostId="1626" RevisionGUID="6dc5a6bb-9ca2-4410-9a1a-97fef9e60c8f" CreationDate="2019-01-26T19:46:45.933" Comment="Proposed by 246 approved by 231 edit id of 457" ContentLicense="CC BY-SA 4.0" />
  <row Id="22925" PostHistoryTypeId="2" PostId="8520" RevisionGUID="9c104e3d-f082-41aa-b522-1e25e3a2c329" CreationDate="2019-01-26T21:49:21.333" UserId="9987" Text="I am reading a paper and there is a part I don't understand:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am wondering why the isotropic BRDF only depends on the view direction and roughness? Why is the light direction not related?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/anl7u.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22926" PostHistoryTypeId="1" PostId="8520" RevisionGUID="9c104e3d-f082-41aa-b522-1e25e3a2c329" CreationDate="2019-01-26T21:49:21.333" UserId="9987" Text="confused on isotropic BRDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="22927" PostHistoryTypeId="3" PostId="8520" RevisionGUID="9c104e3d-f082-41aa-b522-1e25e3a2c329" CreationDate="2019-01-26T21:49:21.333" UserId="9987" Text="|brdf|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22928" PostHistoryTypeId="2" PostId="8521" RevisionGUID="b256bc4d-9252-4ae1-bb7c-421aba4205df" CreationDate="2019-01-27T00:06:35.283" UserId="48" Text="Getting sRGB values outside [0, 1] is expected and normal when using spectral rendering.&#xD;&#xA;&#xD;&#xA;The sRGB gamut only covers a triangle in the middle of the CIE chromaticity space:&#xD;&#xA;&#xD;&#xA;[![CIE chromaticity diagram with sRGB gamut highlighted][1]][1]&#xD;&#xA;(diagram from [Wikipedia](https://en.wikipedia.org/wiki/SRGB#/media/File:Cie_Chart_with_sRGB_gamut_by_spigget.png))&#xD;&#xA;&#xD;&#xA;The big &quot;horseshoe&quot; shape is the set of all physically possible chromaticities (CIE xy coordinates) from any possible spectrum. So your xy coordinates should be expected to land somewhere in the horseshoe...but only the ones that land inside the triangle are representable as sRGB! The others are &quot;too saturated&quot; for sRGB, and will have to be clamped or remapped somehow. (Tone mapping per se doesn't fix this, as it's concerned with luminance rather than chromaticity.)&#xD;&#xA;&#xD;&#xA;There are a variety of approaches to deal with out-of-gamut colors depending on how sophisticated you want to be:&#xD;&#xA;&#xD;&#xA;* You can of course simply clamp the sRGB values, but this may change the hue and/or the luminance of the color in the process.&#xD;&#xA;* To preserve both hue and luminance, you can edit the xy coordinates before calculating `scaledXyz`. If the initial xy coordinates are outside the sRGB triangle, find the line segment from the xy coordinates to the white point (e.g. D65); then find the intersection of that line segement with the sRGB triangle. That's the closest sRGB point that has the same luminance and hue as the original point, but lower saturation. (The vertices of the sRGB triangle can be obtained by converting RGB(1, 0, 0), RGB(0, 1, 0), and RGB(0, 0, 1) to CIE xy space.)&#xD;&#xA;* Alternatively, rather than clamping (which throws away any detail in the saturation outside the sRGB gamut), you could try doing a linear or non-linear remapping of saturation values in the image, similar to how you do for luminance. By &quot;saturation&quot; here I mean distance from the white point. The idea would be to squish the whole image toward the white point so as to bring everything within the gamut. But that may affect the apparent saturation of in-gamut colors in visually undesirable ways.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Y9z7W.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22936" PostHistoryTypeId="2" PostId="8523" RevisionGUID="7240202e-2891-4a2e-ae78-116cbb89a979" CreationDate="2019-01-28T15:10:16.060" UserId="10074" Text="I am trying to determine whether two frusta intersect in 3D space and to quantify this intersection as a percentage of one frustum volume (eg. 100% intersection meaning that the two frusta occupy the same exact space, 0% the two frusta don't touch).&#xD;&#xA;&#xD;&#xA;I have all the possible data about each frustum, the six planes and their position and so on but I can't figure out what's a reliable method to get what I want.&#xD;&#xA;&#xD;&#xA;I had a look at the Separating Axis Algorithm for collision detection but I don't understand if it's what I need.&#xD;&#xA;&#xD;&#xA;Can anyone direct me towards the right path?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="22937" PostHistoryTypeId="1" PostId="8523" RevisionGUID="7240202e-2891-4a2e-ae78-116cbb89a979" CreationDate="2019-01-28T15:10:16.060" UserId="10074" Text="Intersecting Frusta" ContentLicense="CC BY-SA 4.0" />
  <row Id="22938" PostHistoryTypeId="3" PostId="8523" RevisionGUID="7240202e-2891-4a2e-ae78-116cbb89a979" CreationDate="2019-01-28T15:10:16.060" UserId="10074" Text="|3d|geometry|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22941" PostHistoryTypeId="2" PostId="8524" RevisionGUID="1107f8e0-df95-40ae-bc22-d30400f27798" CreationDate="2019-01-28T17:45:33.633" UserId="10075" Text="I am trying to get started with implementing a basic display (i.e a simple red screen) onto a VGA monitor by programming a Xilinx spartan3a fpga for the same.&#xD;&#xA;I have studied about the signal timings for a 640x480 @ 60hz display and implemented the same,however it turns out, The monitor does not recognize it.I tried using a sample test file (it was a bit file so couldn't reverse engineer it), and it worked perfectly so i think there's no issue with the hardware.&#xD;&#xA;&#xD;&#xA;    module main(&#xD;&#xA;        clk,&#xD;&#xA;        Hsync,&#xD;&#xA;        Vsync,&#xD;&#xA;        Red,&#xD;&#xA;        Green,&#xD;&#xA;        Blue,&#xD;&#xA;        led&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    //inputs:&#xD;&#xA;    input clk;&#xD;&#xA;    //outputs:&#xD;&#xA;    output Hsync;&#xD;&#xA;    output Vsync;&#xD;&#xA;    output[2:0] Red;&#xD;&#xA;    output[2:0] Green;&#xD;&#xA;    output [1:0] Blue;&#xD;&#xA;    output [7:0] led;&#xD;&#xA;    //wire&#xD;&#xA;    wire[9:0] hcounter;&#xD;&#xA;    wire[9:0] vcounter;&#xD;&#xA;    wire PixClk;&#xD;&#xA;    wire locked;&#xD;&#xA;    //regs:&#xD;&#xA;    reg reset;&#xD;&#xA;&#xD;&#xA;    clkgen inst(&#xD;&#xA;    .CLKIN_IN(clk), &#xD;&#xA;    .RST_IN(1'b0), &#xD;&#xA;    .CLKIN_IBUFG_OUT(), &#xD;&#xA;    .CLK0_OUT(PixClk), &#xD;&#xA;    .LOCKED_OUT(locked)&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    VGAcontroller controller1(&#xD;&#xA;        .locked(locked),&#xD;&#xA;        .pixel_clk(PixClk),&#xD;&#xA;        .hsync(Hsync),&#xD;&#xA;        .vsync(Vsync),&#xD;&#xA;        .hcounter(hcounter),&#xD;&#xA;        .vcounter(vcounter)&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    generateRGB RedScreen(&#xD;&#xA;        .RedPix(Red),&#xD;&#xA;        .GreenPix(Green),&#xD;&#xA;        .BluePix(Blue),&#xD;&#xA;        .Hcount(hcounter),&#xD;&#xA;        .Vcount(hcounter)&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    assign led[0]=locked;&#xD;&#xA;    assign led[7:1]=7'b0;&#xD;&#xA;    endmodule&#xD;&#xA;&#xD;&#xA;the clockgen module generates a 25mhz signal, and led[0] goes &quot;ON&quot; when the dcm-pll has a locked onto the frequency.(works in the implementation).&#xD;&#xA;&#xD;&#xA;'VGAcontroller' module is responsible for the 'Hsync' and 'Vsync' signal generation taking in 'Pixelclk' and locked as inputs with the rest as outputs. The 'generateRGB' module takes in the 'Hcounter' and 'Vcounter' values to provide the necessary analog values via 3 registers.&#xD;&#xA;&#xD;&#xA;VGAcontroller.v&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    //800 horizontal counts&#xD;&#xA;    //525 vertical counts&#xD;&#xA;&#xD;&#xA;    module VGAcontroller(&#xD;&#xA;        locked,&#xD;&#xA;        pixel_clk,&#xD;&#xA;        hsync,&#xD;&#xA;        vsync,&#xD;&#xA;        hcounter,&#xD;&#xA;        vcounter&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    input locked;&#xD;&#xA;    input pixel_clk;&#xD;&#xA;    output hsync;&#xD;&#xA;    output vsync;&#xD;&#xA;    output[9:0] hcounter;&#xD;&#xA;    output[9:0] vcounter;&#xD;&#xA;&#xD;&#xA;    reg hsync;&#xD;&#xA;    reg vsync;&#xD;&#xA;    reg[9:0] hcounter;&#xD;&#xA;    reg[9:0] vcounter;&#xD;&#xA;&#xD;&#xA;    always @(posedge pixel_clk or posedge locked)&#xD;&#xA;    begin&#xD;&#xA;        if(locked)&#xD;&#xA;        begin&#xD;&#xA;            hcounter=hcounter+1'b1;&#xD;&#xA;            case(hcounter)&#xD;&#xA;                10'b0:              hsync=1'b1; //d&lt;0&gt;&#xD;&#xA;                10'b1010010000: hsync=1'b0; //d&lt;656&gt;&#xD;&#xA;                10'b1011110000: hsync=1'b1; //d&lt;752&gt;&#xD;&#xA;                10'b1100100000:                 //d&lt;800&gt;&#xD;&#xA;                begin&#xD;&#xA;                    hcounter=10'b0;&#xD;&#xA;                    vcounter=vcounter+1'b1;&#xD;&#xA;                end&#xD;&#xA;            endcase&#xD;&#xA;            case(vcounter)&#xD;&#xA;                10'b0:      vsync=1'b1;                 //d&lt;0&gt;&#xD;&#xA;                10'b0111101010: vsync=1'b0;         //d&lt;490&gt;    &#xD;&#xA;                10'b0111101100: vsync=1'b1;         //d&lt;492&gt;&#xD;&#xA;                10'b1000001101: vcounter=10'b0; //d&lt;525&gt;&#xD;&#xA;            endcase&#xD;&#xA;        end else begin&#xD;&#xA;            hcounter=10'b0;&#xD;&#xA;            vcounter=10'b0;&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    endmodule&#xD;&#xA;&#xD;&#xA;the timing sequence is as follows : [visible range]-&gt;[front porch]-&gt;[Sync pulse]-&gt;[back porch]&#xD;&#xA;&#xD;&#xA;the reason for starting the counter with visible range is that the values of counters correspond to the location of the pixel on the screen.&#xD;&#xA;As of now , the 'generateRGB' simply assigns the register responsible for the red color to have full voltage while green and blue to be 0 i.e to print a red screen.&#xD;&#xA;&#xD;&#xA;P.S. I am not exactly sure whether this question is valid for this forum or whether tags do good justice but if there is a better one, kindly recommend.thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="22942" PostHistoryTypeId="1" PostId="8524" RevisionGUID="1107f8e0-df95-40ae-bc22-d30400f27798" CreationDate="2019-01-28T17:45:33.633" UserId="10075" Text="debugging VGA signal timings for 640x480 @ 60hz" ContentLicense="CC BY-SA 4.0" />
  <row Id="22943" PostHistoryTypeId="3" PostId="8524" RevisionGUID="1107f8e0-df95-40ae-bc22-d30400f27798" CreationDate="2019-01-28T17:45:33.633" UserId="10075" Text="|pixel-graphics|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22945" PostHistoryTypeId="6" PostId="8524" RevisionGUID="c74f513a-09ed-43eb-a626-9c177995b132" CreationDate="2019-01-28T18:22:29.513" UserId="2041" Comment="edited tags" Text="|frame-buffer|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22946" PostHistoryTypeId="2" PostId="8525" RevisionGUID="19c72d75-e77e-422e-8fd7-3937f5cc2d91" CreationDate="2019-01-28T19:40:42.307" UserId="6046" Text="So I am currently in the process of implementing Physically based Shading in my pathtracer using microfacet models and I'm quite stuck at comprehending light interaction with diffuse surfaces.&#xD;&#xA;&#xD;&#xA;First of all I want to get a clear concept of how surfaces actually get their color. We all know that the color of any surface is due to their property to absorb light of certain wavelength in the Visible region of the spectrum. More specifically, according to the answer [here][1], when light hits an atom or molecule it gets absorbed if the electrons have the same vibrational frequency as the light. Which is the reason for the color of a surface. Now let's see what happens when light interacts with a diffuse surface.&#xD;&#xA;&#xD;&#xA;When Light hits a diffuse (dielectric or non-metal) surface 2 things happen. It gets reflected specularly or it gets refracted, scattered, and re-emitted which we call &quot;diffuse reflection&quot;. The amount of light that gets reflected/refracted depends on the Fresnel Equation which are wave-length dependent. This gives off the hint that an RGB triple also arises due to wavelength dependent IOR and thus maybe the reason for the color. So here's the main confusion.&#xD;&#xA;&#xD;&#xA; 1. When light hits a diffuse surface and gets reflected specularly it's possible that the atoms or molecules at the interaction surface absorb some of the light. This might be the reason for the color. On the other hand, the composition of light also changes in each of the R, G, B spectrum due to wavelength dependent index of refraction and Fresnel equations. So what's the real reason for the color? Is it the former or the latter or a mix of the two?&#xD;&#xA;&#xD;&#xA;After the above has been clarified how does the whole thing tie with the light that got refracted, scattered and re-emitted?&#xD;&#xA;&#xD;&#xA; 2. Secondly since diffuse surfaces exhibit both specular and diffuse reflection why do I mostly see people using just lambertian model for diffuse surfaces? The proper way would be to use a BRDF for diffuse reflection + a BRDF for specular like Cook Torrance. Am I correct?&#xD;&#xA;&#xD;&#xA; 3. Thirdly shouldn't we be weighting the diffuse component with $(1-F_{in})(1-F_{out})...$ or more fresnel terms depending on, if the refracted ray undergoes total internal reflection. Are these factors built-in by default or what?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://physics.stackexchange.com/questions/269201/what-is-the-actual-mechanism-behind-the-reflection-of-various-colored-light-by-m&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/2285/how-to-properly-combine-the-diffuse-and-specular-terms" ContentLicense="CC BY-SA 4.0" />
  <row Id="22947" PostHistoryTypeId="1" PostId="8525" RevisionGUID="19c72d75-e77e-422e-8fd7-3937f5cc2d91" CreationDate="2019-01-28T19:40:42.307" UserId="6046" Text="Physically Based Shading for Diffuse surfaces" ContentLicense="CC BY-SA 4.0" />
  <row Id="22948" PostHistoryTypeId="3" PostId="8525" RevisionGUID="19c72d75-e77e-422e-8fd7-3937f5cc2d91" CreationDate="2019-01-28T19:40:42.307" UserId="6046" Text="|lighting|physically-based|shading|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22949" PostHistoryTypeId="5" PostId="8525" RevisionGUID="de69bc8d-254c-4f48-a87e-7cae3e7bb418" CreationDate="2019-01-28T19:53:08.027" UserId="6046" Comment="added 206 characters in body" Text="So I am currently in the process of implementing Physically based Shading in my pathtracer using microfacet models and I'm quite stuck at comprehending light interaction with diffuse surfaces.&#xD;&#xA;&#xD;&#xA;First of all I want to get a clear concept of how surfaces actually get their color. We all know that the color of any surface is due to their property to absorb light of certain wavelength in the Visible region of the spectrum. More specifically, according to the answer [here][1], when light hits an atom or molecule it gets absorbed if the electrons have the same vibrational frequency as the light. Which is the reason for the color of a surface. Now let's see what happens when light interacts with a diffuse surface.&#xD;&#xA;&#xD;&#xA;When Light hits a diffuse (dielectric or non-metal) surface 2 things happen. It gets reflected specularly or it gets refracted, scattered, and re-emitted which we call &quot;diffuse reflection&quot;. The amount of light that gets reflected/refracted depends on the Fresnel Equation which are wave-length dependent. This gives off the hint that an RGB triple also arises due to wavelength dependent IOR and thus maybe the reason for the color. So here's the main confusion.&#xD;&#xA;&#xD;&#xA; 1. When light hits a diffuse surface and gets reflected specularly it's possible that the atoms or molecules at the interaction surface absorb some of the light. This might be the reason for the color. On the other hand, the composition of light also changes in each of the R, G, B spectrum due to wavelength dependent index of refraction and Fresnel equations. So what's the real reason for the color? Is it the former or the latter or a mix of the two?  I've read some notes by Naty Hoffman where he also suggests using the Fresnel Reflectance values as the specular color when calculating a specular BRDF like Cook torrance. Adds a lot more to my confusion.&#xD;&#xA;&#xD;&#xA;After the above has been clarified how does the whole thing tie with the light that got refracted, scattered and re-emitted?&#xD;&#xA;&#xD;&#xA; 2. Secondly since diffuse surfaces exhibit both specular and diffuse reflection why do I mostly see people using just lambertian model for diffuse surfaces? The proper way would be to use a BRDF for diffuse reflection + a BRDF for specular like Cook Torrance. Am I correct?&#xD;&#xA;&#xD;&#xA; 3. Thirdly shouldn't we be weighting the diffuse component with $(1-F_{in})(1-F_{out})...$ or more fresnel terms depending on, if the refracted ray undergoes total internal reflection. Are these factors built-in by default or what?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://physics.stackexchange.com/questions/269201/what-is-the-actual-mechanism-behind-the-reflection-of-various-colored-light-by-m&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/2285/how-to-properly-combine-the-diffuse-and-specular-terms" ContentLicense="CC BY-SA 4.0" />
  <row Id="22952" PostHistoryTypeId="50" PostId="8431" RevisionGUID="bcf6da9e-d878-4b46-83db-88c52e488bf2" CreationDate="2019-01-28T23:02:45.573" UserId="-1" />
  <row Id="22957" PostHistoryTypeId="2" PostId="8527" RevisionGUID="4edd2e27-ee06-43ea-931b-11f1d719c9f5" CreationDate="2019-01-29T09:21:45.970" UserId="10080" Text="I am new to shaders and I need to convert efficiently an RGB image to YUV420.&#xD;&#xA;&#xD;&#xA;I can convert the RGB image to YUV420 with a simple c++ program that uses the &#xD;&#xA;&#xD;&#xA;    long length = m_width * m_height;&#xD;&#xA;&#xD;&#xA;	long yuv420FrameLength = (float)length * 1.5;&#xD;&#xA;	unsigned char *yuvdest = (unsigned char *)malloc(yuv420FrameLength * sizeof(unsigned char));&#xD;&#xA;&#xD;&#xA;	int r, g, b, y, u, v, ypos, upos, vpos;&#xD;&#xA;&#xD;&#xA;	for (int j = 0; j &lt; m_height; ++j) {&#xD;&#xA;		for (int i = 0; i &lt; m_width; ++i) {&#xD;&#xA;			r = (int)m_pRGBImage[(j * m_width + i) * 3 + 0];&#xD;&#xA;			g = (int)m_pRGBImage[(j * m_width + i) * 3 + 1];&#xD;&#xA;			b = (int)m_pRGBImage[(j * m_width + i) * 3 + 2];&#xD;&#xA;&#xD;&#xA;			y = ((66 * r + 129 * g + 25 * b + 128) &gt;&gt; 8) + 16;&#xD;&#xA;			u = ((-38 * r - 74 * g + 112 * b + 128) &gt;&gt; 8) + 128;&#xD;&#xA;			v = ((112 * r - 94 * g - 18 * b + 128) &gt;&gt; 8) + 128;&#xD;&#xA;			ypos = j * m_width + i;&#xD;&#xA;			upos = (j / 2) * (m_width / 2) + (i / 2) + length;&#xD;&#xA;			vpos = (j / 2) * (m_width / 2) + (i / 2) + length + (length / 4);&#xD;&#xA;&#xD;&#xA;			yuvdest[ypos] = y;&#xD;&#xA;			yuvdest[upos] = u;&#xD;&#xA;			yuvdest[vpos] = v;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;	std::ofstream myfile;&#xD;&#xA;	myfile.open(pPath, std::ios_base::trunc);&#xD;&#xA;	myfile &lt;&lt; yuvdest;&#xD;&#xA;	myfile.close();&#xD;&#xA;&#xD;&#xA;I can transform the pixels and create the YUV with the following shader code (I did not test it, if I'm wrong, please tell me).&#xD;&#xA;&#xD;&#xA;	sampler2D sampler0            : register(s0);&#xD;&#xA;&#xD;&#xA;	struct VS_INPUT&#xD;&#xA;	{&#xD;&#xA;	  float4 Position   : POSITION;&#xD;&#xA;	  float2 Tex0       : TEXCOORD0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct VS_OUTPUT&#xD;&#xA;	{&#xD;&#xA;	  float4 Position   : POSITION;&#xD;&#xA;	  float2 Tex0       : TEXCOORD0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct PS_OUTPUT&#xD;&#xA;	{&#xD;&#xA;	  float4 Color   : COLOR0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	PS_OUTPUT psmain(in VS_OUTPUT In)&#xD;&#xA;	{&#xD;&#xA;	  PS_OUTPUT Out;&#xD;&#xA;	  Out.Color = tex2D(sampler0, In.Tex0);&#xD;&#xA;	  int r = Out.Color.x;&#xD;&#xA;	  int g = Out.Color.y;&#xD;&#xA;	  int b = Out.Color.z;&#xD;&#xA;	  float y = ((66 * r + 129 * g + 25 * b + 128) &gt;&gt; 8) + 16;&#xD;&#xA;	  float u = ((-38 * r - 74 * g + 112 * b + 128) &gt;&gt; 8) + 128;&#xD;&#xA;	  float v = ((112 * r - 94 * g - 18 * b + 128) &gt;&gt; 8) + 128;;&#xD;&#xA;	  return Out;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	VS_OUTPUT vsmain(in VS_INPUT In)&#xD;&#xA;	{&#xD;&#xA;	  VS_OUTPUT Out;&#xD;&#xA;	  Out.Position = In.Position;&#xD;&#xA;	  Out.Tex0 = In.Tex0;&#xD;&#xA;	  return Out;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;The thing that is missing to me is how to arrange the bytes formation correctly as the C++ code:&#xD;&#xA;&#xD;&#xA;    ypos = j * m_width + i;&#xD;&#xA;	upos = (j / 2) * (m_width / 2) + (i / 2) + length;&#xD;&#xA;	vpos = (j / 2) * (m_width / 2) + (i / 2) + length + (length / 4);" ContentLicense="CC BY-SA 4.0" />
  <row Id="22958" PostHistoryTypeId="1" PostId="8527" RevisionGUID="4edd2e27-ee06-43ea-931b-11f1d719c9f5" CreationDate="2019-01-29T09:21:45.970" UserId="10080" Text="Convert RGB image to YUV420 using a hlsl shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="22959" PostHistoryTypeId="3" PostId="8527" RevisionGUID="4edd2e27-ee06-43ea-931b-11f1d719c9f5" CreationDate="2019-01-29T09:21:45.970" UserId="10080" Text="|shader|image-processing|hlsl|pixel-graphics|pixel-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22960" PostHistoryTypeId="2" PostId="8528" RevisionGUID="9c25d194-a1c4-43c2-93e6-54f5aa2155c7" CreationDate="2019-01-29T14:18:10.777" UserId="6" Text="The problem here is that you're not storing the YUV values of a pixel at the same place in the result image. What you seem to be doing is first storing the full size Y image and after that the quarter-sized U image and then the quarter-sized V image after that (also with a strange gap of half the image size between the Y and the UV data).&#xD;&#xA;&#xD;&#xA;This doesn't work when trying to map it to a standard pixel shader approach, since a pixel shader outputs the value of exactly 1 pixel in the output image, but you actually would need to write 3 different scattered pixels in the output image, at least as your image data is currently laid out in memory.&#xD;&#xA;&#xD;&#xA;So there's a few ways you could get around that:&#xD;&#xA;&#xD;&#xA;- You could output the YUV values directly into a full-sized YUV image (with the Y, u, and v values of a single pixel stored together in the RGB channels of the output) and then further compress this into the disparate memory layout you need, either on the CPU or in another pixel shader that just decides what channels to read from the Yuv image based on the pixel position inside of the output image.&#xD;&#xA;&#xD;&#xA;- You could combine the above two shaders into one, doing either the Y, the U or the V computation, based on which quarter of the output image you're in.&#xD;&#xA;&#xD;&#xA;- You can switch to a different layout for your YUV data, e.g. storing the Yuv values of a 2x2 pixel block of the input image in one compressed pixel of the output image. Then it might actually be useful to write into an unsigned integer image and do the converstion to bytes and the compression yourself in the shader.&#xD;&#xA;&#xD;&#xA;- You can use your C++ algorithm and write the data in a scattered fashion, but not using a pixel shader rather than a *compute shader* and writing into a generalized buffer/image instead (or combining the two and writing into a generalized buffer/image rather than the frambuffer directly from the pixel shader).&#xD;&#xA;&#xD;&#xA;However, I left the above explanations decidedly vague and general for further studying, since there are a few more direct practical mistakes in your actual shader code (e.g. `Out.Color` should contain your output values, you're also computing with float, so they're likely in the [0,1] range and you shouldn't do all these integer operations on them), which indicate that you might first want to delve a little deeper into how shaders and HLSL work." ContentLicense="CC BY-SA 4.0" />
  <row Id="22962" PostHistoryTypeId="2" PostId="8529" RevisionGUID="ae0bc232-f4f3-4ff6-9f0e-69df8dda91c3" CreationDate="2019-01-29T20:49:11.497" UserId="10086" Text="I'm trying to port part of an OpenGL program into an existing DirectX 12 software, at some point in their shaders they use OpenGL [ImageLoadStore][1] in order to store information in 3D Textures without having to use an FBO.&#xD;&#xA;&#xD;&#xA;Is there something similar in the DirectX 12 API? &#xD;&#xA;Or would I have to render to a custom FrameBuffer?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store" ContentLicense="CC BY-SA 4.0" />
  <row Id="22963" PostHistoryTypeId="1" PostId="8529" RevisionGUID="ae0bc232-f4f3-4ff6-9f0e-69df8dda91c3" CreationDate="2019-01-29T20:49:11.497" UserId="10086" Text="Is there an analogous of OpenGL's ImageLoadStore in DirectX 12?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22964" PostHistoryTypeId="3" PostId="8529" RevisionGUID="ae0bc232-f4f3-4ff6-9f0e-69df8dda91c3" CreationDate="2019-01-29T20:49:11.497" UserId="10086" Text="|opengl|shader|directx12|frame-buffer|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22965" PostHistoryTypeId="6" PostId="8529" RevisionGUID="952c26bf-92dc-4610-851f-cc6ad45534d9" CreationDate="2019-01-30T01:44:59.593" UserId="2654" Comment="edited tags" Text="|shader|directx12|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22968" PostHistoryTypeId="5" PostId="8022" RevisionGUID="bba92e8a-a3e1-4219-bce3-316ad7030c4e" CreationDate="2019-01-30T09:25:08.350" UserId="209" Comment="fixed some English" Text="If you are doing a perspective image and your model has implicit intersections then, if you use &quot;linear Z&quot;, those intersections will appear in the wrong places. &#xD;&#xA;&#xD;&#xA;For example, consider a simple ground plane with a line of telephone poles, receding into the distance,  which pierce the ground (and continue below). The implicit intersections will be determined by the interpolated depth values. If those are not interpolated with `1/Z`, then when the projected vertices have been computed with perspective, the image will look incorrect.&#xD;&#xA;&#xD;&#xA;I apologise for the non-aesthetic quality of the following illustrations but I did them back in '97. &#xD;&#xA;&#xD;&#xA;The first image shows the required rendering effect. (Note that the blue &quot;pylons&quot; go quite a long distance under the ground plane so are clipped at the bottom of the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This second image shows the result of using a non-reciprocal depth buffer: (Apologies for the change of scale - these were copied out of an old MS Word doc and I've no idea what has happened with the scaling.)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the results are incorrect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;On another note, are sure you *really* want a linear Z representation? If you are rendering perspective, surely one wants more precision closer to the camera than at a distance?&#xD;&#xA;&#xD;&#xA;Re your later comment:&#xD;&#xA;&gt; “if those are not interpolated with 1/Z” that I don’t understand. What interpolation is that?&#xD;&#xA;&#xD;&#xA;The first thing to note is that, with a standard perspective projection, straight lines in world space remain straight lines in perspective space. Distances/lengths, however, are not preserved.&#xD;&#xA;&#xD;&#xA;For simplicity, let us assume a trivial perspective transform is used to project the vertices, i.e.&#xD;&#xA;$$X_{Screen} = \frac{X_{World}}{Z_{World}}$$&#xD;&#xA;$$Y_{Screen} = \frac{Y_{World}}{Z_{World}}$$&#xD;&#xA;We *should* also compute a reciprocal screen-space depth, e.g. $$Z_{Screen} = \frac{1}{Z_{World}}$$ but linear Z in the depth buffer would, to me, require something like: $$Z_{Screen} = scale*Z_{World}$$ *(We can assume here that scale=1)*&#xD;&#xA;&#xD;&#xA;Let's assume we have a line with world space end points$$&#xD;&#xA;  \begin{matrix} \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and &#xD;&#xA;   \begin{bmatrix}&#xD;&#xA;    200 \\&#xD;&#xA;    0   \\&#xD;&#xA;    10  \\&#xD;&#xA;    \end{bmatrix}\\&#xD;&#xA;  \end{matrix}&#xD;&#xA;$$&#xD;&#xA;With the perspective mapping these map to screen space coordinates&#xD;&#xA; $$ \begin{matrix}   \begin{bmatrix}&#xD;&#xA;    0 \\&#xD;&#xA;    0 \\&#xD;&#xA;    1 \\&#xD;&#xA;    \end{bmatrix} and \begin{bmatrix}&#xD;&#xA;    20 \\&#xD;&#xA;    0  \\&#xD;&#xA;    0.1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; \end{matrix}$$&#xD;&#xA;&#xD;&#xA;The rendering system/hardware will linearly interpolate the screen space z, so at the 1/2 way point of the line, as it appears on-screen, i.e. at pixel (10, 0), we would get a projected (inverse) Z value of 0.55, which corresponds to to a world space Z value value of ~1.818. Given the starting and end Z values, this is about 20% along the length of the line.&#xD;&#xA;&#xD;&#xA;If instead, we tried to interpolate using the original Z values, we'd end up with Z corresponding to a world space value of 5.5. As long as nothing intersects, you might be ok (I've not thought about it too thoroughly) but anything with implicit intersections *will* be incorrect.&#xD;&#xA;&#xD;&#xA;What I haven't mentioned is that once you introduce perspective correct texturing (or even perspective correct shading), you must do per-pixel interpolation of 1/w and, additionally, also compute, per pixel, the reciprocal of that interpolated value.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E1PME.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fouWc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22972" PostHistoryTypeId="2" PostId="8531" RevisionGUID="258b981a-c967-4a7d-befd-fcf765b9de35" CreationDate="2019-01-30T16:18:01.577" UserId="6406" Text="If I use a 4D noise function which returns a noise value and a four-part analytically derived gradient vector, I can create a 2D tile which is effectively seamless through remapping `x,y` and `z,w` coordinates to independent circles, i.e.&#xD;&#xA;&#xD;&#xA;$\ x = r_0*\cos(\theta)$  &#xD;&#xA;$\ y = r_0*\sin(\theta)$  &#xD;&#xA;$\ z = r_1*\cos(\phi) $  &#xD;&#xA;$\ w = r_1*\sin(\phi)$&#xD;&#xA;&#xD;&#xA;However, since the noise function operates in 4D space I'm left with a 4D gradient vector. Is it possible to transform this 4D vector into a 2D vector which describes the gradient of the surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22973" PostHistoryTypeId="1" PostId="8531" RevisionGUID="258b981a-c967-4a7d-befd-fcf765b9de35" CreationDate="2019-01-30T16:18:01.577" UserId="6406" Text="Finding the normal of a tileable 2D surface extracted from 4D space" ContentLicense="CC BY-SA 4.0" />
  <row Id="22974" PostHistoryTypeId="3" PostId="8531" RevisionGUID="258b981a-c967-4a7d-befd-fcf765b9de35" CreationDate="2019-01-30T16:18:01.577" UserId="6406" Text="|noise|normal-mapping|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22977" PostHistoryTypeId="2" PostId="8532" RevisionGUID="c067c3ff-1f07-48a9-ab94-a594bab364a5" CreationDate="2019-01-30T17:37:38.873" UserId="10091" Text="I'm trying to integrate the thin-film interference effect described in the paper &quot;Belcour, L., &amp; Barla, P. (2017). A practical extension to microfacet theory for the modeling of varying iridescence.&quot; (https://hal.archives-ouvertes.fr/hal-01518344/document) into my material model, which is based on google/Filament's material model (https://google.github.io/filament/Filament.md.html).&#xD;&#xA;&#xD;&#xA;However I'm having trouble trying to understand the way to add them together. Let's say I'm shading a pixel, direct lighting goes like this:&#xD;&#xA;&#xD;&#xA;    vec3 Fr = specularLobe();   // D * F * V&#xD;&#xA;    vec3 Fd = diffuseLobe();    // 1 / PI * diffuseColor&#xD;&#xA;&#xD;&#xA;    return (Fd + Fr) * light.color * light.attenuation * NoL;&#xD;&#xA;&#xD;&#xA;And on the other side, indirect lighting goes like this...&#xD;&#xA;&#xD;&#xA;    vec3 Fd = diffuseIrradiance() * diffuseColor;&#xD;&#xA;    vec3 Fr = specularIrradiance() * DFG();&#xD;&#xA;&#xD;&#xA;    return (Fd + Fr);&#xD;&#xA;&#xD;&#xA;Now, if I want to add the thin film/iridescence layer on top of the base material, in what way does it take into account to bottom layer for all the lighting?&#xD;&#xA;&#xD;&#xA;I've been looking at this implementation in UE4 (https://polycount.com/discussion/comment/2604578#Comment_2604578), but they seem to input the result of the BRDF calculation directly into the 'Base Color' of the material, which I really don't think it is what I'm looking for, correct me if I'm wrong...&#xD;&#xA;&#xD;&#xA;[![UE4-editor-example][1]][1] &#xD;&#xA;&#xD;&#xA;In this other implementation in Unity (https://github.com/Xerxes1138/Iridescence/blob/master/Iridescence.shader) they seem to account for iridescence in both IBL and direct lighting separately, but the layer base is not taken much into account as far as I know.&#xD;&#xA;&#xD;&#xA;Finally, in the paper itself, the following statement is made:&#xD;&#xA;&#xD;&#xA;&gt; Our extension consists in replacing the classic Fresnel reflectance&#xD;&#xA;term, F , by a more complex term, R accounting for all inter-reflections&#xD;&#xA;inside the thin-film layer, including constructive and destructive&#xD;&#xA;interference effects.&#xD;&#xA;&#xD;&#xA;From this I understand that simply by replacing the Fresnel Reflectance with the Airy Reflectance function should do the trick, but again, I'm not sure which would be the appropriate approach to being as physically correct as possible.&#xD;&#xA;&#xD;&#xA;(The original supp-code from the paper can be obtained from: https://hal.inria.fr/hal-01518344v2/file/supplemental-code%20%282%29.zip)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks for the help!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TMqe1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="22978" PostHistoryTypeId="1" PostId="8532" RevisionGUID="c067c3ff-1f07-48a9-ab94-a594bab364a5" CreationDate="2019-01-30T17:37:38.873" UserId="10091" Text="Iridescence/Thin-film interference integration as a layer" ContentLicense="CC BY-SA 4.0" />
  <row Id="22979" PostHistoryTypeId="3" PostId="8532" RevisionGUID="c067c3ff-1f07-48a9-ab94-a594bab364a5" CreationDate="2019-01-30T17:37:38.873" UserId="10091" Text="|lighting|pbr|rasterizer|material|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22981" PostHistoryTypeId="2" PostId="8533" RevisionGUID="b94f975a-5806-4a11-aded-aae1428232f6" CreationDate="2019-01-30T22:21:04.113" UserId="10096" Text="It seems like you have a big mess in your head. When people talk about diffuse surfaces in CG they usually mean ideal diffuse surfaces. That is, the brdf is simply: $f(\omega_o,x,\omega_i) = const$.We're talking about Lambertian reflectance. The colour you perceive is due to both the initial light colour and the albedo of the material. If you shine white light, then you'll really perceive what's left of it after absorption. So when you set $albedo = (r,g,b)$ then your surface reflects $r \%$ of the red light, $g\%$ of the green light, and $b\%$ of the blue light. Note that the tricolor formulation is not how it actually works in the real world, to be precise you should really be dealing with wavelengths, however $RGB$ is a good approximation perceptually due to how the human visual system works.&#xD;&#xA;&#xD;&#xA;The cosine term is not actually part of the diffuse BRDF either, it comes from Lambert's law (the cosine term in the rendering equation).&#xD;&#xA;&#xD;&#xA;Lastly you should realize that even Cook-Torrance is an approximation to a class of semi-plausible BRDFs." ContentLicense="CC BY-SA 4.0" />
  <row Id="22982" PostHistoryTypeId="5" PostId="8531" RevisionGUID="4ae492ec-6499-4a45-8582-3990feb38030" CreationDate="2019-01-30T22:46:54.690" UserId="6406" Comment="Clarifications" Text="If I use a 4D noise function which returns a noise value and a four-part analytically derived gradient vector, I can create a 2D tile which is seamless (i.e. the opposite edges match) through remapping `x,y` and `z,w` coordinates to independent circles, i.e.&#xD;&#xA;&#xD;&#xA;$\ x = r_0*\cos(\theta)$  &#xD;&#xA;$\ y = r_0*\sin(\theta)$  &#xD;&#xA;$\ z = r_1*\cos(\phi) $  &#xD;&#xA;$\ w = r_1*\sin(\phi)$&#xD;&#xA;&#xD;&#xA;Effectively the surface created through this coordinate mapping is a [flat torus](https://en.wikipedia.org/wiki/Torus#Flat_torus). &#xD;&#xA;&#xD;&#xA;However, since the noise function operates in 4D space I'm left with a 4D gradient vector. Is it possible to transform this 4D vector into a 2D vector which describes the gradient of the surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22983" PostHistoryTypeId="4" PostId="8531" RevisionGUID="4052d6ae-4028-4118-a801-c7814de7747e" CreationDate="2019-01-30T22:53:40.093" UserId="6406" Comment="Normals, plural. More than one." Text="Finding the normals of a tileable 2D surface extracted from 4D space" ContentLicense="CC BY-SA 4.0" />
  <row Id="22984" PostHistoryTypeId="5" PostId="8533" RevisionGUID="a112654e-3964-4186-b3ec-501c77ef0fb3" CreationDate="2019-01-31T08:46:12.480" UserId="209" Comment="Removed somewhat offensive language" Text="When people talk about diffuse surfaces in CG they usually mean ideal diffuse surfaces. That is, the BRDF is simply: $f(\omega_o,x,\omega_i) = const$. We're talking about Lambertian reflectance. The colour you perceive is due to both the initial light colour and the albedo of the material. If you shine white light, then you'll really perceive what's left of it after absorption. So when you set $albedo = (r,g,b)$ then your surface reflects $r \%$ of the red light, $g\%$ of the green light, and $b\%$ of the blue light. Note that the tricolor formulation is not how it actually works in the real world, to be precise you should really be dealing with wavelengths, however $RGB$ is a good approximation perceptually due to how the human visual system works.&#xD;&#xA;&#xD;&#xA;The cosine term is not actually part of the diffuse BRDF either, it comes from Lambert's law (the cosine term in the rendering equation).&#xD;&#xA;&#xD;&#xA;Lastly you should realise that even Cook-Torrance is an approximation to a class of semi-plausible BRDFs." ContentLicense="CC BY-SA 4.0" />
  <row Id="22985" PostHistoryTypeId="2" PostId="8534" RevisionGUID="94e73838-750e-4fcd-90ac-1f054d9e37dc" CreationDate="2019-01-31T09:54:57.343" UserId="10099" Text="I am currently looking into alternatives to my current, somewhat slow but exact, OIT approach. Specifically, GL_SAMPLE_ALPHA_TO_COVERAGE to convert the alpha value into a per-sample mask.&#xD;&#xA;&#xD;&#xA;    // draw opaque objects&#xD;&#xA;    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);&#xD;&#xA;    glEnable(GL_SAMPLE_ALPHA_TO_ONE);&#xD;&#xA;    glDisable(GL_CULL_FACE);&#xD;&#xA;    // draw translucent objects&#xD;&#xA;&#xD;&#xA;However, if multiple alpha-blended faces are behind one another (such as the back faces which I would want to be visible) I am only seeing the first one. Is depth testing not done per sample? Can I force it to be done per sample? According to https://www.khronos.org/opengl/wiki/Depth_Test it should already be per sample.&#xD;&#xA;&#xD;&#xA;Multisampling is enabled and works fine for everything else (my OIT shaders in fact do sorting per sample which might be a reason for the slowness). The FBO being drawn into is provided by Qt." ContentLicense="CC BY-SA 4.0" />
  <row Id="22986" PostHistoryTypeId="1" PostId="8534" RevisionGUID="94e73838-750e-4fcd-90ac-1f054d9e37dc" CreationDate="2019-01-31T09:54:57.343" UserId="10099" Text="GL_SAMPLE_ALPHA_TO_COVERAGE and depth testing" ContentLicense="CC BY-SA 4.0" />
  <row Id="22987" PostHistoryTypeId="3" PostId="8534" RevisionGUID="94e73838-750e-4fcd-90ac-1f054d9e37dc" CreationDate="2019-01-31T09:54:57.343" UserId="10099" Text="|opengl|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="22988" PostHistoryTypeId="5" PostId="8534" RevisionGUID="7978d2e6-3f35-4100-aa7e-28bf374a78ba" CreationDate="2019-01-31T10:03:17.193" UserId="10099" Comment="added 5 characters in body" Text="I am currently looking into alternatives to my current, somewhat slow but exact, OIT approach. Specifically, GL_SAMPLE_ALPHA_TO_COVERAGE to convert the alpha value into a per-sample mask.&#xD;&#xA;&#xD;&#xA;    // draw opaque objects&#xD;&#xA;    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);&#xD;&#xA;    glEnable(GL_SAMPLE_ALPHA_TO_ONE);&#xD;&#xA;    glDisable(GL_CULL_FACE);&#xD;&#xA;    // draw translucent objects&#xD;&#xA;&#xD;&#xA;However, if multiple alpha-blended faces are behind one another (such as the back faces which I would want to be visible) I am only seeing the front most one. Is depth testing not done per sample? Can I force it to be done per sample? According to https://www.khronos.org/opengl/wiki/Depth_Test it should already be per sample.&#xD;&#xA;&#xD;&#xA;Multisampling is enabled and works fine for everything else (my OIT shaders in fact do sorting per sample which might be a reason for the slowness). The FBO being drawn into is provided by Qt." ContentLicense="CC BY-SA 4.0" />
  <row Id="22989" PostHistoryTypeId="5" PostId="8531" RevisionGUID="719c2da4-cd61-4eaa-81ac-49ced183e9c3" CreationDate="2019-01-31T11:33:20.867" UserId="6406" Comment="More description of problem" Text="If I use a 4D noise function which returns a noise value and a four-part analytically derived gradient vector, I can create a 2D tile which is seamless (i.e. the opposite edges match) through remapping `x,y` and `z,w` coordinates to independent circles, i.e.&#xD;&#xA;&#xD;&#xA;$\ \theta = a*2*\pi$  &#xD;&#xA;$\ \phi = b*2*\pi$&#xD;&#xA;&#xD;&#xA;where $a$ and $b$ are a point on the surface. They should be within the range $[0, size)$ where size is some arbitrary shared dimension for the surface.&#xD;&#xA;&#xD;&#xA;We can then plug $\theta$ and $\phi$ into the below functions to get the equivalent point in 4D space.&#xD;&#xA;&#xD;&#xA;$\ x = r_0*\cos(\theta)$  &#xD;&#xA;$\ y = r_0*\sin(\theta)$  &#xD;&#xA;$\ z = r_1*\cos(\phi) $  &#xD;&#xA;$\ w = r_1*\sin(\phi)$&#xD;&#xA;&#xD;&#xA;Effectively the surface created through this coordinate mapping is a [flat torus](https://en.wikipedia.org/wiki/Torus#Flat_torus). &#xD;&#xA;&#xD;&#xA;However, since the noise function operates in 4D space I'm left with a 4D gradient vector. Is it possible to transform this 4D vector into a 2D vector which describes the gradient of the surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="22990" PostHistoryTypeId="2" PostId="8535" RevisionGUID="b6679880-bafb-432c-8126-83a28eb3bbd6" CreationDate="2019-01-31T12:54:18.363" UserId="209" Text="(Promoting comment to answer)&#xD;&#xA;Do the faces have the same alpha value? That might generate the same coverage mask for the surfaces and, hence, only the closest one would be seen." ContentLicense="CC BY-SA 4.0" />
  <row Id="22994" PostHistoryTypeId="2" PostId="8537" RevisionGUID="64496771-aa97-4c4b-a99c-7df7600e6c7c" CreationDate="2019-01-31T15:43:52.293" UserId="10096" Text="Since the question was somewhat clarified I will formalize both the question and the answer for future readers.&#xD;&#xA;Having a differentiable scalar field $f : \mathbb{R}^4 \rightarrow \mathbb{R}$ we want to find the gradient of the field with respect to $\theta, \phi$ on the 2-manifold defined parametrically by: &#xD;&#xA;$$(x(\theta,\phi), y(\theta,\phi) z(\theta,\phi), w(\theta,\phi)) = (r_0\cos\theta, r_0\sin\theta, r_1\cos\phi,r_1\sin\phi)$$&#xD;&#xA;Where $r_0,r_1$ are constants. We can compute the partial derivatives as follows:&#xD;&#xA;$$\frac{\partial f}{\partial \theta} = \frac{\partial f}{\partial x}\frac{\partial x}{\partial \theta} + \frac{\partial f}{\partial y}\frac{\partial y}{\partial \theta} + \frac{\partial f}{\partial z}\frac{\partial z}{\partial \theta} + \frac{\partial f}{\partial w}\frac{\partial w}{\partial \theta} \\&#xD;&#xA;= -r_0\frac{\partial f}{\partial x}\sin\theta + r_0\frac{\partial f}{\partial y}\cos\theta$$&#xD;&#xA;$$\frac{\partial f}{\partial \phi} = &#xD;&#xA;\frac{\partial f}{\partial x}\frac{\partial x}{\partial \phi} + \frac{\partial f}{\partial y}\frac{\partial y}{\partial \phi} + \frac{\partial f}{\partial z}\frac{\partial z}{\partial \phi} + \frac{\partial f}{\partial w}\frac{\partial w}{\partial \phi} \\ = -r_1\frac{\partial f}{\partial x}\sin\phi + r_1\frac{\partial f}{\partial y}\cos\phi$$&#xD;&#xA;&#xD;&#xA;Assuming that the gradient $\nabla f = (\frac{\partial f}{\partial x},\frac{\partial f}{\partial y},\frac{\partial f}{\partial z},\frac{\partial f}{\partial w})$ is known, it is straightforward to compute the 2d gradient.&#xD;&#xA;&#xD;&#xA;Note that another possibility is to compute the gradient numerically (in case you don't have the partial derivatives of $f$):&#xD;&#xA;$$ \frac{\partial f}{\partial \theta} \approx \frac{f(r_0\cos(\theta+h_{\theta}), r_0\sin(\theta+h_{\theta}), r_1\cos\phi,r_1\sin\phi) - f(r_0\cos\theta, r_0\sin\theta, r_1\cos\phi,r_1\sin\phi)}{h_{\theta}}$$&#xD;&#xA;$$ \frac{\partial f}{\partial \phi} \approx \frac{f(r_0\cos\theta, r_0\sin\theta, r_1\cos(\phi+h_{\phi}),r_1\sin(\phi+h_{\phi})) - f(r_0\cos\theta, r_0\sin\theta, r_1\cos\phi,r_1\sin\phi)}{h_{\phi}}$$&#xD;&#xA;For $h_{\theta}, h_{\phi}$ chosen adequately (note that the choice of these parameters is a nontrivial problem)." ContentLicense="CC BY-SA 4.0" />
  <row Id="22998" PostHistoryTypeId="2" PostId="8539" RevisionGUID="2f9ed7e5-5120-4657-91e3-e7a49ff8d6bf" CreationDate="2019-02-01T06:32:34.783" UserId="10105" Text="I'm having a problem with my model here. I draw an icosahedron using GLUT, and the radius is set to 0.8. The info of the coordinates are listed below: (X and Z are calculated since our radius is 0.8)&#xD;&#xA;&#xD;&#xA;     private static final float X = .4205912828f;&#xD;&#xA;     private static final float Z = .6805166955f;&#xD;&#xA;     private static final float[][] idata =&#xD;&#xA;    {&#xD;&#xA;       {-X, 0, Z},&#xD;&#xA;       {X, 0, Z},&#xD;&#xA;       {-X, 0, -Z},&#xD;&#xA;       {X, 0, -Z},&#xD;&#xA;       {0, Z, X},&#xD;&#xA;       {0, Z, -X},&#xD;&#xA;       {0, -Z, X},&#xD;&#xA;       {0, -Z, -X},&#xD;&#xA;       {Z, X, 0},&#xD;&#xA;       {-Z, X, 0},&#xD;&#xA;       {Z, -X, 0},&#xD;&#xA;       {-Z, -X, 0}&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;    private static final int[][] index =&#xD;&#xA;     {&#xD;&#xA;    		 {0, 4, 1},&#xD;&#xA;    		    {0, 9, 4},&#xD;&#xA;    		    {9, 5, 4},&#xD;&#xA;    		    {4, 5, 8},&#xD;&#xA;    		    {4, 8, 1},&#xD;&#xA;    		    {8, 10, 1},&#xD;&#xA;    		    {8, 3, 10},&#xD;&#xA;    		    {5, 3, 8},&#xD;&#xA;    		    {5, 2, 3},&#xD;&#xA;    		    {2, 7, 3},&#xD;&#xA;    		    {7, 10, 3},&#xD;&#xA;    		    {7, 6, 10},&#xD;&#xA;    		    {7, 11, 6},&#xD;&#xA;    		    {11, 0, 6},&#xD;&#xA;    		    {0, 1, 6},&#xD;&#xA;    		    {6, 1, 10},&#xD;&#xA;    		    {9, 0, 11},&#xD;&#xA;    		    {9, 11, 2},&#xD;&#xA;    		    {9, 2, 5},&#xD;&#xA;    		    {7, 2, 11},&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;I calculate the vertex normal using the glut method as well: &#xD;&#xA;&#xD;&#xA;    private static void icosahedron(final GL2 gl) {&#xD;&#xA;       int i;&#xD;&#xA;       for (i = 0; i &lt;= 19; i++) {&#xD;&#xA;         drawtriangle(gl, i, idata, index);&#xD;&#xA;       }&#xD;&#xA;     }&#xD;&#xA;     private static void diff3(final float[] a, final float[] b, final float[] c) {&#xD;&#xA;    	    c[0] = a[0] - b[0];&#xD;&#xA;    	    c[1] = a[1] - b[1];&#xD;&#xA;    	    c[2] = a[2] - b[2];&#xD;&#xA;    	  }&#xD;&#xA;     &#xD;&#xA;     private static void crossprod(final float[] v1, final float[] v2, final float[] prod) {&#xD;&#xA;    	    final float[] p = new float[3];         /* in case prod == v1 or v2 */&#xD;&#xA;    &#xD;&#xA;    	    p[0] = v1[1] * v2[2] - v2[1] * v1[2];&#xD;&#xA;    	    p[1] = v1[2] * v2[0] - v2[2] * v1[0];&#xD;&#xA;    	    p[2] = v1[0] * v2[1] - v2[0] * v1[1];&#xD;&#xA;    	    prod[0] = p[0];&#xD;&#xA;    	    prod[1] = p[1];&#xD;&#xA;    	    prod[2] = p[2];&#xD;&#xA;    	  }&#xD;&#xA;     &#xD;&#xA;     private static void normalize(final float[] v) {&#xD;&#xA;    	    float d;&#xD;&#xA;    &#xD;&#xA;    	    d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);&#xD;&#xA;    	    if (d == 0.0) {&#xD;&#xA;    	      v[0] = d = 1.0f;&#xD;&#xA;    	    }&#xD;&#xA;    	    d = 1 / d;&#xD;&#xA;    	    v[0] *= d;&#xD;&#xA;    	    v[1] *= d;&#xD;&#xA;    	    v[2] *= d;&#xD;&#xA;    	  }&#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;     private static void recorditem(final GL2 gl, final float[] n1, final float[] n2, final float[] n3) {&#xD;&#xA;    	    final float[] q0 = new float[3];&#xD;&#xA;    	    final float[] q1 = new float[3];&#xD;&#xA;    	    final float[] q2 = new float[3];&#xD;&#xA;    	    diff3(n1, n2, q0);&#xD;&#xA;    	    diff3(n2, n3, q1);&#xD;&#xA;    	    crossprod(q0, q1, q2);&#xD;&#xA;    	    normalize(q2);&#xD;&#xA;    	    System.out.format(&quot;%.5f, %.5f, %.5f&quot;,q2[0],q2[1],q2[2]);&#xD;&#xA;    	    gl.glBegin(GL.GL_TRIANGLES);&#xD;&#xA;    	    gl.glNormal3fv(q2,0);&#xD;&#xA;    	    gl.glVertex3fv(n1, 0);&#xD;&#xA;    	    gl.glVertex3fv(n2, 0);&#xD;&#xA;    	    gl.glVertex3fv(n3, 0);&#xD;&#xA;    	    gl.glEnd();&#xD;&#xA;    	  }&#xD;&#xA;     &#xD;&#xA;     private static void subdivide(final GL2 gl, final float[] v0, final float[] v1, final float[] v2) {&#xD;&#xA;    	    int depth;&#xD;&#xA;    	    final float[] w0 = new float[3];&#xD;&#xA;    	    final float[] w1 = new float[3];&#xD;&#xA;    	    final float[] w2 = new float[3];&#xD;&#xA;    	    float l;&#xD;&#xA;    	    int i, j, k, n;&#xD;&#xA;    &#xD;&#xA;    	    depth = 1;&#xD;&#xA;    	    for (i = 0; i &lt; depth; i++) {&#xD;&#xA;    	      for (j = 0; i + j &lt; depth; j++) {&#xD;&#xA;    	        k = depth - i - j;&#xD;&#xA;    	        for (n = 0; n &lt; 3; n++) {&#xD;&#xA;    	          w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;&#xD;&#xA;    	          w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])&#xD;&#xA;    	            / depth;&#xD;&#xA;    	          w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])&#xD;&#xA;    	            / depth;&#xD;&#xA;    	        }&#xD;&#xA;    	        l = (float) Math.sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);&#xD;&#xA;    	        w0[0] /= l;&#xD;&#xA;    	        w0[1] /= l;&#xD;&#xA;    	        w0[2] /= l;&#xD;&#xA;    	        l = (float) Math.sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);&#xD;&#xA;    	        w1[0] /= l;&#xD;&#xA;    	        w1[1] /= l;&#xD;&#xA;    	        w1[2] /= l;&#xD;&#xA;    	        l = (float) Math.sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);&#xD;&#xA;    	        w2[0] /= l;&#xD;&#xA;    	        w2[1] /= l;&#xD;&#xA;    	        w2[2] /= l;&#xD;&#xA;    	        recorditem(gl, w0, w1, w2);&#xD;&#xA;    	      }&#xD;&#xA;    	    }&#xD;&#xA;    	  }  &#xD;&#xA;     &#xD;&#xA;     private static void drawtriangle(final GL2 gl, final int i, final float[][] data, final int[][] ndx) {&#xD;&#xA;           final float[] x0 = data[ndx[i][0]];&#xD;&#xA;           final float[] x1 = data[ndx[i][1]];&#xD;&#xA;           final float[] x2 = data[ndx[i][2]];&#xD;&#xA;           subdivide(gl, x0, x1, x2);&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, the reflection of the light does not look right on the icosahedron. &#xD;&#xA;&#xD;&#xA;My vertex shader: &#xD;&#xA;&#xD;&#xA;    attribute vec3 inposition;//in vec3 position;          //for #version 130&#xD;&#xA;    attribute vec4 incolor;&#xD;&#xA;    attribute vec3 innormal;&#xD;&#xA;    attribute vec2 intexcoord0;&#xD;&#xA;    varying vec3 normal;&#xD;&#xA;    varying vec4 color;&#xD;&#xA;    varying vec2 texcoord;&#xD;&#xA;    varying vec3 pos;        &#xD;&#xA;    uniform mat4 mat[4];&#xD;&#xA;     &#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;      normal = normalize((mat[3]*vec4(innormal,0.0)).xyz);&#xD;&#xA;      color = incolor;&#xD;&#xA;      texcoord = intexcoord0;&#xD;&#xA;      gl_Position = mat[0]*mat[1]*vec4(inposition, 1.0);&#xD;&#xA;    //  gl_Position = vec4(inposition, 1.0);&#xD;&#xA;      pos = gl_Position.xyz; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here innormal is the vertex normal, and inposition are the coordinates of the vertices. &#xD;&#xA;&#xD;&#xA;And my frag shader is : &#xD;&#xA;&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform vec3 lightpos;&#xD;&#xA;    uniform vec3 lightColor;&#xD;&#xA;    uniform vec3 objectColor;&#xD;&#xA;    varying vec3 normal;&#xD;&#xA;    varying vec4 color;&#xD;&#xA;    varying vec2 texcoord;&#xD;&#xA;    varying vec3 pos; &#xD;&#xA;    &#xD;&#xA;    void main (void){&#xD;&#xA;    //  gl_FragColor = max(texture2D(texture0, texcoord),color.xyzw);&#xD;&#xA;    //  gl_FragColor = texture2D(texture0, texcoord);&#xD;&#xA;    //  gl_FragColor = vec4(0.3, 0.8, 0.2, 1.0);&#xD;&#xA;    //  vec2 dfdx = abs(dFdx(texcoord));&#xD;&#xA;    //  vec2 dfdy = abs(dFdy(texcoord));&#xD;&#xA;    //  float d = max(max(dfdx.x,dfdx.y),max(dfdy.x,dfdy.y));&#xD;&#xA;    //  gl_FragColor = vec4(d*20,0,0,1);&#xD;&#xA;        &#xD;&#xA;    vec3 light = lightpos- pos;&#xD;&#xA;        //light = lightpos;&#xD;&#xA;    &#xD;&#xA;    vec3 norm = normalize(normal);&#xD;&#xA;    vec3 eye_vector = vec3(0.0);&#xD;&#xA;    vec3 viewDir = normalize(eye_vector - pos);&#xD;&#xA;    vec3 lightDir = normalize(light);&#xD;&#xA;    vec3 reflectDir = reflect(lightDir,norm);&#xD;&#xA;    float spec = pow(dot(viewDir,reflectDir), 100.0);&#xD;&#xA;    float specularStrength = 0.5;&#xD;&#xA;    vec3 lightColor = vec3(1.0);&#xD;&#xA;    vec3 spect = spec*specularStrength*lightColor; &#xD;&#xA;    &#xD;&#xA;    gl_FragColor = vec4((0.9*max(dot(normal, normalize(light)),0.0)+0.1)*color.xyz,1.0) + vec4(vec3(spect),1.0);&#xD;&#xA;&#xD;&#xA;The lightpos is the position of the light which is (0,0,10);&#xD;&#xA;&#xD;&#xA;Somehow the result looks like this: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YwDWN.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which doesn't look right. Could anyone give me some hints please? " ContentLicense="CC BY-SA 4.0" />
  <row Id="22999" PostHistoryTypeId="1" PostId="8539" RevisionGUID="2f9ed7e5-5120-4657-91e3-e7a49ff8d6bf" CreationDate="2019-02-01T06:32:34.783" UserId="10105" Text="Specular/Diffuse light on an icosahedron opengl" ContentLicense="CC BY-SA 4.0" />
  <row Id="23000" PostHistoryTypeId="3" PostId="8539" RevisionGUID="2f9ed7e5-5120-4657-91e3-e7a49ff8d6bf" CreationDate="2019-02-01T06:32:34.783" UserId="10105" Text="|opengl|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23006" PostHistoryTypeId="2" PostId="8542" RevisionGUID="2f165f53-d2a4-475f-8ec8-86654a07aba2" CreationDate="2019-02-01T09:42:44.870" UserId="10103" Text="Unfortunately, the iridescence model is not made to be applied to a diffuse term. Pascal and I made it for microfacet models only (that is the specular term).&#xD;&#xA;&#xD;&#xA;One way to understand how to include it to a game engine might be to look at Unity's HDRP implementation.&#xD;&#xA;&#xD;&#xA;In the Lit.hlsl to see how to incorporate the iridescence Fresnel into a specular + diffuse BRDF:&#xD;&#xA;&#xD;&#xA;https://github.com/Unity-Technologies/ScriptableRenderPipeline/blob/master/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl&#xD;&#xA;&#xD;&#xA;    PreLightData GetPreLightData(float3 V, PositionInputs posInput, inout BSDFData bsdfData) {&#xD;&#xA;&#xD;&#xA;        [...]&#xD;&#xA;&#xD;&#xA;        if (bsdfData.iridescenceMask &gt; 0.0)&#xD;&#xA;        {&#xD;&#xA;            bsdfData.fresnel0 = lerp(bsdfData.fresnel0, EvalIridescence(topIor, viewAngle, bsdfData.iridescenceThickness, bsdfData.fresnel0), bsdfData.iridescenceMask);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;See the implementation of the `EvalIridescence` in BSDF.hlsl:&#xD;&#xA;&#xD;&#xA;https://github.com/Unity-Technologies/ScriptableRenderPipeline/blob/30f1b16c8094ca133c165e56380ebb7ab9e7c0d9/com.unity.render-pipelines.core/ShaderLibrary/BSDF.hlsl&#xD;&#xA;&#xD;&#xA;What they are doing is to blend the standard Fresnel term with the iridescence one based on a iridescence mask value.&#xD;&#xA;&#xD;&#xA;I hope this is helpfull." ContentLicense="CC BY-SA 4.0" />
  <row Id="23007" PostHistoryTypeId="5" PostId="8539" RevisionGUID="251d2d6a-94d5-4a67-95db-37b5d4227bcd" CreationDate="2019-02-01T09:52:08.363" UserId="10107" Comment="changes of the question" Text="I'm having a problem with my model here. I draw an icosahedron using GLUT, and the radius is set to 0.8. The info of the coordinates are listed below: (X and Z are calculated since our radius is 0.8)&#xD;&#xA;&#xD;&#xA;     private static final float X = .4205912828f;&#xD;&#xA;     private static final float Z = .6805166955f;&#xD;&#xA;     private static final float[][] idata =&#xD;&#xA;    {&#xD;&#xA;       {-X, 0, Z},&#xD;&#xA;       {X, 0, Z},&#xD;&#xA;       {-X, 0, -Z},&#xD;&#xA;       {X, 0, -Z},&#xD;&#xA;       {0, Z, X},&#xD;&#xA;       {0, Z, -X},&#xD;&#xA;       {0, -Z, X},&#xD;&#xA;       {0, -Z, -X},&#xD;&#xA;       {Z, X, 0},&#xD;&#xA;       {-Z, X, 0},&#xD;&#xA;       {Z, -X, 0},&#xD;&#xA;       {-Z, -X, 0}&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;    private static final int[][] index =&#xD;&#xA;     {&#xD;&#xA;    		 {0, 4, 1},&#xD;&#xA;    		    {0, 9, 4},&#xD;&#xA;    		    {9, 5, 4},&#xD;&#xA;    		    {4, 5, 8},&#xD;&#xA;    		    {4, 8, 1},&#xD;&#xA;    		    {8, 10, 1},&#xD;&#xA;    		    {8, 3, 10},&#xD;&#xA;    		    {5, 3, 8},&#xD;&#xA;    		    {5, 2, 3},&#xD;&#xA;    		    {2, 7, 3},&#xD;&#xA;    		    {7, 10, 3},&#xD;&#xA;    		    {7, 6, 10},&#xD;&#xA;    		    {7, 11, 6},&#xD;&#xA;    		    {11, 0, 6},&#xD;&#xA;    		    {0, 1, 6},&#xD;&#xA;    		    {6, 1, 10},&#xD;&#xA;    		    {9, 0, 11},&#xD;&#xA;    		    {9, 11, 2},&#xD;&#xA;    		    {9, 2, 5},&#xD;&#xA;    		    {7, 2, 11},&#xD;&#xA;     };&#xD;&#xA;&#xD;&#xA;I calculate the vertex normal using the glut method as well: &#xD;&#xA;&#xD;&#xA;    private static void icosahedron(final GL2 gl) {&#xD;&#xA;       int i;&#xD;&#xA;       for (i = 0; i &lt;= 19; i++) {&#xD;&#xA;         drawtriangle(gl, i, idata, index);&#xD;&#xA;       }&#xD;&#xA;     }&#xD;&#xA;     private static void diff3(final float[] a, final float[] b, final float[] c) {&#xD;&#xA;    	    c[0] = a[0] - b[0];&#xD;&#xA;    	    c[1] = a[1] - b[1];&#xD;&#xA;    	    c[2] = a[2] - b[2];&#xD;&#xA;    	  }&#xD;&#xA;     &#xD;&#xA;     private static void crossprod(final float[] v1, final float[] v2, final float[] prod) {&#xD;&#xA;    	    final float[] p = new float[3];         /* in case prod == v1 or v2 */&#xD;&#xA;    &#xD;&#xA;    	    p[0] = v1[1] * v2[2] - v2[1] * v1[2];&#xD;&#xA;    	    p[1] = v1[2] * v2[0] - v2[2] * v1[0];&#xD;&#xA;    	    p[2] = v1[0] * v2[1] - v2[0] * v1[1];&#xD;&#xA;    	    prod[0] = p[0];&#xD;&#xA;    	    prod[1] = p[1];&#xD;&#xA;    	    prod[2] = p[2];&#xD;&#xA;    	  }&#xD;&#xA;     &#xD;&#xA;     private static void normalize(final float[] v) {&#xD;&#xA;    	    float d;&#xD;&#xA;    &#xD;&#xA;    	    d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);&#xD;&#xA;    	    if (d == 0.0) {&#xD;&#xA;    	      v[0] = d = 1.0f;&#xD;&#xA;    	    }&#xD;&#xA;    	    d = 1 / d;&#xD;&#xA;    	    v[0] *= d;&#xD;&#xA;    	    v[1] *= d;&#xD;&#xA;    	    v[2] *= d;&#xD;&#xA;    	  }&#xD;&#xA;    &#xD;&#xA;     &#xD;&#xA;     private static void recorditem(final GL2 gl, final float[] n1, final float[] n2, final float[] n3) {&#xD;&#xA;    	    final float[] q0 = new float[3];&#xD;&#xA;    	    final float[] q1 = new float[3];&#xD;&#xA;    	    final float[] q2 = new float[3];&#xD;&#xA;    	    diff3(n1, n2, q0);&#xD;&#xA;    	    diff3(n2, n3, q1);&#xD;&#xA;    	    crossprod(q0, q1, q2);&#xD;&#xA;    	    normalize(q2);&#xD;&#xA;    	    System.out.format(&quot;%.5f, %.5f, %.5f&quot;,q2[0],q2[1],q2[2]);&#xD;&#xA;    	    gl.glBegin(GL.GL_TRIANGLES);&#xD;&#xA;    	    gl.glNormal3fv(q2,0);&#xD;&#xA;    	    gl.glVertex3fv(n1, 0);&#xD;&#xA;    	    gl.glVertex3fv(n2, 0);&#xD;&#xA;    	    gl.glVertex3fv(n3, 0);&#xD;&#xA;    	    gl.glEnd();&#xD;&#xA;    	  }&#xD;&#xA;     &#xD;&#xA;     private static void subdivide(final GL2 gl, final float[] v0, final float[] v1, final float[] v2) {&#xD;&#xA;    	    int depth;&#xD;&#xA;    	    final float[] w0 = new float[3];&#xD;&#xA;    	    final float[] w1 = new float[3];&#xD;&#xA;    	    final float[] w2 = new float[3];&#xD;&#xA;    	    float l;&#xD;&#xA;    	    int i, j, k, n;&#xD;&#xA;    &#xD;&#xA;    	    depth = 1;&#xD;&#xA;    	    for (i = 0; i &lt; depth; i++) {&#xD;&#xA;    	      for (j = 0; i + j &lt; depth; j++) {&#xD;&#xA;    	        k = depth - i - j;&#xD;&#xA;    	        for (n = 0; n &lt; 3; n++) {&#xD;&#xA;    	          w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;&#xD;&#xA;    	          w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])&#xD;&#xA;    	            / depth;&#xD;&#xA;    	          w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])&#xD;&#xA;    	            / depth;&#xD;&#xA;    	        }&#xD;&#xA;    	        l = (float) Math.sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);&#xD;&#xA;    	        w0[0] /= l;&#xD;&#xA;    	        w0[1] /= l;&#xD;&#xA;    	        w0[2] /= l;&#xD;&#xA;    	        l = (float) Math.sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);&#xD;&#xA;    	        w1[0] /= l;&#xD;&#xA;    	        w1[1] /= l;&#xD;&#xA;    	        w1[2] /= l;&#xD;&#xA;    	        l = (float) Math.sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);&#xD;&#xA;    	        w2[0] /= l;&#xD;&#xA;    	        w2[1] /= l;&#xD;&#xA;    	        w2[2] /= l;&#xD;&#xA;    	        recorditem(gl, w0, w1, w2);&#xD;&#xA;    	      }&#xD;&#xA;    	    }&#xD;&#xA;    	  }  &#xD;&#xA;     &#xD;&#xA;     private static void drawtriangle(final GL2 gl, final int i, final float[][] data, final int[][] ndx) {&#xD;&#xA;           final float[] x0 = data[ndx[i][0]];&#xD;&#xA;           final float[] x1 = data[ndx[i][1]];&#xD;&#xA;           final float[] x2 = data[ndx[i][2]];&#xD;&#xA;           subdivide(gl, x0, x1, x2);&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, the reflection of the light does not look right on the icosahedron. &#xD;&#xA;&#xD;&#xA;My vertex shader: &#xD;&#xA;&#xD;&#xA;    attribute vec3 inposition;//in vec3 position;          //for #version 130&#xD;&#xA;    attribute vec4 incolor;&#xD;&#xA;    attribute vec3 innormal;&#xD;&#xA;    attribute vec2 intexcoord0;&#xD;&#xA;    varying vec3 normal;&#xD;&#xA;    varying vec4 color;&#xD;&#xA;    varying vec2 texcoord;&#xD;&#xA;    varying vec3 pos;        &#xD;&#xA;    uniform mat4 mat[4];&#xD;&#xA;     &#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;      normal = normalize((mat[3]*vec4(innormal,0.0)).xyz);&#xD;&#xA;      color = incolor;&#xD;&#xA;      texcoord = intexcoord0;&#xD;&#xA;      gl_Position = mat[0]*mat[1]*vec4(inposition, 1.0);&#xD;&#xA;    //  gl_Position = vec4(inposition, 1.0);&#xD;&#xA;      pos = gl_Position.xyz; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here innormal is the vertex normal, and inposition are the coordinates of the vertices. &#xD;&#xA;&#xD;&#xA;And my frag shader is : &#xD;&#xA;&#xD;&#xA;    uniform sampler2D texture0;&#xD;&#xA;    uniform vec3 lightpos;&#xD;&#xA;    uniform vec3 lightColor;&#xD;&#xA;    uniform vec3 objectColor;&#xD;&#xA;    varying vec3 normal;&#xD;&#xA;    varying vec4 color;&#xD;&#xA;    varying vec2 texcoord;&#xD;&#xA;    varying vec3 pos; &#xD;&#xA;    &#xD;&#xA;    void main (void){&#xD;&#xA;    //  gl_FragColor = max(texture2D(texture0, texcoord),color.xyzw);&#xD;&#xA;    //  gl_FragColor = texture2D(texture0, texcoord);&#xD;&#xA;    //  gl_FragColor = vec4(0.3, 0.8, 0.2, 1.0);&#xD;&#xA;    //  vec2 dfdx = abs(dFdx(texcoord));&#xD;&#xA;    //  vec2 dfdy = abs(dFdy(texcoord));&#xD;&#xA;    //  float d = max(max(dfdx.x,dfdx.y),max(dfdy.x,dfdy.y));&#xD;&#xA;    //  gl_FragColor = vec4(d*20,0,0,1);&#xD;&#xA;        &#xD;&#xA;    vec3 light = lightpos- pos;&#xD;&#xA;        //light = lightpos;&#xD;&#xA;    &#xD;&#xA;    vec3 norm = normalize(normal);&#xD;&#xA;    vec3 eye_vector = vec3(0.0);&#xD;&#xA;    vec3 viewDir = normalize(eye_vector - pos);&#xD;&#xA;    vec3 lightDir = normalize(light);&#xD;&#xA;    vec3 reflectDir = reflect(lightDir,norm);&#xD;&#xA;    float spec = pow(dot(viewDir,reflectDir), 100.0);&#xD;&#xA;    float specularStrength = 0.5;&#xD;&#xA;    vec3 lightColor = vec3(1.0);&#xD;&#xA;    vec3 spect = spec*specularStrength*lightColor; &#xD;&#xA;    &#xD;&#xA;    gl_FragColor = vec4((0.9*max(dot(normal, normalize(light)),0.0)+0.1)*color.xyz,1.0) + vec4(vec3(spect),1.0);&#xD;&#xA;&#xD;&#xA;The lightpos is the position of the light which is (0,0,10);&#xD;&#xA;&#xD;&#xA;Somehow the result looks like this: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;which doesn't look right. Could anyone give me some hints please? &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is the vertex data and &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is how mat[4] produced. And the following is the normal output by @PaulHK 's idea, and it is broken. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YwDWN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cnp5F.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PKtgA.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ocB8L.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/VtaWY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23008" PostHistoryTypeId="24" PostId="8539" RevisionGUID="251d2d6a-94d5-4a67-95db-37b5d4227bcd" CreationDate="2019-02-01T09:52:08.363" Comment="Proposed by 10107 approved by 209, 182 edit id of 459" ContentLicense="CC BY-SA 4.0" />
  <row Id="23011" PostHistoryTypeId="2" PostId="8544" RevisionGUID="0481d6ae-c025-40c8-9936-f0930a9f4e97" CreationDate="2019-02-01T19:29:16.050" UserId="10110" Text="**In case its  wrong forum , please let me know and delete from here**&#xD;&#xA;&#xD;&#xA;I am looking for a stable way to find a contrast / inverted / opposite color to a given one&#xD;&#xA;&#xD;&#xA;Application of this is to find best possible color for foreground to give background.&#xD;&#xA;&#xD;&#xA;Thank you in advance" ContentLicense="CC BY-SA 4.0" />
  <row Id="23012" PostHistoryTypeId="1" PostId="8544" RevisionGUID="0481d6ae-c025-40c8-9936-f0930a9f4e97" CreationDate="2019-02-01T19:29:16.050" UserId="10110" Text="Getting contrast color to a given color in RGB or ARGB or HEX" ContentLicense="CC BY-SA 4.0" />
  <row Id="23013" PostHistoryTypeId="3" PostId="8544" RevisionGUID="0481d6ae-c025-40c8-9936-f0930a9f4e97" CreationDate="2019-02-01T19:29:16.050" UserId="10110" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23014" PostHistoryTypeId="5" PostId="2495" RevisionGUID="3da9ef4a-a7f3-4482-b1cc-f74a3a1513ad" CreationDate="2019-02-01T22:16:01.837" UserId="5353" Comment="corrected the formule BDSF = BRDF + &gt;BTDF&lt; : instead of BSTF" Text="In Schlick's 1994 paper, [&quot;An Inexpensive Model for Physically-Based Rendering&quot;][1], where they derive the approximation, the formula is:&#xD;&#xA;$$F_{\lambda}(u) = f_{\lambda} + (1 - f_{\lambda})(1 - u)^{5}$$&#xD;&#xA;&#xD;&#xA;Where &#xD;&#xA;&#xD;&#xA;![Description of vectors][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, to answer your first question, $\theta$ refers to the angle between the view vector and the half vector. Consider for a minute that the surface is a perfect mirror. So:&#xD;&#xA;$$V \equiv reflect(V')$$&#xD;&#xA;In this case:&#xD;&#xA;$$N \equiv H$$&#xD;&#xA;&#xD;&#xA;For microfacet-base BRDFs, the $D(h_{r})$ term refers to the statistical percentage of microfacet normals that are oriented towards $H$. Aka, what percentage of the incoming light will bounce in the outgoing direction.&#xD;&#xA;&#xD;&#xA;As for why we use Fresnel in a BRDF, it has to do with the fact that a BRDF by itself is only a portion of the full BSDF. A BRDF attenuates the reflected portion of light and a BTDF attenuates the refracted. We use the Fresnel to calculate the amount of reflected vs. refracted light, so we can properly attenuate it with the BRDF and BTDF.&#xD;&#xA;&#xD;&#xA;$$BSDF = BRDF + BTDF\\&#xD;&#xA;$$&#xD;&#xA;$$\begin{align*}&#xD;&#xA;L_{\text{o}}(p, \omega_{\text{o}}) &amp;=  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BSDF * L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} \\&#xD;&#xA; &amp;= L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BRDF * L_{\text{i, reflected}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}  \ + \  \int_{\Omega} BTDF * L_{\text{i, refracted}}(p, \omega_{\text{i}}) * \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}&#xD;&#xA;\end{align*}$$&#xD;&#xA;&#xD;&#xA;So, in summary, we use $D$ to get the percentage of light that will bounce in the outgoing direction, and $F$, to find out what percentage of the remaining light will reflect/refract. Both these use $H$, because that is the surface orientation that allows a mirror reflection between $V$ and $V'$&#xD;&#xA;  [1]: http://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/xxyc2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23015" PostHistoryTypeId="24" PostId="2495" RevisionGUID="3da9ef4a-a7f3-4482-b1cc-f74a3a1513ad" CreationDate="2019-02-01T22:16:01.837" Comment="Proposed by 5353 approved by 209, 310 edit id of 458" ContentLicense="CC BY-SA 4.0" />
  <row Id="23018" PostHistoryTypeId="2" PostId="8545" RevisionGUID="bb8d3a2a-ecb8-4cd2-a263-84ef145af0d1" CreationDate="2019-02-02T15:41:57.170" UserId="6046" Text="So after reading up some more research papers and the concepts of most people working in this field here and there, I've reached an answer I'm satisfied with. If someone disagrees or thinks there is a better or more correct way to think the problem do share your ideas.&#xD;&#xA;&#xD;&#xA;1) First to answer my point 1. I've noticed that most di-electric surfaces' Index of refraction remains fairly constant over the visible spectrum. This means the Fresnel Reflectances remain constant and are quite low over the visible spectrum for normal incidence. For angles near 90 degrees, even rough di-electric surfaces start reflecting the incoming light specularly. You can see this data [here][1]&#xD;&#xA;&#xD;&#xA;However in the case of metals the IOR or more specifically the Fresnel Reflectances take on the exact same value as the color (in case of gold and copper). From this I conclude that, &#xD;&#xA;&#xD;&#xA;For metals where Fresnel Reflectances (FR) vary greatly over the visible spectrum, FR is linked and is just a consequence of the surface of metals absorbing photons of certain frequencies. This means for Gold, the electrons at the surface absorb the blue-end of the spectrum, the remaining golden colored light either gets reflected or refracted. Thus the Fresnel Reflectance is golden in color which we can also call the &quot;Specular Color&quot;. &#xD;&#xA;Note that the absorption depends on whether there are electrons available. It's possible for some blue photons to refract or reflect if there aren't much electrons for absorbing to begin with. &#xD;&#xA;&#xD;&#xA;In-case of di-electrics the FR don't change much over the visible spectrum. However we can see color. The possible explanation is that the color in case of di-electrics comes from within the surface. That is, there are no such electrons present at the &quot;interface&quot; that absorb certain frequencies. Else we would have seen different FR for different wavelengths. The electrons absorbing wavelengths of certain frequencies come from within the surface, like pigments lying inside a liquid. Hence for di-electrics FR is not really linked to the concept of electrons absorbing certain frequencies imo.&#xD;&#xA;&#xD;&#xA;This makes sense to me as colored metals (gold, copper) tint the reflections with their color. However certain di-electrics don't such as a polished marble floor. The reason for that again is that in case of metals the cause of color i.e. absorption by electrons occurs directly on the surface. The reflected light thus has a different composition for R,G,B giving us the tint. However for di-electrics the cause of color lies beneath the surface. Hence the reflection is non-tinted.&#xD;&#xA;&#xD;&#xA;**Thus simply stating for metals FR is the same as the albedo/color of the surface. For non-metals or di-electrics FR is different from the albedo/color and just defines the amount of specular reflection.**&#xD;&#xA;&#xD;&#xA;2) The proper way would surely be to use a BRDF with both diffuse and specular components since diffuse surfaces reflect greatly at near-grazing angles.&#xD;&#xA;&#xD;&#xA;3) Still don't know about this. It might be baked in or not. What I do know is that the diffuse component should surely get lesser and specular component larger as angle increases to 90.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another interesting point to note is that the basic Fresnel Equations apply for transparent and Flat surfaces. For metals we have complex IOR making the equations a little more complex. Sebastian Lagarde did a comparison [here][2]. Fresnel equations don't apply to rough surfaces but for microfacet models where we assume each facet to be perfectly specular we can maybe. Either way they are a good way to approximate the behaviour for increasing reflection near 90 degrees.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://refractiveindex.info/?shelf=main&amp;book=Au&amp;page=Johnson&#xD;&#xA;  [2]: https://seblagarde.wordpress.com/2013/04/29/memo-on-fresnel-equations/" ContentLicense="CC BY-SA 4.0" />
  <row Id="23019" PostHistoryTypeId="2" PostId="8546" RevisionGUID="8658cce9-3d8a-422f-a9a5-c15cf1ca9ff0" CreationDate="2019-02-03T01:54:46.523" UserId="3003" Text="I read this in a magazine article probably 25 years ago. I don't recall the full derivation, but they said to take each component (red, green, and blue) and invert the high bit of the color. In a C-like programming language, you could do:&#xD;&#xA;&#xD;&#xA;     component = (~component &amp; 0x80) | (component &amp; 0x7F);&#xD;&#xA;&#xD;&#xA;This assumes your components are 8-bit values. This avoids the problems you get with the middle values if you simply invert them. In that case 127 becomes 128, and vice-versa. But with the above solution, 127 becomes 255 and 128 becomes 0." ContentLicense="CC BY-SA 4.0" />
  <row Id="23021" PostHistoryTypeId="2" PostId="8547" RevisionGUID="f05e7617-8245-4806-8020-a15b7e1a7985" CreationDate="2019-02-03T11:28:48.040" UserId="2308" Text="Now I know this isn't the way this is normally done so please bear with me. I am doing this this way so I know I have a solid conceptual understanding of everything that goes beyond example code.&#xD;&#xA;&#xD;&#xA;I am trying to create a simple 2D game with sprites that and rotate, move, scale etc.&#xD;&#xA;&#xD;&#xA;I thus constructed the following matrices &#xD;&#xA;&#xD;&#xA;**Transform**&#xD;&#xA;&#xD;&#xA;I want the sprites center to move from the origin by (`x`, `y`) units&#xD;&#xA;&#xD;&#xA;$$T = \begin{bmatrix} &#xD;&#xA;1 &amp; 0 &amp; x \\&#xD;&#xA;0 &amp; 1 &amp; y \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;**Rotation**&#xD;&#xA;&#xD;&#xA;I want the matrix to rotate by `d` radians so I create the following variables where `s = sin(d)` and `c = cos(d)`&#xD;&#xA;&#xD;&#xA;$$R = \begin{bmatrix} &#xD;&#xA;c &amp; -s &amp; 0 \\&#xD;&#xA;s &amp; c &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;**Scale**&#xD;&#xA;&#xD;&#xA;I want the rectangular sprite to occupy a horizontal units and b vertical units so I generated the following matrix&#xD;&#xA;&#xD;&#xA;$$S= \begin{bmatrix} &#xD;&#xA;a &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; b &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix} $$&#xD;&#xA;&#xD;&#xA;**Center**&#xD;&#xA;&#xD;&#xA;And finally I want the sprite to do all of these transformations with its center of movement being at (`u`, `v`) therefore I will plan to have to use a matrix sort of like this (you'll see why later) &#xD;&#xA;&#xD;&#xA;$$A = \begin{bmatrix} &#xD;&#xA;1 &amp; 0 &amp; -u \\&#xD;&#xA;0 &amp; 1 &amp; -v \\&#xD;&#xA;0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Now the plan is to stream in the points (0, 0) (0, 1) (1, 1) and (1, 0) into my vertex shader and then use **a single** matrix to translate the points to where they need to go.&#xD;&#xA;&#xD;&#xA;So I assumed that I could combine all these matrices as follows based on code examples etc. &#xD;&#xA;&#xD;&#xA;$$A * S * R * T$$&#xD;&#xA;&#xD;&#xA;So I pulled these matrixes into Symbolab and got the following result&#xD;&#xA;&#xD;&#xA;[![Picture of symbolab result][1]][1]&#xD;&#xA;&#xD;&#xA;Great! So time to pass it in. Now Metal uses SIMD but I need my engine to be completely cross platform so instead I read the SIMD alignment guides and tried to match them with this struct: &#xD;&#xA;&#xD;&#xA;    struct float3x3 {&#xD;&#xA;        float columns[3][4];&#xD;&#xA;        &#xD;&#xA;        float3x3() {&#xD;&#xA;            for (int i = 0; i &lt; 3; i++) {&#xD;&#xA;                for (int j = 0; j &lt; 4; j++) {&#xD;&#xA;                    rows[i][j] = 0;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    } __attribute__ ((aligned(16))) ;&#xD;&#xA;&#xD;&#xA;Which means inside of my CPU code I can create the matrix like this (based on the symbolab result)&#xD;&#xA;&#xD;&#xA;    float3x3 matrix;&#xD;&#xA;    matrix.columns[0][0] = a * c;&#xD;&#xA;    matrix.columns[1][0] = -a * s;&#xD;&#xA;    matrix.columns[2][0] = a * c * x - a * s * y + u;&#xD;&#xA;    matrix.columns[0][1] = s * b;&#xD;&#xA;    matrix.columns[1][1] = b * c;&#xD;&#xA;    matrix.columns[2][1] = b * s * x + b * c * y + v;&#xD;&#xA;    matrix.columns[2][2] = 1;&#xD;&#xA;&#xD;&#xA;And pass it in like this &#xD;&#xA;&#xD;&#xA;    [encoder setVertexBytes:&amp;matrix length:sizeof(simd_float3x3) atIndex:2];&#xD;&#xA;&#xD;&#xA;And then finally I can pass it into my vertex shader which looks like this&#xD;&#xA;&#xD;&#xA;    vertex ColorInOut tex_plain_vert(uint vid [[vertex_id]],&#xD;&#xA;                                     constant matrix_float3x3* worldMatrix [[buffer(3)]],&#xD;&#xA;                                     constant matrix_float3x3* localMatrix [[buffer(2)]]) {&#xD;&#xA;        float2 coords[] = {float2(0, 0),&#xD;&#xA;            float2(1.0, 0),&#xD;&#xA;            float2(0, 1.0),&#xD;&#xA;            float2(1.0, 1.0)};&#xD;&#xA;        &#xD;&#xA;        const float2 texc[] = {float2(0.0, 1.0),&#xD;&#xA;            float2(1.0, 1.0),&#xD;&#xA;            float2(0.0, 0.0),&#xD;&#xA;            float2(1.0, 0.0)};&#xD;&#xA;        &#xD;&#xA;        const int lu[] = {0, 1, 2, 2, 1, 3};&#xD;&#xA;        &#xD;&#xA;        ColorInOut out;&#xD;&#xA;        out.texCoord = texc[lu[vid]];&#xD;&#xA;        float3 padded = float3(coords[lu[vid]], 1.0);&#xD;&#xA;        matrix_float3x3 w = *worldMatrix;&#xD;&#xA;        matrix_float3x3 l = *localMatrix;&#xD;&#xA;        float3 res = w * l * padded;&#xD;&#xA;        out.position = float4(res.x, res.y, 0.0 , 1.0);&#xD;&#xA;        return out;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However this doesnt work. Depending on how I have messed with things the square is either wildly off screen or doesn't translate to the (`x`, `y`) at all.&#xD;&#xA;&#xD;&#xA;And yes my world matrix is VERY thoroughly tested and you will see in a bit that it is wrong even without that value.&#xD;&#xA;&#xD;&#xA;So I pulled it into the vertex debugger and got the following information with the following variables&#xD;&#xA;&#xD;&#xA;    x = 0&#xD;&#xA;    y = 50&#xD;&#xA;    s = 0&#xD;&#xA;    c = 1&#xD;&#xA;    a = 120&#xD;&#xA;    b = 120&#xD;&#xA;    u = 0.5&#xD;&#xA;    v = 0.5&#xD;&#xA;&#xD;&#xA;[![Vertex debugger][2]][2]&#xD;&#xA;&#xD;&#xA;p2 is where you can really see the error with those settings `0,0` should have translated to `-60,-10` and `1, 0` should have translated to `60, -60`. None of these huge numbers and it is my inclination to think that it is mostly the 3rd column of the matrix at fault.&#xD;&#xA;&#xD;&#xA;My inclination based on seeing these results is that the matrix I am passing in is wrong. But I dont know another way to do that math.&#xD;&#xA;&#xD;&#xA;I have also tried tweaking things like switching rows and columns changing multiplication order to no avial. The closest I have gotten was something that rotated and scaled but did not move and one that moved but had sheering effects.&#xD;&#xA;&#xD;&#xA;There are a lot of places in this process that I could have gone wrong (initial matrices, matrix multiplication\order, matrix struct, vertex shader, etc) and I would really appreciate your help finding it as I have spent awhile on this now.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KN4Jz.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LM4g5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23022" PostHistoryTypeId="1" PostId="8547" RevisionGUID="f05e7617-8245-4806-8020-a15b7e1a7985" CreationDate="2019-02-03T11:28:48.040" UserId="2308" Text="My 2D translation matrix causes the box to be off screen when it shouldnt be" ContentLicense="CC BY-SA 4.0" />
  <row Id="23023" PostHistoryTypeId="3" PostId="8547" RevisionGUID="f05e7617-8245-4806-8020-a15b7e1a7985" CreationDate="2019-02-03T11:28:48.040" UserId="2308" Text="|transformations|matrix|2d|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23024" PostHistoryTypeId="5" PostId="8544" RevisionGUID="4bafc697-391d-4c51-8a84-ba24a6a20eaa" CreationDate="2019-02-03T14:59:10.030" UserId="6" Comment="deleted 101 characters in body" Text="I am looking for a stable way to find a contrast/inverted/opposite color to a given one.&#xD;&#xA;&#xD;&#xA;Application of this is to find best possible color for foreground to give background." ContentLicense="CC BY-SA 4.0" />
  <row Id="23026" PostHistoryTypeId="2" PostId="8548" RevisionGUID="ed5a6a03-2f61-431a-b86e-cfce77e13dbd" CreationDate="2019-02-03T19:55:44.850" UserId="10117" Text="I have created a 3D model of a local outdoor performance space and I have an app that uses Metal on MacOS 10.14.2 to display the model. I want to create an animation by flying the camera around the scene, while recording each frame (actually every other frame for 30 fps). I know how to do the animated fly-around and I know how to create a video frame-by-frame with AVFoundation. The step for which I can find no information is how I can capture each frame.&#xD;&#xA;&#xD;&#xA;I have a completion handler so I know when the gpu has finished each command buffer.&#xD;&#xA;&#xD;&#xA;But what is the best way to get the image in CPU space?&#xD;&#xA;&#xD;&#xA;I thought perhaps I could do this by attaching a second texture to colorAttachments[1] but this has resulted in some odd behavior where the original scene that used to fill my MTKView window now occupies just the upper left quadrant of the window.&#xD;&#xA;&#xD;&#xA;What I was trying to do is write the same color to both colorAttachments[0] (my screen) and to colorAttachments[1]. In my shader I defined:&#xD;&#xA;&#xD;&#xA;    struct FragmentOut {&#xD;&#xA;        float4 color0 [[ color(0) ]];&#xD;&#xA;        float4 color1 [[ color(1) ]];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;My fragment shader looks like:&#xD;&#xA;&#xD;&#xA;    fragment FragmentOut grove_fragment_function(&#xD;&#xA;        VertexOut vIn [[ stage_in ]],&#xD;&#xA;        constant Uniforms &amp;uniforms [[buffer(1)]]) {&#xD;&#xA;     ....&#xD;&#xA;        float4 color = diffuseColor + ambientColor + specularColor;&#xD;&#xA;        out.color0 = color;&#xD;&#xA;        out.color1 = color;&#xD;&#xA;        return out;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My hope was that I could then use something like:&#xD;&#xA;&#xD;&#xA;    offScreenTextureBuffer?.getBytes(buffer, bytesPerRow: 4 * w, from: MTLRegionMake2D(0, 0, w, h), mipmapLevel: 0)&#xD;&#xA;&#xD;&#xA;to transfer the image data to a local buffer.&#xD;&#xA;This doesn't seem to work, plus I have the unexpected display behavior noted above.&#xD;&#xA;&#xD;&#xA;I am configuring the offScreenTextureBuffer thus:&#xD;&#xA;&#xD;&#xA;    let pixelFormat = MTLPixelFormat.bgra8Unorm_srgb&#xD;&#xA;    var offScreenBufferDescriptor =  MTLTextureDescriptor.texture2DDescriptor(pixelFormat: pixelFormat,                                                                             width: 1000,                                                                             height: 600,                                                                            mipmapped: false)&#xD;&#xA;    offScreenBufferDescriptor.usage = [.renderTarget, .shaderRead]&#xD;&#xA;    offScreenTextureBuffer = device.makeTexture(descriptor: offScreenBufferDescriptor)&#xD;&#xA;&#xD;&#xA;I also tried to use the presentation layer from my MTKView. I can get the texture from the presentation layer but when I try to use the getBytes() func on the returned texture I get an error because the buffer is configured as &quot;framebufferonly&quot;. A presentation layer that can't be read doesn't seem particularly useful.&#xD;&#xA;&#xD;&#xA;Any suggestions on how to capture each frame would be appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="23027" PostHistoryTypeId="1" PostId="8548" RevisionGUID="ed5a6a03-2f61-431a-b86e-cfce77e13dbd" CreationDate="2019-02-03T19:55:44.850" UserId="10117" Text="How to capture frames in a MacOS MTKView for recording to a video" ContentLicense="CC BY-SA 4.0" />
  <row Id="23028" PostHistoryTypeId="3" PostId="8548" RevisionGUID="ed5a6a03-2f61-431a-b86e-cfce77e13dbd" CreationDate="2019-02-03T19:55:44.850" UserId="10117" Text="|metal|frame-buffer|capture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23029" PostHistoryTypeId="2" PostId="8549" RevisionGUID="ff28e133-da71-40b2-8ae6-1cea4bc814c7" CreationDate="2019-02-04T03:26:21.547" UserId="7512" Text="I found this picture &#xD;&#xA;&#xD;&#xA;![picture](https://mir-s3-cdn-cf.behance.net/project_modules/disp/9a556e13045459.5603449940365.jpg)&#xD;&#xA;&#xD;&#xA;When you zoom in to any part of the image, the background looks a bit noisy/grainy. See pixels around &quot;violent violet&quot; label:&#xD;&#xA;&#xD;&#xA;![grains](https://i.stack.imgur.com/1j518.png)&#xD;&#xA;&#xD;&#xA;I'm trying to understand how to achieve the same effect programmatically?&#xD;&#xA;&#xD;&#xA;I was trying to change pixel color in rgb space by adding tiny gaussian offset, but it still doesn't look nearly as natural as in the image above:&#xD;&#xA;&#xD;&#xA;![failed attempts](https://i.stack.imgur.com/Qpy4P.png)&#xD;&#xA;&#xD;&#xA;I feel like I'm missing something very simple, but I don't even know where to start? How is this done in general?&#xD;&#xA;&#xD;&#xA;Maybe you can play with this jsbin to show me how this is done: https://jsbin.com/fatecojolo/edit?js,output ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23030" PostHistoryTypeId="1" PostId="8549" RevisionGUID="ff28e133-da71-40b2-8ae6-1cea4bc814c7" CreationDate="2019-02-04T03:26:21.547" UserId="7512" Text="Adding noise to gradient" ContentLicense="CC BY-SA 4.0" />
  <row Id="23031" PostHistoryTypeId="3" PostId="8549" RevisionGUID="ff28e133-da71-40b2-8ae6-1cea4bc814c7" CreationDate="2019-02-04T03:26:21.547" UserId="7512" Text="|rendering|image-processing|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23032" PostHistoryTypeId="2" PostId="8550" RevisionGUID="e398ccbc-18be-4447-89a5-581656412653" CreationDate="2019-02-04T13:09:09.137" UserId="2041" Text="It's generally a good idea to add noise like this when you're using a gradient, to avoid visible banding in the gradient, especially on smartphones. Often smartphone screens claim to be 24-bit colour but the panel itself is actually only 16 or 20 bit.&#xD;&#xA;&#xD;&#xA;The chief difference between the example and your attempt to reproduce it is that your noise is in RGB space, while the example only adds luminance noise (i.e. brightness). You could achieve this by using HSV colours and only adding to the V channel, or with RGB colours and adding the same amount to each channel." ContentLicense="CC BY-SA 4.0" />
  <row Id="23033" PostHistoryTypeId="2" PostId="8551" RevisionGUID="2c08f392-1334-4b7f-9a04-8d1bdfde9110" CreationDate="2019-02-04T15:39:35.177" UserId="10120" Text="I have been working on a 3D engine and I am now implementing animations, but I can't find out whether or not to use the FPS of the engine or a fixed time method for the transformation's speed. Could someone please tell me the standard for animation timing. Thanks in advanced." ContentLicense="CC BY-SA 4.0" />
  <row Id="23034" PostHistoryTypeId="1" PostId="8551" RevisionGUID="2c08f392-1334-4b7f-9a04-8d1bdfde9110" CreationDate="2019-02-04T15:39:35.177" UserId="10120" Text="Should animations be locked to FPS or Fixed time" ContentLicense="CC BY-SA 4.0" />
  <row Id="23035" PostHistoryTypeId="3" PostId="8551" RevisionGUID="2c08f392-1334-4b7f-9a04-8d1bdfde9110" CreationDate="2019-02-04T15:39:35.177" UserId="10120" Text="|opengl|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23036" PostHistoryTypeId="6" PostId="8551" RevisionGUID="2ee2fa2f-c951-4fe6-9083-0ef3f348d317" CreationDate="2019-02-04T20:45:18.047" UserId="2654" Comment="edited tags" Text="|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23041" PostHistoryTypeId="2" PostId="8553" RevisionGUID="f1580524-0472-457a-89d5-e1e46a488240" CreationDate="2019-02-05T07:41:46.873" UserId="7008" Text="You should use a fixed time for this. Consider the following: Your computer is super fast, you have high end hardware. Now you animate via FPS and make your animation look great. Let's say you had 120 fps.&#xD;&#xA;&#xD;&#xA;Since you did great work, you want to show me. I have bad hardware, everything takes ages. I have to work with just 30 fps - sufficient to call it real-time, but not too nice. It will take four times to completely play your animation on my computer, because you made it follow the fps. Therefore it doesn't convince me at all.&#xD;&#xA;&#xD;&#xA;This is even more problematic, if you do this in a multiplayer scenario. You could already start a new action after the animation, whereas I have to wait for the animation to finish. Therefore, there is an inconsistency in game state as well as an unfair game, because you can do things much faster." ContentLicense="CC BY-SA 4.0" />
  <row Id="23042" PostHistoryTypeId="2" PostId="8554" RevisionGUID="927141e7-eaa4-4b03-8098-ecdae08ff1d8" CreationDate="2019-02-05T08:43:51.127" UserId="6046" Text="The mistake was in the multiplication order during the composition of the matrices.&#xD;&#xA;&#xD;&#xA;Since the OP was working with column vectors the correct order for transformations should have been $TRSA∗v$. The OP did the other way around, $ASRT*v$ thus the incorrect results." ContentLicense="CC BY-SA 4.0" />
  <row Id="23043" PostHistoryTypeId="5" PostId="8554" RevisionGUID="354680c1-3f09-4c49-a3dc-9a01626ee8a0" CreationDate="2019-02-05T08:51:40.790" UserId="6046" Comment="added 301 characters in body" Text="The mistake was in the multiplication order during the composition of the matrices.&#xD;&#xA;&#xD;&#xA;Since the OP was working with column vectors the correct order for transformations should have been $TRSA∗v$. The OP did the other way around, $ASRT*v$ thus the incorrect results.&#xD;&#xA;&#xD;&#xA;Also there need to be another $A^{\prime}$ matrix added which negates the  translation done by  $A$. The first $A$ matrix should have $-u, -v$ to translate $u,v$ to origin. The $A^{\prime}$ matrix should have $u, v$ to translate back.&#xD;&#xA;&#xD;&#xA;Hence the correct composition should be, $TA^{\prime}RSA*v$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23044" PostHistoryTypeId="5" PostId="8554" RevisionGUID="656e24dd-b7ff-43d4-acca-9b797058d050" CreationDate="2019-02-05T09:45:52.040" UserId="6046" Comment="added 99 characters in body" Text="The mistake was in the multiplication order during the composition of the matrices.&#xD;&#xA;&#xD;&#xA;Since the OP was working with column vectors the correct order for transformations should have been $TRSA∗v$. The OP did the other way around, $ASRT*v$ thus the incorrect results.&#xD;&#xA;&#xD;&#xA;Also there need to be another $A^{\prime}$ matrix added which negates the  translation done by  $A$. The first $A$ matrix should have $-u, -v$ to translate $u,v$ to origin. The $A^{\prime}$ matrix should have $u, v$ to translate back.&#xD;&#xA;&#xD;&#xA;Hence the correct composition should be, $TA^{\prime}RSA*v$ or $A^{\prime}TRSA*v$ depending on whether the translation is intended around $u,v$ or the origin." ContentLicense="CC BY-SA 4.0" />
  <row Id="23045" PostHistoryTypeId="2" PostId="8555" RevisionGUID="3d336c26-9b67-4fc8-8873-76a9478fd60a" CreationDate="2019-02-05T15:02:19.313" UserId="10125" Text="## Introduction ##&#xD;&#xA;&#xD;&#xA;I am implementing anisotropic GGX BRDF and have encountered strange behaviour of my implementation. I thought that if I compare the microfacet distribution function I have with the one of an isotropic GGX, then they should be equal when the anisotropy parameter is 0. I haven't been able to do that, though.&#xD;&#xA;&#xD;&#xA;Here is the GGX formula I have used:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the anisotropic GGX formula I have used:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;If anisotropy is 0, then ![\alpha_x](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Calpha_x) is equal to ![\alpha_y](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Calpha_y), therefore I can get the following from the second formula:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;## Problem 1 ##&#xD;&#xA;&#xD;&#xA;The problem now is that the third formula can never match the first one because of the negative 1 in the first one.&#xD;&#xA;&#xD;&#xA;## Problem 2 ##&#xD;&#xA;&#xD;&#xA;The specific issue I have when rendering using my anisotropic GGX is that the normals seem to be ignored in the result.&#xD;&#xA;&#xD;&#xA;Here is a visualization of the distribution function of isotropic GGX on a flat material patch with normal mapping:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;And here is the anisotropic one:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;## Notation ##&#xD;&#xA;&#xD;&#xA;To complete the explanation of my solution, I use ![H](https://chart.googleapis.com/chart?cht=tx&amp;chl=H) for the half-vector, ![N](https://chart.googleapis.com/chart?cht=tx&amp;chl=N) for the normal, ![\alpha](https://chart.googleapis.com/chart?cht=tx&amp;chl=\alpha) for roughness, ![X](https://chart.googleapis.com/chart?cht=tx&amp;chl=X) for the tangent and ![Y](https://chart.googleapis.com/chart?cht=tx&amp;chl=Y) for the bi-tangent (in my case these are simply aligned with the x and y axes respectively). ![\alpha_x](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Calpha_x) and ![\alpha_y](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Calpha_y) represent roughness in the corresponding directions.&#xD;&#xA;&#xD;&#xA;## Questions ##&#xD;&#xA;&#xD;&#xA; 1. Is there a mistake in my reasoning? Is my anisotropic GGX correct?&#xD;&#xA; 2. What is the relationship between the two? Is there a simple explanation for the extension from GGX to anisotropic GGX?&#xD;&#xA; 3. Do you have any general tips for verifying the correctness of one's BRDF implementation?&#xD;&#xA;&#xD;&#xA;## References ##&#xD;&#xA;&#xD;&#xA;Here are my main references:&#xD;&#xA;&#xD;&#xA; - [Anisotropic GGX implementation][6]&#xD;&#xA; - [BRDF formulas][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3MkPf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/evdjG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/TeG4e.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Z5oHJ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/uxw6j.png&#xD;&#xA;  [6]: https://github.com/Kink3d/AnisotropicStandardShader/blob/master/AnisotropicStandardShader/CGIncludes/UnityAnisotropicBRDF.cginc&#xD;&#xA;  [7]: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="23046" PostHistoryTypeId="1" PostId="8555" RevisionGUID="3d336c26-9b67-4fc8-8873-76a9478fd60a" CreationDate="2019-02-05T15:02:19.313" UserId="10125" Text="Anisotropic GGX BRDF implementation. How is it related to isotropic GGX BRDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23047" PostHistoryTypeId="3" PostId="8555" RevisionGUID="3d336c26-9b67-4fc8-8873-76a9478fd60a" CreationDate="2019-02-05T15:02:19.313" UserId="10125" Text="|rendering|brdf|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23049" PostHistoryTypeId="2" PostId="8556" RevisionGUID="a58d69ea-5d2d-4911-9911-aef9069897e1" CreationDate="2019-02-05T20:51:52.390" UserId="10129" Text="I'm trying to implement Skybox in DirectX 11 (DirectXTK) but when I'm rendering skybox, then texture is rendered to my sphere model instead of showing skybox outside.&#xD;&#xA;&#xD;&#xA;**Rendering code:**&#xD;&#xA;&#xD;&#xA;	m_Camera-&gt;Render();&#xD;&#xA;&#xD;&#xA;	m_Camera-&gt;GetViewMatrix(viewMatrix);&#xD;&#xA;	m_D3D-&gt;GetWorldMatrix(worldMatrix);&#xD;&#xA;	m_D3D-&gt;GetProjectionMatrix(projectionMatrix);&#xD;&#xA;&#xD;&#xA;	m_D3D-&gt;ChangeRasterizerCulling(D3D11_CULL_NONE);&#xD;&#xA;	m_D3D-&gt;ChangeDepthStencilComparison(D3D11_COMPARISON_LESS_EQUAL);&#xD;&#xA;&#xD;&#xA;	m_Model-&gt;Render(m_D3D-&gt;GetDeviceContext());&#xD;&#xA;	m_skyboxShader-&gt;Render(m_D3D-&gt;GetDeviceContext(), m_Model-&gt;GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);&#xD;&#xA;&#xD;&#xA;	m_D3D-&gt;ChangeRasterizerCulling(D3D11_CULL_BACK);&#xD;&#xA;	m_D3D-&gt;ChangeDepthStencilComparison(D3D11_COMPARISON_LESS);&#xD;&#xA;	m_D3D-&gt;EndScene();&#xD;&#xA;&#xD;&#xA;**Skybox.vs**&#xD;&#xA;&#xD;&#xA;    cbuffer MatrixBuffer&#xD;&#xA;    {&#xD;&#xA;    	matrix worldMatrix;&#xD;&#xA;    	matrix viewMatrix;&#xD;&#xA;    	matrix projectionMatrix;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VertexInputType&#xD;&#xA;    {&#xD;&#xA;        float4 position : POSITION;    &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct PixelInputType&#xD;&#xA;    {&#xD;&#xA;        float4 positionSV : SV_POSITION;&#xD;&#xA;        float4 position : POSITION;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    PixelInputType ColorVertexShader(VertexInputType input)&#xD;&#xA;    {&#xD;&#xA;        PixelInputType output;&#xD;&#xA;    &#xD;&#xA;    	input.position.w = 1.0f;&#xD;&#xA;    	output.position = input.position;&#xD;&#xA;    &#xD;&#xA;        output.positionSV = mul(input.position, worldMatrix).xyww;&#xD;&#xA;        output.positionSV = mul(output.positionSV, viewMatrix).xyww;&#xD;&#xA;        output.positionSV = mul(output.positionSV, projectionMatrix).xyww;&#xD;&#xA;    &#xD;&#xA;        return output;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Skybox.ps**&#xD;&#xA;&#xD;&#xA;    TextureCube shaderTexture;&#xD;&#xA;    SamplerState SampleType;&#xD;&#xA;    &#xD;&#xA;    struct PixelInputType&#xD;&#xA;    {&#xD;&#xA;        float4 positionSV : SV_POSITION;&#xD;&#xA;    	float4 position : POSITION;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    float4 ColorPixelShader(PixelInputType input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;    	return shaderTexture.Sample(SampleType, input.position.xyz);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Result**&#xD;&#xA;[![DirectX Skybox error][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wX7Hn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23050" PostHistoryTypeId="1" PostId="8556" RevisionGUID="a58d69ea-5d2d-4911-9911-aef9069897e1" CreationDate="2019-02-05T20:51:52.390" UserId="10129" Text="Skybox is rendered on the model instead of surroundings" ContentLicense="CC BY-SA 4.0" />
  <row Id="23051" PostHistoryTypeId="3" PostId="8556" RevisionGUID="a58d69ea-5d2d-4911-9911-aef9069897e1" CreationDate="2019-02-05T20:51:52.390" UserId="10129" Text="|directx|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23054" PostHistoryTypeId="2" PostId="8557" RevisionGUID="cfdda388-c3ee-4979-b627-a5d8cad29f3a" CreationDate="2019-02-06T19:27:55.200" UserId="10086" Text="A skybox is a (large) cube that encompasses the entire scene and contains 6 images of a surrounding environment, giving the player the illusion that the environment he's in is actually much larger than it actually is. &#xD;&#xA;&#xD;&#xA;In order to do this, you need to draw a Cube (or a Sphere) in your Scene that will represent the Skybox. You then need to sample the Skybox Texture (shaderTexture in your shader) to project it into the geometry.&#xD;&#xA;This is exactly what you are doing with your Sphere Model in your Pixel Shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem you have, is that your Model is too small and your Camera is outside of the Skybox. You need to make the Skybox way bigger, and place your camera inside of it.&#xD;&#xA;The best solution is to center the Sky Sphere about the camera in world space, this way when you move the camera around, the Sky follows the camera, giving the illusion that it's infinitely far away and you can't get closer.&#xD;&#xA;&#xD;&#xA;    PixelInputType ColorVertexShader(VertexInputType input)&#xD;&#xA;    {&#xD;&#xA;    PixelInputType output;&#xD;&#xA;    &#xD;&#xA;    // Use local vertex position as cubemap lookup vector.&#xD;&#xA;    output.position = input.position;&#xD;&#xA;    &#xD;&#xA;    // Transform to world space.&#xD;&#xA;    float4 positionWorld = mul(float4(input.position, 1.0f), worldMatrix);&#xD;&#xA;    &#xD;&#xA;    // Always center sky about camera (You need to pass the camera position).&#xD;&#xA;    positionWorld.xyz += eyePositionWorld;&#xD;&#xA;    &#xD;&#xA;    // Set z = w so that z/w = 1 (i.e., skydome always on far plane).&#xD;&#xA;    output.positionSV = mul(posW, viewProjectionMatrix).xyww;&#xD;&#xA;    &#xD;&#xA;    return output;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;To keep the Skybox fragments always on the far plane (z component = 1.0) you can set the z component to w. This will turn into 1 after the perspective division is applied.&#xD;&#xA;With this little hack you can render the SkySphere after having rendered all your meshes, and they would all be rendered on top of it.&#xD;&#xA;&#xD;&#xA;You may also want to do the matrix multiplication on the CPU and pass it in as another parameter for performance reasons." ContentLicense="CC BY-SA 4.0" />
  <row Id="23058" PostHistoryTypeId="2" PostId="8559" RevisionGUID="5c19e936-ecde-465f-88d4-ba49fcecba3a" CreationDate="2019-02-06T21:06:19.027" UserId="10136" Text="On the picture below you can see mathematically perfect smooth transition from black to white. But I noticed that on all gradient picture I see strange strips and the color transition doesn't feel smooth. I even see that if you pass from black to white, there are some small jumps back to a bit darker color, when theoretically the color should become always whiter and whiter.&#xD;&#xA;&#xD;&#xA;Can somebody explaing me this phenomena?&#xD;&#xA;[![Gradient from black to white][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Jcf3t.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23059" PostHistoryTypeId="1" PostId="8559" RevisionGUID="5c19e936-ecde-465f-88d4-ba49fcecba3a" CreationDate="2019-02-06T21:06:19.027" UserId="10136" Text="Strange stripes on the gradient" ContentLicense="CC BY-SA 4.0" />
  <row Id="23060" PostHistoryTypeId="3" PostId="8559" RevisionGUID="5c19e936-ecde-465f-88d4-ba49fcecba3a" CreationDate="2019-02-06T21:06:19.027" UserId="10136" Text="|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23061" PostHistoryTypeId="2" PostId="8560" RevisionGUID="be0a9ccc-959b-464a-9ff5-11df584d753f" CreationDate="2019-02-07T02:44:40.150" UserId="10096" Text="The 'jump' to 'a bit darker' are an optical illusion due to how human perception works. Check out Mach bands in wikipedia. Now as for why you get a step function even though you have a smooth transition in code: this is due to quanization. Your monitor can reproduce a finite amount of grey levels, so you quantize your otherwise continuous range." ContentLicense="CC BY-SA 4.0" />
  <row Id="23062" PostHistoryTypeId="5" PostId="8546" RevisionGUID="6db5b323-0e28-4d5b-941a-9545f2134bbc" CreationDate="2019-02-07T04:16:37.750" UserId="3003" Comment="Added simplified code with explanation." Text="I read this in a magazine article probably 25 years ago. I don't recall the full derivation, but they said to take each component (red, green, and blue) and invert the high bit of the color. In a C-like programming language, you could do:&#xD;&#xA;&#xD;&#xA;     component = (~component &amp; 0x80) | (component &amp; 0x7F);&#xD;&#xA;&#xD;&#xA;This can be simplified to:&#xD;&#xA;&#xD;&#xA;    component ^= 0x80;&#xD;&#xA;&#xD;&#xA;for  a single component or to:&#xD;&#xA;&#xD;&#xA;    component ^= 0x80808000;&#xD;&#xA;&#xD;&#xA;if you want to do 4 components at once (and don't affect the alpha).&#xD;&#xA;&#xD;&#xA;This assumes your components are 8-bit values. This avoids the problems you get with the middle values if you simply invert them. In that case 127 becomes 128, and vice-versa. But with the above solution, 127 becomes 255 and 128 becomes 0." ContentLicense="CC BY-SA 4.0" />
  <row Id="23063" PostHistoryTypeId="2" PostId="8561" RevisionGUID="4c47fb6e-9fa5-4473-a2d7-8e4a129c4ec4" CreationDate="2019-02-07T09:02:40.953" UserId="9194" Text="The image's histogram isn't entirely flat which could imply that some grey levels are represented more than others, I'm not sure this would cause the effects you see - I expect not. Try printing the image as a hight quality photo on glossy paper, this should eliminate the shortcomings of your screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="23064" PostHistoryTypeId="2" PostId="8562" RevisionGUID="adc14057-36db-4b1b-b393-58c09dfa6e3d" CreationDate="2019-02-07T11:05:59.613" UserId="5496" Text="This is not homework. I'm self studying Computer Graphics, using the book &quot;3D Math Primer for Graphics and Game Development&quot; (2nd edition). So there is the exercise 6 in chapter 3 which I can't figure out how to solve exactly. It goes like this:&#xD;&#xA;&#xD;&#xA;&quot;Assume that the robot is at the position (1, 10, 3), and her right, up, and forward vectors expressed in upright space are [0.866, 0, −0.500], [0, 1, 0], and [0.500, 0, 0.866], respectively. (Note that these vectors form an orthonormal basis.) The following points are expressed in object space. Calculate the coordinates for these points in upright and world space.&#xD;&#xA;(a) (−1, 2, 0) (b) (1, 2, 0)&#xD;&#xA;...&quot;&#xD;&#xA;&#xD;&#xA;Now I know that in order to convert from Object space to world space I have to first convert into inertial/upright space by performing a rotation and then into world space by performing a translation. So I assume that that the point (1,10,3) is expressed in world space coordinates. What I don't understand is which one is the matrix I have to use to do the rotation on point (-1,2,0)? I understand conceptually what is going on but I don't know which operations to do here. Help is greatly needed and will be appreciated. Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="23065" PostHistoryTypeId="1" PostId="8562" RevisionGUID="adc14057-36db-4b1b-b393-58c09dfa6e3d" CreationDate="2019-02-07T11:05:59.613" UserId="5496" Text="How to convert from Object space into World space (exercise from 3D Math Primer book)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23066" PostHistoryTypeId="3" PostId="8562" RevisionGUID="adc14057-36db-4b1b-b393-58c09dfa6e3d" CreationDate="2019-02-07T11:05:59.613" UserId="5496" Text="|transformations|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23067" PostHistoryTypeId="2" PostId="8563" RevisionGUID="35d5185d-5d97-4a32-91f6-28b5f063d336" CreationDate="2019-02-07T11:56:12.463" UserId="9739" Text="Suppose we have a world coordinate system `W` and a 3D model `m1` defined in `W`. `m1` has its own local coordinate system `L`.&#xA;&#xA; 1. How would we define `L`? Only by the transform from `W` to the object?&#xA;&#xA;If we add a 3D model `m2` to `W` : How do we define its position and orientation in `L` without worrying about the world coordinate system. Like just saying for instance that it's in (0,0,0) in `L`? &#xA;&#xA;PS : If it's possible using algebraic or 3D geometry matrices transformation equations ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="23068" PostHistoryTypeId="1" PostId="8563" RevisionGUID="35d5185d-5d97-4a32-91f6-28b5f063d336" CreationDate="2019-02-07T11:56:12.463" UserId="9739" Text="Define position and orientation in a local coordinate system" ContentLicense="CC BY-SA 4.0" />
  <row Id="23069" PostHistoryTypeId="3" PostId="8563" RevisionGUID="35d5185d-5d97-4a32-91f6-28b5f063d336" CreationDate="2019-02-07T11:56:12.463" UserId="9739" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23070" PostHistoryTypeId="2" PostId="8564" RevisionGUID="e6161ae6-6ab6-4f2c-826e-755bf5b71ff6" CreationDate="2019-02-07T13:15:14.813" UserId="10096" Text="Assuming that your 'models' can be represented by collections of points, then these points' coordinates are defined with respect to some coordinate system. You said that $m_1$ is defined wrt the coordinate system $W$. And you have some other coordinate system $L$ and want to find the positions of the points of $m_1$ in it. To do this you need to multiply each of your points with the matrix used to go from $W$ to $L$. To build this matrix you need to know the coordinates of the basis vectors of $W$ wrt $L$. Then you can make a 3x3 matrix where each column is a basis vector with which you can go from $W$ to $L$. Note that a translation will also be necessary if the origins do not agree.&#xD;&#xA;The solution for $m_2$ is similar." ContentLicense="CC BY-SA 4.0" />
  <row Id="23071" PostHistoryTypeId="5" PostId="8560" RevisionGUID="b734a731-b8ac-450a-8db0-0d646c391f53" CreationDate="2019-02-07T13:17:32.860" UserId="10096" Comment="Typos" Text="The 'jumps' to 'a bit darker' are an optical illusion due to how human perception works. Check out Mach bands in wikipedia. Now as for why you get a step function even though you have a smooth transition in code: this is due to quantization. Your monitor can reproduce a finite amount of grey levels, so you quantize your otherwise continuous range." ContentLicense="CC BY-SA 4.0" />
  <row Id="23072" PostHistoryTypeId="2" PostId="8565" RevisionGUID="d4b5761f-4bd2-4078-983b-df60a55b07e0" CreationDate="2019-02-07T16:42:15.693" UserId="10142" Text="The non smooth appearance, or visual stripes you see, is called **color banding**. ([Wikipedia](https://en.wikipedia.org/wiki/Colour_banding)) It is produced since the medium, in this case your screen, is only capable of producing a finite array of colors and as the mathematical equation progressively passes through the color change you monitor &quot;jumps&quot; a visual amount of &quot;steps&quot;. Higher resolution monitors will suffer from banding less but still still have noticeable steps in high contrast gradients, such as from black to white.&#xD;&#xA;&#xD;&#xA;The &quot;jumps&quot; back to a darker color is, as **lightxbulb** mentioned, an optical illusion called Mach bands. ([Wikipedia](https://en.wikipedia.org/wiki/Mach_bands))&#xD;&#xA;&#xD;&#xA;Printing a gradient will often have the same issue, no matter how high the resolution is. I have often had clients provide artwork for high quality printing and have been very disappointed with banding effect.&#xD;&#xA;&#xD;&#xA;Banding is not only present in gradients but most noticeable in high contract change gradients and low resolution mediums.&#xD;&#xA;&#xD;&#xA;There are techniques to help with banding like dithering or adding noise. But these techniques will often require moving to pixel based artwork and not mathematical perfect vector.  Here is a great article to understand banding and how to avoid it using Photoshop. https://www.slrlounge.com/remove-banding-photoshop/" ContentLicense="CC BY-SA 4.0" />
  <row Id="23073" PostHistoryTypeId="2" PostId="8566" RevisionGUID="1e69e2af-b1c0-4dbf-94cb-7ea737c06f46" CreationDate="2019-02-07T21:12:32.830" UserId="110" Text="You should be able to use [RWTexture3D](https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/sm5-object-rwtexture3d).   &#xA;The [hlsl documentation page about RWTexture2D](https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/sm5-object-rwtexture3d) also has sample code that you might find useful. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23074" PostHistoryTypeId="50" PostId="8462" RevisionGUID="cae048dc-7bb6-4bee-bfe4-c85b1bb69292" CreationDate="2019-02-08T09:01:15.200" UserId="-1" />
  <row Id="23075" PostHistoryTypeId="5" PostId="8566" RevisionGUID="dc533f63-e617-484e-bccf-f02c4aa45a40" CreationDate="2019-02-08T10:09:10.523" UserId="110" Comment="edited body" Text="You should be able to use [RWTexture3D](https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/sm5-object-rwtexture3d).   &#xA;The [hlsl documentation page about RWTexture2D](https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/sm5-object-rwtexture2d) also has sample code that you might find useful. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23076" PostHistoryTypeId="4" PostId="8529" RevisionGUID="2a70e87f-1aa7-4420-bf6e-ab97f64f9983" CreationDate="2019-02-08T16:44:41.903" UserId="209" Comment="minor correction to title" Text="Is there an analogue of OpenGL's ImageLoadStore in DirectX 12?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23077" PostHistoryTypeId="2" PostId="8567" RevisionGUID="2e373ae5-9daf-438c-8f3d-aca3ed74991f" CreationDate="2019-02-08T21:31:23.550" UserId="120" Text="Let me try to translate the problem statement in a mathematical way so that it can be understood more easily.&#xD;&#xA;&#xD;&#xA;&gt; Assume that the robot is at the position (1, 10, 3)&#xD;&#xA;&#xD;&#xA;Assume there are a set of basis $\mathbf{e}_i$ and origin $\mathbf{O}$, then the robot position $\mathbf{P}$ expressed in this basis is the origin plus a linear combination of the basis and the coefficients $\mathbf{p}=(1,10,3)$:&#xD;&#xA;$$\mathbf{P}=p_i \mathbf{e}_i + \mathbf{O}$$&#xD;&#xA;&#xD;&#xA;&gt; and her right, up, and forward vectors expressed in upright space are [0.866, 0, −0.500], [0, 1, 0], and [0.500, 0, 0.866], respectively.&#xD;&#xA;&#xD;&#xA;Now we have another set of basis denoted as $\mathbf{e}'_i$ attached at $\mathbf{P}$, and the relation between these two basis $\mathbf{e}$ and $\mathbf{e}'$ are also expressed as linear combinations. That is, denote $\mathbf{m}_0=(0.866,0,-0.5)$,$\mathbf{m}_1=(0,1,0)$, and $\mathbf{m}_2=(0.5,0,0.866)$, then&#xD;&#xA;$$&#xD;&#xA;\mathbf{e}'_i=m_{ij} \mathbf{e}_j&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&gt; Calculate the coordinates for these points in upright and world space. (a) (−1, 2, 0) (b) (1, 2, 0) ...&#xD;&#xA;&#xD;&#xA;The given coordinates are in object space and the problem asks us to compute their representations in frames $\{\mathbf{e}_i,\mathbf{O}\}$ and $\{\mathbf{e}'_i,\mathbf{P}\}$ respectively.&#xD;&#xA;&#xD;&#xA;Take $\mathbf{x}=(-1,2,0)$ as an example, we want to find the coordinates $\mathbf{l}$ in object space:&#xD;&#xA;$$ x_i \mathbf{e}'_i + \mathbf{P} = l_i \mathbf{e}'_i + \mathbf{P}$$&#xD;&#xA;$l_i = x_i$ in this case.&#xD;&#xA;&#xD;&#xA;Next we find the coordinates $\mathbf{w}$ in world space:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;x_i \mathbf{e}'_i + \mathbf{P} &amp;= w_i \mathbf{e}_i + \mathbf{O} \\&#xD;&#xA;x_i \mathbf{e}'_i + p_i\mathbf{e}_i &amp;= w_i \mathbf{e}_i \\&#xD;&#xA;x_j m_{ji} \mathbf{e}_i + p_i\mathbf{e}_i &amp;= w_i \mathbf{e}_i \\&#xD;&#xA;x_j m_{ji} + p_i &amp;= w_i&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Written in vector form:&#xD;&#xA;$$&#xD;&#xA;\mathbf{M}^T \mathbf{x} + \mathbf{p} = \mathbf{w}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your idea is generally correct. And the &quot;upright&quot; matrix can be constructed by considering the relation ($m_{ij}$) between the two basis, as shown above.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23078" PostHistoryTypeId="5" PostId="8567" RevisionGUID="8e1db6df-4da0-4717-9cea-8cec644cd174" CreationDate="2019-02-08T21:57:34.983" UserId="120" Comment="My understanding of upright space was incorrect. Fixed." Text="Let me try to translate the problem statement in a mathematical way so that it can be understood more easily.&#xD;&#xA;&#xD;&#xA;&gt; Assume that the robot is at the position (1, 10, 3)&#xD;&#xA;&#xD;&#xA;Assume there are a set of basis $\mathbf{e}_i$ and origin $\mathbf{O}$, then the robot position $\mathbf{P}$ expressed in this basis is the origin plus a linear combination of the basis and the coefficients $\mathbf{p}=(1,10,3)$:&#xD;&#xA;$$\mathbf{P}=p_i \mathbf{e}_i + \mathbf{O}$$&#xD;&#xA;&#xD;&#xA;&gt; and her right, up, and forward vectors expressed in upright space are [0.866, 0, −0.500], [0, 1, 0], and [0.500, 0, 0.866], respectively.&#xD;&#xA;&#xD;&#xA;Now we have another set of basis denoted as $\mathbf{e}'_i$ attached at $\mathbf{P}$, and the relation between these two basis $\mathbf{e}$ and $\mathbf{e}'$ are also expressed as linear combinations. That is, denote $\mathbf{m}_0=(0.866,0,-0.5)$,$\mathbf{m}_1=(0,1,0)$, and $\mathbf{m}_2=(0.5,0,0.866)$, then&#xD;&#xA;$$&#xD;&#xA;\mathbf{e}'_i=m_{ij} \mathbf{e}_j&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&gt; Calculate the coordinates for these points in upright and world space. (a) (−1, 2, 0) (b) (1, 2, 0) ...&#xD;&#xA;&#xD;&#xA;The given coordinates are in object space and the problem asks us to compute their representations in frames $\{\mathbf{e}_i,\mathbf{P}\}$ and $\{\mathbf{e}_i,\mathbf{O}\}$ respectively.&#xD;&#xA;&#xD;&#xA;Take $\mathbf{x}=(-1,2,0)$ as an example, we want to find the coordinates $\mathbf{l}$ in upright space:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;x_i \mathbf{e}'_i + \mathbf{P} &amp;= l_i \mathbf{e}_i + \mathbf{P}\\&#xD;&#xA;x_j m_{ji} \mathbf{e}_i &amp;= l_i \mathbf{e}_i&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Written in matrix form: $\mathbf{M}^T \mathbf{x}=\mathbf{l}$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Next we find the coordinates $\mathbf{w}$ in world space:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;x_i \mathbf{e}'_i + \mathbf{P} &amp;= w_i \mathbf{e}_i + \mathbf{O} \\&#xD;&#xA;x_i \mathbf{e}'_i + p_i\mathbf{e}_i &amp;= w_i \mathbf{e}_i \\&#xD;&#xA;x_j m_{ji} \mathbf{e}_i + p_i\mathbf{e}_i &amp;= w_i \mathbf{e}_i \\&#xD;&#xA;x_j m_{ji} + p_i &amp;= w_i&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Written in vector form:&#xD;&#xA;$$&#xD;&#xA;\mathbf{M}^T \mathbf{x} + \mathbf{p} = \mathbf{w}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your idea is generally correct. And the &quot;upright&quot; matrix can be constructed by considering the relation ($m_{ij}$) between the two basis, as shown above.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23086" PostHistoryTypeId="2" PostId="8568" RevisionGUID="80d27dec-1f18-4900-9f09-ac0ea42e0c2d" CreationDate="2019-02-09T07:18:12.563" UserId="10149" Text="I recently noticed that in all games, no matter what system you play on or what specs you have, your character will always move at the same speed even if there is  no frame rate limit. I was wondering how this worked because if you were to add the same value to a variable, the animation would be faster on faster processors or graphics cards. I heard somewhere that you could use the time between frames to reduce the speed. I do not see how this would work. So how would you get a consistent speed across all systems?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23087" PostHistoryTypeId="1" PostId="8568" RevisionGUID="80d27dec-1f18-4900-9f09-ac0ea42e0c2d" CreationDate="2019-02-09T07:18:12.563" UserId="10149" Text="Consistent animation speed across systems" ContentLicense="CC BY-SA 4.0" />
  <row Id="23088" PostHistoryTypeId="3" PostId="8568" RevisionGUID="80d27dec-1f18-4900-9f09-ac0ea42e0c2d" CreationDate="2019-02-09T07:18:12.563" UserId="10149" Text="|real-time|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23089" PostHistoryTypeId="2" PostId="8569" RevisionGUID="b68e5272-9b16-469a-b61d-3276f9929a7e" CreationDate="2019-02-09T10:41:08.787" UserId="2041" Text="It works exactly the way you describe. Most 3D games work on *keyframe* animations, where the human animator sets the important positions (for each joint or whatever is being animated) and the times they should be shown. The times are usually a number of &quot;frames&quot;, but these are just intervals of 1/60 s, regardless of what frame rate is actually achieved on the client machine. The computer *interpolates* between those keyframe positions to decide what to draw at any given time.&#xD;&#xA;&#xD;&#xA;For example, let's say an animation has keyframes on frame 0, 6, and 12. These are the positions to show at the beginning of the animation, 6/60 s later (that's 0.1 s), and 6/60 s after that. The first frame is drawn with the pose from the first keyframe.&#xD;&#xA;&#xD;&#xA;Let's say the game is running really slowly, and the next frame starts being assembled 0.05 s later (which would give a 20 fps frame rate). The animation system uses interpolation to make a pose that's halfway between the first and second keyframes, because the time is halfway between 0 and 0.1. Next, imagine things are speeding up a bit, and the next frame is drawn 0.04 s later. It's 0.09 s since the start of the animation, so the animation system makes a pose that's 90% from the first keyframe to the second keyframe.&#xD;&#xA;&#xD;&#xA;If this frame rate continues, the next frame will be generated at 0.13 s. This time the animation system has to interpolate between the second and third keyframes, taking 70% of the second and 30% of the third. Note that the second keyframe was never drawn in this example, but it contributed to the poses that were drawn, through interpolation.&#xD;&#xA;&#xD;&#xA;Now to finish off the example quickly, let's assume the computer really slows down so the next frame is another 0.07 s later, making 0.2 s since the start of the animation. This is exactly the time that the third keyframe was set for, so the animation system just uses that pose. Although the animation was designed to take 13 frames (including the one at the start), we've finished it in just 5 frames of jerkiness, but it still takes the same length of time, 0.2 s.&#xD;&#xA;&#xD;&#xA;In summary, it doesn't matter what time each frame actually comes out on the end system, because we can make whatever pose we like via *interpolation*." ContentLicense="CC BY-SA 4.0" />
  <row Id="23090" PostHistoryTypeId="50" PostId="6115" RevisionGUID="ae0f085d-967a-4d78-b8bc-90798748ad4d" CreationDate="2019-02-09T13:01:40.373" UserId="-1" />
  <row Id="23097" PostHistoryTypeId="2" PostId="8572" RevisionGUID="ea36e4eb-60e4-4034-83d4-db93a97edfcc" CreationDate="2019-02-10T00:02:04.857" UserId="10051" Text="What is the oldest hardware or minimum requirements conceptually able to support a fully hardware-accelerated Vulkan implementation? I am not referring to what implementations are currently available or likely to be written, but what could possibly be written.&#xD;&#xA;&#xD;&#xA;Is there a specific set of features that must be provided by hardware in order for the manipulation primitives provided by Vulkan to be used?&#xD;&#xA;&#xD;&#xA;Can Vulkan drivers be written for every video card that supports OpenGL?&#xD;&#xA;&#xD;&#xA;For example, could one create a hardware Vulkan driver for the [Number Nine Imagine 128][1], with 4M VRAM?&#xD;&#xA;&#xD;&#xA;I apologize for how naive my question must be, and thanks in advance for any reply.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Number_Nine_Visual_Technology#Number_Nine_Video_Cards_using_Number_Nine_GPUs" ContentLicense="CC BY-SA 4.0" />
  <row Id="23098" PostHistoryTypeId="1" PostId="8572" RevisionGUID="ea36e4eb-60e4-4034-83d4-db93a97edfcc" CreationDate="2019-02-10T00:02:04.857" UserId="10051" Text="What is the oldest hardware able to feasibly support Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23099" PostHistoryTypeId="3" PostId="8572" RevisionGUID="ea36e4eb-60e4-4034-83d4-db93a97edfcc" CreationDate="2019-02-10T00:02:04.857" UserId="10051" Text="|vulkan|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23100" PostHistoryTypeId="2" PostId="8573" RevisionGUID="1449fde5-67e2-4474-8071-34cb375b0715" CreationDate="2019-02-10T08:28:19.003" UserId="7644" Text="Khronos publishes a list of [Vulkan compliant hardware here][1]. The list also shows compliance to different flavors of OpenGL. I don't know all the card models, but for NVIDIA at least the GeForce GT 630 is supposed to work with Vulkan.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/conformance/adopters/conformant-products/vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="23101" PostHistoryTypeId="2" PostId="8574" RevisionGUID="8f8fd4f5-6b9d-486c-8130-504099f51264" CreationDate="2019-02-10T17:08:58.830" UserId="6910" Text="For example, preparing a scene in Maya using standard lights and rendering out a panorama? &#xA;Could they also be made from scratch in photoshop using 32bit color? &#xA;Is there a reason why people don’t seem to do this more often?&#xA;Cheers" ContentLicense="CC BY-SA 4.0" />
  <row Id="23102" PostHistoryTypeId="1" PostId="8574" RevisionGUID="8f8fd4f5-6b9d-486c-8130-504099f51264" CreationDate="2019-02-10T17:08:58.830" UserId="6910" Text="Can you generate your own HDRI maps without using photos?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23103" PostHistoryTypeId="3" PostId="8574" RevisionGUID="8f8fd4f5-6b9d-486c-8130-504099f51264" CreationDate="2019-02-10T17:08:58.830" UserId="6910" Text="|rendering|3d|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23104" PostHistoryTypeId="2" PostId="8575" RevisionGUID="63593bf3-90db-4f3d-9fd8-616a499db58f" CreationDate="2019-02-10T21:29:48.247" UserId="10160" Text="I try to solve this,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bWhcz.png&#xD;&#xA;&#xD;&#xA;First, I used scaling: $Scale(S_x,S_y)=S(\sqrt 5,\sqrt 5)$&#xD;&#xA;&#xD;&#xA;So, I enlarge the bottom of the house and the sides, to the same size of B image.&#xD;&#xA;&#xD;&#xA;Later, I used rotation: $R(\theta)=R(cos^{-1}(2/\sqrt 5))$&#xD;&#xA;the vertex that was $[\sqrt 5, 0, 1]$ moved $[2, 1, 1]$&#xD;&#xA;&#xD;&#xA;But I stuck with that.&#xD;&#xA;&#xD;&#xA;What is the idea of this question?&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="23105" PostHistoryTypeId="1" PostId="8575" RevisionGUID="63593bf3-90db-4f3d-9fd8-616a499db58f" CreationDate="2019-02-10T21:29:48.247" UserId="10160" Text="Using transformations to get from A to B image" ContentLicense="CC BY-SA 4.0" />
  <row Id="23106" PostHistoryTypeId="3" PostId="8575" RevisionGUID="63593bf3-90db-4f3d-9fd8-616a499db58f" CreationDate="2019-02-10T21:29:48.247" UserId="10160" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23107" PostHistoryTypeId="5" PostId="8575" RevisionGUID="1e37040c-6c91-4b4b-9af4-c4d97fcedbe0" CreationDate="2019-02-10T21:35:28.280" UserId="10160" Comment="added 57 characters in body" Text="I try to solve this,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bWhcz.png&#xD;&#xA;&#xD;&#xA;First, I used scaling: $Scale(S_x,S_y)=S(\sqrt 5,\sqrt 5)$&#xD;&#xA;&#xD;&#xA;So, I enlarge the bottom of the house and the sides, to the same size of B image.&#xD;&#xA;&#xD;&#xA;Later, I used rotation: $R(\theta)=R(cos^{-1}(2/\sqrt 5))$&#xD;&#xA;the vertex that was $[\sqrt 5, 0, 1]$ moved $[2, 1, 1]$ I do that because I thought to translate it to $[5,3,1]$&#xD;&#xA;&#xD;&#xA;But I stuck with that.&#xD;&#xA;&#xD;&#xA;What is the idea of this question?&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="23109" PostHistoryTypeId="5" PostId="8573" RevisionGUID="56ffeb23-1db0-4a1a-8e17-4887c57f76c9" CreationDate="2019-02-10T22:26:39.533" UserId="7644" Comment="added 839 characters in body" Text="Khronos publishes a list of [Vulkan compliant hardware here][1]. The list also shows compliance to different flavors of OpenGL. I don't know all the card models, but for NVIDIA at least the GeForce GT 630 is supposed to work with Vulkan.&#xD;&#xA;&#xD;&#xA;To answer your question a bit more, to support Vulkan a video card must support a certain number of programmable shader stages. Shaders is probably the biggest evolution of graphic cards in the last 10 years in my opinion. This already eliminates the graphic card you mentioned in the question.&#xD;&#xA;&#xD;&#xA;This [early Vulkan presentation from Khronos][2], states that &quot;Vulkan 1.0 provides access to OpenGL ES 3.1 / OpenGL 4.X-class GPU functionalitybut with increased performance and flexibility.&quot; That can give you a basis for finding which individual features a graphic cards must theoretically support to have a Vulkan driver. See the new features [introduced in OpenGL 4 at Wikipedia][3].&#xD;&#xA;&#xD;&#xA;Among them:&#xD;&#xA;&#xD;&#xA;- Transform feedback&#xD;&#xA;- Texture buffer objects&#xD;&#xA;- Tessellation shaders&#xD;&#xA;- Indirect draw commands&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/conformance/adopters/conformant-products/vulkan&#xD;&#xA;  [2]: https://www.khronos.org/assets/uploads/developers/library/overview/vulkan-overview.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/OpenGL#OpenGL_4.0" ContentLicense="CC BY-SA 4.0" />
  <row Id="23110" PostHistoryTypeId="5" PostId="8573" RevisionGUID="2819f2cf-26f1-4b97-9e80-ab7fe8434862" CreationDate="2019-02-10T23:34:44.727" UserId="7644" Comment="added 233 characters in body" Text="Khronos publishes a list of [Vulkan compliant hardware here][1]. The list also shows compliance to different flavors of OpenGL. I don't know all the card models, but for NVIDIA at least the GeForce GT 630 is supposed to work with Vulkan.&#xD;&#xA;&#xD;&#xA;To answer your question a bit more, to support Vulkan a video card must support a certain number of programmable shader stages. Shaders is probably the biggest evolution of graphic cards in the last 10 years in my opinion. This already eliminates the graphic card you mentioned in the question.&#xD;&#xA;&#xD;&#xA;This [early Vulkan presentation from Khronos][2], states that &quot;Vulkan 1.0 provides access to OpenGL ES 3.1 / OpenGL 4.X-class GPU functionalitybut with increased performance and flexibility.&quot; That can give you a basis for finding which individual features a graphic cards must theoretically support to have a Vulkan driver. See the new features [introduced in OpenGL 4 at Wikipedia][3].&#xD;&#xA;&#xD;&#xA;Among them:&#xD;&#xA;&#xD;&#xA;- Tessellation shaders&#xD;&#xA;- Indirect draw commands&#xD;&#xA;- &lt;strike&gt;Transform feedback&lt;/strike&gt; (more flexibility in transform feedback)&#xD;&#xA;- &lt;strike&gt;Texture buffer objects&lt;/strike&gt; (new texture formats only)&#xD;&#xA;&#xD;&#xA;See also the sections &quot;New Features&quot; of the [OpenGL 4.x specs][4].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/conformance/adopters/conformant-products/vulkan&#xD;&#xA;  [2]: https://www.khronos.org/assets/uploads/developers/library/overview/vulkan-overview.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/OpenGL#OpenGL_4.0&#xD;&#xA;  [4]: https://www.khronos.org/registry/OpenGL/index_gl.php" ContentLicense="CC BY-SA 4.0" />
  <row Id="23116" PostHistoryTypeId="2" PostId="8577" RevisionGUID="8c22c2ce-869f-4643-b501-6c8190816206" CreationDate="2019-02-11T05:57:02.433" UserId="3003" Text="Yes, it is possible to do this. If you use a tool like Photoshop in 32-bit per channel mode, any values less than 0 or greater than 1 should be usable as a high dynamic range values. I don't know that I agree with your contention that &quot;people don't seem to do this&quot;. Given that the tools exist, they must be supporting some workflow." ContentLicense="CC BY-SA 4.0" />
  <row Id="23117" PostHistoryTypeId="2" PostId="8578" RevisionGUID="659ee781-b7d3-4161-b262-24936996ae14" CreationDate="2019-02-11T08:11:58.460" UserId="5180" Text="I'm trying to add BRDFs to a very basic path tracer. Starting out, I'd like to convert just the Lambertian material, with two different sampling methods, to ensure that everything is working right. Theoretically, a uniform sample and a cosine-weighted hemispherical sample should both render similar images with different amounts of noise.&#xD;&#xA;&#xD;&#xA;However, I'm finding that the uniform sample yields a significantly darker image than the cosine-weighted sample. This makes sense as the uniform set will always be scaled by 1 whereas the weighted set will usually be scaled by more than one - but I don't know exactly how I should fix that. Maybe someone can enlighten me as to how these PDFs should work?&#xD;&#xA;&#xD;&#xA;Here is the relevant material code:&#xD;&#xA;&#xD;&#xA;    func (l *Lambert) Scatter(_, n geom.Unit, uv, p geom.Vec, rnd *rand.Rand) (in geom.Unit, bsdf Color, pdf float64) {&#xD;&#xA;    	in, pdf = sampleUniform(n, rnd) // should be able to swap this out, right?&#xD;&#xA;    	bsdf = l.texture.Map(uv, p).Scaled(in.Dot(n))&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func sampleUniform(n geom.Unit, rnd *rand.Rand) (sample geom.Unit, pdf float64) {&#xD;&#xA;    	sample = n.RandInHemisphere(rnd)&#xD;&#xA;    	pdf = 1&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func sampleCosWeighted(n geom.Unit, rnd *rand.Rand) (sample geom.Unit, pdf float64) {&#xD;&#xA;    	sample = n.RandInHemisphereCos(rnd)&#xD;&#xA;    	pdf = n.Dot(sample)&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the relevant render loop code:&#xD;&#xA;&#xD;&#xA;    func color(r Ray, s Surface, depth int, rnd *rand.Rand) Color {&#xD;&#xA;    	if depth &gt;= 50 {&#xD;&#xA;    		return black&#xD;&#xA;    	}&#xD;&#xA;    	hit := s.Hit(r, bias, math.MaxFloat64, rnd)&#xD;&#xA;    	if hit == nil {&#xD;&#xA;    		return black&#xD;&#xA;    	}&#xD;&#xA;    	out := r.Dir.Inv()&#xD;&#xA;    	emit := hit.Mat.Emit(hit.UV, hit.Pt)&#xD;&#xA;    	in, bsdf, pdf := hit.Mat.Scatter(out, hit.Norm, hit.UV, hit.Pt, rnd)&#xD;&#xA;    	if pdf &lt;= 0 {&#xD;&#xA;    		return emit&#xD;&#xA;    	}&#xD;&#xA;    	indirect := color(NewRay(hit.Pt, in, r.T), s, depth+1, rnd).Times(bsdf).Scaled(1 / pdf)&#xD;&#xA;    	return emit.Plus(indirect)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23118" PostHistoryTypeId="1" PostId="8578" RevisionGUID="659ee781-b7d3-4161-b262-24936996ae14" CreationDate="2019-02-11T08:11:58.460" UserId="5180" Text="PDFs of cosine-weighted vs uniform-sampled hemispheres" ContentLicense="CC BY-SA 4.0" />
  <row Id="23119" PostHistoryTypeId="3" PostId="8578" RevisionGUID="659ee781-b7d3-4161-b262-24936996ae14" CreationDate="2019-02-11T08:11:58.460" UserId="5180" Text="|raytracing|pathtracing|brdf|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23120" PostHistoryTypeId="4" PostId="8578" RevisionGUID="77513af9-7520-4609-8014-a300f5f34b5d" CreationDate="2019-02-11T08:40:52.410" UserId="5180" Comment="make into a question" Text="How to set equivalent PDFs for cosine-weighted and uniform-sampled hemispheres?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23124" PostHistoryTypeId="2" PostId="8579" RevisionGUID="1abeb3e6-91cd-4929-941f-26648488b6a5" CreationDate="2019-02-11T10:26:07.327" UserId="10096" Text="You're simply not normalizing correctly, since you've picked the pdf for uniform to be $1$ which it is not, and for cosine to be $\cos\theta$ which it is not. The pdf for uniformly distributed points on the upper hemisphere is: $p_U(\theta, \phi) = \frac{\sin\theta}{2\pi}$. The pdf for cosine distributed points on the upper hemisphere is: $p_C(\theta, \phi) = \frac{\cos\theta\sin\theta}{\pi}$. The integrand of the rendering equation (formulated in terms of sampling the hemisphere and not the area formulation) is: $$brdf(\theta_i, \phi_i, x, \theta_o, \phi_o)L_i(x,\theta_i,\phi_i)\cos\theta_i\sin\theta_i$$&#xD;&#xA;Since the estimator is the integrand divided by the pdf, then in the case of uniform sampling the sine cancels and you get:&#xD;&#xA;$$2\pi \cdot brdf(\theta_i, \phi_i, x, \theta_o, \phi_o)L_i(x,\theta_i,\phi_i)\cos\theta_i$$&#xD;&#xA;In the case of cosine sampling the sine and cosine cancel and you get:&#xD;&#xA;$$\pi \cdot brdf(\theta_i, \phi_i, x, \theta_o, \phi_o)L_i(x,\theta_i,\phi_i)$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23125" PostHistoryTypeId="5" PostId="8579" RevisionGUID="b462e7aa-36e1-4eee-b852-3825b9c93d56" CreationDate="2019-02-11T10:33:03.303" UserId="10096" Comment="added 104 characters in body" Text="You're simply not normalizing correctly, since you've picked the pdf for uniform to be $1$ which it is not, and for cosine to be $\cos\theta$ which it is not. The pdf for uniformly distributed points on the upper hemisphere is: $p_U(\theta, \phi) = \frac{\sin\theta}{2\pi}$. The pdf for cosine distributed points on the upper hemisphere is: $p_C(\theta, \phi) = \frac{\cos\theta\sin\theta}{\pi}$. The integrand of the rendering equation (formulated in terms of sampling the hemisphere and not the area formulation) is: $$brdf(\theta_i, \phi_i, x, \theta_o, \phi_o)L_i(x,\theta_i,\phi_i)\cos\theta_i\sin\theta_i$$&#xD;&#xA;Since the estimator is the integrand divided by the pdf, then in the case of uniform sampling the sine cancels and you get:&#xD;&#xA;$$2\pi \cdot brdf(\theta_i, \phi_i, x, \theta_o, \phi_o)L_i(x,\theta_i,\phi_i)\cos\theta_i$$&#xD;&#xA;In the case of cosine sampling the sine and cosine cancel and you get:&#xD;&#xA;$$\pi \cdot brdf(\theta_i, \phi_i, x, \theta_o, \phi_o)L_i(x,\theta_i,\phi_i)$$&#xD;&#xA;&#xD;&#xA;Note that for a Lambertian material you should use cosine sampling since it produces lower variance." ContentLicense="CC BY-SA 4.0" />
  <row Id="23126" PostHistoryTypeId="5" PostId="8578" RevisionGUID="f53b4496-c315-4ade-85b2-cee165c632aa" CreationDate="2019-02-11T15:17:07.097" UserId="5180" Comment="update with latest feedback" Text="I'm trying to add BRDFs to a very basic path tracer. Starting out, I'd like to convert just the Lambertian material, with two different sampling methods, to ensure that everything is working right. Theoretically, a uniform sample and a cosine-weighted hemispherical sample should both render similar images with different amounts of noise.&#xD;&#xA;&#xD;&#xA;However, I'm finding that the uniform sample yields a significantly darker image than the cosine-weighted sample. This makes sense as the uniform set will always be scaled by 1 whereas the weighted set will usually be scaled by more than one - but I don't know exactly how I should fix that. Maybe someone can enlighten me as to how these PDFs should work?&#xD;&#xA;&#xD;&#xA;Here is the relevant material code (edited based on the most recent):&#xD;&#xA;&#xD;&#xA;    func (l *Lambert) Scatter(_, n geom.Unit, uv, p geom.Vec, rnd *rand.Rand) (in geom.Unit, bsdf Color, pdf float64) {&#xD;&#xA;    	in, pdf = sampleUniform(n, rnd) // should be able to swap this out, right?&#xD;&#xA;    	bsdf = l.texture.Map(uv, p).Scaled(in.Dot(n))&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func sampleUniform(n geom.Unit, rnd *rand.Rand) (sample geom.Unit, pdf float64) {&#xD;&#xA;    	sample = n.RandInHemisphere(rnd)&#xD;&#xA;    	pdf = 0.5&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func sampleCosWeighted(n geom.Unit, rnd *rand.Rand) (sample geom.Unit, pdf float64) {&#xD;&#xA;    	sample = n.RandInHemisphereCos(rnd)&#xD;&#xA;    	pdf = n.Dot(sample)&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    func sampleReflected(out, n geom.Unit, rnd *rand.Rand) (sample geom.Unit, pdf float64) {&#xD;&#xA;    	sample = reflect(out, n)&#xD;&#xA;    	pdf = 1&#xD;&#xA;    	return&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the relevant render loop code:&#xD;&#xA;&#xD;&#xA;    func color(r Ray, s Surface, depth int, rnd *rand.Rand) Color {&#xD;&#xA;    	if depth &gt;= 50 {&#xD;&#xA;    		return black&#xD;&#xA;    	}&#xD;&#xA;    	hit := s.Hit(r, bias, math.MaxFloat64, rnd)&#xD;&#xA;    	if hit == nil {&#xD;&#xA;    		return black&#xD;&#xA;    	}&#xD;&#xA;    	out := r.Dir.Inv()&#xD;&#xA;    	emit := hit.Mat.Emit(hit.UV, hit.Pt)&#xD;&#xA;    	in, bsdf, pdf := hit.Mat.Scatter(out, hit.Norm, hit.UV, hit.Pt, rnd)&#xD;&#xA;    	if pdf &lt;= 0 {&#xD;&#xA;    		return emit&#xD;&#xA;    	}&#xD;&#xA;    	indirect := color(NewRay(hit.Pt, in, r.T), s, depth+1, rnd).Times(bsdf).Scaled(1 / pdf)&#xD;&#xA;    	return emit.Plus(indirect)&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23127" PostHistoryTypeId="2" PostId="8580" RevisionGUID="d329b7ab-a0f6-4e70-b8f5-e6d9f550d57c" CreationDate="2019-02-11T18:26:34.420" UserId="6046" Text="So, for Uniform sampling the PDF is $1/2π$, For Cos-weighted its $cos(θ)/π$. The Lambertian BRDF has a $\pi$ term as well in the denominator for energy conservation.&#xD;&#xA;&#xD;&#xA;When not optimizing things you should be dividing by $\pi$ during the BRDF calculation, then dividing by the proper PDFs mentioned above.&#xD;&#xA;&#xD;&#xA;Considering all the factors into account, for uniform sampling you'd have&#xD;&#xA;&#xD;&#xA;$L_i*brdf*\cos(\theta) * \displaystyle{\frac{1}{pdf}}$&#xD;&#xA;&#xD;&#xA;$L_i * \frac{color}{\pi} * \cos(\theta) \displaystyle{\frac{1}{\frac{1}{2\pi}}}$&#xD;&#xA;&#xD;&#xA;$L_i * {color} * \cos(\theta) * 2$&#xD;&#xA;&#xD;&#xA;Similarly for Cosine-weighted hemispherical sampling you'd have&#xD;&#xA;&#xD;&#xA;$L_i*brdf*\cos(\theta) * \displaystyle{\frac{1}{pdf}}$&#xD;&#xA;&#xD;&#xA;$L_i * \frac{color}{\pi} * \cos(\theta) \displaystyle{\frac{1}{\frac{\cos(\theta)}{pi}}}$&#xD;&#xA;&#xD;&#xA;$L_i * {color} $&#xD;&#xA;&#xD;&#xA;Since you weren't dividing by $\pi$ in the BRDF, the division by the PDF should have been $1/2$ and $\cos(\theta)$ as you suggested but couldn't understand since the actual pdfs have a factor of $\pi$ in them." ContentLicense="CC BY-SA 4.0" />
  <row Id="23128" PostHistoryTypeId="2" PostId="8581" RevisionGUID="3daf42bd-047a-43c0-96ab-30c4fd830ac5" CreationDate="2019-02-12T08:59:03.130" UserId="209" Text="Just use linear algebra.&#xD;&#xA; &#xD;&#xA;Since parallel lines have remained parallel (i.e. meaning we can leave the *w* component of homogeneous coordinates as 1), we can just pick 3 starting points and their destinations, e.g.&#xD;&#xA;&#xD;&#xA;    (0,0,1)-&gt;(3,2,1),  (0,1,1)-&gt;(1,3,1), and  (1,0,1)-&gt;(5,3,1),&#xD;&#xA;&#xD;&#xA; then define M to be your (homogeneous) transformation matrix as &#xD;&#xA;&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b &amp; c \\&#xD;&#xA;    d &amp; e &amp; f \\&#xD;&#xA;    0 &amp; 0 &amp; 1\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;and we have &#xD;&#xA;$$ M.\begin{bmatrix}&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix} = &#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;    3 &amp; 1 &amp; 5 \\&#xD;&#xA;    2 &amp; 3 &amp; 3 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; $$&#xD;&#xA;You just need to find the inverse of the 'starting point' matrix (*which is left as an exercise for the reader* ) and rearrange to compute...&#xD;&#xA;$$ M= &#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;    3 &amp; 1 &amp; 5 \\&#xD;&#xA;    2 &amp; 3 &amp; 3 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;    .\begin{bmatrix}&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}^{-1}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23129" PostHistoryTypeId="5" PostId="8581" RevisionGUID="d0dba801-362b-46d2-9648-26e2719aabef" CreationDate="2019-02-12T09:04:50.720" UserId="209" Comment="added 123 characters in body" Text="Just use linear algebra.&#xD;&#xA; &#xD;&#xA;Since parallel lines have remained parallel (i.e. meaning we can probably assume the *w* component of homogeneous coordinates is always 1), we can just pick 3 starting points and their destinations, e.g.&#xD;&#xA;&#xD;&#xA;    (0,0,1)-&gt;(3,2,1),  (0,1,1)-&gt;(1,3,1), and  (1,0,1)-&gt;(5,3,1),&#xD;&#xA;&#xD;&#xA; define M to be your (homogeneous) transformation matrix as &#xD;&#xA;&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b &amp; c \\&#xD;&#xA;    d &amp; e &amp; f \\&#xD;&#xA;    0 &amp; 0 &amp; 1\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;and then we have &#xD;&#xA;$$ M.\begin{bmatrix}&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix} = &#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;    3 &amp; 1 &amp; 5 \\&#xD;&#xA;    2 &amp; 3 &amp; 3 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; $$&#xD;&#xA;&#xD;&#xA;You just need to find the inverse of the 'starting point' matrix (*which is left as an exercise for the reader* ) and rearrange to compute...&#xD;&#xA;$$ M= &#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;    3 &amp; 1 &amp; 5 \\&#xD;&#xA;    2 &amp; 3 &amp; 3 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;    .\begin{bmatrix}&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}^{-1}$$&#xD;&#xA;&#xD;&#xA;To be really thorough, you could also then check that all the remaining points are transformed correctly by your result." ContentLicense="CC BY-SA 4.0" />
  <row Id="23130" PostHistoryTypeId="2" PostId="8582" RevisionGUID="763077dc-3968-4574-93cc-1b51e2f97294" CreationDate="2019-02-12T11:44:33.470" UserId="10096" Text="Since the only answer requires homogeneous coordinates, a $3\times3$ matrix inversion, as well as a $3\times3$ matrix multiplication, here's something simpler, not as tedious to compute, and also more geometrically intuitive (it also gives a better idea what a linear map can do, and what it cannot).&#xD;&#xA;&#xD;&#xA;A linear $2\times2$ transformation obviously cannot translate the origin, for this we will need a translation. We can find the translation from the difference between the lower left vertices of the house(you could use a different point for this too). We see that $(0,0)\rightarrow (3,2)$, then the translation is $(3,2)$. We can move the stretched and rotated house back to the origin: so that the lower left vertex coincides with $(0,0)$ (the initial position of it) by translating with $-(3,2)$. We'll pick two 'nice' points (in the sense that they have $0$ for one of their components and $1$ for the other): $(1,0)$ and $(0,1)$. We can see from the image that $(1,0) \rightarrow (5,3) - (3,2) = (2,1)$  where the subtraction is necessary to move the transformed house back to the origin as already mentioned. Similarly: $(0,1) \rightarrow (1,3) - (3,2) = (-2,1)$. We want to find a matrix:&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b\\&#xD;&#xA;    c &amp; d\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;such that $M(1,0)^T = (2,1)^T$ and $M(0,1)^T = (-2,1)^T$. But this is trivial, since we get $(a,c) = (2,1)$ and $(b,d) = (-2,1)$. Thus you have: $v'=Mv+(3,2)$, where $v$ is a point from the original house, and $v'$ is the transformed such." ContentLicense="CC BY-SA 4.0" />
  <row Id="23131" PostHistoryTypeId="5" PostId="8582" RevisionGUID="3a9aa7aa-9184-4164-886b-f6f7af62c55b" CreationDate="2019-02-12T12:27:11.817" UserId="10096" Comment="added 471 characters in body" Text="Since the only answer requires homogeneous coordinates, a $3\times3$ matrix inversion, as well as a $3\times3$ matrix multiplication, here's something simpler, not as tedious to compute, and also more geometrically intuitive (it also gives a better idea what a linear map can do, and what it cannot).&#xD;&#xA;&#xD;&#xA;A linear $2\times2$ transformation obviously cannot translate the origin, for this we will need a translation. We can find the translation from the difference between the lower left vertices of the house(you could use a different point for this too). We see that $(0,0)\rightarrow (3,2)$, then the translation is $(3,2)$. We can move the stretched and rotated house back to the origin: so that the lower left vertex coincides with $(0,0)$ (the initial position of it) by translating with $-(3,2)$. We'll pick two 'nice' points (in the sense that they have $0$ for one of their components and $1$ for the other): $(1,0)$ and $(0,1)$. We can see from the image that $(1,0) \rightarrow (5,3) - (3,2) = (2,1)$  where the subtraction is necessary to move the transformed house back to the origin as already mentioned. Similarly: $(0,1) \rightarrow (1,3) - (3,2) = (-2,1)$. We want to find a matrix:&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b\\&#xD;&#xA;    c &amp; d\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;such that $M(1,0)^T = (2,1)^T$ and $M(0,1)^T = (-2,1)^T$. But this is trivial, since we get $(a,c) = (2,1)$ and $(b,d) = (-2,1)$. Thus you have: $v'=Mv+(3,2)$, where $v$ is a point from the original house, and $v'$ is the transformed such. Note that it is easy to see that this is simply scaling + rotation (45 degrees) + scaling:&#xD;&#xA;$$ M =\begin{bmatrix} 2 &amp; -2\\1 &amp; 1\\ \end{bmatrix}   &#xD;&#xA;= \begin{bmatrix} 2 &amp; 0\\0 &amp; 1\\ \end{bmatrix} \begin{bmatrix} 1 &amp; -1\\1 &amp; 1\\ \end{bmatrix} \\=  \begin{bmatrix} 2 &amp; 0\\ 0 &amp; 1\\ \end{bmatrix}&#xD;&#xA;\begin{bmatrix} \frac{1}{\sqrt{2}} &amp; -\frac{1}{\sqrt{2}}\\ \frac{1}{\sqrt{2}} &amp; \frac{1}{\sqrt{2}}\\ \end{bmatrix}&#xD;&#xA;\begin{bmatrix} \sqrt{2} &amp; 0\\ 0 &amp; \sqrt{2}\\ \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;The right scaling may be moved inside the left one (since the right is uniform scaling, hence commutative, or just a multiplication by the scalar $\sqrt{2}$, I just thought it's geometrically more intuitive this way)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23135" PostHistoryTypeId="5" PostId="8582" RevisionGUID="fd02d379-7129-4065-9f87-91d3ce4f89db" CreationDate="2019-02-12T12:34:31.097" UserId="10096" Comment="added 24 characters in body" Text="Since the only answer requires homogeneous coordinates, a $3\times3$ matrix inversion, as well as a $3\times3$ matrix multiplication, here's something simpler, not as tedious to compute, and also more geometrically intuitive (it also gives a better idea what a linear map can do, and what it cannot).&#xD;&#xA;&#xD;&#xA;A linear $2\times2$ transformation obviously cannot translate the origin, for this we will need a translation. We can find the translation from the difference between the lower left vertices of the house (since one both should lie at the origin of their coordinate systems). We see that $(0,0)\rightarrow (3,2)$, then the translation is $(3,2)$. We can move the stretched and rotated house back to the origin: so that the lower left vertex coincides with $(0,0)$ (the initial position of it) by translating with $-(3,2)$. We'll pick two 'nice' points (in the sense that they have $0$ for one of their components and $1$ for the other): $(1,0)$ and $(0,1)$. We can see from the image that $(1,0) \rightarrow (5,3) - (3,2) = (2,1)$  where the subtraction is necessary to move the transformed house back to the origin as already mentioned. Similarly: $(0,1) \rightarrow (1,3) - (3,2) = (-2,1)$. We want to find a matrix:&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b\\&#xD;&#xA;    c &amp; d\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;such that $M(1,0)^T = (2,1)^T$ and $M(0,1)^T = (-2,1)^T$. But this is trivial, since we get $(a,c) = (2,1)$ and $(b,d) = (-2,1)$. Thus you have: $v'=Mv+(3,2)$, where $v$ is a point from the original house, and $v'$ is the transformed such. Note that it is easy to see that this is simply scaling + rotation (45 degrees) + scaling:&#xD;&#xA;$$ M =\begin{bmatrix} 2 &amp; -2\\1 &amp; 1\\ \end{bmatrix}   &#xD;&#xA;= \begin{bmatrix} 2 &amp; 0\\0 &amp; 1\\ \end{bmatrix} \begin{bmatrix} 1 &amp; -1\\1 &amp; 1\\ \end{bmatrix} \\=  \begin{bmatrix} 2 &amp; 0\\ 0 &amp; 1\\ \end{bmatrix}&#xD;&#xA;\begin{bmatrix} \frac{1}{\sqrt{2}} &amp; -\frac{1}{\sqrt{2}}\\ \frac{1}{\sqrt{2}} &amp; \frac{1}{\sqrt{2}}\\ \end{bmatrix}&#xD;&#xA;\begin{bmatrix} \sqrt{2} &amp; 0\\ 0 &amp; \sqrt{2}\\ \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;The right scaling may be moved inside the left one (since the right is uniform scaling, hence commutative, or just a multiplication by the scalar $\sqrt{2}$, I just thought it's geometrically more intuitive this way)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23136" PostHistoryTypeId="5" PostId="8582" RevisionGUID="2923b69e-7c62-475d-8971-c2b699709715" CreationDate="2019-02-12T12:43:30.687" UserId="10096" Comment="deleted 4 characters in body" Text="Since the only answer requires homogeneous coordinates, a $3\times3$ matrix inversion, as well as a $3\times3$ matrix multiplication, here's something simpler, not as tedious to compute, and also more geometrically intuitive (it also gives a better idea what a linear map can do, and what it cannot).&#xD;&#xA;&#xD;&#xA;A linear $2\times2$ transformation obviously cannot translate the origin, for this we will need a translation. We can find the translation from the difference between the lower left vertices of the house (since both should lie at the origin of their coordinate systems). We see that $(0,0)\rightarrow (3,2)$, then the translation is $(3,2)$. We can move the stretched and rotated house back to the origin: so that the lower left vertex coincides with $(0,0)$ (the initial position of it) by translating with $-(3,2)$. We'll pick two 'nice' points (in the sense that they have $0$ for one of their components and $1$ for the other): $(1,0)$ and $(0,1)$. We can see from the image that $(1,0) \rightarrow (5,3) - (3,2) = (2,1)$  where the subtraction is necessary to move the transformed house back to the origin as already mentioned. Similarly: $(0,1) \rightarrow (1,3) - (3,2) = (-2,1)$. We want to find a matrix:&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b\\&#xD;&#xA;    c &amp; d\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;such that $M(1,0)^T = (2,1)^T$ and $M(0,1)^T = (-2,1)^T$. But this is trivial, since we get $(a,c) = (2,1)$ and $(b,d) = (-2,1)$. Thus you have: $v'=Mv+(3,2)$, where $v$ is a point from the original house, and $v'$ is the transformed such. Note that it is easy to see that this is simply scaling + rotation (45 degrees) + scaling:&#xD;&#xA;$$ M =\begin{bmatrix} 2 &amp; -2\\1 &amp; 1\\ \end{bmatrix}   &#xD;&#xA;= \begin{bmatrix} 2 &amp; 0\\0 &amp; 1\\ \end{bmatrix} \begin{bmatrix} 1 &amp; -1\\1 &amp; 1\\ \end{bmatrix} \\=  \begin{bmatrix} 2 &amp; 0\\ 0 &amp; 1\\ \end{bmatrix}&#xD;&#xA;\begin{bmatrix} \frac{1}{\sqrt{2}} &amp; -\frac{1}{\sqrt{2}}\\ \frac{1}{\sqrt{2}} &amp; \frac{1}{\sqrt{2}}\\ \end{bmatrix}&#xD;&#xA;\begin{bmatrix} \sqrt{2} &amp; 0\\ 0 &amp; \sqrt{2}\\ \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;The right scaling may be moved inside the left one (since the right is uniform scaling, hence commutative, or just a multiplication by the scalar $\sqrt{2}$, I just thought it's geometrically more intuitive this way)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23137" PostHistoryTypeId="5" PostId="8581" RevisionGUID="a517c7d8-92fa-409d-a086-50a173454346" CreationDate="2019-02-12T15:08:34.640" UserId="209" Comment="Added result" Text="Just use linear algebra.&#xD;&#xA; &#xD;&#xA;Since parallel lines have remained parallel (i.e. meaning we can probably assume the *w* component of homogeneous coordinates is always 1), we can just pick 3 starting points and their destinations, e.g.&#xD;&#xA;&#xD;&#xA;    (0,0,1)-&gt;(3,2,1),  (0,1,1)-&gt;(1,3,1), and  (1,0,1)-&gt;(5,3,1),&#xD;&#xA;&#xD;&#xA; define M to be your (homogeneous) transformation matrix as &#xD;&#xA;&#xD;&#xA;$$ M =\begin{bmatrix}&#xD;&#xA;    a &amp; b &amp; c \\&#xD;&#xA;    d &amp; e &amp; f \\&#xD;&#xA;    0 &amp; 0 &amp; 1\\&#xD;&#xA;    \end{bmatrix}  $$&#xD;&#xA;and then we have &#xD;&#xA;$$ M.\begin{bmatrix}&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix} = &#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;    3 &amp; 1 &amp; 5 \\&#xD;&#xA;    2 &amp; 3 &amp; 3 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA; $$&#xD;&#xA;&#xD;&#xA;You just need to find the inverse of the 'starting point' matrix (*which is left as an exercise for the reader* ) and rearrange to compute...&#xD;&#xA;$$ M= &#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;    3 &amp; 1 &amp; 5 \\&#xD;&#xA;    2 &amp; 3 &amp; 3 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;    .\begin{bmatrix}&#xD;&#xA;    0 &amp; 0 &amp; 1 \\&#xD;&#xA;    0 &amp; 1 &amp; 0 \\&#xD;&#xA;    1 &amp; 1 &amp; 1\\&#xD;&#xA;    \end{bmatrix}^{-1}$$&#xD;&#xA;&#xD;&#xA;To be really thorough, you could also then check that all the remaining points are transformed correctly by your result.&#xD;&#xA;&#xD;&#xA;If you don't want to work through the maths yourself, the resulting matrix is&#xD;&#xA;&gt;! $ M= \begin{bmatrix} 2 &amp; -2 &amp; 3 \\ 1 &amp; 1 &amp; 2 \\ 0 &amp; 0 &amp; 1\\ \end{bmatrix}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23138" PostHistoryTypeId="2" PostId="8584" RevisionGUID="a0506b5e-1da0-46df-b253-2f091e01ac0f" CreationDate="2019-02-12T18:38:14.657" UserId="10168" Text="Given this graph in the 3d cartesian coordinates i should figure out the spherical coordinates representation but without the use of calculations .&#xD;&#xA;I've been trying to solve this the whole day but i don't seem to get it and i've searched on all around the internet also no results .&#xD;&#xA;I'll appreciate any help if anyone has an idea about the topic .&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/o57c0.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;NOTE: this is not a homework :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23139" PostHistoryTypeId="1" PostId="8584" RevisionGUID="a0506b5e-1da0-46df-b253-2f091e01ac0f" CreationDate="2019-02-12T18:38:14.657" UserId="10168" Text="transformation from cartesian coordinates to spherical coordinates without calculations" ContentLicense="CC BY-SA 4.0" />
  <row Id="23140" PostHistoryTypeId="3" PostId="8584" RevisionGUID="a0506b5e-1da0-46df-b253-2f091e01ac0f" CreationDate="2019-02-12T18:38:14.657" UserId="10168" Text="|3d|transformations|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23141" PostHistoryTypeId="5" PostId="5724" RevisionGUID="94c28ed8-8d82-471e-894d-805b5aa2c005" CreationDate="2019-02-12T19:19:11.300" UserId="10159" Comment="Some grammar change; I had the same question as OP." Text="I'm new to shaders and know that you can color pixels with gl_FragColor but sometimes there is this thing:&#xD;&#xA;&#xD;&#xA;    vec2 uv = gl_FragCoord.xy / screenSize; // or resolution or smthn depends on the implementation&#xD;&#xA;&#xD;&#xA;If gl_FragCoord is like pixel coordinates, what does **uv** get?&#xD;&#xA;&#xD;&#xA;Why is it often done in GLSL?&#xD;&#xA;&#xD;&#xA;If someone could even draw an example of which part of the screen will be UV it will be very helpful!" ContentLicense="CC BY-SA 4.0" />
  <row Id="23142" PostHistoryTypeId="24" PostId="5724" RevisionGUID="94c28ed8-8d82-471e-894d-805b5aa2c005" CreationDate="2019-02-12T19:19:11.300" Comment="Proposed by 10159 approved by 209, 6 edit id of 460" ContentLicense="CC BY-SA 4.0" />
  <row Id="23143" PostHistoryTypeId="2" PostId="8585" RevisionGUID="0e3a9623-c16a-4001-90cb-80f1a8a09491" CreationDate="2019-02-12T20:43:40.670" UserId="6046" Text="So I was just reading up on how to create more Physically Based Lights and wandered into the realm of photometry. I read the paper &quot;Moving FrostBite to PBR&quot; and in it the author claims he decided to have all the light sources in units of Photometry (Lumens/Luminance etc). &#xD;&#xA;&#xD;&#xA;The author also writes how to convert between radiometric and photometric units earlier on. But later he decides to ditch this conversion and have his lights in photometric from the get go. I don't understand how is this compatible?&#xD;&#xA;&#xD;&#xA;If I want to use the same technique for my normal path tracer, is there a different form of the rendering equation for photometry? Or should I just swap the radiometric parts for the photometric parts (radiance for luminance, radiant flux for lumens etc). How does this all tie up, if anybody can clear it.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23144" PostHistoryTypeId="1" PostId="8585" RevisionGUID="0e3a9623-c16a-4001-90cb-80f1a8a09491" CreationDate="2019-02-12T20:43:40.670" UserId="6046" Text="How to use Photometric Units with Rendering Equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23145" PostHistoryTypeId="3" PostId="8585" RevisionGUID="0e3a9623-c16a-4001-90cb-80f1a8a09491" CreationDate="2019-02-12T20:43:40.670" UserId="6046" Text="|rendering|lighting|photometric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23146" PostHistoryTypeId="5" PostId="8585" RevisionGUID="4f417d74-e129-48ef-ba4c-ab8de0f207a1" CreationDate="2019-02-12T21:01:31.467" UserId="6046" Comment="added 576 characters in body" Text="So I was just reading up on how to create more Physically Based Lights and wandered into the realm of photometry. I read the paper &quot;Moving FrostBite to PBR&quot; and in it the author claims he decided to have all the light sources in units of Photometry (Lumens/Luminance etc). &#xD;&#xA;&#xD;&#xA;The author also writes how to convert between radiometric and photometric units earlier on. But later he decides to ditch this conversion and have his lights in photometric from the get go. I don't understand how is this compatible?&#xD;&#xA;&#xD;&#xA;If I want to use the same technique for my normal path tracer, is there a different form of the rendering equation for photometry? Or should I just swap the radiometric parts for the photometric parts (radiance for luminance, radiant flux for lumens etc). How does this all tie up, if anybody can clear it.&#xD;&#xA;&#xD;&#xA;EDIT:- Just saw a [similar][1] question (sorry my net is slow). As nathan suggested in his answer rendering RGB images proceeds more naturally in radiometric units. If I opt the approach to convert between radiometric and photometric units using luminous efficacy for light sources will there still be a problem as Nathan suggested (wavelength dependance of photometric units) or that problem exists solely when rendering exclusively in Photometric units?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/1992/rendering-in-radiometric-units-or-photometric?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23152" PostHistoryTypeId="2" PostId="8587" RevisionGUID="3daf43b2-2728-4c9b-a69f-b7894a7736df" CreationDate="2019-02-13T13:08:13.883" UserId="9125" Text="I am looking for an algorithm that is able to cover with non-overlapping rectangles in a pre-defined number, a generic 2d-polygon.&#xD;&#xA;&#xD;&#xA;I found different articles like: https://en.wikipedia.org/wiki/Polygon_covering&#xD;&#xA;&#xD;&#xA;but I am not sure if it is what I am looking for. Can you point me to some source code or something readable for a non-graphic guy?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23153" PostHistoryTypeId="1" PostId="8587" RevisionGUID="3daf43b2-2728-4c9b-a69f-b7894a7736df" CreationDate="2019-02-13T13:08:13.883" UserId="9125" Text="An algorithms for covering a 2d polygon with a prefixed number of rectangles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23154" PostHistoryTypeId="3" PostId="8587" RevisionGUID="3daf43b2-2728-4c9b-a69f-b7894a7736df" CreationDate="2019-02-13T13:08:13.883" UserId="9125" Text="|algorithm|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23155" PostHistoryTypeId="5" PostId="8587" RevisionGUID="07ed55f5-e7dd-466b-aa72-fd7bd67d1999" CreationDate="2019-02-13T13:45:23.853" UserId="9125" Comment="added 16 characters in body" Text="I am looking for an algorithm that is able to cover with non-overlapping rectangles in a pre-defined number and minimum area a generic 2d-polygon.&#xD;&#xA;&#xD;&#xA;I found different articles like: https://en.wikipedia.org/wiki/Polygon_covering&#xD;&#xA;&#xD;&#xA;but I am not sure if it is what I am looking for. Can you point me to some source code or something readable for a non-graphic guy?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23156" PostHistoryTypeId="5" PostId="8587" RevisionGUID="8f3b38ef-9c75-4916-a038-8fa6170a41bc" CreationDate="2019-02-13T14:00:26.977" UserId="9125" Comment="added 117 characters in body" Text="I am looking for an algorithm that is able to cover with non-overlapping rectangles in a pre-defined number and minimum area a generic 2d-polygon.&#xD;&#xA;&#xD;&#xA;Polygons are usually free-hand draws, so they can be of really any shape and number of vertexes and having holes.&#xD;&#xA;&#xD;&#xA;I found different articles like: https://en.wikipedia.org/wiki/Polygon_covering&#xD;&#xA;&#xD;&#xA;but I am not sure if it is what I am looking for. Can you point me to some source code or something readable for a non-graphic guy?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23157" PostHistoryTypeId="2" PostId="8588" RevisionGUID="e9205c05-6c9c-4f6d-8f6d-b5545602914d" CreationDate="2019-02-13T14:52:39.603" UserId="8680" Text="If we take some ring around the sphere such that $\theta=const$, we can see that such a ring transforms into a line on the polar space.&#xD;&#xA;&#xD;&#xA;Converting every possible ring to the polar space gives the desired surface. However this would involve computing many different values to get an approximation or doing some algebra, which we don't want. (I'm assuming you want to keep mathematical notation to a minimum here). However we can get a pretty close idea by figuring out just a few easy to compute values.&#xD;&#xA;&#xD;&#xA;Now. If we grab the ring that goes around the center of the sphere and transform that one, it is clear that it ends up as a line with $\theta=45^o$ and $r=\sqrt{2}R$ (that is because its vertical distance from the origin equals its horizontal distance at every point).&#xD;&#xA;&#xD;&#xA;There are two more rings that are useful to us here: the two very small rings around the poles of the sphere.&#xD;&#xA;&#xD;&#xA;The ring around the bottom pole transforms into a line with $\theta=90^o$ and $r=0$.&#xD;&#xA;&#xD;&#xA;The ring around the bottom pole transforms into a line with $\theta=0^o$ and $r=2R$.&#xD;&#xA;&#xD;&#xA;We now have three lines through which we can fit our surface. You can do this with pen and paper. I'm not quite sure of what kind of curve you end up with (I haven't done the algebra haha) but my guess would be some kind of sideways parabola." ContentLicense="CC BY-SA 4.0" />
  <row Id="23158" PostHistoryTypeId="5" PostId="8588" RevisionGUID="52f2d4e2-cd63-40f6-85ac-0c5b4273cf06" CreationDate="2019-02-13T16:13:08.087" UserId="8680" Comment="deleted 3 characters in body" Text="If we take some ring around the sphere such that $\theta=const$, we can see that such a ring transforms into a line on the polar space.&#xD;&#xA;&#xD;&#xA;Converting every possible ring to the polar space gives the desired surface. However this would involve computing many different values to get an approximation or doing some algebra, which we don't want. (I'm assuming you want to keep mathematical notation to a minimum here). However we can get a pretty close idea by figuring out just a few easy to compute values.&#xD;&#xA;&#xD;&#xA;Now. If we grab the ring that goes around the center of the sphere and transform that one, it is clear that it ends up as a line with $\theta=45^o$ and $r=\sqrt{2}R$ (that is because its vertical distance from the origin equals its horizontal distance at every point).&#xD;&#xA;&#xD;&#xA;There are two more rings that are useful to us here: the two very small rings around the poles of the sphere.&#xD;&#xA;&#xD;&#xA;The ring around the bottom pole transforms into a line with $\theta=90^o$ and $r=0$.&#xD;&#xA;&#xD;&#xA;The ring around the top pole transforms into a line with $\theta=0^o$ and $r=2R$.&#xD;&#xA;&#xD;&#xA;We now have three lines through which we can fit our surface. You can do this with pen and paper. I'm not quite sure of what kind of curve you end up with (I haven't done the algebra haha) but my guess would be some kind of sideways parabola." ContentLicense="CC BY-SA 4.0" />
  <row Id="23159" PostHistoryTypeId="5" PostId="8588" RevisionGUID="e90c1e90-c3c7-43a9-a681-4f33c4a1c3d3" CreationDate="2019-02-13T16:33:55.130" UserId="8680" Comment="added 141 characters in body" Text="If we take some ring around the sphere such that $\theta=const$, we can see that such a ring transforms into a line on the polar space.&#xD;&#xA;&#xD;&#xA;Converting every possible ring to the polar space gives the desired surface. However this would involve computing many different values to get an approximation or doing some algebra, which we don't want. (I'm assuming you want to keep mathematical notation to a minimum here). However we can get a pretty close idea by figuring out just a few easy to compute values.&#xD;&#xA;&#xD;&#xA;Now. If we grab the ring that goes around the center of the sphere and transform that one, it is clear that it ends up as a line with $\theta=45^o$ and $r=\sqrt{2}R$ (that is because its vertical distance from the origin equals its horizontal distance at every point).&#xD;&#xA;&#xD;&#xA;There are two more rings that are useful to us here: the two very small rings around the poles of the sphere.&#xD;&#xA;&#xD;&#xA;The ring around the bottom pole transforms into a line with $\theta=90^o$ and $r=0$.&#xD;&#xA;&#xD;&#xA;The ring around the top pole transforms into a line with $\theta=0^o$ and $r=2R$.&#xD;&#xA;&#xD;&#xA;We now have three lines through which we can fit our surface. You can do this with pen and paper. I'm not quite sure of what kind of curve you end up with (I haven't done the algebra haha) but my guess would be some kind of sideways parabola.&#xD;&#xA;&#xD;&#xA;EDIT: I did the math, $r=2R\cos(\theta)$&#xD;&#xA;&#xD;&#xA;NOTE: I measure my $\theta$ as the angle between some line crossing the origin and the Z axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="23160" PostHistoryTypeId="2" PostId="8589" RevisionGUID="87d98aa3-77fd-4236-b3cb-6489a9b0c08c" CreationDate="2019-02-13T18:11:59.373" UserId="10174" Text="I have an obj file, with texture coordinates (indicated by vt). How would I use this to load textures in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23161" PostHistoryTypeId="1" PostId="8589" RevisionGUID="87d98aa3-77fd-4236-b3cb-6489a9b0c08c" CreationDate="2019-02-13T18:11:59.373" UserId="10174" Text="How do I use texture coordinates of a .obj file in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23162" PostHistoryTypeId="3" PostId="8589" RevisionGUID="87d98aa3-77fd-4236-b3cb-6489a9b0c08c" CreationDate="2019-02-13T18:11:59.373" UserId="10174" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23164" PostHistoryTypeId="2" PostId="8590" RevisionGUID="ffba2828-3337-455e-8477-7b22d9747234" CreationDate="2019-02-14T04:19:59.877" UserId="10178" Text="If you are using vertex arrays and shaders, your vertices (v) can be indexed and stored in an element array buffer and your texture coordinates should be pass to the vertex shader to be send and used by the fragment shader. I recommend you to visit the site https://learnopengl.com/." ContentLicense="CC BY-SA 4.0" />
  <row Id="23165" PostHistoryTypeId="5" PostId="8420" RevisionGUID="173d08bd-c9bd-447c-9607-4648839c55eb" CreationDate="2019-02-14T05:42:10.883" UserId="6046" Comment="Corrected the confusion regarding edge vectors growing outward. Also removed the assumption about lower left corner as it's un-necessary." Text="The best algorithm depends on the condition like whether or not the square is axis aligned for example. I'm gonna discuss the more general case which can find find intersection for any arbitrary oriented square. The algorithm works by first checking the intersection of ray with the plane containing the square or rectangle etc. Then check if the ray is within bounds of the square.&#xD;&#xA;&#xD;&#xA;For this you require the following information&#xD;&#xA;&#xD;&#xA;Ray's in the form $R =e+td $ where $e$ is the origin or eye point and $d$ is the direction vector.&#xD;&#xA;&#xD;&#xA;Secondly you need to define your square by using the following information  &#xD;&#xA;&#xD;&#xA; 1. **Poisition** - This might be the vector to the center or any corner of the square. The algorithm I'm describing assumes it is one of the corners.&#xD;&#xA; 2. **Normal** - Self explanatory.&#xD;&#xA; 3. **Width** and **Height** not as scalars but as vectors. These can be called the two edge vectors. I will denote them as $e1$ and $e2$. *Note that both edge vectors need to grow outward from the corner of the square chosen in point 1.*&#xD;&#xA;&#xD;&#xA;After you have the following information you first need to compute Ray - plane intersection. The plane being where your square lies. This is done as follows. We know the point normal form of a plane as,&#xD;&#xA;&#xD;&#xA;$(p-p1).n= 0$&#xD;&#xA;&#xD;&#xA;If we suppose $p$ is our ray here and $p1 = position$, then we will have,&#xD;&#xA;&#xD;&#xA;$(e+td - p1).n=0$  &#xD;&#xA;$(e+td - p1).n=0$  &#xD;&#xA;$e.n + td.n - p1.n = 0$  &#xD;&#xA;$t = p1.n - e.n/d.n$  &#xD;&#xA;$t = (p1-e).n/d.n$&#xD;&#xA;&#xD;&#xA;If $t \geq 0$ then we have an intersection. Now all we need to do is check whether the ray lies inside the square or anywhere else on the plane. This is easy to do.&#xD;&#xA;&#xD;&#xA;$intersect\_point = e + td$  &#xD;&#xA;$v = intersect\_point - p1$&#xD;&#xA;&#xD;&#xA;$proj1 = v.e1$  &#xD;&#xA;$proj2 = v.e2$  &#xD;&#xA;$width = ||e1||$  &#xD;&#xA;$height = ||e2||$&#xD;&#xA;&#xD;&#xA;$if((proj1 &lt; width \;\&amp;\&amp;\; proj1 &gt; 0) \;\&amp;\&amp;\; (proj2  &lt; height \;\&amp;\&amp;\; proj2 &gt; 0) )$  &#xD;&#xA;$return \, true$&#xD;&#xA;&#xD;&#xA;Note that the above assumes that the edge vectors grow outward from the corner, i.e. A square with the corners A,B,C,D in clockwise fashion starting from  the top left. If we choose corner $A$ then the edge vectors are $\vec{AB}$ and $\vec{AD}$. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23166" PostHistoryTypeId="5" PostId="8420" RevisionGUID="8a9a34a1-fcd3-41c9-a0a7-43925f452b88" CreationDate="2019-02-14T06:52:00.253" UserId="6046" Comment="added 19 characters in body" Text="The best algorithm depends on the condition like whether or not the square is axis aligned for example. I'm gonna discuss the more general case which can find find intersection for any arbitrary oriented square. The algorithm works by first checking the intersection of ray with the plane containing the square or rectangle etc. Then check if the ray is within bounds of the square.&#xD;&#xA;&#xD;&#xA;For this you require the following information&#xD;&#xA;&#xD;&#xA;Ray's in the form $R =e+td $ where $e$ is the origin or eye point and $d$ is the direction vector.&#xD;&#xA;&#xD;&#xA;Secondly you need to define your square by using the following information  &#xD;&#xA;&#xD;&#xA; 1. **Poisition** - This might be the vector to the center or any corner of the square. The algorithm I'm describing assumes it is one of the corners.&#xD;&#xA; 2. **Normal** - Self explanatory.&#xD;&#xA; 3. **Width** and **Height** not as scalars but as vectors. These can be called the two edge vectors. I will denote them as $e1$ and $e2$. *Note that both edge vectors need to grow outward from the corner of the square chosen in point 1.*&#xD;&#xA;&#xD;&#xA;After you have the following information you first need to compute Ray - plane intersection. The plane being where your square lies. This is done as follows. We know the point normal form of a plane as,&#xD;&#xA;&#xD;&#xA;$(p-p1).n= 0$&#xD;&#xA;&#xD;&#xA;If we suppose $p$ is our ray here and $p1 = position$, then we will have,&#xD;&#xA;&#xD;&#xA;$(e+td - p1).n=0$  &#xD;&#xA;$(e+td - p1).n=0$  &#xD;&#xA;$e.n + td.n - p1.n = 0$  &#xD;&#xA;$t = p1.n - e.n/d.n$  &#xD;&#xA;$t = (p1-e).n/d.n$&#xD;&#xA;&#xD;&#xA;If $t \geq 0$ then we have an intersection. Now all we need to do is check whether the ray lies inside the square or anywhere else on the plane. This is easy to do.&#xD;&#xA;&#xD;&#xA;$intersect\_point = e + td$  &#xD;&#xA;$v = intersect\_point - p1$&#xD;&#xA;&#xD;&#xA;$width = ||e1||$  &#xD;&#xA;$height = ||e2||$&#xD;&#xA;&#xD;&#xA;$proj1 = v.e1 /width $  &#xD;&#xA;$proj2 = v.e2 / height$  &#xD;&#xA;&#xD;&#xA;$if((proj1 &lt; width \;\&amp;\&amp;\; proj1 &gt; 0) \;\&amp;\&amp;\; (proj2  &lt; height \;\&amp;\&amp;\; proj2 &gt; 0) )$  &#xD;&#xA;$return \, true$&#xD;&#xA;&#xD;&#xA;Note that the above assumes that the edge vectors grow outward from the corner, i.e. A square with the corners A,B,C,D in clockwise fashion starting from  the top left. If we choose corner $A$ then the edge vectors are $\vec{AB}$ and $\vec{AD}$. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23167" PostHistoryTypeId="2" PostId="8591" RevisionGUID="89742a5a-4b02-43cd-8e90-0a2cf6c03e42" CreationDate="2019-02-14T11:45:04.200" UserId="10096" Text="I am still not sure whether this is what you actually want, but here's how to derive it mathematically. The equation of a sphere with center $(c_x, c_y, c_z)$ and radius $\rho$ is:&#xD;&#xA;$$(x-c_x)^2 + (y-c_y)^2 +(z-c_z)^2 =\rho^2$$&#xD;&#xA;From the first image we can figure out that the sphere has center $(0,0,\rho)$, we also use the spherical coordinates substitution:&#xD;&#xA;$$x=r\cos\phi\sin\theta, y=r\sin\phi\sin\theta, z =r\cos\theta$$&#xD;&#xA;Substituting yields:&#xD;&#xA;$$(r\cos\phi\sin\theta - 0)^2 + (r\sin\phi\sin\theta-0)^2 + (r\cos\theta-\rho)^2 = \rho^2$$&#xD;&#xA;$$r(r-2\rho\cos\theta) = 0$$&#xD;&#xA;The roots to the last equation are $$r=0, r=2\rho\cos\theta, \theta\in [0, \pi/2]$$, we can drop the $0$ since it is covered for $\theta = \pi/2$. Also $\theta$ being in $[0, \pi/2]$ restricts the sphere to being above the $xy$ plane, whereas using the full range: $[0,\pi]$ would produce also a sphere below. Thus you get the offset sphere in spherical coordinates:&#xD;&#xA;$$S=\{(r,\theta,\phi) : r=2\rho\cos\theta, \theta\in [0, \pi/2], \phi \in [0,2\pi]\}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23168" PostHistoryTypeId="5" PostId="8591" RevisionGUID="8255260b-1070-46e7-a0de-efb047abb629" CreationDate="2019-02-14T12:10:26.127" UserId="10096" Comment="added 118 characters in body" Text="I am still not sure whether this is what you actually want, but here's how to derive it mathematically. The equation of a sphere with center $(c_x, c_y, c_z)$ and radius $\rho$ is:&#xD;&#xA;$$(x-c_x)^2 + (y-c_y)^2 +(z-c_z)^2 =\rho^2$$&#xD;&#xA;From the first image we can figure out that the sphere has center $(0,0,\rho)$, we also use the spherical coordinates substitution:&#xD;&#xA;$$x=r\cos\phi\sin\theta, y=r\sin\phi\sin\theta, z =r\cos\theta$$&#xD;&#xA;Substituting yields:&#xD;&#xA;$$(r\cos\phi\sin\theta - 0)^2 + (r\sin\phi\sin\theta-0)^2 + (r\cos\theta-\rho)^2 = \rho^2$$&#xD;&#xA;$$r(r-2\rho\cos\theta) = 0$$&#xD;&#xA;The roots to the last equation are $$r=0, r=2\rho\cos\theta, \theta\in [0, \pi/2]$$, we can drop the $0$ since it is covered for $\theta = \pi/2$. Also $\theta$ being in $[0, \pi/2]$ restricts the sphere to being above the $xy$ plane, whereas using the full range: $[0,\pi]$ would produce also a sphere below. Thus you get the offset sphere in spherical coordinates:&#xD;&#xA;$$S=\{(r,\theta,\phi) : r=2\rho\cos\theta, \theta\in [0, \pi/2], \phi \in [0,2\pi]\}$$&#xD;&#xA;If you want the ball and not only its boundary, then use $r\in [0,2\rho\cos\theta]$ rather than $r=2\rho\cos\theta$." ContentLicense="CC BY-SA 4.0" />
  <row Id="23169" PostHistoryTypeId="2" PostId="8592" RevisionGUID="2551aca5-4dd2-47b3-a404-165e04f9b63d" CreationDate="2019-02-14T13:42:31.297" UserId="2041" Text="The OBJ file itself doesn't contain the texture, only the texture co-ordinates (which describe how to map a texture onto the surface of the mesh.) The texture is an image file (such as a PNG) whose path is given by the accompanying .mtl file. You need to parse the .mtl file to get the path to the image file, then use an image-loading library (such as DevIL) to load the image into memory. Once you have the pixels of the image, you can use `glTexImage2D` to load that image into a texture, which can be accessed from your fragment shader using a `sampler2D`." ContentLicense="CC BY-SA 4.0" />
  <row Id="23170" PostHistoryTypeId="2" PostId="8593" RevisionGUID="93c314de-9ec7-4be7-9a62-aa16b4efba39" CreationDate="2019-02-15T03:16:17.093" UserId="10184" Text="I'm writing a simple box blur for a graphics library.&#xD;&#xA;The formula makes the average of a range of pixels by adding the ARGB amounts and then dividing by the blur range&#xD;&#xA;&#xD;&#xA;For example, with a blur range of 3;&#xD;&#xA;&#xD;&#xA;    pixel1 FF FF 00 00 +&#xD;&#xA;    pixel2 FF 00 FF 00 +&#xD;&#xA;    pixel3 FF 00 00 FF&#xD;&#xA;    / 3 =&#xD;&#xA;    result FF 55 55 55&#xD;&#xA;&#xD;&#xA;Which is correct.&#xD;&#xA;A typical result shows as;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, I am having difficulty with coming up with a formula to blur an image with alpha transparency.&#xD;&#xA;The formula above gives this result for a yellow box on a transparent background;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;You can see that the yellow is surrounded by black colour - because the red and green are being diminished to 0. The result should actually look like so;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So; the formula of `(pixel + pixel + pixel) / range` is not working for alpha-blended images.&#xD;&#xA;Can anyone please give a correct formula?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Z3A8X.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OAlFT.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CTVCu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23171" PostHistoryTypeId="1" PostId="8593" RevisionGUID="93c314de-9ec7-4be7-9a62-aa16b4efba39" CreationDate="2019-02-15T03:16:17.093" UserId="10184" Text="blur with alpha transparency" ContentLicense="CC BY-SA 4.0" />
  <row Id="23172" PostHistoryTypeId="3" PostId="8593" RevisionGUID="93c314de-9ec7-4be7-9a62-aa16b4efba39" CreationDate="2019-02-15T03:16:17.093" UserId="10184" Text="|transparency|blur|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23173" PostHistoryTypeId="5" PostId="8593" RevisionGUID="4671670c-9de4-420b-b5fa-6f9696ab3ad2" CreationDate="2019-02-15T03:38:25.650" UserId="10184" Comment="added 492 characters in body" Text="I'm writing a simple box blur for a graphics library.&#xD;&#xA;The formula makes the average of a range of pixels by adding the ARGB amounts and then dividing by the blur range&#xD;&#xA;&#xD;&#xA;For example, with a blur range of 3;&#xD;&#xA;&#xD;&#xA;    pixel1 FF FF 00 00 +&#xD;&#xA;    pixel2 FF 00 FF 00 +&#xD;&#xA;    pixel3 FF 00 00 FF&#xD;&#xA;    / 3 =&#xD;&#xA;    result FF 55 55 55&#xD;&#xA;&#xD;&#xA;Which is correct.&#xD;&#xA;A typical result shows as;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, I am having difficulty with coming up with a formula to blur an image with alpha transparency.&#xD;&#xA;The formula above gives this result for a yellow box on a transparent background;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;You can see that the yellow is surrounded by black colour - because the red and green are being diminished to 0. The result should actually look like so;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So; the formula of `(pixel + pixel + pixel) / range` is not working for alpha-blended images.&#xD;&#xA;&#xD;&#xA;I tried to adjust the formula to premultiply the RGB by the alpha; but I'm no mathematician and I can't get it right.&#xD;&#xA;&#xD;&#xA;For example with the ARGB:&#xD;&#xA;&#xD;&#xA;    01 FF 00 00&#xD;&#xA;    01 FF 00 00&#xD;&#xA;    01 FF 00 00&#xD;&#xA;    &#xD;&#xA;    weighted RGB:&#xD;&#xA;    &#xD;&#xA;    pixel1 01 00 00 +&#xD;&#xA;    pixel2 01 00 00 +&#xD;&#xA;    pixel3 01 00 00&#xD;&#xA;    / 3 =&#xD;&#xA;    result 01 00 00&#xD;&#xA;    &#xD;&#xA;    incorrect.&#xD;&#xA;    the red is now almost completely gone.&#xD;&#xA;    weighting the red has lost the colour.&#xD;&#xA;    it should still be&#xD;&#xA;&#xD;&#xA;    result FF 00 00&#xD;&#xA;&#xD;&#xA;Can anyone please give a correct formula?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Z3A8X.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OAlFT.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CTVCu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23174" PostHistoryTypeId="4" PostId="8593" RevisionGUID="4671670c-9de4-420b-b5fa-6f9696ab3ad2" CreationDate="2019-02-15T03:38:25.650" UserId="10184" Comment="added 492 characters in body" Text="Blur with alpha transparency" ContentLicense="CC BY-SA 4.0" />
  <row Id="23175" PostHistoryTypeId="5" PostId="8593" RevisionGUID="c709774d-9a8b-4648-b4ca-0f188055f1d9" CreationDate="2019-02-15T03:46:38.300" UserId="10184" Comment="deleted 491 characters in body" Text="I'm writing a simple box blur for a graphics library.&#xD;&#xA;The formula makes the average of a range of pixels by adding the ARGB amounts and then dividing by the blur range&#xD;&#xA;&#xD;&#xA;For example, with a blur range of 3;&#xD;&#xA;&#xD;&#xA;    pixel1 FF FF 00 00 +&#xD;&#xA;    pixel2 FF 00 FF 00 +&#xD;&#xA;    pixel3 FF 00 00 FF&#xD;&#xA;    / 3 =&#xD;&#xA;    result FF 55 55 55&#xD;&#xA;&#xD;&#xA;Which is correct.&#xD;&#xA;A typical result shows as;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However, I am having difficulty with coming up with a formula to blur an image with alpha transparency.&#xD;&#xA;The formula above gives this result for a yellow box on a transparent background;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;You can see that the yellow is surrounded by black colour - because the red and green are being diminished to 0. The result should actually look like so;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;So; the formula of `(pixel + pixel + pixel) / range` is not working for alpha-blended images.&#xD;&#xA;&#xD;&#xA;Can anyone please give a correct formula?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Z3A8X.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OAlFT.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CTVCu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23176" PostHistoryTypeId="2" PostId="8594" RevisionGUID="e61874c9-b93b-4c56-8bc7-e1bc187cc92c" CreationDate="2019-02-15T08:25:07.880" UserId="10185" Text="I've been following these tutorials and i can't figure out how to send data to shaders using textures.&#xD;&#xA;&#xD;&#xA;https://en.wikibooks.org/wiki/OpenGL_Programming/Scientific_OpenGL_Tutorial_02&#xD;&#xA;&#xD;&#xA;In this tutorial they are using GL_LUMINANCE which has been removed from OpenGL 3.1 and above. I was wondering what should i use instead of GL_LUMINANCE? I tried GL_RGB, GL_RED but i was unable to retrieve the values.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23177" PostHistoryTypeId="1" PostId="8594" RevisionGUID="e61874c9-b93b-4c56-8bc7-e1bc187cc92c" CreationDate="2019-02-15T08:25:07.880" UserId="10185" Text="OpenGL Unable to retrieve the values of data sent to shader using textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="23178" PostHistoryTypeId="3" PostId="8594" RevisionGUID="e61874c9-b93b-4c56-8bc7-e1bc187cc92c" CreationDate="2019-02-15T08:25:07.880" UserId="10185" Text="|opengl|shader|texture|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23179" PostHistoryTypeId="2" PostId="8595" RevisionGUID="fd320079-ffd7-41c2-b522-1e3e906ffe6c" CreationDate="2019-02-15T08:58:00.753" UserId="209" Text="Two suggestions:&#xD;&#xA;&#xD;&#xA; 1. If your data is from an image you are displaying on a standard monitor, the chances are it is (or you are implicitly assuming) it is in sRGB format. This [means that the colour components are not linear][1]. Ideally, you should first map into a linear colour space, do your filtering (e.g. blurring) operations, and then map back.   &#xD;&#xA;(If you just want to try a cheap and cheerful approach, squaring each of the R G B components is not terrible approach to &quot;linearise&quot; the values, and take the sqrt to map back). The alpha channel can be assumed to be linear.&#xD;&#xA;&#xD;&#xA; 2. Once in linear colour space, the next thing you want to do before filtering is to convert the pixels to a pre-multiplied-alpha format (AKA &quot;*associated colour*&quot;).  &#xD;&#xA;Basically, given {A,R,G,B} pixel input, produce  {A, A*R/255, A*G/255, A*B/255}.  You then do your averaging on this premultiplied data as above on all four channels, and then map back by dividing through by the resulting alpha (if A=0 then, choose, RGB=0).&#xD;&#xA;&#xD;&#xA;This *should* produce a better result. &#xD;&#xA;For more info I suggest searching for Jim Blinn's &quot;Compositing&quot; articles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_(%22gamma%22)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23180" PostHistoryTypeId="5" PostId="8595" RevisionGUID="58d15190-04b3-40c3-8f89-686e0e2de4b0" CreationDate="2019-02-15T09:03:22.900" UserId="209" Comment="added reference" Text="Two suggestions:&#xD;&#xA;&#xD;&#xA; 1. If your data is from an image you are displaying on a standard monitor, the chances are it is (or you are implicitly assuming that it's) in sRGB format. This [means that the colour components are not linear][1]. Ideally, you should first map into a linear colour space, do your filtering (e.g. blurring) operations, and then map back.   &#xD;&#xA;(If you just want to try a cheap and cheerful approach, squaring each of the R G B components is not terrible approach to &quot;linearise&quot; the values, and take the sqrt to map back). The alpha channel can be assumed to be linear.&#xD;&#xA;&#xD;&#xA; 2. Once in linear colour space, the next thing you want to do before filtering is to convert the pixels to a pre-multiplied-alpha format (AKA &quot;*associated colour*&quot;).  &#xD;&#xA;Basically, given {A,R,G,B} pixel input, produce  {A, A*R/255, A*G/255, A*B/255}.  You then do your averaging on this premultiplied data as above on all four channels, and then map back by dividing through by the resulting alpha (if A=0 then, choose, RGB=0).&#xD;&#xA;&#xD;&#xA;This *should* produce a better result. &#xD;&#xA;For more info I suggest reading through Jim Blinn's [&quot;Compositing, Part1: Theory&quot;][2].  &#xD;&#xA;Particularly, note the line &quot;*Additionally, we must use associated colors for any filtering or interpolation operations*&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_(%22gamma%22)&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="23181" PostHistoryTypeId="5" PostId="8595" RevisionGUID="0baa41a3-a232-4ca9-88b2-ee05b328a49d" CreationDate="2019-02-15T09:55:50.167" UserId="209" Comment="added 125 characters in body" Text="Two suggestions:&#xD;&#xA;&#xD;&#xA; 1. If your data is from an image you are displaying on a standard monitor, the chances are it is (or you are implicitly assuming that it's) in sRGB format. This [means that the colour components are not linear][1]. Ideally, you should first map into a linear colour space, do your filtering (e.g. blurring) operations, and then map back.   &#xD;&#xA;*(If you just want to try a cheap and cheerful approach, squaring each of the R G B components is not terrible approach to &quot;linearise&quot; the values, and, obviously, use sqrt() to map back)*.  &#xD;&#xA;The alpha channel can be assumed to be linear.&#xD;&#xA;&#xD;&#xA; 2. Once in linear colour space, the next thing you want to do before filtering is to convert the pixels to a pre-multiplied-alpha format (AKA &quot;*associated colour*&quot;).  &#xD;&#xA;Basically, given {A,R,G,B} pixel input, produce  {A, A*R/255, A*G/255, A*B/255}.  You then do your averaging on this premultiplied data as above on all four channels, and then map back by dividing through by the resulting alpha (if A=0 then, choose, RGB=0).&#xD;&#xA;&#xD;&#xA;This *should* produce a better result. &#xD;&#xA;For more info I suggest reading through Jim Blinn's [&quot;Compositing, Part1: Theory&quot;][2].  &#xD;&#xA;Particularly, note the line &quot;*Additionally, we must use associated colors for any filtering or interpolation operations*&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Update*: Seems I've posted a [similar answer before][3] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_(%22gamma%22)&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/5517/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="23182" PostHistoryTypeId="2" PostId="8596" RevisionGUID="56bc93db-c2d5-425a-b26e-284a852bc4a4" CreationDate="2019-02-15T10:07:39.423" UserId="7114" Text="I implemented a [path tracer](https://github.com/zwcloud/CSharpPathTracer) and got a similar result like [this one](https://computergraphics.stackexchange.com/questions/3972/is-it-expected-that-a-naive-path-tracer-takes-many-many-samples-to-converge)&#xD;&#xA;&#xD;&#xA;Sample: 4096, time used: 537.05s  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The algorithm is exactly the same as [the one](https://en.wikipedia.org/wiki/Path_tracing#Algorithm) in wikipedia.&#xD;&#xA;&#xD;&#xA;In [this answer](https://computergraphics.stackexchange.com/a/3976/7114), @Nathan Reed said that &quot;Without explicit light sampling, I'd expect very slow convergence.&quot;.&#xD;&#xA;&#xD;&#xA;What is *explicit light sampling*? How to implement it? Do it mean *Shooting rays* from [bidirectional path tracing][2], namely the shooting path?&#xD;&#xA;&#xD;&#xA;Nathan Reed also said that &quot;Naive path tracing is more reasonable with e.g. a sky light, which almost every path can be expected to hit.&quot; So, BTW, what is a sky light? How to implement it?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lu4IP.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Path_tracing#Bidirectional_path_tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="23183" PostHistoryTypeId="1" PostId="8596" RevisionGUID="56bc93db-c2d5-425a-b26e-284a852bc4a4" CreationDate="2019-02-15T10:07:39.423" UserId="7114" Text="How to implement explicit light sampling when implementing path tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23184" PostHistoryTypeId="3" PostId="8596" RevisionGUID="56bc93db-c2d5-425a-b26e-284a852bc4a4" CreationDate="2019-02-15T10:07:39.423" UserId="7114" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23185" PostHistoryTypeId="2" PostId="8597" RevisionGUID="636ddb98-8ca9-43ab-8770-2c84c8b8f494" CreationDate="2019-02-15T10:08:56.557" UserId="9194" Text="(Not an answer but my comments are too large for a &quot;comment&quot;) &#xD;&#xA;&#xD;&#xA;This is more computational geometry than graphics. First of all, it would help if you could give an example (a drawing) which describes your input and your expected output. Are you working with low count polygons, or precise coastal maps? Do you want a real-time solution or is it off-line? It could be a big help if you would describe what you want to obtain with these rectangles covering your polygon. Also, what are your needs concerning the solution(s), for instance do you want the area of the rectangles to be as least as possible?&#xD;&#xA;&#xD;&#xA;Intrinsically this is NP-hard, this means there is a vast amount of possible solutions when the size of input data rises. Think of a circle covered by a square divided in two not necessarily equally sized rectangles. There is an infinite set of solutions already there concerning where they are split. Then just think of the amount of possible solutions for optimally packing a star shape into five or so rectangles, it's simply &quot;not possible&quot; if you want it done on a computer, in finite time.&#xD;&#xA;&#xD;&#xA;So, you will be looking for a heuristic, that gives you a solution but not necessarily an optimal one. This means that you need to figure out what you want to accept being a solution." ContentLicense="CC BY-SA 4.0" />
  <row Id="23186" PostHistoryTypeId="5" PostId="8596" RevisionGUID="efcd7814-5028-43e4-86bf-a7a4a9429b45" CreationDate="2019-02-15T10:22:29.803" UserId="7114" Comment="added 54 characters in body" Text="I implemented a [path tracer](https://github.com/zwcloud/CSharpPathTracer) and got a similar result like [this one](https://computergraphics.stackexchange.com/questions/3972/is-it-expected-that-a-naive-path-tracer-takes-many-many-samples-to-converge).&#xD;&#xA;&#xD;&#xA;Sample: 4096, time used: 537.05s  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The algorithm is exactly the same as [the one](https://en.wikipedia.org/wiki/Path_tracing#Algorithm) in wikipedia, where only the **Gathering Path** is considered.&#xD;&#xA;&#xD;&#xA;In [this answer](https://computergraphics.stackexchange.com/a/3976/7114), @Nathan Reed said that &quot;Without explicit light sampling, I'd expect very slow convergence.&quot;.&#xD;&#xA;&#xD;&#xA;What is *explicit light sampling*? How to implement it? Do it mean *Shooting rays* from [bidirectional path tracing][2], namely the **Shooting Path**?&#xD;&#xA;&#xD;&#xA;Nathan Reed also said that &quot;Naive path tracing is more reasonable with e.g. a sky light, which almost every path can be expected to hit.&quot; So, BTW, what is a sky light? How to implement it?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lu4IP.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Path_tracing#Bidirectional_path_tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="23187" PostHistoryTypeId="2" PostId="8598" RevisionGUID="2eb906ed-d85a-4833-8bb8-12656bb298a5" CreationDate="2019-02-15T11:12:46.580" UserId="6" Text="What `GL_LUMINANCE` as a texture format actually does is store one component of data per pixel that is used for the red, green and blue color components. So, a classic greyscale image (It doesn't use it for the alpha component, though, that's why there was also `GL_LUMINANCE_ALPHA` for two compnent storage and `GLINTENSITY` that broadcasts it to all components).&#xD;&#xA;&#xD;&#xA;When using shaders you don't actually need this distinction anymore, though, since you can do the swizzling yourself in the shader. So you just use a proper typed 1-component internal format, most probably `GL_R8` (i.e. 8-bit normalized fixed point red) in your case, but depending on your exact data type requirements really. And for setting it you would (in that case) use `GL_RED` as the format of the data in your RAM storage. So something like:&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, &lt;width&gt;, &lt;height&gt;, 0, GL_RED, &lt;type&gt;, &lt;data&gt;);&#xD;&#xA;&#xD;&#xA;And in the shader you can do with that red color component whatever you want. If you just need a single value per pixel, you use that. If you need a grey color (i.e. `GL_LUMINANCE` behaviour), you swizzle it to the RGB components, and if you need it as color and opacity, you swizzle it into all four components. Or whatever else you want to do.&#xD;&#xA;&#xD;&#xA;    float data = texture(...).r;&#xD;&#xA;    vec4 luminance = texture(...).rrra;&#xD;&#xA;    vec4 intensity = texture(...).rrrr;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Though, this requires your shader to be somewhat aware of what texture you're working with. But if you want to use a more generic shader working with a 4-component color from an arbitrary texture, this might be too much of a hassle. In this case what you can also do is have the [texture itself control its own swizzling behaviour](https://www.khronos.org/opengl/wiki/Texture#Swizzle_mask). This is an OpenGL 3.3+ feature and can be set with `glTexParameter` and for good old `GL_LUMIMANCE` behaviour this would be:&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_R, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_G, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_B, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_A, GL_ONE);&#xD;&#xA;&#xD;&#xA;For a broadcast into all components, i.e. `GL_INTENSITY` behaviour, you can use the shortcut&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_RGBA, GL_RED);&#xD;&#xA;&#xD;&#xA;So then you can retrieve a normal 4-component color from your texture in the shader and get the 1-component it's storing conveniently broadcast into the RGBA components of the result." ContentLicense="CC BY-SA 4.0" />
  <row Id="23188" PostHistoryTypeId="5" PostId="8598" RevisionGUID="48628ab6-7ac5-4802-a773-478817d9eb96" CreationDate="2019-02-15T11:22:59.040" UserId="6" Comment="added 16 characters in body" Text="What `GL_LUMINANCE` as a texture format actually does is store one component of data per pixel that is used for the red, green and blue color components. So, a classic greyscale image (It doesn't use it for the alpha component, though, that's why there was also `GL_LUMINANCE_ALPHA` for two compnent storage and `GL_INTENSITY` that broadcasts it to all components).&#xD;&#xA;&#xD;&#xA;When using shaders you don't actually need this distinction anymore, though, since you can do the swizzling yourself in the shader. So you just use a proper typed 1-component internal format, most probably `GL_R8` (i.e. 8-bit normalized fixed point red) in your case, but depending on your exact data type requirements really. And for setting it you would (in that case) use `GL_RED` as the format of the data in your RAM storage. So something like:&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, &lt;width&gt;, &lt;height&gt;, 0, GL_RED, &lt;type&gt;, &lt;data&gt;);&#xD;&#xA;&#xD;&#xA;And in the shader you can do with that red color component whatever you want. If you just need a single value per pixel, you use that. If you need a grey color (i.e. `GL_LUMINANCE` behaviour), you swizzle it to the RGB components, and if you need it as color and opacity, you swizzle it into all four components. Or whatever else you want to do.&#xD;&#xA;&#xD;&#xA;    float data = texture(...).r;&#xD;&#xA;    vec4 luminance = texture(...).rrra;&#xD;&#xA;    vec4 intensity = texture(...).rrrr;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Though, this requires your shader to be somewhat aware of what texture you're working with. But if you want to use a more generic shader working with a 4-component color from an arbitrary texture, this might be too much of a hassle. In this case what you can also do is have the [texture itself control its own swizzling behaviour](https://www.khronos.org/opengl/wiki/Texture#Swizzle_mask). This is an OpenGL 3.3+ feature and can be set with `glTexParameter` and for good old `GL_LUMIMANCE` behaviour this would be:&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_R, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_G, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_B, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_A, GL_ONE);&#xD;&#xA;&#xD;&#xA;For a broadcast into all components, i.e. `GL_INTENSITY` behaviour, you can use the shortcut&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_RGBA, GL_RED);&#xD;&#xA;&#xD;&#xA;So then you can retrieve a normal 4-component color from your texture in the shader and get the 1-component it's storing conveniently broadcast into the RGBA components of the result." ContentLicense="CC BY-SA 4.0" />
  <row Id="23189" PostHistoryTypeId="5" PostId="8598" RevisionGUID="295f053d-9332-433e-ba06-2932b14f82aa" CreationDate="2019-02-15T11:28:36.277" UserId="6" Comment="added 14 characters in body" Text="What `GL_LUMINANCE` as a texture format actually does is store one component of data per pixel that is used for the red, green and blue color components. So, a classic greyscale image (It doesn't use it for the alpha component, though, that's why there was also `GL_LUMINANCE_ALPHA` for two compnent storage and `GL_INTENSITY` that broadcasts it to all components).&#xD;&#xA;&#xD;&#xA;When using shaders you don't actually need this distinction anymore, though, since you can do the swizzling yourself in the shader. So you just use a proper typed 1-component internal format, most probably `GL_R8` (i.e. 8-bit normalized fixed point red) in your case, but depending on your exact data type requirements really. And for setting it you would (in that case) use `GL_RED` as the format of the data in your RAM storage. So something like:&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, &lt;width&gt;, &lt;height&gt;, 0, GL_RED, &lt;type&gt;, &lt;data&gt;);&#xD;&#xA;&#xD;&#xA;And in the shader you can do with that red color component whatever you want. If you just need a single value per pixel, you use that. If you need a grey color (i.e. `GL_LUMINANCE` behaviour), you swizzle it to the RGB components, and if you need it as color and opacity, you swizzle it into all four components. Or whatever else you want to do.&#xD;&#xA;&#xD;&#xA;    float data = texture(...).r;&#xD;&#xA;    vec4 luminance = texture(...).rrra;&#xD;&#xA;    vec4 intensity = texture(...).rrrr;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Though, this requires your shader to be somewhat aware of what texture you're working with. But if you want to use a more generic shader working with a 4-component color from an arbitrary texture, this might be too much of a hassle. In this case what you can also do is have the [texture itself control its own swizzling behaviour](https://www.khronos.org/opengl/wiki/Texture#Swizzle_mask). This is an OpenGL 3.3+ feature and can be set with `glTexParameter` and for good old `GL_LUMIMANCE` behaviour this would be:&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_R, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_G, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_B, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_A, GL_ONE);&#xD;&#xA;&#xD;&#xA;For a broadcast into all components, i.e. `GL_INTENSITY` behaviour, you can use the shortcut&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_RGBA, GL_RED);&#xD;&#xA;&#xD;&#xA;So then you can retrieve a normal 4-component color from your texture in the shader and get the 1-component it's storing conveniently broadcast into the RGBA components of the result." ContentLicense="CC BY-SA 4.0" />
  <row Id="23190" PostHistoryTypeId="5" PostId="8597" RevisionGUID="578d32a5-8e33-48da-b2f4-831322e0e6ee" CreationDate="2019-02-15T13:10:43.083" UserId="9194" Comment="added 391 characters in body" Text="(Not an answer but my comments are too large for a &quot;comment&quot;) &#xD;&#xA;&#xD;&#xA;This is more computational geometry than graphics. First of all, it would help if you could give an example (a drawing) which describes your input and your expected output. Are you working with low count polygons, or precise coastal maps? Do you want a real-time solution or is it off-line? It could be a big help if you would describe what you want to obtain with these rectangles covering your polygon. Also, what are your needs concerning the solution(s), for instance do you want the area of the rectangles to be as least as possible?&#xD;&#xA;&#xD;&#xA;Intrinsically this is NP-hard, this means there is a vast amount of possible solutions when the size of input data rises. Think of a circle covered by a square divided in two not necessarily equally sized rectangles. There is an infinite set of solutions already there concerning where they are split. Then just think of the amount of possible solutions for optimally packing a star shape into five or so rectangles, it's simply &quot;not possible&quot; if you want it done on a computer, in finite time.&#xD;&#xA;&#xD;&#xA;So, you will be looking for a heuristic, that gives you a solution but not necessarily an optimal one. This means that you need to figure out what you want to accept being a solution.&#xD;&#xA;&#xD;&#xA;Edit: One variant of the problem at hand, that I didn't think of, could be that you already have N rectangles (size is given up front, they might be of the same size) that you wish to cover a polygon with. It's not simpler, also it could be impossible, for instance if the total area of the rectangles is less than the area of the polygon. So: Please describe your problem at bit more :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23191" PostHistoryTypeId="2" PostId="8599" RevisionGUID="aa92ec61-f224-4b59-b770-8b8618843f12" CreationDate="2019-02-15T15:27:58.447" UserId="228" Text="I read that paper as well last year. There's a strong assumption made by authors which is the &quot;stationary&quot;. What this means is that in absence of light in given 3000x2000 pixels image the material is more or less the same in each tile of 192x192. The reason for this is because we the surface is lit by white light is like they have a sample of BRDF for a set of angles.&#xD;&#xA;&#xD;&#xA;The first shot is to get the stationarity of the material. The second shot is to get how each tile reacts to the interaction with the light from a different angle.&#xD;&#xA;&#xD;&#xA;They collect the set of all tiles with the light and they later use their BRDF model to perform the fitting.&#xD;&#xA;&#xD;&#xA;The fitting, as you say, is done by using the L-M algorithm. There're few inconsistenties with the formula they use to perform the fitting, if I remember correctly the use non differentiable functions and they still perform the fitting.&#xD;&#xA;&#xD;&#xA;If I remember correctly the actual fitting algorithm is constructed by one hand differentiating part of their cost function, while from the other hand they use a numerical approximation of the derivative/gradient/Jacobian.&#xD;&#xA;&#xD;&#xA;The BRDF they use is parametrized using the several maps you mention in your question, therefore when they minimize the cost function they get optimal maps." ContentLicense="CC BY-SA 4.0" />
  <row Id="23199" PostHistoryTypeId="2" PostId="8602" RevisionGUID="ad50c049-f6f3-4602-902c-81ba6b2ea199" CreationDate="2019-02-15T22:43:02.520" UserId="6496" Text="It turned out that the fillModeNonSolid feature needed to be explicitly enabled during logical device creation." ContentLicense="CC BY-SA 4.0" />
  <row Id="23200" PostHistoryTypeId="2" PostId="8603" RevisionGUID="9dbf5622-a9ee-4e79-9425-63246314c9a4" CreationDate="2019-02-15T22:49:26.217" UserId="10188" Text="I rely on this answer from Nathan Reed: https://computergraphics.stackexchange.com/questions/4969/how-much-precision-do-i-need-in-my-g-buffer/4971#4971?newreg=c82ae981d40148c1a38922de1b259a4c&#xD;&#xA;&#xD;&#xA;It is proposed to use two different texture formats for one Gbuffer. &#xD;&#xA;&#xD;&#xA;However as far as I know, color texture attachments to framebuffer objects must have the same format: https://www.khronos.org/opengl/wiki/Framebuffer_Object&#xD;&#xA;&#xD;&#xA;&gt; Texture&#xD;&#xA;    For the purposes of this article, a texture is an object that contains some number of images, as defined above. **All of the images have the same format**, but they do not have to have the same size (different mip-maps, for example). Textures can be accessed from Shaders via various methods.&#xD;&#xA;&#xD;&#xA;Is it possbile to use multiple render targets with different texture formats for a framebuffer? Or should just the lowest common format be choosen and manually pack and unpack the 16-Bit values in the shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23201" PostHistoryTypeId="1" PostId="8603" RevisionGUID="9dbf5622-a9ee-4e79-9425-63246314c9a4" CreationDate="2019-02-15T22:49:26.217" UserId="10188" Text="GBuffer: Framebuffer with different texture format types?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23202" PostHistoryTypeId="3" PostId="8603" RevisionGUID="9dbf5622-a9ee-4e79-9425-63246314c9a4" CreationDate="2019-02-15T22:49:26.217" UserId="10188" Text="|opengl|deferred-rendering|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23240" PostHistoryTypeId="2" PostId="8604" RevisionGUID="be5326d3-1619-43f4-9ead-ae36de68b9e8" CreationDate="2019-02-16T00:27:42.353" UserId="6" Text="You have a bit of a misunderstanding there. The paragraph you quoted doesn't actually say anything about framebuffer objects yet. It just talks about a single *texture*. While we usually understand a texture as a single image, it is (or can be) *actually* comprised of a *set of images*. This might be because it is an [Array Texture](https://www.khronos.org/opengl/wiki/Array_Texture) or, even more common, it just has a set of [Mip Map Levels](https://www.khronos.org/opengl/wiki/Texture#Mip_maps) (basically increasingly smaller filtered versions of the base image, used for advanced texture filtering). And yes, within a single texture, all those images have the same format. However *one* such texture usually makes for *one* render target.&#xD;&#xA;&#xD;&#xA;All this has nothing to do with multiple render targets yet. And you will notice that the later parts of that article that speak about the actual framebuffer attachments, specifically the part about [Framebuffer Completeness](https://www.khronos.org/opengl/wiki/Framebuffer_Object#Completeness_Rules) **don't say anything of the sort of all attachments needing to have the same format, because there is no such restriction**. They don't even need to have the same dimensions. The only thing that is required is that they all have the same number of samples (if they're multisampled at all).&#xD;&#xA;&#xD;&#xA;It *is* possible that an implementation still doesn't support all kinds of image formats and combinations, but there are some that are required and a &quot;reasonable&quot; implementation will support a wide variety of format combinations, including ones with mixed pixel bit-depths.&#xD;&#xA;&#xD;&#xA;There *was* a stricter limitation on the images in the original [GL_EXT_framebuffer_object extension](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_framebuffer_object.txt), namely that all attachments have the same size and internal format. However, since it has found its way into OpenGL 3.0+ core (and was from there exported back as the more advanced [GL_ARB_framebuffer_object extension](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_framebuffer_object.txt)) they loosened these restrictions." ContentLicense="CC BY-SA 4.0" />
  <row Id="23246" PostHistoryTypeId="2" PostId="8606" RevisionGUID="65e3cc9f-4635-452f-b8fc-a3bd1b769211" CreationDate="2019-02-16T13:09:28.590" UserId="10191" Text="&lt;b&gt; Problem &lt;/b&gt;&#xD;&#xA;&#xD;&#xA;I am following the book &lt;b&gt;Ray tracing in one weekend &lt;/b&gt;, and I got stuck after the implementation of the material Metal. I checked my code many times, and it looks exactly like the code implemented by Peter Shirley.&#xD;&#xA;The problem is that, at this point, my code would need to generate this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Instead, my implementation results in this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;There is no reflection on the left and right sphere, even if the code looks fine. I am not posting the code here since many classes are involved, and I implemented it following strictly the book. Did someone have a similar problem? I can post relevant parts of code that can help. &#xD;&#xA;&#xD;&#xA;&lt;b&gt; Possible solution &lt;/b&gt;&#xD;&#xA;&#xD;&#xA;The function of the reflection is not the problem, since it is very simple and it is exactly like the one proposed in the book. Also, when I set the sphere below (the floor) as Metal instead of Lambertian, it shows the reflections correctly:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This suggests that the problem is not the reflection function, nor the material. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EIo3S.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M0qkU.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vnLjf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23247" PostHistoryTypeId="1" PostId="8606" RevisionGUID="65e3cc9f-4635-452f-b8fc-a3bd1b769211" CreationDate="2019-02-16T13:09:28.590" UserId="10191" Text="Ray tracing in One weeked: issue with metal reflection" ContentLicense="CC BY-SA 4.0" />
  <row Id="23248" PostHistoryTypeId="3" PostId="8606" RevisionGUID="65e3cc9f-4635-452f-b8fc-a3bd1b769211" CreationDate="2019-02-16T13:09:28.590" UserId="10191" Text="|raytracing|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23250" PostHistoryTypeId="2" PostId="8607" RevisionGUID="b7132ed8-c060-4bd2-9c8a-3c625733bba6" CreationDate="2019-02-17T13:47:40.817" UserId="10191" Text="The problem was in the way I was calculating the function `bool Sphere::hit()`. The author eliminates some redundant 2's that cancel each other without explicitly showing it, and if you don't pay attention to this detail the code the `hit` function will not work as it is supposed to. In case someone else is stuck, that might be the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="23251" PostHistoryTypeId="5" PostId="8585" RevisionGUID="553a778e-1782-4ca1-9e91-f7a234daa655" CreationDate="2019-02-17T20:04:04.407" UserId="6046" Comment="added 81 characters in body" Text="So I was just reading up on how to create more Physically Based Lights and wandered into the realm of photometry. I read the paper &quot;Moving FrostBite to PBR&quot; and in it the author claims he decided to have all the light sources in units of Photometry (Lumens/Luminance etc). &#xD;&#xA;&#xD;&#xA;The author also writes how to convert between radiometric and photometric units earlier on. But later he decides to ditch this conversion and have his lights in photometric from the get go. I don't understand how is this compatible?&#xD;&#xA;&#xD;&#xA;If I want to use the same technique for my normal path tracer, is there a different form of the rendering equation for photometry? Should I just swap the radiometric parts for the photometric parts (radiance for luminance, radiant flux for lumens etc). Or maybe I should convert from photometric to radiometric like the paper mentioned. How does this all tie up, if anybody can clear it.&#xD;&#xA;&#xD;&#xA;EDIT:- Just saw a [similar][1] question (sorry my net is slow). As nathan suggested in his answer rendering RGB images proceeds more naturally in radiometric units. If I opt the approach to convert between radiometric and photometric units using luminous efficacy for light sources will there still be a problem as Nathan suggested (wavelength dependance of photometric units) or that problem exists solely when rendering exclusively in Photometric units?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/1992/rendering-in-radiometric-units-or-photometric?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23252" PostHistoryTypeId="2" PostId="8608" RevisionGUID="c4589989-8731-4ec6-b6e7-d4be995186aa" CreationDate="2019-02-17T23:20:54.137" UserId="7868" Text="The D3D12 programming guide suggests specific [allocation strategies][1] for command queues and allocators, but the creation methods for those objects [operate][2] [directly][3] on queue/allocator pointers without taking a heap and an offset as an argument. How do I explicitly mark the memory I want to use for command processing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/desktop/direct3d12/memory-management-strategies&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createcommandqueue&#xD;&#xA;  [3]: https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createcommandallocator" ContentLicense="CC BY-SA 4.0" />
  <row Id="23253" PostHistoryTypeId="1" PostId="8608" RevisionGUID="c4589989-8731-4ec6-b6e7-d4be995186aa" CreationDate="2019-02-17T23:20:54.137" UserId="7868" Text="How can I control memory for command allocators and command queues in D3D12?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23254" PostHistoryTypeId="3" PostId="8608" RevisionGUID="c4589989-8731-4ec6-b6e7-d4be995186aa" CreationDate="2019-02-17T23:20:54.137" UserId="7868" Text="|c++|gpu|directx12|memory|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23255" PostHistoryTypeId="2" PostId="8609" RevisionGUID="fd6fbbb5-0feb-4f71-980b-cc71d0973d9d" CreationDate="2019-02-17T23:38:26.360" UserId="7868" Text="An efficient compute-shaded image filter would be emitted with (screenX / [kernel width], screenY / [kernel height], 1) groups and one kernel in each group, allowing texels to pass into groupshared memory and reducing the total number of samples at each pixel. But it seems like this will only apply the filter within the patches defined by each thread-group and create aliasing between them. Why doesn't this happen? If it does happen, how is it avoided?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23256" PostHistoryTypeId="1" PostId="8609" RevisionGUID="fd6fbbb5-0feb-4f71-980b-cc71d0973d9d" CreationDate="2019-02-17T23:38:26.360" UserId="7868" Text="Why don't discretization errors occur with compute-shaded kernel filters?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23257" PostHistoryTypeId="3" PostId="8609" RevisionGUID="fd6fbbb5-0feb-4f71-980b-cc71d0973d9d" CreationDate="2019-02-17T23:38:26.360" UserId="7868" Text="|image-processing|filtering|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23258" PostHistoryTypeId="2" PostId="8610" RevisionGUID="9f87eb45-f7a8-4b4b-95f4-bc40bae47ee9" CreationDate="2019-02-17T23:39:20.707" UserId="2654" Text="You don't.&#xD;&#xA;&#xD;&#xA;These objects typically work with CPU memory, not device memory. And to the extent that they involve device memory, such allocations tend to be rare and/or fixed in size (a queue may have a small spot of device memory that the hardware queue reads commands from or something, but even that is implementation-dependent).&#xD;&#xA;&#xD;&#xA;Vulkan allows you to give objects which may allocate non-device memory allocation parameters to allow you to allocate said memory for them. But even then, there is no *guarantee* that they will always allocate memory through your functions. Such systems can bypass your allocation routines, and only tell you allocator that it is allocating X bytes of memory (this is typically done for memory pages that have to be allocated in a special way). It doesn't let you actually provide it.&#xD;&#xA;&#xD;&#xA;That documentation does not seem to be talking about controlling how those objects allocate memory, but when and how you *create* those objects. Command allocators and queues are critical, so you create X allocators and Y queues at the start and keep them around forever." ContentLicense="CC BY-SA 4.0" />
  <row Id="23259" PostHistoryTypeId="5" PostId="8609" RevisionGUID="df3ce706-96aa-429d-bb7a-dabdfe481a8b" CreationDate="2019-02-18T00:19:07.520" UserId="7868" Comment="Small wording update" Text="An efficient compute-shaded image filter would be emitted with (screenX / [kernel width], screenY / [kernel height], 1) groups and one kernel in each group, allowing texels to pass into groupshared memory and reducing the total number of samples at each pixel. But it seems like this will only apply the filter within the patches defined by each thread-group and create aliasing between them. Why doesn't this happen? If it does happen, how is it mitigated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23263" PostHistoryTypeId="2" PostId="8612" RevisionGUID="79650efa-b366-44a0-9130-5e10a149c432" CreationDate="2019-02-18T18:02:18.913" UserId="10129" Text="I have problem with creating diffuse irradiance map. As reference I am using https://learnopengl.com/PBR/IBL/Diffuse-irradiance and https://github.com/TheEvilBanana/PhysicallyBasedRendering/blob/master/Game.cpp#L490.&#xD;&#xA;&#xD;&#xA;My map convolution looks not as it is supposed. I have black dot on every face. I use 2048x2048 which I render to 256x256 Texture2D and save each face which I then assemble. Below debug image. Up is +Y, Down is -Y, Middle is from the left -X, -Z, +X, +Z. What can I do to fix it? Also it looks like I am rendering same face twice somehow because +(plus) faces looks same like their -(minus) faces. &#xD;&#xA;&#xD;&#xA;[![Skybox / irradiance map][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0NZGq.png&#xD;&#xA;&#xD;&#xA;**Render to texture method:**&#xD;&#xA;&#xD;&#xA;    bool GraphicsClass::ConvoluteShader(ID3D11ShaderResourceView * srcTex, RenderTextureClass * dstTex)&#xD;&#xA;    {&#xD;&#xA;	ifstream skyboxFile;&#xD;&#xA;	skyboxFile.open(&quot;Skyboxes/conv_cubemap.dds&quot;);&#xD;&#xA;	if (skyboxFile.fail() == false)&#xD;&#xA;		return true;&#xD;&#xA;&#xD;&#xA;	XMMATRIX worldMatrix, viewMatrix, projectionMatrix;&#xD;&#xA;	bool result;&#xD;&#xA;&#xD;&#xA;	XMFLOAT3 position = XMFLOAT3(0, 0, 0);&#xD;&#xA;	XMFLOAT3 up[] = { XMFLOAT3(0, 1, 0), XMFLOAT3(0, 0, 1), XMFLOAT3(1, 0, 0), XMFLOAT3(0, -1, 0), XMFLOAT3(0, 0, -1), XMFLOAT3(-1, 0, 0) };&#xD;&#xA;	wchar_t* filenames[] = { L&quot;S﻿kyboxes/conv_posx.dds&quot;, L&quot;Skyboxes/conv_posy.dds&quot; , L&quot;Skyboxes/conv_posz.dds&quot;, L&quot;Skyboxes/conv_negx.dds&quot;, L&quot;Skyboxes/conv_negy.dds&quot;, L&quot;Skyboxes/conv_negz.dds&quot; };&#xD;&#xA;	for (int i = 0; i &lt; 6; i++)&#xD;&#xA;	{&#xD;&#xA;		dstTex-&gt;SetRenderTarget(m_D3D-&gt;GetDeviceContext(), m_D3D-&gt;GetDepthStencilView());&#xD;&#xA;		dstTex-&gt;ClearRenderTarget(m_D3D-&gt;GetDeviceContext(), m_D3D-&gt;GetDepthStencilView(), 1.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;		m_Camera-&gt;Render();&#xD;&#xA;		m_Camera-&gt;GetViewMatrix(viewMatrix);&#xD;&#xA;		m_D3D-&gt;GetWorldMatrix(worldMatrix);&#xD;&#xA;		m_D3D-&gt;GetProjectionMatrix(projectionMatrix);&#xD;&#xA;&#xD;&#xA;		m_convoluteShader-&gt;SetUpVector(up[i]);&#xD;&#xA;&#xD;&#xA;		m_D3D-&gt;ChangeRasterizerCulling(D3D11_CULL_BACK);&#xD;&#xA;		m_D3D-&gt;ChangeDepthStencilComparison(D3D11_COMPARISON_LESS_EQUAL);&#xD;&#xA;&#xD;&#xA;		m_quadModel-&gt;Render(m_D3D-&gt;GetDeviceContext());&#xD;&#xA;		m_convoluteShader-&gt;Render(m_D3D-&gt;GetDeviceContext(), m_quadModel-&gt;GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);&#xD;&#xA;&#xD;&#xA;		m_D3D-&gt;ChangeRasterizerCulling(D3D11_CULL_BACK);&#xD;&#xA;		m_D3D-&gt;ChangeDepthStencilComparison(D3D11_COMPARISON_LESS);&#xD;&#xA;&#xD;&#xA;		m_D3D-&gt;SetBackBufferRenderTarget();&#xD;&#xA;		m_D3D-&gt;ResetViewport();&#xD;&#xA;&#xD;&#xA;		m_renderTexturePreview-&gt;BindTexture(dstTex-&gt;GetShaderResourc﻿eView());&#xD;&#xA;&#xD;&#xA;		SaveDDSTextureToFile(m_D3D-&gt;GetDeviceContext(), dstTex-&gt;GetShaderResource(), filenames[i]);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	system(&quot;texassemble cube -w 256 -h 256 -f R8G8B8A8_UNORM -o Skyboxes/conv_cubemap.dds Skyboxes/conv_posx.dds Skyboxes/conv_negx.dds Skyboxes/conv_posy.dds Skyboxes/conv_negy.dds Skyboxes/conv_posz.dds Skyboxes/conv_negz.dds&quot;);&#xD;&#xA;&#xD;&#xA;**Vertex shader:**&#xD;&#xA;&#xD;&#xA;	cbuffer MatrixBuffer&#xD;&#xA;	{&#xD;&#xA;		matrix worldMatrix;&#xD;&#xA;		matrix viewMatrix;&#xD;&#xA;		matrix projectionMatrix;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct VertexInputType&#xD;&#xA;	{&#xD;&#xA;		float4 position : POSITION;    &#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct PixelInputType&#xD;&#xA;	{&#xD;&#xA;		float4 positionSV : SV_POSITION;&#xD;&#xA;		float4 position : POSITION;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;	PixelInputType ColorVertexShader(VertexInputType input)&#xD;&#xA;	{&#xD;&#xA;		PixelInputType output;&#xD;&#xA;&#xD;&#xA;		output.position = input.position;&#xD;&#xA;		input.position.w = 1.0f;&#xD;&#xA;&#xD;&#xA;		output.positionSV = mul(input.position, worldMatrix).xyww;&#xD;&#xA;		output.positionSV = mul(output.positionSV, viewMatrix).xyww;&#xD;&#xA;		output.positionSV = mul(output.positionSV, projectionMatrix).xyww;&#xD;&#xA;&#xD;&#xA;		return output;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**Pixel Shader:**&#xD;&#xA;&#xD;&#xA;	TextureCube shaderTexture;&#xD;&#xA;	SamplerState SampleType;&#xD;&#xA;&#xD;&#xA;	cbuffer UpVectorBuffer&#xD;&#xA;	{&#xD;&#xA;		float3 g_upVectorVal;&#xD;&#xA;		float g_upVectorPadding;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct PixelInputType&#xD;&#xA;	{&#xD;&#xA;		float4 positionSV : SV_POSITION;&#xD;&#xA;		float4 position : POSITION;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	static const float PI = 3.14159265359f;&#xD;&#xA;&#xD;&#xA;	float4 ColorPixelShader(PixelInputType input) : SV_TARGET&#xD;&#xA;	{&#xD;&#xA;		float3 normal = normalize(input.position.xyz);&#xD;&#xA;&#xD;&#xA;		float3 irradiance = float3(0.0f, 0.0f, 0.0f);&#xD;&#xA;	&#xD;&#xA;		float3 up = g_upVectorVal;&#xD;&#xA;		float3 right = cross(up, normal);&#xD;&#xA;		up = cross(normal, right);&#xD;&#xA;&#xD;&#xA;		float sampleDelta = 0.025f;&#xD;&#xA;		float nrSamples = 0.0f;&#xD;&#xA;		for (float phi = 0.0f; phi &lt; 2.0 * PI; phi += sampleDelta)&#xD;&#xA;		{&#xD;&#xA;			for (float theta = 0.0f; theta &lt; 0.5 * PI; theta += sampleDelta)&#xD;&#xA;			{&#xD;&#xA;				float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));&#xD;&#xA;				float3 sampleVec = (tangentSample.x * right) + (tangentSample.y * up) + (tangentSample.z * normal);&#xD;&#xA;&#xD;&#xA;				irradiance += shaderTexture.Sample(SampleType, sampleVec).rgb * cos(theta) * sin(theta);&#xD;&#xA;				nrSamples++;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		irradiance = PI * irradiance * (1.0f / nrSamples);&#xD;&#xA;		return float4(irradiance, 1.0f);&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="23264" PostHistoryTypeId="1" PostId="8612" RevisionGUID="79650efa-b366-44a0-9130-5e10a149c432" CreationDate="2019-02-18T18:02:18.913" UserId="10129" Text="Weirdly looking diffuse irradiance map" ContentLicense="CC BY-SA 4.0" />
  <row Id="23265" PostHistoryTypeId="3" PostId="8612" RevisionGUID="79650efa-b366-44a0-9130-5e10a149c432" CreationDate="2019-02-18T18:02:18.913" UserId="10129" Text="|pbr|directx11|directx|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23266" PostHistoryTypeId="2" PostId="8613" RevisionGUID="66064d7c-41fe-47f3-988d-2c4a6113052c" CreationDate="2019-02-18T18:03:36.223" UserId="5664" Text="So usually texture samplers are set directly in the `D3D12_ROOT_SIGNATURE_DESC` structure in DX12, at least that's how I've been setting them. I was wondering if it's possible to put them in an upload_heap and map a CPU pointer to it or something similar to make it possible to modify the samplers dynamicaly? " ContentLicense="CC BY-SA 4.0" />
  <row Id="23267" PostHistoryTypeId="1" PostId="8613" RevisionGUID="66064d7c-41fe-47f3-988d-2c4a6113052c" CreationDate="2019-02-18T18:03:36.223" UserId="5664" Text="Is it possible to bind dynamic texture samplers to a shader in DX12?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23268" PostHistoryTypeId="3" PostId="8613" RevisionGUID="66064d7c-41fe-47f3-988d-2c4a6113052c" CreationDate="2019-02-18T18:03:36.223" UserId="5664" Text="|shader|directx12|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23270" PostHistoryTypeId="2" PostId="8614" RevisionGUID="05b21b83-6172-44e8-bcbc-1b004f267e4d" CreationDate="2019-02-19T12:34:22.417" UserId="5664" Text="Yes it is possible by putting Samplers in descriptor tables to dynamically assign and index into them. Source: https://youtu.be/Wbnw87tYqVg?t=754&#xD;&#xA;&#xD;&#xA;Here's an example that uses the HLSL root signature syntax to do this here:&#xD;&#xA;https://youtu.be/Wbnw87tYqVg?t=5277" ContentLicense="CC BY-SA 4.0" />
  <row Id="23271" PostHistoryTypeId="2" PostId="8615" RevisionGUID="5b558030-9370-4a4b-80dd-ffaed50f057f" CreationDate="2019-02-19T18:42:46.317" UserId="9749" Text="I can't comment as I don't have enough reputation but I would take a look at packing algorithms, specially the ones using No/Inner Fit Polygon through computation of Minkowsky differences." ContentLicense="CC BY-SA 4.0" />
  <row Id="23275" PostHistoryTypeId="50" PostId="8444" RevisionGUID="a57cc90f-0976-4545-9e99-d10711772bc3" CreationDate="2019-02-20T01:00:40.117" UserId="-1" />
  <row Id="23276" PostHistoryTypeId="5" PostId="8444" RevisionGUID="0453972a-0f7d-499c-a825-6a00053109f0" CreationDate="2019-02-20T09:21:34.537" UserId="6046" Comment="deleted 9 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS however now I'm getting more fireflies and I think I read that MIS reduces fireflies?. Anyways, I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`.&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter but the fireflies still remain. Note the reflection is harder to converge although its 2500spp while the one below is 1500 spp.&#xD;&#xA;&#xD;&#xA;Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;[![with MIS ][5]][5]&#xD;&#xA;[![Without MIS][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/GYYP1.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/4suBT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23277" PostHistoryTypeId="5" PostId="8444" RevisionGUID="fee183f1-8a05-40ff-ac1e-b8b81175723f" CreationDate="2019-02-20T11:21:33.870" UserId="6046" Comment="added 168 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS &lt;strike&gt;however now I'm getting more fireflies and I think I read that MIS reduces fireflies?&lt;/strike&gt; Updated the images. **It seems fireflies are less in MIS however, the reflection seems harder to converge.** &#xD;&#xA;&#xD;&#xA;I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter but the fireflies still remain.&#xD;&#xA;&#xD;&#xA;Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/WeiZN.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/PPnyh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23278" PostHistoryTypeId="5" PostId="8444" RevisionGUID="5c41ab15-62b1-49e9-bf39-5f5e99d0a3d5" CreationDate="2019-02-20T14:07:35.913" UserId="6046" Comment="added 17 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS &lt;strike&gt;however now I'm getting more fireflies and I think I read that MIS reduces fireflies?&lt;/strike&gt; Updated the images. **It seems fireflies are less in MIS however, the reflection seems harder to converge.** &#xD;&#xA;&#xD;&#xA;I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter. Still don't know if MIS is working as intended.&#xD;&#xA;&#xD;&#xA;Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/WeiZN.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/PPnyh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23280" PostHistoryTypeId="2" PostId="8617" RevisionGUID="c4395db6-69d6-45a0-b9cd-08f3c0319d29" CreationDate="2019-02-20T21:55:41.273" UserId="120" Text="Your understanding of the matrix structure in Q3 is correct. This code just does not construct a matrix explicitly and the matrix multiplication is applied implicitly. I think this part might cause your confusion.&#xD;&#xA;Instead of deciphering the code, I would rather derive the transform and compare it with the code.&#xD;&#xA;&#xD;&#xA;The affine (6 degrees of freedom) and projective matrix (8 dof) map points to points. So you can build a system of equations for each pair of points in different frames. You will need to solve this system for the components of the matrix (Q1).&#xD;&#xA;&#xD;&#xA;Let $M$ be the transform matrix, then&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;M (0,0,1) &amp;= (X_1,Y_1,1) \\&#xD;&#xA;M (1,0,1) &amp;= (X_2,Y_2,1) \\&#xD;&#xA;M (0,1,1) &amp;= (X_3,Y_3,1) \\&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Each of above lines gives you two equations. Now you have 6 equations and the affine matrix can be derived.&#xD;&#xA;For the projective matrix, we need extra two equations using the point $(X_4,Y_4)$:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;H_4 &amp;= M (1,1,1) \\&#xD;&#xA;\frac{H_4}{H_4.z} &amp;= (X_4,Y_4,1)&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Note that I have to divide the homogeneous part for the transformed point.&#xD;&#xA;&#xD;&#xA;Solve this linear system you can get an expression for your matrix $M$. Perform $M (f_x,f_y,1)$ you will see how it transforms the point. I believe this solves your Q2, Q3, Q5 and Q7.&#xD;&#xA;&#xD;&#xA;For Q4, I think it is just a convention of pixel position and your understanding should be correct.&#xD;&#xA;&#xD;&#xA;-----------&#xD;&#xA;Appendix: maple code to verify the answer&#xD;&#xA;```&#xD;&#xA;with(ListTools):&#xD;&#xA;# affine matrix&#xD;&#xA;m:=&lt;m11,m21,0|m12,m22,0|m13,m23,1&gt;;&#xD;&#xA;# Build equations&#xD;&#xA;E:=[convert(m.&lt;0,0,1&gt; - &lt;X1,Y1,1&gt;,list),convert(m.&lt;1,0,1&gt; - &lt;X2,Y2,1&gt;,list), convert(m.&lt;0,1,1&gt; - &lt;X3,Y3,1&gt;,list)];&#xD;&#xA;# E=[[m13 - X1, m23 - Y1, 0], [m11 + m13 - X2, m21 + m23 - Y2, 0],[m12 + m13 - X3, m22 + m23 - Y3, 0]]&#xD;&#xA;# Solve E=0&#xD;&#xA;sol:=eliminate(Flatten(E),indets(m));&#xD;&#xA;# Plug the solution back to m:&#xD;&#xA;subs(sol[1],m);&#xD;&#xA;                           [-X1 + X2    -X1 + X3    X1]&#xD;&#xA;                           [                          ]&#xD;&#xA;                           [-Y1 + Y2    -Y1 + Y3    Y1]&#xD;&#xA;                           [                          ]&#xD;&#xA;                           [   0           0        1 ]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# projective matrix&#xD;&#xA;p:=&lt;m11,m21,a|m12,m22,b|m13,m23,1&gt;;&#xD;&#xA;# Compute transformed points&#xD;&#xA;U0:=p.&lt;0,0,1&gt;;&#xD;&#xA;U1:=p.&lt;1,0,1&gt;;&#xD;&#xA;U2:=p.&lt;1,1,1&gt;;&#xD;&#xA;U2:=p.&lt;0,1,1&gt;;&#xD;&#xA;U3:=p.&lt;1,1,1&gt;;&#xD;&#xA;# Build equations&#xD;&#xA;E:=[convert(U0/U0[3]-&lt;X1,Y1,1&gt;,list),convert(U1/U1[3]-&lt;X2,Y2,1&gt;,list),convert(U2/U2[3]-&lt;X3,Y3,1&gt;,list),convert(U3/U3[3]-&lt;X4,Y4,1&gt;,list)];&#xD;&#xA;# Sove E=0&#xD;&#xA;solp:=eliminate(Flatten(E),indets(p));&#xD;&#xA;# copy their code for xx and yy:&#xD;&#xA;xx:=((X4-X1)*(Y3-Y1)-(Y4-Y1)*(X3-X1))/((X2-X1)*(Y3-Y1)-(Y2-Y1)*(X3-X1));&#xD;&#xA;yy:=((X4-X1)*(Y2-Y1)-(Y4-Y1)*(X2-X1))/((X3-X1)*(Y2-Y1)-(Y3-Y1)*(X2-X1));&#xD;&#xA;# Verify our a and b, compare ours with their expressing using xx and yy&#xD;&#xA;subs(solp[1],a);&#xD;&#xA;subs(solp[1],b);&#xD;&#xA;simplify(subs(solp[1],a)-(yy-1)/(1-xx-yy));&#xD;&#xA;# It is 0 as expected&#xD;&#xA;simplify(subs(solp[1],b)-(xx-1)/(1-xx-yy));&#xD;&#xA;# It is also 0&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23281" PostHistoryTypeId="2" PostId="8618" RevisionGUID="842d87d6-6b42-4f39-a0b3-b8764cea8f18" CreationDate="2019-02-21T03:08:51.373" UserId="120" Text="From your code snippet and your result for 2x2 example, I can see that you are actually simulating a domain with only Neumann boundary conditions (slip wall). In this case, the system contains a null space and your matrix is singular.&#xD;&#xA;&#xD;&#xA;If this is the simulation configuration you want (i.e. no Dirichlet(pressure) BC), you will need to project out the null space from your solution. This is straightforward if you are using the conjugate gradient (CG) as suggested in that paper.&#xD;&#xA;In each iteration of your CG iteration, just take the current solution vector $\mathbf{x}$, and do&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\mathbf{x}' &amp;= (\mathbf{I}-\mathbf{\hat{u}}\mathbf{\hat{u}}^T)\mathbf{x}\\&#xD;&#xA;&amp;= \mathbf{x} - (\mathbf{\hat{u}} \cdot \mathbf{x} )\mathbf{\hat{u}}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $\mathbf{\hat{u}}$ is the normalized null space of gradient operator:&#xD;&#xA;$\mathbf{u} = (1,1,\dots,1)$, $\mathbf{\hat{u}}=\frac{\mathbf{u}}{\lVert \mathbf{u} \rVert}$.&#xD;&#xA;&#xD;&#xA;Otherwise if you do want to simulate air (free boundary or Dirichlet BC), you will need to distinguish a wall and an air cell (i.e. having a boolean `hasLiquid` is not enough), and apply correct discretization for them (see below).&#xD;&#xA;&#xD;&#xA;As a final note, your diagonal entries are negative. You may want to flip the signs so that the CG method works.&#xD;&#xA;&#xD;&#xA;------------&#xD;&#xA;&#xD;&#xA;Below I would like to show more details.&#xD;&#xA;Consider the pressure projection process. Denote the velocity before the pressure projection as $\mathbf{v}^*$. It could be divergent, so we compute pressure to correct it and get the divergence free velocity $\mathbf{v}^{n+1}$. That is,&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\mathbf{v}^{n+1} &amp;= \mathbf{v}^* - \frac{\Delta t}{\rho} \nabla P&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Take divergence of it, and since $\mathbf{v}^{n+1}$ is divergence free,&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\nabla \cdot \nabla P &amp;= \nabla \cdot \mathbf{v}^*&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Suppose that there is no pressure Dirichlet BC presesnt and we have one solution $P_0$, then $P_0+c$ for any constant $c$ is also a solution because $\nabla \cdot \nabla (P_0+c) = \nabla \cdot \nabla P_0 = \nabla \cdot \mathbf{v}^*$.&#xD;&#xA;$c$ is the null space we want to project out.&#xD;&#xA;&#xD;&#xA;To handle the Dirichlet BC, lets consider the 1D case as an example. Assume you are using staggered grid, where pressures $p_i$ are located at grid centers and velocities $v_{i+1/2}$ are located at the faces between nodes $i$ and $i+1$. Then the general discretization for one cell is&#xD;&#xA;$$&#xD;&#xA;\frac{p_{i+1}-p_i-(p_i-p_{i-1})}{\Delta x^2} = \text{rhs}&#xD;&#xA;$$&#xD;&#xA;Suppose that $p_{i+1}$ is an air cell, that is, its pressure has been specified,&#xD;&#xA;then the $p_{i+1}$ term is moved to the right hand side and disappears from the matrix. Note that the count of diagonal term $p_i$ is still two. That is why I said your 2x2 example did not contain a Dirichlet BC.&#xD;&#xA;&#xD;&#xA;With either Dirichlet or Neumann BC the matrix is always symmetric positive definite. That is why the authors said&#xD;&#xA;&#xD;&#xA;    Static object and empty cells don’t disrupt this structure.&#xD;&#xA;    In that case pressure and velocity terms can disappear from both sides&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23282" PostHistoryTypeId="2" PostId="8619" RevisionGUID="a2f675ca-e95e-4172-a6fd-7d1d8104f563" CreationDate="2019-02-21T04:23:46.520" UserId="120" Text="The rigid body simulation is very similar to the point mass case except for&#xD;&#xA;that we have to handle rotational motion (orientation and angular momentum).&#xD;&#xA;&#xD;&#xA;In addition to common particle attributes such as mass, position, and linear velocity, we will need to store initial momentum inertia $\mathbf{\hat{I}}$,&#xD;&#xA;current angular momentum $\mathbf{L}^n$, and current orientation $\mathbf{R}^n$.&#xD;&#xA;If you are using a data driven particle system, this step is as easy as declaring a few new attributes.&#xD;&#xA;&#xD;&#xA;Contract to the mass, the momentum inertia at current time step $\mathbf{I}^n$ depends on the current orientation $\mathbf{R}^n$: $\mathbf{I}^n=\mathbf{R}^n \mathbf{\hat{I}} (\mathbf{R}^n)^T$.&#xD;&#xA;&#xD;&#xA;The kinetic of a rigid body is analogous to the linear motion:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\dot{\mathbf{R}} &amp;= \omega^* \mathbf{R} \\&#xD;&#xA;\frac{\mathbf{R}^{n+1} - \mathbf{R}^n}{\Delta t} &amp;= (\omega^{n*}) \mathbf{R}^n \\&#xD;&#xA;\omega^n &amp;= (\mathbf{I}^n)^{-1} \mathbf{L}^n&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $\omega$ is the angular velocity and $\omega^*$ is the &quot;cross product&quot; matrix.&#xD;&#xA;&#xD;&#xA;For dynamics, we also have a similar version of Newton's &quot;f=ma&quot;:&#xD;&#xA;$$&#xD;&#xA;\frac{\mathbf{L}^{n+1} - \mathbf{L}^n}{\Delta t} = \tau^n&#xD;&#xA;$$&#xD;&#xA;where $\tau$ is the torque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because there will be interactions between rigid spheres, you will also need to implement the collision detection for spheres.&#xD;&#xA;&#xD;&#xA;Now we have known the kinematics and dynamics of rigids. The only thing left is how to solve (integrate) above equations. The naive forward Euler may not give stable result. A good introduction of this topic can be found at [Barraf SIGGRAPH course](http://www.cs.cmu.edu/~baraff/sigcourse/index.html), and here is an another more [recent SIGGRAPH course](https://www.cs.ucr.edu/~shinar/papers/2018_introduction_to_pba.pdf)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23283" PostHistoryTypeId="5" PostId="8619" RevisionGUID="97042ad4-01be-42b8-9db2-f513a23f4c2a" CreationDate="2019-02-21T05:13:09.703" UserId="120" Comment="added 2 characters in body" Text="The rigid body simulation is very similar to the point mass case except for&#xD;&#xA;that we have to handle rotational motion (orientation and angular momentum).&#xD;&#xA;&#xD;&#xA;In addition to common particle attributes such as mass, position, and linear velocity, we will need to store initial moment of inertia $\mathbf{\hat{I}}$,&#xD;&#xA;current angular momentum $\mathbf{L}^n$, and current orientation $\mathbf{R}^n$.&#xD;&#xA;If you are using a data driven particle system, this step is as easy as declaring a few new attributes.&#xD;&#xA;&#xD;&#xA;Contract to the mass, the moment of inertia at current time step $\mathbf{I}^n$ depends on the current orientation $\mathbf{R}^n$: $\mathbf{I}^n=\mathbf{R}^n \mathbf{\hat{I}} (\mathbf{R}^n)^T$.&#xD;&#xA;&#xD;&#xA;The kinetic of a rigid body is analogous to the linear motion:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\dot{\mathbf{R}} &amp;= \omega^* \mathbf{R} \\&#xD;&#xA;\frac{\mathbf{R}^{n+1} - \mathbf{R}^n}{\Delta t} &amp;= (\omega^{n*}) \mathbf{R}^n \\&#xD;&#xA;\omega^n &amp;= (\mathbf{I}^n)^{-1} \mathbf{L}^n&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $\omega$ is the angular velocity and $\omega^*$ is the &quot;cross product&quot; matrix.&#xD;&#xA;&#xD;&#xA;For dynamics, we also have a similar version of Newton's &quot;f=ma&quot;:&#xD;&#xA;$$&#xD;&#xA;\frac{\mathbf{L}^{n+1} - \mathbf{L}^n}{\Delta t} = \tau^n&#xD;&#xA;$$&#xD;&#xA;where $\tau$ is the torque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because there will be interactions between rigid spheres, you will also need to implement the collision detection for spheres.&#xD;&#xA;&#xD;&#xA;Now we have known the kinematics and dynamics of rigids. The only thing left is how to solve (integrate) above equations. The naive forward Euler may not give stable result. A good introduction of this topic can be found at [Barraf SIGGRAPH course](http://www.cs.cmu.edu/~baraff/sigcourse/index.html), and here is an another more [recent SIGGRAPH course](https://www.cs.ucr.edu/~shinar/papers/2018_introduction_to_pba.pdf)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23289" PostHistoryTypeId="2" PostId="8621" RevisionGUID="c4811ffa-6ce8-43b1-840c-beac5aff9249" CreationDate="2019-02-21T12:08:12.017" UserId="7023" Text="I'm just getting started trying to understand noise generation algorithms. What I'm trying to achieve is to get a 2D (or 3D) grid of random directional vectors (again, 2D or 3D) according to a noise distribution like Perlin, ie. not just a grid of totally randomly generated vectors (which would be easy to do).&#xD;&#xA;&#xD;&#xA;Before starting to figure this out, I had assumed that 1D noise functions would be those that produce a series of float values (ranging from -1 to 1, for example), and that 2D noise functions would produce float2 values, 3D noise would produce float3 values, and so on.&#xD;&#xA;&#xD;&#xA;However, searching for so-called 2D noise functions, it seems that they are used to produce a 2D grid (ie. texture) of single float values. However, what I'm looking for is a 2D grid of 2D (float2 / vector2) values, or a 3D grid of 3D (float3 / vector3) values.&#xD;&#xA;&#xD;&#xA;From my (still pretty limited) understanding of a gradient-based noise like Perlin, I feel like I could probably hack something together from an existing Perlin function - doing a bi-linear/tri-linear interpolation of the surrounding gradient vectors which are ordinarily used for the subsequent dot product in Perlin noise. But I have no idea if that's the correct approach.&#xD;&#xA;&#xD;&#xA;Are there existing libraries/methods for something like this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23290" PostHistoryTypeId="1" PostId="8621" RevisionGUID="c4811ffa-6ce8-43b1-840c-beac5aff9249" CreationDate="2019-02-21T12:08:12.017" UserId="7023" Text="How to create 2D (directional) noise?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23291" PostHistoryTypeId="3" PostId="8621" RevisionGUID="c4811ffa-6ce8-43b1-840c-beac5aff9249" CreationDate="2019-02-21T12:08:12.017" UserId="7023" Text="|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23294" PostHistoryTypeId="2" PostId="8622" RevisionGUID="7675fe60-194d-46eb-8897-d1ef0591b5c4" CreationDate="2019-02-21T13:02:58.010" UserId="7724" Text="Why don't you just use Perlin noise twice on the same grid, or volume? Each with slightly different parameters (a phase shift, or different pseudo-random vectors). In this case both component of your float2 are smoothly defined by a Perlin Noise field. So each float2 $v$ is defined as $v = \{P(u,v), P(u+0.5, v+0.5)\},$ where $P(u,v)$ is the Perlin noise function. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23295" PostHistoryTypeId="5" PostId="8622" RevisionGUID="87caf740-f3ba-4c55-8e1a-f6127168aa7c" CreationDate="2019-02-21T13:06:32.227" UserId="7724" Comment="added 112 characters in body" Text="Why don't you just use Perlin noise twice on the same grid, or volume? Each with slightly different parameters (a phase shift, or different pseudo-random vectors). In this case both component of your float2 are smoothly defined by a Perlin Noise field. A float2 $v$ could be defined as $v = \{P(u,v), P(u+0.5, v+0.5)\},$ where $P(u,v)$ is the Perlin noise function. However, this will make the $x$ and $y$ component of $v$ very close depending on the scaling of the grid values." ContentLicense="CC BY-SA 4.0" />
  <row Id="23296" PostHistoryTypeId="2" PostId="8623" RevisionGUID="9c2c7463-5c38-4f5e-925f-e3fc4eb0053e" CreationDate="2019-02-21T13:37:08.107" UserId="10096" Text="You can use the gradient of the noise/hash which for a function $f:\mathbb{R}^n\rightarrow\mathbb{R}$ would be $n$ dimensional (depending on the application this may not work for you). Another possibility, as Reynolds mentioned is to generate the noise by calling the function multiple times." ContentLicense="CC BY-SA 4.0" />
  <row Id="23297" PostHistoryTypeId="2" PostId="8624" RevisionGUID="620c5615-fc99-4f9a-809d-1269a3e6ed89" CreationDate="2019-02-21T13:38:49.560" UserId="10212" Text="Why do animated CG characters always feel fake?&#xD;&#xA;&#xD;&#xA;Usually if a CG character is an animal (or humanoid creature), they tend too look kinda off. Their movement tends to look oddly smooth or lightweight, even if aided with motion capture. Compare to real human or animal movement which is jagged, and has slight irregularity or weight. It doesn't matter whether the texture looks photorealistic, the movement of CG characters always feels off.&#xD;&#xA;&#xD;&#xA;I'm guessing it's because the animation curves for the final images are smoothed out or simplified, like smoothing a bezier curve or something. Is that the case? Is absolute, true-to-life movement possible for CG characters?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23298" PostHistoryTypeId="1" PostId="8624" RevisionGUID="620c5615-fc99-4f9a-809d-1269a3e6ed89" CreationDate="2019-02-21T13:38:49.560" UserId="10212" Text="Why do animated CG characters always feel fake?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23299" PostHistoryTypeId="3" PostId="8624" RevisionGUID="620c5615-fc99-4f9a-809d-1269a3e6ed89" CreationDate="2019-02-21T13:38:49.560" UserId="10212" Text="|3d|animation|cg|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23300" PostHistoryTypeId="2" PostId="8625" RevisionGUID="3ac1bd7c-de6e-4327-8184-875a62bbd217" CreationDate="2019-02-22T02:22:54.087" UserId="120" Text="I guess your question is how to compute the inertia tensor automatically. A parametric equation may not be always possible, but we could write a program to avoid hand calculations as much as possible.&#xD;&#xA;&#xD;&#xA;The inertia tensor $\mathbf{I}$ is defined as an integral over the object domain $\Omega$ (see [Inertia tensor](https://en.wikipedia.org/wiki/Moment_of_inertia#Inertia_tensor)):&#xD;&#xA;$$&#xD;&#xA;\newcommand{\V}[1]{\mathbf{#1}}&#xD;&#xA;\begin{align}&#xD;&#xA;\V{I} &amp;= \int_\Omega \rho (\V{r}\cdot\V{r} \delta - \V{r}\V{r}^T)\,dV&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $\V{r}$ is the position relative to the center of mass (COM),$\rho$ is the density, and $\delta$ is the identity matrix.&#xD;&#xA;&#xD;&#xA;Note that $\text{tr}(\V{r}\V{r}^T) = \V{r}\cdot \V{r}$, the above definition  can be rearranged as&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\V{T} &amp;= \V{r}\V{r}^T \\&#xD;&#xA;\V{I} &amp;= \int_\Omega \rho (\text{tr} \V{T} \delta - \V{T})\,dV&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;## Analytic object&#xD;&#xA;For analytic objects you can substitute their equations into the integral and do symbolic integration. This step can be automated with any symbolic computing software.&#xD;&#xA;&#xD;&#xA;## Object in tetrahedral mesh&#xD;&#xA;We assume the object is simple and has a closed boundary.&#xD;&#xA;An analytic solution is not possible in this case because we do not have an explicit equation for the object. But we could compute the inertia tensor numerically.&#xD;&#xA;The only integral we have to compute is&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\V{C} &amp;=&#xD;&#xA;\int_\Omega \rho \V{r}\V{r}^T\,dV&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;To compute this integral, [this paper](http://number-none.com/blow/inertia/) could be helpful.&#xD;&#xA;The general idea is to compute $\V{C}_t$ for each tetrahedron $t$, and sum $\V{C}_t$ to get $\V{C}$.&#xD;&#xA;We first compute the integral for a canonical tetrahedron $t0$ whose vertices are&#xD;&#xA;$(0,0,0)$, $(1,0,0)$, $(0,1,0)$, and $(0,0,1)$.&#xD;&#xA;&#xD;&#xA;In maple, this canonical integral $\V{C}_{t0}$ is (assume $\rho$ constant)&#xD;&#xA;```&#xD;&#xA;r:=&lt;x,y,z&gt;; &#xD;&#xA;                                                    [x]&#xD;&#xA;                                                    [ ]&#xD;&#xA;                                               r := [y]&#xD;&#xA;                                                    [ ]&#xD;&#xA;                                                    [z]&#xD;&#xA;&#xD;&#xA;with(LinearAlgebra):                                &#xD;&#xA;rrt:=r.Transpose(r);&#xD;&#xA;                                             [ 2               ]&#xD;&#xA;                                             [x      x y    x z]&#xD;&#xA;                                             [                 ]&#xD;&#xA;                                      rrt := [        2        ]&#xD;&#xA;                                             [x y    y      y z]&#xD;&#xA;                                             [                 ]&#xD;&#xA;                                             [               2 ]&#xD;&#xA;                                             [x z    y z    z  ]&#xD;&#xA;&#xD;&#xA;seq(seq(int(int(int(rrt[i,j],x=0..1-y-z),y=0..1-z),z=0..1),i=1..3),j=1..3);&#xD;&#xA;                      1/60, 1/120, 1/120, 1/120, 1/60, 1/120, 1/120, 1/120, 1/60&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then the integral $\V{C}_t$ can be computed by a change of variable.&#xD;&#xA;Assume the coordinates of a world space tetrahedron can be represented as $\V{r}=\V{F}\V{r}_0 + \V{x}$, where $\V{F}$ and $\V{x}$ are constant.&#xD;&#xA;We have&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\V{C}_t &amp;= \rho \int_{\Omega_t} \V{r}\V{r}^T\,dV \\&#xD;&#xA;&amp;= \rho \int_{\Omega_{t0}} (\V{F}\V{r}_0 + \V{x})(\V{F}\V{r}_0+\V{x})^T \det \V{F} \,dV_0 \\&#xD;&#xA;&amp;= \rho \int_{\Omega_{t0}} (\V{F}\V{r}_0\V{r}_0^T\V{F}^T + \V{x}\V{x}^T + \V{F}\V{r}_0\V{x}^T + \V{x}\V{r}_0^T\V{F}^T) \det \V{F} \,dV_0 \\&#xD;&#xA;&amp;= \det(\V{F}) \V{F}\V{C}_{t0}\V{F}^T + \det(\V{F}) m \V{x}\V{x}^T + \det(\V{F}) m \V{\bar{r}}\V{x}^T + \det(\V{F}) m \V{x}\V{\bar{r}}^T&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $\V{\bar{r}}$ is the COM and $m$ is the mass.&#xD;&#xA;&#xD;&#xA;##Objects in other form##&#xD;&#xA;I did not use Inventor before but I suspect the part produced by it may have other formats, such as Bezier surface. For now I would suggest tetrahedralize the object and apply the above method.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23304" PostHistoryTypeId="2" PostId="8627" RevisionGUID="4ba84869-d248-48c4-ad9f-adb0e7a05c6c" CreationDate="2019-02-22T12:51:59.463" UserId="10191" Text="My question is not about the code, but it's about the approach used by the author Peter Shirley (and apparently common practice in ray tracers) of handling Instances. To understand the question it's necessary to be familiar with the book, because posting the code for every class involved is not feasible.&#xD;&#xA;Something I don't understand is how rays behave. &#xD;&#xA;&#xD;&#xA;Let's consider the &lt;i&gt;traslation&lt;/i&gt;. The idea is to offset the origin, and check if the new ray - which is now shot from the new origin with the same direction of the original ray - hits the object. If so, we shift the hitting point by an equal and opposite offset.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Two questions:&#xD;&#xA;&#xD;&#xA;1) Why is it not sufficient to shoot rays from the &quot;standard&quot; origin, and offset the hitting point without actually shifting the origin first? Example: the ray is shot, if it hits the object in point (x,y) I move the hitting point by 2 (x+2, y+2) and store it.&#xD;&#xA;&#xD;&#xA;2) The hit function of the class `translate` is only called when the original ray hits the object? Because in that case, the translation would not result in the whole object, since it would only store those points that are first hit by the original ray, and for which the new ray hits the object again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lPSZh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23305" PostHistoryTypeId="1" PostId="8627" RevisionGUID="4ba84869-d248-48c4-ad9f-adb0e7a05c6c" CreationDate="2019-02-22T12:51:59.463" UserId="10191" Text="Ray tracing the next week: understanding Instances" ContentLicense="CC BY-SA 4.0" />
  <row Id="23306" PostHistoryTypeId="3" PostId="8627" RevisionGUID="4ba84869-d248-48c4-ad9f-adb0e7a05c6c" CreationDate="2019-02-22T12:51:59.463" UserId="10191" Text="|raytracing|shader|transformations|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23307" PostHistoryTypeId="5" PostId="8444" RevisionGUID="5d34e9ba-6fe0-4f11-b664-6e1aff4fd8b8" CreationDate="2019-02-22T13:13:28.360" UserId="6046" Comment="added 196 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS &lt;strike&gt;however now I'm getting more fireflies and I think I read that MIS reduces fireflies?&lt;/strike&gt; Updated the images. **It seems fireflies are less in MIS however, the reflection seems harder to converge.** &#xD;&#xA;&#xD;&#xA;Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter. Still don't know if MIS is working as intended.&#xD;&#xA;&#xD;&#xA;**EDIT3**:- Added a release as well. So if anybody wants, they can try changing the code in &quot;*.cl&quot; file and run the program to see the results. (You must have an OpenCL 1.1 supported GPU or CPU)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/WeiZN.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/PPnyh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23308" PostHistoryTypeId="2" PostId="8628" RevisionGUID="a6917a62-c2f2-4dd8-a88d-31ee8dfd6f2d" CreationDate="2019-02-22T14:49:45.697" UserId="137" Text="Because animators haven't fully bridged the uncanny valley. &#xD;&#xA;&#xD;&#xA;There are a ton of little details you notice subconsciously that hasn't been fully mapped out.&#xD;&#xA;&#xD;&#xA;Things like how muscles and tendons move under the surface, how clothing and hair behaves as you move around. Even how you adjust your stance as you move your arms around, prepare to move, etc.&#xD;&#xA;&#xD;&#xA;Even with mocap it is difficult to capture and recreate all that. It is also not trivial to capture the movement of the fingers. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23309" PostHistoryTypeId="2" PostId="8629" RevisionGUID="652420c6-5e16-49f6-830a-ced8db01ecf8" CreationDate="2019-02-22T15:51:29.927" UserId="10096" Text="There are two ways to 'translate' your object. The first is by moving each point of your object by the desired translation. The second is by translating the origin of your coordinate system. In this case it's the latter. Basically it turns out to be the same, whether you translate your object by a vector $\vec{t}$ or whether you translate your origin by $-\vec{t}$.&#xD;&#xA;&#xD;&#xA;For 2) note that you only care about the intersected points (since that is what you use to compute the pixel color), so you compute the offset only when you need it. So yes, you do translate the origin of the ray at each intersect, it's the same as translating the object though (at each ray intersect), since $\vec{p}+\vec{t} - \vec{o} = \vec{p} - (\vec{o}-\vec{t})$." ContentLicense="CC BY-SA 4.0" />
  <row Id="23313" PostHistoryTypeId="5" PostId="8624" RevisionGUID="753f8513-506e-497d-b558-1acb81acc590" CreationDate="2019-02-23T08:45:17.790" UserId="10212" Comment="added 6 characters in body" Text="Why do animated CG characters always feel fake?&#xD;&#xA;&#xD;&#xA;Usually if a CG character is an animal (or humanoid creature) moves, they tend too look kinda off. Their movement tends to look oddly smooth or lightweight, even if aided with motion capture. Compare to real human or animal movement which is jagged, and has slight irregularity or weight. It doesn't matter whether the texture looks photorealistic, the movement of CG characters always feels off.&#xD;&#xA;&#xD;&#xA;I'm guessing it's because the animation curves for the final images are smoothed out or simplified, like smoothing a bezier curve or something. Is that the case? Is absolute, true-to-life movement possible for CG characters?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23314" PostHistoryTypeId="2" PostId="8630" RevisionGUID="d27b795d-fc2b-4feb-a4d5-d751ca498b32" CreationDate="2019-02-24T08:55:40.133" UserId="6046" Text="So I read about tonemapping and Gamma Correction recently and have implemented it in my path tracer. &#xD;&#xA;&#xD;&#xA;For the time being I'm using Reinhard tonemapping operator as described in his paper&#xD;&#xA;&#xD;&#xA;$L_d = L_w * (1+L_w/L^2_{white})/(1+L_w)$&#xD;&#xA;&#xD;&#xA;and applying it on the luminance channel and scaling it effectively so the colors wouldn't change. I'm applying a Gamma correction of 2.2. Here is the snippet.&#xD;&#xA;&#xD;&#xA;    float lum_world = getYluminance(hdr_col); //Find the Y channel of XYZ from RGB&#xD;&#xA;    float lum_display = lum_world * (1 + lum_world/(lum_white * lum_white) ) / (1+lum_world);&#xD;&#xA;    float4 ldr_color = lum_display *(hdr_col/lum_world); &#xD;&#xA;    ldr_color = pow(ldr_color, (float4) (1/2.2) );  // Gamma correction&#xD;&#xA;So apparently if I leave out the last step of Gamma Correction I feel I get more aesthetically pleasing images. If anybody can confirm if it's working as intended or there's something wrong. Note that I'm using OpenGL to display Images but nowhere am I using `GL_FRAMEBUFFER_SRGB` so there's no implicit gamma correction being done.&#xD;&#xA;&#xD;&#xA;This is gamma corrected (Light intensities are set to 8.0f)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is with tonemapping but without gamma correction. Light intensities were scaled to 18.0f. At 8.0f the image was very dark.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;For comparison here is the gamma-corrected image at 18.0f. It's just the whole image got whiter/brighter.&#xD;&#xA;&#xD;&#xA;We can see that Gamma corrected one looks washed out, shadows are much much lighter and the back wall looks outright bad. I don't know what to call it but the GI in the lower image looks better.&#xD;&#xA;  [1]: https://i.stack.imgur.com/8y7wH.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/06S7D.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23315" PostHistoryTypeId="1" PostId="8630" RevisionGUID="d27b795d-fc2b-4feb-a4d5-d751ca498b32" CreationDate="2019-02-24T08:55:40.133" UserId="6046" Text="Progressive Path tracing - HDR, Tone mapping and Gamma correction" ContentLicense="CC BY-SA 4.0" />
  <row Id="23316" PostHistoryTypeId="3" PostId="8630" RevisionGUID="d27b795d-fc2b-4feb-a4d5-d751ca498b32" CreationDate="2019-02-24T08:55:40.133" UserId="6046" Text="|pathtracing|color|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23317" PostHistoryTypeId="4" PostId="8630" RevisionGUID="8e9311ee-3db6-4061-ad67-e841b7a04ea3" CreationDate="2019-02-24T09:01:03.220" UserId="6046" Comment="edited title" Text="Path tracing - Better images without Gamma correction?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23318" PostHistoryTypeId="5" PostId="8630" RevisionGUID="b497cea1-081d-461f-b2de-50df7ea1221f" CreationDate="2019-02-24T09:14:42.633" UserId="6046" Comment="added 91 characters in body" Text="So I read about tonemapping and Gamma Correction recently and have implemented it in my path tracer. &#xD;&#xA;&#xD;&#xA;For the time being I'm using Reinhard tonemapping operator as described in his paper&#xD;&#xA;&#xD;&#xA;$L_d = L_w * (1+L_w/L^2_{white})/(1+L_w)$&#xD;&#xA;&#xD;&#xA;and applying it on the luminance channel and scaling it effectively so the colors wouldn't change. I'm applying a Gamma correction of 2.2. Here is the snippet.&#xD;&#xA;&#xD;&#xA;    float lum_world = getYluminance(hdr_col); //Find the Y channel of XYZ from RGB&#xD;&#xA;    float lum_display = lum_world * (1 + lum_world/(lum_white * lum_white) ) / (1+lum_world);&#xD;&#xA;    float4 ldr_color = lum_display *(hdr_col/lum_world); &#xD;&#xA;    ldr_color = pow(ldr_color, (float4) (1/2.2) );  // Gamma correction&#xD;&#xA;So apparently if I leave out the last step of Gamma Correction I feel I get more aesthetically pleasing images. If anybody can confirm if it's working as intended or there's something wrong. Note that I'm using OpenGL to display Images but nowhere am I using `GL_FRAMEBUFFER_SRGB` so there's no implicit gamma correction being done.&#xD;&#xA;&#xD;&#xA;This is gamma corrected (Light intensities are set to 8.0f)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is with tonemapping but without gamma correction. Light intensities were scaled to 18.0f. At 8.0f the image was very dark.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;For comparison here is the gamma-corrected image at 18.0f. It's just the whole image got whiter/brighter.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;We can see that Gamma corrected one looks washed out, shadows are much much lighter and the back wall looks outright bad. I don't know what to call it but the GI in the un-corrected image looks better.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8y7wH.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/06S7D.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/KwWiK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23319" PostHistoryTypeId="5" PostId="8444" RevisionGUID="942b5224-8065-4ee5-bce8-9e6e3864f8bb" CreationDate="2019-02-24T15:49:03.400" UserId="6046" Comment="added 1328 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS &lt;strike&gt;however now I'm getting more fireflies and I think I read that MIS reduces fireflies?&lt;/strike&gt; Updated the images. **It seems fireflies are less in MIS however, the reflection seems harder to converge.** &#xD;&#xA;&#xD;&#xA;Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Link to code is &quot;[here][4]&quot;&#xD;&#xA;&#xD;&#xA;--Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter. Still don't know if MIS is working as intended.&#xD;&#xA;&#xD;&#xA;**EDIT3**:- Added a release as well. So if anybody wants, they can try changing the code in &quot;*.cl&quot; file and run the program to see the results. (You must have an OpenCL 1.1 supported GPU or CPU)&#xD;&#xA;&#xD;&#xA;**EDIT4**:- Here's an overview of what I'm doing now.&#xD;&#xA;&#xD;&#xA;First I choose a single light source out of multiple using simple heuristic scheme like the distance, intensity, area and the cosine falloff angles. I appropriately set the weights for the light like this&#xD;&#xA;&#xD;&#xA;$light\_pdf = weight/area$&#xD;&#xA;&#xD;&#xA;where weight is in range 0-1.&#xD;&#xA;&#xD;&#xA;Next I trace the ray to see if light source is visible. If it is I calculate the $light\_sample$ using the direct lighting equation (integral over Area).&#xD;&#xA;&#xD;&#xA;Then I calculate the BRDF PDF for this given ray. However I use Lafortune's algorithm for it. If a random number falls under the specular color I sample through the modfied Phong PDF else through Cosine.&#xD;&#xA;&#xD;&#xA;The weights are computed using power heuristic,&#xD;&#xA;$ weight = light\_pdf^2/(light\_pdf^2+brdf\_pdf^2)$&#xD;&#xA;&#xD;&#xA;The MIS estimator is then calculated as&#xD;&#xA;&#xD;&#xA;$light\_sample = light\_sample * weight/light\_pdf$&#xD;&#xA;&#xD;&#xA;After that I come to BRDF sampling. I again sample through either Phong/Cosine based on what I did earlier during light sample calculation. If the sampled ray doesn't hit any light source or not the **same** one. I set the $brdf\_sample$ to zero. If it hits, I set the $light\_pdf$ to same value as before. Calculate the weights like mentioned above and calculate brdf sample using the original equation (integral over solid angle).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [5]: https://i.stack.imgur.com/WeiZN.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/PPnyh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23320" PostHistoryTypeId="2" PostId="8631" RevisionGUID="490be0e1-0f11-448d-8130-79013acd5440" CreationDate="2019-02-24T17:59:53.187" UserId="10096" Text="Throughout my answer I'll sometimes refer to some results in https://sites.fas.harvard.edu/~cs278/papers/veach.pdf by using [MIS,section_number].&#xD;&#xA;&#xD;&#xA;You can skip the following derivation if you don't care about the mathematical explanation of why using MIS to combine estimators is valid.&#xD;&#xA;I'll have to start with what the purpose of MIS is. The general idea is that you want to estimate some integral $I=\int_{\Omega}{f(x)\,d\mu(x)}$ through Monte Carlo, and you have various sampling pdfs (in our case a pdf for sampling points on the light, and a pdf for sampling directions from the brdf). Additionally you want to sample using more than one technique and then combine the contributions optimally (in some sense). For simplicity I will restrict myself to the case where you have only two pdfs: $p_L(x), p_B(x)$ with respect to the same measure $\mu(x)$.&#xD;&#xA;&#xD;&#xA;Assume that you also have the weighting functions $w_1(x), w_2(x) : \Omega \rightarrow [0,1], w_1(x) + w_2(x) = 1$ and also $n$ independently and identically distributed (i.i.d.) samples $x_{p_L,i}: i=1,...,n$ according to $p_L$, and $m$ i.i.d. samples $x_{p_B,j} : j=1,...,m$ according to $p_B$, we can use Monte Carlo with MIS to estimate the integral $I$:&#xD;&#xA;$$ I = \int_{\Omega}{f(x)\,d\mu(x)} = \int_{\Omega}{f(x)(w_1(x)+w_2(x))\,d\mu(x)}  \\&#xD;&#xA;= \int_{\Omega}{\frac{w_1(x)f(x)}{p_L(x)}p_L(x)\,d\mu(x)} + \int_{\Omega}{\frac{w_2(x)f(x)}{p_B(x)}p_B(x)\,d\mu(x)} \\&#xD;&#xA;= E\left[\frac{w_1(X_{p_L})f(X_{p_L})}{p_L(X_{p_L})}\right] + E\left[\frac{w_2(X_{p_B})f(X_{p_B})}&#xD;&#xA;{p_B(X_{p_B})}\right] \\&#xD;&#xA;= \frac{1}{n}\sum_{i=1}^{n}{E\left[\frac{w_1(X_{p_L,i})f(X_{p_L,i})}{p_L(X_{p_L,i})}\right]} + \frac{1}{m}\sum_{j=1}^{m}{E\left[\frac{w_2(X_{p_B,j})f(X_{p_B,j})}&#xD;&#xA;{p_B(X_{p_B,j})}\right]} \\&#xD;&#xA;= E\left[\frac{1}{n}\sum_{i=1}^{n}{\frac{w_1(X_{p_L,i})f(X_{p_L,i})}{p_L(X_{p_L,i})}}\right] + E\left[\frac{1}{m}\sum_{j=1}^{m}{\frac{w_2(X_{p_B,j})f(X_{p_B,j})}&#xD;&#xA;{p_B(X_{p_B,j})}}\right] \\&#xD;&#xA;\approx \frac{1}{n}\sum_{i=1}^{n}{\frac{w_1(x_{p_L,i})f(x_{p_L,i})}{p_L(x_{p_L,i})}} &#xD;&#xA;+ \frac{1}{m}\sum_{j=1}^{m}{\frac{w_2(x_{p_B,j})f(x_{p_B,j})}&#xD;&#xA;{p_B(x_{p_B,j})}}&#xD;&#xA;$$&#xD;&#xA;Where the second equality holds because $w_1(x)+w_2(x)=1$, the fourth follows from the definition of expected value, the fifth holds since $X_{p_L,i}$ are independently and identically distributed (i.i.d.) according to $p_L$ and similarly $X_{p_B,i}$ are i.i.d. according to $p_B$. The sixth holds because of the properties of the expectation (which follows from the fact that integration is a linear operator). The last approximate equality follows from the strong law of large numbers (the average of the samples converges almost surely to the expected value with the number of samples going to infinity).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Having this result the first thing to note is that both pdfs are defined with respect to the same measure $\mu(x)$. However I believe that in your code and overview you pdf for sampling the light $p_L$ is defined with respect to the area measure, whereas the pdf for sampling the brdf $p_B$ is defined with respect to the solid angle measure. The relationship between those being $d\sigma(x\rightarrow y) = \frac{\cos\theta_y}{||x-y||^2}dA(y)$, where $x \in \mathbb{R}^3$ is the current point for which you are computing the illumination (that is your intersection point), and $y \in \mathbb{R}^3$ is a point on the surface of some light source. Additionally $(x\rightarrow y) = \frac{y-x}{||y-x||}$ is simply the unit direction vector from $x$ to $y$, $\cos\theta_y = n_y \cdot (y\rightarrow x)$ is the cosine of the angle between the normal $n_y$ (also unit length) of the light surface at $y$ and $-(x\rightarrow y)$. More specifically what you have produced as light pdf is really the probability of picking the light $weights[i]/sum$ multiplied by the probability of picking uniformly a point on the light source that you have chosen $1/area$. The solid angle to area (or vice versa) conversion seems to be missing in your code and your overview, that is your pdf is with respect to the area measure, and you combine it with a pdf (the brdf's) that is with respect to the solid angle measure, which is clearly wrong as you can see from my derivation above. To get the  brdf pdf with respect to the area measure and not the solid angle measure you can use: $p_{\omega}(\omega)\,d\sigma(\omega) = p_A(y)\,dA(y)$ then using the relationship between the measures $p_A(y) = p_{\omega}(\omega)\,d\sigma(\omega) / dA(y) = p_{\omega}(\omega) \frac{\cos\theta_y}{||x-y||^2}$. You can refer to [MIS, 2.3] equation (9). For a formal derivation of the relationship between the two measures you can refer to http://www.dgp.toronto.edu/~lessig/dissertation/files/area_formulation.pdf , another possible derivation of the same fact can be done through the divergence theorem.&#xD;&#xA;&#xD;&#xA;Now as far as the practical part goes - you need to know when to apply the mis weighting. There are a few cases which occur. Initially for the very first ray, you should not use MIS since you shouldn't sample any light directly. Additionally if the last bounce was fully deterministic (ideal reflection/refraction) then you also should not use MIS, since sampling the light is useless in that case. Finally if you hit a light through sampling the bsdf, you should use MIS to add this contribution, and convert the bsdf pdf wrt the area measure, and then combine it with the probability of sampling this point on this light by using the light pdf and use the area formulation estimator of the rendering equation. When you sample a light, you should also use MIS, once again computing the area formulation estimator. Finally if you have point lights, those can be sampled only through NEE, so you should not use MIS.&#xD;&#xA;&#xD;&#xA;Note that there may be more mistakes that you have. Also I didn't understand anything of your explanation past &quot;After that I come to BRDF sampling.&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="23321" PostHistoryTypeId="5" PostId="8444" RevisionGUID="5c45b72a-7c44-4c8b-a3ca-1466e60e91ae" CreationDate="2019-02-24T19:41:34.280" UserId="6046" Comment="added 278 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS &lt;strike&gt;however now I'm getting more fireflies and I think I read that MIS reduces fireflies?&lt;/strike&gt; Updated the images. **It seems fireflies are less in MIS however, the reflection seems harder to converge.** &#xD;&#xA;&#xD;&#xA;Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Link to code is &quot;[here][6]&quot;&#xD;&#xA;&#xD;&#xA;--&lt;strike&gt;Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter. Still don't know if MIS is working as intended.&lt;/strike&gt; See answer.&#xD;&#xA;&#xD;&#xA;**EDIT3**:- Added a release as well. So if anybody wants, they can try changing the code in &quot;*.cl&quot; file and run the program to see the results. (You must have an OpenCL 1.1 supported GPU or CPU)&#xD;&#xA;&#xD;&#xA;**EDIT4**:- Here's an overview of what I'm doing now.&#xD;&#xA;&#xD;&#xA;First I choose a single light source out of multiple using simple heuristic scheme like the distance, intensity, area and the cosine falloff angles. I appropriately set the weights for the light like this&#xD;&#xA;&#xD;&#xA;$light\_pdf = weight/area$&#xD;&#xA;&#xD;&#xA;where weight is in range 0-1.&#xD;&#xA;&#xD;&#xA;Next I trace the ray to see if light source is visible. If it is I calculate the $light\_sample$ using the direct lighting equation (integral over Area).&#xD;&#xA;&#xD;&#xA;Then I calculate the BRDF PDF for this given ray. However I use Lafortune's algorithm for it. If a random number falls under the specular color I sample through the modfied Phong PDF else through Cosine.&#xD;&#xA;&#xD;&#xA;The weights are computed using power heuristic,&#xD;&#xA;$ weight = light\_pdf^2/(light\_pdf^2+brdf\_pdf^2)$&#xD;&#xA;&#xD;&#xA;The MIS estimator is then calculated as&#xD;&#xA;&#xD;&#xA;$light\_sample = light\_sample * weight/light\_pdf$&#xD;&#xA;&#xD;&#xA;After that I come to BRDF sampling. I again sample through either Phong/Cosine based on what I did earlier during light sample calculation. If the sampled ray doesn't hit any light source or not the **same** one. I set the $brdf\_sample$ to zero. If it hits, I set the $light\_pdf$ to same value as before. Calculate the weights like mentioned above and calculate brdf sample using the original equation (integral over solid angle).&#xD;&#xA;&#xD;&#xA;**EDIT5**:- After lightxbulb suggestions, I think the problem has resolved.&#xD;&#xA;&#xD;&#xA;With MIS&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Without MIS&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://i.stack.imgur.com/WeiZN.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/PPnyh.png&#xD;&#xA;  [6]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [7]: https://i.stack.imgur.com/1ZWKG.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/jWrUa.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23322" PostHistoryTypeId="5" PostId="8444" RevisionGUID="bcb73ecc-456b-4f48-ab93-42861f5dce47" CreationDate="2019-02-24T19:47:31.477" UserId="6046" Comment="added 131 characters in body" Text="So I recently implemented Multiple Importance Sampling in my path tracer which was based on next event estimation.&#xD;&#xA;&#xD;&#xA;The problem is without MIS I get images like,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obtained by setting   &#xD;&#xA;`light_sample *=  1/light_pdf;  // Note no mis_weight`  &#xD;&#xA;and just returning this sample alone. No BRDF sampling.&#xD;&#xA;&#xD;&#xA;Where as with MIS as defined above I get darker images like,&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA; The reason is surely the `mis_weight` factor. From what I gathered over the internet my MIS code is ok but theoretically it doesn't seem right. For example suppose we performed Light Sampling first and obtained a `mis_weight`. After that when we tried BRDF sampling, the ray didn't intersect any light source resulting in `light_pdf = 0`. We neglected this estimate. Since we neglected this estimate isn't it wrong to weight our light sample by `mis_weight` when we didn't even use multiple estimators, plus how is the sum of weights equal to 1 when we didnt even estimate anything using the BRDF pdf?&#xD;&#xA;&#xD;&#xA;Imo, `mis_weight` factor in `light_sample` should only be used when BRDF sampling also results in a light ray that intersects the light source.&#xD;&#xA;&#xD;&#xA;Can anybody explain if these results are ok or there is something wrong with the code?&#xD;&#xA;&#xD;&#xA;&lt;strike&gt;**EDIT**:- There is another case which is a little confusing. I am currently using a heuristic (basically power/distance) to choose 1 light out of multiple lights. What if Light sampling and BRDF sampling choose different light sources. Is MIS still valid then? Since the PDF would change resulting the weights not being able to sum to 1 anymore&lt;/strike&gt;&#xD;&#xA;&#xD;&#xA;**EDIT2**:- So Stefan pointed out a mistake [here][3], that I was clamping radiance. And this solved that issue and changed the results I'm getting for MIS. I have double checked PBRT's implementation and it is similar to mine. I'm still getting darker images using MIS &lt;strike&gt;however now I'm getting more fireflies and I think I read that MIS reduces fireflies?&lt;/strike&gt; Updated the images. **It seems fireflies are less in MIS however, the reflection seems harder to converge.** &#xD;&#xA;&#xD;&#xA;Note the reflection is harder to converge. Both images are 1000 spp. Top is without MIS.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;I'm removing the snippet and adding a link to github for the whole kernel. The core functions are `evaluateDirectLighting`, `shading`, `sampleLights`. Link to code is &quot;[here][6]&quot;&#xD;&#xA;&#xD;&#xA;--&lt;strike&gt;Found a mistake. I was using the direct lighting equation when calculating the brdf sample. (multiplying by $\cos(\theta^{\prime})$ and dividing by $r^2$). Removed it since we initially sampled through BSDF which is integral over solid angle not area. The image got a little brighter. Still don't know if MIS is working as intended.&lt;/strike&gt; See answer.&#xD;&#xA;&#xD;&#xA;**EDIT3**:- Added a release as well. So if anybody wants, they can try changing the code in &quot;*.cl&quot; file and run the program to see the results. (You must have an OpenCL 1.1 supported GPU or CPU)&#xD;&#xA;&#xD;&#xA;**EDIT4**:- Here's an overview of what I'm doing now.&#xD;&#xA;&#xD;&#xA;First I choose a single light source out of multiple using simple heuristic scheme like the distance, intensity, area and the cosine falloff angles. I appropriately set the weights for the light like this&#xD;&#xA;&#xD;&#xA;$light\_pdf = weight/area$&#xD;&#xA;&#xD;&#xA;where weight is in range 0-1.&#xD;&#xA;&#xD;&#xA;Next I trace the ray to see if light source is visible. If it is I calculate the $light\_sample$ using the direct lighting equation (integral over Area).&#xD;&#xA;&#xD;&#xA;Then I calculate the BRDF PDF for this given ray. However I use Lafortune's algorithm for it. If a random number falls under the specular color I sample through the modfied Phong PDF else through Cosine.&#xD;&#xA;&#xD;&#xA;The weights are computed using power heuristic,&#xD;&#xA;$ weight = light\_pdf^2/(light\_pdf^2+brdf\_pdf^2)$&#xD;&#xA;&#xD;&#xA;The MIS estimator is then calculated as&#xD;&#xA;&#xD;&#xA;$light\_sample = light\_sample * weight/light\_pdf$&#xD;&#xA;&#xD;&#xA;After that I come to BRDF sampling. I again sample through either Phong/Cosine based on what I did earlier during light sample calculation. If the sampled ray doesn't hit any light source or not the **same** one. I set the $brdf\_sample$ to zero. If it hits, I set the $light\_pdf$ to same value as before. Calculate the weights like mentioned above and calculate brdf sample using the original equation (integral over solid angle).&#xD;&#xA;&#xD;&#xA;**EDIT5**:- After lightxbulb suggestions, I think the problem has resolved.&#xD;&#xA;&#xD;&#xA;Note the images might look a whole lot different but that's cause I implemented Tonemapping + Gamma Correction in the meantime :)&#xD;&#xA;With MIS 700spp&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Without MIS 700spp&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SL0B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QYyJw.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/8469/naive-path-tracer-produces-much-darker-images-than-explicit-light-sampling?noredirect=1&amp;lq=1&#xD;&#xA;  [4]: https://i.stack.imgur.com/WeiZN.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/PPnyh.png&#xD;&#xA;  [6]: https://github.com/gallickgunner/Yune/blob/master/progressive-PT.cl&#xD;&#xA;  [7]: https://i.stack.imgur.com/1ZWKG.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/jWrUa.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23323" PostHistoryTypeId="5" PostId="8624" RevisionGUID="66bdb23c-d803-4eeb-8aa6-66f459ba8e25" CreationDate="2019-02-25T04:15:58.097" UserId="10212" Comment="deleted 6 characters in body" Text="Why do animated CG characters always feel fake?&#xD;&#xA;&#xD;&#xA;Usually if a CG character is an animal (or humanoid creature), they tend too look kinda off. Their movement tends to look oddly smooth or lightweight, even if aided with motion capture. Compare to real human or animal movement which is jagged, and has slight irregularity or weight. It doesn't matter whether the texture looks photorealistic, the movement of CG characters always feels off.&#xD;&#xA;&#xD;&#xA;I'm guessing it's because the animation curves for the final images are smoothed out or simplified, like smoothing a bezier curve or something. Is that the case? Is absolute, true-to-life movement possible for CG characters?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23324" PostHistoryTypeId="2" PostId="8632" RevisionGUID="20908088-c0bd-4ef8-b358-3783aaf45bfb" CreationDate="2019-02-25T07:12:19.120" UserId="10227" Text="Utilize `simd` to synchronize your alignment:&#xD;&#xA;&#xD;&#xA;    import simd&#xD;&#xA;    &#xD;&#xA;    private struct BoundingBoxParameters {&#xD;&#xA;    &#xD;&#xA;        let topLeft: float2 = float2(0.0, 0.0)&#xD;&#xA;        let size: float2 = float2(0.0, 0.0)&#xD;&#xA;        let levelOfDetail: Float = 1.0&#xD;&#xA;&#xD;&#xA;        init(topLeft: float2,&#xD;&#xA;             size: float2,&#xD;&#xA;             levelOfDetail: Float) {&#xD;&#xA;            self.topLeft = topLeft&#xD;&#xA;            self.size = size &#xD;&#xA;            self.levelOfDetail = levelOfDetail&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="23325" PostHistoryTypeId="2" PostId="8633" RevisionGUID="c4d0025b-00d5-4e6b-b021-90bbc1e18073" CreationDate="2019-02-25T14:01:33.000" UserId="9864" Text="I would like to segment picture of cloths in order to remove the background. The pictures come from online retailers, they usually have an homogeneous white background. &#xD;&#xA;&#xD;&#xA;Using Canny edge detector works in most of the cases, but sometimes the cloths are nearly as white as the background making the edges hard to detect.&#xD;&#xA;&#xD;&#xA;I tried to play with the min and max parameters in opencv (python), but I can't recover the clean edge, either I do not get the surrounding of the cloths (holes in the reigion) or the the edge is noisy around the cloth.&#xD;&#xA;&#xD;&#xA;Here's one of the tricky example:&#xD;&#xA;&#xD;&#xA;[![Original cloth][1]][1]&#xD;&#xA;[![Canny getting the contour of the cloth but noisy][2]][2]&#xD;&#xA;[![Canny not getting enough contour of the cloth][3]][3]&#xD;&#xA;&#xD;&#xA;Simple growing region for background detection also doesn't work well enough.&#xD;&#xA;&#xD;&#xA;So how do you detect the contour of an object if it has nearly the same color as the background?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Obe5E.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1cm5M.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/TzYzJ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23326" PostHistoryTypeId="1" PostId="8633" RevisionGUID="c4d0025b-00d5-4e6b-b021-90bbc1e18073" CreationDate="2019-02-25T14:01:33.000" UserId="9864" Text="Which algorithm to segment white on white?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23327" PostHistoryTypeId="3" PostId="8633" RevisionGUID="c4d0025b-00d5-4e6b-b021-90bbc1e18073" CreationDate="2019-02-25T14:01:33.000" UserId="9864" Text="|edge-detection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23328" PostHistoryTypeId="4" PostId="8633" RevisionGUID="a9457098-b691-4f33-9914-84d44337b285" CreationDate="2019-02-25T14:07:41.887" UserId="9864" Comment="edited title" Text="Which method to use to segment white object on white background?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23329" PostHistoryTypeId="4" PostId="8633" RevisionGUID="527648a9-58e3-4f59-bf05-a7d32339924a" CreationDate="2019-02-25T14:35:46.433" UserId="9864" Comment="edited title" Text="Which method for detecting edges of white object on white background?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23330" PostHistoryTypeId="2" PostId="8634" RevisionGUID="81e29900-a25b-4aba-bd94-1a1e83e471cf" CreationDate="2019-02-25T20:16:53.660" UserId="10217" Text="It's quite difficult. There is so little contrast, even the JPEG compression artifacts have more contrast than the object on the background.&#xD;&#xA;&#xD;&#xA;You would require a highly specialized deblock filter to eliminate the compression artifacts first. With knowledge about the block size of the used compression algorithm and the number of coefficients used per block you may be able to predict some of the edges.&#xD;&#xA;&#xD;&#xA;For edges you could predict in the previous step, you may try to filter these from the detected edges.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;All around the shirt in the photo, there are over-swings due to an excessively  lossy compression. At the edge of each block, the over-swings form a hard edge which you also successfully detected.&#xD;&#xA;&#xD;&#xA;The block size is 8x8 pixels for JPEG (and hence also in this image), so every vertical or horizontal edge which falls directly onto position `16*n` or `16n+1` X or Y is most likely just a compression artifact and can be ignored.&#xD;&#xA;&#xD;&#xA;This approach can only work though if the image hasn't been re-sampled after compression, respectively hasn't been re-compressed multiple times with potentially different block sizes. At that point, isolating the compression artifacts becomes nearly impossible." ContentLicense="CC BY-SA 4.0" />
  <row Id="23331" PostHistoryTypeId="2" PostId="8635" RevisionGUID="0572f14b-d343-4d85-b431-ca0b57081f4a" CreationDate="2019-02-25T21:26:38.327" UserId="10129" Text="I've actually managed to find problem thanks to @PaulHK, thanks!&#xD;&#xA;I decided to pass which face I am currently working on and setting then coordinates manually per face. It is awful but it works rather good and since it is prefiltered and not done in runtime I found it good enough:&#xD;&#xA;&#xD;&#xA;    [branch] if (g_upVectorVal.z == 1.0f)&#xD;&#xA;	{&#xD;&#xA;		input.position.z = -1.0f;&#xD;&#xA;	}&#xD;&#xA;	[branch] if (g_upVectorVal.z == -1.0f)&#xD;&#xA;	{&#xD;&#xA;		input.position.z = 1.0f;&#xD;&#xA;	}&#xD;&#xA;	[branch] if (g_upVectorVal.x == 1.0f)&#xD;&#xA;	{&#xD;&#xA;		input.position.z = input.position.x;&#xD;&#xA;		input.position.x = -1.0f;&#xD;&#xA;	}&#xD;&#xA;	[branch] if (g_upVectorVal.x == -1.0f)&#xD;&#xA;	{&#xD;&#xA;		input.position.z = -input.position.x;&#xD;&#xA;		input.position.x = 1.0f;&#xD;&#xA;	}&#xD;&#xA;	[branch] if (g_upVectorVal.y == 1.0f)&#xD;&#xA;	{&#xD;&#xA;		input.position.z = -input.position.y;&#xD;&#xA;		input.position.y = -1.0f;&#xD;&#xA;	}&#xD;&#xA;	[branch] if (g_upVectorVal.y == -1.0f)&#xD;&#xA;	{&#xD;&#xA;		input.position.z = -input.position.y;&#xD;&#xA;		input.position.y = 1.0f;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;About discarding z coordinate too early - since I decided to pass my data through g_upVectorVal variable I has no need for view/projection space so I discarded them fully. I am just using code below for my vertex shader:&#xD;&#xA;&#xD;&#xA;    PixelInputType ColorVertexShader(VertexInputType input)&#xD;&#xA;    {&#xD;&#xA;        PixelInputType output;&#xD;&#xA;&#xD;&#xA;	    output.position = input.position;&#xD;&#xA;	    input.position.w = 1.0f;&#xD;&#xA;&#xD;&#xA;        output.positionSV = mul(input.position, worldMatrix).xyww;&#xD;&#xA;   &#xD;&#xA;        return output;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![IBL Diffuse][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WQnGP.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23332" PostHistoryTypeId="5" PostId="8634" RevisionGUID="d3446b70-6323-4482-9bce-3a761d1933d5" CreationDate="2019-02-25T22:01:47.733" UserId="10217" Comment="deleted 2 characters in body" Text="It's quite difficult. There is so little contrast, even the JPEG compression artifacts have more contrast than the object on the background.&#xD;&#xA;&#xD;&#xA;You would require a highly specialized deblock filter to eliminate the compression artifacts first. With knowledge about the block size of the used compression algorithm and the number of coefficients used per block you may be able to predict some of the edges.&#xD;&#xA;&#xD;&#xA;For edges you could predict in the previous step, you may try to filter these from the detected edges.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;All around the shirt in the photo, there are over-swings due to an excessively  lossy compression. At the edge of each block, the over-swings form a hard edge which you also successfully detected.&#xD;&#xA;&#xD;&#xA;The block size is 8x8 pixels for JPEG (and hence also in this image), so every vertical or horizontal edge which falls directly onto position `8*n` or `8n+1` X or Y is most likely just a compression artifact and can be ignored.&#xD;&#xA;&#xD;&#xA;This approach can only work though if the image hasn't been re-sampled after compression, respectively hasn't been re-compressed multiple times with potentially different block sizes. At that point, isolating the compression artifacts becomes nearly impossible." ContentLicense="CC BY-SA 4.0" />
  <row Id="23333" PostHistoryTypeId="2" PostId="8636" RevisionGUID="257005ce-acf0-48cf-94db-f48b6e84a198" CreationDate="2019-02-25T22:28:54.840" UserId="2308" Text="I am trying to get a feel for how much effort I should put into this. I am building a basic 2D engine and for my use case there are only 8 textures. Each draw call in this engine currently requires that its 1 corresponding texture be bound to '0'. My question is essentially: Is there something faster than this?&#xD;&#xA;&#xD;&#xA;For example, what if I bound the texture for the first sprite to '0' the second to '1' etc etc. This would avoid the gpu having to &quot;switch out&quot; these textures. I am guessing that this wouldn't matter much however.&#xD;&#xA;&#xD;&#xA;Is this something that is valid to be concerned about? Is it expensive for the GPU to swap out textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23334" PostHistoryTypeId="1" PostId="8636" RevisionGUID="257005ce-acf0-48cf-94db-f48b6e84a198" CreationDate="2019-02-25T22:28:54.840" UserId="2308" Text="Are texture binds expensive?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23335" PostHistoryTypeId="3" PostId="8636" RevisionGUID="257005ce-acf0-48cf-94db-f48b6e84a198" CreationDate="2019-02-25T22:28:54.840" UserId="2308" Text="|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23336" PostHistoryTypeId="6" PostId="8624" RevisionGUID="246d96a5-8ca7-4385-8636-e04c729c33a6" CreationDate="2019-02-25T23:28:00.200" UserId="6" Comment="edited tags" Text="|3d|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23337" PostHistoryTypeId="2" PostId="8637" RevisionGUID="943b048c-4cd3-482a-8325-eed193d0d489" CreationDate="2019-02-26T06:44:38.757" UserId="120" Text="The damping force you mentioned $f=-k \frac{\dot{l} \cdot l}{|l|} \frac{l}{|l|}$ is a special case of $f=-k \dot{C} \frac{\partial C}{\partial \mathbf{x}}$.&#xD;&#xA;&#xD;&#xA;Let&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;C(\mathbf{x}) &amp;= \lVert\mathbf{l}\rVert-l_0 \\&#xD;&#xA;\mathbf{l} &amp;= \mathbf{x}_1 - \mathbf{x}_2 \\&#xD;&#xA;\mathbf{\dot{l}} &amp;= \mathbf{v}_1 - \mathbf{v}_2 \\&#xD;&#xA;\mathbf{v} &amp;= \dot{\mathbf{x}} = \begin{pmatrix}\mathbf{v}_1 \\ \mathbf{v}_2\end{pmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $l_0$ is the rest length of the spring, and $\mathbf{x}_1$, $\mathbf{x}_2$ are the positions of two end points.&#xD;&#xA;The damping force is&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\mathbf{f} &amp;= -k \dot{C} \frac{\partial C}{\partial \mathbf{x}} \\&#xD;&#xA;&amp;= -k (\frac{\partial C}{\partial \mathbf{x}})^T \dot{\mathbf{x}} \frac{\partial C}{\partial \mathbf{x}}\\&#xD;&#xA;&amp;= -k (\mathbf{l}^T\mathbf{l})^{-1/2} \mathbf{l}^T \begin{pmatrix}\mathbf{I}&amp; -\mathbf{I} \end{pmatrix} \dot{\mathbf{x}} (\mathbf{l}^T\mathbf{l})^{-1/2} \begin{pmatrix}\mathbf{I}&amp; -\mathbf{I} \end{pmatrix}^T \mathbf{l} \\&#xD;&#xA;&amp;= -k (\mathbf{l}^T\mathbf{l})^{-1} \begin{pmatrix}\mathbf{l}^T&amp; -\mathbf{l}^T \end{pmatrix} \mathbf{v} \begin{pmatrix}\mathbf{l} \\ -\mathbf{l} \end{pmatrix}\\&#xD;&#xA;&amp;= -k \frac{(\mathbf{l}\cdot \mathbf{\dot{l}}) }{\lVert \mathbf{l} \rVert^2}&#xD;&#xA;\begin{pmatrix}\mathbf{l} \\ -\mathbf{l} \end{pmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This matches your damping force equation. The $-\mathbf{l}$ part is just the force for the other particle, which has the opposite direction as expected. Bold letters are used to denote vector quantities.&#xD;&#xA;&#xD;&#xA;As mentioned in [baraff98], this damping force is along the direction $\frac{\partial C}{\partial \mathbf{x}}$,&#xD;&#xA;and its magnitude is the projected component of velocity $\frac{\partial C}{\partial \mathbf{x}}^T \mathbf{v}=\frac{\partial C}{\partial \mathbf{x}}^T \mathbf{\dot{x}}=\dot{C}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="23338" PostHistoryTypeId="5" PostId="8632" RevisionGUID="5e37e193-77d0-49df-ac41-d0ade0fb29c3" CreationDate="2019-02-26T09:50:00.073" UserId="10227" Comment="added 31 characters in body" Text="Utilize `simd` to synchronize your alignment:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-swift --&gt;&#xD;&#xA;    import simd&#xD;&#xA;    &#xD;&#xA;    private struct BoundingBoxParameters {&#xD;&#xA;    &#xD;&#xA;        let topLeft: float2 = float2(0.0, 0.0)&#xD;&#xA;        let size: float2 = float2(0.0, 0.0)&#xD;&#xA;        let levelOfDetail: Float = 1.0&#xD;&#xA;&#xD;&#xA;        init(topLeft: float2,&#xD;&#xA;             size: float2,&#xD;&#xA;             levelOfDetail: Float) {&#xD;&#xA;            self.topLeft = topLeft&#xD;&#xA;            self.size = size &#xD;&#xA;            self.levelOfDetail = levelOfDetail&#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="23342" PostHistoryTypeId="2" PostId="8639" RevisionGUID="2efed4e0-4ec9-45ff-b920-572d8662cbcb" CreationDate="2019-02-26T18:27:59.900" UserId="10235" Text="gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)&#xA;&#xA;I have never seen this syntax before. Presumably glfGetProcAddres is a function, but it has the brackets behind it. Is this only possible in open gl or is my c++ trash." ContentLicense="CC BY-SA 4.0" />
  <row Id="23343" PostHistoryTypeId="1" PostId="8639" RevisionGUID="2efed4e0-4ec9-45ff-b920-572d8662cbcb" CreationDate="2019-02-26T18:27:59.900" UserId="10235" Text="This function syntax is confusing me" ContentLicense="CC BY-SA 4.0" />
  <row Id="23344" PostHistoryTypeId="3" PostId="8639" RevisionGUID="2efed4e0-4ec9-45ff-b920-572d8662cbcb" CreationDate="2019-02-26T18:27:59.900" UserId="10235" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23345" PostHistoryTypeId="2" PostId="8640" RevisionGUID="db4b7393-6690-491e-96b0-3ea0fc810c55" CreationDate="2019-02-26T19:26:41.130" UserId="10217" Text="It's hardware dependent, but as it stands, you shouldn't expect a performance drop on modern dedicated GPUs. Typically they have a pipeline state cache which fits such a small number of states easily.&#xD;&#xA;&#xD;&#xA;The only case when that cache even becomes relevant is if the workload performed in that state is insufficient to saturate the shaders, so execution of subsequent drawcalls overlaps. At that point you can eventually exceed the size of the cache if you have too many different pipeline states and effective utilization drops.&#xD;&#xA;&#xD;&#xA;Except that when you do, you will also have trouble combining all the states into one, so you would still end up with multiple states.&#xD;&#xA;&#xD;&#xA;At that point you are better off using a texture array instead - the level of indirection associated with that doesn't cause any significant performance penalty any more, on modern architectures. You &quot;only&quot; have to group your textures by size and tiling at that point, and you loose mipmapping.&#xD;&#xA;&#xD;&#xA;The alternative is to bake the individual textures into a a single, large texture, which does still allow a certain level of mipmapping, but only down to a level at which pixels from different source textures don't blend. Also you loose the ability to use native tiling, but have to do it manually in shader code." ContentLicense="CC BY-SA 4.0" />
  <row Id="23346" PostHistoryTypeId="5" PostId="8640" RevisionGUID="aafda15f-5037-4da3-9cd0-e723580b8ddf" CreationDate="2019-02-26T19:33:25.310" UserId="10217" Comment="added 293 characters in body" Text="It's hardware dependent, but as it stands, you shouldn't expect a performance drop on modern dedicated GPUs. Typically they have a pipeline state cache which fits such a small number of states easily.&#xD;&#xA;&#xD;&#xA;The only case when that cache even becomes relevant is if the workload performed in that state is insufficient to saturate the shaders, so execution of subsequent drawcalls overlaps. At that point you can eventually exceed the size of the cache if you have too many different pipeline states and effective utilization drops.&#xD;&#xA;&#xD;&#xA;Except that when you do, you will also have trouble combining all the states into one, due to a limit on texture bindings per state, so you would still end up with multiple states. Depending on the API you will have different limits, lower bound being set e.g. by OpenGL 3.x spec requiring 16 texture binding slots, but realistically it doesn't even go much higher than 40-64 binding slots per shader even in high end hardware.&#xD;&#xA;&#xD;&#xA;At that point you are better off using a texture array instead - the level of indirection associated with that doesn't cause any significant performance penalty any more, on modern architectures. You &quot;only&quot; have to group your textures by size and tiling at that point.&#xD;&#xA;&#xD;&#xA;The alternative is to bake the individual textures into a a single, large texture, which does still allow a certain level of mipmapping, but only down to a level at which pixels from different source textures don't blend. Also you loose the ability to use native tiling, but have to do it manually in shader code." ContentLicense="CC BY-SA 4.0" />
  <row Id="23347" PostHistoryTypeId="2" PostId="8641" RevisionGUID="93cbee78-b595-407e-b5c5-b4e3badf6af0" CreationDate="2019-02-26T20:08:07.297" UserId="8680" Text="The signature of `glfwGetProcAddress` is:&#xD;&#xA;&#xD;&#xA;    GLFWglproc glfwGetProcAddress(const char *);&#xD;&#xA;&#xD;&#xA;It's a function that takes a string and returns a `GLFWglproc`. which is defined as&#xD;&#xA;&#xD;&#xA;    typedef void(* GLFWglproc) (void);&#xD;&#xA;&#xD;&#xA;Essentially, that means `glfwGetProcAddress` is a function that takes a string and returns **a pointer** to function with no parameters and no return value.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;`GLADloadproc` is a type alias defined as follows:&#xD;&#xA;&#xD;&#xA;    typedef void* (* GLADloadproc)(const char *name);&#xD;&#xA;&#xD;&#xA;Essentially, this means that this is the type of a function that takes a string and returns **a void pointer** (this is a type of pointer that can be safely converted to from every other type of pointer).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;in the expression&#xD;&#xA;&#xD;&#xA;    gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)&#xD;&#xA;&#xD;&#xA;Inside, there is the expression&#xD;&#xA;&#xD;&#xA;    (GLADloadproc)glfwGetProcAddress&#xD;&#xA;&#xD;&#xA;Where we have a **type** in parenthesis followed by an identifier. This is known as a **type cast**, it means we are taking some value of some type and converting it to some other type.&#xD;&#xA;&#xD;&#xA;In this case, we take our `GLADloadproc` function that takes string and returns pointer to function and we 'disguise' it as a function that takes string and returns `void*`. This works because we can convert any pointer to `void*`, even in function pointer return types.&#xD;&#xA;&#xD;&#xA;This is all to end up passing it to `gladLoadGLLoader`, which expects a value of type `GLADloadproc`.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;&#xD;&#xA;`gladLoadGLLoader` takes a `GLADloadproc` but we want to give it a `GLFWglproc (*)(const char *)`. To be able to do this, we force the type system to take it anyways by using a **type cast**.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23348" PostHistoryTypeId="5" PostId="8619" RevisionGUID="d0ba1c0f-c95d-4a60-884b-d9b92853cb81" CreationDate="2019-02-26T21:46:41.207" UserDisplayName="user106" Comment="corrected spelling of Baraff, included other authors" Text="The rigid body simulation is very similar to the point mass case except for&#xD;&#xA;that we have to handle rotational motion (orientation and angular momentum).&#xD;&#xA;&#xD;&#xA;In addition to common particle attributes such as mass, position, and linear velocity, we will need to store initial moment of inertia $\mathbf{\hat{I}}$,&#xD;&#xA;current angular momentum $\mathbf{L}^n$, and current orientation $\mathbf{R}^n$.&#xD;&#xA;If you are using a data driven particle system, this step is as easy as declaring a few new attributes.&#xD;&#xA;&#xD;&#xA;Contract to the mass, the moment of inertia at current time step $\mathbf{I}^n$ depends on the current orientation $\mathbf{R}^n$: $\mathbf{I}^n=\mathbf{R}^n \mathbf{\hat{I}} (\mathbf{R}^n)^T$.&#xD;&#xA;&#xD;&#xA;The kinetic of a rigid body is analogous to the linear motion:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;\dot{\mathbf{R}} &amp;= \omega^* \mathbf{R} \\&#xD;&#xA;\frac{\mathbf{R}^{n+1} - \mathbf{R}^n}{\Delta t} &amp;= (\omega^{n*}) \mathbf{R}^n \\&#xD;&#xA;\omega^n &amp;= (\mathbf{I}^n)^{-1} \mathbf{L}^n&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;where $\omega$ is the angular velocity and $\omega^*$ is the &quot;cross product&quot; matrix.&#xD;&#xA;&#xD;&#xA;For dynamics, we also have a similar version of Newton's &quot;f=ma&quot;:&#xD;&#xA;$$&#xD;&#xA;\frac{\mathbf{L}^{n+1} - \mathbf{L}^n}{\Delta t} = \tau^n&#xD;&#xA;$$&#xD;&#xA;where $\tau$ is the torque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because there will be interactions between rigid spheres, you will also need to implement the collision detection for spheres.&#xD;&#xA;&#xD;&#xA;Now we have known the kinematics and dynamics of rigids. The only thing left is how to solve (integrate) above equations. The naive forward Euler may not give stable result. A good introduction of this topic can be found at [Witkin and Baraff SIGGRAPH course](http://www.cs.cmu.edu/~baraff/sigcourse/index.html), and here is an another more [recent SIGGRAPH course by Bargteil and Shinar](https://www.cs.ucr.edu/~shinar/papers/2018_introduction_to_pba.pdf)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23349" PostHistoryTypeId="24" PostId="8619" RevisionGUID="d0ba1c0f-c95d-4a60-884b-d9b92853cb81" CreationDate="2019-02-26T21:46:41.207" Comment="Proposed by 106 approved by 209, 231 edit id of 462" ContentLicense="CC BY-SA 4.0" />
  <row Id="23350" PostHistoryTypeId="5" PostId="8595" RevisionGUID="9b5e60e9-a24c-41d5-b206-7e49c8a36174" CreationDate="2019-02-26T21:59:07.647" UserId="231" Comment="Escape asterisks to avoid multiplication being rendered as italics" Text="Two suggestions:&#xD;&#xA;&#xD;&#xA; 1. If your data is from an image you are displaying on a standard monitor, the chances are it is (or you are implicitly assuming that it's) in sRGB format. This [means that the colour components are not linear][1]. Ideally, you should first map into a linear colour space, do your filtering (e.g. blurring) operations, and then map back.   &#xD;&#xA;*(If you just want to try a cheap and cheerful approach, squaring each of the R G B components is not terrible approach to &quot;linearise&quot; the values, and, obviously, use sqrt() to map back)*.  &#xD;&#xA;The alpha channel can be assumed to be linear.&#xD;&#xA;&#xD;&#xA; 2. Once in linear colour space, the next thing you want to do before filtering is to convert the pixels to a pre-multiplied-alpha format (AKA &quot;*associated colour*&quot;).  &#xD;&#xA;Basically, given {A,R,G,B} pixel input, produce  {A, A\*R/255, A\*G/255, A\*B/255}.  You then do your averaging on this premultiplied data as above on all four channels, and then map back by dividing through by the resulting alpha (if A=0 then, choose, RGB=0).&#xD;&#xA;&#xD;&#xA;This *should* produce a better result. &#xD;&#xA;For more info I suggest reading through Jim Blinn's [&quot;Compositing, Part1: Theory&quot;][2].  &#xD;&#xA;Particularly, note the line &quot;*Additionally, we must use associated colors for any filtering or interpolation operations*&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Update*: Seems I've posted a [similar answer before][3] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_(%22gamma%22)&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/5517/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="23351" PostHistoryTypeId="5" PostId="8640" RevisionGUID="d0d9c7b1-bca3-455f-a136-9912e5515996" CreationDate="2019-02-26T22:24:17.837" UserId="10217" Comment="added 21 characters in body" Text="It's hardware dependent, but as it stands, you shouldn't expect a performance drop on modern dedicated GPUs. Typically they have a pipeline state cache which fits such a small number of states easily.&#xD;&#xA;&#xD;&#xA;The only case when that cache even becomes relevant is if the workload performed in that state is insufficient to saturate the shaders, so execution of subsequent drawcalls overlaps. At that point you can eventually exceed the size of the cache if you have too many different pipeline states and effective utilization drops.&#xD;&#xA;&#xD;&#xA;Except that when you do, you will also have trouble combining all the states into one, due to a limit on texture bindings per state and stage, so you would still end up with multiple states. Depending on the API you will have different limits, lower bound being set e.g. by OpenGL 3.x spec requiring 16 texture binding slots per shader, but realistically it doesn't even go much higher than 40-64 binding slots per shader even in high end hardware.&#xD;&#xA;&#xD;&#xA;At that point you are better off using a texture array instead - the level of indirection associated with that doesn't cause any significant performance penalty any more, on modern architectures. You &quot;only&quot; have to group your textures by size and tiling at that point.&#xD;&#xA;&#xD;&#xA;The alternative is to bake the individual textures into a a single, large texture, which does still allow a certain level of mipmapping, but only down to a level at which pixels from different source textures don't blend. Also you loose the ability to use native tiling, but have to do it manually in shader code." ContentLicense="CC BY-SA 4.0" />
  <row Id="23352" PostHistoryTypeId="5" PostId="5517" RevisionGUID="f2703859-3999-45d7-9297-9d19a2af047e" CreationDate="2019-02-27T09:00:49.647" UserId="209" Comment="Fixed poorly written sentence and found a better link to Blinn's article" Text="I apologise for only skimming through your question/answer and the links you gave but I thought it would be a good idea to post what needs to be done to *correctly* do any blending and/or filtering on images with an alpha channel.&#xD;&#xA;&#xD;&#xA;The first thing to note is that all calculations should be done in a linear colour space, but the image data in PNGs and JPEGs is most likely to be in [sRGB][1] which is non-linear. You should convert this data to a linear form before doing any calculations. For example, the average of black (0,0,0) and white (255,255,255) in sRGB is not (127,127,127) but (off the top of my head) something like (186,186,186). The filtering of images, especially those with neighbouring, complementary, saturated colours (e.g. Yellow&amp;Blue), can look quite odd if you don't take gamma into account.&#xD;&#xA;&#xD;&#xA;The second part of this theory dates back to Porter and Duff's seminal 1984 paper, &quot;[Compositing Digital Images][2]&quot;, which introduces the concept of pre-multiplied alpha. Pre-multiplied alpha basically means that you multiply the RGBs by the alpha value before doing calculations. &#xD;&#xA;&#xD;&#xA;I get the feeling this was initially done just to reduce computation costs but in his article [&quot;Compositing-Theory&quot;][3], Jim Blinn shows that the correct way to do any filtering or compositing operations is to first convert everything to premultipled. &#xD;&#xA;&#xD;&#xA;Once you have linearised and then pre-multiplied your pixel data, do the filtering/blending and, finally, undo the pre-multiply and reapply the gamma function to map back to sRGB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB&#xD;&#xA;  [2]: https://keithp.com/~keithp/porterduff/p253-porter.pdf&#xD;&#xA;  [3]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="23356" PostHistoryTypeId="2" PostId="8643" RevisionGUID="df12b2a9-0887-4f44-9674-a15242337b68" CreationDate="2019-02-28T01:19:11.413" UserId="10243" Text="In most cases today, image palettization consists of reducing the overall number of colors in an image to some fixed number globally. This is typically solved as a straightforward but computationally difficult clustering problem.&#xD;&#xA;&#xD;&#xA;A more difficult version of this problem involves older graphics hardware where the palette is broken down into N subpalettes (e.g. of 4 colors each) and the image is broken down into XxY-pixel tiles where each tile can only use colors from a single subpalette and N &lt;&lt; the number of tiles. Here both the exact colors, the arrangement of colors into subpalettes, and the subpalette for each tile of the image are all unknowns that must be solved together.&#xD;&#xA;&#xD;&#xA;How could this more difficult problem be solved, algorithmically?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23357" PostHistoryTypeId="1" PostId="8643" RevisionGUID="df12b2a9-0887-4f44-9674-a15242337b68" CreationDate="2019-02-28T01:19:11.413" UserId="10243" Text="Tiled Image Palettization Algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23358" PostHistoryTypeId="3" PostId="8643" RevisionGUID="df12b2a9-0887-4f44-9674-a15242337b68" CreationDate="2019-02-28T01:19:11.413" UserId="10243" Text="|algorithm|image-processing|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23359" PostHistoryTypeId="2" PostId="8644" RevisionGUID="e3ffb01e-fa30-4d6c-8820-0668bd140417" CreationDate="2019-02-28T02:02:05.747" UserId="10244" Text="What are the mathematical constraints required for a polyline, i.e., a piecewise linear curve, to appear as a smooth curve to human vision?  I've discovered one [document][1] that specifies only that the change of direction at each vertex must be less than 3°.  It seems to me that there also needs to be a limit on degrees turned per curve length, but that's a simple enhancement.&#xD;&#xA;&#xD;&#xA;My main question is about how the maximum direction change angle is affected by segment length.  If you have two long segments connected at 3° then the change will be (to my eye anyway) much more visible than a 3° angle between short segments.  Is anyone aware of any studies in this area?&#xD;&#xA;&#xD;&#xA;In case it matters, my application is in polyline generalization for GIS.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.stat.auckland.ac.nz/~ihaka/downloads/Curves-handouts.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="23360" PostHistoryTypeId="1" PostId="8644" RevisionGUID="e3ffb01e-fa30-4d6c-8820-0668bd140417" CreationDate="2019-02-28T02:02:05.747" UserId="10244" Text="Constraining a Polyline to Look Smooth" ContentLicense="CC BY-SA 4.0" />
  <row Id="23361" PostHistoryTypeId="3" PostId="8644" RevisionGUID="e3ffb01e-fa30-4d6c-8820-0668bd140417" CreationDate="2019-02-28T02:02:05.747" UserId="10244" Text="|mathematics|2d|2d-graphics|human-vision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23362" PostHistoryTypeId="2" PostId="8645" RevisionGUID="a5c90d6a-4d7c-4e90-af5a-bf071fc746c5" CreationDate="2019-02-28T09:47:12.897" UserId="209" Text="An interesting problem. I've done a bit of work in texture compression and this sounds something like a generalisation of [Campbell et al's &quot;Color Cell Compression&quot;][1].  It's also a little like a feature we were asked to include in the Dreamcast VQ compressor so that sub-palettes could be swapped to create different colour schemes on textures. &#xD;&#xA;&#xD;&#xA;I was thus thinking that *maybe* you could adapt a standard VQ algorithm, applied in stages, to the problem. &#xD;&#xA;&#xD;&#xA;You say that &#xD;&#xA;&gt;*&quot;the exact colors, the arrangement of colors into subpalettes, and the subpalette for each tile of the image are all unknowns&quot;*&#xD;&#xA;&#xD;&#xA;but can we assume the X*Y tile size *is* predetermined?&#xD;&#xA;&#xD;&#xA;Assuming that is the case, perhaps the following might be worth trying:&#xD;&#xA;&#xD;&#xA;1) Guess an initial palette size for the entire image, perhaps,&#xD;&#xA;  $Psize=(M * SizeOfEachSubpalette)$ where $1 &lt; M &lt; N$.&#xD;&#xA;&#xD;&#xA;Use standard VQ quantisation to generate this palette and map the pixels to it.&#xD;&#xA;&#xD;&#xA;2) Now consider each $X*Y$ tile to be a &quot;super pixel&quot; with $Psize$ channels. Set each channel value in the tile's &quot;super pixel&quot; to the number of pixels that mapped to the corresponding colour in our initial palette.&#xD;&#xA;&#xD;&#xA;Run a second VQ operation on the set of all &quot;super pixels&quot; using '$Psize$-dimensional space' to generate $N$ &quot;palette&quot; entries. *(Actually, you don't need the 'palette' values - the VQ process is just meant as a means of partitioning the tiles into $N$ sets)*  &#xD;&#xA;&#xD;&#xA;Hopefully, this will now identify which tiles should share the same sub-palette.&#xD;&#xA;&#xD;&#xA;3) For each tile set, collect all the pixels in the tiles, and apply a 3rd VQ operation to identify the $SizeOfEachSubpalette$ colours needed for all tiles in that set.&#xD;&#xA;&#xD;&#xA;I would think some sort of clever GLA/k-means process might be needed for step 2 to juggle the assignments of tiles to sub-palettes. The choice of M might also be interesting.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_Cell_Compression" ContentLicense="CC BY-SA 4.0" />
  <row Id="23363" PostHistoryTypeId="5" PostId="8645" RevisionGUID="2c4babfe-552e-4dad-a369-51cb59d5bcb5" CreationDate="2019-02-28T09:53:12.243" UserId="209" Comment="added 181 characters in body" Text="An interesting problem. I've done a bit of work in texture compression and this sounds something like a generalisation of [Campbell et al's &quot;Color Cell Compression&quot;][1].  It's also a little like a feature we were asked to include in the Dreamcast VQ compressor so that sub-palettes could be swapped to create different colour schemes on textures. &#xD;&#xA;&#xD;&#xA;I was thus thinking that *maybe* you could adapt a standard VQ algorithm, applied in stages, to the problem. &#xD;&#xA;&#xD;&#xA;You say that &#xD;&#xA;&gt;*&quot;the exact colors, the arrangement of colors into subpalettes, and the subpalette for each tile of the image are all unknowns&quot;*&#xD;&#xA;&#xD;&#xA;but can we assume the X*Y tile size *is* predetermined?&#xD;&#xA;&#xD;&#xA;Assuming that is the case, perhaps the following might be worth trying:&#xD;&#xA;&#xD;&#xA;1) Guess an initial palette size for the entire image, perhaps, &#xD;&#xA; $$Psize=(M * SizeOfEachSubpalette)$$&#xD;&#xA;where $1 &lt; M &lt; N$.&#xD;&#xA;&#xD;&#xA;Use standard VQ quantisation to generate this palette and map the pixels to it.&#xD;&#xA;&#xD;&#xA;2) Now consider each $X*Y$ tile to be a &quot;super pixel&quot; with $Psize$ channels. Set each channel value in the tile's &quot;super pixel&quot; to the number of pixels that mapped to the corresponding colour in our initial palette.&#xD;&#xA;&#xD;&#xA; For example, if in our initial palette, entry $j$ is [0x11,0x21,0x31] and 5 pixels in the tile mapped to that colour, set the $j'th$ component in the tile's superpixel to 5.&#xD;&#xA;&#xD;&#xA;Run a second VQ operation on the set of all &quot;super pixels&quot; using '$Psize$-dimensional space' to generate $N$ &quot;palette&quot; entries. *(Actually, you don't need the 'palette' values - the VQ process is just meant as a means of partitioning the tiles into $N$ sets)*  &#xD;&#xA;&#xD;&#xA;Hopefully, this will now identify which tiles should share the same sub-palette.&#xD;&#xA;&#xD;&#xA;3) For each tile set, collect all the pixels in the tiles, and apply a 3rd VQ operation to identify the $SizeOfEachSubpalette$ colours needed for all tiles in that set.&#xD;&#xA;&#xD;&#xA;I would think some sort of clever GLA/k-means process might be needed for step 2 to juggle the assignments of tiles to sub-palettes. The choice of M might also be interesting.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_Cell_Compression" ContentLicense="CC BY-SA 4.0" />
  <row Id="23364" PostHistoryTypeId="2" PostId="8646" RevisionGUID="c0e4c1d7-d53a-44c5-85a2-6ff5fa466ccf" CreationDate="2019-02-28T11:02:17.480" UserId="10245" Text="I want to utilize shaders to not only discard fragments if they are on one side of a predefined plane but also render a contour along the intersection. &#xD;&#xA;&#xD;&#xA;My fragment shader currently does something along the lines of: &#xD;&#xA;&#xD;&#xA;    float dot = dot(world_coordinate, normalize(clipping_normal.xyz)) - clipping_normal.w;&#xD;&#xA;    if (dot &gt; 0.0f) &#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;this works but without the desired contour. I tried comparing the dot product against values close to 0.0 but this results in a contour with varying width depending on view etc...&#xD;&#xA;&#xD;&#xA;This is what I am trying to achieve. Notice that the white contour/edge of where the plane intersects the sphere is of consistent width:&#xD;&#xA;&#xD;&#xA;[![cross-section][1]][1]&#xD;&#xA;  [1]: https://i.stack.imgur.com/omrFH.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23365" PostHistoryTypeId="1" PostId="8646" RevisionGUID="c0e4c1d7-d53a-44c5-85a2-6ff5fa466ccf" CreationDate="2019-02-28T11:02:17.480" UserId="10245" Text="Show the edges between the clipping plane and clipped objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="23366" PostHistoryTypeId="3" PostId="8646" RevisionGUID="c0e4c1d7-d53a-44c5-85a2-6ff5fa466ccf" CreationDate="2019-02-28T11:02:17.480" UserId="10245" Text="|opengl|shader|glsl|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23368" PostHistoryTypeId="50" PostId="8527" RevisionGUID="02f7d17f-c4cb-4034-81a3-789f848d2a3a" CreationDate="2019-02-28T15:03:10.687" UserId="-1" />
  <row Id="23372" PostHistoryTypeId="5" PostId="8595" RevisionGUID="be09b9e9-f306-4846-a2b3-72012efa4fa4" CreationDate="2019-03-01T11:51:01.783" UserId="209" Comment="Just clarified the example maths is assuming 8bit/channel" Text="Two suggestions:&#xD;&#xA;&#xD;&#xA; 1. If your data is from an image you are displaying on a standard monitor, the chances are it is (or you are implicitly assuming that it's) in sRGB format. This [means that the colour components are not linear][1]. Ideally, you should first map into a linear colour space, do your filtering (e.g. blurring) operations, and then map back.   &#xD;&#xA;*(If you just want to try a cheap and cheerful approach, squaring each of the R G B components is not terrible approach to &quot;linearise&quot; the values, and, obviously, use sqrt() to map back)*.  &#xD;&#xA;The alpha channel can be assumed to be linear.&#xD;&#xA;&#xD;&#xA; 2. Once in linear colour space, the next thing you want to do before filtering is to convert the pixels to a pre-multiplied-alpha format (AKA &quot;*associated colour*&quot;).  &#xD;&#xA;Basically, given 8bpc {A,R,G,B} pixel input, produce  {A, A\*R/255, A\*G/255, A\*B/255}.  You then do your averaging on this premultiplied data as above on all four channels, and then map back by dividing through by the resulting alpha (if A=0 then, choose, RGB=0).&#xD;&#xA;&#xD;&#xA;This *should* produce a better result. &#xD;&#xA;For more info I suggest reading through Jim Blinn's [&quot;Compositing, Part1: Theory&quot;][2].  &#xD;&#xA;Particularly, note the line &quot;*Additionally, we must use associated colors for any filtering or interpolation operations*&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Update*: Seems I've posted a [similar answer before][3] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_(%22gamma%22)&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/5517/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="23373" PostHistoryTypeId="2" PostId="8648" RevisionGUID="f63655a7-580e-4ec8-8734-f0d1fe3272c0" CreationDate="2019-03-01T17:50:02.500" UserId="10254" Text="Forward rendering is the 'classic' approach to the rendering pipeline. &#xD;&#xA;Nowadays it is mostly replaced by a more flexible, deferred rendering approach.&#xD;&#xA;&#xD;&#xA;I did some research and had trouble finding something specific about the history of Forward Rendering.&#xD;&#xA;It is my understanding, that Forward Shading evolved alongside the rendering pipeline. The pipeline provided the features for forward rendering and Forward Rendering incorporated the features of the pipeline. &#xD;&#xA;&#xD;&#xA;I was wondering: When did a name for the classical shading approach come up and why was this specific name chosen?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23374" PostHistoryTypeId="1" PostId="8648" RevisionGUID="f63655a7-580e-4ec8-8734-f0d1fe3272c0" CreationDate="2019-03-01T17:50:02.500" UserId="10254" Text="Why is Forward Rendering/Shading named this way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23375" PostHistoryTypeId="3" PostId="8648" RevisionGUID="f63655a7-580e-4ec8-8734-f0d1fe3272c0" CreationDate="2019-03-01T17:50:02.500" UserId="10254" Text="|shading|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23377" PostHistoryTypeId="2" PostId="8649" RevisionGUID="d117272b-e442-4965-8ad7-c754a64fdd57" CreationDate="2019-03-02T06:02:11.513" UserId="9987" Text="Currently I am learning PBR by Unity3D. I find that even I turn the smoothness to 1, I can still see the diffuse lighting effect, which does not make any sense to me.&#xD;&#xA;&#xD;&#xA;Imagine I trace a ray from my eye to the mirror, and I do importance sampling based on the material's brdf, there are only two options,  hit the light source or not. However, I find that if I set the metallic to be 0 and smoothness to 1, there will have large amount of area illuminated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1J2PH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23378" PostHistoryTypeId="1" PostId="8649" RevisionGUID="d117272b-e442-4965-8ad7-c754a64fdd57" CreationDate="2019-03-02T06:02:11.513" UserId="9987" Text="Why can I see the diffuse lighting effect on a perfect mirror?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23379" PostHistoryTypeId="3" PostId="8649" RevisionGUID="d117272b-e442-4965-8ad7-c754a64fdd57" CreationDate="2019-03-02T06:02:11.513" UserId="9987" Text="|pbr|unity|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23380" PostHistoryTypeId="10" PostId="8646" RevisionGUID="bed2e3b8-87a8-40ab-88b5-e40a2e68ced1" CreationDate="2019-03-02T09:57:56.920" UserId="2041" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="23383" PostHistoryTypeId="2" PostId="8650" RevisionGUID="12fc04be-0f6e-4a10-9f16-7950ac208e3b" CreationDate="2019-03-02T22:57:50.327" UserId="2817" Text="Dielectric materials (which is what you get when metalness is 0) don't exhibit a mirror-like effect. Think of a sheet of smooth, non-transparent plastic. Real-life mirrors are panes of glass or transparent plastic covered with a thin layer of metal. Try a white base colour (1,1,1) and full metalness (1) instead.&#xD;&#xA;&#xD;&#xA;As Hubble pointed out in his comment, Unity won't do full ray tracing for you out of the box, but it should be able to do some approximation with screen-space reflections and local reflection probes." ContentLicense="CC BY-SA 4.0" />
  <row Id="23389" PostHistoryTypeId="2" PostId="8652" RevisionGUID="a42f8ca8-1498-4f77-99ad-8a46fb635721" CreationDate="2019-03-04T19:19:10.550" UserId="10267" Text="&#xD;&#xA;&#xD;&#xA;Imagine I render to an FBO some arbitrary geometry. Geometry can be rendered via single or multiple draw calls. For the sake of the question, assume I know nothing about geometry or transformation matrices.&#xD;&#xA;&#xD;&#xA;I need to efficiently read back the minimal screen-space bounding box of all drawn geometry after the rendering to FBO is finished.&#xD;&#xA;&#xD;&#xA;I imagine this can be done with via use of atomics on an image (imageLoad/imageStore) or SSBO, sadly these are not available to me. Is there any other mechanism I can try?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23390" PostHistoryTypeId="1" PostId="8652" RevisionGUID="a42f8ca8-1498-4f77-99ad-8a46fb635721" CreationDate="2019-03-04T19:19:10.550" UserId="10267" Text="Convey screenspace bounding box of rendering result" ContentLicense="CC BY-SA 4.0" />
  <row Id="23391" PostHistoryTypeId="3" PostId="8652" RevisionGUID="a42f8ca8-1498-4f77-99ad-8a46fb635721" CreationDate="2019-03-04T19:19:10.550" UserId="10267" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23392" PostHistoryTypeId="2" PostId="8653" RevisionGUID="8367bfff-6f40-4ccc-a58e-9b75b58a495b" CreationDate="2019-03-05T03:38:03.843" UserId="10269" Text="Now the mainstream engine's approach is to use image-based lighting to achieve approximate global illumination, but such a technique seems to be only applicable to outdoor scenes.What kind of technology is used in the indoor scene to achieve global illumination?For example, in a room with natural light, or in a completely enclosed indoor environment" ContentLicense="CC BY-SA 4.0" />
  <row Id="23393" PostHistoryTypeId="1" PostId="8653" RevisionGUID="8367bfff-6f40-4ccc-a58e-9b75b58a495b" CreationDate="2019-03-05T03:38:03.843" UserId="10269" Text="How Image Based Lighting is applied to indoor scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23394" PostHistoryTypeId="3" PostId="8653" RevisionGUID="8367bfff-6f40-4ccc-a58e-9b75b58a495b" CreationDate="2019-03-05T03:38:03.843" UserId="10269" Text="|global-illumination|pbr|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23396" PostHistoryTypeId="2" PostId="8654" RevisionGUID="ef1a672c-4803-4557-b63a-2d66984e937e" CreationDate="2019-03-05T12:00:31.907" UserId="2041" Text="There's two main things it seems like you've not understood correctly.&#xD;&#xA;&#xD;&#xA;## IBL is for indoor scenes and outdoor scenes&#xD;&#xA;&#xD;&#xA;In the early days when IBL was hot, the Uffizi light-probe was probably the most popular for researchers. IBL works really well for indoor scenes with strong light coming from multiple directions, such as churches with stained glass. That kind of scene was the &quot;killer app&quot;, because for most outdoor scenes, skylight simulation was already a popular, fast, and useful method. Environment maps were originally popular for outdoor scenes because simulated clouds didn't *look* right, even though the lighting was good.&#xD;&#xA;&#xD;&#xA;The big limitation for indoor scenes is if the room is small. A light probe taken in the middle of a room won't be accurate for the corners of that room, because the light is coming from different directions. Just like with a reflection map, if your objects are moving far enough for that to be visible, you need to take multiple light probes and blend between them. This can also be a limit for outdoor scenes if the lighting is dominated by (say) the shadow of a building or tree, or a nearby artificial light.&#xD;&#xA;&#xD;&#xA;## IBL is not a global illumination technique&#xD;&#xA;&#xD;&#xA;It's more helpful to think of it as pre-baked lighting. Just as you might use a light map to bake GI computed from your static lights (with some offline technique) into the textures for your static objects, you can also have that pre-computed GI affect your dynamic objects. But it's not an approximation to full GI, because dynamic lights and objects don't contribute at all.&#xD;&#xA;&#xD;&#xA;## So how do I use it indoors?&#xD;&#xA;&#xD;&#xA;There's two ways. If you're trying to place CG objects into a real-world indoor scene, just capture a light probe of that scene exactly the same way as a real-world outdoor scene. If you're trying to light a CG scene (i.e. a room that only exists in your game), then put your scene into an offline renderer (such as a path-tracer with full GI) to create the light probe, then apply that light probe in your real-time engine." ContentLicense="CC BY-SA 4.0" />
  <row Id="23397" PostHistoryTypeId="2" PostId="8655" RevisionGUID="0fd452ed-c5eb-44ca-823a-e5206d85c5ec" CreationDate="2019-03-05T19:12:30.507" UserId="7462" Text="I am well aware of the existence of Blinn-Phong shading, which is a great tool when you are doing, for example, modelling algorithms and wan't to focus on the model. In this case a full BRDF result, even if fast, could make it harder to appreciate the geometry you are analysing.&#xD;&#xA;&#xD;&#xA;On the other end of the spectrum, we have full BRDF approximations through monte-carlo algorithms and ray traycing. Which give amazing results, but are very slow.&#xD;&#xA;&#xD;&#xA;I have tried to look for, but haven't found,a list of commonly used algorithms that have different levels of trade off between quality and speed.&#xD;&#xA;&#xD;&#xA;Does anyone know of a resource where I can find some algorithms, their performance and quality?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23398" PostHistoryTypeId="1" PostId="8655" RevisionGUID="0fd452ed-c5eb-44ca-823a-e5206d85c5ec" CreationDate="2019-03-05T19:12:30.507" UserId="7462" Text="What is a list of common, cheap, real time rendering algorithms?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23399" PostHistoryTypeId="3" PostId="8655" RevisionGUID="0fd452ed-c5eb-44ca-823a-e5206d85c5ec" CreationDate="2019-03-05T19:12:30.507" UserId="7462" Text="|raytracing|rendering|algorithm|real-time|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23400" PostHistoryTypeId="2" PostId="8656" RevisionGUID="81c3c7e9-edfd-420b-b2f8-56ad8e03b377" CreationDate="2019-03-05T20:07:46.410" UserId="10096" Text="For mostly offline rendering (some of those can be done in real-time, but in the majority of cases not for games, which is changing especially with NVIDIA RTX) you can refer to this: https://people.mpi-inf.mpg.de/~ritschel/Papers/GISTAR.pdf&#xD;&#xA;At the bottom there's a very nice table that summarizes the findings.&#xD;&#xA;&#xD;&#xA;For more real-time oriented stuff you can refer to this post:&#xD;&#xA;https://www.reddit.com/r/opengl/comments/28bs74/realtime_global_illumination_ispm_vs_cone_voxel/" ContentLicense="CC BY-SA 4.0" />
  <row Id="23402" PostHistoryTypeId="2" PostId="8657" RevisionGUID="108c49f7-a3e8-442c-9e6b-3f129f9e2dfc" CreationDate="2019-03-06T15:44:37.510" UserId="7462" Text="I found a good article from 2009:&#xD;&#xA;&#xD;&#xA;https://pdfs.semanticscholar.org/09ea/c60a78c84f9048058cb9518ed30335b86169.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="23403" PostHistoryTypeId="2" PostId="8658" RevisionGUID="17a1d044-82da-4a70-9615-c3dde66b9444" CreationDate="2019-03-07T07:36:50.493" UserId="9987" Text="I am implementing a GGX BRDF, this is the formula I used is from:https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2rZhq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/z7l6j.png&#xD;&#xA;&#xD;&#xA;And this is my implementation:&#xD;&#xA;&#xD;&#xA;    float BRDF(float3 viewDir, float roughness, float3 normal, float3 Li) {&#xD;&#xA;				float3 halfDir = normalize(Li + viewDir);&#xD;&#xA;				float nl = saturate(dot(normal, Li));&#xD;&#xA;				float nh = saturate(dot(normal, halfDir));&#xD;&#xA;&#xD;&#xA;				half lv = saturate(dot(Li, viewDir));&#xD;&#xA;				half lh = saturate(dot(Li, halfDir));&#xD;&#xA;				half nv = abs(dot(normal, viewDir));&#xD;&#xA;&#xD;&#xA;				float a2 = roughness * roughness;&#xD;&#xA;				float G2 = SmithGGXMaskingShadowing(nl, nv, a2);&#xD;&#xA;&#xD;&#xA;				float D = GGX(nh, roughness);&#xD;&#xA;				return G2 * D /(4 * abs(nv) * abs(nl));&#xD;&#xA;			}&#xD;&#xA;    			&#xD;&#xA;&#xD;&#xA;    float SmithGGXMaskingShadowing(float NdotL, float NdotV, float a2)&#xD;&#xA;			{&#xD;&#xA;&#xD;&#xA;				float denomA = NdotV * sqrt(a2 + (1.0f - a2) * NdotL * NdotL);&#xD;&#xA;				float denomB = NdotL * sqrt(a2 + (1.0f - a2) * NdotV * NdotV);&#xD;&#xA;&#xD;&#xA;				return 2.0f * NdotL * NdotV / (denomA + denomB);&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;    float GGX(float NdotH, float a) {&#xD;&#xA;				float a2 = sqr(a);&#xD;&#xA;				return a2 / (UNITY_PI * sqr(sqr(NdotH) * (a2 - 1) + 1));&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;I assume the fresnel term is constant: 1. However, I found that my BRDF sometimes give me number greater than 1." ContentLicense="CC BY-SA 4.0" />
  <row Id="23404" PostHistoryTypeId="1" PostId="8658" RevisionGUID="17a1d044-82da-4a70-9615-c3dde66b9444" CreationDate="2019-03-07T07:36:50.493" UserId="9987" Text="GGX BRDF is greater than 1?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23405" PostHistoryTypeId="3" PostId="8658" RevisionGUID="17a1d044-82da-4a70-9615-c3dde66b9444" CreationDate="2019-03-07T07:36:50.493" UserId="9987" Text="|brdf|pbr|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23408" PostHistoryTypeId="2" PostId="8660" RevisionGUID="21913557-7f96-4a25-9cf8-ea8e9e1dd128" CreationDate="2019-03-07T11:58:51.057" UserId="3085" Text="I'm reading [this paper](https://www.cl.cam.ac.uk/~rkm38/pdfs/mantiuk06pfcphdri.pdf) and one thing sticks out at me.&#xD;&#xA;&#xD;&#xA;Let's say I use the approximate transducer:&#xD;&#xA;&#xD;&#xA;    R = 54.09288 ·G^0.41850  &#xD;&#xA;&#xD;&#xA;Then I scale it:&#xD;&#xA;&#xD;&#xA;    R̂ = R * l&#xD;&#xA;&#xD;&#xA;Then I go back to  Ĝ :&#xD;&#xA;&#xD;&#xA;    Ĝ  =  7.2232 · 10^−5 · R̂  ^2.3895&#xD;&#xA;&#xD;&#xA;Combining these 3 calculations, we get:&#xD;&#xA;&#xD;&#xA;    Ĝ  =  7.2232 · 10^−5 · R̂  ^2.3895&#xD;&#xA;       =  7.2232 · 10^−5 · (R*l)  ^2.3895 &#xD;&#xA;       =  7.2232 · 10^−5 · R  ^2.3895 * l  ^2.3895 &#xD;&#xA;       =  7.2232 · 10^−5 · (54.09288 ·G^0.41850)  ^2.3895 * l  ^2.3895 &#xD;&#xA;       = G *  l  ^2.3895&#xD;&#xA;&#xD;&#xA;Here, `l  ^2.3895` is a constant. So the entire contrast mapping procedure appears to amount to a linear scaling of the physical contrast.&#xD;&#xA;&#xD;&#xA;OTOH, in the paper, it says:&#xD;&#xA;&#xD;&#xA;&gt; Since the contrast response R is perceptually linearized, scaling effectively enhances low physical contrast W, for which we are the most sensitive, and compresses large contrast magnitudes, for which the sensitivity is much lower.&#xD;&#xA;&#xD;&#xA;This seems to contradict what I wrote above.&#xD;&#xA;&#xD;&#xA;Am I missing something?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23409" PostHistoryTypeId="1" PostId="8660" RevisionGUID="21913557-7f96-4a25-9cf8-ea8e9e1dd128" CreationDate="2019-03-07T11:58:51.057" UserId="3085" Text="Mantiuk's contrast mapping seems to amount to a gamma correction" ContentLicense="CC BY-SA 4.0" />
  <row Id="23410" PostHistoryTypeId="3" PostId="8660" RevisionGUID="21913557-7f96-4a25-9cf8-ea8e9e1dd128" CreationDate="2019-03-07T11:58:51.057" UserId="3085" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23411" PostHistoryTypeId="2" PostId="8661" RevisionGUID="5f0c1e22-8024-4377-8c50-44751760890b" CreationDate="2019-03-07T15:41:08.497" UserId="10286" Text="We are developing a PPI plot for a radar system, similar to the following: [![http://radar-review.blogspot.com/2014/04/][1]][1]&#xD;&#xA;**NOTE: 1 radial is defined as a single slice of data within the circle, and 1 range gate is defined as a single point along a radial.**&#xD;&#xA;&#xD;&#xA;Our application must operate in real time, with large throughput and with a varying number of range gates per radial. &#xD;&#xA;&#xD;&#xA;We have two implementations at the moment, both which stream radials to the GPU as vertex and/or texture data. &#xD;&#xA;&#xD;&#xA;One version defines each range gate as separate primitives, then colors them using vertex coloring. The problem here is that the vertex buffer size must be rather large to accommodate a suitable amount of radials / range gates; this memory is not something we can necessarily rely on.&#xD;&#xA;&#xD;&#xA;I am exploring another option, which generates one quad to represent each radial, then colors the range gates using texture mapping. The range gate texture buffer is a large 2D texture (2D to increase the maximum texture buffer size); 1D subsets of this texture are mapped to radials represent range gates. The problem with this method is that when a large number of fragments are being processed, each must perform a texture lookup to determine its color, which is wasteful since most fragments are redundant. This problem is compounded when zooming in, as every pixel in the window must sample the texture. The program's GPU usage skyrockets in these instances.&#xD;&#xA;&#xD;&#xA;I've wondered if maybe it would be possible to sample each radial's 1D subset at the vertex level (since all vertices share a single 1D texture) then pass the sampled version to the fragment shader which then sample the subset. Each radial can have up to a thousand unique color samples. This would theoretically reduce the number of texture reads, but of course I don't even know if it's possible.&#xD;&#xA;&#xD;&#xA;Is there an some way to optimize this process, or perhaps a way to reimagine the software that avoids some of these bottlenecks? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lGMg2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23412" PostHistoryTypeId="1" PostId="8661" RevisionGUID="5f0c1e22-8024-4377-8c50-44751760890b" CreationDate="2019-03-07T15:41:08.497" UserId="10286" Text="Trying to optimize texture mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="23413" PostHistoryTypeId="3" PostId="8661" RevisionGUID="5f0c1e22-8024-4377-8c50-44751760890b" CreationDate="2019-03-07T15:41:08.497" UserId="10286" Text="|texture|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23415" PostHistoryTypeId="2" PostId="8662" RevisionGUID="7c0e4e3f-cc32-400a-9c3e-952c051fefda" CreationDate="2019-03-07T18:02:09.673" UserId="7462" Text="Many hair simulations render their hair as lines (usually splines). Since hair is a really think object.&#xD;&#xA;&#xD;&#xA;However if the hair is braided, rather than having thin infinitesimally small cylinders, you have something much thicker and with more volume per individual strand.&#xD;&#xA;&#xD;&#xA;The line method is relatively efficient, since lines are computationally cheap to render.&#xD;&#xA;&#xD;&#xA;However for braids it would seem you would need triangles, which would imply a high concentration of really small triangles on each individual braid, which sounds very expensive.&#xD;&#xA;&#xD;&#xA;Are there any algorithms that attempt at dealing with this issue? Particularily ones that are good at trading quality for speed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23416" PostHistoryTypeId="1" PostId="8662" RevisionGUID="7c0e4e3f-cc32-400a-9c3e-952c051fefda" CreationDate="2019-03-07T18:02:09.673" UserId="7462" Text="How would you model braids?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23417" PostHistoryTypeId="3" PostId="8662" RevisionGUID="7c0e4e3f-cc32-400a-9c3e-952c051fefda" CreationDate="2019-03-07T18:02:09.673" UserId="7462" Text="|rendering|mesh|model|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23418" PostHistoryTypeId="5" PostId="8662" RevisionGUID="ec7f905b-48c9-46b9-9d88-85721a32d0da" CreationDate="2019-03-07T18:21:51.097" UserId="7462" Comment="added 8 characters in body" Text="Many hair simulations render their hair as lines (usually splines). Since hair is a really think object.&#xD;&#xA;&#xD;&#xA;However if the hair is braided, rather than having thin infinitesimally small cylinders, you have something much thicker and with more volume per individual strand.&#xD;&#xA;&#xD;&#xA;The line method is relatively efficient, since lines are computationally cheap to render.&#xD;&#xA;&#xD;&#xA;However for braids it would seem you would need triangles, which would imply a high concentration of really small triangles on each individual braid, which sounds very expensive.&#xD;&#xA;&#xD;&#xA;Are there any algorithms that attempt at dealing with this issue? Particularily ones that are good at trading quality for memory useage?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23419" PostHistoryTypeId="2" PostId="8663" RevisionGUID="c0ede62f-e4cb-4c7e-9bfd-253bdd101b86" CreationDate="2019-03-07T22:42:40.907" UserId="10117" Text="I've seen no answer to my question. But after lots of experimentation and further study of Apple documentation for clues I have figured out how to capture GPU generated frames.&#xD;&#xA;&#xD;&#xA;First, I gave up on the attempt to have the shader write to the screen and an offscreen buffer in the same render pass. The odd (and undocumented as far as I can tell) behavior of MTKView in which the onscreen view occupies only a portion of the original area of the screen. I think this a bug in MTKView. It seems to act as if each attachment should appear somewhere on the screen. MTKView is not checking to see if the attachments are all on the screen.&#xD;&#xA;&#xD;&#xA;Since MTKView calls the draw() function 60 times per second I decided to alternate. One draw() goes to the screen and the following draw() goes to my off screen buffer. This gives me a 30 Hz frame rate for the captured video frames, which is what I wanted anyway. I can watch the screen and see what will appear in the video.&#xD;&#xA;&#xD;&#xA;For the video capture draw() calls I now define the MTLTextureDescriptor in this way:&#xD;&#xA;     &#xD;&#xA;&#xD;&#xA;    let offScreenPixelFormat = MTLPixelFormat.rgba32Float   // 32Float is convenient for AVFoundation video recording&#xD;&#xA;    let offScreenBufferDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: offScreenPixelFormat,&#xD;&#xA;              width: offW, height: offH, mipmapped: false)&#xD;&#xA;    offScreenBufferDescriptor.usage = [.shaderWrite, .renderTarget]&#xD;&#xA;    offScreenBufferDescriptor.storageMode = .managed&#xD;&#xA;    offScreenBufferDescriptor.resourceOptions = [.storageModeManaged]&#xD;&#xA;    offScreenBufferDescriptor.textureType = MTLTextureType.type2D&#xD;&#xA;    offScreenTextureBuffer = device.makeTexture(descriptor:    offScreenBufferDescriptor)&#xD;&#xA;&#xD;&#xA;It turns out this still did not work. I got nothing back from the GPU. That is, I got nothing back until I added this code to the end of the commandBuffer:&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      let blitCommandEncoder = commandBuffer.makeBlitCommandEncoder()&#xD;&#xA;      blitCommandEncoder?.synchronize(resource: offScreenTextureBuffer!)&#xD;&#xA;      blitCommandEncoder?.endEncoding()&#xD;&#xA;&#xD;&#xA;This causes the GPU memory version of the offScreenTextureBuffer to be copied back to the CPU memory version. I figured this out by looking at the Apple documentation. Like all Apple documentation, it doesn't tell you why you might want to synchronize. But you definitely do need to do this. I have seen several online code examples where this is NOT done and they claim to get data back from the GPU.&#xD;&#xA;I tried one example code without the synchronize command and nothing was returned. So I assume the requirement to synchronize is a new feature and the online code is just out of date. It would be nice if the Apple documentation made it clear this is now a requirement.&#xD;&#xA;&#xD;&#xA;With these changes I can retrieve GPU frames. I have created a short video using GPU-generated frames.&#xD;&#xA;&#xD;&#xA;If anyone is interested in seeing a complete code sample let me know.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23420" PostHistoryTypeId="5" PostId="8662" RevisionGUID="715374f6-1f93-498a-9569-41b770bf98e3" CreationDate="2019-03-07T22:49:44.827" UserId="7462" Comment="deleted 1 character in body" Text="Many hair simulations render their hair as lines (usually splines). Since hair is a really thin object.&#xD;&#xA;&#xD;&#xA;However if the hair is braided, rather than having thin infinitesimally small cylinders, you have something much thicker and with more volume per individual strand.&#xD;&#xA;&#xD;&#xA;The line method is relatively efficient, since lines are computationally cheap to render.&#xD;&#xA;&#xD;&#xA;However for braids it would seem you would need triangles, which would imply a high concentration of really small triangles on each individual braid, which sounds very expensive.&#xD;&#xA;&#xD;&#xA;Are there any algorithms that attempt at dealing with this issue? Particularily ones that are good at trading quality for memory useage?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23421" PostHistoryTypeId="6" PostId="8648" RevisionGUID="4af94a54-aaf4-453e-849c-fcb63144a660" CreationDate="2019-03-08T16:27:44.377" UserId="2479" Comment="Added real-time flag" Text="|real-time|shading|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23422" PostHistoryTypeId="24" PostId="8648" RevisionGUID="4af94a54-aaf4-453e-849c-fcb63144a660" CreationDate="2019-03-08T16:27:44.377" Comment="Proposed by 2479 approved by 209, 10254 edit id of 463" ContentLicense="CC BY-SA 4.0" />
  <row Id="23423" PostHistoryTypeId="2" PostId="8664" RevisionGUID="e2548d27-0c9f-4edf-b1cd-b00e8856dbfb" CreationDate="2019-03-08T18:05:11.350" UserId="10129" Text="I am creating Forward-Rendering DX11 engine and I have some troubles with shadow-mapping algorithm as it doesn't work as supposed.&#xD;&#xA;&#xD;&#xA;[![Shadowmap texture][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Rendered scene][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N2ZcY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ehipa.png&#xD;&#xA;&#xD;&#xA;As you can see - shadow is peter-panning and looks totally not releated. Basically as I have tested, comparision in PixelShader has no effect. Only projected shadowmap texture is returned, *if statement* doesn't do anything.&#xD;&#xA;&#xD;&#xA;**MyVertexShader:**&#xD;&#xA;&#xD;&#xA;    PixelInputType ColorVertexShader(VertexInputType input)&#xD;&#xA;    {&#xD;&#xA;		PixelInputType output;&#xD;&#xA;		float4 worldPosition;&#xD;&#xA;&#xD;&#xA;		input.position.w = 1.0f;&#xD;&#xA;		worldPosition = mul(input.position, worldMatrix);&#xD;&#xA;		output.normal = input.normal;&#xD;&#xA;&#xD;&#xA;		// Calculate the position of the vertex against the world, view, and projection matrices.&#xD;&#xA;		output.position = mul(input.position, worldMatrix);&#xD;&#xA;		output.position = mul(output.position, viewMatrix);&#xD;&#xA;		output.position = mul(output.position, projectionMatrix);&#xD;&#xA;&#xD;&#xA;		//Calculate object seen by light&#xD;&#xA;		output.lightViewPosition = mul(input.position, worldMatrix);&#xD;&#xA;		output.lightViewPosition = mul(output.lightViewPosition, g_lightViewMatrix);&#xD;&#xA;		output.lightViewPosition = mul(output.lightViewPosition, g_lightProjectionMatrix);&#xD;&#xA;&#xD;&#xA;		//Calculate light-object vector&#xD;&#xA;		output.lightPos = g_lightPosition.xyz - worldPosition.xyz;&#xD;&#xA;		output.lightPos = normalize(output.lightPos);&#xD;&#xA;&#xD;&#xA;		return output;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**MyPixelShader:**&#xD;&#xA;&#xD;&#xA;    float4 ColorPixelShader(PixelInputType input) : SV_TARGET&#xD;&#xA;	{&#xD;&#xA;		float4 color = float4(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;		float depthValue;&#xD;&#xA;		float lightDepthValue;&#xD;&#xA;		float bias = 0.001f;&#xD;&#xA;		float4 textureColor = float4(1.0, 1.0, 1.0, 1.0);&#xD;&#xA;		float4 ambientColor = float4(1.0, 0.0, 1.0, 1.0);&#xD;&#xA;		float2 tex;&#xD;&#xA;		float lightIntensity = 0.0f;&#xD;&#xA;&#xD;&#xA;		input.lightViewPosition.xyz /= input.lightViewPosition.w;&#xD;&#xA;&#xD;&#xA;		tex.x = input.lightViewPosition.x / 2.0f + 0.5f;&#xD;&#xA;		tex.y = -input.lightViewPosition.y / 2.0f + 0.5f;&#xD;&#xA;	&#xD;&#xA;		return depthValue = shadowMap.Sample(SampleType, tex).r;&#xD;&#xA;		color = float4(depthValue, depthValue, depthValue, 1.0f);&#xD;&#xA;	&#xD;&#xA;		lightDepthValue = input.lightViewPosition.z;// / input.lightViewPosition.w;&#xD;&#xA;		lightDepthValue = lightDepthValue - bias;&#xD;&#xA;		if(lightDepthValue &lt; depthValue)&#xD;&#xA;		{&#xD;&#xA;			lightIntensity = saturate(dot(input.normal, input.lightPos));&#xD;&#xA;&#xD;&#xA;			if(lightIntensity &gt; 0.0f)&#xD;&#xA;			{&#xD;&#xA;				// Determine the final diffuse color based on the diffuse color and the amount of light intensity.&#xD;&#xA;				color += (ambientColor * lightIntensity);&#xD;&#xA;&#xD;&#xA;				// Saturate the final light color.&#xD;&#xA;				color = saturate(color);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		return color;&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="23424" PostHistoryTypeId="1" PostId="8664" RevisionGUID="e2548d27-0c9f-4edf-b1cd-b00e8856dbfb" CreationDate="2019-03-08T18:05:11.350" UserId="10129" Text="ShadowMap peter-panning and wrong direction" ContentLicense="CC BY-SA 4.0" />
  <row Id="23425" PostHistoryTypeId="3" PostId="8664" RevisionGUID="e2548d27-0c9f-4edf-b1cd-b00e8856dbfb" CreationDate="2019-03-08T18:05:11.350" UserId="10129" Text="|shadow|directx11|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23428" PostHistoryTypeId="2" PostId="8666" RevisionGUID="3740cab6-5428-417f-ab1d-8fe939063110" CreationDate="2019-03-09T00:55:35.870" UserId="10290" Text="I'm interested in simulating the way a laser line deforms when it strikes an object and runs along the surface of it. Which concepts would be involved? Is there any 3D modeling software out there that does this already? I'd like to implement it into my Eyeshot-based program at some point." ContentLicense="CC BY-SA 4.0" />
  <row Id="23429" PostHistoryTypeId="1" PostId="8666" RevisionGUID="3740cab6-5428-417f-ab1d-8fe939063110" CreationDate="2019-03-09T00:55:35.870" UserId="10290" Text="How to simulate a line laser diode?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23430" PostHistoryTypeId="3" PostId="8666" RevisionGUID="3740cab6-5428-417f-ab1d-8fe939063110" CreationDate="2019-03-09T00:55:35.870" UserId="10290" Text="|raytracing|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23433" PostHistoryTypeId="2" PostId="8667" RevisionGUID="c10f4847-ccbd-4490-b994-d02b58391cae" CreationDate="2019-03-10T13:09:01.627" UserId="6407" Text="The [article](https://anteru.net/blog/2018/intro-to-compute-shaders/index.html) says that L1 cache is shared by work items in the same work group(aka. SM) and L2 cache is shared by different work groups.&#xD;&#xA;&#xD;&#xA;In Direct3D, it seems that a thread group (which is specified by `numthread(x, y, z)`) is mapped to multi work groups, and `groupshared` could be accessed by all threads of the thread group (which belong to different work groups).&#xD;&#xA;&#xD;&#xA;So, is `groupshared` the L2 cache of GPU? If it is, could I manipulate L1 cache directly in Direct3D?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23434" PostHistoryTypeId="1" PostId="8667" RevisionGUID="c10f4847-ccbd-4490-b994-d02b58391cae" CreationDate="2019-03-10T13:09:01.627" UserId="6407" Text="Is `groupshared` memory stored in L2 cache of GPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23435" PostHistoryTypeId="3" PostId="8667" RevisionGUID="c10f4847-ccbd-4490-b994-d02b58391cae" CreationDate="2019-03-10T13:09:01.627" UserId="6407" Text="|directx11|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23436" PostHistoryTypeId="2" PostId="8668" RevisionGUID="4d5fd93c-2290-4d46-8583-101f33d1cd5c" CreationDate="2019-03-10T17:28:59.783" UserId="9812" Text="There seems to be some confusion of terminology here. In Direct3D, you have *threads* and *thread groups*. &quot;work item&quot; and &quot;work group&quot; are generally encountered in OpenCL terminology, where a &quot;work item&quot; would be what a *thread* is in Direct3D and a &quot;work group&quot; corresponds to a Direct3D *thread group*. `groupshared` memory is memory accessible to all threads that are part of the same thread group.&#xD;&#xA;&#xD;&#xA;It is unclear what exactly you mean by &quot;manipulating L1 cache directly&quot;. A cache is a hardware component that is used to transparently optimize memory access. The word &quot;transparent&quot; is crucial here. While, at the hardware level, caches necessarily contain some form of memory, they are generally not explicitly &quot;accessible&quot; as a region of storage. You can't have a pointer that points into a cache. You can have a pointer that points into memory. Memory accesses will typically go through a cache, i.e., any memory request will be handed off to the next cache, which can then check whether it can serve the request directly or has to go further down the memory hierarchy. There's more to a cache than just the memory it uses to cache stuff. A cache also contains additional logic for managing the cache on top of just the storage itself. Caches are implicit by nature. As you manipulate memory, you will often also cause some caches to manipulate themselves along the way. But you generally can't &quot;manipulate&quot; a cache directly in the sense of explicitly defining what is when to be stored where in the cache. As soon as you can explicitly point into it and read/write from/to it, it kinda stops being a cache and starts being just some form of storage. &#xD;&#xA;&#xD;&#xA;That being said, `groupshared` memory is generally located in fast on-chip storage just like caches are. The whole point of `groupshared` memory is to take advantage of the knowledge that certain threads reside on the same part of the chip to allow them to communicate faster. And on some hardware (e.g., most current NVIDIA architecture), `groupshared` memory and the L1 cache will actually use the same physical memory. However, that just means that one part of that memory is used as &quot;normal&quot; memory, accessed directly via addressing through some memory controller, while another part is used by the L1 to cache stuff&amp;hellip;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23437" PostHistoryTypeId="5" PostId="8668" RevisionGUID="7a202f51-16b1-4397-97ef-ab0274f7a971" CreationDate="2019-03-10T17:36:02.910" UserId="9812" Comment="added 10 characters in body" Text="There seems to be some confusion of terminology here. In Direct3D, you have *threads* and *thread groups*. &quot;work item&quot; and &quot;work group&quot; are generally encountered in OpenCL terminology, where a &quot;work item&quot; would be what a *thread* is in Direct3D and a &quot;work group&quot; corresponds to a Direct3D *thread group*. `groupshared` memory is memory accessible to all threads that are part of the same thread group.&#xD;&#xA;&#xD;&#xA;It is unclear what exactly you mean by &quot;manipulating L1 cache directly&quot;. A cache is a hardware component that is used to transparently optimize memory access. The word &quot;transparent&quot; is crucial here. While, at the hardware level, caches necessarily contain some form of memory, they are generally not explicitly &quot;accessible&quot; as a region of storage. You can't have a pointer that points into a cache. You can have a pointer that points into memory. Memory accesses will typically go through a cache, i.e., any memory request will be handed off to the next cache, which can then check whether it can serve the request directly or has to go further down the memory hierarchy. There's more to a cache than just the memory it uses to cache stuff. A cache also contains additional logic for managing the cache on top of just the storage itself. Caches are implicit by nature. As you manipulate memory, you will typically also cause some caches to manipulate themselves along the way. But you generally can't &quot;manipulate&quot; a cache directly in the sense of explicitly defining what is when to be stored where in the cache. As soon as you can explicitly point into it and read/write from/to it, it kinda stops being a cache and starts being just some form of storage. &#xD;&#xA;&#xD;&#xA;That being said, `groupshared` memory is generally located in fast on-chip storage just like caches are. The whole point of `groupshared` memory is to take advantage of the knowledge that certain threads reside on the same part of the chip to allow them to communicate faster. And on some hardware (e.g., most of the recent NVIDIA architectures), `groupshared` memory and the L1 cache will actually use the same physical memory. However, that just means that one part of that memory is used as &quot;normal&quot; memory, accessed directly via addressing through some memory controller, while another part is used by the L1 cache to cache stuff&amp;hellip;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23438" PostHistoryTypeId="5" PostId="8668" RevisionGUID="19b0f451-0437-4e94-af0f-aaa8142bcbc8" CreationDate="2019-03-10T18:25:03.637" UserId="9812" Comment="added 2 characters in body" Text="There seems to be some confusion of terminology here. In Direct3D, you have *threads* and *thread groups*. &quot;work item&quot; and &quot;work group&quot; are generally encountered in OpenCL terminology, where a &quot;work item&quot; would be what a *thread* is in Direct3D and a &quot;work group&quot; corresponds to a Direct3D *thread group*. `groupshared` memory is memory accessible to all threads that are part of the same thread group.&#xD;&#xA;&#xD;&#xA;It is unclear what exactly you mean by &quot;manipulating L1 cache directly&quot;. A cache is a hardware component that is used to transparently optimize memory access. The word &quot;transparent&quot; is crucial here. While, at the hardware level, caches necessarily contain some form of memory, they are generally not explicitly &quot;accessible&quot; as a region of storage. You can't have a pointer that points into a cache. You can have a pointer that points into memory. Memory accesses will typically go through a cache, i.e., any memory request will be handed off to the next cache, which can then check whether it can serve the request directly or has to go further down the memory hierarchy. There's more to a cache than just the memory it uses to cache stuff. A cache also contains additional logic for managing the cache on top of just the storage itself. Caches are implicit by nature. As you manipulate memory, you will typically also cause some caches to manipulate their memory along the way. But you generally can't &quot;manipulate&quot; a cache directly in the sense of explicitly defining what is when to be stored where in the cache. As soon as you can explicitly point into it and read/write from/to it, it kinda stops being a cache and starts being just some form of storage. &#xD;&#xA;&#xD;&#xA;That being said, `groupshared` memory is generally located in fast on-chip storage just like caches are. The whole point of `groupshared` memory is to take advantage of the knowledge that certain threads reside on the same part of the chip to allow them to communicate faster. And on some hardware (e.g., most of the recent NVIDIA architectures), `groupshared` memory and the L1 cache will actually use the same physical memory. However, that just means that one part of that memory is used as &quot;normal&quot; memory, accessed directly via addressing through some memory controller, while another part is used by the L1 cache to cache stuff&amp;hellip;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23439" PostHistoryTypeId="50" PostId="8562" RevisionGUID="1c96ff79-6000-4b5f-a5cd-dc9cf5e52ab2" CreationDate="2019-03-10T22:02:05.400" UserId="-1" />
  <row Id="23440" PostHistoryTypeId="5" PostId="8668" RevisionGUID="9c12dc2c-abc5-4ba0-a988-111fb6f05d6a" CreationDate="2019-03-11T00:37:35.983" UserId="9812" Comment="deleted 2 characters in body" Text="There seems to be some confusion of terminology here. In Direct3D, you have *threads* and *thread groups*. &quot;work item&quot; and &quot;work group&quot; are generally encountered in OpenCL terminology, where a &quot;work item&quot; would be what a *thread* is in Direct3D and a &quot;work group&quot; corresponds to a Direct3D *thread group*. `groupshared` memory is memory accessible to all threads that are part of the same thread group.&#xD;&#xA;&#xD;&#xA;It is unclear what exactly you mean by &quot;manipulating L1 cache directly&quot;. A cache is a hardware component that is used to transparently optimize memory access. The word &quot;transparent&quot; is crucial here. While, at the hardware level, caches necessarily contain some form of memory, they are generally not explicitly &quot;accessible&quot; as a region of storage. You can't have a pointer that points into a cache. You can have a pointer that points into memory. Memory accesses will typically go through a cache, i.e., any memory request will be handed off to the next cache, which can then check whether it can serve the request directly or has to go further down the memory hierarchy. There's more to a cache than just the memory it uses to cache stuff. A cache also contains additional logic for managing the cache on top of just the storage itself. Caches are implicit by nature. As you manipulate memory, you will typically also cause some caches to manipulate their memory along the way. But you generally can't &quot;manipulate&quot; a cache directly in the sense of explicitly defining what is when to be stored where in the cache. As soon as you can explicitly point into it and read/write from/to it, it kinda stops being a cache and starts being just some form of storage. &#xD;&#xA;&#xD;&#xA;That being said, `groupshared` memory is generally located in fast on-chip storage just like caches are. The whole point of `groupshared` memory is to take advantage of the knowledge that certain threads reside on the same part of the chip to allow them to communicate faster. And on some hardware (e.g., most of the recent NVIDIA architectures), `groupshared` memory and the L1 cache will actually use the same physical memory. However, that just means that one part of that memory is used as &quot;normal&quot; memory, accessed directly via addressing through some load-store-unit, while another part is used by the L1 cache to cache stuff&amp;hellip;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23441" PostHistoryTypeId="2" PostId="8669" RevisionGUID="3b7458e3-4cd8-488b-ba7d-8d03d6c368be" CreationDate="2019-03-11T11:36:28.750" UserId="137" Text="It's a variant to [projective texture mapping][1]. &#xD;&#xA;&#xD;&#xA;The simple way to do this in the fragment shader by using the position of the fragment to decide whether it is close enough to the plane of the laser to light up.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_texture_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="23442" PostHistoryTypeId="6" PostId="8061" RevisionGUID="817cb108-e2b2-435c-aa28-9967532d8b86" CreationDate="2019-03-12T18:00:12.147" UserId="7247" Comment="Edited tags: -Unity (question non specific to Unity) +Lighting (normals are normally used for lighting)" Text="|shader|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23443" PostHistoryTypeId="24" PostId="8061" RevisionGUID="817cb108-e2b2-435c-aa28-9967532d8b86" CreationDate="2019-03-12T18:00:12.147" Comment="Proposed by 7247 approved by -1 edit id of 464" ContentLicense="CC BY-SA 4.0" />
  <row Id="23444" PostHistoryTypeId="5" PostId="8061" RevisionGUID="bce53ff7-f50a-42bf-a739-ce297c80b463" CreationDate="2019-03-12T18:00:12.147" UserId="6" Comment="Edited tags: -Unity (question non specific to Unity) +Lighting (normals are normally used for lighting)" Text="I am learning about normal mapping. I understood that RGB values are converted into XYZ, but my question is **how is it converted and why is the normal map blue and purple in color?** " ContentLicense="CC BY-SA 4.0" />
  <row Id="23445" PostHistoryTypeId="4" PostId="8061" RevisionGUID="bce53ff7-f50a-42bf-a739-ce297c80b463" CreationDate="2019-03-12T18:00:12.147" UserId="6" Comment="Edited tags: -Unity (question non specific to Unity) +Lighting (normals are normally used for lighting)" Text="Why are normal maps is blue and purple in color?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23449" PostHistoryTypeId="4" PostId="8061" RevisionGUID="a4a9c279-29a1-4043-ab43-f3016b360513" CreationDate="2019-03-13T09:38:56.167" UserId="209" Comment="Just fixed title's grammar" Text="Why are normal maps blue and purple in color?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23450" PostHistoryTypeId="2" PostId="8671" RevisionGUID="8e3f26a2-2301-449d-a345-aea58f96b374" CreationDate="2019-03-13T17:57:25.150" UserId="10129" Text="I found out that simply removing minus sign in shader in converting coords to [0, 1] solved direction problem. But scale is still off - here is an example:&#xD;&#xA;&#xD;&#xA;[![Wrong scale - peter panning][1]][1]&#xD;&#xA;&#xD;&#xA;    void LightClass::GenerateViewMatrix()&#xD;&#xA;    {&#xD;&#xA;    	XMVECTOR eyePos = { m_position.x, m_position.y, m_position.z };&#xD;&#xA;    	XMVECTOR focusPos = { m_lookAt.x, m_lookAt.y, m_lookAt.z };&#xD;&#xA;    	XMVECTOR upVec = { 0, 1, 0 };&#xD;&#xA;    &#xD;&#xA;    	m_viewMatrix = XMMatrixLookAtLH(eyePos, focusPos, upVec);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void LightClass::GenerateProjectionMatrix(float screenDepth, float screenNear)&#xD;&#xA;    {&#xD;&#xA;    	float fieldOfView = (float)3.14f / 2.0f;&#xD;&#xA;    	float screenAspect = 16.0f / 9.0f;&#xD;&#xA;    &#xD;&#xA;    	m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v6lK0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23451" PostHistoryTypeId="2" PostId="8672" RevisionGUID="6eca00ff-6039-4965-b297-067c518b6756" CreationDate="2019-03-13T19:23:22.000" UserId="10307" Text="I have no prior experience with any other graphics low level libraries and I have barely any clue how shaders work, any book related to shadings is bloated with opengl code and is demoralizing." ContentLicense="CC BY-SA 4.0" />
  <row Id="23452" PostHistoryTypeId="1" PostId="8672" RevisionGUID="6eca00ff-6039-4965-b297-067c518b6756" CreationDate="2019-03-13T19:23:22.000" UserId="10307" Text="Where should I learn shaders as a vulkan user?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23453" PostHistoryTypeId="3" PostId="8672" RevisionGUID="6eca00ff-6039-4965-b297-067c518b6756" CreationDate="2019-03-13T19:23:22.000" UserId="10307" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23459" PostHistoryTypeId="2" PostId="8674" RevisionGUID="7ed2ff80-a355-453e-be6f-35187e9c49db" CreationDate="2019-03-14T06:28:48.133" UserId="9908" Text="Perhaps you should begin with classic opengl shaders in a more friendly enviroment. [ShaderToy](https://www.shadertoy.com/) is a great community where you'll find tons of tutorials, code examples, masterpieces and great experts that comment everyday." ContentLicense="CC BY-SA 4.0" />
  <row Id="23466" PostHistoryTypeId="5" PostId="8671" RevisionGUID="c98cc921-7cac-423c-849b-60c571be24ea" CreationDate="2019-03-14T18:03:04.743" UserId="10129" Comment="Added correct answer to the question" Text="I found out that simply removing minus sign in shader in converting coords to [0, 1] solved direction problem. But scale is still off - here is an example:&#xD;&#xA;&#xD;&#xA;[![Wrong scale - peter panning][1]][1]&#xD;&#xA;&#xD;&#xA;    void LightClass::GenerateViewMatrix()&#xD;&#xA;    {&#xD;&#xA;    	XMVECTOR eyePos = { m_position.x, m_position.y, m_position.z };&#xD;&#xA;    	XMVECTOR focusPos = { m_lookAt.x, m_lookAt.y, m_lookAt.z };&#xD;&#xA;    	XMVECTOR upVec = { 0, 1, 0 };&#xD;&#xA;    &#xD;&#xA;    	m_viewMatrix = XMMatrixLookAtLH(eyePos, focusPos, upVec);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void LightClass::GenerateProjectionMatrix(float screenDepth, float screenNear)&#xD;&#xA;    {&#xD;&#xA;    	float fieldOfView = (float)3.14f / 2.0f;&#xD;&#xA;    	float screenAspect = 16.0f / 9.0f;&#xD;&#xA;    &#xD;&#xA;    	m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit [Actual solution - ignore previous posts]:**&#xD;&#xA;&#xD;&#xA;I followed PaulHK solution (thanks, it's second time you've helped me) about checking once again View/Projection matrix. Basically my calculations were wrong. I debugged my convertions from model to lightspace and changed **Vertex Shader** from:&#xD;&#xA;&#xD;&#xA;	output.lightViewPosition = mul(input.position, worldMatrix);&#xD;&#xA;	output.lightViewPosition = mul(output.lightViewPosition, g_lightViewMatrix);&#xD;&#xA;	output.lightViewPosition = mul(output.lightViewPosition, g_lightProjectionMatrix);&#xD;&#xA;To correct:&#xD;&#xA;&#xD;&#xA;	matrix lightViewProj = mul(g_lightProjectionMatrix, g_lightViewMatrix);&#xD;&#xA;	output.lightViewPosition = mul(input.position, lightViewProj);&#xD;&#xA;&#xD;&#xA;That simple changed fixed my results. With simple **Pixel shader** code below I am getting this results:&#xD;&#xA;&#xD;&#xA;    input.lightViewPosition.xyz /= input.lightViewPosition.w;&#xD;&#xA;&#xD;&#xA;    tex.x = input.lightViewPosition.x / 2.0f + 0.5f;&#xD;&#xA;    tex.y = -input.lightViewPosition.y / 2.0f + 0.5f;&#xD;&#xA;&#xD;&#xA;    depthValue = shadowMap.Sample(SampleType, tex).r;&#xD;&#xA;    return color = float4(depthValue, depthValue, depthValue, 1.0f);&#xD;&#xA;&#xD;&#xA;[![Correct shadow-map][2]][2]&#xD;&#xA;However, even if it seems correct, my suspicion is that I need to compare my shadowmap to light Z-buffer so I modified my Pixel Shader and added little tint:&#xD;&#xA;&#xD;&#xA;    input.lightViewPosition.xyz /= input.lightViewPosition.w;&#xD;&#xA;&#xD;&#xA;    tex.x = input.lightViewPosition.x / 2.0f + 0.5f;&#xD;&#xA;    tex.y = -input.lightViewPosition.y / 2.0f + 0.5f;&#xD;&#xA;&#xD;&#xA;    depthValue = shadowMap.Sample(SampleType, tex).r;&#xD;&#xA;    color = float4(depthValue, depthValue, depthValue, 1.0f);&#xD;&#xA;&#xD;&#xA;    lightDepthValue = input.lightViewPosition.z - bias;&#xD;&#xA;    if(lightDepthValue &lt; depthValue)&#xD;&#xA;    {&#xD;&#xA;        lightIntensity = saturate(dot(input.normal, input.lightPos));&#xD;&#xA;&#xD;&#xA;        if(lightIntensity &gt; 0.0f)&#xD;&#xA;        {&#xD;&#xA;            // Determine the final diffuse color based on the diffuse color and the amount of light intensity.&#xD;&#xA;            color += (ambientColor * lightIntensity);&#xD;&#xA;&#xD;&#xA;            // Saturate the final light color.&#xD;&#xA;            color = saturate(color);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    return color;&#xD;&#xA;&#xD;&#xA;I may not be right, but without this checking, you would get errors with more complicated shadows. Because my previous PixelShader code basically just project shadowmap on plane without any actual depth checking. Therefore it would lay shadowmap on everything it can without even checking if that's correct.&#xD;&#xA;&#xD;&#xA;[![Correct shadow-map with depth checking][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v6lK0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ylu0o.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/X5fzu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23467" PostHistoryTypeId="2" PostId="8676" RevisionGUID="089cbc45-ca6f-427e-ae58-3f59928f50e4" CreationDate="2019-03-14T20:13:19.960" UserId="10191" Text="I am following the &lt;b&gt;&quot;Ray Tracing - the Rest of your Life&quot;&lt;/b&gt; book by Peter Shirley and I am facing some troubles in the implementation of Monte Carlo importance sampling, and  Direct light sampling.&lt;br&gt;&#xD;&#xA;Monte Carlo theory is clear to me. During the implementation, the way rays are scattered does not actually change and remains random. What changes looks to be the contribution of each ray.&lt;br&gt;&#xD;&#xA;So my first question is:&lt;br&gt;&lt;br&gt;&#xD;&#xA;&lt;i&gt;Do I understand this correctly? Rays, after hitting a surface, are still scattered randomly, but the value of the color is adjusted based on the probability of that direction?&lt;/i&gt;&#xD;&#xA;&#xD;&#xA;&lt;b&gt;For those familiar with the book&lt;/b&gt; &lt;br&gt;&#xD;&#xA;When the author implements the Direct light sampling, he modifies the function &lt;i&gt;color()&lt;/i&gt;, while we previously modified &lt;i&gt;scatter()&lt;/i&gt; and &lt;i&gt;scattering_pdf()&lt;/i&gt;. This way, &lt;i&gt;scatter()&lt;/i&gt; and &lt;i&gt;scattering_pdf()&lt;/i&gt; are sampling based on a specific pdf - proportional to cos(theta) - while &lt;i&gt;color()&lt;/i&gt; introduces a new pdf related to the direction of the light. It is not clear to me how these two things coexist, and if I am supposed to disregard the previous changes to &lt;i&gt;scatter()&lt;/i&gt; and &lt;i&gt;scattering_pdf()&lt;/i&gt;.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23468" PostHistoryTypeId="1" PostId="8676" RevisionGUID="089cbc45-ca6f-427e-ae58-3f59928f50e4" CreationDate="2019-03-14T20:13:19.960" UserId="10191" Text="Monte Carlo Importance Sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="23469" PostHistoryTypeId="3" PostId="8676" RevisionGUID="089cbc45-ca6f-427e-ae58-3f59928f50e4" CreationDate="2019-03-14T20:13:19.960" UserId="10191" Text="|raytracing|c++|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23470" PostHistoryTypeId="2" PostId="8677" RevisionGUID="96de845d-f85f-4765-93d9-9be44ab923aa" CreationDate="2019-03-15T17:14:32.567" UserId="10319" Text="I know this question may be a little basic, but still I haven't found an answer for it anywhere.&#xD;&#xA;&#xD;&#xA;Let's say I have a normalized cube; vertices at (+-0.5, +-0.5, +-0.5)&#xD;&#xA;If I render it on screen (omitting the Z axis), I'll see a square.&#xD;&#xA;&#xD;&#xA;If I rotate it along the Z axis with 45 degrees, I'll see two rectangles:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, I would like to see it with perspective, so it should look something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the matrix multiplication that transfers the original points to the rotated+perspective points?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EulxU.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/4bxmR.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23471" PostHistoryTypeId="1" PostId="8677" RevisionGUID="96de845d-f85f-4765-93d9-9be44ab923aa" CreationDate="2019-03-15T17:14:32.567" UserId="10319" Text="Simple Two Point Perspective of a Cube" ContentLicense="CC BY-SA 4.0" />
  <row Id="23472" PostHistoryTypeId="3" PostId="8677" RevisionGUID="96de845d-f85f-4765-93d9-9be44ab923aa" CreationDate="2019-03-15T17:14:32.567" UserId="10319" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23473" PostHistoryTypeId="2" PostId="8678" RevisionGUID="909e11c0-309f-43f5-97c4-509709a65141" CreationDate="2019-03-15T18:08:01.363" UserId="10096" Text="Your first image employs an orthographics projection, while the second uses a perspective projection. You can look up the perspective matrix derivation in: http://www.songho.ca/opengl/gl_projectionmatrix.html Note that there's a division at the end to account for perspective projection being a non-linear transformation." ContentLicense="CC BY-SA 4.0" />
  <row Id="23475" PostHistoryTypeId="2" PostId="8679" RevisionGUID="268d1be8-dada-47e9-9c14-d6c6c31f7555" CreationDate="2019-03-15T22:06:21.530" UserId="10096" Text="&gt; During the implementation, the way rays are scattered does not actually change and remains random.&#xD;&#xA;&#xD;&#xA;Actually the way rays are scattered does change, specifically when you sample a light. In chapter 8 he makes a mixture pdf in order to sample either the light or the bsdf.&#xD;&#xA;&#xD;&#xA;&gt; What changes looks to be the contribution of each ray.&#xD;&#xA;&#xD;&#xA;This does change, but not specifically due to the sampling of the lights but rather due to importance sampling. But that was already introduced in chapter 4.&#xD;&#xA;&#xD;&#xA;Basically you have the following:&#xD;&#xA;$$I = \int_{\Omega}f(x)\,dx = \int_{\Omega}\frac{f(x)}{p(x)}p(x)\,dx = E\left[\frac{f(X)}{p(X)}\right] = \frac{1}{N}\sum_{i=1}^{N}E\left[\frac{f(X_i)}{p(X_i)}\right] \approx \frac{1}{N}\sum_{i=1}^{N}\frac{f(x_i)}{p(x_i)}$$&#xD;&#xA;Where $X$ and $X_i$ are distributed according to the probability density $p$.&#xD;&#xA;As evident the main difference to the Monte Carlo formulation you are probably used to is the $p(x)$ factor, and the fact that $x_i$ are not uniformly sampled but rather sampled according to $p$. Note that for uniform sampling $p(x)=1$ and the equality still holds. Thus this is simply a generalization." ContentLicense="CC BY-SA 4.0" />
  <row Id="23480" PostHistoryTypeId="5" PostId="4434" RevisionGUID="b9d3e167-7923-4f11-8251-d528e424e921" CreationDate="2019-03-16T20:09:59.560" UserId="-1" Comment="Added mention of D3D12 render passes" Text="Here's a non-exhaustive list of Vulkan and DirectX 12. This is cobbled together using criteria similar to that of Nathan's.&#xD;&#xA;&#xD;&#xA;Overall both APIs are surprisingly similar. Things like shader stages remain unchanged from DX11 and OpenGL. And obviously, DirectX uses views to make things visible to shaders. Vulkan also uses views, but they are less frequent.&#xD;&#xA;&#xD;&#xA;Shader visibility behavior differs a bit between the two. Vulkan uses a mask to determine if a descriptor is visible to the various shader stages. DX12 handles this a little differently, resource visibility is either done on single stage or all stages.&#xD;&#xA;&#xD;&#xA;I broke the descriptor set / root parameter stuff down best I could. Descriptor handling is one of the areas that vary greatly between the two APIs. However, the end result is fairly similar.&#xD;&#xA;&#xD;&#xA;**API Basics**&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    n/a                                 IDXGIFactory4&#xD;&#xA;    VkInstance                          n/a&#xD;&#xA;    VkPhysicalDevice                    IDXGIAdapter1&#xD;&#xA;    VkDevice                            ID3D12Device&#xD;&#xA;    VkQueue                             ID3D12CommandQueue&#xD;&#xA;    VkSwapchain                         IDXGISwapChain3&#xD;&#xA;    VkFormat                            DXGI_FORMAT&#xD;&#xA;    SPIR-V                              D3D12_SHADER_BYTECODE&#xD;&#xA;    VkFence                             fences&#xD;&#xA;    VkSemaphore                         n/a&#xD;&#xA;    VkEvent                             n/a&#xD;&#xA;&#xD;&#xA;Vulkan's WSI layer supplies images for the swapchain. DX12 requires creation resources to represent the image. &#xD;&#xA;&#xD;&#xA;General queue behavior is pretty similar between both. There's a bit of idiosyncrasy when submitting from multiple threads. &#xD;&#xA;&#xD;&#xA;Will try to update as I remember more stuff...&#xD;&#xA;        &#xD;&#xA;**Command Buffer and Pool**&#xD;&#xA;--------------       &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkCommandPool                       ID3D12CommandAllocator&#xD;&#xA;    VkCommandBuffer                     ID3D12CommandList/ID3D12GraphicsCommandList&#xD;&#xA;                &#xD;&#xA;Verbiage about command pool/allocator from Vulkan/DX12 docs state the behavior in very different words - but the actual behavior is pretty similar. Users are free to allocate many command buffers/lists from the pool. However, only one command buffer/list from the pool can be recording. Pools cannot be shared between threads. So multiple threads require multiple pools. You can also begin recording immediately after submitting the command buffer/list on both.&#xD;&#xA;&#xD;&#xA;DX12 command list are created in an open state. I find this a bit annoying since I'm used to Vulkan. DX12 also requires and explicit reset of the command allocator and command list. This is an optional behavior in Vulkan.&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;**Descriptors**&#xD;&#xA;--------------               &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkDescriptorPool                    n/a&#xD;&#xA;    VkDescriptorSet                     n/a&#xD;&#xA;    VkDescriptorSetLayout               n/a&#xD;&#xA;    VkDescriptorSetLayoutBinding        RootParameter**&#xD;&#xA;    n/a                                 ID3D12DescriptorHeap&#xD;&#xA;    &#xD;&#xA;** **RootParameter** - not an exact equivalent to **VkDescriptorSetLayoutBinding** but similar thinking in the bigger picture.&#xD;&#xA;&#xD;&#xA;VkDescriptorPool and ID3D12DescriptorHeaps are sort of similar (thanks Nicolas) in that they both manage allocation of the descriptors themselves. &#xD;&#xA;&#xD;&#xA;It should be noted that DX12 only supports at most two descriptor heaps bound to a command list at any given time. One CBVSRVUAV and one sampler. You can have as many descriptor tables as you want referencing these heaps. &#xD;&#xA;&#xD;&#xA;On the Vulkan side, there is a hard limit to the max number of descriptor sets that you tell the descriptor pool. On both you have to do a bit of manual accounting on the number of descriptors per type the pool/heap can have. Vulkan is also more explicit with the type of descriptors. Whereas on DX12 descriptors are either CBVSRVUAV or sampler. &#xD;&#xA;&#xD;&#xA;DX12 also has a feature where you can sort of bind a CBV on the fly using SetGraphicsRootConstantBufferView. However, the SRV version of this, SetGraphicsRootShaderResourceView, does not work on textures. It's in the docs - but may also take you a couple of hours to figure this out if you're not a careful reader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Pipeline**&#xD;&#xA;--------------           &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkPipelineLayout                    RootSignature***&#xD;&#xA;    VkPipeline                          ID3D12PipelineState&#xD;&#xA;    VkVertexInputAttributeDescription   D3D12_INPUT_ELEMENT_DESC&#xD;&#xA;    VkVertexInputBindingDescription     &quot;&#xD;&#xA;    &#xD;&#xA;*** **RootSignature** - not an exact equivalent to **VkPipelineLayout**.&#xD;&#xA;&#xD;&#xA;DX12 combines the vertex attribute and binding into a single description. &#xD;&#xA;&#xD;&#xA;**Images and Buffers**&#xD;&#xA;--------------        &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkImage                             ID3D12Resource&#xD;&#xA;    VkBuffer                            ID3D12Resource&#xD;&#xA;    uniform buffer                      constant buffer&#xD;&#xA;    index buffer                        index buffer&#xD;&#xA;    vertex buffer                       vertex buffer&#xD;&#xA;    VkSampler                           sampler&#xD;&#xA;    barriers/transitions                barriers/transitions&#xD;&#xA;&#xD;&#xA;Barriers on both APIs break down a bit different, but have similar net result.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**RenderPasses / RenderTargets**&#xD;&#xA;--------------              &#xD;&#xA;    Vulkan                              DirectX 12&#xD;&#xA;    ---------------                     ---------------&#xD;&#xA;    VkRenderPass                        render pass&#xD;&#xA;    VkFramebuffer                       collection of ID3D12Resource&#xD;&#xA;    subpass                             n/a&#xD;&#xA;    n/a                                 render target&#xD;&#xA;&#xD;&#xA;Vulkan render passes have a nice auto-resolve feature. DX12 doesn't have this AFIAK. Both APIs provide functions for manual resolve. &#xD;&#xA;&#xD;&#xA;There's not a direct equivalence between VkFramebuffer and any objects in DX12. A collection of ID3D12Resource that map to RTVs is a loose similarity.&#xD;&#xA;&#xD;&#xA;VkFramebuffer acts more or less like an attachment pool that VkRenderPass references using an index. Subpasses within a VkRenderPass can reference any of the attachments in a VkFramebuffer assuming the same attachment isn't referenced more than once per subpass. Max number of color attachments used at once is limited to VkPhysicalDeviceLimits.maxColorAttachments.&#xD;&#xA;&#xD;&#xA;DX12's render targets are just RTVs that are backed by an ID3D12Resource objects. Max number of color attachments used at once is limited to D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT (8).&#xD;&#xA;&#xD;&#xA;Both APIs require you to specify the render targets/passes at the creation of the pipeline objects. However, Vulkan allows you to use compatible render passes, so you're not locked into the ones you specify during the pipline creation. I haven't tested it on DX12, but I would guess since it's just an RTV, this is also true on DX12." ContentLicense="CC BY-SA 4.0" />
  <row Id="23481" PostHistoryTypeId="24" PostId="4434" RevisionGUID="b9d3e167-7923-4f11-8251-d528e424e921" CreationDate="2019-03-16T20:09:59.560" Comment="Proposed by anonymous approved by 209, 48 edit id of 455" ContentLicense="CC BY-SA 4.0" />
  <row Id="23482" PostHistoryTypeId="50" PostId="8594" RevisionGUID="a909e6ca-e935-42ac-8beb-89e2fe1ba186" CreationDate="2019-03-17T12:01:45.463" UserId="-1" />
  <row Id="23483" PostHistoryTypeId="50" PostId="2421" RevisionGUID="b82cbdd2-9196-46f2-9521-e799dc63c090" CreationDate="2019-03-17T16:02:05.423" UserId="-1" />
  <row Id="23487" PostHistoryTypeId="2" PostId="8681" RevisionGUID="d8e99580-429d-428a-87b1-9226af721602" CreationDate="2019-03-18T06:45:52.623" UserId="10333" Text="I have many objects that store their color values. At the moment I'm storing them as vec4 values, that is four 4-byte values for RGBA, mainly because this is how the shader reads them. I was thinking of storing these colors as a vector or 4 unsigned single-byte integers. Anyway, with storing color values as one byte integers I can have a combination of 255^3, which is 16,581,375.&#xD;&#xA;&#xD;&#xA;I have a couple of question about this.&#xD;&#xA;&#xD;&#xA;If I store the red color as 128, this ends up being a floating point value of about 0.502, and a color of 129 ends up being a floating point value of about 0.506. My question is whether there is any discernible difference to speak of, either consciously or unconsciously between the intensity of a color being 0.502 or 0.506, or shades in between. Does this depend on the limitations of your graphics adaptor or video display? Or is there simply no discernible difference that one could tell with the eye for a value in between those two?&#xD;&#xA;&#xD;&#xA;Further, I have a similar inquiry about things like color changes over time. If for example we use a 0 to 255 value to do a fade to black over a significant period of time, would one integer jumps on the 0-255 scale in terms of brightness, which would result in about 0.004 in floating point on each change, be detectable as opposed to calculating the change in floating point to begin with?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="23488" PostHistoryTypeId="1" PostId="8681" RevisionGUID="d8e99580-429d-428a-87b1-9226af721602" CreationDate="2019-03-18T06:45:52.623" UserId="10333" Text="Some questions about working in 0-255 integers instead of single precision floating point colors" ContentLicense="CC BY-SA 4.0" />
  <row Id="23489" PostHistoryTypeId="3" PostId="8681" RevisionGUID="d8e99580-429d-428a-87b1-9226af721602" CreationDate="2019-03-18T06:45:52.623" UserId="10333" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23490" PostHistoryTypeId="5" PostId="8662" RevisionGUID="25b2eb8c-b84f-47f5-8146-03761654bbae" CreationDate="2019-03-18T16:09:59.440" UserId="10312" Comment="intending done for better understanding" Text="**Many hair simulations render their hair as lines (usually splines). Since hair is a really thin object.**&#xD;&#xA;&#xD;&#xA;if the hair is braided, rather than having thin infinitesimally small cylinders, you have something much thicker and with more volume per individual strand.&#xD;&#xA;&#xD;&#xA;The line method is  efficient, since lines are computationally cheap to render.&#xD;&#xA;&#xD;&#xA;However for braids it would seem you would need triangles, which would imply a high concentration of really small triangles on each individual braid, which sounds very expensive.&#xD;&#xA;&#xD;&#xA;Are there any algorithms that attempt at dealing with this issue? Particularily ones that are good at trading quality for memory useage?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23491" PostHistoryTypeId="4" PostId="8662" RevisionGUID="25b2eb8c-b84f-47f5-8146-03761654bbae" CreationDate="2019-03-18T16:09:59.440" UserId="10312" Comment="intending done for better understanding" Text="How Model braids?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23492" PostHistoryTypeId="24" PostId="8662" RevisionGUID="25b2eb8c-b84f-47f5-8146-03761654bbae" CreationDate="2019-03-18T16:09:59.440" Comment="Proposed by 10312 approved by -1 edit id of 465" ContentLicense="CC BY-SA 4.0" />
  <row Id="23493" PostHistoryTypeId="4" PostId="8662" RevisionGUID="3cd8bd9f-7c2d-4a79-a608-c6ff3beafe06" CreationDate="2019-03-18T16:09:59.440" UserId="209" Comment="intending done for better understanding" Text="How to model braids?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23497" PostHistoryTypeId="2" PostId="8683" RevisionGUID="5f65d2dc-ed34-4e44-bc6b-73c62d7f37a9" CreationDate="2019-03-18T19:14:20.567" UserId="2041" Text="First, a quick correction:&#xD;&#xA;&#xD;&#xA;&gt; storing color values as one byte integers I can have a combination of 255^3&#xD;&#xA;&#xD;&#xA;You mean $256^3$. There are 256 eight-bit integers (including zero), not 255. But here comes the more fundamental thing you need to understand.&#xD;&#xA;&#xD;&#xA;&gt; If I store the red color as 128, this ends up being a floating point value of about 0.502&#xD;&#xA;&#xD;&#xA;It doesn't end up being a floating-point value at all: it ends up as an 8 bit (or possibly 10 bit) integer on your display. Whatever extra precision you had in the floats to start with is thrown away when the final colour goes into the framebuffer. So the rest of what I'm going to say shouldn't influence your choice of *what* to store, because everything will end up as 8 bit colour channels.&#xD;&#xA;&#xD;&#xA;Now that doesn't mean there's never any value in using a higher-precision number earlier on. More precision in the intermediate data means you'll get the full precision in your output format. e.g. if you start out with these normalized integers, and you multiply them all by 2 in the shader, you'll only end up with the even-numbered integers in your output: you lost half of your precision.&#xD;&#xA;&#xD;&#xA;As for the question you really asked, about visible differences, it's easy to test that in live conditions. Just make a grey colour gradient from $(0, 0, 0)$ to $(1, 1, 1)$ in whatever representation you like (floats or normalized integers) and show it in place of your real computation. If you see [Mach bands](https://en.wikipedia.org/wiki/Mach_bands) on your gradient, then yes, you can tell the difference between adjacent intensities. In general, for adults with normal sight and 8 bit-per-channel RGB in common lighting conditions, there *is* a visible difference in a grey gradient. That doesn't mean there's a visible difference between every adjacent pair: the eye is less sensitive to contrast in red and blue than in green, and less sensitive to changes in hue, so it strongly depends on the colours involved.&#xD;&#xA;&#xD;&#xA;However, there are techniques to make the differences invisible most of the time. Check out [my answer explaining what sRGB is for](https://stackoverflow.com/a/12894053/967945) on SO for some examples." ContentLicense="CC BY-SA 4.0" />
  <row Id="23499" PostHistoryTypeId="2" PostId="8684" RevisionGUID="7c59cdeb-0195-41f0-a58e-b456d766b541" CreationDate="2019-03-18T21:25:36.497" UserId="6041" Text="I tried to follow Nathan Reed post [Antialiasing: To Splat Or Not][1] to implement splat method. The image I am getting thorugh the Lanczos filter is very different than Nathan. I do not understand where the problem is.&#xD;&#xA;&#xD;&#xA;According to [Wikipedia page][2] Lanczos filter is defined as either of below formulas:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[Nathan implementation][5] seems to have missed a division by pi**2 and a multiplication by filter radius.&#xD;&#xA;&#xD;&#xA;    elif options.kernel == 'lanczos':&#xD;&#xA;    		weight = &#xD;&#xA;              (np.sin(np.pi * sampleOffsetX) * np.sin(np.pi * sampleOffsetY) *&#xD;&#xA;    	       np.sin(np.pi * sampleOffsetX / options.radius) * &#xD;&#xA;               np.sin(np.pi * sampleOffsetY / options.radius) /  						  &#xD;&#xA;              (sampleOffsetX**2 * sampleOffsetY**2))&#xD;&#xA;&#xD;&#xA;Here is my code which borrowed most of the filter implementation from pbrt code:&#xD;&#xA;&#xD;&#xA;    private void btn_Render_Click(object sender, EventArgs e)&#xD;&#xA;    {&#xD;&#xA;        Random rand = new Random();&#xD;&#xA;        int samples = 16;&#xD;&#xA;        ImageFilm film = new ImageFilmSplat(pictureBox1.Width, pictureBox1.Height);&#xD;&#xA;        film.Filter = new SincFilter(tau: 4, width: 4);&#xD;&#xA;&#xD;&#xA;        for (int i = 0; i &lt; film.Width; i++)&#xD;&#xA;        {&#xD;&#xA;            for (int j = 0; j &lt; film.Height; j++)&#xD;&#xA;            {&#xD;&#xA;                EvaluatePixel(i, j, samples, rand, film);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        for (int i = 0; i &lt; film.Width; i++)&#xD;&#xA;        {&#xD;&#xA;            for (int j = 0; j &lt; film.Height; j++)&#xD;&#xA;            {&#xD;&#xA;                Pixel px = film.GetPixel(i, j);&#xD;&#xA;&#xD;&#xA;                if (px.filterWeightSum != 0)&#xD;&#xA;                {&#xD;&#xA;                    px.radiance = px.radiance / px.filterWeightSum;&#xD;&#xA;&#xD;&#xA;                    film.SetPixel(i, j, px);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        pictureBox1.Image = film.GetImage();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void EvaluatePixel(int i, int j, int nSamples, Random rand, ImageFilm film)&#xD;&#xA;    {&#xD;&#xA;        Vector halfpixel = new Vector(.5 / film.Width, .5 / film.Height, 0);&#xD;&#xA;&#xD;&#xA;        //all samples between [0,1]&#xD;&#xA;        Sample[] samples = sampler.Random(rand, nSamples);&#xD;&#xA;&#xD;&#xA;        for (int n = 0; n &lt; nSamples; n++)&#xD;&#xA;        {&#xD;&#xA;            //set sample coord at centre of the pixel&#xD;&#xA;            double cx = ((double)i / film.Width) + halfpixel.X;&#xD;&#xA;            double cy = ((double)j / film.Height) + halfpixel.Y;&#xD;&#xA;&#xD;&#xA;            //jitter the centre&#xD;&#xA;            cx += ((samples[n].X * 2) - 1) * halfpixel.X&#xD;&#xA;            cy += ((samples[n].Y * 2) - 1) * halfpixel.Y&#xD;&#xA;&#xD;&#xA;            //sample the function&#xD;&#xA;            double f = func(cx, cy);&#xD;&#xA;&#xD;&#xA;            film.AddToPixel(i, j, new Vector(f));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //ImageFilm class&#xD;&#xA;    public void AddToPixel(int i, int j, Vector radiance)&#xD;&#xA;    { &#xD;&#xA;        //splat the value to neighbor pixels&#xD;&#xA;        //find neighbour pixels based on filter width&#xD;&#xA;        int x0 = (int)Math.Max(0, i - Filter.Width);&#xD;&#xA;        int x1 = (int)Math.Min(Width - 1, i + Filter.Width);&#xD;&#xA;        int y0 = (int)Math.Max(0, j - Filter.Width);&#xD;&#xA;        int y1 = (int)Math.Min(Height - 1, j + Filter.Width);&#xD;&#xA;&#xD;&#xA;        for (int x = x0; x &lt;= x1; x++)&#xD;&#xA;        {&#xD;&#xA;            for (int y = y0; y &lt;= y1; y++)&#xD;&#xA;            {&#xD;&#xA;                double weight = this.Filter.eval(x - i, y - j);&#xD;&#xA;&#xD;&#xA;                Pixel pxl = GetPixel(x, y);&#xD;&#xA;&#xD;&#xA;                pxl.radiance += radiance * weight;&#xD;&#xA;                pxl.filterWeightSum += weight;&#xD;&#xA;&#xD;&#xA;                SetPixel(x, y, pxl);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    public class SincFilter&#xD;&#xA;    {&#xD;&#xA;        private double tau;&#xD;&#xA;&#xD;&#xA;        public SincFilter(double tau1, double width)&#xD;&#xA;        {&#xD;&#xA;            Width = width;&#xD;&#xA;            tau = tau1;&#xD;&#xA;        }&#xD;&#xA;        double Sinc(double x)&#xD;&#xA;        {&#xD;&#xA;            x = Math.Abs(x);&#xD;&#xA;            if (x &lt; 1e-5) return 1;&#xD;&#xA;            return Math.Sin(Math.PI * x) / (Math.PI * x);&#xD;&#xA;        }&#xD;&#xA;        double WindowedSinc(double x, double radius)&#xD;&#xA;        {&#xD;&#xA;            x = Math.Abs(x);&#xD;&#xA;            if (x &gt; radius) return 0;&#xD;&#xA;            return Sinc(x) * Sinc(x / tau);&#xD;&#xA;        }&#xD;&#xA;        public override double eval(double x, double y)&#xD;&#xA;        {&#xD;&#xA;            return WindowedSinc(x, Width) * WindowedSinc(y, Width);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    double func(double x, double y)&#xD;&#xA;    {&#xD;&#xA;        double minPeriod = 2e-5;&#xD;&#xA;        double maxPeriod = 0.2;&#xD;&#xA;&#xD;&#xA;        double period = minPeriod + (maxPeriod - minPeriod) * (y * y);&#xD;&#xA;        double phase = x / period;&#xD;&#xA;        phase -= Math.Floor(phase);&#xD;&#xA;&#xD;&#xA;        return Math.Round(phase);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is Nathan image : &#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;And here is mine for lanczos filter width 4, tau 4&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;My implementation is quite noisy for some reason. It doesn't look any better than box filter.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.reedbeta.com/blog/antialiasing-to-splat-or-not/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Lanczos_resampling&#xD;&#xA;  [3]: https://i.stack.imgur.com/UEPNb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/oqq67.png&#xD;&#xA;  [5]: https://gist.github.com/Reedbeta/893b63390160e33ddb3c&#xD;&#xA;  [6]: https://i.stack.imgur.com/R5VlB.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/e3thP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23500" PostHistoryTypeId="1" PostId="8684" RevisionGUID="7c59cdeb-0195-41f0-a58e-b456d766b541" CreationDate="2019-03-18T21:25:36.497" UserId="6041" Text="Lanczos filter implementation issue" ContentLicense="CC BY-SA 4.0" />
  <row Id="23501" PostHistoryTypeId="3" PostId="8684" RevisionGUID="7c59cdeb-0195-41f0-a58e-b456d766b541" CreationDate="2019-03-18T21:25:36.497" UserId="6041" Text="|image-processing|interpolation|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23503" PostHistoryTypeId="2" PostId="8685" RevisionGUID="204d6781-224d-477e-97c0-e718d2e2adf6" CreationDate="2019-03-20T16:18:26.780" UserId="7462" Text="Assume I have a texture with a repeating line pattern. The lines are exactly 2 texels wide (really thin). Ans very spaced out (50 texels in between each line).&#xD;&#xA;&#xD;&#xA;I am now struggling with the minification issue. The goal is to have as many of these lines to show up when rendering them in a textured map plane.&#xD;&#xA;&#xD;&#xA;Using OpenGL's standard mipmaping is not good enough, most of the lines are blurred out of existence, especially when the lines have certain orientations with the screen. &#xD;&#xA;&#xD;&#xA;Assuming the lines are white and the background is black.&#xD;&#xA;A slightly better technique is to, in addidition to mipmapping and anisotropic filtering, multisample a disk around the uv coordinate and look for white texels. If the result is white we discard the previous sample in favour of the white texels we just got.&#xD;&#xA;&#xD;&#xA;The above gives slightly better results, but it's not perfect.&#xD;&#xA;&#xD;&#xA;I have tried looking for papers and resources, but all I get on how to deal with this issue is &quot;minification and anisotropic filtering&quot; which I am already doing.&#xD;&#xA;&#xD;&#xA;How to preserved thin/small details in a texture?&#xD;&#xA;&#xD;&#xA;(I can't show the images displaying the problem)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23504" PostHistoryTypeId="1" PostId="8685" RevisionGUID="204d6781-224d-477e-97c0-e718d2e2adf6" CreationDate="2019-03-20T16:18:26.780" UserId="7462" Text="Anti aliasing thin features in textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="23505" PostHistoryTypeId="3" PostId="8685" RevisionGUID="204d6781-224d-477e-97c0-e718d2e2adf6" CreationDate="2019-03-20T16:18:26.780" UserId="7462" Text="|texture|algorithm|sampling|antialiasing|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23514" PostHistoryTypeId="50" PostId="8613" RevisionGUID="729892df-a4a1-48de-844c-ffdd400621e9" CreationDate="2019-03-21T13:02:42.940" UserId="-1" />
  <row Id="23515" PostHistoryTypeId="50" PostId="8587" RevisionGUID="3f846561-6bee-4710-89f9-fcdfb2cfbce4" CreationDate="2019-03-21T20:02:53.133" UserId="-1" />
  <row Id="23516" PostHistoryTypeId="2" PostId="8688" RevisionGUID="771992c5-e755-40f1-b974-9560231b9839" CreationDate="2019-03-21T21:43:53.483" UserId="10332" Text="I am wondering is there a difference in performance between using floating point textures as my 2D float4 array vs just passing in 2D float4 arrays? &#xD;&#xA;&#xD;&#xA;2D float arrays eliminate the need to do texture look ups to get the colour value, but i am not sure if perhaps textures have some kinda performance boost on GPUs that an array would not due to what ever clever optimisations GPUs can do.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23517" PostHistoryTypeId="1" PostId="8688" RevisionGUID="771992c5-e755-40f1-b974-9560231b9839" CreationDate="2019-03-21T21:43:53.483" UserId="10332" Text="Compute shader textures compared 2D float4 arrays" ContentLicense="CC BY-SA 4.0" />
  <row Id="23518" PostHistoryTypeId="3" PostId="8688" RevisionGUID="771992c5-e755-40f1-b974-9560231b9839" CreationDate="2019-03-21T21:43:53.483" UserId="10332" Text="|performance|compute-shader|optimisation|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23519" PostHistoryTypeId="2" PostId="8689" RevisionGUID="f19d324d-4753-439d-9d8a-12fc25dfeae0" CreationDate="2019-03-22T08:40:16.513" UserId="10353" Text="* In the **painter's algorithm**, you first sort all graphics elements&#xD;&#xA;  on depth (deepest first) and&#xD;&#xA;  then one-by-one fully paint them into the image on top of each other.&#xD;&#xA;  That way, deeper elements are obscured by less deep element.&#xD;&#xA;  (Intersecting graphics element require special attention.)&#xD;&#xA;&#xD;&#xA;* In the **depth-buffering algorithm**,&#xD;&#xA;  you store the current depth of each pixel in the image&#xD;&#xA;  (in addition to other pixel info),&#xD;&#xA;  and fully paint each graphics element pixel-by-pixel,&#xD;&#xA;  where an image pixel is updated&#xD;&#xA;  only if its depth is more than that of the new pixel.&#xD;&#xA;&#xD;&#xA;So, there is a time-memory tradeoff:&#xD;&#xA;&#xD;&#xA;* The **painter's algorithm** requires an extra sorting step (**costs time**),&#xD;&#xA;  but avoids storing additional (depth) information per pixel (**saves memory**).&#xD;&#xA;* **Depth-buffering** avoids sorting (**saves time**),&#xD;&#xA;  but stores extra (depth) information per pixel (**costs memory**)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23520" PostHistoryTypeId="4" PostId="8587" RevisionGUID="2d81dd6c-0c10-4792-994a-f7e6ee81bf0b" CreationDate="2019-03-22T09:01:00.870" UserId="209" Comment="minor correction to title" Text="An algorithms for covering a 2d polygon with a predetermined number of rectangles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23524" PostHistoryTypeId="2" PostId="8691" RevisionGUID="13a09f07-4642-45c8-9d03-63787b7c6fe9" CreationDate="2019-03-22T10:45:02.347" UserId="10354" Text="I'm working on a hybrid real time ray tracing project and trying to tackle the problem of self-intersection with larger scenes due to loss of float accuracy. The logic I'm trying to use is based on [Ray Tracing Gems][1] chapter 6 with the code bellow adapted to work with HLSL. In the snippet, `p` is the unadjusted ray origin and `n` the surface normal.&#xD;&#xA;```cpp&#xD;&#xA;float origin() { return 1.0f / 32.0f; }&#xD;&#xA;float float_scale() { return 1.0f / 65536.0f; }&#xD;&#xA;float int_scale() { return 256.0f; }&#xD;&#xA;&#xD;&#xA; // Normal points outward for rays exiting the surface, else is flipped.&#xD;&#xA; float3 offset_ray(const float3 p, const float3 n)&#xD;&#xA; {&#xD;&#xA; 	int3 of_i = {int_scale() * n.x, int_scale() * n.y, int_scale() * n.z};&#xD;&#xA; &#xD;&#xA;	float3 p_i = {&#xD;&#xA;	asfloat(asint(p.x)+((p.x &lt; 0) ? -of_i.x : of_i.x)),&#xD;&#xA;	asfloat(asint(p.y)+((p.y &lt; 0) ? -of_i.y : of_i.y)),&#xD;&#xA;	asfloat(asint(p.z)+((p.z &lt; 0) ? -of_i.z : of_i.z))};&#xD;&#xA;&#xD;&#xA;	return float3(&#xD;&#xA;	(abs(p.x) &lt; origin() ? p.x+ float_scale()*n.x : p_i.x),&#xD;&#xA;	(abs(p.y) &lt; origin() ? p.y+ float_scale()*n.y : p_i.y),&#xD;&#xA;	(abs(p.z) &lt; origin() ? p.z+ float_scale()*n.z : p_i.z));&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I'm testing this system with Ray Traced Ambient Occlusion and [a single model][2] with plenty of detail. Since the model is rather small I'm not encountering any issues at a scale of 1 with the model centered around the origin. The [output of the AO GBuffer][3] therefore looks plausible. When changing the scale to 100 there is a huge amount of self-intersection with the floor always self-intersecting and other parts of the model flickering when moving the camera and large parts are often being falsely occluded ([output of the GBuffer][4]). When translating the model by [10000 units on each axis][5] and back to a scale of 1 the problem is way less prevalent but still visible. The flickering only happens on parts of the model and underneath the tracks but overall fewer artifacts appear than with the scaling.&#xD;&#xA;&#xD;&#xA;I already have taken a look at the shaders used by UE4 but could only find a method to offset depending on the ray angle instead of the translation and is not a system that will solve my issue as the largest offset used in their system is not sufficient in our test scene. &#xD;&#xA;&#xD;&#xA;I'm curious why the problem is far more severe with a scale of 100 than with a translation of 10000 and what is causing the issues I'm experiencing. Is it a false translation of the shader code? Miss use of it? Or am I approaching the issue completely the wrong way?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.realtimerendering.com/raytracinggems/&#xD;&#xA;  [2]: https://sketchfab.com/3d-models/kv-2-heavy-tank-1940-ba8b84d78c0a42038cf2eaa4210ef296&#xD;&#xA;  [3]: https://i.stack.imgur.com/4WTrZ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pGGSN.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/XnGvr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23525" PostHistoryTypeId="1" PostId="8691" RevisionGUID="13a09f07-4642-45c8-9d03-63787b7c6fe9" CreationDate="2019-03-22T10:45:02.347" UserId="10354" Text="How to account for self intersection with large ray tracing scenes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23526" PostHistoryTypeId="3" PostId="8691" RevisionGUID="13a09f07-4642-45c8-9d03-63787b7c6fe9" CreationDate="2019-03-22T10:45:02.347" UserId="10354" Text="|raytracing|c++|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23527" PostHistoryTypeId="2" PostId="8692" RevisionGUID="3287a4c7-8e55-4b69-bdea-8f89bedab8c9" CreationDate="2019-03-22T19:01:46.110" UserId="506" Text="It depends on what you’re doing. If any given thread of your shader is working with data from multiple nearby pixels, like by sampling from fractional between-pixel locations or doing some calculation involving a pixel’s immediate neighbors, then you should probably use a texture: the GPU can do some caching and even load multiple values in a single operation in that case. If your threads are more independent and working on individual values, an array is fine." ContentLicense="CC BY-SA 4.0" />
  <row Id="23528" PostHistoryTypeId="50" PostId="8044" RevisionGUID="7c2c652b-44d1-4e73-8c12-51cacd02447b" CreationDate="2019-03-22T22:01:30.263" UserId="-1" />
  <row Id="23530" PostHistoryTypeId="50" PostId="6119" RevisionGUID="8de48ef6-937a-41c9-90c4-bcabdcf2bc92" CreationDate="2019-03-24T03:02:43.413" UserId="-1" />
  <row Id="23531" PostHistoryTypeId="2" PostId="8693" RevisionGUID="dad4e125-58e0-4d4e-83e0-b332db27529c" CreationDate="2019-03-24T23:16:27.460" UserId="10365" Text="I'm using a renderer developed by other people, and I found there are fireflies. It is strange that in a completely diffuse scene, there are still fireflies presented.&#xD;&#xA;&#xD;&#xA;To my understanding, I think it is possible to have fireflies in diffuse scene depending on what sampling strategy I use. For example, if I use a very small area light, and the probability of hitting the light by sampling the BRDF will be very small, resulting in an extremely large radiance value. (I'm not sure because I also heard that fireflies will not appear in complete diffuse scene, so correct me if I'm wrong!)&#xD;&#xA;&#xD;&#xA;I'm trying to locate the bug, if there are any, or improve the program, if the fireflies come with some reason. But after googling for a while, most things I found was how to fight fireflies, other than clearly analyzing where they come from.&#xD;&#xA;&#xD;&#xA;I was wondering if anyone knows any good materials, or if you could kindly summarize a bit. &#xD;&#xA;&#xD;&#xA;I'm particularly interested in the sources of the fireflies related to the sampling strategies, BRDF sampling, light sampling or MIS.&#xD;&#xA;&#xD;&#xA;I also think fireflies should be considered separately with **noise**, since they also seem to be caused by numerical stability (from [Wiki][1]).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Fireflies_(computer_graphics)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23532" PostHistoryTypeId="1" PostId="8693" RevisionGUID="dad4e125-58e0-4d4e-83e0-b332db27529c" CreationDate="2019-03-24T23:16:27.460" UserId="10365" Text="Where does fireflies come from?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23533" PostHistoryTypeId="3" PostId="8693" RevisionGUID="dad4e125-58e0-4d4e-83e0-b332db27529c" CreationDate="2019-03-24T23:16:27.460" UserId="10365" Text="|pathtracing|brdf|sampling|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23534" PostHistoryTypeId="4" PostId="8693" RevisionGUID="287bdd17-5ff8-4581-b08f-81fbdc723826" CreationDate="2019-03-25T09:37:38.673" UserId="209" Comment="Just tweaked title" Text="Where do &quot;fireflies&quot; come from?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23535" PostHistoryTypeId="2" PostId="8694" RevisionGUID="0148d0d1-71b6-4e50-8469-044ca073f64c" CreationDate="2019-03-25T11:17:46.270" UserId="10368" Text="I have a very big geometry in three.js and I want to hide a section of that geometry along an axis (for example every vertex with a Z&gt;N must be hidden). My idea is to create a custom shader in GLSL that does something like:&#xD;&#xA;&#xD;&#xA;    if vertex.z&gt;n {&#xD;&#xA;    vertex.hide= True&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have two questions:&#xD;&#xA;&#xD;&#xA; 1. I have to do that in real time several times with different N&#xD;&#xA;    values provided by the user, can I use something that &quot;tells&quot; to the shader the N value dynamically without creating and assign every time a new shader with just a different value?  &#xD;&#xA; 2. Maybe that's a better way? You must consider that to compute a new  &#xD;&#xA;    geometry and rendering it takes like 10 seconds, so I would   &#xD;&#xA;    definitely avoid creating a new &quot;cut&quot; geometry every time.&#xD;&#xA;&#xD;&#xA;Sorry for my poor English and thanks &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23536" PostHistoryTypeId="1" PostId="8694" RevisionGUID="0148d0d1-71b6-4e50-8469-044ca073f64c" CreationDate="2019-03-25T11:17:46.270" UserId="10368" Text="How to hide a part of a geometry dinamically using a shader in three.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="23537" PostHistoryTypeId="3" PostId="8694" RevisionGUID="0148d0d1-71b6-4e50-8469-044ca073f64c" CreationDate="2019-03-25T11:17:46.270" UserId="10368" Text="|glsl|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23538" PostHistoryTypeId="4" PostId="8694" RevisionGUID="814ea319-8093-476c-93b9-757d467a30b2" CreationDate="2019-03-26T14:41:07.840" UserId="209" Comment="fixed spelling in title" Text="How to hide a part of a geometry dynamically using a shader in three.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="23539" PostHistoryTypeId="2" PostId="8695" RevisionGUID="31c820e0-8f20-44c5-9bbd-33546eb75804" CreationDate="2019-03-26T15:49:19.307" UserId="10372" Text="I am currently working on an algorithm to calculate visibility in a 2D top-down level.&#xD;&#xA;&#xD;&#xA;The level contains&#xD;&#xA;&#xD;&#xA; - actors, with `position` and &quot;sight&quot; information&#xD;&#xA; - walls, with `start` &amp; `end` positions&#xD;&#xA; - light sources, with `position` and `range`&#xD;&#xA;&#xD;&#xA;I have written a fragment shader that renders my scene based on a texture I compose of the informations above.&#xD;&#xA;&#xD;&#xA;[![basic line of sight calculation][1]][1]&#xD;&#xA;&#xD;&#xA;[![Left side: my level rendered, right side: the actual texture that is fed to the shader][2]][2]&#xD;&#xA;&#xD;&#xA; - Red channel = line of sight for actors (in the example just the selected token is an actor)&#xD;&#xA; - Green channel = light sources with their range and their respective line of sight&#xD;&#xA; - Blue channel (not present in example) = night-vision of actors (means areas are shaded despite no light present)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am using [Babylonjs][3] and am naively rendering all those calculations one after the other into a DynamicTexture using the canvas 2d context.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can I use the GPU for some of these calculations (or all?) I am no expert for shader programming and don't know where to start / look.&#xD;&#xA;&#xD;&#xA;The code for my line-of-sight calculation can be found here: https://gitlab.com/aiacta/visibility&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rnsp4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wrNqK.jpg&#xD;&#xA;  [3]: https://github.com/BabylonJS/Babylon.js/" ContentLicense="CC BY-SA 4.0" />
  <row Id="23540" PostHistoryTypeId="1" PostId="8695" RevisionGUID="31c820e0-8f20-44c5-9bbd-33546eb75804" CreationDate="2019-03-26T15:49:19.307" UserId="10372" Text="2D Line of Sight + Visibility Calculations" ContentLicense="CC BY-SA 4.0" />
  <row Id="23541" PostHistoryTypeId="3" PostId="8695" RevisionGUID="31c820e0-8f20-44c5-9bbd-33546eb75804" CreationDate="2019-03-26T15:49:19.307" UserId="10372" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23552" PostHistoryTypeId="2" PostId="8699" RevisionGUID="6406a1f7-648c-449f-b993-e9b6ffc77405" CreationDate="2019-03-27T07:54:48.500" UserId="6331" Text="So I have a uniform block that looks something lile this&#xD;&#xA;&#xD;&#xA;{&#xD;&#xA;mat4;&#xD;&#xA;mat4[128];&#xD;&#xA;uint[16]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;The block should total up to 8320 bytes. After aligning by 256 bytes for nvidia, that brings the total allocation size to 8448 bytes.&#xD;&#xA;&#xD;&#xA;However, according to renderdoc and spirv-cross the total block size should be 8512 bytea. Can someone explain to me why there is a 64 byte padding at the end?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23553" PostHistoryTypeId="1" PostId="8699" RevisionGUID="6406a1f7-648c-449f-b993-e9b6ffc77405" CreationDate="2019-03-27T07:54:48.500" UserId="6331" Text="Clarifying vulkan glsl std140" ContentLicense="CC BY-SA 4.0" />
  <row Id="23554" PostHistoryTypeId="3" PostId="8699" RevisionGUID="6406a1f7-648c-449f-b993-e9b6ffc77405" CreationDate="2019-03-27T07:54:48.500" UserId="6331" Text="|glsl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23555" PostHistoryTypeId="2" PostId="8700" RevisionGUID="bfe9003e-98c2-41a6-ab39-f749a65bc398" CreationDate="2019-03-27T13:50:05.703" UserId="2654" Text="&gt; The block should total up to 8320 bytes.&#xD;&#xA;&#xD;&#xA;No, it shouldn't. You use a `uint[16]` array. Well, std140 layout makes it clear that the array stride for *any array* is always rounded up to the stride of a `vec4`. So that array takes up 256 bytes.&#xD;&#xA;&#xD;&#xA;You should instead use a `uvec4[4]` instead, which you would index from like a multidimensional array." ContentLicense="CC BY-SA 4.0" />
  <row Id="23556" PostHistoryTypeId="2" PostId="8701" RevisionGUID="d85e576b-db6b-41b0-93a2-253894915ad2" CreationDate="2019-03-27T17:17:48.477" UserId="10129" Text="I am trying to implement SSAO using DirectX11 but instead I got white screen with few black dots on model. **My suspect is that kernel generation or usage might be wrong**. I've tried **changing order of TBN matrix and sample multiplication order in pixel shader and it doesn't change results** in any way:&#xD;&#xA;[![Final buffer][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In fact those &quot;dots&quot; are small models of model itself that appear on it instead of dark creases (Example with sphere model):[![Sphere model SSAO][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My G-Buffers looks like this (Position, normal, tangent, bitangent):&#xD;&#xA;[![Position][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Normal][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Tangent][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Bitangent][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/otLHt.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vEnCe.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/pLjAp.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/jJq6E.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/EI8iI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/qwNo7.png&#xD;&#xA;&#xD;&#xA;**myKernelGeneration.cpp**&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;	//Create kernel for SSAO&#xD;&#xA;	std::uniform_real_distribution&lt;float&gt; randomFloats(0.0f, 1.0f);&#xD;&#xA;	std::default_random_engine generator;&#xD;&#xA;	XMFLOAT3 tmpSample;&#xD;&#xA;	for (int i = 0; i &lt; SSAO_KERNEL_SIZE; i++)&#xD;&#xA;	{&#xD;&#xA;		//Generate random vector3 ([-1, 1], [-1, 1], [0, 1])&#xD;&#xA;		tmpSample.x = randomFloats(generator) * 2.0f - 1.0f;&#xD;&#xA;		tmpSample.y = randomFloats(generator) * 2.0f - 1.0f;&#xD;&#xA;		tmpSample.z = randomFloats(generator);&#xD;&#xA;&#xD;&#xA;		//Normalize vector3&#xD;&#xA;		XMVECTOR tmpVector;&#xD;&#xA;		tmpVector.m128_f32[0] = tmpSample.x;&#xD;&#xA;		tmpVector.m128_f32[1] = tmpSample.y;&#xD;&#xA;		tmpVector.m128_f32[2] = tmpSample.z;&#xD;&#xA;&#xD;&#xA;		tmpVector = XMVector3Normalize(tmpVector);&#xD;&#xA;		&#xD;&#xA;		tmpSample.x = tmpVector.m128_f32[0];&#xD;&#xA;		tmpSample.y = tmpVector.m128_f32[1];&#xD;&#xA;		tmpSample.z = tmpVector.m128_f32[2];&#xD;&#xA;&#xD;&#xA;		//Multiply by random value all coordinates of vector3&#xD;&#xA;		//float randomMultiply = randomFloats(generator);&#xD;&#xA;		//tmpSample.x *= randomMultiply;&#xD;&#xA;		//tmpSample.y *= randomMultiply;&#xD;&#xA;		//tmpSample.z *= randomMultiply;&#xD;&#xA;&#xD;&#xA;		//Scale samples so they are more aligned to middle of hemisphere&#xD;&#xA;		float scale = float(i) / 64.0f;&#xD;&#xA;		scale = lerp(0.1f, 1.0f, scale * scale);&#xD;&#xA;		tmpSample.x *= scale;&#xD;&#xA;		tmpSample.y *= scale;&#xD;&#xA;		tmpSample.z *= scale;&#xD;&#xA;&#xD;&#xA;		//Pass value to array&#xD;&#xA;		m_ssaoKernel[i] = tmpSample;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**myPixelShader.ps**&#xD;&#xA;	&#xD;&#xA;	Texture2D textures[3]; //position, normal, noise&#xD;&#xA;	SamplerState SampleType;&#xD;&#xA;&#xD;&#xA;	//////////////&#xD;&#xA;	// TYPEDEFS //&#xD;&#xA;	//////////////&#xD;&#xA;&#xD;&#xA;	cbuffer KernelBuffer&#xD;&#xA;	{&#xD;&#xA;		float3 g_kernelValue[64];&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct PixelInputType&#xD;&#xA;	{&#xD;&#xA;		float4 positionSV : SV_POSITION;&#xD;&#xA;		float2 tex : TEXCOORD0;&#xD;&#xA;		float4x4 projection : TEXCOORD1;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	const float2 noiseScale = float2(1280.0f / 4.0f, 720.0f / 4.0f);&#xD;&#xA;	const float radius = 0.5f;&#xD;&#xA;	const float bias = 0.025f;&#xD;&#xA;	////////////////////////////////////////////////////////////////////////////////&#xD;&#xA;	// Pixel Shader&#xD;&#xA;	////////////////////////////////////////////////////////////////////////////////&#xD;&#xA;	float4 ColorPixelShader(PixelInputType input) : SV_TARGET&#xD;&#xA;	{&#xD;&#xA;		float3 position = textures[0].Sample(SampleType, input.tex).xyz;&#xD;&#xA;	float3 normal = normalize(textures[1].Sample(SampleType, input.tex).rgb);&#xD;&#xA;	float3 randomVector = normalize(textures[2].Sample(SampleType, input.tex * noiseScale).xyz);&#xD;&#xA;&#xD;&#xA;	float3 tangent = normalize(randomVector - normal * dot(randomVector, normal));&#xD;&#xA;	float3 bitangent = cross(normal, tangent);&#xD;&#xA;	float3x3 TBN = { tangent, bitangent, normal };&#xD;&#xA;&#xD;&#xA;	float3 sample = float3(0.0f, 0.0f, 0.0f);&#xD;&#xA;	float4 offset = float4(0.0f, 0.0f, 0.0f, 0.0f);&#xD;&#xA;	float occlusion = 0.0f;&#xD;&#xA;&#xD;&#xA;	for (int i = 0; i &lt; 64; i++)&#xD;&#xA;	{&#xD;&#xA;		sample = mul(TBN, g_kernelValue[i]);&#xD;&#xA;		sample = position + sample * radius;&#xD;&#xA;&#xD;&#xA;		offset = float4(sample, 1.0f);&#xD;&#xA;		offset = mul(input.projection, offset);&#xD;&#xA;		offset.xyz /= offset.w;&#xD;&#xA;		offset.xyz = offset.xyz * 0.5f + 0.5f;&#xD;&#xA;&#xD;&#xA;		float sampleDepth = textures[0].Sample(SampleType, offset.xy).z;&#xD;&#xA;		occlusion += (sampleDepth &gt;= sample.z + bias ? 1.0 : 0.0);&#xD;&#xA;	}&#xD;&#xA;	occlusion = 1.0f - (occlusion / 64.0f);&#xD;&#xA;&#xD;&#xA;	return float4(occlusion, occlusion, occlusion, 1.0f);&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="23557" PostHistoryTypeId="1" PostId="8701" RevisionGUID="d85e576b-db6b-41b0-93a2-253894915ad2" CreationDate="2019-03-27T17:17:48.477" UserId="10129" Text="SSAO - artifacts appearing" ContentLicense="CC BY-SA 4.0" />
  <row Id="23558" PostHistoryTypeId="3" PostId="8701" RevisionGUID="d85e576b-db6b-41b0-93a2-253894915ad2" CreationDate="2019-03-27T17:17:48.477" UserId="10129" Text="|directx11|directx|post-processing|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23559" PostHistoryTypeId="2" PostId="8702" RevisionGUID="22882e41-400d-4882-916a-0b9a89faa53e" CreationDate="2019-03-28T03:32:36.807" UserId="10387" Text="I am creating a quad tree from ground zero, because I am going to collapse it from bottom up I am refining it with a certain LoD level.&#xD;&#xA;&#xD;&#xA;I am using glm for mathematics and opengl for rendering. Instead of pointing to a vertex each quad points to an index from a list of vertex to avoid vertex redundancy.&#xD;&#xA;&#xD;&#xA;I start by computing the medians and the center, then I check in the list if any of these vertices exist. For a small amount of vertices this is trivial, however it became&#xD;&#xA;apparent that this strategy is ineffective.&#xD;&#xA;&#xD;&#xA;The code for this split is in the [following repo](https://github.com/worldrender/worldrender/blob/343780997086babcdc964c3239e95d001e34e9d2/QuadTree.cpp#L95-L165), if anyone can help me in finding another strategy, even showing me a code snippet, I would really appreciate it.&#xD;&#xA;&#xD;&#xA;Thanks in advance" ContentLicense="CC BY-SA 4.0" />
  <row Id="23560" PostHistoryTypeId="1" PostId="8702" RevisionGUID="22882e41-400d-4882-916a-0b9a89faa53e" CreationDate="2019-03-28T03:32:36.807" UserId="10387" Text="Help with efficient quadtree vertices indexing to avoid redundancy" ContentLicense="CC BY-SA 4.0" />
  <row Id="23561" PostHistoryTypeId="3" PostId="8702" RevisionGUID="22882e41-400d-4882-916a-0b9a89faa53e" CreationDate="2019-03-28T03:32:36.807" UserId="10387" Text="|algorithm|c++|data-structure|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23568" PostHistoryTypeId="2" PostId="8704" RevisionGUID="78599110-5105-4196-a4cf-dfbdcf552db0" CreationDate="2019-03-28T19:40:53.297" UserId="10396" Text="What I managed to figure out is that the first 3*3 is used for rotation and scale and the 1*3 at the end is used for position, but what is the bottom row used for? &#xD;&#xA;is it only for clipping related things?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23569" PostHistoryTypeId="1" PostId="8704" RevisionGUID="78599110-5105-4196-a4cf-dfbdcf552db0" CreationDate="2019-03-28T19:40:53.297" UserId="10396" Text="Why does opengl use 4d matrices for everything?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23570" PostHistoryTypeId="3" PostId="8704" RevisionGUID="78599110-5105-4196-a4cf-dfbdcf552db0" CreationDate="2019-03-28T19:40:53.297" UserId="10396" Text="|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23571" PostHistoryTypeId="2" PostId="8705" RevisionGUID="414952cc-7428-4843-89ac-d2e635e35bfa" CreationDate="2019-03-29T05:14:16.323" UserId="3003" Text="The bottom row allows you to create [perspective foreshortening](https://en.wikipedia.org/wiki/Perspective_(graphical)#Foreshortening). That is, it makes lines that are getting further away appear to converge. When arranged this way, we call this a perspective matrix.&#xD;&#xA;&#xD;&#xA;There are other ways to arrange a perspective matrix where that foreshortening doesn't happen. For example in an [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection). [This graphic](https://en.wikipedia.org/wiki/Orthographic_projection#/media/File:Graphical_projection_comparison.png) shows some different projections that are possible by  changing the values in the last row of a 4x4 matrix.&#xD;&#xA;&#xD;&#xA;Mathematically, the difference between a perspective projection and an orthographic projection is that the last row of a [perspective matrix has a division in the z component](https://en.wikipedia.org/wiki/3D_projection#Perspective_projection), whereas the [orthographic projection has a 0 in the z component](https://en.wikipedia.org/wiki/Orthographic_projection#Geometry)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23572" PostHistoryTypeId="2" PostId="8706" RevisionGUID="0c45769c-dcc8-470f-8eb2-3be11568a956" CreationDate="2019-03-29T15:09:45.837" UserId="10191" Text="For those familiar with smallpt, the ray tracer in 99 lines: I am looking at the code, and there is something that is not clear to me in the DIFFUSE ray scattering.&#xD;&#xA;After the rays are shot, they keep bouncing until the if-statement with the Russian Roulette stops them. &lt;br&gt;&#xD;&#xA;&#xD;&#xA;    if (++depth&gt;5) if (erand48(Xi)&lt;p) f=f*(1/p); else return obj.e;&#xD;&#xA;&#xD;&#xA;This means that, when rays are scattered and hit the light source, they don't actually stop there (which is what I thought at first: rays bounce until they hit the light source, or after a specific amount of bounces). Am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23573" PostHistoryTypeId="1" PostId="8706" RevisionGUID="0c45769c-dcc8-470f-8eb2-3be11568a956" CreationDate="2019-03-29T15:09:45.837" UserId="10191" Text="smallpt: question about ray scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="23574" PostHistoryTypeId="3" PostId="8706" RevisionGUID="0c45769c-dcc8-470f-8eb2-3be11568a956" CreationDate="2019-03-29T15:09:45.837" UserId="10191" Text="|raytracing|pathtracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23575" PostHistoryTypeId="5" PostId="8706" RevisionGUID="0424408d-6648-4e41-ab3c-e1e249f0e33c" CreationDate="2019-03-29T15:32:17.880" UserId="10191" Comment="added 9 characters in body" Text="For those familiar with smallpt, the ray tracer in 99 lines: I am checking the code, and there is something that is not clear to me in the DIFFUSE ray scattering.&#xD;&#xA;After the rays are shot, they keep bouncing until the if-statement with the Russian Roulette stops them. &lt;br&gt;&#xD;&#xA;&#xD;&#xA;    if (++depth&gt;5) if (erand48(Xi)&lt;p) f=f*(1/p); else return obj.e;&#xD;&#xA;&#xD;&#xA;This means that, when rays are scattered and hit the light source, they don't actually stop there (which is what I thought at first: rays bounce until they hit the light source, or until they reach a specific amount of bounces). Am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23576" PostHistoryTypeId="5" PostId="8705" RevisionGUID="16658219-4405-4339-8909-04642a0ba003" CreationDate="2019-03-29T15:36:27.630" UserId="3003" Comment="Fixed perspective to projection" Text="The bottom row allows you to create [perspective foreshortening](https://en.wikipedia.org/wiki/Perspective_(graphical)#Foreshortening). That is, it makes lines that are getting further away appear to converge. When arranged this way, we call this a perspective projection matrix.&#xD;&#xA;&#xD;&#xA;There are other ways to arrange a projection matrix where that foreshortening doesn't happen. For example in an [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection). [This graphic](https://en.wikipedia.org/wiki/Orthographic_projection#/media/File:Graphical_projection_comparison.png) shows some different projections that are possible by  changing the values in the last row of a 4x4 matrix.&#xD;&#xA;&#xD;&#xA;Mathematically, the difference between a perspective projection and an orthographic projection is that the last row of a [perspective matrix has a division in the z component](https://en.wikipedia.org/wiki/3D_projection#Perspective_projection), whereas the [orthographic projection has a 0 in the z component](https://en.wikipedia.org/wiki/Orthographic_projection#Geometry)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23577" PostHistoryTypeId="2" PostId="8707" RevisionGUID="dfdf4f9b-c496-4049-ac95-a9fe3d07eb3f" CreationDate="2019-03-29T19:40:46.097" UserId="10129" Text="Offset.xy is definatelly off because it just return XY coordinates from screenspace:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Clamping solved 'small copies of model' on the model itself, thanks!&#xD;&#xA;&#xD;&#xA;sampleDepth actually looks like this and indeed is not in viewspace and it may really explain those little models now:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Using viewspace (*offset = mul(projection, offset) ---&gt; offset = mul(view, offset)*) solves depth problem but final buffer is clear white. No effects are actually visible. What next step do you suggest? If depth comparing is correct now, what might be off?&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pTk24.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/edGRY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cEhHh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23581" PostHistoryTypeId="2" PostId="8708" RevisionGUID="10fd93c3-d862-43fb-ad82-536d60793395" CreationDate="2019-03-30T01:41:50.860" UserId="10365" Text="Hi I'm trying to get a better understanding of the BRDF modeling. I only implemented naive diffuse(lambert), specular and microfacet BRDF before, but I don't have much experience in mixed BRDFs and also rendering using 3D softwares like Maya, etc. Now I have to figure out the metal-rough or spec-gloss &quot;work flows&quot;, or PBR materials used in most industrial standard products.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At first, I didn't understand what metallic and roughness are really doing so I read the long paper by Brent Burley on Disney's principal BRDF. However, more and more questions pops up..&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Oh I also read the useful and clear slides https://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf , in which I learn about the specular/diffuse decomposition. I think this is essentially decoupling the reflection into two separate lobes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I want to understand the PBR materials in such a decoupling scheme.&#xD;&#xA;&#xD;&#xA;Basically we have a diffuse + specular pattern, where&#xD;&#xA;&#xD;&#xA;diffuse is usually enough to model by simply Lambert (not always true though..)&#xD;&#xA;&#xD;&#xA;specular term is usually modeled by a microfacet BRDF (contains specularD, specularG, specularF terms)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I start from the metal-rough model, there are usually three parameters&#xD;&#xA;&#xD;&#xA;**1. base color**&#xD;&#xA;&#xD;&#xA;**2. metalness**&#xD;&#xA;&#xD;&#xA;**3. roughness**&#xD;&#xA;&#xD;&#xA;My questions are as follows:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;1. What is base color for? Is it the same as the diffuse color? Will it influence the specular behavior?&#xD;&#xA;&#xD;&#xA;2. Regarding metalness, is it true that we only consider the diffuse term when the material is non-metal, and only specular reflection should be considered when rendering metal materials?&#xD;&#xA;&#xD;&#xA;3. What's the relationship between **roughness** and **specular D (surface normal distribution)**?&#xD;&#xA;&#xD;&#xA;In general, I'm very confused by this three-parameter representation, instead of the diffuse+specular(microfacet) one. What's the relationship between the three parameters and the other ones (diffuse color, specular D/G/F)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I need to understand this because I want to add the conversion (metal-rough -&gt; diffuse+specular) in my own code..&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks in advance!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="23582" PostHistoryTypeId="1" PostId="8708" RevisionGUID="10fd93c3-d862-43fb-ad82-536d60793395" CreationDate="2019-03-30T01:41:50.860" UserId="10365" Text="Questions about BRDF parameterization" ContentLicense="CC BY-SA 4.0" />
  <row Id="23583" PostHistoryTypeId="3" PostId="8708" RevisionGUID="10fd93c3-d862-43fb-ad82-536d60793395" CreationDate="2019-03-30T01:41:50.860" UserId="10365" Text="|brdf|pbr|material|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23584" PostHistoryTypeId="2" PostId="8709" RevisionGUID="7039ef09-4a5d-48d0-92b8-98f869b41054" CreationDate="2019-03-30T04:35:53.013" UserId="10399" Text="check this [link](https://community.khronos.org/t/oblique-frustum/49436/6)&#xD;&#xA;&#xD;&#xA;quotations ：&#xD;&#xA;&#xD;&#xA;“The points (+/-1, +/-1, 1, 1) are the four corners of the view frustum on the far plane in clip space.”&#xD;&#xA;&#xD;&#xA;this should be the point Q' which equals (sgn(Cx), sgn(Cy), 1, 1)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23585" PostHistoryTypeId="5" PostId="8707" RevisionGUID="1c9059f5-270a-458f-bb21-e28ac1acc475" CreationDate="2019-03-30T07:33:52.050" UserId="10129" Comment="added 522 characters in body" Text="Offset.xy is definatelly off because it just return XY coordinates from screenspace:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Clamping solved 'small copies of model' on the model itself, thanks!&#xD;&#xA;&#xD;&#xA;sampleDepth actually looks like this and indeed is not in viewspace and it may really explain those little models now:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Using viewspace (*offset = mul(projection, offset) ---&gt; offset = mul(view, offset)*) solves depth problem but final buffer is clear white. No effects are actually visible. What next step do you suggest? If depth comparing is correct now, what might be off?&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;Comparision is working but in a wrong way. Below line results in just fully white buffer screen:&#xD;&#xA;&#xD;&#xA;    occlusion += (sampleDepth &gt;= sample.z + bias ? 1.0 : 0.0);&#xD;&#xA;&#xD;&#xA;Changing it to:&#xD;&#xA;&#xD;&#xA;    occlusion += (sampleDepth &gt;= sample.z - bias ? 1.0 : 0.0);&#xD;&#xA;&#xD;&#xA;Actually gives us comparision but it is really bold and doesn't include only holes and creases but whole model. Changing bias to small values like 0.001f doesn't help:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pTk24.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/edGRY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cEhHh.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/mtO9k.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23586" PostHistoryTypeId="5" PostId="8707" RevisionGUID="f72b7898-b608-4ef9-a495-16530499f175" CreationDate="2019-03-30T08:04:05.120" UserId="10129" Comment="added 327 characters in body" Text="Offset.xy is definatelly off because it just return XY coordinates from screenspace:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Clamping solved 'small copies of model' on the model itself, thanks!&#xD;&#xA;&#xD;&#xA;sampleDepth actually looks like this and indeed is not in viewspace and it may really explain those little models now:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Using viewspace (*offset = mul(projection, offset) ---&gt; offset = mul(view, offset)*) solves depth problem but final buffer is clear white. No effects are actually visible. What next step do you suggest? If depth comparing is correct now, what might be off?&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;Comparision is working but in a wrong way. Below line results in just fully white buffer screen:&#xD;&#xA;&#xD;&#xA;    occlusion += (sampleDepth &gt;= sample.z + bias ? 1.0 : 0.0);&#xD;&#xA;&#xD;&#xA;Changing it to:&#xD;&#xA;&#xD;&#xA;    occlusion += (sampleDepth &gt;= sample.z - bias ? 1.0 : 0.0);&#xD;&#xA;&#xD;&#xA;Actually gives us comparision but it is really bold and doesn't include only holes and creases but whole model. Changing bias to small values like 0.001f doesn't help:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Update #2:**&#xD;&#xA;Directly comparing gives result presented below. However it doesn't seem satisfying enough to use as it seems to present rather edges than creases and holes:&#xD;&#xA;&#xD;&#xA;    occlusion += (sampleDepth == sample.z ? 1.0 : 0.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pTk24.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/edGRY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cEhHh.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/mtO9k.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/qsHyi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23587" PostHistoryTypeId="2" PostId="8710" RevisionGUID="1af83112-6d09-4f0a-a240-3e0cb73f81ed" CreationDate="2019-03-30T16:15:13.383" UserId="8925" Text="I am trying to understand why my explicit light sampling implemetation does not produce the same results as my naive path tracer. Here are my results :&#xD;&#xA;&#xD;&#xA;Naive Version :&#xD;&#xA;&#xD;&#xA;[![Naive version][1]][1]&#xD;&#xA;&#xD;&#xA;Explicit light sampling version :&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Diff :&#xD;&#xA;&#xD;&#xA;[![Diff with tweaked contrast][3]][3]&#xD;&#xA;&#xD;&#xA;It's not that different, but the top and back planes have a stronger &quot;glow&quot; in the explicit light version. The shadow also seems softer in the explicit light version.&#xD;&#xA;&#xD;&#xA;What I made for the explicit light sampling, based on PBRT and [this][4] answer :&#xD;&#xA;&#xD;&#xA;    vec3 pathTrace( const Ray&amp; ray, int bounces, const std::vector&lt; std::pair&lt; Plane, Material &gt; &gt;&amp; planes, const std::vector&lt; std::pair&lt; Sphere, Material &gt; &gt;&amp; spheres, bool firstBounce = false )&#xD;&#xA;    {&#xD;&#xA;        if( bounces == 0 )&#xD;&#xA;            return vec3( 0.0 );&#xD;&#xA;&#xD;&#xA;        Hit hit = sceneIntersects( ray, planes, spheres );&#xD;&#xA;        if( !hit._any )&#xD;&#xA;            return vec3( 0.0 );&#xD;&#xA;&#xD;&#xA;        // Cast a new ray from the hit position to a random direction on the hemisphere&#xD;&#xA;        Ray secondRay( hit._position, sampleHemisphereUniform( hit._normal ) );&#xD;&#xA;&#xD;&#xA;        vec3 radiance = pathTrace( secondRay, bounces - 1, planes, spheres );&#xD;&#xA;&#xD;&#xA;        vec3 brdf = hit._material._albedo / Pi;&#xD;&#xA;        double pdf = 1.0 / ( 2.0 * Pi );&#xD;&#xA;&#xD;&#xA;    #ifdef NAIVE&#xD;&#xA;        return hit._material._emissive + radiance * brdf * dot( hit._normal, secondRay._direction ) / pdf;&#xD;&#xA;    #else&#xD;&#xA;        // Remove the emission since its taken into account in the directLighting part&#xD;&#xA;        vec3 indirectLighting = radiance * brdf * dot( hit._normal, secondRay._direction ) / pdf;&#xD;&#xA;&#xD;&#xA;        if( firstBounce &amp;&amp; hit._isLight )&#xD;&#xA;        {&#xD;&#xA;            // Unlesss we hit a light at first bounce, to avoid black lights&#xD;&#xA;            indirectLighting += hit._material._emissive;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        vec3 directLighting;&#xD;&#xA;&#xD;&#xA;        // For testing purposes, the sphere area light is hardcoded&#xD;&#xA;        const vec3 lightPosition( 0.0, 8.0, -2.5 );&#xD;&#xA;        const double lightRadius = 1.1;&#xD;&#xA;        const vec3 lightEmission( 4.0 );&#xD;&#xA;&#xD;&#xA;        // Sample a random point on an hemisphere oriented to the point instead of a sphere&#xD;&#xA;        vec3 lightSample = sampleHemisphereUniform( normalize( hit._position - lightPosition ) );&#xD;&#xA;        lightSample *= lightRadius;&#xD;&#xA;        lightSample += lightPosition;&#xD;&#xA;&#xD;&#xA;        vec3 lightDir = normalize( lightSample - hit._position );&#xD;&#xA;&#xD;&#xA;        // Cast a ray to the light&#xD;&#xA;        Hit hitLight = sceneIntersects( Ray( hit._position, lightDir ), planes, spheres );&#xD;&#xA;        if( !hit._isLight &amp;&amp; hitLight._any &amp;&amp; hitLight._isLight )&#xD;&#xA;        {&#xD;&#xA;            // Use the area form of the rendering equation&#xD;&#xA;            double G = dot( hit._normal, lightDir ) * dot( hitLight._normal, -lightDir ) / length2( hitLight._position - hit._position );&#xD;&#xA;&#xD;&#xA;            // The light is sampled using an hemisphere, so the area is the area of an hemisphere&#xD;&#xA;            double lightArea = 2.0 * Pi * 1.1 * 1.1;&#xD;&#xA;            double lightPdf = 1.0 / lightArea;&#xD;&#xA;&#xD;&#xA;            directLighting = lightEmission * brdf * G / lightPdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return directLighting + indirectLighting;&#xD;&#xA;    #endif&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[This][5] answer says that because I am sampling twice, I should divide my twice the number of samples, but it gives me even more different results so I'm not sure if I to do that or not. Anyway I test both every time.&#xD;&#xA;&#xD;&#xA;I was also wondering if it was because 1 bounce of the naive path tracer is not equal to one bounce of the explicit light sampling version (The first bounce of naive will only output color when it hits a light, while the explicit light version will output direct lighting), so I tested with 30 bounces, and bounces - 1, and got almost no difference. Same thing with samples. I am just not able to get the light sampling version with the naive version, and to me it's not a convergence time issue, since the naive version doesn't change much after a 3 min render (other than the noise, of course), so I'm pretty sure the images converges to a different result. &#xD;&#xA;&#xD;&#xA;I don't know if I need multiple importance sampling here, I'd say no because I am not trying to cast a light ray based on the brdf (for now) but I'm again not sure.&#xD;&#xA;&#xD;&#xA;I'm also not sure if I can sample the sphere using an hemisphere. I did that because I had the hemisphere sampling code ready. But intuitively it seems good to me, because the spherical light would have twice of the samples occluded, which is taken into account when dividing by the pdf of an hemisphere instead of the pdf of a sphere.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/B7O0q.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/MSHoh.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/LZxDB.png&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/questions/5152/progressive-path-tracing-with-explicit-light-sampling&#xD;&#xA;  [5]: https://computergraphics.stackexchange.com/questions/4288/path-weight-for-direct-light-sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="23588" PostHistoryTypeId="1" PostId="8710" RevisionGUID="1af83112-6d09-4f0a-a240-3e0cb73f81ed" CreationDate="2019-03-30T16:15:13.383" UserId="8925" Text="Should I expect differences with explicit light sampling other that the noise?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23589" PostHistoryTypeId="3" PostId="8710" RevisionGUID="1af83112-6d09-4f0a-a240-3e0cb73f81ed" CreationDate="2019-03-30T16:15:13.383" UserId="8925" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23594" PostHistoryTypeId="2" PostId="8712" RevisionGUID="c2161725-9e79-4910-aa55-77bb4ccb4627" CreationDate="2019-03-31T22:02:11.343" UserId="10388" Text="Let's say I designed a housing model and rendered it using a rendering engine. how can I measure the performance of my rendering? " ContentLicense="CC BY-SA 4.0" />
  <row Id="23595" PostHistoryTypeId="1" PostId="8712" RevisionGUID="c2161725-9e79-4910-aa55-77bb4ccb4627" CreationDate="2019-03-31T22:02:11.343" UserId="10388" Text="What are the parameters measure the performance of a rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23596" PostHistoryTypeId="3" PostId="8712" RevisionGUID="c2161725-9e79-4910-aa55-77bb4ccb4627" CreationDate="2019-03-31T22:02:11.343" UserId="10388" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23597" PostHistoryTypeId="2" PostId="8713" RevisionGUID="33d17a93-0b07-43ab-8c7c-bd60f389a27c" CreationDate="2019-03-31T23:09:07.760" UserId="6588" Text="I assume you mean performance of the numerical algorithm responsible for generating the image?&#xD;&#xA;&#xD;&#xA;Usually the performance of a rendering algorithm is assessed through a pixel-wise comparison with a ground truth, converged image. This image is typically rendered for a very long time using a standard and (ideally) unbiased technique like unidirectional path tracing. For a fixed time and sampling budget, you then run your custom algorithm and track a meaningful error (e.g. relative MSE) between your intermediate image and the ground truth image. Plotting the error over time on a logarithmic scale should give you a sense of how your algorithm is performing.&#xD;&#xA;&#xD;&#xA;When comparing algorithms, you need to make sure that you are actually comparing images that were output by the *same* rendering engine. This is crucial if you want to report a faithful metric, otherwise the comparison is unfair and inherently depends on the implementation. For instance, if rendering engine $A$ takes twice as long as engine $B$ to fetch and load a texture, your reported error will be double, even though the main algorithm you are testing is the same (assuming you are treating materials as blackboxes). The main downside is that rendering researchers are typically required to implement other algorithms in their engine to report the true performance of their new algorithm." ContentLicense="CC BY-SA 4.0" />
  <row Id="23599" PostHistoryTypeId="2" PostId="8715" RevisionGUID="cabb18a7-48a0-4ae4-bb36-202eecedac62" CreationDate="2019-04-01T06:04:50.273" UserId="6046" Text="`p` is gonna be zero for light sources. Light sources are defined by emission variable and color is zero for them. Hence the reflectance parameter calculated previous to this line `p` would be zero giving us `obj.e`" ContentLicense="CC BY-SA 4.0" />
  <row Id="23600" PostHistoryTypeId="2" PostId="8716" RevisionGUID="c7717b05-b415-48f1-b669-995925a8172f" CreationDate="2019-04-01T09:41:12.970" UserId="10191" Text="# Introduction&#xD;&#xA;For those familiar with &lt;b&gt;smallpt&lt;/b&gt; by Kevin Beason: &lt;br&gt;&#xD;&#xA;In path tracing, when rays hit a surface, they are scattered and the theta angle (the angle between the normal to the surface and the scattered ray) depends on a probability density function. For cosine importance sampling, this probability depends on cos(theta). This is the case implemented in the basic smallpt. Multiple rays should be scattered for each hitting point, and their contribution needs to be calculated to return the color value of the specific pixel. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Sv5IS.png&#xD;&#xA;&#xD;&#xA;# Problem&#xD;&#xA;&#xD;&#xA;Looking at how rays are scattered, this doesn't actually happen in the smallpt code. Multiple rays per pixel are shot at slightly different positions. That means, they don't always land in the same spot on the surface. For this reason, the image posted above does not represent what is happening. Indeed, it is not true that multiple rays are scattered FROM EVERY HITTING POINT, but multiple rays are shot for each pixel. Is my interpretation correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23601" PostHistoryTypeId="1" PostId="8716" RevisionGUID="c7717b05-b415-48f1-b669-995925a8172f" CreationDate="2019-04-01T09:41:12.970" UserId="10191" Text="smallpt: ray scattering and Importance Sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="23602" PostHistoryTypeId="3" PostId="8716" RevisionGUID="c7717b05-b415-48f1-b669-995925a8172f" CreationDate="2019-04-01T09:41:12.970" UserId="10191" Text="|raytracing|pathtracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23603" PostHistoryTypeId="4" PostId="8706" RevisionGUID="51bac264-928c-4e34-9ae9-d5da280fe289" CreationDate="2019-04-01T09:44:15.990" UserId="10191" Comment="edited title" Text="smallpt: when to stop diffuse ray scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="23604" PostHistoryTypeId="2" PostId="8717" RevisionGUID="70a3bc35-2e5e-4bc7-b844-e80592060dd2" CreationDate="2019-04-01T13:58:41.347" UserId="10096" Text="Let me first address some misconceptions you have:&#xD;&#xA;&#xD;&#xA;&gt; the theory states that we need to shoot x number of rays for each&#xD;&#xA;&gt; intersection&#xD;&#xA;&#xD;&#xA;No, the &quot;theory&quot; doesn't state such a thing. Note also that the paper @gallickgunner is referring to is inapplicable in this case since smallpt is based on the rendering equation and not the limited variant present in Cook's paper. Thus you actually need to refer to Kajiya's paper or Veach's path formulation. What @gallickgunner is right about is the canceling of the cosine term (but there's a missing $\pi$ factor).&#xD;&#xA;&#xD;&#xA;Now onto the bigger misconception you have:&#xD;&#xA;&#xD;&#xA;&gt; Multiple rays should be scattered for each hitting point, and their contribution needs to be calculated to return the color value of the specific pixel. &#xD;&#xA;&#xD;&#xA;There's no such requirement, in fact Kajiya proved that scattering multiple rays at each bounce is bad since you get an exponential explosion of the ray count later down the bounce tree where the actual contribution is actually very small. In MC terms you perform splitting where the contribution is small thus wasting computational power which would be a lot more useful in reducing variance in other places. To understand why this is the case, one has to dig deeper into the theory of how raytracing works and how you estimate the rendering equation.&#xD;&#xA;&#xD;&#xA;You start with a Fredholm integral equation of the second kind:&#xD;&#xA;&#xD;&#xA;$$L_o(x,\omega_o) = L_e(x, \omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta\,d\omega_i}$$&#xD;&#xA;&#xD;&#xA;As long as the integral converges (which happens when the operator is a contraction, or when it is not but enough energy can escape the scene for there to be a steady state), you can find the solution as the Liouville-Neumann expansion. To do this however I'll first rewrite the equation in operator form:&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)L_e = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;Where the last equality holds as long as $T$ is a contraction ($||T||&lt;1$). Note that $T^0$ represents $0$ bounces, $T^1$ represents $1$ bounce, and $T^n$ represents $n$ bounces. Thus you can look at the solution as accumulating contributions from all light paths of length $0$, $1$, $2$ etc. till infinity. Now to actually write this out explicitly it's more convenient to rewrite the rendering equation in terms of integration over all scene surface points $S$ rather than the upper hemisphere (this was actually how Kajiya derived it initially, not precisely the form below but in an equivalent form):&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_o(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)}$$&#xD;&#xA;Where $G$ is defined as:&#xD;&#xA;$$G(x \leftrightarrow y) = \frac{|\cos\theta_x\cos\theta_y|}{||x-y||}V(x,y)$$&#xD;&#xA;Where $\theta_x$ is the angle between the vector $y-x$ and the normal at $x$, and $\theta_y$ is the angle betwen the vector $x-y$ and the normal at $y$ (the cosines can be written as dot products provided you have the normals). $V(x,y)$ is the visibility function and it is 1 only if there's no surface point between $x$ and $y$ (if you shoot a ray from $x$ to $y$ the first thing you hit will be $y$), and $0$ otherwise. The visibility function is implicit in the solid angle formulation inside $L_i$ (through the ray-casting function). Now let us rewrite the operator expansion in terms of what we have above, we get:&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)} + $$&#xD;&#xA;$$\int_{S}\int_{S}{{L_e(x_3 \rightarrow x_2)f(x_3 \rightarrow x_2 \rightarrow x_1) G(x_3 \leftrightarrow x_2)f(x_2 \rightarrow x_1 \rightarrow x_0) G(x_2 \leftrightarrow x_1)\,dA(x_3)\,dA(x_2)}}$$&#xD;&#xA;$$+ ...$$&#xD;&#xA;This sum continues till infinity with iterated integrals corresponding to $T^i$, the part expanded above is $T^0L_e + T^1L_e + T^2L_e$. Note that usually you have an extra integration over the area of the pixel (then there's a factor $W$ to account for the sensor sensitivity). When you do pathtracing (what smallpt does) you're actually estimating this infinite sum of integrals through Monte Carlo (this is also the reason why Monte Carlo is employed, since the convergence doesn't depend on the dimension, which in this case is infinite). You can estimate each term in the sum by Monte Carlo integration, that is for a $n$-iterated integral your samples are really paths starting from the camera with length $n$: $x_0x_1x_2...x_{n+1}$ for a path of length $n$. Note that you do not require that you split the path for each subsequent integral.&#xD;&#xA;What path tracing implementations do, is create this path $x_0x_1...x_{n+1}$ incrementally, and reuse the path for earlier terms in the sum. That means that you start by picking some point $x_0$ inside a pixel, pick some point $x_1$ in the scene compute the value of the integrand of the term $T^0L_e$ for the path $x_0x_1$, pick a point $x_2$ in the scene and compute the value of the integrand of the term $T^1L_e$ for the path $x_0x_1x_2$, and so on. In an implementation you usually use the solid angle (at least for bsdf sampling), but there's not major difference, you still end up with paths of the form $x_0x_1...x_{n+1}$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23605" PostHistoryTypeId="5" PostId="8717" RevisionGUID="e30967a3-dee9-4de2-ac58-d6e51d04a3b4" CreationDate="2019-04-01T14:03:43.827" UserId="10096" Comment="added 12 characters in body" Text="Let me first address some misconceptions you have:&#xD;&#xA;&#xD;&#xA;&gt; the theory states that we need to shoot x number of rays for each&#xD;&#xA;&gt; intersection&#xD;&#xA;&#xD;&#xA;No, the &quot;theory&quot; doesn't state such a thing. Note also that the paper @gallickgunner is referring to is inapplicable in this case since smallpt is based on the rendering equation and not the limited variant present in Cook's paper. Thus you actually need to refer to Kajiya's paper or Veach's path formulation. What @gallickgunner is right about is the canceling of the cosine term (but there's a missing $\pi$ factor).&#xD;&#xA;&#xD;&#xA;Now onto the bigger misconception you have:&#xD;&#xA;&#xD;&#xA;&gt; Multiple rays should be scattered for each hitting point, and their contribution needs to be calculated to return the color value of the specific pixel. &#xD;&#xA;&#xD;&#xA;There's no such requirement, in fact Kajiya proved that scattering multiple rays at each bounce is bad since you get an exponential explosion of the ray count later down the bounce tree where the actual contribution is actually very small. In MC terms you perform splitting where the contribution is small thus wasting computational power which would be a lot more useful in reducing variance in other places. To understand why this is the case, one has to dig deeper into the theory of how raytracing works and how you estimate the rendering equation.&#xD;&#xA;&#xD;&#xA;You start with a Fredholm integral equation of the second kind:&#xD;&#xA;&#xD;&#xA;$$L_o(x,\omega_o) = L_e(x, \omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta\,d\omega_i}$$&#xD;&#xA;&#xD;&#xA;As long as the integral converges (which happens when the operator is a contraction, or when it is not but enough energy can escape the scene for there to be a steady state), you can find the solution as the Liouville-Neumann expansion. To do this however I'll first rewrite the equation in operator form:&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)L_e = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;Where the last equality holds as long as $T$ is a contraction ($||T||&lt;1$). Note that $T^0$ represents $0$ bounces, $T^1$ represents $1$ bounce, and $T^n$ represents $n$ bounces. Thus you can look at the solution as accumulating contributions from all light paths of length $0$, $1$, $2$ etc. till infinity. Now to actually write this out explicitly it's more convenient to rewrite the rendering equation in terms of integration over all scene surface points $S$ rather than the upper hemisphere (this was actually how Kajiya derived it initially, not precisely the form below but in an equivalent form):&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_o(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)}$$&#xD;&#xA;Where $G$ is defined as:&#xD;&#xA;$$G(x \leftrightarrow y) = \frac{|\cos\theta_x\cos\theta_y|}{||x-y||}V(x,y)$$&#xD;&#xA;Where $\theta_x$ is the angle between the vector $y-x$ and the normal at $x$, and $\theta_y$ is the angle betwen the vector $x-y$ and the normal at $y$ (the cosines can be written as dot products provided you have the normals). $V(x,y)$ is the visibility function and it is 1 only if there's no surface point between $x$ and $y$ (if you shoot a ray from $x$ to $y$ the first thing you hit will be $y$), and $0$ otherwise. The visibility function is implicit in the solid angle formulation inside $L_i$ (through the ray-casting function). Now let us rewrite the operator expansion in terms of what we have above, we get:&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)} + $$&#xD;&#xA;$$\int_{S}\int_{S}{{L_e(x_3 \rightarrow x_2)f(x_3 \rightarrow x_2 \rightarrow x_1) G(x_3 \leftrightarrow x_2)f(x_2 \rightarrow x_1 \rightarrow x_0) G(x_2 \leftrightarrow x_1)\,dA(x_3)\,dA(x_2)}}$$&#xD;&#xA;$$+ ...$$&#xD;&#xA;This sum continues till infinity with iterated integrals corresponding to $T^i$, the part expanded above is $T^0L_e + T^1L_e + T^2L_e$. Note that usually you have an extra integration over the area of the pixel (then there's a factor $W$ to account for the sensor sensitivity). When you do pathtracing (what smallpt does) you're actually estimating this infinite sum of integrals through Monte Carlo (this is also the reason why Monte Carlo is employed, since the convergence doesn't depend on the dimension, which in this case is infinite). You can estimate each term in the sum by Monte Carlo integration, that is for a $n$-iterated integral your samples are really paths starting from the camera with length $n$: $x_0x_1x_2...x_{n+1}$ for a path of length $n$. Note that you do not require that you split the path for each subsequent integral.&#xD;&#xA;What path tracing implementations do, is create this path $x_0x_1...x_{n+1}$ incrementally, and reuse the path for earlier terms in the sum. That means that you start by picking some point $x_0$ inside a pixel, pick some point $x_1$ in the scene compute the value of the integrand of the term $T^0L_e$ for the path $x_0x_1$, pick a point $x_2$ in the scene and compute the value of the integrand of the term $T^1L_e$ for the path $x_0x_1x_2$, and so on. In an implementation you usually use the solid angle formulation (at least for bsdf sampling), but there's not major difference, you still end up with paths of the form $x_0x_1...x_{n+1}$.&#xD;&#xA;&#xD;&#xA;The takeaway from this is that **path**tracing works with **paths** where, a path starts at the camera and ends at a lightsource. Using different paths that do not split (in general) to estimate the sum of integrals is usually more efficient splitting each path into more paths at each bounce. I am not saying there's no place for splitting (actually smallpt uses it for the first few bounces for materials that refract), you just have to know when to apply it (when the contribution is large and is inadequately sampled by only 1 or a few samples)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23606" PostHistoryTypeId="5" PostId="8717" RevisionGUID="6304c751-c0cb-49c3-a99a-7b7150fe57ca" CreationDate="2019-04-01T14:12:13.963" UserId="10096" Comment="added 12 characters in body" Text="Let me first address some misconceptions you have:&#xD;&#xA;&#xD;&#xA;&gt; the theory states that we need to shoot x number of rays for each&#xD;&#xA;&gt; intersection&#xD;&#xA;&#xD;&#xA;No, the &quot;theory&quot; doesn't state such a thing. Note also that the paper @gallickgunner is referring to is inapplicable in this case since smallpt is based on the rendering equation and not the limited variant present in Cook's paper. Thus you actually need to refer to Kajiya's paper or Veach's path formulation. What @gallickgunner is right about is the canceling of the cosine term (but there's a missing $\pi$ factor).&#xD;&#xA;&#xD;&#xA;Now onto the bigger misconception you have:&#xD;&#xA;&#xD;&#xA;&gt; Multiple rays should be scattered for each hitting point, and their contribution needs to be calculated to return the color value of the specific pixel. &#xD;&#xA;&#xD;&#xA;There's no such requirement, in fact Kajiya proved that scattering multiple rays at each bounce is bad since you get an exponential explosion of the ray count later down the bounce tree where the actual contribution is actually very small. In MC terms you perform splitting where the contribution is small thus wasting computational power which would be a lot more useful in reducing variance in other places. To understand why this is the case, one has to dig deeper into the theory of how raytracing works and how you estimate the rendering equation.&#xD;&#xA;&#xD;&#xA;You start with a Fredholm integral equation of the second kind:&#xD;&#xA;&#xD;&#xA;$$L_o(x,\omega_o) = L_e(x, \omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta\,d\omega_i}$$&#xD;&#xA;&#xD;&#xA;As long as the integral converges (which happens when the operator is a contraction, or when it is not but enough energy can escape the scene for there to be a steady state), you can find the solution as the Liouville-Neumann expansion. To do this however I'll first rewrite the equation in operator form:&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)L_e = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;Where the last equality holds as long as $T$ is a contraction ($||T||&lt;1$). Note that $T^0$ represents $0$ bounces, $T^1$ represents $1$ bounce, and $T^n$ represents $n$ bounces. Thus you can look at the solution as accumulating contributions from all light paths of length $0$, $1$, $2$ etc. till infinity. Now to actually write this out explicitly it's more convenient to rewrite the rendering equation in terms of integration over all scene surface points $S$ rather than the upper hemisphere (this was actually how Kajiya derived it initially, not precisely the form below but in an equivalent form):&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_o(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)}$$&#xD;&#xA;Where $G$ is defined as:&#xD;&#xA;$$G(x \leftrightarrow y) = \frac{|\cos\theta_x\cos\theta_y|}{||x-y||}V(x,y)$$&#xD;&#xA;Where $\theta_x$ is the angle between the vector $y-x$ and the normal at $x$, and $\theta_y$ is the angle betwen the vector $x-y$ and the normal at $y$ (the cosines can be written as dot products provided you have the normals). $V(x,y)$ is the visibility function and it is 1 only if there's no surface point between $x$ and $y$ (if you shoot a ray from $x$ to $y$ the first thing you hit will be $y$), and $0$ otherwise. The visibility function is implicit in the solid angle formulation inside $L_i$ (through the ray-casting function). Now let us rewrite the operator expansion in terms of what we have above, we get:&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)} + $$&#xD;&#xA;$$\int_{S}\int_{S}{{L_e(x_3 \rightarrow x_2)f(x_3 \rightarrow x_2 \rightarrow x_1) G(x_3 \leftrightarrow x_2)f(x_2 \rightarrow x_1 \rightarrow x_0) G(x_2 \leftrightarrow x_1)\,dA(x_3)\,dA(x_2)}}$$&#xD;&#xA;$$+ ...$$&#xD;&#xA;This sum continues till infinity with iterated integrals corresponding to $T^i$, the part expanded above is $T^0L_e + T^1L_e + T^2L_e$. Note that usually you have an extra integration over the area of the pixel (then there's a factor $W$ to account for the sensor sensitivity). When you do pathtracing (what smallpt does) you're actually estimating this infinite sum of integrals through Monte Carlo (this is also the reason why Monte Carlo is employed, since the convergence doesn't depend on the dimension, which in this case is infinite). You can estimate each term in the sum by Monte Carlo integration, that is for a $n$-iterated integral your samples are really paths starting from the camera with length $n$: $x_0x_1x_2...x_{n+1}$ for a path of length $n$. Note that you do not require that you split the path for each subsequent integral.&#xD;&#xA;What path tracing implementations do, is create this path $x_0x_1...x_{n+1}$ incrementally, and reuse the path for earlier terms in the sum. That means that you start by picking some point $x_0$ inside a pixel, pick some point $x_1$ in the scene compute the value of the integrand of the term $T^0L_e$ for the path $x_0x_1$, pick a point $x_2$ in the scene and compute the value of the integrand of the term $T^1L_e$ for the path $x_0x_1x_2$, and so on. In an implementation you usually use the solid angle formulation (at least for bsdf sampling), but there's not major difference, you still end up with paths of the form $x_0x_1...x_{n+1}$.&#xD;&#xA;&#xD;&#xA;The takeaway from this is that **path**tracing works with **paths** where, a path starts at the camera and ends at a lightsource. Using different paths that do not split (in general) to estimate the sum of integrals is usually more efficient than splitting each path into more paths at each bounce. I am not saying there's no place for splitting (actually smallpt uses it for the first few bounces for materials that refract), you just have to know when to apply it (when the contribution is large and is inadequately sampled by only 1 or a few samples). Note that the opposite of splitting is early path termination in the form of the Russian roullete - basically kill off paths with small contributions since it's not worth it wasting computational resources on those (it also lets you make your estimator unbiased, but in practice there's usually a ceiling to the number of bounces allowed, since for most scenes your estimator being &quot;fully unbiased&quot; is not worth it in terms of performance)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23607" PostHistoryTypeId="5" PostId="8694" RevisionGUID="015bade0-db7c-42f4-a0bc-165adb76a9f2" CreationDate="2019-04-01T14:19:26.010" UserId="10373" Comment="I added punctuation and added a very necessary space." Text="I have a very big geometry in three.js and I want to hide a section of that geometry along an axis (for example every vertex with a Z&gt;N must be hidden). My idea is to create a custom shader in GLSL that does something like:&#xD;&#xA;&#xD;&#xA;    if vertex.z&gt;n {&#xD;&#xA;    vertex.hide= True&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have 2 questions:&#xD;&#xA;&#xD;&#xA; 1. I have to do that in real time several times with different N&#xD;&#xA;    values provided by the user, can I use something that &quot;tells&quot; to the shader the N value dynamically without creating and assign every time a new shader with just a different value?  &#xD;&#xA; 2. Maybe that's a better way? You must consider that to compute a new  &#xD;&#xA;    geometry and rendering it takes like 10 seconds, so I would   &#xD;&#xA;    definitely avoid creating a new &quot;cut&quot; geometry every time.&#xD;&#xA;&#xD;&#xA;Sorry for my poor English and thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="23608" PostHistoryTypeId="4" PostId="8694" RevisionGUID="015bade0-db7c-42f4-a0bc-165adb76a9f2" CreationDate="2019-04-01T14:19:26.010" UserId="10373" Comment="I added punctuation and added a very necessary space." Text="How to hide a part of a geometry dynamically using a shader in 3.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="23609" PostHistoryTypeId="24" PostId="8694" RevisionGUID="015bade0-db7c-42f4-a0bc-165adb76a9f2" CreationDate="2019-04-01T14:19:26.010" Comment="Proposed by 10373 approved by  edit id of 467" ContentLicense="CC BY-SA 4.0" />
  <row Id="23610" PostHistoryTypeId="4" PostId="8694" RevisionGUID="994dc30a-b0b6-4d2e-93b7-361f9f4f3234" CreationDate="2019-04-01T14:19:48.787" UserId="10368" Comment="edited title" Text="How to hide a part of a geometry dynamically using a shader in three.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="23611" PostHistoryTypeId="5" PostId="8717" RevisionGUID="cfeab343-6f17-4f98-a0ec-cace4ba609ab" CreationDate="2019-04-01T14:36:11.170" UserId="10096" Comment="Forgot inverse in the operator formulation" Text="Let me first address some misconceptions you have:&#xD;&#xA;&#xD;&#xA;&gt; the theory states that we need to shoot x number of rays for each&#xD;&#xA;&gt; intersection&#xD;&#xA;&#xD;&#xA;No, the &quot;theory&quot; doesn't state such a thing. Note also that the paper @gallickgunner is referring to is inapplicable in this case since smallpt is based on the rendering equation and not the limited variant present in Cook's paper. Thus you actually need to refer to Kajiya's paper or Veach's path formulation. What @gallickgunner is right about is the canceling of the cosine term (but there's a missing $\pi$ factor).&#xD;&#xA;&#xD;&#xA;Now onto the bigger misconception you have:&#xD;&#xA;&#xD;&#xA;&gt; Multiple rays should be scattered for each hitting point, and their contribution needs to be calculated to return the color value of the specific pixel. &#xD;&#xA;&#xD;&#xA;There's no such requirement, in fact Kajiya proved that scattering multiple rays at each bounce is bad since you get an exponential explosion of the ray count later down the bounce tree where the actual contribution is actually very small. In MC terms you perform splitting where the contribution is small thus wasting computational power which would be a lot more useful in reducing variance in other places. To understand why this is the case, one has to dig deeper into the theory of how raytracing works and how you estimate the rendering equation.&#xD;&#xA;&#xD;&#xA;You start with a Fredholm integral equation of the second kind:&#xD;&#xA;&#xD;&#xA;$$L_o(x,\omega_o) = L_e(x, \omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta\,d\omega_i}$$&#xD;&#xA;&#xD;&#xA;As long as the integral converges (which happens when the operator is a contraction, or when it is not but enough energy can escape the scene for there to be a steady state), you can find the solution as the Liouville-Neumann expansion. To do this however I'll first rewrite the equation in operator form:&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;Where the last equality holds as long as $T$ is a contraction ($||T||&lt;1$). Note that $T^0$ represents $0$ bounces, $T^1$ represents $1$ bounce, and $T^n$ represents $n$ bounces. Thus you can look at the solution as accumulating contributions from all light paths of length $0$, $1$, $2$ etc. till infinity. Now to actually write this out explicitly it's more convenient to rewrite the rendering equation in terms of integration over all scene surface points $S$ rather than the upper hemisphere (this was actually how Kajiya derived it initially, not precisely the form below but in an equivalent form):&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_o(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)}$$&#xD;&#xA;Where $G$ is defined as:&#xD;&#xA;$$G(x \leftrightarrow y) = \frac{|\cos\theta_x\cos\theta_y|}{||x-y||}V(x,y)$$&#xD;&#xA;Where $\theta_x$ is the angle between the vector $y-x$ and the normal at $x$, and $\theta_y$ is the angle betwen the vector $x-y$ and the normal at $y$ (the cosines can be written as dot products provided you have the normals). $V(x,y)$ is the visibility function and it is 1 only if there's no surface point between $x$ and $y$ (if you shoot a ray from $x$ to $y$ the first thing you hit will be $y$), and $0$ otherwise. The visibility function is implicit in the solid angle formulation inside $L_i$ (through the ray-casting function). Now let us rewrite the operator expansion in terms of what we have above, we get:&#xD;&#xA;$$L_o(x_1\rightarrow x_0) = L_e(x_1 \rightarrow x_0) + \int_{S}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1) G(x_1 \leftrightarrow x_2)\,dA(x_2)} + $$&#xD;&#xA;$$\int_{S}\int_{S}{{L_e(x_3 \rightarrow x_2)f(x_3 \rightarrow x_2 \rightarrow x_1) G(x_3 \leftrightarrow x_2)f(x_2 \rightarrow x_1 \rightarrow x_0) G(x_2 \leftrightarrow x_1)\,dA(x_3)\,dA(x_2)}}$$&#xD;&#xA;$$+ ...$$&#xD;&#xA;This sum continues till infinity with iterated integrals corresponding to $T^i$, the part expanded above is $T^0L_e + T^1L_e + T^2L_e$. Note that usually you have an extra integration over the area of the pixel (then there's a factor $W$ to account for the sensor sensitivity). When you do pathtracing (what smallpt does) you're actually estimating this infinite sum of integrals through Monte Carlo (this is also the reason why Monte Carlo is employed, since the convergence doesn't depend on the dimension, which in this case is infinite). You can estimate each term in the sum by Monte Carlo integration, that is for a $n$-iterated integral your samples are really paths starting from the camera with length $n$: $x_0x_1x_2...x_{n+1}$ for a path of length $n$. Note that you do not require that you split the path for each subsequent integral.&#xD;&#xA;What path tracing implementations do, is create this path $x_0x_1...x_{n+1}$ incrementally, and reuse the path for earlier terms in the sum. That means that you start by picking some point $x_0$ inside a pixel, pick some point $x_1$ in the scene compute the value of the integrand of the term $T^0L_e$ for the path $x_0x_1$, pick a point $x_2$ in the scene and compute the value of the integrand of the term $T^1L_e$ for the path $x_0x_1x_2$, and so on. In an implementation you usually use the solid angle formulation (at least for bsdf sampling), but there's not major difference, you still end up with paths of the form $x_0x_1...x_{n+1}$.&#xD;&#xA;&#xD;&#xA;The takeaway from this is that **path**tracing works with **paths** where, a path starts at the camera and ends at a lightsource. Using different paths that do not split (in general) to estimate the sum of integrals is usually more efficient than splitting each path into more paths at each bounce. I am not saying there's no place for splitting (actually smallpt uses it for the first few bounces for materials that refract), you just have to know when to apply it (when the contribution is large and is inadequately sampled by only 1 or a few samples). Note that the opposite of splitting is early path termination in the form of the Russian roullete - basically kill off paths with small contributions since it's not worth it wasting computational resources on those (it also lets you make your estimator unbiased, but in practice there's usually a ceiling to the number of bounces allowed, since for most scenes your estimator being &quot;fully unbiased&quot; is not worth it in terms of performance)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23612" PostHistoryTypeId="2" PostId="8718" RevisionGUID="1aa71f50-60af-4fc9-b8f2-f28a6e112ae1" CreationDate="2019-04-01T15:42:08.473" UserId="9908" Text="In this [SIGGRAPH paper](http://gmrv.es/Publications/2016/CMTKPO16/main.pdf) is described a similar operation for the visibility calculation from every pixel in the domain (you only need calculate it from actors position), which has been implemented in GPU. &#xD;&#xA;&#xD;&#xA;Although it is oriented to fluid dynamics, it may be a starting point to look.&#xD;&#xA;&#xD;&#xA;You can see other related shader examples like [this one](https://www.shadertoy.com/view/4d2SzG) with implicit geometry.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23618" PostHistoryTypeId="2" PostId="8720" RevisionGUID="521909a9-89a4-414c-bfdc-91f3f0c3b2a1" CreationDate="2019-04-02T05:30:42.943" UserId="38" Text="If we put homogenious cordinates to the backburner for a second. Then there is also a second reason:&#xD;&#xA;&#xD;&#xA;Mathematical completeness. A 3 by 4 or 4 by 3 matrix is not invertible. Inverse is critical for hierarchy calculations. &#xD;&#xA;&#xD;&#xA;Now you could posit that the  last computer part is always same and be done with it. But having worked for a company that in their main software did just this. Well sure now the matrices are invertible. But not general. I can now not safely transpose my matrices for example. And the truth is that i lose out on a lot of possible mathematics knowledge that i could use. At the end this was a common soirce of errors, anger and confusion among clients.&#xD;&#xA; &#xD;&#xA;Homogeneous coordinates are just one possible application of this mathematical completeness. It turns out to be very useful if you want to model perspective. But its far from the only benefit.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23619" PostHistoryTypeId="2" PostId="8721" RevisionGUID="5977d659-8cb2-45cb-bffa-3709fe1c8579" CreationDate="2019-04-02T12:15:51.570" UserId="10415" Text="I'm trying to perfectly align two or more equirectangular photos of the same place taken from slightly different positions. &#xD;&#xA;Using an example provided by openMVG I managed to get the relative position between the two shots, but I can't figure out how to translate the center of the projection according to the data obtained. &#xD;&#xA;I tried with Hugin without success, editing the camera position information (it doesn't seem to be able to export the entire equirectangular photo) and I didn't found any useful panotools. I found some literature about the problem but not any real implementation to adapt.&#xD;&#xA;&#xD;&#xA;Could you advise me of a possible path to follow?&#xD;&#xA;&#xD;&#xA;My requirement is to do it programmatically because I will have to apply it to thousands of photos.&#xD;&#xA;&#xD;&#xA;Thanks a lot.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23620" PostHistoryTypeId="1" PostId="8721" RevisionGUID="5977d659-8cb2-45cb-bffa-3709fe1c8579" CreationDate="2019-04-02T12:15:51.570" UserId="10415" Text="How to translate the center of an equirectangular projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23621" PostHistoryTypeId="3" PostId="8721" RevisionGUID="5977d659-8cb2-45cb-bffa-3709fe1c8579" CreationDate="2019-04-02T12:15:51.570" UserId="10415" Text="|rendering|image-processing|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23626" PostHistoryTypeId="2" PostId="8723" RevisionGUID="6e136ba5-2ab1-48d3-a6f3-30fd2d77e015" CreationDate="2019-04-03T05:08:48.307" UserId="10418" Text="I'm looking for a code to generate organic 2d trees like thiskind of shapes&#xD;&#xA;&#xD;&#xA;[![Organic tree 01 ][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Organic tree 02][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Gerard Ferrandez has an example to generate some tree but not organic like the picture shape https://codepen.io/ge1doot/pen/BGWzgW?editors=0010&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any recomendation will be much appreciated.&#xD;&#xA;&#xD;&#xA;Many thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jNBs5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/82g8O.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23627" PostHistoryTypeId="1" PostId="8723" RevisionGUID="6e136ba5-2ab1-48d3-a6f3-30fd2d77e015" CreationDate="2019-04-03T05:08:48.307" UserId="10418" Text="Organic 2d tree generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="23628" PostHistoryTypeId="3" PostId="8723" RevisionGUID="6e136ba5-2ab1-48d3-a6f3-30fd2d77e015" CreationDate="2019-04-03T05:08:48.307" UserId="10418" Text="|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23629" PostHistoryTypeId="2" PostId="8724" RevisionGUID="4358ae2e-5775-4e99-9611-4b139bc21905" CreationDate="2019-04-03T07:16:35.973" UserId="9908" Text="I could be generated as a Lindenmayer System (L-system) with some rules for branch widths (plus some fractal noise) and branch bifurcation. They are parameters you can play with.&#xD;&#xA;&#xD;&#xA;You can find lots of resources in the [website](http://algorithmicbotany.org) of the Biological Modeling and Visualization research group in the Department of Computer Science at the University of Calgary. Professor Przemyslaw Prusinkiewicz is the researcher who popularized these systems, and he has made his [main book](http://algorithmicbotany.org/papers/abop/abop.pdf) *The algorithmic beauty of plants* available for free.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23630" PostHistoryTypeId="2" PostId="8725" RevisionGUID="6fa10a64-f038-4074-abe9-a34b5ed527b5" CreationDate="2019-04-03T08:47:59.967" UserId="2041" Text="Normally when we talk about realistic transparent volumes, we care about refraction (and total internal reflection), and we care about scattering. But there's a much simpler case of volume transparency, where the opacity of the object depends on the distance that light travels through it.&#xD;&#xA;&#xD;&#xA;I'm writing a real-time visualization with a forward-rendering pipeline (on WebGL) and I'd like to show transparent solids this way, without having to resort to path tracing. My solids are heterogeneous and isotropic, and I'm not interested in scattering or refraction. I just want thin parts of the solid to be very transparent and thicker parts of the solid to be more opaque.&#xD;&#xA;&#xD;&#xA;It seems like most real-time transparency algorithms (e.g. OIT) are mainly for getting surfaces/sheets right, instead of volumes, and are more concerned about correct stacking, refraction, and scattering.&#xD;&#xA;&#xD;&#xA;It seems like making the colour of the object depend on the thickness of material behind each fragment should be easily achievable with something like an extra depth pass where I draw opaque objects that intersect transparent objects, and back faces of transparent objects, possibly with some extra correction where the notional ray for one pixel goes through a torus-like object more than once. Intuition tells me that this ought to be a standard algorithm, but I don't know of one. Does this algorithm already exist, or do I just need to get my pencil and paper out and write one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23631" PostHistoryTypeId="1" PostId="8725" RevisionGUID="6fa10a64-f038-4074-abe9-a34b5ed527b5" CreationDate="2019-04-03T08:47:59.967" UserId="2041" Text="How to draw depth-based volume in real-time" ContentLicense="CC BY-SA 4.0" />
  <row Id="23632" PostHistoryTypeId="3" PostId="8725" RevisionGUID="6fa10a64-f038-4074-abe9-a34b5ed527b5" CreationDate="2019-04-03T08:47:59.967" UserId="2041" Text="|real-time|transparency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23633" PostHistoryTypeId="2" PostId="8726" RevisionGUID="86784c6f-13f9-4b67-926f-f0dd8a34ad2d" CreationDate="2019-04-03T12:30:42.633" UserId="10096" Text="The issue is that an extra depth pass won't cut it. You may need an arbitrary number of extra depth passes. Just imagine the volume between two sinusoidal surfaces, you would have infinitely many alternating z-intervals of volume/empty space as long as you're looking from a specific direction." ContentLicense="CC BY-SA 4.0" />
  <row Id="23634" PostHistoryTypeId="5" PostId="8720" RevisionGUID="4e8efe5c-a80d-48f8-8444-67d78e414d0e" CreationDate="2019-04-03T13:52:51.137" UserId="38" Comment="added 62 characters in body" Text="If we put homogenious cordinates to the backburner for a second. Then there is also a second reason:&#xD;&#xA;&#xD;&#xA;Mathematical completeness. A 3 by 4 or 4 by 3 matrix is not invertible. Inverse is critical for hierarchy calculations. &#xD;&#xA;&#xD;&#xA;Now you could posit that the  last computer part is always same and be done with it. But having worked for a company that in their main software did just this i would say that it is a mistake. Well, sure now the matrices are invertible but not general. I can now not safely transpose my matrices for example. The truth is that i lose out on a lot of possible mathematics knowledge that i could use because this one part is missing. At the end this was a common source of errors, anger and confusion among clients.&#xD;&#xA; &#xD;&#xA;Homogeneous coordinates are just one possible application of this mathematical completeness. It turns out to be very useful if you want to model perspective. But its far from the only benefit.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23638" PostHistoryTypeId="2" PostId="8728" RevisionGUID="a1e81d03-1647-458c-8bb4-c2dd599b03d4" CreationDate="2019-04-03T15:15:33.603" UserId="7952" Text="In a 3x3 matrix you cannot specify translation, as you have already pointed out. But in 4 dimensions you CAN give a translation. So you pretty much gave the most basic answer in your question. And in fact some math libraries have optimized &quot;4x4&quot; matrix classes that assume the last row/column is &quot;0,0,0,1&quot;. It works out rather nicely and allows code to execute a bit faster since a few calculations can be omitted.&#xD;&#xA;&#xD;&#xA;In your question you asked what is that last row used for, but really the first question you should be asking is &quot;why is that last value in the row a 1?&quot;&#xD;&#xA;&#xD;&#xA;To best understand it go back to two dimensions where we could use a &quot;2x2&quot; matrix to describe everything. But immediately the math lib runs into the same problem as using a &quot;3x3&quot; matrix in 3 dimensions. The 2x2 matrix can't describe translations. But if you bump the 2x2 matrix up to a 3x3 matrix now all of a sudden you CAN do translations. But here again you have that row of &quot;0,0,1&quot;. But this time it is much easier to visualize that all of our 2 dimensional math is happening in a single plane of 3 dimensions. And it is the 1st plane in the Z dimension as indicated by our last row &quot;1&quot;. But what about those zero's?&#xD;&#xA;&#xD;&#xA;Well now a whole host of questions comes up. Like, if a vector has only direction and magnitude what should a 2 dimensional vectors Z value be in 3 dimensions? What about a 2 dimensional point in 3 dimensions? That answer to that is somewhat intuitive when you focus on &quot;a vector has no location&quot;. This should scream ZERO. Which translates to infinity. But a point, which MUST be located inside our 2 dimensional space must also be in the same plane as all the other points and we all ready know that our chosen plane on the Z axis is 1. (Think about how a vector is formed from 2 points, if both points lie in the same Z plane of 1 then the resulting vector has a Z value of zero)&#xD;&#xA;&#xD;&#xA;This I hope is a woe moment. Because now it starts to be very clear that vectors and points are fundamentally different creatures. And all those zero's and the one in the last row/column of a 4x4 matrix now say very clearly that we have 3 vectors and one point, and that point is the translation, which suddenly makes the entire thing make sense.&#xD;&#xA;&#xD;&#xA;That is the fundamental meaning of that row. But the beauty of linear algebra means that we don't have to force those last values to lie in the W plane &quot;1&quot; (traditionally in 4 dimensions the letter chosen for the 4th dimension is W so a vector now has X,Y,Z,W values) of our 4x4 matrix. Or even that we have to use 3 vectors and 1 point. Which leads to perspectives, scales, and other fun in the 4th dimension.&#xD;&#xA;&#xD;&#xA;Thats my answer and I'm stickin to it!" ContentLicense="CC BY-SA 4.0" />
  <row Id="23639" PostHistoryTypeId="5" PostId="8720" RevisionGUID="e5b90689-ef94-42e1-b7c3-920bf2c8430a" CreationDate="2019-04-03T15:28:57.107" UserId="38" Comment="deleted 1 character in body" Text="If we put homogeneous ordinates to the backburner for a second. Then there is also a second reason:&#xD;&#xA;&#xD;&#xA;Mathematical completeness. A 3 by 4 or 4 by 3 matrix is not invertible. Inverse is critical for hierarchy calculations. &#xD;&#xA;&#xD;&#xA;Now you could posit that the  last computer part is always same and be done with it. But having worked for a company that in their main software did just this i would say that it is a mistake. Well, sure now the matrices are invertible but not general. I can now not safely transpose my matrices for example. The truth is that i lose out on a lot of possible mathematics knowledge that i could use because this one part is missing. At the end this was a common source of errors, anger and confusion among clients.&#xD;&#xA; &#xD;&#xA;Homogeneous coordinates are just one possible application of this mathematical completeness. It turns out to be very useful if you want to model perspective. But its far from the only benefit.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23640" PostHistoryTypeId="5" PostId="8720" RevisionGUID="b41e390c-5b71-4940-863d-216e06a79a55" CreationDate="2019-04-03T15:36:20.957" UserId="38" Comment="added 78 characters in body" Text="If we put homogeneous ordinates to the backburner for a second. Then there is also a second reason:&#xD;&#xA;&#xD;&#xA;Mathematical completeness. A 3 by 4 or 4 by 3 matrix is not invertible (although that does not mean you couldn't calculate a inverse by other means just not by standard matrix algebra). Inverse is critical for hierarchy calculations. &#xD;&#xA;&#xD;&#xA;Now you could posit that the  last computer part is always same and be done with it. But having worked for a company that in their main software did just this i would say that it is a mistake. Well, sure now the matrices are invertible but not general. I can now not safely transpose my matrices for example. The truth is that i lose out on a lot of possible mathematics knowledge that i could use because this one part is missing. At the end this was a common source of errors, anger and confusion among clients.&#xD;&#xA; &#xD;&#xA;Homogeneous coordinates are just one possible application of this mathematical completeness. It turns out to be very useful if you want to model perspective. But its far from the only benefit.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23641" PostHistoryTypeId="5" PostId="8728" RevisionGUID="7c988d1e-4320-4386-8611-043e1dd64479" CreationDate="2019-04-03T16:12:06.987" UserId="7952" Comment="added 226 characters in body" Text="Edit: The question, as asked, is a bit vague since it eludes to a specific usage of 4x4 matrices. The answer below responds to the question &quot;What is the meaning of the 4th row in a homogenous affine transformation matrix?&quot;&#xD;&#xA;&#xD;&#xA;In a 3x3 matrix you cannot specify translation, as you have already pointed out. But in 4 dimensions you CAN give a translation. So you pretty much gave the most basic answer in your question. And in fact some math libraries have optimized &quot;4x4&quot; matrix classes that assume the last row/column is &quot;0,0,0,1&quot;. It works out rather nicely and allows code to execute a bit faster since a few calculations can be omitted.&#xD;&#xA;&#xD;&#xA;In your question you asked what is that last row used for, but really the first question you should be asking is &quot;why is that last value in the row a 1?&quot;&#xD;&#xA;&#xD;&#xA;To best understand it go back to two dimensions where we could use a &quot;2x2&quot; matrix to describe everything. But immediately the math lib runs into the same problem as using a &quot;3x3&quot; matrix in 3 dimensions. The 2x2 matrix can't describe translations. But if you bump the 2x2 matrix up to a 3x3 matrix now all of a sudden you CAN do translations. But here again you have that row of &quot;0,0,1&quot;. But this time it is much easier to visualize that all of our 2 dimensional math is happening in a single plane of 3 dimensions. And it is the 1st plane in the Z dimension as indicated by our last row &quot;1&quot;. But what about those zero's?&#xD;&#xA;&#xD;&#xA;Well now a whole host of questions comes up. Like, if a vector has only direction and magnitude what should a 2 dimensional vectors Z value be in 3 dimensions? What about a 2 dimensional point in 3 dimensions? That answer to that is somewhat intuitive when you focus on &quot;a vector has no location&quot;. This should scream ZERO. Which translates to infinity. But a point, which MUST be located inside our 2 dimensional space must also be in the same plane as all the other points and we all ready know that our chosen plane on the Z axis is 1. (Think about how a vector is formed from 2 points, if both points lie in the same Z plane of 1 then the resulting vector has a Z value of zero)&#xD;&#xA;&#xD;&#xA;This I hope is a woe moment. Because now it starts to be very clear that vectors and points are fundamentally different creatures. And all those zero's and the one in the last row/column of a 4x4 matrix now say very clearly that we have 3 vectors and one point, and that point is the translation, which suddenly makes the entire thing make sense.&#xD;&#xA;&#xD;&#xA;That is the fundamental meaning of that row. But the beauty of linear algebra means that we don't have to force those last values to lie in the W plane &quot;1&quot; (traditionally in 4 dimensions the letter chosen for the 4th dimension is W so a vector now has X,Y,Z,W values) of our 4x4 matrix. Or even that we have to use 3 vectors and 1 point. Which leads to perspectives, scales, and other fun in the 4th dimension.&#xD;&#xA;&#xD;&#xA;Thats my answer and I'm stickin to it!" ContentLicense="CC BY-SA 4.0" />
  <row Id="23642" PostHistoryTypeId="12" PostId="8728" RevisionGUID="3bca1e21-7fd4-4825-927c-976bb475c21a" CreationDate="2019-04-03T16:32:08.317" UserId="7952" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7952,&quot;DisplayName&quot;:&quot;pmw1234&quot;}]}" />
  <row Id="23643" PostHistoryTypeId="2" PostId="8729" RevisionGUID="eec04569-e9a1-4b74-8132-f7491c8c7833" CreationDate="2019-04-03T17:01:30.820" UserId="7622" Text="Is there an efficient way to identify the plane of symmetry in a 3D mesh? Preferably with existing code / software but if anyone knows how to implement it that would also be helpful.&#xD;&#xA;&#xD;&#xA;Example of the problem: you have a 3D mesh of a duck that is centered at the origin. The correct answer in this case would be the plane where x = 0." ContentLicense="CC BY-SA 4.0" />
  <row Id="23644" PostHistoryTypeId="1" PostId="8729" RevisionGUID="eec04569-e9a1-4b74-8132-f7491c8c7833" CreationDate="2019-04-03T17:01:30.820" UserId="7622" Text="Identify plane of symmetry in 3D mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="23645" PostHistoryTypeId="3" PostId="8729" RevisionGUID="eec04569-e9a1-4b74-8132-f7491c8c7833" CreationDate="2019-04-03T17:01:30.820" UserId="7622" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23646" PostHistoryTypeId="2" PostId="8730" RevisionGUID="d81224c5-2451-4f45-bd2a-293d2cc41054" CreationDate="2019-04-03T17:03:39.923" UserId="228" Text="I was wondering if there's any known technique/algorithm that would compute a mesh generated by the marching cubes but hierarchically (like a divide and conquer strategy), in the implementation I know (that follows the original paper) the marching cubes is an incremental algorithm that iterates through all the voxels (regardless if they're empty or not) and it will produce from 1 to 4 triangles per voxel.&#xD;&#xA;&#xD;&#xA;Either this or a very fast implementation of marching cubes is fine.&#xD;&#xA;&#xD;&#xA;I cannot manage to find any reference." ContentLicense="CC BY-SA 4.0" />
  <row Id="23647" PostHistoryTypeId="1" PostId="8730" RevisionGUID="d81224c5-2451-4f45-bd2a-293d2cc41054" CreationDate="2019-04-03T17:03:39.923" UserId="228" Text="Very efficient/fast marching cube implementation" ContentLicense="CC BY-SA 4.0" />
  <row Id="23648" PostHistoryTypeId="3" PostId="8730" RevisionGUID="d81224c5-2451-4f45-bd2a-293d2cc41054" CreationDate="2019-04-03T17:03:39.923" UserId="228" Text="|algorithm|computational-geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23649" PostHistoryTypeId="5" PostId="5673" RevisionGUID="1f9d12bd-9d13-45d8-b663-ac7d14661604" CreationDate="2019-04-03T17:21:41.760" UserId="2654" Comment="deleted 231 characters in body" Text="The specification [has been clarified on this point][3], as has the Wiki article. So let's explain that.&#xD;&#xA;&#xD;&#xA;The new wording in the spec says:&#xD;&#xA;&#xD;&#xA;&gt;  the samples-passed count is incremented for each fragment still being processed after the depth test&#xD;&#xA;&#xD;&#xA;This is better wording, as it makes clear that the order in which things are processed matters. OpenGL [defines the depth test as happening after the stencil test, scissor test, etc][1]. So this wording clearly states that the depth test, and everything before it, matter.&#xD;&#xA;&#xD;&#xA;So it does respect the stencil test. And fragment shader `discard`, since the FS is specified to come before all of these tests.&#xD;&#xA;&#xD;&#xA;Well, unless you [force these tests to happen before the fragment shader][2]. If you do that, then `discard`ing the fragment in the FS will not prevent that fragment from being counted by the occlusion query. So if you enforce early tests, you lose the right to use `discard` to affect the occlusion query count.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Per-Sample_Processing&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Early_Fragment_Test#Explicit_specification&#xD;&#xA;  [3]: https://github.com/KhronosGroup/OpenGL-API/issues/19" ContentLicense="CC BY-SA 4.0" />
  <row Id="23650" PostHistoryTypeId="13" PostId="5673" RevisionGUID="df7d8de3-a76f-4065-a720-33f631d1ce26" CreationDate="2019-04-03T17:21:45.567" UserId="2654" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;}]}" />
  <row Id="23651" PostHistoryTypeId="2" PostId="8731" RevisionGUID="ed835ebf-21ff-42bf-b09b-22ef55609a78" CreationDate="2019-04-03T17:54:26.537" UserId="10426" Text="I have been trying to implement GLM (math library) into Visual Studio with OpenGL. I have followed and watched many online resources that point me to include only the GLM folder inside the downloadable zip file into Visual Studio. I believe I have also put the correct relative path in the additional include directories tab. I put the GLM folder into a file I named src/vendor, along with another header file that already works correctly. Visual Studio also is able to be include GLM as #include &quot;glm/glm.hpp&quot;. The configuration is set properly as well, as in it matches debug/x86. &#xD;&#xA;&#xD;&#xA;The issue is apparent when I build the project though, as it is saying that it cannot find any files with the path &quot;src\vendor\glm\test\core\\*randomheaderfiles*.&#xD;&#xA;&#xD;&#xA;All the resources have not said to include the test file of the downloadable zip, or any other file for that matter, except the &quot;glm&quot; file. So what is the issue? I also get a warning saying &quot;Two or more files with the name of glm.cpp will produce outputs to the same location&quot;, but they both have the same path of &quot;src\vendor\glm\detail\glm.cpp&quot;, and I only found one of those files with that name there.&#xD;&#xA;&#xD;&#xA;I did try to put the &quot;test&quot; file of the GLM downloadable zip file into the project as well, but that did not seem to help.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23652" PostHistoryTypeId="1" PostId="8731" RevisionGUID="ed835ebf-21ff-42bf-b09b-22ef55609a78" CreationDate="2019-04-03T17:54:26.537" UserId="10426" Text="Difficulty including GLM into Visual Studio with OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="23653" PostHistoryTypeId="3" PostId="8731" RevisionGUID="ed835ebf-21ff-42bf-b09b-22ef55609a78" CreationDate="2019-04-03T17:54:26.537" UserId="10426" Text="|opengl|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23654" PostHistoryTypeId="2" PostId="8732" RevisionGUID="335b0d94-7ef4-41ca-b771-a7fc2a0f7bb8" CreationDate="2019-04-03T18:50:52.213" UserId="8565" Text="According to this [note][1], Frostbite use photometry unit in their calculation. I am trying to mimic this feature, but I am not sure what transformation need to be done. I will try to explain what I have in mind.&#xD;&#xA;&#xD;&#xA;First we do gamma correction(pow(2.2)) to the albedo texture. Then we apply the BRDF that takes luminance as input and will produce output luminance. After that we do tonemapping(say we use filmic tone mapping) and then inverse gamma correct pow(1/2.2) and store it to the framebuffer. &#xD;&#xA;&#xD;&#xA;Is this process correct? Should I transform the luminance to radiance first before doing the tonemap or maybe I should convert it even before that when doing BRDF calculation? Do I need to convert the albedo with photometry curve after doing gamma correction?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="23655" PostHistoryTypeId="1" PostId="8732" RevisionGUID="335b0d94-7ef4-41ca-b771-a7fc2a0f7bb8" CreationDate="2019-04-03T18:50:52.213" UserId="8565" Text="How to implement physically based unit in pbr renderer" ContentLicense="CC BY-SA 4.0" />
  <row Id="23656" PostHistoryTypeId="3" PostId="8732" RevisionGUID="335b0d94-7ef4-41ca-b771-a7fc2a0f7bb8" CreationDate="2019-04-03T18:50:52.213" UserId="8565" Text="|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23657" PostHistoryTypeId="2" PostId="8733" RevisionGUID="41d15d7c-164e-4dac-a89a-612226075cdc" CreationDate="2019-04-04T05:10:28.810" UserId="3003" Text="An [equirectangular projection](https://en.wikipedia.org/wiki/Equirectangular_projection) treats the x coordinate as the angle theta around the vertical axis going from 0 to 360 degrees. These angles match the longitudinal angles of a globe. The y coordinate is treated as the angle phi that represents the latitudes of a globe. They typically go from +90° at the zenith (or north pole) to -90° at the nadir (or south pole).&#xD;&#xA;&#xD;&#xA;So to translate the center of projection of an image by some amount (x0, y0), you  can simply add x0 to the x value of every coordinate (wrapping around to the other side at the edges). The y coordinate is similar - add y0 to every coordinate.  However, instead of wrapping around, you need to reflect the value. So if your new coordinate is less than 0, simply take the absolute value. If it's greater than the height, take the difference between the new value and the height of the image and subtract that from the height of the image. If it was less than 0 or greater than height then you need to also add half the width to the x coordinate.&#xD;&#xA;&#xD;&#xA;So putting it in pseudocode:&#xD;&#xA;&#xD;&#xA;    newY = oldY + translateY;&#xD;&#xA;    if (newY &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        newY = fabs(newY);&#xD;&#xA;        translateX = fmod((translateX + (width / 2.0)), width);&#xD;&#xA;    }&#xD;&#xA;    else if (newY &gt;= height)&#xD;&#xA;    {&#xD;&#xA;        newY = height - (newY - height);&#xD;&#xA;        translateX = fmod((translateX + (width / 2.0)), width);&#xD;&#xA;    }&#xD;&#xA;    newX = oldX + translateX;&#xD;&#xA;    if (newX &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        newX = width + newX;&#xD;&#xA;    }&#xD;&#xA;    else if (newX &gt;= width)&#xD;&#xA;    {&#xD;&#xA;        newX = newX - width;&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23658" PostHistoryTypeId="2" PostId="8734" RevisionGUID="cdf621f5-4d14-4d6a-aaaa-d48a382f96a1" CreationDate="2019-04-04T06:06:36.230" UserId="5066" Text="Most likely it's a problem with how you have provided relative path to library in visual studio &quot;Additional Include Directories&quot; section. What happens when you right click on  #include &quot;glm/glm.hpp&quot; line in visual studio and say &quot;Open document &quot;glm/glm.hpp&quot;? I am sure you have tried this but just minor check to see if include path is correct or not. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23659" PostHistoryTypeId="2" PostId="8735" RevisionGUID="bc8c81b6-fef5-4a5a-b7dd-52705f085ed1" CreationDate="2019-04-04T06:11:13.430" UserId="10096" Text="You can look into this: https://cescg.org/wp-content/uploads/2017/03/Dvo%C5%99%C3%A1k-Estimating-Approximate-Plane-of-Symmetry-of-3D-Triangle-Meshes.pdf&#xD;&#xA;There are definitely other papers on the subject though" ContentLicense="CC BY-SA 4.0" />
  <row Id="23660" PostHistoryTypeId="5" PostId="8724" RevisionGUID="7e73080b-b848-4517-9a56-67c30f33a0ad" CreationDate="2019-04-04T07:58:25.887" UserId="209" Comment="minor spelling correction" Text="It could be generated as a Lindenmayer System (L-system) with some rules for branch widths (plus some fractal noise) and branch bifurcation. They are parameters you can play with.&#xD;&#xA;&#xD;&#xA;You can find lots of resources in the [website](http://algorithmicbotany.org) of the Biological Modeling and Visualization research group in the Department of Computer Science at the University of Calgary. Professor Przemyslaw Prusinkiewicz is the researcher who popularized these systems, and he has made his [main book](http://algorithmicbotany.org/papers/abop/abop.pdf) *The algorithmic beauty of plants* available for free.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23661" PostHistoryTypeId="5" PostId="8725" RevisionGUID="c3468fbb-0719-452a-9293-6925f717fd28" CreationDate="2019-04-04T13:47:28.953" UserId="2041" Comment="I managed to type the exact opposite of what I was thinking. " Text="Normally when we talk about realistic transparent volumes, we care about refraction (and total internal reflection), and we care about scattering. But there's a much simpler case of volume transparency, where the opacity of the object depends on the distance that light travels through it.&#xD;&#xA;&#xD;&#xA;I'm writing a real-time visualization with a forward-rendering pipeline (on WebGL) and I'd like to show transparent solids this way, without having to resort to path tracing. My solids are homogeneous and isotropic, and I'm not interested in scattering or refraction. I just want thin parts of the solid to be very transparent and thicker parts of the solid to be more opaque.&#xD;&#xA;&#xD;&#xA;It seems like most real-time transparency algorithms (e.g. OIT) are mainly for getting surfaces/sheets right, instead of volumes, and are more concerned about correct stacking, refraction, and scattering.&#xD;&#xA;&#xD;&#xA;It seems like making the colour of the object depend on the thickness of material behind each fragment should be easily achievable with something like an extra depth pass where I draw opaque objects that intersect transparent objects, and back faces of transparent objects, possibly with some extra correction where the notional ray for one pixel goes through a torus-like object more than once. Intuition tells me that this ought to be a standard algorithm, but I don't know of one. Does this algorithm already exist, or do I just need to get my pencil and paper out and write one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23662" PostHistoryTypeId="5" PostId="8726" RevisionGUID="16c64e84-4d7b-44d4-9d87-a604b45abf9d" CreationDate="2019-04-04T16:12:57.413" UserId="10096" Comment="added 2204 characters in body" Text="The issue is that an extra depth pass won't cut it. You may need an arbitrary number of extra depth passes. Just imagine the volume between two sinusoidal surfaces, you would have infinitely many alternating z-intervals of volume/empty space as long as you're looking from a specific direction.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;Taking into consideration the updated formulation, here's my suggestion for a rather general algorithm with different attenuation coefficients $\kappa_i$ for each volume. Note that there are non-trivial parts that are missing, also if you do not require different attenuation coefficients it can be optimized even further.&#xD;&#xA;The algorithm relies on you drawing the volumes pixels in reverse z-order (this is the non-trivial missing part). You draw your volumes in a separate pass. You keep an attenuation density accumulation variable $\kappa$ for each pixel (initialize to $0$), as well as a distance time stamp $\delta$ (initialize to the the $z$ of the far plane, which I will denote $\max$), and a &quot;color&quot; variable $c$ (initialize to $0$). Whenever you draw a pixel:&#xD;&#xA;&#xD;&#xA; - if $\delta==\max$ and you drew a front face of volume $i$ then:&#xD;&#xA;$$d = \delta-pixelDepth$$&#xD;&#xA;$$c = attenuate(c,\kappa_i,d)$$&#xD;&#xA;&#xD;&#xA;Where $\kappa_i$ is the attenuation of the currently drawn pixel (you can simply draw the volumes in the &quot;color&quot; of their attenuation and use that).&#xD;&#xA;&#xD;&#xA;- if $\delta&lt;\max$ and you drew a back face of volume $i$ then:&#xD;&#xA;&#xD;&#xA;$$d = pixelDepth - \delta$$&#xD;&#xA;$$\delta = pixelDepth$$&#xD;&#xA;$$c = attenuate(c,\kappa, d)$$&#xD;&#xA;$$\kappa = \kappa + \kappa_i$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- if $\delta&lt;\max$ and you drew a front face of volume $i$ then:&#xD;&#xA;$$d = pixelDepth - \delta$$&#xD;&#xA;$$\delta = pixelDepth$$&#xD;&#xA;$$c = attenuate(c,\kappa, d)$$&#xD;&#xA;$$\kappa = \kappa - \kappa_i$$&#xD;&#xA;&#xD;&#xA;- after you've drawn all pixels if $\kappa &gt; 0$:&#xD;&#xA;$$c = attenuate(c,\kappa,\delta)$$&#xD;&#xA;&#xD;&#xA;Note that the 4th check handles the case where the camera is inside a volume (and it ends behind the camera), but the frustum is not entirely inside it. Similarly the first check handles the case where a volume is cutoff by the frustum. However, the case where the camera frustum is totally inside a volume is not handled (you can try to check this by verifying that the camera is inside a volume and then simply adding a constant to $\kappa$, then you have to modify the end case too, to check $&gt;const$, or just not have such large volumes).&#xD;&#xA;Note that the $\delta$ part can be handled by the depth buffer. Obviously you can use a compute shader, or use additional buffers to perform all of this. The function $attenuate$ can be standard Beer-Lambert uniform attenuation or whatever else you want. Combining the volumes with the original scene happens by setting the &quot;far plane&quot; for each pixel to the closest drawn solid geometry depth (that is initialize $\delta$ based on what you have in the depth buffer for your solid geometry)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23663" PostHistoryTypeId="5" PostId="8726" RevisionGUID="5d39d743-e8e2-45f6-97b0-ff3c9368212b" CreationDate="2019-04-04T16:20:06.560" UserId="10096" Comment="deleted 1 character in body" Text="The issue is that an extra depth pass won't cut it. You may need an arbitrary number of extra depth passes. Just imagine the volume between two sinusoidal surfaces, you would have infinitely many alternating z-intervals of volume/empty space as long as you're looking from a specific direction.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;Taking into consideration the updated formulation, here's my suggestion for a rather general algorithm with different attenuation coefficients $\kappa_i$ for each volume. Note that there are non-trivial parts that are missing, also if you do not require different attenuation coefficients it can be optimized even further.&#xD;&#xA;The algorithm relies on you drawing the volumes pixels in reverse z-order (this is the non-trivial missing part). You draw your volumes in a separate pass. You keep an attenuation density accumulation variable $\kappa$ for each pixel (initialize to $0$), as well as a distance time stamp $\delta$ (initialize to the the $z$ of the far plane, which I will denote $\max$), and a &quot;color&quot; variable $c$ (initialize to $0$). Whenever you draw a pixel:&#xD;&#xA;&#xD;&#xA; - if $\delta==\max$ and you drew a front face of volume $i$ then:&#xD;&#xA;$$d = \delta-pixelDepth$$&#xD;&#xA;$$c = attenuate(c,\kappa_i,d)$$&#xD;&#xA;&#xD;&#xA;Where $\kappa_i$ is the attenuation of the currently drawn pixel (you can simply draw the volumes in the &quot;color&quot; of their attenuation and use that).&#xD;&#xA;&#xD;&#xA;- if $\delta&lt;\max$ and you drew a back face of volume $i$ then:&#xD;&#xA;&#xD;&#xA;$$d = \delta - pixelDepth$$&#xD;&#xA;$$\delta = pixelDepth$$&#xD;&#xA;$$c = attenuate(c,\kappa, d)$$&#xD;&#xA;$$\kappa = \kappa + \kappa_i$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- if $\delta&lt;\max$ and you drew a front face of volume $i$ then:&#xD;&#xA;$$d = \delta -pixelDepth$$&#xD;&#xA;$$\delta = pixelDepth$$&#xD;&#xA;$$c = attenuate(c,\kappa, d)$$&#xD;&#xA;$$\kappa = \kappa - \kappa_i$$&#xD;&#xA;&#xD;&#xA;- after you've drawn all pixels if $\kappa &gt; 0$:&#xD;&#xA;$$c = attenuate(c,\kappa,\delta)$$&#xD;&#xA;&#xD;&#xA;Note that the 4th check handles the case where the camera is inside a volume (and it ends behind the camera), but the frustum is not entirely inside it. Similarly the first check handles the case where a volume is cutoff by the frustum. However, the case where the camera frustum is totally inside a volume is not handled (you can try to check this by verifying that the camera is inside a volume and then simply adding a constant to $\kappa$, then you have to modify the end case too, to check $&gt;const$, or just not have such large volumes).&#xD;&#xA;Note that the $\delta$ part can be handled by the depth buffer. Obviously you can use a compute shader, or use additional buffers to perform all of this. The function $attenuate$ can be standard Beer-Lambert uniform attenuation or whatever else you want. Combining the volumes with the original scene happens by setting the &quot;far plane&quot; for each pixel to the closest drawn solid geometry depth (that is initialize $\delta$ based on what you have in the depth buffer for your solid geometry)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23664" PostHistoryTypeId="2" PostId="8736" RevisionGUID="b0c4ef34-8aea-4f0b-9f57-01735d35eed0" CreationDate="2019-04-04T17:03:32.227" UserId="7952" Text="This seems to be eluding to a Marching Cubes LOD algorithm such as: Place the entire volume in one giant cube. Break that volume into NxNxN cubes. And continue doing so until the cubes are at the finest granularity needed for the density function about 8 level works. Each volume then responds with either: No voxels - stop processing that sub volume OR Yes there are voxels -- process the sub volumes and keeping doing this until:  the voxel level is reached. Finally set a LOD - such as equating a screen space distance range to each subvolume level and treat the subvolume for that LOD as the final voxel.&#xD;&#xA;&#xD;&#xA;There is also Eric Lengyel's Transvoxel algorithm: https://transvoxel.org" ContentLicense="CC BY-SA 4.0" />
  <row Id="23665" PostHistoryTypeId="5" PostId="8736" RevisionGUID="410214f1-fc54-44f7-bfc3-552e7cb8495a" CreationDate="2019-04-04T17:13:35.787" UserId="7952" Comment="added 82 characters in body" Text="This seems to be eluding to a Marching Cubes LOD algorithm such as: Place the entire volume in one giant cube. Break that volume into NxNxN cubes. And continue doing so until the cubes are at the finest granularity needed for the density function about 8 level works. Each volume then responds with either: No voxels - stop processing that sub volume OR Yes there are voxels -- process the sub volumes and keeping doing this until:  the voxel level is reached. Finally set a LOD - such as equating a screen space distance range to each subvolume level and treat the subvolume for that LOD as the final voxel. Cracks are a major issue with this algorithm and why you won't see many implementation of it.&#xD;&#xA;&#xD;&#xA;There is also Eric Lengyel's Transvoxel algorithm: https://transvoxel.org&#xD;&#xA;&#xD;&#xA;and here is a link an implementation of it&#xD;&#xA;https://github.com/stoyannk/voxels" ContentLicense="CC BY-SA 4.0" />
  <row Id="23666" PostHistoryTypeId="2" PostId="8737" RevisionGUID="c6b480b9-a592-4551-9fc7-ebd8a4801bf5" CreationDate="2019-04-05T00:35:06.787" UserId="10431" Text="My lecturer for a computer graphics (raytracing) paper has stated that &lt;i&gt;'It is easier to apply the inverse transform to the world than it is to apply the transform to the camera.'&lt;/i&gt; The example given was that is it easier to shift all objects in a scene 5 units to the left than it is to shift the camera 5 units to the right.&#xD;&#xA;&#xD;&#xA;This seems to imply that it's easier to iterate through and transform multiple objects in a scene than it is to apply a single transformation to the camera. &#xD;&#xA;&#xD;&#xA;Is this correct, and if so, why is this the case?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23667" PostHistoryTypeId="1" PostId="8737" RevisionGUID="c6b480b9-a592-4551-9fc7-ebd8a4801bf5" CreationDate="2019-04-05T00:35:06.787" UserId="10431" Text="Why is it easier to inverse transform every object in a scene than to transform a camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23668" PostHistoryTypeId="3" PostId="8737" RevisionGUID="c6b480b9-a592-4551-9fc7-ebd8a4801bf5" CreationDate="2019-04-05T00:35:06.787" UserId="10431" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23670" PostHistoryTypeId="2" PostId="8738" RevisionGUID="2819e02f-c8be-4deb-8304-cdb23bd787dd" CreationDate="2019-04-05T04:49:23.210" UserId="10096" Text="That's actually incorrect. You can transform every ray of your camera if you wish (and numerous implementations do so). There are some advantages and disadvantages to each method (e.g. if your rays are more than your vertices you end up doing more transformations, however you don't incur cache misses by running over all vertices)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23671" PostHistoryTypeId="2" PostId="8739" RevisionGUID="42d24fde-3213-46e8-bdb4-09e22a69cf79" CreationDate="2019-04-05T09:45:14.540" UserId="7008" Text="&gt; First we do gamma correction&#xD;&#xA;&#xD;&#xA;1. Make sure you actually need to do gamma correction on the albedo texture (or rather &quot;uncorrection&quot;, i.e. making it linear). Not all textures are stored in sRGB color space. Also, you're doing it the wrong way around: Going from sRGB to linear color space you need to do the `pow(1/2.2)` part here and the `pow(2.2)` part in the end.&#xD;&#xA;&#xD;&#xA;&gt; Should I transform the luminance to radiance first before doing the tonemap or maybe I should convert it even before that when doing BRDF calculation?&#xD;&#xA;&#xD;&#xA;2. Yes you should convert before doing the BRDF calculation. Tonemapping is not a feature that's part of the actual physical simulation of light, therefore it doesn't &quot;need&quot; any physical units. The BRDF however is, and here you should make sure that your units &quot;add up&quot;. E.g. you wouldn't calculate the surface area of a rectangle by using meters as the unit for one side and inches as the unit for another side.&#xD;&#xA;&#xD;&#xA;&gt; Do I need to convert the albedo with photometry curve after doing gamma correction?&#xD;&#xA;&#xD;&#xA;3. I'm not entirely sure here, but I think you don't need to do that. The albedo color basically tells you, how much of a certain light will be reflected. Since you change your light to photometric units (if you do it as suggested in the Frostbite notes), than I would say this already taken care of. You could also look at it like this: Since the color is a ratio and thus unit-less, there is no need to convert it from unit to another.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/5449/tone-mapping-gamma-correction" ContentLicense="CC BY-SA 4.0" />
  <row Id="23672" PostHistoryTypeId="2" PostId="8740" RevisionGUID="e8f3acb0-d793-4603-9610-6be809eccfd5" CreationDate="2019-04-05T09:59:59.973" UserId="10435" Text="I am trying to generate UV coordinates automatically to map a texture on a sphere.&#xD;&#xA;&#xD;&#xA;The problem is with seams when going from 0.8 to 0.2 there is a discontinuity and interpolation in fragment shader is incorrect. It should go from 0.8 to 1 and then from 1 to 0.2. But instead it will interpolate directly between 0.8 to 0.2.&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/UV_mapping&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How to handle this discontinuity from 1 -&gt; 0.&#xD;&#xA;&#xD;&#xA;Here is what is currently happening at the seams &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2HK25.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/UPDcX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/6Fg4m.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23673" PostHistoryTypeId="1" PostId="8740" RevisionGUID="e8f3acb0-d793-4603-9610-6be809eccfd5" CreationDate="2019-04-05T09:59:59.973" UserId="10435" Text="Sphere Texture Mapping Algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="23674" PostHistoryTypeId="3" PostId="8740" RevisionGUID="e8f3acb0-d793-4603-9610-6be809eccfd5" CreationDate="2019-04-05T09:59:59.973" UserId="10435" Text="|opengl|shader|texture|uv-mapping|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23675" PostHistoryTypeId="2" PostId="8741" RevisionGUID="ac8d8757-f8f6-4d67-9ab3-82e1e8aa5c18" CreationDate="2019-04-05T15:57:45.490" UserId="137" Text="A few options:&#xD;&#xA;&#xD;&#xA;1. Make the 0-1 discontinuity explicit in the mesh. That is create a 2 sets of vertices that lie exactly on the line where the value would be 1 or 0 (one set gets 1 and one gets 0) then connect the vertices up like they would makes sense.&#xD;&#xA;&#xD;&#xA;2. Switch to a different texture mapping projection, I prefer a cubemap because it minimizes distortion at the poles and you don't need to have seams in the mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="23676" PostHistoryTypeId="2" PostId="8742" RevisionGUID="21ba23e6-7121-4984-95bb-31d80d65d280" CreationDate="2019-04-06T14:04:33.583" UserId="10447" Text="If I have a straight line in 3D space and I use a camera matrix to do a perspective projection into a 2D plane/screen will the resulting line always be straight too? If I project the start point and end point and join the dots is that equivalent to having projected the line?&#xD;&#xA;&#xD;&#xA;I suspect this is true, but have no basis for this assumption. &#xD;&#xA;&#xD;&#xA;Is this still true for off-centre perspective projection or a cylindrical projection? I assume this isn't true for real cameras as they have all kinds of non-ideal optical effects right?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23677" PostHistoryTypeId="1" PostId="8742" RevisionGUID="21ba23e6-7121-4984-95bb-31d80d65d280" CreationDate="2019-04-06T14:04:33.583" UserId="10447" Text="Do straight lines always remain straight when projected with a perspective camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23678" PostHistoryTypeId="3" PostId="8742" RevisionGUID="21ba23e6-7121-4984-95bb-31d80d65d280" CreationDate="2019-04-06T14:04:33.583" UserId="10447" Text="|geometry|projections|perspective|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23679" PostHistoryTypeId="2" PostId="8743" RevisionGUID="a86d2b78-c67e-4655-9c5c-8e29501242d0" CreationDate="2019-04-06T17:13:08.450" UserId="9749" Text="I am having trouble implementing an algorithm for 3rd degree NURBS.&#xD;&#xA;I have been able to program 2nd degree ones from the equations described [here][1] but I am not able to derive an equation for Rational B-Splines of degree 3. The author describes the Rational Knot Equation as [![NURBS][2]][2] that is a non-recursive form of the [De Boor's Algorithm][3]from there I was able to program **Rational Internal Control Points: Bn** and **Cn** as:&#xD;&#xA;&#xD;&#xA;    /* Note that I had to modify the equations to work from the first point on the list as the ones described in the article only took into account points from the second index **Pn+1**. I though that could have been the problem and rewrote them as they where originally written but that did not solve the issue, so I am posting the ones that work from **Pn** */&#xD;&#xA;&#xD;&#xA;    // Point B. &#xD;&#xA;    /* Iterate over the points(3d vector), knots(double) and weights(double) lists to get the Internal Control Points(3d vector) for the 3rd degree Bézier curves. */&#xD;&#xA;&#xD;&#xA;     // Precompute:&#xD;&#xA;    double knotE = ( knots[i + 4] - knots[i + 2] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;    double knotEO = ( knots[i + 2] - knots[i + 1] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;&#xD;&#xA;    double rationalWeight = (  weights[i] * knotE ) + ( weights[i + 1] * knotEO );&#xD;&#xA;    double w1 = weights[i] / rationalWeight;&#xD;&#xA;    double w2 = weights[i + 1] / rationalWeight;&#xD;&#xA;&#xD;&#xA;    /* Our Point3d class lets us multiply a vector by a scalar. */&#xD;&#xA;    Point3d b = new Point3d( ( knotE * points[i] * w1 ) + ( knotEO * points[i + 1] * w2 ) );&#xD;&#xA;&#xD;&#xA;    // Point C. &#xD;&#xA;    /* Iterate over the points, knots and weights lists to get the Internal Control Points for the 3rd degree Bézier curves. */&#xD;&#xA;&#xD;&#xA;     // Precompute:&#xD;&#xA;    double knotE = ( knots[i + 4] - knots[i + 3] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;    double knotEO = ( knots[i + 3] - knots[i + 1] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;&#xD;&#xA;    double rationalWeight = (  weights[i] * knotE ) + ( weights[i + 1] * knotEO );&#xD;&#xA;    double w1 = weights[i] / rationalWeight;&#xD;&#xA;    double w2 = weights[i + 1] / rationalWeight;&#xD;&#xA;&#xD;&#xA;    /* Our Point3d class lets us multiply a vector by a scalar. */&#xD;&#xA;    Point3d c = new Point3d( ( knotE * points[i] * w1 ) + ( knotEO * points[i + 1] * w2 ) );&#xD;&#xA;&#xD;&#xA;But when I apply the same process for point **Vn** I get results that are not the ones I am looking for:&#xD;&#xA;&#xD;&#xA;    // Point V. &#xD;&#xA;    /* Iterate over the c, b, knots and weights lists to get the Internal Control Points for the 3rd degree Bézier curves. */&#xD;&#xA;&#xD;&#xA;     // Precompute:&#xD;&#xA;    double knotE = ( knots[i + 4] - knots[i + 3] ) / ( knots[i + 4] - knots[i + 2] );&#xD;&#xA;    double knotEO = ( knots[i + 3] - knots[i + 2] ) / ( knots[i + 4] - knots[i + 2] );&#xD;&#xA;&#xD;&#xA;    double rationalWeight = (  weights[i] * knotE ) + ( weights[i + 1] * knotEO );&#xD;&#xA;    double w1 = weights[i] / rationalWeight;&#xD;&#xA;    double w2 = weights[i + 1] / rationalWeight;&#xD;&#xA;&#xD;&#xA;    /* Our Point3d class lets us multiply a vector by a scalar. */&#xD;&#xA;    Point3d v = new Point3d( ( knotE * c[i] * w1 ) + ( knotEO * b[i + 1] * w2 ) );&#xD;&#xA;&#xD;&#xA;When all the weights are the same the points respond as expected, when the weights are not the same points **Bn** and **Cn** work as they should but **Vn** responds incorrectly. So my **Vn Equation** must be wrong. As the function inputs **Bn** and **Cn** lists of points my guess is that I am missing a relationship between those two equations with the one I am having trouble with.&#xD;&#xA;&#xD;&#xA;As my problem is with the mathematical concept instead of an inplementation this is considered a language agnostic question.&#xD;&#xA;&#xD;&#xA;Here's a picture of a 3d degree UniformBSpline [![UBS][4]][4] which I programmed succesfully already but that may help if the link to the resource goes down.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/Articles/996281/NURBS-curve-made-easy &quot;equations&quot;&#xD;&#xA;  [2]: https://i.stack.imgur.com/kmIJK.jpg&#xD;&#xA;  [3]: https://en.m.wikipedia.org/wiki/De_Boor%27s_algorithm&#xD;&#xA;  [4]: https://i.stack.imgur.com/29xeO.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23680" PostHistoryTypeId="1" PostId="8743" RevisionGUID="a86d2b78-c67e-4655-9c5c-8e29501242d0" CreationDate="2019-04-06T17:13:08.450" UserId="9749" Text="NURBS Weights De Boor's Algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="23681" PostHistoryTypeId="3" PostId="8743" RevisionGUID="a86d2b78-c67e-4655-9c5c-8e29501242d0" CreationDate="2019-04-06T17:13:08.450" UserId="9749" Text="|mathematics|computational-geometry|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23682" PostHistoryTypeId="5" PostId="8743" RevisionGUID="323cdaa9-b452-425b-bd9c-d3059c934b31" CreationDate="2019-04-06T19:11:50.997" UserId="9749" Comment="added 1 character in body" Text="I am having trouble implementing an algorithm for 3rd degree NURBS.&#xD;&#xA;I have been able to program 2nd degree ones from the equations described [here][1] but I am not able to derive an equation for Rational B-Splines of degree 3. The author describes the Rational Knot Equation as [![NURBS][2]][2] that is a non-recursive form of the [De Boor's Algorithm][3] from there I was able to program **Rational Internal Control Points: Bn** and **Cn** as:&#xD;&#xA;&#xD;&#xA;    /* Note that I had to modify the equations to work from the first point on the list as the ones described in the article only took into account points from the second index **Pn+1**. I though that could have been the problem and rewrote them as they where originally written but that did not solve the issue, so I am posting the ones that work from **Pn** */&#xD;&#xA;&#xD;&#xA;    // Point B. &#xD;&#xA;    /* Iterate over the points(3d vector), knots(double) and weights(double) lists to get the Internal Control Points(3d vector) for the 3rd degree Bézier curves. */&#xD;&#xA;&#xD;&#xA;     // Precompute:&#xD;&#xA;    double knotE = ( knots[i + 4] - knots[i + 2] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;    double knotEO = ( knots[i + 2] - knots[i + 1] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;&#xD;&#xA;    double rationalWeight = (  weights[i] * knotE ) + ( weights[i + 1] * knotEO );&#xD;&#xA;    double w1 = weights[i] / rationalWeight;&#xD;&#xA;    double w2 = weights[i + 1] / rationalWeight;&#xD;&#xA;&#xD;&#xA;    /* Our Point3d class lets us multiply a vector by a scalar. */&#xD;&#xA;    Point3d b = new Point3d( ( knotE * points[i] * w1 ) + ( knotEO * points[i + 1] * w2 ) );&#xD;&#xA;&#xD;&#xA;    // Point C. &#xD;&#xA;    /* Iterate over the points, knots and weights lists to get the Internal Control Points for the 3rd degree Bézier curves. */&#xD;&#xA;&#xD;&#xA;     // Precompute:&#xD;&#xA;    double knotE = ( knots[i + 4] - knots[i + 3] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;    double knotEO = ( knots[i + 3] - knots[i + 1] ) / ( knots[i + 4] - knots[i + 1] );&#xD;&#xA;&#xD;&#xA;    double rationalWeight = (  weights[i] * knotE ) + ( weights[i + 1] * knotEO );&#xD;&#xA;    double w1 = weights[i] / rationalWeight;&#xD;&#xA;    double w2 = weights[i + 1] / rationalWeight;&#xD;&#xA;&#xD;&#xA;    /* Our Point3d class lets us multiply a vector by a scalar. */&#xD;&#xA;    Point3d c = new Point3d( ( knotE * points[i] * w1 ) + ( knotEO * points[i + 1] * w2 ) );&#xD;&#xA;&#xD;&#xA;But when I apply the same process for point **Vn** I get results that are not the ones I am looking for:&#xD;&#xA;&#xD;&#xA;    // Point V. &#xD;&#xA;    /* Iterate over the c, b, knots and weights lists to get the Internal Control Points for the 3rd degree Bézier curves. */&#xD;&#xA;&#xD;&#xA;     // Precompute:&#xD;&#xA;    double knotE = ( knots[i + 4] - knots[i + 3] ) / ( knots[i + 4] - knots[i + 2] );&#xD;&#xA;    double knotEO = ( knots[i + 3] - knots[i + 2] ) / ( knots[i + 4] - knots[i + 2] );&#xD;&#xA;&#xD;&#xA;    double rationalWeight = (  weights[i] * knotE ) + ( weights[i + 1] * knotEO );&#xD;&#xA;    double w1 = weights[i] / rationalWeight;&#xD;&#xA;    double w2 = weights[i + 1] / rationalWeight;&#xD;&#xA;&#xD;&#xA;    /* Our Point3d class lets us multiply a vector by a scalar. */&#xD;&#xA;    Point3d v = new Point3d( ( knotE * c[i] * w1 ) + ( knotEO * b[i + 1] * w2 ) );&#xD;&#xA;&#xD;&#xA;When all the weights are the same the points respond as expected, when the weights are not the same points **Bn** and **Cn** work as they should but **Vn** responds incorrectly. So my **Vn Equation** must be wrong. As the function inputs **Bn** and **Cn** lists of points my guess is that I am missing a relationship between those two equations with the one I am having trouble with.&#xD;&#xA;&#xD;&#xA;As my problem is with the mathematical concept instead of an inplementation this is considered a language agnostic question.&#xD;&#xA;&#xD;&#xA;Here's a picture of a 3d degree UniformBSpline [![UBS][4]][4] which I programmed succesfully already but that may help if the link to the resource goes down.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/Articles/996281/NURBS-curve-made-easy &quot;equations&quot;&#xD;&#xA;  [2]: https://i.stack.imgur.com/kmIJK.jpg&#xD;&#xA;  [3]: https://en.m.wikipedia.org/wiki/De_Boor%27s_algorithm&#xD;&#xA;  [4]: https://i.stack.imgur.com/29xeO.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23695" PostHistoryTypeId="5" PostId="8595" RevisionGUID="a892d5cc-0182-4ce0-8f35-a56211a86158" CreationDate="2019-04-08T06:51:20.210" UserId="209" Comment="fixed grammar" Text="Two suggestions:&#xD;&#xA;&#xD;&#xA; 1. If your data is from an image you are displaying on a standard monitor, the chances are it is (or you are implicitly assuming that it's) in sRGB format. This [means that the colour components are not linear][1]. Ideally, you should first map into a linear colour space, do your filtering (e.g. blurring) operations, and then map back.   &#xD;&#xA;*(If you just want to try a cheap and cheerful approach, squaring each of the R G B components is not a terrible approach to &quot;linearise&quot; the values&#xD;&#xA; - obviously, use sqrt() to map back)*.  &#xD;&#xA;The alpha channel can be assumed to be linear.&#xD;&#xA;&#xD;&#xA; 2. Once in linear colour space, the next thing you want to do before filtering is to convert the pixels to a pre-multiplied-alpha format (AKA &quot;*associated colour*&quot;).  &#xD;&#xA;Basically, given 8bpc {A,R,G,B} pixel input, produce  {A, A\*R/255, A\*G/255, A\*B/255}.  You then do your averaging on this premultiplied data as above on all four channels, and then map back by dividing through by the resulting alpha (if A=0 then, choose, RGB=0).&#xD;&#xA;&#xD;&#xA;This *should* produce a better result. &#xD;&#xA;For more info I suggest reading through Jim Blinn's [&quot;Compositing, Part1: Theory&quot;][2].  &#xD;&#xA;Particularly, note the line &quot;*Additionally, we must use associated colors for any filtering or interpolation operations*&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Update*: Seems I've posted a [similar answer before][3] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_(%22gamma%22)&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/5517/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="23696" PostHistoryTypeId="2" PostId="8746" RevisionGUID="c49d0b33-ce7d-48bd-9f3b-fd29099babbf" CreationDate="2019-04-08T19:20:37.263" UserId="10096" Text="&quot;A not so simple approach&quot;. I may have messed a little bit too much with grouping the terms, do forgive my elementary math skills, it's a side effect of using tools like wolfram and mathematica too much.&#xD;&#xA;&#xD;&#xA;Without loss of generality we can assume that the near plane is given as $z=1$ (that is having normal $(0,0,1)$ and a point on it $(0,0,1)$) and the camera center (the reflected pinhole camera aperture point) is at $(0,0,0)$. Let $p,q \in \mathbb{R}^3$ be two points on a line (non-degenerate, meaning $p\ne q$, otherwise it's just a point and the projection is also a point - unless it's at $(0,0,0)$ then it's undefined). If the line defined by $p,q$ passes through $(0,0,0)$ the projection is a point and the requirement is trivially satisfied.&#xD;&#xA;Now let this not be the case. A perspective projection onto the plane through $(0,0,0)$ is given by $p' = \frac{p}{p_z}$, and $q' = \frac{q}{q_z}$. The line defined by $p,q$ is given as $r(\lambda) = p + \lambda(q-p), \lambda \in  \mathbb{R}$. Its projection is given by $r'(\lambda) = \frac{r(\lambda)}{r_z(\lambda)}$. Since $z=1$ for all projected points, then we need only study the $x,y$ coordinates. We want to show that any projected point $r'(\lambda)$ can be written as an affine combination of $p',q'$ (this defines a line). Taking that into account:&#xD;&#xA;$$p'+\mu(q'-p') = \frac{r(\lambda)}{r_z(\lambda)}$$&#xD;&#xA;$$(1-\mu)\frac{p}{p_z} + \mu\frac{q}{q_z} = \frac{p + \lambda(q-p)}{p_z + \lambda(q_z-p_z)}$$&#xD;&#xA;$$(1-\mu)q_z(p_z+\lambda(q_z-p_z))p + \mu p_z(p_z+\lambda(q_z-p_z))q = q_zp_z(p + \lambda(q-p))$$&#xD;&#xA;$$q_zp_z(p - \lambda p) + q^2_z\lambda p - \mu q_z(p_z+\lambda(q_z-p_z))p + \mu p_z(p_z+\lambda(q_z-p_z))q - q_zp_z(p - \lambda p) - q_zp_z\lambda q = 0$$&#xD;&#xA;$$(1-\mu)\lambda q^2_z p -\mu(1-\lambda)q_zp_z p + \mu(1-\lambda)p^2_zq - (1-\mu)\lambda p_zq_z q = 0$$&#xD;&#xA;$$(1-\mu)\lambda q_z(q_zp - p_zq) - \mu(1-\lambda)p_z(q_zp-p_zq) = 0$$&#xD;&#xA;$$((1-\mu)\lambda q_z - \mu(1-\lambda)p_z)(q_zp - p_zq) = 0$$&#xD;&#xA;&#xD;&#xA;For this to be satisfied one of the terms must be $0$. The first case concerns the second term: $p' = q'$, which we already considered as the trivial case. Then we must show that we can always pick a $\mu$ such that $(1-\mu)\lambda q_z - \mu(1-\lambda)p_z = 0$. Solve for $\mu$ and you get: $\mu = \frac{\lambda q_z}{(1-\lambda)p_z + \lambda q_z}$. Thus I have not only found that it is a straight line, but also the relationship between the parameterizations.&#xD;&#xA;&#xD;&#xA;In general a projection onto a different 2-manifold (not a plane) will not result in the lines remaining straight (think of a sphere or a cylinder).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23697" PostHistoryTypeId="5" PostId="8746" RevisionGUID="9fd6269d-1db7-4f53-8127-7fd6870fbdc6" CreationDate="2019-04-08T19:39:52.690" UserId="10096" Comment="added 17 characters in body" Text="&quot;A not so simple approach&quot;. I may have messed a little bit too much with grouping the terms, do forgive my elementary math skills, it's a side effect of using tools like wolfram and mathematica too much.&#xD;&#xA;&#xD;&#xA;Without loss of generality we can assume that the near plane is given as $z=1$ (that is having normal $(0,0,1)$ and a point on it $(0,0,1)$) and the camera center (the reflected pinhole camera aperture point) is at $(0,0,0)$. Let $p,q \in \mathbb{R}^3$ be two points on a line (non-degenerate, meaning $p\ne q$, otherwise it's just a point and the projection is also a point - unless it's at $(0,0,0)$ then it's undefined). If the line defined by $p,q$ passes through $(0,0,0)$ the projection is a point and the requirement is trivially satisfied.&#xD;&#xA;Now let this not be the case. A perspective projection onto the plane through $(0,0,0)$ is given by $p' = \frac{p}{p_z}$, and $q' = \frac{q}{q_z}$. The line defined by $p,q$ is given as $r(\lambda) = p + \lambda(q-p), \lambda \in  \mathbb{R}$. Its projection is given by $r'(\lambda) = \frac{r(\lambda)}{r_z(\lambda)}$. Since $z=1$ for all projected points, then we need only study the $x,y$ coordinates. We want to show that any projected point $r'(\lambda)$ can be written as an affine combination of $p',q'$ (this defines a line). Taking that into account:&#xD;&#xA;$$p'+\mu(q'-p') = \frac{r(\lambda)}{r_z(\lambda)}$$&#xD;&#xA;$$(1-\mu)\frac{p}{p_z} + \mu\frac{q}{q_z} = \frac{p + \lambda(q-p)}{p_z + \lambda(q_z-p_z)}$$&#xD;&#xA;$$(1-\mu)q_z(p_z+\lambda(q_z-p_z))p + \mu p_z(p_z+\lambda(q_z-p_z))q = q_zp_z(p + \lambda(q-p))$$&#xD;&#xA;$$q_zp_z(p - \lambda p) + q^2_z\lambda p - \mu q_z(p_z+\lambda(q_z-p_z))p + \mu p_z(p_z+\lambda(q_z-p_z))q - q_zp_z(p - \lambda p) - q_zp_z\lambda q = 0$$&#xD;&#xA;$$(1-\mu)\lambda q^2_z p -\mu(1-\lambda)q_zp_z p + \mu(1-\lambda)p^2_zq - (1-\mu)\lambda p_zq_z q = 0$$&#xD;&#xA;$$(1-\mu)\lambda q_z(q_zp - p_zq) - \mu(1-\lambda)p_z(q_zp-p_zq) = 0$$&#xD;&#xA;$$((1-\mu)\lambda q_z - \mu(1-\lambda)p_z)(q_zp - p_zq) = 0$$&#xD;&#xA;&#xD;&#xA;For this to be satisfied one of the terms must be $0$. The first case concerns the second term: $p' = q'$, which we already considered as the trivial case. Then we must show that we can always pick a $\mu$ such that $(1-\mu)\lambda q_z - \mu(1-\lambda)p_z = 0$. Solve for $\mu$ and you get: $\mu = \frac{\lambda q_z}{(1-\lambda)p_z + \lambda q_z}$. Thus I have not only found that it is a straight line, but also the relationship between the parameterizations.&#xD;&#xA;&#xD;&#xA;In general a projection onto a different 2-manifold (not a plane) will not result in the lines remaining straight (think of a sphere or a cylinder).&#xD;&#xA;&#xD;&#xA;Btw 420 blaze it, don't destroy it pls." ContentLicense="CC BY-SA 4.0" />
  <row Id="23698" PostHistoryTypeId="50" PostId="8246" RevisionGUID="dd1ab5c2-631e-4ee1-b987-f5e369944df9" CreationDate="2019-04-09T01:02:20.573" UserId="-1" />
  <row Id="23699" PostHistoryTypeId="2" PostId="8747" RevisionGUID="be9d6491-e575-4bc7-b40d-f2a6677c64b1" CreationDate="2019-04-09T13:47:48.937" UserId="10461" Text="Background: Im reading https://learnopengl.com/PBR to learn about PBR. In the theory slide (https://learnopengl.com/PBR/Theory), the author has the reflectant equation as&#xD;&#xA; &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LViWC.png&#xD;&#xA;&#xD;&#xA;The theta (the angle between normal vector and the incoming light) is in the denominator. However, on the lighting slide (https://learnopengl.com/PBR/Lighting) he has the familiar code for the radiance of a light source, which makes the cos(theta) on the numerator.&#xD;&#xA;&#xD;&#xA;    vec3  lightColor  = vec3(23.47, 21.31, 20.79);&#xD;&#xA;    vec3  wi          = normalize(lightPos - fragPos);&#xD;&#xA;    float cosTheta    = max(dot(N, Wi), 0.0);&#xD;&#xA;    float attenuation = calculateAttenuation(fragPos, lightPos);&#xD;&#xA;    float radiance    = lightColor * attenuation * cosTheta;&#xD;&#xA;&#xD;&#xA;Can someone explain this fine point to me?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23700" PostHistoryTypeId="1" PostId="8747" RevisionGUID="be9d6491-e575-4bc7-b40d-f2a6677c64b1" CreationDate="2019-04-09T13:47:48.937" UserId="10461" Text="Why is cos(theta) in the denominator in the reflectance equation and in the numerator in the shading equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23701" PostHistoryTypeId="3" PostId="8747" RevisionGUID="be9d6491-e575-4bc7-b40d-f2a6677c64b1" CreationDate="2019-04-09T13:47:48.937" UserId="10461" Text="|opengl|lighting|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23702" PostHistoryTypeId="50" PostId="7804" RevisionGUID="5458fd55-69dc-48ef-bf38-a0838acf2776" CreationDate="2019-04-09T14:02:40.520" UserId="-1" />
  <row Id="23703" PostHistoryTypeId="2" PostId="8748" RevisionGUID="39fb8d4d-8106-4efb-a14a-7ff85eeeb04d" CreationDate="2019-04-09T15:12:57.577" UserId="10096" Text="The first is a definition of radiance in terms of the flux - it's a the derivative of flux with respect to both area and direction. It's simply a relation between $\Phi$ and $L$. It simply says that if you integrate radiance over the area of some surface, and for each point you integrate over all possible directions, then you will get the flux arriving/leaving that surface.&#xD;&#xA;The second part comes from the restriction of the rendering equation to a single point light source.&#xD;&#xA;Remember that:&#xD;&#xA;$$L(x,\omega_o) = L_e(x,\omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta_i \,d\omega_i}$$&#xD;&#xA;Where $x$ is a point on some surface, and $L(x,\omega_o)$ gives you the radiance incoming from $x$ in the direction $\omega_o$. This radiance is the sum of emitted radiance from $x$ in direction $\omega_o$: $L_e(x,\omega_o)$, and the scattered radiance by $x$ in direction $\omega_o$. The integral is necessary, since light may arrive from any direction at $x$, so you need to integrate over all directions. $f$ is the brdf, which really tells you how much of the light arriving from direction $\omega_i$ is reflected towards $\omega_o$ at $x$. $L_i(x,\omega_i)$ is the incoming radiance from direction $\omega_i$ at $x$, and the cosine is there to account for Lambert's law. What happens when you evaluate only direct lighting from a point light is that the integral is over a domain that is a single point, so you get only the integrand part, which you have in your code. Note that this is just an intuitive explanation, there are various issues with radiance not being defined for point lights." ContentLicense="CC BY-SA 4.0" />
  <row Id="23704" PostHistoryTypeId="5" PostId="8746" RevisionGUID="53d050a2-943b-4a3a-98d5-4bc3b3b7c3f0" CreationDate="2019-04-09T16:23:05.473" UserId="10096" Comment="deleted 41 characters in body" Text="&quot;A not so simple approach&quot;. I may have messed a little bit too much with grouping the terms, do forgive my elementary math skills, it's a side effect of using tools like wolfram and mathematica too much.&#xD;&#xA;&#xD;&#xA;Without loss of generality we can assume that the near plane is given as $z=1$ (that is having normal $(0,0,1)$ and a point on it $(0,0,1)$) and the camera center (the reflected pinhole camera aperture point) is at $(0,0,0)$. Let $p,q \in \mathbb{R}^3$ be two points on a line (non-degenerate, meaning $p\ne q$, otherwise it's just a point and the projection is also a point - unless it's at $(0,0,0)$ then it's undefined). If the line defined by $p,q$ passes through $(0,0,0)$ the projection is a point and the requirement is trivially satisfied.&#xD;&#xA;Now let this not be the case. A perspective projection onto the plane through $(0,0,0)$ is given by $p' = \frac{p}{p_z}$, and $q' = \frac{q}{q_z}$. The line defined by $p,q$ is given as $r(\lambda) = p + \lambda(q-p), \lambda \in  \mathbb{R}$. Its projection is given by $r'(\lambda) = \frac{r(\lambda)}{r_z(\lambda)}$. Since $z=1$ for all projected points, then we need only study the $x,y$ coordinates. We want to show that any projected point $r'(\lambda)$ can be written as an affine combination of $p',q'$ (this defines a line). Taking that into account:&#xD;&#xA;$$p'+\mu(q'-p') = \frac{r(\lambda)}{r_z(\lambda)}$$&#xD;&#xA;$$(1-\mu)\frac{p}{p_z} + \mu\frac{q}{q_z} = \frac{p + \lambda(q-p)}{p_z + \lambda(q_z-p_z)}$$&#xD;&#xA;$$(1-\mu)q_z(p_z+\lambda(q_z-p_z))p + \mu p_z(p_z+\lambda(q_z-p_z))q = q_zp_z(p + \lambda(q-p))$$&#xD;&#xA;$$q_zp_z(p - \lambda p) + q^2_z\lambda p - \mu q_z(p_z+\lambda(q_z-p_z))p + \mu p_z(p_z+\lambda(q_z-p_z))q - q_zp_z(p - \lambda p) - q_zp_z\lambda q = 0$$&#xD;&#xA;$$(1-\mu)\lambda q^2_z p -\mu(1-\lambda)q_zp_z p + \mu(1-\lambda)p^2_zq - (1-\mu)\lambda p_zq_z q = 0$$&#xD;&#xA;$$(1-\mu)\lambda q_z(q_zp - p_zq) - \mu(1-\lambda)p_z(q_zp-p_zq) = 0$$&#xD;&#xA;$$((1-\mu)\lambda q_z - \mu(1-\lambda)p_z)(q_zp - p_zq) = 0$$&#xD;&#xA;&#xD;&#xA;For this to be satisfied one of the terms must be $0$. The first case concerns the second term: $p' = q'$, which we already considered as the trivial case. Then we must show that we can always pick a $\mu$ such that $(1-\mu)\lambda q_z - \mu(1-\lambda)p_z = 0$. Solve for $\mu$ and you get: $\mu = \frac{\lambda q_z}{(1-\lambda)p_z + \lambda q_z}$. Thus I have not only found that it is a straight line, but also the relationship between the parameterizations.&#xD;&#xA;&#xD;&#xA;In general a projection onto a different 2-manifold (not a plane) will not result in the lines remaining straight (think of a sphere or a cylinder).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23709" PostHistoryTypeId="2" PostId="8750" RevisionGUID="d78a5521-1d66-4816-a982-8843294dd2cf" CreationDate="2019-04-10T10:46:50.000" UserId="10468" Text="What problems haven't been solved yet when it comes for instance in rendering,deferred rendering, Volumetric lighting, ambient occlusion or in any other interesting area. When i say unsolved problems, i mean topics in computer graphics that haven't been entirely solved and need serious improvement and maybe new techniques." ContentLicense="CC BY-SA 4.0" />
  <row Id="23710" PostHistoryTypeId="1" PostId="8750" RevisionGUID="d78a5521-1d66-4816-a982-8843294dd2cf" CreationDate="2019-04-10T10:46:50.000" UserId="10468" Text="Unsolved Problems in CQ to this day?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23711" PostHistoryTypeId="3" PostId="8750" RevisionGUID="d78a5521-1d66-4816-a982-8843294dd2cf" CreationDate="2019-04-10T10:46:50.000" UserId="10468" Text="|raytracing|rendering|deferred-rendering|volumetric|ambient-occlusion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23712" PostHistoryTypeId="50" PostId="8666" RevisionGUID="40527965-6cf6-406c-b8e3-88457513b926" CreationDate="2019-04-10T12:01:50.583" UserId="-1" />
  <row Id="23713" PostHistoryTypeId="2" PostId="8751" RevisionGUID="fead92a5-f047-4516-a33a-fb1f7b642424" CreationDate="2019-04-10T13:00:37.867" UserId="10096" Text="I am unsure whether you're talking about realistic image synthesis or realtime rendering, but either way these two are somewhat connected. The biggest issues in real time rendering are really finding good approximations of the algorithms used in realistic image synthesis, and the effective implementation of those, as well as hardware that supports this - think RTX atm. RTX in games however is pretty limited - it is highly biased (you can't even call it a good approximation of the rendering equation for most non-trivial scenes), so we're still at a point where rasterization based graphics dominate. Ray tracing has many advantages however, like its average O(logn) complexity versus rasterization's O(n) (where you can think of n as number of triangles in a scene). Note that this is asymptotic notation, so the main reason why ray tracing is not currently faster than rasterization is that: 1) the current hardware is highly optimized for rasterization, 2) the number of drawn triangles needs to be relatively large to offset the constant (it's unclear whether so many triangles would even be necessary for a realistic representation of shapes). There are however effects and realism which you simply cannot achieve with the &quot;hacks&quot; from rasterization graphics, ray tracing (or more precisely path tracing) is what we're aiming at- when you hit that for complex enough scenes/materials/participating media at interactive rates you've basically achieved photorealism.&#xD;&#xA;Now as far as unsolved problems in realistic image synthesis go, there are many. They range from good sampling distributions (the best samplers that we know of currently for CG are usually Owen scrambled Sobol, and some low-discrepancy sequences with blue noise properties - but those usually do not extend as well to higher dimensions), good approximations of the radiance in a scene (there are some recent papers from Vorba and Muller on the topic, they usually call it path guiding), dealing with participating media and complex brdfs (think subsurface scattering), spectral rendering (while there are several techniques for this, you can prove that each of those is bad in some aspect), the theory in general dates back to &quot;Lambert's antiquated framework&quot;, and while there have been attempts to modernize it similar to what's been done to other fields in physics for example, the best attempt at that as far as I am aware is Christian Lessig's thesis and the publications following it (which btw do not manage to solve the issue outlined fully). You can say that most problems in realistic image synthesis are actually unsolved - the problem is simply very hard mathematically." ContentLicense="CC BY-SA 4.0" />
  <row Id="23715" PostHistoryTypeId="2" PostId="8752" RevisionGUID="3cf55c08-f47e-4212-883d-beb0bef87769" CreationDate="2019-04-11T00:06:28.447" UserId="10475" Text="When it comes to line drawing, [DDA](https://www.geeksforgeeks.org/dda-line-generation-algorithm-computer-graphics/) is the simplest and most intuitive algorithm, the core idea being:&#xD;&#xA;&#xD;&#xA;- compute the slope of the line&#xD;&#xA;- for every increment in x, increment y by the slope&#xD;&#xA;&#xD;&#xA;However, DDA is not favored due to its use of floating point operations. In fact, avoiding floating point operations is a common theme in graphics. I am wondering about the relative cost of floating point operations versus integer operations in modern GPU's&#xD;&#xA;&#xD;&#xA;I could do some benchmarking but my CUDA is rusty. There is a [question on SO](https://stackoverflow.com/q/2550281/1382487 &quot;Floating point vs integer calculations on modern hardware&quot;) and the common wisdom there seems to be, &quot;it depends&quot;.&#xD;&#xA;&#xD;&#xA;My question is specific to computer graphics and line drawing. If a more general answer can be given, that will also be appreciated.&#xD;&#xA;&#xD;&#xA;To state my question specifically, is it important with modern GPU architectures to avoid floating point operations in favor of integer operations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23716" PostHistoryTypeId="1" PostId="8752" RevisionGUID="3cf55c08-f47e-4212-883d-beb0bef87769" CreationDate="2019-04-11T00:06:28.447" UserId="10475" Text="Floating Point Operations in Line Drawing Algorithms" ContentLicense="CC BY-SA 4.0" />
  <row Id="23717" PostHistoryTypeId="3" PostId="8752" RevisionGUID="3cf55c08-f47e-4212-883d-beb0bef87769" CreationDate="2019-04-11T00:06:28.447" UserId="10475" Text="|gpu|line-drawing|efficiency|float|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23721" PostHistoryTypeId="2" PostId="8754" RevisionGUID="c8613283-b272-4195-8acf-ef03167d131e" CreationDate="2019-04-11T02:31:28.173" UserId="10476" Text="I followed the book [Ray Tracing in One Weekend] and implemented a simple ray tracing procedure. There are 100 samples every pixel for antialiasing, but the render result looks weird: There is a unnatural circle at the center of the screen, and a strange line lies on the center of the ground, Why?&#xD;&#xA;&#xD;&#xA;![render result][img]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Ray Tracing in One Weekend]: http://www.realtimerendering.com/raytracing/Ray%20Tracing%20in%20a%20Weekend.pdf&#xD;&#xA;&#xD;&#xA;[img]:&#xD;&#xA;https://i.stack.imgur.com/uMb3s.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23722" PostHistoryTypeId="1" PostId="8754" RevisionGUID="c8613283-b272-4195-8acf-ef03167d131e" CreationDate="2019-04-11T02:31:28.173" UserId="10476" Text="Why the ray tracing result looks weird?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23723" PostHistoryTypeId="3" PostId="8754" RevisionGUID="c8613283-b272-4195-8acf-ef03167d131e" CreationDate="2019-04-11T02:31:28.173" UserId="10476" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23724" PostHistoryTypeId="2" PostId="8755" RevisionGUID="1a0d9dc7-1320-496d-b204-ebeca4a6a4bf" CreationDate="2019-04-11T04:42:12.117" UserId="3003" Text="Those are [moire patterns](https://en.wikipedia.org/wiki/Moiré_pattern). They are  an aliasing artifact that usually occurs when sampling on a regular grid. Did you jitter the positions of your samples? If you just sampled an evenly spaced 10x10 grid within each pixel, that could explain it." ContentLicense="CC BY-SA 4.0" />
  <row Id="23730" PostHistoryTypeId="2" PostId="8757" RevisionGUID="e76dd25a-fb4b-4d3c-b010-ee24e434f249" CreationDate="2019-04-11T06:12:37.130" UserId="10478" Text="Suppose I have code to generate a bunch of frames, each of which is a depth map(I have access to the matrices which represent depth) which in turn is used to generate a point cloud. One frame would look like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mo5TN.png&#xD;&#xA;&#xD;&#xA;In short I have a point cloud corresponding to each frame. How would I generate a video where each point cloud in a frame is meshed together? &#xD;&#xA;&#xD;&#xA;Are there frameworks which handle this kind of data? I am assuming OpenGL should help but I am not sure if it can do this." ContentLicense="CC BY-SA 4.0" />
  <row Id="23731" PostHistoryTypeId="1" PostId="8757" RevisionGUID="e76dd25a-fb4b-4d3c-b010-ee24e434f249" CreationDate="2019-04-11T06:12:37.130" UserId="10478" Text="Rendering 3-D point clouds obtained from depth maps as a 2.5D video" ContentLicense="CC BY-SA 4.0" />
  <row Id="23732" PostHistoryTypeId="3" PostId="8757" RevisionGUID="e76dd25a-fb4b-4d3c-b010-ee24e434f249" CreationDate="2019-04-11T06:12:37.130" UserId="10478" Text="|3d|mesh|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23733" PostHistoryTypeId="2" PostId="8758" RevisionGUID="cd4faf66-dbc2-4aea-85ab-545119c02112" CreationDate="2019-04-11T06:32:48.300" UserId="9908" Text="Depending on your application, you could use image-based solutions that are much cheaper than meshing a uniformly sampled set of points. For example, you could use the depth map as a [height map](https://en.wikipedia.org/wiki/Heightmap).&#xD;&#xA;&#xD;&#xA;There are many techniques that allow you to render it in an efficient way, the more realistic the more difficult to code as a shader (but not too much). From easiest to harder:&#xD;&#xA;&#xD;&#xA;* [height maps](https://en.wikipedia.org/wiki/Heightmap)&#xD;&#xA;* [normal maps](https://en.wikipedia.org/wiki/Normal_mapping)&#xD;&#xA;* [displacement mapping](https://en.wikipedia.org/wiki/Displacement_mapping)&#xD;&#xA;* [parallax mapping](https://en.wikipedia.org/wiki/Parallax_mapping)&#xD;&#xA;* geometry shaders to recreate the actual mesh from a set of primitives and the depth map&#xD;&#xA;* and so on. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23734" PostHistoryTypeId="5" PostId="8754" RevisionGUID="d09f96a9-8dde-4c24-a931-e52edad34464" CreationDate="2019-04-11T09:08:42.887" UserId="10476" Comment="added 11 characters in body" Text="I followed the book [Ray Tracing in One Weekend] and implemented a simple ray tracing procedure. There are 100 **random** samples every pixel for antialiasing, but the render result looks weird: There is a unnatural circle at the center of the screen, and a strange line lies on the center of the ground, Why?&#xD;&#xA;&#xD;&#xA;![render result][img]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Ray Tracing in One Weekend]: http://www.realtimerendering.com/raytracing/Ray%20Tracing%20in%20a%20Weekend.pdf&#xD;&#xA;&#xD;&#xA;[img]:&#xD;&#xA;https://i.stack.imgur.com/uMb3s.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23737" PostHistoryTypeId="2" PostId="8760" RevisionGUID="fa5716d5-30c1-4474-b390-ffb0189b586c" CreationDate="2019-04-11T23:49:00.667" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="23738" PostHistoryTypeId="1" PostId="8760" RevisionGUID="fa5716d5-30c1-4474-b390-ffb0189b586c" CreationDate="2019-04-11T23:49:00.667" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23739" PostHistoryTypeId="2" PostId="8761" RevisionGUID="a38cedcd-46aa-4236-a61f-997cf1492f12" CreationDate="2019-04-11T23:49:00.667" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="23740" PostHistoryTypeId="1" PostId="8761" RevisionGUID="a38cedcd-46aa-4236-a61f-997cf1492f12" CreationDate="2019-04-11T23:49:00.667" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23741" PostHistoryTypeId="2" PostId="8762" RevisionGUID="1b68e806-8926-45c5-a7e3-35538a4a2373" CreationDate="2019-04-11T23:50:02.757" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="23742" PostHistoryTypeId="1" PostId="8762" RevisionGUID="1b68e806-8926-45c5-a7e3-35538a4a2373" CreationDate="2019-04-11T23:50:02.757" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23743" PostHistoryTypeId="2" PostId="8763" RevisionGUID="a535a9aa-2c69-414d-85bb-950ae0f67472" CreationDate="2019-04-11T23:50:02.757" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="23744" PostHistoryTypeId="1" PostId="8763" RevisionGUID="a535a9aa-2c69-414d-85bb-950ae0f67472" CreationDate="2019-04-11T23:50:02.757" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23745" PostHistoryTypeId="5" PostId="8755" RevisionGUID="ee158f1d-c4a4-47cb-ab8a-060fcd4fd9c4" CreationDate="2019-04-12T02:27:54.017" UserId="3003" Comment="Added info about numerical errors because  that  was apparently the right answer." Text="Those are [moire patterns](https://en.wikipedia.org/wiki/Moiré_pattern). They are  an aliasing artifact that usually occurs when sampling on a regular grid. Did you jitter the positions of your samples? If you just sampled an evenly spaced 10x10 grid within each pixel, that could explain it. Also, numerical errors or inaccuracy could it." ContentLicense="CC BY-SA 4.0" />
  <row Id="23746" PostHistoryTypeId="2" PostId="8764" RevisionGUID="96f0ad12-b393-4306-8c59-f822e81ac8b0" CreationDate="2019-04-12T04:14:37.567" UserId="3003" Text="&gt; is it important with modern GPU architectures to avoid floating point operations in favor of integer operations?&#xD;&#xA;&#xD;&#xA;Almost certainly not. CPUs have a long history where for many years they only handled integers natively and floating point operations were all done with slow math libraries. That changed about 20-25 years ago, but the thinking has remained entrenched for many years. (And certain applications like finance may require it for other reasons.)&#xD;&#xA;&#xD;&#xA;Modern GPUs, though, have always been about doing lots of floating point calculations in parallel. If you think about how most 3D rasterizers (like OpenGL, Metal, DirectX, etc.) work, they take all the vertices, transform them into normalized device coordinates, and then interpolate between them to draw the actual geometry. While you certainly could do that all with fixed point math, it probably wouldn't gain you much. But you also aren't doing those calculations yourself, unless you've written your own rasterizer as a compute kernel.&#xD;&#xA;&#xD;&#xA;Now depending on what type of work you're doing, the precision of the floating point operations may be reduced. In a language like glsl (in OpenGL ES, anyway) you can [specify the precision](https://www.khronos.org/opengl/wiki/Type_Qualifier_(GLSL)#Precision_qualifiers) of the uniforms. On mobile hardware, it might be worth doing the calculations as floating point, but with only 16 or 24 bits instead of 32 because it saves power,   for example. (And even some desktop GPUs have used lower-precision floating point in the past.) But the desktop hardware of today is optimized for doing floating point work.&#xD;&#xA;&#xD;&#xA;In short, I don't see a compelling reason to stick to integer math when working on the GPU." ContentLicense="CC BY-SA 4.0" />
  <row Id="23748" PostHistoryTypeId="5" PostId="8747" RevisionGUID="73134176-6eb0-486b-a250-76a1e1d05df3" CreationDate="2019-04-12T17:17:54.563" UserId="5778" Comment="typo corrected, formatting" Text="Background: I'm reading https://learnopengl.com/PBR to learn about PBR. In the theory slide (https://learnopengl.com/PBR/Theory), the author has the reflectant equation as&#xD;&#xA; &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LViWC.png&#xD;&#xA;&#xD;&#xA;The theta (the angle between normal vector and the incoming light) is in the denominator. However, on the lighting slide (https://learnopengl.com/PBR/Lighting) he has the familiar code for the radiance of a light source, which makes the $\cos(\theta)$ on the numerator.&#xD;&#xA;&#xD;&#xA;    vec3  lightColor  = vec3(23.47, 21.31, 20.79);&#xD;&#xA;    vec3  wi          = normalize(lightPos - fragPos);&#xD;&#xA;    float cosTheta    = max(dot(N, Wi), 0.0);&#xD;&#xA;    float attenuation = calculateAttenuation(fragPos, lightPos);&#xD;&#xA;    float radiance    = lightColor * attenuation * cosTheta;&#xD;&#xA;&#xD;&#xA;Can someone explain this fine point to me?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23749" PostHistoryTypeId="4" PostId="8747" RevisionGUID="73134176-6eb0-486b-a250-76a1e1d05df3" CreationDate="2019-04-12T17:17:54.563" UserId="5778" Comment="typo corrected, formatting" Text="Why is cos() in the denominator in the reflectance equation and in the numerator in the shading equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23750" PostHistoryTypeId="24" PostId="8747" RevisionGUID="73134176-6eb0-486b-a250-76a1e1d05df3" CreationDate="2019-04-12T17:17:54.563" Comment="Proposed by 5778 approved by 6, 48 edit id of 468" ContentLicense="CC BY-SA 4.0" />
  <row Id="23751" PostHistoryTypeId="2" PostId="8765" RevisionGUID="5fe0f7f1-c690-4c6e-b9fe-c57c88e8d716" CreationDate="2019-04-13T10:24:12.573" UserId="10191" Text="I am trying to reproduce the results obtained by Dahm et al. in the paper [Learning Light Transport the Reinforced Way][1]. &lt;br&gt;&#xD;&#xA;This method takes advantage of the similarity between the Bellman equation (Q-Learning) and the rendering equation. &lt;br&gt;&#xD;&#xA;Here's the overview of the code authors inserted in the first version of their paper: &lt;br&gt;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Question 1**&#xD;&#xA;&#xD;&#xA;What is, in the first function, `idxPrev`? Intuition suggests it is the index of the previous cell (the scene space needs to be discretized, using for example the Voronoi algorithm). But in the function, authors pass `ray.o`, which I believe is the outgoing ray. So, that would not make sense.&#xD;&#xA;&#xD;&#xA;**Question 2**&#xD;&#xA;&#xD;&#xA;The action space is discretized, apparently, dividing the hemisphere built on the hitting point in different stratums. According to what I understand, the Q-Learning algorithm finds the best action (so the best stratum) for each cell in the space, and then a ray is scattered randomly in that stratum. But a stratum covers 360 degrees, so I don't see how this is helpful to scattered a ray towards the light. &lt;br&gt;&#xD;&#xA;In the function `sampleScatteringDIrFromQtable()`, the PDF is calculated based on the `ps` (not clear) multiplied by the number of patches. So, the action is related to circular stratums of the hemisphere, or the number of patches?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/pdf/1701.07403v1.pdf?utm_content=buffer5b1d2&amp;utm_medium=social&amp;utm_source=twitter.com&amp;utm_campaign=buffer&#xD;&#xA;  [2]: https://i.stack.imgur.com/VEMXA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23752" PostHistoryTypeId="1" PostId="8765" RevisionGUID="5fe0f7f1-c690-4c6e-b9fe-c57c88e8d716" CreationDate="2019-04-13T10:24:12.573" UserId="10191" Text="Learning light transport using Q-Learning" ContentLicense="CC BY-SA 4.0" />
  <row Id="23753" PostHistoryTypeId="3" PostId="8765" RevisionGUID="5fe0f7f1-c690-4c6e-b9fe-c57c88e8d716" CreationDate="2019-04-13T10:24:12.573" UserId="10191" Text="|raytracing|pathtracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23754" PostHistoryTypeId="5" PostId="8765" RevisionGUID="1f1186fd-9afa-4530-8236-251ba59d8ced" CreationDate="2019-04-13T11:12:37.817" UserId="10191" Comment="Added a sub-question in Question 1" Text="I am trying to reproduce the results obtained by Dahm et al. in the paper [Learning Light Transport the Reinforced Way][1]. &lt;br&gt;&#xD;&#xA;This method takes advantage of the similarity between the Bellman equation (Q-Learning) and the rendering equation. &lt;br&gt;&#xD;&#xA;Here's the overview of the code authors inserted in the first version of their paper: &lt;br&gt;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Question 1**&#xD;&#xA;&#xD;&#xA;What is, in the first function, `idxPrev`? Intuition suggests it is the index of the previous cell (the scene space needs to be discretized, using for example the Voronoi algorithm). But in the function, authors pass `ray.o`, which I believe is the outgoing ray. So, that would not make sense. &lt;br&gt;&#xD;&#xA;Moreover, in the same function, I understand that `getLastAttenuation()` returns the color of `idxCurr`, but i don't understand what `qmax[idxCurr]` returns (intuitively, the action so the stratum of the hemisphere that maximizes the Q-value).&#xD;&#xA;&#xD;&#xA;**Question 2**&#xD;&#xA;&#xD;&#xA;The action space is discretized, apparently, dividing the hemisphere built on the hitting point in different stratums. According to what I understand, the Q-Learning algorithm finds the best action (so the best stratum) for each cell in the space, and then a ray is scattered randomly in that stratum. But a stratum covers 360 degrees, so I don't see how this is helpful to scattered a ray towards the light. &lt;br&gt;&#xD;&#xA;In the function `sampleScatteringDIrFromQtable()`, the PDF is calculated based on the `ps` (not clear) multiplied by the number of patches. So, the action is related to circular stratums of the hemisphere, or the number of patches?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/pdf/1701.07403v1.pdf?utm_content=buffer5b1d2&amp;utm_medium=social&amp;utm_source=twitter.com&amp;utm_campaign=buffer&#xD;&#xA;  [2]: https://i.stack.imgur.com/VEMXA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23755" PostHistoryTypeId="2" PostId="8766" RevisionGUID="0c6a1589-2ec4-4fd5-a094-65c8c9447cbf" CreationDate="2019-04-13T17:00:41.700" UserId="10492" Text="When doing clipping in homogeneous coordinates, we need to find the coordinates of the intersection of the viewing frustum with the line to be clipped. This can be done easily if we want those coordinates to be in screen space(simply divide by the fourth coordinate). But how can we find those coordinates in 3D space? And do we need to do so in the first place?&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="23756" PostHistoryTypeId="1" PostId="8766" RevisionGUID="0c6a1589-2ec4-4fd5-a094-65c8c9447cbf" CreationDate="2019-04-13T17:00:41.700" UserId="10492" Text="3D coordinates of intersection point in clipping for a rasterizer" ContentLicense="CC BY-SA 4.0" />
  <row Id="23757" PostHistoryTypeId="3" PostId="8766" RevisionGUID="0c6a1589-2ec4-4fd5-a094-65c8c9447cbf" CreationDate="2019-04-13T17:00:41.700" UserId="10492" Text="|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23762" PostHistoryTypeId="50" PostId="5996" RevisionGUID="f67ed354-0dce-43f9-b867-29a1c0cd616f" CreationDate="2019-04-14T11:01:35.290" UserId="-1" />
  <row Id="23764" PostHistoryTypeId="2" PostId="8768" RevisionGUID="24639c52-3659-42c3-8fc8-3429356f8678" CreationDate="2019-04-14T18:20:24.490" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="23765" PostHistoryTypeId="1" PostId="8768" RevisionGUID="24639c52-3659-42c3-8fc8-3429356f8678" CreationDate="2019-04-14T18:20:24.490" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23766" PostHistoryTypeId="2" PostId="8769" RevisionGUID="19056db6-c32b-423d-a783-99ca5cc6d6b5" CreationDate="2019-04-14T18:20:24.490" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="23767" PostHistoryTypeId="1" PostId="8769" RevisionGUID="19056db6-c32b-423d-a783-99ca5cc6d6b5" CreationDate="2019-04-14T18:20:24.490" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="23769" PostHistoryTypeId="2" PostId="8770" RevisionGUID="9301b9b9-e54f-4541-91b1-32ec6779accf" CreationDate="2019-04-15T05:59:53.510" UserId="10500" Text="I have an oval which has -45 degree axis.&#xD;&#xA;&#xD;&#xA;I want to transform the oval into circle.&#xD;&#xA;&#xD;&#xA;How can I transform the oval into circle?&#xD;&#xA;&#xD;&#xA;Can I use shear transformation along x/y axis?&#xD;&#xA;&#xD;&#xA;Thank you very much.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aMJhX.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23770" PostHistoryTypeId="1" PostId="8770" RevisionGUID="9301b9b9-e54f-4541-91b1-32ec6779accf" CreationDate="2019-04-15T05:59:53.510" UserId="10500" Text="How can I transform the oval into circle?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23771" PostHistoryTypeId="3" PostId="8770" RevisionGUID="9301b9b9-e54f-4541-91b1-32ec6779accf" CreationDate="2019-04-15T05:59:53.510" UserId="10500" Text="|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23772" PostHistoryTypeId="2" PostId="8771" RevisionGUID="c57f7411-af3c-4779-be00-da1acb5ac80b" CreationDate="2019-04-15T10:57:27.440" UserId="228" Text="Does anyone have experience with open-mesh or computational geometry and can kindly explain what exactly happens in the function below?&#xD;&#xA;&#xD;&#xA;    PolyConnectivity::FaceHandle&#xD;&#xA;    PolyConnectivity::add_face(const VertexHandle* _vertex_handles, size_t _vhs_size)&#xD;&#xA;    {&#xD;&#xA;      VertexHandle                   vh;&#xD;&#xA;      size_t                         i, ii, n(_vhs_size);&#xD;&#xA;      HalfedgeHandle                 inner_next, inner_prev,&#xD;&#xA;                                     outer_next, outer_prev,&#xD;&#xA;                                     boundary_next, boundary_prev,&#xD;&#xA;                                     patch_start, patch_end;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // Check sufficient working storage available&#xD;&#xA;      if (edgeData_.size() &lt; n)&#xD;&#xA;      {&#xD;&#xA;        edgeData_.resize(n);&#xD;&#xA;        next_cache_.resize(6*n);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      size_t next_cache_count = 0;&#xD;&#xA;    &#xD;&#xA;      // don't allow degenerated faces&#xD;&#xA;      assert (n &gt; 2);&#xD;&#xA;    &#xD;&#xA;      // test for topological errors&#xD;&#xA;      for (i=0, ii=1; i&lt;n; ++i, ++ii, ii%=n)&#xD;&#xA;      {&#xD;&#xA;        if ( !is_boundary(_vertex_handles[i]) )&#xD;&#xA;        {&#xD;&#xA;          omerr() &lt;&lt; &quot;PolyMeshT::add_face: complex vertex\n&quot;;&#xD;&#xA;          return InvalidFaceHandle;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Initialise edge attributes&#xD;&#xA;        edgeData_[i].halfedge_handle = find_halfedge(_vertex_handles[i],&#xD;&#xA;                                                     _vertex_handles[ii]);&#xD;&#xA;        edgeData_[i].is_new = !edgeData_[i].halfedge_handle.is_valid();&#xD;&#xA;        edgeData_[i].needs_adjust = false;&#xD;&#xA;    &#xD;&#xA;        if (!edgeData_[i].is_new &amp;&amp; !is_boundary(edgeData_[i].halfedge_handle))&#xD;&#xA;        {&#xD;&#xA;          omerr() &lt;&lt; &quot;PolyMeshT::add_face: complex edge\n&quot;;&#xD;&#xA;          return InvalidFaceHandle;&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      // re-link patches if necessary&#xD;&#xA;      for (i=0, ii=1; i&lt;n; ++i, ++ii, ii%=n)&#xD;&#xA;      {&#xD;&#xA;        if (!edgeData_[i].is_new &amp;&amp; !edgeData_[ii].is_new)&#xD;&#xA;        {&#xD;&#xA;          inner_prev = edgeData_[i].halfedge_handle;&#xD;&#xA;          inner_next = edgeData_[ii].halfedge_handle;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;          if (next_halfedge_handle(inner_prev) != inner_next)&#xD;&#xA;          {&#xD;&#xA;            // here comes the ugly part... we have to relink a whole patch&#xD;&#xA;    &#xD;&#xA;            // search a free gap&#xD;&#xA;            // free gap will be between boundary_prev and boundary_next&#xD;&#xA;            outer_prev = opposite_halfedge_handle(inner_next);&#xD;&#xA;            outer_next = opposite_halfedge_handle(inner_prev);&#xD;&#xA;            boundary_prev = outer_prev;&#xD;&#xA;            do&#xD;&#xA;              boundary_prev =&#xD;&#xA;                opposite_halfedge_handle(next_halfedge_handle(boundary_prev));&#xD;&#xA;            while (!is_boundary(boundary_prev));&#xD;&#xA;            boundary_next = next_halfedge_handle(boundary_prev);&#xD;&#xA;    &#xD;&#xA;            // ok ?&#xD;&#xA;            if (boundary_prev == inner_prev)&#xD;&#xA;            {&#xD;&#xA;              omerr() &lt;&lt; &quot;PolyMeshT::add_face: patch re-linking failed\n&quot;;&#xD;&#xA;              return InvalidFaceHandle;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            assert(is_boundary(boundary_prev));&#xD;&#xA;            assert(is_boundary(boundary_next));&#xD;&#xA;    &#xD;&#xA;            // other halfedges' handles&#xD;&#xA;            patch_start = next_halfedge_handle(inner_prev);&#xD;&#xA;            patch_end   = prev_halfedge_handle(inner_next);&#xD;&#xA;    &#xD;&#xA;            assert(boundary_prev.is_valid());&#xD;&#xA;            assert(patch_start.is_valid());&#xD;&#xA;            assert(patch_end.is_valid());&#xD;&#xA;            assert(boundary_next.is_valid());&#xD;&#xA;            assert(inner_prev.is_valid());&#xD;&#xA;            assert(inner_next.is_valid());&#xD;&#xA;    &#xD;&#xA;            // relink&#xD;&#xA;            next_cache_[next_cache_count++] = std::make_pair(boundary_prev, patch_start);&#xD;&#xA;            next_cache_[next_cache_count++] = std::make_pair(patch_end, boundary_next);&#xD;&#xA;            next_cache_[next_cache_count++] = std::make_pair(inner_prev, inner_next);&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      // create missing edges&#xD;&#xA;      for (i=0, ii=1; i&lt;n; ++i, ++ii, ii%=n)&#xD;&#xA;        if (edgeData_[i].is_new)&#xD;&#xA;          edgeData_[i].halfedge_handle = new_edge(_vertex_handles[i], _vertex_handles[ii]);&#xD;&#xA;    &#xD;&#xA;      // create the face&#xD;&#xA;      FaceHandle fh(new_face());&#xD;&#xA;      set_halfedge_handle(fh, edgeData_[n-1].halfedge_handle);&#xD;&#xA;    &#xD;&#xA;      // setup halfedges&#xD;&#xA;      for (i=0, ii=1; i&lt;n; ++i, ++ii, ii%=n)&#xD;&#xA;      {&#xD;&#xA;        vh         = _vertex_handles[ii];&#xD;&#xA;    &#xD;&#xA;        inner_prev = edgeData_[i].halfedge_handle;&#xD;&#xA;        inner_next = edgeData_[ii].halfedge_handle;&#xD;&#xA;        assert(inner_prev.is_valid());&#xD;&#xA;        assert(inner_next.is_valid());&#xD;&#xA;    &#xD;&#xA;        size_t id = 0;&#xD;&#xA;        if (edgeData_[i].is_new)  id |= 1;&#xD;&#xA;        if (edgeData_[ii].is_new) id |= 2;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if (id)&#xD;&#xA;        {&#xD;&#xA;          outer_prev = opposite_halfedge_handle(inner_next);&#xD;&#xA;          outer_next = opposite_halfedge_handle(inner_prev);&#xD;&#xA;          assert(outer_prev.is_valid());&#xD;&#xA;          assert(outer_next.is_valid());&#xD;&#xA;    &#xD;&#xA;          // set outer links&#xD;&#xA;          switch (id)&#xD;&#xA;          {&#xD;&#xA;            case 1: // prev is new, next is old&#xD;&#xA;              boundary_prev = prev_halfedge_handle(inner_next);&#xD;&#xA;              assert(boundary_prev.is_valid());&#xD;&#xA;              next_cache_[next_cache_count++] = std::make_pair(boundary_prev, outer_next);&#xD;&#xA;              set_halfedge_handle(vh, outer_next);&#xD;&#xA;              break;&#xD;&#xA;    &#xD;&#xA;            case 2: // next is new, prev is old&#xD;&#xA;              boundary_next = next_halfedge_handle(inner_prev);&#xD;&#xA;              assert(boundary_next.is_valid());&#xD;&#xA;              next_cache_[next_cache_count++] = std::make_pair(outer_prev, boundary_next);&#xD;&#xA;              set_halfedge_handle(vh, boundary_next);&#xD;&#xA;              break;&#xD;&#xA;    &#xD;&#xA;            case 3: // both are new&#xD;&#xA;              if (!halfedge_handle(vh).is_valid())&#xD;&#xA;              {&#xD;&#xA;                set_halfedge_handle(vh, outer_next);&#xD;&#xA;                next_cache_[next_cache_count++] = std::make_pair(outer_prev, outer_next);&#xD;&#xA;              }&#xD;&#xA;              else&#xD;&#xA;              {&#xD;&#xA;                boundary_next = halfedge_handle(vh);&#xD;&#xA;                boundary_prev = prev_halfedge_handle(boundary_next);&#xD;&#xA;                assert(boundary_prev.is_valid());&#xD;&#xA;                assert(boundary_next.is_valid());&#xD;&#xA;                next_cache_[next_cache_count++] = std::make_pair(boundary_prev, outer_next);&#xD;&#xA;                next_cache_[next_cache_count++] = std::make_pair(outer_prev, boundary_next);&#xD;&#xA;              }&#xD;&#xA;              break;&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;          // set inner link&#xD;&#xA;          next_cache_[next_cache_count++] = std::make_pair(inner_prev, inner_next);&#xD;&#xA;        }&#xD;&#xA;        else edgeData_[ii].needs_adjust = (halfedge_handle(vh) == inner_next);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // set face handle&#xD;&#xA;        set_face_handle(edgeData_[i].halfedge_handle, fh);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      // process next halfedge cache&#xD;&#xA;      for (i = 0; i &lt; next_cache_count; ++i)&#xD;&#xA;        set_next_halfedge_handle(next_cache_[i].first, next_cache_[i].second);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      // adjust vertices' halfedge handle&#xD;&#xA;      for (i=0; i&lt;n; ++i)&#xD;&#xA;        if (edgeData_[i].needs_adjust)&#xD;&#xA;          adjust_outgoing_halfedge(_vertex_handles[i]);&#xD;&#xA;    &#xD;&#xA;      return fh;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;More specifically, at the moment, I'd like to understand what exactly happens in the for loop below:&#xD;&#xA;&#xD;&#xA;    // re-link patches if necessary&#xD;&#xA;      for (i=0, ii=1; i&lt;n; ++i, ++ii, ii%=n)&#xD;&#xA;      {&#xD;&#xA;        if (!edgeData_[i].is_new &amp;&amp; !edgeData_[ii].is_new)&#xD;&#xA;        {&#xD;&#xA;          inner_prev = edgeData_[i].halfedge_handle;&#xD;&#xA;          inner_next = edgeData_[ii].halfedge_handle;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;          if (next_halfedge_handle(inner_prev) != inner_next)&#xD;&#xA;          {&#xD;&#xA;            // here comes the ugly part... we have to relink a whole patch&#xD;&#xA;    &#xD;&#xA;            // search a free gap&#xD;&#xA;            // free gap will be between boundary_prev and boundary_next&#xD;&#xA;            outer_prev = opposite_halfedge_handle(inner_next);&#xD;&#xA;            outer_next = opposite_halfedge_handle(inner_prev);&#xD;&#xA;            boundary_prev = outer_prev;&#xD;&#xA;            do&#xD;&#xA;              boundary_prev =&#xD;&#xA;                opposite_halfedge_handle(next_halfedge_handle(boundary_prev));&#xD;&#xA;            while (!is_boundary(boundary_prev));&#xD;&#xA;            boundary_next = next_halfedge_handle(boundary_prev);&#xD;&#xA;    &#xD;&#xA;            // ok ?&#xD;&#xA;            if (boundary_prev == inner_prev)&#xD;&#xA;            {&#xD;&#xA;              omerr() &lt;&lt; &quot;PolyMeshT::add_face: patch re-linking failed\n&quot;;&#xD;&#xA;              return InvalidFaceHandle;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            assert(is_boundary(boundary_prev));&#xD;&#xA;            assert(is_boundary(boundary_next));&#xD;&#xA;    &#xD;&#xA;            // other halfedges' handles&#xD;&#xA;            patch_start = next_halfedge_handle(inner_prev);&#xD;&#xA;            patch_end   = prev_halfedge_handle(inner_next);&#xD;&#xA;    &#xD;&#xA;            assert(boundary_prev.is_valid());&#xD;&#xA;            assert(patch_start.is_valid());&#xD;&#xA;            assert(patch_end.is_valid());&#xD;&#xA;            assert(boundary_next.is_valid());&#xD;&#xA;            assert(inner_prev.is_valid());&#xD;&#xA;            assert(inner_next.is_valid());&#xD;&#xA;    &#xD;&#xA;            // relink&#xD;&#xA;            next_cache_[next_cache_count++] = std::make_pair(boundary_prev, patch_start);&#xD;&#xA;            next_cache_[next_cache_count++] = std::make_pair(patch_end, boundary_next);&#xD;&#xA;            next_cache_[next_cache_count++] = std::make_pair(inner_prev, inner_next);&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;Just to give some context, the `add_face` (which is reused in other subclasses of `PolyConnectivity`) essentially creates a face given a set of vertices, the first part of the function, prior the for loop I've just mentioned, checks if the vertices are boundary vertices and if there's a potential edge connecting two consecutive vertices.&#xD;&#xA;&#xD;&#xA;The for loop I don't understand is supposed to do something when three consecutive vertices `v[i],v[i+1],v[i+2]` are not connected (I think)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23773" PostHistoryTypeId="1" PostId="8771" RevisionGUID="c57f7411-af3c-4779-be00-da1acb5ac80b" CreationDate="2019-04-15T10:57:27.440" UserId="228" Text="HalfEdge data structure in openmesh, create_face function explanation" ContentLicense="CC BY-SA 4.0" />
  <row Id="23774" PostHistoryTypeId="3" PostId="8771" RevisionGUID="c57f7411-af3c-4779-be00-da1acb5ac80b" CreationDate="2019-04-15T10:57:27.440" UserId="228" Text="|algorithm|c++|computational-geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23775" PostHistoryTypeId="10" PostId="8712" RevisionGUID="2e83fad9-10c1-4394-9a2f-036b8e73c3b7" CreationDate="2019-04-15T11:17:48.937" UserId="2041" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="23777" PostHistoryTypeId="50" PostId="8260" RevisionGUID="b7bc5f7f-0b57-4b3a-9c96-4fab8367362d" CreationDate="2019-04-15T23:02:30.630" UserId="-1" />
  <row Id="23778" PostHistoryTypeId="2" PostId="8772" RevisionGUID="5277a722-737e-4897-9389-aa09616e9055" CreationDate="2019-04-16T10:46:31.853" UserId="10096" Text="You can use a shear, or equivalently a rotation by 45, scale along one of the axes, rotate back (which is equivalent to the shear which you are looking for)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23780" PostHistoryTypeId="5" PostId="8713" RevisionGUID="f184fa52-513e-4c23-b55e-4ffabc8f8380" CreationDate="2019-04-17T03:10:08.733" UserId="6588" Comment="Actually it’s much less than double" Text="I assume you mean performance of the numerical algorithm responsible for generating the image?&#xD;&#xA;&#xD;&#xA;Usually the performance of a rendering algorithm is assessed through a pixel-wise comparison with a ground truth, converged image. This image is typically rendered for a very long time using a standard and (ideally) unbiased technique like unidirectional path tracing. For a fixed time and sampling budget, you then run your custom algorithm and track a meaningful error (e.g. relative MSE) between your intermediate image and the ground truth image. Plotting the error over time on a logarithmic scale should give you a sense of how your algorithm is performing.&#xD;&#xA;&#xD;&#xA;When comparing algorithms, you need to make sure that you are actually comparing images that were output by the *same* rendering engine. This is crucial if you want to report a faithful metric, otherwise the comparison is unfair and inherently depends on the implementation. For instance, if rendering engine $A$ takes twice as long as engine $B$ to fetch and load a texture, your reported error will be higher, even though the main algorithm you are testing is the same (assuming you are treating materials as blackboxes). The main downside is that rendering researchers are typically required to implement other algorithms in their engine to report the true performance of their new algorithm." ContentLicense="CC BY-SA 4.0" />
  <row Id="23781" PostHistoryTypeId="5" PostId="8765" RevisionGUID="1f596305-1b7e-4d97-9942-4a28a38810ed" CreationDate="2019-04-17T08:01:03.480" UserId="10191" Comment="added 44 characters in body" Text="I am trying to reproduce the results obtained by Dahm et al. in the paper [Learning Light Transport the Reinforced Way][1]. &lt;br&gt;&#xD;&#xA;This method takes advantage of the similarity between the Bellman equation (Q-Learning) and the rendering equation. &lt;br&gt;&#xD;&#xA;Here's the overview of the code authors inserted in the first version of their paper: &lt;br&gt;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Question 1**&#xD;&#xA;&#xD;&#xA;What is, in the first function, `idxPrev`? Intuition suggests it is the index of the previous cell (the scene space needs to be discretized, using for example the Voronoi algorithm). But in the function, authors pass `ray.o`, which I believe is the outgoing ray. So, that would not make sense. &lt;br&gt;&#xD;&#xA;EDIT: `ray.o` is probably the origin. &lt;br&gt;&#xD;&#xA;Moreover, in the same function, I understand that `getLastAttenuation()` returns the color of `idxCurr`, but i don't understand what `qmax[idxCurr]` returns (intuitively, the action so the stratum of the hemisphere that maximizes the Q-value).&#xD;&#xA;&#xD;&#xA;**Question 2**&#xD;&#xA;&#xD;&#xA;The action space is discretized, apparently, dividing the hemisphere built on the hitting point in different stratums. According to what I understand, the Q-Learning algorithm finds the best action (so the best stratum) for each cell in the space, and then a ray is scattered randomly in that stratum. But a stratum covers 360 degrees, so I don't see how this is helpful to scattered a ray towards the light. &lt;br&gt;&#xD;&#xA;In the function `sampleScatteringDIrFromQtable()`, the PDF is calculated based on the `ps` (not clear) multiplied by the number of patches. So, the action is related to circular stratums of the hemisphere, or the number of patches?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/pdf/1701.07403v1.pdf?utm_content=buffer5b1d2&amp;utm_medium=social&amp;utm_source=twitter.com&amp;utm_campaign=buffer&#xD;&#xA;  [2]: https://i.stack.imgur.com/VEMXA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23782" PostHistoryTypeId="2" PostId="8773" RevisionGUID="ed6de528-a1d0-4da9-ad79-04bc1e9a280a" CreationDate="2019-04-17T13:02:45.657" UserId="9387" Text="In an effort to improve cascaded shadow maps, I have looked into using GL_DEPTH_CLAMP and moving the near and far plane just around the actual view frustum instead of the global bounding box. But the use of GL_DEPTH_CLAMP appears to have no effect and the near plane clips the geometry.&#xD;&#xA;&#xD;&#xA;I use reverse z as per [Reversed-Z in OpenGL](https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/):&#xD;&#xA;&#xD;&#xA;The tl/dr version is:&#xD;&#xA;&#xD;&#xA;1. Change clip control to 0/1&#xD;&#xA;&#xD;&#xA;        glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE);&#xD;&#xA;&#xD;&#xA;2. Use a floating point depth buffer.&#xD;&#xA;3. Clear the depth buffer to 0&#xD;&#xA;    &#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, fbo);&#xD;&#xA;     &#xD;&#xA;        glClearDepth(0.0f);&#xD;&#xA;        glClear(GL_DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;4. Change depth test to grater&#xD;&#xA;&#xD;&#xA;        glDepthFunc(GL_GREATER);&#xD;&#xA;&#xD;&#xA;5. Change the projection matrix to match&#xD;&#xA;&#xD;&#xA;The reverse z works really fine, but apparently it messes with GL_DEPTH_CLAMP. If I switch off reverse z GL_DEPTH_CLAMP appears to work as designed; but many other bits in the code get messed up. (It's just not switchable anymore.)&#xD;&#xA;&#xD;&#xA;If you look at the documentation of [GL_DEPTH_CLAMP](https://www.khronos.org/opengl/wiki/GLAPI/glEnable) it states the following:&#xD;&#xA;&#xD;&#xA;&gt; If enabled, the -wc ≤ zc ≤ wc plane equation is ignored by view volume clipping (effectively, there is no near or far plane clipping).&#xD;&#xA;&#xD;&#xA;My guess is that GL_DEPTH_CLAMP's implementation is just not compatible with reverse z. But I feel like I am missing something. Any idea on how to get GL_DEPTH_CLAMP to working with reverse z?&#xD;&#xA;&#xD;&#xA;See the following image of the depth buffers:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Shjvy.png&#xD;&#xA;&#xD;&#xA;As you can see in the the first cascade, the near plane clips the geometry, it should be all white." ContentLicense="CC BY-SA 4.0" />
  <row Id="23783" PostHistoryTypeId="1" PostId="8773" RevisionGUID="ed6de528-a1d0-4da9-ad79-04bc1e9a280a" CreationDate="2019-04-17T13:02:45.657" UserId="9387" Text="GL_DEPTH_CLAMP has no effect (reverse z)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23784" PostHistoryTypeId="3" PostId="8773" RevisionGUID="ed6de528-a1d0-4da9-ad79-04bc1e9a280a" CreationDate="2019-04-17T13:02:45.657" UserId="9387" Text="|opengl|shadow|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23786" PostHistoryTypeId="50" PostId="8151" RevisionGUID="88b4964a-951a-4918-9d87-e0325de0662d" CreationDate="2019-04-17T23:02:45.537" UserId="-1" />
  <row Id="23787" PostHistoryTypeId="50" PostId="7730" RevisionGUID="69c26a7e-029d-4bc8-bcfe-2d6e3db8b0ee" CreationDate="2019-04-18T01:02:20.453" UserId="-1" />
  <row Id="23789" PostHistoryTypeId="2" PostId="8774" RevisionGUID="d9091389-a9a2-44b8-9dfe-f46b202560bf" CreationDate="2019-04-18T05:51:32.187" UserId="8757" Text="I'm trying to unfold a 3D mesh onto a 2D plane. My general idea to do this, would be to cycle through all the faces of the meshes and perform a hierarchical transformation.&#xD;&#xA;&#xD;&#xA;So I would start at the first face and transform it's vertices to the plane, then go to the next face and transform the vertices, that were not already transformed (since the mesh consists of triangles, each face shares 2 vertices with the next triangle) with the transformation of the last face and then add another transformation to get it to the plane. &#xD;&#xA;&#xD;&#xA;The problem is I don't really have an idea how to calculate the transformation matrices.&#xD;&#xA;Can someone help me?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23790" PostHistoryTypeId="1" PostId="8774" RevisionGUID="d9091389-a9a2-44b8-9dfe-f46b202560bf" CreationDate="2019-04-18T05:51:32.187" UserId="8757" Text="Unfold a 3D mesh to a 2D plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="23791" PostHistoryTypeId="3" PostId="8774" RevisionGUID="d9091389-a9a2-44b8-9dfe-f46b202560bf" CreationDate="2019-04-18T05:51:32.187" UserId="8757" Text="|3d|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23792" PostHistoryTypeId="5" PostId="8770" RevisionGUID="e9bdab3b-8c43-4885-bac0-b87cfeb0c22e" CreationDate="2019-04-18T11:14:56.143" UserId="6" Comment="Minor streamlining." Text="I have an ellipse which has -45 degree axis.&#xD;&#xA;&#xD;&#xA;How can I transform the ellipse into a circle? Can I use shear transformation along the x/y axis?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aMJhX.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23793" PostHistoryTypeId="4" PostId="8770" RevisionGUID="e9bdab3b-8c43-4885-bac0-b87cfeb0c22e" CreationDate="2019-04-18T11:14:56.143" UserId="6" Comment="Minor streamlining." Text="How can I transform an ellipse into a circle?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23797" PostHistoryTypeId="2" PostId="8776" RevisionGUID="e10e259b-25ef-4b12-90c6-eb780858712f" CreationDate="2019-04-18T18:55:59.923" UserId="10512" Text="Please help. I'm trying to implement a ray tracer, going by the PBRT book and got stuck on an issue that I fail to find the answer to. My scenes are made from objects and light sources. From that, I can get the spectral power distribution(SPD) of radiance for each pixel (in watts per steradian per meter squared per meter of wavelength). The problem is, how to correctly convert them to RGB color values? It appears that I should first get the XYZ color, and then convert to RGB. But how do you go from an SPD to the XYZ color? I could just integrate the SPD with the xyz-color-mathing-functions, but they work with &quot;relative power distributions&quot;, and I have absolute. The problem is with this scaling that needs to be done. So, if my understanding is correct so far, then the question is, how should I scale my SPDs so that the final image is correct and the XYZ values don't fly far out of the 0..1 range? &#xD;&#xA;&#xD;&#xA;I'm not an expert in color, and it's possible that my undestanding of the situation is wrong. Does it make sense to ask, what _absolute_(i.e. not relative) SPD of radiance should the pixel get(watts per steradian per meter cubed), so that its RGB value is exactly white (1, 1, 1) ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23798" PostHistoryTypeId="1" PostId="8776" RevisionGUID="e10e259b-25ef-4b12-90c6-eb780858712f" CreationDate="2019-04-18T18:55:59.923" UserId="10512" Text="how many watts are in the SPD of the color white?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23799" PostHistoryTypeId="3" PostId="8776" RevisionGUID="e10e259b-25ef-4b12-90c6-eb780858712f" CreationDate="2019-04-18T18:55:59.923" UserId="10512" Text="|raytracing|rendering|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23801" PostHistoryTypeId="50" PostId="8102" RevisionGUID="d8b60ba3-dd33-43e7-b679-447188a3b7fd" CreationDate="2019-04-19T05:03:40.727" UserId="-1" />
  <row Id="23802" PostHistoryTypeId="2" PostId="8777" RevisionGUID="6a40b5f0-19f5-4f78-b02e-40ef67db7dc2" CreationDate="2019-04-19T08:06:28.697" UserId="10515" Text="I've simplified Mikkel Gjoel's idea of dithering with triangular noise to a simple function that only needs a single RNG call. I've stripped away all unecessary bits so it should be pretty readable and understandable what's going on:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-c --&gt;&#xD;&#xA;&#xD;&#xA;    // Dithers and quantizes color value c in [0, 1] to the given color depth.&#xD;&#xA;    // It's expected that rng contains a uniform random variable on [0, 1].&#xD;&#xA;    uint dither_quantize(float c, uint depth, float rng) {&#xD;&#xA;        float cmax = float(depth) - 1.0;&#xD;&#xA;        float ci = c * cmax;&#xD;&#xA;    &#xD;&#xA;        float d;&#xD;&#xA;        if (ci &lt; 0.5 || ci &gt;= cmax - 0.5) {&#xD;&#xA;            // Uniform distribution on [-0.5, 0.5] for edges.&#xD;&#xA;            d = rng - 0.5;&#xD;&#xA;        } else {&#xD;&#xA;            // Symmetric triangular distribution on [-1, 1].&#xD;&#xA;            d = (rng &lt; 0.5) ? sqrt(2.0 * rng) - 1.0 : 1.0 - sqrt(2.0 - 2.0*rng);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        return uint(clamp(ci + d + 0.5, 0.0, cmax));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For the idea and context I'll refer you to Mikkel Gjoel's answer." ContentLicense="CC BY-SA 4.0" />
  <row Id="23803" PostHistoryTypeId="2" PostId="8778" RevisionGUID="5605fc52-7230-4052-968f-f32c2150e28c" CreationDate="2019-04-19T10:19:10.797" UserId="10521" Text="Unfolding the mesh the way you describe it, most likely you will end up with overlapping triangles in the 2D plane unless your 3D geometry is simple. If that's ok, one laborious way is to compute the distances of the triangle sides and the angles and construct the triangle again in the 2D plane.&#xD;&#xA;For example, set:&#xD;&#xA;&#xD;&#xA;a = (0,0)&#xD;&#xA;&#xD;&#xA;b = (0,D1)&#xD;&#xA;&#xD;&#xA;c = (D2*cos(phi), D2*sin(phi))&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;D1 is the distance between a and b in 3D, &#xD;&#xA;&#xD;&#xA;D2 is the distance between a and c in 3D,&#xD;&#xA;&#xD;&#xA;and phi is the angle at the a point.&#xD;&#xA;&#xD;&#xA;Then using an affine transformation you can transform the triangle where you want.&#xD;&#xA;&#xD;&#xA;UV unwrapping, which was mentioned, is the way to go only if its not important to keep the shapes of the 3D triangles intact." ContentLicense="CC BY-SA 4.0" />
  <row Id="23807" PostHistoryTypeId="2" PostId="8779" RevisionGUID="e3c2533d-3fb4-4356-a29c-2f7306947ebb" CreationDate="2019-04-19T15:34:34.343" UserId="2485" Text="I was following [this guide][1] for drawing circles using shadertoy. Now I am trying to mimic the examples behaviour in WebGL.&#xD;&#xA;&#xD;&#xA;Here is a working shadertoy example I try to mimic. The code is not mine, see link above:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;float Circle(vec2 uv, vec2 p, float r, float blur) {&#xD;&#xA;    float d = length(uv-p);&#xD;&#xA;    float c = smoothstep(r, r - blur, d);&#xD;&#xA;    return c;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;    // Normalized pixel coordinates (from 0 to 1)&#xD;&#xA;    vec2 uv = fragCoord.xy/iResolution.xy;&#xD;&#xA;    uv -= .5;&#xD;&#xA;    uv.x *= iResolution.x / iResolution.y;&#xD;&#xA;&#xD;&#xA;	float c = Circle(uv, vec2(.2, -.1), .1, .01);&#xD;&#xA;    	&#xD;&#xA;    // Output to screen&#xD;&#xA;    fragColor = vec4(vec3(c), 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And this is the fragment shader I am using:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;#version 300 es&#xD;&#xA;precision mediump float;&#xD;&#xA;&#xD;&#xA;uniform vec2 iResolution;&#xD;&#xA;&#xD;&#xA;out vec4 outColor;&#xD;&#xA;&#xD;&#xA;float Circle(vec2 uv, vec2 p, float r, float blur) {&#xD;&#xA;    float d = length(uv-p);&#xD;&#xA;    float c = smoothstep(r, r - blur, d);&#xD;&#xA;    return c;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    // Normalized pixel coordinates (from 0 to 1)&#xD;&#xA;    vec2 uv = gl_FragCoord.xy/iResolution.xy;&#xD;&#xA;    uv -= .5;&#xD;&#xA;    uv.x *= iResolution.x / iResolution.y;&#xD;&#xA;&#xD;&#xA;    float c = Circle(uv, vec2(-.5, .2), .1, .01);&#xD;&#xA;    &#xD;&#xA;    // I am discarding all &quot;blackish&quot; values in order to discard &quot;transparent&quot; pixels&#xD;&#xA;    if (c &lt; .1 ){&#xD;&#xA;        discard;&#xD;&#xA;    }&#xD;&#xA;    outColor = vec4(vec3(c), 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I am using another `program` before rendering this one for transparency I am discarding some pixels, see comment.&#xD;&#xA;&#xD;&#xA;And this is the my drawing class, basically I am drawing two Triangles:&#xD;&#xA;&#xD;&#xA;```javascript&#xD;&#xA;class Hud {&#xD;&#xA;  constructor(gl, hudShader) {&#xD;&#xA;    this.hudShader = hudShader;&#xD;&#xA;    this.gl = gl;&#xD;&#xA;    this.glCanvas = document.getElementById(&quot;glcanvas&quot;);&#xD;&#xA;&#xD;&#xA;    const positionBuffer = this.gl.createBuffer();&#xD;&#xA;    gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer);&#xD;&#xA;&#xD;&#xA;    gl.bufferData(&#xD;&#xA;      gl.ARRAY_BUFFER,&#xD;&#xA;      new Float32Array([&#xD;&#xA;        -1.0, -1.0,&#xD;&#xA;        1.0, -1.0,&#xD;&#xA;        -1.0, 1.0,&#xD;&#xA;        -1.0, 1.0,&#xD;&#xA;        1.0, -1.0,&#xD;&#xA;        1.0, 1.0&#xD;&#xA;      ]),&#xD;&#xA;      this.gl.STATIC_DRAW&#xD;&#xA;    );&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  Update() {}&#xD;&#xA;&#xD;&#xA;  Draw() {&#xD;&#xA;    this.gl.useProgram(this.hudShader.program);&#xD;&#xA;&#xD;&#xA;    this.gl.uniform2f(&#xD;&#xA;      this.hudShader.config.uniformLocations.iResolution,&#xD;&#xA;      this.glCanvas.clientWidth,&#xD;&#xA;      this.glCanvas.clientHeight&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    this.gl.enableVertexAttribArray(&#xD;&#xA;      this.hudShader.config.attributeLocations.position&#xD;&#xA;    );&#xD;&#xA;    this.gl.vertexAttribPointer(&#xD;&#xA;      this.hudShader.config.attributeLocations.position,&#xD;&#xA;      2, this.gl.FLOAT, false, 0, 0);&#xD;&#xA;&#xD;&#xA;    this.gl.drawArrays(gl.TRIANGLES, 0, 6);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;```  &#xD;&#xA;&#xD;&#xA;This produces weird behaviour. For example the position of the circle does not correspond to the example. Also if I scale the viewport the circle seems to change position and scale:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What am I doing wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/GgGBR4z8C9o&#xD;&#xA;  [2]: https://i.stack.imgur.com/RTa7v.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="23808" PostHistoryTypeId="1" PostId="8779" RevisionGUID="e3c2533d-3fb4-4356-a29c-2f7306947ebb" CreationDate="2019-04-19T15:34:34.343" UserId="2485" Text="Mimic shadertoy in WebGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="23809" PostHistoryTypeId="3" PostId="8779" RevisionGUID="e3c2533d-3fb4-4356-a29c-2f7306947ebb" CreationDate="2019-04-19T15:34:34.343" UserId="2485" Text="|glsl|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23810" PostHistoryTypeId="2" PostId="8780" RevisionGUID="a06abede-30fa-496c-a4a2-e1cb12abdf83" CreationDate="2019-04-19T15:57:59.387" UserId="9581" Text="I wonder how is it possible to scale all shapes so that they are within boundaries of a [unit] sphere? I know how to do this for a cube: if radius of the sphere is `S` I set the length of `X`, `Y` and `Z` of the cube to `S * math.sqrt(3)/3`. This way, the corners of the cube are barely touching the surface of the sphere. But I don't know how to do this for other objects such as torus, cylinder and cone in [Blender][1]. I wonder, is there a general rule/equation to calculate the scaling factor of a shape so that it fits into a sphere with radius `S`?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.blender.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="23811" PostHistoryTypeId="1" PostId="8780" RevisionGUID="a06abede-30fa-496c-a4a2-e1cb12abdf83" CreationDate="2019-04-19T15:57:59.387" UserId="9581" Text="How to scale primitive shapes [in Blender] so that they are within a [unit] sphere?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23812" PostHistoryTypeId="3" PostId="8780" RevisionGUID="a06abede-30fa-496c-a4a2-e1cb12abdf83" CreationDate="2019-04-19T15:57:59.387" UserId="9581" Text="|transformations|algorithm|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23813" PostHistoryTypeId="6" PostId="8776" RevisionGUID="92297f53-61ce-45b9-b2cf-4326af2c0c34" CreationDate="2019-04-19T17:54:22.100" UserId="10512" Comment="add tag" Text="|raytracing|rendering|lighting|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23820" PostHistoryTypeId="2" PostId="8783" RevisionGUID="4d33ea69-48b0-4bf4-be8a-e76c3c0187d5" CreationDate="2019-04-19T22:43:16.630" UserId="8851" Text="I think it depends on what your goal is and what kind of initial data you are provided with. I don't think that dividing by the forth coordinate solves a clipping task. What it does is switching of the coordinates of your objects from 3D projective (four components) to 3D Euclidean (three components).&#xD;&#xA;&#xD;&#xA;I would say, the basic component you need is a procedure of calculating the intersection point in projective coordinates of a line and a plane. &#xD;&#xA;&#xD;&#xA;An arbitrary point in projective three space is written as a four-vector column:&#xD;&#xA;$$X = \begin{bmatrix}X_1\\X_2\\X_3\\x_4\end{bmatrix}$$ and a plane in projective three space can be expressed as &#xD;&#xA;$$N^T X = 0$$ where&#xD;&#xA;$$N^T X = \begin{bmatrix}N_1 \,\, N_2 \,\, N_3\,\, N_4\end{bmatrix} \begin{bmatrix}X_1\\X_2\\X_3\\x_4\end{bmatrix} = N_1X_1 + N_2X_2 + N_3X_3 + N_4X_4$$&#xD;&#xA;A line in projective three space is traditionally given by a pair of points &#xD;&#xA;$$A = \begin{bmatrix}A_1\\A_2\\A_3\\A_4\end{bmatrix} \,\, \text{ and }\,\, &#xD;&#xA;B = \begin{bmatrix}B_1\\B_2\\B_3\\B_4\end{bmatrix}$$ and any point $X$ on the line is expressed as&#xD;&#xA;$$X = t_1 A + t_2 B$$ for two real numbers $t_1, \, t_2$ not equal to zero simultaneously. Tho find the intersection point of the line $X = t_1 A + t_2 B$ with the plane $N^TX = 0$ we simply plug &#xD;&#xA;$$0 = N^TX = N^T \big(t_1 A + t_2 B \big) = t_1(N^TA) + t_2 (N^TB)$$ and since $t_1, \, t_2$ are determined uniquely up to a common factor, a solution to the equation &#xD;&#xA;$$t_1(N^TA) + t_2 (N^TB) = 0$$ is $t_1 = -\, (N^TB)$ and $t_2 = (N^TA)$. &#xD;&#xA;&#xD;&#xA;Therefore, given a plane $N^TX = 0$ and a line determined by a pair of points $A$ and $B$, the unique intersection point of the line with the plane is calculated as&#xD;&#xA;$$P = - (N^TB)\, A + (N^TA)\, B$$ We us projective coordinates, because it may happen that one of the points on the line, say $B$ is &quot;at infinity&quot; with respect to our perferred choice of Cartesian coordinates. That means that &#xD;&#xA;$B = \begin{bmatrix}B_1\\B_2\\B_3\\0\end{bmatrix}$. In this case, the line is interpreted in Cartesian coordinates as the line passing through the 3D Cartesian point $A = \begin{bmatrix}\frac{A_1}{A_4}\\\frac{A_2}{A_4}\\\frac{A_3}{A_4}\end{bmatrix}$ and aligned with the 3D vector $\vec{V}_B = \begin{bmatrix}B_1\\B_2\\B_3\end{bmatrix}$.  &#xD;&#xA;&#xD;&#xA;In order to clip a line, you can go about it in two different ways, both of which can use the formula for the intersection between a line and a plane. You can find the (projective) equations of the planes of the frustum, intersect the 3d line with them and then project the points onto the screen, which is again intersection of a plane with lines passing through the origin. Alternatively, you can project the two points that determine the line onto the screen (again you can use the formula for the intersection of the line connecing the origin with any of the two points with the plane of the screen), which allows you to know the projection of the 3D line on the screen, and then find the intersection points of the projected line with the borders of the screen. Maybe the second scenario is simpler?&#xD;&#xA;&#xD;&#xA;The screen is parallel to the $x,\,y$ plane of the 3D Cartesian frame, while the $z$ axis is perpendicular to the screen and the screen is at a distance $l$ from the origin of the coordinate system. Therefore, the Cartesian equation of the plane of the screen is $z = l$. In projective coordinates, $z = \frac{X_3}{X_4}$, which means that $\frac{X_3}{X_4} = l$  so the projective equation is $X_3 = l\, X_4$ and can be also expressed as&#xD;&#xA;$$0 = X_3 - l\, X_4 = S^TX = \begin{bmatrix} 0 \,\,\, 0 \,\,\, 1 \,\, - l\end{bmatrix} \begin{bmatrix}X_1\\X_2\\X_3\\x_4\end{bmatrix} $$ where &#xD;&#xA;$S = \begin{bmatrix}0 \\ 0 \\ 1 \\ -l\end{bmatrix}$&#xD;&#xA;so if the 3D line is determined by the pair of points $A = \begin{bmatrix}A_1\\A_2\\A_3\\A_4\end{bmatrix} $ and $B = \begin{bmatrix}B_1\\B_2\\B_3\\B_4\end{bmatrix}$ Hence, with $O = \begin{bmatrix}0\\0\\0\\1\end{bmatrix}$, the projection of $A$ on the screen is&#xD;&#xA;$$\hat{A} =  - (S^TO)\, A + (S^TA)\, O = l\, A + (A_3-l\, A_4)\, O = \begin{bmatrix}l\,A_1\\l\,A_2\\l\,A_3\\l\,A_4\end{bmatrix} + \begin{bmatrix}0\\0\\0\\A_3-l\, A_4\end{bmatrix} = \begin{bmatrix}l\,A_1\\l\,A_2\\l\,A_3\\A_3\end{bmatrix}$$  and the projection of $B$ on the screen is $$\hat{B}= \begin{bmatrix}l\,B_1\\l\,B_2\\l\,B_3\\B_3\end{bmatrix}$$ So one can write this projection in  matrix form as follows:&#xD;&#xA;&#xD;&#xA;$$P_{scr} = - (S^TO)\, \text{Id} + O\,S^T$$&#xD;&#xA;because $P_{scr}A = \Big(- (S^TO)\, \text{Id} + O\,S^T\Big)\,A = - (S^TO)\,A + O\,(S^TA) = - (S^TO)\,A + (S^TA)\,O = \hat{A}$&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;P_{scr} &amp;= - (S^TO)\, \text{Id} + O\,S^T\\&#xD;&#xA;&amp;\\&#xD;&#xA;&amp;= - (-l)\begin{bmatrix}1 &amp; 0 &amp; 0 &amp; 0 \\0 &amp; 1 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 1 &amp; 0\\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix} + \begin{bmatrix}0\\0\\0\\1\end{bmatrix} &#xD;&#xA;\begin{bmatrix}0\,\,\, 0\,\,\, 1 \,\,\, - l\end{bmatrix}\\ &#xD;&#xA;&amp;\\&#xD;&#xA;&amp;= \begin{bmatrix}l &amp; 0 &amp; 0 &amp; 0 \\0 &amp; l &amp; 0 &amp; 0\\0 &amp; 0 &amp; l &amp; 0\\0 &amp; 0 &amp; 0 &amp; l\end{bmatrix} + \begin{bmatrix}0 &amp; 0 &amp; 0 &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 1 &amp; -l \end{bmatrix}\\&#xD;&#xA;&amp;\\&#xD;&#xA;&amp; = \begin{bmatrix}l &amp; 0 &amp; 0 &amp; 0\\0 &amp; l &amp; 0 &amp; 0\\0 &amp; 0 &amp; l &amp; 0\\0 &amp; 0 &amp; 1 &amp; 0\end{bmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;And thus&#xD;&#xA;$$\hat{A} = P_{scr}\, A \,\, \text{ and } \,\, &#xD;&#xA;\hat{B} = P_{scr}\, B$$ &#xD;&#xA;When you have your points projected on the screen plane, you would like to get rid of the $z-$coordiante, so you need to remove the third (out of our) component of your projected points, i.e.:&#xD;&#xA;$\hat{A} = \begin{bmatrix}l\,A_1\\l\,A_2\\l\,A_3\\A_3\end{bmatrix} \mapsto \begin{bmatrix}l\,A_1\\l\,A_2\\A_3\end{bmatrix}$ so if you take the projection from four vectors to three vectors&#xD;&#xA;$$P_0 = \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0\\0 &amp; 1 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}$$ and muptiply it by  $P_{scr}$ from the right as $P_0P_{scr}$, we can take the projective map from the projective three space to the projective plane of the screen&#xD;&#xA;$$P = P_0P_{scr} = \begin{bmatrix} l &amp; 0 &amp; 0 &amp; 0\\0 &amp; l &amp; 0 &amp; 0\\0 &amp; 0 &amp; 1 &amp; 0\end{bmatrix}$$ &#xD;&#xA;So, to recap, given  a line in projective three space, passing through the pair of points $A$ and $B$, their screen images, in projective coordinates of the screen, are&#xD;&#xA;$\hat{A} = P\, A$ and $\hat{B} =P \, B$. The formula for the intersection of a line with a plane in projective three space translates verbatim to the intersection of a line given by a pair of points $\hat{A}$ and $\hat{B}$ with another line given as an equation $N^T\hat{X} = 0$ in the projective plane, where $N = \begin{bmatrix} n_1\\n_2\\n_3\end{bmatrix}$, &#xD;&#xA;$$\hat{X}_N = (- N^T\hat{B})\hat{A} + (N^T\hat{A})\hat{B}$$ so &#xD;&#xA;alltogether &#xD;&#xA;$$\hat{X}_N = (- N^TP{B})\,P{A} + (N^P{A})\,P{B}$$ So this is the formula for the projected points of intersection of the three dimensional line with the frustum's boundary. For example,  the right vertical boundary of the screen is given by an $N_{right\, vert} = \begin{bmatrix} w\\0\\0\end{bmatrix}$ and the bottom horizontal boundary of the screen is given by an $N_{bottom\, hor} = \begin{bmatrix} 0\\- h\\0\end{bmatrix}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23821" PostHistoryTypeId="2" PostId="8784" RevisionGUID="1c21a52c-f833-4be9-b598-68e7771cd57c" CreationDate="2019-04-19T23:44:01.747" UserDisplayName="user9485" Text="Yes, there is a fairly general algorithm to calculate this scaling factor, which works for all shapes with a known parametric representation. First, substitute the parametric equation of the shape (e.g. a torus, cylinder or cone) into the implicit equation of the sphere, $x^2 + y^2 + z^2 = S^2$. Then, solve this equation for the radius of the sphere. The result will be one or more intervals for values of $S$ for which the shape intersects the sphere with radius $S$. The largest value of $S$ is the radius of the shape's bounding sphere.&#xD;&#xA;&#xD;&#xA;Example (torus): Substituting the parametric equation of the torus centered at the origin with major radius $R$ and minor radius $r$ into the implicit equation of the sphere yields $2Rr \cos(\phi) + R^2 + r^2 - S^2 = 0$, which is equivalent to $S\in[R-r,R+r]$. So if you want a torus to fit into a unit sphere, you need to choose the major radius and minor radius such that $R+r\le 1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="23822" PostHistoryTypeId="2" PostId="8785" RevisionGUID="168063ab-be02-4416-ab54-41ea6ad3b838" CreationDate="2019-04-19T23:44:39.760" UserId="8851" Text="If you have three points on the plane $a = (a_1, a_2), \, b = (b_1, b_2) $ and $c = (c_1, c_2)$ that determine a triangle, and three points $A = (A_1, A_2, A_3), \, B = (B_1, B_2, B_3)$ and $C = (C_1, C_2, C_3)$ in three space determining another triangle. We want the matrix that maps the triangle $ABC$ to $abc$ or vice versa. &#xD;&#xA;&#xD;&#xA;To do that, we map the standard right-angled isosceles triangle with vertices &#xD;&#xA;$$\begin{bmatrix}0\\0\\0 \end{bmatrix},\,\, \begin{bmatrix}1\\0\\0 \end{bmatrix},\,\, \begin{bmatrix}0\\1\\0 \end{bmatrix}$$  to each of the triangles and then compose the maps by multiplying the relevant matrices. The matrix from the standard triangle to $abc$ is&#xD;&#xA;$$m = \begin{bmatrix}b_1-a_1&amp;c_1-a_1&amp;0&amp;a_1\\b_2-a_2&amp;c_2-a_2&amp;0&amp;a_2\\&#xD;&#xA;0 &amp; 0 &amp;(b_1-a_1)(c_2-a_2) - (b_2-a_2)(c_1-a_1)&amp;a_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1  \end{bmatrix}$$  and the matrix from the standard triangle to $ABC$ is&#xD;&#xA;$$M = \begin{bmatrix}&#xD;&#xA;B_1-A_1 &amp; C_1-A_1 &amp;(B_2-A_2)(C_3-A_3) - (B_3-A_3)(C_2-A_2)&amp; A_1\\&#xD;&#xA;B_2-A_2 &amp; C_2-A_2 &amp;(B_3-A_3)(C_1-A_1) - (B_1-A_1)(C_2-A_2)&amp; A_2\\&#xD;&#xA;B_3-A_3 &amp; C_3-A_3 &amp;(B_1-A_1)(C_2-A_2) - (B_2-A_2)(C_1-A_1)&amp; A_3\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1  \end{bmatrix}$$ &#xD;&#xA;Then, the matrix from the triangle $ABC$ to the triangle $abc$ is $\Big(m\, M^{-1}\Big)$ and the matrix from the triangle $abc$ to the triangle $ABC$ is $\Big(M\, m^{-1}\Big)$. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23823" PostHistoryTypeId="5" PostId="8785" RevisionGUID="1afafdab-b052-46eb-9655-1d149d85b8b4" CreationDate="2019-04-19T23:57:46.843" UserId="8851" Comment="added 267 characters in body" Text="If you have three points on the plane $a = (a_1, a_2), \, b = (b_1, b_2) $ and $c = (c_1, c_2)$ that determine a triangle, and three points $A = (A_1, A_2, A_3), \, B = (B_1, B_2, B_3)$ and $C = (C_1, C_2, C_3)$ in three space determining another triangle. We want the matrix that maps the triangle $ABC$ to $abc$ or vice versa. &#xD;&#xA;&#xD;&#xA;To do that, we map the standard right-angled isosceles triangle with vertices &#xD;&#xA;$$\begin{bmatrix}0\\0\\0 \end{bmatrix},\,\, \begin{bmatrix}1\\0\\0 \end{bmatrix},\,\, \begin{bmatrix}0\\1\\0 \end{bmatrix}$$  to each of the triangles and then compose the maps by multiplying the relevant matrices. The matrix from the standard triangle to $abc$ is&#xD;&#xA;$$m = \begin{bmatrix}b_1-a_1&amp;c_1-a_1&amp;0&amp;a_1\\b_2-a_2&amp;c_2-a_2&amp;0&amp;a_2\\&#xD;&#xA;0 &amp; 0 &amp;(b_1-a_1)(c_2-a_2) - (b_2-a_2)(c_1-a_1)&amp;a_2\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1  \end{bmatrix}$$  and the matrix from the standard triangle to $ABC$ is&#xD;&#xA;$$M = \begin{bmatrix}&#xD;&#xA;B_1-A_1 &amp; C_1-A_1 &amp;(B_2-A_2)(C_3-A_3) - (B_3-A_3)(C_2-A_2)&amp; A_1\\&#xD;&#xA;B_2-A_2 &amp; C_2-A_2 &amp;(B_3-A_3)(C_1-A_1) - (B_1-A_1)(C_2-A_2)&amp; A_2\\&#xD;&#xA;B_3-A_3 &amp; C_3-A_3 &amp;(B_1-A_1)(C_2-A_2) - (B_2-A_2)(C_1-A_1)&amp; A_3\\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1  \end{bmatrix}$$ &#xD;&#xA;Then, the matrix from the triangle $ABC$ to the triangle $abc$ is $\Big(m\, M^{-1}\Big)$ and the matrix from the triangle $abc$ to the triangle $ABC$ is $\Big(M\, m^{-1}\Big)$. To obtain fulluy a linear (more accurately affine) map from $ABC$ to $abc$ we can write&#xD;&#xA;$$\begin{bmatrix}y_1\\y_2 \end{bmatrix} = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0\\\end{bmatrix} \Big(m\, M^{-1}\Big) \, \begin{bmatrix}x_1\\x_2\\x_3\\1\end{bmatrix}$$ " ContentLicense="CC BY-SA 4.0" />
  <row Id="23831" PostHistoryTypeId="2" PostId="8787" RevisionGUID="ccb95e18-b999-4801-a14c-5636eadfae85" CreationDate="2019-04-20T08:36:48.623" UserId="10525" Text="What I would like to do is to create a crater on a field. To do so, I thought that creating a universal crater object (something cone-shaped) and then subtracting it from the field on a specified point might be a good idea. &#xD;&#xA;&#xD;&#xA;So I would specify a &quot;middle point&quot; on the field, take the lowest point of the crater and move the crater by its lowest point onto the middle point of the field and then push it by its size of the crater into the field. Then apply said subtracting operation.&#xD;&#xA;&#xD;&#xA;My question is: Are there any techniques/libraries which help me accomplish this? They should be either openGL-compatible or work on .obj file format." ContentLicense="CC BY-SA 4.0" />
  <row Id="23832" PostHistoryTypeId="1" PostId="8787" RevisionGUID="ccb95e18-b999-4801-a14c-5636eadfae85" CreationDate="2019-04-20T08:36:48.623" UserId="10525" Text="How to use boolean operations (eg. subtraction) on 3D triangulated objects, originally stored as a .obj file, using openGL or other libraries?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23833" PostHistoryTypeId="3" PostId="8787" RevisionGUID="ccb95e18-b999-4801-a14c-5636eadfae85" CreationDate="2019-04-20T08:36:48.623" UserId="10525" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23834" PostHistoryTypeId="5" PostId="8785" RevisionGUID="5b5710a7-f4fd-45c7-977d-18c008a47a56" CreationDate="2019-04-20T20:36:10.593" UserId="8851" Comment="added 1774 characters in body" Text="When performing the unfolding the way you want, after you have unfolded one triangle in the plane, the next one should be one of the three triangles, adjacent to the unfolded one, i.e. the next triangle to be unfolded shares a common edge with the unfolded one. &#xD;&#xA;&#xD;&#xA;Assume you have a triangle $ABC$ in three space with vertices  $$A = [A_1, A_2, A_3], \,\, B = [B_1, B_2, B_3],\,\, C = [C_1, C_2, C_3]$$ which is one of the triangles from the 3D mesh. &#xD;&#xA;&#xD;&#xA;**If** $ABC$ is the first triangle you are starting the unfolding with, then: &#xD;&#xA;&#xD;&#xA;1. calculate $l_{AB} = ||A - B|| = \sqrt{(A_1 - B_1)^2 + (A_2 - B_2)^2 + (A_3 - B_3)^2}$; &#xD;&#xA;2. set the 2D vertices $a = [0,0]$ and $b = [l_{AB}, 0]$ as well as $$l_{ab} = l_{AB};&#xD;&#xA;&#xD;&#xA;**Else if** $ABC$ is a next triangle to be unfolded in the plane, i.e. you have already unfolded one of $ABC$'s adjacent (neighboring) triangles, therefore one of $ABC$'s edges is already unfolded in the plane. Say that this edge is $AB$ and it is unfolded in the plane as the edge with vertices $a = [a_1, a_2]$ and $b = [b_1, b_2]$, where $l_{ab} = ||a-b|| = \sqrt{(a_1 - b_1)^2 + (a_2 - b_2)^2} = ||A-B|| = l_{AB}$.  &#xD;&#xA;&#xD;&#xA;Either way, for the triangle $ABC$ you already have the edge $AB$ unfolded as $ab$ in the plane, so that $l_{ab} = l_{AB}$ (i.e. you already know $a, \, b$ and $l_{ab}$). The question is, how do you find the coordinates of the third vertex $c = [c_1, c_2]$ so that $l_{bc} = l_{BC}$ and $l_{ca} = l_{CA}$? We impose the latter two conditions because two triangles that have pairwise equal edge-lengths are congruent (isometric, i.e. identical copies of each other).  &#xD;&#xA;&#xD;&#xA;For your information, I will write vectors like $B - A = [B_1 - A_1, \, B_2 - A_2, \, B_3 - A_3]$ and $C - A = [C_1 - A_1, \, C_2 - A_2, \, C_3 - A_3]$ and $b-a = [b_1 - a_1, b_2-a_2]$ and will use dot product $\cdot$ and cross product $\times$ between vectors. You already know what $||B-A|| = l_{AB}$ and $||C-A|| = l_{CA}$ are and that $l_{AB} = l_{ab} = \|b-a\|$.&#xD;&#xA;&#xD;&#xA;1. Calculate $$s = \frac{\|(B-A)\times(C-A)\|}{l_{ab}^2}$$&#xD;&#xA;&#xD;&#xA;2. Calculate $$c = \frac{(B-A)\cdot(C-A)}{l_{ab}^2}$$   &#xD;&#xA;&#xD;&#xA;3. Calculate both pairs of coordinates &#xD;&#xA;\begin{align}&#xD;&#xA;&amp;c'_1 = a_1 + c(b_1-a_1) - s(b_2 - a_2)\\&#xD;&#xA;&amp;c'_2 = a_2 + c(b_2-a_2) + s(b_1 - a_1)&#xD;&#xA;\end{align}&#xD;&#xA;and &#xD;&#xA;\begin{align}&#xD;&#xA;&amp;c''_1 = a_1 + c(b_1-a_1) + s(b_2 - a_2)\\&#xD;&#xA;&amp;c''_2 = a_2 + c(b_2-a_2) - s(b_1 - a_1)&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;4. You have two candidate points $c' = [c'_1, c'_2]$ and $c'' = [c''_1, c''_2]$&#xD;&#xA;&#xD;&#xA;5. Perform a check whether $c'$ is on the same side of the edge $ab$ as the  triangle unfolded right before $ABC$. &#xD;&#xA;&#xD;&#xA;**If** it is not, then $c = c'$&#xD;&#xA;&#xD;&#xA;**else if** it is, then $c = c''$&#xD;&#xA;&#xD;&#xA; As a result of this procedure, you have constructed the planar unfolding $abc$ of triangle $ABC$ and the next triangle from the 3D mesh to be unfolded (if any), should be the one that shares either edge $BC$ or $CA$ with $ABC$. Either way, for that next triangle, you already know the unfolding $bc$ of the edge $BC$ and the unfolding $ca$ of $CA$ (whichever is relevant), so you can apply the same procedure for that next triangle. And so on and so forth, until you have unfolded all triangles from the mesh. &#xD;&#xA;&#xD;&#xA;Have in mind that there are 3D meshes that do not posses unfolding that do not self overlap, no matter what you do. For such meshes there no greedy algorithms or any other algorithm that can do it.     " ContentLicense="CC BY-SA 4.0" />
  <row Id="23835" PostHistoryTypeId="5" PostId="8772" RevisionGUID="232b53ae-6d4f-4528-9c83-82c971ca5225" CreationDate="2019-04-20T21:42:43.427" UserId="10096" Comment="added 170 characters in body" Text="You can use a shear, or equivalently a rotation by 45, scale along one of the axes, rotate back (which is equivalent to the shear which you are looking for).&#xD;&#xA;&#xD;&#xA;EDIT: On second thought, you don't need to even rotate back unless your circle is marked, since a circle is rotation invariant (if the rotation is around its center)." ContentLicense="CC BY-SA 4.0" />
  <row Id="23836" PostHistoryTypeId="2" PostId="8788" RevisionGUID="ce7027a0-09d3-47fd-ae14-175e60a4690f" CreationDate="2019-04-21T01:30:51.013" UserId="10526" Text="I'm not sure what happens there. Looking at the rendering of &quot;considerations&quot; in your example, the &quot;cons&quot; looks like what you get when you do crude sub pixel anti-aliasing, without applying the necessary &quot;fix up&quot; to make it look good. But then the &quot;der&quot; in the same word looks like there's no sub-pixel anti-aliasing.&#xD;&#xA;&#xD;&#xA;You can find a good article about how good looking sub-pixel anti-aliasing works here https://www.grc.com/ct/ctwhat.htm and for the &quot;fix up&quot; part here https://www.grc.com/ct/freeandclear.htm&#xD;&#xA;&#xD;&#xA;What it comes down to is: if you just compute the R/G/B intensities by calculating the covered area for each sub-pixel, the resulting color fringes are very ugly/irritating. To fix it you have to apply a horizontal blur/low-pass filter to the sub-pixel image. The result is an image that's less sharp but also has far less saturated colors. I.e. something like your &quot;Check you&quot; example." ContentLicense="CC BY-SA 4.0" />
  <row Id="23837" PostHistoryTypeId="5" PostId="8788" RevisionGUID="a519041a-fdd8-4436-a96f-5fca78dde3b9" CreationDate="2019-04-21T01:40:39.120" UserId="10526" Comment="added 43 characters in body" Text="I'm not sure what happens there. Looking at the rendering of &quot;considerations&quot; in your example, the &quot;cons&quot; looks like what you get when you do crude sub pixel anti-aliasing, without applying the necessary &quot;fix up&quot; to make it look good. But then the &quot;der&quot; in the same word looks like there's no sub-pixel anti-aliasing.&#xD;&#xA;&#xD;&#xA;You can find a good article about how good looking sub-pixel anti-aliasing works here https://www.grc.com/ct/ctwhat.htm and for the &quot;fix up&quot; part here https://www.grc.com/ct/freeandclear.htm and here https://www.grc.com/ct/cttech.htm&#xD;&#xA;&#xD;&#xA;What it comes down to is: if you just compute the R/G/B intensities by calculating the covered area for each sub-pixel, the resulting color fringes are very ugly/irritating. To fix it you have to apply a horizontal blur/low-pass filter to the sub-pixel image. The result is an image that's less sharp but also has far less saturated colors. I.e. something like your &quot;Check you&quot; example." ContentLicense="CC BY-SA 4.0" />
  <row Id="23842" PostHistoryTypeId="50" PostId="8587" RevisionGUID="4b20916a-266e-4aa7-8508-7dc70a74fcfb" CreationDate="2019-04-21T09:02:10.407" UserId="-1" />
  <row Id="23843" PostHistoryTypeId="2" PostId="8790" RevisionGUID="5e4f91df-fdaf-4376-aca0-12d7184242ba" CreationDate="2019-04-21T11:28:20.037" UserId="10528" Text="I am novice lacking professional terminology.&#xD;&#xA;&#xD;&#xA;I want to create from 3D object (let's say from polygon mesh) a slice through to PNG file in order to create something like reverse medical MRI scan.&#xD;&#xA;&#xD;&#xA;How it's called? So cant find methods of achieving it. Bonus points for pointing to a library doing that.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23844" PostHistoryTypeId="1" PostId="8790" RevisionGUID="5e4f91df-fdaf-4376-aca0-12d7184242ba" CreationDate="2019-04-21T11:28:20.037" UserId="10528" Text="3D object to slices like in medical scan" ContentLicense="CC BY-SA 4.0" />
  <row Id="23845" PostHistoryTypeId="3" PostId="8790" RevisionGUID="5e4f91df-fdaf-4376-aca0-12d7184242ba" CreationDate="2019-04-21T11:28:20.037" UserId="10528" Text="|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23846" PostHistoryTypeId="2" PostId="8791" RevisionGUID="cc1eea58-cfbd-48c0-ab09-efe4c490990c" CreationDate="2019-04-21T13:19:28.003" UserId="4748" Text="Some terminology: Intersection of a polyhedron with a plane.&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KileD.png&quot; width=&quot;260&quot; /&gt;&#xD;&#xA;&lt;br /&gt;&#xD;&#xA;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#xD;&#xA;&lt;sup&gt;&#xD;&#xA;[Wolfram Demo](http://demonstrations.wolfram.com/IntersectionOfAConvexPolyhedronAndAPlane/).&#xD;&#xA;&lt;/sup&gt;&#xD;&#xA;&lt;hr /&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23847" PostHistoryTypeId="5" PostId="8790" RevisionGUID="905278b4-c0c9-44bc-ba8e-826c87cc8a87" CreationDate="2019-04-21T16:12:15.437" UserId="10528" Comment="added 55 characters in body" Text="I am novice lacking professional terminology.&#xD;&#xA;&#xD;&#xA;I want to create from 3D object (let's say from polygon mesh) a slice through to PNG file in order to create something like reverse medical MRI scan from which volumetric renders are created.&#xD;&#xA;&#xD;&#xA;How it's called? It will enable me to find methods of achieving it. Bonus points for pointing to a library doing that.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23848" PostHistoryTypeId="50" PostId="8688" RevisionGUID="230bb368-00f5-4b99-9ca2-66f460e11550" CreationDate="2019-04-21T19:02:25.477" UserId="-1" />
  <row Id="23849" PostHistoryTypeId="4" PostId="8787" RevisionGUID="d54a1208-9eb0-4751-affa-ea7e1494a5dd" CreationDate="2019-04-21T20:26:20.503" UserId="10525" Comment="specified question" Text="How to do CSG on 3D triangulated objects, originally stored as a .obj file, using openGL or other libraries?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23850" PostHistoryTypeId="2" PostId="8792" RevisionGUID="0f7f1a33-224c-4e55-bbf9-2d6a26f41ac2" CreationDate="2019-04-22T11:53:16.807" UserId="10534" Text="I did not go into much detail with your code but the first thing that comes to mind is that you are rendering with respect to the resolution passed into the shader.&#xD;&#xA;&#xD;&#xA;    ec2 uv = fragCoord.xy/iResolution.xy;&#xD;&#xA;&#xD;&#xA;hope this helps." ContentLicense="CC BY-SA 4.0" />
  <row Id="23851" PostHistoryTypeId="5" PostId="8792" RevisionGUID="59862810-2eed-4d4e-98a8-658e29f3fe86" CreationDate="2019-04-22T12:36:09.967" UserId="10534" Comment="added 128 characters in body" Text="I did not go into much detail with your code but the first thing that comes to mind is that you are rendering with respect to the resolution passed into the shader.&#xD;&#xA;&#xD;&#xA;    ec2 uv = fragCoord.xy/iResolution.xy;&#xD;&#xA;&#xD;&#xA;hope this helps.&#xD;&#xA;&#xD;&#xA;maybe do an aspect Ratio calculation ?&#xD;&#xA;&#xD;&#xA;    float aspect = float(iResolution.x) / float(iResolution.y ? iResolution.y: 1);" ContentLicense="CC BY-SA 4.0" />
  <row Id="23853" PostHistoryTypeId="2" PostId="8793" RevisionGUID="db864daa-3a18-42a4-8838-e44c77204961" CreationDate="2019-04-23T01:49:34.853" UserId="10515" Text="The context of this question is correct dithering of color with gamma correction. In dithering we add (shaped) noise $n$ to a signal $s \in [0, 1]$ based on a random variable $r \in [0, 1]$&#xD;&#xA;&#xD;&#xA;$$s' = s + n(s, r)$$&#xD;&#xA;&#xD;&#xA;such that when we quantize the signal to $m$ steps the rounding will end up distorting the signal less.&#xD;&#xA;&#xD;&#xA;I already have a function that in a linear world from [here](https://computergraphics.stackexchange.com/questions/5904/whats-a-proper-way-to-clamp-dither-noise/8777#8777), where $n$ is a symmetric triangular distribution on $[-1, 1]$ (with the caveat that for $s$ close to $0$ or $1$ we switch to a uniform distribution on $[-\frac{1}{2}, \frac{1}{2}]$), as it has mean $0$ and appropriately smoothes out the rounding (demo that incorrectly ignores gamma: https://www.shadertoy.com/view/Wts3zH).&#xD;&#xA;&#xD;&#xA;However in sRGB files we have to deal with gamma. Essentially we have an invertable transform $t$ (often $t(x) = x^{2.4}$) that is applied before/after quantization to allocate more steps to lower intensities.&#xD;&#xA;&#xD;&#xA;This means that the average color when viewing is no longer (ignoring quantization for now):&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(s + n(s, r)\right) = s$$&#xD;&#xA;&#xD;&#xA;But is instead:&#xD;&#xA;&#xD;&#xA;$$\int_0^1 t^{-1}\left(s + n(s, r)\right) &gt; s$$&#xD;&#xA;&#xD;&#xA;How can we change our noise function $n$ so that the average color is again $s$ after dithering, while maintaining our properties from the triangular distribution as much as possible?&#xD;&#xA;&#xD;&#xA;If you want to give a shot, here is a demo that can show you the error from dithering, which has gamma correction: https://www.shadertoy.com/view/3tf3Dn." ContentLicense="CC BY-SA 4.0" />
  <row Id="23854" PostHistoryTypeId="1" PostId="8793" RevisionGUID="db864daa-3a18-42a4-8838-e44c77204961" CreationDate="2019-04-23T01:49:34.853" UserId="10515" Text="Noise shaping for dithering with gamma?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23855" PostHistoryTypeId="3" PostId="8793" RevisionGUID="db864daa-3a18-42a4-8838-e44c77204961" CreationDate="2019-04-23T01:49:34.853" UserId="10515" Text="|noise|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23856" PostHistoryTypeId="5" PostId="8793" RevisionGUID="ebd557ed-65b1-47d7-a317-bac33ce54fe7" CreationDate="2019-04-23T05:00:08.367" UserId="10515" Comment="added 6 characters in body" Text="The context of this question is correct dithering of color with gamma correction. In dithering we add (shaped) noise $n$ to a signal $s \in [0, 1]$ based on a random variable $r \in [0, 1]$&#xD;&#xA;&#xD;&#xA;$$s' = s + n(s, r)$$&#xD;&#xA;&#xD;&#xA;such that when we quantize the signal to $m$ steps the rounding will end up distorting the signal less.&#xD;&#xA;&#xD;&#xA;I already have a function that works in a linear world from [here](https://computergraphics.stackexchange.com/questions/5904/whats-a-proper-way-to-clamp-dither-noise/8777#8777), where $n$ is a symmetric triangular distribution on $[-1, 1]$ (with the caveat that for $s$ close to $0$ or $1$ we switch to a uniform distribution on $[-\frac{1}{2}, \frac{1}{2}]$), as it has mean $0$ and appropriately smoothes out the rounding (demo that incorrectly ignores gamma: https://www.shadertoy.com/view/Wts3zH).&#xD;&#xA;&#xD;&#xA;However in sRGB files we have to deal with gamma. Essentially we have an invertable transform $t$ (often $t(x) = x^{2.4}$) that is applied before/after quantization to allocate more steps to lower intensities.&#xD;&#xA;&#xD;&#xA;This means that the average color when viewing is no longer (ignoring quantization for now):&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(s + n(s, r)\right) = s$$&#xD;&#xA;&#xD;&#xA;But is instead:&#xD;&#xA;&#xD;&#xA;$$\int_0^1 t^{-1}\left(s + n(s, r)\right) &gt; s$$&#xD;&#xA;&#xD;&#xA;How can we change our noise function $n$ so that the average color is again $s$ after dithering, while maintaining our properties from the triangular distribution as much as possible?&#xD;&#xA;&#xD;&#xA;If you want to give a shot, here is a demo that can show you the error from dithering, which has gamma correction: https://www.shadertoy.com/view/3tf3Dn." ContentLicense="CC BY-SA 4.0" />
  <row Id="23857" PostHistoryTypeId="2" PostId="8794" RevisionGUID="ea4b0932-f019-4512-9fac-72a040726c7a" CreationDate="2019-04-23T18:48:20.897" UserId="10515" Text="There is no unique answer or approach and it's not simple either. I'm afraid that once you know the absolute spectral distribution of light that falls onto your camera, you've only computed half the story. What happens now depends on what observer you are trying to simulate, and to what accuracy. &#xD;&#xA;&#xD;&#xA;I can highly recommend [Moving Frostbite to Physically Based Rendering 3.0](https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf) from SIGGRAPH 2014. It contains many details especially section 4.3 and 5.1.&#xD;&#xA;&#xD;&#xA;If you are trying to simulate a camera you need to answer some other questions for yourself:&#xD;&#xA;&#xD;&#xA; - What ISO am I simulating?&#xD;&#xA; - What is my shutter speed?&#xD;&#xA; - What is my aperture?&#xD;&#xA;&#xD;&#xA;With the answers to that you can correct how much light falls onto your sensor and how sensitive it is to that light. Perhaps you don't have to correct for aperture if you already simulate this for depth-of-field.&#xD;&#xA;&#xD;&#xA;Then knowing that you need to know how that sensor responds to light of different wavelengths. Perhaps you can find some spectral responsitivity diagrams for the camera sensor you are interested in simulating? Then you can divide by integrate for each sensor type (R, G, B) to get RAW exposure, which still needs processing to turn into sRGB (which involves choosing a whitepoint). It's not simple.&#xD;&#xA;&#xD;&#xA;&gt; I'm not an expert in color, and it's possible that my undestanding of the situation is wrong. Does it make sense to ask, what absolute(i.e. not relative) SPD of radiance should the pixel get(watts per steradian per meter cubed), so that its RGB value is exactly white (1, 1, 1) ?&#xD;&#xA;&#xD;&#xA;Absolutely not. If you are indoors and look at a piece of paper, that is white, right? Now if you move outdoors, a much greater amount of light hits your eye, yet you still view it as white.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23858" PostHistoryTypeId="5" PostId="8794" RevisionGUID="31c904b1-9ef5-4164-9aca-3e867757bc38" CreationDate="2019-04-23T18:55:37.477" UserId="10515" Comment="added 256 characters in body" Text="There is no unique answer or approach and it's not simple either. I'm afraid that once you know the absolute spectral distribution of light that falls onto your camera, you've only computed half the story. What happens now depends on what observer you are trying to simulate, and to what accuracy. &#xD;&#xA;&#xD;&#xA;I can highly recommend [Moving Frostbite to Physically Based Rendering 3.0](https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf) from SIGGRAPH 2014. It contains many details especially section 4.3 and 5.1.&#xD;&#xA;&#xD;&#xA;If you are trying to simulate a camera you need to answer some other questions for yourself:&#xD;&#xA;&#xD;&#xA; - What ISO am I simulating?&#xD;&#xA; - What is my shutter speed?&#xD;&#xA; - What is my aperture?&#xD;&#xA;&#xD;&#xA;With the answers to that you can correct how much light falls onto your sensor and how sensitive it is to that light. Perhaps you don't have to correct for aperture if you already simulate this for depth-of-field.&#xD;&#xA;&#xD;&#xA;Then knowing that you need to know how that sensor responds to light of different wavelengths. Perhaps you can find some spectral responsitivity diagrams for the camera sensor you are interested in simulating? Then you can divide by integrate for each sensor type (R, G, B) to get RAW exposure, which still needs processing to turn into sRGB (which involves choosing a whitepoint). It's not simple.&#xD;&#xA;&#xD;&#xA;&gt; I'm not an expert in color, and it's possible that my undestanding of the situation is wrong. Does it make sense to ask, what absolute(i.e. not relative) SPD of radiance should the pixel get(watts per steradian per meter cubed), so that its RGB value is exactly white (1, 1, 1) ?&#xD;&#xA;&#xD;&#xA;Absolutely not. If you are indoors and look at a piece of paper, that is white, right? Now if you move outdoors, a much greater amount of light hits your eye, yet you still view it as white.&#xD;&#xA;&#xD;&#xA;Assuming you view your image on a monitor, there's a lot of color spaces involved: the absolute spectral distribution, the camera, the stored image, the monitor used to display the image and your eyes. They all have different ideas of what 'white' means, and they all have different settings to tweak it: brightness, whitepoint, exposure, viewing conditions, etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="23859" PostHistoryTypeId="5" PostId="8774" RevisionGUID="86dca3e3-8176-4669-b4b6-f5ea0ab9269a" CreationDate="2019-04-24T10:18:06.927" UserId="10527" Comment="deleted 4 characters in body; edited tags" Text="I'm trying to unfold a 3D mesh onto a 2D plane. My general idea to do this, would be to cycle through all the faces of the meshes and perform a hierarchical transformation.&#xD;&#xA;&#xD;&#xA;So I would start at the first face and transform it's vertices to the plane, then go to the next face and transform the vertices, that were not already transformed (since the mesh consists of triangles, each face shares 2 vertices with the next triangle) with the transformation of the last face and then add another transformation to get it to the plane. &#xD;&#xA;&#xD;&#xA;The problem is I don't really have an idea how to calculate the transformation matrices.&#xD;&#xA;Can someone help me?&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="23860" PostHistoryTypeId="24" PostId="8774" RevisionGUID="86dca3e3-8176-4669-b4b6-f5ea0ab9269a" CreationDate="2019-04-24T10:18:06.927" Comment="Proposed by 10527 approved by 8757 edit id of 474" ContentLicense="CC BY-SA 4.0" />
  <row Id="23861" PostHistoryTypeId="5" PostId="8783" RevisionGUID="b76199a0-c06a-4186-8e7e-f00ef8536ad5" CreationDate="2019-04-24T14:48:28.203" UserId="8851" Comment="added 1 character in body" Text="I think it depends on what your goal is and what kind of initial data you are provided with. I don't think that dividing by the forth coordinate solves a clipping task. What it does is switching of the coordinates of your objects from 3D projective (four components) to 3D Euclidean (three components).&#xD;&#xA;&#xD;&#xA;I would say, the basic component you need is a procedure of calculating the intersection point in projective coordinates of a line and a plane. &#xD;&#xA;&#xD;&#xA;An arbitrary point in projective three space is written as a four-vector column:&#xD;&#xA;$$X = \begin{bmatrix}X_1\\X_2\\X_3\\x_4\end{bmatrix}$$ and a plane in projective three space can be expressed as &#xD;&#xA;$$N^T X = 0$$ where&#xD;&#xA;$$N^T X = \begin{bmatrix}N_1 \,\, N_2 \,\, N_3\,\, N_4\end{bmatrix} \begin{bmatrix}X_1\\X_2\\X_3\\x_4\end{bmatrix} = N_1X_1 + N_2X_2 + N_3X_3 + N_4X_4$$&#xD;&#xA;A line in projective three space is traditionally given by a pair of points &#xD;&#xA;$$A = \begin{bmatrix}A_1\\A_2\\A_3\\A_4\end{bmatrix} \,\, \text{ and }\,\, &#xD;&#xA;B = \begin{bmatrix}B_1\\B_2\\B_3\\B_4\end{bmatrix}$$ and any point $X$ on the line is expressed as&#xD;&#xA;$$X = t_1 A + t_2 B$$ for two real numbers $t_1, \, t_2$ not equal to zero simultaneously. Tho find the intersection point of the line $X = t_1 A + t_2 B$ with the plane $N^TX = 0$ we simply plug &#xD;&#xA;$$0 = N^TX = N^T \big(t_1 A + t_2 B \big) = t_1(N^TA) + t_2 (N^TB)$$ and since $t_1, \, t_2$ are determined uniquely up to a common factor, a solution to the equation &#xD;&#xA;$$t_1(N^TA) + t_2 (N^TB) = 0$$ is $t_1 = -\, (N^TB)$ and $t_2 = (N^TA)$. &#xD;&#xA;&#xD;&#xA;Therefore, given a plane $N^TX = 0$ and a line determined by a pair of points $A$ and $B$, the unique intersection point of the line with the plane is calculated as&#xD;&#xA;$$P = - (N^TB)\, A + (N^TA)\, B$$ We us projective coordinates, because it may happen that one of the points on the line, say $B$ is &quot;at infinity&quot; with respect to our perferred choice of Cartesian coordinates. That means that &#xD;&#xA;$B = \begin{bmatrix}B_1\\B_2\\B_3\\0\end{bmatrix}$. In this case, the line is interpreted in Cartesian coordinates as the line passing through the 3D Cartesian point $A = \begin{bmatrix}\frac{A_1}{A_4}\\\frac{A_2}{A_4}\\\frac{A_3}{A_4}\end{bmatrix}$ and aligned with the 3D vector $\vec{V}_B = \begin{bmatrix}B_1\\B_2\\B_3\end{bmatrix}$.  &#xD;&#xA;&#xD;&#xA;In order to clip a line, you can go about it in two different ways, both of which can use the formula for the intersection between a line and a plane. You can find the (projective) equations of the planes of the frustum, intersect the 3d line with them and then project the points onto the screen, which is again intersection of a plane with lines passing through the origin. Alternatively, you can project the two points that determine the line onto the screen (again you can use the formula for the intersection of the line connecing the origin with any of the two points with the plane of the screen), which allows you to know the projection of the 3D line on the screen, and then find the intersection points of the projected line with the borders of the screen. Maybe the second scenario is simpler?&#xD;&#xA;&#xD;&#xA;The screen is parallel to the $x,\,y$ plane of the 3D Cartesian frame, while the $z$ axis is perpendicular to the screen and the screen is at a distance $l$ from the origin of the coordinate system. Therefore, the Cartesian equation of the plane of the screen is $z = l$. In projective coordinates, $z = \frac{X_3}{X_4}$, which means that $\frac{X_3}{X_4} = l$  so the projective equation is $X_3 = l\, X_4$ and can be also expressed as&#xD;&#xA;$$0 = X_3 - l\, X_4 = S^TX = \begin{bmatrix} 0 \,\,\, 0 \,\,\, 1 \,\, - l\end{bmatrix} \begin{bmatrix}X_1\\X_2\\X_3\\x_4\end{bmatrix} $$ where &#xD;&#xA;$S = \begin{bmatrix}0 \\ 0 \\ 1 \\ -l\end{bmatrix}$&#xD;&#xA;so if the 3D line is determined by the pair of points $A = \begin{bmatrix}A_1\\A_2\\A_3\\A_4\end{bmatrix} $ and $B = \begin{bmatrix}B_1\\B_2\\B_3\\B_4\end{bmatrix}$ Hence, with $O = \begin{bmatrix}0\\0\\0\\1\end{bmatrix}$, the projection of $A$ on the screen is&#xD;&#xA;$$\hat{A} =  - (S^TO)\, A + (S^TA)\, O = l\, A + (A_3-l\, A_4)\, O = \begin{bmatrix}l\,A_1\\l\,A_2\\l\,A_3\\l\,A_4\end{bmatrix} + \begin{bmatrix}0\\0\\0\\A_3-l\, A_4\end{bmatrix} = \begin{bmatrix}l\,A_1\\l\,A_2\\l\,A_3\\A_3\end{bmatrix}$$  and the projection of $B$ on the screen is $$\hat{B}= \begin{bmatrix}l\,B_1\\l\,B_2\\l\,B_3\\B_3\end{bmatrix}$$ So one can write this projection in  matrix form as follows:&#xD;&#xA;&#xD;&#xA;$$P_{scr} = - (S^TO)\, \text{Id} + O\,S^T$$&#xD;&#xA;because $P_{scr}A = \Big(- (S^TO)\, \text{Id} + O\,S^T\Big)\,A = - (S^TO)\,A + O\,(S^TA) = - (S^TO)\,A + (S^TA)\,O = \hat{A}$&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;P_{scr} &amp;= - (S^TO)\, \text{Id} + O\,S^T\\&#xD;&#xA;&amp;\\&#xD;&#xA;&amp;= - (-l)\begin{bmatrix}1 &amp; 0 &amp; 0 &amp; 0 \\0 &amp; 1 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 1 &amp; 0\\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix} + \begin{bmatrix}0\\0\\0\\1\end{bmatrix} &#xD;&#xA;\begin{bmatrix}0\,\,\, 0\,\,\, 1 \,\,\, - l\end{bmatrix}\\ &#xD;&#xA;&amp;\\&#xD;&#xA;&amp;= \begin{bmatrix}l &amp; 0 &amp; 0 &amp; 0 \\0 &amp; l &amp; 0 &amp; 0\\0 &amp; 0 &amp; l &amp; 0\\0 &amp; 0 &amp; 0 &amp; l\end{bmatrix} + \begin{bmatrix}0 &amp; 0 &amp; 0 &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 1 &amp; -l \end{bmatrix}\\&#xD;&#xA;&amp;\\&#xD;&#xA;&amp; = \begin{bmatrix}l &amp; 0 &amp; 0 &amp; 0\\0 &amp; l &amp; 0 &amp; 0\\0 &amp; 0 &amp; l &amp; 0\\0 &amp; 0 &amp; 1 &amp; 0\end{bmatrix}&#xD;&#xA;\end{align}&#xD;&#xA;And thus&#xD;&#xA;$$\hat{A} = P_{scr}\, A \,\, \text{ and } \,\, &#xD;&#xA;\hat{B} = P_{scr}\, B$$ &#xD;&#xA;When you have your points projected on the screen plane, you would like to get rid of the $z-$coordiante, so you need to remove the third (out of our) component of your projected points, i.e.:&#xD;&#xA;$\hat{A} = \begin{bmatrix}l\,A_1\\l\,A_2\\l\,A_3\\A_3\end{bmatrix} \mapsto \begin{bmatrix}l\,A_1\\l\,A_2\\A_3\end{bmatrix}$ so if you take the projection from four vectors to three vectors&#xD;&#xA;$$P_0 = \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0\\0 &amp; 1 &amp; 0 &amp; 0\\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}$$ and muptiply it by  $P_{scr}$ from the right as $P_0P_{scr}$, we can take the projective map from the projective three space to the projective plane of the screen&#xD;&#xA;$$P = P_0P_{scr} = \begin{bmatrix} l &amp; 0 &amp; 0 &amp; 0\\0 &amp; l &amp; 0 &amp; 0\\0 &amp; 0 &amp; 1 &amp; 0\end{bmatrix}$$ &#xD;&#xA;So, to recap, given  a line in projective three space, passing through the pair of points $A$ and $B$, their screen images, in projective coordinates of the screen, are&#xD;&#xA;$\hat{A} = P\, A$ and $\hat{B} =P \, B$. The formula for the intersection of a line with a plane in projective three space translates verbatim to the intersection of a line given by a pair of points $\hat{A}$ and $\hat{B}$ with another line given as an equation $N^T\hat{X} = 0$ in the projective plane, where $N = \begin{bmatrix} n_1\\n_2\\n_3\end{bmatrix}$, &#xD;&#xA;$$\hat{X}_N = (- N^T\hat{B})\hat{A} + (N^T\hat{A})\hat{B}$$ so &#xD;&#xA;alltogether &#xD;&#xA;$$\hat{X}_N = (- N^TP{B})\,P{A} + (N^TP{A})\,P{B}$$ So this is the formula for the projected points of intersection of the three dimensional line with the frustum's boundary. For example,  the right vertical boundary of the screen is given by an $N_{right\, vert} = \begin{bmatrix} w\\0\\0\end{bmatrix}$ and the bottom horizontal boundary of the screen is given by an $N_{bottom\, hor} = \begin{bmatrix} 0\\- h\\0\end{bmatrix}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="23862" PostHistoryTypeId="2" PostId="8795" RevisionGUID="bfc34cf0-e1f7-4342-8e98-c90c2f87a9b8" CreationDate="2019-04-25T12:52:49.957" UserId="10547" Text="In glsl, what is the difference between `isnan(x)` and `!(x == x)`?&#xD;&#xA;&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;_This question body does not meet our quality standards. Please make sure that it completely describes your problem - including what you have already tried - and is written using proper grammar._ I do not have a problem, I have a question. Hopefully this makes the question long enough." ContentLicense="CC BY-SA 4.0" />
  <row Id="23863" PostHistoryTypeId="1" PostId="8795" RevisionGUID="bfc34cf0-e1f7-4342-8e98-c90c2f87a9b8" CreationDate="2019-04-25T12:52:49.957" UserId="10547" Text="difference between isnan and comparison to self" ContentLicense="CC BY-SA 4.0" />
  <row Id="23864" PostHistoryTypeId="3" PostId="8795" RevisionGUID="bfc34cf0-e1f7-4342-8e98-c90c2f87a9b8" CreationDate="2019-04-25T12:52:49.957" UserId="10547" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23865" PostHistoryTypeId="2" PostId="8796" RevisionGUID="221919ee-975a-4667-ad7b-9abea763f1d2" CreationDate="2019-04-25T15:10:08.283" UserId="2654" Text="IEEE-754 defines the `isNaN` property, which determines if a value is NaN. However, it is also defined to be a non-signaling operation; calling `isNaN` on an sNaN will never result in a signaled failure. By contrast, equality testing may signal when given sNaN values.&#xD;&#xA;&#xD;&#xA;Now, GLSL explicitly states that signaling doesn't matter:&#xD;&#xA;&#xD;&#xA;&gt; Support for signaling NaNs is not required and exceptions are never raised.&#xD;&#xA;&#xD;&#xA;But of course, there's also the fact that `isnan` is a vector function, while `!(x == x)` only works on scalars. So if you want to test if any of the elements of a `vec3` are NaN, you can do `any(isnan(some_vec))`, while the equality-testing equivalent would be even more obtuse and verbose: `any(not(equal(some_vec, some_vec)))`.&#xD;&#xA;&#xD;&#xA;And all of that ignores the simple usability reasons for having `isnan`. `!(x == x)` is an idiom which must be learned, while `isnan` is an easily looked up function whose name tells you want it does. After all, most users of floats tend to forget about NaN, so such an expression seems like a tautology, while &quot;isnan&quot; explicitly reminds such people that NaNs are a real thing and they are now about to enter code that remembers that fact.&#xD;&#xA;&#xD;&#xA;Also, as previously stated, `isNaN` is a property defined by IEEE-754. It is also a function provided by the standard libraries of C99, C++11, Java, C#, Swift, Go, JavaScript, and I can keep going, but I think my point is clear." ContentLicense="CC BY-SA 4.0" />
  <row Id="23869" PostHistoryTypeId="2" PostId="8798" RevisionGUID="b7dbd01b-6265-4801-9743-e28d30d6df69" CreationDate="2019-04-26T05:05:03.950" UserId="10552" Text="If you plan to build 3d wireframe or mesh from the slice images, you can consider to use marching cube method - as someone mentioned already in the answer, ITK/VTK can provide the pointer to start with." ContentLicense="CC BY-SA 4.0" />
  <row Id="23870" PostHistoryTypeId="2" PostId="8799" RevisionGUID="3701854f-534f-416c-badb-9c52d40f7647" CreationDate="2019-04-26T05:08:35.027" UserId="10552" Text="I just answered the question: https://computergraphics.stackexchange.com/questions/4919/how-to-build-a-3d-model-from-2d-pictures/8798#8798&#xD;&#xA;&#xD;&#xA;and the answer is applicable here. In short, to build wiremesh from the 2d slice, you can take a look marching cube method. In this case you need to assume (or provide) the thickness of each pixel (hence a voxel) so that the MC algorithm can work.&#xD;&#xA;ITK/VTK should have some implementation for that.&#xD;&#xA;&#xD;&#xA;The term could be called: 3d mesh reconstruction from volumetric data" ContentLicense="CC BY-SA 4.0" />
  <row Id="23873" PostHistoryTypeId="5" PostId="8795" RevisionGUID="752744cd-5bfa-4f5b-a25e-2586072a8f36" CreationDate="2019-04-26T13:51:30.167" UserId="6" Comment="deleted 297 characters in body; edited title" Text="In GLSL, what is the difference between `isnan(x)` and `!(x == x)`?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23874" PostHistoryTypeId="4" PostId="8795" RevisionGUID="752744cd-5bfa-4f5b-a25e-2586072a8f36" CreationDate="2019-04-26T13:51:30.167" UserId="6" Comment="deleted 297 characters in body; edited title" Text="Difference between isnan and comparison to self" ContentLicense="CC BY-SA 4.0" />
  <row Id="23875" PostHistoryTypeId="33" PostId="8771" RevisionGUID="8bd93602-af52-4312-a1a8-f8dff49a7be0" CreationDate="2019-04-27T00:19:13.893" UserId="228" Comment="54" />
  <row Id="23879" PostHistoryTypeId="2" PostId="8803" RevisionGUID="f49ba854-ee22-4a78-8f55-fb9d3f680404" CreationDate="2019-04-27T08:25:19.537" UserId="7868" Text="Will unaccessed bindings consume cache or bandwidth? I want to improve cache usage by splitting the per-path information in my renderer across different resources, but I also want to keep my binding model simple by having every resource I might need declared in a single .hlsli included at the top of each shader file. I'm concerned that the GPU might try to load part of each resource, even if a particular shader doesn't access it - is that reasonable? Should I prefer more descriptor heaps and fewer resources/shader instead?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23880" PostHistoryTypeId="1" PostId="8803" RevisionGUID="f49ba854-ee22-4a78-8f55-fb9d3f680404" CreationDate="2019-04-27T08:25:19.537" UserId="7868" Text="Should I use common resource bindings across all my shaders in HLSL/D3D12?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23881" PostHistoryTypeId="3" PostId="8803" RevisionGUID="f49ba854-ee22-4a78-8f55-fb9d3f680404" CreationDate="2019-04-27T08:25:19.537" UserId="7868" Text="|gpu|hlsl|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23886" PostHistoryTypeId="50" PostId="7997" RevisionGUID="5f52293c-126d-49a6-99f8-675885e4fabd" CreationDate="2019-04-28T10:01:10.167" UserId="-1" />
  <row Id="23887" PostHistoryTypeId="2" PostId="8805" RevisionGUID="5441ecd4-8b7a-49c6-b212-ef66f880e304" CreationDate="2019-04-28T19:33:38.567" UserId="10565" Text="I am relatively new to path tracing, and I am trying to implement next event estimation. I am following the Monte Carlo integral used to compute the direct illumination from an area light:&#xD;&#xA;&#xD;&#xA;$$\frac{1}{N}\sum\limits_{i=1}^{N}f_r(p,\omega_o,\omega_i)L_i(p,\omega_i)Vis(p \leftrightarrow p')cos\theta_i\frac{A_Lcos\theta_o}{||p-p'||^2}$$&#xD;&#xA;&#xD;&#xA;(where $p$ is the surface intersection point, $A_L$ is the area of the light, $p'$ is a random point on the surface of the light (uniformly distributed), and $Vis$ returns 1 only if $p$ and $p'$ are mutually visible).&#xD;&#xA;&#xD;&#xA;However, I would like to support transformed area lights, that is, lights which have their own model coordinate space separate from the world space (for example, a stretched and rotated sphere).&#xD;&#xA;&#xD;&#xA;Samples can easily be generated uniformly in model space (since in model space this light is just a sphere), but obviously then the samples are not uniformly distributed in world space. Does this formula need to be modified to account for the samples being generated uniformly in model space, and what parts need to be computed in model space vs. world space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23888" PostHistoryTypeId="1" PostId="8805" RevisionGUID="5441ecd4-8b7a-49c6-b212-ef66f880e304" CreationDate="2019-04-28T19:33:38.567" UserId="10565" Text="How does Next Event Estimation work with transformed lights?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23889" PostHistoryTypeId="3" PostId="8805" RevisionGUID="5441ecd4-8b7a-49c6-b212-ef66f880e304" CreationDate="2019-04-28T19:33:38.567" UserId="10565" Text="|rendering|pathtracing|lighting|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23890" PostHistoryTypeId="2" PostId="8806" RevisionGUID="094ff63f-195e-451f-b3c7-173a8b6b0558" CreationDate="2019-04-28T20:22:53.117" UserId="10564" Text="I am solving the task that is as follows:&#xD;&#xA;&#xD;&#xA;**Input:** a polygon. Can be any kind of polygon without self intersections. Can be a non-convex and with holes inside.&#xD;&#xA;&#xD;&#xA;**Goal:** to cover it with 2 (at least) or more parallelograms that together are equal to or contain the whole polygon. There is no point of the polygon that lies beyond parallelograms. The amount of the parallelograms should be the least possible and the square of the parallelograms should be the least possible.&#xD;&#xA;&#xD;&#xA;**Question:** Is this task solved and if it is solved - how? I am looking for a direction where to start with and what related algorithms/theory to learn." ContentLicense="CC BY-SA 4.0" />
  <row Id="23891" PostHistoryTypeId="1" PostId="8806" RevisionGUID="094ff63f-195e-451f-b3c7-173a8b6b0558" CreationDate="2019-04-28T20:22:53.117" UserId="10564" Text="Cover a polygon with least amount of parallelograms" ContentLicense="CC BY-SA 4.0" />
  <row Id="23892" PostHistoryTypeId="3" PostId="8806" RevisionGUID="094ff63f-195e-451f-b3c7-173a8b6b0558" CreationDate="2019-04-28T20:22:53.117" UserId="10564" Text="|computational-geometry|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23894" PostHistoryTypeId="2" PostId="8807" RevisionGUID="d1433d69-666e-42c0-9667-c902d51ed752" CreationDate="2019-04-29T01:36:46.940" UserId="10567" Text="I'm making a lattice based volume FFD and I'm having trouble with gaps in my data resulting from doing a typical deformer. I think I need to go through the voxels in the deformed lattice and then find the corresponding undeformed coordinate, that is, go from having the deformed position to getting the local (s,t,u) coordinate that was deformed to that position and then write the interpolated value of the original voxel. This is obviously the opposite way of doing a lattice based FFD with vector valued trivariate Bernstein polynomials.&#xD;&#xA;&#xD;&#xA;I am struggling to figure out a way to get the local coordinates of a point in the deformed volume. If anyone has any advice it would be much appreciated.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="23895" PostHistoryTypeId="1" PostId="8807" RevisionGUID="d1433d69-666e-42c0-9667-c902d51ed752" CreationDate="2019-04-29T01:36:46.940" UserId="10567" Text="Local Coordinates of Deformed Lattice" ContentLicense="CC BY-SA 4.0" />
  <row Id="23896" PostHistoryTypeId="3" PostId="8807" RevisionGUID="d1433d69-666e-42c0-9667-c902d51ed752" CreationDate="2019-04-29T01:36:46.940" UserId="10567" Text="|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23897" PostHistoryTypeId="2" PostId="8808" RevisionGUID="68935374-687e-4564-805c-0b25237be639" CreationDate="2019-04-29T03:26:05.190" UserId="6588" Text="Sampling is typically done in local coordinates first and *then* mapped to world space. You don't have to change the formula for this, but $\mathbf{p}'$ needs to be in world space when you compute the solid-angle-to-area Jacobian determinant. For a sphere for instance, you would have a warping function that maps two canonical uniform random numbers to a 3D point on the unit sphere. Only then would you apply the local-to-world matrix on this sample. If this matrix is a rigid motion (e.g. a combination of translations and/or rotations) with a possible scaling factor, then your samples will remain uniformly distributed in world space. However, if you apply a mapping that distorts areas (e.g. stretching), this will not be the case. It technically still &quot;works&quot; for sampling but some regions of your sphere can be overrepresented. You would have to implement an area-preserving sampling mechanism taking into account this stretching factor.&#xD;&#xA;&#xD;&#xA;In practice, it's better to stick with rigid transformations and avoid non area-preserving mappings for analytical shapes. If you truly wish to sample a stretched sphere uniformly, your best bet would be to use an ellipsoid mesh. Then you could sample by area by first choosing a triangle proportional to its area and then picking a point on it by barycentric interpolation. In fact, this is what people have to do to sample area lights of arbitrary shapes.&#xD;&#xA;&#xD;&#xA;There is a small discussion at the end [pbrt](http://www.pbr-book.org/3ed-2018/Retrospective_and_The_Future/Design_Retrospective.html#TrianglesOnly) that addresses the possibility of removing analytical shapes from a rendering engine. Analytical geometry primitives are fun because they can teach you stuff like subtended solid angle sampling when you learn GI and importance sampling, but they are limited and your question highlights one such limitation." ContentLicense="CC BY-SA 4.0" />
  <row Id="23898" PostHistoryTypeId="50" PostId="2146" RevisionGUID="6c161dd3-716d-4311-8762-844b77576982" CreationDate="2019-04-29T05:01:20.223" UserId="-1" />
  <row Id="23899" PostHistoryTypeId="2" PostId="8809" RevisionGUID="8dcb02cf-160e-4f4c-b5ed-d86b790516c0" CreationDate="2019-04-29T09:01:39.747" UserId="10568" Text="I am asking this question purely our of curiosity. I do not look for step-by-step tutorial on how to manipulate a photo and making sure that it will be hard to detect it.&#xD;&#xA;&#xD;&#xA;I was wondering, because tools like http://fotoforensics.com/ make it easy to detect modifications of photographs in software like Photoshop. I can see that it is based on things like Error Level Analysis. Is there a way to modify a photo but &quot;cover the tracks&quot; so there will be no easy way of detecting modifications by &quot;ELA&quot; or other metods? Is it hard, easy to do? Is it widely used?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23900" PostHistoryTypeId="1" PostId="8809" RevisionGUID="8dcb02cf-160e-4f4c-b5ed-d86b790516c0" CreationDate="2019-04-29T09:01:39.747" UserId="10568" Text="Are there some methods of preventing tools like FotoForensics from detecting manipulations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23901" PostHistoryTypeId="3" PostId="8809" RevisionGUID="8dcb02cf-160e-4f4c-b5ed-d86b790516c0" CreationDate="2019-04-29T09:01:39.747" UserId="10568" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23902" PostHistoryTypeId="50" PostId="8701" RevisionGUID="a5b31454-fe1d-49b8-bb5a-5daa920a3ff1" CreationDate="2019-04-29T09:03:41.057" UserId="-1" />
  <row Id="23908" PostHistoryTypeId="5" PostId="8806" RevisionGUID="775394fd-e115-4ead-bb04-fdc0f0c2e493" CreationDate="2019-04-30T07:50:38.313" UserId="10564" Comment="added 116 characters in body" Text="I am solving the task that is as follows:&#xD;&#xA;&#xD;&#xA;**Input:** a polygon. Can be any kind of polygon without self intersections. Can be a non-convex and with holes inside.&#xD;&#xA;&#xD;&#xA;**Goal:** to cover it with 2 (at least) or more parallelograms that together are equal to or contain the whole polygon. The following criteria should be met:&#xD;&#xA;&#xD;&#xA; - There is no point of the polygon that lies beyond parallelograms.&#xD;&#xA; - The number of the parallelograms should be the least possible. I.e. we want to find largest parallelograms that cover the polygon.&#xD;&#xA; - These parallelograms must not intersect within the polygon.&#xD;&#xA;&#xD;&#xA;**Question:** Is this task solved and if it is solved - how? I am looking for a direction where to start with and what related algorithms/theory to learn.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23909" PostHistoryTypeId="2" PostId="8811" RevisionGUID="a86475f9-1a30-44aa-8536-ccac94d5f977" CreationDate="2019-04-30T17:31:05.780" UserId="10578" Text="I'm trying to optimize a geometry pass for a game using dx11 and deferred rendering. (All test are performed on Nvidia GTX 1060 at fixed clock rate)&#xD;&#xA;&#xD;&#xA;After profiling with NSight it seems to have very bad utilization of GPU.&#xD;&#xA;**With the top SOL% being SM:36%** &#xD;&#xA;&#xD;&#xA;[![NSight Capture with texture sampling][1]][1]&#xD;&#xA;&#xD;&#xA;I decided to investigate and tried to remove all texture sampling and have a pass that would only write constants to the GBuffer and obtain a very different profiling in NSight but not much difference in timing.&#xD;&#xA;I would have expected much more throughput for a shader that basically writes constants.&#xD;&#xA;&#xD;&#xA;[![NSight Capture without any texture sampling][2]][2]&#xD;&#xA;&#xD;&#xA;I tried to reduce the GBuffer layout which was originally (FP16 + 2x ARGB32, ARGB32) to 3x ARGB32 with absolutely no difference.&#xD;&#xA;&#xD;&#xA;So I'd like to know if somebody has an idea what could be done to improve this pass. Especially if I could be missing something that slows down.&#xD;&#xA;&#xD;&#xA;More precise question: **WHAT THE HELL IS Stall Short Scoreboard ???** &#xD;&#xA;The only info I found about this counter was that&#xD;&#xA;&gt; Warp was stalled waiting for a scoreboard dependency on a&#xD;&#xA;MIO (memory input/output) operation&#xD;&#xA;&#xD;&#xA;But I don't understand how I could reduce it. &#xD;&#xA;Thanks in advance for any help. Hit me if you need any info that could be useful.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AHpxo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tb0N4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23910" PostHistoryTypeId="1" PostId="8811" RevisionGUID="a86475f9-1a30-44aa-8536-ccac94d5f977" CreationDate="2019-04-30T17:31:05.780" UserId="10578" Text="Optimisation of Geometry Pass" ContentLicense="CC BY-SA 4.0" />
  <row Id="23911" PostHistoryTypeId="3" PostId="8811" RevisionGUID="a86475f9-1a30-44aa-8536-ccac94d5f977" CreationDate="2019-04-30T17:31:05.780" UserId="10578" Text="|rendering|directx11|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23912" PostHistoryTypeId="50" PostId="8321" RevisionGUID="c02ce04a-83e5-422d-bf79-dd2f7859e974" CreationDate="2019-05-01T03:02:55.457" UserId="-1" />
  <row Id="23913" PostHistoryTypeId="50" PostId="6359" RevisionGUID="de21fc9c-0a77-4847-8854-1fb81cdc646b" CreationDate="2019-05-01T05:01:10.223" UserId="-1" />
  <row Id="23914" PostHistoryTypeId="50" PostId="8296" RevisionGUID="e50f4f74-258a-4486-97d8-996b6e208aae" CreationDate="2019-05-01T07:03:00.840" UserId="-1" />
  <row Id="23915" PostHistoryTypeId="5" PostId="8793" RevisionGUID="9aba8a1c-0316-495f-9b45-5ee8a86eab6a" CreationDate="2019-05-01T08:25:43.890" UserId="10515" Comment="added 18 characters in body" Text="The context of this question is correct dithering of color with gamma correction. In dithering we add (shaped) noise $n$ to a signal $s \in [0, 1]$ based on a random variable $r \in [0, 1]$&#xD;&#xA;&#xD;&#xA;$$s' = s + n(s, r)$$&#xD;&#xA;&#xD;&#xA;such that when we quantize the signal to $m$ steps the rounding will end up distorting the signal less.&#xD;&#xA;&#xD;&#xA;I already have a function that works in a linear world from [here](https://computergraphics.stackexchange.com/questions/5904/whats-a-proper-way-to-clamp-dither-noise/8777#8777), where $n$ is a symmetric triangular distribution on $[-1, 1]$ (with the caveat that for $s$ close to $0$ or $1$ we switch to a uniform distribution on $[-\frac{1}{2}, \frac{1}{2}]$), as it has mean $0$ and appropriately smoothes out the rounding (demo that incorrectly ignores gamma: https://www.shadertoy.com/view/Wts3zH).&#xD;&#xA;&#xD;&#xA;However in sRGB files we have to deal with gamma. Essentially we have an invertable transform $t$ (often $t(x) = x^{2.4}$) that is applied before/after quantization to allocate more steps to lower intensities.&#xD;&#xA;&#xD;&#xA;This means that the average color when viewing is no longer (ignoring quantization for now):&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(s + n(s, r)\right)\text{d}r = s$$&#xD;&#xA;&#xD;&#xA;But is instead:&#xD;&#xA;&#xD;&#xA;$$\int_0^1 t^{-1}\left(s + n(s, r)\right)\text{d}r &gt; s$$&#xD;&#xA;&#xD;&#xA;How can we change our noise function $n$ so that the average color is again $s$ after dithering, while maintaining our properties from the triangular distribution as much as possible?&#xD;&#xA;&#xD;&#xA;If you want to give a shot, here is a demo that can show you the error from dithering, which has gamma correction: https://www.shadertoy.com/view/3tf3Dn." ContentLicense="CC BY-SA 4.0" />
  <row Id="23916" PostHistoryTypeId="5" PostId="8793" RevisionGUID="76f2f7ac-7197-4927-8aaa-7b91bd646114" CreationDate="2019-05-01T08:34:37.017" UserId="10515" Comment="added 269 characters in body" Text="The context of this question is correct dithering of color with gamma correction. In dithering we add (shaped) noise $n$ to a signal $s \in [0, 1]$ based on a random variable $r \in [0, 1]$&#xD;&#xA;&#xD;&#xA;$$s' = s + n(s, r)$$&#xD;&#xA;&#xD;&#xA;such that when we quantize the signal to $m$ steps the rounding will end up distorting the signal less.&#xD;&#xA;&#xD;&#xA;I already have a function that works in a linear world from [here](https://computergraphics.stackexchange.com/questions/5904/whats-a-proper-way-to-clamp-dither-noise/8777#8777), where $n$ is a symmetric triangular distribution on $[-1, 1]$ (with the caveat that for $s$ close to $0$ or $1$ we switch to a uniform distribution on $[-\frac{1}{2}, \frac{1}{2}]$), as it has mean $0$ and appropriately smoothes out the rounding (demo that incorrectly ignores gamma: https://www.shadertoy.com/view/Wts3zH).&#xD;&#xA;&#xD;&#xA;However in sRGB files we have to deal with gamma. Essentially we have an invertable transform $t$ (often $t(x) = x^{2.4}$) that is applied before/after quantization to allocate more steps to lower intensities.&#xD;&#xA;&#xD;&#xA;This means that the average color when viewing is no longer (ignoring quantization for now):&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(s + n(s, r)\right)\text{d}r = s$$&#xD;&#xA;&#xD;&#xA;But is instead:&#xD;&#xA;&#xD;&#xA;$$\int_0^1 t^{-1}\left(s + n(s, r)\right)\text{d}r &gt; s$$&#xD;&#xA;&#xD;&#xA;How can we change our noise function $n$ so that the average color is again $s$ after dithering, while maintaining our properties from the triangular distribution as much as possible?&#xD;&#xA;&#xD;&#xA;For the record, the main property the triangular distribution gives is that the variance after rounding becomes constant:&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(\left[(s + n(s, r))(m-1)\right]/(m-1) - s\right)^2\text{d}r = c$$&#xD;&#xA;&#xD;&#xA;Where $[x]$ denotes $x$ rounded to the closest integer.&#xD;&#xA;&#xD;&#xA;If you want to give a shot, here is a demo that can show you the error from dithering, which has gamma correction: https://www.shadertoy.com/view/3tf3Dn." ContentLicense="CC BY-SA 4.0" />
  <row Id="23917" PostHistoryTypeId="5" PostId="8793" RevisionGUID="d79eacba-ade9-4504-af5c-acdab325d4ac" CreationDate="2019-05-01T10:04:35.337" UserId="10515" Comment="added 286 characters in body" Text="The context of this question is correct dithering of color with gamma correction. In dithering we add (shaped) noise $n$ to a signal $s \in [0, 1]$ based on a random variable $r \in [0, 1]$&#xD;&#xA;&#xD;&#xA;$$s' = s + n(s, r)$$&#xD;&#xA;&#xD;&#xA;such that when we quantize the signal to $m$ steps the rounding will end up distorting the signal less.&#xD;&#xA;&#xD;&#xA;I already have a function that works in a linear world from [here](https://computergraphics.stackexchange.com/questions/5904/whats-a-proper-way-to-clamp-dither-noise/8777#8777), where $n$ is a symmetric triangular distribution on $[-1, 1]$ (with the caveat that for $s$ close to $0$ or $1$ we switch to a uniform distribution on $[-\frac{1}{2}, \frac{1}{2}]$), as it has mean $0$ and appropriately smoothes out the rounding (demo that incorrectly ignores gamma: https://www.shadertoy.com/view/Wts3zH). This function written out is (matching top to bottom in priority for the cases):&#xD;&#xA;&#xD;&#xA;$$n(s, r) \cdot (m - 1) = \begin{cases}&#xD;&#xA;r - \frac{1}{2}&amp;s \leq \frac{1}{2(m-1)} \vee s \geq 1-\frac{1}{2(m-1)}\\&#xD;&#xA;\sqrt{2r} - 1&amp;r &lt; \frac{1}{2}\\&#xD;&#xA;1 - \sqrt{2 - 2r}&amp;r \geq \frac{1}{2}\\&#xD;&#xA;\end{cases}$$&#xD;&#xA;&#xD;&#xA;However in sRGB files we have to deal with gamma. Essentially we have an invertable transform $t$ (often $t(x) = x^{2.4}$) that is applied before/after quantization to allocate more steps to lower intensities.&#xD;&#xA;&#xD;&#xA;This means that the average color when viewing is no longer (ignoring quantization for now):&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(s + n(s, r)\right)\text{d}r = s$$&#xD;&#xA;&#xD;&#xA;But is instead:&#xD;&#xA;&#xD;&#xA;$$\int_0^1 t^{-1}\left(s + n(s, r)\right)\text{d}r &gt; s$$&#xD;&#xA;&#xD;&#xA;How can we change our noise function $n$ so that the average color is again $s$ after dithering, while maintaining our properties from the triangular distribution as much as possible?&#xD;&#xA;&#xD;&#xA;For the record, the main property the triangular distribution gives is that the variance after rounding becomes constant:&#xD;&#xA;&#xD;&#xA;$$\int_0^1\left(\left[(s + n(s, r))(m-1)\right]/(m-1) - s\right)^2\text{d}r = c$$&#xD;&#xA;&#xD;&#xA;Where $[x]$ denotes $x$ rounded to the closest integer. Note that this only holds in the triangular part of the domain of $n$, so when $\frac{1}{2(m-1)} \leq s \leq 1-\frac{1}{2(m-1)}$.&#xD;&#xA;&#xD;&#xA;If you want to give a shot, here is a demo that can show you the error from dithering, which has gamma correction: https://www.shadertoy.com/view/3tf3Dn." ContentLicense="CC BY-SA 4.0" />
  <row Id="23918" PostHistoryTypeId="2" PostId="8812" RevisionGUID="25226618-d307-42dd-9459-78c32b8c8c0e" CreationDate="2019-05-01T11:13:53.913" UserId="10580" Text="Right Click on the viewport PERSPECTIVE and enable viewport Clipping.&#xD;&#xA;On the right of the screen, 2 yellow arrows will appear. Drag the bottom arrow up a little. Worked for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="23919" PostHistoryTypeId="50" PostId="8695" RevisionGUID="da6af9ad-f1c2-4a81-aa34-30edfbc2f425" CreationDate="2019-05-01T16:01:35.273" UserId="-1" />
  <row Id="23920" PostHistoryTypeId="2" PostId="8813" RevisionGUID="5fccf872-1785-4f78-923d-fbe1b2da22ea" CreationDate="2019-05-01T22:39:54.980" UserId="8851" Text="Maybe something quick (to set up, no guarantees of actual speed) and dirty. &#xD;&#xA;&#xD;&#xA;Whatever your method was, it probably boiled down to a vector function &#xD;&#xA;\begin{align}&#xD;&#xA;\begin{bmatrix} x,\, y,\, z\end{bmatrix} = F\Big([s,\, t,\, u] \,\, \Big| \,\, V_{ijk} \, : i,j,k = 1..N\Big)&#xD;&#xA;\end{align}  where $V_{ijk} \in \mathbb{R}^3$are the vertices of the three dimensional lattice.&#xD;&#xA;&#xD;&#xA;Basically, you currently have the new coordinates $[x,\, y,\, z]$ of a point, and you want to find the original ones $[s,\, t,\, u]$. I hope you still have the coordinates of the lattice vertices $V_{ijk}$. To retrieve the initial coordinates $[s,\, t,\, u]$ you have to solve for $[s,\, t,\, u]$ the system of equations&#xD;&#xA;\begin{align}&#xD;&#xA;\begin{bmatrix} x,\, y,\, z\end{bmatrix} = F\Big([s,\, t,\, u] \,\, \Big| \,\, V_{ijk} \, : i,j,k = 1..N\Big)&#xD;&#xA;\end{align} where $[x,\, y,\, z]$ is given and the points $V_{ijk}$ are given &#xD;&#xA;For simplicity, I am going to write &#xD;&#xA;$$\begin{bmatrix} x,\, y,\, z\end{bmatrix} = F\big([s,\, t,\, u] \,\, \big| \,\, V \,\big)$$&#xD;&#xA;To solve it, use a type of Newton's method.&#xD;&#xA;Set a small enough number $h$. &#xD;&#xA;&#xD;&#xA;Set your initial $s_0=x, t_0=y, u_0=z$ and set up your error equal to $err = 1$ (or whatever).&#xD;&#xA;&#xD;&#xA;While $err \geq h^2$ execute the following iteration:&#xD;&#xA;&#xD;&#xA;1. Assume you have a current approximation $[s_n,\, t_n,\, u_n]$;&#xD;&#xA;&#xD;&#xA;2. Calculate the following three three-vector (as rows) &#xD;&#xA;\begin{align}&#xD;&#xA;&amp;\Delta_s F_n = \frac{1}{h} \Big( \, F\big([s_n+h,\, t_n,\, u_n] \,\, \big| \,\, V \,\big) - F\big([s_n,\, t_n,\, u_n] \,\, \Big| \,\, V \,\big) \, \Big)\\&#xD;&#xA;&amp;\Delta_t F_n = \frac{1}{h} \Big( \, F\big([s_n,\, t_n+h,\, u_n] \,\, \big| \,\, V \,\big) - F\big([s_n,\, t_n,\, u_n] \,\, \Big| \,\, V \,\big) \, \Big)\\&#xD;&#xA;&amp;\Delta_u F_n = \frac{1}{h} \Big( \, F\big([s_n,\, t_n,\, u_n+h] \,\, \big| \,\, V \,\big) - F\big([s_n,\, t_n,\, u_n] \,\, \Big| \,\, V \,\big) \, \Big)&#xD;&#xA;\end{align}   &#xD;&#xA;&#xD;&#xA;3. Set the following three by three matrix &#xD;&#xA;$$M_n = \begin{bmatrix} \Delta_s F_n \\  \Delta_t F_n \\ &#xD;&#xA;   \Delta_u F_n\end{bmatrix}$$ (the vectors are the ones computed above but transposed and are therefore vector-columns);&#xD;&#xA;&#xD;&#xA;4. Calculate the inverse matrix $M_n^{-1}$;&#xD;&#xA;&#xD;&#xA;5. Calculate the update&#xD;&#xA;$$[s_{n+1},\, t_{n+1},\, u_{n+1}] = [s_n,\, t_n,\, u_n] + \Big(\,[x,\, y,\, z] - F\big([s_n,\, t_n,\, u_n] \,\, \Big| \,\, V \,\big)\,\Big)\, M_n^{-1}$$ &#xD;&#xA;(all of this is written as vector matrix multiplication, where you are working with $1 \times 3$ row-vectors and multiplying such$1 \times 3$ row-vectors with the $3 \times 3$ matrix $M_n^{-1}$ on the right)&#xD;&#xA;&#xD;&#xA;6. Calculate the error $$err = \Big\|\, [x,\, y,\, z] - F\big([s_{n+1},\, t_{n+1},\, u_{n+1}] \,\, \Big| \,\, V \,\big)\, \Big\|^2$$&#xD;&#xA;&#xD;&#xA;7. Go back to the beginning of the iteration to check whether $err \geq h^2$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result of this iteration is an approximation of the coordinates $[s,\, t,\, u]$. I hope this works. " ContentLicense="CC BY-SA 4.0" />
  <row Id="23922" PostHistoryTypeId="2" PostId="8815" RevisionGUID="047a35a3-71bc-4dc8-85dd-cfe454f99365" CreationDate="2019-05-02T12:07:21.657" UserId="10590" Text="I am implementing my own simple ray tracing and I came across some sort of confusion. When defining the verticies in the world I multiply them by the modelView transformation system (the matrix similar to the one generated by glm::lookAt function) in order to transform them to the camera coordinate. However, the verticies are invisible in the world when I do this transformation. My question is: are we supposed to transform the veriticies in Ray tracing with the model view transformation matrix as we do in OpenGL ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23923" PostHistoryTypeId="1" PostId="8815" RevisionGUID="047a35a3-71bc-4dc8-85dd-cfe454f99365" CreationDate="2019-05-02T12:07:21.657" UserId="10590" Text="Camera look at transformation in Ray Tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="23924" PostHistoryTypeId="3" PostId="8815" RevisionGUID="047a35a3-71bc-4dc8-85dd-cfe454f99365" CreationDate="2019-05-02T12:07:21.657" UserId="10590" Text="|raytracing|transformations|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23925" PostHistoryTypeId="4" PostId="8815" RevisionGUID="519690b1-245d-4d9e-9673-f3b8905dd199" CreationDate="2019-05-02T12:21:44.030" UserId="10590" Comment="edited title" Text="Camera Model View transformation in Ray Tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="23926" PostHistoryTypeId="4" PostId="8437" RevisionGUID="98d62537-c343-4878-868c-f38c72f15544" CreationDate="2019-05-03T00:04:09.890" UserId="5846" Comment="edited title" Text="Why does some text on my laptop have only gray-scale pixels while other text has color pixels?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23927" PostHistoryTypeId="50" PostId="5697" RevisionGUID="13e4a8ff-19ad-43c4-a23d-dcc0e256cd5e" CreationDate="2019-05-03T02:01:26.980" UserId="-1" />
  <row Id="23931" PostHistoryTypeId="2" PostId="8817" RevisionGUID="f25c953d-ecb5-4b5e-807e-fd29cf227dbb" CreationDate="2019-05-03T13:34:16.350" UserId="4768" Text="The space at which you transform your vertices is completely up to you, because it depends on what algorithms and kind of effects that you are trying to achieve.&#xD;&#xA;&#xD;&#xA;As of my personal experience, I usually shoot rays in world space because eventually we all need some sort of &quot;world-space&quot; acceleration data structure, such as a space-partition tree, that gathers all objects into a single space. As this data structure is probably going to be pre-computed for static objects, world space seems to be the most preferred one, as the vertices representation never change when you move the camera around. &#xD;&#xA;&#xD;&#xA;When it comes the time to actually test the ray-object intersection, I transform the ray direction onto object space by using the inverse of the model matrix. This makes it possible for all intersection tests to be implemented as if the object were axis-aligned. Thus, you can easily use AABBs (axis-aligned bounding boxes) for coarse intersection testing, even when your models are rotated in world space. This is also a good optimisation for dynamic objects, as the AABB does not change in object space." ContentLicense="CC BY-SA 4.0" />
  <row Id="23932" PostHistoryTypeId="2" PostId="8818" RevisionGUID="398b5553-9c80-4170-a2d3-0cca770e6ecf" CreationDate="2019-05-03T14:01:49.637" UserId="4768" Text="Describing a full CSG algorithm in a forum post is something really hard, and probably you will not find a complete answer to what you are asking here, but I can give you some suggestions.&#xD;&#xA;&#xD;&#xA;First of all, CSG on polygon meshes is not usually employed on real-time graphics, because the algorithms are still considered to be too much resource-intensive. If you are looking for these kinds of algorithms, I would suggest reading books on computational geometry, of which Mark De Berg's is commonly considered a good introduction to the topic. If you are planning to pre-compute everything, then classic CSG algorithms are the way to go.&#xD;&#xA;&#xD;&#xA;However, for just adding craters on a field, CSG seems to be too much overkill to me, and I would suggest some completely different approaches. If you want just a visual result (i.e., your player won't be able to go into the crater), you could use techniques such as z-buffer carving or parallax occlusion mapping, combined with some sort of decal system (preferably, using some deferred-like rendering system). Otherwise, if you need proper collision detection, you will actually need to change your mesh. You can easily apply some vertex modification operators around the center of each crater, such as pushing them down according to a radial-basis function (i.e., spheres, gaussians, etc). For realtime graphics, I would suggest using compute shaders or vertex feedback transforms.&#xD;&#xA;&#xD;&#xA;I'm sorry for not being too descriptive, but I hope that some of the keywords that I have put here may help you out on finding a solution to your problem.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23933" PostHistoryTypeId="5" PostId="8818" RevisionGUID="056736a4-73d8-42f5-9fa4-e19cdc5cbb26" CreationDate="2019-05-03T14:07:56.703" UserId="4768" Comment="added 62 characters in body" Text="Describing a full CSG algorithm in a forum post is something really hard, and probably you will not find a complete answer to what you are asking here, but I can give you some suggestions.&#xD;&#xA;&#xD;&#xA;First of all, CSG on polygon meshes is not usually employed on real-time graphics, because the algorithms are still considered to be too much resource-intensive. If you are looking for these kinds of algorithms, I would suggest reading books on computational geometry, of which Mark De Berg's is commonly considered a good introduction to the topic. If you are planning to pre-compute everything, then classic CSG algorithms are the way to go.&#xD;&#xA;&#xD;&#xA;However, for just adding craters on a field, CSG seems to be too much overkill to me, and I would suggest some completely different approaches. If you want just a visual result (i.e., your player won't be able to go into the crater), you could use techniques such as z-buffer carving or parallax occlusion mapping, combined with some sort of decal system (preferably, using some deferred-like rendering system). Otherwise, if you need proper collision detection, you will actually need to change your mesh. You can easily apply some vertex modification operators around the center of each crater, such as pushing them down according to a radial-basis function (i.e., spheres, gaussians, etc). To accomplish this in realtime graphics, I would suggest using compute shaders or vertex feedback transforms, instead of computing everything in the CPU. These techniques will even allow you to add craters dynamically. Think of some really nice meteor strikes taking place.&#xD;&#xA;&#xD;&#xA;I'm sorry for not being too descriptive, but I hope that some of the keywords that I have put here may help you out on finding a solution to your problem.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23937" PostHistoryTypeId="50" PostId="8359" RevisionGUID="403b8ce4-8bf2-4012-bfa2-cdc9e496d038" CreationDate="2019-05-03T20:00:55.997" UserId="-1" />
  <row Id="23938" PostHistoryTypeId="50" PostId="8721" RevisionGUID="cf3eca84-b7cf-441a-bbac-48c581c8361e" CreationDate="2019-05-04T06:02:45.547" UserId="-1" />
  <row Id="23939" PostHistoryTypeId="50" PostId="8731" RevisionGUID="2a6e2d59-fc55-460a-b6a1-6153a96f9ec1" CreationDate="2019-05-04T07:02:25.503" UserId="-1" />
  <row Id="23940" PostHistoryTypeId="50" PostId="8730" RevisionGUID="74a0160d-5e56-48f7-bb4d-bfe264fd537c" CreationDate="2019-05-04T18:03:00.653" UserId="-1" />
  <row Id="23941" PostHistoryTypeId="50" PostId="8209" RevisionGUID="ab4353ba-44c1-4a12-a00e-4ee0d458f460" CreationDate="2019-05-04T22:01:45.393" UserId="-1" />
  <row Id="23942" PostHistoryTypeId="34" PostId="8771" RevisionGUID="215568e5-b315-4823-9ca9-ae7ce6e9c688" CreationDate="2019-05-05T02:01:10.230" UserId="-1" Comment="54" />
  <row Id="23943" PostHistoryTypeId="50" PostId="8737" RevisionGUID="eee7f891-ec42-4d22-b1e1-71bc3fdfeae9" CreationDate="2019-05-05T06:01:20.423" UserId="-1" />
  <row Id="23944" PostHistoryTypeId="2" PostId="8820" RevisionGUID="e58ab829-69b3-4f3f-ab14-bc27176a2e7f" CreationDate="2019-05-05T17:31:13.800" UserId="10601" Text="Ideal mirror's brdf is simple,&#xD;&#xA;&#xD;&#xA;$F\frac{\delta(\omega_i-\omega_r)}{|\cos(\theta_r)|}$&#xD;&#xA;&#xD;&#xA;as in http://www.pbr-book.org/3ed-2018/Reflection_Models/Specular_Reflection_and_Transmission.html&#xD;&#xA;&#xD;&#xA;As shown in several articles, microfacet brdf can have zero roughness by definition then they should be able to represent ideal mirror. But I cannot derive them to above correct ideal brdf.&#xD;&#xA;&#xD;&#xA;For instance, when I put zero roughness into GGX model,&#xD;&#xA;(https://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf )&#xD;&#xA;&#xD;&#xA;D(m) = D(h) goes to infinity by divided by 0 and G is just one. However, the brdf I got is,&#xD;&#xA;&#xD;&#xA;$F\frac{DG}{4|N\cdot V||N\cdot L|}$&#xD;&#xA;&#xD;&#xA;Then rendering equation is,&#xD;&#xA;&#xD;&#xA;$\int F\frac{DG}{4|N\cdot V||N\cdot L|} \cos\theta_id\omega_i = \int F\frac{DG}{4|N\cdot V|} d\omega_i$&#xD;&#xA;&#xD;&#xA;If this was correct, $\frac{DG}{4|N\cdot V|}$ should be a dirac delta function. But I don't think so.&#xD;&#xA;&#xD;&#xA;Where am I wrong? How can I derive ideal mirror from microfacet brdf?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23945" PostHistoryTypeId="1" PostId="8820" RevisionGUID="e58ab829-69b3-4f3f-ab14-bc27176a2e7f" CreationDate="2019-05-05T17:31:13.800" UserId="10601" Text="Can microfacet BRDF (including ggx) represent ideal mirror?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23946" PostHistoryTypeId="3" PostId="8820" RevisionGUID="e58ab829-69b3-4f3f-ab14-bc27176a2e7f" CreationDate="2019-05-05T17:31:13.800" UserId="10601" Text="|brdf|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23947" PostHistoryTypeId="5" PostId="8820" RevisionGUID="255801fa-27e5-471a-ad14-476fd08a7b79" CreationDate="2019-05-05T17:38:16.750" UserId="10601" Comment="added 33 characters in body" Text="Ideal mirror's brdf is simple,&#xD;&#xA;&#xD;&#xA;$F\frac{\delta(\omega_i-\omega_r)}{|\cos(\theta_r)|}$&#xD;&#xA;&#xD;&#xA;as in http://www.pbr-book.org/3ed-2018/Reflection_Models/Specular_Reflection_and_Transmission.html&#xD;&#xA;&#xD;&#xA;As shown in several articles, microfacet brdf can have zero roughness by definition then they should be able to represent ideal mirror. But I cannot derive them to above correct ideal brdf.&#xD;&#xA;&#xD;&#xA;For instance, when I put zero roughness into GGX model,&#xD;&#xA;(https://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf )&#xD;&#xA;&#xD;&#xA;D(m) = D(H) goes to infinity by divided by 0 and G is just one. However, the brdf I got is,&#xD;&#xA;&#xD;&#xA;$F\frac{DG}{4|N\cdot V||N\cdot L|}$&#xD;&#xA;&#xD;&#xA;Then rendering equation is,&#xD;&#xA;&#xD;&#xA;$\int F\frac{D(H)G(L,V, H)}{4|N\cdot V||N\cdot L|} \cos\theta_id\omega_i = \int F\frac{D(H)G(L,V, H)}{4|N\cdot V|} d\omega_i$&#xD;&#xA;&#xD;&#xA;If this was correct, $\frac{D(H)G(L,V, H)}{4|N\cdot V|}$ should be a dirac delta function. But I don't think so.&#xD;&#xA;&#xD;&#xA;Where am I wrong? How can I derive ideal mirror from microfacet brdf?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23948" PostHistoryTypeId="5" PostId="8820" RevisionGUID="5f196881-16cb-4aa2-9b25-a14c2efa1bc8" CreationDate="2019-05-05T17:52:23.723" UserId="10601" Comment="added 11 characters in body; edited title" Text="Perfect mirror's brdf is simple,&#xD;&#xA;&#xD;&#xA;$F\frac{\delta(\omega_i-\omega_r)}{|\cos(\theta_r)|}$&#xD;&#xA;&#xD;&#xA;as in http://www.pbr-book.org/3ed-2018/Reflection_Models/Specular_Reflection_and_Transmission.html&#xD;&#xA;&#xD;&#xA;As shown in several articles, microfacet brdf can have zero roughness by definition then they should be able to represent a perfect mirror. But I cannot derive them to above correct perfect brdf.&#xD;&#xA;&#xD;&#xA;For instance, when I put zero roughness into GGX model,&#xD;&#xA;(https://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf )&#xD;&#xA;&#xD;&#xA;D(m) = D(H) goes to infinity by divided by 0 and G is just one. However, the brdf I got is,&#xD;&#xA;&#xD;&#xA;$F\frac{DG}{4|N\cdot V||N\cdot L|}$&#xD;&#xA;&#xD;&#xA;Then rendering equation is,&#xD;&#xA;&#xD;&#xA;$\int F\frac{D(H)G(L,V, H)}{4|N\cdot V||N\cdot L|} \cos\theta_id\omega_i = \int F\frac{D(H)G(L,V, H)}{4|N\cdot V|} d\omega_i$&#xD;&#xA;&#xD;&#xA;If this was correct, $\frac{D(H)G(L,V,H)}{4|N\cdot V|}$ should be a dirac delta function. But I don't think so.&#xD;&#xA;&#xD;&#xA;Where am I wrong? How can I derive a perfect mirror from microfacet brdf?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23949" PostHistoryTypeId="4" PostId="8820" RevisionGUID="5f196881-16cb-4aa2-9b25-a14c2efa1bc8" CreationDate="2019-05-05T17:52:23.723" UserId="10601" Comment="added 11 characters in body; edited title" Text="Can microfacet BRDF (including ggx) represent perfect mirror?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23953" PostHistoryTypeId="2" PostId="8822" RevisionGUID="52c63507-e228-4fe2-bc77-5089b09391c8" CreationDate="2019-05-06T04:53:38.723" UserId="7057" Text="Depth buffer values are clamped to that range because usually they are using fixed-point representation, so if clipping is disabled (by `glEnable(GL_DEPTH_CLAMP)`) then they can't hold anything beyond that range.&#xD;&#xA;&#xD;&#xA;However, there isn't really a good reason for this clamping when floating point depth buffers are used. In fact `GL_NV_depth_buffer_float` extensions allows you to disable this clamping on Nvidia hardware for floating point buffers. Unfortunately other vendors don't have any documented way of doing that.&#xD;&#xA;&#xD;&#xA;Also it's worth noting that unclamped floating point depth values have a minor complication: their depth offset is trickier to define. OpenGL spec resolves this by making the depth offset depend on the range of z-coordinates of the primitive. In fixed-point depth buffers, on the other hand, the offset is a function of the triangle slope only." ContentLicense="CC BY-SA 4.0" />
  <row Id="23954" PostHistoryTypeId="2" PostId="8823" RevisionGUID="5180bc2d-0227-4780-a19a-f7bfe830d252" CreationDate="2019-05-06T05:13:56.403" UserId="7057" Text="It is compatible, but instead of clipping it now clamps (hence the name). If the depth of your primitives is outside the [0,1] range it ends up behaving as if you have no depth-test at all. The only way to mitigate that is to either scale down the depth range so it fits in [0,1] or to use `GL_NV_depth_buffer_float` to disable clipping and clamping completely." ContentLicense="CC BY-SA 4.0" />
  <row Id="23955" PostHistoryTypeId="5" PostId="8820" RevisionGUID="6983e941-c968-4a2f-bca4-0945537a8b3d" CreationDate="2019-05-06T08:07:21.380" UserId="10601" Comment="added 281 characters in body; edited tags" Text="Perfect mirror's brdf is simple,&#xD;&#xA;&#xD;&#xA;$F\frac{\delta(\omega_i-\omega_r)}{|\cos(\theta_r)|}$&#xD;&#xA;&#xD;&#xA;as in http://www.pbr-book.org/3ed-2018/Reflection_Models/Specular_Reflection_and_Transmission.html&#xD;&#xA;&#xD;&#xA;As shown in several articles, microfacet brdf can have zero roughness by definition then they should be able to represent a perfect mirror. But I cannot derive them to above correct perfect brdf.&#xD;&#xA;&#xD;&#xA;For instance, when I put zero roughness into GGX model,&#xD;&#xA;(https://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf )&#xD;&#xA;&#xD;&#xA;D(m) = D(H) goes to infinity by divided by 0 and G is just one. However, the brdf I got is,&#xD;&#xA;&#xD;&#xA;$F\frac{DG}{4|N\cdot V||N\cdot L|}$&#xD;&#xA;&#xD;&#xA;Then rendering equation is,&#xD;&#xA;&#xD;&#xA;$\int F\frac{D(H)G(L,V, H)}{4|N\cdot V||N\cdot L|} \cos\theta_id\omega_i = \int F\frac{D(H)G(L,V, H)}{4|N\cdot V|} d\omega_i$&#xD;&#xA;&#xD;&#xA;If this was correct, $\frac{D(H)G(L,V,H)}{4|N\cdot V|}$ should be a dirac delta function. But I don't think so.&#xD;&#xA;&#xD;&#xA;Where am I wrong? How can I derive a perfect mirror from microfacet brdf?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;I concluded that Cook-Torrance's brdf can not represent a perfect mirror. The equation has some small value greater than zero when H $\neq$ N even if roughness is zero. So, normalization factor $4|N\cdot V|$ should be not be removed.&#xD;&#xA;&#xD;&#xA;Correct me if I was wrong." ContentLicense="CC BY-SA 4.0" />
  <row Id="23956" PostHistoryTypeId="6" PostId="8820" RevisionGUID="6983e941-c968-4a2f-bca4-0945537a8b3d" CreationDate="2019-05-06T08:07:21.380" UserId="10601" Comment="added 281 characters in body; edited tags" Text="|brdf|microfacet|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23957" PostHistoryTypeId="2" PostId="8824" RevisionGUID="f56c0a32-5fdf-414a-b0ee-022263d29f52" CreationDate="2019-05-06T17:50:36.397" UserId="8807" Text="I'm going through the [rasterizer tutorial from Scratchapixel][1], but I encountered a problem with the generation of the .ppm file. Since something was off, I reduced the example to the bare minimum, so I currently simply generate a 512x512 image of a plain color.&#xD;&#xA;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    &#xD;&#xA;    using Rgb = unsigned char[3];&#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	const uint32_t w = 512;&#xD;&#xA;    	const uint32_t h = 512;&#xD;&#xA;    &#xD;&#xA;    	Rgb *framebuffer = new Rgb[w * h];&#xD;&#xA;    	for (uint32_t j = 0; j &lt; h; ++j) {&#xD;&#xA;    		for (uint32_t i = 0; i &lt; w; ++i) {&#xD;&#xA;    			framebuffer[j * w + i][0] = static_cast&lt;unsigned char&gt;(255);&#xD;&#xA;    			framebuffer[j * w + i][1] = static_cast&lt;unsigned char&gt;(0);&#xD;&#xA;    			framebuffer[j * w + i][2] = static_cast&lt;unsigned char&gt;(0);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	std::ofstream ofs;&#xD;&#xA;    	ofs.open(&quot;./example.ppm&quot;);&#xD;&#xA;    	ofs &lt;&lt; &quot;P6\n&quot; &lt;&lt; w &lt;&lt; &quot; &quot; &lt;&lt; h &lt;&lt; &quot;\n255\n&quot;;&#xD;&#xA;    	ofs.write((char*)framebuffer, w * h * 3);&#xD;&#xA;    	ofs.close();&#xD;&#xA;    &#xD;&#xA;    	delete[] framebuffer;&#xD;&#xA;    &#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above should generate a red square image, but if I open the file with Gimp, I get a green image.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea of what's happening?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage&#xD;&#xA;  [2]: https://i.stack.imgur.com/LgOJV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23958" PostHistoryTypeId="1" PostId="8824" RevisionGUID="f56c0a32-5fdf-414a-b0ee-022263d29f52" CreationDate="2019-05-06T17:50:36.397" UserId="8807" Text="Wrong color in .ppm file" ContentLicense="CC BY-SA 4.0" />
  <row Id="23959" PostHistoryTypeId="3" PostId="8824" RevisionGUID="f56c0a32-5fdf-414a-b0ee-022263d29f52" CreationDate="2019-05-06T17:50:36.397" UserId="8807" Text="|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23962" PostHistoryTypeId="2" PostId="8825" RevisionGUID="a5b99122-b114-46f0-8f4d-86b3d6c8005b" CreationDate="2019-05-07T05:59:40.460" UserId="10605" Text="Here's the problem :&#xD;&#xA;I have multiple noise generators in my program I Can't change.&#xD;&#xA;Perlin Noise, Diamond Square, Voronoi, etc.&#xD;&#xA;Unfortunately for me, I want the noise to be tileable, no matter the generator :&#xD;&#xA;&#xD;&#xA;The idea is to create a torus-like strategy game with the user choosing a noise and then having it tiled to play on it. &#xD;&#xA;&#xD;&#xA;I'm very well aware it's a rather poor design to make it tileable afterwards, but it's a time saver for the coding part.&#xD;&#xA;&#xD;&#xA;Thank you in advance for your help and ideas.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23963" PostHistoryTypeId="1" PostId="8825" RevisionGUID="a5b99122-b114-46f0-8f4d-86b3d6c8005b" CreationDate="2019-05-07T05:59:40.460" UserId="10605" Text="Nice way to make noise seamless (without tampering with the noise generator)" ContentLicense="CC BY-SA 4.0" />
  <row Id="23964" PostHistoryTypeId="3" PostId="8825" RevisionGUID="a5b99122-b114-46f0-8f4d-86b3d6c8005b" CreationDate="2019-05-07T05:59:40.460" UserId="10605" Text="|texture|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23965" PostHistoryTypeId="2" PostId="8826" RevisionGUID="b27a9924-0676-4507-856e-1ef538a05cf8" CreationDate="2019-05-07T06:24:24.303" UserId="7008" Text="&gt; If this was correct, $\frac{D(H)G(L,V,H)}{4|N⋅V|}$ should be a dirac delta function. But I don't think so.&#xD;&#xA;&#xD;&#xA;Actually, you're close to your answer - you just are trying to find out, what the assumption was in the very beginning - if you're talking about a specular BRDF. The term  $F\frac{DG}{4|N⋅V||N⋅L|}$ only works, if you start with the precondition, that you're dealing with a perfect mirror, otherwise this would be an integral itself. Have a look at [PBR Diffuse Lighting for GGX+SmithMicrosurfaces][1] by Earl Hammon Jr., where explains how to get to the specular BRDF. Especially have a look at slide 29:&#xD;&#xA;&#xD;&#xA; - Microfacet BRDF is a perfect mirror &#xD;&#xA;   - I.e., light reflects if and only if $m = H$&#xD;&#xA;     - Mathematically, BRDF is a scaled dirac delta $\delta_m(H, m)$&#xD;&#xA;&#xD;&#xA;So the perfect mirror is your model in the beginning$^1$ - but only for the specular BRDF! &#xD;&#xA;&#xD;&#xA;If you are trying to see, if including the diffuse BRDF into your BRDF is a perfect mirror, then this assumption does not hold any more and thus you don't have the dirac delta function.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;$^1$ Note that he speaks about a microfacet being a perfect mirror. However, if all your microfacets are perfectly aligned, then your microgeometry &quot;equals&quot; your macrogeometry&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gdcvault.com/play/1024478/PBR-Diffuse-Lighting-for-GGX" ContentLicense="CC BY-SA 4.0" />
  <row Id="23966" PostHistoryTypeId="2" PostId="8827" RevisionGUID="9fbe9cec-9490-4b14-8869-a1dcfee8718e" CreationDate="2019-05-07T10:45:00.733" UserId="10607" Text="For others who might have this question, here a perhaps more straight forward numeric answer (I'm now working myself on this book as well). Consider that:&#xD;&#xA;&#xD;&#xA; 1. We are given object space coordinates that need to be transformed into upright and subsequently world space coordinates.&#xD;&#xA;&#xD;&#xA; 2. We know that a vector $\vec{v}$ can be represented as a linear transformation of its axises in relation to the set of basis vectors $\vec{p}$, $\vec{q}$, $\vec{r}$, when these are ***orthonormal*** (perpendicular to each other and with length $l = 1$)&#xD;&#xA;&#xD;&#xA; 3. The equation to represent this is thus: $\vec{v} = v_{x}p + v_{y}q + v_{z}r$ &#xD;&#xA;&#xD;&#xA; 4. Given the basis vectors we can computed this for each object reference using the above equation. So, the first example would be:&#xD;&#xA;&#xD;&#xA;$\vec{u} = -1 \begin{bmatrix}0.866\\ 0\\ -0.500 \end{bmatrix} + 2 \begin{bmatrix}0\\ 1\\ 0\end{bmatrix} + 0 \begin{bmatrix}0.500\\ 0\\ 0.866\end{bmatrix} = \begin{bmatrix}-0.866\\ 2\\ 0.500\end{bmatrix}$&#xD;&#xA;&#xD;&#xA;Then, to compute this in world space, you simply need to add your world space reference to the upright vector. Meaning:&#xD;&#xA;&#xD;&#xA;$\vec{w} = o + u$&#xD;&#xA;&#xD;&#xA;For the first example in the book that would be:&#xD;&#xA;&#xD;&#xA;$\vec{w} = \begin{bmatrix}1\\ 10\\ 3\end{bmatrix} + \begin{bmatrix}-0.866\\ 2\\ 0.500\end{bmatrix} = \begin{bmatrix}0.134\\ 12\\ 3.500\end{bmatrix}$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="23977" PostHistoryTypeId="5" PostId="8824" RevisionGUID="dd345741-1cf0-4992-91ee-24fafdfd316d" CreationDate="2019-05-08T18:14:55.570" UserId="8807" Comment="added 141 characters in body" Text="I'm going through the [rasterizer tutorial from Scratchapixel][1], but I encountered a problem with the generation of the .ppm file. Since something was off, I reduced the example to the bare minimum, so I currently simply generate a 512x512 image of a plain color.&#xD;&#xA;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    &#xD;&#xA;    using Rgb = unsigned char[3];&#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	const uint32_t w = 512;&#xD;&#xA;    	const uint32_t h = 512;&#xD;&#xA;    &#xD;&#xA;    	Rgb *framebuffer = new Rgb[w * h];&#xD;&#xA;    	for (uint32_t j = 0; j &lt; h; ++j) {&#xD;&#xA;    		for (uint32_t i = 0; i &lt; w; ++i) {&#xD;&#xA;    			framebuffer[j * w + i][0] = static_cast&lt;unsigned char&gt;(255);&#xD;&#xA;    			framebuffer[j * w + i][1] = static_cast&lt;unsigned char&gt;(0);&#xD;&#xA;    			framebuffer[j * w + i][2] = static_cast&lt;unsigned char&gt;(0);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	std::ofstream ofs;&#xD;&#xA;    	ofs.open(&quot;./example.ppm&quot;);&#xD;&#xA;    	ofs &lt;&lt; &quot;P6\n&quot; &lt;&lt; w &lt;&lt; &quot; &quot; &lt;&lt; h &lt;&lt; &quot;\n255\n&quot;;&#xD;&#xA;    	ofs.write((char*)framebuffer, w * h * 3);&#xD;&#xA;    	ofs.close();&#xD;&#xA;    &#xD;&#xA;    	delete[] framebuffer;&#xD;&#xA;    &#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code above should generate a red square image, but if I open the file with Gimp, I get a green image.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Do you have any idea of what's happening?&#xD;&#xA;&#xD;&#xA;**EDIT**: This is the .ppm file with a hex editor:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage&#xD;&#xA;  [2]: https://i.stack.imgur.com/LgOJV.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vA9dG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23978" PostHistoryTypeId="2" PostId="8830" RevisionGUID="8ae93e45-74e9-4b9f-8f14-bcafd7b90175" CreationDate="2019-05-09T00:59:46.153" UserId="3003" Text="The issue is that on your system, writing out &quot;\n&quot; is writing out 0x0D0A, whereas on my system, it's only writing out 0x0A. If you explicitly write out 0x0A instead of &quot;\n&quot; I think it will work for you.&#xD;&#xA;&#xD;&#xA;Here's a hex dump on macOS Mojave:&#xD;&#xA;&#xD;&#xA;    50 36 0A 35 &#xD;&#xA;    31 32 20 35 &#xD;&#xA;    31 32 0A 32 &#xD;&#xA;    35 35 0A &#xD;&#xA;    FF 00 00 // &lt;- pixels start here&#xD;&#xA;    FF 00 00 &#xD;&#xA;    FF 00 00 &#xD;&#xA;    FF 00 00 &#xD;&#xA;    FF 00 00 &#xD;&#xA;    FF 00 00" ContentLicense="CC BY-SA 4.0" />
  <row Id="23979" PostHistoryTypeId="2" PostId="8831" RevisionGUID="d3a99634-81fb-4976-8750-b3adf2d384f9" CreationDate="2019-05-09T04:56:37.033" UserId="10624" Text="I am currently trying to implement [Jensen's paper on subsurface scattering](https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf), but I am getting confused when I am trying to implement it in my pathtracer. I have questions about the data types of certain variables.&#xD;&#xA;&#xD;&#xA;1. On page 3, $z_r$ is defined as $1 / \sigma_t'$, where $\sigma_t' = \sigma_s' + \sigma_a$. Based on Figure 5, $\sigma_s'$ and $\sigma_a$ are RGB values, which are `Spectrum` types in my pathtracer. However, $z_r$ is expected to be a distance above the surface, which I presume must be a float, not a `Spectrum`. How do I handle this discrepancy? Does each RGB wavelength have its own $z_r$?&#xD;&#xA;2. There is a similar issue in the single scattering term in section 4. $s_o'$ is a distance along the refracted outgoing ray, which is presumably a float. However, the formula for this term uses $\sigma_t$, which is a `Spectrum`.&#xD;&#xA;3. What about $\sigma_{tr}$? This value is $\sqrt{3\sigma_a\sigma_t'}$. Is this also a `Spectrum` or a float?" ContentLicense="CC BY-SA 4.0" />
  <row Id="23980" PostHistoryTypeId="1" PostId="8831" RevisionGUID="d3a99634-81fb-4976-8750-b3adf2d384f9" CreationDate="2019-05-09T04:56:37.033" UserId="10624" Text="Confusion about data types in Jensen's subsurface scattering paper" ContentLicense="CC BY-SA 4.0" />
  <row Id="23981" PostHistoryTypeId="3" PostId="8831" RevisionGUID="d3a99634-81fb-4976-8750-b3adf2d384f9" CreationDate="2019-05-09T04:56:37.033" UserId="10624" Text="|c++|brdf|subsurface-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23982" PostHistoryTypeId="5" PostId="352" RevisionGUID="a0b8f74e-2549-4a7a-8f61-af2af5737968" CreationDate="2019-05-09T06:46:24.227" UserId="10617" Comment="Correct me if I'm wrong, but all other sources I can find state that the number of knots = number of control points + degree of the curve + 1. (or numKnots = CP + Order of curve, if you prefer)" Text="The way that NURBS curves are typically split at an arbitrary point is by [knot insertion][1]. You insert knots at the split point until it is at maximum multiplicity, at which point you can just read off the two split curves.&#xD;&#xA;&#xD;&#xA;However, you may not want to split at an arbitrary point. If the ultimate goal is to draw the curves or something like that, then it's worth splitting the curve at the existing knot points (that is, performing knot insertion until all knots are at maximum multiplicity) rather than inserting new ones.&#xD;&#xA;&#xD;&#xA;This process splits the NURBS into *uniform* rational B-splines. Once you have that, you can use [de Boor's algorithm][2] to split further.&#xD;&#xA;&#xD;&#xA;The number of knots in the knot vector is:&#xD;&#xA;&#xD;&#xA;    numKnots = degreeOfCurve + numControlPoints + 1&#xD;&#xA;&#xD;&#xA;or if you prefer:&#xD;&#xA;    &#xD;&#xA;    numKnots = orderOfCurve + numControlPoints&#xD;&#xA;&#xD;&#xA;Inserting a knot thus increases the number of control points by one.&#xD;&#xA;&#xD;&#xA;As you travel along a NURBS curve, each knot represents a place where one control point &quot;drops out&quot; and another one &quot;enters&quot;. If a knot value is repeated, this means that more than one control point is replaced at this place.&#xD;&#xA;&#xD;&#xA;For a curve of degree greater than 1, the and last knots are repeated multiple times for one simple reason: you need to bring in more than one point to start and you need to eject more than one point to end.&#xD;&#xA;&#xD;&#xA;Let's think about cubic curves for the moment, just to keep things simple.&#xD;&#xA;&#xD;&#xA;A curve with the knot vector [0,0,1,1] is a uniform B-spline curve. &#xD;&#xA;&#xD;&#xA;A curve with the knot vector [0,0,1,1,2,2] is non-uniform, but can be thought of as two uniform B-spline curves which connect at t=1, one corresponding to [0,0,1,1] and one corresponding to [1,1,2,2]. You can do this because the multiplicity of the knots is enough to &quot;start&quot; and &quot;end&quot; a cubic curve.&#xD;&#xA;&#xD;&#xA;If you're faced with a curve with a knot vector like [0,0,1,2,2], you can insert a knot at 1 without changing the shape of the curve (this is the knot insertion procedure). This increases the number of control points by one; the knot insertion procedure adjusts the points around the new knot to accommodate it. But once you've done that, you have two uniform B-spline curves.&#xD;&#xA;&#xD;&#xA;Knot insertion won't create overlapping control points unless you insert too many knots at the same place, and by &quot;too many&quot;, I mean the degree of the curve. So for a non-uniform cubic curve, you'd insert knots so that every knot had multiplicity 2. That gives you a number of abutting uniform cubic curves, which you can then use de Boor's algorithm to split further.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS-knot-insert.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/De_Boor%27s_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="23983" PostHistoryTypeId="24" PostId="352" RevisionGUID="a0b8f74e-2549-4a7a-8f61-af2af5737968" CreationDate="2019-05-09T06:46:24.227" Comment="Proposed by 10617 approved by 159 edit id of 476" ContentLicense="CC BY-SA 4.0" />
  <row Id="23984" PostHistoryTypeId="2" PostId="8832" RevisionGUID="79e307d8-b855-4a0c-87e5-9f06e296570e" CreationDate="2019-05-09T07:02:52.477" UserId="159" Text="The heading row of Figure 5(b) says that the units of $\sigma_s'$ and $\sigma_a$ are inverse millimetres, that is, inverse distance. Hence, $1/\sigma_t'$ has units of distance.&#xD;&#xA;&#xD;&#xA;If you send a beam of photons through a medium with scattering coefficient $\sigma$ and measure it at distance $l$, then the probability that a photon has made it that far without being scattered is $e^{-\sigma l}$. Since $l$ has units of distance, $\sigma$ must have units of inverse distance." ContentLicense="CC BY-SA 4.0" />
  <row Id="23985" PostHistoryTypeId="2" PostId="8833" RevisionGUID="aaf570c5-d909-499f-8fbf-ec8a35a9b48e" CreationDate="2019-05-09T16:32:44.307" UserId="7644" Text="If you can't change the textures, I see 2 possibilities:&#xD;&#xA;&#xD;&#xA; 1. Use mirrored repeat on the noise textures so they tile seamlessly. [![enter image description here][1]][1] (taken from [here][2])&#xD;&#xA; 2. Do like [Gimp does][3] (or many other alternatives) and create tilable versions of the noise textures. The idea is to blend the left and right, and bottom and top edges together in pairs. Here's how to do it in an image editor: translate the image by 1/2 in both axis so the corners are in the middle. Blur, smudge, etc. to remove the seams. Revert the translation.&#xD;&#xA;&#xD;&#xA;![enter image description here][4] ![enter image description here][5]&#xD;&#xA;&#xD;&#xA;Keep in mind that the randomness and quality of the noise will of course be affected by either technique.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TEM45.png&#xD;&#xA;  [2]: https://open.gl/textures&#xD;&#xA;  [3]: https://www.gimp.org/tutorials/Tileable_Textures/&#xD;&#xA;  [4]: https://i.stack.imgur.com/b7PI0.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/O17G1.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="23992" PostHistoryTypeId="50" PostId="8757" RevisionGUID="e3047aeb-ebf1-4d1a-923e-7de877b4b3f6" CreationDate="2019-05-11T07:02:00.757" UserId="-1" />
  <row Id="23993" PostHistoryTypeId="2" PostId="8835" RevisionGUID="135b5782-9f09-4735-b345-dd2b18415552" CreationDate="2019-05-11T11:38:11.620" UserId="10633" Text="This question is regarding a homework assignment (want to be upfront because many people on stack exchange don't like helping with homework questions).&#xD;&#xA;&#xD;&#xA;I have a triangular mesh, which is defined by a set of vertices and a set of faces.&#xD;&#xA;I want to calculate the discrete gradient of the mesh, and I even got instructions on how to implement it. The problem is that even after reading them multiple times, I don't understand them...&#xD;&#xA;&#xD;&#xA;**The implementation instructions:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**My Problem:**&#xD;&#xA;&#xD;&#xA;I don't understand how to implement the marked sum, which in turn prevents me from constructing the following E matrix.&#xD;&#xA;&#xD;&#xA;I would appreciate any help. I'm not looking for specific code examples, rather an explanation/example of the calculation for a single triangle. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MTZ2w.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23994" PostHistoryTypeId="1" PostId="8835" RevisionGUID="135b5782-9f09-4735-b345-dd2b18415552" CreationDate="2019-05-11T11:38:11.620" UserId="10633" Text="Calculating the gradient of a triangular mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="23995" PostHistoryTypeId="3" PostId="8835" RevisionGUID="135b5782-9f09-4735-b345-dd2b18415552" CreationDate="2019-05-11T11:38:11.620" UserId="10633" Text="|computational-geometry|matlab|" ContentLicense="CC BY-SA 4.0" />
  <row Id="23996" PostHistoryTypeId="2" PostId="8836" RevisionGUID="3b3a1e3a-f2f7-4b5f-ac85-51c52f355110" CreationDate="2019-05-11T23:00:52.860" UserId="7072" Text="I am trying to render a teapot within a simple raytracing that can handle reflection, refraction, and shadowing from point and directional lights.&#xD;&#xA;&#xD;&#xA;I am very confused about one detail of the raytracer and that is the interpolated normals. This question was brought on when my raytracer rendered this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now there are more than a couple issues with this render however it did bring up an important point. Not using interpolated normals causes blocking reflections like this.&#xD;&#xA;&#xD;&#xA;I had previously figured that I should not use interpolated normals when calculating reflection or refraction rays. I had previously figured that I should not do it because that might introduce edge cases as reflecting off an interpolated normal would have the ray bouncing off the wrong position since I am shading it like its smooth. &#xD;&#xA;&#xD;&#xA;I also feel like this might introduce edge cases when it comes time to implement accelerating spatial data structures.&#xD;&#xA;&#xD;&#xA;So I guess my question is where should/shouldn't I be using interpolated normals in my ray-tracer.&#xD;&#xA;&#xD;&#xA;I am betting there is a different protocol if you are rendering a feature animated film vs just creating a toy/lightweight/quick raytracer. I would love to know the answer for both.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c3SRI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="23997" PostHistoryTypeId="1" PostId="8836" RevisionGUID="3b3a1e3a-f2f7-4b5f-ac85-51c52f355110" CreationDate="2019-05-11T23:00:52.860" UserId="7072" Text="Dealing with interpolated normals within a raytracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="23998" PostHistoryTypeId="3" PostId="8836" RevisionGUID="3b3a1e3a-f2f7-4b5f-ac85-51c52f355110" CreationDate="2019-05-11T23:00:52.860" UserId="7072" Text="|raytracing|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24002" PostHistoryTypeId="2" PostId="8838" RevisionGUID="52cdb20d-3ceb-436a-acac-08a873bab7b2" CreationDate="2019-05-12T10:53:05.347" UserId="209" Text="Disclaimer: It's been a long time since I looked at this sort of thing but here goes...&lt;br&gt;&#xD;&#xA;Disclaimer2: On re-reading your question(s) I realised I might have misunderstood what you were asking. I'll leave this here just in case you were looking for this sort of reply.&#xD;&#xA;&#xD;&#xA;Are you rendering from the original Bezier patch definition (e.g. https://www.cs.utah.edu/gdc/projects/alpha1/help/man/html/model_repo/model_teapot/teapot.pts)  or from a (post tessellation) triangle representation?&#xD;&#xA;&#xD;&#xA;If the former, then you should, in the **vast majority** of cases, be able to 'trivially' generate the normals directly from the Bezier representation, by computing surface partial derivatives at each ray intersection point, to give tangent vectors, and computing the cross product. The cases you *do* have to watch out for are at very centres of the bottom and top of the teapot where the patches, though *geometrically* well-defined, have a zero partial derivative because the rectangular patch has been squeezed into a triangle, e.g. control points for U,V = (0,0), (0,1/3), (0,2/3), (0,1) are all identical, so dPos/dv is 0.  All you need do is compute dPos/du at (0,0) and (0,1) to get valid tangents.&#xD;&#xA;&#xD;&#xA;If you are rendering from triangles, I assume you already have normals at the triangle vertices. If you use an appropriate ray-triangle intersection test you can get the barycentric coordinates of the intersection point. Use these to blend the vertex normals (and after renormalising) you'll have a 'reasonable' surface normal (though it will only be C0 continuous)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24003" PostHistoryTypeId="2" PostId="8839" RevisionGUID="e2380913-d728-473f-8283-e44a398bc559" CreationDate="2019-05-12T11:30:24.513" UserId="10635" Text="Imagine I have an x value that ranges from 1-100. The light source is pointed at x=50.&#xD;&#xA;&#xD;&#xA;From points 35 to 65 I want intensity to be 1&#xD;&#xA;&#xD;&#xA;At the ends (ie 1 and 100), intensity should be 0&#xD;&#xA;&#xD;&#xA;What formula should be used to model the in between values ?&#xD;&#xA;&#xD;&#xA;Cosine ? Inverse square law ? ratio ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24004" PostHistoryTypeId="1" PostId="8839" RevisionGUID="e2380913-d728-473f-8283-e44a398bc559" CreationDate="2019-05-12T11:30:24.513" UserId="10635" Text="gradual transition of light intensity formula" ContentLicense="CC BY-SA 4.0" />
  <row Id="24005" PostHistoryTypeId="3" PostId="8839" RevisionGUID="e2380913-d728-473f-8283-e44a398bc559" CreationDate="2019-05-12T11:30:24.513" UserId="10635" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24007" PostHistoryTypeId="2" PostId="8840" RevisionGUID="1cc0de4a-b049-49e2-846c-d313a127f074" CreationDate="2019-05-12T16:12:09.457" UserId="10333" Text="I have come across this image that's labelled a bump map to be used with a 3D model. It looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In this map, which is an RGB map, it seems we have pixels whose normals face upwards shaded lighter, and normals pointing downward shaded darker. I have isolated just one part of this map, a little mound with a whole in the middle:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I've tried to recreate this shape in an image editing program just using white colour for height, it's essentially a heightmap, or bumpmap. It looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;It's basically a circular mound that rises gradually, and then falls off steeply into a hole.&#xD;&#xA;&#xD;&#xA;So I know that this is one way normals and height can be stored. This is essentially a heightmap, but some people and programs call this a bumpmap. In 3DS Max the bumpmap essentially expects a heightmap.&#xD;&#xA;&#xD;&#xA;Then there's the normal map, which looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Inside the red channel the information about how flat or inclined the surface is from left to right:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;And same as in the green, except from up to down:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;So I understand this, I think. However in the original image, this strange &quot;bumpmap&quot;, it only seems to contain the information of the flatness of the surface from up to down, not left to right. What I've shown is how it appears as an RGB image. Here is each of the channels:&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;They all contain the same information, that is, facing of the surface from up to down. &#xD;&#xA;&#xD;&#xA;How is this map supposed work? I've come across a few maps like these but I don't see how they're supposed to work. Can someone explain if this is possible?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WimNC.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/eQaRw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jxIQ4.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Hw3GH.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/fhPaa.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/uOP5N.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/9VLiF.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/kq7EN.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/cC1Uh.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24008" PostHistoryTypeId="1" PostId="8840" RevisionGUID="1cc0de4a-b049-49e2-846c-d313a127f074" CreationDate="2019-05-12T16:12:09.457" UserId="10333" Text="How is this normals map supposed to work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24009" PostHistoryTypeId="3" PostId="8840" RevisionGUID="1cc0de4a-b049-49e2-846c-d313a127f074" CreationDate="2019-05-12T16:12:09.457" UserId="10333" Text="|normal-mapping|mapping|height-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24010" PostHistoryTypeId="2" PostId="8841" RevisionGUID="202d5733-d5a2-46b9-94a8-db46b70f9338" CreationDate="2019-05-12T16:54:19.887" UserId="506" Text="Yeah, that doesn’t look like any bump, height, or normal map I’ve ever seen—as you’ve identified, there’s only information about the surface contour along a single axis. If anything, it looks like it’s meant to be overlaid on a texture as a cheap form of fake bump-mapping in an era where it was too expensive to do it for real." ContentLicense="CC BY-SA 4.0" />
  <row Id="24011" PostHistoryTypeId="2" PostId="8842" RevisionGUID="5b043167-ba2d-430b-84d7-6abd77eda53f" CreationDate="2019-05-13T03:07:30.967" UserId="8851" Text="A function $f$ on your triangulated surface is an assignment of real numbers on the vertices of the triangulation and therefore $f \in \mathbb{R}^{|\mathcal{V}|}$. According to the continuous theory, the gradient should be a linear (differential) operator that takes a function and spits out a vector field. Hence, in the discrete theory, the gradient should be a linear operator that takes a function $f \in \mathbb{R}^{|\mathcal{V}|}$ and spit out some kind of a discrete version of a vector field. In your case, the vector field is given as an assignment of a vector to each triangle of the triangulation. That is why the discrete gradient operator should be a linear operator, i.e. a linear transformation&#xD;&#xA;$$\text{grad} : \mathbb{R}^{\mathcal{|V|}} \to \mathbb{R}^{3|\mathcal{F}|}$$    &#xD;&#xA;which is represented by a matrix $\text{grad} \in \mathbb{R}^{3|\mathcal{F}| \times |\mathcal{V}|}$. In the continuous theory, the gradient is determined only by local data, i.e. the behaviou of the function near the point at which the gradient is being calculated and by the geometry near that point. Therefore, in the discrete theory, the gradient is determined only by the geometry of one triangle and the values of the function at the triangle's vertices. Let the triangle $j \in  \mathcal{F}$ have vertices denoted (according to the instructions' convention) by $1, 2, 3$. The labels are set up so that the vertices $1,2,3$ define the labels of the opposing edges $\vec{e}_{j_1}, \vec{e}_{j_2}, \vec{e}_{j_3}$, i.e. for the vertex  $i$ the edge opposite to the vertex $i$ is denoted by $\vec{e}_{j_i}$, where the latter vector is oriented so that the vectors form a closed chain of vectors summing to zero in a counterclockwise direction.   &#xD;&#xA;Hence, the gradient can be defined as&#xD;&#xA;$$(\text{grad}\,f)(j) = \frac{1}{2\text{Area}(j)}\, \sum_{i=1}^{3} f_i\, J\vec{e}_{j_i}$$ Or to write it in coordinates, &#xD;&#xA;$$\begin{bmatrix} (\text{grad}\,f)(j)_1\\ (\text{grad}\,f)(j)_2\\(\text{grad}\,f)(j)_3\end{bmatrix} = \frac{1}{2\text{Area}(j)}\left( f_1\, \begin{bmatrix} (Je_{j_1})_1\\ (Je_{j_1})_2\\(Je_{j_1})_3\end{bmatrix} + &#xD;&#xA;f_2\, \begin{bmatrix} (Je_{j_2})_1\\ (Je_{j_2})_2\\(Je_{j_2})_3\end{bmatrix} + f_3\, \begin{bmatrix} (Je_{j_3})_1\\ (Je_{j_3})_2\\(Je_{j_3})_3\end{bmatrix}\right)$$ and in matrix form&#xD;&#xA;$$\begin{bmatrix} (\text{grad}\,f)(j)_1\\ (\text{grad}\,f)(j)_2\\(\text{grad}\,f)(j)_3\end{bmatrix} = \frac{1}{2\text{Area}(j)}\, \begin{bmatrix} (Je_{j_1})_1 &amp;  (Je_{j_2})_1 &amp; (Je_{j_3})_1 \\ (Je_{j_1})_2 &amp; (Je_{j_2})_2 &amp; (Je_{j_3})_2\\(Je_{j_1})_3 &amp; (Je_{j_2})_3 &amp; (Je_{j_3})_3 \end{bmatrix} \begin{bmatrix} f_1\\ f_2\\f_3\end{bmatrix} $$&#xD;&#xA;So, for the matrix $E \in \mathbb{R}^{3|\mathcal{V}|\times|\mathcal{V}|}$ is defined as follows. Let $j$ be a triangle and $i$ one of its vertices. Take the edge $e_{j_i}$ of triangle $j$ opposite to the vertex $i$, and consider the vector $\vec{e}_{j_i}$ along the edge, starting from one vertex, different from $i$, to the other vertex, different from $i$, oriented so that the the vector follows counterclockwise orientation of the boundary of the triangle $j$. Then rotate the vector $\vec{e}_{j_i}$ by $90^{\circ}$ so that it points inside the triangle $j$. Denote this rotated vector by  $$J\vec{e}_{j_i} = \begin{bmatrix} (Je_{j_i})_1\\ (Je_{j_i})_2\\(Je_{j_i})_3\end{bmatrix}$$ Then fill up the following entries of the matrix $E \in \mathbb{R}^{3|\mathcal{V}|\times|\mathcal{V}|}$:   &#xD;&#xA;\begin{align}&#xD;&#xA;&amp;E(j,i) = (Je_{j_i})_1\\&#xD;&#xA;&amp;E(j + |\mathcal{V}|, i) = (Je_{j_i})_2\\&#xD;&#xA;&amp;E(j + 2|\mathcal{V}|, i) = (Je_{j_i})_3&#xD;&#xA;\end{align}  &#xD;&#xA;You can rotate the vector $\vec{e}_{j_i}$ by using the cross-product operation twice. Take two of the edge-vectors of the triangle $j$, say $\vec{e}_{j_1}$ and $\vec{e}_{j_2}$, and calculate the unit normal vector to the triangle $j$:&#xD;&#xA;$$\vec{n}_j = \frac{1}{\|\vec{e}_{j_1} \times \vec{e}_{j_2}\|}\,\Big(\vec{e}_{j_1} \times \vec{e}_{j_2}\Big)$$ It doesn't matter whcih two out of the three edge-vector you would choose, the result is always the same unit normal $\vec{n}_j$. Then&#xD;&#xA;$$J\vec{e}_{j_i} = \vec{n}_j \times \vec{e}_{j_i}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="24012" PostHistoryTypeId="2" PostId="8843" RevisionGUID="ad34c7e4-7b6f-43eb-a6d6-9ba1cb9ffb18" CreationDate="2019-05-13T08:31:42.307" UserId="10270" Text="I'm trying to complete a look-up table for an energy-conserving variation of microfacet GGX as implemented here: https://patapom.com/blog/BRDF/MSBRDFEnergyCompensation/&#xD;&#xA;&#xD;&#xA;I have a (pretty standard) GGX form of the microfacet equation and my white furnace test behaves similar to what is shown elsewhere (i.e., it loses energy as roughness increases).&#xD;&#xA;&#xD;&#xA;However, when I attempt to integrate the brdf and store the total energy in a texture, I get results that are inverse to my expectation - higher roughness yields more total energy in the integral. Some code below (this is done in a compute shader):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float evalSum = 0.0;&#xD;&#xA;const float theta_i = 0.05;&#xD;&#xA;const float phi_i = 0.05;&#xD;&#xA;for (float phiWi = 0.0; phiWi &lt; PI2; phiWi += phi_i)&#xD;&#xA;{&#xD;&#xA;	for (float NoL = 0.0; NoL &lt; 1.0; NoL += theta_i)&#xD;&#xA;	{&#xD;&#xA;		float nohA = 1.0 + NoL * NoV + (1.0 - NoV * NoV) * (1.0 - NoL * NoL) * cos(phiWi);&#xD;&#xA;		float NoH = (NoL + NoV) / sqrt(2.0 * nohA);&#xD;&#xA;			&#xD;&#xA;		float D = Fs.eNDF(NoH, roughness);&#xD;&#xA;		float G = Fs.eGS(NoV, NoL, roughness);&#xD;&#xA;		float Fr = D * G;&#xD;&#xA;			&#xD;&#xA; 		evalSum += D * G * NoL;&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;outBuf[idx] = evalSum * phi_i * theta_i;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here is my texture output:&#xD;&#xA;[![LUT][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm expecting something more like this:&#xD;&#xA;[![energycomp][2]][2]&#xD;&#xA;&#xD;&#xA;As the Y axis goes down, roughness increases, and as the X axis goes to the right, `NoV` (N dot V) increases. Total energy increases with roughness and I also get a strange valley to the energy which I wasn't expecting.&#xD;&#xA;&#xD;&#xA;Here's the two GGX terms:&#xD;&#xA;```&#xD;&#xA;float getNDF(const float NoH, float linearRoughness)&#xD;&#xA;{&#xD;&#xA;	float a2 = linearRoughness * linearRoughness;&#xD;&#xA;	float b = NoH * NoH * (a2 - 1.0) + 1.0;&#xD;&#xA;&#xD;&#xA;	return a2 / (PI * (b * b));&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getGS(const float NoV, const float NoL, const float linearRoughness)&#xD;&#xA;{&#xD;&#xA;	float a2 = linearRoughness * linearRoughness;&#xD;&#xA;	float G_V = NoV + sqrt((NoV - NoV * a2) * NoV + a2);&#xD;&#xA;	float G_L = NoL + sqrt((NoL - NoL * a2) * NoL + a2);&#xD;&#xA;	return rcp(G_V * G_L);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Pretty stumped here. I must be doing the integral wrong somehow because the in-engine renders look correct - the brdf code seems straightforward. Any ideas on why my LUT is not producing the expected result?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Oi3iT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SvxNN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24013" PostHistoryTypeId="1" PostId="8843" RevisionGUID="ad34c7e4-7b6f-43eb-a6d6-9ba1cb9ffb18" CreationDate="2019-05-13T08:31:42.307" UserId="10270" Text="Microfacet GGX not integrating as expected" ContentLicense="CC BY-SA 4.0" />
  <row Id="24014" PostHistoryTypeId="3" PostId="8843" RevisionGUID="ad34c7e4-7b6f-43eb-a6d6-9ba1cb9ffb18" CreationDate="2019-05-13T08:31:42.307" UserId="10270" Text="|brdf|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24015" PostHistoryTypeId="5" PostId="8842" RevisionGUID="07297f9d-3fbf-45cf-8def-ae616d81d7d6" CreationDate="2019-05-13T13:02:24.490" UserId="8851" Comment="edited body" Text="A function $f$ on your triangulated surface is an assignment of real numbers on the vertices of the triangulation and therefore $f \in \mathbb{R}^{|\mathcal{V}|}$. According to the continuous theory, the gradient should be a linear (differential) operator that takes a function and spits out a vector field. Hence, in the discrete theory, the gradient should be a linear operator that takes a function $f \in \mathbb{R}^{|\mathcal{V}|}$ and spit out some kind of a discrete version of a vector field. In your case, the vector field is given as an assignment of a vector to each triangle of the triangulation. That is why the discrete gradient operator should be a linear operator, i.e. a linear transformation&#xD;&#xA;$$\text{grad} : \mathbb{R}^{\mathcal{|V|}} \to \mathbb{R}^{3|\mathcal{F}|}$$    &#xD;&#xA;which is represented by a matrix $\text{grad} \in \mathbb{R}^{3|\mathcal{F}| \times |\mathcal{V}|}$. In the continuous theory, the gradient is determined only by local data, i.e. the behaviou of the function near the point at which the gradient is being calculated and by the geometry near that point. Therefore, in the discrete theory, the gradient is determined only by the geometry of one triangle and the values of the function at the triangle's vertices. Let the triangle $j \in  \mathcal{F}$ have vertices denoted (according to the instructions' convention) by $1, 2, 3$. The labels are set up so that the vertices $1,2,3$ define the labels of the opposing edges $\vec{e}_{j_1}, \vec{e}_{j_2}, \vec{e}_{j_3}$, i.e. for the vertex  $i$ the edge opposite to the vertex $i$ is denoted by $\vec{e}_{j_i}$, where the latter vector is oriented so that the vectors form a closed chain of vectors summing to zero in a counterclockwise direction.   &#xD;&#xA;Hence, the gradient can be defined as&#xD;&#xA;$$(\text{grad}\,f)(j) = \frac{1}{2\text{Area}(j)}\, \sum_{i=1}^{3} f_i\, J\vec{e}_{j_i}$$ Or to write it in coordinates, &#xD;&#xA;$$\begin{bmatrix} (\text{grad}\,f)(j)_1\\ (\text{grad}\,f)(j)_2\\(\text{grad}\,f)(j)_3\end{bmatrix} = \frac{1}{2\text{Area}(j)}\left( f_1\, \begin{bmatrix} (Je_{j_1})_1\\ (Je_{j_1})_2\\(Je_{j_1})_3\end{bmatrix} + &#xD;&#xA;f_2\, \begin{bmatrix} (Je_{j_2})_1\\ (Je_{j_2})_2\\(Je_{j_2})_3\end{bmatrix} + f_3\, \begin{bmatrix} (Je_{j_3})_1\\ (Je_{j_3})_2\\(Je_{j_3})_3\end{bmatrix}\right)$$ and in matrix form&#xD;&#xA;$$\begin{bmatrix} (\text{grad}\,f)(j)_1\\ (\text{grad}\,f)(j)_2\\(\text{grad}\,f)(j)_3\end{bmatrix} = \frac{1}{2\text{Area}(j)}\, \begin{bmatrix} (Je_{j_1})_1 &amp;  (Je_{j_2})_1 &amp; (Je_{j_3})_1 \\ (Je_{j_1})_2 &amp; (Je_{j_2})_2 &amp; (Je_{j_3})_2\\(Je_{j_1})_3 &amp; (Je_{j_2})_3 &amp; (Je_{j_3})_3 \end{bmatrix} \begin{bmatrix} f_1\\ f_2\\f_3\end{bmatrix} $$&#xD;&#xA;So, for the matrix $E \in \mathbb{R}^{3|\mathcal{F}|\times|\mathcal{V}|}$ is defined as follows. Let $j$ be a triangle and $i$ one of its vertices. Take the edge $e_{j_i}$ of triangle $j$ opposite to the vertex $i$, and consider the vector $\vec{e}_{j_i}$ along the edge, starting from one vertex, different from $i$, to the other vertex, different from $i$, oriented so that the the vector follows counterclockwise orientation of the boundary of the triangle $j$. Then rotate the vector $\vec{e}_{j_i}$ by $90^{\circ}$ so that it points inside the triangle $j$. Denote this rotated vector by  $$J\vec{e}_{j_i} = \begin{bmatrix} (Je_{j_i})_1\\ (Je_{j_i})_2\\(Je_{j_i})_3\end{bmatrix}$$ Then fill up the following entries of the matrix $E \in \mathbb{R}^{3|\mathcal{F}|\times|\mathcal{V}|}$:   &#xD;&#xA;\begin{align}&#xD;&#xA;&amp;E(j,i) = (Je_{j_i})_1\\&#xD;&#xA;&amp;E(j + |\mathcal{V}|, i) = (Je_{j_i})_2\\&#xD;&#xA;&amp;E(j + 2|\mathcal{V}|, i) = (Je_{j_i})_3&#xD;&#xA;\end{align}  &#xD;&#xA;You can rotate the vector $\vec{e}_{j_i}$ by using the cross-product operation twice. Take two of the edge-vectors of the triangle $j$, say $\vec{e}_{j_1}$ and $\vec{e}_{j_2}$, and calculate the unit normal vector to the triangle $j$:&#xD;&#xA;$$\vec{n}_j = \frac{1}{\|\vec{e}_{j_1} \times \vec{e}_{j_2}\|}\,\Big(\vec{e}_{j_1} \times \vec{e}_{j_2}\Big)$$ It doesn't matter whcih two out of the three edge-vector you would choose, the result is always the same unit normal $\vec{n}_j$. Then&#xD;&#xA;$$J\vec{e}_{j_i} = \vec{n}_j \times \vec{e}_{j_i}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="24020" PostHistoryTypeId="5" PostId="8842" RevisionGUID="54f4cc6b-142c-4520-9026-beb205916427" CreationDate="2019-05-13T22:43:40.147" UserId="8851" Comment="edited body" Text="A function $f$ on your triangulated surface is an assignment of real numbers on the vertices of the triangulation and therefore $f \in \mathbb{R}^{|\mathcal{V}|}$. According to the continuous theory, the gradient should be a linear (differential) operator that takes a function and spits out a vector field. Hence, in the discrete theory, the gradient should be a linear operator that takes a function $f \in \mathbb{R}^{|\mathcal{V}|}$ and spit out some kind of a discrete version of a vector field. In your case, the vector field is given as an assignment of a vector to each triangle of the triangulation. That is why the discrete gradient operator should be a linear operator, i.e. a linear transformation&#xD;&#xA;$$\text{grad} : \mathbb{R}^{\mathcal{|V|}} \to \mathbb{R}^{3|\mathcal{F}|}$$    &#xD;&#xA;which is represented by a matrix $\text{grad} \in \mathbb{R}^{3|\mathcal{F}| \times |\mathcal{V}|}$. In the continuous theory, the gradient is determined only by local data, i.e. the behaviou of the function near the point at which the gradient is being calculated and by the geometry near that point. Therefore, in the discrete theory, the gradient is determined only by the geometry of one triangle and the values of the function at the triangle's vertices. Let the triangle $j \in  \mathcal{F}$ have vertices denoted (according to the instructions' convention) by $1, 2, 3$. The labels are set up so that the vertices $1,2,3$ define the labels of the opposing edges $\vec{e}_{j_1}, \vec{e}_{j_2}, \vec{e}_{j_3}$, i.e. for the vertex  $i$ the edge opposite to the vertex $i$ is denoted by $\vec{e}_{j_i}$, where the latter vector is oriented so that the vectors form a closed chain of vectors summing to zero in a counterclockwise direction.   &#xD;&#xA;Hence, the gradient can be defined as&#xD;&#xA;$$(\text{grad}\,f)(j) = \frac{1}{2\text{Area}(j)}\, \sum_{i=1}^{3} f_i\, J\vec{e}_{j_i}$$ Or to write it in coordinates, &#xD;&#xA;$$\begin{bmatrix} (\text{grad}\,f)(j)_1\\ (\text{grad}\,f)(j)_2\\(\text{grad}\,f)(j)_3\end{bmatrix} = \frac{1}{2\text{Area}(j)}\left( f_1\, \begin{bmatrix} (Je_{j_1})_1\\ (Je_{j_1})_2\\(Je_{j_1})_3\end{bmatrix} + &#xD;&#xA;f_2\, \begin{bmatrix} (Je_{j_2})_1\\ (Je_{j_2})_2\\(Je_{j_2})_3\end{bmatrix} + f_3\, \begin{bmatrix} (Je_{j_3})_1\\ (Je_{j_3})_2\\(Je_{j_3})_3\end{bmatrix}\right)$$ and in matrix form&#xD;&#xA;$$\begin{bmatrix} (\text{grad}\,f)(j)_1\\ (\text{grad}\,f)(j)_2\\(\text{grad}\,f)(j)_3\end{bmatrix} = \frac{1}{2\text{Area}(j)}\, \begin{bmatrix} (Je_{j_1})_1 &amp;  (Je_{j_2})_1 &amp; (Je_{j_3})_1 \\ (Je_{j_1})_2 &amp; (Je_{j_2})_2 &amp; (Je_{j_3})_2\\(Je_{j_1})_3 &amp; (Je_{j_2})_3 &amp; (Je_{j_3})_3 \end{bmatrix} \begin{bmatrix} f_1\\ f_2\\f_3\end{bmatrix} $$&#xD;&#xA;So, for the matrix $E \in \mathbb{R}^{3|\mathcal{F}|\times|\mathcal{V}|}$ is defined as follows. Let $j$ be a triangle and $i$ one of its vertices. Take the edge $e_{j_i}$ of triangle $j$ opposite to the vertex $i$, and consider the vector $\vec{e}_{j_i}$ along the edge, starting from one vertex, different from $i$, to the other vertex, different from $i$, oriented so that the the vector follows counterclockwise orientation of the boundary of the triangle $j$. Then rotate the vector $\vec{e}_{j_i}$ by $90^{\circ}$ so that it points inside the triangle $j$. Denote this rotated vector by  $$J\vec{e}_{j_i} = \begin{bmatrix} (Je_{j_i})_1\\ (Je_{j_i})_2\\(Je_{j_i})_3\end{bmatrix}$$ Then fill up the following entries of the matrix $E \in \mathbb{R}^{3|\mathcal{F}|\times|\mathcal{V}|}$:   &#xD;&#xA;\begin{align}&#xD;&#xA;&amp;E(j,i) = (Je_{j_i})_1\\&#xD;&#xA;&amp;E(j + |\mathcal{F}|, i) = (Je_{j_i})_2\\&#xD;&#xA;&amp;E(j + 2|\mathcal{F}|, i) = (Je_{j_i})_3&#xD;&#xA;\end{align}  &#xD;&#xA;You can rotate the vector $\vec{e}_{j_i}$ by using the cross-product operation twice. Take two of the edge-vectors of the triangle $j$, say $\vec{e}_{j_1}$ and $\vec{e}_{j_2}$, and calculate the unit normal vector to the triangle $j$:&#xD;&#xA;$$\vec{n}_j = \frac{1}{\|\vec{e}_{j_1} \times \vec{e}_{j_2}\|}\,\Big(\vec{e}_{j_1} \times \vec{e}_{j_2}\Big)$$ It doesn't matter whcih two out of the three edge-vector you would choose, the result is always the same unit normal $\vec{n}_j$. Then&#xD;&#xA;$$J\vec{e}_{j_i} = \vec{n}_j \times \vec{e}_{j_i}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="24024" PostHistoryTypeId="5" PostId="8843" RevisionGUID="f30944b4-ce77-4253-9da0-d9a5085400c5" CreationDate="2019-05-15T01:11:38.457" UserId="10270" Comment="deleted 3 characters in body" Text="I'm trying to complete a look-up table for an energy-conserving variation of microfacet GGX as implemented here: https://patapom.com/blog/BRDF/MSBRDFEnergyCompensation/&#xD;&#xA;&#xD;&#xA;I have a (pretty standard) GGX form of the microfacet equation and my white furnace test behaves similar to what is shown elsewhere (i.e., it loses energy as roughness increases).&#xD;&#xA;&#xD;&#xA;However, when I attempt to integrate the brdf and store the total energy in a texture, I get results that are inverse to my expectation - higher roughness yields more total energy in the integral. Some code below (this is done in a compute shader):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float evalSum = 0.0;&#xD;&#xA;const float theta_i = 0.05;&#xD;&#xA;const float phi_i = 0.05;&#xD;&#xA;for (float phiWi = 0.0; phiWi &lt; PI2; phiWi += phi_i)&#xD;&#xA;{&#xD;&#xA;	for (float NoL = 0.0; NoL &lt; 1.0; NoL += theta_i)&#xD;&#xA;	{&#xD;&#xA;		float nohA = 1.0 + NoL * NoV + (1.0 - NoV * NoV) * (1.0 - NoL * NoL) * cos(phiWi);&#xD;&#xA;		float NoH = (NoL + NoV) / sqrt(2.0 * nohA);&#xD;&#xA;			&#xD;&#xA;		float D = Fs.eNDF(NoH, roughness);&#xD;&#xA;		float G = Fs.eGS(NoV, NoL, roughness);&#xD;&#xA;		float Fr = D * G;&#xD;&#xA;			&#xD;&#xA; 		evalSum += Fr * NoL;&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;outBuf[idx] = evalSum * phi_i * theta_i;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here is my texture output:&#xD;&#xA;[![LUT][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm expecting something more like this:&#xD;&#xA;[![energycomp][2]][2]&#xD;&#xA;&#xD;&#xA;As the Y axis goes down, roughness increases, and as the X axis goes to the right, `NoV` (N dot V) increases. Total energy increases with roughness and I also get a strange valley to the energy which I wasn't expecting.&#xD;&#xA;&#xD;&#xA;Here's the two GGX terms:&#xD;&#xA;```&#xD;&#xA;float getNDF(const float NoH, float linearRoughness)&#xD;&#xA;{&#xD;&#xA;	float a2 = linearRoughness * linearRoughness;&#xD;&#xA;	float b = NoH * NoH * (a2 - 1.0) + 1.0;&#xD;&#xA;&#xD;&#xA;	return a2 / (PI * (b * b));&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getGS(const float NoV, const float NoL, const float linearRoughness)&#xD;&#xA;{&#xD;&#xA;	float a2 = linearRoughness * linearRoughness;&#xD;&#xA;	float G_V = NoV + sqrt((NoV - NoV * a2) * NoV + a2);&#xD;&#xA;	float G_L = NoL + sqrt((NoL - NoL * a2) * NoL + a2);&#xD;&#xA;	return rcp(G_V * G_L);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Pretty stumped here. I must be doing the integral wrong somehow because the in-engine renders look correct - the brdf code seems straightforward. Any ideas on why my LUT is not producing the expected result?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Oi3iT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SvxNN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24030" PostHistoryTypeId="2" PostId="8847" RevisionGUID="a0eb8862-c84c-478c-8ce4-e39e575be21c" CreationDate="2019-05-16T14:32:26.623" UserId="228" Text="I'm reading through [this article][1], and more specifically I'm trying to derive the equation that would explain the implementation the following shader (still in the same article):&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    in vec3 localPos;&#xD;&#xA;    &#xD;&#xA;    uniform samplerCube environmentMap;&#xD;&#xA;    uniform float roughness;&#xD;&#xA;    &#xD;&#xA;    const float PI = 3.14159265359;&#xD;&#xA;    &#xD;&#xA;    float RadicalInverse_VdC(uint bits);&#xD;&#xA;    vec2 Hammersley(uint i, uint N);&#xD;&#xA;    vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);&#xD;&#xA;      &#xD;&#xA;    void main()&#xD;&#xA;    {		&#xD;&#xA;        vec3 N = normalize(localPos);    &#xD;&#xA;        vec3 R = N;&#xD;&#xA;        vec3 V = R;&#xD;&#xA;    &#xD;&#xA;        const uint SAMPLE_COUNT = 1024u;&#xD;&#xA;        float totalWeight = 0.0;   &#xD;&#xA;        vec3 prefilteredColor = vec3(0.0);     &#xD;&#xA;        for(uint i = 0u; i &lt; SAMPLE_COUNT; ++i)&#xD;&#xA;        {&#xD;&#xA;            vec2 Xi = Hammersley(i, SAMPLE_COUNT);&#xD;&#xA;            vec3 H  = ImportanceSampleGGX(Xi, N, roughness);&#xD;&#xA;            vec3 L  = normalize(2.0 * dot(V, H) * H - V);&#xD;&#xA;    &#xD;&#xA;            float NdotL = max(dot(N, L), 0.0);&#xD;&#xA;            if(NdotL &gt; 0.0)&#xD;&#xA;            {&#xD;&#xA;                prefilteredColor += texture(environmentMap, L).rgb * NdotL;&#xD;&#xA;                totalWeight      += NdotL;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        prefilteredColor = prefilteredColor / totalWeight;&#xD;&#xA;    &#xD;&#xA;        FragColor = vec4(prefilteredColor, 1.0);&#xD;&#xA;    }  &#xD;&#xA;      &#xD;&#xA;Which is my understanding suppose to implement the computation of the integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I = \int_{\Omega} L(\omega_i)d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However I'm not entirely sure since `NdotL` is also used in the computation so I might be wrong.&#xD;&#xA;&#xD;&#xA;It seems to me the idea is given $N$ to sample a random halfway vector $H$, and based on this we can construct, by reflection, the light direction vector $L$, which would be random as well by construction. The article also mentions that $H$ is sampled from a normal distribution.&#xD;&#xA;&#xD;&#xA;But anyway suppose I have samples $H^{1} ,\ldots, H^{N}$ and therefore $L^{1},\ldots, L^{N}$ samples, the latter I suppose would define $\omega_{i}^{1} \ldots, \omega_{i}^{N}$ (solid angles).&#xD;&#xA;&#xD;&#xA;By importance sampling &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx \frac{1}{N} \sum_{j=1}^{N} \frac{L(\omega_i^{j})}{pdf(\omega_i^{j})} \;\;\;\; (1)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If what I wrote is correct than I don't know where the dot product and the normalization factor&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;W = \sum_{j=1}^{N} N\cdot L^{j}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;comes from, namely how do I go from $(1)$ to&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx &#xD;&#xA;\frac{\sum_{j=1}^{N}L(\omega_i^{j}) N \cdot L^{j}}&#xD;&#xA;{\sum_{j=1}^{N} N \cdot L^{j}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/IBL/Specular-IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="24031" PostHistoryTypeId="1" PostId="8847" RevisionGUID="a0eb8862-c84c-478c-8ce4-e39e575be21c" CreationDate="2019-05-16T14:32:26.623" UserId="228" Text="Pre-filtered environment map, deriving the equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="24032" PostHistoryTypeId="3" PostId="8847" RevisionGUID="a0eb8862-c84c-478c-8ce4-e39e575be21c" CreationDate="2019-05-16T14:32:26.623" UserId="228" Text="|algorithm|lighting|mathematics|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24033" PostHistoryTypeId="2" PostId="8848" RevisionGUID="f7207abb-1c3c-4956-bb79-f83e4b4c5f03" CreationDate="2019-05-16T16:01:19.563" UserId="7622" Text="I have a group of low polygon meshes, with associated normal maps. The normal maps were created by baking from high polygon meshes, which I no longer have access to. Is it possible to recreate anything approximating the original high polygon meshes from my inputs? &#xD;&#xA;&#xD;&#xA;I wouldn't expect the output to have the same kind of mesh structure, but want any kind of mesh that would have the same shape / volume as the original high polygon meshes. I would prefer the output to be a mesh, but it could also work if I could get a point cloud or set of voxels that recreated the volume of the original high polygon mesh. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24034" PostHistoryTypeId="1" PostId="8848" RevisionGUID="f7207abb-1c3c-4956-bb79-f83e4b4c5f03" CreationDate="2019-05-16T16:01:19.563" UserId="7622" Text="Recreate geometry from normal map" ContentLicense="CC BY-SA 4.0" />
  <row Id="24035" PostHistoryTypeId="3" PostId="8848" RevisionGUID="f7207abb-1c3c-4956-bb79-f83e4b4c5f03" CreationDate="2019-05-16T16:01:19.563" UserId="7622" Text="|mesh|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24048" PostHistoryTypeId="5" PostId="8848" RevisionGUID="2b3a387f-e89f-43f1-91dd-95cac2e26bda" CreationDate="2019-05-18T13:41:48.850" UserId="7622" Comment="added 131 characters in body" Text="I have a group of low polygon meshes, with associated normal maps. The normal maps were created by baking from high polygon meshes, which I no longer have access to. Is it possible to recreate anything approximating the original high polygon meshes from my inputs? &#xD;&#xA;&#xD;&#xA;I wouldn't expect the output to have the same kind of mesh structure, but want any kind of mesh that would have the same shape / volume as the original high polygon meshes. I would prefer the output to be a mesh, but it could also work if I could get a point cloud or set of voxels that recreated the volume of the original high polygon mesh. &#xD;&#xA;&#xD;&#xA;Further clarification: the low poly mesh was created manually from the high poly mesh by retopologising and deleting polygons. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24051" PostHistoryTypeId="2" PostId="8852" RevisionGUID="9b80e082-b711-4ec3-ab4a-26451d32b5dc" CreationDate="2019-05-20T12:46:58.460" UserId="10670" Text="This can be achieved without trigonometric functions by scaling down the [incircle](http://mathworld.wolfram.com/Incircle.html) of the triangle.&#xD;&#xA;&#xD;&#xA;`incircle()` computes the incircle of the triangle formed by the vertices `A,B,C`, it returns center and radius as `vec4`. The vertices `X=A,B,C` are then moved inwards by the fraction of their distance to the incircle center (`Q-X`) which is equal to the ratio of desired margin to incircle radius (`m/Q.w`).&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;vec4 incircle(vec3 A, vec3 B, vec3 C) {&#xD;&#xA;	float a = length(B - C), b = length(C - A), c = length(A - B);&#xD;&#xA;	float abc = a + b + c;&#xD;&#xA;	// http://mathworld.wolfram.com/Incenter.html&#xD;&#xA;	vec3 I = (a * A + b * B + c * C) / abc;&#xD;&#xA;	// http://mathworld.wolfram.com/Inradius.html&#xD;&#xA;	float r = 0.5&#xD;&#xA;			* sqrt((-a + b + c) * (a - b + c) * (a + b - c) / abc);&#xD;&#xA;	return vec4(I, r);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 A,B,C; // vertices&#xD;&#xA;float m; // margin&#xD;&#xA;vec4 Q = incircle(A,B,C);&#xD;&#xA;A += clamp(m / Q.w, 0.0, 1.0) * (Q.xyz - A);&#xD;&#xA;B += clamp(m / Q.w, 0.0, 1.0) * (Q.xyz - B);&#xD;&#xA;C += clamp(m / Q.w, 0.0, 1.0) * (Q.xyz - C);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24055" PostHistoryTypeId="2" PostId="8854" RevisionGUID="ccbf10d3-151c-46c4-905c-7de8fad6316c" CreationDate="2019-05-21T09:54:14.010" UserId="10674" Text="I spent quite some time looking for books on rasterization of vector graphics and related challenges. The best I found is &quot;Raster Tragedy in Low Resolution&quot;,which is old and focused on fonts. There are assorted papers on new renderer here and there, but nothing comprehensive.&#xD;&#xA;&#xD;&#xA;Is ththere something good I missed? " ContentLicense="CC BY-SA 4.0" />
  <row Id="24056" PostHistoryTypeId="1" PostId="8854" RevisionGUID="ccbf10d3-151c-46c4-905c-7de8fad6316c" CreationDate="2019-05-21T09:54:14.010" UserId="10674" Text="Any good sources on advaced/special rasterization algorithms and theory behind them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24057" PostHistoryTypeId="3" PostId="8854" RevisionGUID="ccbf10d3-151c-46c4-905c-7de8fad6316c" CreationDate="2019-05-21T09:54:14.010" UserId="10674" Text="|vector-graphics|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24058" PostHistoryTypeId="4" PostId="8854" RevisionGUID="67a21ade-fd1f-47a2-8c4f-cc47ff35f990" CreationDate="2019-05-21T10:39:48.427" UserId="10674" Comment="edited title" Text="Any good sources on advaced/special rasterization algorithms and techniques and theory behind them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24059" PostHistoryTypeId="33" PostId="8847" RevisionGUID="ca76c0e7-c763-4b98-9e07-40d40817c310" CreationDate="2019-05-21T14:29:54.163" UserId="228" Comment="55" />
  <row Id="24061" PostHistoryTypeId="50" PostId="8779" RevisionGUID="8d24b8d8-0de0-4836-83a5-707a58cfcc88" CreationDate="2019-05-22T13:03:55.820" UserId="-1" />
  <row Id="24063" PostHistoryTypeId="5" PostId="8765" RevisionGUID="6e7e6a2d-17d5-4584-b7f1-846d0e1b18a1" CreationDate="2019-05-22T17:53:32.360" UserId="10191" Comment="added 1 character in body" Text="I am trying to reproduce the results obtained by Dahm et al. in the paper [Learning Light Transport the Reinforced Way][1]. &lt;br&gt;&#xD;&#xA;This method takes advantage of the similarity between the Bellman equation (Q-Learning) and the rendering equation. &lt;br&gt;&#xD;&#xA;Here's the overview of the code authors inserted in the first version of their paper: &lt;br&gt;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Question 1**&#xD;&#xA;&#xD;&#xA;What is, in the first function, `idxPrev`? Intuition suggests it is the index of the previous cell. &lt;br&gt;&#xD;&#xA;EDIT: `ray.o` is probably the origin. &lt;br&gt;&#xD;&#xA;Moreover, in the same function, I understand that `getLastAttenuation()` returns the color of `idxCurr`. How is getLastAttenuation calculated?&#xD;&#xA;&#xD;&#xA;**Question 2**&#xD;&#xA;&#xD;&#xA;The action space is discretized, apparently, dividing the hemisphere built on the hitting point in different stratums. According to what I understand, the Q-Learning algorithm finds the best action (so the best stratum) for each cell in the space, and then a ray is scattered randomly in that stratum. But a stratum covers 360 degrees, so I don't see how this is helpful to scattered a ray towards the light. &lt;br&gt;&#xD;&#xA;In the function `sampleScatteringDIrFromQtable()`, the PDF is calculated based on the `ps` (not clear) multiplied by the number of patches. So, the action is related to circular stratums of the hemisphere, or the number of patches?&#xD;&#xA;&#xD;&#xA;**UPDATE:** &lt;br&gt;&#xD;&#xA;**Question 3**&#xD;&#xA;&#xD;&#xA;I divide the hemispheres over the hitting points in 24 equally-sized patches. Then I scatter rays, for now, not based on a uniform distribution on the hemisphere, but through the center of these 24 equally-sized patched. In this case, what would the PDF be? &#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/pdf/1701.07403v1.pdf?utm_content=buffer5b1d2&amp;utm_medium=social&amp;utm_source=twitter.com&amp;utm_campaign=buffer&#xD;&#xA;  [2]: https://i.stack.imgur.com/VEMXA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24065" PostHistoryTypeId="2" PostId="8855" RevisionGUID="4c29b516-dbc1-4a20-886e-05942f54a4dc" CreationDate="2019-05-23T00:53:49.707" UserId="10685" Text="For a Lambertian surface, the radiance at a point is&#xD;&#xA;&#xD;&#xA;$$L = \frac{\alpha}{\pi}\cos\theta_i E_0$$&#xD;&#xA;&#xD;&#xA;If we have an infinite flat surface, albedo = 1, illuminated directly normal, then we get &#xD;&#xA;&#xD;&#xA;$$L = \frac{E_0}{\pi}$$&#xD;&#xA;&#xD;&#xA;But now suppose we are sitting very close to the surface. The surface occupies $2\pi$ sr of our view, so the irradiance we measure is&#xD;&#xA;&#xD;&#xA;$$E_r = 2\pi L = 2E_0$$&#xD;&#xA;&#xD;&#xA;Is this correct? I was expecting to get $E_0$ back again. $2E_0$ makes it feel like we're violating the conservation of energy or something." ContentLicense="CC BY-SA 4.0" />
  <row Id="24066" PostHistoryTypeId="1" PostId="8855" RevisionGUID="4c29b516-dbc1-4a20-886e-05942f54a4dc" CreationDate="2019-05-23T00:53:49.707" UserId="10685" Text="Factor of 2 converting radiance to irradiance" ContentLicense="CC BY-SA 4.0" />
  <row Id="24067" PostHistoryTypeId="3" PostId="8855" RevisionGUID="4c29b516-dbc1-4a20-886e-05942f54a4dc" CreationDate="2019-05-23T00:53:49.707" UserId="10685" Text="|global-illumination|reflection|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24069" PostHistoryTypeId="2" PostId="8856" RevisionGUID="d86f3253-340c-4f0b-97cb-a0d2d8496e00" CreationDate="2019-05-23T01:57:06.720" UserId="6046" Text="I don't really understand what are you doing. I think your first equation shouldn't have a cos factor in it.&#xD;&#xA;&#xD;&#xA;We have the relation,&#xD;&#xA;&#xD;&#xA;$BRDF = dL_r / dE_i$&#xD;&#xA;&#xD;&#xA;That is the brdf is the ratio of reflected radiance to incoming &quot;irradiance&quot;. Re-arranging this gives us,&#xD;&#xA;&#xD;&#xA;$ dL_r =  BRDF * dE_i$&#xD;&#xA;&#xD;&#xA;For diffuse surfaces we know,&#xD;&#xA;&#xD;&#xA;$BRDF = \alpha/\pi$&#xD;&#xA;&#xD;&#xA;Substituting in above equation we have,&#xD;&#xA;&#xD;&#xA;$dL_r = \alpha/\pi * dE_i$&#xD;&#xA;&#xD;&#xA;Irrespective of what angle we view, the radiance is the same. Now for a diffuse surface with albedo = 1 we have what you said,&#xD;&#xA;&#xD;&#xA;$dL_r = dE_i/\pi$&#xD;&#xA;&#xD;&#xA;Now in order to measure Irradiance, we can use the relation,&#xD;&#xA;&#xD;&#xA;$E = \int_{2\pi} L \cos(\theta) d\omega$&#xD;&#xA;&#xD;&#xA;$E = \displaystyle\int_{\phi = 0}^{2\pi} \displaystyle\int_{\theta = 0}^{\pi/2} L \cos(\theta) \sin(\theta) d\theta d\phi$&#xD;&#xA;&#xD;&#xA;$E = E/\pi * \pi$&#xD;&#xA;&#xD;&#xA;$E = E$&#xD;&#xA;&#xD;&#xA;So you got back the same irradiance.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24070" PostHistoryTypeId="5" PostId="8847" RevisionGUID="c6803f19-a38f-4c03-8ddd-cdc4a9b1d8c1" CreationDate="2019-05-23T09:53:32.697" UserId="228" Comment="added 488 characters in body" Text="I'm reading through [this article][1], and more specifically I'm trying to derive the equation that would explain the implementation the following shader (still in the same article):&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    in vec3 localPos;&#xD;&#xA;    &#xD;&#xA;    uniform samplerCube environmentMap;&#xD;&#xA;    uniform float roughness;&#xD;&#xA;    &#xD;&#xA;    const float PI = 3.14159265359;&#xD;&#xA;    &#xD;&#xA;    float RadicalInverse_VdC(uint bits);&#xD;&#xA;    vec2 Hammersley(uint i, uint N);&#xD;&#xA;    vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);&#xD;&#xA;      &#xD;&#xA;    void main()&#xD;&#xA;    {		&#xD;&#xA;        vec3 N = normalize(localPos);    &#xD;&#xA;        vec3 R = N;&#xD;&#xA;        vec3 V = R;&#xD;&#xA;    &#xD;&#xA;        const uint SAMPLE_COUNT = 1024u;&#xD;&#xA;        float totalWeight = 0.0;   &#xD;&#xA;        vec3 prefilteredColor = vec3(0.0);     &#xD;&#xA;        for(uint i = 0u; i &lt; SAMPLE_COUNT; ++i)&#xD;&#xA;        {&#xD;&#xA;            vec2 Xi = Hammersley(i, SAMPLE_COUNT);&#xD;&#xA;            vec3 H  = ImportanceSampleGGX(Xi, N, roughness);&#xD;&#xA;            vec3 L  = normalize(2.0 * dot(V, H) * H - V);&#xD;&#xA;    &#xD;&#xA;            float NdotL = max(dot(N, L), 0.0);&#xD;&#xA;            if(NdotL &gt; 0.0)&#xD;&#xA;            {&#xD;&#xA;                prefilteredColor += texture(environmentMap, L).rgb * NdotL;&#xD;&#xA;                totalWeight      += NdotL;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        prefilteredColor = prefilteredColor / totalWeight;&#xD;&#xA;    &#xD;&#xA;        FragColor = vec4(prefilteredColor, 1.0);&#xD;&#xA;    }  &#xD;&#xA;      &#xD;&#xA;Which is my understanding suppose to implement the computation of the integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I = \int_{\Omega} L(\omega_i)d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However I'm not entirely sure since `NdotL` is also used in the computation so I might be wrong.&#xD;&#xA;&#xD;&#xA;It seems to me the idea is given $N$ to sample a random halfway vector $H$, and based on this we can construct, by reflection, the light direction vector $L$, which would be random as well by construction. The article also mentions that $H$ is sampled from a normal distribution.&#xD;&#xA;&#xD;&#xA;But anyway suppose I have samples $H^{1} ,\ldots, H^{N}$ and therefore $L^{1},\ldots, L^{N}$ samples, the latter I suppose would define $\omega_{i}^{1} \ldots, \omega_{i}^{N}$ (solid angles).&#xD;&#xA;&#xD;&#xA;By importance sampling &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx \frac{1}{N} \sum_{j=1}^{N} \frac{L(\omega_i^{j})}{pdf(\omega_i^{j})} \;\;\;\; (1)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If what I wrote is correct than I don't know where the dot product and the normalization factor&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;W = \sum_{j=1}^{N} N\cdot L^{j}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;comes from, namely how do I go from $(1)$ to&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx &#xD;&#xA;\frac{\sum_{j=1}^{N}L(\omega_i^{j}) N \cdot L^{j}}&#xD;&#xA;{\sum_{j=1}^{N} N \cdot L^{j}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Update**: I'm pretty sure many of you know this already, but the shader above is for a pre-filtered environt map. Which means in this context the actual integral should be given by&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I(\mathcal{N}) = \int_{\Omega} L(\omega_i) N \cdot L d\omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This explains the factor $N \cdot L$ in the shader, the distribution function used is the GGX distribution, I assume plugging this stuff together might give me the formula.&#xD;&#xA;&#xD;&#xA;Just updating because it might give a better clue.&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/IBL/Specular-IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="24071" PostHistoryTypeId="5" PostId="8847" RevisionGUID="58d8aed1-f280-47f5-a28a-9bd7ccf0af59" CreationDate="2019-05-23T11:44:53.870" UserId="228" Comment="deleted 10 characters in body" Text="I'm reading through [this article][1], and more specifically I'm trying to derive the equation that would explain the implementation the following shader (still in the same article):&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    in vec3 localPos;&#xD;&#xA;    &#xD;&#xA;    uniform samplerCube environmentMap;&#xD;&#xA;    uniform float roughness;&#xD;&#xA;    &#xD;&#xA;    const float PI = 3.14159265359;&#xD;&#xA;    &#xD;&#xA;    float RadicalInverse_VdC(uint bits);&#xD;&#xA;    vec2 Hammersley(uint i, uint N);&#xD;&#xA;    vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);&#xD;&#xA;      &#xD;&#xA;    void main()&#xD;&#xA;    {		&#xD;&#xA;        vec3 N = normalize(localPos);    &#xD;&#xA;        vec3 R = N;&#xD;&#xA;        vec3 V = R;&#xD;&#xA;    &#xD;&#xA;        const uint SAMPLE_COUNT = 1024u;&#xD;&#xA;        float totalWeight = 0.0;   &#xD;&#xA;        vec3 prefilteredColor = vec3(0.0);     &#xD;&#xA;        for(uint i = 0u; i &lt; SAMPLE_COUNT; ++i)&#xD;&#xA;        {&#xD;&#xA;            vec2 Xi = Hammersley(i, SAMPLE_COUNT);&#xD;&#xA;            vec3 H  = ImportanceSampleGGX(Xi, N, roughness);&#xD;&#xA;            vec3 L  = normalize(2.0 * dot(V, H) * H - V);&#xD;&#xA;    &#xD;&#xA;            float NdotL = max(dot(N, L), 0.0);&#xD;&#xA;            if(NdotL &gt; 0.0)&#xD;&#xA;            {&#xD;&#xA;                prefilteredColor += texture(environmentMap, L).rgb * NdotL;&#xD;&#xA;                totalWeight      += NdotL;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        prefilteredColor = prefilteredColor / totalWeight;&#xD;&#xA;    &#xD;&#xA;        FragColor = vec4(prefilteredColor, 1.0);&#xD;&#xA;    }  &#xD;&#xA;      &#xD;&#xA;Which is my understanding suppose to implement the computation of the integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I = \int_{\Omega} L(\omega_i)d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However I'm not entirely sure since `NdotL` is also used in the computation so I might be wrong.&#xD;&#xA;&#xD;&#xA;It seems to me the idea is given $N$ to sample a random halfway vector $H$, and based on this we can construct, by reflection, the light direction vector $L$, which would be random as well by construction. The article also mentions that $H$ is sampled from a normal distribution.&#xD;&#xA;&#xD;&#xA;But anyway suppose I have samples $H^{1} ,\ldots, H^{N}$ and therefore $L^{1},\ldots, L^{N}$ samples, the latter I suppose would define $\omega_{i}^{1} \ldots, \omega_{i}^{N}$ (solid angles).&#xD;&#xA;&#xD;&#xA;By importance sampling &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx \frac{1}{N} \sum_{j=1}^{N} \frac{L(\omega_i^{j})}{pdf(\omega_i^{j})} \;\;\;\; (1)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If what I wrote is correct than I don't know where the dot product and the normalization factor&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;W = \sum_{j=1}^{N} N\cdot L^{j}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;comes from, namely how do I go from $(1)$ to&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx &#xD;&#xA;\frac{\sum_{j=1}^{N}L(\omega_i^{j}) N \cdot L^{j}}&#xD;&#xA;{\sum_{j=1}^{N} N \cdot L^{j}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Update**: I'm pretty sure many of you know this already, but the shader above is for a pre-filtered environt map. Which means in this context the actual integral should be given by&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I(N) = \int_{\Omega} L(\omega_i) N \cdot L d\omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This explains the factor $N \cdot L$ in the shader, the distribution function used is the GGX distribution, I assume plugging this stuff together might give me the formula.&#xD;&#xA;&#xD;&#xA;Just updating because it might give a better clue.&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/IBL/Specular-IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="24075" PostHistoryTypeId="2" PostId="8857" RevisionGUID="396e7117-e030-4f06-9f4e-69783109017b" CreationDate="2019-05-25T20:58:56.210" UserId="10698" Text="I am using the Bresenham algorithm from wikipedia:&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;     plotLine(x0,y0, x1,y1)&#xD;&#xA;          dx = x1 - x0&#xD;&#xA;          dy = y1 - y0&#xD;&#xA;          D = 2*dy - dx&#xD;&#xA;          y = y0&#xD;&#xA;    &#xD;&#xA;         for x from x0 to x1&#xD;&#xA;            plot(x,y)&#xD;&#xA;            if D &gt; 0&#xD;&#xA;               y = y + 1&#xD;&#xA;               D = D - 2*dx&#xD;&#xA;            end if&#xD;&#xA;            D = D + 2*dy&#xD;&#xA;&#xD;&#xA;I have the following two points:&#xD;&#xA;&#xD;&#xA;    P1 = (10, 120) and P2 = (18, 117)&#xD;&#xA;&#xD;&#xA;I wrote a C program to run the algorithm and I got as output:&#xD;&#xA;&#xD;&#xA;    ePlot the following points: &#xD;&#xA;    10, 120&#xD;&#xA;    11, 120&#xD;&#xA;    12, 120&#xD;&#xA;    13, 120&#xD;&#xA;    14, 120&#xD;&#xA;    15, 120&#xD;&#xA;    16, 120&#xD;&#xA;    17, 120&#xD;&#xA;&#xD;&#xA;Which is totally wrong, is there any other version of this algorithm which works for this scenario or it does not exist?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24076" PostHistoryTypeId="1" PostId="8857" RevisionGUID="396e7117-e030-4f06-9f4e-69783109017b" CreationDate="2019-05-25T20:58:56.210" UserId="10698" Text="Why the Bresenham's algorithm does not work for those two points?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24077" PostHistoryTypeId="3" PostId="8857" RevisionGUID="396e7117-e030-4f06-9f4e-69783109017b" CreationDate="2019-05-25T20:58:56.210" UserId="10698" Text="|algorithm|computational-geometry|offline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24078" PostHistoryTypeId="50" PostId="8790" RevisionGUID="329ffe34-86a7-46ad-b6a1-fdbad3effb0f" CreationDate="2019-05-26T06:03:00.353" UserId="-1" />
  <row Id="24080" PostHistoryTypeId="2" PostId="8858" RevisionGUID="214d7733-4321-468b-b121-000546046778" CreationDate="2019-05-27T13:23:42.247" UserId="2750" Text="I [found out][1] that I should use spherical linear interpolation to blend two poses of a joint. I cannot find what to do if I have hundreds of poses to blend except applying the SLERP iteratively.&#xD;&#xA;&#xD;&#xA;What are the default methods to interpolate between multiple skeletal poses? For example, which algorithms are used by Unity3D, UE4, 3DS Max, Maya, etc? How do they solve the problem of rotation non-commutativity?&#xD;&#xA;&#xD;&#xA;I'm looking for an analytical well-differentiable (with respect to blending weights) formula if one exists.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/a/5814107/1305036" ContentLicense="CC BY-SA 4.0" />
  <row Id="24081" PostHistoryTypeId="1" PostId="8858" RevisionGUID="214d7733-4321-468b-b121-000546046778" CreationDate="2019-05-27T13:23:42.247" UserId="2750" Text="How to calculate interpolation between multiple skeleton poses?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24082" PostHistoryTypeId="3" PostId="8858" RevisionGUID="214d7733-4321-468b-b121-000546046778" CreationDate="2019-05-27T13:23:42.247" UserId="2750" Text="|transformations|mathematics|interpolation|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24083" PostHistoryTypeId="2" PostId="8859" RevisionGUID="50cd80da-b089-49f4-8819-4eb21619b93d" CreationDate="2019-05-27T14:01:05.097" UserId="9083" Text="I'm studying Microsoft Windows Bitmap File Format, extension BMP.  &#xD;&#xA;I'm curious to know why scanlines are stored on file from bottom to up, the last scanline on image is the first line on file and the first scanline on image is the last line on file.  &#xD;&#xA;The documents that I have read do not explain it.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24084" PostHistoryTypeId="1" PostId="8859" RevisionGUID="50cd80da-b089-49f4-8819-4eb21619b93d" CreationDate="2019-05-27T14:01:05.097" UserId="9083" Text="Why BMP file format last line of image is first line on file?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24085" PostHistoryTypeId="3" PostId="8859" RevisionGUID="50cd80da-b089-49f4-8819-4eb21619b93d" CreationDate="2019-05-27T14:01:05.097" UserId="9083" Text="|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24086" PostHistoryTypeId="5" PostId="8859" RevisionGUID="57820b3a-77b3-4ccc-b39a-a8e841779f90" CreationDate="2019-05-27T14:08:38.913" UserId="9083" Comment="comma" Text="I'm studying Microsoft Windows Bitmap File Format, extension BMP.  &#xD;&#xA;I'm curious to know why scanlines are stored on file from bottom to up: the last scanline on image is the first line on file and the first scanline on image is the last line on file.  &#xD;&#xA;The documents that I have read do not explain it.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24087" PostHistoryTypeId="5" PostId="8847" RevisionGUID="5de279b9-5fff-4371-9159-fab88a4eed8c" CreationDate="2019-05-27T15:22:01.327" UserId="228" Comment="added 3 characters in body" Text="I'm reading through [this article][1], and more specifically I'm trying to derive the equation that would explain the implementation the following shader (still in the same article):&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    in vec3 localPos;&#xD;&#xA;    &#xD;&#xA;    uniform samplerCube environmentMap;&#xD;&#xA;    uniform float roughness;&#xD;&#xA;    &#xD;&#xA;    const float PI = 3.14159265359;&#xD;&#xA;    &#xD;&#xA;    float RadicalInverse_VdC(uint bits);&#xD;&#xA;    vec2 Hammersley(uint i, uint N);&#xD;&#xA;    vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);&#xD;&#xA;      &#xD;&#xA;    void main()&#xD;&#xA;    {		&#xD;&#xA;        vec3 N = normalize(localPos);    &#xD;&#xA;        vec3 R = N;&#xD;&#xA;        vec3 V = R;&#xD;&#xA;    &#xD;&#xA;        const uint SAMPLE_COUNT = 1024u;&#xD;&#xA;        float totalWeight = 0.0;   &#xD;&#xA;        vec3 prefilteredColor = vec3(0.0);     &#xD;&#xA;        for(uint i = 0u; i &lt; SAMPLE_COUNT; ++i)&#xD;&#xA;        {&#xD;&#xA;            vec2 Xi = Hammersley(i, SAMPLE_COUNT);&#xD;&#xA;            vec3 H  = ImportanceSampleGGX(Xi, N, roughness);&#xD;&#xA;            vec3 L  = normalize(2.0 * dot(V, H) * H - V);&#xD;&#xA;    &#xD;&#xA;            float NdotL = max(dot(N, L), 0.0);&#xD;&#xA;            if(NdotL &gt; 0.0)&#xD;&#xA;            {&#xD;&#xA;                prefilteredColor += texture(environmentMap, L).rgb * NdotL;&#xD;&#xA;                totalWeight      += NdotL;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        prefilteredColor = prefilteredColor / totalWeight;&#xD;&#xA;    &#xD;&#xA;        FragColor = vec4(prefilteredColor, 1.0);&#xD;&#xA;    }  &#xD;&#xA;      &#xD;&#xA;Which is my understanding suppose to implement the computation of the integral&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I = \int_{\Omega} L(\omega_i)d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However I'm not entirely sure since `NdotL` is also used in the computation so I might be wrong.&#xD;&#xA;&#xD;&#xA;It seems to me the idea is given $N$ to sample a random halfway vector $H$, and based on this we can construct, by reflection, the light direction vector $L$, which would be random as well by construction. The article also mentions that $H$ is sampled from a normal distribution.&#xD;&#xA;&#xD;&#xA;But anyway suppose I have samples $H^{1} ,\ldots, H^{N}$ and therefore $L^{1},\ldots, L^{N}$ samples, the latter I suppose would define $\omega_{i}^{1} \ldots, \omega_{i}^{N}$ (solid angles).&#xD;&#xA;&#xD;&#xA;By importance sampling &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx \frac{1}{N} \sum_{j=1}^{N} \frac{L(\omega_i^{j})}{pdf(\omega_i^{j})} \;\;\;\; (1)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If what I wrote is correct than I don't know where the dot product and the normalization factor&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;W = \sum_{j=1}^{N} N\cdot L^{j}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;comes from, namely how do I go from $(1)$ to&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I \approx &#xD;&#xA;\frac{\sum_{j=1}^{N}L(\omega_i^{j}) N \cdot L^{j}}&#xD;&#xA;{\sum_{j=1}^{N} N \cdot L^{j}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Update**: I'm pretty sure many of you know this already, but the shader above is for a pre-filtered environment map. Which means in this context the actual integral should be given by&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;I(N) = \int_{\Omega} L(\omega_i) N \cdot L d\omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This explains the factor $N \cdot L$ in the shader, the distribution function used is the GGX distribution, I assume plugging this stuff together might give me the formula.&#xD;&#xA;&#xD;&#xA;Just updating because it might give a better clue.&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/IBL/Specular-IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="24088" PostHistoryTypeId="2" PostId="8860" RevisionGUID="1b68325f-be6e-4567-aa6e-487fe9aa7fda" CreationDate="2019-05-28T02:11:38.067" UserId="10707" Text="One rasterization method I like is Haar wavelet rasterization:&#xD;&#xA;&#xD;&#xA;http://faculty.cs.tamu.edu/schaefer/research/wavelet_rasterization.pdf&#xD;&#xA;&#xD;&#xA;It can render polygons and Bezier curve shape and good for different resolution. I not see this algorithm in computer graphics books." ContentLicense="CC BY-SA 4.0" />
  <row Id="24089" PostHistoryTypeId="2" PostId="8861" RevisionGUID="c7ce1b1a-4c0a-4c32-8f5e-a9a94ee8f40e" CreationDate="2019-05-28T02:32:01.300" UserId="10708" Text="&gt; &gt; Here's a quote from Petzold:&#xD;&#xA;&gt; &#xD;&#xA;&gt; So, in DIBs, the bottom row of the image is the first row of the file,&#xD;&#xA;&gt; and the top row of the image is the last row in the file. This is&#xD;&#xA;&gt; called a bottom-up organization. Because this organization is&#xD;&#xA;&gt; counterintuitive, you may ask why it's done this way.&#xD;&#xA;&gt; &#xD;&#xA;&gt; Well, it all goes back to the OS/2 Presentation Manager. Someone at&#xD;&#xA;&gt; IBM decided that all coordinate systems in PM—including those for&#xD;&#xA;&gt; windows, graphics, and bitmaps—should be consistent. This provoked a&#xD;&#xA;&gt; debate: Most people, including programmers who have worked with&#xD;&#xA;&gt; full-screen text programming or windowing environments, think in terms&#xD;&#xA;&gt; of vertical coordinates that increase going down the screen. However,&#xD;&#xA;&gt; hardcore computer graphics programmers approach the video display from&#xD;&#xA;&gt; a perspective that originates in the mathematics of analytic geometry.&#xD;&#xA;&gt; This involves a rectangular (or Cartesian) coordinate system where&#xD;&#xA;&gt; increasing vertical coordinates go up in space.&#xD;&#xA;&gt; &#xD;&#xA;&gt; In short, the mathematicians won. Everything in PM was saddled with a&#xD;&#xA;&gt; bottom-left origin, including window coordinates. And that's how DIBs&#xD;&#xA;&gt; came to be this way.&#xD;&#xA;&gt; &#xD;&#xA;&gt; Source: Charles Petzold, Programming for Windows 5th Edition, Chapter&#xD;&#xA;&gt; 15.&#xD;&#xA;&#xD;&#xA;from&#xD;&#xA;https://stackoverflow.com/questions/8346115/why-are-bmps-stored-upside-down" ContentLicense="CC BY-SA 4.0" />
  <row Id="24091" PostHistoryTypeId="5" PostId="8861" RevisionGUID="49bec664-4a7d-4533-850a-f9e4bb919d2e" CreationDate="2019-05-28T09:44:03.240" UserId="6" Comment="added 10 characters in body" Text="&gt; Here's a quote from Petzold:&#xD;&#xA;&gt; &#xD;&#xA;&gt; &gt; So, in DIBs, the bottom row of the image is the first row of the file,&#xD;&#xA;&gt; and the top row of the image is the last row in the file. This is&#xD;&#xA;&gt; called a bottom-up organization. Because this organization is&#xD;&#xA;&gt; counterintuitive, you may ask why it's done this way.&#xD;&#xA;&gt; &#xD;&#xA;&gt; &gt; Well, it all goes back to the OS/2 Presentation Manager. Someone at&#xD;&#xA;&gt; IBM decided that all coordinate systems in PM—including those for&#xD;&#xA;&gt; windows, graphics, and bitmaps—should be consistent. This provoked a&#xD;&#xA;&gt; debate: Most people, including programmers who have worked with&#xD;&#xA;&gt; full-screen text programming or windowing environments, think in terms&#xD;&#xA;&gt; of vertical coordinates that increase going down the screen. However,&#xD;&#xA;&gt; hardcore computer graphics programmers approach the video display from&#xD;&#xA;&gt; a perspective that originates in the mathematics of analytic geometry.&#xD;&#xA;&gt; This involves a rectangular (or Cartesian) coordinate system where&#xD;&#xA;&gt; increasing vertical coordinates go up in space.&#xD;&#xA;&gt; &#xD;&#xA;&gt; &gt; In short, the mathematicians won. Everything in PM was saddled with a&#xD;&#xA;&gt; bottom-left origin, including window coordinates. And that's how DIBs&#xD;&#xA;&gt; came to be this way.&#xD;&#xA;&gt; &#xD;&#xA;&gt; **Source:** Charles Petzold, *Programming for Windows 5th Edition*, Chapter&#xD;&#xA;&gt; 15.&#xD;&#xA;&#xD;&#xA;from&#xD;&#xA;https://stackoverflow.com/questions/8346115/why-are-bmps-stored-upside-down" ContentLicense="CC BY-SA 4.0" />
  <row Id="24092" PostHistoryTypeId="2" PostId="8863" RevisionGUID="a3f818d8-12a6-45bc-b9d4-50d24cd93bb9" CreationDate="2019-05-28T10:16:43.690" UserId="10710" Text="I did not know where to ask, I will try it here. I work in a local planetarium and I wonder if it is possible to edit an image in such way, that when projected on spherical cupola (diameter 8 m), it would not look too much distorted. Is there any easy way to edit an image this way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24093" PostHistoryTypeId="1" PostId="8863" RevisionGUID="a3f818d8-12a6-45bc-b9d4-50d24cd93bb9" CreationDate="2019-05-28T10:16:43.690" UserId="10710" Text="How to project an image on spherical surface with least possible distortion" ContentLicense="CC BY-SA 4.0" />
  <row Id="24094" PostHistoryTypeId="3" PostId="8863" RevisionGUID="a3f818d8-12a6-45bc-b9d4-50d24cd93bb9" CreationDate="2019-05-28T10:16:43.690" UserId="10710" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24098" PostHistoryTypeId="2" PostId="8865" RevisionGUID="caaccedd-4a8a-47f5-bac9-c030d00446e1" CreationDate="2019-05-28T21:50:30.633" UserId="10712" Text="Let's say I had a binary image (i.e. only contains black and white pixels). &#xD;&#xA;&#xD;&#xA;For example, this one:&#xD;&#xA;&#xD;&#xA;[![face][1]][1]&#xD;&#xA;&#xD;&#xA;How would I make all the lines in this image dotted or dashed?&#xD;&#xA;&#xD;&#xA;In other words, the eyes would be left alone, but everything else (including the circle on the nose) would become dotted or dashed.&#xD;&#xA;&#xD;&#xA;I know that, for example, kernels can be used to blur, sharpen, etc - but I don't know if a kernel could do this. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zbw7g.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24099" PostHistoryTypeId="1" PostId="8865" RevisionGUID="caaccedd-4a8a-47f5-bac9-c030d00446e1" CreationDate="2019-05-28T21:50:30.633" UserId="10712" Text="How to make the lines of a (binary) image dotted or dashed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24100" PostHistoryTypeId="3" PostId="8865" RevisionGUID="caaccedd-4a8a-47f5-bac9-c030d00446e1" CreationDate="2019-05-28T21:50:30.633" UserId="10712" Text="|image-processing|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24101" PostHistoryTypeId="50" PostId="8431" RevisionGUID="dc8a5db5-8163-451f-90ba-a70a4d35ce13" CreationDate="2019-05-28T23:03:20.453" UserId="-1" />
  <row Id="24102" PostHistoryTypeId="2" PostId="8866" RevisionGUID="ff30ffc5-1c17-42bd-80dc-65f773a04f93" CreationDate="2019-05-29T09:35:39.567" UserId="7008" Text="A kernel can (probably) not help you, because they are very localized. However, you need to know, where a line is, and that may be out of the reach of a kernel (e.g. a 3x3 Pixel kernel would only be able to detect a line 3 pixels wide. Is that meeting your demands of being a line?)&#xD;&#xA;&#xD;&#xA;Rather you need to define, when a line is a line with the information you have. For simplicity you could say &quot;Having at least 5 pixels in either X or Y direction black next to each other, but not having any pixels black in any other direction makes a line&quot;. Then you can scan the image for those lines and store them in some data structure. &#xD;&#xA;&#xD;&#xA;Now that you have your lines figured out, you need to define what to do with them, e.g. &quot;Every line longer than 20 pixels needs to be dashed, every other line dotted&quot;. &#xD;&#xA;Also &quot;A dashed line has a white pixel at every third and fourth pixel, except the first and last pixel may not be white&quot; and &quot;A dotted line has a white pixel at every other pixel, except the first and last pixel may not be white&quot;. Since you know the lines, you either know or can check the lines, and therefore you can edit them one by one to be dotted or dashed.&#xD;&#xA;&#xD;&#xA;This is of course a pretty high level description, but you don't give much to go on with your question. Perhaps though, this suffices for you to get started.&#xD;&#xA;&#xD;&#xA;The hard part of course is to identify lines. Try to think what makes a line for you (e.g. direction, thickness/width vs height), what edge cases you may have (a single pixel or square block of pixels) and then you can go about finding them in your image. Note that in a rasterized image, non horizontal and non vertical lines will have &quot;strange&quot; patterns of how they fill the image and you will have to decide how to treat those on your own. &#xD;&#xA;Also, make sure to not have any lines stored twice (or more) when scanning, because your dotting / dashing process could possibly lead to an unwanted outcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="24103" PostHistoryTypeId="2" PostId="8867" RevisionGUID="493e51aa-ca99-49ce-b2a2-ef53952cf583" CreationDate="2019-05-29T10:01:13.723" UserId="137" Text="The simplest way is to use n-way nlerp (normalized lerp) instead. It does mean slight inaccuracies in the blend but careful (manual) tweaking of the weights and good key pose selection can take care of that.&#xD;&#xA;&#xD;&#xA;`nlerp` will approximate `slerp` when the key poses are close to each other. So you will very likely get away with not tweaking the weights at all in most cases." ContentLicense="CC BY-SA 4.0" />
  <row Id="24104" PostHistoryTypeId="2" PostId="8868" RevisionGUID="5d1e7a72-9796-4e06-a564-473e5837bc8c" CreationDate="2019-05-29T11:23:19.093" UserId="137" Text="Like Rahul said that algorithm is only in the case where $0 \lt \Delta y \lt \Delta x$. &#xD;&#xA;&#xD;&#xA;So you need to adjust the coordinates to fit within that. &#xD;&#xA;&#xD;&#xA;There are 8 cases:&#xD;&#xA;&#xD;&#xA;1. $0 \lt \Delta y \lt \Delta x$ the normal base case&#xD;&#xA;2. $0 \lt \Delta x \lt \Delta y$ swap x and y except for the drawPixel call.&#xD;&#xA;3. $\Delta x \lt 0 \lt \Delta y$ and $|\Delta y &lt; \Delta x|$ use case 1 but negate $\Delta x$ and instead of counting from x0 to x1 you count from x1 to x0&#xD;&#xA;4. $\Delta x \lt 0 \lt \Delta y$ and $|\Delta x \lt \Delta y|$ use case 2 but negate $\Delta x$ and instead of counting from x0 to x1 you count from x1 to x0&#xD;&#xA;&#xD;&#xA;The remaining cases have $\Delta y \lt 0$ so swap the 2 points and it will fall within the previous 4 cases." ContentLicense="CC BY-SA 4.0" />
  <row Id="24105" PostHistoryTypeId="5" PostId="8867" RevisionGUID="2c2557a5-bae5-4892-ae79-acabcebace6f" CreationDate="2019-05-29T11:59:25.727" UserId="137" Comment="added 74 characters in body" Text="The simplest way is to use n-way nlerp (normalized lerp) instead. It does mean slight inaccuracies in the blend but careful (manual) tweaking of the weights and good key pose selection can take care of that.&#xD;&#xA;&#xD;&#xA;`nlerp` will approximate `slerp` when the key poses are close to each other. So you will very likely get away with not tweaking the weights at all in most cases.&#xD;&#xA;&#xD;&#xA;Also keep in mind that not all bones need to be blended the same way. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24107" PostHistoryTypeId="34" PostId="8847" RevisionGUID="429827d1-3484-4b5a-a505-1b86cbcb2d5b" CreationDate="2019-05-29T16:04:15.547" UserId="-1" Comment="55" />
  <row Id="24108" PostHistoryTypeId="2" PostId="8869" RevisionGUID="86599fb4-7d1c-4326-ad8b-222dbc82be07" CreationDate="2019-05-29T17:24:02.990" UserId="8851" Text="I will suggest something for the rotational part but I do not know how fast it is. Assume you have a 3D coordinate system centered at the pivoting point of the joint and fixed with respect to one of the bars that meet at the joint. The other bar moves in this coordinate system always attached the origin of the system. So its motion is a curve on a sphere centered at the joint's pivoting point and radius the bar's length $l$. Assume you have a sequence of positions $\vec{x}_0, \, \vec{x}_1, \, \vec{x}_2, \, ..., \vec{x}_m$ of the moving bar with respect to this system. Recall the bar has length $l$. Then calculate the cross products: &#xD;&#xA;$$\vec{n}_j = \vec{x}_0 \times \vec{x}_j$$ and the cosine of the angle $$c_j = \cos(\theta_{j}) =  \frac{1}{l^2} \, (\vec{x}_0 \cdot \vec{x}_j) $$ as well as the magnitude $\|\vec{n}_j\| = \sqrt{ (\vec{n}_{j} \cdot \vec{n}_j) }$. Normalize &#xD;&#xA;$$\vec{N}_j = \frac{\vec{n}_j}{\|\vec{n}_j\|}$$  &#xD;&#xA;So now you have the list of pairs &#xD;&#xA;$$\big(\vec{N}_1, \, c_1\big), \, \big(\vec{N}_2, \, c_2\big), \, ... ,\, \big(\vec{N}_m, \, c_m\big)$$&#xD;&#xA;Apply a cubic or some other appropriate spline interpolation to the list of data. The result is the pair of smooth families&#xD;&#xA;$$\vec{N}(t), \, c(t)$$&#xD;&#xA;Use  [Rodrigues' rotation formula][1] to obtain the smooth family of rotation matrices&#xD;&#xA;$$U(t) = \text{Id} \, \pm \, \big(\,\sqrt{1 - c(t)^2}\, \big)\, \hat{N}(t) \, + \, \big(1 - c(t)\big)\, \hat{N}(t)^2$$ where $\hat{N}(t) = \big( \vec{N}(t) \times \cdot \big) $ is the three by three skew symmetric matrix that acts on a vector $\vec{x}$ by&#xD;&#xA;$\hat{N}(t)\, \vec{x} = \vec{N}(t) \times \vec{x}$. Notice the presence of the $\pm$ sign, which is negative when the angle between the vectors $\vec{x}_0$ and $\vec{x}_j$ starts to exceed $180^{\circ}$. This really depends on the range of motion of the joint. Anyway, then the joint moves smoothly by &#xD;&#xA;$$\vec{x}(t) = U(t)\, \vec{x}_0$$ and at each moment of time $t_j$ for which&#xD;&#xA;$c(t_j) = c_j$ and $\vec{N}(t_j) = \vec{N}_j$ due to the interpolation scheme we get&#xD;&#xA;$$\vec{x}_j = U(t_j)\, \vec{x}_0$$&#xD;&#xA;All of this can be done with quaternions, the idea is analogous. It is up to you.  &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula" ContentLicense="CC BY-SA 4.0" />
  <row Id="24110" PostHistoryTypeId="2" PostId="8870" RevisionGUID="c60899d8-6405-4cc6-94e7-41bc6bde0cf4" CreationDate="2019-05-29T23:04:09.300" UserId="8314" Text="I would like to change/add/remove some mesh vertices in existing VBO's (while deforming and remeshing 3D objects) . With OpenGL I would have to reload whole vertex VBO's. I suppose with Vulkan there could be a way to directly access VBO's to only change/add/remove the changed vertex data. Is there some sample code out there demonstrating how this can be achieved? &#xD;&#xA;Many thanks for any help. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24111" PostHistoryTypeId="1" PostId="8870" RevisionGUID="c60899d8-6405-4cc6-94e7-41bc6bde0cf4" CreationDate="2019-05-29T23:04:09.300" UserId="8314" Text="Vulkan: efficient way to update VBO mesh vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24112" PostHistoryTypeId="3" PostId="8870" RevisionGUID="c60899d8-6405-4cc6-94e7-41bc6bde0cf4" CreationDate="2019-05-29T23:04:09.300" UserId="8314" Text="|opengl|3d|vulkan|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24113" PostHistoryTypeId="5" PostId="8869" RevisionGUID="48434992-2821-4965-bfcc-7902ef159d15" CreationDate="2019-05-30T00:00:07.483" UserId="8851" Comment="added 2496 characters in body" Text="I will suggest something for the rotational part but I do not know how fast it is. Assume you have a 3D coordinate system centered at the pivoting point of the joint and fixed with respect to one of the bars that meet at the joint. The other bar moves in this coordinate system always attached the origin of the system. So its motion is a curve on a sphere centered at the joint's pivoting point and radius the bar's length $l$. Assume you have a sequence of positions $\vec{x}_0, \, \vec{x}_1, \, \vec{x}_2, \, ..., \vec{x}_m$ of the moving bar with respect to this system. Recall the bar has length $l$. Then calculate the cross products: &#xD;&#xA;$$\vec{n}_j = \vec{x}_0 \times \vec{x}_j$$ and the cosine of the angle $$c_j = \cos(\theta_{j}) =  \frac{1}{l^2} \, (\vec{x}_0 \cdot \vec{x}_j) $$ as well as the magnitude $\|\vec{n}_j\| = \sqrt{ (\vec{n}_{j} \cdot \vec{n}_j) }$. Normalize &#xD;&#xA;$$\vec{N}_j = \frac{\vec{n}_j}{\|\vec{n}_j\|}$$  &#xD;&#xA;So now you have the list of pairs &#xD;&#xA;$$\big(\vec{N}_1, \, c_1\big), \, \big(\vec{N}_2, \, c_2\big), \, ... ,\, \big(\vec{N}_m, \, c_m\big)$$&#xD;&#xA;Apply a cubic or some other appropriate spline interpolation to the list of data. The result is the pair of smooth families&#xD;&#xA;$$\vec{N}(t), \, c(t)$$&#xD;&#xA;Use  [Rodrigues' rotation formula][1] to obtain the smooth family of rotation matrices&#xD;&#xA;$$U(t) = \text{Id} \, \pm \, \Big(\,\sqrt{1 - c(t)^2}\, \Big)\, \hat{N}(t) \, + \, \big(1 - c(t)\big)\, \hat{N}(t)^2$$ where $\hat{N}(t) = \big( \vec{N}(t) \times \cdot \big) $ is the three by three skew symmetric matrix that acts on a vector $\vec{x}$ by&#xD;&#xA;$\hat{N}(t)\, \vec{x} = \vec{N}(t) \times \vec{x}$. Notice the presence of the $\pm$ sign, which is negative when the angle between the vectors $\vec{x}_0$ and $\vec{x}_j$ starts to exceed $180^{\circ}$. This really depends on the range of motion of the joint. Anyway, then the joint moves smoothly by &#xD;&#xA;$$\vec{x}(t) = U(t)\, \vec{x}_0$$ and at each moment of time $t_j$ for which&#xD;&#xA;$c(t_j) = c_j$ and $\vec{N}(t_j) = \vec{N}_j$ due to the interpolation scheme we get&#xD;&#xA;$$\vec{x}_j = U(t_j)\, \vec{x}_0$$&#xD;&#xA;All of this can be done with quaternions, the idea is analogous. It is up to you.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**The case of framed joint:** If you have one coordinate system attached firmly to the first bar of the joint and a second coordinate system attached firmly to the second bar of the joint (both have origin at the pivoting point of the joint, i.e. I am ignoring translations), then the position of the second bar with respect to the coordinate system of the first one is described by the position of the second coordinate system with respect to the first. Then, if $\vec{u}_1, \, \vec{u}_2, \vec{u}_3$ are the unit orthogonal column-vectors of the second coordinate system written with respect to the first coordinate system, the orthogonal matrix that maps the first system to the second is $U = [\vec{u}_1 \,\, \vec{u}_2 \,\, \vec{u}_3]^T$ (the vectors are 3 x 1 columns of coordinates of the basis vectors of the second coordinate system with respect to the first coordinate system). Consequently, in this case (of framed joint motion) you may actually have a sequence of orthogonal matrices, describing the positions of the second system relative to the first at different times:&#xD;&#xA;$U_1, \, U_2, \, ..., \, U_m$. In this case, calculate the skew symmetric matrices $$\hat{n}_j = \frac{1}{2} \big( U_j - U_j^T \big)$$ and calculate the traces&#xD;&#xA;$$\|\hat{n}_j\| = \sqrt{ - \frac{1}{2} \, \text{trace}\big(\hat{n}_j^2\big) }$$ Then &#xD;&#xA;$$\hat{N}_j = \left(\frac{1}{\|\hat{n}_j\|}\right) \, \hat{n}_j$$ is a skew symmetric matrix with the property that there exists a unique unit vector $\vec{N}_j$ such that for any vector $\vec{x}$&#xD;&#xA;$$\hat{N}_j \, \vec{x} = \vec{N}_j \times \vec{x}$$&#xD;&#xA;and &#xD;&#xA;$$c_j = \cos(\theta_j) = \frac{\text{trace}(U_j) - 1}{2}$$&#xD;&#xA;As before, you have the list of pairs &#xD;&#xA;$$\big(\vec{N}_1, \, c_1\big), \, \big(\vec{N}_2, \, c_2\big), \, ... ,\, \big(\vec{N}_m, \, c_m\big)$$ or equvialently the list of pairs (whichever works better for you, although they are equivalent)&#xD;&#xA;$$\big(\hat{N}_1, \, c_1\big), \, \big(\hat{N}_2, \, c_2\big), \, ... ,\, \big(\hat{N}_m, \, c_m\big)$$&#xD;&#xA;Apply again a cubic or some other spline interpolation to either of the lists of data. The result is the pair of smooth families&#xD;&#xA;$$\hat{N}(t), \, c(t)$$&#xD;&#xA;Just as before,  [by the properties of rotational matrices][2], you obtain the smooth family of rotation matrices&#xD;&#xA;$$U(t) = \text{Id} \, \pm \, \Big(\,\sqrt{1 - c(t)^2}\, \Big)\, \hat{N}(t) \, + \, \big(1 - c(t)\big)\, \hat{N}(t)^2$$ This $U(t_j) = U_j$ for all $j = 1, .., m$.&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rotation_matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="24114" PostHistoryTypeId="2" PostId="8871" RevisionGUID="6af94e2d-d5f4-4dc0-8c97-3ef6bec71815" CreationDate="2019-05-30T01:55:58.180" UserId="9306" Text="&gt; With OpenGL I would have to reload whole vertex VBO's.&#xD;&#xA;&#xD;&#xA;No you wouldn't.  You can use `glBufferSubData`&#xD;&#xA;&#xD;&#xA;&gt; I suppose with Vulkan there could be a way to directly access VBO's to only change/add/remove the changed vertex data&#xD;&#xA;&#xD;&#xA;If you know the memory layout of the vertex buffer, you can find the offset of the contents you want to change, populate a transfer buffer with the new data and then uss [vkCmdCopyBuffer](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCmdCopyBuffer.html) to copy the data.  The `VkBufferCopy` parameter lets you specify the size as well as the source and destination offsets.  In other words, every call to `vkCmdCopyBuffer` is basically the equivalent of N calls to `glBufferSubData`" ContentLicense="CC BY-SA 4.0" />
  <row Id="24115" PostHistoryTypeId="5" PostId="8871" RevisionGUID="a976f45d-7be9-4a6f-9d3e-4c1e72fd2416" CreationDate="2019-05-30T04:05:46.257" UserId="9306" Comment="added 594 characters in body" Text="&gt; With OpenGL I would have to reload whole vertex VBO's.&#xD;&#xA;&#xD;&#xA;No you wouldn't.  You can use `glBufferSubData`&#xD;&#xA;&#xD;&#xA;&gt; I suppose with Vulkan there could be a way to directly access VBO's to only change/add/remove the changed vertex data&#xD;&#xA;&#xD;&#xA;If you know the memory layout of the vertex buffer, you can find the offset of the contents you want to change, populate a transfer buffer with the new data and then uss [vkCmdCopyBuffer](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCmdCopyBuffer.html) to copy the data.  The `VkBufferCopy` parameter lets you specify the size as well as the source and destination offsets.  In other words, every call to `vkCmdCopyBuffer` is basically the equivalent of N calls to `glBufferSubData`&#xD;&#xA;&#xD;&#xA;To clarify, updating a vertex buffer on Vulkan is almost the same as populating it.  If you're on a desktop architecture where _device local_ memory is typically not mappable, then you have to create a transfer buffer that is _host visible_.  You can populate that buffer with a memcpy (or whatever), and then use `vkCmdCopyBuffer` to transfer it to the _device local_ memory backed buffer.  If you're on a mobile architecture with unified memory, then _device local_ memory is typically also _host visible_ and so you can just map it directly and update it with your `memcpy` (or whatever)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24116" PostHistoryTypeId="2" PostId="8872" RevisionGUID="10d63128-8bf6-4be9-b06a-f01298bff6d7" CreationDate="2019-05-30T04:34:39.833" UserId="10707" Text="Perlin noise not good for real planet surface because planet surface is not random. Planet structure is create by geology/physics and interaction between different parts.&lt;br/&gt;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;This video show geology simulator have name PlaTec (have link in text below video):&lt;br/&gt;&#xD;&#xA;https://www.youtube.com/watch?v=bi4b45tMEPE&lt;br/&gt;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;Link have source code at SourceForge web site too." ContentLicense="CC BY-SA 4.0" />
  <row Id="24117" PostHistoryTypeId="2" PostId="8873" RevisionGUID="3653bd5b-f242-41b0-8ee3-1be2dedf5f1d" CreationDate="2019-05-30T20:20:16.183" UserId="2817" Text="I've been scanning the specifications for both OpenGL and GLSL, and I can't find a definitive answer as to *how exactly* are `gl_FragCoord`'s `x` and `y` components computed, other than they are the &#xD;&#xA;&#xD;&#xA;&gt; fragment’s window-space position&#xD;&#xA;&#xD;&#xA;([OpenGL 4.6 specification][1], page 491)&#xD;&#xA;&#xD;&#xA;which does not help me understand why `glViewport()` doesn't seem to affect the values of `gl_FragCoord` in the fragment stage, since that is the case for window-space coordinates in the vertex stage.&#xD;&#xA;&#xD;&#xA;The actual problem I'm trying to solve is rendering a bunch of draws (that depend on `gl_FragCoord` for their shading) to an atlas, without modifying the shaders of the draws to be aware of the atlas. Here's pseudocode for the driving part (all viewports have identical dimensions, just different offsets):&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;	for (size_t i = 0; i &lt; FrameCount; ++i)&#xD;&#xA;	{&#xD;&#xA;		auto&amp; Vp = Viewports[i];&#xD;&#xA;		glViewport(Vp.X, Vp.Y, Vp.X + Vp.Width, Vp.Y + Vp.Height);&#xD;&#xA;		BindConstants(Vp.Width, Vp.Height);&#xD;&#xA;		glDrawArrays(GL_TRIANGLES, 0, Triangles);&#xD;&#xA;	}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;`BindConstants()` simply binds a uniform with the viewport's width &amp; height. When trying to simply output the UVs with the following shader:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 330&#xD;&#xA;uniform vec2 Resolution;&#xD;&#xA;&#xD;&#xA;void main(void)&#xD;&#xA;{&#xD;&#xA;	vec2 UV = gl_FragCoord.xy / Resolution;&#xD;&#xA;	gl_FragColor = vec4(UV, 0.0, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I get the following image, which clearly shows that colour is being clipped to 1.0 beyond the first viewport in a 5x5 atlas:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I've also done additional simple tests that show that `gl_FragCoord` is based off of the entire frame buffer's origin, rather than what's specified via `glViewport()`.&#xD;&#xA;&#xD;&#xA;I have worked around this issue by rendering to a temporary FBO and blitting to the target frame buffer at the desired offset, but it's silly to go to such lengths for a dead-simple use-case like this.&#xD;&#xA;&#xD;&#xA;Am I missing something? Is it possible at all without a temporary FBO, and, above all, **without modifying the shaders?**&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/GIh9o.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24118" PostHistoryTypeId="1" PostId="8873" RevisionGUID="3653bd5b-f242-41b0-8ee3-1be2dedf5f1d" CreationDate="2019-05-30T20:20:16.183" UserId="2817" Text="gl_FragCoord and glViewport" ContentLicense="CC BY-SA 4.0" />
  <row Id="24119" PostHistoryTypeId="3" PostId="8873" RevisionGUID="3653bd5b-f242-41b0-8ee3-1be2dedf5f1d" CreationDate="2019-05-30T20:20:16.183" UserId="2817" Text="|opengl|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24120" PostHistoryTypeId="2" PostId="8874" RevisionGUID="0aa7819b-ca85-4e0b-818b-8f62e4690964" CreationDate="2019-05-30T20:25:32.230" UserId="10716" Text="I wrote the code for checking intersection of ray and meshes on scene. It consist of two parts - broad phase and narrow phase.&#xD;&#xA;In broad phase I build an oriented bounding box around each mesh and check intersection of ray with boxes.&#xD;&#xA;In narrow phase I check intersection of ray and each triangle of the meshes from broad phase using Möller-Trumbore algorithm. In general it works well.&#xD;&#xA;Now my task is to optimize broad phase using Octree. Octree as data structure is well-described and trivial enough. However, I have no idea how to apply it for raytracing and I can't find nothing about it. Could you please give me a hint? " ContentLicense="CC BY-SA 4.0" />
  <row Id="24121" PostHistoryTypeId="1" PostId="8874" RevisionGUID="0aa7819b-ca85-4e0b-818b-8f62e4690964" CreationDate="2019-05-30T20:25:32.230" UserId="10716" Text="Using octree for cheking intersection of ray and meshes" ContentLicense="CC BY-SA 4.0" />
  <row Id="24122" PostHistoryTypeId="3" PostId="8874" RevisionGUID="0aa7819b-ca85-4e0b-818b-8f62e4690964" CreationDate="2019-05-30T20:25:32.230" UserId="10716" Text="|raytracing|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24123" PostHistoryTypeId="2" PostId="8875" RevisionGUID="1edbf610-c15f-4e5c-98cf-e56525c8a3c6" CreationDate="2019-05-31T05:33:52.360" UserId="2654" Text="&gt; since that is the case for window-space coordinates in the vertex stage.&#xD;&#xA;&#xD;&#xA;There are no &quot;window-space coordinates in the vertex stage&quot;. Or at least, not in the vertex *shader*.&#xD;&#xA;&#xD;&#xA;Window-space is not relative to the viewport; it's relative to the *window* (or framebuffer, in this case). The viewport transform is used to convert from NDC-coordinates (which are relative to the viewport) to window coordinates (which are not).&#xD;&#xA;&#xD;&#xA;If you need your fragment shader to have window-relative coordinates, then you need to either compute them in the fragment shader (by providing the viewport as a `uniform`) or pass NDC coordinates from the vertex shader as an `in`/`out` variable pair (just compute `gl_Position.xy/gl_Position.w`)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24124" PostHistoryTypeId="2" PostId="8876" RevisionGUID="76850c52-3275-43d8-a285-3995a8b4bbb8" CreationDate="2019-05-31T08:47:17.083" UserId="10720" Text="I have a need to generate a series of GLB files. I have a base template for a GLTF file which I have to derive off of. The models thus generated will only have varying textures on them. The base mesh doesn't change at all.&#xD;&#xA;&#xD;&#xA;**What Im stuck with**&#xD;&#xA;&#xD;&#xA;Im able to generate the GLB, GLTF files from blender when exporting 3D models. After feeding these two files to: https://sbtron.github.io/makeglb/ Im able to create a GLB file which loads and works fine, with all the textures included.&#xD;&#xA;&#xD;&#xA;However I am unable to generate the bin file programmatically. Ive tried searching google for `generate bin file from images`, but the first few pages dont seem to have anything relating to this.&#xD;&#xA;&#xD;&#xA;**What Ive tried**&#xD;&#xA;&#xD;&#xA;Went through this question, but the selected answer there isnt dealing with images:&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/2338/how-to-generate-binary-gltf-array-buffers&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How do I go about generating a BIN file from a series of images?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24125" PostHistoryTypeId="1" PostId="8876" RevisionGUID="76850c52-3275-43d8-a285-3995a8b4bbb8" CreationDate="2019-05-31T08:47:17.083" UserId="10720" Text="Programmatically generating bin files for GLTF models" ContentLicense="CC BY-SA 4.0" />
  <row Id="24126" PostHistoryTypeId="3" PostId="8876" RevisionGUID="76850c52-3275-43d8-a285-3995a8b4bbb8" CreationDate="2019-05-31T08:47:17.083" UserId="10720" Text="|3d|3dtexture|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24128" PostHistoryTypeId="2" PostId="8877" RevisionGUID="9a147e19-3a67-42b9-bb24-f443e9eebb44" CreationDate="2019-05-31T12:02:45.297" UserId="10615" Text="I'm kind of stuck on this one. When following a conventional, high-level shading tutorial, you'll come across these images that are like ambient + diffuse + specular = result, but I can tell that it's not straight addition (otherwise the picture would seem overexposed).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What's the &quot;formula&quot; for mixing two rgb colors?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KnXE6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24129" PostHistoryTypeId="1" PostId="8877" RevisionGUID="9a147e19-3a67-42b9-bb24-f443e9eebb44" CreationDate="2019-05-31T12:02:45.297" UserId="10615" Text="How are colors really mixed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24130" PostHistoryTypeId="3" PostId="8877" RevisionGUID="9a147e19-3a67-42b9-bb24-f443e9eebb44" CreationDate="2019-05-31T12:02:45.297" UserId="10615" Text="|color|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24134" PostHistoryTypeId="2" PostId="8879" RevisionGUID="1b83ce5a-cfb9-4c94-b209-3f258219de2d" CreationDate="2019-05-31T13:38:09.373" UserId="2041" Text="With an old-style Phong shader (as in your example), they really are just added together. Each of those things is a *contribution* to the overall amount of light, so they're just added together, the same way you add together the contribution from each light source.&#xD;&#xA;&#xD;&#xA;Your intuition is right that you often end up with overexposed specular highlights with this style of shading. In a modern, physically-based pipeline, it's common to instead use an *energy-conserving* shader. The contributions of each layer (specular, clear-coat/lacquer, diffuse, subsurface) are still added together, but the amount of light in each layer reduces the *input* amount of light for the next layer. That is, if the surface is giving a strong specular reflection, it's reflecting most of the light, so less light is available for the diffuse layer. In the same way, any light that's reflected by the diffuse layer reduces the amount of light available for subsurface scattering." ContentLicense="CC BY-SA 4.0" />
  <row Id="24140" PostHistoryTypeId="2" PostId="8881" RevisionGUID="83e8200c-7fb6-4b21-bb82-7ac28139f945" CreationDate="2019-05-31T14:23:54.663" UserId="1908" Text="The `.bin` file that goes with a `.gltf` only includes mesh data (position, normal, uv, other vertex attributes as needed).  It does not normally include any images (unless you're using the base64 export &quot;glTF Embedded&quot;, but don't use that for this, use &quot;glTF Separate&quot; instead).&#xD;&#xA;&#xD;&#xA;If you look in the JSON text of the .gltf file, you'll see an `images` array, where image files are called out by `uri` (filename, if local, or relative URLs for the web).&#xD;&#xA;&#xD;&#xA;So when exporting from Blender, choose `glTF Separate` from the combo box in the export options panel.  This will produce a `.gltf` file, a `.bin` file, and may copy several images (be sure to export to a different folder from your source files, so nothing gets overwritten).  To change the images, just update the `uri` fields in the `images` array inside of the `.gltf` file, and keep the same `.bin` file around (the one that came out of Blender).&#xD;&#xA;&#xD;&#xA;That way, you can swap out images with other images, but keep the same mesh data." ContentLicense="CC BY-SA 4.0" />
  <row Id="24141" PostHistoryTypeId="52" PostId="8877" RevisionGUID="4b2875df-1306-4caa-81aa-8375c6f86e99" CreationDate="2019-05-31T20:04:50.493" />
  <row Id="24142" PostHistoryTypeId="2" PostId="8882" RevisionGUID="8b936924-2e55-4133-83fc-e871a7674901" CreationDate="2019-05-31T20:53:26.313" UserId="4647" Text="You are somewhat right: the rightmost image is not the sum of the three images to the left of it. It's easiest to see that the rightmost image doesn't even have the ambient contribution on the left-hand side of the central spheroid.&#xD;&#xA;&#xD;&#xA;I've done an experiment with two modes of addition of the three images. In the resulting images below, on the LHS, with the label &quot;Addition&quot;, is my result, on the RHS is the rightmost image from the OP.&#xD;&#xA;&#xD;&#xA;1. Simple, naive addition — as if the images were in linear RGB space (and retaining the result in this space). Here's the result:&#xD;&#xA;&#xD;&#xA;[![simple addition comparison][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. sRGB addition, i.e. the addition where we consider the images being in sRGB space (the default assumption on the web when no color profile is present), and so undo the sRGB gamma before actually adding color values, and applying it back afterwards. This will give the following result:&#xD;&#xA;&#xD;&#xA;[![sRGB addition comparison][2]][2]&#xD;&#xA;&#xD;&#xA;So, you can see that both ways of adding colors result in a sharp border from the ambient lighting contribution — the leftmost image in the OP, while the rightmost supposed result doesn't have such a border on some sides.&#xD;&#xA;&#xD;&#xA;I'm not really sure how the rightmost &quot;Phong Reflection&quot; image was created. It may have been manipulated, e.g. some gamma adjustment or something like that. But in any case, in both ways of addition above the image didn't get overexposed as you supposed it would.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/16AC8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tfGhF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24143" PostHistoryTypeId="50" PostId="8807" RevisionGUID="24634f79-b49e-4da6-afde-a862c33beb61" CreationDate="2019-05-31T23:02:55.410" UserId="-1" />
  <row Id="24144" PostHistoryTypeId="2" PostId="8883" RevisionGUID="61817f21-9697-4f56-a10c-486f085373c2" CreationDate="2019-06-01T09:49:42.820" UserId="9978" Text="A simple question. I know that non-manifold meshes are problematic for physics simulations, boolean operations, and 3D printing. I was wondering if they can be problematic for a virtual reality environment as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="24145" PostHistoryTypeId="1" PostId="8883" RevisionGUID="61817f21-9697-4f56-a10c-486f085373c2" CreationDate="2019-06-01T09:49:42.820" UserId="9978" Text="Are non manifold meshes problematic for Virtual Reality?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24146" PostHistoryTypeId="3" PostId="8883" RevisionGUID="61817f21-9697-4f56-a10c-486f085373c2" CreationDate="2019-06-01T09:49:42.820" UserId="9978" Text="|virtual-reality|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24147" PostHistoryTypeId="50" PostId="6359" RevisionGUID="3da7c763-8b0b-4bb1-9967-cbd7337ff0c1" CreationDate="2019-06-01T10:01:45.167" UserId="-1" />
  <row Id="24148" PostHistoryTypeId="2" PostId="8884" RevisionGUID="87c8d0b7-5e8a-4e56-9b06-9ab57e4bce6d" CreationDate="2019-06-01T11:23:25.093" UserId="2041" Text="No, VR is no different to flat graphics applications in this respect. If your VR experience has physics, CSG (Boolean geometry), or any of the things that would have problems with non-manifolds in a flat application, then it'll have the same problems. If your application wouldn't have problems with non-manifolds as a flat application, it won't have problems as a VR application.&#xD;&#xA;&#xD;&#xA;The only real difference is that it's harder to stop the camera being inside objects in VR, since it's attached to the user's head. In a flat application, you might override the camera position or adjust the camera controls to avoid the camera moving through objects in the first place. In VR, those techniques don't really apply, so you might want to have an inside-outside test, so that you can react if the user puts their head inside an object (e.g. by blanking the view completely and/or asking them to move). The inside-outside test would obviously have problems with non-manifolds. It's the same problem as in a flat application, but in a flat application you might not be doing the test at all." ContentLicense="CC BY-SA 4.0" />
  <row Id="24149" PostHistoryTypeId="5" PostId="8882" RevisionGUID="937615ef-6472-4321-af86-be701442ec13" CreationDate="2019-06-01T14:38:22.987" UserId="4647" Comment="deleted 3 characters in body" Text="You are somewhat right: the rightmost image is not the sum of the three images to the left of it. It's easiest to see that the rightmost image doesn't even have the ambient contribution on the left-hand side of the central spheroid.&#xD;&#xA;&#xD;&#xA;I've done an experiment with two modes of addition of the three images. In the resulting images below, on the LHS, with the label &quot;Addition&quot;, is my result, on the RHS is the rightmost image from the OP.&#xD;&#xA;&#xD;&#xA;1. Simple, naive addition — as if the images were in linear RGB space (and retaining the result in this space). Here's the result:&#xD;&#xA;&#xD;&#xA;[![simple addition comparison][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2. sRGB addition, i.e. the addition where we consider the images being in sRGB space (the default assumption on the web when no color profile is present), and so undo the sRGB gamma before actually adding color values, and apply it back afterwards. This will give the following result:&#xD;&#xA;&#xD;&#xA;[![sRGB addition comparison][2]][2]&#xD;&#xA;&#xD;&#xA;So, you can see that both ways of adding colors result in a sharp border from the ambient lighting contribution — the leftmost image in the OP, while the rightmost supposed result doesn't have such a border on some sides.&#xD;&#xA;&#xD;&#xA;I'm not really sure how the rightmost &quot;Phong Reflection&quot; image was created. It may have been manipulated, e.g. some gamma adjustment or something like that. But in any case, in both ways of addition above the image didn't get overexposed as you supposed it would.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/16AC8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tfGhF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24150" PostHistoryTypeId="50" PostId="8787" RevisionGUID="2caffea6-886b-40e2-af9c-f2aca74f6ec2" CreationDate="2019-06-02T15:02:05.310" UserId="-1" />
  <row Id="24154" PostHistoryTypeId="5" PostId="8881" RevisionGUID="70c0f4ae-fe2e-40e0-87eb-8934b75c0a78" CreationDate="2019-06-03T13:52:25.887" UserId="1908" Comment="add more detail" Text="The `.bin` file that goes with a `.gltf` only includes mesh data (position, normal, uv, other vertex attributes as needed).  It does not normally include any images (unless you're using the base64 export &quot;glTF Embedded&quot;, but don't use that for this, use &quot;glTF Separate&quot; instead).&#xD;&#xA;&#xD;&#xA;If you look in the JSON text of the .gltf file, you'll see an `images` array, where image files are called out by `uri` (filename, if local, or relative URLs for the web).&#xD;&#xA;&#xD;&#xA;Let's look at the [Damaged Helmet](https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/DamagedHelmet) sample model for an example.  The JPG images are [called out in the `.gltf` file](https://github.com/KhronosGroup/glTF-Sample-Models/blob/77f1a295e65c3a59c7131e6a15552c69817c9449/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf#L92-L114), separately from the `.bin` file.  The data from the `.bin` file is used by `buffers`, which in turn are used by `bufferViews`, `accessors`, and then mesh primitives.  It is exclusively vertex mesh data, no images.  This is a separate chain from how the JPGs are being used.  The JPGs are called out by `images`, which are referenced by `textures` which in turn are used by `materials`, which are referenced by mesh primitives.  For a more graphical version of this explanation, take a look at the [Overview Chart](https://github.com/KhronosGroup/glTF#overview) for glTF.&#xD;&#xA;&#xD;&#xA;So when exporting from Blender, choose `glTF Separate` from the combo box in the export options panel.  This will produce a `.gltf` file, a `.bin` file, and may copy several images (be sure to export to a different folder from your source files, so nothing gets overwritten).  To change the images, just update the `uri` fields in the `images` array inside of the `.gltf` file, and keep the same `.bin` file around (the one that came out of Blender).&#xD;&#xA;&#xD;&#xA;That way, you can swap out images with other images, but keep the same mesh data." ContentLicense="CC BY-SA 4.0" />
  <row Id="24156" PostHistoryTypeId="2" PostId="8886" RevisionGUID="63398b8d-7750-4886-b191-0f14a560927f" CreationDate="2019-06-04T07:26:23.320" UserId="10460" Text="I'm trying to understand and learn WebGL and computer graphics from button up, that is why I started to work on my own little library for that. I've spent couple of days looking for right answer and I can't make it work.&#xD;&#xA;&#xD;&#xA;I have column major matrices and I'm just trying to render basic rectangle but for some reason no matter what I do after multiplification by perspective matrix my Z of vertex is always out of bounds.&#xD;&#xA;&#xD;&#xA;my perspective matrix calculation : &#xD;&#xA;&#xD;&#xA;    static perspective(fov, aspect, near, far) {&#xD;&#xA;        const r = fov * aspect;&#xD;&#xA;        const l = -4;&#xD;&#xA;        const t = r;&#xD;&#xA;        const b = l;&#xD;&#xA;        const matrix = new Matrix4();&#xD;&#xA;        matrix.n11 = (2 * near) / (r - l);&#xD;&#xA;        matrix.n12 = 0;&#xD;&#xA;        matrix.n13 = (r+l)/(r-l);&#xD;&#xA;        matrix.n14 = 0;&#xD;&#xA;        matrix.n21 = 0;&#xD;&#xA;        matrix.n22 = (2 * near) / (t - b);&#xD;&#xA;        matrix.n23 = (t+b)/(t-b);&#xD;&#xA;        matrix.n24 = 0;&#xD;&#xA;        matrix.n31 = 0;&#xD;&#xA;        matrix.n32 = 0;&#xD;&#xA;        matrix.n33 = (near + far) / (near - far);&#xD;&#xA;        matrix.n34 = (2 * near * far) / (near - far);&#xD;&#xA;        matrix.n41 = 0;&#xD;&#xA;        matrix.n42 = 0;&#xD;&#xA;        matrix.n43 = -1;&#xD;&#xA;        matrix.n44 = 0;&#xD;&#xA;        return matrix;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;my vertex shader&#xD;&#xA;&#xD;&#xA;     this.vertexShaderScript =&#xD;&#xA;            '\r\n' +&#xD;&#xA;            'precision highp float;\r\n' +&#xD;&#xA;            'uniform mat4 u_model;\r\n' +&#xD;&#xA;            'uniform mat4 u_view;\r\n' +&#xD;&#xA;            'uniform mat4 u_projection;\r\n' +&#xD;&#xA;            'attribute vec3 a_position;\r\n' +&#xD;&#xA;            'attribute vec4 a_color;\r\n' +&#xD;&#xA;            'varying vec4 v_color;\r\n' +&#xD;&#xA;            'void main(void) {\r\n' +&#xD;&#xA;            '    v_color = a_color;\r\n' +&#xD;&#xA;            '    gl_Position = u_projection * u_view *  u_model * vec4(a_position, 1.0);\r\n' +&#xD;&#xA;            '}\r\n';" ContentLicense="CC BY-SA 4.0" />
  <row Id="24157" PostHistoryTypeId="1" PostId="8886" RevisionGUID="63398b8d-7750-4886-b191-0f14a560927f" CreationDate="2019-06-04T07:26:23.320" UserId="10460" Text="WebGL Can't render anything, wrong projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24158" PostHistoryTypeId="3" PostId="8886" RevisionGUID="63398b8d-7750-4886-b191-0f14a560927f" CreationDate="2019-06-04T07:26:23.320" UserId="10460" Text="|webgl|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24159" PostHistoryTypeId="5" PostId="8848" RevisionGUID="e8c1d866-2100-48cb-80b5-1d35558a5c54" CreationDate="2019-06-04T16:27:36.210" UserId="7622" Comment="added 542 characters in body" Text="I have a group of low polygon meshes, with associated normal maps. The normal maps were created by baking from high polygon meshes, which I no longer have access to. Is it possible to recreate anything approximating the original high polygon meshes from my inputs? &#xD;&#xA;&#xD;&#xA;I wouldn't expect the output to have the same kind of mesh structure, but want any kind of mesh that would have the same shape / volume as the original high polygon meshes. I would prefer the output to be a mesh, but it could also work if I could get a point cloud or set of voxels that recreated the volume of the original high polygon mesh. &#xD;&#xA;&#xD;&#xA;Further clarification: the low poly mesh was created manually from the high poly mesh by retopologising and deleting polygons. &#xD;&#xA;&#xD;&#xA;I've also attached a screenshot showing what I mean. It shows a close-up of two meshes of the handle of a sword. The left one is a high poly one (you can see the ridges in the handle), while the one on the right is the low poly version (it is flat instead of having ridges, because the ridges are captured by the normal map). In my use case, I have the low poly mesh (like the one on the right) and a normal map, and want to get the high poly version (like the one on the left). &#xD;&#xA;&#xD;&#xA;[Sword handle][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bHFpf.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24166" PostHistoryTypeId="2" PostId="8888" RevisionGUID="602cf7cd-9488-48ca-bf1b-6ccf4c06d824" CreationDate="2019-06-06T09:29:11.300" UserId="7525" Text="I'm working on a scene in Unity where I have textures loaded at runtime. As a result of that, the scene is being slowed down (even with co-routines), so I thought maybe I could move the texture loading task to a plugin and have it run as a parallel thread..&#xD;&#xA;&#xD;&#xA;Is there a way to load a texture with OpenGL in a Unity native plugin, and return a pointer back to the scene for further use?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24167" PostHistoryTypeId="1" PostId="8888" RevisionGUID="602cf7cd-9488-48ca-bf1b-6ccf4c06d824" CreationDate="2019-06-06T09:29:11.300" UserId="7525" Text="Unity: Pass texture pointer from plugin to scene" ContentLicense="CC BY-SA 4.0" />
  <row Id="24168" PostHistoryTypeId="3" PostId="8888" RevisionGUID="602cf7cd-9488-48ca-bf1b-6ccf4c06d824" CreationDate="2019-06-06T09:29:11.300" UserId="7525" Text="|opengl|texture|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24169" PostHistoryTypeId="4" PostId="8888" RevisionGUID="bafd3522-9c8a-4acf-bfe5-44da405649d2" CreationDate="2019-06-06T09:41:42.623" UserId="7525" Comment="edited title" Text="Unity: Pass texture pointer from OpenGL to Unity" ContentLicense="CC BY-SA 4.0" />
  <row Id="24170" PostHistoryTypeId="5" PostId="8848" RevisionGUID="d7b861a3-4d39-45b6-80b2-b4b1ae84d922" CreationDate="2019-06-06T16:51:37.500" UserId="7622" Comment="added 119 characters in body" Text="I have a group of low polygon meshes, with associated normal maps. The normal maps were created by baking from high polygon meshes, which I no longer have access to. Is it possible to recreate anything approximating the original high polygon meshes from my inputs? &#xD;&#xA;&#xD;&#xA;I wouldn't expect the output to have the same kind of mesh structure, but want any kind of mesh that would have the same shape / volume as the original high polygon meshes. I would prefer the output to be a mesh, but it could also work if I could get a point cloud or set of voxels that recreated the volume of the original high polygon mesh. &#xD;&#xA;&#xD;&#xA;Further clarification: the low poly mesh was created manually from the high poly mesh by retopologising and deleting polygons. &#xD;&#xA;&#xD;&#xA;I've also attached a screenshot showing what I mean (as well as the original mesh file in .obj format). It shows a close-up of two meshes of the handle of a sword. The left one is a high poly one (you can see the ridges in the handle), while the one on the right is the low poly version (it is flat instead of having ridges, because the ridges are captured by the normal map). In my use case, I have the low poly mesh (like the one on the right) and a normal map, and want to get the high poly version (like the one on the left). &#xD;&#xA;&#xD;&#xA;[Sword handles image file][1]&#xD;&#xA;&#xD;&#xA;[Swords mesh file][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bHFpf.jpg&#xD;&#xA;  [2]: https://drive.google.com/open?id=1MKwP8jGjLTU_4r-MoDWeRB6W99cO3JVe" ContentLicense="CC BY-SA 4.0" />
  <row Id="24176" PostHistoryTypeId="2" PostId="8891" RevisionGUID="e98caa8c-8381-4caa-ae5c-a6d9e4a46ae6" CreationDate="2019-06-07T16:00:54.567" UserId="10745" Text="I want to randomly generate polyhedrons which need not be convex. What is the most efficient way for doing so?&#xD;&#xA;&#xD;&#xA;I can think of an algorithm for generating random convex polyhedrons, but am unable to figure out a way for generating non-convex ones. How to generate a general polyhedron?&#xD;&#xA;&#xD;&#xA;Taking it a step further, generalising my question to an n dimension space, how to randomly generate bounded finite polytopes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24177" PostHistoryTypeId="1" PostId="8891" RevisionGUID="e98caa8c-8381-4caa-ae5c-a6d9e4a46ae6" CreationDate="2019-06-07T16:00:54.567" UserId="10745" Text="Algorithm for randomly generating polyhedrons?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24178" PostHistoryTypeId="3" PostId="8891" RevisionGUID="e98caa8c-8381-4caa-ae5c-a6d9e4a46ae6" CreationDate="2019-06-07T16:00:54.567" UserId="10745" Text="|computational-geometry|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24187" PostHistoryTypeId="19" PostId="8787" RevisionGUID="02d1d077-eb08-4ad2-b2e9-58eb9499a365" CreationDate="2019-06-08T05:30:34.750" UserId="-1" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:-1,&quot;DisplayName&quot;:&quot;Community&quot;}]}" />
  <row Id="24188" PostHistoryTypeId="50" PostId="8462" RevisionGUID="6f2123bf-d1a5-48ce-acd8-9e60afe63b9e" CreationDate="2019-06-08T09:03:06.593" UserId="-1" />
  <row Id="24189" PostHistoryTypeId="2" PostId="8893" RevisionGUID="606c7bfc-99b7-4924-b8a1-0d04a7b0b6ec" CreationDate="2019-06-08T13:11:02.003" UserId="5066" Text="I am not sure if doing this is right or wrong or actually needed in practice. However, I was curious once &amp; wanted to learn about Unity Native plugins, so i decided to do exactly what you need. &#xD;&#xA;&#xD;&#xA;Basically, I wrote a native plugin, which loads image data using C++ &amp; stb_image library, it then passes byte[] to Unity C# side where it gets applied on a quad. There are many things you need to consider if it's a cross platform app, I was able to run it on both PC &amp; Android during the experiment. &#xD;&#xA;&#xD;&#xA;Let me know if this is what you want to achieve &amp; I can pass on the code to you. &#xD;&#xA;&#xD;&#xA;Best. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24193" PostHistoryTypeId="50" PostId="6115" RevisionGUID="4ad4a6c7-7af1-4c8f-93ed-feddad937851" CreationDate="2019-06-09T13:03:30.360" UserId="-1" />
  <row Id="24194" PostHistoryTypeId="2" PostId="8895" RevisionGUID="c358bb29-b441-4030-83c6-4b8a1f7639ad" CreationDate="2019-06-10T23:47:31.100" UserId="10734" Text="I am updating my scene graph in response to user input and the network. What is the best way to do this? The updating threads are separate. Some approaches I am thinking about:&#xD;&#xA;&#xD;&#xA; - double buffer. There are 2 copies of the scene graph, one is used for rendering and the other for updates. The rendering graph is updated at the end of the render loop. This update can be expensive for a large graph,&#xD;&#xA;&#xD;&#xA; - synchronization objects, like mutices, probably unsuitable,&#xD;&#xA;&#xD;&#xA; - dumping updating functors into a FIFO queue while rendering, then executing the functors at the end of the rendering loop. Updating the queue may block.&#xD;&#xA;&#xD;&#xA;Is there something else and which approach is best?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24195" PostHistoryTypeId="1" PostId="8895" RevisionGUID="c358bb29-b441-4030-83c6-4b8a1f7639ad" CreationDate="2019-06-10T23:47:31.100" UserId="10734" Text="how to update my scene graph?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24196" PostHistoryTypeId="3" PostId="8895" RevisionGUID="c358bb29-b441-4030-83c6-4b8a1f7639ad" CreationDate="2019-06-10T23:47:31.100" UserId="10734" Text="|rendering|multithreading|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24197" PostHistoryTypeId="5" PostId="8895" RevisionGUID="88c934f9-2b89-4224-86f6-c5c7b0fb07ec" CreationDate="2019-06-11T00:44:25.040" UserId="10734" Comment="added 2 characters in body" Text="I am updating my scene graph in response to user input and the network. What is the best way to do this? The updating threads are separate. Some approaches I am thinking about:&#xD;&#xA;&#xD;&#xA; - double buffer. There are 2 copies of the scene graph, one is used for rendering and the other for updates. The rendering graph is updated at the end of the render loop. This update can be expensive for a large graph,&#xD;&#xA;&#xD;&#xA; - synchronization objects, like mutices, probably unsuitable,&#xD;&#xA;&#xD;&#xA; - dumping updating functors into a FIFO queue while rendering, then executing the functors at the end of the rendering loop. Updating the queue may block.&#xD;&#xA;&#xD;&#xA;Is there something better and which approach is best?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24200" PostHistoryTypeId="2" PostId="8896" RevisionGUID="7b2a7388-104f-413f-ad67-7b2ffb69452d" CreationDate="2019-06-11T12:27:49.050" UserId="10760" Text="Try This... I guess you got the matrix wrong.&#xD;&#xA;&#xD;&#xA;    matrix.n11 = -(2 * near) / (r - l);&#xD;&#xA;    matrix.n12 = 0;&#xD;&#xA;    matrix.n13 = 0;&#xD;&#xA;    matrix.n14 = -near*(r+l)/(r-l);&#xD;&#xA;    matrix.n21 = 0;&#xD;&#xA;    matrix.n22 = (2 * near) / (t - b);&#xD;&#xA;    matrix.n23 = 0;&#xD;&#xA;    matrix.n24 = -near*(t+b)/(t-b);&#xD;&#xA;    matrix.n31 = 0;&#xD;&#xA;    matrix.n32 = 0;&#xD;&#xA;    matrix.n33 = (near + far) / (near - far);&#xD;&#xA;    matrix.n34 = (2 * near * far) / (near - far);&#xD;&#xA;    matrix.n41 = 0;&#xD;&#xA;    matrix.n42 = 0;&#xD;&#xA;    matrix.n43 = -1;&#xD;&#xA;    matrix.n44 = 0;&#xD;&#xA;&#xD;&#xA;I referred the following site after I googled =&gt;[Link][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://learnwebgl.brown37.net/08_projections/projections_perspective.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="24201" PostHistoryTypeId="2" PostId="8897" RevisionGUID="626f0f56-24d8-4b66-93f4-962199b41a2b" CreationDate="2019-06-11T15:56:25.933" UserId="137" Text="A few more options:&#xD;&#xA;&#xD;&#xA;4. don't use a scenegraph. They don't map well to the data a gpu needs for rendering. A flat array of object tends to work much better for the cache as well&#xD;&#xA;&#xD;&#xA;4. separate the scenegraph into render-related data and non-render-related data. Then only double buffer the render-related data. &#xD;&#xA;&#xD;&#xA;   The render related data would end up in a flat array containing per rendered object: reference to the mesh, the final model matrix, a reference to the texture&#xD;&#xA;&#xD;&#xA;Flat arrays are much easier to double buffer than node-based data structures." ContentLicense="CC BY-SA 4.0" />
  <row Id="24202" PostHistoryTypeId="2" PostId="8898" RevisionGUID="7fef368c-75ec-4f03-994f-b6686fb72ec5" CreationDate="2019-06-11T19:08:20.823" UserId="10762" Text="I'm implementing a pbr ray tracer. Let's say that I'm at the end of the process:&#xD;&#xA;for each pixel pi, I accumulated the radiance value in vector pi = (radR, radG, radB). At this point, these values are unbounded, so I use the Reinhard tone mapper to have values between 0 and 1. Then I can scale it in the device range, for instance [0, 255] for usual computer images. &#xD;&#xA;&#xD;&#xA;Here is my problem, the Reinhard tone mapping **is not aware of the range of radiance in the whole scene**. I mean to compute the tone mapping I do: pi = pi / (1 + pi). &#xD;&#xA;So if pi = (100, 100, 100), the tone mapped pi is (100/101, 100/101, 100/101), but if pi = (1000, 1000, 1000), the tone mapped pi is (1000/10001, 1000/1001, 1000/10001). So the **final values will be really close** after tone mapping but **one should be a lot greater than the other**, right?&#xD;&#xA;&#xD;&#xA;Am I doing something wrong, or missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24203" PostHistoryTypeId="1" PostId="8898" RevisionGUID="7fef368c-75ec-4f03-994f-b6686fb72ec5" CreationDate="2019-06-11T19:08:20.823" UserId="10762" Text="Tone Mapping in a physically based rendering ray tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="24204" PostHistoryTypeId="3" PostId="8898" RevisionGUID="7fef368c-75ec-4f03-994f-b6686fb72ec5" CreationDate="2019-06-11T19:08:20.823" UserId="10762" Text="|raytracing|rendering|lighting|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24205" PostHistoryTypeId="2" PostId="8899" RevisionGUID="5f1389db-8631-432c-b3dd-bce622c6d381" CreationDate="2019-06-11T22:40:36.200" UserId="10759" Text="I've read some tutorials about Phong and Blinn lighting models and tried to implement a rendered myself.&#xD;&#xA;To my knowledge, the basic approach consists of the following steps:&#xD;&#xA;&#xD;&#xA; - calculate the vector from the current fragment to the light `rayToLight` (and normalize it)&#xD;&#xA; - calculate the diffuse color intensity using `diffuseIntensity = max(dot(rayToLight, normal))`&#xD;&#xA; - calculate the vector from the current fragment and the camera `rayToCamera` (and normalize it)&#xD;&#xA; - reflect `rayToLight`: `reflected = reflect(-rayToLight, normal)`&#xD;&#xA; - calculate the `specularIntensity = pow(max(dot(reflected, rayToCamera), 0.0), shininess)`.&#xD;&#xA;&#xD;&#xA;The problem is that `specularIntensity` ( `dot(reflected, rayToCamera)` to be precise), can be non-zero even if the light and the camera are on the opposite sides of a surface. Take the following example&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;It is possible that the angle between `reflected` and `rayToCamera` is less than 90 deg even if the camera and the light are on the opposite sides of a surface.&#xD;&#xA;This means that despite the surface is not lit by the diffuse light, it can show specular reflections which is, of course, not wanted.&#xD;&#xA;I wasn't aware of this problem until it occurred when I was trying to implement a simple phong lighting model.&#xD;&#xA;&#xD;&#xA;Have I done something wrong or is it just the way it should work?&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4lM81.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24206" PostHistoryTypeId="1" PostId="8899" RevisionGUID="5f1389db-8631-432c-b3dd-bce622c6d381" CreationDate="2019-06-11T22:40:36.200" UserId="10759" Text="Clarification about Phong lighting model" ContentLicense="CC BY-SA 4.0" />
  <row Id="24207" PostHistoryTypeId="3" PostId="8899" RevisionGUID="5f1389db-8631-432c-b3dd-bce622c6d381" CreationDate="2019-06-11T22:40:36.200" UserId="10759" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24208" PostHistoryTypeId="2" PostId="8900" RevisionGUID="aedf4830-6cb8-4b49-bd8e-931de63cc3f4" CreationDate="2019-06-12T02:26:15.940" UserId="9901" Text="I am new to Vulkan. Compared to DX12, the resource binding procedure seems a little bit complicated. In terms of per draw call uniform buffers, I currently have two approaches in mind, and they both seem to work (haven't tested/benchmarked yet). Can someone shine some light on which is the standard way to do this, with pros and cons. You are welcome to provide other ways but I am not considering push constants because I want a universal approach that I can apply to other kinds of uniform buffers as well (i.e. per pass, per frame, per scene and etc.). &#xD;&#xA;  &#xD;&#xA;approach A) One descriptor set and multiple buffers (one buffer for each object). Bind the descriptor set to pipeline only once before rendering. Bind buffers to the only descriptor set between draw calls using vkCmdPushDescriptorSetKHR. &#xD;&#xA;&#xD;&#xA;approach B) Multiple descriptor sets (one descriptor set for each object). (Multiple or single buffers, it doesn't really matter. If single buffer is used, I think it's called a dynamic uniform buffer and all that I need to do is to specify the offset when binding the descriptor set.) Bind buffer/buffers to descriptor sets only once before rendering. Bind the matching descriptor set to the pipeline between draw calls using vkCmdBindDescriptorSets. &#xD;&#xA;  &#xD;&#xA;I am used to DX12 so approach A seems more natural because in my understanding vkCmdPushDescriptorSetKHR in Vulkan is just like SetGraphicsRootConstantBufferView in DX12, because they both bind buffer to pipeline and this operation is buffered with other commands. But the Vulkan one do feels a little bit slower mainly because 1) it is not a root descriptor, 2) Vulkan does not use GPU address and also 3) a descriptor set write operation is needed. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24209" PostHistoryTypeId="1" PostId="8900" RevisionGUID="aedf4830-6cb8-4b49-bd8e-931de63cc3f4" CreationDate="2019-06-12T02:26:15.940" UserId="9901" Text="Is vkCmdPushDescriptorSetKHR efficient?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24210" PostHistoryTypeId="3" PostId="8900" RevisionGUID="aedf4830-6cb8-4b49-bd8e-931de63cc3f4" CreationDate="2019-06-12T02:26:15.940" UserId="9901" Text="|gpu|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24211" PostHistoryTypeId="2" PostId="8901" RevisionGUID="090860f9-f97f-4101-878b-4181a2c3d404" CreationDate="2019-06-12T12:17:57.533" UserId="192" Text="Try these papers:&#xD;&#xA;&#xD;&#xA;- [Octrees for faster isosurface generation](https://doi.org/10.1145/130881.130882) by Wilhelms	and Van Gelde&#xD;&#xA;&#xD;&#xA;- [A survey of the marching cubes algorithm](https://doi.org/10.1016/j.cag.2006.07.021) by Newman and Yi" ContentLicense="CC BY-SA 4.0" />
  <row Id="24212" PostHistoryTypeId="5" PostId="8901" RevisionGUID="b657176f-11b4-4ef5-9894-d39f65c6745d" CreationDate="2019-06-12T12:23:37.890" UserId="192" Comment="added 117 characters in body" Text="Try these papers:&#xD;&#xA;&#xD;&#xA;- [Octrees for faster isosurface generation](https://doi.org/10.1145/130881.130882) by Wilhelms	and Van Gelde (1992)&#xD;&#xA;&#xD;&#xA;- [Speeding up isosurface extraction using interval trees](https://doi.org/10.1109/2945.597798) by  Cignoni et al (1997)&#xD;&#xA;&#xD;&#xA;- [A survey of the marching cubes algorithm](https://doi.org/10.1016/j.cag.2006.07.021) by Newman and Yi (2006)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24216" PostHistoryTypeId="2" PostId="8903" RevisionGUID="08a000d0-02cd-4bdf-b091-92db18daa5b5" CreationDate="2019-06-12T14:05:45.290" UserId="6046" Text="That's just how the Reinhard operator works. If the scene has very high dynamic range important detail may be lost near the high luminance region as you found since both will map near `0.99`. Reinhard is a form of global operator. There are other types of algorithms using local operators which tonemap the pixel based on the intensity of the underlying neighborhood like a 3x3 or 5x5 region. &#xD;&#xA;&#xD;&#xA;I'd recommend reading `HDR Imaging Acquisition, Display and Image Based Lighting` by Erik Reinhard. It's a very good book and explains much of the concepts." ContentLicense="CC BY-SA 4.0" />
  <row Id="24218" PostHistoryTypeId="2" PostId="8904" RevisionGUID="62ad6dfd-9a9c-49d9-aa7a-605e5e6a670c" CreationDate="2019-06-12T20:27:28.650" UserId="10765" Text="I'm currently looking into Mesh Simplification to batch-simplify a large amount of .obj files. It is necessary for these algorithms to preserve the visual representation of a mesh as well as possible.  &#xD;&#xA;&#xD;&#xA;During research I've stumbled over Garland &amp; Heckberts [Surface Simplification Using Quadric Error Metrics][1]. Most of the frameworks I've inspected are making use of this algorithm for Mesh Simplification.  &#xD;&#xA;&#xD;&#xA;My question is, why are most frameworks not making use of seemingly more advanced algorithms e.g. [Simplifying Surfaces with Color and Texture using Quadric Error Metrics][2] or comparable? Is the Quadric Error Metric currently state of the art concerning simplification algorithms?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://chrome-extension://gfbliohnnapiefjpjlpjnehglfpaknnc/pages/pdf_viewer.html?r=https://www.cs.cmu.edu/~./garland/Papers/quadrics.pdf&#xD;&#xA;&#xD;&#xA;[2]: https://mgarland.org/files/papers/quadric2.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24219" PostHistoryTypeId="1" PostId="8904" RevisionGUID="62ad6dfd-9a9c-49d9-aa7a-605e5e6a670c" CreationDate="2019-06-12T20:27:28.650" UserId="10765" Text="Mesh Simplification Algorithms" ContentLicense="CC BY-SA 4.0" />
  <row Id="24220" PostHistoryTypeId="3" PostId="8904" RevisionGUID="62ad6dfd-9a9c-49d9-aa7a-605e5e6a670c" CreationDate="2019-06-12T20:27:28.650" UserId="10765" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24221" PostHistoryTypeId="2" PostId="8905" RevisionGUID="0dd48361-0cbd-4572-b4a1-fe7ba0ae0206" CreationDate="2019-06-13T01:53:44.327" UserId="10767" Text="the image below uses an RGB scale (the values of the scale are displayed on the image) to show the magnetic field strength at each point on the map. I've been struggling to find a way to convert this image into an array that shows the x and y coordinates of the pixel along with the magnetic field value at each coordinate (using MATLAB)[![Magentic field map u][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Sz3BH.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24222" PostHistoryTypeId="1" PostId="8905" RevisionGUID="0dd48361-0cbd-4572-b4a1-fe7ba0ae0206" CreationDate="2019-06-13T01:53:44.327" UserId="10767" Text="RGB map into numerical data" ContentLicense="CC BY-SA 4.0" />
  <row Id="24223" PostHistoryTypeId="3" PostId="8905" RevisionGUID="0dd48361-0cbd-4572-b4a1-fe7ba0ae0206" CreationDate="2019-06-13T01:53:44.327" UserId="10767" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24224" PostHistoryTypeId="2" PostId="8906" RevisionGUID="ac4936d2-6e73-43b2-8589-cdf9b85dcfbe" CreationDate="2019-06-13T02:53:03.897" UserId="2654" Text="What you're ultimately trying to do is, between draw calls, change some state that allows one to select which set of read-only data to use in the rendering process. There are many techniques for this.&#xD;&#xA;&#xD;&#xA;Push constants can be used to provide an index into an array of arbitrary size stored in an SSBO. Indeed, a single push constant can be used to provide multiple indices into multiple SSBOs, for different frequencies of state (per-frame vs. per-object). The upper 16-bits can be for one frequency, with the lower 16-bits for another.&#xD;&#xA;&#xD;&#xA;That may sound slower than other methods, since you're accessing global data rather than an actual UBO. But on some hardware, it won't change anything. AMD hardware for example doesn't actually have any specialized hardware for UBOs, so they implement UBOs as just read-only SSBOs. Even on hardware with dedicated UBOs, the state data you're reading will likely be quickly cached, since all invocations will be reading the same values from the array. So unless your thrashing the SSBO caches, this shouldn't impact performance much.&#xD;&#xA;&#xD;&#xA;Dynamic UBO descriptors also exist, given the `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC` type. Basically, the idea is that, when you call `vkCmdBindDescriptorSets`, you provide a dynamic offset for any dynamic descriptors. The offset represents a byte offset from the buffer attached to that descriptor to where the UBO data you want to fetch lives. So you would have all of your data in a large buffer, and you would select which particular data you're using for a particular render call by invoking `vkCmdBindDescriptorSets` with a different dynamic offset.&#xD;&#xA;&#xD;&#xA;Now `vkCmdBindDescriptorSets` may seem like a more heavyweight call than setting push constant. But the implementation has all the information needed to be able to see that you are using the same descriptor as you used in the previous call in that command buffer, and thus not do the actual heavy part of that operation, simply applying the dynamic offsets to any dynamic descriptors. So that part should not be a concern.&#xD;&#xA;&#xD;&#xA;Push descriptors are mainly intended for texture/sampler/image bindings, which don't have a convenient mechanism like dynamic offsets that would allow you to quickly switch which image/sampler you're using. That being said, push descriptors are a useful concept even for UBO/SSBOs. Whether they are *faster* than dynamic descriptors is a matter of profiling.&#xD;&#xA;&#xD;&#xA;The principle downside is the obvious: push descriptors is an extension. Dynamic UBO offsets and push constants are mandatory, required by every Vulkan 1.0 implementation. Push descriptors aren't even optional features of Vulkan. They're important enough to get a KHR extension, but they didn't go into Vulkan 1.1 as an optional feature. This is not a theoretical issue: [NVIDIA and Intel seem to support it on desktop, but no official AMD drivers do][1].&#xD;&#xA;&#xD;&#xA;So I would go with dynamic UBOs; this is exactly what they were made for, after all.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://vulkan.gpuinfo.org/listdevices.php?platform=windows&amp;extension=VK_KHR_push_descriptor" ContentLicense="CC BY-SA 4.0" />
  <row Id="24225" PostHistoryTypeId="2" PostId="8907" RevisionGUID="d305b7cb-6cda-4873-a5c8-6bc95daaeec6" CreationDate="2019-06-13T06:50:12.367" UserId="9901" Text="I'm using shaderc to compile glsl code in to spirv module and pass to pipelie in REAL-TIME. I want to use #include to reuse some of the shader code but shaderc is having problems recognizing it. Any one know how to solve this? (I'm NOT using command line to compile shader upfront.)&#xD;&#xA;&#xD;&#xA;The error I got from shaderc is:&#xD;&#xA;&#xD;&#xA;    standard.vert:6: error: '#include' : #error unexpected include directive for header name: GlobalInclude.glsl&#xD;&#xA;&#xD;&#xA;Here are my shaders and client codes:&#xD;&#xA;&#xD;&#xA;standard.vert&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    #extension GL_ARB_separate_shader_objects : enable&#xD;&#xA;    #extension GL_KHR_vulkan_glsl : enable&#xD;&#xA;    #extension GL_GOOGLE_include_directive : enable&#xD;&#xA;&#xD;&#xA;    #include &quot;GlobalInclude.glsl&quot;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 inPosition;&#xD;&#xA;    layout(location = 1) in vec3 inColor;&#xD;&#xA;    layout(location = 2) in vec2 inTexCoord;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) out vec3 fragColor;&#xD;&#xA;    layout(location = 1) out vec2 fragTexCoord;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;      gl_Position = passUBO.proj * passUBO.view * objectUBO.model * vec4(inPosition, 1.0);&#xD;&#xA;      fragColor = inColor;&#xD;&#xA;      fragTexCoord = inTexCoord;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;standard.frag&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    #extension GL_ARB_separate_shader_objects : enable&#xD;&#xA;    #extension GL_KHR_vulkan_glsl : enable&#xD;&#xA;    #extension GL_GOOGLE_include_directive : enable&#xD;&#xA;&#xD;&#xA;    #include &quot;GlobalInclude.glsl&quot;&#xD;&#xA;&#xD;&#xA;    layout(set = PASS_SET, binding = TEXTURE_SLOT(0)) uniform sampler2D texSamplerAlbedo;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 fragColor;&#xD;&#xA;    layout(location = 1) in vec2 fragTexCoord;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) out vec4 outColor;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;      //outColor = vec4(fragTexCoord, 0.0, 1.0);&#xD;&#xA;      outColor = texture(texSamplerAlbedo, fragTexCoord);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;GlobalInclude.glsl&#xD;&#xA;&#xD;&#xA;    #define FRAME_SET 0//per frame&#xD;&#xA;    #define SCENE_SET 1//per scene&#xD;&#xA;    #define PASS_SET 2//per pass&#xD;&#xA;    #define OBJECT_SET 3//per draw call&#xD;&#xA;&#xD;&#xA;    #define UNIFORM_BUFFER_BINDING_START 0&#xD;&#xA;    #define TEXTURE_BINDING_START 1&#xD;&#xA;&#xD;&#xA;    #define TEXTURE_SLOT(NUMBER) TEXTURE_BINDING_START + NUMBER&#xD;&#xA;&#xD;&#xA;    layout(set = SCENE_SET, binding = UNIFORM_BUFFER_BINDING_START + 0) uniform SceneUniformBufferObject {&#xD;&#xA;      uint time;&#xD;&#xA;    } sceneUBO;&#xD;&#xA;&#xD;&#xA;    layout(set = PASS_SET, binding = UNIFORM_BUFFER_BINDING_START + 0) uniform PassUniformBufferObject {&#xD;&#xA;      mat4 proj;&#xD;&#xA;      mat4 view;&#xD;&#xA;      uint passNum;&#xD;&#xA;    } passUBO;&#xD;&#xA;&#xD;&#xA;    layout(set = OBJECT_SET, binding = UNIFORM_BUFFER_BINDING_START + 0) uniform ObjectUniformBufferObject {&#xD;&#xA;      mat4 model;&#xD;&#xA;    } objectUBO;&#xD;&#xA;&#xD;&#xA;    layout(set = FRAME_SET, binding = UNIFORM_BUFFER_BINDING_START + 0) uniform FrameUniformBufferObject {&#xD;&#xA;      uint frameNum;&#xD;&#xA;    } frameUBO;&#xD;&#xA;&#xD;&#xA;Compile shader using shaderc API:&#xD;&#xA;&#xD;&#xA;    bool Shader::CreateShaderFromFile(shaderc_shader_kind kind, bool optimize)&#xD;&#xA;    {&#xD;&#xA;	  // read shader string&#xD;&#xA;	  if (!ReadShaderFromFile())&#xD;&#xA;		  return false;&#xD;&#xA;&#xD;&#xA;	  shaderc::Compiler compiler;&#xD;&#xA;	  shaderc::CompileOptions options;&#xD;&#xA;&#xD;&#xA;	  // like -DMY_DEFINE=1&#xD;&#xA;	  //options.AddMacroDefinition(&quot;MY_DEFINE&quot;, &quot;1&quot;);&#xD;&#xA;	  if (optimize) options.SetOptimizationLevel(shaderc_optimization_level_size);&#xD;&#xA;&#xD;&#xA;	  std::cout &lt;&lt; &quot;output 1:&quot; &lt;&lt; shaderString &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;	  // preprocess&#xD;&#xA;	  shaderc::PreprocessedSourceCompilationResult preprocessed = compiler.PreprocessGlsl(shaderString, kind, fileName.c_str(), options);&#xD;&#xA;&#xD;&#xA;	  if (preprocessed.GetCompilationStatus() != shaderc_compilation_status_success) &#xD;&#xA;	  {&#xD;&#xA;		  throw std::runtime_error(preprocessed.GetErrorMessage());&#xD;&#xA;		  return false;&#xD;&#xA;	  }&#xD;&#xA;&#xD;&#xA;	  shaderString = { preprocessed.cbegin(), preprocessed.cend() };&#xD;&#xA;&#xD;&#xA;	  std::cout &lt;&lt; &quot;output 2:&quot; &lt;&lt; shaderString &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;	  // compile&#xD;&#xA;	  shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(shaderString, kind, fileName.c_str(), options);&#xD;&#xA;&#xD;&#xA;	  if (module.GetCompilationStatus() != shaderc_compilation_status_success)&#xD;&#xA;	  {&#xD;&#xA;		  throw std::runtime_error(module.GetErrorMessage());&#xD;&#xA;		  return false;&#xD;&#xA;	  }&#xD;&#xA;&#xD;&#xA;	  shaderBytecode = { module.cbegin(), module.cend() };// not sure why sample code copy vector like this&#xD;&#xA;&#xD;&#xA;	  return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24226" PostHistoryTypeId="1" PostId="8907" RevisionGUID="d305b7cb-6cda-4873-a5c8-6bc95daaeec6" CreationDate="2019-06-13T06:50:12.367" UserId="9901" Text="shaderc compile through api with #include" ContentLicense="CC BY-SA 4.0" />
  <row Id="24227" PostHistoryTypeId="3" PostId="8907" RevisionGUID="d305b7cb-6cda-4873-a5c8-6bc95daaeec6" CreationDate="2019-06-13T06:50:12.367" UserId="9901" Text="|shader|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24228" PostHistoryTypeId="5" PostId="8904" RevisionGUID="fad9925f-ddc2-4511-8a64-9447be05380e" CreationDate="2019-06-13T11:28:52.097" UserId="137" Comment="fixing link" Text="I'm currently looking into Mesh Simplification to batch-simplify a large amount of .obj files. It is necessary for these algorithms to preserve the visual representation of a mesh as well as possible.  &#xD;&#xA;&#xD;&#xA;During research I've stumbled over Garland &amp; Heckberts [Surface Simplification Using Quadric Error Metrics][1]. Most of the frameworks I've inspected are making use of this algorithm for Mesh Simplification.  &#xD;&#xA;&#xD;&#xA;My question is, why are most frameworks not making use of seemingly more advanced algorithms e.g. [Simplifying Surfaces with Color and Texture using Quadric Error Metrics][2] or comparable? Is the Quadric Error Metric currently state of the art concerning simplification algorithms?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cmu.edu/~./garland/Papers/quadrics.pdf&#xD;&#xA;&#xD;&#xA;[2]: https://mgarland.org/files/papers/quadric2.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24229" PostHistoryTypeId="2" PostId="8908" RevisionGUID="3b06cf43-9515-4cf6-b0f5-61dbfa4779ec" CreationDate="2019-06-13T17:00:01.503" UserId="9306" Text="It is _your_ responsibility to support includes by instantiating an [`IncluderInterface`](https://github.com/google/shaderc/blob/master/libshaderc/include/shaderc/shaderc.hpp#L182) instance and calling [`SetIncluder(...)`](https://github.com/google/shaderc/blob/master/libshaderc/include/shaderc/shaderc.hpp#L199) on the `options` instance.  &#xD;&#xA;&#xD;&#xA;The interface includer API consists of the following methods:&#xD;&#xA;&#xD;&#xA;    // Handles shaderc_include_resolver_fn callbacks.&#xD;&#xA;    virtual shaderc_include_result* GetInclude(const char* requested_source,&#xD;&#xA;                                               shaderc_include_type type,&#xD;&#xA;                                               const char* requesting_source,&#xD;&#xA;                                               size_t include_depth) = 0;&#xD;&#xA;&#xD;&#xA;    // Handles shaderc_include_result_release_fn callbacks.&#xD;&#xA;    virtual void ReleaseInclude(shaderc_include_result* data) = 0;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It will therefore also be your responsibility to implement these functions and interpret the `#include` directives from the GLSL into `shaderc_include_result` instances that will be used by shaderc to complete the preprocessing of the GLSL." ContentLicense="CC BY-SA 4.0" />
  <row Id="24231" PostHistoryTypeId="2" PostId="8909" RevisionGUID="32e6c0ca-e423-4ffa-9756-d9e5fb307702" CreationDate="2019-06-16T20:58:17.180" UserId="6496" Text="I am integrating imgui into my app using glfw + vulkan example.&#xD;&#xA;&#xD;&#xA;The function vkCreateSwapchainKHR() is also called by imgui setup logic in addition to my app on the same device and it fails with &quot;internal drawable creation failed&quot;.&#xD;&#xA;&#xD;&#xA;Under what circumstances, if any, would this be a valid approach?&#xD;&#xA;&#xD;&#xA;Should my app and imgui share the same swapchain?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24232" PostHistoryTypeId="1" PostId="8909" RevisionGUID="32e6c0ca-e423-4ffa-9756-d9e5fb307702" CreationDate="2019-06-16T20:58:17.180" UserId="6496" Text="Multiple swapchains in Vulkan app with ImGui" ContentLicense="CC BY-SA 4.0" />
  <row Id="24233" PostHistoryTypeId="3" PostId="8909" RevisionGUID="32e6c0ca-e423-4ffa-9756-d9e5fb307702" CreationDate="2019-06-16T20:58:17.180" UserId="6496" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24234" PostHistoryTypeId="2" PostId="8910" RevisionGUID="c805495d-b768-4636-b2c1-e7459c27e873" CreationDate="2019-06-17T02:11:06.240" UserId="2654" Text="The Vulkan specification is very clear on this:&#xD;&#xA;&#xD;&#xA;&gt; A native window **cannot** be associated with more than one non-retired swapchain at a time.&#xD;&#xA;&#xD;&#xA;You can create a new swapchain for a surface, but only by passing the old swapchain as the `oldSwapchain` parameter, which will cause the old swapchain to enter the retired state.&#xD;&#xA;&#xD;&#xA;So yes, both you and imGUI should get on the same page about who owns the swapchain." ContentLicense="CC BY-SA 4.0" />
  <row Id="24235" PostHistoryTypeId="2" PostId="8911" RevisionGUID="e7a554e8-3753-4e0f-89b3-03a554bea9a1" CreationDate="2019-06-17T02:39:04.613" UserId="10784" Text="I've read multiple tutorials, but I still can't understand how do I properly rotate an object in 3D space on all 3 axis at once. For example, I'd like to give the object a pitch of 60 degrees, yaw of 20 degrees and roll of 70 degrees. **How can I properly do this in OpenGL, preferrably using GLM?**" ContentLicense="CC BY-SA 4.0" />
  <row Id="24236" PostHistoryTypeId="1" PostId="8911" RevisionGUID="e7a554e8-3753-4e0f-89b3-03a554bea9a1" CreationDate="2019-06-17T02:39:04.613" UserId="10784" Text="How to rotate an object in OpenGL on the X, Y and Z axis on its local coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24237" PostHistoryTypeId="3" PostId="8911" RevisionGUID="e7a554e8-3753-4e0f-89b3-03a554bea9a1" CreationDate="2019-06-17T02:39:04.613" UserId="10784" Text="|opengl|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24238" PostHistoryTypeId="2" PostId="8912" RevisionGUID="5b466a08-2bbf-456b-9677-844ea6629326" CreationDate="2019-06-17T04:46:07.910" UserId="10786" Text="The 2D pipeline involves with the construction of world coordinate scene followed by converting world coordinate to viewing coordinate, then transforming viewing coordinate to normalized coordinate and lastly converting normalized coordinate to device coordinate.&#xD;&#xA;&#xD;&#xA;I am confused. Isn't viewing coordinate and device coordinate the same things?&#xD;&#xA;Can someone give me the detail differentiation among these?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24239" PostHistoryTypeId="1" PostId="8912" RevisionGUID="5b466a08-2bbf-456b-9677-844ea6629326" CreationDate="2019-06-17T04:46:07.910" UserId="10786" Text="What is the difference between world coordinate, viewing coordinate and device coordinate in computer graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24240" PostHistoryTypeId="3" PostId="8912" RevisionGUID="5b466a08-2bbf-456b-9677-844ea6629326" CreationDate="2019-06-17T04:46:07.910" UserId="10786" Text="|transformations|2d|normal-mapping|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24241" PostHistoryTypeId="2" PostId="8913" RevisionGUID="810e9a4c-4ff5-48e2-85e7-54ac75b874ce" CreationDate="2019-06-17T09:35:29.093" UserId="10771" Text="As we know, tiles can make it quicker to update large portions of the display at once, as compared with a bitmap. To put, say a letter, on the screen, the Commodore 64 typically does two writes (the screencode and the attribute), but the ZX Spectrum typically does 9 (eight bytes which make up an 8x8 bitmap, plus 1 for the attribute).&#xD;&#xA;&#xD;&#xA;Recently, a demo for the SEGA Genesis was released called Red Eyes. My understanding is that the 3D scenes were rendered on a PC, and some kind of program converted these animations to a tileset so that each frame can quickly be written into VRAM. &#xD;&#xA;&#xD;&#xA;But, however hard I search I cannot find any contemporaneous games for these retro systems which use a tileset to render (an approximation of) three-dimensional graphics. So is there a technical reason for that?&#xD;&#xA;&#xD;&#xA;I am asking because of a game I'm trying to write for the Commodore 64. My choice of platform has meant that the compute budget really is quite miserly, so of course I need to cut down on the amount of time spent pushing pixels to the framebuffer, and tile-based graphics are an obvious solution to that problem on this platform. Also I need to keep in mind the amount of time spent in 3d projection, and I believe this problem can also be solved with tilegfx, since for example a raycaster could cast one ray tile instead of one ray per pixel. But I'm unsure about that.&#xD;&#xA;&#xD;&#xA;So the camera in my game is restricted to movement in one plane in the same way that the camera in DOOM is. It pans left and right only, and moves forward and sometimes backward. Plus I know that the walls in my game always are East-West or North-South. No diagonal walls. I think that this will mean that a manageably small number of pre-computed tiles will be enough to show the walls at various angles depending on how the camera is positioned. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The nature of this question is such that it could be answered in the following ways:&#xD;&#xA;&#xD;&#xA; * It wouldn't work because ...&#xD;&#xA; * You obviously weren't looking hard enough because here's an example of a game that does that. Here's a disassembly or source code so you can figure out how it worked&#xD;&#xA; * It might be possible, but you'd have to watch out for ...&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24242" PostHistoryTypeId="1" PostId="8913" RevisionGUID="810e9a4c-4ff5-48e2-85e7-54ac75b874ce" CreationDate="2019-06-17T09:35:29.093" UserId="10771" Text="Why don't I see tile-based 3D graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24243" PostHistoryTypeId="3" PostId="8913" RevisionGUID="810e9a4c-4ff5-48e2-85e7-54ac75b874ce" CreationDate="2019-06-17T09:35:29.093" UserId="10771" Text="|3d|tile-based-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24244" PostHistoryTypeId="2" PostId="8914" RevisionGUID="0510c373-1a1c-43c6-bc3a-541a554b9a6a" CreationDate="2019-06-17T10:46:15.140" UserId="10788" Text="I saw it here https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications__technical-specifications-per-compute-capability , I don't know if it also happens for AMD." ContentLicense="CC BY-SA 4.0" />
  <row Id="24245" PostHistoryTypeId="1" PostId="8914" RevisionGUID="0510c373-1a1c-43c6-bc3a-541a554b9a6a" CreationDate="2019-06-17T10:46:15.140" UserId="10788" Text="Why cache working set per multiprocessor for texture memory in Nvidia has a variable size?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24246" PostHistoryTypeId="3" PostId="8914" RevisionGUID="0510c373-1a1c-43c6-bc3a-541a554b9a6a" CreationDate="2019-06-17T10:46:15.140" UserId="10788" Text="|texture|memory|gpgpu|opencl|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24247" PostHistoryTypeId="2" PostId="8915" RevisionGUID="464c78f6-b9bd-4b41-8c2e-a782b5c7560e" CreationDate="2019-06-17T19:11:27.663" UserId="10789" Text="[![source: wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;download: https://upload.wikimedia.org/wikipedia/commons/5/57/Subpixel-rendering-RGB.png&#xD;&#xA;&#xD;&#xA;The  above picture is an example for sub pixel rendering. I tried resizing the image to very small size in editor by saving it onto my local machine. As I resize the image, group of pixels (sometimes all of them) turn either into Red, Green or Blue.&#xD;&#xA;&#xD;&#xA;When all 3 diodes(RGB) in a single pixel emits light, to human visual perception it produces White(1,1,1). What happens when i try to reduce the image size? How does one of the RGB color becomes dominant over the other, emitting colors other than white?&#xD;&#xA;&#xD;&#xA;Device used: Macbook Pro 15&quot; 2018&#xD;&#xA;&#xD;&#xA;My assumption on this is considering single pixel block which has three RGB sub pixels. &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;While resizing(upto its limit) the above pixel block(1x1) sits onto either one of the three sub pixel in my physical device screen(3x3 since image size is reduced) which could emit only one color. Thus any of the 3 colors become prevalent based on where the one pixel block in the image above is placed on one of the 3 subpixels of one pixel block in my physical machine.&#xD;&#xA;&#xD;&#xA;I am a newbie to computer graphics. Any clarification or brief explanation on why this happens is much appreciated.&#xD;&#xA;  [1]: https://i.stack.imgur.com/bE0In.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/0JU2p.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24248" PostHistoryTypeId="1" PostId="8915" RevisionGUID="464c78f6-b9bd-4b41-8c2e-a782b5c7560e" CreationDate="2019-06-17T19:11:27.663" UserId="10789" Text="Sub pixel rendered white text on black background changes color when resized to a very small size" ContentLicense="CC BY-SA 4.0" />
  <row Id="24249" PostHistoryTypeId="3" PostId="8915" RevisionGUID="464c78f6-b9bd-4b41-8c2e-a782b5c7560e" CreationDate="2019-06-17T19:11:27.663" UserId="10789" Text="|color|pixel-graphics|pixel-shader|pixels|subpixel-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24250" PostHistoryTypeId="5" PostId="8915" RevisionGUID="fd735aa3-c69c-46a1-8d8a-adf00176636f" CreationDate="2019-06-17T19:37:53.647" UserId="10789" Comment="added 91 characters in body" Text="[![source: wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;download: https://upload.wikimedia.org/wikipedia/commons/5/57/Subpixel-rendering-RGB.png&#xD;&#xA;&#xD;&#xA;The  above picture is an example for sub pixel rendering. I tried resizing the image to very small size in editor by saving it onto my local machine. As I resize the image, group of pixels (sometimes all of them) turn either into Red, Green or Blue.&#xD;&#xA;&#xD;&#xA;When all 3 diodes(RGB) in a single pixel emits light, to human visual perception it produces White(1,1,1). What happens when i try to reduce the image size? How does one of the RGB color becomes dominant over the other, emitting colors other than white?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Device used: Macbook Pro 15&quot; 2018&#xD;&#xA;&#xD;&#xA;My assumption on this is considering single pixel block which has three RGB sub pixels. &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;While resizing(upto its limit) the above pixel block(1x1) sits onto either one of the three sub pixel in my physical device screen(3x3 since image size is reduced) which could emit only one color. Thus any of the 3 colors become prevalent based on where the one pixel block in the image above is placed on one of the 3 subpixels of one pixel block in my physical machine.&#xD;&#xA;&#xD;&#xA;I am a newbie to computer graphics. Any clarification or brief explanation on why this happens is much appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bE0In.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2oQfu.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/0JU2p.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24251" PostHistoryTypeId="2" PostId="8916" RevisionGUID="d6eb59a5-9098-4766-b91a-191d0914864e" CreationDate="2019-06-17T21:23:57.623" UserId="10790" Text="I'm trying to learn computer graphics, but when I tried to get this very simple windower running with c&#xD;&#xA;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA;&#xD;&#xA;    #include &lt;SDL2/SDL.h&gt;&#xD;&#xA;&#xD;&#xA;    static const int width = 320;&#xD;&#xA;    static const int height = 180;&#xD;&#xA;&#xD;&#xA;    int main(int argc, char **argv)&#xD;&#xA;    {&#xD;&#xA;        SDL_Init(SDL_INIT_VIDEO);&#xD;&#xA;&#xD;&#xA;        SDL_Window *window = SDL_CreateWindow(&quot;Hello, SDL2&quot;, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);&#xD;&#xA;&#xD;&#xA;        SDL_DestroyWindow(window);&#xD;&#xA;        SDL_Quit();&#xD;&#xA;&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;I try to compile and...&#xD;&#xA;&#xD;&#xA;    vke@komputilo:~/dev/MiaLudo/source$ gcc -g main.c -o ../ludo&#xD;&#xA;    /tmp/ccfVU5ua.o: In function `main':&#xD;&#xA;    /home/vke/dev/MiaLudo/source/main.c:11: undefined reference to `SDL_Init'&#xD;&#xA;    /home/vke/dev/MiaLudo/source/main.c:13: undefined reference to `SDL_CreateWindow'&#xD;&#xA;    /home/vke/dev/MiaLudo/source/main.c:15: undefined reference to `SDL_DestroyWindow'&#xD;&#xA;    /home/vke/dev/MiaLudo/source/main.c:16: undefined reference to `SDL_Quit'&#xD;&#xA;    collect2: error: ld returned 1 exit status&#xD;&#xA;Hoping someone can help me out, I'm running Trisquel Linux if that's important" ContentLicense="CC BY-SA 4.0" />
  <row Id="24252" PostHistoryTypeId="1" PostId="8916" RevisionGUID="d6eb59a5-9098-4766-b91a-191d0914864e" CreationDate="2019-06-17T21:23:57.623" UserId="10790" Text="sdl2: Compiler throws &quot;Undefined Reference&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24253" PostHistoryTypeId="3" PostId="8916" RevisionGUID="d6eb59a5-9098-4766-b91a-191d0914864e" CreationDate="2019-06-17T21:23:57.623" UserId="10790" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24254" PostHistoryTypeId="2" PostId="8917" RevisionGUID="d0cf4d4f-2ae1-41ec-95dc-bd89c5106fc4" CreationDate="2019-06-18T19:24:40.133" UserId="10787" Text="I'm trying to draw a line between two specified points, by updating values in an array which is heightxWidth with each element a set of four bytes (r,g,b,a). In my naive implementation I get the top line which reaches a point with jagged steps in the top line shown below. My question is, how do I accomplish the standard canvas line effect without jumps seen here as the lower line shown below? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6uPsq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24255" PostHistoryTypeId="1" PostId="8917" RevisionGUID="d0cf4d4f-2ae1-41ec-95dc-bd89c5106fc4" CreationDate="2019-06-18T19:24:40.133" UserId="10787" Text="Non jagged line algorithm for javascript canvas" ContentLicense="CC BY-SA 4.0" />
  <row Id="24256" PostHistoryTypeId="3" PostId="8917" RevisionGUID="d0cf4d4f-2ae1-41ec-95dc-bd89c5106fc4" CreationDate="2019-06-18T19:24:40.133" UserId="10787" Text="|algorithm|javascript|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24260" PostHistoryTypeId="2" PostId="8919" RevisionGUID="3a0ca202-445e-4431-abdf-be2255b7c326" CreationDate="2019-06-19T08:26:27.210" UserId="10798" Text="I am after a simple (not necessarily efficient) algorithm to &quot;continuously&quot; transform a closed surface mesh into a sphere. &#xD;&#xA;&#xD;&#xA;It seems that Blender is able to do this quite well: https://docs.blender.org/manual/en/latest/modeling/meshes/editing/transform/to_sphere.html &#xD;&#xA;&#xD;&#xA;However I cannot find a reference, or technical description of the algorithm they use. I tried looking at [the code](https://github.com/sobotka/blender/blob/5767dcbe60c07cd9ef113e2f54eaad6981a47bce/source/blender/editors/transform/transform.c#L4168) but did not managed to figure out what it does unfortunately." ContentLicense="CC BY-SA 4.0" />
  <row Id="24261" PostHistoryTypeId="1" PostId="8919" RevisionGUID="3a0ca202-445e-4431-abdf-be2255b7c326" CreationDate="2019-06-19T08:26:27.210" UserId="10798" Text="Inflate 3D mesh into sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="24262" PostHistoryTypeId="3" PostId="8919" RevisionGUID="3a0ca202-445e-4431-abdf-be2255b7c326" CreationDate="2019-06-19T08:26:27.210" UserId="10798" Text="|transformations|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24263" PostHistoryTypeId="2" PostId="8920" RevisionGUID="72fd1187-6646-4e97-a56c-d05eec41e8fa" CreationDate="2019-06-19T08:58:49.617" UserId="137" Text="The core calculation seems to be &#xD;&#xA;&#xD;&#xA;      sub_v3_v3v3(vec, td-&gt;iloc, tc-&gt;center_local);&#xD;&#xA;&#xD;&#xA;      radius = normalize_v3(vec);&#xD;&#xA;&#xD;&#xA;      tratio = ratio * td-&gt;factor;&#xD;&#xA;&#xD;&#xA;      mul_v3_fl(vec, radius * (1.0f - tratio) + t-&gt;val * tratio);&#xD;&#xA;&#xD;&#xA;      add_v3_v3v3(td-&gt;loc, tc-&gt;center_local, vec);&#xD;&#xA;&#xD;&#xA;Which in C-ish psuedo code looks like&#xD;&#xA;&#xD;&#xA;    vec = pos - center; //find vector from center to point&#xD;&#xA;    radius = length(vec); // get the length of the vector&#xD;&#xA;    vec = vec / radius;  //normalize the vector&#xD;&#xA;&#xD;&#xA;    tratio = ratio * individual_sensitivity; // adjust sensitivity per vertex &#xD;&#xA;&#xD;&#xA;    vec = lerp(vec * radius, vec * t-&gt;val, tratio); //linearly interpolate between the original and where the point would be on the sphere&#xD;&#xA;    &#xD;&#xA;    pos = center + vec; // store result&#xD;&#xA;&#xD;&#xA;So the code projects the point to the sphere and linearly interpolates the point between the original location and the sphere location. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24264" PostHistoryTypeId="2" PostId="8921" RevisionGUID="aa96bdc0-2dc4-412b-820a-5a87ae7fccec" CreationDate="2019-06-19T16:52:31.163" UserId="228" Text="According to [Polygon-Mesh-Processing][1], section 7.2.2. paragraph &quot;Error quadrics&quot;&#xD;&#xA;&#xD;&#xA;&gt; Error quadrics have major advantages regarding memory consumption and computational efficiency: each vertex $x$ stores a symmetric 4x4 matrix $Q$ only, and the error can efficiently be computed in constant time as $x^T Q x$ - no matter how many planes are associated to vertex $x$ during decimation. Because of this, error quadrics are one of the most frequently employed techniques in mesh decimation.&#xD;&#xA;&#xD;&#xA;The author of the reference I mentioned specifically refers to the paper you mention in your question. My interpretation is that more recent methods might be more sophisticated but resource-wise quadric errors are still better.&#xD;&#xA;&#xD;&#xA;Also I'd add is relatively easy to implement anyway.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books?id=8zX-2VRqBAkC&amp;printsec=frontcover&amp;dq=polygon%20mesh%20processing&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwj6tK_o__XiAhWFY8AKHanSCBYQ6AEIKjAA#v=onepage&amp;q=polygon%20mesh%20processing&amp;f=false" ContentLicense="CC BY-SA 4.0" />
  <row Id="24268" PostHistoryTypeId="2" PostId="8923" RevisionGUID="c9885a40-0033-4075-b408-0bffd7ded5bc" CreationDate="2019-06-21T08:25:26.283" UserId="209" Text="The problem you are seeing, i.e. &quot;jaggies&quot; or &quot;staircasing&quot;, is an example of the more general problem known as *&quot;aliasing&quot;* and, in the graphics field, the term you want to search for is *&quot;Antialiasing&quot;*. &#xD;&#xA;&#xD;&#xA;Aliasing occurs when you undersample a signal. If a signal contains frequencies *at* or above the [Nyquist Frequency][1], which is 1/2 the sampling frequency, those higher frequencies will come back &quot;in disguise&quot; i.e. &quot;under an alias&quot;.&#xD;&#xA;&#xD;&#xA;The example I often give to new starters to explain the problem is:&#xD;&#xA;&gt; *Imagine you've started at a new job and work solidly, 9 to 5, __except__ for a 1hr break from 12 to 1. &lt;br&gt;&#xD;&#xA;The boss, however, regularly walks around the building at 12:30 and never sees you at your desk. He therefore concludes you are lazy and so don't get a pay rise*&#xD;&#xA;&#xD;&#xA;That is an example of aliasing. The boss needs to sample at a (much) higher rate. (Randomised/stratified sampling would also help :-) )&#xD;&#xA;&#xD;&#xA;In your line drawing example, I expect you are taking one sample per pixel, but if you do a Fourier analysis of a line, you will see it contains an infinite spread of frequencies. It's these higher frequencies (plus the reconstruction of the sampled results - which I've ignored) that can lead to the jaggy results. &#xD;&#xA;&#xD;&#xA;The ideal solution is to low pass filter your incoming signal before sampling it, but that's 'nontrivial' with geometric data.&#xD;&#xA;&#xD;&#xA;There are, however, multiple practical approaches to mitigating the problem, including supersampling (SSAA) and multispampling (MSAA), but in your case, perhaps something like [Wu's method][2] for antialiased line drawing will suffice.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Nyquist_frequency&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="24273" PostHistoryTypeId="2" PostId="8925" RevisionGUID="4d87501c-aa83-4ce8-8535-c535ddab36b7" CreationDate="2019-06-21T20:11:48.200" UserDisplayName="user10808" Text="I am trying to understand this seminal [paper][1]. I read this [post][2] on what affine transformations and my understanding is that **affine transformations** are transformations that preserve parallelism of lines such as rotation, translation, etc, but *NOT* distortions of partials of the image, and other related transformations that cause previously parallel lines to no longer be parallel. &#xD;&#xA;&#xD;&#xA;I also understand that **covariant regions** are the same region being detected from two different view points. &#xD;&#xA;&#xD;&#xA;However, in the paper, they use the term &quot;**affine covariant regions**&quot; and state that they can be &quot;exploited to cope with geometric and photometric deformations&quot; (5th paragraph if introduction). This sentence throws off my understanding because I don't quite understand what it means when both terms are combined (affine - covariant). It's probably a subtle difference. Can someone please clarify?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.robots.ox.ac.uk/~vgg/research/affine/det_eval_files/vibes_ijcv2004.pdf&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/q/391/10808" ContentLicense="CC BY-SA 4.0" />
  <row Id="24274" PostHistoryTypeId="1" PostId="8925" RevisionGUID="4d87501c-aa83-4ce8-8535-c535ddab36b7" CreationDate="2019-06-21T20:11:48.200" UserDisplayName="user10808" Text="What are affine covariant regions" ContentLicense="CC BY-SA 4.0" />
  <row Id="24275" PostHistoryTypeId="3" PostId="8925" RevisionGUID="4d87501c-aa83-4ce8-8535-c535ddab36b7" CreationDate="2019-06-21T20:11:48.200" UserDisplayName="user10808" Text="|transformations|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24276" PostHistoryTypeId="2" PostId="8926" RevisionGUID="773cc266-baaa-416d-ad26-3b499de3d5d0" CreationDate="2019-06-21T20:28:22.657" UserId="10809" Text="We're actually going through that paper for our own GGX BRDF metallic &amp; edge_tint model, and we've spotted one crucial problem.&#xD;&#xA;&#xD;&#xA;Hammon is still using the Fresnel Schlick approximation for his microfacet field ray-trace which in reality only works for dielectrics (and conductors but with a hack).&#xD;&#xA;&#xD;&#xA;But we went all out on actual Fresnel (discarding polarization) and do the full calculation, enabling us to set $F_0=0$ when we do not wish for specular on a surface at all.&#xD;&#xA;&#xD;&#xA;https://github.com/Crisspl/IrrlichtBAW/commit/914b50d7238fc4a30f23fc2a4ea570e467f4ab75#r34031272&#xD;&#xA;&#xD;&#xA;The problem is that Schlick falls apart for $F_0&lt;0.02$, so the GGX diffuse would be too dark for those materials (because its still assuming low transmittivity at glancing angles).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As an aside, something that stinks to me is that DIS and PBR use &#xD;&#xA;$(1-F(\theta_i))(1-F(\theta_o))$ which is a split-sum approximation (fresnel with average facet normal) instead of the proper calculation which would be weighted average of fresnel with every facet normal possible, weighted of course by the normal distribution function.&#xD;&#xA;&#xD;&#xA;In PBR the `smooth` component could stay as-is (except that the Schlick would need replacing by proper Fresnel) but I wonder what `rough` and `multi` would have to become with an $F_0&lt;0.02$ .&#xD;&#xA;&#xD;&#xA;I guess that `rough` would probably change very little, but enough to make a difference (since with $\alpha=1$ GGX NDF is a constant) if $F_0=0$.  &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope we could drop E. Hammon an email and see if the simulation could be re-run for full Fresnel and the extended IoR (F0) range, 1.0 (0.0) inclusive." ContentLicense="CC BY-SA 4.0" />
  <row Id="24278" PostHistoryTypeId="5" PostId="8915" RevisionGUID="33287f4d-76af-451d-a6ea-dc5d2353db85" CreationDate="2019-06-22T09:29:45.283" UserId="10794" Comment="Response to comments" Text="[![source: wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;download: https://upload.wikimedia.org/wikipedia/commons/5/57/Subpixel-rendering-RGB.png&#xD;&#xA;&#xD;&#xA;The  above picture is an example for sub pixel rendering. I tried resizing the image to very small size in editor by saving it onto my local machine. As I resize the image, group of pixels (sometimes all of them) turn either into Red, Green or Blue.&#xD;&#xA;&#xD;&#xA;When all 3 diodes(RGB) in a single pixel emits light, to human visual perception it produces White(1,1,1). What happens when i try to reduce the image size? How does one of the RGB color becomes dominant over the other, emitting colors other than white?&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Device used: Macbook Pro 15&quot; 2018&#xD;&#xA;&#xD;&#xA;My assumption on this is considering single pixel block which has three RGB sub pixels. &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;While resizing(upto its limit) the above pixel block(1x1) sits onto either one of the three sub pixel in my physical device screen(3x3 since image size is reduced) which could emit only one color. Thus any of the 3 colors become prevalent based on where the one pixel block in the image above is placed on one of the 3 subpixels of one pixel block in my physical machine.&#xD;&#xA;&#xD;&#xA;I am a newbie to computer graphics. Any clarification or brief explanation on why this happens is much appreciated.&#xD;&#xA;&#xD;&#xA;Update: @Olivier I resized the image using mousepad(Zoom out using two finger pinch) on Preview app in mac&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bE0In.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2oQfu.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/0JU2p.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24279" PostHistoryTypeId="24" PostId="8915" RevisionGUID="33287f4d-76af-451d-a6ea-dc5d2353db85" CreationDate="2019-06-22T09:29:45.283" Comment="Proposed by 10794 approved by 209, 10789 edit id of 477" ContentLicense="CC BY-SA 4.0" />
  <row Id="24281" PostHistoryTypeId="5" PostId="8926" RevisionGUID="3aced800-1d65-4332-81f6-3c792d30b84b" CreationDate="2019-06-22T13:22:41.810" UserId="10809" Comment="added 171 characters in body" Text="We're actually going through that paper for our own GGX BRDF metallic &amp; edge_tint model, and we've spotted one crucial problem.&#xD;&#xA;&#xD;&#xA;Hammon is still using the Fresnel Schlick approximation for his microfacet field ray-trace which in reality only works for dielectrics (and conductors but with a hack).&#xD;&#xA;&#xD;&#xA;But we went all out on actual Fresnel (discarding polarization) and do the full calculation, enabling us to set $F_0=0$ when we do not wish for specular on a surface at all.&#xD;&#xA;&#xD;&#xA;https://github.com/Crisspl/IrrlichtBAW/commit/914b50d7238fc4a30f23fc2a4ea570e467f4ab75#r34031272&#xD;&#xA;&#xD;&#xA;The problem is that Schlick falls apart for $F_0&lt;0.02$, so the GGX diffuse would be too dark for those materials (because its still assuming low transmittivity at glancing angles).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As an aside, something that stinks to me is that DIS and PBR use &#xD;&#xA;$(1-F(\theta_i))(1-F(\theta_o))$ which is a split-sum approximation (fresnel with average facet normal) instead of the proper calculation which would be weighted average of fresnel with every facet normal possible, weighted of course by the normal distribution function.&#xD;&#xA;&#xD;&#xA;In PBR the `smooth` component could stay as-is (except that the Schlick would need replacing by proper Fresnel) but I wonder what `rough` and `multi` would have to become with an $F_0&lt;0.02$ .&#xD;&#xA;&#xD;&#xA;I guess that `rough` would probably change very little, but enough to make a difference (since with $\alpha=1$ GGX NDF is a constant) if $F_0=0$.  &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I hope we could drop E. Hammon an email and see if the simulation could be re-run for full Fresnel and the extended IoR (F0) range, 1.0 (0.0) inclusive.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: Seb. Lagarde also has the same concern as I did about the Fresnel used http://openproblems.realtimerendering.com/s2017/02-PhysicallyBasedMaterialWhereAreWe.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24282" PostHistoryTypeId="2" PostId="8927" RevisionGUID="a3969942-d4f0-4277-8dcd-f5b6c45131d5" CreationDate="2019-06-22T13:22:55.483" UserId="7008" Text="I have a working renderer implemented with Java in JOGL with [NEWT][1]. Now I want to implement a Material Editor which should run in a second window. However I can't get a second window up and render in it.&#xD;&#xA;&#xD;&#xA;My main window is implemented as follows:&#xD;&#xA;I have a class `Backend` which implements the `GLEventListener`. The two important methods are:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    public static void initOpenGl()&#xD;&#xA;	{&#xD;&#xA;		GLProfile.initSingleton();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;which is called before anything else happens on start up and, to create the window itself&#xD;&#xA;&#xD;&#xA;	public void createWindow(int windowWidth, int windowHeight, boolean isFullscreen, String windowTitle&#xD;&#xA;			, Program program)&#xD;&#xA;	{&#xD;&#xA;		GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3));&#xD;&#xA;        caps.setBackgroundOpaque(false);&#xD;&#xA;        glWindow = GLWindow.create(caps);&#xD;&#xA;        &#xD;&#xA;		glWindow.setTitle(windowTitle);&#xD;&#xA;		glWindow.setSize(windowWidth, windowHeight);&#xD;&#xA;		glWindow.setUndecorated(false);&#xD;&#xA;		glWindow.setPointerVisible(true);&#xD;&#xA;		glWindow.setVisible(true);&#xD;&#xA;		&#xD;&#xA;		m_program = program;&#xD;&#xA;		glWindow.addGLEventListener(this);&#xD;&#xA;		glWindow.addKeyListener(m_program);&#xD;&#xA;		glWindow.addMouseListener(m_program);&#xD;&#xA;		m_program.setBackend(this);&#xD;&#xA;&#xD;&#xA;		Animator animator = new Animator();&#xD;&#xA;        animator.add(glWindow);&#xD;&#xA;        animator.start();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;*TRY 1*&#xD;&#xA;&#xD;&#xA;In my first attempt, I created a subwindow thus:&#xD;&#xA;&#xD;&#xA;	public void createSubWindow(int windowWidth, int windowHeight, boolean isFullscreen, String windowTitle&#xD;&#xA;			, Program program)&#xD;&#xA;	{&#xD;&#xA;&#xD;&#xA;		Display display = NewtFactory.createDisplay(&quot;mystring&quot;);&#xD;&#xA;		display.addReference();&#xD;&#xA;&#xD;&#xA;		Screen screen = NewtFactory.createScreen(display, 0);&#xD;&#xA;		screen.addReference();&#xD;&#xA;&#xD;&#xA;		GLProfile profile = GLProfile.get(GLProfile.GL3);&#xD;&#xA;		GLCapabilities caps = new GLCapabilities(profile);&#xD;&#xA;		GLWindow window = GLWindow.create(screen, caps);&#xD;&#xA;		//the following line does not work, context is null&#xD;&#xA;		GLContext context = window.createContext(GLContext.getCurrent());&#xD;&#xA;&#xD;&#xA;		window.setSize(windowWidth, windowHeight);&#xD;&#xA;		window.setVisible(true);&#xD;&#xA;		window.setTitle(windowTitle);&#xD;&#xA;&#xD;&#xA;		System.out.println(windowTitle + &quot; window is open!&quot;);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Since the context is null however, an exception is thrown:&#xD;&#xA;&#xD;&#xA;&gt; No OpenGL context current on this thread&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;*TRY2*&#xD;&#xA;&#xD;&#xA;In my second try I created a `SubWindow` class much like the `Backend` class, which implements `GLEventListener` and has the same `createWindow` method. This throws a different exception:&#xD;&#xA;&#xD;&#xA;&gt; com.jogamp.opengl.GLException: Caught ThreadDeath: null on thread main-Display-.windows_nil-1-EDT-1-AWTAnimator#01&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Perhaps the question would be better stated as &quot;how to create a second GL Context&quot;, I am not exactly sure.&#xD;&#xA;&#xD;&#xA;  [1]: https://jogamp.org/jogl/doc/NEWT-Overview.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="24283" PostHistoryTypeId="1" PostId="8927" RevisionGUID="a3969942-d4f0-4277-8dcd-f5b6c45131d5" CreationDate="2019-06-22T13:22:55.483" UserId="7008" Text="How to open and render in a second window with OpenGL / JOGL with NEWT" ContentLicense="CC BY-SA 4.0" />
  <row Id="24284" PostHistoryTypeId="3" PostId="8927" RevisionGUID="a3969942-d4f0-4277-8dcd-f5b6c45131d5" CreationDate="2019-06-22T13:22:55.483" UserId="7008" Text="|opengl|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24301" PostHistoryTypeId="2" PostId="8933" RevisionGUID="f1c2578c-f658-4f99-b6ae-02f9cd3f827a" CreationDate="2019-06-24T10:05:33.653" UserId="10826" Text="I have a list of 3D points defined by Cartesian coordinates, i.e. *[(x1,y1,z1), (x2,y2,z2), ..., (xn,yn,zn)]*. I want to project them to a 2D plane which has origin in the center (0,0,0) but which is rotated by polar angle theta, and azimuthal angle phi (*).&#xD;&#xA;&#xD;&#xA;As far as I understand I need some kind of 3x2 matrix that when multiplied  with my points matrix nx3 will give me my projection in 2D.&#xD;&#xA;&#xD;&#xA;*nx3 matrix-multiply 3x2 = nx2*&#xD;&#xA;&#xD;&#xA;How to calculate this matrix if I know the angles of the plane rotation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If it helps here's a quick explanation what I'm trying to do. I have a 3d object consisting of point cloud, which is centered in the origin and I want to calculate how it looks from a camera placed on different points that are on equal distance from the origin,  looking directly toward the origin, and with light coming from the camera and toward the origin. &#xD;&#xA;&#xD;&#xA;(*) I'm not sure does does those two angle define the plane in a unique way. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24302" PostHistoryTypeId="1" PostId="8933" RevisionGUID="f1c2578c-f658-4f99-b6ae-02f9cd3f827a" CreationDate="2019-06-24T10:05:33.653" UserId="10826" Text="How to find matrix that projects 3d points into 2d plane centered in the origin?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24303" PostHistoryTypeId="3" PostId="8933" RevisionGUID="f1c2578c-f658-4f99-b6ae-02f9cd3f827a" CreationDate="2019-06-24T10:05:33.653" UserId="10826" Text="|transformations|matrix|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24309" PostHistoryTypeId="2" PostId="8935" RevisionGUID="7123733e-34ba-405a-bcd9-6027498d4dcf" CreationDate="2019-06-25T15:11:41.940" UserId="8598" Text="Inkscape has a feature called Power Stroke which is a form of path effect.  When you apply it to a stroke you gain 3 control points that allow you to adjust the thickness of the stroke.  (I have not yet figured out how to add more control points through the UI, but it can be done in the XML editor).&#xD;&#xA;&#xD;&#xA;Inspecting the SVG reveals that the stroke gets turned into a fill with a path@d that specifies the outline, allowing the SVG file to be rendered by applications that know nothing of Power Stroke.&#xD;&#xA;&#xD;&#xA;Applications that do understand Power Stroke will be looking for these attributes on the `&lt;path&gt;`:&#xD;&#xA;&#xD;&#xA;       inkscape:path-effect=&quot;#path-effect881&quot;&#xD;&#xA;       inkscape:original-d=&quot;m 109.59491,132.23789 c -19.148152,28.51854 -37.80734,35.62606 -46.969458,22.13393 -9.383889,-13.81871 -39.69277,-3.57313 -46.276359,5.34215 -16.01795169,21.691 17.695947,71.79071 39.993907,62.61593 17.000232,-6.99496 23.845432,-20.30176 23.845432,-20.30176&quot;&#xD;&#xA;&#xD;&#xA;The definition of the PowerStroke control points occurs inside the `&lt;defs&gt;`&#xD;&#xA;&#xD;&#xA;    &lt;inkscape:path-effect&#xD;&#xA;       effect=&quot;powerstroke&quot;&#xD;&#xA;       id=&quot;path-effect881&quot;&#xD;&#xA;       is_visible=&quot;true&quot;&#xD;&#xA;       offset_points=&quot;0.11606368,4.5282059 | 0.61857805,2.0941625 | 1.992627,6.538108 | 2.7945971,4.4492524&quot;&#xD;&#xA;       sort_points=&quot;true&quot;&#xD;&#xA;       interpolator_type=&quot;CubicBezierFit&quot;&#xD;&#xA;       interpolator_beta=&quot;0.2&quot;&#xD;&#xA;       start_linecap_type=&quot;round&quot;&#xD;&#xA;       linejoin_type=&quot;bevel&quot;&#xD;&#xA;       miter_limit=&quot;4&quot;&#xD;&#xA;       end_linecap_type=&quot;butt&quot; /&gt;&#xD;&#xA;&#xD;&#xA;I have concluded that the @offset_points list can be interpreted as a list of t,r tuples, where t=0 is the first &quot;major&quot; control point in the path@d, and t=1 is the next.  A segment that is a cubic bezier curve is traditionally interpreted as having 4 control points, but for the purpose of path effects, the first and last control points are what I have termed &quot;major&quot; control points, and are shared with the segments on either side.&#xD;&#xA;&#xD;&#xA;What I do not yet understand is the @interpolator_type, likewise the @interpolator_beta.  I assume this controls how you interpolate the radius you calculate between the different offset_points, but I'm not sure what exact formula to use.  When I think Bezier, I think of Bezier curves, and how they only match up with their control points at the end of the segment.  I think the _beta corresponds to the &quot;smoothness&quot; field in the UI.&#xD;&#xA;&#xD;&#xA;If I wanted to calculate the Power Stroke radius at t=1.32, what formula would I use?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24310" PostHistoryTypeId="1" PostId="8935" RevisionGUID="7123733e-34ba-405a-bcd9-6027498d4dcf" CreationDate="2019-06-25T15:11:41.940" UserId="8598" Text="What is the mathematics behind inkscape's power stroke path effect interpolator_type and interpolator_beta attributes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24311" PostHistoryTypeId="3" PostId="8935" RevisionGUID="7123733e-34ba-405a-bcd9-6027498d4dcf" CreationDate="2019-06-25T15:11:41.940" UserId="8598" Text="|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24312" PostHistoryTypeId="2" PostId="8936" RevisionGUID="7dd717af-b7aa-4cfc-9be5-ace9abcb3580" CreationDate="2019-06-25T16:19:50.057" UserId="10834" Text="Could someone please provide me with/point me to a description of the process involved in displaying a digital image? **Starting from reading the data from a file to displaying the image on the screen**. &#xD;&#xA;&#xD;&#xA;I am puzzled regarding which parts of this process are handled by the OS and which are handled by the GPU.&#xD;&#xA;&#xD;&#xA;I am especially interested in the transition from the initial, device-independent representation of the image to controlling the actual physical pixels on the screen. For example, how does a 1920x1080 image eventually get displayed on screens with higher or lower display resolutions? " ContentLicense="CC BY-SA 4.0" />
  <row Id="24313" PostHistoryTypeId="1" PostId="8936" RevisionGUID="7dd717af-b7aa-4cfc-9be5-ace9abcb3580" CreationDate="2019-06-25T16:19:50.057" UserId="10834" Text="Description of the process involved in displaying digital images" ContentLicense="CC BY-SA 4.0" />
  <row Id="24314" PostHistoryTypeId="3" PostId="8936" RevisionGUID="7dd717af-b7aa-4cfc-9be5-ace9abcb3580" CreationDate="2019-06-25T16:19:50.057" UserId="10834" Text="|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24318" PostHistoryTypeId="2" PostId="8939" RevisionGUID="7acbf00c-78b5-4445-9f08-f79175a23705" CreationDate="2019-06-26T06:58:29.853" UserId="10837" Text="&gt; Starting from reading the data from a file to displaying the image on the screen.&#xD;&#xA;&#xD;&#xA;As was pointed out in the comments, this is an extremely broad question, and depends on what operating system you're using, and which tool sets for that OS you're using. That said, I think it is possible to talk generally about the process with much of it (if not all) being similar from machine to machine, and OS to OS.&#xD;&#xA;&#xD;&#xA;&gt;I am puzzled regarding which parts of this process are handled by the OS and which are handled by the GPU.&#xD;&#xA;&#xD;&#xA;I'll try to point out which parts are handled strictly by the OS, your program, and the graphics hardware, and I'll even provide C-like pseudo code. My pretend code will not be efficient, simply illustrative, and I'll be pretending to read [this example](https://en.wikipedia.org/wiki/Netpbm_format#PPM_example) image file.&#xD;&#xA;&#xD;&#xA;&gt;For example, how does a 1920x1080 image eventually get displayed on screens with higher or lower display resolutions?&#xD;&#xA;&#xD;&#xA;I think some of my pretend pseudo code will illustrate that, but the short answer is that you will manually resize your image to better fit the screen (or any other drawing area) inside your program.&#xD;&#xA;&#xD;&#xA;#The Long Answer&#xD;&#xA;&#xD;&#xA;The first step is to open the image file. It doesn't matter what the format of the image is, from the view of your program it'll simply be a list of bytes. Some languages have tools and libraries that can be used to open files in a generic (OS independent) way, but often this step is OS specific. However, even though the task of opening and/or reading the file is dependent on the operating system, once your program has copied the content into memory it's just bytes for your program to deal with however you desire.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;File imgFile = OS_OPEN_FILE(&quot;sample.ppm&quot;); // Ask the OS for a file.&#xD;&#xA;byte buffer[imgFile.size()];               // Set aside memory to hold the file's content.&#xD;&#xA;for(int i = 0; i &lt; imgFile.size(); ++i) {  // Start a reading loop.&#xD;&#xA;    buffer[i] = OS_READ_BYTE(imgFile);     // Ask the OS for all bytes in the file, one by one.&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Once you have access to all of the bytes in the entire image file it is up to you, the programmer, to know what each byte means, then to make your program read and interpret them correctly. For example, the [portable bitmap format](https://en.wikipedia.org/wiki/Netpbm_format) starts with a couple of bytes letting you know if the picture file is color, gray scale, or black and white. There are bytes that let you know what size the picture is, bytes that should be ignored because they're comments intended for humans to read, and finally bytes that are the dots of color to be sent to the screen. It is up to the program to sort through all of that.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;int bufSize = imgFile.size();&#xD;&#xA;for(int i = 0; i &lt; bufSize; ++i) {  // loop through all the bytes read earlier.&#xD;&#xA;    if(buffer[i] == 'P' &amp;&amp; buffer[i+1] == '3') {  // Handle the image header.&#xD;&#xA;        /* Do something */&#xD;&#xA;    }&#xD;&#xA;    else if(buffer[i] == '#') {  // Handle comments&#xD;&#xA;        /* Do something */&#xD;&#xA;    }&#xD;&#xA;    else if(buffer[i] == /*...*/) {&#xD;&#xA;        /* Do something */&#xD;&#xA;    }&#xD;&#xA;   /* ... etc. */&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The next task is OS specific. You'll need to somehow ask the operating system to give your program access to a &quot;drawing surface&quot;. Again, there are libraries such as [SDL](https://www.libsdl.org/) or [SFML](https://www.sfml-dev.org/) that provide surfaces in a generic way, but they are hiding the surface the system gave them behind an easy to use wrapper.&#xD;&#xA;&#xD;&#xA;Often the drawing surface given by the OS is just a big block of bytes and you can simply copy data into it. Again, it is up to you to know which byte does what (like, which bytes represent red, green, or blue), but the task itself is usually just to copy from one chunk of memory into another. This is known as a **Bl**ock **I**mage **T**ransfer, or a BLIT, and it's at this point that you may be handling memory inside the graphics card. Ultimately, it's up to the OS to decide where the drawing surface keeps the bytes that represent colors, but you can usually request that those bytes be on the GPU.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Surface sampleImage = OS_GET_GPU_DRAWING_SURFACE();&#xD;&#xA;if(sampleImage.good()) {&#xD;&#xA;    /* Copy in bytes from buffer[], sorting or converting data as needed. */&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Depending on what tools you're using, and what task you're performing, a drawing surface you request from the OS can be the screen itself, and other times the screen is something that you can't touch directly but can only send surfaces to. Even when you *can* draw directly to the screen you will want to draw to a hidden surface, then blit the finished work over to the screen to prevent flickering and other visual problems. This is called [double buffering](https://gameprogrammingpatterns.com/double-buffer.html), and mostly applies to the screen because it's always visible to the user.&#xD;&#xA;&#xD;&#xA;Generally you will have many small drawing surfaces that represent things like, buttons, pieces of terrain in a game, letters, or whatever, and you'll use those to assemble a larger image on a bigger (usually screen sized) drawing surface that you will finally send to the screen as one big block.&#xD;&#xA;&#xD;&#xA;Just to reiterate, these steps are all being done by your program, but the way your program has to do them is OS specific, and much of the memory being handled at this late stage is *probably* on the GPU.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// Ready the screen and a drawing area.&#xD;&#xA;Surface * screen = OS_GET_SCREEN_SURFACE();&#xD;&#xA;Surface * screenBuffer = OS_GET_GPU_DRAWING_SURFACE();&#xD;&#xA;&#xD;&#xA;// Make the image 800% bigger!&#xD;&#xA;sampleImage.resize(8.0f);&#xD;&#xA;// Copy the image to the screen sized buffer, centering it.&#xD;&#xA;// blitTo(surface, x, y)&#xD;&#xA;// I'm assuming that in this pretend code images draw from their top left corner.&#xD;&#xA;sampleImage.blitTo(screenBuffer,&#xD;&#xA;                   screenBuffer.width()/2 - sampleImage.width()/2,&#xD;&#xA;                   screenBuffer.height()/2 - sampleImage.height()/2);&#xD;&#xA;/* ... etc. */&#xD;&#xA;/* Do more image drawing work. */&#xD;&#xA;&#xD;&#xA;// Finally, display all our complex behind the scenes work to the user.&#xD;&#xA;// This is called a buffer swap.&#xD;&#xA;Surface * temp = NULL;&#xD;&#xA;temp = screen;&#xD;&#xA;screen = screenBuffer;&#xD;&#xA;screenBuffer = temp;&#xD;&#xA;temp = NULL;&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;#The Short Answer&#xD;&#xA;&#xD;&#xA;In summary...&#xD;&#xA;&#xD;&#xA;Task your program needs to do (what's primarily in charge):&#xD;&#xA;&#xD;&#xA;1. Open a file (OS)&#xD;&#xA;2. Read file (OS &amp; Program)&#xD;&#xA;3. Interpret data (Program)&#xD;&#xA;4. Get a drawing surface (OS &amp; GPU)&#xD;&#xA;5. Fill the drawing surface with image data. (Program &amp; GPU)&#xD;&#xA;6. Assemble your final picture. (Program &amp; GPU)&#xD;&#xA;7. Gain access to the screen (OS)&#xD;&#xA;8. Send your final picture to the screen. (OS and/or Program)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24319" PostHistoryTypeId="2" PostId="8940" RevisionGUID="a68101ff-3db5-43de-89c4-1b428e05572b" CreationDate="2019-06-26T09:26:08.207" UserId="10840" Text="Typically when coplanar or nearly coplanar polygons are rendered in OpenGL, the textures of each polygon mix together in a non-deterministic way. My understanding is that this is caused by the limited precision of the z-buffer as it uses floating point values. However, there seems to be an exception to this case. I've noticed that when two polygons are rendered with the exact same vertex positions, z-fighting does not occur. The polygon that was rendered last appears on top of the other coplanar polygon.&#xD;&#xA;&#xD;&#xA;Why does this occur? Does this behavior always occur? Is this behavior guaranteed across all OpenGL implementations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24320" PostHistoryTypeId="1" PostId="8940" RevisionGUID="a68101ff-3db5-43de-89c4-1b428e05572b" CreationDate="2019-06-26T09:26:08.207" UserId="10840" Text="Why do identical polygons not z-fight in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24321" PostHistoryTypeId="3" PostId="8940" RevisionGUID="a68101ff-3db5-43de-89c4-1b428e05572b" CreationDate="2019-06-26T09:26:08.207" UserId="10840" Text="|opengl|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24322" PostHistoryTypeId="2" PostId="8941" RevisionGUID="cc3c4865-7cde-4053-8f0f-61b4b5bc6fd2" CreationDate="2019-06-26T09:39:57.580" UserId="3073" Text="That would be because the GPU is deterministic. For the same inputs (vertex positions) it should produce the exact same per pixel depth outputs. &#xD;&#xA;&#xD;&#xA;Z-Fighting usually occurs with polygons with different vertex positions but still on the same plane, so interpolation rounding errors show up as differences and hence Z-fighting.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24325" PostHistoryTypeId="2" PostId="8942" RevisionGUID="3152aabb-60ca-4863-9079-10d299f84287" CreationDate="2019-06-26T17:06:01.140" UserId="2654" Text="There are explicit rules in the OpenGL specification about invariance guarantees. For the purpose of this discussion, these rules boil down to the following.&#xD;&#xA;&#xD;&#xA;Given a particular series of vertex processing shaders (VS, tessellation, and GS), there are some set of input values, uniforms, and the like which lead to the computation of the final `gl_Position` value for the primitives in that process. If all of these values are *binary identical* (including the way the vertex format leads to any VS inputs), then you're guaranteed that `gl_Position` will have binary identical values. And if two primitive of the same type have binary identical positions, the rasterizer is *required* to generate binary identical fragment positions.&#xD;&#xA;&#xD;&#xA;And thus, no z-fighting.&#xD;&#xA;&#xD;&#xA;Now, that's kind of restrictive, as it only works with the same shaders. You can use different shaders, so long as:&#xD;&#xA;&#xD;&#xA;1. all shaders involved get binary identical values on expressions leading to the computation of `gl_Position`,&#xD;&#xA;2. all shaders involved use the exact same expressions (and I mean *exact*; `a + b` isn't the &quot;same expression&quot; as `b + a`, no matter what mathematics says) to compute `gl_Position`, and&#xD;&#xA;3. `gl_Position` and any inter-shader in/out variables leading to its computation are qualified with the `invariant` qualifier in all shaders. This tells the compiler not to optimize certain things away in expressions leading to the computation of such values." ContentLicense="CC BY-SA 4.0" />
  <row Id="24329" PostHistoryTypeId="2" PostId="8944" RevisionGUID="94650897-c01f-4bb7-bd23-3a3ef9a3c633" CreationDate="2019-06-27T00:58:59.197" UserId="10837" Text="**Note:** I wasn't 100% certain if this question belonged here or in Ask Ubuntu. I figured since it was about OpenGL programming I'd put it here, but if I should move it to Ask Ubuntu, please let me know.&#xD;&#xA;&#xD;&#xA;#Background&#xD;&#xA;I'm new to OpenGL and needed to figure out which version I could program in on my PC. A few Google/Stack Exchange searches shows that the usual solution is to run `glxinfo | grep version` and read the results, which I did and got the following:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;server glx version string: 1.4&#xD;&#xA;client glx version string: 1.4&#xD;&#xA;GLX version: 1.4&#xD;&#xA;    Max core profile version: 4.5&#xD;&#xA;    Max compat profile version: 3.0&#xD;&#xA;    Max GLES1 profile version: 1.1&#xD;&#xA;    Max GLES[23] profile version: 3.2&#xD;&#xA;OpenGL core profile version string: 4.5 (Core Profile) Mesa 18.0.5&#xD;&#xA;OpenGL core profile shading language version string: 4.50&#xD;&#xA;OpenGL version string: 3.0 Mesa 18.0.5&#xD;&#xA;OpenGL shading language version string: 1.30&#xD;&#xA;OpenGL ES profile version string: OpenGL ES 3.2 Mesa 18.0.5&#xD;&#xA;OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20&#xD;&#xA;```&#xD;&#xA;The confusing part is the following three lines:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;OpenGL core profile version string: 4.5 (Core Profile) Mesa 18.0.5&#xD;&#xA;OpenGL version string: 3.0 Mesa 18.0.5&#xD;&#xA;OpenGL shading language version string: 1.30&#xD;&#xA;```&#xD;&#xA;Everything I've read says to focus only on the Core Profile line, but I'm unable to draw anything unless I load functions and create a context under 3.0 or lower. Plus, when I call `glGetString(GL_VERSION)` I get `3.0 Mesa 18.0.5` printed to the terminal, but I'm not sure if that's because my hardware only supports 3.0 or if that's because I loaded functions for that level. Also, when I start writing shaders (I'm currently using Qt and an OpenGL Widget so haven't made a shader of my own yet) will I only be able to use GLSL 1.3 instead of 3.0+?&#xD;&#xA;&#xD;&#xA;#My Question&#xD;&#xA;My big question is, what do the output strings actually mean? I can't find that answer. Which one tells me what my hardware can actually do? And, what do the other strings mean? Why am I getting a Core Profile of 4.5 when (as far as I can tell) I can't actually use 4.5? If my hardware *can* perform 4.5 operations, how do I make it do so?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24330" PostHistoryTypeId="1" PostId="8944" RevisionGUID="94650897-c01f-4bb7-bd23-3a3ef9a3c633" CreationDate="2019-06-27T00:58:59.197" UserId="10837" Text="What do the OpenGL version strings from glxinfo actually mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24331" PostHistoryTypeId="3" PostId="8944" RevisionGUID="94650897-c01f-4bb7-bd23-3a3ef9a3c633" CreationDate="2019-06-27T00:58:59.197" UserId="10837" Text="|opengl|glsl|c++|hardware|compatibility|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24335" PostHistoryTypeId="2" PostId="8946" RevisionGUID="44a6bc95-7aa4-4c44-b09b-ed61003016de" CreationDate="2019-06-27T09:57:45.787" UserId="9298" Text="I am learning about Cubemap and I learned that **A cubemap is basically a texture that contains 6 individual 2D textures** but my question is **Why does it contain 6 individual texture ?** and also I've read that it uses 3D directional vector for sampling, **so what are the advantages of using 3D directional vector ?**" ContentLicense="CC BY-SA 4.0" />
  <row Id="24336" PostHistoryTypeId="1" PostId="8946" RevisionGUID="44a6bc95-7aa4-4c44-b09b-ed61003016de" CreationDate="2019-06-27T09:57:45.787" UserId="9298" Text="Why does Cubemap have 6 individual textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24337" PostHistoryTypeId="3" PostId="8946" RevisionGUID="44a6bc95-7aa4-4c44-b09b-ed61003016de" CreationDate="2019-06-27T09:57:45.787" UserId="9298" Text="|shader|texture|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24338" PostHistoryTypeId="2" PostId="8947" RevisionGUID="1be3b95a-a942-439f-bae5-e2288ad10799" CreationDate="2019-06-27T10:25:41.493" UserId="9902" Text="I would like to know what common techniques are used for rendering large models. &#xD;&#xA;&#xD;&#xA;For example if I had a model with &gt;10 million triangles, and it would be too slow to render the whole model, what optimisation steps or techniques could I use?&#xD;&#xA;&#xD;&#xA;I am currently aware of:&#xD;&#xA;&#xD;&#xA; - **Frustum culling**&#xD;&#xA; - **Occlusion culling**&#xD;&#xA;&#xD;&#xA;I would not know how to apply frustum culling to a single model. I know it can be used for multiple models:&#xD;&#xA;&#xD;&#xA;    for( int i=0; i &lt; numObjects; i++ )&#xD;&#xA;    {&#xD;&#xA;        if( insideFrustrum( objects[i] )&#xD;&#xA;        {&#xD;&#xA;            addModelToBeRendered( objects[i] );&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA; 1. Can frustum culling be applied to a single model/mesh?&#xD;&#xA; 2. What other techniques besides the two stated can be used when rendering large data-sets?&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="24339" PostHistoryTypeId="1" PostId="8947" RevisionGUID="1be3b95a-a942-439f-bae5-e2288ad10799" CreationDate="2019-06-27T10:25:41.493" UserId="9902" Text="Techniques for rendering high polycount models" ContentLicense="CC BY-SA 4.0" />
  <row Id="24340" PostHistoryTypeId="3" PostId="8947" RevisionGUID="1be3b95a-a942-439f-bae5-e2288ad10799" CreationDate="2019-06-27T10:25:41.493" UserId="9902" Text="|algorithm|computational-geometry|occlusion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24341" PostHistoryTypeId="5" PostId="8947" RevisionGUID="269b66f8-4ad7-4d4d-a607-24c65bff832e" CreationDate="2019-06-27T13:08:18.010" UserId="9902" Comment="Specified" Text="I would like to know what common techniques are used for rendering large models, when using rasterisation within a graphics API, for example OpenGL or Vulkan. &#xD;&#xA;&#xD;&#xA;For example if I had a model with &gt;10 million triangles, and it would be too slow to render the whole model, what optimisation steps or techniques could I use?&#xD;&#xA;&#xD;&#xA;I am currently aware of:&#xD;&#xA;&#xD;&#xA; - **Frustum culling**&#xD;&#xA; - **Occlusion culling**&#xD;&#xA;&#xD;&#xA;I would not know how to apply frustum culling to a single model. I know it can be used for multiple models:&#xD;&#xA;&#xD;&#xA;    for( int i=0; i &lt; numObjects; i++ )&#xD;&#xA;    {&#xD;&#xA;        if( insideFrustrum( objects[i] )&#xD;&#xA;        {&#xD;&#xA;            addModelToBeRendered( objects[i] );&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA; 1. Can frustum culling be applied to a single model/mesh?&#xD;&#xA; 2. What other techniques besides the two stated can be used when rendering large data-sets?&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="24342" PostHistoryTypeId="2" PostId="8948" RevisionGUID="a743e4a3-5a39-4a6c-aef0-6c5e6718bdb5" CreationDate="2019-06-27T14:10:11.460" UserId="137" Text="Why starting from a 3D direction vector? Because that is most commonly the way you get the direction from the sight line where you want to sample the env map along.&#xD;&#xA;&#xD;&#xA;Technically you can use any convex 3D shape as the surface of the map. For example a tetrahedron that gets unfolded into 2 rhomboids.&#xD;&#xA;&#xD;&#xA;However the GPU is already optimized to render to a rectangle. This makes the cubemap easy to create at runtime. And the math to get which face to sample from and the coordinates from which to sample are extremely easy to calculate when dealing with an axis aligned cube. It boils down to finding the max value and dividing the other 2 coordinates with that max value.&#xD;&#xA;&#xD;&#xA;The cubemap has some distortion around the corners of the cube but very much within reason.&#xD;&#xA;&#xD;&#xA;You can also use another projection that lets you go from the direction to a coordinate on a single texture. These typically start from a latitude/longitude on a sphere direction and then map it to a texture using some [map projection][1]. Getting that lat/lon from a 3D direction vector requires using trig functions which are slower compared to the compares and divide the cubmap requires.&#xD;&#xA;&#xD;&#xA;The simplest possible projection from lat/long to UV will create a lot of distortion at the poles. Which leads to massive oversampling of that area and can lead to artifacts. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Map_projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="24343" PostHistoryTypeId="2" PostId="8949" RevisionGUID="00ed16d0-91ec-4960-9e3b-44aa7efbff86" CreationDate="2019-06-27T14:45:26.523" UserId="10849" Text="I am analysing a large number of PDF files from scientific articles, all of which contain images which (I think) were originally monochrome ( black/white). &#xD;&#xA;The images have been extracted with Apache PDFBox and I am doing image processing on `*.png`.&#xD;&#xA;The images have severe colour distortion, and blurring which I do not think is due to the extraction process or to subpixel antialising (see https://stackoverflow.com/questions/16242731/reconstructing-line-diagrams-from-subpixel-rendering). Note that the effect is present on both lines and text.&#xD;&#xA;&#xD;&#xA;The effect is present in all PNG files though in different amounts. I suspect it comes from the tool/s used to create the PDFs from the original images which &#xD;&#xA;apply some softening process (antialising). I have analysed this visually and it consists of a narrow plane in HSV with only two colours mixed with a lot of white/grey/black.&#xD;&#xA;&#xD;&#xA;I'd like to know what the algorithm is that creates this blurring and colour so that I can reverse it. Traditional sharpening is only partially successful.&#xD;&#xA;I'd be delighted if anyone has code that does this (any language will do).&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;NOTE: I do not have originals.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iOWh8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24344" PostHistoryTypeId="1" PostId="8949" RevisionGUID="00ed16d0-91ec-4960-9e3b-44aa7efbff86" CreationDate="2019-06-27T14:45:26.523" UserId="10849" Text="Origin of blurring and colour distortion in monochrome diagrams" ContentLicense="CC BY-SA 4.0" />
  <row Id="24345" PostHistoryTypeId="3" PostId="8949" RevisionGUID="00ed16d0-91ec-4960-9e3b-44aa7efbff86" CreationDate="2019-06-27T14:45:26.523" UserId="10849" Text="|image-processing|antialiasing|blur|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24346" PostHistoryTypeId="2" PostId="8950" RevisionGUID="eada8482-538a-4293-9e17-7e4c6c860ad1" CreationDate="2019-06-27T15:23:22.657" UserId="2654" Text="A texture is just a fancy lookup table; that's all it is. It's a function that you input some coordinate `T` into, which returns a value for that particular `T`.&#xD;&#xA;&#xD;&#xA;There are many ways that one might choose to build such a function. A 1D texture is a lookup table where the coordinate is a single value on the range [0, 1]. A 2D texture is a texture where the coordinate is a pair of values, each on the range [0, 1]. A 3D texture has its coordinates as a triple of values.&#xD;&#xA;&#xD;&#xA;You can think of these textures as lookup tables that answer the question, &quot;what is the value at the position `T` within a normalized [0, 1] space?&quot; 2D textures use a two-dimensional space. 3D textures use a three-dimensional space. But they're all asking about the value at a position.&#xD;&#xA;&#xD;&#xA;A cubemap is a lookup table that answers the question &quot;what is the value in the *direction* `T`?&quot; A 2D texture maps a position into a value; a cubemap maps a direction into a value.&#xD;&#xA;&#xD;&#xA;The purpose of *any* texture, within a shader, is to fill in some parameter in the rendering equation. A texture might be used to define a surface's albedo, shininess, or some other surface property. But a texture might also be used to look up how much light reaches that particular point on the surface; that's what shadow mapping is all about. Textures are not just about changing material properties of a surface; they're useful for many kinds of math in shaders.&#xD;&#xA;&#xD;&#xA;Directional textures (ie: cubemaps) are often used for point-light shadow maps. Given a position on a surface, they answer the question &quot;can I see the light from here?&quot; Well, &quot;from here&quot; means using a direction towards the light. Since point lights are within the scene and cast light in all directions, a direction from the light to the current point on the surface represents the path the light would follow to reach that surface.&#xD;&#xA;&#xD;&#xA;So a cube shadow map stores the distance from the light to the nearest occluding surface in all directions around the point light. And when a surface checks to see if it is in shadow from that light, it computes the direction from the point light to the surface and checks the directional shadow map.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Cubemaps have 6 &quot;textures&quot; (no, they don't have 6 textures. They have 6 sets of potentially mipmapped 2D *images*. There's a difference between a texture and an image) because a cube has 6 faces. A cubemap implements its mapping from a direction to a value by taking that direction and figuring out which point(s) on these images correspond to that direction.&#xD;&#xA;&#xD;&#xA;Imagine being in the center of a cube. Each surface around you is one of these 6 images. For any pixel in those images, there is a unique direction from the center of the cube to that pixel. That creates the mapping from direction to pixel values.&#xD;&#xA;&#xD;&#xA;Why are directional textures cubes instead of something else? Because it's the easiest way to create a directional texture. GPU hardware already knows how to deal with 2D images, how to access pixels from them, how to filter such accesses, and how to do mipmapping on them. All you really need to make cubemaps work is to tie together sets of 6 mipmap image chains and change the mapping algorithm, the means of converting a particular `T` into a pixel location. You don't have to invent some way of storing spherical information or somesuch." ContentLicense="CC BY-SA 4.0" />
  <row Id="24348" PostHistoryTypeId="2" PostId="8952" RevisionGUID="435b0ced-ff6e-4e91-964a-447727876b5a" CreationDate="2019-06-27T16:14:56.843" UserId="137" Text="The straightforward solution is to simple not render the high poly model at all. Have a lower detail model that you can switch to once the model is too far away for it to make a difference. There is no point in rendering 20 triangles that all end up in the same pixel.&#xD;&#xA;&#xD;&#xA;Next option is to partition the model and then cull the individual parts. You can also make each (set of) patch have different Levels of detail. &#xD;&#xA;&#xD;&#xA;This partition can take the form of patches that are mostly flat. That way you can use backface culling on the whole group by taking the dot product of the average normal and comparing it to the look vector, if it is too large only the backsides will be showing and there is no point in rendering that patch.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24350" PostHistoryTypeId="2" PostId="8953" RevisionGUID="25196aad-91be-4859-b11f-0a46ff831469" CreationDate="2019-06-27T17:19:12.630" UserId="10851" Text="I know im a bit late, but hopefully this can help other people. you can add detail by using Fractal Brownian Motion. There is a great article [here](https://cmaher.github.io/posts/working-with-simplex-noise/) that i used as a guide to make my own version in c#. Also I would check to make sure your vars are ints." ContentLicense="CC BY-SA 4.0" />
  <row Id="24352" PostHistoryTypeId="2" PostId="8954" RevisionGUID="8001d4e0-edd2-49bc-beb2-fe5d616d1494" CreationDate="2019-06-28T00:21:15.337" UserId="10837" Text="&gt; The 2D pipeline involves ... [coordinate transformation terms]&#xD;&#xA;&#xD;&#xA;&gt; Can someone give me the detail differentiation among these?&#xD;&#xA;&#xD;&#xA;This is something I very recently learned while trying to understand how software handles 3D graphics behind the scenes. I've never encountered these terms in reference to 2D graphics before, but the ideas still apply. 2D graphics are just 3D graphics without a few fancy tricks.&#xD;&#xA;&#xD;&#xA;#Very Generally&#xD;&#xA;Most of these different coordinate spaces don't technically exist. They come about by considering the objects you wish to draw from some reference point. When you change that reference point, you change the coordinate space. Math gets involved, but I won't do any here.&#xD;&#xA;&#xD;&#xA;#The Drawing Device and Device Coordinates&#xD;&#xA;&#xD;&#xA;&gt; ... converting normalized coordinate to device coordinate.&#xD;&#xA;&#xD;&#xA;&gt; Isn't viewing coordinate and device coordinate the same things?&#xD;&#xA;&#xD;&#xA;Short answer, no, but they can be in certain 2D cases. In 3D, pretty much never.&#xD;&#xA;&#xD;&#xA;There seems to be a confusion not just between view and device coordinates, but also with the distinction between normalized and device coordinates. Lets start with normalized and device, and we'll get to view later.&#xD;&#xA;&#xD;&#xA;In 3D systems (and 2D systems setup to work like them) you are presented with a &quot;drawing device&quot; consisting of two parts: drawing tools (usually functions accessed from application code) and a drawing area. Ignoring the tools, the important thing is that the drawing area has a coordinate system independent of pixels which adds a lot of flexibility and generality to the device.&#xD;&#xA;&#xD;&#xA;Any time something is setup to work numerically in a range from 0 to 1 it is &quot;normal&quot;, and often the range 0 to -1 is included too. With a drawing device the coordinates for both the X and Y directions of your drawing area range from -1 to 1, with -1 meaning &quot;all the way left&quot; for X and &quot;all the way down&quot; for Y, and 1 meaning &quot;all the way right&quot; or &quot;all the way up&quot; for X and Y respectively.&#xD;&#xA;&#xD;&#xA;You can easily add a Z direction too (also ranging from -1 to 1) for &quot;3D&quot; drawing, but all this does is give you a layered 2D image. There is no perspective (or &quot;depth&quot;) in your final drawing which is great for 2D games and graphics. The reason for this is that the drawing device will simply divide the space up into pixel size steps along X and Y then draw each pixel back to front (-Z to +Z). If you want real 3D though, you'll need some extra mathematical steps.&#xD;&#xA;&#xD;&#xA;It is possible (and common) for the device to understand and work with coordinates outside the -1 to 1 range. However, if we want an object to appear on screen than it must be &quot;normalized&quot; so that any coordinates it refers to are within -1 to 1. After this is done to an object the terms &quot;normalized coordinates&quot; and &quot;device coordinates&quot; are practically synonymous, just one refers to the object you altered so that it would fit within the drawing area and the other refers to the drawing area itself.&#xD;&#xA;&#xD;&#xA;#Object and World Spaces&#xD;&#xA;&#xD;&#xA;&gt; The 2D [or 3D] pipeline involves with the construction of world coordinate scene ...&#xD;&#xA;&#xD;&#xA;Yes, but you start in &quot;object space&quot;.&#xD;&#xA;&#xD;&#xA;When someone creates a model of an object (or draws a sprite) all that matters to them, coordinate-wise, is where zero is within the space they're working. This consideration is called &quot;object space&quot; because the artist isn't concerned with the -1 to 1 drawing area, only accurately representing the object they'd like to draw. A model of a pen might be 6 units long and a model of a person might be 5.5 units tall. The important thing is that all of the points that make up some object are positioned with regard to the coordinate (0, 0, 0) and nothing else.&#xD;&#xA;&#xD;&#xA;When later loaded into memory they will be too big for the drawing area (which is only 2 units tall and wide) and the pen will appear larger than the person. It's up to us humans to know what the units mean and adjust them properly. Resizing and positioning all objects in relation to each other instead of each individually being sized with relation to zero transforms the objects into &quot;world space&quot;.&#xD;&#xA;&#xD;&#xA;From the shortness of your question I wasn't sure if you knew that yet or not, but I thought I'd include that for completeness, as a good foundation for answering the next part of your question.&#xD;&#xA;&#xD;&#xA;#View Space&#xD;&#xA;&#xD;&#xA;&gt; ... followed by converting world coordinate to viewing coordinate ...&#xD;&#xA;&#xD;&#xA;&gt; Isn't viewing coordinate and device coordinate the same things?&#xD;&#xA;&#xD;&#xA;Note that in my explanation above nothing ever happened to the drawing device, or the coordinates of the drawing area. The only thing that ever changed was the objects we wanted to draw. The drawing area is fixed and unchanging, only ever drawing any object that fits within the coordinates -1 to 1.&#xD;&#xA;&#xD;&#xA;Each object loaded appears at the center of the drawing area at whatever size it was designed to have (object space) which is practically always too big for the drawing device. After rearranging and resizing every object around each other (object space → world space) we still have a final scene that is too big for the drawing area, and we have no way to move around within the scene. This is where we transform everything into &quot;view space&quot; and work with &quot;eye coordinates&quot;. Again, there is no such space, but what we do to work within it is to consider an imaginary camera and, treating the entire world as one giant object, we resize and reposition everything with respect to the position of the camera. That is &quot;view space&quot;, the movement of everything around a camera, and the terms &quot;view coordinates&quot; (or &quot;eye coordinates&quot;) refer to the positions of everything in relation to the camera.&#xD;&#xA;&#xD;&#xA;#View to Viewport&#xD;&#xA;&#xD;&#xA;At this point everything that you want to see should be within the device space, but there are still a few last tasks to perform to get everything to draw.&#xD;&#xA;&#xD;&#xA;If you were working on a 3D scene instead of a 2D one, you would perform a &quot;perspective transformation&quot; to create the illusion of depth. This is where you squish and warp things to make them look like they're shrinking into the distance.&#xD;&#xA;&#xD;&#xA;Anything outside the drawing area needs to be thrown out. This saves on work for the computer, and it also is considered another transformation from view space to &quot;clip space&quot; because you are &quot;clipping away&quot; the extra data.&#xD;&#xA;&#xD;&#xA;And finally, after clipping, you'll do a &quot;viewport&quot; transformation that turns the -1 to 1 coordinates into pixel coordinates.&#xD;&#xA;&#xD;&#xA;#Summary&#xD;&#xA;&#xD;&#xA;Well... I didn't intend for this answer to get so long. My apologies if I covered anything you already knew. It's hard to guess what someone does or does not already understand. Please leave a comment if you have any further questions.&#xD;&#xA;&#xD;&#xA;**Object Coordinates:** The positions of points relative to a zero point. The points referred to are the building blocks of some single object.&#xD;&#xA;&#xD;&#xA;**World Coordinates:** The positions of collections of points (objects) relative to a single shared standard zero point.&#xD;&#xA;&#xD;&#xA;**View Coordinates:** The position of all points (the whole scene) relative to a camera.&#xD;&#xA;&#xD;&#xA;**Device Coordinates:** Any position within -1 to 1 on both the X and Y axis (and Z too for 3D). Any point within the drawing area of the device.&#xD;&#xA;&#xD;&#xA;**Normalized Coordinates:** The positions of points of any object (or the whole scene) that have been transformed to fit within the -1 to 1 space of the drawing device.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24353" PostHistoryTypeId="2" PostId="8955" RevisionGUID="a7dee506-55a9-4ff0-83b9-227fe07fe8b9" CreationDate="2019-06-28T00:47:17.053" UserId="10837" Text="My first thought (aside from culling) is to perform some sort of distance based level of detail algorithm. I've heard of systems in the past that could selectively remove edges and merge faces to produce lower detail sections on a single mesh, but most systems go for the far simpler method of simply loading in an entirely separate lower detail model once the higher detail model moves far enough from the camera." ContentLicense="CC BY-SA 4.0" />
  <row Id="24354" PostHistoryTypeId="2" PostId="8956" RevisionGUID="6461a3a3-d4a8-4a28-8116-e41078f8fe96" CreationDate="2019-06-28T09:27:23.833" UserId="3073" Text="This looks like JPEG artefacts so I guess the image went through a JPEG compression step at one stage and that permanently introduced noise into the image. The red channel is blurred stronger because JPEG additionally applies chroma subsampling.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24355" PostHistoryTypeId="5" PostId="8956" RevisionGUID="4200cccd-6fff-4bf5-96a5-1055f8fcbdce" CreationDate="2019-06-28T09:53:08.777" UserId="3073" Comment="added 145 characters in body" Text="This looks like JPEG artefacts so I guess the image went through a JPEG compression step at one stage and that permanently introduced noise into the image. The red channel is blurred stronger because JPEG additionally applies chroma subsampling.&#xD;&#xA;&#xD;&#xA;I suspect the original image was subpixel rendered as you shouldn't really have anything in the chroma channels for a monochrome input image.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24357" PostHistoryTypeId="50" PostId="8870" RevisionGUID="2c0eb030-054b-461c-b59b-13905c3f208c" CreationDate="2019-06-29T05:02:25.310" UserId="-1" />
  <row Id="24358" PostHistoryTypeId="2" PostId="8957" RevisionGUID="09a6e8c1-7c0f-49c1-99c7-108aa2b06aab" CreationDate="2019-06-29T09:14:23.763" UserId="10860" Text="I want to split a couple of simple 2d forms into tri meshes. The meshes should conserve the original geometry and ideally I'd like a possibility to influence refinement vs. tris count.&#xD;&#xA;&#xD;&#xA;I have the 2d forms available as images (svg, png) and am happy to convert to something else if necessary (STL, ...?). Output should ideally be an IBO (index buffer containing points and triangle index numbers), but I will settle for something I can convert into that. I don't need a library, a manual process is fine, but I'm not above using one, if it gets the job done.&#xD;&#xA;&#xD;&#xA;I found a number of possible solutions to this (gmsh, netgen, ... [and more][1]) but many of those seem too much (would require high time investment to learn) for my relatively simple problem.&#xD;&#xA;&#xD;&#xA;I am moderately proficient in python, blender and common linux software and am happy to come up with a small script to solve this, but don't want to dive deep into e.g. GL in order to solve this - hence my question: **What is the easiest workflow to generate a trimesh from a svg or png?**&#xD;&#xA;&#xD;&#xA;This feels like a &quot;common&quot; issue, but I'm having a bit of hard time to find a solution with good effort/result ratio (maybe my google-fu is broken).&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/4882993/mesh-generation-from-points-with-x-y-and-z-coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="24359" PostHistoryTypeId="1" PostId="8957" RevisionGUID="09a6e8c1-7c0f-49c1-99c7-108aa2b06aab" CreationDate="2019-06-29T09:14:23.763" UserId="10860" Text="How to triangulate a simple 2d surface to generate a constrained surface trimesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="24360" PostHistoryTypeId="3" PostId="8957" RevisionGUID="09a6e8c1-7c0f-49c1-99c7-108aa2b06aab" CreationDate="2019-06-29T09:14:23.763" UserId="10860" Text="|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24361" PostHistoryTypeId="2" PostId="8958" RevisionGUID="fb8016f0-666b-4771-96de-27704ef2a052" CreationDate="2019-06-29T11:47:43.260" UserId="8796" Text="When creating a OpenGL context you have to specify a profile mask, which is a way of telling the driver whether you want to use compatibility (&quot;legacy&quot;) features or not.&#xA;&#xA;Drivers are required to implement all core profile features, but compatibility profile is optional - creating a compatibility context can fail even if the driver supports the version you've requested.&#xA;&#xA;The output from `glxinfo` you've pasted shows that you can create GL context with version up to 4.5 only when using core profile. If you want to use compatibility profile, the highest version you can request is 3.0.&#xA;&#xA;One reason of the problem you are having is that you:&#xA;&#xA; - requested context version greater than 3.0, and&#xA; - requested a compatibility profile (by setting `GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB` in `GLX_CONTEXT_PROFILE_MASK_ARB`).&#xA;&#xA;If removing compatibility bit doesn't help, you'll need to double check if other context attributes are correct.&#xA;&#xA;*What I described above is documented in a more detailed way [here][1].*&#xA;&#xA;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/ARB/GLX_ARB_create_context.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="24362" PostHistoryTypeId="2" PostId="8959" RevisionGUID="e014d3df-cb19-43fd-8c30-1ff2a8e36020" CreationDate="2019-06-30T06:50:00.183" UserId="2306" Text="Quake subdivision rasterization comes to mind. https://www.bluesnews.com/abrash/chap69.shtml , under ”An idea that did work”." ContentLicense="CC BY-SA 4.0" />
  <row Id="24363" PostHistoryTypeId="2" PostId="8960" RevisionGUID="f68fdece-9a0f-44f5-a39e-e7f40b710225" CreationDate="2019-06-30T08:38:56.903" UserId="10863" Text="A 3d Mesh on plot.ly online graph maker (https://plot.ly/create/#/) takes 3 mandatory variables (X, Y, Z) and 3 optional variables (I, J, K).&#xD;&#xA;I understand that if I want to draw a cube that I then have to use the IJK-variables, since without them nothing will be drawn.&#xD;&#xA;&#xD;&#xA;After some googling I found that with i, j, k you can represent vectors. Though I do not understand how in the following examples they correspond to the XYZ values, so that a cube can be drawn.&#xD;&#xA;There are several examples of cubes and cuboids on plot.ly, all of which share the same i, j, k, values. &#xD;&#xA;f.e.&#xD;&#xA;https://plot.ly/create/?fid=RPlotBot%3A3933#/&#xD;&#xA;&#xD;&#xA;https://plot.ly/create/?fid=markope%3A143#/&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Taking the first link as an example:&#xD;&#xA;&#xD;&#xA;    x	y	z		i	j	k&#xD;&#xA;    0	0	0		7	3	0&#xD;&#xA;    0	1	0		0	4	7&#xD;&#xA;    1	1	0		0	1	2&#xD;&#xA;    1	0	0		0	2	3&#xD;&#xA;    0	0	1		4	5	6&#xD;&#xA;    0	1	1		4	6	7&#xD;&#xA;    1	1	1		6	5	1&#xD;&#xA;    1	0	1		6	2	1&#xD;&#xA;    				4	0	5&#xD;&#xA;    				0	1	5&#xD;&#xA;    				3	6	7&#xD;&#xA;    				2	3	6&#xD;&#xA;&#xD;&#xA;This will draw a normal cube.&#xD;&#xA;When I try my XYZ-coordinates, however, it will draw following:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My xyz-coordinates are:&#xD;&#xA;&#xD;&#xA;    x	y	z&#xD;&#xA;    25	25	65&#xD;&#xA;    25	55	65&#xD;&#xA;    55	25	65&#xD;&#xA;    55	55	65&#xD;&#xA;    25	25	80&#xD;&#xA;    25	55	80&#xD;&#xA;    55	25	80&#xD;&#xA;    55	55	80&#xD;&#xA;&#xD;&#xA;How can I calculate the according ijk-values so that I get a cuboid? Any tips or links to resources?&#xD;&#xA;&#xD;&#xA;The [official tutorial][2] for a 3d mesh on plot.ly online graph maker only mentions the ijk-values, doesn't explain them though.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S4lkf.png&#xD;&#xA;  [2]: https://help.plot.ly/make-a-3d-mesh-plot" ContentLicense="CC BY-SA 4.0" />
  <row Id="24364" PostHistoryTypeId="1" PostId="8960" RevisionGUID="f68fdece-9a0f-44f5-a39e-e7f40b710225" CreationDate="2019-06-30T08:38:56.903" UserId="10863" Text="What are the i,j,k components of a 3d mesh on plot.ly (online)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24365" PostHistoryTypeId="3" PostId="8960" RevisionGUID="f68fdece-9a0f-44f5-a39e-e7f40b710225" CreationDate="2019-06-30T08:38:56.903" UserId="10863" Text="|3d|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24366" PostHistoryTypeId="2" PostId="8961" RevisionGUID="1ab1d787-2102-48db-a978-00ac13a9c7b3" CreationDate="2019-06-30T23:37:06.323" UserId="6647" Text="Most mesh drawing tools use triangles to draw meshes, for technical reasons.&#xA;&#xA;You *could* simply specify the coordinates of the three vertices of each triangle, but that is a bit wasteful in terms of memory.&#xA;&#xA;What is done in many places is to specify a list of points in space, with their coordinates, and then specify a list of triangles, using indices of the points in the first list. &#xA;&#xA;The exact same thing happens here. The x,y,z parameters form a list of points. The I,j,k parameters indicate triangles, using IDs in the list of points. &#xA;&#xA;Have a look at the function documentation for more details:&#xA;https://plot.ly/python/reference/#mesh3d" ContentLicense="CC BY-SA 4.0" />
  <row Id="24370" PostHistoryTypeId="2" PostId="8963" RevisionGUID="4ab4a8ea-4d49-41b3-833a-7440af0921b8" CreationDate="2019-07-01T14:06:10.327" UserId="6046" Text="So I'm trying to render participating media like clouds/sky/fog (Sky is the first step) etc. I had already implemented a normal pathtracer and I was thinking of extending it. But I heard terms like Ray marching/Sphere tracing are used for rendering volumes. &#xD;&#xA;&#xD;&#xA;A quick search brings up [this][1] question where the guy is trying to use Monte Carlo methods to render the Sky. This has me confused. Does this mean we can use Path tracing together with ray marching? Or do we have to choose 1 over the other? Or is it that both are actually solving different problems? I have read up on what ray marching actually means, I just want to get a clear understanding of the connection between raymarching - raytracing/pathtracing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/5520/using-monte-carlo-on-rayleigh-scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="24371" PostHistoryTypeId="1" PostId="8963" RevisionGUID="4ab4a8ea-4d49-41b3-833a-7440af0921b8" CreationDate="2019-07-01T14:06:10.327" UserId="6046" Text="Can I use Path tracing together with Ray Marching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24372" PostHistoryTypeId="3" PostId="8963" RevisionGUID="4ab4a8ea-4d49-41b3-833a-7440af0921b8" CreationDate="2019-07-01T14:06:10.327" UserId="6046" Text="|pathtracing|volumetric|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24373" PostHistoryTypeId="2" PostId="8964" RevisionGUID="249efff0-a612-41a7-9eff-8529033b4575" CreationDate="2019-07-02T16:49:33.233" UserId="10871" Text="I am wondering how was first graphic or image libraries created,I know C and Python ,I want to create plotting application,and I cant imagine these libraries(QT,OpenGL,Vulkan) written by C,how can I create my image library,I just want to create basic graphic library." ContentLicense="CC BY-SA 4.0" />
  <row Id="24374" PostHistoryTypeId="1" PostId="8964" RevisionGUID="249efff0-a612-41a7-9eff-8529033b4575" CreationDate="2019-07-02T16:49:33.233" UserId="10871" Text="How was computer graphics libraries or gtk,qt programmed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24375" PostHistoryTypeId="3" PostId="8964" RevisionGUID="249efff0-a612-41a7-9eff-8529033b4575" CreationDate="2019-07-02T16:49:33.233" UserId="10871" Text="|opengl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24376" PostHistoryTypeId="36" PostId="8965" RevisionGUID="c67bc814-af85-4d7d-ba9e-806899b41a04" CreationDate="2019-07-02T20:37:24.570" UserId="-1" Comment="from https://graphicdesign.stackexchange.com/questions/126203/how-to-separate-modulate-and-reassemble-spatial-frequencies" />
  <row Id="24377" PostHistoryTypeId="2" PostId="8965" RevisionGUID="7575ab38-73f1-4c50-ac10-d2a55e9e7aa8" CreationDate="2019-07-02T14:14:09.990" UserDisplayName="Robert Angels" Text="### Background&#xD;&#xA;&#xD;&#xA;I am trying to create a node in Blender that would allow me to do what you would do with an audio equalizer but on the spatial frequencies of an image: A sort of panel with eight controllers, from low to high spatial frequencies, which allows me to attenuate or increase a certain frequency plus a second panel that allows me to increase the contrast on each of the eight frequencies.&#xD;&#xA;&#xD;&#xA;The idea came to me after playing a bit with [Materialize](http://www.boundingboxsoftware.com/materialize/), a well-known open-source software that serves to generate textures from a photograph and is used a lot in the world of video games.&#xD;&#xA;To generate a height map (but also other maps) it offered a panel with various controllers that allowed to act on the frequency.&#xD;&#xA;&#xD;&#xA;### Question&#xD;&#xA;&#xD;&#xA;On the Internet I have found practically nothing that is not the separation of frequencies made in Photoshop to correct skin imperfections. This procedure divides an image into low and high frequencies and then reassembles them.&#xD;&#xA;My problem is: How do I split an image into several different spatial frequencies (not just two) and then reassemble them to get the original image again but with the possibility of modulating them individually.&#xD;&#xA;Now, regardless of the software, what mathematical operations could I use fr this?&#xD;&#xA;&#xD;&#xA;I'm doing tests with Blender nodes. The node is a group of other nodes, I'm not using Python." ContentLicense="CC BY-SA 4.0" />
  <row Id="24378" PostHistoryTypeId="1" PostId="8965" RevisionGUID="7575ab38-73f1-4c50-ac10-d2a55e9e7aa8" CreationDate="2019-07-02T14:14:09.990" UserDisplayName="Robert Angels" Text="How to separate, modulate, and reassemble spatial frequencies?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24379" PostHistoryTypeId="3" PostId="8965" RevisionGUID="7575ab38-73f1-4c50-ac10-d2a55e9e7aa8" CreationDate="2019-07-02T14:14:09.990" UserDisplayName="Robert Angels" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24380" PostHistoryTypeId="2" PostId="8966" RevisionGUID="9290e8f3-7b9f-40e3-bcce-ff57fa4500e9" CreationDate="2019-07-03T07:28:33.953" UserId="10873" Text="I was recently learning about OpenGL and computer graphics development. I have a question regarding the usage of triangle as the basic building block, or basic shape to develop complex shapes. Is there a particular reason? Or just something that &quot;stuck&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24381" PostHistoryTypeId="1" PostId="8966" RevisionGUID="9290e8f3-7b9f-40e3-bcce-ff57fa4500e9" CreationDate="2019-07-03T07:28:33.953" UserId="10873" Text="Triangle - Why is it the basic building block for complex shapes" ContentLicense="CC BY-SA 4.0" />
  <row Id="24382" PostHistoryTypeId="3" PostId="8966" RevisionGUID="9290e8f3-7b9f-40e3-bcce-ff57fa4500e9" CreationDate="2019-07-03T07:28:33.953" UserId="10873" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24383" PostHistoryTypeId="2" PostId="8967" RevisionGUID="08472169-76ae-4bed-aeeb-5749c1b7177c" CreationDate="2019-07-03T08:02:02.763" UserId="10860" Text="The fastest and easiest way to do this is using [blender][1]. Simply import the svg (supported out of the box) into blender. The svg will be imported as a &quot;curve&quot;-type geometry. Optionally do some clean up/refinement. The curves can then be converted to a mesh. The mesh defaults to a trimesh. Voila - svg to trimesh in a couple of seconds.&#xD;&#xA;&#xD;&#xA;Mesh refinement is not very fine-grained, but there is some measure of control via the &quot;beauty-fill&quot;, &quot;subdivide&quot; and &quot;triangulate&quot; as well as &quot;merge vertices by distance&quot; tools from within blender.&#xD;&#xA;&#xD;&#xA;The IBO (vertices + triangle vertex indices) can then be extracted using a short python script:&#xD;&#xA;&#xD;&#xA;    import bpy&#xD;&#xA;    obdata = bpy.context.object.data # selected object&#xD;&#xA;    for v in obdata.vertices:&#xD;&#xA;        fh.write('({}, {}),\n'.format(v.co.x, v.co.y))&#xD;&#xA;    for f in obdata.polygons:&#xD;&#xA;        for v in f.vertices:&#xD;&#xA;            print('{} '.format(v))&#xD;&#xA;&#xD;&#xA;  [1]: https://blender.org" ContentLicense="CC BY-SA 4.0" />
  <row Id="24384" PostHistoryTypeId="2" PostId="8968" RevisionGUID="b5e80226-e171-4696-9d15-49afe0f37b63" CreationDate="2019-07-03T08:37:34.023" UserId="6647" Text="In computer graphics, people are interested in modelling the *surface* of the objects. And, since we are in the discrete world of computers, we need a discrete representation for surfaces, where we can easily check for stuff like intersections and angles, both vital for rendering.&#xD;&#xA;&#xD;&#xA;The triangle makes it very easy to compute intersections and surface normals, but also has some useful features: it is always convex (if not degenerate), which means that the mathematics is a lot simplified. Being so basic, you can also split pretty much any shape in triangles.&#xD;&#xA;&#xD;&#xA;But keep in mind that there are other basic shapes. Some hardware supports quads or nurbs, although it's much less common." ContentLicense="CC BY-SA 4.0" />
  <row Id="24385" PostHistoryTypeId="5" PostId="8949" RevisionGUID="303d7a37-9913-4cc3-a10a-53d253c9c659" CreationDate="2019-07-03T09:03:22.463" UserId="10849" Comment="added color analysis images" Text="I am analysing a large number of PDF files from scientific articles, all of which contain images which (I think) were originally monochrome ( black/white). &#xD;&#xA;The images have been extracted with Apache PDFBox and I am doing image processing on `*.png`.&#xD;&#xA;The images have severe colour distortion, and blurring which I do not think is due to the extraction process or to subpixel antialising (see https://stackoverflow.com/questions/16242731/reconstructing-line-diagrams-from-subpixel-rendering). Note that the effect is present on both lines and text.&#xD;&#xA;&#xD;&#xA;The effect is present in all PNG files though in different amounts. I suspect it comes from the tool/s used to create the PDFs from the original images which &#xD;&#xA;apply some softening process (antialising). I have analysed this visually and it consists of a narrow plane in HSV with only two colours mixed with a lot of white/grey/black.&#xD;&#xA;&#xD;&#xA;I'd like to know what the algorithm is that creates this blurring and colour so that I can reverse it. Traditional sharpening is only partially successful.&#xD;&#xA;I'd be delighted if anyone has code that does this (any language will do).&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;NOTE: I do not have originals.&#xD;&#xA;&#xD;&#xA;UPDATE.&#xD;&#xA;Here are some analyses of the colors with ImageJ ColorInspector3D plugin in YCbCr space&#xD;&#xA;&#xD;&#xA;= YCbCr frequencies =&#xD;&#xA;Note the *very* sharp plane in which the colors lie&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;and a histogram to show the distribution more clearly. &#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;(The red/pink *is* there on the RH sides - not very clear in this screen shot)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I intend to ask another question on how to sharpen this. (This Q is *where&quot; does the effect arise; the next will be *how to correct it* even if we don't know the origin)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iOWh8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QvIAN.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/h1c1f.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/UTbw8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24386" PostHistoryTypeId="50" PostId="8876" RevisionGUID="28eb5e33-2031-41ea-9d7c-e98c41c61ed3" CreationDate="2019-07-03T14:00:05.353" UserId="-1" />
  <row Id="24387" PostHistoryTypeId="52" PostId="8966" RevisionGUID="9cf502f9-b5a8-4931-aded-428ee005d5c8" CreationDate="2019-07-03T15:33:16.777" />
  <row Id="24388" PostHistoryTypeId="2" PostId="8969" RevisionGUID="f6e4b284-ed81-4fbb-a1db-f28af6254a9e" CreationDate="2019-07-04T03:13:30.133" UserId="3073" Text="Triangles are always flat, unlike a quad which can be made in a way that is bent / not all vertices on the same plane. &#xD;&#xA;&#xD;&#xA;If you were to interpolate say vertex normals across each scanline, on a 4-edge bent quad it will render with horizontal (scanline) artefacts. If you made that same bent quad out of triangles, it will render correctly as each triangle has a different normal slope. &#xD;&#xA;&#xD;&#xA;That's one reason why triangles are preferable for scanline rasterising" ContentLicense="CC BY-SA 4.0" />
  <row Id="24390" PostHistoryTypeId="2" PostId="8970" RevisionGUID="0bd72c02-102c-47ae-b983-0f8ca9d9d7a0" CreationDate="2019-07-04T19:53:25.140" UserId="10876" Text="I've been doing some reading as to how to reduce input delay on modern computing devices. A lot of my understanding from this comes from the [VR research paper by Carmack](https://danluu.com/latency-mitigation/) explaining the numerous circumstances to reduce the latency between the CPU simulation/rendering -&gt; GPU buffering -&gt; video out stages.&#xD;&#xA;&#xD;&#xA;So assuming the optimal case where we have a monitor with a ~60hz refresh rate with a simulation/render that fits in a single tick, I was wondering if software rendering bypasses the GPU buffer stage (G) shown below (but not the video out as we cant force the monitor to refresh).&#xD;&#xA;&#xD;&#xA;    I - Input, S = Simulation, R = Render, G = Gpu buffered commands, V - Video Out&#xD;&#xA;    CPU:ISSSSSRRRRRR----|&#xD;&#xA;    GPU:                |GGGGGGGGGGG----|&#xD;&#xA;    VID:                |               |VVVVVVVVVVVVVVVV|&#xD;&#xA;&#xD;&#xA;This would seem to trade off the need of synchronizing with GPU and GPU fencing that mentioned later at the cost of performance. I was wondering if this was accurate and a reasonable option to reduce display latency?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24391" PostHistoryTypeId="1" PostId="8970" RevisionGUID="0bd72c02-102c-47ae-b983-0f8ca9d9d7a0" CreationDate="2019-07-04T19:53:25.140" UserId="10876" Text="Software Rendering Display Latency" ContentLicense="CC BY-SA 4.0" />
  <row Id="24392" PostHistoryTypeId="3" PostId="8970" RevisionGUID="0bd72c02-102c-47ae-b983-0f8ca9d9d7a0" CreationDate="2019-07-04T19:53:25.140" UserId="10876" Text="|opengl|rendering|gpu|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24393" PostHistoryTypeId="2" PostId="8971" RevisionGUID="d93117cd-ae46-4bad-906f-6ef13da9a7a7" CreationDate="2019-07-05T08:02:30.687" UserId="2041" Text="You're asking about two different types of library. OpenGL and Vulkan aren't just libraries: they're hardware interfaces. They are implemented by GPU vendors so that application developers can access the GPU, like a special kind of hardware driver. They're implemented in C or C++ and the core functionality is implemented by writing some structures in memory that the GPU itself can understand, then writing to registers on the GPU to make it read those structures and do the work. There isn't any C code in OpenGL to transform triangles, compute their projection onto the screen, and shade them, because that work is all done by the GPU.&#xD;&#xA;&#xD;&#xA;OTOH, Qt and Gtk are libraries for making applications. A lot of their work isn't about graphics: they provide a framework for applications to manage themes and interactivity, letting the application developer wire together different parts of the application with callbacks. This is just normal library code. They also provide GUI classes such as buttons and checkboxes. These will each have something like a &quot;draw&quot; function which draws the graphics on the screen. A few years ago this would commonly have been implemented using the OS's 2D drawing API (e.g. GDI on Windows), which offers operations like &quot;draw a filled rectangle&quot;, &quot;blit an image&quot;, but nowadays they're more likely to use OpenGL or Vulkan operations. The UI components are defined in images and they're used as textures to generate the image of the whole window via a sequence of OpenGL draw calls.&#xD;&#xA;&#xD;&#xA;You wouldn't implement OpenGL or Vulkan: this is something that GPU vendors create. You can't really do it yourself without detailed knowledge of the GPU hardware. (However, *Mesa* is an example of a software implementation of OpenGL, which doesn't depend on any GPU.)&#xD;&#xA;&#xD;&#xA;If you wanted to implement a GUI library like Qt, you might start by defining an abstract `Widget` class with a `draw` method, and then implementing concrete subclasses of it to draw particular GUI components. Add extra methods and functionality as you need it.&#xD;&#xA;&#xD;&#xA;To be honest, I don't think that would be a valuable project to work on. There are many smaller GUI frameworks already, and another toy one is not going to improve the world. You might treat it as just a learning project, but I think you'd learn more by studying one of the existing frameworks and writing an interesting GUI application on top of it." ContentLicense="CC BY-SA 4.0" />
  <row Id="24394" PostHistoryTypeId="2" PostId="8972" RevisionGUID="c23012e4-4bdf-442d-add7-a65c43ae8980" CreationDate="2019-07-05T15:52:47.500" UserId="3123" Text="When calculating fog along the ray we have two main part- transmittance and scattering.&#xD;&#xA;&#xD;&#xA;What happens when we have two different fogs? With different extinction and color?&#xD;&#xA;Both extinction and color constant along the ray.&#xD;&#xA;&#xD;&#xA;Transmittance seems easy to merge, probably something like this:&#xD;&#xA;$$T = e^{(\sigma_a+\sigma_b)d}$$&#xD;&#xA;Where _d_ is ray length.&#xD;&#xA;&#xD;&#xA;What about color?&#xD;&#xA;&#xD;&#xA;General in-scattering equation looks like this:&#xD;&#xA;$$S=\sigma *Fog_{color}\int_0^dT(x,\omega x)dx$$&#xD;&#xA;&#xD;&#xA;What will happen with this equation when there are two fogs?&#xD;&#xA;&#xD;&#xA;Will it become:&#xD;&#xA;$$Fog_{color}=lerp(Fog_a,Fog_b,\sigma_b/(\sigma_a+\sigma_b))$$&#xD;&#xA;$$\sigma_t=\sigma_a+\sigma_b$$&#xD;&#xA;$$S=\sigma_t*Fog_{color}*\int_0^de^{-\sigma_tx}dx$$&#xD;&#xA;Or&#xD;&#xA;$$S=\sum_0^n\sigma_i*Fog_i\int_0^dT_i(x,\omega x)dx$$&#xD;&#xA;Where _n_ is fogs count.&#xD;&#xA;&#xD;&#xA;Or something else? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24395" PostHistoryTypeId="1" PostId="8972" RevisionGUID="c23012e4-4bdf-442d-add7-a65c43ae8980" CreationDate="2019-07-05T15:52:47.500" UserId="3123" Text="Adding two fogs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24396" PostHistoryTypeId="3" PostId="8972" RevisionGUID="c23012e4-4bdf-442d-add7-a65c43ae8980" CreationDate="2019-07-05T15:52:47.500" UserId="3123" Text="|volumetric|fog|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24405" PostHistoryTypeId="2" PostId="8975" RevisionGUID="d7418d77-7f7d-47a5-8647-5ceb916a316c" CreationDate="2019-07-06T14:28:44.860" UserId="2479" Text="I am implementing a bloom post-processing effect in my DirectX 11 pet renderer. A post-processing pass is implemented by rendering a full-screen quad covered with texture from the previous pass. I first render the scene into a texture, which is first down-scaled prior to blurring.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene rendered with 1spp looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run a debugging post-processing pass, which just down-scales the image by the factor of 8, the result is very flickery:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Up-scaled back to the original resolution for clarity:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This looks like a result of a nearest neighbour filter and causes flickery artifacts in the bloom after blurring the image. The shader of the first pass originally used a point sampler, so I tried a linear sampler with no change. I also tried to enforce auto mipmap generating for better down-scaling behaviour but with no luck.&#xD;&#xA;&#xD;&#xA;What am I doing wrong? How does the mipmap generation in DirectX work anyway? Can I control the process beyond the mipmap level count?&#xD;&#xA;&#xD;&#xA;# Technical details&#xD;&#xA;&#xD;&#xA;The sampler is created like this:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture is created like this&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The associated render target view for rendering:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The associated shader resource view for reading in PS:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The PS run on a quad smaller by factor of 8: &#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/oweJl.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24406" PostHistoryTypeId="1" PostId="8975" RevisionGUID="d7418d77-7f7d-47a5-8647-5ceb916a316c" CreationDate="2019-07-06T14:28:44.860" UserId="2479" Text="Downscaling texture in DirectX 11" ContentLicense="CC BY-SA 4.0" />
  <row Id="24407" PostHistoryTypeId="3" PostId="8975" RevisionGUID="d7418d77-7f7d-47a5-8647-5ceb916a316c" CreationDate="2019-07-06T14:28:44.860" UserId="2479" Text="|image-processing|real-time|sampling|directx11|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24412" PostHistoryTypeId="5" PostId="8975" RevisionGUID="e908beec-f8d2-48bb-b370-4d28d4c4eec5" CreationDate="2019-07-06T16:16:38.180" UserId="2479" Comment="Removed unnecessary details" Text="I am implementing a bloom post-processing effect in my DirectX 11 pet renderer. A post-processing pass is implemented by rendering a full-screen quad covered with texture from the previous pass. I first render the scene into a texture, which is first down-scaled prior to blurring.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene rendered with 1spp looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run a debugging post-processing pass, which just down-scales the image by the factor of 8, the result is very flickery:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Up-scaled back to the original resolution for clarity:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I tried to improve the result by generating mipmap for the texture, but with no success. What am I doing wrong? How does the mipmap generation in DirectX work anyway? Can I control the process beyond the mipmap level count?&#xD;&#xA;&#xD;&#xA;# Technical details&#xD;&#xA;&#xD;&#xA;The sampler is created like this:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture is created like this&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The associated render target view for rendering:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The associated shader resource view for reading in PS:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The PS run on a quad smaller by factor of 8: &#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/oweJl.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24416" PostHistoryTypeId="5" PostId="8975" RevisionGUID="2b164375-0a59-45f8-b9d9-cff11f3a5cb4" CreationDate="2019-07-07T11:22:50.910" UserId="2479" Comment="minor rewording" Text="I am implementing a bloom post-processing effect in my DirectX 11 pet renderer. A post-processing pass is implemented by rendering a full-screen quad covered with texture from the previous pass. I first render the scene into a texture, which is first down-scaled prior to blurring.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene rendered with 1spp looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run a debugging post-processing pass, which just down-scales the image by the factor of 8, the result is very flickery:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Up-scaled back to the original resolution for clarity:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. Am I doing something wrong?&#xD;&#xA;&#xD;&#xA;How does the mipmap generation in DirectX work anyway? Can I control the process beyond the mipmap level count?&#xD;&#xA;&#xD;&#xA;# Technical details&#xD;&#xA;&#xD;&#xA;The sampler is created like this:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture is created like this&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The associated render target view for rendering:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The associated shader resource view for reading in PS:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The PS run on a quad smaller by factor of 8: &#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/oweJl.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24421" PostHistoryTypeId="2" PostId="8979" RevisionGUID="59280b00-890a-4729-b03b-168f76894c14" CreationDate="2019-07-07T15:15:17.770" UserId="10886" Text="It's probably something obvious but there seems to be a strange issue with lighting in my pipeline. I'm trying to keep everything in world space at the moment for simplicity but cannot figure out what's going on here. Take a look at my code:&#xD;&#xA;&#xD;&#xA;Geometry pass:&#xD;&#xA;&#xD;&#xA;```lang-glsl&#xD;&#xA;void main() {&#xD;&#xA;    vec4 worldPos = model * aPos;&#xD;&#xA;    FragPos = worldPos.xyz;&#xD;&#xA;    TexCoords = aTexCoords;&#xD;&#xA;&#xD;&#xA;    mat3 normalMatrix = transpose(inverse(mat3(model)));&#xD;&#xA;    Normal = normalize(normalMatrix * aNormal.xyz);&#xD;&#xA;    Tangent = normalize(normalMatrix * aTangent);&#xD;&#xA;    Binormal = normalize(normalMatrix * aBitangent);&#xD;&#xA;    NormalMatrix = normalMatrix;&#xD;&#xA;&#xD;&#xA;    gl_Position = projection * view * worldPos;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```lang-glsl&#xD;&#xA;void main() {&#xD;&#xA;    // world space model fragment position&#xD;&#xA;    gPosition = FragPos;&#xD;&#xA;    // world space normals translated from tangent space&#xD;&#xA;    mat3 tangentToWorld = mat3(Tangent, Binormal, Normal);&#xD;&#xA;    gNormal = tangentToWorld * (texture(normalmap, TexCoords).rgb * 2.0 - 1.0);&#xD;&#xA;    // diffuse per-fragment color&#xD;&#xA;    gColor = texture(albedo, TexCoords);&#xD;&#xA;    // Beyond here is material properties&#xD;&#xA;    gSpecular = vec4(&#xD;&#xA;        texture(material, TexCoords).rgb,&#xD;&#xA;        texture(ambient, TexCoords).a&#xD;&#xA;    );&#xD;&#xA;    gEmissive = texture(emissive, TexCoords);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Lighting pass:&#xD;&#xA;```lang-glsl&#xD;&#xA;void main() {&#xD;&#xA;    // rendering onto a framebuffer quad&#xD;&#xA;    TexCoords = aTexCoords;&#xD;&#xA;    gl_Position = vec4(aPos, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```lang-glsl&#xD;&#xA;void main() {&#xD;&#xA;    // World space model vertex&#xD;&#xA;    vec3 v_pos = texture(gPosition, TexCoords).rgb;&#xD;&#xA;&#xD;&#xA;    // light attenuation&#xD;&#xA;    float A = 20.0 / dot(light_position - v_pos, light_position - v_pos);&#xD;&#xA;&#xD;&#xA;    // L, V, H, N vectors&#xD;&#xA;    vec3 L = normalize(light_position - v_pos);&#xD;&#xA;    vec3 V = normalize(-v_pos);&#xD;&#xA;    vec3 H = normalize(L + V);&#xD;&#xA;    vec3 N = normalize(texture(gNormal, TexCoords).rgb);&#xD;&#xA;&#xD;&#xA;    // albedo/specular base&#xD;&#xA;    vec3 base = texture(gColor, TexCoords).xyz;&#xD;&#xA;&#xD;&#xA;    // roughness&#xD;&#xA;    float roughness = texture(gSpecular, TexCoords).y;&#xD;&#xA;&#xD;&#xA;    // metallic&#xD;&#xA;    float metallic = texture(gSpecular, TexCoords).x;&#xD;&#xA;&#xD;&#xA;    // mix between metal and non-metal material, for non-metal&#xD;&#xA;    // constant base specular factor of 0.04 grey is used&#xD;&#xA;    vec3 specular = mix(vec3(0.04), base, metallic);&#xD;&#xA;&#xD;&#xA;    // compute material reflectance&#xD;&#xA;&#xD;&#xA;    float NdL = max(0.0  , dot(N, L));&#xD;&#xA;    float NdV = max(0.001, dot(N, V));&#xD;&#xA;    float NdH = max(0.001, dot(N, H));&#xD;&#xA;    float HdV = max(0.001, dot(H, V));&#xD;&#xA;    float LdV = max(0.001, dot(L, V));&#xD;&#xA;&#xD;&#xA;    // specular reflectance with COOK-TORRANCE&#xD;&#xA;    vec3 specfresnel = fresnel_factor(specular, HdV);&#xD;&#xA;    vec3 specref = cooktorrance_specular(NdL, NdV, NdH, specfresnel, roughness);&#xD;&#xA;&#xD;&#xA;    specref *= vec3(NdL);&#xD;&#xA;    vec3 diffref = (vec3(1.0) - specfresnel) * phong_diffuse() * NdL;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // compute lighting&#xD;&#xA;    vec3 reflected_light = vec3(0);&#xD;&#xA;    vec3 diffuse_light = vec3(0);&#xD;&#xA;&#xD;&#xA;    // point light&#xD;&#xA;    vec3 light_color = vec3(1.0) * A;&#xD;&#xA;    reflected_light += specref * light_color;&#xD;&#xA;    diffuse_light += diffref * light_color;&#xD;&#xA;&#xD;&#xA;    // final result&#xD;&#xA;    vec3 result =&#xD;&#xA;        diffuse_light * mix(base, vec3(0.0), metallic) +&#xD;&#xA;        reflected_light;&#xD;&#xA;&#xD;&#xA;    color = vec4(result, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is before IBL is applied but I don't think that will make a difference here. Anyways, here's the weird result I'm getting (keep in mind the camera is the same as the point light position):&#xD;&#xA;&#xD;&#xA;[![camerapointlight][1]][1]&#xD;&#xA;&#xD;&#xA;For reference I'm using this model https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/DamagedHelmet . Thanks to anyone who can help&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WI1U0.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24422" PostHistoryTypeId="1" PostId="8979" RevisionGUID="59280b00-890a-4729-b03b-168f76894c14" CreationDate="2019-07-07T15:15:17.770" UserId="10886" Text="Strange dark spot when lighting in deferred rendering PBR shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="24423" PostHistoryTypeId="3" PostId="8979" RevisionGUID="59280b00-890a-4729-b03b-168f76894c14" CreationDate="2019-07-07T15:15:17.770" UserId="10886" Text="|shader|glsl|brdf|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24426" PostHistoryTypeId="4" PostId="8975" RevisionGUID="71dd23e7-f98a-4e07-bf5e-a6414dfc2862" CreationDate="2019-07-07T23:26:26.537" UserId="2479" Comment="Better headline " Text="Downscaling texture via mipmap in DirectX 11" ContentLicense="CC BY-SA 4.0" />
  <row Id="24427" PostHistoryTypeId="2" PostId="8980" RevisionGUID="eba4203b-f525-4982-b141-f0b2d7cb004b" CreationDate="2019-07-08T07:02:35.267" UserId="10720" Text="To anyone who is reading this in future:&#xD;&#xA;&#xD;&#xA;I ended up taking an alternative route: Blender scripting.&#xD;&#xA;&#xD;&#xA;Blender comes with a built-in GLTF / GLB exporter. Here is what the render pipeline looks like in my code:&#xD;&#xA;&#xD;&#xA;1. Define blender model which will act as template, complete with textures and materials.&#xD;&#xA;2. Define a meta JSON which defines the images for all sides&#xD;&#xA;3. In blenders Python script panel, read the meta JSON defined in #2 and start replacing the images in #1 in a loop&#xD;&#xA;4. After each replace, call the export plugins GLB functionality&#xD;&#xA;&#xD;&#xA;Profit!&#xD;&#xA;&#xD;&#xA;Unfortunately, I am not allowed to post the script I wrote here / open source it." ContentLicense="CC BY-SA 4.0" />
  <row Id="24431" PostHistoryTypeId="2" PostId="8982" RevisionGUID="aa4ce41b-5379-4e11-a9d4-a03d49c38467" CreationDate="2019-07-08T13:58:28.220" UserId="10892" Text="i want some of your advices. To begin with i ve never studied computer graphics and i want to do a project with Path tracing which i didnt find the right materials to begin with. Is it recomeneded to start directly learn Path tracing or i have to learn something before. and i wish if someone can give some online examples and some materials  &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24432" PostHistoryTypeId="1" PostId="8982" RevisionGUID="aa4ce41b-5379-4e11-a9d4-a03d49c38467" CreationDate="2019-07-08T13:58:28.220" UserId="10892" Text="Path tracing best materials to learn" ContentLicense="CC BY-SA 4.0" />
  <row Id="24433" PostHistoryTypeId="3" PostId="8982" RevisionGUID="aa4ce41b-5379-4e11-a9d4-a03d49c38467" CreationDate="2019-07-08T13:58:28.220" UserId="10892" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24434" PostHistoryTypeId="50" PostId="8888" RevisionGUID="9237fc8a-46c4-462f-9315-a629d56b99fa" CreationDate="2019-07-08T14:01:45.277" UserId="-1" />
  <row Id="24435" PostHistoryTypeId="5" PostId="8979" RevisionGUID="197ab9df-954f-4697-acc6-bbbb376fde76" CreationDate="2019-07-08T16:42:27.240" UserId="10886" Comment="added 2234 characters in body" Text="It's probably something obvious but there seems to be a strange issue with lighting in my pipeline. I'm trying to keep everything in world space at the moment for simplicity but cannot figure out what's going on here. Take a look at my code:&#xD;&#xA;&#xD;&#xA;Geometry pass:&#xD;&#xA;&#xD;&#xA;helmet.vert&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec4 aPos;&#xD;&#xA;layout (location = 1) in vec4 aNormal;&#xD;&#xA;layout (location = 2) in vec2 aTexCoords;&#xD;&#xA;layout (location = 3) in vec3 aTangent;&#xD;&#xA;layout (location = 4) in vec3 aBitangent;&#xD;&#xA;&#xD;&#xA;out vec3 FragPos;&#xD;&#xA;out vec2 TexCoords;&#xD;&#xA;out vec3 Normal;&#xD;&#xA;out vec3 Tangent;&#xD;&#xA;out vec3 Binormal;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 worldPos = model * aPos;&#xD;&#xA;    FragPos = worldPos.xyz;&#xD;&#xA;    TexCoords = aTexCoords;&#xD;&#xA;&#xD;&#xA;    mat3 normalMatrix = transpose(inverse(mat3(model)));&#xD;&#xA;    Normal = normalize(normalMatrix * aNormal.xyz);&#xD;&#xA;    Tangent = normalize(normalMatrix * aTangent);&#xD;&#xA;    Binormal = normalize(normalMatrix * aBitangent);&#xD;&#xA;&#xD;&#xA;    gl_Position = projection * view * worldPos;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;helmet.frag&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) out vec3 gPosition;&#xD;&#xA;layout (location = 1) out vec3 gNormal;&#xD;&#xA;layout (location = 2) out vec4 gColor;&#xD;&#xA;layout (location = 3) out vec4 gSpecular;&#xD;&#xA;layout (location = 4) out vec4 gEmissive;&#xD;&#xA;&#xD;&#xA;in vec2 TexCoords;&#xD;&#xA;in vec3 FragPos;&#xD;&#xA;in vec3 Normal;&#xD;&#xA;in vec3 Tangent;&#xD;&#xA;in vec3 Binormal;&#xD;&#xA;&#xD;&#xA;uniform sampler2D albedo;&#xD;&#xA;uniform sampler2D material;&#xD;&#xA;uniform sampler2D normals;&#xD;&#xA;uniform sampler2D ambient;&#xD;&#xA;uniform sampler2D emissive;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // world space model fragment position&#xD;&#xA;    gPosition = FragPos;&#xD;&#xA;    // world space normals translated from tangent space&#xD;&#xA;    mat3 tangentToWorld = mat3(Tangent, Binormal, Normal);&#xD;&#xA;    gNormal = tangentToWorld * (texture(normalmap, TexCoords).rgb * 2.0 - 1.0);&#xD;&#xA;    // diffuse per-fragment color&#xD;&#xA;    gColor = texture(albedo, TexCoords);&#xD;&#xA;    // Beyond here is material properties&#xD;&#xA;    gSpecular = vec4(&#xD;&#xA;        texture(material, TexCoords).rgb,&#xD;&#xA;        texture(ambient, TexCoords).a&#xD;&#xA;    );&#xD;&#xA;    gEmissive = texture(emissive, TexCoords);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Lighting pass:&#xD;&#xA;&#xD;&#xA;pointlight.vert&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 aPos;&#xD;&#xA;layout (location = 1) in vec2 aTexCoords;&#xD;&#xA;&#xD;&#xA;out vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // rendering onto a framebuffer quad&#xD;&#xA;    TexCoords = aTexCoords;&#xD;&#xA;    gl_Position = vec4(aPos, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;pointlight.frag&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;in vec2 TexCoords;&#xD;&#xA;out vec4 color;&#xD;&#xA;&#xD;&#xA;uniform sampler2D gPosition;&#xD;&#xA;uniform sampler2D gNormal;&#xD;&#xA;uniform sampler2D gColor;&#xD;&#xA;uniform sampler2D gSpecular;&#xD;&#xA;&#xD;&#xA;// light position&#xD;&#xA;uniform vec3 position;&#xD;&#xA;&#xD;&#xA;// phong (lambertian) diffuse term&#xD;&#xA;float phong_diffuse() {&#xD;&#xA;    return (1.0 / PI);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;// compute fresnel specular factor for given base specular and product&#xD;&#xA;vec3 fresnel_factor(in vec3 f0, in float product) {&#xD;&#xA;    return f0 + (1.01 - f0)*pow(1.01 - product, 5.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float D_GGX(in float roughness, in float NdH) {&#xD;&#xA;    float m = roughness * roughness;&#xD;&#xA;    float m2 = m * m;&#xD;&#xA;    float d = (NdH * m2 - NdH) * NdH + 1.0;&#xD;&#xA;    return m2 / (PI * d * d);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float G_schlick(in float roughness, in float NdV, in float NdL) {&#xD;&#xA;    float k = roughness * roughness * 0.5;&#xD;&#xA;    float V = NdV * (1.0 - k) + k;&#xD;&#xA;    float L = NdL * (1.0 - k) + k;&#xD;&#xA;    return 0.25 / (V * L);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// cook-torrance specular calculation&#xD;&#xA;vec3 cooktorrance_specular(in float NdL, in float NdV, in float NdH, in vec3 specular, in float roughness) {&#xD;&#xA;    float D = D_GGX(roughness, NdH);&#xD;&#xA;&#xD;&#xA;    float G = G_schlick(roughness, NdV, NdL);&#xD;&#xA;&#xD;&#xA;    float rim = mix(1.0 - roughness * texture(gSpecular, TexCoords).w * 0.9, 1.0, NdV);&#xD;&#xA;&#xD;&#xA;    return (1.0 / rim) * specular * G * D;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // World space model vertex&#xD;&#xA;    vec3 v_pos = texture(gPosition, TexCoords).rgb;&#xD;&#xA;&#xD;&#xA;    // light attenuation&#xD;&#xA;    float A = 20.0 / dot(light_position - v_pos, light_position - v_pos);&#xD;&#xA;&#xD;&#xA;    // L, V, H, N vectors&#xD;&#xA;    vec3 L = normalize(light_position - v_pos);&#xD;&#xA;    vec3 V = normalize(-v_pos);&#xD;&#xA;    vec3 H = normalize(L + V);&#xD;&#xA;    vec3 N = normalize(texture(gNormal, TexCoords).rgb);&#xD;&#xA;&#xD;&#xA;    // albedo/specular base&#xD;&#xA;    vec3 base = texture(gColor, TexCoords).xyz;&#xD;&#xA;&#xD;&#xA;    // roughness&#xD;&#xA;    float roughness = texture(gSpecular, TexCoords).y;&#xD;&#xA;&#xD;&#xA;    // metallic&#xD;&#xA;    float metallic = texture(gSpecular, TexCoords).x;&#xD;&#xA;&#xD;&#xA;    // mix between metal and non-metal material, for non-metal&#xD;&#xA;    // constant base specular factor of 0.04 grey is used&#xD;&#xA;    vec3 specular = mix(vec3(0.04), base, metallic);&#xD;&#xA;&#xD;&#xA;    // compute material reflectance&#xD;&#xA;&#xD;&#xA;    float NdL = max(0.0  , dot(N, L));&#xD;&#xA;    float NdV = max(0.001, dot(N, V));&#xD;&#xA;    float NdH = max(0.001, dot(N, H));&#xD;&#xA;    float HdV = max(0.001, dot(H, V));&#xD;&#xA;    float LdV = max(0.001, dot(L, V));&#xD;&#xA;&#xD;&#xA;    // specular reflectance with COOK-TORRANCE&#xD;&#xA;    vec3 specfresnel = fresnel_factor(specular, HdV);&#xD;&#xA;    vec3 specref = cooktorrance_specular(NdL, NdV, NdH, specfresnel, roughness);&#xD;&#xA;&#xD;&#xA;    specref *= vec3(NdL);&#xD;&#xA;    vec3 diffref = (vec3(1.0) - specfresnel) * phong_diffuse() * NdL;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // compute lighting&#xD;&#xA;    vec3 reflected_light = vec3(0);&#xD;&#xA;    vec3 diffuse_light = vec3(0);&#xD;&#xA;&#xD;&#xA;    // point light&#xD;&#xA;    vec3 light_color = vec3(1.0) * A;&#xD;&#xA;    reflected_light += specref * light_color;&#xD;&#xA;    diffuse_light += diffref * light_color;&#xD;&#xA;&#xD;&#xA;    // final result&#xD;&#xA;    vec3 result =&#xD;&#xA;        diffuse_light * mix(base, vec3(0.0), metallic) +&#xD;&#xA;        reflected_light;&#xD;&#xA;&#xD;&#xA;    color = vec4(result, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is before IBL is applied but I don't think that will make a difference here. Anyways, here's the weird result I'm getting (keep in mind the camera is the same as the point light position):&#xD;&#xA;&#xD;&#xA;[![camerapointlight][1]][1]&#xD;&#xA;&#xD;&#xA;For reference I'm using this model https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/DamagedHelmet . Thanks to anyone who can help&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WI1U0.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24436" PostHistoryTypeId="5" PostId="8979" RevisionGUID="d42ac709-dcc0-4071-8163-6d45f196c7ba" CreationDate="2019-07-08T16:48:24.433" UserId="10886" Comment="added 2 characters in body" Text="It's probably something obvious but there seems to be a strange issue with lighting in my pipeline. I'm trying to keep everything in world space at the moment for simplicity but cannot figure out what's going on here. Take a look at my code:&#xD;&#xA;&#xD;&#xA;Geometry pass:&#xD;&#xA;&#xD;&#xA;helmet.vert&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec4 aPos;&#xD;&#xA;layout (location = 1) in vec4 aNormal;&#xD;&#xA;layout (location = 2) in vec2 aTexCoords;&#xD;&#xA;layout (location = 3) in vec3 aTangent;&#xD;&#xA;layout (location = 4) in vec3 aBitangent;&#xD;&#xA;&#xD;&#xA;out vec3 FragPos;&#xD;&#xA;out vec2 TexCoords;&#xD;&#xA;out vec3 Normal;&#xD;&#xA;out vec3 Tangent;&#xD;&#xA;out vec3 Binormal;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 worldPos = model * aPos;&#xD;&#xA;    FragPos = worldPos.xyz;&#xD;&#xA;    TexCoords = aTexCoords;&#xD;&#xA;&#xD;&#xA;    mat3 normalMatrix = transpose(inverse(mat3(model)));&#xD;&#xA;    Normal = normalize(normalMatrix * aNormal.xyz);&#xD;&#xA;    Tangent = normalize(normalMatrix * aTangent);&#xD;&#xA;    Binormal = normalize(normalMatrix * aBitangent);&#xD;&#xA;&#xD;&#xA;    gl_Position = projection * view * worldPos;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;helmet.frag&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) out vec3 gPosition;&#xD;&#xA;layout (location = 1) out vec3 gNormal;&#xD;&#xA;layout (location = 2) out vec4 gColor;&#xD;&#xA;layout (location = 3) out vec4 gSpecular;&#xD;&#xA;layout (location = 4) out vec4 gEmissive;&#xD;&#xA;&#xD;&#xA;in vec2 TexCoords;&#xD;&#xA;in vec3 FragPos;&#xD;&#xA;in vec3 Normal;&#xD;&#xA;in vec3 Tangent;&#xD;&#xA;in vec3 Binormal;&#xD;&#xA;&#xD;&#xA;// Textures passed from assimp&#xD;&#xA;uniform sampler2D albedo;&#xD;&#xA;uniform sampler2D material;&#xD;&#xA;uniform sampler2D normalmap;&#xD;&#xA;uniform sampler2D ambient;&#xD;&#xA;uniform sampler2D emissive;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // world space model fragment position&#xD;&#xA;    gPosition = FragPos;&#xD;&#xA;    // world space normals translated from tangent space&#xD;&#xA;    mat3 tangentToWorld = mat3(Tangent, Binormal, Normal);&#xD;&#xA;    gNormal = tangentToWorld * (texture(normalmap, TexCoords).rgb * 2.0 - 1.0);&#xD;&#xA;    // diffuse per-fragment color&#xD;&#xA;    gColor = texture(albedo, TexCoords);&#xD;&#xA;    // Beyond here is material properties&#xD;&#xA;    gSpecular = vec4(&#xD;&#xA;        texture(material, TexCoords).rgb,&#xD;&#xA;        texture(ambient, TexCoords).a&#xD;&#xA;    );&#xD;&#xA;    gEmissive = texture(emissive, TexCoords);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Lighting pass:&#xD;&#xA;&#xD;&#xA;pointlight.vert&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 aPos;&#xD;&#xA;layout (location = 1) in vec2 aTexCoords;&#xD;&#xA;&#xD;&#xA;out vec2 TexCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // rendering onto a framebuffer quad&#xD;&#xA;    TexCoords = aTexCoords;&#xD;&#xA;    gl_Position = vec4(aPos, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;pointlight.frag&#xD;&#xA;```lang-glsl&#xD;&#xA;#version 410 core&#xD;&#xA;&#xD;&#xA;in vec2 TexCoords;&#xD;&#xA;out vec4 color;&#xD;&#xA;&#xD;&#xA;uniform sampler2D gPosition;&#xD;&#xA;uniform sampler2D gNormal;&#xD;&#xA;uniform sampler2D gColor;&#xD;&#xA;uniform sampler2D gSpecular;&#xD;&#xA;&#xD;&#xA;// light position&#xD;&#xA;uniform vec3 position;&#xD;&#xA;&#xD;&#xA;// phong (lambertian) diffuse term&#xD;&#xA;float phong_diffuse() {&#xD;&#xA;    return (1.0 / PI);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;// compute fresnel specular factor for given base specular and product&#xD;&#xA;vec3 fresnel_factor(in vec3 f0, in float product) {&#xD;&#xA;    return f0 + (1.01 - f0)*pow(1.01 - product, 5.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float D_GGX(in float roughness, in float NdH) {&#xD;&#xA;    float m = roughness * roughness;&#xD;&#xA;    float m2 = m * m;&#xD;&#xA;    float d = (NdH * m2 - NdH) * NdH + 1.0;&#xD;&#xA;    return m2 / (PI * d * d);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float G_schlick(in float roughness, in float NdV, in float NdL) {&#xD;&#xA;    float k = roughness * roughness * 0.5;&#xD;&#xA;    float V = NdV * (1.0 - k) + k;&#xD;&#xA;    float L = NdL * (1.0 - k) + k;&#xD;&#xA;    return 0.25 / (V * L);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// cook-torrance specular calculation&#xD;&#xA;vec3 cooktorrance_specular(in float NdL, in float NdV, in float NdH, in vec3 specular, in float roughness) {&#xD;&#xA;    float D = D_GGX(roughness, NdH);&#xD;&#xA;&#xD;&#xA;    float G = G_schlick(roughness, NdV, NdL);&#xD;&#xA;&#xD;&#xA;    float rim = mix(1.0 - roughness * texture(gSpecular, TexCoords).w * 0.9, 1.0, NdV);&#xD;&#xA;&#xD;&#xA;    return (1.0 / rim) * specular * G * D;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // World space model vertex&#xD;&#xA;    vec3 v_pos = texture(gPosition, TexCoords).rgb;&#xD;&#xA;&#xD;&#xA;    // light attenuation&#xD;&#xA;    float A = 20.0 / dot(light_position - v_pos, light_position - v_pos);&#xD;&#xA;&#xD;&#xA;    // L, V, H, N vectors&#xD;&#xA;    vec3 L = normalize(light_position - v_pos);&#xD;&#xA;    vec3 V = normalize(-v_pos);&#xD;&#xA;    vec3 H = normalize(L + V);&#xD;&#xA;    vec3 N = normalize(texture(gNormal, TexCoords).rgb);&#xD;&#xA;&#xD;&#xA;    // albedo/specular base&#xD;&#xA;    vec3 base = texture(gColor, TexCoords).xyz;&#xD;&#xA;&#xD;&#xA;    // roughness&#xD;&#xA;    float roughness = texture(gSpecular, TexCoords).y;&#xD;&#xA;&#xD;&#xA;    // metallic&#xD;&#xA;    float metallic = texture(gSpecular, TexCoords).x;&#xD;&#xA;&#xD;&#xA;    // mix between metal and non-metal material, for non-metal&#xD;&#xA;    // constant base specular factor of 0.04 grey is used&#xD;&#xA;    vec3 specular = mix(vec3(0.04), base, metallic);&#xD;&#xA;&#xD;&#xA;    // compute material reflectance&#xD;&#xA;&#xD;&#xA;    float NdL = max(0.0  , dot(N, L));&#xD;&#xA;    float NdV = max(0.001, dot(N, V));&#xD;&#xA;    float NdH = max(0.001, dot(N, H));&#xD;&#xA;    float HdV = max(0.001, dot(H, V));&#xD;&#xA;    float LdV = max(0.001, dot(L, V));&#xD;&#xA;&#xD;&#xA;    // specular reflectance with COOK-TORRANCE&#xD;&#xA;    vec3 specfresnel = fresnel_factor(specular, HdV);&#xD;&#xA;    vec3 specref = cooktorrance_specular(NdL, NdV, NdH, specfresnel, roughness);&#xD;&#xA;&#xD;&#xA;    specref *= vec3(NdL);&#xD;&#xA;    vec3 diffref = (vec3(1.0) - specfresnel) * phong_diffuse() * NdL;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // compute lighting&#xD;&#xA;    vec3 reflected_light = vec3(0);&#xD;&#xA;    vec3 diffuse_light = vec3(0);&#xD;&#xA;&#xD;&#xA;    // point light&#xD;&#xA;    vec3 light_color = vec3(1.0) * A;&#xD;&#xA;    reflected_light += specref * light_color;&#xD;&#xA;    diffuse_light += diffref * light_color;&#xD;&#xA;&#xD;&#xA;    // final result&#xD;&#xA;    vec3 result =&#xD;&#xA;        diffuse_light * mix(base, vec3(0.0), metallic) +&#xD;&#xA;        reflected_light;&#xD;&#xA;&#xD;&#xA;    color = vec4(result, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is before IBL is applied but I don't think that will make a difference here. Anyways, here's the weird result I'm getting (keep in mind the camera is the same as the point light position):&#xD;&#xA;&#xD;&#xA;[![camerapointlight][1]][1]&#xD;&#xA;&#xD;&#xA;For reference I'm using this model https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/DamagedHelmet . Thanks to anyone who can help&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WI1U0.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24437" PostHistoryTypeId="2" PostId="8983" RevisionGUID="f7540646-16eb-4cf1-a810-505c358dff38" CreationDate="2019-07-08T17:41:47.480" UserId="9420" Text="In the definition of Radiance, which according to PBRT is defined as&#xD;&#xA;&gt; flux per unit solid angle $d\omega$ per unit projected area $dA^\perp$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$L_i=\frac{d\Phi}{d\omega\ dA^\perp}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My original assumption was that the $dA^\perp$ term is used to weaken the irradiance contribution due to the incident angle (which I assume is just Lambert's cosine law). However, in the rendering equation, we've already explicitly apply Lambert's law with the $\cos\theta$ term:  &#xD;&#xA;$$\int_\Omega L_i(\omega') \, f_r(\omega, \omega') \, \cos\theta \, d\omega'$$&#xD;&#xA;&#xD;&#xA;I assume we arn't applying Lambert's law twice, so what exactly is this $dA^\perp$ term?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24438" PostHistoryTypeId="1" PostId="8983" RevisionGUID="f7540646-16eb-4cf1-a810-505c358dff38" CreationDate="2019-07-08T17:41:47.480" UserId="9420" Text="What is the purpose of the projected solid angle $dA^\perp$ term in the definition of Radiance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24439" PostHistoryTypeId="3" PostId="8983" RevisionGUID="f7540646-16eb-4cf1-a810-505c358dff38" CreationDate="2019-07-08T17:41:47.480" UserId="9420" Text="|raytracing|pbr|radiosity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24440" PostHistoryTypeId="2" PostId="8984" RevisionGUID="e17654d3-dc70-43cd-b5e5-b2fc88f0e39f" CreationDate="2019-07-08T20:59:53.557" UserId="2479" Text="Your main idea is more or less correct. The cosine hidden in the projected solid angle measure $$dA^\perp = dA\cos(θ)$$ compensates the weakening of irradiance due to inciden angle (the Lambert's cosine law). This makes radiance independent from the incident angle. Mi guess is that the main motivation was to make it more practical to work with.&#xD;&#xA;&#xD;&#xA;The cosine in the rendering equation comes from the definition of BRDF:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{\mathrm{d}E\left(\omega_{i}\right)} =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{L_{i}\left(\omega_{i}\right)\mathrm{d}\sigma^{\bot}\left(\omega_{i}\right)} =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{L_{i}\left(\omega_{i}\right)\cos\theta_{i}\mathrm{d}\omega_{i}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which can be rewritten as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathrm{d}L_{o}\left(\omega_{o}\right)&#xD;&#xA;=L_{i}\left(\omega_{i}\right) f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) \cos\theta_{i} \mathrm{d}\omega_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which can be integrated over the hemisphere the get the reflected radiance in a given direction $\omega_o$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int_\Omega L_{i}\left(\omega_{i}\right) f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) \cos\theta_{i} \mathrm{d}\omega_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Voila, the rendering equation!&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;PS: Sorry about the changed notation. I find this one more practical. I can rewrite it if it confuses you." ContentLicense="CC BY-SA 4.0" />
  <row Id="24441" PostHistoryTypeId="5" PostId="8984" RevisionGUID="2b12b81b-f98b-4946-8675-c1a137da885e" CreationDate="2019-07-08T21:06:46.387" UserId="2479" Comment="rewording" Text="Your main idea is more or less correct. The cosine hidden in the projected solid angle measure $$dA^\perp = dA\cos(θ)$$ compensates the weakening of irradiance due to inciden angle (the Lambert's cosine law). This makes radiance independent from the incident angle. Mi guess is that the main motivation was to make it more practical to work with.&#xD;&#xA;&#xD;&#xA;The cosine in the rendering equation comes from the definition of BRDF:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{\mathrm{d}E\left(\omega_{i}\right)} =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{L_{i}\left(\omega_{i}\right)\mathrm{d}\sigma^{\bot}\left(\omega_{i}\right)} =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{L_{i}\left(\omega_{i}\right)\cos\theta_{i}\mathrm{d}\omega_{i}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which can be rewritten as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathrm{d}L_{o}\left(\omega_{o}\right)&#xD;&#xA;=f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) L_{i}\left(\omega_{i}\right) \cos\theta_{i} \mathrm{d}\omega_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which can be integrated over the hemisphere the get the radiance reflected in a given direction $\omega_o$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int_\Omega f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) L_{i}\left(\omega_{i}\right) \cos\theta_{i} \mathrm{d}\omega_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Voila, the rendering equation!&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;PS: Sorry about the changed notation ($\omega_{i}, \omega_{o}$ vs. $\omega^{\prime}, \omega$). I find this one more practical. I can rewrite it if it confuses you." ContentLicense="CC BY-SA 4.0" />
  <row Id="24442" PostHistoryTypeId="5" PostId="8975" RevisionGUID="6ec7c3d9-3206-4128-ac25-71e75872d1de" CreationDate="2019-07-08T21:18:51.063" UserId="2479" Comment="Removed unnecessary details" Text="I am implementing a bloom post-processing effect in my DirectX 11 pet renderer. A post-processing pass is implemented by rendering a full-screen quad covered with texture from the previous pass. As a first step I down-scale the texture by rendering it into a smaller texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8, the result is very flickery:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Up-scaled back to the original resolution for clarity:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. Am I doing something wrong?&#xD;&#xA;&#xD;&#xA;How does the mipmap generation in DirectX work anyway? Can I control the process beyond the mipmap level count?&#xD;&#xA;&#xD;&#xA;# Technical details&#xD;&#xA;&#xD;&#xA;The sampler:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture:&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The render target view:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The shader resource view:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The PS:&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/oweJl.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24443" PostHistoryTypeId="2" PostId="8985" RevisionGUID="3d2d262b-a6e6-40ac-bf1e-c44f1188f074" CreationDate="2019-07-09T01:49:24.947" UserId="9500" Text="So, I'll start by saying I'm not a driver developer, but I have read many comments and docs in this regard. &#xD;&#xA;&#xD;&#xA;First of all, we can see how Khronos's own [slides][1] on presentation day were mentioning some rather vague &quot;any OpenGL ES 3.1 GPU&quot; (or desktop 4.X). This means [something][2] added around that mark would be the secret to it. Compute shaders are definitively [at least one of] the things, being confirmed [here][3], by an [Intel developer][4], and in [the spec][5] with no possible unsupported value for `MaxComputeWorkGroupSize` and this likely smoking gun: &#xD;&#xA;&gt; If an implementation exposes any queue family that supports graphics&#xD;&#xA;&gt; operations, at least one queue family of at least one physical device&#xD;&#xA;&gt; exposed by the implementation **must** support both graphics and&#xD;&#xA;&gt; compute operations.&#xD;&#xA;&#xD;&#xA;In addition to that though, it could *also* be there are other mandatory capabilities (such as indirect draws or load&amp;store, mentioned in the comments above too). But I have some slight difficulty interpreting the document. With the exception of [robustBufferAccess][6], it seems like just about anything else big you could imagine is optional (from anisotropic filter, to geometry and tessellation shaders, to any special number format other than good old float32)&#xD;&#xA;&#xD;&#xA;This being the most hypothetically simple case then, doesn't mean it's all fine and dandy. Not having [virtual memory][7] will make your life a hell for example, and lack of other [architectural features][8] may basically nullify whatever theoretical advantage in speed the API has. &#xD;&#xA;&#xD;&#xA;These links should also answer your wonder about ATi cards. Likely not much of a different story for NVidia then (which even managed to eventually release DX12 for Fermi, but that was already [on thin ice][9]). Tesla's question if any would be &quot;what's so special about compute shaders again&quot;. As for Intel, I don't know what you are talking about, Gen8 is supported since [Day1][10] and in fact even [Gen7][11] *shakily* works. &#xD;&#xA;&#xD;&#xA;fun fact p.s.: it turns out that [D3D 9_3][12] feature level is also potentially enough to [support][13] vulkan&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/assets/uploads/developers/library/overview/Vk_201602_Overview_Feb16.pdf#page=13&#xD;&#xA;  [2]: https://www.anandtech.com/show/7867/khronos-announces-opengl-es-31&#xD;&#xA;  [3]: https://pcper.com/2015/03/gdc-15-what-is-vulkan-glnext-spir-v-and-opencl-2-1/&#xD;&#xA;  [4]: https://youtu.be/2ryvYS47V0E?t=3176&#xD;&#xA;  [5]: https://www.khronos.org/registry/vulkan/specs/1.1/pdf/vkspec.pdf&#xD;&#xA;  [6]: https://www.khronos.org/registry/vulkan/specs/1.0/html/chap30.html#features-requirements&#xD;&#xA;  [7]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/open-source-amd-linux/1004192-r600-gallium3d-now-effectively-at-opengl-4-4-a-nudge-away-from-gl-4-5/page2#post1004523&#xD;&#xA;  [8]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/vulkan/845690-amd-s-vulkan-driver-will-only-work-with-the-amdgpu-kernel-driver/page3#post845731&#xD;&#xA;  [9]: https://techreport.com/news/32191/nvidia-finally-lets-fermi-gpu-owners-enjoy-directx-12/&#xD;&#xA;  [10]: https://01.org/linuxgraphics/blogs/jekstrand/2016/open-source-vulkan-drivers-intel-hardware&#xD;&#xA;  [11]: https://stackoverflow.com/questions/41497142/can-i-install-a-vulkan-driver-on-my-3rd-gen-intel-ivy-bridge-integrated-gpu-on-u&#xD;&#xA;  [12]: https://www.anandtech.com/show/8649/arm-announces-mali-800-series-gpus-t860-t830-t820&#xD;&#xA;  [13]: https://developer.arm.com/solutions/graphics/resources/faqs#vulkan_which" ContentLicense="CC BY-SA 4.0" />
  <row Id="24444" PostHistoryTypeId="2" PostId="8986" RevisionGUID="1b8b7369-1d46-4750-ab4e-c82c95f5e246" CreationDate="2019-07-09T07:31:11.077" UserId="6041" Text="The two cosine terms are basically one and refer to the foreshortening effect which is: &#xD;&#xA;&#xD;&#xA;The irradiance falling onto a patch must be modified by the cosine of the angle of the patch to the source.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now from the definition of the irradiance(integrating irradiance on the hemisphere and multiplying it by BRDF gives rendering equation):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;irradiance is flux per unit area, therefore:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Reordering it gives:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;which is the definition of radiance, with the same cosine term in definition of irradiance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-------------------------------------------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Quoting from [Image Acquisition Handbook page 36][5]:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pnJKQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VdqDS.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/X7zm9.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZHsS8.png&#xD;&#xA;  [5]: https://books.google.co.uk/books?id=UmzsCAAAQBAJ&amp;dq=machine%20vision&amp;q=confusing%20to%20novice#v=onepage&amp;q&amp;f=false&#xD;&#xA;  [6]: https://i.stack.imgur.com/Me9OM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24445" PostHistoryTypeId="5" PostId="8986" RevisionGUID="87c73544-2684-4402-8a90-66a4d1579793" CreationDate="2019-07-09T07:37:40.817" UserId="6041" Comment="deleted 201 characters in body" Text="The two cosine terms are basically one and refer to the foreshortening effect which is: &#xD;&#xA;&#xD;&#xA;The irradiance falling onto a patch must be modified by the cosine of the angle of the patch to the source.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now from the definition of the irradiance:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;irradiance is flux per unit area, therefore:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Reordering it gives:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;which is the definition of radiance, with the same cosine term in definition of irradiance(integrating irradiance on the hemisphere and multiplying it by BRDF gives rendering equation).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pnJKQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VdqDS.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/X7zm9.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZHsS8.png&#xD;&#xA;  [5]: https://books.google.co.uk/books?id=UmzsCAAAQBAJ&amp;dq=machine%20vision&amp;q=confusing%20to%20novice#v=onepage&amp;q&amp;f=false" ContentLicense="CC BY-SA 4.0" />
  <row Id="24446" PostHistoryTypeId="5" PostId="8986" RevisionGUID="dcf6d399-c19f-448b-bf5e-87f8864a3a65" CreationDate="2019-07-09T08:32:36.567" UserId="6041" Comment="added 576 characters in body" Text="The two cosine terms basically refer to the foreshortening effect which says: &#xD;&#xA;&#xD;&#xA;The irradiance falling onto a patch must be modified by the cosine of the angle of the patch to the source.&#xD;&#xA;&#xD;&#xA;Now from the definition of the irradiance:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;irradiance is flux per unit area, therefore:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Reordering it gives:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;which is the definition of radiance, with the same cosine term that was in definition of irradiance(integrating irradiance on the hemisphere and multiplying it by BRDF gives rendering equation).&#xD;&#xA;&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;So both cosine terms refer to one effect but I think you are right that there are two cosine terms in rendering equation. The first which is visible in equation compensates for the weakening of irradiance on the receiver patch, and the second cosine implicit in radiance definition corresponds to the radiance of the source patch subtended foreshortened surface area. In path tracing this radiance (Li) either comes from a direct light with a known radiance value or an indirect which is unknown and will be solved recursively. But if you were to calculate the source radiance you need to multiply both terms too.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pnJKQ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VdqDS.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/X7zm9.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZHsS8.png&#xD;&#xA;  [5]: https://books.google.co.uk/books?id=UmzsCAAAQBAJ&amp;dq=machine%20vision&amp;q=confusing%20to%20novice#v=onepage&amp;q&amp;f=false" ContentLicense="CC BY-SA 4.0" />
  <row Id="24447" PostHistoryTypeId="2" PostId="8987" RevisionGUID="137fc4b3-0abb-4a9f-8ad2-aca8696772ac" CreationDate="2019-07-09T09:05:12.937" UserId="10125" Text="After coming back to the problem now with a fresh pair of eyes, I have managed to find my mistake.&#xD;&#xA;&#xD;&#xA;## Ad Question 1&#xD;&#xA;&#xD;&#xA;Yes, the formula is correct. The problem is hidden in the tangent ![X](https://chart.googleapis.com/chart?cht=tx&amp;chl=X) and bi-tangent ![Y](https://chart.googleapis.com/chart?cht=tx&amp;chl=Y). When performing normal mapping, the tangent frame has to be **perpendicular** to the mapped normal, otherwise the term &#xD;&#xA;![tangent-halfway dot][1] will not carry any information about the normal mapping.&#xD;&#xA;&#xD;&#xA;Another issue here might be that once the normal is mapped, the tangent frame is not uniquely determined. Some more info on that can be found here: [http://www.thetenthplanet.de/archives/1180][2]. I have decided to solve this the same way as Blender does (look for `make_orthonormals_tangent()` in their repo) because I need to be compatible with it. Here is my algorithm for that:&#xD;&#xA;&#xD;&#xA;    bitangent_ortho = norm(cross(normal, tangent))&#xD;&#xA;    tangent_ortho = cross(bitangent_ortho, normal)&#xD;&#xA;&#xD;&#xA;(Assuming that the `normal` is mapped and has unit length and the `tangent` was a valid tangent before the normal was mapped.)&#xD;&#xA;&#xD;&#xA;## Ad Question 2&#xD;&#xA;&#xD;&#xA;This was indeed well answered by user [@lightxbulb][3] in a comment to my question. My only problem with the &quot;Physically based shading at Disney&quot; course notes was that the variable symbols weren't very clearly explained. I have since learned that the convention is the following:&#xD;&#xA;&#xD;&#xA; - ![\theta_v](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Ctheta_v) is the angle between the normal and ![v](https://chart.googleapis.com/chart?cht=tx&amp;chl=v) &#xD;&#xA; - ![\phi_v](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Cphi_v) is the azimuthal angle between the tangent and ![v](https://chart.googleapis.com/chart?cht=tx&amp;chl=v)&#xD;&#xA;&#xD;&#xA;## Ad Question 3&#xD;&#xA;&#xD;&#xA;The only pieces of advice that were useful for me here were the following:&#xD;&#xA;&#xD;&#xA; 1. Always come up with the simplest toy examples possible&#xD;&#xA; 2. Verify your assumptions&#xD;&#xA; 3. Visualize everything&#xD;&#xA;&#xD;&#xA;## Conclusion&#xD;&#xA;&#xD;&#xA;I hope this is helpful for somebody else than just me. Good luck implementing BRDFs!&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9Wq9Q.gif&#xD;&#xA;  [2]: http://www.thetenthplanet.de/archives/1180&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/users/10096/lightxbulb" ContentLicense="CC BY-SA 4.0" />
  <row Id="24448" PostHistoryTypeId="2" PostId="8988" RevisionGUID="1395d52c-68e1-4f75-9dfe-ba8ce1579404" CreationDate="2019-07-09T11:57:15.197" UserId="10096" Text="Since you seem to want an explanation in terms of irradiance, consider both the radiance and irradiance definitions:&#xD;&#xA;$$E = \frac{d\Phi}{dA}, \quad  L = \frac{d^2\Phi}{d\omega dA^{\perp}}$$&#xD;&#xA;We can reformulate the radiance definition as:&#xD;&#xA;$$d^2\Phi = L \cos\theta d\omega dA$$&#xD;&#xA;Integrating both sides over the solid angle $d\omega$ (in the sense of Lebesgue-Stieltjes) yields:&#xD;&#xA;$$d\Phi = dA \int_{\Omega}{L\cos\theta d\omega}$$&#xD;&#xA;And thus:&#xD;&#xA;$$E = \frac{d\Phi}{dA} = \int_{\Omega}{L\cos\theta d\omega}$$&#xD;&#xA;So you can think of irradiance as the integral of radiance with respect to the solid angle measure, or vice versa, you can think of radiance as the derivative of irradiance with respect to the solid angle measure. The other answers also provide the link to the rendering equation. So no, you do not have the cosine two times. Though if you were to rewrite the rendering equation in its area formulation you do get another cosine term (which is due to the projection of a differential area patch onto the hemisphere). This uses the relationship:&#xD;&#xA;$$d\omega = \frac{\cos\theta_y}{r^2}dA(y)$$&#xD;&#xA;Then one can rewrite the rendering equation as:&#xD;&#xA;$$L_o(x_0 \rightarrow x_{-1}) = \int_{S}{f(x_1 \rightarrow x_0 \rightarrow x_{-1}) L(x_1 \rightarrow x_0) \cos\theta_{x_0} \frac{\cos\theta_{x_1}}{||x_1-x_0||^2} V(x_0,x_1) \,dA(x_1)}$$&#xD;&#xA;Where the visibility term $V(x_0,x_1)$ appears since it was originally implicit in the solid angle formulation. This is because you cannot get radiance on a straight line between point $x_0$ and $x_1$ if there is an occluder in-between, that's automatically taken care of in the solid angle formulation by using $L_i(x_0,\omega = x_0 \rightarrow x_1)$, which gives us the radiance arriving at $x_0$ from direction $\omega$, note that this considers the first point from which this radiance arrives, and not specifically $x_1$. Formally $L_i(x_0, \omega) = L(r(x_0,\omega), -\omega))$, note the raycasting operator $r$ in which the visibility term is implicitly hidden, since $r(x_0,x_0 \rightarrow x_1) \ne x_1$ if there is an occluder inbetween." ContentLicense="CC BY-SA 4.0" />
  <row Id="24449" PostHistoryTypeId="5" PostId="8984" RevisionGUID="6151ca8c-6e1a-4360-b269-055e81913837" CreationDate="2019-07-09T15:12:21.263" UserId="2479" Comment="fixed incorrect measure type" Text="Your main idea is more or less correct. The cosine hidden in the projected area measure $dA^\perp = dA\cos(θ)$ compensates the weakening of irradiance due to incident angle (the Lambert's cosine law). This makes radiance independent from the incident angle. My guess is that the main motivation was to make it more practical to work with.&#xD;&#xA;&#xD;&#xA;The cosine in the rendering equation comes from the definition of BRDF:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{\mathrm{d}E\left(\omega_{i}\right)} =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{L_{i}\left(\omega_{i}\right)\mathrm{d}\sigma^{\bot}\left(\omega_{i}\right)} =\frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{L_{i}\left(\omega_{i}\right)\cos\theta_{i}\mathrm{d}\omega_{i}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which can be rewritten as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathrm{d}L_{o}\left(\omega_{o}\right)&#xD;&#xA;=f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) L_{i}\left(\omega_{i}\right) \cos\theta_{i} \mathrm{d}\omega_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which can be integrated over the hemisphere the get the radiance reflected in a given direction $\omega_o$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int_\Omega f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) L_{i}\left(\omega_{i}\right) \cos\theta_{i} \mathrm{d}\omega_{i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Voila, the rendering equation!&#xD;&#xA;&#xD;&#xA;**Conclusion:** Althought both cosines come from the same fundamental priciple, they serve different purposes." ContentLicense="CC BY-SA 4.0" />
  <row Id="24450" PostHistoryTypeId="2" PostId="8989" RevisionGUID="ba79bfaf-5fe1-4558-8809-136835e91503" CreationDate="2019-07-09T20:30:45.683" UserId="6046" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. So far I'm getting some results but don't quite understand whether these are the expected images or not. I have extracted the necessary functions for converting &quot;.pvm&quot; file to &quot;.raw&quot; from V^3 package by [Stefan][2]. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I took the &quot;foot&quot; and `lobster` dataset from [here][3]. My rendered images give me,&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Comparing my images with the ones given on the site,&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Instead of mapping the single isovalue to all channels. I used the isovalue for alpha only and used a constant `0.07` for `rgb`. My foot ends up looking as in the below picture. This leads me to believe it's more of a transfer function problem?&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;So are my images wrong or the below images are using some fancy transfer functions? If so, how do you design these transfer functions? I searched the net but found very little information on how to do it.&#xD;&#xA;&#xD;&#xA;The link to the Compute shader is [here][9]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box, just adjusted it so it's in the center. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.&#xD;&#xA;&#xD;&#xA;I'm not posting it here since it's already this big. But if you want I can post it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://sourceforge.net/projects/volren/&#xD;&#xA;  [3]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [4]: https://i.stack.imgur.com/lbGYY.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/eqoJI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Diwng.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/rQ1ds.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/MxDQL.png&#xD;&#xA;  [9]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24451" PostHistoryTypeId="1" PostId="8989" RevisionGUID="ba79bfaf-5fe1-4558-8809-136835e91503" CreationDate="2019-07-09T20:30:45.683" UserId="6046" Text="Volume Rendering - Images not rendered correctly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24452" PostHistoryTypeId="3" PostId="8989" RevisionGUID="ba79bfaf-5fe1-4558-8809-136835e91503" CreationDate="2019-07-09T20:30:45.683" UserId="6046" Text="|raymarching|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24453" PostHistoryTypeId="5" PostId="8989" RevisionGUID="d5ca1456-a161-4250-aaaa-f41f5582634c" CreationDate="2019-07-09T20:35:57.810" UserId="6046" Comment="added 136 characters in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. So far I'm getting some results but don't quite understand whether these are the expected images or not. I have extracted the necessary functions for converting &quot;.pvm&quot; file to &quot;.raw&quot; from V^3 package by [Stefan][2]. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][3]. My renderer give me,&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Comparing my images with the ones given on the site,&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Instead of mapping the single isovalue to all channels. I used the isovalue for alpha only and used a constant `0.07` for `rgb`. My foot ends up looking as in the below picture. This leads me to believe it's more of a transfer function problem?&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;So are my images wrong or the below images are using some fancy transfer functions? If so, how do you design these transfer functions? I searched the net but found very little information on how to do it.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][9]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box, just adjusted it so it's in the center. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;I'm not posting it here since it's already this big. But if you want I can post it. Any help would be greatly appreciated since there isn't much matter on volume rendering and especially transfer functions over the net.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://sourceforge.net/projects/volren/&#xD;&#xA;  [3]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [4]: https://i.stack.imgur.com/lbGYY.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/eqoJI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Diwng.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/rQ1ds.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/MxDQL.png&#xD;&#xA;  [9]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24457" PostHistoryTypeId="2" PostId="8991" RevisionGUID="08f3ea90-1323-40b5-bab7-33dcd12d1136" CreationDate="2019-07-10T03:02:06.040" UserId="10886" Text="Turns out it had to do with the V vector working differently in deferred rendering than it does in forward rendering, something that I overlooked and seems obvious now. Specifically, I passed the view direction calculated in the camera class to the lighting pass fragment shader then negated it like so `vec3 V = normalize(-eye);`. Things seems to be working well now!&#xD;&#xA;&#xD;&#xA;[![Fixed lighting helmet][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YphtI.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24458" PostHistoryTypeId="5" PostId="8989" RevisionGUID="263808ed-324a-4f5d-b573-a09882a55611" CreationDate="2019-07-10T04:40:07.733" UserId="6046" Comment="added 67 characters in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. So far I'm getting some results but don't quite understand whether these are the expected images or not. I have extracted the necessary functions for converting &quot;.pvm&quot; file to &quot;.raw&quot; from V^3 package by [Stefan][2]. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][3]. My renderer give me,&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Comparing my images with the ones given on the site,&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Instead of mapping the single isovalue to all channels. I used the isovalue for alpha only and used a constant `0.07` for `rgb`. My foot ends up looking as in the below picture. This leads me to believe it's more of a transfer function problem?&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;So are my images wrong or the below images are using some fancy transfer functions? If so, how do you design these transfer functions? I searched the net but found very little information on how to do it.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][9]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, just adjusted it so it's in the center and accounted for the aspect ratio. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;I'm not posting it here since it's already this big. But if you want I can post it. Any help would be greatly appreciated since there isn't much matter on volume rendering and especially transfer functions over the net.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://sourceforge.net/projects/volren/&#xD;&#xA;  [3]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [4]: https://i.stack.imgur.com/lbGYY.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/eqoJI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Diwng.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/rQ1ds.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/MxDQL.png&#xD;&#xA;  [9]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24460" PostHistoryTypeId="5" PostId="3964" RevisionGUID="07af5091-13fa-4c2d-aab7-86be99024634" CreationDate="2019-07-10T08:15:33.580" UserId="4793" Comment="Fixed typos" Text="I use Phong shading as my lighting model. Nevertheless, the specular shading produces gradients in the light cone:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Hopefully you can see the gradient starting from the lower left corner expanding along the cuboid.&#xD;&#xA;&#xD;&#xA;Here is the shader code that produces this specular light:&#xD;&#xA;&#xD;&#xA;    vec3 viewDir = normalize(-FragPos);&#xD;&#xA;    vec3 lightDir = normalize(-light.direction);&#xD;&#xA;    vec3 reflectDir = reflect(-lightDir, normal);&#xD;&#xA;	float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);&#xD;&#xA;&#xD;&#xA;By the way, I'm doing my lighting calculations in view-space. &#xD;&#xA;&#xD;&#xA;Is there any chance to make the lighting smoother?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RknYH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24461" PostHistoryTypeId="4" PostId="3964" RevisionGUID="07af5091-13fa-4c2d-aab7-86be99024634" CreationDate="2019-07-10T08:15:33.580" UserId="4793" Comment="Fixed typos" Text="OpenGL specular shading - Gradient banding issues" ContentLicense="CC BY-SA 4.0" />
  <row Id="24462" PostHistoryTypeId="24" PostId="3964" RevisionGUID="07af5091-13fa-4c2d-aab7-86be99024634" CreationDate="2019-07-10T08:15:33.580" Comment="Proposed by 4793 approved by 6, 209 edit id of 478" ContentLicense="CC BY-SA 4.0" />
  <row Id="24463" PostHistoryTypeId="2" PostId="8992" RevisionGUID="e27e988a-63e7-4ed0-ba70-a5c22ea0d2cd" CreationDate="2019-07-10T11:50:02.873" UserId="6647" Text="I have a mesh that records some integer information for its vertices. I expect this information to be quite sparse, with possible large variations.&#xD;&#xA;&#xD;&#xA;How could I visualize this on a colorscheme (e.g. green to red)?&#xD;&#xA;&#xD;&#xA;I can set the colors of the vertices according to their value and simply linearly interpolate the color along the face, but it might be the case where I have one point of large value in a dense region of the mesh, and that won't get rendered (or it would be a very small red point in a green region). &#xD;&#xA;&#xD;&#xA;I was thinking of a Gaussian smoothing over those values, but no idea how to apply this on a mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="24464" PostHistoryTypeId="1" PostId="8992" RevisionGUID="e27e988a-63e7-4ed0-ba70-a5c22ea0d2cd" CreationDate="2019-07-10T11:50:02.873" UserId="6647" Text="Visualize a mesh with sparse vertex counts" ContentLicense="CC BY-SA 4.0" />
  <row Id="24465" PostHistoryTypeId="3" PostId="8992" RevisionGUID="e27e988a-63e7-4ed0-ba70-a5c22ea0d2cd" CreationDate="2019-07-10T11:50:02.873" UserId="6647" Text="|texture|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24466" PostHistoryTypeId="2" PostId="8993" RevisionGUID="ec6b66b8-4f1f-4a67-a329-9178538935dc" CreationDate="2019-07-10T20:21:53.843" UserId="2960" Text="I'm trying to implement a spectral path tracer and comparing results from my program with renders of the same scene done with `pbrt` and `mitsuba`. The scene is just some spheres in a box with one point light. All the surfaces have simple Lambertian BRDFs. The light has &quot;uniform&quot; spectral intensity (i.e., every wavelength has same power as others), same holds for surface reflectances. When I try to render the [scene][1] in `mitsuba` I get a &quot;grayscale&quot; image, as expected:&#xD;&#xA;&#xD;&#xA;[![Mitsuba render][2]][2]&#xD;&#xA;&#xD;&#xA;However, if `pbrt`'s used to render the [same scene][3], result image has a reddish tint:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;With my program I get similar result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;After some digging through source code, I believe difference lies in `mitsuba` [multiplying][6] spectral intensities by D65 spectrum.&#xD;&#xA;&#xD;&#xA;Is it reasonable to expect the image of the described scene to be &quot;in grayscale&quot;? If so, do light intensity spectra indeed are required to be multiplied by D65 spectrum? Again, if so, why `pbrt` doesn't do it?&#xD;&#xA;&#xD;&#xA;  [1]: https://gist.github.com/dmikis/3c66718d27fa672219d618a96c95f7ff#file-mitsuba-xml&#xD;&#xA;  [2]: https://i.stack.imgur.com/xxBsY.png&#xD;&#xA;  [3]: https://gist.github.com/dmikis/3c66718d27fa672219d618a96c95f7ff#file-pbrt-pbrt&#xD;&#xA;  [4]: https://i.stack.imgur.com/XhqUA.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/u8SyF.png&#xD;&#xA;  [6]: https://github.com/mitsuba-renderer/mitsuba/blob/master/src/librender/scenehandler.cpp#L592" ContentLicense="CC BY-SA 4.0" />
  <row Id="24467" PostHistoryTypeId="1" PostId="8993" RevisionGUID="ec6b66b8-4f1f-4a67-a329-9178538935dc" CreationDate="2019-07-10T20:21:53.843" UserId="2960" Text="Reddish tint with spectral renderer" ContentLicense="CC BY-SA 4.0" />
  <row Id="24468" PostHistoryTypeId="3" PostId="8993" RevisionGUID="ec6b66b8-4f1f-4a67-a329-9178538935dc" CreationDate="2019-07-10T20:21:53.843" UserId="2960" Text="|raytracing|color|spectral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24469" PostHistoryTypeId="2" PostId="8994" RevisionGUID="9c65a442-68ef-4463-a68e-50ae747b2f9e" CreationDate="2019-07-10T20:23:22.760" UserId="10903" Text="The CT5 was designed before 1981. I started working at E&amp;S in May 1981. The CT5 was fully designed by then and 3 had been built. All 3 were still at E&amp;S and hadn't shipped yet when I started. Two of them were on the test floor and the third was the engineering prototype that was later sold. The prototype was in the &quot;snake room&quot;, so called because of all the black power cords hanging from the ceiling. I also remember seeing the prototype in the snake room when I made a recruiting visit to E&amp;S in early January 1981. So, the prototype, at least, was up and running before 1981.&#xD;&#xA;&#xD;&#xA;The first two CT5 systems were CH-46 helicopter simulators and the first one went to Cherry Point NAS. I don't think it shipped in 1981 as I remember it being there on the test floor for about a year after I joined the company. So, it probably shipped in 1982. As I recall, the two systems built after the CH-46 systems were AV8B Harrier jet simulators." ContentLicense="CC BY-SA 4.0" />
  <row Id="24470" PostHistoryTypeId="50" PostId="8886" RevisionGUID="1d197cc7-50ef-408d-8438-64188fa60f25" CreationDate="2019-07-11T13:01:25.837" UserId="-1" />
  <row Id="24471" PostHistoryTypeId="2" PostId="8995" RevisionGUID="bef71569-7477-4eaa-b99d-078f403369a1" CreationDate="2019-07-11T13:40:41.843" UserId="10806" Text="Look at this vertex shader:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;&#xD;&#xA;layout(location = 0) in vec3 inPos;&#xD;&#xA;&#xD;&#xA;out gl_PerVertex {&#xD;&#xA;    vec4 gl_Position;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout (std430, binding = 1) buffer depth_range_t {&#xD;&#xA;    int min;&#xD;&#xA;    int max;&#xD;&#xA;} depth_range;&#xD;&#xA;&#xD;&#xA;vec3 project(vec4 pt)&#xD;&#xA;{&#xD;&#xA;// somehow projects to (camera_x, camera_y, distance_to_camera)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    vec4 translated = ubo.worldToCamera * vec4(inPos.xyz, 1.0);&#xD;&#xA;    vec3 projected = project(vec4(inPos.xyz, 1.0));&#xD;&#xA;&#xD;&#xA;    atomicMin(depth_range.min, depth_cast(projected.z);&#xD;&#xA;    atomicMax(depth_range.max, depth_cast(projected.z);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As you see, it uses two atomic operations, which occur to be embarrassingly slow. Using compute shaders I'd be able to utilize hierarchical architecture of a GPU by atomic operations on shared memory, but this in turn, as I see, would introduce hassle with separate writable buffer for vertices.&#xD;&#xA;&#xD;&#xA;**Is there any way to leverage device caches directly in vertex shader?**&#xD;&#xA;&#xD;&#xA;I'm especially interested to find if it's possible using Vulkan API (maybe, SPIR-V tricks?), but would also appreciate any information about possible solutions using other popluar graphics API. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24472" PostHistoryTypeId="1" PostId="8995" RevisionGUID="bef71569-7477-4eaa-b99d-078f403369a1" CreationDate="2019-07-11T13:40:41.843" UserId="10806" Text="Communication between vertex shader executions" ContentLicense="CC BY-SA 4.0" />
  <row Id="24473" PostHistoryTypeId="3" PostId="8995" RevisionGUID="bef71569-7477-4eaa-b99d-078f403369a1" CreationDate="2019-07-11T13:40:41.843" UserId="10806" Text="|glsl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24474" PostHistoryTypeId="2" PostId="8996" RevisionGUID="859fb8cb-0703-4b48-86a0-6b6aafd1c449" CreationDate="2019-07-11T13:53:47.120" UserId="10906" Text="I'm learning light probes used for dynamic global illumination. I have a question regarding the placement of light probes, as based on most of the pictures I have seen, they seem to be placed uniformly in a grid. Is that a reasonable way for placement? I feel that more should be placed in corners than in the middle of an area.&#xD;&#xA;&#xD;&#xA;is there any research on light probe placement that minimize the overall data needed for rendering?&#xD;&#xA;&#xD;&#xA;this GDC talk http://twvideo01.ubm-us.net/o1/vault/gdc2012/slides/Programming%20Track/Cupisz_Robert_Light_Probe_Interpolation.pdf&#xD;&#xA;&#xD;&#xA;mentioned irregular placement on tetrahedrons and how to do interpolation. but it doesn't seem to say much about placement itself.&#xD;&#xA;&#xD;&#xA;this paper http://melancholytree.com/thesis.pdf mentioned that only one probe is needed in a convex shape, but I don't seem to see people do this, is it because this is only for static global illumination without moving objects?&#xD;&#xA;&#xD;&#xA;what's the the latest development in light probe placement?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24475" PostHistoryTypeId="1" PostId="8996" RevisionGUID="859fb8cb-0703-4b48-86a0-6b6aafd1c449" CreationDate="2019-07-11T13:53:47.120" UserId="10906" Text="light probe (for global illumination) placement techniques?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24476" PostHistoryTypeId="3" PostId="8996" RevisionGUID="859fb8cb-0703-4b48-86a0-6b6aafd1c449" CreationDate="2019-07-11T13:53:47.120" UserId="10906" Text="|rendering|real-time|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24477" PostHistoryTypeId="5" PostId="8995" RevisionGUID="7658d90b-a7f9-424a-9e13-87f1b57e1fdb" CreationDate="2019-07-11T15:13:30.213" UserId="10806" Comment="deleted 12 characters in body" Text="Look at this vertex shader:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;&#xD;&#xA;layout(location = 0) in vec3 inPos;&#xD;&#xA;&#xD;&#xA;out gl_PerVertex {&#xD;&#xA;    vec4 gl_Position;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout (std430, binding = 1) buffer depth_range_t {&#xD;&#xA;    int min;&#xD;&#xA;    int max;&#xD;&#xA;} depth_range;&#xD;&#xA;&#xD;&#xA;vec3 project(vec4 pt)&#xD;&#xA;{&#xD;&#xA;// somehow projects to (camera_x, camera_y, distance_to_camera)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    vec4 translated = ubo.worldToCamera * vec4(inPos.xyz, 1.0);&#xD;&#xA;    vec3 projected = project(vec4(inPos.xyz, 1.0));&#xD;&#xA;&#xD;&#xA;    atomicMin(depth_range.min, int(projected.z));&#xD;&#xA;    atomicMax(depth_range.max, int(projected.z));&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As you see, it uses two atomic operations, which occur to be embarrassingly slow. Using compute shaders I'd be able to utilize hierarchical architecture of a GPU by atomic operations on shared memory, but this in turn, as I see, would introduce hassle with separate writable buffer for vertices.&#xD;&#xA;&#xD;&#xA;**Is there any way to leverage device caches directly in vertex shader?**&#xD;&#xA;&#xD;&#xA;I'm especially interested to find if it's possible using Vulkan API (maybe, SPIR-V tricks?), but would also appreciate any information about possible solutions using other popluar graphics API. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24479" PostHistoryTypeId="50" PostId="8730" RevisionGUID="117ae45a-bd0c-4546-bc37-f52a2adb7ff9" CreationDate="2019-07-12T13:01:10.113" UserId="-1" />
  <row Id="24480" PostHistoryTypeId="2" PostId="8997" RevisionGUID="5a6f6577-0325-4c5f-863b-e9fe151e41f5" CreationDate="2019-07-12T14:03:18.680" UserId="2041" Text="I have an experimental workflow that involves very finely subdivided meshes, above the 2 GB limit where signed 32-bit integers stop working, which often causes problems for various tools. I would need my users to be able to handle such mesh files. How big a problem will this be? Do commonplace mesh editing and DCC tools (commercial and free) have trouble with files with more than 2 GB size, or more than 2^31 vertices? I'd imagine at least movie industry tools would be fine with this kind of size, because they store a lot of intermediate files that may have been generated from displacement maps or by marching-cubes on volumes.&#xD;&#xA;&#xD;&#xA;I'm not interested in problems caused by 32-bit OSes or 32-bit installs of tools: my product only supports 64-bit, so it's OK for me to just tell people to use the 64-bit versions of other tools if that's sufficient. But even with this advice, is my large-file-based workflow a non-starter (because users will keep having problems), is it a manageable problem, or is it not a problem at all?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24481" PostHistoryTypeId="1" PostId="8997" RevisionGUID="5a6f6577-0325-4c5f-863b-e9fe151e41f5" CreationDate="2019-07-12T14:03:18.680" UserId="2041" Text="What expectations should I have of large (&gt; 2 GB) file support in common mesh workflow tools?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24482" PostHistoryTypeId="3" PostId="8997" RevisionGUID="5a6f6577-0325-4c5f-863b-e9fe151e41f5" CreationDate="2019-07-12T14:03:18.680" UserId="2041" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24483" PostHistoryTypeId="5" PostId="8985" RevisionGUID="5af56f40-e9c8-49a5-ba80-d37919f24d38" CreationDate="2019-07-12T20:07:53.267" UserId="9500" Comment="reworded, and added &quot;compute shaders&quot; tentative explanation" Text="So, I'll start by saying I'm not a driver developer, but I have read many comments and docs in this regard. &#xD;&#xA;&#xD;&#xA;First of all, we can see how Khronos's own [slides][1] on presentation day were mentioning some rather vague &quot;any OpenGL ES 3.1 GPU&quot; (or desktop 4.X). This means [something][2] added around that mark would be the secret to it. Compute shaders are definitively [at least one of] the things, being confirmed [here][3], by an [Intel developer][4], and in [the spec][5] with no possible unsupported value for `MaxComputeWorkGroupSize` and this likely smoking gun: &#xD;&#xA;&gt; If an implementation exposes any queue family that supports graphics&#xD;&#xA;&gt; operations, at least one queue family of at least one physical device&#xD;&#xA;&gt; exposed by the implementation **must** support both graphics and&#xD;&#xA;&gt; compute operations.&#xD;&#xA;&#xD;&#xA;In addition to that though, it could *also* be there are other mandatory capabilities (such as indirect draws or load&amp;store, mentioned in the comments above too). But I have some slight difficulty interpreting the document. With the exception of [robustBufferAccess][6], it seems like just about anything else big you could imagine is optional (from anisotropic filter, to geometry and tessellation shaders, to any special number format other than good old float32)&#xD;&#xA;&#xD;&#xA;This being the most hypothetically simple case then, doesn't mean it's all fine and dandy. Not having [virtual memory][7] will make your life a hell for example, and lack of other [architectural features][8] may basically nullify whatever theoretical advantage in speed the API has. &#xD;&#xA;&#xD;&#xA;These links should also answer your wonders about ATi cards. Likely same story for NVidia then (aside of perhaps some microbenchmarks, I'm not sure how much *really* workable [Fermi's][9] 2-years-delayed bare-bones DX12 support eventually is). As for Intel, I don't know what you are talking about, Gen8 is supported since [Day1][10] and in fact even [Gen7][11] *shakily* works now.&#xD;&#xA;&#xD;&#xA;Going even further back, I guess if any the question becomes &quot;what's so special about compute shaders again&quot;. &#xD;&#xA;&#xD;&#xA;And, well, the thing isn't probably the very specific [feature][12] itself (because it's [not that][13] you couldn't already do some sort of general purpose calculation even before the unified shader model), but more like the whole general GPU architecture needed to support it. &#xD;&#xA;&#xD;&#xA;Before DX11 raised [the bar][14] for example, just think that you [couldn't][15] even run more than a single &quot;task&quot; on a Tesla GPU, without having to call a context switch (with comparable limitations also likely existing for TeraScale 1 and Gen6). And may God save us from when pixel and vertex units were separated hardware. &#xD;&#xA;&#xD;&#xA;fun fact p.s.: it turns out that if you are a low-end [kind-of-modern][16] mobile gpu (rather than an old desktop card from a time when certain concepts hadn't even been invented yet), engineers can cut you down so much that even if you just sport D3D 9_3 feature level that's still potentially [enough][17] to support Vulkan.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/assets/uploads/developers/library/overview/Vk_201602_Overview_Feb16.pdf#page=13&#xD;&#xA;  [2]: https://www.anandtech.com/show/7867/khronos-announces-opengl-es-31&#xD;&#xA;  [3]: https://pcper.com/2015/03/gdc-15-what-is-vulkan-glnext-spir-v-and-opencl-2-1/&#xD;&#xA;  [4]: https://youtu.be/2ryvYS47V0E?t=3176&#xD;&#xA;  [5]: https://www.khronos.org/registry/vulkan/specs/1.1/pdf/vkspec.pdf&#xD;&#xA;  [6]: https://www.khronos.org/registry/vulkan/specs/1.0/html/chap30.html#features-requirements&#xD;&#xA;  [7]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/open-source-amd-linux/1004192-r600-gallium3d-now-effectively-at-opengl-4-4-a-nudge-away-from-gl-4-5/page2#post1004523&#xD;&#xA;  [8]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/vulkan/845690-amd-s-vulkan-driver-will-only-work-with-the-amdgpu-kernel-driver/page3#post845731&#xD;&#xA;  [9]: https://techreport.com/news/32191/nvidia-finally-lets-fermi-gpu-owners-enjoy-directx-12/&#xD;&#xA;  [10]: https://01.org/linuxgraphics/blogs/jekstrand/2016/open-source-vulkan-drivers-intel-hardware&#xD;&#xA;  [11]: https://stackoverflow.com/questions/41497142/can-i-install-a-vulkan-driver-on-my-3rd-gen-intel-ivy-bridge-integrated-gpu-on-u&#xD;&#xA;  [12]: https://www.anandtech.com/show/2716/5&#xD;&#xA;  [13]: https://en.wikipedia.org/wiki/BrookGPU&#xD;&#xA;  [14]: https://stackoverflow.com/questions/3332782/can-directcompute-really-be-used-on-a-dx10-1-gpu&#xD;&#xA;  [15]: https://www.anandtech.com/show/2977/nvidia-s-geforce-gtx-480-and-gtx-470-6-months-late-was-it-worth-the-wait-/3&#xD;&#xA;  [16]: https://www.anandtech.com/show/8649/arm-announces-mali-800-series-gpus-t860-t830-t820&#xD;&#xA;  [17]: https://developer.arm.com/solutions/graphics/resources/faqs#vulkan_which" ContentLicense="CC BY-SA 4.0" />
  <row Id="24484" PostHistoryTypeId="2" PostId="8998" RevisionGUID="350e8848-e8d2-49e2-becf-51fe769b04f0" CreationDate="2019-07-13T10:12:35.283" UserId="3123" Text="After some research i think i have final answer.&#xD;&#xA;&#xD;&#xA;General fog equation looks something like this:&#xD;&#xA;$$ L(t)=L_p\color{red}{T(t)} + \int_0^t\color{blue}{T(x)}\color{green}{\sigma(x)L(x)}dx $$&#xD;&#xA;Transmittance defined as:&#xD;&#xA;$$T(x)=e^{-\int_0^x\sigma(x) dx}$$&#xD;&#xA;With const $\sigma$ become&#xD;&#xA;$$T(x)=e^{-\sigma x}$$&#xD;&#xA;&#xD;&#xA;So color that will be visible is:&#xD;&#xA;&#xD;&#xA;Visible percent $\color{red}{T(t)}$ of pixel color $L_p$, plus scattering probability $\color{green}{\sigma(x)L(x)}$ multiplied by visible percent $\color{blue}{T(x)}$ at distance $x$ integrated on ray.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;With two or more fogs we get multiple scatterings so equations become:&#xD;&#xA;$$T(x)=e^{-\int_0^x\sum_0^n\sigma_i(x)dx} = e^{-x\sum_0^n\sigma_i}$$&#xD;&#xA;$$L(t)=L_p\color{red}{T(t)} + \int_0^t\color{blue}{T(x)}\sum_0^n\color{green}{\sigma_i(x)L_i(x)}dx=L_p\color{red}{T(t)} + \sum_0^n\color{green}{\sigma_iL_i}\int_0^t\color{blue}{T(x)}dx$$&#xD;&#xA;&#xD;&#xA;All assuming that $\sigma_i$ and fog color $L(x)$ are constant across ray.&#xD;&#xA;&#xD;&#xA;The final equation for two fogs, after resolving $\int_0^t\color{blue}{T(x)}dx$ will become.&#xD;&#xA;$$L(x)=L_p\color{red}{T(t)} + (\color{green}{\sigma_0L_0 + \sigma_1L_1})\color{blue}{\frac{1-T(t)}{\sigma_0+\sigma_1}}$$&#xD;&#xA;&#xD;&#xA;It's the same equation as in [Deep Compositing][2]. After combining it with Lie group/algebra it is possible to integrate only parts of fogs.&#xD;&#xA;&#xD;&#xA;Of course this integration isn't 100% correct if you have more complicated fog with not constant density etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dgnqR.jpg&#xD;&#xA;  [2]: https://graphics.pixar.com/library/DeepCompositing/paper.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24485" PostHistoryTypeId="2" PostId="8999" RevisionGUID="8c8505d7-07d3-4743-8774-c5541b60ceee" CreationDate="2019-07-13T11:50:45.990" UserId="4958" Text="Looking for answer for similar question, I found that work: http://www.cse.chalmers.se/~uffe/xjobb/bowald_final_master_thesis_v2.pdf&#xD;&#xA;&#xD;&#xA;It is based on automatic grid placement which depends on scene voxelization. Inspired by this I developed similar technique:&#xD;&#xA;&#xD;&#xA; - First scene is voxelized with small voxel size (binary voxelization for memory saving)&#xD;&#xA; - Result is downsampled to desired grid size (size of each cube with eight probes on each corner)&#xD;&#xA; - Based on result - data structures are prepared&#xD;&#xA; - Empty areas are optionally computed - cubes size can be bigger to save memory of volumes and probes buffers but it must be always multiplication of smallest cube size to fit in the grid&#xD;&#xA; - Lighting for each probe is precomputed&#xD;&#xA;&#xD;&#xA;Data structures are:&#xD;&#xA;&#xD;&#xA; - Volume map buffer - mapping world position to volume index&#xD;&#xA; - Volumes buffer - each is array of eight probe indices&#xD;&#xA; - Probes buffer - SH data of each probe&#xD;&#xA;&#xD;&#xA;This way performance is constant, fast and independent of quality (size of cube) unlike in tetrahedra grid searching algorithm.&#xD;&#xA;&#xD;&#xA;However I don't know if there is more recent advancement in that field. You might check http://jcgt.org if there are any new research papers. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24486" PostHistoryTypeId="5" PostId="8991" RevisionGUID="d50382fa-a1ba-41ca-8bbd-a9cf24a049ab" CreationDate="2019-07-13T13:22:36.377" UserId="10886" Comment="added 21 characters in body" Text="Turns out it had to do with the V vector working differently in deferred rendering than it does in forward rendering, something that I overlooked and seems obvious now. Specifically, I passed the view direction calculated in the camera class to the lighting pass fragment shader then negated it like so `vec3 V = normalize(-(cameraPosition - v_pos));`. Things seems to be working well now!&#xD;&#xA;&#xD;&#xA;[![Fixed lighting helmet][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YphtI.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24491" PostHistoryTypeId="2" PostId="9001" RevisionGUID="3406a05d-d322-4126-9b8c-946e70024824" CreationDate="2019-07-14T17:06:42.633" UserId="10913" Text="I am trying to implement a custom add-on for Mitsuba, but when I use the Heightfield I have defined in another function call(WaveBrdfAccel) in main.cpp it compiles without any problems but when I try to render the scene I get an error that says:&#xD;&#xA; **undefined symbol: _ZTVN7mitsuba11HeightfieldE**&#xD;&#xA;&#xD;&#xA;Is there something special I need to do to implement this properly in Mitsuba's frameworks?&#xD;&#xA;&#xD;&#xA;I am trying this on Mitsuba version 0.5.0 (Linux, 64 bit).&#xD;&#xA;If I remove the heightfield parameter from the WaveBrdfAccel declaration then This error does not occur which leads me to believe​ there is something wrong in the way I am calling it but I cannot figure it out.  &#xD;&#xA;&#xD;&#xA;Here is my main.cpp file :&#xD;&#xA;```c++&#xD;&#xA;GPTWorkResultTest *spec;&#xD;&#xA;    			spec-&gt;SpectrumInit(); &#xD;&#xA;&#xD;&#xA;			GPTWorkResultEXR heightfieldImage(heightfieldFilename);&#xD;&#xA;			Heightfield heightfield(&amp;heightfieldImage, texelWidth, vertScale);&#xD;&#xA;			Query query;&#xD;&#xA;    			query.mu_p = Vector2(mu_x, mu_y);&#xD;&#xA;    			query.sigma_p = sigma_p;&#xD;&#xA;    			query.lambda = lambda;&#xD;&#xA;&#xD;&#xA;			WaveBrdfAccel waveBrdfAccel(&amp;heightfield, diffModel); &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;the Heightfield and WaveBrdfAccel class both in waveBrdf.h:&#xD;&#xA;```c++&#xD;&#xA;class Heightfield {&#xD;&#xA;public:&#xD;&#xA;     explicit Heightfield() {}&#xD;&#xA;     Heightfield(GPTWorkResultEXR *heightfieldImage, Float texelWidth = 1.0, Float vertScale = 1.0)&#xD;&#xA;        : mHeightfieldImage(heightfieldImage), mTexelWidth(texelWidth), mVertScale(vertScale) {}&#xD;&#xA;    GaborKernel g(int i, int j, Float F, Float lambda);&#xD;&#xA;&#xD;&#xA;    Vector2 n(Float i, Float j);&#xD;&#xA;public:&#xD;&#xA;    GPTWorkResultEXR *mHeightfieldImage;&#xD;&#xA;    Float mTexelWidth;      // in microns.&#xD;&#xA;    Float mVertScale;&#xD;&#xA;	MTS_DECLARE_CLASS()&#xD;&#xA;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;class WaveBrdfAccel {&#xD;&#xA;public:&#xD;&#xA;  &#xD;&#xA;explicit WaveBrdfAccel(Heightfield *heightfield, string method);&#xD;&#xA;&#xD;&#xA; comp queryIntegral(const Query &amp;query, int layer, int xIndex, int yIndex);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;MTS_DECLARE_CLASS()&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and finally the inclusion in waveBrdf.cpp:&#xD;&#xA;```c++&#xD;&#xA;WaveBrdfAccel::WaveBrdfAccel(Heightfield *heightfield, string method) {&#xD;&#xA;cout &lt;&lt; &quot;IT IS ACTUALLY running wave&quot; &lt;&lt; endl;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;MTS_IMPLEMENT_CLASS(WaveBrdfAccel, false, WorkResult)&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="24492" PostHistoryTypeId="1" PostId="9001" RevisionGUID="3406a05d-d322-4126-9b8c-946e70024824" CreationDate="2019-07-14T17:06:42.633" UserId="10913" Text="Mitsuba builds targets with scons but throws &quot;undefined symbol&quot; error when trying to render scene" ContentLicense="CC BY-SA 4.0" />
  <row Id="24493" PostHistoryTypeId="3" PostId="9001" RevisionGUID="3406a05d-d322-4126-9b8c-946e70024824" CreationDate="2019-07-14T17:06:42.633" UserId="10913" Text="|rendering|c++|microfacet|height-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24494" PostHistoryTypeId="2" PostId="9002" RevisionGUID="686a96a7-2285-4db4-b5ad-22fea84f0a02" CreationDate="2019-07-14T22:57:06.833" UserId="10912" Text="I have written a really basic ray tracer. It generates primary rays and sets the colour of the pixel to the colour of the object that I have set myself. The code for which can be seen below.&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;from PIL import Image, ImageDraw&#xD;&#xA;from Sphere import Sphere&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;imgx = 300&#xD;&#xA;imgy = 300&#xD;&#xA;&#xD;&#xA;img = Image.new('RGB', (imgx, imgy), color = 'black')&#xD;&#xA;pixelMap = img.load()&#xD;&#xA;&#xD;&#xA;#Place a Sphere in centre, distance 10 away.&#xD;&#xA;#Sphere has a constructor (centre, colour, radius)&#xD;&#xA;sphere1 = Sphere(np.array([0,0,-1]), (255, 255, 255), 100)&#xD;&#xA;#sphere2 = Sphere(np.array([300,0,-1]), (255, 0, 0), 100)&#xD;&#xA;&#xD;&#xA;objects = [sphere1]&#xD;&#xA;&#xD;&#xA;for i in range(img.size[0]):&#xD;&#xA;	for j in range(img.size[1]):&#xD;&#xA;&#xD;&#xA;		u = -imgx/2 + (imgx)*(i+0.5)/imgx&#xD;&#xA;		v = -imgy/2 + (imgy)*(j+0.5)/imgy&#xD;&#xA;&#xD;&#xA;		rayDirection = -1*np.array([0,0,1]) + u*np.array([1,0,0]) + v*np.array([0,1,0])&#xD;&#xA;		rayOrigin = np.array([0,0,0])&#xD;&#xA;		#p(t) = rayorigin + t*raydirect&#xD;&#xA;		&#xD;&#xA;		#Sphere intersection&#xD;&#xA;		for obj in objects:		&#xD;&#xA;			a = np.dot(rayDirection, rayDirection)&#xD;&#xA;			b = np.dot(2*rayDirection, (rayOrigin - obj.centre))&#xD;&#xA;			c = np.dot((rayOrigin - obj.centre), (rayOrigin - obj.centre)) - obj.radius**2&#xD;&#xA;&#xD;&#xA;			eminc = rayOrigin - obj.centre&#xD;&#xA;&#xD;&#xA;			discrim = (np.dot(rayDirection, eminc))**2 - ((np.dot(rayDirection, rayDirection))*(np.dot(eminc, eminc))-obj.radius**2)&#xD;&#xA;			if(discrim &gt;= 0):&#xD;&#xA;				print(&quot;intersect&quot;)&#xD;&#xA;				pixelMap[i,j] = obj.colour&#xD;&#xA;			else:&#xD;&#xA;				pixelMap[i,j] = (0, 0,0)&#xD;&#xA;&#xD;&#xA;img.save('output.png')&#xD;&#xA;```&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It works in the sense that when I run the code, I get an image of a white circle. My issue arises when I change the centre of the sphere. Instead of shifting to the left, right, up or down. I get a skewed image. Seen below when I set the Sphere to have centre `np.array([3,0,-1])`.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I believe the problem may be to do with the translation between world co-ordinates and camera co-ordinates? However, I am not sure what transformation matrix to use or how to use it. For what it's worth, my code takes ideas from Fundamentals of Computer Graphics by Pete Shirley and Steve Marschner.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cDdocs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KqsPls.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24495" PostHistoryTypeId="1" PostId="9002" RevisionGUID="686a96a7-2285-4db4-b5ad-22fea84f0a02" CreationDate="2019-07-14T22:57:06.833" UserId="10912" Text="Moving a sphere in a basic ray tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="24496" PostHistoryTypeId="3" PostId="9002" RevisionGUID="686a96a7-2285-4db4-b5ad-22fea84f0a02" CreationDate="2019-07-14T22:57:06.833" UserId="10912" Text="|raytracing|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24500" PostHistoryTypeId="5" PostId="4824" RevisionGUID="b67738a7-3e65-430a-b76b-292a76ef5d72" CreationDate="2019-07-15T07:53:53.047" UserId="5778" Comment="broken image fixed (click 'rendered output' or 'side-by-side' to see the difference; image retrieved via Wayback Machine); for more info, see https://gist.github.com/Glorfindel83/9d954d34385d2ac2597bbe864466259f" Text="When I download this image:&#xD;&#xA;&#xD;&#xA;[![https://www.ucn.edu.ni/media/2016/03/graduados-ucn-nicaragua.jpg][1]][1]  &#xA;&lt;sub&gt;(source: [ucn.edu.ni](https://www.ucn.edu.ni/media/2016/03/graduados-ucn-nicaragua.jpg))&lt;/sub&gt;  &#xA; &#xD;&#xA;&#xD;&#xA;then its total size is 341,0 kB.&#xD;&#xA;&#xD;&#xA;The image has a width of 2880 pixels and height of 1100 pixel and 1 X/Y resolution pixel/in.&#xD;&#xA;&#xD;&#xA;I opened the image with gimp and pressed **scale image** and reduced the width to 1920px and auto adjusted height of 733px, and keeped the resolution as it is and used the interpolation cubic. If I now export this as a jpg with 90% quality, then the image size is 546 kB! &#xD;&#xA;&#xD;&#xA;How is that possible and how can I avoid that?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zjaAF.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24501" PostHistoryTypeId="24" PostId="4824" RevisionGUID="b67738a7-3e65-430a-b76b-292a76ef5d72" CreationDate="2019-07-15T07:53:53.047" Comment="Proposed by 5778 approved by 6, 209 edit id of 479" ContentLicense="CC BY-SA 4.0" />
  <row Id="24502" PostHistoryTypeId="6" PostId="8965" RevisionGUID="d9ede4e9-a31a-41ae-9664-e84576339083" CreationDate="2019-07-15T07:54:11.407" UserId="5778" Comment="tags edited" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24503" PostHistoryTypeId="24" PostId="8965" RevisionGUID="d9ede4e9-a31a-41ae-9664-e84576339083" CreationDate="2019-07-15T07:54:11.407" Comment="Proposed by 5778 approved by 6, 209 edit id of 480" ContentLicense="CC BY-SA 4.0" />
  <row Id="24507" PostHistoryTypeId="5" PostId="8975" RevisionGUID="02bb5cd0-6c54-4448-bd90-0eea92a45c8d" CreationDate="2019-07-15T11:17:17.817" UserId="2479" Comment="Simpified a bit" Text="I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8, the result is very flickery:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Up-scaled back to the original resolution for clarity:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. Am I doing something wrong?&#xD;&#xA;&#xD;&#xA;How does the mipmap generation in DirectX work anyway? Can I control the process beyond the mipmap level count?&#xD;&#xA;&#xD;&#xA;# Technical details&#xD;&#xA;&#xD;&#xA;The sampler:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture:&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The render target view:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The shader resource view:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The down-scaling PS:&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/oweJl.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24508" PostHistoryTypeId="50" PostId="2421" RevisionGUID="b2c2100a-229d-40ed-903e-59ed5c09bb1c" CreationDate="2019-07-15T17:01:15.100" UserId="-1" />
  <row Id="24509" PostHistoryTypeId="5" PostId="8975" RevisionGUID="6e562550-ef88-47c5-952d-c13cb4578330" CreationDate="2019-07-16T09:09:40.430" UserId="2479" Comment="minor polishing" Text="I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8, the result is very flickery:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Up-scaled back to the original resolution for clarity:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. Am I doing something wrong?&#xD;&#xA;&#xD;&#xA;How does the mipmap generation in DirectX work anyway? Can I control the process beyond the mipmap level count?&#xD;&#xA;&#xD;&#xA;# DirectX details&#xD;&#xA;&#xD;&#xA;The sampler:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture:&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The render target view:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The shader resource view:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The down-scaling PS:&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/oweJl.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24510" PostHistoryTypeId="4" PostId="8975" RevisionGUID="6e562550-ef88-47c5-952d-c13cb4578330" CreationDate="2019-07-16T09:09:40.430" UserId="2479" Comment="minor polishing" Text="Downscaling texture via mipmap [DirectX 11]" ContentLicense="CC BY-SA 4.0" />
  <row Id="24511" PostHistoryTypeId="2" PostId="9005" RevisionGUID="a507af29-a165-4fbc-96d3-8431b94c694d" CreationDate="2019-07-16T16:12:57.060" UserDisplayName="user9391" Text="I've been going though Peter Shirley's beginner raytracing books. Upon building the Cornell box and rendering an image, I get a much darker / dimmer image than expected.&#xD;&#xA;&#xD;&#xA;[![Picture one][1]][1]&#xD;&#xA;&#xD;&#xA;The color values are normalized (in the range [0.0f, 1.0f]). The author of the books has stated that for a brighter result, I need to gamma correct the values (calculating the nth root of the color values)The  above image has a gamma correction of 2 (square root). This is the same value that the author uses, but his result is much brighter &#xD;&#xA;&#xD;&#xA;[![picture two][2]][2]&#xD;&#xA;&#xD;&#xA;I tried making the gamma correction larger (increasing n) and after setting n=4 (each color gets set to the (1/4)th exponent), I get this image.&#xD;&#xA;&#xD;&#xA;[![picture three][3]][3]&#xD;&#xA;&#xD;&#xA;There are obvious artifacts, like a lack of highlights near the light, and the over-saturated small number of pixels where a wall is close to the sphere.&#xD;&#xA;&#xD;&#xA;The way a pixel's color is calculated is like this:&#xD;&#xA;&#xD;&#xA;    for(int j = height - 1; j &gt;= 0; j--)&#xD;&#xA;    {&#xD;&#xA;    	for(int i = 0; i &lt; width; i++)&#xD;&#xA;    	{&#xD;&#xA;    		vec3 color(0.0f, 0.0f, 0.0f);&#xD;&#xA;    		for(int s = 0; s &lt; samplesPerPixel; s++)&#xD;&#xA;    		{&#xD;&#xA;    			float u = ((float)i + RandomNumber(0.0f, 1.0f)) / width;&#xD;&#xA;    			float v = ((float)j + RandomNumber(0.0f, 1.0f)) / height;&#xD;&#xA;    &#xD;&#xA;    			ray r = cam.CastRay(u, v);&#xD;&#xA;    			color += Color(r, list, depth);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		color /= (float)samplesPerPixel;&#xD;&#xA;    		color = vec3(pow(color.x, gammaCorrection), pow(color.y, gammaCorrection), pow(color.z, gammaCorrection));&#xD;&#xA;    &#xD;&#xA;    		int ir = Map(0.0f, 1.0f, 0.0f, 255.0f, color.x);&#xD;&#xA;    		int ig = Map(0.0f, 1.0f, 0.0f, 255.0f, color.y);&#xD;&#xA;    		int ib = Map(0.0f, 1.0f, 0.0f, 255.0f, color.z);&#xD;&#xA;    &#xD;&#xA;    		output &lt;&lt; ir &lt;&lt; &quot; &quot; &lt;&lt; ig &lt;&lt; &quot; &quot; &lt;&lt; ib &lt;&lt; &quot;\n&quot;;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the resulting color values for each channel (red, green and blue) is in the range of [0, 255].&#xD;&#xA;&#xD;&#xA;Is there a problem with how I calculate a pixel's color based on all samples? My `color` function is pretty much the same as it is in the book &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec3 Color(const ray&amp; r, HitableList&amp; hitables, int depth)&#xD;&#xA;    {&#xD;&#xA;    	float tmin = 0.001f;&#xD;&#xA;    	float tmax = 10000.0f; &#xD;&#xA;    &#xD;&#xA;    	HitData data;&#xD;&#xA;    &#xD;&#xA;    	// If the ray hit something&#xD;&#xA;    	if(hitables.Hit(r, tmin, tmax, data))&#xD;&#xA;    	{&#xD;&#xA;    		ray scattered;&#xD;&#xA;    		vec3 attenuation;&#xD;&#xA;    &#xD;&#xA;    		// If the material is a light, store its emitted color&#xD;&#xA;    		vec3 emitted = data.mat-&gt;Emitted(data.u, data.v, data.point);&#xD;&#xA;    &#xD;&#xA;    		// If the number of bounces is below 50 and the ray gets scattered into a random direction&#xD;&#xA;    		if(depth &lt; 50 &amp;&amp; data.mat-&gt;Scatter(r, data, attenuation, scattered))&#xD;&#xA;    			return emitted + attenuation * Color(scattered, hitables, depth + 1);&#xD;&#xA;    		else&#xD;&#xA;    			return emitted;&#xD;&#xA;    	} else&#xD;&#xA;    		return vec3(0.0, 0.0f, 0.0f);&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;Has anyone come across a similar issue before?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mP9YW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DbVGq.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/thqjM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24512" PostHistoryTypeId="1" PostId="9005" RevisionGUID="a507af29-a165-4fbc-96d3-8431b94c694d" CreationDate="2019-07-16T16:12:57.060" UserDisplayName="user9391" Text="Offline path tracer produces a darker image than expected" ContentLicense="CC BY-SA 4.0" />
  <row Id="24513" PostHistoryTypeId="3" PostId="9005" RevisionGUID="a507af29-a165-4fbc-96d3-8431b94c694d" CreationDate="2019-07-16T16:12:57.060" UserDisplayName="user9391" Text="|raytracing|pathtracing|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24514" PostHistoryTypeId="5" PostId="8989" RevisionGUID="ed726cde-475b-4b6a-a761-db684f23e172" CreationDate="2019-07-16T17:19:47.457" UserId="6046" Comment="deleted 1 character in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. So far I'm getting some results but don't quite understand whether these are the expected images or not. I have extracted the necessary functions for converting &quot;.pvm&quot; file to &quot;.raw&quot; from V^3 package by [Stefan][2]. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][3]. My renderer give me,&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Comparing my images with the ones given on the site,&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Instead of mapping the single isovalue to all channels. I used the isovalue for alpha only and used a constant `0.07` for `rgb`. My foot ends up looking as in the below picture. This leads me to believe it's more of a transfer function problem?&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;So are my images wrong or the below images are using some fancy transfer functions? If so, how do you design these transfer functions? I searched the net but found very little information on how to do it.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][9]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, just adjusted it so it's in the center and accounted for the aspect ratio. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;I'm not posting it here since it's already this big. But if you want I can post it. Any help would be greatly appreciated since there isn't much matter on volume rendering and especially transfer functions over the net&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://sourceforge.net/projects/volren/&#xD;&#xA;  [3]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [4]: https://i.stack.imgur.com/lbGYY.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/eqoJI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Diwng.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/rQ1ds.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/MxDQL.png&#xD;&#xA;  [9]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24515" PostHistoryTypeId="2" PostId="9006" RevisionGUID="b1f6439f-9ec7-4600-8525-87028da460f1" CreationDate="2019-07-16T17:55:38.327" UserDisplayName="user9391" Text="I have found the issue. The gamma correction was the correct value, the same as in the book (1/2), but the light source had the brightness of 1.0f. The book had set the light's brightness to 18.0f for all color channels. &#xD;&#xA;&#xD;&#xA;This would introduce color overflow if left at that, and the very light areas (above 1.0f, and subsequently when converted, outside the range [0, 255]) would have wrong colors. &#xD;&#xA;&#xD;&#xA;To fix this clamp the the pixel's color values.&#xD;&#xA;&#xD;&#xA; 1. Go through all samples and calculate pixel color.&#xD;&#xA; 2. Divide the color by number of samples&#xD;&#xA; 3. Apply gamma correction&#xD;&#xA; 4. Clamp colors in range [0, 1]&#xD;&#xA; 5. Finally, convert values to range [0, 255]&#xD;&#xA;&#xD;&#xA;[![Result after fix][1]][1]&#xD;&#xA;&#xD;&#xA;(I will accept this answer as a solution in 2 days because StackExchange doesn't let me to do it now.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2VAj3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24517" PostHistoryTypeId="2" PostId="9007" RevisionGUID="d80090ab-448f-4f24-8abd-ff686d4afcd1" CreationDate="2019-07-16T23:37:24.830" UserId="3385" Text="I've read about measured BDRFs and models like cook-torrance have parameters that need to be set. It isn't hard to imagine that these parameters and the measured properties would vary from point to point on a lot of surfaces.&#xD;&#xA;&#xD;&#xA;Do artists or scans ever give us textures for these kinds of values? Where could I find or purchase models and textures for these kinds of things? What representations would textures for these models typically have? If these are hard to find is it simply because artists have yet to start using these models?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24518" PostHistoryTypeId="1" PostId="9007" RevisionGUID="d80090ab-448f-4f24-8abd-ff686d4afcd1" CreationDate="2019-07-16T23:37:24.830" UserId="3385" Text="Where to find BRDF textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="24519" PostHistoryTypeId="3" PostId="9007" RevisionGUID="d80090ab-448f-4f24-8abd-ff686d4afcd1" CreationDate="2019-07-16T23:37:24.830" UserId="3385" Text="|texture|pathtracing|brdf|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24520" PostHistoryTypeId="2" PostId="9008" RevisionGUID="5c19e484-9268-481c-8762-04bd872d0ec1" CreationDate="2019-07-17T13:30:50.970" UserId="228" Text="Does anyone know what applications has the computation of a parallel transport on a mesh?&#xD;&#xA;&#xD;&#xA;I'm talking about methods such as [this one][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cmu.edu/~kmcrane/Projects/VectorHeatMethod/paper.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24521" PostHistoryTypeId="1" PostId="9008" RevisionGUID="5c19e484-9268-481c-8762-04bd872d0ec1" CreationDate="2019-07-17T13:30:50.970" UserId="228" Text="Application of parallel transport in computer graphics and mesh processing" ContentLicense="CC BY-SA 4.0" />
  <row Id="24522" PostHistoryTypeId="3" PostId="9008" RevisionGUID="5c19e484-9268-481c-8762-04bd872d0ec1" CreationDate="2019-07-17T13:30:50.970" UserId="228" Text="|mesh|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24527" PostHistoryTypeId="2" PostId="9010" RevisionGUID="15cf1b2d-f6f5-4379-8b39-5adbb1f23ace" CreationDate="2019-07-17T21:35:47.920" UserId="10744" Text="I have a question about Nvidia Flex or any particle based simulation in general:&#xD;&#xA;&#xD;&#xA;The particles are created by sampling the mesh, which can result in fewer particles than there are vertices in the mesh.&#xD;&#xA;&#xD;&#xA;After computing the new particle positions, how are the vertex positions updated based on the particle positions? &#xD;&#xA;&#xD;&#xA;Are they simply projected onto a point within the particle?&#xD;&#xA;And is the mesh fully updated or is it just rendered in a modified way?&#xD;&#xA;&#xD;&#xA;Sorry for these unprofessional questions.&#xD;&#xA;I appreciate any help." ContentLicense="CC BY-SA 4.0" />
  <row Id="24528" PostHistoryTypeId="1" PostId="9010" RevisionGUID="15cf1b2d-f6f5-4379-8b39-5adbb1f23ace" CreationDate="2019-07-17T21:35:47.920" UserId="10744" Text="Vertex positions from particle position" ContentLicense="CC BY-SA 4.0" />
  <row Id="24529" PostHistoryTypeId="3" PostId="9010" RevisionGUID="15cf1b2d-f6f5-4379-8b39-5adbb1f23ace" CreationDate="2019-07-17T21:35:47.920" UserId="10744" Text="|vertex-buffer-object|particles|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24530" PostHistoryTypeId="2" PostId="9011" RevisionGUID="1db03a43-7c34-4d7b-a4b9-548f60b8a397" CreationDate="2019-07-18T11:34:56.477" UserId="10904" Text="The question asks about branch avoidance, so doing that while retaining comparison is still fair play(*).&#xD;&#xA;&#xD;&#xA;Checking if some scalar or vector equals its `clamp`ed version is a terse, intuitive option:&#xD;&#xA;&#xD;&#xA;Combine `float(clampN(d, dMin, dMax) == d)`, which yields 0.0 if false or 1.0 if true, with whatever way you use this resulting value, for example, `mix`. &#xD;&#xA;&#xD;&#xA;`d` can be scalar or any vector, while `dMin`/`dMax` are either scalars, or whatever `d` is.&#xD;&#xA;&#xD;&#xA;If `&lt;` needs to be distinguished from `&lt;=`, it gets a bit more tedious as additional comparisons are needed for the min/max values or subtracting the value from an extremum and getting a `sign`, unless one can safely use some other approach such as introducing an epsilon value.&#xD;&#xA;&#xD;&#xA;For either case, performance may differ (or match) other solutions; in part, because...&#xD;&#xA;&#xD;&#xA;(*) I'm not aware of anything that'd prevent the shader compiler from introducing its own branching if it feels like so; conversely, nothing prevents the shader compiler from converting branching (if) into single-track code, if it can tackle the data flow to the extent to be certain that the results are the same. IIRC the latter is actually done for at least simple cases." ContentLicense="CC BY-SA 4.0" />
  <row Id="24532" PostHistoryTypeId="2" PostId="9012" RevisionGUID="8290f3d2-ba10-4b65-b910-29c5e79d40e7" CreationDate="2019-07-18T17:19:25.847" UserId="10932" Text="I am trying to simulate the actual response of a camera given some object that is reflecting light.  I've written a ray tracer, and have a BRDF that I need to use, and I have a camera sensitivity in terms of signal/Watts.  But I am confused by one (rather important) detail:&#xD;&#xA;&#xD;&#xA;Each ray coming out of the camera has some solid angle associated with it (this part I've already figured out).  So each ray should then have a &quot;Radiance&quot; value associated with it (as radiance has units of W/(sr*m^2)).  That way each ray would just multiply its solid angle by its radiance value, and you'd get an &quot;Irradiance&quot; value of W/m^2.  However, I am unsure how to actually calculate this initial radiance value for each ray.  The reason I am confused is because this seems to be backwards from what the BRDF is giving me.&#xD;&#xA;&#xD;&#xA;A BRDF gives me the radiance leaving the surface in the direction of the camera, meaning the vertex of the solid angle is at the point of intersection.  The solid angle for the ray however is defined flipped, with the vertex of the solid angle at the camera itself.&#xD;&#xA;&#xD;&#xA;How do I bridge this gap?  My idea is that is that if I can actually calculate the radiance for each ray, then I can simply multiple the radiance of each ray by its corresponding solid angle to get an irradiance value, then apply the inverse square law, and finally add up the irradiance for each ray per pixel and divide by the area of the pixel to get the wattage it receives.&#xD;&#xA;&#xD;&#xA;But I am very lost as to how to calculate the radiance for each ray given that the only calculations I'm familiar with (the BRDF) returns a radiance value for a solid angle in the &quot;wrong direction&quot;.&#xD;&#xA;&#xD;&#xA;Am I misunderstanding what is going on?  Am I approaching this incorrectly?  Any help would be really appreciated!" ContentLicense="CC BY-SA 4.0" />
  <row Id="24533" PostHistoryTypeId="1" PostId="9012" RevisionGUID="8290f3d2-ba10-4b65-b910-29c5e79d40e7" CreationDate="2019-07-18T17:19:25.847" UserId="10932" Text="Physically realistic received irradiance values given some BRDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24534" PostHistoryTypeId="3" PostId="9012" RevisionGUID="8290f3d2-ba10-4b65-b910-29c5e79d40e7" CreationDate="2019-07-18T17:19:25.847" UserId="10932" Text="|raytracing|lighting|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24535" PostHistoryTypeId="2" PostId="9013" RevisionGUID="77d386a7-f48d-4234-b3be-d45743009587" CreationDate="2019-07-18T17:34:17.157" UserId="10096" Text="I didn't get this part:&#xD;&#xA;&#xD;&#xA;&gt; That way each ray would just multiply its solid angle by its radiance&#xD;&#xA;&gt; value, and you'd get an &quot;Irradiance&quot; value of W/m^2.&#xD;&#xA;&#xD;&#xA;I'll try to explain how the whole thing works though. You have a light source, it emits light rays. Those light rays bounce around the scene and eventually end up at your camera film. So at the end of the day you have multiple rays hitting the film surface and the radiance of those gets multiplied with the sensitivity function. For efficiency reasons you usually start backwards - from the camera. But if you work with symmetric BRDFs this should not matter. So what arrives at your film is radiance, you multiply that radiance with the sensitivity function and integrate within a &quot;film pixel&quot; to get the result in terms of your screen pixel." ContentLicense="CC BY-SA 4.0" />
  <row Id="24536" PostHistoryTypeId="2" PostId="9014" RevisionGUID="c7b8b8be-e805-4ccf-8f3d-6cc6312b9117" CreationDate="2019-07-18T17:39:23.577" UserId="10930" Text="Exactly the same happened to me as it did to you: I was reading the book, and quite following everything that I was reading, until that bit with the defocus blur. My issue was very specifically with the following bits:&#xD;&#xA;&#xD;&#xA;    lower_left_corner: look_from - half_width*focus_dist*u - half_height*focus_dist*v - focus_dist*w,&#xD;&#xA;    horizontal: 2.0*half_width*focus_dist*u,&#xD;&#xA;    vertical: 2.0*half_height*focus_dist*v&#xD;&#xA;&#xD;&#xA;It was very clear to me that we should multiply `-w` by `focus_dist`, `-w` being the vector pointing towards the subject. But I couldn't figure out why we should multiply the `u` and `v` vectors by `focus_dist` too. That made no sense to me. Was it about the dimensions of the focus plane or something? I couldn't make sense of it. But removing it made the generated image wrong, so it was really needed.&#xD;&#xA;&#xD;&#xA;The insight I had was 'where do we get `half_width` from? And the answer is...&#xD;&#xA;&#xD;&#xA;    let half_height = tan(theta/2.0);&#xD;&#xA;    let half_width = aspect * half_height;&#xD;&#xA;&#xD;&#xA;And NOW everything makes sense! That is obviously wrong, as the code computing `half_height` assumes a distance of 1.0 to the target! Therefore `half_height` was miscalculated in the book, and the author compensated a little later by multiplying by `focus_dist` when using `half_width`...&#xD;&#xA;&#xD;&#xA;Therefore the correct code (despite the fact that the original code worked 100%) would be:&#xD;&#xA;&#xD;&#xA;    let half_height = tan(theta/2.0) * focus_dist;&#xD;&#xA;    let half_width = aspect * half_height;&#xD;&#xA;    // ...&#xD;&#xA;    lower_left_corner: look_from - half_width*u - half_height*v - focus_dist*w,&#xD;&#xA;    horizontal: 2.0*half_width*vertical: 2.0*half_height*v," ContentLicense="CC BY-SA 4.0" />
  <row Id="24537" PostHistoryTypeId="5" PostId="9014" RevisionGUID="e2f960be-2dbc-4bc4-99e8-419e3a567768" CreationDate="2019-07-18T17:51:58.880" UserId="10930" Comment="added 1 character in body" Text="Exactly the same happened to me as it did to you: I was reading the book, and quite following everything that I was reading, until that bit with the defocus blur. My issue was very specifically with the following bits:&#xD;&#xA;&#xD;&#xA;    lower_left_corner: look_from - half_width*focus_dist*u - half_height*focus_dist*v - focus_dist*w,&#xD;&#xA;    horizontal: 2.0*half_width*focus_dist*u,&#xD;&#xA;    vertical: 2.0*half_height*focus_dist*v&#xD;&#xA;&#xD;&#xA;It was very clear to me that we should multiply `-w` by `focus_dist`, `-w` being the vector pointing towards the subject. But I couldn't figure out why we should multiply the `u` and `v` vectors by `focus_dist` too. That made no sense to me. Was it about the dimensions of the focus plane or something? I couldn't make sense of it. But removing it made the generated image wrong, so it was really needed.&#xD;&#xA;&#xD;&#xA;The insight I had was 'where do we get `half_width` from?' And the answer is...&#xD;&#xA;&#xD;&#xA;    let half_height = tan(theta/2.0);&#xD;&#xA;    let half_width = aspect * half_height;&#xD;&#xA;&#xD;&#xA;And NOW everything makes sense! That is obviously wrong, as the code computing `half_height` assumes a distance of 1.0 to the target! Therefore `half_height` was miscalculated in the book, and the author compensated a little later by multiplying by `focus_dist` when using `half_width`...&#xD;&#xA;&#xD;&#xA;Therefore the correct code (despite the fact that the original code worked 100%) would be:&#xD;&#xA;&#xD;&#xA;    let half_height = tan(theta/2.0) * focus_dist;&#xD;&#xA;    let half_width = aspect * half_height;&#xD;&#xA;    // ...&#xD;&#xA;    lower_left_corner: look_from - half_width*u - half_height*v - focus_dist*w,&#xD;&#xA;    horizontal: 2.0*half_width*vertical: 2.0*half_height*v," ContentLicense="CC BY-SA 4.0" />
  <row Id="24538" PostHistoryTypeId="5" PostId="9014" RevisionGUID="a48e2fe1-593b-4fb6-b2f2-216cbf89a4ed" CreationDate="2019-07-18T17:57:19.937" UserId="10930" Comment="added 8 characters in body" Text="Exactly the same happened to me as it did to you: I was reading the book, and quite following everything that I was reading, until that bit with the defocus blur. My issue was very specifically with the following bits:&#xD;&#xA;&#xD;&#xA;    lower_left_corner: look_from - half_width*focus_dist*u - half_height*focus_dist*v - focus_dist*w,&#xD;&#xA;    horizontal: 2.0*half_width*focus_dist*u,&#xD;&#xA;    vertical: 2.0*half_height*focus_dist*v&#xD;&#xA;&#xD;&#xA;It was very clear to me that we should multiply `-w` by `focus_dist`, `-w` being the vector pointing towards the subject. But I couldn't figure out why we should multiply the `u` and `v` vectors by `focus_dist` too. That made no sense to me. Was it about the dimensions of the focus plane or something? I couldn't make sense of it. But removing it made the generated image wrong, so it was really needed.&#xD;&#xA;&#xD;&#xA;The insight I had was 'where do we get `half_width` from?' And the answer is...&#xD;&#xA;&#xD;&#xA;    let half_height = tan(theta/2.0);&#xD;&#xA;    let half_width = aspect * half_height;&#xD;&#xA;&#xD;&#xA;And NOW everything makes sense! That is obviously wrong, as the code computing `half_height` assumes a distance of 1.0 to the target! Therefore `half_height` was miscalculated in the book, and the author compensated a little later by multiplying by `focus_dist` when using `half_width`...&#xD;&#xA;&#xD;&#xA;Therefore the correct code (despite the fact that the original code worked 100%) would be:&#xD;&#xA;&#xD;&#xA;    let half_height = tan(theta/2.0) * focus_dist;&#xD;&#xA;    let half_width = aspect * half_height;&#xD;&#xA;    // ...&#xD;&#xA;    lower_left_corner: look_from - half_width*u - half_height*v - focus_dist*w,&#xD;&#xA;    horizontal: 2.0*half_width*u,&#xD;&#xA;    vertical: 2.0*half_height*v," ContentLicense="CC BY-SA 4.0" />
  <row Id="24539" PostHistoryTypeId="5" PostId="9013" RevisionGUID="cb358ad9-a357-4031-98e0-e1dc23083da2" CreationDate="2019-07-18T17:59:35.397" UserId="10096" Comment="added 579 characters in body" Text="I didn't get this part:&#xD;&#xA;&#xD;&#xA;&gt; That way each ray would just multiply its solid angle by its radiance&#xD;&#xA;&gt; value, and you'd get an &quot;Irradiance&quot; value of W/m^2.&#xD;&#xA;&#xD;&#xA;I'll try to explain how the whole thing works though. You have a light source, it emits light rays. Those light rays bounce around the scene and eventually end up at your camera film. So at the end of the day you have multiple rays hitting the film surface and the radiance of those gets multiplied with the sensitivity function. For efficiency reasons you usually start backwards - from the camera. But if you work with symmetric BRDFs this should not matter. So what arrives at your film is radiance, you multiply that radiance with the sensitivity function and integrate within a &quot;film pixel&quot; to get the result in terms of your screen pixel.&#xD;&#xA;&#xD;&#xA;Edit: To clarify what I meant by integrated out:&#xD;&#xA;&#xD;&#xA;If you have radiance which is a measure of W/(sr * m^2), you can integrate out sr or m^2 like so:&#xD;&#xA;&#xD;&#xA;$$E(x) = \int_{\Omega}{L(x,\omega)\cos\theta\,d\omega}$$&#xD;&#xA;&#xD;&#xA;From where you get irradiance at a point $x$, which gives you the energy arriving from all directions at point $x$ (W/m^2). Now you can go further and find out the energy that arrives at some surface with area A, by integrating over all points on the surface:&#xD;&#xA;&#xD;&#xA;$$\Phi = \int_{A}{E(x)\,d\mu(x)} = \int_{A}\int_{\Omega}{L(x,\omega)\cos\theta\,d\omega\,d\mu(x)}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="24540" PostHistoryTypeId="5" PostId="9001" RevisionGUID="f210a8e7-fa35-4c77-ae44-2b73b4fec315" CreationDate="2019-07-19T03:39:49.873" UserId="10913" Comment="solution figured out" Text="I am trying to implement a custom add-on for Mitsuba, but when I use the Heightfield I have defined in another function call(WaveBrdfAccel) in main.cpp it compiles without any problems but when I try to render the scene I get an error that says:&#xD;&#xA; **undefined symbol: _ZTVN7mitsuba11HeightfieldE**&#xD;&#xA;&#xD;&#xA;Is there something special I need to do to implement this properly in Mitsuba's frameworks?&#xD;&#xA;&#xD;&#xA;I am trying this on Mitsuba version 0.5.0 (Linux, 64 bit).&#xD;&#xA;If I remove the heightfield parameter from the WaveBrdfAccel declaration then This error does not occur which leads me to believe​ there is something wrong in the way I am calling it but I cannot figure it out.  &#xD;&#xA;&#xD;&#xA;Here is my main.cpp file :&#xD;&#xA;```c++&#xD;&#xA;GPTWorkResultTest *spec;&#xD;&#xA;    			spec-&gt;SpectrumInit(); &#xD;&#xA;&#xD;&#xA;			GPTWorkResultEXR heightfieldImage(heightfieldFilename);&#xD;&#xA;			Heightfield heightfield(&amp;heightfieldImage, texelWidth, vertScale);&#xD;&#xA;			Query query;&#xD;&#xA;    			query.mu_p = Vector2(mu_x, mu_y);&#xD;&#xA;    			query.sigma_p = sigma_p;&#xD;&#xA;    			query.lambda = lambda;&#xD;&#xA;&#xD;&#xA;			WaveBrdfAccel waveBrdfAccel(&amp;heightfield, diffModel); &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;the Heightfield and WaveBrdfAccel class both in waveBrdf.h:&#xD;&#xA;```c++&#xD;&#xA;class Heightfield {&#xD;&#xA;public:&#xD;&#xA;     explicit Heightfield() {}&#xD;&#xA;     Heightfield(GPTWorkResultEXR *heightfieldImage, Float texelWidth = 1.0, Float vertScale = 1.0)&#xD;&#xA;        : mHeightfieldImage(heightfieldImage), mTexelWidth(texelWidth), mVertScale(vertScale) {}&#xD;&#xA;    GaborKernel g(int i, int j, Float F, Float lambda);&#xD;&#xA;&#xD;&#xA;    Vector2 n(Float i, Float j);&#xD;&#xA;public:&#xD;&#xA;    GPTWorkResultEXR *mHeightfieldImage;&#xD;&#xA;    Float mTexelWidth;      // in microns.&#xD;&#xA;    Float mVertScale;&#xD;&#xA;	MTS_DECLARE_CLASS()&#xD;&#xA;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;class WaveBrdfAccel {&#xD;&#xA;public:&#xD;&#xA;  &#xD;&#xA;explicit WaveBrdfAccel(Heightfield *heightfield, string method);&#xD;&#xA;&#xD;&#xA; comp queryIntegral(const Query &amp;query, int layer, int xIndex, int yIndex);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;MTS_DECLARE_CLASS()&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and finally the inclusion in waveBrdf.cpp:&#xD;&#xA;```c++&#xD;&#xA;WaveBrdfAccel::WaveBrdfAccel(Heightfield *heightfield, string method) {&#xD;&#xA;cout &lt;&lt; &quot;IT IS ACTUALLY running wave&quot; &lt;&lt; endl;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;MTS_IMPLEMENT_CLASS(WaveBrdfAccel, false, WorkResult)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;*I am not sure exactly why this is the case but I managed to fix it by simply separating the class definitions into sperate header files. If anyone knows why this worked would love to know!*" ContentLicense="CC BY-SA 4.0" />
  <row Id="24541" PostHistoryTypeId="2" PostId="9015" RevisionGUID="4ef88483-2979-4010-ad66-74c6f8f050f4" CreationDate="2019-07-19T04:30:18.740" UserId="3385" Text="Path tracing seems to perform Monte Carlo integration where the space being integrated over is the space of paths (e.g. chains of rays) but the rendering equation is stated in terms of outgoing rays. Naively you would have to perform the integration at each bounce to model the rendering equation but this would take exponential time. It seems that there should be a proof that either a) integration over the space of paths is equivalent to recursive integration over the space of rays or b) sampling paths is a valid numeric technique for evaluating the rendering equation. While somewhat intuitive neither of those facts is obvious to me. Is there a proof of some such claim?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24542" PostHistoryTypeId="1" PostId="9015" RevisionGUID="4ef88483-2979-4010-ad66-74c6f8f050f4" CreationDate="2019-07-19T04:30:18.740" UserId="3385" Text="Rendering equation in terms of paths rather than directions" ContentLicense="CC BY-SA 4.0" />
  <row Id="24543" PostHistoryTypeId="3" PostId="9015" RevisionGUID="4ef88483-2979-4010-ad66-74c6f8f050f4" CreationDate="2019-07-19T04:30:18.740" UserId="3385" Text="|pathtracing|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24544" PostHistoryTypeId="2" PostId="9016" RevisionGUID="63fbe812-1d1c-4659-8b84-69535e78a0fc" CreationDate="2019-07-19T09:14:10.740" UserId="10096" Text="This is a very good question. There is a common misconception that Monte Carlo, or integration is applied &quot;recursively&quot; on the rendering equation. That is not what's happening. Numerical integration methods are tailored to problems of the form:&#xD;&#xA;&#xD;&#xA;$$I = \int_{\Omega}{f(x)d\mu(x)} \approx \sum_{k=0}^{N-1}w(x_k)f(x_k)$$&#xD;&#xA;&#xD;&#xA;Note that this is not the case for the rendering equation. Namely the fact that it is an equation, and the unknown radiance function $L$ shows up on both sides. In order to apply numerical integration techniques (such as Monte Carlo), one has to bring the rendering equation to the above form. Fortunately this is a well studied problem. The rendering equation is a specific case of a Fredholm integral equation of the second kind. If one can show that the scattering operator in that equation is a contraction $||T||&lt;1$ (which holds if brdfs are energy conserving, there are cases where this is not required but that goes outside the scope of my answer), then we may perform a Neumann expansion (https://en.wikipedia.org/wiki/Liouville%E2%80%93Neumann_series).&#xD;&#xA;&#xD;&#xA;The commonly used form of the rendering equation is the solid angle formulation (here $\sigma$ is the solid angle measure, $\sigma(\omega) = \sin\theta\,d\theta d\phi$):&#xD;&#xA;&#xD;&#xA;$$L(x,\omega_o) = L_e(x,\omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta_i\,d\sigma(\omega_i)}$$&#xD;&#xA;&#xD;&#xA;In order to perform the expansion, I will rewrite this in the area formulation (here $\mu(x)$ is the Lebesgue area measure):&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)L(x_2 \rightarrow x_1)\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)}$$&#xD;&#xA;&#xD;&#xA;Where $M$ is the set of all surface points in the scene, $V(x,y)$ is the visibility function which is $1$ if there is nothing between $x$ and $y$ and $0$ otherwise. If the normals of the surfaces at point $x_1$ and $x_2$ are respectively $N_{x_1}$ and $N_{x_2}$, then $\cos\theta_{x_1} = N_{x_1} \cdot \frac{x_2-x1}{||x_2-x_1||}$ and $\cos\theta_{x_2} = N_{x_2} \cdot \frac{x_1-x2}{||x_2-x_1||}$. As for the radiance, $L(x_2 \rightarrow x_1)$ gives the radiance arriving at $x_1$ from the direction of $x_2$. And the brdf notation relationship is: $f(x_2 \rightarrow x_1 \rightarrow x_0) = f(x_1 \rightarrow x_0, x_1, x_1 \rightarrow x_2)$ (that means $\omega_o = x_1 \rightarrow x_0$ and $\omega_i = x_1 \rightarrow x_2$).&#xD;&#xA;&#xD;&#xA;I will rewrite the above for simplicity and conciseness as:&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + L_r(x_1 \rightarrow x_0)$$&#xD;&#xA;&#xD;&#xA;Let us now split the incoming radiance into direct illumination arriving at $x_1$ and indirect (at least one bounce) illumination. The direct illumination is obviously due to direct light source rays arriving at $x_1$:&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)(L_e(x_2 \rightarrow x_1) + L_r(x_2 \rightarrow x_1))\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)} = &#xD;&#xA;L_e(x1 \rightarrow x_0) + \int_{M_L}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1)\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)} + $$&#xD;&#xA;&#xD;&#xA;$$\int_{M \setminus M_L}f(x_2 \rightarrow x_1 \rightarrow x_0)\Bigg[\int_{M}f(x_3 \rightarrow x_2 \rightarrow x_1)L(x_3 \rightarrow x_2)\cos\theta_{x_2}$$&#xD;&#xA;&#xD;&#xA;$$\frac{\cos\theta_{x_3}}{||x_3-x_2||^2}V(x_3,x_2)\,d\mu(x_3)\Bigg]\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Where $M_L$ is the set of points for which $L_e \ne 0$. All I did here was separate the sum $L_e(x_2 \rightarrow x_1) + L_r(x_2 \rightarrow x_1)$ into two integrals, and then I additionally expanded $L_r$ into the corresponding integral using the recursive definition. You can expand this until infinity. For conciseness, I will rewrite the integration as an operator: $L_r = TL$. Now we can see the relationship to the Neumann expansion. Since the rendering equation can be written as:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;&#xD;&#xA;The solution is formally given as: &#xD;&#xA;&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e$$&#xD;&#xA;&#xD;&#xA;Applying the Neumann expansion yields:&#xD;&#xA;&#xD;&#xA;$$L = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;&#xD;&#xA;Note that each term of the sum is an increasingly dimensional integral. The first term is obviously just $L_e(x_1 \rightarrow x_0)$, the second term $TL_e$ is the integral over $M_L$ that I wrote when I split $L_e$ and $L_r$, and so on. What each term gives you is the energy coming from a light source after $i$ bounces. The first term gives you the radiance emitted from $x_1$ towards $x_0$ (paths of length 0), the second term gives you the radiance that is due to direct illumination of $x_1$ scattered towards $x_0$ (paths of length 1), then you have the radiance due to lights two bounces away (paths of length 2) etc. With each bounce each new integral in the sum gains two dimensions (if we are just integrating over incoming directions). I would also like to emphasize that the integration variable $x_2$ in $TL_e$ is not the same $x_2$ as the one in $T^iL_e$ (this means that in the example with integration over $M_L$ and $M\setminus M_L$, $x_2$ in the first integral is not the same as in the second one - they are just integration variables). Another important fact is that within each sum each path starts at the film $x_0$ and ends at a light source (due to the integration over $M_L$).&#xD;&#xA;&#xD;&#xA;Now that we have a sum of integrals, we can apply our numerical techniques to each integral to estimate the sum. An obvious optimization, is reusing the samples used to compute $T^iL$ to compute $T^{i+1}L = T(T^iL)$. This yields a formulation where we can formally write out the sum of integrals as one integral with integration over all paths that start at the camera film and end at a light source. This also illustrates why Monte Carlo is a preferred technique: since we want to estimate an infinite dimensional integral, and Monte Carlo's convergence doesn't depend on the dimensionality unlike standard quadrature rules (there's also the point that it doesn't care about the smoothness of the integrand, but that's a double edged sword). &#xD;&#xA;&#xD;&#xA;As you may have noticed, with the path integration formulation an exponential path count growth is not required. Splitting a path into multiple new ones is a technique known as splitting. While it is beneficial for high energy paths, on average with each bounce the energy gets lower due to attenuation, so this is in most cases counterproductive. On the other hand early path termination (for low energy paths) is more often than not beneficial in terms of efficiency (that's simply cutting off the sum at some point and not computing the remaining infinitely many terms, because you deem they have a contribution that is too low), and that's where Russian roulette comes in. &#xD;&#xA;&#xD;&#xA;All of this is actually contained in Kajiya's paper on the rendering equation, even though he doesn't go into the details I went. He just refers to Rubinstein's book: https://dl.acm.org/citation.cfm?id=539488 (note - the first edition, later editions do not have the part he is referring to). In this book how to solve Fredholm integrals of the second kind is described (what I explained above, but more formally).&#xD;&#xA;&#xD;&#xA;I hope my explanation was useful, and will continue being useful for future readers." ContentLicense="CC BY-SA 4.0" />
  <row Id="24545" PostHistoryTypeId="5" PostId="9016" RevisionGUID="be395d8f-300e-4367-93c3-c055e65c87d9" CreationDate="2019-07-19T10:38:38.940" UserId="10096" Comment="Removed M_L to avoid confusion" Text="This is a very good question. There is a common misconception that Monte Carlo, or integration is applied &quot;recursively&quot; on the rendering equation. That is not what's happening. Numerical integration methods are tailored to problems of the form:&#xD;&#xA;&#xD;&#xA;$$I = \int_{\Omega}{f(x)d\mu(x)} \approx \sum_{k=0}^{N-1}w(x_k)f(x_k)$$&#xD;&#xA;&#xD;&#xA;Note that this is not the case for the rendering equation. Namely the fact that it is an equation, and the unknown radiance function $L$ shows up on both sides. In order to apply numerical integration techniques (such as Monte Carlo), one has to bring the rendering equation to the above form. Fortunately this is a well studied problem. The rendering equation is a specific case of a Fredholm integral equation of the second kind. If one can show that the scattering operator in that equation is a contraction $||T||&lt;1$ (which holds if brdfs are energy conserving, there are cases where this is not required but that goes outside the scope of my answer), then we may perform a Neumann expansion (https://en.wikipedia.org/wiki/Liouville%E2%80%93Neumann_series).&#xD;&#xA;&#xD;&#xA;The commonly used form of the rendering equation is the solid angle formulation (here $\sigma$ is the solid angle measure, $\sigma(\omega) = \sin\theta\,d\theta d\phi$):&#xD;&#xA;&#xD;&#xA;$$L(x,\omega_o) = L_e(x,\omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta_i\,d\sigma(\omega_i)}$$&#xD;&#xA;&#xD;&#xA;In order to perform the expansion, I will rewrite this in the area formulation (here $\mu(x)$ is the Lebesgue area measure):&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)L(x_2 \rightarrow x_1)\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)}$$&#xD;&#xA;&#xD;&#xA;Where $M$ is the set of all surface points in the scene, $V(x,y)$ is the visibility function which is $1$ if there is nothing between $x$ and $y$ and $0$ otherwise. If the normals of the surfaces at point $x_1$ and $x_2$ are respectively $N_{x_1}$ and $N_{x_2}$, then $\cos\theta_{x_1} = N_{x_1} \cdot \frac{x_2-x1}{||x_2-x_1||}$ and $\cos\theta_{x_2} = N_{x_2} \cdot \frac{x_1-x2}{||x_2-x_1||}$. As for the radiance, $L(x_2 \rightarrow x_1)$ gives the radiance arriving at $x_1$ from the direction of $x_2$. And the brdf notation relationship is: $f(x_2 \rightarrow x_1 \rightarrow x_0) = f(x_1 \rightarrow x_0, x_1, x_1 \rightarrow x_2)$ (that means $\omega_o = x_1 \rightarrow x_0$ and $\omega_i = x_1 \rightarrow x_2$).&#xD;&#xA;&#xD;&#xA;I will rewrite the above for simplicity and conciseness as:&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + L_r(x_1 \rightarrow x_0)$$&#xD;&#xA;&#xD;&#xA;Let us now split the incoming radiance into direct illumination arriving at $x_1$ and indirect (at least one bounce) illumination. The direct illumination is obviously due to direct light source rays arriving at $x_1$:&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)(L_e(x_2 \rightarrow x_1) + L_r(x_2 \rightarrow x_1))\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)} = &#xD;&#xA;L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1)\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)} + $$&#xD;&#xA;&#xD;&#xA;$$\int_{M}f(x_2 \rightarrow x_1 \rightarrow x_0)\Bigg[\int_{M}f(x_3 \rightarrow x_2 \rightarrow x_1)L(x_3 \rightarrow x_2)\cos\theta_{x_2}$$&#xD;&#xA;&#xD;&#xA;$$\frac{\cos\theta_{x_3}}{||x_3-x_2||^2}V(x_3,x_2)\,d\mu(x_3)\Bigg]\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;All I did here was separate the sum $L_e(x_2 \rightarrow x_1) + L_r(x_2 \rightarrow x_1)$ into two integrals, and then I additionally expanded $L_r$ into the corresponding integral using the recursive definition. You can expand this until infinity. For conciseness, I will rewrite the integration as an operator: $L_r = TL$. Now we can see the relationship to the Neumann expansion. Since the rendering equation can be written as:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;&#xD;&#xA;The solution is formally given as: &#xD;&#xA;&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e$$&#xD;&#xA;&#xD;&#xA;Applying the Neumann expansion yields:&#xD;&#xA;&#xD;&#xA;$$L = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;&#xD;&#xA;Note that each term of the sum is an increasingly dimensional integral. The first term is obviously just $L_e(x_1 \rightarrow x_0)$, the second term $TL_e$ is the integral for $L_e(x_2 \rightarrow x_2)$ that I wrote when I split $L_e$ and $L_r$, and so on. What each term gives you is the energy coming from a light source after $i$ bounces. The first term gives you the radiance emitted from $x_1$ towards $x_0$ (paths of length 0), the second term gives you the radiance that is due to direct illumination of $x_1$ scattered towards $x_0$ (paths of length 1), then you have the radiance due to lights two bounces away (paths of length 2) etc. With each bounce each new integral in the sum gains two dimensions (if we are just integrating over incoming directions). I would also like to emphasize that the integration variable $x_2$ in $TL_e$ is not the same $x_2$ as the one in $T^iL_e$ (this means that in the example with integration, $x_2$ in the first integral is not the same as in the second one - they are just integration variables). Another important fact is that within each sum each path starts at the film $x_0$ and ends at a light source ($L_e(x_2\rightarrow x_1)$ is non-zero only for points $x_2$ lying on light sources).&#xD;&#xA;&#xD;&#xA;Now that we have a sum of integrals, we can apply our numerical techniques to each integral to estimate the sum. An obvious optimization, is reusing the samples used to compute $T^iL$ to compute $T^{i+1}L = T(T^iL)$. This yields a formulation where we can formally write out the sum of integrals as one integral with integration over all paths that start at the camera film and end at a light source. This also illustrates why Monte Carlo is a preferred technique: since we want to estimate an infinite dimensional integral, and Monte Carlo's convergence doesn't depend on the dimensionality unlike standard quadrature rules (there's also the point that it doesn't care about the smoothness of the integrand, but that's a double edged sword). &#xD;&#xA;&#xD;&#xA;As you may have noticed, with the path integration formulation an exponential path count growth is not required. Splitting a path into multiple new ones is a technique known as splitting. While it is beneficial for high energy paths, on average with each bounce the energy gets lower due to attenuation, so this is in most cases counterproductive. On the other hand early path termination (for low energy paths) is more often than not beneficial in terms of efficiency (that's simply cutting off the sum at some point and not computing the remaining infinitely many terms, because you deem they have a contribution that is too low), and that's where Russian roulette comes in. &#xD;&#xA;&#xD;&#xA;All of this is actually contained in Kajiya's paper on the rendering equation, even though he doesn't go into the details I went. He just refers to Rubinstein's book: https://dl.acm.org/citation.cfm?id=539488 (note - the first edition, later editions do not have the part he is referring to). In this book how to solve Fredholm integrals of the second kind is described (what I explained above, but more formally).&#xD;&#xA;&#xD;&#xA;I hope my explanation was useful, and will continue being useful for future readers." ContentLicense="CC BY-SA 4.0" />
  <row Id="24546" PostHistoryTypeId="50" PostId="8613" RevisionGUID="e9c8ab91-ad6f-4ece-9499-83277602a745" CreationDate="2019-07-19T13:03:05.450" UserId="-1" />
  <row Id="24547" PostHistoryTypeId="2" PostId="9017" RevisionGUID="9efd2f70-bce7-49e6-83b9-3246a39b4535" CreationDate="2019-07-19T15:08:48.347" UserId="1578" Text="I've been trying to implement a microfacet specular BRDF based on the equations in [Real Shading in UE4][1], but I'm getting weird ring-shaped artifacts in the highlights of rough surfaces:&#xD;&#xA;&#xD;&#xA;[![The artifacts][2]][2]&#xD;&#xA;&#xD;&#xA;Here's the relevant pieces of the fragment shader:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;float D(float NoH, float roughness) {&#xD;&#xA;    float a = sqr(roughness);&#xD;&#xA;    float a2 = sqr(a);&#xD;&#xA;    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);&#xD;&#xA;    return a2 / denom;&#xD;&#xA;}&#xD;&#xA;float G1(float NoV, float k) {&#xD;&#xA;    float denom = NoV * (1.0 - k) + k;&#xD;&#xA;    return NoV / denom;&#xD;&#xA;}&#xD;&#xA;float G(float NoL, float NoV, float roughness) {&#xD;&#xA;    float k = sqr(roughness + 1) / 8.0;&#xD;&#xA;    return G1(NoL, k) * G1(NoV, k);&#xD;&#xA;}&#xD;&#xA;float F(float VoH, float ior) {&#xD;&#xA;    float f0 = sqr((1.0-ior)/(1.0+ior));&#xD;&#xA;    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);&#xD;&#xA;}&#xD;&#xA;vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {&#xD;&#xA;    vec3 H = normalize(V+L);&#xD;&#xA;    float NoL = dot(N, L);&#xD;&#xA;    float NoV = dot(N, V);&#xD;&#xA;&#xD;&#xA;    float nom = D(dot(N, H), mat.roughness)&#xD;&#xA;        * F(dot(V, H), mat.ior)&#xD;&#xA;        * G(NoL, NoV, mat.roughness);&#xD;&#xA;    float denom = 4.0 * NoL * NoV;&#xD;&#xA;&#xD;&#xA;    return vec3(1) * nom / denom;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// ----------------------&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // ...&#xD;&#xA;&#xD;&#xA;    vec3 rd = normalize(frag_pos - camera_pos);&#xD;&#xA;    Material mat = materials[mat_index];&#xD;&#xA;    col = brdf(-rd, sun_dir, normal, mat);&#xD;&#xA;&#xD;&#xA;    // ...&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Any idea what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/mYWcu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24548" PostHistoryTypeId="1" PostId="9017" RevisionGUID="9efd2f70-bce7-49e6-83b9-3246a39b4535" CreationDate="2019-07-19T15:08:48.347" UserId="1578" Text="Microfacet BRDF artifacts" ContentLicense="CC BY-SA 4.0" />
  <row Id="24549" PostHistoryTypeId="3" PostId="9017" RevisionGUID="9efd2f70-bce7-49e6-83b9-3246a39b4535" CreationDate="2019-07-19T15:08:48.347" UserId="1578" Text="|brdf|material|artifacts|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24550" PostHistoryTypeId="5" PostId="9016" RevisionGUID="109a7793-d532-41ab-a950-32a19df95cad" CreationDate="2019-07-19T19:14:59.497" UserId="10096" Comment="added 6 characters in body" Text="This is a very good question. There is a common misconception that Monte Carlo, or integration is applied &quot;recursively&quot; on the rendering equation. That is not what's happening. Numerical integration methods are tailored to problems of the form:&#xD;&#xA;&#xD;&#xA;$$I = \int_{\Omega}{f(x)d\mu(x)} \approx \sum_{k=0}^{N-1}w(x_k)f(x_k)$$&#xD;&#xA;&#xD;&#xA;Note that this is not the case for the rendering equation. Namely the fact that it is an equation, and the unknown radiance function $L$ shows up on both sides. In order to apply numerical integration techniques (such as Monte Carlo), one has to bring the rendering equation to the above form. Fortunately this is a well studied problem. The rendering equation is a specific case of a Fredholm integral equation of the second kind. If one can show that the scattering operator in that equation is a contraction $||T||&lt;1$ (which holds if brdfs are energy conserving, there are cases where this is not required but that goes outside the scope of my answer), then we may perform a Neumann expansion (https://en.wikipedia.org/wiki/Liouville%E2%80%93Neumann_series).&#xD;&#xA;&#xD;&#xA;The commonly used form of the rendering equation is the solid angle formulation (here $\sigma$ is the solid angle measure, $\sigma(\omega) = \sin\theta\,d\theta d\phi$):&#xD;&#xA;&#xD;&#xA;$$L(x,\omega_o) = L_e(x,\omega_o) + \int_{\Omega}{f(\omega_o,x,\omega_i)L_i(x,\omega_i)\cos\theta_i\,d\sigma(\omega_i)}$$&#xD;&#xA;&#xD;&#xA;In order to perform the expansion, I will rewrite this in the area formulation (here $\mu(x)$ is the Lebesgue area measure):&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)L(x_2 \rightarrow x_1)\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)}$$&#xD;&#xA;&#xD;&#xA;Where $M$ is the set of all surface points in the scene, $V(x,y)$ is the visibility function which is $1$ if there is nothing between $x$ and $y$ and $0$ otherwise. If the normals of the surfaces at point $x_1$ and $x_2$ are respectively $N_{x_1}$ and $N_{x_2}$, then $\cos\theta_{x_1} = N_{x_1} \cdot \frac{x_2-x1}{||x_2-x_1||}$ and $\cos\theta_{x_2} = N_{x_2} \cdot \frac{x_1-x2}{||x_2-x_1||}$. As for the radiance, $L(x_2 \rightarrow x_1)$ gives the radiance arriving at $x_1$ from the direction of $x_2$. And the brdf notation relationship is: $f(x_2 \rightarrow x_1 \rightarrow x_0) = f(x_1 \rightarrow x_0, x_1, x_1 \rightarrow x_2)$ (that means $\omega_o = x_1 \rightarrow x_0$ and $\omega_i = x_1 \rightarrow x_2$).&#xD;&#xA;&#xD;&#xA;I will rewrite the above for simplicity and conciseness as:&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + L_r(x_1 \rightarrow x_0)$$&#xD;&#xA;&#xD;&#xA;Let us now split the incoming radiance into direct illumination arriving at $x_1$ and indirect (at least one bounce) illumination. The direct illumination is obviously due to direct light source rays arriving at $x_1$:&#xD;&#xA;&#xD;&#xA;$$L(x_1 \rightarrow x_0) = L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)(L_e(x_2 \rightarrow x_1) + L_r(x_2 \rightarrow x_1))\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)} = &#xD;&#xA;L_e(x1 \rightarrow x_0) + \int_{M}{f(x_2 \rightarrow x_1 \rightarrow x_0)L_e(x_2 \rightarrow x_1)\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)} + $$&#xD;&#xA;&#xD;&#xA;$$\int_{M}f(x_2 \rightarrow x_1 \rightarrow x_0)\Bigg[\int_{M}f(x_3 \rightarrow x_2 \rightarrow x_1)L(x_3 \rightarrow x_2)\cos\theta_{x_2}$$&#xD;&#xA;&#xD;&#xA;$$\frac{\cos\theta_{x_3}}{||x_3-x_2||^2}V(x_3,x_2)\,d\mu(x_3)\Bigg]\cos\theta_{x_1}\frac{\cos\theta_{x_2}}{||x_2-x_1||^2}V(x_2,x_1)\,d\mu(x_2)$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;All I did here was separate the sum $L_e(x_2 \rightarrow x_1) + L_r(x_2 \rightarrow x_1)$ into two integrals, and then I additionally expanded $L_r$ into the corresponding integral using the recursive definition. You can expand this until infinity. For conciseness, I will rewrite the integration as an operator: $L_r = TL$. Now we can see the relationship to the Neumann expansion. Since the rendering equation can be written as:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;&#xD;&#xA;The solution is formally given as: &#xD;&#xA;&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e$$&#xD;&#xA;&#xD;&#xA;Applying the Neumann expansion yields:&#xD;&#xA;&#xD;&#xA;$$L = \sum_{i=0}^{\infty}T^iL_e$$&#xD;&#xA;&#xD;&#xA;Note that each term of the sum is an increasingly dimensional integral. The first term is obviously just $L_e(x_1 \rightarrow x_0)$, the second term $TL_e$ is the integral for $L_e(x_2 \rightarrow x_2)$ that I wrote when I split $L_e$ and $L_r$, and so on. What each term gives you is the energy coming from a light source after $i$ bounces. The first term gives you the radiance emitted from $x_1$ towards $x_0$ (paths of length 0), the second term gives you the radiance that is due to direct illumination of $x_1$ scattered towards $x_0$ (paths of length 1), then you have the radiance due to lights two bounces away (paths of length 2) etc. With each bounce each new integral in the sum gains two dimensions (if we are just integrating over incoming directions). I would also like to emphasize that the integration variable $x_2$ in $TL_e$ is not the same $x_2$ as the one in $T^iL_e$ (this means that in the example with integration, $x_2$ in the first integral is not the same as in the second one - they are just integration variables). Another important fact is that within each sum each path starts at the film $x_0$ and ends at a light source ($L_e(x_2\rightarrow x_1)$ is non-zero only for points $x_2$ lying on light sources).&#xD;&#xA;&#xD;&#xA;Now that we have a sum of integrals, we can apply our numerical techniques to each integral to estimate the sum. An obvious optimization, is reusing the samples used to compute $T^iL_e$ to compute $T^{i+1}L_e = T(T^iL_e)$. This yields a formulation where we can formally write out the sum of integrals as one integral with integration over all paths that start at the camera film and end at a light source. This also illustrates why Monte Carlo is a preferred technique: since we want to estimate an infinite dimensional integral, and Monte Carlo's convergence doesn't depend on the dimensionality unlike standard quadrature rules (there's also the point that it doesn't care about the smoothness of the integrand, but that's a double edged sword). &#xD;&#xA;&#xD;&#xA;As you may have noticed, with the path integration formulation an exponential path count growth is not required. Splitting a path into multiple new ones is a technique known as splitting. While it is beneficial for high energy paths, on average with each bounce the energy gets lower due to attenuation, so this is in most cases counterproductive. On the other hand early path termination (for low energy paths) is more often than not beneficial in terms of efficiency (that's simply cutting off the sum at some point and not computing the remaining infinitely many terms, because you deem they have a contribution that is too low), and that's where Russian roulette comes in. &#xD;&#xA;&#xD;&#xA;All of this is actually contained in Kajiya's paper on the rendering equation, even though he doesn't go into the details I went. He just refers to Rubinstein's book: https://dl.acm.org/citation.cfm?id=539488 (note - the first edition, later editions do not have the part he is referring to). In this book how to solve Fredholm integrals of the second kind is described (what I explained above, but more formally).&#xD;&#xA;&#xD;&#xA;I hope my explanation was useful, and will continue being useful for future readers." ContentLicense="CC BY-SA 4.0" />
  <row Id="24551" PostHistoryTypeId="2" PostId="9018" RevisionGUID="bd1e7e41-295b-4984-8371-cd7fb764d5bc" CreationDate="2019-07-19T19:36:31.367" UserId="10871" Text="I have finished Dennis Ritchie's C book, and I would like to create my own plotting software for enhancing my programming skill,I want sources,books or anything to reach this goal.Thanks for answers." ContentLicense="CC BY-SA 4.0" />
  <row Id="24552" PostHistoryTypeId="1" PostId="9018" RevisionGUID="bd1e7e41-295b-4984-8371-cd7fb764d5bc" CreationDate="2019-07-19T19:36:31.367" UserId="10871" Text="How can I create multivariable function plotting software" ContentLicense="CC BY-SA 4.0" />
  <row Id="24553" PostHistoryTypeId="3" PostId="9018" RevisionGUID="bd1e7e41-295b-4984-8371-cd7fb764d5bc" CreationDate="2019-07-19T19:36:31.367" UserId="10871" Text="|computational-geometry|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24554" PostHistoryTypeId="5" PostId="9017" RevisionGUID="20ebabb9-b57a-45c8-9144-06a9c537e81e" CreationDate="2019-07-19T21:09:12.040" UserId="1578" Comment="Partially fixed" Text="I've been trying to implement a microfacet specular BRDF based on the equations in [Real Shading in UE4][1], but I'm getting weird ring-shaped artifacts in the highlights of rough surfaces:&#xD;&#xA;&#xD;&#xA;[![The artifacts][2]][2]&#xD;&#xA;&#xD;&#xA;Here's the relevant pieces of the fragment shader:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;float D(float NoH, float roughness) {&#xD;&#xA;    float a = sqr(roughness);&#xD;&#xA;    float a2 = sqr(a);&#xD;&#xA;    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);&#xD;&#xA;    return a2 / denom;&#xD;&#xA;}&#xD;&#xA;float G1(float NoV, float k) {&#xD;&#xA;    float denom = NoV * (1.0 - k) + k;&#xD;&#xA;    return NoV / denom;&#xD;&#xA;}&#xD;&#xA;float G(float NoL, float NoV, float roughness) {&#xD;&#xA;    float k = sqr(roughness + 1) / 8.0;&#xD;&#xA;    return G1(NoL, k) * G1(NoV, k);&#xD;&#xA;}&#xD;&#xA;float F(float VoH, float ior) {&#xD;&#xA;    float f0 = sqr((1.0-ior)/(1.0+ior));&#xD;&#xA;    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);&#xD;&#xA;}&#xD;&#xA;vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {&#xD;&#xA;    vec3 H = normalize(V+L);&#xD;&#xA;    float NoL = dot(N, L);&#xD;&#xA;    float NoV = dot(N, V);&#xD;&#xA;&#xD;&#xA;    float nom = D(dot(N, H), mat.roughness)&#xD;&#xA;        * F(dot(V, H), mat.ior)&#xD;&#xA;        * G(NoL, NoV, mat.roughness);&#xD;&#xA;&#xD;&#xA;    // Prevent division by zero, even when the GPU uses 8-bit arithmetic&#xD;&#xA;    float denom = max(4.0 * NoL * NoV, 1.0/256.0);&#xD;&#xA;&#xD;&#xA;    return vec3(1) * nom / denom;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// ----------------------&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // ...&#xD;&#xA;&#xD;&#xA;    vec3 rd = normalize(frag_pos - camera_pos);&#xD;&#xA;    Material mat = materials[mat_index];&#xD;&#xA;    col = brdf(-rd, sun_dir, normal, mat);&#xD;&#xA;&#xD;&#xA;    // ...&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Any idea what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I think the black patch in the center of the ring was caused by a division by zero. I fixed that in the above code, but the result still isn't correct. The specular highlights are a flat circle:&#xD;&#xA;&#xD;&#xA;[![Circle artifact][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/mYWcu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/56M5w.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24555" PostHistoryTypeId="2" PostId="9019" RevisionGUID="0bb70b5a-0945-41ef-9ed6-6b6706d4cc39" CreationDate="2019-07-19T21:39:31.090" UserId="1578" Text="It turns out that the ring was happening from a negative divided by a negative, so adding `nom = max(nom, 0.0);` fixed the problem. The new highlight, amplified:&#xD;&#xA;&#xD;&#xA;[![Correct result][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/f6sev.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24556" PostHistoryTypeId="8" PostId="9017" RevisionGUID="053b749f-d6ee-49d5-a913-a46daee03bf2" CreationDate="2019-07-19T21:39:49.163" UserId="1578" Comment="Rollback to [9efd2f70-bce7-49e6-83b9-3246a39b4535]" Text="I've been trying to implement a microfacet specular BRDF based on the equations in [Real Shading in UE4][1], but I'm getting weird ring-shaped artifacts in the highlights of rough surfaces:&#xD;&#xA;&#xD;&#xA;[![The artifacts][2]][2]&#xD;&#xA;&#xD;&#xA;Here's the relevant pieces of the fragment shader:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;float D(float NoH, float roughness) {&#xD;&#xA;    float a = sqr(roughness);&#xD;&#xA;    float a2 = sqr(a);&#xD;&#xA;    float denom = PI * sqr(sqr(NoH) * (a2 - 1.0) + 1.0);&#xD;&#xA;    return a2 / denom;&#xD;&#xA;}&#xD;&#xA;float G1(float NoV, float k) {&#xD;&#xA;    float denom = NoV * (1.0 - k) + k;&#xD;&#xA;    return NoV / denom;&#xD;&#xA;}&#xD;&#xA;float G(float NoL, float NoV, float roughness) {&#xD;&#xA;    float k = sqr(roughness + 1) / 8.0;&#xD;&#xA;    return G1(NoL, k) * G1(NoV, k);&#xD;&#xA;}&#xD;&#xA;float F(float VoH, float ior) {&#xD;&#xA;    float f0 = sqr((1.0-ior)/(1.0+ior));&#xD;&#xA;    return f0 + (1.0 - f0) * exp2((-5.55473*VoH - 6.98316) * VoH);&#xD;&#xA;}&#xD;&#xA;vec3 brdf(in vec3 V, in vec3 L, in vec3 N, in Material mat) {&#xD;&#xA;    vec3 H = normalize(V+L);&#xD;&#xA;    float NoL = dot(N, L);&#xD;&#xA;    float NoV = dot(N, V);&#xD;&#xA;&#xD;&#xA;    float nom = D(dot(N, H), mat.roughness)&#xD;&#xA;        * F(dot(V, H), mat.ior)&#xD;&#xA;        * G(NoL, NoV, mat.roughness);&#xD;&#xA;    float denom = 4.0 * NoL * NoV;&#xD;&#xA;&#xD;&#xA;    return vec3(1) * nom / denom;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// ----------------------&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // ...&#xD;&#xA;&#xD;&#xA;    vec3 rd = normalize(frag_pos - camera_pos);&#xD;&#xA;    Material mat = materials[mat_index];&#xD;&#xA;    col = brdf(-rd, sun_dir, normal, mat);&#xD;&#xA;&#xD;&#xA;    // ...&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Any idea what I'm doing wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/mYWcu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24558" PostHistoryTypeId="50" PostId="8044" RevisionGUID="e469c262-8669-4ce0-9b69-53f4b84d1231" CreationDate="2019-07-20T22:01:50.260" UserId="-1" />
  <row Id="24559" PostHistoryTypeId="2" PostId="9020" RevisionGUID="9d7e4efd-173e-4318-9788-9a3634af5f17" CreationDate="2019-07-21T03:17:08.723" UserId="8925" Text="Every frame I dispatch a compute shader which write data in a storage buffer. The cpu needs to readback this data and use it. I would expect this to work :&#xD;&#xA;&#xD;&#xA;    // Dispatch compute shader&#xD;&#xA;    glDispatchCompute(x, y, z);&#xD;&#xA;    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;    void* data = glMapNamedBuffer(buffer, GL_READ_ONLY);&#xD;&#xA;&#xD;&#xA;But it would introduce a sync point which I'd like to avoid. I'd like to hide the latency by reading the data written by the previous frame dispatch. If I was using textures I would have used PBOs, but I have not found a way to do this for storage buffers.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24560" PostHistoryTypeId="1" PostId="9020" RevisionGUID="9d7e4efd-173e-4318-9788-9a3634af5f17" CreationDate="2019-07-21T03:17:08.723" UserId="8925" Text="Async readback storage buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="24561" PostHistoryTypeId="3" PostId="9020" RevisionGUID="9d7e4efd-173e-4318-9788-9a3634af5f17" CreationDate="2019-07-21T03:17:08.723" UserId="8925" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24562" PostHistoryTypeId="2" PostId="9021" RevisionGUID="a9088978-738b-4cb7-8ab0-864473dbda23" CreationDate="2019-07-21T03:33:02.410" UserId="2654" Text="First, that's the wrong memory barrier. The barrier is for how you intend to *use* the memory, not how it was *written to*.&#xD;&#xA;&#xD;&#xA;&gt; I'd like to hide the latency by reading the data written by the previous frame dispatch.&#xD;&#xA;&#xD;&#xA;This is a general flaw in OpenGL: targeted synchronization of such memory operations is not possible.&#xD;&#xA;&#xD;&#xA;In Vulkan, you can be extremely specific about both execution and visibility operations. When you start the dispatch, you can stick an event after it, which you can wait on using a specific execution and memory barrier.&#xD;&#xA;&#xD;&#xA;In OpenGL, you only really have two tools: fence sync objects and a broad memory barrier that covers *all* prior commands which have executed. And sync objects don't actually ensure visibility. Yes, you can set a fence right after your dispatch, and spin on the CPU (doing actual work between checks of the fence). But even after the fence has completed, you can't guarantee visibility without firing off the barrier. And that barrier will affect *all memory operations* that were submitted before the barrier was called.&#xD;&#xA;&#xD;&#xA;So if you had two dispatch operations, and call `glMemoryBarrier` after both of them, the barrier will wait on *all of them*, even if you only care about waiting for the first one.&#xD;&#xA;&#xD;&#xA;The best you can really do is just delay the memory barrier call for as long as possible. But it's going to synchronize against all submitted commands when you call it.&#xD;&#xA;&#xD;&#xA;You might also try... cheating. Use a persistent/coherent mapped buffer, and use a fence sync object on the CPU *instead of* calling the memory barrier. This is undefined behavior by the OpenGL specification, but on real systems, the fence sync should ensure execution of the operation, and the coherently-mapped buffer ought to ensure visibility.&#xD;&#xA;&#xD;&#xA;But that doesn't mean it *will*. So don't expect miracles." ContentLicense="CC BY-SA 4.0" />
  <row Id="24563" PostHistoryTypeId="13" PostId="7703" RevisionGUID="9ac1be40-06f9-4fed-88af-4ee0ef1266c2" CreationDate="2019-07-21T13:37:10.523" UserId="8709" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:8709,&quot;DisplayName&quot;:&quot;JarsOfJam-Scheduler&quot;}]}" />
  <row Id="24564" PostHistoryTypeId="5" PostId="8975" RevisionGUID="b68fb7cf-04e0-4d45-8ff8-d5e0345afecc" CreationDate="2019-07-21T16:02:40.697" UserId="2479" Comment="RenderDoc update" Text="I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8 using the texture sampler, the result is very flickery (up-scaled for clarity):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. What am I doing wrong?&#xD;&#xA;&#xD;&#xA;# RenderDoc Update&#xD;&#xA;&#xD;&#xA;After investigating the issue using [RenderDoc][3] I found that the mipmap is being generated successfully and it's third level looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;However, the output of the down-scaling pass looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;As if the sampler didn't use the mipmap at all.&#xD;&#xA;&#xD;&#xA;Don't get distracted by coloured object instead almost white ones. I lowered the sphere brightness a bit while investigating the bug.&#xD;&#xA;&#xD;&#xA;# DirectX details&#xD;&#xA;&#xD;&#xA;The sampler:&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;The pass texture:&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;The render target view:&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;The shader resource view:&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;I call explicit generation of mipmap after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;        ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;        mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;&#xD;&#xA;        mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;&#xD;&#xA;        ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;        mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The down-scaling PS:&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;  [3]: https://renderdoc.org/&#xD;&#xA;  [4]: https://i.stack.imgur.com/n8sy7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/WUppN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24565" PostHistoryTypeId="5" PostId="8975" RevisionGUID="705704f9-b8cd-483a-b2d7-3eb47846ad2c" CreationDate="2019-07-21T16:16:29.207" UserId="2479" Comment="added samplers; re-wording" Text="I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8 using the texture sampler, the result is very flickery (up-scaled for clarity):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. What am I doing wrong?&#xD;&#xA;&#xD;&#xA;# RenderDoc Update&#xD;&#xA;&#xD;&#xA;After investigating the issue using [RenderDoc][3] I found that the mipmap is being generated successfully and it's third level looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;However, the output of the down-scaling pass looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;As if the sampler didn't use the mipmap at all. Don't get distracted by coloured object instead almost white ones. I lowered the sphere brightness a bit while investigating the bug.&#xD;&#xA;&#xD;&#xA;# DirectX details&#xD;&#xA;&#xD;&#xA;### Samplers&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;&#xD;&#xA;    hr = mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStatePoint);&#xD;&#xA;&#xD;&#xA;...are set right before rendering the screen quad&#xD;&#xA;&#xD;&#xA;    ID3D11SamplerState* aSamplers[] = { mSamplerStatePoint, mSamplerStateLinear };&#xD;&#xA;    mImmediateContext-&gt;PSSetSamplers(0, 2, aSamplers);&#xD;&#xA;&#xD;&#xA;...and used within the down-scaling PS shader&#xD;&#xA;&#xD;&#xA;    SamplerState PointSampler  : register (s0);&#xD;&#xA;    SamplerState LinearSampler : register (s1);&#xD;&#xA;&#xD;&#xA;    Texture2D s0 : register(t0);&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;### Texture&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;...it's render target view&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;...it's shader resource view&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;Explicit generation of mipmap is called after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;    ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;    mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;    &#xD;&#xA;    mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;    &#xD;&#xA;    ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;    mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;  [3]: https://renderdoc.org/&#xD;&#xA;  [4]: https://i.stack.imgur.com/n8sy7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/WUppN.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24566" PostHistoryTypeId="5" PostId="8975" RevisionGUID="f522462e-c624-4491-8a53-da98f5bcdce6" CreationDate="2019-07-21T16:38:19.360" UserId="2479" Comment="Added SampleLevel" Text="I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8 using the texture sampler, the result is very flickery (up-scaled for clarity):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. What am I doing wrong?&#xD;&#xA;&#xD;&#xA;# RenderDoc Update&#xD;&#xA;&#xD;&#xA;After investigating the issue using [RenderDoc][3] I found that the mipmap is being generated successfully and it's third level looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;However, the output of the down-scaling pass looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;As if the sampler didn't use the mipmap at all. Don't get distracted by coloured object instead almost white ones. I lowered the sphere brightness a bit while investigating the bug.&#xD;&#xA;&#xD;&#xA;Even if I choose the mipmap level explicitly&#xD;&#xA;&#xD;&#xA;    float4 vColor = s0.SampleLevel(LinearSampler, Input.Tex, 3);&#xD;&#xA;&#xD;&#xA;it changes nothing :-/&#xD;&#xA;&#xD;&#xA;# DirectX details&#xD;&#xA;&#xD;&#xA;### Samplers&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;&#xD;&#xA;    hr = mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStatePoint);&#xD;&#xA;&#xD;&#xA;...are set right before rendering the screen quad&#xD;&#xA;&#xD;&#xA;    ID3D11SamplerState* aSamplers[] = { mSamplerStatePoint, mSamplerStateLinear };&#xD;&#xA;    mImmediateContext-&gt;PSSetSamplers(0, 2, aSamplers);&#xD;&#xA;&#xD;&#xA;...and used within the down-scaling PS shader&#xD;&#xA;&#xD;&#xA;    SamplerState PointSampler  : register (s0);&#xD;&#xA;    SamplerState LinearSampler : register (s1);&#xD;&#xA;&#xD;&#xA;    Texture2D s0 : register(t0);&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;### Texture&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;...it's render target view&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;...it's shader resource view&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;Explicit generation of mipmap is called after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;    ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;    mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;    &#xD;&#xA;    mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;    &#xD;&#xA;    ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;    mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;  [3]: https://renderdoc.org/&#xD;&#xA;  [4]: https://i.stack.imgur.com/n8sy7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/WUppN.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24567" PostHistoryTypeId="5" PostId="8975" RevisionGUID="19a6c9f4-c17b-4c84-b09f-777861119faf" CreationDate="2019-07-21T17:02:06.137" UserId="2479" Comment="LOD clamp" Text="I am implementing a post-processing effect in my DirectX 11 pet renderer. The post-processing pass is implemented by rendering a full-screen quad covered with texture containing original rendered image, which works as it should, but I have problems with downscaling the texture.&#xD;&#xA;&#xD;&#xA;The non-processed testing scene looks like this (three very bright emmissive spheres):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I see no problem at this stage, but when I run the first post-processing pass, which just down-scales the image by the factor of 8 using the texture sampler, the result is very flickery (up-scaled for clarity):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I expected a mipmap would solve or at least reduce the flickering, but it didn't change a thing. What am I doing wrong?&#xD;&#xA;&#xD;&#xA;# RenderDoc Update&#xD;&#xA;&#xD;&#xA;After investigating the issue using [RenderDoc][3] I found that the mipmap is being generated successfully and it's third level looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;However, the output of the down-scaling pass looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;As if the sampler didn't use the mipmap at all. Don't get distracted by coloured object instead almost white ones. I lowered the sphere brightness a bit while investigating the bug.&#xD;&#xA;&#xD;&#xA;Even if I choose the mipmap level explicitly&#xD;&#xA;&#xD;&#xA;    float4 vColor = s0.SampleLevel(LinearSampler, Input.Tex, 3);&#xD;&#xA;&#xD;&#xA;it changes nothing :-/&#xD;&#xA;&#xD;&#xA;RenderDoc also says &quot;LOD Clamp 0-0&quot; for the used sampler. What is it? Couldn't this be the problem?&#xD;&#xA;&#xD;&#xA;# DirectX details&#xD;&#xA;&#xD;&#xA;### Samplers&#xD;&#xA;&#xD;&#xA;    D3D11_SAMPLER_DESC descSampler;&#xD;&#xA;    ZeroMemory(&amp;descSampler, sizeof(descSampler));&#xD;&#xA;    descSampler.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;    descSampler.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;&#xD;&#xA;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;&#xD;&#xA;    mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStateLinear);&#xD;&#xA;&#xD;&#xA;    descSampler.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;&#xD;&#xA;    hr = mDevice-&gt;CreateSamplerState(&amp;descSampler, &amp;mSamplerStatePoint);&#xD;&#xA;&#xD;&#xA;...are set right before rendering the screen quad&#xD;&#xA;&#xD;&#xA;    ID3D11SamplerState* aSamplers[] = { mSamplerStatePoint, mSamplerStateLinear };&#xD;&#xA;    mImmediateContext-&gt;PSSetSamplers(0, 2, aSamplers);&#xD;&#xA;&#xD;&#xA;...and used within the down-scaling PS shader&#xD;&#xA;&#xD;&#xA;    SamplerState PointSampler  : register (s0);&#xD;&#xA;    SamplerState LinearSampler : register (s1);&#xD;&#xA;&#xD;&#xA;    Texture2D s0 : register(t0);&#xD;&#xA;&#xD;&#xA;    float4 Pass1PS(QUAD_VS_OUTPUT Input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;        return s0.Sample(LinearSampler, Input.Tex);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;### Texture&#xD;&#xA;&#xD;&#xA;    D3D11_TEXTURE2D_DESC descTex;&#xD;&#xA;    ZeroMemory(&amp;descTex, sizeof(D3D11_TEXTURE2D_DESC));&#xD;&#xA;    descTex.ArraySize = 1;&#xD;&#xA;    descTex.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;&#xD;&#xA;    descTex.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;&#xD;&#xA;    descTex.Usage = D3D11_USAGE_DEFAULT;&#xD;&#xA;    descTex.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;&#xD;&#xA;    descTex.Width  = width;&#xD;&#xA;    descTex.Height = height;&#xD;&#xA;    descTex.MipLevels = 0;&#xD;&#xA;    descTex.SampleDesc.Count = 1;&#xD;&#xA;    device-&gt;CreateTexture2D(&amp;descTex, nullptr, &amp;tex);&#xD;&#xA;&#xD;&#xA;...it's render target view&#xD;&#xA;&#xD;&#xA;    D3D11_RENDER_TARGET_VIEW_DESC descRTV;&#xD;&#xA;    descRTV.Format = descTex.Format;&#xD;&#xA;    descRTV.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descRTV.Texture2D.MipSlice = 0;&#xD;&#xA;    device-&gt;CreateRenderTargetView(tex, &amp;descRTV, &amp;rtv);&#xD;&#xA;&#xD;&#xA;...it's shader resource view&#xD;&#xA;&#xD;&#xA;    D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;&#xD;&#xA;    ZeroMemory(&amp;descSRV, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));&#xD;&#xA;    descSRV.Format = descTex.Format;&#xD;&#xA;    descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;&#xD;&#xA;    descSRV.Texture2D.MipLevels = (UINT)-1;&#xD;&#xA;    descSRV.Texture2D.MostDetailedMip = 0;&#xD;&#xA;    device-&gt;CreateShaderResourceView(tex, &amp;descSRV, &amp;srv);&#xD;&#xA;&#xD;&#xA;Explicit generation of mipmap is called after the scene was rendered into the texture and another texture was set as a render target.&#xD;&#xA;&#xD;&#xA;    ID3D11RenderTargetView* aRTViews[1] = { mPass1Buff.GetRTV() };&#xD;&#xA;    mImmediateContext-&gt;OMSetRenderTargets(1, aRTViews, nullptr);&#xD;&#xA;    &#xD;&#xA;    mImmediateContext-&gt;GenerateMips(mPass0Buff.GetSRV());&#xD;&#xA;    &#xD;&#xA;    ID3D11ShaderResourceView* aSRViews[1] = { mPass0Buff.GetSRV() };&#xD;&#xA;    mImmediateContext-&gt;PSSetShaderResources(0, 1, aSRViews);&#xD;&#xA;&#xD;&#xA;The code is compiled in debug and the D3D device was created with `D3D11_CREATE_DEVICE_DEBUG` flag and I get no runtime errors on the console.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/huGay.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/4tOH8.gif&#xD;&#xA;  [3]: https://renderdoc.org/&#xD;&#xA;  [4]: https://i.stack.imgur.com/n8sy7.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/WUppN.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24568" PostHistoryTypeId="2" PostId="9022" RevisionGUID="a71a1353-0c43-4b31-98fe-f527f734a589" CreationDate="2019-07-21T18:08:43.193" UserId="2479" Text="I found the problem. By zeroing the sampler description I implicitly set LOD bounds to 0. After adding&#xD;&#xA;&#xD;&#xA;    descSampler.MinLOD = 0;&#xD;&#xA;    descSampler.MaxLOD = D3D11_FLOAT32_MAX;&#xD;&#xA;&#xD;&#xA;the mipmap works as expected. Thanks for your attention :-)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24569" PostHistoryTypeId="50" PostId="6119" RevisionGUID="1e5cc9c8-cf98-4074-93e3-050f77d32475" CreationDate="2019-07-22T03:03:50.457" UserId="-1" />
  <row Id="24570" PostHistoryTypeId="5" PostId="9022" RevisionGUID="c4ed7505-8a9d-4d5d-bda8-9d25d4e2ec92" CreationDate="2019-07-22T08:37:29.860" UserId="2479" Comment="minor" Text="I found the problem. By zeroing the sampler description I implicitly set LOD bounds to 0. After adding&#xD;&#xA;&#xD;&#xA;    descSampler.MinLOD = 0;&#xD;&#xA;    descSampler.MaxLOD = D3D11_FLOAT32_MAX;&#xD;&#xA;&#xD;&#xA;the mipmap works as expected. Thank you for your attention :-)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24571" PostHistoryTypeId="2" PostId="9023" RevisionGUID="fa4ebdc8-6a24-4a0f-9ceb-c267e7778565" CreationDate="2019-07-22T14:42:38.383" UserId="10874" Text="I'm using a vertex shader to effectively wrap vertices on a sphere. Starting with `world_position` already after multiplying the vertex by the model transform matrix to get the coordinates in world space, I calculate the new position via an inverse Mercator projection:&#xD;&#xA;&#xD;&#xA;    float theta = 2.0 * PI * world_position.x / world_radius;&#xD;&#xA;    float phi = 2.0 * atan(exp(world_position.y / world_radius)) - PI / 2.0;&#xD;&#xA;    float radius = world_position.z&#xD;&#xA;    &#xD;&#xA;    gl_Position = vec4(radius * vec3(sin(theta)*cos(phi), sin(phi), cos(theta)*cos(phi)), 1.0);&#xD;&#xA;&#xD;&#xA;What I now need to do is take these angles, $\theta$ and $\varphi$, and use them to transform the normals as well. I've tried creating a rotation matrix to represent rotation first around the Y axis (for $\theta$) and then around the X axis (for $\varphi$), and multiplying that by the vertex's normal (after multiplying the normal by the model matrix's inverse transpose), but that didn't give the results I expected.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How do I use the angles to rotate the normals so they match the rotations of the vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24572" PostHistoryTypeId="1" PostId="9023" RevisionGUID="fa4ebdc8-6a24-4a0f-9ceb-c267e7778565" CreationDate="2019-07-22T14:42:38.383" UserId="10874" Text="Wrapping normals around a sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="24573" PostHistoryTypeId="3" PostId="9023" RevisionGUID="fa4ebdc8-6a24-4a0f-9ceb-c267e7778565" CreationDate="2019-07-22T14:42:38.383" UserId="10874" Text="|glsl|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24574" PostHistoryTypeId="2" PostId="9024" RevisionGUID="c8be7247-bbc6-453e-ac57-efafd613ec1b" CreationDate="2019-07-22T15:24:23.673" UserId="10874" Text="Turns out I needed to be looking at the former normal as a unit vector $(\hat{r}, \hat{\theta},\hat{\varphi})$, and then use a rotation matrix as outlined [here][1] to find $(\hat{x},\hat{y},\hat{z})$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Vector_fields_in_cylindrical_and_spherical_coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="24575" PostHistoryTypeId="2" PostId="9025" RevisionGUID="51fc689e-bc13-46e5-9f95-6881ce3c7739" CreationDate="2019-07-23T19:21:14.957" UserId="5215" Text="I've been looking to play with ray tracing, starting with a simplest of minecraft clones (making something more akin to [cave game][1], for starter). &#xD;&#xA;&#xD;&#xA;I figured I'd define a voxel as a primitive and then use the regular voxel grid to trace the rays. I don't need to test (look) for intersections here, I can precisely calculate them, tracing the ray voxel by voxel.&#xD;&#xA;&#xD;&#xA;However, I do have an RTX card which does accelerate ray tracing with dedicated hardware, and I may be able to get faster results if I were to leverage it.&#xD;&#xA;&#xD;&#xA;From what I gathered, one of the components of the RTX system (or any ray tracer, really) is an acceleration structure that speeds up the process of testing for intersections.&#xD;&#xA;&#xD;&#xA;You give the card an octree or a BVH (or something similar) and it uses it to quickly find the closest hit (or any other hits, for that matter).&#xD;&#xA;&#xD;&#xA;If I'm not mistaken, the hardware accelerated part here is the hit test. It's power is in the ability to test many primitives against one or more rays in a very short amount of time.&#xD;&#xA;&#xD;&#xA;Given the method I'm using for ray tracing, that is the one part that I don't really need, since I don't need to search for which primitives the ray intersects (I calculate them explicitly), I just need to check where the intersection on them is.&#xD;&#xA;&#xD;&#xA;Am I wrong? Can the architecture be used to accelerate what I'm doing?&#xD;&#xA;If so, is it due to the fact that I misunderstood how it works, or can I adapt my plan in order to make it more friendly to the architecture, making the resulting plan faster than the original?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=NEwKBy3babgg&amp;usg=AOvVaw3X91bRH8o8Sxdz7jZIuyLt" ContentLicense="CC BY-SA 4.0" />
  <row Id="24576" PostHistoryTypeId="1" PostId="9025" RevisionGUID="51fc689e-bc13-46e5-9f95-6881ce3c7739" CreationDate="2019-07-23T19:21:14.957" UserId="5215" Text="Regular voxel grids and RTX accelerated ray tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="24577" PostHistoryTypeId="3" PostId="9025" RevisionGUID="51fc689e-bc13-46e5-9f95-6881ce3c7739" CreationDate="2019-07-23T19:21:14.957" UserId="5215" Text="|raytracing|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24581" PostHistoryTypeId="5" PostId="6119" RevisionGUID="c8447238-b386-45ca-888a-2ef438839804" CreationDate="2019-07-24T08:00:39.477" UserId="2479" Comment="math formatting: $\rho$, display formula" Text="Whenever you make a part in inventor, the software calculates de properties of the whole body given a constant density. Then, automatically,  it shows the inertial tensor. As you can recall from math, the inertia equation is $$I_x =  \rho\int(y^2+z^2)dV$$ for the $x$ axis. So, clearing $\rho$, how can I get the right hand of the equation that is been solved in the underlying algorithm without doing any hand calculations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24582" PostHistoryTypeId="24" PostId="6119" RevisionGUID="c8447238-b386-45ca-888a-2ef438839804" CreationDate="2019-07-24T08:00:39.477" Comment="Proposed by 2479 approved by 6, 209 edit id of 481" ContentLicense="CC BY-SA 4.0" />
  <row Id="24583" PostHistoryTypeId="2" PostId="9027" RevisionGUID="dfaf4a27-59c5-48d8-9608-97ec3872ba1c" CreationDate="2019-07-24T12:05:21.130" UserId="10952" Text="First of all here is the most minimal example of the program I could make:&#xD;&#xA;https://github.com/TheJhonny007/TextureTracerDebug&#xD;&#xA;&#xD;&#xA;The shader can be found in the 'resources' folder. It takes an SSBO of Photons that have a position, direction, wavelength and intensity and each thread is responsible for tracing exactly one photon through the grid, where at each grid cell the photon hits, the intensity is accumulated for each wavelength to create a spectral distribution for each grid cell.&#xD;&#xA;&#xD;&#xA;The problem is that the shader works perfectly for 100,000 photons, but doesn't return a result for 1,000,000 photons.&#xD;&#xA;&#xD;&#xA;I looked into the sizes for the SSBOs and all were within my GPUs (NVIDIA Quadro P6000) limits of 2GB:&#xD;&#xA;&#xD;&#xA;- SSBO Grid size: **1.5GB**&#xD;&#xA;- SSBO Photons Size: **0.02GB**&#xD;&#xA;&#xD;&#xA;Even the UBO is within limits (**8KB** of allowed 16KB).&#xD;&#xA;&#xD;&#xA;If I change the logic at some places it works with one million photons (see lines 113 and 142 for comments).&#xD;&#xA;&#xD;&#xA;I currently can't see any explanation of why the shader fails for 1,000,000 photons, works for 100,000 photons. The logic is the same and the buffer sizes are within limits. (That the buffer size can't be a problem is also confirmed by that it works when changing the logic.)&#xD;&#xA;&#xD;&#xA;You may need to adjust the CMAKE file for you to compile. You need GLUT, GLEW and GLM." ContentLicense="CC BY-SA 4.0" />
  <row Id="24584" PostHistoryTypeId="1" PostId="9027" RevisionGUID="dfaf4a27-59c5-48d8-9608-97ec3872ba1c" CreationDate="2019-07-24T12:05:21.130" UserId="10952" Text="GLSL Compute Shader doesn't run for large inputs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24585" PostHistoryTypeId="3" PostId="9027" RevisionGUID="dfaf4a27-59c5-48d8-9608-97ec3872ba1c" CreationDate="2019-07-24T12:05:21.130" UserId="10952" Text="|opengl|raytracing|glsl|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24586" PostHistoryTypeId="5" PostId="9027" RevisionGUID="15cb4397-4529-439e-8cfe-2ceae2ab130d" CreationDate="2019-07-24T12:51:35.987" UserId="10952" Comment="included source code" Text="The shader takes an SSBO of Photons that have a position, direction, wavelength and intensity and each thread is responsible for tracing exactly one photon through the grid, where at each grid cell the photon hits, the intensity is accumulated for each wavelength to create a spectral distribution for each grid cell.&#xD;&#xA;&#xD;&#xA;The problem is that the shader works perfectly for 100,000 photons, but doesn't return a result for 1,000,000 photons.&#xD;&#xA;&#xD;&#xA;I looked into the sizes for the SSBOs and all were within my GPUs (NVIDIA Quadro P6000) limits of 2GB:&#xD;&#xA;&#xD;&#xA;- SSBO Grid size: **1.5GB**&#xD;&#xA;- SSBO Photons Size: **0.02GB**&#xD;&#xA;&#xD;&#xA;Even the UBO is within limits (**8KB** of allowed 16KB).&#xD;&#xA;&#xD;&#xA;If I change the logic at some places it works with one million photons (see lines 113 and 142 for comments).&#xD;&#xA;&#xD;&#xA;I currently can't see any explanation of why the shader fails for 1,000,000 photons, works for 100,000 photons. The logic is the same and the buffer sizes are within limits. (That the buffer size can't be a problem is also confirmed by that it works when changing the logic.)&#xD;&#xA;&#xD;&#xA;Below is the source code. If you want to try it yourself here is the code on github: https://github.com/TheJhonny007/TextureTracerDebug&#xD;&#xA;&#xD;&#xA;Compute Shader:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#extension GL_ARB_compute_shader: enable&#xD;&#xA;#extension GL_ARB_shader_storage_buffer_object: enable&#xD;&#xA;#extension GL_ARB_compute_variable_group_size: enable&#xD;&#xA;&#xD;&#xA;const uint TEX_WIDTH = 1024u;&#xD;&#xA;const uint TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const uint MIN_WAVELENGTH = 380u;&#xD;&#xA;const uint MAX_WAVELENGTH = 740u;&#xD;&#xA;const uint NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;// Size: 24 bytes -&gt; ~40,000,000 photons per available gigabyte of ram&#xD;&#xA;struct Photon {&#xD;&#xA;  vec2 position;// m&#xD;&#xA;  vec2 direction;// normalized&#xD;&#xA;  uint wavelength;// nm&#xD;&#xA;  float intensity;// 0..1 should start at 1&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer Photons {&#xD;&#xA;  Photon photons[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// Size: 1440 bytes -&gt; ~700,000 pixels per available gigabyte of ram&#xD;&#xA;struct Pixel {&#xD;&#xA;  uint intensityAtWavelengths[NUM_WAVELENGTHS];// [0..1000]&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 1) buffer Pixels {&#xD;&#xA;  //Pixel pixels[TEX_WIDTH][TEX_HEIGHT];&#xD;&#xA;  // NVIDIAs linker takes ages to link if the sizes are specified :(&#xD;&#xA;  Pixel[] pixels;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// x = x1, y = w1, z = x2, w = w2&#xD;&#xA;layout(std140, binding = 2) uniform HorizontalRectangles {&#xD;&#xA;  vec4 horizontalRectangles[TEX_WIDTH / 2u];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec2 getHorizontalRectangleAt(int i) {&#xD;&#xA;  vec4 entry = horizontalRectangles[i / 2];&#xD;&#xA;  if (i % 2 == 0) {&#xD;&#xA;    return entry.xy;&#xD;&#xA;  } else {&#xD;&#xA;    return entry.zw;&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float rectangleHeight;&#xD;&#xA;&#xD;&#xA;struct Rectangle {&#xD;&#xA;  float x;&#xD;&#xA;  float y;&#xD;&#xA;  float w;&#xD;&#xA;  float h;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout (local_size_variable) in;&#xD;&#xA;&#xD;&#xA;void addToPixel(uvec2 idx, uint wavelength, uint intensity) {&#xD;&#xA;  if (idx.x &gt;= 0u &amp;&amp; idx.x &lt; TEX_WIDTH &amp;&amp; idx.y &gt;= 0u &amp;&amp; idx.y &lt; TEX_HEIGHT) {&#xD;&#xA;    uint index = (idx.y * TEX_WIDTH) + idx.x;&#xD;&#xA;    atomicAdd(pixels[index].intensityAtWavelengths[wavelength - MIN_WAVELENGTH], intensity);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Returns the rectangle at the given indices.&#xD;&#xA;Rectangle getRectangleAt(ivec2 indices) {&#xD;&#xA;  vec2 horRect = getHorizontalRectangleAt(indices.x);&#xD;&#xA;  return Rectangle(horRect.x, rectangleHeight * float(indices.y), horRect.y, rectangleHeight);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Searches for the horizontal index in the rectangle array which contains x.&#xD;&#xA;int binarySearchForHorizontalRectangle(float x) {&#xD;&#xA;  int left = 0;&#xD;&#xA;  int right = int(TEX_WIDTH) - 1;&#xD;&#xA;&#xD;&#xA;  while (left &lt;= right) {&#xD;&#xA;    int middle = (left + right) / 2;&#xD;&#xA;    vec2 rectM = getHorizontalRectangleAt(middle);&#xD;&#xA;    if (rectM.x  + rectM.y &lt; x) {&#xD;&#xA;      left = middle + 1;&#xD;&#xA;    } else if (rectM.x &gt; x) {&#xD;&#xA;      right = middle - 1;&#xD;&#xA;    } else return middle;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  return int(TEX_WIDTH); // outside of grid (should never happen in any reasonable scenario...)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float shadowLength;&#xD;&#xA;uniform float shadowHeight;&#xD;&#xA;&#xD;&#xA;/// Returns the indices of the rectangle at the given location&#xD;&#xA;ivec2 getRectangleIdxAt(vec2 location) {&#xD;&#xA;  if (location.x &gt;= 0 &amp;&amp; location.x &lt; shadowLength &amp;&amp; location.y &gt;= 0 &amp;&amp; location.y &lt; shadowHeight) {&#xD;&#xA;    int x = binarySearchForHorizontalRectangle(location.x);&#xD;&#xA;    int y = int(location.y / rectangleHeight);&#xD;&#xA;    return ivec2(x, y);&#xD;&#xA;  } else return ivec2(TEX_WIDTH, TEX_HEIGHT);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getRayIntersectAtX(Photon ray, float x) {&#xD;&#xA;  float slope = ray.direction.y / ray.direction.x;&#xD;&#xA;  return slope * (x - ray.position.x) + ray.position.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec2 getRayRectangleExitEdge(Photon ray, Rectangle rect) {&#xD;&#xA;  float intersectHeight = getRayIntersectAtX(ray, rect.x + rect.w);&#xD;&#xA;&#xD;&#xA;  // IF ONE OF THE FIRST TWO CONDITIONS GETS REMOVED IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;  if (intersectHeight &lt; rect.y) {&#xD;&#xA;    return ivec2(0, -1);&#xD;&#xA;  } else if (intersectHeight &gt; rect.y + rect.h) {&#xD;&#xA;    return ivec2(0, 1);&#xD;&#xA;  } else {&#xD;&#xA;    return ivec2(1, 0);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;  if(gid &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;  Photon photon = photons[gid];&#xD;&#xA;&#xD;&#xA;  ivec2 photonTexIndices = getRectangleIdxAt(photon.position);&#xD;&#xA;  while (photonTexIndices.x &lt; TEX_WIDTH &amp;&amp; photonTexIndices.y &lt; TEX_HEIGHT &amp;&amp;&#xD;&#xA;  photonTexIndices.x &gt;= 0        &amp;&amp; photonTexIndices.y &gt;= 0) {&#xD;&#xA;    // need to convert to uint for atomic add operations...&#xD;&#xA;    addToPixel(uvec2(photonTexIndices), photon.wavelength, uint(photon.intensity * 100.0));&#xD;&#xA;&#xD;&#xA;    ivec2 dir = getRayRectangleExitEdge(photon, getRectangleAt(photonTexIndices));&#xD;&#xA;    photonTexIndices += dir;&#xD;&#xA;&#xD;&#xA;    // When the ray goes out of bounds on the bottom then mirror it to simulate rays coming from&#xD;&#xA;    // the other side of the planet. This works because of the rotational symmetry of the system.&#xD;&#xA;    // IF COMMENTET OUT IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;    if (photonTexIndices.y &lt; 0) {&#xD;&#xA;      photonTexIndices.y = 0;&#xD;&#xA;      photon.position.y *= -1.0;&#xD;&#xA;      photon.direction.y *= -1.0;&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.hpp&#xD;&#xA;```cpp&#xD;&#xA;#ifndef TEXTURE_TRACER_HPP&#xD;&#xA;#define TEXTURE_TRACER_HPP&#xD;&#xA;&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;&#xD;&#xA;    // 6 * 4 = 24 Bytes&#xD;&#xA;    struct Photon {&#xD;&#xA;        glm::vec2 position;  // m&#xD;&#xA;        glm::vec2 direction; // normalized&#xD;&#xA;        uint32_t waveLength; // nm&#xD;&#xA;        float intensity;     // 0..1 should start at 1&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    class TextureTracer {&#xD;&#xA;    public:&#xD;&#xA;        TextureTracer();&#xD;&#xA;        uint32_t createShadowMap(size_t numPhotons);&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        void initTextureTracer();&#xD;&#xA;        void traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons);&#xD;&#xA;        Photon emitPhoton();&#xD;&#xA;        std::vector&lt;Photon&gt; generatePhotons(uint32_t count);&#xD;&#xA;&#xD;&#xA;        struct {&#xD;&#xA;            uint32_t uRectangleHeight;&#xD;&#xA;            uint32_t uShadowLength;&#xD;&#xA;            uint32_t uShadowHeight;&#xD;&#xA;        } mTextureTracerUniforms;&#xD;&#xA;&#xD;&#xA;        uint32_t mTextureTracerProgram;&#xD;&#xA;&#xD;&#xA;        std::mt19937_64 mRNG;&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; mDistributionSun;&#xD;&#xA;        std::uniform_int_distribution&lt;uint32_t&gt; mDistributionWavelength;&#xD;&#xA;        std::bernoulli_distribution mDistributionBoolean;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;} // namespace gpu&#xD;&#xA;&#xD;&#xA;#endif // TEXTURE_TRACER_HPP&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.cpp&#xD;&#xA;```cpp&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;algorithm&gt;&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;&#xD;&#xA;void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,&#xD;&#xA;                                const GLchar *message, const void *userParam) {&#xD;&#xA;    if (type == GL_DEBUG_TYPE_ERROR)&#xD;&#xA;        fprintf(stderr, &quot;GL ERROR: type = 0x%x, severity = 0x%x, message = %s\n&quot;, type, severity, message);&#xD;&#xA;    else&#xD;&#xA;        fprintf(stdout, &quot;GL INFO: type = 0x%x, severity = 0x%x, message = %s\n&quot;, type, severity, message);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;    const double TEX_HEIGHT_TO_RADIUS_FACTOR = 4;&#xD;&#xA;    const double TEX_SHADOW_LENGTH_FACTOR = 8;&#xD;&#xA;&#xD;&#xA;    const uint32_t TEX_WIDTH = 1024u;&#xD;&#xA;    const uint32_t TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;    const double RADIUS = 6'371'000.0;&#xD;&#xA;    const double RADIUS_FACTORED = RADIUS * TEX_HEIGHT_TO_RADIUS_FACTOR;&#xD;&#xA;&#xD;&#xA;    const double SUN_RADIUS = 695'510'000.0;&#xD;&#xA;    const double DIST_TO_SUN = 149'600'000'000.0;&#xD;&#xA;    const double ATMO_HEIGHT = 42'000.0;&#xD;&#xA;&#xD;&#xA;    std::string loadShader(const std::string &amp;fileName) {&#xD;&#xA;        std::ifstream shaderFileStream(fileName, std::ios::in);&#xD;&#xA;        if (!shaderFileStream.is_open()) {&#xD;&#xA;            std::cerr &lt;&lt; &quot;Could not load the GLSL shader from '&quot; &lt;&lt; fileName &lt;&lt; &quot;'!&quot; &lt;&lt; std::endl;&#xD;&#xA;            exit(-1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        std::string shaderCode;&#xD;&#xA;        while (!shaderFileStream.eof()) {&#xD;&#xA;            std::string line;&#xD;&#xA;            std::getline(shaderFileStream, line);&#xD;&#xA;            shaderCode.append(line + &quot;\n&quot;);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return shaderCode;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void TextureTracer::initTextureTracer() {&#xD;&#xA;        mTextureTracerProgram = glCreateProgram();&#xD;&#xA;        uint32_t rayTracingComputeShader = glCreateShader(GL_COMPUTE_SHADER);&#xD;&#xA;&#xD;&#xA;        std::string code = loadShader(&quot;../resources/TextureTracer.glsl&quot;);&#xD;&#xA;        const char *shader = code.c_str();&#xD;&#xA;        glShaderSource(rayTracingComputeShader, 1, &amp;shader, nullptr);&#xD;&#xA;        glCompileShader(rayTracingComputeShader);&#xD;&#xA;&#xD;&#xA;        glAttachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;        glLinkProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        mTextureTracerUniforms.uRectangleHeight = glGetUniformLocation(mTextureTracerProgram, &quot;rectangleHeight&quot;);&#xD;&#xA;        mTextureTracerUniforms.uShadowHeight = glGetUniformLocation(mTextureTracerProgram, &quot;shadowHeight&quot;);&#xD;&#xA;        mTextureTracerUniforms.uShadowLength = glGetUniformLocation(mTextureTracerProgram, &quot;shadowLength&quot;);&#xD;&#xA;&#xD;&#xA;        glDetachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;        glDeleteShader(rayTracingComputeShader);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    TextureTracer::TextureTracer()&#xD;&#xA;            : mRNG(1L), mDistributionSun(std::uniform_real_distribution&lt;&gt;(-SUN_RADIUS, SUN_RADIUS)),&#xD;&#xA;              mDistributionWavelength(std::uniform_int_distribution&lt;uint32_t&gt;(380, 739)),&#xD;&#xA;              mDistributionBoolean(std::bernoulli_distribution(0.5)) {&#xD;&#xA;        glEnable(GL_DEBUG_OUTPUT);&#xD;&#xA;        glDebugMessageCallback(MessageCallback, nullptr);&#xD;&#xA;&#xD;&#xA;        initTextureTracer();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    double raySphereDistance(glm::dvec2 origin, glm::dvec2 direction, glm::dvec2 center, double radius) {&#xD;&#xA;        glm::dvec2 m = origin - center;&#xD;&#xA;        double b = glm::dot(m, direction);&#xD;&#xA;        double c = glm::dot(m, m) - (radius * radius);&#xD;&#xA;        if (c &gt; 0.0 &amp;&amp; b &gt; 0.0)&#xD;&#xA;            return -1.0;&#xD;&#xA;&#xD;&#xA;        double discr = b * b - c;&#xD;&#xA;&#xD;&#xA;        // A negative discriminant corresponds to ray missing sphere&#xD;&#xA;        if (discr &lt; 0.0)&#xD;&#xA;            return -1.0;&#xD;&#xA;&#xD;&#xA;        // Ray now found to intersect sphere, compute smallest t value of intersection&#xD;&#xA;        return glm::max(0.0, -b - glm::sqrt(discr));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Photon TextureTracer::emitPhoton() {&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; distributionEarth(0.0, ATMO_HEIGHT);&#xD;&#xA;        glm::dvec2 target = {0.0, RADIUS + distributionEarth(mRNG)};&#xD;&#xA;&#xD;&#xA;        double d;&#xD;&#xA;        do {&#xD;&#xA;            d = glm::length(glm::dvec2(mDistributionSun(mRNG), mDistributionSun(mRNG)));&#xD;&#xA;        } while (d &gt; SUN_RADIUS);&#xD;&#xA;&#xD;&#xA;        glm::dvec2 startPosition = glm::dvec2(-DIST_TO_SUN, mDistributionBoolean(mRNG) ? d : -d);&#xD;&#xA;        glm::dvec2 direction = glm::normalize(target - startPosition);&#xD;&#xA;&#xD;&#xA;        startPosition += direction * raySphereDistance(startPosition, direction, {0.0, 0.0},&#xD;&#xA;                                                       RADIUS + ATMO_HEIGHT);&#xD;&#xA;&#xD;&#xA;        return {glm::vec2(0.0, startPosition.y), glm::vec2(direction),&#xD;&#xA;                mDistributionWavelength(mRNG), 1.0f};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    std::vector&lt;Photon&gt; TextureTracer::generatePhotons(uint32_t count) {&#xD;&#xA;        std::vector&lt;Photon&gt; photons(count);&#xD;&#xA;        std::generate(photons.begin(), photons.end(), [this]() {&#xD;&#xA;            return emitPhoton();&#xD;&#xA;        });&#xD;&#xA;        return photons;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void TextureTracer::traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons) {&#xD;&#xA;        glUseProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uRectangleHeight, RADIUS_FACTORED / TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;        const double shadowLength = TEX_SHADOW_LENGTH_FACTOR * (DIST_TO_SUN * RADIUS) / (SUN_RADIUS - RADIUS);&#xD;&#xA;&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uShadowLength, shadowLength);&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uShadowHeight, RADIUS_FACTORED);&#xD;&#xA;&#xD;&#xA;        const double xAxisScalingFactor = glm::log(shadowLength) / glm::log(static_cast&lt;double&gt;(TEX_WIDTH));&#xD;&#xA;&#xD;&#xA;        std::vector&lt;glm::vec4&gt; horizontalRectangles = std::vector&lt;glm::vec4&gt;(TEX_WIDTH / 2);&#xD;&#xA;&#xD;&#xA;        double xx0 = 0.0;&#xD;&#xA;        for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;            const double xx1 = glm::pow(static_cast&lt;double&gt;(x + 1), xAxisScalingFactor);&#xD;&#xA;&#xD;&#xA;            if (x % 2 == 0) {&#xD;&#xA;                horizontalRectangles[x / 2].x = xx0;&#xD;&#xA;                horizontalRectangles[x / 2].y = xx1 - xx0;&#xD;&#xA;            } else {&#xD;&#xA;                horizontalRectangles[x / 2].z = xx0;&#xD;&#xA;                horizontalRectangles[x / 2].w = xx1 - xx0;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            xx0 = xx1;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        uint32_t uboRectangles;&#xD;&#xA;        glGenBuffers(1, &amp;uboRectangles);&#xD;&#xA;        glBindBuffer(GL_UNIFORM_BUFFER, uboRectangles);&#xD;&#xA;        glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) * horizontalRectangles.size(), horizontalRectangles.data(),&#xD;&#xA;                     GL_STATIC_READ);&#xD;&#xA;&#xD;&#xA;        const uint32_t MIN_WAVELENGTH = 380u;&#xD;&#xA;        const uint32_t MAX_WAVELENGTH = 740u;&#xD;&#xA;        const uint32_t NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;        size_t pixelBufferSize = TEX_WIDTH * TEX_HEIGHT * NUM_WAVELENGTHS * sizeof(uint32_t);&#xD;&#xA;        uint32_t ssboPixels;&#xD;&#xA;        glGenBuffers(1, &amp;ssboPixels);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, pixelBufferSize, nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboPhotons);&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboPixels);&#xD;&#xA;        glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboRectangles);&#xD;&#xA;&#xD;&#xA;        const uint32_t numThreads = 32u;&#xD;&#xA;        const uint32_t numBlocks = numPhotons / numThreads;&#xD;&#xA;        std::cout &lt;&lt; &quot;numBlocks: &quot; &lt;&lt; numBlocks &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;        glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;        struct Pixel {&#xD;&#xA;            uint32_t intensityAtWavelengths[NUM_WAVELENGTHS];&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        std::vector&lt;Pixel&gt; pixels(TEX_WIDTH * TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;        glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferSize, pixels.data());&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;        for (int y = 0; y &lt; TEX_HEIGHT; ++y) {&#xD;&#xA;            printf(&quot;%4i | &quot;, y);&#xD;&#xA;            for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;                Pixel p = pixels[y * TEX_WIDTH + x];&#xD;&#xA;                int counter = 0;&#xD;&#xA;                for (uint32_t i : p.intensityAtWavelengths) {&#xD;&#xA;                    counter += i;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (counter == 0) {&#xD;&#xA;                    printf(&quot;  &quot;);&#xD;&#xA;                } else if (counter &gt; 100'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A0&quot;);&#xD;&#xA;                } else if (counter &gt; 10'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A3&quot;);&#xD;&#xA;                } else if (counter &gt; 1'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A6&quot;);&#xD;&#xA;                } else if (counter &gt; 100'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A4&quot;);&#xD;&#xA;                } else {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A1&quot;);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            std::cout &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glDeleteBuffers(1, &amp;uboRectangles);&#xD;&#xA;        glDeleteBuffers(1, &amp;ssboPixels);&#xD;&#xA;&#xD;&#xA;        glUseProgram(0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    uint32_t TextureTracer::createShadowMap(size_t numPhotons) {&#xD;&#xA;        std::vector&lt;Photon&gt; photons = generatePhotons(numPhotons);&#xD;&#xA;&#xD;&#xA;        uint32_t ssboPhotons;&#xD;&#xA;        glGenBuffers(1, &amp;ssboPhotons);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPhotons);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Photon) * photons.size(), photons.data(), GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;        traceThroughTexture(ssboPhotons, photons.size());&#xD;&#xA;&#xD;&#xA;        glDeleteBuffers(1, &amp;ssboPhotons);&#xD;&#xA;        glDeleteProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        glDisable(GL_DEBUG_OUTPUT);&#xD;&#xA;        glDebugMessageCallback(nullptr, nullptr);&#xD;&#xA;&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;&#xD;&#xA;int main(int argc, char *argv[]) {&#xD;&#xA;    glutInit(&amp;argc, argv);&#xD;&#xA;    glutCreateWindow(&quot;Hurr durr OpenGL needs a window o.O&quot;);&#xD;&#xA;    glewInit();&#xD;&#xA;&#xD;&#xA;    auto mapper = gpu::TextureTracer();&#xD;&#xA;&#xD;&#xA;    // WITH 100'000 PHOTONS IT WORKS, WITH 1'000'000 PHOTONS NOT WHY?&#xD;&#xA;    mapper.createShadowMap(100'000);&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="24587" PostHistoryTypeId="5" PostId="9027" RevisionGUID="76eb5531-cba9-420b-814a-5d7b025a9ec7" CreationDate="2019-07-24T13:20:54.363" UserId="10952" Comment="added 2 characters in body" Text="The shader takes an SSBO of Photons that have a position, direction, wavelength and intensity and each thread is responsible for tracing exactly one photon through the grid, where at each grid cell the photon hits, the intensity is accumulated for each wavelength to create a spectral distribution for each grid cell.&#xD;&#xA;&#xD;&#xA;The problem is that the shader works perfectly for 100,000 photons, but doesn't return a result for 1,000,000 photons.&#xD;&#xA;&#xD;&#xA;I looked into the sizes for the SSBOs and all were within my GPUs (NVIDIA Quadro P6000) limits of 2GB:&#xD;&#xA;&#xD;&#xA;- SSBO Grid size: **1.5GB**&#xD;&#xA;- SSBO Photons Size: **0.02GB**&#xD;&#xA;&#xD;&#xA;Even the UBO is within limits (**8KB** of allowed 16KB).&#xD;&#xA;&#xD;&#xA;If I change the logic at some places it works with one million photons (see lines 113 and 142 for comments).&#xD;&#xA;&#xD;&#xA;I currently can't see any explanation of why the shader fails for 1,000,000 photons, works for 100,000 photons. The logic is the same and the buffer sizes are within limits. (That the buffer size can't be a problem is also confirmed by that it works when changing the logic.)&#xD;&#xA;&#xD;&#xA;Below is the source code. If you want to try it yourself here is the code on github: https://github.com/TheJhonny007/TextureTracerDebug&#xD;&#xA;&#xD;&#xA;Compute Shader:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#extension GL_ARB_compute_shader: enable&#xD;&#xA;#extension GL_ARB_shader_storage_buffer_object: enable&#xD;&#xA;#extension GL_ARB_compute_variable_group_size: enable&#xD;&#xA;&#xD;&#xA;const uint TEX_WIDTH = 1024u;&#xD;&#xA;const uint TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const uint MIN_WAVELENGTH = 380u;&#xD;&#xA;const uint MAX_WAVELENGTH = 740u;&#xD;&#xA;const uint NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;// Size: 24 bytes -&gt; ~40,000,000 photons per available gigabyte of ram&#xD;&#xA;struct Photon {&#xD;&#xA;  vec2 position;// m&#xD;&#xA;  vec2 direction;// normalized&#xD;&#xA;  uint wavelength;// nm&#xD;&#xA;  float intensity;// 0..1 should start at 1&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer Photons {&#xD;&#xA;  Photon photons[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// Size: 1440 bytes -&gt; ~700,000 pixels per available gigabyte of ram&#xD;&#xA;struct Pixel {&#xD;&#xA;  uint intensityAtWavelengths[NUM_WAVELENGTHS];// [0..1000]&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 1) buffer Pixels {&#xD;&#xA;  //Pixel pixels[TEX_WIDTH][TEX_HEIGHT];&#xD;&#xA;  // NVIDIAs linker takes ages to link if the sizes are specified :(&#xD;&#xA;  Pixel[] pixels;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// x = x1, y = w1, z = x2, w = w2&#xD;&#xA;layout(std140, binding = 2) uniform HorizontalRectangles {&#xD;&#xA;  vec4 horizontalRectangles[TEX_WIDTH / 2u];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec2 getHorizontalRectangleAt(int i) {&#xD;&#xA;  vec4 entry = horizontalRectangles[i / 2];&#xD;&#xA;  if (i % 2 == 0) {&#xD;&#xA;    return entry.xy;&#xD;&#xA;  } else {&#xD;&#xA;    return entry.zw;&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float rectangleHeight;&#xD;&#xA;&#xD;&#xA;struct Rectangle {&#xD;&#xA;  float x;&#xD;&#xA;  float y;&#xD;&#xA;  float w;&#xD;&#xA;  float h;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout (local_size_variable) in;&#xD;&#xA;&#xD;&#xA;void addToPixel(uvec2 idx, uint wavelength, uint intensity) {&#xD;&#xA;  if (idx.x &gt;= 0u &amp;&amp; idx.x &lt; TEX_WIDTH &amp;&amp; idx.y &gt;= 0u &amp;&amp; idx.y &lt; TEX_HEIGHT) {&#xD;&#xA;    uint index = (idx.y * TEX_WIDTH) + idx.x;&#xD;&#xA;    atomicAdd(pixels[index].intensityAtWavelengths[wavelength - MIN_WAVELENGTH], intensity);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Returns the rectangle at the given indices.&#xD;&#xA;Rectangle getRectangleAt(ivec2 indices) {&#xD;&#xA;  vec2 horRect = getHorizontalRectangleAt(indices.x);&#xD;&#xA;  return Rectangle(horRect.x, rectangleHeight * float(indices.y), horRect.y, rectangleHeight);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Searches for the horizontal index in the rectangle array which contains x.&#xD;&#xA;int binarySearchForHorizontalRectangle(float x) {&#xD;&#xA;  int left = 0;&#xD;&#xA;  int right = int(TEX_WIDTH) - 1;&#xD;&#xA;&#xD;&#xA;  while (left &lt;= right) {&#xD;&#xA;    int middle = (left + right) / 2;&#xD;&#xA;    vec2 rectM = getHorizontalRectangleAt(middle);&#xD;&#xA;    if (rectM.x  + rectM.y &lt; x) {&#xD;&#xA;      left = middle + 1;&#xD;&#xA;    } else if (rectM.x &gt; x) {&#xD;&#xA;      right = middle - 1;&#xD;&#xA;    } else return middle;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  return int(TEX_WIDTH); // outside of grid (should never happen in any reasonable scenario...)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float shadowLength;&#xD;&#xA;uniform float shadowHeight;&#xD;&#xA;&#xD;&#xA;/// Returns the indices of the rectangle at the given location&#xD;&#xA;ivec2 getRectangleIdxAt(vec2 location) {&#xD;&#xA;  if (location.x &gt;= 0 &amp;&amp; location.x &lt; shadowLength &amp;&amp; location.y &gt;= 0 &amp;&amp; location.y &lt; shadowHeight) {&#xD;&#xA;    int x = binarySearchForHorizontalRectangle(location.x);&#xD;&#xA;    int y = int(location.y / rectangleHeight);&#xD;&#xA;    return ivec2(x, y);&#xD;&#xA;  } else return ivec2(TEX_WIDTH, TEX_HEIGHT);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getRayIntersectAtX(Photon ray, float x) {&#xD;&#xA;  float slope = ray.direction.y / ray.direction.x;&#xD;&#xA;  return slope * (x - ray.position.x) + ray.position.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec2 getRayRectangleExitEdge(Photon ray, Rectangle rect) {&#xD;&#xA;  float intersectHeight = getRayIntersectAtX(ray, rect.x + rect.w);&#xD;&#xA;&#xD;&#xA;  // IF ONE OF THE FIRST TWO CONDITIONS GETS REMOVED IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;  if (intersectHeight &lt; rect.y) {&#xD;&#xA;    return ivec2(0, -1);&#xD;&#xA;  } else if (intersectHeight &gt; rect.y + rect.h) {&#xD;&#xA;    return ivec2(0, 1);&#xD;&#xA;  } else {&#xD;&#xA;    return ivec2(1, 0);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;  if(gid &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;  Photon photon = photons[gid];&#xD;&#xA;&#xD;&#xA;  ivec2 photonTexIndices = getRectangleIdxAt(photon.position);&#xD;&#xA;  while (photonTexIndices.x &lt; TEX_WIDTH &amp;&amp; photonTexIndices.y &lt; TEX_HEIGHT &amp;&amp;&#xD;&#xA;  photonTexIndices.x &gt;= 0        &amp;&amp; photonTexIndices.y &gt;= 0) {&#xD;&#xA;    // need to convert to uint for atomic add operations...&#xD;&#xA;    addToPixel(uvec2(photonTexIndices), photon.wavelength, uint(photon.intensity * 100.0));&#xD;&#xA;&#xD;&#xA;    ivec2 dir = getRayRectangleExitEdge(photon, getRectangleAt(photonTexIndices));&#xD;&#xA;    photonTexIndices += dir;&#xD;&#xA;&#xD;&#xA;    // When the ray goes out of bounds on the bottom then mirror it to simulate rays coming from&#xD;&#xA;    // the other side of the planet. This works because of the rotational symmetry of the system.&#xD;&#xA;    // IF COMMENTET OUT IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;    if (photonTexIndices.y &lt; 0) {&#xD;&#xA;      photonTexIndices.y = 0;&#xD;&#xA;      photon.position.y *= -1.0;&#xD;&#xA;      photon.direction.y *= -1.0;&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.hpp&#xD;&#xA;```cpp&#xD;&#xA;#ifndef TEXTURE_TRACER_HPP&#xD;&#xA;#define TEXTURE_TRACER_HPP&#xD;&#xA;&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;&#xD;&#xA;    // 6 * 4 = 24 Bytes&#xD;&#xA;    struct Photon {&#xD;&#xA;        glm::vec2 position;  // m&#xD;&#xA;        glm::vec2 direction; // normalized&#xD;&#xA;        uint32_t waveLength; // nm&#xD;&#xA;        float intensity;     // 0..1 should start at 1&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    class TextureTracer {&#xD;&#xA;    public:&#xD;&#xA;        TextureTracer();&#xD;&#xA;        uint32_t createShadowMap(size_t numPhotons);&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        void initTextureTracer();&#xD;&#xA;        void traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons);&#xD;&#xA;        Photon emitPhoton();&#xD;&#xA;        std::vector&lt;Photon&gt; generatePhotons(uint32_t count);&#xD;&#xA;&#xD;&#xA;        struct {&#xD;&#xA;            uint32_t uRectangleHeight;&#xD;&#xA;            uint32_t uShadowLength;&#xD;&#xA;            uint32_t uShadowHeight;&#xD;&#xA;        } mTextureTracerUniforms;&#xD;&#xA;&#xD;&#xA;        uint32_t mTextureTracerProgram;&#xD;&#xA;&#xD;&#xA;        std::mt19937_64 mRNG;&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; mDistributionSun;&#xD;&#xA;        std::uniform_int_distribution&lt;uint32_t&gt; mDistributionWavelength;&#xD;&#xA;        std::bernoulli_distribution mDistributionBoolean;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;} // namespace gpu&#xD;&#xA;&#xD;&#xA;#endif // TEXTURE_TRACER_HPP&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.cpp&#xD;&#xA;```cpp&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;algorithm&gt;&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;&#xD;&#xA;void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,&#xD;&#xA;                                const GLchar *message, const void *userParam) {&#xD;&#xA;    if (type == GL_DEBUG_TYPE_ERROR)&#xD;&#xA;        fprintf(stderr, &quot;GL ERROR: type = 0x%x, severity = 0x%x, message = %s\n&quot;, type, severity, message);&#xD;&#xA;    else&#xD;&#xA;        fprintf(stdout, &quot;GL INFO: type = 0x%x, severity = 0x%x, message = %s\n&quot;, type, severity, message);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;    const double TEX_HEIGHT_TO_RADIUS_FACTOR = 4;&#xD;&#xA;    const double TEX_SHADOW_LENGTH_FACTOR = 8;&#xD;&#xA;&#xD;&#xA;    const uint32_t TEX_WIDTH = 1024u;&#xD;&#xA;    const uint32_t TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;    const double RADIUS = 6'371'000.0;&#xD;&#xA;    const double RADIUS_FACTORED = RADIUS * TEX_HEIGHT_TO_RADIUS_FACTOR;&#xD;&#xA;&#xD;&#xA;    const double SUN_RADIUS = 695'510'000.0;&#xD;&#xA;    const double DIST_TO_SUN = 149'600'000'000.0;&#xD;&#xA;    const double ATMO_HEIGHT = 42'000.0;&#xD;&#xA;&#xD;&#xA;    std::string loadShader(const std::string &amp;fileName) {&#xD;&#xA;        std::ifstream shaderFileStream(fileName, std::ios::in);&#xD;&#xA;        if (!shaderFileStream.is_open()) {&#xD;&#xA;            std::cerr &lt;&lt; &quot;Could not load the GLSL shader from '&quot; &lt;&lt; fileName &lt;&lt; &quot;'!&quot; &lt;&lt; std::endl;&#xD;&#xA;            exit(-1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        std::string shaderCode;&#xD;&#xA;        while (!shaderFileStream.eof()) {&#xD;&#xA;            std::string line;&#xD;&#xA;            std::getline(shaderFileStream, line);&#xD;&#xA;            shaderCode.append(line + &quot;\n&quot;);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return shaderCode;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void TextureTracer::initTextureTracer() {&#xD;&#xA;        mTextureTracerProgram = glCreateProgram();&#xD;&#xA;        uint32_t rayTracingComputeShader = glCreateShader(GL_COMPUTE_SHADER);&#xD;&#xA;&#xD;&#xA;        std::string code = loadShader(&quot;../resources/TextureTracer.glsl&quot;);&#xD;&#xA;        const char *shader = code.c_str();&#xD;&#xA;        glShaderSource(rayTracingComputeShader, 1, &amp;shader, nullptr);&#xD;&#xA;        glCompileShader(rayTracingComputeShader);&#xD;&#xA;&#xD;&#xA;        glAttachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;        glLinkProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        mTextureTracerUniforms.uRectangleHeight = glGetUniformLocation(mTextureTracerProgram, &quot;rectangleHeight&quot;);&#xD;&#xA;        mTextureTracerUniforms.uShadowHeight = glGetUniformLocation(mTextureTracerProgram, &quot;shadowHeight&quot;);&#xD;&#xA;        mTextureTracerUniforms.uShadowLength = glGetUniformLocation(mTextureTracerProgram, &quot;shadowLength&quot;);&#xD;&#xA;&#xD;&#xA;        glDetachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;        glDeleteShader(rayTracingComputeShader);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    TextureTracer::TextureTracer()&#xD;&#xA;            : mRNG(1L), mDistributionSun(std::uniform_real_distribution&lt;&gt;(-SUN_RADIUS, SUN_RADIUS)),&#xD;&#xA;              mDistributionWavelength(std::uniform_int_distribution&lt;uint32_t&gt;(380, 739)),&#xD;&#xA;              mDistributionBoolean(std::bernoulli_distribution(0.5)) {&#xD;&#xA;        glEnable(GL_DEBUG_OUTPUT);&#xD;&#xA;        glDebugMessageCallback(MessageCallback, nullptr);&#xD;&#xA;&#xD;&#xA;        initTextureTracer();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    double raySphereDistance(glm::dvec2 origin, glm::dvec2 direction, glm::dvec2 center, double radius) {&#xD;&#xA;        glm::dvec2 m = origin - center;&#xD;&#xA;        double b = glm::dot(m, direction);&#xD;&#xA;        double c = glm::dot(m, m) - (radius * radius);&#xD;&#xA;        if (c &gt; 0.0 &amp;&amp; b &gt; 0.0)&#xD;&#xA;            return -1.0;&#xD;&#xA;&#xD;&#xA;        double discr = b * b - c;&#xD;&#xA;&#xD;&#xA;        // A negative discriminant corresponds to ray missing sphere&#xD;&#xA;        if (discr &lt; 0.0)&#xD;&#xA;            return -1.0;&#xD;&#xA;&#xD;&#xA;        // Ray now found to intersect sphere, compute smallest t value of intersection&#xD;&#xA;        return glm::max(0.0, -b - glm::sqrt(discr));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Photon TextureTracer::emitPhoton() {&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; distributionEarth(0.0, ATMO_HEIGHT);&#xD;&#xA;        glm::dvec2 target = {0.0, RADIUS + distributionEarth(mRNG)};&#xD;&#xA;&#xD;&#xA;        double d;&#xD;&#xA;        do {&#xD;&#xA;            d = glm::length(glm::dvec2(mDistributionSun(mRNG), mDistributionSun(mRNG)));&#xD;&#xA;        } while (d &gt; SUN_RADIUS);&#xD;&#xA;&#xD;&#xA;        glm::dvec2 startPosition = glm::dvec2(-DIST_TO_SUN, mDistributionBoolean(mRNG) ? d : -d);&#xD;&#xA;        glm::dvec2 direction = glm::normalize(target - startPosition);&#xD;&#xA;&#xD;&#xA;        startPosition += direction * raySphereDistance(startPosition, direction, {0.0, 0.0},&#xD;&#xA;                                                       RADIUS + ATMO_HEIGHT);&#xD;&#xA;&#xD;&#xA;        return {glm::vec2(0.0, startPosition.y), glm::vec2(direction),&#xD;&#xA;                mDistributionWavelength(mRNG), 1.0f};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    std::vector&lt;Photon&gt; TextureTracer::generatePhotons(uint32_t count) {&#xD;&#xA;        std::vector&lt;Photon&gt; photons(count);&#xD;&#xA;        std::generate(photons.begin(), photons.end(), [this]() {&#xD;&#xA;            return emitPhoton();&#xD;&#xA;        });&#xD;&#xA;        return photons;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void TextureTracer::traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons) {&#xD;&#xA;        glUseProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uRectangleHeight, RADIUS_FACTORED / TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;        const double shadowLength = TEX_SHADOW_LENGTH_FACTOR * (DIST_TO_SUN * RADIUS) / (SUN_RADIUS - RADIUS);&#xD;&#xA;&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uShadowLength, shadowLength);&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uShadowHeight, RADIUS_FACTORED);&#xD;&#xA;&#xD;&#xA;        const double xAxisScalingFactor = glm::log(shadowLength) / glm::log(static_cast&lt;double&gt;(TEX_WIDTH));&#xD;&#xA;&#xD;&#xA;        std::vector&lt;glm::vec4&gt; horizontalRectangles = std::vector&lt;glm::vec4&gt;(TEX_WIDTH / 2);&#xD;&#xA;&#xD;&#xA;        double xx0 = 0.0;&#xD;&#xA;        for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;            const double xx1 = glm::pow(static_cast&lt;double&gt;(x + 1), xAxisScalingFactor);&#xD;&#xA;&#xD;&#xA;            if (x % 2 == 0) {&#xD;&#xA;                horizontalRectangles[x / 2].x = xx0;&#xD;&#xA;                horizontalRectangles[x / 2].y = xx1 - xx0;&#xD;&#xA;            } else {&#xD;&#xA;                horizontalRectangles[x / 2].z = xx0;&#xD;&#xA;                horizontalRectangles[x / 2].w = xx1 - xx0;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            xx0 = xx1;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        uint32_t uboRectangles;&#xD;&#xA;        glGenBuffers(1, &amp;uboRectangles);&#xD;&#xA;        glBindBuffer(GL_UNIFORM_BUFFER, uboRectangles);&#xD;&#xA;        glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) * horizontalRectangles.size(), horizontalRectangles.data(),&#xD;&#xA;                     GL_STATIC_READ);&#xD;&#xA;&#xD;&#xA;        const uint32_t MIN_WAVELENGTH = 380u;&#xD;&#xA;        const uint32_t MAX_WAVELENGTH = 740u;&#xD;&#xA;        const uint32_t NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;        size_t pixelBufferSize = TEX_WIDTH * TEX_HEIGHT * NUM_WAVELENGTHS * sizeof(uint32_t);&#xD;&#xA;        uint32_t ssboPixels;&#xD;&#xA;        glGenBuffers(1, &amp;ssboPixels);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, pixelBufferSize, nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboPhotons);&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboPixels);&#xD;&#xA;        glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboRectangles);&#xD;&#xA;&#xD;&#xA;        const uint32_t numThreads = 32u;&#xD;&#xA;        const uint32_t numBlocks = numPhotons / numThreads;&#xD;&#xA;        std::cout &lt;&lt; &quot;numBlocks: &quot; &lt;&lt; numBlocks &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;        glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;        struct Pixel {&#xD;&#xA;            uint32_t intensityAtWavelengths[NUM_WAVELENGTHS];&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        std::vector&lt;Pixel&gt; pixels(TEX_WIDTH * TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;        glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferSize, pixels.data());&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;        for (int y = 0; y &lt; TEX_HEIGHT; ++y) {&#xD;&#xA;            printf(&quot;%4i | &quot;, y);&#xD;&#xA;            for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;                Pixel p = pixels[y * TEX_WIDTH + x];&#xD;&#xA;                int counter = 0;&#xD;&#xA;                for (uint32_t i : p.intensityAtWavelengths) {&#xD;&#xA;                    counter += i;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (counter == 0) {&#xD;&#xA;                    printf(&quot;  &quot;);&#xD;&#xA;                } else if (counter &gt; 100'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A0&quot;);&#xD;&#xA;                } else if (counter &gt; 10'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A3&quot;);&#xD;&#xA;                } else if (counter &gt; 1'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A6&quot;);&#xD;&#xA;                } else if (counter &gt; 100'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A4&quot;);&#xD;&#xA;                } else {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A1&quot;);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            std::cout &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glDeleteBuffers(1, &amp;uboRectangles);&#xD;&#xA;        glDeleteBuffers(1, &amp;ssboPixels);&#xD;&#xA;&#xD;&#xA;        glUseProgram(0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    uint32_t TextureTracer::createShadowMap(size_t numPhotons) {&#xD;&#xA;        std::vector&lt;Photon&gt; photons = generatePhotons(numPhotons);&#xD;&#xA;&#xD;&#xA;        uint32_t ssboPhotons;&#xD;&#xA;        glGenBuffers(1, &amp;ssboPhotons);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPhotons);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Photon) * photons.size(), photons.data(), GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;        traceThroughTexture(ssboPhotons, photons.size());&#xD;&#xA;&#xD;&#xA;        glDeleteBuffers(1, &amp;ssboPhotons);&#xD;&#xA;        glDeleteProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        glDisable(GL_DEBUG_OUTPUT);&#xD;&#xA;        glDebugMessageCallback(nullptr, nullptr);&#xD;&#xA;&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;&#xD;&#xA;int main(int argc, char *argv[]) {&#xD;&#xA;    glutInit(&amp;argc, argv);&#xD;&#xA;    glutCreateWindow(&quot;Hurr durr OpenGL needs a window o.O&quot;);&#xD;&#xA;    glewInit();&#xD;&#xA;&#xD;&#xA;    auto mapper = gpu::TextureTracer();&#xD;&#xA;&#xD;&#xA;    // WITH 100'000 PHOTONS IT WORKS, WITH 1'000'000 PHOTONS NOT WHY?&#xD;&#xA;    mapper.createShadowMap(100'000);&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24588" PostHistoryTypeId="5" PostId="9027" RevisionGUID="e8a8585e-5b2e-4d06-b62c-e19508234bf6" CreationDate="2019-07-25T08:32:01.883" UserId="10952" Comment="edited body" Text="The shader takes an SSBO of Photons that have a position, direction, wavelength and intensity and each thread is responsible for tracing exactly one photon through the grid, where at each grid cell the photon hits, the intensity is accumulated for each wavelength to create a spectral distribution for each grid cell.&#xD;&#xA;&#xD;&#xA;The problem is that the shader works perfectly for 100,000 photons, but doesn't return a result for 1,000,000 photons.&#xD;&#xA;&#xD;&#xA;I looked into the sizes for the SSBOs and all were within my GPUs (NVIDIA Quadro P6000) limits of 2GB:&#xD;&#xA;&#xD;&#xA;- SSBO Grid size: **1.5GB**&#xD;&#xA;- SSBO Photons Size: **0.02GB**&#xD;&#xA;&#xD;&#xA;Even the UBO is within limits (**8KB** of allowed 16KB).&#xD;&#xA;&#xD;&#xA;If I change the logic at some places it works with one million photons (see lines 113 and 142 for comments).&#xD;&#xA;&#xD;&#xA;I currently can't see any explanation of why the shader fails for 1,000,000 photons, works for 100,000 photons. The logic is the same and the buffer sizes are within limits. (That the buffer size can't be a problem is also confirmed by that it works when changing the logic.)&#xD;&#xA;&#xD;&#xA;Below is the source code. If you want to try it yourself here is the code on github: https://github.com/TheJhonny007/TextureTracerDebug&#xD;&#xA;&#xD;&#xA;Compute Shader:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#extension GL_EXT_compute_shader: enable&#xD;&#xA;#extension GL_EXT_shader_storage_buffer_object: enable&#xD;&#xA;#extension GL_ARB_compute_variable_group_size: enable&#xD;&#xA;&#xD;&#xA;const uint TEX_WIDTH = 1024u;&#xD;&#xA;const uint TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const uint MIN_WAVELENGTH = 380u;&#xD;&#xA;const uint MAX_WAVELENGTH = 740u;&#xD;&#xA;const uint NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;// Size: 24 bytes -&gt; ~40,000,000 photons per available gigabyte of ram&#xD;&#xA;struct Photon {&#xD;&#xA;  vec2 position;// m&#xD;&#xA;  vec2 direction;// normalized&#xD;&#xA;  uint wavelength;// nm&#xD;&#xA;  float intensity;// 0..1 should start at 1&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer Photons {&#xD;&#xA;  Photon photons[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// Size: 1440 bytes -&gt; ~700,000 pixels per available gigabyte of ram&#xD;&#xA;struct Pixel {&#xD;&#xA;  uint intensityAtWavelengths[NUM_WAVELENGTHS];// [0..1000]&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 1) buffer Pixels {&#xD;&#xA;  //Pixel pixels[TEX_WIDTH][TEX_HEIGHT];&#xD;&#xA;  // NVIDIAs linker takes ages to link if the sizes are specified :(&#xD;&#xA;  Pixel[] pixels;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// x = x1, y = w1, z = x2, w = w2&#xD;&#xA;layout(std140, binding = 2) uniform HorizontalRectangles {&#xD;&#xA;  vec4 horizontalRectangles[TEX_WIDTH / 2u];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec2 getHorizontalRectangleAt(int i) {&#xD;&#xA;  vec4 entry = horizontalRectangles[i / 2];&#xD;&#xA;  if (i % 2 == 0) {&#xD;&#xA;    return entry.xy;&#xD;&#xA;  } else {&#xD;&#xA;    return entry.zw;&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float rectangleHeight;&#xD;&#xA;&#xD;&#xA;struct Rectangle {&#xD;&#xA;  float x;&#xD;&#xA;  float y;&#xD;&#xA;  float w;&#xD;&#xA;  float h;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout (local_size_variable) in;&#xD;&#xA;&#xD;&#xA;void addToPixel(uvec2 idx, uint wavelength, uint intensity) {&#xD;&#xA;  if (idx.x &gt;= 0u &amp;&amp; idx.x &lt; TEX_WIDTH &amp;&amp; idx.y &gt;= 0u &amp;&amp; idx.y &lt; TEX_HEIGHT) {&#xD;&#xA;    uint index = (idx.y * TEX_WIDTH) + idx.x;&#xD;&#xA;    atomicAdd(pixels[index].intensityAtWavelengths[wavelength - MIN_WAVELENGTH], intensity);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Returns the rectangle at the given indices.&#xD;&#xA;Rectangle getRectangleAt(ivec2 indices) {&#xD;&#xA;  vec2 horRect = getHorizontalRectangleAt(indices.x);&#xD;&#xA;  return Rectangle(horRect.x, rectangleHeight * float(indices.y), horRect.y, rectangleHeight);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Searches for the horizontal index in the rectangle array which contains x.&#xD;&#xA;int binarySearchForHorizontalRectangle(float x) {&#xD;&#xA;  int left = 0;&#xD;&#xA;  int right = int(TEX_WIDTH) - 1;&#xD;&#xA;&#xD;&#xA;  while (left &lt;= right) {&#xD;&#xA;    int middle = (left + right) / 2;&#xD;&#xA;    vec2 rectM = getHorizontalRectangleAt(middle);&#xD;&#xA;    if (rectM.x  + rectM.y &lt; x) {&#xD;&#xA;      left = middle + 1;&#xD;&#xA;    } else if (rectM.x &gt; x) {&#xD;&#xA;      right = middle - 1;&#xD;&#xA;    } else return middle;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  return int(TEX_WIDTH); // outside of grid (should never happen in any reasonable scenario...)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float shadowLength;&#xD;&#xA;uniform float shadowHeight;&#xD;&#xA;&#xD;&#xA;/// Returns the indices of the rectangle at the given location&#xD;&#xA;ivec2 getRectangleIdxAt(vec2 location) {&#xD;&#xA;  if (location.x &gt;= 0 &amp;&amp; location.x &lt; shadowLength &amp;&amp; location.y &gt;= 0 &amp;&amp; location.y &lt; shadowHeight) {&#xD;&#xA;    int x = binarySearchForHorizontalRectangle(location.x);&#xD;&#xA;    int y = int(location.y / rectangleHeight);&#xD;&#xA;    return ivec2(x, y);&#xD;&#xA;  } else return ivec2(TEX_WIDTH, TEX_HEIGHT);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getRayIntersectAtX(Photon ray, float x) {&#xD;&#xA;  float slope = ray.direction.y / ray.direction.x;&#xD;&#xA;  return slope * (x - ray.position.x) + ray.position.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec2 getRayRectangleExitEdge(Photon ray, Rectangle rect) {&#xD;&#xA;  float intersectHeight = getRayIntersectAtX(ray, rect.x + rect.w);&#xD;&#xA;&#xD;&#xA;  // IF ONE OF THE FIRST TWO CONDITIONS GETS REMOVED IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;  if (intersectHeight &lt; rect.y) {&#xD;&#xA;    return ivec2(0, -1);&#xD;&#xA;  } else if (intersectHeight &gt; rect.y + rect.h) {&#xD;&#xA;    return ivec2(0, 1);&#xD;&#xA;  } else {&#xD;&#xA;    return ivec2(1, 0);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;  if(gid &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;  Photon photon = photons[gid];&#xD;&#xA;&#xD;&#xA;  ivec2 photonTexIndices = getRectangleIdxAt(photon.position);&#xD;&#xA;  while (photonTexIndices.x &lt; TEX_WIDTH &amp;&amp; photonTexIndices.y &lt; TEX_HEIGHT &amp;&amp;&#xD;&#xA;  photonTexIndices.x &gt;= 0        &amp;&amp; photonTexIndices.y &gt;= 0) {&#xD;&#xA;    // need to convert to uint for atomic add operations...&#xD;&#xA;    addToPixel(uvec2(photonTexIndices), photon.wavelength, uint(photon.intensity * 100.0));&#xD;&#xA;&#xD;&#xA;    ivec2 dir = getRayRectangleExitEdge(photon, getRectangleAt(photonTexIndices));&#xD;&#xA;    photonTexIndices += dir;&#xD;&#xA;&#xD;&#xA;    // When the ray goes out of bounds on the bottom then mirror it to simulate rays coming from&#xD;&#xA;    // the other side of the planet. This works because of the rotational symmetry of the system.&#xD;&#xA;    // IF COMMENTET OUT IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;    if (photonTexIndices.y &lt; 0) {&#xD;&#xA;      photonTexIndices.y = 0;&#xD;&#xA;      photon.position.y *= -1.0;&#xD;&#xA;      photon.direction.y *= -1.0;&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.hpp&#xD;&#xA;```cpp&#xD;&#xA;#ifndef TEXTURE_TRACER_HPP&#xD;&#xA;#define TEXTURE_TRACER_HPP&#xD;&#xA;&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;&#xD;&#xA;    // 6 * 4 = 24 Bytes&#xD;&#xA;    struct Photon {&#xD;&#xA;        glm::vec2 position;  // m&#xD;&#xA;        glm::vec2 direction; // normalized&#xD;&#xA;        uint32_t waveLength; // nm&#xD;&#xA;        float intensity;     // 0..1 should start at 1&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    class TextureTracer {&#xD;&#xA;    public:&#xD;&#xA;        TextureTracer();&#xD;&#xA;        uint32_t createShadowMap(size_t numPhotons);&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        void initTextureTracer();&#xD;&#xA;        void traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons);&#xD;&#xA;        Photon emitPhoton();&#xD;&#xA;        std::vector&lt;Photon&gt; generatePhotons(uint32_t count);&#xD;&#xA;&#xD;&#xA;        struct {&#xD;&#xA;            uint32_t uRectangleHeight;&#xD;&#xA;            uint32_t uShadowLength;&#xD;&#xA;            uint32_t uShadowHeight;&#xD;&#xA;        } mTextureTracerUniforms;&#xD;&#xA;&#xD;&#xA;        uint32_t mTextureTracerProgram;&#xD;&#xA;&#xD;&#xA;        std::mt19937_64 mRNG;&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; mDistributionSun;&#xD;&#xA;        std::uniform_int_distribution&lt;uint32_t&gt; mDistributionWavelength;&#xD;&#xA;        std::bernoulli_distribution mDistributionBoolean;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;} // namespace gpu&#xD;&#xA;&#xD;&#xA;#endif // TEXTURE_TRACER_HPP&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.cpp&#xD;&#xA;```cpp&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;algorithm&gt;&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;&#xD;&#xA;void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,&#xD;&#xA;                                const GLchar *message, const void *userParam) {&#xD;&#xA;    if (type == GL_DEBUG_TYPE_ERROR)&#xD;&#xA;        fprintf(stderr, &quot;GL ERROR: type = 0x%x, severity = 0x%x, message = %s\n&quot;, type, severity, message);&#xD;&#xA;    else&#xD;&#xA;        fprintf(stdout, &quot;GL INFO: type = 0x%x, severity = 0x%x, message = %s\n&quot;, type, severity, message);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;    const double TEX_HEIGHT_TO_RADIUS_FACTOR = 4;&#xD;&#xA;    const double TEX_SHADOW_LENGTH_FACTOR = 8;&#xD;&#xA;&#xD;&#xA;    const uint32_t TEX_WIDTH = 1024u;&#xD;&#xA;    const uint32_t TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;    const double RADIUS = 6'371'000.0;&#xD;&#xA;    const double RADIUS_FACTORED = RADIUS * TEX_HEIGHT_TO_RADIUS_FACTOR;&#xD;&#xA;&#xD;&#xA;    const double SUN_RADIUS = 695'510'000.0;&#xD;&#xA;    const double DIST_TO_SUN = 149'600'000'000.0;&#xD;&#xA;    const double ATMO_HEIGHT = 42'000.0;&#xD;&#xA;&#xD;&#xA;    std::string loadShader(const std::string &amp;fileName) {&#xD;&#xA;        std::ifstream shaderFileStream(fileName, std::ios::in);&#xD;&#xA;        if (!shaderFileStream.is_open()) {&#xD;&#xA;            std::cerr &lt;&lt; &quot;Could not load the GLSL shader from '&quot; &lt;&lt; fileName &lt;&lt; &quot;'!&quot; &lt;&lt; std::endl;&#xD;&#xA;            exit(-1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        std::string shaderCode;&#xD;&#xA;        while (!shaderFileStream.eof()) {&#xD;&#xA;            std::string line;&#xD;&#xA;            std::getline(shaderFileStream, line);&#xD;&#xA;            shaderCode.append(line + &quot;\n&quot;);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return shaderCode;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void TextureTracer::initTextureTracer() {&#xD;&#xA;        mTextureTracerProgram = glCreateProgram();&#xD;&#xA;        uint32_t rayTracingComputeShader = glCreateShader(GL_COMPUTE_SHADER);&#xD;&#xA;&#xD;&#xA;        std::string code = loadShader(&quot;../resources/TextureTracer.glsl&quot;);&#xD;&#xA;        const char *shader = code.c_str();&#xD;&#xA;        glShaderSource(rayTracingComputeShader, 1, &amp;shader, nullptr);&#xD;&#xA;        glCompileShader(rayTracingComputeShader);&#xD;&#xA;&#xD;&#xA;        glAttachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;        glLinkProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        mTextureTracerUniforms.uRectangleHeight = glGetUniformLocation(mTextureTracerProgram, &quot;rectangleHeight&quot;);&#xD;&#xA;        mTextureTracerUniforms.uShadowHeight = glGetUniformLocation(mTextureTracerProgram, &quot;shadowHeight&quot;);&#xD;&#xA;        mTextureTracerUniforms.uShadowLength = glGetUniformLocation(mTextureTracerProgram, &quot;shadowLength&quot;);&#xD;&#xA;&#xD;&#xA;        glDetachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;        glDeleteShader(rayTracingComputeShader);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    TextureTracer::TextureTracer()&#xD;&#xA;            : mRNG(1L), mDistributionSun(std::uniform_real_distribution&lt;&gt;(-SUN_RADIUS, SUN_RADIUS)),&#xD;&#xA;              mDistributionWavelength(std::uniform_int_distribution&lt;uint32_t&gt;(380, 739)),&#xD;&#xA;              mDistributionBoolean(std::bernoulli_distribution(0.5)) {&#xD;&#xA;        glEnable(GL_DEBUG_OUTPUT);&#xD;&#xA;        glDebugMessageCallback(MessageCallback, nullptr);&#xD;&#xA;&#xD;&#xA;        initTextureTracer();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    double raySphereDistance(glm::dvec2 origin, glm::dvec2 direction, glm::dvec2 center, double radius) {&#xD;&#xA;        glm::dvec2 m = origin - center;&#xD;&#xA;        double b = glm::dot(m, direction);&#xD;&#xA;        double c = glm::dot(m, m) - (radius * radius);&#xD;&#xA;        if (c &gt; 0.0 &amp;&amp; b &gt; 0.0)&#xD;&#xA;            return -1.0;&#xD;&#xA;&#xD;&#xA;        double discr = b * b - c;&#xD;&#xA;&#xD;&#xA;        // A negative discriminant corresponds to ray missing sphere&#xD;&#xA;        if (discr &lt; 0.0)&#xD;&#xA;            return -1.0;&#xD;&#xA;&#xD;&#xA;        // Ray now found to intersect sphere, compute smallest t value of intersection&#xD;&#xA;        return glm::max(0.0, -b - glm::sqrt(discr));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Photon TextureTracer::emitPhoton() {&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; distributionEarth(0.0, ATMO_HEIGHT);&#xD;&#xA;        glm::dvec2 target = {0.0, RADIUS + distributionEarth(mRNG)};&#xD;&#xA;&#xD;&#xA;        double d;&#xD;&#xA;        do {&#xD;&#xA;            d = glm::length(glm::dvec2(mDistributionSun(mRNG), mDistributionSun(mRNG)));&#xD;&#xA;        } while (d &gt; SUN_RADIUS);&#xD;&#xA;&#xD;&#xA;        glm::dvec2 startPosition = glm::dvec2(-DIST_TO_SUN, mDistributionBoolean(mRNG) ? d : -d);&#xD;&#xA;        glm::dvec2 direction = glm::normalize(target - startPosition);&#xD;&#xA;&#xD;&#xA;        startPosition += direction * raySphereDistance(startPosition, direction, {0.0, 0.0},&#xD;&#xA;                                                       RADIUS + ATMO_HEIGHT);&#xD;&#xA;&#xD;&#xA;        return {glm::vec2(0.0, startPosition.y), glm::vec2(direction),&#xD;&#xA;                mDistributionWavelength(mRNG), 1.0f};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    std::vector&lt;Photon&gt; TextureTracer::generatePhotons(uint32_t count) {&#xD;&#xA;        std::vector&lt;Photon&gt; photons(count);&#xD;&#xA;        std::generate(photons.begin(), photons.end(), [this]() {&#xD;&#xA;            return emitPhoton();&#xD;&#xA;        });&#xD;&#xA;        return photons;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void TextureTracer::traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons) {&#xD;&#xA;        glUseProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uRectangleHeight, RADIUS_FACTORED / TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;        const double shadowLength = TEX_SHADOW_LENGTH_FACTOR * (DIST_TO_SUN * RADIUS) / (SUN_RADIUS - RADIUS);&#xD;&#xA;&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uShadowLength, shadowLength);&#xD;&#xA;        glUniform1f(mTextureTracerUniforms.uShadowHeight, RADIUS_FACTORED);&#xD;&#xA;&#xD;&#xA;        const double xAxisScalingFactor = glm::log(shadowLength) / glm::log(static_cast&lt;double&gt;(TEX_WIDTH));&#xD;&#xA;&#xD;&#xA;        std::vector&lt;glm::vec4&gt; horizontalRectangles = std::vector&lt;glm::vec4&gt;(TEX_WIDTH / 2);&#xD;&#xA;&#xD;&#xA;        double xx0 = 0.0;&#xD;&#xA;        for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;            const double xx1 = glm::pow(static_cast&lt;double&gt;(x + 1), xAxisScalingFactor);&#xD;&#xA;&#xD;&#xA;            if (x % 2 == 0) {&#xD;&#xA;                horizontalRectangles[x / 2].x = xx0;&#xD;&#xA;                horizontalRectangles[x / 2].y = xx1 - xx0;&#xD;&#xA;            } else {&#xD;&#xA;                horizontalRectangles[x / 2].z = xx0;&#xD;&#xA;                horizontalRectangles[x / 2].w = xx1 - xx0;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            xx0 = xx1;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        uint32_t uboRectangles;&#xD;&#xA;        glGenBuffers(1, &amp;uboRectangles);&#xD;&#xA;        glBindBuffer(GL_UNIFORM_BUFFER, uboRectangles);&#xD;&#xA;        glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::vec4) * horizontalRectangles.size(), horizontalRectangles.data(),&#xD;&#xA;                     GL_STATIC_READ);&#xD;&#xA;&#xD;&#xA;        const uint32_t MIN_WAVELENGTH = 380u;&#xD;&#xA;        const uint32_t MAX_WAVELENGTH = 740u;&#xD;&#xA;        const uint32_t NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;        size_t pixelBufferSize = TEX_WIDTH * TEX_HEIGHT * NUM_WAVELENGTHS * sizeof(uint32_t);&#xD;&#xA;        uint32_t ssboPixels;&#xD;&#xA;        glGenBuffers(1, &amp;ssboPixels);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, pixelBufferSize, nullptr, GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboPhotons);&#xD;&#xA;        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboPixels);&#xD;&#xA;        glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboRectangles);&#xD;&#xA;&#xD;&#xA;        const uint32_t numThreads = 32u;&#xD;&#xA;        const uint32_t numBlocks = numPhotons / numThreads;&#xD;&#xA;        std::cout &lt;&lt; &quot;numBlocks: &quot; &lt;&lt; numBlocks &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;        glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;        struct Pixel {&#xD;&#xA;            uint32_t intensityAtWavelengths[NUM_WAVELENGTHS];&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        std::vector&lt;Pixel&gt; pixels(TEX_WIDTH * TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;        glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferSize, pixels.data());&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;        for (int y = 0; y &lt; TEX_HEIGHT; ++y) {&#xD;&#xA;            printf(&quot;%4i | &quot;, y);&#xD;&#xA;            for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;                Pixel p = pixels[y * TEX_WIDTH + x];&#xD;&#xA;                int counter = 0;&#xD;&#xA;                for (uint32_t i : p.intensityAtWavelengths) {&#xD;&#xA;                    counter += i;&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                if (counter == 0) {&#xD;&#xA;                    printf(&quot;  &quot;);&#xD;&#xA;                } else if (counter &gt; 100'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A0&quot;);&#xD;&#xA;                } else if (counter &gt; 10'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A3&quot;);&#xD;&#xA;                } else if (counter &gt; 1'000'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A6&quot;);&#xD;&#xA;                } else if (counter &gt; 100'000) {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A4&quot;);&#xD;&#xA;                } else {&#xD;&#xA;                    printf(&quot;%4s&quot;, &quot;\u25A1&quot;);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            std::cout &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glDeleteBuffers(1, &amp;uboRectangles);&#xD;&#xA;        glDeleteBuffers(1, &amp;ssboPixels);&#xD;&#xA;&#xD;&#xA;        glUseProgram(0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    uint32_t TextureTracer::createShadowMap(size_t numPhotons) {&#xD;&#xA;        std::vector&lt;Photon&gt; photons = generatePhotons(numPhotons);&#xD;&#xA;&#xD;&#xA;        uint32_t ssboPhotons;&#xD;&#xA;        glGenBuffers(1, &amp;ssboPhotons);&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPhotons);&#xD;&#xA;        glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Photon) * photons.size(), photons.data(), GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;        traceThroughTexture(ssboPhotons, photons.size());&#xD;&#xA;&#xD;&#xA;        glDeleteBuffers(1, &amp;ssboPhotons);&#xD;&#xA;        glDeleteProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;        glDisable(GL_DEBUG_OUTPUT);&#xD;&#xA;        glDebugMessageCallback(nullptr, nullptr);&#xD;&#xA;&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;&#xD;&#xA;int main(int argc, char *argv[]) {&#xD;&#xA;    glutInit(&amp;argc, argv);&#xD;&#xA;    glutCreateWindow(&quot;Hurr durr OpenGL needs a window o.O&quot;);&#xD;&#xA;    glewInit();&#xD;&#xA;&#xD;&#xA;    auto mapper = gpu::TextureTracer();&#xD;&#xA;&#xD;&#xA;    // WITH 100'000 PHOTONS IT WORKS, WITH 1'000'000 PHOTONS NOT WHY?&#xD;&#xA;    mapper.createShadowMap(100'000);&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24589" PostHistoryTypeId="5" PostId="9027" RevisionGUID="1eac86f9-7c1a-4b86-a01a-416b81af3768" CreationDate="2019-07-25T08:50:48.390" UserId="10952" Comment="reduced code a little bit" Text="The shader takes an SSBO of Photons that have a position, direction, wavelength and intensity and each thread is responsible for tracing exactly one photon through the grid, where at each grid cell the photon hits, the intensity is accumulated for each wavelength to create a spectral distribution for each grid cell.&#xD;&#xA;&#xD;&#xA;The problem is that the shader works perfectly for 100,000 photons, but doesn't return a result for 1,000,000 photons.&#xD;&#xA;&#xD;&#xA;I looked into the sizes for the SSBOs and all were within my GPUs (NVIDIA Quadro P6000) limits of 2GB:&#xD;&#xA;&#xD;&#xA;- SSBO Grid size: **1.5GB**&#xD;&#xA;- SSBO Photons Size: **0.02GB**&#xD;&#xA;&#xD;&#xA;If I change the logic at some places it works with one million photons (see lines 113 and 142 for comments).&#xD;&#xA;&#xD;&#xA;I currently can't see any explanation of why the shader fails for 1,000,000 photons, but works for 100,000 photons. The logic is the same and the buffer sizes are within limits. (That the buffer size can't be a problem is also confirmed by that it works when changing the logic.)&#xD;&#xA;&#xD;&#xA;Below is the source code. If you want to try it yourself here is the code on github: https://github.com/TheJhonny007/TextureTracerDebug&#xD;&#xA;&#xD;&#xA;Compute Shader:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#extension GL_EXT_compute_shader: enable&#xD;&#xA;#extension GL_EXT_shader_storage_buffer_object: enable&#xD;&#xA;#extension GL_ARB_compute_variable_group_size: enable&#xD;&#xA;&#xD;&#xA;const uint TEX_WIDTH = 1024u;&#xD;&#xA;const uint TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const uint MIN_WAVELENGTH = 380u;&#xD;&#xA;const uint MAX_WAVELENGTH = 740u;&#xD;&#xA;const uint NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;// Size: 24 bytes -&gt; ~40,000,000 photons per available gigabyte of ram&#xD;&#xA;struct Photon {&#xD;&#xA;    vec2 position;// m&#xD;&#xA;    vec2 direction;// normalized&#xD;&#xA;    uint wavelength;// nm&#xD;&#xA;    float intensity;// 0..1 should start at 1&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer Photons {&#xD;&#xA;    Photon photons[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// Size: 1440 bytes -&gt; ~700,000 pixels per available gigabyte of ram&#xD;&#xA;struct Pixel {&#xD;&#xA;    uint intensityAtWavelengths[NUM_WAVELENGTHS];// [0..1000]&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 1) buffer Pixels {&#xD;&#xA;//Pixel pixels[TEX_WIDTH][TEX_HEIGHT];&#xD;&#xA;// NVIDIAs linker takes ages to link if the sizes are specified :(&#xD;&#xA;    Pixel[] pixels;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;uniform float xAxisScalingFactor;&#xD;&#xA;&#xD;&#xA;vec2 getHorizontalRectangleAt(int i) {&#xD;&#xA;    float x = pow(float(i), xAxisScalingFactor);&#xD;&#xA;    float w = pow(float(i + 1), xAxisScalingFactor);&#xD;&#xA;    return vec2(x, w);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float rectangleHeight;&#xD;&#xA;&#xD;&#xA;struct Rectangle {&#xD;&#xA;    float x;&#xD;&#xA;    float y;&#xD;&#xA;    float w;&#xD;&#xA;    float h;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout (local_size_variable) in;&#xD;&#xA;&#xD;&#xA;void addToPixel(uvec2 idx, uint wavelength, uint intensity) {&#xD;&#xA;    if (idx.x &gt;= 0u &amp;&amp; idx.x &lt; TEX_WIDTH &amp;&amp; idx.y &gt;= 0u &amp;&amp; idx.y &lt; TEX_HEIGHT) {&#xD;&#xA;        uint index = (idx.y * TEX_WIDTH) + idx.x;&#xD;&#xA;        atomicAdd(pixels[index].intensityAtWavelengths[wavelength - MIN_WAVELENGTH], intensity);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Returns the rectangle at the given indices.&#xD;&#xA;Rectangle getRectangleAt(ivec2 indices) {&#xD;&#xA;    vec2 horRect = getHorizontalRectangleAt(indices.x);&#xD;&#xA;    return Rectangle(horRect.x, rectangleHeight * float(indices.y), horRect.y, rectangleHeight);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float shadowLength;&#xD;&#xA;uniform float shadowHeight;&#xD;&#xA;&#xD;&#xA;/// Returns the indices of the rectangle at the given location&#xD;&#xA;ivec2 getRectangleIdxAt(vec2 location) {&#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = int(location.y / rectangleHeight);&#xD;&#xA;    return ivec2(x, y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getRayIntersectAtX(Photon ray, float x) {&#xD;&#xA;    float slope = ray.direction.y / ray.direction.x;&#xD;&#xA;    return slope * (x - ray.position.x) + ray.position.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec2 getRayRectangleExitEdge(Photon ray, Rectangle rect) {&#xD;&#xA;    float intersectHeight = getRayIntersectAtX(ray, rect.x + rect.w);&#xD;&#xA;&#xD;&#xA;    // IF ONE OF THE FIRST TWO CONDITIONS GETS REMOVED IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;    if (intersectHeight &lt; rect.y) {&#xD;&#xA;        return ivec2(0, -1);&#xD;&#xA;    } else if (intersectHeight &gt; rect.y + rect.h) {&#xD;&#xA;        return ivec2(0, 1);&#xD;&#xA;    } else {&#xD;&#xA;        return ivec2(1, 0);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;    if (gid &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;    Photon photon = photons[gid];&#xD;&#xA;&#xD;&#xA;    ivec2 photonTexIndices = getRectangleIdxAt(photon.position);&#xD;&#xA;    while (photonTexIndices.x &lt; TEX_WIDTH &amp;&amp; photonTexIndices.y &lt; TEX_HEIGHT &amp;&amp;&#xD;&#xA;    photonTexIndices.x &gt;= 0        &amp;&amp; photonTexIndices.y &gt;= 0) {&#xD;&#xA;        // need to convert to uint for atomic add operations...&#xD;&#xA;        addToPixel(uvec2(photonTexIndices), photon.wavelength, uint(photon.intensity * 100.0));&#xD;&#xA;&#xD;&#xA;        ivec2 dir = getRayRectangleExitEdge(photon, getRectangleAt(photonTexIndices));&#xD;&#xA;        photonTexIndices += dir;&#xD;&#xA;&#xD;&#xA;        // When the ray goes out of bounds on the bottom then mirror it to simulate rays coming from&#xD;&#xA;        // the other side of the planet. This works because of the rotational symmetry of the system.&#xD;&#xA;        // IF COMMENTET OUT IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;        if (photonTexIndices.y &lt; 0) {&#xD;&#xA;            photonTexIndices.y = 0;&#xD;&#xA;            photon.position.y *= -1.0;&#xD;&#xA;            photon.direction.y *= -1.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.hpp&#xD;&#xA;```cpp&#xD;&#xA;#ifndef TEXTURE_TRACER_HPP&#xD;&#xA;#define TEXTURE_TRACER_HPP&#xD;&#xA;&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;&#xD;&#xA;    // 6 * 4 = 24 Bytes&#xD;&#xA;    struct Photon {&#xD;&#xA;        glm::vec2 position;  // m&#xD;&#xA;        glm::vec2 direction; // normalized&#xD;&#xA;        uint32_t waveLength; // nm&#xD;&#xA;        float intensity;     // 0..1 should start at 1&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    class TextureTracer {&#xD;&#xA;    public:&#xD;&#xA;        TextureTracer();&#xD;&#xA;        uint32_t createShadowMap(size_t numPhotons);&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        void initTextureTracer();&#xD;&#xA;        void traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons);&#xD;&#xA;        Photon emitPhoton();&#xD;&#xA;        std::vector&lt;Photon&gt; generatePhotons(uint32_t count);&#xD;&#xA;&#xD;&#xA;        struct {&#xD;&#xA;            uint32_t uRectangleHeight;&#xD;&#xA;            uint32_t uShadowLength;&#xD;&#xA;            uint32_t uShadowHeight;&#xD;&#xA;            uint32_t uXAxisScalingFactor;&#xD;&#xA;        } mTextureTracerUniforms;&#xD;&#xA;&#xD;&#xA;        uint32_t mTextureTracerProgram;&#xD;&#xA;&#xD;&#xA;        std::mt19937_64 mRNG;&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; mDistributionSun;&#xD;&#xA;        std::uniform_int_distribution&lt;uint32_t&gt; mDistributionWavelength;&#xD;&#xA;        std::bernoulli_distribution mDistributionBoolean;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;} // namespace gpu&#xD;&#xA;&#xD;&#xA;#endif // TEXTURE_TRACER_HPP&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.cpp&#xD;&#xA;```cpp&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;algorithm&gt;&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;&#xD;&#xA;void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id,&#xD;&#xA;                                GLenum severity, GLsizei length,&#xD;&#xA;                                const GLchar *message, const void *userParam) {&#xD;&#xA;  if (type == GL_DEBUG_TYPE_ERROR)&#xD;&#xA;    fprintf(stderr, &quot;GL ERROR: type = 0x%x, severity = 0x%x, message = %s\n&quot;,&#xD;&#xA;            type, severity, message);&#xD;&#xA;  else&#xD;&#xA;    fprintf(stdout, &quot;GL INFO: type = 0x%x, severity = 0x%x, message = %s\n&quot;,&#xD;&#xA;            type, severity, message);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;const double TEX_HEIGHT_TO_RADIUS_FACTOR = 4;&#xD;&#xA;const double TEX_SHADOW_LENGTH_FACTOR = 8;&#xD;&#xA;&#xD;&#xA;const uint32_t TEX_WIDTH = 1024u;&#xD;&#xA;const uint32_t TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const double RADIUS = 6'371'000.0;&#xD;&#xA;const double RADIUS_FACTORED = RADIUS * TEX_HEIGHT_TO_RADIUS_FACTOR;&#xD;&#xA;&#xD;&#xA;const double SUN_RADIUS = 695'510'000.0;&#xD;&#xA;const double DIST_TO_SUN = 149'600'000'000.0;&#xD;&#xA;const double ATMO_HEIGHT = 42'000.0;&#xD;&#xA;&#xD;&#xA;std::string loadShader(const std::string &amp;fileName) {&#xD;&#xA;  std::ifstream shaderFileStream(fileName, std::ios::in);&#xD;&#xA;  if (!shaderFileStream.is_open()) {&#xD;&#xA;    std::cerr &lt;&lt; &quot;Could not load the GLSL shader from '&quot; &lt;&lt; fileName &lt;&lt; &quot;'!&quot;&#xD;&#xA;              &lt;&lt; std::endl;&#xD;&#xA;    exit(-1);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  std::string shaderCode;&#xD;&#xA;  while (!shaderFileStream.eof()) {&#xD;&#xA;    std::string line;&#xD;&#xA;    std::getline(shaderFileStream, line);&#xD;&#xA;    shaderCode.append(line + &quot;\n&quot;);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  return shaderCode;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void TextureTracer::initTextureTracer() {&#xD;&#xA;  mTextureTracerProgram = glCreateProgram();&#xD;&#xA;  uint32_t rayTracingComputeShader = glCreateShader(GL_COMPUTE_SHADER);&#xD;&#xA;&#xD;&#xA;  std::string code = loadShader(&quot;../resources/TextureTracer.glsl&quot;);&#xD;&#xA;  const char *shader = code.c_str();&#xD;&#xA;  glShaderSource(rayTracingComputeShader, 1, &amp;shader, nullptr);&#xD;&#xA;  glCompileShader(rayTracingComputeShader);&#xD;&#xA;&#xD;&#xA;  glAttachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;  glLinkProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;  mTextureTracerUniforms.uRectangleHeight =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;rectangleHeight&quot;);&#xD;&#xA;  mTextureTracerUniforms.uShadowHeight =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;shadowHeight&quot;);&#xD;&#xA;  mTextureTracerUniforms.uShadowLength =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;shadowLength&quot;);&#xD;&#xA;  mTextureTracerUniforms.uXAxisScalingFactor =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;xAxisScalingFactor&quot;);&#xD;&#xA;&#xD;&#xA;  glDetachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;  glDeleteShader(rayTracingComputeShader);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;TextureTracer::TextureTracer()&#xD;&#xA;    : mRNG(1L), mDistributionSun(&#xD;&#xA;                    std::uniform_real_distribution&lt;&gt;(-SUN_RADIUS, SUN_RADIUS)),&#xD;&#xA;      mDistributionWavelength(&#xD;&#xA;          std::uniform_int_distribution&lt;uint32_t&gt;(380, 739)),&#xD;&#xA;      mDistributionBoolean(std::bernoulli_distribution(0.5)) {&#xD;&#xA;  glEnable(GL_DEBUG_OUTPUT);&#xD;&#xA;  glDebugMessageCallback(MessageCallback, nullptr);&#xD;&#xA;&#xD;&#xA;  initTextureTracer();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;double raySphereDistance(glm::dvec2 origin, glm::dvec2 direction,&#xD;&#xA;                         glm::dvec2 center, double radius) {&#xD;&#xA;  glm::dvec2 m = origin - center;&#xD;&#xA;  double b = glm::dot(m, direction);&#xD;&#xA;  double c = glm::dot(m, m) - (radius * radius);&#xD;&#xA;  if (c &gt; 0.0 &amp;&amp; b &gt; 0.0)&#xD;&#xA;    return -1.0;&#xD;&#xA;&#xD;&#xA;  double discr = b * b - c;&#xD;&#xA;&#xD;&#xA;  // A negative discriminant corresponds to ray missing sphere&#xD;&#xA;  if (discr &lt; 0.0)&#xD;&#xA;    return -1.0;&#xD;&#xA;&#xD;&#xA;  // Ray now found to intersect sphere, compute smallest t value of intersection&#xD;&#xA;  return glm::max(0.0, -b - glm::sqrt(discr));&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Photon TextureTracer::emitPhoton() {&#xD;&#xA;  std::uniform_real_distribution&lt;&gt; distributionEarth(0.0, ATMO_HEIGHT);&#xD;&#xA;  glm::dvec2 target = {0.0, RADIUS + distributionEarth(mRNG)};&#xD;&#xA;&#xD;&#xA;  double d;&#xD;&#xA;  do {&#xD;&#xA;    d = glm::length(glm::dvec2(mDistributionSun(mRNG), mDistributionSun(mRNG)));&#xD;&#xA;  } while (d &gt; SUN_RADIUS);&#xD;&#xA;&#xD;&#xA;  glm::dvec2 startPosition =&#xD;&#xA;      glm::dvec2(-DIST_TO_SUN, mDistributionBoolean(mRNG) ? d : -d);&#xD;&#xA;  glm::dvec2 direction = glm::normalize(target - startPosition);&#xD;&#xA;&#xD;&#xA;  startPosition +=&#xD;&#xA;      direction * raySphereDistance(startPosition, direction, {0.0, 0.0},&#xD;&#xA;                                    RADIUS + ATMO_HEIGHT);&#xD;&#xA;&#xD;&#xA;  return {glm::vec2(0.0, startPosition.y), glm::vec2(direction),&#xD;&#xA;          mDistributionWavelength(mRNG), 1.0f};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;std::vector&lt;Photon&gt; TextureTracer::generatePhotons(uint32_t count) {&#xD;&#xA;  std::vector&lt;Photon&gt; photons(count);&#xD;&#xA;  std::generate(photons.begin(), photons.end(),&#xD;&#xA;                [this]() { return emitPhoton(); });&#xD;&#xA;  return photons;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void TextureTracer::traceThroughTexture(uint32_t ssboPhotons,&#xD;&#xA;                                        size_t numPhotons) {&#xD;&#xA;  glUseProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uRectangleHeight,&#xD;&#xA;              RADIUS_FACTORED / TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;  const double shadowLength =&#xD;&#xA;      TEX_SHADOW_LENGTH_FACTOR * (DIST_TO_SUN * RADIUS) / (SUN_RADIUS - RADIUS);&#xD;&#xA;&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uShadowLength, shadowLength);&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uShadowHeight, RADIUS_FACTORED);&#xD;&#xA;&#xD;&#xA;  const double xAxisScalingFactor =&#xD;&#xA;      glm::log(shadowLength) / glm::log(static_cast&lt;double&gt;(TEX_WIDTH));&#xD;&#xA;&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uXAxisScalingFactor,&#xD;&#xA;              static_cast&lt;float&gt;(xAxisScalingFactor));&#xD;&#xA;&#xD;&#xA;  const uint32_t MIN_WAVELENGTH = 380u;&#xD;&#xA;  const uint32_t MAX_WAVELENGTH = 740u;&#xD;&#xA;  const uint32_t NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;  size_t pixelBufferSize =&#xD;&#xA;      TEX_WIDTH * TEX_HEIGHT * NUM_WAVELENGTHS * sizeof(uint32_t);&#xD;&#xA;  uint32_t ssboPixels;&#xD;&#xA;  glGenBuffers(1, &amp;ssboPixels);&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;  glBufferData(GL_SHADER_STORAGE_BUFFER, pixelBufferSize, nullptr,&#xD;&#xA;               GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboPhotons);&#xD;&#xA;  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboPixels);&#xD;&#xA;&#xD;&#xA;  const uint32_t numThreads = 32u;&#xD;&#xA;  const uint32_t numBlocks = numPhotons / numThreads;&#xD;&#xA;  std::cout &lt;&lt; &quot;numBlocks: &quot; &lt;&lt; numBlocks &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;  glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;  glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;  struct Pixel {&#xD;&#xA;    uint32_t intensityAtWavelengths[NUM_WAVELENGTHS];&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  std::vector&lt;Pixel&gt; pixels(TEX_WIDTH * TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;  glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferSize,&#xD;&#xA;                     pixels.data());&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;  for (int y = 0; y &lt; TEX_HEIGHT; ++y) {&#xD;&#xA;    printf(&quot;%4i | &quot;, y);&#xD;&#xA;    for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;      Pixel p = pixels[y * TEX_WIDTH + x];&#xD;&#xA;      int counter = 0;&#xD;&#xA;      for (uint32_t i : p.intensityAtWavelengths) {&#xD;&#xA;        counter += i;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      if (counter == 0) {&#xD;&#xA;        printf(&quot;  &quot;);&#xD;&#xA;      } else if (counter &gt; 100'000'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A0&quot;);&#xD;&#xA;      } else if (counter &gt; 10'000'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A3&quot;);&#xD;&#xA;      } else if (counter &gt; 1'000'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A6&quot;);&#xD;&#xA;      } else if (counter &gt; 100'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A4&quot;);&#xD;&#xA;      } else {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A1&quot;);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    std::cout &lt;&lt; std::endl;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  glDeleteBuffers(1, &amp;ssboPixels);&#xD;&#xA;&#xD;&#xA;  glUseProgram(0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uint32_t TextureTracer::createShadowMap(size_t numPhotons) {&#xD;&#xA;  std::vector&lt;Photon&gt; photons = generatePhotons(numPhotons);&#xD;&#xA;&#xD;&#xA;  uint32_t ssboPhotons;&#xD;&#xA;  glGenBuffers(1, &amp;ssboPhotons);&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPhotons);&#xD;&#xA;  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Photon) * photons.size(),&#xD;&#xA;               photons.data(), GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;  traceThroughTexture(ssboPhotons, photons.size());&#xD;&#xA;&#xD;&#xA;  glDeleteBuffers(1, &amp;ssboPhotons);&#xD;&#xA;  glDeleteProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;  glDisable(GL_DEBUG_OUTPUT);&#xD;&#xA;  glDebugMessageCallback(nullptr, nullptr);&#xD;&#xA;&#xD;&#xA;  return 0;&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;&#xD;&#xA;int main(int argc, char *argv[]) {&#xD;&#xA;    glutInit(&amp;argc, argv);&#xD;&#xA;    glutCreateWindow(&quot;OpenGL needs a window o.O&quot;);&#xD;&#xA;    glewInit();&#xD;&#xA;&#xD;&#xA;    auto mapper = gpu::TextureTracer();&#xD;&#xA;&#xD;&#xA;    // WITH 100'000 PHOTONS IT WORKS, WITH 1'000'000 PHOTONS NOT WHY?&#xD;&#xA;    mapper.createShadowMap(100'000);&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="24590" PostHistoryTypeId="5" PostId="9027" RevisionGUID="e348dc44-e808-4b40-a03e-ad0175e3b97e" CreationDate="2019-07-25T09:03:21.583" UserId="10952" Comment="added 2 characters in body; deleted 1 character in body" Text="The shader takes an SSBO of Photons that have a position, direction, wavelength and intensity and each thread is responsible for tracing exactly one photon through the grid, where at each grid cell the photon hits, the intensity is accumulated for each wavelength to create a spectral distribution for each grid cell.&#xD;&#xA;&#xD;&#xA;The problem is that the shader works perfectly for 100,000 photons, but doesn't return a result for 1,000,000 photons.&#xD;&#xA;&#xD;&#xA;I looked into the sizes for the SSBOs and all were within my GPUs (NVIDIA Quadro P6000) limits of 2GB:&#xD;&#xA;&#xD;&#xA;- SSBO Grid size: **1.5GB**&#xD;&#xA;- SSBO Photons Size: **0.02GB**&#xD;&#xA;&#xD;&#xA;If I change the logic at some places it works with one million photons (see lines 87 and 114 for comments).&#xD;&#xA;&#xD;&#xA;I currently can't see any explanation of why the shader fails for 1,000,000 photons, but works for 100,000 photons. The logic is the same and the buffer sizes are within limits. (That the buffer size can't be a problem is also confirmed by that it works when changing the logic.)&#xD;&#xA;&#xD;&#xA;Below is the source code. If you want to try it yourself here is the code on github: https://github.com/TheJhonny007/TextureTracerDebug&#xD;&#xA;&#xD;&#xA;Compute Shader:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#extension GL_EXT_compute_shader: enable&#xD;&#xA;#extension GL_EXT_shader_storage_buffer_object: enable&#xD;&#xA;#extension GL_ARB_compute_variable_group_size: enable&#xD;&#xA;&#xD;&#xA;const uint TEX_WIDTH = 1024u;&#xD;&#xA;const uint TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const uint MIN_WAVELENGTH = 380u;&#xD;&#xA;const uint MAX_WAVELENGTH = 740u;&#xD;&#xA;const uint NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;// Size: 24 bytes -&gt; ~40,000,000 photons per available gigabyte of ram&#xD;&#xA;struct Photon {&#xD;&#xA;    vec2 position;// m&#xD;&#xA;    vec2 direction;// normalized&#xD;&#xA;    uint wavelength;// nm&#xD;&#xA;    float intensity;// 0..1 should start at 1&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer Photons {&#xD;&#xA;    Photon photons[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// Size: 1440 bytes -&gt; ~700,000 pixels per available gigabyte of ram&#xD;&#xA;struct Pixel {&#xD;&#xA;    uint intensityAtWavelengths[NUM_WAVELENGTHS];// [0..1000]&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 1) buffer Pixels {&#xD;&#xA;//Pixel pixels[TEX_WIDTH][TEX_HEIGHT];&#xD;&#xA;// NVIDIAs linker takes ages to link if the sizes are specified :(&#xD;&#xA;    Pixel[] pixels;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;uniform float xAxisScalingFactor;&#xD;&#xA;&#xD;&#xA;vec2 getHorizontalRectangleAt(int i) {&#xD;&#xA;    float x = pow(float(i), xAxisScalingFactor);&#xD;&#xA;    float w = pow(float(i + 1), xAxisScalingFactor);&#xD;&#xA;    return vec2(x, w);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float rectangleHeight;&#xD;&#xA;&#xD;&#xA;struct Rectangle {&#xD;&#xA;    float x;&#xD;&#xA;    float y;&#xD;&#xA;    float w;&#xD;&#xA;    float h;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout (local_size_variable) in;&#xD;&#xA;&#xD;&#xA;void addToPixel(uvec2 idx, uint wavelength, uint intensity) {&#xD;&#xA;    if (idx.x &gt;= 0u &amp;&amp; idx.x &lt; TEX_WIDTH &amp;&amp; idx.y &gt;= 0u &amp;&amp; idx.y &lt; TEX_HEIGHT) {&#xD;&#xA;        uint index = (idx.y * TEX_WIDTH) + idx.x;&#xD;&#xA;        atomicAdd(pixels[index].intensityAtWavelengths[wavelength - MIN_WAVELENGTH], intensity);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// Returns the rectangle at the given indices.&#xD;&#xA;Rectangle getRectangleAt(ivec2 indices) {&#xD;&#xA;    vec2 horRect = getHorizontalRectangleAt(indices.x);&#xD;&#xA;    return Rectangle(horRect.x, rectangleHeight * float(indices.y), horRect.y, rectangleHeight);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uniform float shadowLength;&#xD;&#xA;uniform float shadowHeight;&#xD;&#xA;&#xD;&#xA;/// Returns the indices of the rectangle at the given location&#xD;&#xA;ivec2 getRectangleIdxAt(vec2 location) {&#xD;&#xA;    int x = 0;&#xD;&#xA;    int y = int(location.y / rectangleHeight);&#xD;&#xA;    return ivec2(x, y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float getRayIntersectAtX(Photon ray, float x) {&#xD;&#xA;    float slope = ray.direction.y / ray.direction.x;&#xD;&#xA;    return slope * (x - ray.position.x) + ray.position.y;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec2 getRayRectangleExitEdge(Photon ray, Rectangle rect) {&#xD;&#xA;    float intersectHeight = getRayIntersectAtX(ray, rect.x + rect.w);&#xD;&#xA;&#xD;&#xA;    // IF ONE OF THE FIRST TWO CONDITIONS GETS REMOVED IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;    if (intersectHeight &lt; rect.y) {&#xD;&#xA;        return ivec2(0, -1);&#xD;&#xA;    } else if (intersectHeight &gt; rect.y + rect.h) {&#xD;&#xA;        return ivec2(0, 1);&#xD;&#xA;    } else {&#xD;&#xA;        return ivec2(1, 0);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;    if (gid &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;    Photon photon = photons[gid];&#xD;&#xA;&#xD;&#xA;    ivec2 photonTexIndices = getRectangleIdxAt(photon.position);&#xD;&#xA;    while (photonTexIndices.x &lt; TEX_WIDTH &amp;&amp; photonTexIndices.y &lt; TEX_HEIGHT &amp;&amp;&#xD;&#xA;    photonTexIndices.x &gt;= 0        &amp;&amp; photonTexIndices.y &gt;= 0) {&#xD;&#xA;        // need to convert to uint for atomic add operations...&#xD;&#xA;        addToPixel(uvec2(photonTexIndices), photon.wavelength, uint(photon.intensity * 100.0));&#xD;&#xA;&#xD;&#xA;        ivec2 dir = getRayRectangleExitEdge(photon, getRectangleAt(photonTexIndices));&#xD;&#xA;        photonTexIndices += dir;&#xD;&#xA;&#xD;&#xA;        // When the ray goes out of bounds on the bottom then mirror it to simulate rays coming from&#xD;&#xA;        // the other side of the planet. This works because of the rotational symmetry of the system.&#xD;&#xA;        // IF COMMENTET OUT IT WORKS WITH 1'000'000 PHOTONS OTHERWISE ONLY 100'000 WHY?&#xD;&#xA;        if (photonTexIndices.y &lt; 0) {&#xD;&#xA;            photonTexIndices.y = 0;&#xD;&#xA;            photon.position.y *= -1.0;&#xD;&#xA;            photon.direction.y *= -1.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.hpp&#xD;&#xA;```cpp&#xD;&#xA;#ifndef TEXTURE_TRACER_HPP&#xD;&#xA;#define TEXTURE_TRACER_HPP&#xD;&#xA;&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;&#xD;&#xA;    // 6 * 4 = 24 Bytes&#xD;&#xA;    struct Photon {&#xD;&#xA;        glm::vec2 position;  // m&#xD;&#xA;        glm::vec2 direction; // normalized&#xD;&#xA;        uint32_t waveLength; // nm&#xD;&#xA;        float intensity;     // 0..1 should start at 1&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    class TextureTracer {&#xD;&#xA;    public:&#xD;&#xA;        TextureTracer();&#xD;&#xA;        uint32_t createShadowMap(size_t numPhotons);&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        void initTextureTracer();&#xD;&#xA;        void traceThroughTexture(uint32_t ssboPhotons, size_t numPhotons);&#xD;&#xA;        Photon emitPhoton();&#xD;&#xA;        std::vector&lt;Photon&gt; generatePhotons(uint32_t count);&#xD;&#xA;&#xD;&#xA;        struct {&#xD;&#xA;            uint32_t uRectangleHeight;&#xD;&#xA;            uint32_t uShadowLength;&#xD;&#xA;            uint32_t uShadowHeight;&#xD;&#xA;            uint32_t uXAxisScalingFactor;&#xD;&#xA;        } mTextureTracerUniforms;&#xD;&#xA;&#xD;&#xA;        uint32_t mTextureTracerProgram;&#xD;&#xA;&#xD;&#xA;        std::mt19937_64 mRNG;&#xD;&#xA;        std::uniform_real_distribution&lt;&gt; mDistributionSun;&#xD;&#xA;        std::uniform_int_distribution&lt;uint32_t&gt; mDistributionWavelength;&#xD;&#xA;        std::bernoulli_distribution mDistributionBoolean;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;} // namespace gpu&#xD;&#xA;&#xD;&#xA;#endif // TEXTURE_TRACER_HPP&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Tracer.cpp&#xD;&#xA;```cpp&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;algorithm&gt;&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &lt;random&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;&#xD;&#xA;void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id,&#xD;&#xA;                                GLenum severity, GLsizei length,&#xD;&#xA;                                const GLchar *message, const void *userParam) {&#xD;&#xA;  if (type == GL_DEBUG_TYPE_ERROR)&#xD;&#xA;    fprintf(stderr, &quot;GL ERROR: type = 0x%x, severity = 0x%x, message = %s\n&quot;,&#xD;&#xA;            type, severity, message);&#xD;&#xA;  else&#xD;&#xA;    fprintf(stdout, &quot;GL INFO: type = 0x%x, severity = 0x%x, message = %s\n&quot;,&#xD;&#xA;            type, severity, message);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;namespace gpu {&#xD;&#xA;const double TEX_HEIGHT_TO_RADIUS_FACTOR = 4;&#xD;&#xA;const double TEX_SHADOW_LENGTH_FACTOR = 8;&#xD;&#xA;&#xD;&#xA;const uint32_t TEX_WIDTH = 1024u;&#xD;&#xA;const uint32_t TEX_HEIGHT = TEX_WIDTH;&#xD;&#xA;&#xD;&#xA;const double RADIUS = 6'371'000.0;&#xD;&#xA;const double RADIUS_FACTORED = RADIUS * TEX_HEIGHT_TO_RADIUS_FACTOR;&#xD;&#xA;&#xD;&#xA;const double SUN_RADIUS = 695'510'000.0;&#xD;&#xA;const double DIST_TO_SUN = 149'600'000'000.0;&#xD;&#xA;const double ATMO_HEIGHT = 42'000.0;&#xD;&#xA;&#xD;&#xA;std::string loadShader(const std::string &amp;fileName) {&#xD;&#xA;  std::ifstream shaderFileStream(fileName, std::ios::in);&#xD;&#xA;  if (!shaderFileStream.is_open()) {&#xD;&#xA;    std::cerr &lt;&lt; &quot;Could not load the GLSL shader from '&quot; &lt;&lt; fileName &lt;&lt; &quot;'!&quot;&#xD;&#xA;              &lt;&lt; std::endl;&#xD;&#xA;    exit(-1);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  std::string shaderCode;&#xD;&#xA;  while (!shaderFileStream.eof()) {&#xD;&#xA;    std::string line;&#xD;&#xA;    std::getline(shaderFileStream, line);&#xD;&#xA;    shaderCode.append(line + &quot;\n&quot;);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  return shaderCode;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void TextureTracer::initTextureTracer() {&#xD;&#xA;  mTextureTracerProgram = glCreateProgram();&#xD;&#xA;  uint32_t rayTracingComputeShader = glCreateShader(GL_COMPUTE_SHADER);&#xD;&#xA;&#xD;&#xA;  std::string code = loadShader(&quot;../resources/TextureTracer.glsl&quot;);&#xD;&#xA;  const char *shader = code.c_str();&#xD;&#xA;  glShaderSource(rayTracingComputeShader, 1, &amp;shader, nullptr);&#xD;&#xA;  glCompileShader(rayTracingComputeShader);&#xD;&#xA;&#xD;&#xA;  glAttachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;  glLinkProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;  mTextureTracerUniforms.uRectangleHeight =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;rectangleHeight&quot;);&#xD;&#xA;  mTextureTracerUniforms.uShadowHeight =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;shadowHeight&quot;);&#xD;&#xA;  mTextureTracerUniforms.uShadowLength =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;shadowLength&quot;);&#xD;&#xA;  mTextureTracerUniforms.uXAxisScalingFactor =&#xD;&#xA;      glGetUniformLocation(mTextureTracerProgram, &quot;xAxisScalingFactor&quot;);&#xD;&#xA;&#xD;&#xA;  glDetachShader(mTextureTracerProgram, rayTracingComputeShader);&#xD;&#xA;  glDeleteShader(rayTracingComputeShader);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;TextureTracer::TextureTracer()&#xD;&#xA;    : mRNG(1L), mDistributionSun(&#xD;&#xA;                    std::uniform_real_distribution&lt;&gt;(-SUN_RADIUS, SUN_RADIUS)),&#xD;&#xA;      mDistributionWavelength(&#xD;&#xA;          std::uniform_int_distribution&lt;uint32_t&gt;(380, 739)),&#xD;&#xA;      mDistributionBoolean(std::bernoulli_distribution(0.5)) {&#xD;&#xA;  glEnable(GL_DEBUG_OUTPUT);&#xD;&#xA;  glDebugMessageCallback(MessageCallback, nullptr);&#xD;&#xA;&#xD;&#xA;  initTextureTracer();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;double raySphereDistance(glm::dvec2 origin, glm::dvec2 direction,&#xD;&#xA;                         glm::dvec2 center, double radius) {&#xD;&#xA;  glm::dvec2 m = origin - center;&#xD;&#xA;  double b = glm::dot(m, direction);&#xD;&#xA;  double c = glm::dot(m, m) - (radius * radius);&#xD;&#xA;  if (c &gt; 0.0 &amp;&amp; b &gt; 0.0)&#xD;&#xA;    return -1.0;&#xD;&#xA;&#xD;&#xA;  double discr = b * b - c;&#xD;&#xA;&#xD;&#xA;  // A negative discriminant corresponds to ray missing sphere&#xD;&#xA;  if (discr &lt; 0.0)&#xD;&#xA;    return -1.0;&#xD;&#xA;&#xD;&#xA;  // Ray now found to intersect sphere, compute smallest t value of intersection&#xD;&#xA;  return glm::max(0.0, -b - glm::sqrt(discr));&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Photon TextureTracer::emitPhoton() {&#xD;&#xA;  std::uniform_real_distribution&lt;&gt; distributionEarth(0.0, ATMO_HEIGHT);&#xD;&#xA;  glm::dvec2 target = {0.0, RADIUS + distributionEarth(mRNG)};&#xD;&#xA;&#xD;&#xA;  double d;&#xD;&#xA;  do {&#xD;&#xA;    d = glm::length(glm::dvec2(mDistributionSun(mRNG), mDistributionSun(mRNG)));&#xD;&#xA;  } while (d &gt; SUN_RADIUS);&#xD;&#xA;&#xD;&#xA;  glm::dvec2 startPosition =&#xD;&#xA;      glm::dvec2(-DIST_TO_SUN, mDistributionBoolean(mRNG) ? d : -d);&#xD;&#xA;  glm::dvec2 direction = glm::normalize(target - startPosition);&#xD;&#xA;&#xD;&#xA;  startPosition +=&#xD;&#xA;      direction * raySphereDistance(startPosition, direction, {0.0, 0.0},&#xD;&#xA;                                    RADIUS + ATMO_HEIGHT);&#xD;&#xA;&#xD;&#xA;  return {glm::vec2(0.0, startPosition.y), glm::vec2(direction),&#xD;&#xA;          mDistributionWavelength(mRNG), 1.0f};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;std::vector&lt;Photon&gt; TextureTracer::generatePhotons(uint32_t count) {&#xD;&#xA;  std::vector&lt;Photon&gt; photons(count);&#xD;&#xA;  std::generate(photons.begin(), photons.end(),&#xD;&#xA;                [this]() { return emitPhoton(); });&#xD;&#xA;  return photons;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void TextureTracer::traceThroughTexture(uint32_t ssboPhotons,&#xD;&#xA;                                        size_t numPhotons) {&#xD;&#xA;  glUseProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uRectangleHeight,&#xD;&#xA;              RADIUS_FACTORED / TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;  const double shadowLength =&#xD;&#xA;      TEX_SHADOW_LENGTH_FACTOR * (DIST_TO_SUN * RADIUS) / (SUN_RADIUS - RADIUS);&#xD;&#xA;&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uShadowLength, shadowLength);&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uShadowHeight, RADIUS_FACTORED);&#xD;&#xA;&#xD;&#xA;  const double xAxisScalingFactor =&#xD;&#xA;      glm::log(shadowLength) / glm::log(static_cast&lt;double&gt;(TEX_WIDTH));&#xD;&#xA;&#xD;&#xA;  glUniform1f(mTextureTracerUniforms.uXAxisScalingFactor,&#xD;&#xA;              static_cast&lt;float&gt;(xAxisScalingFactor));&#xD;&#xA;&#xD;&#xA;  const uint32_t MIN_WAVELENGTH = 380u;&#xD;&#xA;  const uint32_t MAX_WAVELENGTH = 740u;&#xD;&#xA;  const uint32_t NUM_WAVELENGTHS = MAX_WAVELENGTH - MIN_WAVELENGTH;&#xD;&#xA;&#xD;&#xA;  size_t pixelBufferSize =&#xD;&#xA;      TEX_WIDTH * TEX_HEIGHT * NUM_WAVELENGTHS * sizeof(uint32_t);&#xD;&#xA;  uint32_t ssboPixels;&#xD;&#xA;  glGenBuffers(1, &amp;ssboPixels);&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;  glBufferData(GL_SHADER_STORAGE_BUFFER, pixelBufferSize, nullptr,&#xD;&#xA;               GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssboPhotons);&#xD;&#xA;  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssboPixels);&#xD;&#xA;&#xD;&#xA;  const uint32_t numThreads = 32u;&#xD;&#xA;  const uint32_t numBlocks = numPhotons / numThreads;&#xD;&#xA;  std::cout &lt;&lt; &quot;numBlocks: &quot; &lt;&lt; numBlocks &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;  glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;  glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;  struct Pixel {&#xD;&#xA;    uint32_t intensityAtWavelengths[NUM_WAVELENGTHS];&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  std::vector&lt;Pixel&gt; pixels(TEX_WIDTH * TEX_HEIGHT);&#xD;&#xA;&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPixels);&#xD;&#xA;  glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, pixelBufferSize,&#xD;&#xA;                     pixels.data());&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;  for (int y = 0; y &lt; TEX_HEIGHT; ++y) {&#xD;&#xA;    printf(&quot;%4i | &quot;, y);&#xD;&#xA;    for (int x = 0; x &lt; TEX_WIDTH; ++x) {&#xD;&#xA;      Pixel p = pixels[y * TEX_WIDTH + x];&#xD;&#xA;      int counter = 0;&#xD;&#xA;      for (uint32_t i : p.intensityAtWavelengths) {&#xD;&#xA;        counter += i;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      if (counter == 0) {&#xD;&#xA;        printf(&quot;  &quot;);&#xD;&#xA;      } else if (counter &gt; 100'000'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A0&quot;);&#xD;&#xA;      } else if (counter &gt; 10'000'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A3&quot;);&#xD;&#xA;      } else if (counter &gt; 1'000'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A6&quot;);&#xD;&#xA;      } else if (counter &gt; 100'000) {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A4&quot;);&#xD;&#xA;      } else {&#xD;&#xA;        printf(&quot;%4s&quot;, &quot;\u25A1&quot;);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    std::cout &lt;&lt; std::endl;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  glDeleteBuffers(1, &amp;ssboPixels);&#xD;&#xA;&#xD;&#xA;  glUseProgram(0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;uint32_t TextureTracer::createShadowMap(size_t numPhotons) {&#xD;&#xA;  std::vector&lt;Photon&gt; photons = generatePhotons(numPhotons);&#xD;&#xA;&#xD;&#xA;  uint32_t ssboPhotons;&#xD;&#xA;  glGenBuffers(1, &amp;ssboPhotons);&#xD;&#xA;  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssboPhotons);&#xD;&#xA;  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Photon) * photons.size(),&#xD;&#xA;               photons.data(), GL_DYNAMIC_COPY);&#xD;&#xA;&#xD;&#xA;  traceThroughTexture(ssboPhotons, photons.size());&#xD;&#xA;&#xD;&#xA;  glDeleteBuffers(1, &amp;ssboPhotons);&#xD;&#xA;  glDeleteProgram(mTextureTracerProgram);&#xD;&#xA;&#xD;&#xA;  glDisable(GL_DEBUG_OUTPUT);&#xD;&#xA;  glDebugMessageCallback(nullptr, nullptr);&#xD;&#xA;&#xD;&#xA;  return 0;&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;#include &lt;GL/glew.h&gt;&#xD;&#xA;#include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;#include &quot;TextureTracer.hpp&quot;&#xD;&#xA;&#xD;&#xA;int main(int argc, char *argv[]) {&#xD;&#xA;    glutInit(&amp;argc, argv);&#xD;&#xA;    glutCreateWindow(&quot;OpenGL needs a window o.O&quot;);&#xD;&#xA;    glewInit();&#xD;&#xA;&#xD;&#xA;    auto mapper = gpu::TextureTracer();&#xD;&#xA;&#xD;&#xA;    // WITH 100'000 PHOTONS IT WORKS, WITH 1'000'000 PHOTONS NOT WHY?&#xD;&#xA;    mapper.createShadowMap(100'000);&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24591" PostHistoryTypeId="5" PostId="8989" RevisionGUID="7c0b38fc-cd20-4666-83b1-f71dcb3a7c27" CreationDate="2019-07-25T13:45:27.580" UserId="6046" Comment="added 1 character in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. So far I'm getting some results but don't quite understand whether these are the expected images or not. I have extracted the necessary functions for converting &quot;.pvm&quot; file to &quot;.raw&quot; from V^3 package by [Stefan][2]. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][3]. My renderer give me,&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Comparing my images with the ones given on the site,&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Instead of mapping the single isovalue to all channels. I used the isovalue for alpha only and used a constant `0.07` for `rgb`. My foot ends up looking as in the below picture. This leads me to believe it's more of a transfer function problem?&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;So are my images wrong or the below images are using some fancy transfer functions? If so, how do you design these transfer functions? I searched the net but found very little information on how to do it.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][9]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, just adjusted it so it's in the center and accounted for the aspect ratio. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;I'm not posting it here since it's already this big. But if you want I can post it. Any help would be greatly appreciated since there isn't much matter on volume rendering and especially transfer functions over the net..&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://sourceforge.net/projects/volren/&#xD;&#xA;  [3]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [4]: https://i.stack.imgur.com/lbGYY.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/eqoJI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Diwng.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/rQ1ds.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/MxDQL.png&#xD;&#xA;  [9]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24595" PostHistoryTypeId="2" PostId="9029" RevisionGUID="cc5cae10-90b0-4f2e-bae7-4687757d1d15" CreationDate="2019-07-25T20:09:51.353" UserId="10955" Text="I have been trying to implement a simple GPU based volumetric renderer, somewhat similar to described [here][1]. I conceptually understand most of the stuff, and implemented some code, but my results are no where close to I would expect. Here is simple data I am trying to render. &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The 3D texture used was programmatically created by me; it’s a 256*256*256 arrays where each element contains 4 floats (RGBA). Most of the texture is just green color, with red and blue colored region in between. The final output I get is kind of “pixelated” and “blurry”; I was hoping that the boundary between green area and red/blue area would be crisp and sharp. Please note that each voxel in my array contains all the information about the RGBA component, and when I am firing rays onto the volume, I collect all the color information from the voxel and blend together. The 3D texture parameters GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER are set to GL_LINEAR and not to GL_NEAREST. Hence I am surprised why this pixelated appearance? Perhaps performing some kind of anti-aliasing might help, in which case I could fire multiple rays in slightly different direction for each fragment in my fragment shader and that would possibly smoothen the appearance? Moreover, do you think this could be because my volume is relatively small, only 256*256*256?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/9w0jz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24596" PostHistoryTypeId="1" PostId="9029" RevisionGUID="cc5cae10-90b0-4f2e-bae7-4687757d1d15" CreationDate="2019-07-25T20:09:51.353" UserId="10955" Text="Pixelated /aliased /blurry edges in volumetric rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="24597" PostHistoryTypeId="3" PostId="9029" RevisionGUID="cc5cae10-90b0-4f2e-bae7-4687757d1d15" CreationDate="2019-07-25T20:09:51.353" UserId="10955" Text="|antialiasing|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24598" PostHistoryTypeId="2" PostId="9030" RevisionGUID="0ac087d5-6fb1-4fb2-8311-18bd91233477" CreationDate="2019-07-26T08:40:04.667" UserId="10952" Text="Operating systems cancel GPU program executions if they take too long. On Windows it is generally two seconds and on Linux it is five seconds most of the time, but it can vary.&#xD;&#xA;&#xD;&#xA;This is to detect GPU programs that are stuck and cancel them. There are different methods to get around this timeout, but they all require admin/root privileges, which is not always available.&#xD;&#xA;&#xD;&#xA;If possible the execution can be split up into multiple invocations like in the following snippet:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;const uint32_t passSize   = 2048u;&#xD;&#xA;const uint32_t numPasses  = (numPhotons / passSize) + 1;&#xD;&#xA;const uint32_t numThreads = 64u;&#xD;&#xA;const uint32_t numBlocks  = passSize / numThreads;&#xD;&#xA;&#xD;&#xA;glUniform1ui(glGetUniformLocation(mTextureTracerProgram, &quot;passSize&quot;), passSize);&#xD;&#xA;for (uint32_t pass = 0u; pass &lt; numPasses; ++pass) {&#xD;&#xA;  glUniform1ui(glGetUniformLocation(mTextureTracerProgram, &quot;pass&quot;), pass);&#xD;&#xA;&#xD;&#xA;  glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;  glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;  glFlush();&#xD;&#xA;  glFinish();&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The `glFlush()` and `glFinish()` calls are important or the executions will get bundled together and the OS triggers a timeout anyways.&#xD;&#xA;&#xD;&#xA;In the shader you just need to access the right sections of the input data like so:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;// other stuff&#xD;&#xA;&#xD;&#xA;uniform uint pass;&#xD;&#xA;uniform uint passSize;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;  uint passId = pass * passSize + gid;&#xD;&#xA;  if (passId &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;  Photon photon = photons[passId];&#xD;&#xA;&#xD;&#xA;  // rest of program&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is all.&#xD;&#xA;&#xD;&#xA;If you want to disable the OS timeouts here is a relevant post for Linux: https://stackoverflow.com/a/30520538/5543884&#xD;&#xA;&#xD;&#xA;And here is a post regarding Windows: https://stackoverflow.com/a/29759823/5543884" ContentLicense="CC BY-SA 4.0" />
  <row Id="24599" PostHistoryTypeId="5" PostId="9030" RevisionGUID="016ae09c-7442-49ff-b3e0-a162ef8a456d" CreationDate="2019-07-26T09:03:13.480" UserId="10952" Comment="changed language from glsl to cpp, because there is no glsl highlighting in the CG stackexchange (why?)" Text="Operating systems cancel GPU program executions if they take too long. On Windows it is generally two seconds and on Linux it is five seconds most of the time, but it can vary.&#xD;&#xA;&#xD;&#xA;This is to detect GPU programs that are stuck and cancel them. There are different methods to get around this timeout, but they all require admin/root privileges, which is not always available.&#xD;&#xA;&#xD;&#xA;If possible the execution can be split up into multiple invocations like in the following snippet:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;const uint32_t passSize   = 2048u;&#xD;&#xA;const uint32_t numPasses  = (numPhotons / passSize) + 1;&#xD;&#xA;const uint32_t numThreads = 64u;&#xD;&#xA;const uint32_t numBlocks  = passSize / numThreads;&#xD;&#xA;&#xD;&#xA;glUniform1ui(glGetUniformLocation(mTextureTracerProgram, &quot;passSize&quot;), passSize);&#xD;&#xA;for (uint32_t pass = 0u; pass &lt; numPasses; ++pass) {&#xD;&#xA;  glUniform1ui(glGetUniformLocation(mTextureTracerProgram, &quot;pass&quot;), pass);&#xD;&#xA;&#xD;&#xA;  glDispatchComputeGroupSizeARB(numBlocks, 1, 1, numThreads, 1, 1);&#xD;&#xA;  glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;  glFlush();&#xD;&#xA;  glFinish();&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The `glFlush()` and `glFinish()` calls are important or the executions will get bundled together and the OS triggers a timeout anyways.&#xD;&#xA;&#xD;&#xA;In the shader you just need to access the right sections of the input data like so:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// other stuff&#xD;&#xA;&#xD;&#xA;uniform uint pass;&#xD;&#xA;uniform uint passSize;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  uint gid = gl_GlobalInvocationID.x;&#xD;&#xA;  uint passId = pass * passSize + gid;&#xD;&#xA;  if (passId &gt;= photons.length()) return;&#xD;&#xA;&#xD;&#xA;  Photon photon = photons[passId];&#xD;&#xA;&#xD;&#xA;  // rest of program&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is all.&#xD;&#xA;&#xD;&#xA;If you want to disable the OS timeouts here is a relevant post for Linux: https://stackoverflow.com/a/30520538/5543884&#xD;&#xA;&#xD;&#xA;And here is a post regarding Windows: https://stackoverflow.com/a/29759823/5543884" ContentLicense="CC BY-SA 4.0" />
  <row Id="24600" PostHistoryTypeId="2" PostId="9031" RevisionGUID="1026caf7-66d7-4cda-be65-203e782ea9cc" CreationDate="2019-07-26T14:36:58.483" UserId="8394" Text="As you said, the RTX Turing architecture comes with wired primitive-ray intersection, (to be more specific, triangle-ray intersection). The BVH is built by specifying the Bounding Box program to OptiX, the signature of which is:&#xD;&#xA;&#xD;&#xA;    RT_PROGRAM void my_boundingbox_build_program( int, float result[6] )&#xD;&#xA;&#xD;&#xA;As you can guess, the result must contain the minimun (3 first components) and maximum (3 last components) bounds of the bounding box. You can use this to build virtual bounding boxes even if you have no geometry (for instance, a chunk of 16x16x16 voxels).&#xD;&#xA;&#xD;&#xA;When you perform `rtTrace` , the OptiX API will detect the collision through the BVH which it has build with the help of your bounding box program. In that momment, it will call the Intersection program, which you can specify and which signature is:&#xD;&#xA;&#xD;&#xA;    RT_PROGRAM void my_intersection_program( int prim_index )&#xD;&#xA;&#xD;&#xA;Where you will report any possible intersection within your 16x16x16 chunk of voxels (obviously you can ignore the prim_index, which is only useful when using geometry primitives). &#xD;&#xA;&#xD;&#xA;Now, if you would use their special structure `RTgeometrytriangles` , the Turing RTX architecture would be able to make use of the wired primitive intersection, which is where performance boost would be gained, and you would not need to implement your own intersection program.&#xD;&#xA;&#xD;&#xA;To sumarize:&#xD;&#xA;Since you are not using the specific `RTgeometrytriangles` , you will not access the intersection performance boost from the Turing architecture." ContentLicense="CC BY-SA 4.0" />
  <row Id="24603" PostHistoryTypeId="2" PostId="9032" RevisionGUID="b81a2bd1-908a-4839-b420-a251e905429f" CreationDate="2019-07-27T01:32:03.067" UserId="10964" Text="Decoding video will result in different pixel formats on different GPUs and drivers. I have an application which can render (using OpenGL), only the RGB8 pixel format, therefore I need to do color conversion from the decoded pixel format to RGB8. I can access the gl... functions in this program but I cannot edit the shader, so I'm stuck with RGB8.&#xD;&#xA;&#xD;&#xA;This ffmpeg example demonstrates how to do hardware decoding: https://github.com/FFmpeg/FFmpeg/blob/release/4.2/doc/examples/hw_decode.c&#xD;&#xA;&#xD;&#xA;At line 109 it does this:&#xD;&#xA;&#xD;&#xA;    /* retrieve data from GPU to CPU */&#xD;&#xA;                if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) &lt; 0) {&#xD;&#xA;&#xD;&#xA;I want to avoid this because it takes time. Therefore, I need a way to reuse that decoded video, which is in GPU memory, to redo color conversion.&#xD;&#xA;&#xD;&#xA;Is it possible to create a shader program that takes input from the GPU memory, not CPU memory? If I want to pass image from CPU to my shader, I simply use `glTexImage2D`. Is there a similar way to do it but from GPU memory?&#xD;&#xA;&#xD;&#xA;Can I do even deeper and render the color decoded video on screen without copying from GPU memory too?&#xD;&#xA;&#xD;&#xA;If what I wanna do is possible, are there shader programs available to color convert pixels for some major graphics cards/drivers? I don't want to support all of them, but I'd like to support at least the Jetson Nano board from NVIDIA." ContentLicense="CC BY-SA 4.0" />
  <row Id="24604" PostHistoryTypeId="1" PostId="9032" RevisionGUID="b81a2bd1-908a-4839-b420-a251e905429f" CreationDate="2019-07-27T01:32:03.067" UserId="10964" Text="Is it possible to do color conversion on decoded video without getting it from GPUmemory to CPU memory?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24605" PostHistoryTypeId="3" PostId="9032" RevisionGUID="b81a2bd1-908a-4839-b420-a251e905429f" CreationDate="2019-07-27T01:32:03.067" UserId="10964" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24609" PostHistoryTypeId="2" PostId="9034" RevisionGUID="bdeaf982-e984-4e4c-b4b4-051333a8cdd9" CreationDate="2019-07-27T17:15:13.460" UserId="10129" Text="I ran into strange problem. My HLSL VS won't compile for given lines:&#xD;&#xA;&#xD;&#xA;    float2 finalUV = input.tex;&#xD;&#xA;	[branch] if(isHorizontal)&#xD;&#xA;	{&#xD;&#xA;		finalUV.y += finalOffset * stepLength;&#xD;&#xA;	}&#xD;&#xA;	else &#xD;&#xA;	{&#xD;&#xA;		finalUV.x += finalOffset * stepLength;&#xD;&#xA;	}	&#xD;&#xA;	float4 finalColor = float4(screenTexture.Sample(SampleType, finalUV).rgb, 1.0f);&#xD;&#xA;&#xD;&#xA;But when I remove **finalOffset** variable - then it's compile fine and works. This HLSL code is actually part of FXAA shader based on http://blog.simonrodriguez.fr/articles/30-07-2016_implementing_fxaa.html&#xD;&#xA;&#xD;&#xA;This code contains a lot of branching. I have no idea if that might be a problem. Here is my full HLSL code:&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;	////////////////////////////////////////////////////////////////////////////////&#xD;&#xA;	// Filename: fxaa.ps&#xD;&#xA;	////////////////////////////////////////////////////////////////////////////////&#xD;&#xA;&#xD;&#xA;	//Based on http://blog.simonrodriguez.fr/articles/30-07-2016_implementing_fxaa.html&#xD;&#xA;&#xD;&#xA;	Texture2D screenTexture : register(t0);&#xD;&#xA;	SamplerState SampleType : register(s0); &#xD;&#xA;&#xD;&#xA;	//////////////&#xD;&#xA;	// TYPEDEFS //&#xD;&#xA;	//////////////&#xD;&#xA;	struct PixelInputType&#xD;&#xA;	{&#xD;&#xA;		float4 position : SV_POSITION;&#xD;&#xA;		float2 tex: TEXCOORD0;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	float rgb2luma(float3 rgb);&#xD;&#xA;&#xD;&#xA;	static const float EDGE_THRESHOLD_MIN = 0.0312f;&#xD;&#xA;	static const float EDGE_THRESHOLD_MAX = 0.125f;&#xD;&#xA;	static const float SUBPIXEL_QUALITY = 0.75f;&#xD;&#xA;	static const int ITERATIONS = 12;&#xD;&#xA;	static const float QUALITY[ITERATIONS] = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 1.5f, 2.0f, 2.0f, 2.0f, 2.0f, 4.0f, 8.0f};&#xD;&#xA;	////////////////////////////////////////////////////////////////////////////////&#xD;&#xA;	// Pixel Shader&#xD;&#xA;	////////////////////////////////////////////////////////////////////////////////&#xD;&#xA;	float4 ColorPixelShader(PixelInputType input) : SV_TARGET&#xD;&#xA;	{&#xD;&#xA;	//TODO - Pass as parameter&#xD;&#xA;		float2 inverseScreenSize = float2(1.0f / 1280.0f, 1.0f / 720.0f);&#xD;&#xA;		&#xD;&#xA;		float3 colorCenter = screenTexture.Sample(SampleType, input.tex).rgb;	&#xD;&#xA;&#xD;&#xA;	//DETECT EDGES	&#xD;&#xA;		//Center luma&#xD;&#xA;		float lumaCenter = rgb2luma(colorCenter);&#xD;&#xA;		&#xD;&#xA;		//Direct neighbour luma&#xD;&#xA;		float lumaDown = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(0, -1)).rgb);&#xD;&#xA;		float lumaUp = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(0, 1)).rgb);&#xD;&#xA;		float lumaLeft = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(-1, 0)).rgb);&#xD;&#xA;		float lumaRight = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(1, 0)).rgb);&#xD;&#xA;		&#xD;&#xA;		//Find max, min luma&#xD;&#xA;		float lumaMin = min(lumaCenter, min(min(lumaDown, lumaUp), min(lumaLeft, lumaRight)));&#xD;&#xA;		float lumaMax = max(lumaCenter, max(max(lumaDown, lumaUp), max(lumaLeft, lumaRight)));&#xD;&#xA;		&#xD;&#xA;		//Delta (max-min)&#xD;&#xA;		float lumaRange = lumaMax - lumaMin;&#xD;&#xA;			&#xD;&#xA;		[branch] if (lumaRange &lt; max(EDGE_THRESHOLD_MIN, lumaMax * EDGE_THRESHOLD_MAX))&#xD;&#xA;		{&#xD;&#xA;			//Difference between lumas too small - there is no edge (or pixel is in very dark area)&#xD;&#xA;			return float4(colorCenter, 1.0f);&#xD;&#xA;		}&#xD;&#xA;	//CHOOSE EDGE DIRECTION&#xD;&#xA;		//Find corners lumas&#xD;&#xA;		float lumaDownLeft = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(-1, -1)).rgb);&#xD;&#xA;		float lumaUpRight = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(1, 1)).rgb);&#xD;&#xA;		float lumaUpLeft = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(-1, 1)).rgb);&#xD;&#xA;		float lumaDownRight = rgb2luma(screenTexture.Sample(SampleType, input.tex, float2(1, -1)).rgb);&#xD;&#xA;		&#xD;&#xA;		//Combine lumas for future computation&#xD;&#xA;		float lumaDownUp = lumaDown + lumaUp;&#xD;&#xA;		float lumaLeftRight = lumaLeft + lumaRight;&#xD;&#xA;		float lumaLeftCorners = lumaDownLeft + lumaUpLeft;&#xD;&#xA;		float lumaDownCorners = lumaDownLeft + lumaDownRight;&#xD;&#xA;		float lumaRightCorners = lumaDownRight + lumaUpRight;&#xD;&#xA;		float lumaUpCorners = lumaUpRight + lumaUpLeft;&#xD;&#xA;&#xD;&#xA;		//Calculate horiozntal/vertical edges&#xD;&#xA;		float edgeHorizontal =  abs(-2.0 * lumaLeft + lumaLeftCorners)  + abs(-2.0 * lumaCenter + lumaDownUp ) * 2.0    + abs(-2.0 * lumaRight + lumaRightCorners);&#xD;&#xA;		float edgeVertical =    abs(-2.0 * lumaUp + lumaUpCorners)      + abs(-2.0 * lumaCenter + lumaLeftRight) * 2.0  + abs(-2.0 * lumaDown + lumaDownCorners);&#xD;&#xA;		&#xD;&#xA;		//Check local edge direction&#xD;&#xA;		bool isHorizontal = (edgeHorizontal &gt;= edgeVertical);&#xD;&#xA;		&#xD;&#xA;		//Get lumas of pixels of opposite directions&#xD;&#xA;		float luma1 = isHorizontal ? lumaDown : lumaLeft;&#xD;&#xA;		float luma2 = isHorizontal ? lumaUp : lumaRight;&#xD;&#xA;		&#xD;&#xA;		//Calculate gradients for both&#xD;&#xA;		float gradient1 = luma1 - lumaCenter;&#xD;&#xA;		float gradient2 = luma2 - lumaCenter;&#xD;&#xA;		&#xD;&#xA;		//Check which direction is steepest&#xD;&#xA;		bool is1Steepest = abs(gradient1) &gt;= abs(gradient2);&#xD;&#xA;		&#xD;&#xA;		//Get strongest gradient and normalize it&#xD;&#xA;		float gradientScaled = 0.25f * max(abs(gradient1), abs(gradient2));&#xD;&#xA;		&#xD;&#xA;	//CALCULATE NEW UV&#xD;&#xA;		//Calculate step length based on screen size&#xD;&#xA;		float stepLength = isHorizontal ? inverseScreenSize.y : inverseScreenSize.x;&#xD;&#xA;		&#xD;&#xA;		//Average luma in correct direction&#xD;&#xA;		float lumaLocalAverage = 0.0f;&#xD;&#xA;		&#xD;&#xA;		[branch] if (is1Steepest)&#xD;&#xA;		{&#xD;&#xA;			//Switch direction, because is1Steepest indicates DOWN or LEFT&#xD;&#xA;			stepLength *= -1.0f;&#xD;&#xA;			lumaLocalAverage = 0.5f * (luma1 + lumaCenter);&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			lumaLocalAverage = 0.5f * (luma2 + lumaCenter);&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;		//Move UV by half a pixel to correct direction&#xD;&#xA;		float2 currentUV = input.tex;&#xD;&#xA;		[branch] if (isHorizontal)&#xD;&#xA;		{&#xD;&#xA;			currentUV.y += stepLength * 0.5f;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			currentUV.x += stepLength * 0.5f;&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;	//FIRST ITERATION&#xD;&#xA;		float2 offset = isHorizontal ? float2(inverseScreenSize.x, 0.0f) : float2(0.0f, inverseScreenSize.y);&#xD;&#xA;		&#xD;&#xA;		//Explore both sides&#xD;&#xA;		float2 uv1 = currentUV - offset;&#xD;&#xA;		float2 uv2 = currentUV + offset;&#xD;&#xA;		&#xD;&#xA;		//Read lumas from both extremes - find delta&#xD;&#xA;		float lumaEnd1 = rgb2luma(screenTexture.Sample(SampleType, uv1).rgb);&#xD;&#xA;		float lumaEnd2 = rgb2luma(screenTexture.Sample(SampleType, uv2).rgb);&#xD;&#xA;		lumaEnd1 -= lumaLocalAverage;&#xD;&#xA;		lumaEnd2 -= lumaLocalAverage;&#xD;&#xA;		&#xD;&#xA;		//If luma deltas is larger than local gradient - reached edge&#xD;&#xA;		bool reached1 = abs(lumaEnd1) &gt;= gradientScaled;&#xD;&#xA;		bool reached2 = abs(lumaEnd2) &gt;= gradientScaled;&#xD;&#xA;		bool reachedBoth = reached1 &amp;&amp; reached2;&#xD;&#xA;		&#xD;&#xA;		//If the side is not reached - continue exploration in given direction&#xD;&#xA;		[branch] if (!reached1)&#xD;&#xA;		{&#xD;&#xA;			uv1 -= offset;&#xD;&#xA;		}&#xD;&#xA;		[branch] if (!reached2)&#xD;&#xA;		{&#xD;&#xA;			uv2 += offset;&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;	//CONTINUE ITERATION&#xD;&#xA;		[branch] if (!reachedBoth)&#xD;&#xA;		{&#xD;&#xA;			for (int i = 2; i &lt; ITERATIONS; ++i)&#xD;&#xA;			{&#xD;&#xA;				[branch] if (!reached1)&#xD;&#xA;				{&#xD;&#xA;					lumaEnd1 = rgb2luma(screenTexture.Sample(SampleType, uv1).rgb);				&#xD;&#xA;					lumaEnd1 -= lumaLocalAverage;&#xD;&#xA;				}			&#xD;&#xA;				[branch] if (!reached2)&#xD;&#xA;				{&#xD;&#xA;					lumaEnd2 = rgb2luma(screenTexture.Sample(SampleType, uv2).rgb);&#xD;&#xA;					lumaEnd2 -= lumaLocalAverage;&#xD;&#xA;				}&#xD;&#xA;				reached1 = abs(lumaEnd1) &gt;= gradientScaled;&#xD;&#xA;				reached2 = abs(lumaEnd2) &gt;= gradientScaled;&#xD;&#xA;				reachedBoth = reached1 &amp;&amp; reached2;&#xD;&#xA;				&#xD;&#xA;				[branch] if(!reached1)&#xD;&#xA;					uv1 -= offset * QUALITY[i];&#xD;&#xA;			&#xD;&#xA;				[branch] if(!reached2)&#xD;&#xA;					uv2 += offset * QUALITY[i];&#xD;&#xA;					&#xD;&#xA;				[branch] if(reachedBoth)&#xD;&#xA;					break;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		&#xD;&#xA;	//ESTIMATE OFFSET&#xD;&#xA;		float distance1 = isHorizontal ? (input.tex.x - uv1.x) : (input.tex.y - uv1.y);&#xD;&#xA;		float distance2 = isHorizontal ? (uv2.x - input.tex.x) : (uv2.y - input.tex.y);&#xD;&#xA;		&#xD;&#xA;		//Get dinal distance with direction&#xD;&#xA;		bool isDirection1 = distance1 &lt; distance2;&#xD;&#xA;		float distanceFinal = min(distance1, distance2);&#xD;&#xA;		&#xD;&#xA;		//Length of edge&#xD;&#xA;		float edgeThickness = (distance1 + distance2);&#xD;&#xA;		&#xD;&#xA;		//UV offset&#xD;&#xA;		float pixelOffset = -distanceFinal/edgeThickness + 0.5f;&#xD;&#xA;		&#xD;&#xA;	//CHECK LUMA&#xD;&#xA;		bool isLumaCenterSmaller = lumaCenter &lt; lumaLocalAverage;&#xD;&#xA;		&#xD;&#xA;		// If the luma at center is smaller than at its neighbour, the delta luma at each end should be positive (same variation).&#xD;&#xA;		// (in the direction of the closer side of the edge.)&#xD;&#xA;		bool correctVariation = ((isDirection1 ? lumaEnd1 : lumaEnd2) &lt; 0.0f) != isLumaCenterSmaller;&#xD;&#xA;		&#xD;&#xA;		//If the luma variation is incorrect, do not offset&#xD;&#xA;		float finalOffset = correctVariation ? pixelOffset : 0.0f;&#xD;&#xA;		&#xD;&#xA;	//SUBPIXEL ANTIALIASING&#xD;&#xA;		//Weighted average&#xD;&#xA;		float lumaAverage = (1.0f / 12.0f) * (2.0f * (lumaDownUp + lumaLeftRight)) + lumaLeftCorners + lumaRightCorners;&#xD;&#xA;		//Radio of the delta between global average and the center luma&#xD;&#xA;		float subPixelOffset1 = clamp(abs(lumaAverage - lumaCenter) / lumaRange, 0.0f, 1.0f);&#xD;&#xA;		float subPixelOffset2 = (-2.0f * subPixelOffset1 + 3.0f) * subPixelOffset1 * subPixelOffset1;&#xD;&#xA;		&#xD;&#xA;		float subPixelOffsetFinal = subPixelOffset2 * subPixelOffset2 * SUBPIXEL_QUALITY;&#xD;&#xA;		// Pick the biggest of the two offsets.&#xD;&#xA;		finalOffset = max(finalOffset, subPixelOffsetFinal);&#xD;&#xA;&#xD;&#xA;	//FINAL READ	&#xD;&#xA;		float2 finalUV = input.tex;&#xD;&#xA;		[branch] if(isHorizontal)&#xD;&#xA;		{&#xD;&#xA;			finalUV.y += finalOffset * stepLength;&#xD;&#xA;		}&#xD;&#xA;		else &#xD;&#xA;		{&#xD;&#xA;			finalUV.x += finalOffset * stepLength;&#xD;&#xA;		}	&#xD;&#xA;		float4 finalColor = float4(screenTexture.Sample(SampleType, finalUV).rgb, 1.0f);&#xD;&#xA;		&#xD;&#xA;		return finalColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float rgb2luma(float3 rgb)&#xD;&#xA;	{&#xD;&#xA;		return sqrt(dot(rgb, float3(0.299f, 0.587f, 0.114f)));&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="24610" PostHistoryTypeId="1" PostId="9034" RevisionGUID="bdeaf982-e984-4e4c-b4b4-051333a8cdd9" CreationDate="2019-07-27T17:15:13.460" UserId="10129" Text="Cannot use variable as texture sample value - HLSL DirectX11" ContentLicense="CC BY-SA 4.0" />
  <row Id="24611" PostHistoryTypeId="3" PostId="9034" RevisionGUID="bdeaf982-e984-4e4c-b4b4-051333a8cdd9" CreationDate="2019-07-27T17:15:13.460" UserId="10129" Text="|directx11|hlsl|pixel-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24612" PostHistoryTypeId="50" PostId="6094" RevisionGUID="caae19b3-78eb-44cb-95c9-d03ddcc5ce73" CreationDate="2019-07-27T18:00:35.410" UserId="-1" />
  <row Id="24613" PostHistoryTypeId="2" PostId="9035" RevisionGUID="71e1f413-b2e6-48a2-939a-767d918b4e18" CreationDate="2019-07-27T23:23:40.850" UserId="3003" Text="So it sounds like the main issue you're having is how to render something when all resources are already on the GPU. I would do it like this:&#xD;&#xA;&#xD;&#xA; 1. Create the destination RGB texture that's the proper width and height&#xD;&#xA; 2. Create an FBO&#xD;&#xA; 3. Set the texture created in step 1 as the output (write) texture of the FBO&#xD;&#xA; 4. Bind the NV12 texture to the texture unit you'll use in your shader&#xD;&#xA; 5. Draw a textured quad that covers the entire output&#xD;&#xA; 6. Apply a shader that samples the NV12 texture to generate the RGB value at each fragment&#xD;&#xA;&#xD;&#xA;For step 1 you use `glGenTextures()` and `glTexImage2D()`.&#xD;&#xA;&#xD;&#xA;For steps 2 and 3 you use `glGenFramebuffers()` and `glBindFramebuffer()` passing `glBindFramebuffer()` the texture created in step 1 to attach it to `GL_COLOR_ATTACHMENT0`. (See [here](https://www.khronos.org/opengl/wiki/Framebuffer_Object) for more details.)&#xD;&#xA;&#xD;&#xA;For step 4 you use `glBindTexture()`.&#xD;&#xA;&#xD;&#xA;For step 5 you can simply draw a quad that goes from (-1, -1) to (1, 1). You don't need any model view matrix or anything.&#xD;&#xA;&#xD;&#xA;For step 6 you'll need to calculate where the red, green, and blue samples that correspond to the current output pixel are in the input texture and then sample them using the `texture()` function. You'll need to do 3 different look-ups for each output pixel. [This link has C code](http://paulbourke.net/dataformats/nv12/) for figuring out where each sample is from. &#xD;&#xA;&#xD;&#xA;Once you're done you can delete the frame buffer and use the texture created in step 1 in your next step (display it, process it, save it to disk, or whatever)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24614" PostHistoryTypeId="5" PostId="8989" RevisionGUID="fba148e8-48dc-45ce-97c2-691f43307ade" CreationDate="2019-07-28T13:13:08.997" UserId="6046" Comment="added 521 characters in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. So far I'm getting some results but don't quite understand whether these are the expected images or not. I have extracted the necessary functions for converting &quot;.pvm&quot; file to &quot;.raw&quot; from V^3 package by [Stefan][2]. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][3]. My renderer give me,&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Comparing my images with the ones given on the site,&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;Instead of mapping the single isovalue to all channels. I used the isovalue for alpha only and used a constant `0.07` for `rgb`. My foot ends up looking as in the below picture. This leads me to believe it's more of a transfer function problem?&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;So are my images wrong or the below images are using some fancy transfer functions? If so, how do you design these transfer functions? I searched the net but found very little information on how to do it.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][9]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, just adjusted it so it's in the center and accounted for the aspect ratio. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;I'm not posting it here since it's already this big. But if you want I can post it. Any help would be greatly appreciated since there isn't much matter on volume rendering and especially transfer functions over the net..&#xD;&#xA;&#xD;&#xA;**UPDATE:-** So I posted this on [reddit][10] as well and got a few advices. I tried only the first 20 rendering slices and apparently there was random white noise in my images which got removed by rendering only first 20 slices. (not seen here since all images here except lobster have alpha scaled by 0.01). &#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://sourceforge.net/projects/volren/&#xD;&#xA;  [3]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [4]: https://i.stack.imgur.com/lbGYY.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/eqoJI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/Diwng.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/rQ1ds.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/MxDQL.png&#xD;&#xA;  [9]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs&#xD;&#xA;  [10]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [11]: https://i.stack.imgur.com/6RNWo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24622" PostHistoryTypeId="2" PostId="9038" RevisionGUID="e12fa7d8-e687-4e98-8928-ecfefaaf5ab5" CreationDate="2019-07-29T13:50:29.943" UserId="10976" Text="I would like to know which is the most important ? More particularly in games or for the display of a desk (ex KDE Plasma, Windows 10 ...) ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24623" PostHistoryTypeId="1" PostId="9038" RevisionGUID="e12fa7d8-e687-4e98-8928-ecfefaaf5ab5" CreationDate="2019-07-29T13:50:29.943" UserId="10976" Text="Which is more important : Texel or Pixel rate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24624" PostHistoryTypeId="3" PostId="9038" RevisionGUID="e12fa7d8-e687-4e98-8928-ecfefaaf5ab5" CreationDate="2019-07-29T13:50:29.943" UserId="10976" Text="|rendering|texture|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24626" PostHistoryTypeId="2" PostId="9039" RevisionGUID="f260f000-9f1c-4da6-a21b-1c24ed6a1c0d" CreationDate="2019-07-30T02:28:11.250" UserId="10980" Text="As described in [PBRT 14.5](http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html), the path tracer stops bouncing rays at a probability `q`, which is determined by the throughput of the path.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&lt;&lt;Possibly terminate the path with Russian roulette&gt;&gt;= &#xD;&#xA;if (bounces &gt; 3) {&#xD;&#xA;    Float q = std::max((Float).05, 1 - beta.y());&#xD;&#xA;    if (sampler.Get1D() &lt; q)&#xD;&#xA;        break;&#xD;&#xA;    beta /= 1 - q;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;In my understanding, the probability `q` should be a constant for paths of the same length, so that the Russian roulette estimator is unbiased. Would such a dynamic termination probability still produce biased results?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24627" PostHistoryTypeId="1" PostId="9039" RevisionGUID="f260f000-9f1c-4da6-a21b-1c24ed6a1c0d" CreationDate="2019-07-30T02:28:11.250" UserId="10980" Text="The termination probability of Russian roulette in PBRT" ContentLicense="CC BY-SA 4.0" />
  <row Id="24628" PostHistoryTypeId="3" PostId="9039" RevisionGUID="f260f000-9f1c-4da6-a21b-1c24ed6a1c0d" CreationDate="2019-07-30T02:28:11.250" UserId="10980" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24632" PostHistoryTypeId="10" PostId="9038" RevisionGUID="b307b9b7-4416-4b50-86f6-db0431e5c5fe" CreationDate="2019-07-30T08:13:28.403" UserId="2041" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2041,&quot;DisplayName&quot;:&quot;Dan Hulme&quot;}]}" />
  <row Id="24634" PostHistoryTypeId="5" PostId="9039" RevisionGUID="422fc53a-d13c-450e-961a-b0ae8e19c34d" CreationDate="2019-07-31T04:46:43.627" UserId="10980" Comment="Add further expanation of my confusion" Text="As described in [PBRT 14.5](http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html), the path tracer stops bouncing rays at a probability `q`, which is determined by the throughput of the path.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&lt;&lt;Possibly terminate the path with Russian roulette&gt;&gt;= &#xD;&#xA;if (bounces &gt; 3) {&#xD;&#xA;    Float q = std::max((Float).05, 1 - beta.y());&#xD;&#xA;    if (sampler.Get1D() &lt; q)&#xD;&#xA;        break;&#xD;&#xA;    beta /= 1 - q;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;In my understanding, the probability `q` should be a constant for paths of the same length, so that the Russian roulette estimator is unbiased. Would such a dynamic termination probability still produce biased results?&#xD;&#xA;&#xD;&#xA;Update:&#xD;&#xA;&#xD;&#xA;Given an estimator `F`, its corresponding Russian roulette estimator is defined to be&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;R = (F - qc) / (1 - q) , if xi &gt; q&#xD;&#xA;R = c                  , otherwise&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Since `E[R] = (1 - q)(E[F] - qc) / (1 - q) + qc = E[F]`, as long as `F` is a unbiased estimator, `R` is a unbiased estimator as well.&#xD;&#xA;&#xD;&#xA;Specific to a path tracer, its path-integral form of LTE with Russian roulette can be written as&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;1 / (1 - q1)(P(p1) + 1 / (1 - q2)(P(p2) + 1 / (1 - q3)(P(p3) + ...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;if `q1, q2, qc, ...` is not a constant, then the estimator for each path length is not an unbiased estimator, I think." ContentLicense="CC BY-SA 4.0" />
  <row Id="24635" PostHistoryTypeId="5" PostId="8983" RevisionGUID="ec707926-619a-4cb7-9acb-5a505c47b8e5" CreationDate="2019-08-01T05:44:24.690" UserId="9420" Comment="Updated notation to match answer" Text="In the definition of Radiance, which according to PBRT is defined as&#xD;&#xA;&gt; flux per unit solid angle $d\omega$ per unit projected area $dA^\perp$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$L_i=\frac{d\Phi}{d\omega\ dA^\perp}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My original assumption was that the $dA^\perp$ term is used to weaken the irradiance contribution due to the incident angle (which I assume is just Lambert's cosine law). However, in the rendering equation, we've already explicitly apply Lambert's law with the $\cos\theta$ term:  &#xD;&#xA;$$\int_\Omega L_i(\omega_{i}) \, f_r(\omega_{i}\rightarrow \omega_{o}) \, \cos\theta_{i} \, d\omega_{i}$$&#xD;&#xA;&#xD;&#xA;I assume we arn't applying Lambert's law twice, so what exactly is this $dA^\perp$ term?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24639" PostHistoryTypeId="5" PostId="6267" RevisionGUID="49904753-64dc-4bd0-a474-f14dbdfe2d46" CreationDate="2019-08-02T08:17:15.157" UserId="7008" Comment="fixed a typo in a formula" Text="&gt; The second matrix translates the eye [...]&#xD;&#xA;&#xD;&#xA;You don't do that in a projection matrix. You do that with your view matrix:&#xD;&#xA;&#xD;&#xA; 1. Model (/Object) Matrix transforms an object into World Space&#xD;&#xA; 2. View Matrix transforms all objects from world space to Eye (/Camera) Space (no projection so far!)&#xD;&#xA; 3. Projection Matrix transforms from Eye Space to Clip Space&#xD;&#xA;&#xD;&#xA;Therefore you don't do any matrix multiplications to get to a projection matrix. Those multiplications happen in the shader, where you do $Projection\cdot View \cdot Model$$^1$ Matrix (for example in the vertex shader to specify your position output).&#xD;&#xA;&#xD;&#xA;Also, remember that a perspective projection changes angles (i.e. parallel lines won't be parallel anymore). As far as I can see that is missing in your derivation.&#xD;&#xA;&#xD;&#xA;***Edit***&#xD;&#xA;&#xD;&#xA;As to how you actually derive it, I'll largely use the explanation by[Etay Meiri][1]. It has some additional information and illustration, so you may want to check it, if something seems unclear.&#xD;&#xA;&#xD;&#xA;First, your camera is (as mentioned earlier) positioned in the origin.&#xD;&#xA;Now assume, you will only project onto a plane of distance $d$ and the plane you project onto is bounded by the aspect ration $ar$ (that is $ar = \frac{window\text{ }width}{window\text{ }height}$ in positive and negative $x$ direction and by $1$ in positive and negative $y$ direction.&#xD;&#xA;&#xD;&#xA;You can now determine $d$ by your vertical field of view $\alpha$ (since looking from the side, your camera, the center at the top of your projection plane and the center of the bottom of your projection plane build a triangle and your vertical field of view is the angle at your camera):&#xD;&#xA;&#xD;&#xA;$\frac{1}{d} = \tan(\frac{\alpha}{2})\\&#xD;&#xA;\implies d = \frac{1}{\tan(\frac{\alpha}{2})}$&#xD;&#xA;&#xD;&#xA;Now you go about calculating projected points. Assume you have an arbitrary point $v = (v_x, v_y, v_z)$, and you want to calculate the point on your plane $p = (p_x, p_y, d)$. Looking at it from the side again, the triangle with your camera, your projection plane top center point and your projected point is similar to the triangle with your camera, your projection plane top center prolonged to have the same z coordinate, as your point $v$ and the point $v$, i.e. they have the same angles$^2$. Therefore, you can now calculate the projected $p_x$ and $p_y$ coordinate:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\frac{p_y}{d} = \frac{v_y}{v_z} \implies p_y = \frac{v_y\cdot d}{v_z} = \frac{v_y}{v_z \cdot \tan(\frac{\alpha}{2})}\\&#xD;&#xA;\frac{p_x}{d} = \frac{v_x}{v_z} \implies p_x = \frac{v_x\cdot d}{v_z} = \frac{v_x}{v_x \cdot \tan(\frac{\alpha}{2})}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;To additionally take into account, that the projection plane ranges from $-ar$ to $ar$ in $x$ direction, you would add $ar$ to the denominator in order to make the projected $x$ range be $\left[-1, 1\right]$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;p_x = \frac{v_x}{ar \cdot v_x \cdot \tan(\frac{\alpha}{2})}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;If you think about applying this to a matrix now, you need to take into account the division by $z$, which is different for any point with differing $z$ value. Therefore, the division by z is deferred until after the projection matrix is applied (and is done without any code of you, i.e. for OpenGL you'd specify the `gl_Position` in Clip Space ($\implies$ after projection) and the division is done for you).&#xD;&#xA;&#xD;&#xA;The depth test (Z-Test) still needs the $z$ value though, so it needs to be &quot;safed&quot; from the $z$ divide. Therefore you copy your $z$ value to the $w$ component (which is what you got right in your assumption) and end up with the following matrix:&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;\frac{1}{ar\cdot\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;\frac{1}{\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;1&amp;0&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;The next step is to not project onto a plane, but into a $z$ range of $\left[-1, 1\right]$ (this range is for correct clipping, as is the same range when handling the $x$ and the $y$ coordinate). To be more specific, you don't want all points to end up in that range, but all points between your near and your far plane, so you map $[n, f]$ to $[-1, 1]$.&#xD;&#xA;The resulting range is $2$, so you first scale your near-to-far range to $2$. Then you move it to be $[-1, 1]$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;f(z) = A\cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And now taking into account that we want to safe the $z$ value from $z$ divide, we get to&#xD;&#xA;&#xD;&#xA;$f(z) = A + \frac{B}{z}$&#xD;&#xA;&#xD;&#xA;Mapping this scaling to $[-1, 1]$ is a little bit of leg work: you know that any point with $z = n$ (on your near plane) will be projected to $p_z = -1$ and any point with $z = f$ (on your far plane) will be projected to $p_z = 1$. This leads to the following equation system:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;A + \frac{B}{n} = -1\\&#xD;&#xA;A + \frac{B}{f} = 1&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Solving this for $A$ and $B$ leads to$^3$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;A = \frac{-n-f}{n-f}\\&#xD;&#xA;B = \frac{2fn}{n-f}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Your third row of the projection matrix must produced the (undivided) $p_z$ (projected) z value. Therefore, you can now choose the individual elements of said row $(\begin{array}{cccc}a&amp;b&amp;c&amp;d\end{array})$ such that the correct $z$ value is produced when multiplying with your point. The correct $p_z$ value is (as established earlier):&#xD;&#xA;$p_z = A\cdot z + B$&#xD;&#xA;&#xD;&#xA;Therefore this must be the right hand side of your multiplication. Assume your point to project is $(x, y, z, w)$, then &#xD;&#xA;you must achieve the following:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;a \cdot x + b \cdot y + c \cdot z + d \cdot w = A \cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Obviously, your point's $x$ and $y$ coordinate should not influence the projected $z$ coordiante, so you can set $a$ and $b$ to $0$.&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;c \cdot z + d \cdot w = A \cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Since you know that $w$ for any point is $1$, you're left with&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;c \cdot z + d = A \cdot z + B&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;And thus, you have $c = A$ and $d = B$.&#xD;&#xA;&#xD;&#xA;Now your matrix is complete for projection&#xD;&#xA;&#xD;&#xA;$\left(&#xD;&#xA;\begin{array}{cccc}&#xD;&#xA;\frac{1}{ar\cdot\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;\frac{1}{\tan(\frac{\alpha}{2})}&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;\frac{-n-f}{n-f}&amp;\frac{2fn}{n-f}\\&#xD;&#xA;0&amp;0&amp;1&amp;0&#xD;&#xA;\end{array}&#xD;&#xA;\right)$&#xD;&#xA;&#xD;&#xA;Obviously, the tutorial works a little differently in projecting with the vertical field of view, so we can take a look at how you can additionally get to that (with the help of [Eric Lengyel][2]:&#xD;&#xA;&#xD;&#xA;Instead of projecting onto a plane at $z = d$, we will project onto the near plane, and thus get for a point $v = (v_x, v_y, v_z)$ the projected point $p = (p_x, p_y, n)$:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;p_x = \frac{v_x \cdot n}{v_z}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Additionally, you want to map any point with $l\leq x \leq r$ to $\left[-1, 1\right]$, as before.&#xD;&#xA;Thus you get &#xD;&#xA;&#xD;&#xA;$f(x) = (x-l) \frac{2}{r-l}-1$&#xD;&#xA;&#xD;&#xA;Combine those two and you achieve&#xD;&#xA;&#xD;&#xA;$p_x = \frac{2n}{r-l}\left(-\frac{v_x}{v_y}\right)- \frac{r+l}{r-l}$&#xD;&#xA;&#xD;&#xA;Now put this (and the term for $y$) into the matrix and you get to the first row, first column being  $\frac{2n}{r-l}$, and the first row, third column being $\frac{r+l}{r-l}$. Since you may assume $r$ and $l$ to be different, here you can see why those two matrices differ. $r$ and $l$ are guaranteed to be the same in the tutorial's matrix and therefore you get $r+l = ar-ar = 0$ in the denominator, making the third row first column (and second column accordingly) $0$.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;$^1$Assuming you have Column-Major matrices like in OpenGL$&#xD;&#xA;&#xD;&#xA;$^2$For the $x$ calculation, you will need to take a different point of your projection plane of course, but the idea is the same&#xD;&#xA;&#xD;&#xA;$^3$The differences of the sign come from how you orient your camera: in your assumption it is along the negative $z$ axis, whereas in the tutorial it is along the positive $z$ axis&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://ogldev.atspace.co.uk/www/tutorial12/tutorial12.html&#xD;&#xA;  [2]: http://mathfor3dgameprogramming.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="24640" PostHistoryTypeId="2" PostId="9041" RevisionGUID="b43f8647-ca60-4e0b-acc6-6e8d9187203f" CreationDate="2019-08-02T08:25:04.683" UserId="10952" Text="I am looking for a list that states which vendor does support which OpenGL extension.&#xD;&#xA;&#xD;&#xA;For example I wanted to use `ARB_shading_language_include`, which was accepted in 2013, but from various forums on the internet I assume it isn't implemented on AMD drivers. But I can't find any official document that states where this extension is supported.&#xD;&#xA;&#xD;&#xA;Does such a list exist?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24641" PostHistoryTypeId="1" PostId="9041" RevisionGUID="b43f8647-ca60-4e0b-acc6-6e8d9187203f" CreationDate="2019-08-02T08:25:04.683" UserId="10952" Text="Is there a list of OpenGL extension support?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24642" PostHistoryTypeId="3" PostId="9041" RevisionGUID="b43f8647-ca60-4e0b-acc6-6e8d9187203f" CreationDate="2019-08-02T08:25:04.683" UserId="10952" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24643" PostHistoryTypeId="2" PostId="9042" RevisionGUID="f917b10a-e716-455d-b9e7-23b24bb94824" CreationDate="2019-08-02T11:26:42.537" UserId="10952" Text="There is no official list, but a community driven one. It is largely up to date:&#xD;&#xA;https://opengl.gpuinfo.org/listextensions.php&#xD;&#xA;&#xD;&#xA;As can be seen [here][1] AMD doesn't support the `ARB_shading_language_include` extension at the time I wrote this answer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://opengl.gpuinfo.org/listreports.php?extension=GL_ARB_shading_language_include" ContentLicense="CC BY-SA 4.0" />
  <row Id="24644" PostHistoryTypeId="2" PostId="9043" RevisionGUID="25d3b695-d0d0-49b3-bb03-3cd4795eca4d" CreationDate="2019-08-02T14:30:19.410" UserId="10996" Text="I'm working on a (toy-level) path/ray-tracer, currently trying to implement (and understand) improved sampling strategies.&#xD;&#xA;&#xD;&#xA;The obvious next choice after uniform random sampling would be stratified/jittered sampling.&#xD;&#xA;The idea itself is clear: You divide the domain to sample (let's say the unit square) into NxN sub regions/cells, place a sample into each of those and add noise to it. Afterwards you shuffle the sample array so the consumption order does not matter - at least that is my understanding for the shuffle step.&#xD;&#xA;&#xD;&#xA;This procedure is explained over and over in lots of sources and literature, but what most barely touch is how you would consume those in practise.&#xD;&#xA;While it is clear for a single use case, like sampling a primary ray/camera pixel or sampling the surface of an area light, my understanding (which might be wrong) is&#xD;&#xA;that those stratified [0,1]^N samples act as a general source of well distributed random numbers.&#xD;&#xA;&#xD;&#xA;An example, say you want to render 1024 samples for some scene with area lights with a path tracer.&#xD;&#xA;&#xD;&#xA;per pixel:&#xD;&#xA;&#xD;&#xA;- just generating 32 x 32 (camera ray) samples is not working out, as you will need more good 2D samples for the area lights. Generating 32x32 arrays for each occasion where you might need good 2D samples is probably not a good idea, or is it? Though, given that you know the max ray bounce number one could make a good upper limit guess for the necessary total amount of 2D samples per pixel.&#xD;&#xA;- you will also need good 1D numbers for things like rolling the russian roulette dice or picking the BRDF to sample, the amount needed is probably unknown in advance, but again, guessing a reasonable upper limit would probably work out&#xD;&#xA;&#xD;&#xA;My immediate (and probably flawed) idea would be to create stratified sample arrays per pixel (or even for the full rendering) for dimensions 1+2 which do not necessarily match the requested total sample per pixel count, e.g. 64x64 each time, no matter the samples per pixel count. You would consume those in order, after shuffling, and if used up generate them fresh. &#xD;&#xA;&#xD;&#xA;Other alternatives i could think of:&#xD;&#xA;&#xD;&#xA;- given number of pixel samples N, always generate N stratified samples on demand whenever needed&#xD;&#xA;&#xD;&#xA;- generate enough samples ahead of time per pixel, when running out fall back to uniform random numbers or generate new stratified samples (so eventually the same as above)&#xD;&#xA;&#xD;&#xA;So long story short, the actual question is probably how do i properly consume those stratified samples? Are you even supposed to use such samples outside of primary pixel or area light samples? (Re)Use unused numbers per pixel sample,  per full rendering? Or am i generally on the wrong path, in that those stratified samples are not meant as a replacement for well distributed random numbers?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24645" PostHistoryTypeId="1" PostId="9043" RevisionGUID="25d3b695-d0d0-49b3-bb03-3cd4795eca4d" CreationDate="2019-08-02T14:30:19.410" UserId="10996" Text="Proper way of consuming stratified samples in path/ray tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="24646" PostHistoryTypeId="3" PostId="9043" RevisionGUID="25d3b695-d0d0-49b3-bb03-3cd4795eca4d" CreationDate="2019-08-02T14:30:19.410" UserId="10996" Text="|raytracing|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24649" PostHistoryTypeId="2" PostId="9045" RevisionGUID="0e9dfecf-497e-4f11-988f-3781060b7b30" CreationDate="2019-08-03T19:22:20.637" UserId="10998" Text="Dear ImGui doesn't attempt to create a swapchain for your main window.&#xD;&#xA;&#xD;&#xA;The **example** code (main.cpp) in the Vulkan back-end calls a helper `ImGui_ImplVulkanH_CreateWindowSwapChain()` which calls `vkCreateSwapchainKHR()`... well, because it is an example app.. you should probably not call those helpers in those app, your app probably already creates a window and a swapchain.&#xD;&#xA;&#xD;&#xA;When the multi-viewports feature enabled (only available in the 'docking' branch), it DOES create additional swap-chains for every secondary window it creates, those are not windows that you manage nor see at all so it shouldn't interferte with your window.&#xD;&#xA;&#xD;&#xA;All the functions with the `ImGui_ImplVulkanH_` prefix are documented in imgui_impl_vulkan.h as serving two purposes: facilitating writing the demo app, and internally by the multi-viewports system. You shouldn't need to call those from your app and therefore there's should not be multiple swapchains trying to associate to a same window." ContentLicense="CC BY-SA 4.0" />
  <row Id="24650" PostHistoryTypeId="2" PostId="9046" RevisionGUID="f420d81a-c1a0-4edd-9743-0c822348ca4b" CreationDate="2019-08-03T19:49:05.940" UserId="10928" Text="If I have a cube in OpenGL, how can I have it appear like rounded?&#xD;&#xA; I think it's too complicated to really have the cube rounded so is there any &quot;light trick&quot; to have something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wtuxO.png&#xD;&#xA;&#xD;&#xA;The cubes in the image seem to be rounded on the top. The screenshot is from the game [Voxatron](https://voxatron.com)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24651" PostHistoryTypeId="1" PostId="9046" RevisionGUID="f420d81a-c1a0-4edd-9743-0c822348ca4b" CreationDate="2019-08-03T19:49:05.940" UserId="10928" Text="Pseudo rounded cube in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="24652" PostHistoryTypeId="3" PostId="9046" RevisionGUID="f420d81a-c1a0-4edd-9743-0c822348ca4b" CreationDate="2019-08-03T19:49:05.940" UserId="10928" Text="|opengl|lighting|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24653" PostHistoryTypeId="5" PostId="9046" RevisionGUID="bfffb8d6-6883-443e-acb4-1fdc2822afa4" CreationDate="2019-08-03T19:55:58.190" UserId="10928" Comment="added new image" Text="If I have a cube in OpenGL, how can I have it appear like rounded?&#xD;&#xA; I think it's too complicated to really have the cube rounded so is there any &quot;light trick&quot; to have something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The cubes in the image seem to be rounded on the top. The screenshot is from the game [Voxatron](https://voxatron.com)&#xD;&#xA;&#xD;&#xA;Another view of the cubes (see how they seem rounded on the top):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wtuxO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/yQb4V.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24654" PostHistoryTypeId="2" PostId="9047" RevisionGUID="c5ab0ee7-e0d4-4bcb-ae40-f557d0dc8cf2" CreationDate="2019-08-03T20:59:01.793" UserId="1582" Text="If silhouette is not important, you could bend the shading normal near edges. &#xD;&#xA;&#xD;&#xA;Since it's a cube you can probably compute the normal procedurally in the shader based off of the uv. I.e. if uv is in range [0,0.1] or [0.9,1.0] start bending the normal towards horizontal. &#xD;&#xA;&#xD;&#xA;If silhouette is important, drawing a rounded cube model with vertex normals would make the most sense. There are cube models which have the beveling to look like a rounded cube.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24655" PostHistoryTypeId="2" PostId="9048" RevisionGUID="d9655e9a-52fe-4379-b23d-a84abd060e5d" CreationDate="2019-08-04T15:31:56.767" UserId="10957" Text="Please help me out with this thing and currently i am a little more than a beginner so please tell me in that context. i don't need any obsolete methods for creating this like using GLUT or GLEW.can you just tell me its algorithm to create the outline of it(like using icosphere or triangles) and how and where in the whole program do i implement this algorithm. currently i am referring the &quot;learnopengl.com&quot; tutorials.i know how to create triangles and 3d rotational cube.   " ContentLicense="CC BY-SA 4.0" />
  <row Id="24656" PostHistoryTypeId="1" PostId="9048" RevisionGUID="d9655e9a-52fe-4379-b23d-a84abd060e5d" CreationDate="2019-08-04T15:31:56.767" UserId="10957" Text="How can i create a 3D Sphere(earth) using OpenGL, GLFW, GLAD, GLM?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24657" PostHistoryTypeId="3" PostId="9048" RevisionGUID="d9655e9a-52fe-4379-b23d-a84abd060e5d" CreationDate="2019-08-04T15:31:56.767" UserId="10957" Text="|opengl|3d|transformations|algorithm|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24658" PostHistoryTypeId="2" PostId="9049" RevisionGUID="2c63ec0f-a85e-414d-9b70-29835f351600" CreationDate="2019-08-04T23:49:36.090" UserId="6046" Text="I'm not going to post proper working code here just giving you a guideline. There might be an easier way but what I did back in my days was to create a sphere using Triangle Strips. There is an icosahedron approach as well but I haven't looked into that.&#xD;&#xA;&#xD;&#xA;So first of all look up on `GL_TRIANGLE_STRIPS` and how they work. Secondly you need to look up on Spherical coordinates and how to convert them to Cartesian Coordinates.&#xD;&#xA;&#xD;&#xA;A brief overview is that Spherical coordinates have parameters (radius, zenith, azimuth). Radius is pretty much self explanatory. Zenith angle is the inclination angle from the pole of the sphere (lines of longitude) While the Azimuth angle runs along the latitude. Zenith runs from `0-PI` (assuming 0 starts from 1 pole and PI is the second pole) or `-PI/2 - PI/2` (assuming the extreme at both poles and 0 is the center) and Azimuth from `0-2PI` (all the way around the sphere).&#xD;&#xA;&#xD;&#xA;Now after that you can think of the sphere forming up from concentric Rings. At each fraction of the Zenith angle there is ring that runs around the sphere (the latitude lines). Then you create triangle strips between those rings to fill the sphere up.&#xD;&#xA;&#xD;&#xA;So basically you want something like,&#xD;&#xA;&#xD;&#xA;    zenith = azimuth = 0&#xD;&#xA;    ring_increment = PI/num_rings;&#xD;&#xA;    sector_inrement = 2PI/num_sectors;&#xD;&#xA;&#xD;&#xA;    for(i=0; i &lt; PI; i+= ring_increment)&#xD;&#xA;    {&#xD;&#xA;    	for(j=0; j &lt; 2PI; j+= sector_increment)&#xD;&#xA;    	{&#xD;&#xA;    		vertex_list.add(convertToCartesianCoord(radius, zenith, azimuth))&#xD;&#xA;    		zenith += ring_increment&#xD;&#xA;    		vertex_list.add(convertToCartesianCoord(radius, zenith, azimuth))&#xD;&#xA;    		zenith -= ring_increment&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The more the number of rings and the number of sectors the smoother the sphere will be." ContentLicense="CC BY-SA 4.0" />
  <row Id="24659" PostHistoryTypeId="6" PostId="9032" RevisionGUID="0edea333-37b9-443c-b1fa-b5599053a707" CreationDate="2019-08-05T05:43:30.263" UserId="2479" Comment="added opengl tag" Text="|opengl|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24660" PostHistoryTypeId="24" PostId="9032" RevisionGUID="0edea333-37b9-443c-b1fa-b5599053a707" CreationDate="2019-08-05T05:43:30.263" Comment="Proposed by 2479 approved by 209, 48 edit id of 483" ContentLicense="CC BY-SA 4.0" />
  <row Id="24661" PostHistoryTypeId="5" PostId="4642" RevisionGUID="b139e689-77d9-4e97-b839-9781c489d8f9" CreationDate="2019-08-05T05:45:12.480" UserId="-1" Comment="Fixed incorrect formula in yellow quote box.  " Text="    Vec3 v = myPoint - pointOnPlane;&#xD;&#xA;    float vDotPlaneNormal = dot(v, planeNormal)&#xD;&#xA;    if (vDotPlaneNormal == 0) &#xD;&#xA;        printf(&quot;point on plane&quot;);&#xD;&#xA;    else if (vDotPlaneNormal &gt; 0)&#xD;&#xA;        printf(&quot;point above somehow...&quot;);&#xD;&#xA;    else&#xD;&#xA;        printf(&quot;point under sadly...&quot;);&#xD;&#xA;&#xD;&#xA;If you wonder what is `pointOnPlane`. In fact it can be any point that lies on the plane. Imagine this as a sheet of paper; draw two lines on this sheet to define the center of the piece of paper, imagine that this point is aligned with the world coordinate system origin and that sheet is in xz plane of that coordinate system (in which y defines the up vector). So the paper is horizontal in a way. Now move the sheet around. The `pointOnPlane` can be the coordinates of the point you drew in the center of the sheet of paper with respect to the world origin.&#xD;&#xA;&#xD;&#xA;All you have to do is rotate that sheet of paper. That rotation is given to you by the plane's normal.&#xD;&#xA;&#xD;&#xA;The rest is basic trig. If the point P is one the plane, the dot product between the vector defined by (P - PointOnPlane) and the plane's normal will be equal to 0. The dot product tells you whether two vectors are orthogonal, on the same side of the plane or point in opposite directions.&#xD;&#xA;&#xD;&#xA;FASTER SOLUTION - EDIT&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;As mentioned by SimonF in a comment, you don't really need the `pointOnPlane` parameter and save the subtraction between this point and the tested point:&#xD;&#xA;&#xD;&#xA;&gt; As you imply, a plane can be represented by its normal, $N$, and a scalar, $d$. &#xD;&#xA;&#xD;&#xA;&gt; A point X is on the plane if $N \cdot X+d = 0$. As for inside and&#xD;&#xA;&gt; outside typically you define a rule, e.g., that the normal points&#xD;&#xA;&gt; &quot;out&quot; from the plane which just means that if $N \cdot X &gt; d$, then&#xD;&#xA;&gt; $X$ is above the plane, while $N \cdot X&lt;d$, implies it's below.  N&#xD;&#xA;&gt; must have unit length.&#xD;&#xA;&#xD;&#xA;You can test/use both techniques.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24662" PostHistoryTypeId="24" PostId="4642" RevisionGUID="b139e689-77d9-4e97-b839-9781c489d8f9" CreationDate="2019-08-05T05:45:12.480" Comment="Proposed by anonymous approved by 209, -1 edit id of 482" ContentLicense="CC BY-SA 4.0" />
  <row Id="24663" PostHistoryTypeId="5" PostId="4642" RevisionGUID="7676e480-0217-447b-9dd5-7493aca9d967" CreationDate="2019-08-05T05:45:12.480" UserId="48" Comment="math formatting" Text="    Vec3 v = myPoint - pointOnPlane;&#xD;&#xA;    float vDotPlaneNormal = dot(v, planeNormal)&#xD;&#xA;    if (vDotPlaneNormal == 0) &#xD;&#xA;        printf(&quot;point on plane&quot;);&#xD;&#xA;    else if (vDotPlaneNormal &gt; 0)&#xD;&#xA;        printf(&quot;point above somehow...&quot;);&#xD;&#xA;    else&#xD;&#xA;        printf(&quot;point under sadly...&quot;);&#xD;&#xA;&#xD;&#xA;If you wonder what is `pointOnPlane`. In fact it can be any point that lies on the plane. Imagine this as a sheet of paper; draw two lines on this sheet to define the center of the piece of paper, imagine that this point is aligned with the world coordinate system origin and that sheet is in xz plane of that coordinate system (in which y defines the up vector). So the paper is horizontal in a way. Now move the sheet around. The `pointOnPlane` can be the coordinates of the point you drew in the center of the sheet of paper with respect to the world origin.&#xD;&#xA;&#xD;&#xA;All you have to do is rotate that sheet of paper. That rotation is given to you by the plane's normal.&#xD;&#xA;&#xD;&#xA;The rest is basic trig. If the point P is one the plane, the dot product between the vector defined by (P - PointOnPlane) and the plane's normal will be equal to 0. The dot product tells you whether two vectors are orthogonal, on the same side of the plane or point in opposite directions.&#xD;&#xA;&#xD;&#xA;FASTER SOLUTION - EDIT&#xD;&#xA;======================&#xD;&#xA;&#xD;&#xA;As mentioned by SimonF in a comment, you don't really need the `pointOnPlane` parameter and save the subtraction between this point and the tested point:&#xD;&#xA;&#xD;&#xA;&gt; As you imply, a plane can be represented by its normal, $N$, and a scalar, $d$. &#xD;&#xA;&#xD;&#xA;&gt; A point X is on the plane if $N \cdot X+d = 0$. As for inside and&#xD;&#xA;&gt; outside typically you define a rule, e.g., that the normal points&#xD;&#xA;&gt; &quot;out&quot; from the plane which just means that if $N \cdot X + d &gt; 0$, then&#xD;&#xA;&gt; $X$ is above the plane, while $N \cdot X + d &lt; 0$, implies it's below.&#xD;&#xA;&#xD;&#xA;You can test/use both techniques.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24666" PostHistoryTypeId="6" PostId="9010" RevisionGUID="a08572fb-ee62-4060-b1f7-1509d6a2d7fc" CreationDate="2019-08-05T10:41:26.403" UserId="11003" Comment="Assign more appropriate tags" Text="|geometry|interpolation|simulation|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24667" PostHistoryTypeId="24" PostId="9010" RevisionGUID="a08572fb-ee62-4060-b1f7-1509d6a2d7fc" CreationDate="2019-08-05T10:41:26.403" Comment="Proposed by 11003 approved by 48, 10744 edit id of 484" ContentLicense="CC BY-SA 4.0" />
  <row Id="24668" PostHistoryTypeId="2" PostId="9050" RevisionGUID="9041a91f-aed6-4b6e-8462-6aa1f5d9e030" CreationDate="2019-08-06T08:09:15.490" UserId="10928" Text="in the vertex shader I have the vertex position `vpos` which is in object space and I want to get the vector going from the camera to `vpos`. Can I just do `vpos - cameraPos` or do I need to do some matrix multiplication with the model-view inverse because `vPos` and `cameraPos` are not in the same space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24669" PostHistoryTypeId="1" PostId="9050" RevisionGUID="9041a91f-aed6-4b6e-8462-6aa1f5d9e030" CreationDate="2019-08-06T08:09:15.490" UserId="10928" Text="Camera position in vertex shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="24670" PostHistoryTypeId="3" PostId="9050" RevisionGUID="9041a91f-aed6-4b6e-8462-6aa1f5d9e030" CreationDate="2019-08-06T08:09:15.490" UserId="10928" Text="|opengl|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24671" PostHistoryTypeId="2" PostId="9051" RevisionGUID="1bcdba4f-5cc7-4a28-876b-166a087438cf" CreationDate="2019-08-06T15:26:22.720" UserId="2654" Text="Operations between two vectors do not make sense unless both vectors are in the same space. So you must either transform the camera position into object space or transform the object position into camera space. I would suggest the latter, since you already likely have a matrix lying around for doing that for other reasons (lighting, etc)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24672" PostHistoryTypeId="2" PostId="9052" RevisionGUID="f21f4fcd-bce8-439e-86bd-29b8ac9c72df" CreationDate="2019-08-06T22:26:38.923" UserId="3377" Text="A friend of mine offers a live-stream via TCP. I can view the live-stream in a browser by fetching it via web-socket. What I want to achieve is to segregate the video into frames. Furthermore, the frames have to be saved to disk as images (e.g. png). I don't want to use a screen recording tool, though.&#xD;&#xA;&#xD;&#xA;My idea was to access the graphics card buffer via OpenGL or any other library and get every frame of the video live stream there. I just don't know if this is possible and where to start. Of course I know that every more or less modern graphics card has its own frame buffer. Is it possible to access this buffer and get every frame during the live stream is played in the browser?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24673" PostHistoryTypeId="1" PostId="9052" RevisionGUID="f21f4fcd-bce8-439e-86bd-29b8ac9c72df" CreationDate="2019-08-06T22:26:38.923" UserId="3377" Text="Access frames of livestream" ContentLicense="CC BY-SA 4.0" />
  <row Id="24674" PostHistoryTypeId="3" PostId="9052" RevisionGUID="f21f4fcd-bce8-439e-86bd-29b8ac9c72df" CreationDate="2019-08-06T22:26:38.923" UserId="3377" Text="|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24675" PostHistoryTypeId="2" PostId="9053" RevisionGUID="54f823c5-9fbb-4902-a3f4-1f58661d1525" CreationDate="2019-08-07T08:25:00.010" UserId="10468" Text="Is there any way to compute the volume when a sphere intersects a AABB(cube), with different centers. Also i want to be able given a percentage of sphere's volume to  to place the sphere's center in a point in 3D space where it intersects the AABB and satisfies that intersected volume. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24676" PostHistoryTypeId="1" PostId="9053" RevisionGUID="54f823c5-9fbb-4902-a3f4-1f58661d1525" CreationDate="2019-08-07T08:25:00.010" UserId="10468" Text="Volume of Intersection of Cube and Sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="24677" PostHistoryTypeId="3" PostId="9053" RevisionGUID="54f823c5-9fbb-4902-a3f4-1f58661d1525" CreationDate="2019-08-07T08:25:00.010" UserId="10468" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24678" PostHistoryTypeId="2" PostId="9054" RevisionGUID="4e2c5c08-d682-498a-a2ac-ec8b126e0f2b" CreationDate="2019-08-07T13:02:07.563" UserId="10806" Text="Suppose there is a frame, which is larger that the device memory (I mean, dozens of Gb). And I would like to render to it from a set of textures, which is larger than the host memory (I mean, dozens to hundreds of Gb). Each texture is rendered to a different part of the frame.  &#xD;&#xA;To give more context, I'm baking the texture of a 3D-model, using its several projections.&#xD;&#xA;&#xD;&#xA;I see two ways to handle it.  &#xD;&#xA;1. Go out of core texture-first, i.e. for each texture perform rendering several times to render each part of the frame.  &#xD;&#xA;2. Go out of core frame-first, i.e. for each frame part load every texture and render the frame part, then shift frame part and repeat.&#xD;&#xA;&#xD;&#xA;The first way is definitely unfeasible, as PCI throughput is insufficient to load-unload the whole memory of a device for each renderpass.  &#xD;&#xA;The second way is much better, but it does not scale with frame dimensions, as it requires loading all the textures from disk and rendering them for each part of the frame.&#xD;&#xA;&#xD;&#xA;So, is there any alternative to this I miss?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24679" PostHistoryTypeId="1" PostId="9054" RevisionGUID="4e2c5c08-d682-498a-a2ac-ec8b126e0f2b" CreationDate="2019-08-07T13:02:07.563" UserId="10806" Text="Out of core rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="24680" PostHistoryTypeId="3" PostId="9054" RevisionGUID="4e2c5c08-d682-498a-a2ac-ec8b126e0f2b" CreationDate="2019-08-07T13:02:07.563" UserId="10806" Text="|algorithm|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24681" PostHistoryTypeId="50" PostId="7804" RevisionGUID="c0da2176-7878-45af-8e91-1096116ff4b5" CreationDate="2019-08-07T15:00:55.077" UserId="-1" />
  <row Id="24682" PostHistoryTypeId="5" PostId="8989" RevisionGUID="76d560d7-9158-47e9-abb8-a7fe5c77a8c6" CreationDate="2019-08-08T08:48:13.440" UserId="6046" Comment="Previous problem got solved. New problems arose so updated post" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][2]. **You can see my Renderer's result in [this][3] video** (check the end of my post and sorry for not providing a direct link as I already uploaded on my reddit post)&#xD;&#xA;&#xD;&#xA;As you can see the lobster dataset stretches when viewed from the side. My first guess was that I wasn't accounting for the aspect ratio correctly. I have tried scaling the Bounding box to account for the aspect ratio, then adjusting the stepsize according to that. I've also tried to ignore aspect ratio altogether. Both give similar images.&#xD;&#xA;&#xD;&#xA;I tried rendering more datasets like &quot;Knee&quot;, &quot;Bruce's head&quot;, &quot;DTI Scan&quot;, etc but those didn't even gave an image. There was just random noise everywhere. Here's an example of &quot;Bruce's head&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This happens with both uniform and non-uniform datasets. If some datasets are getting rendered correctly like the &quot;Foot&quot; in my video, this should mean it's more a with that specific dataset itself rather the core algorithm. Nonetheless the link to the code is provided. If anybody can point out some mistakes I'd be grateful.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][5]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, it's normalized `(0-1)`, accounted for the aspect ratio `(0, ar)` and adjusted so it's in the center `(-ar/2, ar/2)`. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;EDIT:- If you are hesitating to post an answer here since it's only a suggestion, you can post on Reddit, then when the problem is solved you can post your answer here&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [3]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [4]: https://i.stack.imgur.com/EXyYg.png&#xD;&#xA;  [5]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24683" PostHistoryTypeId="4" PostId="8989" RevisionGUID="76d560d7-9158-47e9-abb8-a7fe5c77a8c6" CreationDate="2019-08-08T08:48:13.440" UserId="6046" Comment="Previous problem got solved. New problems arose so updated post" Text="Volume Rendering - Dataset not rendered correctly" ContentLicense="CC BY-SA 4.0" />
  <row Id="24684" PostHistoryTypeId="2" PostId="9055" RevisionGUID="00017884-2f33-4948-9974-eb3f47ecbd45" CreationDate="2019-08-08T11:43:00.450" UserId="11024" Text="Input: Triangles which make up an arbitrary shape. Each triangle is represented by 3 3D points.&#xD;&#xA;&#xD;&#xA;Output: A set of particles which fills up the inside of the object (see image).&#xD;&#xA;&#xD;&#xA;[![Particles generated from a shape][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have read the description made by [GPU-Gems][2], and tried to implement the proposed solution that don't make the computations on the GPU. I have tried to take each triangle one at a time and see if they intersect with lines, and if so store the z-value which I later used to generate particles. This gave bad results, and in theory it is possible for a line to intersect with a lone point which would cause a bug.&#xD;&#xA;&#xD;&#xA;Can anyone tell me how to easily on the CPU side create a set of particles that represent a shape? Where the shape is defined as a set of triangles.&#xD;&#xA;&#xD;&#xA;I prefer a solution that is simple and works well rather than an efficient solution that can have bugs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/sites/all/modules/custom/gpugems/books/GPUGems3/elementLinks/29fig03.jpg&#xD;&#xA;  [2]: https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch29.html&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24685" PostHistoryTypeId="1" PostId="9055" RevisionGUID="00017884-2f33-4948-9974-eb3f47ecbd45" CreationDate="2019-08-08T11:43:00.450" UserId="11024" Text="Represent shape as particles" ContentLicense="CC BY-SA 4.0" />
  <row Id="24686" PostHistoryTypeId="3" PostId="9055" RevisionGUID="00017884-2f33-4948-9974-eb3f47ecbd45" CreationDate="2019-08-08T11:43:00.450" UserId="11024" Text="|opengl|shader|c++|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24687" PostHistoryTypeId="6" PostId="9055" RevisionGUID="6b3915bb-4639-4c12-9663-23fa2331b1bf" CreationDate="2019-08-08T11:56:27.360" UserId="11024" Comment="edited tags" Text="|opengl|shader|c++|simulation|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24688" PostHistoryTypeId="2" PostId="9056" RevisionGUID="8cedd695-8ad8-450e-a733-ce0504d3b12d" CreationDate="2019-08-08T14:45:13.807" UserId="11025" Text="I have a 2-manifold with boundary, built with marching cubes. Are there any well-known algorithms for smoothing its boundary edges?&#xD;&#xA;&#xD;&#xA;Most of the papers I found are concerned with smoothing the surface.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="24689" PostHistoryTypeId="1" PostId="9056" RevisionGUID="8cedd695-8ad8-450e-a733-ce0504d3b12d" CreationDate="2019-08-08T14:45:13.807" UserId="11025" Text="Boundary Smoothing Algorithms" ContentLicense="CC BY-SA 4.0" />
  <row Id="24690" PostHistoryTypeId="3" PostId="9056" RevisionGUID="8cedd695-8ad8-450e-a733-ce0504d3b12d" CreationDate="2019-08-08T14:45:13.807" UserId="11025" Text="|computational-geometry|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24692" PostHistoryTypeId="5" PostId="9055" RevisionGUID="6efc2bda-e231-4a9e-8123-3835eca5536f" CreationDate="2019-08-08T17:43:52.840" UserId="11024" Comment="added 260 characters in body" Text="Input: Triangles which make up an arbitrary shape. Each triangle is represented by 3 3D points.&#xD;&#xA;&#xD;&#xA;Output: A set of particles which fills up the inside of the object (see image).&#xD;&#xA;&#xD;&#xA;[![Particles generated from a shape][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have read the description made by [GPU-Gems][2], and tried to implement the proposed solution that don't make the computations on the GPU. I have tried to take each triangle one at a time and see if they intersect with lines, and if so store the z-value which I later used to generate particles. This gave bad results, and in theory it is possible for a line to intersect with a lone point which would cause a bug.&#xD;&#xA;&#xD;&#xA;Can anyone tell me how to easily on the CPU side create a set of particles that represent a shape? Where the shape is defined as a set of triangles.&#xD;&#xA;&#xD;&#xA;I prefer a solution that is simple and works well rather than an efficient solution that can have bugs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/sites/all/modules/custom/gpugems/books/GPUGems3/elementLinks/29fig03.jpg&#xD;&#xA;  [2]: https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch29.html&#xD;&#xA;&#xD;&#xA;**Edit:** I re-checked my code, and I found that I was not sorting the z-value arrays correctly like I thought I did, after fixing this I got a good result! If anyone still wants to answer this question that is ok, but I consider my problem to be solved now." ContentLicense="CC BY-SA 4.0" />
  <row Id="24693" PostHistoryTypeId="2" PostId="9058" RevisionGUID="8acc2a04-5802-4041-a911-7c6fd4e00420" CreationDate="2019-08-08T17:52:16.307" UserId="11024" Text="Solution: Check for the minimum x,y,z value for all points. Add these values multiplied by (-1) to all points in order to guarantee that all points are not negative. Then take the largest point and subtract with the minimum point (max and minimum x y z) in order to get a cube-like bound for the object.&#xD;&#xA;&#xD;&#xA;Then divide this cube by an arbitrary size constant representing the radius of each particle. Now you should have a 2D array for z-values, such that for any x, y position you can quickly store z-values that you find intersecting lines.&#xD;&#xA;&#xD;&#xA;For each triangle in the mesh, check all possible that have a large or small enough x-y value for intersections with a line going through the whole cube. If there is an intersection, save the z-value in the x-y array for z-values.&#xD;&#xA;&#xD;&#xA;Lastly loop through each possible z-values in the imaginary cube and check if it has an odd number of z-value hits before the current z-value. If that is the case, then we know that there is a particle here. Don't forget to add the minimum x,y,z values that we added in the beginning in order to make the particles have the correct positions again." ContentLicense="CC BY-SA 4.0" />
  <row Id="24694" PostHistoryTypeId="2" PostId="9059" RevisionGUID="56a762bc-d438-46b7-bbf5-3f89549d22df" CreationDate="2019-08-08T18:22:19.383" UserId="2041" Text="I wouldn't recommend trying to write this code yourself. It's not a question of using into OpenGL - which won't get you another process' framebuffer - but of asking the OS. This is not at all easy to do, and it's work you don't need to do yourself.&#xD;&#xA;&#xD;&#xA;Depending on what the streaming protocol is, the easiest way might be just to write or use a client for that protocol directly instead of hooking another application. Failing that, a screen capture tool such as [OBS](https://obsproject.com/) can already do what you want. It can capture another application's frames or your desktop with relative efficiency. You can set up overlays or write a plugin to manipulate the video the way you want. If you access the stream through a web browser, you might not even need to capture a window: it has the built-in feature of being able to render into your video a web browser component it runs itself (you tell it what URL to point to) without having to run a separate web browser and capture it. This feature is how most streamers get things like a Twitch chat view, score board, or timings onto their video.&#xD;&#xA;&#xD;&#xA;OBS has [a C API for writing fast, native plugins as well as Python and Lua interfaces](https://obsproject.com/docs/). And it's open-source, so in the unlikely event you can't write a plugin to do what you want, you could hack it into a private fork directly." ContentLicense="CC BY-SA 4.0" />
  <row Id="24705" PostHistoryTypeId="2" PostId="9063" RevisionGUID="335b82ef-52cc-42ae-a36a-4831d123badc" CreationDate="2019-08-10T15:35:28.547" UserId="11035" Text="I started a ray tracing [project][1] in Python. I made a CUDA kernel and a trace() function for each pixel. It works perfectly when calculating intersections, shadows and lambert shading, however when I introduce a reflection from the surface of a sphere I get a 'band' around the edge of the projected sphere disk and I cannot figure out why.&#xD;&#xA;&#xD;&#xA;Image results: https://i.stack.imgur.com/XgFI5.jpg&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;My reflection algorithm:&#xD;&#xA;----------------------------------------&#xD;&#xA;&#xD;&#xA; 1. Find point **P** of the intersection.&#xD;&#xA; 2. Find normal vector **N** at the intersection with **C** being the sphere center:&#xD;&#xA;```python&#xD;&#xA;    N = P - C&#xD;&#xA;    N = N / norm(N)&#xD;&#xA;```&#xD;&#xA; 3. Find reflection vector **R** using (where D is the original ray direction:&#xD;&#xA;```python&#xD;&#xA;    R = D - 2 * (D * N ) * N&#xD;&#xA;    R = R / norm(R)&#xD;&#xA;```&#xD;&#xA;   &#xD;&#xA; 4. Shift point **P** along **R** a little bit (to avoid reflection acne, adding this didn't solve the problem)&#xD;&#xA;    &#xD;&#xA;```python&#xD;&#xA;    P = P + 1e-4 * R&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA; 5. Call the ray trace function (only one more time) again as:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;    color_refl = trace(ray_origin=P, ray_direction=R) &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA; 6. Add the reflected color using:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;    color = color + color_refl * reflect_intensity&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Notes: &#xD;&#xA;&#xD;&#xA; - Between step 2 and step 3 I calculate the Lambert shading which works quite well.&#xD;&#xA; - Reflections that bounce off a plane work perfectly.&#xD;&#xA; - I use a CUDA kernel which does not support recursive function calls, so I made another trace function with a different name that doesn't calculate reflections. (that's why there is only one reflection call)&#xD;&#xA;&#xD;&#xA;Here is the source code for the trace and reflection trace functions:&#xD;&#xA;https://github.com/Speterius/ray_tracing/blob/master/cuda_ray_tracing.py&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/Speterius/ray_tracing/" ContentLicense="CC BY-SA 4.0" />
  <row Id="24706" PostHistoryTypeId="1" PostId="9063" RevisionGUID="335b82ef-52cc-42ae-a36a-4831d123badc" CreationDate="2019-08-10T15:35:28.547" UserId="11035" Text="Strange sphere reflection effects in ray tracing project. I cannot figure out what causes them" ContentLicense="CC BY-SA 4.0" />
  <row Id="24707" PostHistoryTypeId="3" PostId="9063" RevisionGUID="335b82ef-52cc-42ae-a36a-4831d123badc" CreationDate="2019-08-10T15:35:28.547" UserId="11035" Text="|raytracing|reflection|artifacts|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24708" PostHistoryTypeId="5" PostId="5761" RevisionGUID="c1441fe1-4cb1-43e2-b6a8-8ff16afd9f15" CreationDate="2019-08-10T15:45:30.680" UserDisplayName="user5681" Comment="Fixed some typos, and included a refactored form of the layered BSDF more amenable for actual implementation." Text="This question is somewhat related to [this one][1].&#xD;&#xA;&#xD;&#xA;As Alan has already said, following the actual light path through each layer leads to more physically accurate results. I will base my answer on a paper by Andrea Weidlich and Alexander Wilkie ([&quot;Arbitrarily Layered Micro-Facet Surfaces&quot;][2]) that I have read and partially implemented. In the paper the authors assume that the distance between two layers is smaller than the radius of a differential area element. This assumption simplifies the implementation because we do not have to calculate intersection points separately for each layer, actually we assume that all intersection points over the layers are just the same point.&#xD;&#xA;&#xD;&#xA;According to the paper, two problems must be solved in order to render multilayered material. The first one is to properly sample the layers and the second is to find the resulting BSDF generated by the combination of the multiple BSDFs that are found along the sampling path. &#xD;&#xA;&#xD;&#xA;**UPDATE:** Actually I have adopted a different method to implement the evaluation of this layered model. While I have kept with the idea of considering the intersection points to be just the same point along the layers, I have computed the sampling and the final BRDF differently: for sampling, I have used ordinary ray tracing, but through the layers (using Russian Roulette to select between reflection/refraction when that's the case); for the final BRDF evaluation, I just multiply each BRDF traversed by the ray path (weighting the incident radiances according to the cosine of the incident ray).&#xD;&#xA;&#xD;&#xA;**Sampling**&#xD;&#xA;&#xD;&#xA;In this first stage we will determine the actual light path through the layers. When a light ray is moving from a less dense medium, e.g. air, to a denser medium, e.g. glass, part of its energy is reflected and the remaining part is transmitted. You can find the amount of energy that is reflected through the [Fresnel reflectance equations][3]. So, for instance, if the Fresnel reflectance of a given dielectric is 0.3, we know that 30% of the energy is reflected and 70% will be transmitted:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;When the light ray is moving from a denser to a less dense medium, the same principle described by the Fresnel reflectance applies. However, in this specific case, [total internal reflection][5] (a.k.a TIR) might also happen if the angle of the incident ray is above the critical angle. In the case of TIR, 100% of the energy is reflected back into the material:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;When light hits a conductor or a diffuse surface, it will always be reflected (being the direction of reflection related to the type of the BRDF). In a multilayer material, the resulting light path will be the aggregate result of all those possibilities. Thus, in the case of a 3-layer material, assuming that the first and second layers are dielectrics and the third layer is diffuse, we might end up, for instance, with the following light path (a tree actually):&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;We can simulate this type of interaction using recursion and weighting each light path according to the actual reflectance/transmitance at the corresponding incident points. A problem regarding the use of recursion in this case is that the number of rays increases with the deepness of the recursion, concentrating computational effort on rays that individually might contribute almost nothing to the final result. On the other hand, the aggregate result of those individual rays at deep recursion levels can be significant and should not be discarded. In this case, we can use Russian Roulette (RR) in order to avoid branching and to probabilistic end light paths without losing energy, but at the cost of a higher variance (noisier result). In this case, the result of the Fresnel reflectance, or the TIR, will be used to randomly select which path to follow. For instance:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;As can be seen, TIR or Fresnel reflectance might keep some rays bouncing indefinitely among layers. As far as I know, [Mitsuba][9] implements plastic as a two layer material, and it uses a closed form solution for this specific case that accounts for an infinity number of light bounces among layers. However, Mitsuba also allows for the creation of multilayer materials with an arbitrary number of layers, in which case it imposes a maximum number of internal bounces since no closed form solution seems to exist for the general case. As a side effect, some energy can be lost in the rendering process, making the material look darker than it should eventually be. &#xD;&#xA;&#xD;&#xA;In my current multilayer material implementation I allow for an arbitrary number of internal bounces at the cost of longer rendering times (well... actually, I've implemented only two layers.. one dielectric and one diffuse :).&#xD;&#xA;&#xD;&#xA;An additional option is to mix branching and RR. For instance, the initial rays (lower deep levels) might present substantial contribution to the final image. Thus, one might choose to branch only at the first one or two intersections, using only RR afterwards. This is, for example, the approached used by [smallpt][10].&#xD;&#xA;&#xD;&#xA;An interesting point regarding multilayered materials is that individual reflected/transmitted rays can be importance sampled according to the corresponding BRDFs/BTDFs of each layer. &#xD;&#xA;&#xD;&#xA;**Evaluating the Final BSDF**&#xD;&#xA;&#xD;&#xA;Considering the following light path computed using RR:&#xD;&#xA;&#xD;&#xA;[![enter image description here][11]][11]&#xD;&#xA;&#xD;&#xA;We can evaluate the total amount of radiance $L_r$ reflected by a multilayer BSDF considering each layer as a individual object and applying the same approach used in ordinary path tracing (i.e. the radiance leaving a layer will be the incident radiance for the next layer). The final estimator can thus be represented by the product of each individual Monte Carlo estimator:&#xD;&#xA;&#xD;&#xA;$$ L_r =  \left( \frac{fr_1 \cos \theta_1}{pdf_1}  \left( \frac{fr_2 \cos \theta_2}{pdf_2} \left( \frac{fr_3 \cos \theta_3}{pdf_3} \left( \frac{fr_2 \cos \theta_4}{pdf_2} \left( \frac{L_i fr_1 \cos \theta_5}{pdf_1} \right)\right)\right)\right)\right)$$&#xD;&#xA;&#xD;&#xA;Since all terms of the estimator are multiplied, we can simplify the implementation by computing the final BSDF and $pdf$ and factoring out the $L_i$ term:&#xD;&#xA;&#xD;&#xA;$$fr = fr_1 \cdot fr_2 \cdot fr_3 \cdot fr_2 \cdot fr_1$$&#xD;&#xA;&#xD;&#xA;$$pdf = pdf_1 \cdot pdf_2 \cdot pdf_3 \cdot pdf_2 \cdot pdf_1$$&#xD;&#xA;&#xD;&#xA;$$\cos \theta= \cos \theta_1 \cdot \cos \theta_2 \cdot \cos \theta_3 \cdot \cos \theta_2 \cdot \cos \theta_1$$&#xD;&#xA;&#xD;&#xA;$$ L_r =  \left( \frac{fr \cos \theta}{pdf} \right) L_i$$&#xD;&#xA;&#xD;&#xA;The [paper][2] by Andrea Weidlich and Alexander Wilkie also takes absorption into consideration, i.e. each light ray might be attenuated according to the absorption factor of each transmissive layer and its thickness. I've not included absorption into my renderer yet, but it is represented by just one scalar value, which will be evaluated according to the [Beer's Law][12].&#xD;&#xA;&#xD;&#xA;**Alternate approaches**&#xD;&#xA;&#xD;&#xA;The Mitsuba renderer uses an alternate representation for multilayered material based on the &quot;tabulation of reflectance functions in a Fourier basis&quot;. I have not yet dig into it, but might be of interest: &quot;[A Comprehensive Framework for Rendering Layered Materials][13]&quot; by Wenzel Jacob *et al*. There is also an expanded version of this paper.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/4611/5681&#xD;&#xA;  [2]: https://dl.acm.org/citation.cfm?id=1321292&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Fresnel_equations&#xD;&#xA;  [4]: https://i.stack.imgur.com/S4zHY.png&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Total_internal_reflection&#xD;&#xA;  [6]: https://i.stack.imgur.com/Li0lu.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/WBz0l.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/t5ewd.png&#xD;&#xA;  [9]: https://www.mitsuba-renderer.org&#xD;&#xA;  [10]: http://www.kevinbeason.com/smallpt&#xD;&#xA;  [11]: https://i.stack.imgur.com/GWv6b.png&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law&#xD;&#xA;  [13]: https://dl.acm.org/citation.cfm?id=2601139" ContentLicense="CC BY-SA 4.0" />
  <row Id="24709" PostHistoryTypeId="2" PostId="9064" RevisionGUID="0aa6059f-c2ef-45c5-90a0-9eae2b61d51b" CreationDate="2019-08-10T16:48:01.383" UserId="11035" Text="The issue was caused by an incorrect calculation of the reflection direction vector.&#xD;&#xA;With D ray direction and N the normal vector:&#xD;&#xA;&#xD;&#xA;    R = D - 2 * dot(D, N) * N&#xD;&#xA;&#xD;&#xA;The issue was caused by calculating the components of R as follows:&#xD;&#xA;&#xD;&#xA;    R[i] = D[i] - 2 * (D[i] * N[i]) * N[i]&#xD;&#xA;&#xD;&#xA;It took me a while to find the mistake because this produced a correct reflection with the horizontal plane." ContentLicense="CC BY-SA 4.0" />
  <row Id="24711" PostHistoryTypeId="2" PostId="9065" RevisionGUID="2680b115-7842-44dc-a3c8-5e26690f91eb" CreationDate="2019-08-12T08:27:41.967" UserId="11041" Text="I am trying to write a ray-tracer. The lighting part is proving to work but not accurately. To debug I simplified the scene to a single sphere centered at the origin with a radius of 1 and a point light shining from above (0, 2, 0). The camera is at (0, 0, 4).&#xD;&#xA;&#xD;&#xA;ambient 0.2 0.2 0.2&#xD;&#xA;specular 0 0 0&#xD;&#xA;shininess 1&#xD;&#xA;emission 0 0 0&#xD;&#xA;diffuse 0 1 1 &#xD;&#xA;&#xD;&#xA;The image I'm rendering seems wrong - should its cutoff be lower closer to the equator of the sphere?&#xD;&#xA;&#xD;&#xA;Any help would be appreciated.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AWFWt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24712" PostHistoryTypeId="1" PostId="9065" RevisionGUID="2680b115-7842-44dc-a3c8-5e26690f91eb" CreationDate="2019-08-12T08:27:41.967" UserId="11041" Text="Diffuse lighting calculations in ray-tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="24713" PostHistoryTypeId="3" PostId="9065" RevisionGUID="2680b115-7842-44dc-a3c8-5e26690f91eb" CreationDate="2019-08-12T08:27:41.967" UserId="11041" Text="|raytracing|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24717" PostHistoryTypeId="50" PostId="5996" RevisionGUID="5cdaaae4-1824-402d-87e1-00f1a2f88371" CreationDate="2019-08-12T12:01:45.160" UserId="-1" />
  <row Id="24718" PostHistoryTypeId="50" PostId="8996" RevisionGUID="b6316fdd-525d-4c3f-8703-79355c86008c" CreationDate="2019-08-12T13:02:40.287" UserId="-1" />
  <row Id="24719" PostHistoryTypeId="2" PostId="9067" RevisionGUID="d096367b-2382-4758-9adc-408a2b089d98" CreationDate="2019-08-12T15:29:31.173" UserId="2041" Text="Some elementary trigonometry tells you what to expect from this situation.&#xD;&#xA;&#xD;&#xA;[![Diagram of the situation][1]][1]&#xD;&#xA;&#xD;&#xA;The angle to see the shadow terminator is marked on the diagram, and a use of SOHCAHTOA tells you it's $\cos^{-1}\tfrac{1}{2} = 60^\circ$. Yours looks higher than that so your intuition seems correct. Stepping through the lighting code will help you see where it's going wrong, and you should consider writing unit tests for it, so that it's easier to provoke bugs like this in isolation.&#xD;&#xA;&#xD;&#xA;Something else you might try to help narrow down the problem space is replacing the diffuse calculation with 1 iff $L.N &gt; 0$ (i.e. if the light is in front of the surface), 0 o/w. That will give you a sharp line instead of a gradient, and if that sharp line is in the wrong place, you know the input vectors are wrong. If it's in the right place, the problem is in the diffuse shader itself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TluQN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24720" PostHistoryTypeId="5" PostId="8989" RevisionGUID="5118dbc6-e603-436a-a177-480a0531439d" CreationDate="2019-08-12T18:43:43.983" UserId="6046" Comment="added 1 character in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][2]. **You can see my Renderer's result in [this][3] video** (check the end of my post and sorry for not providing a direct link as I already uploaded on my reddit post)&#xD;&#xA;&#xD;&#xA;As you can see the lobster dataset stretches when viewed from the side. My first guess was that I wasn't accounting for the aspect ratio correctly. I have tried scaling the Bounding box to account for the aspect ratio, then adjusting the stepsize according to that. I've also tried to ignore aspect ratio altogether. Both give similar images.&#xD;&#xA;&#xD;&#xA;I tried rendering more datasets like &quot;Knee&quot;, &quot;Bruce's head&quot;, &quot;DTI Scan&quot;, etc but those didn't even gave an image. There was just random noise everywhere. Here's an example of &quot;Bruce's head&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This happens with both uniform and non-uniform datasets. If some datasets are getting rendered correctly like the &quot;Foot&quot; in my video, this should mean it's more a with that specific dataset itself rather the core algorithm. Nonetheless the link to the code is provided. If anybody can point out some mistakes I'd be grateful.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][5]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, it's normalized `(0-1)`, accounted for the aspect ratio `(0, ar)` and adjusted so it's in the center `(-ar/2, ar/2)`. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;EDIT:- If you are hesitating to post an answer here since it's only a suggestion, you can post on Reddit, then when the problem is solved you can post your answer here.&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [3]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [4]: https://i.stack.imgur.com/EXyYg.png&#xD;&#xA;  [5]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24722" PostHistoryTypeId="2" PostId="9068" RevisionGUID="42ea3afe-4285-44d2-8fe1-558ce3a5f704" CreationDate="2019-08-13T06:52:51.800" UserId="11047" Text="In newer OpenGL it's encouraged to use shaders and pass the model-view-projection as parameters. But what if I drew a complex object, and wanted to translate/rotate it and draw many copies? &#xD;&#xA;&#xD;&#xA;For example I wanted to do something like this :&#xD;&#xA;&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;	{&#xD;&#xA;		shader.bind();&#xD;&#xA;		&#xD;&#xA;		glm::mat4 projectionMatrix = glm::perspective(20.0f, (float)SCRWIDTH/(float)SCRHEIGHT, 0.0f, 100.0f);&#xD;&#xA;		glm::mat4 viewMatrix = glm::lookAt(&#xD;&#xA;			glm::vec3(0, 0, 2), &#xD;&#xA;			glm::vec3(0, 0, 0), &#xD;&#xA;			glm::vec3(0, 1, 0)&#xD;&#xA;		);&#xD;&#xA;		glm::mat4 modelMatrix = glm::toMat4(quaternion);&#xD;&#xA;		glm::mat4 MVP = projectionMatrix * viewMatrix * modelMatrix;&#xD;&#xA;		GLint loc_MVP = glGetUniformLocation(shader.id(), &quot;MVP&quot;);	 &#xD;&#xA;        glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, &amp;MVP[0][0]);&#xD;&#xA;&#xD;&#xA;        glTranslatef(1,0,0);&#xD;&#xA;        gluSphere(...);&#xD;&#xA;        glTranslatef(2,0,0);&#xD;&#xA;        gluSphere(...);&#xD;&#xA;&#xD;&#xA;        shader.unbind();&#xD;&#xA;    }&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;But my experiment shows that the glTranslatef doesn't work here, all the spheres are rendered at (0,0,0). I don't want to call the shader 100 times, each time calculating a different MVP matrix. Is there any easy way around this?&#xD;&#xA;&#xD;&#xA;The vertex shader looks like this :&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;    uniform mat4 MVP;&#xD;&#xA;    in vec3 in_Position;&#xD;&#xA;&#xD;&#xA;    void main(void) {&#xD;&#xA;	    gl_Position = MVP * vec4(in_Position, 1.0);&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24723" PostHistoryTypeId="1" PostId="9068" RevisionGUID="42ea3afe-4285-44d2-8fe1-558ce3a5f704" CreationDate="2019-08-13T06:52:51.800" UserId="11047" Text="Use glTranslatef and shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24724" PostHistoryTypeId="3" PostId="9068" RevisionGUID="42ea3afe-4285-44d2-8fe1-558ce3a5f704" CreationDate="2019-08-13T06:52:51.800" UserId="11047" Text="|opengl|shader|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24725" PostHistoryTypeId="2" PostId="9069" RevisionGUID="66970e2d-4844-43e0-bf20-a13ba2562093" CreationDate="2019-08-13T08:45:07.247" UserId="137" Text="Update the uniform and draw again.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    auto tMVP = glm::translate(MVP, glm::vec3(1,0,0));&#xD;&#xA;    glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, &amp;tMVP[0][0]);&#xD;&#xA;    gluSphere(...);&#xD;&#xA;&#xD;&#xA;    tMVP = glm::translate(MVP, glm::vec3(2,0,0));&#xD;&#xA;    glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, &amp;MVP[0][0]);&#xD;&#xA;    gluSphere(...);&#xD;&#xA;&#xD;&#xA;Using `glTranslate` would have done the *exact same thing* behind the scenes.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;You can instead use instancing instead where you upload all the transforms into a buffer and then tell the gpu to use that. &#xD;&#xA;&#xD;&#xA;However the more portable way involves allocating a vertex attribute for the data. This involves using `glVertexAttribDivisor`.&#xD;&#xA;&#xD;&#xA;So a full mat4 would need 4 vertex attributes. You can decrease that to 2 by separating out the translation as a vec3 and the rotation as a quaternion and pass the view-perspective as a uniform and combining it all in the vertex shader." ContentLicense="CC BY-SA 4.0" />
  <row Id="24729" PostHistoryTypeId="2" PostId="9071" RevisionGUID="ddae1143-bb9a-44ae-a672-33726a06959d" CreationDate="2019-08-13T16:54:41.710" UserId="11047" Text="The code is&#xD;&#xA;&#xD;&#xA;	glColor3f(1, 1, 1);&#xD;&#xA;	gluSphere(gluq, 0.2, 10, 10);&#xD;&#xA;&#xD;&#xA;	glColor3f(1, 0, 0);&#xD;&#xA;	glTranslatef(1, 0, 0);&#xD;&#xA;	gluSphere(gluq, 0.2, 10, 10);&#xD;&#xA;&#xD;&#xA;In short, when I draw directly to screen, it's correct.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But when I create a framebuffer object, attach a texture as color component, draw on the fbo, then draw the texture as rectangle on to the screen, the colors went wrong&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;It seems like the right sphere at (1,0,0) changed the color of the sphere drawn before it.&#xD;&#xA;&#xD;&#xA;And even more bizzare is that if i change the first sphere's color to blue (0,0,1), it becomes black after the second sphere is drawn.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The way I rendered it is like this :&#xD;&#xA;&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);&#xD;&#xA;	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;	{&#xD;&#xA;		glViewport(0, 0, SCRWIDTH, SCRHEIGHT);&#xD;&#xA;		glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, (float)SCRWIDTH / (float)SCRHEIGHT, 0.0f, 100.0f);&#xD;&#xA;		glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;		glColor3f(0, 0, 1);&#xD;&#xA;		gluSphere(gluq, 0.2, 10, 10);&#xD;&#xA;&#xD;&#xA;		glColor3f(1, 0, 0);&#xD;&#xA;		glTranslatef(1, 0, 0);&#xD;&#xA;		gluSphere(gluq, 0.2, 10, 10);&#xD;&#xA;		&#xD;&#xA;	}&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, fbo_tex[0]);&#xD;&#xA;	glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, SCRWIDTH, SCRHEIGHT, 0, -1, 1);&#xD;&#xA;	glMatrixMode(GL_MODELVIEW); glLoadIdentity();&#xD;&#xA;	{&#xD;&#xA;		glBegin(GL_QUADS);&#xD;&#xA;		glTexCoord2f(0, 0); glVertex3i(0, 0, 0);&#xD;&#xA;		glTexCoord2f(0, 1); glVertex3i(0, SCRHEIGHT, 0);&#xD;&#xA;		glTexCoord2f(1, 1); glVertex3i(SCRWIDTH, SCRHEIGHT, 0);&#xD;&#xA;		glTexCoord2f(1, 0); glVertex3i(SCRWIDTH, 0, 0);&#xD;&#xA;		glEnd();&#xD;&#xA;	}&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;&#xD;&#xA;And I created the fbo and texture like this :&#xD;&#xA;&#xD;&#xA;	glGenTextures(1, &amp;fbo_tex[0]);&#xD;&#xA;	&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, fbo_tex[0]);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, SCRWIDTH, SCRHEIGHT, 0, GL_RGBA, GL_FLOAT, 0);&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, 0);&#xD;&#xA;&#xD;&#xA;	glGenFramebuffers(1, &amp;fbo[0]);&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, fbo[0]);&#xD;&#xA;	glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fbo_tex[0], 0);&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;If feels like that consequtive glColor3f caused the colors to mix, taking the minimum RGB values of previous used colors. So white becomes red, but blue turns to black. And the first sphere has the color written to the texture, then the second sphere somehow picks the mixed color and overwrite the first one's pixels. How can I fix this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZKAP9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4fqnS.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/HZpHt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24730" PostHistoryTypeId="1" PostId="9071" RevisionGUID="ddae1143-bb9a-44ae-a672-33726a06959d" CreationDate="2019-08-13T16:54:41.710" UserId="11047" Text="Weird glColor3f results in framebuffer objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="24731" PostHistoryTypeId="3" PostId="9071" RevisionGUID="ddae1143-bb9a-44ae-a672-33726a06959d" CreationDate="2019-08-13T16:54:41.710" UserId="11047" Text="|opengl|color|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24732" PostHistoryTypeId="2" PostId="9072" RevisionGUID="af014c75-c52c-4ec9-8734-b5d7b2516169" CreationDate="2019-08-13T17:54:46.980" UserId="5215" Text="I've managed to write a &quot;small&quot; Vulkan program that outputs a solid color using compute shader directly to swapchain.&#xD;&#xA;&#xD;&#xA;However, it doesn't work properly. ImageMemoryBarriers I've setup don't transition the layouts the way they should and only every third swapchain image (it has three in my implementation) is actually rendered to.&#xD;&#xA;&#xD;&#xA;Two most interesting functions are the one where I record the command buffers and the one where is submit them to the compute/present queue:&#xD;&#xA;&#xD;&#xA;Recording:&#xD;&#xA;&#xD;&#xA;    void createCommandBuffers() {&#xD;&#xA;		commandBuffers.resize(swapchainImages.size());&#xD;&#xA;&#xD;&#xA;		vk::CommandBufferAllocateInfo allocInfo = {};&#xD;&#xA;		allocInfo.commandPool = commandPool.get();&#xD;&#xA;		allocInfo.level = vk::CommandBufferLevel::ePrimary;&#xD;&#xA;		allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();&#xD;&#xA;&#xD;&#xA;		commandBuffers = device-&gt;allocateCommandBuffersUnique(allocInfo);&#xD;&#xA;&#xD;&#xA;		for (size_t i = 0; i &lt; commandBuffers.size(); ++i) {&#xD;&#xA;			vk::CommandBufferBeginInfo beginInfo = {};&#xD;&#xA;			beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;begin(beginInfo);&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;bindPipeline(vk::PipelineBindPoint::eCompute, *pipeline);&#xD;&#xA;			commandBuffers[i]-&gt;bindDescriptorSets(vk::PipelineBindPoint::eCompute, *pipelineLayout, 0, descriptorSets[i], nullptr);&#xD;&#xA;&#xD;&#xA;			vk::ImageMemoryBarrier imageMemoryBarrier = {};&#xD;&#xA;			imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;&#xD;&#xA;			imageMemoryBarrier.newLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;			imageMemoryBarrier.image = swapchainImages[i];&#xD;&#xA;			imageMemoryBarrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseMipLevel = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.levelCount = 1;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.layerCount = 1;&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;pipelineBarrier(&#xD;&#xA;				vk::PipelineStageFlagBits::eTopOfPipe,&#xD;&#xA;				vk::PipelineStageFlagBits::eComputeShader,&#xD;&#xA;				vk::DependencyFlagBits::eByRegion,&#xD;&#xA;				nullptr,&#xD;&#xA;				nullptr,&#xD;&#xA;				imageMemoryBarrier);&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;dispatch(WIDTH, HEIGHT, 1);&#xD;&#xA;&#xD;&#xA;			imageMemoryBarrier = {};&#xD;&#xA;			imageMemoryBarrier.oldLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;			imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;&#xD;&#xA;			imageMemoryBarrier.image = swapchainImages[i];&#xD;&#xA;			imageMemoryBarrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseMipLevel = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.levelCount = 1;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.layerCount = 1;&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;pipelineBarrier(&#xD;&#xA;				vk::PipelineStageFlagBits::eComputeShader,&#xD;&#xA;				vk::PipelineStageFlagBits::eBottomOfPipe,&#xD;&#xA;				vk::DependencyFlagBits::eByRegion,&#xD;&#xA;				nullptr,&#xD;&#xA;				nullptr,&#xD;&#xA;				imageMemoryBarrier);&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;end();&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Submitting:&#xD;&#xA;&#xD;&#xA;    void drawFrame() {&#xD;&#xA;		device-&gt;waitForFences(*inFlightFences[currentFrame], VK_TRUE, std::numeric_limits&lt;uint64_t&gt;::max());&#xD;&#xA;		device-&gt;resetFences(*inFlightFences[currentFrame]);&#xD;&#xA;&#xD;&#xA;		uint32_t imageIndex;&#xD;&#xA;&#xD;&#xA;		try {&#xD;&#xA;			device-&gt;acquireNextImageKHR(*swapchain, std::numeric_limits&lt;uint64_t&gt;::max(), *imageAvailableSemaphores[currentFrame], {}, &amp;imageIndex);&#xD;&#xA;		}&#xD;&#xA;		catch (vk::OutOfDateKHRError) {&#xD;&#xA;			recreateSwapchain();&#xD;&#xA;			return;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		vk::SubmitInfo submitInfo = {};&#xD;&#xA;&#xD;&#xA;		vk::Semaphore waitSemaphores[] = { *imageAvailableSemaphores[currentFrame] };&#xD;&#xA;		submitInfo.waitSemaphoreCount = 1;&#xD;&#xA;		submitInfo.pWaitSemaphores = &amp;waitSemaphores[0];&#xD;&#xA;&#xD;&#xA;		submitInfo.commandBufferCount = 1;&#xD;&#xA;		submitInfo.pCommandBuffers = &amp;*commandBuffers[imageIndex];&#xD;&#xA;&#xD;&#xA;		vk::Semaphore signalSemaphores[] = { *renderFinishedSemaphores[currentFrame] };&#xD;&#xA;		submitInfo.signalSemaphoreCount = 1;&#xD;&#xA;		submitInfo.pSignalSemaphores = &amp;signalSemaphores[0];&#xD;&#xA;		&#xD;&#xA;		vk::PipelineStageFlags waitStages[] = { vk::PipelineStageFlagBits::eTopOfPipe };&#xD;&#xA;		submitInfo.pWaitDstStageMask = waitStages;&#xD;&#xA;&#xD;&#xA;		computeQueue.submit(submitInfo, *inFlightFences[currentFrame]);&#xD;&#xA;&#xD;&#xA;		vk::PresentInfoKHR presentInfo = {};&#xD;&#xA;		presentInfo.waitSemaphoreCount = 1;&#xD;&#xA;		presentInfo.pWaitSemaphores = &amp;signalSemaphores[0];&#xD;&#xA;&#xD;&#xA;		vk::SwapchainKHR swapchains[] = { *swapchain };&#xD;&#xA;		presentInfo.swapchainCount = 1;&#xD;&#xA;		presentInfo.pSwapchains = swapchains;&#xD;&#xA;		presentInfo.pImageIndices = &amp;imageIndex;&#xD;&#xA;&#xD;&#xA;		try {&#xD;&#xA;			vk::Result result = computeQueue.presentKHR(presentInfo);&#xD;&#xA;			if (result == vk::Result::eSuboptimalKHR || framebufferResized) {&#xD;&#xA;				framebufferResized = false;&#xD;&#xA;				recreateSwapchain();&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		catch (vk::OutOfDateKHRError) {&#xD;&#xA;			framebufferResized = false;&#xD;&#xA;			recreateSwapchain();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The last function is basically the main loop at this point.&#xD;&#xA;&#xD;&#xA;I've been staring at it for a while now and I don't get it. I don't know what is wrong. This is also the first Vulkan program I've written semi independently, so there's that as well.&#xD;&#xA;&#xD;&#xA;Here's the rest of the code, if something is unclear: [pastebin][1]&#xD;&#xA;&#xD;&#xA;Also, for completeness sake, here's the shader, as simple as can be:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0, rgba8) uniform image2D resultImage;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	vec4 red = vec4(0.0, 1.0, 0.0, 1.0);&#xD;&#xA;    &#xD;&#xA;    	imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), red);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;P.S. I love how it's called red, but it's actually green, just noticed that.&#xD;&#xA;&#xD;&#xA;  [1]: https://pastebin.com/bGS8Af6t" ContentLicense="CC BY-SA 4.0" />
  <row Id="24733" PostHistoryTypeId="1" PostId="9072" RevisionGUID="af014c75-c52c-4ec9-8734-b5d7b2516169" CreationDate="2019-08-13T17:54:46.980" UserId="5215" Text="Only single image in swapchain being rendered to" ContentLicense="CC BY-SA 4.0" />
  <row Id="24734" PostHistoryTypeId="3" PostId="9072" RevisionGUID="af014c75-c52c-4ec9-8734-b5d7b2516169" CreationDate="2019-08-13T17:54:46.980" UserId="5215" Text="|vulkan|compute-shader|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24735" PostHistoryTypeId="5" PostId="9072" RevisionGUID="cf065dcb-6c78-47dd-b013-00a12eaf3095" CreationDate="2019-08-13T18:49:56.303" UserId="5215" Comment="deleted 76 characters in body" Text="I've managed to write a &quot;small&quot; Vulkan program that outputs a solid color using compute shader directly to swapchain.&#xD;&#xA;&#xD;&#xA;However, it doesn't work properly. ImageMemoryBarriers I've setup don't transition the layouts the way they should and only every third swapchain image (it has three in my implementation) is actually rendered to.&#xD;&#xA;&#xD;&#xA;Two most interesting functions are the one where I record the command buffers and the one where is submit them to the compute/present queue:&#xD;&#xA;&#xD;&#xA;Recording:&#xD;&#xA;&#xD;&#xA;    void createCommandBuffers() {&#xD;&#xA;		commandBuffers.resize(swapchainImages.size());&#xD;&#xA;&#xD;&#xA;		vk::CommandBufferAllocateInfo allocInfo = {};&#xD;&#xA;		allocInfo.commandPool = commandPool.get();&#xD;&#xA;		allocInfo.level = vk::CommandBufferLevel::ePrimary;&#xD;&#xA;		allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();&#xD;&#xA;&#xD;&#xA;		commandBuffers = device-&gt;allocateCommandBuffersUnique(allocInfo);&#xD;&#xA;&#xD;&#xA;		for (size_t i = 0; i &lt; commandBuffers.size(); ++i) {&#xD;&#xA;			vk::CommandBufferBeginInfo beginInfo = {};&#xD;&#xA;			beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;begin(beginInfo);&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;bindPipeline(vk::PipelineBindPoint::eCompute, *pipeline);&#xD;&#xA;			commandBuffers[i]-&gt;bindDescriptorSets(vk::PipelineBindPoint::eCompute, *pipelineLayout, 0, descriptorSets[i], nullptr);&#xD;&#xA;&#xD;&#xA;			vk::ImageMemoryBarrier imageMemoryBarrier = {};&#xD;&#xA;			imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;&#xD;&#xA;			imageMemoryBarrier.newLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;			imageMemoryBarrier.image = swapchainImages[i];&#xD;&#xA;			imageMemoryBarrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseMipLevel = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.levelCount = 1;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.layerCount = 1;&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;pipelineBarrier(&#xD;&#xA;				vk::PipelineStageFlagBits::eTopOfPipe,&#xD;&#xA;				vk::PipelineStageFlagBits::eComputeShader,&#xD;&#xA;				vk::DependencyFlagBits::eByRegion,&#xD;&#xA;				nullptr,&#xD;&#xA;				nullptr,&#xD;&#xA;				imageMemoryBarrier);&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;dispatch(WIDTH, HEIGHT, 1);&#xD;&#xA;&#xD;&#xA;			imageMemoryBarrier = {};&#xD;&#xA;			imageMemoryBarrier.oldLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;			imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;&#xD;&#xA;			imageMemoryBarrier.image = swapchainImages[i];&#xD;&#xA;			imageMemoryBarrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseMipLevel = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.levelCount = 1;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;&#xD;&#xA;			imageMemoryBarrier.subresourceRange.layerCount = 1;&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;pipelineBarrier(&#xD;&#xA;				vk::PipelineStageFlagBits::eComputeShader,&#xD;&#xA;				vk::PipelineStageFlagBits::eBottomOfPipe,&#xD;&#xA;				vk::DependencyFlagBits::eByRegion,&#xD;&#xA;				nullptr,&#xD;&#xA;				nullptr,&#xD;&#xA;				imageMemoryBarrier);&#xD;&#xA;&#xD;&#xA;			commandBuffers[i]-&gt;end();&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Submitting:&#xD;&#xA;&#xD;&#xA;    void drawFrame() {&#xD;&#xA;		device-&gt;waitForFences(*inFlightFences[currentFrame], VK_TRUE, std::numeric_limits&lt;uint64_t&gt;::max());&#xD;&#xA;		device-&gt;resetFences(*inFlightFences[currentFrame]);&#xD;&#xA;&#xD;&#xA;		uint32_t imageIndex;&#xD;&#xA;&#xD;&#xA;		try {&#xD;&#xA;			device-&gt;acquireNextImageKHR(*swapchain, std::numeric_limits&lt;uint64_t&gt;::max(), *imageAvailableSemaphores[currentFrame], {}, &amp;imageIndex);&#xD;&#xA;		}&#xD;&#xA;		catch (vk::OutOfDateKHRError) {&#xD;&#xA;			recreateSwapchain();&#xD;&#xA;			return;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		vk::SubmitInfo submitInfo = {};&#xD;&#xA;&#xD;&#xA;		vk::Semaphore waitSemaphores[] = { *imageAvailableSemaphores[currentFrame] };&#xD;&#xA;		submitInfo.waitSemaphoreCount = 1;&#xD;&#xA;		submitInfo.pWaitSemaphores = &amp;waitSemaphores[0];&#xD;&#xA;&#xD;&#xA;		submitInfo.commandBufferCount = 1;&#xD;&#xA;		submitInfo.pCommandBuffers = &amp;*commandBuffers[imageIndex];&#xD;&#xA;&#xD;&#xA;		vk::Semaphore signalSemaphores[] = { *renderFinishedSemaphores[currentFrame] };&#xD;&#xA;		submitInfo.signalSemaphoreCount = 1;&#xD;&#xA;		submitInfo.pSignalSemaphores = &amp;signalSemaphores[0];&#xD;&#xA;		&#xD;&#xA;		vk::PipelineStageFlags waitStages[] = { vk::PipelineStageFlagBits::eTopOfPipe };&#xD;&#xA;		submitInfo.pWaitDstStageMask = waitStages;&#xD;&#xA;&#xD;&#xA;		computeQueue.submit(submitInfo, *inFlightFences[currentFrame]);&#xD;&#xA;&#xD;&#xA;		vk::PresentInfoKHR presentInfo = {};&#xD;&#xA;		presentInfo.waitSemaphoreCount = 1;&#xD;&#xA;		presentInfo.pWaitSemaphores = &amp;signalSemaphores[0];&#xD;&#xA;&#xD;&#xA;		vk::SwapchainKHR swapchains[] = { *swapchain };&#xD;&#xA;		presentInfo.swapchainCount = 1;&#xD;&#xA;		presentInfo.pSwapchains = swapchains;&#xD;&#xA;		presentInfo.pImageIndices = &amp;imageIndex;&#xD;&#xA;&#xD;&#xA;		try {&#xD;&#xA;			vk::Result result = computeQueue.presentKHR(presentInfo);&#xD;&#xA;			if (result == vk::Result::eSuboptimalKHR || framebufferResized) {&#xD;&#xA;				framebufferResized = false;&#xD;&#xA;				recreateSwapchain();&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		catch (vk::OutOfDateKHRError) {&#xD;&#xA;			framebufferResized = false;&#xD;&#xA;			recreateSwapchain();&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The last function is basically the main loop at this point.&#xD;&#xA;&#xD;&#xA;I've been staring at it for a while now and I don't get it. I don't know what is wrong. This is also the first Vulkan program I've written semi independently, so there's that as well.&#xD;&#xA;&#xD;&#xA;Here's the rest of the code, if something is unclear: [pastebin][1]&#xD;&#xA;&#xD;&#xA;Also, for completeness sake, here's the shader, as simple as can be:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0, rgba8) uniform image2D resultImage;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	vec4 green = vec4(0.0, 1.0, 0.0, 1.0);&#xD;&#xA;    &#xD;&#xA;    	imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), green);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://pastebin.com/bGS8Af6t" ContentLicense="CC BY-SA 4.0" />
  <row Id="24736" PostHistoryTypeId="4" PostId="9072" RevisionGUID="4b197342-47a6-465d-8d6a-0235317c8185" CreationDate="2019-08-13T19:22:52.057" UserId="5215" Comment="edited title" Text="Only each third image in swapchain is being used, causing flickering" ContentLicense="CC BY-SA 4.0" />
  <row Id="24737" PostHistoryTypeId="50" PostId="8260" RevisionGUID="feaa7cbb-4b95-46bc-a52b-17c9eb0adf56" CreationDate="2019-08-14T00:02:45.323" UserId="-1" />
  <row Id="24738" PostHistoryTypeId="2" PostId="9073" RevisionGUID="01f2cff1-9c06-4c26-aeed-4021d71e64d2" CreationDate="2019-08-14T16:50:08.270" UserId="5215" Text="I have managed to find the culprit:&#xD;&#xA;&#xD;&#xA;        std::vector&lt;vk::WriteDescriptorSet&gt; writeDescriptorSets;&#xD;&#xA;&#xD;&#xA;		for (int i = 0; i &lt; swapchainImages.size(); ++i) {&#xD;&#xA;			vk::DescriptorImageInfo descriptorImageInfo = {};&#xD;&#xA;			descriptorImageInfo.imageView = *swapchainImageViews[i];&#xD;&#xA;			descriptorImageInfo.imageLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;&#xD;&#xA;			vk::WriteDescriptorSet writeDescriptorSet = {};&#xD;&#xA;			writeDescriptorSet.dstSet = descriptorSets[i];&#xD;&#xA;			writeDescriptorSet.dstBinding = 0;&#xD;&#xA;			writeDescriptorSet.descriptorCount = 1;&#xD;&#xA;			writeDescriptorSet.descriptorType = vk::DescriptorType::eStorageImage;&#xD;&#xA;			writeDescriptorSet.pImageInfo = &amp;descriptorImageInfo;&#xD;&#xA;			writeDescriptorSets.push_back(writeDescriptorSet);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;        device-&gt;updateDescriptorSets((uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data(), 0, nullptr);&#xD;&#xA;&#xD;&#xA;Do you see it yet?&#xD;&#xA;&#xD;&#xA;What if I told you this fixed it:&#xD;&#xA;&#xD;&#xA;        std::vector&lt;vk::WriteDescriptorSet&gt; writeDescriptorSets;&#xD;&#xA;		std::vector&lt;vk::DescriptorImageInfo&gt; descriptorImageInfos;&#xD;&#xA;&#xD;&#xA;		for (int i = 0; i &lt; swapchainImages.size(); ++i) {&#xD;&#xA;			vk::DescriptorImageInfo descriptorImageInfo = {};&#xD;&#xA;			descriptorImageInfo.imageView = *swapchainImageViews[i];&#xD;&#xA;			descriptorImageInfo.imageLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;			descriptorImageInfos.push_back(descriptorImageInfo);&#xD;&#xA;&#xD;&#xA;			vk::WriteDescriptorSet writeDescriptorSet = {};&#xD;&#xA;			writeDescriptorSet.dstSet = descriptorSets[i];&#xD;&#xA;			writeDescriptorSet.dstBinding = 0;&#xD;&#xA;			writeDescriptorSet.descriptorCount = 1;&#xD;&#xA;			writeDescriptorSet.descriptorType = vk::DescriptorType::eStorageImage;&#xD;&#xA;			writeDescriptorSet.pImageInfo = &amp;descriptorImageInfos[i];&#xD;&#xA;			writeDescriptorSets.push_back(writeDescriptorSet);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;        device-&gt;updateDescriptorSets((uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data(), 0, nullptr);&#xD;&#xA;&#xD;&#xA;vk::DescriptorImageInfo for the first two images was being overwritten before updateDescriptorSets was called&#xD;&#xA;&#xD;&#xA;Remember kids, when you could swear you're treating several things in the absolute same way, but they somehow behave differently (in most cases, only the last one is working), you're probably overwriting something somewhere, or something is going out of scope before you thought it would." ContentLicense="CC BY-SA 4.0" />
  <row Id="24739" PostHistoryTypeId="2" PostId="9074" RevisionGUID="14a88032-1887-46e1-9b7d-43b7fe189088" CreationDate="2019-08-15T07:39:25.730" UserId="11055" Text="I've been reading this [article][1] about the look-at function. I don't understand the part when they're trying to inverse the matrix N.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;They say that R is orthogonal because all its row and column vectors are orthogonal unit vectors.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This means that for example&#xD;&#xA; &#xD;&#xA;$[s_x, v_x, f_x, 0]^T * [s_x, v_x, f_x, 0]^T = 1$ &#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;$[s_x, v_x, f_x, 0]^T * [s_y, v_y, f_y, 0]^T = 0$,&#xD;&#xA;&#xD;&#xA;but why?&#xD;&#xA;Could anyone explain it to me or give a hint about why it's true?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://in2gpu.com/2015/05/17/view-matrix/&#xD;&#xA;  [2]: https://i.stack.imgur.com/M1tEW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/abmQx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24740" PostHistoryTypeId="1" PostId="9074" RevisionGUID="14a88032-1887-46e1-9b7d-43b7fe189088" CreationDate="2019-08-15T07:39:25.730" UserId="11055" Text="Help with understanding the look-at function (the view matrix)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24741" PostHistoryTypeId="3" PostId="9074" RevisionGUID="14a88032-1887-46e1-9b7d-43b7fe189088" CreationDate="2019-08-15T07:39:25.730" UserId="11055" Text="|3d|transformations|mathematics|matrix|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24742" PostHistoryTypeId="6" PostId="8456" RevisionGUID="eb1dbf6c-caef-4082-8c74-c189e8b7d224" CreationDate="2019-08-15T09:03:49.697" UserId="5778" Comment="tags edited" Text="|projections|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24743" PostHistoryTypeId="24" PostId="8456" RevisionGUID="eb1dbf6c-caef-4082-8c74-c189e8b7d224" CreationDate="2019-08-15T09:03:49.697" Comment="Proposed by 5778 approved by 6, 2041 edit id of 485" ContentLicense="CC BY-SA 4.0" />
  <row Id="24745" PostHistoryTypeId="5" PostId="9073" RevisionGUID="2e6a3816-1855-4367-978f-084c5cfa6780" CreationDate="2019-08-15T10:20:37.777" UserId="5215" Comment="added 1 character in body" Text="I have managed to find the culprit:&#xD;&#xA;&#xD;&#xA;        std::vector&lt;vk::WriteDescriptorSet&gt; writeDescriptorSets;&#xD;&#xA;&#xD;&#xA;		for (int i = 0; i &lt; swapchainImages.size(); ++i) {&#xD;&#xA;			vk::DescriptorImageInfo descriptorImageInfo = {};&#xD;&#xA;			descriptorImageInfo.imageView = *swapchainImageViews[i];&#xD;&#xA;			descriptorImageInfo.imageLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;&#xD;&#xA;			vk::WriteDescriptorSet writeDescriptorSet = {};&#xD;&#xA;			writeDescriptorSet.dstSet = descriptorSets[i];&#xD;&#xA;			writeDescriptorSet.dstBinding = 0;&#xD;&#xA;			writeDescriptorSet.descriptorCount = 1;&#xD;&#xA;			writeDescriptorSet.descriptorType = vk::DescriptorType::eStorageImage;&#xD;&#xA;			writeDescriptorSet.pImageInfo = &amp;descriptorImageInfo;&#xD;&#xA;			writeDescriptorSets.push_back(writeDescriptorSet);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;        device-&gt;updateDescriptorSets((uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data(), 0, nullptr);&#xD;&#xA;&#xD;&#xA;Do you see it yet?&#xD;&#xA;&#xD;&#xA;What if I told you this fixed it:&#xD;&#xA;&#xD;&#xA;        std::vector&lt;vk::WriteDescriptorSet&gt; writeDescriptorSets;&#xD;&#xA;		std::vector&lt;vk::DescriptorImageInfo&gt; descriptorImageInfos;&#xD;&#xA;&#xD;&#xA;		for (int i = 0; i &lt; swapchainImages.size(); ++i) {&#xD;&#xA;			vk::DescriptorImageInfo descriptorImageInfo = {};&#xD;&#xA;			descriptorImageInfo.imageView = *swapchainImageViews[i];&#xD;&#xA;			descriptorImageInfo.imageLayout = vk::ImageLayout::eGeneral;&#xD;&#xA;			descriptorImageInfos.push_back(descriptorImageInfo);&#xD;&#xA;&#xD;&#xA;			vk::WriteDescriptorSet writeDescriptorSet = {};&#xD;&#xA;			writeDescriptorSet.dstSet = descriptorSets[i];&#xD;&#xA;			writeDescriptorSet.dstBinding = 0;&#xD;&#xA;			writeDescriptorSet.descriptorCount = 1;&#xD;&#xA;			writeDescriptorSet.descriptorType = vk::DescriptorType::eStorageImage;&#xD;&#xA;			writeDescriptorSet.pImageInfo = &amp;descriptorImageInfos[i];&#xD;&#xA;			writeDescriptorSets.push_back(writeDescriptorSet);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;        device-&gt;updateDescriptorSets((uint32_t)writeDescriptorSets.size(), writeDescriptorSets.data(), 0, nullptr);&#xD;&#xA;&#xD;&#xA;vk::DescriptorImageInfo for the first two images was being overwritten before updateDescriptorSets was called.&#xD;&#xA;&#xD;&#xA;Remember kids, when you could swear you're treating several things in the absolute same way, but they somehow behave differently (in most cases, only the last one is working), you're probably overwriting something somewhere, or something is going out of scope before you thought it would." ContentLicense="CC BY-SA 4.0" />
  <row Id="24746" PostHistoryTypeId="5" PostId="9074" RevisionGUID="4dab1935-a65b-4eb7-9478-a6da6de5d4f0" CreationDate="2019-08-15T13:20:19.443" UserId="11055" Comment="added 378 characters in body" Text="I've been reading this [article][1] about the look-at function. I don't understand the part when they're trying to inverse the matrix N.  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;They say that R is orthogonal because all its row and column vectors are orthogonal unit vectors.&#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;This means that for example  &#xD;&#xA;&#xD;&#xA;$[s_x, v_x, f_x, 0]^T * [s_x, v_x, f_x, 0]^T = 1$   &#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;  &#xD;&#xA;$[s_x, v_x, f_x, 0]^T * [s_y, v_y, f_y, 0]^T = 0$,  &#xD;&#xA;&#xD;&#xA;but why?&#xD;&#xA;Could anyone explain it to me or give a hint about why it's true?  &#xD;&#xA;&#xD;&#xA;**EDIT:**  &#xD;&#xA;I guess I have found the solution:&#xD;&#xA;I can quite easily prove that $R^T*R=I$. So if I could prove that $R^T*R=I\Longrightarrow R*R^T=I$, then by definition R is orthogonal.  &#xD;&#xA;&#xD;&#xA;Is the following proof correct (I'm not really good at math)?  &#xD;&#xA;$&#xD;&#xA;R^T*R=I \Longleftrightarrow&#xD;&#xA;R*(R^T*R)=R*(I) \Longleftrightarrow&#xD;&#xA;(R*R^T)*R=R \Longleftrightarrow&#xD;&#xA;R*R^T=I&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;  [1]: http://in2gpu.com/2015/05/17/view-matrix/&#xD;&#xA;  [2]: https://i.stack.imgur.com/M1tEW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/abmQx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24748" PostHistoryTypeId="2" PostId="9075" RevisionGUID="85059cfd-f1c2-4f7e-a69c-e4ad1a76bee9" CreationDate="2019-08-15T19:57:32.690" UserId="3385" Text="So I've been reading Physicall Based Rendering which in section 16.4.3 defines the &quot;image contribution function&quot; to be the following&#xD;&#xA;&#xD;&#xA;$$I_j = \int_\Omega h_j(X)L(X)d\Omega$$&#xD;&#xA;&#xD;&#xA;where the variables are defined in the following way as I understand them&#xD;&#xA;&#xD;&#xA;- The domain $\Omega$ is the space of paths in the scene&#xD;&#xA;- $h_j$ is the &quot;image reconstruction filter&quot; for the $j$th pixel on a given path. My understanding is that this really only depends on where the path is on image plane.&#xD;&#xA;- $I_j$ is the value of the $j$th pixel&#xD;&#xA;- $L$ is the radiance delivered on a given path&#xD;&#xA;&#xD;&#xA;They also give the following equation which is just an application of Monte Carlo importance sampling when drawing from a sample distribution $p$&#xD;&#xA;&#xD;&#xA;$$\int_\Omega h_j(X)L(X)d\Omega \approx \frac{1}{N}\sum_i^N \frac{h_j(X_i)L(X_i)}{p(X_i)}$$ &#xD;&#xA;&#xD;&#xA;Earlier in section 7.8 the define equation 7.12 to be the following&#xD;&#xA;&#xD;&#xA;$$I(x, y) = \frac{\sum_i f(x - x_i, y - y_i)w(x_i, y_i)L(x_i, y_i)}{\sum_i f(x - x_i, y - y_i)}$$&#xD;&#xA;&#xD;&#xA;Where the variables are defined in the following way as I understand them&#xD;&#xA;&#xD;&#xA; - $(x_i, y_i)$ is the location on the image plane of the $i$th sample&#xD;&#xA;   &#xD;&#xA; - $L(x_i, y_i)$ is the radiance delivered to $(x_i, y_i)$ by the $i$th&#xD;&#xA;   sample&#xD;&#xA;   &#xD;&#xA; - $I(x, y)$ is the value of the pixel at $(x, y)$&#xD;&#xA;   &#xD;&#xA; - $f$ is a filter function like a tent or sinc filter&#xD;&#xA;   &#xD;&#xA; - $w$ is a sample contribution weight. For simplicity of this&#xD;&#xA;   question. I'll assume this to just be the constantly $1$ function. In&#xD;&#xA;   the later chapters where the &quot;importance function&quot; appears to subsume&#xD;&#xA;   this or be the same thing&#xD;&#xA;&#xD;&#xA;So for a given pixel $j$ at location $(x, y)$ on the image I interpret $I(x, y) = I_j$ and for a given sample $L(X_i) = L(x_i, y_i)$ and given that I'm ignoring $w$ the following equation should hold. Taking $f(X_i) = f(x_i, y_i)$ as well&#xD;&#xA;&#xD;&#xA;$$\frac{\sum_i^N f(X_i)L(X_i)}{\sum_i^N f(X_i)} = \frac{1}{N}\sum_i^N \frac{h_j(X_i)L(X_i)}{p(X_i)}$$&#xD;&#xA;&#xD;&#xA;While its clear how to implement $f$ it isn't clear to me how to implement $h_j$. I considered that $L(x_i, y_i)$ might actually be $\frac{L(X_i)}{p(X_i)}$ in the importance sampling case which gets rid of the discrepancy caused by the probability distribution but that implies that $h_j$ must be defined to be the following&#xD;&#xA;&#xD;&#xA;$$h_j(X_i) = \frac{N \cdot f(X_i)}{\sum_i^N f(X_i)}$$&#xD;&#xA;&#xD;&#xA;But it doesn't seem to me that $h_j$ should be dependent on the number of samples $N$ which means I must have made a mistake in some assumption that I've made. I made a lot of assumptions to attempt to connect these to equations but I'm still at a loss. What mistakes have I made so far? How does one implement $h_j$ in the first equation from section 16.4.3?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24749" PostHistoryTypeId="1" PostId="9075" RevisionGUID="85059cfd-f1c2-4f7e-a69c-e4ad1a76bee9" CreationDate="2019-08-15T19:57:32.690" UserId="3385" Text="Image contribution function and reconstruction using filters" ContentLicense="CC BY-SA 4.0" />
  <row Id="24750" PostHistoryTypeId="3" PostId="9075" RevisionGUID="85059cfd-f1c2-4f7e-a69c-e4ad1a76bee9" CreationDate="2019-08-15T19:57:32.690" UserId="3385" Text="|pathtracing|physically-based|filtering|photo-realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24751" PostHistoryTypeId="50" PostId="8151" RevisionGUID="a76fde4a-8c26-4f50-9246-f802301b5fbe" CreationDate="2019-08-16T00:01:10.867" UserId="-1" />
  <row Id="24752" PostHistoryTypeId="50" PostId="7730" RevisionGUID="bb580063-1feb-4f88-becb-66008e209f72" CreationDate="2019-08-16T02:00:45.077" UserId="-1" />
  <row Id="24755" PostHistoryTypeId="2" PostId="9077" RevisionGUID="40a27bc9-bf6a-426f-8079-3bafa2501159" CreationDate="2019-08-16T08:30:05.967" UserId="11062" Text="Is there an efficient algorithm to convert a 3D object described with a set of triangles to a 3D object described with a set of polygons. Polygons can have an arbitrary number of points, more is better. I'd like to minimize the number of polygons necessary to describe the 3D object but it does not have to be optimal. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24756" PostHistoryTypeId="1" PostId="9077" RevisionGUID="40a27bc9-bf6a-426f-8079-3bafa2501159" CreationDate="2019-08-16T08:30:05.967" UserId="11062" Text="Convert triangulated object to a polygonized object" ContentLicense="CC BY-SA 4.0" />
  <row Id="24757" PostHistoryTypeId="3" PostId="9077" RevisionGUID="40a27bc9-bf6a-426f-8079-3bafa2501159" CreationDate="2019-08-16T08:30:05.967" UserId="11062" Text="|algorithm|polygon|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24758" PostHistoryTypeId="2" PostId="9078" RevisionGUID="b8d65f9a-ace3-4d37-a2ac-c865aeb5ce20" CreationDate="2019-08-16T09:19:14.953" UserId="10980" Text="I guess what you wanna achieve is mesh simplification. Then those materials can be useful for you.&#xD;&#xA;&#xD;&#xA;http://graphics.stanford.edu/courses/cs468-10-fall/LectureSlides/08_Simplification.pdf&#xD;&#xA;&#xD;&#xA;https://pages.mtu.edu/~shene/COURSES/cs3621/SLIDES/Simplification.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24759" PostHistoryTypeId="5" PostId="9077" RevisionGUID="8a7542b7-234c-46bc-8969-0e8e347e58ad" CreationDate="2019-08-16T09:31:46.140" UserId="11062" Comment="added 38 characters in body" Text="Is there an efficient algorithm to convert a 3D object described with a set of triangles to a 3D object described with a set of polygons. Polygons can have an arbitrary number of points, more is better. I'd like to minimize the number of polygons necessary to describe the 3D object but it does not have to be optimal.&#xD;&#xA;&#xD;&#xA;The 3D object should stay the same." ContentLicense="CC BY-SA 4.0" />
  <row Id="24760" PostHistoryTypeId="2" PostId="9079" RevisionGUID="029ec3b9-a875-4cd9-aca4-1144e3344135" CreationDate="2019-08-16T10:48:06.790" UserId="11058" Text="When working with animating a rig, quaternions are often used for rotations. However sometimes we need to clear rotation along given local axis of a  joint. With quaternions it's not as simple as just clearing out one component of the quaternion. Doing this will clear out the rotation along that axis, but it will also affect rotation along other axes since the W value of quaternion is interdependent on all three axes.&#xD;&#xA;&#xD;&#xA;Take Blender3D as example. You can key a euler rotation for a given joint. If you then are not satisfied with rotation along say Y axis, you could just remove Y rotation channel for the whole animation. With quaternions this does not work as well. &#xD;&#xA;&#xD;&#xA;How do animators and riggers handle this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24761" PostHistoryTypeId="1" PostId="9079" RevisionGUID="029ec3b9-a875-4cd9-aca4-1144e3344135" CreationDate="2019-08-16T10:48:06.790" UserId="11058" Text="Pitfalls of animating with quaternions" ContentLicense="CC BY-SA 4.0" />
  <row Id="24762" PostHistoryTypeId="3" PostId="9079" RevisionGUID="029ec3b9-a875-4cd9-aca4-1144e3344135" CreationDate="2019-08-16T10:48:06.790" UserId="11058" Text="|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24763" PostHistoryTypeId="5" PostId="9077" RevisionGUID="ea39c069-d456-492b-8cc2-68cdfd609b24" CreationDate="2019-08-16T12:42:16.530" UserId="11062" Comment="added 31 characters in body" Text="Is there an efficient algorithm to convert a 3D object described with a set of triangles to a 3D object described with a set of polygons. Polygons can have an arbitrary number of points, more is better. I'd like to minimize the number of polygons necessary to describe the 3D object but it does not have to be optimal.&#xD;&#xA;&#xD;&#xA;The 3D object should stay the same.&#xD;&#xA;&#xD;&#xA;Polygons can be non-planar." ContentLicense="CC BY-SA 4.0" />
  <row Id="24764" PostHistoryTypeId="2" PostId="9080" RevisionGUID="e4af443b-a550-4e8c-a528-e5a27b829136" CreationDate="2019-08-16T19:32:40.680" UserId="9194" Text="I would try a rim-filling approach starting with a good guess for a central triangle. Rinse, repeat." ContentLicense="CC BY-SA 4.0" />
  <row Id="24765" PostHistoryTypeId="2" PostId="9081" RevisionGUID="dc8c7e60-8765-4a40-a292-80911be47985" CreationDate="2019-08-16T22:18:51.167" UserId="5215" Text="I'm running following compute shader in Vulkan. worldImage is device local memory that holds the world. resultImage is reference to the memory of the swapchain image:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    layout (binding = 0, rgba8) uniform writeonly image2D resultImage;&#xD;&#xA;    layout (binding = 1, r16ui) uniform readonly uimage3D worldImage;&#xD;&#xA;    &#xD;&#xA;    layout(push_constant) uniform PushConstants {&#xD;&#xA;    	vec3 rayOrigin;&#xD;&#xA;    	float viewGridTopLeftCornerX;&#xD;&#xA;    &#xD;&#xA;    	vec3 viewGridRight;&#xD;&#xA;    	float viewGridTopLeftCornerY;&#xD;&#xA;    &#xD;&#xA;    	vec3 viewGridDown;&#xD;&#xA;    	float viewGridTopLeftCornerZ;&#xD;&#xA;    &#xD;&#xA;    	float viewGridDensity;&#xD;&#xA;    } push;&#xD;&#xA;   &#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;    	vec3 viewGridTopLeftCorner = vec3(push.viewGridTopLeftCornerX, push.viewGridTopLeftCornerY, push.viewGridTopLeftCornerZ);&#xD;&#xA;    	vec3 samplePoint = viewGridTopLeftCorner + push.viewGridDensity * (gl_GlobalInvocationID.x * push.viewGridRight + gl_GlobalInvocationID.y * push.viewGridDown);&#xD;&#xA;    &#xD;&#xA;    	vec3 ray = normalize(samplePoint - push.rayOrigin);&#xD;&#xA;    	vec3 inverseRay = 1 / ray;&#xD;&#xA;    &#xD;&#xA;    	ivec3 voxelCoords = ivec3(floor(push.rayOrigin.x), floor(push.rayOrigin.y), floor(push.rayOrigin.z));&#xD;&#xA;    	ivec3 rayOrientation = ivec3(sign(ray));&#xD;&#xA;    	ivec3 rayPositivity = (1 + rayOrientation) &gt;&gt; 1;&#xD;&#xA;    	vec3 withinVoxelCoords = push.rayOrigin - voxelCoords;&#xD;&#xA;    &#xD;&#xA;    	uint blockID = 0;&#xD;&#xA;    	int smallestComponentIndex;&#xD;&#xA;    	do {&#xD;&#xA;    		// Calculate how far each of the neighbouring voxels are&#xD;&#xA;    		vec3 distanceFactor = (rayPositivity - withinVoxelCoords) * inverseRay;&#xD;&#xA;    &#xD;&#xA;    		// Pinpoint the closest voxel of the three candidates&#xD;&#xA;    		smallestComponentIndex = distanceFactor.x &lt; distanceFactor.y&#xD;&#xA;    		? (distanceFactor.x &lt; distanceFactor.z ? 0 : 2)&#xD;&#xA;    		: (distanceFactor.y &lt; distanceFactor.z ? 1 : 2);&#xD;&#xA;    &#xD;&#xA;    		// Move to that voxel&#xD;&#xA;    		voxelCoords[smallestComponentIndex] += rayOrientation[smallestComponentIndex];&#xD;&#xA;    &#xD;&#xA;    		// Advance the ray the distance to the closest voxel in all dimensions&#xD;&#xA;    		withinVoxelCoords += ray * distanceFactor[smallestComponentIndex];&#xD;&#xA;    &#xD;&#xA;    		// The axis towards the next voxel will now have value -1 or 1. Next line resets it to 0.&#xD;&#xA;    		// It can be imageined as going jumping the side of the previus voxel to the side of the next one.&#xD;&#xA;    		withinVoxelCoords[smallestComponentIndex] = 1 - rayPositivity[smallestComponentIndex];&#xD;&#xA;    		&#xD;&#xA;    		blockID = imageLoad(worldImage, voxelCoords).r;&#xD;&#xA;    	} while (blockID == 0);&#xD;&#xA;    &#xD;&#xA;    	switch (blockID) {&#xD;&#xA;    		case 1:&#xD;&#xA;    			vec3 normal = vec3(0, 0, 0);&#xD;&#xA;    			normal[smallestComponentIndex] = rayOrientation[smallestComponentIndex];&#xD;&#xA;    			imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0, 1.0 * dot(ray, normal), 0.0, 1.0));&#xD;&#xA;    			break;&#xD;&#xA;    		case 2:&#xD;&#xA;    			imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(1.0, 0.0, 0.0, 1.0));&#xD;&#xA;    			break;&#xD;&#xA;    		default:&#xD;&#xA;    			imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code traces one ray per pixel until it hits a block (value 1) or the edge (value 2, every edge block has the value 2).&#xD;&#xA;&#xD;&#xA;If the parameters are:&#xD;&#xA;&#xD;&#xA;  -  32x32x32 world with player standing in the middle (so ray tracing itself goes through half of the voxels at worst)&#xD;&#xA;  -   1280x720 resolution (gl_GlobalInvocationID x and y)&#xD;&#xA;&#xD;&#xA;It takes about 50ms to render one frame on GTX 1050 or about 5ms on RTX 2080 Ti.&#xD;&#xA;&#xD;&#xA;The main loop acquires the image, submits the command buffer which transitions the image to proper (general) layout, binds the pipeline and descriptor sets, pushes the push_constants, dispatches the compute shader and transitions image to present layout again. This is what happens in those 50ms/5ms.&#xD;&#xA;&#xD;&#xA;I ran similar code on a single CPU core (i5 4760K) and it takes about 250ms.&#xD;&#xA;This would be equivalent to running just the shader code though.&#xD;&#xA;&#xD;&#xA;I can't believe that something like this would be only five times faster on the GPU than on the CPU.&#xD;&#xA;&#xD;&#xA;I have no experience in graphics, so I can't really tell. Is this really the time it takes for this, or could I expect (hopefully a much) better performance, once I fix whatever is bogging this down?&#xD;&#xA;&#xD;&#xA;Could it be the memory access on the GPU? I don't know what else it could be." ContentLicense="CC BY-SA 4.0" />
  <row Id="24766" PostHistoryTypeId="1" PostId="9081" RevisionGUID="dc8c7e60-8765-4a40-a292-80911be47985" CreationDate="2019-08-16T22:18:51.167" UserId="5215" Text="Compute shader only 5 times faster on the GPU than on the CPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="24767" PostHistoryTypeId="3" PostId="9081" RevisionGUID="dc8c7e60-8765-4a40-a292-80911be47985" CreationDate="2019-08-16T22:18:51.167" UserId="5215" Text="|raytracing|vulkan|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24772" PostHistoryTypeId="8" PostId="6119" RevisionGUID="bec7f3ec-135e-40b1-aaae-51a6f97394c8" CreationDate="2019-08-17T21:01:54.363" UserId="8033" Comment="Rollback to [3d4d45c9-b4ae-4e68-9c31-48a67f4e57b4] - Edit approval overridden by post owner or moderator" Text="Whenever you make a part in inventor, the software calculates de properties of the whole body given a constant density. Then, automatically,  it shows the inertial tensor. As you can recall from math, the inertia equation is $I_x= \rho\int(y^2+z^2)dV$&#xD;&#xA;for the x axis. So, clearing rho, how can I get the right hand of the equation that is been solved in the underlying algorithm without doing any hand calculations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24773" PostHistoryTypeId="50" PostId="8587" RevisionGUID="f3f1b4ed-5904-49d6-a08e-2bfa0468f482" CreationDate="2019-08-19T10:03:05.370" UserId="-1" />
  <row Id="24774" PostHistoryTypeId="2" PostId="9083" RevisionGUID="28398e3b-2004-48e7-9098-20e5f2519838" CreationDate="2019-08-19T18:55:08.653" UserId="11035" Text="I started a raytracing project using the python numba library which provides a just-in-time compiler for CUDA kernels. When the scene is rendered my result is a 1920 x 1080 x 3 RGB array in GPU memory. If I only want to display a single image I can grab the result and save it to a .PNG file. My results are great so far, however, my long-term goal is to make a real-time engine with ray-tracing computations.&#xD;&#xA;&#xD;&#xA;I am aware that python numba does not support CUDA - OPENGL interoperability,  so currently I grab the image from CUDA, and then render it as a texture on the screen. This results in the raytracing being only 3% of computational time. (I can do 30 fps using python arcade and rendering one frame is about 1 ms.)&#xD;&#xA;&#xD;&#xA; - Is there a way to interface CUDA with DirectX/Vulkan/OpenGL to show what the GPU already has in memory? &#xD;&#xA;&#xD;&#xA;If not, then I am ready to port the project to a different language and use a different API.&#xD;&#xA;&#xD;&#xA;  - What library/API/language should I port this raytracing project to display my algorithm real-time on the screen?&#xD;&#xA;&#xD;&#xA;PS: I am quite new to computer graphics, so I don't get the full picture yet. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24775" PostHistoryTypeId="1" PostId="9083" RevisionGUID="28398e3b-2004-48e7-9098-20e5f2519838" CreationDate="2019-08-19T18:55:08.653" UserId="11035" Text="How to display image from CUDA / What API to port my project to for real-time raytracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24776" PostHistoryTypeId="3" PostId="9083" RevisionGUID="28398e3b-2004-48e7-9098-20e5f2519838" CreationDate="2019-08-19T18:55:08.653" UserId="11035" Text="|raytracing|rendering|real-time|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24777" PostHistoryTypeId="2" PostId="9084" RevisionGUID="2ff31aa5-a757-42a5-8751-337666b31d46" CreationDate="2019-08-20T08:46:12.323" UserId="11073" Text="Actually what it meant by Affine Covariant regions is that covariant regions in two images which are related by some affine transformation. So the regions found in one image and those are exactly same regions in other image which have been transformed through affine transformation.&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="24778" PostHistoryTypeId="5" PostId="8989" RevisionGUID="946ca318-581a-4a08-9271-a36aeca94084" CreationDate="2019-08-20T10:58:36.493" UserId="6046" Comment="deleted 1 character in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][2]. **You can see my Renderer's result in [this][3] video** (check the end of my post and sorry for not providing a direct link as I already uploaded on my reddit post)&#xD;&#xA;&#xD;&#xA;As you can see the lobster dataset stretches when viewed from the side. My first guess was that I wasn't accounting for the aspect ratio correctly. I have tried scaling the Bounding box to account for the aspect ratio, then adjusting the stepsize according to that. I've also tried to ignore aspect ratio altogether. Both give similar images.&#xD;&#xA;&#xD;&#xA;I tried rendering more datasets like &quot;Knee&quot;, &quot;Bruce's head&quot;, &quot;DTI Scan&quot;, etc but those didn't even gave an image. There was just random noise everywhere. Here's an example of &quot;Bruce's head&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This happens with both uniform and non-uniform datasets. If some datasets are getting rendered correctly like the &quot;Foot&quot; in my video, this should mean it's more a with that specific dataset itself rather the core algorithm. Nonetheless the link to the code is provided. If anybody can point out some mistakes I'd be grateful.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][5]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, it's normalized `(0-1)`, accounted for the aspect ratio `(0, ar)` and adjusted so it's in the center `(-ar/2, ar/2)`. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;EDIT:- If you are hesitating to post an answer here since it's only a suggestion, you can post on Reddit, then when the problem is solved you can post your answer here&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [3]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [4]: https://i.stack.imgur.com/EXyYg.png&#xD;&#xA;  [5]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24779" PostHistoryTypeId="2" PostId="9085" RevisionGUID="db92c3fd-8b5b-49fd-8c72-e22e237d5d48" CreationDate="2019-08-20T22:32:31.757" UserId="11077" Text="I am trying to understand how the generation of irradiance maps works. I was reading [LearnOpengGL tutorial][1] and [Codinglabs article][2]. Reading those articles, I got a bit confused about how we use convolution to generate the irradiance map.&#xD;&#xA;&#xD;&#xA;Do we apply the integral to the environment map to convolute it, and do we do it because our environment map is equirectangular?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/IBL/Diffuse-irradiance&#xD;&#xA;  [2]: http://www.codinglabs.net/article_physically_based_rendering.aspx" ContentLicense="CC BY-SA 4.0" />
  <row Id="24780" PostHistoryTypeId="1" PostId="9085" RevisionGUID="db92c3fd-8b5b-49fd-8c72-e22e237d5d48" CreationDate="2019-08-20T22:32:31.757" UserId="11077" Text="Understanding the irradiance map generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="24781" PostHistoryTypeId="3" PostId="9085" RevisionGUID="db92c3fd-8b5b-49fd-8c72-e22e237d5d48" CreationDate="2019-08-20T22:32:31.757" UserId="11077" Text="|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24782" PostHistoryTypeId="2" PostId="9086" RevisionGUID="72d930b7-d1b7-46ae-8c59-cb7c6e6cfbc9" CreationDate="2019-08-20T23:01:40.490" UserId="7462" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the above image, you can see that there is some slight variation of the height of each wood plank. These variations do NOT come from the wood texture itself, but from the way it was cut, i.e if a different tool had been used to cut the same plank, it would look different.= and exhibit the pattern of the tool used.&#xD;&#xA;&#xD;&#xA;I am trying to use a perlin noise generated heightmap to approximate, to the best of my ability, this &quot;wavy&quot; pattern exhibited.&#xD;&#xA;&#xD;&#xA;This image is better to see the pattern:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have tried multiple strategies to modify perlin noise but I can't quite get heightmaps that look like the prior images.&#xD;&#xA;&#xD;&#xA;My strategies so far are based around:&#xD;&#xA;&#xD;&#xA;Stretching perlin noise along one direction, taking powers of linear combinations of the sampled noise to try to get a &quot;bowl&quot; shape, similar to the corner of the bottom image.&#xD;&#xA;&#xD;&#xA;Does anyone have suggestions?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/saZHn.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ryqn4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24783" PostHistoryTypeId="1" PostId="9086" RevisionGUID="72d930b7-d1b7-46ae-8c59-cb7c6e6cfbc9" CreationDate="2019-08-20T23:01:40.490" UserId="7462" Text="How to approximate heightmap of processed wood?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24784" PostHistoryTypeId="3" PostId="9086" RevisionGUID="72d930b7-d1b7-46ae-8c59-cb7c6e6cfbc9" CreationDate="2019-08-20T23:01:40.490" UserId="7462" Text="|shading|noise|procedural-generation|height-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24785" PostHistoryTypeId="4" PostId="9086" RevisionGUID="f28669f6-5f23-4f05-8949-9b247c71916d" CreationDate="2019-08-21T14:49:12.470" UserId="7462" Comment="edited title" Text="How to approximate the heightmap of processed wood?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24786" PostHistoryTypeId="2" PostId="9087" RevisionGUID="cd0fc9e9-bae4-412e-81a7-8fbe012cd6c9" CreationDate="2019-08-21T15:00:29.163" UserId="11080" Text="Are there any reasons to use power of two textures (like 128x128 sized) if one targets modern mobile platforms (with OpenGL ES 3.0, Metal and/or Vulkan)?&#xD;&#xA;&#xD;&#xA;With iOS the PVRTC only supports power of two textures that have equal width and height, but e.g. ETC2 and ASTC do not have limits like that. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24787" PostHistoryTypeId="1" PostId="9087" RevisionGUID="cd0fc9e9-bae4-412e-81a7-8fbe012cd6c9" CreationDate="2019-08-21T15:00:29.163" UserId="11080" Text="Are there any reasons to use power of two textures with modern mobile platforms?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24788" PostHistoryTypeId="3" PostId="9087" RevisionGUID="cd0fc9e9-bae4-412e-81a7-8fbe012cd6c9" CreationDate="2019-08-21T15:00:29.163" UserId="11080" Text="|texture|vulkan|opengl-es|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24789" PostHistoryTypeId="2" PostId="9088" RevisionGUID="d50ed863-e0b8-4057-8512-08f1d16cc723" CreationDate="2019-08-21T23:03:09.233" UserId="48" Text="A sine wave remapped to [0, 1] and raised to a power will give you periodic ridges: ([Desmos graph](https://www.desmos.com/calculator/tyr0wno1n5))&#xD;&#xA;&#xD;&#xA;[![graph of sine wave to a power][1]][1]&#xD;&#xA;&#xD;&#xA;That could be a good place to start. It will make perfectly straight, even ridges; but you could then perturb the X position where the sine is evaluated using low-frequency Perlin noise, which will make the ridges bend and waver while still going mostly along the original axis. You could use noise to fluctuate the power that the sine is raised to as well, making the ridges smoother and sharper in different places.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NG092.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24790" PostHistoryTypeId="2" PostId="9089" RevisionGUID="a294a127-56e9-4a10-bdc4-a23d31ab8aff" CreationDate="2019-08-21T23:19:15.460" UserId="48" Text="Yes, the convolution is effectively evaluating the following integral:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\text{irradianceMap}(\vec n) = \frac{1}{\pi} \int \text{environmentMap}(\vec \omega_i) \, \max(\vec n \cdot \vec \omega_i, 0) \, d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This convolution isn't about whether the environment map is equirectangular, cubemap, or some other projection. We still have to do the convolution regardless, because we want to get the total diffuse light (irradiance) coming to a surface with a given normal, from all directions in the hemisphere around that normal. The environment map to start with just has light from one direction (radiance)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24791" PostHistoryTypeId="2" PostId="9090" RevisionGUID="66c4c1a1-6b28-429a-9a95-bded481fdcb7" CreationDate="2019-08-22T04:41:36.067" UserId="2316" Text="You need to set the colour back to white before drawing the framebuffer to the screen. Otherwise, the whole framebuffer gets multiplied with red.&#xD;&#xA;&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;    glColor3f(1, 1, 1); // &lt;------- add this (doesn't have to be exactly here)&#xD;&#xA;&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, fbo_tex[0]);&#xD;&#xA;    glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, SCRWIDTH, SCRHEIGHT, 0, -1, 1);&#xD;&#xA;    glMatrixMode(GL_MODELVIEW); glLoadIdentity();&#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_QUADS);&#xD;&#xA;        glTexCoord2f(0, 0); glVertex3i(0, 0, 0);&#xD;&#xA;        glTexCoord2f(0, 1); glVertex3i(0, SCRHEIGHT, 0);&#xD;&#xA;        glTexCoord2f(1, 1); glVertex3i(SCRWIDTH, SCRHEIGHT, 0);&#xD;&#xA;        glTexCoord2f(1, 0); glVertex3i(SCRWIDTH, 0, 0);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="24792" PostHistoryTypeId="2" PostId="9091" RevisionGUID="e8d10235-e2f7-4589-8ced-8d89f48704a7" CreationDate="2019-08-22T08:59:42.520" UserId="11084" Text="I have a textured 3D object and looking for ways to transform back the texture. Effectively, I think this is an inverse texture mapping task. Do you know of anything close to this? Some papers or implementations that already solved this task you know of?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24793" PostHistoryTypeId="1" PostId="9091" RevisionGUID="e8d10235-e2f7-4589-8ced-8d89f48704a7" CreationDate="2019-08-22T08:59:42.520" UserId="11084" Text="Inverse texture mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="24794" PostHistoryTypeId="3" PostId="9091" RevisionGUID="e8d10235-e2f7-4589-8ced-8d89f48704a7" CreationDate="2019-08-22T08:59:42.520" UserId="11084" Text="|texture|projections|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24795" PostHistoryTypeId="5" PostId="9091" RevisionGUID="b57af6f8-5f5f-4338-a253-9b79a41aefdd" CreationDate="2019-08-22T09:42:55.103" UserId="11084" Comment="added 255 characters in body" Text="I have a textured 3D object and looking for ways to transform back the texture. Effectively, I think this is an inverse texture mapping task. Do you know of anything close to this? Some papers or implementations that already solved this task you know of?&#xD;&#xA;&#xD;&#xA;As has been asked: The background is a &quot;complex 3d object&quot; (think of the shape/form of a non-regular potato, for example). Now, that object is randomly textured at run-time and I would like to restore that texture to the 2d space for further analysis (using machine learning techniques)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24796" PostHistoryTypeId="2" PostId="9092" RevisionGUID="4a1a4b15-8ea9-4fab-8b9c-3d80d2a7e751" CreationDate="2019-08-22T18:39:21.093" UserId="11087" Text="I'm writing my own UV Unfold operation (similar to Maya's Optimize UV tool or 3DS Max's Relax Tool).  My code works great 90% of the time but in some instances, I'm getting faces and edges that flip on top of each other.  This causes the faces to orient in a different direction than intended.&#xD;&#xA;&#xD;&#xA;I'm trying to find a good approach to detecting when this flip occurs to either prevent it beforehand or correct it when it does happen.  I'm currently testing the dot product of the 2D normal compared with the dot product of the previous normal after I move the uvs.  Is this a decent approach?  Am I missing another simple algorithm or check that could prevent the overlap?&#xD;&#xA;&#xD;&#xA;3D mesh for testing&#xD;&#xA;&#xD;&#xA;[![Image of the 3D Mesh][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Results with my algorithm with overlapped faces and edges.&#xD;&#xA;&#xD;&#xA;[![Current results with my code][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Maya's optimize results.&#xD;&#xA;&#xD;&#xA;[![Maya Optimize Results][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SLX9r.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/uoSFd.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/nYFg5.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24797" PostHistoryTypeId="1" PostId="9092" RevisionGUID="4a1a4b15-8ea9-4fab-8b9c-3d80d2a7e751" CreationDate="2019-08-22T18:39:21.093" UserId="11087" Text="How can I detect if an edge has flipped during the UV unfold process?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24798" PostHistoryTypeId="3" PostId="9092" RevisionGUID="4a1a4b15-8ea9-4fab-8b9c-3d80d2a7e751" CreationDate="2019-08-22T18:39:21.093" UserId="11087" Text="|3d|texture|algorithm|mathematics|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24799" PostHistoryTypeId="2" PostId="9093" RevisionGUID="9b5eb0f5-0082-417c-9d07-e9a9e1ccad8d" CreationDate="2019-08-22T21:48:59.537" UserId="11089" Text="I see two kinds of passing Instance Data to **Vertex Shader** in different Examples.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1** .Using a **Uniform Buffer** and filling in an array, like below&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    struct UniformBlock&#xD;&#xA;    {&#xD;&#xA;    	mat4 mProjectView;&#xD;&#xA;    	mat4 mToWorldMat[MAX_INSTANCE];&#xD;&#xA;    	vec4 mColor[MAX_INSTANCES];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;**2**. Filling in buffers, and then define the buffer as **RATE_PER_INSTANCE**  in vertex layout description (I assume this is the more usual way)&#xD;&#xA;&#xD;&#xA;* My Question is :&#xD;&#xA;&#xD;&#xA; * How do these differ from **hardware** or **memory access** Point of View?&#xD;&#xA; * Are there any cases which one is considered &quot;better&quot; or &quot;faster&quot; than the other?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24800" PostHistoryTypeId="1" PostId="9093" RevisionGUID="9b5eb0f5-0082-417c-9d07-e9a9e1ccad8d" CreationDate="2019-08-22T21:48:59.537" UserId="11089" Text="Difference between Passing Instance Data to Vertex Shader methods" ContentLicense="CC BY-SA 4.0" />
  <row Id="24801" PostHistoryTypeId="3" PostId="9093" RevisionGUID="9b5eb0f5-0082-417c-9d07-e9a9e1ccad8d" CreationDate="2019-08-22T21:48:59.537" UserId="11089" Text="|vulkan|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24802" PostHistoryTypeId="2" PostId="9094" RevisionGUID="b1ddd89a-fe46-4668-a9fb-cbad2c1f4901" CreationDate="2019-08-23T05:53:28.480" UserId="11041" Text="Thanks so much for everyone's replies. It really helped to see any reply that kind of encouraged me to continue.&#xD;&#xA;&#xD;&#xA;So after some hours of working out the issue it turns out this is correct on the sphere. The above image is correct. As Dan kindly pointed out and as I later drew it out on paper and tried lights of different heights, the higher the light, the lower the cutoff. Because the light was so close to the sphere only its top was intensely illuminated.&#xD;&#xA;&#xD;&#xA;The thing I had gotten incorrect were actually the ellipses normal transforms, which I didn't include in the post because I thought it was more complex, get the basics right first. So it turns out I had to create a different stack to store the non-uniform transforms as it was being read from the file so that the ellipses' normals could be transformed correctly.&#xD;&#xA;&#xD;&#xA;So lesson learned - understand all the cases before implementing them. &#xD;&#xA;&#xD;&#xA;But I really appreciate this platform! Thanks and cheers to all&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24803" PostHistoryTypeId="2" PostId="9095" RevisionGUID="59b25da4-df4c-4d6e-801b-4d4ab747d298" CreationDate="2019-08-23T07:26:45.893" UserId="386" Text="As a quick reminder, [here][1] is what normal matrix is and why do we need it.&#xD;&#xA;&#xD;&#xA;Now the question - if I take the light position and transform it into an object space than I don't need the normal matrix at all and actually it will save me a good amount of calculations (don't need to multiply a normal by the matrix). By I can't draw a mental picture of how this could work for a scaled object, what does it mean to transform a point (light position) into a scaled object space? And what about a directional light where I have no position at all?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.lighthouse3d.com/tutorials/glsl-12-tutorial/the-normal-matrix/" ContentLicense="CC BY-SA 4.0" />
  <row Id="24804" PostHistoryTypeId="1" PostId="9095" RevisionGUID="59b25da4-df4c-4d6e-801b-4d4ab747d298" CreationDate="2019-08-23T07:26:45.893" UserId="386" Text="Do I need a normal matrix if I calculate lighting in an objects space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24805" PostHistoryTypeId="3" PostId="9095" RevisionGUID="59b25da4-df4c-4d6e-801b-4d4ab747d298" CreationDate="2019-08-23T07:26:45.893" UserId="386" Text="|lighting|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24807" PostHistoryTypeId="2" PostId="9096" RevisionGUID="01a58657-e75d-48a1-a51d-8663c928925b" CreationDate="2019-08-24T18:54:50.743" UserId="6596" Text="These are all good answers, and yet there is another way: (Isn't there always?)&#xD;&#xA;&#xD;&#xA;Due to the growing popularity of virtual reality, the folks at OculusVR have developed a trio of &quot;Multiview&quot; extensions called:&#xD;&#xA;&#xD;&#xA; 1. **OVR_multiview**,&#xD;&#xA; 2. **OVR_multiview2**, &amp;&#xD;&#xA; 3. **OVR_multiview_multisampled_render_to_texture**&#xD;&#xA;&#xD;&#xA;These extensions allow multiple views of the same scene to be rendered in a single draw call, eliminating the redundancy of rendering the same scene in the same state from the viewpoint of each eye. Although created for the purpose of VR, the developer is not necessarily limited to merely two views. Rather, this extension allows for as many views as **MAX_VIEWS_OVR** specifies.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Before using these extensions, the developer should check for their support in the user's graphics driver by adding the following code:&#xD;&#xA;&#xD;&#xA;    const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );&#xD;&#xA;    char * found_extension = strstr( (const char*)extensions, &quot;GL_OVR_multiview&quot; );&#xD;&#xA;    if (NULL == found_extension)&#xD;&#xA;    {&#xD;&#xA;         exit( EXIT_FAILURE );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;From there, it is a matter of setting up your framebuffer to utilize this feature:&#xD;&#xA;&#xD;&#xA;    glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress(&quot;glFramebufferTextureMultisampleMultiviewOVR&quot;));&#xD;&#xA;    glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);&#xD;&#xA;&#xD;&#xA;and likewise in the shader:&#xD;&#xA;&#xD;&#xA;    #version 300 es&#xD;&#xA;    #extension GL_OVR_multiview : enable&#xD;&#xA;&#xD;&#xA;    layout(num_views = 2) in;&#xD;&#xA;    in vec3 vertexPosition;&#xD;&#xA;    uniform mat4 MVP[2];&#xD;&#xA;&#xD;&#xA;    void main(){&#xD;&#xA;        gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In a CPU-bound application, this extension can *dramatically* reduce rendering time, *especially with more complex scenes*:&#xD;&#xA;&#xD;&#xA;[![Relative CPU time between multiview and regular stereo. The smaller the better, with the number of cubes on the x-axis and the relative time on the y-axis.][1]][1]&#xD;&#xA;  [1]: https://i.stack.imgur.com/6nrze.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24808" PostHistoryTypeId="2" PostId="9097" RevisionGUID="c3f43950-efcd-411a-9f6e-1f69e07b78e8" CreationDate="2019-08-24T22:23:29.933" UserId="11099" Text="I've written a shader that writes depth to each face of a cube map, as part of rendering cube map shadows for a realtime 3D engine I'm writing with OpenGL and C++.&#xD;&#xA;&#xD;&#xA;The shader transforms each vertex into world space in the vertex shader, then transforms polygons to each of the cube map's 6 faces in the geometry shader, and then writes depth to the cube map in the fragment shader.&#xD;&#xA;&#xD;&#xA;The shader works correctly, but I receive the following error message when rendering with it for the first time:&#xD;&#xA;```&#xD;&#xA;Error:  OpenGL Error Callback:&#xD;&#xA;Source:&#xD;&#xA;Type: PERFORMANCE&#xD;&#xA;id: 131218&#xD;&#xA;Severity: MEDIUM&#xD;&#xA;Message: Program/shader state performance warning: Vertex shader in program 89 is being recompiled based on GL state.&#xD;&#xA;```&#xD;&#xA;After that, the shader functions perfectly and I'm able to render depth to a cube map, and use it to render shadows for my point lights.&#xD;&#xA;&#xD;&#xA;The shader has a vertex, geometry, and fragment shader component:&#xD;&#xA;&#xD;&#xA;**Vertex:**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 in_position;&#xD;&#xA;&#xD;&#xA;uniform mat4 in_model;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    gl_Position = in_model * vec4(in_position.xyz, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Geometry**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;layout (triangles) in;&#xD;&#xA;layout (triangle_strip, max_vertices = 18) out;&#xD;&#xA;&#xD;&#xA;uniform mat4 shadowCamCubeMap_vp[6];&#xD;&#xA;&#xD;&#xA;out vec4 FragPos;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	for(int currentCubeFace = 0; currentCubeFace &lt; 6; currentCubeFace++)&#xD;&#xA;    {&#xD;&#xA;        gl_Layer = currentCubeFace; // Set the cube map face we're rendering to&#xD;&#xA;&#xD;&#xA;        for(int currentVert = 0; currentVert &lt; 3; currentVert++)&#xD;&#xA;        {				&#xD;&#xA;				FragPos = gl_in[currentVert].gl_Position; // World pos from vert shader&#xD;&#xA;&#xD;&#xA;				gl_Position = shadowCamCubeMap_vp[currentCubeFace] * gl_in[currentVert].gl_Position;&#xD;&#xA;			&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }    &#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Fragment:**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;uniform vec3 lightWorldPos;	&#xD;&#xA;&#xD;&#xA;uniform float shadowCam_near;&#xD;&#xA;uniform float shadowCam_far;&#xD;&#xA;&#xD;&#xA;in vec4 FragPos;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	float lightDistance = length(FragPos.xyz - lightWorldPos);&#xD;&#xA;    &#xD;&#xA;	lightDistance = lightDistance / shadowCam_far;&#xD;&#xA;    &#xD;&#xA;    gl_FragDepth = lightDistance;&#xD;&#xA;} &#xD;&#xA;```&#xD;&#xA;If I delete the geometry shader and just compile the vertex and fragment shaders together, the issue still occurs.&#xD;&#xA;&#xD;&#xA;If I try and debug the program in RenderDoc, the error does not occur (!!).&#xD;&#xA;&#xD;&#xA;I'm scratching my head here. The vertex shader looks near identical to other vertex shaders I'm using.&#xD;&#xA;&#xD;&#xA;I've poured over every google result I could find, but still don't have any idea what's going on here. One thread suggested that, possibly, some part of the OpenGL state was compiled into the program when the shader was first loaded. Then, at some point the state was changed, triggering a recompile when the shader is first used to render something... But it didn't offer any solutions and I'm not really sure if/how this could be the case.&#xD;&#xA;&#xD;&#xA;I'd appreciate any help I can get here!" ContentLicense="CC BY-SA 4.0" />
  <row Id="24809" PostHistoryTypeId="1" PostId="9097" RevisionGUID="c3f43950-efcd-411a-9f6e-1f69e07b78e8" CreationDate="2019-08-24T22:23:29.933" UserId="11099" Text="Why is OpenGL recompiling my depth map vertex shader based on the GL state?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24810" PostHistoryTypeId="3" PostId="9097" RevisionGUID="c3f43950-efcd-411a-9f6e-1f69e07b78e8" CreationDate="2019-08-24T22:23:29.933" UserId="11099" Text="|opengl|shader|shadow-mapping|depth-map|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24813" PostHistoryTypeId="2" PostId="9098" RevisionGUID="a8b30542-e82a-47a8-99f9-c841dddca6d5" CreationDate="2019-08-25T09:52:48.220" UserId="2817" Text="This is an example of implementation details leaking through the abstraction. Parts of the GL state are often implemented via native GPU ISA instructions that the driver injects into user-defined shaders, such as fetching the geometry from vertex and index buffers, or interpolating VS outputs in the subsequent pipeline stages.&#xD;&#xA;&#xD;&#xA;Since we're looking at the GPU driver's black box here, it's difficult to know which state change exactly is triggering this behaviour. But my guess would be that inserting a geometry shader stage into the pipeline is to blame. GS are notorious for poor performance due to the unpredictable workload (of course, we give it an upper bound, but still), and as such, the driver may choose to look for optimisation opportunities, looking at VS &amp; GS together. This is what I think might be triggering a recompile.&#xD;&#xA;&#xD;&#xA;As long as you only get this once at application start, it should be completely safe to ignore. The driver will put the compiled shader in its cache and use it on subsequent occasions.&#xD;&#xA;&#xD;&#xA;As to why you aren't getting it in RenderDoc - it suppresses debug messages while linking shaders and programs in the initial OpenGL state bring-up (i.e. state that existed before the captured frame), [see its source code][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/baldurk/renderdoc/blob/4923aa9d88b232ef48f203fb3cb33f7643a3f756/renderdoc/driver/gl/gl_initstate.cpp#L1327" ContentLicense="CC BY-SA 4.0" />
  <row Id="24814" PostHistoryTypeId="5" PostId="9098" RevisionGUID="8f894f51-a9ca-4f2b-aa78-ba32f7d3c023" CreationDate="2019-08-25T10:04:14.543" UserId="2817" Comment="added 433 characters in body" Text="This is an example of implementation details leaking through the abstraction. Parts of the GL state are often implemented via native GPU ISA instructions that the driver injects into user-defined shaders, such as fetching the geometry from vertex and index buffers, or interpolating VS outputs in the subsequent pipeline stages.&#xD;&#xA;&#xD;&#xA;Since we're looking at the GPU driver's black box here, it's difficult to know which state change exactly is triggering this behaviour. &lt;s&gt;But my guess would be that inserting a geometry shader stage into the pipeline is to blame. GS are notorious for poor performance due to the unpredictable workload (of course, we give it an upper bound, but still), and as such, the driver may choose to look for optimisation opportunities, looking at VS &amp; GS together. This is what I think might be triggering a recompile.&lt;/s&gt; I just noticed that you've tested removing it from the pipeline and the problem persists. The other hypothesis I can offer is that you're overwriting fragment depth. The driver possibly needs to resolve this with the currently bound depth write state, and/or decide what to do about early depth tests (see [the documentation about gl_fragDepth][1]).&#xD;&#xA;&#xD;&#xA;As long as you only get this once at application start, it should be completely safe to ignore. The driver will put the compiled shader in its cache and use it on subsequent occasions.&#xD;&#xA;&#xD;&#xA;As to why you aren't getting it in RenderDoc - it suppresses debug messages while linking shaders and programs in the initial OpenGL state bring-up (i.e. state that existed before the captured frame), [see its source code][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Fragment_Shader/Defined_Outputs&#xD;&#xA;  [2]: https://github.com/baldurk/renderdoc/blob/4923aa9d88b232ef48f203fb3cb33f7643a3f756/renderdoc/driver/gl/gl_initstate.cpp#L1327" ContentLicense="CC BY-SA 4.0" />
  <row Id="24815" PostHistoryTypeId="5" PostId="9097" RevisionGUID="c6eded2d-d161-472a-8323-a631d6423e94" CreationDate="2019-08-25T19:12:22.257" UserId="11099" Comment="Added more information about cube map texture setup" Text="I've written a shader that writes depth to each face of a cube map, as part of rendering cube map shadows for a realtime 3D engine I'm writing with OpenGL and C++.&#xD;&#xA;&#xD;&#xA;The shader transforms each vertex into world space in the vertex shader, then transforms polygons to each of the cube map's 6 faces in the geometry shader, and then writes depth to the cube map in the fragment shader.&#xD;&#xA;&#xD;&#xA;The shader works correctly, but I receive the following error message when rendering with it for the first time:&#xD;&#xA;```&#xD;&#xA;Error:  OpenGL Error Callback:&#xD;&#xA;Source:&#xD;&#xA;Type: PERFORMANCE&#xD;&#xA;id: 131218&#xD;&#xA;Severity: MEDIUM&#xD;&#xA;Message: Program/shader state performance warning: Vertex shader in program 89 is being recompiled based on GL state.&#xD;&#xA;```&#xD;&#xA;After that, the shader functions perfectly and I'm able to render depth to a cube map, and use it to render shadows for my point lights.&#xD;&#xA;&#xD;&#xA;The shader has a vertex, geometry, and fragment shader component:&#xD;&#xA;&#xD;&#xA;**Vertex:**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 in_position;&#xD;&#xA;&#xD;&#xA;uniform mat4 in_model;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    gl_Position = in_model * vec4(in_position.xyz, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Geometry**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;layout (triangles) in;&#xD;&#xA;layout (triangle_strip, max_vertices = 18) out;&#xD;&#xA;&#xD;&#xA;uniform mat4 shadowCamCubeMap_vp[6];&#xD;&#xA;&#xD;&#xA;out vec4 FragPos;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	for(int currentCubeFace = 0; currentCubeFace &lt; 6; currentCubeFace++)&#xD;&#xA;    {&#xD;&#xA;        gl_Layer = currentCubeFace; // Set the cube map face we're rendering to&#xD;&#xA;&#xD;&#xA;        for(int currentVert = 0; currentVert &lt; 3; currentVert++)&#xD;&#xA;        {				&#xD;&#xA;				FragPos = gl_in[currentVert].gl_Position; // World pos from vert shader&#xD;&#xA;&#xD;&#xA;				gl_Position = shadowCamCubeMap_vp[currentCubeFace] * gl_in[currentVert].gl_Position;&#xD;&#xA;			&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }    &#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Fragment:**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;uniform vec3 lightWorldPos;	&#xD;&#xA;&#xD;&#xA;uniform float shadowCam_near;&#xD;&#xA;uniform float shadowCam_far;&#xD;&#xA;&#xD;&#xA;in vec4 FragPos;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	float lightDistance = length(FragPos.xyz - lightWorldPos);&#xD;&#xA;    &#xD;&#xA;	lightDistance = lightDistance / shadowCam_far;&#xD;&#xA;    &#xD;&#xA;    gl_FragDepth = lightDistance;&#xD;&#xA;} &#xD;&#xA;```&#xD;&#xA;If I delete the geometry shader and just compile the vertex and fragment shaders together, the issue still occurs.&#xD;&#xA;&#xD;&#xA;If I try and debug the program in RenderDoc, the error does not occur (!!).&#xD;&#xA;&#xD;&#xA;I'm scratching my head here. The vertex shader looks near identical to other vertex shaders I'm using.&#xD;&#xA;&#xD;&#xA;I've poured over every google result I could find, but still don't have any idea what's going on here. One thread suggested that, possibly, some part of the OpenGL state was compiled into the program when the shader was first loaded. Then, at some point the state was changed, triggering a recompile when the shader is first used to render something... But it didn't offer any solutions and I'm not really sure if/how this could be the case.&#xD;&#xA;&#xD;&#xA;I'd appreciate any help I can get here!&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I have another 2D depth shader that I use to write depth for a key light that doesn't suffer this issue. If I completely replace the cube map depth shader code with the functional key light depth shader (and delete the geometry shader), the issue still persists.&#xD;&#xA;&#xD;&#xA;If I don't render the keylight at all (making the cube map depth shader the only depth shader that gets executed), the issue persists.&#xD;&#xA;&#xD;&#xA;The only difference between the cube and 2D depth map shaders is that the cube map depth shader is being rendered with cube map textures bound... Is it possible I'm screwing up their initialization somehow?&#xD;&#xA;&#xD;&#xA;Here is my cube map setup:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;bool RenderTexture::BufferCubeMap(RenderTexture** cubeFaceRTs)&#xD;&#xA;{&#xD;&#xA;	// Bind Texture:&#xD;&#xA;	glBindTexture(GL_TEXTURE_CUBE_MAP, this-&gt;textureID);&#xD;&#xA;	if (!glIsTexture(this-&gt;textureID))&#xD;&#xA;	{&#xD;&#xA;		glGenTextures(1, &amp;this-&gt;textureID);&#xD;&#xA;		glBindTexture(GL_TEXTURE_CUBE_MAP, this-&gt;textureID);&#xD;&#xA;&#xD;&#xA;		if (! glIsTexture(this-&gt;textureID))&#xD;&#xA;		{&#xD;&#xA;			glBindTexture(GL_TEXTURE_CUBE_MAP, 0);&#xD;&#xA;			return false;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// Generate faces:&#xD;&#xA;	for (int i = 0; i &lt; CUBE_MAP_COUNT; i++)&#xD;&#xA;	{&#xD;&#xA;		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT32F, this-&gt;width, this-&gt;height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	// Set texture params:&#xD;&#xA;	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);  &#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;	// Bind sampler:&#xD;&#xA;	glBindSampler(12, this-&gt;samplerID);&#xD;&#xA;	if (!glIsSampler(this-&gt;samplerID))&#xD;&#xA;	{&#xD;&#xA;		glGenSamplers(1, &amp;this-&gt;samplerID);&#xD;&#xA;		glBindSampler(12, this-&gt;samplerID);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// Set sampler params:&#xD;&#xA;	glSamplerParameteri(this-&gt;samplerID, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;	glSamplerParameteri(this-&gt;samplerID, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);		&#xD;&#xA;	glSamplerParameteri(this-&gt;samplerID, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;	glSamplerParameteri(this-&gt;samplerID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	glSamplerParameteri(this-&gt;samplerID, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;&#xD;&#xA;	// Bind framebuffer:&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, this-&gt;frameBufferObject);&#xD;&#xA;	if (!glIsFramebuffer(this-&gt;frameBufferObject))&#xD;&#xA;	{&#xD;&#xA;		glGenFramebuffers(1, &amp;this-&gt;frameBufferObject);&#xD;&#xA;		glBindFramebuffer(GL_FRAMEBUFFER, this-&gt;frameBufferObject);&#xD;&#xA;		if (!glIsFramebuffer(this-&gt;frameBufferObject))&#xD;&#xA;		{&#xD;&#xA;			return false;&#xD;&#xA;		}	&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// Attach framebuffer as a cube map render buffer:&#xD;&#xA;	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, this-&gt;textureID, 0);&#xD;&#xA;	&#xD;&#xA;	glDrawBuffer(GL_NONE);&#xD;&#xA;	glReadBuffer(GL_NONE);&#xD;&#xA;&#xD;&#xA;	// Ensure all of the textures have the correct information stored in them:&#xD;&#xA;	for (int i = 0; i &lt; 6; i++)&#xD;&#xA;	{&#xD;&#xA;		if (cubeFaceRTs[i] != this)&#xD;&#xA;		{&#xD;&#xA;			cubeFaceRTs[i]-&gt;textureID			= this-&gt;textureID;&#xD;&#xA;			cubeFaceRTs[i]-&gt;samplerID			= this-&gt;samplerID;&#xD;&#xA;			cubeFaceRTs[i]-&gt;frameBufferObject	= this-&gt;frameBufferObject;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	bool result = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;&#xD;&#xA;	if (!result)&#xD;&#xA;	{&#xD;&#xA;		LOG_ERROR(&quot;Cube map framebuffer is not complete!&quot;);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	// Cleanup:&#xD;&#xA;	glBindTexture(GL_TEXTURE_CUBE_MAP, 0);&#xD;&#xA;	glBindSampler(12, 0);&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, 0); &#xD;&#xA;&#xD;&#xA;	return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Finally, the cube map texture is bound with:&#xD;&#xA;```&#xD;&#xA;void RenderTexture::Bind(GLuint const&amp; shaderReference)&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;		glActiveTexture(GL_TEXTURE0 + 12);&#xD;&#xA;		glBindTexture(GL_TEXTURE_CUBE_MAP, this-&gt;textureID);&#xD;&#xA;		glBindSampler(12, this-&gt;samplerID);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I've edited my code to make it as brief and readable as possible, hopefully I didn't make any typos..." ContentLicense="CC BY-SA 4.0" />
  <row Id="24816" PostHistoryTypeId="5" PostId="4388" RevisionGUID="409b8f7f-efe1-47ac-8bab-93fed5ad0e9f" CreationDate="2019-08-25T20:22:57.473" UserId="5778" Comment="TinyPic images are about to become permanently broken, cf. https://meta.stackexchange.com/q/332659/295232 - this one may take a while to load" Text="This problem has been haunting me for some time but I was busy with other things. I can't finish my GI technique (specifically occlusion step) without solving it.&#xD;&#xA;&#xD;&#xA;I made a binary scene voxelization in a single pass. The result is stored in a `RGBA32UI` 3D texture. It is three way so I set three ortho matrices each for X, Y, Z direction. These matrices are centered in camera position and form frustum in cube shape. And in geometry shader choose axis based on triangle normal.&#xD;&#xA;&#xD;&#xA;**First, what works - without binary voxelization** (but it's a waste of VRAM).&#xD;&#xA;Here is fragment shader code of voxelization pass:&#xD;&#xA;&#xD;&#xA;    //gridDim - gridDimensions in voxels&#xD;&#xA;    ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    ivec3 texcoord[3];&#xD;&#xA;&#xD;&#xA;    //correction of texture coord based on chosen axis and ortho matrix &#xD;&#xA;    //(f_axis - 0, 1 or 2 from geometry shader)&#xD;&#xA;    texcoord[0] = temp;&#xD;&#xA;&#xD;&#xA;    texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;    texcoord[1].y = temp.z;&#xD;&#xA;    texcoord[1].z = temp.y;&#xD;&#xA;&#xD;&#xA;    texcoord[2].x = temp.z;&#xD;&#xA;    texcoord[2].y = temp.y;&#xD;&#xA;    texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;&#xD;&#xA;    imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Drawing pass is done using instancing with cubes. The voxels are quite big because more of them results in a big framerate drop:&#xD;&#xA;&#xD;&#xA;    //vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel2 = texelFetch(geometryTexture, index, 0);&#xD;&#xA;    if(voxel2.r == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And it works:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But if I change it to the binary version:**&#xD;&#xA;&#xD;&#xA;    //input - position 1-128, output: coded binary position as 1 in uvec4 format&#xD;&#xA;        uvec4 encodeBinaryVoxel(int position)&#xD;&#xA;        {&#xD;&#xA;            // check for positioning to R channel&#xD;&#xA;            position = max(position, 0);&#xD;&#xA;            uint voxelId1 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to G channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId2 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to B channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId3 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to A channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId4 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            return uvec4(voxelId1, voxelId2, voxelId3, voxelId4);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;        ivec3 texcoord[3];&#xD;&#xA;    &#xD;&#xA;        texcoord[0] = temp;&#xD;&#xA;    &#xD;&#xA;        texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;        texcoord[1].y = temp.z;&#xD;&#xA;        texcoord[1].z = temp.y;&#xD;&#xA;    &#xD;&#xA;        texcoord[2].x = temp.z;&#xD;&#xA;        texcoord[2].y = temp.y;&#xD;&#xA;        texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;    &#xD;&#xA;        //get z index of texture, each z slice has room for 128 bits (32*4)&#xD;&#xA;        int indexZ = texcoord[f_axis].z / 128; &#xD;&#xA;        //get position in slice&#xD;&#xA;        int bitZ = texcoord[f_axis].z % 128 + 1; &#xD;&#xA;        ivec3 index = ivec3(texcoord[f_axis].xy, indexZ);&#xD;&#xA;        uvec4 current = imageLoad(geometryGrid, index);&#xD;&#xA;        //encode position as binary uvec4&#xD;&#xA;        uvec4 bit = encodeBinaryVoxel(bitZ); &#xD;&#xA;        //or operation with stored value&#xD;&#xA;        imageStore(geometryGrid, index, bit | current); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And read:&#xD;&#xA;&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;    int indexZ = index.z / 128;&#xD;&#xA;    int bitZ = index.z % 128 + 1;&#xD;&#xA;    uvec4 binZ = encodeBinaryVoxel(bitZ);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel = texelFetch(geometryTexture, ivec3(index.xy, indexZ), 0);&#xD;&#xA;    uvec4 occupy = binZ &amp; voxel;&#xD;&#xA;    if((occupy.r | occupy.g | occupy.b | occupy.a) == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you see in the binary version it flickers and I have failed to find out the logic behind this (yet). However, voxel positions seem to be fine. I can render these voxels also by raymarching through the texture and this flickers too.&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've made a simplest voxelization using only vertex + fragment and one ortho matrix in X direction (then it is incorrect but whatever), and store value only in first slice (my `gridDim` is less than 128 so it fits) and it still flickers:&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    &#xD;&#xA;    uvec4 bit = encodeBinaryVoxel(index.z + 1);&#xD;&#xA;    &#xD;&#xA;    uvec4 current = imageLoad(geometryGrid, ivec3(index.xy, 0));&#xD;&#xA;    &#xD;&#xA;    imageStore(geometryGrid, ivec3(index.xy, 0), bit | current);&#xD;&#xA;&#xD;&#xA;I don't know, I think  I'll join sceptics (of programming) stack exchange or something.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bQmhv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bQmhvm.png&#xD;&#xA;  [3]: https://web.archive.org/web/20190825194522/http://oi65.tinypic.com/2e6g12b.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24817" PostHistoryTypeId="24" PostId="4388" RevisionGUID="409b8f7f-efe1-47ac-8bab-93fed5ad0e9f" CreationDate="2019-08-25T20:22:57.473" Comment="Proposed by 5778 approved by 4958 edit id of 486" ContentLicense="CC BY-SA 4.0" />
  <row Id="24819" PostHistoryTypeId="50" PostId="7997" RevisionGUID="7c4f7a24-9275-433d-abbb-578f1627fdca" CreationDate="2019-08-26T10:02:25.410" UserId="-1" />
  <row Id="24820" PostHistoryTypeId="5" PostId="8989" RevisionGUID="91ebf3dc-7369-4389-b7d0-5d3c36a563d3" CreationDate="2019-08-26T15:25:27.547" UserId="6046" Comment="added 1 character in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][2]. **You can see my Renderer's result in [this][3] video** (check the end of my post and sorry for not providing a direct link as I already uploaded on my reddit post)&#xD;&#xA;&#xD;&#xA;As you can see the lobster dataset stretches when viewed from the side. My first guess was that I wasn't accounting for the aspect ratio correctly. I have tried scaling the Bounding box to account for the aspect ratio, then adjusting the stepsize according to that. I've also tried to ignore aspect ratio altogether. Both give similar images.&#xD;&#xA;&#xD;&#xA;I tried rendering more datasets like &quot;Knee&quot;, &quot;Bruce's head&quot;, &quot;DTI Scan&quot;, etc but those didn't even gave an image. There was just random noise everywhere. Here's an example of &quot;Bruce's head&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This happens with both uniform and non-uniform datasets. If some datasets are getting rendered correctly like the &quot;Foot&quot; in my video, this should mean it's more a with that specific dataset itself rather the core algorithm. Nonetheless the link to the code is provided. If anybody can point out some mistakes I'd be grateful.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][5]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, it's normalized `(0-1)`, accounted for the aspect ratio `(0, ar)` and adjusted so it's in the center `(-ar/2, ar/2)`. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1.***&#xD;&#xA;&#xD;&#xA;EDIT:- If you are hesitating to post an answer here since it's only a suggestion, you can post on Reddit, then when the problem is solved you can post your answer here.&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [3]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [4]: https://i.stack.imgur.com/EXyYg.png&#xD;&#xA;  [5]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24821" PostHistoryTypeId="5" PostId="4388" RevisionGUID="4962b876-74a6-4283-8ca0-caa6358e7100" CreationDate="2019-08-26T15:28:57.160" UserId="4958" Comment="deleted 91 characters in body" Text="This problem has been haunting me for some time but I was busy with other things. I can't finish my GI technique (specifically occlusion step) without solving it.&#xD;&#xA;&#xD;&#xA;I made a binary scene voxelization in a single pass. The result is stored in a `RGBA32UI` 3D texture. It is three way so I set three ortho matrices each for X, Y, Z direction. These matrices are centered in camera position and form frustum in cube shape. And in geometry shader choose axis based on triangle normal.&#xD;&#xA;&#xD;&#xA;**First, what works - without binary voxelization** (but it's a waste of VRAM).&#xD;&#xA;Here is fragment shader code of voxelization pass:&#xD;&#xA;&#xD;&#xA;    //gridDim - gridDimensions in voxels&#xD;&#xA;    ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    ivec3 texcoord[3];&#xD;&#xA;&#xD;&#xA;    //correction of texture coord based on chosen axis and ortho matrix &#xD;&#xA;    //(f_axis - 0, 1 or 2 from geometry shader)&#xD;&#xA;    texcoord[0] = temp;&#xD;&#xA;&#xD;&#xA;    texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;    texcoord[1].y = temp.z;&#xD;&#xA;    texcoord[1].z = temp.y;&#xD;&#xA;&#xD;&#xA;    texcoord[2].x = temp.z;&#xD;&#xA;    texcoord[2].y = temp.y;&#xD;&#xA;    texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;&#xD;&#xA;    imageStore(geometryGrid, texcoord[f_axis], uvec4(1u));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Drawing pass is done using instancing with cubes. The voxels are quite big because more of them results in a big framerate drop:&#xD;&#xA;&#xD;&#xA;    //vpVoxels is ortho matrix, worldPosCenter - center of each cube from vertex shader&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel2 = texelFetch(geometryTexture, index, 0);&#xD;&#xA;    if(voxel2.r == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And it works:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**But if I change it to the binary version:**&#xD;&#xA;&#xD;&#xA;    //input - position 1-128, output: coded binary position as 1 in uvec4 format&#xD;&#xA;        uvec4 encodeBinaryVoxel(int position)&#xD;&#xA;        {&#xD;&#xA;            // check for positioning to R channel&#xD;&#xA;            position = max(position, 0);&#xD;&#xA;            uint voxelId1 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to G channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId2 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to B channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId3 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            // check for positioning to A channel&#xD;&#xA;            position = max(position - 32, 0);&#xD;&#xA;            uint voxelId4 = (position &gt; 32 || position == 0)? 0u : 1u &lt;&lt; uint(position - 1);&#xD;&#xA;        &#xD;&#xA;            return uvec4(voxelId1, voxelId2, voxelId3, voxelId4);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ivec3 temp = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;        ivec3 texcoord[3];&#xD;&#xA;    &#xD;&#xA;        texcoord[0] = temp;&#xD;&#xA;    &#xD;&#xA;        texcoord[1].x = int(gridDim.z) - temp.x;&#xD;&#xA;        texcoord[1].y = temp.z;&#xD;&#xA;        texcoord[1].z = temp.y;&#xD;&#xA;    &#xD;&#xA;        texcoord[2].x = temp.z;&#xD;&#xA;        texcoord[2].y = temp.y;&#xD;&#xA;        texcoord[2].z = int(gridDim.z) - temp.x;&#xD;&#xA;    &#xD;&#xA;        //get z index of texture, each z slice has room for 128 bits (32*4)&#xD;&#xA;        int indexZ = texcoord[f_axis].z / 128; &#xD;&#xA;        //get position in slice&#xD;&#xA;        int bitZ = texcoord[f_axis].z % 128 + 1; &#xD;&#xA;        ivec3 index = ivec3(texcoord[f_axis].xy, indexZ);&#xD;&#xA;        uvec4 current = imageLoad(geometryGrid, index);&#xD;&#xA;        //encode position as binary uvec4&#xD;&#xA;        uvec4 bit = encodeBinaryVoxel(bitZ); &#xD;&#xA;        //or operation with stored value&#xD;&#xA;        imageStore(geometryGrid, index, bit | current); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And read:&#xD;&#xA;&#xD;&#xA;    vec4 geomCoords = vpVoxels * vec4(worldPosCenter, 1.0);&#xD;&#xA;    geomCoords.xyz /= geomCoords.w;&#xD;&#xA;    geomCoords.xyz = geomCoords.xyz * 0.5 + 0.5;&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3(geomCoords.xyz * gridDim);&#xD;&#xA;    int indexZ = index.z / 128;&#xD;&#xA;    int bitZ = index.z % 128 + 1;&#xD;&#xA;    uvec4 binZ = encodeBinaryVoxel(bitZ);&#xD;&#xA;&#xD;&#xA;    uvec4 voxel = texelFetch(geometryTexture, ivec3(index.xy, indexZ), 0);&#xD;&#xA;    uvec4 occupy = binZ &amp; voxel;&#xD;&#xA;    if((occupy.r | occupy.g | occupy.b | occupy.a) == 0u)&#xD;&#xA;        discard;&#xD;&#xA;&#xD;&#xA;    normalColor = vec4(normal0, 1.0);&#xD;&#xA;    fragColor = vec4(1.0, 0.0, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you see in the binary version it flickers and I have failed to find out the logic behind this (yet). However, voxel positions seem to be fine. I can render these voxels also by raymarching through the texture and this flickers too.&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've made a simplest voxelization using only vertex + fragment and one ortho matrix in X direction (then it is incorrect but whatever), and store value only in first slice (my `gridDim` is less than 128 so it fits) and it still flickers:&#xD;&#xA;&#xD;&#xA;    ivec3 index = ivec3( gl_FragCoord.xy, gridDim.z * gl_FragCoord.z) ;&#xD;&#xA;    &#xD;&#xA;    uvec4 bit = encodeBinaryVoxel(index.z + 1);&#xD;&#xA;    &#xD;&#xA;    uvec4 current = imageLoad(geometryGrid, ivec3(index.xy, 0));&#xD;&#xA;    &#xD;&#xA;    imageStore(geometryGrid, ivec3(index.xy, 0), bit | current);&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bQmhv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bQmhvm.png&#xD;&#xA;  [3]: https://web.archive.org/web/20190825194522/http://oi65.tinypic.com/2e6g12b.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="24823" PostHistoryTypeId="50" PostId="2146" RevisionGUID="c24b013d-afe9-4f55-b071-3912920b923a" CreationDate="2019-08-27T05:02:00.273" UserId="-1" />
  <row Id="24824" PostHistoryTypeId="5" PostId="6309" RevisionGUID="476e4712-c77d-4db5-92ad-8e1754bc3121" CreationDate="2019-08-27T08:28:16.433" UserId="11105" Comment="Typos corrected" Text="What you are missing is, that in OpenGL's NDC space (i.e. clip space after division by `w`) all 3 coordinates are in the range $[-1,1]$. So **`ndc_depth` is in the range $[-1,1]$**, while your computation assumes a range of $[0,1]$.&#xD;&#xA;&#xD;&#xA;So let's take your computation but add an initial step to map $[-1,1]$ to $[0,1]$:&#xD;&#xA;&#xD;&#xA;    float ndc_depth = Pclip.z / Pclip.w;&#xD;&#xA;    float win_depth = (ndc_depth + 1.0) / 2.0;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * win_depth + gl_DepthRange.near;&#xD;&#xA;&#xD;&#xA;If we do some transformations (and realizing that `gl_DepthRange.diff` is just convenience for `gl_DepthRange.far - gl_DepthRange.near`), we get&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = gl_DepthRange.diff * (ndc_depth + 1.0) / 2.0 + gl_DepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff) / 2.0 &#xD;&#xA;                   + gl_DepthRange.near;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff + &#xD;&#xA;                    2.0 * gl_DepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far - gl_DepthRange.near + 2.0 * gl_DepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xD;&#xA;                    gl_DepthRange.far + gl_DepthRange.near) / 2.0;&#xD;&#xA;&#xD;&#xA;So, to answer your specfic questions:&#xD;&#xA;&#xD;&#xA;1. That's just a result from simplifying the calculation based on the fact that [`gl_DepthRange.diff` is nothing else than `gl_DepthRange.far - gl_DepthRange.near`](https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)#Shader_uniforms).&#xD;&#xA;&#xD;&#xA;2. Because the depth range in NDC space is $[-1,1]$, which has a width of $2$.&#xD;&#xA;&#xD;&#xA;3. It doesn't. These values have nothing to do with the near and far values you used to construct your projection matrix, in fact you could use any arbitrary projection matrix (or none at all). They are the depth range values set with [`glDepthRange`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml), which have a totally different meaning (okay, let's say slightly different but related).&#xD;&#xA;&#xD;&#xA; Basically, and special situations notwithstanding, the projection matrix defines where you near and far clipping planes are in eye-space, i.e. which eye-space range is mapped to the $[-1,1]$ NDC depth range. Then the depth range defines what these NDC near/far values of -1 and 1 are mapped to in the actual depth buffer. So the names &quot;near&quot;/&quot;far&quot; *do* relate to the near and far clipping planes. But both transformations are basically independent of each other, using the general NDC (i.e. the *normalized* device space) as a mediator between both stages. This way `glDepthRange` more or less just extends what `glViewport` does onto the z-dimension." ContentLicense="CC BY-SA 4.0" />
  <row Id="24825" PostHistoryTypeId="24" PostId="6309" RevisionGUID="476e4712-c77d-4db5-92ad-8e1754bc3121" CreationDate="2019-08-27T08:28:16.433" Comment="Proposed by 11105 approved by 6 edit id of 487" ContentLicense="CC BY-SA 4.0" />
  <row Id="24826" PostHistoryTypeId="50" PostId="8701" RevisionGUID="f800716c-11d6-495f-9765-ff3ac77671c9" CreationDate="2019-08-27T10:01:30.180" UserId="-1" />
  <row Id="24829" PostHistoryTypeId="2" PostId="9099" RevisionGUID="bb7f03dd-3f14-42c2-af94-d3c9e812ef7e" CreationDate="2019-08-28T11:47:10.753" UserId="11106" Text="Attempting to deskew and crop scans of a CD booklet using ImageMagick.&#xD;&#xA;&#xD;&#xA;Here's one image which I've been using as an example on which to build my one-liner - https://mega.nz/#!jIQD3aqC!PbjG4_Xaq-YPhrPu1APaRmYLKmCSx6pxbIUkaoQzOgM&#xD;&#xA;&#xD;&#xA;So far I've been using something along the lines of;&#xD;&#xA;```&#xD;&#xA;convert testscan.png -background white -deskew 80% -fuzz 40% -trim +repage edited_scan.png&#xD;&#xA;```&#xD;&#xA;The deskewing step works very well, however I've been unable to achieve good results on the cropping stage. When deskewing the image ImageMagick expands it and adds additional pixels to fill in the blanks (here white, but could be transparent as well). This may be interfering with the ability of -trim to crop the image.&#xD;&#xA;&#xD;&#xA;In any case, -trim either;&#xD;&#xA; - fails to crop any edges&#xD;&#xA; - crops a single edge but not the others&#xD;&#xA; - (upon raising -fuzz values) crops multiple sides but fails to accurately crop edges&#xD;&#xA;&#xD;&#xA;Not exactly sure what the issue is, but I've tried a number of different alterations to -trim parameters without success." ContentLicense="CC BY-SA 4.0" />
  <row Id="24830" PostHistoryTypeId="1" PostId="9099" RevisionGUID="bb7f03dd-3f14-42c2-af94-d3c9e812ef7e" CreationDate="2019-08-28T11:47:10.753" UserId="11106" Text="Deskewing and Cropping Scans using ImageMagick" ContentLicense="CC BY-SA 4.0" />
  <row Id="24831" PostHistoryTypeId="3" PostId="9099" RevisionGUID="bb7f03dd-3f14-42c2-af94-d3c9e812ef7e" CreationDate="2019-08-28T11:47:10.753" UserId="11106" Text="|image-processing|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24839" PostHistoryTypeId="2" PostId="9101" RevisionGUID="318f9cc7-c79d-4d89-bbc5-aaefcc8151ac" CreationDate="2019-08-29T02:09:30.493" UserId="11108" Text="I want to study computer graphics but I don't have a strong foundation in mathematics. I am doing a computer science degree that doesn't cover computer vision, image processing or computer graphics, linear algebra, geometry, trigonometry, calculus etc. It does cover discrete math and other math relating to computer science. I don't meet the requirements for a mathematics degree so I can't pursue a minor in that. I want to know if I can teach myself the math necessary for CG or Would discrete math be adequate enough? Any advice would be nice." ContentLicense="CC BY-SA 4.0" />
  <row Id="24840" PostHistoryTypeId="1" PostId="9101" RevisionGUID="318f9cc7-c79d-4d89-bbc5-aaefcc8151ac" CreationDate="2019-08-29T02:09:30.493" UserId="11108" Text="Want to study computer graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="24841" PostHistoryTypeId="3" PostId="9101" RevisionGUID="318f9cc7-c79d-4d89-bbc5-aaefcc8151ac" CreationDate="2019-08-29T02:09:30.493" UserId="11108" Text="|image-processing|mathematics|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24842" PostHistoryTypeId="50" PostId="8321" RevisionGUID="6925f1a7-5c3b-437a-9fdc-0ca42bf14a7a" CreationDate="2019-08-29T03:03:20.380" UserId="-1" />
  <row Id="24843" PostHistoryTypeId="2" PostId="9102" RevisionGUID="0df02533-3cbd-454d-a8da-53e6ff6ac019" CreationDate="2019-08-29T07:59:28.750" UserId="2041" Text="First, graphics is full of linear algebra, so you'll need that whatever you do. If you want to do any research into shaders, or to write a ray-tracer, you'll also need to understand integration and probably some statistics (to understand Monte Carlo integration).&#xD;&#xA;&#xD;&#xA;&gt; I want to know if I can teach myself the math necessary for CG&#xD;&#xA;&#xD;&#xA;We can't answer that question for you: only you know how good you are at teaching yourself. If you &quot;don't have a strong foundation in mathematics&quot; because you struggled with it at school, you'll probably struggle to learn harder maths with less help than you had before. If it's not like that, and you're generally good at self-study, then now's the time. You'll never have more access to the means of learning than when you're at university. Hang out with your local maths students and pay attention when they talk about work. Find out when they have lectures relevant to you that don't clash with your own lectures, and go to as many as you can. Find out what books they use for their course, and read the same books.&#xD;&#xA;&#xD;&#xA;It'll also help to approach any graphics projects you start with the mindset that when you encounter some maths you don't understand, you might need to put the project to one side while you learn what you need to know. You'll probably do this a lot as soon as you get past the &quot;draw the first triangle on the screen&quot; stage.&#xD;&#xA;&#xD;&#xA;A counterpoint to this is that there are a lot of tools today that allow designers and artists to make really impressive graphics content without much maths knowledge, such as Unity and Processing. Maybe you can achieve what *you* want without studying computer graphics as an academic field at all! Try making a Unity game, play around with shaders a bit, and see if it tickles you." ContentLicense="CC BY-SA 4.0" />
  <row Id="24844" PostHistoryTypeId="2" PostId="9103" RevisionGUID="3e40c188-52fc-4243-802b-1827cf90be6a" CreationDate="2019-08-29T09:44:37.553" UserId="11111" Text="For a research project, I have writen a Tessellation Shader to interpolate solution points of a 3-Dimensional mathematical equation. Therefore I don't use any techniques for displacement, I merely use the tessellation hardware to interpolate a lot of data points in parallel. I want to write a paragraph about the potential speed benefits compared with trivial interpolation on a CPU, but I can't find any resources about how fast tessellation is in terms of &quot;generating new points per second&quot; or &quot;subdividing triangles per second&quot;. Even more interesting would be &quot;new points per GPU clock cycle&quot;. But all resources I find are from the video game perspective talking about FPS-performance, which is useless in my case, because first I tessellate my model only once and second I don't use any displacement techniques which are normally used to increase visual quality but will lower the performance again.&#xD;&#xA;&#xD;&#xA;Obviously the performance depends on the actual GPU, but a single data sheet as an anchor point would already help a lot." ContentLicense="CC BY-SA 4.0" />
  <row Id="24845" PostHistoryTypeId="1" PostId="9103" RevisionGUID="3e40c188-52fc-4243-802b-1827cf90be6a" CreationDate="2019-08-29T09:44:37.553" UserId="11111" Text="Tessellation Speed in terms of interpolated points per second" ContentLicense="CC BY-SA 4.0" />
  <row Id="24846" PostHistoryTypeId="3" PostId="9103" RevisionGUID="3e40c188-52fc-4243-802b-1827cf90be6a" CreationDate="2019-08-29T09:44:37.553" UserId="11111" Text="|gpu|performance|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24847" PostHistoryTypeId="5" PostId="9103" RevisionGUID="e2bdeb6e-1487-4287-b9e3-decaf43ffa24" CreationDate="2019-08-29T13:32:14.040" UserId="11111" Comment="added 1 character in body" Text="For a research project, I have written a Tessellation Shader to interpolate solution points of a 3-Dimensional mathematical equation. Therefore I don't use any techniques for displacement, I merely use the tessellation hardware to interpolate a lot of data points in parallel. I want to write a paragraph about the potential speed benefits compared with trivial interpolation on a CPU, but I can't find any resources about how fast tessellation is in terms of &quot;generating new points per second&quot; or &quot;subdividing triangles per second&quot;. Even more interesting would be &quot;new points per GPU clock cycle&quot;. But all resources I find are from the video game perspective talking about FPS-performance, which is useless in my case, because first I tessellate my model only once and second I don't use any displacement techniques which are normally used to increase visual quality but will lower the performance again.&#xD;&#xA;&#xD;&#xA;Obviously the performance depends on the actual GPU, but a single data sheet as an anchor point would already help a lot." ContentLicense="CC BY-SA 4.0" />
  <row Id="24848" PostHistoryTypeId="2" PostId="9104" RevisionGUID="1ab2f981-7277-4974-84e6-00d2a6794cbd" CreationDate="2019-08-29T13:44:44.220" UserId="11114" Text="I have a noob level question about RGB images-&#xD;&#xA;Pixels in RGB images are in the range of (0-255), so technically each channel ranges from 0(black) to 1(white), then why we say that each image has a Red, Green, Blue channel component, although they are only Gray channel. In short, how the image is formed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24849" PostHistoryTypeId="1" PostId="9104" RevisionGUID="1ab2f981-7277-4974-84e6-00d2a6794cbd" CreationDate="2019-08-29T13:44:44.220" UserId="11114" Text="How RGB images are formed" ContentLicense="CC BY-SA 4.0" />
  <row Id="24850" PostHistoryTypeId="3" PostId="9104" RevisionGUID="1ab2f981-7277-4974-84e6-00d2a6794cbd" CreationDate="2019-08-29T13:44:44.220" UserId="11114" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24851" PostHistoryTypeId="50" PostId="8695" RevisionGUID="bd82a29b-8f8e-42c4-bc3f-769b72d457cc" CreationDate="2019-08-29T16:03:10.417" UserId="-1" />
  <row Id="24852" PostHistoryTypeId="2" PostId="9105" RevisionGUID="711b6521-3cce-488e-89d6-16faa82c5820" CreationDate="2019-08-30T07:25:56.350" UserId="2041" Text="Each channel ranges not from *black* to *white*, but from *off* to *full intensity*. What colour is meant by *full intensity* is down to convention and the presentation technology.&#xD;&#xA;&#xD;&#xA;For example, a given image file format might say there are three bytes, of which the first is the red channel, the second is the green channel, and the third is the blue channel. There are many different colours, so to be a real standard, it has to say exactly what that &quot;red&quot; means, usually by reference to a particular colour standard such as sRGB or CIELAB. These international standards provide an absolute way to describe colours.&#xD;&#xA;&#xD;&#xA;After some processing, your red, green, and blue values find their way to your LCD monitor. There, the electronics uses them to control the intensity of three sub-pixels: one of which is a red filter, one a green filter, and one a blue filter. The 0-255 value in the red channel is turned into some voltage which controls the transparency of the liquid crystal behind the red filter, turning it from *completely opaque* at 0 to *lets all light through* at 255. Since this is attached to a red filter, it contributes black or red to the image.&#xD;&#xA;&#xD;&#xA;The same idea is everywhere in computers. The only things inside a computer are numbers. They only mean what we say they mean because of conventions (all software interprets them the same way) and/or because they control some values inside some output hardware. e.g. one number means the red channel in a pixel on your screen, another number means a letter of the alphabet in an email, another number is a pressure sample in an audio file which will be sent to your sound card and control the voltage to a speaker, and so on." ContentLicense="CC BY-SA 4.0" />
  <row Id="24853" PostHistoryTypeId="2" PostId="9106" RevisionGUID="68c43321-e3fc-445e-aa17-d0aee833a77c" CreationDate="2019-08-30T16:13:21.287" UserId="8704" Text="I've been doing some searching online and it seems like I could improve my renderer by ordering my draw calls based on depth. For opaque objects render the closest items first and move backward in depth to hopefully take advantage of depth test rejection.&#xD;&#xA;&#xD;&#xA;The question I have is would this be worth the tradeoff of sacrificing instancing? It seems like the most straightforward approach would be to stop instancing completely and do each draw call one by one. I'm sure you could write some clever code to find groups within a new depth-first rendering order to instance but it seems like you'd get substantially less benefit." ContentLicense="CC BY-SA 4.0" />
  <row Id="24854" PostHistoryTypeId="1" PostId="9106" RevisionGUID="68c43321-e3fc-445e-aa17-d0aee833a77c" CreationDate="2019-08-30T16:13:21.287" UserId="8704" Text="Trading off instancing for render order" ContentLicense="CC BY-SA 4.0" />
  <row Id="24855" PostHistoryTypeId="3" PostId="9106" RevisionGUID="68c43321-e3fc-445e-aa17-d0aee833a77c" CreationDate="2019-08-30T16:13:21.287" UserId="8704" Text="|opengl|directx11|optimisation|scene-graph|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24859" PostHistoryTypeId="2" PostId="9108" RevisionGUID="59bf3091-3b96-40ff-862e-c38f73100f45" CreationDate="2019-08-30T16:51:51.057" UserId="2041" Text="It depends on your GPU. &quot;Tiled renderers&quot; do this for you so the benefit of doing it yourself is minimal (unless you have some more efficient way of knowing the order, e.g. sorting a fixed-viewpoint scene in advance). In this case, your best way of keeping efficiency is by ensuring they are allowed to draw the scene all in one go by avoiding `glReadPixels` and similar sync points between draw calls.&#xD;&#xA;&#xD;&#xA;Even for a truly immediate-mode renderer, instancing can be hugely powerful and reducing overdraw is unlikely to be worth it, but the trade-off comes down to whether you're bottlenecked on the fragment shader or by the memory bandwidth used feeding vertices to the vertex shader. In turn that will depend on how big your instanced geometry is (and how many instances), and how long your fragment shader takes to execute. These are all specific to your application and to the GPU you're running on, so you can only really know by profiling.&#xD;&#xA;&#xD;&#xA;As an outright guess I'd say it's unlikely that the change you're suggesting will improve performance, unless you have few instances and a big fragment shader on a non-tiled GPU architecture." ContentLicense="CC BY-SA 4.0" />
  <row Id="24862" PostHistoryTypeId="50" PostId="5697" RevisionGUID="6ad9f963-7b34-49f3-b6d9-975d58cc821b" CreationDate="2019-08-31T02:02:55.373" UserId="-1" />
  <row Id="24864" PostHistoryTypeId="50" PostId="8359" RevisionGUID="d19c8dcc-490d-462e-8bae-cd321a41ac45" CreationDate="2019-08-31T20:01:00.097" UserId="-1" />
  <row Id="24865" PostHistoryTypeId="50" PostId="8721" RevisionGUID="0081633a-0c40-410b-a25c-02c42db22c85" CreationDate="2019-09-01T07:02:30.363" UserId="-1" />
  <row Id="24871" PostHistoryTypeId="50" PostId="8209" RevisionGUID="180e8002-5146-4384-9196-3d01eddf63b9" CreationDate="2019-09-01T22:02:55.407" UserId="-1" />
  <row Id="24874" PostHistoryTypeId="2" PostId="9111" RevisionGUID="74018cea-a117-403d-a70b-bc79f44edeec" CreationDate="2019-09-03T04:25:41.973" UserId="6442" Text="As a work around this, what I did was to separate static and dynamic lights, have the static illumination go through temporal accumulation and dynamic illumination not (and use a non-temporal de-noising method).&#xD;&#xA;&#xD;&#xA;There could still be artifacts, especially on far-away dynamic lights, but could still be useful. I did this in a game where the flashlight was fixed in view-space, so in fact no denoising was even necessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="24879" PostHistoryTypeId="2" PostId="9113" RevisionGUID="c5034ef5-fd0a-4867-9964-451cef2627a8" CreationDate="2019-09-03T21:21:20.097" UserId="506" Text="If you’re only tessellating the model once and never changing the density of the mesh then tessellation is probably a waste of time here—any measurements you make would include all the extra work the GPU has to do to generate new points / triangles, which is orthogonal to what it sounds like you’re trying to measure. Tessellating the mesh ahead of time (in your tool of choice) and doing the interpolation / evaluation in a vertex shader would probably give you a better benchmark against a CPU implementation working on the same mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="24880" PostHistoryTypeId="50" PostId="9048" RevisionGUID="8ae16c7b-951b-4191-a77d-85e320661419" CreationDate="2019-09-04T00:02:05.273" UserId="-1" />
  <row Id="24881" PostHistoryTypeId="2" PostId="9114" RevisionGUID="c0f89bc9-3f6d-4732-9f9d-aeed2d333e4d" CreationDate="2019-09-04T20:41:05.087" UserId="11136" Text="If you compute the lighting in object space, before you scale the object then you will get false lighting. Imagine a small cube being lit by a single point light representing a light bulb. Now, scale that cube up to the size of a building. The lighting will have been calculated already, and now the entire building is being lit by a single light bulb. " ContentLicense="CC BY-SA 4.0" />
  <row Id="24882" PostHistoryTypeId="2" PostId="9115" RevisionGUID="a2086d86-7456-4f75-a06b-ab11d4d2d765" CreationDate="2019-09-04T21:27:23.280" UserId="11136" Text="CRT monitors are a thing of the past, but I think they are the best example to describe to you &quot;how the image is formed&quot;.&#xD;&#xA;Each pixel on the monitor is actually a group of 3 phosphors. A green phosphor, a red phosphor and a blue phosphor. These phosphors will glow at a certain intensity when they are charged. Inside the monitor there is an electron beam, that is bounced off of a mirror to strike these individual phosphors, and the intensity at which that beam is tuned, is determined by the number 0-255 of that channel. So a completely black pixel would not be hit at all, whereas a bright red pixel would only strike the red phosphor, and at a high intensity  (around 200-255). This is, of course, a simplification of the process, but it answers &quot;how&quot; the red channel relates to a red pixel." ContentLicense="CC BY-SA 4.0" />
  <row Id="24883" PostHistoryTypeId="2" PostId="9116" RevisionGUID="c02b0a41-626a-49b1-8d17-10c368b7a899" CreationDate="2019-09-05T06:39:32.050" UserId="11138" Text="**Introduction to my project:**&#xD;&#xA;&#xD;&#xA;We are machine learning scientists and working on a biomedical system for tracking tongue for speech pathology using a technology called EMA (Electromagnetic articulography). In EMA a coil is attached to tongue surface using a glue and its 3D pos and orientation (roll and pitch) are read by EMA measurement system. So, you can track the coil and thus a point on the surface of tongue while speech is made. Also let's assume we have a low density 3D model of tongue for the patient is obtained by 3D MRI and we know exactly that which vertex in 3D model corresponds to the point that coil is attached.&#xD;&#xA;&#xD;&#xA;It would be very valuable for our research if we can visualize the tongue for the patient. But the issue is that we just track 1 or 2 points on the tongue but our 3D model has more than 100 vertices which are not tracked. Now, we think it might be possible to estimate the position of those point given these two points.&#xD;&#xA;&#xD;&#xA;**Here are some of the facts that we think it should be possible:**&#xD;&#xA;&#xD;&#xA; 1. Although tongue is not a solid object, it has a degree of rigidity thus the position of these 100 vertexes are correlated by physics For example how much they can be stretched or bent (Something like spring and mass model in physics). &#xD;&#xA; 2. by looking at a training set of 3D models for tongue during production of different sounds, we might say that the position of vertexes are not pure random and there is a distribution for them which might be estimated using the training dataset (sequence of MRI 3D models). &#xD;&#xA; 3.  we might assume that in our presentation the tongue can have just a bent toward the palate to simplify the modeling problem. or a 2D profile of tongue (like the line at the center) is enough for modeling. or any simplification that we can make. &#xD;&#xA;&#xD;&#xA;**Now my question:** &#xD;&#xA;&#xD;&#xA;What do you know in computer graphics literature which resembles to our problem (any model, method, tool, software, library,....)? What is your suggestion for us to do this task in more efficient way?&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;Mike" ContentLicense="CC BY-SA 4.0" />
  <row Id="24884" PostHistoryTypeId="1" PostId="9116" RevisionGUID="c02b0a41-626a-49b1-8d17-10c368b7a899" CreationDate="2019-09-05T06:39:32.050" UserId="11138" Text="Estimating the position of vertexes in a 3D model" ContentLicense="CC BY-SA 4.0" />
  <row Id="24885" PostHistoryTypeId="3" PostId="9116" RevisionGUID="c02b0a41-626a-49b1-8d17-10c368b7a899" CreationDate="2019-09-05T06:39:32.050" UserId="11138" Text="|rendering|algorithm|image-processing|computational-geometry|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24887" PostHistoryTypeId="2" PostId="9117" RevisionGUID="77f934c7-f659-48ac-ae99-dfad2e5e7b0b" CreationDate="2019-09-05T13:59:41.147" UserId="11142" Text="Red, Green and Blue apparently contribute differently to the luminosity perceived by humans:&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;&#xD;&#xA;I am trying to find an algorithm to map unsigned 16 bit integers into RGB values such that the relative luminance of the RGB values to which the integers map respects their order (with integer 0 being black, integer 2^16-1 white and all other integers mapped to some RGB color).&#xD;&#xA;&#xD;&#xA;I don't really care about how the colors evolve as one walks up from 0 to 2^16-1 as long as luminosity always increases and a reasonably large part of the RGB space is used.&#xD;&#xA;&#xD;&#xA;Apparently I am missing the right words to describe what I am trying to accomplish as I've failed to google anything pertinent. A couple of weeks ago I had stumbled upon a paper that described such an algorithm in the form of a helix that is arranged diagonally in the three dimensional RGB space such that when one starts at the base of the helix and works his way towards the other end, luminosity always increases and almost all RGB color are employed. Alas, I can't find it any more." ContentLicense="CC BY-SA 4.0" />
  <row Id="24888" PostHistoryTypeId="1" PostId="9117" RevisionGUID="77f934c7-f659-48ac-ae99-dfad2e5e7b0b" CreationDate="2019-09-05T13:59:41.147" UserId="11142" Text="map 16-bit integers to RGB colors with monotonic relative luminosity" ContentLicense="CC BY-SA 4.0" />
  <row Id="24889" PostHistoryTypeId="3" PostId="9117" RevisionGUID="77f934c7-f659-48ac-ae99-dfad2e5e7b0b" CreationDate="2019-09-05T13:59:41.147" UserId="11142" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24890" PostHistoryTypeId="5" PostId="9117" RevisionGUID="689246bb-f7c8-4dcf-bde7-51267f0a6659" CreationDate="2019-09-05T14:43:21.547" UserId="11142" Comment="deleted 1 character in body" Text="Red, Green and Blue apparently contribute differently to the luminosity perceived by humans:&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;&#xD;&#xA;I am trying to find an algorithm to map unsigned 16 bit integers into RGB values such that the relative luminance of the RGB values to which the integers map respects their order (with integer 0 being black, integer 2^16-1 white and all other integers mapped to some RGB color).&#xD;&#xA;&#xD;&#xA;I don't really care about how the colors evolve as one walks up from 0 to 2^16-1 as long as luminosity always increases and a reasonably large part of the RGB space is used.&#xD;&#xA;&#xD;&#xA;Apparently I am missing the right words to describe what I am trying to accomplish as I've failed to google anything pertinent. A couple of weeks ago I had stumbled upon a paper that described such an algorithm in the form of a helix that is arranged diagonally in the three dimensional RGB space such that when one starts at the base of the helix and works his way towards the other end, luminosity always increases and a large variety of color is used. Alas, I can't find it any more." ContentLicense="CC BY-SA 4.0" />
  <row Id="24891" PostHistoryTypeId="5" PostId="9117" RevisionGUID="d88acd29-c6c0-4069-8f3b-bf05f7ba96ca" CreationDate="2019-09-05T15:07:11.897" UserId="11142" Comment="added 2 characters in body" Text="Red, Green and Blue apparently contribute differently to the luminosity perceived by humans:&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;&#xD;&#xA;I am trying to find an algorithm to map unsigned 16 bit integers into RGB values such that the relative luminance of the RGB values to which the integers map respects their order (with integer 0 being black, integer 2^16-1 white and all other integers mapped to some RGB color).&#xD;&#xA;&#xD;&#xA;I don't really care about how the colors evolve as one walks up from 0 to 2^16-1 as long as luminosity always increases and a reasonably large swathe of the RGB space is used.&#xD;&#xA;&#xD;&#xA;Apparently I am missing the right words to describe what I am trying to accomplish as I've failed to google anything pertinent. A couple of weeks ago I had stumbled upon a paper that described such an algorithm in the form of a helix that is arranged diagonally in the three dimensional RGB space such that when one starts at the base of the helix and works his way towards the other end, luminosity always increases and a large variety of color is used. Alas, I can't find it any more." ContentLicense="CC BY-SA 4.0" />
  <row Id="24892" PostHistoryTypeId="2" PostId="9118" RevisionGUID="41198836-cc66-4de0-ba36-ae86edb532ae" CreationDate="2019-09-05T17:07:50.047" UserId="48" Text="By lighting in object space, sure, you could avoid transforming the normals into world space. However, you'd have to transform the light positions/vectors into the object's space. Also, if you want any view-dependent shading such as specular, you would have to transform the camera position into object space as well, to calculate view vectors.&#xD;&#xA;&#xD;&#xA;Now, all of this can be done straightforwardly using the inverse of the object's world matrix. The inverse world matrix will include the inverse of the object's scale (as well as correctly accounting for the inverse of its rotation and translation), so it will transform the light &amp; camera positions to the appropriate points in the scaled coordinate system. Directional lights don't have a position, but you can transform their direction vector by the inverse world matrix to account for rotation and scale. All of this is fine so far.&#xD;&#xA;&#xD;&#xA;However, you will then run into trouble when doing lighting calculations like N·L or N·V. For exactly the same reason that normals don't transform correctly under non-uniform scaling without using a special normal matrix, these dot products will not come out with the same result when done in a non-uniformly scaled object space as compared to world space. Namely, non-uniform scaling distorts angles. So, all your lighting calculations and BRDFs that depend on angles are going to be messed up.&#xD;&#xA;&#xD;&#xA;While there _are_ ways one could correct this problem by using additional matrices when calculating dot products... it's generally easier and fastyer to do lighting in world space (or view space). In any case, transforming the normals to world space is a pretty trivial amount of math by modern GPU standards, especially as it only needs to be done per vertex." ContentLicense="CC BY-SA 4.0" />
  <row Id="24893" PostHistoryTypeId="5" PostId="9115" RevisionGUID="661d5bf2-12cf-4e69-8ec2-e1bc5274ceea" CreationDate="2019-09-05T17:10:53.910" UserId="11136" Comment="deleted 64 characters in body" Text="CRT monitors are a thing of the past, but I think they are the best example to describe to you &quot;how the image is formed&quot;.&#xD;&#xA;Each pixel on the monitor is actually a group of 3 phosphors. A green phosphor, a red phosphor and a blue phosphor. These phosphors will glow at a certain intensity when they are charged. Inside the monitor there is an electron beam that charges these phosphors. The intensity of which, is determined by the number 0-255 of that channel. So a completely black pixel would not be hit at all, whereas a bright red pixel would only strike the red phosphor, and at a high intensity  (around 200-255). This is, of course, a simplification of the process, but it answers &quot;how&quot; the red channel relates to a red pixel." ContentLicense="CC BY-SA 4.0" />
  <row Id="24894" PostHistoryTypeId="2" PostId="9119" RevisionGUID="fcd0d30f-46cb-4555-a5e1-46ae154edf63" CreationDate="2019-09-05T17:39:44.717" UserId="48" Text="Since you want monotonically increasing luminance, it's probably best to work in a color space that separates luma from chroma, such as a [Y'UV space](https://en.wikipedia.org/wiki/YUV#HDTV_with_BT.709). You can assign values in Y'UV and then convert it to RGB using the matrix at that link.&#xD;&#xA;&#xD;&#xA;Start by setting $Y' = N / (2^{16} - 1)$, where N is your input 16-bit integer. Now you just need to make up some function to use for the U and V components.&#xD;&#xA;&#xD;&#xA;It wasn't clear to me if you want the chroma part of the color to vary _continuously_ with the input N, or be pseudo-random. For a continuous curve, you could just have it be a circle in UV space:&#xD;&#xA;$$&#xD;&#xA;U = 0.5 \cos(2\pi N/2^{16}) \\&#xD;&#xA;V = 0.5 \sin(2\pi N/2^{16})&#xD;&#xA;$$&#xD;&#xA;or whatever other curve you feel like coming up with. For a pseudo-random chroma, you could use a hash function, or a [Halton sequence](https://en.wikipedia.org/wiki/Halton_sequence) or another low-discrepancy sequence." ContentLicense="CC BY-SA 4.0" />
  <row Id="24895" PostHistoryTypeId="2" PostId="9120" RevisionGUID="1b8c56f4-bca8-4aed-981e-81cd0098a361" CreationDate="2019-09-06T06:02:52.700" UserId="11136" Text="If you can construct a mesh that is representative of the tongue, like a spring mass system, then you can attach 'hooks' at your two control points and get a close approximation of the deformation of the tongue. &#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24896" PostHistoryTypeId="2" PostId="9121" RevisionGUID="4b5fac28-b9fb-47a2-9fd4-8734e7410727" CreationDate="2019-09-06T06:24:41.467" UserId="11136" Text="There are many ways, but the fastest I think is to create an octtree for your cube and choose a small subdivision level. Then do simple collision detection of the cube to the sphere. If the sphere collides with the cube, subdivide it into 8 smaller cubes. Test each of those cubes and repeat. When you are finished, you will know how many cubes have intersected the sphere, just multiply their dimensions by the number of intersections and you have a close approximation of total volume.&#xA;&#xA;You may want to say that a cube collides with a sphere if its center lies within one radius of the spheres center.&#xA;&#xA;I recently did something similar for a CNC simulator I wrote.&#xA;&#xA;&#xA;Good luck!" ContentLicense="CC BY-SA 4.0" />
  <row Id="24897" PostHistoryTypeId="5" PostId="9121" RevisionGUID="a25dc2b2-37dc-445d-a886-dc6ee7b578b3" CreationDate="2019-09-06T06:30:13.217" UserId="11136" Comment="added 347 characters in body" Text="There are many ways, but the fastest I think is to create an octtree for your cube and choose a small subdivision level. Then do simple collision detection of the cube to the sphere. If the sphere collides with the cube, subdivide it into 8 smaller cubes. Test each of those cubes and repeat. When you are finished, you will know how many cubes have intersected the sphere, just multiply their dimensions by the number of intersections and you have a close approximation of total volume.&#xA;&#xA;You may want to say that a cube collides with a sphere if its center lies within one radius of the spheres center.&#xA;&#xA;I recently did something similar for a CNC simulator I wrote.&#xA;&#xA;&#xA;Good luck!&#xA;&#xA;&#xA;As far as the second part of your question, there would have to be constraints. If the cube is substantially smaller than the sphere, it may not be possible to satisfy your volume requirements. Given that constraints are in place, this method is fast enough that you could just drive your sphere into the cube until your required volume is met." ContentLicense="CC BY-SA 4.0" />
  <row Id="24898" PostHistoryTypeId="2" PostId="9122" RevisionGUID="7f6e8220-7187-48f8-9fac-9db3d963c0c5" CreationDate="2019-09-06T10:41:35.023" UserId="10806" Text="I'd like to store arbitrary float depth, so I have to disable both primitive clipping and depth clamping.&#xD;&#xA;&#xD;&#xA;I can disable clipping by setting ```VkPipelineRasterizationStateCreateInfo::depthClampEnable``` to ```VK_TRUE```, but then I'd have to increase my viewport bounds to the range I wish to store (which is 0..FLT_MAX) and during rasterization my depth value would be multiplied by viewport depth range and would blow up.&#xD;&#xA;&#xD;&#xA;Fortunately, I can disable both clipping and clamping using the VK_EXT_depth_clip_enable, but [turns out][1] it was supported by the drivers quite recently.&#xD;&#xA;&#xD;&#xA;Is there any way to disable both depth clamping and clipping on older drivers (i.e., without using VK_EXT_depth_clip_enable)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan.gpuinfo.org/listdevices.php?platform=linux&amp;extension=VK_EXT_depth_clip_enable" ContentLicense="CC BY-SA 4.0" />
  <row Id="24899" PostHistoryTypeId="1" PostId="9122" RevisionGUID="7f6e8220-7187-48f8-9fac-9db3d963c0c5" CreationDate="2019-09-06T10:41:35.023" UserId="10806" Text="Disable both depth clamp and depth clip in Vulkan (older drivers)" ContentLicense="CC BY-SA 4.0" />
  <row Id="24900" PostHistoryTypeId="3" PostId="9122" RevisionGUID="7f6e8220-7187-48f8-9fac-9db3d963c0c5" CreationDate="2019-09-06T10:41:35.023" UserId="10806" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24901" PostHistoryTypeId="2" PostId="9123" RevisionGUID="43b6ce9d-50ff-477d-b5c7-e94af761588e" CreationDate="2019-09-06T14:16:19.670" UserId="7925" Text="In my Direct Light Physically Based Renderer, when I set the roughness too low (ie. 0.0 or close) the specular reflection doesn't show, not even at high resolutions and at perfect angle with the camera / light position.&#xD;&#xA;&#xD;&#xA;I'm using Cook-Torrance's BRDF with Schlick Smith GGX Geometry Function, Shlick Fresnel Function and Trowbridge-Reitz GGX Normal Distribution Function.&#xD;&#xA;&#xD;&#xA;I suspect the whole reason behind this is because when the roughness is 0.0, the result of the Normal Distribution Function is also 0.0 and, consequently, the specular part will also be null.&#xD;&#xA;&#xD;&#xA;    // Trowbridge-Reitz GGX Normal Distribution Function&#xD;&#xA;    float NormalDistributionFunction(vec3 N, vec3 H, float roughness) {&#xD;&#xA;        float a = roughness * roughness;&#xD;&#xA;        float aSquare = a * a;&#xD;&#xA;        float NdotH = max(dot(N, H), 0.0);&#xD;&#xA;        float NdotHSquare = NdotH * NdotH;&#xD;&#xA;    &#xD;&#xA;        float numerator = aSquare;&#xD;&#xA;        float denominator = (NdotHSquare * (aSquare - 1.0) + 1.0);&#xD;&#xA;        denominator = PI * denominator * denominator;&#xD;&#xA;    &#xD;&#xA;        return numerator / denominator;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Cook-Torrance Bidirectional Reflective Distribution Function&#xD;&#xA;    vec3 BRDF(vec3 L, vec3 V, vec3 N, vec3 radiance, vec4 albedo, float metallic, float roughness, vec3 F0) {&#xD;&#xA;    	vec3 H = normalize (V + L);&#xD;&#xA;    &#xD;&#xA;    	float D = NormalDistributionFunction(N, H, roughness);   &#xD;&#xA;    	float G = GeometryFunction(N, V, L, roughness);      &#xD;&#xA;    	vec3  F = FresnelFunction(max(dot(H, V), 0.0), F0);&#xD;&#xA;    &#xD;&#xA;    	vec3 numerator = D * G * F; &#xD;&#xA;    	float denominator = 4 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.001; // Prevent division by zero.&#xD;&#xA;    	vec3 specular = numerator / denominator;&#xD;&#xA;    	&#xD;&#xA;    	vec3 kS = F;&#xD;&#xA;    	vec3 kD = vec3(1.0) - kS;&#xD;&#xA;    	kD *= 1.0 - metallic;	  &#xD;&#xA;    &#xD;&#xA;    	float NdotL = max(dot(N, L), 0.0);        &#xD;&#xA;    &#xD;&#xA;    	vec3 color = (kD * albedo.rgb / PI + specular) * radiance * NdotL;&#xD;&#xA;    	return color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Does this physically make sense?  &#xD;&#xA;The only workaround I see is either not using a perfect mirror value of 0.0 roughness or always clamp the minimum value to something like 0.04.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zDaPU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24902" PostHistoryTypeId="1" PostId="9123" RevisionGUID="43b6ce9d-50ff-477d-b5c7-e94af761588e" CreationDate="2019-09-06T14:16:19.670" UserId="7925" Text="Roughness Value of (Close to) Zero in Physically Based Rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="24903" PostHistoryTypeId="3" PostId="9123" RevisionGUID="43b6ce9d-50ff-477d-b5c7-e94af761588e" CreationDate="2019-09-06T14:16:19.670" UserId="7925" Text="|lighting|brdf|physically-based|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24904" PostHistoryTypeId="2" PostId="9124" RevisionGUID="b1a17b3e-6c35-430e-ad36-643f3fd1e602" CreationDate="2019-09-07T02:20:57.350" UserId="9522" Text="As described by Shirley in his computer graphics book,&#xD;&#xA;&#xD;&#xA;&gt; Cubiccurvesprovidetheminimum-curvatureinterpolantstoasetofpoints. That is, if you have a set of n + 3 points and define the “smoothest” curve that passes through them (that is the curve that has the minimum curvature over its length), this curve can be represented as a piecewise cubic with n segments.&#xD;&#xA;&#xD;&#xA;Could you please give some hints or references about its proof?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24905" PostHistoryTypeId="1" PostId="9124" RevisionGUID="b1a17b3e-6c35-430e-ad36-643f3fd1e602" CreationDate="2019-09-07T02:20:57.350" UserId="9522" Text="Why cubic curves provide the minimum curvature interpolants?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24906" PostHistoryTypeId="3" PostId="9124" RevisionGUID="b1a17b3e-6c35-430e-ad36-643f3fd1e602" CreationDate="2019-09-07T02:20:57.350" UserId="9522" Text="|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24907" PostHistoryTypeId="2" PostId="9125" RevisionGUID="9122d7d6-5e01-4ffe-90dc-4078c2c666f6" CreationDate="2019-09-07T11:18:13.700" UserId="11150" Text="I am making ski jumping game (in Unity) with procedurally generated hill mesh. I want to add lines on hill like this (mesh is created by script, but I've manually assigned materials in Blender) [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because this is procedurally generated (on runtime) (hills can have different sizes) I cannot bake texture in Blender. Mesh for large hill has around 800 vertices. There is my question - is it better to duplicate vertices and then use one material or use four different materials without duplicating vertices?&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/g502s.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/k0CJH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24908" PostHistoryTypeId="1" PostId="9125" RevisionGUID="9122d7d6-5e01-4ffe-90dc-4078c2c666f6" CreationDate="2019-09-07T11:18:13.700" UserId="11150" Text="What is performance better - add four materials to mesh or duplicate every vertex and use packed texture?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24909" PostHistoryTypeId="3" PostId="9125" RevisionGUID="9122d7d6-5e01-4ffe-90dc-4078c2c666f6" CreationDate="2019-09-07T11:18:13.700" UserId="11150" Text="|3d|mesh|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24910" PostHistoryTypeId="5" PostId="8989" RevisionGUID="1a6791cc-7901-411b-9823-954357e4fb25" CreationDate="2019-09-07T15:26:09.520" UserId="6046" Comment="deleted 1 character in body" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;I took the `foot` and `lobster` dataset from [here][2]. **You can see my Renderer's result in [this][3] video** (check the end of my post and sorry for not providing a direct link as I already uploaded on my reddit post)&#xD;&#xA;&#xD;&#xA;As you can see the lobster dataset stretches when viewed from the side. My first guess was that I wasn't accounting for the aspect ratio correctly. I have tried scaling the Bounding box to account for the aspect ratio, then adjusting the stepsize according to that. I've also tried to ignore aspect ratio altogether. Both give similar images.&#xD;&#xA;&#xD;&#xA;I tried rendering more datasets like &quot;Knee&quot;, &quot;Bruce's head&quot;, &quot;DTI Scan&quot;, etc but those didn't even gave an image. There was just random noise everywhere. Here's an example of &quot;Bruce's head&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This happens with both uniform and non-uniform datasets. If some datasets are getting rendered correctly like the &quot;Foot&quot; in my video, this should mean it's more a with that specific dataset itself rather the core algorithm. Nonetheless the link to the code is provided If anybody can point out some mistakes I'd be grateful.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][5]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, it's normalized `(0-1)`, accounted for the aspect ratio `(0, ar)` and adjusted so it's in the center `(-ar/2, ar/2)`. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1***&#xD;&#xA;&#xD;&#xA;EDIT:- If you are hesitating to post an answer here since it's only a suggestion, you can post on Reddit, then when the problem is solved you can post your answer here&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [3]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [4]: https://i.stack.imgur.com/EXyYg.png&#xD;&#xA;  [5]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="24911" PostHistoryTypeId="2" PostId="9126" RevisionGUID="c5aa5405-bdd3-45c7-b689-82674c82f42c" CreationDate="2019-09-07T18:17:32.527" UserId="48" Text="Yes, I think it's expected that setting roughness = 0, combined with using point lights for illumination, leads to no visible specular highlight. The size of the highlight is infinitesimally small, so the sample points (e.g. pixel centers) almost surely miss it. The math breaks down as well, as the reflectance would become infinite on the zero-sized highlight (a delta function).&#xA;&#xA;Clamping roughness to a minimum seems like a physically reasonable thing to do. 0.04 feels like too large a minimum, though; I might pick 0.001 or 0.0001 or something like that.&#xA;&#xA;If you use area lights, then a perfect mirror surface (roughness = 0) could still work and would show the sharp reflected image of the area light. This would probably still require special-casing the perfect-mirror case in shading code, to avoid the problems with infinities." ContentLicense="CC BY-SA 4.0" />
  <row Id="24912" PostHistoryTypeId="5" PostId="9118" RevisionGUID="48e1034f-220e-4242-a4af-cecaa7ab5d64" CreationDate="2019-09-07T18:47:17.247" UserId="231" Comment="Typo" Text="By lighting in object space, sure, you could avoid transforming the normals into world space. However, you'd have to transform the light positions/vectors into the object's space. Also, if you want any view-dependent shading such as specular, you would have to transform the camera position into object space as well, to calculate view vectors.&#xD;&#xA;&#xD;&#xA;Now, all of this can be done straightforwardly using the inverse of the object's world matrix. The inverse world matrix will include the inverse of the object's scale (as well as correctly accounting for the inverse of its rotation and translation), so it will transform the light &amp; camera positions to the appropriate points in the scaled coordinate system. Directional lights don't have a position, but you can transform their direction vector by the inverse world matrix to account for rotation and scale. All of this is fine so far.&#xD;&#xA;&#xD;&#xA;However, you will then run into trouble when doing lighting calculations like N·L or N·V. For exactly the same reason that normals don't transform correctly under non-uniform scaling without using a special normal matrix, these dot products will not come out with the same result when done in a non-uniformly scaled object space as compared to world space. Namely, non-uniform scaling distorts angles. So, all your lighting calculations and BRDFs that depend on angles are going to be messed up.&#xD;&#xA;&#xD;&#xA;While there _are_ ways one could correct this problem by using additional matrices when calculating dot products... it's generally easier and faster to do lighting in world space (or view space). In any case, transforming the normals to world space is a pretty trivial amount of math by modern GPU standards, especially as it only needs to be done per vertex." ContentLicense="CC BY-SA 4.0" />
  <row Id="24913" PostHistoryTypeId="5" PostId="9124" RevisionGUID="4aa0d159-bc38-4353-9420-bb204f119844" CreationDate="2019-09-07T18:50:28.767" UserId="231" Comment="Insert spaces in unreadable quoted text" Text="As described by Shirley in his computer graphics book,&#xD;&#xA;&#xD;&#xA;&gt; Cubic curves provide the minimum-curvature interpolants to a set of points. That is, if you have a set of n + 3 points and define the “smoothest” curve that passes through them (that is the curve that has the minimum curvature over its length), this curve can be represented as a piecewise cubic with n segments.&#xD;&#xA;&#xD;&#xA;Could you please give some hints or references about its proof?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24914" PostHistoryTypeId="2" PostId="9127" RevisionGUID="e651fc11-ce83-4f19-ac93-238e5c0efb78" CreationDate="2019-09-07T19:59:44.957" UserId="6422" Text="Splines confuse me which is one reason I asked somebody else to write that chapter.&#xD;&#xA;&#xD;&#xA;But I like this explanation:&#xD;&#xA;https://www.johndcook.com/blog/2009/02/06/the-smoothest-curve-through-a-set-of-points/" ContentLicense="CC BY-SA 4.0" />
  <row Id="24915" PostHistoryTypeId="2" PostId="9128" RevisionGUID="ec461224-e040-4042-b94a-c3afcf1bd8a7" CreationDate="2019-09-07T22:33:31.893" UserId="10096" Text="For a function $y = f(x)$ the (signed) curvature at $x$ is given by:&#xD;&#xA;$$&#xD;&#xA;\kappa(x) = \frac{f''(x)}{(1+f'^2(x))^{\frac{3}{2}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If you assume that the slope is very small compared to $1$: $ f'^2&lt;\!&lt;1 $, then:&#xD;&#xA;&#xD;&#xA;$$ k(x) \approx f''(x)$$&#xD;&#xA;&#xD;&#xA;Suppose you are given data points ($x_0&lt;x_1&lt;\cdots&lt;x_N$):&#xD;&#xA;&#xD;&#xA;$$(x_0,y_0), (x_1,y_1), ..., (x_N, y_N)$$&#xD;&#xA;&#xD;&#xA;You want to find an interpolating function $f$, such that:&#xD;&#xA;&#xD;&#xA;$$f(x_k) = y_k$$&#xD;&#xA;&#xD;&#xA;And we'll additionally require that it minimizes the energy:&#xD;&#xA;&#xD;&#xA;$$E[f] = \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx$$&#xD;&#xA;&#xD;&#xA;Let $f(x_k) = y_k \wedge \exists f''(x) \wedge f''(x_0)=f''(x_N) = 0$, and let $f$ be piece-wise cubic, then:&#xD;&#xA;$$\forall g \ne f : g(x_k) = y_k \wedge \exists g''(x) \implies $$&#xD;&#xA;$$ E[g] = \int_{x_0}^{x_N}\left(g''(x)\right)^2\,dx &gt; \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx = E[f]$$&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$E[g] - E[f] = \int_{x_0}^{x_N}\left(g''(x)\right)^2\,dx - \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx = $$&#xD;&#xA;&#xD;&#xA;$$ \int_{x_0}^{x_N}\left(g''(x)\right)^2\,dx -2\int_{x_0}^{x_N}g''(x)f''(x)\,dx + \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx$$&#xD;&#xA;$$- 2\int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx + 2\int_{x_0}^{x_N}g''(x)f''(x)\,dx = $$&#xD;&#xA;&#xD;&#xA;$$\int_{x_0}^{x_N}\left(g''(x)-f''(x)\right)^2\,dx + 2\int_{x_0}^{x_N}(g''(x)-f''(x))f''(x)\,dx $$&#xD;&#xA;&#xD;&#xA;Clearly if $g \ne f$ almost everywhere then $\int_{x_0}^{x_N}\left(g''(x)-f''(x)\right)^2\,dx &gt; 0$, then to prove $E[g]-E[f]&gt;0$ it remains to show that: $2\int_{x_0}^{x_N}(g''(x)-f''(x))f''(x)\,dx \geq 0$.&#xD;&#xA;&#xD;&#xA;Integrating by parts yields:&#xD;&#xA;&#xD;&#xA;$$2\int_{x_0}^{x_N}(g''(x)-f''(x))f''(x)\,dx = 2\int_{x_0}^{x_N}f''(x)\,d[g'(x)-f'(x)] = $$&#xD;&#xA;&#xD;&#xA;$$ 2(g'(x_N)-f'(x_N))f''(x_N) - 2(g'(x_0)-f'(x_0))f''(x_0)$$&#xD;&#xA;$$-2\int_{x_0}^{x_N}(g'(x)-f'(x))f'''(x)\,dx = $$&#xD;&#xA;&#xD;&#xA;Since $f(x_N) = f(x_0) = 0$ the first two terms are 0, and we are left with:&#xD;&#xA;&#xD;&#xA;$$- 2\int_{x_0}^{x_N}(g'(x)-f'(x))f'''(x)\,dx = $$&#xD;&#xA;&#xD;&#xA;Since $f$ was chosen to be piece-wise cubic, then $f(x) = a_kx^3 + b_kx^2 + c_kx + d_k, x \in [x_k,x_{k+1})$ and consequently $f'''([x_k,x_{k+1})) = 6a_k = &#xD;&#xA;\operatorname{const}$, and we can take it out of the integral and integrate in each interval $[x_k,x_{k+1}]$:&#xD;&#xA;&#xD;&#xA;$$-2\sum_{k=0}^{N-1}f'''([x_k,x_{k+1}))\int_{x_k}^{x_{k+1}}(g'(x)-f'(x))\,dx = $$&#xD;&#xA;&#xD;&#xA;$$-2\sum_{k=0}^{N-1}6a_k[g(x_{k+1})-f(x_{k+1}) - (g(x_k) - f(x_k))] = $$&#xD;&#xA;&#xD;&#xA;Using the interpolation constraint $f(x_k) = g(x_k) = y_k$:&#xD;&#xA;&#xD;&#xA;$$-2\sum_{k=0}^{N-1}6a_k[y_{k+1} - y_{k+1} - (y_k-y_k)] = 0$$&#xD;&#xA;&#xD;&#xA;Thus:&#xD;&#xA;&#xD;&#xA;$$E[g] - E[f] = \int_{x_0}^{x_N}\left(g''(x)-f''(x)\right)^2\,dx &gt; 0$$&#xD;&#xA;&#xD;&#xA;And consequently:&#xD;&#xA;&#xD;&#xA;$$E[g] &gt; E[f]$$&#xD;&#xA;&#xD;&#xA;Which proves the fact that an interpolating C2 cubic spline with natural end conditions minimizes the squared (approximate) &quot;curvature&quot; energy:&#xD;&#xA;&#xD;&#xA;$$ E[f] = \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx $$" ContentLicense="CC BY-SA 4.0" />
  <row Id="24916" PostHistoryTypeId="5" PostId="9128" RevisionGUID="4d5b2ab8-bc62-44dc-8347-2fe2f6acd4e6" CreationDate="2019-09-07T22:39:48.397" UserId="10096" Comment="added 4 characters in body" Text="For a function $y = f(x)$ the (signed) curvature at $x$ is given by:&#xD;&#xA;$$&#xD;&#xA;\kappa(x) = \frac{f''(x)}{(1+f'^2(x))^{\frac{3}{2}}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If you assume that the slope is very small compared to $1$: $ f'^2&lt;\!&lt;1 $, then:&#xD;&#xA;&#xD;&#xA;$$ k(x) \approx f''(x)$$&#xD;&#xA;&#xD;&#xA;Suppose you are given data points ($x_0&lt;x_1&lt;\cdots&lt;x_N$):&#xD;&#xA;&#xD;&#xA;$$(x_0,y_0), (x_1,y_1), ..., (x_N, y_N)$$&#xD;&#xA;&#xD;&#xA;You want to find an interpolating function $f$, such that:&#xD;&#xA;&#xD;&#xA;$$f(x_k) = y_k$$&#xD;&#xA;&#xD;&#xA;And we'll additionally require that it minimizes the energy:&#xD;&#xA;&#xD;&#xA;$$E[f] = \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx$$&#xD;&#xA;&#xD;&#xA;Let $f(x_k) = y_k \wedge \exists f''(x) \wedge f''(x_0)=f''(x_N) = 0$, and let $f$ be piece-wise cubic, then:&#xD;&#xA;$$\forall g \ne f : g(x_k) = y_k \wedge \exists g''(x) \implies $$&#xD;&#xA;$$ E[g] = \int_{x_0}^{x_N}\left(g''(x)\right)^2\,dx &gt; \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx = E[f]$$&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$E[g] - E[f] = \int_{x_0}^{x_N}\left(g''(x)\right)^2\,dx - \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx = $$&#xD;&#xA;&#xD;&#xA;$$ \int_{x_0}^{x_N}\left(g''(x)\right)^2\,dx -2\int_{x_0}^{x_N}g''(x)f''(x)\,dx + \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx$$&#xD;&#xA;$$- 2\int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx + 2\int_{x_0}^{x_N}g''(x)f''(x)\,dx = $$&#xD;&#xA;&#xD;&#xA;$$\int_{x_0}^{x_N}\left(g''(x)-f''(x)\right)^2\,dx + 2\int_{x_0}^{x_N}(g''(x)-f''(x))f''(x)\,dx $$&#xD;&#xA;&#xD;&#xA;Clearly if $g \ne f$ almost everywhere then $\int_{x_0}^{x_N}\left(g''(x)-f''(x)\right)^2\,dx &gt; 0$, then to prove $E[g]-E[f]&gt;0$ it remains to show that: $2\int_{x_0}^{x_N}(g''(x)-f''(x))f''(x)\,dx \geq 0$.&#xD;&#xA;&#xD;&#xA;Integrating by parts yields:&#xD;&#xA;&#xD;&#xA;$$2\int_{x_0}^{x_N}(g''(x)-f''(x))f''(x)\,dx = 2\int_{x_0}^{x_N}f''(x)\,d[g'(x)-f'(x)] = $$&#xD;&#xA;&#xD;&#xA;$$ 2(g'(x_N)-f'(x_N))f''(x_N) - 2(g'(x_0)-f'(x_0))f''(x_0)$$&#xD;&#xA;$$-2\int_{x_0}^{x_N}(g'(x)-f'(x))f'''(x)\,dx = $$&#xD;&#xA;&#xD;&#xA;Since $f''(x_N) = f''(x_0) = 0$ the first two terms are 0, and we are left with:&#xD;&#xA;&#xD;&#xA;$$- 2\int_{x_0}^{x_N}(g'(x)-f'(x))f'''(x)\,dx = $$&#xD;&#xA;&#xD;&#xA;Since $f$ was chosen to be piece-wise cubic, then $f(x) = a_kx^3 + b_kx^2 + c_kx + d_k, x \in [x_k,x_{k+1})$ and consequently $f'''([x_k,x_{k+1})) = 6a_k = &#xD;&#xA;\operatorname{const}$, and we can take it out of the integral and integrate in each interval $[x_k,x_{k+1}]$:&#xD;&#xA;&#xD;&#xA;$$-2\sum_{k=0}^{N-1}f'''([x_k,x_{k+1}))\int_{x_k}^{x_{k+1}}(g'(x)-f'(x))\,dx = $$&#xD;&#xA;&#xD;&#xA;$$-2\sum_{k=0}^{N-1}6a_k[g(x_{k+1})-f(x_{k+1}) - (g(x_k) - f(x_k))] = $$&#xD;&#xA;&#xD;&#xA;Using the interpolation constraint $f(x_k) = g(x_k) = y_k$:&#xD;&#xA;&#xD;&#xA;$$-2\sum_{k=0}^{N-1}6a_k[y_{k+1} - y_{k+1} - (y_k-y_k)] = 0$$&#xD;&#xA;&#xD;&#xA;Thus:&#xD;&#xA;&#xD;&#xA;$$E[g] - E[f] = \int_{x_0}^{x_N}\left(g''(x)-f''(x)\right)^2\,dx &gt; 0$$&#xD;&#xA;&#xD;&#xA;And consequently:&#xD;&#xA;&#xD;&#xA;$$E[g] &gt; E[f]$$&#xD;&#xA;&#xD;&#xA;Which proves the fact that an interpolating C2 cubic spline with natural end conditions minimizes the squared (approximate) &quot;curvature&quot; energy:&#xD;&#xA;&#xD;&#xA;$$ E[f] = \int_{x_0}^{x_N}\left(f''(x)\right)^2\,dx $$" ContentLicense="CC BY-SA 4.0" />
  <row Id="24917" PostHistoryTypeId="50" PostId="8757" RevisionGUID="c4c371e8-2b71-4e04-906c-a433368696fd" CreationDate="2019-09-08T08:01:35.367" UserId="-1" />
  <row Id="24918" PostHistoryTypeId="2" PostId="9129" RevisionGUID="eda8322f-2e68-4edd-96b8-79a3d90cd2ca" CreationDate="2019-09-08T15:15:48.260" UserId="228" Text="There's one paper published at siggraph that captured my attention : [Steklov Spectral Geometry][1].&#xD;&#xA;&#xD;&#xA;I'm not an expert in geometry processing, but I'm trying to learn as much as I can.&#xD;&#xA;You can easily read in the introduction:&#xD;&#xA;&#xD;&#xA;&gt; In this paper we provide a practical and mathematically justified spectral approach to extrinsics geometry for geometry processing via an extrinsic alternative to the intrinsic Laplace-Beltrami operator.&#xD;&#xA;&#xD;&#xA;I read through the paper and, for who like me enjoy signal processing, is a very nice read. It my understanding the operator they propose an alternative of the classic laplace beltrami operator:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Delta_{\mathcal{S}} \psi(x) = 0 &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The operator proposed is&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\left\{&#xD;&#xA;\begin{array}{ll}&#xD;&#xA;\Delta \psi(x) = 0 &amp; x \in \Omega \\&#xD;&#xA;\nabla_n \psi(x) = \lambda \psi(x) &amp; x \in \Gamma&#xD;&#xA;\end{array}&#xD;&#xA;\right.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which is the &quot;Steklov eigenproblem&quot;. The first line of the system above is the laplace equation again (but volumetric) the second line is a condition on the normal derivative.&#xD;&#xA;&#xD;&#xA;What I don't understand is why does the former operator represent an &quot;intrinsics&quot; operator while the latter represent an extrinsic operator.&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/pdf/1707.07070.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24919" PostHistoryTypeId="1" PostId="9129" RevisionGUID="eda8322f-2e68-4edd-96b8-79a3d90cd2ca" CreationDate="2019-09-08T15:15:48.260" UserId="228" Text="Stecklov operator vs Laplacian operator" ContentLicense="CC BY-SA 4.0" />
  <row Id="24920" PostHistoryTypeId="3" PostId="9129" RevisionGUID="eda8322f-2e68-4edd-96b8-79a3d90cd2ca" CreationDate="2019-09-08T15:15:48.260" UserId="228" Text="|computational-geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24921" PostHistoryTypeId="2" PostId="9130" RevisionGUID="15b44fa7-1885-4c61-81d8-f782d86a0c97" CreationDate="2019-09-08T16:01:53.950" UserId="5098" Text="I am trying to create a raytracer following peter shirley's in a weekend series. I am getting weird color distortion artifacts when I am running the code on windows. However, the code runs fine when executed on the on my mac. The only difference in code being that I had to replace `drand48()` with `(float)rand() / (RAND_MAX + 1.0)` as the former is not supported on windows.&#xD;&#xA;&#xD;&#xA;How the image looks on windows &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;How it should look&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Heres the code I am using to generate the ppm file &#xD;&#xA;&#xD;&#xA;    void writeToImgae(Vector3f *frameBuffer, RenderOptions *options)&#xD;&#xA;	{&#xD;&#xA;		ofstream ofs(&quot;finalImage.ppm&quot;, ios::out);&#xD;&#xA;		ofs &lt;&lt; &quot;P6\n&quot;&#xD;&#xA;				&lt;&lt; options-&gt;width &lt;&lt; &quot; &quot; &lt;&lt; options-&gt;height &lt;&lt; &quot;\n255\n&quot;;&#xD;&#xA;		for (uint32_t i = 0; i &lt; options-&gt;height * options-&gt;width; ++i)&#xD;&#xA;		{&#xD;&#xA;			char r = (char)(255 * clamp(frameBuffer[i].x, 0.0f, 1.0f));&#xD;&#xA;			char g = (char)(255 * clamp(frameBuffer[i].y, 0.0f, 1.0f));&#xD;&#xA;			char b = (char)(255 * clamp(frameBuffer[i].z, 0.0f, 1.0f));&#xD;&#xA;			ofs &lt;&lt; r &lt;&lt; g &lt;&lt; b;&#xD;&#xA;		}&#xD;&#xA;		ofs.close();&#xD;&#xA;		delete[] frameBuffer;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Would really appreciate if someone could help me with this.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S0Klb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/W2SoL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="24922" PostHistoryTypeId="1" PostId="9130" RevisionGUID="15b44fa7-1885-4c61-81d8-f782d86a0c97" CreationDate="2019-09-08T16:01:53.950" UserId="5098" Text="Weird Ray tracing artifacts when Code run on widows" ContentLicense="CC BY-SA 4.0" />
  <row Id="24923" PostHistoryTypeId="3" PostId="9130" RevisionGUID="15b44fa7-1885-4c61-81d8-f782d86a0c97" CreationDate="2019-09-08T16:01:53.950" UserId="5098" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24924" PostHistoryTypeId="2" PostId="9131" RevisionGUID="c8ae0b65-9f5f-4334-b6d3-19bb6d2070cc" CreationDate="2019-09-08T21:26:29.543" UserId="11153" Text="I'm trying to learn the fundamentals of 3d computer graphics by writing a toy framework in WebGL.&#xD;&#xA;&#xD;&#xA;I'm currently working on mouse based camera controls. There are plenty of good resources in the ACM SIGGRAPH library to be found, but there are some aspects of this area that I can't find answers to.&#xD;&#xA;&#xD;&#xA;A lot of orbit controls simply use the origin as the pivot point, but other implementations can orbit around any arbitrary point in a scene and the camera stays 'still'. I'm trying to implement the latter.&#xD;&#xA;&#xD;&#xA;It seems that a good way to do this would be to simply get the cross product of the two vectors made by the pivot point and 3d coords of the corresponding pixels on the image plane, but I can't anything like this approach anywhere which leads me to believe I've misunderstood some fundamental aspect of image projection/image planes.&#xD;&#xA;&#xD;&#xA;Is the image plane an abstract construct that doesn't really have 3d coords or can pixels in the image plane actually be mapped to world coords?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24925" PostHistoryTypeId="1" PostId="9131" RevisionGUID="c8ae0b65-9f5f-4334-b6d3-19bb6d2070cc" CreationDate="2019-09-08T21:26:29.543" UserId="11153" Text="Can pixels on the image plane be mapped to world space coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24926" PostHistoryTypeId="3" PostId="9131" RevisionGUID="c8ae0b65-9f5f-4334-b6d3-19bb6d2070cc" CreationDate="2019-09-08T21:26:29.543" UserId="11153" Text="|transformations|projections|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24927" PostHistoryTypeId="2" PostId="9132" RevisionGUID="e663ad4c-a51a-41ed-ae88-5299f7e7675d" CreationDate="2019-09-09T04:30:00.433" UserId="4768" Text="Hello and welcome Jonek2208! &#xD;&#xA;&#xD;&#xA;Unity specific questions probably are better suited for the [Unity Graphics Forum][1]. However, I'll try to give you an answer as I do have some experience with the engine.&#xD;&#xA;&#xD;&#xA;In my opinion, the only way of knowing for sure which method is the best would be to implement both and profile them on your target device. Do not fool yourself in thinking that some basic algorithmic analysis is all you need to do. Always profile and compare your solutions, no matter the circumstances.&#xD;&#xA;&#xD;&#xA;One thing I can do is to tell you the trade-offs between the two methods, and also provide a hint at another possible solution. Let's go!&#xD;&#xA;&#xD;&#xA;When using the built-in rendering pipeline, Unity batches objects by materials. A batch is considered to be a change in GPU state followed by one or more draw calls. In other words, if you have four materials, you increase the number of batches when compared to having just one. &#xD;&#xA;&#xD;&#xA;If you are targeting mobile devices, reducing the batch count is one of the keys for achieving good performance, and most mobile developers would choose to use a single material. On the other hand, duplicating vertices incurs a cost in memory, and hence you get better batching at the expense of using more memory. If you are targeting consoles or PCs, you can have a much higher batch count and memory budget, so the solution that you think is simpler to implement, expand, and maintain should be your best bet.&#xD;&#xA;&#xD;&#xA;Another solution would be to use textures instead of vertex colors. For this, you would need to compute the uv-map procedurally when generating the vertices. You could place all textures into an atlas and try to use a single material. This is the usual solution for mobile. If you are targeting PCs/consoles, you could even afford procedural textures in your fragment shader.&#xD;&#xA;&#xD;&#xA;If you are using the latest version of Unity, you can use the SRP Batcher, which batches per shader instead of per material. Hence, you can use 4 materials, but have a single batch if all of them use the same shader. Note some devices may not have this capability, especially on mobile.&#xD;&#xA;&#xD;&#xA;All in all, there are a lot of things to consider in any kind of application. That is why I started talking about profiling on your target device. Honestly, it is the only way of knowing for sure which method is the best. You should build a test scene with thousands of generated meshes and then profile each method. Select the one that fits best in your budget (FPS/memory/etc) and the long-term goals of your project.&#xD;&#xA;&#xD;&#xA;Good luck! :)&#xD;&#xA;&#xD;&#xA;  [1]: https://forum.unity.com/categories/graphics.75/" ContentLicense="CC BY-SA 4.0" />
  <row Id="24931" PostHistoryTypeId="2" PostId="9134" RevisionGUID="054e15c3-bef4-4fde-8fb2-272de6237d93" CreationDate="2019-09-09T05:55:30.447" UserId="48" Text="I'm not entirely sure, but I guess it might have to do with the notions of [intrinsic vs extrinsic curvature](https://www.maths.ox.ac.uk/about-us/departmental-art/theory/differential-geometry). The Laplace–Beltrami operator on a manifold is, I think, intrinsic in the sense that it can be constructed from the geometry of the manifold itself and doesn't depend on any embedding in an ambient space. The Steklov operator, on the other hand, looks like it's written explicitly in terms of an embedding, so would be extrinsic in that sense." ContentLicense="CC BY-SA 4.0" />
  <row Id="24932" PostHistoryTypeId="5" PostId="9134" RevisionGUID="d53d5a1d-d622-43a5-9657-62520146dbf4" CreationDate="2019-09-09T06:00:54.840" UserId="48" Comment="added 16 characters in body" Text="I'm not entirely sure, but I guess it might have to do with the notions of [intrinsic vs extrinsic curvature](https://www.maths.ox.ac.uk/about-us/departmental-art/theory/differential-geometry). The Laplace–Beltrami operator on a manifold is, I think, intrinsic in the sense that it can be constructed from the &quot;internal&quot; geometry within the manifold itself, and doesn't depend on any embedding in an ambient space. The Steklov operator, on the other hand, looks like it's written explicitly in terms of an embedding, so would be extrinsic in that sense." ContentLicense="CC BY-SA 4.0" />
  <row Id="24933" PostHistoryTypeId="2" PostId="9135" RevisionGUID="065a50d3-ae9e-4d3f-9f04-ed09dbe88a9b" CreationDate="2019-09-09T14:04:31.513" UserId="11155" Text="looking for suggestion whether it is worth implementing a post process FXAA pass on modern mobile GPU's (mainly looking at apple A Series chip), or should i simply use the MSAA.&#xD;&#xA;Did a basic test with implementing basic FXAA which took eight neighbouring samples and averaged them for result. The performance of this FXAA was even a bit slower than turning on MSAA. &#xD;&#xA;I am using Metal API, if that helps." ContentLicense="CC BY-SA 4.0" />
  <row Id="24934" PostHistoryTypeId="1" PostId="9135" RevisionGUID="065a50d3-ae9e-4d3f-9f04-ed09dbe88a9b" CreationDate="2019-09-09T14:04:31.513" UserId="11155" Text="FXAA vs MSAA on modern hardware" ContentLicense="CC BY-SA 4.0" />
  <row Id="24935" PostHistoryTypeId="3" PostId="9135" RevisionGUID="065a50d3-ae9e-4d3f-9f04-ed09dbe88a9b" CreationDate="2019-09-09T14:04:31.513" UserId="11155" Text="|antialiasing|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24939" PostHistoryTypeId="2" PostId="9137" RevisionGUID="5f0f4ca1-eae9-445d-8154-a59939a1d880" CreationDate="2019-09-10T03:17:18.660" UserId="48" Text="Most mobile GPUs use [tiled rendering](https://en.wikipedia.org/wiki/Tiled_rendering), which can make MSAA surprisingly cheap relative to desktop GPUs. If the app is doing simple forward rendering without filtering/blurring passes, the GPU may be able to do MSAA rasterization and resolve directly on chip (per tile) without ever storing the MSAA samples out to memory. This may make MSAA both faster and less power-hungry than a technique like FXAA that relies on filtering the framebuffer (which necessitates storing it out to memory and reading it back in when sampling).&#xA;&#xA;As for image quality, it's difficult to compare (and is subjective anyway). FXAA might be better at reducing jaggies depending on the MSAA level, but at the cost of over-blurring edges. FXAA can also address shader aliasing, for example aliasing due to specular on a rough normal map and such things, which MSAA won't help with. Ultimately you'll have to make a choice whether the aesthetic benefits (if any) outweigh the increased cost." ContentLicense="CC BY-SA 4.0" />
  <row Id="24945" PostHistoryTypeId="2" PostId="9139" RevisionGUID="57e01a7f-e6ef-4620-aaa7-4fa054bd7d12" CreationDate="2019-09-10T19:16:01.373" UserId="8233" Text="I've been experimenting with raytracing using GLSL. I had success rendering a cube which encloses the object.&#xD;&#xA;&#xD;&#xA;Now I want to do a full-screen raytrace, and I want to construct a quad which covers the screen. This isn't working.&#xD;&#xA;&#xD;&#xA;First, for the working version, the shaders looked something like this:&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    in vec3 v_position;&#xD;&#xA;&#xD;&#xA;    uniform mat4 u_proj_view;&#xD;&#xA;    &#xD;&#xA;    void main ()&#xD;&#xA;    {&#xD;&#xA;    	gl_Position = u_proj_view * vec4 (v_position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader, which computes the word coordinate `W` of the fragment, and given the eye coordinate `E` solves `P=E+t(W-E)` for `t` given some surface intersection constraint on `P`.&#xD;&#xA;&#xD;&#xA;    vec3 W = screen_to_world (gl_FragCoord, inverse_proj_view, viewport);&#xD;&#xA;    vec3 EW = W - E;&#xD;&#xA;    // solve for t, etc etc.&#xD;&#xA;&#xD;&#xA;The `screen_to_world` function I took from [here](https://stackoverflow.com/questions/38938498/how-do-i-convert-gl-fragcoord-to-a-world-space-point-in-a-fragment-shader)&#xD;&#xA;&#xD;&#xA;    vec3 screen_to_world&#xD;&#xA;    (&#xD;&#xA;    	in vec4 screen_fragment_coordinate,&#xD;&#xA;    	in mat4 inverse_projection_view,&#xD;&#xA;    	in vec4 viewport&#xD;&#xA;    )&#xD;&#xA;    {&#xD;&#xA;    	vec4 S = screen_fragment_coordinate;&#xD;&#xA;    	vec4 NDC;&#xD;&#xA;    &#xD;&#xA;    	NDC.xy = ((2.0 * S.xy) - (2.0 * viewport.xy))&#xD;&#xA;    		/ (viewport.zw) - 1.0;&#xD;&#xA;    &#xD;&#xA;    	NDC.z = (2.0 * S.z - gl_DepthRange.near - gl_DepthRange.far) /&#xD;&#xA;    		(gl_DepthRange.far - gl_DepthRange.near);&#xD;&#xA;    &#xD;&#xA;    	NDC.w = 1.0;&#xD;&#xA;    &#xD;&#xA;    	return vec4 (inverse_projection_view * (NDC / S.w)).xyz;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For the full-screen render, It would be nice to construct a quad directly in clip space, or directly in screen space. I tried using vertex data like this&#xD;&#xA;&#xD;&#xA;	Vertex full_screen_quad [4] =&#xD;&#xA;	{&#xD;&#xA;		{{-1, -1, 0.5}},&#xD;&#xA;		{{+1, -1, 0.5}},&#xD;&#xA;		{{-1, +1, 0.5}},&#xD;&#xA;		{{+1, +1, 0.5}}&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;And changed the vertex shader to&#xD;&#xA;&#xD;&#xA;    gl_Position = vec4 (v_position, 1.0);&#xD;&#xA;&#xD;&#xA;which omits the projection-view transformation. I was hoping that this would still produce valid values for `screen_to_world` in the fragment shader, but no such luck. The screen is filled but the rays are wonky.&#xD;&#xA;&#xD;&#xA;To investigate, I printed out the coordinates of the cube vertices when multiplied by the projection-view matrix and, when the cube was on screen, were something like&#xD;&#xA;&#xD;&#xA;    vec4(-2.704530, -12.888471, 12.998095, 13.171925)&#xD;&#xA;&#xD;&#xA;I was expecting values in the range `[0..1]`, so clearly I don't understand which coordinate space I'm working in, or I don't understand w-coordinates, or viewports, or something.&#xD;&#xA;&#xD;&#xA;Are there *fixed* coordinates which I can *directly* pass to `gl_Position`, *untransformed*, which will effectively cover the near plane of the viewing frustum, exactly?&#xD;&#xA;&#xD;&#xA;(When done correctly, passing such coordinates to the above `screen_to_world` will yield the world-space coordinates of the near frustum plane.)&#xD;&#xA;&#xD;&#xA;Can I describe these independently of the projection-view matrix, and still have `screen_to_world` work correctly for each fragment?&#xD;&#xA;&#xD;&#xA;Alternatively, and less ideally, can I hack some world-space coordinates, given the arguments to `glm::lookAt` and `glm::perspective` (which produce the `projection*view` matrix), such that they will cover the near frustum plane?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24946" PostHistoryTypeId="1" PostId="9139" RevisionGUID="57e01a7f-e6ef-4620-aaa7-4fa054bd7d12" CreationDate="2019-09-10T19:16:01.373" UserId="8233" Text="What quad will fill the screen, which can be inverse-projection-view transformed to map to the near frustum plane?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24947" PostHistoryTypeId="3" PostId="9139" RevisionGUID="57e01a7f-e6ef-4620-aaa7-4fa054bd7d12" CreationDate="2019-09-10T19:16:01.373" UserId="8233" Text="|opengl|transformations|glsl|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24948" PostHistoryTypeId="2" PostId="9140" RevisionGUID="49f81554-b6af-4314-9227-dcde0a1d603e" CreationDate="2019-09-11T03:39:53.173" UserId="2654" Text="It's important to understand that &quot;anti-aliasing&quot; techniques like FXAA were invented mainly to deal with the fact that standard methods like multisampling do not work well at all in deferred rendering situations. In order to do MSAA in a deferred renderer, you would need to have all of your G-buffers be multisampled, which dramatically increases the size of those g-buffers. Which puts more pressure on the GPU's memory bandwidth during the lighting passes, since you have that much more data to read. Plus, the lighting passes have to do per-sample rendering, so most of the benefit of MSAA compared to straight super-sampling gets tossed out with lighting passes.&#xD;&#xA;&#xD;&#xA;However, all of that is only really true on standard desktop GPUs. Tile-based platforms (commonly found in the mobile space) can potentially avoid the memory cost increase entirely by keeping the multisampled g-buffers within tile memory alone. Of course, only modern APIs like Metal and Vulkan are capable of really expressing this concept at the API level, but the capability is there.&#xD;&#xA;&#xD;&#xA;Oh sure, MSAA on a TBR will still require lots more tiles and therefore lighting shader invocations. And the lighting passes still have to do per-sample computations. But the overall performance cost will scale much better than a desktop GPU for deferred rendering, as there will be a *lot* less memory bandwidth pressure.&#xD;&#xA;&#xD;&#xA;Plus, there's the fact that FXAA-style techniques run roughshod over how TBRs work. FXAA-like techniques require reading from neighboring texels, which may be outside of the current tile. Well, that means you have to resolve all of your rendering before doing the FXAA pass. That's a bad thing. By contrast, multisampling, including the multisample resolve operation, can be done in-situ within a given tile.&#xD;&#xA;&#xD;&#xA;So it's not really a surprise that FXAA would not yield better performance than even relatively light MSAA on a TBR-style GPU. *Especially* if you're not using deferred rendering." ContentLicense="CC BY-SA 4.0" />
  <row Id="24949" PostHistoryTypeId="2" PostId="9141" RevisionGUID="fea9ad94-a141-42dc-9730-bd42ef6d48f2" CreationDate="2019-09-11T06:23:36.163" UserId="11163" Text="I'm self taught in C++ without any formal education and throughout the past 15 years I've learned both OpenGL 1.0 up through Modern OpenGL and DirectX 9c, 10 and 11. I have not gotten into DirectX 12 and I've been wanting to try my hand at Vulkan. I have only completed a few basic tutorials to draw a simple triangle or a simple spinning cube with Vulkan. As with DirectX 11 and OpenGL 3.3+ I have written fully working 3D Game Engines and even used them Engines to build simple games.&#xD;&#xA;&#xD;&#xA;I would have to say that it depends on the overall environment of the person who is learning. If you are just getting into 3D Graphics Programming I would say for starters to jump into OpenGL or DirectX 11 since there is plenty of tutorials, resources, examples and already working applications out there. Learning 3D Graphics is by no means an easy subject.&#xD;&#xA;&#xD;&#xA;If we abstract away from the programming aspect of it and just focus on the notion of what kind of techniques are used involving the different levels of math leading into data sets and data structures and algorithms; there is a lot that you have to know and understand first before you can even try to build a 3D Game Engine or to use an existing one effectively.&#xD;&#xA;&#xD;&#xA;Now if you already understand all of the math and theory behind it and you have some programming experience you can use already existing APIs, Libraries and Applications such as Unity or Unreal Engine and just write the source code and scripts you need to make your application work.&#xD;&#xA;&#xD;&#xA;So from my own understanding and the way that I see it is this if you are looking to build a quick game just for the sake of building a game; go with already existing frame works that would make your production time much smaller. On the other hand, if you want to understand the inner workings of how Game Engines / Physics Engines / Animation Engines and Simulators are designed and want to build one yourself, then this is where you have a choice between choosing your API such as DirectX, OpenGL or Vulkan. One of the determining factors here would also be your existing programming knowledge. What I mean by this is if you don't know anything about multi-threading, synchronous vs asynchronous calls, memory fences, data races, semaphores, and parallelism (parallel programming), then I would suggest to stay away from Vulkan and stick with either DirectX 11 or OpenGL versions 3.3 - 4.x.&#xD;&#xA;&#xD;&#xA;I mention this because if you don't know how to properly manage your memory along with your threads and access time; Vulkan will bite you in the arse! Where OpenGL and DirectX will hold your hand all the way through consuming much more CPU power. &#xD;&#xA;&#xD;&#xA;Now if your level of programming knowledge is decent, and you have the following math backgrounds that involves all levels of Algebra, Geometry, Trigonometry, Boolean Algebra, Probability, Statistics, Vector - Matrix based Algebra, Calculus I,II,.... Infinty(lol). Vector Calculus, Linear Algebra, Systems of Linear Equations, Analytical Geometry with Vector Calculus of Multi-variable calculations, Number and Set Theory, Data Sets and Structures, Computational Analysis, Computational and Algorithmic Design. Then you can get into the concepts of what it takes to make an actual game engine and this is without any Applied Mathematics or any Physics equations which you will need. Once you have that background and enough programming experience especially memory management and pointer arithmetic then you can begin to build your Game Engine.&#xD;&#xA;&#xD;&#xA;So the thing here is you have to understand all of the aspects of what it takes to make a Game Engine in order to Do Advanced Graphics Programming. If you are doing just 2D graphics then life isn't too hard as you can do that in Python without any of the aforementioned APIs! But if you want to be serious and design a full fledged power house Game Engine that is robust with many feature sets, then the choice here would be either C or C++ and using either OpenGL, Direct X or Vulkan. Any of them would be just fine. Now if you are building the Engine from Scratch and you are looking for the most &quot;efficient&quot; running Engine with the least amount of resource overhead then you would want to choose Vulkan. But if you go this route you should at least know everything that I had mentioned above and some! &#xD;&#xA;&#xD;&#xA;So as you can see Vulkan is not really geared towards beginner programmers in this field. You have to have extensive knowledge of all of the math, programming paradigms, all of the different types of data sets and algorithms including threading, memory synchronization, parallel programming. And even then that's just to get the application to load a simple 2D triangle on to the screen. What can be done in about 100 lines of code in OpenGL or 250 lines of code in DirectX takes almost 1,000 lines of Code in Vulkan!&#xD;&#xA;&#xD;&#xA;Vulkan leaves everything up to you as your are responsible for all aspects of how you are using Vulkan in your application. There is no hand holding, it doesn't get in your way, it'll allow you to shoot yourself in the foot or allow you to hang yourself buy a recursive noose!&#xD;&#xA;&#xD;&#xA;Now this isn't to say that beginners or those that are new to this field shouldn't learn Vulkan, but what I would suggest for them is this: First Learn enough of OpenGL and or DirectX to get your feet wet to see how a basic application is structured just to render a simple triangle or a spinning cube. Get familiar with their APIs and their recurring patterns of their structures. While learning that you could learn Vulkan on the side in Parallel then this way you can see how each of the three are accomplishing the same task, but know how they do it differently, then you can also compare the results between the different APIs and from there you can then make a choice of which is preferred to you. This method would also give you another tool in your tool box, and you could even write your application to support all 3 and have the &quot;User&quot; select which Renderer to choose at application start up.&#xD;&#xA;&#xD;&#xA;In the end it is all up to that person to choose which route they want to go down, and from there their success will be determined by their dedication, constant study, hard work, trial and error, and most importantly their failures. If you don't fail then you are not successful! You are only successful if you have failed, found your mistake(s), fixed them, moved on and got back up and did it all over again! " ContentLicense="CC BY-SA 4.0" />
  <row Id="24950" PostHistoryTypeId="2" PostId="9142" RevisionGUID="c560d6ff-e3f2-4c83-a249-9de4c1345868" CreationDate="2019-09-11T09:46:37.343" UserId="11165" Text="I'm  using an app for face redaction that doesn't allow access to the source code but only allows me to pass pixel values for red, green and blue channel upon which it creates a matrix with the same average RGB values for every ROI pixel value. For eg. if I give Red=32,Blue=123 and Green=233 it will assign these RGB values for every pixel of the ROI and then draws a colored patch on the face.&#xD;&#xA;&#xD;&#xA; So I was wondering is there a general combination of RGB values of a pixel to distort it and make it look like it's blurred. I can also set the opacity value in the app.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="24951" PostHistoryTypeId="1" PostId="9142" RevisionGUID="c560d6ff-e3f2-4c83-a249-9de4c1345868" CreationDate="2019-09-11T09:46:37.343" UserId="11165" Text="Blurring image with RGB values without convolving it with a kernel" ContentLicense="CC BY-SA 4.0" />
  <row Id="24952" PostHistoryTypeId="3" PostId="9142" RevisionGUID="c560d6ff-e3f2-4c83-a249-9de4c1345868" CreationDate="2019-09-11T09:46:37.343" UserId="11165" Text="|image-processing|blur|gaussian-blur|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24953" PostHistoryTypeId="5" PostId="9117" RevisionGUID="67d78730-637a-4745-9d35-fe60e0e8969b" CreationDate="2019-09-11T14:41:21.587" UserId="11142" Comment="added 180 characters in body" Text="Red, Green and Blue apparently contribute differently to the luminosity perceived by humans:&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;&#xD;&#xA;I am trying to find an algorithm to map unsigned 16 bit integers into RGB values such that the relative luminance of the RGB values to which the integers map respects their order (with integer 0 being black, integer 2^16-1 white and all other integers mapped to some RGB color).&#xD;&#xA;&#xD;&#xA;I don't really care about how the colors evolve as one walks up from 0 to 2^16-1 as long as luminosity always increases and a reasonably large swathe of the RGB space is used.&#xD;&#xA;&#xD;&#xA;Apparently I am missing the right words to describe what I am trying to accomplish as I've failed to google anything pertinent. A couple of weeks ago I had stumbled upon a paper that described such an algorithm in the form of a helix that is arranged diagonally in the three dimensional RGB space such that when one starts at the base of the helix and works his way towards the other end, luminosity always increases and a large variety of color is used. Alas, I can't find it any more.&#xD;&#xA;&#xD;&#xA;&lt;h1&gt;update&lt;/h1&gt;&#xD;&#xA;Found the algorithm I was looking for. It is known as the 'cubehelix' color scheme by Dave Green and is described here:&#xD;&#xA;http://www.mrao.cam.ac.uk/~dag/CUBEHELIX/. The original paper is here: http://astron-soc.in/bulletin/11June/289392011.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="24957" PostHistoryTypeId="2" PostId="9144" RevisionGUID="54f5bb0f-d138-45ae-8c23-35ab645c07a2" CreationDate="2019-09-11T17:24:42.940" UserId="506" Text="Blurring an image depends on being able to read from the image. If you don’t have access to the pixel data, or external information about the image contents (e.g. average hue / luminance), there’s no way to find an overlay color that will look like you’ve blurred what it’s on top of." ContentLicense="CC BY-SA 4.0" />
  <row Id="24958" PostHistoryTypeId="33" PostId="9008" RevisionGUID="b7b011a9-0977-4dae-b040-283649c50af0" CreationDate="2019-09-11T17:44:21.307" UserId="228" Comment="56" />
  <row Id="24959" PostHistoryTypeId="2" PostId="9145" RevisionGUID="48e7a9d5-2a4c-4903-9c67-7327fee77c60" CreationDate="2019-09-12T07:26:56.790" UserId="2041" Text="Since you know vaguely what the pixels you're covering up look like (they are faces), your best bet to get the appearance of a blur is to really blur an image of a face in a standard image editing tool, then use the colour picker to choose a representative colour from that region. That's the closest you can get, but it still won't look blurred: as Noah Witherspoon said, that's impossible given these constraints.&#xD;&#xA;&#xD;&#xA;Obviously it will work less well if the pictures you're operating on have different lighting conditions or faces of a different skin colour from the one you sample. And if the images being redacted are frames of a video, the motion of the video will give you away immediately.&#xD;&#xA;&#xD;&#xA;Another approach might be to choose a colour that you know won't show up in the real images (e.g. programmer pink). Then, instead of showing the image that comes out of your tool, use the marked pixels to generate a mask, and use an actual blur tool on the original image so that only the pixels selected by the mask are blurred." ContentLicense="CC BY-SA 4.0" />
  <row Id="24960" PostHistoryTypeId="2" PostId="9146" RevisionGUID="9c567dd9-1308-4d04-b6d6-eceb4e88b771" CreationDate="2019-09-12T11:42:58.803" UserId="7925" Text="I've developed a simple (Third-Person) Perspective Camera with Orbit controls.&#xD;&#xA;&#xD;&#xA;However, my implementation doesn't handle the case where if the pitch goes over 90º it flips upside down. From what I've learned, the reason behind it has to do with using the Look-At function.&#xD;&#xA;&#xD;&#xA;My questions are:  &#xD;&#xA;&#xD;&#xA; - Is the problem really the Look-at function? How would I fix this, without restricting the camera's pitch?&#xD;&#xA; - I want to develop a camera class that is control agnostic (can be fly, orbit, ...) and therefore not take into account that it's first/third-person. Are there methods on how to develop such a camera abstraction?  &#xD;&#xA; - I also want it to be able to roll, can the advised solution for the last question support it? &#xD;&#xA; - I haven't delved into quaternions yet, is the solution based on them? If so, are there also limitations to an implementation like that?&#xD;&#xA;&#xD;&#xA;I'm basically looking for theory on developing proper robust cameras (with as few limitations as possible), so if you could point me into the right direction it would be nice, but a full answer is also very much appreciated. Code is not essential, but it would be also very helpful to see a proper (yet simple) implementation.&#xD;&#xA;&#xD;&#xA;My camera implementation (in Vulkan):  &#xD;&#xA;Camera.hpp:  &#xD;&#xA;``` lang-cpp&#xD;&#xA;#pragma once&#xD;&#xA;&#xD;&#xA;#define GLM_FORCE_RADIANS&#xD;&#xA;#define GLM_FORCE_DEPTH_ZERO_TO_ONE&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;glm/gtc/quaternion.hpp&gt;&#xD;&#xA;#include &lt;glm/gtc/matrix_transform.hpp&gt;&#xD;&#xA;&#xD;&#xA;#include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;class CameraControl;&#xD;&#xA;&#xD;&#xA;class Camera &#xD;&#xA;{&#xD;&#xA;private:&#xD;&#xA;    glm::vec3 position = glm::vec3(0.0f, 0.0f, 1.0f);&#xD;&#xA;    glm::vec3 target = glm::vec3(0.0f, 0.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;    glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;    float fov = glm::radians(45.0f);&#xD;&#xA;    float aspectRatio = 1.0f;&#xD;&#xA;    float near = 0.1f;&#xD;&#xA;    float far = 1000.0f;&#xD;&#xA;&#xD;&#xA;    glm::mat4 view;&#xD;&#xA;    glm::mat4 projection;&#xD;&#xA;&#xD;&#xA;private:&#xD;&#xA;    void updateViewMatrix();&#xD;&#xA;    void updateProjectionMatrix();&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;    CameraControl *control;&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;    Camera();&#xD;&#xA;    ~Camera();&#xD;&#xA;    void setPosition(glm::vec3 position);&#xD;&#xA;    void setTarget(glm::vec3 target);&#xD;&#xA;    void setPerspective(float fov, float aspectRatio, float near, float far);&#xD;&#xA;&#xD;&#xA;    glm::mat4 inline getView() { return view; };&#xD;&#xA;    glm::mat4 inline getProjection() { return projection; };&#xD;&#xA;    glm::vec3 inline getPosition() { return position; };&#xD;&#xA;    glm::vec3 inline getTarget() { return target; };&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;class CameraControl {&#xD;&#xA;public:&#xD;&#xA;    float orbitSensitivity = 0.2f;&#xD;&#xA;    float zoomSensitivity = 0.0025f;&#xD;&#xA;&#xD;&#xA;private:&#xD;&#xA;    Camera *camera;&#xD;&#xA;    &#xD;&#xA;    bool firstMouse;&#xD;&#xA;    float lastMouseX;&#xD;&#xA;    float lastMouseY;&#xD;&#xA;&#xD;&#xA;    float distance;&#xD;&#xA;    float pitch;&#xD;&#xA;    float yaw;&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;    CameraControl(Camera *camera);&#xD;&#xA;    void handleInput(GLFWwindow *window);&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Camera.cpp:  &#xD;&#xA;``` lang-cpp&#xD;&#xA;#include &quot;Camera.hpp&quot;&#xD;&#xA;&#xD;&#xA;Camera::Camera() {&#xD;&#xA;    control = new CameraControl(this);&#xD;&#xA;    updateViewMatrix();&#xD;&#xA;    updateProjectionMatrix();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Camera::~Camera() {&#xD;&#xA;    delete control;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Camera::setPosition(glm::vec3 position) {&#xD;&#xA;    this-&gt;position = position;&#xD;&#xA;    updateViewMatrix();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Camera::setTarget(glm::vec3 target) {&#xD;&#xA;    this-&gt;target = target;&#xD;&#xA;    updateViewMatrix();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Camera::setPerspective(float fov, float aspectRatio, float near, float far) {&#xD;&#xA;    this-&gt;fov = fov;&#xD;&#xA;    this-&gt;aspectRatio = aspectRatio;&#xD;&#xA;    this-&gt;near = near;&#xD;&#xA;    this-&gt;far = far;&#xD;&#xA;    updateProjectionMatrix();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Camera::updateViewMatrix() {&#xD;&#xA;    view = glm::lookAt(position, target, up);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Camera::updateProjectionMatrix() {&#xD;&#xA;    projection = glm::perspective(fov, aspectRatio, near, far);&#xD;&#xA;    projection[1][1] *= -1; // Vulkan coordinate system fix&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;CameraControl::CameraControl(Camera* camera) {&#xD;&#xA;    this-&gt;camera = camera;&#xD;&#xA;    firstMouse = true;&#xD;&#xA;    distance = 1.0f;&#xD;&#xA;    pitch = 0.0f;&#xD;&#xA;    yaw = 180.0f;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void CameraControl::handleInput(GLFWwindow *window) {&#xD;&#xA;    double xpos, ypos;&#xD;&#xA;    glfwGetCursorPos(window, &amp;xpos, &amp;ypos);&#xD;&#xA;&#xD;&#xA;    if (firstMouse) {&#xD;&#xA;        lastMouseX = xpos;&#xD;&#xA;        lastMouseY = ypos;&#xD;&#xA;        firstMouse = false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float xoffset = xpos - lastMouseX;&#xD;&#xA;    float yoffset = lastMouseY - ypos;&#xD;&#xA;&#xD;&#xA;    lastMouseX = xpos;&#xD;&#xA;    lastMouseY = ypos;&#xD;&#xA;&#xD;&#xA;    if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT)) {&#xD;&#xA;        pitch -= yoffset * orbitSensitivity;&#xD;&#xA;        yaw -= xoffset * orbitSensitivity;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT)) {&#xD;&#xA;        distance += yoffset * zoomSensitivity;&#xD;&#xA;        distance = glm::max(distance, 0.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float verticalDistance = distance * glm::sin(glm::radians(pitch));&#xD;&#xA;    float horizontalDistance = distance * glm::cos(glm::radians(pitch));&#xD;&#xA;&#xD;&#xA;    glm::vec3 position;&#xD;&#xA;    position.x = camera-&gt;getTarget().x - horizontalDistance * glm::sin(glm::radians(yaw));&#xD;&#xA;    position.y = camera-&gt;getTarget().y + verticalDistance;&#xD;&#xA;    position.z = camera-&gt;getTarget().z - horizontalDistance * glm::cos(glm::radians(yaw));&#xD;&#xA;    camera-&gt;setPosition(position);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Thank you for your attention! Cheers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="24961" PostHistoryTypeId="1" PostId="9146" RevisionGUID="9c567dd9-1308-4d04-b6d6-eceb4e88b771" CreationDate="2019-09-12T11:42:58.803" UserId="7925" Text="Camera Implementation without Limitations" ContentLicense="CC BY-SA 4.0" />
  <row Id="24962" PostHistoryTypeId="3" PostId="9146" RevisionGUID="9c567dd9-1308-4d04-b6d6-eceb4e88b771" CreationDate="2019-09-12T11:42:58.803" UserId="7925" Text="|mathematics|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24963" PostHistoryTypeId="2" PostId="9147" RevisionGUID="b51ec7a4-2e98-4001-9aab-aef6155a37d5" CreationDate="2019-09-12T13:40:43.507" UserId="10096" Text="Attach your camera to some pivot (in a transformation hierarchical sense). Rotate the pivot rather than the camera (do not use look at). It boils down to using $T_{pivot} R_{pivot}  T_{cam}  R_{cam}$. Where $T_{pivot}$ is a translation matrix derived from the position of the pivot in world space, $R_{pivot}$ is the rotation matrix of the pivot (what you want), $T_{cam}$ is a translation matrix derived from the position of the camera in the pivot's coord system, similarly for $R_{cam}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="24968" PostHistoryTypeId="2" PostId="9149" RevisionGUID="6b208462-048f-4f16-85e3-bd2c94b95298" CreationDate="2019-09-13T04:01:11.973" UserId="11136" Text="What you are asking about is 'mouse picking'. If a user clicks a pixel on the screen how can you get corresponding world space coordinates of an object being clicked on. &#xA;Imagine a ray from that pixel, through the view volume all the way to the far plane. That ray is a set of all possible points the user is clicking on. So we want to perform ray/poly ntersections with every object in the scene, and return the first intersect.&#xA;&#xA;To transform the pixel into world space, you first have to turn your x,y point in screen space into NDC coordinates (-1 to 1) use -1 for your Z component and 1 for W to create a 4 float component vector and then multiply that vector by the inverse projection and then inverse view matrices.&#xA;There are many examples of this process if you want to see code, but this is the basic process. &#xA;Now we have a ray from the camera/eye position into the scene, we want to do intersection tests with our objects. There are many ways of achieving this, take your pick.&#xA;&#xA;Hope this helps, good luck!" ContentLicense="CC BY-SA 4.0" />
  <row Id="24969" PostHistoryTypeId="2" PostId="9150" RevisionGUID="fcd17622-bca6-4c08-b22f-47cd9db20f1d" CreationDate="2019-09-13T07:40:43.110" UserId="11174" Text="The command,&#xD;&#xA;&#xD;&#xA;    fb-test -f 0&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;generates and displays a test pattern on the screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But, the command,&#xD;&#xA;&#xD;&#xA;    cp /home/root/test.jpg /dev/fb0&#xD;&#xA;&#xD;&#xA;copies test image into dev/fb0 file but fails to display anything on the screen?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How to resolve this issue?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24970" PostHistoryTypeId="1" PostId="9150" RevisionGUID="fcd17622-bca6-4c08-b22f-47cd9db20f1d" CreationDate="2019-09-13T07:40:43.110" UserId="11174" Text="Framebuffer not detecting image" ContentLicense="CC BY-SA 4.0" />
  <row Id="24971" PostHistoryTypeId="3" PostId="9150" RevisionGUID="fcd17622-bca6-4c08-b22f-47cd9db20f1d" CreationDate="2019-09-13T07:40:43.110" UserId="11174" Text="|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24972" PostHistoryTypeId="2" PostId="9151" RevisionGUID="3e0beb18-2d1c-44ae-b575-802dbccc06d9" CreationDate="2019-09-13T08:06:22.600" UserId="2041" Text="Copying the bytes of a JPEG file to the framebuffer device doesn't display the image represented by the JPEG file. The file needs to be decoded by an application that understands the JPEG format, to get the actual image. Your system is working normally. You can use a command like `display` to decode the file and draw the image to the screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="24973" PostHistoryTypeId="2" PostId="9152" RevisionGUID="103f2813-59c7-4c36-b07a-141b0c211a80" CreationDate="2019-09-13T19:21:35.273" UserId="9254" Text="I'm trying to understand the computation of the path density described in the book [Physically Based Rendering](http://www.pbr-book.org/3ed-2018/contents.html). They assume that a path $$x=(x_0,\ldots,x_{n-1})=(q_0,\ldots,q_{s-1},p_{t-1},\ldots,p_0)$$ with $s$ and $t$ vertices on the light and camera path, respectively, has been generated. Along with each vertex $x_i$ they store two densites $\overset{{}_{\rightarrow}} p(x_i)$ and $\overset{{}_{\leftarrow}} p(x_i)$. $\overset{{}_{\rightarrow}} p(x_i)$ is the &quot;forward&quot; density of $x_i$, which is probability per unit area of $x_i$ as generated by the path sampling algorithm. $\overset{{}_{\leftarrow}} p(x_i)$ is the hypothetical probability density of $x_i$ if the direction of light transport was reversed.&#xD;&#xA;&#xD;&#xA;Now let $p_i(x)$ denote the density of sampling the same path $x$ with the strategy $(i, j)$, $i + j = s + t$, instead (i.e. the strategy of considering $x_0,\ldots,x_{i-1}$ and $x_i,\ldots,x_{n-1}$ as being on the light and camera path, respectively). [They claim](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing.html#eq:path-density) that $$p_i(x)=\overset{{}_{\rightarrow}} p(x_0)\cdots\overset{{}_{\rightarrow}} p(x_{i-1})\overset{{}_{\leftarrow}} p(x_i)\cdots\overset{{}_{\leftarrow}} p(x_0)\tag1.$$&#xD;&#xA;&#xD;&#xA;&gt; I can't make sense of $(1)$. Even if we take $i=s$ (in which case the $(i, j) = (s, t)$ is the strategy being used for generating $x$), the formula doesn't make sense to me. Shouldn't $p_s(x)$ be the product of the densities of the light and camera subpaths? The density of the light subpath is clearly $\overset{{}_{\rightarrow}} p(x_0)\cdots\overset{{}_{\rightarrow}} p(x_{i-1})$, since the sampling startet at a light source at $x_0$ and all the densities on the way to $x_{i-1}$ are &quot;forward densities&quot;. On the other hand, the density of the camera subpath should be $\overset{{}_{\rightarrow}} p(p_0)\cdots\overset{{}_{\rightarrow}} p(p_{t-1})$, since from $x_{n-1}=p_0$ all the densities are forward densities as well. However, according to $(1)$ the density of the camera subpath is $\overset{{}_{\leftarrow}} p(p_{t-1})\cdots\overset{{}_{\leftarrow}} p(p_0)$. What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24974" PostHistoryTypeId="1" PostId="9152" RevisionGUID="103f2813-59c7-4c36-b07a-141b0c211a80" CreationDate="2019-09-13T19:21:35.273" UserId="9254" Text="Multiple Importance Sampling in Bidirectional Path Tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="24975" PostHistoryTypeId="3" PostId="9152" RevisionGUID="103f2813-59c7-4c36-b07a-141b0c211a80" CreationDate="2019-09-13T19:21:35.273" UserId="9254" Text="|raytracing|rendering|pathtracing|pbr|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24977" PostHistoryTypeId="5" PostId="9152" RevisionGUID="e6bf167d-d0a8-47e3-9617-d5d0e4fd1bd3" CreationDate="2019-09-14T04:25:27.107" UserId="9254" Comment="added 4 characters in body" Text="I'm trying to understand the computation of the path density described in the book [Physically Based Rendering](http://www.pbr-book.org/3ed-2018/contents.html). They assume that a path $$x=(x_0,\ldots,x_{n-1})=(q_0,\ldots,q_{s-1},p_{t-1},\ldots,p_0)$$ with $s$ and $t$ vertices on the light and camera path, respectively, has been generated. Along with each vertex $x_i$ they store two densites $\overset{{}_{\rightarrow}} p(x_i)$ and $\overset{{}_{\leftarrow}} p(x_i)$. $\overset{{}_{\rightarrow}} p(x_i)$ is the &quot;forward&quot; density of $x_i$, which is probability per unit area of $x_i$ as generated by the path sampling algorithm. $\overset{{}_{\leftarrow}} p(x_i)$ is the hypothetical probability density of $x_i$ if the direction of light transport was reversed.&#xD;&#xA;&#xD;&#xA;Now let $p_i(x)$ denote the density of sampling the same path $x$ with the strategy $(i, j)$, $i + j = s + t$, instead (i.e. the strategy of considering $x_0,\ldots,x_{i-1}$ and $x_i,\ldots,x_{n-1}$ as being on the light and camera path, respectively). [They claim](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing.html#eq:path-density) that $$p_i(x)=\overset{{}_{\rightarrow}} p(x_0)\cdots\overset{{}_{\rightarrow}} p(x_{i-1})\overset{{}_{\leftarrow}} p(x_i)\cdots\overset{{}_{\leftarrow}} p(x_{n-1})\tag1.$$&#xD;&#xA;&#xD;&#xA;&gt; I can't make sense of $(1)$. Even if we take $i=s$ (in which case the $(i, j) = (s, t)$ is the strategy being used for generating $x$), the formula doesn't make sense to me. Shouldn't $p_s(x)$ be the product of the densities of the light and camera subpaths? The density of the light subpath is clearly $\overset{{}_{\rightarrow}} p(x_0)\cdots\overset{{}_{\rightarrow}} p(x_{i-1})$, since the sampling startet at a light source at $x_0$ and all the densities on the way to $x_{i-1}$ are &quot;forward densities&quot;. On the other hand, the density of the camera subpath should be $\overset{{}_{\rightarrow}} p(p_0)\cdots\overset{{}_{\rightarrow}} p(p_{t-1})$, since from $x_{n-1}=p_0$ all the densities are forward densities as well. However, according to $(1)$ the density of the camera subpath is $\overset{{}_{\leftarrow}} p(p_{t-1})\cdots\overset{{}_{\leftarrow}} p(p_0)$. What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24978" PostHistoryTypeId="4" PostId="7809" RevisionGUID="d7dbdeae-bcf6-4e86-a3b7-e1c758fa6fe1" CreationDate="2019-09-14T11:43:26.843" UserId="7553" Comment="corrected grammar in the title" Text="What does GPU assembly look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24979" PostHistoryTypeId="24" PostId="7809" RevisionGUID="d7dbdeae-bcf6-4e86-a3b7-e1c758fa6fe1" CreationDate="2019-09-14T11:43:26.843" Comment="Proposed by 7553 approved by 209, 6 edit id of 488" ContentLicense="CC BY-SA 4.0" />
  <row Id="24980" PostHistoryTypeId="5" PostId="2062" RevisionGUID="9974cfe2-a3b8-41b1-85f4-0a4426257248" CreationDate="2019-09-14T23:49:50.660" UserId="48" Comment="fix broken link to msdn" Text="In DX12, there is no implicit driver-implemented SLI as there was in DX11. Instead, multiple GPUs are exposed to the application as separate &quot;nodes&quot; within a single DX12 device, and each VRAM resource lives on a single node, specified at creation time. There is no implicit mirroring of resources to both GPUs as in DX11 SLI.&#xD;&#xA;&#xD;&#xA;So, the game engine or application has full control and responsibility over how data and work are distributed between the GPUs. It's up to the app developers to implement patterns like alternating frames between GPUs, or splitting the frame across GPUs, if they wish. For example, to implement alternating frames, the app would have to allocate all buffers, textures, render targets etc. on both GPUs and populate both of them. Then, when rendering a frame, it would generate a command list for the current GPU using its local copies of all resources. Any inter-GPU transfers needed (for temporal effects, for instance) would also be the app's responsibility.&#xD;&#xA;&#xD;&#xA;More information on this topic can be found on [this MSDN article on DX12 multi-GPU support](https://docs.microsoft.com/en-us/windows/win32/direct3d12/multi-engine)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24981" PostHistoryTypeId="2" PostId="9153" RevisionGUID="a94874c2-e553-411a-81ee-219ca3eeb3a6" CreationDate="2019-09-15T00:27:34.230" UserId="11180" Text="The Dolphin emulator for GameCube/Wii has the ability to use the [ARB_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_buffer_storage.txt) (or [EXT_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_buffer_storage.txt) for GLES) to improve rendering performance.&#xD;&#xA;&#xD;&#xA;From the extension's description, a GPU driver implementation provides a means to allocate storage that can be marked as immutable (constant). What is required of the driver implementation for this to actually be useful? At one extreme, a naive implementation could allocate such constant memory buffers exactly the same way it allocates typical global memory buffers, functionally correct but not beneficial for performance.&#xD;&#xA;&#xD;&#xA;At least one user has suggested buffer_storage only matters in the case of discrete GPUs which carry their own dedicated RAM storage. I presume that by marking the buffers as immutable the driver can avoid unnecessary transfers to keep coherence between system memory and GPU memory.&#xD;&#xA;&#xD;&#xA;On the other hand, the Dolphin team continually requested buffer_storage for Mali's driver over the years, which suggests there is a performance improvement even in SoCs with integrated graphics and no dedicated GPU DRAM. If so, is the benefit at all comparable and how does the driver achieve it?&#xD;&#xA;&#xD;&#xA;Does Vulkan have an equivalent or somehow avoid the need for such an extension?&#xD;&#xA;&#xD;&#xA;The intent here is to understand the value in implementing EXT_buffer_storage in the driver for Broadcom's VideoCore VI.&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[1]&lt;/sup&gt; [&quot;Dolphin on the pi 4&quot;](https://forums.dolphin-emu.org/Thread-dolphin-on-the-pi-4?page=14)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[2]&lt;/sup&gt; [&quot;Will there be EXT_buffer_storage at all?&quot;](https://community.arm.com/developer/tools-software/graphics/f/discussions/9902/will-there-be-ext_buffer_storage-support-at-all)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[3]&lt;/sup&gt; [&quot;EXT_buffer_storage is now supported by ARM&quot;](https://forums.dolphin-emu.org/Thread-ext-buffer-storage-is-now-supported-by-arm)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[4]&lt;/sup&gt; [&quot;&#xD;&#xA;Possible to add GLES EXT_buffer_storage driver support to Videocore VI on the Pi4?&quot;](https://www.raspberrypi.org/forums/viewtopic.php?t=249636)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24982" PostHistoryTypeId="1" PostId="9153" RevisionGUID="a94874c2-e553-411a-81ee-219ca3eeb3a6" CreationDate="2019-09-15T00:27:34.230" UserId="11180" Text="In what scenarios and how does GL_ARB_buffer_storage help performance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="24983" PostHistoryTypeId="3" PostId="9153" RevisionGUID="a94874c2-e553-411a-81ee-219ca3eeb3a6" CreationDate="2019-09-15T00:27:34.230" UserId="11180" Text="|opengl|memory|buffers|driver|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24984" PostHistoryTypeId="5" PostId="9153" RevisionGUID="bc2a7e67-e873-437c-8d38-006d3390d587" CreationDate="2019-09-15T14:40:47.717" UserId="11180" Comment="deleted 10 characters in body" Text="The Dolphin emulator for GameCube/Wii has the ability to use the [ARB_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_buffer_storage.txt) (or [EXT_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_buffer_storage.txt) for GLES) to improve rendering performance.&#xD;&#xA;&#xD;&#xA;From the extension's description, a GPU driver implementation provides a means to allocate storage that can be marked as immutable. What is required of the driver implementation for this to actually be useful? At one extreme, a naive implementation could allocate such immutable memory buffers exactly the same way it allocates typical global memory buffers, functionally correct but not beneficial for performance.&#xD;&#xA;&#xD;&#xA;At least one user has suggested buffer_storage only matters in the case of discrete GPUs which carry their own dedicated RAM storage. I presume that by marking the buffers as immutable the driver can avoid unnecessary transfers to keep coherence between system memory and GPU memory.&#xD;&#xA;&#xD;&#xA;On the other hand, the Dolphin team continually requested buffer_storage for Mali's driver over the years, which suggests there is a performance improvement even in SoCs with integrated graphics and no dedicated GPU DRAM. If so, is the benefit at all comparable and how does the driver achieve it?&#xD;&#xA;&#xD;&#xA;Does Vulkan have an equivalent or somehow avoid the need for such an extension?&#xD;&#xA;&#xD;&#xA;The intent here is to understand the value in implementing EXT_buffer_storage in the driver for Broadcom's VideoCore VI.&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[1]&lt;/sup&gt; [&quot;Dolphin on the pi 4&quot;](https://forums.dolphin-emu.org/Thread-dolphin-on-the-pi-4?page=14)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[2]&lt;/sup&gt; [&quot;Will there be EXT_buffer_storage at all?&quot;](https://community.arm.com/developer/tools-software/graphics/f/discussions/9902/will-there-be-ext_buffer_storage-support-at-all)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[3]&lt;/sup&gt; [&quot;EXT_buffer_storage is now supported by ARM&quot;](https://forums.dolphin-emu.org/Thread-ext-buffer-storage-is-now-supported-by-arm)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[4]&lt;/sup&gt; [&quot;&#xD;&#xA;Possible to add GLES EXT_buffer_storage driver support to Videocore VI on the Pi4?&quot;](https://www.raspberrypi.org/forums/viewtopic.php?t=249636)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24985" PostHistoryTypeId="5" PostId="9153" RevisionGUID="b8d9ce8f-d3e7-47cc-b66b-bf19c6febd0a" CreationDate="2019-09-15T14:49:13.433" UserId="11180" Comment="deleted 41 characters in body; deleted 5 characters in body" Text="The Dolphin emulator for GameCube/Wii has the ability to use the [ARB_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_buffer_storage.txt) (or [EXT_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_buffer_storage.txt) for GLES) to improve rendering performance.&#xD;&#xA;&#xD;&#xA;From the extension's description, a GPU driver implementation provides a means to allocate storage that can be marked as immutable, i.e. cannot be deallocated or resized while in use. What is required of the driver implementation for this to actually be useful? At one extreme, a naive implementation could allocate such immutable memory buffers exactly the same way it allocates typical global memory buffers, functionally correct but not beneficial for performance.&#xD;&#xA;&#xD;&#xA;At least one user has suggested buffer_storage only matters in the case of discrete GPUs which carry their own dedicated RAM storage. I presume that by marking the buffers as immutable.&#xD;&#xA;&#xD;&#xA;On the other hand, the Dolphin team continually requested buffer_storage for Mali's driver over the years, which suggests there is a performance improvement even in SoCs with integrated graphics and no dedicated GPU DRAM. If so, is the benefit at all comparable and how does the driver achieve it?&#xD;&#xA;&#xD;&#xA;Does Vulkan have an equivalent or somehow avoid the need for such an extension?&#xD;&#xA;&#xD;&#xA;The intent here is to understand the value in implementing EXT_buffer_storage in the driver for Broadcom's VideoCore VI.&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[1]&lt;/sup&gt; [&quot;Dolphin on the pi 4&quot;](https://forums.dolphin-emu.org/Thread-dolphin-on-the-pi-4?page=14)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[2]&lt;/sup&gt; [&quot;Will there be EXT_buffer_storage at all?&quot;](https://community.arm.com/developer/tools-software/graphics/f/discussions/9902/will-there-be-ext_buffer_storage-support-at-all)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[3]&lt;/sup&gt; [&quot;EXT_buffer_storage is now supported by ARM&quot;](https://forums.dolphin-emu.org/Thread-ext-buffer-storage-is-now-supported-by-arm)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[4]&lt;/sup&gt; [&quot;&#xD;&#xA;Possible to add GLES EXT_buffer_storage driver support to Videocore VI on the Pi4?&quot;](https://www.raspberrypi.org/forums/viewtopic.php?t=249636)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24986" PostHistoryTypeId="5" PostId="9153" RevisionGUID="c4011017-7e5c-4873-960d-0b3295cc90f8" CreationDate="2019-09-15T14:54:45.770" UserId="11180" Comment="deleted 52 characters in body; deleted 5 characters in body" Text="The Dolphin emulator for GameCube/Wii has the ability to use the [ARB_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_buffer_storage.txt) (or [EXT_buffer_storage](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_buffer_storage.txt) for GLES) to improve rendering performance.&#xD;&#xA;&#xD;&#xA;From the extension's description, a GPU driver implementation provides a means to allocate storage that can be marked as immutable, i.e. cannot be deallocated or resized while in use. What is required of the driver implementation for this to actually be useful? At one extreme, a naive implementation could allocate immutable memory buffers exactly the same way it allocates typical global memory buffers, functionally correct but not beneficial for performance.&#xD;&#xA;&#xD;&#xA;At least one user has suggested buffer_storage only matters in the case of discrete GPUs which carry their own dedicated RAM storage.&#xD;&#xA;&#xD;&#xA;On the other hand, the Dolphin team continually requested buffer_storage for Mali's driver over the years, which suggests there is a performance improvement even in SoCs with integrated graphics and no dedicated GPU DRAM. If so, is the benefit at all comparable and how does the driver achieve it?&#xD;&#xA;&#xD;&#xA;Does Vulkan have an equivalent or somehow avoid the need for such an extension?&#xD;&#xA;&#xD;&#xA;The intent here is to understand the value in implementing EXT_buffer_storage in the driver for Broadcom's VideoCore VI.&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[1]&lt;/sup&gt; [&quot;Dolphin on the pi 4&quot;](https://forums.dolphin-emu.org/Thread-dolphin-on-the-pi-4?page=14)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[2]&lt;/sup&gt; [&quot;Will there be EXT_buffer_storage at all?&quot;](https://community.arm.com/developer/tools-software/graphics/f/discussions/9902/will-there-be-ext_buffer_storage-support-at-all)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[3]&lt;/sup&gt; [&quot;EXT_buffer_storage is now supported by ARM&quot;](https://forums.dolphin-emu.org/Thread-ext-buffer-storage-is-now-supported-by-arm)&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;[4]&lt;/sup&gt; [&quot;&#xD;&#xA;Possible to add GLES EXT_buffer_storage driver support to Videocore VI on the Pi4?&quot;](https://www.raspberrypi.org/forums/viewtopic.php?t=249636)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24987" PostHistoryTypeId="2" PostId="9154" RevisionGUID="60357468-b73b-4be4-9c56-aa439e48fcbb" CreationDate="2019-09-15T15:09:58.560" UserId="8757" Text="For my application, I want to render models and have edges that are bent &quot;outwards&quot; to have a solid line and those who are bent &quot;inwards&quot; to have a dotted line.&#xD;&#xA;&#xD;&#xA;For this, I need to calculate the angle between two connected triangles.&#xD;&#xA;How can I calculate this angle? How can I define if it is bent outwards or inwards (looking from the top it would always bend downwards if the angle is &gt;180 and inwards (so up) if the angle is &lt;180, but how can i calculate this?&#xD;&#xA;&#xD;&#xA;Thank you for your help in advance.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24988" PostHistoryTypeId="1" PostId="9154" RevisionGUID="60357468-b73b-4be4-9c56-aa439e48fcbb" CreationDate="2019-09-15T15:09:58.560" UserId="8757" Text="Calculating the angle between two polygons" ContentLicense="CC BY-SA 4.0" />
  <row Id="24989" PostHistoryTypeId="3" PostId="9154" RevisionGUID="60357468-b73b-4be4-9c56-aa439e48fcbb" CreationDate="2019-09-15T15:09:58.560" UserId="8757" Text="|3d|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24990" PostHistoryTypeId="2" PostId="9155" RevisionGUID="47dd9827-a4da-4da7-9557-a96bfface356" CreationDate="2019-09-15T15:19:33.280" UserId="2654" Text="The marquee feature of buffer storage is not immutability of the allocation itself, but instead is a feature you couldn't have without immutable allocation: persistent mapped buffers.&#xD;&#xA;&#xD;&#xA;Pre-buffer_storage, you could not use a buffer while it was mapped. This is done to allow implementations the freedom to play games with mapping behind your back. For example, it's legal for `glMapBufferRange` to not actually return a mapped pointer; it could just return some CPU-accessible memory which, at unmap time, will get copied into the actual buffer. To permit such freedoms, mapping and unmapping a buffer is something you have to do semi-frequently.&#xD;&#xA;&#xD;&#xA;Furthermore, pre-buffer_storage, it is 100% legal to call `glBufferData` (note the lack of `Sub`) on that buffer again. This will cause the old data storage to be discarded and new storage allocated. So you couldn't keep a buffer mapped if you tried to reallocate its storage.&#xD;&#xA;&#xD;&#xA;Also, implementations couldn't really know where to allocate storage for GPUs with multiple kinds of memory, so they would tend to move the buffer's allocation around based on how you use it. If you frequently upload to it, they'll eventually put it into CPU accessible memory to speed up such operations. And so forth. But this is all done after allocating storage, and it's done based on how you use the buffer. So having the buffer be mapped would prevent such shuffling around of data.&#xD;&#xA;&#xD;&#xA;Making a buffer's storage immutable solves these problems. You cannot reallocate an immutable buffer's storage, so there's no problem with keeping it mapped forever. `glBufferStorage` takes usage flags which unlike `glBufferData`'s hints, explicitly *forbid* you from using the memory in certain ways. So the implementation knows exactly where to put the storage and will not need to move it around after the fact. So there's no problem with persistently mapped storage.&#xD;&#xA;&#xD;&#xA;And I imagine that, for a console emulator, having persistently mapped storage would be very useful. After all, programs written for such consoles touch memory directly at any time, the same memory that the GPU can address. So storing it in a buffer and keeping that memory mapped all the time probably works out better than uploading pieces of it, or trying to figure out which pieces should be uploaded, or whatever." ContentLicense="CC BY-SA 4.0" />
  <row Id="24991" PostHistoryTypeId="5" PostId="9154" RevisionGUID="44a773e9-425b-49cd-ae94-7ba939a396bb" CreationDate="2019-09-15T16:11:36.013" UserId="6" Comment="added 130 characters in body" Text="For my application, I want to render models as polygonal surfaces in 3D space and have edges that are bent &quot;outwards&quot; to have a solid line and those who are bent &quot;inwards&quot; to have a dotted line. So if I look from the top of the edge if they &quot;bend towards me&quot; they are bending inwards, if they bend away from me, they bend outwards.&#xD;&#xA;&#xD;&#xA;For this, I need to calculate the angle between two connected triangles.&#xD;&#xA;How can I calculate this angle? How can I define if it is bent outwards or inwards (looking from the top it would always bend downwards if the angle is &gt;180 and inwards (so up) if the angle is &lt;180, but how can I calculate this?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="24993" PostHistoryTypeId="2" PostId="9157" RevisionGUID="6336043a-2a02-4eee-a338-2663890046b8" CreationDate="2019-09-15T18:32:32.730" UserId="10590" Text="I am currently building a ray tracer and I came across a problem and a confusion regarding the light calculations. For lighting I am using the following Mathematical model: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Where Ka is the ambient color component, Ke is the emission color component. and The summation calculates the phong and lambert components using Specular and diffusion. The summation is over all the lights where Li is the lightColor and Vi is a binary variable that eliminates the lambert and phong components for the sake of producing the shadowing effet. On the other hand the Ks is the specular component and Ir is the reflective color that is calculated recursively by producing a new ray and tracing this ray. All the Color components are represented by a 3D vector that stores the R, G, B colors and they take a value from 0 to 1. Now my question is The model sums up all the color values which can end up producing values that are greater than and in a way overflowing the maximum value for the color channel. In my ray tracer implementation this was not a problem for all the terms highlighted in white because for all the scenes I produced non of them actually faced the problem where the sum of the colors where greater than zero. Now my attention was brought to this problem when I added the term highlighted in green which is the reflection term. I tried different things like setting the value of the color channel to 1 when it is going to overflow and taking the modulus or even setting it to zeros. All my solutions produce reflections but the reflections are not smooth and has a lot of noise in them which I cant seem to eliminate. I searched online for this issue but I did not find a lot of details. What would be a good solution for handling the possibility of the final color overflowing in one or more channel?&#xD;&#xA;&#xD;&#xA;Note: my implementation works fine without reflection which makes me believe that the color implementation is correct. &#xD;&#xA;&#xD;&#xA;One of my sample Output &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Instead the desired output should be &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MzLVB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/67GBz.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Jvbrd.png&#xD;&#xA;&#xD;&#xA;please ignore the size and aspect ratio differences of the two images" ContentLicense="CC BY-SA 4.0" />
  <row Id="24994" PostHistoryTypeId="1" PostId="9157" RevisionGUID="6336043a-2a02-4eee-a338-2663890046b8" CreationDate="2019-09-15T18:32:32.730" UserId="10590" Text="Color shading and light calculation for ray tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="24995" PostHistoryTypeId="3" PostId="9157" RevisionGUID="6336043a-2a02-4eee-a338-2663890046b8" CreationDate="2019-09-15T18:32:32.730" UserId="10590" Text="|raytracing|lighting|shading|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="24997" PostHistoryTypeId="5" PostId="9155" RevisionGUID="340143ea-dbf1-4111-801b-42567de3ea43" CreationDate="2019-09-15T21:08:38.323" UserId="2654" Comment="added 88 characters in body" Text="The marquee feature of buffer storage is not immutability of the allocation itself, but instead is a feature you couldn't have without immutable allocation: [persistently mapped buffers][1].&#xD;&#xA;&#xD;&#xA;Pre-buffer_storage, you could not use a buffer while it was mapped. This is done to allow implementations the freedom to play games with mapping behind your back. For example, it's legal for `glMapBufferRange` to not actually return a mapped pointer; it could just return some CPU-accessible memory which, at unmap time, will get copied into the actual buffer. To permit such freedoms, mapping and unmapping a buffer is something you have to do semi-frequently.&#xD;&#xA;&#xD;&#xA;Furthermore, pre-buffer_storage, it is 100% legal to call `glBufferData` (note the lack of `Sub`) on that buffer again. This will cause the old data storage to be discarded and new storage allocated. So you couldn't keep a buffer mapped if you tried to reallocate its storage.&#xD;&#xA;&#xD;&#xA;Also, implementations couldn't really know where to allocate storage for GPUs with multiple kinds of memory, so they would tend to move the buffer's allocation around based on how you use it. If you frequently upload to it, they'll eventually put it into CPU accessible memory to speed up such operations. And so forth. But this is all done after allocating storage, and it's done based on how you use the buffer. So having the buffer be mapped would prevent such shuffling around of data.&#xD;&#xA;&#xD;&#xA;Making a buffer's storage immutable solves these problems. You cannot reallocate an immutable buffer's storage, so there's no problem with keeping it mapped forever. `glBufferStorage` takes usage flags which unlike `glBufferData`'s hints, explicitly *forbid* you from using the memory in certain ways. So the implementation knows exactly where to put the storage and will not need to move it around after the fact. So there's no problem with persistently mapped storage.&#xD;&#xA;&#xD;&#xA;And I imagine that, for a console emulator, having persistently mapped storage would be very useful. After all, programs written for such consoles touch memory directly at any time, the same memory that the GPU can address. So storing it in a buffer and keeping that memory mapped all the time probably works out better than uploading pieces of it, or trying to figure out which pieces should be uploaded, or whatever.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object#Persistent_mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="24998" PostHistoryTypeId="2" PostId="9158" RevisionGUID="f08336f0-3d83-4433-8001-d2c8c1f5387c" CreationDate="2019-09-16T09:54:45.887" UserId="11189" Text="What is the difference between aliasing, sampling and processing?  &#xD;&#xA;How do post-/pre-**aliasing** relate to post-/pre-**processing** and post-/pre-**sampling**?  &#xD;&#xA;&#xD;&#xA;On many websites/articles these terms are often used &#xD;&#xA;without clearly stating the differences. &#xD;&#xA;Some even use them interchangeable, all tough they&#xD;&#xA;seem to have different meanings.&#xD;&#xA;It would be very helpfull mentioning where in the &#xD;&#xA;**graphics-pipeline** these steps happen &#xD;&#xA;(e.g. before/while/after rasterization, etc.)." ContentLicense="CC BY-SA 4.0" />
  <row Id="24999" PostHistoryTypeId="1" PostId="9158" RevisionGUID="f08336f0-3d83-4433-8001-d2c8c1f5387c" CreationDate="2019-09-16T09:54:45.887" UserId="11189" Text="What is the difference between aliasing, sampling and processing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25000" PostHistoryTypeId="3" PostId="9158" RevisionGUID="f08336f0-3d83-4433-8001-d2c8c1f5387c" CreationDate="2019-09-16T09:54:45.887" UserId="11189" Text="|sampling|antialiasing|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25001" PostHistoryTypeId="2" PostId="9159" RevisionGUID="d8fd4378-7060-47f9-84ff-90e34d210604" CreationDate="2019-09-16T11:44:07.527" UserId="11191" Text="I am new to OpenGL and I am trying to code un optic flow with dots appearing from the background and moving towards the viewer. As a consequence of a perspective projection, the dots are faster and bigger when they move towards the viewer, but they are smaller and slower when they are farther away from the viewer. &#xD;&#xA;&#xD;&#xA;As a result of OpenGL perspective projection, I got the dots moving faster when approaching the viewer, but their size does not change with the distance. Isn't the change of size a consequence of the projection -- just as the change of speed? If not, shall I compute it separately?&#xD;&#xA;&#xD;&#xA;Thanks in advance for your help![![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hMcPH.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="25002" PostHistoryTypeId="1" PostId="9159" RevisionGUID="d8fd4378-7060-47f9-84ff-90e34d210604" CreationDate="2019-09-16T11:44:07.527" UserId="11191" Text="Change of speed but no change of size after OpenGL Perspective Projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="25003" PostHistoryTypeId="3" PostId="9159" RevisionGUID="d8fd4378-7060-47f9-84ff-90e34d210604" CreationDate="2019-09-16T11:44:07.527" UserId="11191" Text="|opengl|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25004" PostHistoryTypeId="5" PostId="9158" RevisionGUID="a93de912-f1a9-4f92-930d-3c22180fbda2" CreationDate="2019-09-16T12:53:21.347" UserId="11189" Comment="added 171 characters in body; edited tags; edited title" Text="What is the difference between post-/pre- sampling, aliasing, filtering and processing?  &#xD;&#xA;How do the terms post-/pre-**aliasing**, post-/pre-**processing**, post-/pre-**sampling** and post-/pre-**filtering** relate to each other?  &#xD;&#xA;&#xD;&#xA;On many websites/articles these terms are often used &#xD;&#xA;without clearly stating the differences. &#xD;&#xA;Some even use them interchangeable, all tough they&#xD;&#xA;seem to have different meanings.&#xD;&#xA;&#xD;&#xA;It would be very helpfull mentioning where in the &#xD;&#xA;**graphics-pipeline** these steps happen &#xD;&#xA;(e.g. before/while/after rasterization, etc.),&#xD;&#xA;and what the refence points for the name suffixes are  &#xD;&#xA;(pre … before what?, post … after what?)." ContentLicense="CC BY-SA 4.0" />
  <row Id="25005" PostHistoryTypeId="4" PostId="9158" RevisionGUID="a93de912-f1a9-4f92-930d-3c22180fbda2" CreationDate="2019-09-16T12:53:21.347" UserId="11189" Comment="added 171 characters in body; edited tags; edited title" Text="What is the difference between post-/pre- sampling, aliasing, filtering and processing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25006" PostHistoryTypeId="6" PostId="9158" RevisionGUID="a93de912-f1a9-4f92-930d-3c22180fbda2" CreationDate="2019-09-16T12:53:21.347" UserId="11189" Comment="added 171 characters in body; edited tags; edited title" Text="|sampling|antialiasing|filtering|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25007" PostHistoryTypeId="2" PostId="9160" RevisionGUID="61f954c9-a1c2-402d-a0d0-3d8d661918ee" CreationDate="2019-09-16T13:32:59.430" UserId="2041" Text="When you draw a point with `GL_POINTS`, it's not a 3D object with a size in world-space: its size is a fixed number of pixels. Because of that, the size of the point is independent of the distance from the camera.&#xD;&#xA;&#xD;&#xA;If you want to draw dots whose size depends on distance, you either need to compute the perspective yourself and change the point size for each point (not recommended, because state changes like that are expensive); or use another method to draw them. For instance, you might draw a quad and use the fragment shader to make it a circle (e.g. by discarding the fragment if the world co-ordinate was more than a particular distance from the centre of the quad, or by using a transparent texture with a circle in it)." ContentLicense="CC BY-SA 4.0" />
  <row Id="25010" PostHistoryTypeId="2" PostId="9162" RevisionGUID="39deef8f-1548-40d5-8fbf-46fc2c40e77f" CreationDate="2019-09-16T15:08:25.950" UserId="8009" Text="I suggest computing the normal vector for each polygon and compute the angle between the normal vectors.&#xD;&#xA;&#xD;&#xA;See the following illustration, where the red arrows are the normal vectors. (Ignore the blue part. I just found the image [here][1] - and it was suitable enough.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;![this image](https://i.stack.imgur.com/NNxNR.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If your polygons are planar, then you can compute the normal for any polygon ABC by computing the cross product `AB x AC`.&#xD;&#xA;&#xD;&#xA;You then compute the cosine of the angle between the two normal vectors (the two red arrows:  call them `u` and `v`) by taking their dot product, then dividing by their magnitudes.&#xD;&#xA;&#xD;&#xA;![Angle between vectors](https://www.analyzemath.com/stepbystep_mathworksheets/3D_vectors/angle_vectors.png)&#xD;&#xA;&#xD;&#xA;_Image taken from [here][2]._&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/a/67019/111323&#xD;&#xA;  [2]: https://www.analyzemath.com/stepbystep_mathworksheets/vectors/vector3D_angle.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="25011" PostHistoryTypeId="5" PostId="9162" RevisionGUID="c0c3a956-7822-444c-b93c-07ff6e91bf22" CreationDate="2019-09-16T18:18:11.340" UserId="8009" Comment="Missed a critical step in the process.  Oops." Text="I suggest computing the normal vector for each polygon and compute the angle between the normal vector of one triangle and the normal vector of a plane perpendicular to the other surface that passes through the common edge.&#xD;&#xA;&#xD;&#xA;See the following illustration, where the red arrows are the normal vectors of the red polygons. The blue vector is the plane perpendicular to the left polygon that passes through the edge common to both polygons.&#xD;&#xA;&#xD;&#xA;![this image](https://i.stack.imgur.com/NNxNR.png)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If your polygons are planar, then you can compute the normal for any polygon ABC by computing the cross product `AB x AC`.&#xD;&#xA;&#xD;&#xA;To obtain the blue vector, take the cross product of the normal of the left polygon and the vector that is the common edge.&#xD;&#xA;&#xD;&#xA;The angle you're looking for is formed between this blue vector and the normal to the other polygon (the red vector on the right in the diagram).&#xD;&#xA;&#xD;&#xA;You then compute the cosine of the angle between two vectors `u` and `v` by taking their dot product, then dividing by their magnitudes.&#xD;&#xA;&#xD;&#xA;![Angle between vectors](https://www.analyzemath.com/stepbystep_mathworksheets/3D_vectors/angle_vectors.png)&#xD;&#xA;&#xD;&#xA;_Image taken from [here][2]._&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/a/67019/111323&#xD;&#xA;  [2]: https://www.analyzemath.com/stepbystep_mathworksheets/vectors/vector3D_angle.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="25012" PostHistoryTypeId="2" PostId="9163" RevisionGUID="404eaadf-9ec6-4a78-80e9-3fb5f3860e99" CreationDate="2019-09-17T07:59:59.187" UserId="6378" Text="I was wondering if there are any techniques for calculating the intersection point/s between two or more distance fields." ContentLicense="CC BY-SA 4.0" />
  <row Id="25013" PostHistoryTypeId="1" PostId="9163" RevisionGUID="404eaadf-9ec6-4a78-80e9-3fb5f3860e99" CreationDate="2019-09-17T07:59:59.187" UserId="6378" Text="SDF collision detection" ContentLicense="CC BY-SA 4.0" />
  <row Id="25014" PostHistoryTypeId="3" PostId="9163" RevisionGUID="404eaadf-9ec6-4a78-80e9-3fb5f3860e99" CreationDate="2019-09-17T07:59:59.187" UserId="6378" Text="|mathematics|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25019" PostHistoryTypeId="2" PostId="9165" RevisionGUID="a4ca9c68-65b0-4c0c-86f3-803f0bce5e8d" CreationDate="2019-09-18T03:46:50.880" UserId="11204" Text="Sometimes FX studios will use projection painting. The technique basically tracks the footage onto basic geometry and use different frames for different areas of the scene(an actor may be in front of a section of the background, but isn't in another frame.)&#xD;&#xA;&#xD;&#xA;CGMatter has a great tutorial on it: https://www.youtube.com/watch?v=gz4qV5_zuMo&amp;t=202s" ContentLicense="CC BY-SA 4.0" />
  <row Id="25020" PostHistoryTypeId="2" PostId="9166" RevisionGUID="f580d300-5fa7-4c9a-8f32-3168a2592115" CreationDate="2019-09-18T04:21:40.040" UserId="3003" Text="While you can't do what you're asking, you might be able to use a compromise. It turns out that all human skin tones have the same hue. They vary only in saturation and brightness. You can see this on the scopes that television engineers use to calibrate their signals. There's a line where skin tones should be if everything's set correctly. &#xD;&#xA;&#xD;&#xA;You could choose that hue and some low saturation and middle value in HSV space, then convert it to RGB and use that as the color you put in the ROI. &#xD;&#xA;&#xD;&#xA;It looks like on most vectorscopes the skin tone line is about 15° past red towards yellow. According to [this article on skin tone correction](https://larryjordan.com/articles/color-correction-make-people-look-normal/) if the lighting is typical studio lighting, caucasian skin would usually be around 50-75% brightness, asian and hispanic skin around 35-55% brightness and african skin around 15-50% brightness. So setting your color to HSV = (15°, 25% saturation, 50% brightness) is RGB = (128, 104, 96). If you know your subjects will be lighter or darker, adjust accordingly. Note that these values change when in bright outdoor light or dim indoor light, or when there's light with a strong color cast falling on them. But again, this is a compromise." ContentLicense="CC BY-SA 4.0" />
  <row Id="25024" PostHistoryTypeId="2" PostId="9168" RevisionGUID="5a91e1b9-8d6c-473c-8adb-341c3affb44f" CreationDate="2019-09-19T00:46:47.057" UserId="11208" Text="[![Composition of HSV][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a question about the saturation channel.&#xD;&#xA;1.) So far I know, that saturation channel only give intensity to Hue channel, but I do not understand, how saturation channel can be dark and what is the saturation value to be in saturation channel dark?.&#xD;&#xA;&#xD;&#xA;If I am not mistaken the range of value channel is from 0 to 100. 0 is black and 100 is white.&#xD;&#xA;so I am trying to use [online HSV simulator][2] to figure it out what color can be produced after mixing each channel.&#xD;&#xA;&#xD;&#xA;But I still searching the value for the black and white color in saturation channel so I can correct answer for each color on each box (a-d).&#xD;&#xA;&#xD;&#xA;And how saturation channel can be dark if, the value channel has a value of 100 (based on onlie HSV simulator, H = 0-360, V = 100, S = ? )?&#xD;&#xA;sofar my answer is :&#xD;&#xA;a. hell white without saturation.&#xD;&#xA;b. dark gray with little saturation.&#xD;&#xA;c. half gray.&#xD;&#xA;d. dark black with low saturation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;is there any exact value for black and white in saturation channel?.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hXjgh.jpg&#xD;&#xA;  [2]: http://colorizer.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25025" PostHistoryTypeId="1" PostId="9168" RevisionGUID="5a91e1b9-8d6c-473c-8adb-341c3affb44f" CreationDate="2019-09-19T00:46:47.057" UserId="11208" Text="HSV Channel - Mixing HSV Channel" ContentLicense="CC BY-SA 4.0" />
  <row Id="25026" PostHistoryTypeId="3" PostId="9168" RevisionGUID="5a91e1b9-8d6c-473c-8adb-341c3affb44f" CreationDate="2019-09-19T00:46:47.057" UserId="11208" Text="|rendering|color|image|color-separation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25027" PostHistoryTypeId="5" PostId="9168" RevisionGUID="44aa5410-3344-4622-ad6b-922711908300" CreationDate="2019-09-19T00:52:11.863" UserId="11208" Comment="added 2 characters in body" Text="[![Composition of HSV][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a question about the saturation channel.&#xD;&#xA;1.) So far I know, that saturation channel only give intensity to Hue channel, but I do not understand, how saturation channel can be dark and what is the saturation value to be in saturation channel dark?.&#xD;&#xA;&#xD;&#xA;If I am not mistaken the range of value channel is from 0 to 100. 0 is black and 100 is white.&#xD;&#xA;so I am trying to use [online HSV simulator][2] to figure it out what color can be produced after mixing each channel.&#xD;&#xA;&#xD;&#xA;But I still searching the value for the black and white color in saturation channel so I can correct answer for each color on each box (a-d).&#xD;&#xA;&#xD;&#xA;And how saturation channel can be dark if, the value channel has a value of 100 (based on onlie HSV simulator, H = 0-360, V = 100, S = ? )?&#xD;&#xA;&#xD;&#xA;-------------------------&#xD;&#xA;sofar my answer is :&#xD;&#xA;-------------------------&#xD;&#xA;a. hell white without saturation.&#xD;&#xA;b. dark gray with little saturation.&#xD;&#xA;c. half gray.&#xD;&#xA;d. dark black with low saturation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;is there any exact value for black and white in saturation channel?.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hXjgh.jpg&#xD;&#xA;  [2]: http://colorizer.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25028" PostHistoryTypeId="4" PostId="9168" RevisionGUID="44aa5410-3344-4622-ad6b-922711908300" CreationDate="2019-09-19T00:52:11.863" UserId="11208" Comment="added 2 characters in body" Text="(Question) HSV Channel - Mixing HSV Channel" ContentLicense="CC BY-SA 4.0" />
  <row Id="25029" PostHistoryTypeId="2" PostId="9169" RevisionGUID="d4876e59-d298-4a12-a5f6-3032c0c91c0f" CreationDate="2019-09-19T01:03:00.223" UserId="3003" Text="I think your answer is a little off. When the saturation is 0, the hue is basically undefined. It has some numerical value, but that value is ignored. Saturation of 0 means achromatic, or uncolored. So it can only be a shade of gray. &#xD;&#xA;&#xD;&#xA;Saturation is unrelated to value in HSV. You can have all of the following:&#xD;&#xA;&#xD;&#xA; - dark unsaturated colors (basically dark grays or colors close to dark grays)&#xD;&#xA; - dark saturated colors (think of a deep red wine color, for example)&#xD;&#xA; - bright unsaturated colors (bright grays, pastels have a a little bit of saturation)&#xD;&#xA; - bright saturated colors (like the red of a stop sign)&#xD;&#xA;&#xD;&#xA;Looking at your example, it looks like the S channel has only 2 values: 0 and 100%." ContentLicense="CC BY-SA 4.0" />
  <row Id="25030" PostHistoryTypeId="4" PostId="9168" RevisionGUID="490973af-a577-49a6-9be8-17e5c9643c42" CreationDate="2019-09-19T01:05:12.277" UserId="3003" Comment="Removed the word &quot;Question&quot; from title and removed redundancy" Text="Mixing HSV Channel" ContentLicense="CC BY-SA 4.0" />
  <row Id="25031" PostHistoryTypeId="5" PostId="9157" RevisionGUID="cd841810-d0b2-4cbd-8092-96575451d178" CreationDate="2019-09-19T07:41:30.860" UserId="8009" Comment="Broke into paragraphs.  Some formatting and minor readability fixes." Text="I am currently building a ray tracer and I came across a problem and confusion regarding the light calculations. For lighting, I am using the following mathematical model: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Where `Ka` is the ambient color component, `Ke` is the emission color component. The summation calculates the phong and lambert components using specular and diffusion. The summation is over all the lights where `Li` is the light color and `Vi` is a binary variable that eliminates the lambert and phong components for the sake of producing the shadowing effect. On the other hand, the `Ks` is the specular component and `Ir` is the reflective color that is calculated recursively by producing a new ray and tracing this ray. All the color components are represented by a 3D vector that stores the R, G, B colors and they take a value from 0 to 1.&#xD;&#xA;&#xD;&#xA;The model sums up all the color values which can end up producing values that are greater than and in a way overflowing the maximum value for the color channel. In my ray tracer implementation this was not a problem for all the terms highlighted in white because, for all the scenes I produced, none of them actually faced the problem where the sum of the colors were greater than zero. Now my attention was brought to this problem when I added the term highlighted in green which is the reflection term. I tried different things like setting the value of the color channel to 1 when it is going to overflow and taking the modulus or even setting it to zero. &#xD;&#xA;&#xD;&#xA;**All my solutions produce reflections, but the reflections are not smooth and have a lot of noise in them which I can't seem to eliminate.** &#xD;&#xA;&#xD;&#xA;I searched online for this issue but I did not find a lot of details. What would be a good solution for handling the possibility of the final color overflowing in one or more channels?&#xD;&#xA;&#xD;&#xA;Note: my implementation works fine without reflection which makes me believe that the color implementation is correct. &#xD;&#xA;&#xD;&#xA;One of my sample output images:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Instead the desired output should be:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MzLVB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/67GBz.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Jvbrd.png&#xD;&#xA;&#xD;&#xA;*Please ignore the size and aspect ratio differences of the two images.*" ContentLicense="CC BY-SA 4.0" />
  <row Id="25032" PostHistoryTypeId="24" PostId="9157" RevisionGUID="cd841810-d0b2-4cbd-8092-96575451d178" CreationDate="2019-09-19T07:41:30.860" Comment="Proposed by 8009 approved by 209, 2041 edit id of 490" ContentLicense="CC BY-SA 4.0" />
  <row Id="25033" PostHistoryTypeId="5" PostId="8185" RevisionGUID="db1d3856-2711-4fab-9bf5-cfbdf9733e7f" CreationDate="2019-09-19T07:41:54.760" UserId="11180" Comment="Fix spelling" Text="I keep coming across the terms 'Metal' and 'Vulkan' on this site.&#xD;&#xA;Guessing this to be some CG software, I'm interested to know what these are exactly and what the intended and most common usage is.&#xD;&#xA;&#xD;&#xA;A quick search shows me a video about why metal in CG looks fake: https://www.youtube.com/watch?v=NjbLYFXrfFU&#xD;&#xA;&#xD;&#xA;Obviously not the answer, most answers talk about compute kernels. I'm familiar with kernel inversion in machine learning but not like Android kernels and the such. Hope you can help me out. Your input would be most valuable." ContentLicense="CC BY-SA 4.0" />
  <row Id="25034" PostHistoryTypeId="4" PostId="8185" RevisionGUID="db1d3856-2711-4fab-9bf5-cfbdf9733e7f" CreationDate="2019-09-19T07:41:54.760" UserId="11180" Comment="Fix spelling" Text="What are Metal and Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25035" PostHistoryTypeId="24" PostId="8185" RevisionGUID="db1d3856-2711-4fab-9bf5-cfbdf9733e7f" CreationDate="2019-09-19T07:41:54.760" Comment="Proposed by 11180 approved by 209, 2041 edit id of 489" ContentLicense="CC BY-SA 4.0" />
  <row Id="25041" PostHistoryTypeId="50" PostId="8779" RevisionGUID="8322a326-df4f-438b-bcb6-ff5c86744270" CreationDate="2019-09-19T14:01:20.220" UserId="-1" />
  <row Id="25042" PostHistoryTypeId="34" PostId="9008" RevisionGUID="c56cb2c4-bdce-46f4-887c-7c225b59fc8b" CreationDate="2019-09-19T19:01:40.197" UserId="-1" Comment="56" />
  <row Id="25043" PostHistoryTypeId="2" PostId="9172" RevisionGUID="6bd4a44b-b3ef-4cf5-b840-f006d8903592" CreationDate="2019-09-21T02:12:32.900" UserId="10600" Text="I'm working on a small ray tracing project in my free time and I'm currently implementing boolean operations for spheres.&#xD;&#xA;&#xD;&#xA;My code is setup to calculate the intersection points of each of the spheres with any given ray and spit out the correct points to be rendered to the screen based on the type of boolean operation being performed (Union, Difference or Intersection).&#xD;&#xA;&#xD;&#xA;I haven't been at it for too long, but so far I have the code for the Intersection running nicely:&#xD;&#xA;&#xD;&#xA;`v3df` and `v2df` are 3d and 2d float vectors respectively.  &#xD;&#xA;`s1t` and `s2t` are the intersection points for each of the spheres with a ray.&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;if(s1t.x == 0 &amp;&amp; s1t.y == 0 || s2t.x == 0 &amp;&amp; s2t.y == 0)&#xD;&#xA;    return v2df();&#xD;&#xA;    &#xD;&#xA;if(min(s1t.x, s1t.y) &gt; max(s2t.x, s2t.y) || min(s2t.x, s2t.y) &gt; max(s1t.x, s1t.y))&#xD;&#xA;    return v2df();&#xD;&#xA;    &#xD;&#xA;std::vector&lt;float&gt; values = { s1t.x, s1t.y, s2t.x, s2t.y };&#xD;&#xA;std::sort(values.begin(), values.end());&#xD;&#xA;v2df res(values[2], values[1]);&#xD;&#xA;return res;&#xD;&#xA;```&#xD;&#xA;This produces the following output with variable spheres:&#xD;&#xA;[![intersection of two spheres][1]][1]&#xD;&#xA;&#xD;&#xA;Now I would like to implement the normals for said intersection, and my basic idea would be to take the normals of each of the corresponding spheres where their geometry shows, but I'm at a loss for how to implement this.&#xD;&#xA;&#xD;&#xA;here's the method stub I would like to use:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;v3df GetNormal(v3df point) {&#xD;&#xA;	return v3df();&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;  [1]: https://i.stack.imgur.com/qDFud.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25044" PostHistoryTypeId="1" PostId="9172" RevisionGUID="6bd4a44b-b3ef-4cf5-b840-f006d8903592" CreationDate="2019-09-21T02:12:32.900" UserId="10600" Text="Calculate Normals of Boolean Operation for Ray Tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="25045" PostHistoryTypeId="3" PostId="9172" RevisionGUID="6bd4a44b-b3ef-4cf5-b840-f006d8903592" CreationDate="2019-09-21T02:12:32.900" UserId="10600" Text="|raytracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25046" PostHistoryTypeId="2" PostId="9173" RevisionGUID="f82ec1c6-40b6-437a-8d04-866b90d8b355" CreationDate="2019-09-21T03:41:32.510" UserId="2654" Text="&gt; My code is setup to calculate the intersection points of each of the spheres with any given ray and spit out the correct points to be rendered to the screen based on the type of boolean operation being performed (Union, Difference or Intersection).&#xD;&#xA;&#xD;&#xA;Then you need to do the exact same thing with the normals. Indeed, you would typically do this operation with all of the appropriate parametric values for the various leaf surfaces.&#xD;&#xA;&#xD;&#xA;However, you need to take into account how the operations affect the meaning of the intersections. With positions, an intersection is used to determine if you're inside an object or outside of it. An OR operation (union) makes any intersection of the two objects considered &quot;inside&quot;, with &quot;outside&quot; only happening if you're outside of all of them. An AND operation (intersection) only makes the composite object &quot;inside&quot; if you're inside all of the AND'd objects.&#xD;&#xA;&#xD;&#xA;A negation *reverses* the meaning of inside and outside for the object. So an AND with a negation (difference) means that the only part that is inside of the composite object is the part of the first object which is not also inside of the second.&#xD;&#xA;&#xD;&#xA;Normals use the same rules as positions, with one exception. When used with a difference operation, if the ray enters the negated object (and thus is still outside of the composite), then enters the primary object (but is still outside of the composite because it's still inside of the negated one), and then leaves the negated object, that intersection represents a visible point.&#xD;&#xA;&#xD;&#xA;Except that the normal is *backwards*, since you're using the *inside* of the negative surface to define the surface of the composite object.&#xD;&#xA;&#xD;&#xA;When you negate a surface, you invert the meaning of its normals. So when you do a difference operation, you have to negate the normals of any intersections with the negative surface." ContentLicense="CC BY-SA 4.0" />
  <row Id="25047" PostHistoryTypeId="50" PostId="9071" RevisionGUID="63018c35-e904-497f-923e-0df16b1b2123" CreationDate="2019-09-21T05:02:00.293" UserId="-1" />
  <row Id="25048" PostHistoryTypeId="36" PostId="9174" RevisionGUID="415b058a-385b-425e-a31d-c2cf3e9150ab" CreationDate="2019-09-21T11:52:08.953" UserId="-1" Comment="from https://stats.stackexchange.com/questions/427883/is-there-way-for-clustering-joined-rectangles-by-thickness" />
  <row Id="25049" PostHistoryTypeId="2" PostId="9174" RevisionGUID="4086e511-e232-4ed3-9b66-2e1aa55526a2" CreationDate="2019-09-19T12:02:02.800" UserDisplayName="Oleg" Text="Here is an example&#xD;&#xA;&#xD;&#xA;dots representing coordinates of pixels&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*added more representative example*&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SFr02.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4E1ez.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25050" PostHistoryTypeId="1" PostId="9174" RevisionGUID="4086e511-e232-4ed3-9b66-2e1aa55526a2" CreationDate="2019-09-19T12:02:02.800" UserDisplayName="Oleg" Text="Is there way for clustering joined rectangles by thickness?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25051" PostHistoryTypeId="3" PostId="9174" RevisionGUID="4086e511-e232-4ed3-9b66-2e1aa55526a2" CreationDate="2019-09-19T12:02:02.800" UserDisplayName="Oleg" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25052" PostHistoryTypeId="36" PostId="9175" RevisionGUID="ff69676a-5e2b-47fd-b69c-03bc44d47264" CreationDate="2019-09-21T11:52:08.953" UserId="-1" Comment="from https://stats.stackexchange.com/questions/427883/is-there-way-for-clustering-joined-rectangles-by-thickness/427924#427924" />
  <row Id="25053" PostHistoryTypeId="2" PostId="9175" RevisionGUID="c68aacd6-b679-4b70-8401-38518a0f13e3" CreationDate="2019-09-19T17:07:20.047" UserDisplayName="Anony-Mousse" Text="It is a bad idea to try to abuse clustering algorithms for this. In particular k-means will *not* cut vertically, nor consider rectangles.&#xA;&#xA;What you need to do is a trivial axis-aligned corner detection.it does not get much simpler than that!&#xA;&#xA;You begin on the left, and whenever the location of the topmost pixel changes, a rectangle is complete.&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25054" PostHistoryTypeId="2" PostId="9176" RevisionGUID="3f54d358-211f-4823-bc75-990067daafdb" CreationDate="2019-09-22T16:00:52.893" UserId="10191" Text="I noticed that a common metrics for image quality assessment (Monte Carlo path tracing) is MSE between the generated image and a reference one. My question is: why isn't the standard deviation ever mentioned? Isn't it necessary? Shouldn't we generate n number of samples, compare them all with the reference, and then report the average and the standard deviation?&#xA;This is how I have always seen results in technical papers, except for papers in Graphics. I am wondering if the fact that path tracing is unbiased plays a role in the missing std dev. &#xA;Thank you." ContentLicense="CC BY-SA 4.0" />
  <row Id="25055" PostHistoryTypeId="1" PostId="9176" RevisionGUID="3f54d358-211f-4823-bc75-990067daafdb" CreationDate="2019-09-22T16:00:52.893" UserId="10191" Text="Report standard deviation in Rendering results" ContentLicense="CC BY-SA 4.0" />
  <row Id="25056" PostHistoryTypeId="3" PostId="9176" RevisionGUID="3f54d358-211f-4823-bc75-990067daafdb" CreationDate="2019-09-22T16:00:52.893" UserId="10191" Text="|raytracing|rendering|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25057" PostHistoryTypeId="2" PostId="9177" RevisionGUID="b42524e1-c312-4a5b-a940-3e3b5412dc35" CreationDate="2019-09-22T23:33:18.670" UserId="11223" Text="When binding an attribute index using glVertexAttribPointer, what happens when a later binded program does not contain an attribute at said index?&#xD;&#xA;&#xD;&#xA;Is the behaviour undefined, or is the attribute ignored altogether?&#xD;&#xA;&#xD;&#xA;I have searched the docs quite extensively, and have not been able to find much info about the link between programs and dynamic attribute bindings.&#xD;&#xA;&#xD;&#xA;Thanks all." ContentLicense="CC BY-SA 4.0" />
  <row Id="25058" PostHistoryTypeId="1" PostId="9177" RevisionGUID="b42524e1-c312-4a5b-a940-3e3b5412dc35" CreationDate="2019-09-22T23:33:18.670" UserId="11223" Text="Confusion about glVertexAttribPointer and non-active attributes" ContentLicense="CC BY-SA 4.0" />
  <row Id="25059" PostHistoryTypeId="3" PostId="9177" RevisionGUID="b42524e1-c312-4a5b-a940-3e3b5412dc35" CreationDate="2019-09-22T23:33:18.670" UserId="11223" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25060" PostHistoryTypeId="6" PostId="9177" RevisionGUID="a4419a57-226a-45e6-957f-f4a92c283c33" CreationDate="2019-09-22T23:41:12.210" UserId="11223" Comment="edited tags" Text="|opengl|shader|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25061" PostHistoryTypeId="2" PostId="9178" RevisionGUID="ed283993-0db4-4a5e-8db0-2c447e0e7d30" CreationDate="2019-09-22T23:46:12.887" UserId="11224" Text="I would like to imitate the orthographic projection that Matlab uses by default:&#xD;&#xA;&#xD;&#xA;[Matlab View Projections][1]&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;[Matlab camproj][2]&#xD;&#xA;&#xD;&#xA;It seems similar to the &quot;Trimetric&quot; projection described here:&#xD;&#xA;&#xD;&#xA;[Wikipedia on Orthographic Projection][3]&#xD;&#xA;&#xD;&#xA;see the picture here:&#xD;&#xA;&#xD;&#xA;[Wikipedia picture - Comparison of projections][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;but I don't know whether they are definitely the same. Does anyone know the exact details of the Matlab projection ?&#xD;&#xA;&#xD;&#xA;Thank you !&#xD;&#xA;&#xD;&#xA;  [1]: https://uk.mathworks.com/help/matlab/creating_plots/understanding-view-projections.html&#xD;&#xA;  [2]: https://uk.mathworks.com/help/matlab/ref/camproj.html&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Orthographic_projection&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Orthographic_projection#/media/File:Graphical_projection_comparison.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25062" PostHistoryTypeId="1" PostId="9178" RevisionGUID="ed283993-0db4-4a5e-8db0-2c447e0e7d30" CreationDate="2019-09-22T23:46:12.887" UserId="11224" Text="What exactly is the orthographic projection used by Matlab" ContentLicense="CC BY-SA 4.0" />
  <row Id="25063" PostHistoryTypeId="3" PostId="9178" RevisionGUID="ed283993-0db4-4a5e-8db0-2c447e0e7d30" CreationDate="2019-09-22T23:46:12.887" UserId="11224" Text="|projections|matlab|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25067" PostHistoryTypeId="50" PostId="8790" RevisionGUID="0ae0daa0-9154-4e8f-ab09-5495660ba7ec" CreationDate="2019-09-23T07:01:15.380" UserId="-1" />
  <row Id="25072" PostHistoryTypeId="5" PostId="9177" RevisionGUID="629b5535-e21e-4e9e-a06d-9659da09b0da" CreationDate="2019-09-23T11:22:21.980" UserId="209" Comment="minor spelling correction" Text="When binding an attribute index using glVertexAttribPointer, what happens when a later bound program does not contain an attribute at said index?&#xD;&#xA;&#xD;&#xA;Is the behaviour undefined, or is the attribute ignored altogether?&#xD;&#xA;&#xD;&#xA;I have searched the docs quite extensively, and have not been able to find much info about the link between programs and dynamic attribute bindings.&#xD;&#xA;&#xD;&#xA;Thanks all." ContentLicense="CC BY-SA 4.0" />
  <row Id="25073" PostHistoryTypeId="5" PostId="7979" RevisionGUID="bb67c5ed-a180-42f1-bf52-00495f143110" CreationDate="2019-09-23T11:23:17.897" UserId="11180" Comment="s/Vulcan/Vulkan/, use c++ syntax highlighting, fix other typos and broken fragment sentence" Text="Here is my predicament. I am trying to draw a multitude of dots that leave trails behind them real time. Heres the difficulty, that line fades. Each dot line has a defined z position and the goal would be for everything to blend properly, in real time.&#xD;&#xA;&#xD;&#xA;I am currently doing this geometry with a series of triangles that form a triangle strip (I am not using a triangle strip due to the edge case in the circle buffer and spacial locality). This strip is currently implemented as a sort of circle buffer where old triangles are overridden. Each vertex gets passed in the time it was created and thus it knows how to fade (make transparent) its own color.&#xD;&#xA;&#xD;&#xA;To make things more complicated I am also drawing caps on the ends of the dot so there is essentially a half rectangle at the end with fragments of it discarded to shape it into a circle.&#xD;&#xA;&#xD;&#xA;All of this presents a predicament for alpha testing as alpha testing requires drawing to be sorted in order of depth. Just about all the geometry is transparent in some form. Even if I can get the triangle strip to do this properly getting the half circle working would be quite difficult.&#xD;&#xA;&#xD;&#xA;I set the z position based on the dot's id and use the same value that is used to dim the dot's trail to get the triangle strip to have non-conflicting depth.&#xD;&#xA;&#xD;&#xA;As for the half circle part does this mean I am going to have to do two draw calls per circle? One to render their segment of the triangle buffer and the other to draw the semi-circle?&#xD;&#xA;&#xD;&#xA;Currently I am using the following memory layout:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;const int MAX_INDEX = 200;&#xD;&#xA;const int MAX_DOTS = 10000;&#xD;&#xA;int bufferIndex = (bufferIndex + 1) % MAX_INDEX;&#xD;&#xA;int dotIndex = 0..&lt;MAX_DOTS&#xD;&#xA;Rect = triangleStripBuffer[bufferIndex * MAX_DOTS + dotIndex];&#xD;&#xA;```&#xD;&#xA;You can see that data in there is not naturally sorted by anything other than time but even that cycles and there is no consideration for drawing order.&#xD;&#xA;&#xD;&#xA;So I suppose I really need ideas on how I can get the geometry to draw in order so that alpha testing can occur. How do I combine these two different drawing goals in a good way?&#xD;&#xA;&#xD;&#xA;I figure this problem is fairly platform-agnostic but if it is not I am working with Metal and eventually Vulkan can do this." ContentLicense="CC BY-SA 4.0" />
  <row Id="25074" PostHistoryTypeId="24" PostId="7979" RevisionGUID="bb67c5ed-a180-42f1-bf52-00495f143110" CreationDate="2019-09-23T11:23:17.897" Comment="Proposed by 11180 approved by 6, 209 edit id of 491" ContentLicense="CC BY-SA 4.0" />
  <row Id="25075" PostHistoryTypeId="5" PostId="9174" RevisionGUID="6613e33e-1edc-40a9-bb06-e16c257d0988" CreationDate="2019-09-23T12:07:16.680" UserId="11226" Comment="added 120 characters in body" Text="Here is an example&#xD;&#xA;&#xD;&#xA;dots representing coordinates of pixels&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*added more representative example*&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*added real example*&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SFr02.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4E1ez.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Y6bJS.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25077" PostHistoryTypeId="5" PostId="9174" RevisionGUID="7b12df20-53cd-432c-94f2-ad378ab668b1" CreationDate="2019-09-23T14:24:57.973" UserId="11226" Comment="added 87 characters in body" Text="Here is an example&#xD;&#xA;&#xD;&#xA;dots representing coordinates of pixels&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*added more representative example*&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*added real example*&#xD;&#xA;&#xD;&#xA;[![added real example][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*added main problem*&#xD;&#xA;&#xD;&#xA;[![main problem][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SFr02.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4E1ez.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Y6bJS.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/P8Y5p.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25078" PostHistoryTypeId="2" PostId="9181" RevisionGUID="2fe11b55-4021-4ad9-b280-cfd014ac2413" CreationDate="2019-09-23T14:48:25.483" UserId="11155" Text="I am porting some code from Metal to OpenGL since we want to run our app on Windows too. Xcode is my preferred IDE, but the newer versions of Xcode do not support any OpenGL debugging.&#xD;&#xA;&#xD;&#xA;Question: What do people usually use as a debugger for OpenGL? Eg: Frame capture on Metal is great and allows you to do shader debugging etc and nicely view the call hierarchy. Is there any thing similar for OpenGL?&#xD;&#xA;&#xD;&#xA;If there are some good solutions on Windows, i can consider switching to Visual Studio.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="25079" PostHistoryTypeId="1" PostId="9181" RevisionGUID="2fe11b55-4021-4ad9-b280-cfd014ac2413" CreationDate="2019-09-23T14:48:25.483" UserId="11155" Text="Debugging tools for OpenGL on macOS" ContentLicense="CC BY-SA 4.0" />
  <row Id="25080" PostHistoryTypeId="3" PostId="9181" RevisionGUID="2fe11b55-4021-4ad9-b280-cfd014ac2413" CreationDate="2019-09-23T14:48:25.483" UserId="11155" Text="|opengl|metal|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25081" PostHistoryTypeId="4" PostId="9174" RevisionGUID="17973e3f-452e-48cb-91e5-88054a48abdd" CreationDate="2019-09-23T14:55:29.897" UserId="11226" Comment="edited title" Text="Is there way for polygon decomposition by thickness?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25083" PostHistoryTypeId="2" PostId="9182" RevisionGUID="5d1c2756-f30c-4766-8a78-658b3a7dd72a" CreationDate="2019-09-24T05:47:39.253" UserId="11232" Text="Looking at various assets (models / textures / scenes) available online, I have noticed a trend that conflicts with my assumptions. Many of the normal maps contain texels whose vector length deviates from unit length by a significant amount.&#xD;&#xA;&#xD;&#xA;For example, this image from Wikimedia Commons (https://commons.wikimedia.org/wiki/File:Normal_map_example_-_Map.png) contains many vectors (hundreds) that are around 15%+ shorter than unit length, and it is hardly an outlier (in fact, it would seem to have been chosen as an exemplary basic example). In other cases, I have found normal maps where the z component is uniformly set to 1.0.&#xD;&#xA;&#xD;&#xA;On the specification side of things, I note that GLTF 2.0 merely states (https://github.com/KhronosGroup/glTF/issues/993) that a shader implementation should renormalize after sampling, but that it is not required for the maps themselves to have vectors of unit length.&#xD;&#xA;&#xD;&#xA;It seems to me that this poses an accuracy issue. Certainly if normals are sampled using bilinear filtering, the result will generally be shorter than the texels used to generate it, and thus renormalization will be necessary. However, if this is the argument as to why it is not necessary to store as unit length vectors, then it seems short-sighted to me.&#xD;&#xA;&#xD;&#xA;When sampling with e.g. bilinear filtering, if the texels are not all of the same length, the resulting normal will be biased in direction towards the samples with greater length. Therefore, even if you renormalize after sampling, you will not be able to recover the accuracy lost by not starting with unit normals in the first place.&#xD;&#xA;&#xD;&#xA;So I would like to know why such low priority is seemingly placed on generating normal map textures that contain only unit-length normals. Is it just because the loss in accuracy isn't deemed to be significant enough subjectively/perceptually, or is there something else completely here that I am missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25084" PostHistoryTypeId="1" PostId="9182" RevisionGUID="5d1c2756-f30c-4766-8a78-658b3a7dd72a" CreationDate="2019-09-24T05:47:39.253" UserId="11232" Text="Normal Map Storage (Not Unit Length)" ContentLicense="CC BY-SA 4.0" />
  <row Id="25085" PostHistoryTypeId="3" PostId="9182" RevisionGUID="5d1c2756-f30c-4766-8a78-658b3a7dd72a" CreationDate="2019-09-24T05:47:39.253" UserId="11232" Text="|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25086" PostHistoryTypeId="2" PostId="9183" RevisionGUID="d855b784-6304-469d-8ea0-a0573e06722c" CreationDate="2019-09-24T06:55:07.817" UserId="48" Text="Maps with z = 1.0 everywhere are likely [partial derivative maps](http://diaryofagraphicsprogrammer.blogspot.com/2009/01/partial-derivative-normal-maps.html). This is a variant on normal maps that's become fairly widespread. There are a few reasons to prefer it, but probably the most important is it lets you store the map as just two channels (red and green), which allows using better quality BC5 compression, while being cheap to decode in the shader. The normals in such a map are of necessity not all unit length, and as you pointed out that will affect interpolation and blending slightly, but this is generally deemed an acceptable trade-off.&#xD;&#xA;&#xD;&#xA;However, if it's purporting to be a traditional old-school normal map and it has pixels that are significantly off from unit length, that sounds odd and probably unintended. I'm not sure why that would have happened in the particular Wikimedia .png example you linked. However, non-unit-length normals could generally be introduced by doing filtering/blending/compositing operations on the image without renormalizing after (for example, if a normal map was rendered at a higher resolution and then downsampled using a standard image resampling algorithm). They could also be introduced by lossy compression." ContentLicense="CC BY-SA 4.0" />
  <row Id="25088" PostHistoryTypeId="2" PostId="9184" RevisionGUID="d3518491-6efd-4534-ba7b-1c75b52053de" CreationDate="2019-09-25T01:22:30.397" UserId="3003" Text="There's nothing like frame capture for OpenGL on macOS, unfortunately. There are 2 tools that are useful for this: OpenGL Profiler and OpenGL Driver Monitor. You can read about them [here](https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/opengl_performance.html#//apple_ref/doc/uid/TP40001987-CH213-SW1). To download them, you need to log in to your developer account on developer.apple.com, click on &quot;Downloads&quot; on the left side. On the downloads page in the upper right is a tiny &quot;more&quot; link. If you click on that, you'll get the search tool. Enter &quot;OpenGL Profiler&quot; for your search and you'll be presented with a number of packages for different versions of Xcode. Choose the one that matches whichever version of Xcode you have. It's in the &quot;Graphics Tools&quot; section of the download." ContentLicense="CC BY-SA 4.0" />
  <row Id="25089" PostHistoryTypeId="5" PostId="9184" RevisionGUID="647dd7a5-780f-4c14-92fc-6a1b547bda61" CreationDate="2019-09-25T01:58:04.933" UserId="3003" Comment="Added warning about out-of-date images in docs." Text="There's nothing like frame capture for OpenGL on macOS, unfortunately. There are 2 tools that are useful for this: OpenGL Profiler and OpenGL Driver Monitor. You can read about them [here](https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/opengl_performance.html#//apple_ref/doc/uid/TP40001987-CH213-SW1). (Warning the images in the article are *really* old. They look like normal apps today without all the brushed metal, etc.) To download them, you need to log in to your developer account on developer.apple.com, click on &quot;Downloads&quot; on the left side. On the downloads page in the upper right is a tiny &quot;more&quot; link. If you click on that, you'll get the search tool. Enter &quot;OpenGL Profiler&quot; for your search and you'll be presented with a number of packages for different versions of Xcode. Choose the one that matches whichever version of Xcode you have. It's in the &quot;Graphics Tools&quot; section of the download." ContentLicense="CC BY-SA 4.0" />
  <row Id="25090" PostHistoryTypeId="5" PostId="8989" RevisionGUID="91c22f9a-1695-41a8-9ab0-5e6b4e7fc26a" CreationDate="2019-09-25T06:37:23.400" UserId="6046" Comment="Added a release to my project so it's gonna be easier for people to help out" Text="So Im trying to implement a Volume Renderer mainly for medical images like CT-scans and MRI images using GPU raymarching. I'm using the book &quot;Real Time Volume Graphics&quot; and [this][1] tutorial as a refernce. &#xD;&#xA;&#xD;&#xA;I'm trying to render only grayscale images as a start. I understand that the `pvm2raw` part gives us an 8-bit raw file so each voxel has the isovalue in the range [0-255]. So I decided map this single value on all color channels `rgba` when taking a sample.&#xD;&#xA;&#xD;&#xA;I am taking the datasets from [here][2]. **You can see my Renderer's result in [this][3] video** (check the end of my post and sorry for not providing a direct link as I already uploaded on my reddit post)&#xD;&#xA;&#xD;&#xA;As you can see the lobster dataset stretches when viewed from the side. My first guess was that I wasn't accounting for the aspect ratio correctly. I have tried scaling the Bounding box to account for the aspect ratio, then adjusting the stepsize according to that. I've also tried to ignore aspect ratio altogether. Both give similar images.&#xD;&#xA;&#xD;&#xA;I tried rendering more datasets like &quot;Knee&quot;, &quot;Bruce's head&quot;, &quot;DTI Scan&quot;, etc but those didn't even gave an image. There was just random noise everywhere. Here's an example of &quot;Bruce's head&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This happens with both uniform and non-uniform datasets. If some datasets are getting rendered correctly like the &quot;Foot&quot; in my video, this should mean it's more a with that specific dataset itself rather the core algorithm. Nonetheless the link to the code is provided If anybody can point out some mistakes I'd be grateful.&#xD;&#xA;&#xD;&#xA;***The link to the Compute shader is [here][5]. Main functions are `rayMarchVolume`. I didn't scale the root bounding box to the dimensions of the volume, it's normalized `(0-1)`, accounted for the aspect ratio `(0, ar)` and adjusted so it's in the center `(-ar/2, ar/2)`. The function `cartesianToTextureCoord(vec4 point)` accounts for this fact and returns a texture coord in the range 0-1***&#xD;&#xA;&#xD;&#xA;EDIT:- If you are hesitating to post an answer here since it's only a suggestion, you can post on Reddit, then when the problem is solved you can post your answer here&#xD;&#xA;&#xD;&#xA;**UPDATE**:- I've provided a release to this project on github. If anybody is willing to help me with this, he can download the release and run the program. Since the algorithm is based entirely inside the compute shader you can change the file easily and test your findings on the spot. Thanks.&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: http://schorsch.efi.fh-nuernberg.de/data/volume/&#xD;&#xA;  [3]: https://www.reddit.com/r/GraphicsProgramming/comments/chntyk/help_volume_rendering_ray_marching_not_giving/&#xD;&#xA;  [4]: https://i.stack.imgur.com/EXyYg.png&#xD;&#xA;  [5]: https://github.com/gallickgunner/Volume-Renderer/blob/master/VolumeRenderer.cs" ContentLicense="CC BY-SA 4.0" />
  <row Id="25091" PostHistoryTypeId="2" PostId="9185" RevisionGUID="a753e5b6-9ff5-4c73-a118-e3d7ba927626" CreationDate="2019-09-25T11:30:11.570" UserId="11237" Text="I' trying to write a monte carlo ray tracer in julia, but my main function returns stack overflow error. Below is my main function:&#xD;&#xA;&#xD;&#xA;    function trace(ray::Ray, surfaces::Array{Any, 1}, depth::Int64, maxDepth::Int64)&#xD;&#xA;    material, t = findIntersection(ray, surfaces, Inf)&#xD;&#xA;    if typeof(material) == Empty&#xD;&#xA;        Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    if depth &gt; maxDepth&#xD;&#xA;        Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    if material.isLight == true&#xD;&#xA;        material.emittance&#xD;&#xA;    end&#xD;&#xA;    normal = material.normal&#xD;&#xA;    ρ = material.reflectance&#xD;&#xA;    BRDF = ρ/3.1415&#xD;&#xA;    R = randHemi(normal)&#xD;&#xA;    cosθ = dot(R,normal)&#xD;&#xA;    newRay = Ray(ray.s + t*ray.d, R)&#xD;&#xA;    In = trace(newRay, surfaces, depth+1, maxDepth)&#xD;&#xA;    2.0*3.1415*BRDF*In&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;But when I run it, I receive this error:&#xD;&#xA;&#xD;&#xA;    StackOverflowError:&#xD;&#xA;&#xD;&#xA;    Stacktrace:&#xD;&#xA;     [1] findIntersection(::Ray, ::Array{Any,1}, ::Float64) at .\In[31]:10&#xD;&#xA;     [2] trace(::Ray, ::Array{Any,1}, ::Int64, ::Int64) at .\In[33]:2&#xD;&#xA;     [3] trace(::Ray, ::Array{Any,1}, ::Int64, ::Int64) at .\In[33]:18 (repeats &#xD;&#xA;    14493 times)&#xD;&#xA;     [4] top-level scope at In[35]:1&#xD;&#xA;&#xD;&#xA;And here is my intersection function:&#xD;&#xA;&#xD;&#xA;    function findIntersection(ray::Ray, surfaces::Array{Any, 1}, tmin::Float64)&#xD;&#xA;    hitSurface = Empty(Vec3(0,0,0), Vec3(0,0,0), Vec3(0,0,0), false)&#xD;&#xA;    for surface in surfaces&#xD;&#xA;        t = intersect(surface, ray)&#xD;&#xA;        if t &lt; tmin&#xD;&#xA;            hitSurface = surface&#xD;&#xA;            tmin = t&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;    return hitSurface, tmin       &#xD;&#xA;    end" ContentLicense="CC BY-SA 4.0" />
  <row Id="25092" PostHistoryTypeId="1" PostId="9185" RevisionGUID="a753e5b6-9ff5-4c73-a118-e3d7ba927626" CreationDate="2019-09-25T11:30:11.570" UserId="11237" Text="Why does my julia ray tracer return stack overflow error?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25093" PostHistoryTypeId="3" PostId="9185" RevisionGUID="a753e5b6-9ff5-4c73-a118-e3d7ba927626" CreationDate="2019-09-25T11:30:11.570" UserId="11237" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25094" PostHistoryTypeId="2" PostId="9186" RevisionGUID="daa663b6-f5b0-484d-9a05-e84dac0f46a1" CreationDate="2019-09-25T17:11:31.420" UserId="10051" Text="The [Intel 740][1] AGP graphics card read textures directly from system RAM, using VRAM exclusively for depth buffers and the framebuffer. This has the effect of saving video RAM, and it could be implemented with AGP transfer speeds far lower than PCIe transfer speeds of today.&#xD;&#xA;&#xD;&#xA;Is such a method of zero-copy texture loading possible/optimal on modern **discrete** graphics hardware? Is there a specific hardware feature that was present on the i740 requisite for this technique that is not present on modern graphics cards? Furthermore, could zero-copy texture access functionality be exposed by using mapped buffers in OpenGL?&#xD;&#xA;&#xD;&#xA;I apologize if I am not being clear, and thanks in advance for any reply.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Intel740" ContentLicense="CC BY-SA 4.0" />
  <row Id="25095" PostHistoryTypeId="1" PostId="9186" RevisionGUID="daa663b6-f5b0-484d-9a05-e84dac0f46a1" CreationDate="2019-09-25T17:11:31.420" UserId="10051" Text="Zero-copy texture reading from GPU memory," ContentLicense="CC BY-SA 4.0" />
  <row Id="25096" PostHistoryTypeId="3" PostId="9186" RevisionGUID="daa663b6-f5b0-484d-9a05-e84dac0f46a1" CreationDate="2019-09-25T17:11:31.420" UserId="10051" Text="|opengl|texture|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25097" PostHistoryTypeId="4" PostId="9186" RevisionGUID="ba95d645-75a7-4a1e-b51b-ba9d76d92e3a" CreationDate="2019-09-25T17:21:36.113" UserId="10051" Comment="edited title" Text="Zero-copy texture reading from CPU memory" ContentLicense="CC BY-SA 4.0" />
  <row Id="25101" PostHistoryTypeId="5" PostId="9186" RevisionGUID="321002e6-10db-4fc8-85f5-e09e208c5dc8" CreationDate="2019-09-25T20:45:44.513" UserId="2654" Comment="deleted 77 characters in body" Text="The [Intel 740][1] AGP graphics card read textures directly from system RAM, using VRAM exclusively for depth buffers and the framebuffer. This has the effect of saving video RAM, and it could be implemented with AGP transfer speeds far lower than PCIe transfer speeds of today.&#xD;&#xA;&#xD;&#xA;Is such a method of zero-copy texture loading possible/optimal on modern **discrete** graphics hardware? Is there a specific hardware feature that was present on the i740 requisite for this technique that is not present on modern graphics cards? Furthermore, could zero-copy texture access functionality be exposed by using mapped buffers in OpenGL?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Intel740" ContentLicense="CC BY-SA 4.0" />
  <row Id="25102" PostHistoryTypeId="2" PostId="9188" RevisionGUID="ee7fb11f-100e-4b16-b467-2d9314214462" CreationDate="2019-09-25T21:06:05.637" UserId="2654" Text="&gt; Is such a method of zero-copy texture loading possible/optimal on modern discrete graphics hardware?&#xD;&#xA;&#xD;&#xA;You say that as though it were optimal *back then*. The Intel 740 was not exactly warmly embraced by the market, as noted by the Wikipedia article in question:&#xD;&#xA;&#xD;&#xA;&gt; The AGP Texture concept soon proved to be a tremendous error in design, because the card had to constantly access the textures over a channel that was upwards of eight times slower than RAM placed on the graphics card itself.&#xD;&#xA;&#xD;&#xA;The disparity between available memory bandwidth/performance and available compute resources has only *increased* in the last 20 years. So, will it be &quot;optimal&quot; to have a discrete GPU read from main memory?&#xD;&#xA;&#xD;&#xA;No.&#xD;&#xA;&#xD;&#xA;Could it be &quot;possible&quot;? Not in terms of marketability. Even $50 and below discrete GPUs carry their own on-board RAM. Anything much slower/smaller than that isn't worthwhile, because pretty much everyone already has Intel or AMD's on-die GPUs for when performance isn't of importance. If you have a discrete board, it will always be better to put some RAM on the board with its own bus than to have the board try to read most of its data directly from main memory.&#xD;&#xA;&#xD;&#xA;&gt; Furthermore, could zero-copy texture access functionality be exposed by using mapped buffers in OpenGL?&#xD;&#xA;&#xD;&#xA;No. Mapped buffers would be *buffers*, not textures. They're different kinds of storage objects with (hypothetically) distinct allocations behind them. PBO is a means of asynchronously transferring data from a buffer to a texture. That is a *transfer* of data, not an adoption of a memory allocation.&#xD;&#xA;&#xD;&#xA;Intel has an [extension for mapping a texture's storage][1], but that requires that the texture be in a linear format. It's not widely supported, and likely never will be.&#xD;&#xA;&#xD;&#xA;Vulkan provides for the *possibility* of something similar, but using linear texture as sources in sampler read operations from a shader is not required to be supported. You'd have to ask each implementation whether it allows it and in which formats, and for which usages are allowed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/INTEL/INTEL_map_texture.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="25103" PostHistoryTypeId="50" PostId="8431" RevisionGUID="5f38ac30-ab82-4fd9-bd93-894e62850850" CreationDate="2019-09-26T00:01:05.130" UserId="-1" />
  <row Id="25105" PostHistoryTypeId="2" PostId="9189" RevisionGUID="5736661c-8e30-4836-aaee-e67cf9793045" CreationDate="2019-09-26T03:20:06.997" UserId="11239" Text="As we know in C/C++ there is &quot;graphics.h&quot; header file with the help of which we can do graphics programs in C. &#xD;&#xA;There is a function **pieslice** in that header file,its syntax is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#include &lt;graphics.h&gt;&#xD;&#xA;&#xD;&#xA;void pieslice(int x, int y, int stangle, int endangle, int radius);&#xD;&#xA;```&#xD;&#xA;[x,y are the center of the circle,stangle and endangle are the starting and end angles respectively]&#xD;&#xA;&#xD;&#xA;Can we make a pieslice in C/C++ without using this in-built function.Please help.&#xD;&#xA;&#xD;&#xA;Thank You in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="25106" PostHistoryTypeId="1" PostId="9189" RevisionGUID="5736661c-8e30-4836-aaee-e67cf9793045" CreationDate="2019-09-26T03:20:06.997" UserId="11239" Text="Program to make &quot;Pieslice&quot; without using library function?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25107" PostHistoryTypeId="3" PostId="9189" RevisionGUID="5736661c-8e30-4836-aaee-e67cf9793045" CreationDate="2019-09-26T03:20:06.997" UserId="11239" Text="|c++|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25108" PostHistoryTypeId="2" PostId="9190" RevisionGUID="790d18bf-4a9e-4855-a8ec-a882812a7bea" CreationDate="2019-09-26T12:35:23.023" UserId="11241" Text="My first issue is getting a set of planes and a set of points as input, an find the projection of the those points on the nearest plane.&#xD;&#xA;&#xD;&#xA;That was pretty easy, where i just calculate the normal of the plan and do some linear algebra to find the best plane to project  onto.&#xD;&#xA;&#xD;&#xA;Now i do not have just normal planes, i have a set of freeform surfaces, like $\textit{Bspline}$ and $\textit{Nurbs}$ and i have to project my given points on those surfaces. i Struggle to find the  minimum distance between the point and the surface.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any idea how to do that?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25109" PostHistoryTypeId="1" PostId="9190" RevisionGUID="790d18bf-4a9e-4855-a8ec-a882812a7bea" CreationDate="2019-09-26T12:35:23.023" UserId="11241" Text="Projecting a point on a Freefrom surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="25110" PostHistoryTypeId="3" PostId="9190" RevisionGUID="790d18bf-4a9e-4855-a8ec-a882812a7bea" CreationDate="2019-09-26T12:35:23.023" UserId="11241" Text="|c++|projections|nurbs|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25111" PostHistoryTypeId="2" PostId="9191" RevisionGUID="682d7c06-84db-45cc-aa01-fd9d13d5444b" CreationDate="2019-09-26T17:05:51.743" UserId="11243" Text="I've been reading up on images with indexed color, and while most indexed image formats are limited to 256 colors, there are apparently image formats that support larger palettes.&#xD;&#xA;&#xD;&#xA;According to [Wikipedia][1]&#xD;&#xA;&#xD;&#xA;&gt; Indexed color images with palette sizes beyond 256 entries are rare&#xD;&#xA;&#xD;&#xA;I did some extra searching, but I can't seem to find any clear list or mention of specific image formats that support larger color palettes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Indexed_color" ContentLicense="CC BY-SA 4.0" />
  <row Id="25112" PostHistoryTypeId="1" PostId="9191" RevisionGUID="682d7c06-84db-45cc-aa01-fd9d13d5444b" CreationDate="2019-09-26T17:05:51.743" UserId="11243" Text="What image formats support indexed color palettes with more than 256 colors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25113" PostHistoryTypeId="3" PostId="9191" RevisionGUID="682d7c06-84db-45cc-aa01-fd9d13d5444b" CreationDate="2019-09-26T17:05:51.743" UserId="11243" Text="|color|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25114" PostHistoryTypeId="2" PostId="9192" RevisionGUID="9c8e20f9-babd-412f-978f-05074d7c68bb" CreationDate="2019-09-27T01:40:05.277" UserId="7462" Text="A spherical camera is pretty easy to define.&#xD;&#xA;&#xD;&#xA;We have an anchor point C the camera always looks at and a relative position P where the camera is, which can be expressed in spherical coordinates, centered around the point C.&#xD;&#xA;&#xD;&#xA;In this type of camera the the up direction is always the up vector of the world.&#xD;&#xA;&#xD;&#xA;The implementation isn't terribly complex. given the parameters, we will calucate the position of the camera by doing:&#xD;&#xA;&#xD;&#xA;rotation around the x axis by phi, rotation around the y axis by theta, multiply by the radius then translation.&#xD;&#xA;&#xD;&#xA;And then we calculate the orientation of the camera with lookAt, centering the view at the anchor point.&#xD;&#xA;&#xD;&#xA;The trackball camera is different however, it allows for orientations of the view in which the camera up isn't necessarily 0,1,0.&#xD;&#xA;&#xD;&#xA;Also, in a spherical camera, the deltas around the x axis are mapped to one angle and the deltas around the y axis to the other. I am not 100% sure on how to represent nor map mouse movement to camera orientation in the case of a trackball.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25115" PostHistoryTypeId="1" PostId="9192" RevisionGUID="9c8e20f9-babd-412f-978f-05074d7c68bb" CreationDate="2019-09-27T01:40:05.277" UserId="7462" Text="Difference between a spherical camera and a trackball camera" ContentLicense="CC BY-SA 4.0" />
  <row Id="25116" PostHistoryTypeId="3" PostId="9192" RevisionGUID="9c8e20f9-babd-412f-978f-05074d7c68bb" CreationDate="2019-09-27T01:40:05.277" UserId="7462" Text="|mesh|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25117" PostHistoryTypeId="2" PostId="9193" RevisionGUID="f1d3f012-c77b-4fac-9daa-14cdf5076511" CreationDate="2019-09-27T04:19:41.063" UserId="3003" Text="You can use the sine and cosine functions to do this. Normally they start on the x axis and rotate counter-clockwise. The start point can be found by calculating:&#xD;&#xA;&#xD;&#xA;    startX = x + cos(startRadians) * radius;&#xD;&#xA;    startY = y + sin(startRadians) * radius;&#xD;&#xA;&#xD;&#xA;Likewise the ending coordinates are:&#xD;&#xA;&#xD;&#xA;    endX = x + cos(endRadians) * radius;&#xD;&#xA;    endY = y + sin(endRadians) * radius;&#xD;&#xA;&#xD;&#xA;Note that `sin()` and `cos()` take their parameters in radians. Given that `stangle` and `endangle` are integers, I'm guessing they're probably in degrees so you'll need to convert them by doing something like:&#xD;&#xA;&#xD;&#xA;    double startRadians = (double)stangle * M_PI / 180.0;&#xD;&#xA;&#xD;&#xA;etc.&#xD;&#xA;&#xD;&#xA;If you want to draw the entire pie wedge, you'll need to iterate from the start angle to the end angle and calculate every `n` degrees along the curve." ContentLicense="CC BY-SA 4.0" />
  <row Id="25118" PostHistoryTypeId="5" PostId="9184" RevisionGUID="af6bfe3d-c967-4948-a612-fcf4d7e37910" CreationDate="2019-09-27T04:22:48.763" UserId="3003" Comment="Added descriptions of what the tools do." Text="There's nothing like frame capture for OpenGL on macOS, unfortunately. But there are 2 other tools that are useful for GL debugging: OpenGL Profiler and OpenGL Driver Monitor. You can read about them [here](https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/opengl_performance.html#//apple_ref/doc/uid/TP40001987-CH213-SW1). (Warning the images in the article are *really* old. They look like normal apps today without all the brushed metal, etc.) To download them, you need to log in to your developer account on developer.apple.com, click on &quot;Downloads&quot; on the left side. On the downloads page in the upper right is a tiny &quot;more&quot; link. If you click on that, you'll get the search tool. Enter &quot;OpenGL Profiler&quot; for your search and you'll be presented with a number of packages for different versions of Xcode. Choose the one that matches whichever version of Xcode you have. It's in the &quot;Graphics Tools&quot; section of the download.&#xD;&#xA;&#xD;&#xA;OpenGL Profiler can show you the resources currently in use by a program. You can set breakpoints on any OpenGL call and when it breaks you can see all textures, shaders, FBOs, etc. and see what their contents are as well as all OpenGL state.&#xD;&#xA;&#xD;&#xA;OpenGL Driver Monitor will graph over time how many textures are in use, or how much texture memory, etc. It can tell you the frequency of page-ons and page-offs for the GPU and other useful statistics." ContentLicense="CC BY-SA 4.0" />
  <row Id="25119" PostHistoryTypeId="2" PostId="9194" RevisionGUID="d66cf2ea-230f-4ec3-b579-c28a58d0d741" CreationDate="2019-09-27T14:40:45.957" UserId="11114" Text="I am solving an image segmentation problem. To increase the accuracy of the model, I came across the following preprocessing step-&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&gt; First, the set of pixels of the exterior border of the ROI is de-&#xD;&#xA;&gt; termined, i.e., pixels that are outside the ROI and are neighbors&#xD;&#xA;&gt; (using four-neighborhood) to pixels inside it. Then, each pixel value&#xD;&#xA;&gt; of this set is replaced with the mean value of its neighbors (this&#xD;&#xA;&gt; time using eight-neighborhood) inside the ROI. Finally, the ROI is&#xD;&#xA;&gt; expanded by inclusion of this altered set of pixels. This process is&#xD;&#xA;&gt; repeated and can be seen as artificially increasing the ROI.&#xD;&#xA;&#xD;&#xA;The image after applying the following algorithm is below-&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Can anyone please help me how to approach this problem, I am pretty much clue-less how to do it, how to detect the boundary of the image.My image is of the following type-&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Any help in solving this kind of problem is highly appreciated.&#xD;&#xA;  [1]: https://i.stack.imgur.com/jgBZe.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sbVhg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25120" PostHistoryTypeId="1" PostId="9194" RevisionGUID="d66cf2ea-230f-4ec3-b579-c28a58d0d741" CreationDate="2019-09-27T14:40:45.957" UserId="11114" Text="Artificially increase the region of interest of an image" ContentLicense="CC BY-SA 4.0" />
  <row Id="25121" PostHistoryTypeId="3" PostId="9194" RevisionGUID="d66cf2ea-230f-4ec3-b579-c28a58d0d741" CreationDate="2019-09-27T14:40:45.957" UserId="11114" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25122" PostHistoryTypeId="2" PostId="9195" RevisionGUID="27c39519-6576-4f0f-b4fb-70c51d04964c" CreationDate="2019-09-28T02:39:55.920" UserId="3003" Text="It looks like your image will always have the same black area due to the mechanism used to take the picture. If that's the case then you don't need to detect the edges. Instead, you can create a static mask ahead of time. The mask can be a single channel image that's white where the eye image is and black elsewhere. You can use that 1 channel mask as the alpha mask for the RGB image you have.&#xD;&#xA;&#xD;&#xA;If the image can move around, it looks to me that you could threshold the red channel and say any red value under 0.1, say, is outside of the eye. Another possibility is just let the user select a circular region for the big circle, and then let them select a smaller one for the bump.&#xD;&#xA;&#xD;&#xA;To expand the ROI once you've got the mask, you can go pixel by pixel and if the mask is black, follow the vector from the current pixel towards the center of the image until you hit a non-black pixel. When you hit one, just copy that pixel to the one you started with. Do that with each pixel that's not in the eye portion of the image." ContentLicense="CC BY-SA 4.0" />
  <row Id="25124" PostHistoryTypeId="50" PostId="8807" RevisionGUID="87725721-a981-4339-bbd1-12e54a822cf2" CreationDate="2019-09-29T00:01:10.103" UserId="-1" />
  <row Id="25125" PostHistoryTypeId="50" PostId="6359" RevisionGUID="8864713d-561a-4108-a24b-ec47957474e1" CreationDate="2019-09-29T10:01:50.240" UserId="-1" />
  <row Id="25126" PostHistoryTypeId="2" PostId="9196" RevisionGUID="7410f783-0c5a-4120-8dd7-cd311c3bad3a" CreationDate="2019-09-29T12:39:37.387" UserId="11114" Text="I have an image of following type-&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I want to create mask of the following type where the inside area is white and rest of it is black. How to do it?&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ayESL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/NzDB9.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25127" PostHistoryTypeId="1" PostId="9196" RevisionGUID="7410f783-0c5a-4120-8dd7-cd311c3bad3a" CreationDate="2019-09-29T12:39:37.387" UserId="11114" Text="How to create static alpha masks of an image" ContentLicense="CC BY-SA 4.0" />
  <row Id="25128" PostHistoryTypeId="3" PostId="9196" RevisionGUID="7410f783-0c5a-4120-8dd7-cd311c3bad3a" CreationDate="2019-09-29T12:39:37.387" UserId="11114" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25129" PostHistoryTypeId="2" PostId="9197" RevisionGUID="d3316532-ec6b-4769-b148-966442090b0a" CreationDate="2019-09-29T20:33:07.340" UserId="3003" Text="You can either use a threshold, or, since you know the location and size of the 2 circles, simply generate one programatically. In this case, you have a circle that's centered at (279, 283.5) and has a radius of 265. (I haven't calculated the center and radius of the smaller circle, but you should be able to do that fairly easily by looking at the image in any image editor that shows you mouse coordinates.)&#xD;&#xA;&#xD;&#xA;Once you have the smaller circle radius, for each pixel in the mask find the distance to the large circle center and if it's less than the large radius, color it white. Otherwise take the distance to the smaller circle and if it's less than the smaller radius, color it white. Otherwise, color it black." ContentLicense="CC BY-SA 4.0" />
  <row Id="25130" PostHistoryTypeId="2" PostId="9198" RevisionGUID="2613a602-5666-4d35-9129-0f4701e5f00a" CreationDate="2019-09-29T20:38:14.647" UserId="10615" Text="All of the above. If you look on matlabs page a little further down, it becomes apparent that matlab initializes a canvas (the screen), then looks for each pixel what is directly behind that screen. This gets rid of perspective. When you set the camera angle to 45 degrees down and 45 degrees left/right, you will get an implicit isometric projection. So really the &quot;projection&quot; just depends on your camera angle.&#xD;&#xA;&#xD;&#xA;Sidenote: if you would want to keep a 3d perspective, you would need to draw the ray from the camera origin to the position on the canvas. That gives the ray the direction it needs to create perspective." ContentLicense="CC BY-SA 4.0" />
  <row Id="25131" PostHistoryTypeId="2" PostId="9199" RevisionGUID="39cf8434-e973-4a25-8921-bc9e96cef0d6" CreationDate="2019-09-29T21:48:29.800" UserId="10615" Text="Let's suppose we have an object consisting of only 3d points, and triangle faces that each take a subset of these 3d points. How can I interpolate the normal vectors to get that Phong smooth shading? The actual algorithm seems impossible to find yet everybody is doing it.&#xD;&#xA;&#xD;&#xA;There is one post on here, but I still have no idea how to implement it: https://computergraphics.stackexchange.com/questions/5097/normal-interpolation-for-phong-shading&#xD;&#xA;&#xD;&#xA;Also, it seems wrong to me that this supposed formula only takes in account two normals. What if you have a triangle surrounded by 3 other triangles? Then how do you blend the normals?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25132" PostHistoryTypeId="1" PostId="9199" RevisionGUID="39cf8434-e973-4a25-8921-bc9e96cef0d6" CreationDate="2019-09-29T21:48:29.800" UserId="10615" Text="What is the algorithm used for phong shading normal interpolation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25133" PostHistoryTypeId="3" PostId="9199" RevisionGUID="39cf8434-e973-4a25-8921-bc9e96cef0d6" CreationDate="2019-09-29T21:48:29.800" UserId="10615" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25134" PostHistoryTypeId="2" PostId="9200" RevisionGUID="a5b5b010-70d9-45f0-91bf-e6f85e1d1d78" CreationDate="2019-09-30T02:06:06.230" UserId="6588" Text="The Phong shading model assumes a surface normal $\mathbf{n}$ at the shading point $\mathbf{x}$ but it is independent of its [type](https://computergraphics.stackexchange.com/questions/5486/whats-the-difference-between-geometric-surface-normal-and-shading-surface-norma), so either the shading normal or the geometric normal will work. Moreover, this reflectance model requires an incoming and outgoing directions. In that sense, you can't just &quot;interpolate the normals&quot; to get the desired effect since you need to take into account the positions of the camera and the light, as well as the roughness parameters.&#xD;&#xA;&#xD;&#xA;The (normalized) Phong BRDF is a sum of a diffuse and specular term:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r(\mathbf{x},\omega_i,\omega_o) = \frac{\rho_d}{\pi} + \rho_s \frac{n+2}{2\pi}\max(0,\cos^n\alpha),&#xD;&#xA;$$&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;* $\rho_d$ is the _diffuse albedo_, i.e. the fraction of the incoming energy that is reflected diffusely,&#xD;&#xA;* $\rho_s$ is the _specular albedo_, i.e. the fraction of the incoming energy that is reflected specularly,&#xD;&#xA;* $n$ is the _Phong exponent_; higher values yield more mirror-like specular reflection, and&#xD;&#xA;* $\alpha$ is the _angle_ between the perfect specular reflection direction $\omega_r$ and the outgoing direction $\omega_o$.&#xD;&#xA;&#xD;&#xA;You can compute $\omega_r$ from the surface normal $\mathbf{n}$ and the lighting direction $\omega_i$, which is just&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\omega_r = 2\mathbf{n}(\mathbf{n}\cdot\omega_i) - \omega_i.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Typically you pick the albedos such that $\rho_d + \rho_s \leqslant 1$ to conserve energy." ContentLicense="CC BY-SA 4.0" />
  <row Id="25135" PostHistoryTypeId="2" PostId="9201" RevisionGUID="447af265-5ca8-40fc-b4ee-6fbfbfa31017" CreationDate="2019-09-30T15:56:03.473" UserId="10615" Text="I currently can not solve a ray-quad intersection with a quad that bends, because it is impossible to solve (because really a quad can't/shouldn't bend).&#xD;&#xA;&#xD;&#xA;Sadly, often times, models with quadrilaterals have impossible surfaces: some quads &quot;bend&quot; rather than be a perfect plane/polygon. You could break the quads up into triangles, but there are two ways to do that. And even then, what do you do with the normals? Keep the quad normal onto the two resulting triangles or just recalculate the normals? What is the industry standard for this process?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25136" PostHistoryTypeId="1" PostId="9201" RevisionGUID="447af265-5ca8-40fc-b4ee-6fbfbfa31017" CreationDate="2019-09-30T15:56:03.473" UserId="10615" Text="How to handle quads?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25137" PostHistoryTypeId="3" PostId="9201" RevisionGUID="447af265-5ca8-40fc-b4ee-6fbfbfa31017" CreationDate="2019-09-30T15:56:03.473" UserId="10615" Text="|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25142" PostHistoryTypeId="5" PostId="9200" RevisionGUID="de85b4cc-334c-4533-96dd-33c2fe5af7fe" CreationDate="2019-09-30T22:52:14.493" UserId="6588" Comment="misunderstood question" Text="EDIT: I misunderstood your question, so please disregard this answer.&#xD;&#xA;&#xD;&#xA;The Phong shading model assumes a surface normal $\mathbf{n}$ at the shading point $\mathbf{x}$ but it is independent of its [type](https://computergraphics.stackexchange.com/questions/5486/whats-the-difference-between-geometric-surface-normal-and-shading-surface-norma), so either the shading normal or the geometric normal will work. Moreover, this reflectance model requires an incoming and outgoing directions. In that sense, you can't just &quot;interpolate the normals&quot; to get the desired effect since you need to take into account the positions of the camera and the light, as well as the roughness parameters.&#xD;&#xA;&#xD;&#xA;The (normalized) Phong BRDF is a sum of a diffuse and specular term:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r(\mathbf{x},\omega_i,\omega_o) = \frac{\rho_d}{\pi} + \rho_s \frac{n+2}{2\pi}\max(0,\cos^n\alpha),&#xD;&#xA;$$&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;* $\rho_d$ is the _diffuse albedo_, i.e. the fraction of the incoming energy that is reflected diffusely,&#xD;&#xA;* $\rho_s$ is the _specular albedo_, i.e. the fraction of the incoming energy that is reflected specularly,&#xD;&#xA;* $n$ is the _Phong exponent_; higher values yield more mirror-like specular reflection, and&#xD;&#xA;* $\alpha$ is the _angle_ between the perfect specular reflection direction $\omega_r$ and the outgoing direction $\omega_o$.&#xD;&#xA;&#xD;&#xA;You can compute $\omega_r$ from the surface normal $\mathbf{n}$ and the lighting direction $\omega_i$, which is just&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\omega_r = 2\mathbf{n}(\mathbf{n}\cdot\omega_i) - \omega_i.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Typically you pick the albedos such that $\rho_d + \rho_s \leqslant 1$ to conserve energy." ContentLicense="CC BY-SA 4.0" />
  <row Id="25143" PostHistoryTypeId="5" PostId="9195" RevisionGUID="0be16bfd-313a-4461-98fa-b8b14995500c" CreationDate="2019-10-01T01:19:02.713" UserId="3003" Comment="Added a better way to do it." Text="It looks like your image will always have the same black area due to the mechanism used to take the picture. If that's the case then you don't need to detect the edges. Instead, you can create a static mask ahead of time. The mask can be a single channel image that's white where the eye image is and black elsewhere. You can use that 1 channel mask as the alpha mask for the RGB image you have.&#xD;&#xA;&#xD;&#xA;If the image can move around, it looks to me that you could threshold the red channel and say any red value under 0.1, say, is outside of the eye. Another possibility is just let the user select a circular region for the big circle, and then let them select a smaller one for the bump.&#xD;&#xA;&#xD;&#xA;To expand the ROI once you've got the mask, you can go pixel by pixel and if the mask is black, follow the vector from the current pixel towards the center of the image until you hit a non-black pixel. When you hit one, just copy that pixel to the one you started with. Do that with each pixel that's not in the eye portion of the image.&#xD;&#xA;&#xD;&#xA;**EDIT**: Given that the mask is static there's an even easier way. In [your other question](https://computergraphics.stackexchange.com/questions/9196/how-to-create-static-alpha-masks-of-an-image) I pointed out that the center of the larger circle was at approximately (279, 283.5) and its radius was approximately 265. So what you could do is simply iterate over all the pixels in the image and if they're farther than 265 pixels away from the center, replace them with the pixel that is 265 pixels away from the center in the same direction. Something like this untested pseudocode:&#xD;&#xA;&#xD;&#xA;    float centerX = 279;&#xD;&#xA;    float centerY = 283.5;&#xD;&#xA;    float radius = 265;&#xD;&#xA;    for (int row = 0; row &lt; MAX_ROWS; row++)&#xD;&#xA;    {&#xD;&#xA;        for (int col = 0; col &lt; MAX_COLS; col++)&#xD;&#xA;        {&#xD;&#xA;            float deltaX = col - centerX;&#xD;&#xA;            float deltaY = row - centerY;&#xD;&#xA;            float dist = sqrt(deltaX * deltaX + deltaY * deltaY);&#xD;&#xA;            if (dist &gt; radius)&#xD;&#xA;            {&#xD;&#xA;                float dirX = deltaX / dist;&#xD;&#xA;                float dirY = delatY / dist;&#xD;&#xA;                float edgeX = centerX + radius * dirX;&#xD;&#xA;                float edgeY = centerY + radius * dirY;&#xD;&#xA;                SetPixel(col, row, GetPixel(edgeX, edgeY));&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note that the smaller circle presents another issue. You can test whether a given pixel is in the big circle as above, and if not, then see what the distance to the smaller circle is. If that distance is smaller than the distance to the larger circle, then get the pixel from the smaller circle rather than the larger one." ContentLicense="CC BY-SA 4.0" />
  <row Id="25144" PostHistoryTypeId="5" PostId="9189" RevisionGUID="29e171cd-a633-4830-9d1d-580f56aeb36c" CreationDate="2019-10-01T04:41:48.513" UserId="11239" Comment="Tried using arc() and line() of graphics.h header file." Text="As we know in C/C++ there is &quot;graphics.h&quot; header file with the help of which we can do graphics programs in C. &#xD;&#xA;There is a function **pieslice** in that header file,its syntax is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#include &lt;graphics.h&gt;&#xD;&#xA;&#xD;&#xA;void pieslice(int x, int y, int stangle, int endangle, int radius);&#xD;&#xA;```&#xD;&#xA;[x,y are the center of the circle,stangle and endangle are the starting and end angles respectively]&#xD;&#xA;&#xD;&#xA;Can we make a pieslice in C/C++ without using this in-built function.Please help. Tried making it with the help of the lines and arc function of the &#xD;&#xA;`graphics.h` but i am still not able to figure out how to connect the lines with the arc. &#xD;&#xA;Thank You in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="25145" PostHistoryTypeId="5" PostId="9189" RevisionGUID="645bd1e7-711a-4404-bc93-9d6eddfb47d8" CreationDate="2019-10-01T05:00:04.133" UserId="11239" Comment="Entered the codes,i have been able to do so far." Text="As we know in C/C++ there is &quot;graphics.h&quot; header file with the help of which we can do graphics programs in C. &#xD;&#xA;There is a function **pieslice** in that header file,its syntax is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#include &lt;graphics.h&gt;&#xD;&#xA;&#xD;&#xA;void pieslice(int x, int y, int stangle, int endangle, int radius);&#xD;&#xA;```&#xD;&#xA;[x,y are the center of the circle,stangle and endangle are the starting and end angles respectively]&#xD;&#xA;&#xD;&#xA;Can we make a pieslice in C/C++ without using this in-built function.Please help. Tried making it with the help of the lines and arc function of the &#xD;&#xA;`graphics.h` but i am still not able to figure out how to connect the lines with the arc. &#xD;&#xA;Thank You in advance.&#xD;&#xA;&#xD;&#xA;My code so far:&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;#include&lt;stdio.h&gt;&#xD;&#xA;#include&lt;graphics.h&gt;&#xD;&#xA;#include&lt;math.h&gt;&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;	int gd=DETECT,gm;&#xD;&#xA;	initgraph(&amp;gd,&amp;gm,NULL);&#xD;&#xA;	int xc,yc,r,st_angle,ed_angle,StartX,StartY;&#xD;&#xA;	printf(&quot;Enter the centers of pieslice:\n&quot;);&#xD;&#xA;	scanf(&quot;%d %d&quot;,&amp;xc,&amp;yc);&#xD;&#xA;	printf(&quot;Enter the radius:\n&quot;);&#xD;&#xA;	scanf(&quot;%d&quot;,&amp;r);&#xD;&#xA;	printf(&quot;Enter the starting angle:\n&quot;);&#xD;&#xA;	scanf(&quot;%d&quot;,&amp;st_angle);&#xD;&#xA;	printf(&quot;Enter the end angle:\n&quot;);&#xD;&#xA;	scanf(&quot;%d&quot;,&amp;ed_angle);&#xD;&#xA;	&#xD;&#xA;	double startRadians = (double)st_angle * M_PI /180.0;&#xD;&#xA;	double endRadians = (double)ed_angle * M_PI /180.0;&#xD;&#xA;&#xD;&#xA;	for(int k=0; k&lt;startRadians;k++)&#xD;&#xA;	{	&#xD;&#xA;		startX = xc+ cos(startRadians) * r;&#xD;&#xA;		startY = yc+ sin(startRadians) * r;&#xD;&#xA;	}&#xD;&#xA;	for(int	l=o; l&lt;endRadians; l++)&#xD;&#xA;	{&#xD;&#xA;		endX = xc+ cos(endRadians) * r;&#xD;&#xA;		endY = yc+ sin(endRadians) * r;&#xD;&#xA;	}&#xD;&#xA; 	&#xD;&#xA;	" ContentLicense="CC BY-SA 4.0" />
  <row Id="25146" PostHistoryTypeId="2" PostId="9203" RevisionGUID="bda84c11-c0b2-4b7f-b4d8-c09b8e80ecf5" CreationDate="2019-10-01T08:27:09.497" UserId="209" Text="It sounds like you want to know how to ray trace ***a bilinear surface patch***.&#xD;&#xA;&#xD;&#xA;A quick search [turned up this page][1] by Ramsey, Potter &amp; Hansen, which includes a [paper][2] and, probably better still, *source code*!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.utah.edu/~ramsey/bp/&#xD;&#xA;  [2]: https://www.cs.utah.edu/~ramsey/bp/ramseybilinear.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="25147" PostHistoryTypeId="5" PostId="9203" RevisionGUID="35dd33d4-c784-45d8-a40e-bbe66baf3cc5" CreationDate="2019-10-01T08:37:08.407" UserId="209" Comment="Added alternative" Text="It sounds like you want to know how to ray trace ***a bilinear surface patch***.&#xD;&#xA;&#xD;&#xA;A quick search [turned up this page][1] by Ramsey, Potter &amp; Hansen, which includes a [paper][2] and, probably better still, *source code*!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, if you just want a &quot;cheap and cheerful&quot; &lt;strike&gt;hack&lt;/strike&gt; approach, you could try replacing the quad with **4** triangles. That is, by a new vertex at the 'centre' (i.e. computing the average of the corners) and joining each edge to that new vertex. This is generally produces a better looking, and order-independent result that just using a pair of triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.utah.edu/~ramsey/bp/&#xD;&#xA;  [2]: https://www.cs.utah.edu/~ramsey/bp/ramseybilinear.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="25148" PostHistoryTypeId="2" PostId="9204" RevisionGUID="ee4de137-f664-45ba-a478-95c9c8a99a67" CreationDate="2019-10-01T20:04:48.853" UserId="11255" Text="Given the **Point A** with the coordinates ```gl_FragCoord.xy```, I have to find the distance to the **Center** of the cube face to which it belongs in screen coordinates.&#xD;&#xA;&#xD;&#xA;Specifically what I need is the formula to convert the **Center** of every face of the cube in screen coordinates, in order to compare it with ```gl_FragCoord```.&#xD;&#xA;&#xD;&#xA;This the fragment shader:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;&#xD;&#xA;    uniform vec2 u_resolution;&#xD;&#xA;    &#xD;&#xA;    varying vec2 v_uv;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;      gl_FragColor = vec4(v_uv.x, v_uv.y, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This the vertex shader:&#xD;&#xA;&#xD;&#xA;    precision mediump float;&#xD;&#xA;&#xD;&#xA;    attribute vec3 a_position;&#xD;&#xA;    attribute vec2 a_uv;&#xD;&#xA;&#xD;&#xA;    uniform mat4 u_view;&#xD;&#xA;    uniform mat4 u_projection;&#xD;&#xA;&#xD;&#xA;    varying vec2 v_uv;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;      v_uv = a_uv;&#xD;&#xA;&#xD;&#xA;      gl_Position = u_projection * u_view * vec4(a_position, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NMCNY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25149" PostHistoryTypeId="1" PostId="9204" RevisionGUID="ee4de137-f664-45ba-a478-95c9c8a99a67" CreationDate="2019-10-01T20:04:48.853" UserId="11255" Text="Calculate the distance between two 3d points in screen coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="25150" PostHistoryTypeId="3" PostId="9204" RevisionGUID="ee4de137-f664-45ba-a478-95c9c8a99a67" CreationDate="2019-10-01T20:04:48.853" UserId="11255" Text="|opengl|shader|glsl|webgl|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25151" PostHistoryTypeId="6" PostId="9204" RevisionGUID="63020754-90d0-499f-8e7a-ec181eae19ad" CreationDate="2019-10-01T20:35:27.157" UserId="2654" Comment="edited tags" Text="|shader|glsl|webgl|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25153" PostHistoryTypeId="2" PostId="9205" RevisionGUID="8eaa8812-effe-4c47-8e65-5c9deb1a862b" CreationDate="2019-10-01T22:34:12.757" UserId="11256" Text="In [Phong shading](https://en.wikipedia.org/wiki/Phong_shading) model (and other shading models as well), the light color is multiplied together with the surface color component-wise. I want to know the justification for this. Is this some what related to the physics of light?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25154" PostHistoryTypeId="1" PostId="9205" RevisionGUID="8eaa8812-effe-4c47-8e65-5c9deb1a862b" CreationDate="2019-10-01T22:34:12.757" UserId="11256" Text="What's the justification of multiplying colors together?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25155" PostHistoryTypeId="3" PostId="9205" RevisionGUID="8eaa8812-effe-4c47-8e65-5c9deb1a862b" CreationDate="2019-10-01T22:34:12.757" UserId="11256" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25156" PostHistoryTypeId="2" PostId="9206" RevisionGUID="1d7f07ac-f89b-483d-827d-296e34b28e11" CreationDate="2019-10-02T08:52:19.420" UserId="137" Text="When you multiply colors together the surface color acts as a filter.&#xD;&#xA;&#xD;&#xA;That way with white incoming light a green object will remain looking green.&#xD;&#xA;&#xD;&#xA;This does bring a few issues because physical light isn't as orthogonal (where the 3 primary colors are actually overlapping frequency response functions) but for the vast majority of cases you can tweak the values enough for it to stay looking realistic." ContentLicense="CC BY-SA 4.0" />
  <row Id="25157" PostHistoryTypeId="5" PostId="9203" RevisionGUID="99779b5d-bbd2-4568-990e-6a3220567219" CreationDate="2019-10-02T09:55:05.433" UserId="209" Comment="fixed typo" Text="It sounds like you want to know how to ray trace ***a bilinear surface patch***.&#xD;&#xA;&#xD;&#xA;A quick search [turned up this page][1] by Ramsey, Potter &amp; Hansen, which includes a [paper][2] and, probably better still, *source code*!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, if you just want a &quot;cheap and cheerful&quot; &lt;strike&gt;hack&lt;/strike&gt; approach, you could try replacing the quad with **4** triangles. That is, by a new vertex at the 'centre' (i.e. computing the average of the corners) and joining each edge to that new vertex. This is generally produces a better looking, and order-independent result than just using a pair of triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.utah.edu/~ramsey/bp/&#xD;&#xA;  [2]: https://www.cs.utah.edu/~ramsey/bp/ramseybilinear.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="25158" PostHistoryTypeId="5" PostId="9206" RevisionGUID="15bc28ae-13b3-4dd3-918c-c66ede4db9d1" CreationDate="2019-10-02T10:20:59.457" UserId="137" Comment="added 45 characters in body" Text="When you multiply colors together the surface color acts as a filter. Remember that colors are scaled from 0 to 1.&#xD;&#xA;&#xD;&#xA;That way with white incoming light a green object will remain looking green.&#xD;&#xA;&#xD;&#xA;This does bring a few issues because physical light isn't as orthogonal (where the 3 primary colors are actually overlapping frequency response functions) but for the vast majority of cases you can tweak the values enough for it to stay looking realistic." ContentLicense="CC BY-SA 4.0" />
  <row Id="25159" PostHistoryTypeId="2" PostId="9207" RevisionGUID="2eb470fb-6327-4b1a-b80f-739e3ba24cd2" CreationDate="2019-10-02T20:34:00.397" UserId="9562" Text="I have a set of unordered points that I'm getting from an image attached. I'd like to simply fit a parametrized curve such as a catmull-rom curve to with n control points (n = 4 to 10, and can be assumed to be known). &#xD;&#xA;&#xD;&#xA;I've explored ways of doing this and it seems there doesn't seem to be some library function that simply does this. I explore b-spline fitting (as I read that it's possible to convert b-spline to catmull-rom afterwards) with scipy that simply seems to unable to fit this properly.&#xD;&#xA;&#xD;&#xA;    import scipy.interpolate as interpolate&#xD;&#xA;    tck, u = interpolate.splprep([x, y], s=6)&#xD;&#xA;    &#xD;&#xA;    N = 100&#xD;&#xA;    xmin, xmax = 0, 1.01&#xD;&#xA;    unew = np.linspace(xmin, xmax, N)&#xD;&#xA;    spline = interpolate.splev(unew, tck)&#xD;&#xA;    &#xD;&#xA;    plt.plot(x, y, 'bo', label='Original points')&#xD;&#xA;    plt.plot(spline[0], spline[1], 'r', label='BSpline')&#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm now thinking of doing a robust regression approach now [(https://scipy-cookbook.readthedocs.io/items/robust_regression.html][1]). But, I'm lost on how to convert my set of [x, y] points to a parametric formulation for catmull-rom spline to write the loss function needed for least squares fit. &#xD;&#xA;&#xD;&#xA;Any help is appreciated with a relevant code sample.&#xD;&#xA;&#xD;&#xA;Result:&#xD;&#xA;[![as][2]][2].&#xD;&#xA;&#xD;&#xA;Original:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://scipy-cookbook.readthedocs.io/items/robust_regression.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/9Qc1y.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/j3hxf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25160" PostHistoryTypeId="1" PostId="9207" RevisionGUID="2eb470fb-6327-4b1a-b80f-739e3ba24cd2" CreationDate="2019-10-02T20:34:00.397" UserId="9562" Text="Non least squares formulation to fit catmull rom spline" ContentLicense="CC BY-SA 4.0" />
  <row Id="25161" PostHistoryTypeId="3" PostId="9207" RevisionGUID="2eb470fb-6327-4b1a-b80f-739e3ba24cd2" CreationDate="2019-10-02T20:34:00.397" UserId="9562" Text="|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25163" PostHistoryTypeId="2" PostId="9208" RevisionGUID="af1b5a1c-045b-488e-b9b9-a4d1fd0da141" CreationDate="2019-10-03T00:38:51.523" UserId="11259" Text="I was trying to determine if an object (sphere) is inside a view frustum. My strategy was first to get the view matrix:&#xD;&#xA;```&#xD;&#xA;glm::lookAt(cameraPosition, lookAtPosition, cameraUp);&#xD;&#xA;```&#xD;&#xA;Where `cameraPosition` is the position of the camera, `lookAtPosition` is calculate by `cameraPosition + cameraDirection` and `cameraUp` is pretty much self-explanatory.&#xD;&#xA;&#xD;&#xA;After obtaining the view matrix, I calculate the 8 vertices of the frustum in the camera view, then multiply the inverse of the view matrix by each point to get the coordinate of them in the world space.&#xD;&#xA;&#xD;&#xA;Using these 8 points in the world space, I can construct the 6 planes by using cross products (so their normals will point inward). Then I take the dot product of the object vector (I get the vector by subtracting the object position with an arbitrary point on that plane) with the normal vector of each plane, if it is positive for all 6, I know it's inside the frustum.&#xD;&#xA;&#xD;&#xA;So my questions are:&#xD;&#xA;&#xD;&#xA;* Is the camera view is always set at (0,0,0) and looking at the positive z direction?&#xD;&#xA;* The view matrix transform the world view into the camera view, if I use the inverse of it to transform the camera view to the world view, is it correct?&#xD;&#xA;&#xD;&#xA;My frustum is opposite with my `cameraDirection` which causes nothing to be seen on the screen (but it still drawing stuff in the back of my camera)." ContentLicense="CC BY-SA 4.0" />
  <row Id="25164" PostHistoryTypeId="1" PostId="9208" RevisionGUID="af1b5a1c-045b-488e-b9b9-a4d1fd0da141" CreationDate="2019-10-03T00:38:51.523" UserId="11259" Text="About view matrix and frustum culling" ContentLicense="CC BY-SA 4.0" />
  <row Id="25165" PostHistoryTypeId="3" PostId="9208" RevisionGUID="af1b5a1c-045b-488e-b9b9-a4d1fd0da141" CreationDate="2019-10-03T00:38:51.523" UserId="11259" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25166" PostHistoryTypeId="50" PostId="8359" RevisionGUID="f4ddf6b1-cec4-444e-8250-b339c17de3a9" CreationDate="2019-10-03T05:00:37.680" UserId="-1" />
  <row Id="25167" PostHistoryTypeId="2" PostId="9209" RevisionGUID="36874608-96ef-4ffc-947e-76c9cf60f1d0" CreationDate="2019-10-03T20:22:01.893" UserId="38" Text="It is  common that the camera is pointing towards negative Z, in order to satisfy right hand rule. So you need to know the convention.&#xD;&#xA;&#xD;&#xA;As for theinverse matrix of the camera matrix. Sort of yes. You can do it. However the camera matrix is a homogeneous space. While generally our other matrixes are affine spaces. If you take care of the distinction and do the proper camera divide, if tge camera needs one. Then yes you could do that." ContentLicense="CC BY-SA 4.0" />
  <row Id="25168" PostHistoryTypeId="2" PostId="9210" RevisionGUID="6d1eb181-94d7-477d-a9ce-2a1f8a3fe4a8" CreationDate="2019-10-03T20:44:14.147" UserId="11265" Text="I am currently implementing the GGX specular BRDF in a DXR raytracer using the importance sampling method describe by [Heitz](http://jcgt.org/published/0007/04/01/paper.pdf)&#xD;&#xA;&#xD;&#xA;I am sampling the VNDF with:&#xD;&#xA;&#xD;&#xA;```hlsl&#xD;&#xA;//https://hal.archives-ouvertes.fr/hal-01509746/document&#xD;&#xA;inline float3 VNDF_GGX(in float3 wo, float roughness2, float rand1, float rand2)&#xD;&#xA;{&#xD;&#xA;    //Strecht view vector&#xD;&#xA;    float3 view = normalize(float3(wo.x * roughness2, wo.y, wo.z * roughness2));&#xD;&#xA;&#xD;&#xA;    //Orthonormal basis&#xD;&#xA;    float3 lensq = pow(view.x, 2) + pow(view.z, 2);&#xD;&#xA;    float3 t1 = (lensq &gt; 0.0f) ? normalize(cross(view, float3(0.0f, 1.0f, 0.0f))) : float3(1, 0, 0);&#xD;&#xA;    float3 t2 = cross(view, t1);&#xD;&#xA;&#xD;&#xA;    //project&#xD;&#xA;    float r = sqrt(rand1);&#xD;&#xA;    float phi = 2.0f * pi * rand2;&#xD;&#xA;    float p1 = r * cos(phi);&#xD;&#xA;    float p2 = r * sin(phi);&#xD;&#xA;&#xD;&#xA;    float s = 0.5f * (1.0f + view.y);&#xD;&#xA;    p2 = (1.0f - s) * sqrt(1.0f - pow(p1, 2.0f)) + s * p2;&#xD;&#xA;&#xD;&#xA;    float3 n = p1 * t1 + p2 * t2 + sqrt(max(0.0f, 1.0f - pow(p1, 2.0f) - pow(p2, 2.0f))) * view;&#xD;&#xA;&#xD;&#xA;    //unstrech normal and renormalize&#xD;&#xA;    float3 n_out = normalize(float3(roughness2 * n.x, max(0.0f, n.y), roughness2 * n.z));&#xD;&#xA;&#xD;&#xA;    return n_out;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;where wo is the view direction in tangent space, roughness2 is the material roughness [0;1] squared and rand1/rand2 are uniform random numbers [0;1] sampled from a texture. I am using the exact algorithm described by Heitz except using y-up instead of z-up.&#xD;&#xA;&#xD;&#xA;Using the microfacet normal  **_m_** calculated like this I then acquire the sample direction **_wi_** by reflecting the world ray direction **_-wo_** in tangent space about the microfacet normal **_m_**.&#xD;&#xA;&#xD;&#xA;```hlsl&#xD;&#xA;void ImportanceSampleGGXVNDF(float3 wo, Material material, inout float3 wi, inout float reflectance, float2 randSeed, bool isInVec, inout float fschlick)&#xD;&#xA;{&#xD;&#xA;    float roughness2 = pow(material.roughness, 2.0f);&#xD;&#xA;    float3 m = VNDF_GGX(wo, roughness2, randSeed.x, randSeed.y);&#xD;&#xA;&#xD;&#xA;    wi = normalize(reflect(-wo, m));&#xD;&#xA;&#xD;&#xA;    float3 normalTangentSpace = float3(0.0f, 1.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;    fschlick = FresnelSchlick(m, wi, isInVec ? material.ior1 : 1.0f, isInVec ? 1.0f : material.ior1);&#xD;&#xA;    float G1 = SmithMaskingGGX(wi, wo, normalTangentSpace, pow(roughness2, 2));&#xD;&#xA;    float G2 = SmithShdowingGGX(wo, wi, normalTangentSpace, pow(roughness2, 2));&#xD;&#xA;&#xD;&#xA;    reflectance = fschlick *(G2 / G1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;Where wo is the view direction, wi is the sample direction in tangent space, reflectance equaling the BRDF term (everything else cancels out according to Heitz! See [here](https://schuttejoe.github.io/post/ggximportancesamplingpart2/) details of the derivation)&#xD;&#xA;&#xD;&#xA;This however seems to be producing invalid sampling Directions for ray directions with negative values in y or z component resulting in invalid light probes.&#xD;&#xA;&#xD;&#xA;[![invalid samples for negative z direction][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UMbMB.png&#xD;&#xA;&#xD;&#xA;Comparing with similar implementations (including: [here](https://gist.github.com/mebiusbox/32995b0d133a82a05b4023e512addb77) implementing the exact same method, [here](https://github.com/NVIDIA/Q2RTX/issues/40) also implementing the same method and [here](https://github.com/TheRealMJP/DXRPathTracer/blob/master/SampleFramework12/v1.02/Shaders/Sampling.hlsl) using an algorithm described in an older paper also published by [Heitz](https://hal.archives-ouvertes.fr/hal-01509746/document)) sadly yielded no solution.&#xD;&#xA;&#xD;&#xA;The final output color is computed via&#xD;&#xA;```hlsl&#xD;&#xA;    ImportanceSampleGGXVNDF(tangentSpaceDir, halfVec, l_materialCB[0], rayDir, reflectance, rand, isInVec, fschlick);&#xD;&#xA;&#xD;&#xA;    newRayDir = tangentToWorldSpace(rayDir, tangent, bitangent, triangleNormal);&#xD;&#xA;&#xD;&#xA;    ray.Direction = newRayDir;&#xD;&#xA;    ray.TMin = 0.0001f;&#xD;&#xA;    ray.TMax = 10000.0; //Maximum travel distance of ray&#xD;&#xA;    reflected = TraceReflectiveRay(ray, currNumRecursions);&#xD;&#xA;           &#xD;&#xA;    reflected *= reflectance;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="25169" PostHistoryTypeId="1" PostId="9210" RevisionGUID="6d1eb181-94d7-477d-a9ce-2a1f8a3fe4a8" CreationDate="2019-10-03T20:44:14.147" UserId="11265" Text="Implementing GGX VNDF importance sampling with DXR" ContentLicense="CC BY-SA 4.0" />
  <row Id="25170" PostHistoryTypeId="3" PostId="9210" RevisionGUID="6d1eb181-94d7-477d-a9ce-2a1f8a3fe4a8" CreationDate="2019-10-03T20:44:14.147" UserId="11265" Text="|raytracing|rendering|shader|brdf|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25171" PostHistoryTypeId="50" PostId="9103" RevisionGUID="9f79579d-423c-438a-81d7-904bb0afadd7" CreationDate="2019-10-03T22:01:10.187" UserId="-1" />
  <row Id="25173" PostHistoryTypeId="2" PostId="9211" RevisionGUID="9642e06d-2fee-4d9c-ad9f-fdbea60b703e" CreationDate="2019-10-04T09:32:23.427" UserId="209" Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_N]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**N points, $\small P=[P_0,P_1,...P_{2N-1}]$, and replaces it with two sequences of N points each: a *low frequency* set, $\small L=[L_0,...L_{N-1}]$, and a high frequency set, $\small H=[H_0,...H_{N-1}]$. &#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - the simplest being the Haar wavelet - but I think a linear wavelet might be suitable. *(There may be other, higher order wavelets which may be superior for your use case, but linear is likely to be good enough.)*&#xD;&#xA;&#xD;&#xA;For each linear decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms:&#xD;&#xA;$$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;&#xD;&#xA;followed by an 'update':&#xD;&#xA;$$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{2}$$&#xD;&#xA;&#xD;&#xA;&gt;Notes: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array).&lt;br&gt;&#xD;&#xA;Also, I've glossed over what happens when exceeding the bounds of the arrays, i.e. at $P_{2N}$ and $L_{-1}$, but one approach is to repeat and/or pad with zeros.&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the Low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of points will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;More notes: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, repeat them in the source sequence?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25174" PostHistoryTypeId="5" PostId="9211" RevisionGUID="670d68e2-97cf-4b74-9df3-80b414ae10ec" CreationDate="2019-10-04T09:39:20.903" UserId="209" Comment="added 31 characters in body" Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_N]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**N points, $\small P=[P_0,P_1,...P_{2N-1}]$, and replaces it with two sequences of N points each: a *low frequency* set, $\small L=[L_0,...L_{N-1}]$, and a high frequency set, $\small H=[H_0,...H_{N-1}]$. &#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - the simplest being the Haar wavelet - but I think a linear wavelet might be suitable. *(There may be other, higher order wavelets which may be superior for your use case, but linear is likely to be good enough.)*&#xD;&#xA;&#xD;&#xA;For each linear decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms:&#xD;&#xA;$$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;&#xD;&#xA;followed by an 'update':&#xD;&#xA;$$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{2}$$&#xD;&#xA;&#xD;&#xA;&gt;Notes: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array.&lt;br&gt;&#xD;&#xA;Also, I've glossed over what happens when exceeding the bounds of the arrays, i.e. at $P_{2N}$ and $L_{-1}$, but one approach is to simply repeat values and/or pad with zeros.&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of low frequency points, L, will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;More notes: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, repeat them in the source sequence?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25175" PostHistoryTypeId="2" PostId="9212" RevisionGUID="fd739658-8d4b-4ebe-95fa-a2eff1a52a60" CreationDate="2019-10-04T09:45:35.743" UserId="9420" Text="Full disclaimer, this was a test question, but I couldn't find any information online.&#xD;&#xA;&#xD;&#xA;In my opinion, this depends on if the primitive assembly stage happens before or after perspective division. If before, then it must be in homogeneous clip space. If after, NDC space.&#xD;&#xA;&#xD;&#xA;Which of the two is it? Or am I completely wrong and its neither?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25176" PostHistoryTypeId="1" PostId="9212" RevisionGUID="fd739658-8d4b-4ebe-95fa-a2eff1a52a60" CreationDate="2019-10-04T09:45:35.743" UserId="9420" Text="In the rendering pipeline, in what coordinate space are vertices when they arrive at the primitive assembly stage?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25177" PostHistoryTypeId="3" PostId="9212" RevisionGUID="fd739658-8d4b-4ebe-95fa-a2eff1a52a60" CreationDate="2019-10-04T09:45:35.743" UserId="9420" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25178" PostHistoryTypeId="2" PostId="9213" RevisionGUID="90b35b59-0c9d-4a3d-b81b-344f1fdc03a8" CreationDate="2019-10-04T10:11:15.477" UserId="7008" Text="According to [Khronos' wiki][1] the primitive assembly happens after clipping, which includes the following:&#xD;&#xA;&#xD;&#xA;&gt; The vertex positions are transformed from clip-space to window space via the Perspective Divide and the Viewport Transform.&#xD;&#xA;&#xD;&#xA;[Window Space][2] is described as the space after the viewport transform and that means after NDC space:&#xD;&#xA;&#xD;&#xA;&gt; The viewport transform defines the transformation of vertex positions from NDC space to window space. These are the coordinates that are rasterized to the output image.&#xD;&#xA;&#xD;&#xA;Since the viewport transform includes a scaling for the width and height of the viewport, as well as a translation with the viewports position on screen, you should end up with pixel coordiantes of your screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Viewport_transform" ContentLicense="CC BY-SA 4.0" />
  <row Id="25179" PostHistoryTypeId="5" PostId="9213" RevisionGUID="e87e53a7-17f6-4877-94eb-0eb323c1e9fa" CreationDate="2019-10-04T11:05:27.920" UserId="7008" Comment="corrected a logical error as suggested by Simon F; corrected the new source" Text="As pointed out by Simon F, the clipping stage needs to clip against edges (and thus triangles/primitives). Thus the primitive assembly stage cannot happen after clipping, even though the Pipeline is described such that primitive assembly happens after clipping.&#xD;&#xA;&#xD;&#xA;Slide 16 of Ohio university's Han-Wei Shen's 2010 course [The OpenGL Rendering Pipeline][1] suggests that vertices are transformed to Clip Space, then the primitive assembly happens and only afterwards is clipping actually done.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;s&gt;According to [Khronos' wiki][2] the primitive assembly happens after clipping, which includes the following:&lt;/s&gt;&#xD;&#xA;&#xD;&#xA;&gt; The vertex positions are transformed from clip-space to window space via the Perspective Divide and the Viewport Transform.&#xD;&#xA;&#xD;&#xA;[Window Space][3] is described as the space after the viewport transform and that means after NDC space:&#xD;&#xA;&#xD;&#xA;&gt; The viewport transform defines the transformation of vertex positions from NDC space to window space. These are the coordinates that are rasterized to the output image.&#xD;&#xA;&#xD;&#xA;Since the viewport transform includes a scaling for the width and height of the viewport, as well as a translation with the viewports position on screen, you should end up with pixel coordiantes of your screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://web.cse.ohio-state.edu/~shen.94/781/Site/Slides_files/pipeline.pdf&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Viewport_transform" ContentLicense="CC BY-SA 4.0" />
  <row Id="25180" PostHistoryTypeId="2" PostId="9214" RevisionGUID="94e68ce1-58b4-45ad-8701-a7627751358a" CreationDate="2019-10-04T21:53:10.493" UserId="6346" Text="In a tutorial about OpenGL both words are mentioned, unfortunately without a good explanation.&lt;br&gt;&#xD;&#xA;To find out, I have read [this article][1] three times, but I fear I'm a too common man... my understanding is this:&lt;br&gt;&#xD;&#xA;The video frame is rectangular, and the camera can't take the complete scene, so everything outside the camera's rectangular view is &quot;cut&quot; - or &quot;clipped&quot;.&lt;br&gt;&#xD;&#xA;&#xD;&#xA;On the other hand, &quot;culling&quot; means that those polygons are dismissed in further calculation that can't be seen anyway, because of other polygons in the foreground.&#xD;&#xA;&#xD;&#xA;I guess this is what the linked article tries to describe in summary items 1. and 2. Correct?&#xD;&#xA;&#xD;&#xA;What I still don't get are these points:&#xD;&#xA;&#xD;&#xA;&gt; 4.When compared to culling, clipping establishes the highest polygon. In video games, more of the clipping method is used than the culling&#xD;&#xA;&gt; technique.&#xD;&#xA;&#xD;&#xA;So... I have a choice whether to use culling *or* clipping? Then my understanding above is wrong...?&#xD;&#xA;&#xD;&#xA;&gt; 5.The clipping technique is used when the objects are partially visible. By utilizing the clipping technique, the video quality is&#xD;&#xA;&gt; increased and the frame rate is improved. Moreover, clipping also&#xD;&#xA;&gt; increases the presentation speed.&#xD;&#xA;&#xD;&#xA;I understand that framerate increases when I don't have to waste time calculating polygons I don't need (which applies to both clipping and culling).&lt;br&gt;&#xD;&#xA;But how does this increase video quality?&lt;br&gt;&#xD;&#xA;And why should clipping do so, but culling not? Or does it? &#xD;&#xA;&#xD;&#xA;  [1]: http://www.differencebetween.net/technology/software-technology/difference-between-clipping-and-culling/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25181" PostHistoryTypeId="1" PostId="9214" RevisionGUID="94e68ce1-58b4-45ad-8701-a7627751358a" CreationDate="2019-10-04T21:53:10.493" UserId="6346" Text="What's the difference between Clipping and Culling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25182" PostHistoryTypeId="3" PostId="9214" RevisionGUID="94e68ce1-58b4-45ad-8701-a7627751358a" CreationDate="2019-10-04T21:53:10.493" UserId="6346" Text="|opengl|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25184" PostHistoryTypeId="2" PostId="9215" RevisionGUID="d96e2818-635c-42b4-8b1e-746135f2e4b6" CreationDate="2019-10-05T00:07:46.663" UserId="2654" Text="When it comes to graphics, the term &quot;culling&quot; by itself doesn't really have a single definition or location within the pipeline. The term is sometimes applied to primitives and it is sometimes applied to fragments. It is sometimes applied to faces based on orientation relative to the camera, and it is sometimes applied to primitives based on various parameters. So it's not useful to talk about &quot;culling&quot; as though it is a single thing; there are a lot of things called &quot;culling&quot;.&#xD;&#xA;&#xD;&#xA;By contrast, &quot;clipping&quot; with regard to the graphics pipeline is almost always used to refer to [what happens to the vertices of primitives after any programmable shading, but before rasterization][1]. Clipping happens differently for different kinds of primitives, but the basic idea is to take a primitive and split it into one or more primitives, such that all of the new primitives are *entirely* within the clip-space volume.&#xD;&#xA;&#xD;&#xA;If a primitive is partially outside of the clip-space boundary, the process of clipping creates one or more new triangles that are entirely within that boundary. The clip-space boundary, through [the viewport transform][2], defines everything which is visible with the current rendering state, so if something is outside of the clip-space boundary, it is not visible. Well, in theory; in practice, there are ways to draw stuff outside of the viewport (point size, line width, multisampling, etc), but nevermind those now.&#xD;&#xA;&#xD;&#xA;Now this describes the abstract model of how OpenGL and similar specifications talk about rendering. What actually happens in the hardware is often a different matter. Because clipping has the potential to generate many primitives from one (and thus make the pipeline choke a bit, since it has to run more rasterization cycles), hardware tends to avoid performing actual clipping unless absolutely necessary. So the notion that it is a performance optimization is not really true.&#xD;&#xA;&#xD;&#xA;Note that a primitive which is entirely outside of the clip-space boundary gets clipped into nothingness. This particular case is often called &quot;culling&quot; the primitive, which is why the terms sometimes get used in similar places. Point primitives are either rasterized or culled; they don't ever undergo real clipping (since there is only one vertex). But overall, this process of reducing primitives to those within the clip-space boundary is referred to as &quot;clipping&quot;, not &quot;culling&quot;.&#xD;&#xA;&#xD;&#xA;Clipping also allows users to [define some user-defined clipping parameters][3], which clip primitives based on values provided by the previous vertex processing stages. You can use these to implement clipping planes, such that primitives are clipped at the intersection of an invisible plane. All parts of a primitive on one side of the plane are visible, but not on the other side.&#xD;&#xA;&#xD;&#xA;Things which are referred to as &quot;culling&quot; formally within rendering APIs:&#xD;&#xA;&#xD;&#xA;* [Face culling][4]. Discarding triangle primitives based on their winding order relative to the viewport.&#xD;&#xA;* Vertex-based culling (a relatively new feature), whereby entire primitives can be culled based on vertex processing parameters.&#xD;&#xA;&#xD;&#xA;The article you're talking about seems to mostly equate &quot;culling&quot; with visibility culling techniques. These are computations implemented by user code which chooses to render or not render an object based on whether it is visible. These can range from the very simple frustum culling test (ie: asking if the object is even close to the visible region) to complex BSP systems or portal visibility culling (which attempt to detect if objects are entirely behind static geometry). But these are not part of the GPU's rendering pipeline, even if GPU processes are sometimes used to do such testing.&#xD;&#xA;&#xD;&#xA;Overall, that article gets more wrong than it does right, so it's best to just pretend you never read it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Clipping&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Viewport_transform&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#User-defined_clipping&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Face_Culling" ContentLicense="CC BY-SA 4.0" />
  <row Id="25185" PostHistoryTypeId="2" PostId="9216" RevisionGUID="048477a6-2c56-4b38-81f4-01cda1a3067f" CreationDate="2019-10-05T04:16:22.733" UserId="11268" Text="Is there a way when looking at the source of a glTF file that you can determine what the boundingBox values of the object are?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25186" PostHistoryTypeId="1" PostId="9216" RevisionGUID="048477a6-2c56-4b38-81f4-01cda1a3067f" CreationDate="2019-10-05T04:16:22.733" UserId="11268" Text="Determining the Bounding Box values of a glTF file" ContentLicense="CC BY-SA 4.0" />
  <row Id="25187" PostHistoryTypeId="3" PostId="9216" RevisionGUID="048477a6-2c56-4b38-81f4-01cda1a3067f" CreationDate="2019-10-05T04:16:22.733" UserId="11268" Text="|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25194" PostHistoryTypeId="2" PostId="9219" RevisionGUID="1ec3de5d-80d0-4c73-9ed4-f0f618eb01df" CreationDate="2019-10-05T20:00:11.100" UserId="11119" Text="I've tried looking everywhere, but I just don't get it. How is multiple shaders assigned to a mesh if you can only bind a single shader in OpenGL?&#xD;&#xA;&#xD;&#xA;Assume I have a mesh with a texture shader and now I do a ray-cast from the mouse position to select the object from the editor. In this case I would like to apply a selection shader that highlights that the mesh is selected, but still preserves the texture shader of the mesh. &#xD;&#xA;&#xD;&#xA;I want to apply the selection shader on top of the texture shader of the mesh. How is this generally done in game engines?&#xD;&#xA;&#xD;&#xA;One way of doing this would be to make a completely third shader that is combination of both shaders and just apply the third shader. But that doesn't seem efficient and would become tedious when trying to add new shaders; now you have to specify a selection shader for every shader in the game, in case it's selected in the editor.&#xD;&#xA;&#xD;&#xA;Any help is appreciated and if you can guide to some reading material that would be amazing.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25195" PostHistoryTypeId="1" PostId="9219" RevisionGUID="1ec3de5d-80d0-4c73-9ed4-f0f618eb01df" CreationDate="2019-10-05T20:00:11.100" UserId="11119" Text="How to render multiple shaders per mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="25196" PostHistoryTypeId="3" PostId="9219" RevisionGUID="1ec3de5d-80d0-4c73-9ed4-f0f618eb01df" CreationDate="2019-10-05T20:00:11.100" UserId="11119" Text="|opengl|rendering|shader|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25197" PostHistoryTypeId="2" PostId="9220" RevisionGUID="8b0cc331-0091-4f84-91a1-98aced0ffe02" CreationDate="2019-10-05T20:03:12.173" UserId="7950" Text="I'm trying to implement Oren-Nayar reflectance and I don't quite understand the Wikipedia article on it.&#xD;&#xA;&#xD;&#xA;In the article, it has this diagram:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2jinS.png&#xD;&#xA;&#xD;&#xA;I can't figure out what ϴi, ϴr, ϕi, or ϕr represent. They are used in the equation.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="25198" PostHistoryTypeId="1" PostId="9220" RevisionGUID="8b0cc331-0091-4f84-91a1-98aced0ffe02" CreationDate="2019-10-05T20:03:12.173" UserId="7950" Text="Oren-Nayar Reflectance" ContentLicense="CC BY-SA 4.0" />
  <row Id="25199" PostHistoryTypeId="3" PostId="9220" RevisionGUID="8b0cc331-0091-4f84-91a1-98aced0ffe02" CreationDate="2019-10-05T20:03:12.173" UserId="7950" Text="|raytracing|brdf|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25200" PostHistoryTypeId="5" PostId="9220" RevisionGUID="aad885f4-e5f7-40e2-8094-feae517bb030" CreationDate="2019-10-05T21:40:12.877" UserId="10096" Comment="LaTeX the theta and phi" Text="I'm trying to implement Oren-Nayar reflectance and I don't quite understand the Wikipedia article on it.&#xD;&#xA;&#xD;&#xA;In the article, it has this diagram:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2jinS.png&#xD;&#xA;&#xD;&#xA;I can't figure out what $(\theta_i, \phi_i)$ and $(\theta_r, \phi_r)$ represent. They are used in the equation.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="25201" PostHistoryTypeId="24" PostId="9220" RevisionGUID="aad885f4-e5f7-40e2-8094-feae517bb030" CreationDate="2019-10-05T21:40:12.877" Comment="Proposed by 10096 approved by 7950 edit id of 494" ContentLicense="CC BY-SA 4.0" />
  <row Id="25202" PostHistoryTypeId="2" PostId="9221" RevisionGUID="b0f9c98d-d7b4-4aa2-a1f3-4ab20fd0d963" CreationDate="2019-10-06T00:20:30.370" UserId="7462" Text="Currently the graphics API I am using is Vulkan, but I am trying to find a general enough way to represent the following.&#xD;&#xA;&#xD;&#xA;In graphics, drawing can be generalized as:&#xD;&#xA;&#xD;&#xA;Get vertex buffers and send them to the GPU&#xD;&#xA;Get all uniform information (samplers, camera, offsets, light positions) and set them in the relevant shader&#xD;&#xA;&#xD;&#xA;call the draw command.&#xD;&#xA;&#xD;&#xA;Obviously the above may be needed to be done multiple times for the same geometry for certain effects. But in general, that's the gist of the situation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am currently trying to setup a generalized &quot;draw&quot; scheme, in which I would like to just declare the geometry, declare the uniform values, and then just render that geometry with those uniforms.&#xD;&#xA;&#xD;&#xA;I was wondering if there is a data structure to organize this already.&#xD;&#xA;&#xD;&#xA;i.e, is there an existing scheme for arbitrary draw state declaration?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25203" PostHistoryTypeId="1" PostId="9221" RevisionGUID="b0f9c98d-d7b4-4aa2-a1f3-4ab20fd0d963" CreationDate="2019-10-06T00:20:30.370" UserId="7462" Text="How to handle object drawables?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25204" PostHistoryTypeId="3" PostId="9221" RevisionGUID="b0f9c98d-d7b4-4aa2-a1f3-4ab20fd0d963" CreationDate="2019-10-06T00:20:30.370" UserId="7462" Text="|real-time|vulkan|data-structure|drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25205" PostHistoryTypeId="2" PostId="9222" RevisionGUID="18ad896a-60e2-4451-9e8f-1a71f64e4fe9" CreationDate="2019-10-06T06:25:57.107" UserId="11274" Text="Although this is an old post, I feel I should add an important correction. The Human Visual System (HVS) is more sensitive to relative differences in darker tones rather&#xD;&#xA;than brighter tones." ContentLicense="CC BY-SA 4.0" />
  <row Id="25206" PostHistoryTypeId="50" PostId="9116" RevisionGUID="5ff800d2-f86e-4ffc-bb34-4028d57d7494" CreationDate="2019-10-06T07:01:40.420" UserId="-1" />
  <row Id="25207" PostHistoryTypeId="50" PostId="8462" RevisionGUID="51bf2271-acee-463b-977e-74e287ca8430" CreationDate="2019-10-06T10:00:50.140" UserId="-1" />
  <row Id="25208" PostHistoryTypeId="5" PostId="5948" RevisionGUID="0cc1939b-fe01-48d0-8d6d-e7845f326c4a" CreationDate="2019-10-07T08:02:21.960" UserId="209" Comment="Made corrections as noted by @James M" Text="In general, non-linear function would mean that an increase in an input does not produce a proportional increase or decrease in output. Mathematically, any function that relates one value to another that doesn't follow a straight line is non-linear. So x raised to the power y is a non-linear function.&#xD;&#xA;&#xD;&#xA;This matters for colors because our brains don't perceive light in a linear fashion. If you double the number of photons reaching the retina, the brain doesn't interpret it as twice as bright. Further, we can better distinguish two dark shades that are separated by a certain difference in intensity than two bright shades that are separated by the same fixed intensity difference.&#xD;&#xA;&#xD;&#xA;When encoding light values in a computer, we need to choose how precisely to record them without losing too much quality. If we use too many bits, then our hardware becomes more expensive. If we use too few then the image looks bad. Until the last ~10-15 years or so, it was generally considered too expensive to store more than 8 bits per red, green, and blue channel. The problem is that if you encode the light values linearly (where 2x causes your monitor to produce twice as many photons as 1x does), then images stored with only 8 bits per channel will have very obvious banding in bright areas of continuous color.&#xD;&#xA;&#xD;&#xA;But remember above that humans can perceive smaller increments in darker shades than lighter? That means that we can use 8 bits per channel, but not use them linearly. If we instead take each 8-bit color channel value and treat it as a value between 0 and 1, if we raise that value to a power then we have smaller steps in the darker areas than in the lighter. This is called gamma-correction or gamma-encoding. We just have to remember to do the reverse (raise the value to the 1 / x power) when we want to output the values on a display.&#xD;&#xA;&#xD;&#xA;So if you're dealing with non-linear RGB, it is probably gamma encoded. sRGB is a popular encoding that uses a power of ~2.2. (In truth, it's [a little more complicated than just raising it to a power](https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_.28.22gamma.22.29).) So when someone tells you that RGB is non-linear, that's usually what they are referring to. It is entirely possible to store images in linear RGB, so long as you use more than 8 bits per color channel. There are also formats that use a logarithmic encodings, though they are less common outside of film production.&#xD;&#xA;&#xD;&#xA;CMYK is more complicated than RGB. Rather than having only a single thing that is outputting the color (the monitor), with CMYK, you have to deal with the medium you're printing on as well as the inks you are printing with. In a typical scenario, you print onto a white surface (such as a piece of paper). Ideally all visible frequencies of light should be reflected off of the paper and into your eyes or camera. When you add ink, the ink absorbs some frequencies of light and reflects others. (And I believe some passes through the ink, hits the paper and is reflected back as well.) The manner in which an ink reflects light is non-linear. Doubling the amount of ink may not cut in half the number of photons reflected back. So CMYK is also non-linear." ContentLicense="CC BY-SA 4.0" />
  <row Id="25209" PostHistoryTypeId="50" PostId="6115" RevisionGUID="2d7cbbf7-cdd1-4d26-9023-89f5803dca33" CreationDate="2019-10-07T14:01:20.173" UserId="-1" />
  <row Id="25210" PostHistoryTypeId="2" PostId="9223" RevisionGUID="4b39c14c-d9a0-4517-85a4-0e6c9cf46883" CreationDate="2019-10-07T14:38:37.060" UserId="1908" Text="There isn't a bounding box for the whole glTF file, but individual primitives have `POSITION` accessors that indicate `min` and `max` values.  This is specified in the [Meshes section](https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes), with the following text:&#xD;&#xA;&#xD;&#xA;&gt; `POSITION` accessor must have `min` and `max` properties defined.&#xD;&#xA;&#xD;&#xA;For a concrete example of this, take a look at the Box sample model, which assigns [accessor 2 as `POSITION`](https://github.com/KhronosGroup/glTF-Sample-Models/blob/18912e96c60245f71a3775d365c990009307a11a/2.0/Box/glTF/Box.gltf#L48)&#xD;&#xA;&#xD;&#xA;    &quot;meshes&quot;: [&#xD;&#xA;        {&#xD;&#xA;            &quot;primitives&quot;: [&#xD;&#xA;                {&#xD;&#xA;                    &quot;attributes&quot;: {&#xD;&#xA;                        &quot;NORMAL&quot;: 1,&#xD;&#xA;                        &quot;POSITION&quot;: 2&#xD;&#xA;                    },&#xD;&#xA;                    &quot;indices&quot;: 0,&#xD;&#xA;                    &quot;mode&quot;: 4,&#xD;&#xA;                    &quot;material&quot;: 0&#xD;&#xA;                }&#xD;&#xA;            ],&#xD;&#xA;            &quot;name&quot;: &quot;Mesh&quot;&#xD;&#xA;        }&#xD;&#xA;    ],&#xD;&#xA;&#xD;&#xA;The accessor at index `2` (the third one in the list) looks [like this](https://github.com/KhronosGroup/glTF-Sample-Models/blob/18912e96c60245f71a3775d365c990009307a11a/2.0/Box/glTF/Box.gltf#L89-L105):&#xD;&#xA;&#xD;&#xA;    &quot;accessors&quot;: [&#xD;&#xA;        { ... },&#xD;&#xA;        { ... },&#xD;&#xA;        {&#xD;&#xA;            &quot;bufferView&quot;: 1,&#xD;&#xA;            &quot;byteOffset&quot;: 288,&#xD;&#xA;            &quot;componentType&quot;: 5126,&#xD;&#xA;            &quot;count&quot;: 24,&#xD;&#xA;            &quot;max&quot;: [&#xD;&#xA;                0.5,&#xD;&#xA;                0.5,&#xD;&#xA;                0.5&#xD;&#xA;            ],&#xD;&#xA;            &quot;min&quot;: [&#xD;&#xA;                -0.5,&#xD;&#xA;                -0.5,&#xD;&#xA;                -0.5&#xD;&#xA;            ],&#xD;&#xA;            &quot;type&quot;: &quot;VEC3&quot;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In this accessor, `min` and `max` are arrays of `x, y, z` raw position data of the primitive.  This particular sample model is a unit cube, with values ranging from `-0.5` to `0.5` along each axis.&#xD;&#xA;&#xD;&#xA;To understand how this affects the whole model though, one must walk the tree of scene nodes, and look at how these mesh primitives are being transformed by the nodes.  Also, if there are any animations or morph targets taking effect, they can influence the final positions of these meshes as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="25215" PostHistoryTypeId="5" PostId="9211" RevisionGUID="79390bc9-af15-43d0-963c-27e37b8462b8" CreationDate="2019-10-08T13:00:12.300" UserId="209" Comment="Added code example and some results." Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_N]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**N points, $\small P=[P_0,P_1,...P_{2N-1}]$, and replaces it with two sequences of N points each: a *low frequency* set, $\small L=[L_0,...L_{N-1}]$, and a high frequency set, $\small H=[H_0,...H_{N-1}]$. &#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - the simplest being the Haar wavelet - but I think a linear or perhaps a 'Catmull-Rom-based' cubic wavelet (though I don't know if this appears in any literature) might be suitable.&#xD;&#xA;&#xD;&#xA;For each wavelet decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms, i.e. either&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&gt;*Linear*:  $$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;*CR-cubic*:$$H_i := P_{2i+1} - \frac{9(P_{2i} +P_{2i+2})-(P_{2i-2} +P_{2i+4})}{16}$$&#xD;&#xA;&#xD;&#xA;followed by an 'update' (which I'll just assume is the same for both linear and cubic&#xD;&#xA;&gt; $$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{2}$$&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;***Notes**: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array.&lt;br/&gt;&#xD;&#xA;Also, I've glossed over what happens when exceeding the bounds of the arrays, e.g. at $P_{2N}$ and $L_{-1}$, but one approach is to simply repeat values and/or pad with zeros.*&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of low frequency points, L, will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*More notes: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, re-insert them into the lower frequency set?*&#xD;&#xA;&#xD;&#xA;As requested in the comments, I've put together a little bit of C code to do the &quot;cubic&quot; decomposition. For simplicity, this just uses separate arrays for each of the lower frequency results rather than, say, doing the calculation &quot;in place&quot; in the original array.&#xD;&#xA;````&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;assert.h&gt;&#xD;&#xA;&#xD;&#xA;#define IS_EVEN(X) (((X)&amp;1)==0)&#xD;&#xA;#define MAX(X,Y) ((X)&gt;=(Y)?(X):(Y))&#xD;&#xA;#define MIN(X,Y) ((X)&lt;=(Y)?(X):(Y))&#xD;&#xA;&#xD;&#xA;typedef unsigned int UINT;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_DIMS (2)&#xD;&#xA;&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;	float pos[NUM_DIMS];&#xD;&#xA;}vec_t;&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Lift&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;lift&quot; step, i.e. computes high frequency terms, by&#xD;&#xA;// predicting using Catmull-Rom spline through even points, and computing&#xD;&#xA;// differences from odd&#xD;&#xA;*/&#xD;&#xA;static void Lift(const vec_t  PointsIn[], &#xD;&#xA;				 const UINT NumPtsIn,&#xD;&#xA;				 vec_t HFOut[])&#xD;&#xA;{&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through odd values doing a &quot;lifting&quot; step, i.e. predicting &#xD;&#xA;	// a position from neighbourhood of even points and computing the difference&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 1; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// get 2 neighbours on either side of this odd point. IF we step out of range, then&#xD;&#xA;		// clamp to nearest valid point&#xD;&#xA;		//&#xD;&#xA;		// If you want more efficient code, move these decisions out of the loop&#xD;&#xA;		*/&#xD;&#xA;		const vec_t * pv_m3 = &amp;PointsIn[MAX(i, 3) - 3];&#xD;&#xA;		const vec_t * pv_m1 = &amp;PointsIn[i-1];&#xD;&#xA;		const vec_t * pv_p1 = &amp;PointsIn[MIN(i+1, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv_p3 = &amp;PointsIn[MIN(i+3, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;HFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Predict using Catmull-Rom interpolation - i.e. mid point of spline through the even points&#xD;&#xA;			const float PredictedPos = (9.0/16.0) * (pv_m1-&gt;pos[j] + pv_p1-&gt;pos[j]) - (1.0/16.0) * (pv_m3-&gt;pos[j] + pv_p3-&gt;pos[j]);&#xD;&#xA;&#xD;&#xA;			//Compute the difference from actual pos&#xD;&#xA;			pResult-&gt;pos[j] =pv-&gt;pos[j] - PredictedPos;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Update&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;Update&quot; step, i.e. computes the low frequency terms, &#xD;&#xA;// by filtering in the 'errors' in the prediction (i.e the HF terms) into the&#xD;&#xA;// 'even' vals&#xD;&#xA;*/&#xD;&#xA;static void Update(const vec_t  PointsIn[], &#xD;&#xA;				   const UINT NumPtsIn,&#xD;&#xA;				   const vec_t HFIn[],&#xD;&#xA;				   vec_t LFOut[])&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	static const vec_t TheZeroVec = {0};&#xD;&#xA;&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	//init as if for the &quot;i = -1&quot; iteration&#xD;&#xA;	const vec_t * pHFToRight = &amp;TheZeroVec;&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through even values doing an &quot;update&quot; step,&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 0; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// move one spot over in HF data&#xD;&#xA;		*/&#xD;&#xA;		const vec_t *pHFToLeft = pHFToRight;&#xD;&#xA;		pHFToRight = &amp;HFIn[i/2];&#xD;&#xA;&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;LFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Add in 1/2 of the average of the adjacent HF/Odd terms&#xD;&#xA;			pResult-&gt;pos[j] = pv-&gt;pos[j] + (pHFToLeft-&gt;pos[j] + pHFToRight-&gt;pos[j]) * 0.25;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//Some test data ...&#xD;&#xA;#define NUM_ORIG_POINTS (512u)&#xD;&#xA;static const vec_t PointsIn[NUM_ORIG_POINTS]=&#xD;&#xA;{&#xD;&#xA;#include &quot;fjord.h&quot;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_ADDITIONAL_PASSES (4)&#xD;&#xA;extern int main(int argc, const char *argv[])&#xD;&#xA;{&#xD;&#xA;	&#xD;&#xA;	vec_t HighFreq[NUM_ORIG_POINTS/2];&#xD;&#xA;	vec_t LowFreqs[NUM_ADDITIONAL_PASSES+1][NUM_ORIG_POINTS/2];&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do initial wavelet pass&#xD;&#xA;	*/&#xD;&#xA;	Lift(PointsIn, NUM_ORIG_POINTS, HighFreq);&#xD;&#xA;	Update(PointsIn, NUM_ORIG_POINTS, HighFreq, LowFreqs[0]);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do a few more wavelet passes&#xD;&#xA;	*/&#xD;&#xA;	for(UINT Pass=0; Pass &lt; NUM_ADDITIONAL_PASSES; Pass++)&#xD;&#xA;	{&#xD;&#xA;		const UINT CurrentNumSrcPoints = NUM_ORIG_POINTS &gt;&gt; (Pass+1);&#xD;&#xA;&#xD;&#xA;		Lift(LowFreqs[Pass],   CurrentNumSrcPoints, HighFreq);&#xD;&#xA;		Update(LowFreqs[Pass], CurrentNumSrcPoints, HighFreq, LowFreqs[Pass+1]);&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;The above has been run on the outline on a section of a map which I've plotted using Excel's scatter plot tools (which I hope will be a reasonable approximation of Catmull-Rom splines.)&#xD;&#xA;&#xD;&#xA;This shows the original set of 512 points:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This illustrates the 256 points obtained from one step...&#xD;&#xA;[![One Wavelet Step][2]][2]&#xD;&#xA;&#xD;&#xA;...through to the 128 points obtained by two steps:[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t456F.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZktUd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/OfdKt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25216" PostHistoryTypeId="5" PostId="9211" RevisionGUID="48aa3120-4c93-4a20-8bdc-823d0b22b070" CreationDate="2019-10-08T13:16:24.103" UserId="209" Comment="Fixed one of the weights!" Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_{N-1}]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**R points, $\small P=[P_0,P_1,...P_{2R-1}]$, and replaces it with two sequences of R points each: a *low frequency* set, $\small L=[L_0,...L_{R-1}]$, and a high frequency set, $\small H=[H_0,...H_{R-1}]$. I suspect in your use case you might only be interested in the low frequency sequence(s).&#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - the simplest being the Haar wavelet - but I think a linear or perhaps a 'Catmull-Rom-based' cubic wavelet (though I don't know if this appears in any literature) might be suitable.&#xD;&#xA;&#xD;&#xA;For each wavelet decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms, i.e. either&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&gt;*Linear*:  $$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;*CR-cubic*:$$H_i := P_{2i+1} - \frac{9(P_{2i} +P_{2i+2})-(P_{2i-2} +P_{2i+4})}{16}$$&#xD;&#xA;&#xD;&#xA;followed by an 'update' (which I'll just assume is the same for both linear and cubic) which filters in some of the high frequency terms into the 'even'/low frequency terms as a correction.&#xD;&#xA;&gt; $$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{4}$$&#xD;&#xA;&#xD;&#xA;***Notes**: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array.&lt;br/&gt;&#xD;&#xA;Also, I've glossed over what happens when exceeding the bounds of the arrays, e.g. at $P_{2N}$ and $L_{-1}$, but one approach is to simply repeat values and/or pad with zeros.*&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of low frequency points, L, will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*More notes: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, re-insert them into the lower frequency set?*&#xD;&#xA;&#xD;&#xA;As requested in the comments, I've put together a little bit of C code to do the &quot;cubic&quot; decomposition. For simplicity, this just uses separate arrays for each of the lower frequency results rather than, say, doing the calculation &quot;in place&quot; in the original array.&#xD;&#xA;````&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;assert.h&gt;&#xD;&#xA;&#xD;&#xA;#define IS_EVEN(X) (((X)&amp;1)==0)&#xD;&#xA;#define MAX(X,Y) ((X)&gt;=(Y)?(X):(Y))&#xD;&#xA;#define MIN(X,Y) ((X)&lt;=(Y)?(X):(Y))&#xD;&#xA;&#xD;&#xA;typedef unsigned int UINT;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_DIMS (2)&#xD;&#xA;&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;	float pos[NUM_DIMS];&#xD;&#xA;}vec_t;&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Lift&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;lift&quot; step, i.e. computes high frequency terms, by&#xD;&#xA;// predicting using Catmull-Rom spline through even points, and computing&#xD;&#xA;// differences from odd&#xD;&#xA;*/&#xD;&#xA;static void Lift(const vec_t  PointsIn[], &#xD;&#xA;				 const UINT NumPtsIn,&#xD;&#xA;				 vec_t HFOut[])&#xD;&#xA;{&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through odd values doing a &quot;lifting&quot; step, i.e. predicting &#xD;&#xA;	// a position from neighbourhood of even points and computing the difference&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 1; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// get 2 neighbours on either side of this odd point. IF we step out of range, then&#xD;&#xA;		// clamp to nearest valid point&#xD;&#xA;		//&#xD;&#xA;		// If you want more efficient code, move these decisions out of the loop&#xD;&#xA;		*/&#xD;&#xA;		const vec_t * pv_m3 = &amp;PointsIn[MAX(i, 3) - 3];&#xD;&#xA;		const vec_t * pv_m1 = &amp;PointsIn[i-1];&#xD;&#xA;		const vec_t * pv_p1 = &amp;PointsIn[MIN(i+1, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv_p3 = &amp;PointsIn[MIN(i+3, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;HFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Predict using Catmull-Rom interpolation - i.e. mid point of spline through the even points&#xD;&#xA;			const float PredictedPos = (9.0/16.0) * (pv_m1-&gt;pos[j] + pv_p1-&gt;pos[j]) - (1.0/16.0) * (pv_m3-&gt;pos[j] + pv_p3-&gt;pos[j]);&#xD;&#xA;&#xD;&#xA;			//Compute the difference from actual pos&#xD;&#xA;			pResult-&gt;pos[j] =pv-&gt;pos[j] - PredictedPos;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Update&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;Update&quot; step, i.e. computes the low frequency terms, &#xD;&#xA;// by filtering in the 'errors' in the prediction (i.e the HF terms) into the&#xD;&#xA;// 'even' vals&#xD;&#xA;*/&#xD;&#xA;static void Update(const vec_t  PointsIn[], &#xD;&#xA;				   const UINT NumPtsIn,&#xD;&#xA;				   const vec_t HFIn[],&#xD;&#xA;				   vec_t LFOut[])&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	static const vec_t TheZeroVec = {0};&#xD;&#xA;&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	//init as if for the &quot;i = -1&quot; iteration&#xD;&#xA;	const vec_t * pHFToRight = &amp;TheZeroVec;&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through even values doing an &quot;update&quot; step,&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 0; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// move one spot over in HF data&#xD;&#xA;		*/&#xD;&#xA;		const vec_t *pHFToLeft = pHFToRight;&#xD;&#xA;		pHFToRight = &amp;HFIn[i/2];&#xD;&#xA;&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;LFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Add in 1/2 of the average of the adjacent HF/Odd terms&#xD;&#xA;			pResult-&gt;pos[j] = pv-&gt;pos[j] + (pHFToLeft-&gt;pos[j] + pHFToRight-&gt;pos[j]) * 0.25;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//Some test data ...&#xD;&#xA;#define NUM_ORIG_POINTS (512u)&#xD;&#xA;static const vec_t PointsIn[NUM_ORIG_POINTS]=&#xD;&#xA;{&#xD;&#xA;#include &quot;fjord.h&quot;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_ADDITIONAL_PASSES (4)&#xD;&#xA;extern int main(int argc, const char *argv[])&#xD;&#xA;{&#xD;&#xA;	&#xD;&#xA;	vec_t HighFreq[NUM_ORIG_POINTS/2];&#xD;&#xA;	vec_t LowFreqs[NUM_ADDITIONAL_PASSES+1][NUM_ORIG_POINTS/2];&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do initial wavelet pass&#xD;&#xA;	*/&#xD;&#xA;	Lift(PointsIn, NUM_ORIG_POINTS, HighFreq);&#xD;&#xA;	Update(PointsIn, NUM_ORIG_POINTS, HighFreq, LowFreqs[0]);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do a few more wavelet passes&#xD;&#xA;	*/&#xD;&#xA;	for(UINT Pass=0; Pass &lt; NUM_ADDITIONAL_PASSES; Pass++)&#xD;&#xA;	{&#xD;&#xA;		const UINT CurrentNumSrcPoints = NUM_ORIG_POINTS &gt;&gt; (Pass+1);&#xD;&#xA;&#xD;&#xA;		Lift(LowFreqs[Pass],   CurrentNumSrcPoints, HighFreq);&#xD;&#xA;		Update(LowFreqs[Pass], CurrentNumSrcPoints, HighFreq, LowFreqs[Pass+1]);&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;The above has been run on the outline on a section of a map which I've plotted using Excel's scatter plot tools (which I hope will be a reasonable approximation of Catmull-Rom splines.)&#xD;&#xA;&#xD;&#xA;This shows the original set of 512 points:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This illustrates the 256 points obtained from one step...&#xD;&#xA;[![One Wavelet Step][2]][2]&#xD;&#xA;&#xD;&#xA;...through to the 128 points obtained by two steps:[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/t456F.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZktUd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/OfdKt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25217" PostHistoryTypeId="2" PostId="9225" RevisionGUID="ea86bfcb-494c-4aa6-a26f-f5314ca6733e" CreationDate="2019-10-08T18:40:07.083" UserId="5496" Text="I'm reading the book 3d Math Primer for Graphics and Game Development 1st by Fletcher Dunn and Ian Parberry. On page 61 there's this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;How does it this equation for $ v_{||} $ there? It doesn't follow from what preceded this part of the book, unless I'm missing something. Also I'm not sure, is $n$ supposed to be unit vector here? This should probably be in the errata but I didn't find anything. Anyway, how did he deduce this equation? Thanks in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yscWk.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25218" PostHistoryTypeId="1" PostId="9225" RevisionGUID="ea86bfcb-494c-4aa6-a26f-f5314ca6733e" CreationDate="2019-10-08T18:40:07.083" UserId="5496" Text="3d Math Primer book equation derivation - Projecting One vector onto another" ContentLicense="CC BY-SA 4.0" />
  <row Id="25219" PostHistoryTypeId="3" PostId="9225" RevisionGUID="ea86bfcb-494c-4aa6-a26f-f5314ca6733e" CreationDate="2019-10-08T18:40:07.083" UserId="5496" Text="|projections|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25220" PostHistoryTypeId="5" PostId="9225" RevisionGUID="29e1c580-b483-42a8-988d-9f231a000f3b" CreationDate="2019-10-08T19:38:21.487" UserId="5496" Comment="deleted 3 characters in body" Text="I'm reading the book 3d Math Primer for Graphics and Game Development 1st edition by Fletcher Dunn and Ian Parberry. On page 61 there's this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;How does it derive $ v_{||} $ there? It doesn't follow from what preceded this point in the book, unless I'm missing something. Also I'm not sure, is $n$ supposed to be unit vector here? This should probably be in the errata but I didn't find anything. Anyway, how did he deduce this equation? Thanks in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yscWk.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25221" PostHistoryTypeId="2" PostId="9226" RevisionGUID="50bf32fc-6927-4efb-a268-aab2a71e4ae7" CreationDate="2019-10-08T19:49:33.687" UserId="506" Text="Since `v∥` is parallel to `n`, it can be expressed as some multiple of `n`. The multiple is the ratio of the length of `v∥` to the length of `n`. The `n` vector doesn’t have to be normalized, but if it is, then `|n|` is 1, so the equation becomes `v∥ = n * |v∥|`." ContentLicense="CC BY-SA 4.0" />
  <row Id="25222" PostHistoryTypeId="2" PostId="9227" RevisionGUID="f79281aa-0891-4750-95cd-d5e3ee359f5f" CreationDate="2019-10-08T19:49:45.373" UserId="10096" Text="Since we have:&#xD;&#xA;&#xD;&#xA;$$\pmb{v}_{\parallel} \parallel \pmb{n},$$&#xD;&#xA;&#xD;&#xA;then:&#xD;&#xA;&#xD;&#xA;$$\pmb{v}_{\parallel} = k\pmb{n}$$&#xD;&#xA;&#xD;&#xA;We want that the length of $\pmb{v}_{\parallel}$ is $\|\pmb{v}_{\parallel}\|$, then:&#xD;&#xA;&#xD;&#xA;$$\|\pmb{v}_{\parallel}\| =|k|\|\pmb{n}\| \implies |k| = \frac{\|\pmb{v}_{\parallel}\|}{\|\pmb{n}\|}$$&#xD;&#xA;&#xD;&#xA;Then the sign of $k$ is simply chosen to match the direction of $\pmb{v}$ (if the angle between $\pmb{v}$ and $\pmb{n}$ is more than 90 degrees, the sign is negative, otherwise it is positive)." ContentLicense="CC BY-SA 4.0" />
  <row Id="25223" PostHistoryTypeId="5" PostId="9211" RevisionGUID="c146b55a-8b7d-431d-8ae5-482b512a596e" CreationDate="2019-10-09T08:03:05.277" UserId="209" Comment="Added link to Sweldens &amp; Schröder &quot;Building Wavelets at Home&quot; and added comment to code" Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_{N-1}]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**R points, $\small P=[P_0,P_1,...P_{2R-1}]$, and replaces it with two sequences of R points each: a *low frequency* set, $\small L=[L_0,...L_{R-1}]$, and a high frequency set, $\small H=[H_0,...H_{R-1}]$. I suspect in your use case you might only be interested in the low frequency sequence(s).&#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - [the simplest being the Haar wavelet - but I think a linear][1] or perhaps a 'Catmull-Rom-based' cubic wavelet (though I don't know if this appears in any literature) might be suitable.&#xD;&#xA;&#xD;&#xA;For each wavelet decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms, i.e. either&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&gt;*Linear*:  $$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;*CR-cubic*:$$H_i := P_{2i+1} - \frac{9(P_{2i} +P_{2i+2})-(P_{2i-2} +P_{2i+4})}{16}$$&#xD;&#xA;&#xD;&#xA;followed by an 'update' (which I'll just assume is the same for both linear and cubic) which filters in some of the high frequency terms into the 'even'/low frequency terms as a correction.&#xD;&#xA;&gt; $$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{4}$$&#xD;&#xA;&#xD;&#xA;***Notes**: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array.&lt;br/&gt;&#xD;&#xA;Also, I've glossed over what happens when exceeding the bounds of the arrays, e.g. at $P_{2N}$ and $L_{-1}$, but one approach is to simply repeat values and/or pad with zeros.*&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of low frequency points, L, will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*More notes: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, re-insert them into the lower frequency set?*&#xD;&#xA;&#xD;&#xA;As requested in the comments, I've put together a little bit of C code to do the &quot;cubic&quot; decomposition. For simplicity, this just uses separate arrays for each of the lower frequency results rather than, say, doing the calculation &quot;in place&quot; in the original array.&#xD;&#xA;````&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;assert.h&gt;&#xD;&#xA;&#xD;&#xA;#define IS_EVEN(X) (((X)&amp;1)==0)&#xD;&#xA;#define MAX(X,Y) ((X)&gt;=(Y)?(X):(Y))&#xD;&#xA;#define MIN(X,Y) ((X)&lt;=(Y)?(X):(Y))&#xD;&#xA;&#xD;&#xA;typedef unsigned int UINT;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_DIMS (2)&#xD;&#xA;&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;	float pos[NUM_DIMS];&#xD;&#xA;}vec_t;&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Lift&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;lift&quot; step, i.e. computes high frequency terms, by&#xD;&#xA;// predicting using Catmull-Rom spline through even points, and computing&#xD;&#xA;// differences from odd&#xD;&#xA;*/&#xD;&#xA;static void Lift(const vec_t  PointsIn[], &#xD;&#xA;				 const UINT NumPtsIn,&#xD;&#xA;				 vec_t HFOut[])&#xD;&#xA;{&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn) &amp;&amp;  NumPtsIn&gt;=2);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through odd values doing a &quot;lifting&quot; step, i.e. predicting &#xD;&#xA;	// a position from neighbourhood of even points and computing the difference&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 1; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// get 2 neighbours on either side of this odd point. IF we step out of range, then&#xD;&#xA;		// clamp to nearest valid point&#xD;&#xA;		//&#xD;&#xA;		// If you want more efficient code, move these decisions out of the loop&#xD;&#xA;		*/&#xD;&#xA;		const vec_t * pv_m3 = &amp;PointsIn[MAX(i, 3) - 3];&#xD;&#xA;		const vec_t * pv_m1 = &amp;PointsIn[i-1];&#xD;&#xA;		const vec_t * pv_p1 = &amp;PointsIn[MIN(i+1, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv_p3 = &amp;PointsIn[MIN(i+3, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;HFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Predict using Catmull-Rom interpolation - &#xD;&#xA;			//i.e. mid point of CR spline through the even points {p[i-3], p[i-1], p[i+1], p[i+3]}&#xD;&#xA;			const float PredictedPos = (9.0/16.0) * (pv_m1-&gt;pos[j] + pv_p1-&gt;pos[j]) - (1.0/16.0) * (pv_m3-&gt;pos[j] + pv_p3-&gt;pos[j]);&#xD;&#xA;&#xD;&#xA;			//Compute the difference from actual pos&#xD;&#xA;			pResult-&gt;pos[j] =pv-&gt;pos[j] - PredictedPos;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Update&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;Update&quot; step, i.e. computes the low frequency terms, &#xD;&#xA;// by filtering in the 'errors' in the prediction (i.e the HF terms) into the&#xD;&#xA;// 'even' vals&#xD;&#xA;*/&#xD;&#xA;static void Update(const vec_t  PointsIn[], &#xD;&#xA;				   const UINT NumPtsIn,&#xD;&#xA;				   const vec_t HFIn[],&#xD;&#xA;				   vec_t LFOut[])&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	static const vec_t TheZeroVec = {0};&#xD;&#xA;&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	//init as if for the &quot;i = -1&quot; iteration&#xD;&#xA;	const vec_t * pHFToRight = &amp;TheZeroVec;&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through even values doing an &quot;update&quot; step,&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 0; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// move one spot over in HF data&#xD;&#xA;		*/&#xD;&#xA;		const vec_t *pHFToLeft = pHFToRight;&#xD;&#xA;		pHFToRight = &amp;HFIn[i/2];&#xD;&#xA;&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;LFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Add in 1/2 of the average of the adjacent HF/Odd terms&#xD;&#xA;			pResult-&gt;pos[j] = pv-&gt;pos[j] + (pHFToLeft-&gt;pos[j] + pHFToRight-&gt;pos[j]) * 0.25;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//Some test data ...&#xD;&#xA;#define NUM_ORIG_POINTS (512u)&#xD;&#xA;static const vec_t PointsIn[NUM_ORIG_POINTS]=&#xD;&#xA;{&#xD;&#xA;#include &quot;fjord.h&quot;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_ADDITIONAL_PASSES (4)&#xD;&#xA;extern int main(int argc, const char *argv[])&#xD;&#xA;{&#xD;&#xA;	&#xD;&#xA;	vec_t HighFreq[NUM_ORIG_POINTS/2];&#xD;&#xA;	vec_t LowFreqs[NUM_ADDITIONAL_PASSES+1][NUM_ORIG_POINTS/2];&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do initial wavelet pass&#xD;&#xA;	*/&#xD;&#xA;	Lift(PointsIn, NUM_ORIG_POINTS, HighFreq);&#xD;&#xA;	Update(PointsIn, NUM_ORIG_POINTS, HighFreq, LowFreqs[0]);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do a few more wavelet passes&#xD;&#xA;	*/&#xD;&#xA;	for(UINT Pass=0; Pass &lt; NUM_ADDITIONAL_PASSES; Pass++)&#xD;&#xA;	{&#xD;&#xA;		const UINT CurrentNumSrcPoints = NUM_ORIG_POINTS &gt;&gt; (Pass+1);&#xD;&#xA;&#xD;&#xA;		Lift(LowFreqs[Pass],   CurrentNumSrcPoints, HighFreq);&#xD;&#xA;		Update(LowFreqs[Pass], CurrentNumSrcPoints, HighFreq, LowFreqs[Pass+1]);&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;The above has been run on the outline on a section of a map which I've plotted using Excel's scatter plot tools (which I hope will be a reasonable approximation of Catmull-Rom splines.)&#xD;&#xA;&#xD;&#xA;This shows the original set of 512 points:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This illustrates the 256 points obtained from one step...&#xD;&#xA;[![One Wavelet Step][3]][3]&#xD;&#xA;&#xD;&#xA;...through to the 128 points obtained by two steps:[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://9p.io/who/wim/papers/athome/&#xD;&#xA;  [2]: https://i.stack.imgur.com/t456F.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZktUd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OfdKt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25224" PostHistoryTypeId="5" PostId="9211" RevisionGUID="decfb108-d5ec-4321-b70f-ae573d20ff38" CreationDate="2019-10-09T08:13:47.837" UserId="209" Comment="Added link to Sweldens &amp; Schröder &quot;Building Wavelets at Home&quot; and added comments to code" Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_{N-1}]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**R points, $\small P=[P_0,P_1,...P_{2R-1}]$, and replaces it with two sequences of R points each: a *low frequency* set, $\small L=[L_0,...L_{R-1}]$, and a high frequency set, $\small H=[H_0,...H_{R-1}]$. I suspect in your use case you might only be interested in the low frequency sequence(s).&#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - the simplest being the Haar wavelet - but I think a linear (see [Sweldens &amp; Schröder][1] for an easy introduction)  or perhaps a 'Catmull-Rom-based' cubic wavelet might be suitable (though I don't know if this appears in any literature).&#xD;&#xA;&#xD;&#xA;For each wavelet decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms, i.e. either...&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&gt;*Linear*:  $$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;*CR-cubic*:$$H_i := P_{2i+1} - \frac{9(P_{2i} +P_{2i+2})-(P_{2i-2} +P_{2i+4})}{16}$$&#xD;&#xA;&#xD;&#xA;...followed by an 'update'  which filters some of the high frequency terms back into the 'even'/low frequency terms as a correction. (We'll just assume, perhaps sub-optimally, this is the same for both linear and cubic)&#xD;&#xA;&gt; $$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{4}$$&#xD;&#xA;&#xD;&#xA;***Notes**: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array.&lt;br/&gt;&#xD;&#xA;This has also glossed over what happens when exceeding the bounds of the arrays, e.g. at $P_{2N}$ and $L_{-1}$, but one approach is to simply repeat values and/or pad with zeros.*&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of low frequency points, L, will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;***More notes**: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, re-insert them into the lower frequency set?*&#xD;&#xA;&#xD;&#xA;As requested in the comments, I've put together a little bit of C code to do the &quot;cubic&quot; decomposition. For simplicity, this just uses separate arrays for each of the lower frequency results rather than, say, doing the calculation &quot;in place&quot; in the original array.&#xD;&#xA;````&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;assert.h&gt;&#xD;&#xA;&#xD;&#xA;#define IS_EVEN(X) (((X)&amp;1)==0)&#xD;&#xA;#define MAX(X,Y) ((X)&gt;=(Y)?(X):(Y))&#xD;&#xA;#define MIN(X,Y) ((X)&lt;=(Y)?(X):(Y))&#xD;&#xA;&#xD;&#xA;typedef unsigned int UINT;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_DIMS (2)&#xD;&#xA;&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;	float pos[NUM_DIMS];&#xD;&#xA;}vec_t;&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Lift&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;lift&quot; step, i.e. computes high frequency terms, by&#xD;&#xA;// predicting using Catmull-Rom spline through even points, and computing&#xD;&#xA;// differences from odd&#xD;&#xA;*/&#xD;&#xA;static void Lift(const vec_t  PointsIn[], &#xD;&#xA;				 const UINT NumPtsIn,&#xD;&#xA;				 vec_t HFOut[])&#xD;&#xA;{&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn) &amp;&amp;  NumPtsIn&gt;=2);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through odd values doing a &quot;lifting&quot; step, i.e. predicting &#xD;&#xA;	// a position from neighbourhood of even points and computing the difference&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 1; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// get 2 neighbours on either side of this odd point. IF we step out of range, then&#xD;&#xA;		// clamp to nearest valid point&#xD;&#xA;		//&#xD;&#xA;		// If you want more efficient code, move these decisions out of the loop&#xD;&#xA;		*/&#xD;&#xA;		const vec_t * pv_m3 = &amp;PointsIn[MAX(i, 3) - 3];&#xD;&#xA;		const vec_t * pv_m1 = &amp;PointsIn[i-1];&#xD;&#xA;		const vec_t * pv_p1 = &amp;PointsIn[MIN(i+1, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv_p3 = &amp;PointsIn[MIN(i+3, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;HFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Predict using Catmull-Rom interpolation - &#xD;&#xA;			//i.e. mid point of CR spline through the even points {p[i-3], p[i-1], p[i+1], p[i+3]}&#xD;&#xA;			const float PredictedPos = (9.0/16.0) * (pv_m1-&gt;pos[j] + pv_p1-&gt;pos[j]) - (1.0/16.0) * (pv_m3-&gt;pos[j] + pv_p3-&gt;pos[j]);&#xD;&#xA;&#xD;&#xA;			//Compute the difference from actual pos&#xD;&#xA;			pResult-&gt;pos[j] =pv-&gt;pos[j] - PredictedPos;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Update&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;Update&quot; step, i.e. computes the low frequency terms, &#xD;&#xA;// by filtering in the 'errors' in the prediction (i.e the HF terms) into the&#xD;&#xA;// 'even' vals&#xD;&#xA;*/&#xD;&#xA;static void Update(const vec_t  PointsIn[], &#xD;&#xA;				   const UINT NumPtsIn,&#xD;&#xA;				   const vec_t HFIn[],&#xD;&#xA;				   vec_t LFOut[])&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	static const vec_t TheZeroVec = {0};&#xD;&#xA;&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	//init as if for the &quot;i = -1&quot; iteration&#xD;&#xA;	const vec_t * pHFToRight = &amp;TheZeroVec;&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through even values doing an &quot;update&quot; step,&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 0; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// move one spot over in HF data&#xD;&#xA;		*/&#xD;&#xA;		const vec_t *pHFToLeft = pHFToRight;&#xD;&#xA;		pHFToRight = &amp;HFIn[i/2];&#xD;&#xA;&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;LFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Add in 1/2 of the average of the adjacent HF/Odd terms&#xD;&#xA;			pResult-&gt;pos[j] = pv-&gt;pos[j] + (pHFToLeft-&gt;pos[j] + pHFToRight-&gt;pos[j]) * 0.25;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//Some test data ...&#xD;&#xA;#define NUM_ORIG_POINTS (512u)&#xD;&#xA;static const vec_t PointsIn[NUM_ORIG_POINTS]=&#xD;&#xA;{&#xD;&#xA;#include &quot;fjord.h&quot;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_ADDITIONAL_PASSES (4)&#xD;&#xA;extern int main(int argc, const char *argv[])&#xD;&#xA;{&#xD;&#xA;	&#xD;&#xA;	vec_t HighFreq[NUM_ORIG_POINTS/2];&#xD;&#xA;	vec_t LowFreqs[NUM_ADDITIONAL_PASSES+1][NUM_ORIG_POINTS/2];&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do initial wavelet pass&#xD;&#xA;	*/&#xD;&#xA;	Lift(PointsIn, NUM_ORIG_POINTS, HighFreq);&#xD;&#xA;	Update(PointsIn, NUM_ORIG_POINTS, HighFreq, LowFreqs[0]);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do a few more wavelet passes&#xD;&#xA;	*/&#xD;&#xA;	for(UINT Pass=0; Pass &lt; NUM_ADDITIONAL_PASSES; Pass++)&#xD;&#xA;	{&#xD;&#xA;		const UINT CurrentNumSrcPoints = NUM_ORIG_POINTS &gt;&gt; (Pass+1);&#xD;&#xA;&#xD;&#xA;		Lift(LowFreqs[Pass],   CurrentNumSrcPoints, HighFreq);&#xD;&#xA;		Update(LowFreqs[Pass], CurrentNumSrcPoints, HighFreq, LowFreqs[Pass+1]);&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;The above has been run on the outline on a section of a map which I've plotted using Excel's scatter plot tools (which I hope will be a reasonable approximation of Catmull-Rom splines.)&#xD;&#xA;&#xD;&#xA;This shows an original set of 512 points:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;..the set of 256 low-frequency points obtained from one wavelet step...&#xD;&#xA;[![One Wavelet Step][3]][3]&#xD;&#xA;&#xD;&#xA;...through to the 128 points obtained by two steps:[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://9p.io/who/wim/papers/athome/&#xD;&#xA;  [2]: https://i.stack.imgur.com/t456F.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZktUd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OfdKt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25225" PostHistoryTypeId="5" PostId="6359" RevisionGUID="5967d4a4-0d64-4929-aaa2-e4c70a2c0953" CreationDate="2019-10-09T11:42:31.347" UserId="9622" Comment="Improve question" Text="I am trying to fetch a given geometry and, through (potentially multiple) render passes, create a 3D texture that stores the color value of said geometry into an associated texel.&#xD;&#xA;&#xD;&#xA;In other words there is a 3D box that i am trying to color based on the geometry inside of that box.&#xD;&#xA;&#xD;&#xA;Currently I am attempting to do so with the following vertex shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    #define PI 3.1415926535897932384626433832795&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 position; //(x,y,z) coordinates of a vertex&#xD;&#xA;    layout(location = 1) in vec3 norm; //a 3D vertex representing the normal to the vertex &#xD;&#xA;    layout(location = 2) in vec2 texture_coordinate; // texture coordinates&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 3) buffer instance_buffer&#xD;&#xA;    {&#xD;&#xA;        vec4 cubes_info[];//first 3 values are position of object &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    out vec3 normalized_pos;&#xD;&#xA;    out vec3 normal; &#xD;&#xA;    out vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    uniform float width = 128;&#xD;&#xA;    uniform float depth = 128;&#xD;&#xA;    uniform float height = 128;&#xD;&#xA;    &#xD;&#xA;    uniform float voxel_size = 1;&#xD;&#xA;    uniform vec3 origin = vec3(0,0,0);&#xD;&#xA;    &#xD;&#xA;    uniform float level=0;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        texture_coord = texture_coordinate; &#xD;&#xA;        vec4 pos = (vec4(position, 1.0) + vec4(vec3(cubes_info[gl_InstanceID]),0));&#xD;&#xA;    &#xD;&#xA;        pos-=vec4(origin, 0);&#xD;&#xA;    &#xD;&#xA;        pos.x = (2.f*pos.x-width)/(width);&#xD;&#xA;        pos.y = (2.f*pos.y-depth)/(depth);&#xD;&#xA;        pos.z = (2.f*pos.z-depth)/(height);&#xD;&#xA;    &#xD;&#xA;        gl_Position = pos;&#xD;&#xA;    &#xD;&#xA;        normalized_pos = vec3(pos);&#xD;&#xA;    &#xD;&#xA;        normal = normalize(norm);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the following fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    &#xD;&#xA;    in vec3 normalized_pos;&#xD;&#xA;    in vec3 normal;//Normal to the vertex&#xD;&#xA;    in vec2 texture_coord;&#xD;&#xA;    &#xD;&#xA;    out vec4 outColor;//Final color of the pixel&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D text;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        outColor = vec4(0,1,0,1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;Currently the color is ahrd set to green, just to test whether I am doing things in the correct fashion.&#xD;&#xA;&#xD;&#xA;But I seem to have failed.&#xD;&#xA;&#xD;&#xA;How exactly would you design a shading program that voxelizes a 3D grid of a space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25226" PostHistoryTypeId="24" PostId="6359" RevisionGUID="5967d4a4-0d64-4929-aaa2-e4c70a2c0953" CreationDate="2019-10-09T11:42:31.347" Comment="Proposed by 9622 approved by 209, 6 edit id of 492" ContentLicense="CC BY-SA 4.0" />
  <row Id="25230" PostHistoryTypeId="2" PostId="9229" RevisionGUID="23f13ddf-3059-4399-a193-be9e38367d0a" CreationDate="2019-10-09T17:52:39.170" UserId="11290" Text="(Crossposting from here: https://softwareengineering.stackexchange.com/questions/399331/fuse-3d-points-in-bundel-adjustment)&#xD;&#xA;&#xD;&#xA;I'm actually implementing my own Pose-Estimation/- and -Refinement pipeline. For this purpose I use one moving mono-camera. Then I take the consecutive images to estimate the pose and triangulate the points (nothing special). In the last step I refine the poses and 3D-points with a bundle adjustment approach. &#xD;&#xA;&#xD;&#xA;Generating 3D points with triangulation from consecutive image pairs will give me multiple estimations for one real-world 3D point. In fact, all the estimations refer to the same point. For my understanding, these estimations of the same 3D-points have to be fused in some way. Otherwise the poses were not linked anymore through a common point (see also image below). Further, looking at the equation for the re-projection error in different publications:&#xD;&#xA;&#xD;&#xA;[![Core equation Bundle Adjustment][2]][2]&#xD;&#xA;&#xD;&#xA;turns out, that 3D point (vector a) is only related to **j** and not to the cameraindex **i**.&#xD;&#xA;&#xD;&#xA;[![Stolen from: SBA: A Software Package for Generic Sparse Bundle Adjustment, MANOLIS I. A. LOURAKIS and ANTONIS A. ARGYROS][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Do I understand that right or do I have to use a different set of 3D points for each camera view? Suppose I've to merge the 3D points, is there any preferable strategy?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;I know, there are already countless implementations for BA. I want to use it for further development...&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;  [1]: https://i.stack.imgur.com/hl3QAm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5Bmdqm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25231" PostHistoryTypeId="1" PostId="9229" RevisionGUID="23f13ddf-3059-4399-a193-be9e38367d0a" CreationDate="2019-10-09T17:52:39.170" UserId="11290" Text="Fuse 3D-Points in Bundel Adjustment?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25232" PostHistoryTypeId="3" PostId="9229" RevisionGUID="23f13ddf-3059-4399-a193-be9e38367d0a" CreationDate="2019-10-09T17:52:39.170" UserId="11290" Text="|image-processing|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25233" PostHistoryTypeId="2" PostId="9230" RevisionGUID="1e34acc3-0d24-49e4-8aeb-2a87618e14b6" CreationDate="2019-10-09T21:24:47.333" UserId="5828" Text="I have a polyline and I want to simplify it with Douglas-Peucker. It's an easy algorithm, but what if there are points with the same distance. What point should I select? Is there a reasonable solution?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PLKly.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25234" PostHistoryTypeId="1" PostId="9230" RevisionGUID="1e34acc3-0d24-49e4-8aeb-2a87618e14b6" CreationDate="2019-10-09T21:24:47.333" UserId="5828" Text="Douglas-Peuker and equal distances" ContentLicense="CC BY-SA 4.0" />
  <row Id="25235" PostHistoryTypeId="3" PostId="9230" RevisionGUID="1e34acc3-0d24-49e4-8aeb-2a87618e14b6" CreationDate="2019-10-09T21:24:47.333" UserId="5828" Text="|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25236" PostHistoryTypeId="2" PostId="9231" RevisionGUID="d4fa1ffd-2df3-4a68-97e4-bd8ae2783b43" CreationDate="2019-10-09T21:40:36.390" UserId="11291" Text="Apologies, I was going to add a comment to your question thread but found I ended up elaborating too much.  My development experience is from a DX 11 perspective so some of this may not hold in OpenGL&#xD;&#xA;&#xD;&#xA;The memory locality of the data does certainly play a major part.  But there is a few other items that do play into this, the width of the data as you know.  I've had a few GPUs and have had a stark performance hit on some based upon certain tipping points.  That is the for example, on my old AMD r290 if I recall, you could basically pass up to 4 float4s through to the vertex buffer with no additional cost over 1, but once I posted &gt; 4 then there was a measurable drop (in frame rate).   This is purely off my recollection and so is anecdotal as best.  But it holds that GPU architecture is changing all the time, and what niche techniques that give you a performance edge today maybe the bane of your performance tomorrow.  I've tried myself to stick to the advised known best on the assumption that hardware vendors will build their GPUs to the most common techniques of passing payloads via VB (obviously with some looks from constant buffers).&#xD;&#xA;&#xD;&#xA;Having said that, you have asked the question about ordering the vertices, and certainly that will help marginally.  The performance gain is when you combine this with index buffers which then allows the hardware to optimise and cache already calculated vertices.    You certainly may get even more gains from Triangle strips etc which specifically ordered as per your thoughts.  Most of model rendering I do is indice/vertex based optimised models with instancing, I use a small amount of lookups for cyclic motion effects (tree branches for example), in these cases the entire branch of the tree is looking up the same value.  So caching can be taken advantage of here also.&#xD;&#xA;&#xD;&#xA;All I can say in summary from myself is:&#xD;&#xA;&#xD;&#xA;* Try not to overthink optimisation at the start, while your still developing your game/application try not to prematurely optimise.  If you need to come back and add new capabilities, you might lose all the effort.  You have my habit maybe &gt;&lt;, love trying to get the best performance and techniques&#xD;&#xA;* GPU architectures are varied, and strengths of one can reflect weaknesses in another.  AMD and Nvidia are famous for getting devs to optimise games to their architecture, for a reason, each has advantages/disadvantages.  Taking the middle road on development might be the best place, don't use any hardware vendor based features (opinion here).  (add to that, some packed formats only exist in AMD).&#xD;&#xA;&#xD;&#xA;These are just a few thoughts and experiences I have had.  There are a lots books out there that you should get your hands on around these very topics.  I've not seen to many prescribe what you're proposing, but that doesn't mean its wrong.  Good luck.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25237" PostHistoryTypeId="2" PostId="9232" RevisionGUID="cdef9e51-936f-4c44-b385-65119b93edea" CreationDate="2019-10-09T21:45:42.840" UserId="10096" Text="I would consider the curvature in that case too. If the curvature is small - then it is a flat region - so you can safely remove it - your 4th point for example. If the curvature is large (your 5th point for example), even if the distance is the same, you should most likely leave it alone.&#xD;&#xA;&#xD;&#xA;I would actually recommend a curvature based method coming before Douglas-Peucker." ContentLicense="CC BY-SA 4.0" />
  <row Id="25238" PostHistoryTypeId="4" PostId="9229" RevisionGUID="830ae5f1-134e-461b-a86a-6ed7adcf5b85" CreationDate="2019-10-10T08:05:59.740" UserId="209" Comment="minor spelling correction" Text="Fuse 3D-Points in Bundle Adjustment?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25239" PostHistoryTypeId="2" PostId="9233" RevisionGUID="cc89ad2b-5363-4b7b-ba25-9ecfdc032e73" CreationDate="2019-10-10T18:52:45.440" UserId="11296" Text="[Here][1] I was reading about buffers and found such text: &#xD;&#xA;&#xD;&#xA;&gt; When the entire frame has been rendered, the buffers need to be swapped with one another, so the back buffer becomes the front buffer and vice versa.&#xD;&#xA;&#xD;&#xA;And also this &#xD;&#xA;&#xD;&#xA;&gt; The swap interval indicates how many frames to wait until swapping the buffers, commonly known as vsync.&#xD;&#xA;&#xD;&#xA;The question is: what is a frame? And how does it differ from buffer?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.glfw.org/docs/latest/quick.html#quick_swap_buffers" ContentLicense="CC BY-SA 4.0" />
  <row Id="25240" PostHistoryTypeId="1" PostId="9233" RevisionGUID="cc89ad2b-5363-4b7b-ba25-9ecfdc032e73" CreationDate="2019-10-10T18:52:45.440" UserId="11296" Text="GLFW | What is a frame?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25241" PostHistoryTypeId="3" PostId="9233" RevisionGUID="cc89ad2b-5363-4b7b-ba25-9ecfdc032e73" CreationDate="2019-10-10T18:52:45.440" UserId="11296" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25242" PostHistoryTypeId="2" PostId="9234" RevisionGUID="80fdf291-94a1-45fa-851e-22c16c463834" CreationDate="2019-10-10T22:26:58.093" UserId="11297" Text="I'm working on a game set in space with procedurally generated planets, and I'm trying to write a shader that puts an atmosphere over a planet given the color of the atmosphere and the strength of the atmosphere.&#xD;&#xA;&#xD;&#xA;It looks ok at low strengths:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But at high strengths the planet looks really bright:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And neither of them look realistic. For example in space engine the atmosphere really affects every part of the planet including the oceans without necessarily looking very bright:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ndp1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/GomKM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/5FBOW.jpg&#xD;&#xA;&#xD;&#xA;Here's the relevant part of the shader code I'm using (in glsl):&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;//Final atmosphere color to use&#xD;&#xA;vec4 atmo_pixel_color;&#xD;&#xA;    &#xD;&#xA;if(r &gt; radius_percent)&#xD;&#xA;{&#xD;&#xA;    //This is in space, cut off the color quickly&#xD;&#xA;    float atmo_alpha = clamp(0.5 - pow((r - radius_percent), 2) * 600, 0, 1);&#xD;&#xA;    atmo_pixel_color = atmo_color * atmo_strength;&#xD;&#xA;    atmo_pixel_color.w = atmo_alpha;&#xD;&#xA;}&#xD;&#xA;else&#xD;&#xA;{&#xD;&#xA;    //Atmosphere is thicker near the edges of the planet&#xD;&#xA;    float thickness = pow((r / radius_percent), 2) * 0.1f;&#xD;&#xA;    atmo_pixel_color = atmo_color * (atmo_strength + thickness);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;gl_FragColor = planet_color + atmo_pixel_color;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;r is the distance from the center of the planet. radius_percent is the percentage of the texture that is in the planet (above that is empty space). planet_color is the final base color of the planet itself, or empty black if the pixel is in space.&#xD;&#xA;&#xD;&#xA;I have very little experience doing graphics programming and I didn't really know where to start to research this." ContentLicense="CC BY-SA 4.0" />
  <row Id="25243" PostHistoryTypeId="1" PostId="9234" RevisionGUID="80fdf291-94a1-45fa-851e-22c16c463834" CreationDate="2019-10-10T22:26:58.093" UserId="11297" Text="Shader code for putting an atmosphere over a planet" ContentLicense="CC BY-SA 4.0" />
  <row Id="25244" PostHistoryTypeId="3" PostId="9234" RevisionGUID="80fdf291-94a1-45fa-851e-22c16c463834" CreationDate="2019-10-10T22:26:58.093" UserId="11297" Text="|glsl|color|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25248" PostHistoryTypeId="2" PostId="9236" RevisionGUID="de31585b-cc43-4fa9-8ae6-73df3f7afca9" CreationDate="2019-10-11T01:49:34.977" UserId="2654" Text="Conceptually, a frame is the image you're trying to create, presumably for the purpose of display. It is the product of your entire rendering operation for a specific slice of time.&#xD;&#xA;&#xD;&#xA;A &quot;buffer&quot; is the memory *for* the image you either are trying to create or have already created. Hence the common term: framebuffer. Indeed, the choice of the word &quot;buffer&quot; is because you are typically *buffering* multiple images. That is, one buffer will currently be in the process of being displayed, while another buffer is being rendered." ContentLicense="CC BY-SA 4.0" />
  <row Id="25249" PostHistoryTypeId="5" PostId="9234" RevisionGUID="509004e2-38dc-4067-9ff7-d6aed9834d69" CreationDate="2019-10-11T05:21:01.177" UserId="11297" Comment="added 86 characters in body" Text="I'm working on a game set in space with procedurally generated planets, and I'm trying to write a shader that puts an atmosphere over a planet given the color of the atmosphere and the strength of the atmosphere.&#xD;&#xA;&#xD;&#xA;It looks ok at low strengths:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But at high strengths the planet looks really bright:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And neither of them look realistic. For example in space engine the atmosphere really affects every part of the planet including the oceans without necessarily looking very bright:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ndp1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/GomKM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/5FBOW.jpg&#xD;&#xA;&#xD;&#xA;Here's the relevant part of the shader code I'm using (in glsl):&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;//Final atmosphere color to use&#xD;&#xA;vec4 atmo_pixel_color;&#xD;&#xA;    &#xD;&#xA;if(r &gt; radius_percent)&#xD;&#xA;{&#xD;&#xA;    //This is in space, cut off the color quickly&#xD;&#xA;    float atmo_alpha = clamp(0.5 - pow((r - radius_percent), 2) * 600, 0, 1);&#xD;&#xA;    atmo_pixel_color = atmo_color * atmo_strength;&#xD;&#xA;    atmo_pixel_color.w = atmo_alpha;&#xD;&#xA;}&#xD;&#xA;else&#xD;&#xA;{&#xD;&#xA;    //Atmosphere is thicker near the edges of the planet&#xD;&#xA;    float thickness = pow((r / radius_percent), 2) * 0.1f;&#xD;&#xA;    atmo_pixel_color = atmo_color * (atmo_strength + thickness);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;gl_FragColor = planet_color + atmo_pixel_color;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;r is the distance from the center of the planet. radius_percent is the percentage of the texture that is in the planet (above that is empty space). planet_color is the final base color of the planet itself, or empty black if the pixel is in space.&#xD;&#xA;&#xD;&#xA;I have very little experience doing graphics programming and I didn't really know where to start to research this.&#xD;&#xA;&#xD;&#xA;What kind of algorithm should I be using here to make the atmosphere look correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25250" PostHistoryTypeId="2" PostId="9237" RevisionGUID="b499ab93-099d-478b-971b-75b473c577a7" CreationDate="2019-10-11T07:49:54.757" UserId="11295" Text="I'm a software engineer student with a big projet idea but low graphic knowledge.&#xD;&#xA;&#xD;&#xA;My goal is to compare two people dancing. One person would be the teacher with perfect moves and the other would be a dance trainee.&#xD;&#xA;&#xD;&#xA;From my beginner point of view, all I need to retrieve is both skeletons with a motion tracking camera (like Kinect?) then I can do maths with the different reference points (X,Y,Z).&#xD;&#xA;&#xD;&#xA;Is there a motion tracking camera + API or Library you would recommand me ?&#xD;&#xA;&#xD;&#xA;I do not want to open a 3D software like MeshLab. I would like to retrieve the reference points through line of codes and manipulate them as I wish." ContentLicense="CC BY-SA 4.0" />
  <row Id="25251" PostHistoryTypeId="1" PostId="9237" RevisionGUID="b499ab93-099d-478b-971b-75b473c577a7" CreationDate="2019-10-11T07:49:54.757" UserId="11295" Text="How can I reproduce the MatchMoving/MotionTracking technique from Just Dance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25252" PostHistoryTypeId="3" PostId="9237" RevisionGUID="b499ab93-099d-478b-971b-75b473c577a7" CreationDate="2019-10-11T07:49:54.757" UserId="11295" Text="|camera|motion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25253" PostHistoryTypeId="10" PostId="9229" RevisionGUID="a6b9efe7-b4bf-4713-81b6-166f08eb5e34" CreationDate="2019-10-11T15:28:37.487" UserId="7714" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7714,&quot;DisplayName&quot;:&quot;Catija&quot;}]}" />
  <row Id="25254" PostHistoryTypeId="2" PostId="9238" RevisionGUID="f6e212c9-964a-40ad-986c-b56addc4f334" CreationDate="2019-10-11T22:14:33.690" UserId="11300" Text="I am trying to find (or maybe create) an algorithm for creating a smooth, rounded 3D mesh given a 2D outline. I'm trying to recreate a system from a Gamecube game called Amazing Island, and you can see an example of how it works [here][1]. A more modern example of what I'm trying to do would be the [Soft Edge 3D Doodle tool in Paint 3D][2].&#xD;&#xA;&#xD;&#xA;Basically, you draw a shape with a freeform pen tool, and the shape is &quot;inflated&quot; into a 3D mesh. The result should have smooth, curved, somewhat organic-looking edges, rather than simply extruding the shape into a prism. Each shape can be assumed to be simply connected (meaning shapes with holes through them are not possible), and it can be assumed that the outline won't self-intersect. It would be nice if I could find a way to have non-simply connected shapes, but it's not necessary, and seems like it would be significantly more complicated.&#xD;&#xA;&#xD;&#xA;The closest thing that I've been able to find is how to take an outline and triangulate it to make a flat 2D mesh. I'm pretty lost on how I can take that and turn it into what I want though. I can get a list of points representing the vertices of the outline, which seems like it should be the first step.&#xD;&#xA;&#xD;&#xA;I'm implementing this in C#, in Unity, but I'm not necessarily looking for code. A description of an algorithm, or even a good idea for how I could approach the problem, would be great. Thank you for your time.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/8xI2sZwYg10?t=62&#xD;&#xA;  [2]: https://youtu.be/Zl_Gimw62mM?t=98" ContentLicense="CC BY-SA 4.0" />
  <row Id="25255" PostHistoryTypeId="1" PostId="9238" RevisionGUID="f6e212c9-964a-40ad-986c-b56addc4f334" CreationDate="2019-10-11T22:14:33.690" UserId="11300" Text="Creating a Smooth 3D Mesh from a 2D Outline" ContentLicense="CC BY-SA 4.0" />
  <row Id="25256" PostHistoryTypeId="3" PostId="9238" RevisionGUID="f6e212c9-964a-40ad-986c-b56addc4f334" CreationDate="2019-10-11T22:14:33.690" UserId="11300" Text="|3d|algorithm|computational-geometry|mesh|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25258" PostHistoryTypeId="50" PostId="9146" RevisionGUID="485d2cec-c8e1-4258-bea3-ad6fed43ec13" CreationDate="2019-10-12T14:02:45.433" UserId="-1" />
  <row Id="25259" PostHistoryTypeId="2" PostId="9239" RevisionGUID="713e328d-b065-410a-a54a-60371c7a7b0c" CreationDate="2019-10-12T18:42:21.877" UserId="11304" Text="Here's something that's been bothering me while learning graphics. We have two core concatenated matrix sets: &quot;TRS&quot; for transforms, and &quot;MVP&quot; for moving everything into the canonical view volume.&#xD;&#xA;&#xD;&#xA;TRS is applied in this manner: T(R(S(p))), i.e. the scale is applied first, then the rotation, then the translation.&#xD;&#xA;&#xD;&#xA;MVP is applied in this manner: P(V(M(p))), i.e. we apply the model matrix first, then the view matrix, and finally the projection matrix.&#xD;&#xA;&#xD;&#xA;Why is the order in which we name these sets not consistent? I feel like I am getting something very obvious wrong, but I can't help but be confused by this." ContentLicense="CC BY-SA 4.0" />
  <row Id="25260" PostHistoryTypeId="1" PostId="9239" RevisionGUID="713e328d-b065-410a-a54a-60371c7a7b0c" CreationDate="2019-10-12T18:42:21.877" UserId="11304" Text="Why do we call it TRS and MVP, instead of SRT and MVP or TRS and PVM?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25261" PostHistoryTypeId="3" PostId="9239" RevisionGUID="713e328d-b065-410a-a54a-60371c7a7b0c" CreationDate="2019-10-12T18:42:21.877" UserId="11304" Text="|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25262" PostHistoryTypeId="2" PostId="9240" RevisionGUID="b1c4f049-9f6c-4984-a4e5-18bfffeb015f" CreationDate="2019-10-12T20:15:22.553" UserId="10096" Text="Because whether you use $MVP$ or $PVM$ actually depends on how you perform the multiplication: $vMVP$ versus $PVMv$, note that you have:&#xD;&#xA;$(PVMv)^T = v^TM^TV^TP^T=vM^TV^TP^T$, where the last identity does not hold in math, but holds in glsl since vectors can be reinterpreted as either row or column vectors depending on convenience.&#xD;&#xA;&#xD;&#xA;The same holds for $TRS$ and $SRT$. In general CG code and applications have an issue with sticking to standard established conventions, so you get all kinds of funny conventions." ContentLicense="CC BY-SA 4.0" />
  <row Id="25263" PostHistoryTypeId="5" PostId="9240" RevisionGUID="09ed179a-4530-4a9d-9f22-c47faee526a6" CreationDate="2019-10-12T20:21:18.687" UserId="10096" Comment="deleted 9 characters in body" Text="Because whether you use $MVP$ or $PVM$ actually depends on how you perform the multiplication: $vMVP$ versus $PVMv$, note that you have:&#xD;&#xA;$(PVMv)^T = v^TM^TV^TP^T=vM^TV^TP^T$, where the last identity does not hold in math, but holds in glsl since vectors can be reinterpreted as either row or column vectors for convenience.&#xD;&#xA;&#xD;&#xA;The same holds for $TRS$ and $SRT$. In general CG code and applications have an issue with sticking to standard established conventions, so you get all kinds of funny conventions." ContentLicense="CC BY-SA 4.0" />
  <row Id="25267" PostHistoryTypeId="2" PostId="9241" RevisionGUID="ab20f70f-7447-432a-b9f2-483ee3bbc2e6" CreationDate="2019-10-13T11:39:48.907" UserId="5496" Text="What is the difference between all these techniques? I know what a lightning model does, eg Phong, Flat, Gouraud. As far as I know both Ray Tracing and Global Illumination are just lighting models different from the classic ones mentioned above that simulate physical light more accurately, taking into account light ray bouncing, indirect light etc.&#xD;&#xA;&#xD;&#xA;As for shadows, I believe not all lighting models can support shadows. Are shadows something implemented on top of a lighting model, ie they can't be used without a proper one that supports them, or are they used independently of lighting?&#xD;&#xA;&#xD;&#xA;I know that the rendering equation is a general technique for the approximation of lighting in a 3D world. Is the rendering equation used in conjuction with a lighting model, or is a &quot;lighting model&quot; an implementation of the redering equation?&#xD;&#xA;&#xD;&#xA;Does the rendering equation account for shadows as well (from its form on wikipedia I think not) and if not should an &quot;extended&quot; rendering equation be developed for a particular 3d world that enables shadows?&#xD;&#xA;&#xD;&#xA;I'm trying to clarify this foggy cloud of concepts in my mind. Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="25268" PostHistoryTypeId="1" PostId="9241" RevisionGUID="ab20f70f-7447-432a-b9f2-483ee3bbc2e6" CreationDate="2019-10-13T11:39:48.907" UserId="5496" Text="Difference betwen Rendering Equation, Lighting model, Ray Tracing, Global Illumination and Shadows?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25269" PostHistoryTypeId="3" PostId="9241" RevisionGUID="ab20f70f-7447-432a-b9f2-483ee3bbc2e6" CreationDate="2019-10-13T11:39:48.907" UserId="5496" Text="|rendering|lighting|global-illumination|shading|theory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25270" PostHistoryTypeId="2" PostId="9242" RevisionGUID="15f08fcb-ccd6-492c-9749-1b8eb985c794" CreationDate="2019-10-13T12:47:16.817" UserId="4958" Text="I believe that Space Engine as a base algorithm still uses Precomputed Atmospheric Scattering by E. Bruneton. It is released on [github][1]. So it is good starting point if you want to implement atmospheric scattering.&#xD;&#xA;&#xD;&#xA;For beginner this algorithm is pretty advanced stuff written in C++11, and modern OpenGL, so such knowledge is required. In short, to avoid a cost of solving rendering equation for scattering in participating medium (single as well as multiple scattering) it uses precomputed textures where it is possible and equations for Rayleigh and Mie scattering based on physical model.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ebruneton/precomputed_atmospheric_scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="25271" PostHistoryTypeId="5" PostId="9242" RevisionGUID="4477c123-ac72-426f-a6b8-fd23289c7ea4" CreationDate="2019-10-13T13:11:40.243" UserId="4958" Comment="added 208 characters in body" Text="I believe that Space Engine as a base algorithm still uses Precomputed Atmospheric Scattering by E. Bruneton. It is released on [github][1]. So it is good starting point if you want to implement atmospheric scattering.&#xD;&#xA;&#xD;&#xA;For beginner this algorithm is pretty advanced stuff written in C++11, and modern OpenGL, so such knowledge is required. In short, to avoid a cost of solving rendering equation for scattering in participating medium (single as well as multiple scattering) it uses precomputed textures where it is possible and equations for Rayleigh and Mie scattering based on physical model.&#xD;&#xA;&#xD;&#xA;There is also [simpler demo][2] computed in real time on shadertoy. It involves raycasting a sphere and integrating Rayleigh and Mie scattering in real time.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ebruneton/precomputed_atmospheric_scattering&#xD;&#xA;  [2]: https://www.shadertoy.com/view/lslXDr" ContentLicense="CC BY-SA 4.0" />
  <row Id="25272" PostHistoryTypeId="5" PostId="9242" RevisionGUID="d1f9d71b-ace0-44a1-9bd6-3d2f7c640bd3" CreationDate="2019-10-13T13:19:00.317" UserId="4958" Comment="added 208 characters in body" Text="I believe that Space Engine as a base algorithm still uses Precomputed Atmospheric Scattering by E. Bruneton. It is released on [github][1]. So it is good starting point if you want to implement atmospheric scattering.&#xD;&#xA;&#xD;&#xA;For beginner this algorithm is pretty advanced stuff written in C++11, and modern OpenGL, so such knowledge is required. In short, to avoid a cost of solving rendering equation for scattering in participating medium (single as well as multiple scattering) it uses precomputed lookup textures where it is possible and equations for Rayleigh and Mie scattering based on physical model.&#xD;&#xA;&#xD;&#xA;There is also [simpler demo][2] computed in real time on shadertoy. It involves raycasting a sphere and integrating Rayleigh and Mie scattering in real time. It is based on [GPU Gems article][3], which provides some good information how it works.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ebruneton/precomputed_atmospheric_scattering&#xD;&#xA;  [2]: https://www.shadertoy.com/view/lslXDr&#xD;&#xA;  [3]: https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter16.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="25273" PostHistoryTypeId="5" PostId="9242" RevisionGUID="ebf44d20-d9e0-4c8b-b46d-caea701ae230" CreationDate="2019-10-13T13:24:35.587" UserId="4958" Comment="added 12 characters in body" Text="I believe that Space Engine as a base algorithm still uses Precomputed Atmospheric Scattering by E. Bruneton. It is released on [github][1]. So it is good starting point if you want to implement atmospheric scattering.&#xD;&#xA;&#xD;&#xA;For beginner this algorithm is pretty advanced stuff written in C++11, and modern OpenGL, so such knowledge is required. In short, to avoid a cost of solving rendering equation for scattering in participating medium (single as well as multiple scattering) it uses precomputed lookup textures where it is possible and equations for Rayleigh and Mie scattering based on physical model.&#xD;&#xA;&#xD;&#xA;There is also [simpler demo][2] computed in real time on shadertoy. This is probably better place to start. It involves raycasting a sphere and integrating Rayleigh and Mie scattering along a ray in real time. It is based on [GPU Gems article][3], which provides some good information how it works.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/ebruneton/precomputed_atmospheric_scattering&#xD;&#xA;  [2]: https://www.shadertoy.com/view/lslXDr&#xD;&#xA;  [3]: https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter16.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="25274" PostHistoryTypeId="2" PostId="9243" RevisionGUID="69278a0f-6a77-4f6e-b991-d5cde13f4e57" CreationDate="2019-10-13T14:24:12.247" UserId="10096" Text="The rendering equation aims to describe what the light distribution for a specific scene is, under several assumptions. The most important assumption is that we are working in a **geometrical optics framework** - so we do not consider the wave properties of light - meaning no diffraction for example, we also do not consider quantum effects, such as phosphorescence. If the rendering equation is not in its spectral form, then there's also no dispersion. &#xD;&#xA;&#xD;&#xA;There are additional constraints on top of what we have for geometrical optics, like **light travels instantaneously**, light rays traveling in **straight paths** from surface to surface (no spatially continuously varying indices of refraction), no polarization, etc. Many of the constraints can be removed in more general formulations (which are also available), but usually that incurs heavier computations.&#xD;&#xA;&#xD;&#xA;So the rendering equation serves as an approximation to how light works in the real world, but since we want to model only a subset of light effects, various simplification are made in order to make the problem easier to solve. &#xD;&#xA;&#xD;&#xA;Let us consider the commonly shown formulation:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![The rendering equation][1]][1]&#xD;&#xA;[![The rendering equation][2]][2]&#xD;&#xA;&#xD;&#xA;The above images are linked from: [Raytracing - Rendering Equation Insight][3]&#xD;&#xA;&#xD;&#xA;I believe these images are fairly self-explanatory. The function $f_r$ referred to as the [BRDF][4] (or more generally the [BSDF][5]) describes the interaction of materials with light. Often in real-time graphics this is referred to as the illumination or reflectance model - one such example is [the Blinn–Phong reflection model][6], there is the [Cook-Torrance model][7] too, and several others. All of those are brdfs/bsdfs, or constituent parts of brdfs/bsdfs.&#xD;&#xA;&#xD;&#xA;Flat, Gouraud, and Phong shading (or more correctly Gouraud and Phong **interpolation**) is really referring to how the normals of a model are treated (interpolated). &#xD;&#xA;&#xD;&#xA;[Flat shading][8] simply uses the actual normals of an object. If we could render objects made up of infinitely many triangles, even flat shading would be ideal. However, as for most things in graphics, efficiency is key, so we cannot use infinitely may triangles. For that reason people have chosen to modify the surface normals of objects, in order to get a smoother appearance - as if they used a lot more triangles. How is this achieved? Well, one can find per-vertex normals, that are a weighted sum of the face normals, so that a smooth like appearance is achieved. For example by using approaches such as the one described in the following publication: [Weights for Computing Vertex Normals from Facet Normals][9]. &#xD;&#xA;&#xD;&#xA;[Gouraud shading][10] (Gouraud interpolation), refers to computing the illumination per vertex, using these normals, and then **interpolating** the resulting color over the triangle - this explains why it has discontinuities at edges and vertices. &#xD;&#xA;&#xD;&#xA;[Phong shading][11] (Phong interpolation) **interpolates** the normals over the triangle (by using barycentric coordinates) and then computes the shading using those per-pixel which results in an overall smoother appearance. Note that discontinuities at the outline of the object can still be visible - this modifies only the shading of the object, and not its actual geometry.&#xD;&#xA;&#xD;&#xA;One can go further and use [bump mapping][12], [derivative mapping][13], or [normal mapping][14], in order to further enrich the shading information over an otherwise flat surface, by modifying the normals.&#xD;&#xA;&#xD;&#xA;All of those normal modifications (Gouraud and Phong interpolation; bump, derivative, and normal mapping) produce normals which are commonly referred to as shading normals. Note that those violate energy conservation principles in general, and may cause various artifacts. But obviously this is the trade-off for performance. So **all of those techniques fall under the umbrella of normals modification and are not illumination models in their own right** (but those normals are used in the brdf and the rendering equation to compute shading - where the shading part in the terms goes - I still believe interpolating is a better naming).&#xD;&#xA;&#xD;&#xA;To understand the shadow conundrum, let's look at the solution of the rendering equation. The rendering equation in mathematics is known as [Fredholm integral equation of the second kind][15], under some assumptions, its solution is given through the sum of increasingly dimensional integrals: [Liouville–Neumann series][16]. I will avoid writing out the integrals explicitly, since it will get ugly very quickly, you can find the expansion in Veach's thesis however. I will just use the operator formulation of the rendering equation. Let $L = L_o$, and $T$ be that integral from the images. Then the rendering equation can be written concisely as:&#xD;&#xA;&#xD;&#xA;$$L = L_e + L_r = L_e + TL$$&#xD;&#xA;$$L-TL = L_e$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e = \sum_{k=0}^{\infty}T^kL_e$$&#xD;&#xA;&#xD;&#xA;The last equality holds due to the Liouville-Neumann expansion that I talked about. This is a sum of increasingly dimensional integrals similar to the one you had in the rendering equation (with a few additions) - usually this is also done with respect to the area formulation of the rendering equation (the images here provide the solid angle formulation). Informally $T^k$ means that there were $k$ bounces before reaching the light source, so it's a sum of the energy coming from paths starting at the eye and ending at a light source, of length $1, 2, 3, ..., \infty$. Let's look at the area formulation of the rendering equation:&#xD;&#xA;&#xD;&#xA;$$L(\pmb{x}_0\leftarrow\pmb{x}_1) = L_e(\pmb{x}_0\leftarrow\pmb{x}_1) + \int_{\mathcal{M}}f_r(\pmb{x}_0\leftarrow\pmb{x}_1\leftarrow\pmb{x}_2)L(\pmb{x}_1\leftarrow\pmb{x}_2)\frac{\cos\theta_{\pmb{x}_1}\cos\theta_{\pmb{x}_2}}{\|\pmb{x}_2-\pmb{x}_1\|^2_2}V(\pmb{x}_1,\pmb{x}_2)\,d\pmb{x}_2$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $\mathcal{M}$ is the set of all surface points of the scene (including lights), $L(\pmb{x}_0\leftarrow\pmb{x}_1)$ gives you the radiance traveling from surface point $\pmb{x}_1$ to $\pmb{x}_0$, $L_e(\pmb{x}_0\leftarrow\pmb{x}_1)$ gives you the emission from $\pmb{x}_1$ towards $\pmb{x}_0$. To relate the brds to the previous formulation, one can set: $\omega_o = \frac{\pmb{x}_0-\pmb{x}_1}{\|\pmb{x}_0-\pmb{x}_1\|}$, $\omega_i = \frac{\pmb{x}_2-\pmb{x}_1}{\|\pmb{x}_2-\pmb{x}_1\|}$, and $\pmb{x} = \pmb{x}_1$. Furthermore, $\cos\theta_{\pmb{x}_1} = \omega_i \cdot \pmb{n}$, where $\pmb{n}$ is the surface normal at $\pmb{x}_1$, similarly $\cos\theta_{\pmb{x}_2} = -\omega_i \cdot \pmb{n}_{\pmb{x}_2}$, where $\pmb{n}_{\pmb{x}_2}$ is the surface normal at $\pmb{x}_2$. The squared Euclidean distance in the denominator is due to the [inverse-square law][17] (it's implicitly encoded in the solid angle formulation). Finally, $V(\pmb{x}_1,\pmb{x}_2)$ is the visibility function - it is equal to $1$ if there is nothing between $\pmb{x}_1$ and $\pmb{x}_2$ (no occlusion), and $0$ otherwise (it is also implicit in the solid angle formulation) - this is the function that encodes shadows. Approximations, that do not produce shadows, have simply thrown away or modified that visibility function (one such modification is replacing $V$ with the ambient occlusion or with information from a shadow map). This is done for efficiency reasons once again, as instead you would have to trace a ray from $\pmb{x}_1$ to $\pmb{x}_2$ and intersect against the scene to check for occlusion.&#xD;&#xA;&#xD;&#xA;Let us consider the simplifications that are usually made in real-time graphics. Most implementations, simply cut the Neumann sum to the 2nd term:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL_e + T^2L_e + ... \approx L_e + TL_e$$&#xD;&#xA;&#xD;&#xA;So anything beyond direct illumination and emission is thrown away. This has important implications - such as: no indirect illumination or scattering effects. Let's consider what this amounts to:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL_e$$&#xD;&#xA;&#xD;&#xA;$$L(\pmb{x}_0\leftarrow\pmb{x}_1) = L_e(\pmb{x}_0\leftarrow\pmb{x}_1) + \\ \int_{\mathcal{M}}f_r(\pmb{x}_0\leftarrow\pmb{x}_1\leftarrow\pmb{x}_2)L_e(\pmb{x}_1\leftarrow\pmb{x}_2)\frac{\cos\theta_{\pmb{x}_1}\cos\theta_{\pmb{x}_2}}{\|\pmb{x}_2-\pmb{x}_1\|^2_2}V(\pmb{x}_1,\pmb{x}_2)\,d\pmb{x}_2$$&#xD;&#xA;&#xD;&#xA;There is one small difference compared to the area formulation, and that is the fact that we have change $L$ with $L_e$ in the integral, so it is not a recursive integral anymore. It is still an integral however, which implies an infinite sum - this is currently not very fast to compute, unless you have specialized hardware like RTX, especially for more complex scenes. Note that the integral is over all surface points emitting light, so you would in general need to sum up the light coming from area lights, skyboxes etc.&#xD;&#xA;&#xD;&#xA;So the next simplification that is usually done, is using point lights. Point lights have the computationally efficient property, that they are represented through [Dirac delta functions][18]. A Dirac delta function, essentially allows you to get rid of the integral - the light comes only from a single direction. Then your integral turns into a finite sum over all point lights in the scene (a similar argument may be made for directional or spot lights, note that the light cosine term disappears, since informally there's no normal to speak of):&#xD;&#xA;&#xD;&#xA;$$L(\pmb{x}_0\leftarrow\pmb{x}_1) = L_e(\pmb{x}_0\leftarrow\pmb{x}_1) + \\ \sum_{k=1}^{N}f_r(\pmb{x}_0\leftarrow\pmb{x}_1\leftarrow\pmb{y}_k)L_k(\pmb{x}_1\leftarrow\pmb{y}_k)\frac{\cos\theta_{\pmb{x}_1}}{\|\pmb{y}_k-\pmb{x}_1\|^2_2}V(\pmb{x}_1,\pmb{y}_k)$$&#xD;&#xA;&#xD;&#xA;Where $L_e$ is generally constant, $L_k$ is the radiance of light source $k$ and $\pmb{y}_k$ is the position of light source $k$. If your material is diffuse then $f_r$  and the radiance of the point light does not change with directions, the $L_i$ and $f_r$ are also constant so you get the (possibly) familiar expression:&#xD;&#xA;&#xD;&#xA;$$L = L_e + \sum_{k=1}^{N}f_rL_k\cos\theta_k V(\pmb{x}_1,\pmb{y}_k)$$&#xD;&#xA;$$color = emission + \sum_{k=1}^{N}ObjectColor * LightColor * \cos\theta_k * VisibilityFromLight\_k$$&#xD;&#xA;&#xD;&#xA;The only thing that is usually not there is the $V$ term, since it requires tracing rays through the scene, which standard rasterization algorithms don't do. So it's either set to $1$, or replaced with information from a shadow map (for each summand the shadow map from this light's perspective ought to be used for semi-correct results). Often times the remaining terms that were cut off $T^2L_e + T^3L_e + ... + T^{\infty}L_e$ are substituted with a constant ambient light term or with an ambient occlusion term.&#xD;&#xA;&#xD;&#xA;Path tracing usually solves the rendering equation without any of the above simplifications (but requires a lot more computational power), that is the reason why images produced by it look so realistic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Whole books may be written on this matter. But I hope I managed to clarify at least some things regarding Gouraud, Phong interpolation, shadows, and how all of this ties into the rendering equation.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pTB8o.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zDg2Q.png&#xD;&#xA;  [3]: http://viclw17.github.io/2018/06/30/raytracing-rendering-equation/&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Bidirectional_scattering_distribution_function&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Specular_highlight#Cook%E2%80%93Torrance_model&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Shading#Flat_shading&#xD;&#xA;  [9]: https://www.semanticscholar.org/paper/Weights-for-Computing-Vertex-Normals-from-Facet-Max/f6eb2950de296424d35338893f193fb3adb74367&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Gouraud_shading&#xD;&#xA;  [11]: https://en.wikipedia.org/wiki/Phong_shading&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Bump_mapping&#xD;&#xA;  [13]: http://johnwhigham.blogspot.com/2015/03/derivative-mapping.html&#xD;&#xA;  [14]: https://en.wikipedia.org/wiki/Normal_mapping&#xD;&#xA;  [15]: https://en.wikipedia.org/wiki/Fredholm_integral_equation#Equation_of_the_second_kind&#xD;&#xA;  [16]: https://en.wikipedia.org/wiki/Liouville%E2%80%93Neumann_series&#xD;&#xA;  [17]: https://en.wikipedia.org/wiki/Inverse-square_law&#xD;&#xA;  [18]: https://en.wikipedia.org/wiki/Dirac_delta_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="25275" PostHistoryTypeId="5" PostId="9243" RevisionGUID="ebeb8aff-ef56-4485-b8f1-e2efcc9ca763" CreationDate="2019-10-13T14:30:42.087" UserId="10096" Comment="typo" Text="The rendering equation aims to describe what the light distribution for a specific scene is, under several assumptions. The most important assumption is that we are working in a **geometrical optics framework** - so we do not consider the wave properties of light - meaning no diffraction for example, we also do not consider quantum effects, such as phosphorescence. If the rendering equation is not in its spectral form, then there's also no dispersion. &#xD;&#xA;&#xD;&#xA;There are additional constraints on top of what we have for geometrical optics, like **light travels instantaneously**, light rays traveling in **straight paths** from surface to surface (no spatially continuously varying indices of refraction), no polarization, etc. Many of the constraints can be removed in more general formulations (which are also available), but usually that incurs heavier computations.&#xD;&#xA;&#xD;&#xA;So the rendering equation serves as an approximation to how light works in the real world, but since we want to model only a subset of light effects, various simplification are made in order to make the problem easier to solve. &#xD;&#xA;&#xD;&#xA;Let us consider the commonly shown formulation:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![The rendering equation][1]][1]&#xD;&#xA;[![The rendering equation][2]][2]&#xD;&#xA;&#xD;&#xA;The above images are linked from: [Raytracing - Rendering Equation Insight][3]&#xD;&#xA;&#xD;&#xA;I believe these images are fairly self-explanatory. The function $f_r$ referred to as the [BRDF][4] (or more generally the [BSDF][5]) describes the interaction of materials with light. Often in real-time graphics this is referred to as the illumination or reflectance model - one such example is [the Blinn–Phong reflection model][6], there is the [Cook-Torrance model][7] too, and several others. All of those are brdfs/bsdfs, or constituent parts of brdfs/bsdfs.&#xD;&#xA;&#xD;&#xA;Flat, Gouraud, and Phong shading (or more correctly Gouraud and Phong **interpolation**) is really referring to how the normals of a model are treated (interpolated). &#xD;&#xA;&#xD;&#xA;[Flat shading][8] simply uses the actual normals of an object. If we could render objects made up of infinitely many triangles, even flat shading would be ideal. However, as for most things in graphics, efficiency is key, so we cannot use infinitely may triangles. For that reason people have chosen to modify the surface normals of objects, in order to get a smoother appearance - as if they used a lot more triangles. How is this achieved? Well, one can find per-vertex normals, that are a weighted sum of the face normals, so that a smooth like appearance is achieved. For example by using approaches such as the one described in the following publication: [Weights for Computing Vertex Normals from Facet Normals][9]. &#xD;&#xA;&#xD;&#xA;[Gouraud shading][10] (Gouraud interpolation), refers to computing the illumination per vertex, using these normals, and then **interpolating** the resulting color over the triangle - this explains why it has discontinuities at edges and vertices. &#xD;&#xA;&#xD;&#xA;[Phong shading][11] (Phong interpolation) **interpolates** the normals over the triangle (by using barycentric coordinates) and then computes the shading using those per-pixel which results in an overall smoother appearance. Note that discontinuities at the outline of the object can still be visible - this modifies only the shading of the object, and not its actual geometry.&#xD;&#xA;&#xD;&#xA;One can go further and use [bump mapping][12], [derivative mapping][13], or [normal mapping][14], in order to further enrich the shading information over an otherwise flat surface, by modifying the normals.&#xD;&#xA;&#xD;&#xA;All of those normal modifications (Gouraud and Phong interpolation; bump, derivative, and normal mapping) produce normals which are commonly referred to as shading normals. Note that those violate energy conservation principles in general, and may cause various artifacts. But obviously this is the trade-off for performance. So **all of those techniques fall under the umbrella of normals modification and are not illumination models in their own right** (but those normals are used in the brdf and the rendering equation to compute shading - where the shading part in the terms goes - I still believe interpolating is a better naming).&#xD;&#xA;&#xD;&#xA;To understand the shadow conundrum, let's look at the solution of the rendering equation. The rendering equation in mathematics is known as a [Fredholm integral equation of the second kind][15], under some assumptions, its solution is given through the sum of increasingly dimensional integrals: [Liouville–Neumann series][16]. I will avoid writing out the integrals explicitly, since it will get ugly very quickly, you can find the expansion in Veach's thesis however. I will just use the operator formulation of the rendering equation. Let $L = L_o$, and $T$ be that integral from the images. Then the rendering equation can be written concisely as:&#xD;&#xA;&#xD;&#xA;$$L = L_e + L_r = L_e + TL$$&#xD;&#xA;$$L-TL = L_e$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e = \sum_{k=0}^{\infty}T^kL_e$$&#xD;&#xA;&#xD;&#xA;The last equality holds due to the Liouville-Neumann expansion that I talked about. This is a sum of increasingly dimensional integrals similar to the one you had in the rendering equation (with a few additions) - usually this is also done with respect to the area formulation of the rendering equation (the images here provide the solid angle formulation). Informally $T^k$ means that there were $k$ bounces before reaching the light source, so it's a sum of the energy coming from paths starting at the eye and ending at a light source, of length $1, 2, 3, ..., \infty$. Let's look at the area formulation of the rendering equation:&#xD;&#xA;&#xD;&#xA;$$L(\pmb{x}_0\leftarrow\pmb{x}_1) = L_e(\pmb{x}_0\leftarrow\pmb{x}_1) + \\ \int_{\mathcal{M}}f_r(\pmb{x}_0\leftarrow\pmb{x}_1\leftarrow\pmb{x}_2)L(\pmb{x}_1\leftarrow\pmb{x}_2)\frac{\cos\theta_{\pmb{x}_1}\cos\theta_{\pmb{x}_2}}{\|\pmb{x}_2-\pmb{x}_1\|^2_2}V(\pmb{x}_1,\pmb{x}_2)\,d\pmb{x}_2$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here $\mathcal{M}$ is the set of all surface points of the scene (including lights), $L(\pmb{x}_0\leftarrow\pmb{x}_1)$ gives you the radiance traveling from surface point $\pmb{x}_1$ to $\pmb{x}_0$, $L_e(\pmb{x}_0\leftarrow\pmb{x}_1)$ gives you the emission from $\pmb{x}_1$ towards $\pmb{x}_0$. To relate the brds to the previous formulation, one can set: $\omega_o = \frac{\pmb{x}_0-\pmb{x}_1}{\|\pmb{x}_0-\pmb{x}_1\|}$, $\omega_i = \frac{\pmb{x}_2-\pmb{x}_1}{\|\pmb{x}_2-\pmb{x}_1\|}$, and $\pmb{x} = \pmb{x}_1$. Furthermore, $\cos\theta_{\pmb{x}_1} = \omega_i \cdot \pmb{n}$, where $\pmb{n}$ is the surface normal at $\pmb{x}_1$, similarly $\cos\theta_{\pmb{x}_2} = -\omega_i \cdot \pmb{n}_{\pmb{x}_2}$, where $\pmb{n}_{\pmb{x}_2}$ is the surface normal at $\pmb{x}_2$. The squared Euclidean distance in the denominator is due to the [inverse-square law][17] (it's implicitly encoded in the solid angle formulation). Finally, $V(\pmb{x}_1,\pmb{x}_2)$ is the visibility function - it is equal to $1$ if there is nothing between $\pmb{x}_1$ and $\pmb{x}_2$ (no occlusion), and $0$ otherwise (it is also implicit in the solid angle formulation) - this is the function that encodes shadows. Approximations, that do not produce shadows, have simply thrown away or modified that visibility function (one such modification is replacing $V$ with the ambient occlusion or with information from a shadow map). This is done for efficiency reasons once again, as instead you would have to trace a ray from $\pmb{x}_1$ to $\pmb{x}_2$ and intersect against the scene to check for occlusion.&#xD;&#xA;&#xD;&#xA;Let us consider the simplifications that are usually made in real-time graphics. Most implementations, simply cut the Neumann sum to the 2nd term:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL_e + T^2L_e + ... \approx L_e + TL_e$$&#xD;&#xA;&#xD;&#xA;So anything beyond direct illumination and emission is thrown away. This has important implications - such as: no indirect illumination or scattering effects. Let's consider what this amounts to:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL_e$$&#xD;&#xA;&#xD;&#xA;$$L(\pmb{x}_0\leftarrow\pmb{x}_1) = L_e(\pmb{x}_0\leftarrow\pmb{x}_1) + \\ \int_{\mathcal{M}}f_r(\pmb{x}_0\leftarrow\pmb{x}_1\leftarrow\pmb{x}_2)L_e(\pmb{x}_1\leftarrow\pmb{x}_2)\frac{\cos\theta_{\pmb{x}_1}\cos\theta_{\pmb{x}_2}}{\|\pmb{x}_2-\pmb{x}_1\|^2_2}V(\pmb{x}_1,\pmb{x}_2)\,d\pmb{x}_2$$&#xD;&#xA;&#xD;&#xA;There is one small difference compared to the area formulation, and that is the fact that we have $L_e$ in the integral and not $L$, so it is not a recursive integral anymore. It is still an integral however, which implies an infinite sum - this is currently not very fast to compute, unless you have specialized hardware like RTX, especially for more complex scenes. Note that the integral is over all surface points emitting light, so you would in general need to sum up the light coming from area lights, skyboxes etc.&#xD;&#xA;&#xD;&#xA;So the next simplification that is usually done, is using point lights. Point lights have the computationally efficient property, that they are represented through [Dirac delta functions][18]. A Dirac delta function, essentially allows you to get rid of the integral - the light comes only from a single direction. Then your integral turns into a finite sum over all point lights in the scene (a similar argument may be made for directional or spot lights, note that the light cosine term disappears, since informally there's no normal to speak of):&#xD;&#xA;&#xD;&#xA;$$L(\pmb{x}_0\leftarrow\pmb{x}_1) = L_e(\pmb{x}_0\leftarrow\pmb{x}_1) + \\ \sum_{k=1}^{N}f_r(\pmb{x}_0\leftarrow\pmb{x}_1\leftarrow\pmb{y}_k)L_k(\pmb{x}_1\leftarrow\pmb{y}_k)\frac{\cos\theta_{\pmb{x}_1}}{\|\pmb{y}_k-\pmb{x}_1\|^2_2}V(\pmb{x}_1,\pmb{y}_k)$$&#xD;&#xA;&#xD;&#xA;Where $L_e$ is generally constant, $L_k$ is the radiance of light source $k$ and $\pmb{y}_k$ is the position of light source $k$. If your material is diffuse then $f_r$  and the radiance of the point light do not change with directions, then $L_i$ and $f_r$ are also constant so you get the (possibly) familiar expression:&#xD;&#xA;&#xD;&#xA;$$L = L_e + \sum_{k=1}^{N}f_rL_k\cos\theta_k V(\pmb{x}_1,\pmb{y}_k)$$&#xD;&#xA;$$color = emission + \sum_{k=1}^{N}ObjectColor * LightColor * \cos\theta_k * VisibilityFromLight\_k$$&#xD;&#xA;&#xD;&#xA;The only thing that is usually not there is the $V$ term, since it requires tracing rays through the scene, which standard rasterization algorithms don't do. So it's either set to $1$, or replaced with information from a shadow map (for each summand the shadow map from this light's perspective ought to be used for semi-correct results). Often times the remaining terms that were cut off $T^2L_e + T^3L_e + ... + T^{\infty}L_e$ are substituted with a constant ambient light term or with an ambient occlusion term.&#xD;&#xA;&#xD;&#xA;Path tracing usually solves the rendering equation without any of the above simplifications (but requires a lot more computational power), that is the reason why images produced by it look so realistic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Whole books may be written on this matter. But I hope I managed to clarify at least some things regarding Gouraud, Phong interpolation, shadows, and how all of this ties into the rendering equation.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pTB8o.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zDg2Q.png&#xD;&#xA;  [3]: http://viclw17.github.io/2018/06/30/raytracing-rendering-equation/&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Bidirectional_scattering_distribution_function&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Specular_highlight#Cook%E2%80%93Torrance_model&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Shading#Flat_shading&#xD;&#xA;  [9]: https://www.semanticscholar.org/paper/Weights-for-Computing-Vertex-Normals-from-Facet-Max/f6eb2950de296424d35338893f193fb3adb74367&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Gouraud_shading&#xD;&#xA;  [11]: https://en.wikipedia.org/wiki/Phong_shading&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Bump_mapping&#xD;&#xA;  [13]: http://johnwhigham.blogspot.com/2015/03/derivative-mapping.html&#xD;&#xA;  [14]: https://en.wikipedia.org/wiki/Normal_mapping&#xD;&#xA;  [15]: https://en.wikipedia.org/wiki/Fredholm_integral_equation#Equation_of_the_second_kind&#xD;&#xA;  [16]: https://en.wikipedia.org/wiki/Liouville%E2%80%93Neumann_series&#xD;&#xA;  [17]: https://en.wikipedia.org/wiki/Inverse-square_law&#xD;&#xA;  [18]: https://en.wikipedia.org/wiki/Dirac_delta_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="25277" PostHistoryTypeId="2" PostId="9245" RevisionGUID="e94a7203-62dc-4bbe-ad86-c107a56353f7" CreationDate="2019-10-14T02:04:25.693" UserId="3003" Text="One algorithm that's pretty good for this, but very difficult to implement is to find the [Medial Axis](https://en.wikipedia.org/wiki/Medial_axis) of the shape and then have various profiles that are based on the signed distance from the medial axis. You can also use the [Straight Skeleton](https://en.wikipedia.org/wiki/Straight_skeleton) instead of the Medial Axis, but it's also a bit of a pain to calculate.&#xD;&#xA;&#xD;&#xA;An easier way that's not quite as accurate, but usually good enough is described here: [https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf](https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf). You can take a bitmap of the shape the user drew, shrink it down to some manageable size, calculate the distance of every pixel from the edges of the shape, then scale it to the size you need (and scale the distances accordingly). Once you have signed distances you can use them with the same 3D profiles mentioned above.&#xD;&#xA;&#xD;&#xA;For example, the pillow in the video you showed is basically drawn as a square. Your 3D profile would set the front face height to 0 at the squares edges, and increasing up to some maximum as you moved towards the center, peaking after a short distance and holding up to the center. The back face height would be the same but in the opposite direction." ContentLicense="CC BY-SA 4.0" />
  <row Id="25281" PostHistoryTypeId="2" PostId="9247" RevisionGUID="3a599a93-e065-4731-b8ac-a9bf8798436e" CreationDate="2019-10-14T09:22:24.930" UserId="11312" Text="&#xD;&#xA;This is a screen shot from an animation generated by [a matplotlib example][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;the key part in the code is &#xD;&#xA;&#xD;&#xA;        R = 1 - np.sqrt(X**2 + Y**2)&#xD;&#xA;        Z = np.cos(2 * np.pi * X + phi) * R&#xD;&#xA;&#xD;&#xA;corresponding equation is&#xD;&#xA;&#xD;&#xA;$\left(- \sqrt{X^{2} + Y^{2}} + 1\right) \cos{\left (2 \pi X + \phi \right )}$&#xD;&#xA;&#xD;&#xA;Could some give an explanation or hint about this kind of equation?&#xD;&#xA;&#xD;&#xA;Is there a name of this type of graphics?&#xD;&#xA;&#xD;&#xA;usually cosine/sine could generate something like a (half) circle, what does `R` part do?&#xD;&#xA;&#xD;&#xA;  [1]: https://matplotlib.org/1.2.1/examples/mplot3d/wire3d_animation_demo.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/JbI9h.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25282" PostHistoryTypeId="1" PostId="9247" RevisionGUID="3a599a93-e065-4731-b8ac-a9bf8798436e" CreationDate="2019-10-14T09:22:24.930" UserId="11312" Text="Could some give an explanation or hint about this kind of equation? $\left(- \sqrt{X^{2} + Y^{2}} + 1\right) \cos{\left (2 \pi X + \phi \right )}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="25283" PostHistoryTypeId="3" PostId="9247" RevisionGUID="3a599a93-e065-4731-b8ac-a9bf8798436e" CreationDate="2019-10-14T09:22:24.930" UserId="11312" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25284" PostHistoryTypeId="2" PostId="9248" RevisionGUID="211df7ec-897e-4a95-a2e1-8f532ef5047d" CreationDate="2019-10-14T16:04:13.560" UserId="11316" Text="I am trying to render a dielectric sphere inside the Cornell Box. Some circles are generated on the sphere. Here is the photo generated by path tracer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kEAYT.png&#xD;&#xA;&#xD;&#xA;And below is my main function:&#xD;&#xA;&#xD;&#xA;    function trace(surfaces::Array{Surfaces, 1}, ray::Ray, depth::Int64, maxDepth::Int64)&#xD;&#xA;    if depth &gt;= maxDepth&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    t, material = nearest(surfaces, ray, Inf)&#xD;&#xA;    if typeof(material) == Empty&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    if material.isLight == true&#xD;&#xA;        return material.emittance&#xD;&#xA;    end&#xD;&#xA;    ρ = material.reflectance&#xD;&#xA;    n = material.normal&#xD;&#xA;    if material.isDielectric == true&#xD;&#xA;        cosθ = -dot(n, ray.d)&#xD;&#xA;        ref = material.ni/material.nt&#xD;&#xA;        if cosθ &lt; 0&#xD;&#xA;            cosθ = -cosθ&#xD;&#xA;            n = -1.0*n&#xD;&#xA;            ref = 1/ref&#xD;&#xA;        end&#xD;&#xA;        disc = 1 - ref*ref*(1-cosθ*cosθ)&#xD;&#xA;        if disc &lt; 0&#xD;&#xA;            R = ray.d - 2*dot(ray.d, n)*n&#xD;&#xA;            In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;            return In&#xD;&#xA;        elseif disc &gt; 0&#xD;&#xA;            R0 = (ref-1)/(ref+1)&#xD;&#xA;            R0 = R0*R0&#xD;&#xA;            Rθ = R0 + (1-R0)*(1-cosθ)*(1-cosθ)*(1-cosθ)*(1-cosθ)*(1-cosθ)&#xD;&#xA;            u = rand()&#xD;&#xA;            if u &lt; Rθ&#xD;&#xA;                R = ray.d - 2*dot(ray.d, n)*n&#xD;&#xA;                In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;                return In&#xD;&#xA;            else&#xD;&#xA;                R = ref*ray.d + (ref*cosθ - sqrt(disc))*n&#xD;&#xA;                In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;                return In&#xD;&#xA;            end&#xD;&#xA;        end&#xD;&#xA;    end      &#xD;&#xA;    BRDF = ρ/Π&#xD;&#xA;    R = hemiRand(n)&#xD;&#xA;    In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;    return Π*BRDF*In&#xD;&#xA;    end&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25285" PostHistoryTypeId="1" PostId="9248" RevisionGUID="211df7ec-897e-4a95-a2e1-8f532ef5047d" CreationDate="2019-10-14T16:04:13.560" UserId="11316" Text="Strange artifacts while rendering a dielectric material" ContentLicense="CC BY-SA 4.0" />
  <row Id="25286" PostHistoryTypeId="3" PostId="9248" RevisionGUID="211df7ec-897e-4a95-a2e1-8f532ef5047d" CreationDate="2019-10-14T16:04:13.560" UserId="11316" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25287" PostHistoryTypeId="5" PostId="9248" RevisionGUID="354c554a-875d-47d3-bcc7-46e917ba02b4" CreationDate="2019-10-14T16:42:48.153" UserId="11316" Comment="added 100 characters in body" Text="I am trying to render a dielectric sphere inside the Cornell Box. Some circles are generated on the sphere. Here is the photo generated by path tracer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kEAYT.png&#xD;&#xA;&#xD;&#xA;And below is my main function:&#xD;&#xA;&#xD;&#xA;    function trace(surfaces::Array{Surfaces, 1}, ray::Ray, depth::Int64, maxDepth::Int64)&#xD;&#xA;    if depth &gt;= maxDepth&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    t, material = nearest(surfaces, ray, Inf)&#xD;&#xA;    if typeof(material) == Empty&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    if material.isLight == true&#xD;&#xA;        return material.emittance&#xD;&#xA;    end&#xD;&#xA;    ρ = material.reflectance&#xD;&#xA;    n = material.normal&#xD;&#xA;    if material.isDielectric == true&#xD;&#xA;        cosθ = -dot(n, ray.d)&#xD;&#xA;        ref = material.ni/material.nt&#xD;&#xA;        if cosθ &lt; 0&#xD;&#xA;            cosθ = -cosθ&#xD;&#xA;            n = -1.0*n&#xD;&#xA;            ref = 1/ref&#xD;&#xA;        end&#xD;&#xA;        disc = 1 - ref*ref*(1-cosθ*cosθ)&#xD;&#xA;        if disc &lt; 0&#xD;&#xA;            R = ray.d - 2*dot(ray.d, n)*n&#xD;&#xA;            In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;            return In&#xD;&#xA;        elseif disc &gt; 0&#xD;&#xA;            R0 = (ref-1)/(ref+1)&#xD;&#xA;            R0 = R0*R0&#xD;&#xA;            Rθ = R0 + (1-R0)*(1-cosθ)*(1-cosθ)*(1-cosθ)*(1-cosθ)*(1-cosθ)&#xD;&#xA;            u = rand()&#xD;&#xA;            if u &lt; Rθ&#xD;&#xA;                R = ray.d - 2*dot(ray.d, n)*n&#xD;&#xA;                In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;                return In&#xD;&#xA;            else&#xD;&#xA;                R = ref*ray.d + (ref*cosθ - sqrt(disc))*n&#xD;&#xA;                In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;                return In&#xD;&#xA;            end&#xD;&#xA;        end&#xD;&#xA;    end      &#xD;&#xA;    BRDF = ρ/Π&#xD;&#xA;    R = hemiRand(n)&#xD;&#xA;    In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;    return Π*BRDF*In&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;And I think the fresenl effect of the area light on the sphere looks strange and wrong! Am I correct? " ContentLicense="CC BY-SA 4.0" />
  <row Id="25288" PostHistoryTypeId="5" PostId="9248" RevisionGUID="518c4869-d7eb-4a5b-bdb1-14448857344d" CreationDate="2019-10-14T16:58:38.517" UserId="11316" Comment="added 100 characters in body" Text="I am trying to render a dielectric sphere inside the Cornell Box. Some circles are generated on the sphere. Here is the photo generated by path tracer:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kEAYT.png&#xD;&#xA;&#xD;&#xA;And below is my main function:&#xD;&#xA;&#xD;&#xA;    function trace(surfaces::Array{Surfaces, 1}, ray::Ray, depth::Int64, maxDepth::Int64)&#xD;&#xA;    if depth &gt;= maxDepth&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    t, material = nearest(surfaces, ray, Inf)&#xD;&#xA;    if typeof(material) == Empty&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;    end&#xD;&#xA;    if material.isLight == true&#xD;&#xA;        return material.emittance&#xD;&#xA;    end&#xD;&#xA;    ρ = material.reflectance&#xD;&#xA;    n = material.normal&#xD;&#xA;    if material.isDielectric == true&#xD;&#xA;        cosθ = -dot(n, ray.d)&#xD;&#xA;        ref = material.ni/material.nt&#xD;&#xA;        if cosθ &lt; 0&#xD;&#xA;            cosθ = -cosθ&#xD;&#xA;            n = -1.0*n&#xD;&#xA;            ref = 1/ref&#xD;&#xA;        end&#xD;&#xA;        disc = 1 - ref*ref*(1-cosθ*cosθ)&#xD;&#xA;        if disc &lt; 0&#xD;&#xA;            R = ray.d - 2*dot(ray.d, n)*n&#xD;&#xA;            In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;            return In&#xD;&#xA;        elseif disc &gt; 0&#xD;&#xA;            R0 = (ref-1)/(ref+1)&#xD;&#xA;            R0 = R0*R0&#xD;&#xA;            Rθ = R0 + (1-R0)*(1-cosθ)*(1-cosθ)*(1-cosθ)*(1-cosθ)*(1-cosθ)&#xD;&#xA;            u = rand()&#xD;&#xA;            if u &lt; Rθ&#xD;&#xA;                R = ray.d - 2*dot(ray.d, n)*n&#xD;&#xA;                In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;                return In&#xD;&#xA;            else&#xD;&#xA;                R = ref*ray.d + (ref*cosθ - sqrt(disc))*n&#xD;&#xA;                In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;                return In&#xD;&#xA;            end&#xD;&#xA;        end&#xD;&#xA;    end      &#xD;&#xA;    BRDF = ρ/Π&#xD;&#xA;    R = hemiRand(n)&#xD;&#xA;    In = trace(surfaces, Ray(ray.s + t*ray.d, R), depth+1, maxDepth)&#xD;&#xA;    return Π*BRDF*In&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;And I think the fresenl effect of the area light on the sphere looks strange and wrong! Am I correct? &#xD;&#xA;&#xD;&#xA;EDIT: I searched a bit and I guess it's the moire effect. But I don't know how to get rid of it." ContentLicense="CC BY-SA 4.0" />
  <row Id="25289" PostHistoryTypeId="2" PostId="9249" RevisionGUID="d217c2cb-1d0c-440a-a8c2-9861bac86aa0" CreationDate="2019-10-14T18:17:07.760" UserId="3332" Text="We have a projector type display used in an automotive application, where a projector displays an application on the windshield.  Because the projector would normally warp a flat image, we have to counter this warping. The way we do this is:&#xD;&#xA;&#xD;&#xA; 1. Render our content to a framebuffer&#xD;&#xA; 2. Apply that frame buffer as a texture on a special mesh that counteracts the warping from the projector.&#xD;&#xA;&#xD;&#xA;As we've found, the final stages of the rendering pipeline (rendering pixels to a framebuffer / and or screen) are often the biggest bottlenecks on embedded hardware.  &#xD;&#xA;&#xD;&#xA;Is there any potential method we could use to reduce steps 1 and 2 to a single pass?  Essentially going through multiple projections, but without using intermediate frame buffers?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25290" PostHistoryTypeId="1" PostId="9249" RevisionGUID="d217c2cb-1d0c-440a-a8c2-9861bac86aa0" CreationDate="2019-10-14T18:17:07.760" UserId="3332" Text="How combine multiple projections into a single pass?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25291" PostHistoryTypeId="3" PostId="9249" RevisionGUID="d217c2cb-1d0c-440a-a8c2-9861bac86aa0" CreationDate="2019-10-14T18:17:07.760" UserId="3332" Text="|opengl|projections|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25292" PostHistoryTypeId="2" PostId="9250" RevisionGUID="3beddcc4-3801-411c-bfe0-1630a374a7ed" CreationDate="2019-10-14T18:30:55.167" UserId="3003" Text="The `R` part generates a cone where the point is at (0, 0, 1) and it spreads out below that. It meets the x-y plane at the unit circle:&#xD;&#xA;&#xD;&#xA;[![A cone with the point at (0, 0, 1) and spreading out downward][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The `cos` component defines an extruded cosine wave along the X-axis:&#xD;&#xA;&#xD;&#xA;[![The graph of cos(2*π*x)][2]][2]&#xD;&#xA;&#xD;&#xA;So the final equation takes the cosine wave and multiplies its amplitude by the cone. It will have full amplitude at the origin, and decrease to 0 at the unit circle on the x-y plane. Past that it becomes negative:&#xD;&#xA;&#xD;&#xA;[![Multiplying the second equation by the first][3]][3]&#xD;&#xA;&#xD;&#xA;The `phi` component shifts the sine wave forward or backward along the x axis.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jtZdE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dsszO.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/EviPs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25294" PostHistoryTypeId="2" PostId="9251" RevisionGUID="f6672c37-4a28-4ba9-9c6a-90dc3cf1df34" CreationDate="2019-10-15T01:46:04.590" UserId="11312" Text="per this [post][1], this formula&#xD;&#xA;&#xD;&#xA;$Z = 1 - \sqrt{X^{2} + Y^{2}}$&#xD;&#xA;&#xD;&#xA;generates a cone where the point is at (0, 0, 1) and it spreads out below that. It meets the x-y plane at the unit circle&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am trying to reproduce with Python&#xD;&#xA;&#xD;&#xA;    ax = plt.figure().gca(projection='3d')&#xD;&#xA;    xx, yy = np.meshgrid(np.arange(-1,1.1,.1), np.arange(-1,1.1,.1))&#xD;&#xA;    zz = 1 - np.sqrt(xx**2, yy**2)&#xD;&#xA;    ax.plot_surface(xx, yy, zz, alpha=.5)&#xD;&#xA;&#xD;&#xA;and get this &quot;roof&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;what am I missing?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/9250/11312&#xD;&#xA;  [2]: https://i.stack.imgur.com/jtZdE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8n6z6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25295" PostHistoryTypeId="1" PostId="9251" RevisionGUID="f6672c37-4a28-4ba9-9c6a-90dc3cf1df34" CreationDate="2019-10-15T01:46:04.590" UserId="11312" Text="Why does my code to plot a cone actually generate a roof?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25296" PostHistoryTypeId="3" PostId="9251" RevisionGUID="f6672c37-4a28-4ba9-9c6a-90dc3cf1df34" CreationDate="2019-10-15T01:46:04.590" UserId="11312" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25297" PostHistoryTypeId="5" PostId="9251" RevisionGUID="b202d9ba-ebba-4efa-8fc9-1f13182a72e3" CreationDate="2019-10-15T02:12:56.527" UserId="11312" Comment="added 97 characters in body" Text="per this [post][1], this formula&#xD;&#xA;&#xD;&#xA;$Z = 1 - \sqrt{X^{2} + Y^{2}}$&#xD;&#xA;&#xD;&#xA;generates a cone where the point is at (0, 0, 1) and it spreads out below that. It meets the x-y plane at the unit circle&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am trying to reproduce with Python&#xD;&#xA;&#xD;&#xA;    ax = plt.figure().gca(projection='3d')&#xD;&#xA;    xx, yy = np.meshgrid(np.arange(-1,1.1,.1), np.arange(-1,1.1,.1))&#xD;&#xA;    zz = 1 - np.sqrt(xx**2, yy**2)&#xD;&#xA;    ax.plot_surface(xx, yy, zz, alpha=.5)&#xD;&#xA;&#xD;&#xA;and get this &quot;roof&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;each of xx, yy, zz is a 21 by 21 matrix, even if I increase them to 210 by 210, nothing changes, what am I missing?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/9250/11312&#xD;&#xA;  [2]: https://i.stack.imgur.com/jtZdE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8n6z6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25298" PostHistoryTypeId="2" PostId="9252" RevisionGUID="432017d3-fbe1-4fb9-85f6-dd74d6205811" CreationDate="2019-10-15T02:31:20.297" UserId="3003" Text="You need to change the call to `sqrt` from:&#xD;&#xA;&#xD;&#xA;    np.sqrt(xx**2, yy**2)&#xD;&#xA;&#xD;&#xA;to:&#xD;&#xA;&#xD;&#xA;    np.sqrt(xx**2 + yy**2)&#xD;&#xA;&#xD;&#xA;Otherwise you're passing an array of values to the function and will be returned an array of values for the answer.&#xD;&#xA;&#xD;&#xA;[See here](https://numpy.org/devdocs/reference/generated/numpy.sqrt.html?highlight=sqrt#numpy.sqrt) for details:&#xD;&#xA;&#xD;&#xA;&gt; `&gt;&gt;&gt; np.sqrt([1,4,9])`&#xD;&#xA;&gt;&#xD;&#xA;array([ 1.,  2.,  3.])&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25299" PostHistoryTypeId="2" PostId="9253" RevisionGUID="6ca2c951-2af4-4dac-b2ad-5db464aede83" CreationDate="2019-10-15T03:48:47.487" UserId="11312" Text="this [figure](https://math.stackexchange.com/q/3391749/673047) (fig_1) is an univariate normal distribution in 3D, the corresponding equation is in the top left hand corner&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;it seems that x varies from -5 to 5; sigma varies from 0 to 4.&#xD;&#xA;&#xD;&#xA;This Python code is trying to reproduce this figure&#xD;&#xA;&#xD;&#xA;    ax = plt.figure().gca(projection='3d')&#xD;&#xA;    xx, yy = np.meshgrid(np.arange(-5,5,.1), np.arange(0.1,4,.1))&#xD;&#xA;    zz = norm.pdf(xx,0,yy)&#xD;&#xA;    ax.plot_surface(xx, yy, zz, alpha=.5)&#xD;&#xA;&#xD;&#xA;and I got this figure&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;and this guy&#xD;&#xA;&#xD;&#xA;    zz = norm.pdf(xx,0,np.sqrt(yy))&#xD;&#xA;&#xD;&#xA;gives this figure&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;which is better although the kurtosis looks a little higher than fig_1.&#xD;&#xA;&#xD;&#xA;any clue&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/11wRJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/uIylt.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rXfBq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25300" PostHistoryTypeId="1" PostId="9253" RevisionGUID="6ca2c951-2af4-4dac-b2ad-5db464aede83" CreationDate="2019-10-15T03:48:47.487" UserId="11312" Text="Why does my code generate a figure whose kurtosis looks a little higher than the one I am trying to reproduce?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25301" PostHistoryTypeId="3" PostId="9253" RevisionGUID="6ca2c951-2af4-4dac-b2ad-5db464aede83" CreationDate="2019-10-15T03:48:47.487" UserId="11312" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25302" PostHistoryTypeId="2" PostId="9254" RevisionGUID="f4fcaa73-2047-4ba1-b663-8744b3f44772" CreationDate="2019-10-15T12:39:39.810" UserId="7724" Text="You could try the [FiberMesh][1] technique. Fibermesh takes 3D input curves and interprets them as the contours of the surface. It then creates a smooth surface by using an optimization technique. [Here][2] you can see a video, which demonstrates the technique. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.semanticscholar.org/paper/FiberMesh%3A-designing-freeform-surfaces-with-3D-Nealen-Igarashi/25b7f1b06e60a39113ebc25049e13b58f84fec1b&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=OsOauFjnYSo" ContentLicense="CC BY-SA 4.0" />
  <row Id="25306" PostHistoryTypeId="2" PostId="9256" RevisionGUID="e5690ef1-353f-48d5-ad74-bc3c2170cf2c" CreationDate="2019-10-15T17:53:48.767" UserId="11316" Text="I solved my problem by adding a small value to t value when the ray is getting refracted.&#xD;&#xA;But I still doubt the result is true. Below is the new generated photo:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jziQ0.png&#xD;&#xA;&#xD;&#xA;Why is the area light reflected twice on top of the sphere? Is there still a bug in my path tracer? The glass sphere is closer to the camera than the area light." ContentLicense="CC BY-SA 4.0" />
  <row Id="25307" PostHistoryTypeId="2" PostId="9257" RevisionGUID="67471dbd-0863-4dc3-aba6-22e455e1c8ad" CreationDate="2019-10-15T21:01:23.373" UserId="48" Text="The value 's' in the original graph is the variance, which is the square of the Gaussian sigma (i.e. the scale parameter of the normal distribution). So `norm.pdf(xx,0,np.sqrt(yy))` should be correct.&#xD;&#xA;&#xD;&#xA;Note that the shape of the peak you see is very much dependent on the y value where the graph starts. Your starting point of 0.1 may be a little smaller than in the original graph, which looks like it starts at about 1/6 ~= 0.167, so you may see a narrower and taller peak for that reason. Also, the original graph doesn't quite have enough horizontal resolution to resolve the shape of the peak entirely, as you can see from how far apart the grid lines are spaced vertically on the sides of the peak." ContentLicense="CC BY-SA 4.0" />
  <row Id="25308" PostHistoryTypeId="2" PostId="9258" RevisionGUID="e48686bc-948c-4f7b-a123-645f0614f55a" CreationDate="2019-10-16T08:01:50.303" UserId="6346" Text="Question from the graphics newbie:&lt;br&gt;&#xD;&#xA;What I know by now is that &quot;usually&quot; double buffering is used: &lt;br&gt;You calculate the content of frame x+1 while frame x is shown on the screen, if you want to achieve the maximum update rate, calculation must not take longer than one frame time, otherwise the &quot;drawing process&quot; is visible.&lt;br&gt;&#xD;&#xA;So, having two framebuffers absolutely makes sense, and I guess that's why we have that &quot;glfwSwapBuffers&quot; call in some OpenGL tutorials.&lt;br&gt;&#xD;&#xA;&#xD;&#xA;But what if I program my things in a way that every primitive leads to fragments that are horizontal lines, and let the GPU process it from top to bottom line &quot;on the fly&quot;?&lt;br&gt;&#xD;&#xA;In this case I would need only one framebuffer that could be filled with a static background, and I would only have to store the other objects in some much smaller memory.&lt;br&gt;&#xD;&#xA;Is this possible at all?&lt;br&gt;&#xD;&#xA;Is there even any GPU implementation that does it that way to save memory?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25309" PostHistoryTypeId="1" PostId="9258" RevisionGUID="e48686bc-948c-4f7b-a123-645f0614f55a" CreationDate="2019-10-16T08:01:50.303" UserId="6346" Text="Double buffering always necessary?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25310" PostHistoryTypeId="3" PostId="9258" RevisionGUID="e48686bc-948c-4f7b-a123-645f0614f55a" CreationDate="2019-10-16T08:01:50.303" UserId="6346" Text="|opengl|gpu|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25311" PostHistoryTypeId="2" PostId="9259" RevisionGUID="e42247fe-c1b7-4e3f-b380-7690beaf1a22" CreationDate="2019-10-16T09:12:42.743" UserId="209" Text="Indeed there are/were 'just in time' renderers. &#xD;&#xA;&#xD;&#xA;For example, Dreamcast (PowerVR CLX2) had a mode where the 'frame buffer' only had to be a few rows of tiles in size. The system would be rendering into one row while the display was reading out of some subset of the others. It would then cycle through the buffers. &#xD;&#xA;&#xD;&#xA;In order to do this, however, you *do* need a display-list rendering system. A standard 'immediate mode' renderer is not appropriate.&#xD;&#xA;&#xD;&#xA;Of course, scene complexity needs to be considered carefully for this sort of scheme to work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, the PowerVR PCX1/PXC2 versions of Tomb Raider had an optional single buffered rendering mode (This was primarily because one of the guys doing the port (cough, me, cough) only had a 2MB 2D graphics card and thus could only allocate a single 1024x768 framebuffer). Again, since the system was tile-based, it didn't suffer from the artefacts you'd get with a traditional Z-buffer system." ContentLicense="CC BY-SA 4.0" />
  <row Id="25312" PostHistoryTypeId="5" PostId="9259" RevisionGUID="b08c1610-3066-4922-a242-9258b360387f" CreationDate="2019-10-16T09:26:28.810" UserId="209" Comment="added 207 characters in body" Text="Indeed there are/were 'just in time' renderers. &#xD;&#xA;&#xD;&#xA;For example, Dreamcast (PowerVR CLX2) had a mode where the 'frame buffer' only had to be a few rows of tiles in size. The system would be rendering into one row while the display was reading out of some subset of the others. It would then cycle through the buffers. &#xD;&#xA;&#xD;&#xA;In order to do this, however, you *do* need a display-list rendering system. A standard 'immediate mode' renderer is not appropriate.&#xD;&#xA;&#xD;&#xA;Of course, scene complexity needs to be considered carefully for this sort of scheme to work.&#xD;&#xA;&#xD;&#xA;I also have a feeling/seem to recall some old (e.g 60s/70s?) flight simulators might have rendered 'on the fly' because memory (for a frame buffer) was once fiendishly expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, the PowerVR PCX1/PXC2 ports of Tomb Raider had an optional single buffered rendering mode. (This was primarily because one of the guys doing the port (cough, me, cough) only had a 2MB 2D graphics card which could only allocate a single 1024x768 framebuffer).  Again, since the system was tile-based, it didn't suffer from the nasty artefacts you'd get with single buffering on a traditional Z-buffer system." ContentLicense="CC BY-SA 4.0" />
  <row Id="25313" PostHistoryTypeId="2" PostId="9260" RevisionGUID="15e1188c-b628-4e4b-a043-f1b2229de1c3" CreationDate="2019-10-16T13:06:17.903" UserId="11315" Text="By googling, I have found some definition of *squared magnitude* [about mathematical plane applied in the gaming field][1], but I am dubting this is what we would mean in the noise generation's field. &#xD;&#xA; &#xD;&#xA;thanks for any hint&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=nl24ps-IZIU" ContentLicense="CC BY-SA 4.0" />
  <row Id="25314" PostHistoryTypeId="1" PostId="9260" RevisionGUID="15e1188c-b628-4e4b-a043-f1b2229de1c3" CreationDate="2019-10-16T13:06:17.903" UserId="11315" Text="Concerning the Procedural noise's function, how would you define a squared magnitude in plain word?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25315" PostHistoryTypeId="3" PostId="9260" RevisionGUID="15e1188c-b628-4e4b-a043-f1b2229de1c3" CreationDate="2019-10-16T13:06:17.903" UserId="11315" Text="|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25316" PostHistoryTypeId="2" PostId="9261" RevisionGUID="5b99e881-a3c2-4f98-b07b-447b90d92f25" CreationDate="2019-10-16T14:59:23.677" UserId="11322" Text="I have a sampler variable in a shader:&#xD;&#xA;&#xD;&#xA;     uniform sampler2DArray tiles;&#xD;&#xA;   &#xD;&#xA;Which I am trying to bind to a texture unit in GL:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;        int tilesUniformIndex = glGetUniformLocation(shaderProgramId,&quot;tiles&quot;);&#xD;&#xA;        System.out.println(&quot;tiles: &quot;+tilesUniformIndex);&#xD;&#xA;        glUseProgram(shaderProgramId);&#xD;&#xA;        glok();  // &lt;- This calls glGetError() and throws exception if not-ok&#xD;&#xA;        glUniform1i(tilesUniformIndex, GL_TEXTURE0 + TILE_TEXTURE_UNIT_INDEX);&#xD;&#xA;        glok();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;`TILE_TEXTURE_UNIT_INDEX` is a constant defined to be zero.&#xD;&#xA;&#xD;&#xA;The location is being correctly introspected, output is:&#xD;&#xA;&#xD;&#xA;     tiles: 7&#xD;&#xA;&#xD;&#xA;which is the correct binding location I expect in context of the shader source.&#xD;&#xA;&#xD;&#xA;The /second/ glok() is throwing an exception, with 0x501 GL_INVALID_VALUE.&#xD;&#xA;&#xD;&#xA;According to [the documentation][1], this can only happen if the `count` parameter is less than zero.  But `glUniform1i` /doesn't have a count parameter/!&#xD;&#xA;&#xD;&#xA;I've tried:&#xD;&#xA;&#xD;&#xA;    glUniform1iv(tilesUniformIndex, 1, new int[]{GL31.GL_TEXTURE0 + TILE_TEXTURE_UNIT_INDEX});&#xD;&#xA;&#xD;&#xA;as well, and the implementation of that does what it looks like (passes a memory pointer to the array data as output `value`).&#xD;&#xA;&#xD;&#xA;So, what gives?   Anyone know how this function can possibly behave like this?   This is a simple, correct use case, right?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="25317" PostHistoryTypeId="1" PostId="9261" RevisionGUID="5b99e881-a3c2-4f98-b07b-447b90d92f25" CreationDate="2019-10-16T14:59:23.677" UserId="11322" Text="Why is glUniform1i() returning GL_INVALID_VALUE?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25318" PostHistoryTypeId="3" PostId="9261" RevisionGUID="5b99e881-a3c2-4f98-b07b-447b90d92f25" CreationDate="2019-10-16T14:59:23.677" UserId="11322" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25319" PostHistoryTypeId="5" PostId="9261" RevisionGUID="04a6c41a-2f4b-4db5-9891-7bd5a4e80829" CreationDate="2019-10-16T15:09:41.047" UserId="11322" Comment="deleted 5 characters in body" Text="I have a sampler variable in a shader:&#xD;&#xA;&#xD;&#xA;     uniform sampler2DArray tiles;&#xD;&#xA;   &#xD;&#xA;Which I am trying to bind to a texture unit in GL:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;        int tilesUniformIndex = glGetUniformLocation(shaderProgramId,&quot;tiles&quot;);&#xD;&#xA;        System.out.println(&quot;tiles: &quot;+tilesUniformIndex);&#xD;&#xA;        glUseProgram(shaderProgramId);&#xD;&#xA;        glok();  // &lt;- This calls glGetError() and throws exception if not-ok&#xD;&#xA;        glUniform1i(tilesUniformIndex, GL_TEXTURE0 + TILE_TEXTURE_UNIT_INDEX);&#xD;&#xA;        glok();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;`TILE_TEXTURE_UNIT_INDEX` is a constant defined to be zero.&#xD;&#xA;&#xD;&#xA;The location is being correctly introspected, output is:&#xD;&#xA;&#xD;&#xA;     tiles: 7&#xD;&#xA;&#xD;&#xA;which is the correct binding location I expect in context of the shader source.&#xD;&#xA;&#xD;&#xA;The /second/ glok() is throwing an exception, with 0x501 GL_INVALID_VALUE.&#xD;&#xA;&#xD;&#xA;According to [the documentation][1], this can only happen if the `count` parameter is less than zero.  But `glUniform1i` /doesn't have a count parameter/!&#xD;&#xA;&#xD;&#xA;I've tried:&#xD;&#xA;&#xD;&#xA;    glUniform1iv(tilesUniformIndex, 1, new int[]{GL_TEXTURE0 + TILE_TEXTURE_UNIT_INDEX});&#xD;&#xA;&#xD;&#xA;as well, and the implementation of that does what it looks like (passes a memory pointer to the array data as output `value`).&#xD;&#xA;&#xD;&#xA;So, what gives?   Anyone know how this function can possibly behave like this?   This is a simple, correct use case, right?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="25320" PostHistoryTypeId="52" PostId="9258" RevisionGUID="93c5ec0e-90b1-493f-a2fb-61bc177325e8" CreationDate="2019-10-16T16:12:45.010" />
  <row Id="25322" PostHistoryTypeId="2" PostId="9262" RevisionGUID="691cfa6b-03df-47e2-8315-8887d256650b" CreationDate="2019-10-17T17:10:28.830" UserId="6987" Text="In the context of render targets or textures, what does &quot;resolve&quot; mean?&#xD;&#xA;For example: To resolve a color texture.&#xD;&#xA;&#xD;&#xA;From my understanding, it seems to mean, &quot;copy but process/convert at the same time&quot;, but I can't seem to find a good definition for it anywhere." ContentLicense="CC BY-SA 4.0" />
  <row Id="25323" PostHistoryTypeId="1" PostId="9262" RevisionGUID="691cfa6b-03df-47e2-8315-8887d256650b" CreationDate="2019-10-17T17:10:28.830" UserId="6987" Text="What does resolve mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25324" PostHistoryTypeId="3" PostId="9262" RevisionGUID="691cfa6b-03df-47e2-8315-8887d256650b" CreationDate="2019-10-17T17:10:28.830" UserId="6987" Text="|texture|image-processing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25326" PostHistoryTypeId="2" PostId="9264" RevisionGUID="1529833b-bb28-4e02-961b-f49870f1adba" CreationDate="2019-10-18T05:41:30.960" UserId="113" Text="The Kinect SDK has a skeletal tracking demo in the c++ api (BodyBasics). The skeleton you get is the same &quot;topology&quot; unless it fails to acquire the skeleton. So you can easily compare the left shoulder of two captures as you always know which point it is.&#xD;&#xA;&#xD;&#xA;You'll have to experience with metrics. A simple point to point metric would probably be sufficient though. Maybe with some weights on different body parts though." ContentLicense="CC BY-SA 4.0" />
  <row Id="25327" PostHistoryTypeId="5" PostId="9259" RevisionGUID="f9035a3d-bbc8-4555-a4b6-787dd3888cc9" CreationDate="2019-10-18T09:18:54.560" UserId="209" Comment="Added note on using more buffer space" Text="Indeed there are/were 'just in time' renderers. &#xD;&#xA;&#xD;&#xA;For example, Dreamcast (PowerVR CLX2) had a mode where the 'frame buffer' only had to be a few rows of tiles in size. The system would be rendering into one row while the display was reading out of some subset of the others. It would then cycle through the buffers. &#xD;&#xA;&#xD;&#xA;In order to do this, however, you *do* need a display-list rendering system. A standard 'immediate mode' renderer is not appropriate.&#xD;&#xA;&#xD;&#xA;Of course, scene complexity needs to be considered carefully for this sort of scheme to work. In particular, if one tiny section of the screen contains particularly complex geometry, the renderer might not finish it in time before the display needs to read it. Allocating more memory for the partial screen buffer allows for more variability in scene complexity.&#xD;&#xA;&#xD;&#xA;I also have a feeling/seem to recall some old (e.g 60s/70s?) flight simulators might have rendered 'on the fly' because memory (for a frame buffer) was once fiendishly expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, the PowerVR PCX1/PXC2 ports of Tomb Raider had an optional single buffered rendering mode. (This was primarily because one of the guys doing the port (cough, me, cough) only had a 2MB 2D graphics card which could only allocate a single 1024x768 framebuffer).  Again, since the system was tile-based, it didn't suffer from the nasty artefacts you'd get with single buffering on a traditional Z-buffer system." ContentLicense="CC BY-SA 4.0" />
  <row Id="25328" PostHistoryTypeId="2" PostId="9265" RevisionGUID="b812581c-28cc-470a-b2dd-fa6a13c26ce5" CreationDate="2019-10-18T17:02:57.463" UserId="11316" Text="I am trying to implement next event estimation to reduce the noise of path tracer and I need a pesudocode. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25329" PostHistoryTypeId="1" PostId="9265" RevisionGUID="b812581c-28cc-470a-b2dd-fa6a13c26ce5" CreationDate="2019-10-18T17:02:57.463" UserId="11316" Text="How can I implement next event estimation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25330" PostHistoryTypeId="3" PostId="9265" RevisionGUID="b812581c-28cc-470a-b2dd-fa6a13c26ce5" CreationDate="2019-10-18T17:02:57.463" UserId="11316" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25331" PostHistoryTypeId="5" PostId="9265" RevisionGUID="b9f892e9-3e07-4bf5-8c03-ef8b3b5c0496" CreationDate="2019-10-18T19:25:20.697" UserId="11316" Comment="added 194 characters in body" Text="I am trying to implement next event estimation to reduce the noise of path tracer and I need a pseudocode. &#xD;&#xA;&#xD;&#xA;Edit: I know how to sample direct illumination but the visibility function is the real problem I face. How to code the visibility function without iterating over the objects in the scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25332" PostHistoryTypeId="2" PostId="9266" RevisionGUID="763e0753-2790-447e-874d-9f93c7d4f8b5" CreationDate="2019-10-18T20:36:19.130" UserId="10096" Text="You can provide an `intersect_any(ray, scene, min_t, max_t)` function, that returns true at the first intersection. So it has the option to exit early compared to the usual `intersect` function. Additionally you do not care about normals, texture coordinates, positions, so you can avoid computing those in many cases. You need `max_t` though to limit the ray to the segment between the two points you are testing.&#xD;&#xA;&#xD;&#xA;In the worst case scenario (there is nothing between the two points) you will still need to iterate over all objects unless you are using acceleration structures." ContentLicense="CC BY-SA 4.0" />
  <row Id="25333" PostHistoryTypeId="2" PostId="9267" RevisionGUID="7816ffbe-5dd8-408c-800b-37319b0b658f" CreationDate="2019-10-18T21:01:55.893" UserId="11312" Text="In 2d, matplotlib plots all 4 edges(spines) of a figure.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In 3d, matplotlib plots 9 out of 12 edges of a cube.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is it possible to set visible and color for all 12 edges(spines) of a cube in 3d?&#xD;&#xA;&#xD;&#xA;I tried `ax.xaxis._axinfo['juggled'] = (2,0,1)` and found that is something live move instead of setting visible or color. &#xD;&#xA;&#xD;&#xA;I also tried `ax.collections`, didn't work either.&#xD;&#xA;&#xD;&#xA;Any clue?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xqSsr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/IbLwG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25334" PostHistoryTypeId="1" PostId="9267" RevisionGUID="7816ffbe-5dd8-408c-800b-37319b0b658f" CreationDate="2019-10-18T21:01:55.893" UserId="11312" Text="Is it possible to set visible and color for all 12 edges(spines) of the figure (cube) in matplotlib?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25335" PostHistoryTypeId="3" PostId="9267" RevisionGUID="7816ffbe-5dd8-408c-800b-37319b0b658f" CreationDate="2019-10-18T21:01:55.893" UserId="11312" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25336" PostHistoryTypeId="50" PostId="9168" RevisionGUID="4a49aeac-0dad-40ae-87bc-a0fe6aa2a2f5" CreationDate="2019-10-19T02:01:45.220" UserId="-1" />
  <row Id="25337" PostHistoryTypeId="2" PostId="9268" RevisionGUID="432c9d3c-e4a2-410a-a708-ea8c6238ee9d" CreationDate="2019-10-19T03:59:33.723" UserId="11322" Text="Quoting the Khronos OpenGL [documentation pages][1] for the `glGetProgramResourceiv()` function:&#xD;&#xA;&#xD;&#xA;&gt; For the property GL_TYPE, a single integer identifying the type of an&#xD;&#xA;&gt; active variable is written to params. The integer returned is one of&#xD;&#xA;&gt; the values found in table 2.16.&#xD;&#xA;&#xD;&#xA;But, there is no &quot;table 2.16&quot; in that page, there is no &quot;table 2.16&quot; in the specification document (where the language also appears), and several search engines failed to return any other references to such a table.&#xD;&#xA;&#xD;&#xA;So, where is it?   What are the full list of type codes that can be returned by this introspection function (which can presumably represent all GLSL types)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;(I'm using GL core 4.3)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramResource.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="25338" PostHistoryTypeId="1" PostId="9268" RevisionGUID="432c9d3c-e4a2-410a-a708-ea8c6238ee9d" CreationDate="2019-10-19T03:59:33.723" UserId="11322" Text="What are the type constants that the documentation for glGetProgramResourceiv() refers to?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25339" PostHistoryTypeId="3" PostId="9268" RevisionGUID="432c9d3c-e4a2-410a-a708-ea8c6238ee9d" CreationDate="2019-10-19T03:59:33.723" UserId="11322" Text="|opengl|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25340" PostHistoryTypeId="2" PostId="9269" RevisionGUID="98002add-6f31-4b57-b778-f2302298fe61" CreationDate="2019-10-19T05:02:39.043" UserId="2654" Text="For whatever reason, the text for that function documentation was copied from the GL_ARB_program_interface_query extension. Extensions in OpenGL are always defined relative to a specific version of the OpenGL specification. So if an extension references something in a specification, it's talking about that version of the spec.&#xD;&#xA;&#xD;&#xA;However, the OpenGL specification was *massively* restructured between 4.2 and 4.3, with whole chapters moved around. This means that table references in 4.2 become completely wrong relative to 4.3 and above.&#xD;&#xA;&#xD;&#xA;Program interface query was written against the 4.2 specification, where you will indeed find a table 2.16. That table moved to a whole different chapter in 4.3+ versions. It's been renumbered and moved since then, so you'll have to look at a particular specification's definition of `glGetProgramResourceiv` to find it.&#xD;&#xA;&#xD;&#xA;In general, if you find something incongruous in the documentation pages, you should look at the [actual OpenGL specification][1] to see what it says about the function's behavior. In this particular case, the [docs in the OpenGL wiki][2] for this function actually includes the table.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/index_gl.php&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/GLAPI/glGetProgramResource" ContentLicense="CC BY-SA 4.0" />
  <row Id="25344" PostHistoryTypeId="36" PostId="9271" RevisionGUID="9262c9a7-af8a-4b90-908b-df9cf07aaa3c" CreationDate="2019-10-20T08:31:21.060" UserId="-1" Comment="from https://academia.stackexchange.com/questions/138788/issue-with-perspective-projection" />
  <row Id="25345" PostHistoryTypeId="2" PostId="9271" RevisionGUID="bfac36e3-0256-4067-acdd-607a6910d38b" CreationDate="2019-10-20T07:35:18.097" UserDisplayName="fatestayn" Text="I have the following problem. [Perspective projection][1] is often referred to when talking about camera models. I don’t think I understand it very well though this concept is taught when I was at junior high or even primary school. I think programmers with a computer vision background may be familiar with it.&#xD;&#xA;&#xD;&#xA;I read quite some “tutorials” on perspective projection, also computer vision textbooks like “Computer Vision: Algorithms and Applications”, “Multiple View Geometry in Computer Vision:Second Edition”. But the representation conventions seems to be quite a lot. It’s a little bit unfriendly to beginners. Just to get a feeling, here’s one of them:&#xD;&#xA;[example formula][2]&#xD;&#xA;&#xD;&#xA;May I ask if there’s some good, easy-to-read and self-contained articles that can help beginners like me understand perspective projection? It may explains quite clearly the physical meaning of the parameters of it, especially the “scale factor”.&#xD;&#xA;&#xD;&#xA;Any ideas? Thanx in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/3D_projection#Perspective_projection&#xD;&#xA;  [2]: https://i.stack.imgur.com/xmQtT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25346" PostHistoryTypeId="1" PostId="9271" RevisionGUID="bfac36e3-0256-4067-acdd-607a6910d38b" CreationDate="2019-10-20T07:35:18.097" UserDisplayName="fatestayn" Text="Issue with perspective projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="25347" PostHistoryTypeId="3" PostId="9271" RevisionGUID="bfac36e3-0256-4067-acdd-607a6910d38b" CreationDate="2019-10-20T07:35:18.097" UserDisplayName="fatestayn" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25348" PostHistoryTypeId="2" PostId="9272" RevisionGUID="e3ba45f0-3062-47bc-985a-169553ec9071" CreationDate="2019-10-20T11:06:41.020" UserId="11316" Text="Is my understanding of MIS algorithm true?&#xD;&#xA;&#xD;&#xA;I first generate a random number $x\in U(0,1)$ and $w_1=\frac{p_1(direct)}{p_1(direct)+p_2(hemisphere)}$, and then if $x &lt; w_1$ generate the sample directly from the light source, otherwise generate the sample randomly on the unit hemisphere around the hit point.&#xD;&#xA;&#xD;&#xA;And why should I do if the randomly generated samples on the hemisphere hit the light source? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25349" PostHistoryTypeId="1" PostId="9272" RevisionGUID="e3ba45f0-3062-47bc-985a-169553ec9071" CreationDate="2019-10-20T11:06:41.020" UserId="11316" Text="How does multiple importance sampling work and how should I generate the samples?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25350" PostHistoryTypeId="3" PostId="9272" RevisionGUID="e3ba45f0-3062-47bc-985a-169553ec9071" CreationDate="2019-10-20T11:06:41.020" UserId="11316" Text="|raytracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25351" PostHistoryTypeId="5" PostId="9272" RevisionGUID="65eba198-1a5b-4707-b6e4-6a225493b76e" CreationDate="2019-10-20T11:20:08.323" UserId="11316" Comment="added 1 character in body" Text="Is my understanding of MIS algorithm true?&#xD;&#xA;&#xD;&#xA;I first generate a random number $x\in U(0,1)$ and $w_1=\frac{p_1(direct)}{p_1(direct)+p_2(hemisphere)}$, and then if $x &lt; w_1$ generate the sample directly from the light source, otherwise generate the sample randomly on the unit hemisphere around the hit point.&#xD;&#xA;&#xD;&#xA;And what should I do if the randomly generated samples on the hemisphere hit the light source? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25352" PostHistoryTypeId="2" PostId="9273" RevisionGUID="9464c550-3556-4002-ae39-64518e881e7d" CreationDate="2019-10-20T11:42:49.337" UserId="11335" Text="I'm trying to force perspective into the horizon of a Shadertoy scene by drawing horizontal lines at decreasing distances as y grows to create an outrun-esque scene, but can't figure out which functions to use. I know the spaces need to be asymptotic up to uv.y/2, and thought I could use a combination of smoothstep and modulo like:&#xD;&#xA;&#xD;&#xA;    if (mod(smoothstep(-0.07, 2.0, uv.y/1.5), 0.03) &lt; 0.001) {&#xD;&#xA;    	fragColor = vec4(1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This does work, but the lines start wide and quickly become constant width rather than getting smaller. I'd like to offset these lines with iTime so will need to modulo that as well (eg below), but in other tests I get an effect which is nearly correct but the lines bug and either don't draw sometimes, or draw too thick. &#xD;&#xA;&#xD;&#xA;    if (mod(round(fragCoord.y+mod(iTime*150.0, 500.0)), iResolution.y/2.0-fragCoord.y) &lt; 10.0) {&#xD;&#xA;            fragColor = 1.0;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Am I on the right lines?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25353" PostHistoryTypeId="1" PostId="9273" RevisionGUID="9464c550-3556-4002-ae39-64518e881e7d" CreationDate="2019-10-20T11:42:49.337" UserId="11335" Text="GLSL - increasing line spacing with y" ContentLicense="CC BY-SA 4.0" />
  <row Id="25354" PostHistoryTypeId="3" PostId="9273" RevisionGUID="9464c550-3556-4002-ae39-64518e881e7d" CreationDate="2019-10-20T11:42:49.337" UserId="11335" Text="|opengl|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25360" PostHistoryTypeId="5" PostId="9269" RevisionGUID="31311bc5-257e-4442-a725-34cde8f558fa" CreationDate="2019-10-21T16:59:14.967" UserId="2654" Comment="added 115 characters in body" Text="For whatever reason, the text for that function documentation was copied from the GL_ARB_program_interface_query extension. Extensions in OpenGL are always defined relative to a specific version of the OpenGL specification. So if an extension references something in a specification, it's talking about that version of the spec.&#xD;&#xA;&#xD;&#xA;However, the OpenGL specification was *massively* restructured between 4.2 and 4.3, with whole chapters moved around. This means that table references in 4.2 become completely wrong relative to 4.3 and above.&#xD;&#xA;&#xD;&#xA;Program interface query was written against the 4.2 specification. Oddly enough, there is no table 2.16 in that spec; the correct number for that table is 2.13 (so it's likely a typo, since 3 is right below 6 on a number-pad). But even if the extension did mention the right table number, that table moved to a whole different chapter in 4.3+ versions. It's been renumbered and moved since then, so you'll have to look at a particular specification's definition of `glGetProgramResourceiv` to find it.&#xD;&#xA;&#xD;&#xA;In general, if you find something incongruous in the documentation pages, you should look at the [actual OpenGL specification][1] to see what it says about the function's behavior. In this particular case, the [docs in the OpenGL wiki][2] for this function actually includes the table.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/index_gl.php&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/GLAPI/glGetProgramResource" ContentLicense="CC BY-SA 4.0" />
  <row Id="25361" PostHistoryTypeId="2" PostId="9275" RevisionGUID="0bf0c6d4-c58a-4479-add7-57b9ec6e676a" CreationDate="2019-10-21T21:31:47.777" UserId="11346" Text="I would like to intuitively understand the [Path Tracing][1] equation/formula/pseudocode, but I'm not fully getting the last `return` statement.&#xD;&#xA;As per Wikipedia page:&#xD;&#xA;&#xD;&#xA;    // Probability of the newRay&#xD;&#xA;    const float p = 1/(2*M_PI);&#xD;&#xA;    // Compute the BRDF for this ray (assuming Lambertian reflection)&#xD;&#xA;    float cos_theta = DotProduct(newRay.direction, ray.normalWhereObjWasHit);&#xD;&#xA;    Color BRDF = material.reflectance / M_PI ;&#xD;&#xA;    ...&#xD;&#xA;    // Apply the Rendering Equation here.&#xD;&#xA;    return emittance + (BRDF * incoming * cos_theta / p);&#xD;&#xA;&#xD;&#xA;I would understand:&#xD;&#xA;&#xD;&#xA; - _p_ is the probability of new ray (not quite sure what this means), though it's `1 / (2 * PI)`&#xD;&#xA; - *cos_theta* is the angle between the normal of a given surface and the _incoming_ ray&#xD;&#xA; - _BRDF_ is the material colour divided by `PI`&#xD;&#xA; - After computing the _incoming_ colour, we add the _emittance_ component with the _Lambertian_&#xD;&#xA;&#xD;&#xA;I would interpret the second part of the return statement as:&#xD;&#xA;&#xD;&#xA; 1. Reflect current colour based on how much is incoming `BRDF * incoming`&#xD;&#xA; 2. &quot;Weight&quot; it by the angle (rays that are next to the _normal_ would reflect more colour, energy) `* cos_theta`&#xD;&#xA; 3. But then we `/ p`, which if we consider the _BRDF_, removed the PI component and leave a factor of **2** (`BRDF / p = material.reflectance / M_PI * (2 * M_PI) = material.reflectance * 2`)&#xD;&#xA;&#xD;&#xA;Why is there such factor of **2**?&#xD;&#xA;What is the most logical explanation to this?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Path_tracing#Algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="25362" PostHistoryTypeId="1" PostId="9275" RevisionGUID="0bf0c6d4-c58a-4479-add7-57b9ec6e676a" CreationDate="2019-10-21T21:31:47.777" UserId="11346" Text="Why does the reflected component in Lambertian path tracing get multiplied by a factor of 2?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25363" PostHistoryTypeId="3" PostId="9275" RevisionGUID="0bf0c6d4-c58a-4479-add7-57b9ec6e676a" CreationDate="2019-10-21T21:31:47.777" UserId="11346" Text="|rendering|pathtracing|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25365" PostHistoryTypeId="2" PostId="9276" RevisionGUID="9b1a1806-d0a0-4731-9886-6ef4e4e064ee" CreationDate="2019-10-22T11:02:20.180" UserId="2479" Text="I don't know about other platforms, but for DirectX resolving a texture means blending multi-sampled texture into a non-multisampled one. For simple scenarios this is usually done automatically by the output merger, but is often needed to be done explicitly (e.g. [ResolveSubresource][1]) when using multi-sampled render target as an input for a next render pass (e.g. post-processing). Reasons being both lower complexity of the following pass shaders and performance.&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-resolvesubresource" ContentLicense="CC BY-SA 4.0" />
  <row Id="25367" PostHistoryTypeId="2" PostId="9277" RevisionGUID="6fbc12e1-1fea-4bb2-b6ab-19ab596d84d1" CreationDate="2019-10-22T16:11:34.400" UserId="209" Text="Perhaps some example uses from graphics papers might be helpful - it basically refers to computing a 'pixel' potentially from multiple fragments...&#xD;&#xA;&#xD;&#xA;**RealityEngine Graphics  (Akeley. 1993)** &#xD;&#xA;&#xD;&#xA;&gt;Thus the image is complete as soon as the last primitive&#xD;&#xA;has been rendered; there is no need for a final framebuffer operation&#xD;&#xA;to *resolve* the multiple color samples at each pixel location to a&#xD;&#xA;single displayable color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Hardware Accelerated Rendering Of Antialiasing Using A Modified A-buffer Algorithm. (Winner et al, 1997)**&#xD;&#xA;&gt; Pixels which are completely covered by opaque objects are *resolved*&#xD;&#xA;in a single pass.&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&gt;Otherwise multiple passes are required to *resolve* the final color&#xD;&#xA;for each pixel in the scene.&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**A Directionally Adaptive Edge Anti-Aliasing Filter. (Iourcha et al, 2009)**&#xD;&#xA;&#xD;&#xA;&gt;Downsampling is performed by a *resolve*, which is the aggregation of the samples with filtering.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25368" PostHistoryTypeId="5" PostId="9277" RevisionGUID="823bbb74-c2ab-47f4-81bc-bbb3ae663013" CreationDate="2019-10-23T07:42:53.330" UserId="209" Comment="improved English" Text="Perhaps some example usage from graphics papers might be helpful - it basically refers to computing a 'pixel' value potentially from multiple fragments...&#xD;&#xA;&#xD;&#xA;**RealityEngine Graphics  (Akeley. 1993)** &#xD;&#xA;&#xD;&#xA;&gt;Thus the image is complete as soon as the last primitive&#xD;&#xA;has been rendered; there is no need for a final framebuffer operation&#xD;&#xA;to *resolve* the multiple color samples at each pixel location to a&#xD;&#xA;single displayable color.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Hardware Accelerated Rendering Of Antialiasing Using A Modified A-buffer Algorithm. (Winner et al, 1997)**&#xD;&#xA;&gt; Pixels which are completely covered by opaque objects are *resolved*&#xD;&#xA;in a single pass.&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&gt;Otherwise multiple passes are required to *resolve* the final color&#xD;&#xA;for each pixel in the scene.&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;**A Directionally Adaptive Edge Anti-Aliasing Filter. (Iourcha et al, 2009)**&#xD;&#xA;&#xD;&#xA;&gt;Downsampling is performed by a *resolve*, which is the aggregation of the samples with filtering.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25369" PostHistoryTypeId="6" PostId="9271" RevisionGUID="35a5ec75-9c2d-4295-851c-93f506fbc65d" CreationDate="2019-10-23T10:12:26.257" UserId="209" Comment="edited tags" Text="|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25373" PostHistoryTypeId="50" PostId="9174" RevisionGUID="92b1f2fa-f537-4192-9982-7f8e744c5440" CreationDate="2019-10-23T15:02:10.283" UserId="-1" />
  <row Id="25376" PostHistoryTypeId="4" PostId="9262" RevisionGUID="bcef42e5-c302-455b-a068-1b8fdf2fd45f" CreationDate="2019-10-24T12:43:28.003" UserId="2479" Comment="Expanded &quot;resolve&quot; into more specific &quot;texture resolve&quot;" Text="What does texture resolve mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25377" PostHistoryTypeId="24" PostId="9262" RevisionGUID="bcef42e5-c302-455b-a068-1b8fdf2fd45f" CreationDate="2019-10-24T12:43:28.003" Comment="Proposed by 2479 approved by 209, 6 edit id of 495" ContentLicense="CC BY-SA 4.0" />
  <row Id="25381" PostHistoryTypeId="2" PostId="9280" RevisionGUID="0ae06ed5-a520-4c6a-b2a4-ec6cafd33461" CreationDate="2019-10-25T01:33:55.150" UserId="7955" Text="We tackle this problem by computing, like shaders do, the color of a certain pixel with position $y$ at timestamp $t$, namely $I_{x, y}(t)$. All we want to know if that pixel must draw a bar on timestamp $t$. So simple as that, we start with&#xD;&#xA;&#xD;&#xA;    float horizon = 0.5;&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord ) &#xD;&#xA;    {&#xD;&#xA;       // Normalized pixel coordinates (from 0 to 1)&#xD;&#xA;       vec2 uv = fragCoord / iResolution.xy;&#xD;&#xA;    &#xD;&#xA;       float position = uv.y;&#xD;&#xA;       float time = iTime;&#xD;&#xA;&#xD;&#xA;       // everything above our horizon we make white&#xD;&#xA;       if (position &gt; horizon - 0.01) {&#xD;&#xA;          fragColor = vec4(1.0);&#xD;&#xA;          return;&#xD;&#xA;       }&#xD;&#xA;    &#xD;&#xA;       // check if pixel is on the bar, and if so color it white.&#xD;&#xA;       float color = isOnBar(time, position);&#xD;&#xA;    &#xD;&#xA;       fragColor = vec4(color, color, color, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Next step is to determine whether that pixel actually is on the bar.&#xD;&#xA;This problem can be solved with the rules of gravity. We visualize the bars falling down from the horizon. For any pixel $I_{x, y}$, we can say the pixel is on the first bar if&#xD;&#xA;&#xD;&#xA; $h_{bar}(t) = I_{y}(t)$. &#xD;&#xA;&#xD;&#xA;We know however that bars fall with gravity from the horizon, so:&#xD;&#xA;&#xD;&#xA; $h_{bar}(t) = h_{horizon} - gt^{2}$. &#xD;&#xA;&#xD;&#xA;Hence, the falling time $ t_{\text{fall}} $, when the bar hits the pixel, can be calculated with &#xD;&#xA;&#xD;&#xA;$ t_{\text{fall}} = \sqrt{ \frac{h_{horizon} - I_{y}(t_{\text{fall}})}g } $. &#xD;&#xA;&#xD;&#xA;However, this was just our first bar. Any other time a bar hitting that pixel, is when $ &#xD;&#xA;(t - t_{\text{fall}}) \bmod a = 0 $, where $ a $ is our falling frequency. &#xD;&#xA;&#xD;&#xA;*e.g. first bar hits a pixel after 3 seconds, and every 2 seconds another bar falls, then for instance on the 7th second a bar again hits our pixel: $ (7 - 3) \bmod 2 $ is indeed $0$.* &#xD;&#xA;&#xD;&#xA;How much room we give when computing that modulo close to zero, is the width of our bar. Right now, we can incorporate the widening of the bars when they drop. &#xD;&#xA;&#xD;&#xA;    float gravity = 0.1;&#xD;&#xA;    float timeBetweenBars = 0.5; &#xD;&#xA;&#xD;&#xA;    float isOnBar(float time, float position) {&#xD;&#xA;       float timeOfHit = sqrt((horizon - position) / gravity);&#xD;&#xA;       float moddedTime = mod(time - timeOfHit, timeBetweenBars);&#xD;&#xA;       &#xD;&#xA;       // the lower the pixel, the more room we give to catching the bar with this pixel.&#xD;&#xA;       if (moddedTime &lt; 0.1 * (1.0 - position)) {&#xD;&#xA;          return 1.0;&#xD;&#xA;       };&#xD;&#xA;       return 0.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[Here is the code on ShaderToy][1]&#xD;&#xA;&#xD;&#xA;[![Horizon Outrun-esque scene][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/tscXD4&#xD;&#xA;  [2]: https://i.stack.imgur.com/IIqXa.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="25382" PostHistoryTypeId="5" PostId="9259" RevisionGUID="019a99b4-d1d3-4cdb-aa8b-60e4493f5257" CreationDate="2019-10-25T08:10:08.830" UserId="209" Comment="Added link to related question" Text="Indeed there are/were 'just in time' renderers. &#xD;&#xA;&#xD;&#xA;For example, Dreamcast (PowerVR CLX2) had a mode where the 'frame buffer' only had to be a few rows of tiles in size. The system would be rendering into one row while the display was reading out of some subset of the others. It would then cycle through the buffers. &#xD;&#xA;&#xD;&#xA;In order to do this, however, you *do* need a display-list rendering system. A standard 'immediate mode' renderer is not appropriate.&#xD;&#xA;&#xD;&#xA;Of course, scene complexity needs to be considered carefully for this sort of scheme to work. In particular, if one tiny section of the screen contains particularly complex geometry, the renderer might not finish it in time before the display needs to read it. Allocating more memory for the partial screen buffer allows for more variability in scene complexity.&#xD;&#xA;&#xD;&#xA;I also have a feeling/seem to recall some old (e.g 60s/70s?) flight simulators might have rendered 'on the fly' because memory (for a frame buffer) was once fiendishly expensive. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, the PowerVR PCX1/PXC2 ports of Tomb Raider had an optional single buffered rendering mode. (This was primarily because one of the guys doing the port (cough, me, cough) only had a 2MB 2D graphics card which could only allocate a single 1024x768 framebuffer).  Again, since the system was tile-based, it didn't suffer from the nasty artefacts you'd get with single buffering on a traditional Z-buffer system.&#xD;&#xA;&#xD;&#xA;UPDATE:&#xD;&#xA;FWIW there's another related question on [&quot;Racing the Beam&quot; here][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/q/44/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="25383" PostHistoryTypeId="2" PostId="9281" RevisionGUID="91d2956f-ef46-4a2b-849f-128c584ee6ed" CreationDate="2019-10-26T13:27:00.077" UserId="7955" Text="I would write an algorithm where you would iteratively fill lines into rectangles and create a rectangle merging and splitting procedure based on area and thickness. I will use the following image as an example image for the algorithm:&#xD;&#xA;&#xD;&#xA;[![base image wall thickness decomposition][1]][1]&#xD;&#xA;&#xD;&#xA;**Step 1**&#xD;&#xA;Find all the uninterrupted horizontal and vertical lines in the image. &#xD;&#xA;&#xD;&#xA;[![all horizontal uninterrupted lines][2]][2][![all vertical uninterrupted lines][3]][3]&#xD;&#xA;&#xD;&#xA;In python you would do something like this:&#xD;&#xA;&#xD;&#xA;    def horizontal_longest_lines(im):&#xD;&#xA;       counts = {}&#xD;&#xA;       on_a_line = False&#xD;&#xA;       line = None&#xD;&#xA;       for row_index, row in enumerate(im):&#xD;&#xA;           for col_index, pixel in enumerate(row):&#xD;&#xA;               coord = (row_index, col_index)&#xD;&#xA;               if not pixel:&#xD;&#xA;                   on_a_line = False&#xD;&#xA;                   line = None&#xD;&#xA;                   continue&#xD;&#xA;               if pixel:&#xD;&#xA;                   if not on_a_line:&#xD;&#xA;                       on_a_line = True&#xD;&#xA;                       line = (coord, coord)&#xD;&#xA;                       counts[line] = 1&#xD;&#xA;                   else:&#xD;&#xA;                       current = counts[line]&#xD;&#xA;                       del counts[line]&#xD;&#xA;                       line = (line[0], coord)&#xD;&#xA;                       counts[line] = current + 1&#xD;&#xA;       return counts&#xD;&#xA;&#xD;&#xA;    def vertical_longest_lines(im):&#xD;&#xA;       counts = horizontal_longest_lines(im.transpose())&#xD;&#xA;       new_counts = {}&#xD;&#xA;       for key in counts:&#xD;&#xA;          new_counts[(key[0][::-1], key[1][::-1])] = counts[key]&#xD;&#xA;       return new_counts&#xD;&#xA;&#xD;&#xA;**Step 2** fill the area around the lines to create rectangles from the lines:&#xD;&#xA; &#xD;&#xA;[![from line to rectangle for wall thickness decomposition algorithm][4]][4]&#xD;&#xA;[![from line to rectangle for wall thickness decomposition algorithm][5]][5]&#xD;&#xA;[![from line to rectangle for wall thickness decomposition algorithm][6]][6]&#xD;&#xA;[![from line to rectangle for wall thickness decomposition algorithm][7]][7] etc.&#xD;&#xA;&#xD;&#xA;For a more efficient algorithm, you could improve this step by trying to merge existing lines into rectangles. But that would probably a bit more complicated to write.&#xD;&#xA;&#xD;&#xA;**Step 3** Since some lines will create the same rectangle, these duplicate rectangles need to be removed.&#xD;&#xA;&#xD;&#xA;**Step 4** Find overlapping rectangles, give preferences to rectangles that have a bigger area. Cut off the overlapping part from the smaller rectangle.&#xD;&#xA;For these two rectangles:&#xD;&#xA;&#xD;&#xA;[![overlapping rectangles][8]][8]&#xD;&#xA;[![overlapping rectangles][9]][9]&#xD;&#xA;&#xD;&#xA;The result would then be:&#xD;&#xA;&#xD;&#xA;[![split rectangles algorithm][10]][10]&#xD;&#xA;&#xD;&#xA;**Step 5** Some edge cases can happen, where the resulting cut-off does not result in a new rectangle. For these cases, split the resulting shape in new rectangles.&#xD;&#xA;For instance in this case:&#xD;&#xA;&#xD;&#xA;[![edge case wall splitting][11]][11]&#xD;&#xA;[![edge case wall splittinge][12]][12]&#xD;&#xA;[![edge case wall splitting][13]][13]&#xD;&#xA;[![edge case wall splitting][14]][14]&#xD;&#xA;&#xD;&#xA;Do note, there are two possibilities here in splitting up the resulting shape. You would need to fine-tune this process.&#xD;&#xA;&#xD;&#xA;**Step 6** Merge rectangles that have exactly the same width as the other rectangle's height and are touching each other.&#xD;&#xA;&#xD;&#xA;All  the resulting rectangles are now the decomposed walls by thickness:&#xD;&#xA;&#xD;&#xA;[![result wall thickness decomposition algorithm][15]][15]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FYSIUs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ISiSxs.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/n3VYMs.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/O4pk5s.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/Mp8Zds.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/JN7Q9s.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/cdchjs.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/AwUWOs.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/SePJ7s.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/HE6A1s.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/KfojYs.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/SbGUHs.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/b0y2Ys.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/z3ibYs.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/iOYp4s.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25384" PostHistoryTypeId="2" PostId="9282" RevisionGUID="a8bc9b1f-eb0b-4eed-acbd-32f38e56947f" CreationDate="2019-10-26T16:33:42.110" UserId="6041" Text="I am trying to calculate the derivatives of a sampled data set by following an example in [this book][1]. The data is a set of 2d quads(green area in below) and their vertices(4 each). The data is sampled from [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;The book states that the derivatives of any points are calculated by:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5] are the quadrilateral basis functions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;I can calculate df/dx and df/dy. &#xD;&#xA;&#xD;&#xA;Bit for df/dz, where I struggle, I assume&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8] &#xD;&#xA;&#xD;&#xA;and therefore df/dz = 0. But this cannot be correct since df/dz should be 1(by making the above analytic function implicit and differentiating it for z).&#xD;&#xA;&#xD;&#xA;And this could happen, in general, for example, if the data set was rotated 90 degree and align with xz axis. That is the function values were in y coordinates instead of z. But having only sample points one cannot know what two function parameters are whether x,y or x and z.&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books/about/Data_Visualization.html?id=GPwYCwAAQBAJ&amp;printsec=frontcover&amp;source=kp_read_button&amp;redir_esc=y#v=onepage&amp;q=%20gllightfv&amp;f=false&#xD;&#xA;  [2]: https://i.stack.imgur.com/Klwhv.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ySAtb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/iHqWJ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/KdZ65.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/opYtc.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/xrwjd.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/YKxwY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25385" PostHistoryTypeId="1" PostId="9282" RevisionGUID="a8bc9b1f-eb0b-4eed-acbd-32f38e56947f" CreationDate="2019-10-26T16:33:42.110" UserId="6041" Text="computing derivatives of sampled data" ContentLicense="CC BY-SA 4.0" />
  <row Id="25386" PostHistoryTypeId="3" PostId="9282" RevisionGUID="a8bc9b1f-eb0b-4eed-acbd-32f38e56947f" CreationDate="2019-10-26T16:33:42.110" UserId="6041" Text="|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25387" PostHistoryTypeId="50" PostId="9181" RevisionGUID="f5ac294b-ea73-48a3-bf03-036461ee44ee" CreationDate="2019-10-27T05:01:00.117" UserId="-1" />
  <row Id="25388" PostHistoryTypeId="50" PostId="8870" RevisionGUID="59a3fa56-d564-48f6-a098-670c5fbe5945" CreationDate="2019-10-27T06:01:30.347" UserId="-1" />
  <row Id="25389" PostHistoryTypeId="2" PostId="9283" RevisionGUID="4e8e8c8a-eb20-4572-aefe-a8a25557d0e1" CreationDate="2019-10-27T11:46:28.953" UserId="11316" Text="I am trying to reproduce the results of 2017 paper &quot;Learning the light transport the reiforced way&quot; by Duhm and Keller. I already know how to generate random rays inside the equally-sized patches on sphere. The normal of hemisphere around the hit point is along z-axis. And each ray direction generated by:&#xD;&#xA;&#xD;&#xA;$d = (sin(\phi)cos(\theta), sin(\phi)sin(\theta), cos(\phi))$&#xD;&#xA;&#xD;&#xA;How could I apply rotations to this vectors? Should I apply the rotation to patches or rays. For example, imagine the surface is a sphere and not a plane. I'm really confused how to do this!" ContentLicense="CC BY-SA 4.0" />
  <row Id="25390" PostHistoryTypeId="1" PostId="9283" RevisionGUID="4e8e8c8a-eb20-4572-aefe-a8a25557d0e1" CreationDate="2019-10-27T11:46:28.953" UserId="11316" Text="The correct way to apply 3d rotations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25391" PostHistoryTypeId="3" PostId="9283" RevisionGUID="4e8e8c8a-eb20-4572-aefe-a8a25557d0e1" CreationDate="2019-10-27T11:46:28.953" UserId="11316" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25392" PostHistoryTypeId="5" PostId="9283" RevisionGUID="b0c2ad23-c622-4ddc-930c-34e93faec18c" CreationDate="2019-10-27T11:52:13.910" UserId="11316" Comment="added 24 characters in body" Text="I am trying to reproduce the results of 2017 paper &quot;Learning the light transport the reiforced way&quot; by Duhm and Keller. I already know how to generate random samples inside the equally-sized patches on sphere. The normal of hemisphere around the hit point is along z-axis. And each ray direction generated by:&#xD;&#xA;&#xD;&#xA;$d = (sin(\phi)cos(\theta), sin(\phi)sin(\theta), cos(\phi))$&#xD;&#xA;&#xD;&#xA;How could I apply rotations to this vectors by only knowing normals? Should I apply the rotations to patches or rays. For example, imagine the surface is a sphere and not a plane. I'm really confused how to do this!" ContentLicense="CC BY-SA 4.0" />
  <row Id="25393" PostHistoryTypeId="12" PostId="9282" RevisionGUID="bfad6962-d78f-43e9-ac61-5d714b607efa" CreationDate="2019-10-27T14:32:37.823" UserId="6041" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6041,&quot;DisplayName&quot;:&quot;ali&quot;}]}" />
  <row Id="25394" PostHistoryTypeId="2" PostId="9284" RevisionGUID="7af30cdf-c802-49ae-b954-684848a71508" CreationDate="2019-10-27T21:09:48.447" UserId="11375" Text="Given the up and focal vector of the perspective camera, the position of the camera and the vertical and horizontal opening angle of the FOV. How can I calculate a ray for given screen space coordinates (x, y) where x, y are between -1 and 1 (inclusive).&#xD;&#xA;I tried this:&#xD;&#xA;&#xD;&#xA;1) Calculate the vectors sx, sy that span the image plane&#xD;&#xA;&#xD;&#xA;sy = -norm(up)&#xD;&#xA;&#xD;&#xA;sx = norm(cross(focal, sy))&#xD;&#xA;&#xD;&#xA;2) Calculate the focal length f&#xD;&#xA;&#xD;&#xA;f = 1 * sin(90 - vertical) / sin(vertical) &#xD;&#xA;&#xD;&#xA;3) Create the ray&#xD;&#xA;&#xD;&#xA;dir = (center + x * sx + y * sy + f * forward) - center&#xD;&#xA;&#xD;&#xA;r(t) = center + t * norm(dir)&#xD;&#xA;&#xD;&#xA;But the resulting image does not turn out like the reference image. Someone know what I am doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25395" PostHistoryTypeId="1" PostId="9284" RevisionGUID="7af30cdf-c802-49ae-b954-684848a71508" CreationDate="2019-10-27T21:09:48.447" UserId="11375" Text="Perspective Raytracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="25396" PostHistoryTypeId="3" PostId="9284" RevisionGUID="7af30cdf-c802-49ae-b954-684848a71508" CreationDate="2019-10-27T21:09:48.447" UserId="11375" Text="|raytracing|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25397" PostHistoryTypeId="2" PostId="9285" RevisionGUID="2791c915-e459-4449-984c-798d49757d26" CreationDate="2019-10-27T22:37:55.493" UserId="10096" Text="Let the horizontal FOV be given as theta (in radians), and the vertical FOV be given as phi (in radians). The we know that:&#xD;&#xA;&#xD;&#xA;$$\tan\frac{\theta}{2}=\frac{w}{f}, \tan\frac{\phi}{2}=\frac{h}{f}$$&#xD;&#xA;&#xD;&#xA;Let us pick $f = 1$, then $w = \tan\frac{\theta}{2}, h = \tan\frac{\phi}{2}$. Now your ray generation direction generation formula looks like:&#xD;&#xA;&#xD;&#xA;$$\pmb{d} = x w\pmb{u} + yh\pmb{v} + \pmb{w}$$&#xD;&#xA;&#xD;&#xA;Where $\pmb{u},\pmb{v}, \pmb{w}$ are your sx,sy, forward vectors. Essentially, I found th extent of the smallest/largest x and y respectively ($1w = w, -1w=-w$, etc.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="25398" PostHistoryTypeId="5" PostId="9285" RevisionGUID="bf1cd50f-1e68-4fe1-a3fb-571643bc8fb9" CreationDate="2019-10-27T22:43:05.430" UserId="10096" Comment="added 124 characters in body" Text="Let the horizontal FOV be given as theta (in radians), and the vertical FOV be given as phi (in radians). The we know that:&#xD;&#xA;&#xD;&#xA;$$\tan\frac{\theta}{2}=\frac{w}{f}, \tan\frac{\phi}{2}=\frac{h}{f}$$&#xD;&#xA;&#xD;&#xA;Let us pick $f = 1$, then $w = \tan\frac{\theta}{2}, h = \tan\frac{\phi}{2}$. Now your ray generation direction generation formula looks like:&#xD;&#xA;&#xD;&#xA;$$\pmb{d} = x w\pmb{u} + yh\pmb{v} + \pmb{w}$$&#xD;&#xA;&#xD;&#xA;Where $\pmb{u},\pmb{v}, \pmb{w}$ are your sx,sy, forward vectors. Essentially, I found the extent of the smallest/largest x and y respectively ($1w = w, -1w=-w$, etc.). You can premultiply $\pmb{u}, \pmb{v}$ with $w, h$ respectively, if you don't want to perform the multiplication per ray." ContentLicense="CC BY-SA 4.0" />
  <row Id="25399" PostHistoryTypeId="5" PostId="4656" RevisionGUID="1e1635b7-ca8c-4ffb-a838-df3072a77905" CreationDate="2019-10-28T00:51:51.253" UserId="-1" Comment="fixing broken link." Text="I'm implementing mesh skinning in a project of mine. I can calculate vertex positions based on bone transformations, but I've run into a problem with calculating their normals.&#xD;&#xA;&#xD;&#xA;From the resources I've read, it appears that a given vertex's skinned normal is the weighted sum of each influencing bone's transform applied to the vertex's normal.&#xD;&#xA;&#xD;&#xA;What I don't understand, is how this would produce equivalent normals to what you *would* get if you calculated each vertex's normal directly. (I.E. from the sum of the normals of its adjacent faces)&#xD;&#xA;&#xD;&#xA;For example, consider the case of three connected vertices with the normals shown below. Note the bone in the center, which has the same position as the center vertex.&#xD;&#xA;&#xD;&#xA;[![A simple rigged mesh][1]][1]&#xD;&#xA;&#xD;&#xA;Next, suppose this bone is turned 45 degrees CCW. If this bone only influenced the vertex to its right, my understanding is that it would produce the following result:&#xD;&#xA;&#xD;&#xA;[![Single influenced vertex][2]][2]&#xD;&#xA;&#xD;&#xA;This is because there is only one influencing bone, and the normal is rotated by the same rotation as the bone, 45 degrees CCW.&#xD;&#xA;&#xD;&#xA;Next, consider that the bone influenced the middle *and* right vertices. Each vertex's normal would be rotated exactly as in the previous image.&#xD;&#xA;&#xD;&#xA;[![Two influenced vertices][3]][3]&#xD;&#xA;&#xD;&#xA;But, neither of these would produce the &quot;correct&quot; normal for the middle vertex, shown here:&#xD;&#xA;&#xD;&#xA;[![Presumably the correct middle normal][4]][4]&#xD;&#xA;&#xD;&#xA;So, my question is, is this the intended behavior for this algorithm? Is it only meant to be an approximation, or have I missed something critical? How are these normals meant to be calculated?&#xD;&#xA;&#xD;&#xA;For what it's worth, the resources I've been following are presented [here][5] and [here][6].&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/stboN.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mQfeC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/MG97U.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/dKPYh.png&#xD;&#xA;  [5]: http://web.archive.org/web/20161027175806/http://ruh.li/AnimationVertexSkinning.html&#xD;&#xA;  [6]: http://www.3dgep.com/loading-and-animating-md5-models-with-opengl/#The_MD5Model::PrepareMesh_Method" ContentLicense="CC BY-SA 4.0" />
  <row Id="25400" PostHistoryTypeId="24" PostId="4656" RevisionGUID="1e1635b7-ca8c-4ffb-a838-df3072a77905" CreationDate="2019-10-28T00:51:51.253" Comment="Proposed by anonymous approved by 209, 5991 edit id of 493" ContentLicense="CC BY-SA 4.0" />
  <row Id="25401" PostHistoryTypeId="13" PostId="9282" RevisionGUID="255d354e-5a9a-4409-930e-a22cd0927f62" CreationDate="2019-10-28T07:50:15.970" UserId="6041" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6041,&quot;DisplayName&quot;:&quot;ali&quot;}]}" />
  <row Id="25402" PostHistoryTypeId="5" PostId="9282" RevisionGUID="8dfc31e9-3214-4f73-ab76-74b8f94e1a0c" CreationDate="2019-10-28T07:50:52.627" UserId="6041" Comment="deleted 278 characters in body" Text="I am trying to calculate the derivatives of a sampled data set by following an example in [this book][1]. The data is a set of 2d quads(green area in below) and their vertices(4 each). The data is sampled from [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;The book states that the derivatives of any points are calculated by:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5] are the quadrilateral basis functions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;I can calculate df/dx and df/dy. &#xD;&#xA;&#xD;&#xA;But where I struggle is calculating df/dz. I assume&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8] &#xD;&#xA;&#xD;&#xA;and therefore df/dz = 0. But this cannot be correct since df/dz should be 1(by making the above analytic function implicit and differentiating it for z).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books/about/Data_Visualization.html?id=GPwYCwAAQBAJ&amp;printsec=frontcover&amp;source=kp_read_button&amp;redir_esc=y#v=onepage&amp;q=%20gllightfv&amp;f=false&#xD;&#xA;  [2]: https://i.stack.imgur.com/Klwhv.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ySAtb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/iHqWJ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/KdZ65.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/opYtc.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/xrwjd.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/YKxwY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25406" PostHistoryTypeId="2" PostId="9287" RevisionGUID="edcff03a-f8ea-45cd-8601-2bfcdec6ce7d" CreationDate="2019-10-29T01:46:47.810" UserId="11385" Text="I'm posting here after some time searching the Internet and reading presentations and papers, to find out the best options to solve the problem I have.&#xD;&#xA;&#xD;&#xA;I'm implementing irradiance field with spherical harmonics for diffuse global illumination. As any other developer, I'm facing the typical problem of not having enough lit probes to properly approximate irradiance in some parts of the scene, due to the fact that sometimes those irradiance fields are in shadow and therefore don't receive any light. Let's assume the irradiance fields are set in an uniform grid, and that there's no artist to tweak the position of those irradiance fields to avoid them falling in shaded areas.&#xD;&#xA;&#xD;&#xA;Let's use the picture I uploaded as example. In this picture, the green dots represent irradiance fields which are receiving light, and the black ones, irradiance fields which are not receiving light, because of the red plane puts them in shadow (we can think of the red plane as a wall or floor).&#xD;&#xA;&#xD;&#xA;The problem I have is to properly approximate the irradiance at the red plane, since the four irradiance fields in shadow will make the irradiance at the wall darker than it is because of the transition from lit to unlit irradiance fields (I'm using trilinear interplation between the eight irradiance fields surrounding each world position).&#xD;&#xA;&#xD;&#xA;The closest option to solve this problem I've found is to use &quot;Irradiance Gradients&quot; (https://developer.amd.com/wordpress/media/2012/10/Tatarchuk_Irradiance_Volumes.pdf), but I'm not sure this is the only / best option, so I'm wondering, does anyone recommend this / another way to solve the problem?&#xD;&#xA;&#xD;&#xA;Many thanks for your time and help,&#xD;&#xA;&#xD;&#xA;Alex&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IofC8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25407" PostHistoryTypeId="1" PostId="9287" RevisionGUID="edcff03a-f8ea-45cd-8601-2bfcdec6ce7d" CreationDate="2019-10-29T01:46:47.810" UserId="11385" Text="Irradiance field approximation with black probes" ContentLicense="CC BY-SA 4.0" />
  <row Id="25408" PostHistoryTypeId="3" PostId="9287" RevisionGUID="edcff03a-f8ea-45cd-8601-2bfcdec6ce7d" CreationDate="2019-10-29T01:46:47.810" UserId="11385" Text="|rendering|lighting|global-illumination|shading|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25410" PostHistoryTypeId="50" PostId="9178" RevisionGUID="632b1909-024f-4b4b-b383-659a85479a33" CreationDate="2019-10-29T21:02:05.257" UserId="-1" />
  <row Id="25411" PostHistoryTypeId="5" PostId="9282" RevisionGUID="5aa30c70-3a21-47ef-bc36-0912e079f93c" CreationDate="2019-10-30T11:31:46.907" UserId="209" Comment="Added text relating to comments by OP and also replaced one image with mathjax" Text="I am trying to calculate the derivatives of a sampled data set by following an example in [this book][1]. The data is a set of 2d quads(green area in below) and their vertices(4 each). The data is in the following example is sampled from $z=f(x,y)=e^{-(x^2+y^2)}$ but, in general, the underlying function might not be known.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;The book states that the derivatives of any points are calculated by:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5] are the quadrilateral basis functions:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;I can calculate df/dx and df/dy. &#xD;&#xA;&#xD;&#xA;But where I struggle is calculating df/dz. I assume&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8] &#xD;&#xA;&#xD;&#xA;and therefore df/dz = 0. But this cannot be correct since df/dz should be 1(by making the above analytic function implicit and differentiating it for z).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.co.uk/books/about/Data_Visualization.html?id=GPwYCwAAQBAJ&amp;printsec=frontcover&amp;source=kp_read_button&amp;redir_esc=y#v=onepage&amp;q=%20gllightfv&amp;f=false&#xD;&#xA;  [2]: https://i.stack.imgur.com/Klwhv.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ySAtb.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/iHqWJ.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/KdZ65.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/opYtc.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/xrwjd.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/YKxwY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25412" PostHistoryTypeId="6" PostId="9282" RevisionGUID="5aa30c70-3a21-47ef-bc36-0912e079f93c" CreationDate="2019-10-30T11:31:46.907" UserId="209" Comment="Added text relating to comments by OP and also replaced one image with mathjax" Text="|sampling|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25413" PostHistoryTypeId="50" PostId="9199" RevisionGUID="0f2d763b-4703-438b-8250-07db766e1464" CreationDate="2019-10-30T23:02:20.297" UserId="-1" />
  <row Id="25414" PostHistoryTypeId="50" PostId="9189" RevisionGUID="92d19964-c50d-4440-ae40-38ee68ba8586" CreationDate="2019-10-31T05:00:50.103" UserId="-1" />
  <row Id="25422" PostHistoryTypeId="50" PostId="9201" RevisionGUID="d84707ab-7943-432e-a6d8-e2e6d349e1dc" CreationDate="2019-11-01T10:01:30.347" UserId="-1" />
  <row Id="25429" PostHistoryTypeId="2" PostId="9292" RevisionGUID="cac19b79-95de-49a6-977c-cf4bd3003b7b" CreationDate="2019-11-02T22:18:30.457" UserId="11409" Text="In my procedurally generated mesh in Unity, not all vertices are vertexes of all neighbouring triangles - essentially, it's a grid with cells of varying sizes. This is messing up the calculation of normals however, making the lightning not smooth. How should I account for this? This is a part of the mesh to illustrate what I mean, in shaded wireframe and shaded mode:&#xD;&#xA;[![][1]][1][![][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CtwSH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/8vTR6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25430" PostHistoryTypeId="1" PostId="9292" RevisionGUID="cac19b79-95de-49a6-977c-cf4bd3003b7b" CreationDate="2019-11-02T22:18:30.457" UserId="11409" Text="Calculating normals for vertices which aren't a vertex of all neighbouring triangles" ContentLicense="CC BY-SA 4.0" />
  <row Id="25431" PostHistoryTypeId="3" PostId="9292" RevisionGUID="cac19b79-95de-49a6-977c-cf4bd3003b7b" CreationDate="2019-11-02T22:18:30.457" UserId="11409" Text="|3d|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25432" PostHistoryTypeId="2" PostId="9293" RevisionGUID="634460b7-2837-4215-87dd-0e32419534d6" CreationDate="2019-11-02T22:55:57.767" UserId="48" Text="For the shading to match, the normals (and any other vertex attributes) of the small triangles' verts would have to match the linear interpolation along the large triangle edge that they adjoin to.&#xD;&#xA;&#xD;&#xA;For example: all the vertices in the green box below would need to be set by interpolating between the two blue vertices, based on their position along that edge.&#xD;&#xA;&#xD;&#xA;As Nicol alluded to however, you may not get perfectly watertight rendering—or a perfect match in the shading—when constructing a mesh with [T-junctions](https://computergraphics.stackexchange.com/questions/1461/why-do-t-junctions-in-meshes-result-in-cracks) like this.&#xD;&#xA;&#xD;&#xA;![wireframe marked with vertices][1]]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pJ6zm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25433" PostHistoryTypeId="50" PostId="9212" RevisionGUID="102234d3-6fe2-4750-8549-bf0e98536c94" CreationDate="2019-11-03T12:01:05.223" UserId="-1" />
  <row Id="25435" PostHistoryTypeId="2" PostId="9294" RevisionGUID="b35798b4-0fa5-4579-9fcc-0a23fdaa5aa6" CreationDate="2019-11-03T19:38:47.023" UserId="11375" Text="I am having the following issue. I am working on a ray tracer for school and I am trying to render a sphere where the radiance of a intersection point is the dot product of the ray direction and the normal at the point of intersection. This works fine if return the inverted normal ( i.e. a vector going from the intersection point to the center of the sphere but not the other way around as it should be ) and I can't figure out what I messed up. Anyone have a intuitive clue on what I could have messed up? Can't really post code here as it's a school task but feel free to ask for further information and I am trying to provide as best as I can. (left: inverted normals, right: right normals)&#xD;&#xA;&#xD;&#xA;[![inverted_normals][1]][1][![right normals][2]][2] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/shvDJ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ZwI2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25436" PostHistoryTypeId="1" PostId="9294" RevisionGUID="b35798b4-0fa5-4579-9fcc-0a23fdaa5aa6" CreationDate="2019-11-03T19:38:47.023" UserId="11375" Text="Inverted Normals in Raytracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="25437" PostHistoryTypeId="3" PostId="9294" RevisionGUID="b35798b4-0fa5-4579-9fcc-0a23fdaa5aa6" CreationDate="2019-11-03T19:38:47.023" UserId="11375" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25438" PostHistoryTypeId="2" PostId="9295" RevisionGUID="9ef5d50f-5b5e-41a0-b0c8-40cb58d84c35" CreationDate="2019-11-03T20:29:41.323" UserId="10615" Text="When you take the dot product of two unit vectors, you are essentially calculating the cosine of the angle between them. This value can become negative when the two vectors are less than 90 degrees apart (which they are when you have outward normals).&#xD;&#xA;&#xD;&#xA;Negate the normal before dotting it. That way you can have outward facing normals and also correct shading." ContentLicense="CC BY-SA 4.0" />
  <row Id="25439" PostHistoryTypeId="2" PostId="9296" RevisionGUID="14af7bbd-ae1b-4625-b8af-12d5a4ff349b" CreationDate="2019-11-03T20:33:07.540" UserId="10096" Text="The issue is, that you considered that the rays coming from the camera to be the light carrying rays. Instead, the rays bounce off the surface, and return to the light source (which you have decided to position at the camera). This means that your light direction is not $\pmb{d}$ but rather $-\pmb{d}$, then $\cos\theta = - \pmb{d} \cdot \pmb{n}$, provided that both vectors are normalized.&#xD;&#xA;&#xD;&#xA;Also, you really want to try to retirn the correct normal, as it is, your current code will return the wrong normal if the camera is inside the sphere. So your normal should be:&#xD;&#xA;`n = dot(n,d)&lt;0 ? n : -n;`, where `n` is the normal returned by your surface, and `d` is the ray direction for the ray that intersected the surface." ContentLicense="CC BY-SA 4.0" />
  <row Id="25440" PostHistoryTypeId="2" PostId="9297" RevisionGUID="8d836bc6-c894-4a31-b928-d02bb43bf9cb" CreationDate="2019-11-04T13:13:57.837" UserId="10615" Text="If I'm not mistaken, you can make a hybrid renderer which lets a rasterizer solve the visibility problem, then shade all of the projected shapes with a raytracing algorithm. It seems that this isn't commonly done however, what's the reason for that? Oversight?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25441" PostHistoryTypeId="1" PostId="9297" RevisionGUID="8d836bc6-c894-4a31-b928-d02bb43bf9cb" CreationDate="2019-11-04T13:13:57.837" UserId="10615" Text="Why isn't rasterization combined with raytracing more often?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25442" PostHistoryTypeId="3" PostId="9297" RevisionGUID="8d836bc6-c894-4a31-b928-d02bb43bf9cb" CreationDate="2019-11-04T13:13:57.837" UserId="10615" Text="|raytracing|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25443" PostHistoryTypeId="2" PostId="9298" RevisionGUID="be0ed4a0-8d25-4304-a4f0-1dca672c8ed8" CreationDate="2019-11-04T15:39:27.347" UserId="38" Text="There are renderes that do this. Most notably Pixars Renderman prefers to work this way. Hybrid renderers can work in other ways too...&#xD;&#xA;&#xD;&#xA; It used to be that hybrid renderers like this were quite common, they still are somewhat  in software only implementations. They are slowly being replaced though by a new breed of trace only renderes though. Mostly the reason is that by foregoing the other you get a simpler piece of code." ContentLicense="CC BY-SA 4.0" />
  <row Id="25444" PostHistoryTypeId="2" PostId="9299" RevisionGUID="5b9595d5-ffbd-4764-acc1-e0433a22da3e" CreationDate="2019-11-04T16:28:57.627" UserId="137" Text="Because when you test the visibility of a fragment during rasterization you already know (or can easily calculate) all the details that raytracing will give you.&#xD;&#xA;&#xD;&#xA;So doing the ray-triangle collision calculation is redundant.&#xD;&#xA;&#xD;&#xA;But it is the additional lighting beyond the first hit where raytracing is helpful. However each ray is only a small part of what contributes to the lighting in a scene, so you need a lot of them per fragment. And each ray has relatively large cost to compute. &#xD;&#xA;&#xD;&#xA;Those two properties make raytracing not very atractive for real-time rendering without some dedicated acceleration." ContentLicense="CC BY-SA 4.0" />
  <row Id="25445" PostHistoryTypeId="2" PostId="9300" RevisionGUID="e0dab69c-a73f-481b-bf6c-4c670af89a58" CreationDate="2019-11-04T17:29:57.407" UserId="10096" Text="Rasterization is sometimes used for primary rays. However, it limits greatly what you can do - depth of field, motion blur, participating media, refraction, only basic camera models, no adaptive or custom sampling, etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="25446" PostHistoryTypeId="5" PostId="9276" RevisionGUID="4bb77097-4bf5-462b-93c3-81242fc9a6ea" CreationDate="2019-11-04T23:19:25.093" UserId="2479" Comment="minor rewording" Text="I don't know about other contexts, but for DirectX resolving a texture means blending multi-sampled texture into a non-multisampled one. For simple scenarios this is usually done automatically by the output merger, but is often needed to be done explicitly (e.g. [ResolveSubresource][1]) when using multi-sampled render target as an input for a next render pass (e.g. post-processing). Reasons being both performance and lower complexity of the following pass shaders.&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-resolvesubresource" ContentLicense="CC BY-SA 4.0" />
  <row Id="25447" PostHistoryTypeId="2" PostId="9301" RevisionGUID="bdb699a5-5ea1-4993-968f-38314254e1b7" CreationDate="2019-11-05T09:22:21.057" UserId="209" Text="*Disclosure: I work for [IMG/PowerVR][1]*&#xD;&#xA;&#xD;&#xA;Indeed there are rendering systems that can do this: Imagination demonstrated hybrid rendering on their &quot;Wizard&quot; [Ray Tracing/Rasterisation][2] system. Scroll down to &quot;Making ray tracing happen&quot; and there is a screen grab of a hybrid demo.&#xD;&#xA;&#xD;&#xA;As others have mentioned, there are pros and cons: Some advantages include that rasteriser can be extremely efficient at handling the first set of intersections and, for shadows, you don't spend effort pre-rendering portions of shadow maps that may never be visible in the final render. On the downsides, you are typically constrained to the standard pinhole camera model. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/jobs/companies/imagination-technologies&#xD;&#xA;  [2]: https://www.imgtec.com/blog/imagination-technologies-the-ray-tracing-pioneers/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25451" PostHistoryTypeId="50" PostId="8888" RevisionGUID="e0423ca6-865e-4e04-9630-c8aea31284db" CreationDate="2019-11-05T15:00:51.647" UserId="-1" />
  <row Id="25452" PostHistoryTypeId="2" PostId="9303" RevisionGUID="57cc5bf0-891e-4009-8241-4862ef3b2866" CreationDate="2019-11-05T18:25:36.750" UserId="11414" Text="So I'm making a 2D pool game in OpenGL (you might've guessed as soon as I've mentioned collision of circles). I'm having a little trouble with collision detection. What I mean by that is that I have an algorithm that currently works but I'm thinking of improving it.&#xD;&#xA;&#xD;&#xA;So far I've used discrete collision detection, disregarding the possibilities that it might not work at high velocities. However, I've noticed that I in fact sometimes do need the circles (pool balls) to travel at velocities at which the discrete collision detection might fail. The reason for that is that some of those velocities are quite realistic in a real-life game of pool (I've calculated that an average professional break shot in pool can make the ball travel as fast as six times the ball's diameter per 33 milliseconds which is the time interval that one frame lasts on 30FPS machines). Therefore in every such shot my discrete collision detection is very likely to fail.&#xD;&#xA;&#xD;&#xA;This is the idea I've had:&#xD;&#xA;&#xD;&#xA;The dashed circles represent the positions of the balls in the previous frame. The lines from them represent the velocity vectors and, obviously, the circles that they're connected to are their positions in the current frame. &#xD;&#xA;&#xD;&#xA;One thing I would do immediately is check whether the velocity vectors are collinear in which case there's no need to check for any kind of collision. If they're not collinear, I'd find the intersection point of the line segments represented by the points of previous position and the next position (if they don't intersect I just disregard everything) . After that I'd manually translate the balls &quot;before&quot; the point of intersection (I was too lazy to actually compute where the balls would touch so I just put them somewhere near that point for the purposes of illustration, but it doesn't really matter). After I've done all that I would just let the discrete collision detection algorithm, which I already have, do the work.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DJFR6.png&#xD;&#xA;&#xD;&#xA;Couple of things I'm worried about here:&#xD;&#xA;&#xD;&#xA;(1) Since I have more than 2 balls on the table (16 to be precise) can the manual translation step somehow impact eventual collision of one of the balls that have been translated and some other, third ball? It seems to me like it shouldn't, but I'm not sure.&#xD;&#xA;&#xD;&#xA;(2) On one hand I'm thinking that this might cause some glitching since I'm translating the balls &quot;back&quot; after I've already drawn them at their positions. On the other hand since this will only be happening at high velocities it might not matter that much. This also causes me to wonder whether I should do *draw - collide* or *collide - draw*. That is, should I use the principle I've described here (first draw the balls, then check whether they've been drawn too far) or maybe I should &quot;look ahead&quot;, as in check whether the next position could cause problems instead of whether the previous position has caused them?&#xD;&#xA;&#xD;&#xA;Not looking for any code, just ideas and thoughts.&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="25453" PostHistoryTypeId="1" PostId="9303" RevisionGUID="57cc5bf0-891e-4009-8241-4862ef3b2866" CreationDate="2019-11-05T18:25:36.750" UserId="11414" Text="An idea for an implementation of continuos collision detection of circles" ContentLicense="CC BY-SA 4.0" />
  <row Id="25454" PostHistoryTypeId="3" PostId="9303" RevisionGUID="57cc5bf0-891e-4009-8241-4862ef3b2866" CreationDate="2019-11-05T18:25:36.750" UserId="11414" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25455" PostHistoryTypeId="2" PostId="9304" RevisionGUID="191268b5-6241-4ebd-abd5-67c5300336b5" CreationDate="2019-11-05T18:57:33.520" UserId="11114" Text="There is a popular technique of normalising images by dividing each pixel with 255 so that it comes in the range of 0 and 1.&lt;br&gt;&#xD;&#xA;But, then how the same colours are formed when we normalize images.&lt;br&gt;&#xD;&#xA;for instance, there is a pixel with value `0 1 1` and other `0 255 255`, I checked on [RGB colors chart][1], both are showing different colors, but if we normalise the second pixel values then its value will be same as the first one and it should produce different results but on plotting the set of normalized pixels, they come out to be same as the previous one.&#xD;&#xA;&#xD;&#xA;I have previously asked this question - [how RGB images are formed][2]&#xD;&#xA;so deriving out conclusions from the above question.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.rapidtables.com/web/color/RGB_Color.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/9104/how-rgb-images-are-formed" ContentLicense="CC BY-SA 4.0" />
  <row Id="25456" PostHistoryTypeId="1" PostId="9304" RevisionGUID="191268b5-6241-4ebd-abd5-67c5300336b5" CreationDate="2019-11-05T18:57:33.520" UserId="11114" Text="How RGB images are formed when normalized between 0 and 1" ContentLicense="CC BY-SA 4.0" />
  <row Id="25457" PostHistoryTypeId="3" PostId="9304" RevisionGUID="191268b5-6241-4ebd-abd5-67c5300336b5" CreationDate="2019-11-05T18:57:33.520" UserId="11114" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25458" PostHistoryTypeId="2" PostId="9305" RevisionGUID="41e86d61-8029-41d2-aa7a-67739297272e" CreationDate="2019-11-05T21:03:35.317" UserId="10615" Text="I'm kind of lost here as I'm faced with a graphical bug the origin of which I don't even know. In an attempt to recreate a shadertoy I saw that had TXAA, I made a function TemporalAA that takes in 3 buffers: the current frame `buffer`, the last frame `prevbuffer`, and the frame to which we render the anti aliased image `aabuffer`. &#xD;&#xA;&#xD;&#xA;The original implementation: https://www.shadertoy.com/view/4tcXD2&#xD;&#xA;&#xD;&#xA;The issue is that there's this weird overlay pattern, and I don't notice any edge smoothing whatsoever. Also note the brightly colored bands that the spheres get when in this overlay.&#xD;&#xA;&#xD;&#xA;[![Weird artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;It's completely written in C.&#xD;&#xA;&#xD;&#xA;Note: a frame consists of an `uint8` width*height*3 array. (times three for three color channels. `[0] = red, [1] = green, [2] = blue`). Please ignore the fact that everything is `static inline`.&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;static inline vec3 c3tov3(color3 c){&#xD;&#xA;	// convert [0, 255] to [0, 1]&#xD;&#xA;	return (vec3){&#xD;&#xA;		c.r/255.f,&#xD;&#xA;		c.g/255.f,&#xD;&#xA;		c.b/255.f&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static inline color3 v3toc3(vec3 v){&#xD;&#xA;	// convert [0,1] to [0, 255]&#xD;&#xA;	return (color3){&#xD;&#xA;		(uint8_t)fmaxf(fminf(255.f, v.x*255.f), 0),&#xD;&#xA;		(uint8_t)fmaxf(fminf(255.f, v.y*255.f), 0),&#xD;&#xA;		(uint8_t)fmaxf(fminf(255.f, v.z*255.f), 0)&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static inline vec3 encodePalYuv(color3 clr)&#xD;&#xA;{&#xD;&#xA;	vec3 rgb = (vec3){ // pow = gamma correction&#xD;&#xA;		pow((float)clr.r/255, 2),&#xD;&#xA;		pow((float)clr.g/255, 2),&#xD;&#xA;		pow((float)clr.b/255, 2)&#xD;&#xA;	};&#xD;&#xA;	return (vec3){&#xD;&#xA;		dot3(rgb, (vec3){0.299f, 0.587f, 0.114f}),&#xD;&#xA;		dot3(rgb, (vec3){-0.14713f, -0.28886f, 0.436f}),&#xD;&#xA;		dot3(rgb, (vec3){0.615f, -0.51499f, -0.10001f})&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static inline vec3 decodePalYuv(vec3 yuv)&#xD;&#xA;{&#xD;&#xA;	return (vec3){ // pow = gamma correction&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, 0.f, 1.13983}), 0.5),&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, -0.39465, -0.58060}), 0.5),&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, 2.03211, 0.f}), 0.5)&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;static inline void TemporalAA(uint8_t * buffer, uint8_t * prevbuffer, uint8_t * aabuffer, int width, int height) // out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;	int pitch = width*3;&#xD;&#xA;&#xD;&#xA;	for (int u = 1; u &lt; width-1; ++u)&#xD;&#xA;	{&#xD;&#xA;		for (int v = 1; v &lt; height-1; ++v) // we cant do the edge/corner pixels. That would be undefined behaviour&#xD;&#xA;		{&#xD;&#xA;&#xD;&#xA;			int index = (u&lt;&lt;2) + v*pitch; // leftshift 2 == multiply 4 but faster&#xD;&#xA;&#xD;&#xA;			vec3 antialiased = c3tov3( (color3){prevbuffer[index], prevbuffer[index+1], prevbuffer[index+2]} );&#xD;&#xA;			// vec4 lastColor = texture(iChannel1, uv);&#xD;&#xA;			float mixRate = 5.f;//fminf(1/width, 0.5);&#xD;&#xA;			&#xD;&#xA;			//vec3 in0 = texture(iChannel0, uv).xyz;&#xD;&#xA;			color3 in[9];&#xD;&#xA;			in[0] = ( (color3){buffer[index], buffer[index+1], buffer[index+2]} );&#xD;&#xA;			vec3 in0 = c3tov3(in[0]);&#xD;&#xA;&#xD;&#xA;			antialiased = lerp3(compwisemult3(antialiased, antialiased), compwisemult3(in0, in0), mixRate);&#xD;&#xA;			antialiased.x = sqrt(antialiased.x);&#xD;&#xA;			antialiased.y = sqrt(antialiased.y);&#xD;&#xA;			antialiased.z = sqrt(antialiased.z);&#xD;&#xA;&#xD;&#xA;			int nu, nv; //vec2 off = 1.0 / iResolution.xy;&#xD;&#xA;			nu = u+1; nv = v; // vec3 in1 = texture(iChannel0, uv + vec2(+off.x, 0.0)).xyz;&#xD;&#xA;			in[1] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u-1; nv = v; // vec3 in2 = texture(iChannel0, uv + vec2(-off.x, 0.0)).xyz;&#xD;&#xA;			in[2] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u; nv = v+1; // vec3 in3 = texture(iChannel0, uv + vec2(0.0, +off.y)).xyz;&#xD;&#xA;			in[3] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u; nv = v-1; // vec3 in4 = texture(iChannel0, uv + vec2(0.0, -off.y)).xyz;&#xD;&#xA;			in[4] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u+1; nv = v+1; // vec3 in5 = texture(iChannel0, uv + vec2(+off.x, +off.y)).xyz;&#xD;&#xA;			in[5] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u-1; nv = v+1; // vec3 in6 = texture(iChannel0, uv + vec2(-off.x, +off.y)).xyz;&#xD;&#xA;			in[6] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u+1; nv = v-1; // vec3 in7 = texture(iChannel0, uv + vec2(+off.x, -off.y)).xyz;&#xD;&#xA;			in[7] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;			nu = u-1; nv = v-1; // vec3 in8 = texture(iChannel0, uv + vec2(-off.x, -off.y)).xyz;&#xD;&#xA;			in[8] = ((color3){buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch], buffer[(nu&lt;&lt;2) + nv*pitch]});&#xD;&#xA;&#xD;&#xA;			antialiased = encodePalYuv(v3toc3(antialiased));&#xD;&#xA;			     in0 = encodePalYuv(in[0]);&#xD;&#xA;			vec3 in1 = encodePalYuv(in[1]);&#xD;&#xA;			vec3 in2 = encodePalYuv(in[2]);&#xD;&#xA;			vec3 in3 = encodePalYuv(in[3]);&#xD;&#xA;			vec3 in4 = encodePalYuv(in[4]);&#xD;&#xA;			vec3 in5 = encodePalYuv(in[5]);&#xD;&#xA;			vec3 in6 = encodePalYuv(in[6]);&#xD;&#xA;			vec3 in7 = encodePalYuv(in[7]);&#xD;&#xA;			vec3 in8 = encodePalYuv(in[8]);&#xD;&#xA;			&#xD;&#xA;			vec3 minColor;&#xD;&#xA;			minColor.x = fminf(fminf(fminf(in0.x, in1.x), fminf(in2.x, in3.x)), in4.x);&#xD;&#xA;			minColor.y = fminf(fminf(fminf(in0.y, in1.y), fminf(in2.y, in3.y)), in4.y);&#xD;&#xA;			minColor.z = fminf(fminf(fminf(in0.z, in1.z), fminf(in2.z, in3.z)), in4.z);&#xD;&#xA;&#xD;&#xA;			vec3 maxColor;&#xD;&#xA;			maxColor.x = fmaxf(fmaxf(fmaxf(in0.x, in1.x), fmaxf(in2.x, in3.x)), in4.x);&#xD;&#xA;			maxColor.y = fmaxf(fmaxf(fmaxf(in0.y, in1.y), fmaxf(in2.y, in3.y)), in4.y);&#xD;&#xA;			maxColor.z = fmaxf(fmaxf(fmaxf(in0.z, in1.z), fmaxf(in2.z, in3.z)), in4.z);&#xD;&#xA;&#xD;&#xA;			vec3 lerpto1;&#xD;&#xA;			lerpto1.x = fminf(fminf(fminf(in5.x, in6.x), fminf(in7.x, in8.x)), minColor.x);&#xD;&#xA;			lerpto1.y = fminf(fminf(fminf(in5.y, in6.y), fminf(in7.y, in8.y)), minColor.y);&#xD;&#xA;			lerpto1.z = fminf(fminf(fminf(in5.z, in6.z), fminf(in7.z, in8.z)), minColor.z);&#xD;&#xA;&#xD;&#xA;			minColor = lerp3(minColor, lerpto1, 0.5);&#xD;&#xA;&#xD;&#xA;			vec3 lerpto2;&#xD;&#xA;			lerpto2.x = fmaxf(fmaxf(fmaxf(in5.x, in6.x), fmaxf(in7.x, in8.x)), maxColor.x);&#xD;&#xA;			lerpto2.y = fmaxf(fmaxf(fmaxf(in5.y, in6.y), fmaxf(in7.y, in8.y)), maxColor.y);&#xD;&#xA;			lerpto2.z = fmaxf(fmaxf(fmaxf(in5.z, in6.z), fmaxf(in7.z, in8.z)), maxColor.z);&#xD;&#xA;&#xD;&#xA;			maxColor = lerp3(maxColor, lerpto2, 0.5);&#xD;&#xA;			&#xD;&#xA;			vec3 preclamping = antialiased;&#xD;&#xA;			antialiased.x = clampf(antialiased.x, minColor.x, maxColor.x);&#xD;&#xA;			antialiased.y = clampf(antialiased.y, minColor.y, maxColor.y);&#xD;&#xA;			antialiased.z = clampf(antialiased.z, minColor.z, maxColor.z);&#xD;&#xA;&#xD;&#xA;			mixRate = 1.f / (1.f / mixRate + 1.f);&#xD;&#xA;			&#xD;&#xA;			vec3 diff = sub3(antialiased, preclamping);&#xD;&#xA;			float clampAmount = dot3(diff, diff);&#xD;&#xA;			&#xD;&#xA;			mixRate += clampAmount * 4.f;&#xD;&#xA;			mixRate = clampf(mixRate, 0.05f, 0.5f);&#xD;&#xA;			&#xD;&#xA;			antialiased = decodePalYuv(antialiased);&#xD;&#xA;				&#xD;&#xA;			//fragColor = vec4(antialiased, mixRate);&#xD;&#xA;			color3 fragColor = v3toc3(scale3(antialiased, mixRate));&#xD;&#xA;			aabuffer[index  ] = fragColor.r;&#xD;&#xA;			aabuffer[index+1] = fragColor.g;&#xD;&#xA;			aabuffer[index+2] = fragColor.b;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FSfg8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25459" PostHistoryTypeId="1" PostId="9305" RevisionGUID="41e86d61-8029-41d2-aa7a-67739297272e" CreationDate="2019-11-05T21:03:35.317" UserId="10615" Text="Temporal anti-alliasing breaks the entire image" ContentLicense="CC BY-SA 4.0" />
  <row Id="25460" PostHistoryTypeId="3" PostId="9305" RevisionGUID="41e86d61-8029-41d2-aa7a-67739297272e" CreationDate="2019-11-05T21:03:35.317" UserId="10615" Text="|raytracing|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25461" PostHistoryTypeId="2" PostId="9306" RevisionGUID="3225d314-3b87-4078-95e5-1ad7b277057b" CreationDate="2019-11-06T03:53:59.523" UserId="2654" Text="Let's suggest an analogy. I have a distance of 1 centimeter and 2.54 centimeters. If I transform the latter distance to inches, then it's 1 inch. This has the same value as the first distance.&#xD;&#xA;&#xD;&#xA;But 1 inch is still longer than 1 centimeter, no matter the fact that they both use the numeral 1. These numbers are attached to *different units*, so simply comparing their numerical values is meaningless.&#xD;&#xA;&#xD;&#xA;So it doesn't matter if the 8-bit unsigned, normalized value of 255 happens to have the same value of 1. Because you cannot compare them when they are in different spaces like that. Your original values were both in 8-bit normalized, unsigned integer space. If you want to compare them in a floating-point space, you have to transform *both* of them." ContentLicense="CC BY-SA 4.0" />
  <row Id="25462" PostHistoryTypeId="2" PostId="9307" RevisionGUID="8d29cb5a-1942-458e-88ac-0d1ba5407e7e" CreationDate="2019-11-06T07:41:22.127" UserId="11316" Text="It's the algorithm which combines path tracing and reinforcement learning. I can't understand what $p_\omega$ is. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PWbSf.png&#xD;&#xA;&#xD;&#xA;The algorithm is clear. The actions are the directions and the states are the hit points. For updating the Q-values, the hit points are considered as parts of a discretized diagram like Voronoi diagram and the directions of rays are generated by a discretization of a hemisphere surface which divides it into equal areas. The Q-values are initialized as equal for each state. &#xD;&#xA;&#xD;&#xA;First, we generate a camera ray, and when it hits a diffuse surface, it scatters according to a discrete PDF which is calculated by normalizing the Q-values of the state of hit point. &#xD;&#xA;&#xD;&#xA;Second, The Q-values are updated along the path, we have the state $s$ and the next state $s\prime$ is generated from the direction generated by PDF of Q-values in $s$. &#xD;&#xA;&#xD;&#xA;The area of each path on the hemispheres is $2\pi/n$, and integral in the update equation of Q-values is calculated like this:&#xD;&#xA;&#xD;&#xA;$\dfrac{2\pi}{n}\sum_{k=0}^{n-1}Q_k(y)f_s(\omega_k, y, -\omega)cos\theta_k$&#xD;&#xA;&#xD;&#xA;I understand all of the algorithm, but I don't know what $p_\omega$ is in the second part. Is it $1/2\pi$ or $n/2\pi$ ? Could someone prove what it really is? I need the proof. &#xD;&#xA;&#xD;&#xA;I guess it is $1/2\pi$ because the path tracer here only use the PDF generated by Q-values. It doesn't use the Q-values at all. Am I correct? If I am correct, how can I prove it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25463" PostHistoryTypeId="1" PostId="9307" RevisionGUID="8d29cb5a-1942-458e-88ac-0d1ba5407e7e" CreationDate="2019-11-06T07:41:22.127" UserId="11316" Text="What is the PDF for path tracing in the paper &quot;Learning the light transport the reinforced way&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25464" PostHistoryTypeId="3" PostId="9307" RevisionGUID="8d29cb5a-1942-458e-88ac-0d1ba5407e7e" CreationDate="2019-11-06T07:41:22.127" UserId="11316" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25465" PostHistoryTypeId="5" PostId="9307" RevisionGUID="a34d793e-d209-4548-9bb7-dafe415c850a" CreationDate="2019-11-06T08:02:03.243" UserId="11316" Comment="added 112 characters in body" Text="It's the algorithm which combines path tracing and reinforcement learning. I can't understand what $p_\omega$ is. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PWbSf.png&#xD;&#xA;&#xD;&#xA;The algorithm is clear. The actions are the directions and the states are the hit points. For updating the Q-values, the hit points are considered as parts of a discretized diagram like Voronoi diagram and the directions of rays are generated by a discretization of a hemisphere surface which divides it into equal areas. The Q-values are initialized as equal for each state. &#xD;&#xA;&#xD;&#xA;First, we generate a camera ray, and when it hits a diffuse surface, it scatters according to a discrete PDF which is calculated by normalizing the Q-values of the state of hit point. &#xD;&#xA;&#xD;&#xA;Second, The Q-values are updated along the path, we have the state $s$ and the next state $s\prime$ is generated from the direction generated by PDF of Q-values in $s$. &#xD;&#xA;&#xD;&#xA;The area of each path on the hemispheres is $2\pi/n$, and integral in the update equation of Q-values is calculated like this:&#xD;&#xA;&#xD;&#xA;$\dfrac{2\pi}{n}\sum_{k=0}^{n-1}Q_k(y)f_s(\omega_k, y, -\omega)cos\theta_k$&#xD;&#xA;&#xD;&#xA;I understand all of the algorithm, but I don't know what $p_\omega$ is in the second part. Is it $1/2\pi$ or $n/2\pi$ ? Could someone prove what it really is? I need the proof. &#xD;&#xA;&#xD;&#xA;I guess it is $1/2\pi$ because the path tracer here only use the PDF generated by Q-values. It doesn't use the Q-values at all. Am I correct? If I am correct, how can I prove it?&#xD;&#xA;&#xD;&#xA;EDIT: For clarification, a ray generated through a patch uniformly and the Q-values are generated as I said. Because we only change the directions so more samples are generated inside the patches which receive more light. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25466" PostHistoryTypeId="5" PostId="9307" RevisionGUID="07119100-62aa-4418-84a0-79632eb2ebf5" CreationDate="2019-11-06T08:10:54.317" UserId="11316" Comment="added 112 characters in body" Text="It's the algorithm which combines path tracing and reinforcement learning. I can't understand what $p_\omega$ is. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PWbSf.png&#xD;&#xA;&#xD;&#xA;The algorithm is clear. The actions are the directions and the states are the hit points. For updating the Q-values, the hit points are considered as parts of a discretized diagram like Voronoi diagram and the directions of rays are generated by a discretization of a hemisphere surface which divides it into equal areas. The Q-values are initialized as equal for each state. &#xD;&#xA;&#xD;&#xA;First, we generate a camera ray, and when it hits a diffuse surface, it scatters according to a discrete PDF which is calculated by normalizing the Q-values of the state of hit point. &#xD;&#xA;&#xD;&#xA;Second, The Q-values are updated along the path, we have the state $s$ and the next state $s\prime$ is generated from the direction generated by PDF of Q-values in $s$. &#xD;&#xA;&#xD;&#xA;The area of each path on the hemispheres is $2\pi/n$, and integral in the update equation of Q-values is calculated like this:&#xD;&#xA;&#xD;&#xA;$\dfrac{2\pi}{n}\sum_{k=0}^{n-1}Q_k(y)f_s(\omega_k, y, -\omega)cos\theta_k$&#xD;&#xA;&#xD;&#xA;I understand all of the algorithm, but I don't know what $p_\omega$ is in the second part. Is it $1/2\pi$ or $n/2\pi$ ? Could someone prove what it really is? I need the proof. &#xD;&#xA;&#xD;&#xA;I guess it is $1/2\pi$ because the path tracer here only use the PDF generated by Q-values. It doesn't use the Q-values at all. Am I correct? If I am correct, how can I prove it?&#xD;&#xA;&#xD;&#xA;EDIT: For clarification, a ray generated through a patch uniformly and the Q-values are generated as I said. Because we only change the directions so more samples are generated inside the patches which receive more light. &#xD;&#xA;&#xD;&#xA;I used $n/2\pi$ , but scene was so dark, so the PDF must be either $1/2\pi$ or a normalized combination of PDF's of patches. If the second is true, what it really is?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25467" PostHistoryTypeId="4" PostId="9307" RevisionGUID="07119100-62aa-4418-84a0-79632eb2ebf5" CreationDate="2019-11-06T08:10:54.317" UserId="11316" Comment="added 112 characters in body" Text="What is the PDF for path tracing in the paper &quot;Learning the light transport the reinforced way" ContentLicense="CC BY-SA 4.0" />
  <row Id="25468" PostHistoryTypeId="5" PostId="9307" RevisionGUID="8ab4468c-5e5f-4dc9-a736-1ea4910f0f9d" CreationDate="2019-11-06T08:16:29.080" UserId="11316" Comment="added 112 characters in body" Text="It's the algorithm which combines path tracing and reinforcement learning. I can't understand what $p_\omega$ is. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PWbSf.png&#xD;&#xA;&#xD;&#xA;The algorithm is clear. The actions are the directions and the states are the hit points. For updating the Q-values, the hit points are considered as parts of a discretized diagram like Voronoi diagram and the directions of rays are generated by a discretization of a hemisphere surface which divides it into equal areas. The Q-values are initialized as equal for each state. &#xD;&#xA;&#xD;&#xA;First, we generate a camera ray, and when it hits a diffuse surface, it scatters according to a discrete PDF which is calculated by normalizing the Q-values of the state of hit point. &#xD;&#xA;&#xD;&#xA;Second, The Q-values are updated along the path, we have the state $s$ and the next state $s\prime$ is generated from the direction generated by PDF of Q-values in $s$. &#xD;&#xA;&#xD;&#xA;The area of each path on the hemispheres is $2\pi/n$, and integral in the update equation of Q-values is calculated like this:&#xD;&#xA;&#xD;&#xA;$\dfrac{2\pi}{n}\sum_{k=0}^{n-1}Q_k(y)f_s(\omega_k, y, -\omega)cos\theta_k$&#xD;&#xA;&#xD;&#xA;I understand all of the algorithm, but I don't know what $p_\omega$ is in the second part. Is it $1/2\pi$ or $n/2\pi$ ? Could someone prove what it really is? I need the proof. &#xD;&#xA;&#xD;&#xA;I guess it is $1/2\pi$ because the path tracer here only use the PDF generated by Q-values. It doesn't use the Q-values at all. Am I correct? If I am correct, how can I prove it?&#xD;&#xA;&#xD;&#xA;EDIT: For clarification, a ray generated through a patch uniformly and the Q-values are generated as I said. Because we only change the directions so more samples are generated inside the patches which receive more light. &#xD;&#xA;&#xD;&#xA;I used $n/2\pi$ , but scene was so dark, so the PDF must be either $1/2\pi$ or a normalized combination of PDF's of patches. If the second is true, what it really is?&#xD;&#xA;&#xD;&#xA;EDIT 2: Should I ask this question in the statistics community of stack exchange?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25469" PostHistoryTypeId="5" PostId="9305" RevisionGUID="5eb449eb-c67d-4e15-bdeb-fea3ce2f449c" CreationDate="2019-11-06T08:17:57.587" UserId="10615" Comment="deleted 93 characters in body" Text="I'm kind of lost here as I'm faced with a graphical bug the origin of which I don't even know. In an attempt to recreate a shadertoy I saw that had TXAA, I made a function TemporalAA that takes in 3 buffers: the current frame `buffer`, the last frame `prevbuffer`, and the frame to which we render the anti aliased image `aabuffer`. &#xD;&#xA;&#xD;&#xA;The original implementation: https://www.shadertoy.com/view/4tcXD2&#xD;&#xA;&#xD;&#xA;The issue is that there's this weird overlay pattern, and I don't notice any edge smoothing whatsoever. Also note the brightly colored bands that the spheres get when in this overlay.&#xD;&#xA;&#xD;&#xA;[![Weird artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;It's completely written in C.&#xD;&#xA;&#xD;&#xA;Note: a frame consists of an `uint8` width*height*3 array. (times three for three color channels. `[0] = red, [1] = green, [2] = blue`). Please ignore the fact that everything is `static inline`.&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;// YUV-RGB conversion routine from Hyper3D&#xD;&#xA;static inline vec3 encodePalYuv(color3 clr)&#xD;&#xA;{&#xD;&#xA;	vec3 rgb = (vec3){ // pow = gamma correction&#xD;&#xA;		pow((float)clr.r/255, 2),&#xD;&#xA;		pow((float)clr.g/255, 2),&#xD;&#xA;		pow((float)clr.b/255, 2)&#xD;&#xA;	};&#xD;&#xA;	return (vec3){&#xD;&#xA;		dot3(rgb, (vec3){0.299f, 0.587f, 0.114f}),&#xD;&#xA;		dot3(rgb, (vec3){-0.14713f, -0.28886f, 0.436f}),&#xD;&#xA;		dot3(rgb, (vec3){0.615f, -0.51499f, -0.10001f})&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static inline vec3 decodePalYuv(vec3 yuv)&#xD;&#xA;{&#xD;&#xA;	return (vec3){ // pow = gamma correction&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, 0.f, 1.13983}), 0.5),&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, -0.39465, -0.58060}), 0.5),&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, 2.03211, 0.f}), 0.5)&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;static inline void TemporalAA(uint8_t * buffer, uint8_t * prevbuffer, uint8_t * aabuffer, int width, int height) // out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;	int pitch = width*3;&#xD;&#xA;&#xD;&#xA;	for (int u = 1; u &lt; width-1; ++u)&#xD;&#xA;	{&#xD;&#xA;		for (int v = 1; v &lt; height-1; ++v) // we cant do the edge/corner pixels. That would be undefined behaviour&#xD;&#xA;		{&#xD;&#xA;			// index is the position in the buffers at which the current pixel resides&#xD;&#xA;			// buffer[index], +1 and +2 for green &amp; blue respectively.&#xD;&#xA;			int index = (u&lt;&lt;2) + v*pitch; // leftshift 2 == multiply 4 but faster&#xD;&#xA;&#xD;&#xA;			vec3 antialiased = c3tov3( (color3){prevbuffer[index], prevbuffer[index+1], prevbuffer[index+2]} );&#xD;&#xA;			// vec4 lastColor = texture(iChannel1, uv);&#xD;&#xA;			float mixRate = 0.5f;//fminf(1/width, 0.5);&#xD;&#xA;			&#xD;&#xA;			//vec3 in0 = texture(iChannel0, uv).xyz;&#xD;&#xA;			color3 in[9];&#xD;&#xA;			in[0] = ( (color3){buffer[index], buffer[index+1], buffer[index+2]} );&#xD;&#xA;			vec3 in0 = c3tov3(in[0]);&#xD;&#xA;&#xD;&#xA;			antialiased = lerp3(compwisemult3(antialiased, antialiased), compwisemult3(in0, in0), mixRate);&#xD;&#xA;			antialiased.x = sqrt(antialiased.x);&#xD;&#xA;			antialiased.y = sqrt(antialiased.y);&#xD;&#xA;			antialiased.z = sqrt(antialiased.z);&#xD;&#xA;			&#xD;&#xA;			// PaulHK:&#xD;&#xA;			// index = (nu + nv*pitch)*3 == (nu&lt;&lt;2) + nv*pitch&#xD;&#xA;			int nu, nv; //vec2 off = 1.0 / iResolution.xy;&#xD;&#xA;			nu = u+1; nv = v; // vec3 in1 = texture(iChannel0, uv + vec2(+off.x, 0.0)).xyz;&#xD;&#xA;			in[1] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u-1; nv = v; // vec3 in2 = texture(iChannel0, uv + vec2(-off.x, 0.0)).xyz;&#xD;&#xA;			in[2] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u; nv = v+1; // vec3 in3 = texture(iChannel0, uv + vec2(0.0, +off.y)).xyz;&#xD;&#xA;			in[3] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u; nv = v-1; // vec3 in4 = texture(iChannel0, uv + vec2(0.0, -off.y)).xyz;&#xD;&#xA;			in[4] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u+1; nv = v+1; // vec3 in5 = texture(iChannel0, uv + vec2(+off.x, +off.y)).xyz;&#xD;&#xA;			in[5] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u-1; nv = v+1; // vec3 in6 = texture(iChannel0, uv + vec2(-off.x, +off.y)).xyz;&#xD;&#xA;			in[6] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u+1; nv = v-1; // vec3 in7 = texture(iChannel0, uv + vec2(+off.x, -off.y)).xyz;&#xD;&#xA;			in[7] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u-1; nv = v-1; // vec3 in8 = texture(iChannel0, uv + vec2(-off.x, -off.y)).xyz;&#xD;&#xA;			in[8] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;&#xD;&#xA;			antialiased = encodePalYuv(v3toc3(antialiased));&#xD;&#xA;			     in0 = encodePalYuv(in[0]);&#xD;&#xA;			vec3 in1 = encodePalYuv(in[1]);&#xD;&#xA;			vec3 in2 = encodePalYuv(in[2]);&#xD;&#xA;			vec3 in3 = encodePalYuv(in[3]);&#xD;&#xA;			vec3 in4 = encodePalYuv(in[4]);&#xD;&#xA;			vec3 in5 = encodePalYuv(in[5]);&#xD;&#xA;			vec3 in6 = encodePalYuv(in[6]);&#xD;&#xA;			vec3 in7 = encodePalYuv(in[7]);&#xD;&#xA;			vec3 in8 = encodePalYuv(in[8]);&#xD;&#xA;			 &#xD;&#xA;			vec3 minColor;&#xD;&#xA;			minColor.x = fminf(fminf(fminf(in0.x, in1.x), fminf(in2.x, in3.x)), in4.x);&#xD;&#xA;			minColor.y = fminf(fminf(fminf(in0.y, in1.y), fminf(in2.y, in3.y)), in4.y);&#xD;&#xA;			minColor.z = fminf(fminf(fminf(in0.z, in1.z), fminf(in2.z, in3.z)), in4.z);&#xD;&#xA;&#xD;&#xA;			vec3 maxColor;&#xD;&#xA;			maxColor.x = fmaxf(fmaxf(fmaxf(in0.x, in1.x), fmaxf(in2.x, in3.x)), in4.x);&#xD;&#xA;			maxColor.y = fmaxf(fmaxf(fmaxf(in0.y, in1.y), fmaxf(in2.y, in3.y)), in4.y);&#xD;&#xA;			maxColor.z = fmaxf(fmaxf(fmaxf(in0.z, in1.z), fmaxf(in2.z, in3.z)), in4.z);&#xD;&#xA;&#xD;&#xA;			vec3 lerpto1;&#xD;&#xA;			lerpto1.x = fminf(fminf(fminf(in5.x, in6.x), fminf(in7.x, in8.x)), minColor.x);&#xD;&#xA;			lerpto1.y = fminf(fminf(fminf(in5.y, in6.y), fminf(in7.y, in8.y)), minColor.y);&#xD;&#xA;			lerpto1.z = fminf(fminf(fminf(in5.z, in6.z), fminf(in7.z, in8.z)), minColor.z);&#xD;&#xA;&#xD;&#xA;			minColor = lerp3(minColor, lerpto1, 0.5);&#xD;&#xA;&#xD;&#xA;			vec3 lerpto2;&#xD;&#xA;			lerpto2.x = fmaxf(fmaxf(fmaxf(in5.x, in6.x), fmaxf(in7.x, in8.x)), maxColor.x);&#xD;&#xA;			lerpto2.y = fmaxf(fmaxf(fmaxf(in5.y, in6.y), fmaxf(in7.y, in8.y)), maxColor.y);&#xD;&#xA;			lerpto2.z = fmaxf(fmaxf(fmaxf(in5.z, in6.z), fmaxf(in7.z, in8.z)), maxColor.z);&#xD;&#xA;&#xD;&#xA;			maxColor = lerp3(maxColor, lerpto2, 0.5);&#xD;&#xA;			&#xD;&#xA;			vec3 preclamping = antialiased;&#xD;&#xA;			antialiased.x = clampf(antialiased.x, minColor.x, maxColor.x);&#xD;&#xA;			antialiased.y = clampf(antialiased.y, minColor.y, maxColor.y);&#xD;&#xA;			antialiased.z = clampf(antialiased.z, minColor.z, maxColor.z);&#xD;&#xA;&#xD;&#xA;			mixRate = 1.f / (1.f / mixRate + 1.f);&#xD;&#xA;			&#xD;&#xA;			vec3 diff = sub3(antialiased, preclamping);&#xD;&#xA;			float clampAmount = dot3(diff, diff);&#xD;&#xA;			&#xD;&#xA;			mixRate += clampAmount * 4.f;&#xD;&#xA;			mixRate = clampf(mixRate, 0.05f, 0.5f);&#xD;&#xA;			&#xD;&#xA;			antialiased = decodePalYuv(antialiased);&#xD;&#xA;				&#xD;&#xA;			//fragColor = vec4(antialiased, mixRate);&#xD;&#xA;			color3 fragColor = v3toc3(scale3(antialiased, mixRate));&#xD;&#xA;			aabuffer[index  ] = fragColor.r;&#xD;&#xA;			aabuffer[index+1] = fragColor.g;&#xD;&#xA;			aabuffer[index+2] = fragColor.b;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FSfg8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25470" PostHistoryTypeId="5" PostId="9305" RevisionGUID="ae38f60d-a733-4ac7-bb89-5f2895ecb437" CreationDate="2019-11-06T08:42:10.317" UserId="10615" Comment="added 145 characters in body" Text="I'm kind of lost here as I'm faced with a graphical bug the origin of which I don't even know. In an attempt to recreate a shadertoy I saw that had TXAA, I made a function TemporalAA that takes in 3 buffers: the current frame `buffer`, the last frame `prevbuffer`, and the frame to which we render the anti aliased image `aabuffer`. &#xD;&#xA;&#xD;&#xA;The original implementation: https://www.shadertoy.com/view/4tcXD2&#xD;&#xA;&#xD;&#xA;The issue is that there's this weird overlay pattern, and I don't notice any edge smoothing whatsoever. Also note the brightly colored bands that the spheres get when in this overlay.&#xD;&#xA;&#xD;&#xA;[![Weird artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;It's completely written in C.&#xD;&#xA;&#xD;&#xA;Note: a frame consists of an `uint8` width*height*3 array. (times three for three color channels. `[0] = red, [1] = green, [2] = blue`). Please ignore the fact that everything is `static inline`.&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;// YUV-RGB conversion routine from Hyper3D&#xD;&#xA;static inline vec3 encodePalYuv(color3 clr)&#xD;&#xA;{&#xD;&#xA;	vec3 rgb = (vec3){ // pow = gamma correction&#xD;&#xA;		pow((float)clr.r/255, 2),&#xD;&#xA;		pow((float)clr.g/255, 2),&#xD;&#xA;		pow((float)clr.b/255, 2)&#xD;&#xA;	};&#xD;&#xA;	return (vec3){&#xD;&#xA;		dot3(rgb, (vec3){0.299f, 0.587f, 0.114f}),&#xD;&#xA;		dot3(rgb, (vec3){-0.14713f, -0.28886f, 0.436f}),&#xD;&#xA;		dot3(rgb, (vec3){0.615f, -0.51499f, -0.10001f})&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static inline vec3 decodePalYuv(vec3 yuv)&#xD;&#xA;{&#xD;&#xA;	return (vec3){ // pow = gamma correction&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, 0.f, 1.13983}), 0.5),&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, -0.39465, -0.58060}), 0.5),&#xD;&#xA;		pow(dot3(yuv, (vec3){1.f, 2.03211, 0.f}), 0.5)&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// component wise multiplication&#xD;&#xA;static inline vec3 compwisemult3(vec3 v, vec3 u){&#xD;&#xA;	return (vec3){&#xD;&#xA;		v.x*u.x,&#xD;&#xA;		v.y*u.y,&#xD;&#xA;		v.z*u.z&#xD;&#xA;	};&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static inline void TemporalAA(uint8_t * buffer, uint8_t * prevbuffer, uint8_t * aabuffer, int width, int height) // out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;	int pitch = width*3;&#xD;&#xA;&#xD;&#xA;	for (int u = 1; u &lt; width-1; ++u)&#xD;&#xA;	{&#xD;&#xA;		for (int v = 1; v &lt; height-1; ++v) // we cant do the edge/corner pixels. That would be undefined behaviour&#xD;&#xA;		{&#xD;&#xA;			// index is the position in the buffers at which the current pixel resides&#xD;&#xA;			// buffer[index], +1 and +2 for green &amp; blue respectively.&#xD;&#xA;			int index = (u&lt;&lt;2) + v*pitch; // leftshift 2 == multiply 4 but faster&#xD;&#xA;&#xD;&#xA;			vec3 antialiased = c3tov3( (color3){prevbuffer[index], prevbuffer[index+1], prevbuffer[index+2]} );&#xD;&#xA;			// vec4 lastColor = texture(iChannel1, uv);&#xD;&#xA;			float mixRate = 0.5f;//fminf(1/width, 0.5);&#xD;&#xA;			&#xD;&#xA;			//vec3 in0 = texture(iChannel0, uv).xyz;&#xD;&#xA;			color3 in[9];&#xD;&#xA;			in[0] = ( (color3){buffer[index], buffer[index+1], buffer[index+2]} );&#xD;&#xA;			vec3 in0 = c3tov3(in[0]);&#xD;&#xA;&#xD;&#xA;			antialiased = lerp3(compwisemult3(antialiased, antialiased), compwisemult3(in0, in0), mixRate);&#xD;&#xA;			antialiased.x = sqrt(antialiased.x);&#xD;&#xA;			antialiased.y = sqrt(antialiased.y);&#xD;&#xA;			antialiased.z = sqrt(antialiased.z);&#xD;&#xA;			&#xD;&#xA;			// PaulHK:&#xD;&#xA;			// index = (nu + nv*pitch)*3 == (nu&lt;&lt;2) + nv*pitch&#xD;&#xA;			int nu, nv; //vec2 off = 1.0 / iResolution.xy;&#xD;&#xA;			nu = u+1; nv = v; // vec3 in1 = texture(iChannel0, uv + vec2(+off.x, 0.0)).xyz;&#xD;&#xA;			in[1] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u-1; nv = v; // vec3 in2 = texture(iChannel0, uv + vec2(-off.x, 0.0)).xyz;&#xD;&#xA;			in[2] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u; nv = v+1; // vec3 in3 = texture(iChannel0, uv + vec2(0.0, +off.y)).xyz;&#xD;&#xA;			in[3] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u; nv = v-1; // vec3 in4 = texture(iChannel0, uv + vec2(0.0, -off.y)).xyz;&#xD;&#xA;			in[4] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u+1; nv = v+1; // vec3 in5 = texture(iChannel0, uv + vec2(+off.x, +off.y)).xyz;&#xD;&#xA;			in[5] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u-1; nv = v+1; // vec3 in6 = texture(iChannel0, uv + vec2(-off.x, +off.y)).xyz;&#xD;&#xA;			in[6] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u+1; nv = v-1; // vec3 in7 = texture(iChannel0, uv + vec2(+off.x, -off.y)).xyz;&#xD;&#xA;			in[7] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;			nu = u-1; nv = v-1; // vec3 in8 = texture(iChannel0, uv + vec2(-off.x, -off.y)).xyz;&#xD;&#xA;			in[8] = ((color3){buffer[(nu + nv*pitch)*3], buffer[(nu + nv*pitch)*3 +1], buffer[(nu + nv*pitch)*3 +2]});&#xD;&#xA;&#xD;&#xA;			antialiased = encodePalYuv(v3toc3(antialiased));&#xD;&#xA;			     in0 = encodePalYuv(in[0]);&#xD;&#xA;			vec3 in1 = encodePalYuv(in[1]);&#xD;&#xA;			vec3 in2 = encodePalYuv(in[2]);&#xD;&#xA;			vec3 in3 = encodePalYuv(in[3]);&#xD;&#xA;			vec3 in4 = encodePalYuv(in[4]);&#xD;&#xA;			vec3 in5 = encodePalYuv(in[5]);&#xD;&#xA;			vec3 in6 = encodePalYuv(in[6]);&#xD;&#xA;			vec3 in7 = encodePalYuv(in[7]);&#xD;&#xA;			vec3 in8 = encodePalYuv(in[8]);&#xD;&#xA;			 &#xD;&#xA;			vec3 minColor;&#xD;&#xA;			minColor.x = fminf(fminf(fminf(in0.x, in1.x), fminf(in2.x, in3.x)), in4.x);&#xD;&#xA;			minColor.y = fminf(fminf(fminf(in0.y, in1.y), fminf(in2.y, in3.y)), in4.y);&#xD;&#xA;			minColor.z = fminf(fminf(fminf(in0.z, in1.z), fminf(in2.z, in3.z)), in4.z);&#xD;&#xA;&#xD;&#xA;			vec3 maxColor;&#xD;&#xA;			maxColor.x = fmaxf(fmaxf(fmaxf(in0.x, in1.x), fmaxf(in2.x, in3.x)), in4.x);&#xD;&#xA;			maxColor.y = fmaxf(fmaxf(fmaxf(in0.y, in1.y), fmaxf(in2.y, in3.y)), in4.y);&#xD;&#xA;			maxColor.z = fmaxf(fmaxf(fmaxf(in0.z, in1.z), fmaxf(in2.z, in3.z)), in4.z);&#xD;&#xA;&#xD;&#xA;			vec3 lerpto1;&#xD;&#xA;			lerpto1.x = fminf(fminf(fminf(in5.x, in6.x), fminf(in7.x, in8.x)), minColor.x);&#xD;&#xA;			lerpto1.y = fminf(fminf(fminf(in5.y, in6.y), fminf(in7.y, in8.y)), minColor.y);&#xD;&#xA;			lerpto1.z = fminf(fminf(fminf(in5.z, in6.z), fminf(in7.z, in8.z)), minColor.z);&#xD;&#xA;&#xD;&#xA;			minColor = lerp3(minColor, lerpto1, 0.5);&#xD;&#xA;&#xD;&#xA;			vec3 lerpto2;&#xD;&#xA;			lerpto2.x = fmaxf(fmaxf(fmaxf(in5.x, in6.x), fmaxf(in7.x, in8.x)), maxColor.x);&#xD;&#xA;			lerpto2.y = fmaxf(fmaxf(fmaxf(in5.y, in6.y), fmaxf(in7.y, in8.y)), maxColor.y);&#xD;&#xA;			lerpto2.z = fmaxf(fmaxf(fmaxf(in5.z, in6.z), fmaxf(in7.z, in8.z)), maxColor.z);&#xD;&#xA;&#xD;&#xA;			maxColor = lerp3(maxColor, lerpto2, 0.5);&#xD;&#xA;			&#xD;&#xA;			vec3 preclamping = antialiased;&#xD;&#xA;			antialiased.x = clampf(antialiased.x, minColor.x, maxColor.x);&#xD;&#xA;			antialiased.y = clampf(antialiased.y, minColor.y, maxColor.y);&#xD;&#xA;			antialiased.z = clampf(antialiased.z, minColor.z, maxColor.z);&#xD;&#xA;&#xD;&#xA;			mixRate = 1.f / (1.f / mixRate + 1.f);&#xD;&#xA;			&#xD;&#xA;			vec3 diff = sub3(antialiased, preclamping);&#xD;&#xA;			float clampAmount = dot3(diff, diff);&#xD;&#xA;			&#xD;&#xA;			mixRate += clampAmount * 4.f;&#xD;&#xA;			mixRate = clampf(mixRate, 0.05f, 0.5f);&#xD;&#xA;			&#xD;&#xA;			antialiased = decodePalYuv(antialiased);&#xD;&#xA;				&#xD;&#xA;			//fragColor = vec4(antialiased, mixRate);&#xD;&#xA;			color3 fragColor = v3toc3(scale3(antialiased, mixRate));&#xD;&#xA;			aabuffer[index  ] = fragColor.r;&#xD;&#xA;			aabuffer[index+1] = fragColor.g;&#xD;&#xA;			aabuffer[index+2] = fragColor.b;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FSfg8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25471" PostHistoryTypeId="2" PostId="9308" RevisionGUID="d34180b4-2ef2-445d-a36b-cd3e49a61c51" CreationDate="2019-11-06T08:53:32.333" UserId="8314" Text="Some thoughts:&#xD;&#xA;&#xD;&#xA;1. Collinear velocity vectors does not mean there is no collision - if v1 != v2 ...&#xD;&#xA;2. In good pool games you can define the 'hit point', where the queue hits the ball. Then &quot;curvy&quot; ball trajectories are generated, etc. etc. &#xD;&#xA;3. Your system should also consider friction, therefore: v-&gt;0 over time. This should also affect your collision calculations." ContentLicense="CC BY-SA 4.0" />
  <row Id="25472" PostHistoryTypeId="5" PostId="9308" RevisionGUID="03665b5e-5ab0-4417-99d2-b18c93bc7a61" CreationDate="2019-11-06T08:59:46.680" UserId="8314" Comment="deleted 2 characters in body" Text="Some thoughts:&#xD;&#xA;&#xD;&#xA;1. Collinear velocity vectors do not mean there is no collision - if v1 != v2 ...&#xD;&#xA;2. In good pool games you can define the 'hit point', where the queue hits the ball. Then &quot;curvy&quot; ball trajectories are generated, etc. etc. &#xD;&#xA;3. Your system should also consider friction, therefore: v-&gt;0 over time. This should also affect your collision calculations." ContentLicense="CC BY-SA 4.0" />
  <row Id="25473" PostHistoryTypeId="5" PostId="9308" RevisionGUID="1d380c96-e8d2-4630-bf4d-cedab36bf762" CreationDate="2019-11-06T09:11:13.557" UserId="8314" Comment="added 261 characters in body" Text="I think you should determine the &quot;next collision point&quot; in your whole 16-ball-and-table-border system and adjust your simulation 'Delta t&quot; depending on it. Rendering should be de-coupled from this anyway, or it will show irregular ball movements... .&#xD;&#xA;&#xD;&#xA;Some further thoughts:&#xD;&#xA;&#xD;&#xA;1. Collinear velocity vectors do not mean there is no collision - if v1 != v2 ...&#xD;&#xA;2. In good pool games you can define the 'hit point', where the queue hits the ball. Then &quot;curvy&quot; ball trajectories are generated, etc. etc. &#xD;&#xA;3. Your system should also consider friction, therefore: v-&gt;0 over time. This should also affect your collision calculations." ContentLicense="CC BY-SA 4.0" />
  <row Id="25474" PostHistoryTypeId="2" PostId="9309" RevisionGUID="8657fb04-6b26-4570-b7b9-b1ec9ab66883" CreationDate="2019-11-06T14:59:45.760" UserId="209" Text="Rather than fit bilinear patches to your sample points, which are only C0 continuous$^\spadesuit$ may I instead suggest fitting the surface using Catmull-Rom splines, which will give you C2 continuity? &#xD;&#xA;Catmull-Rom is an interpolating spline which means it will pass through your sample points as did the bilinear surface, but will do so smoothly.&#xD;&#xA;&#xD;&#xA;$^\spadesuit$ *because the first derivatives won't generally match at the boundaries of your patches* &#xD;&#xA;&#xD;&#xA;To form a bicubic Catmull-Rom patch which has a given 2x2 set of samples $\{S_{i,j},  S_{i+1,j}, S_{i,j+1},  S_{i+1,j+1}\}$ at the corners, you need a set of 4x4 samples formed from the 2x2 at the centre and the surrounding 12 samples, i.e.$\{S_{i-1,j-1}$ *through* $S_{i+2,j+2}\}$,  as shown below.&#xD;&#xA;(My apologies that this is 'hand placed' so is far from ideal)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we just consider the sample, $S_{i,j}$, then the partial derivative in the 'i' direction is given by &#xD;&#xA;$$\frac{S_{i+1,j}-S_{i-1,j}}{2}$$&#xD;&#xA;and similarly, in the 'j' direction by&#xD;&#xA;$$\frac{S_{i,j+1}-S_{i,j-1}}{2}$$&#xD;&#xA;&#xD;&#xA;Remembering these are vectors, you can use the cross product to generate a surface normal at any of the $S_{i,j}$ points. (Though you may need an extra set of boundary samples)&#xD;&#xA;&#xD;&#xA;If you've sampled the surface 'finely' enough you could probably choose to render the surface by just using 2 or 4 triangles per original patch. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, you can recursively subdivide your quad mesh to get a finer set of triangles. To double the number of points in the 'i' direction, simply insert a new point between each $S_{i,j}$ and $S_{i+1,j}$ that equals ...&#xD;&#xA;$$\frac{9(S_{i,j}+S_{i+1,j}) - (S_{i-1,j}+S_{i+2,j})}{16}$$&#xD;&#xA; Once you have the finer grid in 'i' simply repeat with 'j' with the appropriate equivalent set of points. You can repeat this ad nauseam to get whatever triangle resolution you desire ;-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M48A3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25475" PostHistoryTypeId="2" PostId="9310" RevisionGUID="0b8a48bb-7d19-487c-8ac7-c190fb717dd4" CreationDate="2019-11-06T17:35:34.677" UserId="11316" Text="I have to answer my question. &#xD;&#xA;Consider that all patches have the same value. Then choosing a patch uniformly and selecting a random point uniformly on that patch is as the same as sampling the hemisphere uniformly. If $p_s=Pr(Q_k \in Q)=1/n$, which n is the number of patches, I can conclude that $p_\omega=p_s*(n/2\pi)=1/2\pi$ .&#xD;&#xA;&#xD;&#xA;And if patches don't have the same value, then $p_s=Pr(Q_k \in Q)=q_k/(q_1+...+q_n)$ and &#xD;&#xA;$p_\omega=p_s*(n/2\pi)=(q_k/(q_1+...+q_n))*(n/2\pi)$" ContentLicense="CC BY-SA 4.0" />
  <row Id="25476" PostHistoryTypeId="2" PostId="9311" RevisionGUID="94b96430-34a1-4ecb-89fc-5a299f44de75" CreationDate="2019-11-06T19:32:41.820" UserId="11316" Text="I've implemented the algorithm in the paper &quot;Learning the light transport the reinforced way&quot;. What is the name of this effect and how should solve it?  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P95BI.png&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25477" PostHistoryTypeId="1" PostId="9311" RevisionGUID="94b96430-34a1-4ecb-89fc-5a299f44de75" CreationDate="2019-11-06T19:32:41.820" UserId="11316" Text="What is the name of this effect and how could I solve it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25478" PostHistoryTypeId="3" PostId="9311" RevisionGUID="94b96430-34a1-4ecb-89fc-5a299f44de75" CreationDate="2019-11-06T19:32:41.820" UserId="11316" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25479" PostHistoryTypeId="5" PostId="9311" RevisionGUID="cb7b5af4-e0b6-4676-b2c1-56c2cdb46a20" CreationDate="2019-11-06T20:54:46.557" UserId="11316" Comment="added 2 characters in body" Text="I've implemented the algorithm in the paper &quot;Learning the light transport the reinforced way&quot;. What is the name of this effect and how should I solve it?  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/P95BI.png&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25480" PostHistoryTypeId="2" PostId="9312" RevisionGUID="248d159b-41bb-4ff2-be51-addb0b505e56" CreationDate="2019-11-07T02:18:21.480" UserId="10715" Text="We are implementing a &quot;lazy container&quot; that caches renders of an object at various cutoffs and scales up/down the render-textures from those caches instead of drawing the actual object directly. This is done primarily is reduce the computational overhead of applying (multiple) shader filters.&#xD;&#xA;&#xD;&#xA;Our renderer also implements a grid, which kicks in a high levels of zoom. If we render a downloaded image, then on zooming in we would find that each grid box contains only one color, e.g. it is one pixel in the image. This also applies if we apply any shader filter.&#xD;&#xA;&#xD;&#xA;However, if we enable our &quot;lazy&quot; container, then we find that the grid box contain more than one color. Each texture pixel is not aligned with the grid's lines, sometimes even being smaller than one grid box.&#xD;&#xA;&#xD;&#xA;An example of a zoomed in layer blur is given below (applied on a 320x180 image that is cached at 1024x576 on a 1024x1024 render-texture):[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/n3usi.png&#xD;&#xA;&#xD;&#xA;Is there an explanation for why this is happening?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25481" PostHistoryTypeId="1" PostId="9312" RevisionGUID="248d159b-41bb-4ff2-be51-addb0b505e56" CreationDate="2019-11-07T02:18:21.480" UserId="10715" Text="Irregular subpixel behaviour using cached render textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="25482" PostHistoryTypeId="3" PostId="9312" RevisionGUID="248d159b-41bb-4ff2-be51-addb0b505e56" CreationDate="2019-11-07T02:18:21.480" UserId="10715" Text="|deferred-rendering|subpixel-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25483" PostHistoryTypeId="5" PostId="9309" RevisionGUID="e2f5d462-720f-4694-9842-f56a34e6ce2c" CreationDate="2019-11-07T11:03:35.207" UserId="209" Comment="Responded to comment" Text="Rather than fit bilinear patches to your sample points, which are only C0 continuous$^\spadesuit$ may I instead suggest fitting the surface using Catmull-Rom splines? These will give you C2 continuity. &#xD;&#xA;Catmull-Rom is an interpolating spline which means it will pass through your sample points, as did the bilinear surface, but will do so smoothly from patch to patch.&#xD;&#xA;&#xD;&#xA;$^\spadesuit$ *because the first derivatives won't generally match at the boundaries of your patches* &#xD;&#xA;&#xD;&#xA;To form eachbicubic Catmull-Rom patch, $C$, which has a given 2x2 set of samples $\{S_{i,j},  S_{i+1,j}, S_{i,j+1},  S_{i+1,j+1}\}$ at the corners, you need a set of 4x4 samples formed from the 2x2 at the centre and the surrounding 12 samples, i.e.$\{S_{i-1,j-1}$ *through* $S_{i+2,j+2}\}$,  as shown below.&#xD;&#xA;(My apologies that this is 'hand placed' so is far from ideal)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we just consider the sample, $S_{i,j}$, then the partial derivative in the 'i' direction is given by &#xD;&#xA;$$\frac{\partial C}{\partial i}=\frac{S_{i+1,j}-S_{i-1,j}}{2}$$&#xD;&#xA;and similarly, in the 'j' direction by&#xD;&#xA;$$\frac{\partial C}{\partial j}=\frac{S_{i,j+1}-S_{i,j-1}}{2}$$&#xD;&#xA;&#xD;&#xA;Remembering these are vectors, you can use the cross product to generate a surface normal at any of the $S_{i,j}$ points. (Though you may need an extra set of boundary samples)&#xD;&#xA;&#xD;&#xA;&gt;*Ali: You mentioned that both partial derivatives are vectors(in i,j directions). could you write each vector components plz*&#xD;&#xA;&#xD;&#xA;Certainly: If we say $S_{i,j}=[x_{i,j},y_{i,j},z_{i,j}]^T$ then $$\frac{\partial C}{\partial i}=\frac{1}{2}.[(x_{i+1,j}-x_{i-1,j}),(y_{i+1,j}-y_{i-1,j}),(z_{i+1,j}-z_{i-1,j})]^T$$&#xD;&#xA;$$\frac{\partial C}{\partial j}=\frac{1}{2}.[(x_{i,j+1}-x_{i,j-1}),(y_{i,j+1}-y_{i,j-1}),(z_{i,j+1}-z_{i,j-1})]^T$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;br\&gt;If you've sampled the surface 'finely' enough you could probably choose to render the surface by just using 2 or 4 triangles per original patch. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, you can recursively subdivide your quad mesh to get a finer set of triangles. To double the number of points in the 'i' direction, simply insert a new point between each $S_{i,j}$ and $S_{i+1,j}$ that equals ...&#xD;&#xA;$$\frac{9(S_{i,j}+S_{i+1,j}) - (S_{i-1,j}+S_{i+2,j})}{16}$$&#xD;&#xA; Once you have the finer grid in 'i' simply repeat with 'j' with the appropriate equivalent set of points. You can repeat this ad nauseam to get whatever triangle resolution you desire ;-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M48A3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25484" PostHistoryTypeId="2" PostId="9313" RevisionGUID="3cbfc6ca-5888-4ad5-9a8d-29b555e3759f" CreationDate="2019-11-07T11:34:11.497" UserId="11431" Text="My goal in my project is to render a procedural texture for a given mesh based on a predefined camera projection.&#xD;&#xA;The way I choose to accomplish it is by creating tex coords based on only the visible triangles for a given projection.&#xD;&#xA;&#xD;&#xA;Its important to note that the mesh is unindexed and each vertex is unique to each triangle.&#xD;&#xA;After calculating the UV I pass the tex coords, vertices, MVP matrix to a shader program.&#xD;&#xA;&#xD;&#xA;In the vertex shader I define the gl_position as the generated tex coords so in the end of the pass i will get a texture that is defined by the tex coords.&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec3 aPos;&#xD;&#xA;    layout(location = 1) in vec2 aTexCoord;&#xD;&#xA;    &#xD;&#xA;    out VS_OUT {&#xD;&#xA;    vec4 projector;&#xD;&#xA;    vec2 uv;&#xD;&#xA;    vec2 old_uv;&#xD;&#xA;    } vs_out;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    gl_Position = vec4(aTexCoord*2.0f - 1.0f, 0.0f, 1.0f);&#xD;&#xA;    vs_out.projector = vec4(aPos, 1.0f);&#xD;&#xA;    vs_out.uv = aTexCoord;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;*AN example of the output of the vertex shader*&#xD;&#xA;&#xD;&#xA;Then in the fragment shader, I color the mesh with a simple red color (in the future I hope to project images instead of the red color) :&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    in VS_OUT{&#xD;&#xA;    vec4 projector;&#xD;&#xA;    vec2 uv;&#xD;&#xA;    } vs_out;&#xD;&#xA;    uniform sampler2D shadowMap;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 projProj;&#xD;&#xA;    uniform mat4 projBias;&#xD;&#xA;    uniform mat4 projView;&#xD;&#xA;    float ShadowCalc(vec4 proj)&#xD;&#xA;    {&#xD;&#xA;    float closestDepth = texture2DProj(shadowMap, proj).r;&#xD;&#xA;    float currentDepth = proj.z / proj.w;&#xD;&#xA;    float shadow = currentDepth - 0.00005 &gt; closestDepth ? 0.0 : 1.0;&#xD;&#xA;    return shadow;&#xD;&#xA;    }&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    vec4 ndcProj = (projBias * projProj * projView * model * vs_out.projector);&#xD;&#xA;    vec2 projUV = (ndcProj.xy / ndcProj.w);&#xD;&#xA;    float fDepth = ndcProj.z / ndcProj.w;&#xD;&#xA;    vec4 col = vec4(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    if (0.0 &lt; projUV.x &amp;&amp; projUV.x &lt; 1.0 &amp;&amp; 0.0 &lt; projUV.y &amp;&amp; projUV.y &lt; 1.0 &amp;&amp; ndcProj.w &gt; 0.0 &amp;&amp; ShadowCalc(ndcProj) &gt; 0.5)&#xD;&#xA;    {&#xD;&#xA;    col = vec4(1.0,0.0,0.0,1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    FragColor = col;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;*The result after the fragment shader (the texture is cleared with a green color before)*&#xD;&#xA;&#xD;&#xA;I then display the mesh with the texture using the same tex coords with the following program:&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    layout(location = 0) in vec3 aPos;&#xD;&#xA;    layout(location = 1) in vec2 aTexCoord;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 projProj;&#xD;&#xA;    uniform mat4 projView;&#xD;&#xA;    out vec2 texCoordOut;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    gl_Position = projProj * projView * model * vec4(aPos, 1.0f);&#xD;&#xA;    texCoordOut = aTexCoord;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 450&#xD;&#xA;    in vec2 texCoordOut;&#xD;&#xA;    out vec4 out_color;&#xD;&#xA;    uniform sampler2D unwarp_image;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    vec4 color = texture(unwarp_image, texCoordOut.st);&#xD;&#xA;    out_color = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;*The mesh rendered with the texture on screen*&#xD;&#xA;&#xD;&#xA;As you can see, the mesh has these strange wireframe artifacts.&#xD;&#xA;I've thought of several solutions such as enabling conservative conservative rasterization but none seem to work.&#xD;&#xA;Any ideas on how to get a clean rendering of the mesh with the procedural texture?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bEBrC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/x1L8S.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/iwqrj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25485" PostHistoryTypeId="1" PostId="9313" RevisionGUID="3cbfc6ca-5888-4ad5-9a8d-29b555e3759f" CreationDate="2019-11-07T11:34:11.497" UserId="11431" Text="Help with wireframe artifacts on mesh procedural UV texturing" ContentLicense="CC BY-SA 4.0" />
  <row Id="25486" PostHistoryTypeId="3" PostId="9313" RevisionGUID="3cbfc6ca-5888-4ad5-9a8d-29b555e3759f" CreationDate="2019-11-07T11:34:11.497" UserId="11431" Text="|opengl|glsl|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25487" PostHistoryTypeId="2" PostId="9314" RevisionGUID="327d3bf7-1410-444d-94c3-464d50d08b99" CreationDate="2019-11-07T11:59:33.417" UserId="3073" Text="This looks like a side effect of bilinear filtering where it can sample texels neighbouring those that are in the used areas texture map - the red/green boundary in your case.&#xD;&#xA;&#xD;&#xA;One solution for this is to perform a &quot;colour bleed&quot; pass on the texture where for every 'empty'(Green) texel with none-empty (Red) neighbours you can output the average of all the none-empty neighbours, so what this will do is add a 1 pixel boundary to the red part of your image that matches its neighbours. &#xD;&#xA;&#xD;&#xA;This is a solution to a similar problem seen with alpha blended textures with sharp edges where colour bleeding can sometimes appear at the boundaries between semi-transparent and completely transparent pixels when magnifying the image with bilinear filtering." ContentLicense="CC BY-SA 4.0" />
  <row Id="25488" PostHistoryTypeId="5" PostId="9314" RevisionGUID="9dcba7bb-eb17-4077-b407-35d0698575b9" CreationDate="2019-11-07T12:05:13.237" UserId="3073" Comment="added 16 characters in body" Text="This looks like a side effect of bilinear filtering where it can sample texels neighbouring those that are at the edges of the used areas of the texture - the red/green boundary in your case.&#xD;&#xA;&#xD;&#xA;One solution for this is to perform a &quot;colour bleed&quot; pass on the texture where for every 'empty'(Green) texel with none-empty (Red) neighbours you can output the average of all the none-empty neighbours, so what this will do is add a 1 pixel boundary to the red part of your image that matches its neighbours (In this case the average should be red) &#xD;&#xA;&#xD;&#xA;This is a solution to a similar problem seen with alpha blended textures with sharp edges where colour bleeding can sometimes appear at the boundaries between semi-transparent and completely transparent pixels when magnifying the image. Most modern art packages will automatically colour bleed the RGB channels when saving RGBA images for this reason." ContentLicense="CC BY-SA 4.0" />
  <row Id="25489" PostHistoryTypeId="2" PostId="9315" RevisionGUID="9f65e7f0-0068-4e84-9ed3-7eb0fe55009c" CreationDate="2019-11-07T12:32:01.630" UserId="209" Text="Having read Paulhk's answer, it occurred to me that a possible alternative to the 'bleed', based on premultiplied alpha, would be to initialise your unfilled area to *transparent black* rather than opaque green. &#xD;&#xA;&#xD;&#xA;When you then perform the bilinear filtering, if the returned alpha is non-zero (*not sure if this test is necessary or not as I can't remember the specifics of the shader rcp() function*), multiply the returned filtered (premultiplied) RGB components by the reciprocal of the alpha component to get back a more appropriate colour.&#xD;&#xA;&#xD;&#xA;I would hope the alpha is non-zero, but there may be inaccuracies in the pipeline so you might need to special case it. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25490" PostHistoryTypeId="5" PostId="9315" RevisionGUID="e03980ab-4501-48a4-8a2f-01a544442806" CreationDate="2019-11-07T14:06:32.293" UserId="209" Comment="edited body" Text="Having read PaulHK's answer, it occurred to me that a possible alternative to the 'bleed', based on premultiplied alpha, would be to initialise your unfilled area to *transparent black* rather than opaque green. &#xD;&#xA;&#xD;&#xA;When you then perform the bilinear filtering, if the returned alpha is non-zero (*not sure if this test is necessary or not as I can't remember the specifics of the shader rcp() function*), multiply the returned, filtered (premultiplied) RGB components by the reciprocal of the alpha to get back the appropriate colour.&#xD;&#xA;&#xD;&#xA;One would hope the alpha is always non-zero, ie. you never sample outside of regions of interest, but there may be inaccuracies in the pipeline so you might need to special case it. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25491" PostHistoryTypeId="2" PostId="9316" RevisionGUID="ea0c9967-3c1c-4ff3-8165-793142348fe9" CreationDate="2019-11-07T20:09:04.200" UserId="10615" Text="I want to start developing a hybrid renderer: it first applies a rasterizer, then stores for each pixel the surface pointer, normal vector, and distance to the camera.&#xD;&#xA;&#xD;&#xA;Then it raytraces reflections, refractions, lambertian diffuse, etc using those values.&#xD;&#xA;&#xD;&#xA;The first problem however is rasterizing a sphere: while there are many tutorials for rasterizing quads and triangles, there aren't any on spheres, and I don't know how to do this myself while keeping perspective intact.&#xD;&#xA;&#xD;&#xA;So how do you perfectly rasterize an explicit sphere (with radius, center)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25492" PostHistoryTypeId="1" PostId="9316" RevisionGUID="ea0c9967-3c1c-4ff3-8165-793142348fe9" CreationDate="2019-11-07T20:09:04.200" UserId="10615" Text="Rasterizing spheres?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25493" PostHistoryTypeId="3" PostId="9316" RevisionGUID="ea0c9967-3c1c-4ff3-8165-793142348fe9" CreationDate="2019-11-07T20:09:04.200" UserId="10615" Text="|perspective|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25494" PostHistoryTypeId="2" PostId="9317" RevisionGUID="871ab4e3-9e81-4690-a655-8884de8ee5e2" CreationDate="2019-11-07T22:59:50.700" UserId="11436" Text="everyone!&#xD;&#xA;&#xD;&#xA;I am programing a tessellation shader in OpenGL which computes the [quartic Walton-Meek's Gregory patch][1]. I am searching for a local G1 method with good shading/visual results. So I am trying this patch. I didn't get good (visual/shading) results with PN-Triangles.&#xD;&#xA;&#xD;&#xA;I've just had my first result with this WM patch, which isn't good as well. Perhaps the normal I am calculating is wrong. I am following these equations to compute it:&#xD;&#xA;&#xD;&#xA;[![Bernstein Triangle][2]][2]&#xD;&#xA;[![Bernstein Polynomial][3]][3]&#xD;&#xA;[![Bernstein Derivatives][4]][4]&#xD;&#xA;&#xD;&#xA;Then, I actually compute it through normalizing the cross product between the derivatives (last image).&#xD;&#xA;&#xD;&#xA;If you want to take a look at the shader code, here it is (the first one is the tessellation control shader and the second one is the tessellation evaluation shader):&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout (vertices = 3) out;&#xD;&#xA;&#xD;&#xA;in VertOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;} vertOut[];&#xD;&#xA;&#xD;&#xA;out TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	const float kTessLevel = 12.0;&#xD;&#xA;	gl_TessLevelOuter[gl_InvocationID] = kTessLevel;&#xD;&#xA;	gl_TessLevelInner[0] = kTessLevel;&#xD;&#xA;&#xD;&#xA;	vec3 p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz;&#xD;&#xA;	vec3 n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;	const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;	vec3 edge = gl_in[nextInvID].gl_Position.xyz - p0;&#xD;&#xA;	vec3 nNext = vertOut[nextInvID].normal;&#xD;&#xA;	float d = length(edge), a = dot(n, nNext);&#xD;&#xA;	vec3 gama = edge / d;&#xD;&#xA;	float a0 = dot(n, gama), a1 = dot(nNext, gama);&#xD;&#xA;	float ro = 6.0 * (2.0 * a0 + a * a1)/(4.0 - a * a);&#xD;&#xA;	float sigma = 6.0 * (2.0 * a1 + a * a0)/(4.0 - a * a);&#xD;&#xA;&#xD;&#xA;	vec3 v[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		p0,&#xD;&#xA;		p0 + (d / 18.0) * (6.0 * gama - 2.0 * ro * n + sigma * nNext),&#xD;&#xA;		gl_in[nextInvID].gl_Position.xyz - (d / 18.0) * (6.0 * gama + ro * n - 2.0 * sigma * nNext),&#xD;&#xA;		edge = gl_in[nextInvID].gl_Position.xyz&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 w[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		v[1] - v[0],&#xD;&#xA;		v[2] - v[1],&#xD;&#xA;		v[3] - v[2]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 A[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		cross(n, normalize(w[0])),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		cross(nNext, normalize(w[2]))&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	A[1] = normalize(A[0] + A[2]);&#xD;&#xA;&#xD;&#xA;	vec3 l[5] = vec3[5]&#xD;&#xA;	(&#xD;&#xA;		v[0],&#xD;&#xA;		0.25 * (v[0] + 3.0 * v[1]),&#xD;&#xA;		0.25 * (2.0 * v[1] + 2.0 * v[2]),&#xD;&#xA;		0.25 * (3.0 * v[2] + v[3]),&#xD;&#xA;		v[3]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 p1 = tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;	vec3 p2 = tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;	vec3 p3 = tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;	barrier();&#xD;&#xA;&#xD;&#xA;	const int previousInvID = gl_InvocationID &gt; 0 ? gl_InvocationID - 1 : 2;&#xD;&#xA;	vec3 D[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		tescOut[previousInvID].p3 - 0.5 * (p0 + p1),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		tescOut[nextInvID].p1 - 0.5 * (p3 + tescOut[nextInvID].p0)&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	float mi[2] = float[2](dot(D[0], A[0]), dot(D[3], A[2]));&#xD;&#xA;	float lambda[2] = float[2](dot(D[0], w[0])/dot(w[0], w[0]), dot(D[3], w[2])/dot(w[2], w[2]));&#xD;&#xA;&#xD;&#xA;	tescOut[gl_InvocationID].g0 = 0.5 * (l[1] + l[2]) + (2.0/3.0) * (lambda[0] * w[1] + mi[0] * A[1]) + (1.0/3.0) * (lambda[1] * w[0] + mi[1] * A[0]);&#xD;&#xA;	tescOut[gl_InvocationID].g1 = 0.5 * (l[2] + l[3]) + (1.0/3.0) * (lambda[0] * w[2] + mi[1] * A[2]) + (2.0/3.0) * (lambda[1] * w[1] + mi[1] * A[1]);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout(triangles, equal_spacing, ccw) in;&#xD;&#xA;&#xD;&#xA;in TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;out TeseOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;	vec3 viewPosition;&#xD;&#xA;} teseOut;&#xD;&#xA;&#xD;&#xA;uniform mat4 mvp;&#xD;&#xA;uniform mat4 modelView;&#xD;&#xA;uniform mat4 normalMatrix;&#xD;&#xA;uniform bool isNormalLinearlyInterpolated;&#xD;&#xA;&#xD;&#xA;#define uvw     gl_TessCoord&#xD;&#xA;&#xD;&#xA;const float u = uvw.x, u2 = u * u, u3 = u2 * u, u4 = u2 * u2;&#xD;&#xA;const float v = uvw.y, v2 = v * v, v3 = v2 * v, v4 = v2 * v2;&#xD;&#xA;const float w = uvw.z, w2 = w * w, w3 = w2 * w, w4 = w2 * w2;&#xD;&#xA;&#xD;&#xA;#define p400	tescOut[0].p0&#xD;&#xA;#define p310	tescOut[0].p1&#xD;&#xA;#define p220	tescOut[0].p2&#xD;&#xA;#define p130	tescOut[0].p3&#xD;&#xA;#define G01		tescOut[0].g0&#xD;&#xA;#define	G02		tescOut[0].g1&#xD;&#xA;#define p040	tescOut[1].p0&#xD;&#xA;#define p031	tescOut[1].p1&#xD;&#xA;#define p022	tescOut[1].p2&#xD;&#xA;#define p013	tescOut[1].p3&#xD;&#xA;#define G11		tescOut[1].g0&#xD;&#xA;#define	G12		tescOut[1].g1&#xD;&#xA;#define p004	tescOut[2].p0&#xD;&#xA;#define p103	tescOut[2].p1&#xD;&#xA;#define p202	tescOut[2].p2&#xD;&#xA;#define p301	tescOut[2].p3&#xD;&#xA;#define G21		tescOut[2].g0&#xD;&#xA;#define	G22		tescOut[2].g1&#xD;&#xA;&#xD;&#xA;#define B400	u4&#xD;&#xA;#define B040	v4&#xD;&#xA;#define B004	w4&#xD;&#xA;#define B310	(4.0 * u3 * v)&#xD;&#xA;#define B031	(4.0 * v3 * w)&#xD;&#xA;#define B103	(4.0 * u * w3)&#xD;&#xA;#define B220	(6.0 * u2 * v2)&#xD;&#xA;#define B022	(6.0 * v2 * w2)&#xD;&#xA;#define B202	(6.0 * u2 * w2)&#xD;&#xA;#define B130	(4.0 * u * v3)&#xD;&#xA;#define B013	(4.0 * v * w3)&#xD;&#xA;#define B301	(4.0 * u3 * w)&#xD;&#xA;#define B211	(12.0 * u2 * v * w)&#xD;&#xA;#define B121	(12.0 * u * v2 * w)&#xD;&#xA;#define B112	(12.0 * u * v * w2)&#xD;&#xA;&#xD;&#xA;#define B300	u3&#xD;&#xA;#define B030	v3&#xD;&#xA;#define B003	w3&#xD;&#xA;#define B210	(3.0 * u2 * v)&#xD;&#xA;#define B021	(3.0 * v2 * w)&#xD;&#xA;#define B102	(3.0 * w2 * u)&#xD;&#xA;#define B120	(3.0 * u * v2)&#xD;&#xA;#define B012	(3.0 * v * w2)&#xD;&#xA;#define B201	(3.0 * w * u2)&#xD;&#xA;#define B111	(6.0 * u * v * w)&#xD;&#xA;&#xD;&#xA;vec3 interpolate3D(vec3 p0, vec3 p1, vec3 p2)&#xD;&#xA;{&#xD;&#xA;   	return gl_TessCoord.x * p0 + gl_TessCoord.y * p1 + gl_TessCoord.z * p2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	vec4 pos = vec4(interpolate3D(tescOut[0].p0, tescOut[1].p0, tescOut[2].p0), 1.0);&#xD;&#xA;	vec3 normal = normalize(interpolate3D(tescOut[0].n, tescOut[1].n, tescOut[2].n));&#xD;&#xA;&#xD;&#xA;	if (u != 1.0 &amp;&amp; v != 1.0 &amp;&amp; w != 1.0)&#xD;&#xA;	{&#xD;&#xA;		vec3 p211 = (v * G12 + w * G21)/(v + w);&#xD;&#xA;		vec3 p121 = (w * G02 + u * G11)/(w + u);&#xD;&#xA;		vec3 p112 = (u * G22 + v * G01)/(u + v);&#xD;&#xA;&#xD;&#xA;		vec3 barPos =	p400 * B400 +&#xD;&#xA;						p040 * B040 +&#xD;&#xA;						p004 * B004 +&#xD;&#xA;						p310 * B310 +&#xD;&#xA;						p031 * B031 +&#xD;&#xA;						p103 * B103 +&#xD;&#xA;						p220 * B220 +&#xD;&#xA;						p022 * B022 +&#xD;&#xA;						p202 * B202 +&#xD;&#xA;						p130 * B130 +&#xD;&#xA;						p013 * B013 +&#xD;&#xA;						p301 * B301 +&#xD;&#xA;						p211 * B211 +&#xD;&#xA;						p121 * B121 +&#xD;&#xA;						p112 * B112;&#xD;&#xA;&#xD;&#xA;		pos = vec4(barPos, 1.0);&#xD;&#xA;&#xD;&#xA;		vec3 dpdu =	p400 * B300 +&#xD;&#xA;					p130 * B030 +&#xD;&#xA;					p103 * B003 +&#xD;&#xA;					p310 * B210 +&#xD;&#xA;					p121 * B021 +&#xD;&#xA;					p202 * B102 +&#xD;&#xA;					p220 * B120 +&#xD;&#xA;					p112 * B012 +&#xD;&#xA;					p301 * B201 +&#xD;&#xA;					p211 * B111 ;&#xD;&#xA;&#xD;&#xA;		vec3 dpdv =	p310 * B300 +&#xD;&#xA;					p040 * B030 +&#xD;&#xA;					p013 * B003 +&#xD;&#xA;					p220 * B210 +&#xD;&#xA;					p031 * B021 +&#xD;&#xA;					p112 * B102 +&#xD;&#xA;					p130 * B120 +&#xD;&#xA;					p022 * B012 +&#xD;&#xA;					p211 * B201 +&#xD;&#xA;					p121 * B111 ;&#xD;&#xA;&#xD;&#xA;		normal = normalize(cross(dpdu, dpdv));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	gl_Position = mvp * pos;&#xD;&#xA;	pos = modelView * pos;&#xD;&#xA;	teseOut.viewPosition = pos.xyz / pos.w;&#xD;&#xA;&#xD;&#xA;	teseOut.normal = (normalMatrix * vec4(normal, 0.0)).xyz;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Some screenshots from my current results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;In the &quot;good ones&quot; images (first and third), the normals are computed by linear interpolation, while the in the bad ones the normals are computed through the equations I said previously and are shown in the code.&#xD;&#xA;&#xD;&#xA;So, how can I correctly compute the normals? Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://reader.elsevier.com/reader/sd/pii/0010448595000461?token=4190E80EF50B0C8E2FB4EADFFEF26DF93ACEDF3AED59AA6B97D59B2C1FC52B0B965B255B27749ECC11F49B44C1610688&#xD;&#xA;  [2]: https://i.stack.imgur.com/GAsgv.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/u5rN7.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/kHTJV.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/YIW42.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/7bfza.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/5rw2D.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/a1MBK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25495" PostHistoryTypeId="1" PostId="9317" RevisionGUID="871ab4e3-9e81-4690-a655-8884de8ee5e2" CreationDate="2019-11-07T22:59:50.700" UserId="11436" Text="How to compute normal in quartic Walton-Meek's Gregory patch in tessellation shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25496" PostHistoryTypeId="3" PostId="9317" RevisionGUID="871ab4e3-9e81-4690-a655-8884de8ee5e2" CreationDate="2019-11-07T22:59:50.700" UserId="11436" Text="|opengl|glsl|computational-geometry|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25497" PostHistoryTypeId="5" PostId="9317" RevisionGUID="349bbba0-93b5-4435-8ada-d6fd07e1a0a3" CreationDate="2019-11-07T23:20:46.137" UserId="11436" Comment="Corrected spelling" Text="I am programing a tessellation shader in OpenGL which computes the [quartic Walton-Meek's Gregory patch][1]. I am searching for a local G1 method with good shading/visual results. So I am trying this patch. I didn't get good (visual/shading) results with PN-Triangles.&#xD;&#xA;&#xD;&#xA;I've just had my first result with this WM patch, which isn't good as well. Perhaps the normal I am calculating is wrong. I am following these equations to compute it:&#xD;&#xA;&#xD;&#xA;[![Bernstein Triangle][2]][2]&#xD;&#xA;[![Bernstein Polynomial][3]][3]&#xD;&#xA;[![Bernstein Derivatives][4]][4]&#xD;&#xA;&#xD;&#xA;Then, I actually compute it through normalizing the cross product between the derivatives (last image).&#xD;&#xA;&#xD;&#xA;If you want to take a look at the shader code, here it is (the first one is the tessellation control shader and the second one is the tessellation evaluation shader):&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout (vertices = 3) out;&#xD;&#xA;&#xD;&#xA;in VertOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;} vertOut[];&#xD;&#xA;&#xD;&#xA;out TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	const float kTessLevel = 12.0;&#xD;&#xA;	gl_TessLevelOuter[gl_InvocationID] = kTessLevel;&#xD;&#xA;	gl_TessLevelInner[0] = kTessLevel;&#xD;&#xA;&#xD;&#xA;	vec3 p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz;&#xD;&#xA;	vec3 n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;	const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;	vec3 edge = gl_in[nextInvID].gl_Position.xyz - p0;&#xD;&#xA;	vec3 nNext = vertOut[nextInvID].normal;&#xD;&#xA;	float d = length(edge), a = dot(n, nNext);&#xD;&#xA;	vec3 gama = edge / d;&#xD;&#xA;	float a0 = dot(n, gama), a1 = dot(nNext, gama);&#xD;&#xA;	float ro = 6.0 * (2.0 * a0 + a * a1)/(4.0 - a * a);&#xD;&#xA;	float sigma = 6.0 * (2.0 * a1 + a * a0)/(4.0 - a * a);&#xD;&#xA;&#xD;&#xA;	vec3 v[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		p0,&#xD;&#xA;		p0 + (d / 18.0) * (6.0 * gama - 2.0 * ro * n + sigma * nNext),&#xD;&#xA;		gl_in[nextInvID].gl_Position.xyz - (d / 18.0) * (6.0 * gama + ro * n - 2.0 * sigma * nNext),&#xD;&#xA;		edge = gl_in[nextInvID].gl_Position.xyz&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 w[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		v[1] - v[0],&#xD;&#xA;		v[2] - v[1],&#xD;&#xA;		v[3] - v[2]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 A[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		cross(n, normalize(w[0])),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		cross(nNext, normalize(w[2]))&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	A[1] = normalize(A[0] + A[2]);&#xD;&#xA;&#xD;&#xA;	vec3 l[5] = vec3[5]&#xD;&#xA;	(&#xD;&#xA;		v[0],&#xD;&#xA;		0.25 * (v[0] + 3.0 * v[1]),&#xD;&#xA;		0.25 * (2.0 * v[1] + 2.0 * v[2]),&#xD;&#xA;		0.25 * (3.0 * v[2] + v[3]),&#xD;&#xA;		v[3]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 p1 = tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;	vec3 p2 = tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;	vec3 p3 = tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;	barrier();&#xD;&#xA;&#xD;&#xA;	const int previousInvID = gl_InvocationID &gt; 0 ? gl_InvocationID - 1 : 2;&#xD;&#xA;	vec3 D[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		tescOut[previousInvID].p3 - 0.5 * (p0 + p1),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		tescOut[nextInvID].p1 - 0.5 * (p3 + tescOut[nextInvID].p0)&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	float mi[2] = float[2](dot(D[0], A[0]), dot(D[3], A[2]));&#xD;&#xA;	float lambda[2] = float[2](dot(D[0], w[0])/dot(w[0], w[0]), dot(D[3], w[2])/dot(w[2], w[2]));&#xD;&#xA;&#xD;&#xA;	tescOut[gl_InvocationID].g0 = 0.5 * (l[1] + l[2]) + (2.0/3.0) * (lambda[0] * w[1] + mi[0] * A[1]) + (1.0/3.0) * (lambda[1] * w[0] + mi[1] * A[0]);&#xD;&#xA;	tescOut[gl_InvocationID].g1 = 0.5 * (l[2] + l[3]) + (1.0/3.0) * (lambda[0] * w[2] + mi[1] * A[2]) + (2.0/3.0) * (lambda[1] * w[1] + mi[1] * A[1]);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout(triangles, equal_spacing, ccw) in;&#xD;&#xA;&#xD;&#xA;in TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;out TeseOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;	vec3 viewPosition;&#xD;&#xA;} teseOut;&#xD;&#xA;&#xD;&#xA;uniform mat4 mvp;&#xD;&#xA;uniform mat4 modelView;&#xD;&#xA;uniform mat4 normalMatrix;&#xD;&#xA;uniform bool isNormalLinearlyInterpolated;&#xD;&#xA;&#xD;&#xA;#define uvw     gl_TessCoord&#xD;&#xA;&#xD;&#xA;const float u = uvw.x, u2 = u * u, u3 = u2 * u, u4 = u2 * u2;&#xD;&#xA;const float v = uvw.y, v2 = v * v, v3 = v2 * v, v4 = v2 * v2;&#xD;&#xA;const float w = uvw.z, w2 = w * w, w3 = w2 * w, w4 = w2 * w2;&#xD;&#xA;&#xD;&#xA;#define p400	tescOut[0].p0&#xD;&#xA;#define p310	tescOut[0].p1&#xD;&#xA;#define p220	tescOut[0].p2&#xD;&#xA;#define p130	tescOut[0].p3&#xD;&#xA;#define G01		tescOut[0].g0&#xD;&#xA;#define	G02		tescOut[0].g1&#xD;&#xA;#define p040	tescOut[1].p0&#xD;&#xA;#define p031	tescOut[1].p1&#xD;&#xA;#define p022	tescOut[1].p2&#xD;&#xA;#define p013	tescOut[1].p3&#xD;&#xA;#define G11		tescOut[1].g0&#xD;&#xA;#define	G12		tescOut[1].g1&#xD;&#xA;#define p004	tescOut[2].p0&#xD;&#xA;#define p103	tescOut[2].p1&#xD;&#xA;#define p202	tescOut[2].p2&#xD;&#xA;#define p301	tescOut[2].p3&#xD;&#xA;#define G21		tescOut[2].g0&#xD;&#xA;#define	G22		tescOut[2].g1&#xD;&#xA;&#xD;&#xA;#define B400	u4&#xD;&#xA;#define B040	v4&#xD;&#xA;#define B004	w4&#xD;&#xA;#define B310	(4.0 * u3 * v)&#xD;&#xA;#define B031	(4.0 * v3 * w)&#xD;&#xA;#define B103	(4.0 * u * w3)&#xD;&#xA;#define B220	(6.0 * u2 * v2)&#xD;&#xA;#define B022	(6.0 * v2 * w2)&#xD;&#xA;#define B202	(6.0 * u2 * w2)&#xD;&#xA;#define B130	(4.0 * u * v3)&#xD;&#xA;#define B013	(4.0 * v * w3)&#xD;&#xA;#define B301	(4.0 * u3 * w)&#xD;&#xA;#define B211	(12.0 * u2 * v * w)&#xD;&#xA;#define B121	(12.0 * u * v2 * w)&#xD;&#xA;#define B112	(12.0 * u * v * w2)&#xD;&#xA;&#xD;&#xA;#define B300	u3&#xD;&#xA;#define B030	v3&#xD;&#xA;#define B003	w3&#xD;&#xA;#define B210	(3.0 * u2 * v)&#xD;&#xA;#define B021	(3.0 * v2 * w)&#xD;&#xA;#define B102	(3.0 * w2 * u)&#xD;&#xA;#define B120	(3.0 * u * v2)&#xD;&#xA;#define B012	(3.0 * v * w2)&#xD;&#xA;#define B201	(3.0 * w * u2)&#xD;&#xA;#define B111	(6.0 * u * v * w)&#xD;&#xA;&#xD;&#xA;vec3 interpolate3D(vec3 p0, vec3 p1, vec3 p2)&#xD;&#xA;{&#xD;&#xA;   	return gl_TessCoord.x * p0 + gl_TessCoord.y * p1 + gl_TessCoord.z * p2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	vec4 pos = vec4(interpolate3D(tescOut[0].p0, tescOut[1].p0, tescOut[2].p0), 1.0);&#xD;&#xA;	vec3 normal = normalize(interpolate3D(tescOut[0].n, tescOut[1].n, tescOut[2].n));&#xD;&#xA;&#xD;&#xA;	if (u != 1.0 &amp;&amp; v != 1.0 &amp;&amp; w != 1.0)&#xD;&#xA;	{&#xD;&#xA;		vec3 p211 = (v * G12 + w * G21)/(v + w);&#xD;&#xA;		vec3 p121 = (w * G02 + u * G11)/(w + u);&#xD;&#xA;		vec3 p112 = (u * G22 + v * G01)/(u + v);&#xD;&#xA;&#xD;&#xA;		vec3 barPos =	p400 * B400 +&#xD;&#xA;						p040 * B040 +&#xD;&#xA;						p004 * B004 +&#xD;&#xA;						p310 * B310 +&#xD;&#xA;						p031 * B031 +&#xD;&#xA;						p103 * B103 +&#xD;&#xA;						p220 * B220 +&#xD;&#xA;						p022 * B022 +&#xD;&#xA;						p202 * B202 +&#xD;&#xA;						p130 * B130 +&#xD;&#xA;						p013 * B013 +&#xD;&#xA;						p301 * B301 +&#xD;&#xA;						p211 * B211 +&#xD;&#xA;						p121 * B121 +&#xD;&#xA;						p112 * B112;&#xD;&#xA;&#xD;&#xA;		pos = vec4(barPos, 1.0);&#xD;&#xA;&#xD;&#xA;		vec3 dpdu =	p400 * B300 +&#xD;&#xA;					p130 * B030 +&#xD;&#xA;					p103 * B003 +&#xD;&#xA;					p310 * B210 +&#xD;&#xA;					p121 * B021 +&#xD;&#xA;					p202 * B102 +&#xD;&#xA;					p220 * B120 +&#xD;&#xA;					p112 * B012 +&#xD;&#xA;					p301 * B201 +&#xD;&#xA;					p211 * B111 ;&#xD;&#xA;&#xD;&#xA;		vec3 dpdv =	p310 * B300 +&#xD;&#xA;					p040 * B030 +&#xD;&#xA;					p013 * B003 +&#xD;&#xA;					p220 * B210 +&#xD;&#xA;					p031 * B021 +&#xD;&#xA;					p112 * B102 +&#xD;&#xA;					p130 * B120 +&#xD;&#xA;					p022 * B012 +&#xD;&#xA;					p211 * B201 +&#xD;&#xA;					p121 * B111 ;&#xD;&#xA;&#xD;&#xA;		normal = normalize(cross(dpdu, dpdv));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	gl_Position = mvp * pos;&#xD;&#xA;	pos = modelView * pos;&#xD;&#xA;	teseOut.viewPosition = pos.xyz / pos.w;&#xD;&#xA;&#xD;&#xA;	teseOut.normal = (normalMatrix * vec4(normal, 0.0)).xyz;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Some screenshots from my current results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;In the &quot;good ones&quot; images (first and third), the normals are computed by linear interpolation, while in the bad ones the normals are computed through the equations I said previously and are shown in the code.&#xD;&#xA;&#xD;&#xA;So, how can I correctly compute the normals? Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://reader.elsevier.com/reader/sd/pii/0010448595000461?token=4190E80EF50B0C8E2FB4EADFFEF26DF93ACEDF3AED59AA6B97D59B2C1FC52B0B965B255B27749ECC11F49B44C1610688&#xD;&#xA;  [2]: https://i.stack.imgur.com/GAsgv.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/u5rN7.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/kHTJV.gif&#xD;&#xA;  [5]: https://i.stack.imgur.com/YIW42.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/7bfza.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/5rw2D.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/a1MBK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25498" PostHistoryTypeId="2" PostId="9318" RevisionGUID="261f64f5-0ffb-4d1e-aaa0-e4c33e0a65e5" CreationDate="2019-11-08T05:09:01.187" UserId="20501" Text="Assuming that I have pose information for a human, is there any ways/tools to apply that pose to a 3D model?&#xD;&#xA;&#xD;&#xA;Basically, given continous pose information say from a dancing person, I like to animate a 3D model with that pose, so performing exactly the same dance.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zYpztm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25499" PostHistoryTypeId="1" PostId="9318" RevisionGUID="261f64f5-0ffb-4d1e-aaa0-e4c33e0a65e5" CreationDate="2019-11-08T05:09:01.187" UserId="20501" Text="Apply a pose to a 3D model/mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="25500" PostHistoryTypeId="3" PostId="9318" RevisionGUID="261f64f5-0ffb-4d1e-aaa0-e4c33e0a65e5" CreationDate="2019-11-08T05:09:01.187" UserId="20501" Text="|3d|mesh|animation|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25501" PostHistoryTypeId="2" PostId="9319" RevisionGUID="7b3e8aa0-bf0e-4e29-8584-399f3cebf7c9" CreationDate="2019-11-08T08:48:28.873" UserId="11439" Text="I'm working (as a Post-doc) on an archaeological excavation point cloud dataset with over 2.5 Billion points. This points come from a trench, a cuboid 10 x 10 x 3 m. Each point cloud is a layer, the gaps between are the excavated volumes. There are 444 volumes from this trench, 700 individual point clouds.&#xD;&#xA;&#xD;&#xA;Can anyone give me some direction to any deep learning algorithms which can mesh these empty spaces? I'm already doing this semi-automatically using Open3D and other python libraries, but if we could train the program to assess all the point clouds and deduce the volumes it would save us a lot of time and hopefully get better results.&#xD;&#xA;&#xD;&#xA;We excavate more trenches every year so the perfect place to test these out.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;reposted from here https://stackoverflow.com/questions/58757853/deep-learning-for-3d-point-clouds-volume-detection-and-meshing" ContentLicense="CC BY-SA 4.0" />
  <row Id="25502" PostHistoryTypeId="1" PostId="9319" RevisionGUID="7b3e8aa0-bf0e-4e29-8584-399f3cebf7c9" CreationDate="2019-11-08T08:48:28.873" UserId="11439" Text="Deep Learning for 3D Point Clouds, volume detection and meshing" ContentLicense="CC BY-SA 4.0" />
  <row Id="25503" PostHistoryTypeId="3" PostId="9319" RevisionGUID="7b3e8aa0-bf0e-4e29-8584-399f3cebf7c9" CreationDate="2019-11-08T08:48:28.873" UserId="11439" Text="|algorithm|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25504" PostHistoryTypeId="50" PostId="9207" RevisionGUID="16f8bf5a-d480-452a-b896-3c75278a1b62" CreationDate="2019-11-08T09:02:20.300" UserId="-1" />
  <row Id="25505" PostHistoryTypeId="5" PostId="9309" RevisionGUID="538c1b56-77db-4792-ae85-4b89d86d2a43" CreationDate="2019-11-08T11:05:09.463" UserId="209" Comment="Added some more explanatory notes" Text="Rather than fit bilinear patches to your sample points, which are only C0 continuous$^\spadesuit$ may I instead suggest fitting the surface using Catmull-Rom splines? These will give you C2 continuity. &#xD;&#xA;Catmull-Rom is an interpolating spline which means it will pass through your sample points, as did the bilinear surface, but will do so smoothly from patch to patch.&#xD;&#xA;&#xD;&#xA;$^\spadesuit$ *because the first derivatives won't generally match at the boundaries of your patches* &#xD;&#xA;&#xD;&#xA;To form each bicubic Catmull-Rom patch, $C_{i,j}$, which has a given 2x2 set of samples $\{S_{i,j},  S_{i+1,j}, S_{i,j+1},  S_{i+1,j+1}\}$ at the corners, you need a set of 4x4 samples formed from the 2x2 at the centre and the surrounding 12 samples, i.e.$\{S_{i-1,j-1}$ *through* $S_{i+2,j+2}\}$,  as shown below.&#xD;&#xA;(My apologies that this is 'hand placed' so is far from ideal)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we just consider the behaviour of the surface at sample, $S_{i,j}$, then the partial derivative in the $i$ direction is given by &#xD;&#xA;$$\frac{\partial C_{ij}}{\partial i}=\frac{S_{i+1,j}-S_{i-1,j}}{2}$$&#xD;&#xA;and similarly, in the $j$ direction by&#xD;&#xA;$$\frac{\partial C_{ij}}{\partial j}=\frac{S_{i,j+1}-S_{i,j-1}}{2}$$&#xD;&#xA;&#xD;&#xA;Remembering these are vectors, you can use the cross product to generate a surface normal at any of the $S_{i,j}$ points$^\clubsuit$. (Though you may need an extra set of boundary samples)&#xD;&#xA;&#xD;&#xA;&gt;*Ali: You mentioned that both partial derivatives are vectors(in i,j directions). could you write each vector components plz*&#xD;&#xA;&#xD;&#xA;Certainly: If we say $S_{i,j}=[x_{i,j},y_{i,j},z_{i,j}]^T$ then $$\frac{\partial C_{ij}}{\partial i}=\frac{1}{2}.[(x_{i+1,j}-x_{i-1,j}),(y_{i+1,j}-y_{i-1,j}),(z_{i+1,j}-z_{i-1,j})]^T$$&#xD;&#xA;$$\frac{\partial C_{ij}}{\partial j}=\frac{1}{2}.[(x_{i,j+1}-x_{i,j-1}),(y_{i,j+1}-y_{i,j-1}),(z_{i,j+1}-z_{i,j-1})]^T$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;br\&gt;If you've sampled the surface 'finely' enough you could probably choose to render the surface by just using 2 or 4 triangles per original patch. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, you can recursively subdivide your quad mesh to get a finer set of triangles. To double the number of points in the 'i' direction, simply insert a new point between each $S_{i,j}$ and $S_{i+1,j}$ that equals ...&#xD;&#xA;$$\frac{9(S_{i,j}+S_{i+1,j}) - (S_{i-1,j}+S_{i+2,j})}{16}$$&#xD;&#xA; Once you have the finer grid in 'i' simply repeat with 'j' with the appropriate equivalent set of points. You can repeat this ad nauseam to get whatever triangle resolution you desire ;-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$^\clubsuit$ (Copying some text from the comments below): I've made a couple of valid assumptions here.  Noting that if a given first (partial) derivative is non-zero (which is guaranteed in your case because of the way you construct the surface), then it also is locally tangential to that surface. Further, we know your two partial derivates aren't parallel, so the cross product will construct a valid normal. &#xD;&#xA;FWIW For some arrangements of control points, i.e. in more general use cases, you can get so-called 'degenerate' surfaces where you can't naively apply the above rules, but you're safe here. &#xD;&#xA;  [1]: https://i.stack.imgur.com/M48A3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25506" PostHistoryTypeId="4" PostId="9303" RevisionGUID="13a5451d-9508-4cab-ac1b-9f913fd5be69" CreationDate="2019-11-08T12:02:54.283" UserId="209" Comment="fixed typo" Text="An idea for an implementation of continuous collision detection of circles" ContentLicense="CC BY-SA 4.0" />
  <row Id="25507" PostHistoryTypeId="5" PostId="9211" RevisionGUID="b7f41a6f-6d1a-4cdf-937e-d25d644e27cd" CreationDate="2019-11-08T12:07:13.197" UserId="209" Comment="minor additional notes" Text="_**Disclaimer**: I've done some work in the past with wavelet decomposition of **image** data but it occurred to me that it may be applicable to your problem.  Admittedly, I don't actually know if the following will work well in practice but, given how simple the approach is, and, as no other answer has been put forward, it seems to warrant investigation_&#xD;&#xA;&#xD;&#xA;Let's assume you have a sequence of 2D (or **n**D) vertices, $\small[P_0,P_1,P_2,...P_{N-1}]$, and you want to reduce those to a sequence of just $M$ which form your Catmull-Rom control points. For the *moment* let's assume $\small N=2^kM$, for some small value of $\small k$. We will apply *k* wavelet decompositions to reduce N to M points.&#xD;&#xA;&#xD;&#xA;For our purposes, a single wavelet decomposition step takes a sequence of **2**R points, $\small P=[P_0,P_1,...P_{2R-1}]$, and replaces it with two sequences of R points each: a *low frequency* set, $\small L=[L_0,...L_{R-1}]$, and a high frequency set, $\small H=[H_0,...H_{R-1}]$. I suspect in your use case you might only be interested in the low frequency sequence(s).&#xD;&#xA;&#xD;&#xA;There are multiple different wavelets that can be used - the simplest being the Haar wavelet - but I think a linear (see [Sweldens &amp; Schröder][1] for an easy introduction)  or perhaps a 'Catmull-Rom-based' cubic wavelet might be suitable (though I don't know if this appears in any literature).&#xD;&#xA;&#xD;&#xA;For each wavelet decomposition step we perform two passes; a 'lifting' operation to create all the high frequency terms, i.e. either...&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;&gt;*Linear*:  $$H_i := P_{2i+1} - \frac{(P_{2i} +P_{2i+2})}{2}$$&#xD;&#xA;*CR-cubic*:$$H_i := P_{2i+1} - \frac{9(P_{2i} +P_{2i+2})-(P_{2i-2} +P_{2i+4})}{16}$$&#xD;&#xA;&#xD;&#xA;...followed by an 'update'  which filters some of the high frequency terms back into the 'even'/low frequency terms as a correction. (We'll just assume, perhaps sub-optimally, this is the same for both linear and cubic)&#xD;&#xA;&gt; $$L_i := P_{2i} + \frac{(H_{i-1} + H_{i})}{4}$$&#xD;&#xA;&#xD;&#xA;***Notes**: Actually, in practice, with clever indexing, these calculations can be done 'in place' on the original array.&lt;br/&gt;&#xD;&#xA;This has also glossed over what happens when exceeding the bounds of the arrays, e.g. at $P_{2N}$ and $L_{-1}$, but one approach is to simply repeat values and/or pad with zeros.*&#xD;&#xA;&#xD;&#xA;To do the next wavelet decomposition, you repeat the process with the low frequency data, e.g. &quot;P:=L&quot; and repeat.&#xD;&#xA;&#xD;&#xA;I imagine that the final set of low frequency points, L, will form a *reasonable* set of control points for a piecewise Catmull-Rom curve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;***More notes**: In this I've assumed that all the original points were 'equally important' and probably 'reasonably evenly spread'. It could be that you may want to look at the magnitudes of some of the {H_i} terms and if some are relatively large (compared to their neighbours) perhaps take action, e.g. say, re-insert them into the lower frequency set?*&#xD;&#xA;&#xD;&#xA;As requested in the comments, I've put together a little bit of C code to do the &quot;cubic&quot; decomposition. For simplicity, this just uses separate arrays for each of the lower frequency results rather than, say, doing the calculation &quot;in place&quot; in the original array.&#xD;&#xA;````&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;assert.h&gt;&#xD;&#xA;&#xD;&#xA;#define IS_EVEN(X) (((X)&amp;1)==0)&#xD;&#xA;#define MAX(X,Y) ((X)&gt;=(Y)?(X):(Y))&#xD;&#xA;#define MIN(X,Y) ((X)&lt;=(Y)?(X):(Y))&#xD;&#xA;&#xD;&#xA;typedef unsigned int UINT;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_DIMS (2)&#xD;&#xA;&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;	float pos[NUM_DIMS];&#xD;&#xA;}vec_t;&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Lift&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;lift&quot; step, i.e. computes high frequency terms, by&#xD;&#xA;// predicting using Catmull-Rom spline through even points, and computing&#xD;&#xA;// differences from odd&#xD;&#xA;*/&#xD;&#xA;static void Lift(const vec_t  PointsIn[], &#xD;&#xA;				 const UINT NumPtsIn,&#xD;&#xA;				 vec_t HFOut[])&#xD;&#xA;{&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn) &amp;&amp;  NumPtsIn&gt;=2);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through odd values doing a &quot;lifting&quot; step, i.e. predicting &#xD;&#xA;	// a position from neighbourhood of even points and computing the difference&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 1; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// get 2 neighbours on either side of this odd point. IF we step out of range, then&#xD;&#xA;		// clamp to nearest valid point&#xD;&#xA;		//&#xD;&#xA;		// If you want more efficient code, move these decisions out of the loop&#xD;&#xA;		*/&#xD;&#xA;		const vec_t * pv_m3 = &amp;PointsIn[MAX(i, 3) - 3];&#xD;&#xA;		const vec_t * pv_m1 = &amp;PointsIn[i-1];&#xD;&#xA;		const vec_t * pv_p1 = &amp;PointsIn[MIN(i+1, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv_p3 = &amp;PointsIn[MIN(i+3, NumPtsIn - 1)];&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;HFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Predict using Catmull-Rom interpolation - &#xD;&#xA;			//i.e. mid point of CR spline through the even points {p[i-3], p[i-1], p[i+1], p[i+3]}&#xD;&#xA;			const float PredictedPos = (9.0/16.0) * (pv_m1-&gt;pos[j] + pv_p1-&gt;pos[j]) - (1.0/16.0) * (pv_m3-&gt;pos[j] + pv_p3-&gt;pos[j]);&#xD;&#xA;&#xD;&#xA;			//Compute the difference from actual pos&#xD;&#xA;			pResult-&gt;pos[j] =pv-&gt;pos[j] - PredictedPos;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/*&#xD;&#xA;// Update&#xD;&#xA;//&#xD;&#xA;// Applies a wavelet &quot;Update&quot; step, i.e. computes the low frequency terms, &#xD;&#xA;// by filtering in the 'errors' in the prediction (i.e the HF terms) into the&#xD;&#xA;// 'even' vals&#xD;&#xA;*/&#xD;&#xA;static void Update(const vec_t  PointsIn[], &#xD;&#xA;				   const UINT NumPtsIn,&#xD;&#xA;				   const vec_t HFIn[],&#xD;&#xA;				   vec_t LFOut[])&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	static const vec_t TheZeroVec = {0};&#xD;&#xA;&#xD;&#xA;	//this *example* assumes an even number of input values&#xD;&#xA;	assert(IS_EVEN(NumPtsIn));&#xD;&#xA;&#xD;&#xA;	//init as if for the &quot;i = -1&quot; iteration&#xD;&#xA;	const vec_t * pHFToRight = &amp;TheZeroVec;&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// step through even values doing an &quot;update&quot; step,&#xD;&#xA;	*/&#xD;&#xA;	for(UINT i = 0; i &lt; NumPtsIn; i+= 2)&#xD;&#xA;	{&#xD;&#xA;		/*&#xD;&#xA;		// move one spot over in HF data&#xD;&#xA;		*/&#xD;&#xA;		const vec_t *pHFToLeft = pHFToRight;&#xD;&#xA;		pHFToRight = &amp;HFIn[i/2];&#xD;&#xA;&#xD;&#xA;		const vec_t * pv    = &amp;PointsIn[i];&#xD;&#xA;&#xD;&#xA;		vec_t *pResult = &amp;LFOut[i/2];&#xD;&#xA;&#xD;&#xA;		for(UINT j = 0; j &lt; NUM_DIMS; j++)&#xD;&#xA;		{&#xD;&#xA;			//Add in 1/2 of the average of the adjacent HF/Odd terms&#xD;&#xA;			pResult-&gt;pos[j] = pv-&gt;pos[j] + (pHFToLeft-&gt;pos[j] + pHFToRight-&gt;pos[j]) * 0.25;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//Some test data ...&#xD;&#xA;#define NUM_ORIG_POINTS (512u)&#xD;&#xA;static const vec_t PointsIn[NUM_ORIG_POINTS]=&#xD;&#xA;{&#xD;&#xA;#include &quot;fjord.h&quot;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#define NUM_ADDITIONAL_PASSES (4)&#xD;&#xA;extern int main(int argc, const char *argv[])&#xD;&#xA;{&#xD;&#xA;	&#xD;&#xA;	vec_t HighFreq[NUM_ORIG_POINTS/2];&#xD;&#xA;	vec_t LowFreqs[NUM_ADDITIONAL_PASSES+1][NUM_ORIG_POINTS/2];&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do initial wavelet pass&#xD;&#xA;	*/&#xD;&#xA;	Lift(PointsIn, NUM_ORIG_POINTS, HighFreq);&#xD;&#xA;	Update(PointsIn, NUM_ORIG_POINTS, HighFreq, LowFreqs[0]);&#xD;&#xA;&#xD;&#xA;	/*&#xD;&#xA;	// Do a few more wavelet passes&#xD;&#xA;	*/&#xD;&#xA;	for(UINT Pass=0; Pass &lt; NUM_ADDITIONAL_PASSES; Pass++)&#xD;&#xA;	{&#xD;&#xA;		const UINT CurrentNumSrcPoints = NUM_ORIG_POINTS &gt;&gt; (Pass+1);&#xD;&#xA;&#xD;&#xA;		Lift(LowFreqs[Pass],   CurrentNumSrcPoints, HighFreq);&#xD;&#xA;		Update(LowFreqs[Pass], CurrentNumSrcPoints, HighFreq, LowFreqs[Pass+1]);&#xD;&#xA;	}	&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;The above has been run on the outline on a section of a map (a section of a fjord apparently) which I've plotted using Excel's scatter plot tools (*which I hope will give a 'reasonable' approximation of Catmull-Rom splines without me having to write (or find) my own rendering code*)&#xD;&#xA;&#xD;&#xA;This shows an original set of 512 points:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;..the set of 256 low-frequency points obtained from one wavelet step...&#xD;&#xA;[![One Wavelet Step][3]][3]&#xD;&#xA;&#xD;&#xA;...through to the 128 points obtained by two steps:[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://9p.io/who/wim/papers/athome/&#xD;&#xA;  [2]: https://i.stack.imgur.com/t456F.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZktUd.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/OfdKt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25509" PostHistoryTypeId="2" PostId="9321" RevisionGUID="78dfe6b6-0ec6-4e30-b78e-ab188fa90443" CreationDate="2019-11-08T12:52:42.527" UserId="7724" Text="Computing exact derivatives of Gregory patches is hard due to the rational blending that occurs for the inner control points. Many people thus opt for an easier solution where the rational blending functions are first evaluated and then the resulting control points are interpreted as the control points of a standard polynomial Bézier triangle. This technique is used for instance in [ACC-2][1] to approximate the normal. This will introduce singularities at the vertices but these can easily be removed as the normal is just the vertex normal.&#xD;&#xA;&#xD;&#xA;Remember that the partial derivatives of a Bézier triangle  of degree $p$ is a Bézier triangle of degree $p-1$ where the control points in that case are vectors between the control points. As seen from the figure below you can evaluate each partial derivative as a Bézier triangle. In your case you are using just control points, but you have to use differences between control points. &#xD;&#xA;&#xD;&#xA;[![Partial derivatives as Bézier triangles][2]][2]&#xD;&#xA;&#xD;&#xA;$$\partial u =  4 (B_{300} (P_{301} - P_{400}) + B_{030} (P_{031} - P_{310}) + B_{003} (P_{004} - P_{103}) +  B_{210} (P_{211} - P_{310}) +  B_{120} (P_{121} - P_{220}) ) +  B_{201} (P_{202} - P_{301}) ) +  B_{102} (P_{103} - P_{202}) +  B_{021} (P_{022} - P_{121}) +  B_{012} (P_{013} - P_{112}) +  B_{111} (P_{112} - P_{211}) ) )$$&#xD;&#xA;&#xD;&#xA;and the other derivative similarly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=1618497&#xD;&#xA;  [2]: https://i.stack.imgur.com/nIVg4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25510" PostHistoryTypeId="50" PostId="8886" RevisionGUID="ecb1dae7-a9c4-42a8-af5f-b7ab54e9e171" CreationDate="2019-11-08T13:02:45.353" UserId="-1" />
  <row Id="25511" PostHistoryTypeId="5" PostId="9321" RevisionGUID="6e572575-712c-4697-94da-9f6ffff858c1" CreationDate="2019-11-08T13:11:33.763" UserId="7724" Comment="added 445 characters in body" Text="Computing exact derivatives of Gregory patches is hard due to the rational blending that occurs for the inner control points. Many people thus opt for an easier solution where the rational blending functions are first evaluated and then the resulting control points are interpreted as the control points of a standard polynomial Bézier triangle. This technique is used for instance in [ACC-2][1] to approximate the normal. This will introduce singularities at the vertices but these can easily be removed as the normal is just the vertex normal.&#xD;&#xA;&#xD;&#xA;Remember that the partial derivatives of a Bézier triangle  of degree $p$ is a Bézier triangle of degree $p-1$ where the control points in that case are vectors between the control points. As seen from the figure below you can evaluate each partial derivative as a Bézier triangle. In your case you are using just control points, but you have to use differences between control points. &#xD;&#xA;&#xD;&#xA;[![Partial derivatives as Bézier triangles][2]][2]&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial u} =  4 (B_{300} (P_{301} - P_{400}) + B_{030} (P_{031} - P_{310}) + B_{003} (P_{004} - P_{103}) +  B_{210} (P_{211} - P_{310}) +  B_{120} (P_{121} - P_{220})  +  B_{201} (P_{202} - P_{301})  +  B_{102} (P_{103} - P_{202}) +  B_{021} (P_{022} - P_{121}) +  B_{012} (P_{013} - P_{112}) +  B_{111} (P_{112} - P_{211}) ) $$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial v} =  4 (B_{300} (P_{310} - P_{400}) + B_{030} (P_{004} - P_{310}) + B_{003} (P_{013} - P_{103}) +  B_{210} (P_{220} - P_{310}) +  B_{120} (P_{310} - P_{220})  +  B_{201} (P_{211} - P_{301})  +  B_{102} (P_{112} - P_{202}) +  B_{012} (P_{022} - P_{112}) +  B_{021} (P_{031} - P_{121}) +  B_{111} (P_{121} - P_{211}) ). $$&#xD;&#xA;&#xD;&#xA;Then proceed the same way in producing the normal by the cross product of the two partial derivatives. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=1618497&#xD;&#xA;  [2]: https://i.stack.imgur.com/nIVg4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25512" PostHistoryTypeId="2" PostId="9322" RevisionGUID="b4714f0c-df2e-4ba4-ac0a-94bccf637b5e" CreationDate="2019-11-08T13:13:18.003" UserId="10780" Text="I am about to implement the renderer for a simple particle system. Every particle has to be updated every frame (position, rotation, scale) and so I was wondering which way is usually faster:&#xD;&#xA;&#xD;&#xA;1. Calculate translation, rotation, scale and update the final positions in the vertexbuffer.&#xD;&#xA;&#xD;&#xA;2. Calculate translation, rotation, scale into one transformation matrix and send that one to the GPU Shader for each particle." ContentLicense="CC BY-SA 4.0" />
  <row Id="25513" PostHistoryTypeId="1" PostId="9322" RevisionGUID="b4714f0c-df2e-4ba4-ac0a-94bccf637b5e" CreationDate="2019-11-08T13:13:18.003" UserId="10780" Text="Performance of particle implementation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25514" PostHistoryTypeId="3" PostId="9322" RevisionGUID="b4714f0c-df2e-4ba4-ac0a-94bccf637b5e" CreationDate="2019-11-08T13:13:18.003" UserId="10780" Text="|gpu|vertex-buffer-object|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25516" PostHistoryTypeId="2" PostId="9323" RevisionGUID="83f94570-5418-4687-b90b-bd4031d687e8" CreationDate="2019-11-08T16:52:56.837" UserId="11443" Text="I am experimenting with local (adaptive) grey threshold for the binarization of B&amp;W photographs of yellowed manuscripts:&#xD;&#xA;&#xD;&#xA;[![Raw image][1]][1]&#xD;&#xA;&#xD;&#xA;I got adaptive thresholding working in both scikit-image and cv2. In both cases (```grey &lt; threshold_niblack()``` in scikit-image and ```cv.adaptiveThreshold()``` in cv2 -- all Python) the result I get is successfully binarized, with the background pretty much uniform -- and completely full of noise:&#xD;&#xA;&#xD;&#xA;[![Binarized image][2]][2]&#xD;&#xA;&#xD;&#xA;What kind of step do I now need to separate the text from this background noise?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tAS67.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/8yuGR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25517" PostHistoryTypeId="1" PostId="9323" RevisionGUID="83f94570-5418-4687-b90b-bd4031d687e8" CreationDate="2019-11-08T16:52:56.837" UserId="11443" Text="What kind of denoising must follow locally adaptive binarization?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25518" PostHistoryTypeId="3" PostId="9323" RevisionGUID="83f94570-5418-4687-b90b-bd4031d687e8" CreationDate="2019-11-08T16:52:56.837" UserId="11443" Text="|image-processing|denoise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25519" PostHistoryTypeId="5" PostId="9318" RevisionGUID="6a65b5b4-f81e-45f1-bdf4-c489351b58ff" CreationDate="2019-11-08T17:43:33.670" UserId="20501" Comment="added 151 characters in body" Text="Assuming that I have pose information for a human, is there any ways/tools to apply that pose to a 3D model?&#xD;&#xA;&#xD;&#xA;Basically, given continous pose information say from a dancing person, I like to animate a 3D model with that pose, so performing exactly the same dance.&#xD;&#xA;&#xD;&#xA;e.g. here the left pose is applied to a model to become right:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zYpztm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Rjt8m.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="25520" PostHistoryTypeId="5" PostId="9309" RevisionGUID="d218c557-4c5b-4712-8be7-89eccab8db6f" CreationDate="2019-11-08T17:44:55.533" UserId="209" Comment="Further remarks" Text="Rather than fit bilinear patches to your sample points, which are only C0 continuous$^\spadesuit$ may I instead suggest fitting the surface using Catmull-Rom splines? These will give you C2 continuity. &#xD;&#xA;Catmull-Rom is an interpolating spline which means it will pass through your sample points, as did the bilinear surface, but will do so smoothly from patch to patch.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$^\spadesuit$ *because the first derivatives won't generally match at the boundaries of your patches* &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Background/Assumption ###&#xD;&#xA;You have a function $$F:\Re^2\to\Re^3$$ of the form  $$F(s,t)=[s,t,f(s,t)]$$ where $f:\Re^2\to\Re$. The function, $f$, can be considered a 'black box' in the sense that we might not be given it explicitly.&#xD;&#xA; &#xD;&#xA;$F$ has been regularly sampled as $$S_{i,j}=F(x_{scale}.i, y_{scale}.j, f(x_{scale}.i,y_{scale}.j))$$ where $i,j\in\mathbb{Z}$.  You then want interpolate between these sample points using piecewise bicubic Catmull-Rom patches.&#xD;&#xA;&#xD;&#xA;### Constructing patches ###&#xD;&#xA;To form a particular bicubic Catmull-Rom patch, $C_{i,j}$, which has a given 2x2 set of samples $\{S_{i,j},  S_{i+1,j}, S_{i,j+1},  S_{i+1,j+1}\}$ at the corners, you need the set of 4x4 samples formed from the 2x2 at the centre and the surrounding 12 samples, i.e.$\{S_{i-1,j-1}$ *through* $S_{i+2,j+2}\}$,  as shown below.&#xD;&#xA;(My apologies that this is 'hand placed' so is far from ideal)&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If we just consider the behaviour of the surface at sample, $S_{i,j}$, then the partial derivative in the $i$ direction is given by &#xD;&#xA;$$\frac{\partial C_{ij}}{\partial i}=\frac{S_{i+1,j}-S_{i-1,j}}{2}$$&#xD;&#xA;and similarly, in the $j$ direction by&#xD;&#xA;$$\frac{\partial C_{ij}}{\partial j}=\frac{S_{i,j+1}-S_{i,j-1}}{2}$$&#xD;&#xA;&#xD;&#xA;Remembering these are vectors, you can use the cross product to generate a surface normal at any of the $S_{i,j}$ points$^\clubsuit$. (Though you may need an extra set of boundary samples)&#xD;&#xA;&#xD;&#xA;&gt;*Ali: You mentioned that both partial derivatives are vectors(in i,j directions). could you write each vector components plz*&#xD;&#xA;&#xD;&#xA;Certainly: If we say $S_{i,j}=[x_{i,j},y_{i,j},z_{i,j}]^T$ then $$\frac{\partial C_{ij}}{\partial i}=\frac{1}{2}.[(x_{i+1,j}-x_{i-1,j}),(y_{i+1,j}-y_{i-1,j}),(z_{i+1,j}-z_{i-1,j})]^T$$&#xD;&#xA;$$\frac{\partial C_{ij}}{\partial j}=\frac{1}{2}.[(x_{i,j+1}-x_{i,j-1}),(y_{i,j+1}-y_{i,j-1}),(z_{i,j+1}-z_{i,j-1})]^T$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;br\&gt;If you've sampled the surface 'finely' enough you could probably choose to render the surface by just using 2 or 4 triangles per original patch. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Alternatively, you can recursively subdivide your quad mesh to get a finer set of triangles. To double the number of points in the 'i' direction, simply insert a new point between each $S_{i,j}$ and $S_{i+1,j}$ that equals ...&#xD;&#xA;$$\frac{9(S_{i,j}+S_{i+1,j}) - (S_{i-1,j}+S_{i+2,j})}{16}$$&#xD;&#xA; Once you have the finer grid in 'i' simply repeat with 'j' with the appropriate equivalent set of points. You can repeat this ad nauseam to get whatever triangle resolution you desire ;-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$^\clubsuit$ (Copying some text from the comments below): I've made a couple of valid assumptions here.  Noting that if a given first (partial) derivative is non-zero (which is guaranteed in your case because of the way you construct the surface), then it also is locally tangential to that surface. Further, we know your two partial derivates aren't parallel, so the cross product will construct a valid normal. &#xD;&#xA;FWIW For some arrangements of control points, i.e. in more general use cases, you can get so-called 'degenerate' surfaces where you can't naively apply the above rules, but you're safe here. &#xD;&#xA;  [1]: https://i.stack.imgur.com/M48A3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25521" PostHistoryTypeId="2" PostId="9324" RevisionGUID="6c689c82-7de3-4882-ac9a-2e5bfc3cebe4" CreationDate="2019-11-08T18:36:56.033" UserId="9438" Text="I need some help understanding whats happening to my view space.&#xD;&#xA;&#xD;&#xA;I have the following colour buffers coming out of my deffered renderer...&#xD;&#xA;[![Depth buffer][1]][1]&#xD;&#xA;[![Normal buffer][2]][2]&#xD;&#xA;[![ViewSpace positions][3]][3]&#xD;&#xA;My concern is with the view space buffer (third image), while this seems correct for the xy view space coordinate, should I not be seeing some purple/pink/white for the z component of the view space coordinate?&#xD;&#xA;&#xD;&#xA;This scene is fairly large in an attempt to try to get varying depth values to see in the view space position buffer.&#xD;&#xA;&#xD;&#xA;For a small model (near and far clipping planes are sized according to scene bounding box), I get...&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;Which, while it has gradient changes between the xy (not like the large scene which has sharp gradient changes, due to its size perhaps?) which makes sense to me. However I am still missing z/depth values it appears (pinks, purples and whites).&#xD;&#xA;&#xD;&#xA;I pressume the view space in the range -1 &lt; x &lt; 1, -1 &lt; y &lt; 1, -1 &lt; z &lt; 1. Is this correct? Is there a problem with my view space coordinates? Could anyone spot anything I am doing wrong here?&#xD;&#xA;&#xD;&#xA;Here are my shaders:&#xD;&#xA;&#xD;&#xA;Vertex shader of gBuffer...&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    layout (std140) uniform MatrixPV&#xD;&#xA;    {&#xD;&#xA;        mat4 P;&#xD;&#xA;        mat4 V;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec3 InPoint;&#xD;&#xA;    layout(location = 1) in vec3 InNormal;&#xD;&#xA;    layout(location = 2) in vec2 InUV;&#xD;&#xA;    &#xD;&#xA;    uniform mat4 M;&#xD;&#xA;    &#xD;&#xA;    out vec4 MVPosition;&#xD;&#xA;    out vec3 Normal;&#xD;&#xA;    out vec2 UV;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	mat4 VM = V * M;&#xD;&#xA;    	gl_Position = P * VM * vec4(InPoint, 1.0);&#xD;&#xA;    	MVPosition = VM * vec4(InPoint, 1.0);&#xD;&#xA;    	Normal = mat3(M) * InNormal;&#xD;&#xA;    	UV = InUV;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader of gBuffer...&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) out vec4 gBufferPicker;&#xD;&#xA;    layout(location = 1) out vec4 gBufferPosition;&#xD;&#xA;    layout(location = 2) out vec4 gBufferNormal;&#xD;&#xA;    layout(location = 3) out vec4 gBufferDiffuse;&#xD;&#xA;    &#xD;&#xA;    in vec3 Normal;&#xD;&#xA;    in vec4 MVPosition;&#xD;&#xA;    &#xD;&#xA;    vec4 Diffuse();&#xD;&#xA;    uniform vec4 PickerColour;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	gBufferPosition = MVPosition;&#xD;&#xA;        gBufferNormal = vec4(Normal.xyz, 1.0);&#xD;&#xA;        gBufferPicker = PickerColour;&#xD;&#xA;        gBufferDiffuse = Diffuse();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And here is the 'lighting pass' shader to visualise the view space coordinate...&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D debugBufferPosition;&#xD;&#xA;    &#xD;&#xA;    in vec2 UV;&#xD;&#xA;    out vec4 frag;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	vec3 val = texture(debugBufferPosition, UV).xyz;&#xD;&#xA;    	frag = vec4(val.xyz, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Any help is appreciated. Many thanks in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yeuak.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QXHjT.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/e5fgE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/EL98Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25522" PostHistoryTypeId="1" PostId="9324" RevisionGUID="6c689c82-7de3-4882-ac9a-2e5bfc3cebe4" CreationDate="2019-11-08T18:36:56.033" UserId="9438" Text="gBuffer view/eye space missing z (depth) value?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25523" PostHistoryTypeId="3" PostId="9324" RevisionGUID="6c689c82-7de3-4882-ac9a-2e5bfc3cebe4" CreationDate="2019-11-08T18:36:56.033" UserId="9438" Text="|opengl|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25524" PostHistoryTypeId="2" PostId="9325" RevisionGUID="70f7de68-6146-4d61-bfe5-76b8bfd17f88" CreationDate="2019-11-08T19:24:47.387" UserId="11316" Text="Where can I find a pseudocode to parallelize a path tracer using multiple cpu threads? How should I change the normal path tracer to be capable of parallelization?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="25525" PostHistoryTypeId="1" PostId="9325" RevisionGUID="70f7de68-6146-4d61-bfe5-76b8bfd17f88" CreationDate="2019-11-08T19:24:47.387" UserId="11316" Text="A pseudocode to parallelize a path tracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25526" PostHistoryTypeId="3" PostId="9325" RevisionGUID="70f7de68-6146-4d61-bfe5-76b8bfd17f88" CreationDate="2019-11-08T19:24:47.387" UserId="11316" Text="|raytracing|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25527" PostHistoryTypeId="2" PostId="9326" RevisionGUID="f7a8d483-727f-4eb0-9e00-9c64731df3e0" CreationDate="2019-11-08T22:07:34.623" UserId="11444" Text="Jim Blinn's book *Jim Blinn's Corner: Notation, Notation, Notation* has a couple of chapters which go through this in detail with all of the edge cases. This book is a collection of essays from his column in *IEEE Computer Graphics and Applications*. Highly recommended." ContentLicense="CC BY-SA 4.0" />
  <row Id="25528" PostHistoryTypeId="2" PostId="9327" RevisionGUID="d845fa3e-d6fc-43ef-b787-e86826d337b6" CreationDate="2019-11-08T22:30:41.123" UserId="11444" Text="It's tricky because there are 2 non-uniform scales called &quot;DataAspectRatio&quot; and &quot;PlotBoxAspectRatio&quot;. I worked through a simple case in [the answer to this post][1], but I'm afraid that doesn't cover all of the edge cases.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.mathworks.com/matlabcentral/answers/248362-screen-2d-projection-of-3d-plot" ContentLicense="CC BY-SA 4.0" />
  <row Id="25529" PostHistoryTypeId="2" PostId="9328" RevisionGUID="964d55a0-9f4f-44f0-8e82-59e714b15a95" CreationDate="2019-11-08T22:32:33.367" UserId="11445" Text="Does anyone understand normal maps and what would color a uniformly 0 normal map be? &#xD;&#xA;&#xD;&#xA;I'd like to convert a standard shader into an unlit shader, so (I think?) the idea is that the normal map should not contribute to the lighting. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25530" PostHistoryTypeId="1" PostId="9328" RevisionGUID="964d55a0-9f4f-44f0-8e82-59e714b15a95" CreationDate="2019-11-08T22:32:33.367" UserId="11445" Text="What is a 0 &quot;null&quot; normal map? Or Unlit shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="25531" PostHistoryTypeId="3" PostId="9328" RevisionGUID="964d55a0-9f4f-44f0-8e82-59e714b15a95" CreationDate="2019-11-08T22:32:33.367" UserId="11445" Text="|shader|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25532" PostHistoryTypeId="2" PostId="9329" RevisionGUID="78e436fd-c5bf-4cb8-807d-8e6912526f22" CreationDate="2019-11-08T23:54:30.297" UserId="506" Text="In the most common normal map encoding, an RGB value of (0.5,0.5,1) would be uniformly flat. If the shader is meant to be unlit, you should be able to remove anything in the code that’s using the surface normal, light / view direction, etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="25533" PostHistoryTypeId="2" PostId="9330" RevisionGUID="3cf778f7-dd1e-4fc5-a356-c41ae4248a7c" CreationDate="2019-11-09T00:00:14.923" UserId="506" Text="Updating the position/rotation/scale in the vertex buffer will use less memory bandwidth—that’s 9 values, where a transform matrix would be either 12 or 16—and the GPU can parallelize the work of turning the position/rotation/scale into a transform for the vertices. I’d go with 1." ContentLicense="CC BY-SA 4.0" />
  <row Id="25534" PostHistoryTypeId="2" PostId="9331" RevisionGUID="a7ed005a-8a72-49ff-8fc2-369e973d18c8" CreationDate="2019-11-09T00:01:53.957" UserId="11446" Text="I am working with a 1 dimensional array of an RGBA struct composed of unsigned 8-bit integers. I have implemented a very basic line algorithm, and can draw lines from one point to another accurately, **as long as they are within my 2D coordinate space**.&#xD;&#xA;&#xD;&#xA;For cases where one of my end points is outside of the range of my image, my system breaks down. I am trying to understand conceptually in computer graphics **how one might implement an infinite (or perceptually infinite) coordinate space** to take into account lines that go outside the range of my pixel array.&#xD;&#xA;&#xD;&#xA;For example, consider that my pixel array represents a 500x500 pixel space. If I draw a line from (0, 250) to (7000, 100), I would ideally like the line would be drawn to that coordinate that is out of view with the accurate slope of the line maintained." ContentLicense="CC BY-SA 4.0" />
  <row Id="25535" PostHistoryTypeId="1" PostId="9331" RevisionGUID="a7ed005a-8a72-49ff-8fc2-369e973d18c8" CreationDate="2019-11-09T00:01:53.957" UserId="11446" Text="Infinite 2D Coordinate Space" ContentLicense="CC BY-SA 4.0" />
  <row Id="25536" PostHistoryTypeId="3" PostId="9331" RevisionGUID="a7ed005a-8a72-49ff-8fc2-369e973d18c8" CreationDate="2019-11-09T00:01:53.957" UserId="11446" Text="|2d-graphics|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25540" PostHistoryTypeId="2" PostId="9333" RevisionGUID="08efe3b9-4626-44fc-b464-83b3a90001b5" CreationDate="2019-11-09T14:17:50.963" UserId="11450" Text="I'm a student in computer science and I have a project where I need to create a 3d scene with a train. I loaded the model correctly but the texture is a .mtl file.&#xD;&#xA;So I looked the official documentation and I saw the MTLLoader. The problem is it's not in three.js and I need to use the code from&#xD;&#xA; https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/MTLLoader.js &#xD;&#xA;and I have no idea how to do it. &#xD;&#xA;I tried to do an import like my teacher did in the sample of code he gave us :&#xD;&#xA; import { OBJLoader } from './threejs/OBJLoader.js';&#xD;&#xA;But it didn't work, the console told me I couldn't use THREE. in my mtl file. So I ask for help here ! Thank you&#xD;&#xA;&#xD;&#xA;PS : Sorry if I made mistakes or if I didn't use the website correctly it's the first time I post here" ContentLicense="CC BY-SA 4.0" />
  <row Id="25541" PostHistoryTypeId="1" PostId="9333" RevisionGUID="08efe3b9-4626-44fc-b464-83b3a90001b5" CreationDate="2019-11-09T14:17:50.963" UserId="11450" Text="How to use MTLLoader in THREE.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="25542" PostHistoryTypeId="3" PostId="9333" RevisionGUID="08efe3b9-4626-44fc-b464-83b3a90001b5" CreationDate="2019-11-09T14:17:50.963" UserId="11450" Text="|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25543" PostHistoryTypeId="2" PostId="9334" RevisionGUID="30418c41-043c-4ad8-8562-170389bdd17e" CreationDate="2019-11-10T11:34:18.787" UserId="11316" Text="I have written some path tracers. But some of them suffer from moire effect. Some of them look like a regular grid and some of them look like concentric circles and some of them are even more complicated. What is the best way to get rid of them completely? How are they generated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25544" PostHistoryTypeId="1" PostId="9334" RevisionGUID="30418c41-043c-4ad8-8562-170389bdd17e" CreationDate="2019-11-10T11:34:18.787" UserId="11316" Text="What is the cause of moire effect?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25545" PostHistoryTypeId="3" PostId="9334" RevisionGUID="30418c41-043c-4ad8-8562-170389bdd17e" CreationDate="2019-11-10T11:34:18.787" UserId="11316" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25546" PostHistoryTypeId="5" PostId="9334" RevisionGUID="2c24ffbf-cfbe-4810-a5f3-e5daa9fdd4e2" CreationDate="2019-11-10T12:00:16.833" UserId="11316" Comment="deleted 14 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25548" PostHistoryTypeId="5" PostId="9319" RevisionGUID="9f8b8a89-e69b-47f1-b33f-ed7e89571955" CreationDate="2019-11-10T20:48:08.917" UserId="11439" Comment="added 649 characters in body" Text="I'm working (as a Post-doc) on an archaeological excavation point cloud dataset with over 2.5 Billion points. This points come from a trench, a cuboid 10 x 10 x 3 m. Each point cloud is a layer, the gaps between are the excavated volumes. There are 444 volumes from this trench, 700 individual point clouds.&#xD;&#xA;&#xD;&#xA;Can anyone give me some direction to any deep learning algorithms which can mesh these empty spaces? I'm already doing this semi-automatically using Open3D and other python libraries, but if we could train the program to assess all the point clouds and deduce the volumes it would save us a lot of time and hopefully get better results.&#xD;&#xA;&#xD;&#xA;We excavate more trenches every year so the perfect place to test these out.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;reposted from here https://stackoverflow.com/questions/58757853/deep-learning-for-3d-point-clouds-volume-detection-and-meshing&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;To clarify the nature of the data, as requested.&#xD;&#xA;&#xD;&#xA;We gather a point cloud of the ground surface using Structure from Motion - photogrammetry. We then excavate a layer (e.g remove 10cm of soil across the trench) and record again. This process repeats until we hit bedrock, in this trench it is 3m deep. This is a vastly simplified example since we have fire pits, walls, and irregularly shaped features. each point cloud is between 1 - 20 million points, we are currently using a 1 - 10 % sample of this data and getting good results, however we would like to employ deep learning to eventually save time and produce more accurate results." ContentLicense="CC BY-SA 4.0" />
  <row Id="25549" PostHistoryTypeId="2" PostId="9336" RevisionGUID="9f3d98f1-e5b4-455f-83ae-2ddc0fb65e42" CreationDate="2019-11-11T07:50:08.310" UserId="6046" Text="So I've written a personal volume renderer which currently visualizes datasets (CT-Scans mostly) that have a `.raw` extension and the values are in the range `0-255` or `uint8`.&#xD;&#xA;&#xD;&#xA;Now I searched the net and found some datasets that had `uint16` (ranging from `0-4095`) and `float` which was arbitrary but went from like `0-20` or something. I think the `uint16` dataset corresponds to values in Hounsfield scale but I'm unsure of how do I map these to 0-255.&#xD;&#xA;&#xD;&#xA;I haven't implemented any fancy transfer functions currently. For the `uint8` datasets I just read the isovalues from the dataset and use that value for all the channels." ContentLicense="CC BY-SA 4.0" />
  <row Id="25550" PostHistoryTypeId="1" PostId="9336" RevisionGUID="9f3d98f1-e5b4-455f-83ae-2ddc0fb65e42" CreationDate="2019-11-11T07:50:08.310" UserId="6046" Text="How to handle different data types (uint8, uint16, float) in Volume Datasets?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25551" PostHistoryTypeId="3" PostId="9336" RevisionGUID="9f3d98f1-e5b4-455f-83ae-2ddc0fb65e42" CreationDate="2019-11-11T07:50:08.310" UserId="6046" Text="|volumetric|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25552" PostHistoryTypeId="5" PostId="9321" RevisionGUID="c4e9a7cc-fbb2-4121-8289-2d8f8bba5dcb" CreationDate="2019-11-11T11:52:46.520" UserId="7724" Comment="added 869 characters in body" Text="Computing exact derivatives of Gregory patches is hard due to the rational blending that occurs for the inner control points. Many people thus opt for an easier solution where the rational blending functions are first evaluated and then the resulting control points are interpreted as the control points of a standard polynomial Bézier triangle. This technique is used for instance in [ACC-2][1] to approximate the normal. This will introduce singularities at the vertices but these can easily be removed as the normal is just the vertex normal.&#xD;&#xA;&#xD;&#xA;Remember that the partial derivatives of a Bézier triangle  of degree $p$ is a Bézier triangle of degree $p-1$ where the control points in that case are vectors between the control points. As seen from the figure below you can evaluate each partial derivative as a Bézier triangle. In your case you are using just control points, but you have to use differences between control points. &#xD;&#xA;&#xD;&#xA;[![Partial derivatives as Bézier triangles][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial u} =  4 \left(B_{300} (P_{301} - P_{400}) + B_{030} (P_{031} - P_{130}) + B_{003} (P_{004} - P_{103}) +  B_{210} (P_{211} - P_{310}) +  B_{120} (P_{121} - P_{220})  +  B_{201} (P_{202} - P_{301})  +  B_{102} (P_{103} - P_{202}) +  B_{021} (P_{022} - P_{121}) +  B_{012} (P_{013} - P_{112}) +  B_{111} (P_{112} - P_{211}) \right) $$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial v} =  4 \left(B_{300} (P_{310} - P_{400}) + B_{030} (P_{040} - P_{130}) + B_{003} (P_{013} - P_{103}) +  B_{210} (P_{220} - P_{310}) +  B_{120} (P_{130} - P_{220})  +  B_{201} (P_{211} - P_{301})  +  B_{102} (P_{112} - P_{202}) +  B_{012} (P_{022} - P_{112}) +  B_{021} (P_{031} - P_{121}) +  B_{111} (P_{121} - P_{211}) \right). $$&#xD;&#xA;&#xD;&#xA;Then proceed the same way in producing the normal by the cross product of the two partial derivatives. &#xD;&#xA;&#xD;&#xA;To get some intuition about why this is this case we can look at the simpler case of a cubic Bézier curve with control points $[P_{30}, P_{21}, P_{12}, P_{03}]$&#xD;&#xA;&#xD;&#xA;$$C(u) = (1-u)^3 P_{30} + 3 (1-u)^2 u P_{21} + 3 (1-u) u^2 P_{12} + u^3 P_{03},$$&#xD;&#xA;&#xD;&#xA;if we take the derivative with respect to $u$ we obtain&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = -3 (1-u)^2 P_{30} - 6 (1-u) u P_{21} + 3 (1-u)^2 P_{21} - 3 u^2 P_{12} +  6 (1-u) u P_{12} + 3 u^2 P_{03}.$$&#xD;&#xA;&#xD;&#xA;If we then rearrange the terms we get&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = 3 \left((1-u)^2 (P_{21} - P_{30}) + 2 (1-u) u (P_{12}  - P_{21}) + u^2 ( P_{03} - P_{12})\right) .$$&#xD;&#xA;&#xD;&#xA;As you can see the derivative is a quadratic Bézier where the control points are the vectors between the control points of the initial cubic Bézier curve. This same principle holds for Bézier triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=1618497&#xD;&#xA;  [2]: https://i.stack.imgur.com/FCsiA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25553" PostHistoryTypeId="5" PostId="9321" RevisionGUID="e806785e-31e1-4044-bed0-03e1d547c0ab" CreationDate="2019-11-11T12:05:14.030" UserId="7724" Comment="added 95 characters in body" Text="Computing exact derivatives of Gregory patches is hard due to the rational blending that occurs for the inner control points. Many people thus opt for an easier solution where the rational blending functions are first evaluated and then the resulting control points are interpreted as the control points of a standard polynomial Bézier triangle. This technique is used for instance in [ACC-2][1] to approximate the normal. This will introduce singularities at the vertices due a zero denominator in the blending functions of the control points but these can easily be fixed as the normal is simply just the vertex normal at these instances.&#xD;&#xA;&#xD;&#xA;Remember that the partial derivatives of a Bézier triangle  of degree $p$ is a Bézier triangle of degree $p-1$ where the control points in that case are vectors between the control points. As seen from the figure below you can evaluate each partial derivative as a Bézier triangle. In your case you are using just control points, but you have to use differences between control points. &#xD;&#xA;&#xD;&#xA;[![Partial derivatives as Bézier triangles][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial u} =  4 \left(B_{300} (P_{301} - P_{400}) + B_{030} (P_{031} - P_{130}) + B_{003} (P_{004} - P_{103}) +  B_{210} (P_{211} - P_{310}) +  B_{120} (P_{121} - P_{220})  +  B_{201} (P_{202} - P_{301})  +  B_{102} (P_{103} - P_{202}) +  B_{021} (P_{022} - P_{121}) +  B_{012} (P_{013} - P_{112}) +  B_{111} (P_{112} - P_{211}) \right) $$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial v} =  4 \left(B_{300} (P_{310} - P_{400}) + B_{030} (P_{040} - P_{130}) + B_{003} (P_{013} - P_{103}) +  B_{210} (P_{220} - P_{310}) +  B_{120} (P_{130} - P_{220})  +  B_{201} (P_{211} - P_{301})  +  B_{102} (P_{112} - P_{202}) +  B_{012} (P_{022} - P_{112}) +  B_{021} (P_{031} - P_{121}) +  B_{111} (P_{121} - P_{211}) \right). $$&#xD;&#xA;&#xD;&#xA;Then proceed the same way in producing the normal by the cross product of the two partial derivatives. &#xD;&#xA;&#xD;&#xA;To get some intuition about why this is this case we can look at the simpler case of a cubic Bézier curve with control points $[P_{30}, P_{21}, P_{12}, P_{03}]$&#xD;&#xA;&#xD;&#xA;$$C(u) = (1-u)^3 P_{30} + 3 (1-u)^2 u P_{21} + 3 (1-u) u^2 P_{12} + u^3 P_{03},$$&#xD;&#xA;&#xD;&#xA;if we take the derivative with respect to $u$ we obtain&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = -3 (1-u)^2 P_{30} - 6 (1-u) u P_{21} + 3 (1-u)^2 P_{21} - 3 u^2 P_{12} +  6 (1-u) u P_{12} + 3 u^2 P_{03}.$$&#xD;&#xA;&#xD;&#xA;If we then rearrange the terms we get&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = 3 \left((1-u)^2 (P_{21} - P_{30}) + 2 (1-u) u (P_{12}  - P_{21}) + u^2 ( P_{03} - P_{12})\right) .$$&#xD;&#xA;&#xD;&#xA;As you can see the derivative is a quadratic Bézier where the control points are the vectors between the control points of the initial cubic Bézier curve. This same principle holds for Bézier triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=1618497&#xD;&#xA;  [2]: https://i.stack.imgur.com/FCsiA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25554" PostHistoryTypeId="2" PostId="9337" RevisionGUID="93cdac5a-b9e8-469b-980f-d9be23dfe796" CreationDate="2019-11-12T08:21:55.943" UserId="11456" Text="From what I've found, signed distance fields are not suited for minification (drawing the text on fewer pixels on screen than it covers in the texture), no matter how you mip-map them. Their main use case is magnification, and they shine here, because you don't need to increase the size of the distance field texture when the renderered object increases in size on screen.&#xD;&#xA;&#xD;&#xA;To render (e.g. text) with signed distance fields:&#xD;&#xA;&#xD;&#xA;- the texture should be large enough so that it represents the full geometric detail of the object you're trying to render. A good rule of thumb is that each line/stroke of your glyphs in the texture should be at least 2 pixels wide.&#xD;&#xA;- the object that you draw on screen with a distance field-based texture should be larger on screen that in the texture (e.g. a glyph that covers 64x64 pixels in the distance field texture should cover at least 64 pixels in each direction on screen)&#xD;&#xA;&#xD;&#xA;If those properties don't hold for your use case then better use a directly rasterized texture - not a distance field - , as those mip-map much better." ContentLicense="CC BY-SA 4.0" />
  <row Id="25555" PostHistoryTypeId="5" PostId="9336" RevisionGUID="ee4c6f0a-e88f-4d39-834d-bc0f4128453c" CreationDate="2019-11-12T11:25:33.237" UserId="6046" Comment="added 493 characters in body" Text="So I've written a personal volume renderer which currently visualizes datasets (CT-Scans mostly) that have a `.raw` extension and the values are in the range `0-255` or `uint8`.&#xD;&#xA;&#xD;&#xA;Now I searched the net and found some datasets that had `uint16` (ranging from `0-4095`) and `float` which was arbitrary but went from like `0-20` or something. I think the `uint16` dataset corresponds to values in Hounsfield scale but I'm unsure of how do I map these to 0-255.&#xD;&#xA;&#xD;&#xA;I haven't implemented any fancy transfer functions currently. For the `uint8` datasets I just read the isovalues from the dataset and use that value for all the channels.&#xD;&#xA;&#xD;&#xA;EDIT:- To clarify further, I have implemented a gpu based ray marching algorithm taking help from this site [here][1], I'm taking the datasets from [here][2], As mentioned in the comments I don't really know how you should interpret these values, but a quick read shows that normally the CT data is based on Hounsfield units which represents density afaik.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://klacansky.com/open-scivis-datasets/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25556" PostHistoryTypeId="5" PostId="9334" RevisionGUID="0ce71d5e-3b0f-4a78-a032-3fa15365e180" CreationDate="2019-11-12T14:56:37.580" UserId="11316" Comment="added 498 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25557" PostHistoryTypeId="5" PostId="9317" RevisionGUID="41e4eae3-6a31-4bd6-837c-3b5d367f697d" CreationDate="2019-11-12T15:00:04.587" UserId="11436" Comment="Updating results according to answers" Text="I am programing a tessellation shader in OpenGL which computes the [quartic Walton-Meek's Gregory patch][1]. I am searching for a local G1 method with good shading/visual results. So I am trying this patch. I didn't get good (visual/shading) results with PN-Triangles.&#xD;&#xA;&#xD;&#xA;I've just had my first result with this WM patch, which isn't good as well. Perhaps the normal I am calculating is wrong. I am following these equations to compute it:&#xD;&#xA;&#xD;&#xA;[![Bézier-Bernstein Triangle and Derivatives Equations][2]][2]&#xD;&#xA;&#xD;&#xA;Then, I actually compute it through normalizing the cross product between the derivatives (last image).&#xD;&#xA;&#xD;&#xA;If you want to take a look at the shader code, here it is (the first one is the tessellation control shader and the second one is the tessellation evaluation shader):&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout (vertices = 3) out;&#xD;&#xA;&#xD;&#xA;in VertOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;} vertOut[];&#xD;&#xA;&#xD;&#xA;out TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	const float kTessLevel = 12.0;&#xD;&#xA;	gl_TessLevelOuter[gl_InvocationID] = kTessLevel;&#xD;&#xA;	gl_TessLevelInner[0] = kTessLevel;&#xD;&#xA;&#xD;&#xA;	vec3 p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz;&#xD;&#xA;	vec3 n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;	const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;	vec3 edge = gl_in[nextInvID].gl_Position.xyz - p0;&#xD;&#xA;	vec3 nNext = vertOut[nextInvID].normal;&#xD;&#xA;	float d = length(edge), a = dot(n, nNext);&#xD;&#xA;	vec3 gama = edge / d;&#xD;&#xA;	float a0 = dot(n, gama), a1 = dot(nNext, gama);&#xD;&#xA;	float ro = 6.0 * (2.0 * a0 + a * a1)/(4.0 - a * a);&#xD;&#xA;	float sigma = 6.0 * (2.0 * a1 + a * a0)/(4.0 - a * a);&#xD;&#xA;&#xD;&#xA;	vec3 v[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		p0,&#xD;&#xA;		p0 + (d / 18.0) * (6.0 * gama - 2.0 * ro * n + sigma * nNext),&#xD;&#xA;		gl_in[nextInvID].gl_Position.xyz - (d / 18.0) * (6.0 * gama + ro * n - 2.0 * sigma * nNext),&#xD;&#xA;		edge = gl_in[nextInvID].gl_Position.xyz&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 w[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		v[1] - v[0],&#xD;&#xA;		v[2] - v[1],&#xD;&#xA;		v[3] - v[2]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 A[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		cross(n, normalize(w[0])),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		cross(nNext, normalize(w[2]))&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	A[1] = normalize(A[0] + A[2]);&#xD;&#xA;&#xD;&#xA;	vec3 l[5] = vec3[5]&#xD;&#xA;	(&#xD;&#xA;		v[0],&#xD;&#xA;		0.25 * (v[0] + 3.0 * v[1]),&#xD;&#xA;		0.25 * (2.0 * v[1] + 2.0 * v[2]),&#xD;&#xA;		0.25 * (3.0 * v[2] + v[3]),&#xD;&#xA;		v[3]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 p1 = tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;	vec3 p2 = tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;	vec3 p3 = tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;	barrier();&#xD;&#xA;&#xD;&#xA;	const int previousInvID = gl_InvocationID &gt; 0 ? gl_InvocationID - 1 : 2;&#xD;&#xA;	vec3 D[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		tescOut[previousInvID].p3 - 0.5 * (p0 + p1),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		tescOut[nextInvID].p1 - 0.5 * (p3 + tescOut[nextInvID].p0)&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	float mi[2] = float[2](dot(D[0], A[0]), dot(D[3], A[2]));&#xD;&#xA;	float lambda[2] = float[2](dot(D[0], w[0])/dot(w[0], w[0]), dot(D[3], w[2])/dot(w[2], w[2]));&#xD;&#xA;&#xD;&#xA;	tescOut[gl_InvocationID].g0 = 0.5 * (l[1] + l[2]) + (2.0/3.0) * (lambda[0] * w[1] + mi[0] * A[1]) + (1.0/3.0) * (lambda[1] * w[0] + mi[1] * A[0]);&#xD;&#xA;	tescOut[gl_InvocationID].g1 = 0.5 * (l[2] + l[3]) + (1.0/3.0) * (lambda[0] * w[2] + mi[1] * A[2]) + (2.0/3.0) * (lambda[1] * w[1] + mi[1] * A[1]);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout(triangles, equal_spacing, ccw) in;&#xD;&#xA;&#xD;&#xA;in TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;out TeseOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;	vec3 viewPosition;&#xD;&#xA;} teseOut;&#xD;&#xA;&#xD;&#xA;uniform mat4 mvp;&#xD;&#xA;uniform mat4 modelView;&#xD;&#xA;uniform mat4 normalMatrix;&#xD;&#xA;uniform bool isNormalLinearlyInterpolated;&#xD;&#xA;&#xD;&#xA;#define uvw     gl_TessCoord&#xD;&#xA;&#xD;&#xA;const float u = uvw.x, u2 = u * u, u3 = u2 * u, u4 = u2 * u2;&#xD;&#xA;const float v = uvw.y, v2 = v * v, v3 = v2 * v, v4 = v2 * v2;&#xD;&#xA;const float w = uvw.z, w2 = w * w, w3 = w2 * w, w4 = w2 * w2;&#xD;&#xA;&#xD;&#xA;#define p400	tescOut[0].p0&#xD;&#xA;#define p310	tescOut[0].p1&#xD;&#xA;#define p220	tescOut[0].p2&#xD;&#xA;#define p130	tescOut[0].p3&#xD;&#xA;#define G01		tescOut[0].g0&#xD;&#xA;#define	G02		tescOut[0].g1&#xD;&#xA;#define p040	tescOut[1].p0&#xD;&#xA;#define p031	tescOut[1].p1&#xD;&#xA;#define p022	tescOut[1].p2&#xD;&#xA;#define p013	tescOut[1].p3&#xD;&#xA;#define G11		tescOut[1].g0&#xD;&#xA;#define	G12		tescOut[1].g1&#xD;&#xA;#define p004	tescOut[2].p0&#xD;&#xA;#define p103	tescOut[2].p1&#xD;&#xA;#define p202	tescOut[2].p2&#xD;&#xA;#define p301	tescOut[2].p3&#xD;&#xA;#define G21		tescOut[2].g0&#xD;&#xA;#define	G22		tescOut[2].g1&#xD;&#xA;&#xD;&#xA;#define B400	u4&#xD;&#xA;#define B040	v4&#xD;&#xA;#define B004	w4&#xD;&#xA;#define B310	(4.0 * u3 * v)&#xD;&#xA;#define B031	(4.0 * v3 * w)&#xD;&#xA;#define B103	(4.0 * u * w3)&#xD;&#xA;#define B220	(6.0 * u2 * v2)&#xD;&#xA;#define B022	(6.0 * v2 * w2)&#xD;&#xA;#define B202	(6.0 * u2 * w2)&#xD;&#xA;#define B130	(4.0 * u * v3)&#xD;&#xA;#define B013	(4.0 * v * w3)&#xD;&#xA;#define B301	(4.0 * u3 * w)&#xD;&#xA;#define B211	(12.0 * u2 * v * w)&#xD;&#xA;#define B121	(12.0 * u * v2 * w)&#xD;&#xA;#define B112	(12.0 * u * v * w2)&#xD;&#xA;&#xD;&#xA;#define B300	u3&#xD;&#xA;#define B030	v3&#xD;&#xA;#define B003	w3&#xD;&#xA;#define B210	(3.0 * u2 * v)&#xD;&#xA;#define B021	(3.0 * v2 * w)&#xD;&#xA;#define B102	(3.0 * w2 * u)&#xD;&#xA;#define B120	(3.0 * u * v2)&#xD;&#xA;#define B012	(3.0 * v * w2)&#xD;&#xA;#define B201	(3.0 * w * u2)&#xD;&#xA;#define B111	(6.0 * u * v * w)&#xD;&#xA;&#xD;&#xA;vec3 interpolate3D(vec3 p0, vec3 p1, vec3 p2)&#xD;&#xA;{&#xD;&#xA;   	return gl_TessCoord.x * p0 + gl_TessCoord.y * p1 + gl_TessCoord.z * p2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	vec4 pos = vec4(interpolate3D(tescOut[0].p0, tescOut[1].p0, tescOut[2].p0), 1.0);&#xD;&#xA;	vec3 normal = normalize(interpolate3D(tescOut[0].n, tescOut[1].n, tescOut[2].n));&#xD;&#xA;&#xD;&#xA;	if (u != 1.0 &amp;&amp; v != 1.0 &amp;&amp; w != 1.0)&#xD;&#xA;	{&#xD;&#xA;		vec3 p211 = (v * G12 + w * G21)/(v + w);&#xD;&#xA;		vec3 p121 = (w * G02 + u * G11)/(w + u);&#xD;&#xA;		vec3 p112 = (u * G22 + v * G01)/(u + v);&#xD;&#xA;&#xD;&#xA;		vec3 barPos =	p400 * B400 +&#xD;&#xA;						p040 * B040 +&#xD;&#xA;						p004 * B004 +&#xD;&#xA;						p310 * B310 +&#xD;&#xA;						p031 * B031 +&#xD;&#xA;						p103 * B103 +&#xD;&#xA;						p220 * B220 +&#xD;&#xA;						p022 * B022 +&#xD;&#xA;						p202 * B202 +&#xD;&#xA;						p130 * B130 +&#xD;&#xA;						p013 * B013 +&#xD;&#xA;						p301 * B301 +&#xD;&#xA;						p211 * B211 +&#xD;&#xA;						p121 * B121 +&#xD;&#xA;						p112 * B112;&#xD;&#xA;&#xD;&#xA;		pos = vec4(barPos, 1.0);&#xD;&#xA;&#xD;&#xA;		vec3 dpdu =	p400 * B300 +&#xD;&#xA;					p130 * B030 +&#xD;&#xA;					p103 * B003 +&#xD;&#xA;					p310 * B210 +&#xD;&#xA;					p121 * B021 +&#xD;&#xA;					p202 * B102 +&#xD;&#xA;					p220 * B120 +&#xD;&#xA;					p112 * B012 +&#xD;&#xA;					p301 * B201 +&#xD;&#xA;					p211 * B111 ;&#xD;&#xA;&#xD;&#xA;		vec3 dpdv =	p310 * B300 +&#xD;&#xA;					p040 * B030 +&#xD;&#xA;					p013 * B003 +&#xD;&#xA;					p220 * B210 +&#xD;&#xA;					p031 * B021 +&#xD;&#xA;					p112 * B102 +&#xD;&#xA;					p130 * B120 +&#xD;&#xA;					p022 * B012 +&#xD;&#xA;					p211 * B201 +&#xD;&#xA;					p121 * B111 ;&#xD;&#xA;&#xD;&#xA;		normal = normalize(cross(dpdu, dpdv));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	gl_Position = mvp * pos;&#xD;&#xA;	pos = modelView * pos;&#xD;&#xA;	teseOut.viewPosition = pos.xyz / pos.w;&#xD;&#xA;&#xD;&#xA;	teseOut.normal = (normalMatrix * vec4(normal, 0.0)).xyz;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Some screenshots from my current results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;In the &quot;good ones&quot; images (first and third), the normals are computed by linear interpolation, while in the bad ones the normals are computed through the equations I said previously and are shown in the code.&#xD;&#xA;&#xD;&#xA;So, how can I correctly compute the normals? Thanks in advance!&#xD;&#xA;&#xD;&#xA;@edit&#xD;&#xA;&#xD;&#xA;So, I tried @Reynolds (see comment below) derivatives, but still it didn't work properly, unfortunately. These are the results: [![New results][7]][7]&#xD;&#xA;&#xD;&#xA;Results at the left (the dark ones) are using the code below and the ones at the right are flipping the normal (i.e., -normalize(cross(dpdu,dpdv)). The code:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;vec3 dpdu = 4.0 * (B300 * (p301 - p400) + B030 * (p031 - p130) + B003 * (p004 - p103) + B210 * (p211 - p310) +&#xD;&#xA;					B120 * (p121 - p220) + B201 * (p202 - p301) + B102 * (p103 - p202) + B021 * (p022 - p121) +&#xD;&#xA;					B012 * (p013 - p112) + B111 * (p112 - p211));&#xD;&#xA;		&#xD;&#xA;vec3 dpdv = 4.0 * (B300 * (p310 - p400) + B030 * (p040 - p130) + B003 * (p013 - p103) + B210 * (p220 - p310) +&#xD;&#xA;					B120 * (p130 - p220) + B201 * (p211 - p301) + B102 * (p112 - p202) + B012 * (p022 - p112) +&#xD;&#xA;					B021 * (p031 - p121) + B111 * (p121 - p211));&#xD;&#xA;normal = normalize(cross(dpdu, dpdv)); // -normalize(cross(dpdu, dpdv));&#xD;&#xA;```&#xD;&#xA;Any ideas?? Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://reader.elsevier.com/reader/sd/pii/0010448595000461?token=4190E80EF50B0C8E2FB4EADFFEF26DF93ACEDF3AED59AA6B97D59B2C1FC52B0B965B255B27749ECC11F49B44C1610688&#xD;&#xA;  [2]: https://i.stack.imgur.com/AQq0v.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/YIW42.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7bfza.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/5rw2D.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/a1MBK.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/d26TV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25558" PostHistoryTypeId="50" PostId="9234" RevisionGUID="ec87a12c-05a5-47ab-9134-0aa88244480c" CreationDate="2019-11-12T15:02:25.377" UserId="-1" />
  <row Id="25559" PostHistoryTypeId="5" PostId="9334" RevisionGUID="9ee8864c-2de0-4398-b0f6-5fdbc814f9db" CreationDate="2019-11-12T15:06:33.827" UserId="11316" Comment="added 498 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25560" PostHistoryTypeId="2" PostId="9338" RevisionGUID="32fbf5c3-3584-4c23-b429-73666a240196" CreationDate="2019-11-12T15:30:47.943" UserId="11436" Text="It seems you want to work with values between 0-255. For uint16 datasets, you can put it inside 0-255 range like this:&#xD;&#xA;&#xD;&#xA;$newValue = 255 * \frac{oldValue}{(2^{16} - 1)}$&#xD;&#xA;&#xD;&#xA;where $oldValue$ is an uint16 value and $2^{16} - 1$ is the uint16 max number. For the float ones without any previous knowledge about its range, you could read all the values from the dataset in order to find out the min and the max values. Then, you could map this way:&#xD;&#xA;&#xD;&#xA;$newValue = 255 * \frac{oldValue - min}{max - min}$&#xD;&#xA;&#xD;&#xA;The key idea is to map first to range 0-1 and then map it to 0-255 by multiplying it by 255. Don't forget to round/ceil/floor your value as you want an integer, not a float number." ContentLicense="CC BY-SA 4.0" />
  <row Id="25561" PostHistoryTypeId="2" PostId="9339" RevisionGUID="8f08cb0a-df77-430c-a201-2d58616eb472" CreationDate="2019-11-12T15:33:48.253" UserId="11458" Text="Hi i am rather new to computergraphics but i am trying to map an equirectangular image (360 video) to the inside of a sphere now i found the following formula to do this. &#xD;&#xA;&#xD;&#xA;    phi = 2*Pi*u&#xD;&#xA;    cos(theta) = 2*v -1&#xD;&#xA;&#xD;&#xA;But how do i get `u` and `v` ? In the article he talks about this: &#xD;&#xA;&gt;So we can just project the sphere points in the xy plane onto the unit radius cylinder and unwrap it!   If we have such an image with texture coordinates (u,v) in [0,1]^2&#xD;&#xA;&#xD;&#xA;But how do i get those texture coordinates from and image with lets say the following dimensions 4096x2048 pixels?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Sorry if this is a bit vague, i am trying to understand it myself. If clarification is needed i am happy to edit my question!" ContentLicense="CC BY-SA 4.0" />
  <row Id="25562" PostHistoryTypeId="1" PostId="9339" RevisionGUID="8f08cb0a-df77-430c-a201-2d58616eb472" CreationDate="2019-11-12T15:33:48.253" UserId="11458" Text="convert image pixel dimensions to UV" ContentLicense="CC BY-SA 4.0" />
  <row Id="25563" PostHistoryTypeId="3" PostId="9339" RevisionGUID="8f08cb0a-df77-430c-a201-2d58616eb472" CreationDate="2019-11-12T15:33:48.253" UserId="11458" Text="|texture|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25564" PostHistoryTypeId="5" PostId="9334" RevisionGUID="3479bf5d-1141-4dc8-af56-a94c9db89c04" CreationDate="2019-11-12T15:42:45.557" UserId="11316" Comment="added 402 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;&#xD;&#xA;EDIT 2: I think I shouldn't use ceiling function, instead it is better to set a threshold ($\tau = 1e-4$). For every point with distance from the borders of each rectangle less than this threshold, I consider that this point belongs to a rectangle of its neighbour rectangle randomly. Am I correct? I still don't know how to overcome this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25565" PostHistoryTypeId="2" PostId="9340" RevisionGUID="0afe3676-aa36-4a5e-bdcf-af41ae528077" CreationDate="2019-11-12T15:55:46.733" UserId="7008" Text="UV coordinates are defined such that (0, 0) is your lower left (or upper left, depending on what you're working with) corner of the image and (1, 1) the opposite corner (technically (1, 1) is outside the UV range, but we ignore this for easiness sake). Thus, if you want the exact middle, you obviously get (0.5, 0.5)&#xD;&#xA;&#xD;&#xA;Now with your image, the first pixel lower left is the pixel at (0, 0) as well. The pixel in the opposite corner is (4095, 2047). &#xD;&#xA;To get to the (1, 1) corner, you need to take that corner pixel and divide it's coordinates by the image's width and height respectively. here you will see, that the (1, 1) does not fit exactly:&#xD;&#xA;&#xD;&#xA;$u = 4095 / 4096 = 0.99976$&#xD;&#xA;$v = 2047 / 2048 = 0.99951$&#xD;&#xA;&#xD;&#xA;The same principle applies to any other pixel of your image, you just have to divide by the image's width in pixels.&#xD;&#xA;Your center pixel is at (2047, 1023) (or the image borders on this pixel and three of its neighbours). The resulting UVs are:&#xD;&#xA;&#xD;&#xA;$u = 2047 / 4096 = 0.49975$&#xD;&#xA;$v = 1023 / 2048 = 0.49951$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25566" PostHistoryTypeId="5" PostId="9336" RevisionGUID="e0a85f90-f65c-4fb2-8f34-12c871542dfc" CreationDate="2019-11-12T16:07:28.330" UserId="6046" Comment="added 45 characters in body" Text="So I've written a personal volume renderer which currently visualizes datasets (CT-Scans mostly) that have a `.raw` extension and the values are in the range `0-255` or `uint8`.&#xD;&#xA;&#xD;&#xA;Now I searched the net and found some datasets that had `uint16` (ranging from `0-4095`) and `float` which was arbitrary but went from like `0-20` or something. I think the `uint16` dataset corresponds to values in Hounsfield scale but I'm unsure of how do I map these to 0-255.&#xD;&#xA;&#xD;&#xA;I haven't implemented any fancy transfer functions currently. For the `uint8` datasets I just read the isovalues from the dataset and use that value for all the channels (r,g,b) as it is giving me a grayscale image.&#xD;&#xA;&#xD;&#xA;EDIT:- To clarify further, I have implemented a gpu based ray marching algorithm taking help from this site [here][1], I'm taking the datasets from [here][2], As mentioned in the comments I don't really know how you should interpret these values, but a quick read shows that normally the CT data is based on Hounsfield units which represents density afaik.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;  [2]: https://klacansky.com/open-scivis-datasets/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25567" PostHistoryTypeId="5" PostId="9321" RevisionGUID="5fbdc346-f375-4c13-8570-525bc4dbb30e" CreationDate="2019-11-12T16:08:08.847" UserId="7724" Comment="deleted 19 characters in body" Text="Computing exact derivatives of Gregory patches is hard due to the rational blending that occurs for the inner control points. Many people thus opt for an easier solution where the rational blending functions are first evaluated and then the resulting control points are interpreted as the control points of a standard polynomial Bézier triangle. This technique is used for instance in [ACC-2][1] to approximate the normal. This will introduce singularities at the vertices due a zero denominator in the blending functions of the control points but these can easily be fixed as the normal is simply just the vertex normal at these instances.&#xD;&#xA;&#xD;&#xA;Remember that the partial derivatives of a Bézier triangle  of degree $p$ is a Bézier triangle of degree $p-1$ where the control points in that case are vectors between the control points. As seen from the figure below you can evaluate each partial derivative as a Bézier triangle. In your case you are using just control points, but you have to use differences between control points. &#xD;&#xA;&#xD;&#xA;[![cubic derivatives][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial u} =  4 \left(B_{300} (P_{400} - P_{301}) + B_{030} (P_{130} - P_{031}) + B_{003} (P_{103} - P_{004} ) +  B_{210} ( P_{310} - P_{211} ) +  B_{120} (P_{220} - P_{121})  +  B_{201} (P_{301} - P_{202})  +  B_{102} (P_{202} - P_{103}) +  B_{021} (P_{121} - P_{022}) +  B_{012} (P_{112} - P_{013}) +  B_{111} (P_{211} - P_{112}) \right) $$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial v} =  4 \left(B_{300} (P_{310} - P_{310}) + B_{030} (P_{040} - P_{031}) + B_{003} (P_{013} - P_{004}) +  B_{210} (P_{220} - P_{211}) +  B_{120} (P_{130} - P_{121})  +  B_{201} (P_{211} - P_{202})  +  B_{102} (P_{112} - P_{103}) +  B_{012} (P_{022} - P_{013}) +  B_{021} (P_{031} - P_{022}) +  B_{111} (P_{121} - P_{112}) \right). $$&#xD;&#xA;&#xD;&#xA;Then proceed the same way in producing the normal by the cross product of the two partial derivatives. &#xD;&#xA;&#xD;&#xA;To get some intuition about why this is this case we can look at the simpler case of a cubic Bézier curve with control points $[P_{30}, P_{21}, P_{12}, P_{03}]$&#xD;&#xA;&#xD;&#xA;$$C(u) = (1-u)^3 P_{30} + 3 (1-u)^2 u P_{21} + 3 (1-u) u^2 P_{12} + u^3 P_{03},$$&#xD;&#xA;&#xD;&#xA;if we take the derivative with respect to $u$ we obtain&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = -3 (1-u)^2 P_{30} - 6 (1-u) u P_{21} + 3 (1-u)^2 P_{21} - 3 u^2 P_{12} +  6 (1-u) u P_{12} + 3 u^2 P_{03}.$$&#xD;&#xA;&#xD;&#xA;If we then rearrange the terms we get&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = 3 \left((1-u)^2 (P_{21} - P_{30}) + 2 (1-u) u (P_{12}  - P_{21}) + u^2 ( P_{03} - P_{12})\right) .$$&#xD;&#xA;&#xD;&#xA;As you can see the derivative is a quadratic Bézier where the control points are the vectors between the control points of the initial cubic Bézier curve. This same principle holds for Bézier triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=1618497&#xD;&#xA;  [2]: https://i.stack.imgur.com/4dxSV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25568" PostHistoryTypeId="5" PostId="9334" RevisionGUID="6104b86d-3c37-4c77-8f25-8bdeea71ad0d" CreationDate="2019-11-12T16:08:52.880" UserId="11316" Comment="deleted 205 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;&#xD;&#xA;EDIT 2: I sample primary rays randomly in each pixel without jittering. Is it the cause of moire effect? Do I have to use stratified sampling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25569" PostHistoryTypeId="5" PostId="9321" RevisionGUID="ac94c5f8-9f5d-4dd2-9654-dbd1bd089662" CreationDate="2019-11-12T16:16:38.137" UserId="7724" Comment="edited body" Text="Computing exact derivatives of Gregory patches is hard due to the rational blending that occurs for the inner control points. Many people thus opt for an easier solution where the rational blending functions are first evaluated and then the resulting control points are interpreted as the control points of a standard polynomial Bézier triangle. This technique is used for instance in [ACC-2][1] to approximate the normal. This will introduce singularities at the vertices due a zero denominator in the blending functions of the control points but these can easily be fixed as the normal is simply just the vertex normal at these instances.&#xD;&#xA;&#xD;&#xA;Remember that the partial derivatives of a Bézier triangle  of degree $p$ is a Bézier triangle of degree $p-1$ where the control points in that case are vectors between the control points. As seen from the figure below you can evaluate each partial derivative as a Bézier triangle. In your case you are using just control points, but you have to use differences between control points. &#xD;&#xA;&#xD;&#xA;[![cubic derivatives][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial u} =  4 \left(B_{300} (P_{400} - P_{301}) + B_{030} (P_{130} - P_{031}) + B_{003} (P_{103} - P_{004} ) +  B_{210} ( P_{310} - P_{211} ) +  B_{120} (P_{220} - P_{121})  +  B_{201} (P_{301} - P_{202})  +  B_{102} (P_{202} - P_{103}) +  B_{021} (P_{121} - P_{022}) +  B_{012} (P_{112} - P_{013}) +  B_{111} (P_{211} - P_{112}) \right) $$&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;$$\frac{\partial P}{\partial v} =  4 \left(B_{300} (P_{310} - P_{301}) + B_{030} (P_{040} - P_{031}) + B_{003} (P_{013} - P_{004}) +  B_{210} (P_{220} - P_{211}) +  B_{120} (P_{130} - P_{121})  +  B_{201} (P_{211} - P_{202})  +  B_{102} (P_{112} - P_{103}) +  B_{012} (P_{022} - P_{013}) +  B_{021} (P_{031} - P_{022}) +  B_{111} (P_{121} - P_{112}) \right). $$&#xD;&#xA;&#xD;&#xA;Then proceed the same way in producing the normal by the cross product of the two partial derivatives. &#xD;&#xA;&#xD;&#xA;To get some intuition about why this is this case we can look at the simpler case of a cubic Bézier curve with control points $[P_{30}, P_{21}, P_{12}, P_{03}]$&#xD;&#xA;&#xD;&#xA;$$C(u) = (1-u)^3 P_{30} + 3 (1-u)^2 u P_{21} + 3 (1-u) u^2 P_{12} + u^3 P_{03},$$&#xD;&#xA;&#xD;&#xA;if we take the derivative with respect to $u$ we obtain&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = -3 (1-u)^2 P_{30} - 6 (1-u) u P_{21} + 3 (1-u)^2 P_{21} - 3 u^2 P_{12} +  6 (1-u) u P_{12} + 3 u^2 P_{03}.$$&#xD;&#xA;&#xD;&#xA;If we then rearrange the terms we get&#xD;&#xA;&#xD;&#xA;$$\frac{\partial C(u)}{\partial u} = 3 \left((1-u)^2 (P_{21} - P_{30}) + 2 (1-u) u (P_{12}  - P_{21}) + u^2 ( P_{03} - P_{12})\right) .$$&#xD;&#xA;&#xD;&#xA;As you can see the derivative is a quadratic Bézier where the control points are the vectors between the control points of the initial cubic Bézier curve. This same principle holds for Bézier triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/citation.cfm?id=1618497&#xD;&#xA;  [2]: https://i.stack.imgur.com/4dxSV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25570" PostHistoryTypeId="2" PostId="9341" RevisionGUID="459f28d5-ddf6-450d-a5cf-84ee36e06fd7" CreationDate="2019-11-12T17:38:12.727" UserId="11459" Text="I'm out of my wits. I've been working an a voxel game for the last couple of years, written in C# and OpenTK (=OpenGL backend)&#xD;&#xA;&#xD;&#xA;I've been struggling to achieve a stable frame rate and one of the major issues I can see after countless hours of frame profiling, is that the windows 10 nvidia graphics driver seems to act in some really strange ways.&#xD;&#xA;&#xD;&#xA;It almost seems as if my card is in some sort of low power mode by default in which it renders at arbitrarily changing speeds, but once its put under load it renders reliably again.&#xD;&#xA;&#xD;&#xA;I can reliably reproduce this by launching my game with non-demanding graphics setting, then up the GPU load with dynamic shadows, god rays and such, then lowering the demands again.&#xD;&#xA;&#xD;&#xA;This is all with VSync enabled (and in the nvidia control panel the vsync option is set to &quot;Let the application decide&quot;)&#xD;&#xA;&#xD;&#xA;Here are some frame rate graphs:&#xD;&#xA;&#xD;&#xA;Low gpu load, draw calls randomly take a few milliseconds longer, then it almost seems to overcompensate by drawing the next frame too fast.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I increase the gpu load for a few seconds and lower it again. The frame rate gets buttery smooth:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As mentioned I carefully profiled this issue and it always seems that the time is spend on various draw calls (usually GLMultiDrawElements), but highly inconsistent.&#xD;&#xA;&#xD;&#xA;Anyone have an idea what the heck is going on here and how I can fix this?&#xD;&#xA;&#xD;&#xA;Is there any call I could make to NVAPI to force it into this hypothetical high power mode?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/odOeA.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/nLDtH.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25571" PostHistoryTypeId="1" PostId="9341" RevisionGUID="459f28d5-ddf6-450d-a5cf-84ee36e06fd7" CreationDate="2019-11-12T17:38:12.727" UserId="11459" Text="Strange VSync issues on a GTX 1060" ContentLicense="CC BY-SA 4.0" />
  <row Id="25572" PostHistoryTypeId="3" PostId="9341" RevisionGUID="459f28d5-ddf6-450d-a5cf-84ee36e06fd7" CreationDate="2019-11-12T17:38:12.727" UserId="11459" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25573" PostHistoryTypeId="2" PostId="9342" RevisionGUID="74cc4476-c0b8-4604-ac06-9c6b0d50155b" CreationDate="2019-11-12T20:11:00.063" UserId="11459" Text="Ok so setting the &quot;power management mode&quot; to &quot;prefer maximum performance&quot; in the nvidia control panel seems to fix it. &#xD;&#xA;&#xD;&#xA;Since I already create an optimus profile automatically through code all I had to do was to set this value as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="25574" PostHistoryTypeId="5" PostId="9334" RevisionGUID="599becb1-6521-481b-bc30-4a62135800b8" CreationDate="2019-11-13T04:55:31.307" UserId="11316" Comment="added 1231 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;&#xD;&#xA;EDIT 2: I sample primary rays randomly in each pixel without jittering. Is it the cause of moire effect? Do I have to use stratified sampling?&#xD;&#xA;&#xD;&#xA;EDIT 3: I have to show some parts of code:&#xD;&#xA;This function generates a ray inside patches on sphere:&#xD;&#xA;&#xD;&#xA;    function Q_dir(ith::Int64)&#xD;&#xA;        i = ceil(Int64, ith/H)&#xD;&#xA;        j = ith - H*(i-1)&#xD;&#xA;        u = (i-rand())/V&#xD;&#xA;        ϕ = 2π*(j-rand())/H&#xD;&#xA;        return Vec3(cos(ϕ)*sqrt(1.0 - u*u), sin(ϕ)*sqrt(1.0 - u*u), u)&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;This function returns the index of a rectangular cell on each plane which contains the hit point:&#xD;&#xA;&#xD;&#xA;    function find_state(a::Float64, a1::Float64, a2::Float64, b::Float64, b1::Float64, b2::Float64)&#xD;&#xA;        return [ceil(Int64, M*(abs(a)/(a2-a1))),   ceil(Int64, N*(abs(b)/(b2-b1)))]&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;Ant this intersection function, returns the hit point and the cell&#xD;&#xA;&#xD;&#xA;    function intersect!(plane::xzPlane, ray::Ray)&#xD;&#xA;        x1 = plane.a1&#xD;&#xA;        x2 = plane.a2&#xD;&#xA;        z1 = plane.b1&#xD;&#xA;        z2 = plane.b2&#xD;&#xA;        t = (plane.y - ray.org.y)/ray.dir.y&#xD;&#xA;        point = ray.org + t*ray.dir&#xD;&#xA;        if x1 &lt; point.x &lt; x2 &amp;&amp; z1 &lt; point.z &lt; z2 &amp;&amp; 0 &lt; t&#xD;&#xA;            hsect, wsect = find_state(point.x, x1, x2, point.z, z1, z2)&#xD;&#xA;            normal = Vec3(0,1,0)&#xD;&#xA;            return HitPoint(t, point , normal, hsect, wsect)&#xD;&#xA;        else&#xD;&#xA;            return HitPoint()&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;The problem is surely related to this parts, because I can reproduce the results of the paper. My only problem is this artifact.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25575" PostHistoryTypeId="5" PostId="9334" RevisionGUID="940f1aa9-ba3a-4f83-8656-a1437641ca70" CreationDate="2019-11-13T09:06:42.267" UserId="11316" Comment="added 243 characters in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;&#xD;&#xA;EDIT 2: I sample primary rays randomly in each pixel without jittering. Is it the cause of moire effect? Do I have to use stratified sampling?&#xD;&#xA;&#xD;&#xA;EDIT 3: I have to show some parts of code:&#xD;&#xA;This function generates a ray inside patches on sphere:&#xD;&#xA;&#xD;&#xA;    function Q_dir(ith::Int64)&#xD;&#xA;        i = ceil(Int64, ith/H)&#xD;&#xA;        j = ith - H*(i-1)&#xD;&#xA;        u = (i-rand())/V&#xD;&#xA;        ϕ = 2π*(j-rand())/H&#xD;&#xA;        return Vec3(cos(ϕ)*sqrt(1.0 - u*u), sin(ϕ)*sqrt(1.0 - u*u), u)&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;This function returns the index of a rectangular cell on each plane which contains the hit point:&#xD;&#xA;&#xD;&#xA;    function find_state(a::Float64, a1::Float64, a2::Float64, b::Float64, b1::Float64, b2::Float64)&#xD;&#xA;        return [ceil(Int64, M*(abs(a)/(a2-a1))),   ceil(Int64, N*(abs(b)/(b2-b1)))]&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;Ant this intersection function, returns the hit point and the cell&#xD;&#xA;&#xD;&#xA;    function intersect!(plane::xzPlane, ray::Ray)&#xD;&#xA;        x1 = plane.a1&#xD;&#xA;        x2 = plane.a2&#xD;&#xA;        z1 = plane.b1&#xD;&#xA;        z2 = plane.b2&#xD;&#xA;        t = (plane.y - ray.org.y)/ray.dir.y&#xD;&#xA;        point = ray.org + t*ray.dir&#xD;&#xA;        if x1 &lt; point.x &lt; x2 &amp;&amp; z1 &lt; point.z &lt; z2 &amp;&amp; 0 &lt; t&#xD;&#xA;            hsect, wsect = find_state(point.x, x1, x2, point.z, z1, z2)&#xD;&#xA;            normal = Vec3(0,1,0)&#xD;&#xA;            return HitPoint(t, point , normal, hsect, wsect)&#xD;&#xA;        else&#xD;&#xA;            return HitPoint()&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;The problem is surely related to this parts, because I can reproduce the results of the paper. My only problem is this artifact.&#xD;&#xA;&#xD;&#xA;EDIT 4: When I generate a ray uniformly through each uniformly selected stratum, everything works fine. But when I generate a ray uniformly through importance sampled stratum (each stratum has a different value), I encounter this problem. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25576" PostHistoryTypeId="2" PostId="9343" RevisionGUID="9ac7c63e-bd39-4596-90e9-1ebba1092072" CreationDate="2019-11-13T16:08:05.587" UserId="310" Text="In PBRT, a BSDF is represented as an array of BxDF lobes. Each lobe sets a bitflag representing what kind of lobe it is. (Specular, Diffuse, Reflection, Transmission, etc.) I'm investigating how PBRT implemented sampling a BSDF for an input direction, wi.&#xD;&#xA;&#xD;&#xA;Following standard Monte Carlo sampling, I was expecting the code to randomly sample an appropriate lobe, then set the $pdf = pdf_{picked}/n$ where $n$ is the number of lobes of the appropriate type. However this isn't what PBRT does. My question is why? To go in futher, this is the PBRT function:&#xD;&#xA;&#xD;&#xA;    Spectrum BSDF::Sample_f(const Vector3f &amp;woWorld, Vector3f *wiWorld,&#xD;&#xA;                            const Point2f &amp;u, Float *pdf, BxDFType type,&#xD;&#xA;                            BxDFType *sampledType) const {&#xD;&#xA;        // Choose which _BxDF_ to sample&#xD;&#xA;        int matchingComps = NumComponents(type);&#xD;&#xA;        if (matchingComps == 0) {&#xD;&#xA;            *pdf = 0;&#xD;&#xA;            if (sampledType)&#xD;&#xA;                *sampledType = BxDFType(0);&#xD;&#xA;            return Spectrum(0);&#xD;&#xA;        }&#xD;&#xA;        int comp = std::min((int)std::floor(u[0] * matchingComps), matchingComps - 1);&#xD;&#xA;    &#xD;&#xA;        // Get _BxDF_ pointer for chosen component&#xD;&#xA;        BxDF *bxdf = nullptr;&#xD;&#xA;        int count = comp;&#xD;&#xA;        for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;            if (bxdfs[i]-&gt;MatchesFlags(type) &amp;&amp; count-- == 0) {&#xD;&#xA;                bxdf = bxdfs[i];&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        // Remap _BxDF_ sample _u_ to $[0,1)^2$&#xD;&#xA;        Point2f uRemapped(std::min(u[0] * matchingComps - comp, OneMinusEpsilon),&#xD;&#xA;                          u[1]);&#xD;&#xA;    &#xD;&#xA;        // Sample chosen _BxDF_&#xD;&#xA;        Vector3f wi, wo = WorldToLocal(woWorld);&#xD;&#xA;        if (wo.z == 0)&#xD;&#xA;            return 0.;&#xD;&#xA;        *pdf = 0;&#xD;&#xA;        if (sampledType) *sampledType = bxdf-&gt;type;&#xD;&#xA;        Spectrum f = bxdf-&gt;Sample_f(wo, &amp;wi, uRemapped, pdf, sampledType);&#xD;&#xA;    &#xD;&#xA;        if (*pdf == 0) {&#xD;&#xA;            if (sampledType) *sampledType = BxDFType(0);&#xD;&#xA;            return 0;&#xD;&#xA;        }&#xD;&#xA;        *wiWorld = LocalToWorld(wi);&#xD;&#xA;    &#xD;&#xA;        // Compute overall PDF with all matching _BxDF_s&#xD;&#xA;        if (!(bxdf-&gt;type &amp; BSDF_SPECULAR) &amp;&amp; matchingComps &gt; 1)&#xD;&#xA;            for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;                if (bxdfs[i] != bxdf &amp;&amp; bxdfs[i]-&gt;MatchesFlags(type))&#xD;&#xA;                    *pdf += bxdfs[i]-&gt;Pdf(wo, wi);&#xD;&#xA;        if (matchingComps &gt; 1)&#xD;&#xA;            *pdf /= matchingComps;&#xD;&#xA;    &#xD;&#xA;        // Compute value of BSDF for sampled direction&#xD;&#xA;        if (!(bxdf-&gt;type &amp; BSDF_SPECULAR)) {&#xD;&#xA;            bool reflect = Dot(*wiWorld, ng) * Dot(woWorld, ng) &gt; 0;&#xD;&#xA;            f = 0.;&#xD;&#xA;            for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;                if (bxdfs[i]-&gt;MatchesFlags(type) &amp;&amp;&#xD;&#xA;                    ((reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_REFLECTION)) ||&#xD;&#xA;                     (!reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_TRANSMISSION))))&#xD;&#xA;                    f += bxdfs[i]-&gt;f(wo, wi);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        return f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In pseudo-code, it looks to be doing the following:&#xD;&#xA;&#xD;&#xA;    // Get the number of lobes that match the ones we asked for&#xD;&#xA;    numMatchingLobes = NumComponents(type);&#xD;&#xA;    &#xD;&#xA;    // Early out check&#xD;&#xA;    if (numMatchingLobes == 0):&#xD;&#xA;        return&#xD;&#xA;    &#xD;&#xA;    // Randomly pick one of the matching lobes&#xD;&#xA;    pickedBxDF = Rand()&#xD;&#xA;    &#xD;&#xA;    // Transform wo from world space to local space&#xD;&#xA;    // Then sample the chosen BxDF to get f, pdf, and wi&#xD;&#xA;    f, pdf, wi = pickedBxDF.sample_f(woWorld.ToLocal())&#xD;&#xA;    &#xD;&#xA;    // Early out check&#xD;&#xA;    if (pdf == 0):&#xD;&#xA;        return&#xD;&#xA;    &#xD;&#xA;    // Transform wi to world space&#xD;&#xA;    wiWorld = wi.ToWorld()&#xD;&#xA;    &#xD;&#xA;    // Add all of the pdfs of the matching lobes if the picked BxDF wasn't specular&#xD;&#xA;    if pickedBxDF.type not Specular &amp;&amp; numMatchingLobes &gt; 1:&#xD;&#xA;        for BxDF in matchingLobes:&#xD;&#xA;            pdf += BxDF.pdf(wi, wo)&#xD;&#xA;    &#xD;&#xA;    // Divide the resulting pdf by the number of matching lobes&#xD;&#xA;    pdf /= numMatchingLobes;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Calculate the combined f if the picked BxDF isn't specular&#xD;&#xA;    if pickedBxDF.type not Specular:&#xD;&#xA;        // Reset f to zero&#xD;&#xA;        f = 0&#xD;&#xA;        &#xD;&#xA;        // Add each BxDF's f, iff it matches reflection / transmission&#xD;&#xA;        reflect = wo and wi on same hemisphere as geoNormal&#xD;&#xA;        for BxDF in matchingLobes:&#xD;&#xA;            // Add the &#xD;&#xA;            if reflect and BxDF.type == Reflection:&#xD;&#xA;                f += BxDF.f(wo, wi)&#xD;&#xA;            elif !reflect and BxDF.type == Transmission:&#xD;&#xA;                f += BxDF.f(wo, wi)&#xD;&#xA;&#xD;&#xA;The part I'm not understanding is why it adds the pdf's of all the matching lobes on top of the already calculated pdf. This seems like it would double count the pdf of the picked lobe.&#xD;&#xA;&#xD;&#xA;For example, if there are two matching lobes, called A and B. A is picked.&#xD;&#xA;&#xD;&#xA;We calculate f, pdf, and wi with A. Then with a for loop, we add the pdf for A and B and divide by 2. Aka:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{A + A + B}{2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This doesn't seem right. Is PBRT code wrong? Should it be resetting the pdf, similar to the f calculation code below it?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25577" PostHistoryTypeId="1" PostId="9343" RevisionGUID="9ac7c63e-bd39-4596-90e9-1ebba1092072" CreationDate="2019-11-13T16:08:05.587" UserId="310" Text="How to calculate the PDF of a multi-lobe BSDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="25578" PostHistoryTypeId="3" PostId="9343" RevisionGUID="9ac7c63e-bd39-4596-90e9-1ebba1092072" CreationDate="2019-11-13T16:08:05.587" UserId="310" Text="|sampling|monte-carlo|bsdf|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25580" PostHistoryTypeId="5" PostId="4994" RevisionGUID="7380a296-33a1-4627-bdbc-61c6930b8fc4" CreationDate="2019-11-13T20:00:45.940" UserId="310" Comment="deleted 9 characters in body" Text="Short answer:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;**Importance sampling** is a method to reduce variance in Monte Carlo Integration by choosing an estimator close to the shape of the actual function.&#xD;&#xA;&#xD;&#xA;**PDF** is an abbreviation for [Probability Density Function][1]. A $pdf(x)$ gives the probability of a random sample generated being $x$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Long Answer:&#xD;&#xA;=====&#xD;&#xA;&#xD;&#xA;To start, let's review what Monte Carlo Integration is, and what it looks like mathematically. &#xD;&#xA;&#xD;&#xA;Monte Carlo Integration is an technique to estimate the value of an integral. It's typically used when there isn't a closed form solution to the integral. It looks like this:&#xD;&#xA;&#xD;&#xA;$$\int f(x) \, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;In english, this says that you can approximate an integral by averaging successive random samples from the function. As $N$ gets large, the approximation gets closer and closer to the solution. $pdf(x_{i})$ represents the probability density function of each random sample.&#xD;&#xA;&#xD;&#xA;Let's do an example: Calculate the value of the integral $I$.&#xD;&#xA;&#xD;&#xA;$$I = \int_{0}^{2\pi} e^{-x} \sin(x) dx$$&#xD;&#xA;&#xD;&#xA;Let's use Monte Carlo Integration:&#xD;&#xA;&#xD;&#xA;$$I \approx \frac{1}{N} \sum_{i=1}^N \frac{e^{-x} \sin(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;A simple python program to calculate this is:&#xD;&#xA;&#xD;&#xA;    import random&#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    N = 200000&#xD;&#xA;    TwoPi = 2.0 * math.pi&#xD;&#xA;&#xD;&#xA;    sum = 0.0&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;        x = random.uniform(0, TwoPi)&#xD;&#xA;        &#xD;&#xA;        fx = math.exp(-x) * math.sin(x)&#xD;&#xA;        pdf = 1 / (TwoPi - 0.0)&#xD;&#xA;        &#xD;&#xA;        sum += fx / pdf&#xD;&#xA;&#xD;&#xA;    I = (1 / N) * sum&#xD;&#xA;    print(I)&#xD;&#xA;&#xD;&#xA;If we run the program we get $I = 0.4986941$&#xD;&#xA;&#xD;&#xA;Using separation by parts, we can get the exact solution:&#xD;&#xA;&#xD;&#xA;$$I = \frac{1}{2} (1 − e−2π) = 0.4990663$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You'll notice that the Monte Carlo Solution is not quite correct. This is because it is an estimate. That said, as $N$ goes to infinity, the estimate should get closer and closer to the correct answer. Already at $N = 2000$ some runs are almost identical to the correct answer.&#xD;&#xA;&#xD;&#xA;A note about the PDF: In this simple example, we always take a uniform random sample. A uniform random sample means every sample has the exact same probability of being chosen. We sample in the range $[0, 2\pi]$ so, $pdf(x) = 1 / (2\pi - 0)$&#xD;&#xA;&#xD;&#xA;Importance sampling works by *not* uniformly sampling. Instead we try to choose more samples that contribute a lot to the result (important), and less samples that only contribute a little to the result (less important). Hence the name, importance sampling.&#xD;&#xA;&#xD;&#xA;If you choose a sampling function whose pdf very closely matches the shape of $f$, you can greatly reduce the variance, which means you can take less samples. However, if you choose a sampling function whose value is very different from $f$, you can ***increase*** the variance. See the picture below:&#xD;&#xA;[![Comparison of good sampling vs bad sampling][2]][2]&#xD;&#xA;Image from Wojciech Jarosz's [Dissertation Appendix A][3]&#xD;&#xA;&#xD;&#xA;One example of importance sampling in Path Tracing is how to choose the direction of a ray after it hits a surface. If the surface is not perfectly specular (ie. a mirror or glass), the outgoing ray can be anywhere in the hemisphere.&#xD;&#xA;&#xD;&#xA;[![Outgoing rays can go anywhere in the hemisphere][4]][4]&#xD;&#xA;&#xD;&#xA;We ***could*** uniformly sample the hemisphere to generate the new ray. However, we can exploit the fact that the rendering equation has a cosine factor in it:&#xD;&#xA;&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) + \int_{\Omega} f(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}$$&#xD;&#xA;&#xD;&#xA;Specifically, we know that any rays at the horizon will be heavily attenuated (specifically, $\cos(x)$ ). So, rays generated near the horizon will not contribute very much to the final value.&#xD;&#xA;&#xD;&#xA;To combat this, we use importance sampling. If we generate rays according to a cosine weighted hemisphere, we ensure that more rays are generated well above the horizon, and less near the horizon. This will lower variance and reduce noise.&#xD;&#xA;&#xD;&#xA;In your case, you specified that you will be using a Cook-Torrance, microfacet-based BRDF. The common form being:&#xD;&#xA;&#xD;&#xA;$$f(p, \omega_{\text{i}}, \omega_{\text{o}}) = \frac{F(\omega_{\text{i}}, h) G(\omega_{\text{i}}, \omega_{\text{o}}, h) D(h)}{4 \cos(\theta_{i}) \cos(\theta_{o})}$$&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;$$F(\omega_{\text{i}}, h) = \text{Fresnel function} \\&#xD;&#xA;G(\omega_{\text{i}}, \omega_{\text{o}}, h) = \text{Geometry Masking and Shadowing function} \\&#xD;&#xA;D(h) = \text{Normal Distribution Function}$$&#xD;&#xA;&#xD;&#xA;The blog &quot;A Graphic's Guy's Note&quot; has an excellent write up on how to sample Cook-Torrance BRDFs. I will refer you to [his blog post][5]. That said, I will try to create a brief overview below:&#xD;&#xA;&#xD;&#xA;The NDF is generally the dominant portion of the Cook-Torrance BRDF, so if we are going to importance sample, the we should sample based on the NDF.&#xD;&#xA;&#xD;&#xA;Cook-Torrance doesn't specify a specific NDF to use; we are free to choose whichever one suits our fancy. That said, there are a few popular NDFs:&#xD;&#xA;&#xD;&#xA; - GGX&#xD;&#xA; - Beckmann&#xD;&#xA; - Blinn&#xD;&#xA;&#xD;&#xA;Each NDF has it's own formula, thus each must be sampled differently. I am only going to show the final sampling function for each. If you would like to see how the formula is derived, see the blog post.&#xD;&#xA;&#xD;&#xA;**GGX** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{GGX}(m) = \frac{\alpha^2}{\pi((\alpha^2-1) \cos^2(\theta) + 1)^2}$$&#xD;&#xA;&#xD;&#xA;To sample the spherical coordinates angle $\theta$, we can use the formula:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left( \sqrt{\frac{\alpha^2}{\xi_1 (\alpha^2 - 1) + 1}} \right)$$&#xD;&#xA;&#xD;&#xA;where $\xi$ is a uniform random variable.&#xD;&#xA;&#xD;&#xA;We assume that the NDF is isotropic, so we can sample $\phi$ uniformly:&#xD;&#xA;&#xD;&#xA;$$\phi = \xi_{2}$$&#xD;&#xA;&#xD;&#xA;**Beckmann** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Beckmann}(m) = \frac{1}{\pi \alpha^2\cos^4(\theta)} e^{-\frac{\tan^2(\theta)}{\alpha^2}}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\sqrt{\frac{1}{1 = \alpha^2 \ln(1 - \xi_1)}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;Lastly, **Blinn** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Blinn}(m) = \frac{\alpha + 2}{2 \pi} (\cos(\theta))^{\alpha}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\frac{1}{\xi_{1}^{\alpha + 1}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Putting it in Practice&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;Let's look at a basic backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. At each bounce, we have to choose a new direction for the ray. As mentioned above, we ***could*** uniformly sample the hemisphere to generate the new ray. However, the code is smarter; it importance samples the new direction based on the BRDF. (Note: This is the input direction, because we are a backwards path tracer)&#xD;&#xA;&#xD;&#xA;    // Get the new ray direction&#xD;&#xA;    // Choose the direction based on the material&#xD;&#xA;    float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;    float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;Which could be implemented as:&#xD;&#xA;&#xD;&#xA;    void LambertBRDF::Sample(float3 outputDirection, float3 normal, UniformSampler *sampler) {&#xD;&#xA;        float rand = sampler-&gt;NextFloat();&#xD;&#xA;        float r = std::sqrtf(rand);&#xD;&#xA;        float theta = sampler-&gt;NextFloat() * 2.0f * M_PI;&#xD;&#xA;&#xD;&#xA;        float x = r * std::cosf(theta);&#xD;&#xA;        float y = r * std::sinf(theta);&#xD;&#xA;&#xD;&#xA;        // Project z up to the unit hemisphere&#xD;&#xA;        float z = std::sqrtf(1.0f - x * x - y * y);&#xD;&#xA;&#xD;&#xA;        return normalize(TransformToWorld(x, y, z, normal));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float3a TransformToWorld(float x, float y, float z, float3a &amp;normal) {&#xD;&#xA;        // Find an axis that is not parallel to normal&#xD;&#xA;        float3a majorAxis;&#xD;&#xA;        if (abs(normal.x) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(1, 0, 0);&#xD;&#xA;        } else if (abs(normal.y) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(0, 1, 0);&#xD;&#xA;        } else {&#xD;&#xA;            majorAxis = float3a(0, 0, 1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Use majorAxis to create a coordinate system relative to world space&#xD;&#xA;        float3a u = normalize(cross(normal, majorAxis));&#xD;&#xA;        float3a v = cross(normal, u);&#xD;&#xA;        float3a w = normal;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Transform from local coordinates to world coordinates&#xD;&#xA;        return u * x +&#xD;&#xA;               v * y +&#xD;&#xA;               w * z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float LambertBRDF::Pdf(float3 inputDirection, float3 normal) {&#xD;&#xA;        return dot(inputDirection, normal) * M_1_PI;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After we sample the inputDirection ('wi' in the code), we use that to calculate the value of the BRDF. And then we divide by the pdf as per the Monte Carlo formula:&#xD;&#xA;&#xD;&#xA;    // Accumulate the brdf attenuation&#xD;&#xA;    throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;&#xD;&#xA;Where *Eval()* is just the BRDF function itself (Lambert, Blinn-Phong, Cook-Torrance, etc.):&#xD;&#xA;&#xD;&#xA;    float3 LambertBRDF::Eval(float3 inputDirection, float3 outputDirection, float3 normal) const override {&#xD;&#xA;        return m_albedo * M_1_PI * dot(inputDirection, normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGyXh.png&#xD;&#xA;  [3]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/appendixA.pdf&#xD;&#xA;  [4]: https://i.stack.imgur.com/6crnH.png&#xD;&#xA;  [5]: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/" ContentLicense="CC BY-SA 4.0" />
  <row Id="25581" PostHistoryTypeId="2" PostId="9345" RevisionGUID="799b0ed9-f5c2-4da5-8b9a-0a3d3f1657e8" CreationDate="2019-11-13T21:20:43.117" UserId="48" Text="The summation doesn't include the BxDF that was picked for sampling. Look again at this line:&#xD;&#xA;&#xD;&#xA;    if (bxdfs[i] != bxdf &amp;&amp; bxdfs[i]-&gt;MatchesFlags(type))&#xD;&#xA;&#xD;&#xA;Here `bxdf` is the one that was sampled earlier, so when it iterates to that one it skips it." ContentLicense="CC BY-SA 4.0" />
  <row Id="25582" PostHistoryTypeId="2" PostId="9346" RevisionGUID="f65691e4-d9d4-40ae-88d6-93647ef58f98" CreationDate="2019-11-14T02:29:41.417" UserId="56" Text="When you are making an SDF, you commonly have infinitely detailed data (like, bezier curves making up a letter) that you are making into an SDF image of a specific size.&#xA;&#xA;If you make one that is 64x64, the first mop will be 32x32. The right way to make that mip is to do the original process of creating the SDF texture from the source data. You just have the output be 32x32 instead of 64x64." ContentLicense="CC BY-SA 4.0" />
  <row Id="25583" PostHistoryTypeId="5" PostId="9346" RevisionGUID="161f5c56-263a-47d8-828f-6464e7c534a7" CreationDate="2019-11-14T02:59:30.000" UserId="56" Comment="added 244 characters in body" Text="When you are making an SDF, you commonly have infinitely detailed data (like, bezier curves making up a letter) that you are making into an SDF image of a specific size.&#xA;&#xA;If you make one that is 64x64, the first mip will be 32x32. The right way to make that mip is to do the original process of creating the SDF texture from the source data, but do it at 32x32 instead of 64x64. Repeat for the other mips.&#xA;&#xA;It will break down at lower resolutions though, but that is just the nature of how SDFs work. The more correct, but slower way is to do super sampling. Take multiple samples at different places in the pixel and average the result." ContentLicense="CC BY-SA 4.0" />
  <row Id="25584" PostHistoryTypeId="2" PostId="9347" RevisionGUID="e3e1bd28-4c70-4355-9a4e-c4abc29618ef" CreationDate="2019-11-14T05:26:09.723" UserId="56" Text="An easy way to parallelize a path tracer is to have different threads (or machines!) work on different parts of the image.&#xA;&#xA;For instance, you could break the image into a 20x20 grid and have each thread grab a tile, render it, and try to grab another tile.&#xA;&#xA;A way I like to divy out this work is to use an atomic integer. Each thread atomically increments the integer and uses the value as an index into the work to do. They repeat this process until the atomic integer goes out of bounds." ContentLicense="CC BY-SA 4.0" />
  <row Id="25586" PostHistoryTypeId="2" PostId="9348" RevisionGUID="bb8dc122-946e-48b4-b6b7-b7943a117d7a" CreationDate="2019-11-15T09:51:20.147" UserId="6046" Text="Ok after searching a whole lot on the internet I found a [slide][1] which answered most of my questions and doubts. I'm dumping it here in-case anybody else is curious what these datasets usually contain and what should be (in my opinion) the correct way to handle mappings.&#xD;&#xA;&#xD;&#xA;So apparently the CT scanner always records the densities of the substances in Hounsfield Scale. The Hounsfield Scale itself is a little interesting. For body organs and stuff, the scale has the range from -1024 to 3000. This was the scale I talked about earlier as when normalized the values usually lie between 0-4096. However metals usually go past this 3k boundary and some metals like stainless steel and gold having HU number as high as 13k and 30k respectively. This is usually called the &quot;extended&quot; Hounsfield Scale.&#xD;&#xA;Some volumetric datasets contain data for computer simulations mostly fluids etc. For these type of datasets either density or flow velocity is captured. Precision is important for these datasets hence `float` is used.&#xD;&#xA;&#xD;&#xA;Hence the `uint8` datasets are probably grey-scale data converted from the original HU units. `uint16` datasets contain the original Hounsfield data while `float` may contain density or velocity. &#xD;&#xA;&#xD;&#xA;Now for the mapping part, as others stated one way might be to just divide by the max value of the data type or the max value of the data itself, to get the `uint16` or `float` data in `0-1` range then multiply by `255` to get a grey-scale image. However doing so may lower the contrast and hide minute details. For example, dividing a `uint16` dataset that contained only HU units in range `300-2000` with the $2^{16}$ will map the HU units to only a small range of grey values. Dividing by `2000` in this case is surely better. However after reading how CT-scanners work, it's better to let the user set the minimum and maximum range of Hounsfield units they wish to observe. This is usually called the **window width**. And then map this window width to the whole `0-255` range of grey levels as YardenJ2R mentioned in his second formula. This is more in line with how radiologists visualise the data. &#xD;&#xA;&#xD;&#xA;For fancy transfer functions which I haven't implemented yet, we might have to convert the Hounsfield units to opacity or grey scale as mentioned above then map that opacity to color or there might be a way to directly map it to colors using a LUT as defined by the user's control point settings.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://humanhealth.iaea.org/HHW/MedicalPhysics/TheMedicalPhysicist/Studentscorner/HandbookforTeachersandStudents/Chapter_11.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="25592" PostHistoryTypeId="2" PostId="9350" RevisionGUID="f9e4e616-4f89-4950-961c-ca12853d66f9" CreationDate="2019-11-16T04:29:37.950" UserId="9528" Text="I have two meshes that I want to align, I'll call the reference mesh the *template mesh* and the other is the *target mesh*. I have 1 point-to-point correspondence between my template and target mesh. &#xD;&#xA;I am trying to find the uniform scale and translation to align these 2 meshes. &#xD;&#xA;This is what I've been doing :&#xD;&#xA;&#xD;&#xA;My optimal transformation matrix M = `[M11 0 0 M14; 0 M11 0 M24 ; 0 0 M11 M34; 0 0 0 1 ]` , here M11 is my scale and M14, M24, M34 are the translation in x,y and z.&#xD;&#xA;I represent my points from the template mesh as homogeneous coordinates -&gt; A = `[xt, yt, zt, 1]`&#xD;&#xA;the corresponding points on the target mesh -&gt; B = `[xp, yp, zp, 1]`&#xD;&#xA;&#xD;&#xA;I know that :&#xD;&#xA;&#xD;&#xA;    xp = M11*xt + M14&#xD;&#xA;    yp = M11*xt + M24&#xD;&#xA;    zp = M11*xt + M34&#xD;&#xA;&#xD;&#xA;This is how I form and solve my least sqauares problem :&#xD;&#xA;&#xD;&#xA;    findMin((X*T - B)^2) &#xD;&#xA;Where T, X and B are  :&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;      B  =      X      *   T&#xD;&#xA;      [xp  [ xt 1 0 0    [M11&#xD;&#xA;       yp =  yt 0 1 0  *  M14&#xD;&#xA;       zp    zt 0 0 1     M24&#xD;&#xA;       1]    1  1 1 1]    M34]&#xD;&#xA;&#xD;&#xA;This is how I find the least squares fit for T :&#xD;&#xA;&#xD;&#xA;    (Inverse(X'*X))*X'*B&#xD;&#xA;I am not sure if this is the right way to go about this, particularly&#xD;&#xA;&#xD;&#xA; 1. Is it acceptable to add the row of ones in the last row of matrix X&#xD;&#xA;    in my least sqaures problem? It has no physical meaning, I just&#xD;&#xA;    added it to make dimensions match and ensure that the matrix X is&#xD;&#xA;    invertible.&#xD;&#xA; 2. With this I get negative scale values, is there a way I can add constraints in the least squares problem to ensure that I get a scale that is always greater than 0? Is this even the right approach to find a scale value?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25593" PostHistoryTypeId="1" PostId="9350" RevisionGUID="f9e4e616-4f89-4950-961c-ca12853d66f9" CreationDate="2019-11-16T04:29:37.950" UserId="9528" Text="Least squares for uniform scale and translation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25594" PostHistoryTypeId="3" PostId="9350" RevisionGUID="f9e4e616-4f89-4950-961c-ca12853d66f9" CreationDate="2019-11-16T04:29:37.950" UserId="9528" Text="|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25597" PostHistoryTypeId="2" PostId="9352" RevisionGUID="dacab306-98b6-4d7d-ac50-7ea898eed291" CreationDate="2019-11-16T18:26:01.453" UserId="11474" Text="http://graphics.stanford.edu/papers/veach_thesis/chapter8.ps&#xD;&#xA;&#xD;&#xA;In chapter 8 of his thesis which he talks about the three-point form of the transport equations, equation (8.1) in particular, it seems the integrand will expand into something that contains a $\cos^2(\theta_i^\prime)$ term. One of the cosine terms comes from the $G$, and the other one comes the BSDF $f_s$ which is defined with respect to the projected solid angle.&#xD;&#xA;&#xD;&#xA;When I look at PBRT V3's implementation, BSDF is defined upon solid angle. However, the geometry term $G$ is the same as Veach's.&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;Spectrum G(const Scene &amp;scene, Sampler &amp;sampler, const Vertex &amp;v0,&#xD;&#xA;           const Vertex &amp;v1) {&#xD;&#xA;    Vector3f d = v0.p() - v1.p();&#xD;&#xA;    Float g = 1 / d.LengthSquared();&#xD;&#xA;    d *= std::sqrt(g);&#xD;&#xA;    if (v0.IsOnSurface()) g *= AbsDot(v0.ns(), d);&#xD;&#xA;    if (v1.IsOnSurface()) g *= AbsDot(v1.ns(), d);&#xD;&#xA;    VisibilityTester vis(v0.GetInteraction(), v1.GetInteraction());&#xD;&#xA;    return g * vis.Tr(scene, sampler);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;This implies there is only one $\cos(\theta_i^\prime)$ term. Am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25598" PostHistoryTypeId="1" PostId="9352" RevisionGUID="dacab306-98b6-4d7d-ac50-7ea898eed291" CreationDate="2019-11-16T18:26:01.453" UserId="11474" Text="Questions in Veach path-space formulation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25599" PostHistoryTypeId="3" PostId="9352" RevisionGUID="dacab306-98b6-4d7d-ac50-7ea898eed291" CreationDate="2019-11-16T18:26:01.453" UserId="11474" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25600" PostHistoryTypeId="2" PostId="9353" RevisionGUID="15c80d78-2cea-4f5a-a552-33707c2ddc6a" CreationDate="2019-11-16T19:11:49.630" UserId="10193" Text="Let's say I have some shader program in DirectX or OpenGL rendering a full screen quad. And in a pixel/fragment shader I sample some huge textures at random texture coordinates. That is one same texture coordinate for all texture samplings in one shader invocation, but it is various among different shader invocations. These fetch operations produce performance drop, I even think that due to the size of the textures the GPU texture cache is not big enough and is used not efficiently.&#xD;&#xA;&#xD;&#xA;Now I have a theoretical question: can I optimize the performance by using some low-resolution like 32x32 *mask* textures, which are built by mipmapping the large textures, and if a value in a mask texture at given texture coordinate at some higher mip level is not appropriate, then I don't need to perform texture fetches at full-size level 0? Something like this in HLSL (GLSL code is pretty similar, but there is no [branch] attribute):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float2 tc = calculateTexCoordinates();&#xD;&#xA;bool performHeavyComputations = testValue(largeMipmappedTexture.SampleLevel(sampler, tc, 5));&#xD;&#xA;&#xD;&#xA;float result = 0;&#xD;&#xA;&#xD;&#xA;[branch]&#xD;&#xA;if (performHeavyComputations)&#xD;&#xA;{&#xD;&#xA;    result += largeMipmappedTexture.SampleLevel(sampler, tc, 0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;About 50% of texels at mip level 5 will not pass the test. And so a lot of shader invocations should not sample the full-size textures.&#xD;&#xA;&#xD;&#xA;But I am introducing branching in the code. May this branching hurt the performance even worse than sampling the full-size texture even if that is not needed? Different GPUs may behave differently, some may not even support branching, will they perform **two** fetches instead of one?&#xD;&#xA;&#xD;&#xA;I can test this code on some machines, but my question is theoretical.&#xD;&#xA;&#xD;&#xA;And can you suggest another optimizations, if this won't work properly ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25601" PostHistoryTypeId="1" PostId="9353" RevisionGUID="15c80d78-2cea-4f5a-a552-33707c2ddc6a" CreationDate="2019-11-16T19:11:49.630" UserId="10193" Text="Optimizing texture fetches with higher mip levels" ContentLicense="CC BY-SA 4.0" />
  <row Id="25602" PostHistoryTypeId="3" PostId="9353" RevisionGUID="15c80d78-2cea-4f5a-a552-33707c2ddc6a" CreationDate="2019-11-16T19:11:49.630" UserId="10193" Text="|opengl|shader|texture|performance|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25603" PostHistoryTypeId="5" PostId="9353" RevisionGUID="5d906bd8-79f4-47f4-9e0e-4654731af8db" CreationDate="2019-11-16T19:17:08.297" UserId="10193" Comment="added 6 characters in body" Text="Let's say I have some shader program in DirectX or OpenGL rendering a full screen quad. And in a pixel/fragment shader I sample some huge textures at random texture coordinates. That is one same texture coordinate for all texture samplings in one shader invocation, but it is various among different shader invocations. These fetch operations produce performance drop, I even think that due to the size of the textures the GPU texture cache is not big enough and is used not efficiently.&#xD;&#xA;&#xD;&#xA;Now I have a theoretical question: can I optimize the performance by using some low-resolution like 32x32 *mask* textures, which are built by mipmapping the large textures, and if a value in a mask texture at given texture coordinate at some higher mip level is not appropriate, then I don't need to perform texture fetches at full-size level 0? Something like this in HLSL (GLSL code is pretty similar, but there is no [branch] attribute):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float2 tc = calculateTexCoordinates();&#xD;&#xA;bool performHeavyComputations = testValue(largeMipmappedTexture.SampleLevel(sampler, tc, 5));&#xD;&#xA;&#xD;&#xA;float result = 0;&#xD;&#xA;&#xD;&#xA;[branch]&#xD;&#xA;if (performHeavyComputations)&#xD;&#xA;{&#xD;&#xA;    result += largeMipmappedTexture.SampleLevel(sampler, tc, 0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;About 50% of texels at mip level 5 will not pass the test. And so a lot of shader invocations should not sample the full-size textures.&#xD;&#xA;&#xD;&#xA;But I am introducing branching in the code. May this branching hurt the performance even worse than sampling the full-size texture even if that is not needed? Different GPUs may behave differently, some may not even support branching, will they perform **two** fetches instead of one?&#xD;&#xA;&#xD;&#xA;I can test this code on some machines later, but my question is theoretical.&#xD;&#xA;&#xD;&#xA;And can you suggest another optimizations, if this won't work properly ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25604" PostHistoryTypeId="2" PostId="9354" RevisionGUID="3d1b8e67-8786-461c-a696-92dbcbaf984b" CreationDate="2019-11-17T08:12:14.837" UserId="11475" Text="Does anyone happen to know the latency difference between copying a texture on cpu (using, say, `memcpy`) compared to gpu (using, say, `CopyResource`)? I would do a perf test myself, but I'm not actually sure how to do the trace for the `CopyResource`. A rule of thumb would be fine, it doesn't have to be exact, I just figure that the GPU is faster than the cpu for this but am just curious how expensive a copy of, say, a 1920x1080 texture is." ContentLicense="CC BY-SA 4.0" />
  <row Id="25605" PostHistoryTypeId="1" PostId="9354" RevisionGUID="3d1b8e67-8786-461c-a696-92dbcbaf984b" CreationDate="2019-11-17T08:12:14.837" UserId="11475" Text="Latency difference between texture copy on GPU vs CPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25606" PostHistoryTypeId="3" PostId="9354" RevisionGUID="3d1b8e67-8786-461c-a696-92dbcbaf984b" CreationDate="2019-11-17T08:12:14.837" UserId="11475" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25607" PostHistoryTypeId="2" PostId="9355" RevisionGUID="bdaafafa-89da-440d-a3f3-244d9d0d9c4c" CreationDate="2019-11-17T14:29:32.617" UserId="11476" Text="Is there a way to change a picture so it would fail to match against existing copy of the same picture on the big social networks such as Facebook, Twitter, Instagram, Tinder and others? Desired result should be as close as possible to the original." ContentLicense="CC BY-SA 4.0" />
  <row Id="25608" PostHistoryTypeId="1" PostId="9355" RevisionGUID="bdaafafa-89da-440d-a3f3-244d9d0d9c4c" CreationDate="2019-11-17T14:29:32.617" UserId="11476" Text="How to change a picture to fail comparison algorithms?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25609" PostHistoryTypeId="3" PostId="9355" RevisionGUID="bdaafafa-89da-440d-a3f3-244d9d0d9c4c" CreationDate="2019-11-17T14:29:32.617" UserId="11476" Text="|image-comparison|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25610" PostHistoryTypeId="2" PostId="9356" RevisionGUID="971b854d-3faf-4d75-8687-cd25ef3a9692" CreationDate="2019-11-17T19:30:52.803" UserId="56" Text="It's dependent on the algorithm used for comparison, but if you have access to that algorithm, you can add small amounts of noise to pixels randomly until it misclassifies the image.&#xA;&#xA;If you had deeper knowledge of the algorithm used, and it was differentiable, you could use gradient descent (ascent) to modify the image to increase the error of what was detected. This is the reverse of what you do when training image comparisons/classifiers which modify the weights to minimize the error.&#xA;&#xA;But in short, if you dont have much knowledge of how the algorithm used works, I personally would try adding noise to pixels randomly, such that the image was still easily recognizable, but a decent amount of noise was added in." ContentLicense="CC BY-SA 4.0" />
  <row Id="25611" PostHistoryTypeId="2" PostId="9357" RevisionGUID="b297a129-af0c-48c1-865a-d83c02fa8cd0" CreationDate="2019-11-17T22:08:03.190" UserId="11479" Text="I am currently implementing omni lights in my DirectX game engine. I decided to build the shading formula from the classical rendering equation. Here is what I get:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The simplifications show that the cosine term should be removed for omni lights since power is a Flux.&#xD;&#xA;Here the problem. While looking for recourses online I found that engines always multiply by the cosine term, even for omni lights.&#xD;&#xA;&#xD;&#xA;Is it wrong or am I missing something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MiwIQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25612" PostHistoryTypeId="1" PostId="9357" RevisionGUID="b297a129-af0c-48c1-865a-d83c02fa8cd0" CreationDate="2019-11-17T22:08:03.190" UserId="11479" Text="Rendering equation for omnidirectional lights" ContentLicense="CC BY-SA 4.0" />
  <row Id="25613" PostHistoryTypeId="3" PostId="9357" RevisionGUID="b297a129-af0c-48c1-865a-d83c02fa8cd0" CreationDate="2019-11-17T22:08:03.190" UserId="11479" Text="|rendering|3d|lighting|brdf|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25621" PostHistoryTypeId="2" PostId="9360" RevisionGUID="28600b9a-5353-42d3-8de9-aeb10b595739" CreationDate="2019-11-18T10:12:41.393" UserId="6046" Text="Sorry to post such a silly solution but apparently the problem was reading 16 bit uint data into 8bit uint array. This was the reason for inexplainable noise, interleaving and other artifacts. &#xD;&#xA;&#xD;&#xA;After I explored [more][1] about what the medical datasets actually represent and what flavors they come in (8,16,32bit) I managed to solve the problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/9336/how-to-handle-different-data-types-uint8-uint16-float-in-volume-datasets?noredirect=1#comment14110_9336" ContentLicense="CC BY-SA 4.0" />
  <row Id="25622" PostHistoryTypeId="2" PostId="9361" RevisionGUID="5035c397-fb76-4305-ae20-00301fb9d799" CreationDate="2019-11-18T15:12:23.970" UserId="11191" Text="I have created two animations:&#xD;&#xA;&#xD;&#xA; - One where a &quot;camera&quot; moves towards the spheres creating an optic flow (1st GIF).The code can be found [here][2].&#xD;&#xA;&#xD;&#xA; - One where spheres move randomly in a 3D coordinates space (2nd GIF). To do so I have computed two angles theta and phi. The code can be found [here][1].&#xD;&#xA;&#xD;&#xA;I need to compute the speed of each sphere frame by frame in both animations, but I have no idea of the mathematics. I would assume that the formula would be different in the two animations. I have found only the calculation of 3D velocity, and I was wondering whether I could calculate the speed as a single value?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codepile.net/pile/vWz91BKA&#xD;&#xA;  [2]: https://www.codepile.net/pile/7pvd7rGJ&#xD;&#xA;  [3]: https://i.stack.imgur.com/RKv9T.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/ETe7F.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="25623" PostHistoryTypeId="1" PostId="9361" RevisionGUID="5035c397-fb76-4305-ae20-00301fb9d799" CreationDate="2019-11-18T15:12:23.970" UserId="11191" Text="Compute Speed of Spheres in 3D animation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25624" PostHistoryTypeId="3" PostId="9361" RevisionGUID="5035c397-fb76-4305-ae20-00301fb9d799" CreationDate="2019-11-18T15:12:23.970" UserId="11191" Text="|3d|transformations|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25625" PostHistoryTypeId="5" PostId="9357" RevisionGUID="66c617d5-ce1b-4fd6-a96f-e4fd5850515f" CreationDate="2019-11-18T19:34:17.680" UserId="11479" Comment="added 15 characters in body; edited title" Text="I am currently implementing spherical lights in my DirectX game engine. I decided to build the shading formula from the classical rendering equation. Here is what I get:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The simplifications show that the cosine term should be removed for spherical lights since power is a Flux.&#xD;&#xA;Here the problem. While looking for recourses online I found that engines always multiply by the cosine term, even for spherical lights.&#xD;&#xA;&#xD;&#xA;Is it wrong or am I missing something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MiwIQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25626" PostHistoryTypeId="4" PostId="9357" RevisionGUID="66c617d5-ce1b-4fd6-a96f-e4fd5850515f" CreationDate="2019-11-18T19:34:17.680" UserId="11479" Comment="added 15 characters in body; edited title" Text="Rendering equation for spherical lights" ContentLicense="CC BY-SA 4.0" />
  <row Id="25627" PostHistoryTypeId="2" PostId="9362" RevisionGUID="1c69e233-754c-4aa6-8746-3790679245f0" CreationDate="2019-11-18T22:00:09.013" UserId="10096" Text="If you just want to explicitly sample an area light, then here's the general procedure you should follow. Pick light $i$ out of $L$ lights with some probability $p_i$ (the other probabilities being $p_1,...,p_L$, a light may be picked through inverse transform sampling). Pick a point $\pmb{y}$ on the surface of the light with some probability $q_i(\pmb{y})$. Then your estimator is:&#xD;&#xA;&#xD;&#xA;$$I_N = \frac{1}{N}\sum_{k=1}^{N}\frac{1}{p_{i_k}q_{i_k}(\pmb{y}_k)}f(\pmb{z} \leftarrow \pmb{x} \leftarrow \pmb{y}_k)L_e(\pmb{y}_k\rightarrow\pmb{x})\frac{\cos\theta_x\cos\theta_{y_k}}{\|\pmb{x}-\pmb{y}_k\|^2_2}V(\pmb{x},\pmb{y}_k)$$&#xD;&#xA;&#xD;&#xA;Note that this is only for direct illumination at point $\pmb{x}$. I have generalized it to a secondary estimator using $N$ samples, so essentially you pick $N$ points $\pmb{y}_1,...,\pmb{y}_N$ on possibly different lights. This is an estimator that can directly be derived from the area formulation of the rendering equation:&#xD;&#xA;&#xD;&#xA;$$L(\pmb{z} \leftarrow \pmb{x}) = L_e(\pmb{x} \leftarrow \pmb{z}) + \int_{\Omega}f(\pmb{z} \leftarrow \pmb{x} \leftarrow \pmb{y})L(\pmb{y}\rightarrow\pmb{x})\frac{\cos\theta_x\cos\theta_y}{\|\pmb{x}-\pmb{y}_k\|^2_2}V(\pmb{x},\pmb{y})\,dA(\pmb{y})$$&#xD;&#xA;&#xD;&#xA;The area formulation can be derived from the solid angle one, by using the identity:&#xD;&#xA;&#xD;&#xA;$$d\omega = \frac{\cos\theta_y}{r^2}dA$$,&#xD;&#xA;&#xD;&#xA;as well as:&#xD;&#xA;&#xD;&#xA;$$L_i(\pmb{x}, \omega) = L(r(\pmb{x},\omega) \rightarrow \pmb{x}) = L(\pmb{y} \rightarrow \pmb{x})V(\pmb{x},\pmb{y})$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="25628" PostHistoryTypeId="5" PostId="9317" RevisionGUID="335ab0ca-4d2f-41e6-8c84-bc12064f2cbe" CreationDate="2019-11-19T17:09:36.607" UserId="11436" Comment="Putting more error examples" Text="I am programing a tessellation shader in OpenGL which computes the [quartic Walton-Meek's Gregory patch][1]. I am searching for a local G1 method with good shading/visual results. So I am trying this patch. I didn't get good (visual/shading) results with PN-Triangles.&#xD;&#xA;&#xD;&#xA;I've just had my first result with this WM patch, which isn't good as well. Perhaps the normal I am calculating is wrong. I am following these equations to compute it:&#xD;&#xA;&#xD;&#xA;[![Bézier-Bernstein Triangle and Derivatives Equations][2]][2]&#xD;&#xA;&#xD;&#xA;Then, I actually compute it through normalizing the cross product between the derivatives (last image).&#xD;&#xA;&#xD;&#xA;If you want to take a look at the shader code, here it is (the first one is the tessellation control shader and the second one is the tessellation evaluation shader):&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout (vertices = 3) out;&#xD;&#xA;&#xD;&#xA;in VertOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;} vertOut[];&#xD;&#xA;&#xD;&#xA;out TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	const float kTessLevel = 12.0;&#xD;&#xA;	gl_TessLevelOuter[gl_InvocationID] = kTessLevel;&#xD;&#xA;	gl_TessLevelInner[0] = kTessLevel;&#xD;&#xA;&#xD;&#xA;	vec3 p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz;&#xD;&#xA;	vec3 n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;	const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;	vec3 edge = gl_in[nextInvID].gl_Position.xyz - p0;&#xD;&#xA;	vec3 nNext = vertOut[nextInvID].normal;&#xD;&#xA;	float d = length(edge), a = dot(n, nNext);&#xD;&#xA;	vec3 gama = edge / d;&#xD;&#xA;	float a0 = dot(n, gama), a1 = dot(nNext, gama);&#xD;&#xA;	float ro = 6.0 * (2.0 * a0 + a * a1)/(4.0 - a * a);&#xD;&#xA;	float sigma = 6.0 * (2.0 * a1 + a * a0)/(4.0 - a * a);&#xD;&#xA;&#xD;&#xA;	vec3 v[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		p0,&#xD;&#xA;		p0 + (d / 18.0) * (6.0 * gama - 2.0 * ro * n + sigma * nNext),&#xD;&#xA;		gl_in[nextInvID].gl_Position.xyz - (d / 18.0) * (6.0 * gama + ro * n - 2.0 * sigma * nNext),&#xD;&#xA;		edge = gl_in[nextInvID].gl_Position.xyz&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 w[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		v[1] - v[0],&#xD;&#xA;		v[2] - v[1],&#xD;&#xA;		v[3] - v[2]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 A[3] = vec3[3]&#xD;&#xA;	(&#xD;&#xA;		cross(n, normalize(w[0])),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		cross(nNext, normalize(w[2]))&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	A[1] = normalize(A[0] + A[2]);&#xD;&#xA;&#xD;&#xA;	vec3 l[5] = vec3[5]&#xD;&#xA;	(&#xD;&#xA;		v[0],&#xD;&#xA;		0.25 * (v[0] + 3.0 * v[1]),&#xD;&#xA;		0.25 * (2.0 * v[1] + 2.0 * v[2]),&#xD;&#xA;		0.25 * (3.0 * v[2] + v[3]),&#xD;&#xA;		v[3]&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	vec3 p1 = tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;	vec3 p2 = tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;	vec3 p3 = tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;	barrier();&#xD;&#xA;&#xD;&#xA;	const int previousInvID = gl_InvocationID &gt; 0 ? gl_InvocationID - 1 : 2;&#xD;&#xA;	vec3 D[4] = vec3[4]&#xD;&#xA;	(&#xD;&#xA;		tescOut[previousInvID].p3 - 0.5 * (p0 + p1),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		vec3(0.0),&#xD;&#xA;		tescOut[nextInvID].p1 - 0.5 * (p3 + tescOut[nextInvID].p0)&#xD;&#xA;	);&#xD;&#xA;&#xD;&#xA;	float mi[2] = float[2](dot(D[0], A[0]), dot(D[3], A[2]));&#xD;&#xA;	float lambda[2] = float[2](dot(D[0], w[0])/dot(w[0], w[0]), dot(D[3], w[2])/dot(w[2], w[2]));&#xD;&#xA;&#xD;&#xA;	tescOut[gl_InvocationID].g0 = 0.5 * (l[1] + l[2]) + (2.0/3.0) * (lambda[0] * w[1] + mi[0] * A[1]) + (1.0/3.0) * (lambda[1] * w[0] + mi[1] * A[0]);&#xD;&#xA;	tescOut[gl_InvocationID].g1 = 0.5 * (l[2] + l[3]) + (1.0/3.0) * (lambda[0] * w[2] + mi[1] * A[2]) + (2.0/3.0) * (lambda[1] * w[1] + mi[1] * A[1]);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;#version 430 core&#xD;&#xA;layout(triangles, equal_spacing, ccw) in;&#xD;&#xA;&#xD;&#xA;in TescOut&#xD;&#xA;{&#xD;&#xA;	vec3 p0;&#xD;&#xA;	vec3 p1;&#xD;&#xA;	vec3 p2;&#xD;&#xA;	vec3 p3;&#xD;&#xA;	vec3 g0;&#xD;&#xA;	vec3 g1;&#xD;&#xA;	vec3 n;&#xD;&#xA;} tescOut[];&#xD;&#xA;&#xD;&#xA;out TeseOut&#xD;&#xA;{&#xD;&#xA;	vec3 normal;&#xD;&#xA;	vec3 viewPosition;&#xD;&#xA;} teseOut;&#xD;&#xA;&#xD;&#xA;uniform mat4 mvp;&#xD;&#xA;uniform mat4 modelView;&#xD;&#xA;uniform mat4 normalMatrix;&#xD;&#xA;uniform bool isNormalLinearlyInterpolated;&#xD;&#xA;&#xD;&#xA;#define uvw     gl_TessCoord&#xD;&#xA;&#xD;&#xA;const float u = uvw.x, u2 = u * u, u3 = u2 * u, u4 = u2 * u2;&#xD;&#xA;const float v = uvw.y, v2 = v * v, v3 = v2 * v, v4 = v2 * v2;&#xD;&#xA;const float w = uvw.z, w2 = w * w, w3 = w2 * w, w4 = w2 * w2;&#xD;&#xA;&#xD;&#xA;#define p400	tescOut[0].p0&#xD;&#xA;#define p310	tescOut[0].p1&#xD;&#xA;#define p220	tescOut[0].p2&#xD;&#xA;#define p130	tescOut[0].p3&#xD;&#xA;#define G01		tescOut[0].g0&#xD;&#xA;#define	G02		tescOut[0].g1&#xD;&#xA;#define p040	tescOut[1].p0&#xD;&#xA;#define p031	tescOut[1].p1&#xD;&#xA;#define p022	tescOut[1].p2&#xD;&#xA;#define p013	tescOut[1].p3&#xD;&#xA;#define G11		tescOut[1].g0&#xD;&#xA;#define	G12		tescOut[1].g1&#xD;&#xA;#define p004	tescOut[2].p0&#xD;&#xA;#define p103	tescOut[2].p1&#xD;&#xA;#define p202	tescOut[2].p2&#xD;&#xA;#define p301	tescOut[2].p3&#xD;&#xA;#define G21		tescOut[2].g0&#xD;&#xA;#define	G22		tescOut[2].g1&#xD;&#xA;&#xD;&#xA;#define B400	u4&#xD;&#xA;#define B040	v4&#xD;&#xA;#define B004	w4&#xD;&#xA;#define B310	(4.0 * u3 * v)&#xD;&#xA;#define B031	(4.0 * v3 * w)&#xD;&#xA;#define B103	(4.0 * u * w3)&#xD;&#xA;#define B220	(6.0 * u2 * v2)&#xD;&#xA;#define B022	(6.0 * v2 * w2)&#xD;&#xA;#define B202	(6.0 * u2 * w2)&#xD;&#xA;#define B130	(4.0 * u * v3)&#xD;&#xA;#define B013	(4.0 * v * w3)&#xD;&#xA;#define B301	(4.0 * u3 * w)&#xD;&#xA;#define B211	(12.0 * u2 * v * w)&#xD;&#xA;#define B121	(12.0 * u * v2 * w)&#xD;&#xA;#define B112	(12.0 * u * v * w2)&#xD;&#xA;&#xD;&#xA;#define B300	u3&#xD;&#xA;#define B030	v3&#xD;&#xA;#define B003	w3&#xD;&#xA;#define B210	(3.0 * u2 * v)&#xD;&#xA;#define B021	(3.0 * v2 * w)&#xD;&#xA;#define B102	(3.0 * w2 * u)&#xD;&#xA;#define B120	(3.0 * u * v2)&#xD;&#xA;#define B012	(3.0 * v * w2)&#xD;&#xA;#define B201	(3.0 * w * u2)&#xD;&#xA;#define B111	(6.0 * u * v * w)&#xD;&#xA;&#xD;&#xA;vec3 interpolate3D(vec3 p0, vec3 p1, vec3 p2)&#xD;&#xA;{&#xD;&#xA;   	return gl_TessCoord.x * p0 + gl_TessCoord.y * p1 + gl_TessCoord.z * p2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	vec4 pos = vec4(interpolate3D(tescOut[0].p0, tescOut[1].p0, tescOut[2].p0), 1.0);&#xD;&#xA;	vec3 normal = normalize(interpolate3D(tescOut[0].n, tescOut[1].n, tescOut[2].n));&#xD;&#xA;&#xD;&#xA;	if (u != 1.0 &amp;&amp; v != 1.0 &amp;&amp; w != 1.0)&#xD;&#xA;	{&#xD;&#xA;		vec3 p211 = (v * G12 + w * G21)/(v + w);&#xD;&#xA;		vec3 p121 = (w * G02 + u * G11)/(w + u);&#xD;&#xA;		vec3 p112 = (u * G22 + v * G01)/(u + v);&#xD;&#xA;&#xD;&#xA;		vec3 barPos =	p400 * B400 +&#xD;&#xA;						p040 * B040 +&#xD;&#xA;						p004 * B004 +&#xD;&#xA;						p310 * B310 +&#xD;&#xA;						p031 * B031 +&#xD;&#xA;						p103 * B103 +&#xD;&#xA;						p220 * B220 +&#xD;&#xA;						p022 * B022 +&#xD;&#xA;						p202 * B202 +&#xD;&#xA;						p130 * B130 +&#xD;&#xA;						p013 * B013 +&#xD;&#xA;						p301 * B301 +&#xD;&#xA;						p211 * B211 +&#xD;&#xA;						p121 * B121 +&#xD;&#xA;						p112 * B112;&#xD;&#xA;&#xD;&#xA;		pos = vec4(barPos, 1.0);&#xD;&#xA;&#xD;&#xA;		vec3 dpdu =	p400 * B300 +&#xD;&#xA;					p130 * B030 +&#xD;&#xA;					p103 * B003 +&#xD;&#xA;					p310 * B210 +&#xD;&#xA;					p121 * B021 +&#xD;&#xA;					p202 * B102 +&#xD;&#xA;					p220 * B120 +&#xD;&#xA;					p112 * B012 +&#xD;&#xA;					p301 * B201 +&#xD;&#xA;					p211 * B111 ;&#xD;&#xA;&#xD;&#xA;		vec3 dpdv =	p310 * B300 +&#xD;&#xA;					p040 * B030 +&#xD;&#xA;					p013 * B003 +&#xD;&#xA;					p220 * B210 +&#xD;&#xA;					p031 * B021 +&#xD;&#xA;					p112 * B102 +&#xD;&#xA;					p130 * B120 +&#xD;&#xA;					p022 * B012 +&#xD;&#xA;					p211 * B201 +&#xD;&#xA;					p121 * B111 ;&#xD;&#xA;&#xD;&#xA;		normal = normalize(cross(dpdu, dpdv));&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	gl_Position = mvp * pos;&#xD;&#xA;	pos = modelView * pos;&#xD;&#xA;	teseOut.viewPosition = pos.xyz / pos.w;&#xD;&#xA;&#xD;&#xA;	teseOut.normal = (normalMatrix * vec4(normal, 0.0)).xyz;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Some screenshots from my current results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;In the &quot;good ones&quot; images (first and third), the normals are computed by linear interpolation, while in the bad ones the normals are computed through the equations I said previously and are shown in the code.&#xD;&#xA;&#xD;&#xA;So, how can I correctly compute the normals? Thanks in advance!&#xD;&#xA;&#xD;&#xA;@edit&#xD;&#xA;&#xD;&#xA;So, I tried @Reynolds (see comment below) derivatives, but still it didn't work properly, unfortunately. These are the results: [![New results][7]][7]&#xD;&#xA;&#xD;&#xA;Results at the left (the dark ones) are using the code below and the ones at the right are flipping the normal (i.e., -normalize(cross(dpdu,dpdv)). The code:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;vec3 dpdu = 4.0 * (B300 * (p301 - p400) + B030 * (p031 - p130) + B003 * (p004 - p103) + B210 * (p211 - p310) +&#xD;&#xA;					B120 * (p121 - p220) + B201 * (p202 - p301) + B102 * (p103 - p202) + B021 * (p022 - p121) +&#xD;&#xA;					B012 * (p013 - p112) + B111 * (p112 - p211));&#xD;&#xA;		&#xD;&#xA;vec3 dpdv = 4.0 * (B300 * (p310 - p400) + B030 * (p040 - p130) + B003 * (p013 - p103) + B210 * (p220 - p310) +&#xD;&#xA;					B120 * (p130 - p220) + B201 * (p211 - p301) + B102 * (p112 - p202) + B012 * (p022 - p112) +&#xD;&#xA;					B021 * (p031 - p121) + B111 * (p121 - p211));&#xD;&#xA;normal = normalize(cross(dpdu, dpdv)); // -normalize(cross(dpdu, dpdv));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;@edit2&#xD;&#xA;&#xD;&#xA;Some more results:&#xD;&#xA;&#xD;&#xA;[![Example of some errors][8]][8]&#xD;&#xA;See as the bottom part of the mesh disappeared. It seems to me a problem with the zero singularity. Probably I am not treating this correctly.&#xD;&#xA;&#xD;&#xA;[![Another example][9]][9]&#xD;&#xA;Here, the normals of the bottom part of the mesh have a negative component in Y (vertical axis). In the previous picture, Y = 0 (for normals).&#xD;&#xA;&#xD;&#xA;Top-left: raw mesh with normals in white&#xD;&#xA;Top-right: raw mesh shading without tessellation (hence, without WM patch)&#xD;&#xA;Bottom-left: wireframe mode of mesh with tessellation (hence with WM patch)&#xD;&#xA;Bottom-right: mesh with tessellation (hence with WM patch)&#xD;&#xA;&#xD;&#xA;Any ideas?? Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://reader.elsevier.com/reader/sd/pii/0010448595000461?token=4190E80EF50B0C8E2FB4EADFFEF26DF93ACEDF3AED59AA6B97D59B2C1FC52B0B965B255B27749ECC11F49B44C1610688&#xD;&#xA;  [2]: https://i.stack.imgur.com/AQq0v.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/YIW42.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7bfza.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/5rw2D.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/a1MBK.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/d26TV.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/AVd7g.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/NaNdJ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25629" PostHistoryTypeId="2" PostId="9363" RevisionGUID="7a6a25c0-bb8f-4a80-9ba3-71597488963b" CreationDate="2019-11-19T20:14:48.730" UserId="9505" Text="I'd use the euclidean distance between two 3D positions. Velocity is distance over time. Time is a single frame in this case.&#xD;&#xA;&#xD;&#xA;$$\sqrt{(x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2}$$&#xD;&#xA;&#xD;&#xA;If you only move the camera, it is simply that frame of reference that moves, so all spheres have a relative velocity equal to the camera's velocity." ContentLicense="CC BY-SA 4.0" />
  <row Id="25630" PostHistoryTypeId="2" PostId="9364" RevisionGUID="fbb1332b-c749-4f96-bc36-6ca0d2fdfc78" CreationDate="2019-11-20T02:16:08.820" UserId="11492" Text="My major is mechanical, please forgive me for asking questions that may seem trivial to you. I'm reading the following paper:&#xD;&#xA;&#xD;&#xA;&gt; Dam, Erik B., Martin Koch, and Martin Lillholm. Quaternions, interpolation and animation. Vol. 2. Copenhagen: Datalogisk Institut, Københavns Universitet, 1998.&#xD;&#xA;&#xD;&#xA;On page 35, it says:&#xD;&#xA;&#xD;&#xA;&gt; Since quaternion space is four-dimensional, we cannot visualise the interpolated curves directly. We will always interpolate between unit quaternions, and the interpolated quaternions will always (with a few exceptions in chapter 6 on page 38 and 69) be unit quaternions. This means that we only need three dimensions to visualize the interpolation curves, because they lie on the surface of the unit sphere. &#xD;&#xA;&#xD;&#xA;I don't quite get the last sentence: why only three dimensions are needed to visualize the unit quaternion or why unit quaternion lies on the surface of the unit sphere? I thought they lie on the unit hyper-sphere. Does the author assume that we are viewing the quaternions from the south pole of the hyper-sphere?&#xD;&#xA;&#xD;&#xA;Any help is appreciated. Thank you. &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25631" PostHistoryTypeId="1" PostId="9364" RevisionGUID="fbb1332b-c749-4f96-bc36-6ca0d2fdfc78" CreationDate="2019-11-20T02:16:08.820" UserId="11492" Text="Is 3 dimension enough to visualize the interpolate quaternion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25632" PostHistoryTypeId="3" PostId="9364" RevisionGUID="fbb1332b-c749-4f96-bc36-6ca0d2fdfc78" CreationDate="2019-11-20T02:16:08.820" UserId="11492" Text="|3d|transformations|mathematics|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25633" PostHistoryTypeId="4" PostId="9364" RevisionGUID="258f639a-2f33-4d93-afc6-026cc1dd21e6" CreationDate="2019-11-20T03:14:34.583" UserId="11492" Comment="edited title" Text="Visualize the interpolated unit quaternion on the surface of the unit sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="25634" PostHistoryTypeId="5" PostId="9364" RevisionGUID="258f639a-2f33-4d93-afc6-026cc1dd21e6" CreationDate="2019-11-20T03:14:34.583" UserId="11492" Comment="edited title" Text="My major is mechanical, please forgive me for asking questions that may seem trivial to you. I'm reading the following paper:&#xD;&#xA;&#xD;&#xA;&gt; Dam, Erik B., Martin Koch, and Martin Lillholm. Quaternions, interpolation and animation. Vol. 2. Copenhagen: Datalogisk Institut, Københavns Universitet, 1998.&#xD;&#xA;&#xD;&#xA;On page 35, it says:&#xD;&#xA;&#xD;&#xA;&gt; Since quaternion space is four-dimensional, we cannot visualise the interpolated curves directly. We will always interpolate between unit quaternions, and the interpolated quaternions will always (with a few exceptions in chapter 6 on page 38 and 69) be unit quaternions. This means that we only need three dimensions to visualize the interpolation curves, $\textbf{because they lie on the surface of the unit sphere.}$ &#xD;&#xA;&#xD;&#xA;I don't quite get the last sentence: why only three dimensions are needed to visualize the unit quaternion or why unit quaternion lies on the surface of the unit sphere? I thought they lie on the unit hyper-sphere. Does the author assume that we are viewing the quaternions from the south pole of the hyper-sphere?&#xD;&#xA;&#xD;&#xA;Any help is appreciated. Thank you. &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25635" PostHistoryTypeId="2" PostId="9365" RevisionGUID="40ba7ae3-b2d7-4511-93dd-755f7888f153" CreationDate="2019-11-20T13:02:34.687" UserId="137" Text="Because given 3 values of a unit quaterion we can derive the fourth value.&#xD;&#xA;&#xD;&#xA;Which means there exists a [bijective][1] mapping from unit quaternion to 3D space. &#xD;&#xA;&#xD;&#xA;Though for visualization you want the mapping that makes what is happening the most easily discernible. However a usable visualization doesn't need to be fully bijective.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bijection" ContentLicense="CC BY-SA 4.0" />
  <row Id="25636" PostHistoryTypeId="2" PostId="9366" RevisionGUID="9dbba1df-767d-4dbf-9433-8a6fb6a6ea09" CreationDate="2019-11-20T13:05:42.807" UserId="11466" Text="In [this post][1], Nathan-Reed gave a simple, neat, &quot;heuristic&quot; estimation for the discrete curvature at vertices of a mesh.&#xD;&#xA;&#xD;&#xA;In a nutshell, it computes a curvature *along* each edge incident to the vertex, then takes the geometric mean for the curvature in the vertex.&#xD;&#xA;&#xD;&#xA;My question is: why is it better to take the geometric mean, instead of the arithmetic mean?&#xD;&#xA;&#xD;&#xA;Is it because that would resemble somewhat Gaussian curvature?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/1718/what-is-the-simplest-way-to-compute-principal-curvature-for-a-mesh-triangle/9344?noredirect=1#comment14162_9344" ContentLicense="CC BY-SA 4.0" />
  <row Id="25637" PostHistoryTypeId="1" PostId="9366" RevisionGUID="9dbba1df-767d-4dbf-9433-8a6fb6a6ea09" CreationDate="2019-11-20T13:05:42.807" UserId="11466" Text="Question about simple estimation of the discrete curvature at vertices of a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="25638" PostHistoryTypeId="3" PostId="9366" RevisionGUID="9dbba1df-767d-4dbf-9433-8a6fb6a6ea09" CreationDate="2019-11-20T13:05:42.807" UserId="11466" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25639" PostHistoryTypeId="5" PostId="9364" RevisionGUID="209d71ba-b473-426e-b7f6-6423972721a3" CreationDate="2019-11-20T21:54:13.813" UserDisplayName="user106" Comment="formatting" Text="My major is mechanical, please forgive me for asking questions that may seem trivial to you. I'm reading the following paper:&#xD;&#xA;&#xD;&#xA;&gt; Dam, Erik B., Martin Koch, and Martin Lillholm. [Quaternions, interpolation and animation](https://archive.org/details/Erik_B_Dam_Martin_Koch_and_Martin_Lillholm___Quaternions_Interpolation_and_Animation). Vol. 2. Copenhagen: Datalogisk Institut, Københavns Universitet, 1998.&#xD;&#xA;&#xD;&#xA;On page 35, it says:&#xD;&#xA;&#xD;&#xA;&gt; Since quaternion space is four-dimensional, we cannot visualise the interpolated curves directly. We will always interpolate between unit quaternions, and the interpolated quaternions will always (with a few exceptions in chapter 6 on page 38 and 69) be unit quaternions. This means that we only need three dimensions to visualize the interpolation curves, **because they lie on the surface of the unit sphere.** &#xD;&#xA;&#xD;&#xA;I don't quite get the last sentence: why only three dimensions are needed to visualize the unit quaternion or why unit quaternion lies on the surface of the unit sphere? I thought they lie on the unit hyper-sphere. Does the author assume that we are viewing the quaternions from the south pole of the hyper-sphere?&#xD;&#xA;&#xD;&#xA;Any help is appreciated. Thank you. &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25640" PostHistoryTypeId="24" PostId="9364" RevisionGUID="209d71ba-b473-426e-b7f6-6423972721a3" CreationDate="2019-11-20T21:54:13.813" Comment="Proposed by 106 approved by 209, 11492 edit id of 496" ContentLicense="CC BY-SA 4.0" />
  <row Id="25641" PostHistoryTypeId="5" PostId="9364" RevisionGUID="13289f99-bc71-4fab-8413-df3d67710428" CreationDate="2019-11-20T22:00:10.297" UserId="11492" Comment="added 437 characters in body" Text="My major is mechanical, please forgive me for asking questions that may seem trivial to you. &#xD;&#xA;&#xD;&#xA;First, I'm reading the following paper:&#xD;&#xA;&#xD;&#xA;&gt; Dam, Erik B., Martin Koch, and Martin Lillholm. [Quaternions, interpolation and animation](https://archive.org/details/Erik_B_Dam_Martin_Koch_and_Martin_Lillholm___Quaternions_Interpolation_and_Animation). Vol. 2. Copenhagen: Datalogisk Institut, Københavns Universitet, 1998.&#xD;&#xA;&#xD;&#xA;On page 35, it says:&#xD;&#xA;&#xD;&#xA;&gt; Since quaternion space is four-dimensional, we cannot visualise the interpolated curves directly. We will always interpolate between unit quaternions, and the interpolated quaternions will always (with a few exceptions in chapter 6 on page 38 and 69) be unit quaternions. This means that we only need three dimensions to visualize the interpolation curves, **because they lie on the surface of the unit sphere.** &#xD;&#xA;&#xD;&#xA;I don't quite get the last sentence: why only three dimensions are needed to visualize the unit quaternion or why unit quaternion lies on the surface of the unit sphere? I thought they lie on the unit hyper-sphere. Does the author assume that we are viewing the quaternions from the south pole of the hyper-sphere?&#xD;&#xA;&#xD;&#xA;Second, I was also following this paper:&#xD;&#xA;&#xD;&#xA;&gt; Ramamoorthi, R., &amp; Barr, A. H. (1997). Fast construction of accurate quaternion splines.&#xD;&#xA;&#xD;&#xA;I found they are also treating (plotting) a unit quaternion as a point on a unit sphere $\mathbb{S}^{2}$. I wonder if you could recommend some resources in why we can view a unit quaternion $q = (a+b\mathbf{i}+c\mathbf{j}+d\mathbf{k})$ as a point on a unit sphere $\mathbb{S}^{2}$? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any help is appreciated. Thank you. &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25642" PostHistoryTypeId="2" PostId="9367" RevisionGUID="69219af8-e8ad-44c3-8dd4-0cfc28b7f192" CreationDate="2019-11-21T01:18:59.283" UserId="11497" Text="In computer graphics Bresenham's line drawing algorithm used to draw line . But i want to know the properties why i can't draw vertical and horizontal line by this algorithm." ContentLicense="CC BY-SA 4.0" />
  <row Id="25643" PostHistoryTypeId="1" PostId="9367" RevisionGUID="69219af8-e8ad-44c3-8dd4-0cfc28b7f192" CreationDate="2019-11-21T01:18:59.283" UserId="11497" Text="Is it possible to draw horizontal and vertical line with Bresenham's line drawing algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25644" PostHistoryTypeId="3" PostId="9367" RevisionGUID="69219af8-e8ad-44c3-8dd4-0cfc28b7f192" CreationDate="2019-11-21T01:18:59.283" UserId="11497" Text="|2d-graphics|line-drawing|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25645" PostHistoryTypeId="2" PostId="9368" RevisionGUID="ca474eb8-8c24-4038-9228-101af473890c" CreationDate="2019-11-21T08:18:16.893" UserId="2695" Text="I think Fig. 1 in the referenced paper is only a 2D-sketch, as the unit quaternions lie on the 3-dimensional sphere embedded in four dimensions. &#xD;&#xA;&#xD;&#xA;Quaternions are used to represent orientations / rotations and these can be associated with the axis-angle representation (determining the angle from the first quaternion coefficient and the axis from the last three coefficients.) However, I could think of a visualization in 3D, where a point in space is associated to a unit quaternion / or axis-angle: Place the point in direction of the axis &quot;angle&quot;-units away from the origin. This would be a sphere of radius two pi, where also internal points represent rotations. I dont know of a direct visualization in 3D of the quaternion coefficients. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25646" PostHistoryTypeId="5" PostId="8270" RevisionGUID="1311dcf9-a9d9-44be-ab1e-8b1a8d2685e4" CreationDate="2019-11-21T09:31:16.730" UserId="209" Comment="Minor improvements to text" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, i.e. a *total* of $4n-12$ control points , but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the correct matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; 2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;2 &amp; 5 &amp; -4 &amp; 7\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;First consider trying to go from BSpline to CR. If we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\begin{bmatrix}CR_0\\CR_1\\ ...\\CR_{n-1} \end{bmatrix} = M_{NxBtoCR}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;M_{NxBtoCR}= \frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;If we invert that matrix to get $M_{NxBtoCR}^{-1}$, one should then be able to map the other way. &#xD;&#xA;&#xD;&#xA;Using a maths package such as Maple, one finds that each row of $M_{NxBtoCR}^{-1}$ consists of the same set of values, all non-zero, which are progressively offset in each row. If we ignore the smaller terms, it suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;.&#xD;&#xA;&#xD;&#xA;*Update* Those weights don't *quite* sum to 1.0 - you'll need to normalise them slightly.&#xD;&#xA;&#xD;&#xA;Obviously, this has assumed the curve is a loop. It's probably possible to adjust the weights for the end points but I'll leave that as an exercise for the reader." ContentLicense="CC BY-SA 4.0" />
  <row Id="25648" PostHistoryTypeId="2" PostId="9369" RevisionGUID="f8e37831-bb0e-49fb-8846-f1ae72012bdb" CreationDate="2019-11-21T14:20:45.483" UserId="6346" Text="After watching some Youtube tutorials I thought I had understood the concept of UV mapping:&lt;br&gt;&#xD;&#xA;I have a net of triangles, and I have an image representing my texture.&lt;br&gt;&#xD;&#xA;Now I tell the GPU which point of the image shall be mapped to which point of my triangle net, and then some magic happens inside the GPU to generate a textured object.&lt;br&gt;&#xD;&#xA;IF I move a point of a triangle, the mapped texture is distorted accordingly.&lt;br&gt;&#xD;&#xA;Correct so far?&lt;br&gt;&#xD;&#xA;Now I read somewhere the following &quot;specification&quot; regarding UV mapping on a planar surface:&lt;br&gt;&#xD;&#xA;&#xD;&#xA;A three pixel wide texture belongs to every single triangle.&lt;br&gt;&#xD;&#xA;Per triangle the following UV mapping shall be used:&lt;br&gt;&#xD;&#xA;triangle point A: UV(0.2, 0.5)&lt;br&gt;&#xD;&#xA;triangle point B: UV(0.5, 0.5)&lt;br&gt;&#xD;&#xA;triangle point C: UV(0.8, 0.5)&#xD;&#xA;&#xD;&#xA;How does this make sense?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25649" PostHistoryTypeId="1" PostId="9369" RevisionGUID="f8e37831-bb0e-49fb-8846-f1ae72012bdb" CreationDate="2019-11-21T14:20:45.483" UserId="6346" Text="UV mapping on triangles" ContentLicense="CC BY-SA 4.0" />
  <row Id="25650" PostHistoryTypeId="3" PostId="9369" RevisionGUID="f8e37831-bb0e-49fb-8846-f1ae72012bdb" CreationDate="2019-11-21T14:20:45.483" UserId="6346" Text="|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25652" PostHistoryTypeId="5" PostId="9369" RevisionGUID="4bbbda42-d6dd-424f-baab-8552712af8ab" CreationDate="2019-11-21T15:52:09.027" UserId="6346" Comment="problem clarified " Text="After watching some Youtube tutorials I thought I had understood the concept of UV mapping:&lt;br&gt;&#xD;&#xA;I have a net of triangles, and I have an image representing my texture.&lt;br&gt;&#xD;&#xA;Now I tell the GPU which point of the image shall be mapped to which point of my triangle net, and then some magic happens inside the GPU to generate a textured object.&lt;br&gt;&#xD;&#xA;IF I move a point of a triangle, the mapped texture is distorted accordingly.&lt;br&gt;&#xD;&#xA;Correct so far?&lt;br&gt;&#xD;&#xA;Now I read somewhere the following &quot;specification&quot; regarding UV mapping on a planar surface:&lt;br&gt;&#xD;&#xA;&#xD;&#xA;A three pixel wide texture belongs to every single triangle.&lt;br&gt;&#xD;&#xA;Per triangle the following UV mapping shall be used:&lt;br&gt;&#xD;&#xA;triangle point A: UV(0.2, 0.5)&lt;br&gt;&#xD;&#xA;triangle point B: UV(0.5, 0.5)&lt;br&gt;&#xD;&#xA;triangle point C: UV(0.8, 0.5)&#xD;&#xA;&#xD;&#xA;My problem is that I don't understand what the author means:&lt;br&gt;&#xD;&#xA;I have a three pixel wide texture, values are... whatever... 2,4,6. &lt;br&gt;Let's define coordinate 0, 0 for the left pixel and 1, 0 for the right one.&lt;br&gt; Then UV(0.2,0.5) means that point A of my triangle shall have value (0.8 * 2) + (0.2 * 4) = 2.4, point B then has value 4 (it's in the middle) and point C has value (0.2 * 4) + (0.8 * 6) = 5.6. &#xD;&#xA;&lt;br&gt;Is it so?&lt;br&gt;&#xD;&#xA;And all other points of the triangle are interpolated according to their coordinates based on these three corners? Or what happens to them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25654" PostHistoryTypeId="2" PostId="9370" RevisionGUID="cec1b8ea-da19-48a2-bf66-ca633ef4e037" CreationDate="2019-11-23T12:11:12.307" UserId="11452" Text="I am not sure what is the correct way to do tone mapping and gamma correction in a Monte-Carlo Path Tracer. Should I apply tone mapping before or after averaging the samples?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25655" PostHistoryTypeId="1" PostId="9370" RevisionGUID="cec1b8ea-da19-48a2-bf66-ca633ef4e037" CreationDate="2019-11-23T12:11:12.307" UserId="11452" Text="Path tracing: How to do tone mapping and gamma correction?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25656" PostHistoryTypeId="3" PostId="9370" RevisionGUID="cec1b8ea-da19-48a2-bf66-ca633ef4e037" CreationDate="2019-11-23T12:11:12.307" UserId="11452" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25657" PostHistoryTypeId="2" PostId="9371" RevisionGUID="bc6288dd-77fa-425d-8e52-20cea913c882" CreationDate="2019-11-23T21:03:09.270" UserId="8432" Text="A [question][1] has come up recently in Blender SE, remarking on the *absence* of blur due to depth of field in reflections in a spherical surface. This is a real-life effect.. can anyone come up with a nice explanation of it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://blender.stackexchange.com/q/158942/35559" ContentLicense="CC BY-SA 4.0" />
  <row Id="25658" PostHistoryTypeId="1" PostId="9371" RevisionGUID="bc6288dd-77fa-425d-8e52-20cea913c882" CreationDate="2019-11-23T21:03:09.270" UserId="8432" Text="Why are reflections in a spherical surface sharp, regardless of depth of field?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25659" PostHistoryTypeId="3" PostId="9371" RevisionGUID="bc6288dd-77fa-425d-8e52-20cea913c882" CreationDate="2019-11-23T21:03:09.270" UserId="8432" Text="|reflection|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25660" PostHistoryTypeId="2" PostId="9372" RevisionGUID="9dc8e377-0fc0-4597-b424-2b1e5b73f10c" CreationDate="2019-11-24T02:55:31.043" UserId="11518" Text="I have an OpenGL based graphics engine coming along quite nicely, but I'm currently stumped on a problem that arose after adding a new vertex shader output array.&#xD;&#xA;&#xD;&#xA;The vertex shader is outputing the usual things one would calculate per vertex to minimise fragment processing - eg fragment locations in tangent and light space etc which are done on a per light basis with currently an 8 light max per lighting zone.  Structure as below.&#xD;&#xA;&#xD;&#xA;    #version 460&#xD;&#xA;    const int cMaxZoneLightCount = 8;&#xD;&#xA;    &#xD;&#xA;    out vData&#xD;&#xA;    {&#xD;&#xA;    	vec3 vFragmentLocationWorld;  //  This vertice's location in world coords&#xD;&#xA;    	vec2 vTextureUV;&#xD;&#xA;    	vec4 vNormal;&#xD;&#xA;    	vec4 vFragmentLocationLightSpace[cMaxZoneLightCount];  // Light space location per light (up to 8)&#xD;&#xA;    	vec4 vFragmentLocationTextureSpace[cMaxZoneLightCount]; //  Transform for projective texture lights&#xD;&#xA;    	vec4 vViewLocationTangent;&#xD;&#xA;    	vec4 vFragmentLocationTangent;  //  Tangent space transforms for normal mapping&#xD;&#xA;    	vec4 vLightLocationTangent[cMaxZoneLightCount];  // Light locations in tangent space (up to 8)&#xD;&#xA;    	vec4 vLightMRPTangent[cMaxZoneLightCount];  //  MRP for tube lights in tangent space (up to 8)&#xD;&#xA;    	vec4 vTangent;&#xD;&#xA;    	vec4 vBitangent;  //  Pre computed vertex tangent/bitangent data.&#xD;&#xA;    }   vDataOut;&#xD;&#xA;&#xD;&#xA;Everything was working fine until I added the vLightMRPTangent[cMaxZoneLightCount] array.  Adding that brings the total number of vertex outputs to 153 and I receive error C5041 when the shader compiles - &quot;cannot located suitable resources to bind variable... possibly large array&quot;.&#xD;&#xA;&#xD;&#xA;This is strange though because an int mvoc = GL_MAX_VERTEX_OUTPUT_COMPONENTS returns 37,154.&#xD;&#xA;&#xD;&#xA;Now, the interesting thing is - if I make vLightMRPTangent[2] instead of 8, this brings the number of vertex shader outputs down to 129 and it works.  Similarly, a vLightMRPTangent[3] which would put it up to 133 output components generates a different but verbose and nasty link failure message.&#xD;&#xA;&#xD;&#xA;So it's looking a lot like my still formidible GTX970 only wants to send 128 components down the pipeline!! (tell me that can't be right...)&#xD;&#xA;&#xD;&#xA;I'm developing on Windows 10 with GLEW v2.1 and the November 2019 nVidia driver.  I'm not using any other extensions/libraries, eg glm/glut (doing all my matrix work myself).&#xD;&#xA;&#xD;&#xA;I can get around this by implementing subsequent features per pixel rather than per vertex, but that's a real pain because its going to result in sub-optimal efficiency which could become a big problem later.&#xD;&#xA;&#xD;&#xA;Any ideas anyone?&#xD;&#xA;&#xD;&#xA;Cheers,&#xD;&#xA;MWS&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25661" PostHistoryTypeId="1" PostId="9372" RevisionGUID="9dc8e377-0fc0-4597-b424-2b1e5b73f10c" CreationDate="2019-11-24T02:55:31.043" UserId="11518" Text="Stumped on GLSL error C5041 (cannot located suitable resources to bind variable... possibly large array" ContentLicense="CC BY-SA 4.0" />
  <row Id="25662" PostHistoryTypeId="3" PostId="9372" RevisionGUID="9dc8e377-0fc0-4597-b424-2b1e5b73f10c" CreationDate="2019-11-24T02:55:31.043" UserId="11518" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25663" PostHistoryTypeId="5" PostId="3887" RevisionGUID="6c9b1db4-e1ff-4e56-8139-cb1acb37e846" CreationDate="2019-11-24T03:49:57.477" UserId="11503" Comment="Update the outdated hyperlink." Text="I'm writing my implementation of ray tracer and I've got result which you can see at this image.&#xD;&#xA;&#xD;&#xA;![img](https://i.stack.imgur.com/tFCEf.png)&#xD;&#xA;So you can see that some dark parts are overlapping. And I have them even in the part where it should be bright in my opinion. There are two lights one from above and the second one from right-bottom corner.&#xD;&#xA;&#xD;&#xA;And I have two questions. Is it right? I really tried to google some references but failed. I'm not still sure that results in my imagination are correct ones.&#xD;&#xA;&#xD;&#xA;And the second one where does it come from?&#xD;&#xA;&#xD;&#xA;I use usual lambertian shading model and have something like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = (0, 0, 0)&#xD;&#xA;    normal = get normal of sphere in point of intersection;&#xD;&#xA;    normal = unit vector of normal;&#xD;&#xA;    for each light from light_set {&#xD;&#xA;        light = unit vector of light;&#xD;&#xA;        pixel = pixel + diffuseColor * max(0, scalar multiplication of light and normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm really struggling to find out the reason where this strange thing is coming from. But couldn't find it.&#xD;&#xA;&#xD;&#xA;UPD0: added some of my real code. The part which is described here is next:&#xD;&#xA;&#xD;&#xA;    Material mat = surfaces[closestSurfase]-&gt;getMaterial();&#xD;&#xA;    Color pixel = Color(0, 0, 0);&#xD;&#xA;    Vector3f normal = surfaces[closestSurfase]-&gt;getNormal(point).getUnitVector();&#xD;&#xA;    Vector3f view = -ray.getDirection().getUnitVector();&#xD;&#xA;    for (size_t i = 0; i &lt; lights.size(); ++i) {&#xD;&#xA;        Vector3f normal_light = lights[i]-&gt;getDirection().getUnitVector();&#xD;&#xA;        Vector3f specVect = (normal_light + view).getUnitVector();&#xD;&#xA;        float intenst = lights[i]-&gt;getIntensity();&#xD;&#xA;        pixel = pixel + mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;    }&#xD;&#xA;    result-&gt;setPixel(x, y, pixel);&#xD;&#xA;&#xD;&#xA;Or you can find more here: https://github.com/minebv/ray_tracer/tree/lambertian_shading_fix/src&#xD;&#xA;&#xD;&#xA;Described above is from Camera's method getRender.&#xD;&#xA;&#xD;&#xA;UPD1: It looks like the problem in the mixing colors in gamma space instead linear one, as answered @PaulHK .&#xD;&#xA;&#xD;&#xA;But I've still some kind of problem. Here you can see 2 renders.&#xD;&#xA;![img1](https://i.stack.imgur.com/HNclL.png)&#xD;&#xA;At the left one I make all work after transformation all colors into linear space, I mean it's like this in my code:&#xD;&#xA;&#xD;&#xA;    pixel = pixel + mat.getDiffuse().toLinear() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst;&#xD;&#xA;&#xD;&#xA;At the right one I make transformation after multiplying:&#xD;&#xA;&#xD;&#xA;    pixel = pixel + (mat.getDiffuse() * std::max(0.0f, normal_light.dotMultiply(normal)) * intenst).toLinear();&#xD;&#xA;&#xD;&#xA;And I didn't forget to make pixel into gamma space again after all job.&#xD;&#xA;&#xD;&#xA;As for me, the right one is more correct. But then there is a question: why should I make multiplication on angle into gamma space? Or is it my incorrect way to think about what is right?&#xD;&#xA;&#xD;&#xA;UPD3:it looks like the whole thing really was about mixing colors in gamma space instead of linear one. Here is result with ambient light.&#xD;&#xA;![img3](https://i.stack.imgur.com/DOjAR.png)&#xD;&#xA;&#xD;&#xA;Also about overlapping lights, it was my incorrect way of thinking. I finally found reference material where they have the same thing. Found it at blender [docs](https://docs.blender.org/manual/en/2.79/render/blender_render/materials/properties/specular_shaders.html#cook-torrance).&#xD;&#xA;&#xD;&#xA;Thank everyone for answers." ContentLicense="CC BY-SA 4.0" />
  <row Id="25664" PostHistoryTypeId="24" PostId="3887" RevisionGUID="6c9b1db4-e1ff-4e56-8139-cb1acb37e846" CreationDate="2019-11-24T03:49:57.477" Comment="Proposed by 11503 approved by 4966 edit id of 498" ContentLicense="CC BY-SA 4.0" />
  <row Id="25665" PostHistoryTypeId="2" PostId="9373" RevisionGUID="50bba93d-6952-4ac5-b96b-04ea3a3d5759" CreationDate="2019-11-24T08:08:59.683" UserId="10096" Text="Because the ball doesn't &quot;see&quot; the world through an imperfect lens system, whereas your camera in that case does. If you were to introduce an imperfect visual system around it, with a resulting blurring point spread function, you will get a blurry reflection." ContentLicense="CC BY-SA 4.0" />
  <row Id="25666" PostHistoryTypeId="2" PostId="9374" RevisionGUID="7f35d639-f148-4bb1-b81a-f70299b6866a" CreationDate="2019-11-24T14:43:33.590" UserId="11519" Text="I've just worked my way through [this OpenGL shadow mapping tutorial][1].&#xD;&#xA;While I understand the basic algorithm, one thing puzzles me:&#xD;&#xA;During the 2nd render pass all vertices are transformed into the clip space of the light source. This is done by multiplying them with the light's view-projection matrix in the vertex shader:&#xD;&#xA;&#xD;&#xA;    vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);&#xD;&#xA;&#xD;&#xA;However, for texture lookup into the shadow map a perspective division is needed. This is done in the fragment shader:&#xD;&#xA;&#xD;&#xA;    float ShadowCalculation(vec4 fragPosLightSpace)&#xD;&#xA;    {&#xD;&#xA;        // perform perspective divide&#xD;&#xA;        vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;&#xD;&#xA;        //continue w. texture lookup&#xD;&#xA;        [...]&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So my question is - why can't I perform the perspective division in the vertex shader? I did try moving the division from fragment to vertex shader in my otherwise finished shadow mapping code, and ended up with some really weird artifacts. So I guess it has something to do with the interpolation performed by the rasterizer, but I would like a more detailed explanation if possible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="25667" PostHistoryTypeId="1" PostId="9374" RevisionGUID="7f35d639-f148-4bb1-b81a-f70299b6866a" CreationDate="2019-11-24T14:43:33.590" UserId="11519" Text="Projective Texture / Shadow Mapping -- Why is the perspective division performed in the fragment shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25668" PostHistoryTypeId="3" PostId="9374" RevisionGUID="7f35d639-f148-4bb1-b81a-f70299b6866a" CreationDate="2019-11-24T14:43:33.590" UserId="11519" Text="|opengl|glsl|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25669" PostHistoryTypeId="2" PostId="9375" RevisionGUID="9db656eb-f42c-4616-a92e-fc2dc74c3311" CreationDate="2019-11-24T14:44:46.197" UserId="2654" Text="&gt; This is strange though because an int mvoc = GL_MAX_VERTEX_OUTPUT_COMPONENTS returns 37,154.&#xD;&#xA;&#xD;&#xA;That's the value of the *enumerator*; it's a static, compile-time value. The actual runtime limit is queried from the implementation *using* that enumerator. Typically via `glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &amp;mvoc)`.&#xD;&#xA;&#xD;&#xA;&gt; tell me that can't be right...&#xD;&#xA;&#xD;&#xA;Why not? Sending 128 components *per vertex* is plenty.&#xD;&#xA;&#xD;&#xA;You shouldn't be doing transformations into light-space in your VS; that should happen in your fragment shader. You should be sending the basic information to the FS needed for it to do its job: normals (and tangent/bitangent as needed), texture coordinates, etc.&#xD;&#xA;&#xD;&#xA;If you find that your FS's performance is not what it needs to be, then the best thing you can do is reduce the number of FS executions. You can use a depth pre-pass to eliminate overdraw, so the only FS executions that happen are those which produces an actual visible element. Or you can go to full-on deferred rendering.&#xD;&#xA;&#xD;&#xA;But this method of pre-computing large quantities of data per-vertex is not going to work. Interpolation of vertex data is not free, nor are the caches between the VS and the rasterizer." ContentLicense="CC BY-SA 4.0" />
  <row Id="25670" PostHistoryTypeId="50" PostId="6094" RevisionGUID="2237f47a-c2b4-41f0-9633-d42a4730ba09" CreationDate="2019-11-24T18:02:15.310" UserId="-1" />
  <row Id="25671" PostHistoryTypeId="5" PostId="3892" RevisionGUID="014f202b-821e-4dad-b014-f717a68d688e" CreationDate="2019-11-25T12:11:19.520" UserId="11503" Comment="Update the outdated hyperlink." Text="I think what you're describing is what happens when you mix colours in gamma space. You should be using linear colour space when mixing.&#xD;&#xA;&#xD;&#xA;When reading colours of lights and materials, convert them from gamma-&gt;linear using the inverse gamma function.&#xD;&#xA;&#xD;&#xA;    colourLin = pow(colourLight, 2.2);&#xD;&#xA;    ... do lambert calculation here and accumulate in 'colour' variable ..&#xD;&#xA;&#xD;&#xA;    // On output (linear-&gt;gamma conversion)&#xD;&#xA;    gl_FragColor = pow(colour, 1.0/2.2);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There is an in depth chapter in GPU Gems on this topic: [The Importance of Being Linear](https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch24.html).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25672" PostHistoryTypeId="24" PostId="3892" RevisionGUID="014f202b-821e-4dad-b014-f717a68d688e" CreationDate="2019-11-25T12:11:19.520" Comment="Proposed by 11503 approved by 209, 6 edit id of 497" ContentLicense="CC BY-SA 4.0" />
  <row Id="25673" PostHistoryTypeId="5" PostId="8886" RevisionGUID="f3360e20-f04c-4219-a72a-841f1a3b44bf" CreationDate="2019-11-25T12:11:27.643" UserId="11503" Comment="Fix a few typos." Text="I'm trying to understand and learn WebGL and computer graphics from the bottom  up, that is why I started to work on my own little library for that. I've spent a couple of days looking for a right answer but I can't make it work.&#xD;&#xA;&#xD;&#xA;I have column major matrices and I'm just trying to render a basic rectangle but for some reason no matter what I do after multiplication by a perspective matrix the vertex's Z is always out of bounds.&#xD;&#xA;&#xD;&#xA;My perspective matrix calculation : &#xD;&#xA;&#xD;&#xA;    static perspective(fov, aspect, near, far) {&#xD;&#xA;        const r = fov * aspect;&#xD;&#xA;        const l = -4;&#xD;&#xA;        const t = r;&#xD;&#xA;        const b = l;&#xD;&#xA;        const matrix = new Matrix4();&#xD;&#xA;        matrix.n11 = (2 * near) / (r - l);&#xD;&#xA;        matrix.n12 = 0;&#xD;&#xA;        matrix.n13 = (r+l)/(r-l);&#xD;&#xA;        matrix.n14 = 0;&#xD;&#xA;        matrix.n21 = 0;&#xD;&#xA;        matrix.n22 = (2 * near) / (t - b);&#xD;&#xA;        matrix.n23 = (t+b)/(t-b);&#xD;&#xA;        matrix.n24 = 0;&#xD;&#xA;        matrix.n31 = 0;&#xD;&#xA;        matrix.n32 = 0;&#xD;&#xA;        matrix.n33 = (near + far) / (near - far);&#xD;&#xA;        matrix.n34 = (2 * near * far) / (near - far);&#xD;&#xA;        matrix.n41 = 0;&#xD;&#xA;        matrix.n42 = 0;&#xD;&#xA;        matrix.n43 = -1;&#xD;&#xA;        matrix.n44 = 0;&#xD;&#xA;        return matrix;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My vertex shader:&#xD;&#xA;&#xD;&#xA;     this.vertexShaderScript =&#xD;&#xA;            '\r\n' +&#xD;&#xA;            'precision highp float;\r\n' +&#xD;&#xA;            'uniform mat4 u_model;\r\n' +&#xD;&#xA;            'uniform mat4 u_view;\r\n' +&#xD;&#xA;            'uniform mat4 u_projection;\r\n' +&#xD;&#xA;            'attribute vec3 a_position;\r\n' +&#xD;&#xA;            'attribute vec4 a_color;\r\n' +&#xD;&#xA;            'varying vec4 v_color;\r\n' +&#xD;&#xA;            'void main(void) {\r\n' +&#xD;&#xA;            '    v_color = a_color;\r\n' +&#xD;&#xA;            '    gl_Position = u_projection * u_view *  u_model * vec4(a_position, 1.0);\r\n' +&#xD;&#xA;            '}\r\n';" ContentLicense="CC BY-SA 4.0" />
  <row Id="25674" PostHistoryTypeId="24" PostId="8886" RevisionGUID="f3360e20-f04c-4219-a72a-841f1a3b44bf" CreationDate="2019-11-25T12:11:27.643" Comment="Proposed by 11503 approved by 209, 6 edit id of 499" ContentLicense="CC BY-SA 4.0" />
  <row Id="25675" PostHistoryTypeId="2" PostId="9376" RevisionGUID="999213a8-2415-4dc5-9f23-40ce5032a7ed" CreationDate="2019-11-25T16:37:21.293" UserId="11521" Text="As far as I know path tracers (or super-sampling antialiasing) typically calculate the final color of a single pixel by averaging the result of all samples taken inside that pixel. This gives a nice anti-aliasing effect on the edges, however has the side effect of slightly blurring textures, because they most certainly do not have enough samples for each pixel, so samples have to be guessed with some kind of filter (like bilinear). From a mathematical point of view, averaging those samples applies a box low-pass filter to the reconstructed texture. This causes blurring.&#xD;&#xA;&#xD;&#xA;How do path traced renderers/SSAA usually deal with this blur? Is there no way around it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25676" PostHistoryTypeId="1" PostId="9376" RevisionGUID="999213a8-2415-4dc5-9f23-40ce5032a7ed" CreationDate="2019-11-25T16:37:21.293" UserId="11521" Text="Multiple samples per pixel and texture blurring" ContentLicense="CC BY-SA 4.0" />
  <row Id="25677" PostHistoryTypeId="3" PostId="9376" RevisionGUID="999213a8-2415-4dc5-9f23-40ce5032a7ed" CreationDate="2019-11-25T16:37:21.293" UserId="11521" Text="|pathtracing|sampling|antialiasing|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25678" PostHistoryTypeId="2" PostId="9377" RevisionGUID="6eec6844-e6cb-44f1-bc32-34aded0cdfdf" CreationDate="2019-11-25T17:58:40.240" UserId="11452" Text="Is the normal distribution term D in the Cook-Torrance BRDF supposed to be between 0 and 1? What does this number actually represent?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25679" PostHistoryTypeId="1" PostId="9377" RevisionGUID="6eec6844-e6cb-44f1-bc32-34aded0cdfdf" CreationDate="2019-11-25T17:58:40.240" UserId="11452" Text="Value range of normal distribution function" ContentLicense="CC BY-SA 4.0" />
  <row Id="25680" PostHistoryTypeId="3" PostId="9377" RevisionGUID="6eec6844-e6cb-44f1-bc32-34aded0cdfdf" CreationDate="2019-11-25T17:58:40.240" UserId="11452" Text="|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25682" PostHistoryTypeId="5" PostId="9334" RevisionGUID="3033fd74-527d-416e-b7cb-0c9c5aeaae75" CreationDate="2019-11-27T17:07:26.203" UserId="11316" Comment="deleted 1 character in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;&#xD;&#xA;EDIT 2: I sample primary rays randomly in each pixel without jittering. Is it the cause of moire effect? Do I have to use stratified sampling?&#xD;&#xA;&#xD;&#xA;EDIT 3: I have to show some parts of code:&#xD;&#xA;This function generates a ray inside patches on sphere:&#xD;&#xA;&#xD;&#xA;    function Q_dir(ith::Int64)&#xD;&#xA;        i = ceil(Int64, ith/H)&#xD;&#xA;        j = ith - H*(i-1)&#xD;&#xA;        u = (i-rand())/V&#xD;&#xA;        ϕ = 2π*(j-rand())/H&#xD;&#xA;        return Vec3(cos(ϕ)*sqrt(1.0 - u*u), sin(ϕ)*sqrt(1.0 - u*u), u)&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;This function returns the index of a rectangular cell on each plane which contains the hit point:&#xD;&#xA;&#xD;&#xA;    function find_state(a::Float64, a1::Float64, a2::Float64, b::Float64, b1::Float64, b2::Float64)&#xD;&#xA;        return [ceil(Int64, M*(abs(a)/(a2-a1))),   ceil(Int64, N*(abs(b)/(b2-b1)))]&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;Ant this intersection function, returns the hit point and the cell&#xD;&#xA;&#xD;&#xA;    function intersect!(plane::xzPlane, ray::Ray)&#xD;&#xA;        x1 = plane.a1&#xD;&#xA;        x2 = plane.a2&#xD;&#xA;        z1 = plane.b1&#xD;&#xA;        z2 = plane.b2&#xD;&#xA;        t = (plane.y - ray.org.y)/ray.dir.y&#xD;&#xA;        point = ray.org + t*ray.dir&#xD;&#xA;        if x1 &lt; point.x &lt; x2 &amp;&amp; z1 &lt; point.z &lt; z2 &amp;&amp; 0 &lt; t&#xD;&#xA;            hsect, wsect = find_state(point.x, x1, x2, point.z, z1, z2)&#xD;&#xA;            normal = Vec3(0,1,0)&#xD;&#xA;            return HitPoint(t, point , normal, hsect, wsect)&#xD;&#xA;        else&#xD;&#xA;            return HitPoint()&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;The problem is surely related to this part, because I can reproduce the results of the paper. My only problem is this artifact.&#xD;&#xA;&#xD;&#xA;EDIT 4: When I generate a ray uniformly through each uniformly selected stratum, everything works fine. But when I generate a ray uniformly through importance sampled stratum (each stratum has a different value), I encounter this problem. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25683" PostHistoryTypeId="5" PostId="9334" RevisionGUID="44338563-ab66-4ded-8fcb-ee1abeb7e78f" CreationDate="2019-11-27T17:16:22.477" UserId="11316" Comment="deleted 1 character in body" Text="I have written some path tracers. But some of them suffer from moire effect. Some of the patterns look like a regular grid and the rest look like concentric circles or even more complicated shapes. What is the best way to get rid of them completely? How are they generated?&#xD;&#xA;&#xD;&#xA;EDIT: I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT 2: I sample primary rays randomly in each pixel without jittering. Is it the cause of moire effect? Do I have to use stratified sampling?&#xD;&#xA;&#xD;&#xA;EDIT 3: I have to show some parts of code:&#xD;&#xA;This function generates a ray inside patches on sphere:&#xD;&#xA;&#xD;&#xA;    function Q_dir(ith::Int64)&#xD;&#xA;        i = ceil(Int64, ith/H)&#xD;&#xA;        j = ith - H*(i-1)&#xD;&#xA;        u = (i-rand())/V&#xD;&#xA;        ϕ = 2π*(j-rand())/H&#xD;&#xA;        return Vec3(cos(ϕ)*sqrt(1.0 - u*u), sin(ϕ)*sqrt(1.0 - u*u), u)&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;This function returns the index of a rectangular cell on each plane which contains the hit point:&#xD;&#xA;&#xD;&#xA;    function find_state(a::Float64, a1::Float64, a2::Float64, b::Float64, b1::Float64, b2::Float64)&#xD;&#xA;        return [ceil(Int64, M*(abs(a)/(a2-a1))),   ceil(Int64, N*(abs(b)/(b2-b1)))]&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;Ant this intersection function, returns the hit point and the cell&#xD;&#xA;&#xD;&#xA;    function intersect!(plane::xzPlane, ray::Ray)&#xD;&#xA;        x1 = plane.a1&#xD;&#xA;        x2 = plane.a2&#xD;&#xA;        z1 = plane.b1&#xD;&#xA;        z2 = plane.b2&#xD;&#xA;        t = (plane.y - ray.org.y)/ray.dir.y&#xD;&#xA;        point = ray.org + t*ray.dir&#xD;&#xA;        if x1 &lt; point.x &lt; x2 &amp;&amp; z1 &lt; point.z &lt; z2 &amp;&amp; 0 &lt; t&#xD;&#xA;            hsect, wsect = find_state(point.x, x1, x2, point.z, z1, z2)&#xD;&#xA;            normal = Vec3(0,1,0)&#xD;&#xA;            return HitPoint(t, point , normal, hsect, wsect)&#xD;&#xA;        else&#xD;&#xA;            return HitPoint()&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;The problem is surely related to this part, because I can reproduce the results of the paper. My only problem is this artifact.&#xD;&#xA;&#xD;&#xA;EDIT 4: When I generate a ray uniformly through each uniformly selected stratum, everything works fine. But when I generate a ray uniformly through importance sampled stratum (each stratum has a different value), I encounter this problem. &#xD;&#xA;&#xD;&#xA;EDIT 5: Sampling discretized hemisphere is surely part of the problem. I guess the Q_dir function is causing some problems. Here is another generated photo:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;H in Q-dir function is equal to 6. The number of half-lines generated on the floor equals 6. So this sampling method is incorrect. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vmYeF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25684" PostHistoryTypeId="2" PostId="9378" RevisionGUID="edbd34c5-54ea-4aac-bfca-62e853211322" CreationDate="2019-11-27T18:15:23.493" UserId="2654" Text="In signal processing, it is well-understood that you cannot accurately reproduce an analog signal of higher frequency than half the frequency of your digital sampling rate. That's just how the math works. Various aspects of rendering are just forms of signal processing, so this applies here too.&#xD;&#xA;&#xD;&#xA;So you're going to get some kind of artifact. You have a choice: aliasing or noise (aka: blur). You're always going to have some of these. Aliasing artifacts are usually very noticeable and considered quite distracting. Human vision tends to focus on motion, and aliasing artifacts almost always create motion where none existed (*especially* when animating). Human vision is generally much more tolerant of noise, as noise patterns don't appear to move nearly as much. Plus, our eyes have their own anti-aliasing filters that impart some noise to what we see, so we're somewhat used to it.&#xD;&#xA;&#xD;&#xA;Broadly speaking, you deal with it by not dealing with it, because it's preferable to the alternative. Yes, you can reduce the effect of noise with better anti-aliasing mechanisms, but broadly speaking, you're still going to have noise." ContentLicense="CC BY-SA 4.0" />
  <row Id="25685" PostHistoryTypeId="5" PostId="9334" RevisionGUID="7d7f1550-11b4-4470-9898-ec2a03be2fb9" CreationDate="2019-11-28T17:39:20.870" UserId="11316" Comment="deleted 195 characters in body; edited title" Text="I have implemented a ray tracer using reinforcement learning. But I see some problems.&#xD;&#xA;I tried to divide the planes into rectangular grids. I searched the moire effect and realized that I can solve my problem by adding noise ( for example $\epsilon = 1e-5$) to the hit points on the diffuse surfaces, but even after doing this, I haven't seen any change. I created grid using ceiling function.&#xD;&#xA;&#xD;&#xA;It seems that I shouldn't use the ceiling function (to understand which cell current hit point is in) and use another algorithm to find in which rectangular cells, the hit points are. Could someone tell me which algorithm to use?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT 2: I sample primary rays randomly in each pixel without jittering. Is it the cause of moire effect? Do I have to use stratified sampling?&#xD;&#xA;&#xD;&#xA;EDIT 3: I have to show some parts of code:&#xD;&#xA;This function generates a ray inside patches on sphere:&#xD;&#xA;&#xD;&#xA;    function Q_dir(ith::Int64)&#xD;&#xA;        i = ceil(Int64, ith/H)&#xD;&#xA;        j = ith - H*(i-1)&#xD;&#xA;        u = (i-rand())/V&#xD;&#xA;        ϕ = 2π*(j-rand())/H&#xD;&#xA;        return Vec3(cos(ϕ)*sqrt(1.0 - u*u), sin(ϕ)*sqrt(1.0 - u*u), u)&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;This function returns the index of a rectangular cell on each plane which contains the hit point:&#xD;&#xA;&#xD;&#xA;    function find_state(a::Float64, a1::Float64, a2::Float64, b::Float64, b1::Float64, b2::Float64)&#xD;&#xA;        return [ceil(Int64, M*(abs(a)/(a2-a1))),   ceil(Int64, N*(abs(b)/(b2-b1)))]&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;Ant this intersection function, returns the hit point and the cell&#xD;&#xA;&#xD;&#xA;    function intersect!(plane::xzPlane, ray::Ray)&#xD;&#xA;        x1 = plane.a1&#xD;&#xA;        x2 = plane.a2&#xD;&#xA;        z1 = plane.b1&#xD;&#xA;        z2 = plane.b2&#xD;&#xA;        t = (plane.y - ray.org.y)/ray.dir.y&#xD;&#xA;        point = ray.org + t*ray.dir&#xD;&#xA;        if x1 &lt; point.x &lt; x2 &amp;&amp; z1 &lt; point.z &lt; z2 &amp;&amp; 0 &lt; t&#xD;&#xA;            hsect, wsect = find_state(point.x, x1, x2, point.z, z1, z2)&#xD;&#xA;            normal = Vec3(0,1,0)&#xD;&#xA;            return HitPoint(t, point , normal, hsect, wsect)&#xD;&#xA;        else&#xD;&#xA;            return HitPoint()&#xD;&#xA;        end&#xD;&#xA;    end&#xD;&#xA;&#xD;&#xA;The problem is surely related to this part, because I can reproduce the results of the paper. My only problem is this artifact.&#xD;&#xA;&#xD;&#xA;EDIT 4: When I generate a ray uniformly through each uniformly selected stratum, everything works fine. But when I generate a ray uniformly through importance sampled stratum (each stratum has a different value), I encounter this problem. &#xD;&#xA;&#xD;&#xA;EDIT 5: Sampling discretized hemisphere is surely part of the problem. I guess the Q_dir function is causing some problems. Here is another generated photo:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;H in Q-dir function is equal to 6. The number of half-lines generated on the floor equals 6. So this sampling method is incorrect. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xPBD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vmYeF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25686" PostHistoryTypeId="4" PostId="9334" RevisionGUID="7d7f1550-11b4-4470-9898-ec2a03be2fb9" CreationDate="2019-11-28T17:39:20.870" UserId="11316" Comment="deleted 195 characters in body; edited title" Text="Strange behaviour when tracing rays through hemisphere patches" ContentLicense="CC BY-SA 4.0" />
  <row Id="25687" PostHistoryTypeId="2" PostId="9379" RevisionGUID="dd58ca4d-1944-432c-8d3a-a3fcf83e7f2f" CreationDate="2019-11-28T19:29:32.677" UserId="11316" Text="Why should we use Russian Roulette? Does it reduce ray tracing artifacts? " ContentLicense="CC BY-SA 4.0" />
  <row Id="25688" PostHistoryTypeId="1" PostId="9379" RevisionGUID="dd58ca4d-1944-432c-8d3a-a3fcf83e7f2f" CreationDate="2019-11-28T19:29:32.677" UserId="11316" Text="Why is Russian Roulette used in ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25689" PostHistoryTypeId="3" PostId="9379" RevisionGUID="dd58ca4d-1944-432c-8d3a-a3fcf83e7f2f" CreationDate="2019-11-28T19:29:32.677" UserId="11316" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25691" PostHistoryTypeId="2" PostId="9381" RevisionGUID="f6448878-d68c-4640-9759-4292434c8cd3" CreationDate="2019-11-29T06:46:12.513" UserId="9881" Text="I would like to create program in JavaScript (JS) which draws [Mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set) with arbitrary precision (zoom). In JS there is build in integer type [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) which support simple operations like +,*,/,power on arbitrary precision integer numbers. JS not support calculations on arbitrary precision floating point numbers. &#xD;&#xA;&#xD;&#xA;**Question**: Is there a way to perform calculations of Mandelbrot set using calculations based only on integers (with arbitrary precision) - if yes how I to do it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25692" PostHistoryTypeId="1" PostId="9381" RevisionGUID="f6448878-d68c-4640-9759-4292434c8cd3" CreationDate="2019-11-29T06:46:12.513" UserId="9881" Text="Is there a way to perform calculations of Mandelbrot set using only integer numbers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25693" PostHistoryTypeId="3" PostId="9381" RevisionGUID="f6448878-d68c-4640-9759-4292434c8cd3" CreationDate="2019-11-29T06:46:12.513" UserId="9881" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25694" PostHistoryTypeId="5" PostId="9381" RevisionGUID="33584508-c668-4fa7-b308-1e1dffad2848" CreationDate="2019-11-29T06:51:35.153" UserId="9881" Comment="deleted 2 characters in body" Text="I would like to create program in JavaScript (JS) which draws [Mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set) with arbitrary precision (zoom). In JS there is build in integer type [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) which support simple operations like +,*,/,power on arbitrary precision integer numbers. JS not support calculations on arbitrary precision floating point numbers. &#xD;&#xA;&#xD;&#xA;**Question**: Is there a way to perform calculations of Mandelbrot set using calculations based only on integers (with arbitrary precision) - if yes how to do it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25695" PostHistoryTypeId="2" PostId="9382" RevisionGUID="2e9454e4-333e-4744-8389-b74e3989f7cd" CreationDate="2019-11-29T08:09:58.340" UserId="7647" Text="Probably the easiest way to get an arbitrary precision Mandelbrot set using full-precision integers is to combine two integers into a rational number $p/q$. These numbers are added by finding the common denominator:&#xD;&#xA;$$ \frac{m}{n} + \frac{p}{q} = \frac{mq + np}{nq} $$&#xD;&#xA;and multiplied by just multiplying the respective numerators and denominators:&#xD;&#xA;$$ \frac{m}{n} * \frac{p}{q} = \frac{mp}{nq} $$&#xD;&#xA;Then a single point $\vec{p}$ would be represented in rational coordinates by&#xD;&#xA;$$ \vec{p} = \left( \frac{n_x}{d_x} , \frac{n_y}{d_y} \right) $$&#xD;&#xA;and the iteration for the point would proceed&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;\vec{z} &amp;\rightarrow&amp; \vec{z}^2 + \vec{p} \\&#xD;&#xA;\left( \frac{a_x}{b_x} , \frac{a_y}{b_y} \right) &amp;\rightarrow&amp;&#xD;&#xA;\left( \frac{a_x^2}{b_x^2} - \frac{a_y^2}{b_y^2}&#xD;&#xA;, \frac{2 a_x a_y}{b_x b_y} \right) +&#xD;&#xA;\left( \frac{n_x}{d_x} , \frac{n_y}{d_y} \right)\\&#xD;&#xA;&amp;=&amp;&#xD;&#xA;\left( \frac{a_x^2 b_y^2 - a_y^2 b_x^2}{b_x^2 b_y^2} +&#xD;&#xA;\frac{n_x}{d_x}&#xD;&#xA;, \frac{2 a_x a_y}{b_x b_y} + \frac{n_y}{d_y} \right) \\&#xD;&#xA;&amp;=&amp; \left(&#xD;&#xA;\frac{(a_x^2 b_y^2 - a_y^2 b_x^2)d_x + n_x b_x^2 b_y^2}&#xD;&#xA;     {b_x^2 b_y^2 d_x},&#xD;&#xA;\frac{2 a_x a_y d_y + b_x b_y n_y}{b_x b_y d_y}&#xD;&#xA;\right).&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;Easy this may be, but I can't claim it'll be _fast_; near the boundaries of the Mandelbrot set, the numerators and denominators in the iteration will get pretty big fairly soon, even if you reduce the rationals by dividing by the greatest common denominator." ContentLicense="CC BY-SA 4.0" />
  <row Id="25696" PostHistoryTypeId="2" PostId="9383" RevisionGUID="b9e84b3f-13ab-4d79-ac80-933fffe740f6" CreationDate="2019-11-30T02:56:04.670" UserId="5717" Text="There's no **visible** blur for the same reason you often don't see blur in very wide angle lenses: the circle of confusion is much smaller than a pixel. But it is still there. An extreme example of this is fisheye lenses.&#xD;&#xA;&#xD;&#xA;If you had a camera with infinite resolution, such that you could zoom into the reflection on the ball, you would eventually see the blur. And it would be exactly the same blur as if you had aimed a flat mirror at the part of the scene you're looking at through the ball.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, we don't have such a camera, but we have something even better: software! So I built this simple setup with two perfectly sharp checkered planes, a sphere and a camera with some depth of field:&#xD;&#xA;&#xD;&#xA;[![scene setup][1]][1]&#xD;&#xA;&#xD;&#xA;Rendering it with some depth of field at 512x512, you'd think the reflection in the sphere is perfectly sharp:&#xD;&#xA;&#xD;&#xA;[![normal view][2]][2]&#xD;&#xA;&#xD;&#xA;But here is a central crop of the exact same scene rendered at 8192x8192:&#xD;&#xA;&#xD;&#xA;[![zoom into sphere][3]][3]&#xD;&#xA;&#xD;&#xA;And we can see the exact same blur on the checker pattern. It's as simple as that: you don't see the blur because it's too small.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nKdZu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/K6EXH.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UA3pm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25697" PostHistoryTypeId="2" PostId="9384" RevisionGUID="9ae8a8f0-d9c5-4cd2-bc7d-928aee84b019" CreationDate="2019-11-30T09:54:05.463" UserId="10468" Text="i wanted to ask if you know the best books or resources to understand light physics. I have heard that Subrahmanyan Chandrasekhar's book &quot;Radiance Transfer&quot; is very good. Any other books or suggestions will be appreciated" ContentLicense="CC BY-SA 4.0" />
  <row Id="25698" PostHistoryTypeId="1" PostId="9384" RevisionGUID="9ae8a8f0-d9c5-4cd2-bc7d-928aee84b019" CreationDate="2019-11-30T09:54:05.463" UserId="10468" Text="Understanding lighting for physically based rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="25699" PostHistoryTypeId="3" PostId="9384" RevisionGUID="9ae8a8f0-d9c5-4cd2-bc7d-928aee84b019" CreationDate="2019-11-30T09:54:05.463" UserId="10468" Text="|physically-based|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25712" PostHistoryTypeId="2" PostId="9388" RevisionGUID="63c38ed2-ca09-4b5d-8fb5-5b7dd9e8428a" CreationDate="2019-12-02T02:46:49.847" UserId="11547" Text="If you want to warp the space as in the raymarching infinite spheres example,&#xD;&#xA;&#xD;&#xA;    float SDF (vec3 p) {&#xD;&#xA;        p = mod(p+3., 6.)-3.;&#xD;&#xA;        return length(p-vec3(0., 0., 0.))-2.;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;what you really need to do is &lt;i&gt;warp the space by turning it into a cyllindrical one&lt;/i&gt; and what that means is that you need to make it so that if a ray hits a wall, the wall is like a portal to the wall opposite it and it comes out of the same point on the opposite wall. To do this you could just here is some pseudocode:&#xD;&#xA;&#xD;&#xA;    Color trace (vec3 p, vec3 d) {&#xD;&#xA;        if (intersects sphere) {&#xD;&#xA;            *return sphere color with recursive tracing blah*&#xD;&#xA;        }&#xD;&#xA;        Plane frontwall = plane(vec3(0, 0, 3), vec3(0, 0, -1));&#xD;&#xA;        Plane backwall = plane(vec3(0, 0, -3), vec3(0, 0, 1));&#xD;&#xA;        Plane leftwall = plane(vec3(-3, 0, 0), vec3(1, 0, 0));&#xD;&#xA;        ...&#xD;&#xA;        *find closest wall intersection and then*&#xD;&#xA;        return recursively traced color from opposite wall than the one that got hit&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;of note is that to do this enough times for it to look infinite, you would need like thousands of recursion iterations which would probably be slow and whatever language would probably not allow it, so your other option is to use some kind of a for loop since each portal/wall-intersection only requires base-1 recursion and therefore can be easily tranformed into an iterative process.&#xD;&#xA;&#xD;&#xA;And instead of downvoting, I would request anyone who found my answer unhelpful to elaborate on how I could improve it; if someone really is interested in seeing a proof of concept of this in action then I will provide one but until that seems to be the case I will not waste my time." ContentLicense="CC BY-SA 4.0" />
  <row Id="25714" PostHistoryTypeId="2" PostId="9389" RevisionGUID="ecca5721-956d-4a46-8631-1cf1680644c0" CreationDate="2019-12-02T08:53:50.780" UserId="11548" Text="It may be worth mentioning that the [reverse painter's algorithm][1] **does not handle** transparency. If you read and understand @Chris's answer the reason for this is straightforward. Combining the already rendered color (using alpha blending) does not work if the objects behind your transparent object have not been rendered yet.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Painter%27s_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="25715" PostHistoryTypeId="2" PostId="9390" RevisionGUID="2feba14b-1815-4ff4-a4d6-e5e26d80a03d" CreationDate="2019-12-02T10:01:35.623" UserId="209" Text="I would like to add that Painters algorithm **can** be run from front to back with transparency *provided* your blending operations are *associative*. I would recommend reading Jim Blinn's &quot;Compositing, Part 1: Theory&quot;. (Indeed, reading anything graphics related by Jim Blinn is highly recommended).&#xD;&#xA;&#xD;&#xA;In this article, he explains that *premultiplied alpha* blending operations are associative and thus the back-to-front blend operation $$Result=Blend(A, Blend(B,C))$$ gives the same result as $$Blend(Blend(A,B), C))$$&#xD;&#xA;&#xD;&#xA;It does mean that you need to keep a destination alpha value with each pixel - you can't just assume each pixel is 100% opaque.&#xD;&#xA;&#xD;&#xA;*Note that the operations are generally not commutative so you still can't just process the polygons in random order.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25716" PostHistoryTypeId="5" PostId="9390" RevisionGUID="0f371bb3-8a0b-419d-bfa2-261ebce19e3d" CreationDate="2019-12-02T10:08:55.280" UserId="209" Comment="added 64 characters in body" Text="I would like to add that Painters algorithm **can** be run from front to back with transparency *provided* your blending operations are *associative*. I would recommend reading Jim Blinn's &quot;Compositing, Part 1: Theory&quot;. (Indeed, reading anything graphics related by Jim Blinn is highly recommended).&#xD;&#xA;&#xD;&#xA;In this article, he explains that *premultiplied alpha* blending operations are associative and, assuming &quot;C&quot; is the furthest polygon and &quot;A&quot; the closest, the usual the back-to-front blend operation $$Result=Blend(A, Blend(B,C))$$ gives the same result as $$Blend(Blend(A,B), C))$$&#xD;&#xA;&#xD;&#xA;It does mean that you need to keep a destination alpha value with each pixel - you can't just assume each pixel is 100% opaque.&#xD;&#xA;&#xD;&#xA;*Note that the operations are generally not commutative so you still can't just process the polygons in random order.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25718" PostHistoryTypeId="5" PostId="9390" RevisionGUID="0920a73e-0ff3-4437-9522-71b3e1b6b2de" CreationDate="2019-12-02T10:37:12.487" UserId="209" Comment="formatting of equation" Text="I would like to add that Painters' algorithm **can** be run from front to back with transparency *provided* your blending operations are *associative*. I would recommend reading Jim Blinn's &quot;Compositing, Part 1: Theory&quot;. (Indeed, reading anything graphics related by Jim Blinn is highly recommended).&#xD;&#xA;&#xD;&#xA;In this article, he explains (amongst their other advantages) that *premultiplied alpha* blending operations are associative and, assuming &quot;C&quot; is the furthest polygon and &quot;A&quot; the closest, the usual the back-to-front blend operation $$Result=Blend(A, Blend(B,C))$$ gives the same result as $$Blend(Blend(A,B), C))$$&#xD;&#xA;&#xD;&#xA;It does mean that you need to keep a destination alpha value with each pixel - you can't just assume each pixel is 100% opaque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you're unfamiliar with premultiplied alpha, the typical &quot;GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA&quot; OpenGL blend, i.e. $$DstOut_{RGB} := Src_A * Src_{RGB} + (1-Src_A) * DstIn_{RGB}$$&#xD;&#xA;&#xD;&#xA;is replaced with&#xD;&#xA; $$\left[DstOut_A, \overline{DstOut_{RGB}}\right] :=\\ \left[Src_A + (1-Src_A)*DstIn_A,  \overline{Src}_{RGB} + (1-Src_A) * \overline{DstIn_{RGB}}\right]$$&#xD;&#xA;&#xD;&#xA;where $\overline{X_{RGB}}=X_{RGB}*X_A$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA; - The operations are generally not commutative so, sadly, you still can't just process the polygons in random order. &#xD;&#xA; - (IIRC, some games use(d) additive-only blending, e.g. for lighting effects, which is of course commutative.)&#xD;&#xA; - Additive blending can also be mapped to premultiplied as the colour [0, RBG_to_Add].&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25719" PostHistoryTypeId="5" PostId="9390" RevisionGUID="17688c93-2447-4169-be1a-a4b7c55dc04f" CreationDate="2019-12-02T13:06:54.837" UserId="209" Comment="fixed grammar" Text="I would like to add that Painters' algorithm **can** be run from front to back with transparency *provided* your blending operations are *associative*. I would recommend reading Jim Blinn's &quot;Compositing, Part 1: Theory&quot;. (Indeed, reading anything graphics related by Jim Blinn is highly recommended).&#xD;&#xA;&#xD;&#xA;In this article, he explains (amongst their other advantages) that *premultiplied alpha* blending operations are associative and, assuming &quot;C&quot; is the furthest polygon and &quot;A&quot; the closest, the usual the back-to-front blend operation $$Result=Blend(A, Blend(B,C))$$ can be replaced with $$Blend(Blend(A,B), C))$$&#xD;&#xA;&#xD;&#xA;It does mean that you need to keep a destination alpha value with each pixel - you can't just assume each pixel is 100% opaque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you're unfamiliar with premultiplied alpha, the typical &quot;GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA&quot; OpenGL blend, i.e. $$DstOut_{RGB} := Src_A * Src_{RGB} + (1-Src_A) * DstIn_{RGB}$$&#xD;&#xA;&#xD;&#xA;can be mapped to &#xD;&#xA; $$\left[DstOut_A, \overline{DstOut_{RGB}}\right] :=\\ \left[Src_A + (1-Src_A)*DstIn_A,  \overline{Src}_{RGB} + (1-Src_A) * \overline{DstIn_{RGB}}\right]$$&#xD;&#xA;&#xD;&#xA;where $\overline{X_{RGB}}=X_{RGB}*X_A$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA; - The operations are generally not commutative so, sadly, you still can't just process the polygons in random order. &#xD;&#xA; - (IIRC, some games use(d) additive-only blending, e.g. for lighting effects, which is of course commutative.)&#xD;&#xA; - Additive blending can also be mapped to premultiplied as the colour [0, RBG_to_Add].&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25720" PostHistoryTypeId="2" PostId="9391" RevisionGUID="bf553e09-7150-4e9c-8a4b-5d3d186ba3b8" CreationDate="2019-12-02T16:13:15.437" UserId="8283" Text="What is the best way to synchronize resource access between the (async) compute engine and the 3d engine (aka. direct engine) in D3D 12?&#xD;&#xA;&#xD;&#xA;I found [this][1] paragraph about multi-engine synchronization on MSDN but it's not very detailed.&#xD;&#xA;&#xD;&#xA;You can certainly use a fence for synchronization but then you'd have split the command lists for both engines since fences only operate on queues.&#xD;&#xA;&#xD;&#xA;According to the documentation, the 3d engine and the compute engine share the same resource state (only the copy engine has it's own resource state). So if you write to a resource using the async compute engine and then read from it using the 3d engine, is there a way to synchronize this via resource barriers?&#xD;&#xA;&#xD;&#xA;I doubt that it works if you use the compute engine to submit a resource barrier since the 3d engine probably won't wait automatically if the resource state is wrong. Same issue if you use the 3d engine for the resource transition (it could happen that the resource state is being changed while the compute engine is still writing to the resource).&#xD;&#xA;&#xD;&#xA;Do you have to use [split barriers][2]? You could use the compute engine with the D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY flag and the 3d engine with the D3D12_RESOURCE_BARRIER_FLAG_END_ONLY flag. Unfortunately, the documentation doesn't say whether split barriers can be used across engines. What happens if the direct engine executes the end barrier before the compute engine has executed the start barrier? &#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/direct3d12/user-mode-heap-synchronization#multi-queue-resource-access&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/win32/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#split-barriers" ContentLicense="CC BY-SA 4.0" />
  <row Id="25721" PostHistoryTypeId="1" PostId="9391" RevisionGUID="bf553e09-7150-4e9c-8a4b-5d3d186ba3b8" CreationDate="2019-12-02T16:13:15.437" UserId="8283" Text="Can D3D12 resource barriers be used to synchronize between the compute and 3D engine?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25722" PostHistoryTypeId="3" PostId="9391" RevisionGUID="bf553e09-7150-4e9c-8a4b-5d3d186ba3b8" CreationDate="2019-12-02T16:13:15.437" UserId="8283" Text="|directx12|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25723" PostHistoryTypeId="2" PostId="9392" RevisionGUID="9315c7ef-cc83-48ca-b8e4-e7851ec467f3" CreationDate="2019-12-02T16:30:31.757" UserId="2479" Text="The most usual way of employing Russian roulette in path tracing is to cut paths with high attenuation (low throughput) without adding bias into the resulting estimator, which would occur if you just use constant maximum path length. &#xD;&#xA;&#xD;&#xA;Although Russian roulette incorporates additional variance into the resulting estimator, it helps throwing away long paths consuming a lot of processing power while contributing little into the resulting image, possibly leading to increased performance of a renderer." ContentLicense="CC BY-SA 4.0" />
  <row Id="25724" PostHistoryTypeId="2" PostId="9393" RevisionGUID="5c8d4a8b-d2d2-4d05-9b3a-daec796221be" CreationDate="2019-12-02T18:28:21.073" UserId="9812" Text="My understanding would be that resource barriers are not at all about synchronization. They are about memory ordering, which is a related but separate concern. Basically, synchronization is about making sure that A happens before B. Memory ordering is about making sure that if A did X, someone how saw A happen will always also see X an no one will ever see X without first also having seen A happen.&#xD;&#xA;&#xD;&#xA;In Direct3D terms, resource barriers are about making sure that if shader A writes to texture X, shader B running after shader A actually gets to see the result of shader A having written to texture X. Fences, on the other hand, are about making sure that shader A actually runs before shader B.&#xD;&#xA;&#xD;&#xA;Direct3D resource barriers are just you stating in which way you are going to be using a resource. You cannot rely on just a resource barrier to automagically perform the necessary synchronization for you. The section you yourself linked you seem to agree (emphasis mine):&#xD;&#xA;&#xD;&#xA;&gt; * Although resource state is shared across all Compute and 3D queues, it is not permitted to write to the resource simultaneously on different queues. &quot;Simultaneously&quot; here means unsynchronized, noting unsynchronized execution is not possible on some hardware. The following rules apply.  &#xD;&#xA;&gt;  * Only one queue can write to a resource at a time.&#xD;&#xA;&gt;  * Multiple queues can read from the resource as long as they don’t read the bytes being modified by the writer (reading bytes being simultaneously written produces undefined results).  &#xD;&#xA;&gt;  * **A fence must be used to synchronize after writing before another queue can read the written bytes or make any write access.**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Memory_barrier" ContentLicense="CC BY-SA 4.0" />
  <row Id="25725" PostHistoryTypeId="5" PostId="9393" RevisionGUID="4e3713ad-858a-4306-b98a-d62fec93833a" CreationDate="2019-12-02T19:52:28.777" UserId="9812" Comment="deleted 7 characters in body" Text="My understanding would be that resource barriers are not at all about synchronization. They are about memory ordering, which is a related but separate concern. Basically, synchronization is about making sure that A happens before B. Memory ordering is about making sure that if A did X, someone how saw A happen will always also see X an no one will ever see X without first also having seen A happen.&#xD;&#xA;&#xD;&#xA;In Direct3D terms, resource barriers are about making sure that if shader A writes to texture X, shader B running after shader A actually gets to see the result of shader A having written to texture X. Fences, on the other hand, are about making sure that shader A actually runs before shader B.&#xD;&#xA;&#xD;&#xA;Direct3D resource barriers are just you stating in which way you are going to be using a resource. You cannot rely on just a resource barrier to automagically perform the necessary synchronization for you. The section you linked would seem to agree (emphasis mine):&#xD;&#xA;&#xD;&#xA;&gt; * Although resource state is shared across all Compute and 3D queues, it is not permitted to write to the resource simultaneously on different queues. &quot;Simultaneously&quot; here means unsynchronized, noting unsynchronized execution is not possible on some hardware. The following rules apply.  &#xD;&#xA;&gt;  * Only one queue can write to a resource at a time.&#xD;&#xA;&gt;  * Multiple queues can read from the resource as long as they don’t read the bytes being modified by the writer (reading bytes being simultaneously written produces undefined results).  &#xD;&#xA;&gt;  * **A fence must be used to synchronize after writing before another queue can read the written bytes or make any write access.**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Memory_barrier" ContentLicense="CC BY-SA 4.0" />
  <row Id="25726" PostHistoryTypeId="5" PostId="9393" RevisionGUID="6c0be1d5-d2ca-42e2-b11f-f83fde8b4f49" CreationDate="2019-12-02T21:47:19.207" UserId="9812" Comment="added 1 character in body" Text="My understanding would be that resource barriers are not at all about synchronization. They are about memory ordering, which is a related but separate concern. Basically, synchronization is about making sure that A happens before B. Memory ordering is about making sure that if A did X, someone how saw A happen will always also see X and no one will ever see X without first also having seen A happen.&#xD;&#xA;&#xD;&#xA;In Direct3D terms, resource barriers are about making sure that if shader A writes to texture X, shader B running after shader A actually gets to see the result of shader A having written to texture X. Fences, on the other hand, are about making sure that shader A actually runs before shader B.&#xD;&#xA;&#xD;&#xA;Direct3D resource barriers are just you stating in which way you are going to be using a resource. You cannot rely on just a resource barrier to automagically perform the necessary synchronization for you. The section you linked would seem to agree (emphasis mine):&#xD;&#xA;&#xD;&#xA;&gt; * Although resource state is shared across all Compute and 3D queues, it is not permitted to write to the resource simultaneously on different queues. &quot;Simultaneously&quot; here means unsynchronized, noting unsynchronized execution is not possible on some hardware. The following rules apply.  &#xD;&#xA;&gt;  * Only one queue can write to a resource at a time.&#xD;&#xA;&gt;  * Multiple queues can read from the resource as long as they don’t read the bytes being modified by the writer (reading bytes being simultaneously written produces undefined results).  &#xD;&#xA;&gt;  * **A fence must be used to synchronize after writing before another queue can read the written bytes or make any write access.**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Memory_barrier" ContentLicense="CC BY-SA 4.0" />
  <row Id="25727" PostHistoryTypeId="5" PostId="9390" RevisionGUID="a9502cfc-cb60-4485-92a3-76d378b8370a" CreationDate="2019-12-03T10:34:10.690" UserId="209" Comment="Minor improvements to text" Text="I would like to add that Painters' algorithm **can** be run from front to back with transparency *provided* your blending operations are *associative*. I would recommend reading Jim Blinn's &quot;Compositing, Part 1: Theory&quot;. (Indeed, reading anything graphics related by Jim Blinn is highly recommended).&#xD;&#xA;&#xD;&#xA;In this article, Blinn explains (amongst their other advantages) that *premultiplied alpha* blending operations are associative and, assuming &quot;C&quot; is the furthest polygon and &quot;A&quot; the closest, the usual the back-to-front blend operation $$Result=Blend(A, Blend(B,C))$$ can be replaced with $$Blend(Blend(A,B), C))$$&#xD;&#xA;&#xD;&#xA;It does mean that you need to keep a destination alpha value with each pixel - you can't just assume each pixel is 100% opaque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you're unfamiliar with premultiplied alpha, the typical OpenGL  &quot;GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA&quot; blend, i.e. $$DstOut_{RGB} := Src_A * Src_{RGB} + (1-Src_A) * DstIn_{RGB}$$&#xD;&#xA;&#xD;&#xA;is expressed &#xD;&#xA; $$\left[DstOut_A, \overline{DstOut_{RGB}}\right] :=\\ \left[Src_A + (1-Src_A)*DstIn_A,  \overline{Src}_{RGB} + (1-Src_A) * \overline{DstIn_{RGB}}\right]$$&#xD;&#xA;&#xD;&#xA;where $$\overline{X_{RGB}}=X_{RGB}*X_A$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA; - The operations are generally not commutative so, sadly, you still can't just process the polygons in random order. &#xD;&#xA; - (IIRC, some games use(d) additive-only blending, e.g. for lighting effects, which is of course commutative and so can be done in arbitrary order)&#xD;&#xA; - Additive blending can also be expressed in a premultiplied form as the colour [0, RBG_to_Add].&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25732" PostHistoryTypeId="2" PostId="9395" RevisionGUID="aaa07f1a-2852-4080-8344-2e2300829f81" CreationDate="2019-12-03T14:22:30.217" UserId="11553" Text="I have a video feed generating a stream of of Y'CbCr frames from which I'd like to calculate relative luminance of specific pixels in each frame with a margin of error at ~2%.&#xD;&#xA;&#xD;&#xA;My understanding is that the Y' channel in a Y'CbCr signal is not luminance but luma, and therefore further work is required to reverse that conversion into its linear form.&#xD;&#xA;&#xD;&#xA;Of course, to do that I need to know what values were used to compress the signal from its original linear RGB form into its current Y'CbCr state.&#xD;&#xA;&#xD;&#xA;I understand there's usually a compression function used to convert linear RGB into R'G'B', so if I know what these are – I should have a fairly good shot at doing it. (That's assuming that *not* having the camera response curves isn't a problem, as I'm hoping that these are used to transform non-linear raw camera data into a linear form – and so for my purposes there isn't a benefit to reversing the signal transform this far.)&#xD;&#xA;&#xD;&#xA;Available to me with the feed are references to a 'transfer function' (usually some ITU standard – BT.601-4 on my test device), a Y'CbCr Matrix (another ITU standard – BT.709-2 on my test device), and some color primaries  (P3 D65 on my test device) and white balance gain values.&#xD;&#xA;&#xD;&#xA;What steps are required to convert 'luma' to luminance given the available data?&#xD;&#xA;&#xD;&#xA;My naive approach is to simply apply the inverse of the transfer function to the luma channel but my concern is that this will be grossly inaccurate. Also, white balance might be a factor too, but perhaps marginally enough to be within the 2% margin of error.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25733" PostHistoryTypeId="1" PostId="9395" RevisionGUID="aaa07f1a-2852-4080-8344-2e2300829f81" CreationDate="2019-12-03T14:22:30.217" UserId="11553" Text="Calculating Luminance From Y'CbCr" ContentLicense="CC BY-SA 4.0" />
  <row Id="25734" PostHistoryTypeId="3" PostId="9395" RevisionGUID="aaa07f1a-2852-4080-8344-2e2300829f81" CreationDate="2019-12-03T14:22:30.217" UserId="11553" Text="|color|color-science|color-management|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25735" PostHistoryTypeId="2" PostId="9396" RevisionGUID="f6c6b78e-9539-46a5-b9e3-ae81fca22f13" CreationDate="2019-12-03T16:46:08.183" UserId="8962" Text="I'm reading about BVH from PBRT. According to the book, in the linear bvh part using morton encoding:&#xD;&#xA;&#xD;&#xA;&gt;An efficient way to perform a front-to-back traversal without incurring the expense of intersecting the ray with both child nodes and comparing the distances is to use the sign of the ray’s direction vector for the coordinate axis along which primitives were partitioned for the current node: if the sign is negative, we should visit the second child before the first child, since the primitives that went into the second child’s subtree were on the upper side of the partition point. (And conversely for a positive-signed direction.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm unable to understand how the sign of the ray's direction vector helps in deciding which child to visit. If the partitioning axis is x, doesn't the point with a lower x come in the 1st child? Or have I understood something wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25736" PostHistoryTypeId="1" PostId="9396" RevisionGUID="f6c6b78e-9539-46a5-b9e3-ae81fca22f13" CreationDate="2019-12-03T16:46:08.183" UserId="8962" Text="How to decide which child of BVH to visit based on sign of ray's direction vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25737" PostHistoryTypeId="3" PostId="9396" RevisionGUID="f6c6b78e-9539-46a5-b9e3-ae81fca22f13" CreationDate="2019-12-03T16:46:08.183" UserId="8962" Text="|raytracing|bounding-volume-hierarchy|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25738" PostHistoryTypeId="5" PostId="9395" RevisionGUID="1284afce-6422-415f-b719-9ad7f0e3249e" CreationDate="2019-12-03T18:15:36.240" UserId="11553" Comment="More precisely described Y'CbCr source feed format" Text="I have a video feed generating a stream of of Y'CbCr frames (specifically 8-bit component Y'CbCr 4:2:0, luma range of 16-235, chroma range of 16-240) from which I'd like to calculate relative luminance of specific pixels in each frame with a margin of error at ~2%.&#xD;&#xA;&#xD;&#xA;My understanding is that the Y' channel in a Y'CbCr signal is not luminance but luma, and therefore further work is required to reverse that conversion into its linear form.&#xD;&#xA;&#xD;&#xA;Of course, to do that I need to know what values were used to compress the signal from its original linear RGB form into its current Y'CbCr state.&#xD;&#xA;&#xD;&#xA;I understand there's usually a compression function used to convert linear RGB into R'G'B', so if I know what these are – I should have a fairly good shot at doing it. (That's assuming that *not* having the camera response curves isn't a problem, as I'm hoping that these are used to transform non-linear raw camera data into a linear form – and so for my purposes there isn't a benefit to reversing the signal transform this far.)&#xD;&#xA;&#xD;&#xA;Available to me with the feed are references to a 'transfer function' (usually some ITU standard – BT.601-4 on my test device), a Y'CbCr Matrix (another ITU standard – BT.709-2 on my test device), and some color primaries  (P3 D65 on my test device) and white balance gain values.&#xD;&#xA;&#xD;&#xA;What steps are required to convert 'luma' to luminance given the available data?&#xD;&#xA;&#xD;&#xA;My naive approach is to simply apply the inverse of the transfer function to the luma channel but my concern is that this will be grossly inaccurate. Also, white balance might be a factor too, but perhaps marginally enough to be within the 2% margin of error.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25743" PostHistoryTypeId="2" PostId="9398" RevisionGUID="20611ea3-ad61-41da-ae99-42710a19be06" CreationDate="2019-12-03T22:40:35.220" UserId="11556" Text="I'm making a 2D cell simulation game. &#xD;&#xA;&#xD;&#xA;The mesh for my cell is basically just a manually-generated triangle fan that looks like [this][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I would like to reproduce the wobbling/vibration effect on the cell membrane caused by inertia after a decelleration (e.g. collision), but I can't really figure out a way to do it.&#xD;&#xA;&#xD;&#xA;I was thinking that I could apply a transformation to each vertex of the mesh in order to move it inwards and outwards alternately (with respect to the cell center) and then syncronize all the vertices based on a sinusoidal function.&#xD;&#xA;&#xD;&#xA;The result would be a deformed cell shape but where all the triangles are still connected.&#xD;&#xA;&#xD;&#xA;Is it possible to apply transformations to the vertices inside the model separately without having to reconstruct the VBO? Is there a better way to achieve this?&#xD;&#xA;&#xD;&#xA;  [1]: https://nullprogram.s3.amazonaws.com/voronoi/triangle-fan.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25744" PostHistoryTypeId="1" PostId="9398" RevisionGUID="20611ea3-ad61-41da-ae99-42710a19be06" CreationDate="2019-12-03T22:40:35.220" UserId="11556" Text="Apply transformation to single vertices in OpenGL in order to deform mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="25745" PostHistoryTypeId="3" PostId="9398" RevisionGUID="20611ea3-ad61-41da-ae99-42710a19be06" CreationDate="2019-12-03T22:40:35.220" UserId="11556" Text="|opengl|transformations|mesh|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25746" PostHistoryTypeId="2" PostId="9399" RevisionGUID="e80a259f-aea6-4644-9620-e133b4234f9f" CreationDate="2019-12-04T07:18:37.963" UserId="48" Text="In your example of a BVH cell partitioned along the x axis, if the ray is going left to right (increasing x), then the cell with the lower x comes first; but if it's going right to left (decreasing x), then the cell with the higher x comes first. So, you can look at the sign of the x component of the direction vector to determine which cell to test first." ContentLicense="CC BY-SA 4.0" />
  <row Id="25747" PostHistoryTypeId="5" PostId="9390" RevisionGUID="2d568a9c-d344-4447-b677-4b597f4759a0" CreationDate="2019-12-04T09:26:40.030" UserId="209" Comment="fixed grammar" Text="I would like to add that Painters' algorithm **can** be run from front to back with transparency *provided* your blending operations are *associative*. I would recommend reading Jim Blinn's &quot;Compositing, Part 1: Theory&quot;. (Indeed, reading anything graphics related by Jim Blinn is highly recommended).&#xD;&#xA;&#xD;&#xA;In this article, Blinn explains (amongst their other advantages) that *premultiplied alpha* blending operations are associative and, assuming &quot;C&quot; is the furthest polygon and &quot;A&quot; the closest, the usual the back-to-front blend operation $$Result=Blend(A, Blend(B,C))$$ can be replaced with $$Blend(Blend(A,B), C))$$&#xD;&#xA;&#xD;&#xA;It does mean that you need to keep a destination alpha value with each pixel - you can't just assume each pixel is 100% opaque.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you're unfamiliar with premultiplied alpha, the typical OpenGL  &quot;GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA&quot; blend, i.e. $$DstOut_{RGB} := Src_A * Src_{RGB} + (1-Src_A) * DstIn_{RGB}$$&#xD;&#xA;&#xD;&#xA;becomes &#xD;&#xA; $$\left[DstOut_A, \overline{DstOut_{RGB}}\right] :=\\ \left[Src_A + (1-Src_A)*DstIn_A,  \overline{Src}_{RGB} + (1-Src_A) * \overline{DstIn_{RGB}}\right]$$&#xD;&#xA;&#xD;&#xA;where $$\overline{X_{RGB}}=X_{RGB}*X_A$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Notes:&#xD;&#xA;&#xD;&#xA; - The operations are generally not commutative so, sadly, you still can't just process the polygons in random order. &#xD;&#xA; - (IIRC, some games use(d) additive-only blending, e.g. for lighting effects, which is of course commutative and so can be done in arbitrary order)&#xD;&#xA; - Additive blending can also be expressed in a premultiplied form as the colour [0, RBG_to_Add].&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25749" PostHistoryTypeId="2" PostId="9400" RevisionGUID="68ff947d-2253-46ab-bbd6-bd3aa11e9bb9" CreationDate="2019-12-04T17:30:23.837" UserId="2479" Text="The term D is a [probability distribution function][1] (PDF) of microfacets' directions. Vaguely speaking, it says what &quot;portion&quot; of all microfacets points in the given direction.&#xD;&#xA;&#xD;&#xA;Since it is a PDF, it doesn't have to be less or equal to 1. It can, and often is, higher than 1 for some directions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="25754" PostHistoryTypeId="50" PostId="7804" RevisionGUID="dca5a770-0183-4ea3-b60e-ef0154f47e59" CreationDate="2019-12-05T15:02:50.363" UserId="-1" />
  <row Id="25755" PostHistoryTypeId="2" PostId="9402" RevisionGUID="84a57e58-35b9-4978-8574-6fde3056499b" CreationDate="2019-12-06T11:36:49.733" UserId="11571" Text="Monte Carlo integration is an unbiased estimator for the synthesis of lights that contributed to a pixel. While we cannot exactly simulate the real world light path because the amount of rays is infinite, we can use Monte Carlo integration to estimate the expected value. That's why it is much more realistic: from the statistics aspect, the expectation of Monte Carlo ray tracing is the &quot;real light paths&quot;.&#xD;&#xA;&#xD;&#xA;You can read [my blog](https://hsuanwei.codes/2019/12/06/pt/#more) for more math details." ContentLicense="CC BY-SA 4.0" />
  <row Id="25756" PostHistoryTypeId="50" PostId="9307" RevisionGUID="9b601370-d8e6-4d1f-8d3e-1078f3dec32c" CreationDate="2019-12-06T18:01:30.550" UserId="-1" />
  <row Id="25757" PostHistoryTypeId="2" PostId="9403" RevisionGUID="4d44d24b-d83b-4703-bc84-d57d45d923d2" CreationDate="2019-12-06T22:22:16.390" UserId="10136" Text="I am currently implementing the Mandelbrot fractal on the GPU. I wrote two programs: the first in OpenGL (desktop C++ application) and the second in WebGL (static webpage). The two programs use almost the same fragment shader for generating the fractal, but picture on WebGL looks less detailed than the OpenGL one. I cannot understand the reason behind that.&#xD;&#xA;&#xD;&#xA;**WebGL version:**&#xD;&#xA;[![WebGL version][1]][1] &#xD;&#xA;&#xD;&#xA;**OpenGL version:**&#xD;&#xA;&#xD;&#xA;[![OpenGL version][2]][2]&#xD;&#xA;&#xD;&#xA;I place here the fragment shader code:&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;    float xShift = 200.0;&#xD;&#xA;    float yShift = 50.0;&#xD;&#xA;    float fade = 0.02;&#xD;&#xA;  &#xD;&#xA;    struct ComplexNumber&#xD;&#xA;    {&#xD;&#xA;      float Real;&#xD;&#xA;      float Imagine;&#xD;&#xA;    };&#xD;&#xA;  &#xD;&#xA;    &#xD;&#xA;    ComplexNumber Product(in ComplexNumber first, in ComplexNumber second)&#xD;&#xA;    {&#xD;&#xA;      ComplexNumber result;  &#xD;&#xA;      result.Real = first.Real * second.Real - first.Imagine * second.Imagine;&#xD;&#xA;      result.Imagine = first.Real * second.Imagine + first.Imagine * second.Real;&#xD;&#xA;      return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;  &#xD;&#xA;    ComplexNumber Add(in ComplexNumber first, in ComplexNumber second)&#xD;&#xA;    {&#xD;&#xA;      ComplexNumber result;  &#xD;&#xA;      result.Real = first.Real + second.Real;&#xD;&#xA;      result.Imagine = first.Imagine + second.Imagine;&#xD;&#xA;      return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;  &#xD;&#xA;    float length2(in ComplexNumber number)&#xD;&#xA;    {&#xD;&#xA;       return number.Real * number.Real + number.Imagine * number.Imagine;&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    &#xD;&#xA;    vec4 linearExtrapolation(const vec4 first, const vec4 last, int min, int max, int x)&#xD;&#xA;    {&#xD;&#xA;      float xDiff = float(max - min);&#xD;&#xA;      return first + float(x - min) * (last - first) / xDiff;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int getOutOfBoundsIdx()&#xD;&#xA;    {&#xD;&#xA;      const int nMax = 1000;&#xD;&#xA;  &#xD;&#xA;      ComplexNumber z;&#xD;&#xA;      z.Real = 0.;&#xD;&#xA;      z.Imagine = 0.;&#xD;&#xA;    &#xD;&#xA;      ComplexNumber c;&#xD;&#xA;      c.Real = float((gl_FragCoord.x - xShift ) * fade);&#xD;&#xA;      c.Imagine = float((gl_FragCoord.y - yShift) * fade); &#xD;&#xA;  &#xD;&#xA;      for (int i = 0; i &lt; nMax; i++)&#xD;&#xA;      {&#xD;&#xA;         z = Add (Product(z,z), c);&#xD;&#xA;         if (length2(z) &gt; 4.)&#xD;&#xA;         {&#xD;&#xA;           return i;&#xD;&#xA;         }&#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      return nMax;&#xD;&#xA;    } &#xD;&#xA;  &#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;  &#xD;&#xA;      const vec4 blue = vec4(166, 202, 240, 255) / 255.;&#xD;&#xA;      const vec4 biruz = vec4(123, 228, 209, 255) / 255.;&#xD;&#xA;      const vec4 red = vec4(255, 0, 0, 255) / 255.;&#xD;&#xA;      const vec4 green = vec4(0, 255, 0, 255) / 255.;&#xD;&#xA;      const vec4 black = vec4(0, 0, 0, 255) / 255.;&#xD;&#xA;       &#xD;&#xA;      &#xD;&#xA;  &#xD;&#xA;      const int kThreshold0 = 0;&#xD;&#xA;      const int kThreshold1 = 100;&#xD;&#xA;      const int kThreshold2 = 150;&#xD;&#xA;      const int kThreshold3 = 250;&#xD;&#xA;      const int kThreshold4 = 390;&#xD;&#xA;      &#xD;&#xA;  &#xD;&#xA;      int k = getOutOfBoundsIdx();&#xD;&#xA;  &#xD;&#xA;  &#xD;&#xA;      vec4 color;&#xD;&#xA;      if (k &lt; kThreshold1)&#xD;&#xA;      {&#xD;&#xA;         color = linearExtrapolation(biruz, blue, kThreshold0, kThreshold1, k);&#xD;&#xA;      }&#xD;&#xA;      else if (k &lt; kThreshold2)&#xD;&#xA;      {&#xD;&#xA;         color = linearExtrapolation(red, green, kThreshold1, kThreshold2, k);&#xD;&#xA;      }&#xD;&#xA;      else if (k &lt; kThreshold3)&#xD;&#xA;      {&#xD;&#xA;         color = linearExtrapolation(biruz, blue, kThreshold2, kThreshold3, k);&#xD;&#xA;      }&#xD;&#xA;      else if (k &lt; kThreshold4)&#xD;&#xA;      {&#xD;&#xA;         color = linearExtrapolation(biruz, green, kThreshold3, kThreshold4, k);&#xD;&#xA;      }&#xD;&#xA;  &#xD;&#xA;      else&#xD;&#xA;      {&#xD;&#xA;         color = black;  &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      gl_FragColor = color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What can be a reason of such weird difference? I have a feeling that the float operations on WebGL are less precise than in OpenGL. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CI7tS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/V60I4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25758" PostHistoryTypeId="1" PostId="9403" RevisionGUID="4d44d24b-d83b-4703-bc84-d57d45d923d2" CreationDate="2019-12-06T22:22:16.390" UserId="10136" Text="Why there are calculation differences in WebGL and OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="25759" PostHistoryTypeId="3" PostId="9403" RevisionGUID="4d44d24b-d83b-4703-bc84-d57d45d923d2" CreationDate="2019-12-06T22:22:16.390" UserId="10136" Text="|opengl|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25760" PostHistoryTypeId="5" PostId="9400" RevisionGUID="36c8fc78-bf54-49fe-9f79-31c17f4b458c" CreationDate="2019-12-07T03:29:34.110" UserId="2479" Comment="deleted 5 characters in body" Text="The term D is a [probability density function][1] (PDF) of microfacets' directions. Vaguely speaking, it says what &quot;portion&quot; of all microfacets points in the given direction.&#xD;&#xA;&#xD;&#xA;Since it is a PDF, it doesn't have to be less or equal to 1. It can, and often is, higher than 1 for some directions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="25765" PostHistoryTypeId="2" PostId="9405" RevisionGUID="deab9abf-c60b-4044-ab3b-dec13a0fc62f" CreationDate="2019-12-08T01:50:56.087" UserId="11577" Text="Apologize for crossposting, but I posted this in Stack Overflow and thought it might be a better post here.&#xD;&#xA;&#xD;&#xA;Recently, Spotify released their 2019 Spotify wrapped web application, which is essentially a way for both music artists and music listeners to rewind and review what they listened to/who listened to their music in the past year.&#xD;&#xA;&#xD;&#xA;As part of their site, they dynamically created these images that people could either export or share to one of their social media networks.&#xD;&#xA;&#xD;&#xA;[![Example of dynamically generated image from Spotify][1]][1]&#xD;&#xA;&#xD;&#xA;Above is an example of one of those dynamically generated images (of course, the image, and the text/statistics below change).&#xD;&#xA;&#xD;&#xA;How would I go about doing this in code? &#xD;&#xA;&#xD;&#xA;Sorry if this is in the wrong place - just wasn't sure where I would post this. Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/28fZc.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25766" PostHistoryTypeId="1" PostId="9405" RevisionGUID="deab9abf-c60b-4044-ab3b-dec13a0fc62f" CreationDate="2019-12-08T01:50:56.087" UserId="11577" Text="How do you add text dynamically to an image and export it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25767" PostHistoryTypeId="3" PostId="9405" RevisionGUID="deab9abf-c60b-4044-ab3b-dec13a0fc62f" CreationDate="2019-12-08T01:50:56.087" UserId="11577" Text="|image-processing|vector-graphics|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25768" PostHistoryTypeId="2" PostId="9406" RevisionGUID="02734956-798e-4346-9d98-abc54e606b5f" CreationDate="2019-12-08T08:20:21.087" UserId="11579" Text="Refer to narthex's excellent answer for details and example, but simply put,&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;If you want to *map* the pixel coordinate values to the range **0** to **1** , you divide by viewPortSize." ContentLicense="CC BY-SA 4.0" />
  <row Id="25769" PostHistoryTypeId="2" PostId="9407" RevisionGUID="fb01055d-b12a-4093-9ae9-12d023f0a0e1" CreationDate="2019-12-08T11:18:29.990" UserId="11580" Text="Your phone would have to do all of the CPU processing too then beam it to your laptop using scrypy if it's Linu: https://github.com/Genymobile/scrcpy/issues" ContentLicense="CC BY-SA 4.0" />
  <row Id="25770" PostHistoryTypeId="2" PostId="9408" RevisionGUID="578880dd-e66a-4cb7-a445-5cf3e8322f47" CreationDate="2019-12-08T12:41:36.947" UserId="11581" Text="I'm having a lot of trouble implementing Importance Sampling path tracer.&#xD;&#xA;&#xD;&#xA;I've been going at this for a ridiculous ammount of time and I'm starting to suspect that I'm either reaching the limits of floating point precission, or I've misunderstood the basic concept.&#xD;&#xA;&#xD;&#xA;If I understand it correctly, what I need to evaluate for a path tracer is this:  &#xD;&#xA;$\int_\Omega L_{in}(L) * fr(L, V) * \cos(\Theta_L) d\omega_L$&#xD;&#xA;&#xD;&#xA;Which for an Importance sampling PT is estimated by sampling $n$ times $L_i$ according to some pdf $p(L)$, i.e.:    &#xD;&#xA;$\frac{1}{M} * \sum_1^n L_{in}(L) * \frac{fr(L, V) * \cos(\Theta_L)}{p(L_i)}$&#xD;&#xA;&#xD;&#xA;Which in it's simplest form, for a single sample of a recursive reverse Path Tracer using an environment map, translates to roughly this pseudocode:&#xD;&#xA;&#xD;&#xA;    trace(scene, ray, throughput, depth) =&#xD;&#xA;        if(depth &gt; ...)&#xD;&#xA;             return 0&#xD;&#xA;        else&#xD;&#xA;            intersection, normal, material = intersect(ray, scene)&#xD;&#xA;            if(intersection)&#xD;&#xA;                new_ray = material.sample_direction(normal, ray)&#xD;&#xA;                new_throughput = material.brdf(normal, ray, new_ray)&#xD;&#xA;                               * cos(normal, new_ray)&#xD;&#xA;                               / material.pdf(normal, ray, new_ray)&#xD;&#xA;                return trace(scene, new_ray, new_throughut, depth + 1)&#xD;&#xA;            else&#xD;&#xA;                return throughput * environment(ray)&#xD;&#xA;&#xD;&#xA;Usually the $brdf * cos(theta)$ and the $pdf$ would be similar. In my case for Lambertian importance sampling, they are equal.&#xD;&#xA;&#xD;&#xA;What I think this means is that if, instead of importance sampling the material, I sample a random direction in the &quot;$normal$-oriented&quot; hemisphere, and use constant $\frac{1}{2 * PI}$ for the pdf, the radiance (for a sufficient number of samples) should be equal (up to some trivial variance):&#xD;&#xA;&#xD;&#xA;    trace(scene, ray, throughput, depth) =&#xD;&#xA;        if(depth &gt; ...)&#xD;&#xA;             return 0&#xD;&#xA;        else&#xD;&#xA;            intersection, normal, material = intersect(ray, scene)&#xD;&#xA;            if(intersection)&#xD;&#xA;                new_ray = sample_uniform_hemisphere(normal, ray)&#xD;&#xA;                new_throughput = material.brdf(normal, ray, new_ray)&#xD;&#xA;                               * cos(normal, new_ray)&#xD;&#xA;                               / (1/(2 * PI))        &#xD;&#xA;                return trace(scene, new_ray, new_throughut, depth + 1)&#xD;&#xA;            else&#xD;&#xA;                return throughput * environment(ray)&#xD;&#xA;&#xD;&#xA;Instead, even for trivial Lambertian materials, IF i switch the sampling pdfs in a checkerboard pattern, it shows a large difference in luminance:  &#xD;&#xA;[![enter image description here][1]][1]  &#xD;&#xA;&lt;sup&gt;&lt;i&gt;Switching sampling PDFs in a checkerboard pattern shows a difference in luminance&lt;/i&gt;&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;For more complex materials the problem is MUCH worse.&#xD;&#xA;&#xD;&#xA;The actual Lambert implementation is (note the albedo is separated out):&#xD;&#xA; &#xD;&#xA;    glm::vec3 lambert::sample(glm::vec3 n, glm::vec3 v) const&#xD;&#xA;    {&#xD;&#xA;        glm::vec2 xi{drand48(), drand48()};&#xD;&#xA;        float th = acosf(sqrtf(xi.x));&#xD;&#xA;        float ph = 2 * M_PIf32 * xi.y;&#xD;&#xA;        glm::vec3 dir{sinf(th) * cosf(ph), sinf(th) * sinf(ph), cosf(th)};&#xD;&#xA;        return local_to_normal(dir, n);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float lambert::bxdf(glm::vec3 n, glm::vec3 v, glm::vec3 l) const&#xD;&#xA;    {&#xD;&#xA;        return M_1_PIf32;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float lambert::pdf(glm::vec3 n, glm::vec3 v, glm::vec3 l) const&#xD;&#xA;    {&#xD;&#xA;        return glm::dot(n, l) * M_1_PIf32;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The actual trace routine is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    auto trace(ray r, scene const &amp;s)&#xD;&#xA;    {&#xD;&#xA;           float throughput = 1.0f;&#xD;&#xA;           for(int num_bounces = 0; num_bounces &lt; 6; ++num_bounces) {&#xD;&#xA;               auto &amp;&amp;[i, hit] = intersect_scene(r, s);&#xD;&#xA;               if(!i) {&#xD;&#xA;                       return throughput * sample_environment(r.dir, s.environment);&#xD;&#xA;               }&#xD;&#xA;               auto out_direction = hit.mat-&gt;sample(hit.x_norm, -r.dir);&#xD;&#xA;               throughput *= hit.mat-&gt;albedo * hit.mat-&gt;bxdf(hit.normal, -r.dir, out_direction)  * glm::dot(hit.normal, out_direction)/ hit.mat-&gt;pdf(hit.normal, -r.dir, out_direction);&#xD;&#xA;               r.src = hit.pos + hit.normal * 1e-4f;&#xD;&#xA;               r.dir = out_direction;    &#xD;&#xA;           }&#xD;&#xA;           return 0.f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For the uniform hemispherical sampling I use this:&#xD;&#xA;&#xD;&#xA;        auto const r = sqrtf(1.f - u1 * u1);&#xD;&#xA;        auto const phi = 2 * M_PIf32 * u2;&#xD;&#xA;        return {r * cosf(phi), r * sinf(phi), u1};&#xD;&#xA;&#xD;&#xA;And then change the basis to the intersection normal again.&#xD;&#xA;&#xD;&#xA;Please, if anyone has any idea could you please help?&#xD;&#xA;&#xD;&#xA;I can provide the whole project if it's necessary.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nUamC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25771" PostHistoryTypeId="1" PostId="9408" RevisionGUID="578880dd-e66a-4cb7-a445-5cf3e8322f47" CreationDate="2019-12-08T12:41:36.947" UserId="11581" Text="Can't get Importance Sampling to work" ContentLicense="CC BY-SA 4.0" />
  <row Id="25772" PostHistoryTypeId="3" PostId="9408" RevisionGUID="578880dd-e66a-4cb7-a445-5cf3e8322f47" CreationDate="2019-12-08T12:41:36.947" UserId="11581" Text="|pathtracing|brdf|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25773" PostHistoryTypeId="50" PostId="9303" RevisionGUID="0926c907-ab07-47a7-8ce9-625d54485c26" CreationDate="2019-12-08T13:02:25.347" UserId="-1" />
  <row Id="25774" PostHistoryTypeId="50" PostId="9207" RevisionGUID="adcad75e-9e42-4873-8df6-4a221dc93a52" CreationDate="2019-12-08T14:01:25.367" UserId="-1" />
  <row Id="25775" PostHistoryTypeId="2" PostId="9409" RevisionGUID="ca238113-ad94-4206-9c1d-d035ef4bc6f5" CreationDate="2019-12-08T15:34:58.047" UserId="11452" Text="In the accepted answer for the question https://computergraphics.stackexchange.com/questions/4979/what-is-importance-sampling, in the example code there is this line:&#xD;&#xA;&#xD;&#xA;    // Accumulate the brdf attenuation&#xD;&#xA;    throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;&#xD;&#xA;If the PDF is between 0.0 and 1.0, the division will potentially increase the throughput. I do not think it makes sense. What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25776" PostHistoryTypeId="1" PostId="9409" RevisionGUID="ca238113-ad94-4206-9c1d-d035ef4bc6f5" CreationDate="2019-12-08T15:34:58.047" UserId="11452" Text="Should ray throughput always decrease when bouncing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25777" PostHistoryTypeId="3" PostId="9409" RevisionGUID="ca238113-ad94-4206-9c1d-d035ef4bc6f5" CreationDate="2019-12-08T15:34:58.047" UserId="11452" Text="|pathtracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25778" PostHistoryTypeId="5" PostId="9408" RevisionGUID="6ac280ce-c667-45f3-90fc-452cd91ea8b6" CreationDate="2019-12-08T15:35:25.230" UserId="11581" Comment="deleted 193 characters in body; edited title" Text="I'm having a lot of trouble implementing Importance Sampling path tracer.&#xD;&#xA;&#xD;&#xA;If I understand it correctly, what I need to evaluate for a path tracer is this:  &#xD;&#xA;$\int_\Omega L_{in}(L) * fr(L, V) * \cos(\Theta_L) d\omega_L$&#xD;&#xA;&#xD;&#xA;Which for an Importance sampling PT is estimated by sampling $n$ times $L_i$ according to some pdf $p(L)$, i.e.:    &#xD;&#xA;$\frac{1}{M} * \sum_1^n L_{in}(L) * \frac{fr(L, V) * \cos(\Theta_L)}{p(L_i)}$&#xD;&#xA;&#xD;&#xA;Which in it's simplest form, for a single sample of a recursive reverse Path Tracer using an environment map, translates to roughly this pseudocode:&#xD;&#xA;&#xD;&#xA;    trace(scene, ray, throughput, depth) =&#xD;&#xA;        if(depth &gt; ...)&#xD;&#xA;             return 0&#xD;&#xA;        else&#xD;&#xA;            intersection, normal, material = intersect(ray, scene)&#xD;&#xA;            if(intersection)&#xD;&#xA;                new_ray = material.sample_direction(normal, ray)&#xD;&#xA;                new_throughput = material.brdf(normal, ray, new_ray)&#xD;&#xA;                               * cos(normal, new_ray)&#xD;&#xA;                               / material.pdf(normal, ray, new_ray)&#xD;&#xA;                return trace(scene, new_ray, new_throughut, depth + 1)&#xD;&#xA;            else&#xD;&#xA;                return throughput * environment(ray)&#xD;&#xA;&#xD;&#xA;Usually the $brdf * cos(theta)$ and the $pdf$ would be similar. In my case for Lambertian importance sampling, they are equal.&#xD;&#xA;&#xD;&#xA;What I think this means is that if, instead of importance sampling the material, I sample a random direction in the &quot;$normal$-oriented&quot; hemisphere, and use constant $\frac{1}{2 * PI}$ for the pdf, the radiance (for a sufficient number of samples) should be equal (up to some trivial variance):&#xD;&#xA;&#xD;&#xA;    trace(scene, ray, throughput, depth) =&#xD;&#xA;        if(depth &gt; ...)&#xD;&#xA;             return 0&#xD;&#xA;        else&#xD;&#xA;            intersection, normal, material = intersect(ray, scene)&#xD;&#xA;            if(intersection)&#xD;&#xA;                new_ray = sample_uniform_hemisphere(normal, ray)&#xD;&#xA;                new_throughput = material.brdf(normal, ray, new_ray)&#xD;&#xA;                               * cos(normal, new_ray)&#xD;&#xA;                               / (1/(2 * PI))        &#xD;&#xA;                return trace(scene, new_ray, new_throughut, depth + 1)&#xD;&#xA;            else&#xD;&#xA;                return throughput * environment(ray)&#xD;&#xA;&#xD;&#xA;Instead, even for trivial Lambertian materials, IF i switch the sampling pdfs in a checkerboard pattern, it shows a large difference in luminance:  &#xD;&#xA;[![enter image description here][1]][1]  &#xD;&#xA;&lt;sup&gt;&lt;i&gt;Switching sampling PDFs in a checkerboard pattern shows a difference in luminance&lt;/i&gt;&lt;/sup&gt;&#xD;&#xA;&#xD;&#xA;For more complex materials the problem is MUCH worse.&#xD;&#xA;&#xD;&#xA;The actual Lambert implementation is (note the albedo is separated out):&#xD;&#xA; &#xD;&#xA;    glm::vec3 lambert::sample(glm::vec3 n, glm::vec3 v) const&#xD;&#xA;    {&#xD;&#xA;        glm::vec2 xi{drand48(), drand48()};&#xD;&#xA;        float th = acosf(sqrtf(xi.x));&#xD;&#xA;        float ph = 2 * M_PIf32 * xi.y;&#xD;&#xA;        glm::vec3 dir{sinf(th) * cosf(ph), sinf(th) * sinf(ph), cosf(th)};&#xD;&#xA;        return local_to_normal(dir, n);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float lambert::bxdf(glm::vec3 n, glm::vec3 v, glm::vec3 l) const&#xD;&#xA;    {&#xD;&#xA;        return M_1_PIf32;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float lambert::pdf(glm::vec3 n, glm::vec3 v, glm::vec3 l) const&#xD;&#xA;    {&#xD;&#xA;        return glm::dot(n, l) * M_1_PIf32;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The actual trace routine is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    auto trace(ray r, scene const &amp;s)&#xD;&#xA;    {&#xD;&#xA;           float throughput = 1.0f;&#xD;&#xA;           for(int num_bounces = 0; num_bounces &lt; 6; ++num_bounces) {&#xD;&#xA;               auto &amp;&amp;[i, hit] = intersect_scene(r, s);&#xD;&#xA;               if(!i) {&#xD;&#xA;                       return throughput * sample_environment(r.dir, s.environment);&#xD;&#xA;               }&#xD;&#xA;               auto out_direction = hit.mat-&gt;sample(hit.x_norm, -r.dir);&#xD;&#xA;               throughput *= hit.mat-&gt;albedo * hit.mat-&gt;bxdf(hit.normal, -r.dir, out_direction)  * glm::dot(hit.normal, out_direction)/ hit.mat-&gt;pdf(hit.normal, -r.dir, out_direction);&#xD;&#xA;               r.src = hit.pos + hit.normal * 1e-4f;&#xD;&#xA;               r.dir = out_direction;    &#xD;&#xA;           }&#xD;&#xA;           return 0.f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For the uniform hemispherical sampling I use this:&#xD;&#xA;&#xD;&#xA;        auto const r = sqrtf(1.f - u1 * u1);&#xD;&#xA;        auto const phi = 2 * M_PIf32 * u2;&#xD;&#xA;        return {r * cosf(phi), r * sinf(phi), u1};&#xD;&#xA;&#xD;&#xA;And then change the basis to the intersection normal again.&#xD;&#xA;&#xD;&#xA;Please, if anyone has any idea could you please help?&#xD;&#xA;&#xD;&#xA;I can provide more of the project if it's necessary.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nUamC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25779" PostHistoryTypeId="4" PostId="9408" RevisionGUID="6ac280ce-c667-45f3-90fc-452cd91ea8b6" CreationDate="2019-12-08T15:35:25.230" UserId="11581" Comment="deleted 193 characters in body; edited title" Text="Importance Sampling path tracer, Different pdfs result in different luminance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25780" PostHistoryTypeId="2" PostId="9410" RevisionGUID="f36b97bd-a1cf-4ef3-a1ad-5272537effb1" CreationDate="2019-12-08T20:18:25.643" UserId="11581" Text="I have a similar question currently posted, so take the following with a grain of salt (I'd have made it a comment, but I don't have 50 reputation).&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. It is just the product of $brdf\times\cos(\theta)\div pdf$, i.e. the number we multiply the indirect light contribution by.  &#xD;&#xA;If this is true, and it is possible for $\cos(\theta)$ and the $pdf$ to be equal to 1,  then for the case of 1 bounce (direct light) the throughput needs to equal brdf, and brdf can reach infinity." ContentLicense="CC BY-SA 4.0" />
  <row Id="25781" PostHistoryTypeId="5" PostId="9410" RevisionGUID="24ba6b04-96e9-4274-8dfe-c22dcad365af" CreationDate="2019-12-08T20:33:13.330" UserId="11581" Comment="deleted 128 characters in body" Text="I have a similar question currently posted, so take the following with a grain of salt (I'd have made it a comment, but I don't have 50 reputation).&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. Even if you just consider the throughput for a single bounce (direct light) and disregard the possibility of the pdf being less than 1, unless the pdf is infinite, the throughput can - and should be able - to reach infinity, because the brdf can." ContentLicense="CC BY-SA 4.0" />
  <row Id="25782" PostHistoryTypeId="5" PostId="9410" RevisionGUID="bd7ff7a9-4c44-4a47-916c-77ee4c840b6a" CreationDate="2019-12-08T20:38:45.767" UserId="11581" Comment="deleted 128 characters in body" Text="I have a similar question currently posted, so take the following with a grain of salt (I'd have made it a comment, but I don't have 50 reputation).&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. BRDF only needs to be non negative and to integrate to 1 over the hemisphere. It can reach infinity - e.g. in the case of a mirror. &#xD;&#xA;Unless the pdf is always larger than the BRDF, the throughput should be able to reach infinity." ContentLicense="CC BY-SA 4.0" />
  <row Id="25783" PostHistoryTypeId="5" PostId="9410" RevisionGUID="bb606f77-5fa7-4385-ad9d-4cea4e7cb0da" CreationDate="2019-12-08T20:47:10.213" UserId="11581" Comment="deleted 61 characters in body" Text="I have a similar question currently posted, so take the following with a grain of salt.&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. BRDF only needs to be non negative and to integrate to 1 over the hemisphere. It can reach infinity - e.g. in the case of a mirror. &#xD;&#xA;Unless the pdf is always larger than the BRDF, the throughput should be able to reach infinity.&#xD;&#xA;&#xD;&#xA;*BRDF in your case corresponds to material-&gt;Eval(wi, wo, normal) / dot(normal, wi)*" ContentLicense="CC BY-SA 4.0" />
  <row Id="25784" PostHistoryTypeId="5" PostId="9410" RevisionGUID="c02944ec-339b-43d9-9e93-e0396e41986a" CreationDate="2019-12-08T20:59:48.150" UserId="11581" Comment="deleted 61 characters in body" Text="I have a similar question currently posted, so take the following with a grain of salt.&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. BRDF only needs to be non negative and to integrate to 1 over the hemisphere. It can reach infinity - e.g. in the case of a mirror. &#xD;&#xA;&#xD;&#xA;The pdf should approximate the BRDF to reduce variance. However, unless it is always larger than the BRDF, the throughput will be larger than 1 and should be able to reach infinity.&#xD;&#xA;&#xD;&#xA;*BRDF in your case corresponds to material-&gt;Eval(wi, wo, normal) / dot(normal, wi)*" ContentLicense="CC BY-SA 4.0" />
  <row Id="25786" PostHistoryTypeId="2" PostId="9411" RevisionGUID="19d9409c-37ec-42a6-b45a-ecd0569341b2" CreationDate="2019-12-08T22:48:27.970" UserId="11581" Text="To do this in a web app is trivial. Judging by the image, even the built-in HTML canvas should be able to do everything that you need.&#xD;&#xA;&#xD;&#xA;Once you have obtained your image and text, to give you a vague idea of the ammount of code involved, drawing them with the canvas API looks roughly as follows:&#xD;&#xA;&#xD;&#xA;    ctx.drawImage(img, x, y, width, height);&#xD;&#xA;    ctx.font = '12px serif';&#xD;&#xA;    ctx.fillText(txt, x, y);&#xD;&#xA;&#xD;&#xA;Saving the image is equally simple:&#xD;&#xA;&#xD;&#xA;    canvas.toDataURL(&quot;image/png&quot;)&#xD;&#xA;&#xD;&#xA;It's actually the obtaining and sharing of images are the scary parts. Spotify surely have all the images on their cloud and similarly that is where they export them to before sharing to social media. There are so many sollutions that without more detail this is probably something you'll need to find yourself.&#xD;&#xA;&#xD;&#xA;If you just need a tutorial on html canvas, [mozzilla usually have great interactive tutorials][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage" ContentLicense="CC BY-SA 4.0" />
  <row Id="25787" PostHistoryTypeId="50" PostId="9178" RevisionGUID="cd0c3012-caa1-44d8-b75a-d8db18c06e52" CreationDate="2019-12-08T23:00:35.050" UserId="-1" />
  <row Id="25792" PostHistoryTypeId="50" PostId="9328" RevisionGUID="7cca456b-8392-4e7d-ac1b-7bc299c7c668" CreationDate="2019-12-09T00:02:05.550" UserId="-1" />
  <row Id="25794" PostHistoryTypeId="2" PostId="9413" RevisionGUID="9efb8ec4-a011-4ff9-a198-fdf51a727a30" CreationDate="2019-12-09T15:41:31.030" UserId="10928" Text="I wonder what is the reason that when z increase, the objects appear far away and when z is negative, the object is behind the camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25795" PostHistoryTypeId="1" PostId="9413" RevisionGUID="9efb8ec4-a011-4ff9-a198-fdf51a727a30" CreationDate="2019-12-09T15:41:31.030" UserId="10928" Text="Why is the z direction towards the screen?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25796" PostHistoryTypeId="3" PostId="9413" RevisionGUID="9efb8ec4-a011-4ff9-a198-fdf51a727a30" CreationDate="2019-12-09T15:41:31.030" UserId="10928" Text="|3d|projections|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25797" PostHistoryTypeId="2" PostId="9414" RevisionGUID="e59fb86a-6c27-4de2-af38-e18881512d51" CreationDate="2019-12-09T19:45:18.977" UserId="38" Text=" If you want to use the traditional x is towards right and y is up you are used to in math and physics classes. Now if you follow a right handed coordinate space, which is also commonly used. Then the direction of the z follows from the x and y direction. &#xD;&#xA;&#xD;&#xA;So to recap right hand rule is causing this.&#xD;&#xA;&#xD;&#xA;This is s typical convention thats all." ContentLicense="CC BY-SA 4.0" />
  <row Id="25798" PostHistoryTypeId="5" PostId="9414" RevisionGUID="ba8ff383-9931-4eaf-9b1c-4815c782530d" CreationDate="2019-12-09T19:53:16.833" UserId="38" Comment="added 435 characters in body" Text=" If you want to use the traditional x is towards right and y is up you are used to in math and physics classes. Now if you follow a right handed coordinate space, which is also commonly used. Then the direction of the z follows from the x and y direction.  In this sceme positive z is pointing out from the screen.&#xD;&#xA;&#xD;&#xA;Now you can also choose a left handed coordinate system in which case the z is reversed. Its just a matter of choosing which convention you want to use. &#xD;&#xA;&#xD;&#xA;Likewise if you choose y to be down, ala traditional windowing math then z is reversed even if you use right hand rule.&#xD;&#xA;&#xD;&#xA;None of these conventions are set in stone you can do whatever you want. A bit like you can choose row major or column major matrixes. You just need to know what comvention you follow." ContentLicense="CC BY-SA 4.0" />
  <row Id="25799" PostHistoryTypeId="4" PostId="9413" RevisionGUID="446b27f9-e4c5-459e-aa73-ccc0e970a4bf" CreationDate="2019-12-10T08:49:39.287" UserId="209" Comment="As lightxbulb pointed out, the title of the question was the opposite of the actual question (and also tried to remove some ambiguity)." Text="Why is the z direction away from the screen/viewer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25800" PostHistoryTypeId="2" PostId="9415" RevisionGUID="299b9100-8761-4dce-890f-c87f9d94c201" CreationDate="2019-12-10T09:44:12.827" UserId="11586" Text="This question is in reference to the method described in ShaderX7 section 2.4 &quot;Fast Skin Shading&quot; by Hable et. al. The part I do not understand is how they derived the weights for the individual samples. They describe the process only very briefly like this: &#xD;&#xA;&#xD;&#xA;_&quot;Since using a sum of Gaussian blurs is a good way to describe subsurface scattering, we&#xD;&#xA;describe the blur in this way. Then, in an offline process, we combine the sum of the blurs into a&#xD;&#xA;single blur, and then sample. This approach provides us with an intuitive way to tweak the blur&#xD;&#xA;for different skin types.&quot;_&#xD;&#xA;&#xD;&#xA;I assumed this means that they calculated the weight $W$ for a sample as&#xD;&#xA;&#xD;&#xA;$$W = \sum_i w_iG(v_i, r)$$&#xD;&#xA;&#xD;&#xA;but the result is completely off. So what is the correct way to calculate these?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25801" PostHistoryTypeId="1" PostId="9415" RevisionGUID="299b9100-8761-4dce-890f-c87f9d94c201" CreationDate="2019-12-10T09:44:12.827" UserId="11586" Text="How to calculate subsurface scatteing weights for fast skin shading" ContentLicense="CC BY-SA 4.0" />
  <row Id="25802" PostHistoryTypeId="3" PostId="9415" RevisionGUID="299b9100-8761-4dce-890f-c87f9d94c201" CreationDate="2019-12-10T09:44:12.827" UserId="11586" Text="|subsurface-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25803" PostHistoryTypeId="50" PostId="5996" RevisionGUID="b7b82179-a5fc-41e3-9f70-221067c73ec1" CreationDate="2019-12-10T12:02:15.267" UserId="-1" />
  <row Id="25804" PostHistoryTypeId="50" PostId="8996" RevisionGUID="77c11812-c7c1-45a0-bf35-c4c8e42b401e" CreationDate="2019-12-10T14:03:00.530" UserId="-1" />
  <row Id="25809" PostHistoryTypeId="2" PostId="9417" RevisionGUID="fab82884-0e20-4949-9da5-6f2c8c071dec" CreationDate="2019-12-11T17:57:31.210" UserId="7462" Text="I asked this in regular SO but I think people are not understanding the question so i will try here:&#xD;&#xA;&#xD;&#xA;So, for anyone familiar with Google Maps, when you zoom, it does it around the cursor.&#xD;&#xA;&#xD;&#xA;That is to say, the matrix transformation for such a zoom is as simple as:&#xD;&#xA;&#xD;&#xA;TST^{-1}*x&#xD;&#xA;&#xD;&#xA;Where T is the translation matrix representing the point of focus, S the scale matrix and x is any arbitrary point on the plane.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, I want to produce a similar effect with a spherical camera, think [sketchfab][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When you zoom in and out, the camera needs to be translated so as to give a similar effect as the 2D zooming in Maps. To be more precise, given a fully composed MVP matrix, there exists a set of parallel planes that are parallel to the camera plane. Among those there exists a unique plane P that also contains the center of the current spherical camera.&#xD;&#xA;&#xD;&#xA;Given that plane, there exists a point x, that is the unprojection of the current cursor position onto the camera plane. &#xD;&#xA;&#xD;&#xA;If the center of the spherical camera is c then the direction from c to x is d = x - c.&#xD;&#xA;&#xD;&#xA;And here's where my challenge comes. Zooming is implemented as just offsetting the camera radially from the center, given a change in zoom Delta, I need to find the translation vector u, colinear with d, that moves the center of the camera towards x, such that I get a similar visual effect as zooming in google maps.&#xD;&#xA;&#xD;&#xA;Since I know this is a bit hard to parse I tried to make a diagram:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://sketchfab.com/3d-models/poisonous-cfba7da278eb41bc941022ca9ecebabe&#xD;&#xA;  [2]: https://i.stack.imgur.com/E2hqx.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;TL;DR&#xD;&#xA;&#xD;&#xA;I want to offset a spherical camera towards the cursor when I zoom, how do i pick my translation vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25810" PostHistoryTypeId="1" PostId="9417" RevisionGUID="fab82884-0e20-4949-9da5-6f2c8c071dec" CreationDate="2019-12-11T17:57:31.210" UserId="7462" Text="How to Pan Zoom a spherical camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25811" PostHistoryTypeId="3" PostId="9417" RevisionGUID="fab82884-0e20-4949-9da5-6f2c8c071dec" CreationDate="2019-12-11T17:57:31.210" UserId="7462" Text="|projections|camera|linear-algebra|ui|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25813" PostHistoryTypeId="2" PostId="9418" RevisionGUID="945ad099-02ad-4651-82e0-0321a0034a95" CreationDate="2019-12-11T21:47:13.260" UserId="8962" Text="I'm trying to use open image denoise. Here's the code:&#xD;&#xA;&#xD;&#xA;    int main() {&#xD;&#xA;    	int width, height, nrChannels;&#xD;&#xA;    	unsigned char* image = stbi_load(&quot;img_cornell_box.png&quot;, &amp;width, &amp;height, &amp;nrChannels, 0);&#xD;&#xA;    	unsigned char* resultImage = new unsigned char[width*height*nrChannels];&#xD;&#xA;    	oidn::DeviceRef device = oidn::newDevice();&#xD;&#xA;    	device.commit();&#xD;&#xA;    	std::cout &lt;&lt; nrChannels &lt;&lt; std::endl;&#xD;&#xA;    	oidn::FilterRef filter = device.newFilter(&quot;RT&quot;);&#xD;&#xA;    	filter.setImage(&quot;color&quot;, image, oidn::Format::Float4, width, height);&#xD;&#xA;    	filter.setImage(&quot;output&quot;, resultImage, oidn::Format::Float4, width, height);&#xD;&#xA;    	filter.set(&quot;hdr&quot;, false);&#xD;&#xA;    	filter.set(&quot;srgb&quot;, true);&#xD;&#xA;    	filter.commit();&#xD;&#xA;    	filter.execute();&#xD;&#xA;    &#xD;&#xA;    	const char* errorMessage;&#xD;&#xA;    	if (device.getError(errorMessage) != oidn::Error::None) {&#xD;&#xA;    		std::cout &lt;&lt; &quot;Error: &quot; &lt;&lt; errorMessage &lt;&lt; std::endl;&#xD;&#xA;    	}&#xD;&#xA;    	else {&#xD;&#xA;    		stbi_write_png(&quot;img.png&quot;, width, height, nrChannels, resultImage, width * nrChannels);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm getting an error saying that the image format is unsupported.&#xD;&#xA;&#xD;&#xA;If I use jpg, and change Format::Float4 to Format::Float3 I get this error:&#xD;&#xA;&#xD;&#xA;    Exception thrown at 0x00007FFC5588E1F5 (OpenImageDenoise.dll) in oidntest.exe: 0xC0000005: Access violation reading location 0x0000021D9C42FA70.&#xD;&#xA;&#xD;&#xA;Am I doing something wrong?&#xD;&#xA;This is the image I'm using: https://drive.google.com/open?id=1uSjsyWCRisXNFUJG6R8iL5AdVbM7_18u" ContentLicense="CC BY-SA 4.0" />
  <row Id="25814" PostHistoryTypeId="1" PostId="9418" RevisionGUID="945ad099-02ad-4651-82e0-0321a0034a95" CreationDate="2019-12-11T21:47:13.260" UserId="8962" Text="Trouble using Open Image Denoise" ContentLicense="CC BY-SA 4.0" />
  <row Id="25815" PostHistoryTypeId="3" PostId="9418" RevisionGUID="945ad099-02ad-4651-82e0-0321a0034a95" CreationDate="2019-12-11T21:47:13.260" UserId="8962" Text="|image|denoise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25816" PostHistoryTypeId="50" PostId="8260" RevisionGUID="d9cf0fb4-f119-4c62-bb3c-666da523643d" CreationDate="2019-12-12T00:02:50.383" UserId="-1" />
  <row Id="25817" PostHistoryTypeId="4" PostId="9415" RevisionGUID="07556255-1522-4cae-8769-1c99dfc7f6ae" CreationDate="2019-12-12T09:53:03.277" UserId="11586" Comment="edited title" Text="How to calculate subsurface scattering weights for fast skin shading" ContentLicense="CC BY-SA 4.0" />
  <row Id="25818" PostHistoryTypeId="2" PostId="9419" RevisionGUID="b963c1aa-e320-4f7e-a865-f78f916fae32" CreationDate="2019-12-12T20:13:46.390" UserId="11241" Text="$\textbf{Problem:}$&#xD;&#xA;&#xD;&#xA;Getting a $\textit{polygon-mesh}$ as input, I have to construct a surface that looks exactly to the given input. My task is to generate a $\textit{b-spline}$ surface that exactly looks like the connected polygon mesh. It is obvious that my $\textit{b-spline}$ surface has to have a degree of one in both directions $\textit{u}$ and $\textit{v}$.&#xD;&#xA;&#xD;&#xA;$\textbf{Output:}$&#xD;&#xA;&#xD;&#xA;As an output for my solution. I have to generate a matrix of $\textit{control point}$ that represent that generated surface.&#xD;&#xA;&#xD;&#xA;One property of this matrix is that each elements of each row and column are connected with each others.&#xD;&#xA;If our control points matrix is a $ n \times m$ matrix, then let $C_i$ a column of this matrix with $C_i = &lt;e_{1i}, e_{2i}, \dots, e_{mi}&gt;$ then there must exist path in the polygon from $e_{1i}$ to $e_{mi}$.&#xD;&#xA;&#xD;&#xA;One thing to consider if there is no edge between  $e_{ji}$ to $e_{(j+1)i}$, we can construct one as long as this edge lies inside the polygon.&#xD;&#xA;&#xD;&#xA;$\textbf{my trivial idea}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Assuming that the polygon has $n$ nodes. I create $n$ other nodes inside the polygon near each original node. I create then a $2 \times n$ matrix. The first row contains all the points constructing the polygon. Second row contains the corresponding additional inserted node. In order to connect two additional inserted nodes, i have to make sure that the line between two nodes is kept inside the polygon.&#xD;&#xA;&#xD;&#xA;This idea works only for simple structure and the complexer is the polygon the hard to find these additional points.&#xD;&#xA;&#xD;&#xA;Any good solutions maybe ?.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25819" PostHistoryTypeId="1" PostId="9419" RevisionGUID="b963c1aa-e320-4f7e-a865-f78f916fae32" CreationDate="2019-12-12T20:13:46.390" UserId="11241" Text="Convert a polygon mesh to a bspline surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="25820" PostHistoryTypeId="3" PostId="9419" RevisionGUID="b963c1aa-e320-4f7e-a865-f78f916fae32" CreationDate="2019-12-12T20:13:46.390" UserId="11241" Text="|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25821" PostHistoryTypeId="50" PostId="9341" RevisionGUID="326bb8bc-37b0-4358-8cee-6559a49383b1" CreationDate="2019-12-12T21:02:00.233" UserId="-1" />
  <row Id="25822" PostHistoryTypeId="2" PostId="9420" RevisionGUID="103ed4b5-5e8a-46d7-9959-b6445ff43cf1" CreationDate="2019-12-13T05:35:12.407" UserId="9903" Text="You can use Query for mesuring time on GPU. Idea is follow:&#xD;&#xA;Create buffer with two int64 values. Write time stamp before and after CopyResource() on GPU to this buffer. Then retrive values on CPU and substract them. Substraction is time on GPU." ContentLicense="CC BY-SA 4.0" />
  <row Id="25823" PostHistoryTypeId="5" PostId="9419" RevisionGUID="a592670e-6741-44c4-8d10-2c05e13840ce" CreationDate="2019-12-13T14:19:50.497" UserDisplayName="user106" Comment="don't use MathJaX for text formatting" Text="**Problem:**&#xD;&#xA;&#xD;&#xA;Getting a *polygon mesh* as input, I have to construct a surface that looks exactly to the given input. My task is to generate a *b-spline* surface that exactly looks like the connected polygon mesh. It is obvious that my *b-spline* surface has to have a degree of one in both directions $u$ and $v$.&#xD;&#xA;&#xD;&#xA;**Output:**&#xD;&#xA;&#xD;&#xA;As an output for my solution. I have to generate a matrix of *control points* that represent that generated surface.&#xD;&#xA;&#xD;&#xA;One property of this matrix is that each elements of each row and column are connected with each others.&#xD;&#xA;If our control points matrix is a $ n \times m$ matrix, then let $C_i$ a column of this matrix with $C_i = \langle e_{1i}, e_{2i}, \dots, e_{mi} \rangle$ then there must exist path in the polygon from $e_{1i}$ to $e_{mi}$.&#xD;&#xA;&#xD;&#xA;One thing to consider if there is no edge between  $e_{ji}$ to $e_{(j+1)i}$, we can construct one as long as this edge lies inside the polygon.&#xD;&#xA;&#xD;&#xA;**My trivial idea:**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Assuming that the polygon has $n$ nodes. I create $n$ other nodes inside the polygon near each original node. I create then a $2 \times n$ matrix. The first row contains all the points constructing the polygon. Second row contains the corresponding additional inserted node. In order to connect two additional inserted nodes, i have to make sure that the line between two nodes is kept inside the polygon.&#xD;&#xA;&#xD;&#xA;This idea works only for simple structure and the complexer is the polygon the hard to find these additional points.&#xD;&#xA;&#xD;&#xA;Any good solutions maybe?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25824" PostHistoryTypeId="24" PostId="9419" RevisionGUID="a592670e-6741-44c4-8d10-2c05e13840ce" CreationDate="2019-12-13T14:19:50.497" Comment="Proposed by 106 approved by 5717, 11241 edit id of 500" ContentLicense="CC BY-SA 4.0" />
  <row Id="25825" PostHistoryTypeId="2" PostId="9421" RevisionGUID="6551a13e-7d31-4c9e-ba4d-8632138f1b9c" CreationDate="2019-12-13T21:59:29.790" UserId="11598" Text="As the title suggests I'm trying to implement the last images of the &quot;Microfacet Models for Refraction through Rough Surfaces&quot; Paper by Walter et al. in OpenGL[![see here for the picture][1]][1]&#xD;&#xA;&#xD;&#xA;I &quot;think&quot; (I had to put that into quotation marks) I know how the microfacet model should work and hopefully am only stuck on practical execution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I started by implementing the GGX formulas for the Normal Distribution, Fresnel and Geometry Function.&#xD;&#xA;&#xD;&#xA;Initially and still I'm not so sure how to get the color of the object behind the glass into the formulas. My first thought was to create a cubemap around the slate of glass and then use the outgoing direction vectors (o_t and o_r) to sample the cubemap. But then I'm still not so sure how to incorporate that into the larger picture. Going by my first thought again I just multiplied the result of the BTFD with the sample of the o_t vector but apparently the BTDF was really big so the whole slate turned white (possible bug?). After dividing the result a few times some washed-up version of what was supposed to show up appeared.&#xD;&#xA;&#xD;&#xA;Also I think I read somewhere that the reflection and transmission should be handled seperatly depending on the result of the Fresnel formula.&#xD;&#xA;Or should it be handled at the same time (possibly somethink like : BRDF * sample_of_reflection + BTDF * sample_of_refraction)?&#xD;&#xA;&#xD;&#xA;And another thing I found curious is the given equation for sampling:&#xD;&#xA;&#xD;&#xA;$\theta = arctan(a * sqrt(rand1) / sqrt(1 - rand1))$&#xD;&#xA;&#xD;&#xA;$\phi = 2 * \pi * rand2$&#xD;&#xA;&#xD;&#xA;After some playing around with this function I noticed that is basically something akin to a gaussian distribution pointing towards the positive z-axis. But shouldn't the distribution give samples which are distributed around the surface normal? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm wondering if I have to add an additional pair of quotation marks to my earlier statement...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So anyway here is the pseudocode for my implementation until now:&#xD;&#xA;```glsl&#xD;&#xA;for(#samplecount)&#xD;&#xA;{&#xD;&#xA; //get a sample m&#xD;&#xA; vec3 m = drawsample();&#xD;&#xA; &#xD;&#xA; //calculate normal and incoming vector&#xD;&#xA; vec3 i = normalize(viewPosition - fragmentPosition);&#xD;&#xA; vec3 n = normalize(Normal); &#xD;&#xA; &#xD;&#xA; // calculate outgoing vector&#xD;&#xA; vec3 o_r = calculate_like_paper();&#xD;&#xA; vec3 o_t = calculate_like_paper();&#xD;&#xA;&#xD;&#xA; //sample cubemap&#xD;&#xA; vec3 reflection = sampleCubemap();&#xD;&#xA; vec3 refraction = sampleCubemap(); &#xD;&#xA;&#xD;&#xA; //calculate halfvectors&#xD;&#xA; vec3 h_r = calculate_like_paper();&#xD;&#xA; vec3 h_t = calculate_like_paper();&#xD;&#xA;&#xD;&#xA; //calculate NDF, Fresnel and Geometry&#xD;&#xA; float D = GGX_D(h_r);&#xD;&#xA; float G = GGX_G(i, o_r, h_r);&#xD;&#xA; float F = GGX_F(i, h_r);&#xD;&#xA;&#xD;&#xA; //calculate BSDF, BRDF &amp; BTDF&#xD;&#xA; float BRDF = F * G * D / (4.0 * abs(dot(i, n)) * abs(dot(o_r, n)));&#xD;&#xA; float BTDF = longFormula();&#xD;&#xA;&#xD;&#xA; float BSDF = BRDF + BTDF&#xD;&#xA; &#xD;&#xA; vec3 result += BRDF * reflection + BTDF * refraction //?&#xD;&#xA;}&#xD;&#xA;result /= #samplecount;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you if you take your time to answer and I'm relatively new to StackExchange so I could definitely do with some feedback to improve the way I ask questions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xofnw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25826" PostHistoryTypeId="1" PostId="9421" RevisionGUID="6551a13e-7d31-4c9e-ba4d-8632138f1b9c" CreationDate="2019-12-13T21:59:29.790" UserId="11598" Text="Implementing the example of Walter et al. (2007) paper" ContentLicense="CC BY-SA 4.0" />
  <row Id="25827" PostHistoryTypeId="3" PostId="9421" RevisionGUID="6551a13e-7d31-4c9e-ba4d-8632138f1b9c" CreationDate="2019-12-13T21:59:29.790" UserId="11598" Text="|opengl|brdf|microfacet|bsdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25828" PostHistoryTypeId="50" PostId="8151" RevisionGUID="63e5a976-f157-4d54-a0c8-a48008ba0976" CreationDate="2019-12-14T00:02:50.330" UserId="-1" />
  <row Id="25829" PostHistoryTypeId="50" PostId="7730" RevisionGUID="a2b7dc52-5b3d-4ff9-8d32-41a1744ead7f" CreationDate="2019-12-14T02:00:50.350" UserId="-1" />
  <row Id="25830" PostHistoryTypeId="2" PostId="9422" RevisionGUID="47c31481-c601-459d-8ab9-73c8759ee6ac" CreationDate="2019-12-14T02:28:41.630" UserId="5717" Text="&gt; Initially and still I'm not so sure how to get the color of the object behind the glass into the formulas.&#xD;&#xA;&#xD;&#xA;Normal, this was written with path / ray tracers in mind where that part is easy. Your idea of a cube map might be ok for some use cases (eg. reasonably rough surface for the distance to the surrounding objects). It is not a general solution however. That would likely require GPU ray tracing.&#xD;&#xA;&#xD;&#xA;&gt; Going by my first thought again I just multiplied the result of the BTFD with the sample of the o_t vector but apparently the BTDF was really big so the whole slate turned white (possible bug?).&#xD;&#xA;&#xD;&#xA;I'm writing this from memory but I think you need to divide by the PDF. Which means that your weights will be close to 1. But not quite 1 as the sampling distributions don't include the shadowing terms.&#xD;&#xA;&#xD;&#xA;&gt; Also I think I read somewhere that the reflection and transmission should be handled seperatly depending on the result of the Fresnel formula. Or should it be handled at the same time (possibly somethink like : BRDF * sample_of_reflection + BTDF * sample_of_refraction)?&#xD;&#xA;&#xD;&#xA;A classic path tracer would randomly pick either reflection or refraction based on the fresnel coefficient. That does efficient sampling. But if you can easily get both from a cube map, you can also blend them with the fresnel coefficient.&#xD;&#xA;&#xD;&#xA;&gt; After some playing around with this function I noticed that is basically something akin to a gaussian distribution pointing towards the positive z-axis. But shouldn't the distribution give samples which are distributed around the surface normal?&#xD;&#xA;&#xD;&#xA;Yes, you need to transform the generated direction. It is mentionned in section 5.2, after equation (24), that $\theta_m$ is the angle between $m$ (microfacet normal) and $n$ (surface normal). They don't go into great detail as this way of defining microfacet models goes back to much older articles.&#xD;&#xA;&#xD;&#xA;The short version is that you build an orthonormal basis using the surface normal as z and two other perpendicular vectors as x and y. Here it does not matter which as the distribution is isotropic, as long as they are perpendicular to each other and to the normal. Then you transform using that basis." ContentLicense="CC BY-SA 4.0" />
  <row Id="25832" PostHistoryTypeId="2" PostId="9423" RevisionGUID="822baade-0435-405e-a0b7-2d82fff17486" CreationDate="2019-12-15T06:15:32.847" UserId="5066" Text="As far as I remember, you need to input data in float array. Right now your input is unsigned char array. To quick check this, try loading any HDR image in float array &amp; pass it on to the setImage functions, this seems to work. &#xD;&#xA;&#xD;&#xA;In your case, you would need to read individual image channel data &amp; cast it to float. If your image color is stored in [0-255] range, you would then need to bring it to [0-1] range (Not completely sure about this stage!) &amp; then pass the data in float array to denoiser functions.&#xD;&#xA;&#xD;&#xA;Hope this helps. &#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25834" PostHistoryTypeId="2" PostId="9424" RevisionGUID="146b598e-a7f0-4039-aa64-a3463fcfb6d8" CreationDate="2019-12-16T20:50:57.737" UserId="11605" Text="## The problem ##&#xD;&#xA;&#xD;&#xA;I'm using a 3D extension of the well-known &quot;[Turtle graphics][1]&quot; to draw plants. My system works by maintaining a position $\vec{p}$ and three vectors:&#xD;&#xA;&#xD;&#xA; - The heading $\vec{H}$&#xD;&#xA; - The &quot;up&quot; direction $\vec{U}$&#xD;&#xA; - The &quot;left&quot; direction $\vec{L}$&#xD;&#xA;&#xD;&#xA;My problem is now that I want to be able to create 3D objects at the position of the turtle, but with the added difficulty of being &quot;transformed&quot; into the turtle's coordinate system defined by the vectors $\vec{H}, \vec{U}$ and $\vec{L}$, so that the model is &quot;aligned&quot; with the direction and orientation of the turtle. I basically want to achieve that the model is transformed in such a way, that:&#xD;&#xA;&#xD;&#xA; - The local origin becomes the turtle position&#xD;&#xA; - The local x-Axis is rotated onto the heading vector $\vec{H}$&#xD;&#xA; - The local y-Axis is rotated onto the right vector $- \vec{L}$&#xD;&#xA; - The local z-Axis is rotated onto the up vector $\vec{U}$&#xD;&#xA;&#xD;&#xA;The reason I want this is to be able to spawn 3D models that describe the leaves of a plant on stalks generated by the turtle.&#xD;&#xA;&#xD;&#xA;## My own idea so far ##&#xD;&#xA;&#xD;&#xA;I'm not very good at linear algebra, but I thought of using a base change matrix of the form:&#xD;&#xA;$$A := \begin{pmatrix}\vec{H} &amp; -\vec{L} &amp; \vec{U} \end{pmatrix}$$&#xD;&#xA;And combining that with the translation by $\vec{p}$ to obtain the following model matrix:&#xD;&#xA;&#xD;&#xA;$$T := \begin{pmatrix} A &amp; \begin{matrix} p_1 \\ p_2 \\ p_3\end{matrix}\\ &#xD;&#xA;\begin{matrix}0 &amp; 0&amp; 0\end{matrix} &amp; 1&#xD;&#xA;\end{pmatrix}$$&#xD;&#xA;&#xD;&#xA;Would this achieve the effect I want? I am currently only in the planning phase of the project this will be used in, so I can't check this myself.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Turtle_graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="25835" PostHistoryTypeId="1" PostId="9424" RevisionGUID="146b598e-a7f0-4039-aa64-a3463fcfb6d8" CreationDate="2019-12-16T20:50:57.737" UserId="11605" Text="Transformation for aligning 3D object with reference frame of 3D turtle graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="25836" PostHistoryTypeId="3" PostId="9424" RevisionGUID="146b598e-a7f0-4039-aa64-a3463fcfb6d8" CreationDate="2019-12-16T20:50:57.737" UserId="11605" Text="|transformations|model|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25843" PostHistoryTypeId="2" PostId="9426" RevisionGUID="ef793c51-f865-45d8-8cc1-da74803c6d77" CreationDate="2019-12-17T06:22:20.217" UserId="11609" Text="I am attempting to implement chunks/octrees to speed up my render times. However, sometimes the walls show horizontal or vertical lines (rays hitting the inside of voxels?) or some blocks disappear altogether, although sometimes everything renders fine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```    for(int x = a; x &lt; RESX; x += 2) {    &#xD;&#xA;      &#xD;&#xA;      float cameraX = x/(float)HALFRESX -1;// -1 to 1&#xD;&#xA;      struct Point3D rayd;&#xD;&#xA;      rayd.x = dir.x + plane.x * cameraX;&#xD;&#xA;      rayd.y = dir.y + plane.y * cameraX;&#xD;&#xA;&#xD;&#xA;      struct Point3D delta;&#xD;&#xA;      delta.x = fabsf(1/rayd.x);&#xD;&#xA;      delta.y = fabsf(1/rayd.y);&#xD;&#xA;&#xD;&#xA;      int zy = -HALFRESY;&#xD;&#xA;&#xD;&#xA;      struct pos map;&#xD;&#xA;      map.x = (char)pos.x;&#xD;&#xA;      map.y = (char)pos.y;&#xD;&#xA;&#xD;&#xA;      float sdistX;&#xD;&#xA;      float sdistY;&#xD;&#xA;      struct pos s;&#xD;&#xA;      struct pos step;&#xD;&#xA;      struct Point3D sdist;&#xD;&#xA;      if(rayd.x &lt; 0) {&#xD;&#xA;        step.x = -1;&#xD;&#xA;        s.x = 1;&#xD;&#xA;        sdistX = (pos.x - map.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.x = 1;&#xD;&#xA;        s.x = 0;&#xD;&#xA;        sdistX = (map.x + 1 - pos.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      if(rayd.y &lt; 0) {&#xD;&#xA;        step.y = -1;&#xD;&#xA;        s.y = 1;&#xD;&#xA;        sdistY = (pos.y - map.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.y = 1;&#xD;&#xA;        s.y = 0;&#xD;&#xA;        sdistY = (map.y + 1 - pos.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      for(int y = 0; y &lt; RESY; y += 1) { &#xD;&#xA;&#xD;&#xA;        zy++;&#xD;&#xA;        float cameraY = y/(float)HALFRESY - 1;&#xD;&#xA;        rayd.z = dir.z + plane.z * cameraY;&#xD;&#xA;        delta.z = fabsf(1/rayd.z);&#xD;&#xA; &#xD;&#xA;        map.x = (char)pos.x;&#xD;&#xA;        map.y = (char)pos.y;&#xD;&#xA;        map.z = (char)pos.z;&#xD;&#xA;        sdist.x = sdistX;&#xD;&#xA;        sdist.y = sdistY; &#xD;&#xA;&#xD;&#xA;        if(rayd.z &lt; 0) {&#xD;&#xA;          step.z = -1;&#xD;&#xA;          s.z = 1;&#xD;&#xA;          sdist.z = (pos.z - map.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.z = 1;&#xD;&#xA;          s.z = 0;&#xD;&#xA;          sdist.z = (map.z + 1 - pos.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;#ifdef USE_OCTREE&#xD;&#xA;&#xD;&#xA;        if(sdist.y &lt; sdist.x ) { //prevent rendering artifacts when inside octree&#xD;&#xA;          if(sdist.y &lt; sdist.z) {&#xD;&#xA;            sdist.y += delta.y;&#xD;&#xA;            map.y += step.y;&#xD;&#xA;          }&#xD;&#xA;          else { &#xD;&#xA;            sdist.z += delta.z;&#xD;&#xA;            map.z += step.z;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          if(sdist.x &lt; sdist.z) {&#xD;&#xA;            sdist.x += delta.x;&#xD;&#xA;            map.x += step.x;&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            sdist.z += delta.z;&#xD;&#xA;            map.z += step.z; &#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if(sdist.y &lt; sdist.x ) {&#xD;&#xA;          if(sdist.y &lt; sdist.z) {&#xD;&#xA;            sdist.y += delta.y;&#xD;&#xA;            map.y += step.y;&#xD;&#xA;          }&#xD;&#xA;          else { &#xD;&#xA;            sdist.z += delta.z;&#xD;&#xA;            map.z += step.z;&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        else { &#xD;&#xA;          if(sdist.x &lt; sdist.z) {&#xD;&#xA;            sdist.x += delta.x;&#xD;&#xA;            map.x += step.x;&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            sdist.z += delta.z;&#xD;&#xA;            map.z += step.z; &#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        while( !octrA[map.x/2][map.y/2][map.z/2]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y*2;&#xD;&#xA;              map.y += step.y*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x*2;&#xD;&#xA;              map.x += step.x*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;#endif&#xD;&#xA;        char side; //either 0 (NS), or 1 (EW), or 2(UD)&#xD;&#xA;        while( !MAP[map.x][map.y][map.z]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y;&#xD;&#xA;              map.y += step.y;&#xD;&#xA;              side = 1; // y&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z;&#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x;&#xD;&#xA;              map.x += step.x;&#xD;&#xA;              side = 0; &#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z; &#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25844" PostHistoryTypeId="1" PostId="9426" RevisionGUID="ef793c51-f865-45d8-8cc1-da74803c6d77" CreationDate="2019-12-17T06:22:20.217" UserId="11609" Text="How can I raycast with chunks?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25845" PostHistoryTypeId="3" PostId="9426" RevisionGUID="ef793c51-f865-45d8-8cc1-da74803c6d77" CreationDate="2019-12-17T06:22:20.217" UserId="11609" Text="|raytracing|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25846" PostHistoryTypeId="5" PostId="9426" RevisionGUID="ea8a377d-c09d-4bf4-a386-9beea4796112" CreationDate="2019-12-17T10:22:09.430" UserId="11609" Comment="deleted 1020 characters in body" Text="I am attempting to implement chunks/octrees to speed up my render times. However, sometimes the walls show horizontal or vertical lines (rays hitting the inside of voxels?) or some blocks disappear altogether, although sometimes everything renders fine.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```    for(int x = a; x &lt; RESX; x += 2) {    &#xD;&#xA;      &#xD;&#xA;      float cameraX = x/(float)HALFRESX -1;// -1 to 1&#xD;&#xA;      struct Point3D rayd;&#xD;&#xA;      rayd.x = dir.x + plane.x * cameraX;&#xD;&#xA;      rayd.y = dir.y + plane.y * cameraX;&#xD;&#xA;&#xD;&#xA;      struct Point3D delta;&#xD;&#xA;      delta.x = fabsf(1/rayd.x);&#xD;&#xA;      delta.y = fabsf(1/rayd.y);&#xD;&#xA;&#xD;&#xA;      int zy = -HALFRESY;&#xD;&#xA;&#xD;&#xA;      struct pos map;&#xD;&#xA;      map.x = (char)pos.x;&#xD;&#xA;      map.y = (char)pos.y;&#xD;&#xA;&#xD;&#xA;      float sdistX;&#xD;&#xA;      float sdistY;&#xD;&#xA;      struct pos s;&#xD;&#xA;      struct pos step;&#xD;&#xA;      struct Point3D sdist;&#xD;&#xA;      if(rayd.x &lt; 0) {&#xD;&#xA;        step.x = -1;&#xD;&#xA;        s.x = 1;&#xD;&#xA;        sdistX = (pos.x - map.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.x = 1;&#xD;&#xA;        s.x = 0;&#xD;&#xA;        sdistX = (map.x + 1 - pos.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      if(rayd.y &lt; 0) {&#xD;&#xA;        step.y = -1;&#xD;&#xA;        s.y = 1;&#xD;&#xA;        sdistY = (pos.y - map.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.y = 1;&#xD;&#xA;        s.y = 0;&#xD;&#xA;        sdistY = (map.y + 1 - pos.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      for(int y = 0; y &lt; RESY; y += 1) { &#xD;&#xA;&#xD;&#xA;        zy++;&#xD;&#xA;        float cameraY = y/(float)HALFRESY - 1;&#xD;&#xA;        rayd.z = dir.z + plane.z * cameraY;&#xD;&#xA;        delta.z = fabsf(1/rayd.z);&#xD;&#xA; &#xD;&#xA;        map.x = (char)pos.x;&#xD;&#xA;        map.y = (char)pos.y;&#xD;&#xA;        map.z = (char)pos.z;&#xD;&#xA;        sdist.x = sdistX;&#xD;&#xA;        sdist.y = sdistY; &#xD;&#xA;&#xD;&#xA;        if(rayd.z &lt; 0) {&#xD;&#xA;          step.z = -1;&#xD;&#xA;          s.z = 1;&#xD;&#xA;          sdist.z = (pos.z - map.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.z = 1;&#xD;&#xA;          s.z = 0;&#xD;&#xA;          sdist.z = (map.z + 1 - pos.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;#ifdef USE_OCTREE&#xD;&#xA;&#xD;&#xA;        while( !octrA[map.x/2][map.y/2][map.z/2]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y*2;&#xD;&#xA;              map.y += step.y*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x*2;&#xD;&#xA;              map.x += step.x*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;#endif&#xD;&#xA;        char side; //either 0 (NS), or 1 (EW), or 2(UD)&#xD;&#xA;        while( !MAP[map.x][map.y][map.z]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y;&#xD;&#xA;              map.y += step.y;&#xD;&#xA;              side = 1; // y&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z;&#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x;&#xD;&#xA;              map.x += step.x;&#xD;&#xA;              side = 0; &#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z; &#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25847" PostHistoryTypeId="50" PostId="8587" RevisionGUID="27071e06-8d3c-465e-bc7e-d9b79856e128" CreationDate="2019-12-17T11:01:10.120" UserId="-1" />
  <row Id="25848" PostHistoryTypeId="2" PostId="9427" RevisionGUID="5070cd4a-4744-462d-a9b5-6b463e379d66" CreationDate="2019-12-17T13:26:14.657" UserId="10615" Text="Have you confirmed that objects that clip a chunk border are stored in both chunks?&#xD;&#xA;&#xD;&#xA;Have you confirmed that octrA[map.x/2][map.y/2][map.z/2] can't point to anything weird?&#xD;&#xA;&#xD;&#xA;In fact, what even is octrA? I assume that it's the array storing the chunks but I can't know for sure because I couldn't find it anywhere else in your code.&#xD;&#xA;&#xD;&#xA;Other than that I'm having a bit of a hard time interpreting the problem and your code. Could you add some pictures and comments to your code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25849" PostHistoryTypeId="2" PostId="9428" RevisionGUID="fe534a0c-bbd3-4538-aa61-6bb3f2cee8ae" CreationDate="2019-12-17T13:36:55.263" UserId="8962" Text="I'm trying to make the path tracer shown in the Ray Tracing in One Weekend series multithreaded.&#xD;&#xA;&#xD;&#xA;Here's the starting of my main function:&#xD;&#xA;&#xD;&#xA;    //scene setup&#xD;&#xA;    	hitable* world = cornell_box();&#xD;&#xA;    	auto start = std::chrono::high_resolution_clock::now();&#xD;&#xA;    	light_hitable_list = hitable_list(lightsVector);&#xD;&#xA;    	string filePath = &quot;img.png&quot;;&#xD;&#xA;    &#xD;&#xA;    	Image image(nx, ny);&#xD;&#xA;    	TilePool tilePool(nx, ny, 50);&#xD;&#xA;    &#xD;&#xA;    	//maxThreads = std::thread::hardware_concurrency();&#xD;&#xA;    	maxThreads = 1;&#xD;&#xA;    	std::vector&lt;std::thread&gt; renderThreads;&#xD;&#xA;    	renderThreads.resize(maxThreads);&#xD;&#xA;    &#xD;&#xA;    	//RenderSettings renderSettings{world, &amp;image, &amp;tilePool, ns, BLACK_SKY, false, &quot;img.png&quot;};&#xD;&#xA;    &#xD;&#xA;    	for (unsigned int i = 0; i &lt; maxThreads; i++)&#xD;&#xA;    	{&#xD;&#xA;    		renderThreads[i] = std::thread(&amp;renderScene, world, &amp;image, &amp;tilePool);&#xD;&#xA;    	}&#xD;&#xA;    	for (unsigned int i = 0; i &lt; maxThreads; i++)&#xD;&#xA;    	{&#xD;&#xA;    		if (renderThreads[i].joinable())&#xD;&#xA;    		{&#xD;&#xA;    			renderThreads[i].join();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;And here's the renderScene function:&#xD;&#xA;&#xD;&#xA;    void renderScene(hitable* world, Image* image, TilePool* tilePool) {&#xD;&#xA;    &#xD;&#xA;    	while (tilePool-&gt;getPoolSize() &gt; 0)&#xD;&#xA;    	{	&#xD;&#xA;    		Tile tile = tilePool-&gt;getNextTile();&#xD;&#xA;    &#xD;&#xA;    		for (int j = tile.yMax - 1; j &gt;= tile.yMin; j--) {&#xD;&#xA;    &#xD;&#xA;    			for (int i = tile.xMin; i &lt; tile.xMax; i++) {&#xD;&#xA;    				vec3 col(0, 0, 0);&#xD;&#xA;    				for (int s = 0; s &lt; ns; s++) {&#xD;&#xA;    					float u = (float(i) + random_number()) / float(nx);&#xD;&#xA;    					float v = (float(j) + random_number()) / float(ny);&#xD;&#xA;    &#xD;&#xA;    					ray r = cam.get_ray(u, v);&#xD;&#xA;    					vec3 p = r.point_at_parameter(2.0);&#xD;&#xA;    					col += de_nan(color(r, world, &amp;light_hitable_list, 0));&#xD;&#xA;    				}&#xD;&#xA;    				col /= float(ns);&#xD;&#xA;    				col = vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2]));&#xD;&#xA;    &#xD;&#xA;    				(*image)[3 * i + 3 * nx * (ny - 1 - j)] = col[0];&#xD;&#xA;    				(*image)[3 * i + 3 * nx * (ny - 1 - j) + 1] = col[1];&#xD;&#xA;    				(*image)[3 * i + 3 * nx * (ny - 1 - j) + 2] = col[2];&#xD;&#xA;    &#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I run the code above as it is I get this error:&#xD;&#xA;&#xD;&#xA;&gt; Exception thrown at 0x00007FF70F601F2E in raytracer.exe: 0xC0000005:&#xD;&#xA;&gt; Access violation reading location 0x000001C200000190.&#xD;&#xA;&#xD;&#xA;here: https://github.com/KarthikRIyer/RayTracer/blob/ec51999070218839e6aef2a65868e57fc6bb728d/src/objects/hitables/hitable_list.h#L29&#xD;&#xA;&#xD;&#xA;And instead of using just 1 thread if I use `maxThreads = std::thread::hardware_concurrency();`&#xD;&#xA;&#xD;&#xA;I get this error:&#xD;&#xA;&#xD;&#xA;&gt; Exception thrown at 0x00007FF79DE01FCE in raytracer.exe: 0xC0000005:&#xD;&#xA;&gt; Access violation reading location 0x0000015E0000012C.&#xD;&#xA;&#xD;&#xA;here: https://github.com/KarthikRIyer/RayTracer/blob/ec51999070218839e6aef2a65868e57fc6bb728d/src/objects/hitables/hitable_list.h#L38&#xD;&#xA;&#xD;&#xA;I'm completely new to multithreaded programming. But it doesn't feel like the error might be due to multithreading because I get such an error even while using `maxThreads = 1`. &#xD;&#xA;&#xD;&#xA;Instead of the cornell box scene if I use the `model_scene` defined here: https://github.com/KarthikRIyer/RayTracer/blob/ec51999070218839e6aef2a65868e57fc6bb728d/src/Source.cpp#L135 sometimes I get the same error as above and sometimes it randomly starts working even with more than one threads.&#xD;&#xA;&#xD;&#xA;Can someone please shed light as to why this might be occuring and what points should I keep in mind while writing a multithreaded path tracer?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25850" PostHistoryTypeId="1" PostId="9428" RevisionGUID="fe534a0c-bbd3-4538-aa61-6bb3f2cee8ae" CreationDate="2019-12-17T13:36:55.263" UserId="8962" Text="Trouble making path tracer multithreaded, read access violation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25851" PostHistoryTypeId="3" PostId="9428" RevisionGUID="fe534a0c-bbd3-4538-aa61-6bb3f2cee8ae" CreationDate="2019-12-17T13:36:55.263" UserId="8962" Text="|pathtracing|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25852" PostHistoryTypeId="5" PostId="9428" RevisionGUID="4ffc81f5-b9b0-4b22-96b7-ac880a041135" CreationDate="2019-12-17T13:45:44.547" UserId="8962" Comment="added 138 characters in body" Text="I'm trying to make the path tracer shown in the Ray Tracing in One Weekend series multithreaded.&#xD;&#xA;&#xD;&#xA;Here's the starting of my main function:&#xD;&#xA;&#xD;&#xA;    //scene setup&#xD;&#xA;    	hitable* world = cornell_box();&#xD;&#xA;    	auto start = std::chrono::high_resolution_clock::now();&#xD;&#xA;    	light_hitable_list = hitable_list(lightsVector);&#xD;&#xA;    	string filePath = &quot;img.png&quot;;&#xD;&#xA;    &#xD;&#xA;    	Image image(nx, ny);&#xD;&#xA;    	TilePool tilePool(nx, ny, 50);&#xD;&#xA;    &#xD;&#xA;    	//maxThreads = std::thread::hardware_concurrency();&#xD;&#xA;    	maxThreads = 1;&#xD;&#xA;    	std::vector&lt;std::thread&gt; renderThreads;&#xD;&#xA;    	renderThreads.resize(maxThreads);&#xD;&#xA;    &#xD;&#xA;    	//RenderSettings renderSettings{world, &amp;image, &amp;tilePool, ns, BLACK_SKY, false, &quot;img.png&quot;};&#xD;&#xA;    &#xD;&#xA;    	for (unsigned int i = 0; i &lt; maxThreads; i++)&#xD;&#xA;    	{&#xD;&#xA;    		renderThreads[i] = std::thread(&amp;renderScene, world, &amp;image, &amp;tilePool);&#xD;&#xA;    	}&#xD;&#xA;    	for (unsigned int i = 0; i &lt; maxThreads; i++)&#xD;&#xA;    	{&#xD;&#xA;    		if (renderThreads[i].joinable())&#xD;&#xA;    		{&#xD;&#xA;    			renderThreads[i].join();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;And here's the renderScene function:&#xD;&#xA;&#xD;&#xA;    void renderScene(hitable* world, Image* image, TilePool* tilePool) {&#xD;&#xA;    &#xD;&#xA;    	while (tilePool-&gt;getPoolSize() &gt; 0)&#xD;&#xA;    	{	&#xD;&#xA;    		Tile tile = tilePool-&gt;getNextTile();&#xD;&#xA;    &#xD;&#xA;    		for (int j = tile.yMax - 1; j &gt;= tile.yMin; j--) {&#xD;&#xA;    &#xD;&#xA;    			for (int i = tile.xMin; i &lt; tile.xMax; i++) {&#xD;&#xA;    				vec3 col(0, 0, 0);&#xD;&#xA;    				for (int s = 0; s &lt; ns; s++) {&#xD;&#xA;    					float u = (float(i) + random_number()) / float(nx);&#xD;&#xA;    					float v = (float(j) + random_number()) / float(ny);&#xD;&#xA;    &#xD;&#xA;    					ray r = cam.get_ray(u, v);&#xD;&#xA;    					vec3 p = r.point_at_parameter(2.0);&#xD;&#xA;    					col += de_nan(color(r, world, &amp;light_hitable_list, 0));&#xD;&#xA;    				}&#xD;&#xA;    				col /= float(ns);&#xD;&#xA;    				col = vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2]));&#xD;&#xA;    &#xD;&#xA;    				(*image)[3 * i + 3 * nx * (ny - 1 - j)] = col[0];&#xD;&#xA;    				(*image)[3 * i + 3 * nx * (ny - 1 - j) + 1] = col[1];&#xD;&#xA;    				(*image)[3 * i + 3 * nx * (ny - 1 - j) + 2] = col[2];&#xD;&#xA;    &#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I run the code above as it is I get this error:&#xD;&#xA;&#xD;&#xA;&gt; Exception thrown at 0x00007FF70F601F2E in raytracer.exe: 0xC0000005:&#xD;&#xA;&gt; Access violation reading location 0x000001C200000190.&#xD;&#xA;&#xD;&#xA;here: https://github.com/KarthikRIyer/RayTracer/blob/ec51999070218839e6aef2a65868e57fc6bb728d/src/objects/hitables/hitable_list.h#L29&#xD;&#xA;&#xD;&#xA;And instead of using just 1 thread if I use `maxThreads = std::thread::hardware_concurrency();`&#xD;&#xA;&#xD;&#xA;I get this error:&#xD;&#xA;&#xD;&#xA;&gt; Exception thrown at 0x00007FF79DE01FCE in raytracer.exe: 0xC0000005:&#xD;&#xA;&gt; Access violation reading location 0x0000015E0000012C.&#xD;&#xA;&#xD;&#xA;here: https://github.com/KarthikRIyer/RayTracer/blob/ec51999070218839e6aef2a65868e57fc6bb728d/src/objects/hitables/hitable_list.h#L38&#xD;&#xA;&#xD;&#xA;These errors are not for the parameters passed into the function. I have checked if they are NULL. It seems to be for the function call.&#xD;&#xA;I'm completely new to multithreaded programming. But it doesn't feel like the error might be due to multithreading because I get such an error even while using `maxThreads = 1`. &#xD;&#xA;&#xD;&#xA;Instead of the cornell box scene if I use the `model_scene` defined here: https://github.com/KarthikRIyer/RayTracer/blob/ec51999070218839e6aef2a65868e57fc6bb728d/src/Source.cpp#L135 sometimes I get the same error as above and sometimes it randomly starts working even with more than one threads.&#xD;&#xA;&#xD;&#xA;Can someone please shed light as to why this might be occuring and what points should I keep in mind while writing a multithreaded path tracer?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25853" PostHistoryTypeId="5" PostId="9426" RevisionGUID="88f5c267-87f0-4ef3-aeea-cc217771e7d7" CreationDate="2019-12-17T15:11:44.043" UserId="11609" Comment="added 87 characters in body" Text="I am attempting to implement chunks/octrees to speed up my render times. However, sometimes the walls show horizontal or vertical lines (rays hitting the inside of voxels?) or some blocks disappear altogether, although sometimes everything renders fine.&#xD;&#xA;&#xD;&#xA;Edit: Yes, the chunks are stored fine. OctrA stands for OctreeA,  which is the chunk.&#xD;&#xA;&#xD;&#xA;```    for(int x = a; x &lt; RESX; x += 2) {    &#xD;&#xA;      &#xD;&#xA;      float cameraX = x/(float)HALFRESX -1;// -1 to 1&#xD;&#xA;      struct Point3D rayd;&#xD;&#xA;      rayd.x = dir.x + plane.x * cameraX;&#xD;&#xA;      rayd.y = dir.y + plane.y * cameraX;&#xD;&#xA;&#xD;&#xA;      struct Point3D delta;&#xD;&#xA;      delta.x = fabsf(1/rayd.x);&#xD;&#xA;      delta.y = fabsf(1/rayd.y);&#xD;&#xA;&#xD;&#xA;      int zy = -HALFRESY;&#xD;&#xA;&#xD;&#xA;      struct pos map;&#xD;&#xA;      map.x = (char)pos.x;&#xD;&#xA;      map.y = (char)pos.y;&#xD;&#xA;&#xD;&#xA;      float sdistX;&#xD;&#xA;      float sdistY;&#xD;&#xA;      struct pos s;&#xD;&#xA;      struct pos step;&#xD;&#xA;      struct Point3D sdist;&#xD;&#xA;      if(rayd.x &lt; 0) {&#xD;&#xA;        step.x = -1;&#xD;&#xA;        s.x = 1;&#xD;&#xA;        sdistX = (pos.x - map.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.x = 1;&#xD;&#xA;        s.x = 0;&#xD;&#xA;        sdistX = (map.x + 1 - pos.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      if(rayd.y &lt; 0) {&#xD;&#xA;        step.y = -1;&#xD;&#xA;        s.y = 1;&#xD;&#xA;        sdistY = (pos.y - map.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.y = 1;&#xD;&#xA;        s.y = 0;&#xD;&#xA;        sdistY = (map.y + 1 - pos.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      for(int y = 0; y &lt; RESY; y += 1) { &#xD;&#xA;&#xD;&#xA;        zy++;&#xD;&#xA;        float cameraY = y/(float)HALFRESY - 1;&#xD;&#xA;        rayd.z = dir.z + plane.z * cameraY;&#xD;&#xA;        delta.z = fabsf(1/rayd.z);&#xD;&#xA; &#xD;&#xA;        map.x = (char)pos.x;&#xD;&#xA;        map.y = (char)pos.y;&#xD;&#xA;        map.z = (char)pos.z;&#xD;&#xA;        sdist.x = sdistX;&#xD;&#xA;        sdist.y = sdistY; &#xD;&#xA;&#xD;&#xA;        if(rayd.z &lt; 0) {&#xD;&#xA;          step.z = -1;&#xD;&#xA;          s.z = 1;&#xD;&#xA;          sdist.z = (pos.z - map.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.z = 1;&#xD;&#xA;          s.z = 0;&#xD;&#xA;          sdist.z = (map.z + 1 - pos.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;#ifdef USE_OCTREE&#xD;&#xA;&#xD;&#xA;        while( !octrA[map.x/2][map.y/2][map.z/2]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y*2;&#xD;&#xA;              map.y += step.y*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x*2;&#xD;&#xA;              map.x += step.x*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;#endif&#xD;&#xA;        char side; //either 0 (NS), or 1 (EW), or 2(UD)&#xD;&#xA;        while( !MAP[map.x][map.y][map.z]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y;&#xD;&#xA;              map.y += step.y;&#xD;&#xA;              side = 1; // y&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z;&#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x;&#xD;&#xA;              map.x += step.x;&#xD;&#xA;              side = 0; &#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z; &#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25855" PostHistoryTypeId="5" PostId="9426" RevisionGUID="aa392454-e1d1-4c0d-bed5-4a90a2bc465b" CreationDate="2019-12-18T09:52:44.763" UserId="11609" Comment="added 708 characters in body" Text="I am attempting to implement chunks/octrees to speed up my render times. However, sometimes the walls show horizontal or vertical lines (rays hitting the inside of voxels?) or some blocks disappear altogether, although sometimes everything renders fine.&#xD;&#xA;&#xD;&#xA;Edit: Yes, the chunks are stored fine. OctrA stands for OctreeA,  which is the chunk.&#xD;&#xA;Edit: I reversed the ray for two steps after hitting a chunk. Although the glitches have gotten better, there is still the same problem.&#xD;&#xA;&#xD;&#xA;```    for(int x = a; x &lt; RESX; x += 2) {    &#xD;&#xA;      &#xD;&#xA;      float cameraX = x/(float)HALFRESX -1;// -1 to 1&#xD;&#xA;      struct Point3D rayd;&#xD;&#xA;      rayd.x = dir.x + plane.x * cameraX;&#xD;&#xA;      rayd.y = dir.y + plane.y * cameraX;&#xD;&#xA;&#xD;&#xA;      struct Point3D delta;&#xD;&#xA;      delta.x = fabsf(1/rayd.x);&#xD;&#xA;      delta.y = fabsf(1/rayd.y);&#xD;&#xA;&#xD;&#xA;      int zy = -HALFRESY;&#xD;&#xA;&#xD;&#xA;      struct pos map;&#xD;&#xA;      map.x = (char)pos.x;&#xD;&#xA;      map.y = (char)pos.y;&#xD;&#xA;&#xD;&#xA;      float sdistX;&#xD;&#xA;      float sdistY;&#xD;&#xA;      struct pos s;&#xD;&#xA;      struct pos step;&#xD;&#xA;      struct Point3D sdist;&#xD;&#xA;      if(rayd.x &lt; 0) {&#xD;&#xA;        step.x = -1;&#xD;&#xA;        s.x = 1;&#xD;&#xA;        sdistX = (pos.x - map.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.x = 1;&#xD;&#xA;        s.x = 0;&#xD;&#xA;        sdistX = (map.x + 1 - pos.x) * delta.x; &#xD;&#xA;      }&#xD;&#xA;      if(rayd.y &lt; 0) {&#xD;&#xA;        step.y = -1;&#xD;&#xA;        s.y = 1;&#xD;&#xA;        sdistY = (pos.y - map.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.y = 1;&#xD;&#xA;        s.y = 0;&#xD;&#xA;        sdistY = (map.y + 1 - pos.y) * delta.y; &#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      for(int y = 0; y &lt; RESY; y += 1) { &#xD;&#xA;&#xD;&#xA;        zy++;&#xD;&#xA;        float cameraY = y/(float)HALFRESY - 1;&#xD;&#xA;        rayd.z = dir.z + plane.z * cameraY;&#xD;&#xA;        delta.z = fabsf(1/rayd.z);&#xD;&#xA; &#xD;&#xA;        map.x = (char)pos.x;&#xD;&#xA;        map.y = (char)pos.y;&#xD;&#xA;        map.z = (char)pos.z;&#xD;&#xA;        sdist.x = sdistX;&#xD;&#xA;        sdist.y = sdistY; &#xD;&#xA;&#xD;&#xA;        if(rayd.z &lt; 0) {&#xD;&#xA;          step.z = -1;&#xD;&#xA;          s.z = 1;&#xD;&#xA;          sdist.z = (pos.z - map.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.z = 1;&#xD;&#xA;          s.z = 0;&#xD;&#xA;          sdist.z = (map.z + 1 - pos.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;#ifdef USE_OCTREE&#xD;&#xA;&#xD;&#xA;        while( !octrA[map.x/2][map.y/2][map.z/2]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y*2;&#xD;&#xA;              map.y += step.y*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x*2;&#xD;&#xA;              map.x += step.x*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z*2;&#xD;&#xA;              map.z += step.z*2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        if(octr) {&#xD;&#xA;          if(sdist.y &gt; sdist.x ) {&#xD;&#xA;            if(sdist.y &gt; sdist.z) {&#xD;&#xA;              sdist.y -= delta.y*2;&#xD;&#xA;              map.y -= step.y*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z -= delta.z*2;&#xD;&#xA;              map.z -= step.z*2;&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &gt; sdist.z) {&#xD;&#xA;              sdist.x -= delta.x*2;&#xD;&#xA;              map.x -= step.x*2;&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z -= delta.z*2;&#xD;&#xA;              map.z -= step.z*2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;#endif&#xD;&#xA;        char side; //either 0 (NS), or 1 (EW), or 2(UD)&#xD;&#xA;        while( !MAP[map.x][map.y][map.z]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y;&#xD;&#xA;              map.y += step.y;&#xD;&#xA;              side = 1; // y&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z;&#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x;&#xD;&#xA;              map.x += step.x;&#xD;&#xA;              side = 0; &#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z; &#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="25856" PostHistoryTypeId="2" PostId="9429" RevisionGUID="e307758c-426c-4df6-bbdf-80a1dd9ddb80" CreationDate="2019-12-18T20:41:28.847" UserId="8962" Text="I found out what was wrong. It wasn't related to multithreading at all.&#xD;&#xA;I was taking in a vector in a constructor `hitable_list(std::vector&lt;hitable*&gt; listVector)` and using a pointer to the first element of the vector elsewhere. So as soon as the vector went out of scope the pointer became invalid.&#xD;&#xA;&#xD;&#xA;To solve this issue I just removed this constructor and whenever I need to pass in a vector I make sure that the vector stays in scope always and directly pass in the pointer to the first element of the vector, and it's size." ContentLicense="CC BY-SA 4.0" />
  <row Id="25857" PostHistoryTypeId="2" PostId="9430" RevisionGUID="0aa71013-d216-4852-a235-277edb679e97" CreationDate="2019-12-19T15:42:55.813" UserId="5066" Text="So I have been reading this wonderful book on ray tracing by Kevin Suffern, Ray tracing from Ground Up. I am reading this book after finishing Peter Shirley's first two book on ray tracing &amp; implementing multi-threaded ray tracer, adding features like Intel's denoiser, assimp integration etc. &#xD;&#xA;&#xD;&#xA;What struck me was before I read the third book, it would be good idea to read more on sampling. Which is why am skimming through this current book. At this moment, am stuck on a topic which explains how sample point in unit square is mapped onto unit radius disk. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am stuck at the part where book mentions how equations are mapped. Radius part is clear to me, however, am not very clear about the angle (phi) part. Is there any derivation as to how this was deduced? Or is it done to avoid atan() calculation and is a neat approximation of it? After putting in test values I have understood how values get converted, however, am very keen to understand how this formulas for Phi was deduced based on different quarters, unless it's very obvious and I have overlooked it :(  &#xD;&#xA;&#xD;&#xA;Regards. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lqjec.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25858" PostHistoryTypeId="1" PostId="9430" RevisionGUID="0aa71013-d216-4852-a235-277edb679e97" CreationDate="2019-12-19T15:42:55.813" UserId="5066" Text="Mapping sample to a disk" ContentLicense="CC BY-SA 4.0" />
  <row Id="25859" PostHistoryTypeId="3" PostId="9430" RevisionGUID="0aa71013-d216-4852-a235-277edb679e97" CreationDate="2019-12-19T15:42:55.813" UserId="5066" Text="|raytracing|mathematics|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25860" PostHistoryTypeId="5" PostId="9430" RevisionGUID="8fb20fa0-ee09-4ac2-882a-d61c03d47ccd" CreationDate="2019-12-19T17:17:19.683" UserId="5066" Comment="added 271 characters in body" Text="So I have been reading this wonderful book on ray tracing by Kevin Suffern, Ray tracing from Ground Up. I am reading this book after finishing Peter Shirley's first two book on ray tracing &amp; implementing multi-threaded ray tracer, adding features like Intel's denoiser, assimp integration etc. &#xD;&#xA;&#xD;&#xA;What struck me was before I read the third book, it would be good idea to read more on sampling. Which is why am skimming through this current book. At this moment, am stuck on a topic which explains how sample point in unit square is mapped onto unit radius disk. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am stuck at the part where book mentions how equations are mapped. Radius part is clear to me, however, am not very clear about the angle (phi) part. Is there any derivation as to how this was deduced? Or is it done to avoid atan() calculation and is a neat approximation of it? After putting in test values I have understood how values get converted, however, am very keen to understand how this formulas for Phi was deduced based on different quarters, unless it's very obvious and I have overlooked it :(  &#xD;&#xA;&#xD;&#xA;Regards. &#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;After more digging, i have understood that if i assume first quadrant value, then second, third &amp; fourth values can be deduced by rotating/adding (Pi/2) to angle phi &amp; switching axis due to quadrant change. However, first quadrant value is still not clear :|&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lqjec.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25861" PostHistoryTypeId="5" PostId="8397" RevisionGUID="1497d1a0-ca63-4e41-91f6-b1da44185e4c" CreationDate="2019-12-19T18:09:04.513" UserId="9853" Comment="added 4 characters in body" Text="My 2 cents from writting the Chipmunk2D physics engine is that spatial hashing is great when you have a lot of objects that are all the same size. I had a demo 10 years ago that ran with 20k interacting particles on a Core 2 Duo in real time. The spatial hash worked great for that *if you tuned it*.&#xD;&#xA;&#xD;&#xA;I've since replaced the spatial hash with a binary AABB tree as the the default structure. It's far from perfect, but it was faster than the spatial hash in the average case *with no tuning*. It also was easier to add a temporal component to it so I could incrementally update a set of potential collisions. With all of that in place, the *only* test I had that ran faster with the spatial hash were the ones with thousands of particles and no static geometry.&#xD;&#xA;&#xD;&#xA;As for octrees... Meh, I never use them. Basic quad/octrees don't really fit real data as well as the plethora of other BVHs you can use. Basic AABB trees are nearly as simple, and *way* more effective." ContentLicense="CC BY-SA 4.0" />
  <row Id="25865" PostHistoryTypeId="2" PostId="9432" RevisionGUID="290c0ab0-c20d-4ba0-9dff-895b9173e64b" CreationDate="2019-12-20T01:53:06.793" UserId="11619" Text="[![Simplified Map Equations][1]][1]&#xD;&#xA;&#xD;&#xA;Check the last column in the table for the deciphered version of the existing Map Equations for easier comprehension. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CGpwF.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25870" PostHistoryTypeId="2" PostId="9434" RevisionGUID="0b7a3091-5b71-4b95-b21f-892047ea1571" CreationDate="2019-12-21T05:45:14.220" UserId="11623" Text="I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.&#xD;&#xA;&#xD;&#xA;So, this image:&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;instead of being deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Should rather be deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying [this gist][4] to no avail.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AKqdd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5eWvg.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Sh5og.jpg&#xD;&#xA;  [4]: https://gist.github.com/quiglemj/971f4cec1b128c58b4864c5200bfc579" ContentLicense="CC BY-SA 4.0" />
  <row Id="25871" PostHistoryTypeId="1" PostId="9434" RevisionGUID="0b7a3091-5b71-4b95-b21f-892047ea1571" CreationDate="2019-12-21T05:45:14.220" UserId="11623" Text="Shader or formula that distorts inward" ContentLicense="CC BY-SA 4.0" />
  <row Id="25872" PostHistoryTypeId="3" PostId="9434" RevisionGUID="0b7a3091-5b71-4b95-b21f-892047ea1571" CreationDate="2019-12-21T05:45:14.220" UserId="11623" Text="|shader|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25873" PostHistoryTypeId="50" PostId="9364" RevisionGUID="0c52812c-ede2-43eb-8f3e-b66119ad6050" CreationDate="2019-12-21T09:01:15.333" UserId="-1" />
  <row Id="25874" PostHistoryTypeId="2" PostId="9435" RevisionGUID="d5b996b8-d2e3-4242-9155-00308d61b770" CreationDate="2019-12-21T19:19:10.070" UserId="6145" Text="Your example images do make the desired effect very apparent, but the opposite of a barrel distortion is a pincushion distortion:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I found a [fisheye shader on ShaderToy](https://www.shadertoy.com/view/ll2GWV) which produces the following image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;By slightly modifying the shader code:&#xD;&#xA;&#xD;&#xA;    // This shader is based on cafe's fisheye shader:&#xD;&#xA;    // https://www.shadertoy.com/view/ll2GWV&#xD;&#xA;&#xD;&#xA;    vec3 checker(vec2 uv){&#xD;&#xA;        return vec3(abs(floor(mod(uv.x*10.,2.))-floor(mod(uv.y*10.,2.))));   &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;        vec2 uv = fragCoord.xy*2. / iResolution.xy-vec2(1.);&#xD;&#xA;        &#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        // To use in Godot, port this section:&#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        &#xD;&#xA;        // I picked these somewhat arbitrarily&#xD;&#xA;        const float BARREL = -1.0;&#xD;&#xA;        const float PINCUSHION = 0.1;&#xD;&#xA;        &#xD;&#xA;        float effect = PINCUSHION; // Set effect to either BARREL or PINCUSHION&#xD;&#xA;        float effect_scale = 1.0;  // Play with this to slightly vary the results&#xD;&#xA;        &#xD;&#xA;        /// Fisheye Distortion ///&#xD;&#xA;        float d=length(uv);&#xD;&#xA;        float z = sqrt(1.0 + d * d * effect);&#xD;&#xA;        float r = atan(d, z) / 3.14159;&#xD;&#xA;        r *= effect_scale;&#xD;&#xA;        float phi = atan(uv.y, uv.x);&#xD;&#xA;        &#xD;&#xA;        uv = vec2(r*cos(phi)+.5,r*sin(phi)+.5);&#xD;&#xA;        &#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        // end relevant logic&#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        &#xD;&#xA;        fragColor = vec4(checker(uv),1.);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;We can easily obtain [the opposite effect](https://www.shadertoy.com/view/wtt3z2):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If this is not the exact effect you're looking for, I recommend playing around with the code a bit yourself. Change some signs from + to -, add scale factors and explore the possibilities. You may even stumble across a more interesting effect than what were you looking for.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cD2a8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hTDCV.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cZAYV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25875" PostHistoryTypeId="5" PostId="9434" RevisionGUID="77f0b4c2-65c1-4408-9982-96387590856e" CreationDate="2019-12-21T21:25:23.687" UserId="11623" Comment="added 227 characters in body" Text="I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.&#xD;&#xA;&#xD;&#xA;So, this image:&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;instead of being deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Should rather be deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying [this gist][4] to no avail.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;h1&gt;EDIT:&lt;/h1&gt;&#xD;&#xA;Pincushion distortion has been suggested, but the lines bend in the opposite direction of what is desired.&#xD;&#xA;&#xD;&#xA;Example:&lt;br&gt;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AKqdd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5eWvg.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Sh5og.jpg&#xD;&#xA;  [4]: https://gist.github.com/quiglemj/971f4cec1b128c58b4864c5200bfc579&#xD;&#xA;  [5]: https://i.stack.imgur.com/xNbtB.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25876" PostHistoryTypeId="5" PostId="9434" RevisionGUID="ac2b221a-08a5-4279-bef2-528d19d3722f" CreationDate="2019-12-21T21:35:37.247" UserId="11623" Comment="added 158 characters in body" Text="I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.&#xD;&#xA;&#xD;&#xA;So, this image:&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;instead of being deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Should rather be deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying [this gist][4] to no avail.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;h1&gt;EDIT:&lt;/h1&gt;&#xD;&#xA;Pincushion distortion has been suggested, but the lines bend in the opposite direction of what is desired.&#xD;&#xA;&#xD;&#xA;Example:&lt;br&gt;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;My example looks a bit like a UV wrap, but this does not have to be the case. Ugly or imprecise distortion around the edges, for example, is perfectly ok. A barrel distortion technically achieves the desired affect, but it drastically pixelates the center, which is something I'm trying to avoid. So I was hoping the the edges could be crushed to center, instead of the center being stretched to the edges.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AKqdd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5eWvg.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Sh5og.jpg&#xD;&#xA;  [4]: https://gist.github.com/quiglemj/971f4cec1b128c58b4864c5200bfc579&#xD;&#xA;  [5]: https://i.stack.imgur.com/xNbtB.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25877" PostHistoryTypeId="5" PostId="9434" RevisionGUID="76840fe7-76df-415d-b20e-5b44664ce3a8" CreationDate="2019-12-21T21:44:15.903" UserId="11623" Comment="edited body" Text="I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.&#xD;&#xA;&#xD;&#xA;So, this image:&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;instead of being deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Should rather be deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying [this gist][4] to no avail.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;h1&gt;EDIT:&lt;/h1&gt;&#xD;&#xA;Pincushion distortion has been suggested, but the lines bend in the opposite direction of what is desired.&#xD;&#xA;&#xD;&#xA;Example:&lt;br&gt;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;A barrel distortion technically achieves the desired affect, but it drastically pixelates the center, which is something I'm trying to avoid. So I was hoping the the edges could be crushed to center, instead of the center being stretched to the edges. My example looks a bit like a UV wrap, but this does not have to be the case. Ugly or imprecise distortion around the edges, for example, is perfectly ok.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AKqdd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5eWvg.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Sh5og.jpg&#xD;&#xA;  [4]: https://gist.github.com/quiglemj/971f4cec1b128c58b4864c5200bfc579&#xD;&#xA;  [5]: https://i.stack.imgur.com/xNbtB.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25878" PostHistoryTypeId="5" PostId="9434" RevisionGUID="5f031381-7ee1-4853-ba01-01b689bd94d5" CreationDate="2019-12-21T22:01:42.157" UserId="11623" Comment="deleted 845 characters in body" Text="I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.&#xD;&#xA;&#xD;&#xA;So, this image:&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;instead of being deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Should rather be deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying [this gist][4] to no avail.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AKqdd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5eWvg.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Sh5og.jpg&#xD;&#xA;  [4]: https://gist.github.com/quiglemj/971f4cec1b128c58b4864c5200bfc579&#xD;&#xA;  [5]: https://i.stack.imgur.com/xNbtB.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25879" PostHistoryTypeId="5" PostId="9434" RevisionGUID="2a0034f1-1a96-4005-93b2-24f0bcc56787" CreationDate="2019-12-22T07:10:06.803" UserId="11623" Comment="added 124 characters in body" Text="I am looking for a shader (or at least the right terminology) for crushing an image. It should be something very similar to barrel distortion, but instead of the center crushing outward to the edges, I want to edges to crush inward to the center.&#xD;&#xA;&#xD;&#xA;So, this image:&lt;br&gt;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;instead of being deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Should rather be deformed like this:&lt;br&gt;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This will be used for a Godot project, but even regular shading language would be tremendously helpful. I tried modifying [this gist][4] to no avail.&#xD;&#xA;&#xD;&#xA;&lt;h1&gt;Edit&lt;/h1&gt;&#xD;&#xA;Here is the final result using the accepted answer's solution:&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AKqdd.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5eWvg.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Sh5og.jpg&#xD;&#xA;  [4]: https://gist.github.com/quiglemj/971f4cec1b128c58b4864c5200bfc579&#xD;&#xA;  [5]: https://i.stack.imgur.com/HRIq8.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="25880" PostHistoryTypeId="5" PostId="9435" RevisionGUID="1b3c1d26-1f9f-4551-83bb-4d8a3a022d6e" CreationDate="2019-12-23T00:33:39.583" UserId="6145" Comment="added 4 characters in body" Text="Your example images do not make the desired effect very apparent, but the opposite of a barrel distortion is a pincushion distortion:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I found a [fisheye shader on ShaderToy](https://www.shadertoy.com/view/ll2GWV) which produces the following image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;By slightly modifying the shader code:&#xD;&#xA;&#xD;&#xA;    // This shader is based on cafe's fisheye shader:&#xD;&#xA;    // https://www.shadertoy.com/view/ll2GWV&#xD;&#xA;&#xD;&#xA;    vec3 checker(vec2 uv){&#xD;&#xA;        return vec3(abs(floor(mod(uv.x*10.,2.))-floor(mod(uv.y*10.,2.))));   &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;        vec2 uv = fragCoord.xy*2. / iResolution.xy-vec2(1.);&#xD;&#xA;        &#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        // To use in Godot, port this section:&#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        &#xD;&#xA;        // I picked these somewhat arbitrarily&#xD;&#xA;        const float BARREL = -1.0;&#xD;&#xA;        const float PINCUSHION = 0.1;&#xD;&#xA;        &#xD;&#xA;        float effect = PINCUSHION; // Set effect to either BARREL or PINCUSHION&#xD;&#xA;        float effect_scale = 1.0;  // Play with this to slightly vary the results&#xD;&#xA;        &#xD;&#xA;        /// Fisheye Distortion ///&#xD;&#xA;        float d=length(uv);&#xD;&#xA;        float z = sqrt(1.0 + d * d * effect);&#xD;&#xA;        float r = atan(d, z) / 3.14159;&#xD;&#xA;        r *= effect_scale;&#xD;&#xA;        float phi = atan(uv.y, uv.x);&#xD;&#xA;        &#xD;&#xA;        uv = vec2(r*cos(phi)+.5,r*sin(phi)+.5);&#xD;&#xA;        &#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        // end relevant logic&#xD;&#xA;        //------------------------------------------------&#xD;&#xA;        &#xD;&#xA;        fragColor = vec4(checker(uv),1.);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;We can easily obtain [the opposite effect](https://www.shadertoy.com/view/wtt3z2):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;If this is not the exact effect you're looking for, I recommend playing around with the code a bit yourself. Change some signs from + to -, add scale factors and explore the possibilities. You may even stumble across a more interesting effect than what were you looking for.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cD2a8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hTDCV.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/cZAYV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25881" PostHistoryTypeId="2" PostId="9436" RevisionGUID="2e25ed7b-6bf8-431c-933c-75a4a925f1b3" CreationDate="2019-12-23T04:53:21.970" UserId="11605" Text="I know how to generate the walls of a cylinder with triangle strips and the caps with triangle fans, but since I am working inside a geometry shader, I can only output triangle strips, so I am kind of lost here.&#xD;&#xA;&#xD;&#xA;This here is my current code, which only generates the hull of the cylinder based on a line segment:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;&#xD;&#xA;        layout(lines) in;&#xD;&#xA;        layout(triangle_strip, max_vertices = 32) out;&#xD;&#xA;&#xD;&#xA;        uniform mat4 projection;&#xD;&#xA;        uniform mat4 view;&#xD;&#xA;        uniform mat4 model;&#xD;&#xA;&#xD;&#xA;        in Vertex &#xD;&#xA;        {&#xD;&#xA;            vec4 color;&#xD;&#xA;            float width;&#xD;&#xA;        } vertex[];&#xD;&#xA;&#xD;&#xA;        out vec4 vertex_color;&#xD;&#xA;        out vec3 normal_vector;&#xD;&#xA;&#xD;&#xA;        vec3 createPerp(vec3 p1, vec3 p2)&#xD;&#xA;        {&#xD;&#xA;            vec3 invec = normalize(p2 - p1);&#xD;&#xA;            vec3 ret = cross( invec, vec3(0.0, 0.0, 1.0) );&#xD;&#xA;            if ( length(ret) == 0.0 )&#xD;&#xA;            {&#xD;&#xA;                ret = cross(invec, vec3(0.0, 1.0, 0.0) );&#xD;&#xA;            }&#xD;&#xA;            return ret;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;            mat4 mvp = projection * view * model;&#xD;&#xA;&#xD;&#xA;            vec3 axis = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz;&#xD;&#xA;&#xD;&#xA;            vec3 perpx = normalize(createPerp(gl_in[1].gl_Position.xyz, gl_in[0].gl_Position.xyz));&#xD;&#xA;            vec3 perpy = cross(normalize(axis), perpx);&#xD;&#xA;&#xD;&#xA;            float r1 = vertex[0].width / 1000.0;&#xD;&#xA;            float r2 = vertex[0].width / 1000.0;&#xD;&#xA;&#xD;&#xA;            int segs = 16;&#xD;&#xA;            for(int i=0; i&lt;segs; i++) {&#xD;&#xA;                float a = i/float(segs-1) * 2.0 * 3.14159;&#xD;&#xA;                float ca = cos(a); float sa = sin(a);&#xD;&#xA;                vec3 normal = vec3( ca*perpx.x + sa*perpy.x,&#xD;&#xA;                                ca*perpx.y + sa*perpy.y,&#xD;&#xA;                                ca*perpx.z + sa*perpy.z );&#xD;&#xA;&#xD;&#xA;                &#xD;&#xA;&#xD;&#xA;                vec3 p1 = gl_in[0].gl_Position.xyz + r1*normal;&#xD;&#xA;                vec3 p2 = gl_in[1].gl_Position.xyz + r2*normal;&#xD;&#xA;                &#xD;&#xA;                gl_Position = mvp * vec4(p1, 1.0);&#xD;&#xA;                vertex_color = vertex[0].color;&#xD;&#xA;                normal_vector = normal;&#xD;&#xA;                EmitVertex();&#xD;&#xA;&#xD;&#xA;                gl_Position = mvp * vec4(p2, 1.0);&#xD;&#xA;                vertex_color = vertex[0].color;&#xD;&#xA;                normal_vector = normal;&#xD;&#xA;                EmitVertex();       &#xD;&#xA;            }&#xD;&#xA;            EndPrimitive();   &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Is there some simple way to integrate the generation of the endcaps here?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25882" PostHistoryTypeId="1" PostId="9436" RevisionGUID="2e25ed7b-6bf8-431c-933c-75a4a925f1b3" CreationDate="2019-12-23T04:53:21.970" UserId="11605" Text="Generating the end caps of a cylinder using triangle strips for use in a geometry shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="25883" PostHistoryTypeId="3" PostId="9436" RevisionGUID="2e25ed7b-6bf8-431c-933c-75a4a925f1b3" CreationDate="2019-12-23T04:53:21.970" UserId="11605" Text="|opengl|computational-geometry|mesh|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25884" PostHistoryTypeId="2" PostId="9437" RevisionGUID="6a073b84-92a8-4858-b93a-634abb1c9a57" CreationDate="2019-12-23T09:54:50.367" UserId="209" Text="If the end of your cylinder is convex, with vertices $V_0, V_1, V_2,...V_{N-1}$ then just replace your fan order (i.e. as above) with this strip $V_0, V_1, V_{N-1}, V_2, V_{N-2}, V_3...$, i.e. just zig-zag across the polygon.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;(There are 'arguably better' orderings but that is the simplest to describe)." ContentLicense="CC BY-SA 4.0" />
  <row Id="25885" PostHistoryTypeId="2" PostId="9438" RevisionGUID="592bb04a-f3e8-440d-9968-a4f496c426fa" CreationDate="2019-12-23T13:19:58.583" UserId="10928" Text="I wonder why all the well known algorithms of drawing for example circles (bresenham, mid-point, etc) all use integer arithmetics? For example, here is a simple circle drawn with bresenham algorithm:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this is what I get with a circle drawn using naive algorithm (with real numbers):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The bresenham's version just look terrible and feels laggy while the floating point version is much smoother. So why do we read everywhere that &quot;integer&quot; versions are preferred? The integer version is maybe faster but horrible when it comes to animating a moving shape. So the question is: should I use floating point version or bresenham's version in my little toy rasterizer?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N7Spm.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/nHCk1.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="25886" PostHistoryTypeId="1" PostId="9438" RevisionGUID="592bb04a-f3e8-440d-9968-a4f496c426fa" CreationDate="2019-12-23T13:19:58.583" UserId="10928" Text="What is the point of having integer-based draw routines in software rasterizer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25887" PostHistoryTypeId="3" PostId="9438" RevisionGUID="592bb04a-f3e8-440d-9968-a4f496c426fa" CreationDate="2019-12-23T13:19:58.583" UserId="10928" Text="|animation|rasterizer|drawing|midpoint|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25888" PostHistoryTypeId="2" PostId="9439" RevisionGUID="ddc0e5e2-ba24-48ec-9fdf-3018ca363935" CreationDate="2019-12-23T15:35:06.510" UserId="11630" Text="Various operations on 2D vectors naturally generalise to 3D vectors simply by including the $z$-coordinate. The ones that come to mind are:&#xD;&#xA;&#xD;&#xA;* Vector sum and difference&#xD;&#xA;* Dot product&#xD;&#xA;* Magnitude (Euclidean norm)&#xD;&#xA;&#xD;&#xA;Various graphics programming tasks also use 4D vectors, usually(?) to represent points in 3D projective space. Given this, it would seem that the above operations should *not* use the $w$-coordinate.&#xD;&#xA;&#xD;&#xA;For example, the magnitude of a 4D vector would be calculated in exactly the same way as the equivalent 3D vector:&#xD;&#xA;&#xD;&#xA;$\lVert \mathbf{v} \rVert = \sqrt{x^2+y^2+z^2}$&#xD;&#xA;&#xD;&#xA;...and not with the inclusion of the $w$-coordinate:&#xD;&#xA;&#xD;&#xA;$\lVert \mathbf{v} \rVert = \sqrt{x^2+y^2+z^2+w^2}$&#xD;&#xA;&#xD;&#xA;(For a point at infinity, where $w=0$, there wouldn't be a difference, but for finite points, there would. I'm also assuming that a finite 4D projective vector is in canonical form, with $w=1$.)&#xD;&#xA;&#xD;&#xA;**Is this always the case?** Is there any situation in graphics programming where calculations on 4D vectors should *not* treat them as their 3D equivalents, but should actually make use of the $w$-coordinate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25889" PostHistoryTypeId="1" PostId="9439" RevisionGUID="ddc0e5e2-ba24-48ec-9fdf-3018ca363935" CreationDate="2019-12-23T15:35:06.510" UserId="11630" Text="When should operations on 4D (projective) vectors use the w-coordinate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25890" PostHistoryTypeId="3" PostId="9439" RevisionGUID="ddc0e5e2-ba24-48ec-9fdf-3018ca363935" CreationDate="2019-12-23T15:35:06.510" UserId="11630" Text="|mathematics|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25891" PostHistoryTypeId="5" PostId="9438" RevisionGUID="be1c4ad2-1c1f-4bc7-a1f5-fecf491083b9" CreationDate="2019-12-23T15:35:52.097" UserId="10928" Comment="Add other circles" Text="I wonder why all the well known algorithms of drawing for example circles (bresenham, mid-point, etc) all use integer arithmetics? For example, here is a simple circle drawn with bresenham algorithm:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this is what I get with a circle drawn using naive algorithm (with real numbers):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The bresenham's version just look terrible and feels laggy while the floating point version is much smoother. So why do we read everywhere that &quot;integer&quot; versions are preferred? The integer version is maybe faster but horrible when it comes to animating a moving shape. So the question is: should I use floating point version or bresenham's version in my little toy rasterizer?&#xD;&#xA;&#xD;&#xA;Here's a more real world example:&#xD;&#xA;&#xD;&#xA;Bresenham:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Floating point:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;So what which version is the correct one? The floating point looks wobbly but smoother than Bresenham. Should I stick with Bresenham integer or use a floating point version smoother (or even a fixed point version)?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/N7Spm.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/nHCk1.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/69abW.gif&#xD;&#xA;  [4]: https://i.stack.imgur.com/G19fN.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="25892" PostHistoryTypeId="5" PostId="9439" RevisionGUID="f8a3c13c-bc6d-44e2-8504-92dfea1b1571" CreationDate="2019-12-23T15:41:04.030" UserId="11630" Comment="Projective AKA homogeneous" Text="Various operations on 2D vectors naturally generalise to 3D vectors simply by including the $z$-coordinate. The ones that come to mind are:&#xD;&#xA;&#xD;&#xA;* Vector sum and difference&#xD;&#xA;* Dot product&#xD;&#xA;* Magnitude (Euclidean norm)&#xD;&#xA;&#xD;&#xA;Various graphics programming tasks also use 4D vectors, usually(?) to represent points in 3D projective space (AKA homogeneous coordinates). Given this, it would seem that the above operations should *not* use the $w$-coordinate.&#xD;&#xA;&#xD;&#xA;For example, the magnitude of a 4D vector would be calculated in exactly the same way as the equivalent 3D vector:&#xD;&#xA;&#xD;&#xA;$\lVert \mathbf{v} \rVert = \sqrt{x^2+y^2+z^2}$&#xD;&#xA;&#xD;&#xA;...and not with the inclusion of the $w$-coordinate:&#xD;&#xA;&#xD;&#xA;$\lVert \mathbf{v} \rVert = \sqrt{x^2+y^2+z^2+w^2}$&#xD;&#xA;&#xD;&#xA;(For a point at infinity, where $w=0$, there wouldn't be a difference, but for finite points, there would. I'm also assuming that a finite 4D homogeneous vector is in canonical form, with $w=1$.)&#xD;&#xA;&#xD;&#xA;**Is this always the case?** Is there any situation in graphics programming where calculations on 4D vectors should *not* treat them as their 3D equivalents, but should actually make use of the $w$-coordinate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25893" PostHistoryTypeId="4" PostId="9439" RevisionGUID="f8a3c13c-bc6d-44e2-8504-92dfea1b1571" CreationDate="2019-12-23T15:41:04.030" UserId="11630" Comment="Projective AKA homogeneous" Text="When should operations on 4D (homogeneous/projective) vectors use the w-coordinate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25894" PostHistoryTypeId="5" PostId="9437" RevisionGUID="c59273e3-32f2-4c1b-b7fd-0f086ba08641" CreationDate="2019-12-23T16:13:17.680" UserId="209" Comment="deleted confusing additional note" Text="If the end of your cylinder is convex, with vertices $V_0, V_1, V_2,...V_{N-1}$ then just replace your fan order (i.e. as above) with this strip $V_0, V_1, V_{N-1}, V_2, V_{N-2}, V_3...$, i.e. just zig-zag across the polygon.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25895" PostHistoryTypeId="2" PostId="9440" RevisionGUID="87090d38-8f36-4b39-a4d9-6dce9669cbbb" CreationDate="2019-12-23T16:44:51.590" UserId="209" Text="The following is really an assorted set of comments:&#xD;&#xA;&#xD;&#xA;Why integer? Floating-point hardware is (in general) far more complex than integer and so on many (old) CPUs it (a) might not have been available (because of silicon budget) and/or (b) took considerably more clock cycles to execute.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Re &quot;Bresenham's&quot; algorithm: IIRC there is a branch/decision per pixel. On old CPUs (with relatively little or no pipelining) this would have not been a penalty, but with modern, highly pipelined/superscalar  CPUs, each mispredicted branch will be detrimental. &#xD;&#xA;Presumably (as I can't see your code) using floating-point removes that decision from the loop but, then again, you could use fixed-point (i.e. integer) to get the same effect.&#xD;&#xA;&#xD;&#xA;Having said this, hardware rasterisation is probably using fixed-point (i.e. integer) maths when filling polygons as this (a) makes conforming to the OpenGL fill rules easier and (b) prevents some very nasty problems occuring with long/thin triangles.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25896" PostHistoryTypeId="5" PostId="9440" RevisionGUID="923a89d4-06b0-470b-b2fc-75b50833d582" CreationDate="2019-12-23T16:50:12.230" UserId="209" Comment="added 24 characters in body" Text="The following is really an assorted set of comments:&#xD;&#xA;&#xD;&#xA;Why integer? Floating-point hardware is (in general) far more complex than integer and so on many (old) CPUs it (a) might not have been available (because of silicon budget) and/or (b) took considerably more clock cycles to execute than integer operations.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Re &quot;Bresenham's&quot; algorithm: IIRC there is a branch/decision per pixel. On old CPUs (with relatively little or no pipelining) this would have not been a penalty, but with modern, highly pipelined/superscalar  CPUs, each mispredicted branch will be detrimental. &#xD;&#xA;Presumably (as I can't see your code) using floating-point removes that decision from the loop but, then again, you could use fixed-point (i.e. integer) to get the same effect.&#xD;&#xA;&#xD;&#xA;Having said this, hardware rasterisation is probably using fixed-point (i.e. integer) maths when filling polygons as this (a) makes conforming to the OpenGL fill rules easier and (b) prevents some very nasty problems occuring with long/thin triangles.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25897" PostHistoryTypeId="2" PostId="9441" RevisionGUID="240c1149-ad3a-457d-9718-cee4554e9cdb" CreationDate="2019-12-25T02:26:10.413" UserId="11634" Text="my question might come in a bit weird but I'm looking for something that would be considered very CPU-intensive video to decode (for playback I mean). I would like to have some sample of 1080p and 4k videos that would classify to see if my CPU can handle it.&#xD;&#xA;&#xD;&#xA;Sorry if this is a bit of off-topic but I'm not sure where else on the internet to ask.&#xD;&#xA;&#xD;&#xA;Backstory to prevent XY-problem: HW-accelerated video decoding on my GPU is not working and I'm trying to find if it actually is a problem or if my CPU can handle it fine." ContentLicense="CC BY-SA 4.0" />
  <row Id="25898" PostHistoryTypeId="1" PostId="9441" RevisionGUID="240c1149-ad3a-457d-9718-cee4554e9cdb" CreationDate="2019-12-25T02:26:10.413" UserId="11634" Text="What would be an example of decoding-intensive video?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25899" PostHistoryTypeId="3" PostId="9441" RevisionGUID="240c1149-ad3a-457d-9718-cee4554e9cdb" CreationDate="2019-12-25T02:26:10.413" UserId="11634" Text="|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25900" PostHistoryTypeId="50" PostId="2146" RevisionGUID="d1d6ce5d-a845-4b7d-a1d9-3f8d321cf326" CreationDate="2019-12-25T06:02:10.377" UserId="-1" />
  <row Id="25901" PostHistoryTypeId="2" PostId="9442" RevisionGUID="f34d37f7-8672-44ca-ba6a-427ae03ff7d0" CreationDate="2019-12-25T09:18:44.583" UserId="11636" Text="Consider a square S with vertices (1,1,0), (1,-1,0), (-1,-1,0) and (-1,1,0) and a plane P defined by $z=1$. Let the perspective projection of S on P is denoted by S'. &#xD;&#xA;What coordinates of the Center of projection(COP) will convert the square S in rectangle or rhombus in S'? &#xD;&#xA;&#xD;&#xA;I found this question in my class test. As the object and the projection plane are parallel to each other, i think every coordinates for center of projection will generate square. But i can't find any valid mathematical proof for that. Is my assumption valid or not?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="25902" PostHistoryTypeId="1" PostId="9442" RevisionGUID="f34d37f7-8672-44ca-ba6a-427ae03ff7d0" CreationDate="2019-12-25T09:18:44.583" UserId="11636" Text="Project a Square as rectangle in projection plane using perspective projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="25903" PostHistoryTypeId="3" PostId="9442" RevisionGUID="f34d37f7-8672-44ca-ba6a-427ae03ff7d0" CreationDate="2019-12-25T09:18:44.583" UserId="11636" Text="|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25904" PostHistoryTypeId="50" PostId="8701" RevisionGUID="004decb4-2898-4bac-b49c-ee20bd176b9f" CreationDate="2019-12-25T11:01:00.137" UserId="-1" />
  <row Id="25905" PostHistoryTypeId="50" PostId="8886" RevisionGUID="99cc4238-1a97-4245-a4c3-7157de7b526d" CreationDate="2019-12-25T13:03:05.480" UserId="-1" />
  <row Id="25910" PostHistoryTypeId="5" PostId="9407" RevisionGUID="486c2aad-d46b-4293-bbc4-4b33fc588239" CreationDate="2019-12-25T19:43:41.230" UserId="7724" Comment="Fixed typo and link" Text="Your phone would have to do all of the CPU processing too then beam it to your laptop using scrcpy: https://github.com/Genymobile/scrcpy" ContentLicense="CC BY-SA 4.0" />
  <row Id="25911" PostHistoryTypeId="24" PostId="9407" RevisionGUID="486c2aad-d46b-4293-bbc4-4b33fc588239" CreationDate="2019-12-25T19:43:41.230" Comment="Proposed by 7724 approved by 209, 48 edit id of 501" ContentLicense="CC BY-SA 4.0" />
  <row Id="25912" PostHistoryTypeId="2" PostId="9444" RevisionGUID="cd7ed73b-5454-4926-9c09-1f1e2fd8f6cf" CreationDate="2019-12-26T06:04:01.220" UserId="9254" Text="In the context of global illumination and the scattering equation, do we need to understand &quot;light sources&quot; as surfaces with a &quot;purely emissive&quot; material on which no scattering is present?&#xD;&#xA;&#xD;&#xA;In contrast, any surface in the scene geometry could be equipped with a self-emissive material and hence being somehow a &quot;light source&quot; (it's kind of a philosophical question, I guess).&#xD;&#xA;&#xD;&#xA;However, since we often talk about light-carrying paths of &quot;length&quot; $k$, where one endpoint is located on the camera and the other on a light source, I guess that's how we need to see it. Am I correct or is there something I'm missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25913" PostHistoryTypeId="1" PostId="9444" RevisionGUID="cd7ed73b-5454-4926-9c09-1f1e2fd8f6cf" CreationDate="2019-12-26T06:04:01.220" UserId="9254" Text="What is a &quot;light source&quot; in global illumination?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25914" PostHistoryTypeId="3" PostId="9444" RevisionGUID="cd7ed73b-5454-4926-9c09-1f1e2fd8f6cf" CreationDate="2019-12-26T06:04:01.220" UserId="9254" Text="|raytracing|pathtracing|global-illumination|material|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25915" PostHistoryTypeId="2" PostId="9445" RevisionGUID="40da206c-163b-4fb2-be35-111b31aa3e12" CreationDate="2019-12-26T10:13:55.317" UserDisplayName="user8592" Text="Like @lightxbulb said, a light source (i.e. an emissive surface whose `L_e` term in the rendering equation is greater than zero) can also have a BRDF.&#xD;&#xA;People usually do not model light sources really accurately down to the Tungsten filament geometry inside of a glass-enclosed gas chamber for incandescent light bulbs. Such light sources usually are modelled as simple geometries, like spheres, capsules, lines, rectangles or more generic polygons, etc.&#xD;&#xA;So, most often, light sources are usually not exactly physically accurate anyways, because it would be too computationally expensive (imagine computing the intersection of a ray with the Tungsten filament in addition to account for a very little bit of volumetric scattering through the gas).&#xD;&#xA;Therefore, in the simplest cases, such an incandescent light source is down to a simple sphere anyways. In that case, it would make most sense to model this light source with a translucent BTDF (Bidirectional Transmittance Distribution Function), because most of the rays will probably not hit the filament but would go straight through the glass.&#xD;&#xA;What we would have to consider, however, is Fresnel and retro-reflection on the glass surface of the light bulb.&#xD;&#xA;But it all depends on how accurately you want to model your light sources.&#xD;&#xA;If, on the other hand, your light source is a milk glass light bulb, then you would probably need a BRDF + BTDF (or more generally a BSDF - bidirectional scattering distribution function) to account for the light that is reflected off the glass surface and the amount of light that is trasmitting through the glass.&#xD;&#xA;&#xD;&#xA;In any case, stopping a ray at the light source (as you pointed out) would only be actually physically correct, if the surface of the light source is a black body not reflecting any light but only emitting light due to its temperature." ContentLicense="CC BY-SA 4.0" />
  <row Id="25916" PostHistoryTypeId="52" PostId="9444" RevisionGUID="dd14c19b-22ba-45eb-aeba-a66aaecb35aa" CreationDate="2019-12-26T14:10:48.523" />
  <row Id="25920" PostHistoryTypeId="50" PostId="8321" RevisionGUID="3feddf23-4d54-48d8-837d-db00427db75e" CreationDate="2019-12-27T03:03:25.453" UserId="-1" />
  <row Id="25921" PostHistoryTypeId="50" PostId="8695" RevisionGUID="1dee4775-e110-41d3-8c6e-aa430cd106e1" CreationDate="2019-12-27T17:03:25.557" UserId="-1" />
  <row Id="25922" PostHistoryTypeId="2" PostId="9447" RevisionGUID="fae932d2-27fe-4994-8ee1-5ddff5503bf5" CreationDate="2019-12-28T08:47:00.870" UserId="7515" Text="I have paths in SVG file with `d` attributes with values like &#xD;&#xA;&#xD;&#xA;&gt; M 48.75521890547264 45.77014427860697 Q 48.756218905472636&#xD;&#xA;&gt; 45.77114427860697 50.24875621890547 45.77114427860697 Q 51.74129353233831 45.77114427860697 55.72139303482587 46.26865671641791 Q 59.701492537313435 46.766169154228855 64.17910447761194 46.766169154228855 Q 68.65671641791045 46.766169154228855 73.6318407960199 47.2636815920398 Q 78.60696517412936 47.76119402985075 82.08955223880596 47.76119402985075 Q 85.57213930348259 47.76119402985075 88.55721393034827&#xD;&#xA;&#xD;&#xA; etc.&#xD;&#xA;&#xD;&#xA;I want to classify this path into geometric shapes like circle, rectangle, ellipse etc programmatically.When i mean programmatically i mean no image processing techniques should be involved i.e strict requirement. Is there any way to do this. Please guide me.  &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25923" PostHistoryTypeId="1" PostId="9447" RevisionGUID="fae932d2-27fe-4994-8ee1-5ddff5503bf5" CreationDate="2019-12-28T08:47:00.870" UserId="7515" Text="how to programmatically extract shape types like circle etc from SVG file path attributes" ContentLicense="CC BY-SA 4.0" />
  <row Id="25924" PostHistoryTypeId="3" PostId="9447" RevisionGUID="fae932d2-27fe-4994-8ee1-5ddff5503bf5" CreationDate="2019-12-28T08:47:00.870" UserId="7515" Text="|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25925" PostHistoryTypeId="2" PostId="9448" RevisionGUID="25ed53f0-8098-49be-b038-98f0b26cbd38" CreationDate="2019-12-28T09:29:30.683" UserDisplayName="user11352" Text="In 3d modeling, there is some &quot;triangle count&quot; which determines complexity. I am not sure but I think cubes have 12 triangles or somethong.But I see NONE They have squares, no triangles! Can someone please help me understand what a triangle is?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25926" PostHistoryTypeId="1" PostId="9448" RevisionGUID="25ed53f0-8098-49be-b038-98f0b26cbd38" CreationDate="2019-12-28T09:29:30.683" UserDisplayName="user11352" Text="WTF are &quot;Triangles&quot; in 3d modeling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25927" PostHistoryTypeId="3" PostId="9448" RevisionGUID="25ed53f0-8098-49be-b038-98f0b26cbd38" CreationDate="2019-12-28T09:29:30.683" UserDisplayName="user11352" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25928" PostHistoryTypeId="4" PostId="9448" RevisionGUID="2303c361-ccd9-405f-b605-7c8cffc7dfcf" CreationDate="2019-12-28T10:15:27.407" UserId="209" Comment="Toned down title" Text="What are &quot;Triangles&quot; in 3d modeling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25929" PostHistoryTypeId="2" PostId="9449" RevisionGUID="fd12217f-0fcc-42eb-81f5-f22145ba3b48" CreationDate="2019-12-28T13:13:09.823" UserId="10806" Text="When compiling a glsl fragment shader which reads ``gl_PrimitiveID`` with glslc compiler I get the spirv-1.0 with Geometry capability enabled, which is technically correct, as it's stated in spirv spec. &#xD;&#xA;Vulkan 1.0 spec says that Geometry capability must be supported if ``geometryShader`` feature is enabled. &#xD;&#xA;&#xD;&#xA;So I assume that unless ``geometryShader`` is enabled, one can't use ``gl_PrimitiveID``. Specifically, using ``gl_PrimitiveID`` is impossible on moltenVK, as it does not support this feature, isn't it?&#xD;&#xA;&#xD;&#xA;In my pipeline I used ``gl_PrimitiveID`` to fetch per-face data from global ssbo and to render face ids to attachment for later reuse. Is it possible to achieve similar result without ``gl_PrimitiveID``?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25930" PostHistoryTypeId="1" PostId="9449" RevisionGUID="fd12217f-0fcc-42eb-81f5-f22145ba3b48" CreationDate="2019-12-28T13:13:09.823" UserId="10806" Text="Vulkan: using gl_PrimitiveID without geometryShader feature" ContentLicense="CC BY-SA 4.0" />
  <row Id="25931" PostHistoryTypeId="3" PostId="9449" RevisionGUID="fd12217f-0fcc-42eb-81f5-f22145ba3b48" CreationDate="2019-12-28T13:13:09.823" UserId="10806" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25932" PostHistoryTypeId="50" PostId="5697" RevisionGUID="539cae9b-1107-4e51-ac0f-83e3fb9e80bf" CreationDate="2019-12-29T03:03:35.477" UserId="-1" />
  <row Id="25933" PostHistoryTypeId="2" PostId="9450" RevisionGUID="ed4762b4-aef0-4b2c-a882-6152e7ec08bf" CreationDate="2019-12-29T13:45:14.423" UserId="11656" Text="As a little project, I'd like to implement a BSP merging algorithm for Boolean operations on solids. But to even tell whether it works, I need some way to render the BSP tree. In other words, I have a BSP tree corresponding to some 3D solid, with all its leaves having an indicator value of &quot;0&quot; or &quot;1&quot;, and I'd like to render out the areas corresponding to the leaves with value 1.&#xD;&#xA;&#xD;&#xA;I understand the general approach for doing the actual BSP tree merging, but I'm not really sure how to render a BSP tree. I'm not interested in efficiency, and I don't need to convert the BSP tree to an actual mesh/boundary representation - I just want to render the BSP tree somehow (as simply as possible), to have an idea whether the implementation works.&#xD;&#xA;&#xD;&#xA;I'd guess that one way to do this would be to go through the tree, and somehow progressively clip the space I have. So I might start with some sort of very large cube (that corresponds to the full 3D space), and I keep clipping it by half planes as  I go through the tree. If I reach a leaf with value 1, I &quot;save&quot; the mesh and render it. This might work, but it seems like a bit too much work, and honestly I'm not experienced in computer graphics, so I'd prefer if there was some easier way.&#xD;&#xA;&#xD;&#xA;I'd appreciate any advice.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25934" PostHistoryTypeId="1" PostId="9450" RevisionGUID="ed4762b4-aef0-4b2c-a882-6152e7ec08bf" CreationDate="2019-12-29T13:45:14.423" UserId="11656" Text="BSP tree rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="25935" PostHistoryTypeId="3" PostId="9450" RevisionGUID="ed4762b4-aef0-4b2c-a882-6152e7ec08bf" CreationDate="2019-12-29T13:45:14.423" UserId="11656" Text="|rendering|3d|algorithm|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25936" PostHistoryTypeId="2" PostId="9451" RevisionGUID="31224624-eb29-42aa-8b05-00174ea6de4c" CreationDate="2019-12-29T17:02:11.097" UserId="2654" Text="It seems likely that the mechanism by which the `gl_PrimitiveID` is generated is, in some way, based on the hardware that makes geometry shaders possible.&#xD;&#xA;&#xD;&#xA;OpenGL ES 3.1 contains compute shaders but not geometry shaders (or tessellation). But it doesn't have `gl_PrimitiveID`. By contrast, ES 3.2 contains GS's and `gl_PrimitiveID`. The same goes for desktop OpenGL 3.1 vs. 3.2 and its GS functionality. Having a GS and having the ability to identify primitives in a sequence seem to be part of the same general functionality.&#xD;&#xA;&#xD;&#xA;&gt; In my pipeline I used gl_PrimitiveID to fetch per-face data from global ssbo and to render face ids to attachment for later reuse.&#xD;&#xA;&#xD;&#xA;Without the hardware functionality, there is no *general* way to compute a count of primitives. There are only specific solutions for specific circumstances.&#xD;&#xA;&#xD;&#xA;For example, if you are using non-index rendering of triangle lists, then you can use `gl_VertexID / 3` to compute a primitive ID. Obviously that's a pretty tight restriction, but it would work in that circumstance.&#xD;&#xA;&#xD;&#xA;You could also provide each vertex with a per-vertex face ID. The VS would output this value using `flat` interpolation. By carefully matching the face ID with the [provoking vertex for the primitive topology](https://www.khronos.org/registry/vulkan/specs/1.1/html/chap19.html#drawing-primitive-topologies), you can effectively assign a face ID to a face. This works best with indexed triangle lists, as you can play around with the order of indices in a triangle more than you can with strips. You basically have to decide which vertex maps to which face, and make sure that that face uses that vertex as the first one." ContentLicense="CC BY-SA 4.0" />
  <row Id="25937" PostHistoryTypeId="2" PostId="9452" RevisionGUID="6854d36b-2ba2-410c-bfb6-ee2f34d4f560" CreationDate="2019-12-29T23:36:33.577" UserId="6470" Text="Given the rendering equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(x, \theta_o) = L_e(x, \theta_o) + \int_{\Omega} \! f(x,\theta_i,\theta_o) L_i(x,\theta_i) \cos(\theta_i, \theta_o) \, \mathrm{d} \theta_i.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Rewriting it using linear operator $F$, as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o = L_e + F \circ L_i.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Consider the final state that $L = L_o = L_i$, then there are two ways to rewrite and interpret:&#xD;&#xA;&#xD;&#xA;(1) (light tracing?)&#xD;&#xA;$$&#xD;&#xA;L_e = (I - F)^{-1} \circ L.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;(2) (path tracing?)&#xD;&#xA;$$&#xD;&#xA;L = (I + F + F^2 + F^3 + \cdots ) \circ L_e.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;- Are the two classifications the correct intrepretation?&#xD;&#xA;&#xD;&#xA;- Thinking about (2) as path tracing is easy, in that rays starting from $L$ go through multiple bounces and finally reaching $L_e$; while thinking of (1) as light tracing is difficult for me. Are there any intuitive explanations?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25938" PostHistoryTypeId="1" PostId="9452" RevisionGUID="6854d36b-2ba2-410c-bfb6-ee2f34d4f560" CreationDate="2019-12-29T23:36:33.577" UserId="6470" Text="Intrepret path/light tracing by rewriting light transport equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25939" PostHistoryTypeId="3" PostId="9452" RevisionGUID="6854d36b-2ba2-410c-bfb6-ee2f34d4f560" CreationDate="2019-12-29T23:36:33.577" UserId="6470" Text="|rendering|pathtracing|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25940" PostHistoryTypeId="5" PostId="9452" RevisionGUID="ec2cb257-93b0-4dbb-b7d3-a3e857625301" CreationDate="2019-12-29T23:57:09.977" UserId="6470" Comment="Corrections" Text="Given the rendering equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(x, \theta_o) = L_e(x, \theta_o) + \int_{\Omega} \! f(x,\theta_i,\theta_o) L_i(x,\theta_i) \cos(\theta_i, \theta_o) \, \mathrm{d} \theta_i.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Rewriting it using linear operator $F$, as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o = L_e + F \circ L_i.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Consider the final state that $L = L_o = L_i$, then there are two ways to rewrite and interpret:&#xD;&#xA;&#xD;&#xA;(1) (light tracing?)&#xD;&#xA;$$&#xD;&#xA;L_e = (I - F) \circ L.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;(2) (path tracing?)&#xD;&#xA;$$&#xD;&#xA;L = (I + F + F^2 + F^3 + \cdots ) \circ L_e.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;- Are the two classifications the correct intrepretation?&#xD;&#xA;&#xD;&#xA;- Thinking about (2) as path tracing is easy, in that rays starting from $L$ go through multiple bounces and finally reaching $L_e$; while thinking of (1) as light tracing is difficult for me. Are there any intuitive explanations for both?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25942" PostHistoryTypeId="50" PostId="8721" RevisionGUID="22f2fc79-bf87-49be-bc47-6429ac58cce3" CreationDate="2019-12-30T08:01:50.260" UserId="-1" />
  <row Id="25944" PostHistoryTypeId="5" PostId="9447" RevisionGUID="5e1a0a9b-87d6-4fac-ad11-7ef7b929e215" CreationDate="2019-12-30T09:22:32.153" UserId="11652" Comment="Fixed the text" Text="I have paths in SVG file with `d` attributes with values like &#xD;&#xA;&#xD;&#xA;&gt; M 48.75521890547264 45.77014427860697 Q 48.756218905472636&#xD;&#xA;&gt; 45.77114427860697 50.24875621890547 45.77114427860697 Q 51.74129353233831 45.77114427860697 55.72139303482587 46.26865671641791 Q 59.701492537313435 46.766169154228855 64.17910447761194 46.766169154228855 Q 68.65671641791045 46.766169154228855 73.6318407960199 47.2636815920398 Q 78.60696517412936 47.76119402985075 82.08955223880596 47.76119402985075 Q 85.57213930348259 47.76119402985075 88.55721393034827&#xD;&#xA;&#xD;&#xA; etc.&#xD;&#xA;&#xD;&#xA;I want to classify this path into geometric shapes like circle, rectangle, ellipse etc programmatically. When I say programmatically I mean no image processing techniques should be involved i.e. strict requirement.  &#xD;&#xA;Is there any way to do this. Please guide me.  &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25945" PostHistoryTypeId="4" PostId="9447" RevisionGUID="5e1a0a9b-87d6-4fac-ad11-7ef7b929e215" CreationDate="2019-12-30T09:22:32.153" UserId="11652" Comment="Fixed the text" Text="How to programmatically extract shape types like circle etc from SVG file path attributes" ContentLicense="CC BY-SA 4.0" />
  <row Id="25946" PostHistoryTypeId="24" PostId="9447" RevisionGUID="5e1a0a9b-87d6-4fac-ad11-7ef7b929e215" CreationDate="2019-12-30T09:22:32.153" Comment="Proposed by 11652 approved by 7515 edit id of 503" ContentLicense="CC BY-SA 4.0" />
  <row Id="25947" PostHistoryTypeId="2" PostId="9454" RevisionGUID="be526155-2a3c-4222-86c2-fd55d05bbe42" CreationDate="2019-12-30T15:16:30.510" UserId="10096" Text="Having the rendering equation one can rewrite it in operator form:&#xD;&#xA;&#xD;&#xA;$$L = L_e + TL$$&#xD;&#xA;$$(I-T)L = L_e$$&#xD;&#xA;$$L = (I-T)^{-1}L_e$$&#xD;&#xA;$$L = \sum_{k=0}^{\infty}T^kL_e$$&#xD;&#xA;&#xD;&#xA;The last equality holds if $T$ is a contraction ($\|T\| &lt; 1$), and under very specific conditions if $T$ is not a contraction. An example of when the 4th equality does not hold would be picking an enclosed volume bounded by some surface, that is made of a non-energy conserving material, and putting a light source inside. Then the radiance will keep increasing with every bounce so at some point $L$ will be infinity everywhere on the inside of the volume. Meaning that the the series does not converge.&#xD;&#xA;&#xD;&#xA;The 4th equality is really the [Liouville-Neumann][1] expansion. So you get an infinite sum of increasingly-dimensional integrals, each subsequent term being a bounce away from the previous. Each term gives you the contribution due to a light path of length equal to the index of the term. &#xD;&#xA;&#xD;&#xA;More precisely, this solution gives you the steady state $L$ if it exists (we assume that light travels instantaneously, that it is incoherent, linear etc). Note that $L$ is simply the radiance function, so this formalism really gives you the solution at every point in the scene. &#xD;&#xA;&#xD;&#xA;In practice you usually need only the radiance measured at the surface of a virtual camera film. So a straightforward optimization is to trace rays starting from the surface of the camera film. This does not guarantee that you get the solution for $L$ at every point of the scene, but is a lot more efficient. You can also trace rays starting at the light source, but you are usually also interested in their contribution to the film, so the measurement function (see Veach's thesis) has to also make it in there, and only a subset of lights may be of interest. Finally you can do photon mapping, or light tracing where you are interested of the radiance over the whole scene, and that would be the closest thing to the original formulation.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Liouville%E2%80%93Neumann_series" ContentLicense="CC BY-SA 4.0" />
  <row Id="25948" PostHistoryTypeId="50" PostId="8209" RevisionGUID="d6532fd4-ced1-4703-9d66-4db9f13b00fa" CreationDate="2019-12-30T23:00:36.037" UserId="-1" />
  <row Id="25949" PostHistoryTypeId="2" PostId="9455" RevisionGUID="09f1da7c-21db-4d91-a272-248fd0763f08" CreationDate="2019-12-31T01:48:53.277" UserId="9987" Text="I am doing some animation jobs. I need to pack some pivots into UV and then my shader can read them. &#xD;&#xA;&#xD;&#xA;I need to pack 4 float3 into a float4. Therefore, I need to pack each float3 into a  float.&#xD;&#xA;&#xD;&#xA;These 4 float3 are (model space position1, direction1, model space position2, direction2). I know how to handle the directions because they are normalized. I can use something like:&#xD;&#xA;&#xD;&#xA;     #define f3_f(c) (dot(round((c) * 255), float3(65536, 256, 1)))&#xD;&#xA;     #define f_f3(f) (frac((f) / float3(16777216, 65536, 256)))&#xD;&#xA;&#xD;&#xA;But How can I pack these positions? I am using SM3.0 and I can't use bitwise operations" ContentLicense="CC BY-SA 4.0" />
  <row Id="25950" PostHistoryTypeId="1" PostId="9455" RevisionGUID="09f1da7c-21db-4d91-a272-248fd0763f08" CreationDate="2019-12-31T01:48:53.277" UserId="9987" Text="How to pack 3 floats into one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25951" PostHistoryTypeId="3" PostId="9455" RevisionGUID="09f1da7c-21db-4d91-a272-248fd0763f08" CreationDate="2019-12-31T01:48:53.277" UserId="9987" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25954" PostHistoryTypeId="50" PostId="9048" RevisionGUID="31f961e9-3e7a-445a-bf1c-9be010cca75f" CreationDate="2020-01-02T00:02:15.297" UserId="-1" />
  <row Id="25958" PostHistoryTypeId="19" PostId="1513" RevisionGUID="4342c881-8943-4b24-a9c4-9cf7b68a14dd" CreationDate="2020-01-02T09:04:22.590" UserId="-1" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:-1,&quot;DisplayName&quot;:&quot;Community&quot;}]}" />
  <row Id="25959" PostHistoryTypeId="2" PostId="9457" RevisionGUID="5ddeda16-da72-4c18-84ab-e782411cb4bf" CreationDate="2020-01-02T09:38:01.110" UserId="10928" Text="I don't understand something about the near clipping plane. It's there to avoid the division by $0$ but when we compute the pixel coordinates, we just need to multiply by the clipping plane to clip the object?&#xD;&#xA;&#xD;&#xA;For example in this code, from https://www.scratchapixel.com/lessons/3d-basic-rendering/3d-viewing-pinhole-camera/implementing-virtual-pinhole-camera&#xD;&#xA;```cpp&#xD;&#xA;pScreen.x = pCamera.x / -pCamera.z * near; &#xD;&#xA;pScreen.y = pCamera.y / -pCamera.z * near; &#xD;&#xA; &#xD;&#xA;Vec2f pNDC; &#xD;&#xA;pNDC.x = (pScreen.x + r) / (2 * r); &#xD;&#xA;pNDC.y = (pScreen.y + t) / (2 * t); &#xD;&#xA;pRaster.x = (int)(pNDC.x * imageWidth); &#xD;&#xA;pRaster.y = (int)((1 - pNDC.y) * imageHeight); &#xD;&#xA; &#xD;&#xA;bool visible = true; &#xD;&#xA;if (pScreen.x &lt; l || pScreen.x &gt; r || pScreen.y &lt; b || pScreen.y &gt; t) &#xD;&#xA;    visible = false; &#xD;&#xA;&#xD;&#xA;return visible; &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;When do they actually discard points that have a z component smaller than the near clipping plane? They just discard those which have a x and y coordinate not visible to the screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="25960" PostHistoryTypeId="1" PostId="9457" RevisionGUID="5ddeda16-da72-4c18-84ab-e782411cb4bf" CreationDate="2020-01-02T09:38:01.110" UserId="10928" Text="Understanding the near clipping plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="25961" PostHistoryTypeId="3" PostId="9457" RevisionGUID="5ddeda16-da72-4c18-84ab-e782411cb4bf" CreationDate="2020-01-02T09:38:01.110" UserId="10928" Text="|3d|projections|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25962" PostHistoryTypeId="2" PostId="9458" RevisionGUID="17f5c9a8-8773-45c8-8b9d-2230ae6f51bb" CreationDate="2020-01-02T16:29:49.687" UserId="2654" Text="&gt; When do they actually discard points that have a z component smaller than the near clipping plane?&#xD;&#xA;&#xD;&#xA;For actual rendering hardware, they don't. Clipping happens in clip space, before the NDC transform. &quot;Points&quot; outside of the clipping volume are never seen by the rasterizer (in theory, at least. In practice, guard-band clipping is often used to minimize the need for clipping against the sizes).&#xD;&#xA;&#xD;&#xA;The renderer presented at that site doesn't appear to do clipping at all. It has an approximation of what *would* be clipped, but it doesn't actually do the clipping. " ContentLicense="CC BY-SA 4.0" />
  <row Id="25963" PostHistoryTypeId="2" PostId="9459" RevisionGUID="e4d67e3d-2256-48df-9377-fae5dcd6ccf5" CreationDate="2020-01-03T03:29:31.840" UserId="6470" Text="I am a newbie in computer graphics and just started working on physically based rendering engines such as Mitsuba.&#xD;&#xA;&#xD;&#xA;I found it difficult to create my own scenes, that are xml files. To create one, there are three ways as I know so far:&#xD;&#xA;&#xD;&#xA;1. Build a scene in [Blender](https://www.blender.org/) and export it to a xml file using prasers, e.g. https://www.mitsuba-renderer.org/plugins.html.&#xD;&#xA;&#xD;&#xA;2. Download free xml scenes, e.g. from https://benedikt-bitterli.me/resources/.&#xD;&#xA;&#xD;&#xA;3. Hand-write an xml scene with Python from scratch, e.g. this example http://www.djmannion.net/psych_programming/vision/mitsuba/mitsuba.html. &#xD;&#xA;&#xD;&#xA;However, I am suffering from following issues:&#xD;&#xA;&#xD;&#xA;- It takes long time for me to create a scene via 1 and 3, yet not customizable via 2.&#xD;&#xA;&#xD;&#xA;- I do not know where to get free meshes (and license issues?)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA;- Are there any better ways to create an xml scene?&#xD;&#xA;&#xD;&#xA;- What is the canonical way to create delicate scenes, e.g. the ones in SIGGRAPH papers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25964" PostHistoryTypeId="1" PostId="9459" RevisionGUID="e4d67e3d-2256-48df-9377-fae5dcd6ccf5" CreationDate="2020-01-03T03:29:31.840" UserId="6470" Text="Standard ways to create xml scenes for research purposes" ContentLicense="CC BY-SA 4.0" />
  <row Id="25965" PostHistoryTypeId="3" PostId="9459" RevisionGUID="e4d67e3d-2256-48df-9377-fae5dcd6ccf5" CreationDate="2020-01-03T03:29:31.840" UserId="6470" Text="|pbr|scene-description|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25969" PostHistoryTypeId="2" PostId="9461" RevisionGUID="e8ddfc7d-e502-430e-81cd-81fda1206e72" CreationDate="2020-01-03T13:59:14.897" UserId="11679" Text="I am working on a procedural placement system on the GPU, inspired by the work done by Guerrilla Games in Horizon Zero Dawn:&#xD;&#xA;https://www.guerrilla-games.com/read/gpu-based-procedural-placement-in-horizon-zero-dawn&#xD;&#xA;&#xD;&#xA;On slide 28 they are showing a sampling pattern, which they use to determine whether to place an object or not. The pattern consists of evenly distributed points, each with a threshold value, which they test a artist-authored density map against.&#xD;&#xA;&#xD;&#xA;The threshold values are picked, such that they are evenly distributed and maximize the distance to neighboring sample points.&#xD;&#xA;&#xD;&#xA;I have looked into circle packing on a unit square to generate the sampling points, and this seems fine.&#xD;&#xA;&#xD;&#xA;The point I am having trouble with is how to create the threshold values with the specified requirement (even distribution between 0 and 1 and maximizing the distance to neighbors).&#xD;&#xA;Can someone point me in the right direction, as to how to achieve this? Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="25970" PostHistoryTypeId="1" PostId="9461" RevisionGUID="e8ddfc7d-e502-430e-81cd-81fda1206e72" CreationDate="2020-01-03T13:59:14.897" UserId="11679" Text="GPU Procedural placement - Creating evenly distributed sampling points" ContentLicense="CC BY-SA 4.0" />
  <row Id="25971" PostHistoryTypeId="3" PostId="9461" RevisionGUID="e8ddfc7d-e502-430e-81cd-81fda1206e72" CreationDate="2020-01-03T13:59:14.897" UserId="11679" Text="|mathematics|sampling|noise|distribution|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25976" PostHistoryTypeId="5" PostId="5118" RevisionGUID="222239cf-6f13-4a57-b155-206ad351eeff" CreationDate="2020-01-04T03:51:34.203" UserId="2654" Comment="edited body" Text="&gt; In this case, the geometry of similar triangles ABC and ADE is used to determine the height of D via the solution of DE. It is obvious that if the near plane is at 0 (AE=0), then a division by 0 occurs -- hence, why the near plane cannot be located at position 0.&#xD;&#xA;&#xD;&#xA;This is *not* why the nearZ plane cannot be zero. The goal of perspective math is not to project the E onto the near plane. If you look at the actual perspective matrices, you'll find that the nearZ *only* applies to the computed clip-space Z coordinate, not the X and Y.&#xD;&#xA;&#xD;&#xA;Remember: projection is essentially transforming a position such that you lose one or more dimensions. You're projecting from 3D space to 2D space. So projection is removing the Z component, projecting a scene into a 2D region of space. Orthographic projection just discards the Z; perspective projection does something more complex, rescaling the X and Y based on the Z.&#xD;&#xA;&#xD;&#xA;Of course, we're not *really* doing that; Z still exists. Otherwise, the depth buffer wouldn't work. But the basic perspective projection math does not define how the Z is computed.&#xD;&#xA;&#xD;&#xA;Therefore, we can compute the Z however we want. The traditional depth equation (for OpenGL's standard NDC space) is where near/farZ come from:&#xD;&#xA;&#xD;&#xA;$$Z_{ndc} = \frac{\frac{Z_{camera}(F + N)}{N - F} + \frac{2NF}{N - F}}{-Z_{camera}}$$&#xD;&#xA;&#xD;&#xA;`N` and `F` are near/farZ, respectively. If `N` is zero, then the equation degenerates:&#xD;&#xA;&#xD;&#xA;$$Z_{ndc} = \frac{\frac{Z_{camera}(F)}{-F} + 0}{-Z_{camera}}$$&#xD;&#xA;$$Z_{ndc} = \frac{-Z_{camera}}{-Z_{camera}}$$&#xD;&#xA;$$Z_{ndc} = 1$$&#xD;&#xA;&#xD;&#xA;Oops.&#xD;&#xA;&#xD;&#xA;So your question really is why we use depth computations (which again, don't really have anything to do with perspective projection) that require near/farZ values like this.&#xD;&#xA;&#xD;&#xA;This equation, and those like it, has some very nice properties. It plays well with the clip-space W component needed for perspective projection (the division by $-Z_{camera}$). But it also has the effect of being a non-linear Z projection. It puts more precision at the front of the scene than in the distance. And that's generally where you *need* depth precision the most.&#xD;&#xA;&#xD;&#xA;There are alternative ways to compute the clip-space Z. You can use a linear method, which doesn't forbid near Z from being 0. You can also use a method that allows for an infinitely distant far Z (but still relies on near Z); this requires a floating-point Z buffer, though. And so forth.&#xD;&#xA;&#xD;&#xA;You haven't really shown your code, so I can't say if it truly &quot;works&quot;. The clip-space W in particular is important, as it is used for [perspective-correct interpolation of vertex data][1]. If you set it to one, then you won't get proper perspective-correct interpolation. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://nicolbolas.github.io/oldtut/Texturing/Tut14%20Interpolation%20Redux.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="25977" PostHistoryTypeId="2" PostId="9463" RevisionGUID="fbb5b631-35ef-44f2-b960-3d9ce26288ba" CreationDate="2020-01-04T13:38:37.077" UserId="9169" Text="I compute bounding box of a mesh:&#xD;&#xA;&#xD;&#xA;````c++&#xD;&#xA;(xMin, xMax)&#xD;&#xA;(yMin, yMax)&#xD;&#xA;(zMin, zMax)&#xD;&#xA;````&#xD;&#xA;To get the bounding box, I need to go through all the mesh points and compute the min/max in X, Y and Z directions.&#xD;&#xA;&#xD;&#xA;[![Mesh not rotated][1]][1]&#xD;&#xA;&#xD;&#xA;Then I rotate the mesh. To get the bounding box for the rotated mesh, I need to go through all the mesh points again.&#xD;&#xA;&#xD;&#xA;[![Mesh rotated][2]][2]&#xD;&#xA;&#xD;&#xA;Is there a method to avoid going through all the mesh points **again** when object is rotated?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aFosU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PrIUB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25978" PostHistoryTypeId="1" PostId="9463" RevisionGUID="fbb5b631-35ef-44f2-b960-3d9ce26288ba" CreationDate="2020-01-04T13:38:37.077" UserId="9169" Text="Bounding box of a rotating mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="25979" PostHistoryTypeId="3" PostId="9463" RevisionGUID="fbb5b631-35ef-44f2-b960-3d9ce26288ba" CreationDate="2020-01-04T13:38:37.077" UserId="9169" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25980" PostHistoryTypeId="2" PostId="9464" RevisionGUID="e6865bb7-90a8-43e8-be68-c97032a7996c" CreationDate="2020-01-04T16:16:26.547" UserId="3305" Text="I have some photos of 3D cube. I also know the 3D pose of the cube in each photo (yaw, pitch, roll).&#xD;&#xA;&#xD;&#xA;I want to estimate the new pose (yaw, pitch, roll) of the cube after performing 2D rotation to the photo (like 2D camera rotation).&#xD;&#xA;&#xD;&#xA;I don't care its new position but the pose only.&#xD;&#xA;&#xD;&#xA;So, how can I calculate the new pose of 3D object after 2D rotation?&#xD;&#xA;&#xD;&#xA;For example:  &#xD;&#xA;**Original**  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**After image rotation (-45 deg) - Yaw, Pitch &amp; Roll are different** &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/y8EFh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FFhYq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="25981" PostHistoryTypeId="1" PostId="9464" RevisionGUID="e6865bb7-90a8-43e8-be68-c97032a7996c" CreationDate="2020-01-04T16:16:26.547" UserId="3305" Text="Estimate 3D object pose after camera rotation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25982" PostHistoryTypeId="3" PostId="9464" RevisionGUID="e6865bb7-90a8-43e8-be68-c97032a7996c" CreationDate="2020-01-04T16:16:26.547" UserId="3305" Text="|3d|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25986" PostHistoryTypeId="4" PostId="9464" RevisionGUID="1bbfa312-143d-4e9f-9f4e-d242abbbc051" CreationDate="2020-01-05T20:57:13.860" UserId="3305" Comment="edited title" Text="Estimate 3D cube pose after camera rotation" ContentLicense="CC BY-SA 4.0" />
  <row Id="25987" PostHistoryTypeId="5" PostId="2317" RevisionGUID="b09a81a7-fc3d-437a-8dd9-c62e56dc2068" CreationDate="2020-01-06T03:51:50.203" UserId="-1" Comment="Corrected the documentation link" Text="The error ```not well-formed        male.json``` doesn't appear to have anything to do with the code you've posted. I don't see any references to a JSON file called ```male.json```.&#xD;&#xA;&#xD;&#xA;If this file is in your code somewhere, the error is telling you the problem. It is malformed. Paste the contents of the file into an online validation tool such as [JSONLint][1]. It will tell you what is making it malformed.&#xD;&#xA;&#xD;&#xA;Also, you're passing JSON into ```ObjectLoader.load``` but you don't do anything with the results. Instead try this:&#xD;&#xA;&#xD;&#xA;    var loader = new THREE.ObjectLoader();&#xD;&#xA;    loader.load('somemodel.json', function (object) {&#xD;&#xA;        scene.add(object);&#xD;&#xA;    });&#xD;&#xA;&#xD;&#xA;Check out [the documentation][2] for more information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1]: http://jsonlint.com/&#xD;&#xA;[2]: https://threejs.org/docs/#api/en/loaders/ObjectLoader&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="25988" PostHistoryTypeId="24" PostId="2317" RevisionGUID="b09a81a7-fc3d-437a-8dd9-c62e56dc2068" CreationDate="2020-01-06T03:51:50.203" Comment="Proposed by anonymous approved by 3143 edit id of 505" ContentLicense="CC BY-SA 4.0" />
  <row Id="25989" PostHistoryTypeId="2" PostId="9465" RevisionGUID="4ac531b6-7af9-4a0d-9a75-0cbdf75867a2" CreationDate="2020-01-06T04:50:36.603" UserId="11609" Text="I'm trying to write a raycaster similar to Voxlap, but it's many times slower. I've tried octrees, but the performance gains are marginal- only 10 to 20 percent. I use the algorithm from this site: https://lodev.org/cgtutor/raycasting.html&#xD;&#xA;&#xD;&#xA;The full code: https://pastebin.com/kYs9zs7S&#xD;&#xA;&#xD;&#xA; The raycasting loop:&#xD;&#xA;```    for(int x = 0; x &lt; RESX; x ++) {   &#xD;&#xA;      float cameraX = x/HALFRESX -1;&#xD;&#xA;&#xD;&#xA;      for(int y = 0; y &lt; RESY; y ++) { &#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;        float cameraY = y/HALFRESY -1;//cam vec, -1 to 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        struct Point3D rayd;&#xD;&#xA;        rayd.z = dir.z + plane.z*cameraY;&#xD;&#xA;        rayd.x = dir.x + plane.x*cameraX;&#xD;&#xA;        rayd.y = dir.y + plane.y*cameraX;&#xD;&#xA;&#xD;&#xA;        struct Point3D delta;&#xD;&#xA;        delta.y = fabsf(1/rayd.y);&#xD;&#xA;        delta.x = fabsf(1/rayd.x);&#xD;&#xA;        delta.z = fabsf(1/rayd.z);&#xD;&#xA;&#xD;&#xA;       &#xD;&#xA;        struct pos map;&#xD;&#xA;        map.x = (char)pos.x;&#xD;&#xA;        map.y = (char)pos.y;&#xD;&#xA;        map.z = (char)pos.z; &#xD;&#xA;&#xD;&#xA;        struct pos s;&#xD;&#xA;        struct pos step;&#xD;&#xA;        struct Point3D sdist;&#xD;&#xA;        if(rayd.x &lt; 0) {&#xD;&#xA;          step.x = -1;&#xD;&#xA;          s.x = 1;&#xD;&#xA;          sdist.x = (pos.x - map.x) * delta.x; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.x = 1;&#xD;&#xA;          s.x = 0;&#xD;&#xA;          sdist.x = (map.x + 1 - pos.x) * delta.x; &#xD;&#xA;        }&#xD;&#xA;        if(rayd.y &lt; 0) {&#xD;&#xA;          step.y = -1;&#xD;&#xA;          s.y = 1;&#xD;&#xA;          sdist.y = (pos.y - map.y) * delta.y; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.y = 1;&#xD;&#xA;          s.y = 0;&#xD;&#xA;          sdist.y = (map.y + 1 - pos.y) * delta.y; &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if(rayd.z &lt; 0) {&#xD;&#xA;          step.z = -1;&#xD;&#xA;          s.z = 1;&#xD;&#xA;          sdist.z = (pos.z - map.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;        else {&#xD;&#xA;          step.z = 1;&#xD;&#xA;          s.z = 0;&#xD;&#xA;          sdist.z = (map.z + 1 - pos.z) * delta.z; &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        char side; //either 0 (NS), or 1 (EW), or 2(UD)&#xD;&#xA;        while( !MAP[map.x][map.y][map.z]) {&#xD;&#xA;          if(sdist.y &lt; sdist.x ) {&#xD;&#xA;            if(sdist.y &lt; sdist.z) {&#xD;&#xA;              sdist.y += delta.y;&#xD;&#xA;              map.y += step.y;&#xD;&#xA;              side = 1; // y&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z;&#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            if(sdist.x &lt; sdist.z) {&#xD;&#xA;              sdist.x += delta.x;&#xD;&#xA;              map.x += step.x;&#xD;&#xA;              side = 0; &#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              sdist.z += delta.z;&#xD;&#xA;              map.z += step.z; &#xD;&#xA;              side = 2; &#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;        char blockHit = MAP[map.x][map.y][map.z];&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;#ifdef USE_REFLECTIONS&#xD;&#xA;        bool reflect = false;&#xD;&#xA;reflect:;&#xD;&#xA;        if(blockHit == 6){&#xD;&#xA;          reflect = true;&#xD;&#xA;          if(!side) {&#xD;&#xA;            step.x*=-1;&#xD;&#xA;            sdist.x += delta.x;&#xD;&#xA;            map.x += step.x;&#xD;&#xA;            rayd.x*=-1;&#xD;&#xA;          }&#xD;&#xA;          else if(side == 1) {&#xD;&#xA;            step.y*=-1;&#xD;&#xA;            sdist.y += delta.y;&#xD;&#xA;            map.y += step.y;&#xD;&#xA;            rayd.y*=-1;&#xD;&#xA;          }&#xD;&#xA;          else {&#xD;&#xA;            step.z*=-1;&#xD;&#xA;            sdist.z += delta.z;&#xD;&#xA;            map.z += step.z;&#xD;&#xA;            rayd.z*=-1;&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          while( !MAP[map.x][map.y][map.z]) {&#xD;&#xA;            if(sdist.y &lt; sdist.x ) {&#xD;&#xA;              if(sdist.y &lt; sdist.z) {&#xD;&#xA;                sdist.y += delta.y;&#xD;&#xA;                map.y += step.y;&#xD;&#xA;                side = 1; // y&#xD;&#xA;              }&#xD;&#xA;              else {&#xD;&#xA;                sdist.z += delta.z;&#xD;&#xA;                map.z += step.z;&#xD;&#xA;                side = 2; &#xD;&#xA;              }&#xD;&#xA;            }&#xD;&#xA;            else {&#xD;&#xA;              if(sdist.x &lt; sdist.z) {&#xD;&#xA;                sdist.x += delta.x;&#xD;&#xA;                map.x += step.x;&#xD;&#xA;                side = 0; &#xD;&#xA;              }&#xD;&#xA;              else {&#xD;&#xA;                sdist.z += delta.z;&#xD;&#xA;                map.z += step.z; &#xD;&#xA;                side = 2; &#xD;&#xA;              }&#xD;&#xA;            }&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;        blockHit = MAP[map.x][map.y][map.z];&#xD;&#xA;        }&#xD;&#xA;#endif&#xD;&#xA;        struct Point3D lightDist;&#xD;&#xA;        struct Point3D hit;&#xD;&#xA;&#xD;&#xA;        if(!side) {  // x side hit&#xD;&#xA;&#xD;&#xA;          hit.x = map.x + s.x;&#xD;&#xA;          float relativeHit = hit.x-pos.x;&#xD;&#xA;          hit.y = pos.y + relativeHit/rayd.x*rayd.y;&#xD;&#xA;          hit.z = pos.z + relativeHit/rayd.x*rayd.z;&#xD;&#xA;  &#xD;&#xA;        }&#xD;&#xA;        else if(side == 1) {  // y side hit&#xD;&#xA;&#xD;&#xA;          hit.y = map.y + s.y;&#xD;&#xA;          float relativeHit = hit.y-pos.y;&#xD;&#xA;          hit.x = pos.x + relativeHit/rayd.y*rayd.x;&#xD;&#xA;          hit.z = pos.z + relativeHit/rayd.y*rayd.z;&#xD;&#xA;  &#xD;&#xA;        }&#xD;&#xA;        else {  // z side hit&#xD;&#xA;&#xD;&#xA;          hit.z = map.z + s.z;&#xD;&#xA;          float relativeHit = hit.z-pos.z;&#xD;&#xA;          hit.x = pos.x + relativeHit/rayd.z*rayd.x;&#xD;&#xA;          hit.y = pos.y + relativeHit/rayd.z*rayd.y;&#xD;&#xA;        }&#xD;&#xA;        lightDist.x = light[0][0] - hit.x;  // x&#xD;&#xA;        lightDist.y = light[0][1] - hit.y;  // y&#xD;&#xA;        lightDist.z = light[0][2] - hit.z;  // z&#xD;&#xA;&#xD;&#xA;        double lightdist = sqrt(lightDist.x*lightDist.x + lightDist.y*lightDist.y + lightDist.z*lightDist.z);&#xD;&#xA;        if(lightdist &gt; 32) {voxelColour = 32;}&#xD;&#xA;        else if(lightdist &gt; 4)  voxelColour = 1024/lightdist;&#xD;&#xA;        else voxelColour = 255;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#ifdef USE_REFLECTIONS&#xD;&#xA;        if(reflect) voxelColour/=1.2;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;        void drawPixel( Uint32 colour) {&#xD;&#xA;          pixels[y][x] = colour;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if(blockHit &lt;3) drawPixel(0x010101*voxelColour);&#xD;&#xA;        else if(blockHit == 3) drawPixel(voxelColour);&#xD;&#xA;        else if(blockHit == 4) drawPixel(0x10000*voxelColour);&#xD;&#xA;#ifdef USE_REFLECTIONS&#xD;&#xA;        else if(blockHit == 6) goto reflect;&#xD;&#xA;#endif&#xD;&#xA;        else drawPixel(0x100*voxelColour);&#xD;&#xA;         &#xD;&#xA;      }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="25990" PostHistoryTypeId="1" PostId="9465" RevisionGUID="4ac531b6-7af9-4a0d-9a75-0cbdf75867a2" CreationDate="2020-01-06T04:50:36.603" UserId="11609" Text="Why is my raycaster so slow?" ContentLicense="CC BY-SA 4.0" />
  <row Id="25991" PostHistoryTypeId="3" PostId="9465" RevisionGUID="4ac531b6-7af9-4a0d-9a75-0cbdf75867a2" CreationDate="2020-01-06T04:50:36.603" UserId="11609" Text="|raytracing|c++|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="25992" PostHistoryTypeId="50" PostId="8757" RevisionGUID="8480eedd-835c-4d7c-8ae7-5990f23b19c3" CreationDate="2020-01-06T08:01:55.297" UserId="-1" />
  <row Id="25993" PostHistoryTypeId="2" PostId="9466" RevisionGUID="c9019ee3-6547-411c-9396-d71e5eb13405" CreationDate="2020-01-06T09:28:40.417" UserId="209" Text="*Disclaimer: I've only skimmed through the code.*&#xD;&#xA;To be honest, the best thing to do would be to use a  profiler on your code to identify what actually is costing CPU cycles.&#xD;&#xA;&#xD;&#xA;BTW: the following looks a little 'odd'&#xD;&#xA;```&#xD;&#xA;        rayd.z = dir.z + plane.z*cameraY;&#xD;&#xA;        rayd.x = dir.x + plane.x*cameraX;&#xD;&#xA;        rayd.y = dir.y + plane.y*cameraX;&#xD;&#xA;```&#xD;&#xA;Do you really intend to use cameraX twice? I've not really thought about it but it just looks suspicious.&#xD;&#xA;&#xD;&#xA;Having said that, some operations are more expensive than others - e.g. floating point division and sqrt.&#xD;&#xA;For example, in...&#xD;&#xA;```&#xD;&#xA; double lightdist = sqrt(lightDist.x*lightDist.x + lightDist.y*lightDist.y + lightDist.z*lightDist.z);&#xD;&#xA;        if(lightdist &gt; 32) {voxelColour = 32;}&#xD;&#xA;        else if(lightdist &gt; 4)  voxelColour = 1024/lightdist;&#xD;&#xA;        else voxelColour = 255;&#xD;&#xA;```&#xD;&#xA;...it doesn't look to me like you always need to compute the sqrt in 2 of the branches. Perhaps instead, just keep the square of the distance and compare against SQ(32), SQ(4) etc.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26007" PostHistoryTypeId="2" PostId="9470" RevisionGUID="260650af-2021-4608-83b7-7a4f008b6dfd" CreationDate="2020-01-07T03:55:38.967" UserId="32" Text="The new C interface for `glslang` is coming.&#xD;&#xA;&#xD;&#xA;https://github.com/KhronosGroup/glslang/pull/2038&#xD;&#xA;&#xD;&#xA;Here is a way how to use it:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    const char* shaderCodeVertex = ...;&#xD;&#xA;    &#xD;&#xA;    const glslang_input_t input =&#xD;&#xA;    {&#xD;&#xA;    	.language = GLSLANG_SOURCE_GLSL,&#xD;&#xA;    	.stage = GLSLANG_STAGE_VERTEX,&#xD;&#xA;    	.client = GLSLANG_CLIENT_VULKAN,&#xD;&#xA;    	.client_version = GLSLANG_TARGET_VULKAN_1_1,&#xD;&#xA;    	.target_language = GLSLANG_TARGET_SPV,&#xD;&#xA;    	.target_language_version = GLSLANG_TARGET_SPV_1_3,&#xD;&#xA;    	.code = shaderCodeVertex,&#xD;&#xA;    	.default_version = 100,&#xD;&#xA;    	.default_profile = GLSLANG_NO_PROFILE,&#xD;&#xA;    	.force_default_version_and_profile = false,&#xD;&#xA;    	.forward_compatible = false,&#xD;&#xA;    	.messages = GLSLANG_MSG_DEFAULT_BIT,&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    glslang_initialize_process();&#xD;&#xA;    &#xD;&#xA;    glslang_shader_t* shader = glslang_shader_create( &amp;input );&#xD;&#xA;    &#xD;&#xA;    if ( !glslang_shader_preprocess(shader, &amp;input) )&#xD;&#xA;    {&#xD;&#xA;    	// use glslang_shader_get_info_log() and glslang_shader_get_info_debug_log()&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if ( !glslang_shader_parse(shader, &amp;input) )&#xD;&#xA;    {&#xD;&#xA;    	// use glslang_shader_get_info_log() and glslang_shader_get_info_debug_log()&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glslang_program_t* program = glslang_program_create();&#xD;&#xA;    glslang_program_add_shader( program, shader );&#xD;&#xA;    &#xD;&#xA;    if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT))&#xD;&#xA;    {&#xD;&#xA;    	// use glslang_program_get_info_log() and glslang_program_get_info_debug_log();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glslang_program_SPIRV_generate( program, input.stage );&#xD;&#xA;    &#xD;&#xA;    if ( glslang_program_SPIRV_get_messages(program) )&#xD;&#xA;    {&#xD;&#xA;    	printf(&quot;%s&quot;, glslang_program_SPIRV_get_messages(program));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glslang_shader_delete( shader );&#xD;&#xA;    &#xD;&#xA;    const VkShaderModuleCreateInfo ci =&#xD;&#xA;    {&#xD;&#xA;    	.sType    = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,&#xD;&#xA;    	.codeSize = glslang_program_SPIRV_get_size(program) * sizeof(unsigned int),&#xD;&#xA;    	.pCode    = glslang_program_SPIRV_get_ptr(program)&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    VkResult result = vkCreateShaderModule(device, &amp;ci, nullptr, ...);&#xD;&#xA;    &#xD;&#xA;    glslang_program_delete( program );&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26008" PostHistoryTypeId="2" PostId="9471" RevisionGUID="aecac7c8-1715-4066-b155-ea838549caba" CreationDate="2020-01-07T05:20:49.280" UserId="7057" Text="&gt; Is it reasonable to expect the image of the described scene to be &quot;in grayscale&quot;? If so, do light intensity spectra indeed are required to be multiplied by D65 spectrum? &#xD;&#xA;&#xD;&#xA;My expectation from a physically-based spectral rendered is that it would&#xD;&#xA;&#xD;&#xA;1. compute the physical spectra&#xD;&#xA;2. use the CIE color matching functions to relate that to a quantified color space (eg CIEXYZ)&#xD;&#xA;3. convert that into the destination color space.&#xD;&#xA;&#xD;&#xA;D65 shall not appear anywhere till step 3, and only if we actually render into sRGB (or similar).&#xD;&#xA;&#xD;&#xA;A flat spectra translates to `XYZ = (0.33, 0.33, 0.33)`, which is `RGB = (1.20, 0.95, 0.91)` prior to gamma compression. So the &quot;red tint&quot; is the expected result following the above procedure.&#xD;&#xA;&#xD;&#xA;Don't know why Mitsuba would have such a 'feature'.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26011" PostHistoryTypeId="2" PostId="9472" RevisionGUID="c80219e4-3e80-4591-b069-4fb30131afad" CreationDate="2020-01-07T08:35:28.917" UserId="11696" Text="I'm looking for a format where I could store a triangle mesh and multiple textures into a single file. Most formats only reference an external file for textures. I found that the FBX format should support this, but I need something with an open-source C++ library. And by single file I don't mean putting it into a single archive, I don't want users to have to deal with that.&#xD;&#xA;&#xD;&#xA;I don't need anything fancy, no animation, no shading, nothing. Just triangles + textures. Ideally this would be a binary format (or at least the textures would be stored in binary inside the file). This should be some well supported format, so that tools exist to open it. I'm currently looking at X3D but I can't figure out if it can include the textures directly." ContentLicense="CC BY-SA 4.0" />
  <row Id="26012" PostHistoryTypeId="1" PostId="9472" RevisionGUID="c80219e4-3e80-4591-b069-4fb30131afad" CreationDate="2020-01-07T08:35:28.917" UserId="11696" Text="Saving a mesh and textures into a single file" ContentLicense="CC BY-SA 4.0" />
  <row Id="26013" PostHistoryTypeId="3" PostId="9472" RevisionGUID="c80219e4-3e80-4591-b069-4fb30131afad" CreationDate="2020-01-07T08:35:28.917" UserId="11696" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26014" PostHistoryTypeId="2" PostId="9473" RevisionGUID="20c76072-d6de-4e3c-b966-b8f272820bb8" CreationDate="2020-01-07T11:12:53.437" UserId="2479" Text="[glTF][1] is capable if embedding both geometry and texture data in a single file. It also has binary version (*.glb). There are several open-source savers/loaders, one of them being header-only [tinygltf][2] by Syoyo Fujita.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF/blob/master/README.md&#xD;&#xA;  [2]: https://github.com/syoyo/tinygltf" ContentLicense="CC BY-SA 4.0" />
  <row Id="26015" PostHistoryTypeId="2" PostId="9474" RevisionGUID="15e960a8-1d19-41a9-b725-21ded9d9f7c6" CreationDate="2020-01-07T12:19:42.683" UserId="9254" Text="In the Multiplexed Metropolis Light Transport implementation of the book *Physically Based Rendering*, the proposal samples are generated by the [Primary Sample Space Sampler](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#PrimarySampleSpaceSampler) `MLTSampler`.&#xD;&#xA;&#xD;&#xA;I'm not sure if I really understand what the authors mean in the following paragraph:&#xD;&#xA;&#xD;&#xA;&gt; In the context of MLT, the resulting sequence of sample requests creates a mapping between components $X$ of and vertices on the camera or light subpath. With the process described above, the components $X_0,\ldots,X_n$ determine the camera subpath (for some $n\in\mathbb N_0$), and the remaining values $X_{n+1},\ldots,X_m$ determine the light subpath. If the camera subpath requires a different number of samples after a perturbation (e.g., because the random walk produced fewer vertices), then there is a shift in the assignment of primary sample space components to the light subpath. This leads to an unintended large-scale modification to the light path.&#xD;&#xA;&#xD;&#xA;Does this mean that even for a fixed strategy with $n\in\mathbb N_0$ vertices on the camera subpath, the number of random numbers needed to generate such a subpath may vary? Or do they mean that the shift in the assignment is happening only when we switch to an other strategy?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26016" PostHistoryTypeId="1" PostId="9474" RevisionGUID="15e960a8-1d19-41a9-b725-21ded9d9f7c6" CreationDate="2020-01-07T12:19:42.683" UserId="9254" Text="In bidirectional path tracing, is a camera subpath with $n$ vertices determined by a fixed number of random numbers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26017" PostHistoryTypeId="3" PostId="9474" RevisionGUID="15e960a8-1d19-41a9-b725-21ded9d9f7c6" CreationDate="2020-01-07T12:19:42.683" UserId="9254" Text="|raytracing|pathtracing|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26018" PostHistoryTypeId="2" PostId="9475" RevisionGUID="bbb90e90-8606-4e31-a664-e53f755d5d4b" CreationDate="2020-01-07T14:07:53.597" UserId="11699" Text="I'm trying to implement an hybrid renderer based on Vulkan extension VK_NV_ray_tracing. Basically, the rasterizer compute the albedo and depth map of the scene. Then I try to compute the distance from the depth buffer so that I can send a shadow ray from a raygen program to compute direct lighting. I linearize the depth to obtain a correct distance value from the depth buffer. What I am doing is this :&#xD;&#xA;```&#xD;&#xA;const vec2 texcoord = vec2(gl_LaunchIDNV) / vec2(gl_LaunchSizeNV);&#xD;&#xA;const double z_b = texture(depthBuffer, texcoord).x;&#xD;&#xA;const double depth = (2.0 * near * far) / (far + near - z_b * (far - near));&#xD;&#xA;```&#xD;&#xA;I am then computing the ray position and direction&#xD;&#xA;```&#xD;&#xA;const vec2 pixelCenter = vec2(gl_LaunchIDNV.xy) + vec2(0.5);&#xD;&#xA;const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeNV.xy);&#xD;&#xA;const vec2 d = inUV * 2.0 - 1.0;&#xD;&#xA;const vec4 camFront  = cam.viewInverse * vec4(0, 0, 1, 0);&#xD;&#xA;const vec4 camPos    = cam.viewInverse * vec4(0, 0, 0, 1);&#xD;&#xA;const vec4 camTarget = cam.projInverse * vec4(d.x, d.y, 1, 1);&#xD;&#xA;const vec4 camDir    = cam.viewInverse * vec4(normalize(camTarget.xyz), 0);&#xD;&#xA;```&#xD;&#xA;And the final ray position is then set using the depth I just computed.&#xD;&#xA;```&#xD;&#xA;const vec3 pos = camPos.xyz + camDir.xyz * float(depth);&#xD;&#xA;```&#xD;&#xA;The problem here is that the depth seems incorrect because shadows tend to curve at the edges of the screen and do not fit the geometry. &#xD;&#xA;[![bended shadows][1]][1]&#xD;&#xA;I think this might be because of the depth buffer value that does not represent the distance from the origin of the camera but from the near plane, which would explain the problem, but I am not sure of that.&#xD;&#xA;&#xD;&#xA;Any idea ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CgIwK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26019" PostHistoryTypeId="1" PostId="9475" RevisionGUID="bbb90e90-8606-4e31-a664-e53f755d5d4b" CreationDate="2020-01-07T14:07:53.597" UserId="11699" Text="Retrieve real distance from depth buffer for shadow ray (vulkan hybrid rendering)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26020" PostHistoryTypeId="3" PostId="9475" RevisionGUID="bbb90e90-8606-4e31-a664-e53f755d5d4b" CreationDate="2020-01-07T14:07:53.597" UserId="11699" Text="|raytracing|glsl|vulkan|shadow|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26021" PostHistoryTypeId="2" PostId="9476" RevisionGUID="e1d0e130-6a76-49e5-81e7-e1a108122c58" CreationDate="2020-01-07T16:03:04.170" UserId="6588" Text="For a fixed strategy, you can end up consuming a different number of samples depending on your mutation. This can happen for at least two reasons. If your perturbation changes some material along the path to, say, a multi-lobe BSDF, you would need more samples to account for the lobe choice. This would shift everything by the number of extra samples used. If your ray eventually escapes the scene as you are tracing your mutation, or it hits a light source prematurely, you would use fewer samples. In these cases, you'd keep the subpart of the path that is relevant to avoid discarding the full state.&#xD;&#xA;&#xD;&#xA;One way of mitigating this issue in practice is to separate the two random number vectors for the camera and light subpaths and always mutate _all_ dimensions of the unit hypercube $\mathcal{U}^{o(k)}$, regardless if they are being used or not by the mutation. This doesn't remove the shift caused by BSDF changes (which is unavoidable) but at least you're not spilling your samples between camera and light subpaths.&#xD;&#xA;&#xD;&#xA;Note that changing the strategy can also lead to an undesired rippling effect as primary samples will be used to perform a slightly different task (i.e. tracing a different strategy). This can be handled by introducing inverse mappings to preserve the geometry of the path, which is what is done by [Reversible Jump MLT](https://dl.acm.org/doi/10.1145/3132704).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26022" PostHistoryTypeId="5" PostId="9476" RevisionGUID="8c61e1ad-a78f-4071-a703-a08cfd23e724" CreationDate="2020-01-07T16:26:45.430" UserId="6588" Comment="Correct claim on subpart recycling" Text="For a fixed strategy, you can end up consuming a different number of samples depending on your mutation. This can happen for at least two reasons. If your perturbation changes some material along the path to, say, a multi-lobe BSDF, you would need more samples to account for the lobe choice. This would shift everything by the number of extra samples used. If your ray eventually escapes the scene as you are tracing your mutation, or it hits a light source prematurely, you would use fewer samples. In these cases, you'd have to reject this proposal automatically.&#xD;&#xA;&#xD;&#xA;One way of mitigating this issue in practice is to separate the two random number vectors for the camera and light subpaths and always mutate _all_ dimensions of the unit hypercube $\mathcal{U}^{o(k)}$, regardless if they are being used or not by the mutation. This doesn't remove the shift caused by BSDF changes (which is unavoidable) but at least you're not spilling your samples between camera and light subpaths.&#xD;&#xA;&#xD;&#xA;Note that changing the strategy can also lead to an undesired rippling effect as primary samples will be used to perform a slightly different task (i.e. tracing a different strategy). This can be handled by introducing inverse mappings to preserve the geometry of the path, which is what is done by [Reversible Jump MLT](https://dl.acm.org/doi/10.1145/3132704).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26023" PostHistoryTypeId="52" PostId="9472" RevisionGUID="66c39469-c860-49d5-8b55-3447e1728d0e" CreationDate="2020-01-07T16:46:36.673" />
  <row Id="26024" PostHistoryTypeId="5" PostId="9466" RevisionGUID="2aad468d-68aa-4274-93a2-8962065a2e6d" CreationDate="2020-01-07T18:29:20.140" UserId="209" Comment="reordered the text to improve logical flow" Text="*Disclaimer: I've only skimmed through the code.*&#xD;&#xA;&#xD;&#xA;To be honest, the best thing to do would be to use a  profiler on your code to identify what actually is costing CPU cycles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Having said that, some operations are more expensive than others - e.g. floating point division and sqrt.&#xD;&#xA;For example, in...&#xD;&#xA;```&#xD;&#xA; double lightdist = sqrt(lightDist.x*lightDist.x + lightDist.y*lightDist.y + lightDist.z*lightDist.z);&#xD;&#xA;        if(lightdist &gt; 32) {voxelColour = 32;}&#xD;&#xA;        else if(lightdist &gt; 4)  voxelColour = 1024/lightdist;&#xD;&#xA;        else voxelColour = 255;&#xD;&#xA;```&#xD;&#xA;...it doesn't look to me like you always need to compute the sqrt in 2 of the branches. Perhaps instead, just keep the square of the distance and compare against SQ(32), SQ(4) etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;BTW: the following looks a little 'odd'&#xD;&#xA;```&#xD;&#xA;        rayd.z = dir.z + plane.z*cameraY;&#xD;&#xA;        rayd.x = dir.x + plane.x*cameraX;&#xD;&#xA;        rayd.y = dir.y + plane.y*cameraX;&#xD;&#xA;```&#xD;&#xA;Do you really intend to use cameraX twice? I've not really thought about it but it just looks suspicious." ContentLicense="CC BY-SA 4.0" />
  <row Id="26025" PostHistoryTypeId="50" PostId="9409" RevisionGUID="8070b986-6803-497d-9c2a-a0d6c0d97a7a" CreationDate="2020-01-07T21:01:55.207" UserId="-1" />
  <row Id="26026" PostHistoryTypeId="50" PostId="9405" RevisionGUID="c2d7b778-6b27-4818-a7f2-6e2bf3ae3b30" CreationDate="2020-01-07T23:00:45.083" UserId="-1" />
  <row Id="26029" PostHistoryTypeId="5" PostId="9475" RevisionGUID="1be8be3f-de4a-4f5f-80d4-48be077e724d" CreationDate="2020-01-08T18:47:34.337" UserId="6" Comment="deleted 2 characters in body" Text="I'm trying to implement an hybrid renderer based on Vulkan extension VK_NV_ray_tracing. Basically, the rasterizer compute the albedo and depth map of the scene. Then I try to compute the distance from the depth buffer so that I can send a shadow ray from a raygen program to compute direct lighting. I linearize the depth to obtain a correct distance value from the depth buffer. What I am doing is this:&#xD;&#xA;```&#xD;&#xA;const vec2 texcoord = vec2(gl_LaunchIDNV) / vec2(gl_LaunchSizeNV);&#xD;&#xA;const double z_b = texture(depthBuffer, texcoord).x;&#xD;&#xA;const double depth = (2.0 * near * far) / (far + near - z_b * (far - near));&#xD;&#xA;```&#xD;&#xA;I am then computing the ray position and direction&#xD;&#xA;```&#xD;&#xA;const vec2 pixelCenter = vec2(gl_LaunchIDNV.xy) + vec2(0.5);&#xD;&#xA;const vec2 inUV = pixelCenter / vec2(gl_LaunchSizeNV.xy);&#xD;&#xA;const vec2 d = inUV * 2.0 - 1.0;&#xD;&#xA;const vec4 camFront  = cam.viewInverse * vec4(0, 0, 1, 0);&#xD;&#xA;const vec4 camPos    = cam.viewInverse * vec4(0, 0, 0, 1);&#xD;&#xA;const vec4 camTarget = cam.projInverse * vec4(d.x, d.y, 1, 1);&#xD;&#xA;const vec4 camDir    = cam.viewInverse * vec4(normalize(camTarget.xyz), 0);&#xD;&#xA;```&#xD;&#xA;And the final ray position is then set using the depth I just computed.&#xD;&#xA;```&#xD;&#xA;const vec3 pos = camPos.xyz + camDir.xyz * float(depth);&#xD;&#xA;```&#xD;&#xA;The problem here is that the depth seems incorrect because shadows tend to curve at the edges of the screen and do not fit the geometry. &#xD;&#xA;[![bended shadows][1]][1]&#xD;&#xA;I think this might be because of the depth buffer value that does not represent the distance from the origin of the camera but from the near plane, which would explain the problem, but I am not sure of that.&#xD;&#xA;&#xD;&#xA;Any idea?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CgIwK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26030" PostHistoryTypeId="2" PostId="9478" RevisionGUID="ae658cd2-75d9-424d-8c95-b8e4abb090c7" CreationDate="2020-01-08T18:57:29.487" UserId="7462" Text="A literal triangle, as in 3 vertices connected by 3 edges.&#xD;&#xA;&#xD;&#xA;They are the basic building block for any other shape, any polygon can be represented with a set of triangles (called triangulation)." ContentLicense="CC BY-SA 4.0" />
  <row Id="26031" PostHistoryTypeId="2" PostId="9479" RevisionGUID="72948e0d-8095-40fa-8f19-062ebf5542e7" CreationDate="2020-01-09T10:51:40.013" UserId="137" Text="You have a lot of if condition affecting different components of various `Point3D`. If conditions, especially hard to predict ones are very expensive, instead look into using SIMD to remove most of the conditions by replacing the false branches with identity operations.&#xD;&#xA;&#xD;&#xA;for example      &#xD;&#xA;&#xD;&#xA;      if(!side) {&#xD;&#xA;        step.x*=-1;&#xD;&#xA;        sdist.x += delta.x;&#xD;&#xA;        map.x += step.x;&#xD;&#xA;        rayd.x*=-1;&#xD;&#xA;      }&#xD;&#xA;      else if(side == 1) {&#xD;&#xA;        step.y*=-1;&#xD;&#xA;        sdist.y += delta.y;&#xD;&#xA;        map.y += step.y;&#xD;&#xA;        rayd.y*=-1;&#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        step.z*=-1;&#xD;&#xA;        sdist.z += delta.z;&#xD;&#xA;        map.z += step.z;&#xD;&#xA;        rayd.z*=-1;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;can be replaced with&#xD;&#xA;&#xD;&#xA;    step = simd_xor(step, negateTable[side]); //negate can be done by xoring the sign bit&#xD;&#xA;    sdist = simd_add(sdist, simd_and(delta, addMask[side]));&#xD;&#xA;    map = simd_add(map, simd_and(step, addMask[side]));&#xD;&#xA;    rayd= simd_xor(step, negateTable[side]);" ContentLicense="CC BY-SA 4.0" />
  <row Id="26032" PostHistoryTypeId="5" PostId="9466" RevisionGUID="4d2695a9-a82c-4790-a23b-6ab49dd93fe8" CreationDate="2020-01-09T14:34:36.260" UserId="209" Comment="added 4 characters in body" Text="*Disclaimer: I've only skimmed through the code.*&#xD;&#xA;&#xD;&#xA;To be honest, the best thing to do would be to **use a  profiler on your code** to identify what actually is costing CPU cycles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Having said that, some operations are more expensive than others - e.g. floating point division and sqrt.&#xD;&#xA;For example, in...&#xD;&#xA;```&#xD;&#xA; double lightdist = sqrt(lightDist.x*lightDist.x + lightDist.y*lightDist.y + lightDist.z*lightDist.z);&#xD;&#xA;        if(lightdist &gt; 32) {voxelColour = 32;}&#xD;&#xA;        else if(lightdist &gt; 4)  voxelColour = 1024/lightdist;&#xD;&#xA;        else voxelColour = 255;&#xD;&#xA;```&#xD;&#xA;...it doesn't look to me like you always need to compute the sqrt in 2 of the branches. Perhaps instead, just keep the square of the distance and compare against SQ(32), SQ(4) etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;BTW: the following looks a little 'odd'&#xD;&#xA;```&#xD;&#xA;        rayd.z = dir.z + plane.z*cameraY;&#xD;&#xA;        rayd.x = dir.x + plane.x*cameraX;&#xD;&#xA;        rayd.y = dir.y + plane.y*cameraX;&#xD;&#xA;```&#xD;&#xA;Do you really intend to use cameraX twice? I've not really thought about it but it just looks suspicious." ContentLicense="CC BY-SA 4.0" />
  <row Id="26034" PostHistoryTypeId="2" PostId="9480" RevisionGUID="c8a2c507-a5a9-4960-a586-08c9a87b5df2" CreationDate="2020-01-09T15:12:03.967" UserId="209" Text="To expand on @Makogan and @lightxbulb's answers/comments: &#xD;&#xA;&#xD;&#xA;There are several reasons for using triangles as the basic primitive.&#xD;&#xA;&#xD;&#xA; 1. (Non-degenerate) triangles are guaranteed to be *planar*. This means that an individual single triangle cannot obscure itself (in terms of hidden surface removal) and thus cannot  form an internal silhouette edge (when being rendered)  nor, say, cast a shadow on itself.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is also means that when scan converting a triangle, for each pixel, each attribute (e.g. depth, texture coordinate, shading) can only take a 'single' value.&#xD;&#xA; 2. They are guaranteed to be convex. Scan converting/filling convex polygons is *far* simpler than a general polygon filling algorithm&#xD;&#xA;&#xD;&#xA; 3. An arbitrary polygonal mesh can always be decomposed into triangles - you can't do the same with quads.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you are concerned about the 'cost' in vertices of supplying two triangles to represent your quad, remember that APIs (and HW) have triangle strips/fans/indexed representations which will, in most cases, eliminate the additional vertex overheads.&#xD;&#xA;There is thus little point in adding additional hardware to support 'fast' quad rendering as (a) it wouldn't get used much and (b) is extremely unlikely to be the bottleneck in rendering!&#xD;&#xA;&#xD;&#xA;Having said all this, the *original* Series 1 PowerVR graphics chips (eg PCX1 and PCX2) used a lower-level primitive (the half plane) from which N-sided convex polygons (*or in fact N-sided polyhedra - e.g a entire cube was, at most, 6 half-planes*) could be constructed. IIRC the driver tried to detect if two consecutive triangles actually formed a planar quad and then replaced them with a more efficient representation.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26035" PostHistoryTypeId="2" PostId="9481" RevisionGUID="c2a772b4-c12a-4097-b677-523fef7fd1d4" CreationDate="2020-01-09T20:53:47.880" UserId="11709" Text="I am interested in Path Tracing, I currently follow the Ray Tracing in a weekend book. When implementing the metal material, I get a strange artifact on the edge of the sphere that does not appear in the book's result. I might be caused by the fuzz parameter, when it's set to zero, it does not occur.&#xD;&#xA;&#xD;&#xA;I wrote my code in Rust&#xD;&#xA;&#xD;&#xA;Screenshots:  &#xD;&#xA;Fuzziness set to 0.0  &#xD;&#xA;https://imgur.com/F1AiW02&#xD;&#xA;&#xD;&#xA;Fuzziness set to 0.5  &#xD;&#xA;https://imgur.com/Bxn28Tk&#xD;&#xA;&#xD;&#xA;As you can see there is a white outline-like artifact at the edge of the sphere.  &#xD;&#xA;I am not sure what causes that...&#xD;&#xA;&#xD;&#xA;The full code is available here: https://github.com/AregevDev/pathtracer  &#xD;&#xA;Some highlights:&#xD;&#xA;&#xD;&#xA;My random point function&#xD;&#xA;```rust&#xD;&#xA;fn random_double() -&gt; f64 {&#xD;&#xA;    let mut rnd = rand::thread_rng();&#xD;&#xA;    rnd.gen::&lt;f64&gt;()&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Generate a random point in the unit sphere&#xD;&#xA;fn random_in_unit_sphere() -&gt; Vector3 {&#xD;&#xA;    loop {&#xD;&#xA;        let p =&#xD;&#xA;            2.0 * Vector3::new(&#xD;&#xA;                random_double() as f32,&#xD;&#xA;                random_double() as f32,&#xD;&#xA;                random_double() as f32,&#xD;&#xA;            ) - Vector3::new(1.0, 1.0, 1.0);&#xD;&#xA;        if p.squared_length() &lt;= 1.0 {&#xD;&#xA;            return p;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;My material scatter function, I match the material type and calculate the rays accordingly:&#xD;&#xA;```rust&#xD;&#xA;pub fn scatter(&amp;self, ray_in: Ray, record: &amp;HitRecord) -&gt; Option&lt;Scatter&gt; {&#xD;&#xA;        match *self {&#xD;&#xA;            Material::Lambertian { albedo } =&gt; {&#xD;&#xA;                let mut scattered = Scatter::default();&#xD;&#xA;                let target = record.p + record.normal + random_in_unit_sphere();&#xD;&#xA;&#xD;&#xA;                scattered.color = albedo;&#xD;&#xA;                scattered.ray = Some(Ray::new(record.p, target - record.p));&#xD;&#xA;&#xD;&#xA;                Some(scattered)&#xD;&#xA;            }&#xD;&#xA;            Material::Metal { albedo, fuzz } =&gt; {&#xD;&#xA;                let mut scattered = Scatter::default();&#xD;&#xA;                let reflected = ray_in.direction.normalize().reflect(record.normal);&#xD;&#xA;                let new_fuzz = fuzz.min(1.0);&#xD;&#xA;&#xD;&#xA;                scattered.color = albedo;&#xD;&#xA;                scattered.ray = Some(Ray::new(&#xD;&#xA;                    record.p,&#xD;&#xA;                    reflected + new_fuzz * random_in_unit_sphere(),&#xD;&#xA;                ));&#xD;&#xA;&#xD;&#xA;                if scattered.ray.unwrap().direction.dot(record.normal) &gt; 0.0 {&#xD;&#xA;                    Some(scattered)&#xD;&#xA;                } else {&#xD;&#xA;                    None&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            _ =&gt; None,&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="26036" PostHistoryTypeId="1" PostId="9481" RevisionGUID="c2a772b4-c12a-4097-b677-523fef7fd1d4" CreationDate="2020-01-09T20:53:47.880" UserId="11709" Text="Ray Tracing -Weird Edge Artifact" ContentLicense="CC BY-SA 4.0" />
  <row Id="26037" PostHistoryTypeId="3" PostId="9481" RevisionGUID="c2a772b4-c12a-4097-b677-523fef7fd1d4" CreationDate="2020-01-09T20:53:47.880" UserId="11709" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26038" PostHistoryTypeId="5" PostId="9480" RevisionGUID="98973464-f8b0-4856-ad55-042d0cac268d" CreationDate="2020-01-10T06:28:17.317" UserId="38" Comment="nitpicking suggestion" Text="To expand on @Makogan and @lightxbulb's answers/comments: &#xD;&#xA;&#xD;&#xA;There are several reasons for using triangles as the basic primitive.&#xD;&#xA;&#xD;&#xA; 1. (Non-degenerate) triangles are guaranteed to be *planar*. This means that an individual single triangle cannot obscure itself (in terms of hidden surface removal) and thus cannot  form an internal silhouette edge (when being rendered)  nor, say, cast a shadow on itself.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is also means that when scan converting a triangle, for each pixel, each attribute (e.g. depth, texture coordinate, shading) can only take a 'single' value.&#xD;&#xA; 2. They are guaranteed to be convex. Scan converting/filling convex polygons is *far* simpler than a general polygon filling algorithm&#xD;&#xA;&#xD;&#xA; 3. An arbitrary polygonal mesh can always be easily decomposed into triangles - you can't do the same with quads.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you are concerned about the 'cost' in vertices of supplying two triangles to represent your quad, remember that APIs (and HW) have triangle strips/fans/indexed representations which will, in most cases, eliminate the additional vertex overheads.&#xD;&#xA;There is thus little point in adding additional hardware to support 'fast' quad rendering as (a) it wouldn't get used much and (b) is extremely unlikely to be the bottleneck in rendering!&#xD;&#xA;&#xD;&#xA;Having said all this, the *original* Series 1 PowerVR graphics chips (eg PCX1 and PCX2) used a lower-level primitive (the half plane) from which N-sided convex polygons (*or in fact N-sided polyhedra - e.g a entire cube was, at most, 6 half-planes*) could be constructed. IIRC the driver tried to detect if two consecutive triangles actually formed a planar quad and then replaced them with a more efficient representation.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26039" PostHistoryTypeId="5" PostId="9480" RevisionGUID="64a6a6a7-6bb4-46b3-b0c3-a5c2157f716f" CreationDate="2020-01-10T08:45:30.923" UserId="209" Comment="added 374 characters in body" Text="To expand on @Makogan and @lightxbulb's answers/comments: &#xD;&#xA;&#xD;&#xA;There are several reasons for using triangles as the basic primitive.&#xD;&#xA;&#xD;&#xA; 1. (Non-degenerate) triangles are guaranteed to be *planar*. This means that an individual single triangle cannot obscure itself (in terms of hidden surface removal) and thus cannot  form an internal silhouette edge (when being rendered)  nor, say, cast a shadow on itself.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is also means that when scan converting a triangle, for each pixel, each attribute (e.g. depth, texture coordinate, shading) can only take a 'single' value.&#xD;&#xA; 2. They are guaranteed to be convex. Scan converting/filling convex polygons is *far* simpler than a general polygon filling algorithm&#xD;&#xA;&#xD;&#xA; 3. An arbitrary polygonal mesh can always be easily decomposed into triangles - you can't do the same with (true) quads...&lt;br/&gt;&#xD;&#xA;[**Update**: As @joojaa pointed out, you could use a degenerate quad to create a triangle - i.e. either collapse an edge by repeating a vertex *or* (but this may have other problems due to precision) making 3 of the vertices collinear].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you are concerned about the 'cost' in vertices of supplying two triangles to represent your quad, remember that APIs (and HW) have triangle strips/fans/indexed representations which will, in most cases, eliminate the additional vertex overheads.&#xD;&#xA;There is thus little point in adding additional hardware to support 'fast' quad rendering as (a) it wouldn't get used much and (b) is extremely unlikely to be the bottleneck in rendering!&#xD;&#xA;&#xD;&#xA;Having said all this, the *original* Series 1 PowerVR graphics chips (eg PCX1 and PCX2) used a lower-level primitive (the half plane) from which N-sided convex polygons (*or in fact N-sided polyhedra - e.g a entire cube was, at most, 6 half-planes*) could be constructed. IIRC the driver tried to detect if two consecutive triangles actually formed a planar quad and then replaced them with a more efficient representation. Further, for a quad to be &quot;planar&quot; not only was it geometrically flat but the texture coordinates also had to be 'flat'. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26040" PostHistoryTypeId="5" PostId="9480" RevisionGUID="e4b4e8ec-45ef-4d09-9fcd-e6f101fadc95" CreationDate="2020-01-10T08:53:28.203" UserId="209" Comment="added 374 characters in body" Text="To expand on @Makogan and @lightxbulb's answers/comments: &#xD;&#xA;&#xD;&#xA;There are several reasons for using triangles as the basic primitive.&#xD;&#xA;&#xD;&#xA; 1. (Non-degenerate) triangles are guaranteed to be *planar*. This means that an individual single triangle cannot obscure itself (in terms of hidden surface removal) and thus cannot  form an internal silhouette edge (when being rendered)  nor, say, cast a shadow on itself.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is also means that when scan converting a triangle, for each pixel, each attribute (e.g. depth, texture coordinate, shading) can only take a 'single' value.&#xD;&#xA; 2. They are guaranteed to be convex. Scan converting/filling convex polygons is *far* simpler than a general polygon filling algorithm&#xD;&#xA;&#xD;&#xA; 3. An arbitrary polygonal mesh can always be *easily* decomposed into triangles&lt;br/&gt;&#xD;&#xA;[**Update**: As @joojaa pointed out, you could still use quads by either&lt;br/&gt;&#xD;&#xA;**a)** Noting that any triangle can be represented as 3 quads by the addition of four more vertices - one at the centre of the triangle and one on each edge). You need to be careful, though, not to [introduce T-Junctions][1]. *or*&lt;br/&gt;&#xD;&#xA;**b)** Using degenerate quad to create a triangle - i.e. either collapse an edge by repeating a vertex *or* (but this may have other problems due to precision) making 3 of the vertices collinear&#xD;&#xA;Neither seems, to me at least, as particularly attractive].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you are concerned about the 'cost' in vertices of supplying two triangles to represent your quad, remember that APIs (and HW) have triangle strips/fans/indexed representations which will, in most cases, eliminate the additional vertex overheads.&#xD;&#xA;There is thus little point in adding additional hardware to support 'fast' quad rendering as (a) it wouldn't get used much and (b) is extremely unlikely to be the bottleneck in rendering!&#xD;&#xA;&#xD;&#xA;Having said all this, the *original* Series 1 PowerVR graphics chips (eg PCX1 and PCX2) used a lower-level primitive (the half plane) from which N-sided convex polygons (*or in fact N-sided polyhedra - e.g a entire cube was, at most, 6 half-planes*) could be constructed. IIRC the driver tried to detect if two consecutive triangles actually formed a planar quad and then replaced them with a more efficient representation. Further, for a quad to be &quot;planar&quot; not only was it geometrically flat but the texture coordinates also had to be 'flat'. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/1464/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="26041" PostHistoryTypeId="5" PostId="9481" RevisionGUID="8ef203e7-b2de-4d67-95c5-0c89ae8048e6" CreationDate="2020-01-10T16:24:56.773" UserId="4958" Comment="added 104 characters in body" Text="I am interested in Path Tracing, I currently follow the Ray Tracing in a weekend book. When implementing the metal material, I get a strange artifact on the edge of the sphere that does not appear in the book's result. I might be caused by the fuzz parameter, when it's set to zero, it does not occur.&#xD;&#xA;&#xD;&#xA;I wrote my code in Rust&#xD;&#xA;&#xD;&#xA;Screenshots:  &#xD;&#xA;Fuzziness set to 0.0  &#xD;&#xA;[![Fuzziness set to 0.0][1]][1]&#xD;&#xA;&#xD;&#xA;Fuzziness set to 0.5  &#xD;&#xA;[![Fuzziness set to 0.5][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see there is a white outline-like artifact at the edge of the sphere.  &#xD;&#xA;I am not sure what causes that...&#xD;&#xA;&#xD;&#xA;The full code is available here: https://github.com/AregevDev/pathtracer  &#xD;&#xA;Some highlights:&#xD;&#xA;&#xD;&#xA;My random point function&#xD;&#xA;```rust&#xD;&#xA;fn random_double() -&gt; f64 {&#xD;&#xA;    let mut rnd = rand::thread_rng();&#xD;&#xA;    rnd.gen::&lt;f64&gt;()&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Generate a random point in the unit sphere&#xD;&#xA;fn random_in_unit_sphere() -&gt; Vector3 {&#xD;&#xA;    loop {&#xD;&#xA;        let p =&#xD;&#xA;            2.0 * Vector3::new(&#xD;&#xA;                random_double() as f32,&#xD;&#xA;                random_double() as f32,&#xD;&#xA;                random_double() as f32,&#xD;&#xA;            ) - Vector3::new(1.0, 1.0, 1.0);&#xD;&#xA;        if p.squared_length() &lt;= 1.0 {&#xD;&#xA;            return p;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;My material scatter function, I match the material type and calculate the rays accordingly:&#xD;&#xA;```rust&#xD;&#xA;pub fn scatter(&amp;self, ray_in: Ray, record: &amp;HitRecord) -&gt; Option&lt;Scatter&gt; {&#xD;&#xA;        match *self {&#xD;&#xA;            Material::Lambertian { albedo } =&gt; {&#xD;&#xA;                let mut scattered = Scatter::default();&#xD;&#xA;                let target = record.p + record.normal + random_in_unit_sphere();&#xD;&#xA;&#xD;&#xA;                scattered.color = albedo;&#xD;&#xA;                scattered.ray = Some(Ray::new(record.p, target - record.p));&#xD;&#xA;&#xD;&#xA;                Some(scattered)&#xD;&#xA;            }&#xD;&#xA;            Material::Metal { albedo, fuzz } =&gt; {&#xD;&#xA;                let mut scattered = Scatter::default();&#xD;&#xA;                let reflected = ray_in.direction.normalize().reflect(record.normal);&#xD;&#xA;                let new_fuzz = fuzz.min(1.0);&#xD;&#xA;&#xD;&#xA;                scattered.color = albedo;&#xD;&#xA;                scattered.ray = Some(Ray::new(&#xD;&#xA;                    record.p,&#xD;&#xA;                    reflected + new_fuzz * random_in_unit_sphere(),&#xD;&#xA;                ));&#xD;&#xA;&#xD;&#xA;                if scattered.ray.unwrap().direction.dot(record.normal) &gt; 0.0 {&#xD;&#xA;                    Some(scattered)&#xD;&#xA;                } else {&#xD;&#xA;                    None&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            _ =&gt; None,&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HC5l2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zpF2k.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26051" PostHistoryTypeId="2" PostId="9485" RevisionGUID="18c3b05b-e469-4847-a687-fe91f2784efa" CreationDate="2020-01-12T01:11:21.533" UserId="6470" Text="(In case someone encounters similar issue)&#xD;&#xA;&#xD;&#xA;I end-up in Way 1, and it seems the standard way in academia.&#xD;&#xA;&#xD;&#xA;Once I am familar with Blender, the scene creation becomes less challenging; still, it takes some time to create a simple scene. Fortunately for academic papers the number of scenes are a few (&lt; 10).&#xD;&#xA;&#xD;&#xA;Unfortunately the old Mitsuba parser does not work for the latest Blender version. So I wrote a custom 2.8x Blender add-on for Mitsuba, as well as creating new, custom material nodes for my own renderer." ContentLicense="CC BY-SA 4.0" />
  <row Id="26052" PostHistoryTypeId="50" PostId="9354" RevisionGUID="2dfc8d49-d47b-4334-9387-a4b007054ab8" CreationDate="2020-01-12T06:02:30.337" UserId="-1" />
  <row Id="26056" PostHistoryTypeId="2" PostId="9487" RevisionGUID="209e1f2e-1e13-454f-b165-f463fd207260" CreationDate="2020-01-12T21:31:16.000" UserId="8314" Text="Build a hexahedron from 6 triangles(!), setting its 2 vertices at the poles of the sphere, and the other 3 vertices equally around the equator. Then iteratively or recursively subdivide all triangles, projecting the new vertices at the sphere surface (!). Triangle subdivision can be done by replacing an original triangle by 4 new ones, adding new vertices in the middle of all 3 edges and in the middle of the original triangle." ContentLicense="CC BY-SA 4.0" />
  <row Id="26058" PostHistoryTypeId="2" PostId="9489" RevisionGUID="9404cf8a-4cfa-4833-910b-6017c053003c" CreationDate="2020-01-13T09:00:10.583" UserId="11699" Text="Thanks for your help, I fixed it by changing the way i am computing the depth :)&#xD;&#xA;```&#xD;&#xA;const double z_b = texture(depthBuffer, texcoord).x;&#xD;&#xA;const vec4 clipSpacePosition = vec4(texcoord * 2.0 - 1.0, z_b, 1.0);&#xD;&#xA;vec4 viewSpacePosition = cam.projInverse * clipSpacePosition;&#xD;&#xA;viewSpacePosition /= viewSpacePosition.w;&#xD;&#xA;float depth = length(viewSpacePosition.xyz);&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="26059" PostHistoryTypeId="5" PostId="9480" RevisionGUID="5bac8dd1-a3c4-4cad-ab10-4d53254bf495" CreationDate="2020-01-13T09:09:32.743" UserId="209" Comment="fixed grammar" Text="To expand on @Makogan and @lightxbulb's answers/comments: &#xD;&#xA;&#xD;&#xA;There are several reasons for using triangles as the basic primitive.&#xD;&#xA;&#xD;&#xA; 1. (Non-degenerate) triangles are guaranteed to be *planar*. This means that an individual single triangle cannot obscure itself (in terms of hidden surface removal) and thus cannot  form an internal silhouette edge (when being rendered)  nor, say, cast a shadow on itself.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is also means that when scan converting a triangle, for each pixel, each attribute (e.g. depth, texture coordinate, shading) can only take a 'single' value.&#xD;&#xA; 2. They are guaranteed to be convex. Scan converting/filling convex polygons is *far* simpler than a general polygon filling algorithm&#xD;&#xA;&#xD;&#xA; 3. An arbitrary polygonal mesh can always be *easily* decomposed into triangles&lt;br/&gt;&#xD;&#xA;[**Update**: As @joojaa pointed out, you could still use quads by either&lt;br/&gt;&#xD;&#xA;**a)** Noting that any triangle can be represented as 3 quads by the addition of four more vertices - one at the centre of the triangle and one on each edge). You need to be careful, though, not to [introduce T-Junctions][1]. *or*&lt;br/&gt;&#xD;&#xA;**b)** Using a degenerate quad to create a triangle - i.e. either collapse an edge by repeating a vertex *or* (but this may have other problems due to precision) making 3 of the vertices collinear&#xD;&#xA;Neither seems, to me at least, as particularly attractive].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you are concerned about the 'cost' in vertices of supplying two triangles to represent your quad, remember that APIs (and HW) have triangle strips/fans/indexed representations which will, in most cases, eliminate the additional vertex overheads.&#xD;&#xA;There is thus little point in adding additional hardware to support 'fast' quad rendering as (a) it wouldn't get used much and (b) is extremely unlikely to be the bottleneck in rendering!&#xD;&#xA;&#xD;&#xA;Having said all this, the *original* Series 1 PowerVR graphics chips (eg PCX1 and PCX2) used a lower-level primitive (the half plane) from which N-sided convex polygons (*or in fact N-sided polyhedra - e.g a entire cube was, at most, 6 half-planes*) could be constructed. IIRC the driver tried to detect if two consecutive triangles actually formed a planar quad and then replaced them with a more efficient representation. Further, for a quad to be &quot;planar&quot; not only was it geometrically flat but the texture coordinates also had to be 'flat'. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/1464/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="26060" PostHistoryTypeId="5" PostId="9466" RevisionGUID="51e0839f-67cf-4d4f-8315-68559aa64a10" CreationDate="2020-01-13T09:12:30.977" UserId="209" Comment="Ade" Text="*Disclaimer: I've only skimmed through the code.*&#xD;&#xA;&#xD;&#xA;To be honest, the best thing to do would be to **use a  profiler on your code** to identify what actually is costing CPU cycles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Having said that, some operations are more expensive than others - e.g. floating point division and sqrt OR, potentially far more detrimental to performance, cache misses.&#xD;&#xA; &#xD;&#xA;WRT to the former, for example, in...&#xD;&#xA;```&#xD;&#xA; double lightdist = sqrt(lightDist.x*lightDist.x + lightDist.y*lightDist.y + lightDist.z*lightDist.z);&#xD;&#xA;        if(lightdist &gt; 32) {voxelColour = 32;}&#xD;&#xA;        else if(lightdist &gt; 4)  voxelColour = 1024/lightdist;&#xD;&#xA;        else voxelColour = 255;&#xD;&#xA;```&#xD;&#xA;...it doesn't look to me like you always need to compute the sqrt in two of the branches. Perhaps instead, just keep the square of the distance and compare against SQ(32), SQ(4) etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;BTW: the following looks a little 'odd'&#xD;&#xA;```&#xD;&#xA;        rayd.z = dir.z + plane.z*cameraY;&#xD;&#xA;        rayd.x = dir.x + plane.x*cameraX;&#xD;&#xA;        rayd.y = dir.y + plane.y*cameraX;&#xD;&#xA;```&#xD;&#xA;Do you really intend to use cameraX twice? I've not really thought about it but it just looks suspicious." ContentLicense="CC BY-SA 4.0" />
  <row Id="26062" PostHistoryTypeId="2" PostId="9490" RevisionGUID="5edb3b42-21c9-49d7-8d52-041a66d3ffd8" CreationDate="2020-01-13T11:05:03.000" UserId="9254" Text="Assume we're generating a path ${\rm x}=(\rm x_0,\rm x_1,\rm x_2)$ of length $2$ using the $(s,t)$-strategy in bidirectional path tracing (see picture below). Assume that there is no participating media in the scene and we're using a pinhole camera.&#xD;&#xA;&#xD;&#xA;Now assume $s=0$ and $t=3$. Since we're using a pinhole camera, $\rm x_0$ is deterministically  fixed at the eye. A raster point is determined by drawing random numbers $u_1,u_2\in(0,1)$ and mapping them uniformly to the raster space. The raster point determines a ray $r_1=(\rm x_0,\omega_1)$ with origin $\rm x_0$ and direction $\omega_1$. Assume that $r_1$ hits a surface point ${\rm x_1}$. Now another pair of random numbers $u_3,u_4\in(0,1)$ are drawn and mapped to a direction $\omega_2$ by the$^1$ bidirectional scattering distribution function at $\rm x_1$ and thereby giving rise to the next ray $r_2=(\rm x_1,\omega_2)$. $r_2$ might either hit another point $\rm x_2$ (located on a surface or a light source) or escape the scene. In the last case, we assume that $\rm x_2$ is located on an infinite light.&#xD;&#xA;&#xD;&#xA;&gt; In summary, we've used the random numbers $u_1,u_2,u_3,u_4$ to sample $\rm x=(\rm x_0,\rm x_1,\rm x_2)$. Now assume we're switching to the strategy. How can we determine random numbers $v_1,v_2,\ldots$ which would have produced the same path $\rm x$ under the $(1,2)$-strategy?&#xD;&#xA;&#xD;&#xA;We should clearly be able to reuse $u_1,u_2$, since $(\rm x_0,\rm x_1)$ is still part of the truncated camera subpath of the $(1,2)$-strategy.&#xD;&#xA;&#xD;&#xA;The abstract process is described in Section 6.1 of the paper [Charted Metropolis Light Transport](https://arxiv.org/pdf/1612.05395.pdf). I've got a hard time to understand how we would need to implement it in practice. I'd be great if someone could explain the details for the example above.&#xD;&#xA;&#xD;&#xA;[![(s,t)-strategy][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gmQlI.png&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$^1$ It might actually be a composition of multiple BSDFs and $u_3$ is used to select one of it." ContentLicense="CC BY-SA 4.0" />
  <row Id="26063" PostHistoryTypeId="1" PostId="9490" RevisionGUID="5edb3b42-21c9-49d7-8d52-041a66d3ffd8" CreationDate="2020-01-13T11:05:03.000" UserId="9254" Text="Chart swaps and path inversion in bidirectional path tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="26065" PostHistoryTypeId="3" PostId="9490" RevisionGUID="5edb3b42-21c9-49d7-8d52-041a66d3ffd8" CreationDate="2020-01-13T11:05:03.000" UserId="9254" Text="|raytracing|pathtracing|physically-based|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26068" PostHistoryTypeId="5" PostId="9490" RevisionGUID="34aeb2cf-156b-4bbe-975b-a9a8b00a1e6a" CreationDate="2020-01-13T14:46:59.953" UserId="9254" Comment="added 354 characters in body" Text="Assume we're generating a path ${\rm x}=(\rm x_0,\rm x_1,\rm x_2)$ of length $2$ using the $(s,t)$-strategy in bidirectional path tracing (see picture below). Assume that there is no participating media in the scene and we're using a pinhole camera.&#xD;&#xA;&#xD;&#xA;Now assume $s=0$ and $t=3$. Since we're using a pinhole camera, $\rm x_0$ is deterministically  fixed at the eye. A raster point is determined by drawing random numbers $u_1,u_2\in(0,1)$ and mapping them uniformly to the raster space. The raster point determines a ray $r_1=(\rm x_0,\omega_1)$ with origin $\rm x_0$ and direction $\omega_1$. Assume that $r_1$ hits a surface point ${\rm x_1}$. Now another pair of random numbers $u_3,u_4\in(0,1)$ are drawn and mapped to a direction $\omega_2$ by the$^1$ bidirectional scattering distribution function at $\rm x_1$ and thereby giving rise to the next ray $r_2=(\rm x_1,\omega_2)$. $r_2$ might either hit another point $\rm x_2$ (located on a surface or a light source) or escape the scene. In the last case, we assume that $\rm x_2$ is located on an infinite light.&#xD;&#xA;&#xD;&#xA;&gt; In summary, we've used the random numbers $u_1,u_2,u_3,u_4$ to sample $\rm x=(\rm x_0,\rm x_1,\rm x_2)$. Now assume we're switching to the strategy. How can we determine random numbers $v_1,v_2,\ldots$ which would have produced the same path $\rm x$ under the $(1,2)$-strategy?&#xD;&#xA;&#xD;&#xA;We should clearly be able to reuse $u_1,u_2$, since $(\rm x_0,\rm x_1)$ is still part of the truncated camera subpath of the $(1,2)$-strategy.&#xD;&#xA;&#xD;&#xA;The abstract process is described in Section 6.1 of the paper [Charted Metropolis Light Transport](https://arxiv.org/pdf/1612.05395.pdf). I've got a hard time to understand how we would need to implement it in practice. I'd be great if someone could explain the details for the example above.&#xD;&#xA;&#xD;&#xA;[![(s,t)-strategy][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gmQlI.png&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$^1$ It might actually be a composition of multiple BSDFs and $u_3$ is used to select one of it.&#xD;&#xA;&#xD;&#xA;**EDIT**: I'm actually trying to implement this in [PBRT](https://www.pbrt.org/). So, if necessary, feel free to assume that each BSDF has only a single component and that this component is either of type `(pbrt::BSDF_REFLECTION | pbrt::BSDF_DIFFUSE)`, `pbrt::BSDF_REFLECTION | pbrt::BSDF_SPECULAR` or `pbrt::BSDF_TRANSMISSION | pbrt::BSDF_SPECULAR`." ContentLicense="CC BY-SA 4.0" />
  <row Id="26069" PostHistoryTypeId="2" PostId="9492" RevisionGUID="3fe162a5-859c-438e-b981-0771f8b52c21" CreationDate="2020-01-14T06:43:24.213" UserId="11735" Text="I was going through the camera matrix explained in the [wikipedia][1] article and understand how the matrix **K** \begin{bmatrix}f_x&amp;s&amp;x_0\\0&amp;f_y&amp;y_0\\0&amp;0&amp;1\end{bmatrix} is [built][2]. The projection matrix is then essentially `K * [R | T]`&#xD;&#xA;&#xD;&#xA;However, I am not able to understand what the [perspective projection][3] matrix is and how is it same to the intrinsic matrix **K**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Camera_matrix&#xD;&#xA;  [2]: http://ksimek.github.io/2013/08/13/intrinsic/&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/6254/how-to-derive-a-perspective-projection-matrix-from-its-components" ContentLicense="CC BY-SA 4.0" />
  <row Id="26070" PostHistoryTypeId="1" PostId="9492" RevisionGUID="3fe162a5-859c-438e-b981-0771f8b52c21" CreationDate="2020-01-14T06:43:24.213" UserId="11735" Text="Intrinsic Matrix vs Perspective projection matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="26071" PostHistoryTypeId="3" PostId="9492" RevisionGUID="3fe162a5-859c-438e-b981-0771f8b52c21" CreationDate="2020-01-14T06:43:24.213" UserId="11735" Text="|projections|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26072" PostHistoryTypeId="6" PostId="9492" RevisionGUID="f68fedae-4d07-41f3-a044-c459f98e0956" CreationDate="2020-01-14T08:10:54.780" UserId="11735" Comment="edited tags" Text="|3d|projections|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26073" PostHistoryTypeId="5" PostId="9490" RevisionGUID="6dc18aad-5e39-43eb-a62d-b6db2c750371" CreationDate="2020-01-14T08:47:03.520" UserId="209" Comment="The actual question was hidden towards the bottom of the text so I re-ordered it." Text="**I've got a hard time to understand how we would implement the following in practice. I'd be great if someone could explain the details for the example below.**&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;Assume we're generating a path ${\rm x}=(\rm x_0,\rm x_1,\rm x_2)$ of length $2$ using the $(s,t)$-strategy in bidirectional path tracing (see picture below). Assume that there is no participating media in the scene and we're using a pinhole camera.&#xD;&#xA;&#xD;&#xA;Now assume $s=0$ and $t=3$. Since we're using a pinhole camera, $\rm x_0$ is deterministically  fixed at the eye. A raster point is determined by drawing random numbers $u_1,u_2\in(0,1)$ and mapping them uniformly to the raster space. The raster point determines a ray $r_1=(\rm x_0,\omega_1)$ with origin $\rm x_0$ and direction $\omega_1$. Assume that $r_1$ hits a surface point ${\rm x_1}$. Now another pair of random numbers $u_3,u_4\in(0,1)$ are drawn and mapped to a direction $\omega_2$ by the$^1$ bidirectional scattering distribution function at $\rm x_1$ and thereby giving rise to the next ray $r_2=(\rm x_1,\omega_2)$. $r_2$ might either hit another point $\rm x_2$ (located on a surface or a light source) or escape the scene. In the last case, we assume that $\rm x_2$ is located on an infinite light.&#xD;&#xA;&#xD;&#xA;&gt; In summary, we've used the random numbers $u_1,u_2,u_3,u_4$ to sample $\rm x=(\rm x_0,\rm x_1,\rm x_2)$. Now assume we're switching to the strategy. How can we determine random numbers $v_1,v_2,\ldots$ which would have produced the same path $\rm x$ under the $(1,2)$-strategy?&#xD;&#xA;&#xD;&#xA;We should clearly be able to reuse $u_1,u_2$, since $(\rm x_0,\rm x_1)$ is still part of the truncated camera subpath of the $(1,2)$-strategy.&#xD;&#xA;&#xD;&#xA;The abstract process is described in Section 6.1 of the paper [Charted Metropolis Light Transport](https://arxiv.org/pdf/1612.05395.pdf).&#xD;&#xA;&#xD;&#xA;[![(s,t)-strategy][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gmQlI.png&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$^1$ It might actually be a composition of multiple BSDFs and $u_3$ is used to select one of it.&#xD;&#xA;&#xD;&#xA;**EDIT**: I'm actually trying to implement this in [PBRT](https://www.pbrt.org/). So, if necessary, feel free to assume that each BSDF has only a single component and that this component is either of type `(pbrt::BSDF_REFLECTION | pbrt::BSDF_DIFFUSE)`, `pbrt::BSDF_REFLECTION | pbrt::BSDF_SPECULAR` or `pbrt::BSDF_TRANSMISSION | pbrt::BSDF_SPECULAR`." ContentLicense="CC BY-SA 4.0" />
  <row Id="26074" PostHistoryTypeId="2" PostId="9493" RevisionGUID="2d4e65c5-a7ac-45c9-b017-56788cd66ae9" CreationDate="2020-01-15T00:56:31.190" UserId="7462" Text="I essentially know of 2 geometry processing data structures. one is the half edge (which has some really nice properties, but can't represent non manifold meshes nor tet meshes).&#xD;&#xA;&#xD;&#xA;The other is an extended adjacency list representation of the graph connectivity that also stores faces and edges.&#xD;&#xA;&#xD;&#xA;Are there more?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26075" PostHistoryTypeId="1" PostId="9493" RevisionGUID="2d4e65c5-a7ac-45c9-b017-56788cd66ae9" CreationDate="2020-01-15T00:56:31.190" UserId="7462" Text="What other geometry processing data structures are there?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26076" PostHistoryTypeId="3" PostId="9493" RevisionGUID="2d4e65c5-a7ac-45c9-b017-56788cd66ae9" CreationDate="2020-01-15T00:56:31.190" UserId="7462" Text="|algorithm|computational-geometry|geometry|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26077" PostHistoryTypeId="2" PostId="9494" RevisionGUID="da3e0749-93a9-4bbd-be1a-f25ee3320215" CreationDate="2020-01-15T04:35:47.330" UserDisplayName="user11739" Text="I am working on a Renderer that should do a Depth Prepass before rendering the desired geometry.  &#xD;&#xA;For this I have a Vertex and Pixel Shader that outputs to the Depth Texture.&#xD;&#xA;After that it should render the same geometry using different shaders with texture and such.  &#xD;&#xA;My question is how should I organize the Data on CPU side (classes/structs)?&#xD;&#xA;The &quot;Main&quot; Vertex Buffer Layout contains&#xD;&#xA;&#xD;&#xA;    Position&#xD;&#xA;    Normal&#xD;&#xA;    TexCoord&#xD;&#xA;    Color&#xD;&#xA;    (BoneWeight)&#xD;&#xA;&#xD;&#xA;The Depth Pass only needs `Position`&#xD;&#xA;Do I need to store two different Layouts and keep two different Vertex Buffers to reduce Bandwidth?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26078" PostHistoryTypeId="1" PostId="9494" RevisionGUID="da3e0749-93a9-4bbd-be1a-f25ee3320215" CreationDate="2020-01-15T04:35:47.330" UserDisplayName="user11739" Text="Multipass Rendering Vertex Buffer Organisation" ContentLicense="CC BY-SA 4.0" />
  <row Id="26079" PostHistoryTypeId="3" PostId="9494" RevisionGUID="da3e0749-93a9-4bbd-be1a-f25ee3320215" CreationDate="2020-01-15T04:35:47.330" UserDisplayName="user11739" Text="|directx11|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26081" PostHistoryTypeId="5" PostId="9490" RevisionGUID="447849bb-83ba-42d5-a5b3-d35039bdf1ea" CreationDate="2020-01-15T15:51:19.213" UserId="9254" Comment="deleted 22 characters in body" Text="**I've got a hard time to understand how we would implement the following in practice. I'd be great if someone could explain the details for the example below.**&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;Assume we're generating a path ${\rm x}=(\rm x_0,\rm x_1,\rm x_2)$ of length $2$ using the $(s,t)$-strategy in bidirectional path tracing (see picture below). Assume that there is no participating media in the scene and we're using a pinhole camera.&#xD;&#xA;&#xD;&#xA;Now assume $s=0$ and $t=3$. Since we're using a pinhole camera, $\rm x_0$ is deterministically  fixed at the eye. A raster point is determined by drawing random numbers $u_1,u_2\in(0,1)$ and mapping them uniformly to the raster space. The raster point determines a ray $r_1=(\rm x_0,\omega_1)$ with origin $\rm x_0$ and direction $\omega_1$. Assume that $r_1$ hits a surface point ${\rm x_1}$. Now another pair of random numbers $u_3,u_4\in(0,1)$ are drawn and mapped to a direction $\omega_2$ by the$^1$ bidirectional scattering distribution function at $\rm x_1$ and thereby giving rise to the next ray $r_2=(\rm x_1,\omega_2)$. $r_2$ might either hit another point $\rm x_2$ (located on a surface or a light source) or escape the scene. In the last case, we assume that $\rm x_2$ is located on an infinite light.&#xD;&#xA;&#xD;&#xA;&gt; In summary, we've used the random numbers $u_1,u_2,u_3,u_4$ to sample $\rm x=(\rm x_0,\rm x_1,\rm x_2)$. Now assume we're switching to the strategy. How can we determine random numbers $v_1,v_2,\ldots$ which would have produced the same path $\rm x$ under the $(1,2)$-strategy?&#xD;&#xA;&#xD;&#xA;We should clearly be able to reuse $u_1,u_2$, since $(\rm x_0,\rm x_1)$ is still part of the truncated camera subpath of the $(1,2)$-strategy.&#xD;&#xA;&#xD;&#xA;The abstract process is described in Section 6.1 of the paper [Charted Metropolis Light Transport](https://arxiv.org/pdf/1612.05395.pdf).&#xD;&#xA;&#xD;&#xA;[![(s,t)-strategy][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gmQlI.png&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;$^1$ It might actually be a composition of multiple BSDFs and $u_3$ is used to select one of it.&#xD;&#xA;&#xD;&#xA;**EDIT**: I'm actually trying to implement this in [PBRT](https://www.pbrt.org/). So, if necessary, feel free to assume that each BSDF has only a single component and that this component is of type `(pbrt::BSDF_REFLECTION | pbrt::BSDF_DIFFUSE)`. Thus, you can assume that there is a single Lambertian BSDF at each surface point." ContentLicense="CC BY-SA 4.0" />
  <row Id="26082" PostHistoryTypeId="33" PostId="9490" RevisionGUID="26873125-47d5-4183-9eee-57d630650481" CreationDate="2020-01-15T15:51:29.637" UserId="9254" Comment="58" />
  <row Id="26087" PostHistoryTypeId="2" PostId="9496" RevisionGUID="ccf3d8f3-ad28-4200-a1ea-e8089ee274f1" CreationDate="2020-01-16T13:29:54.773" UserId="11748" Text="I have a geometric shape (assuming that is a rectangle). I want to rotate it about it geometric center by an angle of 45° and plot the result using matplotlib with an equal aspect ratio, I get something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However for some reason, I want to plot the result in a figure with a non-equal aspect, I am getting this result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see, the rotated shape is deformed (skewed). But the original shape seems to be scaled only in the y direction.&#xD;&#xA;&#xD;&#xA;I am trying to understand what kind of transformation is occuring to the orange shape from a linear algebra perspective: Is it a shear? a combination of scaling and shear (Affine transformation)? if not what kind of transformation is that?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My goal is to identify the type of transformation, then finding it's inverse to get the following result:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I appreciate any help.&#xD;&#xA;  [1]: https://i.stack.imgur.com/iXe7B.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3V3VD.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yhn2Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26088" PostHistoryTypeId="1" PostId="9496" RevisionGUID="ccf3d8f3-ad28-4200-a1ea-e8089ee274f1" CreationDate="2020-01-16T13:29:54.773" UserId="11748" Text="What kind of transformation when the aspect is changed for a rotated shape?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26089" PostHistoryTypeId="3" PostId="9496" RevisionGUID="ccf3d8f3-ad28-4200-a1ea-e8089ee274f1" CreationDate="2020-01-16T13:29:54.773" UserId="11748" Text="|transformations|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26090" PostHistoryTypeId="2" PostId="9497" RevisionGUID="585d1c10-1152-4efc-ba6c-44a9dc74d091" CreationDate="2020-01-16T14:49:16.780" UserId="10096" Text="The transformation is non-uniform scale - it does not preserve angles. The only reason the angles for the other shape were preserved was because the scaling was in the same direction as the edge. To get the result that you want, you either have to scale by the same amount in each direction, or just rescale the &quot;viewing window&quot; and not the shapes." ContentLicense="CC BY-SA 4.0" />
  <row Id="26091" PostHistoryTypeId="2" PostId="9498" RevisionGUID="31401d9c-f285-45ff-a915-2b8637d2daa2" CreationDate="2020-01-16T20:27:13.953" UserId="9254" Text="Suppose we are sampling camera rays of a perspective camera with a finite aperture. The [PBRT implementation](http://www.pbr-book.org/3ed-2018/Camera_Models/Projective_Camera_Models.html#TheThinLensModelandDepthofField) of the sampling scheme looks like this:&#xD;&#xA;&#xD;&#xA;    Float PerspectiveCamera::GenerateRay(const CameraSample &amp;sample,&#xD;&#xA;                                         Ray *ray) const {&#xD;&#xA;        ProfilePhase prof(Prof::GenerateCameraRay);&#xD;&#xA;        // Compute raster and camera sample positions&#xD;&#xA;        Point3f pFilm = Point3f(sample.pFilm.x, sample.pFilm.y, 0);&#xD;&#xA;        Point3f pCamera = RasterToCamera(pFilm);&#xD;&#xA;        *ray = Ray(Point3f(0, 0, 0), Normalize(Vector3f(pCamera)));&#xD;&#xA;        // Modify ray for depth of field&#xD;&#xA;        if (lensRadius &gt; 0) {&#xD;&#xA;            // Sample point on lens&#xD;&#xA;            Point2f pLens = lensRadius * ConcentricSampleDisk(sample.pLens);&#xD;&#xA;    &#xD;&#xA;            // Compute point on plane of focus&#xD;&#xA;            Float ft = focalDistance / ray-&gt;d.z;&#xD;&#xA;            Point3f pFocus = (*ray)(ft);&#xD;&#xA;    &#xD;&#xA;            // Update ray for effect of lens&#xD;&#xA;            ray-&gt;o = Point3f(pLens.x, pLens.y, 0);&#xD;&#xA;            ray-&gt;d = Normalize(pFocus - ray-&gt;o);&#xD;&#xA;        }&#xD;&#xA;        ray-&gt;time = Lerp(sample.time, shutterOpen, shutterClose);&#xD;&#xA;        ray-&gt;medium = medium;&#xD;&#xA;        *ray = CameraToWorld(*ray);&#xD;&#xA;        return 1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&gt; Let $X_0\in M$ and $\Omega_1\in S^2$ denote the sampled point on the camera and direction, respectively. The next surface point in a path tracer would be $$Y:=X+d_M(X,\Omega)\Omega,$$ where $$d_M(x,\omega):=\inf\left\{t&gt;0:x+t\omega\in M\right\}\;\;\;\text{for }x\in M\text{ and }\omega\in S^2.$$ What is the conditional distribution of $Y$ given $(X,\Omega)$?&#xD;&#xA;&#xD;&#xA;From page 303 in [Veach's thesis](http://graphics.stanford.edu/papers/veach_thesis/thesis.pdf) the conditional distribution of $Y$ given $X$ should have a density with respect to the projected solid angle kernel $$\sigma_M^\perp(x,B):=\int_B\sigma_{S^2}({\rm d}\omega)|\langle\nu_M(x),\omega\rangle|\;\;\;\text{for }(x,B)\in M\times\mathcal B(S^2).$$&#xD;&#xA;&#xD;&#xA;Formally, we assume that the lens is part of our scene geometry $M$, which is assumed to be an oriented embedded $C^1$-submanifold of $\mathbb R^3$, $\nu_M$ denotes the outer normal field on $M$ and $\sigma_M$ denotes the surface measure on $\mathcal B(M)$. Moreover, let $S^2$ denote the unit $2$-sphere, $$S^2(x):=\left\{y\in\mathbb R^3:|x-y|=1\right\}=x+S^2\;\;\;\text{for }x\in\mathbb R^3$$ and $$\omega_{x\to y}:=\frac{y-x}{|y-x|}\in S^2\;\;\;\text{for }x,y\in\mathbb R^3\text{ with }x\ne y.$$ For simplicity, assume that $$d_M(x,\omega):=\inf\left\{t&gt;0:x+t\omega\in M\right\}&lt;\infty\;\;\;\text{for all }x\in M\text{ and }\omega\in S^2\tag1$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="26092" PostHistoryTypeId="1" PostId="9498" RevisionGUID="31401d9c-f285-45ff-a915-2b8637d2daa2" CreationDate="2020-01-16T20:27:13.953" UserId="9254" Text="Distribution of the first vertex on a camera subpath in bidirectional path tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="26093" PostHistoryTypeId="3" PostId="9498" RevisionGUID="31401d9c-f285-45ff-a915-2b8637d2daa2" CreationDate="2020-01-16T20:27:13.953" UserId="9254" Text="|raytracing|pathtracing|global-illumination|pbr|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26094" PostHistoryTypeId="2" PostId="9499" RevisionGUID="55472040-4f18-488c-9e55-9d34f1876178" CreationDate="2020-01-17T02:29:25.803" UserId="11750" Text="Peter Shirely's *Ray Tracing in One Weekend* presents the following function to calculate the color of a lambertian material (See chapter's 7 and 8):&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;bool lambertian::scatter(ray ray_in, hit_record rec, vec3&amp; attenuation, ray &amp;scattered) {&#xD;&#xA;  vec3 target = rec.p + rec.normal + random_in_unit_sphere();&#xD;&#xA;  scattered = ray(rec.p, target - rec.p);&#xD;&#xA;  attenuation = this-&gt;albedo;&#xD;&#xA;  return true;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I've read through other material that mentions Lambert's Cosine Law when discussing diffuse materials. Why is the term omitted from Peter Shirely's text? Is it canceled out somehow? My expectation is that the attenuation term should look something like:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;  attenuation = this-&gt;albedo * dot(rec.normal, ray_in.direction);&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="26095" PostHistoryTypeId="1" PostId="9499" RevisionGUID="55472040-4f18-488c-9e55-9d34f1876178" CreationDate="2020-01-17T02:29:25.803" UserId="11750" Text="Confusion around Lambert's Cosine Law in Ray Tracing in One Weekend" ContentLicense="CC BY-SA 4.0" />
  <row Id="26096" PostHistoryTypeId="3" PostId="9499" RevisionGUID="55472040-4f18-488c-9e55-9d34f1876178" CreationDate="2020-01-17T02:29:25.803" UserId="11750" Text="|raytracing|mathematics|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26097" PostHistoryTypeId="5" PostId="9499" RevisionGUID="edefd089-e478-4010-b325-d80c4e04b89a" CreationDate="2020-01-17T02:36:23.217" UserId="11750" Comment="added 6 characters in body" Text="Peter Shirely's *Ray Tracing in One Weekend* presents the following function to calculate the color of a lambertian material (See chapter's 7 and 8):&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;bool lambertian::scatter(ray ray_in, hit_record rec, vec3&amp; attenuation, ray &amp;scattered) {&#xD;&#xA;  vec3 target = rec.p + rec.normal + random_in_unit_sphere();&#xD;&#xA;  scattered = ray(rec.p, target - rec.p);&#xD;&#xA;  attenuation = this-&gt;albedo;&#xD;&#xA;  return true;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I've read through other material that mentions Lambert's Cosine Law when discussing diffuse materials. Why is the `cos` term omitted from Peter Shirely's text? Is it canceled out somehow? My expectation is that the attenuation term should look something like:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;  attenuation = this-&gt;albedo * dot(rec.normal, ray_in.direction);&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="26098" PostHistoryTypeId="2" PostId="9500" RevisionGUID="9a0f87e1-657c-4feb-8bd3-c33a661ac923" CreationDate="2020-01-17T04:47:50.137" UserId="10096" Text="It is cancelled out by the probability density function in the estimator. The pdf in their case is exactly: $\frac{\cos\theta}{\pi}$, which is in the denominator: `att = albedo * cos_theta / pdf = albedo * pi`. They have absorbed pi in the albedo. Note that there's an update on github to the code, since `random_in_unit_sphere()` actually generates a $\cos^3\theta$ distribution, they fixed it to `random_on_unit_sphere()` which generates a $\cos\theta$ distribution. So technically you are working with a $\cos^2\theta$ brdf here and not constant." ContentLicense="CC BY-SA 4.0" />
  <row Id="26099" PostHistoryTypeId="50" PostId="9426" RevisionGUID="593afc57-e856-40e8-9d1f-be1fb11c5654" CreationDate="2020-01-17T10:01:35.177" UserId="-1" />
  <row Id="26100" PostHistoryTypeId="50" PostId="8779" RevisionGUID="9f2af4fd-7fbb-4877-9307-f230363efd6a" CreationDate="2020-01-17T14:02:30.380" UserId="-1" />
  <row Id="26102" PostHistoryTypeId="2" PostId="9501" RevisionGUID="50b3f973-2d36-4cfb-940d-2a61f3458545" CreationDate="2020-01-18T21:15:59.553" UserId="11754" Text="I'm working on improving an open source rasterization library called Gudni that I started a few years ago. It's source repository and the branch I'm currently working on are here: &#xD;&#xA;https://github.com/ianmbloom/gudni/tree/texturetransformation. &#xD;&#xA;&#xD;&#xA;I'm trying to implement a function that maps a quadratic bezier curve onto another curve (see illustration below). This is important for the library because it will not only allow one to describe things like dotted lines as just a series of rectangles projected onto a bezier path, but the same mechanism can (hopefully) be used to make text that follows a path or to make arrowheads etc and many other useful things. Using unified operation to do all of these things will hopefully make the library really easy to use and make a lot of useful figures very easy to describe.&#xD;&#xA;&#xD;&#xA;But I've run into a bit of an impasse and I'm looking for some help.&#xD;&#xA;&#xD;&#xA;The function I need has this description:&#xD;&#xA;&#xD;&#xA;Given two quadratic bezier curves, a source and a target curve, transform the target curve such that the targets x-axis corresponds to the arc-distance along the source curve and the targets y-axis corresponds to the distance from the curve.&#xD;&#xA;In other words given a point (x,y) in the target curves coordinate space find a point and a normal vector that is x units along the arc-length of the source curve then take that point and add it to the normal vector * y.&#xD;&#xA;&#xD;&#xA;This works great for points but it doesn't work for quadratic bezier curves because the control point must be transformed such that each point on the resulting curve approximates a projected point. I'm trying to find method of calculating a control point such that the resulting curve is consistent, well behaved, doesn't require excessive computation, and is visually pleasing (though not necessarily precisely accurate) and can be applied to arbitrary target curves. Probably the most important requirement for the result is that two consecutive bezier segments that share the same tangent, share the same tangent in the projected curves.&#xD;&#xA;&#xD;&#xA;Since the control point of a quadratic bezier is always the intersection of the tangent lines through its start and end point, my solution so far is to take the tangent vectors from the original target curve, transform them relative to the source normal vectors and then calculate the intersection of the lines defined by these transformed tangent vectors. Unfortunately this appears to work well for horizontal target curves but somehow it is often wrong for diagonal curves. I think this is because of the arc-length transformation but I haven't figured it out yet.&#xD;&#xA;&#xD;&#xA;I'm curious if anyone has any thoughts on how to approach this problem.&#xD;&#xA;The current (incorrect) implementation of the function in question can be found here:&#xD;&#xA;https://github.com/ianmbloom/gudni/blob/c65daed3e74a24c47db9d0488159104dbd1b8b62/src/Graphics/Gudni/Figure/Projection.hs#L243&#xD;&#xA;&#xD;&#xA;Let me know if reading haskell is a problem and I can find a way to walk you through it.&#xD;&#xA;&#xD;&#xA;Kind regards,&#xD;&#xA;Ian Bloom&#xD;&#xA;&#xD;&#xA;[![Projection of one quadratic bezier onto another.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mbmpq.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26103" PostHistoryTypeId="1" PostId="9501" RevisionGUID="50b3f973-2d36-4cfb-940d-2a61f3458545" CreationDate="2020-01-18T21:15:59.553" UserId="11754" Text="Projecting one Quadratic Bezier Curve Onto Another" ContentLicense="CC BY-SA 4.0" />
  <row Id="26104" PostHistoryTypeId="3" PostId="9501" RevisionGUID="50b3f973-2d36-4cfb-940d-2a61f3458545" CreationDate="2020-01-18T21:15:59.553" UserId="11754" Text="|rasterizer|curve|bezier-curve|opencl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26105" PostHistoryTypeId="50" PostId="9430" RevisionGUID="5ae389cb-df3f-47e8-abe6-8ae424f4fb94" CreationDate="2020-01-19T02:03:30.683" UserId="-1" />
  <row Id="26106" PostHistoryTypeId="50" PostId="9071" RevisionGUID="5b202b12-ce5e-4a30-bab9-5624082eba8b" CreationDate="2020-01-19T06:01:15.163" UserId="-1" />
  <row Id="26107" PostHistoryTypeId="2" PostId="9502" RevisionGUID="331444b9-3450-467a-871f-d27cd7f90cc5" CreationDate="2020-01-19T12:19:00.600" UserId="11757" Text="I'm trying to make simple 3d modeling program in c++ with Opengl. So I don't know how to transfer/convert/export or save data of 3D model  in .dae file. &#xD;&#xA;NOTE:- 3d model is made using Opengl programming. " ContentLicense="CC BY-SA 4.0" />
  <row Id="26108" PostHistoryTypeId="1" PostId="9502" RevisionGUID="331444b9-3450-467a-871f-d27cd7f90cc5" CreationDate="2020-01-19T12:19:00.600" UserId="11757" Text="After making any 3D model using Opengl how to export it's data in .dae file?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26109" PostHistoryTypeId="3" PostId="9502" RevisionGUID="331444b9-3450-467a-871f-d27cd7f90cc5" CreationDate="2020-01-19T12:19:00.600" UserId="11757" Text="|opengl|3d|c++|gpu|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26111" PostHistoryTypeId="5" PostId="9501" RevisionGUID="0df79c53-2f5a-4dd8-9dee-9188e7d5c9d7" CreationDate="2020-01-19T22:13:38.277" UserId="11754" Comment="added 111 characters in body" Text="I'm working on improving an open source rasterization library called Gudni that I started a few years ago. It's source repository and the branch I'm currently working on are here: &#xD;&#xA;https://github.com/ianmbloom/gudni/tree/texturetransformation. &#xD;&#xA;&#xD;&#xA;I'm trying to implement a function that maps a quadratic bezier curve onto another curve (see illustration below). This is important for the library because it will not only allow one to describe things like dotted lines as just a series of rectangles projected onto a bezier path, but the same mechanism can (hopefully) be used to make text that follows a path or to make arrowheads etc and many other useful things. Using unified operation to do all of these things will hopefully make the library really easy to use and make a lot of useful figures very easy to describe.&#xD;&#xA;&#xD;&#xA;But I've run into a bit of an impasse and I'm looking for some help.&#xD;&#xA;&#xD;&#xA;The function I need has this description:&#xD;&#xA;&#xD;&#xA;Given two quadratic bezier curves, a source and a target curve, transform the target curve such that the targets x-axis corresponds to the arc-distance along the source curve and the targets y-axis corresponds to the distance from the curve.&#xD;&#xA;In other words given a point (x,y) in the target curves coordinate space find a point and a normal vector that is x units along the arc-length of the source curve then take that point and add it to the normal vector * y.&#xD;&#xA;&#xD;&#xA;This works great for points but it doesn't work for quadratic bezier curves because the control point must be transformed such that each point on the resulting curve approximates a projected point. I'm trying to find method of calculating a control point such that the resulting curve is consistent, well behaved, doesn't require excessive computation, and is visually pleasing (though not necessarily precisely accurate) and can be applied to arbitrary target curves. Probably the most important requirement for the result is that two consecutive bezier segments that share the same tangent, share the same tangent in the projected curves.&#xD;&#xA;&#xD;&#xA;Since the control point of a quadratic bezier is always the intersection of the tangent lines through its start and end point, my solution so far is to take the tangent vectors from the original target curve, transform them relative to the source normal vectors and then calculate the intersection of the lines defined by these transformed tangent vectors. Unfortunately this appears to work well for horizontal target curves but somehow it is often wrong for diagonal curves. I think this is because of the arc-length transformation but I haven't figured it out yet.&#xD;&#xA;&#xD;&#xA;I'm curious if anyone has any thoughts on how to approach this problem.&#xD;&#xA;The current (incorrect) implementation of the function in question can be found here:&#xD;&#xA;https://github.com/ianmbloom/gudni/blob/c65daed3e74a24c47db9d0488159104dbd1b8b62/src/Graphics/Gudni/Figure/Projection.hs#L243&#xD;&#xA;&#xD;&#xA;Let me know if reading haskell is a problem and I can find a way to walk you through it.&#xD;&#xA;&#xD;&#xA;Upon request, here is a link to a formalization of the problem:&#xD;&#xA;https://medium.com/@ianbloom/-6e88ea8e8888&#xD;&#xA;&#xD;&#xA;Kind regards,&#xD;&#xA;Ian Bloom&#xD;&#xA;&#xD;&#xA;[![Projection of one quadratic bezier onto another.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mbmpq.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26112" PostHistoryTypeId="50" PostId="8790" RevisionGUID="83463630-444e-4fd2-9527-35ccb0d87ee4" CreationDate="2020-01-21T07:01:20.207" UserId="-1" />
  <row Id="26116" PostHistoryTypeId="2" PostId="9504" RevisionGUID="a1a3e2ae-6e3f-4ada-bdf5-009946b16f3f" CreationDate="2020-01-21T17:58:28.277" UserId="11282" Text="There are plenty of well-known algorithms for determining *if* a ray hit an Axis-Aligned Bounding Box (AABB), like Andrew Woo's covered in a response [here](https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms). &#xD;&#xA;&#xD;&#xA;Using ```exit = origin + (dir * tMax)``` will give you the exact position of exit using distance through the ray. (and same for tMin and the entry)&#xD;&#xA;&#xD;&#xA;However, I need a way to not only do that, but also get if we hit the left, right, top, bottom, front, or rear face of the AABB.&#xD;&#xA;&#xD;&#xA;Is there an algorithm for this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26117" PostHistoryTypeId="1" PostId="9504" RevisionGUID="a1a3e2ae-6e3f-4ada-bdf5-009946b16f3f" CreationDate="2020-01-21T17:58:28.277" UserId="11282" Text="Ray vs AABB algorithm that also gives which side was hit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26118" PostHistoryTypeId="3" PostId="9504" RevisionGUID="a1a3e2ae-6e3f-4ada-bdf5-009946b16f3f" CreationDate="2020-01-21T17:58:28.277" UserId="11282" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26119" PostHistoryTypeId="2" PostId="9505" RevisionGUID="705609d9-a1ef-4625-9452-347b24b74374" CreationDate="2020-01-21T18:45:19.317" UserId="11771" Text="A point light is illuminating only a half of a scene in my small 3D renderer. It happens on every scene I've tried (conference room, cornell box, etc). &#xD;&#xA;&#xD;&#xA;How do I go about debugging this? What could be wrong?&#xD;&#xA;&#xD;&#xA;[![sponza scene][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RF9YY.png&#xD;&#xA;&#xD;&#xA;Here are the shaders. I'm not doing anything out of the ordinary. Light is positioned at (0, 1.0, 0) in world space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;//&#xD;&#xA;// VERT SHADER&#xD;&#xA;//&#xD;&#xA;#version 410 core&#xD;&#xA; &#xD;&#xA;uniform mat4 M;&#xD;&#xA;uniform mat4 V;&#xD;&#xA;uniform mat4 P;&#xD;&#xA; &#xD;&#xA;layout (location = 0) in vec3 position;&#xD;&#xA;layout (location = 1) in vec3 normal;&#xD;&#xA;layout (location = 2) in vec3 color;&#xD;&#xA;layout (location = 3) in vec2 texCoords;&#xD;&#xA; &#xD;&#xA;out vec3 fWorldPos;&#xD;&#xA;out vec3 fNormal;&#xD;&#xA;out vec3 fColor;&#xD;&#xA;out vec2 fTexCoords;&#xD;&#xA;                 &#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    mat4 normalMatrix = transpose(inverse(M));&#xD;&#xA; &#xD;&#xA;    fWorldPos = vec3(M * vec4(position, 1.0));&#xD;&#xA;    fNormal = normal; // also tested multiplying with normal, M, and MV matrices&#xD;&#xA;    fColor = color;&#xD;&#xA;    fTexCoords = texCoords;&#xD;&#xA; &#xD;&#xA;    gl_Position = P * V * M * vec4(position, 1);&#xD;&#xA;}&#xD;&#xA; &#xD;&#xA; &#xD;&#xA;//&#xD;&#xA;// FRAG SHADER&#xD;&#xA;//&#xD;&#xA;#version 410 core&#xD;&#xA;#define MAX_POINT_LIGHTS 4&#xD;&#xA; &#xD;&#xA;struct PointLight {&#xD;&#xA;    float strength;&#xD;&#xA;    vec3 position;&#xD;&#xA;    vec3 color;&#xD;&#xA;    vec3 attenuation;&#xD;&#xA;};&#xD;&#xA; &#xD;&#xA;struct Material {&#xD;&#xA;    vec3 color;&#xD;&#xA;};&#xD;&#xA; &#xD;&#xA;uniform Material material;&#xD;&#xA;uniform int totalPointLights;&#xD;&#xA;uniform PointLight pointLights[MAX_POINT_LIGHTS];&#xD;&#xA;uniform vec3 cameraPosition;&#xD;&#xA; &#xD;&#xA;in vec3 fWorldPos;&#xD;&#xA;in vec3 fNormal;&#xD;&#xA;in vec3 fColor;&#xD;&#xA;in vec2 fTexCoords;&#xD;&#xA; &#xD;&#xA;out vec4 color;&#xD;&#xA; &#xD;&#xA;float attenuate(float dist, const PointLight light) {&#xD;&#xA;    return light.strength / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);&#xD;&#xA;}&#xD;&#xA; &#xD;&#xA;//&#xD;&#xA;// MAIN&#xD;&#xA;//&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;  vec3 normal = normalize(fNormal);&#xD;&#xA; &#xD;&#xA;  PointLight light = pointLights[0];&#xD;&#xA; &#xD;&#xA;  vec3 lightDir = light.position - fWorldPos;&#xD;&#xA;  float lightDst = length(lightDir);&#xD;&#xA;  lightDir = lightDir / lightDst;&#xD;&#xA; &#xD;&#xA;  float att = attenuate(lightDst, light);&#xD;&#xA;  float diffuseFactor = max(dot(normal, lightDir), 0.0);&#xD;&#xA; &#xD;&#xA;  color = vec4(material.color * diffuseFactor * att, 1);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="26120" PostHistoryTypeId="1" PostId="9505" RevisionGUID="705609d9-a1ef-4625-9452-347b24b74374" CreationDate="2020-01-21T18:45:19.317" UserId="11771" Text="Point light illuminating only half of a scene" ContentLicense="CC BY-SA 4.0" />
  <row Id="26121" PostHistoryTypeId="3" PostId="9505" RevisionGUID="705609d9-a1ef-4625-9452-347b24b74374" CreationDate="2020-01-21T18:45:19.317" UserId="11771" Text="|opengl|glsl|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26122" PostHistoryTypeId="5" PostId="9504" RevisionGUID="3046a67d-9bb1-4dd0-b058-701330c1bc96" CreationDate="2020-01-21T21:30:52.040" UserId="11282" Comment="added 287 characters in body" Text="There are plenty of well-known algorithms for determining *if* a ray hit an Axis-Aligned Bounding Box (AABB), like Andrew Woo's covered in a response [here](https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms). &#xD;&#xA;&#xD;&#xA;Using ```exit = origin + (dir * tMax)``` will give you the exact position of exit using distance through the ray. (and same for tMin and the entry)&#xD;&#xA;&#xD;&#xA;However, I need a way to not only do that, but also get if we hit the left, right, top, bottom, front, or rear face of the AABB.&#xD;&#xA;&#xD;&#xA;The naive approach would be to do some kind of floating-point comparison given the minpoint/maxpoint and try to see what side (if any) the point exactly equals in each dimension, or exactly equals within a tolerance. That seems error-prone, I was wondering if there was a better way.&#xD;&#xA;&#xD;&#xA;Is there an algorithm for this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26123" PostHistoryTypeId="2" PostId="9506" RevisionGUID="afc280d2-bd6f-4a30-9ac6-2075af724340" CreationDate="2020-01-22T01:35:51.820" UserId="5717" Text="Given an intersection algorithm like [the one you linked][1] which first generates a $t$ value for every plane of the AABB, then computes $t_{min}$ and $t_{max}$ from those, you simply need to figure out which of the six initial values correspond to your final $t_{min}$. There will be two matches if your ray hits an edge, three if it hits a corner. In that case, this may include a back face (see the fix below).&#xD;&#xA;&#xD;&#xA;This will not require a tolerance as $t_{min}$ is always one of the six values. In fact, it is always one of three intermediate values and you can use that to make your check simpler, faster and better. Given code, from the link above, such as:&#xD;&#xA;&#xD;&#xA;    float tmin = max(max(min(t1, t2), min(t3, t4)), min(t5, t6));&#xD;&#xA;&#xD;&#xA;you could rewrite as:&#xD;&#xA;&#xD;&#xA;    float tminx = min(t1, t2);&#xD;&#xA;    float tminy = min(t3, t4);&#xD;&#xA;    float tmin = max(max(tminx, tminy), min(t5, t6));&#xD;&#xA;    int axis = 2;&#xD;&#xA;    if (tmin == tminx) axis = 0;&#xD;&#xA;    if (tmin == tminy) axis = 1;&#xD;&#xA;&#xD;&#xA;As an added bonus, unlike testing all six values, this will not match the back face in the event that a far edge is hit.&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/a/18459" ContentLicense="CC BY-SA 4.0" />
  <row Id="26124" PostHistoryTypeId="2" PostId="9507" RevisionGUID="c608b2cc-fc54-4f81-b231-67be1160db35" CreationDate="2020-01-22T08:46:36.273" UserId="11771" Text="The normals were indeed wrong. Which was crazy, because I had even checked in Blender that they were correct (and they were). Turns out, when loading the mesh, I was passing the normal as color and vice versa. Valletin's normal visualization shader was great (https://vallentin.dev/2015/02/16/visualizing-normals).&#xD;&#xA;&#xD;&#xA;Thanks for your help!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BbOk8.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26125" PostHistoryTypeId="5" PostId="9507" RevisionGUID="579b2f9d-d546-4e12-a3ad-2e53f977776f" CreationDate="2020-01-22T09:00:47.623" UserId="11771" Comment="changed to better image" Text="The normals were indeed wrong. Which was crazy, because I had even checked in Blender that they were correct (and they were). Turns out, when loading the mesh, I was passing the normal as color and vice versa. Valletin's normal visualization shader was great (https://vallentin.dev/2015/02/16/visualizing-normals).&#xD;&#xA;&#xD;&#xA;Thanks for your help!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6Ifpz.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26126" PostHistoryTypeId="50" PostId="9436" RevisionGUID="ab069fa7-7a82-4af5-a560-2c6f322b0883" CreationDate="2020-01-22T17:00:08.467" UserId="-1" />
  <row Id="26127" PostHistoryTypeId="2" PostId="9508" RevisionGUID="d90ddb9a-91df-45a8-96c8-759aca649668" CreationDate="2020-01-23T16:37:12.880" UserId="7462" Text="I am reading [this document][1] that talks about signed distance field rendering.&#xD;&#xA;&#xD;&#xA;In that document section 6.3, on the topic of cone tracing, it says:&#xD;&#xA;&#xD;&#xA;&gt; Cone tracing is an extension of the sphere tracing algorithm. In&#xD;&#xA;&gt; addition to the ray, a cone is created and expanded in the marching&#xD;&#xA;&gt; direction. At each sampling step, the current cone radius is compared&#xD;&#xA;&gt; with the minimum distance from the distance field. If the SDF value is&#xD;&#xA;&gt; smaller than the current radius, the cone has intersected an object&#xD;&#xA;&gt; [14]. This incurs very little additional cost to the normal sphere&#xD;&#xA;&gt; trace, while providing useful intersection information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In particular: `If the SDF value is smaller than the current radius, the cone has intersected an object`.&#xD;&#xA;&#xD;&#xA;Am I reading this wrong? there's no way that's true. Consider the following diagram:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;From that diagram, it seems obvious that for any cone radius $R$ there exists an SDF value $\epsilon$ such that $R &gt; \epsilon$ and the cone doesn't intersect the sphere.&#xD;&#xA;&#xD;&#xA;Am I interpreting the document wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://static1.squarespace.com/static/559921a3e4b02c1d7480f8f4/t/596773e9f7e0ab3d29bb102f/1499952110561/Mroz+Michael_746.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/wGL7T.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26128" PostHistoryTypeId="1" PostId="9508" RevisionGUID="d90ddb9a-91df-45a8-96c8-759aca649668" CreationDate="2020-01-23T16:37:12.880" UserId="7462" Text="Reading thesis on cone tracing, did the author make a mistake?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26129" PostHistoryTypeId="3" PostId="9508" RevisionGUID="d90ddb9a-91df-45a8-96c8-759aca649668" CreationDate="2020-01-23T16:37:12.880" UserId="7462" Text="|raytracing|mathematics|geometry|raymarching|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26130" PostHistoryTypeId="34" PostId="9490" RevisionGUID="29158a8a-4441-4957-89d5-66a0edf1d9f9" CreationDate="2020-01-23T17:03:20.473" UserId="-1" Comment="58" />
  <row Id="26131" PostHistoryTypeId="50" PostId="8431" RevisionGUID="3a23826d-d9fc-4240-995f-f327dc3958a9" CreationDate="2020-01-24T00:01:50.253" UserId="-1" />
  <row Id="26132" PostHistoryTypeId="2" PostId="9509" RevisionGUID="0f5f5878-2476-449b-b4c5-c3c16f4e6c29" CreationDate="2020-01-24T00:37:10.107" UserId="506" Text="It’s kind of inaccurately stated—by comparing the SDF with a linearly increasing radius, the shape that’s being traced out is a cone with a hemisphere on the end, something like this:&#xD;&#xA;&#xD;&#xA;[![diagram][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zTeTH.png&#xD;&#xA;&#xD;&#xA;At any point along the horizontal center line, if the distance to the nearest surface is less than the current test radius, the cone-plus-hemisphere has intersected that surface." ContentLicense="CC BY-SA 4.0" />
  <row Id="26133" PostHistoryTypeId="6" PostId="9504" RevisionGUID="d844c471-20ed-4cb1-8768-18604606902d" CreationDate="2020-01-24T02:36:07.873" UserId="11652" Comment="Added a tag" Text="|raytracing|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26134" PostHistoryTypeId="24" PostId="9504" RevisionGUID="d844c471-20ed-4cb1-8768-18604606902d" CreationDate="2020-01-24T02:36:07.873" Comment="Proposed by 11652 approved by 11282 edit id of 506" ContentLicense="CC BY-SA 4.0" />
  <row Id="26135" PostHistoryTypeId="2" PostId="9510" RevisionGUID="02d059ed-bf8c-44b3-8bde-133297b61165" CreationDate="2020-01-24T05:01:46.850" UserId="11784" Text="the image shown below illustrate the process to break a cube down into 4 small equal cubes.&#xD;&#xA;&#xD;&#xA;is there a term to refer to this process, something like cube-break-down?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Why would I like to know the term? Because I am trying to perform this process by coding, and I am wondering if there existing code base to do this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IOSrD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26136" PostHistoryTypeId="1" PostId="9510" RevisionGUID="02d059ed-bf8c-44b3-8bde-133297b61165" CreationDate="2020-01-24T05:01:46.850" UserId="11784" Text="is there a term to refer to this process, something like cube-break-down?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26137" PostHistoryTypeId="3" PostId="9510" RevisionGUID="02d059ed-bf8c-44b3-8bde-133297b61165" CreationDate="2020-01-24T05:01:46.850" UserId="11784" Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26138" PostHistoryTypeId="5" PostId="9437" RevisionGUID="4bf02c78-f49a-46ac-a8ce-497c7659e15f" CreationDate="2020-01-24T09:51:46.233" UserId="209" Comment="emphasised convex requirement" Text="If the end of your cylinder is **convex**, with vertices $V_0, V_1, V_2,...V_{N-1}$ then just replace your fan order (i.e. as above) with this strip $V_0, V_1, V_{N-1}, V_2, V_{N-2}, V_3...$, i.e. just zig-zag across the polygon.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26149" PostHistoryTypeId="2" PostId="9514" RevisionGUID="a09852ae-954f-4a49-b1f7-35e5145f0b72" CreationDate="2020-01-26T13:28:34.383" UserId="11797" Text="[The approximation](https://en.wikipedia.org/wiki/Schlick%27s_approximation) writes the reflection coefficient as$$R(\theta)=R_0+(1-R_0)(1-\cos\theta)^5,\,R_0=\left(\frac{n_1-n_2}{n_1+n_2}\right)^2.$$Why is the exponent 5? [Schlick 1994](https://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf) introduces this exponent in Eq. (24), claiming it's the right Fresnel approximation, but with no explanation." ContentLicense="CC BY-SA 4.0" />
  <row Id="26150" PostHistoryTypeId="1" PostId="9514" RevisionGUID="a09852ae-954f-4a49-b1f7-35e5145f0b72" CreationDate="2020-01-26T13:28:34.383" UserId="11797" Text="Why does Schlick's approximation contain a \$(1-\cos\theta)^5\$ term?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26151" PostHistoryTypeId="3" PostId="9514" RevisionGUID="a09852ae-954f-4a49-b1f7-35e5145f0b72" CreationDate="2020-01-26T13:28:34.383" UserId="11797" Text="|lighting|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26152" PostHistoryTypeId="2" PostId="9515" RevisionGUID="b875d86f-2a5f-4d40-ab0c-3d30a7e5ce64" CreationDate="2020-01-26T16:06:34.657" UserId="11799" Text="I[![enter image description here][1]][1] want to do a non-linear transformation of a svg in python. My specific problem is to transform a rectangular svg image into a frustum like image, for which i have a mathematical equation of the form (x',y') = f(x,y).&#xD;&#xA;&#xD;&#xA;So far, I've been able to find a javascript library called warp.js (https://github.com/benjamminf/warpjs), which supports application of generic point-wise transformation on svg. But I'm unable to find any such tools for python or C++ except for basic transformation like skew, rotation etc.&#xD;&#xA;&#xD;&#xA;Any help would be greatly appreciated. Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E0px9.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26153" PostHistoryTypeId="1" PostId="9515" RevisionGUID="b875d86f-2a5f-4d40-ab0c-3d30a7e5ce64" CreationDate="2020-01-26T16:06:34.657" UserId="11799" Text="Non linear transformation of vector graphic" ContentLicense="CC BY-SA 4.0" />
  <row Id="26154" PostHistoryTypeId="3" PostId="9515" RevisionGUID="b875d86f-2a5f-4d40-ab0c-3d30a7e5ce64" CreationDate="2020-01-26T16:06:34.657" UserId="11799" Text="|c++|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26155" PostHistoryTypeId="50" PostId="8807" RevisionGUID="6f42cd26-1ebe-4ea7-a82c-7c133c89c8fe" CreationDate="2020-01-27T00:03:50.517" UserId="-1" />
  <row Id="26156" PostHistoryTypeId="2" PostId="9516" RevisionGUID="15487d15-2103-4d6d-abc0-558f6128b503" CreationDate="2020-01-27T00:09:51.563" UserId="10079" Text="In reading the wikipedia page about B-Splines https://en.wikipedia.org/wiki/B-spline, I am getting confused about the concept of knots.&#xD;&#xA;&#xD;&#xA;If we have a spline of order $n$, with a knot vector ($t_0, \cdots, t_k$),&#xD;&#xA;then if the $k$ knots are distinct, I think we have $k$ polynomials that are pieced together, but if we have that $r \leq k$ knots are distinct, then I am not sure what this means.&#xD;&#xA;&#xD;&#xA; How many polynomials are we piecing together?&#xD;&#xA; How is the overall piecewise curve defined?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26157" PostHistoryTypeId="1" PostId="9516" RevisionGUID="15487d15-2103-4d6d-abc0-558f6128b503" CreationDate="2020-01-27T00:09:51.563" UserId="10079" Text="Understanding distinct vs. not distinct knots in B-splines" ContentLicense="CC BY-SA 4.0" />
  <row Id="26158" PostHistoryTypeId="3" PostId="9516" RevisionGUID="15487d15-2103-4d6d-abc0-558f6128b503" CreationDate="2020-01-27T00:09:51.563" UserId="10079" Text="|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26160" PostHistoryTypeId="2" PostId="9517" RevisionGUID="322ffa71-2fa5-4fb2-bd85-174a89827b93" CreationDate="2020-01-27T20:33:25.077" UserId="11786" Text="I extract a mesh from a method similar to Marching cube. I want to estimate the topological relationship among connected components.&#xD;&#xA;&#xD;&#xA;For example, below, let's assume that we have 4 connected components. One is the outside sphere and inside it, there are threes spheres.&#xD;&#xA;&#xD;&#xA;I computed connected components based on edge information of a mesh. Do you have any idea to extract topology information?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4fEns.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26161" PostHistoryTypeId="1" PostId="9517" RevisionGUID="322ffa71-2fa5-4fb2-bd85-174a89827b93" CreationDate="2020-01-27T20:33:25.077" UserId="11786" Text="Find the topology of connected components in a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="26162" PostHistoryTypeId="3" PostId="9517" RevisionGUID="322ffa71-2fa5-4fb2-bd85-174a89827b93" CreationDate="2020-01-27T20:33:25.077" UserId="11786" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26163" PostHistoryTypeId="5" PostId="8985" RevisionGUID="8d390a8c-8371-4f39-998e-859dcd30f97d" CreationDate="2020-01-27T21:58:22.983" UserId="9500" Comment="added backstory note; it doesn't add much, but perhaps you can feel the flow towards computing better" Text="So, I'll start by saying I'm not a driver developer, but I have read many comments and docs in this regard. &#xD;&#xA;&#xD;&#xA;First of all, we can see how Khronos's own [slides][1] on presentation day were mentioning some rather vague &quot;any OpenGL ES 3.1 GPU&quot; (or desktop 4.X). This means [something][2] added around that mark would be the secret to it. Compute shaders are definitively [at least one of] the things, being confirmed [here][3], by an [Intel developer][4], and in [the spec][5] with no possible unsupported value for `MaxComputeWorkGroupSize` and this likely smoking gun: &#xD;&#xA;&gt; If an implementation exposes any queue family that supports graphics&#xD;&#xA;&gt; operations, at least one queue family of at least one physical device&#xD;&#xA;&gt; exposed by the implementation **must** support both graphics and&#xD;&#xA;&gt; compute operations.&#xD;&#xA;&#xD;&#xA;In addition to that though, it could *also* be there are other mandatory capabilities (such as indirect draws or load&amp;store, mentioned in the comments above too). But I have some slight difficulty interpreting the document. With the exception of [robustBufferAccess][6], it seems like just about anything else big you could imagine is optional (from anisotropic filter, to geometry and tessellation shaders, to any special number format other than good old float32)&#xD;&#xA;&#xD;&#xA;This being the most hypothetically simple case then, doesn't mean it's all fine and dandy. Not having [virtual memory][7] will make your life a hell for example, and lack of other [architectural features][8] may basically nullify whatever theoretical advantage in speed the API has. &#xD;&#xA;&#xD;&#xA;These links should also answer your wonders about ATi cards. Likely same story for NVidia then (aside of perhaps some microbenchmarks, I'm not sure how much *really* workable [Fermi's][9] 2-years-delayed bare-bones DX12 support eventually is). As for Intel, I don't know what you are talking about, Gen8 is supported since [Day1][10] and in fact even [Gen7][11] *shakily* works now.&#xD;&#xA;&#xD;&#xA;Going even further back, I guess if any the question becomes &quot;what's so special about compute shaders again&quot;. &#xD;&#xA;&#xD;&#xA;And, well, the thing isn't probably the very specific [feature][12] itself (because it's [not that][13] you couldn't already do some sort of general purpose calculation even before the unified shader model), but more like the whole general GPU architecture needed to support it. Check [this][14] for some backstory. &#xD;&#xA;&#xD;&#xA;Before DX11 raised [the bar][15] for example, just think that you [couldn't][16] even run more than a single &quot;task&quot; on a Tesla GPU, without having to call a context switch (with comparable limitations also likely existing for TeraScale 1 and Gen6). And may God save us from when pixel and vertex units were separated hardware. &#xD;&#xA;&#xD;&#xA;fun fact p.s.: it turns out that if you are a low-end [kind-of-modern][17] mobile gpu (rather than an old desktop card from a time when certain concepts hadn't even been invented yet), engineers can cut you down so much that even if you just sport D3D 9_3 feature level that's still potentially [enough][18] to support Vulkan.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/assets/uploads/developers/library/overview/Vk_201602_Overview_Feb16.pdf#page=13&#xD;&#xA;  [2]: https://www.anandtech.com/show/7867/khronos-announces-opengl-es-31&#xD;&#xA;  [3]: https://pcper.com/2015/03/gdc-15-what-is-vulkan-glnext-spir-v-and-opencl-2-1/&#xD;&#xA;  [4]: https://youtu.be/2ryvYS47V0E?t=3176&#xD;&#xA;  [5]: https://www.khronos.org/registry/vulkan/specs/1.1/pdf/vkspec.pdf&#xD;&#xA;  [6]: https://www.khronos.org/registry/vulkan/specs/1.0/html/chap30.html#features-requirements&#xD;&#xA;  [7]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/open-source-amd-linux/1004192-r600-gallium3d-now-effectively-at-opengl-4-4-a-nudge-away-from-gl-4-5/page2#post1004523&#xD;&#xA;  [8]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/vulkan/845690-amd-s-vulkan-driver-will-only-work-with-the-amdgpu-kernel-driver/page3#post845731&#xD;&#xA;  [9]: https://techreport.com/news/32191/nvidia-finally-lets-fermi-gpu-owners-enjoy-directx-12/&#xD;&#xA;  [10]: https://01.org/linuxgraphics/blogs/jekstrand/2016/open-source-vulkan-drivers-intel-hardware&#xD;&#xA;  [11]: https://stackoverflow.com/questions/41497142/can-i-install-a-vulkan-driver-on-my-3rd-gen-intel-ivy-bridge-integrated-gpu-on-u&#xD;&#xA;  [12]: https://www.anandtech.com/show/2716/5&#xD;&#xA;  [13]: https://en.wikipedia.org/wiki/BrookGPU&#xD;&#xA;  [14]: https://www.gamedev.net/forums/topic/666419-what-are-your-opinions-on-dx12vulkanmantle/5215019/&#xD;&#xA;  [15]: https://stackoverflow.com/questions/3332782/can-directcompute-really-be-used-on-a-dx10-1-gpu&#xD;&#xA;  [16]: https://www.anandtech.com/show/2977/nvidia-s-geforce-gtx-480-and-gtx-470-6-months-late-was-it-worth-the-wait-/3&#xD;&#xA;  [17]: https://www.anandtech.com/show/8649/arm-announces-mali-800-series-gpus-t860-t830-t820&#xD;&#xA;  [18]: https://developer.arm.com/solutions/graphics/resources/faqs#vulkan_which" ContentLicense="CC BY-SA 4.0" />
  <row Id="26165" PostHistoryTypeId="5" PostId="9517" RevisionGUID="ed1c8da7-82ff-4335-bb98-7eef80b49f93" CreationDate="2020-01-28T11:10:59.433" UserId="11786" Comment="added 247 characters in body" Text="I extract a mesh from a method similar to Marching cube. I want to estimate the topological relationship among connected components.&#xD;&#xA;&#xD;&#xA;For example, below, let's assume that we have 4 connected components. One is the outside sphere and inside it, there are threes spheres.&#xD;&#xA;&#xD;&#xA;I computed connected components based on edge information of a mesh. Do you have any idea to extract topology information?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;My Idea is to make a tree where a node denotes an object and edge (a,b) represents that `a` contains `b`. I just compare their bounding boxes. But it can have some degenerate cases and I'm not sure how I can implement this efficiently. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4fEns.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26166" PostHistoryTypeId="2" PostId="9518" RevisionGUID="cf9dbc06-0119-4401-87d7-dc8ae2da51bd" CreationDate="2020-01-28T11:41:06.460" UserId="10928" Text="What is the correct way to invert the y axis during the 3D projection?&#xD;&#xA;&#xD;&#xA;I see a lot a people doing:&#xD;&#xA;```c&#xD;&#xA;pixel_x = (x_world / z_world + 1) / 2 * ScreenWidth(); // This is right&#xD;&#xA;pixel_y = (1 - y_world / z_world) / 2 * ScreenHeight();&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;But by inverting like this, we get an incorrect position of `pixel_y` because what this does is saying that `pixel_y` is 1 when `y_world` is -1 and 1 when `y_world` is -1. This seems right but don't forget that a point at `x == 1` in NDC space will map to `pixel_x = ScreenWidth()` and therefore won't be visible. In contrast, a point at `x == -1` in NDC space will map to `pixel_x = 0` and WILL be visible.&#xD;&#xA;So if we invert like this, a point at `y == -1` will become `pixel_y == ScreenHeight()` and WON'T be visible but a point at `y == 1` will become `pixel_y == 0` and will be visible.&#xD;&#xA;&#xD;&#xA;I think that the correct way of inverting y is by first calculating `pixel_y` like `pixel_x` and then and only then invert it in pixel space:&#xD;&#xA;```&#xD;&#xA;pixel_y = (y_world / z_world + 1) / 2 * ScreenHeight(); // Y points up&#xD;&#xA;pixel_y = ScreenHeight() - 1 - pixel_y; // now it points down&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So what is the correct way to invert the y axis during the projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26167" PostHistoryTypeId="1" PostId="9518" RevisionGUID="cf9dbc06-0119-4401-87d7-dc8ae2da51bd" CreationDate="2020-01-28T11:41:06.460" UserId="10928" Text="Y axis inversion in 3D rasterization" ContentLicense="CC BY-SA 4.0" />
  <row Id="26168" PostHistoryTypeId="3" PostId="9518" RevisionGUID="cf9dbc06-0119-4401-87d7-dc8ae2da51bd" CreationDate="2020-01-28T11:41:06.460" UserId="10928" Text="|3d|projections|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26169" PostHistoryTypeId="2" PostId="9519" RevisionGUID="b60e6595-642c-4079-bde8-68e01bd025ff" CreationDate="2020-01-28T18:07:51.260" UserId="11807" Text="First of all, you talk about inverse orientation of points in matrix, this is needed because the subtraction logic in world transformations are directly relationed with screen rotation, instead it that the camera moviments (translation you mentioned) no are directly relationed of the screen position around center of projection." ContentLicense="CC BY-SA 4.0" />
  <row Id="26170" PostHistoryTypeId="2" PostId="9520" RevisionGUID="f0213eb6-25c4-4097-8906-ee23f6aa9ea3" CreationDate="2020-01-28T21:50:15.430" UserId="7462" Text="So the number of polynomials that you piece together depends on multiple factors, including the number of control points and the degree of the curve. It the number of points is equal to the order, then you have a single polynomial, if the order is $n$ and you have $n+1$ points, then you are piecing together 2 polynomials, etc...&#xD;&#xA;&#xD;&#xA;Distinct points are points that are different from each other.&#xD;&#xA;Take the vector [0,1,2,3,4] where all knots are distinct and contrast it with [0,1,2,2,3,4] where the knot 2 has multiplicity 2 (it's not distinct since it appears twice). These knots lower the degree of the curve locally by 1 for each repetition.&#xD;&#xA;&#xD;&#xA;The overall curve can be defined in many ways, the simplest way to look at it is as DeDoor's algorithm, which is a generalisation of DeCastlejeau's.&#xD;&#xA;&#xD;&#xA;I am going to do a bit of self promotion and link my [own notes of B-Splines][1]. Gitlab's PDF viewer butchers them a bit so I recommend downloading them and reading them with Okular or Adobe reader.&#xD;&#xA;&#xD;&#xA;Regardless, that document has more information than what can be put into a stack exchange answer and does indeed try to convey the intuition about how to build B-Splines, both mathematically and algorithmically.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gitlab.com/Makogan/mathproofs/blob/master/B-splines/b-splines.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="26173" PostHistoryTypeId="2" PostId="9522" RevisionGUID="d667d2cd-2b1b-40e6-870e-27d2899406b2" CreationDate="2020-01-29T06:11:42.507" UserId="6442" Text="Let's look at your formula:&#xD;&#xA;&#xD;&#xA;    pixel_y = (y_world / z_world + 1) / 2 * ScreenHeight();&#xD;&#xA;    pixel_y = ScreenHeight() - 1 - pixel_y;&#xD;&#xA;&#xD;&#xA;Let's call `y_world / z_world` for short `a`, `H` for `ScreenHeight()`. So you have:&#xD;&#xA;&#xD;&#xA;    Y = (a + 1) / 2 *H&#xD;&#xA;    Y = H - 1 - Y&#xD;&#xA;&#xD;&#xA;Let's replace the first in the second:&#xD;&#xA;&#xD;&#xA;       Y = H - 1 - (a + 1) / 2 * H&#xD;&#xA;    =&gt; Y = H * (1 - (a + 1) / 2) - 1&#xD;&#xA;    =&gt; Y = H * ((2 - a - 1) / 2) - 1&#xD;&#xA;    =&gt; Y = H * (1 - a) / 2 - 1&#xD;&#xA;&#xD;&#xA;Which is the formula you said every one uses (except with an off-by-one error):&#xD;&#xA;&#xD;&#xA;    pixel_y = (1 - y_world / z_world) / 2 * ScreenHeight();&#xD;&#xA;&#xD;&#xA;Off-by-one error aside, looks like you have the right understanding, just didn't work out that the formula everyone uses is the optimized version of what you came up with." ContentLicense="CC BY-SA 4.0" />
  <row Id="26177" PostHistoryTypeId="4" PostId="9517" RevisionGUID="56794ef9-dc5d-4d2d-99ef-b121ae8dd42d" CreationDate="2020-01-29T07:51:46.923" UserId="11786" Comment="edited title" Text="Find the inside and outside relationship of connected components in a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="26178" PostHistoryTypeId="2" PostId="9524" RevisionGUID="275377eb-9867-419c-a5dc-79a1ff677b7c" CreationDate="2020-01-29T08:09:47.407" UserId="9971" Text="I have found the following from this link&#xD;&#xA;[enter link description here][1]&#xD;&#xA;&#xD;&#xA;&gt; pData&#xD;&#xA;&gt; &#xD;&#xA;&gt; Type: void*&#xD;&#xA;&gt; &#xD;&#xA;&gt; Pointer to the data. When ID3D11DeviceContext::Map provides the&#xD;&#xA;&gt; pointer, the runtime ensures that the pointer has a specific&#xD;&#xA;&gt; alignment, depending on the following feature levels:&#xD;&#xA;&gt; &#xD;&#xA;&gt; For D3D_FEATURE_LEVEL_10_0 and higher, the pointer is aligned to 16&#xD;&#xA;&gt; bytes. For lower than D3D_FEATURE_LEVEL_10_0, the pointer is aligned&#xD;&#xA;&gt; to 4 bytes.&#xD;&#xA;&#xD;&#xA;Would someone please explain if I can reinterpret cast the void pointer into OLD_HANDLE or not?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_mapped_subresource" ContentLicense="CC BY-SA 4.0" />
  <row Id="26179" PostHistoryTypeId="1" PostId="9524" RevisionGUID="275377eb-9867-419c-a5dc-79a1ff677b7c" CreationDate="2020-01-29T08:09:47.407" UserId="9971" Text="void* D3D11_MAPPED_SUBRESOURCE::pData to OLE_HANDLE possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26180" PostHistoryTypeId="3" PostId="9524" RevisionGUID="275377eb-9867-419c-a5dc-79a1ff677b7c" CreationDate="2020-01-29T08:09:47.407" UserId="9971" Text="|c++|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26181" PostHistoryTypeId="2" PostId="9525" RevisionGUID="5ca7567f-5e78-4968-9ae3-5de7e1f7814e" CreationDate="2020-01-29T12:58:34.423" UserId="11811" Text="(possible duplicate)&#xD;&#xA;&#xD;&#xA;I'm trying to implement multiple importance sampling, as described in the [PBRT book][1] (no bouncing yet, I want to make MIS work first).&#xD;&#xA;&#xD;&#xA;What my problem is, that while the BRDF sampling looks okay, the light sampling is much dimmer (yet according to the pictures in the book they should look the same in intensity).&#xD;&#xA;&#xD;&#xA;[![sampling the BRDF][2]][2]&#xD;&#xA;[![sampling the light][3]][3]&#xD;&#xA;&#xD;&#xA;I uploaded the [compilable code][4] (VS 2015). The relevant parts can be found in *multipleimportance.frag* (SampleLightsExplicit) and *pbr_common.head* (ConeSampleSphere).&#xD;&#xA;&#xD;&#xA;*(note that I don't apply the MIS weights yet)*&#xD;&#xA;&#xD;&#xA;    for (int k = 0; k &lt; numLights; ++k) {&#xD;&#xA;        SceneObject light = objects.data[k];&#xD;&#xA;    &#xD;&#xA;        center = vec3(light.toworld[3].xyz);&#xD;&#xA;        radius = light.toworld[0][0];&#xD;&#xA;    &#xD;&#xA;        // importance sample light (xyz = direction, w = PDF)&#xD;&#xA;        sample1 = ConeSampleSphere(p, center, radius, pixel, seed + float(k));&#xD;&#xA;    &#xD;&#xA;        // cast shadow ray&#xD;&#xA;        vis = Visibility(p, sample1.xyz, k);&#xD;&#xA;        ndotl = vis * max(0.0, dot(sample1.xyz, n));&#xD;&#xA;    &#xD;&#xA;        // evaluate BRDF&#xD;&#xA;        fd = vec3(0.0); //obj.color.rgb * ONE_OVER_PI;&#xD;&#xA;        fs = CookTorrance_General(sample1.xyz, v, n, vec3(0.04), roughness);&#xD;&#xA;    &#xD;&#xA;        sum += (light.color.rgb * (fd + fs) * ndotl) / sample1.w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My question is why light sampling looks so dim? Did I misunderstand something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#fragment-SampleBSDFwithmultipleimportancesampling-0&#xD;&#xA;  [2]: https://i.stack.imgur.com/W36nQm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/2zQz2m.jpg&#xD;&#xA;  [4]: https://www.dropbox.com/s/bkprhax5dgwpmu2/FOR_STACKEXCHANGE_1.zip?dl=0" ContentLicense="CC BY-SA 4.0" />
  <row Id="26182" PostHistoryTypeId="1" PostId="9525" RevisionGUID="5ca7567f-5e78-4968-9ae3-5de7e1f7814e" CreationDate="2020-01-29T12:58:34.423" UserId="11811" Text="Sampling the light vs. sampling the BRDF: difference in intensity" ContentLicense="CC BY-SA 4.0" />
  <row Id="26183" PostHistoryTypeId="3" PostId="9525" RevisionGUID="5ca7567f-5e78-4968-9ae3-5de7e1f7814e" CreationDate="2020-01-29T12:58:34.423" UserId="11811" Text="|opengl|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26184" PostHistoryTypeId="2" PostId="9526" RevisionGUID="080c22aa-698a-4bc0-ac21-1fa5b0409179" CreationDate="2020-01-29T14:35:55.033" UserId="11813" Text="&#xD;&#xA;&#xD;&#xA;I want to set the color of the lamps in my game with a black body curve, but the approximations I can find for it are all in sRGB color space; and I want it in linear floating RGB.&#xD;&#xA;&#xD;&#xA;The closest thing i was able to find is this: https://mathematica.stackexchange.com/questions/57389/convert-spectral-distribution-to-rgb-color&#xD;&#xA;&#xD;&#xA;But i really don't understand most of the notation in the answer.&#xD;&#xA;&#xD;&#xA;Mainly I'm unsure: if i just use planck's law, using the wavelengths of the subpixels in a standard monitor--not that I know what those are--will it get the right answer, or would it need to be an integral with respect to cone response.&#xD;&#xA;&#xD;&#xA;Furthermore I'm not sure how to normalize the resulting radiation density from.... whatever units its in, to 1.0 = X nits; as I'm unsure of the conversion between the units..." ContentLicense="CC BY-SA 4.0" />
  <row Id="26185" PostHistoryTypeId="1" PostId="9526" RevisionGUID="080c22aa-698a-4bc0-ac21-1fa5b0409179" CreationDate="2020-01-29T14:35:55.033" UserId="11813" Text="Blackbody curve to floating RGB" ContentLicense="CC BY-SA 4.0" />
  <row Id="26186" PostHistoryTypeId="3" PostId="9526" RevisionGUID="080c22aa-698a-4bc0-ac21-1fa5b0409179" CreationDate="2020-01-29T14:35:55.033" UserId="11813" Text="|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26187" PostHistoryTypeId="2" PostId="9527" RevisionGUID="a8c6d058-84b3-4ad5-9a65-97d311dd0184" CreationDate="2020-01-29T15:17:22.400" UserId="6284" Text="The code below is based on the article [How to Convert Temperature (K) to RGB: Algorithm and Sample Code](http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code) with Neil Bartlett modifications from the article [Color Temperature Conversion Of Homestar.io](http://www.zombieprototypes.com/?p=210).&#xD;&#xA;&#xD;&#xA;Bartlett has released a javascript library [`neilbartlett/color-temperature`](https://github.com/neilbartlett/color-temperature) which computes RGB from kelvin with the color components in the range `0` to `255`. The code below is adjusted for RGB components in the range `0.0` to `1.0`.&#xD;&#xA;&#xD;&#xA;    float t = kelvin / 100.0;&#xD;&#xA;    float x;&#xD;&#xA;    float red;&#xD;&#xA;    float green;&#xD;&#xA;    float blue;&#xD;&#xA;    if (t &lt;= 66)&#xD;&#xA;    {&#xD;&#xA;        red = 1.0;&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        x = t - 55.0;&#xD;&#xA;        red = clamp(&#xD;&#xA;            1.38030159086 + 0.00044786845 * x - 0.15785750233 * log(x),&#xD;&#xA;            0.0,&#xD;&#xA;            1.0);&#xD;&#xA;    }&#xD;&#xA;    if (t &lt;= 10)&#xD;&#xA;    {&#xD;&#xA;        green = 0.0;&#xD;&#xA;    }&#xD;&#xA;    else if (t &lt;= 66)&#xD;&#xA;    {&#xD;&#xA;        x = t - 2.0;&#xD;&#xA;        green = clamp(&#xD;&#xA;            -0.60884257109 - 0.00174890002 * x + 0.40977318429 * log(x),&#xD;&#xA;            0.0,&#xD;&#xA;            1.0);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        x = t - 50.0;&#xD;&#xA;        green = clamp(&#xD;&#xA;            1.27627220616 + 0.0003115081 * x - 0.11013841706 * log(x),&#xD;&#xA;            0.0,&#xD;&#xA;            1.0);&#xD;&#xA;    }&#xD;&#xA;    if (t &lt;= 20)&#xD;&#xA;    {&#xD;&#xA;        blue = 0.0;&#xD;&#xA;    }&#xD;&#xA;    else if (t &lt;= 66)&#xD;&#xA;    {&#xD;&#xA;        x = t - 10.0;&#xD;&#xA;        blue = clamp(&#xD;&#xA;            -0.99909549742 + 0.00324474355 * x + 0.45364683926 * log(x),&#xD;&#xA;            0.0,&#xD;&#xA;            1.0);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        blue = 1.0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Note**: `log` refers to natural log." ContentLicense="CC BY-SA 4.0" />
  <row Id="26188" PostHistoryTypeId="2" PostId="9528" RevisionGUID="03250dff-a37a-4276-be09-d4908ed5eb76" CreationDate="2020-01-29T18:16:23.403" UserId="5717" Text="The [Open Shading Language][1] has [a complete implementation][2] which is based on [this source code][3] from [Color Rendering of Spectra][4] by John Walker, according to the comments. I can't vouch for its theoretical correctness but I have used it and it appears to work reasonably well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/imageworks/OpenShadingLanguage/&#xD;&#xA;  [2]: https://github.com/imageworks/OpenShadingLanguage/blob/master/src/liboslexec/opcolor.cpp#L785&#xD;&#xA;  [3]: http://www.fourmilab.ch/documents/specrend/specrend.c&#xD;&#xA;  [4]: https://www.fourmilab.ch/documents/specrend/" ContentLicense="CC BY-SA 4.0" />
  <row Id="26190" PostHistoryTypeId="5" PostId="9517" RevisionGUID="d011159b-a812-4504-8565-1beb0fe74f21" CreationDate="2020-01-30T14:52:02.690" UserId="7462" Comment="Corrected the grammar" Text="I extract a mesh from a method similar to Marching cubes. I want to estimate the topological relationship between connected components.&#xD;&#xA;&#xD;&#xA;For example, below, let's assume that we have 4 connected components. One is the outside sphere and inside it there are threes spheres.&#xD;&#xA;&#xD;&#xA;I computed the connected components based on the edge information of the mesh. Do you have an idea about how to extract topology information?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;My Idea is to make a tree where a node denotes an object and edge (a,b) represents that `a` contains `b`. I just compare their bounding boxes. But it can have some degenerate cases and I'm not sure how I can implement this efficiently. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4fEns.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26191" PostHistoryTypeId="24" PostId="9517" RevisionGUID="d011159b-a812-4504-8565-1beb0fe74f21" CreationDate="2020-01-30T14:52:02.690" Comment="Proposed by 7462 approved by 209, 6 edit id of 508" ContentLicense="CC BY-SA 4.0" />
  <row Id="26192" PostHistoryTypeId="5" PostId="9510" RevisionGUID="14c520e0-6e3f-4b76-8887-d9b86e30b7f5" CreationDate="2020-01-30T16:57:03.323" UserId="11652" Comment="Another title" Text="The image shown below illustrate the process to break a cube down into 4 small equal cubes.&#xD;&#xA;&#xD;&#xA;Is there a term to refer to this process, something like cube-break-down?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Why would I like to know the term?  &#xD;&#xA;&#xD;&#xA;Because I am trying to perform this process by coding, and I am wondering if there existing code base to do this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IOSrD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26193" PostHistoryTypeId="4" PostId="9510" RevisionGUID="14c520e0-6e3f-4b76-8887-d9b86e30b7f5" CreationDate="2020-01-30T16:57:03.323" UserId="11652" Comment="Another title" Text="Is there a term to refer to a cube-break-down process?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26194" PostHistoryTypeId="24" PostId="9510" RevisionGUID="14c520e0-6e3f-4b76-8887-d9b86e30b7f5" CreationDate="2020-01-30T16:57:03.323" Comment="Proposed by 11652 approved by 209, 6 edit id of 507" ContentLicense="CC BY-SA 4.0" />
  <row Id="26209" PostHistoryTypeId="50" PostId="9103" RevisionGUID="71151c2a-d03c-4bba-8851-41ba4523c02f" CreationDate="2020-01-31T22:02:30.353" UserId="-1" />
  <row Id="26210" PostHistoryTypeId="2" PostId="9533" RevisionGUID="7b4f4a0f-6b9a-4fe3-9cf7-fac997027e8b" CreationDate="2020-01-31T23:30:25.133" UserId="11282" Text="I've seen lots of spins on the ray-box intersection test, and a lot of them seem to boil down to this code: (omitting some details here)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  invRay.x = 1.0 / ray.x;&#xD;&#xA;&#xD;&#xA;  tx1 = (box.min.x - rayOrigin.x) * invRay.x;&#xD;&#xA;  tx2 = (box.max.x - rayOrigin.x) * invRay.x;&#xD;&#xA;&#xD;&#xA;  tmin = min(tx1, tx2);&#xD;&#xA;  tmax = max(tx1, tx2);&#xD;&#xA;&#xD;&#xA;  // Repeat for Y and Z&#xD;&#xA;  // Then check to ensure tmin &lt; tmax&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(I got mine specifically from [this discussion](https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms) and [this source](https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c#n196). Also note that if you use std::min and std::max, it's far from branchless)&#xD;&#xA;&#xD;&#xA;However, this raises a significant problem.&#xD;&#xA;&#xD;&#xA;What if the ray's origin in one or more dimensions is equal to the min or max points?&#xD;&#xA;&#xD;&#xA;What I found is that I get this situation on an example ray and box:&#xD;&#xA;&#xD;&#xA;* Ray origin: (3.225, 0.243, 2.221)&#xD;&#xA;* Ray direction: (0, 0, -1)&#xD;&#xA;* Box min: (3.223, 0.241, 2.119)&#xD;&#xA;* Box max: (3.225, 0.243, 2.121)&#xD;&#xA;&#xD;&#xA;Is that when tx1 is calculated, it correctly gets -inf. However, when tx2 is calculated, it gets ```(3.225 - 3.225) * inf``` which is coming out to ```-nan```. This means that later, when we do:&#xD;&#xA;&#xD;&#xA;```float tmax = std::max(tx1, tx2);```&#xD;&#xA;&#xD;&#xA;We get ```max(-inf, -nan)``` which comes out to ```-inf``` and from that point on in the tests, tmax will always be -inf, making the overall ray-box test fail.&#xD;&#xA;&#xD;&#xA;This is confirmed by some comments on the page where I got the code:&#xD;&#xA;&#xD;&#xA;&gt;Something to consider here is that 0 * inf =nan which occurs when the ray starts exactly on the edge of a box&#xD;&#xA;&#xD;&#xA;And&#xD;&#xA;&#xD;&#xA;&gt;Having read both this and part 2, I'm unable to work out what changes I need to make in order to reliably detect intersections when a ray is exactly on the edge of an AABB.&#xD;&#xA;&#xD;&#xA;Does anyone know a fast method for ray-box intersection with edge and corner hits?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26211" PostHistoryTypeId="1" PostId="9533" RevisionGUID="7b4f4a0f-6b9a-4fe3-9cf7-fac997027e8b" CreationDate="2020-01-31T23:30:25.133" UserId="11282" Text="Need a fast ray-box intersection that also handles edge and corner hits" ContentLicense="CC BY-SA 4.0" />
  <row Id="26212" PostHistoryTypeId="3" PostId="9533" RevisionGUID="7b4f4a0f-6b9a-4fe3-9cf7-fac997027e8b" CreationDate="2020-01-31T23:30:25.133" UserId="11282" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26214" PostHistoryTypeId="5" PostId="9525" RevisionGUID="fa582bda-4c9e-4105-b3cd-44338b25c57e" CreationDate="2020-02-01T11:00:03.620" UserId="11811" Comment="added 1214 characters in body" Text="(possible duplicate)&#xD;&#xA;&#xD;&#xA;I'm trying to implement multiple importance sampling, as described in the [PBRT book][1] (no bouncing yet, I want to make MIS work first).&#xD;&#xA;&#xD;&#xA;What my problem is, that while the BRDF sampling looks okay, the light sampling is much dimmer (yet according to the pictures in the book they should look the same in intensity).&#xD;&#xA;&#xD;&#xA;[![sampling the BRDF][2]][2]&#xD;&#xA;[![sampling the light][3]][3]&#xD;&#xA;&#xD;&#xA;I uploaded the *(updated)* [compilable code][4] (VS 2015). The relevant parts can be found in *multipleimportance.frag* (SampleLightsExplicit) and *pbr_common.head* (ConeSampleSphere).&#xD;&#xA;&#xD;&#xA;*(note that I don't apply the MIS weights yet)*&#xD;&#xA;&#xD;&#xA;    for (int k = 0; k &lt; numLights; ++k) {&#xD;&#xA;        SceneObject light = objects.data[k];&#xD;&#xA;    &#xD;&#xA;        center = vec3(light.toworld[3].xyz);&#xD;&#xA;        radius = light.toworld[0][0];&#xD;&#xA;    &#xD;&#xA;        // importance sample light (xyz = direction, w = PDF)&#xD;&#xA;        sample1 = ConeSampleSphere(p, center, radius, pixel, seed + float(k));&#xD;&#xA;    &#xD;&#xA;        // cast shadow ray&#xD;&#xA;        vis = Visibility(p, sample1.xyz, k);&#xD;&#xA;        ndotl = vis * max(0.0, dot(sample1.xyz, n));&#xD;&#xA;    &#xD;&#xA;        // evaluate BRDF&#xD;&#xA;        fd = vec3(0.0); //obj.color.rgb * ONE_OVER_PI;&#xD;&#xA;        fs = CookTorrance_General(sample1.xyz, v, n, vec3(0.04), roughness);&#xD;&#xA;    &#xD;&#xA;        sum += (light.color.rgb * (fd + fs) * ndotl) / sample1.w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My question is why light sampling looks so dim? Did I misunderstand something?&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;&#xD;&#xA;Looking through the code I noticed some inconsistencies which probably originated from a typo in one of the older SIGGRAPH course notes (can't tell which one tho).&#xD;&#xA;&#xD;&#xA;The PDF of the GGX distribution is:&#xD;&#xA;&#xD;&#xA;    PDF = D(h) * dot(n, h)&#xD;&#xA;&#xD;&#xA;While some implementations (including UE4) incorrectly write it as&#xD;&#xA;&#xD;&#xA;    PDF = (D(h) * dot(n, h)) / (4 * dot(v, h))&#xD;&#xA;&#xD;&#xA;which essentially means that they include the Cook-Torrance denominator into this variable (*ndotl* cancels out). Dividing with the correct PDF cancels out *D* in the Cook-Torrance model, which I forgot to account for, while the *1 / (4 \* dot(v, h))* term goes into the *Vis_Schlick* function.&#xD;&#xA;&#xD;&#xA;So regarding intensity the second picture is the &quot;correct&quot; one. The dimness is still a problem tho. Changing the Fresnel *F0* to 0.11 (as it supposedly is in the book) and applying the MIS weights, the picture looks a lot more promising, except for the topmost plate which should almost explicitly reflect the light sources:&#xD;&#xA;&#xD;&#xA;[![multiple importance sampling][5]][5]&#xD;&#xA;&#xD;&#xA;So this is *almost okay* now. I'm gonna look deeper into the MIS part to see why it makes those highlights disappear.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#fragment-SampleBSDFwithmultipleimportancesampling-0&#xD;&#xA;  [2]: https://i.stack.imgur.com/W36nQm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/2zQz2m.jpg&#xD;&#xA;  [4]: https://www.dropbox.com/s/bkprhax5dgwpmu2/FOR_STACKEXCHANGE_1.zip?dl=0&#xD;&#xA;  [5]: https://i.stack.imgur.com/lFnVt.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26224" PostHistoryTypeId="2" PostId="9537" RevisionGUID="c8d4c88a-b50d-41a7-b3d4-8f86820d19f8" CreationDate="2020-02-02T23:38:38.570" UserId="10461" Text="When I was writing a software rasterizer for my university class, we did culling in  eye coordinates. Essentially, we use cross product to get a normal from the 3 vertices (in eye coordinates), then we dot product that normal with one of the 3 vertices (since we are in eye coordinate, that vertex is essentially a vector from eye [0, 0, 0,.1] to triangle surface). If the dot product is &gt; 0, meaning the normal and the eye vector point in the same direction, we cull that triangle.&#xD;&#xA;&#xD;&#xA;OpenGL however doesn't do culling in eye space, since culling is after vertex shader. So all they have are vertices in clip space. So how do they know which triangle to do culling? Our triangles, when fed into the graphic pipeline, are always in CCW order. How do some turn into CW order?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26225" PostHistoryTypeId="1" PostId="9537" RevisionGUID="c8d4c88a-b50d-41a7-b3d4-8f86820d19f8" CreationDate="2020-02-02T23:38:38.570" UserId="10461" Text="How does graphics api like OpenGL determine which triangle is back face to cull?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26226" PostHistoryTypeId="3" PostId="9537" RevisionGUID="c8d4c88a-b50d-41a7-b3d4-8f86820d19f8" CreationDate="2020-02-02T23:38:38.570" UserId="10461" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26227" PostHistoryTypeId="50" PostId="9116" RevisionGUID="d14daeab-b3f3-47bd-ab94-b47d5cb103b2" CreationDate="2020-02-03T08:01:30.177" UserId="-1" />
  <row Id="26228" PostHistoryTypeId="2" PostId="9538" RevisionGUID="a506b555-742a-48c2-8a50-f32ca9d764ba" CreationDate="2020-02-03T09:51:12.430" UserId="209" Text="It's actually fairly simple (and in essence 'equivalent' to what you said above). If you represent triangle ABC's *projected* XY coordinates as a matrix...&#xD;&#xA;&#xD;&#xA;$$M_{ABC} =   \begin{bmatrix}&#xD;&#xA;    X_A &amp; X_B &amp; X_C \\&#xD;&#xA;    Y_A &amp; Y_B &amp; Y_C \\&#xD;&#xA;    1 &amp; 1 &amp; 1 \\&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;...then the sign of the determinant e.g. $X_A (Y_B - Y_C)+X_B(Y_C-Ya)+X_C(Y_A-Y_B)$ will allow you to decide how to cull. &#xD;&#xA;Further if the determinant is zero, then the on-screen triangle has zero area and can clearly be removed.&#xD;&#xA;&#xD;&#xA;Another reason to use this notation is that the adjoint of $M_{ABC}$  gives you equations for the edges." ContentLicense="CC BY-SA 4.0" />
  <row Id="26229" PostHistoryTypeId="50" PostId="8462" RevisionGUID="5b3b51f4-8bc6-45fe-9f57-cd724dd8086d" CreationDate="2020-02-03T10:02:40.330" UserId="-1" />
  <row Id="26230" PostHistoryTypeId="2" PostId="9539" RevisionGUID="5bb54752-f842-4595-ae6a-b47348b23300" CreationDate="2020-02-03T12:27:49.927" UserId="10188" Text="Currently I have textures which need GL_NEAREST and some other need GL_LINEAR in the same texture2dArray. In the shader I perform a manual GL_NEAREST lookup via textureFetch().&#xD;&#xA;&#xD;&#xA;To avoid this my question is, is it possible to set the value of GL_TEXTURE_MIN/MAG_FILTER for each texture in a texture array to different values?&#xD;&#xA;&#xD;&#xA;I know of the same size restrictions, but could not find anything regarding mipmapping.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26231" PostHistoryTypeId="1" PostId="9539" RevisionGUID="5bb54752-f842-4595-ae6a-b47348b23300" CreationDate="2020-02-03T12:27:49.927" UserId="10188" Text="2D array texture with different mipmap setting per texture?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26232" PostHistoryTypeId="3" PostId="9539" RevisionGUID="5bb54752-f842-4595-ae6a-b47348b23300" CreationDate="2020-02-03T12:27:49.927" UserId="10188" Text="|opengl|texture|3dtexture|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26233" PostHistoryTypeId="2" PostId="9540" RevisionGUID="6a60e2f2-08c6-439d-b4fd-030989d29d64" CreationDate="2020-02-03T14:41:39.860" UserId="2654" Text="&gt; then we dot product that normal with one of the 3 vertices&#xD;&#xA;&#xD;&#xA;That's incorrect. It's not difficult to construct a scenario where this will result in an incorrect determination of facing.&#xD;&#xA;&#xD;&#xA;Imagine a triangle that is nearly edge-on with the view, but is still facing the view. Now, imagine that this triangle has a normal that, when edge-on, is pointed slightly away from the view. Remember: vertex normals on a surface that is supposed to be curved represent the normal at that portion of the curved surface. And therefore they don't have to be aligned with the face normal.&#xD;&#xA;&#xD;&#xA;In any case, the math for determining the facing of a triangle happens in *window* space, not clip-space. It's pretty simple: you get the direction from the first position to the second and the direction from the second to the third. And you take the cross-product of them. If the Z component of the cross product is positive, then the triangle is counter-clockwise, relative to the window. So this doesn't even require the entire cross product; just the Z component (and just the sign of it at that)." ContentLicense="CC BY-SA 4.0" />
  <row Id="26234" PostHistoryTypeId="2" PostId="9541" RevisionGUID="b0d95907-bd44-48da-b6a5-f80abefce31d" CreationDate="2020-02-03T15:22:22.857" UserId="11811" Text="Shoot me... After the fixes I posted above, I started debugging Mitsuba to see whether it does anything differently on a large scale. Of course it didn't; my code is completely correct, the dimness is due to this macro def:&#xD;&#xA;&#xD;&#xA;    #define EPSILON   1e-5&#xD;&#xA;&#xD;&#xA;This is used in divisions to avoid dividing with zero. Unfortunately, it accumulates to a large value during the calculations. Changing it to 1e-9 fixes everything:&#xD;&#xA;&#xD;&#xA;[![mis_final][1]][1]&#xD;&#xA;&#xD;&#xA;For future generations I leave the source code up (just remember to change this value).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/URn4F.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26235" PostHistoryTypeId="2" PostId="9542" RevisionGUID="28846902-e6a7-4c13-993b-f6158b4e78fa" CreationDate="2020-02-03T17:04:47.317" UserId="6114" Text="Here you have a full repository with a lot of papers about light transport. There's also a folder named 'theory' where you can get both intro and advanced refs regard light physics. And much more. I'm personally curating this and keeping up to date with latest advancements. &#xD;&#xA;&#xD;&#xA;https://drive.google.com/drive/folders/16A6Yj2esRTk0FP-ALr6XfxkGQvTb_1dD?usp=sharing&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26236" PostHistoryTypeId="4" PostId="9533" RevisionGUID="10343a49-a820-4c97-b4b0-326ae18579cf" CreationDate="2020-02-03T17:59:27.827" UserId="11282" Comment="edited title" Text="Need a fast ray-box intersection that handles if a ray is parallel and in line with a plane of the box" ContentLicense="CC BY-SA 4.0" />
  <row Id="26237" PostHistoryTypeId="2" PostId="9543" RevisionGUID="0e5d5afa-2d83-40a1-b5bd-b65354fe7c1a" CreationDate="2020-02-03T19:24:32.273" UserId="11282" Text="Here is how I found this can be solved.&#xD;&#xA;&#xD;&#xA;(The below also happens at the start, just fyi)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  float tmin = std::numeric_limits&lt;float&gt;::lowest();&#xD;&#xA;  float tmax = std::numeric_limits&lt;float&gt;::max();&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Add an additional check:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;if(rayDir.x == 0.0f)&#xD;&#xA;{&#xD;&#xA;  if (rayOrigin.x() &lt; box.min.x() || rayOrigin.x() &gt; box.max.x())&#xD;&#xA;  {     &#xD;&#xA;    return false;&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;else &#xD;&#xA;{&#xD;&#xA;  tx1 = (box.min.x - rayOrigin.x) * invRay.x;&#xD;&#xA;  tx2 = (box.max.x - rayOrigin.x) * invRay.x;&#xD;&#xA;&#xD;&#xA;  tmin = std::max(tmin, std::min(tx1, tx2));&#xD;&#xA;  tmax = std::min(tmax, std::max(tx1, tx2));&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This way the tx1/tx2 values never get calculated if the ray's direction vector is zero in that direction, aka if it's parallel to that plane.&#xD;&#xA;&#xD;&#xA;It's not particularly compact or pretty, but it does neatly solve the issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="26238" PostHistoryTypeId="2" PostId="9544" RevisionGUID="a25b1e2e-4737-40f9-a918-820a5a51b06d" CreationDate="2020-02-04T01:53:07.500" UserId="7462" Text="Assume we have a mesh represented as a HE.&#xD;&#xA;&#xD;&#xA;We want to subdivide faces without introducing unnecessary vertices (i.e the new number of vertices must be exactly V + E where V is the old number of vertices and E is the old number of edges).&#xD;&#xA;&#xD;&#xA;This is what a single subdivided triangle looks like:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I naively try to iterate over every edge and reconnect faces I get the following sequence&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Clearly this is wrong.&#xD;&#xA;&#xD;&#xA;If instead I iterate over the faces I get the following pattern:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This is hapening because at every step I am trying to to:&#xD;&#xA;&#xD;&#xA; * Focus on only one simplex at a time, &#xD;&#xA; * Maintain the connectivity information of the mesh in a valid state (every edge has &lt;2 faces, vertices only exist at the end of edges, faces only have 3 Half edges...), like for example, I am avoiding getting into this state:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Any suggestions?&#xD;&#xA;  [1]: https://i.stack.imgur.com/MYmhk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Jgn94.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/D4SZe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/04SMi.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/vWp6b.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4SexY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26239" PostHistoryTypeId="1" PostId="9544" RevisionGUID="a25b1e2e-4737-40f9-a918-820a5a51b06d" CreationDate="2020-02-04T01:53:07.500" UserId="7462" Text="How to subdivide faces with a half edge DS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26240" PostHistoryTypeId="3" PostId="9544" RevisionGUID="a25b1e2e-4737-40f9-a918-820a5a51b06d" CreationDate="2020-02-04T01:53:07.500" UserId="7462" Text="|mathematics|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26241" PostHistoryTypeId="5" PostId="9544" RevisionGUID="477cd4b5-f7fd-4eeb-9cb2-407df9c4dc1f" CreationDate="2020-02-04T03:44:22.617" UserId="7462" Comment="added 65 characters in body" Text="Assume we have a mesh represented as a HE.&#xD;&#xA;&#xD;&#xA;We want to subdivide faces without introducing unnecessary vertices (i.e the new number of vertices must be exactly V + E where V is the old number of vertices and E is the old number of edges).&#xD;&#xA;&#xD;&#xA;This is what a single subdivided triangle looks like:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I naively try to iterate over every edge and reconnect faces I get the following sequence&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Clearly this is wrong.&#xD;&#xA;&#xD;&#xA;If instead I iterate over the faces I get the following pattern:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This is hapening because at every step I am trying to to:&#xD;&#xA;&#xD;&#xA; * Focus on only one simplex at a time, &#xD;&#xA; * Maintain the connectivity information of the mesh in a valid state (every edge has &lt;2 faces, vertices only exist at the end of edges, faces only have 3 Half edges...), like for example, I am avoiding getting into this state:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Any suggestions?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Found this, but I don;t know what edge flipping means.&#xD;&#xA;  [1]: https://i.stack.imgur.com/MYmhk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Jgn94.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/D4SZe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/04SMi.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/vWp6b.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4SexY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26242" PostHistoryTypeId="5" PostId="9544" RevisionGUID="7e3045f3-17fe-40be-9071-e8f9fc7b8a95" CreationDate="2020-02-04T03:53:08.167" UserId="7462" Comment="deleted 65 characters in body" Text="Assume we have a mesh represented as a HE.&#xD;&#xA;&#xD;&#xA;We want to subdivide faces without introducing unnecessary vertices (i.e the new number of vertices must be exactly V + E where V is the old number of vertices and E is the old number of edges).&#xD;&#xA;&#xD;&#xA;This is what a single subdivided triangle looks like:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I naively try to iterate over every edge and reconnect faces I get the following sequence&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Clearly this is wrong.&#xD;&#xA;&#xD;&#xA;If instead I iterate over the faces I get the following pattern:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This is hapening because at every step I am trying to to:&#xD;&#xA;&#xD;&#xA; * Focus on only one simplex at a time, &#xD;&#xA; * Maintain the connectivity information of the mesh in a valid state (every edge has &lt;2 faces, vertices only exist at the end of edges, faces only have 3 Half edges...), like for example, I am avoiding getting into this state:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Any suggestions?&#xD;&#xA;  [1]: https://i.stack.imgur.com/MYmhk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Jgn94.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/D4SZe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/04SMi.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/vWp6b.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4SexY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26243" PostHistoryTypeId="4" PostId="9539" RevisionGUID="ff05dbb5-6692-4e87-99ab-2797bcffb2ab" CreationDate="2020-02-04T06:00:20.217" UserId="2654" Comment="edited title" Text="2D array texture with different filtering setting per texture?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26244" PostHistoryTypeId="2" PostId="9545" RevisionGUID="7458bc97-2b55-49a9-a871-0549aa1d7607" CreationDate="2020-02-04T06:06:29.833" UserId="2654" Text="Array textures do not contain textures; they are a single texture that contains a number of images, with each image being of the same size, format, mipmap depth, etc.&#xD;&#xA;&#xD;&#xA;As such, the [sampling parameters that are part of the texture][1] apply to sample fetches for all images within the texture.&#xD;&#xA;&#xD;&#xA;That having been said:&#xD;&#xA;&#xD;&#xA;&gt; In the shader I perform a manual GL_NEAREST lookup via textureFetch().&#xD;&#xA;&#xD;&#xA;This means your FS knows when to look the texture up with linear filtering and when not to. As such, you could have two different array texture samplers in the shader, one of which you expect to use linear sampling and one which uses nearest.&#xD;&#xA;&#xD;&#xA;Both of these samplers can be using the same texture object, just paired with a different *[sampler object][2]* (which contains all of the filtering parameters for the texture). One sampler would use nearest filtering, the other would use linear.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Texture#Texture_Objects&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Sampler_Object" ContentLicense="CC BY-SA 4.0" />
  <row Id="26245" PostHistoryTypeId="19" PostId="1718" RevisionGUID="8ebd5038-5446-44be-bca3-cebaf3012424" CreationDate="2020-02-04T13:36:58.510" UserId="-1" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:-1,&quot;DisplayName&quot;:&quot;Community&quot;}]}" />
  <row Id="26247" PostHistoryTypeId="2" PostId="9546" RevisionGUID="ee13c41c-0bc7-436b-b4f4-2d1951cb9c22" CreationDate="2020-02-04T14:51:10.570" UserId="9309" Text="I am confronted with the problem to render 3D representations for objects marked on microscope slices.&#xD;&#xA;So I have a set of aligned polygons in parallel planes from tracing the outline of the object in the slices. I want to turn this into a 3d mesh of an approximate surface of the object.&#xD;&#xA;The curves can have vastly different point density per curve length and overall number of points.&#xD;&#xA;&#xD;&#xA;I know that there is not a unique solution, but I wonder if there is a fast algorithm to find A solution that looks reasonable.&#xD;&#xA;&#xD;&#xA;Unfortunately, this also has to be solved in MATLAB. Not expecting MATLAB code of course, I just want to say that use function X in Y, Y not being MATLAB, is not extremely helpful." ContentLicense="CC BY-SA 4.0" />
  <row Id="26248" PostHistoryTypeId="1" PostId="9546" RevisionGUID="ee13c41c-0bc7-436b-b4f4-2d1951cb9c22" CreationDate="2020-02-04T14:51:10.570" UserId="9309" Text="Turning layered curves to polygon mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26249" PostHistoryTypeId="3" PostId="9546" RevisionGUID="ee13c41c-0bc7-436b-b4f4-2d1951cb9c22" CreationDate="2020-02-04T14:51:10.570" UserId="9309" Text="|3d|mesh|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26250" PostHistoryTypeId="5" PostId="9544" RevisionGUID="918edf82-d7b0-415d-92d2-f7ef6d1e2888" CreationDate="2020-02-04T15:06:41.567" UserId="6" Comment="added 22 characters in body; edited tags" Text="Assume we have a mesh represented as a half edge datastructure.&#xD;&#xA;&#xD;&#xA;We want to subdivide faces without introducing unnecessary vertices (i.e the new number of vertices must be exactly V + E where V is the old number of vertices and E is the old number of edges).&#xD;&#xA;&#xD;&#xA;This is what a single subdivided triangle looks like:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I naively try to iterate over every edge and reconnect faces I get the following sequence&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Clearly this is wrong.&#xD;&#xA;&#xD;&#xA;If instead I iterate over the faces I get the following pattern:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This is happening because at every step I am trying to to:&#xD;&#xA;&#xD;&#xA; * Focus on only one simplex at a time, &#xD;&#xA; * Maintain the connectivity information of the mesh in a valid state (every edge has &lt;2 faces, vertices only exist at the end of edges, faces only have 3 Half edges...), like for example, I am avoiding getting into this state:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Any suggestions?&#xD;&#xA;  [1]: https://i.stack.imgur.com/MYmhk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Jgn94.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/D4SZe.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/04SMi.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/vWp6b.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4SexY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26251" PostHistoryTypeId="6" PostId="9544" RevisionGUID="918edf82-d7b0-415d-92d2-f7ef6d1e2888" CreationDate="2020-02-04T15:06:41.567" UserId="6" Comment="added 22 characters in body; edited tags" Text="|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26252" PostHistoryTypeId="2" PostId="9547" RevisionGUID="0cccba6c-2bb1-4846-926c-16453f8087b0" CreationDate="2020-02-04T18:15:21.247" UserId="11842" Text="Rendering is the process of computing a three-dimensional geometric description of a scene into a two-dimensional image representation that looks real. Ray-tracing and Radiosity are two of the most famous rendering techniques for photo realistic images.right?&#xD;&#xA;so which technique is suitable for rendering ten under-water images of marine creatures showing total internal reflection needed by ABC Marine Department. The department needs the images to be more natural and can wait for image generation for a month." ContentLicense="CC BY-SA 4.0" />
  <row Id="26253" PostHistoryTypeId="1" PostId="9547" RevisionGUID="0cccba6c-2bb1-4846-926c-16453f8087b0" CreationDate="2020-02-04T18:15:21.247" UserId="11842" Text="which technique should be used for rendering the under water images ,ray tracing or radiosity?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26254" PostHistoryTypeId="3" PostId="9547" RevisionGUID="0cccba6c-2bb1-4846-926c-16453f8087b0" CreationDate="2020-02-04T18:15:21.247" UserId="11842" Text="|raytracing|rendering|reflection|radiosity|render|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26255" PostHistoryTypeId="5" PostId="9533" RevisionGUID="2b611161-6cd4-4004-90e0-3353d8091e97" CreationDate="2020-02-04T18:26:00.383" UserId="11282" Comment="added 56 characters in body" Text="I've seen lots of spins on the ray-box intersection test, and a lot of them seem to boil down to this code: (omitting some details here)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  invRay.x = 1.0 / ray.x;&#xD;&#xA;&#xD;&#xA;  tx1 = (box.min.x - rayOrigin.x) * invRay.x;&#xD;&#xA;  tx2 = (box.max.x - rayOrigin.x) * invRay.x;&#xD;&#xA;&#xD;&#xA;  tmin = min(tx1, tx2);&#xD;&#xA;  tmax = max(tx1, tx2);&#xD;&#xA;&#xD;&#xA;  // Repeat for Y and Z&#xD;&#xA;  // Then check to ensure tmin &lt; tmax&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(I got mine specifically from [this discussion](https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms) and [this source](https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c#n196). Also note that if you use std::min and std::max, it's far from branchless)&#xD;&#xA;&#xD;&#xA;However, this raises a significant problem.&#xD;&#xA;&#xD;&#xA;What if the ray's origin in one or more dimensions is equal to the min or max points?&#xD;&#xA;&#xD;&#xA;What I found is that I get this situation on an example ray and box:&#xD;&#xA;&#xD;&#xA;* Ray origin: (3.225, 0.243, 2.221)&#xD;&#xA;* Ray direction: (0, 0, -1)&#xD;&#xA;* Box min: (3.223, 0.241, 2.119)&#xD;&#xA;* Box max: (3.225, 0.243, 2.121)&#xD;&#xA;&#xD;&#xA;Is that when tx1 is calculated, it correctly gets -inf. However, when tx2 is calculated, it gets ```(3.225 - 3.225) * inf``` which is coming out to ```-nan```. This means that later, when we do:&#xD;&#xA;&#xD;&#xA;```float tmax = std::max(tx1, tx2);```&#xD;&#xA;&#xD;&#xA;We get ```max(-inf, -nan)``` which comes out to ```-inf``` and from that point on in the tests, tmax will always be -inf, making the overall ray-box test fail.&#xD;&#xA;&#xD;&#xA;This is confirmed by some comments on the page where I got the code:&#xD;&#xA;&#xD;&#xA;&gt;Something to consider here is that 0 * inf =nan which occurs when the ray starts exactly on the edge of a box&#xD;&#xA;&#xD;&#xA;And&#xD;&#xA;&#xD;&#xA;&gt;Having read both this and part 2, I'm unable to work out what changes I need to make in order to reliably detect intersections when a ray is exactly on the edge of an AABB.&#xD;&#xA;&#xD;&#xA;Does anyone know a fast method for ray-box intersection with edge and corner hits?&#xD;&#xA;&#xD;&#xA;I should note **this is not being used with a BVH**." ContentLicense="CC BY-SA 4.0" />
  <row Id="26256" PostHistoryTypeId="5" PostId="9533" RevisionGUID="879c1e00-3f2b-44e5-b9ce-d4815c672ae9" CreationDate="2020-02-04T18:38:31.407" UserId="11282" Comment="added 85 characters in body" Text="I've seen lots of spins on the ray-box intersection test, and a lot of them seem to boil down to this code: (omitting some details here)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  invRay.x = 1.0 / ray.x;&#xD;&#xA;&#xD;&#xA;  tx1 = (box.min.x - rayOrigin.x) * invRay.x;&#xD;&#xA;  tx2 = (box.max.x - rayOrigin.x) * invRay.x;&#xD;&#xA;&#xD;&#xA;  tmin = min(tx1, tx2);&#xD;&#xA;  tmax = max(tx1, tx2);&#xD;&#xA;&#xD;&#xA;  // Repeat for Y and Z&#xD;&#xA;  // Then check to ensure tmin &lt; tmax&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(I got mine specifically from [this discussion](https://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms) and [this source](https://tavianator.com/cgit/dimension.git/tree/libdimension/bvh/bvh.c#n196). Also note that if you use std::min and std::max, it's far from branchless)&#xD;&#xA;&#xD;&#xA;However, this raises a significant problem.&#xD;&#xA;&#xD;&#xA;What if the ray's origin in one or more dimensions is equal to the min or max points?&#xD;&#xA;&#xD;&#xA;What I found is that I get this situation on an example ray and box:&#xD;&#xA;&#xD;&#xA;* Ray origin: (3.225, 0.243, 2.221)&#xD;&#xA;* Ray direction: (0, 0, -1)&#xD;&#xA;* Box min: (3.223, 0.241, 2.119)&#xD;&#xA;* Box max: (3.225, 0.243, 2.121)&#xD;&#xA;&#xD;&#xA;Is that when tx1 is calculated, it correctly gets -inf. However, when tx2 is calculated, it gets ```(3.225 - 3.225) * inf``` which is coming out to ```-nan```. This means that later, when we do:&#xD;&#xA;&#xD;&#xA;```float tmax = std::max(tx1, tx2);```&#xD;&#xA;&#xD;&#xA;We get ```max(-inf, -nan)``` which comes out to ```-inf``` and from that point on in the tests, tmax will always be -inf, making the overall ray-box test fail.&#xD;&#xA;&#xD;&#xA;This is confirmed by some comments on the page where I got the code:&#xD;&#xA;&#xD;&#xA;&gt;Something to consider here is that 0 * inf =nan which occurs when the ray starts exactly on the edge of a box&#xD;&#xA;&#xD;&#xA;And&#xD;&#xA;&#xD;&#xA;&gt;Having read both this and part 2, I'm unable to work out what changes I need to make in order to reliably detect intersections when a ray is exactly on the edge of an AABB.&#xD;&#xA;&#xD;&#xA;Does anyone know a fast method for ray-box intersection with edge and corner hits?&#xD;&#xA;&#xD;&#xA;I should note **this is not being used with a BVH**. I need an **exact** intersection test, I cannot increase the size of the box at all." ContentLicense="CC BY-SA 4.0" />
  <row Id="26258" PostHistoryTypeId="50" PostId="8993" RevisionGUID="d22f02aa-5d27-4d87-a04a-c6ab50aa5417" CreationDate="2020-02-06T06:01:35.180" UserId="-1" />
  <row Id="26259" PostHistoryTypeId="2" PostId="9548" RevisionGUID="bc7868c4-6ba1-40b3-b3ae-dac2f8d8f859" CreationDate="2020-02-06T06:21:38.517" UserDisplayName="user11739" Text="What about Division or subdivision? " ContentLicense="CC BY-SA 4.0" />
  <row Id="26260" PostHistoryTypeId="2" PostId="9549" RevisionGUID="c8a1201e-91f1-42bc-b256-f0ee52f8c5d4" CreationDate="2020-02-06T09:48:53.650" UserId="11850" Text="I am not sure if this is the correct SE to ask this question. However, lets say I have been given 3D models of several enclosed spaces.&#xD;&#xA;&#xD;&#xA;I want to populate spaces with, lets say, planes flying through them, taking the optimum route from A to B. Since there are many of them, I want to write an algorithm that does this; I already have the 3D models of the planes. &#xD;&#xA;&#xD;&#xA;I am looking for resources I can use to learn how to do this. " ContentLicense="CC BY-SA 4.0" />
  <row Id="26261" PostHistoryTypeId="1" PostId="9549" RevisionGUID="c8a1201e-91f1-42bc-b256-f0ee52f8c5d4" CreationDate="2020-02-06T09:48:53.650" UserId="11850" Text="Defining empty space in 3D model" ContentLicense="CC BY-SA 4.0" />
  <row Id="26262" PostHistoryTypeId="3" PostId="9549" RevisionGUID="c8a1201e-91f1-42bc-b256-f0ee52f8c5d4" CreationDate="2020-02-06T09:48:53.650" UserId="11850" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26263" PostHistoryTypeId="2" PostId="9550" RevisionGUID="b203baaf-9d93-409e-bf86-79e2de93919c" CreationDate="2020-02-06T09:56:00.587" UserId="11851" Text="Besides the suggestions in comments, I would suggest a high pass filtering to get rid of the low frequency noise, before running your local thresholding. Here an example with GIMP, that you can probably easily reproduce with opencv as well.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YPJ4s.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26264" PostHistoryTypeId="5" PostId="9549" RevisionGUID="02117108-177e-453f-acf6-9be1777a6dd5" CreationDate="2020-02-06T10:01:31.820" UserId="11850" Comment="added 75 characters in body" Text="I am not sure if this is the correct SE to ask this question. However, lets say I have been given 3D models of several enclosed spaces.&#xD;&#xA;&#xD;&#xA;I want to populate spaces with, lets say, planes flying through them, taking the optimum route from A to B. Since there are many of them, I want to write an algorithm that does this; I already have the 3D models of the planes. &#xD;&#xA;&#xD;&#xA;I am looking for resources I can use to learn how to do define the boundary conditions for the opimization algorithm given the 3D model. " ContentLicense="CC BY-SA 4.0" />
  <row Id="26265" PostHistoryTypeId="2" PostId="9551" RevisionGUID="d152392d-f537-4096-83b3-7185dd719800" CreationDate="2020-02-06T12:44:25.517" UserId="11853" Text="Is just read about image-dithering ? So I tried to implement that. Here is my result. Can someone verify it?&#xD;&#xA;&#xD;&#xA;[My code](https://github.com/maifeeulasad/dithering-cg/blob/master/python/render.py) :&#xD;&#xA;```&#xD;&#xA;import numpy as np&#xD;&#xA;from numpy.random import default_rng&#xD;&#xA;import matplotlib.pyplot as plt&#xD;&#xA;&#xD;&#xA;n = 300&#xD;&#xA;real = np.random.randint(low = 0, high=256, size=(n,n), dtype='l')&#xD;&#xA;#print(real)&#xD;&#xA;&#xD;&#xA;dn = 3&#xD;&#xA;rng = default_rng()&#xD;&#xA;dither = rng.choice(dn*dn, size=(dn,dn), replace=False)&#xD;&#xA;print(dither)&#xD;&#xA;&#xD;&#xA;res = np.zeros((n,n))&#xD;&#xA;for y in range (0,n):&#xD;&#xA;    for x in range (0,n):&#xD;&#xA;        i = x % dn&#xD;&#xA;        j = y % dn&#xD;&#xA;        res[x][y] = 255 if (real[x][y] &gt; dither[i][j]) else 0&#xD;&#xA;#print(res)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;fig = plt.figure()&#xD;&#xA;&#xD;&#xA;ax1 = plt.subplot(1, 3, 1)&#xD;&#xA;ax1.title.set_text('Real Image(300x300)')&#xD;&#xA;plt.imshow(real, cmap=&quot;gray&quot;)&#xD;&#xA;&#xD;&#xA;ax2 = plt.subplot(1, 3, 2)&#xD;&#xA;ax2.title.set_text('Dithering Matrix(3x3)')&#xD;&#xA;plt.imshow(dither, cmap=&quot;gray&quot;)&#xD;&#xA;&#xD;&#xA;ax3 = plt.subplot(1, 3, 3)&#xD;&#xA;ax3.title.set_text('Resultant Image(300x300)')&#xD;&#xA;plt.imshow(res, cmap=&quot;gray&quot;)&#xD;&#xA;&#xD;&#xA;plt.show()&#xD;&#xA;```&#xD;&#xA;reduced value of  n to 6, so that image may become easily understandable.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Result :&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kOxfb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26266" PostHistoryTypeId="1" PostId="9551" RevisionGUID="d152392d-f537-4096-83b3-7185dd719800" CreationDate="2020-02-06T12:44:25.517" UserId="11853" Text="basic of image dithering" ContentLicense="CC BY-SA 4.0" />
  <row Id="26267" PostHistoryTypeId="3" PostId="9551" RevisionGUID="d152392d-f537-4096-83b3-7185dd719800" CreationDate="2020-02-06T12:44:25.517" UserId="11853" Text="|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26271" PostHistoryTypeId="4" PostId="9549" RevisionGUID="eac34432-b3b6-492f-b0cd-080e0a6d8c19" CreationDate="2020-02-06T16:23:41.580" UserId="11850" Comment="edited title" Text="Defining &quot;inside&quot; and &quot;outside&quot; of a 3D space" ContentLicense="CC BY-SA 4.0" />
  <row Id="26272" PostHistoryTypeId="2" PostId="9553" RevisionGUID="79e4691a-04f5-4ed8-ac74-3a75e1c25aa5" CreationDate="2020-02-06T17:47:36.223" UserId="11598" Text="I'm trying to implement the derivation of the masking function G_1 by Smith.&#xD;&#xA;The appendix of Walter et al [1](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf), Hammons presentation [2](https://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf) and this research paper [3](https://docs.chaosgroup.com/display/RESEARCH/Deriving+the+Smith+shadowing+function+for+the+GTR+BRDF) talk in detail about it and I feel as I do understand the majority of the math behind it. But when it comes to turning this into code I cannot seem to get it right.&#xD;&#xA;&#xD;&#xA;Some of my questions entail:&#xD;&#xA;&#xD;&#xA;In the first integral from minus infinity to infinity over *P22(p, q)*, the way I understand it I can simply iterate over all of my microfacets and use the previous formular (*P22(p, q) = D(**m**) cos^4(theta_m)*) and add them together for a riemann sum?&#xD;&#xA;&#xD;&#xA;As far as I understand is mu (*= |cot(theta_v)|*) the slope of the view vector and when using an integral from mu to infinity the goal is to decrease te angle of theta_v until it is zero?&#xD;&#xA;&#xD;&#xA;The way I naivly implemented it is as an nested loop of two riemann sums that aim to describe the two integrals. In pseudocode:&#xD;&#xA;&#xD;&#xA;    calculate mu from view angle&#xD;&#xA;    Aux = 0.0;&#xD;&#xA;    //for loop uses calculation of the angle theta_v to decide termination of loop&#xD;&#xA;    for(float q = mu; angleof(q) &gt; 0.0001f; q += dq)&#xD;&#xA;    {&#xD;&#xA;       float P2 = 0.0;&#xD;&#xA;       for(iterate through all maicrofacets)&#xD;&#xA;       {&#xD;&#xA;          calulate theta of current microfacet&#xD;&#xA;          calculate cos^4(theta)&#xD;&#xA;          get D of current microfacet&#xD;&#xA;          &#xD;&#xA;          P2 += D * cos^4(theta) * dp;&#xD;&#xA;       }&#xD;&#xA;       Aux += (q - mu) * P2 * dq;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Aux *= 1.0 / mu;&#xD;&#xA;    return 1.0 / (1.0 + Aux)&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I write in C++ but I would be very happy with any kind of code or hint as to how to solve this.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26273" PostHistoryTypeId="1" PostId="9553" RevisionGUID="79e4691a-04f5-4ed8-ac74-3a75e1c25aa5" CreationDate="2020-02-06T17:47:36.223" UserId="11598" Text="Implementing the derivation of the Smith Shadowing function for arbitrary distributions" ContentLicense="CC BY-SA 4.0" />
  <row Id="26274" PostHistoryTypeId="3" PostId="9553" RevisionGUID="79e4691a-04f5-4ed8-ac74-3a75e1c25aa5" CreationDate="2020-02-06T17:47:36.223" UserId="11598" Text="|opengl|c++|microfacet|masking|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26275" PostHistoryTypeId="2" PostId="9554" RevisionGUID="2d4db60b-d16a-4e14-8fe6-d6890be06451" CreationDate="2020-02-07T03:24:54.147" UserId="11858" Text="I am trying to perform quad-based tessellation using GLSL on Unity to be able to render polynomial-based parametric surfaces on a Unity quad. The quad-based tessellation using GLSL seems to be incorrectly choosing the vertices for the patch to be tessellated. I am using this shader (https://github.com/przemyslawzaworski/Unity3D-CG-programming/blob/master/GLSL/tessellation.shader) as a reference. However, modifying it to use quads in the domain shader stage messes up the ordering. &#xD;&#xA;&#xD;&#xA;    Shader &quot;Custom/Tessellation&quot;&#xD;&#xA;{&#xD;&#xA;	Properties&#xD;&#xA;	{&#xD;&#xA;		_MainTex (&quot;Texture&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;		_factor(&quot;Tessellation scale&quot;,Range(1.0,64.0)) = 1.0&#xD;&#xA;	}&#xD;&#xA;	SubShader&#xD;&#xA;	{&#xD;&#xA;		Cull Off&#xD;&#xA;		Pass&#xD;&#xA;		{&#xD;&#xA;			GLSLPROGRAM&#xD;&#xA;			#version 460     &#xD;&#xA;			uniform float _factor;&#xD;&#xA;			&#xD;&#xA;			#ifdef VERTEX&#xD;&#xA;				in  vec4 in_POSITION0;&#xD;&#xA;				void main()&#xD;&#xA;				{&#xD;&#xA;					gl_Position =  gl_ModelViewProjectionMatrix * in_POSITION0;&#xD;&#xA;				}&#xD;&#xA;			#endif&#xD;&#xA;&#xD;&#xA;			#ifdef HULL          //GLSL Tessellation Control Shader&#xD;&#xA;&#xD;&#xA;				layout (vertices = 4) out;&#xD;&#xA;				void main()&#xD;&#xA;				{&#xD;&#xA;					if (gl_InvocationID == 0)&#xD;&#xA;					{&#xD;&#xA;						gl_TessLevelInner[0] = _factor;   //Inside tessellation factor&#xD;&#xA;						gl_TessLevelInner[1] = _factor;   //Inside tessellation factor&#xD;&#xA;&#xD;&#xA;						gl_TessLevelOuter[0] = _factor;   //Edge tessellation factor&#xD;&#xA;						gl_TessLevelOuter[1] = _factor;   //Edge tessellation factor&#xD;&#xA;						gl_TessLevelOuter[2] = _factor;   //Edge tessellation factor&#xD;&#xA;						gl_TessLevelOuter[3] = _factor;   //Edge tessellation factor&#xD;&#xA;					} &#xD;&#xA;					gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;				}&#xD;&#xA;			#endif&#xD;&#xA;&#xD;&#xA;			#ifdef DOMAIN        //GLSL Tessellation Evaluation Shader&#xD;&#xA;				layout (quads) in;&#xD;&#xA;				void main()&#xD;&#xA;				{ 	&#xD;&#xA;					vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);&#xD;&#xA;				    vec4 p2 = mix(gl_in[2].gl_Position, gl_in[3].gl_Position, gl_TessCoord.x);&#xD;&#xA;				    gl_Position = mix(p1, p2, gl_TessCoord.y);		&#xD;&#xA;				}&#xD;&#xA;			#endif&#xD;&#xA;&#xD;&#xA;			#ifdef GEOMETRY      //geometry shader for rendering wireframe&#xD;&#xA;				layout(triangles) in;&#xD;&#xA;				layout(line_strip, max_vertices = 3) out;&#xD;&#xA;				void main()&#xD;&#xA;				{&#xD;&#xA;					for(int i = 0; i &lt; gl_in.length(); ++i)&#xD;&#xA;					{&#xD;&#xA;						gl_Position = gl_in[i].gl_Position;&#xD;&#xA;						EmitVertex();&#xD;&#xA;					}&#xD;&#xA;					gl_Position = gl_in[0].gl_Position;&#xD;&#xA;					EmitVertex();  &#xD;&#xA;					EndPrimitive();&#xD;&#xA;				}    &#xD;&#xA;			#endif&#xD;&#xA;                   &#xD;&#xA;			#ifdef FRAGMENT&#xD;&#xA;				out vec4 color;&#xD;&#xA;				void main()&#xD;&#xA;				{&#xD;&#xA;					color = vec4(1,1,1,1);&#xD;&#xA;				}&#xD;&#xA;			#endif&#xD;&#xA;           &#xD;&#xA;			ENDGLSL&#xD;&#xA;			}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Please help me in identifying what modifications are incorrect. I would appreciate any and all the help. The following are the outputs both from the triangle-based shader as given in the link to the Github page above, and the quad-based shader with modifications for quads made by me. &#xD;&#xA;&#xD;&#xA;[![Triangle-based Tessellation Working Properly][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Quad-based Tessellation Generating Incorrect Results][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m8Cnk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KUUKV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26276" PostHistoryTypeId="1" PostId="9554" RevisionGUID="2d4db60b-d16a-4e14-8fe6-d6890be06451" CreationDate="2020-02-07T03:24:54.147" UserId="11858" Text="Problem with Quad-based Tessellation in GLSL generating incorrect vertex ordered tessellation" ContentLicense="CC BY-SA 4.0" />
  <row Id="26277" PostHistoryTypeId="3" PostId="9554" RevisionGUID="2d4db60b-d16a-4e14-8fe6-d6890be06451" CreationDate="2020-02-07T03:24:54.147" UserId="11858" Text="|shader|glsl|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26278" PostHistoryTypeId="5" PostId="9554" RevisionGUID="ed40ff3d-878c-4ad0-94f0-7e159709b766" CreationDate="2020-02-07T09:58:18.840" UserId="6" Comment="added 287 characters in body" Text="I am trying to perform quad-based tessellation using GLSL on Unity to be able to render polynomial-based parametric surfaces on a Unity quad. The quad-based tessellation using GLSL seems to be incorrectly choosing the vertices for the patch to be tessellated. I am using this shader (https://github.com/przemyslawzaworski/Unity3D-CG-programming/blob/master/GLSL/tessellation.shader) as a reference. However, modifying it to use quads in the domain shader stage messes up the ordering. &#xD;&#xA;&#xD;&#xA;    Shader &quot;Custom/Tessellation&quot;&#xD;&#xA;    {&#xD;&#xA;	    Properties&#xD;&#xA;	    {&#xD;&#xA;		    _MainTex (&quot;Texture&quot;, 2D) = &quot;white&quot; {}&#xD;&#xA;		    _factor(&quot;Tessellation scale&quot;,Range(1.0,64.0)) = 1.0&#xD;&#xA;	    }&#xD;&#xA;	    SubShader&#xD;&#xA;	    {&#xD;&#xA;		    Cull Off&#xD;&#xA;		    Pass&#xD;&#xA;		    {&#xD;&#xA;			    GLSLPROGRAM&#xD;&#xA;			    #version 460     &#xD;&#xA;			    uniform float _factor;&#xD;&#xA;			&#xD;&#xA;			    #ifdef VERTEX&#xD;&#xA;				    in  vec4 in_POSITION0;&#xD;&#xA;				    void main()&#xD;&#xA;				    {&#xD;&#xA;				        gl_Position =  gl_ModelViewProjectionMatrix * in_POSITION0;&#xD;&#xA;				    }&#xD;&#xA;			    #endif&#xD;&#xA;&#xD;&#xA;			    #ifdef HULL          //GLSL Tessellation Control Shader&#xD;&#xA;&#xD;&#xA;				    layout (vertices = 4) out;&#xD;&#xA;				    void main()&#xD;&#xA;				    {&#xD;&#xA;					    if (gl_InvocationID == 0)&#xD;&#xA;					    {&#xD;&#xA;						    gl_TessLevelInner[0] = _factor;   //Inside tessellation factor&#xD;&#xA;						    gl_TessLevelInner[1] = _factor;   //Inside tessellation factor&#xD;&#xA;&#xD;&#xA;						    gl_TessLevelOuter[0] = _factor;   //Edge tessellation factor&#xD;&#xA;						    gl_TessLevelOuter[1] = _factor;   //Edge tessellation factor&#xD;&#xA;						    gl_TessLevelOuter[2] = _factor;   //Edge tessellation factor&#xD;&#xA;						    gl_TessLevelOuter[3] = _factor;   //Edge tessellation factor&#xD;&#xA;					    } &#xD;&#xA;					    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;				    }&#xD;&#xA;			    #endif&#xD;&#xA;&#xD;&#xA;			    #ifdef DOMAIN        //GLSL Tessellation Evaluation Shader&#xD;&#xA;				    layout (quads) in;&#xD;&#xA;				    void main()&#xD;&#xA;				    { 	&#xD;&#xA;					    vec4 p1 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);&#xD;&#xA;				        vec4 p2 = mix(gl_in[2].gl_Position, gl_in[3].gl_Position, gl_TessCoord.x);&#xD;&#xA;				        gl_Position = mix(p1, p2, gl_TessCoord.y);		&#xD;&#xA;				    }&#xD;&#xA;			    #endif&#xD;&#xA;&#xD;&#xA;			    #ifdef GEOMETRY      //geometry shader for rendering wireframe&#xD;&#xA;				    layout(triangles) in;&#xD;&#xA;				    layout(line_strip, max_vertices = 3) out;&#xD;&#xA;				    void main()&#xD;&#xA;				    {&#xD;&#xA;					    for(int i = 0; i &lt; gl_in.length(); ++i)&#xD;&#xA;					    {&#xD;&#xA;					    	gl_Position = gl_in[i].gl_Position;&#xD;&#xA;					    	EmitVertex();&#xD;&#xA;					    }&#xD;&#xA;					    gl_Position = gl_in[0].gl_Position;&#xD;&#xA;					    EmitVertex();  &#xD;&#xA;					    EndPrimitive();&#xD;&#xA;				    }    &#xD;&#xA;			    #endif&#xD;&#xA;                   &#xD;&#xA;			    #ifdef FRAGMENT&#xD;&#xA;				    out vec4 color;&#xD;&#xA;				    void main()&#xD;&#xA;				    {&#xD;&#xA;					    color = vec4(1,1,1,1);&#xD;&#xA;				    }&#xD;&#xA;			    #endif&#xD;&#xA;           &#xD;&#xA;			    ENDGLSL&#xD;&#xA;			}&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Please help me in identifying what modifications are incorrect. I would appreciate any and all the help. The following are the outputs both from the triangle-based shader as given in the link to the Github page above, and the quad-based shader with modifications for quads made by me. &#xD;&#xA;&#xD;&#xA;[![Triangle-based Tessellation Working Properly][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Quad-based Tessellation Generating Incorrect Results][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m8Cnk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KUUKV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26283" PostHistoryTypeId="2" PostId="9556" RevisionGUID="8e62bb60-112b-43e7-bee8-13274ac3ea15" CreationDate="2020-02-07T18:37:22.823" UserId="1865" Text="In the godot game engine (using opengl) it is not possible to define custom shader attributes.  &#xD;&#xA;A workaround is creating a sampler2D texture uniform instead and use vertexId (or in fact UV since vertexID also isn't exposed) to get the per vertex attributes.  &#xD;&#xA;  &#xD;&#xA;I am wondering are there any downsides to this approach and/or caveats one should keep in mind ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26284" PostHistoryTypeId="1" PostId="9556" RevisionGUID="8e62bb60-112b-43e7-bee8-13274ac3ea15" CreationDate="2020-02-07T18:37:22.823" UserId="1865" Text="Shader sampler2D uniforms instead of attributes" ContentLicense="CC BY-SA 4.0" />
  <row Id="26285" PostHistoryTypeId="3" PostId="9556" RevisionGUID="8e62bb60-112b-43e7-bee8-13274ac3ea15" CreationDate="2020-02-07T18:37:22.823" UserId="1865" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26287" PostHistoryTypeId="2" PostId="9557" RevisionGUID="3bbe0d1c-2798-4e1c-a1bc-9c3c56895b18" CreationDate="2020-02-08T17:26:16.743" UserId="11702" Text="Radiosity is only efficient for diffuse to diffuse rendering. Path tracing is more versatile on the type of light transport that could be computed. The main issue with underwater rendering is the caustics generated from specular from the water-air interface. These caustics are very important to generate a realistic underwater image (except for deepwater rendering here the sunlight is completely attenuated).&#xD;&#xA;&#xD;&#xA;The problem of rendering caustics from path tracing is the lack of non-efficient sampling strategies to generate a valid path. Density estimation [1] (a.k.a. photon mapping) could be a good candidate for rendering these difficult caustics, but a large scene will require light subpaths guiding to get a reasonable rendering time. Metropolis light transport (MLT) [2,3] provide this guiding automatically and could be used in a density estimation framework [4].&#xD;&#xA;&#xD;&#xA;Recently, path guiding techniques [5,6] was proposed to render these difficult paths efficiently with unidirectional path tracing. The simplest approach to use/implement is the technique proposed by Muller et al. [5]. A Mitsuba code plugin is available on GitHub: https://github.com/Tom94/practical-path-guiding &#xD;&#xA;&#xD;&#xA;Note that, inside water, there might are volume scattering events [7] to take into account, depending on the amount of particle floating. &#xD;&#xA;&#xD;&#xA;[1] &quot;Stochastic progressive photon mapping&quot; Hachisuka et al., 2009&#xD;&#xA;&#xD;&#xA;[2] &quot;Metropolis light transport&quot; Veach et al. 1997 &#xD;&#xA;&#xD;&#xA;[3] &quot;Primary sample space MLT&quot; Kelemen et al. 2002&#xD;&#xA;&#xD;&#xA;[4] &quot;Robust Adaptive Photon Tracing using Photon Path Visibility&quot;, Hachisuka et al., 2011&#xD;&#xA;&#xD;&#xA;[5] &quot;Practical path guiding for efficient light-transport simulation&quot;, Muller et al. 2017&#xD;&#xA;&#xD;&#xA;[6] &quot;On-line Learning of Parametric Mixture Models for Light Transport Simulation&quot;, Vorba et al. 2014&#xD;&#xA;&#xD;&#xA;[7] &quot;Monte Carlo Methods for Physically Based Volume Rendering&quot;, Novak et al., 2018" ContentLicense="CC BY-SA 4.0" />
  <row Id="26289" PostHistoryTypeId="2" PostId="9558" RevisionGUID="30854526-0311-49de-b3b0-445d0c2e5701" CreationDate="2020-02-08T19:26:04.620" UserId="7462" Text="Be it chaikin subdivision, loop subdivision, catmull-clark subdivision...&#xD;&#xA;&#xD;&#xA;Hoiw do people come up with the coefficients for an arbitrary subdivision scheme?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26290" PostHistoryTypeId="1" PostId="9558" RevisionGUID="30854526-0311-49de-b3b0-445d0c2e5701" CreationDate="2020-02-08T19:26:04.620" UserId="7462" Text="How do people come up with subdivision schemes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26291" PostHistoryTypeId="3" PostId="9558" RevisionGUID="30854526-0311-49de-b3b0-445d0c2e5701" CreationDate="2020-02-08T19:26:04.620" UserId="7462" Text="|algorithm|mathematics|curve|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26292" PostHistoryTypeId="2" PostId="9559" RevisionGUID="6693be1e-343a-4d68-8ae5-b51b2f34b0a8" CreationDate="2020-02-08T20:20:03.823" UserId="11702" Text="There is a small issue in the original code. Indeed, real array values ranging between [0, 255]. However, the mask values ranging between [0, 3*3] (as dn = 3 in the example above).&#xD;&#xA;&#xD;&#xA;After fixing the issue:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The correct code (with image reading and all data normalized between [0, 1.0]):&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;import numpy as np&#xD;&#xA;from numpy.random import default_rng&#xD;&#xA;import matplotlib.pyplot as plt&#xD;&#xA;from PIL import Image&#xD;&#xA;&#xD;&#xA;# Read an image from the disk&#xD;&#xA;real = Image.open(&quot;example.jpeg&quot;)&#xD;&#xA;real = np.array(real) / 255.0&#xD;&#xA;# If it is a RGB image, transform it to a gray image&#xD;&#xA;# TODO: Could use any function (like luminance)&#xD;&#xA;real = (real[:,:,0] + real[:,:,1] + real[:,:,2]) / 3.0&#xD;&#xA;&#xD;&#xA;# Create the mask by shuffling&#xD;&#xA;dn = 6&#xD;&#xA;rng = default_rng()&#xD;&#xA;# In the original code, there was a problem here.&#xD;&#xA;# Indeed, the mask values ranging between [0, dn*dn]&#xD;&#xA;# So the generated mask needs to be properly normalized&#xD;&#xA;dither = rng.choice(dn*dn, size=(dn,dn), replace=False) / float(dn*dn)&#xD;&#xA;print(dither)&#xD;&#xA;&#xD;&#xA;# Generate the results&#xD;&#xA;res = np.zeros_like(real)&#xD;&#xA;width, height = res.shape[1], res.shape[0]&#xD;&#xA;for y in range (0,width):&#xD;&#xA;    for x in range (0,height):&#xD;&#xA;        i = x % dn&#xD;&#xA;        j = y % dn&#xD;&#xA;        res[x][y] = 1.0 if (real[x][y] &gt; dither[i][j]) else 0.0&#xD;&#xA;&#xD;&#xA;# Display the result&#xD;&#xA;fig = plt.figure()&#xD;&#xA;ax1 = plt.subplot(1, 3, 1)&#xD;&#xA;ax1.title.set_text('Real Image(300x300)')&#xD;&#xA;plt.imshow(real, cmap=&quot;gray&quot;)&#xD;&#xA;ax2 = plt.subplot(1, 3, 2)&#xD;&#xA;ax2.title.set_text('Dithering Matrix(3x3)')&#xD;&#xA;plt.imshow(dither, cmap=&quot;gray&quot;)&#xD;&#xA;ax3 = plt.subplot(1, 3, 3)&#xD;&#xA;ax3.title.set_text('Resultant Image(300x300)')&#xD;&#xA;plt.imshow(res, cmap=&quot;gray&quot;)&#xD;&#xA;plt.show()&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/KUBRK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26296" PostHistoryTypeId="5" PostId="9524" RevisionGUID="2c0ccfc0-d94d-4115-a8ce-0d9fedb667e2" CreationDate="2020-02-09T08:44:11.343" UserId="9971" Comment="OLE_HANDLE to OLE_COLOR*" Text="I have found the following from this link&#xD;&#xA;[enter link description here][1]&#xD;&#xA;&#xD;&#xA;&gt; pData&#xD;&#xA;&gt; &#xD;&#xA;&gt; Type: void*&#xD;&#xA;&gt; &#xD;&#xA;&gt; Pointer to the data. When ID3D11DeviceContext::Map provides the&#xD;&#xA;&gt; pointer, the runtime ensures that the pointer has a specific&#xD;&#xA;&gt; alignment, depending on the following feature levels:&#xD;&#xA;&gt; &#xD;&#xA;&gt; For D3D_FEATURE_LEVEL_10_0 and higher, the pointer is aligned to 16&#xD;&#xA;&gt; bytes. For lower than D3D_FEATURE_LEVEL_10_0, the pointer is aligned&#xD;&#xA;&gt; to 4 bytes.&#xD;&#xA;&#xD;&#xA;Would someone please explain if I can reinterpret cast the void pointer into OLE_COLOR* or not?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_mapped_subresource" ContentLicense="CC BY-SA 4.0" />
  <row Id="26297" PostHistoryTypeId="4" PostId="9524" RevisionGUID="2c0ccfc0-d94d-4115-a8ce-0d9fedb667e2" CreationDate="2020-02-09T08:44:11.343" UserId="9971" Comment="OLE_HANDLE to OLE_COLOR*" Text="void* D3D11_MAPPED_SUBRESOURCE::pData to OLE_COLOR* possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26298" PostHistoryTypeId="50" PostId="9146" RevisionGUID="ffa00dac-10ef-40b6-b73d-e7f81c31d220" CreationDate="2020-02-09T15:03:10.443" UserId="-1" />
  <row Id="26303" PostHistoryTypeId="5" PostId="9448" RevisionGUID="a25dfc6b-5dcf-4de5-ab67-adecf1ee5b19" CreationDate="2020-02-09T21:48:10.373" UserDisplayName="user11352" Comment="added 54 characters in body" Text="In 3d modeling, there is some &quot;triangle count&quot; which determines complexity. I am not sure but I think cubes have 12 triangles or somethong. But I see NONE. They have squares, no triangles! Can someone please help me understand what a triangle is? Where in the cube are these 12 &quot;triangles&quot; located?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26305" PostHistoryTypeId="2" PostId="9562" RevisionGUID="ef1d015a-3b8b-4bff-bd15-398170f3260a" CreationDate="2020-02-10T06:07:27.530" UserId="11871" Text="I'm reading a graphics book and it talks about BRDFs being the ratio between differential outgoing radiance and differential irradiance. The formula it gives is &#xD;&#xA;f(l, v) = dL(v)/dE(l)&#xD;&#xA;Where l is the light vector and v is the outgoing direction vector, and L is outgoing radiance and E is incoming irradiance. &#xD;&#xA;&#xD;&#xA;But then the book says that for non area lights like directional and point lights, the BRDF can be expressed without differentials:&#xD;&#xA;f(l, v) = L(v) / E(l). &#xD;&#xA;How is this possible? The first formula seems to be a derivative, how do we get to this formula? What is the difference between non area and area lights that would allow us to arrive at this simplification? " ContentLicense="CC BY-SA 4.0" />
  <row Id="26306" PostHistoryTypeId="1" PostId="9562" RevisionGUID="ef1d015a-3b8b-4bff-bd15-398170f3260a" CreationDate="2020-02-10T06:07:27.530" UserId="11871" Text="Formula for non area light BRDFs" ContentLicense="CC BY-SA 4.0" />
  <row Id="26307" PostHistoryTypeId="3" PostId="9562" RevisionGUID="ef1d015a-3b8b-4bff-bd15-398170f3260a" CreationDate="2020-02-10T06:07:27.530" UserId="11871" Text="|lighting|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26308" PostHistoryTypeId="2" PostId="9563" RevisionGUID="4d1e065e-2577-4b0c-a749-b6bbb5de3adb" CreationDate="2020-02-10T13:54:04.123" UserId="7724" Text="The subdivision schemes are not arbitrary. Catmull-Clark, arguably the most used subdivision scheme, generalizes bicubic B-splines to meshes of arbitrary topology. &#xD;&#xA;&#xD;&#xA;Most, other subdivision schemes also generalize other degree B-splines to arbitrary topology. Doo-Sabin for biquadratic B-splines and Loop subdivision generalizes quartic box-splines defined over regular triangulations.  &#xD;&#xA;&#xD;&#xA;Most of the coefficients for subdivision are obtained by looking at [knot-insertion][1]. Knot-insertion is the process of adding knots into B-splines such that the same curve is obtained by expressing it as more curve pieces, i.e. subdividing the original curves. The rules for subdivision and thus the coefficients are derived from these algorithms. However, these rules only hold for the regular regions of the control mesh. For the irregular regions the rules are generalized, such that they give a satisfactory result.&#xD;&#xA;&#xD;&#xA;Another way to look at it is through subdivision stencils. The simplest subdivision stencil $[1,1]$ applied to the control polygon with points $P_i, \ldots, P_N$ will generate new points $Q_i = P_i$, will simply insert points at the same positions as the original points. &#xD;&#xA;We can convolve the stencil with itself $[1,1] * [1,1] = [1,2,1]$. We can decompose this stencil into an even [1,1] and an odd stencil [2] and again apply it to the control polygon. The odd stencil $Q_{i*2} = 2 P_i / 2$ will keep the original points, but the even stencil will generate points $Q_{i*2+1} = (1 P_i + 1 P_{i+1})/2$ half-way between points. &#xD;&#xA;&#xD;&#xA;Continuing the convolution process to the second stencil $[1,2,1] * [1,1] = [1, 3, 3, 1]$ will generate odd $[1, 3]$ and $[3,1]$ stencils which will generate points one quarter and three quarters along the line piece between points $P_i$ and $P_{i+1}$. This is of course the exact coefficients used in Chaikin's corner cutting algorithm, which in the limit of subdivision will generate quadratic B-splines. Applying it again $[1,3, 3,1] * [1,1] = [1, 4, 6, 4, 1]$ will generate the stencils that generate cubic B-splines. &#xD;&#xA;&#xD;&#xA;To generalize this again to surfaces we can apply this convolution process in two parametric directions to obtain bi-degree B-splines. In the cubic case we obtain this matrix of coefficients through convolution:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}1 &amp; 4 &amp; 6 &amp; 4 &amp; 1\\&#xD;&#xA;                4 &amp; 16 &amp; 24 &amp; 16 &amp; 4\\&#xD;&#xA;                6 &amp; 24 &amp; 36 &amp; 24 &amp; 6\\&#xD;&#xA;                4 &amp; 16 &amp; 24 &amp; 16 &amp; 4\\&#xD;&#xA;                1 &amp; 4 &amp; 6 &amp; 4 &amp; 1\\ \end{bmatrix}$&#xD;&#xA;&#xD;&#xA;We can decompose this matrix into vertex stencils:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}1 &amp;  6 &amp; 1\\&#xD;&#xA;                6 &amp; 36 &amp; 6\\&#xD;&#xA;                1 &amp;  6 &amp; 1\\ \end{bmatrix}$&#xD;&#xA;&#xD;&#xA;edge point stencils:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}4 &amp;  24 &amp; 4\\ 4 &amp; 24 &amp; 4\\ \end{bmatrix}$ and $\begin{bmatrix}4 &amp; 4\\ 24 &amp; 24\\ 4 &amp; 4\\ \end{bmatrix}$ &#xD;&#xA;&#xD;&#xA;face stencils:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;16 &amp; 16 \\&#xD;&#xA;16 &amp; 16 \\&#xD;&#xA;\end{bmatrix}$&#xD;&#xA; &#xD;&#xA;Applying these as control point masks to a regular control grid will obtain bicubic B-splines.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/single-insertion.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="26309" PostHistoryTypeId="5" PostId="9563" RevisionGUID="5a017401-32e2-4bdd-ad66-c616a3e812ee" CreationDate="2020-02-10T14:15:13.270" UserId="7724" Comment="added 886 characters in body" Text="The subdivision schemes are not arbitrary. Catmull-Clark, arguably the most used subdivision scheme, generalizes bicubic B-splines to meshes of arbitrary topology. &#xD;&#xA;&#xD;&#xA;Most, other subdivision schemes also generalize other degree B-splines to arbitrary topology. Doo-Sabin for biquadratic B-splines and Loop subdivision generalizes quartic box-splines defined over regular triangulations.  &#xD;&#xA;&#xD;&#xA;Most of the coefficients for subdivision are obtained by looking at [knot-insertion][1]. Knot-insertion is the process of adding knots into B-splines such that the same curve is obtained by expressing it as more curve pieces, i.e. subdividing the original curves. The rules for subdivision and thus the coefficients are derived from these algorithms. However, these rules only hold for the regular regions of the control mesh. For the irregular regions the rules are generalized, such that they give a satisfactory result.&#xD;&#xA;&#xD;&#xA;Another way to look at it is through subdivision stencils and masks. The simplest subdivision stencil $[1,1]$ applied to the control polygon with points $P_i, \ldots, P_N$ will generate new points $Q_i = P_i$, will simply insert points at the same positions as the original points. &#xD;&#xA;We can convolve the stencil with itself $[1,1] * [1,1] = [1,2,1]$. We can decompose this stencil into an even [1,1] and an odd mask [2] and again apply it to the control polygon by multiplying the coefficients in the mask and dividing by the sum of coefficients. The odd mask $Q_{i*2} = 2 P_i / 2$ will keep the original points, but the even mask will generate points $Q_{i*2+1} = (1 P_i + 1 P_{i+1})/2$ half-way between points. &#xD;&#xA;&#xD;&#xA;Continuing the convolution process to the second stencil $[1,2,1] * [1,1] = [1, 3, 3, 1]$ will generate odd $[1, 3]$ and even $[3,1]$ masks which will generate points one quarter and three quarters along the line piece between points $P_i$ and $P_{i+1}$. This are of course the exact coefficients used in Chaikin's corner cutting algorithm, which in the limit of subdivision will generate quadratic B-splines. Applying it again $[1,3, 3,1] * [1,1] = [1, 4, 6, 4, 1]$ will generate the stencils that generate cubic B-splines. &#xD;&#xA;&#xD;&#xA;To generalize this again to surfaces we can apply this convolution process in two parametric directions to obtain bi-degree B-splines. In the cubic case we obtain this matrix of coefficients through convolution:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}1 &amp; 4 &amp; 6 &amp; 4 &amp; 1\\&#xD;&#xA;                4 &amp; 16 &amp; 24 &amp; 16 &amp; 4\\&#xD;&#xA;                6 &amp; 24 &amp; 36 &amp; 24 &amp; 6\\&#xD;&#xA;                4 &amp; 16 &amp; 24 &amp; 16 &amp; 4\\&#xD;&#xA;                1 &amp; 4 &amp; 6 &amp; 4 &amp; 1\\ \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;We can decompose this matrix into vertex mask:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}1 &amp;  6 &amp; 1\\&#xD;&#xA;                6 &amp; 36 &amp; 6\\&#xD;&#xA;                1 &amp;  6 &amp; 1\\ \end{bmatrix}$&#xD;&#xA;&#xD;&#xA;edge point mask:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}4 &amp;  24 &amp; 4\\ 4 &amp; 24 &amp; 4\\ \end{bmatrix}$ and $\begin{bmatrix}4 &amp; 4\\ 24 &amp; 24\\ 4 &amp; 4\\ \end{bmatrix}$ &#xD;&#xA;&#xD;&#xA;face point mask:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;16 &amp; 16 \\&#xD;&#xA;16 &amp; 16 \\&#xD;&#xA;\end{bmatrix}$&#xD;&#xA; &#xD;&#xA;Applying these as control point masks to a regular control grid will obtain bicubic B-splines. The observation made for the Catmull-Clark algorithm is that the inserted points through the face stencils are the average of the surrounding vertices. This can easily be generalized for arbitrary polygons, the same thing goes for the edge stencil. The hard case is the vertex stencil as the original is only valid for vertices with valency 4. Catmull-Clark came up with this expression&#xD;&#xA;&#xD;&#xA;$$\frac{Q}{N} + \frac{2R}{N} + \frac{S(N-3)}{N}$$&#xD;&#xA;&#xD;&#xA;Where $S$ is the old vertex position $R$ is the average of the points created by the edge mask for the outgoing edges of the vertex and $Q$ the average of the points created by face mask for the surrounding faces. The ratios in this expression are such that it reproduces the regular vertex mask in the case $N=4$ and is aesthetically pleasing for other $N$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/single-insertion.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="26310" PostHistoryTypeId="50" PostId="9459" RevisionGUID="9f395ff9-1be7-486c-b507-810ac6e9d03f" CreationDate="2020-02-11T02:00:42.133" UserId="-1" />
  <row Id="26311" PostHistoryTypeId="5" PostId="9480" RevisionGUID="8b84cf60-7689-405c-903c-153b4a0b38d0" CreationDate="2020-02-11T09:19:23.940" UserId="209" Comment="fixed grammar" Text="To expand on @Makogan and @lightxbulb's answers/comments: &#xD;&#xA;&#xD;&#xA;There are several reasons for using triangles as the basic primitive.&#xD;&#xA;&#xD;&#xA; 1. (Non-degenerate) triangles are guaranteed to be *planar*. This means that an individual single triangle cannot obscure itself (in terms of hidden surface removal) and thus cannot  form an internal silhouette edge (when being rendered)  nor, say, cast a shadow on itself.&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;This is also means that when scan converting a triangle, for each pixel, each attribute (e.g. depth, texture coordinate, shading) can only take a 'single' value.&#xD;&#xA; 2. They are guaranteed to be convex. Scan converting/filling convex polygons is *far* simpler than a general polygon filling algorithm&#xD;&#xA;&#xD;&#xA; 3. An arbitrary polygonal mesh can always be *easily* decomposed into triangles&lt;br/&gt;&#xD;&#xA;[**Update**: As @joojaa pointed out, you could still use quads by either&lt;br/&gt;&#xD;&#xA;**a)** Noting that any triangle can be represented as 3 quads by the addition of four more vertices - one at the centre of the triangle and one on each edge). You need to be careful, though, not to [introduce T-Junctions][1]. *or*&lt;br/&gt;&#xD;&#xA;**b)** Using a degenerate quad to create a triangle - i.e. either collapse an edge by repeating a vertex *or* (but this may have other problems due to precision) making 3 of the vertices collinear&#xD;&#xA;Neither seems, to me at least, as particularly attractive].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you are concerned about the 'cost' in vertices of supplying two triangles to represent your quad, remember that APIs (and HW) have triangle strips/fans/indexed representations which will, in most cases, eliminate the additional vertex overheads.&#xD;&#xA;There is thus little point in adding additional hardware to support 'fast' quad rendering as (a) it wouldn't get used much and (b) is extremely unlikely to be the bottleneck in rendering!&#xD;&#xA;&#xD;&#xA;Having said all this, the *original* Series 1 PowerVR graphics chips (eg PCX1 and PCX2) used a lower-level primitive (the half plane) from which N-sided convex polygons (*or in fact N-sided polyhedra - e.g an entire cube was, at most, 6 half-planes*) could be constructed. IIRC the driver tried to detect if two consecutive triangles actually formed a planar quad and then replaced them with a more efficient representation. Further, for a quad to be &quot;planar&quot;, not only did it need to be geometrically flat but the texture coordinates also had to be 'flat'. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/1464/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="26315" PostHistoryTypeId="50" PostId="9048" RevisionGUID="4904f614-2887-4658-b241-0a4c4f491338" CreationDate="2020-02-11T22:02:30.413" UserId="-1" />
  <row Id="26316" PostHistoryTypeId="50" PostId="9475" RevisionGUID="2eff2430-336e-45a8-80c1-f24fc6c49665" CreationDate="2020-02-12T09:02:30.323" UserId="-1" />
  <row Id="26317" PostHistoryTypeId="2" PostId="9565" RevisionGUID="68c85166-e58f-4f0a-b529-bb0035b8c184" CreationDate="2020-02-13T02:37:45.817" UserId="7462" Text="No one answered so I will. The solution is to do the subdivision in 2 passes, first generating new triangles as I showed in the question.&#xD;&#xA;&#xD;&#xA;Then on the second pass you flip them.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As described there:&#xD;&#xA;https://github.com/cmu462/Scotty3D/wiki/Loop-Subdivision&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/75X6y.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26318" PostHistoryTypeId="2" PostId="9566" RevisionGUID="755775f3-d2d5-4309-ac3a-0ab9010025d9" CreationDate="2020-02-13T02:47:45.957" UserId="7462" Text="Ok so let's say we have a portion of a mesh that looks somewhat like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;A triangle fan with one of the triangles removed. If that triangles was not removed, we could get all the edges adjacent to that vertex this way:&#xD;&#xA;&#xD;&#xA;    std::vector&lt;GraphEdgePtr&gt; GraphVertex::GetVertexEdges()&#xD;&#xA;    {&#xD;&#xA;        std::vector&lt;GraphEdgePtr&gt; edges;&#xD;&#xA;        auto current_edge = edge;&#xD;&#xA;        do&#xD;&#xA;        {&#xD;&#xA;            edges.push_back(current_edge);&#xD;&#xA;            current_edge = current_edge-&gt;pair-&gt;next;&#xD;&#xA;        } while(current_edge != edges[0]);&#xD;&#xA;    &#xD;&#xA;        return edges;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, if the triangle is removed, the above will segfault. One could create an additional loop that iterates backwards from the starting edge in the case the first loop finds a null pointer.&#xD;&#xA;&#xD;&#xA;However that is a bit inelegant in my opinion. Is there a way to do it in a single loop? Using a stack or a queue or some sort for example?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Tk5F4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26319" PostHistoryTypeId="1" PostId="9566" RevisionGUID="755775f3-d2d5-4309-ac3a-0ab9010025d9" CreationDate="2020-02-13T02:47:45.957" UserId="7462" Text="How to handle Half edge boundary edge iteration from vertex?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26320" PostHistoryTypeId="3" PostId="9566" RevisionGUID="755775f3-d2d5-4309-ac3a-0ab9010025d9" CreationDate="2020-02-13T02:47:45.957" UserId="7462" Text="|algorithm|c++|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26321" PostHistoryTypeId="5" PostId="9547" RevisionGUID="520e86eb-75f7-49f4-b7bc-ec57216068b9" CreationDate="2020-02-13T11:44:16.017" UserId="11652" Comment="Fixed the text" Text="Rendering is the process of computing a three-dimensional geometric description of a scene into a two-dimensional image representation that looks real. Ray-tracing and Radiosity are two of the most famous rendering techniques for photo realistic images, right?  &#xD;&#xA;&#xD;&#xA;So which technique is suitable for rendering ten under-water images of marine creatures showing total internal reflection needed by ABC Marine Department. The department needs the images to be more natural and can wait for image generation for a month." ContentLicense="CC BY-SA 4.0" />
  <row Id="26322" PostHistoryTypeId="4" PostId="9547" RevisionGUID="520e86eb-75f7-49f4-b7bc-ec57216068b9" CreationDate="2020-02-13T11:44:16.017" UserId="11652" Comment="Fixed the text" Text="Which technique should be used for rendering under water images, Ray tracing or Radiosity?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26323" PostHistoryTypeId="24" PostId="9547" RevisionGUID="520e86eb-75f7-49f4-b7bc-ec57216068b9" CreationDate="2020-02-13T11:44:16.017" Comment="Proposed by 11652 approved by 6, 209 edit id of 509" ContentLicense="CC BY-SA 4.0" />
  <row Id="26324" PostHistoryTypeId="2" PostId="9567" RevisionGUID="e2f3bf92-8011-47c1-a469-d7669498ef77" CreationDate="2020-02-13T13:03:19.510" UserId="6" Text="It depends a little on your actual data structure and how it even encodes boundary edges. What I find more useful than representing the boundary with a null half edge pointer, and thus having this situation of a half edge without an opposite and thus a hard stop for any such iteration, is instead **encoding the boundary with a full half edge pair too, but with one of the half edges having a null *face* pointer**.&#xD;&#xA;&#xD;&#xA;So the boundary edge actually does have an opposite (or `pair` pointer) and that opposite is fully integrated into the pointer structure, complete with `next` pointer and everything. Just that its face pointer in null, thus denoting an empty face or hole. So basically **every hole is represented by a null face with half edges going around it**.&#xD;&#xA;&#xD;&#xA;In addition to being able to iterate around vertices regardless of the starting point, this also has the advantage that you can easily iterate around boundary curves. And you can even have more than one hole at a vertex (although, that can still be problematic in other situations). Of course you might still have to handle the boundary half edges specially in some situations, especially when you're using the face pointers, but you won't get around that anyway if your mesh can have holes.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;If that is too much of a hassle to restructure your data and algorithms this way, though, maybe you can instead adjust your **vertex starting edge pointers to always point to the boundary edge** if there is one. You'd of course have to make sure that stays consistent, but if you can assume that as a precondition, you can just start iterating from there. And you can also check immediately if the vertex is at a boundary without having to iterate." ContentLicense="CC BY-SA 4.0" />
  <row Id="26326" PostHistoryTypeId="2" PostId="9568" RevisionGUID="720138e3-e5b9-4652-bf1e-fe9b88d9f548" CreationDate="2020-02-14T10:39:21.973" UserId="209" Text="As no one else seems to want to suggest something, given that you said you wanted to navigate within an arbitrary enclosed volume, perhaps you could use an approach similar to that of the 1995 game [Descent][1].&#xD;&#xA;&#xD;&#xA;IIRC the world model of 'mine' the spacecraft and enemy mining robots navigated was made up of &quot;cuboid&quot; units/vovels that pieced seamlessly together, some of which had solid walls. The source code is freely available online [e.g. here ][2].&#xD;&#xA;&#xD;&#xA;If you can't force the enclosing volume to have quadrilateral facets, then you might want to consider &quot;tetrahedral&quot; volumes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Descent_(video_game)&#xD;&#xA;  [2]: https://archive.org/details/Descent_source" ContentLicense="CC BY-SA 4.0" />
  <row Id="26330" PostHistoryTypeId="2" PostId="9570" RevisionGUID="4fe712a6-dfdc-49bc-9d14-5bc21cc12f58" CreationDate="2020-02-15T10:14:56.777" UserId="11893" Text="Let's talk about linear geometric transformations in homogeneous coordinates.  In your question there are mainly two kind of geometric transformations involved: planar rotation and planar scaling, the computation-friendly analytical re-definitions of which are found here[Unified frameworks of elementary geometric transformations][1].&#xD;&#xA;&#xD;&#xA;The 2D homogenous rotation matrix that rotates 2D objects clockwise by $\theta$ radians is as below:&#xD;&#xA;&#xD;&#xA;$$R=\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; \cos \theta &amp; \sin \theta&amp; 0 \\&#xD;&#xA; -\sin\theta &amp; \cos\theta &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]$$&#xD;&#xA;&#xD;&#xA;A 2D scaling due to unequal aspect ratio $\rho$ in this case is a stereohomology with $x$ axis $(0,1,0)^T$ as the stereohomology interface (a line of invariant points), and the normal direction $(0,1,0)^T$ as its stereohomology center per definition 3.9 in page 12 and line No. 5 in Table 1, page 9 of the article [Unified frameworks of elementary geometric transformations][1]. Then its scaling matrix can be obtained as below:&#xD;&#xA;&#xD;&#xA;$$S=\color{gray}{\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; 1 &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]+\left(\rho-1\right)\dfrac{\left[&#xD;&#xA;\begin{array}{c}&#xD;&#xA; 0 \\&#xD;&#xA; 1 \\&#xD;&#xA; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]\cdot \left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]}{\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]\cdot \left[&#xD;&#xA;\begin{array}{c}&#xD;&#xA; 0 \\&#xD;&#xA; 1 \\&#xD;&#xA; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]}=}\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; \rho  &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]$$&#xD;&#xA;&#xD;&#xA;When aspect ratio normally is $\rho=1$, suppose under this circumstance the original object has the homogeneous coordinates of $n$ points in $3\times n$ matrix $X$, and the transformed object in $3\times n$ matrix $Y$, then the geometric transformation between them is the rotation you have mentioned:&#xD;&#xA;&#xD;&#xA;$$Y=R\cdot X$$&#xD;&#xA;&#xD;&#xA;When the aspect ratio abnormally is $\rho\ne 1$, both $X$ and the $Y$ after rotation are as a matter of fact scaled along the $y$ axis:&#xD;&#xA;&#xD;&#xA;$$X'=S\cdot X$$&#xD;&#xA;$$Y'=S\cdot Y$$&#xD;&#xA;&#xD;&#xA;Now you want to find the geometric transformation $T$ between $Y'$ and $X'$:&#xD;&#xA;&#xD;&#xA;$$Y'=S\cdot Y=S\cdot R\cdot X =S\cdot R\cdot S^{-1}\cdot X'$$&#xD;&#xA;&#xD;&#xA;then&#xD;&#xA;&#xD;&#xA;$$T=\color{gray}{S\cdot R\cdot S^{-1}=\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; \rho  &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]&#xD;&#xA;\cdot&#xD;&#xA;\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; \cos \theta &amp; \sin \theta&amp; 0 \\&#xD;&#xA; -\sin\theta &amp; \cos\theta &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]\cdot&#xD;&#xA;\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; \dfrac{1}\rho  &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]=}\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; \cos \theta &amp; \dfrac{\sin \theta}{\rho } &amp; 0 \\&#xD;&#xA; -\rho  \sin\theta &amp; \cos \theta&amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]$$&#xD;&#xA;&#xD;&#xA;It is a rotation under the generalized meaning.&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/abs/1307.0998" ContentLicense="CC BY-SA 4.0" />
  <row Id="26331" PostHistoryTypeId="5" PostId="9570" RevisionGUID="fc8943f4-f8cc-427b-baab-1d83406a5d1f" CreationDate="2020-02-15T10:22:00.643" UserId="11893" Comment="added 10 characters in body" Text="Let's talk about linear geometric transformations in homogeneous coordinates.  In your question there are mainly two kind of geometric transformations involved: planar rotation and planar scaling, the computation-friendly analytical re-definitions of which are found here[Unified frameworks of elementary geometric transformations][1].&#xD;&#xA;&#xD;&#xA;The 2D homogenous rotation matrix that rotates 2D objects clockwise by $\theta$ radians is as below:&#xD;&#xA;&#xD;&#xA;$$R=\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; \cos \theta &amp; \sin \theta&amp; 0 \\&#xD;&#xA; -\sin\theta &amp; \cos\theta &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]$$&#xD;&#xA;&#xD;&#xA;A 2D scaling due to unequal aspect ratio $\rho$ in this case is a stereohomology with $x$ axis $(0,1,0)^T$ as the stereohomology interface (a line of invariant points), and the normal direction $(0,1,0)^T$ as its stereohomology center per definition 3.9 in page 12 and line No. 5 in Table 1, page 9 of the article [Unified frameworks of elementary geometric transformations][1]. Then its scaling matrix can be obtained as below:&#xD;&#xA;&#xD;&#xA;$$S=\color{gray}{\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; 1 &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]+\left(\rho-1\right)\dfrac{\left[&#xD;&#xA;\begin{array}{c}&#xD;&#xA; 0 \\&#xD;&#xA; 1 \\&#xD;&#xA; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]\cdot \left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]}{\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]\cdot \left[&#xD;&#xA;\begin{array}{c}&#xD;&#xA; 0 \\&#xD;&#xA; 1 \\&#xD;&#xA; 0 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]}=}\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; \rho  &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]$$&#xD;&#xA;&#xD;&#xA;When aspect ratio normally is $\rho=1$, suppose under this circumstance the original object has the homogeneous coordinates of $n$ points in $3\times n$ matrix $X$, and the transformed object in $3\times n$ matrix $Y$, then the geometric transformation between them is the rotation you have mentioned:&#xD;&#xA;&#xD;&#xA;$$Y=R\cdot X$$&#xD;&#xA;&#xD;&#xA;When the aspect ratio abnormally is $\rho\ne 1$, both $X$ and the $Y$ after rotation are as a matter of fact scaled along the $y$ axis:&#xD;&#xA;&#xD;&#xA;$$X'=S\cdot X$$&#xD;&#xA;$$Y'=S\cdot Y$$&#xD;&#xA;&#xD;&#xA;Now you want to find the geometric transformation $T$  which satisfies $Y'=T\cdot X'$. Since:&#xD;&#xA;&#xD;&#xA;$$Y'=S\cdot Y=S\cdot R\cdot X =S\cdot R\cdot S^{-1}\cdot X'$$&#xD;&#xA;&#xD;&#xA;then&#xD;&#xA;&#xD;&#xA;$$T=S\cdot R\cdot S^{-1}$$ &#xD;&#xA;$$=\color{gray}{\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; \rho  &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]&#xD;&#xA;\cdot&#xD;&#xA;\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; \cos \theta &amp; \sin \theta&amp; 0 \\&#xD;&#xA; -\sin\theta &amp; \cos\theta &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]\cdot&#xD;&#xA;\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; 1 &amp; 0 &amp; 0 \\&#xD;&#xA; 0 &amp; \dfrac{1}\rho  &amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]=}\left[&#xD;&#xA;\begin{array}{ccc}&#xD;&#xA; \cos \theta &amp; \dfrac{\sin \theta}{\rho } &amp; 0 \\&#xD;&#xA; -\rho  \sin\theta &amp; \cos \theta&amp; 0 \\&#xD;&#xA; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{array}&#xD;&#xA;\right]$$&#xD;&#xA;&#xD;&#xA;It is a rotation under the generalized meaning.&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/abs/1307.0998" ContentLicense="CC BY-SA 4.0" />
  <row Id="26332" PostHistoryTypeId="2" PostId="9571" RevisionGUID="0188bcd3-7839-49d4-9ea3-d9ede80c0300" CreationDate="2020-02-15T13:14:05.210" UserId="11895" Text="How does a CPU know which piece of code should be executed on GPU (i.e how to recognize whether a code is shader or not) and how is it been sent to GPU VRAM?Is it via DMA?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26333" PostHistoryTypeId="1" PostId="9571" RevisionGUID="0188bcd3-7839-49d4-9ea3-d9ede80c0300" CreationDate="2020-02-15T13:14:05.210" UserId="11895" Text="Sending programs from CPU to GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="26334" PostHistoryTypeId="3" PostId="9571" RevisionGUID="0188bcd3-7839-49d4-9ea3-d9ede80c0300" CreationDate="2020-02-15T13:14:05.210" UserId="11895" Text="|shader|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26340" PostHistoryTypeId="2" PostId="9572" RevisionGUID="8d63bd7b-c55d-4f33-aace-1d1326a4c41e" CreationDate="2020-02-16T11:02:51.030" UserId="9254" Text="According to the [description in the book](http://www.pbr-book.org/3ed-2018/Introduction/pbrt_System_Overview.html#IntegratorInterfaceandSamplerIntegrator), `Scene::IntersectP()` &quot;checks for the existence of intersections along the [passed] ray&quot;. This operatorion should be symmetric in the sense that if `i1` and `i2` are `pbrt::Interaction`'s, then `scene.IntersectP(i1.SpawnRayTo(i2))` should be `true` if and only if `scene.IntersectP(i2.SpawnRayTo(i1))` is true.&#xD;&#xA;&#xD;&#xA;However, I've encountered the following contradiction to this expectation: For two `pbrt::Vertex`'s `x1` and `x2`, `pbrt::VisibilityTester{ x1.GetInteraction(), x2.GetInteraction() }.Unoccluded(scene)` and `pbrt::VisibilityTester{ x2.GetInteraction(), x1.GetInteraction() }.Unoccluded(scene)` returned opposite values. Since `VisibilityTester::Unoccluded` does nothing else than calling `Scene::IntersectP` in the previously described way (see the [description in the book](http://www.pbr-book.org/3ed-2018/Light_Sources/Light_Interface.html#VisibilityTesting)), it seems like I'm missing something crucial here." ContentLicense="CC BY-SA 4.0" />
  <row Id="26341" PostHistoryTypeId="1" PostId="9572" RevisionGUID="8d63bd7b-c55d-4f33-aace-1d1326a4c41e" CreationDate="2020-02-16T11:02:51.030" UserId="9254" Text="Is casting a shadow ray non-symmetric in pbrt?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26342" PostHistoryTypeId="3" PostId="9572" RevisionGUID="8d63bd7b-c55d-4f33-aace-1d1326a4c41e" CreationDate="2020-02-16T11:02:51.030" UserId="9254" Text="|raytracing|physically-based|global-illumination|pbr|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26343" PostHistoryTypeId="2" PostId="9573" RevisionGUID="58d45ed5-64d0-4150-9e22-e6d608f9b11d" CreationDate="2020-02-16T12:34:39.370" UserDisplayName="user2500" Text="Most, if not all, approaches to GPU programming require the developer to manually identify code that will be executed on the GPU. The code for the GPU is compiled separately from CPU code, so it is clear which binary code is for which processor type. Moving the GPU code to VRAM is often done with DMA, but may be moved to GPU accessible memory using other techniques such as CPU writes across PCIe, or direct CPU memory access by the GPU.&#xD;&#xA;&#xD;&#xA;The GPU compiler often resides in userspace, and a system call will hand binary GPU code to the kernel, which can then make the code available to the GPU.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26344" PostHistoryTypeId="2" PostId="9574" RevisionGUID="aaad08ef-0f0e-4cc4-8b30-2bf926dc41fe" CreationDate="2020-02-16T16:33:27.773" UserId="9254" Text="Say $E_j$ is an estimator of the value $$I_j=\int f_j\:{\rm d}\lambda$$ of the $j$th pixel given by the path space integral of the corresponding measurement contribution function $f_j$. $f_j$ is of the form $f_j=h_jf$, where $h_j$ is essentially the image reconstruction filter of the pixel $j$ (as described, for example, [here](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#ApplicationtoRendering)).&#xD;&#xA;&#xD;&#xA;If we want to quantify the &quot;variance&quot; of the estimates $E_j$ over all pixels $j$, which notion of variance should we consider? Since $f_j$ is 3-dimensional, the natural choice would be given by the covariance matrix of $E_j$. Another option would be to take the variance $\operatorname{Var}\left[\left\|E_j\right\|^2\right]$ of the squared Euclidean norm $\left\|E_j\right\|$ of $E_j$ (which is the trace of the covariance matrix), but this might not contain enough information.&#xD;&#xA;&#xD;&#xA;Since I want to minimize the variances over all $j$, the covariance matrices are too complicated to handle.&#xD;&#xA;&#xD;&#xA;&gt; So, my question is: Can we somehow control the supremum of all variances in terms of a scalar-valued variance? Maybe in terms of the luminance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26345" PostHistoryTypeId="1" PostId="9574" RevisionGUID="aaad08ef-0f0e-4cc4-8b30-2bf926dc41fe" CreationDate="2020-02-16T16:33:27.773" UserId="9254" Text="Quantify the variance of pixel measurements" ContentLicense="CC BY-SA 4.0" />
  <row Id="26346" PostHistoryTypeId="3" PostId="9574" RevisionGUID="aaad08ef-0f0e-4cc4-8b30-2bf926dc41fe" CreationDate="2020-02-16T16:33:27.773" UserId="9254" Text="|raytracing|global-illumination|sampling|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26351" PostHistoryTypeId="2" PostId="9576" RevisionGUID="dd150ed5-5e0e-4a20-bf2b-25346390ba2f" CreationDate="2020-02-17T00:18:29.643" UserId="11903" Text="Ever since I was a small child, seeing the amazing 3D visuals that developed in the 1980s and 1990s, I was certain that photo-realism was &quot;just around the corner&quot;. In the year 2020, I certainly thought it was going to be a standard fact of life.&#xD;&#xA;&#xD;&#xA;That never happened.&#xD;&#xA;&#xD;&#xA;It's as if not only the technology halted, having taken a giant loap from the SNES to the Nintendo 64 in just a few years, but also the whole mentality of game developers seemed to shift around year 2000. Video games, even simulators, started looking more and more unreal and uninteresting to me.&#xD;&#xA;&#xD;&#xA;As the resolutions increased, it only became more and more apparent how crude and fake the 3D environments really were. To me, it seems like they tried to make up for this by adding heaps of visual filters on top, giving a thin illusion of &quot;visual eyecandy&quot;. But not realism. Or even something which looks appealing.&#xD;&#xA;&#xD;&#xA;Movies started to look more and more like these ugly new video games, and the video games started looking less and less like video games, yet still not anywhere close to reality. They both blended together into &quot;generic CGI&quot; which really does look ugly to my eyes, and very far from &quot;real&quot;.&#xD;&#xA;&#xD;&#xA;Today, in the year 2020, there isn't a single modern video game you would catch me dead playing. I'd rather watch paint dry or even sports than I'd play or watch somebody else play these modern video games. How can that be? I don't want it to be the case. I want it to be like how I dreamed it would be 20+ years ago. It seemed like video games and simulations would just keep on getting more and more fun and exciting, but they just... died.&#xD;&#xA;&#xD;&#xA;Now, all I see are dead polygon models with nonexistent AI and which are lightyears away from even resembling real-life wax figures. They look nothing like reality, yet don't have the visual appeal of the &quot;early&quot; 3D games and simulations.&#xD;&#xA;&#xD;&#xA;My dream remains to get to run a program which literally looks like somebody is walking around with a camera in reality. Nothing has ever come close to resembling this, and in fact, we seem to be drifting *further away* from it with each year. And I don't mean that extremely limited tech demo I saw a few years ago where they had made one single room in &quot;OK&quot; detail/realism. While slightly cool, it had zero interactivity and the room was too small and uninteresting for it to qualify. Not to mention it had no living entities in it.&#xD;&#xA;&#xD;&#xA;They don't even seem to be *attempting* to make such things. Everything uses these ugly, unreal visuals with a bunch of uninteresting garbage story where they seem to have spent all their budget on voice actors and motion capture, which I couldn't care less about. I want a perfectly recreated realistic environment to explore with zero story/plot/cutscenes. Just me, walking around, in first-person view. It just starts like that, with no menus or settings or cutscenes or logos. I just double-click an EXE on the desktop and BAM! I'm in a 3D world of the size of perhaps a neighbourhood, free to explore it as if I were actually walking around in the real-life location.&#xD;&#xA;&#xD;&#xA;I don't care if the resolution is 320 x 240 pixels or 4K. It's become clear to me that the resolution has zero to do with how it looks; an old black-and-white 1920s film camera or a 1980s cheap consumer camera will capture infinitely more realistic visuals than the biggest monster computer in existence today can produce. It has nothing to do with the resolution.&#xD;&#xA;&#xD;&#xA;What's stopping people with skills and resources from doing this? I know what's stopping *me* -- I can't make a cube in Blender to save my life. But surely I can't be the only person on this planet who has this strong desire for such a digital, photo-realistic recreation of some -- any! -- location?&#xD;&#xA;&#xD;&#xA;I remember seeing footage of a &quot;game&quot; in the mid-1990s where they had just taken a camera and walked around a real old castle, then made it into an interactive multimedia CD-ROM or something. I didn't understand what technique they had used, so it seemed like it was a photo-realistic simulation to me back then. Ever since that day, I have wanted such a thing &quot;for real&quot;, but not even the most impressive VR demos come anywhere near close.&#xD;&#xA;&#xD;&#xA;Note: This does NOT need to be VR by any means. In fact, since I have sold my VR headset and won't be buying a new one for a very long time, if ever, I don't even want this to be VR." ContentLicense="CC BY-SA 4.0" />
  <row Id="26352" PostHistoryTypeId="1" PostId="9576" RevisionGUID="dd150ed5-5e0e-4a20-bf2b-25346390ba2f" CreationDate="2020-02-17T00:18:29.643" UserId="11903" Text="What is it that really prevents photo-realistic, real-time, digital 3D simulations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26353" PostHistoryTypeId="3" PostId="9576" RevisionGUID="dd150ed5-5e0e-4a20-bf2b-25346390ba2f" CreationDate="2020-02-17T00:18:29.643" UserId="11903" Text="|3d|real-time|simulation|photo-realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26354" PostHistoryTypeId="2" PostId="9577" RevisionGUID="e897969c-5254-45f6-abec-4ddad26a0fab" CreationDate="2020-02-17T05:11:32.777" UserId="11904" Text="I think we should have both and also have a factor based on material&#xD;&#xA;&#xD;&#xA;Some material has high diffusive so it will reflect only light of its own color. But some material can also reflect some light as it is. For the phong shader I think we use additive ambient because phong object tends to reflect all light and so ambient light could be lit it with that light's color, but other lights was used to make diffuse color&#xD;&#xA;&#xD;&#xA;On the contrary to lambert, if what I know is right, are material with high diffusion, and so the ambient light was added to the lit and multiply by material's color&#xD;&#xA;&#xD;&#xA;I guess modern shader should have a parameter to set this factor and write equation like this&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float factor; // 0.0 - 1.0 maybe reflectiveness?&#xD;&#xA;float3 light = (factor * ambient.rgb); // ambient light&#xD;&#xA;light += _MainLightColor.rgb * dot(normal,_MainLightDirection); // lambert&#xD;&#xA;// maybe also specular&#xD;&#xA;float3 color = ((1 - factor) * ambient.rgb) + (matColor * light);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Actually I take this concept from PBR material, there was a concept of energy conservation. All the light may lit the object by diffusion or reflection but to conserve energy, more diffuse color means lower reflection. And so ambient light just add more light energy, then get treat as the same as other light" ContentLicense="CC BY-SA 4.0" />
  <row Id="26356" PostHistoryTypeId="2" PostId="9578" RevisionGUID="c733ba14-868d-4a14-98c3-2392d2911f52" CreationDate="2020-02-17T06:29:41.437" UserId="7462" Text="I coded loop subdivision and ran it on a cube with triangle faces. I noticed this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am using doubles to represent my vertex positions, I am not 100% sure these are caused by floating point imprecisions, but since the general shape looks ok I am not sure what else it could be.&#xD;&#xA;&#xD;&#xA;Any suggestions on how to find the cause? My linear algebra library is glm and I am coding this in C++.&#xD;&#xA;  [1]: https://i.stack.imgur.com/nGaiv.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26357" PostHistoryTypeId="1" PostId="9578" RevisionGUID="c733ba14-868d-4a14-98c3-2392d2911f52" CreationDate="2020-02-17T06:29:41.437" UserId="7462" Text="Loop subdivision, certain areas converging towards degenerate geometry" ContentLicense="CC BY-SA 4.0" />
  <row Id="26358" PostHistoryTypeId="3" PostId="9578" RevisionGUID="c733ba14-868d-4a14-98c3-2392d2911f52" CreationDate="2020-02-17T06:29:41.437" UserId="7462" Text="|c++|mesh|subdivision|float|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26359" PostHistoryTypeId="2" PostId="9579" RevisionGUID="19d6550f-6e92-48aa-a7b2-e4b7019b8ca6" CreationDate="2020-02-17T07:34:59.667" UserId="11832" Text="Since a projection plane and a center of projection is used for achieving perspective projection, the shape of the view frustum doesn't change changing the focal length(which is the distance from the center of projection to the plane of projection i.e. the screen or buffer)  &#xD;&#xA;  &#xD;&#xA;Then how is zooming done in computer graphics? It is mentioned in my textbook that this is done by changing the size of the view frustum and that the relationship that *field of view is inversely proportional to the zoom* holds(somehow I don't know) but looks to me more like a bit conterintuitive, e.g.:  &#xD;&#xA;  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wCGAf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26360" PostHistoryTypeId="1" PostId="9579" RevisionGUID="19d6550f-6e92-48aa-a7b2-e4b7019b8ca6" CreationDate="2020-02-17T07:34:59.667" UserId="11832" Text="how is zooming done in computer graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="26361" PostHistoryTypeId="3" PostId="9579" RevisionGUID="19d6550f-6e92-48aa-a7b2-e4b7019b8ca6" CreationDate="2020-02-17T07:34:59.667" UserId="11832" Text="|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26362" PostHistoryTypeId="2" PostId="9580" RevisionGUID="dd45a229-edb3-4eb3-811a-1b89f223598f" CreationDate="2020-02-17T20:47:15.803" UserId="11907" Text="I am relatively new to computer vision and image processing. I have a single EXR file with 7 channels: 1-3 give me the RGB values, 4-6 give me the surface normals coded as RGB values and 7th channel contains depth information from the camera of the rendered image. I obtained this from the mitsuba renderer using the multi-channel plug-in. &#xD;&#xA;&#xD;&#xA;I was wondering if there was any way to view these 7 channels separately. For eg. I would like an image showing only the depth values in grayscale. So far I haven't found a multi-channel EXR file viewer that does this for me. An example of what I'm talking about is shown in the link: https://www.mitsuba-renderer.org/devblog/wp-content/uploads/2014/02/multichannel.jpg&#xD;&#xA;&#xD;&#xA;Really looking forward to any help. Thanks!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="26363" PostHistoryTypeId="1" PostId="9580" RevisionGUID="dd45a229-edb3-4eb3-811a-1b89f223598f" CreationDate="2020-02-17T20:47:15.803" UserId="11907" Text="Extracting information from EXR Files" ContentLicense="CC BY-SA 4.0" />
  <row Id="26364" PostHistoryTypeId="3" PostId="9580" RevisionGUID="dd45a229-edb3-4eb3-811a-1b89f223598f" CreationDate="2020-02-17T20:47:15.803" UserId="11907" Text="|rendering|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26365" PostHistoryTypeId="2" PostId="9581" RevisionGUID="7597ca16-1de3-4a54-85c0-b7e528472bac" CreationDate="2020-02-18T04:11:50.787" UserId="6588" Text="I don't know any IDE-based tools that do this but a quick Python script should do the trick. I usually use Thijs Vogels' [PyEXR](https://github.com/tvogels/pyexr) to read the multi-channel EXR. Assuming your depth channel is called `distance` (which needs to be specified in your Mitsuba XML file under your `hdrfilm`), you can visualize it with the following code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    import pyexr&#xD;&#xA;    &#xD;&#xA;    fp = pyexr.open('multichannel.exr')&#xD;&#xA;    img = fp.get('distance')&#xD;&#xA;    pyexr.write('distance.exr', img)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26366" PostHistoryTypeId="5" PostId="9568" RevisionGUID="a955212b-9a96-4edd-acaa-753d46467ab0" CreationDate="2020-02-18T08:10:53.970" UserId="209" Comment="fixed grammar and spelling" Text="As no one else seems to want to suggest something, given that you said you wanted to navigate within an arbitrary enclosed volume, perhaps you could use an approach similar to that of the 1995 game [Descent][1].&#xD;&#xA;&#xD;&#xA;IIRC the world model of the 'mine' the spacecraft and enemy robots navigated was made up of &quot;cuboid&quot; units/voxels that pieced seamlessly together, *some* of which had solid walls that then formed the boundaries of the enclosing volume. The source code is freely available online [e.g. here ][2].&#xD;&#xA;&#xD;&#xA;If, in the likely scenario you can't force the enclosing volume to have quadrilateral facets, you might want to consider &quot;tetrahedral&quot; volumes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Descent_(video_game)&#xD;&#xA;  [2]: https://archive.org/details/Descent_source" ContentLicense="CC BY-SA 4.0" />
  <row Id="26367" PostHistoryTypeId="2" PostId="9582" RevisionGUID="b555827d-b7cb-4d41-a3ad-15ff3b139fa9" CreationDate="2020-02-18T08:39:37.920" UserId="11912" Text="From my understanding game developers used mostly proprietary, in-house graphics engines during the sixth console generation (Xbox, PS2, GC, DC) on a game to game basis. Why didn't standard engines like Unreal (for consoles), Unity etc. emerge earlier?&#xD;&#xA;Wasn't it very inefficient to develop a new engine just for one (or probably a few) games?&#xD;&#xA;&#xD;&#xA;Bonus question: Are there any good ressources on graphics development during that time? I'm especially interested in articles about the effort needed to develop an engine for any of the mentioned consoles." ContentLicense="CC BY-SA 4.0" />
  <row Id="26368" PostHistoryTypeId="1" PostId="9582" RevisionGUID="b555827d-b7cb-4d41-a3ad-15ff3b139fa9" CreationDate="2020-02-18T08:39:37.920" UserId="11912" Text="Graphics engines during the sixth console generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="26369" PostHistoryTypeId="3" PostId="9582" RevisionGUID="b555827d-b7cb-4d41-a3ad-15ff3b139fa9" CreationDate="2020-02-18T08:39:37.920" UserId="11912" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26371" PostHistoryTypeId="2" PostId="9583" RevisionGUID="b9dec0e5-1bb2-4cfd-8039-c23fdd86b108" CreationDate="2020-02-18T11:09:56.907" UserId="11832" Text="Now there has already been an answer [here in this stackexchange][1], but I don't understand certain aspects of it.  The author has [MORE DETAILED DESCRIPTION HERE(#1)][2] but the problem is he doesn't describe what the linear mapping is done or how is the frustum transformed into the bounding box, there's **NOWHERE IN THE WORLD** mentioned how these two subspaces overlap or one is transformed to the other, for example:  &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;Is this how these two spaces exist and after projecting the point from inside the view frustum to the near plane a linear mapping is done where the author says:  &#xD;&#xA;  &#xD;&#xA;&quot;Our input to the linear mapping is x=x_near, and our output is the x coordinate in NDC space y=x_ndc, whose range is [-1.0, 1.0]&quot; [from the above page][4]&#xD;&#xA;&#xD;&#xA;It looks as if he somehow connects a line from the frustum to the NDC space but not clear on how it is done e.g. does he connect the top left vertex to the top left front vertex of the NDC cube?   Are the four corners of the frustum mapped to four corners of the cube?&#xD;&#xA;  &#xD;&#xA;As much I'd like to make this answer self contained, I don't know if I can copy his materials in here, please be kind enough to check the link out and help me understand this. Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6254/how-to-derive-a-perspective-projection-matrix-from-its-components&#xD;&#xA;  [2]: https://dovo329.github.io/DeriveOpenGLPerspectiveProjectionMatrix/&#xD;&#xA;  [3]: https://i.stack.imgur.com/02bgu.png&#xD;&#xA;  [4]: http://%20%20%20[2]:%20https://dovo329.github.io/DeriveOpenGLPerspectiveProjectionMatrix/" ContentLicense="CC BY-SA 4.0" />
  <row Id="26372" PostHistoryTypeId="1" PostId="9583" RevisionGUID="b9dec0e5-1bb2-4cfd-8039-c23fdd86b108" CreationDate="2020-02-18T11:09:56.907" UserId="11832" Text="perspective matrix derivation" ContentLicense="CC BY-SA 4.0" />
  <row Id="26373" PostHistoryTypeId="3" PostId="9583" RevisionGUID="b9dec0e5-1bb2-4cfd-8039-c23fdd86b108" CreationDate="2020-02-18T11:09:56.907" UserId="11832" Text="|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26374" PostHistoryTypeId="2" PostId="9584" RevisionGUID="08aff3da-bad9-4fbf-941f-c07a3b8e4538" CreationDate="2020-02-18T12:06:47.277" UserId="137" Text="The key trick is the perspective divide, This divides the position by the `w` component. &#xD;&#xA;&#xD;&#xA;If you swap z and w (using a identity matrix that has swapped 3rd and 4th rows) and then do a perspective divide you end up with a double pyramid with a angle between the side (FoV) of 90° if applied to a unit cube. &#xD;&#xA;&#xD;&#xA;Once you have that transformation you can remap you can do further remapping pre and post the swap to make the corners of the input and output match up. The well known algorithm to create a perspective matrix has all those remaps inlined as an optimization." ContentLicense="CC BY-SA 4.0" />
  <row Id="26375" PostHistoryTypeId="2" PostId="9585" RevisionGUID="7bf7db5b-2221-41f4-a078-5ee9d9896b76" CreationDate="2020-02-18T12:46:10.550" UserId="3073" Text="Renderware was common on the PS2. &#xD;&#xA;&#xD;&#xA;[List of PS2 Renderware titles][1]&#xD;&#xA;&#xD;&#xA;I would guess because these platforms were proprietary and none-standard from a graphics and resources POV that it would be a bigger effort to port Unreal.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/List_of_RenderWare_games" ContentLicense="CC BY-SA 4.0" />
  <row Id="26376" PostHistoryTypeId="5" PostId="9585" RevisionGUID="a5077397-4028-4796-b72c-9849b03c4a9a" CreationDate="2020-02-18T12:53:28.157" UserId="3073" Comment="added 53 characters in body" Text="Renderware was common on the PS2. &#xD;&#xA;&#xD;&#xA;[List of PS2 Renderware titles][1]&#xD;&#xA;&#xD;&#xA;I would guess because these platforms were proprietary and none-standard from a graphics and resources POV that it would be a bigger effort to port Unreal along with all their existing content creation tools.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/List_of_RenderWare_games" ContentLicense="CC BY-SA 4.0" />
  <row Id="26377" PostHistoryTypeId="2" PostId="9586" RevisionGUID="f4df0ca2-23a5-477a-867a-43ccb64ff3cf" CreationDate="2020-02-18T14:53:09.987" UserId="7008" Text="So after letting this lie for quite a while, I just came back to it. Turns out, the error was in my code with a faulty `false` return value which would lead to a `System.exit`. I have no idea how I didn't catch this the last time round, but it now works with *Try 2*. That is:&#xD;&#xA;&#xD;&#xA;    public class SubWindow implements GLEventListener&#xD;&#xA;    {&#xD;&#xA;        GLWindow glWindow;&#xD;&#xA;        Program m_program;&#xD;&#xA;    &#xD;&#xA;        public void createSubWindow(int windowWidth, int windowHeight, boolean isFullscreen, String windowTitle&#xD;&#xA;                , Program program)&#xD;&#xA;        {&#xD;&#xA;            GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3));&#xD;&#xA;            caps.setBackgroundOpaque(false);&#xD;&#xA;            glWindow = GLWindow.create(caps);&#xD;&#xA;    &#xD;&#xA;            glWindow.setTitle(windowTitle);&#xD;&#xA;            glWindow.setSize(windowWidth, windowHeight);&#xD;&#xA;            glWindow.setUndecorated(false);&#xD;&#xA;            glWindow.setPointerVisible(true);&#xD;&#xA;            glWindow.setVisible(true);&#xD;&#xA;    &#xD;&#xA;            m_program = program;&#xD;&#xA;            glWindow.addGLEventListener(this);&#xD;&#xA;            glWindow.addKeyListener(m_program);&#xD;&#xA;            glWindow.addMouseListener(m_program);&#xD;&#xA;    &#xD;&#xA;            Animator animator = new Animator();&#xD;&#xA;            animator.add(glWindow);&#xD;&#xA;            animator.start();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;Where the `Program` is one of my own classes handling the logic and the SubWindow class additionally implements the required `init`, `display`, etc. methods." ContentLicense="CC BY-SA 4.0" />
  <row Id="26378" PostHistoryTypeId="2" PostId="9587" RevisionGUID="c29d0eef-5cd1-4ea8-90b1-a753c14cc736" CreationDate="2020-02-18T16:20:18.180" UserId="11282" Text="I have a situation where (due to floating point error) a ray that is *known* to hit a bounding box fails due to floating point error. (1e-8 or so)&#xD;&#xA;&#xD;&#xA;Expanding the box is not an acceptable solution in my specific use case. However, if I could &quot;snap&quot; the ray to the box, that would work out well.&#xD;&#xA;&#xD;&#xA;In order to do so, I need to find the shortest ray from a given ray to a bounding box. In 2 dimensions, that would look like this: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LtRig.png&#xD;&#xA;&#xD;&#xA;If I can get that red vector, I can add it to the origin and the ray will be shifted to the bounding box.&#xD;&#xA;&#xD;&#xA;In 2D this is apparently relatively easy, as you can get distance between two lines like [here](http://csharphelper.com/blog/2014/08/find-the-shortest-distance-between-two-line-segments-in-c/), then find the smallest of the 4 lines and use that. &#xD;&#xA;&#xD;&#xA;But in 3D I am not aware of how to do this. Does anyone know if there is a way?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26379" PostHistoryTypeId="1" PostId="9587" RevisionGUID="c29d0eef-5cd1-4ea8-90b1-a753c14cc736" CreationDate="2020-02-18T16:20:18.180" UserId="11282" Text="Determining shortest vector between a ray and a 3D bounding box (correcting a near-miss)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26380" PostHistoryTypeId="3" PostId="9587" RevisionGUID="c29d0eef-5cd1-4ea8-90b1-a753c14cc736" CreationDate="2020-02-18T16:20:18.180" UserId="11282" Text="|raytracing|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26381" PostHistoryTypeId="4" PostId="9587" RevisionGUID="1bbcb045-0ff3-4453-af33-c6113eb13832" CreationDate="2020-02-18T16:26:51.333" UserId="11282" Comment="edited title" Text="Determining shortest vector between a ray and an axis-aligned 3D bounding box (correcting a near-miss)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26382" PostHistoryTypeId="5" PostId="9587" RevisionGUID="1bbcb045-0ff3-4453-af33-c6113eb13832" CreationDate="2020-02-18T16:26:51.333" UserId="11282" Comment="edited title" Text="I have a situation where (due to floating point error) a ray that is *known* to hit a bounding box fails due to floating point error. (1e-8 or so)&#xD;&#xA;&#xD;&#xA;Expanding the box is not an acceptable solution in my specific use case. However, if I could &quot;snap&quot; the ray to the box, that would work out well.&#xD;&#xA;&#xD;&#xA;In order to do so, I need to find the shortest vector from a given ray to a bounding box. In 2 dimensions, that would look like this: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LtRig.png&#xD;&#xA;&#xD;&#xA;If I can get that red vector, I can add it to the origin and the ray will be shifted to the bounding box.&#xD;&#xA;&#xD;&#xA;In 2D this is apparently relatively easy, as you can get distance between two lines like [here](http://csharphelper.com/blog/2014/08/find-the-shortest-distance-between-two-line-segments-in-c/), then find the smallest of the 4 lines and use that. &#xD;&#xA;&#xD;&#xA;But in 3D I am not aware of how to do this. Does anyone know if there is a way?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26383" PostHistoryTypeId="2" PostId="9588" RevisionGUID="8a933012-800d-4dc0-b743-1abb639197d3" CreationDate="2020-02-18T23:24:27.027" UserId="11915" Text="If you know the rounding error, you could subtract the error from your vectors so that rays would overlap the bounding box. This could be done in your intersection tests.&#xD;&#xA;&#xD;&#xA;In 3D, computing shortest distance between a vector and face of a bounding box would be another way to shift the vector to overlap the bounding box. But I doubt this approach would work well as it essentially tries to fix a rounding problem. " ContentLicense="CC BY-SA 4.0" />
  <row Id="26384" PostHistoryTypeId="2" PostId="9589" RevisionGUID="534378bb-de25-4031-a665-04005ae42672" CreationDate="2020-02-19T14:31:30.183" UserId="9254" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xD;&#xA;&#xD;&#xA;The authors write:&#xD;&#xA;&#xD;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xD;&#xA;&#xD;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xD;&#xA;&#xD;&#xA;I don't get that. For simplicity assume that we only run a single chain (i.e. `nChains = 1`). Then `nChainMutations = nTotalMutations = mutationsPerPixel * film.GetSampleBounds().Area()`. Clearly, we can somehow expect that `mutationsPerPixel` samples are added to each pixel. However, the pixel color value of the $j$th pixel is $$I_j=\int h_jL\:{\rm d}\mu$$ and $h_j$ is essentially an indicator function of the $j$th pixel. The estimate used for $I_j$ is $\frac bN\sum_{n=0}^{N-1}\frac{h_jL}I(X_i)$, where $b=\int I\:{\rm d}\mu$ and $N$ is eqaul to `nTotalMutations`. So shouldn't we scale by `b / nTotalMutatons` instead?&#xD;&#xA;&#xD;&#xA;Maybe something inside the `film-&gt;AddSplat` or `film-&gt;WriteImage` methods already scales the samples by `1 / film.GetSampleBounds().Area()` so that we only need to further scale it by `b / mutationsPerPixel`, but I don't see where this prescaling happends." ContentLicense="CC BY-SA 4.0" />
  <row Id="26385" PostHistoryTypeId="1" PostId="9589" RevisionGUID="534378bb-de25-4031-a665-04005ae42672" CreationDate="2020-02-19T14:31:30.183" UserId="9254" Text="Scaling of the final image in Metropolis Light Transport" ContentLicense="CC BY-SA 4.0" />
  <row Id="26386" PostHistoryTypeId="3" PostId="9589" RevisionGUID="534378bb-de25-4031-a665-04005ae42672" CreationDate="2020-02-19T14:31:30.183" UserId="9254" Text="|raytracing|global-illumination|pbr|monte-carlo|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26390" PostHistoryTypeId="4" PostId="9048" RevisionGUID="dfc426a5-3876-4e71-8756-be5a2f8f62e2" CreationDate="2020-02-19T17:36:06.437" UserId="10957" Comment="edited title" Text="How can i wrap the earth image around a 3D Sphere using OpenGL, GLFW, GLAD, GLM?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26391" PostHistoryTypeId="5" PostId="9558" RevisionGUID="c62f2d74-3652-47bd-aece-8093d2d80fb8" CreationDate="2020-02-19T18:28:51.727" UserId="7462" Comment="deleted 1 character in body" Text="Be it chaikin subdivision, loop subdivision, catmull-clark subdivision...&#xD;&#xA;&#xD;&#xA;How do people come up with the coefficients for an arbitrary subdivision scheme?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26392" PostHistoryTypeId="2" PostId="9591" RevisionGUID="34d370ba-cfbd-4398-867e-147963d7c84a" CreationDate="2020-02-19T18:56:41.740" UserId="9254" Text="Let $f$ denote the measurement contribution function for paths of length $k\in\mathbb N$, i.e. $$f(x)=g(x_0\leftrightarrow x_1)W_{\text e}(x_1\to x_0)t_k(x_0,\ldots,x_k)L_{\text e}(x_k\to x_{k-1}),$$ where $$t_k(x)=\prod_{i=2}^kg(x_{i-1}\leftrightarrow x_i)f_{\text s}(x_i\to x_{i-1}\to x_{i-2}),$$ and $h_j$ denote the image reconstruction filter of the $j$th pixel so that the measurement $I_j$ of the $j$th pixel color is given by $$I_j=\int h_jf\:{\rm d}\mu.$$&#xD;&#xA;&#xD;&#xA;What can we assume know about $h_j$ in general? One thing is that it will only depend on first two vertices of a path.&#xD;&#xA;&#xD;&#xA;There are two properties which I really would like to being able to assume: (a) $c:=\sup_j\left\|h_j\right\|&lt;\infty$ (b) $\int|h_jf-I_j|^2\:{\rm d}\mu\le\int|f_0|^2\:{\rm d}\mu$, where $f_0:=f-\int f\:{\rm d}\mu$.&#xD;&#xA;&#xD;&#xA;However, I know almost nothing about the mathematical properties of $h_j$ and so it's hard for me to verify if these properties hold. I guess that generally $h_j\ge0$, but I'm even unsure about that. Maybe even $h_j\in[0,1]$? It would be great if someone could answer if (a) and/or (b) hold or link me to a reference." ContentLicense="CC BY-SA 4.0" />
  <row Id="26393" PostHistoryTypeId="1" PostId="9591" RevisionGUID="34d370ba-cfbd-4398-867e-147963d7c84a" CreationDate="2020-02-19T18:56:41.740" UserId="9254" Text="Properties of the image reconstruction filter in rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="26394" PostHistoryTypeId="3" PostId="9591" RevisionGUID="34d370ba-cfbd-4398-867e-147963d7c84a" CreationDate="2020-02-19T18:56:41.740" UserId="9254" Text="|raytracing|physically-based|global-illumination|monte-carlo|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26397" PostHistoryTypeId="2" PostId="9593" RevisionGUID="779403f4-662a-4b4b-8ca3-c1ea63398219" CreationDate="2020-02-19T19:39:43.223" UserId="11922" Text="What is the size of the final filter after implement convolution of multiple gaussian filters with different sizes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26398" PostHistoryTypeId="1" PostId="9593" RevisionGUID="779403f4-662a-4b4b-8ca3-c1ea63398219" CreationDate="2020-02-19T19:39:43.223" UserId="11922" Text="Convolution of multiple gaussian filters with different sizes" ContentLicense="CC BY-SA 4.0" />
  <row Id="26399" PostHistoryTypeId="3" PostId="9593" RevisionGUID="779403f4-662a-4b4b-8ca3-c1ea63398219" CreationDate="2020-02-19T19:39:43.223" UserId="11922" Text="|image-processing|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26400" PostHistoryTypeId="5" PostId="9591" RevisionGUID="2bde83d5-3d47-4647-95ca-e5095ca86dad" CreationDate="2020-02-20T05:32:52.997" UserId="9254" Comment="added 28 characters in body" Text="Let $f$ denote the measurement contribution function for paths of length $k\in\mathbb N$, i.e. $$f(x)=g(x_0\leftrightarrow x_1)W_{\text e}(x_1\to x_0)t_k(x_0,\ldots,x_k)L_{\text e}(x_k\to x_{k-1}),$$ where $$t_k(x)=\prod_{i=2}^kg(x_{i-1}\leftrightarrow x_i)f_{\text s}(x_i\to x_{i-1}\to x_{i-2}),$$ and $h_j$ denote the image reconstruction filter of the $j$th pixel so that the measurement $I_j$ of the $j$th pixel color is given by $$I_j=\int h_jf\:{\rm d}\mu.$$&#xD;&#xA;&#xD;&#xA;What can we assume know about $h_j$ in general? One thing is that it will only depend on first two vertices of a path.&#xD;&#xA;&#xD;&#xA;There are two properties which I really would like to being able to assume: (a) $c:=\sup_j\left\|h_j\right\|&lt;\infty$ (b) $\int|h_jf-I_j|^2\:{\rm d}\mu\le\alpha\int|f_0|^2\:{\rm d}\mu$ for some $\alpha\ge0$, where $f_0:=f-\int f\:{\rm d}\mu$.&#xD;&#xA;&#xD;&#xA;However, I know almost nothing about the mathematical properties of $h_j$ and so it's hard for me to verify if these properties hold. I guess that generally $h_j\ge0$, but I'm even unsure about that. Maybe even $h_j\in[0,1]$? It would be great if someone could answer if (a) and/or (b) hold or link me to a reference." ContentLicense="CC BY-SA 4.0" />
  <row Id="26401" PostHistoryTypeId="5" PostId="258" RevisionGUID="b3539f3a-f827-4afb-9bb9-e330ddb1ecbf" CreationDate="2020-02-20T11:08:50.343" UserId="209" Comment="The original initial &quot;Yes&quot; in the reply was perhaps accidentally misleading given the final question in the original post." Text="Almost. Applying two Gaussian blurs *is* equivalent to doing one Gaussian blur, but with a slightly different size calculation.&#xD;&#xA;&#xD;&#xA;Applying a Gaussian blur to an image means doing a [convolution](https://en.wikipedia.org/wiki/Convolution) of the Gaussian with the image. Convolution is associative: Applying two Gaussian blurs to an image is equivalent to convolving the two Gaussians with each other, and convolving the resulting function with the image.&#xD;&#xA;&#xD;&#xA;As it happens, the convolution of two Gaussians with each other is another Gaussian, whose variance is the sum of variances of the two original Gaussians. A Gaussian of N pixel width has variance $N^2$; applying it twice is equivalent to a Gaussian with variance $2\cdot N^2$, which corresponds to a width of $\sqrt{2}\cdot N$ pixels.&#xD;&#xA;&#xD;&#xA;In the same vein, applying a Gaussian of width $2\cdot N$ is equivalent to applying a Gaussian of width $N$ four times." ContentLicense="CC BY-SA 4.0" />
  <row Id="26402" PostHistoryTypeId="2" PostId="9594" RevisionGUID="ee387402-f0b8-40d0-98aa-ed027246fb32" CreationDate="2020-02-20T12:04:00.063" UserId="11850" Text="I know OBJ-files essentially are one or more lists of n-tuples containing information about the location of vertices, texture and normals. However, I am not sure how this is structured in an IFC-file. &#xD;&#xA;&#xD;&#xA;However, whenever I look for the data structure of IFC-files, I find information regarding the hierarchy of elements in IFC, but I cannot find information regarding how the geometry is saved. Also, how is this related to the hierarchy of entities in the model?&#xD;&#xA;&#xD;&#xA;What should I learn to understand this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26403" PostHistoryTypeId="1" PostId="9594" RevisionGUID="ee387402-f0b8-40d0-98aa-ed027246fb32" CreationDate="2020-02-20T12:04:00.063" UserId="11850" Text="Data structure of IFC-files" ContentLicense="CC BY-SA 4.0" />
  <row Id="26404" PostHistoryTypeId="3" PostId="9594" RevisionGUID="ee387402-f0b8-40d0-98aa-ed027246fb32" CreationDate="2020-02-20T12:04:00.063" UserId="11850" Text="|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26408" PostHistoryTypeId="2" PostId="9596" RevisionGUID="116527a4-d325-43c0-95c6-9b1954c91261" CreationDate="2020-02-20T20:21:34.007" UserId="9254" Text="Let $W_{\text e}$ denote the camera sensor responsivity (i.e. importance) and $h_j$ and $W_{\text e}^{(j)}$ denote the  image reconstruction filter and sensor response associated with the $j$th pixel, respectively, i.e. $$W_{\text e}^{(j)}=h_jW_{\text e}.\tag1$$ The measurement of the $j$th pixel is given by \begin{equation}\begin{split}\Phi_j&amp;:=\sigma_M({\rm d}x_0)\int\sigma_M({\rm d}x_1)g(x_0\leftrightarrow x_1)W_{\text e}^{(j)}(x_1\to x_0)L_{\text o}(x_1\to x_0)\\&amp;=\int\lambda({\rm d}x)h_j(x_1\to x_0)f(x),\end{split}\tag2\end{equation} where $g$ denotes the geometry term, $\lambda$ is the infinite-product area measure on the path space and $f$ is the measurement contribution function, i.e. $$f(x)=g(x_0\leftrightarrow x_1)W_{\text e}(x_1\to x_0)\prod_{i=2}^kg(x_{i-1}\leftrightarrow x_i)f_{\text s}(x_i\to x_{i-1}\to x_{i-2})L_{\text e}(x_k\to x_{k-1}),\tag3$$ if $x$ is a path of length $k\in\mathbb N$.&#xD;&#xA;&#xD;&#xA;&gt; Usually, in the context of Metropolis Light Transport, the scalar contribution function $p$ is defined to be the luminance of $f$. So, by definition, $p(x)=0$ whenever $(x_0,x_1)$ doesn't belong to $$B:=\left\{(x_0,x_1):W_{\text e}(x_1\to x_0)\ne 0\right\}.$$ Now let $$B_j:=\left\{(x_0,x_1):W_{\text e}(x_1\to x_0)\ne 0\right\}.$$ We clearly have $$B=\bigcup_jB_j.\tag4$$ However, in light of the way samples are splat to image (see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#fragment-Splatbothcurrentandproposedsamplestomonofilm-0 or https://pdfs.semanticscholar.org/a386/55316ee7f438ba115b38e8d0b1410c691a26.pdf and [my other question](https://computergraphics.stackexchange.com/q/9589/9254)), it seems like it is assumed that the union in $(4)$ is disjoint. Is this really guaranteed to be the case?&#xD;&#xA;&#xD;&#xA;Taking a look in Section 2.6.4, on page 51, of [this PhD thesis]](https://backend.orbit.dtu.dk/ws/portalfiles/portal/51112612/phd240_awk_vers2.pdf), this seems at least to be the case when the camera is a pinhole camera and a suitable filter $h_j$ (how exactly is it defined?) is used." ContentLicense="CC BY-SA 4.0" />
  <row Id="26409" PostHistoryTypeId="1" PostId="9596" RevisionGUID="116527a4-d325-43c0-95c6-9b1954c91261" CreationDate="2020-02-20T20:21:34.007" UserId="9254" Text="Relation between camera sensor responsivity and image reconstruction filter associated with a pixel" ContentLicense="CC BY-SA 4.0" />
  <row Id="26410" PostHistoryTypeId="3" PostId="9596" RevisionGUID="116527a4-d325-43c0-95c6-9b1954c91261" CreationDate="2020-02-20T20:21:34.007" UserId="9254" Text="|raytracing|physically-based|global-illumination|monte-carlo|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26411" PostHistoryTypeId="5" PostId="9596" RevisionGUID="d7723373-2079-47d5-8a3f-d5791fc88c68" CreationDate="2020-02-20T20:29:14.043" UserId="9254" Comment="added 359 characters in body" Text="Let $W_{\text e}$ denote the camera sensor responsivity (i.e. importance) and $h_j$ and $W_{\text e}^{(j)}$ denote the  image reconstruction filter and sensor response associated with the $j$th pixel, respectively, i.e. $$W_{\text e}^{(j)}=h_jW_{\text e}.\tag1$$ The measurement of the $j$th pixel is given by \begin{equation}\begin{split}\Phi_j&amp;:=\sigma_M({\rm d}x_0)\int\sigma_M({\rm d}x_1)g(x_0\leftrightarrow x_1)W_{\text e}^{(j)}(x_1\to x_0)L_{\text o}(x_1\to x_0)\\&amp;=\int\lambda({\rm d}x)h_j(x_1\to x_0)f(x),\end{split}\tag2\end{equation} where $g$ denotes the geometry term, $\lambda$ is the infinite-product area measure on the path space and $f$ is the measurement contribution function, i.e. $$f(x)=g(x_0\leftrightarrow x_1)W_{\text e}(x_1\to x_0)\prod_{i=2}^kg(x_{i-1}\leftrightarrow x_i)f_{\text s}(x_i\to x_{i-1}\to x_{i-2})L_{\text e}(x_k\to x_{k-1}),\tag3$$ if $x$ is a path of length $k\in\mathbb N$.&#xD;&#xA;&#xD;&#xA;&gt; Usually, in the context of Metropolis Light Transport, the scalar contribution function $p$ is defined to be the luminance of $f$. So, by definition, $p(x)=0$ whenever $(x_0,x_1)$ doesn't belong to $$B:=\left\{(x_0,x_1):W_{\text e}(x_1\to x_0)\ne 0\right\}.$$ Now let $$B_j:=\left\{(x_0,x_1):W_{\text e}(x_1\to x_0)\ne 0\right\}.$$ We clearly have $$B=\bigcup_jB_j.\tag4$$ However, in light of the way samples are splat to image (see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#fragment-Splatbothcurrentandproposedsamplestomonofilm-0 or https://pdfs.semanticscholar.org/a386/55316ee7f438ba115b38e8d0b1410c691a26.pdf and [my other question](https://computergraphics.stackexchange.com/q/9589/9254)), it seems like it is assumed that the union in $(4)$ is disjoint. Is this really guaranteed to be the case?&#xD;&#xA;&#xD;&#xA;Taking a look in Section 2.6.4, on page 51, of [this PhD thesis]](https://backend.orbit.dtu.dk/ws/portalfiles/portal/51112612/phd240_awk_vers2.pdf), this seems at least to be the case when the camera is a pinhole camera. The authors write: $W_{\text e}^{(j)}$ *is non-zero only for the set of directions within the pyramid formed by the pinhole and the four corners of the corresponding pixel* $j$.&#xD;&#xA;&#xD;&#xA;This seems to indicate that (at least for the pinhole camera) the &quot;support&quot; of $W_{\text e}^{(j)}$ is limited to the image rectangle region occupied by the $j$th pixel. But is this really true for *any* filter $h_j$ or only for a special one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26412" PostHistoryTypeId="2" PostId="9597" RevisionGUID="912341bb-c024-4e9d-a479-6563159d61d8" CreationDate="2020-02-21T10:53:46.600" UserId="5574" Text="**NOTE: THIS IS A WORK IN PROGRESS - WORKING ON LaTeX AND DIAGRAMS**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;My derivation notes were based partially on the perspective projection matrix derivation in [`Computer Graphics: Principles and Practice (2nd Ed)`](https://www.amazon.com/Computer-Graphics-Principles-Practice-2nd/dp/0201848406). My understanding is that the 3rd edition takes a more contemporary approach with references to OpenGL and Direct3D. I haven't read this edition, and can't vouch for it.&#xD;&#xA;&#xD;&#xA;- Assume a ['right-handed' coordinate space](https://en.wikipedia.org/wiki/Right-hand_rule#Coordinates). The 'eye' is at: `(0, 0, 0)`. `(+Z)` may be considered the direction pointing 'out' of the screen (or window / viewport), while `(X, Y)` are Cartesian coordinates: `(0, 0)` corresponds to the centre of that viewport.&#xD;&#xA;&#xD;&#xA;- The [**view frustum**](https://en.wikipedia.org/wiki/Viewing_frustum) has a near plane at: `Z = - N` and a far plane at: `Z = - F`, with normals in the `+Z` direction. The near plane: `Z = - N`, has `X: L &lt;= X &lt;= R`, and `Y: B &lt;= Y &lt;= T`, which will eventually map to a **3D viewport**. This frustum encapsulates all visible geometry.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Any view frustum (camera) in space can be transformed by pre-multiplying the (homogeneous) space by an 'orientation matrix'. That's beyond your question, but typically requires a general **PRP** (camera eye point), **VRP** (the centre of the 'near' projection plane), and the **VUP** point, which references a point defining 'up'. In effect, it's sufficient to form a orthonormal coordinate system. This is the view coordinate space **(VCS)**.&#xD;&#xA;&#xD;&#xA;The orthonormal basis, along with the **PRP** translation, can be used to construct an inverse transform that 'premultiplies' geometry to world coordinate space **(WCS)**. Again, you can save the concept of orthonormal basis / coordinate system transforms for a rainy day...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;- We do not *assume* the view frustum is centred on the Z axis - although this is almost certainly the case for most projections. There are more exotic transforms (a mirror in a scene comes to mind); we'll concentrate on the general case.&#xD;&#xA;&#xD;&#xA;- The direction of projection is: `DOP = [(R + L) / 2, (T + B) / 2, - N]`. The view frustum typically exhibits symmetry about the Z axis s.t. `R = - L`, `T = - B`, to yield `DOP = [0, 0, - N]`. Of course, this is not *required*, so our first step in the perspective projection derivation is to apply a *shear* matrix that maps to the `DOP` to the (negative) Z-axis:&#xD;&#xA;&#xD;&#xA;`(R + L) / 2 + shear.x (- N) = 0 =&gt; shear.x = (R + L) / (2N)`&lt;br/&gt;&#xD;&#xA;`(T + B) / 2 + shear.y (- N) = 0 =&gt; shear.y = (T + B) / (2N)`&#xD;&#xA;&#xD;&#xA;Consider the shear transformation applied to the near-plane frustum vertex point: $\small \begin{bmatrix}R,&amp;T,&amp;-N,&amp;1\end {bmatrix}^T\\$ :&#xD;&#xA;&#xD;&#xA;$$\small \begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;R \\ T \\ -N \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= \begin{bmatrix}&#xD;&#xA;(R-L)/2 \\ (T-B)/2 \\ -N \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and the point: $\small \begin{bmatrix}L,&amp;B,&amp;-N,&amp;1\end {bmatrix}^T\\$ :&#xD;&#xA;&#xD;&#xA;$$\small \begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;L \\ B \\ -N \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= \begin{bmatrix}&#xD;&#xA;(L-R)/2 \\ (B-T)/2 \\ -N \\1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Following this transform, the `DOP` is in direction of the `-Z` axis. Specifically, the centre of the near view plane: `((R + L) / 2, (T + B) / 2, - N, 1)` maps to: `(0, 0, - N, 1)`.&#xD;&#xA;&#xD;&#xA;- Now we want to scale the perspective projection transform such that we have unit slopes. The current slopes are `(R - L) / (2N)` (right and left), and `(T - B) / (2N)` (top and bottom). The symmetry is due to the previous shearing transform.&#xD;&#xA;&#xD;&#xA;`(R - L) / (2N) * scale.x = 1 =&gt; scale.x = 2N / (R - L)`&lt;br/&gt;&#xD;&#xA;`(T - B) / (2N) * scale.y = 1 =&gt; scale.y = 2N / (T - B)`&#xD;&#xA;&#xD;&#xA;- Furthermore, we want to scale by `(1 / F)` s.t. the far clipping plane is mapped to `(Z = - 1)`, while the unit slopes of the right, left, top, and bottom clipping planes are preserved. These scaling factors premultiply the perspective projection matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\small\begin{bmatrix}&#xD;&#xA;2N/(F(R-L)) &amp; 0 &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 2N/(F(T-B)) &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;To yield:&#xD;&#xA;$$&#xD;&#xA;\small\begin{bmatrix}&#xD;&#xA;2N/(F(R-L)) &amp; 0 &amp; (R+L)/(F(R-L)) &amp; 0 \\ &#xD;&#xA;0 &amp; 2N/(F(T-B)) &amp; (T+B)/(F(T-B)) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**(TODO: need an image to show this transform!!)**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26413" PostHistoryTypeId="5" PostId="9597" RevisionGUID="4fa104d2-6ea9-490f-8d92-9bf422aa7f82" CreationDate="2020-02-21T11:12:09.633" UserId="5574" Comment="added 164 characters in body" Text="**NOTE: THIS IS A WORK IN PROGRESS - WORKING ON LaTeX AND DIAGRAMS**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;My derivation notes were based partially on the perspective projection matrix derivation in [`Computer Graphics: Principles and Practice (2nd Ed)`](https://www.amazon.com/Computer-Graphics-Principles-Practice-2nd/dp/0201848406). My understanding is that the 3rd edition takes a more contemporary approach with references to OpenGL and Direct3D. I haven't read this edition, and can't vouch for it.&#xD;&#xA;&#xD;&#xA;- Assume a ['right-handed' coordinate space](https://en.wikipedia.org/wiki/Right-hand_rule#Coordinates). The 'eye' is at: `(0, 0, 0)`. `(+Z)` may be considered the direction pointing 'out' of the screen (or window / viewport), while `(X, Y)` are Cartesian coordinates: `(0, 0)` corresponds to the centre of that viewport.&#xD;&#xA;&#xD;&#xA;- The [**view frustum**](https://en.wikipedia.org/wiki/Viewing_frustum) has a near plane at: `Z = - N` and a far plane at: `Z = - F`, with normals in the `+Z` direction. The near plane: `Z = - N`, has `X: L &lt;= X &lt;= R`, and `Y: B &lt;= Y &lt;= T`, which will eventually map to a **3D viewport**. This frustum encapsulates all visible geometry. (Technically speaking, `R &lt; L`, `T &lt; B`, and `N &gt; F &gt; 0` are permitted by `glFrustum`. Arbitrary matrices are of course permitted in core profile OpenGL contexts.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Any view frustum (camera) in space can be transformed by pre-multiplying the (homogeneous) space by an 'orientation matrix'. That's beyond your question, but typically requires a general **PRP** (camera eye point), **VRP** (the centre of the 'near' projection plane), and the **VUP** point, which references a point defining 'up'. In effect, it's sufficient to form a orthonormal coordinate system. This is the view coordinate space **(VCS)**.&#xD;&#xA;&#xD;&#xA;The orthonormal basis, along with the **PRP** translation, can be used to construct an inverse transform that 'premultiplies' geometry to world coordinate space **(WCS)**. Again, you can save the concept of orthonormal basis / coordinate system transforms for a rainy day...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;- We do not *assume* the view frustum is centred on the Z axis - although this is almost certainly the case for most projections. There are more exotic transforms (a mirror in a scene comes to mind); we'll concentrate on the general case.&#xD;&#xA;&#xD;&#xA;- The direction of projection is: `DOP = [(R + L) / 2, (T + B) / 2, - N]`. The view frustum typically exhibits symmetry about the Z axis s.t. `R = - L`, `T = - B`, to yield `DOP = [0, 0, - N]`. Of course, this is not *required*, so our first step in the perspective projection derivation is to apply a *shear* matrix that maps to the `DOP` to the (negative) Z-axis:&#xD;&#xA;&#xD;&#xA;`(R + L) / 2 + shear.x (- N) = 0 =&gt; shear.x = (R + L) / (2N)`&lt;br/&gt;&#xD;&#xA;`(T + B) / 2 + shear.y (- N) = 0 =&gt; shear.y = (T + B) / (2N)`&#xD;&#xA;&#xD;&#xA;Consider the shear transformation applied to the near-plane frustum vertex point: $\small \begin{bmatrix}R,&amp;T,&amp;-N,&amp;1\end {bmatrix}^T\\$ :&#xD;&#xA;&#xD;&#xA;$$\small \begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;R \\ T \\ -N \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= \begin{bmatrix}&#xD;&#xA;(R-L)/2 \\ (T-B)/2 \\ -N \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and the point: $\small \begin{bmatrix}L,&amp;B,&amp;-N,&amp;1\end {bmatrix}^T\\$ :&#xD;&#xA;&#xD;&#xA;$$\small \begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;L \\ B \\ -N \\ 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;= \begin{bmatrix}&#xD;&#xA;(L-R)/2 \\ (B-T)/2 \\ -N \\1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Following this transform, the `DOP` is in direction of the `-Z` axis. Specifically, the centre of the near view plane: `((R + L) / 2, (T + B) / 2, - N, 1)` maps to: `(0, 0, - N, 1)`.&#xD;&#xA;&#xD;&#xA;- Now we want to scale the perspective projection transform such that we have unit slopes. The current slopes are `(R - L) / (2N)` (right and left), and `(T - B) / (2N)` (top and bottom). The symmetry is due to the previous shearing transform.&#xD;&#xA;&#xD;&#xA;`(R - L) / (2N) * scale.x = 1 =&gt; scale.x = 2N / (R - L)`&lt;br/&gt;&#xD;&#xA;`(T - B) / (2N) * scale.y = 1 =&gt; scale.y = 2N / (T - B)`&#xD;&#xA;&#xD;&#xA;- Furthermore, we want to scale by `(1 / F)` s.t. the far clipping plane is mapped to `(Z = - 1)`, while the unit slopes of the right, left, top, and bottom clipping planes are preserved. These scaling factors premultiply the perspective projection matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\small\begin{bmatrix}&#xD;&#xA;2N/(F(R-L)) &amp; 0 &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 2N/(F(T-B)) &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;To yield:&#xD;&#xA;$$&#xD;&#xA;\small\begin{bmatrix}&#xD;&#xA;2N/(F(R-L)) &amp; 0 &amp; (R+L)/(F(R-L)) &amp; 0 \\ &#xD;&#xA;0 &amp; 2N/(F(T-B)) &amp; (T+B)/(F(T-B)) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**(TODO: need an image to show this transform!!)**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26419" PostHistoryTypeId="2" PostId="9600" RevisionGUID="d4a2f4e2-3019-40f9-981b-51dfa1b300d8" CreationDate="2020-02-22T01:00:29.017" UserId="7656" Text="I'm curious if anyone has any insight into how one might procedurally generate 4D objects, as showcased in Miegakure (or the developer's other game, [4D Toys][1] ).&#xD;&#xA;&#xD;&#xA;I built a program a while back to do this, basically using &quot;shape definition&quot; files that I found (and subsequently processed) for the regular polychora like the hypercube, 120-cell, 600-cell etc. Example shape files can be found on [Paul Bourke's website][2]. &#xD;&#xA;&#xD;&#xA;Another way that I've recently discovered is, using a convex hull algorithm like Qhull to extract this information. You can first generate all of the vertices for your polytope (these are usually just even/odd permutations of certain 4-tuples). Then, you run Qhull to find how the vertices are connected to one another. The problem with this method is, it requires significant pre-processing, and the tetrahedral meshes that are generated aren't always very clean. &#xD;&#xA;&#xD;&#xA;In 4D Toys, the author(s) are able to build shapes like a &quot;hollowed out&quot; 120-cell, so I'm curious if they are approaching this problem from a different angle - perhaps, one that is more flexible than the aforementioned approaches.&#xD;&#xA;&#xD;&#xA;I'm curious if there are other ways of modeling and/or algorithmically generating shapes like those found in Miegakure that I haven't thought about? &#xD;&#xA;What are other ways of approaching this design challenge?&#xD;&#xA;&#xD;&#xA;Thanks in advance for any help or guidance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://4dtoys.com/&#xD;&#xA;  [2]: http://paulbourke.net/geometry/hyperspace/" ContentLicense="CC BY-SA 4.0" />
  <row Id="26420" PostHistoryTypeId="1" PostId="9600" RevisionGUID="d4a2f4e2-3019-40f9-981b-51dfa1b300d8" CreationDate="2020-02-22T01:00:29.017" UserId="7656" Text="Procedural Generation of 4D Shapes" ContentLicense="CC BY-SA 4.0" />
  <row Id="26421" PostHistoryTypeId="3" PostId="9600" RevisionGUID="d4a2f4e2-3019-40f9-981b-51dfa1b300d8" CreationDate="2020-02-22T01:00:29.017" UserId="7656" Text="|rendering|mathematics|computational-geometry|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26422" PostHistoryTypeId="2" PostId="9601" RevisionGUID="46b6283c-87d4-44a9-a3e1-c65f8b138d90" CreationDate="2020-02-23T07:51:54.750" UserId="8009" Text="#TL;DR: &#xD;&#xA;&#xD;&#xA;The view frustum **is** the NDC box.  It's just that NDC space is nonlinear because it occurs **after** the perspective divide by w.  The tops and sides of the frustum are *parallel* in NDC space. All lines that project to the viewpoint are parallel in NDC space.&#xD;&#xA;&#xD;&#xA;# Explanation:&#xD;&#xA;&#xD;&#xA;I don't like math.  I dislike sites that try to explain all this with math and matrices and boring stuff like that.  I prefer pictures.  So I'll try to explain it with mainly pictures and descriptions.  Unfortunately the one thing that I must refer to mathematically is the fact that we have to _divide by Z_ to transform 3D points to 2D points according to the perspective transformation.  But &quot;divide by Z&quot; is as mathematical as I'll get, I promise.&#xD;&#xA;&#xD;&#xA;### The spaces&#xD;&#xA;&#xD;&#xA;Recall the different spaces.  The View and Projection matrices are all linear transformations.  World Space, Camera Space, and Homogeneous Clip Space are all linear spaces.  The Normalized Device Coordinates are in a non-linear (projective) space and the Divide by w is a non-linear transformation.  We reinterpret these coordinates as screen coordinates and do a linear transform from NDC to viewport coordinates.&#xD;&#xA;&#xD;&#xA;The whole point of clip space is to keep the space linear and defer dividing by Z until the very end.  The denominator of the perspective transformation is kept as its own coordinate in linear space and called W (it's the divisor for the homogeneous coordinates).  At some point we can no longer defer this divide because we need screen coordinates so we must ultimately go from (X,Y,Z,W) to (X/W, Y/W, Z/W) and wind up in NDC space.  (Technically we go from homogeneous coordinates to 3-space.)  &#xD;&#xA;&#xD;&#xA;&gt; So I think this is the mathematical part of the answer to your question:  `(X,Y,Z,W) → (X/W, Y/W, Z/W)` is called the **Perspective Divide by W** and it's the operation you're looking for that maps from Clip space to NDC.  &#xD;&#xA;&#xD;&#xA;### The transformations&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;### Visualizing NDC&#xD;&#xA;&#xD;&#xA;I've always hated how people draw the frustum with straight lines and draw the NDC box with straight lines but never show what's going on in the interior.  It really betrays our understanding of the non-linearity of relationship between the two spaces.  So here's a better diagram to help visualize the non-linearity of NDC space after the perspective projection.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Imagine you stand where the person with the camera is and take a picture.  The red lines are the boundaries of what the camera can see.&#xD;&#xA;Some familiar properties:&#xD;&#xA;&#xD;&#xA; - All points along the top of the red frustum will be at the top of the camera image&#xD;&#xA; - All points along the bottom of the red frustum will be at the bottom of the camera image.&#xD;&#xA; - The side of the frustum closest to the camera (left of this diagram) is the near clipping plane&#xD;&#xA; - The side of the frustum farthest from the camera (right of this diagram) is the far clipping plane. &#xD;&#xA;&#xD;&#xA;The top part of the diagram is World / View / Clip clip space. They are all linear transforms of one another, so for this diagram they are all basically the same.&#xD;&#xA;&#xD;&#xA;The bottom part of the diagram is Normalized Device Coordinate space. In NDC space the top and bottom of that frustum are _parallel_.  Notice the frustum in Clip space became a rectangle in NDC space.  Because the near clipping plane and the far clipping plane both become the same size as the camera image (camera sensor / camera frame).&#xD;&#xA;&#xD;&#xA;Note that any line that passes through the viewpoint is parallel to the top and bottom of this frustum in NDC space -- the magenta line is an example of this.   Notice that the magenta line passes just over the roof of the first (near) car and just over the back tire of the yellow (far) car.  Yet in NDC space, this line is parallel to the top of the frustum and the bottom of the frustum.  All the points along that magenta line will have the same coordinates in the final camera image (will appear at the same point on the screen in your rendering).  Cool, right?&#xD;&#xA;&#xD;&#xA;The frustum becomes a box in NDC space, which, I'll admit, is deceptively linear-seeming.  But you can tell the NDC space is non-linear (has that &quot;divides by Z&quot; property) because the lines of the sidewalk (which are parallel in world space or view/camera space) are not parallel in NDC space.  They follow that characteristic 1/x style curve in the diagram.&#xD;&#xA;&#xD;&#xA;In the diagram, for some distance away from the camera, everything is proportionally the same distance away from the top and bottom of the camera frustum in both Clip space, and NDC.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qJyXv.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zaLzI.png&#xD;&#xA;&#xD;&#xA;### Summary &#xD;&#xA;&#xD;&#xA;Hopefully this is a useful visual explanation of how to get between World / View / Clip space and NDC.  This is intended to supplement the mathematical descriptions you've already been given, not replace them.  Hopefully this gives you a visual with which you can ground your understanding of the non-linearity of projective transformations.&#xD;&#xA;&#xD;&#xA;Just remember:&#xD;&#xA;&#xD;&#xA; - That although all the camera boundaries (red lines in the diagram) match between&#xD;&#xA;   World space and NDC, it's a **frustum in World space** and a **rectangle in NDC space**.  (So _yes_, the corners of the view frustum *are* the corners of the NDC &quot;cube&quot;)&#xD;&#xA; - That straight lines (that run closer or farther to the camera and don't pass through the viewpoint) like the edges of the sidewalk are **straight in World space** but **may be curved in NDC space**. :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26425" PostHistoryTypeId="5" PostId="9596" RevisionGUID="3f5db89e-a2ce-450d-b1c8-2b7faa5bcfec" CreationDate="2020-02-23T16:18:22.737" UserId="9254" Comment="added 5 characters in body" Text="Let $W_{\text e}$ denote the camera sensor responsivity (i.e. importance) and $h_j$ and $W_{\text e}^{(j)}$ denote the  image reconstruction filter and sensor response associated with the $j$th pixel, respectively, i.e. $$W_{\text e}^{(j)}=h_jW_{\text e}.\tag1$$ The measurement of the $j$th pixel is given by \begin{equation}\begin{split}\Phi_j&amp;:=\sigma_M({\rm d}x_0)\int\sigma_M({\rm d}x_1)g(x_0\leftrightarrow x_1)W_{\text e}^{(j)}(x_1\to x_0)L_{\text o}(x_1\to x_0)\\&amp;=\int\lambda({\rm d}x)h_j(x_1\to x_0)f(x),\end{split}\tag2\end{equation} where $g$ denotes the geometry term, $\lambda$ is the infinite-product area measure on the path space and $f$ is the measurement contribution function, i.e. $$f(x)=g(x_0\leftrightarrow x_1)W_{\text e}(x_1\to x_0)\prod_{i=2}^kg(x_{i-1}\leftrightarrow x_i)f_{\text s}(x_i\to x_{i-1}\to x_{i-2})L_{\text e}(x_k\to x_{k-1}),\tag3$$ if $x$ is a path of length $k\in\mathbb N$.&#xD;&#xA;&#xD;&#xA;&gt; Usually, in the context of Metropolis Light Transport, the scalar contribution function $p$ is defined to be the luminance of $f$. So, by definition, $p(x)=0$ whenever $(x_0,x_1)$ doesn't belong to $$B:=\left\{(x_0,x_1):W_{\text e}(x_1\to x_0)\ne 0\right\}.$$ Now let $$B_j:=\left\{(x_0,x_1):W_{\text e}^{(j)}(x_1\to x_0)\ne 0\right\}.$$ We clearly have $$B=\bigcup_jB_j.\tag4$$ However, in light of the way samples are splat to image (see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#fragment-Splatbothcurrentandproposedsamplestomonofilm-0 or https://pdfs.semanticscholar.org/a386/55316ee7f438ba115b38e8d0b1410c691a26.pdf and [my other question](https://computergraphics.stackexchange.com/q/9589/9254)), it seems like it is assumed that the union in $(4)$ is disjoint. Is this really guaranteed to be the case?&#xD;&#xA;&#xD;&#xA;Taking a look in Section 2.6.4, on page 51, of [this PhD thesis](https://backend.orbit.dtu.dk/ws/portalfiles/portal/51112612/phd240_awk_vers2.pdf), this seems at least to be the case when the camera is a pinhole camera. The authors write: $W_{\text e}^{(j)}$ *is non-zero only for the set of directions within the pyramid formed by the pinhole and the four corners of the corresponding pixel* $j$.&#xD;&#xA;&#xD;&#xA;This seems to indicate that (at least for the pinhole camera) the &quot;support&quot; of $W_{\text e}^{(j)}$ is limited to the image rectangle region occupied by the $j$th pixel. But is this really true for *any* filter $h_j$ or only for a special one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26430" PostHistoryTypeId="2" PostId="9604" RevisionGUID="05b827f6-1f70-4236-a71d-94111daf0520" CreationDate="2020-02-24T07:30:47.797" UserId="10769" Text="This is a C++ implementation. Slab is the space between a pair of parallel planes.Test if ray R(t) = p + t * d intersect against bounding box bb.&#xD;&#xA;&#xD;&#xA;    bool IntersectRayBB( const double* p, const double* d, const BoundingBox&amp; bb, double&amp; tmin, double* q )&#xD;&#xA;    {&#xD;&#xA;    	double tolerance = 1e-9;&#xD;&#xA;    	tmin = 0.0;&#xD;&#xA;    	double tmax = FLOAT32_MAX; // Set to max distance ray can travel&#xD;&#xA;    	for( int i = 0; i &lt; 3; i++ )&#xD;&#xA;    	{&#xD;&#xA;    		if( Abs( d[i] ) &lt; tolerance )&#xD;&#xA;    		{&#xD;&#xA;    			// Ray is parallel to slab. No hit if origin not within slab.&#xD;&#xA;    			if( p[i] &lt; bb.min[i] || p[i] &gt; bb.max[i] )&#xD;&#xA;    				return false;&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			// Compute intersection t value of ray within near and far plane of slab&#xD;&#xA;    			double denom = 1.0 / d[i];&#xD;&#xA;    			double t1 = ( bb.min[i] - p[i] ) * denom;&#xD;&#xA;    			double t2 = ( bb.max[i] - p[i] ) * denom;&#xD;&#xA;    			// Make t1 be intersection with near plane, t2 with far plane&#xD;&#xA;    			if( t1 &gt; t2 )&#xD;&#xA;    				std::Swap( t1, t2 );&#xD;&#xA;    			// Compute the intersection of slab intersection intervals&#xD;&#xA;    			if( t1 &gt; tmin )&#xD;&#xA;    				tmin = t1;&#xD;&#xA;    			if( t2 &gt; tmax )&#xD;&#xA;    				tmax = t2;&#xD;&#xA;    			// Exit with no collision as soon as slab intersection becomes empty&#xD;&#xA;    			if( tmin &gt; tmax )&#xD;&#xA;    				return false;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	//Ray intersects all 3 slabs. Return point (q) and intersesction t value (tmin)&#xD;&#xA;    	q = p + d * tmin;&#xD;&#xA;    	return true;&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="26432" PostHistoryTypeId="5" PostId="8504" RevisionGUID="cc3d2365-d410-4396-94b5-a083e286058f" CreationDate="2020-02-24T08:00:38.243" UserId="9881" Comment="added 19 characters in body" Text="GPU friendly&#xD;&#xA;-&#xD;&#xA;&#xD;&#xA;**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{1m}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: Below we introduce formulas which includes distance $d$ between eye and viewport however this value will be reduced during ray $r_{ij}$ normalization (so you might as well accept that $d=1$ and remove it from calculations).&#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $q_x,q_y$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{1m} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{1m} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [HERE][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{1m}$. Wiki [here][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)#Calculate_rays_for_rectangular_viewport" ContentLicense="CC BY-SA 4.0" />
  <row Id="26433" PostHistoryTypeId="2" PostId="9606" RevisionGUID="54fe4828-b484-4ef6-bcb3-84811db78e08" CreationDate="2020-02-24T12:16:18.060" UserId="6046" Text="I'm trying to implement a simple BDPT without MIS as described in Lafortune's paper. I've used the weighting scheme defined in the paper in which they suggest that the weight be based on the surface specularity i.e. specular surfaces should add more weight to continue following the eye path rather than connect with the light path (which makes sense since the eye path is based on the current surface BRDF sampling).&#xD;&#xA;&#xD;&#xA;I shoot rays from the light source and the camera a fixed number of times. Each bounce stores the Hit Information and the PDF of the next ray generated. The light path can easily be inverted to get the directions similar to the eye path and by connecting both the paths and using the weighting scheme we can use the simple path tracer algorithm to calculate the total radiance.&#xD;&#xA;&#xD;&#xA;There are only 2 things that are different from what happens in a normal path tracer.&#xD;&#xA;&#xD;&#xA;1) First is the determinstic ray step i.e. the connection of each eye path vertex with the light vertex. This ray is not sampled from a PDF but instead shot deterministically. What should I use the value for the PDF for this step? Do I need to inverse sample the determinstic ray direction from the eye vertex BRDF PDF to get the probability? Or perhaps from the light vertex?&#xD;&#xA;&#xD;&#xA;2) The first ray shot from the light has its own PDF unlike in the normal path tracer where light is found explicitly using Direct Light Sampling. How can I incorporate this factor when I have path tracer that uses Next Event Estimation and Direct Light Sampling? I suppose I can fallback to the naive algorithm (no NEE or explicit Direct Light Sampling) since I already have pin pointed the light source from the light path. Just wanted clarification regarding this.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="26434" PostHistoryTypeId="1" PostId="9606" RevisionGUID="54fe4828-b484-4ef6-bcb3-84811db78e08" CreationDate="2020-02-24T12:16:18.060" UserId="6046" Text="BDPT - How to handle deterministic ray PDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26435" PostHistoryTypeId="3" PostId="9606" RevisionGUID="54fe4828-b484-4ef6-bcb3-84811db78e08" CreationDate="2020-02-24T12:16:18.060" UserId="6046" Text="|rendering|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26436" PostHistoryTypeId="2" PostId="9607" RevisionGUID="488c19f4-013d-4183-bee6-3cfd1ba5e293" CreationDate="2020-02-24T12:34:48.780" UserId="11939" Text="I am currently studying for a computer graphics exam and on the slides about bilinear interpolation it is said that it is in reality quadratic interpolation. &#xD;&#xA;&#xD;&#xA;An (on the slides) unanswered question then asks what interpolation on a 2D texture would be linear, but I can't really think of a way that is not cheating like going nearest neigbour in one dimension. Did I miss something or is it a trick question?&#xD;&#xA;&#xD;&#xA;Thank you very much :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26437" PostHistoryTypeId="1" PostId="9607" RevisionGUID="488c19f4-013d-4183-bee6-3cfd1ba5e293" CreationDate="2020-02-24T12:34:48.780" UserId="11939" Text="Is linear interpolation in a 2D texture possible (not quadratic like bilinear interpolation)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26438" PostHistoryTypeId="3" PostId="9607" RevisionGUID="488c19f4-013d-4183-bee6-3cfd1ba5e293" CreationDate="2020-02-24T12:34:48.780" UserId="11939" Text="|texture|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26442" PostHistoryTypeId="5" PostId="258" RevisionGUID="b56aa96a-0aed-43b1-b59b-a510314816e1" CreationDate="2020-02-25T08:43:59.617" UserId="209" Comment="added 121 characters in body" Text="&gt; If I did two Gaussian blurs of size N, would that be the same mathematically as doing one Gaussian blur of size 2N?&#xD;&#xA;&#xD;&#xA;Almost. Applying two Gaussian blurs *is* equivalent to doing one Gaussian blur, but with a slightly different size calculation.&#xD;&#xA;&#xD;&#xA;Applying a Gaussian blur to an image means doing a [convolution](https://en.wikipedia.org/wiki/Convolution) of the Gaussian with the image. Convolution is associative: Applying two Gaussian blurs to an image is equivalent to convolving the two Gaussians with each other, and convolving the resulting function with the image.&#xD;&#xA;&#xD;&#xA;As it happens, the convolution of two Gaussians with each other is another Gaussian, whose variance is the sum of variances of the two original Gaussians. A Gaussian of N pixel width has variance $N^2$; applying it twice is equivalent to a Gaussian with variance $2\cdot N^2$, which corresponds to a width of $\sqrt{2}\cdot N$ pixels.&#xD;&#xA;&#xD;&#xA;In the same vein, applying a Gaussian of width $2\cdot N$ is equivalent to applying a Gaussian of width $N$ four times." ContentLicense="CC BY-SA 4.0" />
  <row Id="26443" PostHistoryTypeId="2" PostId="9609" RevisionGUID="ccfee15a-6052-4e6b-a37b-3fa8a1701532" CreationDate="2020-02-25T11:25:23.140" UserId="9254" Text="Say we have a [image reconstruction filter](http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Image_Reconstruction.html) $h:R\to\mathbb R$ defined on the raster space $[0,w]\times[0,h]$, where $w,h\in\mathbb N$ define the width and height of the image plane in pixels, respectively.&#xD;&#xA;&#xD;&#xA;&gt; How is this $h$ related to the image reconstruction filter $\tilde h$ defined on the path space occuring in the [path integral formula](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#ApplicationtoRendering) for the measurement of a pixel?&#xD;&#xA;&#xD;&#xA;Asked differently: How is $\tilde h$ defined in terms of $h$?&#xD;&#xA;&#xD;&#xA;Since $\tilde h$ only depends on the first two components of a path, we may clearly assume that $\tilde h$ is a function on $M^2\to\mathbb R$, where $M$ denotes the scene geometry. For simplicity, assume a pinhole camera with eye $x_0$ so that $\tilde h$ is a function $M\to\mathbb R$. I guess we may likewise consider it as a function of directions, i.e. as a function on the unit 2-sphere $S^2:=\{\omega\in\mathbb R^3:|\omega|=1\}$ or on the hemisphere $H^2:=\{\omega\in S^2:\omega_3&gt;0\}$, corresponding to the front-facing directions (assuming camera space), if that's easier." ContentLicense="CC BY-SA 4.0" />
  <row Id="26444" PostHistoryTypeId="1" PostId="9609" RevisionGUID="ccfee15a-6052-4e6b-a37b-3fa8a1701532" CreationDate="2020-02-25T11:25:23.140" UserId="9254" Text="How is the image reconstruction filter on the path space defined in terms of the filter on the raster space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26445" PostHistoryTypeId="3" PostId="9609" RevisionGUID="ccfee15a-6052-4e6b-a37b-3fa8a1701532" CreationDate="2020-02-25T11:25:23.140" UserId="9254" Text="|raytracing|pathtracing|physically-based|global-illumination|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26446" PostHistoryTypeId="5" PostId="9609" RevisionGUID="f26852ed-fc0c-4996-b8ae-3196ae336328" CreationDate="2020-02-25T13:52:13.093" UserId="9254" Comment="added 1649 characters in body" Text="Say we have a [image reconstruction filter](http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Image_Reconstruction.html) $h:R\to\mathbb R$ defined on the raster space $[0,w]\times[0,h]$, where $w,h\in\mathbb N$ define the width and height of the image plane in pixels, respectively.&#xD;&#xA;&#xD;&#xA;&gt; How is this $h$ related to the image reconstruction filter $\tilde h$ defined on the path space occuring in the [path integral formula](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#ApplicationtoRendering) for the measurement of a pixel?&#xD;&#xA;&#xD;&#xA;Asked differently: How is $\tilde h$ defined in terms of $h$?&#xD;&#xA;&#xD;&#xA;Since $\tilde h$ only depends on the first two components of a path, we may clearly assume that $\tilde h$ is a function on $M^2\to\mathbb R$, where $M$ denotes the scene geometry. For simplicity, assume a pinhole camera with eye $x_0$ so that $\tilde h$ is a function $M\to\mathbb R$. I guess we may likewise consider it as a function of directions, i.e. as a function on the unit 2-sphere $S^2:=\{\omega\in\mathbb R^3:|\omega|=1\}$ or on the hemisphere $H^2:=\{\omega\in S^2:\omega_3&gt;0\}$, corresponding to the front-facing directions (assuming camera space), if that's easier.&#xD;&#xA;&#xD;&#xA;**EDIT**: I define the path space $(E,\mathcal E,\lambda)$ in the same way as Veach did in his seminal work: $$E_k:=M^{\{0,\:\ldots\:,\:k\}},\mathcal E_k:=\mathcal B(M)^{\otimes\{0,\:\ldots\:,\:k\}},\lambda_k:=\sigma_M^{\otimes\{0,\:\ldots\:,\:k\}}$$ for $k\in\mathbb N,$ where $\sigma_M$ denotes the surface measure on $M$, and $$E:=\bigcup_{k\in\mathbb N}E_k,\mathcal E:=\mathcal B(E),$$$$\lambda(B):=\sum_{k\in\mathbb N}\lambda_k(B\cap E_k)\;\;\;\text{for }B\in\mathcal E.$$ But, as noted before, we can restrict our attention to $(E_2,\mathcal E_2,\lambda_2)$ and, assuming a pinhole camera with the eye at the origin $0$, we're simply actually only dealing with $(M,\mathcal B(M),\sigma_M)$. Denoting the surface measure on the unit sphere by $\sigma_{S^2}$, I'll define the projected solid angle kernel to be $$\sigma_M^\perp(x,B):=\int_B\sigma_{S^2}({\rm d}\omega)|\langle\nu_M(x),\omega\rangle|\;\;\;\text{for }(x,B)\in M\times\mathcal B(S^2),$$ where $\langle\nu_M$ denotes the unit normal field on $M$. $\sigma_{S^2}$ and $\sigma_M$ are related by $$\int\sigma_M^\perp(x,{\rm d}\omega)f(\omega)=\int\sigma_M({\rm d}y)g(x\leftrightarrow y)f(\omega_{x\to y})\tag1$$ for all $x\in M$ and Borel measurable $f:S^2\to[0,\infty)$, where $$g(x\leftrightarrow y):=\left.\begin{cases}\displaystyle\frac{\left|\left\langle\nu_M(x),\omega_{x\to y}\right\rangle\right|\left|\left\langle\nu_M(y),\omega_{y\to x}\right\rangle\right|}{|x-y|^2}&amp;\text{, if }y\text{ is visible from }x\\0&amp;\text{,otherwise}\end{cases}\right\}$$ for $x,y\in M$ and $\omega_{x\to y}:=\pi(y-x)$, where $\pi$ denotes the projection of $\mathbb R^3\setminus\{0\}$ onto $S^2$." ContentLicense="CC BY-SA 4.0" />
  <row Id="26447" PostHistoryTypeId="5" PostId="9609" RevisionGUID="8976abce-ecc7-4adc-8430-fb080905e678" CreationDate="2020-02-25T14:08:58.373" UserId="9254" Comment="added 542 characters in body" Text="Say we have a [image reconstruction filter](http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Image_Reconstruction.html) $h:R\to\mathbb R$ defined on the raster space $[0,w]\times[0,h]$, where $w,h\in\mathbb N$ define the width and height of the image plane in pixels, respectively.&#xD;&#xA;&#xD;&#xA;&gt; How is this $h$ related to the image reconstruction filter $\tilde h$ defined on the path space occuring in the [path integral formula](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#ApplicationtoRendering) for the measurement of a pixel?&#xD;&#xA;&#xD;&#xA;Asked differently: How is $\tilde h$ defined in terms of $h$?&#xD;&#xA;&#xD;&#xA;Since $\tilde h$ only depends on the first two components of a path, we may clearly assume that $\tilde h$ is a function on $M^2\to\mathbb R$, where $M$ denotes the scene geometry. For simplicity, assume a pinhole camera with eye $x_0$ so that $\tilde h$ is a function $M\to\mathbb R$. I guess we may likewise consider it as a function of directions, i.e. as a function on the unit 2-sphere $S^2:=\{\omega\in\mathbb R^3:|\omega|=1\}$ or on the hemisphere $H^2:=\{\omega\in S^2:\omega_3&gt;0\}$, corresponding to the front-facing directions (assuming camera space), if that's easier.&#xD;&#xA;&#xD;&#xA;**EDIT 1**: I define the path space $(E,\mathcal E,\lambda)$ in the same way as Veach did in his seminal work: $$E_k:=M^{\{0,\:\ldots\:,\:k\}},\mathcal E_k:=\mathcal B(M)^{\otimes\{0,\:\ldots\:,\:k\}},\lambda_k:=\sigma_M^{\otimes\{0,\:\ldots\:,\:k\}}$$ for $k\in\mathbb N,$ where $\sigma_M$ denotes the surface measure on $M$, and $$E:=\bigcup_{k\in\mathbb N}E_k,\mathcal E:=\mathcal B(E),$$$$\lambda(B):=\sum_{k\in\mathbb N}\lambda_k(B\cap E_k)\;\;\;\text{for }B\in\mathcal E.$$ But, as noted before, we can restrict our attention to $(E_2,\mathcal E_2,\lambda_2)$ and, assuming a pinhole camera with the eye at the origin $0$, we're simply actually only dealing with $(M,\mathcal B(M),\sigma_M)$. Denoting the surface measure on the unit sphere by $\sigma_{S^2}$, I'll define the projected solid angle kernel to be $$\sigma_M^\perp(x,B):=\int_B\sigma_{S^2}({\rm d}\omega)|\langle\nu_M(x),\omega\rangle|\;\;\;\text{for }(x,B)\in M\times\mathcal B(S^2),$$ where $\langle\nu_M$ denotes the unit normal field on $M$. $\sigma_{S^2}$ and $\sigma_M$ are related by $$\int\sigma_M^\perp(x,{\rm d}\omega)f(\omega)=\int\sigma_M({\rm d}y)g(x\leftrightarrow y)f(\omega_{x\to y})\tag1$$ for all $x\in M$ and Borel measurable $f:S^2\to[0,\infty)$, where $$g(x\leftrightarrow y):=\left.\begin{cases}\displaystyle\frac{\left|\left\langle\nu_M(x),\omega_{x\to y}\right\rangle\right|\left|\left\langle\nu_M(y),\omega_{y\to x}\right\rangle\right|}{|x-y|^2}&amp;\text{, if }y\text{ is visible from }x\\0&amp;\text{,otherwise}\end{cases}\right\}$$ for $x,y\in M$ and $\omega_{x\to y}:=\pi(y-x)$, where $\pi$ denotes the projection of $\mathbb R^3\setminus\{0\}$ onto $S^2$.&#xD;&#xA;&#xD;&#xA;**EDIT 2**: The image plane in camera space is of the form $$I:=\left[-\frac w2,\frac w2\right)\times\left[-\frac h2,\frac h2\right)\times\{1\},$$ where $w,h&gt;0$ are the width and height (in camera space) of the image plane, respectively. It's easy to see that a ray starting at $0$ (the camera position in camera space) with direction $\omega\in S^2$ has an intersection with the infinite extension $\mathbb R^2\times\{1\}$ of $I$ if and only if $\omega\in H^2$ and in that case the intersection is occurring at $\frac\omega{\omega_3}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="26448" PostHistoryTypeId="5" PostId="9609" RevisionGUID="08cd2ec3-b7fb-4712-9762-378822289dc5" CreationDate="2020-02-25T14:19:31.370" UserId="9254" Comment="added 9 characters in body" Text="Say we have a [image reconstruction filter](http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Image_Reconstruction.html) $h:R\to\mathbb R$ defined on the raster space $[0,w]\times[0,h]$, where $w,h\in\mathbb N$ define the width and height of the image plane in pixels, respectively.&#xD;&#xA;&#xD;&#xA;&gt; How is this $h$ related to the image reconstruction filter $\tilde h$ defined on the path space occuring in the [path integral formula](http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html#ApplicationtoRendering) for the measurement of a pixel?&#xD;&#xA;&#xD;&#xA;Asked differently: How is $\tilde h$ defined in terms of $h$?&#xD;&#xA;&#xD;&#xA;Since $\tilde h$ only depends on the first two components of a path, we may clearly assume that $\tilde h$ is a function on $M^2\to\mathbb R$, where $M$ denotes the scene geometry. For simplicity, assume a pinhole camera with eye $x_0$ so that $\tilde h$ is a function $M\to\mathbb R$. I guess we may likewise consider it as a function of directions, i.e. as a function on the unit 2-sphere $S^2:=\{\omega\in\mathbb R^3:|\omega|=1\}$ or on the hemisphere $H^2:=\{\omega\in S^2:\omega_3&gt;0\}$, corresponding to the front-facing directions (assuming camera space), if that's easier.&#xD;&#xA;&#xD;&#xA;**EDIT 1**: I define the path space $(E,\mathcal E,\lambda)$ in the same way as Veach did in his seminal work: $$E_k:=M^{\{0,\:\ldots\:,\:k\}},\mathcal E_k:=\mathcal B(M)^{\otimes\{0,\:\ldots\:,\:k\}},\lambda_k:=\sigma_M^{\otimes\{0,\:\ldots\:,\:k\}}$$ for $k\in\mathbb N,$ where $\sigma_M$ denotes the surface measure on $M$, and $$E:=\bigcup_{k\in\mathbb N}E_k,\mathcal E:=\mathcal B(E),$$$$\lambda(B):=\sum_{k\in\mathbb N}\lambda_k(B\cap E_k)\;\;\;\text{for }B\in\mathcal E.$$ But, as noted before, we can restrict our attention to $(E_2,\mathcal E_2,\lambda_2)$ and, assuming a pinhole camera with the eye at the origin $0$, we're simply actually only dealing with $(M,\mathcal B(M),\sigma_M)$. Denoting the surface measure on the unit sphere by $\sigma_{S^2}$, I'll define the projected solid angle kernel to be $$\sigma_M^\perp(x,B):=\int_B\sigma_{S^2}({\rm d}\omega)|\langle\nu_M(x),\omega\rangle|\;\;\;\text{for }(x,B)\in M\times\mathcal B(S^2),$$ where $\langle\nu_M$ denotes the unit normal field on $M$. $\sigma_{S^2}$ and $\sigma_M$ are related by $$\int\sigma_M^\perp(x,{\rm d}\omega)f(\omega)=\int\sigma_M({\rm d}y)g(x\leftrightarrow y)f(\omega_{x\to y})\tag1$$ for all $x\in M$ and Borel measurable $f:S^2\to[0,\infty)$, where $$g(x\leftrightarrow y):=\left.\begin{cases}\displaystyle\frac{\left|\left\langle\nu_M(x),\omega_{x\to y}\right\rangle\right|\left|\left\langle\nu_M(y),\omega_{y\to x}\right\rangle\right|}{|x-y|^2}&amp;\text{, if }y\text{ is visible from }x\\0&amp;\text{,otherwise}\end{cases}\right\}$$ for $x,y\in M$ and $\omega_{x\to y}:=\pi(y-x)$, where $\pi$ denotes the projection of $\mathbb R^3\setminus\{0\}$ onto $S^2$.&#xD;&#xA;&#xD;&#xA;**EDIT 2**: The image plane at $z=1$ in camera space is of the form $$I:=\left[-\frac w2,\frac w2\right)\times\left[-\frac h2,\frac h2\right)\times\{1\},$$ where $w,h&gt;0$ are the width and height (in camera space) of the image plane, respectively. It's easy to see that a ray starting at $0$ (the camera position in camera space) with direction $\omega\in S^2$ has an intersection with the infinite extension $\mathbb R^2\times\{1\}$ of $I$ if and only if $\omega\in H^2$ and in that case the intersection is occurring at $\frac\omega{\omega_3}$." ContentLicense="CC BY-SA 4.0" />
  <row Id="26449" PostHistoryTypeId="2" PostId="9610" RevisionGUID="eb0a69ab-fcfb-4c11-b3f8-dae032cc1c0f" CreationDate="2020-02-25T16:53:04.230" UserId="11282" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary cylinder (defined by startpoint, endpoint, and radius)&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26450" PostHistoryTypeId="1" PostId="9610" RevisionGUID="eb0a69ab-fcfb-4c11-b3f8-dae032cc1c0f" CreationDate="2020-02-25T16:53:04.230" UserId="11282" Text="Looking for a cylinder / axis-aligned box intersection test" ContentLicense="CC BY-SA 4.0" />
  <row Id="26451" PostHistoryTypeId="3" PostId="9610" RevisionGUID="eb0a69ab-fcfb-4c11-b3f8-dae032cc1c0f" CreationDate="2020-02-25T16:53:04.230" UserId="11282" Text="|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26452" PostHistoryTypeId="5" PostId="9610" RevisionGUID="ecddbce9-ebc3-4048-a1ad-ee375d75a1d1" CreationDate="2020-02-25T17:06:52.293" UserId="11282" Comment="added 218 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary cylinder (defined by startpoint, endpoint, and radius)&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it." ContentLicense="CC BY-SA 4.0" />
  <row Id="26453" PostHistoryTypeId="5" PostId="9610" RevisionGUID="65850e1d-9708-4a18-9370-87a6e85d5832" CreationDate="2020-02-25T17:18:11.263" UserId="11282" Comment="added 67 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary cylinder (defined by startpoint, endpoint, and radius)&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic." ContentLicense="CC BY-SA 4.0" />
  <row Id="26454" PostHistoryTypeId="5" PostId="9610" RevisionGUID="d39a0852-3e9f-40c2-a2da-e381c284e870" CreationDate="2020-02-25T17:35:57.453" UserId="11282" Comment="added 45 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary cylinder (defined by startpoint, endpoint, and radius). An **Infinite cylinder is acceptable as well**, as long as it passes through those points and has the same radius.&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic." ContentLicense="CC BY-SA 4.0" />
  <row Id="26455" PostHistoryTypeId="2" PostId="9611" RevisionGUID="48f2cba2-225c-4044-85a1-0445927084cf" CreationDate="2020-02-25T17:46:41.723" UserId="10096" Text="The canonical equation of an elliptic cylinder aligned with the $Z$ axis and having center $(c_x, c_y, c_z)$ is given as:&#xD;&#xA;$$\frac{(x-c_x)^2}{a^2} + \frac{(y-c_y)^2}{b^2} = 1$$&#xD;&#xA;The parametric form of a ray is given as:&#xD;&#xA;$$\vec{r}(t) = \vec{o} + t\vec{d}$$&#xD;&#xA;Then by plugging r into the canonical equation one gets:&#xD;&#xA;$$\frac{(o_x + td_x -c_x)^2}{a^2} + \frac{(o_y + td_y -c_y)^2}{b^2} = 1$$&#xD;&#xA;Solve the quadratic equation for $t$ and you have your intersection. If the discriminant is negative then there is no intersection. To get a rotated cylinder, the easiest way is to apply the inverse rotation to the ray (the equation may be modified however too).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26456" PostHistoryTypeId="12" PostId="9611" RevisionGUID="162e7af7-fbe2-456a-b266-3827362f0058" CreationDate="2020-02-25T17:47:20.223" UserId="10096" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:10096,&quot;DisplayName&quot;:&quot;lightxbulb&quot;}]}" />
  <row Id="26457" PostHistoryTypeId="5" PostId="9610" RevisionGUID="34ca213c-0b0e-467f-94c7-12627fcc03bc" CreationDate="2020-02-25T21:40:53.560" UserId="11282" Comment="added 88 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary cylinder (defined by startpoint, endpoint, and radius). An **Infinite cylinder is acceptable as well**, as long as it passes through those points and has the same radius.&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;* The box being inside the volume of the cylinder should also count as an intersection&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic." ContentLicense="CC BY-SA 4.0" />
  <row Id="26460" PostHistoryTypeId="5" PostId="9611" RevisionGUID="6031e2e2-e0f4-45c5-99c8-35478be78f5d" CreationDate="2020-02-26T09:44:06.517" UserId="10096" Comment="added 519 characters in body" Text="As mentioned the problem of cylinder box intersection reduces to the problem of line-parallelogram intersection, and line segment-cylinder intersection.&#xD;&#xA;&#xD;&#xA;I will assume that you know how to intersect a line and a parallelogram. Here is a sketch for solving the line segment-cylinder intersection:&#xD;&#xA;&#xD;&#xA;The canonical equation of an elliptic cylinder aligned with the $Z$ axis and having center $(c_x, c_y, c_z)$ is given as:&#xD;&#xA;$$\frac{(x-c_x)^2}{a^2} + \frac{(y-c_y)^2}{b^2} = 1$$&#xD;&#xA;The parametric form of a ray is given as:&#xD;&#xA;$$\vec{r}(t) = \vec{o} + t\vec{d}$$&#xD;&#xA;Then by plugging r into the canonical equation one gets:&#xD;&#xA;$$\frac{(o_x + td_x -c_x)^2}{a^2} + \frac{(o_y + td_y -c_y)^2}{b^2} = 1$$&#xD;&#xA;Solve the quadratic equation for $t$ and you have your intersection. If the discriminant is negative then there is no intersection. To get a rotated cylinder, the easiest way is to apply the inverse rotation to the ray (the equation may be modified however too). Note that for a line segment, you simply need to check whether $t \in [t_0, t_1]$, where $\vec{a} = \vec{o} + t_0\vec{d}$ is the first point of the line segment, and $\vec{b} = \vec{o} + t_1\vec{d}$ is the second one.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26461" PostHistoryTypeId="13" PostId="9611" RevisionGUID="5eab6d3c-dffa-4f9b-813a-88441e18fe42" CreationDate="2020-02-26T09:44:10.497" UserId="10096" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:10096,&quot;DisplayName&quot;:&quot;lightxbulb&quot;}]}" />
  <row Id="26464" PostHistoryTypeId="5" PostId="9583" RevisionGUID="d04fab82-4c4b-4075-b54c-c7fdce611cbe" CreationDate="2020-02-26T10:21:43.923" UserId="8009" Comment="Fixed weird 4th link with %20%20%20 which was supposed to be a link to [2]" Text="Now there has already been an answer [here in this stackexchange][1], but I don't understand certain aspects of it.  The author has [MORE DETAILED DESCRIPTION HERE(#1)][2] but the problem is he doesn't describe what the linear mapping is done or how is the frustum transformed into the bounding box, there's **NOWHERE IN THE WORLD** mentioned how these two subspaces overlap or one is transformed to the other, for example:  &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;Is this how these two spaces exist and after projecting the point from inside the view frustum to the near plane a linear mapping is done where the author says:  &#xD;&#xA;  &#xD;&#xA;&quot;Our input to the linear mapping is x=x_near, and our output is the x coordinate in NDC space y=x_ndc, whose range is [-1.0, 1.0]&quot; [from the above page][2]&#xD;&#xA;&#xD;&#xA;It looks as if he somehow connects a line from the frustum to the NDC space but not clear on how it is done e.g. does he connect the top left vertex to the top left front vertex of the NDC cube?   Are the four corners of the frustum mapped to four corners of the cube?&#xD;&#xA;  &#xD;&#xA;As much I'd like to make this answer self contained, I don't know if I can copy his materials in here, please be kind enough to check the link out and help me understand this. Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6254/how-to-derive-a-perspective-projection-matrix-from-its-components&#xD;&#xA;  [2]: https://dovo329.github.io/DeriveOpenGLPerspectiveProjectionMatrix/&#xD;&#xA;  [3]: https://i.stack.imgur.com/02bgu.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26465" PostHistoryTypeId="24" PostId="9583" RevisionGUID="d04fab82-4c4b-4075-b54c-c7fdce611cbe" CreationDate="2020-02-26T10:21:43.923" Comment="Proposed by 8009 approved by 209, 6 edit id of 511" ContentLicense="CC BY-SA 4.0" />
  <row Id="26467" PostHistoryTypeId="2" PostId="9614" RevisionGUID="ace43b61-c588-4832-912e-3bd9ecc2608e" CreationDate="2020-02-26T19:50:06.933" UserId="7512" Text="I have a standard 3d camera/projection/model setup that renders rectangles with a WebGL shader. &#xD;&#xA;&#xD;&#xA;Users can zoom out and fly anywhere. &#xD;&#xA;&#xD;&#xA;I want to make sure that regardless of the scale, width of the rendered rectangles is a constant value (e.g. 2 pixels). &#xD;&#xA;&#xD;&#xA;What is the most efficient way to do so?&#xD;&#xA;&#xD;&#xA;This is very similar to SVG's non-scaling-stroke vector effect: https://www.w3.org/TR/SVGTiny12/painting.html#NonScalingStroke" ContentLicense="CC BY-SA 4.0" />
  <row Id="26468" PostHistoryTypeId="1" PostId="9614" RevisionGUID="ace43b61-c588-4832-912e-3bd9ecc2608e" CreationDate="2020-02-26T19:50:06.933" UserId="7512" Text="constant pixel width for any scale" ContentLicense="CC BY-SA 4.0" />
  <row Id="26469" PostHistoryTypeId="3" PostId="9614" RevisionGUID="ace43b61-c588-4832-912e-3bd9ecc2608e" CreationDate="2020-02-26T19:50:06.933" UserId="7512" Text="|rendering|3d|shader|glsl|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26470" PostHistoryTypeId="50" PostId="6085" RevisionGUID="88c6cb2a-84f9-4c60-8164-31860051eeac" CreationDate="2020-02-27T03:02:50.327" UserId="-1" />
  <row Id="26471" PostHistoryTypeId="50" PostId="6350" RevisionGUID="775dbc03-a104-4e4f-8433-7c9a53bf1ff0" CreationDate="2020-02-27T04:03:40.340" UserId="-1" />
  <row Id="26473" PostHistoryTypeId="50" PostId="8825" RevisionGUID="bd78b2a8-1e83-44fb-aeef-13fee54efbc5" CreationDate="2020-02-27T05:03:00.460" UserId="-1" />
  <row Id="26477" PostHistoryTypeId="5" PostId="9541" RevisionGUID="603cb44e-3b22-4730-ad29-f1c2926885d8" CreationDate="2020-02-27T11:35:18.773" UserId="11811" Comment="added 1262 characters in body" Text="Shoot me... After the fixes I posted above, I started debugging Mitsuba to see whether it does anything differently on a large scale. Of course it didn't; my code is completely correct, the dimness is due to this macro def:&#xD;&#xA;&#xD;&#xA;    #define EPSILON   1e-5&#xD;&#xA;&#xD;&#xA;This is used in divisions to avoid dividing with zero. Unfortunately, it accumulates to a large value during the calculations. Changing it to 1e-9 fixes everything:&#xD;&#xA;&#xD;&#xA;[![mis_final][1]][1]&#xD;&#xA;&#xD;&#xA;For future generations I leave the source code up (just remember to change this value).&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;I found another mistake in my calculations, but it isn't apparent in this scene. Microsurface-based BRDFs are usually sampled according to the microfacet normal distribution function (D(h, a), in this case GGX).&#xD;&#xA;&#xD;&#xA;Don't forget however, that you also have a shadowing-masking function (G(l, v, a)) which has to be evaluated according to the chosen microfacet distribution. This means that I can't just mix-and-match f.e. GGX sampling and the *Smith-Schlick* evaluation; I have to use the *Smith-GGX* solution:&#xD;&#xA;&#xD;&#xA;    float G_Smith_GGX(float ndotl, float ndotv, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float a = roughness * roughness;&#xD;&#xA;        float a2 = a * a;&#xD;&#xA;    &#xD;&#xA;        float lambda_l = sqrt(a2 + (1.0 - a2) * ndotl * ndotl);&#xD;&#xA;        float lambda_v = sqrt(a2 + (1.0 - a2) * ndotv * ndotv);&#xD;&#xA;    &#xD;&#xA;        return (2.0 * ndotl * ndotv) / (ndotv * lambda_l + ndotl * lambda_v);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Which explains the UE4 approach, as:&#xD;&#xA;&#xD;&#xA;    vec3 F = F_Schlick(F0, ldoth);&#xD;&#xA;    float G = G_Smith_GGX(ndotl, ndotv, roughness);&#xD;&#xA;    &#xD;&#xA;    // PDF = (D(h) * dot(n, h)) / (4 * dot(v, h))&#xD;&#xA;    return (F * G * vdoth) / (ndotv * ndoth + EPSILON);&#xD;&#xA;&#xD;&#xA;See [this article][2] for the derivation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/URn4F.jpg&#xD;&#xA;  [2]: https://schuttejoe.github.io/post/ggximportancesamplingpart1/" ContentLicense="CC BY-SA 4.0" />
  <row Id="26478" PostHistoryTypeId="5" PostId="9597" RevisionGUID="2a44e7dc-557f-4ce4-8450-4b4b6896b952" CreationDate="2020-02-27T14:03:41.227" UserId="5574" Comment="Second pass editing. Some LaTeX inlines. 'Code' blocks look ugly, but LaTeX for every simple equation... I need help to make it look good." Text="**Note: This is a work in progress - working on LaTeX and useful illustrations.**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;My derivation notes were based partially on the perspective projection matrix derivation in [`Computer Graphics: Principles and Practice (2nd Ed)`](https://www.amazon.com/Computer-Graphics-Principles-Practice-2nd/dp/0201848406). My understanding is that the 3rd edition takes a more contemporary approach with references to OpenGL and Direct3D. I haven't read this edition, and can't vouch for it.&#xD;&#xA;&#xD;&#xA;This derivation also assumes an understanding of homogeneous coordinates and the notion of a projective space. The wikipedia entry is concise, but lacks the intuition provided by a few good **2D** example illustrations. (If you're *really* keen, search for early articles on the subject by [Jim Blinn](http://www.jimblinn.com/)).&#xD;&#xA;&#xD;&#xA;First, we need to outline a few assertions and conventions:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- We always assume a ['right-handed' coordinate space](https://en.wikipedia.org/wiki/Right-hand_rule#Coordinates), unless otherwise stated. The 'eye' is at: `(0, 0, 0)`. `(+Z)` may be considered the direction pointing 'out' of the screen (or window / viewport), while `(X, Y)` are Cartesian coordinates, where: `(0, 0)` corresponds to the centre of that viewport.&#xD;&#xA;&#xD;&#xA;&lt;/br&gt;&#xD;&#xA;&#xD;&#xA;- The [**view frustum**](https://en.wikipedia.org/wiki/Viewing_frustum) has a near plane at: `Z = - N` and a far plane at: `Z = - F`, with normals in the `+Z` direction. The near plane: `Z = - N`, has `X: L &lt;= X &lt;= R`, and `Y: B &lt;= Y &lt;= T`, which will eventually map to a **3D viewport**. This frustum encapsulates all visible geometry. (Technically speaking, `R &lt; L`, `T &lt; B`, and `N &gt; F &gt; 0` are permitted by `glFrustum`. Arbitrary matrices are of course permitted in core profile OpenGL contexts.)&#xD;&#xA;&#xD;&#xA;&lt;/br&gt;&#xD;&#xA;&#xD;&#xA;- The mathematics will use what are somewhat misleadingly called 'row-major' matrices, but I insist on the use of column vectors when describing a system of transforms, i.e., the *column* vector is 'pre-multiplied' by the matrix: `v' = [M]v`. Disagree all you want - just know that you are sick and need help.&#xD;&#xA;&#xD;&#xA; In all seriousness, either convention can be made to work; it's just a matter of being aware of the conventions and sticking with a choice. The 'column-vector' convention is typically the one taught in linear algebra. We apply *successive* transforms: `[A]`, `[B]`, `[C]` to a vector: `v`, like we would apply functions: `C(B(A(v)))`, hence: `v' = [C][B][A]v`.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Any view frustum (camera) in space can be transformed by pre-multiplying the (homogeneous) coordinates by an 'orientation matrix'. That's beyond your question, but typically requires a general **PRP** (camera eye point), **VRP** (the centre of the 'near' projection plane), and the **VUP** point, which references a point defining 'up'. In effect, it's sufficient to form a orthonormal coordinate system. This is the view coordinate space **(VCS)**.&#xD;&#xA;&#xD;&#xA;The orthonormal basis, along with the **PRP** translation, can be used to construct an inverse transform that 'premultiplies' geometry to world coordinate space **(WCS)**. Again, you can save the concept of orthonormal basis / coordinate system transforms for a rainy day...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;We do not *assume* the view frustum is centred on the Z axis - although this is almost certainly the case for most projections. There are more exotic transforms (a mirror in a scene comes to mind); we'll concentrate on the general case.&#xD;&#xA;&#xD;&#xA;The direction of projection: $\small\\\mathbf{DOP}=\left[(R+L)/2,\: (T+B)/2,\: -N\right]\,^T$. The view frustum is typically symmetric about the Z axis s.t. `R = - L`, `T = - B`, yielding: $\small\\\mathbf{DOP}=\left[0,\: 0,\: -N\right]\,^T$.&#xD;&#xA;&#xD;&#xA;Of course, this is not *required*, so our first step in the perspective projection derivation is to apply a *shear* matrix that maps the $\small\\\mathbf{DOP}$ to the (negative) Z-axis:&#xD;&#xA;&#xD;&#xA;`(R + L) / 2 + shear.x (- N) = 0` =&gt; `shear.x = (R + L) / (2.N)`&lt;br/&gt;&#xD;&#xA;`(T + B) / 2 + shear.y (- N) = 0` =&gt; `shear.y = (T + B) / (2.N)`&#xD;&#xA;&#xD;&#xA;Consider the shear transformation applied to the frustum's near-clipping plane vertex coordinates:&#xD;&#xA;&#xD;&#xA;$\small\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;R \\ T \\ -N \\ 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;= \begin{pmatrix}&#xD;&#xA;(R-L)/2 \\ (T-B)/2 \\ -N \\ 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\:,$&#xD;&#xA;&#xD;&#xA;$\small\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;L \\ B \\ -N \\ 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;= \begin{pmatrix}&#xD;&#xA;(L-R)/2 \\ (B-T)/2 \\ -N \\1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Following this transform, the $\small\\\mathbf{DOP}$ is in direction of the `- Z` axis; specifically, the centre of the near view plane: $\small\left((R+L)/2,\: (T+B)/2,\: -N,\: 1\right)\,^T$ has been mapped to: $\small\left(0,\: 0,\: -N,\: 1\right)\,^T$.&#xD;&#xA;&#xD;&#xA;Now we want to scale the perspective projection transform such that the `R, L, T, B` planes of the frustum have have a unit gradient. The current gradients are `(R - L) / (2.N)` (right and left), and `(T - B) / (2.N)` (top and bottom). The symmetry is due to the previous shearing transform.&#xD;&#xA;&#xD;&#xA;`(R - L) / (2.N) * scale.x = 1` =&gt; `scale.x = 2.N / (R - L)`&lt;br/&gt;&#xD;&#xA;`(T - B) / (2.N) * scale.y = 1` =&gt; `scale.y = 2.N / (T - B)`&#xD;&#xA;&#xD;&#xA;Furthermore, we want to scale by `(1 / F)` s.t. the far clipping plane is mapped to: `Z = - 1`, while the unit slopes of the right, left, top, and bottom clipping planes are preserved. These scaling factors premultiply the perspective projection matrix:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\small\begin{pmatrix}&#xD;&#xA;2N/(F(R-L)) &amp; 0 &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 2N/(F(T-B)) &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 1 &amp; (T+B)/(2N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\:,$&#xD;&#xA;&#xD;&#xA;to yield:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\small\begin{pmatrix}&#xD;&#xA;2N/(F(R-L)) &amp; 0 &amp; (R+L)/(F(R-L)) &amp; 0 \\ &#xD;&#xA;0 &amp; 2N/(F(T-B)) &amp; (T+B)/(F(T-B)) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;This transform yields what may be considered *the normalized frustum*.&#xD;&#xA;&#xD;&#xA;**(TODO: need an image to show this transform!)**&#xD;&#xA;&#xD;&#xA;The vertices of near clipping plane are mapped to: $\small\left(\pm N/F,\: \pm N/F,\: -N/F,\: 1\right)\,^T$, while the vertices of the far-clipping plane are mapped to: $\small\left(\pm 1,\: \pm 1,\: -1,\: 1\right)\,^T$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**(TODO: perspective (projection) transform unification -&gt; CCS)** " ContentLicense="CC BY-SA 4.0" />
  <row Id="26479" PostHistoryTypeId="2" PostId="9616" RevisionGUID="3c574fa5-64ca-4aa9-9d84-d411d96c7382" CreationDate="2020-02-27T15:55:45.490" UserId="11282" Text="I am looking for a file format to output some 3D geometry. In my case, it only needs to handle very simple shapes - uniformly spaced and sized cubes at points in space. So far I've ended up just representing them as triangles or quads depending on what I can use. &#xD;&#xA;&#xD;&#xA;I've tried Binary STL format which is decently compact, but has no support for colors.&#xD;&#xA;&#xD;&#xA;Wavefront Object format (OBJ) and the material library (MTL) work well for color support, but there is no binary version as far as I know - making it very bulky. &#xD;&#xA;&#xD;&#xA;Is there a file format that:&#xD;&#xA;&#xD;&#xA;* Is compact in size&#xD;&#xA;* Has some way to support colors&#xD;&#xA;* Can be opened by software like 3D Viewer, Paint 3D, or other common tools?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26480" PostHistoryTypeId="1" PostId="9616" RevisionGUID="3c574fa5-64ca-4aa9-9d84-d411d96c7382" CreationDate="2020-02-27T15:55:45.490" UserId="11282" Text="Looking for a compact file format for outputting 3D geometry with color support" ContentLicense="CC BY-SA 4.0" />
  <row Id="26481" PostHistoryTypeId="3" PostId="9616" RevisionGUID="3c574fa5-64ca-4aa9-9d84-d411d96c7382" CreationDate="2020-02-27T15:55:45.490" UserId="11282" Text="|3d|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26482" PostHistoryTypeId="2" PostId="9617" RevisionGUID="b07ff310-6f8a-448c-b22f-2202dafc2561" CreationDate="2020-02-27T16:20:57.617" UserId="7647" Text="The [PLY file format][1] is a simple format similar to OBJ that allows arbitrary attributes (like colours) and has a binary mode.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cc.gatech.edu/projects/large_models/ply.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="26483" PostHistoryTypeId="5" PostId="9597" RevisionGUID="a9869614-c5be-44ab-b488-e70aa1041f34" CreationDate="2020-02-27T16:33:13.460" UserId="5574" Comment="Finished all matrix transforms - just have illustrations and some explanations. Particularly CCS -&gt; NDCS..." Text="**Note: This is a work in progress - working on LaTeX and useful illustrations.**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;My derivation notes were based partially on the perspective projection matrix derivation in [`Computer Graphics: Principles and Practice (2nd Ed)`](https://www.amazon.com/Computer-Graphics-Principles-Practice-2nd/dp/0201848406). My understanding is that the 3rd edition takes a more contemporary approach with references to OpenGL and Direct3D. I haven't read this edition, and can't vouch for it.&#xD;&#xA;&#xD;&#xA;This derivation also assumes an understanding of homogeneous coordinates and the notion of a projective space. The wikipedia entry is concise, but lacks the intuition provided by a few good **2D** example illustrations. (If you're *really* keen, search for early articles on the subject by [Jim Blinn](http://www.jimblinn.com/)).&#xD;&#xA;&#xD;&#xA;First, we need to outline a few assertions and conventions:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- We always assume a ['right-handed' coordinate space](https://en.wikipedia.org/wiki/Right-hand_rule#Coordinates), unless otherwise stated. The 'eye' is at: `(0, 0, 0)`. `(+Z)` may be considered the direction pointing 'out' of the screen (or window / viewport), while `(X, Y)` are Cartesian coordinates, where: `(0, 0)` corresponds to the centre of that viewport.&#xD;&#xA;&#xD;&#xA;&lt;/br&gt;&#xD;&#xA;&#xD;&#xA;- The [**view frustum**](https://en.wikipedia.org/wiki/Viewing_frustum) has a near plane at: `Z = - N` and a far plane at: `Z = - F`, with normals in the `+Z` direction. The near plane: `Z = - N`, has `X: L &lt;= X &lt;= R`, and `Y: B &lt;= Y &lt;= T`, which will eventually map to a **3D viewport**. This frustum encapsulates all visible geometry. (Technically speaking, `R &lt; L`, `T &lt; B`, and `N &gt; F &gt; 0` are permitted by `glFrustum`. Arbitrary matrices are of course permitted in core profile OpenGL contexts.)&#xD;&#xA;&#xD;&#xA;&lt;/br&gt;&#xD;&#xA;&#xD;&#xA;- The mathematics will use what are somewhat misleadingly called 'row-major' matrices, but I insist on the use of column vectors when describing a system of transforms, i.e., the *column* vector is 'pre-multiplied' by the matrix: `v' = [M]v`. Disagree all you want - just know that you are sick and need help.&#xD;&#xA;&#xD;&#xA; In all seriousness, either convention can be made to work; it's just a matter of being aware of the conventions and sticking with a choice. The 'column-vector' convention is typically the one taught in linear algebra. We apply *successive* transforms: `[A]`, `[B]`, `[C]` to a vector: `v`, like we would apply functions: `C(B(A(v)))`, hence: `v' = [C][B][A]v`.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Any view frustum (camera) in space can be transformed by pre-multiplying the (homogeneous) coordinates by an 'orientation matrix'. That's beyond your question, but typically requires a general **PRP** (camera eye point), **VRP** (the centre of the 'near' projection plane), and the **VUP** point, which references a point defining 'up'. In effect, it's sufficient to form a orthonormal coordinate system. This is the view coordinate space **(VCS)**.&#xD;&#xA;&#xD;&#xA;The orthonormal basis, along with the **PRP** translation, can be used to construct an inverse transform that 'premultiplies' geometry to world coordinate space **(WCS)**. Again, you can save the concept of orthonormal basis / coordinate system transforms for a rainy day...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;We do not *assume* the view frustum is centred on the Z axis - although this is almost certainly the case for most projections. There are more exotic transforms (a mirror in a scene comes to mind); we'll concentrate on the general case.&#xD;&#xA;&#xD;&#xA;The direction of projection: $\small\\\mathbf{DOP}=\left[(R+L)/2,\: (T+B)/2,\: -N\right]\,^T$. The view frustum is typically symmetric about the Z axis s.t. `R = - L`, `T = - B`, yielding: $\small\\\mathbf{DOP}=\left[0,\: 0,\: -N\right]\,^T$.&#xD;&#xA;&#xD;&#xA;Of course, this is not *required*, so our first step in the perspective projection derivation is to apply a *shear* matrix that maps the $\small\\\mathbf{DOP}$ to the (negative) Z-axis:&#xD;&#xA;&#xD;&#xA;`(R + L) / 2 + shear.x (- N) = 0` =&gt; `shear.x = (R + L) / (2.N)`&lt;br/&gt;&#xD;&#xA;`(T + B) / 2 + shear.y (- N) = 0` =&gt; `shear.y = (T + B) / (2.N)`&#xD;&#xA;&#xD;&#xA;Consider the shear transformation applied to the frustum's near-clipping plane vertex coordinates:&#xD;&#xA;&#xD;&#xA;$\tiny\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ 0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;R \\ T \\ -N \\ 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;= \begin{pmatrix}&#xD;&#xA;(R-L)/2 \\ (T-B)/2 \\ -N \\ 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\:,$&#xD;&#xA;&#xD;&#xA;$\tiny\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ 0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;L \\ B \\ -N \\ 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;= \begin{pmatrix}&#xD;&#xA;(L-R)/2 \\ (B-T)/2 \\ -N \\1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Following this transform, the $\small\\\mathbf{DOP}$ is in direction of the `- Z` axis; specifically, the centre of the near view plane: $\small\left((R+L)/2,\: (T+B)/2,\: -N,\: 1\right)\,^T$ has been mapped to: $\small\left(0,\: 0,\: -N,\: 1\right)\,^T$.&#xD;&#xA;&#xD;&#xA;Now we want to scale the perspective projection transform such that the `R, L, T, B` planes of the frustum have have a unit gradient. The current gradients are `(R - L) / (2.N)` (right and left), and `(T - B) / (2.N)` (top and bottom). The symmetry is due to the previous shearing transform.&#xD;&#xA;&#xD;&#xA;`(R - L) / (2.N) * scale.x = 1` =&gt; `scale.x = 2.N / (R - L)`&lt;br/&gt;&#xD;&#xA;`(T - B) / (2.N) * scale.y = 1` =&gt; `scale.y = 2.N / (T - B)`&#xD;&#xA;&#xD;&#xA;Furthermore, we want to scale by `(1 / F)` s.t. the far clipping plane is mapped to: `Z = - 1`, while the unit slopes of the right, left, top, and bottom clipping planes are preserved. These scaling factors premultiply the perspective projection matrix:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;2.N/(F(R-L)) &amp; 0 &amp; 0 &amp; 1 \\ 0 &amp; 2.N/(F(T-B)) &amp; 0 &amp; 1 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ 0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;=\\&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;2.N/(F(R-L)) &amp; 0 &amp; (R+L)/(F(R-L)) &amp; 0 \\ &#xD;&#xA;0 &amp; 2.N/(F(T-B)) &amp; (T+B)/(F(T-B)) &amp; 0 \\ &#xD;&#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;This transform yields what may be considered *the normalized frustum*.&#xD;&#xA;&#xD;&#xA;**(TODO: need an image to show this transform)**&#xD;&#xA;&#xD;&#xA;The vertices of near clipping plane are mapped to: $\small\left(\pm N/F,\: \pm N/F,\: -N/F,\: 1\right)\,^T$, while the vertices of the far-clipping plane are mapped to: $\small\left(\pm 1,\: \pm 1,\: -1,\: 1\right)\,^T$.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**(TODO: perspective (projection) transform unification -&gt; CCS)**&#xD;&#xA;&#xD;&#xA;As a homogeneous transform, the matrix can be simplified by scaling all elements by `F`, since: $\small\left(X,\: Y,\: Z,\: W\right)\,^T \equiv \left(F.X,\: F.Y,\: F.Z,\: F.W\right)\,^T$ :&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xD;&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; F&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;The normalized perspective projection view volume can be transformed into a parallel projection view volume:&#xD;&#xA;&#xD;&#xA;**(TODO: partial justification for this step. Perspective projection is just another homogeneous transform. Final CCS / NDCS have exquisite clip test properties)**&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; F/(F-N) &amp; N/(F-N) \\ 0 &amp; 0 &amp; -1 &amp; 0&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xD;&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; F&#xD;&#xA;\end{pmatrix}&#xD;&#xA;=\\&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xD;&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; F/(F-N) &amp; F.N/(F-N) \\ 0 &amp; 0 &amp; -1 &amp; 0&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;**(TODO: need an image to show this transform)**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Finally, we apply the following transforms to the current projection matrix:&#xD;&#xA;&#xD;&#xA;- Scale in `Z` by `(2)` to yield a cubic view volume.&#xD;&#xA;- Translate by: $\small\left(0,\: 0,\: 1,\: 1\right)\,^T$ to centre the cube at the origin.&#xD;&#xA;- Convert to a left-handed coordinate system to satisfy **NDCS** conventions.&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 1 &amp; 1 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 2 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;=\&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -2 &amp; -1 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;This yields:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -2 &amp; -1 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xD;&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; F/(F-N) &amp; F.N/(F-N) \\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xD;&#xA;\end{pmatrix}&#xD;&#xA;=\\&#xD;&#xA;\tiny\begin{pmatrix}&#xD;&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xD;&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; -(F+N)/(F-N) &amp; -2.F.N/(F-N) \\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;**(TODO: need an image to show this transform)**&#xD;&#xA;&#xD;&#xA;**This is the canonical OpenGL perspective projection matrix:**&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;\small\begin{pmatrix}&#xD;&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xD;&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; -(F+N)/(F-N) &amp; -2.F.N/(F-N) \\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26484" PostHistoryTypeId="5" PostId="9520" RevisionGUID="a866ad76-2af1-4ac8-b65a-e663cdeb99ac" CreationDate="2020-02-27T18:04:42.437" UserId="7462" Comment="added 1 character in body" Text="So, the number of polynomials that you piece together depends on multiple factors, including the number of control points and the degree of the curve. If the number of points is equal to the order, then you have a single polynomial, if the order is $n$ and you have $n+1$ points, then you are piecing together 2 polynomials, etc...&#xD;&#xA;&#xD;&#xA;Distinct points are points that are different from each other.&#xD;&#xA;Take the vector [0,1,2,3,4] where all knots are distinct and contrast it with [0,1,2,2,3,4] where the knot 2 has multiplicity 2 (it's not distinct since it appears twice). These knots lower the degree of the curve locally by 1 for each repetition.&#xD;&#xA;&#xD;&#xA;The overall curve can be defined in many ways, the simplest way to look at it is as DeDoor's algorithm, which is a generalisation of DeCastlejeau's.&#xD;&#xA;&#xD;&#xA;I am going to do a bit of self promotion and link my [own notes of B-Splines][1]. Gitlab's PDF viewer butchers them a bit so I recommend downloading them and reading them with Okular or Adobe reader.&#xD;&#xA;&#xD;&#xA;Regardless, that document has more information than what can be put into a stack exchange answer and does indeed try to convey the intuition about how to build B-Splines, both mathematically and algorithmically.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gitlab.com/Makogan/mathproofs/blob/master/B-splines/b-splines.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="26486" PostHistoryTypeId="5" PostId="9610" RevisionGUID="3110adfd-ff3c-4ec6-9780-feecfb8745d5" CreationDate="2020-02-27T20:59:37.730" UserId="11282" Comment="added 13 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary **circular** cylinder (defined by startpoint, endpoint, and radius). An **Infinite cylinder is acceptable as well**, as long as it passes through those points and has the same radius.&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;* The box being inside the volume of the cylinder should also count as an intersection&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic." ContentLicense="CC BY-SA 4.0" />
  <row Id="26487" PostHistoryTypeId="50" PostId="9199" RevisionGUID="220969cb-e794-49a1-a19a-179e318cf70d" CreationDate="2020-02-28T00:01:45.213" UserId="-1" />
  <row Id="26488" PostHistoryTypeId="50" PostId="9189" RevisionGUID="5b915e7c-1758-4888-b5fa-99638fea8599" CreationDate="2020-02-28T05:01:25.133" UserId="-1" />
  <row Id="26489" PostHistoryTypeId="5" PostId="9611" RevisionGUID="bbde8f07-9f14-49bf-a3b1-63e9ea2fd001" CreationDate="2020-02-28T19:32:20.230" UserId="10096" Comment="added 1617 characters in body" Text="As mentioned the problem of cylinder box intersection reduces to the problem of line-parallelogram intersection, and line segment-cylinder intersection.&#xD;&#xA;&#xD;&#xA;I will assume that you know how to intersect a line and a parallelogram. Here is a sketch for solving the line segment-cylinder intersection:&#xD;&#xA;&#xD;&#xA;The canonical equation of an elliptic cylinder aligned with the $Z$ axis and having center $(c_x, c_y, c_z)$ is given as:&#xD;&#xA;$$\frac{(x-c_x)^2}{a^2} + \frac{(y-c_y)^2}{b^2} = 1$$&#xD;&#xA;The parametric form of a ray is given as:&#xD;&#xA;$$\vec{r}(t) = \vec{o} + t\vec{d}$$&#xD;&#xA;Then by plugging r into the canonical equation one gets:&#xD;&#xA;$$\frac{(o_x + td_x -c_x)^2}{a^2} + \frac{(o_y + td_y -c_y)^2}{b^2} = 1$$&#xD;&#xA;Solve the quadratic equation for $t$ and you have your intersection. If the discriminant is negative then there is no intersection. To get a rotated cylinder, the easiest way is to apply the inverse rotation to the ray (the equation may be modified however too). Note that for a line segment, you simply need to check whether $t \in [t_0, t_1]$, where $\vec{a} = \vec{o} + t_0\vec{d}$ is the first point of the line segment, and $\vec{b} = \vec{o} + t_1\vec{d}$ is the second one.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT: To clarify you further questions in the comments:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;1) a,b in the denominator are the radii along the $X$ and $Y$ axes respectively. In the trivial case where $a=b=r$ we have the canonical equation for a circular cylinder:&#xD;&#xA;$$(x-c_x)^2 + (y-c_y)^2 = r^2$$&#xD;&#xA;&#xD;&#xA;2) For the intersection between the cylinder axis and the box a rotation is only required if your box is OOBB and you want to use your AABB intersection code.&#xD;&#xA;&#xD;&#xA;3) The solution of the quadratic equation is trivial (note, I renamed $a,b$ to $r_1,r_2$ to further emphasize that they are the radii):&#xD;&#xA;&#xD;&#xA;$$\frac{(o_x + td_x -c_x)^2}{r_1^2} + \frac{(o_y + td_y -c_y)^2}{r_2^2} = 1$$&#xD;&#xA;$$r_2^2(o_x + td_x - c_x)^2 + r_1^2(o_y + td_y -c_y)^2 = r_1^2r_2^2$$&#xD;&#xA;$$(r_2^2d_x^2+r_1^2d_y^2)t^2 - 2(r_2^2d_x(c_x-o_x) + r_1^2d_y(c_y-o_y))t + r_2^2(c_x-o_x)^2 + r_1^2(c_y-o_y)^2 - r_1^2r_2^2 = 0$$&#xD;&#xA;&#xD;&#xA;Let us substitute:&#xD;&#xA;$$A = (r_2^2d_x^2+r_1^2d_y^2)$$ &#xD;&#xA;$$B = (r_2^2d_x(c_x-o_x) + r_1^2d_y(c_y-o_y))$$ &#xD;&#xA;$$C = r_2^2(c_x-o_x)^2 + r_1^2(c_y-o_y)^2 - r_1^2r_2^2$$&#xD;&#xA;&#xD;&#xA;Then you have the quadratic equation:&#xD;&#xA;&#xD;&#xA;$$At^2 -2Bt + C = 0$$&#xD;&#xA;$$D = B^2-AC$$&#xD;&#xA;&#xD;&#xA;If $D&lt;0$ there is no intersection between the ray $\vec{o}+t\vec{d}$ and the cylinder, otherwise:&#xD;&#xA;&#xD;&#xA;$$t_1 = \frac{B-\sqrt{D}}{A}, t_2 = \frac{B+\sqrt{D}}{A},$$&#xD;&#xA;&#xD;&#xA;give you the two intersections (it is one intersection if $D=0$).&#xD;&#xA;&#xD;&#xA;Now let your segment vertices be $\vec{v}_a = \vec{o}+t_a\vec{d}$ and $\vec{v}_b = \vec{o} + t_b\vec{d}$. If $t_a \leq t_1 \leq t_b$ then you have an intersection at $t_1$, if $t_a \leq t_2 \leq t_b$ then you have an intersection at $t_2$, otherwise there is not intersection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26490" PostHistoryTypeId="5" PostId="9610" RevisionGUID="2104c79f-a457-43a4-8497-7009904f2bf3" CreationDate="2020-02-28T20:51:46.950" UserId="11282" Comment="added 495 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary **circular** cylinder (defined by startpoint, endpoint, and radius). An **Infinite cylinder is acceptable as well**, as long as it passes through those points and has the same radius.&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;* The box being inside the volume of the cylinder should also count as an intersection&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic.&#xD;&#xA;&#xD;&#xA;**EDIT:** I think I have realized there is a far, far simpler solution. (Though it still involves rotations)&#xD;&#xA;&#xD;&#xA;1: Rotate the cylinder to the Z axis &#xD;&#xA;&#xD;&#xA;2: Apply the same rotation to the axis-aligned bounding box vertices&#xD;&#xA;&#xD;&#xA;3: Get the distance of every vertex (in x,y) from 0,0. If *any* of them report a distance less than the radius of the cylinder, part of the box must overlap with the cylinder. &#xD;&#xA;&#xD;&#xA;I'm not positive, but I think that should work! If it does, I will put it into a full solution." ContentLicense="CC BY-SA 4.0" />
  <row Id="26491" PostHistoryTypeId="5" PostId="9610" RevisionGUID="d44b472d-b98d-460e-9fd6-440535b7b3d5" CreationDate="2020-02-28T21:44:23.547" UserId="11282" Comment="added 11 characters in body; edited title" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary **circular** cylinder (defined by startpoint, endpoint, and radius). An **Infinite cylinder is acceptable as well**, as long as it passes through those points and has the same radius.&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;* The box being completely inside the volume of the cylinder should also count as an intersection&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic.&#xD;&#xA;&#xD;&#xA;**EDIT:** I think I have realized there is a far, far simpler solution. (Though it still involves rotations)&#xD;&#xA;&#xD;&#xA;1: Rotate the cylinder to the Z axis &#xD;&#xA;&#xD;&#xA;2: Apply the same rotation to the axis-aligned bounding box vertices&#xD;&#xA;&#xD;&#xA;3: Get the distance of every vertex (in x,y) from 0,0. If *any* of them report a distance less than the radius of the cylinder, part of the box must overlap with the cylinder. &#xD;&#xA;&#xD;&#xA;I'm not positive, but I think that should work! If it does, I will put it into a full solution." ContentLicense="CC BY-SA 4.0" />
  <row Id="26492" PostHistoryTypeId="4" PostId="9610" RevisionGUID="d44b472d-b98d-460e-9fd6-440535b7b3d5" CreationDate="2020-02-28T21:44:23.547" UserId="11282" Comment="added 11 characters in body; edited title" Text="Looking for a cylinder / axis-aligned box volume intersection test" ContentLicense="CC BY-SA 4.0" />
  <row Id="26494" PostHistoryTypeId="2" PostId="9618" RevisionGUID="57beb3de-78a5-47ae-baf2-d198efdcb9a9" CreationDate="2020-02-29T05:56:51.310" UserId="10079" Text="I am reading a paper *TileGAN: Synthesis of Large-Scale Non-Homogeneous Textures*&#xD;&#xA;available [here](https://arxiv.org/abs/1904.12795), and in the section entitled *Selected Applications of GANS* (i.e. applications of Generative Adversarial networks), they make claim that recent papers in computer grahics apply GANs&#xD;&#xA;to :&#xD;&#xA;&#xD;&#xA; - Volumetric modeling of shapes&#xD;&#xA;&#xD;&#xA;A quick google search of this term does not yield great results for a definition of this word. What does the term &quot;volumetric modeling&quot; mean?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26495" PostHistoryTypeId="1" PostId="9618" RevisionGUID="57beb3de-78a5-47ae-baf2-d198efdcb9a9" CreationDate="2020-02-29T05:56:51.310" UserId="10079" Text="Terminology: Volumetric Model" ContentLicense="CC BY-SA 4.0" />
  <row Id="26496" PostHistoryTypeId="3" PostId="9618" RevisionGUID="57beb3de-78a5-47ae-baf2-d198efdcb9a9" CreationDate="2020-02-29T05:56:51.310" UserId="10079" Text="|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26497" PostHistoryTypeId="2" PostId="9619" RevisionGUID="98fa201e-7ef1-4303-b357-ff83f719911a" CreationDate="2020-02-29T17:46:20.117" UserDisplayName="user2500" Text="Volumetric Modeling usually refers to using a regular 3D grid of voxels, analogous to 2D pixels, to define properties of an object at points or small regions of space.&#xD;&#xA;&#xD;&#xA;While more complex data might be stored at each voxel, often each contains a simple vector of values which can be interpreted directly as density or material properties for analysis and rendering. There is a whole literature on such techniques (search for Volume Rendering), often in the context of medical imaging where e.g. MRI scanners produce such data directly.&#xD;&#xA;&#xD;&#xA;It is natural to consider extending techniques for generating images composed of 2D pixels to 3D voxels and modeling solids.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26501" PostHistoryTypeId="2" PostId="9621" RevisionGUID="77bf968b-a3dc-4f42-beb5-91b3baf5d968" CreationDate="2020-03-01T16:58:49.263" UserId="11933" Text="Here is a youtube video showing my problem:&#xD;&#xA;&#xD;&#xA;  * [youtube.com/watch?v=y8J7VhS2pkM][1]&#xD;&#xA;&#xD;&#xA;I think I'm either doing the texture lookup on the reflection texture wrong, or the reflection or view matrix is somehow wrong.&#xD;&#xA;&#xD;&#xA;The reflection matrix is calculated after Goldman formula with plane normal pointing in positive y-Axis (world up vector).&#xD;&#xA;&#xD;&#xA;   * [WorldRenderer.cpp#L97][2] (`reflectionMatrix()` and `renderClippingPlanes()` at those positions)&#xD;&#xA;   * [Water vertex shader][3]&#xD;&#xA;   * [Water fragment shader][4]&#xD;&#xA;   * [Camera viewmatrix calculation][5]&#xD;&#xA;&#xD;&#xA;What am I doing wrong here? Notice the renderings of the framebuffer textures in the debug ui.&#xD;&#xA;&#xD;&#xA;I was following this water rendering tutorial series here: [Youtube Water rendering tutorial][6]&#xD;&#xA;&#xD;&#xA;There are other projects following this tutorial:&#xD;&#xA;&#xD;&#xA;   * https://github.com/fede-vaccaro/TerrainEngine-OpenGL&#xD;&#xA;   * https://github.com/codycoolwaffle/avaritia&#xD;&#xA;&#xD;&#xA;I couldn't find my error even after looking at the above code bases.&#xD;&#xA;&#xD;&#xA;What might the error be? Anyone any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=y8J7VhS2pkM&#xD;&#xA;  [2]: https://github.com/mgerhardy/engine/blob/master/src/modules/voxelrender/WorldRenderer.cpp#L97&#xD;&#xA;  [3]: https://github.com/mgerhardy/engine/blob/master/src/modules/voxelrender/shaders/water.vert&#xD;&#xA;  [4]: https://github.com/mgerhardy/engine/blob/master/src/modules/voxelrender/shaders/water.frag&#xD;&#xA;  [5]: https://github.com/mgerhardy/engine/blob/master/src/modules/video/Camera.cpp#L309&#xD;&#xA;  [6]: https://www.youtube.com/watch?v=0NH9k4zTAqk&amp;list=PLRIWtICgwaX23jiqVByUs0bqhnalNTNZh&amp;index=3" ContentLicense="CC BY-SA 4.0" />
  <row Id="26502" PostHistoryTypeId="1" PostId="9621" RevisionGUID="77bf968b-a3dc-4f42-beb5-91b3baf5d968" CreationDate="2020-03-01T16:58:49.263" UserId="11933" Text="Wrong reflection" ContentLicense="CC BY-SA 4.0" />
  <row Id="26503" PostHistoryTypeId="3" PostId="9621" RevisionGUID="77bf968b-a3dc-4f42-beb5-91b3baf5d968" CreationDate="2020-03-01T16:58:49.263" UserId="11933" Text="|opengl|glsl|mathematics|reflection|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26504" PostHistoryTypeId="5" PostId="9591" RevisionGUID="7f40bbe7-82e6-4efb-9600-6b16faaa1246" CreationDate="2020-03-02T11:27:22.240" UserId="9254" Comment="added 171 characters in body" Text="Let $f$ denote the measurement contribution function for paths of length $k\in\mathbb N$, i.e. $$f(x)=g(x_0\leftrightarrow x_1)W_{\text e}(x_1\to x_0)t_k(x_0,\ldots,x_k)L_{\text e}(x_k\to x_{k-1}),$$ where $$t_k(x)=\prod_{i=2}^kg(x_{i-1}\leftrightarrow x_i)f_{\text s}(x_i\to x_{i-1}\to x_{i-2}),$$ and $h_j$ denote the image reconstruction filter of the $j$th pixel so that the measurement $I_j$ of the $j$th pixel color is given by $$I_j=\int h_jf\:{\rm d}\mu.$$&#xD;&#xA;&#xD;&#xA;What can we assume know about $h_j$ in general? One thing is that it will only depend on first two vertices of a path.&#xD;&#xA;&#xD;&#xA;There are two properties which I really would like to being able to assume: (a) $c:=\sup_j\left\|h_j\right\|&lt;\infty$ (b) $\int|g_j|^2\:{\rm d}\mu\le\alpha\int|f_0|^2\:{\rm d}\mu$ for some $\alpha\ge0$, where $g_j:=1_{\{\:h_j\:&gt;\:0\:\}}\left(h_jf-\frac1{\mu\left(\left\{h_j&gt;0\right\}\right)}I_j\right)$ and $f_0:=1_{\{\:f\:\ne\:0\:\}}\left(f-\frac1{\mu\left(\left\{f\ne0\right\}\right)}\int f\:{\rm d}\mu\right)$.&#xD;&#xA;&#xD;&#xA;However, I know almost nothing about the mathematical properties of $h_j$ and so it's hard for me to verify if these properties hold. I guess that generally $h_j\ge0$, but I'm even unsure about that. Maybe even $h_j\in[0,1]$? It would be great if someone could answer if (a) and/or (b) hold or link me to a reference." ContentLicense="CC BY-SA 4.0" />
  <row Id="26505" PostHistoryTypeId="2" PostId="9622" RevisionGUID="fd36cc52-884f-45bc-b2fb-a6901b48ad75" CreationDate="2020-03-02T12:00:58.207" UserId="10096" Text="I am replying to the last edit of the question.&#xD;&#xA;&#xD;&#xA;You can show that $\|h_j * f \|^2_2 \leq \|h_j\|^2_1\|f\|^2_2$ from Young's theorem. Provided that  $\|h_j\|_1 \leq 1$ you have: $\|h_j * f \|^2_2 \leq \|f\|^2_2$. Additionally for $g_j$ I believe you want to clamp the indicator function to $\{h_j &gt; 0 \wedge f &gt; 0\}$. Then $\int_{\{h_j&gt;0 \wedge f&gt;0\}} a\leq \int_{\{f&gt;0\}}a$ (since the integrands are always non-negative: $a\geq 0$). This basically proves that the inequality holds for the left terms of the quadratic expansions, the middle terms are both negative, so those may be ignored. The only thing left to prove is: $(\frac{1}{\mu(\{h_j&gt;0 \wedge f&gt;0\})}\int h_jf)^2 \leq (\frac{1}{\mu(\{f&gt;0\})}\int f)^2$, which is the case if $h_j \leq 1$ everywhere. Basically, as long as your filter $h_j$ preserves the minimum and maximum of the image, you're good (this is not an unreasonable requirement for a filter, note however, that there are filers that do not preserve min-max).&#xD;&#xA;&#xD;&#xA;Edit: My bad, the middle terms may not be ignored (at least the one on the right of the inequality). Which means you are left to prove that:&#xD;&#xA;&#xD;&#xA;$$\int h_jf-\frac{\int h_jf}{\mu(\{h_j&gt;0 \wedge f&gt;0\})} \geq \int f-\frac{\int f}{\mu(\{f&gt;0\})}$$, which will be a problem.&#xD;&#xA;&#xD;&#xA;I guess one has to use tighter bounds to relate the mixed term with the squared terms." ContentLicense="CC BY-SA 4.0" />
  <row Id="26506" PostHistoryTypeId="5" PostId="9622" RevisionGUID="51ab6404-3d80-4e69-9710-7dcd5659eff2" CreationDate="2020-03-02T12:07:10.787" UserId="10096" Comment="added 17 characters in body" Text="I am replying to the last edit of the question.&#xD;&#xA;&#xD;&#xA;You can show that $\|h_j * f \|^2_2 \leq \|h_j\|^2_1\|f\|^2_2$ from Young's theorem. Provided that  $\|h_j\|_1 \leq 1$ you have: $\|h_j * f \|^2_2 \leq \|f\|^2_2$. Additionally for $g_j$ I believe you want to clamp the indicator function to $\{h_j &gt; 0 \wedge f &gt; 0\}$. Then $\int_{\{h_j&gt;0 \wedge f&gt;0\}} a\leq \int_{\{f&gt;0\}}a$ (since the integrands are always non-negative: $a\geq 0$). This basically proves that the inequality holds for the left terms of the quadratic expansions, the middle terms are both negative, &lt;strike&gt;so those may be ignored&lt;/strike&gt;. The only thing left to prove is: $(\frac{1}{\mu(\{h_j&gt;0 \wedge f&gt;0\})}\int h_jf)^2 \leq (\frac{1}{\mu(\{f&gt;0\})}\int f)^2$, which is the case if $h_j \leq 1$ everywhere. Basically, as long as your filter $h_j$ preserves the minimum and maximum of the image, you're good (this is not an unreasonable requirement for a filter, note however, that there are filers that do not preserve min-max).&#xD;&#xA;&#xD;&#xA;Edit: My bad, the middle terms may not be ignored (at least the one on the right of the inequality). Which means you are left to prove that:&#xD;&#xA;&#xD;&#xA;$$\frac{(\int h_jf)^2}{\mu(\{h_j&gt;0 \wedge f&gt;0\})} \geq \frac{(\int f)^2}{\mu(\{f&gt;0\})}$$, which will be a problem.&#xD;&#xA;&#xD;&#xA;I guess one has to use tighter bounds to relate the mixed term with the squared terms." ContentLicense="CC BY-SA 4.0" />
  <row Id="26507" PostHistoryTypeId="5" PostId="9622" RevisionGUID="7f2410b5-be83-40f6-856a-ced5029ad392" CreationDate="2020-03-02T12:29:10.437" UserId="10096" Comment="added 673 characters in body" Text="I am replying to the last edit of the question.&#xD;&#xA;&#xD;&#xA;You can show that $\|h_j * f \|^2_2 \leq \|h_j\|^2_1\|f\|^2_2$ from Young's theorem. Provided that  $\|h_j\|_1 \leq 1$ you have: $\|h_j * f \|^2_2 \leq \|f\|^2_2$. Additionally for $g_j$ I believe you want to clamp the indicator function to $\{h_j &gt; 0 \wedge f &gt; 0\}$. Then $\int_{\{h_j&gt;0 \wedge f&gt;0\}} a\leq \int_{\{f&gt;0\}}a$ (since the integrands are always non-negative: $a\geq 0$). This basically proves that the inequality holds for the left terms of the quadratic expansions, the middle terms are both negative, &lt;strike&gt;so those may be ignored&lt;/strike&gt;. The only thing left to prove is: $(\frac{1}{\mu(\{h_j&gt;0 \wedge f&gt;0\})}\int h_jf)^2 \leq (\frac{1}{\mu(\{f&gt;0\})}\int f)^2$, which is the case if $h_j \leq 1$ everywhere. Basically, as long as your filter $h_j$ preserves the minimum and maximum of the image, you're good (this is not an unreasonable requirement for a filter, note however, that there are filers that do not preserve min-max).&#xD;&#xA;&#xD;&#xA;Edit: My bad, the middle terms may not be ignored (at least the one on the right of the inequality). Which means you are left to prove that:&#xD;&#xA;&#xD;&#xA;$$\frac{(\int h_jf)^2}{\mu(\{h_j&gt;0 \wedge f&gt;0\})} \geq \frac{(\int f)^2}{\mu(\{f&gt;0\})}$$, which will be a problem.&#xD;&#xA;&#xD;&#xA;I guess one has to use tighter bounds to relate the mixed term with the squared terms.&#xD;&#xA;&#xD;&#xA;Edit 2:&#xD;&#xA;&#xD;&#xA;Let's consider the expression as a whole then:&#xD;&#xA;&#xD;&#xA;$$\int \left(h_jf - \frac{\int h_jf}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})} \right)^2 \leq \alpha \int \left(f - \frac{\int f}{\mu(\{f &gt; 0\})} \right)^2$$&#xD;&#xA;$$ 0 \leq \alpha\int (f)^2 - \int (h_jf)^2 +\alpha\frac{(\int f)^2}{\mu^2(\{f &gt; 0\})} - \frac{(\int h_jf)^2}{\mu^2(\{h_j &gt; 0 \wedge f &gt; 0\})} + \frac{2(\int h_jf)^2}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})} - \alpha\frac{2(\int f)^2}{\mu(\{f &gt; 0\})}$$&#xD;&#xA;$$ 0 \leq \alpha\left(\int (f)^2 - \frac{(1-2\mu(\{f &gt; 0\}))(\int f)^2}{\mu^2(\{f &gt; 0\})}\right) - \left( \int (h_jf)^2 - \frac{(1-2\mu(\{h_j &gt; 0 \wedge f &gt; 0\}))(\int h_jf)^2}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})}\right) $$" ContentLicense="CC BY-SA 4.0" />
  <row Id="26508" PostHistoryTypeId="5" PostId="9622" RevisionGUID="c114e98a-fb45-4d7a-95a4-33240cbb4840" CreationDate="2020-03-02T12:32:04.827" UserId="10096" Comment="added 673 characters in body" Text="I am replying to the last edit of the question.&#xD;&#xA;&#xD;&#xA;You can show that $\|h_j * f \|^2_2 \leq \|h_j\|^2_1\|f\|^2_2$ from Young's theorem. Provided that  $\|h_j\|_1 \leq 1$ you have: $\|h_j * f \|^2_2 \leq \|f\|^2_2$. Additionally for $g_j$ I believe you want to clamp the indicator function to $\{h_j &gt; 0 \wedge f &gt; 0\}$. Then $\int_{\{h_j&gt;0 \wedge f&gt;0\}} a\leq \int_{\{f&gt;0\}}a$ (since the integrands are always non-negative: $a\geq 0$). This basically proves that the inequality holds for the left terms of the quadratic expansions, the middle terms are both negative, &lt;strike&gt;so those may be ignored&lt;/strike&gt;. The only thing left to prove is: $(\frac{1}{\mu(\{h_j&gt;0 \wedge f&gt;0\})}\int h_jf)^2 \leq (\frac{1}{\mu(\{f&gt;0\})}\int f)^2$, which is the case if $h_j \leq 1$ everywhere. Basically, as long as your filter $h_j$ preserves the minimum and maximum of the image, you're good (this is not an unreasonable requirement for a filter, note however, that there are filers that do not preserve min-max).&#xD;&#xA;&#xD;&#xA;Edit: My bad, the middle terms may not be ignored (at least the one on the right of the inequality). Which means you are left to prove that:&#xD;&#xA;&#xD;&#xA;$$\frac{(\int h_jf)^2}{\mu(\{h_j&gt;0 \wedge f&gt;0\})} \geq \frac{(\int f)^2}{\mu(\{f&gt;0\})}$$, which will be a problem.&#xD;&#xA;&#xD;&#xA;I guess one has to use tighter bounds to relate the mixed term with the squared terms.&#xD;&#xA;&#xD;&#xA;Edit 2:&#xD;&#xA;&#xD;&#xA;Let's consider the expression as a whole then:&#xD;&#xA;&#xD;&#xA;$$\int \left(h_jf - \frac{\int h_jf}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})} \right)^2 \leq \alpha \int \left(f - \frac{\int f}{\mu(\{f &gt; 0\})} \right)^2$$&#xD;&#xA;$$ 0 \leq \alpha\int (f)^2 - \int (h_jf)^2 +\alpha\frac{(\int f)^2}{\mu^2(\{f &gt; 0\})} - \frac{(\int h_jf)^2}{\mu^2(\{h_j &gt; 0 \wedge f &gt; 0\})} + \frac{2(\int h_jf)^2}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})} - \alpha\frac{2(\int f)^2}{\mu(\{f &gt; 0\})}$$&#xD;&#xA;$$ 0 \leq \alpha\left(\int (f)^2 - \frac{(1-2\mu(\{f &gt; 0\}))(\int f)^2}{\mu^2(\{f &gt; 0\})}\right) - \left( \int (h_jf)^2 - \frac{(1-2\mu(\{h_j &gt; 0 \wedge f &gt; 0\}))(\int h_jf)^2}{\mu^2(\{h_j &gt; 0 \wedge f &gt; 0\})}\right) $$" ContentLicense="CC BY-SA 4.0" />
  <row Id="26509" PostHistoryTypeId="5" PostId="9622" RevisionGUID="bdf7727d-f52a-4766-970c-5329b938bb27" CreationDate="2020-03-02T12:55:23.620" UserId="10096" Comment="added 673 characters in body" Text="I am replying to the last edit of the question.&#xD;&#xA;&#xD;&#xA;You can show that $\|h_j * f \|^2_2 \leq \|h_j\|^2_1\|f\|^2_2$ from Young's theorem. Provided that  $\|h_j\|_1 \leq 1$ you have: $\|h_j * f \|^2_2 \leq \|f\|^2_2$. Additionally for $g_j$ I believe you want to clamp the indicator function to $\{h_j &gt; 0 \wedge f &gt; 0\}$. Then $\int_{\{h_j&gt;0 \wedge f&gt;0\}} a\leq \int_{\{f&gt;0\}}a$ (since the integrands are always non-negative: $a\geq 0$). This basically proves that the inequality holds for the left terms of the quadratic expansions, the middle terms are both negative, &lt;strike&gt;so those may be ignored&lt;/strike&gt;. The only thing left to prove is: $(\frac{1}{\mu(\{h_j&gt;0 \wedge f&gt;0\})}\int h_jf)^2 \leq (\frac{1}{\mu(\{f&gt;0\})}\int f)^2$, which is the case if $h_j \leq 1$ everywhere. Basically, as long as your filter $h_j$ preserves the minimum and maximum of the image, you're good (this is not an unreasonable requirement for a filter, note however, that there are filers that do not preserve min-max).&#xD;&#xA;&#xD;&#xA;Edit: My bad, the middle terms may not be ignored (at least the one on the right of the inequality). Which means you are left to prove that:&#xD;&#xA;&#xD;&#xA;$$\frac{(\int h_jf)^2}{\mu(\{h_j&gt;0 \wedge f&gt;0\})} \geq \frac{(\int f)^2}{\mu(\{f&gt;0\})}$$, which will be a problem.&#xD;&#xA;&#xD;&#xA;I guess one has to use tighter bounds to relate the mixed term with the squared terms.&#xD;&#xA;&#xD;&#xA;Edit 2:&#xD;&#xA;&#xD;&#xA;Let's consider the expression as a whole then:&#xD;&#xA;&#xD;&#xA;$$\int \left(h_jf - \frac{\int h_jf}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})} \right)^2 \leq \alpha \int \left(f - \frac{\int f}{\mu(\{f &gt; 0\})} \right)^2$$&#xD;&#xA;$$ 0 \leq \alpha\int (f)^2 - \int (h_jf)^2 +\alpha\frac{(\int f)^2}{\mu^2(\{f &gt; 0\})} - \frac{(\int h_jf)^2}{\mu^2(\{h_j &gt; 0 \wedge f &gt; 0\})} + \frac{2(\int h_jf)^2}{\mu(\{h_j &gt; 0 \wedge f &gt; 0\})} - \alpha\frac{2(\int f)^2}{\mu(\{f &gt; 0\})}$$&#xD;&#xA;$$ 0 \leq \alpha\left(\int (f)^2 - \frac{(1-2\mu(\{f &gt; 0\}))(\int f)^2}{\mu^2(\{f &gt; 0\})}\right) - \left( \int (h_jf)^2 - \frac{(1-2\mu(\{h_j &gt; 0 \wedge f &gt; 0\}))(\int h_jf)^2}{\mu^2(\{h_j &gt; 0 \wedge f &gt; 0\})}\right) $$&#xD;&#xA;&#xD;&#xA;$$0 \leq \left(\int(\sqrt{\alpha}f)^2-\int (h_jf)^2\right) - \left(\frac{\alpha(1-2\mu(\{f &gt; 0\}))(\int f)^2}{\mu^2(\{f &gt; 0\})}  - \frac{(1-2\mu(\{h_j &gt; 0 \wedge f &gt; 0\}))(\int h_jf)^2}{\mu^2(\{h_j &gt; 0 \wedge f &gt; 0\})}\right) $$&#xD;&#xA;&#xD;&#xA;$$0 \leq \left(\int(\sqrt{\alpha}f)^2-\int (h_jf)^2\right) - \left(a \left(\int \sqrt{\alpha}f\right)^2 - b\left(\int h_jf\right)^2\right)$$&#xD;&#xA;&#xD;&#xA;Note also that $\left(\int u\right)^2 \leq \int u^2$. Then with an appropriate $\alpha$ and $h_j$ bounded it should hold. You may want to study the $a,b$ tems also." ContentLicense="CC BY-SA 4.0" />
  <row Id="26513" PostHistoryTypeId="2" PostId="9624" RevisionGUID="2a26a246-3136-43c6-b8a8-488903b5ec9c" CreationDate="2020-03-02T20:45:35.203" UserId="11282" Text="I ended up finding a fairly simple, fairly performant solution.&#xD;&#xA;&#xD;&#xA;1: Create a transformation matrix that rotates the cylinder to one of the axis (x, y or z)&#xD;&#xA;&#xD;&#xA;(That part is non-trivial)&#xD;&#xA;&#xD;&#xA;2: Apply the transformation matrix to the cylinder&#xD;&#xA;&#xD;&#xA;3: Apply the transformation matrix to the eight corners of the axis-aligned bounding box. &#xD;&#xA;&#xD;&#xA;(Applying a transformation matrix is not too hard, it looks like this:)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;newPoint[0] = (original[0] * xform[0][0]) + (original[1] * xform[1][0]) + (original[2] * xform[2][0] + xform[3][0]);&#xD;&#xA;newPoint[1] = (original[0] * xform[0][1]) + (original[1] * xform[1][1]) + (original[2] * xform[2][1] + xform[3][1]);&#xD;&#xA;newPoint[2] = (original[0] * xform[0][2]) + (original[1] * xform[1][2]) + (original[2] * xform[2][2] + xform[3][2]);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4: Get the distance of the corners to (0,0,0). Keep in mind that depending on your method of determining distance (IE, using a 3D distance formula) you may need to zero out the value of the point on the axis the cylinder was rotated to. If the cylinder was rotated to the Z axis, you would need to zero out the Z value for that point.&#xD;&#xA;&#xD;&#xA;5: If *any* of the points report a distance less than the radius of the cylinder, you know there must be a volume intersection.&#xD;&#xA;&#xD;&#xA;6: Special case: If the cylinder has a diameter small enough, it could fit inside of the bounding box completely, thus there would be no points for which their distance &lt; cylinder radius. So make sure to get the diagonal width of the box, and check if the cylinder's radius is less than that. If it is, you need to perform a raytrace down the center of the cylinder to catch the box that way. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26514" PostHistoryTypeId="5" PostId="9610" RevisionGUID="9fd8d80f-60c7-4f15-a0f5-b9f591f9a65a" CreationDate="2020-03-02T20:49:11.057" UserId="11282" Comment="deleted 504 characters in body" Text="Given:&#xD;&#xA;&#xD;&#xA;* An arbitrary **circular** cylinder (defined by startpoint, endpoint, and radius). An **Infinite cylinder is acceptable as well**, as long as it passes through those points and has the same radius.&#xD;&#xA;* An axis-aligned box (defined by its minimum and maximum point)&#xD;&#xA;* The box being completely inside the volume of the cylinder should also count as an intersection&#xD;&#xA;&#xD;&#xA;To test if the cylinder and the box intersect.&#xD;&#xA;&#xD;&#xA;Does such a test exist?&#xD;&#xA;&#xD;&#xA;EDIT: I found [this](https://math.stackexchange.com/questions/166863/intersection-between-a-cylinder-and-an-axis-aligned-bounding-box?rq=1) on the mathmatics stack exchange, though at the moment I do not follow it. If there is an example of it in code form that would be fantastic." ContentLicense="CC BY-SA 4.0" />
  <row Id="26515" PostHistoryTypeId="2" PostId="9625" RevisionGUID="b626bc5a-7992-4322-b217-749f0bceb031" CreationDate="2020-03-03T22:45:58.920" UserId="9438" Text="You need to learn and understand STEP data exchange format (ISO 10303-21) which is the fundamental exchange format which the IFC schema is built on top of. This is no easy feat though, especially when comparing to a file format such as OBJ. OBJ files are designed to define geometry (and other information via associated MTL) as so are optimised for this purpose. IFC on the other hand is designed to exchange many aspects of AEC including building, services, structural, furnishings, energy model etc and so is far more complex with the geometry definitions being only a subset of the information supplied in an IFC. It would be easier to use an existing IFC library to do this, and even then, an understanding and the structure of the IFC entities and their hierarchy is still required to traverse the relationships (inverse attributes) between the object definitions in an IFC file in order to reconstruct the desired geometry.&#xD;&#xA;&#xD;&#xA;OBJ files explicitly define the vertices, normals and faces that represent a mesh, however while there are IFC entities which can represent meshes in a similar fashion (namely IfcConnectedFaceSet), most geometry defined in an IFC file should be considered more like a series of instructions/commands to recreate the geometry. For this reason you would also require a geometry library (one which can do things like extrusions, Boolean/CSG operations, curves, NURBS etc). For example, one of the main things that is represented in many IFC files would be the walls, doors, windows etc of a building, and while these could be represented as explicit tessellated data or breps, in my experience these tend to be represented as an IfcExtrudedAreaSolid (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometricmodelresource/lexical/ifcextrudedareasolid.htm) which supplies the direction and length to extrude a path/outline curve (the curve being defined by an IfcProfileDef which is related to the IfcExtrudedAreaSolid through an inverse attribute, https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcprofileresource/lexical/ifcprofiledef.htm). This gets even more complicated when there is an opening (i.e window recess or door opening in the wall) which again is related (through an inverse attribute) to the geometry representing the opening to be removed through a geometric Boolean operation (CSG). As you can see it starts to get complicated fairly quickly and isn't just a case of reading in raw vertices, normals and faces etc.&#xD;&#xA;&#xD;&#xA;All geometry in an IFC file is defined by objects which are sub types of IfcRepresentationItem (http://dcom.arch.gatech.edu/aci/cic/schema/ifcgeometryresource/lexical/ifcrepresentationitem.htm) and so that would be the place to start to understand what types of geometry definitions are used by IFC. Other items within the model (namely furnishings) are far more likely to be represented by raw tessellated data (IfcFacetedBrep, https://standards.buildingsmart.org/IFC/RELEASE/IFC4_1/FINAL/HTML/schema/ifcgeometricmodelresource/lexical/ifcfacetedbrep.htm) which is geometry that would be more familiar to you, and there is a chance you can isolate these definitions within in an IFC file and concentrate on processing that (you would still need to understand STEP format, namely the inverse attributes involved, in order to faithfully generate the mesh geometry). Also this geometry could be either explicitly located (in world space), but in many cases is also positioned through IfcPlacements (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometryresource/lexical/ifcaxis2placement3d.htm) locally, so you need to build up the hierarchy of transformations based on these definitions.&#xD;&#xA;&#xD;&#xA;In short, if you wanted to RYO IFC parser to grab geometry, it would be a steep learning curve and require you to understand many other concepts of STEP/IFC outside just knowing the geometry types and transforms. Easier to use an IFC library coupled with a geometry library (although many IFC libs do come with geometry libs to do this for you), but even then, depending on the lib used, you may need to have a basic understanding of the building hierarchy involved in order to correctly place and reconstruct much of the geometry.&#xD;&#xA;&#xD;&#xA;Also note, while many of the geometry concepts remain the same through the various versions of IFC (IFc2x3, IFC4, IFC4 ADD1 etc), in some cases there are subtle differences in the schema in relation to geometry object definitions. However much of the version difference in IFC is do to with the building hierarchy, and associated information for the various disciplines in AEC.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26516" PostHistoryTypeId="5" PostId="9625" RevisionGUID="3f8d5823-bf4f-485a-8c25-a985363ed14c" CreationDate="2020-03-03T23:13:20.283" UserId="9438" Comment="typo" Text="You need to learn and understand STEP data exchange format (ISO 10303-21) which is the fundamental exchange format which the IFC schema is built on top of. This is no easy feat though, especially when comparing to a file format such as OBJ. OBJ files are designed to define geometry (and other information via associated MTL) as so are optimised for this purpose. IFC on the other hand is designed to exchange many aspects of AEC including building, services, structural, furnishings, energy model etc and so is far more complex with the geometry definitions being only a subset of the information supplied in an IFC. It would be easier to use an existing IFC library to do this, and even then, an understanding of the structure of the IFC entities and their hierarchy is still required to traverse the relationships (inverse attributes) between the object definitions in an IFC file in order to reconstruct the desired geometry.&#xD;&#xA;&#xD;&#xA;OBJ files explicitly define the vertices, normals and faces that represent a mesh, however while there are IFC entities which can represent meshes in a similar fashion (namely IfcConnectedFaceSet), most geometry defined in an IFC file should be considered more like a series of instructions/commands to recreate the geometry. For this reason you would also require a geometry library (one which can do things like extrusions, Boolean/CSG operations, curves, NURBS etc). For example, one of the main things that is represented in many IFC files would be the walls, doors, windows etc of a building, and while these could be represented as explicit tessellated data or breps, in my experience these tend to be represented as an IfcExtrudedAreaSolid (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometricmodelresource/lexical/ifcextrudedareasolid.htm) which supplies the direction and length to extrude a path/outline curve (the curve being defined by an IfcProfileDef which is related to the IfcExtrudedAreaSolid through an inverse attribute, https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcprofileresource/lexical/ifcprofiledef.htm). This gets even more complicated when there is an opening (i.e window recess or door opening in the wall) which again is related (through an inverse attribute) to the geometry representing the opening to be removed through a geometric Boolean operation (CSG). As you can see it starts to get complicated fairly quickly and isn't just a case of reading in raw vertices, normals and faces etc.&#xD;&#xA;&#xD;&#xA;All geometry in an IFC file is defined by objects which are sub types of IfcRepresentationItem (http://dcom.arch.gatech.edu/aci/cic/schema/ifcgeometryresource/lexical/ifcrepresentationitem.htm) and so that would be the place to start to understand what types of geometry definitions are used by IFC. Other items within the model (namely furnishings) are far more likely to be represented by raw tessellated data (IfcFacetedBrep, https://standards.buildingsmart.org/IFC/RELEASE/IFC4_1/FINAL/HTML/schema/ifcgeometricmodelresource/lexical/ifcfacetedbrep.htm) which is geometry that would be more familiar to you, and there is a chance you can isolate these definitions within in an IFC file and concentrate on processing that (you would still need to understand STEP format, namely the inverse attributes involved, in order to faithfully generate the mesh geometry). Also this geometry could be either explicitly located (in world space), but in many cases is also positioned through IfcPlacements (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometryresource/lexical/ifcaxis2placement3d.htm) locally, so you need to build up the hierarchy of transformations based on these definitions.&#xD;&#xA;&#xD;&#xA;In short, if you wanted to RYO IFC parser to grab geometry, it would be a steep learning curve and require you to understand many other concepts of STEP/IFC outside just knowing the geometry types and transforms. Easier to use an IFC library coupled with a geometry library (although many IFC libs do come with geometry libs to do this for you), but even then, depending on the lib used, you may need to have a basic understanding of the building hierarchy involved in order to correctly place and reconstruct much of the geometry.&#xD;&#xA;&#xD;&#xA;Also note, while many of the geometry concepts remain the same through the various versions of IFC (IFc2x3, IFC4, IFC4 ADD1 etc), in some cases there are subtle differences in the schema in relation to geometry object definitions. However much of the version difference in IFC is do to with the building hierarchy, and associated information for the various disciplines in AEC.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26517" PostHistoryTypeId="5" PostId="9625" RevisionGUID="8cdd0e3d-77bd-40ee-8117-6200aece2e94" CreationDate="2020-03-03T23:39:41.050" UserId="9438" Comment="deleted 28 characters in body" Text="You need to learn and understand STEP data exchange format (ISO 10303-21) which is the fundamental exchange format which the IFC schema is built on top of. This is no easy feat though, especially when comparing to a file format such as OBJ. OBJ files are designed to define geometry (and other information via associated MTL) as so are optimised for this purpose. IFC on the other hand is designed to exchange many aspects of AEC including building, services, structural, furnishings, energy model etc and so is far more complex with the geometry definitions being only a subset of the information supplied in an IFC. It would be easier to use an existing IFC library to do this, and even then, an understanding of the structure of the IFC entities and their hierarchy is still required to traverse the relationships (inverse attributes) between the object definitions in an IFC file in order to reconstruct the desired geometry.&#xD;&#xA;&#xD;&#xA;OBJ files explicitly define the vertices, normals and faces that represent a mesh, however while there are IFC entities which can represent meshes in a similar fashion (namely IfcConnectedFaceSet), most geometry defined in an IFC file should be considered more like a series of instructions/commands to recreate the geometry. For this reason you would also require a geometry library (one which can do things like extrusions, Boolean/CSG operations, curves, NURBS etc). For example, one of the main things that is represented in many IFC files would be the walls, doors, windows etc of a building, and while these could be represented as explicit tessellated data or breps, in my experience these tend to be represented as an IfcExtrudedAreaSolid (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometricmodelresource/lexical/ifcextrudedareasolid.htm) which supplies the direction and length to extrude a path/outline curve (the curve being defined by an IfcProfileDef which is an attribute of IfcExtrudedAreaSolid, https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcprofileresource/lexical/ifcprofiledef.htm). This gets even more complicated when there is an opening (i.e window recess or door opening in the wall) which again is related (through an inverse attribute) to the geometry representing the opening to be removed through a geometric Boolean operation (CSG). As you can see it starts to get complicated fairly quickly and isn't just a case of reading in raw vertices, normals and faces etc.&#xD;&#xA;&#xD;&#xA;All geometry in an IFC file is defined by objects which are sub types of IfcRepresentationItem (http://dcom.arch.gatech.edu/aci/cic/schema/ifcgeometryresource/lexical/ifcrepresentationitem.htm) and so that would be the place to start to understand what types of geometry definitions are used by IFC. Other items within the model (namely furnishings) are far more likely to be represented by raw tessellated data (IfcFacetedBrep, https://standards.buildingsmart.org/IFC/RELEASE/IFC4_1/FINAL/HTML/schema/ifcgeometricmodelresource/lexical/ifcfacetedbrep.htm) which is geometry that would be more familiar to you, and there is a chance you can isolate these definitions within in an IFC file and concentrate on processing that (you would still need to understand STEP format, namely the inverse attributes involved, in order to faithfully generate the mesh geometry). Also this geometry could be either explicitly located (in world space), but in many cases is also positioned through IfcPlacements (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometryresource/lexical/ifcaxis2placement3d.htm) locally, so you need to build up the hierarchy of transformations based on these definitions.&#xD;&#xA;&#xD;&#xA;In short, if you wanted to RYO IFC parser to grab geometry, it would be a steep learning curve and require you to understand many other concepts of STEP/IFC outside just knowing the geometry types and transforms. Easier to use an IFC library coupled with a geometry library (although many IFC libs do come with geometry libs to do this for you), but even then, depending on the lib used, you may need to have a basic understanding of the building hierarchy involved in order to correctly place and reconstruct much of the geometry.&#xD;&#xA;&#xD;&#xA;Also note, while many of the geometry concepts remain the same through the various versions of IFC (IFc2x3, IFC4, IFC4 ADD1 etc), in some cases there are subtle differences in the schema in relation to geometry object definitions. However much of the version difference in IFC is do to with the building hierarchy, and associated information for the various disciplines in AEC.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26518" PostHistoryTypeId="2" PostId="9626" RevisionGUID="e0322e58-7840-4dd4-8ceb-a96f4f4b5be4" CreationDate="2020-03-04T12:28:51.183" UserId="11191" Text="I have created a 3D animation with a perspective projection of white circles moving randomly in a fake 3D space projected on a 2D computer screen (GIF 1). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Since I need to keep the same number of visible circles, every time a circle disappears from the frame, I have to create a new visible one within the frame. To do so, I have written this piece of code:&#xD;&#xA;&#xD;&#xA;- First I created initial coordinates and the two angles of movements (spherical coordinates):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;        for circle in circles:&#xD;&#xA;    &#xD;&#xA;            circle.position.xy = np.random.uniform(-25, 25, size=2)&#xD;&#xA;            z = np.random.uniform(near_z, far_z)&#xD;&#xA;    &#xD;&#xA;            circle.position.z = z&#xD;&#xA;            circle.position.x *= z/-50&#xD;&#xA;            circle.position.y *= z/-50&#xD;&#xA;    &#xD;&#xA;            circle.theta_deg = np.random.rand(1) * 360&#xD;&#xA;            circle.phi_deg = np.random.rand(1) * 360&#xD;&#xA;    &#xD;&#xA;            theta_rad = circle.theta_deg * np.pi / 180&#xD;&#xA;            phi_rad = circle.phi_deg* np.pi / 180&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            circle.dx = speed * np.sin(-phi_rad - theta_rad) / frameRate&#xD;&#xA;            circle.dy = -speed * np.cos(phi_rad + theta_rad) / frameRate&#xD;&#xA;            circle.dz = -speed * np.cos(theta_rad) / frameRate&#xD;&#xA;&#xD;&#xA; - Then, in the loop that plays the animation, and updates the position of each circle, I have put this condition following the same answer that was provided to the same kind of issue [here][2]:&#xD;&#xA;&#xD;&#xA;            max_dist = max(abs(circle.position.x),abs(circle.position.y))&#xD;&#xA;            limit_dist = 25 * abs((circle.position.z-near_z) / far_z)&#xD;&#xA;&#xD;&#xA;            z_rel = np.random.uniform(near_z,far_z)&#xD;&#xA;&#xD;&#xA;            if max_dist &gt; limit_dist: &#xD;&#xA;                circle.position.x = np.random.uniform(-25, 25) * z_rel/far_z&#xD;&#xA;                circle.position.y = np.random.uniform(-25, 25) * z_rel/far_z&#xD;&#xA;&#xD;&#xA;I got a weird result as shown in GIF 2&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What is wrong with my condition and how can I detect a circle that disappears from the frame and recreate one inside the frame? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LWqA7.gif&#xD;&#xA;  [2]: https://stackoverflow.com/questions/58917165/keep-constant-number-of-visible-spheres-in-front-of-the-camera-in-3d-animation&#xD;&#xA;  [3]: https://i.stack.imgur.com/k5leO.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="26519" PostHistoryTypeId="1" PostId="9626" RevisionGUID="e0322e58-7840-4dd4-8ceb-a96f4f4b5be4" CreationDate="2020-03-04T12:28:51.183" UserId="11191" Text="Keep constant number of visible circles in 3D animation" ContentLicense="CC BY-SA 4.0" />
  <row Id="26520" PostHistoryTypeId="3" PostId="9626" RevisionGUID="e0322e58-7840-4dd4-8ceb-a96f4f4b5be4" CreationDate="2020-03-04T12:28:51.183" UserId="11191" Text="|opengl|3d|projections|perspective|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26521" PostHistoryTypeId="5" PostId="9625" RevisionGUID="5f88caa0-72c9-4d5e-95c7-02373b1d7f1d" CreationDate="2020-03-04T13:24:09.287" UserId="9438" Comment="typos and grammos" Text="You need to learn and understand STEP data exchange format (ISO 10303-21) which is the fundamental exchange format which the IFC schema is built on top of. This is no easy feat though, especially when comparing to a file format such as OBJ. OBJ files are designed to define geometry (and other information via associated MTL) and so are optimised for this purpose. IFC on the other hand, is designed to exchange many aspects of AEC including building, services, structural, furnishings, energy model etc and so is far more complex with the geometry definitions being only a subset of the information supplied in an IFC. It would be easier to use an existing IFC library to do this, and even then, an understanding of the structure of the IFC entities and their hierarchy is still required to traverse the relationships (inverse attributes) between the object definitions in an IFC file in order to reconstruct the desired geometry.&#xD;&#xA;&#xD;&#xA;OBJ files explicitly define the vertices, normals and faces that represent a mesh, however while there are IFC entities which can represent meshes in a similar fashion (namely IfcConnectedFaceSet), most geometry defined in an IFC file should be considered more like a series of instructions/commands to recreate the geometry. For this reason you would also require a geometry library (one which can do things like extrusions, Boolean/CSG operations, curves, NURBS etc). For example, one of the main things that is represented in many IFC files would be the walls, doors, windows etc of a building, and while these could be represented as explicit tessellated data or breps, in my experience these tend to be represented as an IfcExtrudedAreaSolid (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometricmodelresource/lexical/ifcextrudedareasolid.htm) which supplies the direction and length to extrude a path/outline curve (the curve being defined by an IfcProfileDef which is an attribute of IfcExtrudedAreaSolid, https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcprofileresource/lexical/ifcprofiledef.htm). This gets even more complicated when there is an opening (i.e window recess or door opening in the wall) which again is related (through an inverse attribute) to the geometry representing the opening to be removed through a geometric Boolean operation (CSG). As you can see it starts to get complicated fairly quickly and isn't just a case of reading in raw vertices, normals and faces etc.&#xD;&#xA;&#xD;&#xA;All geometry in an IFC file is defined by objects which are sub types of IfcRepresentationItem (http://dcom.arch.gatech.edu/aci/cic/schema/ifcgeometryresource/lexical/ifcrepresentationitem.htm) and so that would be the place to start to understand what types of geometry definitions are used by IFC. Other items within the model (namely furnishings) are far more likely to be represented by raw tessellated data (IfcFacetedBrep, https://standards.buildingsmart.org/IFC/RELEASE/IFC4_1/FINAL/HTML/schema/ifcgeometricmodelresource/lexical/ifcfacetedbrep.htm) which is geometry that would be more familiar to you, and there is a chance you can isolate these definitions within in an IFC file and concentrate on processing that (you would still need to understand STEP format, namely the inverse attributes involved, in order to faithfully generate the mesh geometry). Also this geometry could be either explicitly located (in world space), but in many cases is also positioned through IfcPlacements (https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcgeometryresource/lexical/ifcaxis2placement3d.htm) locally, so you need to build up the hierarchy of transformations based on these definitions.&#xD;&#xA;&#xD;&#xA;In short, if you wanted to RYO IFC parser to grab geometry, it would be a steep learning curve and require you to understand many other concepts of STEP/IFC outside just knowing the geometry types and transforms. Easier to use an IFC library coupled with a geometry library (although many IFC libs do come with geometry libs to do this for you), but even then, depending on the lib used, you may need to have a basic understanding of the building hierarchy involved in order to correctly place and reconstruct much of the geometry.&#xD;&#xA;&#xD;&#xA;Also note, while many of the geometry concepts remain the same through the various versions of IFC (IFc2x3, IFC4, IFC4 ADD1 etc), in some cases there are subtle differences in the schema in relation to geometry object definitions. However, much of the version difference in IFC is do to with the building hierarchy, and associated information for the various disciplines in AEC.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26522" PostHistoryTypeId="50" PostId="8888" RevisionGUID="055d90dc-239a-4704-b081-3c73e40a251e" CreationDate="2020-03-04T15:02:15.240" UserId="-1" />
  <row Id="26523" PostHistoryTypeId="50" PostId="9384" RevisionGUID="e46ab63c-08cb-43fa-8df8-b0abceeec05e" CreationDate="2020-03-04T17:05:40.733" UserId="-1" />
  <row Id="26526" PostHistoryTypeId="5" PostId="9589" RevisionGUID="7b70e7e0-a890-4af8-b5ea-23ea37763f8b" CreationDate="2020-03-05T07:55:06.170" UserId="9254" Comment="added 3457 characters in body" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xD;&#xA;&#xD;&#xA;The authors write:&#xD;&#xA;&#xD;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xD;&#xA;&#xD;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xD;&#xA;&#xD;&#xA;For simplicity, assume that we are considering a fixed path length $k\in\mathbb N$ and a fixed $(s,t)$-strategy. Formally, let&#xD;&#xA;&#xD;&#xA; - $M$ denote the scene surface set, $\mathcal B(M)$ denote the Borel $\sigma$-algebra on $M$ and $\sigma_M$ denote the surface measure on $\mathcal B(M)$&#xD;&#xA; - $E:=M^{\{0,\:\ldots\:,\:,k\}}$, $\mathcal E:={\mathcal B(M)}^{\otimes\{0,\:\ldots\:,\:,k\}}$ and $\lambda:=\sigma_M^{\otimes\{0,\:\ldots\:,\:,k\}}$&#xD;&#xA; - $f:E\to[0,\infty)^3$ denote the measurement contribution function&#xD;&#xA; - $q$ be the probability density on $(E,\mathcal E,\lambda)$ corresponding to the $(s,t)$-strategy satisfying $\{q=0\}\subseteq\{f=0\}$&#xD;&#xA;&#xD;&#xA;Once more, for simplicity, assume that the generated $(E,\mathcal E)$-valued chain $(X_n)_{n\in\mathbb N}$ is independent and $$X_n\sim q\lambda\;\;\;\text{for all }n\in\mathbb N.$$ If it's easier to understand for you, you might want to take a look at the `importance_sampling_integrator::render()` method in [this code](https://coliru.stacked-crooked.com/view?id=7f55a67c5e1dab10), where I've implemented these simplifications.&#xD;&#xA;&#xD;&#xA;Now let's consider the measurement of a single pixel value $$I:=\int hf\:{\rm d}\lambda,$$ where $h:E\to[0,\infty)$ is the image reconstruction filter corresponding to this pixel. Assume (as PBRT does) that $h$ is a Box filter with radius 1/2. So, if $\psi:E\to R$ is the canonical mapping from the path space $E$ to the raster space $R=[0,a)\times[0,b)$, where $a\in\mathbb N$ and $b\in\mathbb N$ are the vertical and horizontal resolution of the image, respectively, and the pixel we've fixed is pixel $(i,j)\in J:=\{0,\ldots,a-1\}\times\{0,\ldots,b-1\}$ then $h$ is simply the indicator function of the set $$B:=\left\{x\in E:\psi(x)\in\underbrace{[i,i+1)\times[j,j+1)}_{=:\:R_{(i,\:j)}}\right\},$$ i.e. $h=1_B$. Now let $$U_n:=\psi(X_n)\;\;\;\text{for }n\in\mathbb N$$ and note that, by construction of $q$, $$U_n\sim\mathcal U_R\;\;\;\text{for all }n\in\mathbb N\tag1,$$ where $\mathcal U_R$ denotes the uniform distribution on $R$. This immediately yields that $$(q\lambda)(B)=\mathcal U_R\left(R_{(i,\:j)}\right)=\frac1{|J|}\tag2.$$&#xD;&#xA;&#xD;&#xA;&gt; Let $$g(x):=h(x)\left.\begin{cases}\displaystyle\frac fq(x)&amp;\text{, if }q(x)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\;\;\;\text{for }x\in E.$$ Now the naive estimator for $I$ is $$\frac1n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty} I\;\;\;\text{almost surely}\tag3.$$ However, if I implement this (which corresponds to replacing `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_sampler-&gt;samplesPerPixel);` in the last line of `importance_sampling_integrator::render()` by `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_n);`), I end up with a black image. This is not surprising, since due to the very small support of $h$ compared to the whole image, only very few terms contribute to the sum in $(3)$.&#xD;&#xA;&#xD;&#xA;So, it seems like that one needs to consider ony the visits of $(X_n)_{n\in\mathbb N}$ to the set $B$, i.e. consider the process $$Y_k:=X_{\tau_k}\;\;\;\text{for }k\in\mathbb N$$ instead, where $\tau_0:=0$, $$\tau_k:=\inf\left\{n&gt;\tau_{k-1}:X_n\in B\right\}\;\;\;\text{for }k\in\mathbb N.$$ It's easy to see that $(Y_k)_{k\in\mathbb N}$ is independent with $$Y_n\sim (q\lambda)\left[\;\cdot\mid B\right]\;\;\;\text{for all }k\in\mathbb N\tag4.$$ Moreover, $$\frac1k\sum_{i=1}^kg(Y_i)\xrightarrow{k\to\infty}(q\lambda)\left[g\mid B\right]=|J|I\tag5$$ by $(2)$.&#xD;&#xA;&#xD;&#xA;&gt; Now what the code does is independently drawing $X_1,\ldots,X_n\sim q\lambda$, where $$n=n_0|J|\tag6$$ for some $n_0\in\mathbb N$ (called `mutationsPerPixel` in PBRT).&#xD;&#xA;&#xD;&#xA;We may consider the number $$N_n:=\sum_{i=1}^n1_B(X_i)$$ of visits to $B$ up to time $n$ and note that $$\operatorname E\left[N_n\right]=\frac n{|J|}\tag7$$ and $$\frac{N_n}n\xrightarrow{n\to\infty}\frac1{|J|}\;\;\;\text{almost surely}.\tag8$$&#xD;&#xA;&#xD;&#xA;&gt; Now PBRT (and the code I've provided above as well) uses the estimatr $$\frac1{n_0}\sum_{i=1}^ng(X_i)=\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i),$$ but I absolutely don't understand why this works. From $(5)$ we should obtain $$\frac1{\operatorname E\left[N_n\right]\sum_{i=1}^{N_n}g(Y_i)=\frac{|J|}n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty}|J|I\tag9$$ almost surely, but the left-hand side of $(9)$, dividied by $|J|$, is once again the pracitcally not working estimator $(3)$.&#xD;&#xA;&#xD;&#xA;&gt; What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26527" PostHistoryTypeId="33" PostId="9589" RevisionGUID="eaa1fc4c-4cb8-48bd-82f0-d7919d74f34e" CreationDate="2020-03-05T07:55:17.510" UserId="9254" Comment="60" />
  <row Id="26528" PostHistoryTypeId="5" PostId="9589" RevisionGUID="48cdcbf4-37c6-44f9-8a67-fa201c4f9009" CreationDate="2020-03-05T08:01:01.903" UserId="9254" Comment="added 1 character in body" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xD;&#xA;&#xD;&#xA;The authors write:&#xD;&#xA;&#xD;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xD;&#xA;&#xD;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xD;&#xA;&#xD;&#xA;For simplicity, assume that we are considering a fixed path length $k\in\mathbb N$ and a fixed $(s,t)$-strategy. Formally, let&#xD;&#xA;&#xD;&#xA; - $M$ denote the scene surface set, $\mathcal B(M)$ denote the Borel $\sigma$-algebra on $M$ and $\sigma_M$ denote the surface measure on $\mathcal B(M)$&#xD;&#xA; - $E:=M^{\{0,\:\ldots\:,\:,k\}}$, $\mathcal E:={\mathcal B(M)}^{\otimes\{0,\:\ldots\:,\:,k\}}$ and $\lambda:=\sigma_M^{\otimes\{0,\:\ldots\:,\:,k\}}$&#xD;&#xA; - $f:E\to[0,\infty)^3$ denote the measurement contribution function&#xD;&#xA; - $q$ be the probability density on $(E,\mathcal E,\lambda)$ corresponding to the $(s,t)$-strategy satisfying $\{q=0\}\subseteq\{f=0\}$&#xD;&#xA;&#xD;&#xA;Once more, for simplicity, assume that the generated $(E,\mathcal E)$-valued chain $(X_n)_{n\in\mathbb N}$ is independent and $$X_n\sim q\lambda\;\;\;\text{for all }n\in\mathbb N.$$ If it's easier to understand for you, you might want to take a look at the `importance_sampling_integrator::render()` method in [this code](https://coliru.stacked-crooked.com/view?id=7f55a67c5e1dab10), where I've implemented these simplifications.&#xD;&#xA;&#xD;&#xA;Now let's consider the measurement of a single pixel value $$I:=\int hf\:{\rm d}\lambda,$$ where $h:E\to[0,\infty)$ is the image reconstruction filter corresponding to this pixel. Assume (as PBRT does) that $h$ is a Box filter with radius 1/2. So, if $\psi:E\to R$ is the canonical mapping from the path space $E$ to the raster space $R=[0,a)\times[0,b)$, where $a\in\mathbb N$ and $b\in\mathbb N$ are the vertical and horizontal resolution of the image, respectively, and the pixel we've fixed is pixel $(i,j)\in J:=\{0,\ldots,a-1\}\times\{0,\ldots,b-1\}$ then $h$ is simply the indicator function of the set $$B:=\left\{x\in E:\psi(x)\in\underbrace{[i,i+1)\times[j,j+1)}_{=:\:R_{(i,\:j)}}\right\},$$ i.e. $h=1_B$. Now let $$U_n:=\psi(X_n)\;\;\;\text{for }n\in\mathbb N$$ and note that, by construction of $q$, $$U_n\sim\mathcal U_R\;\;\;\text{for all }n\in\mathbb N\tag1,$$ where $\mathcal U_R$ denotes the uniform distribution on $R$. This immediately yields that $$(q\lambda)(B)=\mathcal U_R\left(R_{(i,\:j)}\right)=\frac1{|J|}\tag2.$$&#xD;&#xA;&#xD;&#xA;&gt; Let $$g(x):=h(x)\left.\begin{cases}\displaystyle\frac fq(x)&amp;\text{, if }q(x)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\;\;\;\text{for }x\in E.$$ Now the naive estimator for $I$ is $$\frac1n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty} I\;\;\;\text{almost surely}\tag3.$$ However, if I implement this (which corresponds to replacing `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_sampler-&gt;samplesPerPixel);` in the last line of `importance_sampling_integrator::render()` by `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_n);`), I end up with a black image. This is not surprising, since due to the very small support of $h$ compared to the whole image, only very few terms contribute to the sum in $(3)$.&#xD;&#xA;&#xD;&#xA;So, it seems like that one needs to consider ony the visits of $(X_n)_{n\in\mathbb N}$ to the set $B$, i.e. consider the process $$Y_k:=X_{\tau_k}\;\;\;\text{for }k\in\mathbb N$$ instead, where $\tau_0:=0$, $$\tau_k:=\inf\left\{n&gt;\tau_{k-1}:X_n\in B\right\}\;\;\;\text{for }k\in\mathbb N.$$ It's easy to see that $(Y_k)_{k\in\mathbb N}$ is independent with $$Y_n\sim (q\lambda)\left[\;\cdot\mid B\right]\;\;\;\text{for all }k\in\mathbb N\tag4.$$ Moreover, $$\frac1k\sum_{i=1}^kg(Y_i)\xrightarrow{k\to\infty}(q\lambda)\left[g\mid B\right]=|J|I\tag5$$ by $(2)$.&#xD;&#xA;&#xD;&#xA;&gt; Now what the code does is independently drawing $X_1,\ldots,X_n\sim q\lambda$, where $$n=n_0|J|\tag6$$ for some $n_0\in\mathbb N$ (called `mutationsPerPixel` in PBRT).&#xD;&#xA;&#xD;&#xA;We may consider the number $$N_n:=\sum_{i=1}^n1_B(X_i)$$ of visits to $B$ up to time $n$ and note that $$\operatorname E\left[N_n\right]=\frac n{|J|}\tag7$$ and $$\frac{N_n}n\xrightarrow{n\to\infty}\frac1{|J|}\;\;\;\text{almost surely}.\tag8$$&#xD;&#xA;&#xD;&#xA;&gt; Now PBRT (and the code I've provided above as well) uses the estimator $$\frac1{n_0}\sum_{i=1}^ng(X_i)=\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i),$$ but I absolutely don't understand why this works. From $(5)$ we should obtain $$\frac1{\operatorname E\left[N_n\right]\sum_{i=1}^{N_n}g(Y_i)=\frac{|J|}n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty}|J|I\tag9$$ almost surely, but the left-hand side of $(9)$, dividied by $|J|$, is once again the pracitcally not working estimator $(3)$.&#xD;&#xA;&#xD;&#xA;&gt; What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26529" PostHistoryTypeId="5" PostId="9589" RevisionGUID="cfab5ffe-aa57-4e52-8197-98c3131aa373" CreationDate="2020-03-05T09:42:24.173" UserId="9254" Comment="added 7 characters in body" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xD;&#xA;&#xD;&#xA;The authors write:&#xD;&#xA;&#xD;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xD;&#xA;&#xD;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xD;&#xA;&#xD;&#xA;For simplicity, assume that we are considering a fixed path length $k\in\mathbb N$ and a single fixed $(s,t)$-strategy. Formally, let&#xD;&#xA;&#xD;&#xA; - $M$ denote the scene surface set, $\mathcal B(M)$ denote the Borel $\sigma$-algebra on $M$ and $\sigma_M$ denote the surface measure on $\mathcal B(M)$&#xD;&#xA; - $E:=M^{\{0,\:\ldots\:,\:,k\}}$, $\mathcal E:={\mathcal B(M)}^{\otimes\{0,\:\ldots\:,\:,k\}}$ and $\lambda:=\sigma_M^{\otimes\{0,\:\ldots\:,\:,k\}}$&#xD;&#xA; - $f:E\to[0,\infty)^3$ denote the measurement contribution function&#xD;&#xA; - $q$ be the probability density on $(E,\mathcal E,\lambda)$ corresponding to the $(s,t)$-strategy satisfying $\{q=0\}\subseteq\{f=0\}$&#xD;&#xA;&#xD;&#xA;Once more, for simplicity, assume that the generated $(E,\mathcal E)$-valued chain $(X_n)_{n\in\mathbb N}$ is independent and $$X_n\sim q\lambda\;\;\;\text{for all }n\in\mathbb N.$$ If it's easier to understand for you, you might want to take a look at the `importance_sampling_integrator::render()` method in [this code](https://coliru.stacked-crooked.com/view?id=7f55a67c5e1dab10), where I've implemented these simplifications.&#xD;&#xA;&#xD;&#xA;Now let's consider the measurement of a single pixel value $$I:=\int hf\:{\rm d}\lambda,$$ where $h:E\to[0,\infty)$ is the image reconstruction filter corresponding to this pixel. Assume (as PBRT does) that $h$ is a Box filter with radius 1/2. So, if $\psi:E\to R$ is the canonical mapping from the path space $E$ to the raster space $R=[0,a)\times[0,b)$, where $a\in\mathbb N$ and $b\in\mathbb N$ are the vertical and horizontal resolution of the image, respectively, and the pixel we've fixed is pixel $(i,j)\in J:=\{0,\ldots,a-1\}\times\{0,\ldots,b-1\}$ then $h$ is simply the indicator function of the set $$B:=\left\{x\in E:\psi(x)\in\underbrace{[i,i+1)\times[j,j+1)}_{=:\:R_{(i,\:j)}}\right\},$$ i.e. $h=1_B$. Now let $$U_n:=\psi(X_n)\;\;\;\text{for }n\in\mathbb N$$ and note that, by construction of $q$, $$U_n\sim\mathcal U_R\;\;\;\text{for all }n\in\mathbb N\tag1,$$ where $\mathcal U_R$ denotes the uniform distribution on $R$. This immediately yields that $$(q\lambda)(B)=\mathcal U_R\left(R_{(i,\:j)}\right)=\frac1{|J|}\tag2.$$&#xD;&#xA;&#xD;&#xA;&gt; Let $$g(x):=h(x)\left.\begin{cases}\displaystyle\frac fq(x)&amp;\text{, if }q(x)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\;\;\;\text{for }x\in E.$$ Now the naive estimator for $I$ is $$\frac1n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty} I\;\;\;\text{almost surely}\tag3.$$ However, if I implement this (which corresponds to replacing `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_sampler-&gt;samplesPerPixel);` in the last line of `importance_sampling_integrator::render()` by `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_n);`), I end up with a black image. This is not surprising, since due to the very small support of $h$ compared to the whole image, only very few terms contribute to the sum in $(3)$.&#xD;&#xA;&#xD;&#xA;So, it seems like that one needs to consider only the visits of $(X_n)_{n\in\mathbb N}$ to the set $B$, i.e. consider the process $$Y_k:=X_{\tau_k}\;\;\;\text{for }k\in\mathbb N$$ instead, where $\tau_0:=0$, $$\tau_k:=\inf\left\{n&gt;\tau_{k-1}:X_n\in B\right\}\;\;\;\text{for }k\in\mathbb N.$$ It's easy to see that $(Y_k)_{k\in\mathbb N}$ is independent with $$Y_n\sim (q\lambda)\left[\;\cdot\mid B\right]\;\;\;\text{for all }k\in\mathbb N\tag4.$$ Moreover, $$\frac1k\sum_{i=1}^kg(Y_i)\xrightarrow{k\to\infty}(q\lambda)\left[g\mid B\right]=|J|I\tag5$$ by $(2)$.&#xD;&#xA;&#xD;&#xA;&gt; Now what the code does is independently drawing $X_1,\ldots,X_n\sim q\lambda$, where $$n=n_0|J|\tag6$$ for some $n_0\in\mathbb N$ (called `mutationsPerPixel` in PBRT).&#xD;&#xA;&#xD;&#xA;We may consider the number $$N_n:=\sum_{i=1}^n1_B(X_i)$$ of visits to $B$ up to time $n$ and note that $$\operatorname E\left[N_n\right]=\frac n{|J|}\tag7$$ and $$\frac{N_n}n\xrightarrow{n\to\infty}\frac1{|J|}\;\;\;\text{almost surely}.\tag8$$&#xD;&#xA;&#xD;&#xA;&gt; Now PBRT (and the code I've provided above as well) uses the estimator $$\frac1{n_0}\sum_{i=1}^ng(X_i)=\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i),$$ but I absolutely don't understand why this works. From $(5)$ we should obtain $$\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i)=\frac{|J|}n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty}|J|I\tag9$$ almost surely, but the left-hand side of $(9)$, dividied by $|J|$, is once again the pracitcally not working estimator $(3)$.&#xD;&#xA;&#xD;&#xA;&gt; What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26534" PostHistoryTypeId="2" PostId="9629" RevisionGUID="d192320b-2211-451f-b444-6d0380e22537" CreationDate="2020-03-05T09:59:46.053" UserId="9669" Text="This is easy to do in javascript or gl, but for expediency let's do it in mathematica. We first need the background image and an alpha mask:&#xD;&#xA;&#xD;&#xA;    bg = ImageRotate[&#xD;&#xA;       LinearGradientImage[&#xD;&#xA;        RGBColor @@@ {{0.024, 0.051, 0.125}, {0.122, 0.078, &#xD;&#xA;           0.212}, {0.216, 0.102, 0.275}, {0.216, 0.102, 0.275}}, {300, &#xD;&#xA;         Round[300*1.394]}], -90 \[Degree]]&#xD;&#xA;    &#xD;&#xA;    mask = ImageRotate[&#xD;&#xA;       LinearGradientImage[{Sequence @@ Table[RGBColor[0, 0, 0, 0], 5],&#xD;&#xA;         RGBColor[0.09, 0.07, 0.196, .3],&#xD;&#xA;         RGBColor[0.09, 0.07, 0.196, .9], &#xD;&#xA;         RGBColor[0.023, 0.050, 0.125, 1]},&#xD;&#xA;        {300, Round[300*1.394]}], 90 \[Degree]]&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now we can draw the grid in 3D space using infinite lines:&#xD;&#xA;&#xD;&#xA;    grid[j_ : 5] := Module[{g3d, b},&#xD;&#xA;      Overlay[{Image[bg, ImageSize -&gt; All], &#xD;&#xA;        g3d = Graphics3D[{Thickness[0.005],RGBColor[0.905, 0.352, 0.713],&#xD;&#xA;           Sequence @@ Table[InfiniteLine[{{0, i + j, 0}, {1, i + j, 0}}], {i, -10, 20}],&#xD;&#xA;           Table[InfiniteLine[{{i, 0, 0}, {i, 1, 0}}], {i, -20, 20}]}, &#xD;&#xA;          Boxed -&gt; False, ViewAngle -&gt; Pi/3, ViewVector -&gt; {{0, -5, 6}, {0, -1, 2}}, Background -&gt; None, PlotRange -&gt; All, ImageSize -&gt; is], &#xD;&#xA;        b = Blur[Rasterize[g3d, RasterSize -&gt; is], {20, 20}];&#xD;&#xA;        Image[SetAlphaChannel[b, ColorNegate@ColorConvert[b, &quot;Grayscale&quot;]], &#xD;&#xA;         ImageSize -&gt; is]}, {1, 3, 2}]&#xD;&#xA;      ]&#xD;&#xA;&#xD;&#xA;Lastly, make some frames and export the animation:&#xD;&#xA;&#xD;&#xA;    frames = Table[Overlay[{grid[j], Image[mask, ImageSize -&gt; All]}, All] , {j, 5, 6, .01}];&#xD;&#xA;    Export[&quot;~/grid.gif&quot;, frames, AnimationRepetitions -&gt; \[Infinity]]&#xD;&#xA;&#xD;&#xA;Et voila!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nTzUx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mjZG8.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="26535" PostHistoryTypeId="5" PostId="9589" RevisionGUID="8b7f4291-e71c-432d-a7ef-9f791d74295a" CreationDate="2020-03-05T10:38:08.003" UserId="9254" Comment="added 1937 characters in body" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xD;&#xA;&#xD;&#xA;The authors write:&#xD;&#xA;&#xD;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xD;&#xA;&#xD;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xD;&#xA;&#xD;&#xA;For simplicity, assume that we are considering a fixed path length $k\in\mathbb N$ and a single fixed $(s,t)$-strategy. Formally, let&#xD;&#xA;&#xD;&#xA; - $M$ denote the scene surface set, $\mathcal B(M)$ denote the Borel $\sigma$-algebra on $M$ and $\sigma_M$ denote the surface measure on $\mathcal B(M)$&#xD;&#xA; - $E:=M^{\{0,\:\ldots\:,\:,k\}}$, $\mathcal E:={\mathcal B(M)}^{\otimes\{0,\:\ldots\:,\:,k\}}$ and $\lambda:=\sigma_M^{\otimes\{0,\:\ldots\:,\:,k\}}$&#xD;&#xA; - $f:E\to[0,\infty)^3$ denote the measurement contribution function&#xD;&#xA; - $q$ be the probability density on $(E,\mathcal E,\lambda)$ corresponding to the $(s,t)$-strategy satisfying $\{q=0\}\subseteq\{f=0\}$&#xD;&#xA;&#xD;&#xA;Once more, for simplicity, assume that the generated $(E,\mathcal E)$-valued chain $(X_n)_{n\in\mathbb N}$ is independent and $$X_n\sim q\lambda\;\;\;\text{for all }n\in\mathbb N.$$ If it's easier to understand for you, you might want to take a look at the `importance_sampling_integrator::render()` method in [this code](https://coliru.stacked-crooked.com/view?id=7f55a67c5e1dab10), where I've implemented these simplifications.&#xD;&#xA;&#xD;&#xA;Now let's consider the measurement of a single pixel value $$I:=\int hf\:{\rm d}\lambda,$$ where $h:E\to[0,\infty)$ is the image reconstruction filter corresponding to this pixel. Assume (as PBRT does) that $h$ is a Box filter with radius 1/2. So, if $\psi:E\to R$ is the canonical mapping from the path space $E$ to the raster space $R=[0,a)\times[0,b)$, where $a\in\mathbb N$ and $b\in\mathbb N$ are the vertical and horizontal resolution of the image, respectively, and the pixel we've fixed is pixel $(i,j)\in J:=\{0,\ldots,a-1\}\times\{0,\ldots,b-1\}$ then $h$ is simply the indicator function of the set $$B:=\left\{x\in E:\psi(x)\in\underbrace{[i,i+1)\times[j,j+1)}_{=:\:R_{(i,\:j)}}\right\},$$ i.e. $h=1_B$. Now let $$U_n:=\psi(X_n)\;\;\;\text{for }n\in\mathbb N$$ and note that, by construction of $q$, $$U_n\sim\mathcal U_R\;\;\;\text{for all }n\in\mathbb N\tag1,$$ where $\mathcal U_R$ denotes the uniform distribution on $R$. This immediately yields that $$(q\lambda)(B)=\mathcal U_R\left(R_{(i,\:j)}\right)=\frac1{|J|}\tag2.$$&#xD;&#xA;&#xD;&#xA;&gt; Let $$g(x):=h(x)\left.\begin{cases}\displaystyle\frac fq(x)&amp;\text{, if }q(x)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\;\;\;\text{for }x\in E.$$ Now the naive estimator for $I$ is $$\frac1n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty} I\;\;\;\text{almost surely}\tag3.$$ However, if I implement this (which corresponds to replacing `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_sampler-&gt;samplesPerPixel);` in the last line of `importance_sampling_integrator::render()` by `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_n);`), I end up with a black image. This is not surprising, since due to the very small support of $h$ compared to the whole image, only very few terms contribute to the sum in $(3)$.&#xD;&#xA;&#xD;&#xA;So, it seems like that one needs to consider only the visits of $(X_n)_{n\in\mathbb N}$ to the set $B$, i.e. consider the process $$Y_k:=X_{\tau_k}\;\;\;\text{for }k\in\mathbb N$$ instead, where $\tau_0:=0$, $$\tau_k:=\inf\left\{n&gt;\tau_{k-1}:X_n\in B\right\}\;\;\;\text{for }k\in\mathbb N.$$ It's easy to see that $(Y_k)_{k\in\mathbb N}$ is independent with $$Y_n\sim (q\lambda)\left[\;\cdot\mid B\right]\;\;\;\text{for all }k\in\mathbb N\tag4.$$ Moreover, $$\frac1k\sum_{i=1}^kg(Y_i)\xrightarrow{k\to\infty}(q\lambda)\left[g\mid B\right]=|J|I\tag5$$ by $(2)$.&#xD;&#xA;&#xD;&#xA;&gt; Now what the code does is independently drawing $X_1,\ldots,X_n\sim q\lambda$, where $$n=n_0|J|\tag6$$ for some $n_0\in\mathbb N$ (called `mutationsPerPixel` in PBRT).&#xD;&#xA;&#xD;&#xA;We may consider the number $$N_n:=\sum_{i=1}^n1_B(X_i)$$ of visits to $B$ up to time $n$ and note that $$\operatorname E\left[N_n\right]=\frac n{|J|}\tag7$$ and $$\frac{N_n}n\xrightarrow{n\to\infty}\frac1{|J|}\;\;\;\text{almost surely}.\tag8$$&#xD;&#xA;&#xD;&#xA;&gt; Now PBRT (and the code I've provided above as well) uses the estimator $$\frac1{n_0}\sum_{i=1}^ng(X_i)=\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i),$$ but I absolutely don't understand why this works. From $(5)$ we should obtain $$\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i)=\frac{|J|}n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty}|J|I\tag9$$ almost surely, but the left-hand side of $(9)$, dividied by $|J|$, is once again the pracitcally not working estimator $(3)$.&#xD;&#xA;&#xD;&#xA;&gt; What am I missing?&#xD;&#xA;&#xD;&#xA;**EDIT**: Just to be completely sure I've built the image array by myself using the (supposed to be correct) estimator $(5)$:&#xD;&#xA;&#xD;&#xA;    void render(pbrt::Scene const&amp; scene)&#xD;&#xA;    {&#xD;&#xA;    	auto const light_distribution = pbrt::ComputeLightPowerDistribution(scene);&#xD;&#xA;    &#xD;&#xA;    	std::unordered_map&lt;pbrt::Light const*, std::size_t&gt; light_to_index;&#xD;&#xA;    	for (std::size_t i = 0; i &lt; scene.lights.size(); ++i)&#xD;&#xA;    		light_to_index[scene.lights[i].get()] = i;&#xD;&#xA;    &#xD;&#xA;    	std::vector&lt;vertex&gt; z(m_t),&#xD;&#xA;    		y(m_s);&#xD;&#xA;    &#xD;&#xA;    	std::size_t const a = m_camera-&gt;film-&gt;GetSampleBounds().pMax.y,&#xD;&#xA;    		b = m_camera-&gt;film-&gt;GetSampleBounds().pMax.x;&#xD;&#xA;    	std::vector&lt;pbrt::Spectrum&gt; image(a * b);&#xD;&#xA;    	std::vector&lt;std::size_t&gt; n(a * b);&#xD;&#xA;    &#xD;&#xA;    	pbrt::MemoryArena arena;&#xD;&#xA;    	for (std::size_t i = 0; i &lt; m_n; ++i)&#xD;&#xA;    	{&#xD;&#xA;    		pbrt::Point2f raster_point;&#xD;&#xA;    		auto const contribution = sample_path(scene, *m_camera, *light_distribution, light_to_index,&#xD;&#xA;    			arena, m_k, m_s, *m_sampler, raster_point, z.data(), y.data());&#xD;&#xA;    		arena.Reset();&#xD;&#xA;    &#xD;&#xA;    		std::size_t const index = static_cast&lt;std::size_t&gt;(raster_point.y) * b + static_cast&lt;std::size_t&gt;(raster_point.x);&#xD;&#xA;    &#xD;&#xA;    		image[index] += contribution.value_or(0);&#xD;&#xA;    		++n[index];&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	for (std::size_t i = 0; i &lt; n.size(); ++i)&#xD;&#xA;    	{&#xD;&#xA;    		if (n[i] &gt; 0)&#xD;&#xA;    			image[i] = image[i] / (n[i] /** a * b*/);&#xD;&#xA;    	}&#xD;&#xA;    	m_camera-&gt;film-&gt;SetImage(image.data());&#xD;&#xA;    	m_camera-&gt;film-&gt;WriteImage();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;At the end, I should devide each pixel value by $|J|=ab$. However, if I uncomment the devision in the code, I end up with a black image again. So, my guess right now is that the values provided by `BxDF::Sample_f()` are not what I thought they are. Maybe they are &quot;normalized&quot; and maybe this is what they mean by &quot;*Each Metropolis iteration within &lt;&lt;Run nChains Markov chains in parallel&gt;&gt; has splatted contributions with weighted unit luminance*&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="26536" PostHistoryTypeId="5" PostId="9589" RevisionGUID="9059d915-a7be-4d87-8ed1-674462c8e652" CreationDate="2020-03-05T10:44:01.373" UserId="10096" Comment="C++ code highlight" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xD;&#xA;&#xD;&#xA;The authors write:&#xD;&#xA;&#xD;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xD;&#xA;&#xD;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xD;&#xA;&#xD;&#xA;For simplicity, assume that we are considering a fixed path length $k\in\mathbb N$ and a single fixed $(s,t)$-strategy. Formally, let&#xD;&#xA;&#xD;&#xA; - $M$ denote the scene surface set, $\mathcal B(M)$ denote the Borel $\sigma$-algebra on $M$ and $\sigma_M$ denote the surface measure on $\mathcal B(M)$&#xD;&#xA; - $E:=M^{\{0,\:\ldots\:,\:,k\}}$, $\mathcal E:={\mathcal B(M)}^{\otimes\{0,\:\ldots\:,\:,k\}}$ and $\lambda:=\sigma_M^{\otimes\{0,\:\ldots\:,\:,k\}}$&#xD;&#xA; - $f:E\to[0,\infty)^3$ denote the measurement contribution function&#xD;&#xA; - $q$ be the probability density on $(E,\mathcal E,\lambda)$ corresponding to the $(s,t)$-strategy satisfying $\{q=0\}\subseteq\{f=0\}$&#xD;&#xA;&#xD;&#xA;Once more, for simplicity, assume that the generated $(E,\mathcal E)$-valued chain $(X_n)_{n\in\mathbb N}$ is independent and $$X_n\sim q\lambda\;\;\;\text{for all }n\in\mathbb N.$$ If it's easier to understand for you, you might want to take a look at the `importance_sampling_integrator::render()` method in [this code](https://coliru.stacked-crooked.com/view?id=7f55a67c5e1dab10), where I've implemented these simplifications.&#xD;&#xA;&#xD;&#xA;Now let's consider the measurement of a single pixel value $$I:=\int hf\:{\rm d}\lambda,$$ where $h:E\to[0,\infty)$ is the image reconstruction filter corresponding to this pixel. Assume (as PBRT does) that $h$ is a Box filter with radius 1/2. So, if $\psi:E\to R$ is the canonical mapping from the path space $E$ to the raster space $R=[0,a)\times[0,b)$, where $a\in\mathbb N$ and $b\in\mathbb N$ are the vertical and horizontal resolution of the image, respectively, and the pixel we've fixed is pixel $(i,j)\in J:=\{0,\ldots,a-1\}\times\{0,\ldots,b-1\}$ then $h$ is simply the indicator function of the set $$B:=\left\{x\in E:\psi(x)\in\underbrace{[i,i+1)\times[j,j+1)}_{=:\:R_{(i,\:j)}}\right\},$$ i.e. $h=1_B$. Now let $$U_n:=\psi(X_n)\;\;\;\text{for }n\in\mathbb N$$ and note that, by construction of $q$, $$U_n\sim\mathcal U_R\;\;\;\text{for all }n\in\mathbb N\tag1,$$ where $\mathcal U_R$ denotes the uniform distribution on $R$. This immediately yields that $$(q\lambda)(B)=\mathcal U_R\left(R_{(i,\:j)}\right)=\frac1{|J|}\tag2.$$&#xD;&#xA;&#xD;&#xA;&gt; Let $$g(x):=h(x)\left.\begin{cases}\displaystyle\frac fq(x)&amp;\text{, if }q(x)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\;\;\;\text{for }x\in E.$$ Now the naive estimator for $I$ is $$\frac1n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty} I\;\;\;\text{almost surely}\tag3.$$ However, if I implement this (which corresponds to replacing `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_sampler-&gt;samplesPerPixel);` in the last line of `importance_sampling_integrator::render()` by `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_n);`), I end up with a black image. This is not surprising, since due to the very small support of $h$ compared to the whole image, only very few terms contribute to the sum in $(3)$.&#xD;&#xA;&#xD;&#xA;So, it seems like that one needs to consider only the visits of $(X_n)_{n\in\mathbb N}$ to the set $B$, i.e. consider the process $$Y_k:=X_{\tau_k}\;\;\;\text{for }k\in\mathbb N$$ instead, where $\tau_0:=0$, $$\tau_k:=\inf\left\{n&gt;\tau_{k-1}:X_n\in B\right\}\;\;\;\text{for }k\in\mathbb N.$$ It's easy to see that $(Y_k)_{k\in\mathbb N}$ is independent with $$Y_n\sim (q\lambda)\left[\;\cdot\mid B\right]\;\;\;\text{for all }k\in\mathbb N\tag4.$$ Moreover, $$\frac1k\sum_{i=1}^kg(Y_i)\xrightarrow{k\to\infty}(q\lambda)\left[g\mid B\right]=|J|I\tag5$$ by $(2)$.&#xD;&#xA;&#xD;&#xA;&gt; Now what the code does is independently drawing $X_1,\ldots,X_n\sim q\lambda$, where $$n=n_0|J|\tag6$$ for some $n_0\in\mathbb N$ (called `mutationsPerPixel` in PBRT).&#xD;&#xA;&#xD;&#xA;We may consider the number $$N_n:=\sum_{i=1}^n1_B(X_i)$$ of visits to $B$ up to time $n$ and note that $$\operatorname E\left[N_n\right]=\frac n{|J|}\tag7$$ and $$\frac{N_n}n\xrightarrow{n\to\infty}\frac1{|J|}\;\;\;\text{almost surely}.\tag8$$&#xD;&#xA;&#xD;&#xA;&gt; Now PBRT (and the code I've provided above as well) uses the estimator $$\frac1{n_0}\sum_{i=1}^ng(X_i)=\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i),$$ but I absolutely don't understand why this works. From $(5)$ we should obtain $$\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i)=\frac{|J|}n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty}|J|I\tag9$$ almost surely, but the left-hand side of $(9)$, dividied by $|J|$, is once again the pracitcally not working estimator $(3)$.&#xD;&#xA;&#xD;&#xA;&gt; What am I missing?&#xD;&#xA;&#xD;&#xA;**EDIT**: Just to be completely sure I've built the image array by myself using the (supposed to be correct) estimator $(5)$:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-cpp --&gt;&#xD;&#xA;&#xD;&#xA;    void render(pbrt::Scene const&amp; scene)&#xD;&#xA;    {&#xD;&#xA;    	auto const light_distribution = pbrt::ComputeLightPowerDistribution(scene);&#xD;&#xA;    &#xD;&#xA;    	std::unordered_map&lt;pbrt::Light const*, std::size_t&gt; light_to_index;&#xD;&#xA;    	for (std::size_t i = 0; i &lt; scene.lights.size(); ++i)&#xD;&#xA;    		light_to_index[scene.lights[i].get()] = i;&#xD;&#xA;    &#xD;&#xA;    	std::vector&lt;vertex&gt; z(m_t),&#xD;&#xA;    		y(m_s);&#xD;&#xA;    &#xD;&#xA;    	std::size_t const a = m_camera-&gt;film-&gt;GetSampleBounds().pMax.y,&#xD;&#xA;    		b = m_camera-&gt;film-&gt;GetSampleBounds().pMax.x;&#xD;&#xA;    	std::vector&lt;pbrt::Spectrum&gt; image(a * b);&#xD;&#xA;    	std::vector&lt;std::size_t&gt; n(a * b);&#xD;&#xA;    &#xD;&#xA;    	pbrt::MemoryArena arena;&#xD;&#xA;    	for (std::size_t i = 0; i &lt; m_n; ++i)&#xD;&#xA;    	{&#xD;&#xA;    		pbrt::Point2f raster_point;&#xD;&#xA;    		auto const contribution = sample_path(scene, *m_camera, *light_distribution, light_to_index,&#xD;&#xA;    			arena, m_k, m_s, *m_sampler, raster_point, z.data(), y.data());&#xD;&#xA;    		arena.Reset();&#xD;&#xA;    &#xD;&#xA;    		std::size_t const index = static_cast&lt;std::size_t&gt;(raster_point.y) * b + static_cast&lt;std::size_t&gt;(raster_point.x);&#xD;&#xA;    &#xD;&#xA;    		image[index] += contribution.value_or(0);&#xD;&#xA;    		++n[index];&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	for (std::size_t i = 0; i &lt; n.size(); ++i)&#xD;&#xA;    	{&#xD;&#xA;    		if (n[i] &gt; 0)&#xD;&#xA;    			image[i] = image[i] / (n[i] /** a * b*/);&#xD;&#xA;    	}&#xD;&#xA;    	m_camera-&gt;film-&gt;SetImage(image.data());&#xD;&#xA;    	m_camera-&gt;film-&gt;WriteImage();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;At the end, I should devide each pixel value by $|J|=ab$. However, if I uncomment the devision in the code, I end up with a black image again. So, my guess right now is that the values provided by `BxDF::Sample_f()` are not what I thought they are. Maybe they are &quot;normalized&quot; and maybe this is what they mean by &quot;*Each Metropolis iteration within &lt;&lt;Run nChains Markov chains in parallel&gt;&gt; has splatted contributions with weighted unit luminance*&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="26537" PostHistoryTypeId="2" PostId="9630" RevisionGUID="c82cf9cc-5652-4e14-8992-c658c4571dc1" CreationDate="2020-03-05T10:53:28.280" UserId="3085" Text="You don't seem to be setting circle.position.z" ContentLicense="CC BY-SA 4.0" />
  <row Id="26540" PostHistoryTypeId="2" PostId="9631" RevisionGUID="fc1fa65e-6cea-4ab0-9983-f23cc770a332" CreationDate="2020-03-06T22:37:52.930" UserId="7462" Text="Pretty much the title, given a closed curve in 2D, defined by a set of points, and a point. What's the algorithm to calculate the winding number of that curve, point pair?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26541" PostHistoryTypeId="1" PostId="9631" RevisionGUID="fc1fa65e-6cea-4ab0-9983-f23cc770a332" CreationDate="2020-03-06T22:37:52.930" UserId="7462" Text="How do you compute the winding number of a closed poly curve?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26542" PostHistoryTypeId="3" PostId="9631" RevisionGUID="fc1fa65e-6cea-4ab0-9983-f23cc770a332" CreationDate="2020-03-06T22:37:52.930" UserId="7462" Text="|mathematics|computational-geometry|geometry|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26544" PostHistoryTypeId="50" PostId="9510" RevisionGUID="16fc33df-6d88-49e8-bf23-d1a44adfd590" CreationDate="2020-03-07T07:02:05.213" UserId="-1" />
  <row Id="26545" PostHistoryTypeId="2" PostId="9632" RevisionGUID="311501c4-1cfa-4742-8335-b311599db103" CreationDate="2020-03-07T09:15:25.650" UserId="11933" Text="With the help of this article I was able to fix the problem. The problem was the the missing inversion.&#xD;&#xA;&#xD;&#xA;http://www.bcnine.com/articles/water/water.md.html&#xD;&#xA;&#xD;&#xA;The working code is available via the above given links." ContentLicense="CC BY-SA 4.0" />
  <row Id="26546" PostHistoryTypeId="2" PostId="9633" RevisionGUID="4daccdd1-03a2-41f2-8b99-5ab08f0a31ad" CreationDate="2020-03-07T11:07:11.363" UserId="12002" Text="SHORT BACKGROUND: &#xD;&#xA;&#xD;&#xA;I am developing a neural network based model to differentiate benign and malignant ovarian tumors. I am working with transvaginal ultrasound images, some of which contains yellow markers as seen in the first image below. Without going into too mach details, there is a risk that the presence of the markers could introduce a bias that the network will be able to exploit. As a way of trying to counter this bias, I will insert semi-random markers to the images during training and validation as a type of image augmentation. &#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;PROBLEM:&#xD;&#xA;&#xD;&#xA;During training, I import the images (stored as JPEG-files) and convert them to NumPy arrays. &#xD;&#xA;&#xD;&#xA;- Simply overlaying a marker is not good enough, since the marker would have a clear/sharp outline, while the &quot;real&quot;/already present markers are somewhat distorted due to anti-aliasing/JPEG-image compression.&#xD;&#xA;&#xD;&#xA;I have some identical images with/without markers (e.g. first and second image below). After importing the two images as NumPy arrays the marker can be extracted by&#xD;&#xA;&#xD;&#xA;- Option 1: ... subtracting one image from the other (see the third and fourth image below for the result). (Would result in incorrect pixel values for the marker.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- Option 2: ... copying the image with markers and setting all cells to zero where the two images (with/without markers) are (almost) equal (see the fifth and sixth image below for the result).&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;a) &#xD;&#xA;&#xD;&#xA;Let's say, for simplicity, that the only thing that I wanted to achieve was to apply the extracted marker to a different transvaginal ultrasound image. How would I do that?&#xD;&#xA;&#xD;&#xA;- Simply overlaying the marker would create black patches around the marker.&#xD;&#xA;&#xD;&#xA;- Simply adding the pixel values would result in incorrect pixel values for the marker.&#xD;&#xA;_________________________&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;b)  (given that a) is solved)&#xD;&#xA;&#xD;&#xA;Let's say that I now also want to be able to insert a marker of a different size and orientation. &#xD;&#xA;&#xD;&#xA;Orientation: I could rotate and move the marker.&#xD;&#xA;Size: Any suggestion of how I could go about doing this? I still want the marker to have the same properties, i.e. simply stretching is not an option.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_________________________&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;from keras.preprocessing.image import load_img, img_to_array&#xD;&#xA;from scipy.ndimage import rotate&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;# importing images as NumPy arrays&#xD;&#xA;img1 = img_to_array(load_img('img1.jpg'))&#xD;&#xA;img2 = img_to_array(load_img('img2.jpg'))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# option 1&#xD;&#xA;img3 = img2-img1   # extracting the marker by subtracting the image arrays&#xD;&#xA;img3 = img3[:-100] # getting rid of the yellow/grey marker in the down-right corner&#xD;&#xA;&#xD;&#xA;# option 2&#xD;&#xA;img3 = img2[np.abs(img2 - img1) &lt; 15] = 0&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# rotating the image &#xD;&#xA;img3 = rotate(img3, angle=-23.6)&#xD;&#xA;&#xD;&#xA;# cropping the image &#xD;&#xA;img3_copy = img3.copy()&#xD;&#xA;img3_copy[np.abs(img3_copy) &lt; 10**-4] = 0&#xD;&#xA;idx = np.nonzero(img3_copy)&#xD;&#xA;img3 = img3[np.min(idx[0]):np.max(idx[0])+1, np.min(idx[1]):np.max(idx[1])+1]&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KbujB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/U4yt5.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/UWDt8.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/7g7BB.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/nXzx1.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/L7dKC.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="26547" PostHistoryTypeId="1" PostId="9633" RevisionGUID="4daccdd1-03a2-41f2-8b99-5ab08f0a31ad" CreationDate="2020-03-07T11:07:11.363" UserId="12002" Text="Extract object from image and apply it to different image" ContentLicense="CC BY-SA 4.0" />
  <row Id="26548" PostHistoryTypeId="3" PostId="9633" RevisionGUID="4daccdd1-03a2-41f2-8b99-5ab08f0a31ad" CreationDate="2020-03-07T11:07:11.363" UserId="12002" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26549" PostHistoryTypeId="5" PostId="5949" RevisionGUID="5b8516e0-2b77-428a-a68b-3e3feba9ac99" CreationDate="2020-03-07T21:06:14.593" UserId="3003" Comment="Fixed a bug in the error loop" Text="If you can't go to OpenGL 4.3 (or your implementation doesn't support `glDebugMessageCallback`s), you can simplify your code in a number of ways.&#xD;&#xA;&#xD;&#xA;The first is to move the calls to `glGetError()` into a function like this:&#xD;&#xA;&#xD;&#xA;    void checkGLError()&#xD;&#xA;    {&#xD;&#xA;        GLenum err;&#xD;&#xA;        while((err = glGetError()) != GL_NO_ERROR){&#xD;&#xA;            std::cout &lt;&lt; err;&#xD;&#xA;        }  &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;That reduces your code to:&#xD;&#xA;&#xD;&#xA;    unsigned int buffer = 0;&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    checkGLError();&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;    checkGLError();&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), vertices, GL_STATIC_DRAW); &#xD;&#xA;    checkGLError();&#xD;&#xA;&#xD;&#xA;However, calling `glGetError()` frequently can hurt performance, so it's best to conditionalize it so it only gets called in debug builds by doing something like this:&#xD;&#xA;&#xD;&#xA;    #if DEBUG&#xD;&#xA;    #define checkGLError() debugCheckGLError()&#xD;&#xA;    #else&#xD;&#xA;    #define checkGLError()&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;Then name the actual function `debugCheckGLError()`. It will get called in debug builds but not release builds." ContentLicense="CC BY-SA 4.0" />
  <row Id="26550" PostHistoryTypeId="2" PostId="9634" RevisionGUID="b4bb0106-310c-43cc-8c1f-06ca5cbea4d5" CreationDate="2020-03-08T18:17:02.993" UserId="6046" Text="Sorry about leaving it for so long but I was so busy implementing the goddamn algorithm, I forgot about this :)&#xD;&#xA;&#xD;&#xA;So after reading up on Veach's thesis pretty closely, I understood what was going on. First of all Veach's thesis describes about BDPT using MIS. However I implemented without MIS using the techniques described in the original Lafortune's paper.&#xD;&#xA;&#xD;&#xA;One thing to note is, that we have to calculate the radiance by the light path inversely as opposed to the normal flow in the eye path. As lightxbulb said for point 1, there is no pdf since the step is deterministic. However the deterministic step needs to be multiplied by the Geometric factor, the BRDF evaluation of light vertex to eye vertex and the BRDF evaluation of eye vertex to light vertex.&#xD;&#xA;&#xD;&#xA;For the second point, you don't have to worry about NEE since at each eye path vertex there is a path that connects to the light vertex directly, according to PBRT and the paper we can discard the already generated light source and use explicit light sampling there. Calculating the light path radiance separately (as done in light tracing) handles all the respective PDFs for generating the vertices there.&#xD;&#xA;&#xD;&#xA;Will post another question regarding the result comparison soon." ContentLicense="CC BY-SA 4.0" />
  <row Id="26551" PostHistoryTypeId="5" PostId="8796" RevisionGUID="05130e14-935c-4ab1-ba86-fed713828355" CreationDate="2020-03-08T18:37:08.140" UserId="2654" Comment="deleted 7 characters in body" Text="IEEE-754 defines the `isNaN` property, which determines if a value is NaN. However, it is also defined to be a non-signaling operation; calling `isNaN` on an sNaN will never result in a signaled failure. By contrast, equality testing may signal when given sNaN values.&#xD;&#xA;&#xD;&#xA;Now, GLSL explicitly states that signaling doesn't matter:&#xD;&#xA;&#xD;&#xA;&gt; Support for signaling NaNs is not required and exceptions are never raised.&#xD;&#xA;&#xD;&#xA;But of course, there's also the fact that `isnan` is a vector function, while `!(x == x)` only works on scalars. So if you want to test if any of the elements of a `vec3` are NaN, you can do `any(isnan(some_vec))`, while the equality-testing equivalent would be even more obtuse and verbose: `any(not(equal(some_vec, some_vec)))`.&#xD;&#xA;&#xD;&#xA;And all of that ignores the simple usability reasons for having `isnan`. `!(x == x)` is an idiom which must be learned, while `isnan` is an easily looked up function whose name tells you want it does. After all, most users of floats tend to forget about NaN, so such an expression seems like a tautology, while &quot;isnan&quot; explicitly reminds such people that NaNs are a real thing and they are reading code where that fact is important.&#xD;&#xA;&#xD;&#xA;Also, as previously stated, `isNaN` is a property defined by IEEE-754. It is also a function provided by the standard libraries of C99, C++11, Java, C#, Swift, Go, JavaScript, and I can keep going, but I think my point is clear." ContentLicense="CC BY-SA 4.0" />
  <row Id="26552" PostHistoryTypeId="2" PostId="9635" RevisionGUID="fee97b07-c0e0-4483-a38b-894f0ebbb75e" CreationDate="2020-03-09T00:32:44.420" UserId="12011" Text="Pantone spot colors are specified in the RGB and CMYK color models on the &lt;https://pantone.com&gt; website. For example, the [Pantone 122C](https://www.pantone.com/color-finder/122-C) spot color is specified as RGB 254, 209, 65 and as CMYK 0, 9, 80, 0.&#xD;&#xA;&#xD;&#xA;Since the RGB color is also specified as HEX/HTML #FED141, I assume that the color is specified in the sRGB color space, see [CSS Color Module Level 3, Section 4.2.1](https://www.w3.org/TR/css-color-3/#rgb-color):&#xD;&#xA;&#xD;&#xA;&gt; All RGB colors are specified in the sRGB color space (see [[SRGB]](https://www.w3.org/TR/css-color-3/#ref-SRGB)). […]&#xD;&#xA;&#xD;&#xA;However, what would be the CMYK color space / color profile?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26553" PostHistoryTypeId="1" PostId="9635" RevisionGUID="fee97b07-c0e0-4483-a38b-894f0ebbb75e" CreationDate="2020-03-09T00:32:44.420" UserId="12011" Text="What is the CMYK color profile used by pantone.com" ContentLicense="CC BY-SA 4.0" />
  <row Id="26554" PostHistoryTypeId="3" PostId="9635" RevisionGUID="fee97b07-c0e0-4483-a38b-894f0ebbb75e" CreationDate="2020-03-09T00:32:44.420" UserId="12011" Text="|color|color-management|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26555" PostHistoryTypeId="5" PostId="9635" RevisionGUID="296bae9b-190d-45cb-9b5d-6ad1689d0a1e" CreationDate="2020-03-09T16:38:28.757" UserId="12011" Comment="added 94 characters in body" Text="Pantone spot colors are specified in the RGB and CMYK color models on the &lt;https://pantone.com&gt; website. For example, the [Pantone 122C](https://www.pantone.com/color-finder/122-C) spot color is specified as RGB 254, 209, 65 and as CMYK 0, 9, 80, 0.&#xD;&#xA;&#xD;&#xA;Since the RGB color is also specified as HEX/HTML #FED141, I assume that the color is specified in the sRGB color space, see [CSS Color Module Level 3, Section 4.2.1](https://www.w3.org/TR/css-color-3/#rgb-color):&#xD;&#xA;&#xD;&#xA;&gt; All RGB colors are specified in the sRGB color space (see [[SRGB]](https://www.w3.org/TR/css-color-3/#ref-SRGB)). […]&#xD;&#xA;&#xD;&#xA;However, what would be the CMYK color space / color profile? I would assume U.S. Web Coated (SWOP) v2, which is the default CMYK color space in Photoshop." ContentLicense="CC BY-SA 4.0" />
  <row Id="26558" PostHistoryTypeId="2" PostId="9636" RevisionGUID="98e5e2b3-e017-416e-aed6-ff2a07816884" CreationDate="2020-03-09T17:12:24.550" UserId="12014" Text="Referring to the answer that lightxbulb already gave, you can find a very in-depth explanation of the physics of light and their simulation in the thesis of Eric Veach named &quot;Robust Monte Carlo methods for light transport simulation&quot;.&#xD;&#xA;&#xD;&#xA;I read it for a class that I took in Computer Graphics and really liked it.&#xD;&#xA;&#xD;&#xA;You can find it yourself by searching the web or by visiting this link:&#xD;&#xA;https://graphics.stanford.edu/papers/veach_thesis/thesis.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="26559" PostHistoryTypeId="5" PostId="9635" RevisionGUID="ef126a00-6fa8-4e3d-a0d0-9e6c4a0cae23" CreationDate="2020-03-09T17:53:13.327" UserId="12011" Comment="added 114 characters in body" Text="Pantone spot colors are specified in the RGB and CMYK color models on the &lt;https://pantone.com&gt; website. For example, the [Pantone 122 spot color as it appears when printed on coated paper](https://www.pantone.com/color-finder/122-C) is specified as RGB 254, 209, 65 and as CMYK 0, 9, 80, 0.&#xD;&#xA;&#xD;&#xA;Since the RGB color is also specified as HEX/HTML #FED141, I assume that the color is specified in the sRGB color space, see [CSS Color Module Level 3, Section 4.2.1](https://www.w3.org/TR/css-color-3/#rgb-color):&#xD;&#xA;&#xD;&#xA;&gt; All RGB colors are specified in the sRGB color space (see [[SRGB]](https://www.w3.org/TR/css-color-3/#ref-SRGB)). […]&#xD;&#xA;&#xD;&#xA;However, what would be the CMYK color space / color profile? My wild guess would be the U.S. Web Coated (SWOP) v2, which is the default CMYK color space in Photoshop, but there are many other color profiles, which produce different colors for the same CMYK quadruplet." ContentLicense="CC BY-SA 4.0" />
  <row Id="26563" PostHistoryTypeId="2" PostId="9638" RevisionGUID="6f48a84a-dc47-4daf-96e0-a703176f7e14" CreationDate="2020-03-10T08:55:29.667" UserId="209" Text="Winding number as in https://en.wikipedia.org/wiki/Winding_number?&#xD;&#xA;&#xD;&#xA;Unless I'm mistaken, one way is to fire, say, a horizontal 'ray' out from your point towards, say, $+\infty$. Each time you cross an edge, $(V_n V_{n+1})$ that is going up (i.e.$V_n[y] &lt;V_{n+1}[y]$) , increment a counter, and decrement if the edge is going down.&#xD;&#xA;&#xD;&#xA;The special cases of horizontal edges and vertices that lie on the ray are left as a (not too difficult) exercise for the reader.&#xD;&#xA;&#xD;&#xA;If you want to do it quickly/approximately with a graphics API, you can use stencil buffers." ContentLicense="CC BY-SA 4.0" />
  <row Id="26564" PostHistoryTypeId="5" PostId="9635" RevisionGUID="41951cf7-a5f5-46ff-823d-0d4687403acc" CreationDate="2020-03-10T11:30:29.053" UserId="12011" Comment="Add an additional question" Text="Pantone spot colors are specified in the RGB and CMYK color models on the &lt;https://pantone.com&gt; website. For example, the [Pantone 122 spot color as it appears when printed on coated paper](https://www.pantone.com/color-finder/122-C) is specified as RGB 254, 209, 65 and as CMYK 0, 9, 80, 0.&#xD;&#xA;&#xD;&#xA;Since the RGB color is also specified as HEX/HTML #FED141, I assume that the color is specified in the sRGB color space, see [CSS Color Module Level 3, Section 4.2.1](https://www.w3.org/TR/css-color-3/#rgb-color):&#xD;&#xA;&#xD;&#xA;&gt; All RGB colors are specified in the sRGB color space (see [[SRGB]](https://www.w3.org/TR/css-color-3/#ref-SRGB)). […]&#xD;&#xA;&#xD;&#xA;However, what would be the CMYK color space / color profile? My wild guess would be the U.S. Web Coated (SWOP) v2, which is the default CMYK color space in Photoshop, but there are many other color profiles, which produce different colors for the same CMYK quadruplet.&#xD;&#xA;&#xD;&#xA;Additionally, why are there separate CMYK quadruplets for the [Pantone 122 spot color as it appears when printed on coated paper](https://www.pantone.com/color-finder/122-C) and [when printed on coated paper](https://www.pantone.com/color-finder/122-U). I would expect a single CMYK quadruplet, which would result appear differently based on the paper used, just like there is just a single Pantone 122 spot color." ContentLicense="CC BY-SA 4.0" />
  <row Id="26565" PostHistoryTypeId="2" PostId="9639" RevisionGUID="3c7ad2fa-589a-400a-a6ac-8562d92eefbc" CreationDate="2020-03-10T17:35:21.667" UserId="12022" Text="Upscaling a screenshot with subpixel antialiased text produces unpleasant color fringes, e.g. https://computergraphics.stackexchange.com/q/2034/12022 This is especially annoying when trying to show an application on a projector, when you have to zoom in with a tool like the Windows [Magnifier](https://en.wikipedia.org/wiki/Magnifier_(Windows)) to show details to the audience.&#xD;&#xA;&#xD;&#xA;There are some solutions available to exploit the subpixel geometry of a display when _downscaling_ an image, e.g. https://computergraphics.stackexchange.com/a/1431/12022. Are there any solutions for the opposite, i.e. taking an image with subpixel rendering and producing an upscaled image without color artifacts? I imagine this task is much more difficult in the presence of both subpixel (text) and non-subpixel (the rest of the screenshot) content in the same image, though." ContentLicense="CC BY-SA 4.0" />
  <row Id="26566" PostHistoryTypeId="1" PostId="9639" RevisionGUID="3c7ad2fa-589a-400a-a6ac-8562d92eefbc" CreationDate="2020-03-10T17:35:21.667" UserId="12022" Text="Upscaling screenshots with subpixel rendered text" ContentLicense="CC BY-SA 4.0" />
  <row Id="26567" PostHistoryTypeId="3" PostId="9639" RevisionGUID="3c7ad2fa-589a-400a-a6ac-8562d92eefbc" CreationDate="2020-03-10T17:35:21.667" UserId="12022" Text="|image-processing|subpixel-rendering|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26570" PostHistoryTypeId="33" PostId="9635" RevisionGUID="fa267600-36b8-4c84-bf2d-d82d36e1225d" CreationDate="2020-03-11T16:13:23.213" UserId="12011" Comment="61" />
  <row Id="26571" PostHistoryTypeId="34" PostId="9589" RevisionGUID="3e41f068-45c3-45a3-a73a-3b2d904324d6" CreationDate="2020-03-13T09:02:15.453" UserId="-1" Comment="60" />
  <row Id="26572" PostHistoryTypeId="2" PostId="9640" RevisionGUID="3b4971cc-d502-4407-ba1e-8daf007e2c17" CreationDate="2020-03-13T14:30:34.903" UserId="12033" Text="I'm working on an OpenGL compute shader in which each work item results in a single number output I'll call x, as well as a struct output with more information, I'll call y. What I would like is a single output for each work group being the y of the work item with the maximum x. Now I'm aware of the GLSL atomic operations and I believe I could easily get the maximum x, but I'm having trouble thinking of how to get the y associated with the maximum x. I could, in the compute shader, do a conditional right after I check for maximum x to check if x changed and change y accordingly, but I believe there is no guarantee that no other work item has replaced the maximum x at that point. I think this might be possible with memory barriers but I'm having trouble figuring out if it really is.&#xD;&#xA;&#xD;&#xA;So I guess my question is, is there an established method to do something like this? Am I perhaps over complicating it? Is there a way, with memory barriers, to create critical section-like behavior? Do I need to do the maximums on the CPU or in another serial compute shader?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="26573" PostHistoryTypeId="1" PostId="9640" RevisionGUID="3b4971cc-d502-4407-ba1e-8daf007e2c17" CreationDate="2020-03-13T14:30:34.903" UserId="12033" Text="OpenGL Compute Shader Shared Maximum" ContentLicense="CC BY-SA 4.0" />
  <row Id="26574" PostHistoryTypeId="3" PostId="9640" RevisionGUID="3b4971cc-d502-4407-ba1e-8daf007e2c17" CreationDate="2020-03-13T14:30:34.903" UserId="12033" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26575" PostHistoryTypeId="5" PostId="9640" RevisionGUID="5bff3a4b-6ddd-430b-98eb-ac39bde516cf" CreationDate="2020-03-13T14:42:27.277" UserId="2654" Comment="deleted 7 characters in body" Text="I'm working on an OpenGL compute shader in which each work item results in a single number output I'll call x, as well as a struct output with more information, I'll call y. What I would like is a single output for each work group being the y of the work item with the maximum x.&#xD;&#xA;&#xD;&#xA;Now I'm aware of the GLSL atomic operations and I believe I could easily get the maximum x, but I'm having trouble thinking of how to get the y associated with the maximum x. I could, in the compute shader, do a conditional right after I check for maximum x to check if x changed and change y accordingly, but I believe there is no guarantee that no other work item has replaced the maximum x at that point. I think this might be possible with memory barriers but I'm having trouble figuring out if it really is.&#xD;&#xA;&#xD;&#xA;So I guess my question is, is there an established method to do something like this? Am I perhaps over complicating it? Is there a way, with memory barriers, to create critical section-like behavior? Do I need to do the maximums on the CPU or in another serial compute shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26576" PostHistoryTypeId="12" PostId="9597" RevisionGUID="1b270912-81ea-46cd-86e4-2e48c268799b" CreationDate="2020-03-14T07:17:42.063" UserId="5574" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:5574,&quot;DisplayName&quot;:&quot;Brett Hale&quot;}]}" />
  <row Id="26581" PostHistoryTypeId="50" PostId="9496" RevisionGUID="fecb21b7-b311-4839-9870-075370312ab9" CreationDate="2020-03-16T11:01:25.240" UserId="-1" />
  <row Id="26585" PostHistoryTypeId="2" PostId="9643" RevisionGUID="15fb95cd-5776-4701-a122-d6b123d01418" CreationDate="2020-03-17T10:42:37.940" UserId="6046" Text="So I've written a GPU based [pathtracer][1] using OpenCL-GL interoperability. The system uses the Mega-Kernel Approach instead of a wavefront one as I was aiming it as an educational software for other young people who wanted to dive into raytracing/pathtracing but didn't want to mess with all the boilerplate code (opening windows, getting opengl context, etc).  &#xD;&#xA;&#xD;&#xA;I basically spawn as many work-items as there are pixels. Then each work-item shoots a single ray through that pixel and calculates the color. Currently on my GTX 1660, rendering around 5-6k Triangles give only 5-10 fps in 1280x720 resolution. I suppose its fairly slow even though I implemented a SAH based BVH and Möller–Trumbore ray-triangle intersection. Hence one big problem is that since the kernel takes too much time, loading big models causes a timeout error. I've already extended the timeout delay through the registery. In order to avoid it, I've also currently broken the image into 4 blocks and passed 4 mega kernels to do the job. This reduces the time of a single kernel, nevertheless the problem still remains.&#xD;&#xA;&#xD;&#xA;I've looked into the [paper][2] for Brigade renderer which is a realtime GPU pathtracer but couldn't understand what approach they followed. According to the text, they are talking about a single kernel per pixel,&#xD;&#xA;&#xD;&#xA;&gt; The path tracing algorithm can be efficiently implemented as on the&#xD;&#xA;&gt; GPU, using a single kernel per pixel. The kernel loops over the&#xD;&#xA;&gt; samples for a pixel and outputs the final color. This limits memory&#xD;&#xA;&gt; access to read-only scene access and a single write for the final&#xD;&#xA;&gt; pixel color.&#xD;&#xA;&#xD;&#xA;1. However the looping part is strange. If there is supposed to be a single kernel launched for every pixel, then the global work items or the threads must be the samples for that pixel. Why are they looping over the samples inside the kernel? &#xD;&#xA;&#xD;&#xA;2. Secondly, I've also found [sources][3] that suggest that Brigade, infact used the wavefront approach?&#xD;&#xA;&#xD;&#xA;I also realize the old Brigade demos are done with either a single or dual Titan X but the difference isn't that great. I admit I haven't taken cache coherency and such things into account but these are hard to do with the mega-kernel approach anyway. **So in short the main crux of what I want to know is, Is the megakernel approach bound to give this FPS OR Am I doing something wrong here? Any tips on how I can improve the FPS for my mega-kernel pathtracer would be appreciated.** Link to the [kernel][4].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/gallickgunner/Yune&#xD;&#xA;  [2]: https://www.researchgate.net/publication/258395638_The_Brigade_Renderer_A_Path_Tracer_for_Real-Time_Games&#xD;&#xA;  [3]: https://jacco.ompf2.com/2019/07/18/wavefront-path-tracing/&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/kernels/legacy/udpt.cl" ContentLicense="CC BY-SA 4.0" />
  <row Id="26586" PostHistoryTypeId="1" PostId="9643" RevisionGUID="15fb95cd-5776-4701-a122-d6b123d01418" CreationDate="2020-03-17T10:42:37.940" UserId="6046" Text="How to achieve higher FPS for my GPU pathtracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26587" PostHistoryTypeId="3" PostId="9643" RevisionGUID="15fb95cd-5776-4701-a122-d6b123d01418" CreationDate="2020-03-17T10:42:37.940" UserId="6046" Text="|rendering|pathtracing|gpgpu|opencl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26588" PostHistoryTypeId="5" PostId="9643" RevisionGUID="e5f0541c-cd90-41c9-a438-a39a8d9c4d9d" CreationDate="2020-03-17T10:49:52.500" UserId="6046" Comment="added 119 characters in body" Text="So I've written a GPU based [pathtracer][1] using OpenCL-GL interoperability. The system uses the Mega-Kernel Approach instead of a wavefront one as I was aiming it as an educational software for other young people who wanted to dive into raytracing/pathtracing but didn't want to mess with all the boilerplate code (opening windows, getting opengl context, etc) similar to coding it on shadertoy but with the added feature of loading models, having other benchmarking facilities etc.&#xD;&#xA;&#xD;&#xA;I basically spawn as many work-items as there are pixels. Then each work-item shoots a single ray through that pixel and calculates the color. Currently on my GTX 1660, rendering around 5-6k Triangles give only 5-10 fps in 1280x720 resolution. I suppose its fairly slow even though I implemented a SAH based BVH and Möller–Trumbore ray-triangle intersection. Hence one big problem is that since the kernel takes too much time, loading big models causes a timeout error. I've already extended the timeout delay through the registery. In order to avoid it, I've also currently broken the image into 4 blocks and passed 4 mega kernels to do the job. This reduces the time of a single kernel, nevertheless the problem still remains.&#xD;&#xA;&#xD;&#xA;I've looked into the [paper][2] for Brigade renderer which is a realtime GPU pathtracer but couldn't understand what approach they followed. According to the text, they are talking about a single kernel per pixel,&#xD;&#xA;&#xD;&#xA;&gt; The path tracing algorithm can be efficiently implemented as on the&#xD;&#xA;&gt; GPU, using a single kernel per pixel. The kernel loops over the&#xD;&#xA;&gt; samples for a pixel and outputs the final color. This limits memory&#xD;&#xA;&gt; access to read-only scene access and a single write for the final&#xD;&#xA;&gt; pixel color.&#xD;&#xA;&#xD;&#xA;1. However the looping part is strange. If there is supposed to be a single kernel launched for every pixel, then the global work items or the threads must be the samples for that pixel. Why are they looping over the samples inside the kernel? &#xD;&#xA;&#xD;&#xA;2. Secondly, I've also found [sources][3] that suggest that Brigade, infact used the wavefront approach?&#xD;&#xA;&#xD;&#xA;I also realize the old Brigade demos are done with either a single or dual Titan X but the difference isn't that great. I admit I haven't taken cache coherency and such things into account but these are hard to do with the mega-kernel approach anyway. **So in short the main crux of what I want to know is, Is the megakernel approach bound to give this FPS OR Am I doing something wrong here? Any tips on how I can improve the FPS for my mega-kernel pathtracer would be appreciated.** Link to the [kernel][4].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/gallickgunner/Yune&#xD;&#xA;  [2]: https://www.researchgate.net/publication/258395638_The_Brigade_Renderer_A_Path_Tracer_for_Real-Time_Games&#xD;&#xA;  [3]: https://jacco.ompf2.com/2019/07/18/wavefront-path-tracing/&#xD;&#xA;  [4]: https://github.com/gallickgunner/Yune/blob/master/kernels/legacy/udpt.cl" ContentLicense="CC BY-SA 4.0" />
  <row Id="26589" PostHistoryTypeId="5" PostId="9624" RevisionGUID="deedafbc-f86c-4801-ad59-9634915f48fb" CreationDate="2020-03-17T16:26:35.753" UserId="11282" Comment="Improved answer from own work" Text="I ended up finding a fairly simple, fairly performant solution.&#xD;&#xA;&#xD;&#xA;1: Create a transformation matrix that rotates the cylinder to one of the axis (x, y or z)&#xD;&#xA;&#xD;&#xA;(That part is non-trivial)&#xD;&#xA;&#xD;&#xA;2: Apply the transformation matrix to the cylinder&#xD;&#xA;&#xD;&#xA;3: Apply the transformation matrix to the eight corners of the axis-aligned bounding box. &#xD;&#xA;&#xD;&#xA;(Applying a transformation matrix is not too hard, it looks like this:)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;newPoint[0] = (original[0] * xform[0][0]) + (original[1] * xform[1][0]) + (original[2] * xform[2][0] + xform[3][0]);&#xD;&#xA;newPoint[1] = (original[0] * xform[0][1]) + (original[1] * xform[1][1]) + (original[2] * xform[2][1] + xform[3][1]);&#xD;&#xA;newPoint[2] = (original[0] * xform[0][2]) + (original[1] * xform[1][2]) + (original[2] * xform[2][2] + xform[3][2]);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4: Get the distance of the corners to (0,0,0). Keep in mind that depending on your method of determining distance (IE, using a 3D distance formula) you may need to zero out the value of the point on the axis the cylinder was rotated to. If the cylinder was rotated to the Z axis, you would need to zero out the Z value for that point.&#xD;&#xA;&#xD;&#xA;5: If *any* of the points report a distance less than the radius of the cylinder, you know there must be a volume intersection.&#xD;&#xA;&#xD;&#xA;6: Special case: If the cylinder has a diameter small enough, it could fit inside of the bounding box completely, thus there would be no points for which their distance &lt; cylinder radius. I am unsure of the maximum circle that fits within the projection of a box while not encompassing any points. My best guess is just to check if the diameter is &lt; than any of the box's edge length. &#xD;&#xA;&#xD;&#xA;7: If you want the cylinder to have a maximum length, that's not too bad either. Just take one point of the cylinder, a vector representing its direction and its length, and do ```origin + (dir * length)``` to get the endpoint of the cylinder. Transform it as well, and make sure any points you have fall within the Z of that transformed endpoint. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26590" PostHistoryTypeId="5" PostId="9624" RevisionGUID="ccc9402e-9d2c-4e40-ad26-d5a2925810ac" CreationDate="2020-03-17T16:34:20.823" UserId="11282" Comment="added 92 characters in body" Text="I ended up finding a fairly simple, fairly performant solution.&#xD;&#xA;&#xD;&#xA;1: Create a transformation matrix that rotates the cylinder to one of the axis (x, y or z)&#xD;&#xA;&#xD;&#xA;(That part is non-trivial)&#xD;&#xA;&#xD;&#xA;2: Apply the transformation matrix to the cylinder&#xD;&#xA;&#xD;&#xA;3: Apply the transformation matrix to the eight corners of the axis-aligned bounding box. &#xD;&#xA;&#xD;&#xA;(Applying a transformation matrix is not too hard, it looks like this:)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;newPoint[0] = (original[0] * xform[0][0]) + (original[1] * xform[1][0]) + (original[2] * xform[2][0] + xform[3][0]);&#xD;&#xA;newPoint[1] = (original[0] * xform[0][1]) + (original[1] * xform[1][1]) + (original[2] * xform[2][1] + xform[3][1]);&#xD;&#xA;newPoint[2] = (original[0] * xform[0][2]) + (original[1] * xform[1][2]) + (original[2] * xform[2][2] + xform[3][2]);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4: Get the distance of the corners to (0,0,0). Keep in mind that depending on your method of determining distance (IE, using a 3D distance formula) you may need to zero out the value of the point on the axis the cylinder was rotated to. If the cylinder was rotated to the Z axis, you would need to zero out the Z value for that point.&#xD;&#xA;&#xD;&#xA;5: If *any* of the points report a distance less than the radius of the cylinder, you know there must be a volume intersection.&#xD;&#xA;&#xD;&#xA;6: Special case: If the cylinder has a diameter small enough, it could fit inside of the bounding box completely, thus there would be no points for which their distance &lt; cylinder radius. I am unsure of the maximum circle that fits within the projection of a box while not encompassing any points. My best guess is just to check if the diameter is &lt; than any of the box's edge length, or check if the diameter is less than the diagonal of the box, which may be safer. Not sure.&#xD;&#xA;&#xD;&#xA;7: If you want the cylinder to have a maximum length, that's not too bad either. Just take one point of the cylinder, a vector representing its direction and its length, and do ```origin + (dir * length)``` to get the endpoint of the cylinder. Transform it as well, and make sure any points you have fall within the Z of that transformed endpoint. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26591" PostHistoryTypeId="2" PostId="9644" RevisionGUID="9d3fa105-90f8-43fd-ad3d-74cabb4187c5" CreationDate="2020-03-18T16:19:05.957" UserId="9254" Text="Say I have constructed a path, using bidirectional path tracing (BDPT), consisting of a light subpath $y$ with $s=2$ vertices and a camera subpath $z$ with $t=3$ camera vertices.&#xD;&#xA;&#xD;&#xA;Now I want to compute the contribution (measurement contribution over sampling density) of the same path considered under the BDPT strategy with $s'=3$ and $t'=2$ light and camera vertices, respectively.&#xD;&#xA;&#xD;&#xA;Doing this involves the computation of the density of sampling the direction $\omega_{y_{s-1}\to z_{t-1}}$. Assuming the path has positive luminance, can I expect this density to be positive?&#xD;&#xA;&#xD;&#xA;I'm only considering &quot;lambertian reflection&quot; components of the involved BSDFs. Here's my example code in PBRT:&#xD;&#xA;&#xD;&#xA;    auto const omega1 = pbrt::Normalize(z[t - 1].p() - y[s - 1].p());&#xD;&#xA;    auto const omega2 = y[s - 1].si.wo;&#xD;&#xA;    auto const p = y[s - 1].si.bsdf-&gt;Pdf(omega1, omega2, lambertian_reflection);&#xD;&#xA;    &#xD;&#xA;    auto const c =&#xD;&#xA;    	g(scene, z[t - 1], y[s - 1]) *							// g(Z_{t-1} ↔ Y_{s-1})&#xD;&#xA;    	z[t - 1].f(y[s - 1], pbrt::TransportMode::Radiance) *	// f_s(Y_{s-1} → Z_{t-1} → Z_{t-2})&#xD;&#xA;    	y[s - 1].f(z[t - 1], pbrt::TransportMode::Importance);	// f_s(Y_{s-2} → Y_{s-1} → Z_{t-1})&#xD;&#xA;&#xD;&#xA;I've encountered a situation where `c` is nonzero, but the density `p` is `0` since internally `si.bsdf-&gt;Pdf` checks whether `omega1` and `omega2` are on the same side of the hemisphere induced by the normal at `y[s - 1]` and they were not in that situation.&#xD;&#xA;&#xD;&#xA;However, this is confusing. If they are not on the same side, shouldn't this imply that `y[s - 2]` and `z[t - 1]` are occluded from each other (and hence the geometry term `g(scene, z[t - 1], y[s - 1])` should be $0$?). Am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26592" PostHistoryTypeId="1" PostId="9644" RevisionGUID="9d3fa105-90f8-43fd-ad3d-74cabb4187c5" CreationDate="2020-03-18T16:19:05.957" UserId="9254" Text="Considering a path generated by bidirectional path tracing under a different strategy" ContentLicense="CC BY-SA 4.0" />
  <row Id="26593" PostHistoryTypeId="3" PostId="9644" RevisionGUID="9d3fa105-90f8-43fd-ad3d-74cabb4187c5" CreationDate="2020-03-18T16:19:05.957" UserId="9254" Text="|raytracing|pathtracing|global-illumination|pbr|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26594" PostHistoryTypeId="5" PostId="9644" RevisionGUID="27dc7722-d39a-4203-aa2c-82cff1f3c0de" CreationDate="2020-03-18T19:30:16.403" UserId="9254" Comment="added 909 characters in body" Text="Say I have constructed a path, using bidirectional path tracing (BDPT), consisting of a light subpath $y$ with $s=2$ vertices and a camera subpath $z$ with $t=3$ camera vertices.&#xD;&#xA;&#xD;&#xA;Now I want to compute the contribution (measurement contribution over sampling density) of the same path considered under the BDPT strategy with $s'=3$ and $t'=2$ light and camera vertices, respectively.&#xD;&#xA;&#xD;&#xA;Doing this involves the computation of the density of sampling the direction $\omega_{y_{s-1}\to z_{t-1}}$. Assuming the path has positive luminance, can I expect this density to be positive?&#xD;&#xA;&#xD;&#xA;I'm only considering &quot;lambertian reflection&quot; components of the involved BSDFs. Here's my example code in PBRT:&#xD;&#xA;&#xD;&#xA;    auto const omega1 = pbrt::Normalize(z[t - 1].p() - y[s - 1].p());&#xD;&#xA;    auto const omega2 = y[s - 1].si.wo;&#xD;&#xA;    auto const p = y[s - 1].si.bsdf-&gt;Pdf(omega1, omega2, lambertian_reflection);&#xD;&#xA;    &#xD;&#xA;    auto const c =&#xD;&#xA;    	g(scene, z[t - 1], y[s - 1]) *							// g(Z_{t-1} ↔ Y_{s-1})&#xD;&#xA;    	z[t - 1].f(y[s - 1], pbrt::TransportMode::Radiance) *	// f_s(Y_{s-1} → Z_{t-1} → Z_{t-2})&#xD;&#xA;    	y[s - 1].f(z[t - 1], pbrt::TransportMode::Importance);	// f_s(Y_{s-2} → Y_{s-1} → Z_{t-1})&#xD;&#xA;&#xD;&#xA;I've encountered a situation where `c` is nonzero, but the density `p` is `0` since internally `si.bsdf-&gt;Pdf` checks whether `omega1` and `omega2` are on the same side of the hemisphere induced by the normal at `y[s - 1]` and they were not in that situation.&#xD;&#xA;&#xD;&#xA;However, this is confusing. If they are not on the same side, shouldn't this imply that `y[s - 2]` and `z[t - 1]` are occluded from each other (and hence the geometry term `g(scene, z[t - 1], y[s - 1])` should be $0$?). Am I missing something?&#xD;&#xA;&#xD;&#xA;**EDIT**: Note that the density of sampling a path of length $k$ using the $(s,t)$-strategy is $q_{s,\:t}(x)=q_{0,\:t}(x_0,\ldots,x_{t-1})q_{s,\:0}(x_t,\ldots,x_k)$, where $$\begin{equation}\label{eq:path-tracing-strategy}\begin{split}q_{0,\:t}(z)=&amp;\prod_{i=1}^kg(z_{i-1}\leftrightarrow z_i)\left.\begin{cases}p_0\left(z_0,\omega_{z_0\to z_1}\right)&amp;\text{, if }q_0(z_0)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\\&amp;\prod_{i=2}^kp_{S^2}\left(z_{i-1},\omega_{z_{i-1}\to z_{i-2}},\omega_{z_{i-1}\to z_i}\right)\end{split}\end{equation}$$ where $p_0$ is the density of sampling the inital camera ray (with respect to the path throughput measure as defined by Veach), $q_0$ is the marginal density of sampling the initial vertex and $p$ is the conditional density (with respect to projected solid angle) of sampling the third argument given the first and second argument. The form of $q_{s,\:0}$ is analogous.&#xD;&#xA;&#xD;&#xA;**EDIT 2**: The relevant PBRT code:&#xD;&#xA;&#xD;&#xA;    Float BxDF::Pdf(const Vector3f &amp;wo, const Vector3f &amp;wi) const {&#xD;&#xA;        return SameHemisphere(wo, wi) ? AbsCosTheta(wi) * InvPi : 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline bool SameHemisphere(const Vector3f &amp;w, const Vector3f &amp;wp) {&#xD;&#xA;        return w.z * wp.z &gt; 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // BSDF Method Definitions&#xD;&#xA;    Spectrum BSDF::f(const Vector3f &amp;woW, const Vector3f &amp;wiW,&#xD;&#xA;                     BxDFType flags) const {&#xD;&#xA;        ProfilePhase pp(Prof::BSDFEvaluation);&#xD;&#xA;        Vector3f wi = WorldToLocal(wiW), wo = WorldToLocal(woW);&#xD;&#xA;        if (wo.z == 0) return 0.;&#xD;&#xA;        bool reflect = Dot(wiW, ng) * Dot(woW, ng) &gt; 0;&#xD;&#xA;        Spectrum f(0.f);&#xD;&#xA;        for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;            if (bxdfs[i]-&gt;MatchesFlags(flags) &amp;&amp;&#xD;&#xA;                ((reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_REFLECTION)) ||&#xD;&#xA;                 (!reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_TRANSMISSION))))&#xD;&#xA;                f += bxdfs[i]-&gt;f(wo, wi);&#xD;&#xA;        return f;&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="26595" PostHistoryTypeId="5" PostId="9644" RevisionGUID="07004279-42c2-4b60-bdae-f6d9b0dce231" CreationDate="2020-03-18T19:38:58.283" UserId="9254" Comment="deleted 6 characters in body" Text="Say I have constructed a path, using bidirectional path tracing (BDPT), consisting of a light subpath $y$ with $s=2$ vertices and a camera subpath $z$ with $t=3$ camera vertices.&#xD;&#xA;&#xD;&#xA;Now I want to compute the contribution (measurement contribution over sampling density) of the same path considered under the BDPT strategy with $s'=3$ and $t'=2$ light and camera vertices, respectively.&#xD;&#xA;&#xD;&#xA;Doing this involves the computation of the density of sampling the direction $\omega_{y_{s-1}\to z_{t-1}}$. Assuming the path has positive luminance, can I expect this density to be positive?&#xD;&#xA;&#xD;&#xA;I'm only considering &quot;lambertian reflection&quot; components of the involved BSDFs. Here's my example code in PBRT:&#xD;&#xA;&#xD;&#xA;    auto const omega1 = pbrt::Normalize(z[t - 1].p() - y[s - 1].p());&#xD;&#xA;    auto const omega2 = y[s - 1].si.wo;&#xD;&#xA;    auto const p = y[s - 1].si.bsdf-&gt;Pdf(omega1, omega2, lambertian_reflection);&#xD;&#xA;    &#xD;&#xA;    auto const c =&#xD;&#xA;    	g(scene, z[t - 1], y[s - 1]) *							// g(Z_{t-1} ↔ Y_{s-1})&#xD;&#xA;    	z[t - 1].f(y[s - 1], pbrt::TransportMode::Radiance) *	// f_s(Y_{s-1} → Z_{t-1} → Z_{t-2})&#xD;&#xA;    	y[s - 1].f(z[t - 1], pbrt::TransportMode::Importance);	// f_s(Y_{s-2} → Y_{s-1} → Z_{t-1})&#xD;&#xA;&#xD;&#xA;I've encountered a situation where `c` is nonzero, but the density `p` is `0` since internally `si.bsdf-&gt;Pdf` checks whether `omega1` and `omega2` are on the same side of the hemisphere induced by the normal at `y[s - 1]` and they were not in that situation.&#xD;&#xA;&#xD;&#xA;However, this is confusing. If they are not on the same side, shouldn't this imply that `y[s - 2]` and `z[t - 1]` are occluded from each other (and hence the geometry term `g(scene, z[t - 1], y[s - 1])` should be $0$?). Am I missing something?&#xD;&#xA;&#xD;&#xA;**EDIT**: Note that the density of sampling a path of length $k$ using the $(s,t)$-strategy is $q_{s,\:t}(x)=q_{0,\:t}(x_0,\ldots,x_{t-1})q_{s,\:0}(x_t,\ldots,x_k)$, where $$\begin{equation}\label{eq:path-tracing-strategy}\begin{split}q_{0,\:t}(z)=&amp;\prod_{i=1}^kg(z_{i-1}\leftrightarrow z_i)\left.\begin{cases}p_0\left(z_0,\omega_{z_0\to z_1}\right)&amp;\text{, if }q_0(z_0)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\\&amp;\prod_{i=2}^kp\left(z_{i-1},\omega_{z_{i-1}\to z_{i-2}},\omega_{z_{i-1}\to z_i}\right)\end{split}\end{equation}$$ where $p_0$ is the density of sampling the inital camera ray (with respect to the path throughput measure as defined by Veach), $q_0$ is the marginal density of sampling the initial vertex and $p$ is the conditional density (with respect to projected solid angle) of sampling the third argument given the first and second argument. The form of $q_{s,\:0}$ is analogous.&#xD;&#xA;&#xD;&#xA;**EDIT 2**: The relevant PBRT code:&#xD;&#xA;&#xD;&#xA;    Float BxDF::Pdf(const Vector3f &amp;wo, const Vector3f &amp;wi) const {&#xD;&#xA;        return SameHemisphere(wo, wi) ? AbsCosTheta(wi) * InvPi : 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline bool SameHemisphere(const Vector3f &amp;w, const Vector3f &amp;wp) {&#xD;&#xA;        return w.z * wp.z &gt; 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // BSDF Method Definitions&#xD;&#xA;    Spectrum BSDF::f(const Vector3f &amp;woW, const Vector3f &amp;wiW,&#xD;&#xA;                     BxDFType flags) const {&#xD;&#xA;        ProfilePhase pp(Prof::BSDFEvaluation);&#xD;&#xA;        Vector3f wi = WorldToLocal(wiW), wo = WorldToLocal(woW);&#xD;&#xA;        if (wo.z == 0) return 0.;&#xD;&#xA;        bool reflect = Dot(wiW, ng) * Dot(woW, ng) &gt; 0;&#xD;&#xA;        Spectrum f(0.f);&#xD;&#xA;        for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;            if (bxdfs[i]-&gt;MatchesFlags(flags) &amp;&amp;&#xD;&#xA;                ((reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_REFLECTION)) ||&#xD;&#xA;                 (!reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_TRANSMISSION))))&#xD;&#xA;                f += bxdfs[i]-&gt;f(wo, wi);&#xD;&#xA;        return f;&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="26597" PostHistoryTypeId="2" PostId="9645" RevisionGUID="13140e2e-b776-4190-b2fc-7714552031d4" CreationDate="2020-03-19T08:14:42.133" UserId="12046" Text="I am learning Perlin Noise, the original version and the improved version. &#xD;&#xA;&#xD;&#xA;In the paper &lt;Improving Noise&gt; which Ken Perlin wrote in 2002. He said &quot;The second deficiency is that whereas the gradients in G are&#xD;&#xA;distributed uniformly over a sphere, the cubic grid itself has&#xD;&#xA;directional biases, being shortened along the axes and elongated&#xD;&#xA;on the diagonals between opposite cube vertices. This directional&#xD;&#xA;asymmetry tends to cause a sporadic clumping effect, where&#xD;&#xA;nearby gradients that are almost axis-aligned, and therefore close&#xD;&#xA;together, happen to align with each other, causing anomalously&#xD;&#xA;high values in those regions&quot;. Here I can not understand what means &quot;directional biases, being shortened along the axes and elongated&#xD;&#xA;on the diagonals between opposite cube vertices.&quot; and why it causing &quot;axis-aligned clumping&quot;. &#xD;&#xA;&#xD;&#xA;Could anyone help me out? Thank you." ContentLicense="CC BY-SA 4.0" />
  <row Id="26598" PostHistoryTypeId="1" PostId="9645" RevisionGUID="13140e2e-b776-4190-b2fc-7714552031d4" CreationDate="2020-03-19T08:14:42.133" UserId="12046" Text="Why the gradients generated in original Perlin Noise causing axis-aligned clumping?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26599" PostHistoryTypeId="3" PostId="9645" RevisionGUID="13140e2e-b776-4190-b2fc-7714552031d4" CreationDate="2020-03-19T08:14:42.133" UserId="12046" Text="|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26600" PostHistoryTypeId="50" PostId="9549" RevisionGUID="1cfa9772-36ce-467d-b2b3-a64dfbd7b925" CreationDate="2020-03-19T09:02:55.473" UserId="-1" />
  <row Id="26605" PostHistoryTypeId="5" PostId="9644" RevisionGUID="9e657dc2-f1e6-48e7-8289-cd2d8a789ff0" CreationDate="2020-03-19T17:08:00.160" UserId="9254" Comment="added 799 characters in body" Text="Say I have constructed a path, using bidirectional path tracing (BDPT), consisting of a light subpath $y$ with $s=2$ vertices and a camera subpath $z$ with $t=3$ camera vertices.&#xD;&#xA;&#xD;&#xA;Now I want to compute the contribution (measurement contribution over sampling density) of the same path considered under the BDPT strategy with $s'=3$ and $t'=2$ light and camera vertices, respectively.&#xD;&#xA;&#xD;&#xA;Doing this involves the computation of the density of sampling the direction $\omega_{y_{s-1}\to z_{t-1}}$. Assuming the path has positive luminance, can I expect this density to be positive?&#xD;&#xA;&#xD;&#xA;I'm only considering &quot;lambertian reflection&quot; components of the involved BSDFs. Here's my example code in PBRT:&#xD;&#xA;&#xD;&#xA;    auto const omega1 = pbrt::Normalize(z[t - 1].p() - y[s - 1].p());&#xD;&#xA;    auto const omega2 = y[s - 1].si.wo;&#xD;&#xA;    auto const p = y[s - 1].si.bsdf-&gt;Pdf(omega1, omega2, lambertian_reflection);&#xD;&#xA;    &#xD;&#xA;    auto const c =&#xD;&#xA;    	g(scene, z[t - 1], y[s - 1]) *							// g(Z_{t-1} ↔ Y_{s-1})&#xD;&#xA;    	z[t - 1].f(y[s - 1], pbrt::TransportMode::Radiance) *	// f_s(Y_{s-1} → Z_{t-1} → Z_{t-2})&#xD;&#xA;    	y[s - 1].f(z[t - 1], pbrt::TransportMode::Importance);	// f_s(Y_{s-2} → Y_{s-1} → Z_{t-1})&#xD;&#xA;&#xD;&#xA;I've encountered a situation where `c` is nonzero, but the density `p` is `0` since internally `si.bsdf-&gt;Pdf` checks whether `omega1` and `omega2` are on the same side of the hemisphere induced by the normal at `y[s - 1]` and they were not in that situation.&#xD;&#xA;&#xD;&#xA;However, this is confusing. If they are not on the same side, shouldn't this imply that `y[s - 2]` and `z[t - 1]` are occluded from each other (and hence the geometry term `g(scene, z[t - 1], y[s - 1])` should be $0$?). Am I missing something?&#xD;&#xA;&#xD;&#xA;**EDIT**: Note that the density of sampling a path of length $k$ using the $(s,t)$-strategy is $q_{s,\:t}(x)=q_{0,\:t}(x_0,\ldots,x_{t-1})q_{s,\:0}(x_t,\ldots,x_k)$, where $$\begin{equation}\label{eq:path-tracing-strategy}\begin{split}q_{0,\:t}(z)=&amp;\prod_{i=1}^kg(z_{i-1}\leftrightarrow z_i)\left.\begin{cases}p_0\left(z_0,\omega_{z_0\to z_1}\right)&amp;\text{, if }q_0(z_0)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\\&amp;\prod_{i=2}^kp\left(z_{i-1},\omega_{z_{i-1}\to z_{i-2}},\omega_{z_{i-1}\to z_i}\right)\end{split}\end{equation}$$ where $p_0$ is the density of sampling the inital camera ray (with respect to the path throughput measure as defined by Veach), $q_0$ is the marginal density of sampling the initial vertex and $p$ is the conditional density (with respect to projected solid angle) of sampling the third argument given the first and second argument. The form of $q_{s,\:0}$ is analogous.&#xD;&#xA;&#xD;&#xA;**EDIT 2**: The relevant PBRT code:&#xD;&#xA;&#xD;&#xA;    Float BxDF::Pdf(const Vector3f &amp;wo, const Vector3f &amp;wi) const {&#xD;&#xA;        return SameHemisphere(wo, wi) ? AbsCosTheta(wi) * InvPi : 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline bool SameHemisphere(const Vector3f &amp;w, const Vector3f &amp;wp) {&#xD;&#xA;        return w.z * wp.z &gt; 0;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // BSDF Method Definitions&#xD;&#xA;    Spectrum BSDF::f(const Vector3f &amp;woW, const Vector3f &amp;wiW,&#xD;&#xA;                     BxDFType flags) const {&#xD;&#xA;        ProfilePhase pp(Prof::BSDFEvaluation);&#xD;&#xA;        Vector3f wi = WorldToLocal(wiW), wo = WorldToLocal(woW);&#xD;&#xA;        if (wo.z == 0) return 0.;&#xD;&#xA;        bool reflect = Dot(wiW, ng) * Dot(woW, ng) &gt; 0;&#xD;&#xA;        Spectrum f(0.f);&#xD;&#xA;        for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;            if (bxdfs[i]-&gt;MatchesFlags(flags) &amp;&amp;&#xD;&#xA;                ((reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_REFLECTION)) ||&#xD;&#xA;                 (!reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_TRANSMISSION))))&#xD;&#xA;                f += bxdfs[i]-&gt;f(wo, wi);&#xD;&#xA;        return f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**EDIT 3**: Here is an example: PBRT is using a local coordinate system for shading where the $z$-axis is aligned with the shading normal. The following picture shows the local coordinates of the geometric normal at $y_1$, the direction `wi` from $y_1$ to $z_2$ and the direction `wo` from $y_1$ to $y_0$,&#xD;&#xA;&#xD;&#xA;    wi = (0.93675665128065100,0.34934790470253263,-0.021047987110668076)&#xD;&#xA;    wo = (0.37751541702974800,0.28880688322120657,0.87981401108922330)&#xD;&#xA;    ng (local) = (0.025315795417292675,-0.0035753744029505263,0.99967311017165450)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;`ng` is slightly off from the shading normal `ns = (0,0,1)`. With respect to `ng`, `wi` and `wo` are in the same hemisphere, but with respect to `ns` they are not.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7RDSl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26606" PostHistoryTypeId="34" PostId="9635" RevisionGUID="9ece56fa-4a21-4cec-81e2-e3ef7c1d4e6d" CreationDate="2020-03-19T18:01:35.243" UserId="-1" Comment="61" />
  <row Id="26610" PostHistoryTypeId="2" PostId="9648" RevisionGUID="ad1de014-7c40-440f-bd61-b4dd6f70e6f7" CreationDate="2020-03-20T15:36:50.423" UserId="209" Text="Very briefly, Perlin noise ideally is meant to have, on average, the same frequency characteristics no matter where in the texture you are or in what direction you are looking.&#xD;&#xA;&#xD;&#xA;However, the way it's done is to define pseudo-random values (and derivatives) on a regular 3D grid which introduces some compromises.&#xD;&#xA;&#xD;&#xA;To make this easier to understand, imagine instead using just a 2D grid, and on every grid location with an even-numbered X coordinate, you set the value to 0.0, and on every odd X, 1.0.  So at (0,0), (2,0), (4,99) etc you have 0.0, while at at (1,0) etc, you have 1.0.&#xD;&#xA;&#xD;&#xA;If you followed a horizontal line, e.g (0,0) (1,0) (2,0) etc, it would go up and down, in a sine-wave-like pattern every 2 steps, but if you followed it in a diagonal direction,  (0,0), (1,1), (2,2,) then, per distance traveled, it would go up and down more slowly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I believe that is what Perlin is referring to." ContentLicense="CC BY-SA 4.0" />
  <row Id="26611" PostHistoryTypeId="2" PostId="9649" RevisionGUID="191ec57e-cfa2-43d8-811b-02cad3e12eaf" CreationDate="2020-03-20T16:18:40.100" UserId="7462" Text="I am trying to mimic reflections in image composition using shaders.&#xD;&#xA;&#xD;&#xA;I have gotten this far:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In this image the floor is &quot;reflecting&quot; the back wall, however the reflection is uncanny because the scale and the positions of the objects are very wrong. &#xD;&#xA;&#xD;&#xA;For example the plant is nowhere even close to where it should be. Assuming I have a ground truth set of values for the camera parameters, is there a way I could &quot;move&quot; the reflections to better match what I expect to see? It doesn't have to be perfect, just better than what I have.&#xD;&#xA;&#xD;&#xA;The way I am generating the image is the same as learnopengl's code:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {             &#xD;&#xA;        float ratio = 1.00 / 1.52;&#xD;&#xA;        vec3 I = normalize(Position - cameraPos);&#xD;&#xA;        vec3 R = refract(I, normalize(Normal), ratio);&#xD;&#xA;        FragColor = vec4(texture(skybox, R).rgb, 1.0);&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xm92r.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26612" PostHistoryTypeId="1" PostId="9649" RevisionGUID="191ec57e-cfa2-43d8-811b-02cad3e12eaf" CreationDate="2020-03-20T16:18:40.100" UserId="7462" Text="Controlling &quot;zoom&quot; and &quot;position&quot; of a cubemap in shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="26613" PostHistoryTypeId="3" PostId="9649" RevisionGUID="191ec57e-cfa2-43d8-811b-02cad3e12eaf" CreationDate="2020-03-20T16:18:40.100" UserId="7462" Text="|rendering|image-processing|reflection|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26614" PostHistoryTypeId="50" PostId="9048" RevisionGUID="2ab44e5e-671d-4cfc-a4fc-e8712174a2aa" CreationDate="2020-03-20T18:02:30.287" UserId="-1" />
  <row Id="26616" PostHistoryTypeId="2" PostId="9650" RevisionGUID="8278a287-14b6-4e24-a03c-215b36c9ce09" CreationDate="2020-03-21T14:57:57.880" UserId="2654" Text="Reflections based on a cubemap best represent a reflection at infinity. That is, since the only factor that a cubemap provides is direction, the cubemap acts as though it were at a distance from the reflective surface where only direction to the reflecting objects matters. And that only happens if the reflecting objects are infinitely far from the reflective surface.&#xD;&#xA;&#xD;&#xA;That works fine for reflecting distant environmental details like skies or distant landscapes. But it's not going to work with anything even remotely close to the reflective surface. And if the reflecting object and a reflective surface touch, then you can basically forget about it.&#xD;&#xA;&#xD;&#xA;Cubemap reflections are simply not the right tool for this scene. You will instead have to employ other strategies for reflections, like rendering the back wall under the reflective surface (using transparency of the reflective surface to create the appearance of reflection), or doing screen-space reflections or something like that." ContentLicense="CC BY-SA 4.0" />
  <row Id="26617" PostHistoryTypeId="5" PostId="9649" RevisionGUID="fd090bd3-6b80-42fb-8baa-895a10d52b39" CreationDate="2020-03-21T16:15:47.757" UserId="7462" Comment="added 215 characters in body" Text="I am trying to mimic reflections in image composition using shaders.&#xD;&#xA;&#xD;&#xA;I have gotten this far:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In this image the floor is &quot;reflecting&quot; the back wall, however the reflection is uncanny because the scale and the positions of the objects are very wrong. &#xD;&#xA;&#xD;&#xA;For example the plant is nowhere even close to where it should be. Assuming I have a ground truth set of values for the camera parameters, is there a way I could &quot;move&quot; the reflections to better match what I expect to see? It doesn't have to be perfect, just better than what I have.&#xD;&#xA;&#xD;&#xA;The way I am generating the image is the same as learnopengl's code:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {             &#xD;&#xA;        float ratio = 1.00 / 1.52;&#xD;&#xA;        vec3 I = normalize(Position - cameraPos);&#xD;&#xA;        vec3 R = refract(I, normalize(Normal), ratio);&#xD;&#xA;        FragColor = vec4(texture(skybox, R).rgb, 1.0);&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;An important thing I should mention is, I don't have geometry, just a still image and information of where the floor is. So I don't have any depth, normals, or anything like that for most of the image. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xm92r.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26618" PostHistoryTypeId="2" PostId="9651" RevisionGUID="f644b1db-3ee5-498a-8f01-ca18dad45080" CreationDate="2020-03-21T18:05:26.417" UserId="12055" Text="Can you please recommend some topic for research work related to mathematics in CG?&#xD;&#xA;(Maybe something like &quot;Affine transformations in CG&quot;) " ContentLicense="CC BY-SA 4.0" />
  <row Id="26619" PostHistoryTypeId="1" PostId="9651" RevisionGUID="f644b1db-3ee5-498a-8f01-ca18dad45080" CreationDate="2020-03-21T18:05:26.417" UserId="12055" Text="Mathematics in Computer Graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="26620" PostHistoryTypeId="3" PostId="9651" RevisionGUID="f644b1db-3ee5-498a-8f01-ca18dad45080" CreationDate="2020-03-21T18:05:26.417" UserId="12055" Text="|3d|mathematics|vector-graphics|vectors|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26621" PostHistoryTypeId="5" PostId="9650" RevisionGUID="3648aebb-ad08-4ff2-8214-53c9bef585bd" CreationDate="2020-03-21T20:22:24.717" UserId="2654" Comment="added 917 characters in body" Text="Reflections based on a cubemap best represent a reflection at infinity. That is, since the only factor that a cubemap provides is direction, the cubemap acts as though it were at a distance from the reflective surface where only direction to the reflecting objects matters. And that only happens if the reflecting objects are infinitely far from the reflective surface.&#xD;&#xA;&#xD;&#xA;That works fine for reflecting distant environmental details like skies or distant landscapes. But it's not going to work with anything even remotely close to the reflective surface. And if the reflecting object and a reflective surface touch, then you can basically forget about it.&#xD;&#xA;&#xD;&#xA;Cubemap reflections are simply not the right tool for this scene. You will instead have to employ other strategies for reflections, like rendering the back wall under the reflective surface (using transparency of the reflective surface to create the appearance of reflection), or doing screen-space reflections or something like that.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&gt; I don't have geometry, just a still image and information of where the floor is. So I don't have any depth, normals, or anything like that for most of the image.&#xD;&#xA;&#xD;&#xA;If you don't have geometry information or any equivalent to it, then you're pretty much out of luck. Accurate reflection of a scene requires knowing where the scene being reflected is relative to each point on the reflective surface. Even if the surface of reflection itself is flat, the reflected *scene* isn't. If you don't have some approximation of geometry information, and you cannot generate such a thing, then you cannot generate an accurate reflection.&#xD;&#xA;&#xD;&#xA;If computer vision algorithms are available to you, I would suggest trying to fine one that can reconstruct the depth information of the scene from a single image. If that's not feasible, then you're going to have to live with an inaccurate reflection in one way or another." ContentLicense="CC BY-SA 4.0" />
  <row Id="26622" PostHistoryTypeId="5" PostId="9650" RevisionGUID="a435edad-1919-4e67-8f6e-daca943928a1" CreationDate="2020-03-22T01:38:09.063" UserId="2654" Comment="added 4 characters in body" Text="Reflections based on a cubemap best represent a reflection at infinity. That is, since the only factor that a cubemap provides is direction, the cubemap acts as though it were at a distance from the reflective surface where only the direction to the reflecting objects matters. And that only happens if the reflecting objects are infinitely far from the reflective surface.&#xD;&#xA;&#xD;&#xA;That works fine for reflecting distant environmental details like skies or distant landscapes. But it's not going to work with anything even remotely close to the reflective surface. And if the reflecting object and a reflective surface touch, then you can basically forget about it.&#xD;&#xA;&#xD;&#xA;Cubemap reflections are simply not the right tool for this scene. You will instead have to employ other strategies for reflections, like rendering the back wall under the reflective surface (using transparency of the reflective surface to create the appearance of reflection), or doing screen-space reflections or something like that.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&gt; I don't have geometry, just a still image and information of where the floor is. So I don't have any depth, normals, or anything like that for most of the image.&#xD;&#xA;&#xD;&#xA;If you don't have geometry information or any equivalent to it, then you're pretty much out of luck. Accurate reflection of a scene requires knowing where the scene being reflected is relative to each point on the reflective surface. Even if the surface of reflection itself is flat, the reflected *scene* isn't. If you don't have some approximation of geometry information, and you cannot generate such a thing, then you cannot generate an accurate reflection.&#xD;&#xA;&#xD;&#xA;If computer vision algorithms are available to you, I would suggest trying to fine one that can reconstruct the depth information of the scene from a single image. If that's not feasible, then you're going to have to live with an inaccurate reflection in one way or another." ContentLicense="CC BY-SA 4.0" />
  <row Id="26626" PostHistoryTypeId="2" PostId="9653" RevisionGUID="b93916b8-c40e-4c56-8d77-ab53370a4b28" CreationDate="2020-03-23T08:56:46.630" UserId="11458" Text="I was making some circles in the HTML Canvas element and the circles were so smooth. In a sense that you cant see any vertices. &#xD;&#xA;&#xD;&#xA;I normally work in unity and I you make a shape in 3d you most of the time see vertices (aka not a perfectly smooth circle). It only really looks smooth if you crank the vertices count up to something like 100 - 150 But this would be highly inefficient to render. &#xD;&#xA;&#xD;&#xA;So now my question: How does HTML canvas manage to draw such smooth circles? Is this A: with a very high vertices count, or B: some other magic is used if so how do they do it?&#xD;&#xA;&#xD;&#xA;Let me know if anything is unclear or needs extra information. " ContentLicense="CC BY-SA 4.0" />
  <row Id="26627" PostHistoryTypeId="1" PostId="9653" RevisionGUID="b93916b8-c40e-4c56-8d77-ab53370a4b28" CreationDate="2020-03-23T08:56:46.630" UserId="11458" Text="How are 2D graphics rendered in HTML canvas" ContentLicense="CC BY-SA 4.0" />
  <row Id="26628" PostHistoryTypeId="3" PostId="9653" RevisionGUID="b93916b8-c40e-4c56-8d77-ab53370a4b28" CreationDate="2020-03-23T08:56:46.630" UserId="11458" Text="|performance|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26629" PostHistoryTypeId="2" PostId="9654" RevisionGUID="bd13bd2e-cc0a-4012-a47b-6f33d7b8baeb" CreationDate="2020-03-23T13:34:43.387" UserId="12059" Text="I am currently having an issue with OpenGL as I am trying to load some vector information into a 3D texture. Currently, I am developing in OpenGL 4.6 which should support Image bindings. &#xD;&#xA;&#xD;&#xA;this my code to bind the texture to an image: &#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;field_sbo);&#xD;&#xA;	glBindTexture(GL_TEXTURE_3D, field_sbo);&#xD;&#xA;	glTextureStorage3D(field_sbo, 1, GL_RGB32F, 10,10,10);&#xD;&#xA;	glTextureSubImage3D(field_sbo, 0, 0, 0, 0, 10, 10, 10, GL_RGB, GL_FLOAT, vector_data);&#xD;&#xA;	glBindImageTexture(0, field_sbo, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGB32F);&#xD;&#xA;	&#xD;&#xA;Additionally, this is the declaration in the compute shader:&#xD;&#xA;&#xD;&#xA;    layout(binding = 0, RGB32F) uniform image3D field;&#xD;&#xA;&#xD;&#xA;From my understanding, the glTextureStorage3D should make the texture immutable, however I keep getting an INVALID_VALUE at the glBindImageTexture stage. I have looked at the documentation for the errors however I cannot seem to fix the issue.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26630" PostHistoryTypeId="1" PostId="9654" RevisionGUID="bd13bd2e-cc0a-4012-a47b-6f33d7b8baeb" CreationDate="2020-03-23T13:34:43.387" UserId="12059" Text="glBindImageTexture returning INVALID_VALUE" ContentLicense="CC BY-SA 4.0" />
  <row Id="26631" PostHistoryTypeId="3" PostId="9654" RevisionGUID="bd13bd2e-cc0a-4012-a47b-6f33d7b8baeb" CreationDate="2020-03-23T13:34:43.387" UserId="12059" Text="|opengl|rendering|3d|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26637" PostHistoryTypeId="50" PostId="6094" RevisionGUID="dc8fd683-ebd5-46da-9a36-c07b41c57248" CreationDate="2020-03-23T19:03:40.643" UserId="-1" />
  <row Id="26641" PostHistoryTypeId="2" PostId="9658" RevisionGUID="b1eb34cf-95ca-4d60-83bd-c8052bb6dc10" CreationDate="2020-03-24T04:47:24.357" UserId="2654" Text="Outside of `GL_R11F_G11F_B10F`, 3-channel formats are [not allowed for image load/store][1]. And you'll note that `rgb32f` is [not in the list of valid format qualifiers for GLSL variables][2], nor are any other 3-channel formats (except `r11f_g11f_b10f`).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store#Images_in_the_context&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Image_Load_Store#Format_qualifiers" ContentLicense="CC BY-SA 4.0" />
  <row Id="26651" PostHistoryTypeId="5" PostId="4248" RevisionGUID="51bfa3b3-4d80-488c-9be5-fb7270a9d26b" CreationDate="2020-03-24T22:56:51.860" UserId="12035" Comment="fixed grammar" Text="After reading a few articles online I can confidently say I am clueless on **how Anti-Aliasing works when using Ray Tracing**.&#xD;&#xA;&#xD;&#xA;All I understand is that **A Single Pixel/Ray is split into 4 sub-pixels and 4 rays rather than 1**.&#xD;&#xA;&#xD;&#xA;Could somebody please explain how this is done (preferably with code)? " ContentLicense="CC BY-SA 4.0" />
  <row Id="26652" PostHistoryTypeId="24" PostId="4248" RevisionGUID="51bfa3b3-4d80-488c-9be5-fb7270a9d26b" CreationDate="2020-03-24T22:56:51.860" Comment="Proposed by 12035 approved by 209, 6 edit id of 512" ContentLicense="CC BY-SA 4.0" />
  <row Id="26655" PostHistoryTypeId="13" PostId="9597" RevisionGUID="ec10aef2-b73c-4907-a012-f50b92f06df5" CreationDate="2020-03-25T12:17:08.833" UserId="5574" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:5574,&quot;DisplayName&quot;:&quot;Brett Hale&quot;}]}" />
  <row Id="26656" PostHistoryTypeId="2" PostId="9661" RevisionGUID="64259f4b-ddce-4649-8a7e-0b9ce1434525" CreationDate="2020-03-25T16:07:03.117" UserId="12069" Text="I got a function that generates samples from a GGX visible normal distribution function. When I use it to calculate reflection directions obviously some of these intersect with the surface agin (negative).&#xD;&#xA;These bas samples become more of an issue if the roughness increases.&#xD;&#xA;How to handle this case ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26657" PostHistoryTypeId="1" PostId="9661" RevisionGUID="64259f4b-ddce-4649-8a7e-0b9ce1434525" CreationDate="2020-03-25T16:07:03.117" UserId="12069" Text="How to handle negative reflection directions in raytracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26658" PostHistoryTypeId="3" PostId="9661" RevisionGUID="64259f4b-ddce-4649-8a7e-0b9ce1434525" CreationDate="2020-03-25T16:07:03.117" UserId="12069" Text="|raytracing|brdf|pbr|sampling|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26660" PostHistoryTypeId="2" PostId="9662" RevisionGUID="94575f7e-d80a-48c0-92e8-0fdda8cb578a" CreationDate="2020-03-25T21:39:24.360" UserId="11458" Text="I am designing a 2D drawing library (it is its very early stages) and I was wondering what to do with Alpha (transparency). &#xD;&#xA;&#xD;&#xA;I have two trains of thought:  &#xD;&#xA;&#xD;&#xA;A. Implement Alpha in the Color class since it affects the eventual color. The color red (255, 0, 0, 255) looks totally different from the color (255, 0, 0, 127) both on a white background. &#xD;&#xA;&#xD;&#xA;B. Implement the Alpha value in the Shape class containing all base properties for a shape like position, color (in this case color would only contain r, g, b values), stroke weight etc. This could also work since Alpha would affect the entire object. &#xD;&#xA;&#xD;&#xA;What do you guys think makes more sense? &#xD;&#xA;&#xD;&#xA;Side notes:  &#xD;&#xA;If Alpha would be part of Shape it would be harder to quickly change colors and reassign them. &#xD;&#xA;But this would make it easier to implement functions like color mixing etc in the color class. &#xD;&#xA;&#xD;&#xA;(let me know if this is the place to ask this, I was also thinking about software engineering stack exchange. But this seemed to make more sense)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26661" PostHistoryTypeId="1" PostId="9662" RevisionGUID="94575f7e-d80a-48c0-92e8-0fdda8cb578a" CreationDate="2020-03-25T21:39:24.360" UserId="11458" Text="Alpha part of color class or shape class" ContentLicense="CC BY-SA 4.0" />
  <row Id="26662" PostHistoryTypeId="3" PostId="9662" RevisionGUID="94575f7e-d80a-48c0-92e8-0fdda8cb578a" CreationDate="2020-03-25T21:39:24.360" UserId="11458" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26666" PostHistoryTypeId="2" PostId="9664" RevisionGUID="aa13f4d9-c320-4af6-a688-82d97d28911d" CreationDate="2020-03-26T08:06:08.493" UserId="209" Text="Just to add to the answers above:&#xD;&#xA;&#xD;&#xA;[Distributed Ray Tracing][1] (Cook, Porter, &amp; Carpenter).  Allows you to simultaneously do spatial AA, temporal AA (i.e. motion blur), and focus/depth of field.  Best to read the paper, but basically the N-rays you fire per pixel can also be assigned pseudo-random times (for motion blur) and positions on a lens (to get focus effects).&#xD;&#xA;&#xD;&#xA;Adaptive Supersampling: You initially fire a certain number of rays per pixel. However, if the rays in a local neighbourhood return significantly different results, then you can *locally* increase the sampling rate (say 2x), to improve the results. You can opt to repeat the process.&#xD;&#xA;It's not perfect since objects can still 'fall between the samples', but it's possibly cheaper than uniformly sampling at a higher rate.&#xD;&#xA;&#xD;&#xA;[Ray tracing with cones][2] (Amanatides): Instead of using an infinitely thin ray, each ray is instead approximated by a cone, say with a diameter that covers all of the pixel (and a little of the neighbours) allowing you to do evaluate partial coverage. It also has benefits for texture sampling/antialiasing, soft shadows, and potentially LOD of models. I did an implementation *many* years ago - it's certainly more difficult to do, but does avoid a lot of additional rays.&#xD;&#xA;IIRC there was also a scheme called pencil tracing (but my initial search didn't find a link to the paper)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphics.pixar.com/library/DistributedRayTracing/paper.pdf&#xD;&#xA;  [2]: http://www.cs.yorku.ca/~amana/research/cones.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="26673" PostHistoryTypeId="2" PostId="9667" RevisionGUID="b2385500-ba05-43f9-9678-ed62430d4843" CreationDate="2020-03-27T12:34:20.123" UserId="12080" Text="I'm trying to implement Perlin Noise. Earlier I implemented it using HTML Canvas and then converted it to WebGL2 since I wanted a faster implementation. But the WebGL2 code has obvious edge artifacts in the generated noise where the noise function is not smooth.&#xD;&#xA;&#xD;&#xA;I used [Understanding Perlin Noise][1] as my reference for understanding Perlin Noise. However, I did use a different implementation for calculating the dot product of the gradient and distance vectors since I could not get the default implementation to work.&#xD;&#xA;&#xD;&#xA;This is the resulting noise that I'm getting:&#xD;&#xA;[![Perlin Noise with edges][2]][2]&#xD;&#xA;&#xD;&#xA;This is the noise I was getting in my Canvas implementation:&#xD;&#xA;[![Canvas Perlin Noise][3]][3]&#xD;&#xA;&#xD;&#xA;My algorithm for both the Canvas and WebGL is the same. I have attached my WebGL code below. Any ideas why this is happening?&#xD;&#xA;&#xD;&#xA;```let canvas = document.querySelector(&quot;canvas&quot;);&#xD;&#xA;let gl = canvas.getContext(&quot;webgl2&quot;);&#xD;&#xA;if (!gl) {&#xD;&#xA;	console.log(&quot;WebGL2 support not found&quot;);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;let octaveCount = 6;&#xD;&#xA;let persistence = 1.0;&#xD;&#xA;&#xD;&#xA;canvas.width = window.innerWidth;&#xD;&#xA;canvas.height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;const vertexSrc = `&#xD;&#xA;#version 300 es&#xD;&#xA;precision mediump float;&#xD;&#xA;&#xD;&#xA;vec2 quad[6] = vec2[](&#xD;&#xA;	vec2(-1.0, -1.0),&#xD;&#xA;	vec2(-1.0, 1.0),&#xD;&#xA;	vec2(1.0, -1.0),&#xD;&#xA;	vec2(-1.0, 1.0),&#xD;&#xA;	vec2(1.0, -1.0),&#xD;&#xA;	vec2(1.0, 1.0)&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;	gl_Position = vec4(quad[gl_VertexID], 0.0, 1.0);&#xD;&#xA;}&#xD;&#xA;`;&#xD;&#xA;&#xD;&#xA;const fragmentSrc = `&#xD;&#xA;#version 300 es&#xD;&#xA;precision mediump float;&#xD;&#xA;&#xD;&#xA;uniform vec2 offset;&#xD;&#xA;uniform int octaveCount;&#xD;&#xA;uniform float persistence;&#xD;&#xA;uniform vec2 resolution;&#xD;&#xA;out vec4 color;&#xD;&#xA;&#xD;&#xA;int p[256] = int[](151,.../*abbreviated for conveinence*/..180);&#xD;&#xA;&#xD;&#xA;vec2 grad[256] = vec2[](&#xD;&#xA;	vec2(1, 0),.../*abbreviated for conveinence*/...vec2(0.999698818696, -0.0245412285229)&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;float fade(float t) {&#xD;&#xA;	return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 getVec(int xi, int yi) {&#xD;&#xA;	int a = p[xi &amp; 255];&#xD;&#xA;	int b = p[yi &amp; 255];&#xD;&#xA;	int val = p[(a + b) &amp; 255];&#xD;&#xA;	return grad[val];&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float perlinAux(vec2 st) {&#xD;&#xA;	int xi = int(round(st.x)) &amp; 255;&#xD;&#xA;	int yi = int(round(st.y)) &amp; 255;&#xD;&#xA;	float xf = st.x - float(xi);&#xD;&#xA;	float yf = st.y - float(yi);&#xD;&#xA;	float u = fade(xf);&#xD;&#xA;	float v = fade(yf);&#xD;&#xA;&#xD;&#xA;	float n00 = dot(vec2(xf, yf), getVec(xi, yi));&#xD;&#xA;	float n01 = dot(vec2(xf, yf - 1.0), getVec(xi, yi + 1));&#xD;&#xA;	float n10 = dot(vec2(xf - 1.0, yf), getVec(xi + 1, yi));&#xD;&#xA;	float n11 = dot(vec2(xf - 1.0, yf - 1.0), getVec(xi + 1, yi + 1));&#xD;&#xA;&#xD;&#xA;	float x1 = mix(n00, n10, u);&#xD;&#xA;	float x2 = mix(n01, n11, u);&#xD;&#xA;	return (mix(x1, x2, v) + 1.0) / 2.0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float perlin(vec2 offset, vec2 st, int octaveCount, float persistence) {&#xD;&#xA;	float total = 0.0;&#xD;&#xA;	float freq = 1.0;&#xD;&#xA;	float amp = 1.0;&#xD;&#xA;	float maxValue = 0.0;&#xD;&#xA;	for (int i = 0; i &lt; octaveCount; i++) {&#xD;&#xA;		total += perlinAux(offset + st * freq) * amp;&#xD;&#xA;		maxValue += amp;&#xD;&#xA;		amp *= persistence;&#xD;&#xA;		freq *= 2.0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	return total / maxValue;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;	vec2 st = gl_FragCoord.xy / resolution;&#xD;&#xA;	float perlinVal = perlin(offset, st, octaveCount, persistence);&#xD;&#xA;	color = vec4(perlinVal, perlinVal, perlinVal, 1.0);&#xD;&#xA;}&#xD;&#xA;`;&#xD;&#xA;&#xD;&#xA;function compileShader(shaderSource, shaderType) {&#xD;&#xA;	const shader = gl.createShader(shaderType);&#xD;&#xA;	gl.shaderSource(shader, shaderSource);&#xD;&#xA;	gl.compileShader(shader);&#xD;&#xA;	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {&#xD;&#xA;		throw &quot;Shader compile failed with: &quot; + gl.getShaderInfoLog(shader);&#xD;&#xA;	}&#xD;&#xA;	return shader;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;const vertexShader = compileShader(vertexSrc.trim(), gl.VERTEX_SHADER);&#xD;&#xA;const fragmentShader = compileShader(fragmentSrc.trim(), gl.FRAGMENT_SHADER);&#xD;&#xA;&#xD;&#xA;const program = gl.createProgram();&#xD;&#xA;gl.attachShader(program, vertexShader);&#xD;&#xA;gl.attachShader(program, fragmentShader);&#xD;&#xA;gl.linkProgram(program);&#xD;&#xA;if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {&#xD;&#xA;	throw &quot;Program link failed with: &quot; + gl.getProgramInfoLog(program);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;const offsetLOC = gl.getUniformLocation(program, &quot;offset&quot;);&#xD;&#xA;const resolutionLOC = gl.getUniformLocation(program, &quot;resolution&quot;);&#xD;&#xA;const octaveCountLOC = gl.getUniformLocation(program, &quot;octaveCount&quot;);&#xD;&#xA;const persistenceLOC = gl.getUniformLocation(program, &quot;persistence&quot;);&#xD;&#xA;&#xD;&#xA;gl.useProgram(program);&#xD;&#xA;gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);&#xD;&#xA;gl.clearColor(0, 0, 0, 1.0);&#xD;&#xA;gl.clear(gl.COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;gl.uniform2f(offsetLOC, 0.0, 0.0);&#xD;&#xA;gl.uniform2f(resolutionLOC, gl.canvas.width, gl.canvas.height);&#xD;&#xA;gl.uniform1i(octaveCountLOC, octaveCount);&#xD;&#xA;gl.uniform1f(persistenceLOC, persistence);&#xD;&#xA;&#xD;&#xA;gl.drawArrays(gl.TRIANGLES, 0, 6);&#xD;&#xA;``` &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://flafla2.github.io/2014/08/09/perlinnoise.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/1oz6b.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/WdN3V.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26674" PostHistoryTypeId="1" PostId="9667" RevisionGUID="b2385500-ba05-43f9-9678-ed62430d4843" CreationDate="2020-03-27T12:34:20.123" UserId="12080" Text="Perlin Noise implementation looks blocky in WebGL2" ContentLicense="CC BY-SA 4.0" />
  <row Id="26675" PostHistoryTypeId="3" PostId="9667" RevisionGUID="b2385500-ba05-43f9-9678-ed62430d4843" CreationDate="2020-03-27T12:34:20.123" UserId="12080" Text="|algorithm|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26676" PostHistoryTypeId="5" PostId="8792" RevisionGUID="b5a24c22-6c31-4645-b7e1-34d3ae38acc9" CreationDate="2020-03-27T17:06:55.930" UserId="12056" Comment="fixed typo in type name (ec2 -&gt; vec2)" Text="I did not go into much detail with your code but the first thing that comes to mind is that you are rendering with respect to the resolution passed into the shader.&#xD;&#xA;&#xD;&#xA;    vec2 uv = fragCoord.xy/iResolution.xy;&#xD;&#xA;&#xD;&#xA;hope this helps.&#xD;&#xA;&#xD;&#xA;Maybe calculate the aspect ratio?&#xD;&#xA;&#xD;&#xA;    float aspect = float(iResolution.x) / float(iResolution.y ? iResolution.y: 1);" ContentLicense="CC BY-SA 4.0" />
  <row Id="26677" PostHistoryTypeId="24" PostId="8792" RevisionGUID="b5a24c22-6c31-4645-b7e1-34d3ae38acc9" CreationDate="2020-03-27T17:06:55.930" Comment="Proposed by 12056 approved by 6, 209 edit id of 513" ContentLicense="CC BY-SA 4.0" />
  <row Id="26680" PostHistoryTypeId="2" PostId="9668" RevisionGUID="5c5f0484-bff3-4d76-845e-dbd0b93b2fdf" CreationDate="2020-03-28T01:10:59.903" UserId="12073" Text="What are some common techniques for making the edges on a tesselated shape less apparent without increasing the amount of tesselation which is actually carried out?&#xD;&#xA;&#xD;&#xA;As an example, I followed along with this tutorial on [tesselation shaders](https://prideout.net/blog/old/blog/index.html@p=48.html), and one can control the inner and outer tesselation levels. With relatively low levels of both, one can achieve a pretty good sphere. However, in order for the surface to actually appear smooth, a fairly bright light seems to be required.&#xD;&#xA;&#xD;&#xA;This particular implementation uses triangular tesselation beginning from an icosahedron to approach a sphere.&#xD;&#xA;&#xD;&#xA;My understanding is that performing the tesselation with quads would result in a smoother surface.&#xD;&#xA;&#xD;&#xA;Here is a picture which illustrates how direct lighting makes it much harder to see the level of tesselation. On the top right of the sphere, where the light is hitting it strongly, no edges are visible, wheres on the bottom left, the edges can easily be seen. Perhaps in practice, simply applying a texture would mask many of the edges?&#xD;&#xA;&#xD;&#xA;[![tesselation and lighting][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c1XR6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="26681" PostHistoryTypeId="1" PostId="9668" RevisionGUID="5c5f0484-bff3-4d76-845e-dbd0b93b2fdf" CreationDate="2020-03-28T01:10:59.903" UserId="12073" Text="Techniques for making tesselated shapes appear smoother?" ContentLicense="CC BY-SA 4.0" />
  <row Id="26682" PostHistoryTypeId="3" PostId="9668" RevisionGUID="5c5f0484-bff3-4d76-845e-dbd0b93b2fdf" CreationDate="2020-03-28T01:10:59.903" UserId="12073" Text="|lighting|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26683" PostHistoryTypeId="2" PostId="9669" RevisionGUID="872f99d8-9ab7-4635-a3a1-4a40fabadd2d" CreationDate="2020-03-28T06:58:57.670" UserId="8125" Text="`glShadeModel(GL_SMOOTH);` - probably in PezInitialize - should do what you need." ContentLicense="CC BY-SA 4.0" />
  <row Id="26684" PostHistoryTypeId="2" PostId="9670" RevisionGUID="fc323fd5-e7d3-488f-9768-324724089443" CreationDate="2020-03-28T10:51:48.310" UserId="12082" Text="I am having trouble in making this program and DFA:-&#xD;&#xA;Write CPP program, DFA and NFA diagram for DFA accepting string with &#xD;&#xA;length 5 and starting at 0 , ending at 1 input(0, 1).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="26685" PostHistoryTypeId="1" PostId="9670" RevisionGUID="fc323fd5-e7d3-488f-9768-324724089443" CreationDate="2020-03-28T10:51:48.310" UserId="12082" Text="Write CPP program, DFA and NFA diagram for DFA accepting string with length 5 and starting at 0 , ending at 1 input(0, 1)" ContentLicense="CC BY-SA 4.0" />
  <row Id="26686" PostHistoryTypeId="3" PostId="9670" RevisionGUID="fc323fd5-e7d3-488f-9768-324724089443" CreationDate="2020-03-28T10:51:48.310" UserId="12082" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="26687" PostHistoryTypeId="6" PostId="9670" RevisionGUID="afb7e418-77e9-45aa-9a63-f1e881078137" CreationDate="2020-03-28T11:26:39.187" UserId="12082" Comment="edited tags" Text="|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27687" PostHistoryTypeId="50" PostId="9616" RevisionGUID="70d505a1-384e-4d82-a579-60c2575eaf33" CreationDate="2020-03-28T17:02:15.333" UserId="-1" />
  <row Id="27688" PostHistoryTypeId="5" PostId="4253" RevisionGUID="3f1daf61-5e74-45bb-883c-bf937cb88366" CreationDate="2020-03-28T17:52:30.003" UserId="182" Comment="Fixed typo." Text="Let's suppose a fairly typical raytracing main loop:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    struct Ray&#xD;&#xA;    {&#xD;&#xA;        vec3 origin;&#xD;&#xA;        vec3 direction;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    RGBColor* image = CreateImageBuffer(width, height);&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            float x = 2.0 * (float)i / (float)max(width, height) - 1.0;&#xD;&#xA;            float y = 2.0 * (float)j / (float)max(width, height) - 1.0;&#xD;&#xA;&#xD;&#xA;            vec3 dir = normalize(vec3(x, y, -tanHalfFov));&#xD;&#xA;            Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;            image[width * j + i] = ComputeColor(r);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;One possible modification of it to do 4 samples SSAA would be:&#xD;&#xA;&#xD;&#xA;&lt;!-- language: c++ --&gt;&#xD;&#xA;&#xD;&#xA;    float jitterMatrix[4 * 2] = {&#xD;&#xA;        -1.0/4.0,  3.0/4.0,&#xD;&#xA;         3.0/4.0,  1.0/3.0,&#xD;&#xA;        -3.0/4.0, -1.0/4.0,&#xD;&#xA;         1.0/4.0, -3.0/4.0,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (int j=0; j &lt; height; ++i)&#xD;&#xA;    {&#xD;&#xA;        for (int i=0; i &lt; width; ++i)&#xD;&#xA;        {&#xD;&#xA;            // Init the pixel to 100% black (no light).&#xD;&#xA;            image[width * j + i] = RGBColor(0.0);&#xD;&#xA;&#xD;&#xA;            // Accumulate light for N samples.&#xD;&#xA;            for (int sample = 0; sample &lt; 4; ++sample)&#xD;&#xA;            {&#xD;&#xA;                float x = 2.0 * (i + jitterMatrix[2*sample]) / (float)max(width, height) - 1.0;&#xD;&#xA;                float y = 2.0 * (i + jitterMatrix[2*sample+1]) / (float)max(width, height) - 1.0;&#xD;&#xA;&#xD;&#xA;                vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);&#xD;&#xA;                Ray r = { cameraPosition, dir };&#xD;&#xA;&#xD;&#xA;                image[width * j + i] += ComputeColor(r);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // Get the average.&#xD;&#xA;            image[width * j + i] /= 4.0;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Another possibility is to do a random jitter (instead of the matrix based one above), but you then soon enter the realm of signal processing and it takes a lot of reading to know how to choose a good noise function.&#xD;&#xA;&#xD;&#xA;The idea remains the same though: consider the pixel to represent a tiny square area, and instead of shooting only one ray that passes through the center of the pixel, shoot many rays covering the entire pixel area. The more dense the ray distribution is, the better signal you get.&#xD;&#xA;&#xD;&#xA;P.S.: I wrote the code above on the fly, so I'd expect a few errors in it. It's only meant to show the basic idea." ContentLicense="CC BY-SA 4.0" />
  <row Id="27689" PostHistoryTypeId="2" PostId="9671" RevisionGUID="3d06c088-778a-40d3-9beb-0cf5cb40bf9d" CreationDate="2020-03-28T18:27:57.937" UserId="13083" Text="I'm a noob to the OpenGL world and am picking up ideas through practice. I've been writing some code to build retro-arcade games recently and need to load textures to provide the graphic interface. I'm using OpenGL v4.6 with GLFW3 and the stb library to load images. &#xD;&#xA;&#xD;&#xA;To load textures, I draw a box and define the texture coordinates of the image on the box. Only some of the png's that I use have loaded properly- often, the image is blurred and distorted. There were two things I tried so far-&#xD;&#xA;&#xD;&#xA;1. Look exclusively for jpg files as these were loading properly. But most of the textures that I download of google are exclusively png&#xD;&#xA;&#xD;&#xA;2. Convert the png into a jpg file. Since I was converting, I decided to use other file formats as well, cropping some of the images if need be. I used GIMP to export them in jpg format. However, when I try to load it OpenGL, I still get bad-poor results.&#xD;&#xA;&#xD;&#xA;Another possible approach I'm considering is to convert them into dxt formats and see if that does the trick. However, this seems a tad too tedious and something I'd only go for if nothing else works. &#xD;&#xA;&#xD;&#xA;Below is the code that I'm using to load the image. &#xD;&#xA;```&#xD;&#xA;int width, height, nrChannels;&#xD;&#xA;unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 0);&#xD;&#xA;GLenum format{};&#xD;&#xA;if (data)&#xD;&#xA;{&#xD;&#xA;	if (nrChannels == 1)&#xD;&#xA;		format = GL_RED;&#xD;&#xA;	else if (nrChannels == 3)&#xD;&#xA;		format = GL_RGB;&#xD;&#xA;	else if (nrChannels == 4)&#xD;&#xA;		format = GL_RGBA;&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;	glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I'm starting to spend a significant amount of time looking for images that will load properly and less time learning/implementing; this is quite concerning. Can someone please point out where I'm going wrong or a better way of skirting around this issue?&#xD;&#xA;&#xD;&#xA;[![The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL][1]][1]&#xD;&#xA;The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL&#xD;&#xA;&#xD;&#xA;[![Example 2][2]][2]&#xD;&#xA;Again, the image to the left is the output from Opengl while the one to the right is the original image. Note the inclination of the render and lack of colour in it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p5Zz9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jORfg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27690" PostHistoryTypeId="1" PostId="9671" RevisionGUID="3d06c088-778a-40d3-9beb-0cf5cb40bf9d" CreationDate="2020-03-28T18:27:57.937" UserId="13083" Text="Texture loading- erratic working" ContentLicense="CC BY-SA 4.0" />
  <row Id="27691" PostHistoryTypeId="3" PostId="9671" RevisionGUID="3d06c088-778a-40d3-9beb-0cf5cb40bf9d" CreationDate="2020-03-28T18:27:57.937" UserId="13083" Text="|opengl|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27692" PostHistoryTypeId="2" PostId="9672" RevisionGUID="c5493c73-92b7-4c47-a144-507d865b0b05" CreationDate="2020-03-28T20:49:46.400" UserId="12080" Text="I made a mistake while translating the code from JavaScript to GLSL. The first line in the `perlinAux` function:&#xD;&#xA;&#xD;&#xA;```int xi = int(round(st.x)) &amp; 255;```&#xD;&#xA;&#xD;&#xA;It uses the round() function even though it is not necessary. Moreover, it seems that the [rounding direction can be implementation-specific][1]. Changing it to simply `int xi = int(st.x) &amp; 255` solves the problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/round.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="27693" PostHistoryTypeId="2" PostId="9673" RevisionGUID="20166a50-3e13-462f-900e-0e5b35200237" CreationDate="2020-03-28T21:43:03.300" UserId="13085" Text="I am learning about fragment shaders and have seen how by setting the colours of each vertex a triangle can be coloured via interpolation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However what if we want to use our own function to manually specify the colour of each fragment (e.g. for lighting or for creating a procedurally generated texture)?&#xD;&#xA;&#xD;&#xA;Is there any way to create a fragment shader that runs a user-defined function to determine the colour of each fragment instead of leaving it up to opengl to interpolate between vertex colours?&#xD;&#xA;&#xD;&#xA;As an example - is it possible to create a fragment shader that sets each fragment to a random colour? Or one that creates a striped effect by setting pixels between a certain x range to black and others to white?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sxTXz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27694" PostHistoryTypeId="1" PostId="9673" RevisionGUID="20166a50-3e13-462f-900e-0e5b35200237" CreationDate="2020-03-28T21:43:03.300" UserId="13085" Text="Running Fragment Shader per Fragment (Instead of per Vertex)" ContentLicense="CC BY-SA 4.0" />
  <row Id="27695" PostHistoryTypeId="3" PostId="9673" RevisionGUID="20166a50-3e13-462f-900e-0e5b35200237" CreationDate="2020-03-28T21:43:03.300" UserId="13085" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27696" PostHistoryTypeId="4" PostId="9673" RevisionGUID="d6db7e0c-a4c7-4a55-8510-0914ca3f1333" CreationDate="2020-03-28T21:53:32.403" UserId="13085" Comment="edited title" Text="Specifying Fragment Shader Values per Fragment (Instead of per Vertex)" ContentLicense="CC BY-SA 4.0" />
  <row Id="27697" PostHistoryTypeId="2" PostId="9674" RevisionGUID="128608e4-aced-4f56-b5ba-d9fefa3b2c21" CreationDate="2020-03-28T23:14:00.520" UserId="10658" Text="You can figure out which thread has the max value by modifying x: pack gl_LocalInvocationIndex in the least significant bits of x. The number of bits you need for the index depends on your group size.&#xD;&#xA;&#xD;&#xA;If you need all 32 bits of x then I suggest using 2 compute shaders - first record max per group. Then compute x again and compare." ContentLicense="CC BY-SA 4.0" />
  <row Id="27701" PostHistoryTypeId="2" PostId="9676" RevisionGUID="16413c0a-3861-4465-94dd-403957d579e8" CreationDate="2020-03-29T09:08:28.303" UserId="11386" Text="I am relatively new to compute shaders and gpgpu in general so bare with me if i am missing the point somewhere. &#xD;&#xA;&#xD;&#xA;The main thing i do not yet understand / see is how to get memory from a compute shader to global shader memory usable in a pixel shader without passing it back and forth between GPU and CPU. &#xD;&#xA;&#xD;&#xA;I am implementing an irradiance caching lighting solution with Unity3D for learning purposes. I have written a compute shader that calculates the spherical harmonic coefficients for each volume. Now i can go ahead and read those values back to gpu using buffer.GetData() on the cpu side and shader.SetGlobalVectorArray(), but as far as I understand that will copy the memory to CPU resulting in allocation overhead. &#xD;&#xA;&#xD;&#xA;I have seen similar posts where people were suggesting jsut doing the computation in a pixel shader to begin with, but i don't see how that is supposed to help? Which pixel shader and how? I only want these computations to be done once for each volume and they require parallel reduction. &#xD;&#xA;&#xD;&#xA;Potentially my search terms are inadequate but i cannot find any answer to how to get results from compute shaders to global shader memory. &#xD;&#xA;Thanks in advance " ContentLicense="CC BY-SA 4.0" />
  <row Id="27702" PostHistoryTypeId="1" PostId="9676" RevisionGUID="16413c0a-3861-4465-94dd-403957d579e8" CreationDate="2020-03-29T09:08:28.303" UserId="11386" Text="Sharing memory between compute shader and pixel shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="27703" PostHistoryTypeId="3" PostId="9676" RevisionGUID="16413c0a-3861-4465-94dd-403957d579e8" CreationDate="2020-03-29T09:08:28.303" UserId="11386" Text="|compute-shader|unity|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27704" PostHistoryTypeId="4" PostId="9673" RevisionGUID="a36f0433-ccac-471a-8263-02dbfe246dcd" CreationDate="2020-03-29T12:54:03.197" UserId="13085" Comment="edited title" Text="Specifying Fragment Shader Colors per Fragment (Instead of per Vertex)" ContentLicense="CC BY-SA 4.0" />
  <row Id="27706" PostHistoryTypeId="2" PostId="9677" RevisionGUID="3167aaee-4986-41fd-9c87-af54ff1be1f6" CreationDate="2020-03-29T19:52:41.857" UserId="13087" Text="I can't manage to produce a metallic looking sphere despite trying many things. I have the basics working, i.e shadows, refraction etc. but I'm not sure what combination of these will allow me to produce a metallic surface. I know that it should be reflective and retain it's color but how do I go about accomplishing that?&#xD;&#xA;This is my spec and diffuse calc:&#xD;&#xA;specular code = vec(1,1,1) * pow((std::max(0.f, dot(light, reflection))), spec)//white specular highlights&#xD;&#xA;&#xD;&#xA;diffuse code = 	vec diffuse = col*std::max(0.f, dot(normal, light));//col = object col&#xD;&#xA;&#xD;&#xA;I test if the object that is hit is reflective and calculate the reflection ray, but how do I make it look metallic after producing the reflective image on the sphere?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27707" PostHistoryTypeId="1" PostId="9677" RevisionGUID="3167aaee-4986-41fd-9c87-af54ff1be1f6" CreationDate="2020-03-29T19:52:41.857" UserId="13087" Text="How do I produce a metallic surface in ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27708" PostHistoryTypeId="3" PostId="9677" RevisionGUID="3167aaee-4986-41fd-9c87-af54ff1be1f6" CreationDate="2020-03-29T19:52:41.857" UserId="13087" Text="|raytracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27709" PostHistoryTypeId="5" PostId="9676" RevisionGUID="56ff50d0-3e83-4dc0-9af0-d9bc4d21b6e9" CreationDate="2020-03-30T06:39:03.923" UserId="209" Comment="minor spelling" Text="I am relatively new to compute shaders and gpgpu in general so bear with me if i am missing the point somewhere. &#xD;&#xA;&#xD;&#xA;The main thing i do not yet understand / see is how to get memory from a compute shader to global shader memory usable in a pixel shader without passing it back and forth between GPU and CPU. &#xD;&#xA;&#xD;&#xA;I am implementing an irradiance caching lighting solution with Unity3D for learning purposes. I have written a compute shader that calculates the spherical harmonic coefficients for each volume. Now i can go ahead and read those values back to gpu using buffer.GetData() on the cpu side and shader.SetGlobalVectorArray(), but as far as I understand that will copy the memory to CPU resulting in allocation overhead. &#xD;&#xA;&#xD;&#xA;I have seen similar posts where people were suggesting just doing the computation in a pixel shader to begin with, but i don't see how that is supposed to help? Which pixel shader and how? I only want these computations to be done once for each volume and they require parallel reduction. &#xD;&#xA;&#xD;&#xA;Potentially my search terms are inadequate but i cannot find any answer to how to get results from compute shaders to global shader memory. &#xD;&#xA;Thanks in advance " ContentLicense="CC BY-SA 4.0" />
  <row Id="27710" PostHistoryTypeId="2" PostId="9678" RevisionGUID="5e9d04d3-3ac4-46ee-b368-4082b2e65352" CreationDate="2020-03-30T10:14:41.127" UserId="11696" Text="I'm interpolating RGB values by transforming them into HSV space and then back into RGB. I have trouble figuring out how to achieve `interpolate(green, black, 0.5) = darkgreen`.&#xD;&#xA;&#xD;&#xA;Black has multiple representations in HSV, for example `(0, 0, 0)` and `(30, 0, 0)` are both black. When I convert the RGB black `#000000`, I turn it into `(0, 0, 0)`. When I then interpolate it with green `(120, 1, 1)`, I get `(60, 0.5, 0.5)` which is dark semi-saturated yellow. A similar issue exist for white.&#xD;&#xA;&#xD;&#xA;Am I supposed to choose a different color space? How can I make this correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27711" PostHistoryTypeId="1" PostId="9678" RevisionGUID="5e9d04d3-3ac4-46ee-b368-4082b2e65352" CreationDate="2020-03-30T10:14:41.127" UserId="11696" Text="Interpolating HSV color with black" ContentLicense="CC BY-SA 4.0" />
  <row Id="27712" PostHistoryTypeId="3" PostId="9678" RevisionGUID="5e9d04d3-3ac4-46ee-b368-4082b2e65352" CreationDate="2020-03-30T10:14:41.127" UserId="11696" Text="|color|interpolation|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27717" PostHistoryTypeId="2" PostId="9680" RevisionGUID="37fc2a1b-ba9c-4aaa-a98f-cf90e998d5a0" CreationDate="2020-03-30T13:39:30.087" UserId="13093" Text="I have been trying to detect defects on &quot;before-and-after&quot; meshes, by finding the boolean difference between them, to no avail.&#xD;&#xA;&#xD;&#xA;I tried these two Python libraries(algorithms run in C++) but their boolean operations would produce error or never finish:&#xD;&#xA;&#xD;&#xA; - PyVista(VTK wrapper) : https://docs.pyvista.org&#xD;&#xA; - Pymesh : https://pymesh.readthedocs.io&#xD;&#xA;&#xD;&#xA;More specifically, some testing and findings that I had:&#xD;&#xA;&#xD;&#xA; - The libraries would operate normally in any other case of boolean operations between two different meshes. &#xD;&#xA; - The 2 almost-identical meshes I wanted to use were clean and water-tight. I even used an example shape which I subtracted from itself. It crashed too.&#xD;&#xA; - These 2 similar meshes are originating from the same mesh, but with a small difference, like a dent or some noise. I tried to introduce stronger noise or bigger changes, but it still would not work if the 2 meshes had their biggest part identical. &#xD;&#xA; - by enlarging 1 of the 2 meshes by more than 0.1%, or by transforming/moving(see attached picture) it by a similar amount, the algorithm starts working. But by that point, the shapes are too different to be useful.&#xD;&#xA;&#xD;&#xA;[![meshes apart from each other][1]][1]&#xD;&#xA;&#xD;&#xA;To reproduce the error with Pyvista with an example shape from their website:&#xD;&#xA;&#xD;&#xA;    import pyvista as pv&#xD;&#xA;    mesh_knot = pv.read(&quot;knot.ply&quot;)&#xD;&#xA;    mesh_knot2 = pv.read(&quot;knot.ply&quot;)&#xD;&#xA;    mesh =  mesh_knot.boolean_difference(mesh_knot2)&#xD;&#xA;    mesh.plot(eye_dome_lighting=True)&#xD;&#xA;&#xD;&#xA;To conclude, has anyone any idea why this would happen? Do you think that there is a way to bypass the problem if no solution is found? Any other ideas of how I should approach my initial problem?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Av0ng.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27718" PostHistoryTypeId="1" PostId="9680" RevisionGUID="37fc2a1b-ba9c-4aaa-a98f-cf90e998d5a0" CreationDate="2020-03-30T13:39:30.087" UserId="13093" Text="What is the reason that a boolean operation between two almost identical 3D triangular meshes fails?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27719" PostHistoryTypeId="3" PostId="9680" RevisionGUID="37fc2a1b-ba9c-4aaa-a98f-cf90e998d5a0" CreationDate="2020-03-30T13:39:30.087" UserId="13093" Text="|3d|computational-geometry|mesh|vtk|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27725" PostHistoryTypeId="2" PostId="9682" RevisionGUID="85c1dd72-576d-4ee5-b5ad-7d7891cb10e0" CreationDate="2020-03-31T16:50:10.683" UserId="9438" Text="Without debugging the routines with the offending data, it's impossible to say conclusively. However given the examples you have given it sounds like the libraries are falling foul of the coplanar triangle cases when evaluating the meshes. This is certainly an *Achilles heel* of many CSG implementations out there (far to many in my experience). In many cases, both theory and implementations seem to fail to address these coplanar cases in many CSG libs. &#xD;&#xA;&#xD;&#xA;Certainly the fact that it crashes or fails to produce the desired result implies that the libraries you use are buggy or incomplete in this regard.&#xD;&#xA;&#xD;&#xA;&gt; The libraries would operate normally in any other case of Boolean operations between two different meshes. &#xD;&#xA;&#xD;&#xA;When there are no coplanar triangles between manifolds, the result is well defined and since CSG operations use triangle/triangle intersections fundamentally, if the case of coplanar triangle intersections is not accounted for, everything should be fine and dandy when there are no coplanar triangle tests between meshes. Of course this is not what you require, but makes sense that this operates normally in these scenarios.&#xD;&#xA;&#xD;&#xA;&gt; The 2 almost-identical meshes I wanted to use were clean and water-tight. I even used an example shape which I subtracted from itself. It crashed too.&#xD;&#xA;&#xD;&#xA;This is certainly not correct and I would say a bug. A crash implies something is very wrong and either the coplanar triangle support is buggy, limited, or simply not implemented at all.&#xD;&#xA;&#xD;&#xA;I suspect the latter unless you can get a result out with something simple such as diff'ing one cube from another... if you can get a result in some sandboxed cases, then it could be any of the former possibilities.&#xD;&#xA;&#xD;&#xA;To see if your CSG routines can handle the coplanar cases, subtracting one cube from another should produce nothing (which as you said it fails). You could also attempt to subtract one cube from another which has a single face coplanar. e.g. Two cubes, both of length *length*. One positioned at *x - length* should produce a cube which is a closed manifold. i.e. Cube A (1x1x1) positioned at 0,0,0... and cube B (1x1x1) positioned at 1,0,0.&#xD;&#xA;&#xD;&#xA;&gt; These 2 similar meshes are originating from the same mesh, but with a small difference, like a dent or some noise. I tried to introduce stronger noise or bigger changes, but it still would not work if the 2 meshes had their biggest part identical. &#xD;&#xA;&#xD;&#xA;Probably just one triangle in a mesh is coplanar to another triangle in the other mesh which you are operating on, and thus failing. This may be a way to test by creating two meshes with only one triangle from each mesh being coplanar to another in the other mesh. If this fails then It might indicate that this corner case of coplanar intersection is not catered for at all. As said above, if it does work, then this may point to buggy behaviour at much higher level when dealing with coplanar triangles.&#xD;&#xA;&#xD;&#xA;&gt; By enlarging 1 of the 2 meshes by more than 0.1%, or by transforming/moving(see attached picture) it by a similar amount, the algorithm starts working. But by that point, the shapes are too different to be useful.&#xD;&#xA;&#xD;&#xA;I presume these libs work on floating point numbers, in which case this sounds like the FP equality tolerances are kicking in and evaluating 'almost' coplanar triangles as coplanar, and then subsequently failing to result in the CSG operation. Of course this is problematic for you if the tolerances are high since the input geometry is expected to be 'different enough' to not fall within these tolerances.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Unfortunately, there is nothing you can really do which I think you would find satisfactory since you are effectively at the mercy of the accuracy of the implementation. &#xD;&#xA;&#xD;&#xA;If you suspect the libs can handle coplanar triangles between meshes, and its just failing in many cases, you might need to find out how you can kludge the input geometry to not fall foul of the shortcomings that may or may not be present for these corner cases in the implementations:&#xD;&#xA;&#xD;&#xA;* Remeshing the input geometry may help, although this may result is varying quality of input data in comparison to your measured data, which kind of defeats the purpose and will result in loss of accuracy wrt the original input meshes, but may at least give a result.&#xD;&#xA;&#xD;&#xA;* Re-tessellating triangles while retaining the mesh features may help. This involves inserting Steiner points into a given triangle and re-tessellating into more triangles. This will result in larger meshes (mem footprint, not geometrically speaking) but may help the routines to resolve coplanar intersections. Unlike the previous suggestion, It will retain the accuracy of the topology of the original meshes though.&#xD;&#xA;&#xD;&#xA;* Change the FP tolerance (if applicable) that the routines use which may allow you to keep meshes a similar size. However the problem is still there, but this may be satisfactory for your needs allowing you to not have to scale as much. Certainly from a visual standpoint this would be satisfactory I would have thought, however from a numerical point of view this may not be. However this does not fix the issue, rather attempt to circumvent it.&#xD;&#xA;&#xD;&#xA;Given that the majority of the meshes will perhaps be similar, if the vertices are what are similar (i.e coplanar triangles have the SAME vertex values, although that screen shot you posted suggests otherwise) you could perhaps simply diff the meshes yourself, finding all the vertices that are not equal when comparing and then tessellating these. This is far more complex though as you would need to keep track of the edges around the different vertices (these edges will use vertices which are equal to others in the other mesh, so not a quick and dirty fix, rather a slightly different approach avoiding the libs you use) so that you can tessellate the different vertices into a meaningful manifold. I wouldn't recommend this as it is quite a specialised case, and may not be generalised enough for your needs.&#xD;&#xA;&#xD;&#xA;Ultimately, if you can't circumvent the issue present with the current libs. You may have to find another. I certainly wasn't able to find many that matched my needs with a correct lic that was applicable to work, however I think there are certainly libs out there that would cater for this. Look for CAD libs as this is an important operation in many CAD programs.&#xD;&#xA;&#xD;&#xA;A few years ago I spent some time testing and evaluating various different C++ CSG libs for our needs at work as we required a fairly robust implementation for production. While there were various success, they all failed at some point, and coplanar triangles were usually the culprit. It's quite frustrating as the answer is actually quite straight forward and simply requires the Boolean operation to be performed in 2D between the coplanar triangles and then testing if the resulting split triangles are within the 'other' triangle. &#xD;&#xA;/rant" ContentLicense="CC BY-SA 4.0" />
  <row Id="27726" PostHistoryTypeId="5" PostId="9682" RevisionGUID="a273ed48-ff38-495c-9ac1-d021b3923df2" CreationDate="2020-03-31T17:45:45.027" UserId="9438" Comment="added 92 characters in body" Text="Without debugging the routines with the offending data, it's impossible to say conclusively. However given the examples you have given it sounds like the libraries are falling foul of the coplanar triangle cases when evaluating the meshes. This is certainly an *Achilles heel* of many CSG implementations out there (far to many in my experience). In many cases, both theory and implementations seem to fail to address these coplanar cases in many CSG libs. &#xD;&#xA;&#xD;&#xA;Certainly the fact that it crashes or fails to produce the desired result implies that the libraries you use are buggy or incomplete in this regard.&#xD;&#xA;&#xD;&#xA;&gt; The libraries would operate normally in any other case of Boolean operations between two different meshes. &#xD;&#xA;&#xD;&#xA;When there are no coplanar triangles between manifolds, the result is well defined and since CSG operations use triangle/triangle intersections fundamentally, if the case of coplanar triangle intersections is not accounted for, everything should be fine and dandy when there are no coplanar triangle tests between meshes. Of course this is not what you require, but makes sense that this operates normally in these scenarios.&#xD;&#xA;&#xD;&#xA;&gt; The 2 almost-identical meshes I wanted to use were clean and water-tight. I even used an example shape which I subtracted from itself. It crashed too.&#xD;&#xA;&#xD;&#xA;This is certainly not correct and I would say a bug. A crash implies something is very wrong and either the coplanar triangle support is buggy, limited, or simply not implemented at all.&#xD;&#xA;&#xD;&#xA;I suspect the latter unless you can get a result out with something simple such as diff'ing one cube from another... if you can get a result in some sandboxed cases, then it could be any of the former possibilities.&#xD;&#xA;&#xD;&#xA;To see if your CSG routines can handle the coplanar cases, subtracting one cube from another should produce nothing (which as you said it fails). You could also attempt to subtract one cube from another which has a single face coplanar. e.g. Two cubes, both of length *length*. One positioned at *x - length* should produce a cube which is a closed manifold. i.e. Cube A (1x1x1) positioned at 0,0,0... and cube B (1x1x1) positioned at 1,0,0.&#xD;&#xA;&#xD;&#xA;&gt; These 2 similar meshes are originating from the same mesh, but with a small difference, like a dent or some noise. I tried to introduce stronger noise or bigger changes, but it still would not work if the 2 meshes had their biggest part identical. &#xD;&#xA;&#xD;&#xA;Probably just one triangle in a mesh is coplanar to another triangle in the other mesh which you are operating on, and thus failing. This may be a way to test by creating two meshes with only one triangle from each mesh being coplanar to another in the other mesh. If this fails then It might indicate that this corner case of coplanar intersection is not catered for at all. As said above, if it does work, then this may point to buggy behaviour at much higher level when dealing with coplanar triangles.&#xD;&#xA;&#xD;&#xA;&gt; By enlarging 1 of the 2 meshes by more than 0.1%, or by transforming/moving(see attached picture) it by a similar amount, the algorithm starts working. But by that point, the shapes are too different to be useful.&#xD;&#xA;&#xD;&#xA;I presume these libs work on floating point numbers, in which case this sounds like the FP equality tolerances are kicking in and evaluating 'almost' coplanar triangles as coplanar, and then subsequently failing to result in the CSG operation. Of course this is problematic for you if the tolerances are high since the input geometry is expected to be 'different enough' to not fall within these tolerances.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Unfortunately, there is nothing you can really do which I think you would find satisfactory since you are effectively at the mercy of the accuracy of the implementation. &#xD;&#xA;&#xD;&#xA;If you suspect the libs can handle coplanar triangles between meshes, and its just failing in many cases, you might need to find out how you can kludge the input geometry to not fall foul of the shortcomings that may or may not be present for these corner cases in the implementations:&#xD;&#xA;&#xD;&#xA;* Remeshing the input geometry may help, although this may result is varying quality of input data in comparison to your measured data, which kind of defeats the purpose and will result in loss of accuracy wrt the original input meshes, but may at least give a result.&#xD;&#xA;&#xD;&#xA;* Re-tessellating triangles while retaining the mesh features may help. This involves inserting Steiner points into a given triangle and re-tessellating into more triangles. This will result in larger meshes (mem footprint, not geometrically speaking) but may help the routines to resolve coplanar intersections. Unlike the previous suggestion, It will retain the accuracy of the topology of the original meshes though.&#xD;&#xA;&#xD;&#xA;* Change the FP tolerance (if applicable) that the routines use which may allow you to keep meshes a similar size. However the problem is still there, but this may be satisfactory for your needs allowing you to not have to scale as much. Certainly from a visual standpoint this would be satisfactory I would have thought, however from a numerical point of view this may not be. However this does not fix the issue, rather attempt to circumvent it.&#xD;&#xA;&#xD;&#xA;Given that the majority of the meshes will perhaps be similar, if the vertices are what are similar (i.e coplanar triangles have the SAME vertex values, although that screen shot you posted suggests otherwise) you could perhaps simply diff the meshes yourself, finding all the vertices that are not equal when comparing and then tessellating these. This is far more complex though as you would need to keep track of the edges around the different vertices (these edges will use vertices which are equal to others in the other mesh, so not a quick and dirty fix, rather a slightly different approach avoiding the libs you use) so that you can tessellate the different vertices into a meaningful manifold. I wouldn't recommend this as it is quite a specialised case, and may not be generalised enough for your needs.&#xD;&#xA;&#xD;&#xA;Ultimately, if you can't circumvent the issue present with the current libs. You may have to find another. I certainly wasn't able to find many that matched my needs with a correct lic that was applicable to work, however I think there are certainly libs out there that would cater for this. Look for CAD libs as this is an important operation in many CAD programs.&#xD;&#xA;&#xD;&#xA;A few years ago I spent some time testing and evaluating various different C++ CSG libs for our needs at work as we required a fairly robust implementation for production. While there were various success, they all failed at some point, and coplanar triangles were usually the culprit. It's quite frustrating as the answer is actually quite straight forward and simply requires the Boolean operation to be performed in 2D between the coplanar triangles and then testing if the resulting split triangles are within the 'other' triangle. Why this rather crucial point is missed in a lot of implementations and theory is beyond me.&#xD;&#xA;/rant" ContentLicense="CC BY-SA 4.0" />
  <row Id="27730" PostHistoryTypeId="2" PostId="9684" RevisionGUID="0569acef-feb9-49f6-ba53-a0060bdf42aa" CreationDate="2020-03-31T22:23:34.110" UserId="9438" Text="GL_SMOOTH interpolates the vertex attributes of the primitive (triangle), it looks like your normals are setup per face, rather than per vertex. &#xD;&#xA;&#xD;&#xA;If using normal per face (i.e. a single normal for the triangle), increasing the number of triangles will produce a less faceted look as there is more granularity when interpolating the normals over the surface of a given surface area given the increase in the number of triangles within that area. It is recommended to use normals per vertex for smooth surfaces when feature edges are not important (i.e. Not for cubes!).&#xD;&#xA;&#xD;&#xA;If using normal per vertex (i.e. a normal for each vertex, resulting in each triangle having 3 vertices), each 3 vertices of a face will be slightly different if the neighbouring triangles are not coplanar to the triangle in question (i.e. not a flat surface). This will aid in the smoothness of the shading.&#xD;&#xA;&#xD;&#xA;Normals per vertex can be easily calculated by averaging the three normals of the three vertices defining a triangle, however your surface needs to be defined with shared vertices for this. The exception to this is if you have a sphere or ellipsoid, in which case you can calculate a more precise normal easily by unitising *vertex - sphereOrigin* rather than averaging the three normals of the face.&#xD;&#xA;&#xD;&#xA;On a side note: Are you using two lights in the scene of the screen shot you posted or one? If two it looks like the normals are currently not correct as the shading does not appear correct since there is a well-lit area of the surface on the bottom left region. With a single light, either the front (top right) of the sphere would be lit, or the bottom left, but not both.&#xD;&#xA;&#xD;&#xA;Also note that simply increasing the power of the light simply over exposes the surface colour rather than improving the smoothing. You lose the surface definition.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27731" PostHistoryTypeId="50" PostId="9591" RevisionGUID="95e01aa5-2646-45bf-9c76-8be0fcbc10df" CreationDate="2020-04-01T13:02:30.313" UserId="-1" />
  <row Id="27732" PostHistoryTypeId="5" PostId="9671" RevisionGUID="b14cca99-85eb-4004-92bc-bff3532d7157" CreationDate="2020-04-01T14:52:21.257" UserId="13083" Comment="added 2227 characters in body" Text="I'm a noob to the OpenGL world and am picking up ideas through practice. I've been writing some code to build retro-arcade games recently and need to load textures to provide the graphic interface. I'm using OpenGL v4.6 with GLFW3 and the stb library to load images. &#xD;&#xA;&#xD;&#xA;To load textures, I draw a box and define the texture coordinates of the image on the box. Only some of the png's that I use have loaded properly- often, the image is blurred and distorted. There were two things I tried so far-&#xD;&#xA;&#xD;&#xA;1. Look exclusively for jpg files as these were loading properly. But most of the textures that I download of google are exclusively png&#xD;&#xA;&#xD;&#xA;2. Convert the png into a jpg file. Since I was converting, I decided to use other file formats as well, cropping some of the images if need be. I used GIMP to export them in jpg format. However, when I try to load it OpenGL, I still get bad-poor results.&#xD;&#xA;&#xD;&#xA;Another possible approach I'm considering is to convert them into dxt formats and see if that does the trick. However, this seems a tad too tedious and something I'd only go for if nothing else works. &#xD;&#xA;&#xD;&#xA;Below is the code that I'm using to load the image. &#xD;&#xA;```&#xD;&#xA;int width, height, nrChannels;&#xD;&#xA;unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 0);&#xD;&#xA;GLenum format{};&#xD;&#xA;if (data)&#xD;&#xA;{&#xD;&#xA;	if (nrChannels == 1)&#xD;&#xA;		format = GL_RED;&#xD;&#xA;	else if (nrChannels == 3)&#xD;&#xA;		format = GL_RGB;&#xD;&#xA;	else if (nrChannels == 4)&#xD;&#xA;		format = GL_RGBA;&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);&#xD;&#xA;	glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I'm starting to spend a significant amount of time looking for images that will load properly and less time learning/implementing; this is quite concerning. Can someone please point out where I'm going wrong or a better way of skirting around this issue?&#xD;&#xA;&#xD;&#xA;[![The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL][1]][1]&#xD;&#xA;The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL&#xD;&#xA;&#xD;&#xA;[![Example 2][2]][2]&#xD;&#xA;Again, the image to the left is the output from Opengl while the one to the right is the original image. Note the inclination of the render and lack of colour in it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p5Zz9.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jORfg.png&#xD;&#xA;&#xD;&#xA;------------------------------------&#xD;&#xA;Edit: Here are some of the implementation details-&#xD;&#xA;&#xD;&#xA;I'm believe this portion should be correct because the render is perfect for .jpg files. _rect_ is a vector to hold the box and texture coordinates and _ind_ is a vector that holds the indices that are used by the element buffer to avoid repeat drawing. Both are initialised as arrays and converted into a vector (loop through array and push_back into vector). &#xD;&#xA;&#xD;&#xA;PS. Apologies for the verbosity. I was trying to couch the drawing inside a class and this was my first attempt at it. So, please bear with me.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// Box container to hold images&#xD;&#xA;//             x      y   tex-x   tex-y    &#xD;&#xA;const float rect[] = {&#xD;&#xA;			-0.2f, -0.2f, 0.0f, 0.0f,&#xD;&#xA;			 0.2f, -0.2f, 1.0f, 0.0f,&#xD;&#xA;			 0.2f,  0.2f, 1.0f, 1.0f,&#xD;&#xA;			-0.2f,  0.2f, 0.0f, 1.0f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;int ind[] = {&#xD;&#xA;		0,1,2,&#xD;&#xA;		0,2,3&#xD;&#xA;	};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;_num_attr_ is the number of attributes given to the vao, which in this case is 2. _cumsum_ contains the sum of the number of attributes and is used to assign the stride and size of each attribute.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;sizes = {2,2}; // initialized &#xD;&#xA;cumsum = 0;&#xD;&#xA;for (int i = 0; i &lt; num_attr; ++i)&#xD;&#xA;{&#xD;&#xA;	attr_num_cumsum.push_back(cumsum);&#xD;&#xA;	cumsum += sizes[i];&#xD;&#xA;	attr_size.push_back(sizes[i]);	&#xD;&#xA;}&#xD;&#xA;attr_num_cumsum.push_back(cumsum);&#xD;&#xA;```&#xD;&#xA;At the end of this block, _cumsum_ has a value of 4 and _attr_num_cumsum_ = {0,2,4} and _attr_size_ = {2,2}.&#xD;&#xA;&#xD;&#xA;_vbo_data_ contains the values in _rect_ while _ebo_data_ contains the values in _ind_ Here is the buffer set-up for drawing-&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glBindVertexArray(vao);&#xD;&#xA;glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;glBufferData(GL_ARRAY_BUFFER, vbo_data.size()*sizeof(GL_FLOAT), &amp;vbo_data[0], GL_DYNAMIC_DRAW);&#xD;&#xA;glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;glBufferData(GL_ELEMENT_ARRAY_BUFFER, ebo_data.size()*sizeof(GL_INT), &amp;ebo_data[0], GL_DYNAMIC_DRAW);&#xD;&#xA;for (int i = 0; i &lt; num_attr; ++i)&#xD;&#xA;{&#xD;&#xA;	glVertexAttribPointer(i, attr_size[i], GL_FLOAT, GL_FALSE, attr_num_cumsum[num_attr] * sizeof(GL_FLOAT), (void*)(attr_num_cumsum[i] * sizeof(GL_FLOAT)));&#xD;&#xA;	glEnableVertexAttribArray(i);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And the actual drawing&#xD;&#xA;```&#xD;&#xA;glBindVertexArray(vao);&#xD;&#xA;glDrawElements(GL_TRIANGLES, num_vertices, GL_UNSIGNED_INT, 0);&#xD;&#xA;```&#xD;&#xA;Vertex Shader&#xD;&#xA;```&#xD;&#xA;#version 460 core&#xD;&#xA;layout(location = 0) in vec2 aPos;&#xD;&#xA;layout(location = 1) in vec2 tex;&#xD;&#xA;out float C;&#xD;&#xA;out vec2 Tex;&#xD;&#xA;uniform mat4 model;&#xD;&#xA;uniform float col;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	gl_Position = model*vec4(aPos.x,aPos.y,0.0f, 1.0f);&#xD;&#xA;	C=col;&#xD;&#xA;	Tex=tex;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;Fragment Shader&#xD;&#xA;```&#xD;&#xA;#version 460 core&#xD;&#xA;out vec4 Fragcolor;&#xD;&#xA;in float C;&#xD;&#xA;in vec2 Tex;&#xD;&#xA;uniform sampler2D texture1;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	Fragcolor = texture(texture1,Tex);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="27747" PostHistoryTypeId="50" PostId="7804" RevisionGUID="808be610-39e2-4b40-963f-d4b67c2cdf28" CreationDate="2020-04-03T16:02:00.267" UserId="-1" />
  <row Id="27754" PostHistoryTypeId="2" PostId="9691" RevisionGUID="8052369c-dad2-4add-9212-fd955b5918fc" CreationDate="2020-04-04T08:58:12.233" UserId="9254" Text="Let $h_j$ denote the image reconstruction filter of pixel $j$. &#xD;&#xA;I'm estimating the color value $$I_j=\int h_jf\:{\rm d}\mu$$ of the $j$th pixel (see [[Veach, Section 8.2]](http://graphics.stanford.edu/papers/veach_thesis/thesis.pdf)) by an asymptotically consistent estimator whose asymptotic variance is given by $\sigma^2_j$. (This has to be understood in a component-wise sense, i.e. $\sigma_j^2$ is a 3-dimensional vector whose $i$th component is the asymptotic variance of the estimate of the $i$th component of $I_j$.&#xD;&#xA;&#xD;&#xA;&gt; **Question 1**: I want to compare different estimators which lead to different asymptotic variances and would like to visualize that one is superior to another (with respect to variance reduction). How can I do that? Simply writing the variances into an image doesn't seem to be sensible. (The problem is the scale of the values.)&#xD;&#xA;&#xD;&#xA;&gt; **Question 2**: For simplicity, assume a box filter with radius $\frac12$ so that the computation of $I_j$ only involves the $j$th pixel. Instead of considering the variances of each pixel, I've seen that we could consider the variances of a &quot;local window&quot; (for example a $3\times 3$ pixel window). Is this a better or worse metric for the total variance of the image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27755" PostHistoryTypeId="1" PostId="9691" RevisionGUID="8052369c-dad2-4add-9212-fd955b5918fc" CreationDate="2020-04-04T08:58:12.233" UserId="9254" Text="Visualize the variance of an image" ContentLicense="CC BY-SA 4.0" />
  <row Id="27756" PostHistoryTypeId="3" PostId="9691" RevisionGUID="8052369c-dad2-4add-9212-fd955b5918fc" CreationDate="2020-04-04T08:58:12.233" UserId="9254" Text="|raytracing|pathtracing|image-processing|monte-carlo|image-comparison|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27757" PostHistoryTypeId="2" PostId="9692" RevisionGUID="f53c3e67-e76b-4d8e-99ea-0a8c942340c4" CreationDate="2020-04-04T10:04:55.540" UserId="9774" Text="By given belows,&#xA;Base mesh(vertices, faces, texture coordinates - UV map),&#xA;Normal map(1024x1024 image),&#xA;Displacement map(1024x1024 image), &#xA;I want to make a mesh which reflects the displacement map. Since the vertices of the base mesh is not directly corresponds  to those maps, it seems that a re-meshing method based on the displacement map is required. Can someone tell me what method is applicable?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27758" PostHistoryTypeId="1" PostId="9692" RevisionGUID="f53c3e67-e76b-4d8e-99ea-0a8c942340c4" CreationDate="2020-04-04T10:04:55.540" UserId="9774" Text="What algorithms are needed to map displacement to base mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27759" PostHistoryTypeId="3" PostId="9692" RevisionGUID="f53c3e67-e76b-4d8e-99ea-0a8c942340c4" CreationDate="2020-04-04T10:04:55.540" UserId="9774" Text="|algorithm|mesh|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27760" PostHistoryTypeId="50" PostId="9626" RevisionGUID="eb385c65-0223-4c36-86ea-c8c4f5c0da9e" CreationDate="2020-04-04T11:02:05.240" UserId="-1" />
  <row Id="27761" PostHistoryTypeId="50" PostId="9307" RevisionGUID="e6cc3cfd-f0b7-4471-98ff-28319d654bb8" CreationDate="2020-04-04T18:02:10.420" UserId="-1" />
  <row Id="27762" PostHistoryTypeId="2" PostId="9693" RevisionGUID="fb64cb16-f196-46cf-ad9f-8322ce46bbb8" CreationDate="2020-04-04T19:15:36.617" UserId="10615" Text="I want to use Vulkan's rasterization to solve for the visibility problem, but once that is done I want to do shading, reflection and transmission through a raytracer which also runs on the GPU. With a lot of geometry however it's pretty much a need to have some sort of binary partition tree. How can I have C++ and the vulkan shader language communicate this tree? I thought about pushing the tree into GPU memory wrapped in a buffer, but then of course pointers to the left and right bounding box node (it's a binary tree) wouldn't translate.&#xD;&#xA;&#xD;&#xA;It seems my only option is to pass an array of bounding boxes, then pass a tree which just keeps indexes of this array instead of absolute pointers, but that really seems like a botch, because I'll need to traverse the entire tree to assemble the linear array and convert the pointers to indexes of that array.&#xD;&#xA;&#xD;&#xA;I would also need to keep in mind how the compiler packs structs (and thus how I read them in the shader). For now I won't even consider that certain datatypes of certain sizes may not even exist on some gpus to keep my head from exploding.&#xD;&#xA;&#xD;&#xA;Since generating a bsp tree is badly parallelizable I'm not considering doing it on the gpu.&#xD;&#xA;&#xD;&#xA;Edit: the objects will also be interacting physically so I need to have a tree available for the CPU as well. I can't just keep all of the geometry on the GPU from the get go." ContentLicense="CC BY-SA 4.0" />
  <row Id="27763" PostHistoryTypeId="1" PostId="9693" RevisionGUID="fb64cb16-f196-46cf-ad9f-8322ce46bbb8" CreationDate="2020-04-04T19:15:36.617" UserId="10615" Text="Feeding acceleration structure to the GPU then raytracing it in a compute shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27764" PostHistoryTypeId="3" PostId="9693" RevisionGUID="fb64cb16-f196-46cf-ad9f-8322ce46bbb8" CreationDate="2020-04-04T19:15:36.617" UserId="10615" Text="|raytracing|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27765" PostHistoryTypeId="2" PostId="9694" RevisionGUID="7ed49a0a-6dcc-44fa-a4b5-e2df56688b6e" CreationDate="2020-04-05T02:02:57.990" UserId="7072" Text="I am following the algorithm shown in [this code][1] here. Essentially there is a simple simulation of heights and then the difference in heights on the x and y axis respectively (sampling adjacent points) ends up defining how much you add/subtract to your texture coordinate.&#xD;&#xA;&#xD;&#xA;The result is displayed in this video [here][2] &#xD;&#xA;&#xD;&#xA;My question is essentially do you think you could write a fragment shader that adds some sort of good looking specular highlight to this. Almost as though there were some sort of light off the edge. Just to add more feeling of depth/shape.&#xD;&#xA;&#xD;&#xA;So far the only thing I have thought of is to look at the difference between the distorted and the normal texture coordinate which ends up looking something like this:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;However since that vector is inherently 2D I am not sure how to figure out a 3D normal that would be useful for calculating the specular.&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/robovm/apple-ios-samples/tree/master/GLCameraRipple&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=0KoqUdynPpY&#xD;&#xA;  [3]: https://i.stack.imgur.com/0xWJJ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="27766" PostHistoryTypeId="1" PostId="9694" RevisionGUID="7ed49a0a-6dcc-44fa-a4b5-e2df56688b6e" CreationDate="2020-04-05T02:02:57.990" UserId="7072" Text="Adding specular reflections to a ripple simulation" ContentLicense="CC BY-SA 4.0" />
  <row Id="27767" PostHistoryTypeId="3" PostId="9694" RevisionGUID="7ed49a0a-6dcc-44fa-a4b5-e2df56688b6e" CreationDate="2020-04-05T02:02:57.990" UserId="7072" Text="|lighting|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27768" PostHistoryTypeId="2" PostId="9695" RevisionGUID="6fda248a-e3b0-4dbd-aa52-8f0fb3150166" CreationDate="2020-04-05T11:48:21.053" UserId="13124" Text="If using the new real-time ray tracing functionality is an option for you, it would be worth a try! It might be that getting it to run is less work than porting your CPU data structure into a GPU-compatible format. Furthermore, using the hardware functionality would result in much better performance since BVH traversal (and triangle intersection, if that is relevant to you) are accelerated in hardware.&#xD;&#xA;&#xD;&#xA;Official real-time ray tracing support has been announced by Khronos (in the form of an `KHR` extension) lately, see [Ray Tracing In Vulkan](https://www.khronos.org/blog/ray-tracing-in-vulkan). With the Vulkan API version 1.2, the option for &quot;Ray Queries&quot; has been added. It could be relevant for your use case since it allows to trace rays against the BVH from arbitrary shaders (i.e., e.g., also from compute shaders or fragment shaders).&#xD;&#xA;&#xD;&#xA;Using real-time ray tracing, you would have to update the acceleration structure on the GPU every time after you have updated your CPU data structure. The API supports updating acceleration structures every frame. In NVIDIA's extension this is done via the `VkBool32 update` flag in [`vkCmdBuildAccelerationStructureNV`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdBuildAccelerationStructureNV.html). In the KHR-extension it is handled a bit differently, but in a very similar fashion: The update-flags are contained in the [`VkAccelerationStructureBuildGeometryInfoKHR`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkAccelerationStructureBuildGeometryInfoKHR.html) structures." ContentLicense="CC BY-SA 4.0" />
  <row Id="27770" PostHistoryTypeId="2" PostId="9696" RevisionGUID="c8421f08-e7c3-410a-b984-00429ca4866f" CreationDate="2020-04-06T06:38:58.347" UserId="13083" Text="Briefly, modify the stb_load as follows and everything should work.&#xD;&#xA;```&#xD;&#xA;unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 0);&#xD;&#xA;nrChannels = 4;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Details:*&#xD;&#xA;Okay, after a lot of heartache trying and failing to get libpng to work, I finally decided to have a look at the stbi implementation that I'm using to load the texture files. This is where the problem comes in from. &#xD;&#xA;&#xD;&#xA;@wychmaster was right when he suspected that there was an incorrect stride used. The problem, though, is in the reading of the image. Apparently, this has something to do with alignment of pixel data which is set by glPixelStorei. &#xD;&#xA;&#xD;&#xA;Someone posted the same problem in https://github.com/nothings/stb/issues/335 and determined that this was solution (it works!).&#xD;&#xA;&#xD;&#xA;The solution is to set the number of desired channels to 4 in the loading function and read the image as an RGBA instead of whatever the image format actually is. This works and all the misaligned images are now perfect. The images that worked before continue to work too. &#xD;&#xA;&#xD;&#xA;But, I do completely understand why nothing else is affected. This seems strange to me... If someone can explain why this works, I'd be quite grateful for the help. In the event this is a niche question, I'll likely return to make a more detailed post on it. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27774" PostHistoryTypeId="50" PostId="9303" RevisionGUID="f1831cbd-81e3-4bbb-b987-6154e5429b57" CreationDate="2020-04-06T13:02:45.387" UserId="-1" />
  <row Id="27775" PostHistoryTypeId="5" PostId="9696" RevisionGUID="8634e2aa-7e6c-4c15-8557-7140c419dcbd" CreationDate="2020-04-06T13:50:35.210" UserId="13083" Comment="deleted 4 characters in body" Text="Briefly, modify the stb_load as follows and everything should work.&#xD;&#xA;```&#xD;&#xA;unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 0);&#xD;&#xA;nrChannels = 4;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Details:*&#xD;&#xA;Okay, after a lot of heartache trying and failing to get libpng to work, I finally decided to have a look at the stbi implementation that I'm using to load the texture files. This is where the problem comes in from. &#xD;&#xA;&#xD;&#xA;@wychmaster was right when he suspected that there was an incorrect stride used. The problem, though, is in the reading of the image. Apparently, this has something to do with alignment of pixel data which is set by glPixelStorei. &#xD;&#xA;&#xD;&#xA;Someone posted the same problem in https://github.com/nothings/stb/issues/335 and determined that this was solution (it works!).&#xD;&#xA;&#xD;&#xA;The solution is to set the number of desired channels to 4 in the loading function and read the image as an RGBA instead of whatever the image format actually is. This works and all the misaligned images are now perfect. The images that worked before continue to work too. &#xD;&#xA;&#xD;&#xA;But, I do not completely understand why nothing else is affected. This seems strange to me... If someone can explain why this works, that would be very helpful. In the event this is a niche question, I'll likely return to make a more detailed post on it. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27780" PostHistoryTypeId="50" PostId="9178" RevisionGUID="798207f5-9b76-4a9a-86f1-8147c00c9183" CreationDate="2020-04-06T23:01:00.230" UserId="-1" />
  <row Id="27781" PostHistoryTypeId="50" PostId="9328" RevisionGUID="ab6a1a64-d8bc-470e-9b1f-c68959e5eeab" CreationDate="2020-04-07T01:02:20.360" UserId="-1" />
  <row Id="27782" PostHistoryTypeId="50" PostId="9606" RevisionGUID="13203350-6d1f-4769-a919-089c7b5d908b" CreationDate="2020-04-07T19:01:25.343" UserId="-1" />
  <row Id="27786" PostHistoryTypeId="50" PostId="5996" RevisionGUID="c3625540-252e-4bee-a8aa-80df6954541c" CreationDate="2020-04-08T12:03:30.483" UserId="-1" />
  <row Id="27794" PostHistoryTypeId="2" PostId="9702" RevisionGUID="2d41f0d6-fa6d-4ae6-92f3-524032aa770a" CreationDate="2020-04-08T21:30:38.133" UserId="7462" Text="Assume you have a list of vertices and their connectivity information. (I.e you can find all the adjacent edges and faces to each vertex).&#xD;&#xA;&#xD;&#xA;What is a good approach to calculate a normal from this information?&#xD;&#xA;&#xD;&#xA;Currently I first tried naive averaging, i.e:&#xD;&#xA;&#xD;&#xA;$\frac{\sum n_i}{N}$&#xD;&#xA;&#xD;&#xA;Where $n_i$ are the face normals and $N$ is the total number of faces&#xD;&#xA;&#xD;&#xA;And I also tried:&#xD;&#xA;&#xD;&#xA;$\frac{\sum n_i * a_i}{A}$&#xD;&#xA;&#xD;&#xA;Where $a_i$ are the respective areas of each face and $A$ is the sum of the areas of all adjacent faces.&#xD;&#xA;&#xD;&#xA;The first gave me this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The second gave me this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What I want is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;That last image I obtained by setting the normal to be the vector from the origin to the vertex position, but this is only true for highly regular meshes like cubes and spheres, it doesn't hold generally. The data I am using to make this is just the default blender cube.&#xD;&#xA;&#xD;&#xA;Increasing precision to doubles doesn't seem to affect the result. This is the wiremesh:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Obviously the issue occurs because the number of faces adjacent to a vertex isn't balanced, which skews the normals into certain directions, but I don;t know how to compensate for that&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5n4Rc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Mht2J.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rVP44.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Hrj1f.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27795" PostHistoryTypeId="1" PostId="9702" RevisionGUID="2d41f0d6-fa6d-4ae6-92f3-524032aa770a" CreationDate="2020-04-08T21:30:38.133" UserId="7462" Text="Calculate normals from vertices" ContentLicense="CC BY-SA 4.0" />
  <row Id="27796" PostHistoryTypeId="3" PostId="9702" RevisionGUID="2d41f0d6-fa6d-4ae6-92f3-524032aa770a" CreationDate="2020-04-08T21:30:38.133" UserId="7462" Text="|computational-geometry|mesh|geometry|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27797" PostHistoryTypeId="50" PostId="9631" RevisionGUID="918eac64-02eb-482e-9a8f-e996221daa38" CreationDate="2020-04-09T09:00:55.090" UserId="-1" />
  <row Id="27798" PostHistoryTypeId="2" PostId="9703" RevisionGUID="b512a94c-9384-47a4-8fb1-b9c10dc52177" CreationDate="2020-04-09T09:54:30.173" UserId="13147" Text="I am currently writing a 3D rendering engine for educational purposes. In general everything is working except that I am chasing down a problem in my cube mesh / tangent calculations that I can't find.&#xD;&#xA;This picture shows the tangent fragment position I receive in the fragment shader. As you can see, there's clearly an issue here:&#xD;&#xA;&#xD;&#xA;![Tangent fragment position][1]&#xD;&#xA;&#xD;&#xA;I tried to find this issue for quite some time - at this point I'm probably missing the obvious. What I have been trying to do so far:&#xD;&#xA;&#xD;&#xA; - Ensuring that it's not a winding order issue: In that case face culling would make the faces disappear - that's not happening here.&#xD;&#xA; - Tripple checking tangent calculation (function `mesh::calculate_tangents()`)&#xD;&#xA; - Tripple checking TBN matrix calculation&#xD;&#xA;&#xD;&#xA;Unfortunately, I am unable to find the problem. Any help on this would be greatly appreciated!&#xD;&#xA;&#xD;&#xA;To get started, here's my `vertex` struct definition:&#xD;&#xA;```&#xD;&#xA;    struct vertex {&#xD;&#xA;        glm::vec3 position;&#xD;&#xA;        glm::vec3 normal;&#xD;&#xA;        glm::vec2 texture_uv;&#xD;&#xA;        glm::vec3 tangent;&#xD;&#xA;        glm::vec3 bitangent;&#xD;&#xA;    };&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;`cube.cpp`:&#xD;&#xA;```c++&#xD;&#xA;cube::cube()&#xD;&#xA;{&#xD;&#xA;    constexpr std::size_t vertices_count = 36;&#xD;&#xA;&#xD;&#xA;    std::array&lt;glm::vec3, vertices_count&gt; positions = {&#xD;&#xA;            glm::vec3(-0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3(-0.5f,  0.5f, -0.5f),&#xD;&#xA;&#xD;&#xA;            glm::vec3(-0.5f, -0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f,  0.5f),&#xD;&#xA;&#xD;&#xA;            glm::vec3(-0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f,  0.5f,  0.5f),&#xD;&#xA;&#xD;&#xA;            glm::vec3( 0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f,  0.5f),&#xD;&#xA;&#xD;&#xA;            glm::vec3(-0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f, -0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f, -0.5f, -0.5f),&#xD;&#xA;&#xD;&#xA;            glm::vec3(-0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3( 0.5f,  0.5f,  0.5f),&#xD;&#xA;            glm::vec3(-0.5f,  0.5f, -0.5f),&#xD;&#xA;            glm::vec3(-0.5f,  0.5f,  0.5f),&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    std::array&lt;glm::vec2, vertices_count&gt; texture_uv = {&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(1.0f, 1.0f),&#xD;&#xA;            glm::vec2(1.0f, 0.0f),&#xD;&#xA;            glm::vec2(0.0f, 1.0f),&#xD;&#xA;            glm::vec2(0.0f, 0.0f),&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    std::array&lt;glm::vec3, vertices_count&gt; normals = {&#xD;&#xA;            glm::vec3( 0.0f,  0.0f, -1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f, -1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f, -1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f, -1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f, -1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f, -1.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec3( 0.0f,  0.0f,  1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f,  1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f,  1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f,  1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f,  1.0f),&#xD;&#xA;            glm::vec3( 0.0f,  0.0f,  1.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec3(-1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3(-1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3(-1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3(-1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3(-1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3(-1.0f,  0.0f,  0.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec3( 1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3( 1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3( 1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3( 1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3( 1.0f,  0.0f,  0.0f),&#xD;&#xA;            glm::vec3( 1.0f,  0.0f,  0.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec3( 0.0f, -1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f, -1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f, -1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f, -1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f, -1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f, -1.0f,  0.0f),&#xD;&#xA;&#xD;&#xA;            glm::vec3( 0.0f,  1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f,  1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f,  1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f,  1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f,  1.0f,  0.0f),&#xD;&#xA;            glm::vec3( 0.0f,  1.0f,  0.0f),&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    // Build indices&#xD;&#xA;    std::vector&lt;GLuint&gt; indices;&#xD;&#xA;    for (std::size_t i = 0; i &lt; vertices_count; ++i) {&#xD;&#xA;        indices.emplace_back(static_cast&lt;GLuint&gt;(i));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Build vertices&#xD;&#xA;    std::vector&lt;vertex&gt; vertices = build_vertices(std::move(positions), std::move(normals), std::move(texture_uv));&#xD;&#xA;&#xD;&#xA;    // Textures&#xD;&#xA;    std::vector&lt;texture&gt; textures;&#xD;&#xA;	// ...&#xD;&#xA;&#xD;&#xA;    // Create mesh&#xD;&#xA;    mesh m(std::move(vertices), std::move(indices), std::move(textures));&#xD;&#xA;    m.calculate_tangents();&#xD;&#xA;    set_mesh(std::move(m));&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Function `mesh::calculate_tangents()`:&#xD;&#xA;```&#xD;&#xA;void mesh::calculate_tangents()&#xD;&#xA;{&#xD;&#xA;    for (std::size_t i = 0; i &lt; m_indices.size()-2; ++i)&#xD;&#xA;    {&#xD;&#xA;        // Honor indices order&#xD;&#xA;        const GLuint&amp; index1 = m_indices.at(i + 0);&#xD;&#xA;        const GLuint&amp; index2 = m_indices.at(i + 1);&#xD;&#xA;        const GLuint&amp; index3 = m_indices.at(i + 2);&#xD;&#xA;&#xD;&#xA;        // Get the three adjacent vertices&#xD;&#xA;        const auto&amp; v1 = m_vertices[index1];&#xD;&#xA;        const auto&amp; v2 = m_vertices[index2];&#xD;&#xA;        const auto&amp; v3 = m_vertices[index3];&#xD;&#xA;&#xD;&#xA;        // Edges &amp; delta-UVs&#xD;&#xA;        const glm::vec3&amp; edge1 = v2.position - v1.position;&#xD;&#xA;        const glm::vec3&amp; edge2 = v3.position - v1.position;&#xD;&#xA;        const glm::vec2&amp; deltaUV1 = v2.texture_uv - v1.texture_uv;&#xD;&#xA;        const glm::vec2&amp; deltaUV2 = v3.texture_uv - v1.texture_uv;&#xD;&#xA;&#xD;&#xA;        const GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);&#xD;&#xA;&#xD;&#xA;        // Calculate tangent&#xD;&#xA;        glm::vec3 tangent;&#xD;&#xA;        tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);&#xD;&#xA;        tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);&#xD;&#xA;        tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);&#xD;&#xA;        tangent = glm::normalize(tangent);&#xD;&#xA;        m_vertices[index1].tangent = tangent;&#xD;&#xA;        m_vertices[index2].tangent = tangent;&#xD;&#xA;        m_vertices[index3].tangent = tangent;&#xD;&#xA;&#xD;&#xA;        // Calculate bitangent&#xD;&#xA;        glm::vec3 bitangent;&#xD;&#xA;        bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);&#xD;&#xA;        bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);&#xD;&#xA;        bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);&#xD;&#xA;        bitangent = glm::normalize(bitangent);&#xD;&#xA;        m_vertices[index1].bitangent = bitangent;&#xD;&#xA;        m_vertices[index2].bitangent = bitangent;&#xD;&#xA;        m_vertices[index3].bitangent = bitangent;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is how I calculate the TBN matrix in the vertex shader:&#xD;&#xA;```glsl&#xD;&#xA;    mat3 normalMatrix = transpose(inverse(mat3(model)));&#xD;&#xA;    vec3 T = normalize(normalMatrix * a_tangent);&#xD;&#xA;    vec3 N = normalize(normalMatrix * a_normal);&#xD;&#xA;    T = normalize(T - dot(T, N) * N);&#xD;&#xA;    vec3 B = cross(N, T);&#xD;&#xA;&#xD;&#xA;    mat3 TBN = transpose(mat3(T, B, N));&#xD;&#xA;    vs_out.TangentLightPos = TBN * light.position;&#xD;&#xA;    vs_out.TangentViewPos  = TBN * camera_position;&#xD;&#xA;    vs_out.TangentFragPos  = TBN * vs_out.fragment_position;&#xD;&#xA;```&#xD;&#xA;For completeness, here's my `mesh` class definition:&#xD;&#xA;```&#xD;&#xA;    class mesh&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;        // Construction&#xD;&#xA;        mesh();&#xD;&#xA;        mesh(std::vector&lt;vertex&gt;&amp;&amp; vertices, std::vector&lt;GLuint&gt;&amp;&amp; indices, std::vector&lt;texture&gt;&amp;&amp; textures);&#xD;&#xA;        mesh(const mesh&amp; other) = delete;&#xD;&#xA;        mesh(mesh&amp;&amp; other);&#xD;&#xA;        virtual ~mesh() = default;&#xD;&#xA;&#xD;&#xA;        // Operators&#xD;&#xA;        mesh&amp; operator=(mesh&amp;&amp; rhs);&#xD;&#xA;&#xD;&#xA;        // Common&#xD;&#xA;        void calculate_tangents();&#xD;&#xA;        void render(rendering::shader&amp; shader) const;&#xD;&#xA;&#xD;&#xA;    private:&#xD;&#xA;        std::vector&lt;vertex&gt; m_vertices;&#xD;&#xA;        std::vector&lt;GLuint&gt; m_indices;&#xD;&#xA;        std::vector&lt;texture&gt; m_textures;&#xD;&#xA;&#xD;&#xA;        GLuint m_vbo;   // Vertex buffer object&#xD;&#xA;        GLuint m_vao;   // Vertex array object&#xD;&#xA;        GLuint m_ebo;   // Element buffer object&#xD;&#xA;&#xD;&#xA;        void finalize();&#xD;&#xA;    };&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lXPMw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27799" PostHistoryTypeId="1" PostId="9703" RevisionGUID="b512a94c-9384-47a4-8fb1-b9c10dc52177" CreationDate="2020-04-09T09:54:30.173" UserId="13147" Text="Problem calculating tangent space" ContentLicense="CC BY-SA 4.0" />
  <row Id="27800" PostHistoryTypeId="3" PostId="9703" RevisionGUID="b512a94c-9384-47a4-8fb1-b9c10dc52177" CreationDate="2020-04-09T09:54:30.173" UserId="13147" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27801" PostHistoryTypeId="6" PostId="9703" RevisionGUID="c1d8e4c2-96a8-4b98-8f7a-c41a5cee212b" CreationDate="2020-04-09T10:57:28.713" UserId="13147" Comment="Fix tags" Text="|mesh|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27805" PostHistoryTypeId="2" PostId="9705" RevisionGUID="d29bab5f-1b70-4c1e-a866-c6405c37e465" CreationDate="2020-04-09T13:29:40.850" UserId="13095" Text="You are not too far off with your second averaging approach. The problem is, that the area is the wrong weighting factor for what you want to achieve. You want each of the 3 sides of the cube to contribute equally to the vertex normal, but you need to extract the information from the adjacent triangles. The area and the number of triangles are bad weighting factors since they vary with the number of triangles per side. But one thing stays always the same at each vertex: The angle between two edges at the side. So you just need to take the angle of each triangle connected to the vertex and use it as a weighting factor for its face normal. The weighting factors will always sum up to 90°/$\frac{\pi}{2}$ per side of the cube. Look for example at the bottom left vertex at the front in the image you posted.&#xD;&#xA;&#xD;&#xA;Your first approach fails because it yields:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2*N_l + 2 \cdot N_f + 1 \cdot N_b}{5}$$&#xD;&#xA;&#xD;&#xA;where $N_l$ is the left, $N_f$ the front and $N_b$ the bottom side normal. The factors result from the triangle count at the vertex and their sum.&#xD;&#xA;&#xD;&#xA;Your second approach fails because it yields: &#xD;&#xA;&#xD;&#xA;$$N_v = \frac{N_l + 0.5 \cdot N_f + 0.5 \cdot N_b}{2}$$&#xD;&#xA;&#xD;&#xA;Here the factors result from the fact, that only the left face has all its triangles connected to the vertex. The bottom face connects only 1 of 2 and front face only 2 of 4 equally sized triangles to the vertex.&#xD;&#xA;&#xD;&#xA;If you take the angles, you get:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2\cdot 45 \cdot N_l + 2 \cdot 45 \cdot N_f+ 90 \cdot N_b}{270}$$&#xD;&#xA;&#xD;&#xA;Now each side contributes equally and independent of the number and size of triangles connected to the vertex." ContentLicense="CC BY-SA 4.0" />
  <row Id="27806" PostHistoryTypeId="5" PostId="9705" RevisionGUID="50f61ba1-c014-428d-9713-bad8b1c8c829" CreationDate="2020-04-09T13:35:16.263" UserId="13095" Comment="added 41 characters in body" Text="You are not too far off with your second averaging approach. The problem is, that the area is the wrong weighting factor for what you want to achieve. You want each of the 3 sides of the cube to contribute equally to the vertex normal, but you need to extract the information from the adjacent triangles. The area and the number of triangles are bad weighting factors since they vary with the number of triangles per side. But one thing stays always the same at each vertex: The angle between two edges at the side. So you just need to take the angle of each triangle connected to the vertex and use it as a weighting factor for its normalized face normal. The weighting factors will always sum up to 90°/$\frac{\pi}{2}$ per side of the cube. Look for example at the bottom left vertex at the front in the image you posted.&#xD;&#xA;&#xD;&#xA;Your first approach fails because it yields:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2*N_l + 2 \cdot N_f + 1 \cdot N_b}{5}$$&#xD;&#xA;&#xD;&#xA;where $N_l$ is the left, $N_f$ the front and $N_b$ the bottom side normal. Assume them to be normalized. The factors result from the triangle count at the vertex and their sum.&#xD;&#xA;&#xD;&#xA;Your second approach fails because it yields: &#xD;&#xA;&#xD;&#xA;$$N_v = \frac{N_l + 0.5 \cdot N_f + 0.5 \cdot N_b}{2}$$&#xD;&#xA;&#xD;&#xA;Here the factors result from the fact, that only the left face has all its triangles connected to the vertex. The bottom face connects only 1 of 2 and front face only 2 of 4 equally sized triangles to the vertex.&#xD;&#xA;&#xD;&#xA;If you take the angles, you get:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2\cdot 45 \cdot N_l + 2 \cdot 45 \cdot N_f+ 90 \cdot N_b}{270}$$&#xD;&#xA;&#xD;&#xA;Now each side contributes equally and independent of the number and size of triangles connected to the vertex." ContentLicense="CC BY-SA 4.0" />
  <row Id="27807" PostHistoryTypeId="5" PostId="9696" RevisionGUID="7f37ef3b-0f1f-4661-84c6-d14cad889ae5" CreationDate="2020-04-09T14:08:56.907" UserId="13083" Comment="edited body" Text="Briefly, modify the stb_load as follows and everything should work.&#xD;&#xA;```&#xD;&#xA;unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 4);&#xD;&#xA;nrChannels = 4;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Details:*&#xD;&#xA;Okay, after a lot of heartache trying and failing to get libpng to work, I finally decided to have a look at the stbi implementation that I'm using to load the texture files. This is where the problem comes in from. &#xD;&#xA;&#xD;&#xA;@wychmaster was right when he suspected that there was an incorrect stride used. The problem, though, is in the reading of the image. Apparently, this has something to do with alignment of pixel data which is set by glPixelStorei. &#xD;&#xA;&#xD;&#xA;Someone posted the same problem in https://github.com/nothings/stb/issues/335 and determined that this was solution (it works!).&#xD;&#xA;&#xD;&#xA;The solution is to set the number of desired channels to 4 in the loading function and read the image as an RGBA instead of whatever the image format actually is. This works and all the misaligned images are now perfect. The images that worked before continue to work too. &#xD;&#xA;&#xD;&#xA;But, I do not completely understand why nothing else is affected. This seems strange to me... If someone can explain why this works, that would be very helpful. In the event this is a niche question, I'll likely return to make a more detailed post on it. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27808" PostHistoryTypeId="6" PostId="7874" RevisionGUID="d46c006c-7f2d-4343-9409-0a778f39dfd2" CreationDate="2020-04-09T15:16:50.467" UserId="6" Comment="edited tags" Text="|directx|raster-image|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27809" PostHistoryTypeId="6" PostId="8859" RevisionGUID="970bd4a9-e950-4ef2-8391-4dbb40f91873" CreationDate="2020-04-09T15:17:28.017" UserId="6" Comment="edited tags" Text="|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27810" PostHistoryTypeId="6" PostId="9671" RevisionGUID="cb7e4e36-7a9d-4162-b388-69fe7c24aae0" CreationDate="2020-04-09T15:18:44.583" UserId="6" Comment="edited tags" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27811" PostHistoryTypeId="2" PostId="9706" RevisionGUID="41dd4d03-3b21-4bef-9366-13fe327f08c1" CreationDate="2020-04-09T15:31:25.810" UserId="9438" Text="Assuming you want to calculate the vertex normal... if you know which faces use the vertex and they have unitised normals.&#xD;&#xA;&#xD;&#xA;\begin{equation*}\left \| \sum \left \| n_{t} \right \| \right \|\end{equation*}&#xD;&#xA;&#xD;&#xA;Your first appraoch is close, but would only work if the face normals are unitised otherwise they will skew.&#xD;&#xA;&#xD;&#xA;[See this question for more information][1]&#xD;&#xA;&#xD;&#xA;I'm not sure it is what you are asking though, since this will interpolate the normal essentially giving you a normal which is equidistant from all face normals. Given your last image, it looks like you want normals per face (flat shading) in which case you shouldn't share your vertices between faces, instead you need three vertices for each triangle (i.e 36 for a cube using tgriangles, or 24 for a cube if using quads).&#xD;&#xA;&#xD;&#xA;If you want to use no more than 8 vertices, you will effectively get smooth shading (possibly what your first two images show) and not flat shading (what it looks like you want with your 3rd image), or you need to have normals per face (and not per vertex).&#xD;&#xA;&#xD;&#xA;tbh I don't understand the last image. You origin must be really far away if you are using the same origin to calculate for each vertex.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4031/programmatically-generating-vertex-normals" ContentLicense="CC BY-SA 4.0" />
  <row Id="27812" PostHistoryTypeId="5" PostId="9706" RevisionGUID="f1c74158-fcc8-418c-a311-421056521ac2" CreationDate="2020-04-09T15:37:26.367" UserId="9438" Comment="deleted 162 characters in body" Text="Assuming you want to calculate the vertex normal... if you know which faces use the vertex and they have unitised normals.&#xD;&#xA;&#xD;&#xA;\begin{equation*}\left \| \sum \left \| n_{t} \right \| \right \|\end{equation*}&#xD;&#xA;&#xD;&#xA;Your first appraoch is close, but would only work if the face normals are unitised otherwise they will skew.&#xD;&#xA;&#xD;&#xA;[See this question for more information][1]&#xD;&#xA;&#xD;&#xA;Given your last image, it looks like you want normals per face (flat shading) in which case you shouldn't share your vertices between faces, instead you need three vertices for each triangle (i.e 36 for a cube using tgriangles, or 24 for a cube if using quads).&#xD;&#xA;&#xD;&#xA;If you want to use no more than 8 vertices, you will effectively get smooth shading (possibly what your first two images show) and not flat shading (what it looks like you want with your 3rd image), or you need to have normals per face (and not per vertex).&#xD;&#xA;&#xD;&#xA;tbh I don't understand the last image. You origin must be really far away if you are using the same origin to calculate for each vertex.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4031/programmatically-generating-vertex-normals" ContentLicense="CC BY-SA 4.0" />
  <row Id="27813" PostHistoryTypeId="5" PostId="9706" RevisionGUID="ad4e909d-d0e1-464c-bd42-a92f92fec5d5" CreationDate="2020-04-09T15:44:17.380" UserId="9438" Comment="deleted 133 characters in body" Text="Assuming you want to calculate the *shared* vertex normal... if you know which faces use the vertex and they have unitised normals.&#xD;&#xA;&#xD;&#xA;\begin{equation*}\left \| \sum \left \| n_{t} \right \| \right \|\end{equation*}&#xD;&#xA;&#xD;&#xA;Your first appraoch is close, but would only work if the face normals are unitised otherwise they will skew.&#xD;&#xA;&#xD;&#xA;[See this question for more information][1]&#xD;&#xA;&#xD;&#xA;Given your last image, it looks like you want normals per face (flat shading) in which case you shouldn't share your vertices between faces, instead you need three vertices for each triangle (i.e 36 for a cube using tgriangles, or 24 for a cube if using quads).&#xD;&#xA;&#xD;&#xA;If you want to use no more than 8 vertices, you will effectively get smooth shading (possibly what your first two images show) and not flat shading (what it looks like you want with your 3rd image), or you need to have normals per face (and not per vertex).&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/4031/programmatically-generating-vertex-normals" ContentLicense="CC BY-SA 4.0" />
  <row Id="27814" PostHistoryTypeId="2" PostId="9707" RevisionGUID="e0330386-3b03-48bd-90ca-74cf79199ed0" CreationDate="2020-04-09T16:11:29.037" UserId="13151" Text="I'm following [this tutorial on Vulkan][1] and I tried to see if it actually worked with different queues for drawing and presenting the image of the triangle. [My GPU supports presentation with every queue family][2] but it actually works only when I use a queue from the first or second family, not the third. Is there any thing wrong with the code or is it possible something like that?&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan-tutorial.com/Introduction&#xD;&#xA;  [2]: https://vulkan.gpuinfo.org/displayreport.php?id=2675#queuefamilies" ContentLicense="CC BY-SA 4.0" />
  <row Id="27815" PostHistoryTypeId="1" PostId="9707" RevisionGUID="e0330386-3b03-48bd-90ca-74cf79199ed0" CreationDate="2020-04-09T16:11:29.037" UserId="13151" Text="Queue from a family queue that supports presentation doesn't work [Vulkan]" ContentLicense="CC BY-SA 4.0" />
  <row Id="27816" PostHistoryTypeId="3" PostId="9707" RevisionGUID="e0330386-3b03-48bd-90ca-74cf79199ed0" CreationDate="2020-04-09T16:11:29.037" UserId="13151" Text="|c++|gpu|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27818" PostHistoryTypeId="5" PostId="9707" RevisionGUID="256d5861-edd7-4e9a-84e7-1fd2f36f3703" CreationDate="2020-04-09T17:04:32.160" UserId="13151" Comment="deleted 4 characters in body" Text="I'm following [this tutorial on Vulkan][1] and I tried to see if it actually worked with different queues for drawing and presenting the image of the triangle. [My GPU supports presentation with every queue family][2] but it actually works only when I use a queue from the first or second family, not the third. Is there anything wrong with the code or is something like that possible?&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan-tutorial.com/Introduction&#xD;&#xA;  [2]: https://vulkan.gpuinfo.org/displayreport.php?id=2675#queuefamilies" ContentLicense="CC BY-SA 4.0" />
  <row Id="27819" PostHistoryTypeId="5" PostId="9705" RevisionGUID="c218fa26-b329-40ec-8ee8-3b20a1d45d2d" CreationDate="2020-04-09T17:44:16.767" UserId="13095" Comment="added 697 characters in body" Text="You are not too far off with your second averaging approach. The problem is, that the area is the wrong weighting factor for what you want to achieve. You want each of the 3 sides of the cube to contribute equally to the vertex normal, but you need to extract the information from the adjacent triangles. The area and the number of triangles are bad weighting factors since they vary with the number of triangles per side. But one thing stays always the same at each vertex: The angle between two edges at the side. So you just need to take the angle of each triangle connected to the vertex and use it as a weighting factor for its normalized face normal. The weighting factors will always sum up to 90°/$\frac{\pi}{2}$ per side of the cube. Look for example at the bottom left vertex at the front in the image you posted.&#xD;&#xA;&#xD;&#xA;Your first approach fails because it yields:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2*N_l + 2 \cdot N_f + 1 \cdot N_b}{5}$$&#xD;&#xA;&#xD;&#xA;where $N_l$ is the left, $N_f$ the front and $N_b$ the bottom side normal. Assume them to be normalized. The factors result from the triangle count at the vertex and their sum.&#xD;&#xA;&#xD;&#xA;Your second approach fails because it yields: &#xD;&#xA;&#xD;&#xA;$$N_v = \frac{N_l + 0.5 \cdot N_f + 0.5 \cdot N_b}{2}$$&#xD;&#xA;&#xD;&#xA;Here the factors result from the fact, that only the left face has all its triangles connected to the vertex. The bottom face connects only 1 of 2 and front face only 2 of 4 equally sized triangles to the vertex.&#xD;&#xA;&#xD;&#xA;If you take the angles, you get:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2\cdot 45 \cdot N_l + 2 \cdot 45 \cdot N_f+ 90 \cdot N_b}{270}$$&#xD;&#xA;&#xD;&#xA;Now each side contributes equally and independent of the number and size of triangles connected to the vertex.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I just realized, that the front face also contains only 2 triangles. The diagonal of the back face triangles irritated me. However, this will not affect the conclusion but the weigting factors change. For the fist approach you get:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2*N_l + 1 \cdot N_f + 1 \cdot N_b}{4}$$&#xD;&#xA;&#xD;&#xA;The second remains unchanged and for the angles you get:&#xD;&#xA;&#xD;&#xA;$$N_v = \frac{2\cdot 45 \cdot N_l + 90 \cdot N_f+ 90 \cdot N_b}{270}$$&#xD;&#xA;&#xD;&#xA;which is still correct. What is interesting is that both your approaches give the same results for the shown cube, since a connection of the vertex to 2 triangles also means that the area weight is doubled. You can also see this if you compare both pictures." ContentLicense="CC BY-SA 4.0" />
  <row Id="27821" PostHistoryTypeId="50" PostId="8260" RevisionGUID="d2ab6055-515e-4259-9321-d4df182e363d" CreationDate="2020-04-10T01:00:35.057" UserId="-1" />
  <row Id="27822" PostHistoryTypeId="2" PostId="9708" RevisionGUID="d238ec58-bd89-4f27-a1eb-18b380f818ba" CreationDate="2020-04-10T03:46:48.517" UserId="13154" Text="&#xD;&#xA;&#xD;&#xA;There are lots of cool things you can do with SDFs to render implicit surfaces. Most of the examples I've seen have been “all in the shader”, where the entire distance function is encoded in the shader source code.&#xD;&#xA;&#xD;&#xA;Examples:&#xD;&#xA;&#xD;&#xA;* https://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm&#xD;&#xA;* https://www.shadertoy.com/view/3lsSzf&#xD;&#xA;&#xD;&#xA;The problem is that all of those examples assume the shader has total knowledge of the entire world. It evaluates a single distance function, which is complex, but complete.&#xD;&#xA;&#xD;&#xA;I want to make a large world (too large to fit in a shader, certainly), and am looking for approaches to render it with the SDF approach.&#xD;&#xA;&#xD;&#xA;Does anyone have experience with this? It is 2D-only, if it helps.&#xD;&#xA;&#xD;&#xA;The stumbling block seems to be: Since the rendering happens in the fragment shader, I somehow have to transfer “game world” information into that shader. But there do not seem to be good ways to send bulk data to the fragment shader.&#xD;&#xA;&#xD;&#xA;Some ideas I have had:&#xD;&#xA;&#xD;&#xA;* Write one generic shader that can draw, say, a combination of 500 SDFs.&#xD;&#xA; * The input to the shader (maybe a UBO?) would contain an encoded version of a piece of the world, with commands like “put a circle at (x,y,radius), do a union with the next object, …” to build the total SDF for that piece of the world.&#xD;&#xA; * On the CPU side, I'd have to split the world into chunks that could be rendered by that shader, and populate the input data appropriately for each draw call.&#xD;&#xA; * So for 2D, I might do a tile-based render of the screen, where each tile has “small” amount of data, enough to be handled in the shader.&#xD;&#xA;* Generate shaders on-the-fly, depending on the part of the world I want to render.&#xD;&#xA; * Here, the shader code would look a lot like the “everything baked in” shaders, but I'd just be generating the code on the CPU.&#xD;&#xA; * This approach seems bad though, since compiling shaders is a pretty heavy process, in my experience. I did a test with an SDF that was the union of a few thousand circles, and it took 30sec+ to compile.&#xD;&#xA;&#xD;&#xA;Any other ideas?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27823" PostHistoryTypeId="1" PostId="9708" RevisionGUID="d238ec58-bd89-4f27-a1eb-18b380f818ba" CreationDate="2020-04-10T03:46:48.517" UserId="13154" Text="SDF rendering for large world" ContentLicense="CC BY-SA 4.0" />
  <row Id="27824" PostHistoryTypeId="3" PostId="9708" RevisionGUID="d238ec58-bd89-4f27-a1eb-18b380f818ba" CreationDate="2020-04-10T03:46:48.517" UserId="13154" Text="|shader|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27827" PostHistoryTypeId="5" PostId="9695" RevisionGUID="e45c259b-0ebd-4ed3-9283-7d15661e1300" CreationDate="2020-04-11T07:40:33.940" UserId="13124" Comment="added links to the particular extensions" Text="If using the new real-time ray tracing functionality is an option for you, it would be worth a try! It might be that getting it to run is less work than porting your CPU data structure into a GPU-compatible format. Furthermore, using the hardware functionality would result in much better performance since BVH traversal (and triangle intersection, if that is relevant to you) are accelerated in hardware.&#xD;&#xA;&#xD;&#xA;Official real-time ray tracing support has been announced by Khronos (in the form of an `KHR` extension) lately, see [Ray Tracing In Vulkan](https://www.khronos.org/blog/ray-tracing-in-vulkan). With the Vulkan API version 1.2, the option for &quot;Ray Queries&quot; has been added. It could be relevant for your use case since it allows to trace rays against the BVH from arbitrary shaders (i.e., e.g., also from compute shaders or fragment shaders).&#xD;&#xA;&#xD;&#xA;Using [VK_KHR_ray_tracing](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_ray_tracing.html) (or NVIDIA's precursor [VK_NV_ray_tracing](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_NV_ray_tracing.html)), you would have to update the acceleration structure on the GPU every time after you have updated your CPU data structure. The API supports updating acceleration structures every frame. In NVIDIA's extension this is done via the `VkBool32 update` flag in [`vkCmdBuildAccelerationStructureNV`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdBuildAccelerationStructureNV.html). In the KHR-extension it is handled a bit differently, but in a very similar fashion: The update-flags are contained in the [`VkAccelerationStructureBuildGeometryInfoKHR`](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkAccelerationStructureBuildGeometryInfoKHR.html) structures." ContentLicense="CC BY-SA 4.0" />
  <row Id="27828" PostHistoryTypeId="2" PostId="9709" RevisionGUID="26b850b3-ff66-46ca-ab21-124a5e3326cc" CreationDate="2020-04-11T21:19:14.107" UserDisplayName="user13167" Text="I have a simplistic shader program that adds reference coordinate planes to a scene. &#xD;&#xA;&#xD;&#xA;These planes are drawn as intersecting lines.&#xD;&#xA;&#xD;&#xA;When viewed at a distance, a visual artifact is created; there is a ripple of lighter and darker areas going left to right across the image.&#xD;&#xA;&#xD;&#xA;[![artifact][1]][1]&#xD;&#xA;&#xD;&#xA;Given how simple the shader program is, I think this must be due to the interpolation that occurs between the vertex and fragment shaders.&#xD;&#xA;&#xD;&#xA;- (a) Does this type of artifact have a name? &#xD;&#xA;- (b) What causes it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qNKfb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27829" PostHistoryTypeId="1" PostId="9709" RevisionGUID="26b850b3-ff66-46ca-ab21-124a5e3326cc" CreationDate="2020-04-11T21:19:14.107" UserDisplayName="user13167" Text="Visual Artifact in Wireframe Grid/Plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="27830" PostHistoryTypeId="3" PostId="9709" RevisionGUID="26b850b3-ff66-46ca-ab21-124a5e3326cc" CreationDate="2020-04-11T21:19:14.107" UserDisplayName="user13167" Text="|webgl|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27831" PostHistoryTypeId="2" PostId="9710" RevisionGUID="93252c08-1655-4f27-a3fa-06429799dd38" CreationDate="2020-04-11T21:33:27.060" UserId="9438" Text="It's a interference pattern, called [Moire pattern][1]. You get them in signal analysis and various other fields. I guess it could be considered an optical illusion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Moir%C3%A9_pattern" ContentLicense="CC BY-SA 4.0" />
  <row Id="27832" PostHistoryTypeId="50" PostId="8151" RevisionGUID="b4a8aa88-7983-4832-99a8-d2e867fc3cdc" CreationDate="2020-04-12T01:01:45.223" UserId="-1" />
  <row Id="27833" PostHistoryTypeId="2" PostId="9711" RevisionGUID="14550831-2c15-48df-b4fa-168d896872b3" CreationDate="2020-04-12T04:16:02.353" UserId="11521" Text="I have a doubt regarding shape lights pdfs, specifically various sources point at the fact that the pdf is a constant:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;lightpdf = 1/A&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $A$ is the area of the light surface. Expressed in solid angle terms, this becomes:&#xD;&#xA;$$&#xD;&#xA;lightpdf(\omega) = \frac{r^2}{cos\theta A}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or $= 0$ for directions on the hemisphere which do not hit the light.&#xD;&#xA;&#xD;&#xA;Where $r^2$ is the squared distance from the hit point o the light surface and the point we are sampling from, and $\theta$ the angle from the light surface normal and our ray direction ([source][1]).&#xD;&#xA;&#xD;&#xA;What isn't clear to me is knowing that the pdf should satisfy this condition:&#xD;&#xA;&#xD;&#xA;$$\int_0^{2\pi} lightpdf(\omega)d\omega = 1$$&#xD;&#xA;&#xD;&#xA;Assuming for example a sphere light source (but a cylinder would also do), if in the second formula above we use the entire sphere area as $A$, aren't we using a solid angle for the sphere which is double of what it actually should be? (by including the half surface we cannot see from $p$:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Sampling_Light_Sources.html#SamplingShapes&#xD;&#xA;  [2]: https://i.stack.imgur.com/Yu2GP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27834" PostHistoryTypeId="1" PostId="9711" RevisionGUID="14550831-2c15-48df-b4fa-168d896872b3" CreationDate="2020-04-12T04:16:02.353" UserId="11521" Text="Confusion about light PDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="27835" PostHistoryTypeId="3" PostId="9711" RevisionGUID="14550831-2c15-48df-b4fa-168d896872b3" CreationDate="2020-04-12T04:16:02.353" UserId="11521" Text="|lighting|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27836" PostHistoryTypeId="12" PostId="9711" RevisionGUID="62e03df4-49c2-4694-8a1a-8808dabfec59" CreationDate="2020-04-12T04:16:36.063" UserId="11521" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:11521,&quot;DisplayName&quot;:&quot;A. S.&quot;}]}" />
  <row Id="27837" PostHistoryTypeId="13" PostId="9711" RevisionGUID="1df48359-a1e8-480f-a6c0-ad8777ca5227" CreationDate="2020-04-12T04:18:29.510" UserId="11521" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:11521,&quot;DisplayName&quot;:&quot;yggdrasil&quot;}]}" />
  <row Id="27838" PostHistoryTypeId="2" PostId="9712" RevisionGUID="a851eb7b-3055-48e5-8e53-c53f29afe61f" CreationDate="2020-04-12T14:33:05.007" UserDisplayName="user6625" Text="I want to write code from scratch about Projective Transformation in order to apply this transformation to 2d rectangular. I searched about this transformation, but I could not figure out completely. These are some formulas I have seen:&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;       x' = xH&#xD;&#xA;       y' = yH&#xD;&#xA;       A.H = 0&#xD;&#xA;       A = UΣV^T&#xD;&#xA;How can I apply Projective Transformation to a rectangle? Also is there any alternative solution like composition of rotation, translation etc?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27839" PostHistoryTypeId="1" PostId="9712" RevisionGUID="a851eb7b-3055-48e5-8e53-c53f29afe61f" CreationDate="2020-04-12T14:33:05.007" UserDisplayName="user6625" Text="Apply Projective Transformation 2D Rectangular" ContentLicense="CC BY-SA 4.0" />
  <row Id="27840" PostHistoryTypeId="3" PostId="9712" RevisionGUID="a851eb7b-3055-48e5-8e53-c53f29afe61f" CreationDate="2020-04-12T14:33:05.007" UserDisplayName="user6625" Text="|transformations|perspective|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27841" PostHistoryTypeId="6" PostId="9712" RevisionGUID="aceeb1cb-d88e-4c37-b469-6f156d4b15b3" CreationDate="2020-04-12T14:41:38.593" UserDisplayName="user6625" Comment="[Edit removed during grace period]" Text="|transformations|perspective|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27842" PostHistoryTypeId="5" PostId="9712" RevisionGUID="587de14c-45bb-4048-982d-aad9238cb7fd" CreationDate="2020-04-12T15:20:13.237" UserDisplayName="user6625" Comment="added 185 characters in body" Text="I want to write code from scratch about Projective Transformation in order to apply this transformation to 2d rectangular. I searched about this transformation, but I could not figure out completely. These are some formulas I have seen:&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;       x' = xH&#xD;&#xA;       y' = yH&#xD;&#xA;       A.H = 0&#xD;&#xA;       A = UΣV^T&#xD;&#xA;Accordint to these formulas,SVD is calculated from A matrix, and then H is obtained from V. Then target points should be found by H. But this is a bit confusing. Also is there any alternative solution like composition of transformations like Similarity Transform which can be obtained rotation, translation and scale?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27843" PostHistoryTypeId="6" PostId="9712" RevisionGUID="587de14c-45bb-4048-982d-aad9238cb7fd" CreationDate="2020-04-12T15:20:13.237" UserDisplayName="user6625" Comment="added 185 characters in body" Text="|transformations|perspective|2d-graphics|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27844" PostHistoryTypeId="4" PostId="9712" RevisionGUID="3dd7904b-364a-44ba-9570-d13767f1ef70" CreationDate="2020-04-12T15:25:40.090" UserDisplayName="user6625" Comment="added 185 characters in body" Text="Apply Projective Transformation 2D Rectangle" ContentLicense="CC BY-SA 4.0" />
  <row Id="27845" PostHistoryTypeId="2" PostId="9713" RevisionGUID="ccfa36ec-82f9-40da-8558-7f3d2dcb3995" CreationDate="2020-04-12T15:32:29.900" UserId="13159" Text="The pattern you are seeing arises from perspective projection. Which causes all those parallel lines not to be parallel to each other when projected on the screen.&#xD;&#xA;&#xD;&#xA;Your problem with darker and lighter areas is caused by anti-aliasing which is trying to smooth the lines that are sometimes passing right in between 2 pixels, so it blends the lines with the black background.  &#xD;&#xA;You also have a problem that sometimes there is an empty (black) pixel between the lines lines and sometimes the lines are right next to each other.&#xD;&#xA;&#xD;&#xA;All this always occurs but the reason you're noticing a pattern here is that you just have a lot of really dense parallel lines.&#xD;&#xA;&#xD;&#xA;This reminds me of a common problem in game graphics where high-resolution textures viewed from a distance tend to look bad and flicker from frame to frame.  &#xD;&#xA;The usual way that is solved is by using a lower resolution texture when the object is far away.&#xD;&#xA;&#xD;&#xA;For you an equivalent would be to have more lines closer to the perspective camera and fewer lines further away. I'd also recommend adding transparency to the denser lines as they get further away to achieve a smooth transition." ContentLicense="CC BY-SA 4.0" />
  <row Id="27846" PostHistoryTypeId="6" PostId="9712" RevisionGUID="b8fb5afc-4a4a-498a-8606-77515ff0c128" CreationDate="2020-04-12T15:36:01.510" UserDisplayName="user6625" Comment="edited tags" Text="|transformations|perspective|2d-graphics|camera|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27847" PostHistoryTypeId="5" PostId="9712" RevisionGUID="b8fb5afc-4a4a-498a-8606-77515ff0c128" CreationDate="2020-04-12T15:36:01.510" UserDisplayName="user6625" Comment="edited tags" Text="I want to write code from scratch about Projective Transformation in order to apply this transformation to 2d rectangular. I searched about this transformation, but I could not figure out completely. These are some formulas I have seen:&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;       x' = xH&#xD;&#xA;       y' = yH&#xD;&#xA;       A.H = 0&#xD;&#xA;       A = UΣV^T&#xD;&#xA;Accordint to these formulas,SVD is calculated from A matrix, and then H is obtained from V. Then target points should be found by H. But this is a bit confusing. Also is there any alternative solution like composition of transformations like Similarity Transform which can be obtained by rotation, translation and scale?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27848" PostHistoryTypeId="5" PostId="9712" RevisionGUID="73831dd2-8076-4d0e-98aa-3a296d21c033" CreationDate="2020-04-12T15:53:44.197" UserDisplayName="user6625" Comment="added 22 characters in body" Text="I want to write code from scratch about Projective Transformation in order to apply this transformation to 2d rectangular. I searched about this transformation, but I could not figure out completely. These are some formulas I have seen:&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;       x' = xH&#xD;&#xA;       y' = yH&#xD;&#xA;       A.H = 0&#xD;&#xA;       A = UΣV^T&#xD;&#xA;According to these formulas,SVD is calculated from A matrix, and then H is obtained from V. Then target points should be found by H. But this is a bit confusing. Could you explain it? Also is there any alternative solution like composition of transformations like Similarity Transform which can be obtained by rotation, translation and scale?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27849" PostHistoryTypeId="5" PostId="5564" RevisionGUID="c03ddec1-f6d8-4305-bc89-e6c63a41a9c2" CreationDate="2020-04-12T16:25:21.887" UserId="2654" Comment="added 626 characters in body" Text="The post October 22, 2019 version of the OpenGL 4.6 standard gives atomic counters the same incoherency restrictions as image load/store and SSBO operations. You have to use explicit barriers to synchronize access to them and so forth. This is a textual change from older versions of the standard, but it isn't a behavioral change from implementations. The older wording [is considered a bug][1] and thus it should be assumed that atomic counters have always worked incoherently.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Note: the following predates the October 22, 2019 update to OpenGL 4.6.&#xD;&#xA;&#xD;&#xA;From the OpenGL 4.6 specification, section 7.12: Shader Memory Access:&#xD;&#xA;&#xD;&#xA;&gt; As described in the OpenGL Shading Language Specification, shaders may perform random-access reads and writes to buffer object memory by reading from, assigning to, or performing atomic memory operation on shader buffer variables, or to texture or buffer object memory by using built-in image load, store, and atomic functions operating on shader image variables. The ability to perform such random-access reads and writes in systems that may be highly pipelined results in ordering and synchronization issues discussed in the sections below.&#xD;&#xA;&#xD;&#xA;Notice something missing from that list? It mentions &quot;shader buffer variables&quot;, and &quot;shader image variables&quot;. But atomic counter variables are not mentioned. And atomic counter variables are a different kind of thing from either of those.&#xD;&#xA;&#xD;&#xA;Therefore, that entire section (which is what explains the behavior of `glMemoryBarrier`) does not apply to atomic counters. Well, except where it specifically says otherwise, but that's only where it defines that helper FS invocations don't have side-effects. Note that even this *explicitly* calls out atomic counters as being something different from regular buffer or image operations: &quot;stores, atomics, and atomic counter updates&quot;.&#xD;&#xA;&#xD;&#xA;To lend greater credence to this view, the [ARB_atomic_counter_buffer_object][2] extension does not mention barriers at all. It doesn't require [ARB_shader_image_load_store][3] as a companion extension either, which is what defines `glMemoryBarrier`. Indeed, it has no interactions whatsoever with image load/store, while image load/store does have specified interactions with atomic counters.&#xD;&#xA;&#xD;&#xA;Given the weight of the evidence in the specifications, I would have to say that the Wiki is right. In the interest of full disclosure, I did write that Wiki article. Though I also did all this research *before* I wrote it.&#xD;&#xA;&#xD;&#xA;Basically, what the API seems to be saying is that buffer updates from atomic counters are treated like buffer updates from feedback operations. The implementation is required to track when you attempt to use that buffer for a read operation, then issue any synchronization needed to make sure that you can read the value. Or if you write to the value in the buffer (like clearing it to a value), then the implementation must automatically synchronize this.&#xD;&#xA;&#xD;&#xA;The likely reason the specification permits this for atomic counters but not for image load/store is that the range of data for atomic counters is *fixed*. SSBOs and image load/store through buffer textures can write to arbitrary parts of the bound range of buffer data. By contrast, atomic counters write to 4 bytes times the number of atomic counter variables used by the shader.&#xD;&#xA;&#xD;&#xA;Note however that atomic counters are affected by the in-shader `memoryBarrier` function. That is, atomic counters are subject to the requirements of, as the Wiki calls it, &quot;[Internal Visibility][4]&quot;. Granted, that's not very useful most of the time, as the primary use of atomic counters is for when multiple invocations are all updating the same one.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;On the other hand:&#xD;&#xA;&#xD;&#xA;&gt; the glMemoryBarrier() function supports a bit specifically for synchronizing access to atomic counters with other parts of the OpenGL pipeline&#xD;&#xA;&#xD;&#xA;The specification describes this particular barrier as:&#xD;&#xA;&#xD;&#xA;&gt; Memory accesses using shader atomic counter built-in functions issued after the barrier will reflect data written by shaders prior to the barrier. Additionally, atomic counter function invocations after the barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated prior to the barrier complete.&#xD;&#xA;&#xD;&#xA;What's curious about this is the &quot;all memory accesses&quot; part. This specific wording is only used in two other bits: shader storage and shader image. Other barriers for coherent operations like query buffers and transform feedbacks tend to use the term &quot;all shader writes&quot;.&#xD;&#xA;&#xD;&#xA;So... I would say that there is confusion at the specification level.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/OpenGL-API/issues/14&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_atomic_counters.txt&#xD;&#xA;  [3]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Memory_Model#Internal_visibility" ContentLicense="CC BY-SA 4.0" />
  <row Id="27850" PostHistoryTypeId="5" PostId="9712" RevisionGUID="a814669c-9bcb-4d7c-bfe2-ee82572c1882" CreationDate="2020-04-12T18:47:39.737" UserDisplayName="user6625" Comment="added 312 characters in body" Text="I want to write code from scratch about Projective Transformation in order to apply this transformation to 2d rectangular. I searched about this transformation, but I could not figure out completely. These are some formulas I have seen:&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;       x' = xH&#xD;&#xA;       y' = yH&#xD;&#xA;       A.H = 0&#xD;&#xA;       A = UΣV^T&#xD;&#xA;According to these formulas,SVD is calculated from A matrix, and then H is obtained from V. Then target points should be found by H. But this is a bit confusing. Could you explain it? Also is there any alternative solution like composition of transformations like Similarity Transform which can be obtained by rotation, translation and scale?&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;I watched this youtube video (https://www.youtube.com/watch?v=54Qtu3S9HJU) . It explains how calculate homography by the equations above after 12 minutes.This method seems very complex. I want to learn how exactly we calculate homography and obtain another rectangle by applying Projective Transfrom?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27851" PostHistoryTypeId="5" PostId="9712" RevisionGUID="52f54fb9-1e14-48b4-9e70-65be759cce91" CreationDate="2020-04-12T20:20:59.587" UserDisplayName="user6625" Comment="added 21 characters in body" Text="I want to write code from scratch about Projective Transformation in order to apply this transformation to 2d rectangular. I searched about this transformation, but I could not figure out completely. These are some formulas I have seen:&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;       x' = xH&#xD;&#xA;       y' = yH&#xD;&#xA;       A.H = 0&#xD;&#xA;       A = UΣV^T&#xD;&#xA;According to these formulas,SVD is calculated from A matrix, and then H is obtained from V. Then target points should be found by H. But this is a bit confusing. Could you explain it? Also is there any alternative solution like composition of transformations like Similarity Transform which can be obtained by multiplying rotation, translation and scale matrixes?&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;&#xD;&#xA;I watched this youtube video (https://www.youtube.com/watch?v=54Qtu3S9HJU) . It explains how calculate homography by the equations above after 12 minutes.This method seems very complex. I want to learn how exactly we calculate homography and obtain another rectangle by applying Projective Transfrom?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27852" PostHistoryTypeId="2" PostId="9714" RevisionGUID="53a49d5b-32a2-4077-b4f3-9a7d76766076" CreationDate="2020-04-12T20:53:57.833" UserId="5717" Text="Most of the answer is in the text you linked:&#xD;&#xA;&#xD;&#xA;&gt; Shapes almost always sample uniformly by area on their surface.&#xD;&#xA;&gt; Therefore, we will provide a default implementation of the&#xD;&#xA;&gt; Shape::Pdf() method corresponding to this sampling approach that&#xD;&#xA;&gt; returns the corresponding PDF: 1 over the surface area.&#xD;&#xA;&#xD;&#xA;So it is not always 1. This is just the most basic way to sample a light. It is simple, fast and provides a good baseline to check other algorithms for correctness. As for:&#xD;&#xA;&#xD;&#xA;&gt; Assuming for example a sphere light source (but a cylinder would also&#xD;&#xA;&gt; do), if in the second formula above we use the entire sphere area as&#xD;&#xA;&gt; $A$, aren't we using a solid angle for the sphere which is double of&#xD;&#xA;&gt; what it actually should be? (by including the half surface we cannot&#xD;&#xA;&gt; see from $p$:&#xD;&#xA;&#xD;&#xA;The half you cannot see will simply be excluded by the visibiliy test. Or because it is back facing, if you choose to emit light only on one side of the object. A better sampling algorithm will take that into consideration and adjust the PDF accordingly. Indeed, if you read a little further on that page, you will find:&#xD;&#xA;&#xD;&#xA;&gt; The second shape sampling method takes the point from which the&#xD;&#xA;&gt; surface of the shape is being integrated over as a parameter. This&#xD;&#xA;&gt; method is particularly useful for lighting, since the caller can pass&#xD;&#xA;&gt; in the point to be lit and allow shape implementations to ensure that&#xD;&#xA;&gt; they only sample the portion of the shape that is potentially visible&#xD;&#xA;&gt; from that point.&#xD;&#xA;&#xD;&#xA;Which is exactly what you are asking about. But doing this is not about having correct sampling, it's about having efficient sampling. Any sampling method is correct as long as:&#xD;&#xA;&#xD;&#xA; 1. It can generate samples everywhere they are potentially needed.&#xD;&#xA; 2. Its PDF correctly represents the probability of generating each sample.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27858" PostHistoryTypeId="2" PostId="9718" RevisionGUID="ef5df1ab-4ead-40c5-a780-6b044007ce91" CreationDate="2020-04-13T15:03:28.700" UserId="13095" Text="Since homography is not my topic, I can't really tell if I am missing some important edge cases, but after some research, I think I got the basics. I will use the same variable names, the guy in the video uses on slide 15 (slide numbers are in the bottom right corner on the red background).&#xD;&#xA;&#xD;&#xA;You start by defining 4 points in the plane $X$ where you say you know their projected points in plane $x$. You assume, that the transformation between $X$ and $x$ is linear and can be described by a matrix $H$. Means&#xD;&#xA;$$x = HX$$&#xD;&#xA;&#xD;&#xA;Now you want to calculate the Matrix $H$ that perfoms the projection:&#xD;&#xA;&#xD;&#xA;$$H = \begin{bmatrix}h_1&amp;h_2&amp;h_3\\h_4&amp;h_5&amp;h_6\\h_7&amp;h_8&amp;h_9\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;$h_1$ to $h_9$ are unknowns. So how do you get them? Well, you have 4 times:&#xD;&#xA;&#xD;&#xA;$p_i' = Hp_i$&#xD;&#xA;&#xD;&#xA;where $p_i'$ and $p_i$ are the projected and the original points. This full equation looks like this:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}x_i'\\y_i'\\1\end{bmatrix}= \begin{bmatrix}h_1&amp;h_2&amp;h_3\\h_4&amp;h_5&amp;h_6\\h_7&amp;h_8&amp;h_9\end{bmatrix}\begin{bmatrix}x_i\\y_i\\1\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Perform the multiplication and you will get this:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}x_i'\\y_i'\\1\end{bmatrix}= \begin{bmatrix}x_ih_1+y_ih_2+h_3\\x_ih_4+y_ih_5+h_6\\x_ih_7+y_ih_8+h_9\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can also write this in some kind of nested vector fashion:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}x_i'\\y_i'\\1\end{bmatrix}= \begin{bmatrix}\bar{h_1}^T p\\\bar{h_2}^T p\\\bar{h_3}^T p\end{bmatrix} = \begin{bmatrix}p^T\bar{h_1}\\p^T\bar{h_2}\\p^T\bar{h_3}\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;$$\begin{matrix}\bar{h_1} = \begin{bmatrix}h_1\\h_2\\h_3\end{bmatrix}&amp;\bar{h_2} = \begin{bmatrix}h_4\\h_5\\h_6\end{bmatrix}&amp;\bar{h_1} = \begin{bmatrix}h_7\\h_8\\h_9\end{bmatrix}\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Now here comes the trick (got it from [this link][1]). If  $p'$ is equal to the vector $Hp$ their cross product must be the zero vector $\bar{0}$:&#xD;&#xA;&#xD;&#xA;$$p' \times Hp = \bar{0}$$&#xD;&#xA;&#xD;&#xA;Applying the cross product will give you three equations:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}y_i'p^T\bar{h_3} -  p^T\bar{h_2} &amp;= 0 \\ p^T\bar{h_1} - x_i' p^T\bar{h_3} &amp;= 0\\x_i' p^T\bar{h_2}-y_i' p^T\bar{h_1}&amp;=0\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Write this as a matrix equation and you get:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}\bar{0}^T &amp;-p^T&amp;y_i'p^T\\p^T&amp;\bar{0}^T&amp;-x_i'p^T\\-y_i' p^T&amp;x_i' p^T&amp;\bar{0}^T\end{bmatrix} \begin{bmatrix}\bar{h_1}\\\bar{h_2}\\\bar{h_3}\end{bmatrix}= \begin{bmatrix}0\\0\\0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;Now, if you look at the matrix, you might notice, that the 3 columns are not linear independent. $-y_i'$ times the first column minus $x_i'$ times the second one, yields the third column. So you can drop one. &#xD;&#xA;&#xD;&#xA;If you drop the last column and replace all the vectors with their corresponding entries, you get:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}0&amp;0&amp;0 &amp;-x_i&amp;-y_i&amp;-1&amp;y_i'x_i&amp;y_i'y_i&amp;y_i'\\x_i&amp;y_i&amp;1&amp;0&amp;0&amp;0&amp;-x_ix_i'&amp;-y_ix_i'&amp;-x_i'\end{bmatrix} \begin{bmatrix}h_1\\h_2\\h_3\\h_4\\h_5\\h_6\\h_7\\h_8\\h_9\end{bmatrix}= \begin{bmatrix}0\\0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;You can multiply the second row by $-1$ and swap it with the first one (that does not change the solution of the system) to get the exact same formula as presented in the video on the slide 17.&#xD;&#xA;&#xD;&#xA;If you apply the formula to all 4 points you get the system:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;0&amp;0&amp;0 &amp;-x_1&amp;-y_1&amp;-1&amp;y_1'x_1&amp;y_1'y_1&amp;y_1'\\&#xD;&#xA;x_1&amp;y_1&amp;1&amp;0&amp;0&amp;0&amp;-x_1x_1'&amp;-y_1x_1'&amp;-x_1' \\&#xD;&#xA;0&amp;0&amp;0 &amp;-x_2&amp;-y_2&amp;-1&amp;y_2'x_2&amp;y_2'y_2&amp;y_2'\\&#xD;&#xA;x_2&amp;y_2&amp;1&amp;0&amp;0&amp;0&amp;-x_2x_2'&amp;-y_2x_2'&amp;-x_2' \\&#xD;&#xA;0&amp;0&amp;0 &amp;-x_3&amp;-y_3&amp;-1&amp;y_3'x_3&amp;y_3'y_3&amp;y_3'\\&#xD;&#xA;x_3&amp;y_3&amp;1&amp;0&amp;0&amp;0&amp;-x_3x_3'&amp;-y_3x_3'&amp;-x_3' \\&#xD;&#xA;0&amp;0&amp;0 &amp;-x_4&amp;-y_4&amp;-1&amp;y_4'x_4&amp;y_4'y_4&amp;y_4'\\&#xD;&#xA;x_4&amp;y_4&amp;1&amp;0&amp;0&amp;0&amp;-x_4x_4'&amp;-y_4x_4'&amp;-x_4' \\&#xD;&#xA;\end{bmatrix} \begin{bmatrix}h_1\\h_2\\h_3\\h_4\\h_5\\h_6\\h_7\\h_8\\h_9\end{bmatrix}= \begin{bmatrix}0\\0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is now, that you have 9 unknowns but just 8 formulas. According to the answers in [this question][2], one possible solution is to constraint $h_9$ to be 1 and solve the resulting linear system. However, another way is to solve it as an underdetermined least-squares problem. This might be done using the SVD. However, as I said in the comments, this is a rather complicated algorithm. An easier one is to use QR decomposition, which can be a substep of the SVD, but this is also not too easy to code yourself. Since you don't seem to be that experienced in advanced linear algebra, you might try the constraint version first, before trying the SVD.&#xD;&#xA;&#xD;&#xA;You can also use more than 4 points, but then you get an overdetermined system, which can be solved with the SVD, QR decomposition or any other least-squares solver.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://engineering.purdue.edu/kak/computervision/ECE661Folder/Lecture10.pdf&#xD;&#xA;  [2]: https://math.stackexchange.com/questions/494238/how-to-compute-homography-matrix-h-from-corresponding-points-2d-2d-planar-homog" ContentLicense="CC BY-SA 4.0" />
  <row Id="27859" PostHistoryTypeId="5" PostId="9713" RevisionGUID="b09c64eb-b033-4f7f-aeac-39c5dbf8affe" CreationDate="2020-04-13T15:13:02.430" UserId="13159" Comment="added 110 characters in body" Text="The pattern you are seeing arises from perspective projection. Which causes all those parallel lines not to be parallel to each other when projected on the screen.&#xD;&#xA;&#xD;&#xA;Your problem with darker and lighter areas is caused by anti-aliasing which is trying to smooth the lines that are sometimes passing right in between 2 pixels, so it blends the lines with the black background.  &#xD;&#xA;You also have a problem that sometimes there is an empty (black) pixel between the lines lines and sometimes the lines are right next to each other.&#xD;&#xA;&#xD;&#xA;All this always occurs but the reason you're noticing a pattern here is that you just have a lot of really dense parallel lines.&#xD;&#xA;&#xD;&#xA;This reminds me of a common problem in game graphics where high-resolution textures viewed from a distance tend to look bad and flicker from frame to frame.  &#xD;&#xA;The usual way that is solved is by using a lower resolution texture when the object is far away.&#xD;&#xA;&#xD;&#xA;For you an equivalent would be to have more lines closer to the perspective camera and fewer lines further away. I'd also recommend adding transparency to the denser lines as they get further away to achieve a smooth transition.&#xD;&#xA;&#xD;&#xA;Edit: Just ran into a problem that has the most pronounced version of this effect, it's called shadow acne" ContentLicense="CC BY-SA 4.0" />
  <row Id="27860" PostHistoryTypeId="5" PostId="9718" RevisionGUID="8ea830ea-98eb-4f19-a89b-ff08a794cd8f" CreationDate="2020-04-13T15:13:17.907" UserId="13095" Comment="added 2 characters in body" Text="Since homography is not my topic, I can't really tell if I am missing some important edge cases, but after some research, I think I got the basics. I will use the same variable names, the guy in the video uses on slide 15 (slide numbers are in the bottom right corner on the red background).&#xD;&#xA;&#xD;&#xA;You start by defining 4 points in the plane $X$ where you say you know their projected points in plane $x$. You assume, that the transformation between $X$ and $x$ is linear and can be described by a matrix $H$. Means&#xD;&#xA;$$x = HX$$&#xD;&#xA;&#xD;&#xA;Now you want to calculate the Matrix $H$ that perfoms the projection:&#xD;&#xA;&#xD;&#xA;$$H = \begin{bmatrix}h_1&amp;h_2&amp;h_3\\h_4&amp;h_5&amp;h_6\\h_7&amp;h_8&amp;h_9\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;$h_1$ to $h_9$ are unknowns. So how do you get them? Well, you have 4 times:&#xD;&#xA;&#xD;&#xA;$p_i' = Hp_i$&#xD;&#xA;&#xD;&#xA;where $p_i'$ and $p_i$ are the projected and the original points. This full equation looks like this:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}x_i'\\y_i'\\1\end{bmatrix}= \begin{bmatrix}h_1&amp;h_2&amp;h_3\\h_4&amp;h_5&amp;h_6\\h_7&amp;h_8&amp;h_9\end{bmatrix}\begin{bmatrix}x_i\\y_i\\1\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;Perform the multiplication and you will get this:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}x_i'\\y_i'\\1\end{bmatrix}= \begin{bmatrix}x_ih_1+y_ih_2+h_3\\x_ih_4+y_ih_5+h_6\\x_ih_7+y_ih_8+h_9\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can also write this in some kind of nested vector fashion:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}x_i'\\y_i'\\1\end{bmatrix}= \begin{bmatrix}\bar{h_1}^T p\\\bar{h_2}^T p\\\bar{h_3}^T p\end{bmatrix} = \begin{bmatrix}p^T\bar{h_1}\\p^T\bar{h_2}\\p^T\bar{h_3}\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;$$\begin{matrix}\bar{h_1} = \begin{bmatrix}h_1\\h_2\\h_3\end{bmatrix}&amp;\bar{h_2} = \begin{bmatrix}h_4\\h_5\\h_6\end{bmatrix}&amp;\bar{h_1} = \begin{bmatrix}h_7\\h_8\\h_9\end{bmatrix}\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Now here comes the trick (got it from [this link][1]). If  $p'$ is equal to the vector $Hp$ their cross product must be the zero vector $\bar{0}$:&#xD;&#xA;&#xD;&#xA;$$p' \times Hp = \bar{0}$$&#xD;&#xA;&#xD;&#xA;Applying the cross product will give you three equations:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}y_i'p^T\bar{h_3} -  p^T\bar{h_2} &amp;= 0 \\ p^T\bar{h_1} - x_i' p^T\bar{h_3} &amp;= 0\\x_i' p^T\bar{h_2}-y_i' p^T\bar{h_1}&amp;=0\end{matrix}$$&#xD;&#xA;&#xD;&#xA;Write this as a matrix equation and you get:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}\bar{0}^T &amp;-p^T&amp;y_i'p^T\\p^T&amp;\bar{0}^T&amp;-x_i'p^T\\-y_i' p^T&amp;x_i' p^T&amp;\bar{0}^T\end{bmatrix} \begin{bmatrix}\bar{h_1}\\\bar{h_2}\\\bar{h_3}\end{bmatrix}= \begin{bmatrix}0\\0\\0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;Now, if you look at the matrix, you might notice, that the 3 columns are not linear independent. $-y_i'$ times the first column minus $x_i'$ times the second one, yields the third column. So you can drop one. &#xD;&#xA;&#xD;&#xA;If you drop the last column and replace all the vectors with their corresponding entries, you get:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}0&amp;0&amp;0 &amp;-x_i&amp;-y_i&amp;-1&amp;y_i'x_i&amp;y_i'y_i&amp;y_i'\\x_i&amp;y_i&amp;1&amp;0&amp;0&amp;0&amp;-x_ix_i'&amp;-y_ix_i'&amp;-x_i'\end{bmatrix} \begin{bmatrix}h_1\\h_2\\h_3\\h_4\\h_5\\h_6\\h_7\\h_8\\h_9\end{bmatrix}= \begin{bmatrix}0\\0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;You can multiply the second row by $-1$ and swap it with the first one (that does not change the solution of the system) to get the exact same formula as presented in the video on the slide 17.&#xD;&#xA;&#xD;&#xA;If you apply the formula to all 4 points you get the system:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA;0&amp;0&amp;0 &amp;-x_1&amp;-y_1&amp;-1&amp;y_1'x_1&amp;y_1'y_1&amp;y_1'\\&#xD;&#xA;x_1&amp;y_1&amp;1&amp;0&amp;0&amp;0&amp;-x_1x_1'&amp;-y_1x_1'&amp;-x_1' \\&#xD;&#xA;0&amp;0&amp;0 &amp;-x_2&amp;-y_2&amp;-1&amp;y_2'x_2&amp;y_2'y_2&amp;y_2'\\&#xD;&#xA;x_2&amp;y_2&amp;1&amp;0&amp;0&amp;0&amp;-x_2x_2'&amp;-y_2x_2'&amp;-x_2' \\&#xD;&#xA;0&amp;0&amp;0 &amp;-x_3&amp;-y_3&amp;-1&amp;y_3'x_3&amp;y_3'y_3&amp;y_3'\\&#xD;&#xA;x_3&amp;y_3&amp;1&amp;0&amp;0&amp;0&amp;-x_3x_3'&amp;-y_3x_3'&amp;-x_3' \\&#xD;&#xA;0&amp;0&amp;0 &amp;-x_4&amp;-y_4&amp;-1&amp;y_4'x_4&amp;y_4'y_4&amp;y_4'\\&#xD;&#xA;x_4&amp;y_4&amp;1&amp;0&amp;0&amp;0&amp;-x_4x_4'&amp;-y_4x_4'&amp;-x_4' \\&#xD;&#xA;\end{bmatrix} \begin{bmatrix}h_1\\h_2\\h_3\\h_4\\h_5\\h_6\\h_7\\h_8\\h_9\end{bmatrix}= \begin{bmatrix}0\\0\end{bmatrix}$$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is now, that you have 9 unknowns but just 8 formulas. According to the answers in [this question][2], one possible solution is to constraint $h_9$ to be 1 and solve the resulting linear system. However, another way is to solve it as an underdetermined least-squares problem. This might be done using the SVD. However, as I said in the comments, this is a rather complicated algorithm. An easier one is to use QR decomposition, which can be a substep of the SVD, but this is also not too easy to code yourself. Since you don't seem to be that experienced in advanced linear algebra, you might try the constraint technique first, before trying the SVD.&#xD;&#xA;&#xD;&#xA;You can also use more than 4 points, but then you get an overdetermined system, which can be solved with the SVD, QR decomposition or any other least-squares solver.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://engineering.purdue.edu/kak/computervision/ECE661Folder/Lecture10.pdf&#xD;&#xA;  [2]: https://math.stackexchange.com/questions/494238/how-to-compute-homography-matrix-h-from-corresponding-points-2d-2d-planar-homog" ContentLicense="CC BY-SA 4.0" />
  <row Id="27861" PostHistoryTypeId="2" PostId="9719" RevisionGUID="3361f0fb-d257-4ee3-8e98-99eb32ea38f5" CreationDate="2020-04-13T21:32:20.103" UserId="13159" Text="With WebGL 1 we can use WEBGL_draw_buffers extension which lets us use a texture as the depth attachment on the frame buffer.&#xD;&#xA;&#xD;&#xA;And we can chose to use LINEAR or NEAREST as the filtering method.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;gl.getExtension('WEBGL_draw_buffers');&#xD;&#xA;gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);&#xD;&#xA;gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);&#xD;&#xA;gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;WebGL 2 doesn't require an extension for this, but as soon as I switched to WebGL 2 I noticed that nothing happens unless I use NEAREST as the filtering method.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT24, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);&#xD;&#xA;gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); // wont work&#xD;&#xA;gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); // has to be NEAREST&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Is there something I have to do to make this possible?&#xD;&#xA;&#xD;&#xA;The only workaround for this that I know of would be to draw this depth texture onto another texture, but that seems like a waste of time." ContentLicense="CC BY-SA 4.0" />
  <row Id="27862" PostHistoryTypeId="1" PostId="9719" RevisionGUID="3361f0fb-d257-4ee3-8e98-99eb32ea38f5" CreationDate="2020-04-13T21:32:20.103" UserId="13159" Text="Does WebGL 2 support linear depth texture sampling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27863" PostHistoryTypeId="3" PostId="9719" RevisionGUID="3361f0fb-d257-4ee3-8e98-99eb32ea38f5" CreationDate="2020-04-13T21:32:20.103" UserId="13159" Text="|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27864" PostHistoryTypeId="2" PostId="9720" RevisionGUID="9838863e-561b-45aa-999c-3c0665973f5b" CreationDate="2020-04-13T23:36:10.003" UserId="5717" Text="Although it's not wrong to call it an interference pattern, it isn't the whole story here.&#xD;&#xA;&#xD;&#xA;The difference between the dark and bright areas is caused by antialiasing (filtering) which is done in the wrong color space. The lines drawn as a single bright pixel (red=219) do not have the same apparent brightness as the lines drawn as two darker pixels (red=118).&#xD;&#xA;&#xD;&#xA;After some fiddling with the numbers, they appear to be a match for &quot;TV RGB&quot; which is a range 16-235, given that ${219-16\over2}+16=117.5$ But those values are wrong even if you actually have a monitor correctly configured for that range (unlikely) as it is still not linear, as far as I know." ContentLicense="CC BY-SA 4.0" />
  <row Id="27865" PostHistoryTypeId="5" PostId="9709" RevisionGUID="a37da0cc-b06b-4ba7-af62-5318375df06d" CreationDate="2020-04-14T01:31:06.480" UserDisplayName="user13167" Comment="added 579 characters in body" Text="I have a simplistic shader program that adds reference coordinate planes to a scene. &#xD;&#xA;&#xD;&#xA;These planes are drawn as intersecting lines.&#xD;&#xA;&#xD;&#xA;When viewed at a distance, a visual artifact is created; there is a ripple of lighter and darker areas going left to right across the image.&#xD;&#xA;&#xD;&#xA;[![artifact][1]][1]&#xD;&#xA;&#xD;&#xA;Given how simple the shader program is, I think this must be due to the interpolation that occurs between the vertex and fragment shaders.&#xD;&#xA;&#xD;&#xA;- (a) Does this type of artifact have a name? &#xD;&#xA;- (b) What causes it?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I looked into whether this was being caused by anti-aliasing. However, disabling the anti-aliasing shows that the pattern is created beforehand. See here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;in short:&#xD;&#xA;&#xD;&#xA;- this is a Moire pattern (see [lfgtm's answer][3])&#xD;&#xA;- it is caused by trying to map a perspective projection of parallel lines onto a fixed grid of pixels. (see [zoran's answer][4])&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qNKfb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ulv9h.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/9710/13167&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/9713/13167" ContentLicense="CC BY-SA 4.0" />
  <row Id="27866" PostHistoryTypeId="5" PostId="9710" RevisionGUID="de83d2c0-f799-4f3d-8808-c7d54cb15f47" CreationDate="2020-04-14T08:46:22.643" UserId="9438" Comment="added 955 characters in body" Text="It's a interference pattern, called [Moire pattern][1]. You get them in signal analysis and various other fields. I guess it could be considered an optical illusion.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;To elaborate, this occurs when a periodic waveform goes out of phase with the observer. In your case the periodic waveform are the lines when observed as a scanline (from left to right of the image or vice versa), and since the image has a set number of horizontal pixels, in some parts, the pixel rasterization falls on pixel boundaries and then there is a watershed moment... should it be rasterized in pixel x, or x + 1. This then manifests as the wave pattern (due to the 'watershed' moment being slightly out of phase with the previous or next scanline). Also the display device can also have an effect. The moire in your image is much more pronounced on my computer monitor, than it is with my phone. (however this could be due to my phone’s browser scaling or applying some other filtering by default, which could help to reduce it).&#xD;&#xA;&#xD;&#xA;Anti aliasing certainly helps, however moire can never be completely eradicated, only mitigated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Moir%C3%A9_pattern" ContentLicense="CC BY-SA 4.0" />
  <row Id="27867" PostHistoryTypeId="5" PostId="9710" RevisionGUID="afe2acf3-6109-497a-ad5c-69bddef9fe1d" CreationDate="2020-04-14T09:38:43.633" UserId="9438" Comment="added 209 characters in body" Text="It's a interference pattern, called [Moire pattern][1]. You get them in signal analysis and various other fields. I guess it could be considered an optical illusion.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;To elaborate, this occurs when a periodic waveform goes out of phase with the observer. In your case the periodic waveform are the lines when observed as a scanline (from left to right of the image or vice versa), and the observer is the image with a set number of horizontal pixels. In some parts, the pixel rasterization falls on pixel boundaries and then there is a watershed moment... should it be rasterized in pixel x, or x + 1. This then manifests as the wave pattern (due to the 'watershed' moment being slightly out of phase with the previous or next scanline i.e one scanline, pixel falls on x, the next scanline it falls on x+1). Also the display device can also have an effect. The moire in your image is much more pronounced on my computer monitor, than it is with my phone. (however this could be due to my phone’s browser scaling or applying some other filtering by default, which could help to reduce it).&#xD;&#xA;&#xD;&#xA;Anti aliasing certainly helps, however moire can never be completely eradicated, only mitigated. Also note this can occur with rotated grids in orthographic, however perspective projection will certainly amplify this effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Moir%C3%A9_pattern" ContentLicense="CC BY-SA 4.0" />
  <row Id="27868" PostHistoryTypeId="5" PostId="9709" RevisionGUID="22408eca-b113-4a28-b914-4650c195d0ca" CreationDate="2020-04-14T11:24:03.510" UserDisplayName="user13167" Comment="added 499 characters in body" Text="I have a simplistic shader program that adds reference coordinate planes to a scene. &#xD;&#xA;&#xD;&#xA;These planes are drawn as intersecting lines.&#xD;&#xA;&#xD;&#xA;When viewed at a distance, a visual artifact is created; there is a ripple of lighter and darker areas going left to right across the image.&#xD;&#xA;&#xD;&#xA;[![with anti-aliasing][1]][1]&#xD;&#xA;&#xD;&#xA;Given how simple the shader program is, I think this must be due to the interpolation that occurs between the vertex and fragment shaders.&#xD;&#xA;&#xD;&#xA;- (a) Does this type of artifact have a name? &#xD;&#xA;- (b) What causes it?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I looked into whether this was being caused by anti-aliasing. However, disabling the anti-aliasing shows that the pattern is created beforehand. See here:&#xD;&#xA;&#xD;&#xA;[![without anti-aliasing][2]][2]&#xD;&#xA;&#xD;&#xA;in short:&#xD;&#xA;&#xD;&#xA;- this is a Moire pattern (see [lfgtm's answer][3])&#xD;&#xA;- it is caused by trying to map a perspective projection of parallel lines onto a fixed grid of pixels. (see [zoran's answer][4])&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;When looking at ways to address this problem, I thought that drawing the lines as surfaces with a gradient transparency across the width of the line would help by allowing the line to _straddle_ pixels and giving it a more accurate width.&#xD;&#xA;&#xD;&#xA;Here is how the grid looks when drawn as simple lines vs surfaces with gradient transparency.&#xD;&#xA;&#xD;&#xA;[![lines vs surfaces][5]][5]&#xD;&#xA;&#xD;&#xA;However, this had little appreciable effect on the light &amp; dark ripples.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qNKfb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ulv9h.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/9710/13167&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/9713/13167&#xD;&#xA;  [5]: https://i.stack.imgur.com/zBX9G.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27869" PostHistoryTypeId="5" PostId="9709" RevisionGUID="dd21a7dc-4aa5-4d5e-ba22-3c384b682fd3" CreationDate="2020-04-14T11:29:39.580" UserDisplayName="user13167" Comment="added 499 characters in body" Text="I have a simplistic shader program that adds reference coordinate planes to a scene. &#xD;&#xA;&#xD;&#xA;These planes are drawn as intersecting lines.&#xD;&#xA;&#xD;&#xA;When viewed at a distance, a visual artifact is created; there is a ripple of lighter and darker areas going left to right across the image.&#xD;&#xA;&#xD;&#xA;[![with anti-aliasing][1]][1]&#xD;&#xA;&#xD;&#xA;Given how simple the shader program is, I think this must be due to the interpolation that occurs between the vertex and fragment shaders.&#xD;&#xA;&#xD;&#xA;- (a) Does this type of artifact have a name? &#xD;&#xA;- (b) What causes it?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I looked into whether this was being caused by anti-aliasing. However, disabling the anti-aliasing shows that the pattern is created beforehand. See here:&#xD;&#xA;&#xD;&#xA;[![without anti-aliasing][2]][2]&#xD;&#xA;&#xD;&#xA;in short:&#xD;&#xA;&#xD;&#xA;- this is a Moire pattern (see [lfgtm's answer][3])&#xD;&#xA;- it is caused by trying to map a perspective projection of parallel lines onto a fixed grid of pixels. (see [zoran's answer][4])&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;When looking at ways to address this problem, I thought that drawing the lines as surfaces with a gradient transparency across the width of the line would help by allowing the line to _straddle_ pixels and giving it a more accurate width.&#xD;&#xA;&#xD;&#xA;Here is how the grid looks when drawn as simple lines vs surfaces with gradient transparency.&#xD;&#xA;&#xD;&#xA;[![lines vs surfaces][5]][5]&#xD;&#xA;&#xD;&#xA;This improved the definition between lines at a distance (i.e. they don't overlap each other and create a solid plane). However, this had little appreciable effect on the light &amp; dark ripples.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qNKfb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ulv9h.png&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/9710/13167&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/9713/13167&#xD;&#xA;  [5]: https://i.stack.imgur.com/zBX9G.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27870" PostHistoryTypeId="2" PostId="9721" RevisionGUID="96ae9ab5-50b0-4404-af17-469038fc15a7" CreationDate="2020-04-14T17:04:47.687" UserId="13179" Text="I'm trying to understand BRDF importance sampling following the exemples of the lambertian/diffuse model and the reciprocal Phong model.&#xD;&#xA;&#xD;&#xA;I would like to be able to extend the principle to other models. If you know good ressources on the subject please feel free to give me references.&#xD;&#xA;&#xD;&#xA;1) In the diffuse case, the pdf $p_d(\theta,\phi)$ of directions is :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{f_r\cos{\theta}\sin{\theta}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}} f_r\cos{\theta}\sin{\theta}\,\mathrm{d}\theta\mathrm{d}\phi}&#xD;&#xA;=\frac{\cos{\theta}\sin{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;In the reciprocal Phong model the pdf $p_s(\theta_s,\phi_s)$ is :&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{k_s\cos^n{\theta_s}\sin{\theta_s}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}}k_s\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s}&#xD;&#xA;=\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;But it seems that people use the densities :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{n+1}{2\pi}\cos^n{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;What is the reason ? Could we use both versions ? Are they equivalent ?&#xD;&#xA;&#xD;&#xA;2) Furthermore :&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi=2\pi\neq 1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s = \quad?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Shouldn't the pdfs have an integral equal to 1?&#xD;&#xA;&#xD;&#xA;3) In another post (https://computergraphics.stackexchange.com/questions/5968/probability-density-function-while-using-spherical-coordinates), people explains that the sines functions are never taken into account because they are &quot;artefacts&quot; of the coordinate system.&#xD;&#xA;&#xD;&#xA;Is that true ? Should we always reject sines functions ? And if so, why do we compute pdf with sines and reject them after ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27871" PostHistoryTypeId="1" PostId="9721" RevisionGUID="96ae9ab5-50b0-4404-af17-469038fc15a7" CreationDate="2020-04-14T17:04:47.687" UserId="13179" Text="Understanding BRDF sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="27872" PostHistoryTypeId="3" PostId="9721" RevisionGUID="96ae9ab5-50b0-4404-af17-469038fc15a7" CreationDate="2020-04-14T17:04:47.687" UserId="13179" Text="|pathtracing|brdf|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27873" PostHistoryTypeId="5" PostId="9720" RevisionGUID="38caf7ab-0f41-4127-b267-241bd917f648" CreationDate="2020-04-14T18:02:25.250" UserId="5717" Comment="added example of a better filtered grid" Text="Although it's not wrong to call it an interference pattern, it isn't the whole story here.&#xD;&#xA;&#xD;&#xA;The difference between the dark and bright areas is caused by antialiasing (filtering) which is done in the wrong color space. The lines drawn as a single bright pixel (red=219) do not have the same apparent brightness as the lines drawn as two darker pixels (red=118).&#xD;&#xA;&#xD;&#xA;After some fiddling with the numbers, they appear to be a match for &quot;TV RGB&quot; which is a range 16-235, given that ${219-16\over2}+16=117.5$ But those values are wrong even if you actually have a monitor correctly configured for that range (unlikely) as it is still not linear, as far as I know.&#xD;&#xA;&#xD;&#xA;Here's what a better filtered grid should look like:&#xD;&#xA;[![perspective grid][1]][1]&#xD;&#xA;Make sure to view this in its own window, without any browser zoom applied as that can introduce its own artifacts.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AHtck.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27878" PostHistoryTypeId="6" PostId="9668" RevisionGUID="c08ee39c-091c-4a55-9faf-d90151e7f2f5" CreationDate="2020-04-14T23:26:44.477" UserId="9438" Comment="added opengl tag" Text="|opengl|lighting|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27879" PostHistoryTypeId="24" PostId="9668" RevisionGUID="c08ee39c-091c-4a55-9faf-d90151e7f2f5" CreationDate="2020-04-14T23:26:44.477" Comment="Proposed by 9438 approved by 209, 5717 edit id of 514" ContentLicense="CC BY-SA 4.0" />
  <row Id="27880" PostHistoryTypeId="2" PostId="9723" RevisionGUID="b8181329-3ccc-4b57-a4a4-149e852a58bc" CreationDate="2020-04-15T00:53:17.873" UserId="4766" Text="[The spec](https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf) says depth textures are not filterable.&#xD;&#xA;&#xD;&#xA;&gt; ### 3.8.13&#xD;&#xA;&gt;&#xD;&#xA;&gt;...&#xD;&#xA;&gt;&#xD;&#xA;&gt; Using the preceding definitions, a texture is complete unless any of the following conditions hold true:&#xD;&#xA;&gt;&#xD;&#xA;&gt; * The effective internal format specified for the texture arrays is a sized internal depth or depth and stencil format (see table 3.14), the value of TEXTURE_COMPARE_MODE is NONE, and either the magnification filter is not NEAREST or the minification filter is neither NEAREST nor NEAREST_-&#xD;&#xA;MIPMAP_NEAREST" ContentLicense="CC BY-SA 4.0" />
  <row Id="27881" PostHistoryTypeId="5" PostId="9721" RevisionGUID="d17c47f8-def2-43ff-8d94-5a88f31c523b" CreationDate="2020-04-15T08:32:23.057" UserId="13179" Comment="added 1953 characters in body" Text="I'm trying to understand BRDF importance sampling following the exemples of the lambertian/diffuse model and the reciprocal Phong model.&#xD;&#xA;&#xD;&#xA;I would like to be able to extend the principle to other models. If you know good ressources on the subject please feel free to give me references.&#xD;&#xA;&#xD;&#xA;1) In the diffuse case, the pdf $p_d(\theta,\phi)$ of directions is :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{f_r\cos{\theta}\sin{\theta}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}} f_r\cos{\theta}\sin{\theta}\,\mathrm{d}\theta\mathrm{d}\phi}&#xD;&#xA;=\frac{\cos{\theta}\sin{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;In the reciprocal Phong model the pdf $p_s(\theta_s,\phi_s)$ is :&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{k_s\cos^n{\theta_s}\sin{\theta_s}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}}k_s\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s}&#xD;&#xA;=\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;But it seems that people use the densities :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{n+1}{2\pi}\cos^n{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;What is the reason ? Could we use both versions ? Are they equivalent ?&#xD;&#xA;&#xD;&#xA;2) Furthermore :&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi=2\pi\neq 1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s = \quad?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Shouldn't the pdfs have an integral equal to 1?&#xD;&#xA;&#xD;&#xA;3) In another post (https://computergraphics.stackexchange.com/questions/5968/probability-density-function-while-using-spherical-coordinates), people explains that the sines functions are never taken into account because they are &quot;artefacts&quot; of the coordinate system.&#xD;&#xA;&#xD;&#xA;Is that true ? Should we always reject sines functions ? And if so, why do we compute pdf with sines and reject them after ?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;Thanks to the comment of @lightxbulb, it seems that the integrals of my second point should be evaluated with respect to solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_{\Omega} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\omega&#xD;&#xA;=\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}\sin{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi&#xD;&#xA;=1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_{\Omega}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\omega&#xD;&#xA;=\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s&#xD;&#xA;=1&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;which brings me to another point:&#xD;&#xA;&#xD;&#xA;4) Here are different Monte-Carlo estimators for the reflected part of the rendering equation, with respect to different coordinate system:&#xD;&#xA;&#xD;&#xA;Solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{1}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(x,y,z)) f_r(\vec{x},\vec{\omega}_i(x,y,z),\vec{\omega}_o) \cos{\theta}}{p_1(\vec{\omega}_i(x,y,z))}&#xD;&#xA;\end{equation}&#xD;&#xA;Spherical coordinates:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{1}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(\theta,\phi)) f_r(\vec{x},\vec{\omega}_i(\theta,\phi),\vec{\omega}_o) \cos{\theta}\sin{\theta}}{p_2(\vec{\omega}_i(\theta,\phi))}&#xD;&#xA;\end{equation}&#xD;&#xA;Unit square:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{\pi}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(u,v)) f_r(\vec{x},\vec{\omega}_i(u,v),\vec{\omega}_o)}{p_3(\vec{\omega}_i(u,v))}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Sorry for the heavy notations but I would like to fully understand. So:&#xD;&#xA;\begin{equation}&#xD;&#xA;p_1(\vec{\omega_i})=\frac{\cos{\theta}}{\pi}\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_2(\vec{\omega_i})=\frac{\cos{\theta}\sin{\theta}}{\pi}\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_3(\vec{\omega_i})=\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;People seem to use:&#xD;&#xA;\begin{equation}&#xD;&#xA;p_3(\vec{\omega_i})=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;I'm doing something wrong but I don't know why" ContentLicense="CC BY-SA 4.0" />
  <row Id="27882" PostHistoryTypeId="5" PostId="9721" RevisionGUID="83e012f3-8ed4-4d0e-ac0b-8d62637635fd" CreationDate="2020-04-15T11:28:43.783" UserId="13179" Comment="added 1 character in body" Text="I'm trying to understand BRDF importance sampling following the exemples of the lambertian/diffuse model and the reciprocal Phong model.&#xD;&#xA;&#xD;&#xA;I would like to be able to extend the principle to other models. If you know good ressources on the subject please feel free to give me references.&#xD;&#xA;&#xD;&#xA;1) In the diffuse case, the pdf $p_d(\theta,\phi)$ of directions is :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{f_r\cos{\theta}\sin{\theta}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}} f_r\cos{\theta}\sin{\theta}\,\mathrm{d}\theta\mathrm{d}\phi}&#xD;&#xA;=\frac{\cos{\theta}\sin{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;In the reciprocal Phong model the pdf $p_s(\theta_s,\phi_s)$ is :&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{k_s\cos^n{\theta_s}\sin{\theta_s}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}}k_s\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s}&#xD;&#xA;=\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;But it seems that people use the densities :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{n+1}{2\pi}\cos^n{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;What is the reason ? Could we use both versions ? Are they equivalent ?&#xD;&#xA;&#xD;&#xA;2) Furthermore :&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi=2\pi\neq 1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s = \quad?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Shouldn't the pdfs have an integral equal to 1?&#xD;&#xA;&#xD;&#xA;3) In another post (https://computergraphics.stackexchange.com/questions/5968/probability-density-function-while-using-spherical-coordinates), people explains that the sines functions are never taken into account because they are &quot;artefacts&quot; of the coordinate system.&#xD;&#xA;&#xD;&#xA;Is that true ? Should we always reject sines functions ? And if so, why do we compute pdf with sines and reject them after ?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;Thanks to the comment of @lightxbulb, it seems that the integrals of my second point should be evaluated with respect to solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_{\Omega} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\omega&#xD;&#xA;=\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}\sin{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi&#xD;&#xA;=1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_{\Omega}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\omega&#xD;&#xA;=\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s&#xD;&#xA;=1&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;which brings me to another point:&#xD;&#xA;&#xD;&#xA;4) Here are different Monte-Carlo estimators for the reflected part of the rendering equation, with respect to different coordinate system:&#xD;&#xA;&#xD;&#xA;Solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{1}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(x,y,z)) f_r(\vec{x},\vec{\omega}_i(x,y,z),\vec{\omega}_o) \cos{\theta}}{p_1(\vec{\omega}_i(x,y,z))}&#xD;&#xA;\end{equation}&#xD;&#xA;Spherical coordinates:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{1}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(\theta,\phi)) f_r(\vec{x},\vec{\omega}_i(\theta,\phi),\vec{\omega}_o) \cos{\theta}\sin{\theta}}{p_2(\vec{\omega}_i(\theta,\phi))}&#xD;&#xA;\end{equation}&#xD;&#xA;Unit square:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{\pi}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(u,v)) f_r(\vec{x},\vec{\omega}_i(u,v),\vec{\omega}_o)}{p_3(\vec{\omega}_i(u,v))}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Sorry for the heavy notations but I would like to fully understand. So:&#xD;&#xA;\begin{equation}&#xD;&#xA;p_1(\vec{\omega_i})=\frac{\cos{\theta}}{\pi}\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_2(\vec{\omega_i})=\frac{\cos{\theta}\sin{\theta}}{\pi}\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_3(\vec{\omega_i})=\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;People seem to use:&#xD;&#xA;\begin{equation}&#xD;&#xA;p_3(\vec{\omega_i})=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;I'm doing something wrong but I don't know what" ContentLicense="CC BY-SA 4.0" />
  <row Id="27883" PostHistoryTypeId="50" PostId="8587" RevisionGUID="13ea4ab4-3361-457c-a014-9aaf78bbe570" CreationDate="2020-04-15T12:01:40.257" UserId="-1" />
  <row Id="27885" PostHistoryTypeId="2" PostId="9724" RevisionGUID="6984f6aa-bef4-45af-93d7-5b7015328ea8" CreationDate="2020-04-15T12:33:25.480" UserId="13184" Text="I am loading an OBJ file using the ASSIMP library. Following is the MTL file associated with the obj file.&#xD;&#xA;&#xD;&#xA;    newmtl initialShadingGroup&#xD;&#xA;    Kd 0.50 0.50 0.50&#xD;&#xA;    Ka 0.09 0.09 0.09&#xD;&#xA;    Tf 1.00 1.00 1.00&#xD;&#xA;    Ns 10.0&#xD;&#xA;    map_Ka sphere_roughness.jpg&#xD;&#xA;    map_Kd sphere_albedo.jpg&#xD;&#xA;    map_Ks sphere_metallic.jpg&#xD;&#xA;    bump sphere_normal.jpg&#xD;&#xA;    disp sphere_bump.jpg&#xD;&#xA;    illum 7&#xD;&#xA;&#xD;&#xA;I want to read the illum value so that I can choose an appropriate sharding model in my shaders. The code I'm using is &#xD;&#xA;&#xD;&#xA;    int shadingModel;&#xD;&#xA;    material-&gt;Get(AI_MATKEY_SHADING_MODEL, shadingModel);&#xD;&#xA;    std::cout &lt;&lt; &quot;ShadingModel: &quot; &lt;&lt; shadingModel&lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;But the output I'm getting is &#xD;&#xA;&#xD;&#xA;    ShadingModel: 2&#xD;&#xA;&#xD;&#xA;when the value is 7. Is there something that I'm doing it wrong or is it the wrong way to retrieve the shading model. &#xD;&#xA;Thanks for your help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="27886" PostHistoryTypeId="1" PostId="9724" RevisionGUID="6984f6aa-bef4-45af-93d7-5b7015328ea8" CreationDate="2020-04-15T12:33:25.480" UserId="13184" Text="How to read illum value from mtl file using Assimp library?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27887" PostHistoryTypeId="3" PostId="9724" RevisionGUID="6984f6aa-bef4-45af-93d7-5b7015328ea8" CreationDate="2020-04-15T12:33:25.480" UserId="13184" Text="|opengl|rendering|shading|material|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27893" PostHistoryTypeId="5" PostId="9721" RevisionGUID="90891443-8715-44bb-b10c-4ab5d769475c" CreationDate="2020-04-15T21:52:37.987" UserId="13179" Comment="added 1678 characters in body" Text="I'm trying to understand BRDF importance sampling following the exemples of the lambertian/diffuse model and the reciprocal Phong model.&#xD;&#xA;&#xD;&#xA;I would like to be able to extend the principle to other models. If you know good ressources on the subject please feel free to give me references.&#xD;&#xA;&#xD;&#xA;1) In the diffuse case, the pdf $p_d(\theta,\phi)$ of directions is :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{f_r\cos{\theta}\sin{\theta}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}} f_r\cos{\theta}\sin{\theta}\,\mathrm{d}\theta\mathrm{d}\phi}&#xD;&#xA;=\frac{\cos{\theta}\sin{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;In the reciprocal Phong model the pdf $p_s(\theta_s,\phi_s)$ is :&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{k_s\cos^n{\theta_s}\sin{\theta_s}}{\int_0^{2\pi}\int_0^{\frac{\pi}{2}}k_s\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s}&#xD;&#xA;=\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;But it seems that people use the densities :&#xD;&#xA;\begin{equation}&#xD;&#xA;p_d(\theta,\phi)=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;p_s(\theta_s,\phi_s)=\frac{n+1}{2\pi}\cos^n{\theta_s}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;What is the reason ? Could we use both versions ? Are they equivalent ?&#xD;&#xA;&#xD;&#xA;2) Furthermore :&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi=2\pi\neq 1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s = \quad?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Shouldn't the pdfs have an integral equal to 1?&#xD;&#xA;&#xD;&#xA;3) In another post (https://computergraphics.stackexchange.com/questions/5968/probability-density-function-while-using-spherical-coordinates), people explains that the sines functions are never taken into account because they are &quot;artefacts&quot; of the coordinate system.&#xD;&#xA;&#xD;&#xA;Is that true ? Should we always reject sines functions ? And if so, why do we compute pdf with sines and reject them after ?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;Thanks to the comment of @lightxbulb, it seems that the integrals of my second point should be evaluated with respect to solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_{\Omega} \frac{\cos{\theta}}{\pi}\,\mathrm{d}\omega&#xD;&#xA;=\int_0^{2\pi}\int_0^{\frac{\pi}{2}} \frac{\cos{\theta}\sin{\theta}}{\pi}\,\mathrm{d}\theta\mathrm{d}\phi&#xD;&#xA;=1&#xD;&#xA;\end{equation}&#xD;&#xA;and&#xD;&#xA;\begin{equation}&#xD;&#xA;\int_{\Omega}\frac{n+1}{2\pi}\cos^n{\theta_s}\,\mathrm{d}\omega&#xD;&#xA;=\int_0^{2\pi}\int_0^{\frac{\pi}{2}}\frac{n+1}{2\pi}\cos^n{\theta_s}\sin{\theta_s}\,\mathrm{d}\theta_s\mathrm{d}\phi_s&#xD;&#xA;=1&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;which brings me to another point:&#xD;&#xA;&#xD;&#xA;4) Here are different Monte-Carlo estimators for the reflected part of the rendering equation, with respect to different coordinate system:&#xD;&#xA;&#xD;&#xA;Solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{1}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(x,y,z)) f_r(\vec{x},\vec{\omega}_i(x,y,z),\vec{\omega}_o) \cos{\theta}}{p_1(\vec{\omega}_i(x,y,z))}&#xD;&#xA;\end{equation}&#xD;&#xA;Spherical coordinates:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{1}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(\theta,\phi)) f_r(\vec{x},\vec{\omega}_i(\theta,\phi),\vec{\omega}_o) \cos{\theta}\sin{\theta}}{p_2(\vec{\omega}_i(\theta,\phi))}&#xD;&#xA;\end{equation}&#xD;&#xA;Unit square:&#xD;&#xA;\begin{equation}&#xD;&#xA;L_r(\vec{x},\vec{\omega}_o)=\frac{\pi}{N}\sum_{i=1}^N \frac{L_i(\vec{x},\vec{\omega}_i(u,v)) f_r(\vec{x},\vec{\omega}_i(u,v),\vec{\omega}_o)}{p_3(\vec{\omega}_i(u,v))}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Sorry for the heavy notations but I would like to fully understand. So:&#xD;&#xA;\begin{equation}&#xD;&#xA;p_1(\vec{\omega_i})=\frac{\cos{\theta}}{\pi}\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_2(\vec{\omega_i})=\frac{\cos{\theta}\sin{\theta}}{\pi}\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;p_3(\vec{\omega_i})=\quad ?&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;People seem to use:&#xD;&#xA;\begin{equation}&#xD;&#xA;p_3(\vec{\omega_i})=\frac{\cos{\theta}}{\pi}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;I'm doing something wrong but I don't know what&#xD;&#xA;&#xD;&#xA;EDIT2:&#xD;&#xA;&#xD;&#xA;The equation involving ($\xi_1,\xi_2$) on page 9 in the reference is not the reflected part of the rendering equation but the integral of the BRDF on the hemisphere. But we don't care here because 1) the luminance $L_i$ in the reflected part is not known (that's why we use importance sampling only on the BRDF) and 2) a Monte-Carlo estimator is something like:&#xD;&#xA;\begin{equation}&#xD;&#xA;\int f(x)\, \mathrm{d}x\approx\frac{1}{N}\sum_{i=1}^N \frac{f(x_i)}{p(x_i)}&#xD;&#xA;\end{equation}&#xD;&#xA;So that's just different integrands but the pdfs should be the same. Correct me if I'm wrong.&#xD;&#xA;&#xD;&#xA;Here are the mappings:&#xD;&#xA;&#xD;&#xA;From the spherical coordinates to solid angles:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{cases}&#xD;&#xA;x = \sin{\theta}\cos{\phi} \\&#xD;&#xA;y = \sin{\theta}\sin{\phi} \\&#xD;&#xA;z = \cos{\theta}&#xD;&#xA;\end{cases}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;From the unit square to the spherical coordinates:&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{cases}&#xD;&#xA;\theta = \arcsin{\sqrt{u}} \\&#xD;&#xA;\phi = 2\pi v&#xD;&#xA;\end{cases}&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;I suppose that the expression &quot;cosine weighted mapping&quot; comes from the cosine with the normal ($z=\cos{\theta}$) ? If the cosine of the mapping modify the pdf why the sine of the Jacobian doesn't ? And if the mapping modify the pdf why ($\theta = \arcsin{\sqrt{u}}$) doesn't too ?&#xD;&#xA;&#xD;&#xA;I have an implementation in front of me (ref : Lászlo Szirmay-Kalos, Monte Carlo Methods in Global Illumination, page 104 and 112). I think that what is done is to use the first estimator with the pdf $p(\vec{\omega}_i)=\frac{\cos{\theta}}{\pi}$. But the choice of the pdf is not explained and I'm very confused with the different mappings and the influence of each transformation on the mathematical formulation of the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="27897" PostHistoryTypeId="2" PostId="9726" RevisionGUID="6eb9d821-e2d5-473c-b1cf-4b5785aaa11f" CreationDate="2020-04-16T01:51:33.223" UserId="7462" Text="I seem to have an off by one error when creating the indices for the faces of a sphere and I can't understand where.&#xD;&#xA;&#xD;&#xA;The exact problem is that when I try to calculate the normals of each face a dark region of nans appears in the region where the vertices wrap around.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generate the vertices and face information like this:&#xD;&#xA;&#xD;&#xA;    pair&lt;vector&lt;vec3&gt;, vector&lt;uint&gt;&gt; GenerateSphere(&#xD;&#xA;        float radius,&#xD;&#xA;        uint u_resolution,&#xD;&#xA;        uint v_resolution)&#xD;&#xA;    {&#xD;&#xA;        vector&lt;vec3&gt; points;&#xD;&#xA;        vector&lt;uint&gt; indices;&#xD;&#xA;        for(uint i=0; i&lt; u_resolution; i++)&#xD;&#xA;        {&#xD;&#xA;            float u = (float(i) / float(u_resolution - 1)) * M_PI - M_PI / 2.f;&#xD;&#xA;            for(uint j=0; j &lt; v_resolution; j++)&#xD;&#xA;            {&#xD;&#xA;                float v = float(j) * 2.f * M_PI / float(v_resolution - 1);&#xD;&#xA;    &#xD;&#xA;                points.push_back(vec3(cos(u) * cos(v), cos(u) * sin(v), sin(u)) * radius);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for(uint i=0; i &lt; u_resolution - 1; i++)&#xD;&#xA;        {&#xD;&#xA;            for(uint j=0; j &lt; v_resolution; j++)&#xD;&#xA;            {&#xD;&#xA;                // Grab the 4 points in a quad face in the sphere&#xD;&#xA;                uint p00 = (i * (v_resolution) + j);&#xD;&#xA;                uint p01 = (i * (v_resolution) + ((j + 1) % v_resolution));&#xD;&#xA;                uint p10 = ((i + 1) * v_resolution + j);&#xD;&#xA;                uint p11 = ((i + 1) * v_resolution + ((j + 1) % v_resolution));&#xD;&#xA;    &#xD;&#xA;                assert((i + 1) &lt; u_resolution);&#xD;&#xA;                assert(p00 &lt; points.size());&#xD;&#xA;                assert(p01 &lt; points.size());&#xD;&#xA;                assert(p10 &lt; points.size());&#xD;&#xA;                assert(p11 &lt; points.size());&#xD;&#xA;                assert(&#xD;&#xA;                    p00 != p01 &amp;&amp; p00 != p11 &amp;&amp; p00 != p10 &amp;&amp;&#xD;&#xA;                    p01 != p10 &amp;&amp; p01 != p11 &amp;&amp;&#xD;&#xA;                    p10 != p11&#xD;&#xA;                );&#xD;&#xA;    &#xD;&#xA;                // Add the first triangle&#xD;&#xA;                indices.push_back(p00);&#xD;&#xA;                indices.push_back(p01);&#xD;&#xA;                indices.push_back(p11);&#xD;&#xA;    &#xD;&#xA;                // Add the second triangle&#xD;&#xA;                indices.push_back(p00);&#xD;&#xA;                indices.push_back(p11);&#xD;&#xA;                indices.push_back(p10);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        //for(auto&amp; v : points) cout &lt;&lt; to_string(v) &lt;&lt; endl;&#xD;&#xA;        //cout &lt;&lt; endl;&#xD;&#xA;        return {points, indices};&#xD;&#xA;    }&#xD;&#xA;And immediately after calculate the normals like this:&#xD;&#xA;&#xD;&#xA;    std::vector&lt;glm::vec3&gt; GenerateNormals(const std::vector&lt;glm::vec3&gt;&amp; vertices,&#xD;&#xA;        const std::vector&lt;uint&gt;&amp; indices)&#xD;&#xA;    {&#xD;&#xA;        assert(indices.size() % 3 ==0);&#xD;&#xA;    &#xD;&#xA;        map&lt;uint, vector&lt;vec3&gt;&gt; normal_map;&#xD;&#xA;        for(uint i=0; i &lt; indices.size(); i += 3)&#xD;&#xA;        {&#xD;&#xA;            vec3 v1 = vertices[indices[i]];&#xD;&#xA;            vec3 v2 = vertices[indices[i + 1]];&#xD;&#xA;            vec3 v3 = vertices[indices[i + 2]];&#xD;&#xA;    &#xD;&#xA;            vec3 d1 = v2 - v1;&#xD;&#xA;            vec3 d2 = v3 - v1;&#xD;&#xA;    &#xD;&#xA;            assert(indices[i] &lt; vertices.size());&#xD;&#xA;            assert(indices[i + 1] &lt; vertices.size());&#xD;&#xA;            assert(indices[i + 2] &lt; vertices.size());&#xD;&#xA;            assert(indices[i] != indices[i+1] &amp;&amp; indices[i] != indices[i+2] &amp;&amp;&#xD;&#xA;                indices[i+1] != indices[i+2]);&#xD;&#xA;    &#xD;&#xA;            if(abs(dot(d1, d2)) &lt; 0.0001)&#xD;&#xA;            {&#xD;&#xA;                d1 = v3 - v2;&#xD;&#xA;                d2 = v1 - v2;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(abs(dot(d1, d2)) &lt; 0.0001)&#xD;&#xA;            {&#xD;&#xA;                d1 = v1 - v3;&#xD;&#xA;                d2 = v2 - v3;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            vec3 normal = normalize(cross(d1, d2));&#xD;&#xA;    &#xD;&#xA;            normal_map[indices[i]].push_back(normal);&#xD;&#xA;            normal_map[indices[i + 1]].push_back(normal);&#xD;&#xA;            normal_map[indices[i + 2]].push_back(normal);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        assert(normal_map.size() == vertices.size());&#xD;&#xA;        std::vector&lt;glm::vec3&gt; normals(vertices.size());&#xD;&#xA;        for(auto&amp; pair : normal_map)&#xD;&#xA;        {&#xD;&#xA;            uint index = pair.first;&#xD;&#xA;            vector&lt;vec3&gt; v_normals = pair.second;&#xD;&#xA;    &#xD;&#xA;            vec3 normal(0);&#xD;&#xA;            for(auto&amp; n : v_normals)&#xD;&#xA;                normal += n;&#xD;&#xA;    &#xD;&#xA;            normal /= float(v_normals.size());&#xD;&#xA;            normals[index] = normal;&#xD;&#xA;        }&#xD;&#xA;        assert(normals.size() == vertices.size());&#xD;&#xA;        return normals;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note: I know that I could just calculate the normals by taking the difference between the current vertex and the center of the sphere. This 2 functions I plan to use as templates to code other paramtetric surfaces, so that's not a solution for me I am trying to understand what I did wrong more than trying to fix it.&#xD;&#xA;&#xD;&#xA;I have added lots of assertions through the code to try to catch the issue and I have also stepped through gdb but I can't seem to find the issue. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yh3pn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27898" PostHistoryTypeId="1" PostId="9726" RevisionGUID="6eb9d821-e2d5-473c-b1cf-4b5785aaa11f" CreationDate="2020-04-16T01:51:33.223" UserId="7462" Text="Off by one error when creating face indices" ContentLicense="CC BY-SA 4.0" />
  <row Id="27899" PostHistoryTypeId="3" PostId="9726" RevisionGUID="6eb9d821-e2d5-473c-b1cf-4b5785aaa11f" CreationDate="2020-04-16T01:51:33.223" UserId="7462" Text="|c++|geometry|parametrization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27900" PostHistoryTypeId="2" PostId="9727" RevisionGUID="cf3c49b0-9e27-457a-b1d5-e91d14253f45" CreationDate="2020-04-16T01:52:10.217" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="27901" PostHistoryTypeId="1" PostId="9727" RevisionGUID="cf3c49b0-9e27-457a-b1d5-e91d14253f45" CreationDate="2020-04-16T01:52:10.217" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="27902" PostHistoryTypeId="2" PostId="9728" RevisionGUID="1e5cbaee-173a-4578-9f9a-0d88ef82b25d" CreationDate="2020-04-16T01:52:10.217" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="27903" PostHistoryTypeId="1" PostId="9728" RevisionGUID="1e5cbaee-173a-4578-9f9a-0d88ef82b25d" CreationDate="2020-04-16T01:52:10.217" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="27905" PostHistoryTypeId="2" PostId="9730" RevisionGUID="133e11d4-24d2-487c-912b-671b42f703f6" CreationDate="2020-04-16T04:06:20.223" UserId="10079" Text="I am reading the paper *Texture Synthesis over Arbitrary Manifold Surfaces* available [here](http://graphics.stanford.edu/papers/texture-synthesis-sig01/texture.pdf?q=illustrating-smooth-surfaces).&#xD;&#xA;&#xD;&#xA;On page $3$ on the right sight of the page they refer to isotropic and anisotropic textures.&#xD;&#xA;I am familiar with anistropic texture filtering, but not an actual texture itself called anisotropic.&#xD;&#xA;&#xD;&#xA;Further they refer to an *n-way symmetric texture*, which I am not familiar with, and a google search did not yield any results.&#xD;&#xA;&#xD;&#xA;I am guessing an *anisotropic* texture is a texture that accounts for different viewing directions (?) and perhaps an *n-way symmetric texture* is such a texture that accounts for $n$ different viewing directions?&#xD;&#xA;&#xD;&#xA;If anyone could clarify these two terms that would be much appreciated. I realize this paper is from $2001$ so these terms might not still be in use.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27906" PostHistoryTypeId="1" PostId="9730" RevisionGUID="133e11d4-24d2-487c-912b-671b42f703f6" CreationDate="2020-04-16T04:06:20.223" UserId="10079" Text="Isotropic vs Anisotropic Textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="27907" PostHistoryTypeId="3" PostId="9730" RevisionGUID="133e11d4-24d2-487c-912b-671b42f703f6" CreationDate="2020-04-16T04:06:20.223" UserId="10079" Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27908" PostHistoryTypeId="2" PostId="9731" RevisionGUID="e574e57c-561b-4aef-842e-a48741d21449" CreationDate="2020-04-16T13:06:44.980" UserId="13095" Text="The problem with your code is, that it produces a lot of degenerated triangles. The not so obvious ones are at the top and bottom. The obvious ones are at the &quot;wrapping line&quot;.&#xD;&#xA;&#xD;&#xA;So what exactly is the problem? Each of your faces is a rectangle that consists of 2 triangles and 4 points. The 2 triangles share 2 points and each one has 1 individual point. But at the bottom/top 2 points are identical, so your rectangle degenerates to a triangle. As a result, one triangle degenerates to a line because of the duplicate points.&#xD;&#xA;&#xD;&#xA;Now, why is this problematic for you? It is this line, that causes the trouble: &#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;vec3 normal = normalize(cross(d1, d2));&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The cross product of a vector with itself is the zero vector. If you normalize a vector, you divide by its length, which is 0 in this case. So this is were your `NaN`s come from. Until now I just spoke about the top and bottom, but why is it happening at the &quot;wrapping line&quot;? The problem is during your creation of the indices:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;    for(uint i=0; i &lt; u_resolution - 1; i++)&#xD;&#xA;    {&#xD;&#xA;        for(uint j=0; j &lt; v_resolution; j++)&#xD;&#xA;        {&#xD;&#xA;            // Grab the 4 points in a quad face in the sphere&#xD;&#xA;            uint p00 = (i * (v_resolution) + j);&#xD;&#xA;            uint p01 = (i * (v_resolution) + ((j + 1) % v_resolution));&#xD;&#xA;            uint p10 = ((i + 1) * v_resolution + j);&#xD;&#xA;            uint p11 = ((i + 1) * v_resolution + ((j + 1) % v_resolution));&#xD;&#xA;   ...&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The `j` loop is running until `v_resolution`.  So `j+1` gets problematic. I know your intention here is, that you need the triangles from the &quot;other side&quot;, to calculate your normals correctly. That is why you performed the `% v_resolution` to get the corresponding points. But the problem is, you are not getting the points you want. With your code, you are including the last and first point of a &quot;horizontal line&quot;, but they are identical in your case. The result is that you get a face that degenerates to a line, which means, that you will divide by 0 during normalization of both triangles surface normals.&#xD;&#xA;&#xD;&#xA;A quick way to fix the `NaN`s at the &quot;wrapping line&quot; would be to make a temporary variable and store `j+1` in it. Then check if it is equal or higher than `v_resolution`. If `true`, increase it by one. Use this variable everywhere you used `j+1` during the index generation. However, this will still cause an issue at the wrapping line, since your start and end vertices are not the same and you only considered &quot;both sides&quot; for the last vertices of a horizontal line, but not for the first. This will lead to incorrect normals for the start vertices and you should see a jump in the shading. You might fix it, by just copying the normals of the last vertices to the first ones. &#xD;&#xA;&#xD;&#xA;Also, you still need to address the problems at the top and bottom. This can be fixed by making a special loop only for top and bottom triangles. However, these are suboptimal fixes. A better approach would be to write code that does not produce duplicate points since it lowers the risk of creating degenerated triangles and is more memory efficient.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27909" PostHistoryTypeId="5" PostId="9731" RevisionGUID="12e77d74-3b19-469e-99e4-280001aa5fe7" CreationDate="2020-04-16T15:36:11.303" UserId="13095" Comment="added 1 character in body" Text="The problem with your code is, that it produces a lot of degenerated triangles. The not so obvious ones are at the top and bottom. The obvious ones are at the &quot;wrapping line&quot;.&#xD;&#xA;&#xD;&#xA;So what exactly is the problem? Each of your faces is a rectangle that consists of 2 triangles and 4 points. The 2 triangles share 2 points and each one has 1 individual point. But at the bottom/top 2 points are identical, so your rectangle degenerates to a triangle. As a result, one triangle degenerates to a line because of the duplicate points.&#xD;&#xA;&#xD;&#xA;Now, why is this problematic for you? It is this line, that causes the trouble: &#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;vec3 normal = normalize(cross(d1, d2));&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The cross product of a vector with itself is the zero vector. If you normalize a vector, you divide by its length, which is 0 in this case. So this is where your `NaN`s come from. Until now, I just spoke about the top and bottom, but why is it happening at the &quot;wrapping line&quot;? The problem is a result of your index calculation:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;    for(uint i=0; i &lt; u_resolution - 1; i++)&#xD;&#xA;    {&#xD;&#xA;        for(uint j=0; j &lt; v_resolution; j++)&#xD;&#xA;        {&#xD;&#xA;            // Grab the 4 points in a quad face in the sphere&#xD;&#xA;            uint p00 = (i * (v_resolution) + j);&#xD;&#xA;            uint p01 = (i * (v_resolution) + ((j + 1) % v_resolution));&#xD;&#xA;            uint p10 = ((i + 1) * v_resolution + j);&#xD;&#xA;            uint p11 = ((i + 1) * v_resolution + ((j + 1) % v_resolution));&#xD;&#xA;   ...&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The `j` loop is running until `v_resolution`.  So `j+1` gets problematic. I know your intention here is, that you need the triangles from the &quot;other side&quot;, to calculate your normals correctly. That is why you performed the `% v_resolution` to get the corresponding points. But the problem is, you are not getting the points you want. With your code, you are including the last and first point of a &quot;horizontal line&quot;, but they are identical in your case. The result is that you get a face that degenerates to a line, which means, that you will divide by 0 during normalization of both triangles surface normals.&#xD;&#xA;&#xD;&#xA;A quick way to fix the `NaN`s at the &quot;wrapping line&quot; would be to make a temporary variable and store `j+1` in it. Then check if it is equal or higher than `v_resolution`. If `true`, increase it by one. Use this variable everywhere you used `j+1` during the index generation. However, this will still cause an issue at the wrapping line, since your start and end vertices are not the same and you only considered &quot;both sides&quot; for the last vertices of a horizontal line, but not for the first. This will lead to incorrect normals for the start vertices and you should see a jump in the shading. You might fix it, by just copying the normals of the last vertices to the first ones. &#xD;&#xA;&#xD;&#xA;Also, you still need to address the problems at the top and bottom. This can be fixed by making a special loop only for top and bottom triangles. However, these are suboptimal fixes. A better approach would be to write code that does not produce duplicate points since it lowers the risk of creating degenerated triangles and is more memory efficient.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27910" PostHistoryTypeId="2" PostId="9732" RevisionGUID="6b80696a-e644-4381-af21-474eb8f4e025" CreationDate="2020-04-16T16:41:23.730" UserId="11521" Text="While following [this][1] tutorial on indirect diffuse implementation in path tracing, the samples gets divided by the pdf, which in case of a uniform pdf results in $1/2\pi$ so we have that the sum of N samples gets multiplied by this factor:&#xD;&#xA;$$k=\frac{1}{N * \frac{1}{2  \pi}} = \frac{2\pi}{N}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this is that unless the albedo color is very dark, the final color quickly increases:&#xD;&#xA;&#xD;&#xA;(From &quot;Step 7: Add the Contribution of the Indirect Diffuse...&quot; in the link above)&#xD;&#xA;&#xD;&#xA;$$hitColor = (directDiffuse + \frac{2\pi * indirectDiffuse}{N}) * \frac{albedo}{\pi}; $$&#xD;&#xA; &#xD;&#xA;Other implementations instead just average the samples and the $2\pi$ term above is completely absent.&#xD;&#xA;&#xD;&#xA;Which one is correct?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation" ContentLicense="CC BY-SA 4.0" />
  <row Id="27911" PostHistoryTypeId="1" PostId="9732" RevisionGUID="6b80696a-e644-4381-af21-474eb8f4e025" CreationDate="2020-04-16T16:41:23.730" UserId="11521" Text="Pdf division in BRDF sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="27912" PostHistoryTypeId="3" PostId="9732" RevisionGUID="6b80696a-e644-4381-af21-474eb8f4e025" CreationDate="2020-04-16T16:41:23.730" UserId="11521" Text="|lighting|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27913" PostHistoryTypeId="5" PostId="9732" RevisionGUID="317e5822-7e05-478e-ad20-83f2c9140ee2" CreationDate="2020-04-17T04:31:02.817" UserId="11521" Comment="added 1455 characters in body" Text="While following [scratchapixel's][1] tutorial on indirect diffuse implementation in path tracing, the samples gets divided by the pdf, which in case of a uniform pdf results in $1/2\pi$ so we have that the sum of N samples gets multiplied by this factor:&#xD;&#xA;$$k=\frac{1}{N * \frac{1}{2  \pi}} = \frac{2\pi}{N}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this is that unless the albedo color is very dark, the final color quickly increases:&#xD;&#xA;&#xD;&#xA;(From &quot;Step 7: Add the Contribution of the Indirect Diffuse...&quot; in the link above)&#xD;&#xA;&#xD;&#xA;$$hitColor = (directDiffuse + \frac{2\pi * indirectDiffuse}{N}) * \frac{albedo}{\pi}; $$&#xD;&#xA; &#xD;&#xA;Other implementations instead just average the samples and the $2\pi$ term above is completely absent, like in Sherley's &quot;[ray tracing in a weekend][2]&quot; p.20&#xD;&#xA;&#xD;&#xA;Which one is correct?&#xD;&#xA;&#xD;&#xA;There's a difference in Sherley's and scratchapixel implementation, in the fact that Sherley's is a progressive path tracer (evaluates one path at a time)&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;While scratchapixel's is a non-progressive or branched path tracer, evaluating multiple paths at once:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;But I believe this does not allow us to remove the $2\pi$ term in the former, because we are doing the same thing (sampling the BRDF hemisphere) albeit differently.&#xD;&#xA;&#xD;&#xA;When evaluating direct lighting with point lights, the solid angle term is also [completely absent][5], which makes things even more strange:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Here the integral over the hemisphere is 0 except in the direction $\omega i$, but (for example considering only diffuse) we only use:&#xD;&#xA;&#xD;&#xA;$$ L(P) = albedo*L(\omega i, P)*cos\theta$$&#xD;&#xA;&#xD;&#xA;where $L(P)$ is the radiance from the point $P$, and $L(\omega i, P)$ gets replaced with out light radiance, $\theta$ is the angle with from $\omega i$ to the surface normal. Where has the solid angle term ($ \omega i$) gone?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation&#xD;&#xA;  [2]: https://www.realtimerendering.com/raytracing/Ray%20Tracing%20in%20a%20Weekend.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/W9BY4.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/8AlLb.png&#xD;&#xA;  [5]: https://learnopengl.com/PBR/Lighting&#xD;&#xA;  [6]: https://i.stack.imgur.com/5rkhs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27914" PostHistoryTypeId="5" PostId="9732" RevisionGUID="e5959e97-e4dd-4227-8356-0e05c9b0b0f1" CreationDate="2020-04-17T08:13:00.860" UserId="11521" Comment="edited body" Text="While following [scratchapixel's][1] tutorial on indirect diffuse implementation in path tracing, the samples gets divided by the pdf, which in case of a uniform pdf results in $1/2\pi$ so we have that the sum of N samples gets multiplied by this factor:&#xD;&#xA;$$k=\frac{1}{N * \frac{1}{2  \pi}} = \frac{2\pi}{N}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem with this is that unless the albedo color is very dark, the final color quickly increases:&#xD;&#xA;&#xD;&#xA;(From &quot;Step 7: Add the Contribution of the Indirect Diffuse...&quot; in the link above)&#xD;&#xA;&#xD;&#xA;$$hitColor = (directDiffuse + \frac{2\pi * indirectDiffuse}{N}) * \frac{albedo}{\pi}; $$&#xD;&#xA; &#xD;&#xA;Other implementations instead just average the samples and the $2\pi$ term above is completely absent, like in Shirley's &quot;[ray tracing in a weekend][2]&quot; p.20&#xD;&#xA;&#xD;&#xA;Which one is correct?&#xD;&#xA;&#xD;&#xA;There's a difference in Shirley's and scratchapixel implementation, in the fact that Shirley's is a progressive path tracer (evaluates one path at a time)&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;While scratchapixel's is a non-progressive or branched path tracer, evaluating multiple paths at once:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;But I believe this does not allow us to remove the $2\pi$ term in the former, because we are doing the same thing (sampling the BRDF hemisphere) albeit differently.&#xD;&#xA;&#xD;&#xA;When evaluating direct lighting with point lights, the solid angle term is also [completely absent][5], which makes things even more strange:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Here the integral over the hemisphere is 0 except in the direction $\omega i$, but (for example considering only diffuse) we only use:&#xD;&#xA;&#xD;&#xA;$$ L(P) = albedo*L(\omega i, P)*cos\theta$$&#xD;&#xA;&#xD;&#xA;where $L(P)$ is the radiance from the point $P$, and $L(\omega i, P)$ gets replaced with our light radiance, $\theta$ is the angle with from $\omega i$ to the surface normal. Where has the solid angle term ($ \omega i$) gone?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation&#xD;&#xA;  [2]: https://www.realtimerendering.com/raytracing/Ray%20Tracing%20in%20a%20Weekend.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/W9BY4.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/8AlLb.png&#xD;&#xA;  [5]: https://learnopengl.com/PBR/Lighting&#xD;&#xA;  [6]: https://i.stack.imgur.com/5rkhs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27915" PostHistoryTypeId="2" PostId="9733" RevisionGUID="69f32bba-82e1-425c-8171-ba5fbc8dc857" CreationDate="2020-04-17T08:50:05.560" UserId="10928" Text="In the Bresenham circle drawing algorithm, we have to choose between the top and bottom pixel, but what we always do is using the circle's equation ($f(x, y) = x^2 + y^2 = r^2$) to determine which of the two pixels is closer to the circle (r is the radius).&#xD;&#xA;&#xD;&#xA;For the top pixel (N), we thus have $f(N) = x_{k+1}^2 + y_k^2 - r^2$&#xD;&#xA;&#xD;&#xA;And for the bottom pixel (S), we have $f(S) = x_{k+1}^2 + y_{k-1}^2 - r^2$&#xD;&#xA;&#xD;&#xA;Okay, we're using the circle equation to determine which is the closest point to the circle but why not simply using the euclidean distance? What is the point to use f instead of the actual distance? It would be easier to understand (this f function seems to come out of nowhere).&#xD;&#xA;&#xD;&#xA;The actual distance between the top pixel and the circle is $\sqrt{x_{k+1}^2 + y_k^2} - r$ and with the bottom pixel it's $r - \sqrt{x_{k+1}^2 + y_{k-1}^2}$.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3UQIZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27916" PostHistoryTypeId="1" PostId="9733" RevisionGUID="69f32bba-82e1-425c-8171-ba5fbc8dc857" CreationDate="2020-04-17T08:50:05.560" UserId="10928" Text="Bresenham circle drawing algorithm, compute the distance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27917" PostHistoryTypeId="3" PostId="9733" RevisionGUID="69f32bba-82e1-425c-8171-ba5fbc8dc857" CreationDate="2020-04-17T08:50:05.560" UserId="10928" Text="|algorithm|drawing|midpoint|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27918" PostHistoryTypeId="2" PostId="9734" RevisionGUID="6fc939b7-0118-42c7-8766-31853e176e15" CreationDate="2020-04-17T09:04:55.903" UserId="13192" Text="I am trying to program my own version of WEBGL graphics pipeline in python, however, I am confused as to where the color interpolation takes place in the pipeline. According to my research, it happens after the rasterizer has calculated the points covered by the primitive. Does that mean rasterizer has access to color attribute, if so, how is the color attribute passed to the rasterizer, as the inputs for rasterizer are vertices? Or is it happening in the fragment shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27919" PostHistoryTypeId="1" PostId="9734" RevisionGUID="6fc939b7-0118-42c7-8766-31853e176e15" CreationDate="2020-04-17T09:04:55.903" UserId="13192" Text="Interpolation in Graphics Pipeline" ContentLicense="CC BY-SA 4.0" />
  <row Id="27920" PostHistoryTypeId="3" PostId="9734" RevisionGUID="6fc939b7-0118-42c7-8766-31853e176e15" CreationDate="2020-04-17T09:04:55.903" UserId="13192" Text="|interpolation|rasterizer|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27921" PostHistoryTypeId="2" PostId="9735" RevisionGUID="d582d7c5-6984-420f-ad79-77b02dbd5d75" CreationDate="2020-04-17T10:44:38.640" UserId="13095" Text="After a short research, I found [this site][1], which describes the algorithm. I didn't know it before. An important thing you didn't mention in your question is the calculation of the decision parameter $d$, which is:&#xD;&#xA;&#xD;&#xA;$$d=f\left(N\right)+f\left(S\right)$$&#xD;&#xA;&#xD;&#xA;It abuses the fact, that the bottom pixel will always lie on the circle or inside and the right pixel will always be on the circle or outside (for this particular segment). In conclusion, this means that $f\left(S\right) \le 0$ and $f\left(N\right) \ge 0$. So if $d = 0$, both pixels have the same distance to the arc and you can choose which one to take. If $d&lt;0$, the bottom pixel is farther away. So you pick the right one. for $d&gt;0$ its the opposite. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Okay, we're using the circle equation to determine which is the closest point to the circle but why not simply using the euclidean distance?&#xD;&#xA;&#xD;&#xA;Most probably for performance reasons. Using the Euclidean distance requires you to calculate 2 square roots, which is quite expensive when compared to simple multiplication ($r\cdot r$). On a Haswell CPU, you can perform 6 independent multiplications at the same time as calculating a single square root. &#xD;&#xA;&#xD;&#xA;You can avoid using the square roots by comparing the squared Euclidean length. It won't change the comparison. If you do, you will notice, that this already looks quite similar to your $f$ function. Just with some swapped signs for $d_2^2$:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d_1^2 &amp;= x_{k+1}^2 + y_k^2 - r^2\\&#xD;&#xA;d_2^2 &amp;= r^2 - \left(x_{k+1}^2 + y_{k-1}^2\right) &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;If you optimize the Bresenham algorithm you will probably get something like that:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d &amp;=&amp; x_{k+1}^2 + y_k^2 - r^2 +  x_{k+1}^2 + y_{k-1}^2 - r^2\\&#xD;&#xA; &amp;=&amp; 2x_{k+1}^2- 2r^2 + y_k^2   + y_{k-1}^2 \\&#xD;&#xA; &amp;=&amp; 2\left(x_{k+1}^2- r^2\right) + y_k^2   + y_{k-1}^2&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;then compare&#xD;&#xA;&#xD;&#xA;$$d \le 0$$&#xD;&#xA;So in total you end up with 9 multiplications, 2 additions, 1 substraction and 1 comparison. If you optimize the squared Euclidean length approach, you will get something like this:&#xD;&#xA;&#xD;&#xA;$$x_{k+1}^2 + y_k^2 - r^2 \le r^2 - x_{k+1}^2 - y_{k-1}^2$$&#xD;&#xA;&#xD;&#xA;If you precalculate the squares, and the difference $s = x_{k+1}^2-r^2$ store them in a variable and reuse them, you will end up exchanging one multiplication by one negation and one addition by subtraction: &#xD;&#xA;&#xD;&#xA;$$s + y_k^2 \le - s - y_{k-1}^2$$&#xD;&#xA;&#xD;&#xA;You might further see, that you can reformulate it to:&#xD;&#xA;&#xD;&#xA;$$2s + y_k^2 + y_{k-1} \le 0$$&#xD;&#xA;&#xD;&#xA;which is exactly the same as the Bresenham algorithm. You might wonder, if it isn't faster to use $$s + y_k^2 \le - s - y_{k-1}^2$$ since swapping a sign should faster than multiplication. Truth is, that only a benchmark can say for sure and I wouldn't wonder if nowadays smart compilers will produce exactly the same assembly for both versions (if you use a compiled programming language)&#xD;&#xA;&#xD;&#xA;To sum it up: You want to avoid calculating expensive square roots by using the squared distances instead.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.javatpoint.com/computer-graphics-bresenhams-circle-algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="27922" PostHistoryTypeId="2" PostId="9736" RevisionGUID="a1e933aa-4f97-4c56-8400-d7a39c23e636" CreationDate="2020-04-17T11:32:21.197" UserId="13095" Text="The rasterizer determines, which pixel is rendered depending on vertex positions that come out of the vertex shader. For each rasterized pixel, the rasterizer knows where it lies inside the triangle formed by its three positions. With the known position inside the triangle, the rasterizer can also interpolate the vertex values for each pixel. So it also calculates the interpolated color, in case your vertex shader passes a color down the pipeline. The interpolated value is then provided to the fragment shader. However, the fragment shader can still modify the color before it is finally rendered to the screen.&#xD;&#xA;&#xD;&#xA;&gt; Does that mean rasterizer has access to color attribute&#xD;&#xA;&#xD;&#xA;It has full access to everything that comes out of the vertex shader. A vertex shader must always have a position as output (`gl_Position`). In some special cases also other outputs are required. However, if your initial vertices had a color, but the color is not passed down the pipeline by the vertex shader, the rasterizer won't produce an interpolated color. It only interpolates each variable/attribute, that comes out of the vertex shader.&#xD;&#xA;&#xD;&#xA;&gt; how is the color attribute passed to the rasterizer, as the inputs for rasterizer are vertices?&#xD;&#xA;&#xD;&#xA;You can define arbitrary outputs in your vertex shader. Even if the initially submitted vertex, did not have a color attribute, you can add a color output in the vertex shader. The data the rasterizer gets per vertex is just the vertex shader outputs. A vertex is a data point containing a position and optional additional values/attributes. So if a vertex has a color attribute, the rasterizer can see it, since it is part of the vertex. &#xD;&#xA;&#xD;&#xA;Note that the vertices you pass into the vertex shader and the vertices that come out of it are not the same and might differ.&#xD;&#xA;&#xD;&#xA;&gt; Or is it happening in the fragment shader?&#xD;&#xA;&#xD;&#xA;No, the fragment shader receives already interpolated values as input. But it can decide to pass it directly, ignore it or modify it as you wish. If you just pass it through, you will see the interpolated vertex colors. &#xD;&#xA;&#xD;&#xA;Further information can be found [on this site][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview" ContentLicense="CC BY-SA 4.0" />
  <row Id="27923" PostHistoryTypeId="5" PostId="9735" RevisionGUID="c40ce778-0e7e-457c-adba-97e36162c93f" CreationDate="2020-04-17T12:09:27.770" UserId="13095" Comment="correct a typical mistake of mine -.-" Text="After a short research, I found [this site][1], which describes the algorithm. I didn't know it before. An important thing you didn't mention in your question is the calculation of the decision parameter $d$, which is:&#xD;&#xA;&#xD;&#xA;$$d=f\left(N\right)+f\left(S\right)$$&#xD;&#xA;&#xD;&#xA;It abuses the fact, that the bottom pixel will always lie on the circle or inside and the right pixel will always be on the circle or outside (for this particular segment). In conclusion, this means that $f\left(S\right) \le 0$ and $f\left(N\right) \ge 0$. So if $d = 0$, both pixels have the same distance to the arc and you can choose which one to take. If $d&lt;0$, the bottom pixel is farther away. So you pick the right one. for $d&gt;0$ its the opposite. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Okay, we're using the circle equation to determine which is the closest point to the circle but why not simply using the euclidean distance?&#xD;&#xA;&#xD;&#xA;Most probably for performance reasons. Using the Euclidean distance requires you to calculate 2 square roots, which is quite expensive when compared to simple multiplication ($r\cdot r$). On a Haswell CPU, it takes 3 times longer to get the result of a square root compared to multiplication and you can perform 2 multiplications in parallel. &#xD;&#xA;&#xD;&#xA;You can avoid using the square roots by comparing the squared Euclidean length. It won't change the comparison. If you do, you will notice, that this already looks quite similar to your $f$ function. Just with some swapped signs for $d_2^2$:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d_1^2 &amp;= x_{k+1}^2 + y_k^2 - r^2\\&#xD;&#xA;d_2^2 &amp;= r^2 - \left(x_{k+1}^2 + y_{k-1}^2\right) &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;If you optimize the Bresenham algorithm you will probably get something like that:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d &amp;=&amp; x_{k+1}^2 + y_k^2 - r^2 +  x_{k+1}^2 + y_{k-1}^2 - r^2\\&#xD;&#xA; &amp;=&amp; 2x_{k+1}^2- 2r^2 + y_k^2   + y_{k-1}^2 \\&#xD;&#xA; &amp;=&amp; 2\left(x_{k+1}^2- r^2\right) + y_k^2   + y_{k-1}^2&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;then compare&#xD;&#xA;&#xD;&#xA;$$d \le 0$$&#xD;&#xA;So in total you end up with 9 multiplications, 2 additions, 1 substraction and 1 comparison. If you optimize the squared Euclidean length approach, you will get something like this:&#xD;&#xA;&#xD;&#xA;$$x_{k+1}^2 + y_k^2 - r^2 \le r^2 - x_{k+1}^2 - y_{k-1}^2$$&#xD;&#xA;&#xD;&#xA;If you precalculate the squares, and the difference $s = x_{k+1}^2-r^2$ store them in a variable and reuse them, you will end up exchanging one multiplication by one negation and one addition by subtraction: &#xD;&#xA;&#xD;&#xA;$$s + y_k^2 \le - s - y_{k-1}^2$$&#xD;&#xA;&#xD;&#xA;You might further see, that you can reformulate it to:&#xD;&#xA;&#xD;&#xA;$$2s + y_k^2 + y_{k-1} \le 0$$&#xD;&#xA;&#xD;&#xA;which is exactly the same as the Bresenham algorithm. You might wonder, if it isn't faster to use $$s + y_k^2 \le - s - y_{k-1}^2$$ since swapping a sign should faster than multiplication. Truth is, that only a benchmark can say for sure and I wouldn't wonder if nowadays smart compilers will produce exactly the same assembly for both versions (if you use a compiled programming language)&#xD;&#xA;&#xD;&#xA;To sum it up: You want to avoid calculating expensive square roots by using the squared distances instead.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.javatpoint.com/computer-graphics-bresenhams-circle-algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="27924" PostHistoryTypeId="8" PostId="9735" RevisionGUID="6d104b55-e471-40a0-93d1-d09e2a3eedff" CreationDate="2020-04-17T12:14:00.993" UserId="13095" Comment="Rollback to [d582d7c5-6984-420f-ad79-77b02dbd5d75]" Text="After a short research, I found [this site][1], which describes the algorithm. I didn't know it before. An important thing you didn't mention in your question is the calculation of the decision parameter $d$, which is:&#xD;&#xA;&#xD;&#xA;$$d=f\left(N\right)+f\left(S\right)$$&#xD;&#xA;&#xD;&#xA;It abuses the fact, that the bottom pixel will always lie on the circle or inside and the right pixel will always be on the circle or outside (for this particular segment). In conclusion, this means that $f\left(S\right) \le 0$ and $f\left(N\right) \ge 0$. So if $d = 0$, both pixels have the same distance to the arc and you can choose which one to take. If $d&lt;0$, the bottom pixel is farther away. So you pick the right one. for $d&gt;0$ its the opposite. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Okay, we're using the circle equation to determine which is the closest point to the circle but why not simply using the euclidean distance?&#xD;&#xA;&#xD;&#xA;Most probably for performance reasons. Using the Euclidean distance requires you to calculate 2 square roots, which is quite expensive when compared to simple multiplication ($r\cdot r$). On a Haswell CPU, you can perform 6 independent multiplications at the same time as calculating a single square root. &#xD;&#xA;&#xD;&#xA;You can avoid using the square roots by comparing the squared Euclidean length. It won't change the comparison. If you do, you will notice, that this already looks quite similar to your $f$ function. Just with some swapped signs for $d_2^2$:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d_1^2 &amp;= x_{k+1}^2 + y_k^2 - r^2\\&#xD;&#xA;d_2^2 &amp;= r^2 - \left(x_{k+1}^2 + y_{k-1}^2\right) &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;If you optimize the Bresenham algorithm you will probably get something like that:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d &amp;=&amp; x_{k+1}^2 + y_k^2 - r^2 +  x_{k+1}^2 + y_{k-1}^2 - r^2\\&#xD;&#xA; &amp;=&amp; 2x_{k+1}^2- 2r^2 + y_k^2   + y_{k-1}^2 \\&#xD;&#xA; &amp;=&amp; 2\left(x_{k+1}^2- r^2\right) + y_k^2   + y_{k-1}^2&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;then compare&#xD;&#xA;&#xD;&#xA;$$d \le 0$$&#xD;&#xA;So in total you end up with 9 multiplications, 2 additions, 1 substraction and 1 comparison. If you optimize the squared Euclidean length approach, you will get something like this:&#xD;&#xA;&#xD;&#xA;$$x_{k+1}^2 + y_k^2 - r^2 \le r^2 - x_{k+1}^2 - y_{k-1}^2$$&#xD;&#xA;&#xD;&#xA;If you precalculate the squares, and the difference $s = x_{k+1}^2-r^2$ store them in a variable and reuse them, you will end up exchanging one multiplication by one negation and one addition by subtraction: &#xD;&#xA;&#xD;&#xA;$$s + y_k^2 \le - s - y_{k-1}^2$$&#xD;&#xA;&#xD;&#xA;You might further see, that you can reformulate it to:&#xD;&#xA;&#xD;&#xA;$$2s + y_k^2 + y_{k-1} \le 0$$&#xD;&#xA;&#xD;&#xA;which is exactly the same as the Bresenham algorithm. You might wonder, if it isn't faster to use $$s + y_k^2 \le - s - y_{k-1}^2$$ since swapping a sign should faster than multiplication. Truth is, that only a benchmark can say for sure and I wouldn't wonder if nowadays smart compilers will produce exactly the same assembly for both versions (if you use a compiled programming language)&#xD;&#xA;&#xD;&#xA;To sum it up: You want to avoid calculating expensive square roots by using the squared distances instead.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.javatpoint.com/computer-graphics-bresenhams-circle-algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="27928" PostHistoryTypeId="2" PostId="9738" RevisionGUID="4e03fc71-3214-4733-a8f4-970dcda63c32" CreationDate="2020-04-17T16:29:16.187" UserId="6407" Text="I had a hard time to understand this.&#xD;&#xA;&#xD;&#xA;I thought `*Spectrum` classes (`SampledSpectrum`, specifically) store power (SI unit: W) in them and when I want RGB colors from them, I have to use some complicated method to convert power to XYZ then to RGB.&#xD;&#xA;&#xD;&#xA;I thought `RGBspectrum` is just a three-sample `SampledSpectrum`, but it seems not ... If it stores power (W), how could its `ToRGB` method directly return its power?&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;void ToRGB(Float *rgb) const {&#xD;&#xA;    rgb[0] = c[0];&#xD;&#xA;    rgb[1] = c[1];&#xD;&#xA;    rgb[2] = c[2];&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Does `RGBSpectrum` directly store color values in it? If that so, how could we use color to calculate radiance instead of power?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27929" PostHistoryTypeId="1" PostId="9738" RevisionGUID="4e03fc71-3214-4733-a8f4-970dcda63c32" CreationDate="2020-04-17T16:29:16.187" UserId="6407" Text="Does the RGBSpectrum class in pbrt store RGB color values directly, not power?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27930" PostHistoryTypeId="3" PostId="9738" RevisionGUID="4e03fc71-3214-4733-a8f4-970dcda63c32" CreationDate="2020-04-17T16:29:16.187" UserId="6407" Text="|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27931" PostHistoryTypeId="5" PostId="9735" RevisionGUID="10e6c51b-e57d-4fdd-8252-70fe40604d16" CreationDate="2020-04-17T19:37:50.023" UserId="13095" Comment="deleted 1046 characters in body" Text="After a short research, I found [this site][1], which describes the algorithm. I didn't know it before. An important thing you didn't mention in your question is the calculation of the decision parameter $d$, which is:&#xD;&#xA;&#xD;&#xA;$$d=f\left(N\right)+f\left(S\right)$$&#xD;&#xA;&#xD;&#xA;It abuses the fact, that the bottom pixel will always lie on the circle or inside and the right pixel will always be on the circle or outside (for this particular segment). In conclusion, this means that $f\left(S\right) \le 0$ and $f\left(N\right) \ge 0$. If $d&lt;=0$ you pick the right one and the left one otherwise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Okay, we're using the circle equation to determine which is the closest point to the circle but why not simply using the euclidean distance?&#xD;&#xA;&#xD;&#xA;Most probably for performance reasons. Using the Euclidean distance requires you to calculate 2 square roots, which is quite expensive when compared to simple multiplication ($r\cdot r$). On a Haswell CPU, you can perform 6 independent multiplications at the same time as calculating a single square root. &#xD;&#xA;&#xD;&#xA;If you optimize the Bresenham algorithm you will probably get something like that:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d &amp;=&amp; x_{k+1}^2 + y_k^2 - r^2 +  x_{k+1}^2 + y_{k-1}^2 - r^2\\&#xD;&#xA; &amp;=&amp; 2x_{k+1}^2- 2r^2 + y_k^2   + y_{k-1}^2 \\&#xD;&#xA; &amp;=&amp; 2\left(x_{k+1}^2- r^2\right) + y_k^2   + y_{k-1}^2&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;then compare&#xD;&#xA;&#xD;&#xA;$$d \le 0$$&#xD;&#xA;So in total, you end up with 9 multiplications, 2 additions, 1 subtraction and 1 comparison. &#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;As mentioned in the comments to this answer, the Euclidean length and the Bresenham algorithm won't give you the same results. While the Euclidean length will always give you the Pixel with the closest distance of its center to the arc, the Bresenham algorithm will favor points inside the circle, even though they are a little bit farther away. However, this error gets smaller the closer you get to the circle and shouldn't be noticeable.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.javatpoint.com/computer-graphics-bresenhams-circle-algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="27936" PostHistoryTypeId="2" PostId="9740" RevisionGUID="92cc46f2-6aed-49e2-a5a2-1236a5a2bec7" CreationDate="2020-04-17T23:24:51.620" UserId="13201" Text="I’m fairly new to shader programs in general but I have a question concerning vector graphics. I understand that a pixel shader can generate the color information to draw some sort of geometry on screen. But let’s say you had a shader that created a silhouette (outline) around some geometry. Is it possible for a shader program to generate vector graphics (ie. Curves) that follow that exact silhouette (instead of pixel data)? I’ve tried to do some preliminary internet searches but can’t find anything that would answer this type of question. Are shader programs fundamentally different and as such could not generate lines, curves, etc. as a form of output?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27937" PostHistoryTypeId="1" PostId="9740" RevisionGUID="92cc46f2-6aed-49e2-a5a2-1236a5a2bec7" CreationDate="2020-04-17T23:24:51.620" UserId="13201" Text="Vector graphics output from shader program" ContentLicense="CC BY-SA 4.0" />
  <row Id="27938" PostHistoryTypeId="3" PostId="9740" RevisionGUID="92cc46f2-6aed-49e2-a5a2-1236a5a2bec7" CreationDate="2020-04-17T23:24:51.620" UserId="13201" Text="|opengl|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27939" PostHistoryTypeId="5" PostId="9740" RevisionGUID="6dbc9698-04b4-4fbd-acc5-2e159f38d7dc" CreationDate="2020-04-17T23:31:09.607" UserId="13201" Comment="added 275 characters in body" Text="I’m fairly new to shader programs in general but I have a question concerning vector graphics. I understand that a pixel shader can generate the color information to draw some sort of geometry on screen. But let’s say you had a shader that created a silhouette (outline) around some geometry. Is it possible for a shader program to generate vector graphics (ie. Curves) that follow that exact silhouette (instead of pixel data)? &#xD;&#xA;&#xD;&#xA;Or in a different example, [this image](https://i.stack.imgur.com/YvwZq.jpg) was created by using a pixel shader. Would it be possible for a shader to generate the lines on a teapot as actual curve geometry rather than just a bitmap that is mapped to the 3D geometry?&#xD;&#xA;&#xD;&#xA;I’ve tried to do some preliminary internet searches but can’t find anything that would answer this type of question. Are shader programs fundamentally different and as such could not generate lines, curves, etc. as a form of output?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27944" PostHistoryTypeId="2" PostId="9741" RevisionGUID="44839124-029a-4cc8-a711-5849a6ec60a2" CreationDate="2020-04-18T11:17:27.273" UserId="13095" Text="In OpenGL, there are 6 different shader types:&#xD;&#xA;&#xD;&#xA;1. Vertex Shader&#xD;&#xA;2. Tesselation Control Shader&#xD;&#xA;3. Tesselation Evaluation Shader&#xD;&#xA;4. Geometry Shader&#xD;&#xA;5. Fragment Shader (Pixel)&#xD;&#xA;6. Compute Shader&#xD;&#xA;&#xD;&#xA;The first 5 are part of the render pipeline and fulfill a very specific purpose in that pipeline. They are executed in ascending order. The shader types 2.-4. are optional and can be skipped. Between those stages, some operations are performed, that are very specific to rendering. Have a look at [this link][1] for further information. &#xD;&#xA;&#xD;&#xA;The problem here is: Since the rendering pipeline has a very specific purpose (generating an image of pixels), it is very hard to use it and its shaders for something else than rendering. Won't say it is impossible, but it gets certainly harder and harder the less your goal has something to do with pixel generation.&#xD;&#xA;&#xD;&#xA;For general-purpose computations, you can use compute shaders. You can basically compute anything there, so this is probably the shader type you are looking for. However, the way you ask your questions gives me the feeling, that you have some misunderstandings on how rendering works in general and you should probably read some literature about how the render pipeline creates an image from 3d data.&#xD;&#xA;&#xD;&#xA;&gt; But let’s say you had a shader that created a silhouette (outline) around some geometry. Is it possible for a shader program to generate vector graphics (ie. Curves) that follow that exact silhouette (instead of pixel data)? &#xD;&#xA;&#xD;&#xA;As written above, generally yes. It is possible to write a shader that does that. But probably not with the same technique as the outline is created in the &quot;pixel case&quot;. It is certainly much more complicated.&#xD;&#xA;&#xD;&#xA;&gt; Or in a different example, this image was created by using a pixel shader. Would it be possible for a shader to generate the lines on a teapot as actual curve geometry rather than just a bitmap that is mapped to the 3D geometry?&#xD;&#xA;&#xD;&#xA;Again, yes it is possible for **a** shader to fulfill this task, but you wouldn't use a pixel (fragment) shader for that. You would also need to approach the whole task very differently.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Are shader programs fundamentally different and as such could not generate lines, curves, etc. as a form of output?&#xD;&#xA;&#xD;&#xA;The shaders of the rendering pipeline are tied to a very specific task and have very specific boundaries on their inputs and outputs. But if you know what you are doing, you can probably hack around those limitations. However, I think it wouldn't make much sense to do so, except you want to prove that you can. &#xD;&#xA;Instead, you can use a compute shader for any computation, that has nothing to do with rendering.&#xD;&#xA;&#xD;&#xA;**To sum it up**&#xD;&#xA;&#xD;&#xA;You can use compute shaders to get other output types than just pixels and images made of pixels. However, calculating basic 2d shapes/curves/vector graphics from 3d data will most likly be fundamentally different than generating a corresponding bunch of pixels from that same data. In conclusion, you can't just turn a switch (change 2-3 lines of code) to select which output you like to have.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview" ContentLicense="CC BY-SA 4.0" />
  <row Id="27945" PostHistoryTypeId="2" PostId="9742" RevisionGUID="a42a1b44-ac93-4806-812e-c1b2168be358" CreationDate="2020-04-18T12:55:56.383" UserId="13204" Text="I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's [here](https://github.com/NAThompson/graphics), if relevant.)&#xD;&#xA;&#xD;&#xA;Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.&#xD;&#xA;&#xD;&#xA;When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.&#xD;&#xA;&#xD;&#xA;What can I do to get these graphs uniformly thick?&#xD;&#xA;&#xD;&#xA;If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Uws93.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27946" PostHistoryTypeId="1" PostId="9742" RevisionGUID="a42a1b44-ac93-4806-812e-c1b2168be358" CreationDate="2020-04-18T12:55:56.383" UserId="13204" Text="Uniform line thickness in plot" ContentLicense="CC BY-SA 4.0" />
  <row Id="27947" PostHistoryTypeId="3" PostId="9742" RevisionGUID="a42a1b44-ac93-4806-812e-c1b2168be358" CreationDate="2020-04-18T12:55:56.383" UserId="13204" Text="|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27948" PostHistoryTypeId="5" PostId="9742" RevisionGUID="8d5f02ca-8cad-4b2e-85fe-cc8b9c3d21d2" CreationDate="2020-04-18T13:03:48.523" UserId="13204" Comment="added 457 characters in body" Text="I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's [here](https://github.com/NAThompson/graphics), if relevant.)&#xD;&#xA;&#xD;&#xA;Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.&#xD;&#xA;&#xD;&#xA;When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.&#xD;&#xA;&#xD;&#xA;What can I do to get these graphs uniformly thick?&#xD;&#xA;&#xD;&#xA;If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?&#xD;&#xA;&#xD;&#xA;*Note*: I tried setting the line thickness at point $x$ to&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\max(1, |f'(x)|)&#xD;&#xA;$$&#xD;&#xA;where $ t_{\mathrm{user}}$ is the user requested thickness.&#xD;&#xA;But of course $|f'|$ can diverge, so this did horrible things to the graph. So I did:&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)&#xD;&#xA;$$&#xD;&#xA;which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Uws93.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27949" PostHistoryTypeId="5" PostId="9742" RevisionGUID="fab8071e-880f-4904-a968-aa0ec1f4138a" CreationDate="2020-04-18T14:17:09.347" UserId="13204" Comment="added 153 characters in body" Text="I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's [here](https://github.com/NAThompson/graphics), if relevant.)&#xD;&#xA;&#xD;&#xA;Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.&#xD;&#xA;&#xD;&#xA;When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.&#xD;&#xA;&#xD;&#xA;What can I do to get these graphs uniformly thick?&#xD;&#xA;&#xD;&#xA;If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?&#xD;&#xA;&#xD;&#xA;*Note*: I tried setting the line thickness at point $x$ to&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\max(1, |f'(x)|)&#xD;&#xA;$$&#xD;&#xA;where $ t_{\mathrm{user}}$ is the user requested thickness.&#xD;&#xA;But of course $|f'|$ can diverge, so this did horrible things to the graph. So I did:&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)&#xD;&#xA;$$&#xD;&#xA;which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.&#xD;&#xA;&#xD;&#xA;*Edit*: I'm now thinking that the width should be marked along the normal to the tangent, not along a vertical. So automatic differentiation is required?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Uws93.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27950" PostHistoryTypeId="5" PostId="9735" RevisionGUID="9e3c1d60-2071-4381-9d91-1f8e4560b621" CreationDate="2020-04-18T14:21:11.480" UserId="13095" Comment="added 3970 characters in body" Text="After a short research, I found [this site][1], which describes the algorithm. I didn't know it before. An important thing you didn't mention in your question is the calculation of the decision parameter $d$, which is:&#xD;&#xA;&#xD;&#xA;$$d=f\left(N\right)+f\left(S\right)$$&#xD;&#xA;&#xD;&#xA;It abuses the fact, that the bottom pixel will always lie on the circle or inside and the right pixel will always be on the circle or outside (for this particular segment). In conclusion, this means that $f\left(S\right) \le 0$ and $f\left(N\right) \ge 0$. If $d&lt;=0$ you pick the right one and the left one otherwise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; Okay, we're using the circle equation to determine which is the closest point to the circle but why not simply using the euclidean distance?&#xD;&#xA;&#xD;&#xA;Most probably for performance reasons. Using the Euclidean distance requires you to calculate 2 square roots, which is quite expensive when compared to simple multiplication ($r\cdot r$). On a Haswell CPU, you can perform 6 independent multiplications at the same time as calculating a single square root. &#xD;&#xA;&#xD;&#xA;If you optimize the Bresenham algorithm you will probably get something like that:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;d &amp;=&amp; x_{k+1}^2 + y_k^2 - r^2 +  x_{k+1}^2 + y_{k-1}^2 - r^2\\&#xD;&#xA; &amp;=&amp; 2x_{k+1}^2- 2r^2 + y_k^2   + y_{k-1}^2 \\&#xD;&#xA; &amp;=&amp; 2\left(x_{k+1}^2- r^2\right) + y_k^2   + y_{k-1}^2&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;then compare&#xD;&#xA;&#xD;&#xA;$$d \le 0$$&#xD;&#xA;So in total, you end up with 9 multiplications, 2 additions, 1 subtraction and 1 comparison. &#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;As mentioned in the comments to this answer, the Euclidean length and the Bresenham algorithm won't give you the same results. While the Euclidean length will always give you the Pixel with the closest distance of its center to the arc, the Bresenham algorithm will favor points inside the circle, even though they are a little bit farther away. However, this error gets smaller the closer you get to the circle and shouldn't be noticeable.  &#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;**Update**&#xD;&#xA;&#xD;&#xA;After rereading some tutorials like the one above or [this one][2], I am not totally sure if they are really stating that they take the closest point. The tutorial I linked says:&#xD;&#xA;&#xD;&#xA;&gt;  So if $Dk &lt; 0$ that means the negative $F(S)$ is bigger then the positive $F(N)$, that implies Point $N$ is closer to the circle than point $S$.&#xD;&#xA;&#xD;&#xA;Language details are not my strong suit, but I think &quot;implies&quot; is meant more in the way of &quot;indicating&quot; something. In this case, it does not mean it is the exact result.&#xD;&#xA;&#xD;&#xA;Anyways, after some elongated calculations, you are right, that $d=f\left(N\right)+f\left(S\right)$ will give wrong results in favor of the inner point if both distances to the circle are quite close. I did some error estimation.&#xD;&#xA;With:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;a &amp;=&amp; \sqrt{x_{k+1}^2 + y_k^2} \\&#xD;&#xA;b &amp;=&amp; \sqrt{x_{k+1}^2 + y_{k-1}^2} \\&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;being the distances to the points from the center, you can calculate the error $\epsilon$ as follows:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;a^2 - r^2 + b^2 - r^2 + \epsilon &amp;=&amp; ((a-r) - (r-b))^2\\&#xD;&#xA;&amp;=&amp; (2r -a - b)^2&#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;If you solve that for $\epsilon$ you will get:&#xD;&#xA;&#xD;&#xA;$$\epsilon = 6r + 2ab - 4ra - 4 rb$$&#xD;&#xA;&#xD;&#xA;You can get 2 interesting pieces of information from that. First, as you already claimed, the Bresenham algorithm does not take the exact distance to the circle when deciding which point is the next one, otherwise $\epsilon$ must have been 0. However, the second information is: If $a$ and $b$ are both on the circle, the error vanishes.&#xD;&#xA;&#xD;&#xA;I was wondering how much closer $a$ must be than $b$ until it is selected. So I did the following:&#xD;&#xA;&#xD;&#xA;$$\begin{matrix}&#xD;&#xA;a &amp;=&amp; r+\delta + \tau\\&#xD;&#xA;b &amp;=&amp; r-\delta &#xD;&#xA;\end{matrix}$$&#xD;&#xA;&#xD;&#xA;The reasoning here is as follows: If $\tau = 0$, then both points have the same distance $\delta$ to the circle. So the right-hand side of&#xD;&#xA;&#xD;&#xA;$$\begin{matrix} a^2 - r^2 + b^2 - r^2 + \epsilon &amp;=&amp; (2r -a - b)^2 \end{matrix}$$&#xD;&#xA;&#xD;&#xA;, the Euclidean distance, will be 0. Now I want to find an offset $\tau$, which causes the left-hand side to be 0, which is the condition where the Bresenham algorithm &quot;assumes&quot; both points to be equally distant to the circle. So if you say  $$a^2 - r^2 + b^2 - r^2 = 0$$, replace the $a$ and $b$ with the shown formulas and solve for $\tau$ you get:&#xD;&#xA;&#xD;&#xA;$$\tau =   \sqrt{r^2 + 2\delta - \delta^2}- (r + \delta)$$&#xD;&#xA;&#xD;&#xA;You can rewrite this a little bit so that it looks like this&#xD;&#xA;&#xD;&#xA;$$\tau =   \sqrt{(r + \delta)^2 - 2\delta^2}- \sqrt{(r + \delta)^2}$$&#xD;&#xA;&#xD;&#xA;From this, you can see again that both approaches give the same result in the special case that both points lie on the circle since $\tau$ gets 0. Putting in some real numbers will also show, that $\tau$ does not get too big. I am no mathematician, but I think you can show, that the &quot;error&quot; and $\tau$ get relatively small with a growing ratio of $r:\delta$. So if you are not drawing circles with a radius of just 2-3 pixels, the differences in the visual output should be negligible. &#xD;&#xA;&#xD;&#xA;Apart from that, taking the Euclidean distance might also not be the best way in the first place. &#xD;&#xA;In the end, a rasterized circle is just an approximation and not a true circle. So there is no &quot;correct&quot; rasterization method for that. With enough distance, you won't notice that it contains of pixels. But in this case, you won't also notice anymore which pixels center is closer to the &quot;true circle&quot;. &#xD;&#xA;&#xD;&#xA;**Conclusion**&#xD;&#xA;&#xD;&#xA;The Euclidean distance and Bresenham algorithm result in slightly different rasterizations (probably not noticeable most of the times).&#xD;&#xA;The Euclidean distance is much more expensive to calculate due to the square roots. Additionally, as one can read in the linked sources, the Bresenham algorithm can be optimized even further than written in this answer, which makes it really fast. If I got it right, one just needs 1-2 multiplications and 2-3 additions/subtractions per pixel.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.javatpoint.com/computer-graphics-bresenhams-circle-algorithm&#xD;&#xA;  [2]: https://www.getsetcg.com/2018/10/bresenhams-circle-drawing-derivation.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="27951" PostHistoryTypeId="2" PostId="9743" RevisionGUID="ea729fc6-2b4c-4884-93aa-eacc88b613fe" CreationDate="2020-04-18T14:23:45.060" UserId="13159" Text="You should separate your line drawing logic from your calculation logic.  &#xD;&#xA;In general you should try to have a generic line drawing function that would accept any number of points and draw a line from one point to the next.  &#xD;&#xA;The simplest implementation for this would be to have dense points and draw a circle at each point.&#xD;&#xA;&#xD;&#xA;If you however absolutely have to calculate the color of a pixel as a function of the X coordinate you'll have to calculate the value multiple times.  &#xD;&#xA;Lets say you want thickness of 3 pixels, you will have to calculate this for [X-1, X, X+1] and then check if the current pixel is close to any of the values.  &#xD;&#xA;A big downside to this is that you have many duplicate calculations." ContentLicense="CC BY-SA 4.0" />
  <row Id="27952" PostHistoryTypeId="2" PostId="9744" RevisionGUID="2f607526-5ac2-4702-833f-4c507ba30c21" CreationDate="2020-04-18T16:44:20.233" UserId="13159" Text="I feel like my light conservation math isn't correct, but I am not sure which part is wrong.&#xD;&#xA;&#xD;&#xA;Is reflected light supposed to influence the diffuse light?&#xD;&#xA;&#xD;&#xA;Does metalness only affect the reflected light or does it also affect ambient and diffuse light?&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;vec4 falbedo;&#xD;&#xA;vec3 fnormal;&#xD;&#xA;&#xD;&#xA;vec3 ambientLight;&#xD;&#xA;&#xD;&#xA;vec3 directionToCamera;&#xD;&#xA;vec3 directionToLight;&#xD;&#xA;vec3 lightColor;&#xD;&#xA;&#xD;&#xA;float metalness; // 0-1&#xD;&#xA;float shininess; // 1-256&#xD;&#xA;float subsurface; // 0-1&#xD;&#xA;&#xD;&#xA;// Diffuse light&#xD;&#xA;float lightNormalDot = dot(fnormal, directionToLight);&#xD;&#xA;float lightIntensity = max(.0, lightNormalDot);&#xD;&#xA;&#xD;&#xA;// Blinn–Phong reflection&#xD;&#xA;vec3 halfway = normalize(directionToCamera + directionToLight);&#xD;&#xA;float reflectionFactor = max(.0, dot(halfway, fnormal));&#xD;&#xA;&#xD;&#xA;float reflection = pow(reflectionFactor, shininess);&#xD;&#xA;&#xD;&#xA;vec3 res = falbedo.rgb * ambientLight;&#xD;&#xA;res += subsurface * lightIntensity * lightColor * falbedo.rgb;&#xD;&#xA;res += (1. - subsurface) * reflection * mix(lightColor, lightColor * falbedo.rgb, metalness);&#xD;&#xA;&#xD;&#xA;gl_FragColor = vec4(res, falbedo.a);&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27953" PostHistoryTypeId="1" PostId="9744" RevisionGUID="2f607526-5ac2-4702-833f-4c507ba30c21" CreationDate="2020-04-18T16:44:20.233" UserId="13159" Text="What is wrong with my metalic PBR shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27954" PostHistoryTypeId="3" PostId="9744" RevisionGUID="2f607526-5ac2-4702-833f-4c507ba30c21" CreationDate="2020-04-18T16:44:20.233" UserId="13159" Text="|glsl|webgl|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27955" PostHistoryTypeId="5" PostId="9742" RevisionGUID="63a4005f-7464-4e82-bcc0-721ef823abf7" CreationDate="2020-04-18T17:27:29.130" UserId="13204" Comment="added 65 characters in body" Text="I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's [here](https://github.com/NAThompson/graphics), if relevant.)&#xD;&#xA;&#xD;&#xA;Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.&#xD;&#xA;&#xD;&#xA;When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.&#xD;&#xA;&#xD;&#xA;What can I do to get these graphs uniformly thick?&#xD;&#xA;&#xD;&#xA;If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?&#xD;&#xA;&#xD;&#xA;*Note*: I tried setting the line thickness at point $x$ to&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\max(1, |f'(x)|)&#xD;&#xA;$$&#xD;&#xA;where $ t_{\mathrm{user}}$ is the user requested thickness.&#xD;&#xA;But of course $|f'|$ can diverge, so this did horrible things to the graph. So I did:&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)&#xD;&#xA;$$&#xD;&#xA;which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.&#xD;&#xA;&#xD;&#xA;*Edit*: I'm now thinking that the width should be marked along the normal to the tangent, i.e. the line&#xD;&#xA;$$&#xD;&#xA;y - f(x_i) = -\frac{1}{f'(x_i)} (x-x_i),&#xD;&#xA;$$&#xD;&#xA;not along a vertical. So automatic differentiation is required?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Uws93.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27959" PostHistoryTypeId="5" PostId="9726" RevisionGUID="abf477c8-d270-4a8a-b109-29f369993a1d" CreationDate="2020-04-19T03:35:57.867" UserId="7462" Comment="added 1 character in body" Text="I seem to have an off by one error when creating the indices for the faces of a sphere and I can't understand where.&#xD;&#xA;&#xD;&#xA;The exact problem is that when I try to calculate the normals of each face a dark region of nans appears in the region where the vertices wrap around.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I generate the vertices and face information like this:&#xD;&#xA;&#xD;&#xA;    pair&lt;vector&lt;vec3&gt;, vector&lt;uint&gt;&gt; GenerateSphere(&#xD;&#xA;        float radius,&#xD;&#xA;        uint u_resolution,&#xD;&#xA;        uint v_resolution)&#xD;&#xA;    {&#xD;&#xA;        vector&lt;vec3&gt; points;&#xD;&#xA;        vector&lt;uint&gt; indices;&#xD;&#xA;        for(uint i=0; i&lt; u_resolution; i++)&#xD;&#xA;        {&#xD;&#xA;            float u = (float(i) / float(u_resolution - 1)) * M_PI - M_PI / 2.f;&#xD;&#xA;            for(uint j=0; j &lt; v_resolution; j++)&#xD;&#xA;            {&#xD;&#xA;                float v = float(j) * 2.f * M_PI / float(v_resolution - 1);&#xD;&#xA;    &#xD;&#xA;                points.push_back(vec3(cos(u) * cos(v), cos(u) * sin(v), sin(u)) * radius);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for(uint i=0; i &lt; u_resolution - 1; i++)&#xD;&#xA;        {&#xD;&#xA;            for(uint j=0; j &lt; v_resolution; j++)&#xD;&#xA;            {&#xD;&#xA;                // Grab the 4 points in a quad face in the sphere&#xD;&#xA;                uint p00 = (i * (v_resolution) + j);&#xD;&#xA;                uint p01 = (i * (v_resolution) + ((j + 1) % v_resolution));&#xD;&#xA;                uint p10 = ((i + 1) * v_resolution + j);&#xD;&#xA;                uint p11 = ((i + 1) * v_resolution + ((j + 1) % v_resolution));&#xD;&#xA;    &#xD;&#xA;                assert((i + 1) &lt; u_resolution);&#xD;&#xA;                assert(p00 &lt; points.size());&#xD;&#xA;                assert(p01 &lt; points.size());&#xD;&#xA;                assert(p10 &lt; points.size());&#xD;&#xA;                assert(p11 &lt; points.size());&#xD;&#xA;                assert(&#xD;&#xA;                    p00 != p01 &amp;&amp; p00 != p11 &amp;&amp; p00 != p10 &amp;&amp;&#xD;&#xA;                    p01 != p10 &amp;&amp; p01 != p11 &amp;&amp;&#xD;&#xA;                    p10 != p11&#xD;&#xA;                );&#xD;&#xA;    &#xD;&#xA;                // Add the first triangle&#xD;&#xA;                indices.push_back(p00);&#xD;&#xA;                indices.push_back(p01);&#xD;&#xA;                indices.push_back(p11);&#xD;&#xA;    &#xD;&#xA;                // Add the second triangle&#xD;&#xA;                indices.push_back(p00);&#xD;&#xA;                indices.push_back(p11);&#xD;&#xA;                indices.push_back(p10);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        //for(auto&amp; v : points) cout &lt;&lt; to_string(v) &lt;&lt; endl;&#xD;&#xA;        //cout &lt;&lt; endl;&#xD;&#xA;        return {points, indices};&#xD;&#xA;    }&#xD;&#xA;And immediately after calculate the normals like this:&#xD;&#xA;&#xD;&#xA;    std::vector&lt;glm::vec3&gt; GenerateNormals(const std::vector&lt;glm::vec3&gt;&amp; vertices,&#xD;&#xA;        const std::vector&lt;uint&gt;&amp; indices)&#xD;&#xA;    {&#xD;&#xA;        assert(indices.size() % 3 ==0);&#xD;&#xA;    &#xD;&#xA;        map&lt;uint, vector&lt;vec3&gt;&gt; normal_map;&#xD;&#xA;        for(uint i=0; i &lt; indices.size(); i += 3)&#xD;&#xA;        {&#xD;&#xA;            vec3 v1 = vertices[indices[i]];&#xD;&#xA;            vec3 v2 = vertices[indices[i + 1]];&#xD;&#xA;            vec3 v3 = vertices[indices[i + 2]];&#xD;&#xA;    &#xD;&#xA;            vec3 d1 = v2 - v1;&#xD;&#xA;            vec3 d2 = v3 - v1;&#xD;&#xA;    &#xD;&#xA;            assert(indices[i] &lt; vertices.size());&#xD;&#xA;            assert(indices[i + 1] &lt; vertices.size());&#xD;&#xA;            assert(indices[i + 2] &lt; vertices.size());&#xD;&#xA;            assert(indices[i] != indices[i+1] &amp;&amp; indices[i] != indices[i+2] &amp;&amp;&#xD;&#xA;                indices[i+1] != indices[i+2]);&#xD;&#xA;    &#xD;&#xA;            if(abs(dot(d1, d2)) &lt; 0.0001)&#xD;&#xA;            {&#xD;&#xA;                d1 = v3 - v2;&#xD;&#xA;                d2 = v1 - v2;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if(abs(dot(d1, d2)) &lt; 0.0001)&#xD;&#xA;            {&#xD;&#xA;                d1 = v1 - v3;&#xD;&#xA;                d2 = v2 - v3;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            vec3 normal = normalize(cross(d1, d2));&#xD;&#xA;    &#xD;&#xA;            normal_map[indices[i]].push_back(normal);&#xD;&#xA;            normal_map[indices[i + 1]].push_back(normal);&#xD;&#xA;            normal_map[indices[i + 2]].push_back(normal);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        assert(normal_map.size() == vertices.size());&#xD;&#xA;        std::vector&lt;glm::vec3&gt; normals(vertices.size());&#xD;&#xA;        for(auto&amp; pair : normal_map)&#xD;&#xA;        {&#xD;&#xA;            uint index = pair.first;&#xD;&#xA;            vector&lt;vec3&gt; v_normals = pair.second;&#xD;&#xA;    &#xD;&#xA;            vec3 normal(0);&#xD;&#xA;            for(auto&amp; n : v_normals)&#xD;&#xA;                normal += n;&#xD;&#xA;    &#xD;&#xA;            normal /= float(v_normals.size());&#xD;&#xA;            normals[index] = normal;&#xD;&#xA;        }&#xD;&#xA;        assert(normals.size() == vertices.size());&#xD;&#xA;        return normals;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Note: I know that I could just calculate the normals by taking the difference between the current vertex and the center of the sphere. These 2 functions I plan to use as templates to code other paramtetric surfaces, so that's not a solution for me I am trying to understand what I did wrong more than trying to fix it.&#xD;&#xA;&#xD;&#xA;I have added lots of assertions through the code to try to catch the issue and I have also stepped through gdb but I can't seem to find the issue. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yh3pn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27960" PostHistoryTypeId="50" PostId="9364" RevisionGUID="812558c6-d3f5-4d78-9406-a566144ed29f" CreationDate="2020-04-19T10:05:25.590" UserId="-1" />
  <row Id="27961" PostHistoryTypeId="5" PostId="9742" RevisionGUID="7ccba22f-06b5-4d9a-88d9-a01ff4a864d0" CreationDate="2020-04-19T15:05:19.340" UserId="13204" Comment="added 204 characters in body" Text="I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's [here](https://github.com/NAThompson/graphics), if relevant.)&#xD;&#xA;&#xD;&#xA;Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.&#xD;&#xA;&#xD;&#xA;When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.&#xD;&#xA;&#xD;&#xA;What can I do to get these graphs uniformly thick?&#xD;&#xA;&#xD;&#xA;If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?&#xD;&#xA;&#xD;&#xA;*Note*: I tried setting the line thickness at point $x$ to&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\max(1, |f'(x)|)&#xD;&#xA;$$&#xD;&#xA;where $ t_{\mathrm{user}}$ is the user requested thickness.&#xD;&#xA;But of course $|f'|$ can diverge, so this did horrible things to the graph. So I did:&#xD;&#xA;$$&#xD;&#xA;t(x) = t_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)&#xD;&#xA;$$&#xD;&#xA;which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.&#xD;&#xA;&#xD;&#xA;*Edit*: I'm now thinking that the width should be marked along the normal to the tangent, i.e. the line&#xD;&#xA;$$&#xD;&#xA;y - f(x_i) = -\frac{1}{f'(x_i)} (x-x_i),&#xD;&#xA;$$&#xD;&#xA;not along a vertical. So automatic differentiation is required?&#xD;&#xA;&#xD;&#xA;*Edit 2*: You can get the derivative in pixel space via finite differences; that's just fine, and I image cheaper. Then it's Bresenham's line algorithm + some alpha decay with distance from the curve?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Uws93.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27962" PostHistoryTypeId="50" PostId="9645" RevisionGUID="4d90fa7c-a14f-48c1-a5a3-72732de31cc8" CreationDate="2020-04-19T16:01:30.153" UserId="-1" />
  <row Id="27963" PostHistoryTypeId="2" PostId="9745" RevisionGUID="cd230363-4eb9-4d83-a73a-a10dc2d7bdac" CreationDate="2020-04-20T02:04:04.813" UserId="13215" Text="Sorry if this is OT, but I'm wondering if there's a specific graphics technique in which it is required to extend a preexisting orthogonal set of vectors (not necessarily to a full basis, but perhaps so).  In a matrix theory lecture, the prof said that this computation has a real-world application, but I can't remember him saying what it was.  Could be computer graphics, could be a lot of things.  I realize that it is only an issue in a high-dimensional space.  For example, if you had two orthogonal vectors in 3-space, you could compute their cross product cheaply.  I asked at Math SE, and it was not appreciated.  &#xD;&#xA;&#xD;&#xA;TLDR:  Just need the application, if any.  You don't have to say how it is computed, but feel free to if you like.  I'll read it.  I know that orthogonal vectors are often easier to work with than oblique vectors, and other very general math facts like that." ContentLicense="CC BY-SA 4.0" />
  <row Id="27964" PostHistoryTypeId="1" PostId="9745" RevisionGUID="cd230363-4eb9-4d83-a73a-a10dc2d7bdac" CreationDate="2020-04-20T02:04:04.813" UserId="13215" Text="Extending an orthogonal set of vectors (graphics application?)" ContentLicense="CC BY-SA 4.0" />
  <row Id="27965" PostHistoryTypeId="3" PostId="9745" RevisionGUID="cd230363-4eb9-4d83-a73a-a10dc2d7bdac" CreationDate="2020-04-20T02:04:04.813" UserId="13215" Text="|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27966" PostHistoryTypeId="2" PostId="9746" RevisionGUID="fdb9476b-acb4-4889-b06f-02dd6ff0db5a" CreationDate="2020-04-21T00:26:49.293" UserId="12040" Text="I am trying to implement BRDF microfacet path tracing and I think I need a little push.&#xD;&#xA;I will explain what I understand so that you can correct my mistakes.&#xD;&#xA;&#xD;&#xA;I start with simple rendering equation:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Le and Li are radiance we have no control of so I cannot change anything about them. The only thing I can change is function F which is called BRDF. Specifically, I am using this Cook-Torrance microfacet specular BRDF I found [here][2]. &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;For functions F, G and D I choose these formulas.&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Let's start with the Fresnel function. Greater the angle between H and Wo (or Wi, it should be the same) the more light is reflected. When the angle between H and Wo will be 90° then the function will return 1. That means that all of the light is reflected. That is understandable, but when I will look directly down to normal the result will be 0.14163. is really so little light reflected back? I thought that Fresnel gives percentage between reflection and refraction on the water surface for example. Is this right?&#xD;&#xA;&#xD;&#xA;Following with function G - Geometric shading. I want to use the Smith shadowing model because I want to improve it later for multiple scattering BSDF. The equation goes like this:&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;As G1 can be used more types of functions, but I like GGX. D_GGX is evaluated for both incoming light and outgoing light. It describes how much light will **NOT** be blocked by surface imperfections.&#xD;&#xA;&#xD;&#xA;And last function D - Normal distribution function. With this one, I have the biggest problems. It describes the probability that a new microfacet normal will be pointing to the given direction. This depends on roughness. So perfectly smooth surface will have every normal pointing upward, but as the surface gets rougher and rougher normals will start to point to different directions. With 100% rough material the chance of normal pointing a given direction should be uniform over the whole hemisphere. Because we are talking about probability the integral of probability over hemisphere should be 1. as this equation says, but I don't understand why there is a dot product of N and H.&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Now I will explain how I am using these equations.&#xD;&#xA;&#xD;&#xA;I start with generation microfacet normal H with distribution D_ggx. Spherical coordinates a generated like this: (epsilon is a random number from the interval (0;1&gt;. I can't use 1 because we cannot divide by 0)&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;With H defined I can reflect Wo and get Wi. H is now half vector between Wo and Wi. Now I calculate F and G. I am not using D anymore because I already used it for generating the microfacet normal H (that is against what I read in this [answer][8]).  I divide them by 4 * dot(H, Wi)*dot(n*Wo). This final number should be weight describing how much light [Li(Wi)] is reflected towards Wo. Together with a dot product of n and Wi from rendering equation. I think I have this part wrong.&#xD;&#xA;&#xD;&#xA;I am not using any importance sampling for now because I think it is not necessary to work. Am I right? Of cause with importance sampling, the image would converge faster. This is my final equation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Of cause, as you might guess when I implement this it returns almost totally black image. If you don't find any mistake in the math then the error has to be in code (but I will bet a 10$ it is a math problem)&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;If you need any specification of my decisions or goals I will happy to answer you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nU5Ao.png&#xD;&#xA;  [2]: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;  [3]: https://i.stack.imgur.com/hdv5m.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/a4RIm.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/cGRGi.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/ujEqV.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/T4MdA.png&#xD;&#xA;  [8]: https://computergraphics.stackexchange.com/questions/4394/path-tracing-the-cook-torrance-brdf&#xD;&#xA;  [9]: https://i.stack.imgur.com/H0H3s.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27967" PostHistoryTypeId="1" PostId="9746" RevisionGUID="fdb9476b-acb4-4889-b06f-02dd6ff0db5a" CreationDate="2020-04-21T00:26:49.293" UserId="12040" Text="Understanding of Microfacet monte-carlo path tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="27968" PostHistoryTypeId="3" PostId="9746" RevisionGUID="fdb9476b-acb4-4889-b06f-02dd6ff0db5a" CreationDate="2020-04-21T00:26:49.293" UserId="12040" Text="|raytracing|pathtracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27973" PostHistoryTypeId="2" PostId="9748" RevisionGUID="d18de396-b5f3-4b90-ac3d-8dae2bbbf1fe" CreationDate="2020-04-21T18:07:55.343" UserId="5717" Text="The most common use is almost certainly computing normal vectors for a surface, using a cross product. Although strictly speaking, this does not quite qualify as the two initial vectors are usually not orthogonal. This is used for shading calculations and various other algorithms. I know of [at least one][1] where the initial surface is explicitly a rectangle so it would qualify.&#xD;&#xA;&#xD;&#xA;The sampling of BRDFs is another application. In many cases, the math is done for a canonical space with the surface normal pointing up and must be transformed to the actual surface. This is done by building a full 3D basis from the surface normal vector.&#xD;&#xA;&#xD;&#xA;Anisotropic BRDFs typically have two vectors as input: the surface normal and one vector to define the orientation of anisotropy. Depending on the implementation, it may be assumed to be orthogonal to the normal. Otherwise, it is made orthogonal. Then, again, a full basis is built from those two.&#xD;&#xA;&#xD;&#xA;There is a class of ray intersection algorithms which work by projecting the surface in two dimensions. This is done by starting with the ray and generating two more orthogonal vectors which define the projection plane.&#xD;&#xA;&#xD;&#xA;This is certainly not an exhaustive list but they are the main ones that came to mind. I am not aware of any uses for higher dimensions but I don't know about every corner of computer graphics either.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.arnoldrenderer.com/research/egsr2013_spherical_rectangle.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="27974" PostHistoryTypeId="2" PostId="9749" RevisionGUID="bdde9a60-eced-409e-a7a1-d0d443c8eba6" CreationDate="2020-04-22T00:34:41.113" UserId="12040" Text="I am using Schlick approximation to calculate the value of the Fresnel effect I found [here][1]&#xD;&#xA;&#xD;&#xA;When I try to find corner cases for the formula I get the value of 1 when the angle between normal and viewing direction is 90° and 0,02 for 0° (I am using IOR 1 and 1.33). This means that when looking, for example, at a sphere its edges will reflect almost all of the light and its center will reflect just 2% of light.&#xD;&#xA;&#xD;&#xA;But he doesn't make sense for me when I try to use it in the microfacet model for BRDF.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This means that the reflectance when looking directly from above on the surface will be just 2% which is unrealistically low. 98% of the energy would be absorbed by the surface. So just after 3 bounces, the ray would transmit less than 0,0008% of the light. This would darken an image and I would have to increase its emitted light by a great amount.&#xD;&#xA;&#xD;&#xA;Am I thinking in a bad way about it? &#xD;&#xA;&#xD;&#xA;My second idea what that it means how much light is directly reflected as a perfect reflection without being scattered my microfacet to other directions. The rest is used for diffuse/glossy reflection. But I cannot find any evidence for it anywhere. &#xD;&#xA;&#xD;&#xA;Or I don't simply have to use Fresnel when I am dealing with non-transparent materials. &#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Schlick%27s_approximation&#xD;&#xA;  [2]: https://i.stack.imgur.com/6bSTk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27975" PostHistoryTypeId="1" PostId="9749" RevisionGUID="bdde9a60-eced-409e-a7a1-d0d443c8eba6" CreationDate="2020-04-22T00:34:41.113" UserId="12040" Text="Correct way to think about Fresnel effect" ContentLicense="CC BY-SA 4.0" />
  <row Id="27976" PostHistoryTypeId="3" PostId="9749" RevisionGUID="bdde9a60-eced-409e-a7a1-d0d443c8eba6" CreationDate="2020-04-22T00:34:41.113" UserId="12040" Text="|pathtracing|brdf|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="27977" PostHistoryTypeId="5" PostId="9744" RevisionGUID="8df7cc2a-9973-4844-a7de-da8898e81e00" CreationDate="2020-04-22T15:59:11.137" UserId="13159" Comment="added 107 characters in body" Text="I feel like my light conservation math isn't correct, but I am not sure which part is wrong.&#xD;&#xA;&#xD;&#xA;Is reflected light supposed to influence the diffuse light?&#xD;&#xA;&#xD;&#xA;Does metalness only affect the reflected light or does it also affect ambient and diffuse light?&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;vec4 falbedo; // surface color&#xD;&#xA;vec3 fnormal; // surface normal&#xD;&#xA;&#xD;&#xA;vec3 ambientLight;&#xD;&#xA;&#xD;&#xA;vec3 directionToCamera; // Camera normal&#xD;&#xA;vec3 directionToLight; // Directional light normal&#xD;&#xA;vec3 lightColor; // Directional light color&#xD;&#xA;&#xD;&#xA;float metalness; // 0-1&#xD;&#xA;float shininess; // 1-256&#xD;&#xA;float subsurface; // 0-1&#xD;&#xA;&#xD;&#xA;// Diffuse light&#xD;&#xA;float lightNormalDot = dot(fnormal, directionToLight);&#xD;&#xA;float lightIntensity = max(.0, lightNormalDot);&#xD;&#xA;&#xD;&#xA;// Blinn–Phong reflection&#xD;&#xA;vec3 halfway = normalize(directionToCamera + directionToLight);&#xD;&#xA;float reflectionFactor = max(.0, dot(halfway, fnormal));&#xD;&#xA;&#xD;&#xA;float reflection = pow(reflectionFactor, shininess);&#xD;&#xA;&#xD;&#xA;vec3 res = falbedo.rgb * ambientLight;&#xD;&#xA;res += subsurface * lightIntensity * lightColor * falbedo.rgb;&#xD;&#xA;res += (1. - subsurface) * reflection * mix(lightColor, lightColor * falbedo.rgb, metalness);&#xD;&#xA;&#xD;&#xA;gl_FragColor = vec4(res, falbedo.a);&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27978" PostHistoryTypeId="2" PostId="9750" RevisionGUID="aca53c39-3bee-4c6a-99f6-cce2ef2e5af4" CreationDate="2020-04-22T17:55:29.370" UserId="5717" Text="You tile idea seems to be a good one to cut down on local complexity. You can't reasonably evaluate every primitive everywhere. Not if you want good performance anyway. So you need a simplified version for each tile, where you remove elements which have insignificant contribution. This is an interesting problem of its own. A simple version of this would be to:&#xD;&#xA;&#xD;&#xA;  - Assign each primitive &quot;usefulness bounds&quot; beyond which it is considered 0. What exactly those are will depend on the curves you're using to map distance to world height. To make your life easier, pick something which actually goes to 0 over a finite distance. Or alter your favorite curve so it does.&#xD;&#xA;  - For each tile, trim out primitives for which the bounds don't intersect the tile. You can do this with a simple loop to begin with.&#xD;&#xA;  - Further simplify the operation tree. This is a little vague because you did not provide details on the kind of operations which will be in your function. But essentially, you want to do the like of replacing $x \times 0$ by $0$ and $x + 0$ by $x$, until you can't anymore. The zeroes come from the previous step where you removed some primitives.&#xD;&#xA;&#xD;&#xA;You may need spatial hierarchies if you want this to scale to a world with millions of primitives. This can quickly become a complex topic so I'll leave it at that for now. Ask again when you get there :-)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For your more immediate problem, I suggest using the CPU to rewrite your SDF using [reverse polish notation][1]. This will allow you to write your shader as a simple interpreter, with two large buffers as inputs:&#xD;&#xA;&#xD;&#xA; - An integer buffer with commands (union, add, multiply, point primitive, segment primitive, etc).&#xD;&#xA; - A float buffer with operands and transforms for the primitives.&#xD;&#xA;&#xD;&#xA;The shader is then just a loop over commands which consumes operands as needed. You'll need different command/operand buffers for every tile, obviously. Depending on the typical nature of your SDF, you may find it more efficient to have your primitives always perform union and have an explicit push command for the rare exceptions. There are a lot of ways to go about this really.&#xD;&#xA;&#xD;&#xA;You should take care to make sure the resulting SDF can be evaluated with a reasonably small stack as this will be fixed in your shader. This is another problem by itself, perhaps well suited for the computer science SE, but probably not too difficult to solve on your own either.&#xD;&#xA;&#xD;&#xA;I'm sorry if I have not provided enough OpenGL specific details but GPUs are not my specialty.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Reverse_Polish_notation" ContentLicense="CC BY-SA 4.0" />
  <row Id="27979" PostHistoryTypeId="2" PostId="9751" RevisionGUID="a0b118f5-2ccc-4a26-a766-dd350fc7bd67" CreationDate="2020-04-22T21:37:51.163" UserId="13237" Text="I will answer based on my experience with Fresnel models. Due to Kirchhoff's law of thermal radiation, in an opaque material the emissivity plus reflectivity plus absorptivity equals to one for every direction in thermal equilibrium. If the BRDF model you are using is physically-based, it should preserve energy conservation. That means that for a given viewing angle, the integral of the equation for the entire hemisphere should be equal to 1. It may be possible the reflectivity value near the normal is low, but that means that most of its contribution is elsewhere. For example, for a near-normal viewing direction, you can have a really low specular reflectivity but a much higher diffuse component. That may be the case of your model." ContentLicense="CC BY-SA 4.0" />
  <row Id="27980" PostHistoryTypeId="2" PostId="9752" RevisionGUID="c56464fd-303d-4652-a777-5ddd41e2fcb7" CreationDate="2020-04-23T00:41:17.687" UserId="12040" Text="Ok, after some searching I have probably found a reason why it is totally ok to use Fresnel in the microfacet model.&#xD;&#xA;&#xD;&#xA;My problem was low reflectance when looking from 0° grazing angle and as I said I used IOR 1 for the air and 1.33 for the objects. **This was a big mistake.**&#xD;&#xA;&#xD;&#xA;When you create a graph of Schlick approximation for IOR = 1.33 your lower limit is 0.02. But this is only true for materials with IOR of 1.33 such as glass. When I look at this [page][1] that shows IOR of different material and you find for a section for a 3D artist you can see that IOR for metal is 3.17. Plugging this into the equation your lower limit becomes 0.27. That's 10 times more!!!&#xD;&#xA;&#xD;&#xA;Even more fascinating is a fact that when you scroll down you can find &quot;Reflection calculate&quot;. This outputs a function of reflectance (use non-polarized light) which I need. It is quite strange that Schlick approximation results in almost exactly the same function as on the website for glass, but when I use IOR = 3.17 from iron it is waaayyy off. The smallest reflectance should be 0.7688 by the website.&#xD;&#xA;&#xD;&#xA;This means that the only thing I have to do is to find a more accurate function for F component (stop using Schick approximation) and use real IOR of materials. Simply said, &quot;walls are not from water, most of the time&quot; :D&#xD;&#xA;&#xD;&#xA;Please tell me if I am wrong here... again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://refractiveindex.info/" ContentLicense="CC BY-SA 4.0" />
  <row Id="27981" PostHistoryTypeId="5" PostId="9752" RevisionGUID="63677644-108b-4c68-a5b5-d3a50f051a5f" CreationDate="2020-04-23T01:12:09.403" UserId="12040" Comment="added 836 characters in body" Text="Ok, after some searching I have probably found a reason why it is totally ok to use Fresnel in the microfacet model.&#xD;&#xA;&#xD;&#xA;My problem was low reflectance when looking from 0° grazing angle and as I said I used IOR 1 for the air and 1.33 for the objects. **This was a big mistake.**&#xD;&#xA;&#xD;&#xA;When you create a graph of Schlick approximation for IOR = 1.33 your lower limit is 0.02. But this is only true for materials with IOR of 1.33 such as glass. When I look at this [page][1] that shows IOR of different material and you find for a section for a 3D artist you can see that IOR for metal is 3.17. Plugging this into the equation your lower limit becomes 0.27. That's 10 times more!!!&#xD;&#xA;&#xD;&#xA;Even more fascinating is a fact that when you scroll down you can find &quot;Reflection calculate&quot;. This outputs a function of reflectance (use non-polarized light) which I need. It is quite strange that Schlick approximation results in almost exactly the same function as on the website for glass, but when I use IOR = 3.17 from iron it is waaayyy off. The smallest reflectance should be 0.7688 by the website.&#xD;&#xA;&#xD;&#xA;This means that the only thing I have to do is to find a more accurate function for F component (stop using Schick approximation) and use real IOR of materials. Simply said, &quot;walls are not from water, most of the time&quot; :D&#xD;&#xA;&#xD;&#xA;Please tell me if I am wrong here... again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;I found this [page][2]. It explains everything you need to know about the Fresnel effect. Most importantly it cares about both dielectrics and metals.&#xD;&#xA;&#xD;&#xA;Here is a simplified version:&#xD;&#xA;&#xD;&#xA;Use Schlick approximation every time, but instead of calculation F0 = [(n1-n2)/(n1+n2)]^2 use your own value. If you want accurate reflection then look on the website and for F0 choose reflectance at 0°. It is a sort of a baseline. This isn't much important for dielectric (IOR up to 1.5), where base form Schlick approximation works so be free to use the equation above.&#xD;&#xA;&#xD;&#xA;Be careful about metallic materials. Fresnel effect depends on the wavelength of light so there will be different values of R, G a B.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://refractiveindex.info/&#xD;&#xA;  [2]: http://psgraphics.blogspot.com/2020/03/fresnel-equations-schlick-approximation.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="27982" PostHistoryTypeId="50" PostId="9654" RevisionGUID="c6922588-c395-4294-a1a5-4186247bc00e" CreationDate="2020-04-23T05:04:25.453" UserId="-1" />
  <row Id="27983" PostHistoryTypeId="50" PostId="2146" RevisionGUID="aa5ec522-2857-4b9e-bbf9-5b3549ee9b74" CreationDate="2020-04-23T06:02:35.270" UserId="-1" />
  <row Id="27984" PostHistoryTypeId="5" PostId="9678" RevisionGUID="f7d7348b-3728-4cfd-ac46-119220713fea" CreationDate="2020-04-23T11:42:29.387" UserId="11696" Comment="added 77 characters in body" Text="I'm interpolating RGB values by transforming them into HSV space and then back into RGB. I have trouble figuring out how to achieve `interpolate(green, black, 0.5) = darkgreen`.&#xD;&#xA;&#xD;&#xA;Black has multiple representations in HSV, for example `(0, 0, 0)` and `(30, 0, 0)` are both black. When I convert the RGB black `#000000`, I turn it into `(0, 0, 0)`. When I then interpolate it with green `(120, 1, 1)`, I get `(60, 0.5, 0.5)` which is dark semi-saturated yellow. A similar issue exist for white.&#xD;&#xA;&#xD;&#xA;Am I supposed to choose a different color space? I don't want to use LAB color space, because it's computationally expensive. How can I make this correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="27985" PostHistoryTypeId="50" PostId="8701" RevisionGUID="11d9f4f1-507c-4bef-a8b3-51dbd7f8b65d" CreationDate="2020-04-23T12:04:25.537" UserId="-1" />
  <row Id="27986" PostHistoryTypeId="50" PostId="8886" RevisionGUID="93cdad1f-66c1-4e7e-b6f2-6b4256623bfd" CreationDate="2020-04-23T13:04:00.377" UserId="-1" />
  <row Id="27987" PostHistoryTypeId="5" PostId="9752" RevisionGUID="61fa5c71-78a5-43e3-8142-6cb6d0812cb8" CreationDate="2020-04-23T19:05:41.353" UserId="12040" Comment="Final explanation and solution of the problem" Text="**BIG UPDATE and explanation of BRDF model**&#xD;&#xA;============================================&#xD;&#xA;&#xD;&#xA;While I was cleaning my browser and closing about 100 tabs I found this awesome [website][1] (it was there 3 days so I could already found an answer...) which finally made everything clear for me.&#xD;&#xA;&#xD;&#xA;The problem wasn't in Fresnel at all. In fact, it doesn't matter what IOR you are using for the most time. Fresnel says how much light is reflected as a part of **specular brdf**. Here important is the word &quot;specular&quot;. It means that light is reflected right when it hit the surface and it does not go through. The rest of it light that isn't refected do one of these things: is absorbed or is refracted (like in glass) or is scattered around and return to the surface as diffuse light. And the diffuse component is missing in my path tracer. I thought that specular BRDF takes a diffuse light into the count but it doesn't.&#xD;&#xA;&#xD;&#xA;So here I will sum up how to use microfacet specular BRDF and diffuse BRDF for recursive path tracer, where I can hold only 1 ray at a time for a pixel.&#xD;&#xA;&#xD;&#xA; 1. Intersection with geometry&#xD;&#xA; 2. Calculate Fresnel&#xD;&#xA; 3. Generate random number in range 0 to 1&#xD;&#xA; 4. If the number is smaller or equal to Fresnel then use specular BRDF to calculate the new direction based on the distribution function of microfacet normals and evaluate.&#xD;&#xA; 5. If the number is bigger than Fresnel then use simple cosine-weighted diffuse BRDF or do refraction it is up to you.&#xD;&#xA;&#xD;&#xA;It is important to use both components of BRDF. Unfortunately, when you search for microfacet BRDF they usually expect you to know that it is just for the specular part.&#xD;&#xA;&#xD;&#xA;I hope this help some beginners because it was a big struggle for me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Original answer - some part of it is wrong. For explanation look at update above.**&#xD;&#xA;========================================================================&#xD;&#xA;&#xD;&#xA;Ok, after some searching I have probably found a reason why it is totally ok to use Fresnel in the microfacet model.&#xD;&#xA;&#xD;&#xA;My problem was low reflectance when looking from 0° grazing angle and as I said I used IOR 1 for the air and 1.33 for the objects. **This was a big mistake.**&#xD;&#xA;&#xD;&#xA;When you create a graph of Schlick approximation for IOR = 1.33 your lower limit is 0.02. But this is only true for materials with IOR of 1.33 such as glass. When I look at this [page][2] that shows IOR of different material and you find for a section for a 3D artist you can see that IOR for metal is 3.17. Plugging this into the equation your lower limit becomes 0.27. That's 10 times more!!!&#xD;&#xA;&#xD;&#xA;Even more fascinating is a fact that when you scroll down you can find &quot;Reflection calculate&quot;. This outputs a function of reflectance (use non-polarized light) which I need. It is quite strange that Schlick approximation results in almost exactly the same function as on the website for glass, but when I use IOR = 3.17 from iron it is waaayyy off. The smallest reflectance should be 0.7688 by the website.&#xD;&#xA;&#xD;&#xA;This means that the only thing I have to do is to find a more accurate function for F component (stop using Schick approximation) and use real IOR of materials. Simply said, &quot;walls are not from water, most of the time&quot; :D&#xD;&#xA;&#xD;&#xA;Please tell me if I am wrong here... again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;I found this [page][3]. It explains everything you need to know about the Fresnel effect. Most importantly it cares about both dielectrics and metals.&#xD;&#xA;&#xD;&#xA;Here is a simplified version:&#xD;&#xA;&#xD;&#xA;Use Schlick approximation every time, but instead of calculation F0 = [(n1-n2)/(n1+n2)]^2 use your own value. If you want accurate reflection then look on the website and for F0 choose reflectance at 0°. It is a sort of a baseline. This isn't much important for dielectric (IOR up to 1.5), where base form Schlick approximation works so be free to use the equation above.&#xD;&#xA;&#xD;&#xA;Be careful about metallic materials. Fresnel effect depends on the wavelength of light so there will be different values of R, G a B.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://simonstechblog.blogspot.com/2011/12/microfacet-brdf.html&#xD;&#xA;  [2]: https://refractiveindex.info/&#xD;&#xA;  [3]: http://psgraphics.blogspot.com/2020/03/fresnel-equations-schlick-approximation.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="27988" PostHistoryTypeId="2" PostId="9753" RevisionGUID="53ea4e46-0b60-485a-ba6f-cdb138aedd15" CreationDate="2020-04-23T19:47:27.420" UserId="1988" Text="Though quaternions cannot be visualized as points on the surface of a unit sphere in 3 dimensions, they can be readily visualized as unit *tangents* attached to the surface of the unit sphere. [Here is an example visualization](https://www.ri.cmu.edu/pub_files/pub4/kuffner_james_2004_1/kuffner_james_2004_1.pdf). &#xA;&#xA;One could construct a similar visualization by drawing an arrow, starting at&#xA;$q * \hat{x}$ and ending at $q * \hat{y}$, where $\hat{x}$ is the unit x vector, $\hat{y}$ is the unit y vector, and $q$ is the unit quaternion we are trying to visualize. This allows the drawing of nice smooth curves, while remaining bijective." ContentLicense="CC BY-SA 4.0" />
  <row Id="27989" PostHistoryTypeId="5" PostId="9542" RevisionGUID="891affcb-b33e-4abb-93d5-0482905fe633" CreationDate="2020-04-23T19:59:16.187" UserId="6114" Comment="added 387 characters in body" Text="Here you have a full repository with a lot of papers about light transport. There's also a folder named 'theory' where you can get both intro and advanced refs regard light physics. And much more. I'm personally curating this and keeping up to date with latest advancements. &#xD;&#xA;&#xD;&#xA;https://drive.google.com/drive/folders/16A6Yj2esRTk0FP-ALr6XfxkGQvTb_1dD?usp=sharing&#xD;&#xA;&#xD;&#xA;However here are the main books I suggest to read :&#xD;&#xA;&#xD;&#xA;1985 - Physically Based Lighting Calculations For Computer Graphics&#xD;&#xA;&#xD;&#xA;1986 - The Rendering Equation&#xD;&#xA;&#xD;&#xA;1997 - A Framework for Realistic Image Synthesis&#xD;&#xA;&#xD;&#xA;1997 - Robust MonteCarlo Methods For Light Transport Simulation&#xD;&#xA;&#xD;&#xA;2011 - The State of the Art in Interactive Global Illumination&#xD;&#xA;&#xD;&#xA;2014 - The Path to Path-Traced Movies&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27990" PostHistoryTypeId="2" PostId="9754" RevisionGUID="4ad97577-b436-41a5-9693-444c7611e0d8" CreationDate="2020-04-23T20:49:20.117" UserId="6114" Text="If you just implement Fresnel alone you'll see that what you think in your original question is mainly correct for dieletric materials.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However don't calculate Fresnel ahead and then stochastically decide if evaluate your specular component or your diffuse one. Being part of the BRDF you have to accumulate the Fresnel term while evaluating the BRDF and only then eventually do 1-Facc for the diffuse part. If you are in a pure stochastic pathtracer then you do that directly while evaluating your microfacet. This is called 'rough Fresnel' and it's the model all modern render engines use.&#xD;&#xA;&#xD;&#xA;For better Fresnel get the full Fresnel formula (complex Fresnel for metals). For friendlier Fresnel you can implement the 'Fresnel by colors' (can't remember the exact name rightnow I'll add it later), so instead to input numbers you input colors for F0 and F1. This is the way latest Renderman does it. Eventually add a 'metalness' parameter to switch between Fresnel and ComplexFresnel for metals.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hkXpO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27991" PostHistoryTypeId="2" PostId="9755" RevisionGUID="9a1e5e0b-d8f5-42c9-80ec-c811f5bf37b0" CreationDate="2020-04-23T20:54:31.333" UserId="6114" Text="What is wrong ? Almost everything. It is not a PBR material at all. PBR metallic materials do not use ambient term and do use generally microfacet BRDFs and ComplexFresnel." ContentLicense="CC BY-SA 4.0" />
  <row Id="27992" PostHistoryTypeId="5" PostId="9542" RevisionGUID="705b7b0c-fe19-4004-b082-9d18d44dbcc0" CreationDate="2020-04-23T21:52:18.183" UserId="6114" Comment="added 7 characters in body" Text="Here you have a full repository with a lot of papers about light transport. There's also a folder named 'theory' where you can get both intro and advanced refs regard light physics. And much more. I'm personally curating this and keeping up to date with latest advancements. &#xD;&#xA;&#xD;&#xA;https://drive.google.com/drive/folders/16A6Yj2esRTk0FP-ALr6XfxkGQvTb_1dD?usp=sharing&#xD;&#xA;&#xD;&#xA;However here are the main books/papers I suggest to read :&#xD;&#xA;&#xD;&#xA;1985 - Physically Based Lighting Calculations For Computer Graphics&#xD;&#xA;&#xD;&#xA;1986 - The Rendering Equation&#xD;&#xA;&#xD;&#xA;1997 - A Framework for Realistic Image Synthesis&#xD;&#xA;&#xD;&#xA;1997 - Robust MonteCarlo Methods For Light Transport Simulation&#xD;&#xA;&#xD;&#xA;2011 - The State of the Art in Interactive Global Illumination&#xD;&#xA;&#xD;&#xA;2014 - The Path to Path-Traced Movies&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="27993" PostHistoryTypeId="5" PostId="9754" RevisionGUID="f2980152-73b1-4261-861b-98c9b2b8cf41" CreationDate="2020-04-23T22:09:07.047" UserId="6114" Comment="added 130 characters in body" Text="If you just implement Fresnel alone you'll see that what you think in your original question is mainly correct for dieletric materials.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;However don't calculate Fresnel ahead and then stochastically decide if evaluate your specular component or your diffuse one. Being part of the BRDF you have to accumulate the Fresnel term while evaluating the BRDF and only then eventually do 1-Facc for the diffuse part. If you are in a pure stochastic pathtracer then you do that directly while evaluating your microfacet. This is called 'rough Fresnel' and it's the model all modern render engines use.&#xD;&#xA;&#xD;&#xA;For better Fresnel get the full Fresnel formula (complex Fresnel for metals). For friendlier Fresnel you can implement the 'Fresnel by colors' (can't remember the exact name rightnow I'll add it later), so instead to input numbers you input colors for F0 and F1. This is the way latest Renderman does it. Eventually add a 'metalness' parameter to switch between Fresnel and ComplexFresnel for metals.&#xD;&#xA;&#xD;&#xA;For example some code (BRDF sample fnc) to inspect:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hkXpO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/W0ZZd.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27994" PostHistoryTypeId="5" PostId="9749" RevisionGUID="a5440880-e141-4f59-9943-8ba0c7215d2a" CreationDate="2020-04-23T23:02:15.483" UserId="12040" Comment="added 1569 characters in body" Text="I am using Schlick approximation to calculate the value of the Fresnel effect I found [here][1]&#xD;&#xA;&#xD;&#xA;When I try to find corner cases for the formula I get the value of 1 when the angle between normal and viewing direction is 90° and 0,02 for 0° (I am using IOR 1 and 1.33). This means that when looking, for example, at a sphere its edges will reflect almost all of the light and its center will reflect just 2% of light.&#xD;&#xA;&#xD;&#xA;But he doesn't make sense for me when I try to use it in the microfacet model for BRDF.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This means that the reflectance when looking directly from above on the surface will be just 2% which is unrealistically low. 98% of the energy would be absorbed by the surface. So just after 3 bounces, the ray would transmit less than 0,0008% of the light. This would darken an image and I would have to increase its emitted light by a great amount.&#xD;&#xA;&#xD;&#xA;Am I thinking in a bad way about it? &#xD;&#xA;&#xD;&#xA;My second idea what that it means how much light is directly reflected as a perfect reflection without being scattered my microfacet to other directions. The rest is used for diffuse/glossy reflection. But I cannot find any evidence for it anywhere. &#xD;&#xA;&#xD;&#xA;Or I don't simply have to use Fresnel when I am dealing with non-transparent materials. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;This is my code for now.&#xD;&#xA;&#xD;&#xA;    //Position of intersection is world space&#xD;&#xA;    float3 hitpoint = ray.origin + ray.direction * ray.distance;&#xD;&#xA;    &#xD;&#xA;	//Direction towards camera&#xD;&#xA;	float3 wo = -ray.direction;&#xD;&#xA;    &#xD;&#xA;	//Geometry normal&#xD;&#xA;	float3 N = ray.worldNormal;&#xD;&#xA;	    			&#xD;&#xA;    //Microfacet normal&#xD;&#xA;    float3 H = SampleMicrofacetNormal(roughness, &amp;N, &amp;ray);&#xD;&#xA;    	&#xD;&#xA;    //New direction of ray&#xD;&#xA;	float3 wi;		&#xD;&#xA;    &#xD;&#xA;    // Add light emitted from surface&#xD;&#xA;    ray.color += ray.mask * emission;&#xD;&#xA;    			&#xD;&#xA;    float F = Fresnel(&amp;H, &amp;wi);&#xD;&#xA;    &#xD;&#xA;    float r1 = new_random(&amp;ray.seed1);&#xD;&#xA;    &#xD;&#xA;    if (r1 &lt;= F) {&#xD;&#xA;    	//Specular&#xD;&#xA;&#xD;&#xA;        //Reflected direction&#xD;&#xA;        float3 wi = reflect(&amp;H, &amp;wo);    &#xD;&#xA;&#xD;&#xA;    	float D = D_ggx(roughness, &amp;N, &amp;H);&#xD;&#xA;    	float G = G_CookTorrance(roughness, &amp;N, &amp;H, &amp;wo, &amp;wi);&#xD;&#xA;    &#xD;&#xA;    	float weight = fabs(dot(wo, H)) / fabs(dot(N, wo) * dot(N, H));&#xD;&#xA;    	float reflectance = F * G * weight;&#xD;&#xA;    	&#xD;&#xA;        ray.mask *= reflectance;&#xD;&#xA;    &#xD;&#xA;    	//Check - new direction cannot point towards surface&#xD;&#xA;    	if (dot(wi, N) &lt; 0) ray.mask = (float3)(0.0, 0.0, 0.0);&#xD;&#xA;   	}&#xD;&#xA;    else {&#xD;&#xA;    	//Diffuse&#xD;&#xA;        //Ray change color because light to through the material&#xD;&#xA;    	ray.mask *= color;&#xD;&#xA;    &#xD;&#xA;        //New random direction of diffuse ray&#xD;&#xA;    	wi = SampleDiffuseCosineWeighted(&amp;N, &amp;ray);&#xD;&#xA;    		&#xD;&#xA;        //Importance sampling weight	&#xD;&#xA;    	ray.mask *= dot(wi, N);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;	//Set new direction and position for next tracing&#xD;&#xA;	ray.direction = wi;&#xD;&#xA;	ray.origin = hitpoint + N * EPSILON;&#xD;&#xA;    		&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Schlick%27s_approximation&#xD;&#xA;  [2]: https://i.stack.imgur.com/6bSTk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27995" PostHistoryTypeId="5" PostId="9749" RevisionGUID="1de5f4b8-d4ee-41b2-8644-cbcd3ba9a3d7" CreationDate="2020-04-23T23:09:19.803" UserId="12040" Comment="added 127 characters in body" Text="I am using Schlick approximation to calculate the value of the Fresnel effect I found [here][1]&#xD;&#xA;&#xD;&#xA;When I try to find corner cases for the formula I get the value of 1 when the angle between normal and viewing direction is 90° and 0,02 for 0° (I am using IOR 1 and 1.33). This means that when looking, for example, at a sphere its edges will reflect almost all of the light and its center will reflect just 2% of light.&#xD;&#xA;&#xD;&#xA;But he doesn't make sense for me when I try to use it in the microfacet model for BRDF.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This means that the reflectance when looking directly from above on the surface will be just 2% which is unrealistically low. 98% of the energy would be absorbed by the surface. So just after 3 bounces, the ray would transmit less than 0,0008% of the light. This would darken an image and I would have to increase its emitted light by a great amount.&#xD;&#xA;&#xD;&#xA;Am I thinking in a bad way about it? &#xD;&#xA;&#xD;&#xA;My second idea what that it means how much light is directly reflected as a perfect reflection without being scattered my microfacet to other directions. The rest is used for diffuse/glossy reflection. But I cannot find any evidence for it anywhere. &#xD;&#xA;&#xD;&#xA;Or I don't simply have to use Fresnel when I am dealing with non-transparent materials. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;This is my code for now.&#xD;&#xA;&#xD;&#xA;    //Position of intersection is world space&#xD;&#xA;    float3 hitpoint = ray.origin + ray.direction * ray.distance;&#xD;&#xA;    &#xD;&#xA;	//Direction towards camera&#xD;&#xA;	float3 wo = -ray.direction;&#xD;&#xA;    &#xD;&#xA;	//Geometry normal&#xD;&#xA;	float3 N = ray.worldNormal;&#xD;&#xA;	    			&#xD;&#xA;    //Microfacet normal&#xD;&#xA;    float3 H = SampleMicrofacetNormal(roughness, &amp;N, &amp;ray);&#xD;&#xA;    	&#xD;&#xA;    //New direction of ray&#xD;&#xA;	float3 wi;		&#xD;&#xA;    &#xD;&#xA;    // Add light emitted from surface&#xD;&#xA;    ray.color += ray.mask * emission;&#xD;&#xA;    			&#xD;&#xA;    float F = Fresnel(&amp;H, &amp;wi);&#xD;&#xA;    &#xD;&#xA;    float r1 = new_random(&amp;ray.seed1);&#xD;&#xA;    &#xD;&#xA;    if (r1 &lt;= F) {&#xD;&#xA;    	//Specular&#xD;&#xA;&#xD;&#xA;        //Reflected direction&#xD;&#xA;        float3 wi = reflect(&amp;H, &amp;wo);    &#xD;&#xA;&#xD;&#xA;    	float D = D_ggx(roughness, &amp;N, &amp;H);&#xD;&#xA;    	float G = G_CookTorrance(roughness, &amp;N, &amp;H, &amp;wo, &amp;wi);&#xD;&#xA;    &#xD;&#xA;    	float weight = fabs(dot(wo, H)) / fabs(dot(N, wo) * dot(N, H));&#xD;&#xA;    	&#xD;&#xA;        //Not using F because it is already taken into a count by &#xD;&#xA;        //the probability of this IF/ELSE statement&#xD;&#xA;        float reflectance = G * weight;&#xD;&#xA;    	&#xD;&#xA;        ray.mask *= reflectance;&#xD;&#xA;    &#xD;&#xA;    	//Check - new direction cannot point towards surface&#xD;&#xA;    	if (dot(wi, N) &lt; 0) ray.mask = (float3)(0.0, 0.0, 0.0);&#xD;&#xA;   	}&#xD;&#xA;    else {&#xD;&#xA;    	//Diffuse&#xD;&#xA;        //Ray change color because light to through the material&#xD;&#xA;    	ray.mask *= color;&#xD;&#xA;    &#xD;&#xA;        //New random direction of diffuse ray&#xD;&#xA;    	wi = SampleDiffuseCosineWeighted(&amp;N, &amp;ray);&#xD;&#xA;    		&#xD;&#xA;        //Importance sampling weight	&#xD;&#xA;    	ray.mask *= dot(wi, N);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;	//Set new direction and position for next tracing&#xD;&#xA;	ray.direction = wi;&#xD;&#xA;	ray.origin = hitpoint + N * EPSILON;&#xD;&#xA;    		&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Schlick%27s_approximation&#xD;&#xA;  [2]: https://i.stack.imgur.com/6bSTk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="27997" PostHistoryTypeId="2" PostId="9756" RevisionGUID="c2a20e46-f30b-49bb-881b-defebb967a92" CreationDate="2020-04-24T12:41:03.547" UserId="13254" Text="I'm trying to implement the following paper in modern OpenGL&#xD;&#xA;&#xD;&#xA;http://web.media.mit.edu/~lieber/Publications/Coloring-Book.pdf&#xD;&#xA;&#xD;&#xA;The issue is that the algorithm described requires you to consider interior points in an orderly fashion -- horizontally first, then vertically. You also need a way to remember throughout the entire coloring process which parts have been already colored. &#xD;&#xA;&#xD;&#xA;I initially thought of putting the logic in a fragment shader, but that will clearly not work because I have no control over the order in which it is called, and also no way to remember state between different invocations.&#xD;&#xA;&#xD;&#xA;Maybe we can perform this logic on the CPU and use it to make a texture? The problem here is that I don't know of any way to access and modify specific pixels outside of shaders.&#xD;&#xA;&#xD;&#xA;Note that doing this using the fixed function pipeline would be much more straightforward, but I want to learn modern OpenGL.&#xD;&#xA;&#xD;&#xA;I'm very new to OpenGL and graphics programming, so would appreciate any suggestions on how one would go about this." ContentLicense="CC BY-SA 4.0" />
  <row Id="27998" PostHistoryTypeId="1" PostId="9756" RevisionGUID="c2a20e46-f30b-49bb-881b-defebb967a92" CreationDate="2020-04-24T12:41:03.547" UserId="13254" Text="Coloring arbitrary closed regions" ContentLicense="CC BY-SA 4.0" />
  <row Id="27999" PostHistoryTypeId="3" PostId="9756" RevisionGUID="c2a20e46-f30b-49bb-881b-defebb967a92" CreationDate="2020-04-24T12:41:03.547" UserId="13254" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28000" PostHistoryTypeId="2" PostId="9757" RevisionGUID="16308b35-e9cf-488e-b801-f4f74c9f629b" CreationDate="2020-04-24T13:13:52.277" UserId="12040" Text="So I found out where was a problem.&#xD;&#xA;&#xD;&#xA;This whole equation is for specular BRDF which is only one part of light interaction. When you hit the surface you have to generate new microfacet normal from distribution D. Then use it to calculate Fresnel. it gives you value from 0 to 1. That is now much light is directly reflected from the surface, but there is another part I forgot about, the diffuse component also contributes to the equation with (1 - Fresnel value).&#xD;&#xA;&#xD;&#xA;So the only problem was using just one component.&#xD;&#xA;&#xD;&#xA;And I also introduced the importance of sampling, which negates the D resulting in:&#xD;&#xA;&#xD;&#xA;Integral over omega = incoming light from wi *  (F * G * dot(wo, H(new microfacet normal))) / (dot(N, wo) * dot(N, H))&#xD;&#xA;&#xD;&#xA;There is also one check. New direction wi cannot point towards the surface, because it would go through. &#xD;&#xA;&#xD;&#xA;if (dot(wi, N) &lt; 0) ray.mask = (float3)(0.0, 0.0, 0.0);&#xD;&#xA;&#xD;&#xA;This can darken an image quite a lot especially when you use it on the glass. But there is a solution in BSSRDF. This equation takes a multiple scattering of the light on surface into a count.&#xD;&#xA;&#xD;&#xA;This is the specular part. For the diffuse, I used a basic cosine weighted distribution with (1 - Fresnel) multiplier.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28001" PostHistoryTypeId="2" PostId="9758" RevisionGUID="7ac9c9c1-b01d-4b2a-be24-9cde6a51abe6" CreationDate="2020-04-24T13:16:21.563" UserId="13095" Text="According to [this discussion in the official OpenGL Forum][1], you can use `glReadPixels` to get a texture from VRAM back to your normal RAM. However, in the [reference pages][2], they say:&#xD;&#xA;&#xD;&#xA;&gt; glReadPixels, glReadnPixels — read a block of pixels from the frame buffer&#xD;&#xA;&#xD;&#xA;Important here is the term &quot;frame buffer&quot;. To find out how to use it with textures, have a look at [this StackOverflow question][3].&#xD;&#xA;&#xD;&#xA;However, the accepted answer also mentions, that you can use `glGetTexImage` ([link to reference page][4]), which is probably more suited. Have a look into the accepted answer of this [StackOverflow link][5] to get an understanding of how to use it. &#xD;&#xA;&#xD;&#xA;Both methods should give you the pixel data on the CPU side, so you can modify it as you wish and send it back to the GPU afterward. However, this is probably a relatively slow approach.&#xD;&#xA;&#xD;&#xA;I think the best solution would be to do all modifications on the GPU. If you can't achieve what you want with the standard render pipeline, you should read some tutorials about OpenGL compute shaders. I haven't worked myself with them yet, but I am pretty confident, that your problem should be solvable with them. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.khronos.org/t/fastest-way-to-transfer-texture-data-from-gpu-to-ram-and-back/46011&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadPixels.xhtml&#xD;&#xA;  [3]: https://stackoverflow.com/questions/11863416/read-texture-bytes-with-glreadpixels&#xD;&#xA;  [4]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexImage.xhtml&#xD;&#xA;  [5]: https://stackoverflow.com/questions/48938930/pixel-access-with-glgetteximage" ContentLicense="CC BY-SA 4.0" />
  <row Id="28002" PostHistoryTypeId="5" PostId="9758" RevisionGUID="9fed1d23-29d6-437f-9c78-faa18ea3a81a" CreationDate="2020-04-24T13:42:47.293" UserId="13095" Comment="added 1277 characters in body" Text="**EDIT**&#xD;&#xA;&#xD;&#xA;After rereading your question, I got the feeling, that I misunderstood your question. So I'll expand my answer referring to this specific part of your question:&#xD;&#xA;&#xD;&#xA;&gt; Maybe we can perform this logic on the CPU and use it to make a texture? The problem here is that I don't know of any way to access and modify specific pixels outside of shaders.&#xD;&#xA;&#xD;&#xA;A texture is basically just an array of (color) values. If you have a 256x256 image, that uses 3 color values (RGB) and each color value is stored in a single byte (`GLubyte`/`char`), then your array has 196608 byte sized elements. The color values are usually grouped so that 3 subsequent values represent a single pixel. Then the pixels are also ordered by column and row. So the first 765 array elements represent your first row/column of pixels in the image, the next 765 the second, and so on. With this information, you can calculate where every pixel is located in the image and modify its value as desired.&#xD;&#xA;&#xD;&#xA;In case the texture you want to modify is loaded from a file, you should already have the pixel data, that you can modify before you pass it to the GPU. If the texture is dynamically generated on the GPU, just look into the previous version of my answer (below) for further guidance.&#xD;&#xA;&#xD;&#xA;However, calculating lots of pixel data on the CPU is probably quite ineffective. I think the best solution would be to do all modifications on the GPU. If you can't achieve what you want with the standard render pipeline, you should read some tutorials about OpenGL compute shaders. I haven't worked myself with them yet, but I am pretty confident, that your problem should be solvable with them. &#xD;&#xA;&#xD;&#xA;**Previous version**&#xD;&#xA;&#xD;&#xA;According to [this discussion in the official OpenGL Forum][1], you can use `glReadPixels` to get a texture from VRAM back to your normal RAM. However, in the [reference pages][2], they say:&#xD;&#xA;&#xD;&#xA;&gt; glReadPixels, glReadnPixels — read a block of pixels from the frame buffer&#xD;&#xA;&#xD;&#xA;Important here is the term &quot;frame buffer&quot;. To find out how to use it with textures, have a look at [this StackOverflow question][3].&#xD;&#xA;&#xD;&#xA;However, the accepted answer also mentions, that you can use `glGetTexImage` ([link to reference page][4]), which is probably more suited. Have a look into the accepted answer of this [StackOverflow link][5] to get an understanding of how to use it. &#xD;&#xA;&#xD;&#xA;Both methods should give you the pixel data on the CPU side, so you can modify it as you wish and send it back to the GPU afterward. However, this is probably a relatively slow approach.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;  [1]: https://community.khronos.org/t/fastest-way-to-transfer-texture-data-from-gpu-to-ram-and-back/46011&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadPixels.xhtml&#xD;&#xA;  [3]: https://stackoverflow.com/questions/11863416/read-texture-bytes-with-glreadpixels&#xD;&#xA;  [4]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexImage.xhtml&#xD;&#xA;  [5]: https://stackoverflow.com/questions/48938930/pixel-access-with-glgetteximage" ContentLicense="CC BY-SA 4.0" />
  <row Id="28003" PostHistoryTypeId="5" PostId="9758" RevisionGUID="ce0a084d-8077-47b6-88e5-5d3e6afc832b" CreationDate="2020-04-24T13:51:35.347" UserId="13095" Comment="added 25 characters in body" Text="**EDIT**&#xD;&#xA;&#xD;&#xA;After rereading your question, I got the feeling, that I misunderstood your question. So I'll expand my answer referring to this specific part of your question:&#xD;&#xA;&#xD;&#xA;&gt; Maybe we can perform this logic on the CPU and use it to make a texture? The problem here is that I don't know of any way to access and modify specific pixels outside of shaders.&#xD;&#xA;&#xD;&#xA;A texture is basically just an array of (color) values. If you have a 256x256 image, that uses 3 color values (RGB) and each color value is stored in a single byte (`GLubyte`/`char`), then your array has 196608 byte sized elements. The color values are usually grouped so that 3 subsequent values represent a single pixel. Then the pixels are also ordered by column and row. So the first 765 array elements represent your first row/column of pixels in the image, the next 765 the second, and so on. With this information, you can calculate where every pixel is located in the image and modify its value as desired.&#xD;&#xA;&#xD;&#xA;In case the texture you want to modify is loaded from a file, you should already have the pixel data since this is the format that OpenGL expects when you upload your texture. If the texture is dynamically generated on the GPU, just look into the previous version of my answer (below) for further guidance.&#xD;&#xA;&#xD;&#xA;However, calculating lots of pixel data on the CPU is probably quite ineffective. I think the best solution would be to do all modifications on the GPU. If you can't achieve what you want with the standard render pipeline, you should read some tutorials about OpenGL compute shaders. I haven't worked myself with them yet, but I am pretty confident, that your problem should be solvable with them. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Previous version**&#xD;&#xA;&#xD;&#xA;According to [this discussion in the official OpenGL Forum][1], you can use `glReadPixels` to get a texture from VRAM back to your normal RAM. However, in the [reference pages][2], they say:&#xD;&#xA;&#xD;&#xA;&gt; glReadPixels, glReadnPixels — read a block of pixels from the frame buffer&#xD;&#xA;&#xD;&#xA;Important here is the term &quot;frame buffer&quot;. To find out how to use it with textures, have a look at [this StackOverflow question][3].&#xD;&#xA;&#xD;&#xA;However, the accepted answer also mentions, that you can use `glGetTexImage` ([link to reference page][4]), which is probably more suited. Have a look into the accepted answer of this [StackOverflow link][5] to get an understanding of how to use it. &#xD;&#xA;&#xD;&#xA;Both methods should give you the pixel data on the CPU side, so you can modify it as you wish and send it back to the GPU afterward. However, this is probably a relatively slow approach.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;  [1]: https://community.khronos.org/t/fastest-way-to-transfer-texture-data-from-gpu-to-ram-and-back/46011&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadPixels.xhtml&#xD;&#xA;  [3]: https://stackoverflow.com/questions/11863416/read-texture-bytes-with-glreadpixels&#xD;&#xA;  [4]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexImage.xhtml&#xD;&#xA;  [5]: https://stackoverflow.com/questions/48938930/pixel-access-with-glgetteximage" ContentLicense="CC BY-SA 4.0" />
  <row Id="28007" PostHistoryTypeId="50" PostId="8321" RevisionGUID="9c92ed2f-b27a-4e85-b66b-b344ae37acf9" CreationDate="2020-04-25T04:03:15.247" UserId="-1" />
  <row Id="28008" PostHistoryTypeId="50" PostId="8695" RevisionGUID="2fce68c3-f5dd-41ee-bafc-4ec176fe2bb0" CreationDate="2020-04-25T18:02:30.310" UserId="-1" />
  <row Id="28009" PostHistoryTypeId="2" PostId="9759" RevisionGUID="38d23af2-f9ec-4428-ac48-d4183cb2091d" CreationDate="2020-04-25T20:38:37.217" UserId="13260" Text="I often find myself in the situation where I have some old image where I composed a translucent overlay on top of a background, but then lost (or more likely discarded) the overlay. I still have pre-operation copies of the background, but have not managed to figure out how to perform an inverse operation to calculate the original overlay. Best results would be an operation I could perform in Gimp or Image Magick, but I could write an uncomposer if I had to, so long as I knew what to calculate." ContentLicense="CC BY-SA 4.0" />
  <row Id="28010" PostHistoryTypeId="1" PostId="9759" RevisionGUID="38d23af2-f9ec-4428-ac48-d4183cb2091d" CreationDate="2020-04-25T20:38:37.217" UserId="13260" Text="Given a background image B and a composie image of A OVER B, can we somehow recover image A?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28011" PostHistoryTypeId="3" PostId="9759" RevisionGUID="38d23af2-f9ec-4428-ac48-d4183cb2091d" CreationDate="2020-04-25T20:38:37.217" UserId="13260" Text="|image-processing|alpha|compositing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28015" PostHistoryTypeId="50" PostId="8779" RevisionGUID="df2a85ac-db79-4834-af7b-edc19061c68e" CreationDate="2020-04-26T18:05:35.583" UserId="-1" />
  <row Id="28016" PostHistoryTypeId="50" PostId="5697" RevisionGUID="2ce668d4-d583-492a-81ef-d3e361983776" CreationDate="2020-04-27T03:05:50.630" UserId="-1" />
  <row Id="28017" PostHistoryTypeId="2" PostId="9761" RevisionGUID="7b96b049-afee-439a-a73e-28e162f2c404" CreationDate="2020-04-27T15:46:43.033" UserId="12040" Text="When I am sampling diffuse BRDF I am using cosine-weighted distribution and when I want to sample specular BRDF I use sampling by GGX distribution. I can decide how much light is reflected and how much is diffused by using Fresnel. That gives me an evaluation formula like this:&#xD;&#xA;&#xD;&#xA;Eval = BRDF_specular * F + BRDF_diffuse * (1 - F)&#xD;&#xA;&#xD;&#xA;the same principle I can use on PDF. But the problem comes up when I try to use this on sampling. It is obvious that I cannot use this interpolation for the sampled vector. But what I can do is to have some probability that I will sample specular direction and probability for sampling diffuse direction. As sample count goes up it will perform as if it was interpolation between these types of sampling. I can use this for dielectric materials because their Fresnel value is the same for RGB. But because I am using separate values for RGB for Fresnel on metallic material I can have different probabilities (for example, R = 0.8, G = 0.3, B = 0.0). This gives a nice look to metals as you can see in this [post][1]. What probability I should choose then? The biggest?? Average? Or is this some different approach to this problem, because I cannot find anywhere how to combine these BRDFs? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://shanesimmsart.wordpress.com/2018/03/29/fresnel-reflection/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28018" PostHistoryTypeId="1" PostId="9761" RevisionGUID="7b96b049-afee-439a-a73e-28e162f2c404" CreationDate="2020-04-27T15:46:43.033" UserId="12040" Text="BRDF sampling and evaluation of diffuse vs specular component" ContentLicense="CC BY-SA 4.0" />
  <row Id="28019" PostHistoryTypeId="3" PostId="9761" RevisionGUID="7b96b049-afee-439a-a73e-28e162f2c404" CreationDate="2020-04-27T15:46:43.033" UserId="12040" Text="|pathtracing|brdf|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28021" PostHistoryTypeId="50" PostId="9667" RevisionGUID="8a99a569-0f62-49ec-9ee5-59b8d49f8fa4" CreationDate="2020-04-27T21:07:20.847" UserId="-1" />
  <row Id="28022" PostHistoryTypeId="50" PostId="9640" RevisionGUID="00d9ece9-7181-44ed-a7da-ef4dd7c9482e" CreationDate="2020-04-28T00:03:10.387" UserId="-1" />
  <row Id="28023" PostHistoryTypeId="50" PostId="8721" RevisionGUID="58cb71a8-fcc4-4e98-94d8-4d2461cf426d" CreationDate="2020-04-28T09:00:40.047" UserId="-1" />
  <row Id="28030" PostHistoryTypeId="2" PostId="9763" RevisionGUID="228dbeab-39d9-415f-95bf-11000fb26196" CreationDate="2020-04-28T18:41:44.190" UserId="10333" Text="By a bumpmap, I mean the black and white height map, not the rgb normal map style one. If I were to convert a bumpmap to a normal map then I don't think I should linearize the values because if an artist creates two pixels, one looking twice as bright to them, and therefore high, let's say at 0.2 and 0.4 values in sRGB, this is how they should be read and what the normals should be based on, right?&#xD;&#xA;&#xD;&#xA;Converting them from sRGB to linear would mean that what looked liked two pixels with a height difference of 2 times (0.2 and 0.4) would get read as (0.03 and 0.13), if I got the calculation right. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28031" PostHistoryTypeId="1" PostId="9763" RevisionGUID="228dbeab-39d9-415f-95bf-11000fb26196" CreationDate="2020-04-28T18:41:44.190" UserId="10333" Text="Does a bumpmap need to be linearized from sRGB when being read?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28032" PostHistoryTypeId="3" PostId="9763" RevisionGUID="228dbeab-39d9-415f-95bf-11000fb26196" CreationDate="2020-04-28T18:41:44.190" UserId="10333" Text="|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28033" PostHistoryTypeId="2" PostId="9764" RevisionGUID="dfa38d3d-5a2f-484d-b31a-91acd412560f" CreationDate="2020-04-28T20:42:40.107" UserId="38" Text="We can not answer this question. This is important, and you need to get this info from the artist (or vice versa you need to give this info to the artist before he begins) It entirely depends on what kind assumptions were made when the artist was working with the image.&#xD;&#xA;&#xD;&#xA;1. Was the artist working by numbers&#xD;&#xA;2. Was the artist working by eye&#xD;&#xA;3. Was the artist working with a sculpting application&#xD;&#xA;4. Was the data bult from a photograph&#xD;&#xA;&#xD;&#xA;You would be right if the artist worked by number. But of the artist was working by eye, which is incredibly hard, then you would be a bit off. sRGB does not entirely match human brightness sense so you should really fiddle a bit with the exponent if this was the case. But you might aswell skip this. For sculpting and baking the image is most likely be linear allready to begin with, although the profile might not reflect this. And for the photograph case depends heavily on method.&#xD;&#xA;&#xD;&#xA;Safest bet is to do no conversion at all. But it is not really defined so strictly. Kindof the entire world of imagemanipulation has skipped the how to tag images that arent you know display images but pure data. Who knows how it is encoded." ContentLicense="CC BY-SA 4.0" />
  <row Id="28034" PostHistoryTypeId="2" PostId="9765" RevisionGUID="6cb31333-4c1b-4047-8d49-6cd7264892d3" CreationDate="2020-04-28T21:43:16.303" UserId="4908" Text="A bump map should **not** be linearised from sRGB, in theory.&#xD;&#xA;&#xD;&#xA;A diffuse map or photo contains colour data, which must be encoded in a colour space. Colour spaces consist of two things, a colour gamut (what kind of red is red, what kind of green is green, what kind of blue is blue and what kind of white is white) and a transfer functions (how do you allocate the limited bits, often called gamma). Without a colour space, we would not know how to interpret the data. Choosing to then simply interpret it as sRGB would just be an assumption, that could be wrong.&#xD;&#xA;&#xD;&#xA;Bump maps, roughness maps, normal maps, etc. do not contain colour data, but rather geometric data, and therefor **do not have a colour space** and no transfer function. So, the data is already linear. Another way of thinking about it, is that a transfer function is about more efficiently allocating the limited bits. Our eyes see more detail in dark areas than bright areas, so we want more of the, often, 8 bits to be for the darker areas. However, with a bump map we want the bits to be spaced out evenly. So, a transfer function wouldn't be a good idea.&#xD;&#xA;&#xD;&#xA;In some cases, a transfer function might be useful with a bump map. Maybe you have a lot of detail in a small range (between 0.0 and 0.4) but occasionally a spike to 1.0 that prevents you from scaling that small range up. You might want to have more precision in that small range and less precision in the spike because of the detail in the small range. This is perfect for a transfer function. There would still be no colour gamut, just a transfer function. Although, this doesn't happen often.&#xD;&#xA;&#xD;&#xA;In some other cases, the artist or the program might have added a transfer function without realising it or thinking that since it was an image saved as, for example, a JPEG, it would have needed the transfer function. In these cases, you must apply the inverse of the transfer function to get the original values back.&#xD;&#xA;&#xD;&#xA;In short, you should always assume, unless stated otherwise, that bump maps, roughness maps, normal maps, etc. are geometric data stored in the image file as-is and not using a transfer function. Most software that generate these maps will save them in linear.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Two irrelevant side notes:*&#xD;&#xA;*In my simple explanation of colour spaces, I assumed that we are talking about three different values for red, green and blue. However, colour data can also be encoded in different ways and you have different colour spaces to reflect that. Examples are YCbCr or YUV, CMYK, LAB and XYZ.*&#xD;&#xA;&#xD;&#xA;*People often talk about linear as if it is a colour space, however what you are just doing, when linearising, is applying the inverse transfer function. The colour gamut is still there. You still need to know what kind of red red is. If you would be linearising sRGB or Rec.709, you would be talking about (scene-)linear sRGB. But, most people will understand you anyways.*" ContentLicense="CC BY-SA 4.0" />
  <row Id="28035" PostHistoryTypeId="50" PostId="8209" RevisionGUID="5ad01cc3-792b-4637-8865-cdd2cbc1e4f3" CreationDate="2020-04-28T23:08:05.863" UserId="-1" />
  <row Id="28036" PostHistoryTypeId="2" PostId="9766" RevisionGUID="22c684a5-f493-4809-a7b0-3f247e14b777" CreationDate="2020-04-29T00:50:43.983" UserId="11058" Text="When specifying member values for a structure consisting of float values like `vec3` or `mat3`, is it guaranteed that if an integer value is passed it's going to be promoted to a float? For example if I write&#xD;&#xA;&#xD;&#xA;    vec3 var = vec3(1, 0, 0)&#xD;&#xA;&#xD;&#xA;Same when assigning an integer value to a float variable:&#xD;&#xA;&#xD;&#xA;    float var = 1&#xD;&#xA;&#xD;&#xA;Is the implicit conversion guaranteed here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28037" PostHistoryTypeId="1" PostId="9766" RevisionGUID="22c684a5-f493-4809-a7b0-3f247e14b777" CreationDate="2020-04-29T00:50:43.983" UserId="11058" Text="Implicit conversion in glsl shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="28038" PostHistoryTypeId="3" PostId="9766" RevisionGUID="22c684a5-f493-4809-a7b0-3f247e14b777" CreationDate="2020-04-29T00:50:43.983" UserId="11058" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28039" PostHistoryTypeId="2" PostId="9767" RevisionGUID="381e42e8-53e2-4d19-8e34-cc9693aef90a" CreationDate="2020-04-29T06:56:48.507" UserId="13095" Text="Yes, it is guaranteed by the GLSL language specifications ([click me][1]). Section &quot;4.1.10. Implicit Conversions&quot; says&#xD;&#xA;&#xD;&#xA;&gt; In some situations, an expression and its type will be implicitly converted to a different type. &#xD;&#xA;&#xD;&#xA;The spec shows all possible implicit conversions inside a table, also `int` -&gt; `float`. It further says:&#xD;&#xA;&#xD;&#xA;&gt; When an implicit conversion is done, it is the same conversion that would be done under explicit&#xD;&#xA;conversion, using a constructor. &#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;float a = 1;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;is equivalent to writing&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;float a = float(1);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;There is one sentence at the end of the section, that you should keep in mind:&#xD;&#xA;&#xD;&#xA;&gt; The conversions in the table above are done only as indicated by other sections of this specification.&#xD;&#xA;&#xD;&#xA;If read it correctly, it says that you can not rely on implicit conversions in any kind of instruction you might come up with. However, regarding `vec3 var = vec3(1, 0, 0)` section &quot;5.4.2. Vector and Matrix Constructors&quot; says:&#xD;&#xA;&#xD;&#xA;&gt; If the basic type (bool, int, float, or double) of a parameter to a constructor does not match the&#xD;&#xA;basic type of the object being constructed, the scalar construction rules (above) are used to convert&#xD;&#xA;the parameters&#xD;&#xA;&#xD;&#xA;So it calls the constructor `float(int)` before consuming each value.&#xD;&#xA;&#xD;&#xA;Even though both cases are explicitly backed by the language specifications, my personal advice is to never rely on implicit conversions. They can lead to subtle, hard to track bugs. Not sure how it is in GLSL, since I didn't test it, but in C++ this one:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;float a = 1 / 2; # &lt;--- this evaluates to 0.f!&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;, deeply hidden somewhere in larger calculations, has cost me several hours of debugging more than once. It gets worse if one or both values of the fraction are taken from a variable. However, in C++ I can step through the code with a nice debugger, something that is not so easily done in GLSL. So if the only reason for using implicit conversions is laziness or some sort of taste-related decision, force yourself to be explicit. It will safe you a lot of pain.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28040" PostHistoryTypeId="5" PostId="9764" RevisionGUID="72d54c86-4b19-4ba0-9b47-a807adbc59d4" CreationDate="2020-04-29T07:38:37.813" UserId="13095" Comment="Fix some typos" Text="We can not answer this question. This is important, and you need to get this info from the artist (or vice versa you need to give this info to the artist before he begins) It entirely depends on what kind of assumptions were made when the artist was working with the image.&#xD;&#xA;&#xD;&#xA;1. Was the artist working by numbers&#xD;&#xA;2. Was the artist working by eye&#xD;&#xA;3. Was the artist working with a sculpting application&#xD;&#xA;4. Was the data built from a photograph&#xD;&#xA;&#xD;&#xA;You would be right if the artist worked by number. But if the artist was working by eye, which is incredibly hard, then you would be a bit off. sRGB does not entirely match human brightness sense so you should really fiddle a bit with the exponent if this was the case. But you might as well skip this. For sculpting and baking the image is most likely to be linear already to begin with, although the profile might not reflect this. And for the photograph case depends heavily on the method.&#xD;&#xA;&#xD;&#xA;Safest bet is to do no conversion at all. But it is not really defined so strictly. Kind of the entire world of image manipulation has skipped how to tag images that arent you know display images but pure data. Who knows how it is encoded." ContentLicense="CC BY-SA 4.0" />
  <row Id="28041" PostHistoryTypeId="24" PostId="9764" RevisionGUID="72d54c86-4b19-4ba0-9b47-a807adbc59d4" CreationDate="2020-04-29T07:38:37.813" Comment="Proposed by 13095 approved by 38 edit id of 518" ContentLicense="CC BY-SA 4.0" />
  <row Id="28042" PostHistoryTypeId="5" PostId="9728" RevisionGUID="2e31c26e-8c62-44cb-ad0e-28a04cd8913e" CreationDate="2020-04-29T07:38:55.547" UserId="7462" Comment="added 102 characters in body" Text="For questions about parametric shapes, such as NURB surfaces, the parametric sphere, cylinders, etc..." ContentLicense="CC BY-SA 4.0" />
  <row Id="28043" PostHistoryTypeId="24" PostId="9728" RevisionGUID="2e31c26e-8c62-44cb-ad0e-28a04cd8913e" CreationDate="2020-04-29T07:38:55.547" Comment="Proposed by 7462 approved by 209, 38 edit id of 515" ContentLicense="CC BY-SA 4.0" />
  <row Id="28044" PostHistoryTypeId="6" PostId="9766" RevisionGUID="78c3be68-7ecb-4e0f-bf6b-18a8205bf347" CreationDate="2020-04-29T11:09:49.753" UserId="13095" Comment="Add glsl tag, since it is the scope of the question" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28045" PostHistoryTypeId="24" PostId="9766" RevisionGUID="78c3be68-7ecb-4e0f-bf6b-18a8205bf347" CreationDate="2020-04-29T11:09:49.753" Comment="Proposed by 13095 approved by 38, 11058 edit id of 517" ContentLicense="CC BY-SA 4.0" />
  <row Id="28047" PostHistoryTypeId="2" PostId="9768" RevisionGUID="3644372e-a542-4b58-9e90-1270877bdaf4" CreationDate="2020-04-29T15:21:10.107" UserId="11471" Text="I am currently using a older IntelHd Gpu which supports **Opengl3.1 (Glsl #version140)**.  &#xD;&#xA;&#xD;&#xA;While trying to locate the relevant Api for this version ,the Khronos site only provides  [documentation for Opengl2.1 and Opengl4.5][1].    &#xD;&#xA;&#xD;&#xA;On their [Github page][2] documentation for Opengl2.1 and Opengl4 is available.  &#xD;&#xA;&#xD;&#xA;How to locate the Api for Opengl 3.1?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/&#xD;&#xA;  [2]: https://github.com/KhronosGroup/OpenGL-Refpages" ContentLicense="CC BY-SA 4.0" />
  <row Id="28048" PostHistoryTypeId="1" PostId="9768" RevisionGUID="3644372e-a542-4b58-9e90-1270877bdaf4" CreationDate="2020-04-29T15:21:10.107" UserId="11471" Text="Older Api documentation" ContentLicense="CC BY-SA 4.0" />
  <row Id="28049" PostHistoryTypeId="3" PostId="9768" RevisionGUID="3644372e-a542-4b58-9e90-1270877bdaf4" CreationDate="2020-04-29T15:21:10.107" UserId="11471" Text="|opengl|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28054" PostHistoryTypeId="2" PostId="9770" RevisionGUID="1708fca1-5e99-4226-8a63-06a544af7171" CreationDate="2020-04-30T04:40:25.993" UserId="11471" Text="Older Opengl Api documentation can be found at this [ Official Khronos Registry][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/index_gl.php#oldspecs" ContentLicense="CC BY-SA 4.0" />
  <row Id="28055" PostHistoryTypeId="2" PostId="9771" RevisionGUID="033ddf38-bd6b-4da4-a48a-c6130418c757" CreationDate="2020-04-30T04:48:24.777" UserId="13284" Text="My question is : to allocate **static** mesh data (vertex/index buffers that never change), is it best :&#xD;&#xA;&#xD;&#xA; - To go the &quot;obvious&quot; way : &quot;1 mesh = 1 VBO&quot;, submitting data using glBufferData with GL_STATIC_DRAW flag.&#xD;&#xA; - To preallocate big buffers (say, a few megabytes) using glBufferStorage with a GL_DYNAMIC_STORAGE_BIT flag, and using glBufferSubData to &quot;fill&quot; the buffer with actual mesh data, side by side in the same VBO. I keep the VBO ID and offset in the VBO of every mesh.&#xD;&#xA; - Besides, to transfer data there is also the [persistent-mapped buffer][1] technique. I could map all or part of the buffer, and write to it directly (no glBufferSubData needed). I don't see the point for static data. Perhaps I'm mistaken?&#xD;&#xA;&#xD;&#xA;I implemented [a buddy allocator][2] allowing me to split an OpenGL buffer in power-of-2 blocks to follow my second alternative. It allows me to &quot;pack&quot; multiple meshes in the same VBO, and to keep reusing it as mesh allocation/deallocation occurs.&#xD;&#xA;&#xD;&#xA;It works great, but no huge speedup is observed vs. a more classic approach.&#xD;&#xA;Then reading [these slides][3] for example (especially slide 24), they're basically saying this approach isn't the efficient path except for very specific cases (uniform buffer, less than 64 kb, offsets have to be multiple of 4 !). &#xD;&#xA;&#xD;&#xA;Are there some &quot;best practices&quot; regarding buffer data management ? Is it useful to worry about it at all ?&#xD;&#xA;&#xD;&#xA;I've read tons of material regarding OpenGL buffer management lately, and now I feel a bit lost. It would be great to have a &quot;recap&quot; of all the possibilities and expected relative performance of each vs. the others.&#xD;&#xA;&#xD;&#xA;(Note : I'm targeting OpenGL 4.5, so DSA is allowed).&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object#Persistent_mapping&#xD;&#xA;  [2]: https://bitsquid.blogspot.com/2015/08/allocation-adventures-3-buddy-allocator.html&#xD;&#xA;  [3]: http://on-demand.gputechconf.com/gtc/2014/presentations/S4379-opengl-44-scene-rendering-techniques.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28056" PostHistoryTypeId="1" PostId="9771" RevisionGUID="033ddf38-bd6b-4da4-a48a-c6130418c757" CreationDate="2020-04-30T04:48:24.777" UserId="13284" Text="Best practices fo OpenGL static buffer data : what is best for performance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28057" PostHistoryTypeId="3" PostId="9771" RevisionGUID="033ddf38-bd6b-4da4-a48a-c6130418c757" CreationDate="2020-04-30T04:48:24.777" UserId="13284" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28060" PostHistoryTypeId="2" PostId="9772" RevisionGUID="6b9c9034-04bb-4194-8477-4445d24da13d" CreationDate="2020-04-30T17:17:26.210" UserId="11412" Text="I’m looking to somehow programmatically query the state of graphics during a PC gameplay session. What I mean by “state of graphics” is, how polygons, textures, lighting and any other scene elements are stored and computed for any particular frame. I’m mainly interested in what the graphics card is doing on a low level. &#xD;&#xA;&#xD;&#xA;Is there any need to be game engine specific in this matter, or will all games be drawn to the screen in the same way?&#xD;&#xA;&#xD;&#xA;I’m specifically interested in NVIDIA cards if at all possible. I’m not sure if different manufacturers do things differently, but I only have an NVIDIA card. &#xD;&#xA; &#xD;&#xA;Are there any tools or APIs that will give me access to this data? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28061" PostHistoryTypeId="1" PostId="9772" RevisionGUID="6b9c9034-04bb-4194-8477-4445d24da13d" CreationDate="2020-04-30T17:17:26.210" UserId="11412" Text="API or Tools to query state of graphics during gameplay?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28062" PostHistoryTypeId="3" PostId="9772" RevisionGUID="6b9c9034-04bb-4194-8477-4445d24da13d" CreationDate="2020-04-30T17:17:26.210" UserId="11412" Text="|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28063" PostHistoryTypeId="2" PostId="9773" RevisionGUID="55ed91ac-b70d-4d55-84ce-90f6f4139ca9" CreationDate="2020-04-30T18:44:46.837" UserId="7072" Text="For a real-time application I am trying to add glow to a few hundred points. These points are more like 2D circles of various small sizes on the screen. These points are sometimes as small as 4 pixels so they can easily disappear in lower resolutions. Previously I have done this using convolutions (gaussian blur) and have employed a variety of processes to speed things up.&#xD;&#xA;&#xD;&#xA; - Separate vertical and horizontal passes&#xD;&#xA; - Taking advantage of bilinear sampling&#xD;&#xA; - Doing the blur at a lower resolution&#xD;&#xA; - Using Metal's special kernel for it&#xD;&#xA;&#xD;&#xA;However none of these performs quite well enough. They are ok but I want to try to push further.  A few ways these methods all fail are the following&#xD;&#xA;&#xD;&#xA; - If the points cluster or overlap it doesn't look too bright. They are completely opaque and so even with additive blending it doesn't work.&#xD;&#xA; - I have to have a lower radius of blur than I would like as I tradeoff quality for blur distance.&#xD;&#xA;&#xD;&#xA;What I am looking for is to see if there are any techniques that I might be able to replace these with or add to them. One thought has been spatial data structures. I thought about splitting up the space with a BSP and then coloring squares based on how deep into the tree that square is and how many points it has in it. This has issues for the following reasons.&#xD;&#xA;&#xD;&#xA; - I don't feel like a BSP algorithm translates nicely to GPUs&#xD;&#xA; - Points on the edge of multiple partitions would be poorly represented&#xD;&#xA; - How do you even visualize on a GPU how many points are within each partition in a binary tree&#xD;&#xA;&#xD;&#xA;Do you think any part of this algorithm would translate well to GPUs?&#xD;&#xA;&#xD;&#xA;I am ok with it looking square because I can blur that or just blend it in with the existing blur. &#xD;&#xA;&#xD;&#xA;Can you think of any sorts of algorithms that might help me achieve my two goals&#xD;&#xA;&#xD;&#xA; - A bunch of points clustered close together have an aura that is very far reaching and looks brighter than just one point.&#xD;&#xA; - General portions of the screen where a lot of points are are a bit brighter" ContentLicense="CC BY-SA 4.0" />
  <row Id="28064" PostHistoryTypeId="1" PostId="9773" RevisionGUID="55ed91ac-b70d-4d55-84ce-90f6f4139ca9" CreationDate="2020-04-30T18:44:46.837" UserId="7072" Text="Visualizing clusters of points" ContentLicense="CC BY-SA 4.0" />
  <row Id="28065" PostHistoryTypeId="3" PostId="9773" RevisionGUID="55ed91ac-b70d-4d55-84ce-90f6f4139ca9" CreationDate="2020-04-30T18:44:46.837" UserId="7072" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28066" PostHistoryTypeId="4" PostId="9773" RevisionGUID="11da308b-b090-4401-ba80-73f0032afd51" CreationDate="2020-04-30T18:50:35.157" UserId="7072" Comment="edited title" Text="Visualizing auras around clusters of points" ContentLicense="CC BY-SA 4.0" />
  <row Id="28067" PostHistoryTypeId="5" PostId="9773" RevisionGUID="11da308b-b090-4401-ba80-73f0032afd51" CreationDate="2020-04-30T18:50:35.157" UserId="7072" Comment="edited title" Text="For a real-time application I am trying to add glow to a few hundred points. These points are more like 2D circles of various small sizes on the screen. &#xD;&#xA;&#xD;&#xA;These points are supposed to be like balls of light so it makes sense that they should glow and that it should be very bright when multiple are in proximity.&#xD;&#xA;&#xD;&#xA;These points are sometimes as small as 4 pixels so they can easily disappear in lower resolutions. Previously I have done this using convolutions (gaussian blur) and have employed a variety of processes to speed things up.&#xD;&#xA;&#xD;&#xA; - Separate vertical and horizontal passes&#xD;&#xA; - Taking advantage of bilinear sampling&#xD;&#xA; - Doing the blur at a lower resolution&#xD;&#xA; - Using Metal's special kernel for it&#xD;&#xA;&#xD;&#xA;However none of these performs quite well enough. They are ok but I want to try to push further.  A few ways these methods all fail are the following&#xD;&#xA;&#xD;&#xA; - If the points cluster or overlap it doesn't look too bright. They are completely opaque and so even with additive blending it doesn't work.&#xD;&#xA; - I have to have a lower radius of blur than I would like as I tradeoff quality for blur distance.&#xD;&#xA;&#xD;&#xA;What I am looking for is to see if there are any techniques that I might be able to replace these with or add to them. One thought has been spatial data structures. I thought about splitting up the space with a BSP and then coloring squares based on how deep into the tree that square is and how many points it has in it. This has issues for the following reasons.&#xD;&#xA;&#xD;&#xA; - I don't feel like a BSP algorithm translates nicely to GPUs&#xD;&#xA; - Points on the edge of multiple partitions would be poorly represented&#xD;&#xA; - How do you even visualize on a GPU how many points are within each partition in a binary tree&#xD;&#xA;&#xD;&#xA;Do you think any part of this algorithm would translate well to GPUs?&#xD;&#xA;&#xD;&#xA;I am ok with it looking square because I can blur that or just blend it in with the existing blur. &#xD;&#xA;&#xD;&#xA;Can you think of any sorts of algorithms that might help me achieve my two goals&#xD;&#xA;&#xD;&#xA; - A bunch of points clustered close together have an aura that is very far reaching and looks brighter than just one point.&#xD;&#xA; - General portions of the screen where a lot of points are are a bit brighter" ContentLicense="CC BY-SA 4.0" />
  <row Id="28068" PostHistoryTypeId="2" PostId="9774" RevisionGUID="6e37011b-69b2-42d4-bfe4-91faea14e061" CreationDate="2020-04-30T21:07:18.510" UserId="6041" Text="I have few questions regarding tone-mapping and gamma correction.&#xD;&#xA;&#xD;&#xA;1. is a tone-mapping operator a function whose output is a value between [0,1] ?&#xD;&#xA;If this isn't the case and since gamma encoding requires a value to be in range [0,1], do I need to normalize the values after tone-mapping?&#xD;&#xA;&#xD;&#xA;2. imagine a diffuse horizontal surface with (0.5,0.5,0.5) reflectance under an unobstructed uniform sky of radiance (1,1,1) cd/m2. The incident radiance on an image pixel coming off this surface will have value of (0.5,0.5,0.5). Now, most codes I have seen apply gamma encoding(raising pxl value to the power of 0.45) at this stage just before saving it to the file. But on viewing the image, the colors are distorted and much brighter corresponding to (186,186,186) color value. If I don't apply gamma encoding then the image file displays the expected color that is (127,127,127).&#xD;&#xA;&#xD;&#xA;If the CRT monitor or the LCD does apply the inverse of gamma, then by encoding it I must see the original color that is (127,127,127), is that right? &#xD;&#xA;And if I am seeing (186,186,186) instead, am I right therefore to assume the encoding happens internally on saving the image data as png or jpg format? and therefore I don't need to do any gamma encoding? " ContentLicense="CC BY-SA 4.0" />
  <row Id="28069" PostHistoryTypeId="1" PostId="9774" RevisionGUID="6e37011b-69b2-42d4-bfe4-91faea14e061" CreationDate="2020-04-30T21:07:18.510" UserId="6041" Text="Few questions on Gamma correction and Tonemapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="28070" PostHistoryTypeId="3" PostId="9774" RevisionGUID="6e37011b-69b2-42d4-bfe4-91faea14e061" CreationDate="2020-04-30T21:07:18.510" UserId="6041" Text="|rendering|gamma|tone|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28071" PostHistoryTypeId="4" PostId="9774" RevisionGUID="f46744c1-5fa9-46c3-b216-7e3b13a6a65c" CreationDate="2020-04-30T21:32:21.820" UserId="6041" Comment="edited title" Text="Two questions on Gamma correction and Tonemapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="28072" PostHistoryTypeId="2" PostId="9775" RevisionGUID="2546ee62-417e-46d8-9de0-7fb9b1fbf5d2" CreationDate="2020-05-01T02:31:03.460" UserId="2654" Text="&gt; the colors are distorted and much brighter corresponding to (186,186,186) color value. If I don't apply gamma encoding then the image file displays the expected color that is (127,127,127).&#xD;&#xA;&#xD;&#xA;No, the gamma-correct color is not distorted; your *expectations* are. If your lighting, meshes, textures, and other scene elements were not built to be properly linear and gamma correct to the screen, then every decision you have made has been through a distorted lens. If you don't like the effect you're getting with a properly gamma-correct lighting system, that's the fault of all of those decisions you've been making, not with gamma correction.&#xD;&#xA;&#xD;&#xA;Half of the full lighting intensity in a linear colorspace does correspond to greater than half in a gamma-correct colorspace. And those gamma-correct values are what you *ought* to be passing to the screen. If that's not what you're shoving into the display, then you're doing lighting wrong." ContentLicense="CC BY-SA 4.0" />
  <row Id="28073" PostHistoryTypeId="2" PostId="9776" RevisionGUID="799944cf-e693-4f0d-ae1d-82b8595c274f" CreationDate="2020-05-01T09:39:36.947" UserId="13290" Text="I know that 3D artists make a 3D model with quads. And they advise to remesh with quads only (if it's possible).&#xD;&#xA;&#xD;&#xA;So I have some questions:&#xD;&#xA;&#xD;&#xA;1. Why do we use quads in CG (for games, cartoons, film, etc) if the graphic card (or render, I'm not sure) convert quads to tris all the same?&#xD;&#xA;2. Why many 3D apps (Max, Blender, Maya, etc) have a triangulate function? Eventually, the graphic card (or render) does that.&#xD;&#xA;&#xD;&#xA;I want to clarify this question for myself since I know it incompletely." ContentLicense="CC BY-SA 4.0" />
  <row Id="28074" PostHistoryTypeId="1" PostId="9776" RevisionGUID="799944cf-e693-4f0d-ae1d-82b8595c274f" CreationDate="2020-05-01T09:39:36.947" UserId="13290" Text="What tris and quads need for?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28075" PostHistoryTypeId="3" PostId="9776" RevisionGUID="799944cf-e693-4f0d-ae1d-82b8595c274f" CreationDate="2020-05-01T09:39:36.947" UserId="13290" Text="|3d|mesh|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28076" PostHistoryTypeId="2" PostId="9777" RevisionGUID="f635c30f-300f-48f0-b852-82f3cf3d614c" CreationDate="2020-05-01T10:21:40.307" UserId="13095" Text="&gt; What I mean by “state of graphics” is, how polygons, textures, lighting and any other scene elements are stored and computed for any particular frame.&#xD;&#xA;&#xD;&#xA;The closest to what you are asking and that I know of is [RenderDoc](https://renderdoc.org/). I have not tested it myself so far, but some [features they list in their documentation](https://renderdoc.org/docs/getting_started/features.html) that are related to your question are:&#xD;&#xA;&#xD;&#xA;- Full graphics pipeline state display&#xD;&#xA;- Shader source display&#xD;&#xA;- Flexible resource inspector&#xD;&#xA;- Mesh buffer inspection and visualisation&#xD;&#xA;- ‘Raw’ buffer inspection for buffers&#xD;&#xA;- Texture/render target viewer&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; I’m looking to somehow programmatically query the state of graphics during a PC gameplay session.&#xD;&#xA; &#xD;&#xA;&gt;...&#xD;&#xA;&#xD;&#xA;&gt; Is there any need to be game engine specific in this matter, or will all games be drawn to the screen in the same way?&#xD;&#xA;&#xD;&#xA;I am not sure here if you are asking to dissect the graphics state of a commercial game or software that is not written by yourself. If so, there is no guarantee that RenderDoc can capture data but it is possible. See for example [this issue on their GitHub page](https://github.com/baldurk/renderdoc/issues/666), where the author says:&#xD;&#xA;&#xD;&#xA;&gt; However I want to be clear that I cannot and do not support capturing 3rd party programs that you do not control. **It generally works** but for obvious reasons I don't provide any help with problems...&#xD;&#xA;&#xD;&#xA;As stated in [this section of their documentation](https://renderdoc.org/docs/behind_scenes/how_works.html), RenderDoc uses a &quot;man-in-the-middle&quot; approach to get the data. So it intercepts any calls to the graphics API (OpenGL, DirectX, Vulkan) of the executed program, gathers the data it needs, and passes it along to the API afterward." ContentLicense="CC BY-SA 4.0" />
  <row Id="28077" PostHistoryTypeId="2" PostId="9778" RevisionGUID="17d629e5-d2f7-4830-8e01-f2a351444144" CreationDate="2020-05-01T10:43:12.487" UserId="38" Text="1. Because the geometry will be subdivided into quads. Anyway the primary reason for this is if you have a function with 2 directions it is easer for humans to think it out andcanticipate results if its a quad.&#xD;&#xA;&#xD;&#xA;    Software renderers dont have to rely on triangles. And did not for a long time.&#xD;&#xA;&#xD;&#xA;    For more on this read [this post](https://computergraphics.stackexchange.com/questions/5465/why-are-quads-used-in-filmmaking-and-triangle-in-gaming)&#xD;&#xA;&#xD;&#xA;2. You might want to control the triangulation yourself. Interpolation does not happen the same way regardless of how the triangles are laid out. So being able to triangulate and then flip offending triangles is useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="28078" PostHistoryTypeId="16" PostId="9778" RevisionGUID="17d629e5-d2f7-4830-8e01-f2a351444144" CreationDate="2020-05-01T10:43:12.487" UserId="38" />
  <row Id="28079" PostHistoryTypeId="5" PostId="9778" RevisionGUID="11275b58-a4c1-470e-adaa-23481c2d2994" CreationDate="2020-05-01T10:50:59.113" UserId="38" Comment="added 99 characters in body" Text="1. Because the geometry will be subdivided into quads. Anyway the primary reason for this is if you have a function with 2 directions it is easer for humans to think it out andcanticipate results if its a quad.&#xD;&#xA;&#xD;&#xA;    Software renderers dont have to rely on triangles. And did not for a long time. But then if you microdice your surface who cares its not like you can see the micropolygon anyway.&#xD;&#xA;&#xD;&#xA;    For more on this read [this post](https://computergraphics.stackexchange.com/questions/5465/why-are-quads-used-in-filmmaking-and-triangle-in-gaming)&#xD;&#xA;&#xD;&#xA;2. You might want to control the triangulation yourself. Interpolation does not happen the same way regardless of how the triangles are laid out. So being able to triangulate and then flip offending triangles is useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="28087" PostHistoryTypeId="2" PostId="9780" RevisionGUID="9bb71cd0-2a39-43d9-9132-7e06df0df7d3" CreationDate="2020-05-02T20:29:00.643" UserId="7512" Text="Found a solution. &#xD;&#xA;&#xD;&#xA;In the vertex shader I project position from model to the clip-space, then from clip-space to screen space, adjust the width in screen pixels, and the project back to clip-space, which ultimately becomes `gl_Position` value." ContentLicense="CC BY-SA 4.0" />
  <row Id="28088" PostHistoryTypeId="2" PostId="9781" RevisionGUID="2e3628b6-18ea-49f1-b7ec-2afddbcf41c4" CreationDate="2020-05-02T23:47:23.653" UserId="13298" Text="I am doing some project on object reconstruction and I need to rotate object in PyTorch while training to make sure I am augmenting data properly. My data consists of points and it's normals. My question is, how should I (or should I traing them at all) rotate normals of my mesh. Note that this rotation also needs to keep object in unit cube, where it was  before running this  code. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28089" PostHistoryTypeId="1" PostId="9781" RevisionGUID="2e3628b6-18ea-49f1-b7ec-2afddbcf41c4" CreationDate="2020-05-02T23:47:23.653" UserId="13298" Text="Rotation of meshes in PyTorch" ContentLicense="CC BY-SA 4.0" />
  <row Id="28090" PostHistoryTypeId="3" PostId="9781" RevisionGUID="2e3628b6-18ea-49f1-b7ec-2afddbcf41c4" CreationDate="2020-05-02T23:47:23.653" UserId="13298" Text="|3d|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28094" PostHistoryTypeId="2" PostId="9783" RevisionGUID="5c35d858-f6e1-4ad9-bc30-9092f1fc25ab" CreationDate="2020-05-03T09:29:27.763" UserId="13095" Text="&gt; My question is, how should I (...) rotate normals of my mesh.&#xD;&#xA;&#xD;&#xA;Normals are rotated the same way as the rest of your mesh/point cloud. But make sure that you use a &quot;pure rotation matrix&quot; for this (no scaling, no translation). Since rotations preserve lengths, you do not need to renormalize your normals (usually - floating-point errors might accumulate).&#xD;&#xA;&#xD;&#xA;This sentence of you&#xD;&#xA;&#xD;&#xA;&gt; Note that this rotation also needs to keep object in unit cube, where it was before running this code.&#xD;&#xA;&#xD;&#xA;lets me guess, that you are actually asking how to rotate an object and its normals and not just the normals. In python, you can use the packages SciPy and NumPy for that.&#xD;&#xA;&#xD;&#xA;The Rotation package ([documentation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.html)) of SciPy helps you to generate an arbitrary rotation matrix. Then you can use NumPys `matmul` function to rotate your points and normals.&#xD;&#xA;&#xD;&#xA;Here is a short example script that rotates a single point 20 degrees around the z axis:&#xD;&#xA;&#xD;&#xA;~~~ python&#xD;&#xA;from scipy.spatial.transform import Rotation as Rot&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;p = np.array([1, 1, 0]).transpose()&#xD;&#xA;rot_mat = Rot.from_euler(seq=&quot;z&quot;, angles=20, degrees=True).as_matrix()&#xD;&#xA;&#xD;&#xA;p_r = np.matmul(rot_mat, p)&#xD;&#xA;&#xD;&#xA;print(p)&#xD;&#xA;print(p_r)&#xD;&#xA;print(np.linalg.norm(p))&#xD;&#xA;print(np.linalg.norm(p_r))&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;output:&#xD;&#xA;&#xD;&#xA;~~~&#xD;&#xA;[1 1 0]&#xD;&#xA;[0.59767248 1.28171276 0.        ]&#xD;&#xA;1.4142135623730951&#xD;&#xA;1.414213562373095&#xD;&#xA;~~~&#xD;&#xA;&gt; **Info:** Depending on your SciPy version you might need to replace `as_matrix` with `as_dcm`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, apart from some minor floating-point error, the length (last 2 outputs) did not change. Furthermore, I chose the example point, so that it gets outside the unit cube. To address this problem, you need to find the maximum absolute value inside the transformed data. You can use `amax` and `amin` to get the maximum and minimum value ([see also here](https://stackoverflow.com/questions/55284090/how-to-find-max-value-in-2d-array-with-index)) if you put all your coordinates into one large 2d array (a matrix). Then compare the absolute values of the `amax` and `amin` results and pick the larger one. Divide all your coordinates (not the normals!) by this value, to scale your model back into the unit cube. Alternatively, you can create a uniform scaling matrix&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;s&amp;0&amp;0\\&#xD;&#xA;0&amp;s&amp;0\\&#xD;&#xA;0&amp;0&amp;s&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with $s$ being the reciprocal of the maximum absolute value. Multiply this matrix with all points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To sum it up:&#xD;&#xA;&#xD;&#xA;- calculate the rotation matrix with SciPy&#xD;&#xA;- Multiply the rotation matrix with all points and normals&#xD;&#xA;- find the maximum absolute value in the rotated data&#xD;&#xA;- scale your coordinates with the found maximum value&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Remark:** If you put your points and normals into 2 matrices, you can apply the rotations and scaling matrices without a loop, which makes it much faster.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28095" PostHistoryTypeId="2" PostId="9784" RevisionGUID="ab60f7a0-fa7f-4996-8870-a9955dddbdd7" CreationDate="2020-05-03T13:33:59.533" UserId="8796" Text="OpenGL 4.5 reference pages have tables at the bottom of each page indicating in which version particular function was added. For example, if you look at [glTexStorage2D][1], you can see that it was introduced in 4.2, while its DSA equivalent in 4.5.&#xA;&#xA;I think that the reason for having separate pages for 2.1 and 4.5 is that the former includes legacy functions, while the latter has only core profile functions.&#xA;&#xA;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage2D.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="28096" PostHistoryTypeId="2" PostId="9785" RevisionGUID="0115bd5a-ee4c-4116-bf1b-128b8faa8002" CreationDate="2020-05-03T22:03:13.743" UserDisplayName="user13304" Text="I'm currently passing an array of bone positions to GLSL for a skeletal animation shader; the positions are passing successfully but producing a GL_INVALID_OPERATION error.&#xD;&#xA;&#xD;&#xA;I'm passing the matrices in the following line:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;std::vector&lt;glm::mat4x4&gt; bpos;&#xD;&#xA;...&#xD;&#xA;glUniformMatrix4fv(shader.uniform(&quot;bpos&quot;), 50, GL_FALSE, &amp;bpos.at(0)[0][0]);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Where the `shader.uniform(&quot;bpos&quot;)` position has been assigned earlier as:&#xD;&#xA;&#xD;&#xA;```this-&gt;m_uniforms[&quot;bpos&quot;] = glGetUniformLocation(this-&gt;m_program, &quot;uniform_bpos&quot;);```&#xD;&#xA;&#xD;&#xA;I'm getting the following output:&#xD;&#xA;&#xD;&#xA;```GL CALLBACK: ** GL ERROR ** type = 0x824c, severity = 0x9146, message = GL_INVALID_OPERATION in glUniform3(uniform &quot;uniform_bpos&quot;@1 is matrix)```&#xD;&#xA;&#xD;&#xA;Has anyone here encountered this error or does anyone here see what I'm doing incorrectly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28097" PostHistoryTypeId="1" PostId="9785" RevisionGUID="0115bd5a-ee4c-4116-bf1b-128b8faa8002" CreationDate="2020-05-03T22:03:13.743" UserDisplayName="user13304" Text="Passing mat4 array to GLSL succeeding but producing GL_INVALID_OPERATION" ContentLicense="CC BY-SA 4.0" />
  <row Id="28098" PostHistoryTypeId="3" PostId="9785" RevisionGUID="0115bd5a-ee4c-4116-bf1b-128b8faa8002" CreationDate="2020-05-03T22:03:13.743" UserDisplayName="user13304" Text="|opengl|glsl|c++|uniform-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28102" PostHistoryTypeId="6" PostId="9785" RevisionGUID="4c73547e-fc57-44ae-9d23-4059befaafee" CreationDate="2020-05-04T04:55:24.027" UserDisplayName="user13304" Comment="edited tags" Text="|opengl|glsl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28104" PostHistoryTypeId="2" PostId="9788" RevisionGUID="7d0f079b-60ec-4660-b404-8ceece781635" CreationDate="2020-05-04T11:58:23.597" UserId="13298" Text="I am just trying to rotate my pointcloud object which is inside the unit cube ([-1,1] in all x,y,z axis). What I did is use the basic rotation matrix from [wiki][1] and extend it to homogenuous 4x4 matrix (with 0 everywhere in 4th row and 4th column except in [4,4] position where  I put 1). When I did multiplication of object by rotation matrix and normalized points by their 4th value like this:  $$(x,y,z,k) -&gt; (x/k,y/k,z/k, 1)$$&#xD;&#xA;I see that my pointcloud object is no longer inside the unit cube and since I know that rotation is shape and length preserving transformation, I want to know how can I shift my pointcloud object back to unit cube in a way it is centered in (0,0,0) as before.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations" ContentLicense="CC BY-SA 4.0" />
  <row Id="28105" PostHistoryTypeId="1" PostId="9788" RevisionGUID="7d0f079b-60ec-4660-b404-8ceece781635" CreationDate="2020-05-04T11:58:23.597" UserId="13298" Text="Does rotating object inside unit cube [-1,1] by homogenous matrix move it outside unit cube" ContentLicense="CC BY-SA 4.0" />
  <row Id="28106" PostHistoryTypeId="3" PostId="9788" RevisionGUID="7d0f079b-60ec-4660-b404-8ceece781635" CreationDate="2020-05-04T11:58:23.597" UserId="13298" Text="|transformations|projections|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28107" PostHistoryTypeId="5" PostId="9785" RevisionGUID="815d6b86-86bf-488a-b12a-d235d585e58e" CreationDate="2020-05-04T15:21:54.177" UserDisplayName="user13304" Comment="Include more code for context" Text="I'm currently passing an array of bone positions to GLSL for a skeletal animation shader; the positions are passing successfully but producing a GL_INVALID_OPERATION error.&#xD;&#xA;&#xD;&#xA;I'm passing the matrices in the following line:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;std::vector&lt;glm::mat4x4&gt; bpos;&#xD;&#xA;...&#xD;&#xA;glUniformMatrix4fv(shader.uniform(&quot;bpos&quot;), 50, GL_FALSE, &amp;bpos.at(0)[0][0]);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Where the `shader.uniform(&quot;bpos&quot;)` position has been assigned earlier as:&#xD;&#xA;&#xD;&#xA;```this-&gt;m_uniforms[&quot;bpos&quot;] = glGetUniformLocation(this-&gt;m_program, &quot;uniform_bpos&quot;);```&#xD;&#xA;&#xD;&#xA;I'm getting the following output:&#xD;&#xA;&#xD;&#xA;```GL CALLBACK: ** GL ERROR ** type = 0x824c, severity = 0x9146, message = GL_INVALID_OPERATION in glUniform3(uniform &quot;uniform_bpos&quot;@1 is matrix)```&#xD;&#xA;&#xD;&#xA;Has anyone here encountered this error or does anyone here see what I'm doing incorrectly?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;The vertex shader:&#xD;&#xA;```&#xD;&#xA;#version 330 core&#xD;&#xA;&#xD;&#xA;layout(location = 0) in vec3 vert_ms;&#xD;&#xA;layout(location = 1) in vec3 norm_ms;&#xD;&#xA;layout(location = 2) in ivec4 bone_ids;&#xD;&#xA;layout(location = 3) in vec4 bone_weights;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;out vec3 norm_ws;&#xD;&#xA;out vec3 pos_ws;&#xD;&#xA;&#xD;&#xA;uniform mat4 uniform_mvp;&#xD;&#xA;uniform mat4 uniform_bpos[50];&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;     mat4 bone = uniform_bpos[bone_ids[0]] * bone_weights[0];&#xD;&#xA;     bone += uniform_bpos[bone_ids[1]] * bone_weights[1];&#xD;&#xA;     bone += uniform_bpos[bone_ids[2]] * bone_weights[2];&#xD;&#xA;     bone += uniform_bpos[bone_ids[3]] * bone_weights[3];&#xD;&#xA;&#xD;&#xA;     gl_Position = uniform_mvp * bone * vec4(vert_ms, 1);&#xD;&#xA;     norm_ws = (uniform_mvp * bone * vec4 (norm_ms, 0)).xyz;&#xD;&#xA;     pos_ws = vec3(gl_Position);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;the function getting the uniform locations:&#xD;&#xA;```&#xD;&#xA;Shader::Shader(GLuint shader_program)&#xD;&#xA;{&#xD;&#xA;  this-&gt;m_program = shader_program;&#xD;&#xA;&#xD;&#xA;  this-&gt;m_uniforms[&quot;mvp&quot;] = glGetUniformLocation(this-&gt;m_program, &quot;uniform_mvp&quot;);&#xD;&#xA;  this-&gt;m_uniforms[&quot;bpos&quot;] = glGetUniformLocation(this-&gt;m_program, &quot;uniform_bpos&quot;);&#xD;&#xA;  this-&gt;m_uniforms[&quot;eye&quot;] = glGetUniformLocation(this-&gt;m_program, &quot;uniform_eye&quot;);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;from this file: https://github.com/EricJIsaac/opengl-engine/blob/feature/pb-materials/src/graphics/shader.cpp&#xD;&#xA;&#xD;&#xA;uploading the vertex data:&#xD;&#xA;```&#xD;&#xA;void SkeletonMeshBuffer::predraw()&#xD;&#xA;{&#xD;&#xA;  glEnableVertexAttribArray(0);&#xD;&#xA;  glEnableVertexAttribArray(1);&#xD;&#xA;  glEnableVertexAttribArray(2);&#xD;&#xA;  glEnableVertexAttribArray(3);&#xD;&#xA;  glBindBuffer(GL_ARRAY_BUFFER, this-&gt;m_vbo);&#xD;&#xA;&#xD;&#xA;  // Vertices&#xD;&#xA;  std::size_t stride = sizeof(graphics::data::SkeletonMesh_Vertex);&#xD;&#xA;  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);&#xD;&#xA;&#xD;&#xA;  // Normals&#xD;&#xA;  char* offset = (char*)0 + 3 * sizeof(float);&#xD;&#xA;  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, stride, (void*)offset);&#xD;&#xA;&#xD;&#xA;  // Bone Ids&#xD;&#xA;  offset = (char*)0 + 6 * sizeof(float);&#xD;&#xA;  glVertexAttribIPointer(2, 4, GL_UNSIGNED_SHORT, stride, (void*)offset);&#xD;&#xA;&#xD;&#xA;  // Bone Weights&#xD;&#xA;  offset = (char*)0 + 6 * sizeof(float) + 4 * sizeof(unsigned short);&#xD;&#xA;  glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, stride, (void*)offset);&#xD;&#xA;&#xD;&#xA;  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this-&gt;m_ele);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void SkeletonMeshBuffer::draw(std::size_t id)&#xD;&#xA;{&#xD;&#xA;  if(id &lt; 0 || id &gt; this-&gt;m_entries.size())&#xD;&#xA;  {&#xD;&#xA;    printf(&quot;Invalid skeleton mesh id %lu requested\n&quot;, id);&#xD;&#xA;    return;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  char* offset = (char*)0 +&#xD;&#xA;    this-&gt;m_entries[id].index_offset * sizeof(unsigned short);&#xD;&#xA;&#xD;&#xA;  glDrawElementsBaseVertex(&#xD;&#xA;    GL_TRIANGLES,&#xD;&#xA;    this-&gt;m_entries[id].index_count,&#xD;&#xA;    GL_UNSIGNED_SHORT,&#xD;&#xA;    (void*)offset,&#xD;&#xA;    this-&gt;m_entries[id].vertex_offset / 3);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void SkeletonMeshBuffer::postdraw()&#xD;&#xA;{&#xD;&#xA;    glDisableVertexAttribArray(0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;from this file: https://github.com/EricJIsaac/opengl-engine/blob/feature/pb-materials/src/graphics/skeleton_mesh_buffer.cpp&#xD;&#xA;&#xD;&#xA;The meshes being loaded:&#xD;&#xA;https://github.com/EricJIsaac/opengl-engine/tree/master/data/geometry/skeletonMeshes" ContentLicense="CC BY-SA 4.0" />
  <row Id="28108" PostHistoryTypeId="5" PostId="9781" RevisionGUID="2ed1405d-1211-4843-9cc1-87a063cd49de" CreationDate="2020-05-04T15:38:18.340" UserId="13095" Comment="Correct some grammar" Text="I am doing some project on object reconstruction and I need to rotate an object in PyTorch during the training to make sure I am augmenting the data properly. My data consists of points and it's normals. My question is, how should I (or should I train them at all) rotate the normals of my mesh. Note that this rotation also needs to keep the object inside the unit cube, where it was before the transformation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28109" PostHistoryTypeId="24" PostId="9781" RevisionGUID="2ed1405d-1211-4843-9cc1-87a063cd49de" CreationDate="2020-05-04T15:38:18.340" Comment="Proposed by 13095 approved by 5717, 209 edit id of 521" ContentLicense="CC BY-SA 4.0" />
  <row Id="28110" PostHistoryTypeId="2" PostId="9789" RevisionGUID="c2727b16-78b9-44c6-b4f0-2a9b458c730e" CreationDate="2020-05-04T18:36:24.323" UserId="13273" Text="I have three quaternions A, B, C.&#xD;&#xA;&#xD;&#xA;I also have a 3D vector P which describes the barycentric coordinate to interpolate.&#xD;&#xA;&#xD;&#xA;I want to interpolate the three quaternions with respect to the barycentric coordinate P&#xD;&#xA;&#xD;&#xA;This Image shows how to do it would A, B and C be usual vectors.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tz13g.png&#xD;&#xA;&#xD;&#xA;but how to calculate the quaternion interpolation?&#xD;&#xA;Can I use the &quot;slerp&quot; command somehow?&#xD;&#xA;How would the glm code look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28111" PostHistoryTypeId="1" PostId="9789" RevisionGUID="c2727b16-78b9-44c6-b4f0-2a9b458c730e" CreationDate="2020-05-04T18:36:24.323" UserId="13273" Text="Three quaternions interpolation with barycentric coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="28112" PostHistoryTypeId="3" PostId="9789" RevisionGUID="c2727b16-78b9-44c6-b4f0-2a9b458c730e" CreationDate="2020-05-04T18:36:24.323" UserId="13273" Text="|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28116" PostHistoryTypeId="2" PostId="9791" RevisionGUID="f3646e32-a919-4b96-b965-cafc76fa4c73" CreationDate="2020-05-04T22:23:31.167" UserId="13309" Text="I am trying to implement a simple raytracer in python. [I am following this tutorial here][1] &#xD;&#xA;&#xD;&#xA;here is my code, i have explained in comments the relevant parts .All i am getting is a black image. I  don't want someone else to debug this for me, just a pointer on where to look might help.       &#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/basic-ray-tracing.html&#xD;&#xA; &#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;            self.img = [[None]*width]*height&#xD;&#xA;    &#xD;&#xA;        def pixel(self, x, y, color):&#xD;&#xA;            self.img[x][y] = color&#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            print(self.img)&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;                f.write(f'P3\n {self.width} {self.height}\n255\n')&#xD;&#xA;                for y in range(self.height):&#xD;&#xA;                    for x in range(self.width):&#xD;&#xA;                        if self.img[y][x] is not None:&#xD;&#xA;                            color = self.__rescale(self.img[y][x])&#xD;&#xA;                            f.write(f'{color.x} {color.y} {color.z}  ')&#xD;&#xA;                    f.write('\n')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Vec3:&#xD;&#xA;        def __init__(self, x, y, z):&#xD;&#xA;    &#xD;&#xA;            self.x = x&#xD;&#xA;            self.y = y&#xD;&#xA;            self.z = z&#xD;&#xA;    &#xD;&#xA;        def __str__(self):&#xD;&#xA;            return f'Vec3({self.x},{self.y},{self.z})'&#xD;&#xA;    &#xD;&#xA;        def __sub__(self, other):&#xD;&#xA;            return Vec3(self.x - other.x , self.y - other.y , self.z - other.z)&#xD;&#xA;    &#xD;&#xA;        def __add__(self, other):&#xD;&#xA;            return Vec3(self.x +  other.x , self.y + other.y , self.z + other.z)&#xD;&#xA;    &#xD;&#xA;        def mag(self):&#xD;&#xA;            return math.sqrt(self.x**2, self.y**2, self.z**2)&#xD;&#xA;    &#xD;&#xA;        def dot(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return self.x * other.x + self.y * other.y + self.z * other.z&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3')&#xD;&#xA;    &#xD;&#xA;        def cross(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return Vec3( self.y* other.z - self.x* other.y, self.z* other.x - self.x* other.z , self.x * self.y - self.y * self.x)&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def trace_ray(O, D, t_min, t_max):&#xD;&#xA;        closest_t = 'inf'&#xD;&#xA;        closest_sphere = None&#xD;&#xA;    &#xD;&#xA;        for sphere in scene['spheres']:&#xD;&#xA;            t1, t2 = ray_sphere_intersect(O, D, sphere)&#xD;&#xA;            if t1 in [t_min, t_max] and t1 &lt; closest_t:&#xD;&#xA;                closest_t  = t1&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;            if t2 in [t_min, t_max] and t2 &lt; closest_t:&#xD;&#xA;                closest_t = t2&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;        if closest_sphere == None:&#xD;&#xA;            return Vec3(255,255,255)&#xD;&#xA;        else:&#xD;&#xA;            return closest_sphere['color']&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def dot(v1, v2):&#xD;&#xA;        return v1.x* v2.x + v1.y * v2.y + v1.z * v2.z&#xD;&#xA;    &#xD;&#xA;    def ray_sphere_intersect(O, D, sphere):&#xD;&#xA;        C = sphere['center']&#xD;&#xA;        r = sphere['radius']&#xD;&#xA;    &#xD;&#xA;        oc = O - C&#xD;&#xA;        k1 = dot(D,D)&#xD;&#xA;        k2 = 2*dot(oc, D)&#xD;&#xA;        k3 = dot(oc, oc) - r*r&#xD;&#xA;    &#xD;&#xA;        discriminant = k2*k2 - 4*k1*k3&#xD;&#xA;    &#xD;&#xA;        if discriminant &lt; 0:&#xD;&#xA;            return 'inf', 'inf'&#xD;&#xA;    &#xD;&#xA;        t1 = (-k2 + math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        t2 = (-k2 - math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        return t1, t2&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def canvas_to_viewport(x,y):&#xD;&#xA;        return Vec3(x*Vw/Cw, y*Vh/Ch, d)&#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;    &#xD;&#xA;        Cw = 200 # canvas width&#xD;&#xA;        Ch = 100 # canvas height&#xD;&#xA;        O = Vec3(0,0,0) # origin of camera&#xD;&#xA;        Vw = 1 # viewport width&#xD;&#xA;        Vh = 1 # viewport height&#xD;&#xA;        d = 1  # projection plane&#xD;&#xA;    &#xD;&#xA;        # define a PPM  image with width &amp; height equal to Canvas width &amp; canvas height respectively&#xD;&#xA;        image = P3Image(Cw,Ch)&#xD;&#xA;    &#xD;&#xA;        # define scene with one sphere&#xD;&#xA;        scene = {&#xD;&#xA;                'spheres':[&#xD;&#xA;                        {&#xD;&#xA;                        'center':Vec3(0,-1 ,3),&#xD;&#xA;                        'radius': 1,&#xD;&#xA;                        'color':Vec3(1,0,0)&#xD;&#xA;                        }&#xD;&#xA;                    ]&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;        for x in range(-Cw//2 , Cw//2):&#xD;&#xA;            for y in range(-Ch//2 , Ch//2):&#xD;&#xA;                D = canvas_to_viewport(x,y)&#xD;&#xA;                color = trace_ray(O,D,1,'inf')&#xD;&#xA;                print(x,y, color)&#xD;&#xA;                image.pixel(x,y, color)&#xD;&#xA;    &#xD;&#xA;        image.save('ii.ppm')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28117" PostHistoryTypeId="1" PostId="9791" RevisionGUID="f3646e32-a919-4b96-b965-cafc76fa4c73" CreationDate="2020-05-04T22:23:31.167" UserId="13309" Text="a very simple raytracer is giving a black output which is implemented in python" ContentLicense="CC BY-SA 4.0" />
  <row Id="28118" PostHistoryTypeId="3" PostId="9791" RevisionGUID="f3646e32-a919-4b96-b965-cafc76fa4c73" CreationDate="2020-05-04T22:23:31.167" UserId="13309" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28119" PostHistoryTypeId="5" PostId="9791" RevisionGUID="99c023c4-30a6-4121-87c4-f702f3bb48db" CreationDate="2020-05-04T22:32:26.790" UserId="13309" Comment="chnage 'inf' to math.inf" Text="I am trying to implement a simple raytracer in python. [I am following this tutorial here][1] &#xD;&#xA;&#xD;&#xA;here is my code, i have explained in comments the relevant parts .All i am getting is a black image. I  don't want someone else to debug this for me, just a pointer on where to look might help.       &#xD;&#xA;&#xD;&#xA;i think its because this condition is always evaluating to true?&#xD;&#xA;&#xD;&#xA;    if closest_sphere == None:&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Program&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/basic-ray-tracing.html&#xD;&#xA; &#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;            self.img = [[None]*width]*height&#xD;&#xA;    &#xD;&#xA;        def pixel(self, x, y, color):&#xD;&#xA;            self.img[x][y] = color&#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            print(self.img)&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;                f.write(f'P3\n {self.width} {self.height}\n255\n')&#xD;&#xA;                for y in range(self.height):&#xD;&#xA;                    for x in range(self.width):&#xD;&#xA;                        if self.img[y][x] is not None:&#xD;&#xA;                            color = self.__rescale(self.img[y][x])&#xD;&#xA;                            f.write(f'{color.x} {color.y} {color.z}  ')&#xD;&#xA;                    f.write('\n')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Vec3:&#xD;&#xA;        def __init__(self, x, y, z):&#xD;&#xA;    &#xD;&#xA;            self.x = x&#xD;&#xA;            self.y = y&#xD;&#xA;            self.z = z&#xD;&#xA;    &#xD;&#xA;        def __str__(self):&#xD;&#xA;            return f'Vec3({self.x},{self.y},{self.z})'&#xD;&#xA;    &#xD;&#xA;        def __sub__(self, other):&#xD;&#xA;            return Vec3(self.x - other.x , self.y - other.y , self.z - other.z)&#xD;&#xA;    &#xD;&#xA;        def __add__(self, other):&#xD;&#xA;            return Vec3(self.x +  other.x , self.y + other.y , self.z + other.z)&#xD;&#xA;    &#xD;&#xA;        def mag(self):&#xD;&#xA;            return math.sqrt(self.x**2, self.y**2, self.z**2)&#xD;&#xA;    &#xD;&#xA;        def dot(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return self.x * other.x + self.y * other.y + self.z * other.z&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3')&#xD;&#xA;    &#xD;&#xA;        def cross(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return Vec3( self.y* other.z - self.x* other.y, self.z* other.x - self.x* other.z , self.x * self.y - self.y * self.x)&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def trace_ray(O, D, t_min, t_max):&#xD;&#xA;        closest_t = math.inf&#xD;&#xA;        closest_sphere = None&#xD;&#xA;    &#xD;&#xA;        for sphere in scene['spheres']:&#xD;&#xA;            t1, t2 = ray_sphere_intersect(O, D, sphere)&#xD;&#xA;            if t1 in [t_min, t_max] and t1 &lt; closest_t:&#xD;&#xA;                closest_t  = t1&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;            if t2 in [t_min, t_max] and t2 &lt; closest_t:&#xD;&#xA;                closest_t = t2&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;        if closest_sphere == None:&#xD;&#xA;            return Vec3(0,0,0)&#xD;&#xA;        else:&#xD;&#xA;            return closest_sphere['color']&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def dot(v1, v2):&#xD;&#xA;        return v1.x* v2.x + v1.y * v2.y + v1.z * v2.z&#xD;&#xA;    &#xD;&#xA;    def ray_sphere_intersect(O, D, sphere):&#xD;&#xA;        C = sphere['center']&#xD;&#xA;        r = sphere['radius']&#xD;&#xA;    &#xD;&#xA;        oc = O - C&#xD;&#xA;        k1 = dot(D,D)&#xD;&#xA;        k2 = 2*dot(oc, D)&#xD;&#xA;        k3 = dot(oc, oc) - r*r&#xD;&#xA;    &#xD;&#xA;        discriminant = k2*k2 - 4*k1*k3&#xD;&#xA;    &#xD;&#xA;        if discriminant &lt; 0:&#xD;&#xA;            return math.inf, math.inf&#xD;&#xA;    &#xD;&#xA;        t1 = (-k2 + math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        t2 = (-k2 - math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        return t1, t2&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def canvas_to_viewport(x,y):&#xD;&#xA;        return Vec3(x*Vw/Cw, y*Vh/Ch, d)&#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;    &#xD;&#xA;        Cw = 200 # canvas width&#xD;&#xA;        Ch = 100 # canvas height&#xD;&#xA;        O = Vec3(0,0,0) # origin of camera&#xD;&#xA;        Vw = 1 # viewport width&#xD;&#xA;        Vh = 1 # viewport height&#xD;&#xA;        d = 1  # projection plane&#xD;&#xA;    &#xD;&#xA;        # define a PPM  image with width &amp; height equal to Canvas width &amp; canvas height respectively&#xD;&#xA;        image = P3Image(Cw,Ch)&#xD;&#xA;    &#xD;&#xA;        # define scene with one sphere&#xD;&#xA;        scene = {&#xD;&#xA;                'spheres':[&#xD;&#xA;                        {&#xD;&#xA;                        'center':Vec3(0,-1 ,3),&#xD;&#xA;                        'radius': 1,&#xD;&#xA;                        'color':Vec3(1,0,0)&#xD;&#xA;                        }&#xD;&#xA;                    ]&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;        for x in range(-Cw//2 , Cw//2):&#xD;&#xA;            for y in range(-Ch//2 , Ch//2):&#xD;&#xA;                D = canvas_to_viewport(x,y)&#xD;&#xA;                color = trace_ray(O,D,1,math.inf)&#xD;&#xA;                print(x,y, color)&#xD;&#xA;                image.pixel(x,y, color)&#xD;&#xA;    &#xD;&#xA;        image.save('ii.ppm')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28120" PostHistoryTypeId="5" PostId="9791" RevisionGUID="90b8bae0-899e-4e70-a8e6-34117e2fa3f4" CreationDate="2020-05-04T22:53:38.253" UserId="13309" Comment="edited body" Text="I am trying to implement a simple raytracer in python. [I am following this tutorial here][1] &#xD;&#xA;&#xD;&#xA;here is my code, i have explained in comments the relevant parts .All i am getting is a black image. I  don't want someone else to debug this for me, just a pointer on where to look might help.       &#xD;&#xA;&#xD;&#xA;i think its because this condition is always evaluating to true?&#xD;&#xA;&#xD;&#xA;    if closest_sphere == None:&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Program&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/basic-ray-tracing.html&#xD;&#xA; &#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;            self.img = [[None]*width]*height&#xD;&#xA;    &#xD;&#xA;        def pixel(self, x, y, color):&#xD;&#xA;            self.img[x][y] = color&#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            print(self.img)&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;                f.write(f'P3\n {self.width} {self.height}\n255\n')&#xD;&#xA;                for y in range(self.height):&#xD;&#xA;                    for x in range(self.width):&#xD;&#xA;                        if self.img[y][x] is not None:&#xD;&#xA;                            color = self.__rescale(self.img[y][x])&#xD;&#xA;                            f.write(f'{color.x} {color.y} {color.z}  ')&#xD;&#xA;                    f.write('\n')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Vec3:&#xD;&#xA;        def __init__(self, x, y, z):&#xD;&#xA;    &#xD;&#xA;            self.x = x&#xD;&#xA;            self.y = y&#xD;&#xA;            self.z = z&#xD;&#xA;    &#xD;&#xA;        def __str__(self):&#xD;&#xA;            return f'Vec3({self.x},{self.y},{self.z})'&#xD;&#xA;    &#xD;&#xA;        def __sub__(self, other):&#xD;&#xA;            return Vec3(self.x - other.x , self.y - other.y , self.z - other.z)&#xD;&#xA;    &#xD;&#xA;        def __add__(self, other):&#xD;&#xA;            return Vec3(self.x +  other.x , self.y + other.y , self.z + other.z)&#xD;&#xA;    &#xD;&#xA;        def mag(self):&#xD;&#xA;            return math.sqrt(self.x**2, self.y**2, self.z**2)&#xD;&#xA;    &#xD;&#xA;        def dot(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return self.x * other.x + self.y * other.y + self.z * other.z&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3')&#xD;&#xA;    &#xD;&#xA;        def cross(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return Vec3( self.y* other.z - self.x* other.y, self.z* other.x - self.x* other.z , self.x * self.y - self.y * self.x)&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def trace_ray(O, D, t_min, t_max):&#xD;&#xA;        closest_t = math.inf&#xD;&#xA;        closest_sphere = None&#xD;&#xA;    &#xD;&#xA;        for sphere in scene['spheres']:&#xD;&#xA;            t1, t2 = ray_sphere_intersect(O, D, sphere)&#xD;&#xA;            if (t_min &lt; t1 &lt; t_max) and t1 &lt; closest_t:&#xD;&#xA;                closest_t  = t1&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;            if (t_min &lt; t2 &lt; t_max) and t2 &lt; closest_t:&#xD;&#xA;                closest_t = t2&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;        if closest_sphere == None:&#xD;&#xA;            return Vec3(0,0,0)&#xD;&#xA;        else:&#xD;&#xA;            return closest_sphere['color']&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def dot(v1, v2):&#xD;&#xA;        return v1.x* v2.x + v1.y * v2.y + v1.z * v2.z&#xD;&#xA;    &#xD;&#xA;    def ray_sphere_intersect(O, D, sphere):&#xD;&#xA;        C = sphere['center']&#xD;&#xA;        r = sphere['radius']&#xD;&#xA;    &#xD;&#xA;        oc = O - C&#xD;&#xA;        k1 = dot(D,D)&#xD;&#xA;        k2 = 2*dot(oc, D)&#xD;&#xA;        k3 = dot(oc, oc) - r*r&#xD;&#xA;    &#xD;&#xA;        discriminant = k2*k2 - 4*k1*k3&#xD;&#xA;    &#xD;&#xA;        if discriminant &lt; 0:&#xD;&#xA;            return math.inf, math.inf&#xD;&#xA;    &#xD;&#xA;        t1 = (-k2 + math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        t2 = (-k2 - math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        return t1, t2&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def canvas_to_viewport(x,y):&#xD;&#xA;        return Vec3(x*Vw/Cw, y*Vh/Ch, d)&#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;    &#xD;&#xA;        Cw = 200 # canvas width&#xD;&#xA;        Ch = 100 # canvas height&#xD;&#xA;        O = Vec3(0,0,0) # origin of camera&#xD;&#xA;        Vw = 1 # viewport width&#xD;&#xA;        Vh = 1 # viewport height&#xD;&#xA;        d = 1  # projection plane&#xD;&#xA;    &#xD;&#xA;        # define a PPM  image with width &amp; height equal to Canvas width &amp; canvas height respectively&#xD;&#xA;        image = P3Image(Cw,Ch)&#xD;&#xA;    &#xD;&#xA;        # define scene with one sphere&#xD;&#xA;        scene = {&#xD;&#xA;                'spheres':[&#xD;&#xA;                        {&#xD;&#xA;                        'center':Vec3(0,-1 ,3),&#xD;&#xA;                        'radius': 1,&#xD;&#xA;                        'color':Vec3(1,0,0)&#xD;&#xA;                        }&#xD;&#xA;                    ]&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;        for x in range(-Cw//2 , Cw//2):&#xD;&#xA;            for y in range(-Ch//2 , Ch//2):&#xD;&#xA;                D = canvas_to_viewport(x,y)&#xD;&#xA;                color = trace_ray(O,D,1,math.inf)&#xD;&#xA;                print(x,y, color)&#xD;&#xA;                image.pixel(x,y, color)&#xD;&#xA;    &#xD;&#xA;        image.save('ii.ppm')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28121" PostHistoryTypeId="50" PostId="8757" RevisionGUID="47d3af80-9de9-4cb1-9de0-e390437ed8f1" CreationDate="2020-05-05T09:00:45.067" UserId="-1" />
  <row Id="28122" PostHistoryTypeId="2" PostId="9792" RevisionGUID="7c52d75e-cedb-4498-bb35-c5a6cb9b1937" CreationDate="2020-05-05T18:01:59.740" UserId="1988" Text="## Defining the problem&#xD;&#xA;&#xD;&#xA;The weighted arithmetic mean $\mu$, of a set of vectors, minimizes squared L2 norm of the error ($v_i$) to all elements of the set.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;v_i &amp;= \mu - x_i \\&#xD;&#xA;\mu &amp;= \underset{\mu \in \mathbb{R^n}}{\text{argmin}} \; \frac{1}{2}\sum\limits_{v_i} w_i ||v_i||^2_2 \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This empowers us to define special means, where we use different notions of distance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Specializing for rotations&#xD;&#xA;&#xD;&#xA;A reasonable notion of distance for SO(3) is the *angle* separating two rotations. That's $||\log(\mu \ q^{-1})||$ Your geometry library probably implements this $log$, and expressions for it can be found [here](http://ethaneade.com/lie.pdf). It is not the log one is accustomed to on the real numbers.&#xD;&#xA;&#xD;&#xA;Intuition: Recall that the every sequence of rotations corresponds to [a single rotation about a single axis](https://en.wikipedia.org/wiki/Euler%27s_rotation_theorem), so the difference between a pair of rotations can always be summarized by a single angle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;v_i &amp;= log(\mu \ x_i^{-1}) \\&#xD;&#xA;\mu &amp;= \underset{\mu \in \mathbb{SO3}}{\text{argmin}} \sum\limits_{v_i} w_i || v_i||^2_2 \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's no analytical form for this minimum for more than two rotations. We can, however, treat this as a [least squares problem](http://ethaneade.com/optimization.pdf) and compute the result by Gauss-Newton. &#xD;&#xA;&#xD;&#xA;To apply Gauss-Newton in general, for some error, we need to be able to find $\mathbf{J_i} = \frac{d}{d\mu}v_i(\mu)$, which requires differentiating $v_i$. Then we can take a step as&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;\Delta \mu &amp;= \sum\limits_{i}(w_i \mathbf{J_i}^T \mathbf{J_i})^{-1} \sum\limits_{i} w_i \mathbf{J_i}^T v_i&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Our error function cannot readily be differentiated, since its argument is a rotation $\mu$ and not a vector. We invent a parameter $\delta \in \mathbb{R^3}$ which we will $Exp$ into a rotation. This, we can differentiate&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;v_i &amp;= log(Exp(\delta)\; \mu \ x_i^{-1}) \\ &#xD;&#xA;\mathbf{J_i} &amp;= \frac{d}{d\delta} v_i = \mathbf{I} \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So the update to $\mu$ is&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;\delta &amp;= \sum\limits_{i}(w_i \mathbf{J_i}^T \mathbf{J_i})^{-1} \sum\limits_{i} w_i \mathbf{J_i}^T v_i\\&#xD;&#xA;\delta &amp;= \sum\limits_{i} w_i \sum\limits_{i} w_i v_i \\&#xD;&#xA;\delta &amp;= \sum\limits_{i} w_i v_i&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Conclusion&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;\delta = \sum\limits_{i} w_i v_i &amp;= \sum\limits_{i}w_i log(\mu_{k}^{\mathstrut} x_{i}^{-1}) \\&#xD;&#xA;\mu_{k + 1} &amp;= Exp(\delta) \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;This will converge quadratically to a mean.&#xD;&#xA;&#xD;&#xA;Caveat emptor: for rotations, there may be many &quot;means&quot;. By analogy: What is the average point, on Earth's surface, of the north and south poles? Every point on the equator has equal right to be called the average. This is the case for all equispaced rotations." ContentLicense="CC BY-SA 4.0" />
  <row Id="28123" PostHistoryTypeId="5" PostId="9791" RevisionGUID="895e9033-4cb9-4486-bb2e-9ff280279bcb" CreationDate="2020-05-05T18:35:20.430" UserId="13309" Comment="added 569 characters in body" Text="I am trying to implement a simple raytracer in python. [I am following this tutorial here][1] &#xD;&#xA;&#xD;&#xA;here is my code, i have explained in comments the relevant parts .All i am getting is a black image. I  don't want someone else to debug this for me, just a pointer on where to look might help.       &#xD;&#xA;&#xD;&#xA;i think its because this condition is always evaluating to true?&#xD;&#xA;&#xD;&#xA;    if closest_sphere == None:&#xD;&#xA;        return Vec3(0,0,0)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Program&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/basic-ray-tracing.html&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    import math&#xD;&#xA;    from collections import namedtuple&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;            self.img = [[None]*width]*height&#xD;&#xA;        &#xD;&#xA;        def pixel(self, x, y, color):&#xD;&#xA;            self.img[y][x] = color&#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;                f.write(f'P3\n {self.width} {self.height}\n255\n')&#xD;&#xA;                for y in range(self.height):&#xD;&#xA;                    for x in range(self.width):&#xD;&#xA;                        color = self.__rescale(self.img[y][x])&#xD;&#xA;                        f.write(f'{color.x} {color.y} {color.z}  ')&#xD;&#xA;                    f.write('\n')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Vec3:&#xD;&#xA;        def __init__(self, x, y, z):&#xD;&#xA;            &#xD;&#xA;            self.x = x&#xD;&#xA;            self.y = y&#xD;&#xA;            self.z = z&#xD;&#xA;        &#xD;&#xA;        def __str__(self):&#xD;&#xA;            return f'Vec3({self.x},{self.y},{self.z})'&#xD;&#xA;    &#xD;&#xA;        def __sub__(self, other):&#xD;&#xA;            return Vec3(self.x - other.x , self.y - other.y , self.z - other.z)&#xD;&#xA;    &#xD;&#xA;        def __add__(self, other):&#xD;&#xA;            return Vec3(self.x +  other.x , self.y + other.y , self.z + other.z)&#xD;&#xA;    &#xD;&#xA;        def mag(self):&#xD;&#xA;            return math.sqrt(self.x**2, self.y**2, self.z**2)&#xD;&#xA;    &#xD;&#xA;        def dot(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return self.x * other.x + self.y * other.y + self.z * other.z&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3') &#xD;&#xA;        &#xD;&#xA;        def cross(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return Vec3( self.y* other.z - self.x* other.y, self.z* other.x - self.x* other.z , self.x * self.y - self.y * self.x)&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3') &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def trace_ray(O, D, t_min, t_max):&#xD;&#xA;        closest_t = math.inf&#xD;&#xA;        closest_sphere = None&#xD;&#xA;    &#xD;&#xA;        for sphere in scene['spheres']:&#xD;&#xA;            t1, t2 = ray_sphere_intersect(O, D, sphere)&#xD;&#xA;            &#xD;&#xA;            if  (t_min &lt; t1 &lt; t_max) and t1 &lt; closest_t:&#xD;&#xA;                closest_t  = t1&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;            if (t_min &lt; t2 &lt; t_max) and t2 &lt; closest_t:&#xD;&#xA;                closest_t = t2&#xD;&#xA;    &#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;        if closest_sphere == None:&#xD;&#xA;            return Vec3(1,1,1)&#xD;&#xA;        else:&#xD;&#xA;            return closest_sphere['color']&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def dot(v1, v2):&#xD;&#xA;        return v1.x* v2.x + v1.y * v2.y + v1.z * v2.z&#xD;&#xA;    &#xD;&#xA;    def ray_sphere_intersect(O, D, sphere):&#xD;&#xA;        C = sphere['center']&#xD;&#xA;        r = sphere['radius']&#xD;&#xA;        oc = O - C&#xD;&#xA;        k1 = dot(D,D)&#xD;&#xA;        k2 = 2*dot(oc, D)&#xD;&#xA;        k3 = dot(oc, oc) - r*r&#xD;&#xA;    &#xD;&#xA;        discriminant = k2*k2 - 4*k1*k3&#xD;&#xA;        &#xD;&#xA;        if discriminant &lt; 0:&#xD;&#xA;            return math.inf, math.inf&#xD;&#xA;        &#xD;&#xA;        t1 = (-k2 + math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        t2 = (-k2 - math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        return t1, t2&#xD;&#xA;    &#xD;&#xA; &#xD;&#xA;      &#xD;&#xA;    # define scene with one sphere &#xD;&#xA;    scene = {&#xD;&#xA;            'spheres':[&#xD;&#xA;                    {&#xD;&#xA;                    'center':Vec3(0,0 ,0),&#xD;&#xA;                    'radius': 0.5,&#xD;&#xA;                    'color':Vec3(1,0,0)&#xD;&#xA;                    },&#xD;&#xA;                ]&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;        &#xD;&#xA;        WIDTH  = 320 &#xD;&#xA;        HEIGHT = 200&#xD;&#xA;        camera = Vec3(0, 0, -1)&#xD;&#xA;    &#xD;&#xA;        aspect_ratio = WIDTH/HEIGHT&#xD;&#xA;    &#xD;&#xA;        xmin = -1 &#xD;&#xA;        xmax = 1  &#xD;&#xA;    &#xD;&#xA;        ymax = 1/aspect_ratio&#xD;&#xA;        ymin = -1*ymax&#xD;&#xA;    &#xD;&#xA;        xstep = (xmax - xmin) / (WIDTH-1)&#xD;&#xA;        ystep = (ymax - ymin) / (HEIGHT-1)&#xD;&#xA;    &#xD;&#xA;        image = P3Image(WIDTH, HEIGHT)&#xD;&#xA;    &#xD;&#xA;        for j in range(HEIGHT):&#xD;&#xA;            y  = ymin + j*ystep&#xD;&#xA;            for i in range(WIDTH): &#xD;&#xA;                x  = xmin + i*xstep&#xD;&#xA;                ray = Vec3(x,y,0) - camera&#xD;&#xA;                color = trace_ray(camera, ray, -1, math.inf)&#xD;&#xA;    &#xD;&#xA;                print(i,j,color)&#xD;&#xA;                &#xD;&#xA;                image.pixel(i, j, color)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        image.save('ii.ppm')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE:** *I modified the main render loop to avoid negative index while generating image as suggested by @Oliver. but now even now i get a blank image. but i am sure the rays are hitting sphere properly as evident from the output of print statement in code.*&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28124" PostHistoryTypeId="5" PostId="9791" RevisionGUID="685300a8-26be-494c-8164-f05c2fc7db7c" CreationDate="2020-05-05T18:41:12.910" UserId="13309" Comment="I guess i might need someone to help me debug this as i have spent 2 days staright and cant figure out myself; deleted 130 characters in body" Text="I am trying to implement a simple raytracer in python. [I am following this tutorial here][1] &#xD;&#xA;&#xD;&#xA;here is my code, i have explained in comments the relevant parts .All i am getting is a blank image.      &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Program&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/basic-ray-tracing.html&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    import math&#xD;&#xA;    from collections import namedtuple&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;            self.img = [[None]*width]*height&#xD;&#xA;        &#xD;&#xA;        def pixel(self, x, y, color):&#xD;&#xA;            self.img[y][x] = color&#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;                f.write(f'P3\n {self.width} {self.height}\n255\n')&#xD;&#xA;                for y in range(self.height):&#xD;&#xA;                    for x in range(self.width):&#xD;&#xA;                        color = self.__rescale(self.img[y][x])&#xD;&#xA;                        f.write(f'{color.x} {color.y} {color.z}  ')&#xD;&#xA;                    f.write('\n')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Vec3:&#xD;&#xA;        def __init__(self, x, y, z):&#xD;&#xA;            &#xD;&#xA;            self.x = x&#xD;&#xA;            self.y = y&#xD;&#xA;            self.z = z&#xD;&#xA;        &#xD;&#xA;        def __str__(self):&#xD;&#xA;            return f'Vec3({self.x},{self.y},{self.z})'&#xD;&#xA;    &#xD;&#xA;        def __sub__(self, other):&#xD;&#xA;            return Vec3(self.x - other.x , self.y - other.y , self.z - other.z)&#xD;&#xA;    &#xD;&#xA;        def __add__(self, other):&#xD;&#xA;            return Vec3(self.x +  other.x , self.y + other.y , self.z + other.z)&#xD;&#xA;    &#xD;&#xA;        def mag(self):&#xD;&#xA;            return math.sqrt(self.x**2, self.y**2, self.z**2)&#xD;&#xA;    &#xD;&#xA;        def dot(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return self.x * other.x + self.y * other.y + self.z * other.z&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3') &#xD;&#xA;        &#xD;&#xA;        def cross(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return Vec3( self.y* other.z - self.x* other.y, self.z* other.x - self.x* other.z , self.x * self.y - self.y * self.x)&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3') &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def trace_ray(O, D, t_min, t_max):&#xD;&#xA;        closest_t = math.inf&#xD;&#xA;        closest_sphere = None&#xD;&#xA;    &#xD;&#xA;        for sphere in scene['spheres']:&#xD;&#xA;            t1, t2 = ray_sphere_intersect(O, D, sphere)&#xD;&#xA;            &#xD;&#xA;            if  (t_min &lt; t1 &lt; t_max) and t1 &lt; closest_t:&#xD;&#xA;                closest_t  = t1&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;            if (t_min &lt; t2 &lt; t_max) and t2 &lt; closest_t:&#xD;&#xA;                closest_t = t2&#xD;&#xA;    &#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;        if closest_sphere == None:&#xD;&#xA;            return Vec3(1,1,1)&#xD;&#xA;        else:&#xD;&#xA;            return closest_sphere['color']&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def dot(v1, v2):&#xD;&#xA;        return v1.x* v2.x + v1.y * v2.y + v1.z * v2.z&#xD;&#xA;    &#xD;&#xA;    def ray_sphere_intersect(O, D, sphere):&#xD;&#xA;        C = sphere['center']&#xD;&#xA;        r = sphere['radius']&#xD;&#xA;        oc = O - C&#xD;&#xA;        k1 = dot(D,D)&#xD;&#xA;        k2 = 2*dot(oc, D)&#xD;&#xA;        k3 = dot(oc, oc) - r*r&#xD;&#xA;    &#xD;&#xA;        discriminant = k2*k2 - 4*k1*k3&#xD;&#xA;        &#xD;&#xA;        if discriminant &lt; 0:&#xD;&#xA;            return math.inf, math.inf&#xD;&#xA;        &#xD;&#xA;        t1 = (-k2 + math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        t2 = (-k2 - math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        return t1, t2&#xD;&#xA;    &#xD;&#xA; &#xD;&#xA;      &#xD;&#xA;    # define scene with one sphere &#xD;&#xA;    scene = {&#xD;&#xA;            'spheres':[&#xD;&#xA;                    {&#xD;&#xA;                    'center':Vec3(0,0 ,0),&#xD;&#xA;                    'radius': 0.5,&#xD;&#xA;                    'color':Vec3(1,0,0)&#xD;&#xA;                    },&#xD;&#xA;                ]&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;        &#xD;&#xA;        WIDTH  = 320 &#xD;&#xA;        HEIGHT = 200&#xD;&#xA;        camera = Vec3(0, 0, -1)&#xD;&#xA;    &#xD;&#xA;        aspect_ratio = WIDTH/HEIGHT&#xD;&#xA;    &#xD;&#xA;        xmin = -1 &#xD;&#xA;        xmax = 1  &#xD;&#xA;    &#xD;&#xA;        ymax = 1/aspect_ratio&#xD;&#xA;        ymin = -1*ymax&#xD;&#xA;    &#xD;&#xA;        xstep = (xmax - xmin) / (WIDTH-1)&#xD;&#xA;        ystep = (ymax - ymin) / (HEIGHT-1)&#xD;&#xA;    &#xD;&#xA;        image = P3Image(WIDTH, HEIGHT)&#xD;&#xA;    &#xD;&#xA;        for j in range(HEIGHT):&#xD;&#xA;            y  = ymin + j*ystep&#xD;&#xA;            for i in range(WIDTH): &#xD;&#xA;                x  = xmin + i*xstep&#xD;&#xA;                ray = Vec3(x,y,0) - camera&#xD;&#xA;                color = trace_ray(camera, ray, -1, math.inf)&#xD;&#xA;    &#xD;&#xA;                print(i,j,color)&#xD;&#xA;                &#xD;&#xA;                image.pixel(i, j, color)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        image.save('ii.ppm')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE:** *I modified the main render loop to avoid negative index while generating image as suggested by @Oliver. but now even now i get a blank image. but i am sure the rays are hitting sphere properly as evident from the output of print statement in code.*&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28125" PostHistoryTypeId="5" PostId="9791" RevisionGUID="5afe46d5-89d8-405a-bc33-c79ca826adb3" CreationDate="2020-05-05T19:07:59.070" UserId="13309" Comment="added 254 characters in body" Text="I am trying to implement a simple raytracer in python. [I am following this tutorial here][1] &#xD;&#xA;&#xD;&#xA;here is my code, i have explained in comments the relevant parts .All i am getting is a blank image.      &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Program&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/basic-ray-tracing.html&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    import math&#xD;&#xA;    from collections import namedtuple&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;            self.img = [[0]*width]*height&#xD;&#xA;        &#xD;&#xA;        def pixel(self, x, y, color):&#xD;&#xA;            self.img[y][x] = color&#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;                f.write(f'P3 {self.width} {self.height}\n255\n')&#xD;&#xA;                for row in self.img:&#xD;&#xA;                    for color in row:&#xD;&#xA;                        color = self.__rescale(color)&#xD;&#xA;                        f.write(f'{color.x} {color.y} {color.z}  ')&#xD;&#xA;                    f.write('\n')&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Vec3:&#xD;&#xA;        def __init__(self, x, y, z):&#xD;&#xA;            &#xD;&#xA;            self.x = x&#xD;&#xA;            self.y = y&#xD;&#xA;            self.z = z&#xD;&#xA;        &#xD;&#xA;        def __str__(self):&#xD;&#xA;            return f'Vec3({self.x},{self.y},{self.z})'&#xD;&#xA;    &#xD;&#xA;        def __sub__(self, other):&#xD;&#xA;            return Vec3(self.x - other.x , self.y - other.y , self.z - other.z)&#xD;&#xA;    &#xD;&#xA;        def __add__(self, other):&#xD;&#xA;            return Vec3(self.x +  other.x , self.y + other.y , self.z + other.z)&#xD;&#xA;    &#xD;&#xA;        def mag(self):&#xD;&#xA;            return math.sqrt(self.x**2, self.y**2, self.z**2)&#xD;&#xA;    &#xD;&#xA;        def dot(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return self.x * other.x + self.y * other.y + self.z * other.z&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3') &#xD;&#xA;        &#xD;&#xA;        def cross(self, other):&#xD;&#xA;            if isinstance(other, Vec3):&#xD;&#xA;                return Vec3( self.y* other.z - self.x* other.y, self.z* other.x - self.x* other.z , self.x * self.y - self.y * self.x)&#xD;&#xA;            raise Exception('this should recieve an arfument of type Vec3') &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def trace_ray(O, D, t_min, t_max):&#xD;&#xA;        closest_t = math.inf&#xD;&#xA;        closest_sphere = None&#xD;&#xA;    &#xD;&#xA;        for sphere in scene['spheres']:&#xD;&#xA;            t1, t2 = ray_sphere_intersect(O, D, sphere)&#xD;&#xA;            &#xD;&#xA;            if  (t_min &lt; t1 &lt; t_max) and t1 &lt; closest_t:&#xD;&#xA;                closest_t  = t1&#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;            if (t_min &lt; t2 &lt; t_max) and t2 &lt; closest_t:&#xD;&#xA;                closest_t = t2&#xD;&#xA;    &#xD;&#xA;                closest_sphere = sphere&#xD;&#xA;    &#xD;&#xA;        if closest_sphere == None:&#xD;&#xA;            return Vec3(1,1,1)&#xD;&#xA;        else:&#xD;&#xA;            return closest_sphere['color']&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def dot(v1, v2):&#xD;&#xA;        return v1.x* v2.x + v1.y * v2.y + v1.z * v2.z&#xD;&#xA;    &#xD;&#xA;    def ray_sphere_intersect(O, D, sphere):&#xD;&#xA;        C = sphere['center']&#xD;&#xA;        r = sphere['radius']&#xD;&#xA;        oc = O - C&#xD;&#xA;        k1 = dot(D,D)&#xD;&#xA;        k2 = 2*dot(oc, D)&#xD;&#xA;        k3 = dot(oc, oc) - r*r&#xD;&#xA;    &#xD;&#xA;        discriminant = k2*k2 - 4*k1*k3&#xD;&#xA;        &#xD;&#xA;        if discriminant &lt; 0:&#xD;&#xA;            return math.inf, math.inf&#xD;&#xA;        &#xD;&#xA;        t1 = (-k2 + math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        t2 = (-k2 - math.sqrt(discriminant))/(2*k1)&#xD;&#xA;        return t1, t2&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def canvas_to_viewport(x,y):&#xD;&#xA;        return Vec3(x*Vw/Cw, y*Vh/Ch, d)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def c_to_i(x, y):&#xD;&#xA;        '''canvas to image'''&#xD;&#xA;        &#xD;&#xA;        xnew = xmin + (xmax - xmin)/Cw&#xD;&#xA;        ynew = ymin + (ymax - ymin)/Ch&#xD;&#xA;        return Vec3(xnew, ynew, d)&#xD;&#xA;           &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    # define scene with one sphere &#xD;&#xA;    scene = {&#xD;&#xA;            'spheres':[&#xD;&#xA;                    {&#xD;&#xA;                    'center':Vec3(0,0 ,0),&#xD;&#xA;                    'radius': 0.5,&#xD;&#xA;                    'color':Vec3(1,0,0)&#xD;&#xA;                    },&#xD;&#xA;                ]&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if __name__ == '__main__':&#xD;&#xA;        &#xD;&#xA;        WIDTH  = 320 &#xD;&#xA;        HEIGHT = 200&#xD;&#xA;        camera = Vec3(0, 0, -1)&#xD;&#xA;    &#xD;&#xA;        aspect_ratio = WIDTH/HEIGHT&#xD;&#xA;    &#xD;&#xA;        xmin = -1 &#xD;&#xA;        xmax = 1  &#xD;&#xA;    &#xD;&#xA;        ymax = 1/aspect_ratio&#xD;&#xA;        ymin = -1*ymax&#xD;&#xA;    &#xD;&#xA;        xstep = (xmax - xmin) / (WIDTH-1)&#xD;&#xA;        ystep = (ymax - ymin) / (HEIGHT-1)&#xD;&#xA;    &#xD;&#xA;        image = P3Image(WIDTH, HEIGHT)&#xD;&#xA;    &#xD;&#xA;        for j in range(HEIGHT):&#xD;&#xA;            y  = ymin + j*ystep&#xD;&#xA;            for i in range(WIDTH): &#xD;&#xA;                x  = xmin + i*xstep&#xD;&#xA;                ray = Vec3(x,y,0) - camera&#xD;&#xA;                color = trace_ray(camera, ray, -1, math.inf)&#xD;&#xA;    &#xD;&#xA;                print(i,j,color)&#xD;&#xA;                &#xD;&#xA;                image.pixel(i, j, color)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        image.save('ii.ppm')&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE:** *I modified the main render loop to avoid negative index while generating image as suggested by @Oliver. but now even now i get a blank image. but i am sure the rays are hitting sphere properly as evident from the output of print statement in code.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28126" PostHistoryTypeId="2" PostId="9793" RevisionGUID="da197d31-69b2-4b22-8028-23ccc35b19c0" CreationDate="2020-05-05T20:12:56.653" UserId="13309" Text="Ok, after several hours of debugging, I finally got the answer and posting it here.&#xD;&#xA;The issue was in image generation.&#xD;&#xA;&#xD;&#xA;    class P3Image:&#xD;&#xA;        def __init__(self, width,  height):&#xD;&#xA;            self.width = width&#xD;&#xA;            self.height = height&#xD;&#xA;    &#xD;&#xA;            self.img = [[None for _ in range(width)] for _ in range(height)]&#xD;&#xA;    &#xD;&#xA;        def set_pixel(self, x, y, color):&#xD;&#xA;            self.img[y][x] = color&#xD;&#xA;            print(self.img[19][173], y,x, color)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        def __rescale(self, color):&#xD;&#xA;            ''' rescale a color range from 0-1 to 0-225 '''&#xD;&#xA;            return Vec3(round(color.x*255), round(color.y*255) , round(color.z*255))&#xD;&#xA;    &#xD;&#xA;        def save(self, filename):&#xD;&#xA;            with open(filename, 'w') as f:&#xD;&#xA;    &#xD;&#xA;                f.write(f'P3 {self.width} {self.height}\n255\n')&#xD;&#xA;                for row in self.img:&#xD;&#xA;                    for color in row:&#xD;&#xA;                        c = self.__rescale(color)&#xD;&#xA;                        f.write(f'{c.x} {c.y} {c.z}  ')&#xD;&#xA;    &#xD;&#xA;                    f.write('\n')&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28137" PostHistoryTypeId="2" PostId="9795" RevisionGUID="878ae4dc-67f0-46f7-aef5-47de8393d276" CreationDate="2020-05-06T07:25:13.870" UserId="209" Text="Just to confirm, assuming non-premultiplied alpha, at one point you performed the following, per pixel operation:&#xD;&#xA;$$ Result_{RGB} = Src_{A} * Src_{RGB} + (1.0 - Src_{A})* Background_{RGB} $$&#xD;&#xA;&#xD;&#xA;You say you've lost the $Src_{ARBG}$ data,  but have retained the $Background_{RGB}$ and the $Result_{RGB}$, but want to recover the $Src$ data?&#xD;&#xA;&#xD;&#xA;Unless you can make some other assumptions, you *might* be out of luck. It's a rather underconstrained problem. &#xD;&#xA;Jim Blinn notes in &quot;*Fun with Premultiplied Alpha*&quot; that there are some commercial systems that are used to 'de-bluescreen' but they may require the operator to identify, say, what is 'Source' and 'Background'.&#xD;&#xA;&#xD;&#xA;As an extreme example, you may have a pixel in the result which exactly matches the background but the source pixel may also have been the same colour.&#xD;&#xA;&#xD;&#xA;If, on the other hand, $Result$ and $Background$ don't match, then you know that the source is involved but *if* the $Src$, $Result$, $Background$ RGB values are all collinear, then there could be multiple possible solutions.&#xD;&#xA;&#xD;&#xA;Having said this, there may be some heuristics that perhaps could be used, but it'd require some thinking. &#xD;&#xA;Perhaps, pixels which differ and are not collinear could be used to estimate $Src_A$, with some level of 'certainty', and this could be 'filtered' to neighbouring 'uncertain' pixels and the process repeated.&#xD;&#xA;Non-constant pixels in the destination with a local neighbourhood which all match the background might be assumed to have an alpha of 0.0.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28140" PostHistoryTypeId="2" PostId="9796" RevisionGUID="9ccfcdab-451b-4c67-b5a1-d890dbf53bee" CreationDate="2020-05-06T14:12:10.820" UserId="13321" Text="In addition to what other people have said, for cpu / raytracing it is more memory effecient to store quads even though they may be intersected as two triangles.&#xD;&#xA;&#xD;&#xA;When you have millions of polygons, this memory saving is useful and there are no real performance side effects." ContentLicense="CC BY-SA 4.0" />
  <row Id="28141" PostHistoryTypeId="2" PostId="9797" RevisionGUID="159c216e-2dd5-43d6-8bb0-4c5ce98e2bc4" CreationDate="2020-05-06T14:33:23.683" UserId="13321" Text="Some more clarity on the fresnel.&#xD;&#xA;&#xD;&#xA;F tells you how much light is reflected, and (1 - F) therefore tells you how much light is transmitted through the layer/material/surface.&#xD;&#xA;&#xD;&#xA;Generally we put fresnels into two types Dielectric(water/glass) and Conductor(metals).&#xD;&#xA;&#xD;&#xA;The approximation you are using is for a dielectric fresnel, so what you are actually modelling is a thin layer over the top of your diffuse. In renderers this layer is normally called the coat or clearcoat. It can be used to emulate laminated materials or a coating of water/sweat.&#xD;&#xA;&#xD;&#xA;If you want to render metals you would need to swap out the fresnel for a conductive one. There are better approximations, but an easy artistic approximation is to swap the F0 of your schlick approximation with the rgb of your material. You can layer a diffuse below this if you need to but you may find with conductive it's not nessisary.&#xD;&#xA;&#xD;&#xA;http://www.codinglabs.net/article_physically_based_rendering_cook_torrance.aspx&#xD;&#xA;&#xD;&#xA;This is a good article on the topic for further reading." ContentLicense="CC BY-SA 4.0" />
  <row Id="28143" PostHistoryTypeId="50" PostId="9409" RevisionGUID="28bc579b-83cb-4070-a9e0-1c59f99022c5" CreationDate="2020-05-06T21:04:35.473" UserId="-1" />
  <row Id="28144" PostHistoryTypeId="2" PostId="9798" RevisionGUID="80f59336-8b5b-480c-adac-73aa3cf93cb9" CreationDate="2020-05-07T14:15:00.233" UserId="13318" Text="I have a bezier curve and would like to draw it's stroke. To do that, I planned to approximate the stroke to a polygon and fill it with a scanline algorithm. While I feel confident about implementing the conversion and the scanline algorithm, I am unsure how to handle the situation when a polygon intersects itself.&#xD;&#xA;&#xD;&#xA;If I don't treat it specially, it will look like on this picture on the left side, but what I am actually looking for is something like on the right side. Is there a popular method how to do that?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;  [1]: https://i.stack.imgur.com/uggRT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28145" PostHistoryTypeId="1" PostId="9798" RevisionGUID="80f59336-8b5b-480c-adac-73aa3cf93cb9" CreationDate="2020-05-07T14:15:00.233" UserId="13318" Text="How to do a scanline fill with a self intersecting polygon?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28146" PostHistoryTypeId="3" PostId="9798" RevisionGUID="80f59336-8b5b-480c-adac-73aa3cf93cb9" CreationDate="2020-05-07T14:15:00.233" UserId="13318" Text="|vector-graphics|polygon|bezier-curve|drawing|scanline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28147" PostHistoryTypeId="2" PostId="9799" RevisionGUID="bbeef826-cf92-4df0-b7a8-2624f1d27f5b" CreationDate="2020-05-07T15:38:23.367" UserId="11412" Text="I'm trying to understand how much graphics programming actually needs to be done if you are using an engine like Unreal Engine to build and package a game.&#xD;&#xA;&#xD;&#xA;I understand some of this might have to do with whether the engine in question supports your targeted rendering features or not. Generally speaking however, if you didn't need to add any rendering features to the engine, would there be any need for graphics programming at all?&#xD;&#xA;&#xD;&#xA;Doesn't it handle all of the needed rendering instruction under the hood right off the shelf?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28148" PostHistoryTypeId="1" PostId="9799" RevisionGUID="bbeef826-cf92-4df0-b7a8-2624f1d27f5b" CreationDate="2020-05-07T15:38:23.367" UserId="11412" Text="In Game Engines, how much of the graphics pipeline is already written?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28149" PostHistoryTypeId="3" PostId="9799" RevisionGUID="bbeef826-cf92-4df0-b7a8-2624f1d27f5b" CreationDate="2020-05-07T15:38:23.367" UserId="11412" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28150" PostHistoryTypeId="2" PostId="9800" RevisionGUID="d4066e7d-6289-4114-8bd2-4ffc21581895" CreationDate="2020-05-07T20:08:48.577" UserId="48" Text="Any full-featured engine such as UE4 or Unity will include a fully functional renderer out of the box, with support for multiple platforms/APIs, and typical modern graphics features such as PBR shaders/materials, various types of lights and shadows, global illumination, particles, postprocessing effects, etc.&#xD;&#xA;&#xD;&#xA;If the built-in renderer already handles everything you want, there is no need to do any graphics coding with these engines. But many games have at least a few things they want to do differently, or custom effects that aren't built in, so they will extend the engine with some of their own shaders or graphics passes." ContentLicense="CC BY-SA 4.0" />
  <row Id="28151" PostHistoryTypeId="2" PostId="9801" RevisionGUID="c7197e0d-be40-4981-b27d-1f3522fd07a2" CreationDate="2020-05-08T07:08:50.717" UserDisplayName="user13304" Text="The eye position (a vec3) was being bound to the wrong shader, resulting in the `glUniform3` error when OpenGL (mesa) checked the validity of the uniforms. The error was due to a typo; I named my simple-mesh and animated-mesh shaders similar things.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glUseProgram(smesh_shader.get());&#xD;&#xA;      smb.predraw();&#xD;&#xA;      glUniform3fv(mesh_shader.uniform(&quot;eye&quot;), 1, &amp;eye[0]); // &lt;- Oops&#xD;&#xA;      graphics::ogl::render(scene.getRoot(), smb, mv, smesh_shader);&#xD;&#xA;      smb.postdraw();&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Following @Christian Rau's and @wychmaster's suggestions, I was able to debug the issue. I also needed to build a debug version of the mesa library to make sense of the stack-trace in gdb." ContentLicense="CC BY-SA 4.0" />
  <row Id="28158" PostHistoryTypeId="2" PostId="9804" RevisionGUID="c994442d-eddd-4d77-89bc-6960fb2460e1" CreationDate="2020-05-08T21:10:30.373" UserId="8709" Text="I was looking for algorithms that quickly computes realistic, or not realistic, but quite handsome animated landscapes in video format (&quot;animated&quot; = the camera moves, or water is animated, etc.). But all I've found is: deep-learning GANs, which are hard to train, even hard to fine tune or transfert... (&quot;hard&quot; and takes long time too)&#xD;&#xA;&#xD;&#xA;Rendered animated landscapes can be as children animated drawings: I just want to generate quickly such animated landscapes, which must be quite beautiful, that's all.&#xD;&#xA;&#xD;&#xA;What research papers, documentation, tutorials, tools, API, libraries, Github/Gitlab repositories should I read? In MIT licence or equivalent please.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28159" PostHistoryTypeId="1" PostId="9804" RevisionGUID="c994442d-eddd-4d77-89bc-6960fb2460e1" CreationDate="2020-05-08T21:10:30.373" UserId="8709" Text="What fast algorithms can generate not-realistic but quite handsome animated landscapes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28160" PostHistoryTypeId="3" PostId="9804" RevisionGUID="c994442d-eddd-4d77-89bc-6960fb2460e1" CreationDate="2020-05-08T21:10:30.373" UserId="8709" Text="|image-processing|image|procedural-generation|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28161" PostHistoryTypeId="5" PostId="9804" RevisionGUID="1976297d-7a6c-42c2-8483-0b1db4aa58a1" CreationDate="2020-05-08T21:19:04.813" UserId="8709" Comment="edited body" Text="I was looking for algorithms that quickly compute quite nice realistic, or not realistic, animated landscapes, in video format (&quot;animated&quot; = the camera moves, or the water is animated, etc.) But all I found were: deep learning GANs, which are difficult to train, or even difficult to set or transfer. (&quot;hard&quot; and time-consuming too)&#xD;&#xA;&#xD;&#xA;The animated landscapes rendered can be like children's cartoons: I just want to quickly generate landscapes, which have to be quite beautiful, that's all.&#xD;&#xA;&#xD;&#xA;What research papers, documentation, tutorials, tools, APIs, libraries, Github/Gitlab repositories should I read? MIT license or equivalent please.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28169" PostHistoryTypeId="5" PostId="9410" RevisionGUID="8955c826-7337-44bf-b356-f780d5ed7107" CreationDate="2020-05-09T19:54:37.930" UserId="11581" Comment="added 6 characters in body" Text="I have a similar question currently posted, so take the following with a grain of salt.&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. BRDF only needs to be non negative and to integrate to 1 over the hemisphere. It can be arbitrarily large - e.g. in the case of a mirror. &#xD;&#xA;&#xD;&#xA;The pdf should approximate the BRDF to reduce variance. However, unless it is always larger than the BRDF, the throughput will be larger than 1 and should be able to reach infinity.&#xD;&#xA;&#xD;&#xA;*BRDF in your case corresponds to material-&gt;Eval(wi, wo, normal) / dot(normal, wi)*" ContentLicense="CC BY-SA 4.0" />
  <row Id="28170" PostHistoryTypeId="5" PostId="9410" RevisionGUID="d65943e8-8283-45f0-8f91-fb2bc525ac29" CreationDate="2020-05-09T20:00:46.437" UserId="11581" Comment="added 44 characters in body" Text="I have a similar question currently posted, so take the following with a grain of salt.&#xD;&#xA;&#xD;&#xA;Throughput does not need to be smaller than 1. BRDF only needs to be non negative and to integrate to less than 1 (conservation of energy / albedo) over the hemisphere. It can be arbitrarily large - e.g. in the case of a mirror. &#xD;&#xA;&#xD;&#xA;The pdf should approximate the BRDF to reduce variance. However, unless it is always larger than the BRDF, the throughput will be larger than 1 and should be able to reach infinity.&#xD;&#xA;&#xD;&#xA;*BRDF in your case corresponds to material-&gt;Eval(wi, wo, normal) / dot(normal, wi)*" ContentLicense="CC BY-SA 4.0" />
  <row Id="28171" PostHistoryTypeId="2" PostId="9807" RevisionGUID="8b88b8df-ff52-4b63-9918-35bacc4704ba" CreationDate="2020-05-09T22:38:06.823" UserId="12040" Text="I have a few questions about setting up a bidirectional path tracer described by Veach [here][1].&#xD;&#xA;&#xD;&#xA;I have created both an eye path and a light path. Both are using BRDF for calculating how much light can pass after bounce and directions are sampled with importance sampling.&#xD;&#xA;&#xD;&#xA;My first question is: Can I connect all possible combinations of paths? In the example below, it is a connection of points [1;3], [1;4], [1;light], [2;3], [2;4], [2; light]. It is definitely a bad idea to connect the camera with anything, but I am not sure if it the same with directly connecting with a light source.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And secondly, do I have to average the radiance coming from all the connected paths? I am not implementing a multiple-importance sampling for now. It will be the next step because without it I am adding even more variance.&#xD;&#xA;&#xD;&#xA;Last one. Because I am using an importance sampling I am dividing by PDF. But when I am connecting these two paths I am making deterministic connection so I use PDF of 1. Is this right?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/SUTpD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28172" PostHistoryTypeId="1" PostId="9807" RevisionGUID="8b88b8df-ff52-4b63-9918-35bacc4704ba" CreationDate="2020-05-09T22:38:06.823" UserId="12040" Text="Birectional path tracing - connection of paths" ContentLicense="CC BY-SA 4.0" />
  <row Id="28173" PostHistoryTypeId="3" PostId="9807" RevisionGUID="8b88b8df-ff52-4b63-9918-35bacc4704ba" CreationDate="2020-05-09T22:38:06.823" UserId="12040" Text="|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28177" PostHistoryTypeId="2" PostId="9808" RevisionGUID="6cbf7a1b-a051-4369-b779-d032ec79ab71" CreationDate="2020-05-09T22:44:42.270" UserId="12040" Text="So I found a solution on a shader toy.&#xD;&#xA;&#xD;&#xA;I choose randomly from sampling diffuse or sampling specular with distribution 50:50. But I calculate PDF of both and average then. If you want to use a different proportion between sample function you just have to make sure that PDFs are combined with the same proportion as choose. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28178" PostHistoryTypeId="2" PostId="9809" RevisionGUID="23ce9829-8a28-47b0-ab86-e480d0cbff01" CreationDate="2020-05-10T09:05:44.710" UserId="13225" Text="When ray tracing, I find it intuitively clear that deeper paths have a lower contribution to the overal picture than shorter paths. This is the main reason why it is generally okay to render a picture only to a certain depth, but I am currently not able to prove this.&#xD;&#xA;&#xD;&#xA;Formally, we can write the rendering equation as&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/VyNFZ.jpg&quot; width=&quot;500&quot; /&gt;&#xD;&#xA;&#xD;&#xA;where `p(j+1)` is defined as the intersection of a ray with origin `p(j)` and direction `-w(j+1)` and `theta(j+1)` is the angle between the normal of the surface at `p(j)` and `-w(j+1)`. Each term represents the radiance contribution of respectively paths with depth 0, 1, 2, and so on. Let's denote the contribution of depth `d` with `L(d)`. **I suspect that, under mild conditions on the scene, the contributions of these terms will asymptotically decrease exponentially: `L(d) = O(t^d)` for some `t` with `0 &lt; t &lt; 1`**, where I have used the big-O notation.&#xD;&#xA;&#xD;&#xA;Of course, I expect this only to hold when the scene is somehow &quot;realistic&quot;, which I define as follows.&#xD;&#xA;&#xD;&#xA;Firstly, all light sources should have only a limited amount of power. Note that infinite radiances, like with point lights, should be permitted, as long as their power is finite. &#xD;&#xA;  &#xD;&#xA;1.  **The total power of all light sources should be finite.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/RbHvb.gif&quot; width=&quot;250&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Secondly, we should exclude scenes that consists only of mirrors or diffuse white materials, or any other material that perfectly conserves energy. In other words, the scene should always absorb a little energy. These materials should still be permitted though, as long as their reflected light eventually ends up in materials that do not conserve the energy. I tried to formalize this the following way.&#xD;&#xA;&#xD;&#xA;2. **There exists an integer `k` with the following property: for every point `p` in the scene there should be a path of length `k` that starts in `p` and which has a throughput smaller than 1.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KzuU3.gif&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;Using these assumptions, is it possible to prove my suspicion? How would you do it?&#xD;&#xA;&#xD;&#xA;If it isn't possible, are there other &quot;realistic&quot; conditions that will make it proveable? Any conditions you come up with should not limit scenes that are used in practice in any way. (I know, sometimes people create materials that transmit more light than what comes in. You can ignore these materials).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**What I tried so far.**&#xD;&#xA;&#xD;&#xA;I was able to prove this with some stronger conditions, namely&#xD;&#xA;&#xD;&#xA;1. There is an upperbound `L_max` on emitted radiance `L_e`.&#xD;&#xA;2. There is an upperbound `t &lt; 1` on the percentage of energy that materials conserve.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0oNkf.gif&quot; width=&quot;360&quot; /&gt;&#xD;&#xA;&#xD;&#xA;With these conditions, the prove is straightforward, but they do not allow point lights or perfectly white diffuse materials and such." ContentLicense="CC BY-SA 4.0" />
  <row Id="28179" PostHistoryTypeId="1" PostId="9809" RevisionGUID="23ce9829-8a28-47b0-ab86-e480d0cbff01" CreationDate="2020-05-10T09:05:44.710" UserId="13225" Text="Prove radiance contributions of deeper paths fade away" ContentLicense="CC BY-SA 4.0" />
  <row Id="28180" PostHistoryTypeId="3" PostId="9809" RevisionGUID="23ce9829-8a28-47b0-ab86-e480d0cbff01" CreationDate="2020-05-10T09:05:44.710" UserId="13225" Text="|raytracing|lighting|mathematics|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28194" PostHistoryTypeId="2" PostId="9813" RevisionGUID="5da6736b-fdbf-4e73-8cb1-14d3d7130722" CreationDate="2020-05-10T21:02:33.587" UserId="13346" Text="I had this doubt in my head for several months and have been unable to find an answer anywhere on internet.&#xD;&#xA;&#xD;&#xA;I know what OpenGL, DirectX, Vulkan, Metal, etc... are, I already know what they are used for (literally in any multimedia software application).&#xD;&#xA;&#xD;&#xA;My question is &quot;in the real world when people work directly with a graphical API (eg: DirectX)?&quot;.&#xD;&#xA;&#xD;&#xA;For example, if I want to create a game I will use a game engine, if I want to create special effects I will use a program for VFX, if I want to create an animated scene with different 3D models I will use something like Blender.&#xD;&#xA;&#xD;&#xA;What are the situations where a person could say &quot;Ok, this problem can only be solved by writing my own software with DirectX/C++&quot;?&#xD;&#xA;&#xD;&#xA;My question arises from the fact that I would like to learn DirectX (later Vulkan also) as a matter of curiosity but I know that graphic programming is a demanding topic that requires a lot (a lot!) of time.&#xD;&#xA;&#xD;&#xA;I work for a company most of my day and since the salary is quite low (especially because at 21yo nobody takes you seriously), in the evening I dedicate myself to secondary activities in order to earn something more. I can't find a good reason to stop dedicating myself to these activities to study something that will not lead me to any type of business.&#xD;&#xA;&#xD;&#xA;In my country (Italy) there are really few job offerings concerning graphic programming and all require a degree in Metematics/Physics, which I don't have.&#xD;&#xA;&#xD;&#xA;So, in summary, what are the situations where you need to &quot;get your hands dirty&quot; with a graphical API (eg: DirectX) instead of using a tool already made?&#xD;&#xA;&#xD;&#xA;I know there are big game companies that for example reinvent the wheel (they write the rendering engine from 0) because they will pay off the costs and it is not convenient for them to pay for an engine already made. This environment doesn't interest me much because it certainly cannot lead to an individual business.&#xD;&#xA;&#xD;&#xA;Other situations where you work directly with a graphical API is the world of simulations, but there I imagine it is more a matter of mathematics and physics, not of graphics.&#xD;&#xA;&#xD;&#xA;I'd like to read about some experience of those who work/worked with a graphic API and what your role was in the industry. I'd also like to read about someone who has his own business that somehow relates to a graphical API.&#xD;&#xA;&#xD;&#xA;Thanks a lot to everyone :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28195" PostHistoryTypeId="1" PostId="9813" RevisionGUID="5da6736b-fdbf-4e73-8cb1-14d3d7130722" CreationDate="2020-05-10T21:02:33.587" UserId="13346" Text="When do people need to work directly with a graphical API (eg: Direct3D) instead of using already made software?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28196" PostHistoryTypeId="3" PostId="9813" RevisionGUID="5da6736b-fdbf-4e73-8cb1-14d3d7130722" CreationDate="2020-05-10T21:02:33.587" UserId="13346" Text="|opengl|3d|vulkan|directx|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28202" PostHistoryTypeId="2" PostId="9815" RevisionGUID="c0f31308-3395-40f3-84e2-f011c1fd99ba" CreationDate="2020-05-10T21:43:59.263" UserId="38" Text="This is a similar question to following: When do you need to cook? You can go to a restaurant. Why would you need to know woodworking? You can buy things from a shop.&#xD;&#xA;&#xD;&#xA;There are two answers here&#xD;&#xA;&#xD;&#xA;1. In order for you to claim ownership on some tech. You need to build it. This can be simply because ypu have chosen to sell a competing product or need to lower your licensing fees.&#xD;&#xA;&#xD;&#xA;Note you dont have to be big to benefit from this.&#xD;&#xA;&#xD;&#xA;2. You have custom needs that are not being met by other things. Even if you msinly work in a engine by others you may still need to generate some form of asset or shader to handle some aspect. &#xD;&#xA;&#xD;&#xA;    Not because you exsctly might need it but it makes the product better or it mskes your life easier. Also: If you dont practice then you can never recognize when you could have help in the custom thing. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28203" PostHistoryTypeId="5" PostId="9815" RevisionGUID="7cab2771-d04f-462b-aae7-c4d13c32d6d9" CreationDate="2020-05-10T21:51:08.287" UserId="38" Comment="added 578 characters in body" Text="This is a similar question to following: When do you need to cook? You can go to a restaurant. Why would you need to know woodworking? You can buy things from a shop.&#xD;&#xA;&#xD;&#xA;There are two answers here&#xD;&#xA;&#xD;&#xA;1. In order for you to claim ownership on some tech. You need to build it. This can be simply because you have chosen to sell a competing product or need to lower your licensing fees.&#xD;&#xA;&#xD;&#xA;   Note you dont have to be big to benefit from this.&#xD;&#xA;&#xD;&#xA;2. You have custom needs that are not being met by other things. Even if you mainly work in a engine by others you may still need to generate some form of asset or shader to handle some aspect. &#xD;&#xA;&#xD;&#xA;    Not because you exactly might need it but it makes the product better or it mskes your life easier. Also: If you dont practice then you can never recognize when you could have help in the custom thing. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is really hard to come up with concrete situations where you meed either. Because once that situation arises it gets snatched up by someone so you nolonger need it. &#xD;&#xA;&#xD;&#xA;The thing is the world isnt as ready as you think. And technology has a very nasty habit of dropping you entirely when you need something more. You might suddenly realize that because you stepped slightly out of bounds of your tech you now need to implement a very large chunk of the system since your not covered by their legal framework or their particular implementation does not extend neatly." ContentLicense="CC BY-SA 4.0" />
  <row Id="28204" PostHistoryTypeId="5" PostId="9815" RevisionGUID="97c7394b-f46b-43e9-bb8a-de933976f313" CreationDate="2020-05-10T21:57:56.383" UserId="38" Comment="added 578 characters in body" Text="This is a similar question to following: When do you need to cook? You can go to a restaurant. Why would you need to know woodworking? You can buy things from a shop.&#xD;&#xA;&#xD;&#xA;There are two answers here&#xD;&#xA;&#xD;&#xA;1. In order for you to claim ownership on some tech. You need to build it. This can be simply because you have chosen to sell a competing product or need to lower your licensing fees.&#xD;&#xA;&#xD;&#xA;   Note you dont have to be big to benefit from this.&#xD;&#xA;&#xD;&#xA;2. You have custom needs that are not being met by other things. Even if you mainly work in a engine by others you may still need to generate some form of asset or shader to handle some aspect. &#xD;&#xA;&#xD;&#xA;    Not because you exactly might need it but it makes the product better or it mskes your life easier. Also: If you dont practice then you can never recognize when you could have help in the custom thing. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is really hard to come up with concrete situations where you meed either. Because once that situation arises it gets snatched up by someone so you nolonger need it. &#xD;&#xA;&#xD;&#xA;The thing is the world isnt as ready as you think. And technology has a very nasty habit of dropping you entirely when you need something more. You might suddenly realize that because you stepped slightly out of bounds of your tech you now need to implement a very large chunk of the system since your not covered by their legal framework or their particular implementation does not extend neatly.&#xD;&#xA;&#xD;&#xA;There is also a third option. But you have dismissed it out of hand:&#xD;&#xA;&#xD;&#xA;3. Because you can! I mean ive done a lot of things with this principle. &#xD;&#xA;&#xD;&#xA;    But if you mever do anything like this you might not be invited to do so in the future&#xD;&#xA;&#xD;&#xA;PS: None of this is valid fuel for saying i dont need to learn this. Even if you never use stuff like this knowing it can be done can be extremely valuable. Learning more makes you undertand what can be done better." ContentLicense="CC BY-SA 4.0" />
  <row Id="28205" PostHistoryTypeId="50" PostId="9354" RevisionGUID="5c221f30-d49d-497b-b92d-c144e75f3dc0" CreationDate="2020-05-11T07:04:05.417" UserId="-1" />
  <row Id="28206" PostHistoryTypeId="2" PostId="9816" RevisionGUID="16d85816-fc99-40ce-9e0f-c50b4383c80a" CreationDate="2020-05-11T08:16:02.483" UserId="13343" Text="Shaders get compiled during runtime every single time an app starts. I understand the reasoning for this is that there are so many GPU architectures out there that it does not make sense to ship pre-compiled shaders. However, I wonder if the designers have explored the possibility of storing out the compiled shader during the first run and load the compiled version from the next run. This is akin to having the intermediate &quot;```*.o```&quot; as in C/C++ compilation and just linking them when we're building the app. If this is possible, is it a bad idea to do this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28207" PostHistoryTypeId="1" PostId="9816" RevisionGUID="16d85816-fc99-40ce-9e0f-c50b4383c80a" CreationDate="2020-05-11T08:16:02.483" UserId="13343" Text="Do we have OpenGL shaders write out the intermediate *.o-esque file on first compile so that we can skip compiling them in run-time every single time?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28208" PostHistoryTypeId="3" PostId="9816" RevisionGUID="16d85816-fc99-40ce-9e0f-c50b4383c80a" CreationDate="2020-05-11T08:16:02.483" UserId="13343" Text="|opengl|shader|c++|gpu|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28209" PostHistoryTypeId="5" PostId="9815" RevisionGUID="929a7bed-8a22-43e4-9c9c-2b43fb46fa3c" CreationDate="2020-05-11T08:55:11.663" UserId="38" Comment="edited body" Text="This is a similar question to following: When do you need to cook? You can go to a restaurant. Why would you need to know woodworking? You can buy things from a shop.&#xD;&#xA;&#xD;&#xA;There are two answers here&#xD;&#xA;&#xD;&#xA;1. In order for you to claim ownership on some tech. You need to build it. This can be simply because you have chosen to sell a competing product or need to lower your licensing fees.&#xD;&#xA;&#xD;&#xA;   Note you dont have to be big to benefit from this.&#xD;&#xA;&#xD;&#xA;2. You have custom needs that are not being met by other things. Even if you mainly work in a engine by others you may still need to generate some form of asset or shader to handle some aspect. &#xD;&#xA;&#xD;&#xA;    Not because you exactly might need it but it makes the product better or it mskes your life easier. Also: If you dont practice then you can never recognize when you could have help in the custom thing. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is really hard to come up with concrete situations where you need either. Because once that situation arises it gets snatched up by someone so you nolonger need it. &#xD;&#xA;&#xD;&#xA;The thing is the world isnt as ready as you think. And technology has a very nasty habit of dropping you entirely when you need something more. You might suddenly realize that because you stepped slightly out of bounds of your tech you now need to implement a very large chunk of the system since your not covered by their legal framework or their particular implementation does not extend neatly.&#xD;&#xA;&#xD;&#xA;There is also a third option. But you have dismissed it out of hand:&#xD;&#xA;&#xD;&#xA;3. Because you can! I mean ive done a lot of things with this principle. &#xD;&#xA;&#xD;&#xA;    But if you mever do anything like this you might not be invited to do so in the future&#xD;&#xA;&#xD;&#xA;PS: None of this is valid fuel for saying i dont need to learn this. Even if you never use stuff like this knowing it can be done can be extremely valuable. Learning more makes you undertand what can be done better." ContentLicense="CC BY-SA 4.0" />
  <row Id="28210" PostHistoryTypeId="2" PostId="9817" RevisionGUID="7c04aca7-b84e-402d-8890-8dac54b900a6" CreationDate="2020-05-11T13:50:50.080" UserId="2654" Text="OpenGL 4.1's [`glGetProgramBinary`][1] and [`glProgramBinary`][2] exist for this purpose. The first one retrieves a binary that represents the compiled program in its entirety (though none of the state stored within it. It, and its implementation-defined format, can be stored and reloaded via `glProgramBinary`.&#xD;&#xA;&#xD;&#xA;Of course, there are limitations. Implementations are not required to be able to load the format they gave you. That is, a driver change could cause implementations to switch to a different versions, leaving all of your binaries obsolete and un-loadable. So you have to be ready to recompile from the source.&#xD;&#xA;&#xD;&#xA;Alternatively, GL 4.6 allows you to [employ SPIR-V][3], an intermediate shader language. The idea here is that you compile your code to SPIR-V, then load that SPIR-V into a shader, where you can move forward from there. There are no version changes that could break your code.&#xD;&#xA;&#xD;&#xA;Of course, SPIR-V is an intermediate language, so it still has to be compiled to some degree, along with all of the error checking and the like needed to make the final GPU code. It won't be faster than program binaries, but it's a bit more reliable (for implementations that support it).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramBinary.xhtml&#xD;&#xA;  [2]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramBinary.xhtml&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/SPIR-V" ContentLicense="CC BY-SA 4.0" />
  <row Id="28211" PostHistoryTypeId="2" PostId="9818" RevisionGUID="b009cff9-a05c-4efc-a859-14b5f65265cc" CreationDate="2020-05-11T15:58:34.627" UserId="13321" Text="If you are asking whether:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int fr(...) cos\theta_1Le_1 &gt; \int fr(...)cos\theta_1 fr(...)cos\theta_2 Le_2&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;(simplified terms from the render equation you posted above), I don't think you could prove this. Le_2 could just be much greater than Le_1. &#xD;&#xA;&#xD;&#xA;For example you could have a set of mirrors which only hit a light source after two bounces. Then all the light would come from the second integral." ContentLicense="CC BY-SA 4.0" />
  <row Id="28213" PostHistoryTypeId="2" PostId="9820" RevisionGUID="7f6aa7a1-5ee3-40ce-9aac-f68ea1522ab9" CreationDate="2020-05-11T16:52:16.790" UserId="6281" Text="I am new to concepts in CG. What are the red and white rectangles trying to represent in the following screenshot?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rU0eh.jpg&#xD;&#xA;&#xD;&#xA;The image is from the paper &quot;MoSh: Motion and Shape Capture from Sparse Markers&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="28214" PostHistoryTypeId="1" PostId="9820" RevisionGUID="7f6aa7a1-5ee3-40ce-9aac-f68ea1522ab9" CreationDate="2020-05-11T16:52:16.790" UserId="6281" Text="chess-like rectangles on the mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="28215" PostHistoryTypeId="3" PostId="9820" RevisionGUID="7f6aa7a1-5ee3-40ce-9aac-f68ea1522ab9" CreationDate="2020-05-11T16:52:16.790" UserId="6281" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28216" PostHistoryTypeId="5" PostId="9809" RevisionGUID="fa3bb6a1-22be-473c-9ea0-f6eb7ab99675" CreationDate="2020-05-11T17:09:22.317" UserId="13225" Comment="Latexified" Text="When ray tracing, I find it intuitively clear that deeper paths have a lower contribution to the overal picture than shorter paths. This is the main reason why it is generally okay to render a picture only to a certain depth, but I am currently not able to prove this.&#xD;&#xA;&#xD;&#xA;Formally, we can write the rendering equation as&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o(\vec{p}_0, \omega_0) &amp;= L_e(\vec{p}_0, \omega_0) \\&#xD;&#xA;    &amp;+ \int_{\Omega} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} L_e(\vec{p}_1, \omega_1) \text{d} \omega_1 \\&#xD;&#xA;    &amp;+ \int_{\Omega^2} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} f_r(\vec{p}_1, \omega_1, -\omega_2) \cos{\theta_2} L_e(\vec{p}_2, \omega_2) \text{d} \omega_1 \text{d} \omega_2 \\&#xD;&#xA;    &amp;+ \dots \,,&#xD;&#xA;\end{align*}&#xD;&#xA;where $\vec{p}_{j+1}$ is defined as the intersection of a ray with origin $\vec{p}_j$ and direction $-\omega_{j+1}$ and $\theta_{j+1}$ is the angle between the normal of the surface at $\vec{p}_j$ and $-\omega_{j+1}$. Each term represents the radiance contribution of respectively paths with depth 0, 1, 2, and so on. Let's denote the contribution of depth $d$ with $L_o^{(d)}(\vec{p}_0, \omega_0)$. **I suspect that, under mild conditions on the scene, the contributions of these terms will asymptotically decrease exponentially:** $$L_o^{(d)}(\vec{p}_0, \omega_0) = \mathcal{O}(t^d)$$ for some $t$ with $0 &lt; t &lt; 1$, where I have used the big-O notation.&#xD;&#xA;&#xD;&#xA;Of course, I expect this only to hold when the scene is somehow &quot;realistic&quot;, which I define as follows.&#xD;&#xA;&#xD;&#xA;Firstly, all light sources should have only a limited amount of power. Note that infinite radiances, like with point lights, should be permitted, as long as their power is finite. &#xD;&#xA;  &#xD;&#xA;1.  **The total power of all light sources should be finite.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/RbHvb.gif&quot; width=&quot;250&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Secondly, we should exclude scenes that consists only of mirrors or diffuse white materials, or any other material that perfectly conserves energy. In other words, the scene should always absorb a little energy. These materials should still be permitted though, as long as their reflected light eventually ends up in materials that do not conserve the energy. I tried to formalize this the following way.&#xD;&#xA;&#xD;&#xA;2. **There exists an integer $k$ with the following property: for every point $\vec{p}$ in the scene there should be a path of length $k$ that starts in $\vec{p}$ and which has a throughput smaller than 1.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KzuU3.gif&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;Using these assumptions, is it possible to prove my suspicion? How would you do it?&#xD;&#xA;&#xD;&#xA;If it isn't possible, are there other &quot;realistic&quot; conditions that will make it proveable? Any conditions you come up with should not limit scenes that are used in practice in any way. (I know, sometimes people create materials that transmit more light than what comes in. You can ignore these materials).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**What I tried so far.**&#xD;&#xA;&#xD;&#xA;I was able to prove this with some stronger conditions, namely&#xD;&#xA;&#xD;&#xA;1. There is an upperbound $L_{max}$ on emitted radiance $L_e$.&#xD;&#xA;2. There is an upperbound $t &lt; 1$ on the percentage of energy that materials conserve.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0oNkf.gif&quot; width=&quot;360&quot; /&gt;&#xD;&#xA;&#xD;&#xA;With these conditions, the prove is straightforward, but they do not allow point lights or perfectly white diffuse materials and such." ContentLicense="CC BY-SA 4.0" />
  <row Id="28217" PostHistoryTypeId="5" PostId="9809" RevisionGUID="7a191319-5e39-4e60-91d8-c84f2e04223b" CreationDate="2020-05-11T17:20:03.993" UserId="13225" Comment="added 764 characters in body" Text="When ray tracing, I find it intuitively clear that deeper paths have a lower contribution to the overal picture than shorter paths. This is the main reason why it is generally okay to render a picture only to a certain depth, but I am currently not able to prove this.&#xD;&#xA;&#xD;&#xA;Formally, we can write the rendering equation as&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o(\vec{p}_0, \omega_0) &amp;= L_e(\vec{p}_0, \omega_0) \\&#xD;&#xA;    &amp;+ \int_{\Omega} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} L_e(\vec{p}_1, \omega_1) \text{d} \omega_1 \\&#xD;&#xA;    &amp;+ \int_{\Omega^2} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} f_r(\vec{p}_1, \omega_1, -\omega_2) \cos{\theta_2} L_e(\vec{p}_2, \omega_2) \text{d} \omega_1 \text{d} \omega_2 \\&#xD;&#xA;    &amp;+ \dots \,,&#xD;&#xA;\end{align*}&#xD;&#xA;where $\vec{p}_{j+1}$ is defined as the intersection of a ray with origin $\vec{p}_j$ and direction $-\omega_{j+1}$ and $\theta_{j+1}$ is the angle between the normal of the surface at $\vec{p}_j$ and $-\omega_{j+1}$. Each term represents the radiance contribution of respectively paths with depth 0, 1, 2, and so on. Let's denote the contribution of depth $d$ with $L_o^{(d)}(\vec{p}_0, \omega_0)$. **I suspect that, under mild conditions on the scene, the contributions of these terms will asymptotically decrease exponentially:** $$L_o^{(d)}(\vec{p}_0, \omega_0) = \mathcal{O}(t^d)$$ for some $t$ with $0 &lt; t &lt; 1$, where I have used the big-O notation.&#xD;&#xA;&#xD;&#xA;Of course, I expect this only to hold when the scene is somehow &quot;realistic&quot;, which I define as follows.&#xD;&#xA;&#xD;&#xA;Firstly, all light sources should have only a limited amount of power. Note that infinite radiances, like with point lights, should be permitted, as long as their power is finite. &#xD;&#xA;  &#xD;&#xA;1.  **The total power of all light sources should be finite.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/RbHvb.gif&quot; width=&quot;250&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Secondly, we should exclude scenes that consists only of mirrors or diffuse white materials, or any other material that perfectly conserves energy. In other words, the scene should always absorb a little energy. These materials should still be permitted though, as long as their reflected light eventually ends up in materials that do not conserve the energy. I tried to formalize this the following way.&#xD;&#xA;&#xD;&#xA;2. **There exists an integer $k$ with the following property: for every point $\vec{p}$ in the scene there should be a path of length $k$ that starts in $\vec{p}$ and which has a throughput smaller than 1.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KzuU3.gif&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;Using these assumptions, is it possible to prove my suspicion? How would you do it?&#xD;&#xA;&#xD;&#xA;If it isn't possible, are there other &quot;realistic&quot; conditions that will make it proveable? Any conditions you come up with should not limit scenes that are used in practice in any way. (I know, sometimes people create materials that transmit more light than what comes in. You can ignore these materials).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**What I tried so far.**&#xD;&#xA;&#xD;&#xA;I was able to prove this with some stronger conditions, namely&#xD;&#xA;&#xD;&#xA;1. There is an upperbound $L_{max}$ on emitted radiance $L_e$.&#xD;&#xA;2. There is an upperbound $t &lt; 1$ on the percentage of energy that materials conserve.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0oNkf.gif&quot; width=&quot;360&quot; /&gt;&#xD;&#xA;&#xD;&#xA;With these conditions, the prove is straightforward, but they do not allow point lights or perfectly white diffuse materials and such.&#xD;&#xA;&#xD;&#xA;*Proof.*&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o^{(d)}(\vec{p}_0, \omega_0) &amp;= \int_{\Omega^d} \left(\prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \right) L_e(\vec{p}_d, \omega_d) \text{d} \omega_1 \dots \text{d} \omega_d&#xD;&#xA;\end{align*}&#xD;&#xA;Using condition (1):&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \int_{\Omega^d} \prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \text{d}\omega_j \\&#xD;&#xA;    &amp;= L_{max} \int_{\Omega} \text{d}\omega_1 f_r(\vec{p}_{0}, \omega_{0}, -\omega_1) \cos{\theta_1} \int_\Omega \dotsm \int_{\Omega} \text{d}\omega_d f_r(\vec{p}_{d-1}, \omega_{d-1}, -\omega_d) \cos{\theta_d}&#xD;&#xA;\end{align*}&#xD;&#xA;By applying condition (2) recursively on the innermost integral:&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \tau^d&#xD;&#xA;\end{align*}" ContentLicense="CC BY-SA 4.0" />
  <row Id="28219" PostHistoryTypeId="5" PostId="9809" RevisionGUID="22a0b3c2-d415-4f1e-bea2-7d5feabc231a" CreationDate="2020-05-11T18:29:54.630" UserId="13225" Comment="added 2 characters in body" Text="When ray tracing, I find it intuitively clear that deeper paths have a lower contribution to the overal picture than shorter paths. This is the main reason why it is generally okay to render a picture only to a certain depth, but I am currently not able to prove this.&#xD;&#xA;&#xD;&#xA;Formally, we can write the rendering equation as&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o(\vec{p}_0, \omega_0) &amp;= L_e(\vec{p}_0, \omega_0) \\&#xD;&#xA;    &amp;+ \int_{\Omega} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} L_e(\vec{p}_1, \omega_1) \text{d} \omega_1 \\&#xD;&#xA;    &amp;+ \int_{\Omega^2} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} f_r(\vec{p}_1, \omega_1, -\omega_2) \cos{\theta_2} L_e(\vec{p}_2, \omega_2) \text{d} \omega_1 \text{d} \omega_2 \\&#xD;&#xA;    &amp;+ \dots \,,&#xD;&#xA;\end{align*}&#xD;&#xA;where $\vec{p}_{j+1}$ is defined as the intersection of a ray with origin $\vec{p}_j$ and direction $-\omega_{j+1}$ and $\theta_{j+1}$ is the angle between the normal of the surface at $\vec{p}_j$ and $-\omega_{j+1}$. Each term represents the radiance contribution of respectively paths with depth 0, 1, 2, and so on. Let's denote the contribution of depth $d$ with $L_o^{(d)}(\vec{p}_0, \omega_0)$. **I suspect that, under mild conditions on the scene, the contributions of these terms will asymptotically decrease exponentially:** $$L_o^{(d)}(\vec{p}_0, \omega_0) = \mathcal{O}(t^d)$$ for some $t$ with $0 &lt; t &lt; 1$, where I have used the big-O notation.&#xD;&#xA;&#xD;&#xA;Of course, I expect this only to hold when the scene is somehow &quot;realistic&quot;, which I define as follows.&#xD;&#xA;&#xD;&#xA;Firstly, all light sources should have only a limited amount of power. Note that infinite radiances, like with point lights, should be permitted, as long as their power is finite. &#xD;&#xA;  &#xD;&#xA;1.  **The total power of all light sources should be finite.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/RbHvb.gif&quot; width=&quot;250&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Secondly, we should exclude scenes that consists only of mirrors or diffuse white materials, or any other material that perfectly conserves energy. In other words, the scene should always absorb a little energy. These materials should still be permitted though, as long as their reflected light eventually ends up in materials that do not conserve the energy. I tried to formalize this the following way.&#xD;&#xA;&#xD;&#xA;2. **There exists an integer $k$ with the following property: for every point $\vec{p}$ in the scene there should be a path of length $k$ that starts in $\vec{p}$ and which has a throughput smaller than 1.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KzuU3.gif&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;Using these assumptions, is it possible to prove my suspicion? How would you do it?&#xD;&#xA;&#xD;&#xA;If it isn't possible, are there other &quot;realistic&quot; conditions that will make it proveable? Any conditions you come up with should not limit scenes that are used in practice in any way. (I know, sometimes people create materials that transmit more light than what comes in. You can ignore these materials).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**What I tried so far.**&#xD;&#xA;&#xD;&#xA;I was able to prove this with some stronger conditions, namely&#xD;&#xA;&#xD;&#xA;1. There is an upper bound $L_{max}$ on emitted radiance $L_e$.&#xD;&#xA;2. There is an upper bound $t &lt; 1$ on the percentage of energy that materials conserve.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0oNkf.gif&quot; width=&quot;360&quot; /&gt;&#xD;&#xA;&#xD;&#xA;With these conditions, the prove is straightforward, but they do not allow point lights or perfectly white diffuse materials and such.&#xD;&#xA;&#xD;&#xA;*Proof.*&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o^{(d)}(\vec{p}_0, \omega_0) &amp;= \int_{\Omega^d} \left(\prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \right) L_e(\vec{p}_d, \omega_d) \text{d} \omega_1 \dots \text{d} \omega_d&#xD;&#xA;\end{align*}&#xD;&#xA;Using condition (1):&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \int_{\Omega^d} \prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \text{d}\omega_j \\&#xD;&#xA;    &amp;= L_{max} \int_{\Omega} \text{d}\omega_1 f_r(\vec{p}_{0}, \omega_{0}, -\omega_1) \cos{\theta_1} \int_\Omega \dotsm \int_{\Omega} \text{d}\omega_d f_r(\vec{p}_{d-1}, \omega_{d-1}, -\omega_d) \cos{\theta_d}&#xD;&#xA;\end{align*}&#xD;&#xA;By applying condition (2) recursively on the innermost integral:&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \tau^d&#xD;&#xA;\end{align*}" ContentLicense="CC BY-SA 4.0" />
  <row Id="28220" PostHistoryTypeId="6" PostId="9809" RevisionGUID="88fe5383-1d7f-4ec4-a3db-7ad62c34318f" CreationDate="2020-05-11T20:13:45.340" UserId="13225" Comment="edited tags" Text="|raytracing|lighting|mathematics|physically-based|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28221" PostHistoryTypeId="2" PostId="9821" RevisionGUID="bd976304-9edc-434d-a010-75988ee84c05" CreationDate="2020-05-11T22:07:56.647" UserId="11058" Text="I'm working on a simple 3d modeller and I would like to render the back facing triangles a bit darker, to easier differentiate between front and back faces. Like you can see in most modelling applications. How does one achieve is? As is when I render triangles front and back faces get shaded identically." ContentLicense="CC BY-SA 4.0" />
  <row Id="28222" PostHistoryTypeId="1" PostId="9821" RevisionGUID="bd976304-9edc-434d-a010-75988ee84c05" CreationDate="2020-05-11T22:07:56.647" UserId="11058" Text="Render front and back faces with different shading" ContentLicense="CC BY-SA 4.0" />
  <row Id="28223" PostHistoryTypeId="3" PostId="9821" RevisionGUID="bd976304-9edc-434d-a010-75988ee84c05" CreationDate="2020-05-11T22:07:56.647" UserId="11058" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28224" PostHistoryTypeId="4" PostId="9821" RevisionGUID="8b469fdf-0b46-4dbe-bef8-713d477be423" CreationDate="2020-05-11T22:14:54.243" UserId="11058" Comment="edited tags; edited title" Text="OpenGL Render front and back faces with different shading for 3d modeller" ContentLicense="CC BY-SA 4.0" />
  <row Id="28225" PostHistoryTypeId="6" PostId="9821" RevisionGUID="8b469fdf-0b46-4dbe-bef8-713d477be423" CreationDate="2020-05-11T22:14:54.243" UserId="11058" Comment="edited tags; edited title" Text="|opengl|shading|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28226" PostHistoryTypeId="5" PostId="9821" RevisionGUID="2872d5a1-574f-4b1a-84b6-48ab1c1478e4" CreationDate="2020-05-11T22:31:24.897" UserId="11058" Comment="added 103 characters in body" Text="I'm working on a simple 3d modeller and I would like to render the back facing triangles a bit darker, to easier differentiate between front and back faces. Like you can see in most modelling applications. How does one achieve is?&#xD;&#xA;&#xD;&#xA;Should I enable back face culling and render the primitives and then enable front face culling, rotate the normals by 180 degrees and render the primitives again? Is this a practical approach?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28227" PostHistoryTypeId="2" PostId="9822" RevisionGUID="8d021d46-9190-4282-bca0-f4533dd0c874" CreationDate="2020-05-12T01:55:50.563" UserId="2654" Text="A fragment shader receives the [`gl_FrontFacing` system-defined input value][1]. It will be `false` if the fragment was generated from a back-facing triangle, and `true` otherwise. So you can use that in your shader to determine how to generate a color value.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Fragment_Shader#System_inputs" ContentLicense="CC BY-SA 4.0" />
  <row Id="28228" PostHistoryTypeId="2" PostId="9823" RevisionGUID="159db3d3-2598-43f8-8a4c-e7fa15423585" CreationDate="2020-05-12T10:52:58.797" UserId="13321" Text="I don't think it's trying to represent anything in particular.&#xD;&#xA;&#xD;&#xA;In CG there is a concept of textures, which is a bit like painting the surface of an object a specific color/look. For example, on a car you may want to paint scratches and dust on the surface.&#xD;&#xA;&#xD;&#xA;Here they have created a human model from their capture data, and when visualising it they have decided to texture/paint a red/white checker pattern on top.&#xD;&#xA;&#xD;&#xA;They have most likely added it for the viewer's benifit, as it helps emphasise the curves and overall shape of the model, esspesially as it animates. They also probably chose contrasting colors so the model was easier to view on a white background." ContentLicense="CC BY-SA 4.0" />
  <row Id="28229" PostHistoryTypeId="5" PostId="9818" RevisionGUID="4d12727d-4a34-4dbc-a87e-07bda572701e" CreationDate="2020-05-12T11:29:15.833" UserId="13321" Comment="Added a second answer" Text="If you are asking whether:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int fr(...) cos\theta_1Le_1 &gt; \int fr(...)cos\theta_1 fr(...)cos\theta_2 Le_2&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;(simplified terms from the render equation you posted above), I don't think you could prove this. Le_2 could just be much greater than Le_1. &#xD;&#xA;&#xD;&#xA;For example you could have a set of mirrors which only hit a light source after two bounces. Then all the light would come from the second integral.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;EDIT: Updating answer after your response.&#xD;&#xA;&#xD;&#xA;If you are trying to prove that, ignoring the layout and lights of the scene, deeper paths contribute less to the overall equation, then you could try ignoring Le and assuming it is always 1. You are then trying to prove:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int_\Omega fr(...)cos\theta_1  &gt; \int_{\Omega^2}fr(...)cos\theta_1fr(...)cos\theta_2&#xD;&#xA;$$&#xD;&#xA;or&#xD;&#xA;$$&#xD;&#xA;\int_{\Omega_1} fr(...)cos\theta_1 dw_1 &gt; \int_{\Omega_1} fr(...)cos\theta_1\int_{\Omega_2} fr(...)cos\theta_2 dw_2 dw_1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;We also know that if the fr is energy conserving:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;0 \leq \int fr(...)  \leq 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And if 0 &lt; cos &lt; 1 we can say that:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;0 \leq \int fr(...)cos\theta \leq 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Substituting this knowlege into the equation into the inner integration of the right hand side doesnt give us much, as it could always be equal to 1 which would give us: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int_{\Omega_2} fr(...)cos\theta_2 dw_2  = 1&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;\int_{\Omega_1} fr(...)cos\theta_1 dw_1 &gt; \int_{\Omega_1} fr(...)cos\theta_1 dw_1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;which disproves your idea. However if your bxdf is never perfectly energy conserving, eg:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;0 \leq \int fr(...)  &lt; 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I think subsitituting this in does prove the above as we get something like:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;0 \leq n(w) &lt; 1&#xD;&#xA;$$&#xD;&#xA;$$&#xD;&#xA;\int_{\Omega_1} fr(...)cos\theta_1 dw_1 &gt; \int_{\Omega_1} fr(...)cos\theta_1 n(w)dw_1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As each term can only be less than the integral on the left.&#xD;&#xA;&#xD;&#xA;Hopefully my math is okay here I might have made a mistake. You may need to clean it up and do some more formal proofs. I am sorry if this still doesnt help answer your question." ContentLicense="CC BY-SA 4.0" />
  <row Id="28230" PostHistoryTypeId="2" PostId="9824" RevisionGUID="b65cf065-0444-435c-8a5e-259e8811dacf" CreationDate="2020-05-12T15:27:41.173" UserId="13309" Text="I am writing a small raytracer in python , everything was working fine but when i implemented plane geometry then the reflective spheres are getting weird patches on lower bottom. image below:&#xD;&#xA;&#xD;&#xA;*I guess this is happening because of some error in calculating lighting with wrong normals? but i am unable to figure out exactly what.*&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fHB56.png&#xD;&#xA;&#xD;&#xA;code to find palne-ray intersection:&#xD;&#xA;&#xD;&#xA;    class Plane(Shape):&#xD;&#xA;        def __init__(self, color, y=0, specular=-1, reflective=0):&#xD;&#xA;            self.specular = specular&#xD;&#xA;            self.reflective = reflective&#xD;&#xA;            self.center = Vec3(0,y,0)&#xD;&#xA;            self.normal = Vec3(0,-1,0)&#xD;&#xA;            self.color = color&#xD;&#xA;    &#xD;&#xA;        def intersect_at_point(self, origin, ray):&#xD;&#xA;    &#xD;&#xA;            denom = ray.dot(self.normal)&#xD;&#xA;    &#xD;&#xA;            if abs(denom) &gt; 0.0001:&#xD;&#xA;                diff  = self.center - ray&#xD;&#xA;                t = diff.dot(self.normal) / denom&#xD;&#xA;    &#xD;&#xA;                if t &gt; 0.0001:&#xD;&#xA;                    return t&#xD;&#xA;            return None&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;trace ray function.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    def trace_ray(self, origin, direction, t_min, t_max, depth):&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;    &#xD;&#xA;        closest_object, closest_t = self.closest_intersection(origin, direction, t_min, t_max)&#xD;&#xA;    &#xD;&#xA;        if closest_object == None:&#xD;&#xA;            return Vec3(173/255, 216/255, 230/255)&#xD;&#xA;    &#xD;&#xA;        # Compute local color&#xD;&#xA;        P = origin + closest_t * direction  # Compute intersection&#xD;&#xA;        N = P - closest_object.center  # Compute  normal at intersection&#xD;&#xA;        N = N / N.mag()&#xD;&#xA;        local_color = closest_object.color * self.compute_light(P, N)&#xD;&#xA;    &#xD;&#xA;        # If we hit the recursion limit or the object is not reflective, we're done&#xD;&#xA;        r = closest_object.reflective&#xD;&#xA;        if depth &lt;= 0 or r &lt;= 0:&#xD;&#xA;            return local_color&#xD;&#xA;    &#xD;&#xA;        # Compute the reflected color&#xD;&#xA;        R = self.reflect_ray(-1*direction, N)&#xD;&#xA;        reflected_color = self.trace_ray(P, R, 0.001, math.inf, depth - 1)&#xD;&#xA;    &#xD;&#xA;        return local_color * (1 - r) + reflected_color * r&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;closest intersection method.&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;      def closest_intersection(self, O, D, t_min, t_max):&#xD;&#xA;            closest_t = math.inf&#xD;&#xA;            closest_object = None&#xD;&#xA;    &#xD;&#xA;            for object in self.world.objects:&#xD;&#xA;                t1, t2 = object.intersect_at_point(O, D)&#xD;&#xA;    &#xD;&#xA;                if (t_min &lt; t1 &lt; t_max) and t1 &lt; closest_t:&#xD;&#xA;                    closest_t = t1&#xD;&#xA;                    closest_object = object&#xD;&#xA;    &#xD;&#xA;                if (t_min &lt; t2 &lt; t_max) and t2 &lt; closest_t:&#xD;&#xA;                    closest_t = t2&#xD;&#xA;                    closest_object = object&#xD;&#xA;    &#xD;&#xA;            for plane in self.world.planes:&#xD;&#xA;    &#xD;&#xA;                t = plane.intersect_at_point(O,D)&#xD;&#xA;    &#xD;&#xA;                if t and (t_min &lt; t &lt; t_max) and t &lt; closest_t:&#xD;&#xA;                        closest_t = t&#xD;&#xA;                        closest_object = plane&#xD;&#xA;    &#xD;&#xA;            return closest_object, closest_t&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Calculate light method.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;def compute_light(self, Point, Normal):&#xD;&#xA;&#xD;&#xA;    i = 0.0&#xD;&#xA;    P = Point&#xD;&#xA;    N = Normal&#xD;&#xA;&#xD;&#xA;    for light in self.world.lights:&#xD;&#xA;        if light.type == 'ambient':&#xD;&#xA;            i += light.intensity&#xD;&#xA;        else:&#xD;&#xA;            if light.type == 'point':&#xD;&#xA;                L = light.position - P&#xD;&#xA;                t_max = 1&#xD;&#xA;&#xD;&#xA;            if light.type == 'directional':&#xD;&#xA;                L = light.direction&#xD;&#xA;                t_max = math.inf&#xD;&#xA;&#xD;&#xA;            # Shadow check&#xD;&#xA;            shadow_sphere, shadow_t = self.closest_intersection(P, L, 0.001, t_max)&#xD;&#xA;            if shadow_sphere != None:&#xD;&#xA;                continue&#xD;&#xA;&#xD;&#xA;            n_dot_l = N.dot(L)&#xD;&#xA;&#xD;&#xA;            if n_dot_l &gt; 0:&#xD;&#xA;                # print(f'light intensity {light.intensity}')&#xD;&#xA;                i+= light.intensity * n_dot_l / (N.mag() * L.mag())&#xD;&#xA;&#xD;&#xA;    return i&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="28231" PostHistoryTypeId="1" PostId="9824" RevisionGUID="b65cf065-0444-435c-8a5e-259e8811dacf" CreationDate="2020-05-12T15:27:41.173" UserId="13309" Text="Weird patch on reflective spheres on planes in raytracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="28232" PostHistoryTypeId="3" PostId="9824" RevisionGUID="b65cf065-0444-435c-8a5e-259e8811dacf" CreationDate="2020-05-12T15:27:41.173" UserId="13309" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28233" PostHistoryTypeId="5" PostId="9809" RevisionGUID="473abbee-8cf1-45d5-94f7-08acc3cb1cca" CreationDate="2020-05-12T15:29:16.920" UserId="13225" Comment="added 35 characters in body" Text="When ray tracing, I find it intuitively clear that deeper paths have a lower contribution to the overal picture than shorter paths. This is the main reason why it is generally okay to render a picture only to a certain depth, but I am currently not able to prove this.&#xD;&#xA;&#xD;&#xA;Formally, we can write the rendering equation as&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o(\vec{p}_0, \omega_0) &amp;= L_e(\vec{p}_0, \omega_0) \\&#xD;&#xA;    &amp;+ \int_{\Omega} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} L_e(\vec{p}_1, \omega_1) \text{d} \omega_1 \\&#xD;&#xA;    &amp;+ \int_{\Omega^2} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} f_r(\vec{p}_1, \omega_1, -\omega_2) \cos{\theta_2} L_e(\vec{p}_2, \omega_2) \text{d} \omega_1 \text{d} \omega_2 \\&#xD;&#xA;    &amp;+ \dots \,,&#xD;&#xA;\end{align*}&#xD;&#xA;where $\vec{p}_{j+1}$ is defined as the intersection of a ray with origin $\vec{p}_j$ and direction $-\omega_{j+1}$ and $\theta_{j+1}$ is the angle between the normal of the surface at $\vec{p}_j$ and $-\omega_{j+1}$. Each term represents the radiance contribution of respectively paths with depth 0, 1, 2, and so on. Let's denote the contribution of depth $d$ with $L_o^{(d)}(\vec{p}_0, \omega_0)$. **I suspect that, under mild conditions on the scene, the contributions of these terms will asymptotically decrease exponentially:** $$L_o^{(d)}(\vec{p}_0, \omega_0) = \mathcal{O}(t^d) \,\text{ as } d \rightarrow \infty$$ for some $t$ with $0 &lt; t &lt; 1$, where I have used the big-O notation.&#xD;&#xA;&#xD;&#xA;Of course, I expect this only to hold when the scene is somehow &quot;realistic&quot;, which I define as follows.&#xD;&#xA;&#xD;&#xA;Firstly, all light sources should have only a limited amount of power. Note that infinite radiances, like with point lights, should be permitted, as long as their power is finite. &#xD;&#xA;  &#xD;&#xA;1.  **The total power of all light sources should be finite.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/RbHvb.gif&quot; width=&quot;250&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Secondly, we should exclude scenes that consists only of mirrors or diffuse white materials, or any other material that perfectly conserves energy. In other words, the scene should always absorb a little energy. These materials should still be permitted though, as long as their reflected light eventually ends up in materials that do not conserve the energy. I tried to formalize this the following way.&#xD;&#xA;&#xD;&#xA;2. **There exists an integer $k$ with the following property: for every point $\vec{p}$ in the scene there should be a path of length $k$ that starts in $\vec{p}$ and which has a throughput smaller than 1.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KzuU3.gif&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;Using these assumptions, is it possible to prove my suspicion? How would you do it?&#xD;&#xA;&#xD;&#xA;If it isn't possible, are there other &quot;realistic&quot; conditions that will make it proveable? Any conditions you come up with should not limit scenes that are used in practice in any way. (I know, sometimes people create materials that transmit more light than what comes in. You can ignore these materials).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**What I tried so far.**&#xD;&#xA;&#xD;&#xA;I was able to prove this with some stronger conditions, namely&#xD;&#xA;&#xD;&#xA;1. There is an upper bound $L_{max}$ on emitted radiance $L_e$.&#xD;&#xA;2. There is an upper bound $t &lt; 1$ on the percentage of energy that materials conserve.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0oNkf.gif&quot; width=&quot;360&quot; /&gt;&#xD;&#xA;&#xD;&#xA;With these conditions, the prove is straightforward, but they do not allow point lights or perfectly white diffuse materials and such.&#xD;&#xA;&#xD;&#xA;*Proof.*&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o^{(d)}(\vec{p}_0, \omega_0) &amp;= \int_{\Omega^d} \left(\prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \right) L_e(\vec{p}_d, \omega_d) \text{d} \omega_1 \dots \text{d} \omega_d&#xD;&#xA;\end{align*}&#xD;&#xA;Using condition (1):&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \int_{\Omega^d} \prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \text{d}\omega_j \\&#xD;&#xA;    &amp;= L_{max} \int_{\Omega} \text{d}\omega_1 f_r(\vec{p}_{0}, \omega_{0}, -\omega_1) \cos{\theta_1} \int_\Omega \dotsm \int_{\Omega} \text{d}\omega_d f_r(\vec{p}_{d-1}, \omega_{d-1}, -\omega_d) \cos{\theta_d}&#xD;&#xA;\end{align*}&#xD;&#xA;By applying condition (2) recursively on the innermost integral:&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \tau^d&#xD;&#xA;\end{align*}" ContentLicense="CC BY-SA 4.0" />
  <row Id="28234" PostHistoryTypeId="2" PostId="9825" RevisionGUID="771de55b-941a-4276-a1fe-bbad1315543a" CreationDate="2020-05-12T18:12:25.863" UserId="13359" Text="I am wondering this, as e.g. YouTube offers some videos 60fps, but computer may be too slow to play them." ContentLicense="CC BY-SA 4.0" />
  <row Id="28235" PostHistoryTypeId="1" PostId="9825" RevisionGUID="771de55b-941a-4276-a1fe-bbad1315543a" CreationDate="2020-05-12T18:12:25.863" UserId="13359" Text="Is it possible to decode and play e.g. 60fps video as 30fps, if computer is too slow for 60fps?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28236" PostHistoryTypeId="3" PostId="9825" RevisionGUID="771de55b-941a-4276-a1fe-bbad1315543a" CreationDate="2020-05-12T18:12:25.863" UserId="13359" Text="|video|efficiency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28237" PostHistoryTypeId="2" PostId="9826" RevisionGUID="227eeeb2-26df-4ef1-a73c-abd4baaf6649" CreationDate="2020-05-12T18:57:09.520" UserId="13359" Text="You could try to play 1080p and 2160p videos, possibly 60fps in YouTube. If you right-click on the playback window and click on &quot;Stats for nerds&quot; you will get more information about used video and audio codecs and dropped frames, which can indicate that your hardware may be too slow. Currently the videos are mostly encoded as VP9 codec, but you can change settings to prefer AV1 codec, at https://www.youtube.com/account_playback. However please note that not all videos are available as AV1, but you can find some videos at [AV1 Beta Launch Playlist][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/playlist?list=PLyqf6gJt7KuHBmeVzZteZUlNUQAVLwrZS" ContentLicense="CC BY-SA 4.0" />
  <row Id="28238" PostHistoryTypeId="5" PostId="9813" RevisionGUID="8cbacada-cd3a-4ab9-aeab-f654cbd9e901" CreationDate="2020-05-12T20:55:31.210" UserId="13346" Comment="added 6 characters in body" Text="I had this doubt in my head for several months and have been unable to find an answer anywhere on internet.&#xD;&#xA;&#xD;&#xA;I know what OpenGL, DirectX, Vulkan, Metal, etc... are, I already know what they are used for (literally in any multimedia software application).&#xD;&#xA;&#xD;&#xA;My question is &quot;in the real world when people work directly with a graphical API (eg: DirectX)?&quot;.&#xD;&#xA;&#xD;&#xA;For example, if I want to create a game I will use a game engine, if I want to create special effects I will use a program for VFX, if I want to create an animated scene with different 3D models I will use something like Blender.&#xD;&#xA;&#xD;&#xA;What are the situations where a person could say &quot;Ok, this problem can only be solved by writing my own software with DirectX/C++&quot;?&#xD;&#xA;&#xD;&#xA;My question arises from the fact that I would like to learn DirectX (later Vulkan also) as a matter of curiosity but I know that graphic programming is a demanding topic that requires a lot (a lot!) of time.&#xD;&#xA;&#xD;&#xA;I work for a company most of my day and since the salary is quite low (especially because at 21yo nobody takes you seriously), in the evening I dedicate myself to secondary activities in order to earn something more. I can't find a good reason to stop dedicating myself to these activities to study something that will not lead me to any type of business.&#xD;&#xA;&#xD;&#xA;In my country (Italy) there are some (not a lot) job offerings concerning graphic programming but all require a degree in Metematics/Physics, which I don't have.&#xD;&#xA;&#xD;&#xA;So, in summary, what are the situations where you need to &quot;get your hands dirty&quot; with a graphical API (eg: DirectX) instead of using a tool already made?&#xD;&#xA;&#xD;&#xA;I know there are big game companies that for example reinvent the wheel (they write the rendering engine from 0) because they will pay off the costs and it is not convenient for them to pay for an engine already made. This environment doesn't interest me much because it certainly cannot lead to an individual business.&#xD;&#xA;&#xD;&#xA;Other situations where you work directly with a graphical API is the world of simulations, but there I imagine it is more a matter of mathematics and physics, not of graphics.&#xD;&#xA;&#xD;&#xA;I'd like to read about some experience of those who work/worked with a graphic API and what your role was in the industry. I'd also like to read about someone who has his own business that somehow relates to a graphical API.&#xD;&#xA;&#xD;&#xA;Thanks a lot to everyone :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28242" PostHistoryTypeId="36" PostId="9828" RevisionGUID="14c2628f-2f30-4fc7-982f-5357b60a4b90" CreationDate="2020-05-13T08:19:20.643" UserId="-1" Comment="from https://stackoverflow.com/questions/61590462/how-to-get-equal-saturation-brightness-red-and-green-colours-in-a-web-based" />
  <row Id="28243" PostHistoryTypeId="2" PostId="9828" RevisionGUID="673411f3-0b30-4db6-b8f7-30d0f3d7f99a" CreationDate="2020-05-04T10:48:47.007" UserDisplayName="Kiki Kawai" Text="I am looking for a red and a green hue that are equally discernable against a gray background on any PC monitor, using HTML/CSS-based application. There are many possible solutions to balance these factors, but none of them work well, and I don't know how to best implement this programmatically.&#xD;&#xA;&#xD;&#xA;The gray could be a mid-gray (e.g., `#909090`). If, for example, I select a red and green similar in lightness and saturation `hsl(h*, 100%, 25.1%)`, red `RGB(128,0,0)`(`#800000`) and green `RGB(0,128,0)`(`#008000`), the result is, at least to my eyes, far from equal. Red-on-gray is definitely more discernable than green-on-gray see [image hsl red-on-gray][1] and [image hsl green-on-gray][2].&#xD;&#xA;&#xD;&#xA;If I follow the CIELCh, wherein saturation can be defined as `sat = C*/L*` ([Wilms &amp; Oberfeld, 2018][3]), a balanced pair could be this: **red** CIE-LCh°(ab) (D65/2°) = 34, 100, 57, `rgb(164, 14, 0)` (`#A40E00`, `hsl(5.1, 100%, 32.2%)`) and  **green** CIE-LCh°(ab) (D65/2°) = 34, 100, 150, `rgb(0, 103, 0)` (`#006700`, `hsl(120, 100%, 20.2%)`). Now, the lightness from the HSL model does not correspond anymore. How can I satisfy all colour models? Admittedly, or maybe I am just going crazy and see what I wanna see, the pictures with the CIELCh saturation balanced version seems a bit more balanced to me, see [image lch red-on-gray][4] and [image lch green-on-gray][5]&#xD;&#xA;&#xD;&#xA;Also, I don't know how (much) the gray factors in here in the perception of the colours, since they aren't presented against white.&#xD;&#xA;&#xD;&#xA;I have a specific aim in mind: I want to run an online study (using a JS/HTML/CSS application, hence preferably HEX colors). Of course it is not possible to achieve a perfect balance in an online study where we cannot know the properties of the monitors, but the main measure is within-subjects, hence it should not matter much if there are some differences to a certain extent. &#xD;&#xA;&#xD;&#xA;**All in all, I just want to make sure that I use the &quot;least worst&quot; solution.** &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/O9uWn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EUWEI.png&#xD;&#xA;  [3]: https://link.springer.com/article/10.1007/s00426-017-0880-8&#xD;&#xA;  [4]: https://i.stack.imgur.com/VeE0k.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/j1j8h.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28244" PostHistoryTypeId="1" PostId="9828" RevisionGUID="673411f3-0b30-4db6-b8f7-30d0f3d7f99a" CreationDate="2020-05-04T10:48:47.007" UserDisplayName="Kiki Kawai" Text="How to get &quot;Equal&quot; (saturation, brightness) Red and Green Colours in a Web-based Application?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28245" PostHistoryTypeId="3" PostId="9828" RevisionGUID="673411f3-0b30-4db6-b8f7-30d0f3d7f99a" CreationDate="2020-05-04T10:48:47.007" UserDisplayName="Kiki Kawai" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28247" PostHistoryTypeId="2" PostId="9829" RevisionGUID="dded5672-a827-4ecd-82c6-250ffa4f0079" CreationDate="2020-05-13T12:28:06.827" UserId="13362" Text="I learned in PBRT that to sample direct lighting for a surface a integrator usually calculates the sample as&#xD;&#xA;$$&#xD;&#xA;Sample = \frac{L_d(p,\omega_r) f(p,\omega_o,\omega_r)|cos\theta_i|}{p(\omega_r)}&#xD;&#xA;$$&#xD;&#xA;where BRDF $f(p,\omega_o,\omega_r)$ is the sum of brdf from all the components (for instance microfacet specular &amp; lambertian diffuse), and PDF $p(\omega_r)$ is the average of all the components. My question is why for $f$ we calculate sum while for $p$ it's average. I have the intuition that for $f$ we should also calculate average.&#xD;&#xA;In addition, why can we use the distribution of importance sampling to evaluate $p(\omega_r)$ for the given $\omega_r$?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28248" PostHistoryTypeId="1" PostId="9829" RevisionGUID="dded5672-a827-4ecd-82c6-250ffa4f0079" CreationDate="2020-05-13T12:28:06.827" UserId="13362" Text="Calculate BRDF and PDF when doing direct light sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="28249" PostHistoryTypeId="3" PostId="9829" RevisionGUID="dded5672-a827-4ecd-82c6-250ffa4f0079" CreationDate="2020-05-13T12:28:06.827" UserId="13362" Text="|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28250" PostHistoryTypeId="2" PostId="9830" RevisionGUID="925ee985-919f-4a00-980c-1b6b42148636" CreationDate="2020-05-13T14:33:37.837" UserId="5717" Text="It is likely somewhat possible, depending on how the video was encoded. The player can easily skip displaying half the frames but that won't gain us much. What needs to happen is to skip decoding some of the frames.&#xD;&#xA;&#xD;&#xA;Modern video codecs nearly all use a mix of [I, P and B frames][1]. Most are quite flexible in which frame types are used and only specify what a decoder should be able to handle, leaving the encoder free to pick the most appropriate way to encode a video.&#xD;&#xA;&#xD;&#xA;Because of this, even if we want to show only half the frames, we may still end up having to decode more than that. It is possible to build a video stream where every other frame can be skipped because it is not referenced by other frames. But I suspect that most encoders will prioritize encoding efficiency over this rigid requirement. So in practice, we will only be able to skip decoding a smaller number of frames, unless the video was specifically encoded to support this scheme.&#xD;&#xA;&#xD;&#xA;The other issue is player support. The player would need to recognize that computing power is insufficient and specifically target half the frame rate. In practice, most that I've seen will skip erratically instead. They expect the lack of computing power to be temporary as that is the most common scenario.&#xD;&#xA;&#xD;&#xA;The expected fix for a permanent lack of computing power is to use a lower quality video stream. For devices with well known computing power (eg. phones, tablets, etc), this can be handled automatically by not presenting the high quality alternative. I don't know specifically if YouTube's &quot;auto&quot; quality setting handles this the same way it handles insufficient bandwidth but it could certainly be done and would be a much better solution.&#xD;&#xA;&#xD;&#xA;TL;DR: It's possible but usually not worth doing.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Video_compression_picture_types" ContentLicense="CC BY-SA 4.0" />
  <row Id="28251" PostHistoryTypeId="2" PostId="9831" RevisionGUID="99a3b041-ff39-4f83-b278-4b05da8962bd" CreationDate="2020-05-13T15:08:25.190" UserId="13321" Text="1) When we have multiple BRDFs, adding thier components together can break energy conservation, as I think you suspect. However most renderers will handle this problem when constructing the layered BRDFs. For example you would might weight each layer or use a fresnel term to decide the weight for each layer.&#xD;&#xA;&#xD;&#xA;Here is the spec for arnolds standard shader:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7lt3o.png&#xD;&#xA;&#xD;&#xA;https://autodesk.github.io/standard-surface/&#xD;&#xA;&#xD;&#xA;Each layer is multiplied by 1 - previous layer weight, which the artist is setting. This is done inside the fr function, which means that energy conservation is solved here.&#xD;&#xA;&#xD;&#xA;2) The pdf is an average, I think, if each bxdf has an equal chance of being sampled. You therefore average the pdf even though each layer may contribute different amounts.&#xD;&#xA;&#xD;&#xA;Note: Becareful which value you use for p(wr), this will be the pdf you used to sample your direction, so either the bxdf pdf or the light pdf. (You still need to calculate both pdfs at some point for MIS though.) " ContentLicense="CC BY-SA 4.0" />
  <row Id="28252" PostHistoryTypeId="2" PostId="9832" RevisionGUID="e6305529-bda7-4be8-b923-1fde87ebe8d1" CreationDate="2020-05-13T18:45:55.873" UserId="13365" Text="I'm new to computer graphics programming so I apologize in advance if my question is stupid.&#xD;&#xA;&#xD;&#xA;I'm trying to implement a BVH for my ray tracer and I looked at some lectures explaining BVH. They all mention that a BVH takes in primitives which are then divided until they end up as nodes of the tree, but when I looked at scratch-pixel, they were talking about having the meshes as nodes. I'm a bit confused here because I'm not sure exactly which is the right way of doing it. Should the nodes contain the meshes as a whole or should I just feed the BVH construction algorithm the primitive triangles (ignoring the fact that they are a part of a mesh by just grouping them into a list/array of primitives)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28253" PostHistoryTypeId="1" PostId="9832" RevisionGUID="e6305529-bda7-4be8-b923-1fde87ebe8d1" CreationDate="2020-05-13T18:45:55.873" UserId="13365" Text="Ray Tracing Bounding Volume Hierarchies nodes" ContentLicense="CC BY-SA 4.0" />
  <row Id="28254" PostHistoryTypeId="3" PostId="9832" RevisionGUID="e6305529-bda7-4be8-b923-1fde87ebe8d1" CreationDate="2020-05-13T18:45:55.873" UserId="13365" Text="|raytracing|rendering|optimisation|bounding-volume-hierarchy|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28255" PostHistoryTypeId="2" PostId="9833" RevisionGUID="e5e7235e-adae-4c25-82ee-9468b2ddfc3e" CreationDate="2020-05-13T19:08:28.540" UserId="13192" Text="I understand that in OpenGL early depth test can be performed in the rasterizer (before running the fragment shader), but is it the same case for WebGL? If so, how is early depth test enabled in WebGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28256" PostHistoryTypeId="1" PostId="9833" RevisionGUID="e5e7235e-adae-4c25-82ee-9468b2ddfc3e" CreationDate="2020-05-13T19:08:28.540" UserId="13192" Text="Early depth test in WebGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="28257" PostHistoryTypeId="3" PostId="9833" RevisionGUID="e5e7235e-adae-4c25-82ee-9468b2ddfc3e" CreationDate="2020-05-13T19:08:28.540" UserId="13192" Text="|webgl|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28258" PostHistoryTypeId="2" PostId="9834" RevisionGUID="bbeb15ae-ba2d-40b2-82bf-efcc964eb612" CreationDate="2020-05-13T21:14:21.873" UserId="13367" Text="I'm confused about how to properly convert from sRGB or XYZ color space to ACEScg. Specifically whether I have to account for differences in white point explicitly.&#xD;&#xA;&#xD;&#xA;The [aces github page](https://github.com/ampas/aces-dev/blob/master/transforms/ctl/README-MATRIX.md) gives the following matrix to convert from XYZ to AP1:&#xD;&#xA;         &#xD;&#xA;     1.6410233797, -0.3248032942, -0.2364246952,&#xD;&#xA;    -0.6636628587,  1.6153315917,  0.0167563477,&#xD;&#xA;     0.0117218943, -0.0082844420,  0.9883948585&#xD;&#xA;&#xD;&#xA;[FGED2](http://terathon.com/blog/rgb-xyz-conversion-matrix-accuracy/) gives the following matrix to convert from XYZ to sRGB with white point D65:&#xD;&#xA;&#xD;&#xA;     3.240970, -1.537383, -0.498611,&#xD;&#xA;    -0.969244,  1.875968,  0.041555,&#xD;&#xA;     0.055630, -0.203977,  1.056972 &#xD;&#xA;&#xD;&#xA;And [this shadertoy](https://www.shadertoy.com/view/WltSRB) gives the following matrix to convert from sRGB to AP1:&#xD;&#xA;&#xD;&#xA;	0.613097, 0.339523, 0.047379,&#xD;&#xA;	0.070194, 0.916354, 0.013452,&#xD;&#xA;	0.020616, 0.109570, 0.869815&#xD;&#xA;&#xD;&#xA;So I figured if I combine the XYZ-&gt;sRGB and sRGB-&gt;AP1 matrices it should be the same result as XYZ0-&gt;AP1. However there is a small, but noticeable difference:&#xD;&#xA;&#xD;&#xA;     1.66058,    -0.315295,  -0.24151,&#xD;&#xA;    -0.659926,    1.60839,    0.017298,&#xD;&#xA;     0.00900358, -0.00356713, 0.913644&#xD;&#xA;&#xD;&#xA;I assume the difference comes from the way the white point is handled? My question is, which is &quot;correct&quot;. I have use cases for both XYZ-&gt;AP1 and sRGB-&gt;AP1, but now I'm irritated that my matrices don't allow me to round-trip.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28259" PostHistoryTypeId="1" PostId="9834" RevisionGUID="bbeb15ae-ba2d-40b2-82bf-efcc964eb612" CreationDate="2020-05-13T21:14:21.873" UserId="13367" Text="How to convert from XYZ or sRGB to ACEScg/AP1" ContentLicense="CC BY-SA 4.0" />
  <row Id="28260" PostHistoryTypeId="3" PostId="9834" RevisionGUID="bbeb15ae-ba2d-40b2-82bf-efcc964eb612" CreationDate="2020-05-13T21:14:21.873" UserId="13367" Text="|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28261" PostHistoryTypeId="2" PostId="9835" RevisionGUID="d26a8160-24ed-42ea-822b-6e90035b0be0" CreationDate="2020-05-13T23:51:57.830" UserId="13370" Text="#Bounding Volumes&#xD;&#xA;A bounding volume is for example an Axis-Aligned Bounding-Box (AABB), a generaal Bounding-Box not aligned with the major axes or a Bounding-Sphere. They differ in &#xD;&#xA;&#xD;&#xA;* how much memory they take (e.g. a sphere takes only 4 floats, a box takes 6 floats)&#xD;&#xA;* how good they enclose the object's geometry&#xD;&#xA;* how fast are the related computations (mainly intersection tests).&#xD;&#xA;&#xD;&#xA;You will find an extensive overview at [Wikipedia](https://en.wikipedia.org/wiki/Bounding_volume).&#xD;&#xA;&#xD;&#xA;#Hierarchy of volumes&#xD;&#xA;So in the hierarchy of bounding volumes, instead of whole meshes you will store only their bounding volumes. You choose a single type, e.g. a bounding sphere, and will use it to build the whole BVH. At the bottom level each bounding volume will probably enclose only a single object. You will build the hierarchy up by enclosing pairs or smaller groups of volumes in a larger volume. So using spheres you would always create a new sphere enclosing a smaller few spheres close to each other. You proceed until a single root volume encloses all 3D objects in your scene.&#xD;&#xA;&#xD;&#xA;There are different [strategies to create BVH](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy). But all have in common that complex structures like triangle meshes are hierarchically clustered using very simple entities." ContentLicense="CC BY-SA 4.0" />
  <row Id="28276" PostHistoryTypeId="2" PostId="9840" RevisionGUID="7f66473d-af89-4b78-bc15-119f173af3ed" CreationDate="2020-05-14T13:25:04.277" UserId="13376" Text="Couldn't find any resources on this, so I'll ask here.&#xA;&#xA;For example, I want to create a game model of a mountain peak.&#xA;&#xA;I took lots and lots of drone footage, almost from every side, photography footage, just lots of it. (Realistically viable amounts of footage)&#xA;&#xA;Could I somehow, import, or make a 3D model out of these footages so I could import it into the game.&#xA;&#xA;It should be a 3D model. Thank you." ContentLicense="CC BY-SA 4.0" />
  <row Id="28277" PostHistoryTypeId="1" PostId="9840" RevisionGUID="7f66473d-af89-4b78-bc15-119f173af3ed" CreationDate="2020-05-14T13:25:04.277" UserId="13376" Text="Is it viable to create computer graphics via terrain scanning?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28278" PostHistoryTypeId="3" PostId="9840" RevisionGUID="7f66473d-af89-4b78-bc15-119f173af3ed" CreationDate="2020-05-14T13:25:04.277" UserId="13376" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28279" PostHistoryTypeId="2" PostId="9841" RevisionGUID="6434efe6-8cdc-46c4-bbd7-9cda6ca5a60a" CreationDate="2020-05-14T13:26:07.230" UserId="13377" Text="I would like to construct a projection matrix for reverse perspective.&#xD;&#xA;I'm using OpenGL and tried to modify concepts from [this excelent tutorial](http://www.songho.ca/opengl/gl_projectionmatrix.html).&#xD;&#xA;&#xD;&#xA;I came up with:&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;2\frac{(near-M)}{right-left} &amp;  0  &amp; \frac{right + left}{right-left} &amp; M\frac{right + left}{right-left}\\&#xD;&#xA;0  &amp;  2\frac{(near-M)}{top-bottom} &amp; \frac{top + bottom}{top-bottom} &amp; M\frac{top + bottom}{top-bottom}\\&#xD;&#xA;0 &amp; 0 &amp; \frac{2M-near-far}{far-near} &amp; \frac{2(M-far)*near}{far-near} + M\\&#xD;&#xA;0 &amp; 0 &amp; -1 &amp; -M&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;$$ \text{Variables define viewing frustum. }M \text{ is the tip; point } (0,0,-M) \text{ in eye space.}$$&#xD;&#xA;&#xD;&#xA;To avoid ambiguity near point **M** I put far plane closer to the camera. To debug this, I inverted points from NDC [-1,1] cube and they seem to fit the desired frustum. Sadly my models don't render correctly when using this matrix. They don't show up when they clearly are in the viewing frustum. I verify this by rendering the scene from other cameras using regular perspective or orthographic projection.&#xD;&#xA;&#xD;&#xA;To clarify, what kind of perspective I'm talking about, here are links:&#xD;&#xA;&#xD;&#xA; - &lt;https://en.wikipedia.org/wiki/Reverse_perspective&gt;&#xD;&#xA; - [True Reverse Perspective](https://vimeo.com/12518619)&#xD;&#xA;&#xD;&#xA;Code in c++ using glm:&#xD;&#xA;```&#xD;&#xA;template &lt;typename T&gt;&#xD;&#xA;auto frustum(T left, T right, T bottom, T top, T near, T M, T far) {&#xD;&#xA;	glm::tmat4x4&lt;T, glm::defaultp&gt; result(0);&#xD;&#xA;	result[0][0] = (static_cast&lt;T&gt;(2) * (near - M)) / (right - left);&#xD;&#xA;	result[2][0] = (right + left) / (right - left);&#xD;&#xA;	result[3][0] = (right + left) / (right - left) * M;&#xD;&#xA;&#xD;&#xA;	result[1][1] = (static_cast&lt;T&gt;(2) * (near - M)) / (top - bottom);&#xD;&#xA;	result[2][1] = (top + bottom) / (top - bottom);&#xD;&#xA;	result[3][1] = (top + bottom) / (top - bottom) * M;&#xD;&#xA;&#xD;&#xA;	result[2][2] = ((static_cast&lt;T&gt;(2) * M) - near - far) / (far - near);&#xD;&#xA;	result[3][2] = static_cast&lt;T&gt;(2) * (M - far) * near / (far - near) + M;&#xD;&#xA;&#xD;&#xA;	result[2][3] = static_cast&lt;T&gt;(-1);&#xD;&#xA;	result[3][3] = static_cast&lt;T&gt;(-M);&#xD;&#xA;	return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28280" PostHistoryTypeId="1" PostId="9841" RevisionGUID="6434efe6-8cdc-46c4-bbd7-9cda6ca5a60a" CreationDate="2020-05-14T13:26:07.230" UserId="13377" Text="What is the projection matrix of reverse (Byzantine) perspective?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28281" PostHistoryTypeId="3" PostId="9841" RevisionGUID="6434efe6-8cdc-46c4-bbd7-9cda6ca5a60a" CreationDate="2020-05-14T13:26:07.230" UserId="13377" Text="|opengl|c++|mathematics|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28282" PostHistoryTypeId="2" PostId="9842" RevisionGUID="79d4de67-cd7f-4690-ba5e-0d4ed25375b5" CreationDate="2020-05-14T16:04:25.060" UserId="5664" Text="I have just learned about the vector triple product (Lagrange formula) from a math for computer graphics textbook, however the book does not mention any use cases for it beyond the fact that it's a simpler way to say: &#xD;&#xA;&#xD;&#xA;       cross(a,cross(b,c) == b*(dot(a,c))-c*(dot(a,b)&#xD;&#xA;&#xD;&#xA;Why is this emphasized? Is it because it's simpler to read?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28283" PostHistoryTypeId="1" PostId="9842" RevisionGUID="79d4de67-cd7f-4690-ba5e-0d4ed25375b5" CreationDate="2020-05-14T16:04:25.060" UserId="5664" Text="What are some uses for the vector triple product in computer graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28284" PostHistoryTypeId="3" PostId="9842" RevisionGUID="79d4de67-cd7f-4690-ba5e-0d4ed25375b5" CreationDate="2020-05-14T16:04:25.060" UserId="5664" Text="|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28285" PostHistoryTypeId="5" PostId="9835" RevisionGUID="0cee06a7-4196-40d4-b531-500883b2ead6" CreationDate="2020-05-14T17:06:13.387" UserId="13370" Comment="Imrpoved the answer a bit." Text="#Bounding Volumes&#xD;&#xA;A bounding volume is for example an Axis-Aligned Bounding-Box (AABB), a generaal Bounding-Box not aligned with the major axes or a Bounding-Sphere. They differ in &#xD;&#xA;&#xD;&#xA;* how much memory they take (e.g. a sphere takes only 4 floats, AABB 6 floats)&#xD;&#xA;* how good they enclose the object's geometry &#xD;&#xA;* how fast are the related computations (mainly intersection tests).&#xD;&#xA;&#xD;&#xA;You will find an extensive overview at [Wikipedia](https://en.wikipedia.org/wiki/Bounding_volume).&#xD;&#xA;&#xD;&#xA;#Hierarchy of volumes&#xD;&#xA;So in the hierarchy of bounding volumes, instead of whole meshes you will store only their bounding volumes. You choose a single type, e.g. a bounding sphere, and will use it to build the whole BVH. At the bottom level each bounding volume will probably enclose only a single object. You will build the hierarchy up by enclosing pairs or smaller groups of volumes in a larger volume.&#xD;&#xA;&#xD;&#xA;So using spheres you would enclose each object into a bounding sphere at first. Then at the higher levels of the hierarchy, you would always create a new sphere enclosing a few spheres from the previous level which are close to each other. You proceed until a single root sphere encloses all 3D objects in your scene.&#xD;&#xA;&#xD;&#xA;There are different [strategies to create BVH](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy). But all have in common that complex structures like triangle meshes are hierarchically clustered using very simple entities." ContentLicense="CC BY-SA 4.0" />
  <row Id="28286" PostHistoryTypeId="2" PostId="9843" RevisionGUID="1885ed8d-4cff-458f-9b5e-0d539b1d1a17" CreationDate="2020-05-14T19:34:32.680" UserId="10450" Text="It looks like the light and colour calculation for the sphere reflection is peaking and may need to be clipped to the range 0-255. [This][1] video around 1:21:45 mark shows an example of this.&#xA;&#xA;&#xA;  [1]: https://m.youtube.com/watch?v=vE5c2hTRLZM&amp;list=PLHm_I0tE5kKPPWXkTTtOn8fkcwEGZNETh&amp;index=7 &quot;Raytracer from scratch in C++&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28287" PostHistoryTypeId="2" PostId="9844" RevisionGUID="4f9625a5-2c3f-4879-9535-31c6488fd633" CreationDate="2020-05-14T22:38:11.737" UserId="13370" Text="I have to disagree with @jack11111, this is definitely not a clipping issue. I have two possible explanations which you can easily test and verify.&#xD;&#xA;&#xD;&#xA;###Clipping theory&#xD;&#xA;* The patch looks pretty constant in color, clipping would be sort of a gradient (modulo 255) of full intensity in at least one channel (R/G/B).&#xD;&#xA;* There is no direct light source to cause a strong specular highlight. According to the ground shading and the Lambert-shaded green balls a point light source is placed above, little bit in front of the camera. It seems to have normal intensity that should not cause any trouble. In fact I see in your code that you apply only basic Lambert `n . l` shading, so no specular highlights possible.&#xD;&#xA;* There is no indirect source to cause such a peak. The rays reflect to towards ground that is rather dark. The bright spot on the ground is located else where. That is well visible on the red sphere where the error occurs closer than the next green sphere, but the highlight on the ground is even further away.&#xD;&#xA;* It is a strange coincidence that the secondary color of the patch is exactly the same for both spheres.&#xD;&#xA;&#xD;&#xA;### Normals theory&#xD;&#xA;* Normals seem to be computed correctly elsewhere, all your shading is consistent with nice gradients.&#xD;&#xA;* You reflections are also correct elsewhere, that will be on problem.&#xD;&#xA;&#xD;&#xA;# It's a trap! (almost)&#xD;&#xA;Looking closely at your image I believe I can explain what is happening there. The rays hitting the suspicious regions at the sphere will reflect towards ground in a direction very similar to the ground normal.&#xD;&#xA;&#xD;&#xA;You ground does not seem to be reflective, but if it were: The rays would reflect back in almost the exact opposite direction hitting back the ball and then heading towards the camera. So they would hit the ball twice which could cause its color to gain dominance. You can test this theory by comparing the rendering results with `maxDepth = 1`. If the discontinuity disappears then that is the problem.&#xD;&#xA;&#xD;&#xA;# Upside down&#xD;&#xA;My second explanation is much more likely to be the case. It is also based on the observation that the rays reflected from the suspicious patches hit the ground in a direction pointing almost exactly down. I noticed a bit strange setup of your plane in your code. It has its normal pointing down!?&#xD;&#xA;```lang-py&#xD;&#xA;self.normal = Vec3(0,-1,0)&#xD;&#xA;```&#xD;&#xA;I am not sure how the Lambert shading of the ground works then (should be then all just ambient in fact), but assuming `Vec(0,1,0)` is your up then the intersection will in fact yield `None`&#xD;&#xA;```lang-py&#xD;&#xA;denom = ray.dot(self.normal) #something like 1e-6 in the suspicious area&#xD;&#xA;if abs(denom) &gt; 0.0001: #evaluates to false&#xD;&#xA;    #... true branch ignored&#xD;&#xA;return None #false branch activated, returns no intersection&#xD;&#xA;```&#xD;&#xA;Having no intersection means that the hit point is shaded only with a constant color&#xD;&#xA;&gt; ```lang-py&#xD;&#xA;&gt; if closest_object == None:&#xD;&#xA;&gt;    return Vec3(173/255, 216/255, 230/255)&#xD;&#xA;&gt; ```&#xD;&#xA;&#xD;&#xA;So to test this explanation, just change the returned color for this case to black and see if the patch darkens.&#xD;&#xA;```lang-py&#xD;&#xA;if closest_object == None:&#xD;&#xA;    return Vec3(0, 0, 0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Another option to test this explanation is to invert the plane normal:&#xD;&#xA;```lang-py&#xD;&#xA;self.normal = Vec3(0,1,0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I hope that helps. Please let me know the results." ContentLicense="CC BY-SA 4.0" />
  <row Id="28288" PostHistoryTypeId="5" PostId="9824" RevisionGUID="31e2f719-52bd-4f5c-bfff-e4870c1912c2" CreationDate="2020-05-14T22:56:49.530" UserId="13370" Comment="Improved code formatting and activated syntax highlighting" Text="I am writing a small raytracer in python , everything was working fine but when i implemented plane geometry then the reflective spheres are getting weird patches on lower bottom. image below:&#xD;&#xA;&#xD;&#xA;*I guess this is happening because of some error in calculating lighting with wrong normals? but i am unable to figure out exactly what.*&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fHB56.png&#xD;&#xA;&#xD;&#xA;code to find palne-ray intersection:&#xD;&#xA;```lang-py&#xD;&#xA;class Plane(Shape):&#xD;&#xA;    def __init__(self, color, y=0, specular=-1, reflective=0):&#xD;&#xA;        self.specular = specular&#xD;&#xA;        self.reflective = reflective&#xD;&#xA;        self.center = Vec3(0,y,0)&#xD;&#xA;        self.normal = Vec3(0,-1,0)&#xD;&#xA;        self.color = color&#xD;&#xA;&#xD;&#xA;    def intersect_at_point(self, origin, ray):&#xD;&#xA;        denom = ray.dot(self.normal)&#xD;&#xA;    &#xD;&#xA;        if abs(denom) &gt; 0.0001:&#xD;&#xA;            diff  = self.center - ray&#xD;&#xA;            t = diff.dot(self.normal) / denom&#xD;&#xA;&#xD;&#xA;            if t &gt; 0.0001:&#xD;&#xA;                return t&#xD;&#xA;        return None&#xD;&#xA;```&#xD;&#xA;trace ray function.&#xD;&#xA;```lang-py&#xD;&#xA;def trace_ray(self, origin, direction, t_min, t_max, depth):&#xD;&#xA;    closest_object, closest_t = self.closest_intersection(origin, direction, t_min, t_max)&#xD;&#xA;&#xD;&#xA;    if closest_object == None:&#xD;&#xA;        return Vec3(173/255, 216/255, 230/255)&#xD;&#xA;    &#xD;&#xA;    # Compute local color&#xD;&#xA;    P = origin + closest_t * direction  # Compute intersection&#xD;&#xA;    N = P - closest_object.center  # Compute  normal at intersection&#xD;&#xA;    N = N / N.mag()&#xD;&#xA;    local_color = closest_object.color * self.compute_light(P, N)&#xD;&#xA;    &#xD;&#xA;    # If we hit the recursion limit or the object is not reflective, we're done&#xD;&#xA;    r = closest_object.reflective&#xD;&#xA;    if depth &lt;= 0 or r &lt;= 0:&#xD;&#xA;        return local_color&#xD;&#xA;    &#xD;&#xA;    # Compute the reflected color&#xD;&#xA;    R = self.reflect_ray(-1*direction, N)&#xD;&#xA;    reflected_color = self.trace_ray(P, R, 0.001, math.inf, depth - 1)&#xD;&#xA;&#xD;&#xA;    return local_color * (1 - r) + reflected_color * r&#xD;&#xA;```&#xD;&#xA;closest intersection method.&#xD;&#xA;```lang-py &#xD;&#xA;def closest_intersection(self, O, D, t_min, t_max):&#xD;&#xA;    closest_t = math.inf&#xD;&#xA;    closest_object = None&#xD;&#xA;    &#xD;&#xA;    for object in self.world.objects:&#xD;&#xA;        t1, t2 = object.intersect_at_point(O, D)&#xD;&#xA;    &#xD;&#xA;        if (t_min &lt; t1 &lt; t_max) and t1 &lt; closest_t:&#xD;&#xA;            closest_t = t1&#xD;&#xA;            closest_object = object&#xD;&#xA;    &#xD;&#xA;        if (t_min &lt; t2 &lt; t_max) and t2 &lt; closest_t:&#xD;&#xA;            closest_t = t2&#xD;&#xA;            closest_object = object&#xD;&#xA;    &#xD;&#xA;    for plane in self.world.planes:&#xD;&#xA;        t = plane.intersect_at_point(O,D)&#xD;&#xA;    &#xD;&#xA;        if t and (t_min &lt; t &lt; t_max) and t &lt; closest_t:&#xD;&#xA;            closest_t = t&#xD;&#xA;            closest_object = plane&#xD;&#xA;    &#xD;&#xA;    return closest_object, closest_t&#xD;&#xA;```&#xD;&#xA;Calculate light method.&#xD;&#xA;&#xD;&#xA;```lang-py&#xD;&#xA;def compute_light(self, Point, Normal):&#xD;&#xA;    i = 0.0&#xD;&#xA;    P = Point&#xD;&#xA;    N = Normal&#xD;&#xA;&#xD;&#xA;    for light in self.world.lights:&#xD;&#xA;        if light.type == 'ambient':&#xD;&#xA;            i += light.intensity&#xD;&#xA;        else:&#xD;&#xA;            if light.type == 'point':&#xD;&#xA;                L = light.position - P&#xD;&#xA;                t_max = 1&#xD;&#xA;&#xD;&#xA;            if light.type == 'directional':&#xD;&#xA;                L = light.direction&#xD;&#xA;                t_max = math.inf&#xD;&#xA;&#xD;&#xA;            # Shadow check&#xD;&#xA;            shadow_sphere, shadow_t = self.closest_intersection(P, L, 0.001, t_max)&#xD;&#xA;            if shadow_sphere != None:&#xD;&#xA;                continue&#xD;&#xA;&#xD;&#xA;            n_dot_l = N.dot(L)&#xD;&#xA;&#xD;&#xA;            if n_dot_l &gt; 0:&#xD;&#xA;                # print(f'light intensity {light.intensity}')&#xD;&#xA;                i+= light.intensity * n_dot_l / (N.mag() * L.mag())&#xD;&#xA;&#xD;&#xA;    return i" ContentLicense="CC BY-SA 4.0" />
  <row Id="28289" PostHistoryTypeId="24" PostId="9824" RevisionGUID="31e2f719-52bd-4f5c-bfff-e4870c1912c2" CreationDate="2020-05-14T22:56:49.530" Comment="Proposed by 13370 approved by 13309 edit id of 523" ContentLicense="CC BY-SA 4.0" />
  <row Id="28290" PostHistoryTypeId="2" PostId="9845" RevisionGUID="158aaf6f-f81b-4da3-be83-a7e816499c04" CreationDate="2020-05-14T23:00:58.247" UserId="6562" Text="I am using Simplex Noise to generate a 3D field. The specific implementation is [FastNoise-SIMD][1].&#xD;&#xA;&#xD;&#xA;Assume I want to have a gradient (or derivative) for a sample at Sx, Sy, Sz in that field.&#xD;&#xA;&#xD;&#xA;Do I actually need to sample the value of the field at all neighbours of sample S?&#xD;&#xA;&#xD;&#xA;If so, that makes it a quite expensive operation, as the 4-octave Simplex Noise function I use is already quite expensive, evaluating them for all neighbours would make it too slow for my purposes.&#xD;&#xA;&#xD;&#xA;Is there a way to directly compute the derivative of SimplexNoise that is cheaper than getting the deltas from the neighbours?&#xD;&#xA;&#xD;&#xA;Some Perlin noise implementations [have an analytical derivative][2]. But none of the Simplex Noise implementations that I have found support sampling the gradient along with the field value.&#xD;&#xA;&#xD;&#xA;Have analytical derivatives been done on Simplex Noise, or is it maybe not possible for Simplex Noise? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/jackmott/FastNoise-SIMD&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/perlin-noise-part-2/perlin-noise-computing-derivatives" ContentLicense="CC BY-SA 4.0" />
  <row Id="28291" PostHistoryTypeId="1" PostId="9845" RevisionGUID="158aaf6f-f81b-4da3-be83-a7e816499c04" CreationDate="2020-05-14T23:00:58.247" UserId="6562" Text="Analytical derivative of a 3D Simplex Noise field" ContentLicense="CC BY-SA 4.0" />
  <row Id="28292" PostHistoryTypeId="3" PostId="9845" RevisionGUID="158aaf6f-f81b-4da3-be83-a7e816499c04" CreationDate="2020-05-14T23:00:58.247" UserId="6562" Text="|sampling|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28293" PostHistoryTypeId="5" PostId="9844" RevisionGUID="1cc48273-a0f6-43c8-823c-1e495feb4550" CreationDate="2020-05-14T23:27:49.660" UserId="13370" Comment="Removed the previous sugesstion for testing to flip the normal as it is not the problem source." Text="I have to disagree with @jack11111, this is definitely not a clipping issue. I have two possible explanations which you can easily test and verify.&#xD;&#xA;&#xD;&#xA;###Clipping theory&#xD;&#xA;* The patch looks pretty constant in color, clipping would be sort of a gradient (modulo 255) of full intensity in at least one channel (R/G/B).&#xD;&#xA;* There is no direct light source to cause a strong specular highlight. According to the ground shading and the Lambert-shaded green balls a point light source is placed above, little bit in front of the camera. It seems to have normal intensity that should not cause any trouble. In fact I see in your code that you apply only basic Lambert `n . l` shading, so no specular highlights possible.&#xD;&#xA;* There is no indirect source to cause such a peak. The rays reflect to towards ground that is rather dark. The bright spot on the ground is located else where. That is well visible on the red sphere where the error occurs closer than the next green sphere, but the highlight on the ground is even further away.&#xD;&#xA;* It is a strange coincidence that the secondary color of the patch is exactly the same for both spheres.&#xD;&#xA;&#xD;&#xA;### Normals theory&#xD;&#xA;* Normals seem to be computed correctly elsewhere, all your shading is consistent with nice gradients.&#xD;&#xA;* You reflections are also correct elsewhere, that will be on problem.&#xD;&#xA;&#xD;&#xA;# It's a trap! (almost)&#xD;&#xA;Looking closely at your image I believe I can explain what is happening there. The rays hitting the suspicious regions at the sphere will reflect towards ground in a direction very similar to the ground normal.&#xD;&#xA;&#xD;&#xA;You ground does not seem to be reflective, but if it were: The rays would reflect back in almost the exact opposite direction hitting back the ball and then heading towards the camera. So they would hit the ball twice which could cause its color to gain dominance. You can test this theory by comparing the rendering results with `maxDepth = 1`. If the discontinuity disappears then that is the problem.&#xD;&#xA;&#xD;&#xA;# Upside down&#xD;&#xA;My second explanation is much more likely to be the case. It is also based on the observation that the rays reflected from the suspicious patches hit the ground in a direction pointing almost exactly down. I noticed a bit strange setup of your plane in your code. It has its normal pointing down!?&#xD;&#xA;```lang-py&#xD;&#xA;self.normal = Vec3(0,-1,0)&#xD;&#xA;```&#xD;&#xA;I am not sure how the Lambert shading of the ground works then (should be then all just ambient in fact), but assuming `Vec(0,1,0)` is your up then the intersection will in fact yield `None`&#xD;&#xA;```lang-py&#xD;&#xA;denom = ray.dot(self.normal) #something like 1e-6 in the suspicious area&#xD;&#xA;if abs(denom) &gt; 0.0001: #evaluates to false&#xD;&#xA;    #... true branch ignored&#xD;&#xA;return None #false branch activated, returns no intersection&#xD;&#xA;```&#xD;&#xA;Having no intersection means that the hit point is shaded only with a constant color&#xD;&#xA;&gt; ```lang-py&#xD;&#xA;&gt; if closest_object == None:&#xD;&#xA;&gt;    return Vec3(173/255, 216/255, 230/255)&#xD;&#xA;&gt; ```&#xD;&#xA;&#xD;&#xA;So to test this explanation, just change the returned color for this case to black and see if the patch darkens.&#xD;&#xA;```lang-py&#xD;&#xA;if closest_object == None:&#xD;&#xA;    return Vec3(0, 0, 0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I hope that helps. Please let me know the results.&#xD;&#xA;&#xD;&#xA;# Update&#xD;&#xA;After the author confirmed my second explanation I found the reason in the code. The source of the problem is in the ray-plane intersection method. &#xD;&#xA;&#xD;&#xA;**Most important of all the epsilon in the comparison should be omitted, since that is causing the patch to be discontinuous.** As mentioned earlier, the incoming ray direction is almost `Vec3(0,-1,0)`. You have set your plane normal to exactly `Vec3(0,-1,0)` so the dot product yields something very close to `0`.&#xD;&#xA;&#xD;&#xA;So the quick fix would be:&#xD;&#xA;```lang-py&#xD;&#xA;denom = ray.dot(self.normal)&#xD;&#xA;if abs(denom) &gt;= 0: #omit the epsilon&#xD;&#xA;    #...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Your plane normal is inconsistent with how a normal is usually defined. I believe your plane is not supposed to face down. It would be much better and correct to have the plane normal pointing **up** and then testing for a **negative** dot product.&#xD;&#xA;&#xD;&#xA;A front-face hit occurs when the face normal and the ray are pointing in opposite directions, i.e. their angle `θ` is smaller than `-π/2` or larger than `π/2`, so `cos(θ) &lt; 0`. Note that `denom` is in fact `cos(θ)`. If `|θ| &lt; π/2`, i.e. `cos(θ) &gt; 0`, then it is a back-face hit. You ignore such hits for now but once you add transparency to your raycaster you will need them as well.&#xD;&#xA;&#xD;&#xA;The correct way would be:&#xD;&#xA;```lang-py&#xD;&#xA;def __init__(self, color, y=0, specular=-1, reflective=0):&#xD;&#xA;    # ...&#xD;&#xA;    self.normal = Vec3(0,1,0) #pointing UP&#xD;&#xA;&#xD;&#xA;    def intersect_at_point(self, origin, ray):&#xD;&#xA;        denom = ray.dot(self.normal) # denom == cos(θ)&#xD;&#xA;&#xD;&#xA;        if abs(denom) &lt;= 0: #is negative &lt;=&gt; |θ| &gt; π/2; omit the epsilon&#xD;&#xA;            diff  = self.center - ray&#xD;&#xA;            t = diff.dot(self.normal) / denom&#xD;&#xA;&#xD;&#xA;            if t &gt; 0: #I suggest to omit the epsilon here as well&#xD;&#xA;                return t&#xD;&#xA;        return None" ContentLicense="CC BY-SA 4.0" />
  <row Id="28294" PostHistoryTypeId="2" PostId="9846" RevisionGUID="be7250fc-4f90-4c38-86d6-d7ee8ed46176" CreationDate="2020-05-15T00:34:29.843" UserId="13370" Text="Yes that is possible using **photogrammetry** like @SimonF mentioned in his comment. There is plenty of commercial and free software. Peter Falkingham has a great [blog with many reviews](https://peterfalkingham.com/blog/) mainly for the free tools.&#xD;&#xA;&#xD;&#xA;Here is a [video of scanning a mountain](https://www.youtube.com/watch?v=b84MwuupHKg) using my favourite open-source solution. Specialists do much more [extreme scanning](https://www.youtube.com/watch?v=NuZUSe87miY) using their tools, the resulting Matterhorn point-cloud dataset is used by some of my research colleagues as well.&#xD;&#xA;&#xD;&#xA;# Requirements&#xD;&#xA;To cover a mountain, you will need a lot of photos. Depending on the peak size and required precision you may end up with thousands to hundreds of thousands of photos. To process all of them, it needs a lot of RAM and powerful GPU(s). I did a reconstruction for 10k photos on a _Ryzen 2700X_ with _64 GB Ram_ and a _1080 Ti_ inside... it took 10 days to complete.&#xD;&#xA;&#xD;&#xA;There are two critical phases: &#xD;&#xA;&#xD;&#xA;1. Alignment to create the sparse point cloud is partly CPU-based and requires a lot of RAM. Once the system starts to swap to the HDD, you've lost.&#xD;&#xA;&#xD;&#xA;2. Patch-match for the dense point cloud heavily uses the GPU and takes most of the reconstruction time.&#xD;&#xA;&#xD;&#xA;# Scanning procedure&#xD;&#xA;In ideal case all photos would be taken in exact the same moment. When you fly around it takes time and the sun moves. Shadows change. That is often a problem at reconstruction so cloudy days are generally better. Try to get all footage on one day and as fast as possible. The atmospheric conditions may change the next day(s). I hope there is no snow and no water, those are the most difficult to reconstruct due to reflections :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28295" PostHistoryTypeId="5" PostId="9834" RevisionGUID="89df9cba-61d3-4edf-92e7-35e519b276ef" CreationDate="2020-05-15T08:11:02.640" UserId="13367" Comment="deleted 1 character in body" Text="I'm confused about how to properly convert from sRGB or XYZ color space to ACEScg. Specifically whether I have to account for differences in white point explicitly.&#xD;&#xA;&#xD;&#xA;The [aces github page](https://github.com/ampas/aces-dev/blob/master/transforms/ctl/README-MATRIX.md) gives the following matrix to convert from XYZ to AP1:&#xD;&#xA;         &#xD;&#xA;     1.6410233797, -0.3248032942, -0.2364246952,&#xD;&#xA;    -0.6636628587,  1.6153315917,  0.0167563477,&#xD;&#xA;     0.0117218943, -0.0082844420,  0.9883948585&#xD;&#xA;&#xD;&#xA;[FGED2](http://terathon.com/blog/rgb-xyz-conversion-matrix-accuracy/) gives the following matrix to convert from XYZ to sRGB with white point D65:&#xD;&#xA;&#xD;&#xA;     3.240970, -1.537383, -0.498611,&#xD;&#xA;    -0.969244,  1.875968,  0.041555,&#xD;&#xA;     0.055630, -0.203977,  1.056972 &#xD;&#xA;&#xD;&#xA;And [this shadertoy](https://www.shadertoy.com/view/WltSRB) gives the following matrix to convert from sRGB to AP1:&#xD;&#xA;&#xD;&#xA;	0.613097, 0.339523, 0.047379,&#xD;&#xA;	0.070194, 0.916354, 0.013452,&#xD;&#xA;	0.020616, 0.109570, 0.869815&#xD;&#xA;&#xD;&#xA;So I figured if I combine the XYZ-&gt;sRGB and sRGB-&gt;AP1 matrices it should be the same result as XYZ-&gt;AP1. However there is a small, but noticeable difference:&#xD;&#xA;&#xD;&#xA;     1.66058,    -0.315295,  -0.24151,&#xD;&#xA;    -0.659926,    1.60839,    0.017298,&#xD;&#xA;     0.00900358, -0.00356713, 0.913644&#xD;&#xA;&#xD;&#xA;I assume the difference comes from the way the white point is handled? My question is, which is &quot;correct&quot;. I have use cases for both XYZ-&gt;AP1 and sRGB-&gt;AP1, but now I'm irritated that my matrices don't allow me to round-trip.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28296" PostHistoryTypeId="2" PostId="9847" RevisionGUID="7c6408a4-e164-45c9-8756-1460dd549b37" CreationDate="2020-05-15T08:31:06.117" UserId="13367" Text="The discrepancy comes from chromatic adaptation, which is included in the matrix from shadertoy. If you combine XYZ-&gt;AP1 with D65-&gt;D60 from the aces page you end up with the same matrix that I got by chaining XYZ-&gt;sRGB and sRGB-&gt;AP1 (with chromatic adaptation) together." ContentLicense="CC BY-SA 4.0" />
  <row Id="28297" PostHistoryTypeId="2" PostId="9848" RevisionGUID="bb65bc49-3a33-4869-b6fb-97e5af8f203c" CreationDate="2020-05-15T14:21:53.853" UserId="13387" Text="Even film/animation speeds are something that 3D content creation teams and studios try to increase.  Of course they don't mind adding minutes per frame if the output is much nicer, whereas games can add so much to graphics processing before FPS rates drop below an acceptable level, which I think coinsides with the point you are making.&#xD;&#xA;&#xD;&#xA;This difference isn't the reason that film/animation works in quads though.  Quads are easier to work with when creating rounded and organic shapes. In the end though, it is in fact triangulated, at rendertime.  The renderer just creates a new line, per quad, from opposite corners to cut the quad into 2 triangles. This doesn't happen to your model, but do the data streamed to the renderer.  The reason is that if your quad's  4 points are not coplanar, and on a larger percentage of your quads in many models, they won't be, you will have nonmanifold geometry.  The calculation of the area is basically undefined.  If you slice the quad into two tris, that solves the issue as any 3 points are always coplanar." ContentLicense="CC BY-SA 4.0" />
  <row Id="28301" PostHistoryTypeId="2" PostId="9850" RevisionGUID="99dce191-f5d9-4979-acf8-068ff1ac9fb5" CreationDate="2020-05-15T20:46:28.547" UserId="13370" Text="In my answer I relate to WebGL 2 / Opengl ES 3.0. &#xD;&#xA;&#xD;&#xA;As far as I know there is now `ARB_shader_image_load_store` is not supported. But there is `discard` available for fragment shaders in WebGL 2! So what you can do is to&#xD;&#xA;&#xD;&#xA;1. make a depth pass with a straight-forward fragment shader and &#xD;&#xA;2. then in a second pass test `gl_FragCoord.z` against the value of the depth texture, if it's worth the additional texture lookup." ContentLicense="CC BY-SA 4.0" />
  <row Id="28306" PostHistoryTypeId="50" PostId="9426" RevisionGUID="8f1f9068-4ce7-41b2-958e-c9df5b197efd" CreationDate="2020-05-16T10:08:05.893" UserId="-1" />
  <row Id="28307" PostHistoryTypeId="2" PostId="9852" RevisionGUID="db0162bc-7fe0-402d-bf7f-4303530557f3" CreationDate="2020-05-16T10:50:27.350" UserId="13273" Text="I have different functions for example normalmapping which I like always use...&#xD;&#xA;Now I thought about making a small glsl library.&#xD;&#xA;&#xD;&#xA;My problem:&#xD;&#xA;I don't want to have all functions within the same &quot;namespace&quot;.&#xD;&#xA;&#xD;&#xA;I would like to have it like:&#xD;&#xA;&#xD;&#xA;vec4 lighting::Phong(vec3 normal, vec3 color, vec3 lightPositionRelative)&#xD;&#xA;&#xD;&#xA;The thing is, that I have tons of functions and sometimes multiple functions are related to the same thing, for example: A HashTable, AddKey, GetKey, HasKey...&#xD;&#xA;&#xD;&#xA;So some kind of namespace or even better a class like structure.&#xD;&#xA;What are the options I have?&#xD;&#xA;How are you guys handle this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28308" PostHistoryTypeId="1" PostId="9852" RevisionGUID="db0162bc-7fe0-402d-bf7f-4303530557f3" CreationDate="2020-05-16T10:50:27.350" UserId="13273" Text="Creating glsl library" ContentLicense="CC BY-SA 4.0" />
  <row Id="28309" PostHistoryTypeId="3" PostId="9852" RevisionGUID="db0162bc-7fe0-402d-bf7f-4303530557f3" CreationDate="2020-05-16T10:50:27.350" UserId="13273" Text="|glsl|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28310" PostHistoryTypeId="5" PostId="9852" RevisionGUID="14e4add6-bbb8-43ca-9f10-a8fecc07bf7d" CreationDate="2020-05-16T13:30:27.890" UserId="13273" Comment="added 5 characters in body" Text="I have different functions for example normalmapping which I use all the time...&#xD;&#xA;Now I thought about making a small glsl library.&#xD;&#xA;&#xD;&#xA;My problem:&#xD;&#xA;I don't want to have all functions within the same &quot;namespace&quot;.&#xD;&#xA;&#xD;&#xA;I would like to have it like:&#xD;&#xA;&#xD;&#xA;    vec4 lighting::Phong(vec3 normal, vec3 color, vec3 lightPositionRelative)&#xD;&#xA;&#xD;&#xA;The thing is, that I have tons of functions and sometimes multiple functions are related to the same thing, for example: A HashTable, AddKey, GetKey, HasKey...&#xD;&#xA;&#xD;&#xA;So some kind of namespace or even better a class like structure.&#xD;&#xA;What are the options I have?&#xD;&#xA;How are you guys handle this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28311" PostHistoryTypeId="2" PostId="9853" RevisionGUID="c00926eb-4b6f-4f59-8c91-183e585b89da" CreationDate="2020-05-16T15:10:20.930" UserId="11521" Text="Looking around here on various sources (including related questions on this site), if my understanding is correct, when implementing a path tracer with a material which has both a diffuse term and a specular term, we can randomly choose whether to evaluate the diffuse or the specular ray then divide the result by the probability of choosing diffuse or specular.&#xD;&#xA;&#xD;&#xA;For example if we have a material 50% specular, we would have:&#xD;&#xA;&#xD;&#xA;If diffuse ray was chosen:&#xD;&#xA;&#xD;&#xA;$\frac{DiffuseBRDF*incomingLight}{0.5}$&#xD;&#xA;&#xD;&#xA;If specular ray was chosen:&#xD;&#xA;&#xD;&#xA;$\frac{SpecularBRDF*incomingLight}{0.5}$&#xD;&#xA;&#xD;&#xA;Once diffuse/specular is chosen, we have to find which ray exactly we want to use for $incomingLight$. In my case I have a rough dieletric surface (not a perfect mirror) and I would like to use importance sampling and use for example a cosine weighted pdf for diffuse and a NDF weighted pdf for the specular term. I couldn't find a source for this particular case, but If my understanding is correct, I would end up with either:&#xD;&#xA;&#xD;&#xA;$\frac{DiffuseBRDF*incomingLight}{0.5*DiffusePdf}$&#xD;&#xA;&#xD;&#xA;if diffuse was chosen, or:&#xD;&#xA;&#xD;&#xA;$\frac{SpecularBRDF*incomingLight}{0.5*SpecularPdf}$&#xD;&#xA;&#xD;&#xA;if specular was chosen. Is this result correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28312" PostHistoryTypeId="1" PostId="9853" RevisionGUID="c00926eb-4b6f-4f59-8c91-183e585b89da" CreationDate="2020-05-16T15:10:20.930" UserId="11521" Text="How to properly combine diffuse and rough specular BRDFs in a path tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="28313" PostHistoryTypeId="3" PostId="9853" RevisionGUID="c00926eb-4b6f-4f59-8c91-183e585b89da" CreationDate="2020-05-16T15:10:20.930" UserId="11521" Text="|pathtracing|brdf|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28314" PostHistoryTypeId="2" PostId="9854" RevisionGUID="3b330b88-bcf7-4507-9435-0a52595bfec1" CreationDate="2020-05-16T16:05:06.210" UserId="13393" Text="I am trying to create some procedurally created terrains for which i need to create noise maps. How do I create a texture of noise map in OpenGL and then pass that in my vertex shader as a heightMap? &#xD;&#xA;I know the algorithms to create noises, like Perlin or Simplex, but no idea how to put this data into a texture." ContentLicense="CC BY-SA 4.0" />
  <row Id="28315" PostHistoryTypeId="1" PostId="9854" RevisionGUID="3b330b88-bcf7-4507-9435-0a52595bfec1" CreationDate="2020-05-16T16:05:06.210" UserId="13393" Text="Custom Create Maps in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="28316" PostHistoryTypeId="3" PostId="9854" RevisionGUID="3b330b88-bcf7-4507-9435-0a52595bfec1" CreationDate="2020-05-16T16:05:06.210" UserId="13393" Text="|opengl|texture|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28317" PostHistoryTypeId="5" PostId="9850" RevisionGUID="359d65f4-b231-4c51-9b3c-fc4d104524f9" CreationDate="2020-05-16T20:09:02.207" UserId="13370" Comment="Improved ending." Text="In my answer I relate to WebGL 2 / Opengl ES 3.0. &#xD;&#xA;&#xD;&#xA;As far as I know `ARB_shader_image_load_store` is not supported. But there is `discard` available for fragment shaders in WebGL 2! So what you can do is to&#xD;&#xA;&#xD;&#xA;1. make a depth pass with a straight-forward fragment shader and &#xD;&#xA;2. then in a second pass test `gl_FragCoord.z` against the value of the depth texture.&#xD;&#xA;&#xD;&#xA;It's up to you, if it's worth the additional texture lookup and rendering the scene twice." ContentLicense="CC BY-SA 4.0" />
  <row Id="28318" PostHistoryTypeId="2" PostId="9855" RevisionGUID="72684302-a476-428a-8a44-dd9271d651f0" CreationDate="2020-05-16T20:58:18.597" UserId="13394" Text="GLSL does not support C++ style namespaces. You might want to do some regex magic before parsing the shader, replacing '::' with '_' or something. You might want to have a preprocessor of sorts - or just forget about it entirely. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28322" PostHistoryTypeId="5" PostId="9828" RevisionGUID="728d5cf7-8deb-406f-9fc7-bda8027e91ce" CreationDate="2020-05-17T09:02:14.040" UserId="13390" Comment="added tags plus small correction" Text="I am looking for a red and a green hue that are equally discernable against a gray background on any PC monitor, using HTML/CSS-based application. There are many possible solutions to balance these factors, but none of them work well, and I don't know how to best implement it.&#xD;&#xA;&#xD;&#xA;The gray could be a mid-gray (e.g., `#909090`). If, for example, I select a red and green similar in lightness and saturation `hsl(h*, 100%, 25.1%)`, red `RGB(128,0,0)`(`#800000`) and green `RGB(0,128,0)`(`#008000`), the result is, at least to my eyes, far from equal. Red-on-gray is definitely more discernable than green-on-gray see [image hsl red-on-gray][1] and [image hsl green-on-gray][2].&#xD;&#xA;&#xD;&#xA;If I follow the CIELCh, wherein saturation can be defined as `sat = C*/L*` ([Wilms &amp; Oberfeld, 2018][3]), a balanced pair could be this: **red** CIE-LCh°(ab) (D65/2°) = 34, 100, 57, `rgb(164, 14, 0)` (`#A40E00`, `hsl(5.1, 100%, 32.2%)`) and  **green** CIE-LCh°(ab) (D65/2°) = 34, 100, 150, `rgb(0, 103, 0)` (`#006700`, `hsl(120, 100%, 20.2%)`). Now, the lightness from the HSL model does not correspond anymore. How can I satisfy all colour models? Admittedly, or maybe I am just going crazy and see what I wanna see, the pictures with the CIELCh saturation balanced version seems a bit more balanced to me, see [image lch red-on-gray][4] and [image lch green-on-gray][5]&#xD;&#xA;&#xD;&#xA;Also, I don't know how (much) the gray factors in here in the perception of the colours, since they aren't presented against white.&#xD;&#xA;&#xD;&#xA;I have a specific aim in mind: I want to run an online study (using a JS/HTML/CSS application, hence preferably HEX colors). Of course it is not possible to achieve a perfect balance in an online study where we cannot know the properties of the monitors, but the main measure is within-subjects, hence it should not matter much if there are some differences to a certain extent. &#xD;&#xA;&#xD;&#xA;**All in all, I just want to make sure that I use the &quot;least worst&quot; solution.** &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/O9uWn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EUWEI.png&#xD;&#xA;  [3]: https://link.springer.com/article/10.1007/s00426-017-0880-8&#xD;&#xA;  [4]: https://i.stack.imgur.com/VeE0k.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/j1j8h.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28323" PostHistoryTypeId="6" PostId="9828" RevisionGUID="728d5cf7-8deb-406f-9fc7-bda8027e91ce" CreationDate="2020-05-17T09:02:14.040" UserId="13390" Comment="added tags plus small correction" Text="|color|perspective|color-science|human-vision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28324" PostHistoryTypeId="24" PostId="9828" RevisionGUID="728d5cf7-8deb-406f-9fc7-bda8027e91ce" CreationDate="2020-05-17T09:02:14.040" Comment="Proposed by 13390 approved by 13385 edit id of 524" ContentLicense="CC BY-SA 4.0" />
  <row Id="28325" PostHistoryTypeId="2" PostId="9858" RevisionGUID="09af59db-c713-4d32-9c2b-0cdb559140a8" CreationDate="2020-05-17T12:02:01.253" UserId="13396" Text="I am trying to understand the voronoi shader implemented in the Book of Shaders in the Tiling and iteration section: https://thebookofshaders.com/12/&#xD;&#xA;&#xD;&#xA;Specifically how do these lines calculate the distance from a point to its neighboring tile's point:&#xD;&#xA;&#xD;&#xA;    // Random position from current + neighbor place in the grid&#xD;&#xA;    vec2 point = random2(i_st + neighbor);&#xD;&#xA;    vec2 diff = neighbor + point - f_st;&#xD;&#xA;&#xD;&#xA;    // Distance to the point&#xD;&#xA;    float dist = length(diff);&#xD;&#xA;&#xD;&#xA;    // Keep the closer distance&#xD;&#xA;    m_dist = min(m_dist, dist);&#xD;&#xA;&#xD;&#xA;Specifically how is the `diff` calculation working? I would have expected `i_st` to reappear there." ContentLicense="CC BY-SA 4.0" />
  <row Id="28326" PostHistoryTypeId="1" PostId="9858" RevisionGUID="09af59db-c713-4d32-9c2b-0cdb559140a8" CreationDate="2020-05-17T12:02:01.253" UserId="13396" Text="Help me understand the voronoi shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="28327" PostHistoryTypeId="3" PostId="9858" RevisionGUID="09af59db-c713-4d32-9c2b-0cdb559140a8" CreationDate="2020-05-17T12:02:01.253" UserId="13396" Text="|shader|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28331" PostHistoryTypeId="2" PostId="9860" RevisionGUID="1d932bc5-7edf-4c2f-b02a-9c1016b34098" CreationDate="2020-05-17T23:03:45.310" UserId="13370" Text="**1)** Scale the texture coordinates from [0,1]x[0,1] -&gt; [0,3]x[0,3]. It works with higher integer scales as well. This creates an imaginary 3x3 tiles grid.&#xD;&#xA;```lang-glsl&#xD;&#xA;st *= 3.;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**2)** Split the upscaled texture coordinates into the integer part and its float reminder.&#xD;&#xA;```lang-glsl&#xD;&#xA;vec2 i_st = floor(st); //the tile coords of the fragment - an integer pair {0,1,2}x{0,1,2}&#xD;&#xA;vec2 f_st = fract(st); //fragment coords within the tile - a float vec2 [0,1]x[0,1]&#xD;&#xA;&#xD;&#xA;//e.g. let's take&#xD;&#xA;//  st == vec2(1.1,1.7)&#xD;&#xA;//  i_st == vec2(1.,1.)&#xD;&#xA;//  f_st == vec2(.1,.7)&#xD;&#xA;```&#xD;&#xA;Now `st == i_st + f_st` holds.&#xD;&#xA;&#xD;&#xA;**3)** In order to avoid terms confusion I will call the points that build the Voronoi cells _Voronoi points_. Each of the 9 tiles has one _Voronoi point_ inside to produce a Voronoi cell. So there will be 9 Voronoi cells visible in the resulting texture.&#xD;&#xA;&#xD;&#xA;The main hack here is to have this regular 3x3 tiles grid with the same amount of _Voronoi points_ and randomize their positions only within the respective tile. So the distribution will be pseudo-even. You give up irregular distributions by this assumption, e.g. all points grouped in the upper-left corner, but such arrangements are highly unlikely to result from biologic processes that the cellular noise tries to mimic.&#xD;&#xA;&#xD;&#xA;Since `random2` is deterministic, it will return the same `vec2` each time you enter the same `i_st`, so for a fixed `i_st` it will stay constant across all fragments.&#xD;&#xA;```lang-glsl&#xD;&#xA;vec2 point = random2(i_st); //pick the Voronoi point, e.g. vec2(.6,.4)&#xD;&#xA;```&#xD;&#xA;The global position of the picked _Voronoi point_ is in fact `i_st + point`.&#xD;&#xA;&#xD;&#xA;**4)** Take the distance to the _Voronoi point_ inside of the current tile as the initial minimum distance.&#xD;&#xA;```lang-glsl&#xD;&#xA;vec2 diff = point - f_st //e.g. vec2(.6,.4) - vec2(.1,.7) == vec2(.5,-.3)&#xD;&#xA;float dist = length(diff); //e.g.0.583 &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**5)** So you know that there is exactly one _Voronoi point_ in each cell, thus by simple geometric means you can prove that you need to check only the direct neighbors. You need to test if any of the neighboring tiles has a _Voronoi point_ closer to the current fragment than the _Voronoi point_ from _4)_. Two loops iterate over all 3x3 neighborhood of the current tile. It is much easier to do that relatively `{-1, 0, 1}x{-1, 0, 1}` instead of using absolute numbers {`i_st.x`-1, `i_st.x`, `i_st.x`+1}x{`i_st.y`-1, `i_st.y`, `i_st.y`+1}. Moreover, we know that each tile is 1x1 in size.&#xD;&#xA;```lang-glsl&#xD;&#xA;for (int y= -1; y &lt;= 1; y++) {&#xD;&#xA;    for (int x= -1; x &lt;= 1; x++) {&#xD;&#xA;        // relative neighbor coordinates will be sufficient&#xD;&#xA;        // this is the integer part indicating the neighboring tile coordinates&#xD;&#xA;        vec2 neighbor = vec2(float(x),float(y)); //e.g. vec2(-1., 1)&#xD;&#xA;&#xD;&#xA;        //to be continued&#xD;&#xA;```&#xD;&#xA;**6)** Now you will need to compute the absolute coordinates of neighboring tile to obtain its _Voronoi point_ consistently across all fragments.&#xD;&#xA;```lang-glsl&#xD;&#xA;        //the global neighbor tile coordinates are neighbor + i_st &#xD;&#xA;        vec2 point = random2(i_st + neighbor); //note that this is a local scope variable&#xD;&#xA;&#xD;&#xA;        //to be continued&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**7)** And now the most interesting step for you, computing the distance to the neighboring _Voronoi point_&#xD;&#xA;```lang-glsl&#xD;&#xA;        //neighbor: relative tile coords, e.g. vec2(-1., 1.)&#xD;&#xA;        //point:    Voronoi point inside of the neighboring tile e.g. vec2(0.9, 0.2)&#xD;&#xA;        //f_st:     current fragment position within its home tile,&#xD;&#xA;        //          e.g. when st == vec2(1.1, 1.7) then f_st == vec2(.1,.7)&#xD;&#xA;&#xD;&#xA;        vec2 diff = neighbor + point - f_st;&#xD;&#xA;&#xD;&#xA;        //to be continued&#xD;&#xA;```&#xD;&#xA;The example values yield:&#xD;&#xA;&#xD;&#xA;`neighbor + point`: `vec2(-1.,1.) + vec2(0.9, 0.2) == vec2(-0.1, 1.2)`&#xD;&#xA;&#xD;&#xA;That is the relative position of the neighboring tile Voronoi point. **Relative means **with respect to the lower-left corner of the current fragment's tile**.&#xD;&#xA;The same _relative_ coordinates apply to `f_st` and also to `point` from 3).&#xD;&#xA;&#xD;&#xA;`(neighbor + point) - f_st`: `vec2(-0.1, 1.2) - vec2(.1,.7) == vec2(-.2,.5)`&#xD;&#xA;&#xD;&#xA;This is shorter distance (`0.538` vs. previous `0.583`) so for the example positions the _Voronoi point_ from the upper left cell is closer.&#xD;&#xA;&#xD;&#xA;**8)** The rest is pretty straight forward. Compute the magnitude of the `diff` vector and keep the minimum.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```lang-glsl&#xD;&#xA;        float dist = length(diff); //distance to the neighboring Voronoi point&#xD;&#xA;&#xD;&#xA;        m_dist = min(m_dist, dist); //remember the minimum of distances&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I hope this will help you to understand that. The main simplification is the switch to _relative_ coordinates as described in 7). &#xD;&#xA;&#xD;&#xA;* Looking at the code I see that the middle tile (current fragment tile) will be evaluated twice. This can be reduced by omiting step 4) initializing `dist` to `2*sqrt(2)` which is very roughly `3`. That is the length of the diagonal of two cells - the farthest distance the current fragment st could be from one of the neighboring _Voronoi points_.&#xD;&#xA;&#xD;&#xA;* Border tiles are handled in an elegant implicit way. `random2` generates a _Voronoi point_ for them as well and involves it in the minimal distance computation. So You will see 9 complete and possibly up to 16 more incomplete Voronoi cells.&#xD;&#xA;&#xD;&#xA;Hope that helps, feel free to ask any further details." ContentLicense="CC BY-SA 4.0" />
  <row Id="28335" PostHistoryTypeId="2" PostId="9862" RevisionGUID="c7c13064-c49e-4f62-a284-85aa4bf33ff3" CreationDate="2020-05-18T06:42:31.997" UserId="13398" Text="I am new in the OpenGL - GLSL and trying to make a shader that taking a [mercator projection][1] texture as a source and converting it to an [equirectangular projection][2] texture.&#xD;&#xA;&#xD;&#xA;**Sample input: (512x512)**&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Desired output (512x~256)**&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I found [this question][5], that have a similar problem in unity3d. But i stuck to understand it.&#xD;&#xA;&#xD;&#xA;I have a C# code that do this task, using `WindowsForms`, but it's not efficient.&#xD;&#xA;&#xD;&#xA;    static class Program&#xD;&#xA;    {&#xD;&#xA;        const double TWO_PI = Math.PI * 2;&#xD;&#xA;        const double PI180 = Math.PI / 180;&#xD;&#xA;&#xD;&#xA;        private static double Clip(double value, double min, double max)&#xD;&#xA;        {&#xD;&#xA;             return Math.Min(Math.Max(value, min), max);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        public static PointF PixelXYToLatLong(int X, int Y, int mapSize)&#xD;&#xA;        {&#xD;&#xA;             PointF coordinate = new PointF();&#xD;&#xA;             double x = (Clip(X, 0, mapSize - 1) / mapSize) - 0.5;&#xD;&#xA;             double y = 0.5 - (Clip(Y, 0, mapSize - 1) / mapSize);&#xD;&#xA;             coordinate.X = (float)(360 * x);&#xD;&#xA;             coordinate.Y = (float)(90 - 360 * Math.Atan(Math.Exp(0 - y * 2 * Math.PI)) / Math.PI);&#xD;&#xA;             return coordinate;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        static void Main()&#xD;&#xA;        {&#xD;&#xA;            Bitmap source = new Bitmap(&quot;INPUT_PATH&quot;);&#xD;&#xA;            int w = source.Width;&#xD;&#xA;            int h = source.Height;&#xD;&#xA;            int dh = h &gt;&gt; 1;&#xD;&#xA;            Bitmap des = new Bitmap(w, dh);&#xD;&#xA;            dh = dh &gt;&gt; 1;&#xD;&#xA;            int dw = w &gt;&gt; 1;&#xD;&#xA;            double r = w / TWO_PI;&#xD;&#xA;            for (int i = 0; i &lt; w; i++)&#xD;&#xA;            {&#xD;&#xA;                for (int j = 0; j &lt; h; j++)&#xD;&#xA;                {&#xD;&#xA;                    Color color = source.GetPixel(i, j);&#xD;&#xA;                    PointF point = PixelXYToLatLong(i, j, w);&#xD;&#xA;                    double x = point.X * PI180;&#xD;&#xA;                    double y = point.Y * PI180;&#xD;&#xA;                    x = r * x;&#xD;&#xA;                    y = r * y;&#xD;&#xA;                    x = Math.Round(dw + x);&#xD;&#xA;                    y = Math.Round(dh - y);&#xD;&#xA;                    des.SetPixel((int)x, (int)y, color);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            des.Save(&quot;OUTPUT_PATH&quot;);&#xD;&#xA;            source.Dispose();&#xD;&#xA;            des.Dispose();&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So i try to implement it in c++ and OpenGL. &#xD;&#xA;&#xD;&#xA;**My vertex and fragment shaders**&#xD;&#xA;&#xD;&#xA;    const GLchar* vertexSource = R&quot;glsl(&#xD;&#xA;        #version 330 core&#xD;&#xA;    &#xD;&#xA;        layout (location = 0) in vec3 texPos;&#xD;&#xA;        layout (location = 1) in vec2 texCoord;&#xD;&#xA;&#xD;&#xA;        out vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;    		gl_Position.xyz = texPos.xyz;&#xD;&#xA;            gl_Position.w = 1.0;&#xD;&#xA;&#xD;&#xA;            TexCoord = texCoord;&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 330 core&#xD;&#xA;    &#xD;&#xA;        in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;        uniform sampler2D ourTexture;&#xD;&#xA;    &#xD;&#xA;        void main(){&#xD;&#xA;    		float pi180 = 3.14159265 / 180;&#xD;&#xA;    		float r = 1 / (2 * 3.14159265);&#xD;&#xA;    		float x = min(max(TexCoord.x, 0), 1) - 0.5;&#xD;&#xA;    		float y = 0.5 - min(max(TexCoord.y, 0), 1);&#xD;&#xA;    		x = 360 * x;&#xD;&#xA;    		y = 90 - (360 * atan(exp(0 - y * 2 * 3.14159265)) / 3.14159265);&#xD;&#xA;    		x = x * pi180;&#xD;&#xA;    		y = y * pi180;&#xD;&#xA;    		x = 0.5 + (r * x);&#xD;&#xA;    		y = 0.5 - (r * y);&#xD;&#xA;            &#xD;&#xA;            gl_FragColor = texture(ourTexture, vec2(x,y));&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;And my vertex buffer:&#xD;&#xA;&#xD;&#xA;    static const GLfloat g_vertex_buffer_data[] = {&#xD;&#xA;       1.0f,  1.0f, 0.0f, 1.0f, 0.0f,&#xD;&#xA;       1.0f, -1.0f, 0.0f, 1.0f, 1.0f,&#xD;&#xA;      -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,&#xD;&#xA;       1.0f,  1.0f, 0.0f, 1.0f, 0.0f,&#xD;&#xA;      -1.0f,  1.0f, 0.0f, 0.0f, 0.0f,&#xD;&#xA;      -1.0f, -1.0f, 0.0f, 0.0f, 1.0f&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Output:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;As you can see there are a lot of problems (*Except to the image itself*).&#xD;&#xA;&#xD;&#xA;Also i try to change texture wrapping to `GL_REPEAT`, `GL_MIRRORED_REPEAT`, `GL_CLAMP_TO_EDGE` and `GL_CLAMP_TO_BORDER`, as below:&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And `glViewport(0, 0, 512, 256)` but without any success.&#xD;&#xA;&#xD;&#xA;So where I'm wrong?&#xD;&#xA;&#xD;&#xA;Sorry for the long question, Thanks in advance.&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Mercator_projection&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Equirectangular_projection&#xD;&#xA;  [3]: https://i.stack.imgur.com/vsCRz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/qYxQF.jpg&#xD;&#xA;  [5]: https://stackoverflow.com/questions/59907996/shader-that-transforms-a-mercator-projection-to-equirectangular&#xD;&#xA;  [6]: https://i.stack.imgur.com/JjzrH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28336" PostHistoryTypeId="1" PostId="9862" RevisionGUID="c7c13064-c49e-4f62-a284-85aa4bf33ff3" CreationDate="2020-05-18T06:42:31.997" UserId="13398" Text="Shader that transforms a mercator projection to equirectangular?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28337" PostHistoryTypeId="3" PostId="9862" RevisionGUID="c7c13064-c49e-4f62-a284-85aa4bf33ff3" CreationDate="2020-05-18T06:42:31.997" UserId="13398" Text="|opengl|glsl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28338" PostHistoryTypeId="50" PostId="9071" RevisionGUID="778de28a-f1bf-4696-a931-5a3e883eaa5d" CreationDate="2020-05-18T07:02:40.247" UserId="-1" />
  <row Id="28339" PostHistoryTypeId="2" PostId="9863" RevisionGUID="d9d5a3c0-08c3-48a8-83a0-d53b9732dc81" CreationDate="2020-05-18T20:34:45.340" UserId="13404" Text="I'm going through and optimizing some of my glsl code for a project, and have come across a scenario several times that I am not sure how best to optimize.&#xD;&#xA;&#xD;&#xA;In summary - Is it faster to sample a texture once with `.rgba` vs 4 times with simply `.r` at the end?&#xD;&#xA;&#xD;&#xA;Here's what I have now:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    mat4 getLightProjectionMatrix(int lightIndex){&#xD;&#xA;    	mat4 m;&#xD;&#xA;    	&#xD;&#xA;    	m[0][0] = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[0][1] = texelFetch( projMatricies , ivec2( 1 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[0][2] = texelFetch( projMatricies , ivec2( 2 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[0][3] = texelFetch( projMatricies , ivec2( 3 , lightIndex ) , 0 ).r;&#xD;&#xA;    	&#xD;&#xA;    	m[1][0] = texelFetch( projMatricies , ivec2( 4 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[1][1] = texelFetch( projMatricies , ivec2( 5 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[1][2] = texelFetch( projMatricies , ivec2( 6 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[1][3] = texelFetch( projMatricies , ivec2( 7 , lightIndex ) , 0 ).r;&#xD;&#xA;    	&#xD;&#xA;    	m[2][0] = texelFetch( projMatricies , ivec2( 8 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[2][1] = texelFetch( projMatricies , ivec2( 9 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[2][2] = texelFetch( projMatricies , ivec2( 10 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[2][3] = texelFetch( projMatricies , ivec2( 11 , lightIndex ) , 0 ).r;&#xD;&#xA;    	&#xD;&#xA;    	m[3][0] = texelFetch( projMatricies , ivec2( 12 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[3][1] = texelFetch( projMatricies , ivec2( 13 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[3][2] = texelFetch( projMatricies , ivec2( 14 , lightIndex ) , 0 ).r;&#xD;&#xA;    	m[3][3] = texelFetch( projMatricies , ivec2( 15 , lightIndex ) , 0 ).r;&#xD;&#xA;    	&#xD;&#xA;    	return m;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's what I'm considering doing:&#xD;&#xA;&#xD;&#xA;    mat4 getLightProjectionMatrix(int lightIndex){&#xD;&#xA;    	mat4 m;&#xD;&#xA;    	&#xD;&#xA;    	vec4 A = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;&#xD;&#xA;    	m[0][0] = A[0];&#xD;&#xA;    	m[0][1] = A[1];&#xD;&#xA;    	m[0][2] = A[2];&#xD;&#xA;    	m[0][3] = A[3];&#xD;&#xA;    	&#xD;&#xA;    	vec4 B = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;&#xD;&#xA;    	m[1][0] = B[0];&#xD;&#xA;    	m[1][1] = B[1];&#xD;&#xA;    	m[1][2] = B[2];&#xD;&#xA;    	m[1][3] = B[3];&#xD;&#xA;    	&#xD;&#xA;    	vec4 C = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;&#xD;&#xA;    	m[2][0] = C[0];&#xD;&#xA;    	m[2][1] = C[1];&#xD;&#xA;    	m[2][2] = C[2];&#xD;&#xA;    	m[2][3] = C[3];&#xD;&#xA;    	&#xD;&#xA;    	vec4 D = texelFetch( projMatricies , ivec2( 0 , lightIndex ) , 0 ).rgba;&#xD;&#xA;    	m[3][0] = D[0];&#xD;&#xA;    	m[3][1] = D[1];&#xD;&#xA;    	m[3][2] = D[2];&#xD;&#xA;    	m[3][3] = D[3];&#xD;&#xA;    	&#xD;&#xA;    	return m;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Does the compiler know how to optimize both of these into the same thing in the end? or would it be more efficient to pack more data into a texture fetch no matter what?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28340" PostHistoryTypeId="1" PostId="9863" RevisionGUID="d9d5a3c0-08c3-48a8-83a0-d53b9732dc81" CreationDate="2020-05-18T20:34:45.340" UserId="13404" Text="What's more optimal - sampling one channel at a time or all channels at once?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28341" PostHistoryTypeId="3" PostId="9863" RevisionGUID="d9d5a3c0-08c3-48a8-83a0-d53b9732dc81" CreationDate="2020-05-18T20:34:45.340" UserId="13404" Text="|shader|texture|glsl|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28342" PostHistoryTypeId="2" PostId="9864" RevisionGUID="e24f3425-9144-4d2e-be30-08bcc7449cc1" CreationDate="2020-05-18T20:59:05.390" UserId="506" Text="It should be significantly faster to sample one RGBA value from one location in a texture than four R values from different locations in the texture." ContentLicense="CC BY-SA 4.0" />
  <row Id="28343" PostHistoryTypeId="2" PostId="9865" RevisionGUID="9f38a18e-96de-4156-9169-7c4b26604347" CreationDate="2020-05-18T22:12:54.257" UserId="13370" Text="I fully agree with all other replies and comments that `rgba` is definitely faster as it reduces the number of fetches from 16 to 4. You can even omit the per-element assignment:&#xD;&#xA;&#xD;&#xA;```lang-glsl&#xD;&#xA;//I also fixed the typo in Matric[i]es&#xD;&#xA;m[0] = texelFetch( projMatrices , ivec2( 0 , lightIndex ) , 0 );&#xD;&#xA;m[1] = texelFetch( projMatrices , ivec2( 1 , lightIndex ) , 0 );&#xD;&#xA;m[2] = texelFetch( projMatrices , ivec2( 2 , lightIndex ) , 0 );&#xD;&#xA;m[3] = texelFetch( projMatrices , ivec2( 3 , lightIndex ) , 0 );&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="28344" PostHistoryTypeId="5" PostId="9862" RevisionGUID="42794b80-3373-4c7c-bb7b-2ba0b3dddc98" CreationDate="2020-05-19T00:45:56.043" UserId="13398" Comment="deleted 25 characters in body" Text="I am new in the OpenGL - GLSL and trying to make a shader that taking a [mercator projection][1] texture as a source and converting it to an [equirectangular projection][2] texture.&#xD;&#xA;&#xD;&#xA;**Sample input: (1024x1024)**&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Desired output (1024x512)**&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I found [this question][5], that have a similar problem in unity3d. But i stuck to understand it.&#xD;&#xA;&#xD;&#xA;I have a C# code that do this task, using `WindowsForms`, but it's not efficient.&#xD;&#xA;&#xD;&#xA;    static class Program&#xD;&#xA;    {&#xD;&#xA;        const double TWO_PI = Math.PI * 2;&#xD;&#xA;        const double PI180 = Math.PI / 180;&#xD;&#xA;&#xD;&#xA;        private static double Clip(double value, double min, double max)&#xD;&#xA;        {&#xD;&#xA;             return Math.Min(Math.Max(value, min), max);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        public static PointF PixelXYToLatLong(int X, int Y, int mapSize)&#xD;&#xA;        {&#xD;&#xA;             PointF coordinate = new PointF();&#xD;&#xA;             double x = (Clip(X, 0, mapSize - 1) / mapSize) - 0.5;&#xD;&#xA;             double y = 0.5 - (Clip(Y, 0, mapSize - 1) / mapSize);&#xD;&#xA;             coordinate.X = (float)(360 * x);&#xD;&#xA;             coordinate.Y = (float)(90 - 360 * Math.Atan(Math.Exp(0 - y * 2 * Math.PI)) / Math.PI);&#xD;&#xA;             return coordinate;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        static void Main()&#xD;&#xA;        {&#xD;&#xA;            Bitmap source = new Bitmap(&quot;INPUT_PATH&quot;);&#xD;&#xA;            int w = source.Width;&#xD;&#xA;            int h = source.Height;&#xD;&#xA;            int dh = h &gt;&gt; 1;&#xD;&#xA;            Bitmap des = new Bitmap(w, dh);&#xD;&#xA;            dh = dh &gt;&gt; 1;&#xD;&#xA;            int dw = w &gt;&gt; 1;&#xD;&#xA;            double r = w / TWO_PI;&#xD;&#xA;            for (int i = 0; i &lt; w; i++)&#xD;&#xA;            {&#xD;&#xA;                for (int j = 0; j &lt; h; j++)&#xD;&#xA;                {&#xD;&#xA;                    Color color = source.GetPixel(i, j);&#xD;&#xA;                    PointF point = PixelXYToLatLong(i, j, w);&#xD;&#xA;                    double x = point.X * PI180;&#xD;&#xA;                    double y = point.Y * PI180;&#xD;&#xA;                    x = r * x;&#xD;&#xA;                    y = r * y;&#xD;&#xA;                    x = Math.Round(dw + x);&#xD;&#xA;                    y = Math.Round(dh - y);&#xD;&#xA;                    des.SetPixel((int)x, (int)y, color);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            des.Save(&quot;OUTPUT_PATH&quot;);&#xD;&#xA;            source.Dispose();&#xD;&#xA;            des.Dispose();&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So i try to implement it in c++ and OpenGL. &#xD;&#xA;&#xD;&#xA;**My vertex and fragment shaders**&#xD;&#xA;&#xD;&#xA;    const GLchar* vertexSource = R&quot;glsl(&#xD;&#xA;        #version 330 core&#xD;&#xA;    &#xD;&#xA;        layout (location = 0) in vec3 texPos;&#xD;&#xA;        layout (location = 1) in vec2 texCoord;&#xD;&#xA;&#xD;&#xA;        out vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;        void main()&#xD;&#xA;        {&#xD;&#xA;    		gl_Position.xyz = texPos.xyz;&#xD;&#xA;            gl_Position.w = 1.0;&#xD;&#xA;&#xD;&#xA;            TexCoord = texCoord;&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 330 core&#xD;&#xA;    &#xD;&#xA;        in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;        uniform sampler2D ourTexture;&#xD;&#xA;    &#xD;&#xA;        void main(){&#xD;&#xA;    		float pi180 = 3.14159265 / 180;&#xD;&#xA;    		float r = 1 / (2 * 3.14159265);&#xD;&#xA;    		float x = min(max(TexCoord.x, 0), 1) - 0.5;&#xD;&#xA;    		float y = 0.5 - min(max(TexCoord.y, 0), 1);&#xD;&#xA;    		x = 360 * x;&#xD;&#xA;    		y = 90 - (360 * atan(exp(0 - y * 2 * 3.14159265)) / 3.14159265);&#xD;&#xA;    		x = x * pi180;&#xD;&#xA;    		y = y * pi180;&#xD;&#xA;    		x = 0.5 + (r * x);&#xD;&#xA;    		y = 0.5 - (r * y);&#xD;&#xA;            &#xD;&#xA;            gl_FragColor = texture(ourTexture, vec2(x,y));&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;And my vertex buffer:&#xD;&#xA;&#xD;&#xA;    static const GLfloat g_vertex_buffer_data[] = {&#xD;&#xA;       1.0f,  1.0f, 0.0f, 1.0f, 0.0f,&#xD;&#xA;       1.0f, -1.0f, 0.0f, 1.0f, 1.0f,&#xD;&#xA;      -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,&#xD;&#xA;       1.0f,  1.0f, 0.0f, 1.0f, 0.0f,&#xD;&#xA;      -1.0f,  1.0f, 0.0f, 0.0f, 0.0f,&#xD;&#xA;      -1.0f, -1.0f, 0.0f, 0.0f, 1.0f&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Output:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;As you can see there are a lot of problems.&#xD;&#xA;&#xD;&#xA;Also i try to change texture wrapping to `GL_REPEAT`, `GL_MIRRORED_REPEAT`, `GL_CLAMP_TO_EDGE` and `GL_CLAMP_TO_BORDER`, as below:&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;And `glViewport(0, 0, 512, 256)` but without any success.&#xD;&#xA;&#xD;&#xA;So where I'm wrong?&#xD;&#xA;&#xD;&#xA;Sorry for the long question, Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Mercator_projection&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Equirectangular_projection&#xD;&#xA;  [3]: https://i.stack.imgur.com/1h4vk.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/qLQlo.jpg&#xD;&#xA;  [5]: https://stackoverflow.com/questions/59907996/shader-that-transforms-a-mercator-projection-to-equirectangular&#xD;&#xA;  [6]: https://i.stack.imgur.com/JjzrH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28345" PostHistoryTypeId="2" PostId="9866" RevisionGUID="b3c78b79-eed4-430a-9433-1501806f5312" CreationDate="2020-05-19T09:30:03.427" UserId="13398" Text="[This question](https://stackoverflow.com/questions/59907996/shader-that-transforms-a-mercator-projection-to-equirectangular) and its answer, actually answer my question. I had to read its answer carefully and find my mistake.&#xD;&#xA;&#xD;&#xA;Now my fragment shader look like this:&#xD;&#xA;&#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 330 core&#xD;&#xA;    &#xD;&#xA;        in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;        uniform sampler2D ourTexture;&#xD;&#xA;    &#xD;&#xA;        #define PI       3.141592653589793238462f&#xD;&#xA;        #define TWO_PI   6.283185307179586476924f&#xD;&#xA;        #define PI4      0.7853981633974483096155f&#xD;&#xA;    &#xD;&#xA;        void main(){&#xD;&#xA;			if(TexCoord.y &gt; 0){&#xD;&#xA;            	float lat = (TexCoord.y - 0.5f) * PI;&#xD;&#xA;            	if(lat &gt;= -1.48442222974871 &amp;&amp; lat &lt;= 1.48442222974871){&#xD;&#xA;                	float y = log(tan(PI4 + (lat / 2.0)));&#xD;&#xA;                	y = (y + PI) / TWO_PI;&#xD;&#xA;                	gl_FragColor = texture(ourTexture, vec2(TexCoord.x, y));&#xD;&#xA;                	return;&#xD;&#xA;            	}&#xD;&#xA;			}&#xD;&#xA;            gl_FragColor = vec4(1, 1, 1, 0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;And it's works perfectly." ContentLicense="CC BY-SA 4.0" />
  <row Id="28346" PostHistoryTypeId="5" PostId="9866" RevisionGUID="d4acb065-e6d5-4f2c-8834-43c091e0defc" CreationDate="2020-05-19T09:40:15.693" UserId="13398" Comment="deleted 37 characters in body" Text="[This question](https://stackoverflow.com/questions/59907996/shader-that-transforms-a-mercator-projection-to-equirectangular) and its answer, actually answer my question. I had to read its answer carefully and find my mistake.&#xD;&#xA;&#xD;&#xA;Now my fragment shader look like this:&#xD;&#xA;&#xD;&#xA;    const GLchar* fragmentSource = R&quot;glsl(&#xD;&#xA;        #version 330 core&#xD;&#xA;    &#xD;&#xA;        in vec2 TexCoord;&#xD;&#xA;    &#xD;&#xA;        uniform sampler2D ourTexture;&#xD;&#xA;    &#xD;&#xA;        #define PI       3.141592653589793238462f&#xD;&#xA;        #define TWO_PI   6.283185307179586476924f&#xD;&#xA;        #define PI4      0.7853981633974483096155f&#xD;&#xA;    &#xD;&#xA;        void main(){&#xD;&#xA;            float lat = (TexCoord.y - 0.5f) * PI;&#xD;&#xA;            if(lat &gt;= -1.48442222974871 &amp;&amp; lat &lt;= 1.48442222974871){&#xD;&#xA;                float y = log(tan(PI4 + (lat / 2.0)));&#xD;&#xA;                y = (y + PI) / TWO_PI;&#xD;&#xA;                gl_FragColor = texture(ourTexture, vec2(TexCoord.x, y));&#xD;&#xA;                return;&#xD;&#xA;            }&#xD;&#xA;            gl_FragColor = vec4(1, 1, 1, 0);&#xD;&#xA;        }&#xD;&#xA;    )glsl&quot;;&#xD;&#xA;&#xD;&#xA;And it's works perfectly." ContentLicense="CC BY-SA 4.0" />
  <row Id="28348" PostHistoryTypeId="50" PostId="8790" RevisionGUID="7bc6b4af-7b3d-4ebe-8716-ae853c7c0e12" CreationDate="2020-05-20T08:09:10.903" UserId="-1" />
  <row Id="28350" PostHistoryTypeId="2" PostId="9867" RevisionGUID="847681ad-b657-4cfa-963d-3ca05aa5eec0" CreationDate="2020-05-20T17:16:31.950" UserId="13410" Text="If the iPhone had LiDAR sensors, it would be possible to generate a 3D point cloud that you could theoretically use to furnish a 3D AR reconstruction of your surroundings. E.g. you could create an AR video chat whereby you see a &quot;hologram&quot; projection of the person you are speaking with in your 3D environment. &#xD;&#xA;&gt;However, given that LiDAR is yet to be released on iPhone, would it be possible use two cameras simultaneously, e.g. the wide and normal, to correct for the camera FOV and optic distortion in each and then use the 3D stereoscopic transform in OpenCV knowing the optical properties of the setup (distance between the cameras, focal length, etc.) to generate a 3D image of the scene with almost as much precision as LiDAR? I think [depth map](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/capturing_photos_with_depth) in Apple's AVFoundation is certainly an alternative; however, the TrueDepth camera system was only introduced with the iPhoneX.&#xD;&#xA;&#xD;&#xA;This [Medium article](https://becominghuman.ai/stereo-3d-reconstruction-with-opencv-using-an-iphone-camera-part-i-c013907d1ab5) on Stereo 3D reconstruction seems to suggest that such a configuration is possible, although I suppose the small baseline distance between the cameras relative to the object might affect the outcome.&#xD;&#xA;&#xD;&#xA;Thanks in advance! I would appreciate it if this could be demonstrated by example :) I cross-posted [this question](https://stackoverflow.com/questions/61859605/can-you-use-opencv-stereo-3d-reconstruction-with-iphone-cameras-to-approximate-l) on Stackoverflow." ContentLicense="CC BY-SA 4.0" />
  <row Id="28351" PostHistoryTypeId="1" PostId="9867" RevisionGUID="847681ad-b657-4cfa-963d-3ca05aa5eec0" CreationDate="2020-05-20T17:16:31.950" UserId="13410" Text="Can you use OpenCV Stereo 3D Reconstruction with iPhone cameras to approximate LiDAR?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28352" PostHistoryTypeId="3" PostId="9867" RevisionGUID="847681ad-b657-4cfa-963d-3ca05aa5eec0" CreationDate="2020-05-20T17:16:31.950" UserId="13410" Text="|3d|transformations|geometry|projections|stereo-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28356" PostHistoryTypeId="2" PostId="9869" RevisionGUID="084d5429-9194-4c70-a895-380102c8115d" CreationDate="2020-05-21T17:50:27.423" UserId="11058" Text="When having vsync enabled I'm imagining that OpenGL has an explicit wait function to try and keep the frame rate constant. If so where is this function implemented exactly? After running some tests `glClear()` function seems to take almost 16 ms with minimal OpenGL script on my machine. When removing this function, the wait seems to happen where the first `glDrawArrays()` or `glDrawElements()` function is implemented (?). If none of these functions are implemented then on my machine the wait happens during `glxSwapBuffers()`.&#xD;&#xA;&#xD;&#xA;I'm hoping to get some better understanding behind his, partly to know when to best poll the input events. Previously I polled at the start of the main loop and then rendered the scene. But since there's a wait during `glClear()` function, I'm experiencing a bit of an input delay. So maybe it would make more sense to poll in-between clearing the buffers and rendering the scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28357" PostHistoryTypeId="1" PostId="9869" RevisionGUID="084d5429-9194-4c70-a895-380102c8115d" CreationDate="2020-05-21T17:50:27.423" UserId="11058" Text="With vsync enabled where does the wait happen in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28358" PostHistoryTypeId="3" PostId="9869" RevisionGUID="084d5429-9194-4c70-a895-380102c8115d" CreationDate="2020-05-21T17:50:27.423" UserId="11058" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28359" PostHistoryTypeId="2" PostId="9870" RevisionGUID="10bfb6a8-d97c-40c6-9d7a-6385cfbb78b0" CreationDate="2020-05-21T17:56:19.090" UserId="6041" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). Assume the color picker gives color C1=(186,70,2). If I create an image and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, then open it on a viewer I see exactly same color C1. &#xD;&#xA;And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28360" PostHistoryTypeId="1" PostId="9870" RevisionGUID="10bfb6a8-d97c-40c6-9d7a-6385cfbb78b0" CreationDate="2020-05-21T17:56:19.090" UserId="6041" Text="Problem on understanding gamma correction" ContentLicense="CC BY-SA 4.0" />
  <row Id="28361" PostHistoryTypeId="3" PostId="9870" RevisionGUID="10bfb6a8-d97c-40c6-9d7a-6385cfbb78b0" CreationDate="2020-05-21T17:56:19.090" UserId="6041" Text="|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28362" PostHistoryTypeId="5" PostId="9870" RevisionGUID="162162d7-8278-488e-89ec-fcb21cd8375d" CreationDate="2020-05-21T18:18:08.697" UserId="6041" Comment="added 45 characters in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, then open it on a viewer I see exactly same color C1. &#xD;&#xA;And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28363" PostHistoryTypeId="5" PostId="9870" RevisionGUID="bc156481-a55b-4afa-9dc4-d783947b3e64" CreationDate="2020-05-21T18:23:53.240" UserId="6041" Comment="added 6 characters in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). &#xD;&#xA;&#xD;&#xA;Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, I see exactly same color C1 on opening the file on a viewer.&#xD;&#xA;&#xD;&#xA;And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28364" PostHistoryTypeId="5" PostId="9869" RevisionGUID="31b34421-0051-49e8-b882-f2deb29ef894" CreationDate="2020-05-21T18:31:47.603" UserId="11058" Comment="edited body" Text="When having vsync enabled I'm imagining that OpenGL has an explicit wait function to try and keep the frame rate constant. If so where is this function implemented exactly? After running some tests `glClear()` function seems to take almost 16 ms with minimal OpenGL script on my machine. When removing this function, the wait seems to happen where the first (?) `glDrawArrays()` or `glDrawElements()` function is implemented. If none of these functions are implemented then on my machine the wait happens during `glxSwapBuffers()`.&#xD;&#xA;&#xD;&#xA;I'm hoping to get some better understanding behind his, partly to know when to best poll the input events. Previously I polled at the start of the main loop and then rendered the scene. But since there's a wait during `glClear()` function, I'm experiencing a bit of an input delay. So maybe it would make more sense to poll in-between clearing the buffers and rendering the scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28365" PostHistoryTypeId="2" PostId="9871" RevisionGUID="dab81f2a-c24b-4633-90b7-8fe8b04e9b57" CreationDate="2020-05-21T19:08:01.730" UserId="13421" Text="I'm implementing a volume raymarcher and the unlit basic version seems to be working fine. This article helped a ton grokking the view-to-volume-space transform: http://www.lebarba.com&#xD;&#xA;&#xD;&#xA;However, it's quickly gets ugly when reducing the ray step count to something that's feasible for doing a lighting nested loop.&#xD;&#xA;&#xD;&#xA;exaggerated sampling artifacts, 32 steps:&#xD;&#xA;&#xD;&#xA;[![steppy ray cube][1]][1]&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Ryan Brucks has some nice write up [here][2] where he describes some workarounds. I'm specifically trying to understand the **plane alignment** technique:&#xD;&#xA;&#xD;&#xA;[![Ray Brucks plane alignment][3]][3]&#xD;&#xA;&#xD;&#xA;his relevant shader snippet: &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;//bring vectors into local space to support object transforms&#xD;&#xA;float3 localcampos = mul(float4( ResolvedView.WorldCameraOrigin,1.00000000), (Primitive.WorldToLocal)).xyz;&#xD;&#xA;float3 localcamvec = -normalize( mul(Parameters.CameraVector, Primitive.WorldToLocal) );&#xD;&#xA;&#xD;&#xA;//make camera position 0-1&#xD;&#xA;localcampos = (localcampos / (Primitive.LocalObjectBoundsMax.x * 2)) + 0.5;&#xD;&#xA;&#xD;&#xA;float3 invraydir = 1 / localcamvec;&#xD;&#xA;&#xD;&#xA;float3 firstintersections = (0 - localcampos) * invraydir;&#xD;&#xA;float3 secondintersections = (1 - localcampos) * invraydir;&#xD;&#xA;float3 closest = min(firstintersections, secondintersections);&#xD;&#xA;float3 furthest = max(firstintersections, secondintersections);&#xD;&#xA;&#xD;&#xA;float t0 = max(closest.x, max(closest.y, closest.z));&#xD;&#xA;float t1 = min(furthest.x, min(furthest.y, furthest.z));&#xD;&#xA;&#xD;&#xA;float planeoffset = 1-frac( ( t0 - length(localcampos-0.5) ) * MaxSteps );&#xD;&#xA;&#xD;&#xA;t0 += (planeoffset / MaxSteps) * PlaneAlignment;&#xD;&#xA;t0 = max(0, t0);&#xD;&#xA;&#xD;&#xA;float boxthickness = max(0, t1 - t0);&#xD;&#xA;float3 entrypos = localcampos + (max(0,t0) * localcamvec);&#xD;&#xA;&#xD;&#xA;return float4( entrypos, boxthickness ); &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;For the life of me, I don't get how this works. I'm not familiar with Unreal Engine at all and doing my version in Metal.&#xD;&#xA;&#xD;&#xA;here's my version without plane offset adjustment:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;constant bool cam_inside        [[ function_constant(FogVolumeCamInsideIndex) ]];&#xD;&#xA;&#xD;&#xA;vertex VolumeVertexInOut vert_volume_raymarch(VolumeCubeVertex                   in             [[ stage_in   ]],&#xD;&#xA;                                              constant float4x4                  &amp;mvp           [[ buffer(10) ]],&#xD;&#xA;                                              constant float4x4                  &amp;model_inv     [[ buffer(11) ]],&#xD;&#xA;                                              constant float4                    &amp;cam_pos       [[ buffer(12) ]]) {&#xD;&#xA;    VolumeVertexInOut out;&#xD;&#xA;    out.local_cam_pos         = model_inv * cam_pos;&#xD;&#xA;    float4 world_pos          = cam_inside ? out.local_cam_pos : float4(in.position, 1.0);&#xD;&#xA;    out.position              = mvp * float4(in.position, 1);&#xD;&#xA;    out.volume_space_coords   = float4(world_pos.xyz + 0.5, 1).xyz;&#xD;&#xA;    out.projected_coords      = mvp * (cam_inside ? float4(in.position, 1) : world_pos);&#xD;&#xA;    return out;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;constant float MAX_STEPS = 512;&#xD;&#xA;constexpr sampler depth_sampler(filter::nearest);&#xD;&#xA;&#xD;&#xA;fragment float4 vert_volume_raymarch_compute_rays(VolumeVertexInOut                  in                           [[ stage_in     ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   tex_back_pos                 [[ texture(1)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   tex_front_pos                [[ texture(2)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   scene_depth_buffer           [[ texture(3)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   volume_depth_buffer_back     [[ texture(4)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   volume_depth_buffer_front    [[ texture(5)   ]],&#xD;&#xA;                                                  constant float                     &amp;zNear_scene                 [[ buffer(1)    ]],&#xD;&#xA;                                                  constant float                     &amp;zNear_local                 [[ buffer(2)    ]],&#xD;&#xA;                                                  constant float                     &amp;zFar                        [[ buffer(3)    ]],&#xD;&#xA;                                                  constant uint                      &amp;plane_alignment             [[ buffer(4)    ]]) {&#xD;&#xA;    &#xD;&#xA;    float2 texcoord         = (in.projected_coords.xy / in.projected_coords.w + 1) / 2;&#xD;&#xA;    texcoord.y              = 1-texcoord.y;&#xD;&#xA;    &#xD;&#xA;    float3 furthest         = tex_back_pos.sample(linearSampler, texcoord).xyz;&#xD;&#xA;    float3 entry_pos        = in.volume_space_coords;&#xD;&#xA;    &#xD;&#xA;    float scene_depth       = scene_depth_buffer.sample(depth_sampler, texcoord).r;&#xD;&#xA;    float closest_depth     = cam_inside ? 0 : volume_depth_buffer_front.sample(depth_sampler, texcoord).r;&#xD;&#xA;    float furthest_depth    = volume_depth_buffer_back.sample(depth_sampler, texcoord).r;&#xD;&#xA;    &#xD;&#xA;    scene_depth             = linearize_depth(scene_depth, zNear_scene, zFar);&#xD;&#xA;    closest_depth           = linearize_depth(closest_depth, zNear_local, zFar);&#xD;&#xA;    furthest_depth          = linearize_depth(furthest_depth, zNear_local, zFar);&#xD;&#xA;    closest_depth           = min(closest_depth, scene_depth);&#xD;&#xA;    &#xD;&#xA;    float thickness         = length(furthest - entry_pos);&#xD;&#xA;    scene_depth             = map(scene_depth, closest_depth, furthest_depth, 0.0, thickness);&#xD;&#xA;    scene_depth             = clamp(scene_depth, 0.0, thickness);&#xD;&#xA;    thickness               = min(scene_depth, thickness);&#xD;&#xA;    &#xD;&#xA;    return float4(entry_pos, thickness);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I think the method of computing the ray start/end points differs a bit. The scene depth bits are for interacting with classic vertex geometry.&#xD;&#xA;&#xD;&#xA;So the question is, how do I change my shader code to include that plane alignment thing? Or if there are other ways to do this right... I'm all ears. thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/chLYK.jpg&#xD;&#xA;  [2]: https://shaderbits.com/blog/creating-volumetric-ray-marcher&#xD;&#xA;  [3]: https://i.stack.imgur.com/LWGJv.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28366" PostHistoryTypeId="1" PostId="9871" RevisionGUID="dab81f2a-c24b-4633-90b7-8fe8b04e9b57" CreationDate="2020-05-21T19:08:01.730" UserId="13421" Text="volume raymarching - aligning sample coords with the 3d texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="28367" PostHistoryTypeId="3" PostId="9871" RevisionGUID="dab81f2a-c24b-4633-90b7-8fe8b04e9b57" CreationDate="2020-05-21T19:08:01.730" UserId="13421" Text="|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28368" PostHistoryTypeId="5" PostId="9871" RevisionGUID="ae54dce1-15b7-4594-a095-d3f9b7b35c9a" CreationDate="2020-05-21T19:14:45.687" UserId="13421" Comment="edited body" Text="I'm implementing a volume raymarcher and the unlit basic version seems to be working fine. This article helped a ton grokking the view-to-volume-space transform: http://www.lebarba.com&#xD;&#xA;&#xD;&#xA;However, it's quickly gets ugly when reducing the ray step count to something that's feasible for doing a lighting nested loop.&#xD;&#xA;&#xD;&#xA;exaggerated sampling artifacts, 32 steps:&#xD;&#xA;&#xD;&#xA;[![steppy ray cube][1]][1]&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Ryan Brucks has some nice write up [here][2] where he describes some workarounds. I'm specifically trying to understand the **plane alignment** technique:&#xD;&#xA;&#xD;&#xA;[![Ray Brucks plane alignment][3]][3]&#xD;&#xA;&#xD;&#xA;his relevant shader snippet: &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;//bring vectors into local space to support object transforms&#xD;&#xA;float3 localcampos = mul(float4( ResolvedView.WorldCameraOrigin,1.00000000), (Primitive.WorldToLocal)).xyz;&#xD;&#xA;float3 localcamvec = -normalize( mul(Parameters.CameraVector, Primitive.WorldToLocal) );&#xD;&#xA;&#xD;&#xA;//make camera position 0-1&#xD;&#xA;localcampos = (localcampos / (Primitive.LocalObjectBoundsMax.x * 2)) + 0.5;&#xD;&#xA;&#xD;&#xA;float3 invraydir = 1 / localcamvec;&#xD;&#xA;&#xD;&#xA;float3 firstintersections = (0 - localcampos) * invraydir;&#xD;&#xA;float3 secondintersections = (1 - localcampos) * invraydir;&#xD;&#xA;float3 closest = min(firstintersections, secondintersections);&#xD;&#xA;float3 furthest = max(firstintersections, secondintersections);&#xD;&#xA;&#xD;&#xA;float t0 = max(closest.x, max(closest.y, closest.z));&#xD;&#xA;float t1 = min(furthest.x, min(furthest.y, furthest.z));&#xD;&#xA;&#xD;&#xA;float planeoffset = 1-frac( ( t0 - length(localcampos-0.5) ) * MaxSteps );&#xD;&#xA;&#xD;&#xA;t0 += (planeoffset / MaxSteps) * PlaneAlignment;&#xD;&#xA;t0 = max(0, t0);&#xD;&#xA;&#xD;&#xA;float boxthickness = max(0, t1 - t0);&#xD;&#xA;float3 entrypos = localcampos + (max(0,t0) * localcamvec);&#xD;&#xA;&#xD;&#xA;return float4( entrypos, boxthickness ); &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;For the life of me, I don't get how this works. I'm not familiar with Unreal Engine at all and doing my version in Metal.&#xD;&#xA;&#xD;&#xA;here's my version without plane offset adjustment:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;constant bool cam_inside        [[ function_constant(FogVolumeCamInsideIndex) ]];&#xD;&#xA;&#xD;&#xA;vertex VolumeVertexInOut vert_volume_raymarch(VolumeCubeVertex                   in             [[ stage_in   ]],&#xD;&#xA;                                              constant float4x4                  &amp;mvp           [[ buffer(10) ]],&#xD;&#xA;                                              constant float4x4                  &amp;model_inv     [[ buffer(11) ]],&#xD;&#xA;                                              constant float4                    &amp;cam_pos       [[ buffer(12) ]]) {&#xD;&#xA;    VolumeVertexInOut out;&#xD;&#xA;    out.local_cam_pos         = model_inv * cam_pos;&#xD;&#xA;    float4 world_pos          = cam_inside ? out.local_cam_pos : float4(in.position, 1.0);&#xD;&#xA;    out.position              = mvp * float4(in.position, 1);&#xD;&#xA;    out.volume_space_coords   = float4(world_pos.xyz + 0.5, 1).xyz;&#xD;&#xA;    out.projected_coords      = mvp * (cam_inside ? float4(in.position, 1) : world_pos);&#xD;&#xA;    return out;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;constant float MAX_STEPS = 512;&#xD;&#xA;constexpr sampler depth_sampler(filter::nearest);&#xD;&#xA;&#xD;&#xA;fragment float4 frag_volume_raymarch_compute_rays(VolumeVertexInOut                  in                           [[ stage_in     ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   tex_back_pos                 [[ texture(1)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   tex_front_pos                [[ texture(2)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   scene_depth_buffer           [[ texture(3)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   volume_depth_buffer_back     [[ texture(4)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   volume_depth_buffer_front    [[ texture(5)   ]],&#xD;&#xA;                                                  constant float                     &amp;zNear_scene                 [[ buffer(1)    ]],&#xD;&#xA;                                                  constant float                     &amp;zNear_local                 [[ buffer(2)    ]],&#xD;&#xA;                                                  constant float                     &amp;zFar                        [[ buffer(3)    ]],&#xD;&#xA;                                                  constant uint                      &amp;plane_alignment             [[ buffer(4)    ]]) {&#xD;&#xA;    &#xD;&#xA;    float2 texcoord         = (in.projected_coords.xy / in.projected_coords.w + 1) / 2;&#xD;&#xA;    texcoord.y              = 1-texcoord.y;&#xD;&#xA;    &#xD;&#xA;    float3 furthest         = tex_back_pos.sample(linearSampler, texcoord).xyz;&#xD;&#xA;    float3 entry_pos        = in.volume_space_coords;&#xD;&#xA;    &#xD;&#xA;    float scene_depth       = scene_depth_buffer.sample(depth_sampler, texcoord).r;&#xD;&#xA;    float closest_depth     = cam_inside ? 0 : volume_depth_buffer_front.sample(depth_sampler, texcoord).r;&#xD;&#xA;    float furthest_depth    = volume_depth_buffer_back.sample(depth_sampler, texcoord).r;&#xD;&#xA;    &#xD;&#xA;    scene_depth             = linearize_depth(scene_depth, zNear_scene, zFar);&#xD;&#xA;    closest_depth           = linearize_depth(closest_depth, zNear_local, zFar);&#xD;&#xA;    furthest_depth          = linearize_depth(furthest_depth, zNear_local, zFar);&#xD;&#xA;    closest_depth           = min(closest_depth, scene_depth);&#xD;&#xA;    &#xD;&#xA;    float thickness         = length(furthest - entry_pos);&#xD;&#xA;    scene_depth             = map(scene_depth, closest_depth, furthest_depth, 0.0, thickness);&#xD;&#xA;    scene_depth             = clamp(scene_depth, 0.0, thickness);&#xD;&#xA;    thickness               = min(scene_depth, thickness);&#xD;&#xA;    &#xD;&#xA;    return float4(entry_pos, thickness);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I think the method of computing the ray start/end points differs a bit. The scene depth bits are for interacting with classic vertex geometry.&#xD;&#xA;&#xD;&#xA;So the question is, how do I change my shader code to include that plane alignment thing? Or if there are other ways to do this right... I'm all ears. thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/chLYK.jpg&#xD;&#xA;  [2]: https://shaderbits.com/blog/creating-volumetric-ray-marcher&#xD;&#xA;  [3]: https://i.stack.imgur.com/LWGJv.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28369" PostHistoryTypeId="2" PostId="9872" RevisionGUID="52fc352b-e165-442a-b177-6ce62774baf9" CreationDate="2020-05-21T19:23:05.510" UserId="13422" Text="I am visualizing a dataset. My technique is to encode the data into a rgb image with the channel range [0, 255]. The data clusters in a narrow range relative to [0, 255], however, so I'm not getting enough spread in the data to get a legible visualization when I use the standard normalization:&#xD;&#xA;&#xD;&#xA;    255 * (dataValue - dataMin) / (dataMax - dataMin)&#xD;&#xA;&#xD;&#xA;What non-linear normalization techniques could I use?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28370" PostHistoryTypeId="1" PostId="9872" RevisionGUID="52fc352b-e165-442a-b177-6ce62774baf9" CreationDate="2020-05-21T19:23:05.510" UserId="13422" Text="Normalization technique to increase spread of data in rgb space" ContentLicense="CC BY-SA 4.0" />
  <row Id="28371" PostHistoryTypeId="3" PostId="9872" RevisionGUID="52fc352b-e165-442a-b177-6ce62774baf9" CreationDate="2020-05-21T19:23:05.510" UserId="13422" Text="|normal-mapping|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28372" PostHistoryTypeId="5" PostId="9870" RevisionGUID="4ad019e5-a88b-465e-8c8c-5e2b99cfca2b" CreationDate="2020-05-21T19:57:22.143" UserId="6041" Comment="added 479 characters in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). &#xD;&#xA;&#xD;&#xA;Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, I see exactly same color C1 on opening the file on a viewer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Quoting from Wikipedia [Gamma correction][1] page:&#xD;&#xA;&#xD;&#xA;&gt; *For example, when using 24-bit RGB color (8 bits per channel), writing*&#xD;&#xA;&gt; *a value of 128 (rounded midpoint of the 0–255 byte range) in video*&#xD;&#xA;&gt; *memory it outputs the proportional ≈ 0.5 voltage to the display, which*&#xD;&#xA;&gt; *it is shown darker due to the monitor behavior.*&#xD;&#xA;&gt; *Alternatively, to achieve ≈ 50% intensity, a gamma-encoded look-up*&#xD;&#xA;&gt; *table can be applied to write a value near to 187 instead of 128 by*&#xD;&#xA;&gt; *the rendering software.*&#xD;&#xA;&#xD;&#xA;But this is not the case in my experiment. I save values of color C1 into the file and see color C1. And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gamma_correction#Methods_to_perform_display_gamma_correction_in_computing" ContentLicense="CC BY-SA 4.0" />
  <row Id="28373" PostHistoryTypeId="5" PostId="9872" RevisionGUID="0dcd998e-9577-4569-aabd-67437eff08d2" CreationDate="2020-05-21T21:08:22.817" UserId="13422" Comment="added 40 characters in body" Text="I am visualizing a dataset. My technique is to encode the data into a rgb image with the channel range [0, 255]. The data clusters in a narrow range relative to [0, 255], however, so I'm not getting enough spread in the data to get a legible visualization when I use the standard normalization:&#xD;&#xA;&#xD;&#xA;    255 * (dataValue - dataMin) / (dataMax - dataMin)&#xD;&#xA;&#xD;&#xA;What non-linear normalization techniques could I use? I know the mean and standard deviation." ContentLicense="CC BY-SA 4.0" />
  <row Id="28374" PostHistoryTypeId="2" PostId="9873" RevisionGUID="229c0114-cbef-4a01-8d9b-5d8210e9d252" CreationDate="2020-05-21T22:32:44.020" UserId="48" Text="It's a bit complicated because the actual wait for vsync does not happen on the CPU, it happens on the GPU. The GPU wait then creates [back-pressure](https://medium.com/@jayphelps/backpressure-explained-the-flow-of-data-through-software-2350b3e77ce7) that propagates back to the queue of submitted command lists on the CPU, through the GL driver, and eventually to your app. The exact behavior will depend on the details of how the GPU vendor chose to implement their GL driver, and also probably depends on the behavior of the windowing system as it controls frame presentation. Unfortunately there are no real guarantees about this in GL as far as I'm aware, it's really up to the vendors.&#xD;&#xA;&#xD;&#xA;In this case, it seems likely that you're seeing the wait become visible to your app at the first GL command that causes the driver to try to begin recording into a new command list (which may entail waiting for a previous command list to finish executing on the GPU, so that the driver can reuse it for the new frame). Clears, draw calls, dispatches, buffer mapping or copying, etc would probably qualify, while (for example) state-setting calls or memory allocation calls might not issue any actual commands to the GPU." ContentLicense="CC BY-SA 4.0" />
  <row Id="28375" PostHistoryTypeId="2" PostId="9874" RevisionGUID="4c21a109-4bc1-4cdd-a23b-2d8a3ac892b5" CreationDate="2020-05-21T23:15:23.417" UserId="48" Text="Almost all image formats store colors gamma-encoded, so if you write out those values to a file then that's what you'll see on opening it. The pixel pickers etc operate on the same values stored in the file. It's much less common to store linear-light color values in a file (one example is digital camera RAW files).&#xD;&#xA;&#xD;&#xA;When you &quot;see color C1&quot; on the screen, you *are* seeing C1^gamma. Or rather, you are seeing however that particular monitor renders the RGB value C1, which is at least approximately described by C1^gamma for some gamma. The color you see does not differ between the paint program and the programmatically generated file because they're both sending C1 to the monitor, and the monitor is doing the same thing with it." ContentLicense="CC BY-SA 4.0" />
  <row Id="28376" PostHistoryTypeId="5" PostId="9871" RevisionGUID="8362bc42-bbbf-4900-b0b4-a862c56a9062" CreationDate="2020-05-22T02:21:13.017" UserId="13421" Comment="deleted 1 character in body" Text="I'm implementing a volume raymarcher and the unlit basic version seems to be working fine. This article helped a ton grokking the view-to-volume-space transform: http://www.lebarba.com&#xD;&#xA;&#xD;&#xA;However, it quickly gets ugly when reducing the ray step count to something that's feasible for doing a lighting nested loop.&#xD;&#xA;&#xD;&#xA;exaggerated sampling artifacts, 32 steps:&#xD;&#xA;&#xD;&#xA;[![steppy ray cube][1]][1]&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Ryan Brucks has some nice write up [here][2] where he describes some workarounds. I'm specifically trying to understand the **plane alignment** technique:&#xD;&#xA;&#xD;&#xA;[![Ryan Brucks plane alignment][3]][3]&#xD;&#xA;&#xD;&#xA;his relevant shader snippet: &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;//bring vectors into local space to support object transforms&#xD;&#xA;float3 localcampos = mul(float4( ResolvedView.WorldCameraOrigin,1.00000000), (Primitive.WorldToLocal)).xyz;&#xD;&#xA;float3 localcamvec = -normalize( mul(Parameters.CameraVector, Primitive.WorldToLocal) );&#xD;&#xA;&#xD;&#xA;//make camera position 0-1&#xD;&#xA;localcampos = (localcampos / (Primitive.LocalObjectBoundsMax.x * 2)) + 0.5;&#xD;&#xA;&#xD;&#xA;float3 invraydir = 1 / localcamvec;&#xD;&#xA;&#xD;&#xA;float3 firstintersections = (0 - localcampos) * invraydir;&#xD;&#xA;float3 secondintersections = (1 - localcampos) * invraydir;&#xD;&#xA;float3 closest = min(firstintersections, secondintersections);&#xD;&#xA;float3 furthest = max(firstintersections, secondintersections);&#xD;&#xA;&#xD;&#xA;float t0 = max(closest.x, max(closest.y, closest.z));&#xD;&#xA;float t1 = min(furthest.x, min(furthest.y, furthest.z));&#xD;&#xA;&#xD;&#xA;float planeoffset = 1-frac( ( t0 - length(localcampos-0.5) ) * MaxSteps );&#xD;&#xA;&#xD;&#xA;t0 += (planeoffset / MaxSteps) * PlaneAlignment;&#xD;&#xA;t0 = max(0, t0);&#xD;&#xA;&#xD;&#xA;float boxthickness = max(0, t1 - t0);&#xD;&#xA;float3 entrypos = localcampos + (max(0,t0) * localcamvec);&#xD;&#xA;&#xD;&#xA;return float4( entrypos, boxthickness ); &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;For the life of me, I don't get how this works. I'm not familiar with Unreal Engine at all and doing my version in Metal.&#xD;&#xA;&#xD;&#xA;here's my version without plane offset adjustment:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;constant bool cam_inside        [[ function_constant(FogVolumeCamInsideIndex) ]];&#xD;&#xA;&#xD;&#xA;vertex VolumeVertexInOut vert_volume_raymarch(VolumeCubeVertex                   in             [[ stage_in   ]],&#xD;&#xA;                                              constant float4x4                  &amp;mvp           [[ buffer(10) ]],&#xD;&#xA;                                              constant float4x4                  &amp;model_inv     [[ buffer(11) ]],&#xD;&#xA;                                              constant float4                    &amp;cam_pos       [[ buffer(12) ]]) {&#xD;&#xA;    VolumeVertexInOut out;&#xD;&#xA;    out.local_cam_pos         = model_inv * cam_pos;&#xD;&#xA;    float4 world_pos          = cam_inside ? out.local_cam_pos : float4(in.position, 1.0);&#xD;&#xA;    out.position              = mvp * float4(in.position, 1);&#xD;&#xA;    out.volume_space_coords   = float4(world_pos.xyz + 0.5, 1).xyz;&#xD;&#xA;    out.projected_coords      = mvp * (cam_inside ? float4(in.position, 1) : world_pos);&#xD;&#xA;    return out;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;constant float MAX_STEPS = 512;&#xD;&#xA;constexpr sampler depth_sampler(filter::nearest);&#xD;&#xA;&#xD;&#xA;fragment float4 frag_volume_raymarch_compute_rays(VolumeVertexInOut                  in                           [[ stage_in     ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   tex_back_pos                 [[ texture(1)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   tex_front_pos                [[ texture(2)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   scene_depth_buffer           [[ texture(3)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   volume_depth_buffer_back     [[ texture(4)   ]],&#xD;&#xA;                                                  texture2d&lt;float, access::sample&gt;   volume_depth_buffer_front    [[ texture(5)   ]],&#xD;&#xA;                                                  constant float                     &amp;zNear_scene                 [[ buffer(1)    ]],&#xD;&#xA;                                                  constant float                     &amp;zNear_local                 [[ buffer(2)    ]],&#xD;&#xA;                                                  constant float                     &amp;zFar                        [[ buffer(3)    ]],&#xD;&#xA;                                                  constant uint                      &amp;plane_alignment             [[ buffer(4)    ]]) {&#xD;&#xA;    &#xD;&#xA;    float2 texcoord         = (in.projected_coords.xy / in.projected_coords.w + 1) / 2;&#xD;&#xA;    texcoord.y              = 1-texcoord.y;&#xD;&#xA;    &#xD;&#xA;    float3 furthest         = tex_back_pos.sample(linearSampler, texcoord).xyz;&#xD;&#xA;    float3 entry_pos        = in.volume_space_coords;&#xD;&#xA;    &#xD;&#xA;    float scene_depth       = scene_depth_buffer.sample(depth_sampler, texcoord).r;&#xD;&#xA;    float closest_depth     = cam_inside ? 0 : volume_depth_buffer_front.sample(depth_sampler, texcoord).r;&#xD;&#xA;    float furthest_depth    = volume_depth_buffer_back.sample(depth_sampler, texcoord).r;&#xD;&#xA;    &#xD;&#xA;    scene_depth             = linearize_depth(scene_depth, zNear_scene, zFar);&#xD;&#xA;    closest_depth           = linearize_depth(closest_depth, zNear_local, zFar);&#xD;&#xA;    furthest_depth          = linearize_depth(furthest_depth, zNear_local, zFar);&#xD;&#xA;    closest_depth           = min(closest_depth, scene_depth);&#xD;&#xA;    &#xD;&#xA;    float thickness         = length(furthest - entry_pos);&#xD;&#xA;    scene_depth             = map(scene_depth, closest_depth, furthest_depth, 0.0, thickness);&#xD;&#xA;    scene_depth             = clamp(scene_depth, 0.0, thickness);&#xD;&#xA;    thickness               = min(scene_depth, thickness);&#xD;&#xA;    &#xD;&#xA;    return float4(entry_pos, thickness);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I think the method of computing the ray start/end points differs a bit. The scene depth bits are for interacting with classic vertex geometry.&#xD;&#xA;&#xD;&#xA;So the question is, how do I change my shader code to include that plane alignment thing? Or if there are other ways to do this right... I'm all ears. thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/chLYK.jpg&#xD;&#xA;  [2]: https://shaderbits.com/blog/creating-volumetric-ray-marcher&#xD;&#xA;  [3]: https://i.stack.imgur.com/LWGJv.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28378" PostHistoryTypeId="5" PostId="9870" RevisionGUID="2a982aa0-5942-487c-accd-81dd3eeaaba2" CreationDate="2020-05-22T14:31:20.057" UserId="6041" Comment="added 467 characters in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). &#xD;&#xA;&#xD;&#xA;Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, I see exactly same color C1 on opening the file on a viewer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But this is not the case in my experiment. I save values of color C1 into the file and see color C1. And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;Basically here is the ppm file with all pixel RGB values (128,128,128). &#xD;&#xA;No gamma-encoding has been applied. That is simply writing linear values of 128.&#xD;&#xA;&#xD;&#xA;    P3&#xD;&#xA;    400 400&#xD;&#xA;    255&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;According to Wikipedia [Gamma correction][1] page:&#xD;&#xA;&#xD;&#xA;&gt; *For example, when using 24-bit RGB color (8 bits per channel), writing*&#xD;&#xA;&gt; *a value of 128 (rounded midpoint of the 0–255 byte range) in video*&#xD;&#xA;&gt; *memory it outputs the proportional ≈ 0.5 voltage to the display, which*&#xD;&#xA;&gt; *it is shown darker due to the monitor behavior.*&#xD;&#xA;&#xD;&#xA;Wikipedia clearly says write a value 128 and you will see a darker than you expect. Those values in my ppm file are not gamma-encoded and so I expect seeing &#xD;&#xA;a darker color(0.5^gamma) on the screen. Yet this is not the case and if you open this file on a viewer you will see pixels with brightness half as white.&#xD;&#xA;That is what I don't get.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gamma_correction#Methods_to_perform_display_gamma_correction_in_computing" ContentLicense="CC BY-SA 4.0" />
  <row Id="28379" PostHistoryTypeId="5" PostId="9874" RevisionGUID="f6b8a4fd-34a1-445f-afa4-bfc06da80efa" CreationDate="2020-05-22T19:56:30.990" UserId="48" Comment="added 1463 characters in body" Text="Almost all image formats store colors gamma-encoded, so if you write out those values to a file then that's what you'll see on opening it. The pixel pickers etc operate on the same values stored in the file. It's much less common to store linear-light color values in a file (one example is digital camera RAW files).&#xD;&#xA;&#xD;&#xA;When you &quot;see color C1&quot; on the screen, you *are* seeing C1^gamma. Or rather, you are seeing however that particular monitor renders the RGB value C1, which is at least approximately described by C1^gamma for some gamma. The color you see does not differ between the paint program and the programmatically generated file because they're both sending C1 to the monitor, and the monitor is doing the same thing with it.&#xD;&#xA;&#xD;&#xA;Re: your update, you wrote:&#xD;&#xA;&#xD;&#xA;&gt;if you open this file on a viewer you will see pixels with brightness half as white&#xD;&#xA;&#xD;&#xA;Think about this carefully. How are you judging that the pixels are &quot;half as white&quot;? Are you measuring them with a photometer and finding that they emit half the luminous intensity of a full white pixel? Or are you looking at them and judging that they appear roughly halfway between black and white?&#xD;&#xA;&#xD;&#xA;Human perception of brightness is very non-linear. A value that looks _perceptually_ halfway between black and white is _physically_ closer to 20% of the brightness of white, not 50%.&#xD;&#xA;&#xD;&#xA;A good way to find a true 50% brightness is to create an image with a checkerboard of black and white pixels, then defocus your eyes slightly, or stand farther away from the monitor, so that the pattern blurs into a uniform grey. That grey is 50% brightness (because it's an average over 50% black pixels and 50% white pixels). You will find that this grey looks considerably brighter than an RGB (128, 128, 128) grey.&#xD;&#xA;&#xD;&#xA;For example, open this image in a new tab to be sure it's appearing at 1:1 resolution (browsers resizing it do not necessarily respect gamma):&#xD;&#xA;[![gamma test image][1]][1]&#xD;&#xA;You will see that the checkerboard in the center looks a lot brighter than the 128 grey on the left, and should be pretty close to the 186 grey on the right. The 186 is encoding a 50% brightness at 2.2 gamma.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aMtnt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28382" PostHistoryTypeId="50" PostId="8431" RevisionGUID="8267d556-193c-46f8-9b0c-d9596430caa6" CreationDate="2020-05-23T00:02:20.227" UserId="-1" />
  <row Id="28383" PostHistoryTypeId="5" PostId="9870" RevisionGUID="45abaa33-841d-4c10-a629-4bb0c536b8c7" CreationDate="2020-05-23T11:19:14.443" UserId="6041" Comment="added 910 characters in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). &#xD;&#xA;&#xD;&#xA;Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, I see exactly same color C1 on opening the file on a viewer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But this is not the case in my experiment. I save values of color C1 into the file and see color C1. And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;Basically here is the ppm file with all pixel RGB values (128,128,128). &#xD;&#xA;No gamma-encoding has been applied. That is simply writing linear values of 128.&#xD;&#xA;&#xD;&#xA;    P3&#xD;&#xA;    400 400&#xD;&#xA;    255&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;According to Wikipedia [Gamma correction][1] page:&#xD;&#xA;&#xD;&#xA;&gt; *For example, when using 24-bit RGB color (8 bits per channel), writing*&#xD;&#xA;&gt; *a value of 128 (rounded midpoint of the 0–255 byte range) in video*&#xD;&#xA;&gt; *memory it outputs the proportional ≈ 0.5 voltage to the display, which*&#xD;&#xA;&gt; *it is shown darker due to the monitor behavior.*&#xD;&#xA;&#xD;&#xA;Wikipedia clearly says write a value 128 and you will see a darker than you expect. Those values in my ppm file are not gamma-encoded and so I expect seeing &#xD;&#xA;a darker color(0.5^gamma) on the screen. Yet this is not the case and if you open this file on a viewer you will see pixels with brightness half as white.&#xD;&#xA;That is what I don't get.&#xD;&#xA;&#xD;&#xA;***Update 2* (After Nathan good answer..)**&#xD;&#xA;&#xD;&#xA;So with input of 186 the screen outputs 50% of white intensity? &#xD;&#xA;And the eye perceives it as 50% as bright as white? is this right?&#xD;&#xA;But if the screen output is 50% in intensity, and eye has its own curve(roughly power of 1/gamma) then the screen output of 50% should be *seen* brighter? &#xD;&#xA;&#xD;&#xA;Another question I have is that, &#xD;&#xA;So is it the programmer responsibility to apply gamma-corrected values into the file or the whatever API we use to save image file formats does it internaly?&#xD;&#xA;For example i use .Net Bitmap class. Do I need to save bitmap with gamma-encoded values or Bitmap.Save method does it?&#xD;&#xA;I ask this since according Wikipedia, and you mentioned this too, almost all image formats are encoded&#xD;&#xA;&#xD;&#xA;&gt;  binary data in still image files (such as JPEG) are explicitly&#xD;&#xA;&gt; encoded (that is, they carry gamma-encoded values, not linear&#xD;&#xA;&gt; intensities)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gamma_correction#Methods_to_perform_display_gamma_correction_in_computing" ContentLicense="CC BY-SA 4.0" />
  <row Id="28384" PostHistoryTypeId="5" PostId="9870" RevisionGUID="b2288723-5b5f-4915-9e32-d1f23230f6b9" CreationDate="2020-05-23T11:56:52.743" UserId="6041" Comment="added 1 character in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). &#xD;&#xA;&#xD;&#xA;Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, I see exactly same color C1 on opening the file on a viewer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But this is not the case in my experiment. I save values of color C1 into the file and see color C1. And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;Basically here is the ppm file with all pixel RGB values (128,128,128). &#xD;&#xA;No gamma-encoding has been applied. That is simply writing linear values of 128.&#xD;&#xA;&#xD;&#xA;    P3&#xD;&#xA;    400 400&#xD;&#xA;    255&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;According to Wikipedia [Gamma correction][1] page:&#xD;&#xA;&#xD;&#xA;&gt; *For example, when using 24-bit RGB color (8 bits per channel), writing*&#xD;&#xA;&gt; *a value of 128 (rounded midpoint of the 0–255 byte range) in video*&#xD;&#xA;&gt; *memory it outputs the proportional ≈ 0.5 voltage to the display, which*&#xD;&#xA;&gt; *it is shown darker due to the monitor behavior.*&#xD;&#xA;&#xD;&#xA;Wikipedia clearly says write a value 128 and you will see a darker than you expect. Those values in my ppm file are not gamma-encoded and so I expect seeing &#xD;&#xA;a darker color(0.5^gamma) on the screen. Yet this is not the case and if you open this file on a viewer you will see pixels with brightness half as white.&#xD;&#xA;That is what I don't get.&#xD;&#xA;&#xD;&#xA;***Update 2* (After Nathan good answer..)**&#xD;&#xA;&#xD;&#xA;So with input of 186 the screen outputs 50% of white intensity? &#xD;&#xA;And the eye perceives it as 50% as bright as white? is this right?&#xD;&#xA;But if the screen output is 50% in intensity, and eye has its own curve(roughly power of 1/gamma) then the screen output of 50% should be *seen* brighter? &#xD;&#xA;&#xD;&#xA;Another question I have is that, &#xD;&#xA;So is it the programmer responsibility to write gamma-corrected values into the file or the whatever API we use to save image file formats does it internally?&#xD;&#xA;For example i use .Net Bitmap class. Do I need to save bitmap with gamma-encoded values or Bitmap.Save method does it?&#xD;&#xA;I ask this since according Wikipedia, and you mentioned this too, almost all image formats are encoded&#xD;&#xA;&#xD;&#xA;&gt;  binary data in still image files (such as JPEG) are explicitly&#xD;&#xA;&gt; encoded (that is, they carry gamma-encoded values, not linear&#xD;&#xA;&gt; intensities)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gamma_correction#Methods_to_perform_display_gamma_correction_in_computing" ContentLicense="CC BY-SA 4.0" />
  <row Id="28385" PostHistoryTypeId="5" PostId="9874" RevisionGUID="4a214ac4-c1a7-497a-962c-607c6af04b8b" CreationDate="2020-05-23T18:55:00.840" UserId="48" Comment="added 1220 characters in body" Text="Almost all image formats store colors gamma-encoded, so if you write out those values to a file then that's what you'll see on opening it. The pixel pickers etc operate on the same values stored in the file. It's much less common to store linear-light color values in a file (one example is digital camera RAW files).&#xD;&#xA;&#xD;&#xA;When you &quot;see color C1&quot; on the screen, you *are* seeing C1^gamma. Or rather, you are seeing however that particular monitor renders the RGB value C1, which is at least approximately described by C1^gamma for some gamma. The color you see does not differ between the paint program and the programmatically generated file because they're both sending C1 to the monitor, and the monitor is doing the same thing with it.&#xD;&#xA;&#xD;&#xA;**Re: your update**, you wrote:&#xD;&#xA;&#xD;&#xA;&gt;if you open this file on a viewer you will see pixels with brightness half as white&#xD;&#xA;&#xD;&#xA;Think about this carefully. How are you judging that the pixels are &quot;half as white&quot;? Are you measuring them with a photometer and finding that they emit half the luminous intensity of a full white pixel? Or are you looking at them and judging that they appear roughly halfway between black and white?&#xD;&#xA;&#xD;&#xA;Human perception of brightness is very non-linear. A value that looks _perceptually_ halfway between black and white is _physically_ closer to 20% of the brightness of white, not 50%.&#xD;&#xA;&#xD;&#xA;A good way to find a true 50% brightness is to create an image with a checkerboard of black and white pixels, then defocus your eyes slightly, or stand farther away from the monitor, so that the pattern blurs into a uniform grey. That grey is 50% brightness (because it's an average over 50% black pixels and 50% white pixels). You will find that this grey looks considerably brighter than an RGB (128, 128, 128) grey.&#xD;&#xA;&#xD;&#xA;For example, open this image in a new tab to be sure it's appearing at 1:1 resolution (browsers resizing it do not necessarily respect gamma):&#xD;&#xA;[![gamma test image][1]][1]&#xD;&#xA;You will see that the checkerboard in the center looks a lot brighter than the 128 grey on the left, and should be pretty close to the 186 grey on the right. The 186 is encoding a 50% brightness at 2.2 gamma.&#xD;&#xA;&#xD;&#xA;**Re: update 2**, you wrote:&#xD;&#xA;&#xD;&#xA;&gt;So with input of 186 the screen outputs 50% of white intensity? And the eye perceives it as 50% as bright as white?&#xD;&#xA;&#xD;&#xA;Not quite—the eye perceives a 50% physical intensity as *more* than halfway between black and white. Maybe around 70% or so. Conversely, the grey that the eye perceives as halfway between black and white is more like a 20% physical intensity.&#xD;&#xA;&#xD;&#xA;Actually, gamma-encoded values are a fairly close match to how we perceive brightness, which is convenient (although it's sort of a coincidence; the original reason for gamma was due to how CRT phosphors worked, not anything to do with perception). For a true perceptually uniform color space, you can look at [CIELAB](https://en.wikipedia.org/wiki/CIELAB_color_space), which has a more complicated nonlinear transformation that's designed to mimic average human perception.&#xD;&#xA;&#xD;&#xA;&gt;is it the programmer responsibility to write gamma-corrected values into the file or the whatever API we use to save image file formats does it internally?&#xD;&#xA;&#xD;&#xA;It's the programmer's responsibility. Almost all image file formats, libraries, and APIs are just passing around gamma-encoded values and do not do any transformations on them.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aMtnt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28386" PostHistoryTypeId="50" PostId="9364" RevisionGUID="fb2f0ace-fda9-4bcd-911d-958c6db09dd9" CreationDate="2020-05-23T20:05:40.563" UserId="-1" />
  <row Id="28387" PostHistoryTypeId="50" PostId="9744" RevisionGUID="2b76639c-4df8-4636-aa83-39fa6537e38e" CreationDate="2020-05-23T21:01:00.200" UserId="-1" />
  <row Id="28388" PostHistoryTypeId="2" PostId="9875" RevisionGUID="4c988f53-7cb8-45c5-b92d-defa78174ebb" CreationDate="2020-05-24T08:42:05.060" UserId="13436" Text="I'm working on a pathtracer and while it's working mostly fine, I'm getting different outputs with cosine-weighted sampling and uniform sampling : &#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;Uniform sampling is on the left, cosine-weighted is on the right. The difference is somewhat subtle, but it does not go away with more samples so it's not some kind of start up bias.&#xD;&#xA;&#xD;&#xA;I've checked my code against PBRT and Wikipedia but I cannot figure out what is wrong, because all the factors seem to be there (brdf, pdf, Li, and cos(theta)). I'm hoping someone here could take a fresh look at it :&#xD;&#xA;&#xD;&#xA;    // Sampling functions :&#xD;&#xA;    Vec3 sample_uniform_hemisphere(Sampler* sampler, float* pdf) {&#xD;&#xA;        float cosTheta, v;&#xD;&#xA;        sample_unit_square(sampler, &amp;cosTheta, &amp;v, NULL);&#xD;&#xA;        float sinTheta = sqrtf(1 - cosTheta * cosTheta);&#xD;&#xA;        float cosPhi = cosf(2 * M_PI * v);&#xD;&#xA;        float sinPhi = sinf(2 * M_PI * v);&#xD;&#xA;    &#xD;&#xA;        if (pdf)&#xD;&#xA;    	    *pdf = .5f / M_PI;&#xD;&#xA;        return (Vec3) {&#xD;&#xA;    	    sinTheta * cosPhi,&#xD;&#xA;    	    sinTheta * sinPhi,&#xD;&#xA;    	    cosTheta&#xD;&#xA;        };&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Vec3 sample_cosine_weighted_hemisphere(Sampler* sampler, float* pdf) {&#xD;&#xA;        Vec3 sample;&#xD;&#xA;        sample_unit_disc(sampler, &amp;sample.x, &amp;sample.y, NULL);&#xD;&#xA;    &#xD;&#xA;        float z2 = 1.0f - sample.x * sample.x - sample.y * sample.y;&#xD;&#xA;        sample.z = sqrtf(z2 &gt; 0.0f ? z2 : 0.0f);&#xD;&#xA;        if (pdf)&#xD;&#xA;    	    *pdf = sample.z / M_PI; // p(theta, phi) = cos(theta) / pi&#xD;&#xA;        return sample;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Snippet that does the actual shading :&#xD;&#xA;            float pdf;&#xD;&#xA;    	    Vec3 bounce_sample = it.material-&gt;bsdf-&gt;sampler(it.sampler, local_out, &amp;pdf);&#xD;&#xA;    	    Ray bounce = {&#xD;&#xA;    		.o = surface_point,&#xD;&#xA;    		.d = basis2world(bounce_sample, u, v, it.normal)&#xD;&#xA;    	    };&#xD;&#xA;    &#xD;&#xA;    	    Intersect bounce_it = trace_ray(sc, bounce, it.depth + 1, it.sampler);&#xD;&#xA;    	    Color f = it.material-&gt;bsdf-&gt;f(it.material-&gt;params,&#xD;&#xA;    					   bounce_sample, local_out);&#xD;&#xA;    	    Color dc = cmul(&#xD;&#xA;    		    bounce_it.outgoing_radiance,&#xD;&#xA;    		    f);&#xD;&#xA;    	    float inv_pdf = pdf &gt; EPSILON ? (1.0f / pdf) : 1.0f;&#xD;&#xA;    	    rval = cadd(rval,&#xD;&#xA;    			cscale(dc, inv_pdf * bounce_sample.z));&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/25oxs.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28389" PostHistoryTypeId="1" PostId="9875" RevisionGUID="4c988f53-7cb8-45c5-b92d-defa78174ebb" CreationDate="2020-05-24T08:42:05.060" UserId="13436" Text="How do I make sure my cosine-weighted sampling works fine?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28390" PostHistoryTypeId="3" PostId="9875" RevisionGUID="4c988f53-7cb8-45c5-b92d-defa78174ebb" CreationDate="2020-05-24T08:42:05.060" UserId="13436" Text="|pathtracing|brdf|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28392" PostHistoryTypeId="50" PostId="9756" RevisionGUID="ab02acca-e174-44d3-9c7a-a3a4ae45d0a9" CreationDate="2020-05-24T14:06:20.733" UserId="-1" />
  <row Id="28393" PostHistoryTypeId="2" PostId="9876" RevisionGUID="f7771f27-6564-4983-bd39-ac45715b85e1" CreationDate="2020-05-24T14:14:52.397" UserId="13095" Text="During vertex processing with 4x4 matrices, we might stack multiple transformations like projection, model-world, world-camera, etc. by doing something like this:&#xD;&#xA;&#xD;&#xA;$$v_{final} = T_N \cdot ... \cdot T_1 \cdot T_0 \cdot v$$&#xD;&#xA;&#xD;&#xA;Now from the [GLSL specs](https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf) (section 5.1), I get that the operator associativity is &quot;left to right&quot;. So this:&#xD;&#xA;&#xD;&#xA;$$v_{final} = T_2 \cdot T_1 \cdot T_0 \cdot v$$&#xD;&#xA;&#xD;&#xA;is equivalent to:&#xD;&#xA;&#xD;&#xA;$$v_{final} = ((T_2 \cdot T_1) \cdot T_0) \cdot v$$&#xD;&#xA;&#xD;&#xA;However, as matrix multiplication is associative, the result does not change if we write:&#xD;&#xA;&#xD;&#xA;$$v_{final} = T_2 \cdot (T_1 \cdot (T_0 \cdot v))$$&#xD;&#xA;&#xD;&#xA;While both versions yield the same result, the second version should (at least in theory) be much cheaper to compute since it incorporates 3 matrix-vector multiplications while the first version does 2 matrix-matrix multiplications and a final matrix-vector multiplication.&#xD;&#xA;&#xD;&#xA;So my question is, does enforcing the order by adding extra parenthesis really boost performance or is the GLSL compiler usually smart enough to figure out, that the order of operations does not matter for the result and he can reorder the executions for performance even though the specs say &quot;left to right&quot; associativity?&#xD;&#xA;&#xD;&#xA;**Additional Note**: &#xD;&#xA;I specially mentioned 4x4 matrices, because if you use 3x3 matrices or quaternions, you have to use parenthesis anyways because of the addition of the translations." ContentLicense="CC BY-SA 4.0" />
  <row Id="28394" PostHistoryTypeId="1" PostId="9876" RevisionGUID="f7771f27-6564-4983-bd39-ac45715b85e1" CreationDate="2020-05-24T14:14:52.397" UserId="13095" Text="Operator associativity and 4x4 matrices - performance question" ContentLicense="CC BY-SA 4.0" />
  <row Id="28395" PostHistoryTypeId="3" PostId="9876" RevisionGUID="f7771f27-6564-4983-bd39-ac45715b85e1" CreationDate="2020-05-24T14:14:52.397" UserId="13095" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28396" PostHistoryTypeId="2" PostId="9877" RevisionGUID="e26fc807-94a4-46e9-86ae-effb378ad086" CreationDate="2020-05-24T18:49:16.173" UserId="11386" Text="I am doing some parallel reduction and mostly following [these nVidia slides][1]. However they are not very detailed in places or I might be missing/misunderstanding something. &#xD;&#xA;I am working from Unity with compute shaders&#xD;&#xA;I successfully reduced data thus far but now ran out of groupshared memory when attempting to upscale everything*. Now the nVidia slides on parallel reduction say to use multiple kernel invocations and &quot;kernel launch serves as global synchronisation point&quot;. But I am a little unsure of how to take advantage of that. Currently my parallel reduction looks roughly like this: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RWStructuredBuffer&lt;float4&gt; buffers;&#xD;&#xA;    groupshared float4 sharedMem1[1024];&#xD;&#xA;    groupshared float4 sharedMem2[1024];&#xD;&#xA;    int specificIndex;&#xD;&#xA;&#xD;&#xA;    [numthreads(32, 32, 1)]&#xD;&#xA;    void ComputeStuff32x32(int3 id : SV_GroupThreadID, int3 gID : SV_GroupID)&#xD;&#xA;    {&#xD;&#xA;       Dostuff();...&#xD;&#xA;&#xD;&#xA;       GroupMemoryBarrierWithGroupSync();&#xD;&#xA; &#xD;&#xA;	   for (unsigned int s = 512; s &gt; 0; s &gt;&gt;= 1)&#xD;&#xA;       {&#xD;&#xA;		   if (flatId &lt; s)&#xD;&#xA;		   {&#xD;&#xA;		     	for (int i = 0; i &lt; 9; i++)&#xD;&#xA;			    {&#xD;&#xA;		    		sharedMem[flatId] += sharedMem[flatId+ s];&#xD;&#xA;                    sharedMem2[flatId] += sharedMem2[flatId+ s];&#xD;&#xA;		    	}&#xD;&#xA;	    	}&#xD;&#xA;	    	GroupMemoryBarrierWithGroupSync();&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;    	if (flatId == 0) {&#xD;&#xA;        buffer[specificIndex] = sharedMem[0]&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this all works fine in a 16x16 kernel but when i get to 32x32 I'm running out of shared memory. How exactly would i go about dispatching the kernel 4 times as a 16x16 reduction and combining the 4 resulting values?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Unity says: &quot;Shader error in 'computeStuff.compute': Program 'ComputeStuff32x32', error X4586: The total amount of group shared memory (110592 bytes) exceeds the cs_5_0 limit of 32768 bytes at kernel ComputeSH32x32 (on d3d11)&quot;) &#xD;&#xA;&#xD;&#xA;  [1]: https://developer.download.nvidia.com/assets/cuda/files/reduction.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28397" PostHistoryTypeId="1" PostId="9877" RevisionGUID="e26fc807-94a4-46e9-86ae-effb378ad086" CreationDate="2020-05-24T18:49:16.173" UserId="11386" Text="Groupshared memory and parallel reduction over multiple kernel dispatch" ContentLicense="CC BY-SA 4.0" />
  <row Id="28398" PostHistoryTypeId="3" PostId="9877" RevisionGUID="e26fc807-94a4-46e9-86ae-effb378ad086" CreationDate="2020-05-24T18:49:16.173" UserId="11386" Text="|compute-shader|memory|unity|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28399" PostHistoryTypeId="2" PostId="9878" RevisionGUID="c88283c5-96ce-41fe-8e7e-4ba0831aca68" CreationDate="2020-05-24T19:09:32.600" UserId="48" Text="As Olivier mentioned, it's not safe in general to apply algebraic optimizations to floating-point math, as floating point doesn't actually obey associativity rules due to roundoff error. $(a + b) - b$ will not be equal to $a$, if the intermediate result $(a + b)$ had to be rounded; nor will $a \cdot (b + c)$ be equal to $a \cdot b + a \cdot c$ in general, for the same reason.&#xD;&#xA;&#xD;&#xA;That being said, shader compilers are typically very relaxed about floating-point math optimizations. They behave like using [-ffast-math](https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math) on a C++ compiler, where they make various simplifying assumptions—including that algebraic operations _are_ associative—in order to optimize more aggressively. So it's not out of the question that a GLSL compiler could actually make the optimization you describe.&#xD;&#xA;&#xD;&#xA;That said, GLSL compilers vary wildly in quality; there is no canonical GLSL compiler, every GPU vendor implements their own (for OpenGL at least—in the case of Vulkan there are a couple standardized options), and who knows what level of optimizations they might or might not apply under various circumstances. If you wish the code to be optimized in a particular way, better to write it explicitly that way.&#xD;&#xA;&#xD;&#xA;One other point,&#xD;&#xA;&#xD;&#xA;&gt;the second version should (at least in theory) be much cheaper to compute &#xD;&#xA;&#xD;&#xA;It's only cheaper if you're transforming just a single vertex. If you want to transform thousands of vertices by the same matrix, it will be cheaper to multiply all the matrices together up front; then each vertex only needs to be transformed by a single 4×4 matrix instead of several." ContentLicense="CC BY-SA 4.0" />
  <row Id="28400" PostHistoryTypeId="2" PostId="9879" RevisionGUID="b73f7a80-a3e7-44d4-99dc-ffa5aaab232d" CreationDate="2020-05-24T19:09:48.757" UserId="11386" Text="well, if anyone is stumbling across this and needs to know what solved it for me: We can bind a computebuffer to global shader memory if we just know what exactly we need to do&#xD;&#xA;&#xD;&#xA;within the Compute shader the RWstructuredBuffer is declared as (without the &quot;\&quot; infront of float): &#xD;&#xA;&gt; uniform RWStructuredBuffer&lt;\float3&gt; buffer : register(u1);&#xD;&#xA;&#xD;&#xA;(not certain whether register(u1) is really needed&#xD;&#xA;&#xD;&#xA;within the vert/frag shader the buffer is defined as:&#xD;&#xA;&gt; uniform StructuredBuffer&lt;\float3&gt; buffer;	&#xD;&#xA;&#xD;&#xA;In a c# script before kernel dispatch i assign the buffer via&#xD;&#xA;&#xD;&#xA;&gt; buffer = new ComputeBuffer(size, sizeof(float)*3,ComputeBufferType.Default);&#xD;&#xA;Shader.SetGlobalBuffer(Shader.PropertyToID(&quot;buffer&quot;), buffer);&#xD;&#xA;&#xD;&#xA;It took me ages to find this and it works as far as i can tell. [The article i finally stumbled over that did something similar][1]. I do not have to read the data back to cpu with buffer.GetData(container) and put it into the material manually. &#xD;&#xA;If the compute shader changes the buffer data this will be reflected in the vert/frag shader immediately. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.tzaeru.com/site/compute-shader-basics-with-unity/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28401" PostHistoryTypeId="2" PostId="9880" RevisionGUID="056f7d0e-9627-4083-b9db-d5da8c61f935" CreationDate="2020-05-24T19:44:09.817" UserId="48" Text="Flood filling is not a very GPU-friendly operation to begin with, and the algorithm described in the paper is not a very good way to go about flood-filling on the GPU either. It might be possible to make it happen with some heroic efforts and compute shaders, but if flood-filling is what you want to do, I would use a different approach altogether. For example [this answer](https://gamedev.stackexchange.com/a/150033/9894) describes how to do flood-filling with a multi-pass approach where each pass extends the filled region by 1 pixel in all directions. It will take a lot of passes to fill a large region. You could probably use some variant of [jump flooding](https://blog.demofox.org/2016/02/29/fast-voronoi-diagrams-and-distance-dield-textures-on-the-gpu-with-the-jump-flooding-algorithm/) for a more efficient method.&#xD;&#xA;&#xD;&#xA;However, if you don't actually care about flood filling but are just looking to do exercises to learn GPU programming, I'd recommend trying things like: blur filters, outlining, color transforms, image warping, and so on as those will be a lot more straightforward than any kind of flood fill." ContentLicense="CC BY-SA 4.0" />
  <row Id="28402" PostHistoryTypeId="5" PostId="9877" RevisionGUID="34043ef4-574e-483e-a0ba-bb10ea8f8f17" CreationDate="2020-05-24T20:38:02.533" UserId="11386" Comment="deleted 58 characters in body" Text="I am doing some parallel reduction and mostly following [these nVidia slides][1]. However they are not very detailed in places or I might be missing/misunderstanding something. &#xD;&#xA;I am working from Unity with compute shaders&#xD;&#xA;I successfully reduced data thus far but now ran out of groupshared memory when attempting to upscale everything*. Now the nVidia slides on parallel reduction say to use multiple kernel invocations and &quot;kernel launch serves as global synchronisation point&quot;. But I am a little unsure of how to take advantage of that. Currently my parallel reduction looks roughly like this: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RWStructuredBuffer&lt;float4&gt; buffers;&#xD;&#xA;    groupshared float4 sharedMem1[1024];&#xD;&#xA;    groupshared float4 sharedMem2[1024];&#xD;&#xA;    int specificIndex;&#xD;&#xA;&#xD;&#xA;    [numthreads(32, 32, 1)]&#xD;&#xA;    void ComputeStuff32x32(int3 id : SV_GroupThreadID, int3 gID : SV_GroupID)&#xD;&#xA;    {&#xD;&#xA;       Dostuff();...&#xD;&#xA;&#xD;&#xA;       GroupMemoryBarrierWithGroupSync();&#xD;&#xA; &#xD;&#xA;	   for (unsigned int s = 512; s &gt; 0; s &gt;&gt;= 1)&#xD;&#xA;       {&#xD;&#xA;		   if (flatId &lt; s)&#xD;&#xA;		   {&#xD;&#xA;		    	sharedMem[flatId] += sharedMem[flatId+ s];&#xD;&#xA;                sharedMem2[flatId] += sharedMem2[flatId+ s];&#xD;&#xA;	       }&#xD;&#xA;	       GroupMemoryBarrierWithGroupSync();&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;    	if (flatId == 0) {&#xD;&#xA;        buffer[specificIndex] = sharedMem[0]&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this all works fine in a 16x16 kernel but when i get to 32x32 I'm running out of shared memory. How exactly would i go about dispatching the kernel 4 times as a 16x16 reduction and combining the 4 resulting values?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Unity says: &quot;Shader error in 'computeStuff.compute': Program 'ComputeStuff32x32', error X4586: The total amount of group shared memory (110592 bytes) exceeds the cs_5_0 limit of 32768 bytes at kernel ComputeSH32x32 (on d3d11)&quot;) &#xD;&#xA;&#xD;&#xA;  [1]: https://developer.download.nvidia.com/assets/cuda/files/reduction.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28403" PostHistoryTypeId="5" PostId="9877" RevisionGUID="f26c2f88-4056-4f55-b2d6-4fa87b3aa029" CreationDate="2020-05-24T22:23:03.420" UserId="11386" Comment="added 201 characters in body" Text="I am doing some parallel reduction and mostly following [these nVidia slides][1]. However they are not very detailed in places or I might be missing/misunderstanding something. &#xD;&#xA;I am working from Unity with compute shaders&#xD;&#xA;I successfully reduced data thus far but now ran out of groupshared memory when attempting to upscale everything*. Now the nVidia slides on parallel reduction say to use multiple kernel invocations and &quot;kernel launch serves as global synchronisation point&quot;. But I am a little unsure of how to take advantage of that. Currently my parallel reduction looks roughly like this: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RWStructuredBuffer&lt;float4&gt; buffers;&#xD;&#xA;    groupshared float4 sharedMem1[1024];&#xD;&#xA;    groupshared float4 sharedMem2[1024];&#xD;&#xA;    int specificIndex;&#xD;&#xA;&#xD;&#xA;    [numthreads(32, 32, 1)]&#xD;&#xA;    void ComputeStuff32x32(int3 id : SV_GroupThreadID, int3 gID : SV_GroupID)&#xD;&#xA;    {&#xD;&#xA;       Dostuff();...&#xD;&#xA;&#xD;&#xA;       GroupMemoryBarrierWithGroupSync();&#xD;&#xA; &#xD;&#xA;	   for (unsigned int s = 512; s &gt; 0; s &gt;&gt;= 1)&#xD;&#xA;       {&#xD;&#xA;		   if (flatId &lt; s)&#xD;&#xA;		   {&#xD;&#xA;		    	sharedMem[flatId] += sharedMem[flatId+ s];&#xD;&#xA;                sharedMem2[flatId] += sharedMem2[flatId+ s];&#xD;&#xA;	       }&#xD;&#xA;	       GroupMemoryBarrierWithGroupSync();&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;    	if (flatId == 0) {&#xD;&#xA;        buffer[specificIndex] = sharedMem[0]&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this all works fine in a 16x16 kernel but when i get to 32x32 I'm running out of shared memory. How exactly would i go about dispatching the kernel 4 times as a 16x16 reduction and combining the 4 resulting values? **Edit:** And if I need to synchronize over multiple kernel dispatches what exactly are multiple thread groups good for? Can I somehow just create multiple groups and synchronize them? **end of edit**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Unity says: &quot;Shader error in 'computeStuff.compute': Program 'ComputeStuff32x32', error X4586: The total amount of group shared memory (110592 bytes) exceeds the cs_5_0 limit of 32768 bytes at kernel ComputeSH32x32 (on d3d11)&quot;) &#xD;&#xA;&#xD;&#xA;  [1]: https://developer.download.nvidia.com/assets/cuda/files/reduction.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28404" PostHistoryTypeId="2" PostId="9881" RevisionGUID="48314d0a-dd53-4562-9cea-4505cd8ec485" CreationDate="2020-05-25T00:54:31.617" UserId="13439" Text="I need to embed text in an image, research papers say HSI produces better mse and psnr therefore are better for steganography. I have RGB values(69,223,90) and its corresponding HSI is (127.223,0.458 ,0.499) I transformed I-plane 0.499 so its between 0 and 255 and got 127 as the Intensity, decreased it by one to 126(embed 0 bit). 126 was converted to the I plane normal range 0.494 and the new RGB values are red=68 green=221 blue=89. It decreased all 3 RGB values and green even more than 1. I dont understand how this is better and makes psnr better? I know the equation but say i decreased/increased the value of the intensity plane by 1 how does this affect RGB?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28405" PostHistoryTypeId="1" PostId="9881" RevisionGUID="48314d0a-dd53-4562-9cea-4505cd8ec485" CreationDate="2020-05-25T00:54:31.617" UserId="13439" Text="HSI color space and rgb color space relationship in Steganography" ContentLicense="CC BY-SA 4.0" />
  <row Id="28406" PostHistoryTypeId="3" PostId="9881" RevisionGUID="48314d0a-dd53-4562-9cea-4505cd8ec485" CreationDate="2020-05-25T00:54:31.617" UserId="13439" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28407" PostHistoryTypeId="2" PostId="9882" RevisionGUID="62c6532e-bd26-47c3-8149-b64a125295f2" CreationDate="2020-05-25T07:56:21.213" UserId="1614" Text="The approaches mentioned by the 3 answers up to now (May 2020) mention:&#xD;&#xA;&#xD;&#xA; - subdivision surfaces&#xD;&#xA; - BVH per object tracing/eviction + ray cache + memory management&#xD;&#xA;&#xD;&#xA;There are other orthogonal techniques that can be added or used by themselves. That is decimation based on something else than OpenSubdiv. Like:&#xD;&#xA;&#xD;&#xA; - Distance fields&#xD;&#xA; - Octahedral impostors https://www.shaderbits.com/blog/octahedral-impostors&#xD;&#xA; - image meshes (geometry is baked in maps)&#xD;&#xA; - camera mapping&#xD;&#xA; - voxelization&#xD;&#xA;&#xD;&#xA;A different angle of thought: if your scene doesn't fit in memory, it has an entropy problem. You only have 4k res (~8 Million pixels?), therefore in the sense of Shannon &quot;more than memory&quot; cannot reasonably map to less data than can be projected to these 8Mp. Which means a scene that uses &quot;more than memory&quot; is most likely a super overkill. Thus again, the simplification approach will probably not only speed up things, but also could help aliasing." ContentLicense="CC BY-SA 4.0" />
  <row Id="28408" PostHistoryTypeId="2" PostId="9883" RevisionGUID="e11e4de9-7b16-4511-87ad-256c740249d3" CreationDate="2020-05-25T10:00:31.563" UserId="5944" Text="Why does the equation at the bottom of the following page hold?&#xD;&#xA;&#xD;&#xA;http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Transforming_between_Distributions.html&#xD;&#xA;&#xD;&#xA;$p(\theta,\phi)d\theta d\phi=p(\omega)d\omega$&#xD;&#xA;&#xD;&#xA;Is this a conclusion of probability and measure theory?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28409" PostHistoryTypeId="1" PostId="9883" RevisionGUID="e11e4de9-7b16-4511-87ad-256c740249d3" CreationDate="2020-05-25T10:00:31.563" UserId="5944" Text="An equation about PDFs and differentials in the book of pbrt-v3" ContentLicense="CC BY-SA 4.0" />
  <row Id="28410" PostHistoryTypeId="3" PostId="9883" RevisionGUID="e11e4de9-7b16-4511-87ad-256c740249d3" CreationDate="2020-05-25T10:00:31.563" UserId="5944" Text="|distribution|pbrt|pdf|differential|pbrt-v3|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28411" PostHistoryTypeId="2" PostId="9884" RevisionGUID="5c8c915f-2995-4820-b055-1614e1f77522" CreationDate="2020-05-25T11:01:59.143" UserId="8877" Text="https://courses.cs.washington.edu/courses/cse458/99sp/projects/help/phong_params.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        Material	Diff. slider	Diff. color	            Spec. slider    Spec. color	        Shininess&#xD;&#xA;        Metal	    low	            color of metal	        high	        color of metal	    high&#xD;&#xA;        Plastic	    medium	        color of plastic	    medium	        white	            medium&#xD;&#xA;        Lunar dust	high	        white	                0	            --	                0&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28412" PostHistoryTypeId="4" PostId="9881" RevisionGUID="e9d5d67a-df06-4780-8148-54ca74ce3e7a" CreationDate="2020-05-25T11:44:33.347" UserId="13439" Comment="edited title" Text="HSI color space and RGB color space relationship in Steganography" ContentLicense="CC BY-SA 4.0" />
  <row Id="28413" PostHistoryTypeId="5" PostId="9877" RevisionGUID="1fcb217d-72ec-4778-9da9-0825cef71674" CreationDate="2020-05-25T14:10:43.003" UserId="11386" Comment="added 1781 characters in body" Text="I am doing some parallel reduction and mostly following [these nVidia slides][1]. However they are not very detailed in places or I might be missing/misunderstanding something. &#xD;&#xA;&#xD;&#xA;**Edit 2:**&#xD;&#xA;While I figured out a solution for my usecase as mentioned later I am very skeptical of the efficiency of this (assigning a second computebuffer and second kernel etc.) and would appreciate if anyone could tell me how to do this properly or point out problems with this solution. *NB: i am storing more data in groupshared memory than in these code examples but the fundamental operations are the same*&#xD;&#xA;**end of edit**&#xD;&#xA;&#xD;&#xA;I am working from Unity with compute shaders.&#xD;&#xA;I successfully reduced data thus far but now ran out of groupshared memory when attempting to upscale everything*. Now the nVidia slides on parallel reduction say to use multiple kernel invocations and &quot;kernel launch serves as global synchronisation point&quot;. But I am a little unsure of how to take advantage of that. Currently my parallel reduction looks roughly like this: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    RWStructuredBuffer&lt;float4&gt; buffers;&#xD;&#xA;    groupshared float4 sharedMem1[1024];&#xD;&#xA;    groupshared float4 sharedMem2[1024];&#xD;&#xA;    int specificIndex;&#xD;&#xA;&#xD;&#xA;    [numthreads(32, 32, 1)]&#xD;&#xA;    void ComputeStuff32x32(int3 id : SV_GroupThreadID, int3 gID : SV_GroupID)&#xD;&#xA;    {&#xD;&#xA;       Dostuff();...&#xD;&#xA;&#xD;&#xA;       GroupMemoryBarrierWithGroupSync();&#xD;&#xA; &#xD;&#xA;	   for (unsigned int s = 512; s &gt; 0; s &gt;&gt;= 1)&#xD;&#xA;       {&#xD;&#xA;		   if (flatId &lt; s)&#xD;&#xA;		   {&#xD;&#xA;		    	sharedMem[flatId] += sharedMem[flatId+ s];&#xD;&#xA;                sharedMem2[flatId] += sharedMem2[flatId+ s];&#xD;&#xA;	       }&#xD;&#xA;	       GroupMemoryBarrierWithGroupSync();&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;    	if (flatId == 0) {&#xD;&#xA;        buffer[specificIndex] = sharedMem[0]&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now this all works fine in a 16x16 kernel but when i get to 32x32 I'm running out of shared memory. How exactly would i go about dispatching the kernel 4 times as a 16x16 reduction and combining the 4 resulting values? **Edit:** And if I need to synchronize over multiple kernel dispatches what exactly are multiple thread groups good for? Can I somehow just create multiple groups and synchronize them? **end of edit**&#xD;&#xA;&#xD;&#xA;**Edit 2:**&#xD;&#xA;I am succesfully brute forcing this by simply having an additional RWStructuredBuffer&lt;\float3&gt; tempBuffer; with a size of 32*sizeof(float3). The first kernel is dispatched in 32 groups of 32 threads (rather than 32x32 threads) that reduce all data along x axis and store it in the tempBuffer[groupID] &#xD;&#xA;&#xD;&#xA;    RWStructuredBuffer&lt;float4&gt; groupResults;&#xD;&#xA;    RWStructuredBuffer&lt;float4&gt; finalResult;&#xD;&#xA;    groupshared float4 sharedMem1[32];&#xD;&#xA;    [numthreads(32, 1, 1)]&#xD;&#xA;    void Compute32x32(int3 id : SV_GroupThreadID, int3 gID : SV_GroupID)&#xD;&#xA;    {   &#xD;&#xA;        doReduction();&#xD;&#xA;    	if (id.x == 0) &#xD;&#xA;  	    {&#xD;&#xA;             groupResults[gID.x] = sharedMem1[0]&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After dispatch of this kernel i dispatch another kernel to combine the result:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    groupshared float4 sharedMem2[32];&#xD;&#xA;    [numthreads(32, 1, 1)]	// combines the result from previous thread groups&#xD;&#xA;    void combine32x32Result(int3 id : SV_GroupThreadID, int3 gID : SV_GroupID)&#xD;&#xA;    {&#xD;&#xA;    	sharedMem2[i] = groupResults[i];&#xD;&#xA;		&#xD;&#xA;    	for (unsigned int s = 16; s &gt; 0; s &gt;&gt;= 1) &#xD;&#xA;    	{				&#xD;&#xA;    		if (id.x &lt; s)&#xD;&#xA;		    {&#xD;&#xA;			    sharedMem2[i] += sharedMem2[i+s];	&#xD;&#xA;		    }&#xD;&#xA;	     	GroupMemoryBarrierWithGroupSync();&#xD;&#xA;     	}&#xD;&#xA;&#xD;&#xA;	    if (id.x == 0) &#xD;&#xA;	    {&#xD;&#xA;		    finalResult[0] = sharedMem2[0];&#xD;&#xA;	    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As mentioned above i would refardless appreciate any pointers to things I am doing suboptimally / how to do things more efficiently or properly. &#xD;&#xA;**end of edit**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Unity says: &quot;Shader error in 'computeStuff.compute': Program 'ComputeStuff32x32', error X4586: The total amount of group shared memory (110592 bytes) exceeds the cs_5_0 limit of 32768 bytes at kernel ComputeSH32x32 (on d3d11)&quot;) &#xD;&#xA;&#xD;&#xA;  [1]: https://developer.download.nvidia.com/assets/cuda/files/reduction.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28414" PostHistoryTypeId="50" PostId="8807" RevisionGUID="edd056d2-e8ab-4955-a637-b6ec7079ff14" CreationDate="2020-05-26T01:02:50.330" UserId="-1" />
  <row Id="28415" PostHistoryTypeId="2" PostId="9885" RevisionGUID="dacf8af0-b356-4068-bf49-9429fd17bdda" CreationDate="2020-05-26T08:05:30.353" UserId="13447" Text="I have an ecommerce website dealing with flowers and cakes, we get our photoshoot done inhouse and also the post shoot editing of images. While we upload them on website all images go through same image compression algorithm. But if we compare all images, then we find product images having red color in them loosing out most of its details only in the areas with red color. &#xD;&#xA;&#xD;&#xA;I have attached an image below for your reference, here left hand side image is at 80% quality and right side have no compression in place. If you compare all these images, then you will find images have red color areas, they loose details most, at least visually. &#xD;&#xA;&#xD;&#xA;I have read about jpeg compression but it says that color doesn't make any difference, but it is not the case here. &#xD;&#xA;&#xD;&#xA;Can we do anything while photoshoot or post editing to fix these issues?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zsb3a.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28416" PostHistoryTypeId="1" PostId="9885" RevisionGUID="dacf8af0-b356-4068-bf49-9429fd17bdda" CreationDate="2020-05-26T08:05:30.353" UserId="13447" Text="Why red color looses details most in jpeg compression" ContentLicense="CC BY-SA 4.0" />
  <row Id="28417" PostHistoryTypeId="3" PostId="9885" RevisionGUID="dacf8af0-b356-4068-bf49-9429fd17bdda" CreationDate="2020-05-26T08:05:30.353" UserId="13447" Text="|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28418" PostHistoryTypeId="2" PostId="9886" RevisionGUID="67c6a573-890a-404d-849e-122a72d99647" CreationDate="2020-05-26T09:43:23.287" UserId="13095" Text="First, [here is a link](https://graphicdesign.stackexchange.com/questions/21204/why-do-jpeg-files-blur-red-more-than-other-colors) to a related topic of the graphic design stack exchange site. &#xD;&#xA;&#xD;&#xA;Even though the discussion was more focussed around effects on an image with large homogeneous color areas, here are some quotes I think that are relevant for your case:&#xD;&#xA;&#xD;&#xA;&gt; JPEGs are best suited for **continuous tone** images like photographs or natural artwork; **not so well on sharp-edged** or flat-color art like lettering, simple cartoons, or line drawings&#xD;&#xA;&#xD;&#xA;&gt; JPEG is actually just a compression algorithm, not a file format. JPEG is designed to exploit certain properties of our eyes, namely, **that we are more sensitive to slow changes of brightness and color than we are to rapid changes** over a short distance&#xD;&#xA;&#xD;&#xA;&gt; Compression artifacts from **hard edges** are proportional to the contrast of the edges&#xD;&#xA;&#xD;&#xA;&gt; This loss of data is most often noticeable where colors transition from one field of solid color to another field of solid color. **There's no direct issue with any particular color specifically.** It is more about large areas of similar colors.&#xD;&#xA;&#xD;&#xA;Also [Wikipedia says](https://en.wikipedia.org/wiki/JPEG) in the articles &quot;JPEG compression&quot; section:&#xD;&#xA;&#xD;&#xA;&gt;  A perceptual model based loosely on the human psychovisual system discards high-frequency information, i.e. **sharp transitions in intensity**, and color hue.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Building upon these quotes I conclude, that the compression artifacts do not depend on the color, as you already read in other sources. However, JPEGs are obviously not suited for high contrasts and sharp edges.&#xD;&#xA;&#xD;&#xA;Now when I look at your pictures, the rose blossoms and the red cake have complex/rough surfaces that cast a lot of shadows. So they have hard edges in their intensity/brightness and you can expect some artifacts there. Most of the other parts of those images don't have such a high density of sharp edges, this why you might think that red is particularly affected by the compression. The fact that the high contrast and brightness of the red attracts your eye's attention increases this impression. But if you look at other sharp edges, for example, the chocolate on top of the second cake or the yellow paper that is wrapped around the roses in the first picture, you can also see those compression artifacts. The lower density of sharp edges and the duller colors just don't make them so obvious.&#xD;&#xA;&#xD;&#xA;&gt; Can we do anything while photoshoot or post editing to fix these issues?&#xD;&#xA;&#xD;&#xA;If you have the option, the best thing would be to use an image format with loss-free compression -&gt; PNG. &#xD;&#xA;&#xD;&#xA;If this is not an option, the only thing I can come up with is avoiding high contrasts in your motives. Also, maybe you can use some photoshop filters to soften the hard edges a little bit before you compress the image. This will also reduce the image quality, but maybe it will give more acceptable results after compression (no guarantees here - might be worse).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28419" PostHistoryTypeId="2" PostId="9887" RevisionGUID="38875a43-515a-42a5-8c0d-00098aa7d6d4" CreationDate="2020-05-26T14:57:56.167" UserId="13449" Text="I have managed to greatly minimize draw calls on my recent project, but as I'm adding more shaders, I see that I have to switch more times and that is causing a lot of draw calls. What is the best practice for managing multiple (dozens) of shaders in a scene with many materials?&#xD;&#xA;&#xD;&#xA;I read that it's best to combine them together and you have a shader variable &quot;mode&quot; that you switch upon inside the shader, to end up with the specific branch of code in the shader that is to handle the fragment.&#xD;&#xA;&#xD;&#xA;Since shaders do have alot of parameters populated from the model material/mesh and sent down to the fragment shader, I fear that unifying the shaders and passing too many parameters in the VBO each frame/vertex/fragment, would be really bad for performance. I target mobile/tablet devices with my product so this is important, I understand that this is less of a concern with desktop GPUs. I see modern engines like unity and unreal allowing full flexibility on adding shaders &amp; materials at-will and their scenes render perfectly - how do they do that without increasing their shader switching and draw calls?&#xD;&#xA;&#xD;&#xA;So how many parameters are too much? And what is the best recomendation to manage multiple shaders in a drawing a scene. I understand and have allready applied grouping and rendering each material at once to minimize shader switching, but that has its limitations if there are dozens of shaders.&#xD;&#xA;&#xD;&#xA;Is there a technique or capability I'm missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28420" PostHistoryTypeId="1" PostId="9887" RevisionGUID="38875a43-515a-42a5-8c0d-00098aa7d6d4" CreationDate="2020-05-26T14:57:56.167" UserId="13449" Text="Best practice for managing many shaders and merging multiple shaders into one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28421" PostHistoryTypeId="3" PostId="9887" RevisionGUID="38875a43-515a-42a5-8c0d-00098aa7d6d4" CreationDate="2020-05-26T14:57:56.167" UserId="13449" Text="|opengl|performance|opengl-es|mobile|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28422" PostHistoryTypeId="2" PostId="9888" RevisionGUID="5997469d-1e85-4f18-b50f-28e88e852f4d" CreationDate="2020-05-26T19:36:46.593" UserId="13337" Text="I am writing a forward monte carlo path tracer with the added feature of specular refractions for transparent materials, I have managed to come this far but something is not quite right and I am having a hard time figuring out what. I have looked at the [following guide](https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel) and I make sure to invert the normal, switch the refractive indices etc depending on whether we are entering a material with a lower or higher refractive index. It seems like the reflection part when I get total internal reflection works great but the problem is the refraction direction I think but I don't see the problem with it. I am using a russian roulette approach to choose either reflection or refraction and the variable p is the pdf.&#xD;&#xA;&#xD;&#xA;This is what I achieve right now with Transparency = 1.0f, refractive index = 1.5f:&#xD;&#xA;&#xD;&#xA;![Refraction](https://i.stack.imgur.com/tDOeN.jpg)&#xD;&#xA;&#xD;&#xA;My code for calculating the sample direction looks like this:&#xD;&#xA;        &#xD;&#xA;    vec3 BlinnPhongGlass::sample_wi(vec3 &amp; wi, const vec3 &amp; wo, vec3 &amp; n, float &amp; p) {&#xD;&#xA;        vec3 tangent = normalize(perpendicular(n));&#xD;&#xA;        vec3 bitangent = normalize(cross(tangent, n));&#xD;&#xA;        float phi = 2.0f * M_PI * randf();&#xD;&#xA;        float cos_theta = pow(randf(), 1.0f / (shininess + 1));&#xD;&#xA;        float sin_theta = sqrt(max(0.0f, 1.0f - cos_theta * cos_theta));&#xD;&#xA;        vec3 wh = normalize(sin_theta * cos(phi) * tangent + sin_theta * sin(phi) * bitangent + cos_theta * n);&#xD;&#xA;&#xD;&#xA;        if (randf() &lt; 0.5f) {&#xD;&#xA;            // Sample a direction based on the Microfacet brdf&#xD;&#xA;            // PDF for wh&#xD;&#xA;            p = (shininess + 1.0f) * pow(dot(n, wh), shininess) / (2.0f * M_PI);&#xD;&#xA;&#xD;&#xA;            // Reflect wo around wh to get wi&#xD;&#xA;            wi = -(wo - (2.0f * dot(wo, wh) * wh));&#xD;&#xA;&#xD;&#xA;            // PDF for wi&#xD;&#xA;            p = p / (4.0f * dot(wo, wh));&#xD;&#xA;            p = p * 0.5f;&#xD;&#xA;&#xD;&#xA;            return reflection_brdf(wi, wo, n);&#xD;&#xA;        } else {&#xD;&#xA;            p = 1.0f;&#xD;&#xA;            p = p * 0.5f;&#xD;&#xA;&#xD;&#xA;            float no = 1.5f; // Glass&#xD;&#xA;            float ni = 1.0f; // Air&#xD;&#xA;&#xD;&#xA;            bool outside = dot(wo, n) &lt; 0;&#xD;&#xA;            float etaI = outside ? ni : no; // Index of medium we are currently in&#xD;&#xA;            float etaT = outside ? no : ni; // Index of medium we are about to enter&#xD;&#xA;            float eta = etaI / etaT;&#xD;&#xA;&#xD;&#xA;            // Compute wi using Snell's law&#xD;&#xA;            float cosThetaI = outside ? -dot(n, wo) : dot(n, wo);&#xD;&#xA;            float sin2ThetaI = max(0.0f, 1.0f - cosThetaI * cosThetaI);&#xD;&#xA;            float sin2ThetaT = eta * eta * sin2ThetaI;&#xD;&#xA;&#xD;&#xA;            // Total internal reflection -&gt; reflect instead&#xD;&#xA;            if (sin2ThetaT &gt;= 1) {&#xD;&#xA;                wi = -(wo - (2.0f * dot(wo, wh) * wh));&#xD;&#xA;                return reflection_brdf(wi, wo, n);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            n = outside ? n : -n; // Invert normal when exiting&#xD;&#xA;&#xD;&#xA;            float cosThetaT = sqrt(1.0f - sin2ThetaT);&#xD;&#xA;          &#xD;&#xA;            wi = normalize(eta * -wo + (eta * cosThetaI - cosThetaT) * n);&#xD;&#xA;&#xD;&#xA;            vec3 brdf = vec3(transparency) / dot(wo, n);&#xD;&#xA;&#xD;&#xA;            return brdf;&#xD;&#xA;            // We need to attenuate the refracted brdf with (1 - F)&#xD;&#xA;            //const float fresnel_term = R0 + (1.0f - R0) * pow(1.0f - abs(dot(wh, wi)), 5.0f);&#xD;&#xA;            //return (1 - fresnel_term) * brdf;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28423" PostHistoryTypeId="1" PostId="9888" RevisionGUID="5997469d-1e85-4f18-b50f-28e88e852f4d" CreationDate="2020-05-26T19:36:46.593" UserId="13337" Text="Implementing monte carlo path traced refractions" ContentLicense="CC BY-SA 4.0" />
  <row Id="28424" PostHistoryTypeId="3" PostId="9888" RevisionGUID="5997469d-1e85-4f18-b50f-28e88e852f4d" CreationDate="2020-05-26T19:36:46.593" UserId="13337" Text="|raytracing|3d|pathtracing|monte-carlo|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28425" PostHistoryTypeId="6" PostId="9887" RevisionGUID="ae7b2348-9108-4729-a498-95f936c6d13c" CreationDate="2020-05-26T21:45:18.553" UserId="2654" Comment="edited tags" Text="|performance|opengl-es|mobile|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28426" PostHistoryTypeId="2" PostId="9889" RevisionGUID="4eb25ee0-9777-47aa-bc4c-d5b612ceebf4" CreationDate="2020-05-27T02:08:52.480" UserId="8487" Text="I'm making a raytracer and want to print debug arrows&#xD;&#xA;&#xD;&#xA;Blender example:  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Old version of 3d max:  &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;How do I do the same having camera forward, up and right vector?&#xD;&#xA;I think I need some kind of matrix transformation? Can it be done without using matrices?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/z2hGH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5lRWz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28427" PostHistoryTypeId="1" PostId="9889" RevisionGUID="4eb25ee0-9777-47aa-bc4c-d5b612ceebf4" CreationDate="2020-05-27T02:08:52.480" UserId="8487" Text="How to transform x-y-z red-green-blue arrows and draw them on 2D screen?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28428" PostHistoryTypeId="3" PostId="9889" RevisionGUID="4eb25ee0-9777-47aa-bc4c-d5b612ceebf4" CreationDate="2020-05-27T02:08:52.480" UserId="8487" Text="|3d|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28429" PostHistoryTypeId="2" PostId="9890" RevisionGUID="e3c5a1cc-14f5-4ea8-a288-69172348459d" CreationDate="2020-05-27T04:51:32.297" UserId="3073" Text="One issue is &quot;chroma subsampling&quot;. The image data of a JPEG is not stored in packed RGB but YCbCr as 3 seperate planes. The Cr and Cb channels contain colour information and the Y channel is luminance. In JPEG it is common to use a lower resolution Cr/Cb channel, typically at half the resolution of the Y channel, this is know as 422 Chroma subsampling (another variant is 420 where only the horizontal resolution is halved).&#xD;&#xA;&#xD;&#xA;What you can do is select 444 Chroma subsampling, if possible, which will mean no down-scaling of the Cr/Cb channels. &#xD;&#xA;&#xD;&#xA;In Gimp you can select the subsampling type in &quot;advanced options&quot; when exporting JPEG files. This is independent of the quality setting slider." ContentLicense="CC BY-SA 4.0" />
  <row Id="28430" PostHistoryTypeId="5" PostId="9890" RevisionGUID="0cb8b1a8-c865-4b23-89b2-834f1bfce485" CreationDate="2020-05-27T04:57:10.770" UserId="3073" Comment="added 247 characters in body" Text="One issue is &quot;chroma subsampling&quot;. The image data of a JPEG is not stored in packed RGB but YCbCr as 3 seperate planes. The Cr and Cb channels contain colour information and the Y channel is luminance. In JPEG it is common to use a lower resolution Cr/Cb channel, typically at half the resolution of the Y channel, this is know as 422 Chroma subsampling (another variant is 420 where only the horizontal resolution is halved).&#xD;&#xA;&#xD;&#xA;What you can do is select 444 Chroma subsampling, if possible, which will mean no down-scaling of the Cr/Cb channels. &#xD;&#xA;&#xD;&#xA;In Gimp you can select the subsampling type in &quot;advanced options&quot; when exporting JPEG files. This is independent of the quality setting slider.&#xD;&#xA;&#xD;&#xA;There is a great image from wikipedia which compares the various subsampling modes side-by-side, you can see the red indicator light is the object most effected by it &gt; &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yswEk.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28431" PostHistoryTypeId="5" PostId="9890" RevisionGUID="c218ceab-e46d-4538-b360-a4bb26c214d3" CreationDate="2020-05-27T05:12:14.203" UserId="3073" Comment="added 114 characters in body" Text="One issue is &quot;chroma subsampling&quot;. The image data of a JPEG is not stored in packed RGB but YCbCr as 3 seperate planes. The Cr and Cb channels contain colour information and the Y channel is luminance. In JPEG it is common to use a lower resolution Cr/Cb channel, typically at half the resolution of the Y channel, this is know as 422 Chroma subsampling (another variant is 420 where only the horizontal resolution is halved).&#xD;&#xA;&#xD;&#xA;What you can do is select 444 Chroma subsampling, if possible, which will mean no down-scaling of the Cr/Cb channels. &#xD;&#xA;&#xD;&#xA;In Gimp you can select the subsampling type in &quot;advanced options&quot; when exporting JPEG files. This is independent of the quality setting slider.&#xD;&#xA;&#xD;&#xA;There is a great image from wikipedia which compares the various subsampling modes side-by-side, you can see the red decal in the centre is most affected by it as that channel has high contrast for certain features - This should be similar to the Red-&gt;White edges in your example images &gt; &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yswEk.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28432" PostHistoryTypeId="5" PostId="9890" RevisionGUID="016f4d57-a8cd-4ab3-9415-539b05274c74" CreationDate="2020-05-27T05:41:49.970" UserId="3073" Comment="deleted 27 characters in body" Text="One issue is &quot;chroma subsampling&quot;. The image data of a JPEG is not stored in packed RGB but YCbCr as 3 seperate planes. The Cr and Cb channels contain colour information and the Y channel is luminance. In JPEG it is common to use a lower resolution Cr/Cb channel, typically at half the resolution of the Y channel, this is know as 422 Chroma subsampling (another variant is 420 where only the horizontal resolution is halved).&#xD;&#xA;&#xD;&#xA;What you can do is select 444 Chroma subsampling, if possible, which will mean no down-scaling of the Cr/Cb channels. &#xD;&#xA;&#xD;&#xA;In Gimp you can select the subsampling type in &quot;advanced options&quot; when exporting JPEG files. This is independent of the quality setting slider.&#xD;&#xA;&#xD;&#xA;There is a great image from wikipedia which compares the various subsampling modes side-by-side with a visualisation of one of the chroma channels, you can see the red decal in the centre is most affected by downscaling as that channel has high contrast edges&#xD;&#xA;&#xD;&#xA;[![Chroma example - from Wikipedia][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Wikipedia article for Chroma Subsampling][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yswEk.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Chroma_subsampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="28433" PostHistoryTypeId="5" PostId="9885" RevisionGUID="fc561a3c-ae5b-48f8-ba8f-1f8533d2799c" CreationDate="2020-05-27T06:55:37.723" UserId="13095" Comment="Fix some grammar and spelling" Text="I have an e-commerce website dealing with flowers and cakes. We get our photoshoot done inhouse and also the post-shoot editing of images. While we upload them on the website all images go through the same image compression algorithm. But if we compare all images, then we find product images having red color in them loosing out most of its details only in the areas with red color. &#xD;&#xA;&#xD;&#xA;I have attached an image below for your reference, here the left-hand side image is at 80% quality and the right side has no compression in place. If you compare all these images, then you will see that the red-colored areas of the images lose the most details, at least visually. &#xD;&#xA;&#xD;&#xA;I have read about jpeg compression but it says that color doesn't make any difference, but it is not the case here. &#xD;&#xA;&#xD;&#xA;Can we do anything during photoshoot or post-editing to fix these issues?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zsb3a.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28434" PostHistoryTypeId="4" PostId="9885" RevisionGUID="fc561a3c-ae5b-48f8-ba8f-1f8533d2799c" CreationDate="2020-05-27T06:55:37.723" UserId="13095" Comment="Fix some grammar and spelling" Text="Why does red color lose the most details during jpeg compression" ContentLicense="CC BY-SA 4.0" />
  <row Id="28435" PostHistoryTypeId="24" PostId="9885" RevisionGUID="fc561a3c-ae5b-48f8-ba8f-1f8533d2799c" CreationDate="2020-05-27T06:55:37.723" Comment="Proposed by 13095 approved by -1 edit id of 526" ContentLicense="CC BY-SA 4.0" />
  <row Id="28436" PostHistoryTypeId="4" PostId="9885" RevisionGUID="583ae41a-4632-41dd-8d35-bde36bf2f36b" CreationDate="2020-05-27T06:55:37.723" UserId="209" Comment="Fix some grammar and spelling" Text="Why does red color channel lose the most details during jpeg compression" ContentLicense="CC BY-SA 4.0" />
  <row Id="28437" PostHistoryTypeId="5" PostId="7897" RevisionGUID="d5f30e35-fcf4-42e2-bbd4-90ef93d43669" CreationDate="2020-05-27T07:11:53.413" UserId="3363" Comment="Updated link to use https, other small edits" Text="Where should the ray origin be put in the perspective camera ray tracing?&#xD;&#xA;&#xD;&#xA;The following gives a picture of the ray tracing in the perspective camera setting:&#xD;&#xA;https://www.cs.cornell.edu/courses/cs4620/2011fa/lectures/06raytracingWeb.pdf&#xD;&#xA;&#xD;&#xA;and says that the $e$ is the ray origin, which is the same for all rays. &#xD;&#xA;&#xD;&#xA;However, I don't understand how $e$ is supposed to be selected.&#xD;&#xA;Can it be the zero vector? Or perhaps it is supposed to be the camera center?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28438" PostHistoryTypeId="24" PostId="7897" RevisionGUID="d5f30e35-fcf4-42e2-bbd4-90ef93d43669" CreationDate="2020-05-27T07:11:53.413" Comment="Proposed by 3363 approved by -1 edit id of 525" ContentLicense="CC BY-SA 4.0" />
  <row Id="28439" PostHistoryTypeId="5" PostId="7897" RevisionGUID="3355fd25-a380-479a-be43-4eef7df19f3d" CreationDate="2020-05-27T07:11:53.413" UserId="209" Comment="Updated link to use https, other small edits" Text="Where should the ray origin be put in perspective camera ray tracing?&#xD;&#xA;&#xD;&#xA;The following gives a picture of the ray tracing in the perspective camera setting:&#xD;&#xA;https://www.cs.cornell.edu/courses/cs4620/2011fa/lectures/06raytracingWeb.pdf&#xD;&#xA;&#xD;&#xA;and says that the $e$ is the ray origin, which is the same for all rays. &#xD;&#xA;&#xD;&#xA;However, I don't understand how $e$ is supposed to be selected.&#xD;&#xA;Can it be the zero vector? Or perhaps it is supposed to be the camera center?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28440" PostHistoryTypeId="4" PostId="9885" RevisionGUID="fe9246b3-ff34-4acc-bfc5-6a077e475807" CreationDate="2020-05-27T07:13:37.147" UserId="209" Comment="Missing &quot;definite article&quot; in the title" Text="Why does the red color channel lose the most details during jpeg compression" ContentLicense="CC BY-SA 4.0" />
  <row Id="28441" PostHistoryTypeId="2" PostId="9891" RevisionGUID="a890bbec-dd86-4ad7-b153-4a61739dd2d8" CreationDate="2020-05-27T13:06:57.127" UserId="13455" Text="I know this is old but game engines/graphics cards run in &quot;triangles&quot; because that is how they calculate mesh. They do not calculate mesh in quads. That was something created to allow all of the features mentioned above to happen in 3D modeling. All quads are two triangles in the &quot;engine&quot;. They are propagated that way to allow you to work with them efficiently. Essentially, all engines triangulate in the final process. The first answer here explains it correctly: https://gamedev.stackexchange.com/questions/66312/quads-vs-triangles/66314#66314" ContentLicense="CC BY-SA 4.0" />
  <row Id="28442" PostHistoryTypeId="4" PostId="9888" RevisionGUID="a7a3927c-0678-43b7-a41f-1e9a16b15f3e" CreationDate="2020-05-27T18:03:25.460" UserId="13337" Comment="edited title" Text="Implementing monte carlo path traced refractions problem" ContentLicense="CC BY-SA 4.0" />
  <row Id="28443" PostHistoryTypeId="2" PostId="9892" RevisionGUID="f183975b-2441-47df-bc8f-9b983daf77a9" CreationDate="2020-05-28T08:23:11.943" UserId="13457" Text="So i've a made a texture. I've saved the RGB one with BC7 compression, then added alpha channel[specular map] with varying levels of grayscale, and saved the file again as RGBA with BC7 compression. The resulting file has the same size as the one without alpha, yet it contain additional information -alpha channel. How it is possible? You can't have cake and eat cake as i understand, so are there any compromises made to ensure same size? &#xD;&#xA;&#xD;&#xA;Im using photoshop with intel DDS plugin. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28444" PostHistoryTypeId="1" PostId="9892" RevisionGUID="f183975b-2441-47df-bc8f-9b983daf77a9" CreationDate="2020-05-28T08:23:11.943" UserId="13457" Text="BC7 texture with alpha has the same size as BC7 without alpha" ContentLicense="CC BY-SA 4.0" />
  <row Id="28445" PostHistoryTypeId="3" PostId="9892" RevisionGUID="f183975b-2441-47df-bc8f-9b983daf77a9" CreationDate="2020-05-28T08:23:11.943" UserId="13457" Text="|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28446" PostHistoryTypeId="5" PostId="9879" RevisionGUID="9c63a2d8-21ac-48dd-916b-31c8e5ed3199" CreationDate="2020-05-28T10:27:10.550" UserId="13095" Comment="Put code into correct environment and apply some minor corrections  " Text="well, if anyone is stumbling across this and needs to know what solved it for me: We can bind a compute buffer to global shader memory if we just know what exactly we need to do&#xD;&#xA;&#xD;&#xA;within the Compute shader the RWstructuredBuffer is declared as (without the &quot;\&quot; infront of float):&#xD;&#xA;&#xD;&#xA;~~~ &#xD;&#xA;uniform RWStructuredBuffer&lt;\float3&gt; buffer : register(u1);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;(not certain whether `register(u1)` is really needed&#xD;&#xA;&#xD;&#xA;within the vert/frag shader the buffer is defined as:&#xD;&#xA;&#xD;&#xA;~~~&#xD;&#xA;uniform StructuredBuffer&lt;\float3&gt; buffer;	&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In a c# script before kernel dispatch, I assign the buffer via&#xD;&#xA;&#xD;&#xA;~~~ c#&#xD;&#xA;buffer = new ComputeBuffer(size, sizeof(float)*3,ComputeBufferType.Default);&#xD;&#xA;Shader.SetGlobalBuffer(Shader.PropertyToID(&quot;buffer&quot;), buffer);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;It took me ages to find this and it works as far as I can tell. [The article I finally stumbled over that did something similar][1]. I do not have to read the data back to cpu with buffer.GetData(container) and put it into the material manually. &#xD;&#xA;If the compute shader changes the buffer data this will be reflected in the vert/frag shader immediately. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.tzaeru.com/site/compute-shader-basics-with-unity/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28447" PostHistoryTypeId="24" PostId="9879" RevisionGUID="9c63a2d8-21ac-48dd-916b-31c8e5ed3199" CreationDate="2020-05-28T10:27:10.550" Comment="Proposed by 13095 approved by -1 edit id of 527" ContentLicense="CC BY-SA 4.0" />
  <row Id="28448" PostHistoryTypeId="5" PostId="9879" RevisionGUID="aacee7e3-5382-49ed-b03a-10cf16082db7" CreationDate="2020-05-28T10:27:10.550" UserId="11386" Comment="Put code into correct environment and apply some minor corrections  " Text="well, if anyone is stumbling across this and needs to know what solved it for me: We can bind a compute buffer to global shader memory if we just know what exactly we need to do&#xD;&#xA;&#xD;&#xA;within the Compute shader the RWstructuredBuffer is declared as (without the &quot;\&quot; infront of float):&#xD;&#xA;&#xD;&#xA;~~~ &#xD;&#xA;uniform RWStructuredBuffer&lt;\float3&gt; buffer : register(u1);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;(not certain whether `register(u1)` is really needed&#xD;&#xA;&#xD;&#xA;within the vert/frag shader the buffer is defined as:&#xD;&#xA;&#xD;&#xA;~~~&#xD;&#xA;uniform StructuredBuffer&lt;\float3&gt; buffer;	&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In a c# script before the first kernel dispatch (we only need to assign this buffer once), I assign the buffer via&#xD;&#xA;&#xD;&#xA;~~~ c#&#xD;&#xA;buffer = new ComputeBuffer(size, sizeof(float)*3,ComputeBufferType.Default);&#xD;&#xA;Shader.SetGlobalBuffer(Shader.PropertyToID(&quot;buffer&quot;), buffer);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;It took me ages to find this and it works as far as I can tell. [The article I finally stumbled over that did something similar][1]. I do not have to read the data back to cpu with buffer.GetData(container) and put it into the material manually. &#xD;&#xA;If the compute shader changes the buffer data this will be reflected in the vert/frag shader immediately. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.tzaeru.com/site/compute-shader-basics-with-unity/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28449" PostHistoryTypeId="2" PostId="9893" RevisionGUID="d12e520d-b998-4f51-a6da-bf62eb7f825a" CreationDate="2020-05-28T10:47:31.990" UserId="13095" Text="Here is an article about the BCn format: [click me](http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/). It is written by Nathan Reed, who is quite active on this site. So he will probably pass by and might answer your question with more details, even though I think the article will explain everything you need to know.&#xD;&#xA;&#xD;&#xA;The most relevant part for your question seems to be this section from the article:&#xD;&#xA;&#xD;&#xA;&gt; BC stands for “block compression”, and the BCn formats **all operate in terms of 4×4 blocks of pixels.** All images are sliced up into these small blocks, and each block is self-contained—the data to decode it is all in one contiguous chunk in memory. Moreover, **the size of each compressed block is fixed—either 8 or 16 bytes**, depending on which BCn format is being used. This represents a 4:1 or 8:1 compression ratio, if the source image is in 8-bit RGBA format.&#xD;&#xA;&#xD;&#xA;So as long as your pixel count does not change, the size of the texture does not change either. However, the more channels you use (only 3 and 4 are supported by BC7 according to [the Microsoft documentation](https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format)), the less information you can store per color channel. So the bits needed for the alpha channel are taken away from the other channels (RGB). This means, that you lose more information per channel due to compression when using RGBA instead of RGB. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28450" PostHistoryTypeId="5" PostId="9893" RevisionGUID="66dcbb91-3b22-4915-b18b-392f2005c153" CreationDate="2020-05-28T10:56:06.910" UserId="13095" Comment="deleted 88 characters in body" Text="Here is an article about the BCn format: [click me](http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/). It is written by Nathan Reed, who is quite active on this site. So he will probably pass by and might answer your question with more details, even though I think the article will explain everything you need to know.&#xD;&#xA;&#xD;&#xA;The most relevant part for your question seems to be this section from the article:&#xD;&#xA;&#xD;&#xA;&gt; BC stands for “block compression”, and the BCn formats **all operate in terms of 4×4 blocks of pixels.** All images are sliced up into these small blocks, and each block is self-contained—the data to decode it is all in one contiguous chunk in memory. Moreover, **the size of each compressed block is fixed—either 8 or 16 bytes**, depending on which BCn format is being used. This represents a 4:1 or 8:1 compression ratio, if the source image is in 8-bit RGBA format.&#xD;&#xA;&#xD;&#xA;So as long as your pixel count does not change, the size of the texture does not change either. However, the more channels you use (only 3 and 4 are supported by BC7 according to [the Microsoft documentation](https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format)), the less information you can store per color channel in a block. This means, that you lose more information due to compression when using RGBA instead of RGB. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28451" PostHistoryTypeId="2" PostId="9894" RevisionGUID="17a47a44-9670-4c6b-9141-dfa3f20e6a8b" CreationDate="2020-05-28T11:50:09.620" UserId="13459" Text="Most of the existing open-source libraries such as OpenCV, Tensorflow, and Pytorch use **Google Test**. I would like to know about strong alternative testing frameworks that thrive under a similar workload. Suggestions from areas such as real-time graphics and physics engines are absolutely welcome!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28452" PostHistoryTypeId="1" PostId="9894" RevisionGUID="17a47a44-9670-4c6b-9141-dfa3f20e6a8b" CreationDate="2020-05-28T11:50:09.620" UserId="13459" Text="What modern C++ Unit Testing Framework do you use for highly parallel image, 3D and higher dimensional matrix processing workloads?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28453" PostHistoryTypeId="3" PostId="9894" RevisionGUID="17a47a44-9670-4c6b-9141-dfa3f20e6a8b" CreationDate="2020-05-28T11:50:09.620" UserId="13459" Text="|3d|image-processing|c++|gpu|real-time|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28454" PostHistoryTypeId="6" PostId="5447" RevisionGUID="a04ac075-e417-42c7-ab3e-ece19db28dbe" CreationDate="2020-05-28T12:31:41.153" UserId="7008" Comment="edited tags" Text="|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28456" PostHistoryTypeId="2" PostId="9895" RevisionGUID="0c0e9604-c59c-4f8a-96ce-1f9761294b87" CreationDate="2020-05-28T17:50:55.903" UserId="2654" Text="BC7 always effectively encodes 4 channels. That's part of the nature of the format. Turning on alpha means that the compressor will read and use the alpha value in your source image, but that's all.&#xD;&#xA;&#xD;&#xA;All BC7 compressed images of a given dimension have the same size, since BC7 compresses each 4x4 group of texels into 128-bits. But that doesn't mean they have the same *quality*.&#xD;&#xA;&#xD;&#xA;BC7 is an adaptive encoding. The block stores within its encoding how many channels it actually compresses and the way that they correlate with one another. The [specifics are complex][1], but the general upside is that the compressor figures out on a per-block basis what manner of compression works best for a particular block. If the compressor can look at a block and see that the alpha for all texels is 1.0, then it can spend more bits of the 128 bits on the colors and fewer on the alpha.&#xD;&#xA;&#xD;&#xA;As such, a texture &quot;without alpha&quot; is exactly like a texture with alpha where every texel has an alpha of 1. These blocks will spend the majority of their bits on the non-alpha parts of the texels, only wasting a few bits on a &quot;mode&quot; field that lets the decompressor know that the alpha is a constant 1.0.&#xD;&#xA;&#xD;&#xA;This also means that, if your texture has a varying alpha, but parts of it have a constant alpha, BC7 can encode these constant alpha areas with fewer bits, so that more bits can be spent on improved color encoding.&#xD;&#xA;&#xD;&#xA;So you shouldn't feel that there is a problem because the two compression switches came out with the same number of bytes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#bptc_bc7" ContentLicense="CC BY-SA 4.0" />
  <row Id="28457" PostHistoryTypeId="5" PostId="9895" RevisionGUID="0967db75-d6e7-47b3-abc7-693f3dd8b5e4" CreationDate="2020-05-28T17:55:56.033" UserId="2654" Comment="added 9 characters in body" Text="BC7 always effectively encodes 4 channels. That's part of the nature of the format. Turning on alpha means that the compressor will read and use the alpha value in your source image, but that's all.&#xD;&#xA;&#xD;&#xA;All BC7 compressed images of a given dimension have the same size, since BC7 compresses each 4x4 group of texels into 128-bits (indeed, this is true of every BC* format). But that doesn't mean they have the same *quality*.&#xD;&#xA;&#xD;&#xA;BC7 is an adaptive encoding. Each block stores within its encoding how many channels that block actually compresses and the way that they correlate with one another. The [specifics are complex][1], but the general upside is that the compressor figures out on a per-block basis what manner of compression works best for a particular block. If the compressor can look at a block and see that the alpha for all texels is 1.0, then it can spend more bits of the 128 bits on the colors and fewer on the alpha.&#xD;&#xA;&#xD;&#xA;As such, a texture &quot;without alpha&quot; is exactly like a texture with alpha where every texel has an alpha of 1. These blocks will spend the majority of their bits on the non-alpha parts of the texels, only wasting a few bits on a &quot;mode&quot; field that lets the decompressor know that the alpha is a constant 1.0.&#xD;&#xA;&#xD;&#xA;This also means that, if your texture has a varying alpha, but parts of it have a constant alpha, BC7 can encode these constant alpha areas with fewer bits, so that more bits can be spent on improved color encoding.&#xD;&#xA;&#xD;&#xA;So you shouldn't feel that there is a problem because the two compression switches came out with the same number of bytes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#bptc_bc7" ContentLicense="CC BY-SA 4.0" />
  <row Id="28458" PostHistoryTypeId="5" PostId="9895" RevisionGUID="16cc05e8-d10d-4f65-994a-6ddae0bbf199" CreationDate="2020-05-28T20:33:39.973" UserId="2654" Comment="added 52 characters in body" Text="BC7 always effectively encodes 4 channels. That's part of the nature of the format. Turning on alpha means that the compressor will read and use the alpha value in your source image, but that's all.&#xD;&#xA;&#xD;&#xA;All BC7 compressed images of a given dimension have the same size, since BC7 compresses each 4x4 group of texels into 128-bits (indeed, this is true of every BC* format). But that doesn't mean they have the same *quality*.&#xD;&#xA;&#xD;&#xA;BC7 is an adaptive encoding format. While each block has a fixed size (both spatially and bit-wise), each block stores how many channels that block actually compresses and the way that they correlate with one another. The [specifics are complex][1], but the general upside is that the compressor figures out on a per-block basis what manner of compression works best for a particular block. If the compressor can look at a block and see that the alpha for all texels is 1.0, then it can spend more bits of the 128 bits on the colors and fewer on the alpha.&#xD;&#xA;&#xD;&#xA;As such, a texture &quot;without alpha&quot; is exactly like a texture with alpha where every texel has an alpha of 1. These blocks will spend the majority of their bits on the non-alpha parts of the texels, only wasting a few bits on a &quot;mode&quot; field that lets the decompressor know that the alpha is a constant 1.0.&#xD;&#xA;&#xD;&#xA;This also means that, if your texture has a varying alpha, but parts of it have a constant alpha, BC7 can encode these constant alpha areas with fewer bits, so that more bits can be spent on improved color encoding.&#xD;&#xA;&#xD;&#xA;So you shouldn't feel that there is a problem because the two compression switches came out with the same number of bytes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#bptc_bc7" ContentLicense="CC BY-SA 4.0" />
  <row Id="28459" PostHistoryTypeId="2" PostId="9896" RevisionGUID="e1d580c8-d043-416b-8e28-e9cc0ce9a6d4" CreationDate="2020-05-29T03:06:34.630" UserId="13466" Text="I'm new to the graphics area, and when comes to the light part, the concept vertex normal confused me a lot.&#xD;&#xA;&#xD;&#xA;First, I cannot imagine how could a vertex have a normal, and second, when calculate the reflection lights, shouldn't I use the normal of a face?&#xD;&#xA;&#xD;&#xA;So, can some one help to explain what a vertex normal is and what it used for, and how is it compared with a face normal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28460" PostHistoryTypeId="1" PostId="9896" RevisionGUID="e1d580c8-d043-416b-8e28-e9cc0ce9a6d4" CreationDate="2020-05-29T03:06:34.630" UserId="13466" Text="What is a vertex normal used for?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28461" PostHistoryTypeId="3" PostId="9896" RevisionGUID="e1d580c8-d043-416b-8e28-e9cc0ce9a6d4" CreationDate="2020-05-29T03:06:34.630" UserId="13466" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28462" PostHistoryTypeId="2" PostId="9897" RevisionGUID="64b28e00-5d23-4cbd-bde3-8860a8707e5a" CreationDate="2020-05-29T07:00:02.767" UserId="13095" Text="&gt; First, I cannot imagine how could a vertex have a normal,...&#xD;&#xA;&#xD;&#xA;Welcome to the exciting field of computer graphics. The first thing that might lead to your confusion is to think about a vertex too much as a point in space in a geometrical way. ---&gt; A 3d point can't have normal since it does not have a face. &#xD;&#xA;But the way you should think about it is more like a checkpoint that contains all information of an arbitrary 3d curve at a certain position. &#xD;&#xA;&#xD;&#xA;&gt; ... and second, when calculate the reflection lights, shouldn't I use the normal of a face? &#xD;&#xA;&#xD;&#xA;What happens if you want to render a perfect sphere that can only be represented by a limited set of triangles? It will look like the one in the middle in [this question](https://blender.stackexchange.com/questions/13554/applied-boolean-modifier-leaving-shading-artifacts-with-flat-shading?rq=1). The flat surfaces are clearly visible, but that is not what you want. You can improve this by drastically increasing the triangle count, but that comes with a huge performance impact and memory footprint. &#xD;&#xA;&#xD;&#xA;The solution here is using **vertex normals**. To understand, why this is a solution, you need to know a little bit about how the [render pipeline](https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview) works. The most important parts for your understanding are vertex processing, rasterization, and the pixel/fragment shader.&#xD;&#xA;&#xD;&#xA;Vertex processing is the first programable (in modern APIs) step in the pipeline and is mostly used to reposition your vertices so that your 3d world is displayed correctly on a 2d display. Therefore you apply some mathematical corrections (perspective for example) to your vertex positions. You can do a lot more, but that is not important here. What is important is, that the vertex processor does not know to which triangle a vertex belongs. He sees it in total isolation. Therefore, he can not calculate any face normals, so you have to provide it in some way, for example by adding it as vertex attribute.&#xD;&#xA;&#xD;&#xA;After some optional pipeline steps, you get to the rasterizer. Its job is to turn your triangles into actual pixels on your screen. The information he gets are three vertices that form a triangle. Now here is, where the magic happens. For each pixel, he interpolates the properties of the three vertices and passes them to the final step, the pixel shader (also programable in modern APIs). So if your vertices had normals, you will have an interpolated normal for each pixel of your triangle. This enables you to render perfectly smooth surfaces (or at least fake them) since you can perform the lighting calculation for each pixel with individual normals in the pixel shader.&#xD;&#xA;&#xD;&#xA;This is why you need vertex normals. The vertices are checkpoints that hold information about your surfaces at specific points. You connect these points to triangles. The information in between is interpolated by the rasterizer. So you essentially describe a whole triangle-shaped field of normals with its three edge values. &#xD;&#xA;&#xD;&#xA;However, even if you want to render flat surfaces, you might still need vertex normals. As I said before, the vertex processor does not know anything about triangles, so you can not calculate any surface normals there. So you have to pass them in somehow. There are other ways, but attaching the normals to the vertices is usually the best and easiest solution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Additional note:** You do not necessarily need to perform the lighting calculation in the pixel shader. You can also do this in the vertex stage. So you need vertex normals again ;). This is called Gouraud Shading and gives you a performance boost since you do not need to perform the light calculations per pixel. However, the visual quality of curved surfaces suffers from that. For flat surfaces, you should not see any differences." ContentLicense="CC BY-SA 4.0" />
  <row Id="28463" PostHistoryTypeId="2" PostId="9898" RevisionGUID="c9626a1d-d38d-4609-9ed1-e426dc9f4b55" CreationDate="2020-05-29T07:27:13.860" UserId="13467" Text="matplotlib's 3d rendering settings are not yet complete (it's meant to be a 2d renderer program). I don't think at this stage it has this option without big hacks to the code locally (i.e. done by yourself). Mathematica offers this setting naturally." ContentLicense="CC BY-SA 4.0" />
  <row Id="28464" PostHistoryTypeId="5" PostId="9896" RevisionGUID="9c7477b8-484a-42da-b88a-7afd7f4f5a2b" CreationDate="2020-05-29T08:08:38.900" UserId="13095" Comment="Fix some grammar and spelling" Text="I'm new to the graphics area, and when it comes to the light part, the concept of vertex normals confuses me a lot.&#xD;&#xA;&#xD;&#xA;First, I cannot imagine how a vertex could have a normal, and second, when calculating the reflection lights, shouldn't I use the normal of a face?&#xD;&#xA;&#xD;&#xA;So, can someone help me understand what a vertex normal is, what it is used for, and how it compares to a face normal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28465" PostHistoryTypeId="24" PostId="9896" RevisionGUID="9c7477b8-484a-42da-b88a-7afd7f4f5a2b" CreationDate="2020-05-29T08:08:38.900" Comment="Proposed by 13095 approved by 13466 edit id of 528" ContentLicense="CC BY-SA 4.0" />
  <row Id="28466" PostHistoryTypeId="52" PostId="9896" RevisionGUID="52e19224-1b6c-49f5-98e3-04dfcdb5e21c" CreationDate="2020-05-29T11:07:58.953" />
  <row Id="28468" PostHistoryTypeId="2" PostId="9899" RevisionGUID="c3952a9b-5dd4-47ad-83a8-902ed6f6843a" CreationDate="2020-05-29T11:34:38.303" UserId="13468" Text="I struggle do understand how linear interpolation works in the marching square rendering algorithm context.&#xD;&#xA;&#xD;&#xA;I created simple example in GDScript (Godot) of random floating metaballs to demonstrate the problem:&#xD;&#xA;&#xD;&#xA;    extends Node2D&#xD;&#xA;    &#xD;&#xA;    class Blob:&#xD;&#xA;    	var pos_x&#xD;&#xA;    	var pos_y&#xD;&#xA;    	var radius&#xD;&#xA;    	var velocity&#xD;&#xA;    	func _init(x, y, r, v):&#xD;&#xA;    		pos_x = x&#xD;&#xA;    		pos_y = y&#xD;&#xA;    		radius = r&#xD;&#xA;    		velocity = v&#xD;&#xA;    &#xD;&#xA;    # Declare member variables here. Examples:&#xD;&#xA;    # const a = 2&#xD;&#xA;    # var b = &quot;text&quot;&#xD;&#xA;    &#xD;&#xA;    const cell_size = 16&#xD;&#xA;    const blobs_count = 10&#xD;&#xA;    const blob_size = [20, 40]&#xD;&#xA;    const max_sum = 1&#xD;&#xA;    var screen_size&#xD;&#xA;    var blobs&#xD;&#xA;    var allowUpdate = true&#xD;&#xA;    &#xD;&#xA;    const drawMap = {&#xD;&#xA;    	0: null,&#xD;&#xA;    	1: [-0.5, 0, 0, -0.5],&#xD;&#xA;    	2: [-0.5, -1, 0, -0.5],&#xD;&#xA;    	3: [-0.5, 0, -0.5, -1],&#xD;&#xA;    	4: [-1, -0.5, -0.5, -1],&#xD;&#xA;    	5: [-1, -0.5, -0.5, 0, -0.5, -1, 0, -0.5],&#xD;&#xA;    	6: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	7: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	8: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	9: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	10: [-1, -0.5, -0.5, -1, -0.5, 0, 0, -0.5],&#xD;&#xA;    	11: [-1, -0.5, -0.5, -1],&#xD;&#xA;    	12: [-0.5, -1, -0.5, 0],&#xD;&#xA;    	13: [-0.5, -1, 0, -0.5],&#xD;&#xA;    	14: [-0.5, 0, 0, -0.5],&#xD;&#xA;    	15: null&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    const test = []&#xD;&#xA;    &#xD;&#xA;    func calcIsoSurface(x1, x2, y1, y2, r):&#xD;&#xA;    	var dx = x1 - x2&#xD;&#xA;    	var dy = y1 - y2&#xD;&#xA;    	var sd = dx*dx + dy*dy&#xD;&#xA;    	var res = r*r / sd&#xD;&#xA;    	return res&#xD;&#xA;    &#xD;&#xA;    # Called when the node enters the scene tree for the first time.&#xD;&#xA;    func _ready():&#xD;&#xA;    	screen_size = get_viewport().size&#xD;&#xA;    	blobs = Array()&#xD;&#xA;    	var rng = RandomNumberGenerator.new()&#xD;&#xA;    	var r = rng.randi_range(blob_size[0], blob_size[1])&#xD;&#xA;    	var x = rng.randi_range(r, screen_size.x - r)&#xD;&#xA;    	var y = rng.randi_range(r, screen_size.y - r)&#xD;&#xA;    	for n in range(blobs_count):&#xD;&#xA;    		blobs.push_back(&#xD;&#xA;    			Blob.new(&#xD;&#xA;    				x, &#xD;&#xA;    				y, &#xD;&#xA;    				r, &#xD;&#xA;    				Vector2(rng.randf_range(-1, 1), rng.randf_range(-1, 1))&#xD;&#xA;    			)&#xD;&#xA;    		)&#xD;&#xA;    	print(screen_size)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func formDrawIndex(x, y, sum, vertexes):&#xD;&#xA;    	var drawIndex = 0&#xD;&#xA;    	var corners = []&#xD;&#xA;    	if x &gt; 0 &amp;&amp; y &gt; 0:&#xD;&#xA;    		if sum &gt;= 1:&#xD;&#xA;    			drawIndex |= 1&#xD;&#xA;    		&#xD;&#xA;    		corners.push_back(sum)&#xD;&#xA;    		&#xD;&#xA;    		if vertexes.back() &gt;= 1:&#xD;&#xA;    			drawIndex |= 2&#xD;&#xA;    &#xD;&#xA;    		corners.push_back(vertexes.back())&#xD;&#xA;    		corners.push_back(vertexes.pop_front())&#xD;&#xA;    		&#xD;&#xA;    		if corners.back() &gt;= 1:&#xD;&#xA;    			drawIndex |= 4	&#xD;&#xA;    		if vertexes.front() &gt;= 1:&#xD;&#xA;    			drawIndex |= 8&#xD;&#xA;    		&#xD;&#xA;    		corners.push_back(vertexes.front())&#xD;&#xA;    	return 	{&quot;draw_index&quot;: drawIndex, &quot;corners&quot;: corners}	&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func exLerp(oneSum, zeroSum):&#xD;&#xA;    	if oneSum == zeroSum:&#xD;&#xA;    		return null&#xD;&#xA;    	return (1 - oneSum) / (zeroSum - oneSum)&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    func interpolateLines(lines, corners):&#xD;&#xA;    	if lines == null:&#xD;&#xA;    		return lines&#xD;&#xA;    	for i in range(0, lines.size(), 2):&#xD;&#xA;    		var x = lines[i]&#xD;&#xA;    		var y = lines[i+1]&#xD;&#xA;    		#somehow implement correct interpolation here&#xD;&#xA;    	return lines&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func drawLines(x, y, lines):&#xD;&#xA;    	if lines != null &amp;&amp; lines.size() &gt;= 4:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[0]), y + (cell_size*lines[1])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[2]), y + (cell_size*lines[3])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    					&#xD;&#xA;    	if lines != null &amp;&amp; lines.size() == 8:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[4]), y + (cell_size*lines[5])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[6]), y + (cell_size*lines[7])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    &#xD;&#xA;    # Called after update() in the _process()&#xD;&#xA;    func _draw():&#xD;&#xA;    	var vertexes = []&#xD;&#xA;    	for x in range(0, screen_size.x, cell_size):&#xD;&#xA;    		for y in range(0, screen_size.y, cell_size):&#xD;&#xA;    			var sum = 0&#xD;&#xA;    			for blob in blobs:&#xD;&#xA;    				sum += calcIsoSurface(x, blob.pos_x, y, blob.pos_y, blob.radius)&#xD;&#xA;    				#draw_circle(Vector2(blob.pos_x,blob.pos_y), blob.radius, Color.darkgray)&#xD;&#xA;    	&#xD;&#xA;    			#if sum &gt;= 1:&#xD;&#xA;    				#draw_rect(Rect2(x, y, 1, 1), Color.red)&#xD;&#xA;    			#else: 	draw_rect(Rect2(x, y, 1, 1), Color.black)&#xD;&#xA;    			&#xD;&#xA;    			var indexies = formDrawIndex(x, y, sum, vertexes)&#xD;&#xA;    			var lines = drawMap[indexies[&quot;draw_index&quot;]]&#xD;&#xA;    			lines = interpolateLines(lines, indexies[&quot;corners&quot;])			&#xD;&#xA;    			drawLines(x, y, lines)&#xD;&#xA;    					&#xD;&#xA;    			vertexes.push_back(sum)&#xD;&#xA;    			&#xD;&#xA;    		if x &gt; 0:&#xD;&#xA;    			vertexes.pop_front()&#xD;&#xA;    			&#xD;&#xA;    		&#xD;&#xA;    			&#xD;&#xA;    func _input(event):&#xD;&#xA;    	if event is InputEventMouseButton &amp;&amp; event.is_pressed():&#xD;&#xA;    		allowUpdate = !allowUpdate&#xD;&#xA;    		print(allowUpdate)&#xD;&#xA;    		&#xD;&#xA;    	&#xD;&#xA;    # Called every frame. 'delta' is the elapsed time since the previous frame.&#xD;&#xA;    func _process(delta):&#xD;&#xA;    	if !allowUpdate:		&#xD;&#xA;    		return		&#xD;&#xA;    	update()&#xD;&#xA;    &#xD;&#xA;    	for blob in blobs:&#xD;&#xA;    		blob.pos_x += blob.velocity.x&#xD;&#xA;    		blob.pos_y += blob.velocity.y&#xD;&#xA;    		if blob.pos_x &gt; screen_size.x || blob.pos_x &lt; 0:&#xD;&#xA;    			blob.velocity.x *= -1&#xD;&#xA;    		if blob.pos_y &gt; screen_size.y || blob.pos_y &lt; 0:&#xD;&#xA;    			blob.velocity.y *= -1&#xD;&#xA;&#xD;&#xA;The outcome looks something like this:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I would like to apply linear interpolation to make my meatballs smoother. This is where I stuck. The desire outcome is transform rendering of this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;To this:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I already created `interpolateLines` and `exLerp` functions, but don't understand how exactly in this context linear interpolation works and why?&#xD;&#xA;I used this [material][4] as a theory for code implementation, but last part is still blurry for me.&#xD;&#xA;&#xD;&#xA;Anyone can provide working code example and explain theory in dump language with more deep math explanation and visual demonstration?&#xD;&#xA;So I can finally breakthrough this problem.   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vCcqM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/t1Nve.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/v6V2m.png&#xD;&#xA;  [4]: http://jamie-wong.com/2014/08/19/metaballs-and-marching-squares/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28469" PostHistoryTypeId="1" PostId="9899" RevisionGUID="c3952a9b-5dd4-47ad-83a8-902ed6f6843a" CreationDate="2020-05-29T11:34:38.303" UserId="13468" Text="2D metaballs with marching squares and linear interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="28470" PostHistoryTypeId="3" PostId="9899" RevisionGUID="c3952a9b-5dd4-47ad-83a8-902ed6f6843a" CreationDate="2020-05-29T11:34:38.303" UserId="13468" Text="|rendering|algorithm|2d-graphics|physics|fluid-sim|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28471" PostHistoryTypeId="5" PostId="9899" RevisionGUID="f121883a-96bc-4035-8a48-1b2b4cc10a41" CreationDate="2020-05-29T11:41:19.047" UserId="13468" Comment="deleted 24 characters in body" Text="I struggle do understand how linear interpolation works in the marching square rendering algorithm context.&#xD;&#xA;&#xD;&#xA;I created simple example in GDScript (Godot) of random floating metaballs to demonstrate the problem:&#xD;&#xA;&#xD;&#xA;    extends Node2D&#xD;&#xA;    &#xD;&#xA;    class Blob:&#xD;&#xA;    	var pos_x&#xD;&#xA;    	var pos_y&#xD;&#xA;    	var radius&#xD;&#xA;    	var velocity&#xD;&#xA;    	func _init(x, y, r, v):&#xD;&#xA;    		pos_x = x&#xD;&#xA;    		pos_y = y&#xD;&#xA;    		radius = r&#xD;&#xA;    		velocity = v&#xD;&#xA;    &#xD;&#xA;    # Declare member variables here. Examples:&#xD;&#xA;    # const a = 2&#xD;&#xA;    # var b = &quot;text&quot;&#xD;&#xA;    &#xD;&#xA;    const cell_size = 16&#xD;&#xA;    const blobs_count = 10&#xD;&#xA;    const blob_size = [20, 40]&#xD;&#xA;    const max_sum = 1&#xD;&#xA;    var screen_size&#xD;&#xA;    var blobs&#xD;&#xA;    var allowUpdate = true&#xD;&#xA;    &#xD;&#xA;    const drawMap = {&#xD;&#xA;    	0: null,&#xD;&#xA;    	1: [-0.5, 0, 0, -0.5],&#xD;&#xA;    	2: [-0.5, -1, 0, -0.5],&#xD;&#xA;    	3: [-0.5, 0, -0.5, -1],&#xD;&#xA;    	4: [-1, -0.5, -0.5, -1],&#xD;&#xA;    	5: [-1, -0.5, -0.5, 0, -0.5, -1, 0, -0.5],&#xD;&#xA;    	6: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	7: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	8: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	9: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	10: [-1, -0.5, -0.5, -1, -0.5, 0, 0, -0.5],&#xD;&#xA;    	11: [-1, -0.5, -0.5, -1],&#xD;&#xA;    	12: [-0.5, -1, -0.5, 0],&#xD;&#xA;    	13: [-0.5, -1, 0, -0.5],&#xD;&#xA;    	14: [-0.5, 0, 0, -0.5],&#xD;&#xA;    	15: null&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA; &#xD;&#xA;    func calcIsoSurface(x1, x2, y1, y2, r):&#xD;&#xA;    	var dx = x1 - x2&#xD;&#xA;    	var dy = y1 - y2&#xD;&#xA;    	var sd = dx*dx + dy*dy&#xD;&#xA;    	var res = r*r / sd&#xD;&#xA;    	return res&#xD;&#xA;    &#xD;&#xA;    # Called when the node enters the scene tree for the first time.&#xD;&#xA;    func _ready():&#xD;&#xA;    	screen_size = get_viewport().size&#xD;&#xA;    	blobs = Array()&#xD;&#xA;    	var rng = RandomNumberGenerator.new()&#xD;&#xA;    	var r = rng.randi_range(blob_size[0], blob_size[1])&#xD;&#xA;    	var x = rng.randi_range(r, screen_size.x - r)&#xD;&#xA;    	var y = rng.randi_range(r, screen_size.y - r)&#xD;&#xA;    	for n in range(blobs_count):&#xD;&#xA;    		blobs.push_back(&#xD;&#xA;    			Blob.new(&#xD;&#xA;    				x, &#xD;&#xA;    				y, &#xD;&#xA;    				r, &#xD;&#xA;    				Vector2(rng.randf_range(-1, 1), rng.randf_range(-1, 1))&#xD;&#xA;    			)&#xD;&#xA;    		)&#xD;&#xA;    	print(screen_size)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func formDrawIndex(x, y, sum, vertexes):&#xD;&#xA;    	var drawIndex = 0&#xD;&#xA;    	var corners = []&#xD;&#xA;    	if x &gt; 0 &amp;&amp; y &gt; 0:&#xD;&#xA;    		if sum &gt;= 1:&#xD;&#xA;    			drawIndex |= 1&#xD;&#xA;    		&#xD;&#xA;    		corners.push_back(sum)&#xD;&#xA;    		&#xD;&#xA;    		if vertexes.back() &gt;= 1:&#xD;&#xA;    			drawIndex |= 2&#xD;&#xA;    &#xD;&#xA;    		corners.push_back(vertexes.back())&#xD;&#xA;    		corners.push_back(vertexes.pop_front())&#xD;&#xA;    		&#xD;&#xA;    		if corners.back() &gt;= 1:&#xD;&#xA;    			drawIndex |= 4	&#xD;&#xA;    		if vertexes.front() &gt;= 1:&#xD;&#xA;    			drawIndex |= 8&#xD;&#xA;    		&#xD;&#xA;    		corners.push_back(vertexes.front())&#xD;&#xA;    	return 	{&quot;draw_index&quot;: drawIndex, &quot;corners&quot;: corners}	&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func exLerp(oneSum, zeroSum):&#xD;&#xA;    	if oneSum == zeroSum:&#xD;&#xA;    		return null&#xD;&#xA;    	return (1 - oneSum) / (zeroSum - oneSum)&#xD;&#xA;    	&#xD;&#xA;    	&#xD;&#xA;    func interpolateLines(lines, corners):&#xD;&#xA;    	if lines == null:&#xD;&#xA;    		return lines&#xD;&#xA;    	for i in range(0, lines.size(), 2):&#xD;&#xA;    		var x = lines[i]&#xD;&#xA;    		var y = lines[i+1]&#xD;&#xA;    		#somehow implement correct interpolation here&#xD;&#xA;    	return lines&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func drawLines(x, y, lines):&#xD;&#xA;    	if lines != null &amp;&amp; lines.size() &gt;= 4:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[0]), y + (cell_size*lines[1])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[2]), y + (cell_size*lines[3])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    					&#xD;&#xA;    	if lines != null &amp;&amp; lines.size() == 8:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[4]), y + (cell_size*lines[5])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[6]), y + (cell_size*lines[7])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    &#xD;&#xA;    # Called after update() in the _process()&#xD;&#xA;    func _draw():&#xD;&#xA;    	var vertexes = []&#xD;&#xA;    	for x in range(0, screen_size.x, cell_size):&#xD;&#xA;    		for y in range(0, screen_size.y, cell_size):&#xD;&#xA;    			var sum = 0&#xD;&#xA;    			for blob in blobs:&#xD;&#xA;    				sum += calcIsoSurface(x, blob.pos_x, y, blob.pos_y, blob.radius)&#xD;&#xA;    				#draw_circle(Vector2(blob.pos_x,blob.pos_y), blob.radius, Color.darkgray)&#xD;&#xA;    	&#xD;&#xA;    			#if sum &gt;= 1:&#xD;&#xA;    				#draw_rect(Rect2(x, y, 1, 1), Color.red)&#xD;&#xA;    			#else: 	draw_rect(Rect2(x, y, 1, 1), Color.black)&#xD;&#xA;    			&#xD;&#xA;    			var indexies = formDrawIndex(x, y, sum, vertexes)&#xD;&#xA;    			var lines = drawMap[indexies[&quot;draw_index&quot;]]&#xD;&#xA;    			lines = interpolateLines(lines, indexies[&quot;corners&quot;])			&#xD;&#xA;    			drawLines(x, y, lines)&#xD;&#xA;    					&#xD;&#xA;    			vertexes.push_back(sum)&#xD;&#xA;    			&#xD;&#xA;    		if x &gt; 0:&#xD;&#xA;    			vertexes.pop_front()&#xD;&#xA;    			&#xD;&#xA;    		&#xD;&#xA;    			&#xD;&#xA;    func _input(event):&#xD;&#xA;    	if event is InputEventMouseButton &amp;&amp; event.is_pressed():&#xD;&#xA;    		allowUpdate = !allowUpdate&#xD;&#xA;    		print(allowUpdate)&#xD;&#xA;    		&#xD;&#xA;    	&#xD;&#xA;    # Called every frame. 'delta' is the elapsed time since the previous frame.&#xD;&#xA;    func _process(delta):&#xD;&#xA;    	if !allowUpdate:		&#xD;&#xA;    		return		&#xD;&#xA;    	update()&#xD;&#xA;    &#xD;&#xA;    	for blob in blobs:&#xD;&#xA;    		blob.pos_x += blob.velocity.x&#xD;&#xA;    		blob.pos_y += blob.velocity.y&#xD;&#xA;    		if blob.pos_x &gt; screen_size.x || blob.pos_x &lt; 0:&#xD;&#xA;    			blob.velocity.x *= -1&#xD;&#xA;    		if blob.pos_y &gt; screen_size.y || blob.pos_y &lt; 0:&#xD;&#xA;    			blob.velocity.y *= -1&#xD;&#xA;&#xD;&#xA;The outcome looks something like this:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I would like to apply linear interpolation to make my meatballs smoother. This is where I stuck. The desire outcome is transform rendering of this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;To this:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I already created `interpolateLines` and `exLerp` functions, but don't understand how exactly in this context linear interpolation works and why?&#xD;&#xA;I used this [material][4] as a theory for code implementation, but last part is still blurry for me.&#xD;&#xA;&#xD;&#xA;Anyone can provide working code example and explain theory in dump language with more deep math explanation and visual demonstration?&#xD;&#xA;So I can finally breakthrough this problem.   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vCcqM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/t1Nve.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/v6V2m.png&#xD;&#xA;  [4]: http://jamie-wong.com/2014/08/19/metaballs-and-marching-squares/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28472" PostHistoryTypeId="2" PostId="9900" RevisionGUID="63eefccc-8fd3-4904-b7c5-ed88c914e81c" CreationDate="2020-05-29T20:29:39.043" UserId="6530" Text="I'm trying to produce wave surface animations, and I came across this paper: [Fast_Water_Animation_Using_the_Wave_Equation_with_Damping](https://www.researchgate.net/publication/220859148_Fast_Water_Animation_Using_the_Wave_Equation_with_Damping).  In the paper they go to provide the following equation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;At first I just blindly implemented this, but soon saw some strange bugs I realized weren't from me. When you evaluate the equation, say, with delta t = 1/60, delta x = 1, c = 0.01, and k = 1.0, on a grid with all zeros except the center point, you realize there's something off about this.  If you are at that center grid point, and say your value is 1.0, the acceleration component( the delta t^2 stuff in the above equation) is *positive* when you assume all the surrounding neighbors are zero. That makes no sense. Peaks in waves do not accelerate upwards when the values around them are smaller. And further more, normally when I see finite difference of the laplacian, it is *the average of the surrounding samples minus the current sample*.  &#xD;&#xA;&#xD;&#xA;Indeed, when I reverse the sign on the acceleration component, I get what appears to be the correct result (before vs after on 16x16 grid)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This is what I changed the equation to:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Was this just some pervasive typo or am I completely missing something here? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yCvdb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ypr9B.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bWYit.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/34hPn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28473" PostHistoryTypeId="1" PostId="9900" RevisionGUID="63eefccc-8fd3-4904-b7c5-ed88c914e81c" CreationDate="2020-05-29T20:29:39.043" UserId="6530" Text="Finite difference wave equation shown in paper is wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28474" PostHistoryTypeId="3" PostId="9900" RevisionGUID="63eefccc-8fd3-4904-b7c5-ed88c914e81c" CreationDate="2020-05-29T20:29:39.043" UserId="6530" Text="|rendering|simulation|fluid-sim|height-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28476" PostHistoryTypeId="2" PostId="9901" RevisionGUID="48fea3e4-a6b3-46e4-9ac8-42134b5e4128" CreationDate="2020-05-30T00:28:36.113" UserId="48" Text="Yes, it looks like a sign error in the paper. It looks like it was introduced in equation (4) and then carried through the following ones. In fact, the third term (the one with the diagonal neighbors) should be negative as well, as it's another part of the Laplacian.&#xD;&#xA;&#xD;&#xA;Probably the authors wrote the source code first and the paper after, so did not notice that their equations did not match what their code was doing. Ideally it should have been caught in the paper review, but, mistakes happen." ContentLicense="CC BY-SA 4.0" />
  <row Id="28477" PostHistoryTypeId="2" PostId="9902" RevisionGUID="6693c079-1915-463f-90b7-2eb294baafd0" CreationDate="2020-05-30T01:18:37.933" UserId="48" Text="The code you've shown here looks right to me. In order to verify the implementations, you could try writing some code that just integrates a few test functions over the hemisphere using both methods and verify that you get the same result (within some sampling error). Also if you haven't already, verify that the outputs from `sample_unit_square` and `sample_unit_disc` are doing what they're supposed to." ContentLicense="CC BY-SA 4.0" />
  <row Id="28478" PostHistoryTypeId="2" PostId="9903" RevisionGUID="87da5e1c-56db-416c-b483-34c031cbdefc" CreationDate="2020-05-30T03:58:53.173" UserId="13476" Text="you don't actually need to transform the z component, just ommit it and replace it with 1,because it is in tangent space it will only cause problems for this&#xD;&#xA;edit: I had the same problem and that fixed it&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28480" PostHistoryTypeId="5" PostId="9901" RevisionGUID="bef7f267-b382-444f-9908-4bb65fe2b9e5" CreationDate="2020-05-30T17:11:26.863" UserId="48" Comment="misread it; the third term is actually in the brackets for the second term" Text="Yes, it looks like a sign error in the paper. It looks like it was introduced in equation (4) and then carried through the following ones.&#xA;&#xD;&#xA;Probably the authors wrote the source code first and the paper after, so did not notice that their equations did not match what their code was doing. Ideally it should have been caught in the paper review, but, mistakes happen." ContentLicense="CC BY-SA 4.0" />
  <row Id="28481" PostHistoryTypeId="2" PostId="9905" RevisionGUID="527a5aee-723b-41ee-b72b-cab2be8cc6bc" CreationDate="2020-05-30T20:20:00.870" UserId="13472" Text="How do I determine how many (jittered) rays to trace for a given pixel, as a function of the statistics of a small initial set of test rays? Also, what size should the initial set be? (it's currently 20, based on eyeball tests)&#xD;&#xA;&#xD;&#xA;Currently I'm calculating the variance of the initial set and multiplying that by a arbitrary number (4000..40,000) to give the number of additional rays to trace. This gives acceptable results but I would prefer something grounded in real statistics, mostly so I can get some kind of confidence interval for how close to the true mean my sample mean is likely to be.&#xD;&#xA;&#xD;&#xA;Additional possibly relevant info: RGB values are 0..1, pixel color is mean of all samples, jitter is currently random but I'm looking into using a Halton sequence to ensure better distribution" ContentLicense="CC BY-SA 4.0" />
  <row Id="28482" PostHistoryTypeId="1" PostId="9905" RevisionGUID="527a5aee-723b-41ee-b72b-cab2be8cc6bc" CreationDate="2020-05-30T20:20:00.870" UserId="13472" Text="Math for adaptive supersampling for raytracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="28483" PostHistoryTypeId="3" PostId="9905" RevisionGUID="527a5aee-723b-41ee-b72b-cab2be8cc6bc" CreationDate="2020-05-30T20:20:00.870" UserId="13472" Text="|raytracing|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28484" PostHistoryTypeId="5" PostId="9867" RevisionGUID="0cce41b0-bd34-4f68-87fc-c416d62bfc07" CreationDate="2020-05-30T20:44:28.213" UserId="13410" Comment="added 756 characters in body; edited title" Text="If the iPhone had LiDAR sensors, it would be possible to generate a 3D point cloud that you could theoretically use to furnish a 3D AR reconstruction of your surroundings. E.g. you could create an AR video chat whereby you see a &quot;hologram&quot; projection of the person you are speaking with in your 3D environment. &#xD;&#xA;&#xD;&#xA;&gt;However, given that LiDAR has yet to be released on iPhone, do you know of an alternative transformation algorithm that may be employed on a single video stream for consistent video depth estimation? &#xD;&#xA;&#xD;&#xA;I came across [this SIGGRAPH 2020 video depth esitmation project](https://roxanneluo.github.io/Consistent-Video-Depth-Estimation/) which seems to do this pretty reliably. I think this question ultimately falls with the class of SLAM problems. The SIGGRAPH paper seems to be very promising, but ideally this would be done in realtime (or with a small time lag), which doesn't seem plausible; this is a [demo video](https://www.youtube.com/watch?v=5Tia2oblJAg&amp;fbclid=IwAR3xaG82vvatIeTQ9wVn0O-R_sbZoqN_e6qGwmUdgHleNPsY5ZGyHOkuBzk) in case you're curious.&#xD;&#xA;&#xD;&#xA;Alternatively, I thought it might be possible use two cameras simultaneously, e.g. the wide and normal, to correct for the camera FOV and optic distortion in each and then use the 3D stereoscopic transform in OpenCV knowing the optical properties of the setup (distance between the cameras, focal length, etc.) to generate a 3D image of the scene with almost as much precision as LiDAR. This [Medium article](https://becominghuman.ai/stereo-3d-reconstruction-with-opencv-using-an-iphone-camera-part-i-c013907d1ab5) on Stereo 3D reconstruction seems to suggest that such a configuration is possible, although I suppose the small baseline distance between the cameras relative to the object might affect the outcome. I think [depth map](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/capturing_photos_with_depth) in Apple's AVFoundation is certainly an alternative; however, the TrueDepth camera system was only introduced with the iPhoneX.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks in advance! I would appreciate it if this could be demonstrated by example :) I cross-posted [this question](https://computergraphics.stackexchange.com/questions/9867/can-you-use-opencv-stereo-3d-reconstruction-with-iphone-cameras-to-approximate-l) on the Computer Graphics exchange." ContentLicense="CC BY-SA 4.0" />
  <row Id="28485" PostHistoryTypeId="4" PostId="9867" RevisionGUID="0cce41b0-bd34-4f68-87fc-c416d62bfc07" CreationDate="2020-05-30T20:44:28.213" UserId="13410" Comment="added 756 characters in body; edited title" Text="Consistent Video Depth Estimation to approximate LiDAR?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28486" PostHistoryTypeId="2" PostId="9906" RevisionGUID="dc0facef-9e63-4fe6-8b21-a4df41ece6db" CreationDate="2020-05-30T21:01:32.017" UserId="13481" Text="I am trying to build a dedocohedron in OpenGL, and I know that there is a built-in function in GLUT for the purpose. I was wondering if there is a way to either see the sourcecode for those functions, or to extract the generated data for vertices, colors, and indeces and print them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28487" PostHistoryTypeId="1" PostId="9906" RevisionGUID="dc0facef-9e63-4fe6-8b21-a4df41ece6db" CreationDate="2020-05-30T21:01:32.017" UserId="13481" Text="glutSolid* source code" ContentLicense="CC BY-SA 4.0" />
  <row Id="28488" PostHistoryTypeId="3" PostId="9906" RevisionGUID="dc0facef-9e63-4fe6-8b21-a4df41ece6db" CreationDate="2020-05-30T21:01:32.017" UserId="13481" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28489" PostHistoryTypeId="50" PostId="9103" RevisionGUID="3db60f27-4b7b-4322-94c3-817fdb7bf68d" CreationDate="2020-05-30T22:03:05.410" UserId="-1" />
  <row Id="28490" PostHistoryTypeId="2" PostId="9907" RevisionGUID="f2c1f595-7748-4357-8609-b2725ddb6cc6" CreationDate="2020-05-31T02:02:31.583" UserId="7462" Text="If you open the modern Blender UI and select for example scaling, and then you use the scroll wheel to &quot;zoom&quot; (move the camera along the radial axis). You will notice that the size of the 3D&#xD;&#xA;widget remains constant in screen space (it becomes bigger or smaller in regards to all the other objects).&#xD;&#xA;&#xD;&#xA;I am wondering how this can be achieved. I assume there is an obvious matrix cancellation you can do, e.g setting the w component to 1 after projecting. But I am not sure.&#xD;&#xA;&#xD;&#xA;As you can see the widget's size in screen space is identical:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oZxDj.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/8VnC7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28491" PostHistoryTypeId="1" PostId="9907" RevisionGUID="f2c1f595-7748-4357-8609-b2725ddb6cc6" CreationDate="2020-05-31T02:02:31.583" UserId="7462" Text="How to keep an object constant in screen space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28492" PostHistoryTypeId="3" PostId="9907" RevisionGUID="f2c1f595-7748-4357-8609-b2725ddb6cc6" CreationDate="2020-05-31T02:02:31.583" UserId="7462" Text="|transformations|camera|linear-algebra|gui|ui|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28493" PostHistoryTypeId="5" PostId="9905" RevisionGUID="43f73d9e-a673-4436-87a6-3a392bb85327" CreationDate="2020-05-31T05:07:01.830" UserId="13472" Comment="added 150 characters in body" Text="How do I determine how many (jittered) rays to trace for a given pixel, as a function of the statistics of a small initial set of test rays? Also, what size should the initial set be? (it's currently 20, based on eyeball tests)&#xD;&#xA;&#xD;&#xA;Currently I'm calculating the variance of the initial set and multiplying that by a arbitrary number (4000..40,000) to give the number of additional rays to trace. This gives acceptable results but I would prefer something grounded in real statistics, mostly so I can get some kind of confidence interval for how close to the true mean my sample mean is likely to be.&#xD;&#xA;&#xD;&#xA;Additional possibly relevant info: RGB values are 0..1, pixel color is mean of all samples, jitter is currently random but I'm looking into using a Halton sequence to ensure better distribution, I am modeling diffuse inter-reflections, I'm rendering on a CPU using two threads per core, each rendering thread gets a row of pixels all to itself" ContentLicense="CC BY-SA 4.0" />
  <row Id="28494" PostHistoryTypeId="2" PostId="9908" RevisionGUID="faafc784-7d10-445e-8828-68dd2f62855c" CreationDate="2020-05-31T19:21:00.670" UserId="48" Text="Scale the object proportional to its depth (z in camera space) and it will retain the same size on screen regardless of its position in world space.&#xD;&#xA;&#xD;&#xA;Additionally, you might also wish to scale the object proportional to the field of view so that it retains the same screen size regardless of the camera zoom. (Specifically, scale it by tan(fov/2)).&#xD;&#xA;&#xD;&#xA;Finally, you might also wish to scale it inversely proportional to the pixel size of the window if you want the widget to retain a constant size in pixels regardless of how large the window is. Otherwise it will be constant as a fraction of the window size." ContentLicense="CC BY-SA 4.0" />
  <row Id="28495" PostHistoryTypeId="5" PostId="9908" RevisionGUID="e0f9da2b-536f-4a06-aa36-e8660c1e1ef4" CreationDate="2020-05-31T19:29:53.813" UserId="48" Comment="added 354 characters in body" Text="Scale the object proportional to its depth (z in camera space) and it will retain the same size on screen regardless of its position in world space.&#xD;&#xA;&#xD;&#xA;Additionally, you might also wish to scale the object proportional to the field of view so that it retains the same screen size regardless of the camera zoom. (Specifically, scale it by tan(fov/2)).&#xD;&#xA;&#xD;&#xA;Finally, you might also wish to scale it inversely proportional to the pixel size of the window if you want the widget to retain a constant size in pixels regardless of how large the window is. Otherwise it will be constant as a fraction of the window size.&#xD;&#xA;&#xD;&#xA;I wouldn't recommend trying to do this in post-projective space (by manipulating w, etc) because it will scale the object's distance from the camera at the same time as scaling its size. Effectively you're scaling it in camera space. What you really want to do is scale it in its own local space before applying world-view-projection transformations." ContentLicense="CC BY-SA 4.0" />
  <row Id="28496" PostHistoryTypeId="10" PostId="9894" RevisionGUID="c1d827e4-31ef-4ac7-b648-caa65799a8c9" CreationDate="2020-06-01T09:21:27.350" UserId="-1" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:506,&quot;DisplayName&quot;:&quot;Noah Witherspoon&quot;},{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;}]}" />
  <row Id="28497" PostHistoryTypeId="2" PostId="9909" RevisionGUID="d4735358-f4e9-48be-8c87-540273875e8a" CreationDate="2020-06-01T13:56:12.403" UserId="13485" Text="I do this already. &#xD;&#xA;-&#xD;&#xA;**TL;DR: The latency between services decelerate the enthusiasm.**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have a steam-vr-client supporting a wide range of Helmets and the vr-client is connecting to a local server (Currently connectors for Java exsits only) and then further cloud-services. &#xD;&#xA;&#xD;&#xA;As most games have two threads who must be synchronized&#xD;&#xA;&#xD;&#xA;1. Frontend: The visualization of the gamelogic&#xD;&#xA;2. Backend: The gamelogic, model, rules....&#xD;&#xA;3. (Optional) Multiplayer Thread: Synchronizing gamestate between contributors.&#xD;&#xA;&#xD;&#xA;In VR there will be a growing latency between Frontend and Backend the more work is done in the Clouded-Backend. So we have to estimate what contribution to the VR is a lightweight-transported information and do the rest in the cloud.&#xD;&#xA;&#xD;&#xA;1. Frontend (locally): The low-level visualisation. Calculating shadows and &quot;depth of field blur&quot;, but not calculating ambient occlusion, not calculating raytracing, not calculating Bumpmapping.&#xD;&#xA;2. Backend (locally): Collecting results from the cloud, collect Bumpmaps, transport Mesh, UV-Coodinates, Normal-Mappings, Bumpmappings, Raytrace-Results and send it to Frontend.&#xD;&#xA;3. Cloud (web/internet). Calculating raytrace, generate Bumpmaps, Calculate Mesh resolution, calculate UV-Coordinates and Normals.&#xD;&#xA;&#xD;&#xA;The key to seperate work for different cloud services is to understand what work can be done packed autark.&#xD;&#xA;&#xD;&#xA;My project: https://github.com/enexusde/VRServer" ContentLicense="CC BY-SA 4.0" />
  <row Id="28499" PostHistoryTypeId="50" PostId="9614" RevisionGUID="00ac515f-2166-405e-8492-0c059b21c939" CreationDate="2020-06-01T21:01:50.220" UserId="-1" />
  <row Id="28500" PostHistoryTypeId="50" PostId="9116" RevisionGUID="a618826b-d211-4ac7-ae95-d1c351b71135" CreationDate="2020-06-02T09:02:50.280" UserId="-1" />
  <row Id="28501" PostHistoryTypeId="2" PostId="9910" RevisionGUID="3956d3b0-1896-4d1d-8f01-99eda1bf8083" CreationDate="2020-06-02T10:01:10.027" UserId="2372" Text="I am currently trying to sample a texture in screen space. This works well :&#xD;&#xA;&#xD;&#xA;    float4 positionCS = vertexInput.positionCS / vertexInput.positionCS.w;&#xD;&#xA;    screenPos = ComputeScreenPos(positionCS).xy;&#xD;&#xA;    float aspect = _ScreenParams.x / _ScreenParams.y;&#xD;&#xA;    screenPos.x = screenPos.x * aspect;&#xD;&#xA;&#xD;&#xA;But I would like to be able to constrain uv position and scale based on object's position and distance from camera. I found some example but I also faced some issues and for the moment I don't see how to fix them. Here's the code :&#xD;&#xA;&#xD;&#xA;    float4 positionCS = vertexInput.positionCS / vertexInput.positionCS.w;&#xD;&#xA;    screenPos = ComputeScreenPos(positionCS).xy;&#xD;&#xA;    float aspect = _ScreenParams.x / _ScreenParams.y;&#xD;&#xA;    screenPos.x = screenPos.x * aspect;&#xD;&#xA;     &#xD;&#xA;    float4 originCS = TransformObjectToHClip(float3(0.0, 0.0, 0.0));&#xD;&#xA;    originCS = originCS / originCS.w;&#xD;&#xA;    float2 originSPos = ComputeScreenPos(originCS).xy;&#xD;&#xA;    originSPos.x = originSPos.x * aspect;&#xD;&#xA;    screenPos = screenPos - originSPos;&#xD;&#xA;     &#xD;&#xA;    // You can match object's distance like this&#xD;&#xA;    float3 cameraPosWS = GetCameraPositionWS();&#xD;&#xA;    float3 originPosWS = TransformObjectToWorld(float4(0.0, 0.0, 0.0, 1.0));&#xD;&#xA;    float d = distance(float4(0.0, 0.0, 0.0, 0.0), cameraPosWS - originPosWS);&#xD;&#xA;    screenPos *= d;&#xD;&#xA;&#xD;&#xA;And here's the issue I am facing. You can notice that when the object is near screen edges the texture starts to move. Is there a way to avoid that ?&#xD;&#xA;&#xD;&#xA;https://thumbs.gfycat.com/HairySpryArawana-mobile.mp4&#xD;&#xA;&#xD;&#xA;I am using URP but this doesn't really matter. " ContentLicense="CC BY-SA 4.0" />
  <row Id="28502" PostHistoryTypeId="1" PostId="9910" RevisionGUID="3956d3b0-1896-4d1d-8f01-99eda1bf8083" CreationDate="2020-06-02T10:01:10.027" UserId="2372" Text="Per-object screen space uv issue" ContentLicense="CC BY-SA 4.0" />
  <row Id="28503" PostHistoryTypeId="3" PostId="9910" RevisionGUID="3956d3b0-1896-4d1d-8f01-99eda1bf8083" CreationDate="2020-06-02T10:01:10.027" UserId="2372" Text="|shader|glsl|uv-mapping|hlsl|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28504" PostHistoryTypeId="50" PostId="8462" RevisionGUID="afc062ac-054c-4e10-8424-ec6ba6e1f618" CreationDate="2020-06-02T10:07:20.700" UserId="-1" />
  <row Id="28505" PostHistoryTypeId="2" PostId="9911" RevisionGUID="07959d2b-dd1d-4cba-b65a-6ffe9638a4aa" CreationDate="2020-06-02T10:57:39.960" UserId="13490" Text="I have a 2D region defined by 4 points in 3D space. I want to position my camera so that it looks at the region, with a settable variable determining which side it looks at, where looks at means that the camera view covers the entire region to be looked at, and as little beyond that as possible. How do I calculate the orientation and position of the camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28506" PostHistoryTypeId="1" PostId="9911" RevisionGUID="07959d2b-dd1d-4cba-b65a-6ffe9638a4aa" CreationDate="2020-06-02T10:57:39.960" UserId="13490" Text="Calculate the position and rotation needed to have a camera look at a certain region" ContentLicense="CC BY-SA 4.0" />
  <row Id="28507" PostHistoryTypeId="3" PostId="9911" RevisionGUID="07959d2b-dd1d-4cba-b65a-6ffe9638a4aa" CreationDate="2020-06-02T10:57:39.960" UserId="13490" Text="|2d|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28508" PostHistoryTypeId="2" PostId="9912" RevisionGUID="6ef0b2ce-f0ea-4080-8d1b-11955049bf49" CreationDate="2020-06-02T15:49:13.177" UserId="13491" Text="I am trying to measure the reflectance% of a surface (it is made of Teflon and is very white). I am using a line spectrometer. I believe the piece can replace an expensive Spectralon for some experiments. To show that it has a quite acceptable reflectance, I need to draw its reflectance plot at different wavelengths similar to the chart presented with Spectralon. See the below image.&#xD;&#xA;[![Reflectance spectrum of Spectralon][1]][1]&#xD;&#xA;&#xD;&#xA;I had a look at different pieces of literature and I found out with two spectrum recordings of direct light source facing the spectrometer and illuminating the surface with the light then recording its reflection I am able to calculate the reflectance. To do so, I normalized the two readings with respect to the exposure times and I divided the two signals (surface spectrum divided by direct illumination spectrum) and this graph is obtained.&#xD;&#xA;[![Reflectance][2]][2]&#xD;&#xA;&#xD;&#xA;I also attached the Digital Number read by camera here.&#xD;&#xA;[![Teflon Digital Number normalized by the exposure time][3]][3]&#xD;&#xA;[![Digital Number from direct light][4]][4]&#xD;&#xA;&#xD;&#xA;The detail of the experimental setup is as follows:&#xD;&#xA;1- The camera angle is 45 degrees with respect to the surface and the illumination light is facing 45 degrees to the surface.  &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2MAyS.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/TMgh1.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/k49xF.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/FWnBi.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28509" PostHistoryTypeId="1" PostId="9912" RevisionGUID="6ef0b2ce-f0ea-4080-8d1b-11955049bf49" CreationDate="2020-06-02T15:49:13.177" UserId="13491" Text="How to measure the reflectance of a material without using a Spectralon" ContentLicense="CC BY-SA 4.0" />
  <row Id="28510" PostHistoryTypeId="3" PostId="9912" RevisionGUID="6ef0b2ce-f0ea-4080-8d1b-11955049bf49" CreationDate="2020-06-02T15:49:13.177" UserId="13491" Text="|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28511" PostHistoryTypeId="5" PostId="9867" RevisionGUID="2e383368-71ce-4010-812d-0d574a2e102b" CreationDate="2020-06-03T07:04:22.177" UserId="13095" Comment="Fix some typos" Text="If the iPhone had LiDAR sensors, it would be possible to generate a 3D point cloud that you could theoretically use to furnish a 3D AR reconstruction of your surroundings. E.g. you could create an AR video chat whereby you see a &quot;hologram&quot; projection of the person you are speaking within your 3D environment. &#xD;&#xA;&#xD;&#xA;&gt;However, given that LiDAR has yet to be released on iPhone, do you know of an alternative transformation algorithm that may be employed on a single video stream for consistent video depth estimation? &#xD;&#xA;&#xD;&#xA;I came across [this SIGGRAPH 2020 video depth estimation project](https://roxanneluo.github.io/Consistent-Video-Depth-Estimation/) which seems to do this pretty reliably. I think this question ultimately falls with the class of SLAM problems. The SIGGRAPH paper seems to be very promising, but ideally, this would be done in realtime (or with a small time lag), which doesn't seem plausible; this is a [demo video](https://www.youtube.com/watch?v=5Tia2oblJAg&amp;fbclid=IwAR3xaG82vvatIeTQ9wVn0O-R_sbZoqN_e6qGwmUdgHleNPsY5ZGyHOkuBzk) in case you're curious.&#xD;&#xA;&#xD;&#xA;Alternatively, I thought it might be possible using two cameras simultaneously, e.g. the wide and normal, to correct for the camera FOV and optic distortion in each and then use the 3D stereoscopic transform in OpenCV knowing the optical properties of the setup (distance between the cameras, focal length, etc.) to generate a 3D image of the scene with almost as much precision as LiDAR. This [Medium article](https://becominghuman.ai/stereo-3d-reconstruction-with-opencv-using-an-iphone-camera-part-i-c013907d1ab5) on Stereo 3D reconstruction seems to suggest that such a configuration is possible, although I suppose the small baseline distance between the cameras relative to the object might affect the outcome. I think [depth map](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/capturing_photos_with_depth) in Apple's AVFoundation is certainly an alternative; however, the TrueDepth camera system was only introduced with the iPhoneX.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks in advance! I would appreciate it if this could be demonstrated by example :) I cross-posted [this question](https://computergraphics.stackexchange.com/questions/9867/can-you-use-opencv-stereo-3d-reconstruction-with-iphone-cameras-to-approximate-l) on the Computer Graphics exchange." ContentLicense="CC BY-SA 4.0" />
  <row Id="28512" PostHistoryTypeId="24" PostId="9867" RevisionGUID="2e383368-71ce-4010-812d-0d574a2e102b" CreationDate="2020-06-03T07:04:22.177" Comment="Proposed by 13095 approved by 209, 13410 edit id of 529" ContentLicense="CC BY-SA 4.0" />
  <row Id="28513" PostHistoryTypeId="2" PostId="9913" RevisionGUID="6d0634d6-a6c9-4779-a81e-bfa31b4b69b4" CreationDate="2020-06-03T11:22:12.497" UserId="13095" Text="&gt; I have a 2D region defined by 4 points in 3D space. I want to position my camera so that it looks at the region, with a settable variable determining which side it looks at,...&#xD;&#xA;&#xD;&#xA;The first thing you need to do for this is to define a convention that specifies which side is the front and which one is the back of your plane depending on the ordering of your nodes. With triangles, you usually use the winding order. So you can define that if you look at the front of a triangle, the points have to be in clockwise order. In conclusion, if you see that the nodes of the triangle are ordered counter-clockwise, you look at the back.&#xD;&#xA;&#xD;&#xA;&gt; How do I calculate the orientation and position of the camera?&#xD;&#xA;&#xD;&#xA;Once you have this convention, you have to calculate the normal of the surface. You can get it by calculating the cross product of 2 vectors. For example, if your points are named A, B, C, D, take the vectors A-&gt;B and A-&gt;C and calculate their cross product to get the surface normal. Be aware, that the cross product is sensitive to the vector/node order. So make sure the selected points result in a normal that points away from your front side. &#xD;&#xA;&#xD;&#xA;Now, your camera orientation is the negative normal direction if you look at the front and the normal's direction if you look at the back.&#xD;&#xA;&#xD;&#xA;Then you calculate the center point of your quadriliteral. There are several ways to do this, so just pick your favorite method or search the internet for it. Your camera position C has to be on the line that has the same direction as your surfaces' **unit** normal N and goes through the center point P of your surface. So it can be calculated by&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;C = P + d \cdot N&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where d is the distance of the camera to point P. The distance depends on your camera's field of view and the size of your plane. In your special case, where the camera looks directly onto your surface, the camera/screen plane is parallel to your surface. So you can use the [intercept theorem](https://en.wikipedia.org/wiki/Intercept_theorem) to calculate the minimal necessary camera distance so that all points of your plane are inside the cameras FOV.&#xD;&#xA;&#xD;&#xA;**Remark:**&#xD;&#xA;&#xD;&#xA;The described method leaves you with one degree of freedom for your camera that is chosen more or less randomly. The rotation angle around its view direction. Depending on the size and shape of your plane, the rotation angle also influences the camera's distance to the plane. So you might want to define an additional constraint to always get the same result. For example, you could say, that your surfaces side A-B has to be parallel to your screens left-hand side." ContentLicense="CC BY-SA 4.0" />
  <row Id="28514" PostHistoryTypeId="50" PostId="9781" RevisionGUID="1ee5ea56-73c6-46f6-b082-f79d6f3091c3" CreationDate="2020-06-03T17:00:35.047" UserId="-1" />
  <row Id="28515" PostHistoryTypeId="2" PostId="9914" RevisionGUID="8d119113-c3a3-4cbb-95e5-626713dce233" CreationDate="2020-06-03T19:17:33.757" UserId="13449" Text="This is in reference and contrast to the discipline (or more or less requirement) of opengl to group draws that use the same materials together, to minimize making many draw calls or many switch shader calls.&#xD;&#xA;&#xD;&#xA;So is it safe to say, that since vulkan is not state/context based, you can throw any mixture of draw commands with multiple seperate shaders/materials in the command queue, with no slowdown or overhead impact, and that even if you did the grouping optimization, you wouldn't see a speedup as well?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28516" PostHistoryTypeId="1" PostId="9914" RevisionGUID="8d119113-c3a3-4cbb-95e5-626713dce233" CreationDate="2020-06-03T19:17:33.757" UserId="13449" Text="Do you have to group and optimize your draw and shader calls in Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28517" PostHistoryTypeId="3" PostId="9914" RevisionGUID="8d119113-c3a3-4cbb-95e5-626713dce233" CreationDate="2020-06-03T19:17:33.757" UserId="13449" Text="|vulkan|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28518" PostHistoryTypeId="2" PostId="9915" RevisionGUID="a3175166-ae61-4f29-b3aa-bc4fe9ab3137" CreationDate="2020-06-04T01:26:40.457" UserId="2654" Text="Vulkan will not have the CPU-time performance costs associated with state changes (validation overhead, etc). But Vulkan command buffers do have state. They have two very major pieces of state: descriptor sets and the pipeline object.&#xD;&#xA;&#xD;&#xA;Both of these objects are monolithic, dealing with potentially lots of pieces of information. The (potentially) huge quantity of stuff these objects control should strongly suggest to you that binding new objects is not cheap. And that's in terms of GPU execution speed, not CPU validation or whatever else.&#xD;&#xA;&#xD;&#xA;Vulkan in general tries to make slow things in the API look slow and fast things look fast. Render passes are big, huge and complicated, so clearly you shouldn't just be starting and stopping them whenever you feel like it. Pipeline objects control a huge amount of information, so binding new ones feels like a heavyweight operation.&#xD;&#xA;&#xD;&#xA;By contrast, changing what buffers get used for vertex input feels like a short, quick, *focused* operation. So it's probably cheaper than changing the pipeline that uses those buffers.&#xD;&#xA;&#xD;&#xA;So yes, you should avoid state changes in Vulkan, just as much if not moreso than in OpenGL (since many state changes in Vulkan require entirely new pipelines)." ContentLicense="CC BY-SA 4.0" />
  <row Id="28519" PostHistoryTypeId="2" PostId="9916" RevisionGUID="b204ff53-8a12-4d74-947c-90d79d0e8ded" CreationDate="2020-06-04T08:59:54.127" UserId="13497" Text="In [The Road to PS5](https://youtu.be/ph8LyNIT9sg?t=2028), Mark Cerny states:&#xD;&#xA;&#xD;&#xA;&gt; It's counter-intuitive, but processing dense geometry typically consumes less power than processing simple geometry.&#xD;&#xA;&#xD;&#xA;Why is this the case?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28520" PostHistoryTypeId="1" PostId="9916" RevisionGUID="b204ff53-8a12-4d74-947c-90d79d0e8ded" CreationDate="2020-06-04T08:59:54.127" UserId="13497" Text="Why does processing dense geometry consume less power than simple geometry?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28521" PostHistoryTypeId="3" PostId="9916" RevisionGUID="b204ff53-8a12-4d74-947c-90d79d0e8ded" CreationDate="2020-06-04T08:59:54.127" UserId="13497" Text="|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28522" PostHistoryTypeId="2" PostId="9917" RevisionGUID="bbc5d3bd-0ec1-4bf4-8fe6-42fe0bff913e" CreationDate="2020-06-04T13:06:19.827" UserId="11412" Text="I have many sets of vertex and index buffers that I’d like to render on to the screen. Ideally each model in different locations with-in world space. I’m actually doing a statistical study on spatial relationships between models in world space. &#xD;&#xA;&#xD;&#xA;I have done a lot of reading on the DirectX graphics pipeline to try and get a basic understanding of how it works.&#xD;&#xA;&#xD;&#xA;Instead of programming my own model viewer from the ground up, I thought I’d first take a look at some pre-built solutions first to save me the time. I found this: https://github.com/walbourn/directxtkmodelviewer&#xD;&#xA;&#xD;&#xA;From what I can tell, it only supports loading models from DirectX SDK .SDKMESH files and .VBO files. So 2 questions:&#xD;&#xA;&#xD;&#xA;1)	How do I convert my vertex and index buffers to one of those file formats?&#xD;&#xA;&#xD;&#xA;2)	For changing the models world space in the viewer, isn’t that done by changing the view matrix before uploading the model? &#xD;&#xA;&#xD;&#xA;Also, if this can be done in standard 3D modeling application, that would be ideal. All I want to do is view the models in relation to each other. I haven’t been able to find any applications that accept vertex and index buffers in raw form though. &#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28523" PostHistoryTypeId="1" PostId="9917" RevisionGUID="bbc5d3bd-0ec1-4bf4-8fe6-42fe0bff913e" CreationDate="2020-06-04T13:06:19.827" UserId="11412" Text="Converting Vertex and Index buffers to a File Format" ContentLicense="CC BY-SA 4.0" />
  <row Id="28524" PostHistoryTypeId="3" PostId="9917" RevisionGUID="bbc5d3bd-0ec1-4bf4-8fe6-42fe0bff913e" CreationDate="2020-06-04T13:06:19.827" UserId="11412" Text="|rendering|transformations|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28525" PostHistoryTypeId="50" PostId="9789" RevisionGUID="2f76c404-a27d-42c1-9d69-ff411516ff06" CreationDate="2020-06-04T18:05:05.483" UserId="-1" />
  <row Id="28526" PostHistoryTypeId="50" PostId="9791" RevisionGUID="5cc3b47a-418b-4e71-94af-5cc1856850fa" CreationDate="2020-06-04T21:00:45.093" UserId="-1" />
  <row Id="28527" PostHistoryTypeId="2" PostId="9918" RevisionGUID="1e7dce3d-7d58-4de3-a0de-c819cd67927d" CreationDate="2020-06-05T00:37:19.637" UserId="7462" Text="In section 4.2 of this paper:&#xD;&#xA;&#xD;&#xA;http://cseweb.ucsd.edu/~ravir/274/15/papers/a209-xu.pdf&#xD;&#xA;&#xD;&#xA;Xu et al approximate the product of 2 anisotropic Gaussian distributions. I want to know if someone has found not an approximation but THE solution to what the resulting ASG distribution is after taking the product." ContentLicense="CC BY-SA 4.0" />
  <row Id="28528" PostHistoryTypeId="1" PostId="9918" RevisionGUID="1e7dce3d-7d58-4de3-a0de-c819cd67927d" CreationDate="2020-06-05T00:37:19.637" UserId="7462" Text="Has anyone found an analytic solution to the product of spherical gaussians from Xu et al?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28529" PostHistoryTypeId="3" PostId="9918" RevisionGUID="1e7dce3d-7d58-4de3-a0de-c819cd67927d" CreationDate="2020-06-05T00:37:19.637" UserId="7462" Text="|rendering|geometry|hemisphere|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28530" PostHistoryTypeId="4" PostId="9867" RevisionGUID="04747971-135f-43d7-890f-1ec6a330f89f" CreationDate="2020-06-05T02:13:24.940" UserId="13410" Comment="edited title" Text="Consistent Video Depth Estimation from Monocular Lens to approximate LiDAR?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28531" PostHistoryTypeId="2" PostId="9919" RevisionGUID="29c0eede-a9ee-47d3-a6ff-9e1de4387510" CreationDate="2020-06-07T05:39:25.920" UserId="13508" Text="Given a set of human body mesh {S_i}, for each S_i, the points are N*3, we can do PCA on that. We can use PCA to reduce the dimension of {S_i}, for example to k dimension. Let the main direction of PCA be [D1, D2, ..., Dk], then the body geometry can be represented by S = W1 * D1 + W2 * D2 + ... + Wk * Dk, where W = [W1, W2, ..., W3] is the weights.&#xD;&#xA;&#xD;&#xA;But how can we get the weight W of one specific mesh S_i in {S_i}?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28532" PostHistoryTypeId="1" PostId="9919" RevisionGUID="29c0eede-a9ee-47d3-a6ff-9e1de4387510" CreationDate="2020-06-07T05:39:25.920" UserId="13508" Text="How to use PCA to reconstruct 3D Mesh？" ContentLicense="CC BY-SA 4.0" />
  <row Id="28533" PostHistoryTypeId="3" PostId="9919" RevisionGUID="29c0eede-a9ee-47d3-a6ff-9e1de4387510" CreationDate="2020-06-07T05:39:25.920" UserId="13508" Text="|mesh|processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28534" PostHistoryTypeId="2" PostId="9920" RevisionGUID="e0d7af22-ed9b-4281-8a41-d073ecbb0176" CreationDate="2020-06-07T10:05:15.583" UserId="10188" Text="I have following structure which i use as an uniform buffer object.&#xD;&#xA;&#xD;&#xA;    struct GlobalShaderData&#xD;&#xA;	{&#xD;&#xA;	    #define CLUSTER_X_MAX 16&#xD;&#xA;	    #define CLUSTER_Y_MAX 8&#xD;&#xA;	    #define CLUSTER_Z_MAX 8&#xD;&#xA;	    #define CLUSTER_MAX_LIGHTS 4&#xD;&#xA;		int pointLightIndices[CLUSTER_X_MAX * CLUSTER_Y_MAX * CLUSTER_Z_MAX * CLUSTER_MAX_LIGHTS];&#xD;&#xA;		int pointLightsPerTile[CLUSTER_X_MAX * CLUSTER_Y_MAX * CLUSTER_Z_MAX];&#xD;&#xA;	};&#xD;&#xA;	GlobalShaderData globalShaderData;&#xD;&#xA;&#xD;&#xA;The total size of the first int array should be 4 bytes * 16 * 8 * 8 * 4 = 16384 bytes, thus the maximum ubo memory is not exceeded.&#xD;&#xA;&#xD;&#xA;However, when compiling the shaders I receive an &quot;out of resource&quot; error message.&#xD;&#xA;&#xD;&#xA;I guess the integer actually takes 16 bytes on the glsl side to align with a vec4.&#xD;&#xA;Because if we calculate with 16 bytes * 16 * 8 * 8 * 4 = 65536 bytes, which just exceedes the maximum capacity.&#xD;&#xA;&#xD;&#xA;What are my options to have an smaller integer array on glsl side.&#xD;&#xA;&#xD;&#xA;(I know that I could use other storage buffers but thats not relevant to the question.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28535" PostHistoryTypeId="1" PostId="9920" RevisionGUID="e0d7af22-ed9b-4281-8a41-d073ecbb0176" CreationDate="2020-06-07T10:05:15.583" UserId="10188" Text="Force int array to compact memory" ContentLicense="CC BY-SA 4.0" />
  <row Id="28536" PostHistoryTypeId="3" PostId="9920" RevisionGUID="e0d7af22-ed9b-4281-8a41-d073ecbb0176" CreationDate="2020-06-07T10:05:15.583" UserId="10188" Text="|opengl|glsl|memory|uniform-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28537" PostHistoryTypeId="2" PostId="9921" RevisionGUID="79c59d40-e911-493b-a3b0-8dae1fd0b68b" CreationDate="2020-06-08T04:06:26.570" UserId="2654" Text="Assuming you use this structure within an actual UBO (which your example code doesn't do), just use an array of `ivec4` and two indices.&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;const ivec3 cluster_max = ivec3(16, 8, 8);&#xD;&#xA;const int cluster_max_lights = 4;&#xD;&#xA;&#xD;&#xA;const int plix_count = cluster_max.x * cluster_max.y * cluster_max.z * cluster_max_lights;&#xD;&#xA;const int plix_index_size = pl_count / 4;&#xD;&#xA;&#xD;&#xA;const int plpt_count = cluster_max.x * cluster_max.y * cluster_max.z;&#xD;&#xA;const int plpt_index_size = plpt_count / 4;&#xD;&#xA;&#xD;&#xA;struct GlobalShaderData&#xD;&#xA;{&#xD;&#xA;    ivec4 pointLightIndices[plix_index_size];&#xD;&#xA;    ivec4 pointLightsPerTile[plpt_index_size];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std140) uniform shaderData&#xD;&#xA;{&#xD;&#xA;    GlobalShaderData globalShaderData;&#xD;&#xA;};&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;To access a value from the arrays, you will have to divide the index by 4 to get the `ivec4` index, then take the original index mod 4 and use that to index the `ivec4`.&#xD;&#xA;To get the " ContentLicense="CC BY-SA 4.0" />
  <row Id="28538" PostHistoryTypeId="50" PostId="9146" RevisionGUID="651c82d3-59a9-477f-a13f-6ec2ba68741d" CreationDate="2020-06-08T16:06:45.653" UserId="-1" />
  <row Id="28539" PostHistoryTypeId="2" PostId="9922" RevisionGUID="f47285ed-e494-4001-9cea-3857c9f10fa9" CreationDate="2020-06-08T17:36:24.483" UserId="13515" Text="I am trying to get up to speed with the NV_mesh_shader extension from NVidia (on my RTX2080). Samples are rare, so I tried to come up with my own small sample.&#xD;&#xA;&#xD;&#xA;I am rendering a sphere (20 triangles) using an index buffer and a vertex buffer. I can render it the &quot;usual&quot; way using &quot;vertex pulling&quot; with two shader storage buffers, one for vertices, one for indices, (like I want to do it with a mesh shader) just fine.&#xD;&#xA;&#xD;&#xA;When using a mesh shader (no task shader so far) I get the following problem: calling ```glDrawMeshTaskNV(0,1)```with the mesh shader set to ```layout(local_size_x=20) in``` I only get a single triangle rendered. It looks like the mesh shader is not being invoked 20 times as I think it should?&#xD;&#xA;If I call ```glDrawMeshTaskNV(0,20)``` and set ```layout(local_size_x=1) in``` it renders just fine with nothing else changed in the shader. I use ```gl_GlobalInvocationID.x``` to pull the proper vertices for a triangle.&#xD;&#xA;&#xD;&#xA;Here's the complete shader for the non-working variant:&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;#extension GL_NV_mesh_shader : require&#xD;&#xA;&#xD;&#xA;#define GROUP_SIZE 20&#xD;&#xA;// mesh shader setup&#xD;&#xA;layout(local_size_x=GROUP_SIZE) in;&#xD;&#xA;&#xD;&#xA;layout(max_vertices=3, max_primitives=1) out;&#xD;&#xA;layout(triangles) out;&#xD;&#xA;&#xD;&#xA;// vertex/index data setup&#xD;&#xA;struct Vertex&#xD;&#xA;{&#xD;&#xA;	vec4 position;&#xD;&#xA;	vec4 uv;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding=1) readonly buffer vertex_data&#xD;&#xA;{&#xD;&#xA;	Vertex vertex[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(std430, binding=2) readonly buffer index_data&#xD;&#xA;{&#xD;&#xA;	uint indices[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;uniform mat4 model;&#xD;&#xA;uniform mat4 view;&#xD;&#xA;uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;// mesh output&#xD;&#xA;out gl_MeshPerVertexNV {&#xD;&#xA;	vec4 gl_Position;&#xD;&#xA;} gl_MeshVerticesNV[];&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;out uint gl_PrimitiveCountNV;&#xD;&#xA;out uint gl_PrimitiveIndicesNV[];&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	// get starting index&#xD;&#xA;	const uint primitive_start_index = gl_GlobalInvocationID.x * 3;&#xD;&#xA;&#xD;&#xA;	uint index_A = indices[primitive_start_index];&#xD;&#xA;	uint index_B = indices[primitive_start_index+1];&#xD;&#xA;	uint index_C = indices[primitive_start_index+2];&#xD;&#xA;&#xD;&#xA;	// get vertices&#xD;&#xA;	vec3 A = vertex[index_A].position.xyz;&#xD;&#xA;	vec3 B = vertex[index_B].position.xyz;&#xD;&#xA;	vec3 C = vertex[index_C].position.xyz;&#xD;&#xA;&#xD;&#xA;	gl_MeshVerticesNV[0].gl_Position = projection * (view * (model * vec4(A, 1.0)));&#xD;&#xA;	gl_MeshVerticesNV[1].gl_Position = projection * (view * (model * vec4(B, 1.0)));&#xD;&#xA;	gl_MeshVerticesNV[2].gl_Position = projection * (view * (model * vec4(C, 1.0)));&#xD;&#xA;&#xD;&#xA;	gl_PrimitiveIndicesNV[0] = 0;&#xD;&#xA;	gl_PrimitiveIndicesNV[1] = 1;&#xD;&#xA;	gl_PrimitiveIndicesNV[2] = 2;&#xD;&#xA;&#xD;&#xA;	gl_PrimitiveCountNV += 1;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Keep in mind this is only a learning sample, I know this is maybe overkill for a mesh shader :)&#xD;&#xA;&#xD;&#xA;Thanks for any hints.&#xD;&#xA;pettersson" ContentLicense="CC BY-SA 4.0" />
  <row Id="28540" PostHistoryTypeId="1" PostId="9922" RevisionGUID="f47285ed-e494-4001-9cea-3857c9f10fa9" CreationDate="2020-06-08T17:36:24.483" UserId="13515" Text="OpenGL task/mesh shader extension NV_mesh_shader not behaving as I expected" ContentLicense="CC BY-SA 4.0" />
  <row Id="28541" PostHistoryTypeId="3" PostId="9922" RevisionGUID="f47285ed-e494-4001-9cea-3857c9f10fa9" CreationDate="2020-06-08T17:36:24.483" UserId="13515" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28542" PostHistoryTypeId="50" PostId="9409" RevisionGUID="bcfcc62e-77b3-4af4-a7e9-0afb61fb92a2" CreationDate="2020-06-08T20:03:10.237" UserId="-1" />
  <row Id="28543" PostHistoryTypeId="50" PostId="9761" RevisionGUID="4c8f1a63-bc52-488a-8bd9-733bb81e0390" CreationDate="2020-06-08T23:01:00.103" UserId="-1" />
  <row Id="28544" PostHistoryTypeId="2" PostId="9923" RevisionGUID="26aab7e5-7759-4949-8f9c-fb00880653a0" CreationDate="2020-06-08T23:28:03.537" UserId="13517" Text="Digital painting and raster graphics software like Krita and Photoshop have a canvas where you can paint with brushes. From a programming perspective, how is this canvas rendered? Can it be included on a graphics pipeline like OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28545" PostHistoryTypeId="1" PostId="9923" RevisionGUID="26aab7e5-7759-4949-8f9c-fb00880653a0" CreationDate="2020-06-08T23:28:03.537" UserId="13517" Text="How are digital painting canvas rendered?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28546" PostHistoryTypeId="3" PostId="9923" RevisionGUID="26aab7e5-7759-4949-8f9c-fb00880653a0" CreationDate="2020-06-08T23:28:03.537" UserId="13517" Text="|rendering|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28551" PostHistoryTypeId="2" PostId="9925" RevisionGUID="6d675b37-04cb-43ed-95f6-271995ffd6b6" CreationDate="2020-06-09T07:45:10.237" UserId="13095" Text="&gt; Digital painting and raster graphics software like Krita and Photoshop have a canvas where you can paint with brushes. From a programming perspective, how is this canvas rendered?&#xD;&#xA;&#xD;&#xA;I don't have access to the code of the programs you mentioned, so I can't tell how exactly they did this since there are usually multiple ways to solve a programming problem. However, I guess everybody with some graphics programming experience will immediately think of the solution @lightxbulb already mentioned in his comment because it is the simplest one.&#xD;&#xA;&#xD;&#xA;Textures are just an array of color values and a graphics API like OpenGL expects you to upload them as such. So a possible solution would be to represent your modifiable canvas in memory in this form too. Every time a modification is made, you find the affected pixels in your array, adjust their color values, and upload the updated canvas as texture (or update the already existing one). Then you just draw a fullscreen (or any other size you like) quad and attach the texture to it. Simple as that.&#xD;&#xA;&#xD;&#xA;&gt; Can it be included on a graphics pipeline like OpenGL?&#xD;&#xA;&#xD;&#xA;As you might already guess: Yes, you can do that. If you use the texture approach, you can do anything you can do with an ordinary texture in the graphics pipeline. If your intention is to include a canvas in a 3d game, then keep in mind that finding the pixel that should be modified gets a little bit more complicated due to the perspective projection. However, the rendering process stays the same." ContentLicense="CC BY-SA 4.0" />
  <row Id="28552" PostHistoryTypeId="2" PostId="9926" RevisionGUID="e90f84ab-0687-4cca-a285-8534a94289fb" CreationDate="2020-06-09T12:32:02.030" UserId="13522" Text="I'm trying to create some graphic functions for a ZX Spectrum (Z80) machine in assembler. I already have the basics except for the arc.&#xD;&#xA;&#xD;&#xA;I need a fast algorithm to draw an arc, ideally one that uses integer or fixed point math.&#xD;&#xA;&#xD;&#xA;I know there must be some way to draw an arc using the Bresenham's circle algorithm but I'm unable to find concrete info about it, there are sentences like &quot;set the pixels only if they fall into the wanted interval&quot; but I have no clue on how to determine if the pixels fall within it.&#xD;&#xA;&#xD;&#xA;I only miss how to determine if a pixel lies in the arc, if the algorithm were completely linear (start at 0º and sweep to 360º) it would be easy to skip pixels until the start point and then continue drawing until the last point is reached, but the Bresenham's algorithm is drawn in octants simultaneously so I have no idea on how to do it. Also I had the idea to compute the circle's area in pixels and then divide 360 by the number of pixels to know how many degrees a pixel represents so I could use the start and end angle and check if a pixel must be drawn or not, but it does not work as the computed area is ideal and not the real one that Bresenham's algorithm generates.&#xD;&#xA;&#xD;&#xA;As input data I have the circle's center and radius and the start and end points of the arc in the circle (I can derive the start and end angle from those, no problem), I'm not tied to anything so any other algorithm is welcome, no need to be specifically for the spectrum, just any assembler algorithm to draw an arc using integer or fixed point math  will be enough even if I need different info (like the three point arc algorithm).&#xD;&#xA;&#xD;&#xA;Cheers." ContentLicense="CC BY-SA 4.0" />
  <row Id="28553" PostHistoryTypeId="1" PostId="9926" RevisionGUID="e90f84ab-0687-4cca-a285-8534a94289fb" CreationDate="2020-06-09T12:32:02.030" UserId="13522" Text="Using Bresenham's circle algorithm (or another alternative algorithm) to draw an arc" ContentLicense="CC BY-SA 4.0" />
  <row Id="28554" PostHistoryTypeId="3" PostId="9926" RevisionGUID="e90f84ab-0687-4cca-a285-8534a94289fb" CreationDate="2020-06-09T12:32:02.030" UserId="13522" Text="|drawing|assembly|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28555" PostHistoryTypeId="5" PostId="9923" RevisionGUID="2c09fad0-487a-4d14-b97e-8a8ca891c3e1" CreationDate="2020-06-09T12:36:44.847" UserId="13517" Comment="added 123 characters in body" Text="Digital painting and raster graphics software like Krita and Photoshop have a canvas where you can paint with brushes. From a programming perspective, how is this canvas rendered? Can it be included on a graphics pipeline like OpenGL?&#xD;&#xA;&#xD;&#xA;One proposed solution is to represent the canvas as a texture. If you know more possible solutions let me know. Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="28556" PostHistoryTypeId="2" PostId="9927" RevisionGUID="253ba0c8-55a7-40bd-bea7-b1dd43144cf3" CreationDate="2020-06-09T16:48:17.420" UserId="13524" Text="I am reading &quot;Image Processing and Analysis&quot; by Chan and Shen, c 2005 SIAM. They introduce some notation I'm not 100% sure how to interpret:&#xD;&#xA;&#xD;&#xA;$$ u_0(x)=u(x)+n(x),  x=(x_1,x_2) \in \Omega $$&#xD;&#xA;&#xD;&#xA;They state $u_0$ represents a noisy image, $u$ is the clean image and $n$ is Gaussian white noise. I assume that $ x=(x_1,x_2) $ is meant to convey that x is a two-dimensional vector indexing both image height and width. I don't know how to interpret $\Omega$. Is it meant to denote the entire image index range? " ContentLicense="CC BY-SA 4.0" />
  <row Id="28557" PostHistoryTypeId="1" PostId="9927" RevisionGUID="253ba0c8-55a7-40bd-bea7-b1dd43144cf3" CreationDate="2020-06-09T16:48:17.420" UserId="13524" Text="Interpreting Image Processing Math Equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="28558" PostHistoryTypeId="3" PostId="9927" RevisionGUID="253ba0c8-55a7-40bd-bea7-b1dd43144cf3" CreationDate="2020-06-09T16:48:17.420" UserId="13524" Text="|image-processing|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28559" PostHistoryTypeId="2" PostId="9928" RevisionGUID="18967ca8-5a44-4a70-a82b-fc8c97141c67" CreationDate="2020-06-09T16:52:35.717" UserId="13515" Text="I managed to figure it out. A coworker told me that I was misinterpreting the documentation.&#xD;&#xA;```layout(max_vertices=3, max_primitives=1) out;```&#xD;&#xA;actually means max_vertices and max_primitives per workgroup, not per shader invocation. So I was always only outputting a single triangle, regardless of what I set ```local_size_x``` to.&#xD;&#xA;&#xD;&#xA;Changing the values to proper numbers resulted in a proper rendering.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28560" PostHistoryTypeId="2" PostId="9929" RevisionGUID="d81efd2a-904d-4ed2-ac46-c30ed65bc726" CreationDate="2020-06-09T18:30:44.320" UserId="13370" Text="It sounds exactly like that!&#xD;&#xA;&#xD;&#xA;* $\Omega$ is the image domain, it can be either discrete or continuous. No idea how it is defined in that particular book.&#xD;&#xA;* $x=(x_1, x_2)$ are the coordinates&#xD;&#xA;* $u_0, u, n$ are functions that return intensity values at the given location $x$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28561" PostHistoryTypeId="5" PostId="9929" RevisionGUID="27a14e1a-99cd-44c9-9ac5-406527523ad5" CreationDate="2020-06-09T19:07:03.113" UserId="13370" Comment="added 9 characters in body" Text="It sounds exactly like that!&#xD;&#xA;&#xD;&#xA;* $\Omega$ is the image domain, it can be either discrete or continuous. No idea how it is defined in that particular book.&#xD;&#xA;* $x=(x_1, x_2)$ are the 2D image coordinates&#xD;&#xA;* $u_0, u, n$ are functions that return intensity values at the given location $x$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28562" PostHistoryTypeId="2" PostId="9930" RevisionGUID="c1bd0508-2e86-46cd-9af6-9efcb2d8c78d" CreationDate="2020-06-10T10:27:28.267" UserId="13305" Text="Given a matrix $D \in \mathbb{R}^{3N\times k}$ where each column is $D_i$, just calculate $D^TS_i$ to get weights. This is equivalent to calculating dot products between each PCA basis and $S_i$. What is done here is you project $S_i$ onto each orthogonal basis $D_i$, and calculate the (length of the projected vector) times (the length of the basis), so you are basically calculating the required contribution of each basis to construct the given $S_i$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28563" PostHistoryTypeId="12" PostId="9930" RevisionGUID="1b3362ac-5dbe-4303-8f55-4cd931448641" CreationDate="2020-06-10T10:30:41.173" UserId="13305" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13305,&quot;DisplayName&quot;:&quot;mz kt&quot;}]}" />
  <row Id="28564" PostHistoryTypeId="5" PostId="9930" RevisionGUID="76ba1782-26d9-460b-b51c-a161430bc065" CreationDate="2020-06-10T10:39:21.743" UserId="13305" Comment="added 400 characters in body" Text="Given a matrix $D \in \mathbb{R}^{3N\times k}$ where each column is normalized $D_i$, You can get $W = D^TS_i$, and later it can be used to reconstruct the shape with $S_i = DW$ (With some error if you truncated some basis). The acquisition of weights is equivalent to calculating dot products between each PCA basis and $S_i$. What is done here is you project $S_i$ onto each orthogonal basis $D_i$, and calculate the length of the projected vector, so you are basically calculating the required contribution of each basis to construct the given $S_i$.&#xD;&#xA;&#xD;&#xA;If you are using unnormalized PCA basis, you can decompose the unnormalized PCA basis matrix into a diagonal matrix an an orthonormal matrix (Say, $\Lambda D$), then use a similar approach to obtain the contribution of each basis. In this case, you'll have to use $\Lambda^{-1}D^T$ instead of $D^T$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28565" PostHistoryTypeId="13" PostId="9930" RevisionGUID="4de3d142-34ed-44cf-b5b2-d0dfc3296c88" CreationDate="2020-06-10T10:39:27.040" UserId="13305" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13305,&quot;DisplayName&quot;:&quot;mz kt&quot;}]}" />
  <row Id="28566" PostHistoryTypeId="2" PostId="9931" RevisionGUID="fc90856f-ff12-4d40-b7cb-efdb9182bed8" CreationDate="2020-06-10T11:10:32.843" UserId="7028" Text="In the [Unreal Engine 5][1] tech demo, they mention, that there is no need to manually generate LOD levels for each model, because the on the fly LOD system will generate polygons from the original mesh, which are around one pixel in size.&#xD;&#xA;&#xD;&#xA;I tried to search for &quot;on the fly LOD&quot;, but I was not able to find anything useful.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.unrealengine.com/en-US/blog/a-first-look-at-unreal-engine-5" ContentLicense="CC BY-SA 4.0" />
  <row Id="28567" PostHistoryTypeId="1" PostId="9931" RevisionGUID="fc90856f-ff12-4d40-b7cb-efdb9182bed8" CreationDate="2020-06-10T11:10:32.843" UserId="7028" Text="How does on the fly LOD work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28568" PostHistoryTypeId="3" PostId="9931" RevisionGUID="fc90856f-ff12-4d40-b7cb-efdb9182bed8" CreationDate="2020-06-10T11:10:32.843" UserId="7028" Text="|algorithm|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28569" PostHistoryTypeId="2" PostId="9932" RevisionGUID="1d05aedc-d159-4427-8edf-ff6df3aebd8a" CreationDate="2020-06-10T12:23:22.380" UserId="13370" Text="No idea about DirectX, but in OpenGL the buffers are just [a block of binary data](https://en.wikipedia.org/wiki/Vertex_buffer_object) so you can easily load and save them.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In any 3D framework, changing the object position to achieve a different relative arrangement of a scene is not done through the *view* matrix (that represents the camera position and viewing direction) but through the *model* matrix of each model. Note that the vertex and index buffers stay unaffected by matrix transformations, that is the main benefit of such pipelines.&#xD;&#xA;&#xD;&#xA;Perhaps you could do your study with less effort using a 3D game engine, to list just a few:&#xD;&#xA;&#xD;&#xA;* https://godotengine.org/&#xD;&#xA;* https://www.unrealengine.com/&#xD;&#xA;* https://unity.com/&#xD;&#xA;&#xD;&#xA;I am not aware that any of them would support loading the raw buffers straight away, but they can load [OBJ files](https://en.wikipedia.org/wiki/Wavefront_.obj_file). OBJ is one of the oldest text-based 3D model formats. It has a simple structure, so you can easily convert your buffer data to an OBJ file." ContentLicense="CC BY-SA 4.0" />
  <row Id="28572" PostHistoryTypeId="2" PostId="9934" RevisionGUID="312bec9e-697e-41bd-abfe-a12a23d791f4" CreationDate="2020-06-10T16:42:35.930" UserId="13524" Text="This morning I was thinking about how I would tackle the problem:&#xD;&#xA;&#xD;&#xA; 1. Draw a circle of radius R and origin (H, K)&#xD;&#xA; 2. Using integer math&#xD;&#xA; 3. No anti-aliasing&#xD;&#xA; 4. Speed is important&#xD;&#xA;&#xD;&#xA;The first thing I noticed is if we assume (H, K) is (0,0), there is 8-way symmetry in the problem. That means if I find a pixel (x, y) between 0° and 45°, I already know 7 more pixel locations:&#xD;&#xA;&#xD;&#xA; - pixel (x, y) is between 0° and 45°&#xD;&#xA; - pixel (y, x) is between 45° and 90°&#xD;&#xA; - pixel (-y, x) is between 90° and 135°&#xD;&#xA; - pixel (-x, y) is between 135° and 180°&#xD;&#xA; - pixel (-x, -y) is between 180° and 225°&#xD;&#xA; - pixel (-y, -x) is between 225° and 270°&#xD;&#xA; - pixel (y, -x) is between 270° and 315°&#xD;&#xA; - pixel (x, -y) is between 315° and 360°&#xD;&#xA;&#xD;&#xA;Because the tangent line to the circle between 0° and 45° has as slope less than -1, there is exactly 1 integer x value for any y value in that range. We find the x values for all $ y \in [0, \frac{\sqrt{2}}{2} R ]$, plot them using symmetry, and we're done.&#xD;&#xA;&#xD;&#xA;In Python it the algorithm would look like this:&#xD;&#xA;&#xD;&#xA;``` python&#xD;&#xA;    def circle(h, k, r):&#xD;&#xA;        p=round( r* math.sqrt(2)/2 ) # find the 45 degree value, use enough precision for the highest expected radius&#xD;&#xA;        r2=r**2 # square r&#xD;&#xA;        &#xD;&#xA;        for y in range(0, p+1): &#xD;&#xA;            x=round(math.sqrt(r2 - y*y )) # this can be replaced with a fast integer square root function&#xD;&#xA;            setPixel(h+x, k+y)&#xD;&#xA;            setPixel(h+y, k+x)&#xD;&#xA;            setPixel(h-y, k+x)&#xD;&#xA;            setPixel(h-x, k+y)&#xD;&#xA;            setPixel(h-x, k-y)&#xD;&#xA;            setPixel(h-y, k-x)&#xD;&#xA;            setPixel(h+y, k-x)&#xD;&#xA;            setPixel(h+x, k-y)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28573" PostHistoryTypeId="5" PostId="9934" RevisionGUID="5de76010-3926-4e5d-b218-e633355a21e3" CreationDate="2020-06-10T18:53:34.297" UserId="13524" Comment="I replaced the square root in the loop with a little algebra." Text="This morning I was thinking about how I would tackle the problem:&#xD;&#xA;&#xD;&#xA; 1. Draw a circle of radius R and origin (H, K)&#xD;&#xA; 2. Using integer math&#xD;&#xA; 3. No anti-aliasing&#xD;&#xA; 4. Speed is important&#xD;&#xA;&#xD;&#xA;The first thing I noticed is if we assume (H, K) is (0,0), there is 8-way symmetry in the problem. That means if I find a pixel (x, y) between 0° and 45°, I already know 7 more pixel locations:&#xD;&#xA;&#xD;&#xA; - pixel (x, y) is between 0° and 45°&#xD;&#xA; - pixel (y, x) is between 45° and 90°&#xD;&#xA; - pixel (-y, x) is between 90° and 135°&#xD;&#xA; - pixel (-x, y) is between 135° and 180°&#xD;&#xA; - pixel (-x, -y) is between 180° and 225°&#xD;&#xA; - pixel (-y, -x) is between 225° and 270°&#xD;&#xA; - pixel (y, -x) is between 270° and 315°&#xD;&#xA; - pixel (x, -y) is between 315° and 360°&#xD;&#xA;&#xD;&#xA;Because the tangent line to the circle between 0° and 45° has as slope less than -1, there is exactly 1 integer x value for any y value in that range. We find the x values for all $ y \in [0, \frac{\sqrt{2}}{2} R ]$, plot them using symmetry, and we're done.&#xD;&#xA;&#xD;&#xA;In Python it the algorithm would look like this:&#xD;&#xA;&#xD;&#xA;``` python&#xD;&#xA;def circle(h, k, r):&#xD;&#xA;    d=round( r* math.sqrt(2)/2 ) # find the 45 degree value&#xD;&#xA;    r2=r**2 # square r&#xD;&#xA;    p=r&#xD;&#xA;    &#xD;&#xA;    for y in range(0, d+1): &#xD;&#xA;#####   x=round(math.sqrt(r2 - y*y ))&#xD;&#xA;        q=(r2-p*p-y*y)&#xD;&#xA;        if( q &lt; -p):&#xD;&#xA;            p-=1&#xD;&#xA;        x=p&#xD;&#xA;        setPixel(h+x, k+y)&#xD;&#xA;        setPixel(h+y, k+x)&#xD;&#xA;        setPixel(h-y, k+x)&#xD;&#xA;        setPixel(h-x, k+y)&#xD;&#xA;        setPixel(h-x, k-y)&#xD;&#xA;        setPixel(h-y, k-x)&#xD;&#xA;        setPixel(h+y, k-x)&#xD;&#xA;        setPixel(h+x, k-y)&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28574" PostHistoryTypeId="5" PostId="9926" RevisionGUID="c3502598-3f5d-4387-bc80-ad0a5939dee6" CreationDate="2020-06-10T20:17:48.827" UserId="13522" Comment="added 3796 characters in body" Text="I'm trying to create some graphic functions for a ZX Spectrum (Z80) machine in assembler. I already have the basics except for the arc.&#xD;&#xA;&#xD;&#xA;I need a fast algorithm to draw an arc, ideally one that uses integer or fixed point math.&#xD;&#xA;&#xD;&#xA;I know there must be some way to draw an arc using the Bresenham's circle algorithm but I'm unable to find concrete info about it, there are sentences like &quot;set the pixels only if they fall into the wanted interval&quot; but I have no clue on how to determine if the pixels fall within it.&#xD;&#xA;&#xD;&#xA;I only miss how to determine if a pixel lies in the arc, if the algorithm were completely linear (start at 0º and sweep to 360º) it would be easy to skip pixels until the start point and then continue drawing until the last point is reached, but the Bresenham's algorithm is drawn in octants simultaneously so I have no idea on how to do it. Also I had the idea to compute the circle's area in pixels and then divide 360 by the number of pixels to know how many degrees a pixel represents so I could use the start and end angle and check if a pixel must be drawn or not, but it does not work as the computed area is ideal and not the real one that Bresenham's algorithm generates.&#xD;&#xA;&#xD;&#xA;As input data I have the circle's center and radius and the start and end points of the arc in the circle (I can derive the start and end angle from those, no problem), I'm not tied to anything so any other algorithm is welcome, no need to be specifically for the spectrum, just any assembler algorithm to draw an arc using integer or fixed point math  will be enough even if I need different info (like the three point arc algorithm).&#xD;&#xA;&#xD;&#xA;Cheers.&#xD;&#xA;&#xD;&#xA;*EDIT*: I already have the circle's implementation, in C and assembler, I only need to determine what pixels of the circle belong to the arc to skip the ones that doesn't belong.&#xD;&#xA;&#xD;&#xA;Here is the assembler implementation:&#xD;&#xA;&#xD;&#xA;       ;--------------CIRCLE ROUTINE&#xD;&#xA;       ; Plot function isn't included as it's very specific for the ZX Spectrum&#xD;&#xA;       ;because of the way the video memory is mapped and it's irrelevant to the question&#xD;&#xA;&#xD;&#xA;		CENTER_X: .defb 0        ;Input parameter&#xD;&#xA;		CENTER_Y: .defb 0        ;Input parameter&#xD;&#xA;		RADII: .defb 0           ;Input parameter&#xD;&#xA;&#xD;&#xA;		CIRCLE_D: .defw 0        ;Temp variable&#xD;&#xA;		CIRCLE_D_SIGN: .defb 0   ;Temp variable&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		Draw_Circle:			;D = X, E = Y&#xD;&#xA;&#xD;&#xA;		LD DE, 5&#xD;&#xA;		LD A, (RADII)&#xD;&#xA;		LD L, A&#xD;&#xA;		LD H, 0&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		OR A&#xD;&#xA;		ADD HL, HL &#xD;&#xA;		ADD HL, HL&#xD;&#xA;		EX DE, HL&#xD;&#xA;		SBC HL, DE&#xD;&#xA;		JP P, POS_VAL&#xD;&#xA;		LD A, -1&#xD;&#xA;		LD (CIRCLE_D_SIGN), A&#xD;&#xA;&#xD;&#xA;		;NEG HL&#xD;&#xA;		xor a&#xD;&#xA;		sub l&#xD;&#xA;		ld l,a&#xD;&#xA;		sbc a,a&#xD;&#xA;		sub h&#xD;&#xA;		ld h,a&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		LD C, 4&#xD;&#xA;		CALL HL_Div_C&#xD;&#xA;&#xD;&#xA;		;NEG HL&#xD;&#xA;		xor a&#xD;&#xA;		sub l&#xD;&#xA;		ld l,a&#xD;&#xA;		sbc a,a&#xD;&#xA;		sub h&#xD;&#xA;		ld h,a&#xD;&#xA;&#xD;&#xA;		JR D_DONE&#xD;&#xA;		POS_VAL:&#xD;&#xA;		LD A, 1&#xD;&#xA;		LD (CIRCLE_D_SIGN), A&#xD;&#xA;		LD C, 4&#xD;&#xA;		CALL HL_Div_C&#xD;&#xA;		D_DONE:&#xD;&#xA;		LD (CIRCLE_D), HL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		LD D, 0&#xD;&#xA;		LD A, (RADII)&#xD;&#xA;		LD E, A&#xD;&#xA;&#xD;&#xA;		CIRCLE_LOOP:&#xD;&#xA;&#xD;&#xA;		LD A, (CENTER_X)&#xD;&#xA;		LD H, A&#xD;&#xA;		LD A, (CENTER_Y)&#xD;&#xA;		LD L, A&#xD;&#xA;&#xD;&#xA;		;seq x.X/y.Y&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		ADD A, D				;x&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		ADD A, E				;y&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		ADD A, D				;x&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		SUB A, E				;y&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		SUB A, D				;x&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		ADD A, E				;y&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		SUB A, D				;x&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		SUB A, E				;y&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;		;seq x.Y/y.X&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		ADD A, E				;y&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		ADD A, D				;x&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		ADD A, E				;y&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		SUB A, D				;x&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		SUB A, E				;y&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		ADD A, D				;x&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH HL&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;		POP HL&#xD;&#xA;&#xD;&#xA;		LD A, H				;center_x&#xD;&#xA;		SUB A, E				;y&#xD;&#xA;		LD C, A				;point_x&#xD;&#xA;		LD A, L				;center_y&#xD;&#xA;		SUB A, D				;x&#xD;&#xA;		LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;		PUSH DE&#xD;&#xA;		CALL Plot&#xD;&#xA;		POP DE&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		LD HL, (CIRCLE_D)				;if (d &lt; 0)&#xD;&#xA;		LD A, (CIRCLE_D_SIGN)&#xD;&#xA;		CP -1&#xD;&#xA;		JR Z, NEGATIVE_D&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		POSITIVE_D:						;no&#xD;&#xA;		PUSH DE&#xD;&#xA;		PUSH HL&#xD;&#xA;		LD L, D&#xD;&#xA;		LD H, 0&#xD;&#xA;		LD D, 0&#xD;&#xA;		XOR A&#xD;&#xA;		SBC HL, DE&#xD;&#xA;		ADD HL, HL&#xD;&#xA;		INC HL&#xD;&#xA;		POP DE&#xD;&#xA;		ADD HL, DE&#xD;&#xA;		POP DE&#xD;&#xA;&#xD;&#xA;		LD A, H							;is negative?&#xD;&#xA;		CP #FF&#xD;&#xA;		JP NZ, POS_VAL_POS&#xD;&#xA;		LD A, -1					    ;yes&#xD;&#xA;		LD (CIRCLE_D_SIGN), A&#xD;&#xA;		JP DEC_Y&#xD;&#xA;&#xD;&#xA;		POS_VAL_POS:					;no&#xD;&#xA;		LD A, 1&#xD;&#xA;		LD (CIRCLE_D_SIGN), A&#xD;&#xA;&#xD;&#xA;		DEC_Y:&#xD;&#xA;		DEC E&#xD;&#xA;		JP STORE_D&#xD;&#xA;&#xD;&#xA;		NEGATIVE_D:&#xD;&#xA;		PUSH HL&#xD;&#xA;		LD L, D&#xD;&#xA;		LD H,0&#xD;&#xA;		ADD HL, HL&#xD;&#xA;		INC HL&#xD;&#xA;&#xD;&#xA;		LD A, D						;2 * x&#xD;&#xA;		ADD A, A&#xD;&#xA;		INC A						; + 1&#xD;&#xA;&#xD;&#xA;		LD C, A&#xD;&#xA;		LD B, 0&#xD;&#xA;		POP HL&#xD;&#xA;		ADD HL, BC					;d = d +&#xD;&#xA;&#xD;&#xA;		LD A, H						;is negative?&#xD;&#xA;		CP #FF&#xD;&#xA;		JP NZ, POS_VAL_NEG&#xD;&#xA;&#xD;&#xA;		LD A, -1					;yes&#xD;&#xA;		LD (CIRCLE_D_SIGN), A&#xD;&#xA;		JP STORE_D&#xD;&#xA;&#xD;&#xA;		POS_VAL_NEG:&#xD;&#xA;		LD A, 1					;no&#xD;&#xA;		LD (CIRCLE_D_SIGN), A&#xD;&#xA;&#xD;&#xA;		STORE_D:&#xD;&#xA;		INC D&#xD;&#xA;		LD (CIRCLE_D), HL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		TEST_LOOP:&#xD;&#xA;		LD A, E&#xD;&#xA;		CP D&#xD;&#xA;		JP P, CIRCLE_LOOP&#xD;&#xA;&#xD;&#xA;		RET" ContentLicense="CC BY-SA 4.0" />
  <row Id="28576" PostHistoryTypeId="5" PostId="9926" RevisionGUID="dcf11bed-a827-44a1-86a6-7b1bd381f67c" CreationDate="2020-06-10T22:33:44.597" UserDisplayName="user7220" Comment="changed the typography a bit" Text="I'm trying to create some graphic functions for a ZX Spectrum (Z80) machine in assembler. I already have the basics except for the arc.&#xD;&#xA;&#xD;&#xA;I need a fast algorithm to draw an arc, ideally one that uses integer or fixed point math.&#xD;&#xA;&#xD;&#xA;I know there must be some way to draw an arc using the Bresenham's circle algorithm but I'm unable to find concrete info about it, there are sentences like &quot;set the pixels only if they fall into the wanted interval&quot; but I have no clue on how to determine if the pixels fall within it.&#xD;&#xA;&#xD;&#xA;I only miss how to determine if a pixel lies in the arc, if the algorithm were completely linear (start at 0º and sweep to 360º) it would be easy to skip pixels until the start point and then continue drawing until the last point is reached, but the Bresenham's algorithm is drawn in octants simultaneously so I have no idea on how to do it. Also I had the idea to compute the circle's area in pixels and then divide 360 by the number of pixels to know how many degrees a pixel represents so I could use the start and end angle and check if a pixel must be drawn or not, but it does not work as the computed area is ideal and not the real one that Bresenham's algorithm generates.&#xD;&#xA;&#xD;&#xA;As input data I have the circle's center and radius and the start and end points of the arc in the circle (I can derive the start and end angle from those, no problem), I'm not tied to anything so any other algorithm is welcome, no need to be specifically for the spectrum, just any assembler algorithm to draw an arc using integer or fixed point math  will be enough even if I need different info (like the three point arc algorithm).&#xD;&#xA;&#xD;&#xA;Cheers.&#xD;&#xA;&#xD;&#xA;*EDIT*: I already have the circle's implementation, in C and assembler, I only need to determine what pixels of the circle belong to the arc to skip the ones that doesn't belong.&#xD;&#xA;&#xD;&#xA;Here is the assembler implementation:&#xD;&#xA;&#xD;&#xA;    ;--------------CIRCLE ROUTINE&#xD;&#xA;    ; Plot function isn't included as it's very specific for the ZX Spectrum&#xD;&#xA;    ;because of the way the video memory is mapped and it's irrelevant to the question&#xD;&#xA;&#xD;&#xA;	CENTER_X: .defb 0        ;Input parameter&#xD;&#xA;	CENTER_Y: .defb 0        ;Input parameter&#xD;&#xA;	RADII: .defb 0           ;Input parameter&#xD;&#xA;&#xD;&#xA;	CIRCLE_D: .defw 0        ;Temp variable&#xD;&#xA;	CIRCLE_D_SIGN: .defb 0   ;Temp variable&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	Draw_Circle:			;D = X, E = Y&#xD;&#xA;&#xD;&#xA;	LD DE, 5&#xD;&#xA;	LD A, (RADII)&#xD;&#xA;	LD L, A&#xD;&#xA;	LD H, 0&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	OR A&#xD;&#xA;	ADD HL, HL &#xD;&#xA;	ADD HL, HL&#xD;&#xA;	EX DE, HL&#xD;&#xA;	SBC HL, DE&#xD;&#xA;	JP P, POS_VAL&#xD;&#xA;	LD A, -1&#xD;&#xA;	LD (CIRCLE_D_SIGN), A&#xD;&#xA;&#xD;&#xA;	;NEG HL&#xD;&#xA;	xor a&#xD;&#xA;	sub l&#xD;&#xA;	ld l,a&#xD;&#xA;	sbc a,a&#xD;&#xA;	sub h&#xD;&#xA;	ld h,a&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	LD C, 4&#xD;&#xA;	CALL HL_Div_C&#xD;&#xA;&#xD;&#xA;	;NEG HL&#xD;&#xA;	xor a&#xD;&#xA;	sub l&#xD;&#xA;	ld l,a&#xD;&#xA;	sbc a,a&#xD;&#xA;	sub h&#xD;&#xA;	ld h,a&#xD;&#xA;&#xD;&#xA;	JR D_DONE&#xD;&#xA;	POS_VAL:&#xD;&#xA;	LD A, 1&#xD;&#xA;	LD (CIRCLE_D_SIGN), A&#xD;&#xA;	LD C, 4&#xD;&#xA;	CALL HL_Div_C&#xD;&#xA;	D_DONE:&#xD;&#xA;	LD (CIRCLE_D), HL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	LD D, 0&#xD;&#xA;	LD A, (RADII)&#xD;&#xA;	LD E, A&#xD;&#xA;&#xD;&#xA;	CIRCLE_LOOP:&#xD;&#xA;&#xD;&#xA;	LD A, (CENTER_X)&#xD;&#xA;	LD H, A&#xD;&#xA;	LD A, (CENTER_Y)&#xD;&#xA;	LD L, A&#xD;&#xA;&#xD;&#xA;	;seq x.X/y.Y&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	ADD A, D				;x&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	ADD A, E				;y&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	ADD A, D				;x&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	SUB A, E				;y&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	SUB A, D				;x&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	ADD A, E				;y&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	SUB A, D				;x&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	SUB A, E				;y&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;	;seq x.Y/y.X&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	ADD A, E				;y&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	ADD A, D				;x&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	ADD A, E				;y&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	SUB A, D				;x&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	SUB A, E				;y&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	ADD A, D				;x&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH HL&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;	POP HL&#xD;&#xA;&#xD;&#xA;	LD A, H				;center_x&#xD;&#xA;	SUB A, E				;y&#xD;&#xA;	LD C, A				;point_x&#xD;&#xA;	LD A, L				;center_y&#xD;&#xA;	SUB A, D				;x&#xD;&#xA;	LD B, A				;point_y&#xD;&#xA;&#xD;&#xA;	PUSH DE&#xD;&#xA;	CALL Plot&#xD;&#xA;	POP DE&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	LD HL, (CIRCLE_D)				;if (d &lt; 0)&#xD;&#xA;	LD A, (CIRCLE_D_SIGN)&#xD;&#xA;	CP -1&#xD;&#xA;	JR Z, NEGATIVE_D&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	POSITIVE_D:						;no&#xD;&#xA;	PUSH DE&#xD;&#xA;	PUSH HL&#xD;&#xA;	LD L, D&#xD;&#xA;	LD H, 0&#xD;&#xA;	LD D, 0&#xD;&#xA;	XOR A&#xD;&#xA;	SBC HL, DE&#xD;&#xA;	ADD HL, HL&#xD;&#xA;	INC HL&#xD;&#xA;	POP DE&#xD;&#xA;	ADD HL, DE&#xD;&#xA;	POP DE&#xD;&#xA;&#xD;&#xA;	LD A, H							;is negative?&#xD;&#xA;	CP #FF&#xD;&#xA;	JP NZ, POS_VAL_POS&#xD;&#xA;	LD A, -1					    ;yes&#xD;&#xA;	LD (CIRCLE_D_SIGN), A&#xD;&#xA;	JP DEC_Y&#xD;&#xA;&#xD;&#xA;	POS_VAL_POS:					;no&#xD;&#xA;	LD A, 1&#xD;&#xA;	LD (CIRCLE_D_SIGN), A&#xD;&#xA;&#xD;&#xA;	DEC_Y:&#xD;&#xA;	DEC E&#xD;&#xA;	JP STORE_D&#xD;&#xA;&#xD;&#xA;	NEGATIVE_D:&#xD;&#xA;	PUSH HL&#xD;&#xA;	LD L, D&#xD;&#xA;	LD H,0&#xD;&#xA;	ADD HL, HL&#xD;&#xA;	INC HL&#xD;&#xA;&#xD;&#xA;	LD A, D						;2 * x&#xD;&#xA;	ADD A, A&#xD;&#xA;	INC A						; + 1&#xD;&#xA;&#xD;&#xA;	LD C, A&#xD;&#xA;	LD B, 0&#xD;&#xA;	POP HL&#xD;&#xA;	ADD HL, BC					;d = d +&#xD;&#xA;&#xD;&#xA;	LD A, H						;is negative?&#xD;&#xA;	CP #FF&#xD;&#xA;	JP NZ, POS_VAL_NEG&#xD;&#xA;&#xD;&#xA;	LD A, -1					;yes&#xD;&#xA;	LD (CIRCLE_D_SIGN), A&#xD;&#xA;	JP STORE_D&#xD;&#xA;&#xD;&#xA;	POS_VAL_NEG:&#xD;&#xA;	LD A, 1					;no&#xD;&#xA;	LD (CIRCLE_D_SIGN), A&#xD;&#xA;&#xD;&#xA;	STORE_D:&#xD;&#xA;	INC D&#xD;&#xA;	LD (CIRCLE_D), HL&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	TEST_LOOP:&#xD;&#xA;	LD A, E&#xD;&#xA;	CP D&#xD;&#xA;	JP P, CIRCLE_LOOP&#xD;&#xA;&#xD;&#xA;	RET" ContentLicense="CC BY-SA 4.0" />
  <row Id="28577" PostHistoryTypeId="24" PostId="9926" RevisionGUID="dcf11bed-a827-44a1-86a6-7b1bd381f67c" CreationDate="2020-06-10T22:33:44.597" Comment="Proposed by 7220 approved by 13522 edit id of 530" ContentLicense="CC BY-SA 4.0" />
  <row Id="28578" PostHistoryTypeId="2" PostId="9935" RevisionGUID="d8e39d79-78cc-40ec-8779-06786e3c53c5" CreationDate="2020-06-11T10:11:07.303" UserId="2372" Text="I am trying to get a segment closest point on a surface and display a circle (or sphere in this case) at that position.&#xD;&#xA;&#xD;&#xA;I actually get the correct position but I can't get a uniform sphere based on the computed data.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here's the associated code I use to find the intersection point and draw the sphere.&#xD;&#xA;&#xD;&#xA;    float3 a = from;&#xD;&#xA;    float3 b = to;&#xD;&#xA;    float3 c = worldPosition;&#xD;&#xA;    &#xD;&#xA;    float3  ab = b - a;&#xD;&#xA;    float t = dot(c - a, ab) / dot(ab, ab);&#xD;&#xA;    float3 point = a + saturate(t) * ab;&#xD;&#xA;    &#xD;&#xA;    return length(point - worldPosition) - radius;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fdhyQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28579" PostHistoryTypeId="1" PostId="9935" RevisionGUID="d8e39d79-78cc-40ec-8779-06786e3c53c5" CreationDate="2020-06-11T10:11:07.303" UserId="2372" Text="Closest sphere on segment" ContentLicense="CC BY-SA 4.0" />
  <row Id="28580" PostHistoryTypeId="3" PostId="9935" RevisionGUID="d8e39d79-78cc-40ec-8779-06786e3c53c5" CreationDate="2020-06-11T10:11:07.303" UserId="2372" Text="|shader|glsl|mathematics|hlsl|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28581" PostHistoryTypeId="2" PostId="9936" RevisionGUID="8be5213e-08d1-47c3-b933-d3d5daead8fb" CreationDate="2020-06-11T11:52:32.100" UserId="13370" Text="Your _actual_ result is correct in terms of what you can achieve in a single-pass with a fragment shader. It calculates the distance of the fragment's world position to the line segment. That distance is **different for each fragment** so the stretched black ellipsoid is the correct output.&#xD;&#xA;&#xD;&#xA;A fragment shader has only local information about the current fragment being processed. You can't do more with that. Your _expected_ result requires some global knowledge about the scene, since you are searching for the **minimum distance across the whole surface**.&#xD;&#xA;&#xD;&#xA;Without any thoughts on optimization, the naive solution path should involve differential information to find local minima of the fragment-to-linesegment distance.&#xD;&#xA;&#xD;&#xA;1. Compute the raw distance field in the first pass (same as your example but no `radius` subtraction at the end.&#xD;&#xA;2. Mark the pixels with local minima in the second pass (e.g. by setting the alpha channel to 1). This will be screen-space pass. The best is to have a `rgba` float texture at output with `rgb` being fragment's world position and `a` being 1 for local minima and `0` else.&#xD;&#xA;3. Paint the black circles/spheres in a third pass (also screen-space).&#xD;&#xA;&#xD;&#xA;Having the information about the local minimum of your distance function enables you to output the right shape for around the minima in the last pass. In pseudocode:&#xD;&#xA;```lang-glsl&#xD;&#xA;vec4 worldPos = tex2D(distance_texture, frag.x, frag.y);&#xD;&#xA;if (worldPos.a &gt; 0.5) //is minimum&#xD;&#xA;    return vec3(0,0,0);&#xD;&#xA;else&#xD;&#xA;{&#xD;&#xA;    //Sample the screen-space neighborhood in larger and larger circles&#xD;&#xA;    // until a fragment with distance.a == 1 is found&#xD;&#xA;    // or until all fragments are more than radius away (in world coords).&#xD;&#xA;&#xD;&#xA;    //Minimum world space distance of any sampled fragment.&#xD;&#xA;    float minDist = 0.0;&#xD;&#xA;    int iter = 1;&#xD;&#xA;    //Search for a local minimum until all fragments are more than radius away,&#xD;&#xA;    // since then even if a local minimum gets found it will no longer produce&#xD;&#xA;    // the black shading.&#xD;&#xA;    while (minDist &lt; radius &amp;&amp; iter &lt; Math.Max(screenWidth, screenHeight))&#xD;&#xA;        minDist = sampleNeighborhood(iter++, worldPos);&#xD;&#xA;    //I am aware that the function call above checks central fragments several times.&#xD;&#xA;    //That should be of course optimized in production code.&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float sampleNeighborhood(int neigh, vec4 worldPos)&#xD;&#xA;{&#xD;&#xA;    float minDist = float.MaxValue;&#xD;&#xA;    for(int x = Math.max(0, frag.x - neigh); x &lt;= Math.Min(screenWidth, frag.x + neigh; ++x)&#xD;&#xA;        for(int y = Math.max(0, frag.y - neigh); x &lt;= Math.Min(screenHeight, frag.y + neigh; ++y)&#xD;&#xA;        {&#xD;&#xA;            float p = tex2D(distance_texture, x, y);&#xD;&#xA;            float d = distance(p.xyz, worldPos.xyz);&#xD;&#xA;            if (p.a &gt; 0.5 &amp;&amp; d &lt;= radius)&#xD;&#xA;                return vec3(0,0,0);&#xD;&#xA;            else&#xD;&#xA;                minDist = Math.min(minDist, d);&#xD;&#xA;        }&#xD;&#xA;    return minDist;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Finding the local minima in the second pass is much easier, since you only need to sample the local 3x3 neighborhood.&#xD;&#xA;&#xD;&#xA;I hope that helps you in reaching the desired rendering!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28582" PostHistoryTypeId="5" PostId="9936" RevisionGUID="d89a6650-7537-463f-811e-2564d83e5608" CreationDate="2020-06-11T11:57:58.820" UserId="13370" Comment="Improved a paragraph a bit." Text="Your _actual_ result is correct in terms of what you can achieve in a single-pass with a fragment shader. It calculates the distance of the fragment's world position to the line segment. That distance is **different for each fragment** so the stretched black ellipsoid is the correct output.&#xD;&#xA;&#xD;&#xA;A fragment shader has only local information about the current fragment being processed. You can't do more with that. Your _expected_ result requires some global knowledge about the scene, since you are searching for the **minimum distance across the whole surface**.&#xD;&#xA;&#xD;&#xA;Without any thoughts on optimization, the naive solution path should involve contextual computation of local minima of the fragment-to-linesegment distance. In order to get such context, you need to compute the distance field first and then access it to find the local minima in a separate pass.&#xD;&#xA;&#xD;&#xA;1. Compute the raw distance field in the first pass (same as your example but no `radius` subtraction at the end.&#xD;&#xA;2. Mark the pixels with local minima in the second pass (e.g. by setting the alpha channel to 1). This will be screen-space pass. The best is to have a `rgba` float texture at output with `rgb` being fragment's world position and `a` being 1 for local minima and `0` else.&#xD;&#xA;3. Paint the black circles/spheres in a third pass (also screen-space).&#xD;&#xA;&#xD;&#xA;Having the information about the local minimum of your distance function enables you to output the right shape for around the minima in the last pass. In pseudocode:&#xD;&#xA;```lang-glsl&#xD;&#xA;vec4 worldPos = tex2D(distance_texture, frag.x, frag.y);&#xD;&#xA;if (worldPos.a &gt; 0.5) //is minimum&#xD;&#xA;    return vec3(0,0,0);&#xD;&#xA;else&#xD;&#xA;{&#xD;&#xA;    //Sample the screen-space neighborhood in larger and larger circles&#xD;&#xA;    // until a fragment with distance.a == 1 is found&#xD;&#xA;    // or until all fragments are more than radius away (in world coords).&#xD;&#xA;&#xD;&#xA;    //Minimum world space distance of any sampled fragment.&#xD;&#xA;    float minDist = 0.0;&#xD;&#xA;    int iter = 1;&#xD;&#xA;    //Search for a local minimum until all fragments are more than radius away,&#xD;&#xA;    // since then even if a local minimum gets found it will no longer produce&#xD;&#xA;    // the black shading.&#xD;&#xA;    while (minDist &lt; radius &amp;&amp; iter &lt; Math.Max(screenWidth, screenHeight))&#xD;&#xA;        minDist = sampleNeighborhood(iter++, worldPos);&#xD;&#xA;    //I am aware that the function call above checks central fragments several times.&#xD;&#xA;    //That should be of course optimized in production code.&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float sampleNeighborhood(int neigh, vec4 worldPos)&#xD;&#xA;{&#xD;&#xA;    float minDist = float.MaxValue;&#xD;&#xA;    for(int x = Math.max(0, frag.x - neigh); x &lt;= Math.Min(screenWidth, frag.x + neigh; ++x)&#xD;&#xA;        for(int y = Math.max(0, frag.y - neigh); x &lt;= Math.Min(screenHeight, frag.y + neigh; ++y)&#xD;&#xA;        {&#xD;&#xA;            float p = tex2D(distance_texture, x, y);&#xD;&#xA;            float d = distance(p.xyz, worldPos.xyz);&#xD;&#xA;            if (p.a &gt; 0.5 &amp;&amp; d &lt;= radius)&#xD;&#xA;                return vec3(0,0,0);&#xD;&#xA;            else&#xD;&#xA;                minDist = Math.min(minDist, d);&#xD;&#xA;        }&#xD;&#xA;    return minDist;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Finding the local minima in the second pass is much easier, since you only need to sample the local 3x3 neighborhood.&#xD;&#xA;&#xD;&#xA;I hope that helps you in reaching the desired rendering!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28583" PostHistoryTypeId="5" PostId="9936" RevisionGUID="1702773d-2937-4c19-a913-125b06ca2ff7" CreationDate="2020-06-11T13:09:36.263" UserId="13370" Comment="Fixed the code." Text="Your _actual_ result is correct in terms of what you can achieve in a single-pass with a fragment shader. It calculates the distance of the fragment's world position to the line segment. That distance is **different for each fragment** so the stretched black ellipsoid is the correct output.&#xD;&#xA;&#xD;&#xA;A fragment shader has only local information about the current fragment being processed. You can't do more with that. Your _expected_ result requires some global knowledge about the scene, since you are searching for the **minimum distance across the whole surface**.&#xD;&#xA;&#xD;&#xA;Without any thoughts on optimization, the naive solution path should involve contextual computation of local minima of the fragment-to-linesegment distance. In order to get such context, you need to compute the distance field first and then access it to find the local minima in a separate pass.&#xD;&#xA;&#xD;&#xA;1. Compute the raw distance field in the first pass (same as your example but no `radius` subtraction at the end.&#xD;&#xA;2. Mark the pixels with local minima in the second pass (e.g. by setting the alpha channel to 1). This will be screen-space pass. The best is to have a `rgba` float texture at output with `rgb` being fragment's world position and `a` being 1 for local minima and `0` else.&#xD;&#xA;3. Paint the black circles/spheres in a third pass (also screen-space).&#xD;&#xA;&#xD;&#xA;Having the information about the local minimum of your distance function enables you to output the right shape for around the minima in the last pass. In pseudocode:&#xD;&#xA;```lang-glsl&#xD;&#xA;vec4 worldPos = tex2D(distance_texture, frag.x, frag.y);&#xD;&#xA;if (worldPos.a &gt; 0.5) //is minimum&#xD;&#xA;    return vec3(0,0,0);&#xD;&#xA;else&#xD;&#xA;{&#xD;&#xA;    //Sample the screen-space neighborhood in larger and larger circles&#xD;&#xA;    // until a fragment with distance.a == 1 is found&#xD;&#xA;    // or until all fragments are more than radius away (in world coords).&#xD;&#xA;&#xD;&#xA;    //Minimum world space distance of any sampled fragment.&#xD;&#xA;    float minDist = 0.0;&#xD;&#xA;    int iter = 1;&#xD;&#xA;    //Search for a local minimum until all fragments are more than radius away,&#xD;&#xA;    // since then even if a local minimum gets found it will no longer produce&#xD;&#xA;    // the black shading.&#xD;&#xA;    while (minDist &lt; radius &amp;&amp; minDist &gt;= 0.0 &amp;&amp; iter &lt; Math.Max(screenWidth, screenHeight))&#xD;&#xA;        minDist = sampleNeighborhood(iter++, worldPos);&#xD;&#xA;&#xD;&#xA;    if (minDist &lt; 0.0) //found a local minimum&#xD;&#xA;        return vec3(0,0,0);&#xD;&#xA;    else&#xD;&#xA;        return vec3(1,1,1); //or any other computed shading&#xD;&#xA;&#xD;&#xA;    //I am aware that the function call above checks central fragments several times.&#xD;&#xA;    //That should be of course optimized in production code.&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float sampleNeighborhood(int neigh, vec4 worldPos)&#xD;&#xA;{&#xD;&#xA;    float minDist = float.MaxValue;&#xD;&#xA;    for(int x = Math.max(0, frag.x - neigh); x &lt;= Math.Min(screenWidth, frag.x + neigh; ++x)&#xD;&#xA;        for(int y = Math.max(0, frag.y - neigh); x &lt;= Math.Min(screenHeight, frag.y + neigh; ++y)&#xD;&#xA;        {&#xD;&#xA;            float p = tex2D(distance_texture, x, y);&#xD;&#xA;            float d = distance(p.xyz, worldPos.xyz);&#xD;&#xA;            if (p.a &gt; 0.5 &amp;&amp; d &lt;= radius)&#xD;&#xA;                //Return negative distance to indicate a local minimum was found.&#xD;&#xA;                return -1.0; &#xD;&#xA;            else&#xD;&#xA;                minDist = Math.min(minDist, d);&#xD;&#xA;        }&#xD;&#xA;    return minDist;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Finding the local minima in the second pass is much easier, since you only need to sample the local 3x3 neighborhood.&#xD;&#xA;&#xD;&#xA;I hope that helps you in reaching the desired rendering!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28584" PostHistoryTypeId="2" PostId="9937" RevisionGUID="2a62e11f-4013-4036-9842-f3c9e106d8e1" CreationDate="2020-06-11T13:10:23.247" UserId="9845" Text="During radiation therapy, appropriate radiation is fired from various positions around the patient. Radiation therapy planning determines the values of the radiation at various positions. This optimization problem requires a huge matrix, whose elements are the doses deposited by unit strength beamlets at all possible positions around the patient at all the voxels of the patient volume. Thus each pair of beamlet and voxel has an entry in this matrix.&#xD;&#xA;&#xD;&#xA;The main bottleneck in radiation therapy planning is the computation of this matrix. While searching the literature, it is hard to find ideas from computer graphics (especially, rendering) being used to accelerate the computation of this matrix. Why is it so? Could it be just a lack of communication between the two communities? It appears unlikely, though. The radiation in radiation therapy is different from visible light. However, is it possible to borrow ideas from participating media rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28585" PostHistoryTypeId="1" PostId="9937" RevisionGUID="2a62e11f-4013-4036-9842-f3c9e106d8e1" CreationDate="2020-06-11T13:10:23.247" UserId="9845" Text="Accelerating dose calculation for a radiation therapy planning system" ContentLicense="CC BY-SA 4.0" />
  <row Id="28586" PostHistoryTypeId="3" PostId="9937" RevisionGUID="2a62e11f-4013-4036-9842-f3c9e106d8e1" CreationDate="2020-06-11T13:10:23.247" UserId="9845" Text="|rendering|real-time|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28587" PostHistoryTypeId="5" PostId="9937" RevisionGUID="8b850fe7-1a04-44cd-9eb1-f9dba4c87ae4" CreationDate="2020-06-11T14:11:12.330" UserId="9845" Comment="Added links to give more details." Text="During radiation therapy, appropriate radiation is fired from various positions around the patient. Radiation therapy planning determines the values of the radiation at various positions. This optimization problem requires a huge matrix, whose elements are the doses deposited by unit strength beamlets at all possible positions around the patient at all the voxels of the patient volume. Thus each pair of beamlet and voxel has an entry in this matrix.&#xD;&#xA;&#xD;&#xA;To get an idea about what algorithms can be used for dose calculation, this paper is good starting point:&#xD;&#xA;[Monte Carlo- versus pencil-beam-/collapsed-cone-dose calculation in a heterogeneous multi-layer phantom][1]&#xD;&#xA;&#xD;&#xA;To get an idea about how this matrix is subsequently used in radiation therapy, one could look at:&#xD;&#xA;[Real-Time Radiation Treatment Planning with Optimality&#xD;&#xA;Guarantees via Cluster and Bound Methods][2]&#xD;&#xA;&#xD;&#xA;The main bottleneck in radiation therapy planning is the computation of this matrix. While searching the literature, it is hard to find ideas from computer graphics (especially, rendering) being used to accelerate the computation of this matrix. Why is it so? Could it be just a lack of communication between the two communities? It appears unlikely, though. The radiation in radiation therapy is different from visible light. However, is it possible to borrow ideas from participating media rendering?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/profile/Thomas_Krieger3/publication/7938276_Monte_Carlo-_versus_pencil-beam-collapsed-cone-dose_calculation_in_a_heterogeneous_multi-layer_phantom/links/544a1ed50cf244fe9ea63062.pdf&#xD;&#xA;  [2]: https://pdfs.semanticscholar.org/433e/76872d510585c40ab4f505486a4aae670a02.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28588" PostHistoryTypeId="2" PostId="9938" RevisionGUID="001c515f-98dd-49fb-a74a-3c62b160de75" CreationDate="2020-06-11T14:11:23.907" UserId="7028" Text="I would like to project the triangles of my mesh to a 2D surface. I would like to minimalize the distorion, avoid breaking connected polygons if possible, and also maximalize the used space on the 2D surface.&#xD;&#xA;&#xD;&#xA;I tried to look for algorithms/papers about the topic, but I can only find articles about how to use UV unwrapping in 3D modelling softwares like Blender." ContentLicense="CC BY-SA 4.0" />
  <row Id="28589" PostHistoryTypeId="1" PostId="9938" RevisionGUID="001c515f-98dd-49fb-a74a-3c62b160de75" CreationDate="2020-06-11T14:11:23.907" UserId="7028" Text="How does UV unwrapping work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28590" PostHistoryTypeId="3" PostId="9938" RevisionGUID="001c515f-98dd-49fb-a74a-3c62b160de75" CreationDate="2020-06-11T14:11:23.907" UserId="7028" Text="|geometry|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28591" PostHistoryTypeId="2" PostId="9939" RevisionGUID="709df918-bea1-4ae8-b590-271f89a09ecf" CreationDate="2020-06-11T15:28:46.117" UserId="228" Text="UV unwrapping is a difficult topic. They can be both combinatorial algorithms or variational methods but in general they're optimization based, i.e. you setup an optimization problem and you solve it using some numerical optimization solver. I'm just going to give you some names and some libraries you can use eventually. I'll give you few names (both classic and more recent) and you can have a look yourself. ABF (Angle Based Flattening), LSCM (Least Square Conformal Mapping), ARAP (As rigid as possible), BFF (Boundary first flattening), Variational Surface Cutting, OptCuts.&#xD;&#xA;&#xD;&#xA;For ARAP and LSCM you can use [libigl][1]. [Boundary first flattening][2] was developed by Keenan Crane few years ago. [Variational surface cutting][3] is an improvement over BFF. And I recently discovered [OptCuts][4]. The code is available and you can run them yourself.&#xD;&#xA;&#xD;&#xA;You need to read through the papers to understand how they works if you wanted to implement them from scratch (not going to be easy, parametrization is a difficult subject). But if you want to just to run them just clone the repos and try them yourself.&#xD;&#xA;(libigl comes with tutorials, and two of these are about ARAP and LSCM). BFF, Variational Surface Cutting and OptCuts have a GUI based app so you can see the unwrapping and you can easily isolate the code if you need them in your own code.&#xD;&#xA;&#xD;&#xA;  [1]: https://libigl.github.io/&#xD;&#xA;  [2]: https://github.com/GeometryCollective/boundary-first-flattening&#xD;&#xA;  [3]: https://github.com/nmwsharp/variational-surface-cutting&#xD;&#xA;  [4]: https://github.com/liminchen/OptCuts" ContentLicense="CC BY-SA 4.0" />
  <row Id="28596" PostHistoryTypeId="52" PostId="9938" RevisionGUID="4e07d399-ff53-4a19-8a1d-2847bf7f8189" CreationDate="2020-06-11T22:11:27.877" />
  <row Id="28598" PostHistoryTypeId="5" PostId="9937" RevisionGUID="f956844b-5f7b-42d3-8748-409138e8df82" CreationDate="2020-06-12T12:48:35.477" UserId="9845" Comment="more information" Text="During radiation therapy, appropriate radiation is fired from various positions around the patient. Radiation therapy planning determines the values of the radiation at various positions. This optimization problem requires a huge matrix, whose elements are the doses deposited by unit strength beamlets at all possible positions around the patient at all the voxels of the patient volume. Thus each pair of beamlet and voxel has an entry in this matrix. This matrix is generally referred to by the following names: dose deposition matrix/dose influence matrix/dose information matrix.&#xD;&#xA;&#xD;&#xA;To get an idea about what algorithms can be used for dose calculation, this paper is good starting point:&#xD;&#xA;[Monte Carlo- versus pencil-beam-/collapsed-cone-dose calculation in a heterogeneous multi-layer phantom][1]&#xD;&#xA;&#xD;&#xA;To get an idea about how this matrix is subsequently used in radiation therapy, one could look at:&#xD;&#xA;[Real-Time Radiation Treatment Planning with Optimality&#xD;&#xA;Guarantees via Cluster and Bound Methods][2]&#xD;&#xA;&#xD;&#xA;The main bottleneck in radiation therapy planning is the computation of this matrix. While searching the literature, it is hard to find ideas from computer graphics (especially, rendering) being used to accelerate the computation of this matrix. Why is it so? Could it be just a lack of communication between the two communities? It appears unlikely, though. The radiation in radiation therapy is different from visible light. However, is it possible to borrow ideas from participating media rendering?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/profile/Thomas_Krieger3/publication/7938276_Monte_Carlo-_versus_pencil-beam-collapsed-cone-dose_calculation_in_a_heterogeneous_multi-layer_phantom/links/544a1ed50cf244fe9ea63062.pdf&#xD;&#xA;  [2]: https://pdfs.semanticscholar.org/433e/76872d510585c40ab4f505486a4aae670a02.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28599" PostHistoryTypeId="50" PostId="9829" RevisionGUID="7e0ab543-9b89-4011-a619-ac4230bf9fd1" CreationDate="2020-06-12T16:02:55.327" UserId="-1" />
  <row Id="28600" PostHistoryTypeId="2" PostId="9941" RevisionGUID="b806551e-cd59-4e33-867c-d864d831830f" CreationDate="2020-06-12T16:26:41.750" UserId="110" Text="&#xA;&gt; I target mobile/tablet devices with my product&#xA;&gt; this is less of a concern with desktop GPUs. &#xA;&gt; unity and unreal allowing full flexibility on adding shaders &amp; materials at-will&#xA;&#xA;Well, Unity and Unreal can also be used to make games targetting mobile/tablet devices, right?  &#xA;Do you think you can throw at them all the shaders &amp; materials you want, and expect them to magically output a performant application every time?  &#xA;Try to do it and you will find that they also struggle at some point.  &#xA;  &#xA;This can also happen on desktop ; the newest smartphones are totally faster than my oldest laptop.   &#xA;   &#xA;  &#xA;  &#xA;&gt; What is the best practice for managing multiple (dozens) of shaders in a scene with many materials?&#xA;&gt; how many parameters are too much?&#xA;  &#xA;The best practice is to test on the real hardware that you are targetting. If you target a wide range of mobile devices, then you have to decide the lowest spec that your product will officially support.  &#xA;Then, it is a matter of finding a good balance between performance (few materials/shaders) and visual quality (more variety/complexity).  &#xA;If you are comfortable with the process, you can prepare a number of performance profiles based on the type of device that will run your product (lower-end, higher-end?), with better quality for the higher end.  &#xA;&#xA;&#xA;&gt; Since shaders do have a lot of parameters populated from the model&#xA;&gt; material/mesh and sent down to the fragment shader, I fear that&#xA;&gt; unifying the shaders and passing too many parameters in the VBO each&#xA;&gt; frame/vertex/fragment, would be really bad for performance.&#xA;&#xA;You meant Uniform Buffer Object, not Vertex Buffer Object, right?  &#xA;I expect that the size of the uniform data that you pass to the GPU is not that big?  &#xA;However if your shaders are complex, it could take time for the GPU to execute them. &#xA;  &#xA;Here again it is a balance, between the amount of parameters that you pass, and the complexity of the shader, that you have to find.  &#xA;You just can try different solutions on real hardware, note down the performance and aspect of each one, and somehow compare them ; to find the optimal solution for your product. &#xA;&#xA;&#xA;&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28601" PostHistoryTypeId="2" PostId="9942" RevisionGUID="679b1c0e-f037-4eed-a6d2-1870fe49d7d5" CreationDate="2020-06-12T22:19:33.667" UserId="13298" Text="So, I would like to do capture on 3d pointclouds of 3d models the planes/vectors where for each object we have the highest variance (i.e. for object represented by 2000 3d points I would like to get vectors or planes along which we have the most variance of points), and I assume PCA can be used to show that per object. Did anyone attempt to do something like that and what kind of other variance capturing methods would you suggest? Do you have any particular python library I can use for this, besides the sklearn one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28602" PostHistoryTypeId="1" PostId="9942" RevisionGUID="679b1c0e-f037-4eed-a6d2-1870fe49d7d5" CreationDate="2020-06-12T22:19:33.667" UserId="13298" Text="Principal component analysis on 3d points and other ways of capturing variance" ContentLicense="CC BY-SA 4.0" />
  <row Id="28603" PostHistoryTypeId="3" PostId="9942" RevisionGUID="679b1c0e-f037-4eed-a6d2-1870fe49d7d5" CreationDate="2020-06-12T22:19:33.667" UserId="13298" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28606" PostHistoryTypeId="2" PostId="9943" RevisionGUID="b270ab36-f8e4-4bcd-bf53-4e27ee474c2a" CreationDate="2020-06-14T08:00:43.193" UserId="13551" Text="I am implementing an algorithm which requires me to compute the following integral,&#xD;&#xA;$$\int_{Poly(P_i)}||P-P_i||^2 dP$$&#xD;&#xA;where $P_i=(X_i, Y_i)$ is a point in 2D and $Poly(P_i)$ is a polygon containing $P_i$ (it is the Voronoi Cell of $P_i$ with a certain weight). Could anyone give me some indications on how to compute this quantity?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28607" PostHistoryTypeId="1" PostId="9943" RevisionGUID="b270ab36-f8e4-4bcd-bf53-4e27ee474c2a" CreationDate="2020-06-14T08:00:43.193" UserId="13551" Text="How to compute the following integral over a polygon?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28608" PostHistoryTypeId="3" PostId="9943" RevisionGUID="b270ab36-f8e4-4bcd-bf53-4e27ee474c2a" CreationDate="2020-06-14T08:00:43.193" UserId="13551" Text="|polygon|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28609" PostHistoryTypeId="2" PostId="9944" RevisionGUID="b1f0cbb1-6e8b-4683-8836-77da6d1d1959" CreationDate="2020-06-14T08:26:27.077" UserId="10096" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - P_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials." ContentLicense="CC BY-SA 4.0" />
  <row Id="28610" PostHistoryTypeId="5" PostId="9944" RevisionGUID="afd5e161-260a-4f55-bf36-02a492b00c84" CreationDate="2020-06-14T08:31:30.903" UserId="10096" Comment="added 228 characters in body" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - P_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials. The Jacobian determinants is: $$|det(J)| = \|(v_2-v_1) \times (v_3 - v_1)\|$$.&#xD;&#xA;If you are working in 3D, $\times$ is the cross product here. If it's 2D then augment the vectors with a $0$ for $Z$ and perform the cross product." ContentLicense="CC BY-SA 4.0" />
  <row Id="28611" PostHistoryTypeId="5" PostId="9944" RevisionGUID="970fbc85-2832-4397-8173-3dc54f4707f5" CreationDate="2020-06-14T08:38:58.743" UserId="10096" Comment="added 228 characters in body" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - \vec{P}_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials. The Jacobian determinant is: $$|det(J)| = \|(v_2-v_1) \times (v_3 - v_1)\|$$.&#xD;&#xA;If you are working in 3D, $\times$ is the cross product here. If it's 2D then augment the vectors with a $0$ for $Z$ and perform the cross product.&#xD;&#xA;&#xD;&#xA;Another option is to use a quadrature rule to compute this. For example you can still triangulate, but evaluate the integral over a triangle (let $f(P) =\|P - P_i\|^2$) through samples at the edge midpoints:&#xD;&#xA;$$\int_{\Delta}f(P)\,dP = \frac{\|\Delta\|}{6}\sum_{k=1}^{3}f\left(\frac{\vec{v}_k + \vec{v}_{k+1}}{2}\right).$$&#xD;&#xA;&#xD;&#xA;If memory serves me right, the above quadrature is exact for polynomials of up to order 2 (which is what you have, and the reason I wrote $=$ instead of $\approx$). Note that $k+1$ is taken to wrap around, that is, for $k = 3$ I use $\vec{v}_4 = \vec{v}_1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28612" PostHistoryTypeId="5" PostId="9944" RevisionGUID="93510f7a-3376-46ff-af65-ac5cc3d4a114" CreationDate="2020-06-14T08:46:10.550" UserId="10096" Comment="added 55 characters in body" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation, from barycentric coordinates to physical coordinates, for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - \vec{P}_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials. The absolute value of the Jacobian determinant is: $$|det(J)| = \|(v_2-v_1) \times (v_3 - v_1)\|$$.&#xD;&#xA;If you are working in 3D, $\times$ is the cross product here. If it's 2D then augment the vectors with a $0$ for $Z$ and perform the cross product.&#xD;&#xA;&#xD;&#xA;Another option is to use a quadrature rule to compute this. For example you can still triangulate, but evaluate the integral over a triangle (let $f(P) =\|P - P_i\|^2$) through samples at the edge midpoints:&#xD;&#xA;$$\int_{\Delta}f(P)\,dP = \frac{\|\Delta\|}{6}\sum_{k=1}^{3}f\left(\frac{\vec{v}_k + \vec{v}_{k+1}}{2}\right).$$&#xD;&#xA;&#xD;&#xA;If memory serves me right, the above quadrature is exact for polynomials of up to order 2 (which is what you have, and the reason I wrote $=$ instead of $\approx$). Note that $k+1$ is taken to wrap around, that is, for $k = 3$ I use $\vec{v}_4 = \vec{v}_1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28613" PostHistoryTypeId="5" PostId="9944" RevisionGUID="f6f3901f-b666-48cf-8fa6-08977d29d5bb" CreationDate="2020-06-14T08:58:44.833" UserId="10096" Comment="deleted 1 character in body" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation, from barycentric coordinates to physical coordinates, for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - \vec{P}_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials. The absolute value of the Jacobian determinant is: $$|det(J)| = \|(v_2-v_1) \times (v_3 - v_1)\|$$.&#xD;&#xA;If you are working in 3D, $\times$ is the cross product here. If it's 2D then augment the vectors with a $0$ for $Z$ and perform the cross product.&#xD;&#xA;&#xD;&#xA;Another option is to use a quadrature rule to compute this. For example you can still triangulate, but evaluate the integral over a triangle (let $f(P) =\|P - P_i\|^2$) through samples at the edge midpoints:&#xD;&#xA;$$\int_{\Delta}f(P)\,dP = \frac{|det(J)||}{6}\sum_{k=1}^{3}f\left(\frac{\vec{v}_k + \vec{v}_{k+1}}{2}\right).$$&#xD;&#xA;&#xD;&#xA;If memory serves me right, the above quadrature is exact for polynomials of up to order 2 (which is what you have, and the reason I wrote $=$ instead of $\approx$). Note that $k+1$ is taken to wrap around, that is, for $k = 3$ I use $\vec{v}_4 = \vec{v}_1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28618" PostHistoryTypeId="5" PostId="9944" RevisionGUID="46873028-7367-469f-97a8-554982511940" CreationDate="2020-06-15T19:13:54.117" UserId="10096" Comment="deleted 1 character in body" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation, from barycentric coordinates to physical coordinates, for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - \vec{P}_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials. The absolute value of the Jacobian determinant is: $$|det(J)| = \|(v_2-v_1) \times (v_3 - v_1)\|$$.&#xD;&#xA;If you are working in 3D, $\times$ is the cross product here. If it's 2D then augment the vectors with a $0$ for $Z$ and perform the cross product.&#xD;&#xA;&#xD;&#xA;Another option is to use a quadrature rule to compute this. For example you can still triangulate, but evaluate the integral over a triangle (let $f(P) =\|P - P_i\|^2$) through samples at the edge midpoints:&#xD;&#xA;$$\int_{\Delta}f(P)\,dP = \frac{|det(J)|}{6}\sum_{k=1}^{3}f\left(\frac{\vec{v}_k + \vec{v}_{k+1}}{2}\right).$$&#xD;&#xA;&#xD;&#xA;If memory serves me right, the above quadrature is exact for polynomials of up to order 2 (which is what you have, and the reason I wrote $=$ instead of $\approx$). Note that $k+1$ is taken to wrap around, that is, for $k = 3$ I use $\vec{v}_4 = \vec{v}_1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28620" PostHistoryTypeId="2" PostId="9946" RevisionGUID="775aa3d6-cfef-41d0-8cdb-75680c11970d" CreationDate="2020-06-16T14:04:23.573" UserId="13560" Text="Is there some historical reason texture coordinates are often called UVs? I get that vertex positions are x, y, z but even OpenGL has `TEXTURE_WRAP_S` and `TEXTURE_WRAP_T` and GLSL has aliases so if texture coord is in a `vec` you can access it with&#xD;&#xA;&#xD;&#xA;    someVec.st&#xD;&#xA;&#xD;&#xA;but not&#xD;&#xA;&#xD;&#xA;    someVec.uv  (these would be the 3rd and 4th elements of the vector)&#xD;&#xA;&#xD;&#xA;And yet pretty much every modeling package calls them UVs [Maya](https://knowledge.autodesk.com/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2018/ENU/Maya-Modeling/files/GUID-73BF7546-3BF2-44F3-9192-15A024CEC173-htm.html#:~:text=The%20UV%20Editor%20lets%20you,in%20the%20Modeling%20menu%20set.), [Blender](https://docs.blender.org/manual/en/latest/editors/uv/index.html), [Unity](https://docs.unity3d.com/Packages/com.unity.probuilder@4.0/manual/uv-editor.html), [Unreal](https://docs.unrealengine.com/en-US/Engine/Content/Types/StaticMeshes/HowTo/UVChannels/index.html), [3dsmax](https://knowledge.autodesk.com/support/3ds-max/learn-explore/caas/CloudHelp/cloudhelp/2017/ENU/3DSMax/files/GUID-A7CC32F5-40BE-4DE5-A364-05E7986D4BA5-htm.html)&#xD;&#xA;&#xD;&#xA;Where does the term UVs come from? Is this a known part of computer graphics history or is the reason they are called UVs lost in pixels of cg time?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28621" PostHistoryTypeId="1" PostId="9946" RevisionGUID="775aa3d6-cfef-41d0-8cdb-75680c11970d" CreationDate="2020-06-16T14:04:23.573" UserId="13560" Text="Why are texture coordinates often called UVs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28622" PostHistoryTypeId="3" PostId="9946" RevisionGUID="775aa3d6-cfef-41d0-8cdb-75680c11970d" CreationDate="2020-06-16T14:04:23.573" UserId="13560" Text="|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28623" PostHistoryTypeId="2" PostId="9947" RevisionGUID="8d01b478-47e5-4d52-9d36-2c21a088315c" CreationDate="2020-06-16T14:33:51.780" UserId="209" Text="This is not a definitive answer, but it is generally accepted that [Ed Catmull][1] introduced Texture Mapping in his 1974 thesis, &quot;*A SUBDIVISION ALGORITHM FOR COMPUTER DISPLAY OF CURVED SURFACES*&quot;   &#xD;&#xA;&#xD;&#xA;In that, he uses U,V to access the image data (page 42)&#xD;&#xA;&#xD;&#xA;&gt; MAPPING&lt;br&gt;&#xD;&#xA; Photographs, drawings, or any picture can be mapped onto bivariate patches. This&#xD;&#xA; is one of the most interesting consequences of the patch splitting algorithm. It&#xD;&#xA;gives a method for puitintg texture, drawings, or photographs onto surfaces....&lt;br&gt;&lt;br&gt;&#xD;&#xA;...If a photograph is scanned in at a resolution of x times y then every&#xD;&#xA;element can be referenced by u·x and v·y where 0&lt;=u,v&lt;=1. In general, one could think of the intensity as a function l(u,v) where I references a picture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I believe this thesis also introduced the concept of the Z-Buffer.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Edwin_Catmull" ContentLicense="CC BY-SA 4.0" />
  <row Id="28624" PostHistoryTypeId="5" PostId="9947" RevisionGUID="9c1f6233-51bb-4341-8586-d4b97231110f" CreationDate="2020-06-16T14:40:07.807" UserId="209" Comment="fixed OCR errors in the cut and paste of the text" Text="This is not a definitive answer, but it is generally accepted that [Ed Catmull][1] introduced Texture Mapping in his 1974 thesis, &quot;*A SUBDIVISION ALGORITHM FOR COMPUTER DISPLAY OF CURVED SURFACES*&quot;   &#xD;&#xA;&#xD;&#xA;In that, he uses U,V to access the image data (page 42)&#xD;&#xA;&#xD;&#xA;&gt; MAPPING&lt;br&gt;&#xD;&#xA; Photographs, drawings, or any picture can be mapped onto bivariate patches. This&#xD;&#xA; is one of the most interesting consequences of the patch splitting algorithm. It&#xD;&#xA;gives a method for putting texture, drawings, or photographs onto surfaces....&lt;br&gt;&lt;br&gt;&#xD;&#xA;...If a photograph is scanned in at a resolution of x times y then every&#xD;&#xA;element can be referenced by u·x and v·y where 0&lt;=u,v&lt;=1. In general, one could think of the intensity as a function l(u,v) where I references a picture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I believe this thesis also introduced the concept of the Z-Buffer.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Edwin_Catmull" ContentLicense="CC BY-SA 4.0" />
  <row Id="28625" PostHistoryTypeId="5" PostId="9944" RevisionGUID="a8e8afdb-af5e-491a-a33d-a60ea3da3a70" CreationDate="2020-06-16T18:01:14.110" UserId="10096" Comment="added 1 character in body" Text="Triangulate the Voronoi cell then write the integral as a sum over the triangles:&#xD;&#xA;&#xD;&#xA;$$\int_{\Omega}\|P - Pi\|\,dP = \sum_{k=1}^{N}\int_{\Delta_k}\|P-P_i\|\,dP.$$&#xD;&#xA;&#xD;&#xA;Write the integration over the triangle in barycebtric coordinates. Let the Jacobian of the transformation, from barycentric coordinates to physical coordinates, for triangle $k$ be $J_k$, and $|det(J_k)| = 2|Area_{\Delta_k}|$. Then $\int_{\Delta_k}f(P)\,dP = |det(J_k)|\int_0^1\int_0^{1-\beta}f(P(\alpha, \beta))\,d\beta\,d\alpha$, where $\alpha, \beta$ are two of the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;Now we need only evaluate (let $\vec{v}_i$ be the vertices of the current triangle):&#xD;&#xA;$$\int_0^1\int_0^{1-\beta}\|\vec{v}_1 + \alpha (\vec{v}_2 - \vec{v}_1) + \beta (\vec{v}_3 - \vec{v}_1) - \vec{P}_i\|^2\,d\alpha\,d\beta$$&#xD;&#xA;&#xD;&#xA;Expand this and integrate the polynomials. The absolute value of the Jacobian determinant is: $$|det(J)| = \|(v_2-v_1) \times (v_3 - v_1)\|$$.&#xD;&#xA;If you are working in 3D, $\times$ is the cross product here. If it's 2D then augment the vectors with a $0$ for $Z$ and perform the cross product.&#xD;&#xA;&#xD;&#xA;Another option is to use a quadrature rule to compute this. For example you can still triangulate, but evaluate the integral over a triangle (let $f(P) =\|P - P_i\|^2$) through samples at the edge midpoints:&#xD;&#xA;$$\int_{\Delta}f(P)\,dP = \frac{|det(J)|}{6}\sum_{k=1}^{3}f\left(\frac{\vec{v}_k + \vec{v}_{k+1}}{2}\right).$$&#xD;&#xA;&#xD;&#xA;If memory serves me right, the above quadrature is exact for polynomials of up to degree 2 (which is what you have, and the reason I wrote $=$ instead of $\approx$). Note that $k+1$ is taken to wrap around, that is, for $k = 3$ I use $\vec{v}_4 = \vec{v}_1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28626" PostHistoryTypeId="52" PostId="9946" RevisionGUID="318eca66-c5d5-44e3-b150-0c67d6f9eaf9" CreationDate="2020-06-16T22:04:36.083" />
  <row Id="28627" PostHistoryTypeId="2" PostId="9948" RevisionGUID="b83d5246-b3c9-4d12-88b5-2bbd0dfae5de" CreationDate="2020-06-17T12:55:28.743" UserId="11814" Text="Thanks a lot for your attention to this question in advance!&#xD;&#xA;&#xD;&#xA;  It is my first try to ask for help on this amazing StackExchange. If I do something inappropriate, please point it out directly so that I can correct this question to be better.&#xD;&#xA;&#xD;&#xA;  Please let me clear my background first: Recently I am investigating the simulation of rigid bodies.It's really interesting! &#xD;&#xA;&#xD;&#xA;  Till now, I have implemented 3 different kinds of rigid body/multibody simulators, one of them is by Featherstone method, one of them is by Lagrangian method(Generalized coordinates), and the left one is simply for isolated rigid bodies governed by Newton-Euler equations, respectively。&#xD;&#xA;&#xD;&#xA;  I use bullet as a collision detection backend in my simulator and begin to implement the collision resolving algorithms(for example, interactive Sequential Impulse or MLCP problem then solve it by PGS, etc) by myself.&#xD;&#xA;&#xD;&#xA;  **The question**: in lots of papers and books, people mentioned 2 different concepts. They say that the rigid body simulation can be roughly classified into &quot;constraint-based&quot; and &quot;impulse-based&quot;, later then they reference some famous papers of Mirtich or David Baraff... For example the book &quot;Physics-based animation&quot; written by Kenny Erleben in 2005, chapter 6 and chapter 7.&#xD;&#xA;&#xD;&#xA;  **But I really can not get the point. I felt quite hard to distinguish these 2 concepts &quot;constraint-based&quot; and &quot;impulse-based&quot;.** It nearly drove me crazy. &#xD;&#xA;&#xD;&#xA;  I can use a constraint solver in collision resolving to solve the contact impulse or contact force then push the contacting objects away.&#xD;&#xA;&#xD;&#xA;  I can also use a constraint solver between rigid bodies and make them into a chain connected by joints. &#xD;&#xA;&#xD;&#xA;  I can also calculate the force in contact points or user-customed external force and forward the simulation from the second-order &quot;acceleration&quot; term, or vice versa calculate the impulse and drive my simulator from the first-order &quot;velocity&quot;.&#xD;&#xA;&#xD;&#xA;  Would you kindly please help me to sort out my confused thoughts? :(" ContentLicense="CC BY-SA 4.0" />
  <row Id="28628" PostHistoryTypeId="1" PostId="9948" RevisionGUID="b83d5246-b3c9-4d12-88b5-2bbd0dfae5de" CreationDate="2020-06-17T12:55:28.743" UserId="11814" Text="Confusion about the concepts of &quot;constraint-based&quot; and &quot;impulse-based&quot; for rigidbody simulation" ContentLicense="CC BY-SA 4.0" />
  <row Id="28629" PostHistoryTypeId="3" PostId="9948" RevisionGUID="b83d5246-b3c9-4d12-88b5-2bbd0dfae5de" CreationDate="2020-06-17T12:55:28.743" UserId="11814" Text="|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28630" PostHistoryTypeId="2" PostId="9949" RevisionGUID="ec70377a-64a5-41c8-a82c-7ef12cd36cc8" CreationDate="2020-06-17T15:27:00.897" UserId="13565" Text="I'm planning to write a small software rendering engine (before anyone asks, it's kind of a learning/scientific experiment for me).&#xD;&#xA;&#xD;&#xA;Before writing any code, I'm already stuck at the very first step: how to display my framebuffer on the screen? What I'm planning to do is to render into an in-memory buffer e.g. 320x200 24-bit RGB format. Then of course I need to display the results on the screen; full-screen or in a window.&#xD;&#xA;&#xD;&#xA;I know that similar questions already exists here: &#xD;&#xA;&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/4648/how-can-i-send-custom-bitmap-to-frame-buffer&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/9923/how-are-digital-painting-canvas-rendered&#xD;&#xA;&#xD;&#xA;The difference is that I'd like to update the image frequently, with a decent framerate like 50FPS.&#xD;&#xA;&#xD;&#xA;It seems one possibility would be OpenGL framebuffer objects and/or buffer streaming. I'm not sure I should go that way or is it an overkill for this use case?&#xD;&#xA;I've also considered displaying a simple rectangle with a texture I would update each frame, but I'm not sure about the performance (I guess transferring a few megabytes of data each frame shouldn't be a problem though).&#xD;&#xA;Several years earlier I've experimented with GDI+ and WPF, but the performance was nowhere near what I wanted to achieve. Unfortunately I don't have the source code any more, but I'd admit that my approach was maybe completely wrong back then.&#xD;&#xA;&#xD;&#xA;I'm not expecting source code or a ready solution, but rather some directions: what functionality to use, I'd be happy to read articles or a tutorial about the topic.&#xD;&#xA;&#xD;&#xA;I was considering OpenGL first, but I'm fine with DirectX too. Other suggestions are welcome. I'm planning to use C/C++ or C#, maybe Python for the implementation.&#xD;&#xA;&#xD;&#xA;I'm sure there must be an easy solution, but I admit I'm a complete noob when it comes to graphics programming. I guess it's just about finding an effective way to copy data from RAM to GPU memory. I was wondering how retro emulators (e.g. Vice) or fantasy consoles (e.g. Pico-8) are solving this problem?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28631" PostHistoryTypeId="1" PostId="9949" RevisionGUID="ec70377a-64a5-41c8-a82c-7ef12cd36cc8" CreationDate="2020-06-17T15:27:00.897" UserId="13565" Text="How to display an in-memory framebuffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="28632" PostHistoryTypeId="3" PostId="9949" RevisionGUID="ec70377a-64a5-41c8-a82c-7ef12cd36cc8" CreationDate="2020-06-17T15:27:00.897" UserId="13565" Text="|rendering|real-time|2d|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28633" PostHistoryTypeId="2" PostId="9950" RevisionGUID="afba2cdd-567c-44a9-8bc1-0d0d3e3afe10" CreationDate="2020-06-17T16:12:45.557" UserId="13566" Text="&#xD;&#xA;&#xD;&#xA;Not sure if this is just specific to the article; but from https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point/mathematics-computing-2d-coordinates-of-3d-points is says:&#xD;&#xA;&#xD;&#xA;&gt; We learned how to convert points from world to any local coordinate&#xD;&#xA;&gt; system. If we know the local-to-world matrix, we can multiply the&#xD;&#xA;&gt; world coordinate of the point by the inverse of the local-to-world&#xD;&#xA;&gt; matrix (the world-to-local matrix).&#xD;&#xA;&#xD;&#xA;Nothing else is ever done with the local-to-world matrix - other than taking its inverse. So I'm wondering if it would be easier just to define the world-to-local matrix directly? Does taking the inverse make things like &quot;moving&quot; the camera more intuitive?&#xD;&#xA;&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 4.0" />
  <row Id="28634" PostHistoryTypeId="1" PostId="9950" RevisionGUID="afba2cdd-567c-44a9-8bc1-0d0d3e3afe10" CreationDate="2020-06-17T16:12:45.557" UserId="13566" Text="Is there a general rule with regard to using the inverse of the &quot;camera&quot; to world when using a homogeneous transform matrix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28635" PostHistoryTypeId="3" PostId="9950" RevisionGUID="afba2cdd-567c-44a9-8bc1-0d0d3e3afe10" CreationDate="2020-06-17T16:12:45.557" UserId="13566" Text="|perspective|render|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28636" PostHistoryTypeId="6" PostId="9949" RevisionGUID="7d516e48-cccf-4411-8dbd-676b10fda45c" CreationDate="2020-06-17T22:04:53.527" UserId="13565" Comment="edited tags" Text="|rendering|real-time|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28637" PostHistoryTypeId="5" PostId="4642" RevisionGUID="b0622f1e-d848-4e6e-8d54-859757dd1bd6" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="    Vec3 v = myPoint - pointOnPlane;&#xA;    float vDotPlaneNormal = dot(v, planeNormal)&#xA;    if (vDotPlaneNormal == 0) &#xA;        printf(&quot;point on plane&quot;);&#xA;    else if (vDotPlaneNormal &gt; 0)&#xA;        printf(&quot;point above somehow...&quot;);&#xA;    else&#xA;        printf(&quot;point under sadly...&quot;);&#xA;&#xA;If you wonder what is `pointOnPlane`. In fact it can be any point that lies on the plane. Imagine this as a sheet of paper; draw two lines on this sheet to define the center of the piece of paper, imagine that this point is aligned with the world coordinate system origin and that sheet is in xz plane of that coordinate system (in which y defines the up vector). So the paper is horizontal in a way. Now move the sheet around. The `pointOnPlane` can be the coordinates of the point you drew in the center of the sheet of paper with respect to the world origin.&#xA;&#xA;All you have to do is rotate that sheet of paper. That rotation is given to you by the plane's normal.&#xA;&#xA;The rest is basic trig. If the point P is one the plane, the dot product between the vector defined by (P - PointOnPlane) and the plane's normal will be equal to 0. The dot product tells you whether two vectors are orthogonal, on the same side of the plane or point in opposite directions.&#xA;&#xA;FASTER SOLUTION - EDIT&#xA;======================&#xA;&#xA;As mentioned by SimonF in a comment, you don't really need the `pointOnPlane` parameter and save the subtraction between this point and the tested point:&#xA;&#xA;&gt; As you imply, a plane can be represented by its normal, $N$, and a scalar, $d$. &#xA;&gt;&#xA;&gt; A point X is on the plane if $N \cdot X+d = 0$. As for inside and&#xA;&gt; outside typically you define a rule, e.g., that the normal points&#xA;&gt; &quot;out&quot; from the plane which just means that if $N \cdot X + d &gt; 0$, then&#xA;&gt; $X$ is above the plane, while $N \cdot X + d &lt; 0$, implies it's below.&#xA;&#xA;You can test/use both techniques.&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28638" PostHistoryTypeId="5" PostId="2266" RevisionGUID="6e2726c0-a066-40b8-8737-7c1e58793cc6" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="What the video is talking about is called [gamma correction](https://en.wikipedia.org/wiki/Gamma_correction) and it's a very familiar topic for graphics programmers. The first 30 minutes of John Hable's [talk on Uncharted 2 rendering](http://www.gdcvault.com/play/1012351/Uncharted-2-HDR) is my favorite introduction to &quot;why graphics programmers should care about gamma&quot;, as well as being a good introduction to HDR rendering. If you don't want to watch the talk (though I highly recommend it), [The Importance of Being Linear](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch24.html) is also a good article, and Charles Poynton has a [Gamma FAQ](http://www.poynton.com/notes/colour_and_gamma/GammaFAQ.html) that goes into more technical detail and explains the terminology used.&#xA;&#xA;By the way, square/squareroot is only an approximation; the [sRGB gamma curve](https://en.wikipedia.org/wiki/SRGB) is what's most commonly used in practice (see the formulas there mentioning $C_\text{srgb}$ and $C_\text{linear}$). See also [this related question](https://computergraphics.stackexchange.com/questions/68/is-gamma-still-important-to-take-into-account) about gamma and color spaces. It's a bit more complicated of a topic than the video makes it sound. :)&#xA;&#xA;To answer your specific questions:&#xA;&#xA;1. Yes, most image data is stored in gamma format, so the pixel values do _not_ represent linear luminance. I wouldn't describe it as &quot;incorrect&quot;, since gamma encoding has the useful property of putting more values in the darks, which is better for perceptual precision (as mentioned in the video). Gamma encoding is absolutely necessary to make good-looking images with only 8 bits per RGB component; if you stored linear values you would need more like 12 bits per component to get enough precision in the darks.&#xA;&#xA;2. To be more physically correct, when blurring an image, one should convert it to linear luminance, then do the blur (Gaussian or otherwise), then convert it back to the original color space.&#xA;&#xA;3. The monitor accepts image data in gamma format. So the pixel values do not represent linear luminance, and the output brightness is not linearly proportional to the pixel values.&#xA;&#xA;   If it's a good-quality, calibrated monitor, then it accepts data in a specific color space such as sRGB or Adobe RGB and reproduces the colors accurately based on the definition of that color space. If it's a crap uncalibrated monitor, then who knows what you'll get, but it'll be something _kinda_ like sRGB.&#xA;&#xA;4. GPUs can be configured to do various things here. Modern GPUs have hardware support to automatically convert values between gamma and linear when sampling a texture, or storing a value out to the framebuffer, but the programmer has to explicitly enable that using an API such as Direct3D or OpenGL.&#xA;&#xA;5. Computer graphics people certainly do know about this topic, and it's critical to get it right when building a realistic renderer for film, AAA games, and so on. However, a lot of more &quot;everyday&quot; apps like web browsers and image editors (even Photoshop, as the video mentions) don't really handle gamma correctly.&#xA;&#xA;   It's not an issue of processing power; maybe that was a problem 20 years ago, but today even mobile phones have ample processing power to convert images between gamma and linear. The reason why web browsers and image editors still don't get this right is some combination of (a) ignorance, (b) not believing that gamma is important enough to be worth getting right, and (c) simply being stuck with bad behavior because it's been that way for a long time and users have come to expect it, so they freak out if something changes.&#xA;&#xA;6. As mentioned, we have to think a lot about gamma when building a renderer. Most computations (e.g. lighting) should be done in linear space, but the input textures and output image should be in gamma space. Also, maybe some parts of rendering such as UI compositing should happen in gamma space because it's more familiar to artists (it works more like Photoshop layer compositing and such). Also, we have to decide if internal render targets are going to be stored in linear or gamma space, as it will affect precision. And we have to get all the conversions right, so that data gets converted between linear and gamma at the right spots in the rendering process." ContentLicense="CC BY-SA 4.0" />
  <row Id="28639" PostHistoryTypeId="5" PostId="2217" RevisionGUID="bb5bd997-72df-4890-910e-efc5ae8ca237" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Macs are not gaming machines.  They never have been.  There was a time maybe 10-15 years ago when you could build a mid-tier gaming Mac, at significantly higher expense than a PC, but Macs have never catered to anything more than very casual gamers.  They don't run other games &quot;easily&quot; - they just adequately run *some* games, *barely* run others, and simply can't run a lot of popular titles (if they exist at all).&#xA;&#xA;Every Mac, with two exceptions, uses integrated graphics on their Intel chips.&#xA;&#xA;The MacBookPro can optionally can be fitted with a Radeon R9 370X, and the MacPro has the FirePro option above.  Let's look at 3D performance of these various options (The FirePro D700 is a Mac special - it's roughly in line with the specs of the W9000 PC variant):&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;The multi-thousand dollar FirePro is sitting there next to an old GTX 670 that you can pick up in used bargain bins these days.  So what gives?&#xA;&#xA;The FirePro is a professional GPU - it competes with NVidia's Quadro and Tesla line of cards.  It is designed specifically for precision workstation GPU tasks, particularly for double-precision calculations.  These are important for CAD/Architechtural and Engineering applications as well as for scientific computing.  The cards **can** be used just fine to play 3D games, but they are not optimized for that task and naturally underperform when compared to high end gaming GPUs like the GTX970/980, etc.&#xA;&#xA;Gaming GPUs dedicate resources to lower precision calculations (which they can do more of, and more quickly) and eye-candy goodies.  The tasks which they set themselves to are largely at odds with each other in terms of the style of hardware that is needed to get the job done.&#xA;&#xA;If you wanted to build a gaming mac right now, you really can't.  None of the systems available even have slots anymore to add in aftermarket GPUs (and they were twice the price of PC GPUs back in the days when you could, and came out months and months later than their PC counterparts so were always behind the cutting edge).  The only expandable Mac right now is the MacPro, and it is so ludicrously expensive that you would be crazy to try to make a gaming machine out of it (in fact, the hardware simply can't be had).  With expensive Xeon processors and FirePro graphics, the system is a highly specialized workstation that is firmly aimed at creative, scientific, and engineering professionals.  &#xA;&#xA;So where does that leave the Mac?  Absolutely, completely out of the gaming arena - full stop.  It's got enough juice to run a few very casual games at very modest quality for home users, but that's just about it.  The Oculus Rift needs major GPU horsepower.  For 3D it needs to compute every scene from two unique perspectives (one for each eye), instantly doubling the amount of pre-rendering calculation it needs to do.  It then needs to render each of these independent scenes to two independent displays and keep everything moving fast and smooth enough to not make you want to vomit or have some sort of seizure.  That means it needs a powerful gaming GPU, and these just aren't available for the Mac anywhere.&#xA;&#xA;  [1]: https://i.stack.imgur.com/fiOdu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28640" PostHistoryTypeId="5" PostId="2152" RevisionGUID="3039954a-0004-4f05-ac83-a81ccbed0a55" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="&lt;strike&gt;The &quot;Uniform Mapping&quot; here is incorrect.  It does not transform to a uniform distribution on the sphere.&lt;/strike&gt;&#xA;&#xA;Very very bad me.  I misread the equation AND I didn't even consult my own reference [1], if I had I would have seen my mistake.&#xA;&#xA;Still the method from [2] is interesting and is described below.&#xA;&#xA;# Additional note:&#xA;To map a uniform point set from the unit square to the sphere or half sphere requires an area-preserving map.  That will maintain the uniform property.  For pseudo-random that's sufficient (points are independent), however low-discrepancy point set will have its discrepancy measure effected by distortions in area introduced by the map.  I'm not aware of any references with respect to this point.&#xA;&#xA;----&#xA;&#xA;The method from [2] starts by mapping unit square to the unit disk.  One way we can do this is by using a rejection method.  Pseudo-code looks like this:&#xA;&#xA;    d = 0;&#xA;&#xA;    do {&#xA;      p = uniform2d(...);  // [0,1) x [0,1)   given to be uniform&#xA;      p = 2p;              // [0,2) x [0,2)   scaling (area-preserving)&#xA;      p = p-1;             // (-1,1) x (-1,1) translating (area-preserving)&#xA;      d = dot(p,p);        // is p in disk?&#xA;    } while(d &gt;= 1);       //   if not rinse-and-repeat&#xA;&#xA;the area of the transformed square is $4$ and the unit disk is $\pi$, so the acceptance rate is $\frac{\pi }{4}$ (~.785) so on average requires $\frac{4}{\pi}$ (~1.273) iterations.&#xA;&#xA;Also non-rejection based methods exist, for example [3] which requires one square root and one trig operation. Note that the rejection method does not distort areas so the discrepancy measure remains the same.&#xA;&#xA;----&#xA;&#xA;Once we have $ p = \left(u_0, u_1 \right) $ uniformly distributed in the unit disk, we have:&#xA;&#xA;$$ u_0, u_1 \in \left(-1,1\right) $$&#xA;$$ d = p\cdot p = u_0^2+u_1^2,\; d &lt; 1 $$&#xA;&#xA;then the transform to the sphere is:&#xA;&#xA;$$ s=2\sqrt{1-d} $$&#xA;$$ p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, 1-2d\right\} $$&#xA;&#xA;or if you wanted a half-sphere, say positive Z, (just to state the obvious):&#xA;&#xA;$$p = \left\{s\thinspace u_0,\thinspace s\thinspace u_1, d\right\} $$&#xA;&#xA;There is a Stackexchange: Mathematics thread that discusses this method ([4],[5]).&#xA;&#xA;----&#xA;&#xA;Also if you want to procedurally generate a LDS the additive recurrence formulation of the Weyl sequence is very cheap.&#xA;&#xA;----&#xA;References:&#xA;&#xA;1. [Wolfram MathWorld: Sphere Point Picking](http://mathworld.wolfram.com/SpherePointPicking.html)&#xA;2. &quot;Choosing a Point from the Surface of a Sphere.&quot;, George Marsaglia, 1972. \([PDF](http://projecteuclid.org/euclid.aoms/1177692644;))&#xA;3. [Wolfram MathWorld: Disk Point Picking](http://mathworld.wolfram.com/DiskPointPicking.html)&#xA;4. [SE Mathematics](https://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838336#838336)&#xA;5. [SE Mathematics](https://math.stackexchange.com/questions/838326/3-random-numbers-to-describe-point-on-a-sphere/838882#838882)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28641" PostHistoryTypeId="5" PostId="2055" RevisionGUID="a451fc53-f400-4a6e-9447-7fc43a378a84" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have to use a propriertary graphics-engine for drawing a line. I can rotate the whole drawing by its origin point (P1). What I want, is to rotate it around its center point(M). So basically that it looks like the green line (L_correct instead of L_wrong). &#xA;&#xA;I think, it should be possible to correct it, by moving it from P1 to P2. But I cannot figure out what formula could be used, to determine the distance. It must probably involve the angle, with and height... Can anyone give me a hint?&#xA;&#xA;![1][1]&#xA;&#xA;[1]: https://i.stack.imgur.com/75MpZ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28642" PostHistoryTypeId="5" PostId="2048" RevisionGUID="54a6abcf-bd09-4869-b0c2-04964de3e2eb" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Yes, its pretty standard stuff. Most 3D applications our there can do this. Since the nomenclature of 3d applications is not standardized, the tool has different names in different applications: Loft (Maya, 3DSMax), Blend (Creo, Catia...) and so on.&#xA;&#xA;[![Blend][1]][1]&#xA;&#xA;**Image 1**: Blend between 3 curves, not closed but same principle applies. Open curves are easier as they clearly define the boundary conditions. (software used is Creo because that's what I had open)&#xA;&#xA;You usually want the first edge be from a surface edge because otherwise you will lose the tangency info. But nothing prevents you from using a natural tangent direction, you just lose control. Also you need to pay attention to how you intend the curves to connect (what point connects to what point).&#xA;&#xA;Personally I prefer drawing the hull or using some of the network based tools. This way allow you to specify control curves in 2 directions, thus giving control of what to connect where and how it should work mid run.&#xA;&#xA;[![Image 2][2]][2]&#xA;&#xA;**Image 2**: Curve network.&#xA;&#xA;There are many ways to do this, infinite ways in fact. Also if you want to be compatible with other mainstream CAD apps use NURBS instead of beziers than its easier for you to write a exporter/importer if your data set is rich enough. Beziers are just special cases of NURBS after all so your code itself should not need to change all that much (fitting also gets easier).&#xA;&#xA;What you do is simply fit a curve trough your points in the second direction this will then give you the corresponding hull in the other direction. In your case you could just make a Bezier patch for each segment and then try to deduce a natural tangent direction.&#xA;&#xA;### One way &#xA;&#xA;Like I said theres a infinite ways of constructing these, you have an artistic freedom of doing whatever you see fit it's a over constrained problem. One way of constructing this would be to have a patch for each consecutive cross section. This is nice and tidy as it generalizes works well with an arbitrary number of cross sections.&#xA;&#xA;[![enter image description here][3]][3]&#xA;&#xA;**Image 3**: Example of deriving one row for 2 consecutive bezier spans.&#xA;&#xA;First recognize there are 3 cases (ill cover 2):&#xA;&#xA;  1. Free edges,&#xA;  2. Internal edges,&#xA;  3. External constraint.&#xA;&#xA;I'll cover 1 and 2. First the Internal edge as its simple you want it to be smooth so the tangent length and direction in both patches must match. If that's not true then its not sufficiently continuous. You could simply take that this is the furthest point from the surrounding patches control points and due to mean value theorem it should have a tangent direction perpendicular to these (Line A-C is parallel with D-E). The tangent length should be about 1/3 of the length of the distance to the adjoining vertices (A-B or A-C, in this case the shorter of the spans. It could be longer or average. though that could pose problems). Obviously if you have more spans just repeat for one span forward and after for more internal spans if needed. &#xA;&#xA;For free edges find the point on the perpendicular line that is as far from the point as half distance between the points (length B-D is equal to length (A-B)/2 and length B-E is equal to length (B-D)/2). The free tangent points towards this point. The length of the tangent is as long as one third of corresponding point difference (length (A-B)/3 and (B-C)/3). Obviously the distances and points could be arbitrary but these are somewhat natural. &#xA;&#xA;&#xA;Repeat for next point sequence in line and next and next. You end up with 2 spans that means 2 times 16 points.  There are other ways but this is relatively easy to convert into a visual form without going into deeper maths. But this is pretty well known math you can find many ways to form these by searching in literature.&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/zeKrH.png&#xA;  [2]: https://i.stack.imgur.com/Qm5Bk.png&#xA;  [3]: https://i.stack.imgur.com/ES0Mq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28643" PostHistoryTypeId="5" PostId="2032" RevisionGUID="7270fb5e-7af1-41ca-b150-7f22bafef5e2" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="&gt; Multi-view stereo (MVS) is the general term&#xA;given to a group of techniques that use stereo correspondence as their&#xA;main cue and use more than two images.&#xA;&#xA;A quote from ['Multi-View Stereo: A Tutorial'][1] by Yasutaka Furukawa and Carlos Hernández.&#xA;&#xA;So to paraphrase: We have a set of images that is larger than two, and use them in a pairwise manner by applying techniques that finde stereo correspondences to reconstruct the object shown in them.&#xA;&#xA;If you want to know more about MVS algorithms that paper I linked seems to be pretty good and at least Furukawa is a name that I know and have read papers from, so he seems to know the topic.&#xA;&#xA;  [1]: http://www.cse.wustl.edu/~furukawa/papers/fnt_mvs.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28644" PostHistoryTypeId="5" PostId="1994" RevisionGUID="db519849-4d07-4849-baf1-cb7133465cce" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="It's fine to use photometric units as an overall scale for setting light brightnesses. However, there's a technical subtlety you should be aware of. I'll quote from [a blog post I wrote on the subject last year](http://www.reedbeta.com/blog/2014/08/17/radiometry-versus-photometry/):&#xA;&#xA;&gt; With RGB images, it’s important to recognize that our display devices behave more radiometrically than photometrically. A red pixel value of 255, and a green pixel value of 255, both result in about equal amounts of _radiant_ flux (watts) being generated by a pixel on a screen—_not_ equal amounts of luminous flux. By the same token, digital cameras capture pixel values that correspond to radiant flux, not luminous flux.&#xA;&gt;&#xA;&gt; That’s why we need to use luma coefficients when converting images to grayscale, or calculating the brightness of a pixel, to get a perceptually accurate result; and it also means that rendering RGB images proceeds more naturally in radiometric units than in photometric ones.&#xA;&#xA;In other words, the wavelength dependence of photometric units is different to what you might be expecting. In ordinary RGB color spaces, white is (1, 1, 1) and has a roughly flat radiometric spectrum; but in a supposed &quot;photometric RGB&quot;, (1, 1, 1) would not be white; it would be a purpleish color, with less energy in the green range and more in the red and blue ranges. A similar problem would afflict spectral renderers trying to measure all their bins in wavelength-dependent photometric units, but even worse, as the radiance needed to generate a given luminance _diverges_ toward either end of the visible spectrum, where the human luminous efficiency function goes to zero.&#xA;&#xA;So, if you wish to use photometric units, IMO it's better to &quot;cheat&quot; a bit and not use _true_ wavelength-dependent photometric units, but just use some fixed wavelength (such as 555 nm green, which is the peak of the human luminous efficiency function), or perhaps an average over the spectrum, as a reference unit, and apply that single unit to measure all wavelengths. This will get you in less trouble when importing RGB colors and spectra from other sources, and when generating them as outputs." ContentLicense="CC BY-SA 4.0" />
  <row Id="28645" PostHistoryTypeId="5" PostId="1916" RevisionGUID="72d58703-853d-49b3-bbaa-d8ff5af30eac" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I've stumbled upon this question on a CG exam:&#xA;&#xA;&gt; Which of the following techniques/optimizations doesn't apply to ray tracing?&#xA;&gt;&#xA;&gt; A: Back-face culling&#xA;&gt;&#xA;&gt; B: &quot;Shadow-feeler&quot; rays&#xA;&gt;&#xA;&gt; C: Recursive tracing of rays&#xA;&gt;&#xA;&gt; D: Calculation of refraction rays&#xA;&gt;&#xA;&gt; E: None of the above&#xA;&#xA;B, C and D are obviously false, but what about A? [Here](http://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/single-vs-double-sided-triangle-backface-culling), is says that &quot;with ray tracing, this feature is not as useful. Generally with ray tracing, we want geometry in the scene to cast shadows for example, regardless of the orientation of the object's surface with respect to the ray direction however the backface culling option might still be desired for primary rays&quot;.&#xA;&#xA;I feel that the question is a bit ambiguous, since back-face culling can be applied to ray tracing but it's not (correct me if I'm wrong) a &quot;native&quot; feature as the other techniques." ContentLicense="CC BY-SA 4.0" />
  <row Id="28646" PostHistoryTypeId="5" PostId="1822" RevisionGUID="ef74bb30-8c38-44ef-a750-64f48041cd6c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="### You're comparing apples to oranges&#xA;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xA;&#xA;There is no reason why you can not get realtime graphics that are very good out of modelling software like Maya or 3DS Max. Results that are par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (I've done full HD renders at 30 fps from Maya). All you have to do is stop using the provided software raytracers.&#xA;&#xA;There are some differences though. The primary difference is that you as a user do not optimize stuff as much as game developers do (optimization is using all the tricks in the book). Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xA;&#xA;Many of the things may in fact have been precomputed, so they aren't so much faster just better organized. Baking your indirect illumination will beat non baked results every day.&#xA;&#xA;### Why are the raytracers slower?&#xA;&#xA;They aren't\*, one just tends to do more work on a ray tracer because its easy. Feature by feature they aren't much slower in computation cycles. For example theres no need for a ray tracer to cast secondary rays (life reflections in that case the ray tracer will cull geometry away, or not even load it, in fact mental ray does just that). Its just usually done because it trivial to do so and that's the clear advantage of ray tracers. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xA;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xA;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact a Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xA;&#xA;So you pay for flexibility and ease of use. But yes ill admit both Maya and Max suffer from extreme old age. So they could be faster.&#xA;&#xA;**TL;DR** The difference is mostly in optimization (read lots of tricks) and available external resources.&#xA;&#xA;PS: There is a misconception that this is because it is more physically correct. It certainly can be but the ray tracer is not inherently more physically correct than your average game or any other computation. In fact many games use really good models while quite many modelers do not.&#xA;&#xA;&#xA;\* See http://www.graphics.cornell.edu/~bjw/mca.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28647" PostHistoryTypeId="5" PostId="1800" RevisionGUID="d72c695b-51d6-4979-9b91-0efa31facec8" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="The polar coordinate system commonly used in BRDF definitions is set up relative to the surface being shaded, i.e. in tangent space. The $\theta$ angle measures how far you are from the surface normal while $\phi$ is the azimuth around the plane of the surface relative to some reference direction (which doesn't matter unless the BRDF is anisotropic). So if you want to convert to these coordinates, you have to first get your vector in tangent space (with the origin at the intersection point and two of the axes aligned with the surface), then apply the usual Cartesian-to-spherical transformation.&#xA;&#xA;However, normally you can and should evaluate BRDFs *without* using polar coordinates, trigonometric functions, or angles at all, but just using vector math primitives such as dot products. This is usually more efficient *and* it's more robust, as you don't have to deal with angle wraparound, factors of pi, out-of-range arguments to inverse trig functions and so on. For instance, you probably know that the cosine of the angle between vectors can be obtained by just dotting the (normalized) vectors. The sine and tangent can be obtained through trig identities from the cosine (i.e. from the dot product).&#xA;&#xA;Fabian Giesen wrote an article on this topic, [Finish your derivations, please](https://fgiesen.wordpress.com/2010/10/21/finish-your-derivations-please/), that refers to the exact Oren-Nayar article you linked and gives an alternate, trig-free form:&#xA;&#xA;&gt;Time to brush up your trigonometric identities. A particularly bad offender can be found here – the relevant section from the simplified shader is this:&#xA;&gt;&#xA;&gt;     float alpha = max( acos( dot( v, n ) ), acos( dot( l, n ) ) );&#xA;&gt;     float beta  = min( acos( dot( v, n ) ), acos( dot( l, n ) ) );&#xA;&gt;     C = sin(alpha) * tan(beta);&#xA;&gt;&#xA;&gt;Ouch! If you use some trig identities and the fact that acos is monotonically decreasing over its domain, this reduces to:&#xA;&gt;&#xA;&gt;     float vdotn = dot(v, n);&#xA;&gt;     float ldotn = dot(l, n);&#xA;&gt;     C = sqrt((1.0 - vdotn*vdotn) * (1.0 - ldotn*ldotn))&#xA;&gt;       / max(vdotn, ldotn);&#xA;&gt;&#xA;&gt;..and suddenly there’s no need to use a lookup texture anymore (and by the way, this has way higher accuracy too).&#xA;&#xA;And note that this formulation only has one transcendental function (`sqrt`) in place of four (two `acos`, a `sin`, and a `tan`)." ContentLicense="CC BY-SA 4.0" />
  <row Id="28648" PostHistoryTypeId="5" PostId="1764" RevisionGUID="8674512a-ff9f-496b-964b-4480604e0730" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="The general problem is called [graph drawing](https://en.wikipedia.org/wiki/Graph_drawing) and is not an easy problem.&#xA;&#xA;The graphs that can be drawn on the plane without crossings are called [planar](https://en.wikipedia.org/wiki/Planar_graph), but not all graphs are planar: the typical graphs that are not planar are the complete graph on $5$ vertices $K_5$ and the complete bipartite graph on 6 vertices $K_{3,3}$, famous because of the [three utilities problem](https://en.wikipedia.org/wiki/Three_utilities_problem).&#xA;&#xA;You may want to try [Graphviz - Graph Visualization Software](http://www.graphviz.org/) to produce nice drawings.&#xA;&#xA;See also &#xA;&#xA;&gt; Szirmay-Kalos, László, [Dynamic layout algorithm to display general graphs](http://www.iit.bme.hu/~szirmay/lsgraph.ps.gz), in *Graphics Gems IV*, 1994. [code](http://www.realtimerendering.com/resources/GraphicsGems/gemsiv/graph_layout/)&#xA;&gt;&#xA;&gt; Rosati, Claudio, A simple connection algorithm for 2-d drawing, *Graphics Gems III*, 1992, [code](http://www.realtimerendering.com/resources/GraphicsGems/gemsiii/con2d.c)." ContentLicense="CC BY-SA 4.0" />
  <row Id="28649" PostHistoryTypeId="5" PostId="1591" RevisionGUID="d169972c-28ea-48c7-bb6f-91612bcadab5" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="As usual with numerical methods and samplings, it also depends of your quality threshold of what you consider &quot;isotropic&quot;. And of what you would consider as a being or not a &quot;grid-based noise algorithm&quot;.&#xA;&#xA;For instance Gabor Noise reproduces a target spectrum, for instance blue noise, which in Fourier domain is a simple isotropic ring.&#xA;Now if you consider that this ring is not analytic but rasterized, as such it is not perfectly symmetrical. Also if the ring radius (i.e., frequency) get too close to the window size (i.e., maximum frequency), it will be truncated (and thus no longer symmetrical). Up to you to accept or not these as anisotropic ;-)&#xA;&#xA;&#xA;[![&quot;this is not a circle&quot; - Magritte][2]][2]&#xA;[![&quot;this is not a circle&quot; - Nyquist][1]][1]&#xA;*&quot;This is not a circle&quot; - Magritte . . . . . . . . . . . . . . . .   &quot;This is not a circle&quot; - Nyquist*&#xA;&#xA;You might or might not accept a rasterized ring in Fourier space to be &quot;isotropic&quot;. Still, in the extreme cases where the ring get thinner than the resolution, or larger than the window, isotropy is objectively lost.&#xA;&#xA;  [1]: https://i.stack.imgur.com/c4Xaj.png&#xA;  [2]: https://i.stack.imgur.com/vFj2M.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28650" PostHistoryTypeId="5" PostId="1576" RevisionGUID="ecc2912f-7998-4c6f-888c-c21407230de6" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I see mainly three ways of computing normals for a generated shape.&#xA;&#xA;# Analytic normals&#xA;&#xA;In some cases you have enough information about the surface to generate the normals. For example, the normal of any point on a sphere is trivial to compute. Put simply, when you know the derivative of the function, you also know the normal.&#xA;&#xA;If your case is narrow enough to allow you to use analytic normals, they will probably give the best result in terms of precision. The technique doesn't scale too well though: if you also need to handle cases where you cannot use analytic normals, it may be easier to keep the technique that handles the general case and drop the analytic one altogether.&#xA;&#xA;# Vertex normals&#xA;&#xA;The cross product of two vectors gives a vector perpendicular to the plane they belong to. So getting the normal of a triangle is straightforward:&#xA;&#xA;    vec3 computeNormal(vec3 a, vec3 b, vec3 c)&#xA;    {&#xA;        return normalize(crossProduct(b - a, c - a));&#xA;    }&#xA;&#xA;Moreover, in the above example, the length of the cross product is proportional to the area inside _abc_. So the smoothed normal at a vertex shared by several triangles can be computed by summing up the cross products and normalizing as a last step, thus weighting each triangle by its area.&#xA;&#xA;    vec3 computeNormal(vertex a)&#xA;    {&#xA;        vec3 sum = vec3(0, 0, 0);&#xA;        list&lt;vertex&gt; adjacentVertices = getAdjacentVertices(a);&#xA;        for (int i = 1; i &lt; adjacentVertices; ++i)&#xA;        {&#xA;            vec3 b = adjacentVertices[i - 1];&#xA;            vec3 c = adjacentVertices[i];&#xA;            sum += crossProduct(b - a, c - a);&#xA;        }&#xA;        if (norm(sum) == 0)&#xA;        {&#xA;            // Degenerate case&#xA;            return sum;&#xA;        }&#xA;        return normalize(sum);&#xA;    }&#xA;&#xA;If you are working with quads, there is a nice trick you can use: for a quad _abcd_, use `crossProduct(c - a, d - b)` and it will handle nicely cases where the quad is in fact a triangle.&#xA;&#xA;Iñigo quilez wrote a few short articles on the topic: [clever normalization of a mesh](http://www.iquilezles.org/www/articles/normals/normals.htm), and [normal and area of n sided polygons](http://iquilezles.org/www/articles/areas/areas.htm).&#xA;&#xA;# Normals from partial derivatives&#xA;&#xA;Normals can be computed in the fragment shader from the partial derivatives. The math behind is the same, except this time it is done in screen space. This article by Angelo Pesce describes the technique: [Normals without normals](http://c0de517e.blogspot.jp/2008/10/normals-without-normals.html).&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28651" PostHistoryTypeId="5" PostId="1472" RevisionGUID="d442aa73-b6c0-499c-a567-b00237374177" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have an issue with rendering my textures in Silverlight. When I look at it from above everything looks fine:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;&#xA;&#xA;But if I only change angle of watching it it looks terrible:&#xA;&#xA;[![enter image description here][2]][2]&#xA;&#xA;I am using very simple pixel shader (hlsl):&#xA;&#xA;    float4 main(VsOutput vertex) : COLOR&#xA;    {&#xA;            float4 texColor = tex2D(textureSampler, texCoord);&#xA;    &#xA;            return texColor;&#xA;    }&#xA;&#xA;If I don' t use that pixel shader and load texture via BasicEffect like:&#xA;&#xA;    BasicEffect.texture = myTexture&#xA;&#xA;Everything looks fine. Why my pixel shader affects texture so bad?&#xA;&#xA;____&#xA;I expect that it might be somehow connected with mipmapping, but I am not sure - my texture is pretty small so I guess it shouldn' t have such a big effect. Anyway I need some advices :).&#xA;&#xA;____&#xA;&#xA;  [1]: https://i.stack.imgur.com/zjAeu.png&#xA;  [2]: https://i.stack.imgur.com/4b2AU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28652" PostHistoryTypeId="5" PostId="1446" RevisionGUID="9f796fac-734c-4594-a068-cbb9d5e7a66c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="LOD (Level of Detail) means managing objects in different display scales, which could be devided by two parts. However, you may use one of them and that would be enough for most cases.&#xA;&#xA;&#xA;&#xA; 1. Show/hide layers ( group of objects of same type) depending on magnitude (display scale).&#xA;&#xA; 2. Algebraic Geomery based method, called Generalization (which is an algorithm to simplify polygons). look at the following picture&#xA;&#xA;    ![generalization](https://i.stack.imgur.com/lYP5y.jpg)&#xA;&#xA;The most famous and efficient method to generalize (simplify) a polygon mesh is known as [Descartes-Euler polyhedron theorem][1] (Equation 4.5 sorry if I am refering to a book, that was best I can do) and is used by most of the spatial databases for example PostGIS modules in PostgreSQL. It simply removes smaller sides of a polygon and makes a very rounded one.(above picture)&#xA;&#xA;To implement LOD in a game you need to save and manage the scale of your map (scene) during th zoom in/out operations. The scale changes from zero to infinity and you have to divide this into a particular number of ranges for example something like this:&#xA;&#xA; 1. 1/zero = infinity to 1/50&#xA; 2. 1/50 to 1/100&#xA; 3. 1/100 to 1/1000&#xA; 4. 1/1000 to 1/infinity = 0&#xA;&#xA;Then you need to define which types of your objects (layers) should be visible or invisible in each of the above ranges. For example a small type of object like a hydrant valve should not be visible when the user is in the fourth range because it will be very small at that scale and can not be discriminated so it doesn't matter if you skip drawing it on the screen.&#xA;&#xA;So when a user uses zoom in and zoom out to change the magnification he moves through the above limits from one to the other range, and your game uses these display scales to manage level of details by showing or hiding objects on the scene. This makes a discrete solution that objects suddenly fade during your zoom out operation, however having the display scales and magnification ranges defined carefully, the user woudn't feel anything.&#xA;&#xA;The above group of 4 ranges are just an example and you need to find the best for your own case by trial and error. There is no rule for that.&#xA;&#xA;Sometimes the games use their own LOD methods, Subway Surfer for instant, shows a small, without texture rectangle to show a building at far, and by getting close suddenly it gets texture,  gamer feels it. You didnt talk about your projection system which is very important also didn't talk about what kind of game you are creating.&#xA;&#xA;However suppose you are implementing a full 3D game with openGl and you wish to filter some mesh before transfering them to graphic hardware, I am sure this will help you to reduce binding/unbinding operations with buffer objects and vertex arrays (VBO,VAO) while dealing with OpenGl.&#xA;&#xA;&gt;Using only a layer managment or just implement Euler's Generalization&#xA;&#xA;In most cases it is not necessary to implement a generalization algorithm, and filtering objects just works and gets you to the efficiency(refresh rate) you need, however it totally depends, case by case. Although it is an easy algorithm that just removes the small sides of a polygon, you need to define a threshold which is the product of magnitude and a constant number, so bigger sides get filtered in a much farther point of view.&#xA;&#xA;Forgeting the layer manamgment and only implementing Eulers generalization algorithm, provides a very neat and continuous method in which you just check each sides and lines against a pre-defined threshold and show them only in case they are big enough to be discriminated on the screen.&#xA;&#xA;P.S : magnification is a float number &gt; 0 which is equal to 1/scale and the scale is usually &lt; 1 since a 1:1 scale means you have real world lengths in your game.&#xA;&#xA;&#xA;  [1]: https://books.google.com/books?isbn=0080477267" ContentLicense="CC BY-SA 4.0" />
  <row Id="28653" PostHistoryTypeId="5" PostId="337" RevisionGUID="2dba963f-f2a9-4207-bcd4-d487fbff9768" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Radiosity is basically what allows this:&#xA;[![Direct Illumination VS Radiosity][1]][1]&#xA;&#xA;In a tutorial of [Cornell University about Radiosity][2] it is mentioned that:&#xA;&#xA;&gt; A ray-traced version of the image shows only the light reaching the viewer by direct reflection -- hence misses the color effects.&#xA;&#xA;However in [Wikipedia][3]:&#xA;&#xA;&gt; Radiosity is a global illumination algorithm in the sense that the illumination arriving on a surface comes not just directly from the light sources, but also from other surfaces reflecting light.&#xA;&gt;&#xA;&gt; ...&#xA;&gt;&#xA;&gt; The [radiosity method][4] in the current computer graphics context derives from (and is fundamentally the same as) the radiosity method in heat transfer.&#xA;&#xA;And if [ray tracing][5] is capable of:&#xA;&#xA;&gt; simulating a wide variety of optical effects, such as reflection ([diffuse reflection][6]) and [**scattering** (i.e. the deflection of a ray from a straight path, for example by irregularities in the propagation medium, particles, or in the interface between two media)][7]&#xA;&#xA;Has that tutorial not considered these effects or are there radiosity methods that can be used in ray tracing in order to enable them?&#xA;&#xA;If not, couldn't these optical effects simulate radiosity entirely or is the [radiosity algorithm][8] more efficient in solving the diffuse reflection problem?&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/j9CFM.jpg&#xA;  [2]: http://www.graphics.cornell.edu/online/tutorial/radiosity/&#xA;  [3]: https://en.wikipedia.org/wiki/Radiosity_%28computer_graphics%29&#xA;  [4]: https://en.wikipedia.org/wiki/Radiosity_(computer_graphics)#Confusion_about_terminology&#xA;  [5]: https://en.wikipedia.org/wiki/Ray_tracing_%28graphics%29&#xA;  [6]: https://en.wikipedia.org/wiki/Diffuse_reflection&#xA;  [7]: https://en.wikipedia.org/wiki/Light_scattering&#xA;  [8]: https://en.wikipedia.org/wiki/Radiosity_(computer_graphics)#Overview_of_the_radiosity_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="28654" PostHistoryTypeId="5" PostId="253" RevisionGUID="734c66d5-3dad-44db-b7f9-6493bd60da3f" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="From the [GIMP docs]:&#xA;&#xA;&gt; ### IIR&#xA;&gt;&#xA;&gt; IIR stands for “infinite impulse response”. This blur works best for large radius values and for images which are not computer generated.&#xA;&gt;&#xA;&gt; ### RLE&#xA;&gt;&#xA;&gt; RLE stands for “run-length encoding”. RLE Gaussian Blur is best used on computer-generated images or those with large areas of constant intensity.&#xA;&#xA;and also&#xA;&#xA;&gt; They both produce the same results, but each one can be faster in some cases. &#xA;&#xA;So the short answer is that IIR is optimised for photographs, and RLE is optimised for images with areas of flat colour.&#xA;&#xA;The claim seems to be that the only difference is the time taken to calculate the blur, and that the end results are identical. I haven't tested this, so if you need to rely on that claim you should test both and check for any differences in the results.&#xA;&#xA;&#xA;  [GIMP docs]: http://docs.gimp.org/en/plug-in-gauss.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="28655" PostHistoryTypeId="5" PostId="163" RevisionGUID="c695a908-b5b7-4988-8762-2b8a51ceda60" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="### TL;DR&#xA;&#xA;They belong to the same family of solvers, where sphere tracing is one method of ray marching, which is the family name.&#xA;&#xA;### Raymarching a definition&#xA;&#xA;Raymarching is a technique a bit like traditional raytracing where the surface function is not easy to solve (or impossible without numeric iterative methods). In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.&#xA;&#xA;This can be useful if you:&#xA;&#xA;* Need to render volumetrics that arenot uniform&#xA;* Rendering implicit functions, fractals&#xA;* Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping&#xA;* Etc&#xA;&#xA;![Traditional raymarching][1]&#xA;&#xA;**Image 1**: Traditional ray marching for surface finding&#xA;&#xA;Related posts:&#xA;&#xA;* [how-do-raymarch-shaders-work](https://gamedev.stackexchange.com/questions/67719/how-do-raymarch-shaders-work) (GameDev.SE)&#xA;&#xA;&#xA;### Sphere tracing &#xA;&#xA;Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.&#xA;&#xA;Sphere tracing is used for rendering [implicit surfaces](https://en.wikipedia.org/wiki/Implicit_surface). Implicit surfaces are formed at some level of a continuous function. In essence solving the equation&#xA;&#xA;    F(X,Y,Z) = 0&#xA;&#xA;Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.&#xA;&#xA;![Sphere tracing has a adaptive step size][2]&#xA;&#xA;**Image 2**: Sphere tracing\* in action note how the step size is adaptive&#xA;&#xA;For more info see: &#xA;&#xA;* [Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/bc4D5.png&#xA;  [2]: https://i.stack.imgur.com/dFHFY.png&#xA;&#xA;\* Perhaps in 2d it's should be called circle tracing :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28656" PostHistoryTypeId="5" PostId="156" RevisionGUID="e1998b24-51c5-4dfe-b905-fae0a0a86012" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="When I was first reading about all of this I stumbled upon this [link][1] which helped me better understand this large subject.  Also [this][2] goes into some more detail on things mentioned here.&#xA;&#xA;Light scattering is a natural phenomenon which arises when light interacts with particles distributed in a media as it travels through it.  From [Wikipedia][3]:&#xA;&#xA;&gt; Light scattering can be thought of as the deflection of a ray from a straight path, for example by irregularities in the propagation medium, particles, or in the interface between two media&#xA;&#xA;In computer graphics there are models that have been developed to simulate the effect of light traversing volume objects from an entry point (*Point A*) to an exit point (*Point B*).  As the light travels from *A* to *B* it is changed due to interactions with particles and these interactions are often referred to as **Absorption**, **Out Scattering** and **In Scattering**.  Often you will see these split into two groups; *Transmittance* (Absorption and Out Scattering) which I like to think of as 'light lost' and *In-Scattering* ('light gained').&#xA;&#xA;**Absorption** is basically incident light energy that is transformed into some other form of energy and therefore 'lost'.&#xA;&#xA;### Transmittance ###&#xA;Transmittance describes how light reflected behind a volume will be attenuated due to Absorption as it travels through a medium from *A* to *B*.  This is usually calculated with the Beer-Lambert law which relates the attenuation of light to the properties of the material through which it is travelling.  &#xA;&#xA;As the light travels through the medium there is a chance that the photons can be scattered away from their incident direction and therefore not make it to the eye of the observer and this is referred to as Out-Scattering.  In most models the Transmittance equation is changed slightly to introduce the concept of Out-Scattering. &#xA;&#xA;### In Scattering ###&#xA;Above we have seen how light can be lost due to photons been scattered away from the viewing direction.  At the same time light can be scattered back into the viewing direction as it is travelling from *A* to *B* and this is called In-Scattering. &#xA;&#xA;Particle In-Scattering itself is a pretty complex topic but basically you can split it into Isotropic and Anisotropic scattering.  Modelling Anisotropic scattering would take a considerable amount of time so usually in computer graphics this is simplified by using a Phase Function which describes the amount of light from the incident light direction that is scattered into the viewing direction as it travels from *A* to *B*.&#xA;&#xA;One commonly used non-isotropic Phase Function is called the Henyey-Greenstein phase function which can model Backward and Forward scattering.  It usually has a single parameter, g ∈ [−1,1], that determines the relative strength of forward and backward scattering.&#xA;&#xA;&#xA;  [1]: http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/volume-rendering/volume-rendering-for-artists/&#xA;  [2]: http://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/chapter4.pdf&#xA;  [3]: https://en.wikipedia.org/wiki/Light_scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="28657" PostHistoryTypeId="5" PostId="2328" RevisionGUID="f0d73421-18f7-4979-9688-45f1d514cc67" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="### A note first&#xA;From the look of your screen capture, I suspect there might still be a bug in your code. Noise is to be expected with only 16 spp, but your picture still looks surprisingly dark to me. For comparison, here is what my implementation of SmallPT looks like with 16 spp, 15 bounces, and no next event prediction:&#xA;&#xA;[![SmallPT, 16 spp, 15 bounces, no next event predicition][1]][1]&#xA;([here it is on ShaderToy][2])&#xA;&#xA;Noisy, but not nearly as dark as your picture. It is very different scene, but considering the that the shape is similar (a box with one side open and only one light source), I would expect to get a similar luminosity/noise appearance.&#xA;&#xA;_The rest of this answer assumes your code to be correct._&#xA;&#xA;---&#xA;&#xA;## Path tracing and reducing noise&#xA;&#xA;The balance between light source size, noise and SPP is a classic problem, to which there is no magical solution. From easiest to hardest, you could:&#xA;&#xA;* Use a scene that is more suitable to your algorithm:&#xA;&#xA;  Rendering algorithms have limitations, may shine in certain cases and poorly handle other cases. Knowing the limitations of yours, you can choose to restrict its use to a case that works best for it: a large light source, a sky dome, many light sources, a scene with less occlusion, etc.&#xA;&#xA;* Implement next event prediction:&#xA;&#xA;  When you know where your light sources are, at each bounce you can try and shoot rays directly toward them. If the ray doesn't hit other geometry first, you get a path that contributes. Since doing so biases the randomness, you will need to use proper factors to take it into account.&#xA;&#xA;* Implement [Bi-Directional Path Tracing][3]:&#xA;&#xA;  When tracing rays from the camera, if the light source is small, a large number of paths will never reach it. This is the problem you are having. On the opposite, when tracing rays from the light, many of them will never reach the camera. BDPT consists in first shooting rays both from the camera and from the light source, then trying to connect them. Each pair that can be connected is a contributing path. BDPT will significantly reduce noise.&#xA;&#xA;* Implement [Metropolis Light Transport][4]:&#xA;&#xA;  If there is a path between the camera and a light source, it is likely there will be a similar path between them. MLT consists in searching for those contributing paths in the neighborhood of paths that are already known to contribute by mutating them (adding, removing or changing one or more bounces). This is a lot less trivial already, as the math to keep it unbiased gets a bit hairy.&#xA;&#xA;The problem of reducing noise is still under active research though, and there is no silver bullet. At this point you will need to read what are the latest developments.&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/zFFjC.png&#xA;  [2]: https://www.shadertoy.com/view/4sfGDB&#xA;  [3]: http://www.graphics.cornell.edu/~eric/Portugal.html&#xA;  [4]: http://graphics.stanford.edu/papers/metro/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28658" PostHistoryTypeId="5" PostId="4601" RevisionGUID="dbeb38c9-16ca-480d-aaec-0429a3d50d62" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Maybe not the best solution but one that should work would be to multiply them by matrix like&#xA;\begin{bmatrix}-1&amp;0&amp;0\\0&amp;1&amp;0\\0&amp;0&amp;-1\end{bmatrix}&#xA;And multiply by this your `mvp` matrix to convert meshes vertices (this could be done offline).&#xA;&#xA;Quaternion can be change to matrix form, multiply and save as quaternion.&#xA;&#xA;You also need to change culling in `OpenGL` because triangle order will be inverted.&#xA;&#xA;I did this in one project and it works fine. If I will find this project I will write something more about it.&#xA;&#xA;//EDIT&#xA;&#xA;This matrix will invert your Z-axis and X-axis&#xA;&#xA;//EDIT2&#xA;&#xA;To apply this solution to each to component you need to:&#xA;&#xA; 1. Change translation `x` and `z` component to `-x` and `-z`.&#xA; 2. Rotation in matrix form multiply by matrix above and change it to quaternion.&#xA; 3. Scale leave how it is.&#xA;&#xA;    &lt;s&gt;4. Iterate through all meshes and multiply each of their vertices by this matrix.&lt;/s&gt;&#xA;&#xA;//EDIT3&#xA;&#xA;Instead of matrix you can just multiply rotation by quaternion `(0, 0, 1, 0)` (in order `(w, x, y, z)`) and new quaternion will look like this: `(-y,z,w,-x)`. This operation (and matrix too) just rotate object by 180 degree in y-axis.&#xA; &#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28659" PostHistoryTypeId="5" PostId="2329" RevisionGUID="44ea5547-fc8e-481b-8eac-00bc01824b60" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="## Avoid stereo when possible&#xA;&#xA;There was some research published recently measuring when users can or cannot tell whether the specular contribution, which is view point dependent, is different between eyes.&#xA;&#xA;[Perception of Highlight Disparity at a Distance in Consumer Head-Mounted Displays][1]&#xA;&#xA;In the future, this could be use to share some computation between the two eye renders. Unfortunately this sounds hard to take advantage of in a typical rasterization pipeline.&#xA;&#xA;Some games already avoid stereo when rendering far objects and background.&#xA;&#xA;---&#xA;&#xA;## Reduce shading when possible&#xA;&#xA;### Lens distortion&#xA;&#xA;Part of the NVidia VRWorks SDK is a feature, [Multi-Res Shading][2], that allow to reduce the amount of shading, to take into account the fact that some pixels contribute less to the final image due to lens distortion.&#xA;&#xA;In [Alex Vlachos' GDC 2015 presentation][3], he also mentions the idea of rendering the image in two parts of different resolution, to achieve the same goal.&#xA;&#xA;### Foveated rendering&#xA;&#xA;Finally, like your question mentions, foveated rendering aims at scaling the resolution to take into account the fact that eyes have more precision in the fovea and less in the periphery. There is some [research on the topic][4], but this requires eye tracking like in the [Fove][5] HMD.&#xA;&#xA;&#xA;  [1]: https://software.intel.com/en-us/articles/perception-of-highlight-disparity-at-a-distance-in-consumer-head-mounted-displays&#xA;  [2]: https://blogs.nvidia.com/blog/2016/04/20/ue-4/&#xA;  [3]: http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf&#xA;  [4]: http://research.lighttransport.com/foveated-real-time-ray-tracing-for-virtual-reality-headset/&#xA;  [5]: http://www.getfove.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28660" PostHistoryTypeId="5" PostId="2495" RevisionGUID="fa5b68d8-4f05-4c23-a302-d338c8a95616" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="In Schlick's 1994 paper, [&quot;An Inexpensive Model for Physically-Based Rendering&quot;][1], where they derive the approximation, the formula is:&#xA;$$F_{\lambda}(u) = f_{\lambda} + (1 - f_{\lambda})(1 - u)^{5}$$&#xA;&#xA;Where &#xA;&#xA;![Description of vectors][2]&#xA;&#xA;&#xA;So, to answer your first question, $\theta$ refers to the angle between the view vector and the half vector. Consider for a minute that the surface is a perfect mirror. So:&#xA;$$V \equiv reflect(V')$$&#xA;In this case:&#xA;$$N \equiv H$$&#xA;&#xA;For microfacet-base BRDFs, the $D(h_{r})$ term refers to the statistical percentage of microfacet normals that are oriented towards $H$. Aka, what percentage of the incoming light will bounce in the outgoing direction.&#xA;&#xA;As for why we use Fresnel in a BRDF, it has to do with the fact that a BRDF by itself is only a portion of the full BSDF. A BRDF attenuates the reflected portion of light and a BTDF attenuates the refracted. We use the Fresnel to calculate the amount of reflected vs. refracted light, so we can properly attenuate it with the BRDF and BTDF.&#xA;&#xA;$$BSDF = BRDF + BTDF\\&#xA;$$&#xA;$$\begin{align*}&#xA;L_{\text{o}}(p, \omega_{\text{o}}) &amp;=  L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BSDF * L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}} \\&#xA; &amp;= L_{e}(p, \omega_{\text{o}}) \ + \  \int_{\Omega} BRDF * L_{\text{i, reflected}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}  \ + \  \int_{\Omega} BTDF * L_{\text{i, refracted}}(p, \omega_{\text{i}}) * \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}&#xA;\end{align*}$$&#xA;&#xA;So, in summary, we use $D$ to get the percentage of light that will bounce in the outgoing direction, and $F$, to find out what percentage of the remaining light will reflect/refract. Both these use $H$, because that is the surface orientation that allows a mirror reflection between $V$ and $V'$&#xA;&#xA;  [1]: http://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf&#xA;  [2]: https://i.stack.imgur.com/xxyc2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28661" PostHistoryTypeId="5" PostId="4557" RevisionGUID="66441ffc-ca4e-4529-82fa-0255c3ed7609" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="&gt; I have some colors in RGB in [0,1] and want to find a way to rate&#xA;&gt; their similarity, as percieved by a human.&#xA;&#xA;This is a huge subject, and loosely is found under the banner of *colour appearance models*. Why is it not strictly a more simple formation is due to the psychophysical nature of colour in that colour does not exist beyond the human organism.&#xA;&#xA;&gt; My first idea is to treat the RGB colors as XYZ points and calculate&#xA;&gt; their distance.&#xA;&gt; &#xA;&gt; Another idea I have is to treat the RGB values as a histogram and use&#xA;&gt; dot product to get a similarity value between them, where a larger&#xA;&gt; value is better.&#xA;&gt;&#xA;&gt; I know however, that not all of the color channels have the same&#xA;&gt; percieved brightness so maybe i ought to weight the color channels&#xA;&gt; differently for both cases?&#xA;&#xA;Best advice is, much like cryptography, do not roll your own; you are likely to arrive at a sub-optimal system that will, in the best of cases, hit walls already hit by other researchers in the field. If you base your work on existing models and research, you might find it to be more accurate for your needs[1].&#xA;&#xA;One could point at the historical developments around CAMs, but it is easier here to suggest that you research the IPT colour encoding model and its cylindrical equivalent that models colourfulness and hue as an angle. The evolutions in the IPT model overcome most of the issues of the earlier Lab model, and simplifies some of the work involved in CIECAM02.&#xA;&#xA;&gt; Another challenge to this may be that different displays will display&#xA;&gt; the same color values differently. Not sure if that's relevant in this&#xA;&gt; case.&#xA;&#xA;IPT, and every RGB colour space for that matter, are anchored in the 1931 CIE research. As such, these sorts of issues are solved at a lower level.&#xA;&#xA;[1] This expanded answer is due to Mr. Wolfe's comment below in an attempt to explain why rolling your own solution might be a sub-optimal approach." ContentLicense="CC BY-SA 4.0" />
  <row Id="28662" PostHistoryTypeId="5" PostId="4546" RevisionGUID="c0eeafbf-cd1e-49d5-8eb7-180fa64194eb" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="As stated in [documentation][1] possible values for layout qualifiers of image formats are (for example floating point):&#xA;&#xA;&gt; Floating-point layout image formats:&#xA;&gt;&#xA;&gt;  - rgba32f&#xA;&gt;  - rgba16f&#xA;&gt;  - rg32f&#xA;&gt;  - rg16f&#xA;&gt;  - r11f_g11f_b10f&#xA;&gt;  - r32f&#xA;&gt;  - r16f&#xA;&gt;  - rgba16&#xA;&gt;  - rgb10_a2&#xA;&gt;  - rgba8&#xA;&gt;  - rg16&#xA;&gt;  - rg8&#xA;&gt;  - r16&#xA;&gt;  - r8&#xA;&gt;  - rgba16_snorm&#xA;&gt;  - rgba8_snorm&#xA;&gt;  - rg16_snorm&#xA;&gt;  - rg8_snorm&#xA;&gt;  - r16_snorm&#xA;&gt;  - r8_snorm&#xA;&#xA;So we can use `R`, `RG` and `RGBA` formats. But why `RGB` (except r11f_g11f_b10f) is not allowed?&#xA;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Image_formats" ContentLicense="CC BY-SA 4.0" />
  <row Id="28663" PostHistoryTypeId="5" PostId="4276" RevisionGUID="63e6cbb0-5792-429a-a457-a46e29dd667f" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I've the following problem:&#xA;&#xA;&gt; Let the camera opening angle be $\frac{3}{4}\pi$ and the window be $15 \times 15$ pixels large. &#xA;&gt;&#xA;&gt; Which pixels does the midpoint algorithm (_without_ anti-aliasing) set for the line from $p_1 = (1, 1, 4)$ to $p_2 = (2, 1, 1)$, given in **global coordinates**?&#xA;&#xA;My question are:&#xA;&#xA;1. Why is the detail that the points are given in global coordinates important? &#xA;&#xA;2. Could the points be given in local coordinates? If yes, how would they would look like? How would that affect the answer?&#xA;&#xA;3. What would that mean local coordinates in this case?&#xA;&#xA;I think I understood what are local coordinates, i.e. coordinates of an object given with respect to a local system to the object. I think that global coordinates at the end are just local coordinates with respect to the camera or the viewer. Am I right?&#xA;&#xA;_Note: I'm not asking you to solve the problem, i.e. telling me which pixels are set, maybe I'm going to ask another question regarding that._" ContentLicense="CC BY-SA 4.0" />
  <row Id="28664" PostHistoryTypeId="5" PostId="4241" RevisionGUID="12045235-4a6f-4f4c-93f3-4c573ae3af11" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="# Source&#xA;&#xA;In this [webpage][1] from Nvidia, the author(s) seems to imply that you could create a command buffer for each eye on separate threads. However, I don't see the benefit to this over instanced stereo rendering since you must also handle synchronization with multiple command buffers.&#xA;&#xA;# Possible Synchronization Issues&#xA;&#xA;For synchronization (feel free to correct me if I'm wrong), I was thinking about when using a framebuffer for each eye, kind of the &quot;naive&quot; way of rendering for VR. I suppose though you could just render to one framebuffer like with stereo instanced rendering. Regardless, the issue with synchronization that I'm concerned about would be if one eye finishes considerably faster than the other eye. It seems that with stereo instanced rendering, this would be less likely to happen since the workload is more divisible. The other issue I see where synchronization could cause a performance hit is that you must wait for both threads to complete sending their respective command buffer before sending it again. Arguably, this might not be a huge concern, but it seems unnecessary nonetheless.&#xA;&#xA;# Spatial Locality Issues&#xA;&#xA;It also seems that since there isn't a way to guarantee when an object is going through the pipeline that you may get additional cache misses on the GPU compared to instancing here.&#xA;&#xA;# Question&#xA;&#xA;Is there any advantage to using multiple command buffers for stereo rendering compared to instanced stereo rendering?&#xA;&#xA;  [1]: https://developer.nvidia.com/engaging-voyage-vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="28665" PostHistoryTypeId="5" PostId="4224" RevisionGUID="3b6c5e6a-7ad4-4795-a111-c7fd5c337246" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I guess physicists, and before that term was used philosophers, have always been thinking about the nature of light, color and shadow. Knowledge about those matters is not purely rooted in people trying to create the ultimate rendering technique for CGI. In [Wikipedia][1] there are whole [categories][2] that show formulas and models that were invented to describe attributes of lighting. What programmers do is to try to combine and fit those models into a probably more simple model that can be implemented in some way. &#xA;With the increase in computing power, those models align more and more with the models that were created by physicists to describe lighting in the real world. &#xA;If you look into recent (by that i mean 5 years back) papers that describe physically based rendering techniques, you will see that almost all of them base their algorithms on formulas and units of measure that are somehow used to describe real lighting.&#xA;&#xA;  [1]: https://en.wikipedia.org/wiki/Category:Photometry&#xA;  [2]: https://en.wikipedia.org/wiki/Category:Radiometry" ContentLicense="CC BY-SA 4.0" />
  <row Id="28666" PostHistoryTypeId="5" PostId="4211" RevisionGUID="86c9a456-15e9-4745-b623-816c82d37a28" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I'm trying to get a **grey** linear-RGB-triple that is equally bright as another (colorful) RGB-triple.&#xA;&#xA;I have to admit, that there is great confusion for me with all the color stuff, even though I read a lot of wikipedia articles, but I don't really get the big picture. I'm kind of lost and need help.&#xA;&#xA;Wikipedia seems to mention a formula to receive the [perceived brightness of a linear RGB color][1].  &#xA;So I can measure the brightness of my color and do something like this I suppose:&#xA;&#xA;    public Vector3d get_equally_bright_grey(Vector3d color) {&#xA;        for (double c = 0.0; c &lt;= 1.0; c += 0.001) {&#xA;            Vector3d grey = new Vector3d(c, c, c);&#xA;            if (brightness(color) == brightness(grey)){&#xA;                return grey;&#xA;            }&#xA;        }&#xA;    }&#xA;&#xA;But there has to be something other :)&#xA;&#xA;----&#xA;Some context:&#xA;&#xA;My input colors were spectral distributions that I converted to XYZ values (after [Bruce Lindbloom][2]).&#xA;Then I have converted those XYZ values to linear RGB (again with [Bruce][3]). And here comes my question.&#xA;&#xA;I know that the `Y` component of my `XYZ` triples is also something like the luminance, but I don't know how I generate a grey color XYZ color from this either..&#xA;&#xA;----&#xA;&#xA;[1]: https://en.wikipedia.org/wiki/Relative_luminance&#xA;&#xA;[2]: http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html&#xA;&#xA;[3]: http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="28667" PostHistoryTypeId="5" PostId="4179" RevisionGUID="88b01628-2ad0-498c-8303-71d15c62b931" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I've been introduced to local coordinates in contrast to the global ones which I was used to work on, where we have basically the camera at the origin.&#xA;&#xA;For example, I've the following picture of a cube:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;According to a slides that I've:&#xA;&#xA;&gt; the object is rotated about the x-axis by $R$ and then translated by $T$&#xA;&gt;&#xA;&gt; from the object's perspective, the world is first translated by $–T$ and then rotated about the (object's local) x-axis by $–R$&#xA;&#xA;Not just the sign but also the order of the transformations changes. Why is that? &#xA;&#xA;_Note: I've some ideas, clearly, but I would like to hear a good answer with a mathematical explanation_.&#xA;&#xA;  [1]: https://i.stack.imgur.com/MXVuX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28668" PostHistoryTypeId="5" PostId="4117" RevisionGUID="ebbf37a1-c893-4930-baee-40fd179848f2" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="# Old Hardware&#xA;&#xA;Some older cards didn't used to jump instructions in warps, so this was indeed an issue. If you have a conditional with these cards, the inside logic of the conditional would still be evaluated even if the block wasn't entered by any of the pixels, vertices, etc. There's little you can do in this case because every instruction will be executed. The worst case is also the best case here.&#xA;&#xA;# Modern Hardware&#xA;&#xA;However, if you are working with relatively modern hardware though, this isn't an issue and &quot;if/else&quot; blocks will be skipped when necessary. There really shouldn't be a downside to using &quot;if/else&quot; blocks compared to not using them. You are still branching with an &quot;else&quot;-less statement. In fact, some post-processing effects/deferred rendering specifically benefit from this.&#xA;&#xA;The worst case scenario is that some threads go through the &quot;if&quot; block and the rest go through the &quot;else&quot; block. The best case scenario is that all go through the &quot;if&quot; block or the &quot;else&quot; block. There isn't a downside to using &quot;if/else&quot; conditionals as they are needed (either on old hardware or newer hardware), but there's a possible upside with newer hardware." ContentLicense="CC BY-SA 4.0" />
  <row Id="28669" PostHistoryTypeId="5" PostId="4098" RevisionGUID="bef2a1ca-7f97-40e3-b7d9-34caea73544b" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Recently while searching of solving the shadow acne problem of traditional shadow mapping I implemented exponential shadow maps. It did the trick (no acne at all) but at the same time introduced other unacceptable errors.&#xA;&#xA;For depth map blur I use gaussian blur with smallest sigma=1.&#xA;&#xA;Test for shadow map:&#xA;&#xA;    float occluder = texture(shadowMap lightCoords.xy).r;&#xA;    float c = 5000.0;&#xA;    float receiver = lightCoords.z;&#xA;    float shadow = exp(c*(occluder-receiver));&#xA;    shadow = clamp(shadow, 0.0, 1.0);&#xA;&#xA;with small c factor `c=100.0`:&#xA;&#xA;[![enter image description here][2]][1]&#xA;&#xA;Unacceptable light bleeding&#xA;&#xA;with high c factor `c=5000.0`:&#xA;&#xA;[![enter image description here][4]][3]&#xA;&#xA;No light bleeding but high frequency detail appear &quot;swollen&quot;.&#xA;&#xA;Cant find optimal c - light bleeding appear even at `c=3000.0` and high frequency shadow error is already there. Not blurring the depth map helps but then aliasing occurs.&#xA;&#xA;And my question is - how can I improve this technique (ESM) or should I look for another? I think good quality shadows with nice performance are definitely possible - as seen in modern games like Witcher 3 or Fallout 4.&#xA;&#xA;  [1]: https://i.stack.imgur.com/2EHPH.jpg&#xA;[2]: https://i.stack.imgur.com/2EHPHm.jpg&#xA;  [3]: https://i.stack.imgur.com/BBYtJ.jpg&#xA;[4]: https://i.stack.imgur.com/BBYtJm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28670" PostHistoryTypeId="5" PostId="4040" RevisionGUID="d4b92838-7069-4e5f-82ba-457fdc791736" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="# Context&#xA;&#xA;As I was trying to learn more about Vulkan, I learned that certain fixed-function steps could be implemented with shader code from this video (at around the spot where he talks about the following problem):&#xA;&#xA;https://youtu.be/X8Ob_b3ANzs?t=24m&#xA;&#xA;In this video, the presenter says &quot;hitching&quot; can occur in OpenGL because for some GPUs the colorblend stage apparently needs to be recompiled at certain times. He gives an example of when a player takes out a torch and causes hitching due to bloom.&#xA;&#xA;# Questions&#xA;&#xA;Why would this shader need to be recompiled in this scenario? In what scenarios would this shader need to be recompiled? Is this common practice/an issue across vendors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28671" PostHistoryTypeId="5" PostId="4037" RevisionGUID="55567e9f-aab5-4c51-a40e-f2435bf4f1f5" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="## 1&#xA;&#xA;For each texel of the generated diffuse cube map (which has $6$ faces times $32 \times 32$ texels), the diffuse equation combines all texels of the environment map (which has $6$ faces times $64 \times 64$ texels). Thus $32 \times 32 \times 6 \times 64 \times 64 \times 6$ as stated.&#xA;&#xA;Since the article considers SH with $9$ coefficients, and each coefficient needs to combine all texels of the environment map, that's $9 \times 64 \times 64 \times 6$.&#xA;&#xA;## 2&#xA;&#xA;_&quot;Bruteforce&quot;_ doesn't necessarily refer to graph theory. In this article it refers to the naive approach of going through every single texel of the diffuse map and each time combine every single texel of the environment map.&#xA;&#xA;---&#xA;&#xA;### Appendix&#xA;&#xA;Let's describe the problem at hand.&#xA;&#xA;**As an input**, we have an environment map: it's a set of six textures forming a cube, that represents the light coming from all directions. The light is assumed to be coming from sources far enough that, at our scale, it's as if they were infinitely far. An environment map typically looks like the left figure of this illustration from the GPU Gems article:&#xA;&#xA;[![Environment map and diffuse irradiance][1]][1]&#xA;&#xA;**As an output**, for a any point of a given object that we're rendering, we want to know the diffuse irradiance affecting it. _What does that mean?_&#xA;&#xA;### A parenthesis&#xA;&#xA;Models describing how the perceived color of a surface varies depending the light reaching it, typically consist in [integrating all incoming light over an hemisphere][2], with a weight that depends both on the direction of the light and of the observer.&#xA;&#xA;For opaque materials, it is common to consider two components contributing to that color: the diffuse and the specular. The diffuse is due to light slightly penetrating the surface, getting partly absorbed, then getting out in random directions. The specular is due to light bouncing off the surface without entering it.&#xA;&#xA;[![Diffuse and specular reflections][3]][3]&#xA;&#xA;### Back to the problem&#xA;&#xA;So we want to know the color of the points of an object, we know that to compute it we need to integrate light in all directions, and we have a cube map that represents light coming from all directions. So far so good.&#xA;&#xA;A problem though is _integrating_ basically means we need to go over every single texel of the hemisphere (so half the environment map: $(64 \times 64 \times 6) / 2$ texels), do some math, and add that to the result. That's a lot of computation for each point, which we'd like to avoid if possible.&#xA;&#xA;We know that the contribution of one light depends on the light direction. If we consider the environment to be static (the lighting doesn't change), then we can isolate the part of the computation that only depends on the light and surface normal (and not on the material or the observer), pre-compute it and store it to use later. For the diffuse term, that's the _diffuse irradiance_ mentioned earlier, and it typically looks like the center figure of the illustration. Each pixel represents the irradiance term for a given surface normal. The right figure is the specular environment map, computed in a similar way but with a different integral.&#xA;&#xA;[![Environment map and diffuse irradiance][1]][1]&#xA;&#xA;With that texture, instead of painfully integrating, we just fetch the precomputed result, combine it with the rest of the equation (the material diffuse color, etc.) and voilà.&#xA;&#xA;### Finding the 32x32x6x64x64x6&#xA;&#xA;Since the result looks very blurry, it probably doesn't need to be $64 \times 64$ for storing, and the article assumes $32 \times 32$. But still, each of those $32 \times 32 \times 6$ texels' color is computed separately, by integrating over the entire corresponding hemisphere. That part never disappeared: we just moved it from the rendering stage to a pre-computation stage.&#xA;&#xA;So that's still $(32 \times 32 \times 6) \times (64 \times 64 \times 6) / 2$. That's half the figure stated in the article. I suppose the author was either assuming a model that integrates of the entire sphere, or just dropped the $0.5$ factor for the sake of clarity.&#xA;&#xA;### Finding the 9x64x64x6&#xA;&#xA;We can't help but notice this irradiance diffuse environment map is really blurry: surely there must be a way to store its information using a lot less than $32 \times 32 \times 6$ terms, and hopefully reduce the amount of work as well. That's what [spherical harmonics][4] do, by compressing the irradiance in just a few coefficients.&#xA;&#xA;I am not familiar enough with the math to engage in an explanation, but suffice to say it is generally considered that for diffuse, order three SH are sufficient. Order three SH involve nine coefficient, and again, for each of these we need to integrate over the entire hemisphere.&#xA;&#xA;So that's $(9 \times 64 \times 64 \times 6) / 2$ texels to fetch and process. Here too a $2$ factor is missing from the article.&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/ZFIHb.jpg&#xA;  [2]: https://en.wikipedia.org/wiki/Rendering_equation&#xA;  [3]: https://i.stack.imgur.com/85Pmg.png&#xA;  [4]: https://en.wikipedia.org/wiki/Spherical_harmonics" ContentLicense="CC BY-SA 4.0" />
  <row Id="28672" PostHistoryTypeId="5" PostId="4030" RevisionGUID="3a31e6c1-c5ac-45eb-b749-1d5ab07262c0" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="*&quot;Go not to the CG Elves for counsel for they will say both no and yes&quot;.* &#xA;&#xA;  Yes and No. As noted in another post, these issues don't exist with ray tracing but I'll assume you are interested in standard rasterisation.&#xA;&#xA; - It's possible to dispose of near clipping by using homogeneous rendering but that can introduce additional cost. (e.g more expensive triangle set up, more difficulty in identifying which screen regions are covered in tile-based renderers) &#xA;&#xA; - You could eliminate XY clipping by using float representations for the X and Y coordinates in the rasteriser *but* that can lead to catastrophic cancellation when computing triangle determinants which, AFAICS, is a necessary step. In my experience, hardware rasterisers* usually work in fixed-point so that everything is 'exact'.&#xA;&#xA; - As a compromise to XY clipping, guard-band clipping was introduced so that clipping only needs to be done on triangles that extend a 'long'** way off screen. Culling, however, is still be done with the standard frustum planes to eliminate those that are trivially off-screen.&#xA;&#xA;&#xA;*Dreamcast being a notable exception.&#xA;&#xA;**for certain definitions of 'long', e.g. a small integer multiple of the screen width/height." ContentLicense="CC BY-SA 4.0" />
  <row Id="28673" PostHistoryTypeId="5" PostId="4024" RevisionGUID="da5008e8-5982-47fa-9819-92700a8f1cd0" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="# Explanation&#xA;&#xA;With a non-linear scale, you apply different weights for each pixel (or whatever unit you are using). You can use Euclidean distance towards the closest pixels in both directions to determine the weights.&#xA;&#xA;# Example&#xA;&#xA;## Normalization&#xA;&#xA;For example, in the image below, the red image is the downsampled image (3x3) and the black image is the original image (4x4). The dots represent the sample points (center of the pixels).&#xA;&#xA;You can align the two images by treating each pixel coordinate as a set of two values (x and y) between 0 and 1 (inclusive). Pixels should not be treated as square, so you should treat each pixel as a point rather than a square (when aligning the two images).&#xA;&#xA;[![Larger and downsampled image][1]][1]&#xA;&#xA;In the above image, the four corners would all carry the weight of the original image's four corners, for example. The points in the middle would carry different weights depending on the difference between the four neighboring points.&#xA;&#xA;## With numbers:&#xA;&#xA;This is a hypothetical area to sample in larger images (not related to the image above). The distances are between original pixels are normalized from 0 to 1 to simplify the math. &#xA;&#xA;The black dots represent the sample points (pixels) of the original image. The larger red dots represent the sample points of the downsampled image. The red dot in the top left is closer to the black dot in the top left than the other three surrounding dots, so that pixel will have a heavier weight for determining the color of the downsampled pixel.&#xA;&#xA;[![Closeup of sampling region][2]][2]&#xA;&#xA;Horizontal distance from:&#xA;&#xA; - Right 2 original (green) pixels = 0.1 pixels&#xA; - Left 2 original (green) pixels = 0.9 pixels&#xA;&#xA;Vertical distance from:&#xA;&#xA; - Top 2 original (green) pixels = 0.1 pixels&#xA; - Bottom 2 original (green) pixels = 0.9 pixels&#xA;&#xA;Weight for final pixel:&#xA;$$weight(0, 0) = (1.0 - 0.1)(1.0 - 0.1) = 0.81$$&#xA;$$weight(0, 1) = (1.0 - 0.1)(1.0 - 0.9) = 0.09$$&#xA;$$weight(1, 0) = (1.0 - 0.9)(1.0 - 0.1) = 0.09$$&#xA;$$weight(1, 1) = (1.0 - 0.9)(1.0 - 0.9) = 0.01$$&#xA;&#xA;Subtract from 1 both the horizontal and vertical distance (because closer pixels should carry more weight). The scale factor in this example is 0.75 in each direction.&#xA;&#xA;# Scaling Up vs. Scaling Down&#xA;&#xA;Scaling up in the same  process as scaling down. By normalizing both the original image and the new image to between (0, 0) and (1, 1), you can do either with the same process. As an exercise, in the first figure, if the red points were from the original image and the black points were from the enlarged image, you should be able to see that the process is the same.&#xA;&#xA;  [1]: https://i.stack.imgur.com/dPoxG.png&#xA;  [2]: https://i.stack.imgur.com/B2wip.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28674" PostHistoryTypeId="5" PostId="3864" RevisionGUID="ecd525d6-2073-42a0-80a3-b6e7e4904c48" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="**Intro**&#xA;&#xA;Maxwell Render has a feature called _multilight_, where one can ray-trace a scene with multiple light sources, and **change the brightness** of the individual light sources _afterwards_.&#xA;Luxrender has a similar feature called _light groups_.&#xA;&#xA;I image that behind the scenes, these renderers keep track of the contributions of the different light sources separately, and then composing a final image (given brightnesses of light sources) just amounts to mixing these per-light contributions with appropriate coefficients. Effectively, instead of keeping track of the color of a ray as a tuple (R,G,B), one keeps track of more numbers (R1, G1, B1, R2, G2, B2, ..., Rk, Gk, Bk) if there are k light sources (let's assume no spectral rendering, just for ease of notation -- it's conceptually identical).&#xA;&#xA;From a mathematical point of view, the final image is a **linear combination** of the images resulting from the individual light sources.&#xA;&#xA;---&#xA;&#xA;**Question**&#xA;&#xA;Now it seems interesting to have a similar feature that allows **changing the colors of objects** in the scene _after rendering_.&#xA;This can be done with an entirely similar technique: suppose that we have two objects whose color we want to be able to change after rendering. The final image is a **polynomial** in the color of these objects, with two variables (one for each object) and of degree n, where n is the maximum number of bounces for a ray.&#xA;&#xA;Specifically, instead of keeping track of tuples (R,G,B), the integrator would keep track of&#xA;expressions of the form (R00,G00,B00) + (R10,G10,B10)x + (R01,G01,B01)y + (R11,G11,B11)xy + (R21,G21,B21)x²y + ..., for a total of k^n terms, where k is the number of colors you want to be able to change, and n the maximum number of bounces.&#xA;For modest k and n, this certainly seems tractable. Color calculations become more expensive, as does storing the resulting &quot;polynomial-image&quot;, but all the geometric calculations are identical.&#xA;&#xA;&gt; Is this feature implemented in any widely available renderers?&#xA;&gt;&#xA;&gt; - If so, which ones?&#xA;&gt;&#xA;&gt; - If not, why not? Is this not something that's useful in practice? Is it not computationally feasible?&#xA;&#xA;---&#xA;&#xA;**Remark**&#xA;&#xA;I hope I've made myself clear in my explanation. I don't know much about computer graphics (mathematician by training), so my notation may be unusual. More general that just changing the colors of objects, one could change more properties of materials after rendering. For example, the transparency of objects could be changed afterwards (though assuming importance sampling is used by the integrator, this comes at the cost of noise, I guess).&#xA;&#xA;&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28675" PostHistoryTypeId="5" PostId="3832" RevisionGUID="9b0751ca-7eba-4b9e-9465-e9190bb0af1a" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="1. A &quot;face&quot; simply specifies one of the six images at a level in a cubemap (and its optional mip pyramid). &#xA;&#xA;    It is helpful to think of level L of your mipmapped cube array texture as consisting of a 2D array of images, with exactly six columns comprising the six faces of the logical cube, and the N rows corresponding to the N layers of the array (some APIs call these &quot;slices&quot;). This is because non-array Cube textures are already structured like 2D arrays with exactly 6 layers. &#xA;&#xA;2. This is correct with the exception that it would refer to the entire mip pyramid for that layer-face. Regarding the 2D array of faces and layers i just mentioned, OpenGL uses a single index for this 2d array, &quot;unrolls&quot; it, and calls this 1D index a &quot;layer-face&quot;.  &#xA;&#xA;3. Yes, but again, encompasses the mip pyramids for each layer-face image in that layer&#xA;&#xA;4. Depends on the context, could be either.&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28676" PostHistoryTypeId="5" PostId="3655" RevisionGUID="07e5e9cd-809b-45e2-8861-c97033040f91" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="It seems like you're asking two things.  I can't really speak technically about JBU, but I can give an overview of the necessary concepts and bilateral filtering generally.  You'll probably need to find more details yourself, but this should give a coherent structure to start from.&#xA;&#xA;---&#xA;&#xA;## Fixing &quot;Image&quot;s&#xA;&#xA;Many image-processing people view filtering as either something to be done as a post-process, or as a way to scale images.  The mathematician's perspective is more accurate, descriptive, and complex.&#xA;&#xA;When you have an image file, you don't have a real image.  You have pixel &quot;values&quot;, which are strictly valid _only_ at the center of pixels.  Roughly speaking, each pixel has an _area_ that takes on that color.  Mathematically, what you're doing is using a _nearest-neighbor reconstruction filter_ to reconstruct the true image from pixel values.  So **an &quot;image&quot; is really a set of samples and a reconstruction filter, typically nearest-neighbor**.&#xA;&#xA;## Resampling&#xA;&#xA;When you upscale an image, what you're really doing is _resampling_.  How do you do this?  You take your signal, and generate a new set of samples from it.  But for an image, I just said we don't _have_ the real image; we have to reconstruct it first.  So a typical resampling procedure looks like this:&#xA;&#xA;1. Take your pixel values.&#xA;2. Reconstruct an image between the values, which live at pixel centers, by using reconstruction filtering.&#xA;3. Measure a new set of samples from the reconstructed image, possibly spaced differently.&#xA;4. Throw away the old samples and use the new ones.&#xA;&#xA;**The key point is that the reconstruction filter used is the &quot;filter&quot; used for resampling.**  For example, a &quot;bicubic upsample&quot; would use a bicubic reconstruction filter.&#xA;&#xA;It turns out that if you use a sinc function for the reconstruction filter, and you don't shrink the image, you get (theoretically) the same image back.  In fact, if you upscale the image and then downscale it again, you'll get the same answer.  This isn't generally true for any other filter.&#xA;&#xA;Most filters approximate a sinc filter to more or lesser degrees.  Deviations result in image loss.&#xA;&#xA;## Filtering&#xA;&#xA;If you use the same before/after sampling rate, you do something called &quot;filtering&quot;.  Formally, **filtering is resampling without a change in sample rate.  Filtering is a special case of resampling.**&#xA;&#xA;The only possible purpose to filtering it to throw away information (e.g. a Gaussian) or possibly also to distort or add spurious information (e.g. a Sobel).&#xA;&#xA;# Bilateral Filtering&#xA;&#xA;You can use many different filters for filtering.  Bilateral filtering is one of them.  I don't believe it's considered state-of-the-art for any purpose now (though I don't know what is; probably some newfangled machine-learning thing I expect).&#xA;&#xA;A bilateral filter is a non-linear filter, meaning it doesn't have a nice Fourier representation.  Conceptually, it is like a Gaussian, but the source colors themselves also factor into a pixel's &quot;distance&quot; from others.  This tends to smooth flat areas while preserving edges.&#xA;&#xA;# Bilateral Upscaling&#xA;&#xA;By now, I hope you see where I'm going with this: any filter you can use for filtering, you can use for upscaling or downscaling, which are really the same thing (because all of it is resampling).&#xA;&#xA;If you've implemented a bilateral filter, you should be able to rather simply implement a bilateral filter resampler - just as, if you've implemented a Gaussian filter, you should be able to implement a Gaussian filter resampler.&#xA;&#xA;The only difficulty may be the definitions.  Unfortunately, the distinction between filtering and resampling is systemically muddied to occasional non-existence in the image-processing literature.  For implementing a bilateral-type filter, I would rely heavily on its similarities to Gaussian resampling.  IIRC (I haven't read the paper in years) bilateral filtering is posed in terms of pixels, not samples." ContentLicense="CC BY-SA 4.0" />
  <row Id="28677" PostHistoryTypeId="5" PostId="3607" RevisionGUID="e0b28e7b-bfed-486b-a058-da2533cc2b58" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="## α = 90° - β/4&#xA;&#xA;Lets call the bend angle `β`.&#xA;The math is quite easy after following observation:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;We can draw a perpendicular bisector `middle-&gt;w` of the isoscles triangle `v1-&gt;middle-&gt;v2`. Then the anlge at `v1` is the desired `α`, the angle at `w` is `90°` and the angle at `middle` is just `β/4`. &#xA;&#xA;By the [triangle postulate](https://en.wikipedia.org/wiki/Sum_of_angles_of_a_triangle) the sum of the interior angles of a triangle is `180°`. By applying this to our new triangle we get&#xA; `180° = α + 90° + β/4`, so we get &#xA;&#xA;## α = 90° - β/4&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/Xv0WO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28678" PostHistoryTypeId="5" PostId="3602" RevisionGUID="cb019c01-8b5f-45dd-9e1b-6c26c8e9c798" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="My understanding is that in 5.4, instancing will use API calls like glDrawElementsInstanced and shaders need to be modified for instance buffers like in this document: [Basic GPU Instancing Support | docs.google.com][1]&#xA;&#xA;&gt; UNITY_INSTANCING_CBUFFER_START (MyProperties)&#xA;&gt;&#xA;&gt; UNITY_DEFINE_INSTANCED_PROP (float4, _Color)&#xA;&gt;&#xA;&gt; UNITY_INSTANCING_CBUFFER_END&#xA;&#xA;&#xA;  [1]: https://docs.google.com/document/d/1RS6cVjE8mBVOKqQUuXbaZcPW3kmw3ZWySJwr-5rDwSs/edit" ContentLicense="CC BY-SA 4.0" />
  <row Id="28679" PostHistoryTypeId="5" PostId="2533" RevisionGUID="009836cb-ff20-4b11-957a-aa785a5e3963" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="As you said you want to create something like this [![][1]][1]&#xA;&#xA;As you know these are not graphic intense rendering.&#xA;Thus, (i guess but not 100%) Windows do these rendering on CPU not on GPU.&#xA;GPU is for intense rendering with lighting, textures, 3D models, etc. Where you can take the benefit of algorithm built in GPU circuit, Which is what OpenGL does.&#xA;&#xA;So i would recommend to use built-in libraries that don't use GPU and use CPU for rendering, Although you can use OpenGL or Direct3D as well.     &#xA;&#xA;Some libraries that are built in different programming languages are :-&#xA;&#xA;&gt;Java - Jframe, Graphics, Buffered image,  Canvas. (Note : all these libraries have different functionality and you have to use them together for software rendering [See this for more detail][2]) &#xA;&gt;&#xA;&gt;C# - System.drawing,  (i don't have much experience of C#, So i can't name any more libraries), also C# form application.&#xA;&gt;&#xA;&gt;JavaScript - Canvas [check this out][3]&#xA;&gt;&#xA;&gt;C++ - you need third party libraries like QT, GTX etc. [Qt learning resource][4], [related resource][5]&#xA;&gt;&#xA;&gt;Python - Pygame (No personnal eperience) [See this for detail][6]&#xA; &#xA;  [1]: https://i.stack.imgur.com/WOk2z.png&#xA;  [2]: https://www.youtube.com/playlist?list=PLEETnX-uPtBUbVOok816vTl1K9vV1GgH5&#xA;  [3]: https://www.youtube.com/playlist?list=PLh-MBXZEiyMhulEqYE3gn63idSAKG6Sx1&#xA;  [4]: https://www.youtube.com/watch?v=6KtOzh0StTc&amp;list=PL2D1942A4688E9D63&#xA;  [5]: https://www.youtube.com/watch?v=FxCC9Ces1Yg&amp;list=PLSPw4ASQYyymu3PfG9gxywSPghnSMiOAW&#xA;  [6]: https://www.youtube.com/playlist?list=PLQVvvaa0QuDdLkP8MrOXLe_rKuf6r80KO" ContentLicense="CC BY-SA 4.0" />
  <row Id="28680" PostHistoryTypeId="5" PostId="2484" RevisionGUID="95d9447b-8b4d-4837-8799-e28db60ea80d" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="In [this tutorial][1], &#xA;&#xA;&gt; It is very often the case that triangles are rendered that share&#xA;&gt; edges. OpenGL offers a guarantee that, so long as the shared edge&#xA;&gt; vertex positions are identical, there will be no sample gaps during&#xA;&gt; scan conversion.&#xA;&#xA;1 What exactly are sample gaps during scan conversion? &#xA;&#xA;2 Under what circumstances, will it happen? &#xA;&#xA;3 Does it happen when the line cross the center of the fragment?&#xA;&#xA;  [1]: https://www.roiatalla.com/public/arcsynthesis/Basics/Intro%20Graphics%20and%20Rendering.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="28681" PostHistoryTypeId="5" PostId="8954" RevisionGUID="ed0d7de6-9869-48c3-b95c-4986437d7f2c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="&gt; The 2D pipeline involves ... [coordinate transformation terms]&#xA;&gt;&#xA;&gt; Can someone give me the detail differentiation among these?&#xA;&#xA;This is something I very recently learned while trying to understand how software handles 3D graphics behind the scenes. I've never encountered these terms in reference to 2D graphics before, but the ideas still apply. 2D graphics are just 3D graphics without a few fancy tricks.&#xA;&#xA;# Very Generally&#xA;Most of these different coordinate spaces don't technically exist. They come about by considering the objects you wish to draw from some reference point. When you change that reference point, you change the coordinate space. Math gets involved, but I won't do any here.&#xA;&#xA;# The Drawing Device and Device Coordinates&#xA;&#xA;&gt; ... converting normalized coordinate to device coordinate.&#xA;&gt;&#xA;&gt; Isn't viewing coordinate and device coordinate the same things?&#xA;&#xA;Short answer, no, but they can be in certain 2D cases. In 3D, pretty much never.&#xA;&#xA;There seems to be a confusion not just between view and device coordinates, but also with the distinction between normalized and device coordinates. Lets start with normalized and device, and we'll get to view later.&#xA;&#xA;In 3D systems (and 2D systems setup to work like them) you are presented with a &quot;drawing device&quot; consisting of two parts: drawing tools (usually functions accessed from application code) and a drawing area. Ignoring the tools, the important thing is that the drawing area has a coordinate system independent of pixels which adds a lot of flexibility and generality to the device.&#xA;&#xA;Any time something is setup to work numerically in a range from 0 to 1 it is &quot;normal&quot;, and often the range 0 to -1 is included too. With a drawing device the coordinates for both the X and Y directions of your drawing area range from -1 to 1, with -1 meaning &quot;all the way left&quot; for X and &quot;all the way down&quot; for Y, and 1 meaning &quot;all the way right&quot; or &quot;all the way up&quot; for X and Y respectively.&#xA;&#xA;You can easily add a Z direction too (also ranging from -1 to 1) for &quot;3D&quot; drawing, but all this does is give you a layered 2D image. There is no perspective (or &quot;depth&quot;) in your final drawing which is great for 2D games and graphics. The reason for this is that the drawing device will simply divide the space up into pixel size steps along X and Y then draw each pixel back to front (-Z to +Z). If you want real 3D though, you'll need some extra mathematical steps.&#xA;&#xA;It is possible (and common) for the device to understand and work with coordinates outside the -1 to 1 range. However, if we want an object to appear on screen than it must be &quot;normalized&quot; so that any coordinates it refers to are within -1 to 1. After this is done to an object the terms &quot;normalized coordinates&quot; and &quot;device coordinates&quot; are practically synonymous, just one refers to the object you altered so that it would fit within the drawing area and the other refers to the drawing area itself.&#xA;&#xA;# Object and World Spaces&#xA;&#xA;&gt; The 2D [or 3D] pipeline involves with the construction of world coordinate scene ...&#xA;&#xA;Yes, but you start in &quot;object space&quot;.&#xA;&#xA;When someone creates a model of an object (or draws a sprite) all that matters to them, coordinate-wise, is where zero is within the space they're working. This consideration is called &quot;object space&quot; because the artist isn't concerned with the -1 to 1 drawing area, only accurately representing the object they'd like to draw. A model of a pen might be 6 units long and a model of a person might be 5.5 units tall. The important thing is that all of the points that make up some object are positioned with regard to the coordinate (0, 0, 0) and nothing else.&#xA;&#xA;When later loaded into memory they will be too big for the drawing area (which is only 2 units tall and wide) and the pen will appear larger than the person. It's up to us humans to know what the units mean and adjust them properly. Resizing and positioning all objects in relation to each other instead of each individually being sized with relation to zero transforms the objects into &quot;world space&quot;.&#xA;&#xA;From the shortness of your question I wasn't sure if you knew that yet or not, but I thought I'd include that for completeness, as a good foundation for answering the next part of your question.&#xA;&#xA;# View Space&#xA;&#xA;&gt; ... followed by converting world coordinate to viewing coordinate ...&#xA;&gt;&#xA;&gt; Isn't viewing coordinate and device coordinate the same things?&#xA;&#xA;Note that in my explanation above nothing ever happened to the drawing device, or the coordinates of the drawing area. The only thing that ever changed was the objects we wanted to draw. The drawing area is fixed and unchanging, only ever drawing any object that fits within the coordinates -1 to 1.&#xA;&#xA;Each object loaded appears at the center of the drawing area at whatever size it was designed to have (object space) which is practically always too big for the drawing device. After rearranging and resizing every object around each other (object space → world space) we still have a final scene that is too big for the drawing area, and we have no way to move around within the scene. This is where we transform everything into &quot;view space&quot; and work with &quot;eye coordinates&quot;. Again, there is no such space, but what we do to work within it is to consider an imaginary camera and, treating the entire world as one giant object, we resize and reposition everything with respect to the position of the camera. That is &quot;view space&quot;, the movement of everything around a camera, and the terms &quot;view coordinates&quot; (or &quot;eye coordinates&quot;) refer to the positions of everything in relation to the camera.&#xA;&#xA;# View to Viewport&#xA;&#xA;At this point everything that you want to see should be within the device space, but there are still a few last tasks to perform to get everything to draw.&#xA;&#xA;If you were working on a 3D scene instead of a 2D one, you would perform a &quot;perspective transformation&quot; to create the illusion of depth. This is where you squish and warp things to make them look like they're shrinking into the distance.&#xA;&#xA;Anything outside the drawing area needs to be thrown out. This saves on work for the computer, and it also is considered another transformation from view space to &quot;clip space&quot; because you are &quot;clipping away&quot; the extra data.&#xA;&#xA;And finally, after clipping, you'll do a &quot;viewport&quot; transformation that turns the -1 to 1 coordinates into pixel coordinates.&#xA;&#xA;# Summary&#xA;&#xA;Well... I didn't intend for this answer to get so long. My apologies if I covered anything you already knew. It's hard to guess what someone does or does not already understand. Please leave a comment if you have any further questions.&#xA;&#xA;**Object Coordinates:** The positions of points relative to a zero point. The points referred to are the building blocks of some single object.&#xA;&#xA;**World Coordinates:** The positions of collections of points (objects) relative to a single shared standard zero point.&#xA;&#xA;**View Coordinates:** The position of all points (the whole scene) relative to a camera.&#xA;&#xA;**Device Coordinates:** Any position within -1 to 1 on both the X and Y axis (and Z too for 3D). Any point within the drawing area of the device.&#xA;&#xA;**Normalized Coordinates:** The positions of points of any object (or the whole scene) that have been transformed to fit within the -1 to 1 space of the drawing device.&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28682" PostHistoryTypeId="5" PostId="6230" RevisionGUID="c41bc6c2-6e40-4e55-9bf5-cbaffa7493b4" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Taken from [The Making Of &quot;Shadow Of The Colossus&quot;:&#xA;](http://www.froyok.fr/documents/making_of_sotc.pdf)&#xA;&gt; The rough algorithm is outlined below:&#xA;&gt;&#xA;&gt; 1. Rendering the distant view, and save it.&#xA;&gt; 2. Foreground rendering.&#xA;&gt; 3. Composite the distant view and foreground together. It uses the contents of the Z-buffer like a mask pattern (see image 2).&#xA;&gt; 4. Again using the Z-buffer, generate a separate image of the mask pattern.&#xA;&gt; 5. Reduce this to 64x64 pixels, using a bilinear filter. (This makes it ultra-low resolution.) This gets reused in step (8).&#xA;&gt; 6. Blend in the previous frame (from step 7) using a percentage specified in the scene box.&#xA;&gt; 7. Store the image for use in step (6). It is used for drawing the next frame.&#xA;&gt; 8. Expand step (5) to a suitable resolution, using the bilinear filter. Thus, it becomes the material for the bloom effect where the&#xA;&gt; distant view starts bleeding out from the shape of the foreground.&#xA;&gt; 9. Blend (7) and (8) using a ratio specified in the scene box.&#xA;&gt; [![enter image description here][1]][1]&#xA;&gt;&#xA;&gt; Landscape rendering is divided into 3 stages, the furthest background&#xA;&gt; being either a rendered image or a texture, which is stuck on a&#xA;&gt; distant polygon. The internal development team nicknamed this &quot;Super&#xA;&gt; Low&quot;. &#xA;&gt; &#xA;&gt; Consequently, most of the medium range which goes from nearby to&#xA;&gt; just past the furthest background, is rendered using a low-resolution&#xA;&gt; landscape. This is managed in units of 600x600m, and as the player&#xA;&gt; approaches it, once he gets nearer than a certain fixed distance, it&#xA;&gt; changes to the high-res landscape model for the foreground. This&#xA;&gt; switch is designed to blend well so it not obvious. &#xA;&gt; &#xA;&gt; In addition before&#xA;&gt; being combined down into one picture for the Super Low, most of the&#xA;&gt; distant scenery being managed in 600x600m chunks has been reduced to&#xA;&gt; around 1/30th - 1/100th of the polygons. Because there is little&#xA;&gt; memory, we usually try and spread it around the landmark which&#xA;&gt; represents that area. The combined image for the most distance scenery&#xA;&gt; is done using this low-res model. With this, the low-resolution model&#xA;&gt; appears seamlessly out of the Super Low image. By connecting the&#xA;&gt; foreground and distant background well, we are able to produce a&#xA;&gt; landscape rendering system which seems very natural.&#xA;&gt; [![enter image description here][2]][2]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/ePJ61.png&#xA;  [2]: https://i.stack.imgur.com/UTSjG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28683" PostHistoryTypeId="5" PostId="6085" RevisionGUID="aa6e14c8-9790-4f5b-9e39-0dcf2713923f" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I'm currently making a small 3D renderer and I got stuck in Phong shading.&#xA;&#xA;My questions are: &#xA;&#xA;1. Into which space should the light coordinate be converted? &#xA;&#xA;   I have my light position at world coordinates (0,0,0). I'd like to calculate &quot;phong shading&quot; after converting all the vertices to screen space (viewport). &#xA;So Should I convert the light position to screen space too?    &#xA;&#xA;2. Is there a faster way to calculate Phong shading with normal interpolation if the camera's position equals the light's position?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28684" PostHistoryTypeId="5" PostId="5932" RevisionGUID="e192d859-cff8-4b98-98a7-5cb0f53beb2c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I don't have a definite authoritive answer for you but I'm very confident that the answer is &quot;yes&quot;. Here's why:&#xA;&#xA;When using framebuffer objects, [stencil attachments are usually combined][1] with the depth attachment in a single texture (`GL_DEPTH24_STENCIL8` or `GL_DEPTH32F_STENCIL8`). In fact, until recently, a combined depth and stencil was the only way to get a stencil buffer. It is now possible to create a stencil only attachment for an FBO.&#xA;&#xA;This [OpenGL wiki article on FBOs][2] states (emphasis mine):&#xA;&#xA;&gt; These color formats can be combined with a depth attachment with any of the required depth formats. Stencil attachments can also be used, again with the required stencil formats, as well as the combined depth/stencil formats. However, **implementations are only required to support both a depth and stencil attachment simultaneously if both attachments refer to the same image**.&#xA;&gt;&#xA;&gt; This means that if you want stencil with no depth, you can use one of the required stencil formats. If you want depth with no stencil, you can use one of the required depth formats. **But if you want depth and stencil, you must use a depth/stencil format and the same image in that texture must be attached to both the depth and stencil attachments**.&#xA;&#xA;All this strongly hints towards an accelerated storage format for stencils similar to the one used by depth buffers.&#xA;&#xA;Also, empirically, over the years many rendering algorithms (e.g. stencil shadows) using the stencil buffer would have been prohibitively slow if stencil buffers did not use some form of accelerated structure.&#xA;&#xA;The [NV_packed_depth_stencil extension][3] (2001) spec also provides interesting insight:&#xA;&#xA;&gt; Many OpenGL implementations have chosen to interleave the depth and stencil buffers into one buffer, often with 24 bits of depth precision and 8 bits of stencil data.&#xA;&#xA;and (emphasis mine)&#xA;&#xA;&gt; Should the depth/stencil format support other standard types, like GL_FLOAT or GL_UNSIGNED_INT?&#xA;&gt;&#xA;&gt; RESOLVED: No, this extension is designed to be minimalist. Supporting more types gains little because the new types will just require data format conversions.  **Our goal is to match the native format of the buffer**, not add broad new classes of functionality.&#xA;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Format#Depth_stencil_formats&#xA;  [2]: https://www.khronos.org/opengl/wiki/Framebuffer_Object&#xA;  [3]: https://www.khronos.org/registry/OpenGL/extensions/NV/NV_packed_depth_stencil.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="28685" PostHistoryTypeId="5" PostId="5728" RevisionGUID="871b2810-6bc8-4c9d-9135-1de8ef687f19" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Yes, such rendering exists. It is called a parametric surface and there are several methods you can render such entities. In this case you are talking of bezier patches.&#xA;&#xA;&#xA;1. Turn the object into enough triangles. The triangilation is called tesselation or meshing depending on what literature you read.&#xA;&#xA;    There are lots of applications that do this allready. Most cad applications work this way and many graphics apps like blender can work &#xA;this way.&#xA;&#xA;2. raytrace or raymarch the surface in a shader.&#xA;&#xA;3. Microdice the surface&#xA;&#xA;4. etc.&#xA;&#xA;The reason this is not often done is that the on line tesselation is for most intent and purposes just a hindrance to asset developpers. You get the same with subdivision schemes and its just easier. The primary reason to drag the bezier (or nurbs, or t-splines...) is that unless you need to find better intersection of underlying primitives then it is often just a waste of resources. Although subdividing your mesh  via a subdivision surface is allready more useful&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28686" PostHistoryTypeId="5" PostId="5725" RevisionGUID="e27a45d8-e10a-4fb2-8fb4-4bce1a4e9635" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="First, `gl_FragCoord.xy` are screen space coordinates of current pixel based on viewport size. So if viewport size is `width=5`, `height=4` then each fragment contains:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;Why are uvs needed? For example I rendered geometry to screen quad and then I need to apply some postprocessing on this quad in another rendering pass. To sample from that quad I need texture coordinates in range [0, 1]. So to calculate them I perform division `gl_FragCoord.xy / viewPortSize`.&#xA;&#xA;  [1]: https://i.stack.imgur.com/Oa1zn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28687" PostHistoryTypeId="5" PostId="5684" RevisionGUID="ed37ae39-81c5-4f14-9b51-99a896fdd841" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I need to highlight(colour) sun reflections(through the year) off a mirror surface. It was easy having one Sun like in the below image but how about if it is to determine if a ray hits the entire surface that represents sun positions throughout the year. &#xA; &#xA;**Update**:&#xA;&#xA;  Suppose the house surfaces are all mirror, so that from specific angles the viewer might see the reflection of the sun off the house surfaces. this is easy to render an image that simulate this but how about rendering an image that shows the reflection of not just one Sun, in a specific day time, but all the Suns, one for every second throughout the year. It's not efficient to dump in all these Suns into model and intersect them for each surface point. So I need to check if a ray intersects the entire surface that represents the path of the sun throughout the year.&#xA;&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/S7EU4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28688" PostHistoryTypeId="5" PostId="5651" RevisionGUID="88d3debf-eba9-47de-bd43-f2a2aa95b5e7" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="- I have done my due hour of research before asking this question, it's a simple question, but I have found no hint at an answer online.&#xA;&#xA;I want the ability to extend an object infinitely in one direction, such as a tower that appears infinitely high, or a road infinitely long. I have tried my hardest to think up an approach to this that doesn't cheat, but nothing has come to mind.&#xA;&#xA;An example, take a textured cube, and have it appear infinitely tiled in one direction, to its vanishing point:&#xA;[![enter image description here][1]][1]&#xA;&#xA;Is there a way of doing this while retaining lighting and bumpmaps so it seamlessly blends with level geometry? Is there any way to do this efficiently?&#xA;&#xA;Hopefully this isn't a stupid or misplaced question, thanks for your time.&#xA;&#xA;  [1]: https://i.stack.imgur.com/ZEwMC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28689" PostHistoryTypeId="5" PostId="5646" RevisionGUID="396e72d1-332e-4ac9-8eb8-48570e27cae0" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I am no expert in offline renderers, but I'll give it a go until someone else comes with a better answer :) &#xA;&#xA;&#xA;## Shadow rays intersecting area light&#xA;&#xA;It is *very* common to assign an extent to your rays. How to do so? Think about the parametric formula of a ray:&#xA;&#xA; $$R(t) = O + t\vec{D}$$&#xA;&#xA;it should immediately jumps out that how far $R(t)$ can be from the origin $O$ depends on how much we can travel in the direction $\vec{D}$, and this travelling is clearly governed by the parameter $t$. &#xA;&#xA;Your problem here is that you don't want to let the ray travel indefinitely, but you want to stop just before it hits the source of the light, because otherwise, as you correctly noticed, everything will result occluded. &#xA;&#xA;So how do you limit how much your ray can travel? You just have to limit the maximum value that $t$ can take. You have two option:&#xA;&#xA; 1. Probably the most intuitive one is to compute at what $t_{light}$ your light source lies. By using the same parametric formulation of the ray, if $L_p$ is the point you've chosen on the area light, then $t_{light}$ will be:&#xA;&#xA;$$t_{light} = \frac{L_{p}[i] - O[i]}{\vec{D}[i]}$$&#xA;  where $[i]$ represents the coordinate of your choice.  Given this, you want to stop your shadow ray to travel just before $t$ reaches $t_{light}$. If it goes over this value, report an unoccluded result. &#xA;&#xA; 2. Now while the option above is probably the first thing that comes to mind, it is wasteful as you'd need to both have $L_p$ around and perform some unneeded arithmetic operations if you have your light vector $\vec{D}$ as unnormalized around. In fact, this is none other than $L_p - O$ and in a case like this, the Light lies at exactly $t == 1$: &#xA;&#xA;$$ O + 1 \times (L_p - O ) = L_p $$&#xA;&#xA;So if you trace your shadow ray with an unnormalized direction $\vec{D}$, you can just set your maximum $t$ to be *just under* $1$. This is in fact what PBRT does, and as far as I am aware many other renderers.  &#xA;&#xA;## Black dots (or NaNs)&#xA;&#xA;Nothing to add over @Dan Hulme comment, so I'll just add it here for completeness of the answer: &#xA;&#xA;&gt; &quot;I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated.&quot; The common scenario is that you're using floating-point and you have a bug in your code :-) You have to expect that you'll get NaNs during development, so you should either (a) make sure they get filtered out instead of propagated by the filter, or (b) show all NaNs as bright pink so it's immediately obvious when they're there. – Dan Hulme♦ &#xA;&#xA;and if I may add, you should expect some &lt;code&gt;inf&lt;/code&gt; as well from time to time, so it's always good to account for these two special cases. &#xA;&#xA;&#xA;## &quot;Bright pixels&quot;&#xA;&#xA;With that, I assume you are talking about what is commonly referred to as fireflies. Fireflies avoidance is indeed quite a big topic and probably warrant its own question. However, just briefly.&#xA;&#xA;Fireflies typically occur when you lots of your paths end in areas with low light and very few paths end up in very bright light. &#xA;There is lots of material on how to fight fireflies, a short google search will lead to a lot of techniques depending on your case. &#xA;Just to name drop a few: &#xA;&#xA; - Radiance clamping&#xA; - Multiple Importance Sampling (especially if in presence of glossy/shiny surfaces)&#xA; - Denoising techniques&#xA; - Increment your sample count :-) &#xA; - etc.&#xA;&#xA;Also, generally increasing the size of the light source tends to help as well. Remember, the goal is always to hit those bright spot with higher probability! &#xA;&#xA;A better solution to the problem is probably to use something like [Bidirectional Path Tracing][1] as this will have sub-paths starting from the light source as well, increasing the likelihood of sampling the bright areas. &#xA;&#xA;Another cause of fireflies are caustics, but I don't want to make this answer longer, so if you are interested this is well worth an additional question. &#xA;&#xA;&#xA;  [1]: https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter10.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28690" PostHistoryTypeId="5" PostId="5599" RevisionGUID="ce629606-6239-41ff-a380-42341e26ed7d" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I've been trying to build a simple DirectX renderer from the ground up (was an OpenGL guy before but i figure it's good to know different APIs). I've been following the guide at rastertek.com to learn how to get the basics up and running.&#xA;&#xA;I got as far as [this lesson][1], following the guide verbatim except for variable names, and ran into a really weird bug. The renderer class contains 3 XMMatrix instances, world, perspective and orthographic, but trying to initialize them would crash my application - it ran fine once i commented out these lines :&#xA;&#xA;    m_projMat = XMMatrixPerspectiveFovLH(fov, aspect, nearplane, farplane);&#xA;    m_orthoMat = XMMatrixOrthographicLH(width, height, nearplane, farplane);&#xA;    m_worldMat = XMMatrixIdentity();&#xA;&#xA;At first i thought it was the dreaded SIMD alignment issue, but I'm compiling 64-bit so that should be taken care of. After a bit more tinkering i found out the ortho and world matrices were fine, it was just the projection matrix that was causing problems. Assigning to this matrix with the other XMMatrix... functions also works ok. &#xA;So:&#xA;&#xA;    m_projMat = XMMatrixPerspectiveFovLH(fov, aspect, nearplane, farplane); &#xA;fails, but:&#xA;&#xA;    m_projMat = XMMatrixPerspectiveLH(fov*aspect*nearplane, fov*nearplane, nearplane, farplane); &#xA;works! The right-handed version also fails. Also, the failure only happens in release mode, not in debug. I'm using Visual Studio 2015 community and the SDKs that installed with it.&#xA;&#xA;Has anyone else encountered this bug, or have any idea what's going on here?&#xA;&#xA;  [1]: http://www.rastertek.com/dx11s2tut03.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="28691" PostHistoryTypeId="5" PostId="6243" RevisionGUID="4268abe8-455b-4d27-983f-5923fb7345f6" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I want to learn is it good or bad idea.&#xA;&#xA;Let's assume video RAM is not a problem.&#xA;&#xA;For source texture create a texture of texels: spherical functions. Spherical functions defined by small arrays of spherical harmonics coefficients up to some reasonable degree (say 3). To gather single sample for particular texel and particular coordinates on sphere (theta, phi) it is needed to integrate over the footprint (here I mean *footprint assembly* method) started from the textel and use this value later when spherical harmonic coefficients are calculated. Phi is exactly polar angle of the footprint on `uv` plane. Theta is length of the footprint up to (and from, as optimization) some reasonable length. I almost sure, that continuity is almost preserved, except bottom of the sphere (and to, where theta begins, if we starts from some threshold minimal length of a footprint).&#xA;&#xA;There are possible some optimizations when performed backing of a footprints: save value of integrated color in both pixels footprint begins and ends. Calculate values for fixed number of directions and radii (and on power of two proximities). And, maybe others.&#xA;&#xA;The advantage of the method is possibility to get color of whole screen pixel footprint in single sampling act. The disadvantage is requirement to prepare ($O(N^4) \approx x_{resolution} \cdot y_{resolution} \cdot n_\phi \cdot n_\theta$?) such a texture for every LOD (separately? or bilinear scaling applicable?) and huge amount of memory even for coefficients of spherical harmonics to represent a spherical function of even 3 degree ($3^2 = 9$ RGB values) for better angular and *footprint length* resolution.&#xA;&#xA;### ADDITIONAL&#xA;&#xA;Now I think there is no need to have mips. All other LODs can be modeled __continuously__ by using different cone angle to make convolution with saved spherical function. It is very smooth.&#xA;&#xA;It seems also better to save value of color itself, not integral over footprint, because spherical harmonics allow to easily calculate integrals (just a scalar product). Especially with zonal sperical functions like integral into a solid angle inside of arbitrary oriented cone.&#xA;&#xA;I think this format of textures is best for cartoon industry." ContentLicense="CC BY-SA 4.0" />
  <row Id="28692" PostHistoryTypeId="5" PostId="5467" RevisionGUID="54877430-c792-4b64-bda6-f7e359b44372" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="## Basic calculations&#xA;I'm assuming you want to calculate the bounds of the rectangle of intersection, so you can draw it later. As AlanWolfe mentioned, you will want to use the max and min functions. This is so you can retrieve the left-most, right-most, top and bottom squares. We'll call these placeholders `right`, `bottom`, `left`, and `top` (each of these will point to one of the two squares). &#xA;&#xA;Now that you know these, you can start mathing. The top-left position of the intersection will be at `(right.x_left, bottom.y_top)`. The bottom-right position of the intersection will be at `(left.x_left + left.width, bottom.y_top + bottom.height)`.&#xA;&#xA;## Rendering the intersection&#xA;To draw this rectangle (unconditionally), first you will need a location and a dimension, because most draw functions require these.&#xA;&#xA;    Intersection.width = Intersection.x_right - Intersection.x_left&#xA;and the same for the height. Now suppose the squares don't overlap. This would mean at least one dimension is negative. We don't want anything to draw in this case, so we will set any negative dimensions to zero.&#xA;&#xA;    Intersection.width = max(Intersection.width, 0)&#xA;and the same for the height. And to wrap up, we render our rectangle:&#xA;&#xA;    fillRect(Intersection.x_left, Intersection.y_top, Intersection.width, Intersection.height)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28693" PostHistoryTypeId="5" PostId="5415" RevisionGUID="a156142d-19a9-4723-8863-a6c9f5fbf964" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="[![enter image description here][1]][1]&#xA;(example of effect i am trying to render)&#xA;&#xA;Rendering Transparent Object in forward rendering is far easier. However I am having an issue when it comes to transparent glass like object that applies post processing like effect when seen through it.&#xA;&#xA;I do know how to render &quot;glass&quot; that reflects &quot;skybox&quot; however I do not know how to render a glass like object that applies its distortion effect around its dynamic surroundings.&#xA;&#xA;I need help figuring out how to render this effect. &#xA;&#xA;  [1]: https://i.stack.imgur.com/KGI2H.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28694" PostHistoryTypeId="5" PostId="5408" RevisionGUID="80e4b9ea-dcc3-40cc-a5f5-f1038724cc38" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I'm launching OpenGL from a VBA module linked to an Excel spreadsheet which goes quasi-dormant (the quasi will become clear in a moment) once I enter glutMainLoop. I would like to be able to edit the Excel spreadsheet and observe corresponding changes in the OpenGL simulation. In this context,  I have two issues:&#xA;&#xA;Issue 1 (as John McLaughlin used to bark on his PBS show!): Currently, **once within glutMainLoop**, I can only make changes to Excel cells that have pulldown menus, but not cells that require keyboard input. I believe that this issue may be related to the lack of a multi-threading ability either withing glut or VBA (this is WAY above my Mech E pay grade). I'd like to know however, if there's a workaround. &#xA;&#xA;Issue 2: When I make changes to the Excel cells with pulldown menus, the OpenGL window gets minimised, unless I move it to a second screen or outside the Excel window which is not convenient. I understand that this is typical Windows behaviour, but at the very least, is there an openGL command to maximise it again after the changes to the Excel spreadsheet, **from within glutMainLoop**? &#xA;&#xA;I'd like to emphasise that Issue 1 above - the lack of ability to edit Excel cells requiring keyboard input once within glutMainLoop - is far more important. &#xA;&#xA;Thanks in advance. I've added an image below that (hopefully!) describes what I'm trying to accomplish.&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;  [1]: https://i.stack.imgur.com/IpzMc.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28695" PostHistoryTypeId="5" PostId="5358" RevisionGUID="a4ba70ac-008d-41d5-b9dd-5b3ad3ef39f6" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="CNT is a promising new material, which [Wikipedia][1] describes as such:&#xA;&#xA;&gt; Carbon nanotubes (CNTs) are allotropes of carbon with a cylindrical nanostructure. These cylindrical carbon molecules have unusual properties, which are valuable for nanotechnology, electronics, optics and other fields of materials science and technology. Owing to the material's exceptional strength and stiffness, nanotubes have been constructed with length-to-diameter ratio of up to 132,000,000:1, significantly larger than for any other material.&#xA;&gt;&#xA;&gt; In addition, owing to their extraordinary thermal conductivity, mechanical, and electrical properties, carbon nanotubes find applications as additives to various structural materials.&#xA;&#xA;For this reason, the name carbon nanotubes appear from time to time in various works of science fiction, and I too want to use CNT in a science fiction game, set in the near future which I am making, since I am trying to achieve some degree of photorealistic graphic, I will, however, need to know what CNT will look like.&#xA;&#xA;specifically, I want to know which of the two main categories of solid, non-transparent material surfaces commonly used in physically based rendering CNT would fall under.&#xA;&#xA;as [this][2] article on PBR computer graphics explains, &#xA;&#xA;&gt; »Electrically conductive materials, most notably metals« look quite different from other materials.&#xA;&#xA;Which is why it often is sufficient to assume that the most common materials in the world are either *metallic* or *dielectric*/*insulating*.&#xA;&#xA;Given that CNT by Wikipedia is described as:&#xA;&#xA;&gt; Unlike graphene, which is a two-dimensional semimetal, carbon&#xA;&gt; nanotubes are either metallic or semiconducting&#xA;&#xA;I first assumed was that I should treat CNT as a metal, but I am not certain if CNT has other properties which would make it look significantly different from metal.&#xA;&#xA;My question is, therefore, is it a fair approximation to render carbon nanotubes using a metallic shader? or would it be better to render it as an insulator? Edit 1: and would CNT look anisotropic.&#xA;&#xA;Edit 0: So it looks like we actually already have some macroscopic CNT structures, but I really can't tell whether or not this looks metallic or not: &#xA;&#xA;[![enter image description here][3]][3]&#xA;&#xA;&#xA;  [1]: https://en.wikipedia.org/wiki/Carbon_nanotube#Electrical&#xA;  [2]: https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/&#xA;  [3]: https://i.stack.imgur.com/aSvgK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28696" PostHistoryTypeId="5" PostId="5295" RevisionGUID="0c737c86-244d-45a0-90f3-110267568de2" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="### Idea A:&#xA;&#xA;Draw an invisible mesh that will occlude the points we don't want.&#xA;&#xA; 1. Create a mesh from the point cloud.&#xA; 2. Render that mesh to a depth buffer but not to the color buffer.&#xA; 3. Render the point cloud using a depth test &quot;closer or equal&quot;.&#xA;&#xA;This approach should give the expected result, but the problem with it is the first part, which is not trivial at all.&#xA;&#xA;&#xA;### Idea B:&#xA;&#xA;Approximate the mesh with fat particles, that are big enough to hide points in the background.&#xA;&#xA; 1. Pick a size that is roughly the typical distance between two points.&#xA; 2. Use that size as a particle diameter.&#xA; 3. Render the point clouds using such large particles, to a depth buffer but not to the color buffer. Maybe offset that point cloud a little, so it's a bit farther from the camera.&#xA; 4. Render the point cloud using points this time, and using a depth test &quot;closer or equal&quot;.&#xA;&#xA;This method should be a lot simpler to implement than A, because there is no need to triangulate anymore. The result will not be perfect though: some points that should be visible might disappear, and some that shouldn't be visible will remain visible. Tweaking the particle diameter and offset will yield different results.&#xA;&#xA;### Idea C:&#xA;&#xA;As a very cheap trick, just render the point cloud with a fog function. The farther points are from the camera, the less visible they are. This method won't hide any point, but still help reading the volume." ContentLicense="CC BY-SA 4.0" />
  <row Id="28697" PostHistoryTypeId="5" PostId="5188" RevisionGUID="51eea930-1672-4653-8234-b846d3ee4b4c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="[The GLSL Specification](https://khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.40.pdf) in section 6.1.1 &quot;Function Calling Conventions&quot; states:&#xA;&#xA;&gt;- The keyword **in** is used as a qualifier to denote a parameter is to be copied in, but not copied out.&#xA;&gt;&#xA;&gt;- The keyword **out** is used as a qualifier to denote a parameter is to be copied out, but not copied in. This should be used whenever possible to avoid unnecessarily copying parameters in.&#xA;&gt;&#xA;&gt;- The keyword **inout** is used as a qualifier to denote the parameter is to be both copied in and copied out. It means the same thing as specifying both in and out.&#xA;&gt;&#xA;&gt;- A function parameter declared with no such qualifier means the same thing as specifying **in**." ContentLicense="CC BY-SA 4.0" />
  <row Id="28698" PostHistoryTypeId="5" PostId="5156" RevisionGUID="564bd850-cffb-47cc-a829-cf48fdce51e9" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have a JPEG file with a [200 dpi scan of a sample printout](https://www.dropbox.com/s/01ygrkzlhylu612/ACPU-128.jpg?dl=0) from a **badly maintained** old drum printer. I was able to segment it and to collect [all instances of each letter together](https://www.dropbox.com/s/doc2bzh155mey26/tiles.zip?dl=0), for example&#xA;&#xA;[![Letters A][1]][1]&#xA;[![Letters G][2]][2]&#xA;[![Letters Q][3]][3]&#xA;[![Letters W][4]][4]&#xA;&#xA;I would like to recreate its font; as the first step I've written a utility that estimates the shift amount (in pixels) between two images using MSE, then weighted-averages them according to that shift amount, and continues until all instances of a character have been processed. &#xA;&#xA;My results look like&#xA;&#xA;[![Sample result][5]][5]&#xA;&#xA;Is this the best I can hope for, or are there smarter algorithms that are able to deal with low-quality samples? &#xA;&#xA;Specifically, I would like to get rid of the ink smear at the top of the characters due to the rotational momentum of the drum with respect to the hammers.&#xA;&#xA;(As far as I understand, [super-resolution](https://en.wikipedia.org/wiki/Super-resolution_imaging) is not a good match for this task, and I couldn't find a good open source implementation of it.)&#xA;&#xA;The second step is to use [Potrace](https://en.wikipedia.org/wiki/Potrace), of course.&#xA;&#xA;  [1]: https://i.stack.imgur.com/ZJqH0.png&#xA;  [2]: https://i.stack.imgur.com/rFNd6.png&#xA;  [3]: https://i.stack.imgur.com/x3BwS.png&#xA;  [4]: https://i.stack.imgur.com/dEohV.png&#xA;  [5]: https://i.stack.imgur.com/nuumF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28699" PostHistoryTypeId="5" PostId="5106" RevisionGUID="828ada9a-c2ef-4344-a26f-2acf9d84641c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="According to the OpenGL spec, any integer other than zero can be a potential name. Zero is the only value that's guaranteed not to be an object name.&#xA;&#xA;Relevant quote from [the spec](https://khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf):&#xA;&#xA;&gt; **2.6.1.1    Name Spaces, Name Generation, and Object Creation**&#xA;&gt;&#xA;&gt; Each object type has a corresponding _name space_.  Names of objects are represented by unsigned integers of type `uint`.  The name zero is reserved by the GL; for some object types, zero names a _default object_ of that type, and in others zero will never correspond to an actual instance of that object type.&#xA;&gt;&#xA;&gt; Names of most types of objects are created by _generating_ unused names using commands starting with **Gen** followed by the object type.  For example, the command **GenBuffers** returns one or more previously unused buffer object names." ContentLicense="CC BY-SA 4.0" />
  <row Id="28700" PostHistoryTypeId="5" PostId="5037" RevisionGUID="9dc8106c-5b40-4660-8210-9d749d669270" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="The vertex shader only runs per vertex, not for every point in the square. So the four vertices are mapped to (±2, ±2), and then the GPU draws a polygon between those vertices, which does cross the viewport.&#xA;&#xA;The points interior to the polygon do not go through the `v.y = v.y/v.z` transform, so the resulting point set is not $(-\infty,-2] \cup [2,\infty)$ after all.&#xA;&#xA;For this reason, one can't generally do non-linear geometry transformations in the vertex shader alone—except for perspective projection, which has special hardware support. (You run into this problem as well if you try to do any non-linear camera projection, such as a fisheye projection.) There are two ways to solve it:&#xA;&#xA;1. Subdivide the geometry into small pieces so that the vertices are closely spaced. Then, applying the nonlinear transform per vertex may be a good-enough approximation.&#xA;&#xA;   Also, since in your case the transform has a discontinuity at $z = 0$, you would need to split the original polygon into two pieces (each with its own set of vertices) where it crosses the $z = 0$ plane, and push the split vertices away from that plane, so you'd have $z = \pm \epsilon$, where $\epsilon$ is some small number. [It might even work to use IEEE floating point &quot;negative zero&quot; values here; not sure.] Otherwise the pieces that cross $z = 0$ will cause the same problem all over again.&#xA;&#xA;2. Do the transform as an image-space process, i.e. in the pixel shader rather than the vertex shader. This is used for example for lens distortion correction in VR: the image is rendered first using an ordinary perspective projection, then resampled to the distorted projection. This requires being able to invert the transform, i.e. map from the destination pixel position back to the corresponding source position, then sampling the source pixel from a texture." ContentLicense="CC BY-SA 4.0" />
  <row Id="28701" PostHistoryTypeId="5" PostId="8944" RevisionGUID="6e3c76b5-320e-44f9-a391-9e7bba5b01e1" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="**Note:** I wasn't 100% certain if this question belonged here or in Ask Ubuntu. I figured since it was about OpenGL programming I'd put it here, but if I should move it to Ask Ubuntu, please let me know.&#xA;&#xA;# Background&#xA;I'm new to OpenGL and needed to figure out which version I could program in on my PC. A few Google/Stack Exchange searches shows that the usual solution is to run `glxinfo | grep version` and read the results, which I did and got the following:&#xA;&#xA;```&#xA;server glx version string: 1.4&#xA;client glx version string: 1.4&#xA;GLX version: 1.4&#xA;    Max core profile version: 4.5&#xA;    Max compat profile version: 3.0&#xA;    Max GLES1 profile version: 1.1&#xA;    Max GLES[23] profile version: 3.2&#xA;OpenGL core profile version string: 4.5 (Core Profile) Mesa 18.0.5&#xA;OpenGL core profile shading language version string: 4.50&#xA;OpenGL version string: 3.0 Mesa 18.0.5&#xA;OpenGL shading language version string: 1.30&#xA;OpenGL ES profile version string: OpenGL ES 3.2 Mesa 18.0.5&#xA;OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20&#xA;```&#xA;The confusing part is the following three lines:&#xA;&#xA;```&#xA;OpenGL core profile version string: 4.5 (Core Profile) Mesa 18.0.5&#xA;OpenGL version string: 3.0 Mesa 18.0.5&#xA;OpenGL shading language version string: 1.30&#xA;```&#xA;Everything I've read says to focus only on the Core Profile line, but I'm unable to draw anything unless I load functions and create a context under 3.0 or lower. Plus, when I call `glGetString(GL_VERSION)` I get `3.0 Mesa 18.0.5` printed to the terminal, but I'm not sure if that's because my hardware only supports 3.0 or if that's because I loaded functions for that level. Also, when I start writing shaders (I'm currently using Qt and an OpenGL Widget so haven't made a shader of my own yet) will I only be able to use GLSL 1.3 instead of 3.0+?&#xA;&#xA;# My Question&#xA;My big question is, what do the output strings actually mean? I can't find that answer. Which one tells me what my hardware can actually do? And, what do the other strings mean? Why am I getting a Core Profile of 4.5 when (as far as I can tell) I can't actually use 4.5? If my hardware *can* perform 4.5 operations, how do I make it do so?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28702" PostHistoryTypeId="5" PostId="5458" RevisionGUID="24816ddf-3083-4c1f-a457-e06024a6d1e4" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I am writing a large 3D game in Java with OpenGL. &#xA;### Question #1&#xA;As of now, I am rendering my 3D objects using a `Model` class that I defined. This class contains vertex, color, model matrix, code (a custom attribute I defined), and index arrays. I defined a method `addModels` that can concatenate an array of `Model` instances into a new, larger `Model` (it concatenates all the attribute arrays using `System.arraycopy`). For instance, to draw a forest; for every tree, I create a `Model`; and at the end I combine them all into one forest `Model`, which I render. This procedure is a very _object-oriented_ way of doing it, and consists of fitting together many bundles of attribute arrays into larger ones.&#xA;Simple example code:&#xA;    &#xA;    Model[] models = new Model[trees.length];&#xA;    for (int i=0; i&lt;trees.length; i++) {&#xA;        models[i] = getTreeModel(trees[i]);&#xA;    }&#xA;    Model result = addModels(models);&#xA;    return result;&#xA;&#xA;However, this procedure may be bad practice memory-wise, since I create _many_ `Model` instances per frame. (Nonetheless, I read in [this answer](https://softwareengineering.stackexchange.com/a/149569/279723) that objects do not take much memory.) **Would it be better practice to lean towards a more _data-oriented_ approach; like first declaring large attribute arrays (vertex, color, etc.), and creating them individually?** Simple example code:&#xA;    &#xA;    float[] vertices, colors;&#xA;    for (int i=0; i&lt;trees.length; i++) {&#xA;        float[] treeVertices = getTreeVertices(trees[i]),&#xA;                treeColors = getTreeColors(trees[i]);&#xA;        // copy treeVertices into vertices, and treeColors into colors at appropriate positions&#xA;    }&#xA;    return new Model(vertices, colors);&#xA;_Please note that either option results in_ one _model that is going to be rendered finally._&#xA;&#xA;Are there any better ways of doing this?&#xA;&#xA;### Question #2&#xA;When I render a `Model`, I convert each attribute array into an attribute buffer (e.g. `float[]` into `FloatBuffer`). Would it make my game run faster to, first, load data into a buffer without using the array at all? (I'm using arrays because they're easier for me to manipulate.) &#xA;&#xA;### Question #3&#xA;Would it be more efficient to call `glBufferSubData` then to concatenate all the attribute arrays into longer ones and then call `glBufferData` (or a similar method)?&#xA;&#xA;### Question #4&#xA;[One tutorial](https://learnopengl.com/#!Model-Loading/Model) I read defined a `Model` class as containing multiple `Mesh`s. _Then, they drew each mesh separately to the screen._ Is this good practice if I have a lot of meshes (trees) per model (forest)? I heard it isn't good to make a lot of `glDraw*` calls." ContentLicense="CC BY-SA 4.0" />
  <row Id="28703" PostHistoryTypeId="5" PostId="6309" RevisionGUID="f13a07ed-276e-4cb7-b144-f3a7472247df" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="What you are missing is, that in OpenGL's NDC space (i.e. clip space after division by `w`) all 3 coordinates are in the range $[-1,1]$. So **`ndc_depth` is in the range $[-1,1]$**, while your computation assumes a range of $[0,1]$.&#xA;&#xA;So let's take your computation but add an initial step to map $[-1,1]$ to $[0,1]$:&#xA;&#xA;    float ndc_depth = Pclip.z / Pclip.w;&#xA;    float win_depth = (ndc_depth + 1.0) / 2.0;&#xA;    gl_FragDepth = gl_DepthRange.diff * win_depth + gl_DepthRange.near;&#xA;&#xA;If we do some transformations (and realizing that `gl_DepthRange.diff` is just convenience for `gl_DepthRange.far - gl_DepthRange.near`), we get&#xA;&#xA;    gl_FragDepth = gl_DepthRange.diff * (ndc_depth + 1.0) / 2.0 + gl_DepthRange.near;&#xA;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff) / 2.0 &#xA;                   + gl_DepthRange.near;&#xA;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + gl_DepthRange.diff + &#xA;                    2.0 * gl_DepthRange.near) / 2.0;&#xA;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xA;                    gl_DepthRange.far - gl_DepthRange.near + 2.0 * gl_DepthRange.near) / 2.0;&#xA;&#xA;    gl_FragDepth = (gl_DepthRange.diff * ndc_depth + &#xA;                    gl_DepthRange.far + gl_DepthRange.near) / 2.0;&#xA;&#xA;So, to answer your specfic questions:&#xA;&#xA;1. That's just a result from simplifying the calculation based on the fact that [`gl_DepthRange.diff` is nothing else than `gl_DepthRange.far - gl_DepthRange.near`](https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)#Shader_uniforms).&#xA;&#xA;2. Because the depth range in NDC space is $[-1,1]$, which has a width of $2$.&#xA;&#xA;3. It doesn't. These values have nothing to do with the near and far values you used to construct your projection matrix, in fact you could use any arbitrary projection matrix (or none at all). They are the depth range values set with [`glDepthRange`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml), which have a totally different meaning (okay, let's say slightly different but related).&#xA;&#xA;   Basically, and special situations notwithstanding, the projection matrix defines where you near and far clipping planes are in eye-space, i.e. which eye-space range is mapped to the $[-1,1]$ NDC depth range. Then the depth range defines what these NDC near/far values of -1 and 1 are mapped to in the actual depth buffer. So the names &quot;near&quot;/&quot;far&quot; *do* relate to the near and far clipping planes. But both transformations are basically independent of each other, using the general NDC (i.e. the *normalized* device space) as a mediator between both stages. This way `glDepthRange` more or less just extends what `glViewport` does onto the z-dimension." ContentLicense="CC BY-SA 4.0" />
  <row Id="28704" PostHistoryTypeId="5" PostId="6385" RevisionGUID="8bd00078-7e46-4d65-96e8-5ad1741e2d1b" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I drew simple [triangle wave](https://en.wikipedia.org/wiki/Triangle_wave) (that you can see It on [graph toy](http://www.iquilezles.org/apps/graphtoy/)).&#xA;&#xA;![triangle wave](https://user-images.githubusercontent.com/16706911/37163629-80fb47c2-230d-11e8-9210-736648fb74a4.png)&#xA;&#xA;&#xA;       f1(x) = frac(x/(PI+5))*(PI+5)&#xA;       f2(x) = frac(-x/(PI+5))*(PI+5)&#xA;       f3(x) = min(f1(x),f2(x))*1.5&#xA;&#xA;_____&#xA;&#xA;I want to change above shape like [Approximating Pi](https://www.desmos.com/calculator/hmcutwfumj) and repeat It periodically along the horizontal axis.&#xA;&#xA;![Approximating Pi](https://user-images.githubusercontent.com/16706911/37164290-167419cc-230f-11e8-9e65-75aca83d33c5.gif)&#xA;&#xA;then I want to cut negative parts of the vertical axis:&#xA;&#xA;![image](https://user-images.githubusercontent.com/16706911/36645755-be8cd206-1a82-11e8-9046-dd2923095e16.png)&#xA;&#xA;# Update&#xA;&#xA;Note that I know how can I draw It by shader In [ShaderToy](https://www.shadertoy.com/view/XsVyzR).I Just need drawing mathematics In desmos or graphtoy,because I want Extract values of wave.I want to create polygon [wave form](https://en.wikipedia.org/wiki/Waveform).&#xA;&#xA;I drew Periodic shape that I want to change the number of polygons&#xA;[Desoms Link][1].&#xA;&#xA;&#xA;  [1]: https://www.desmos.com/calculator/gh7fmcrbys" ContentLicense="CC BY-SA 4.0" />
  <row Id="28705" PostHistoryTypeId="5" PostId="8092" RevisionGUID="2bfdd5aa-cd15-4e85-8c5e-90da8eaf0427" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Online games do not work the way you describe. The server doesn't give the client one frame's worth of data every frame. That would be awful. Instead, every client has its own copy of the game state, and the rendering happens as if it were an offline game: every frame, the game state is updated locally. That means your inputs such as moving the mouse to control the view take effect immediately. Things that aren't under players' control (such as the movement of projectiles in flight) are also updated locally. Many games also have some kind of motion prediction for other players' characters - in the simplest case, just updating the state as if they kept going in the same direction.&#xA;&#xA;These state updates are performed by the CPU on its scene-graph, and they result in some update to GPU state too. The frame is then rendered by the GPU, usually in parallel with the CPU starting work on the next frame's updates.&#xA;&#xA;When an update arrives from the server, this also updates the state on the CPU. This update will include new projectiles, replacements for the predicted motions of other player characters, and replacements for the motions of the local player's character (e.g. if they bumped into another player or were hit by some unpredicted projectiles).&#xA;&#xA;Resolving conflicts between the predicted state on the client and the new state from the server, and applying the lag to the server state before applying it, are important parts of the game's architecture that really determine how the game feels to play and what lag looks like. Applying the updates from the server is done within one frame update on the client, so if an update takes too long to apply, it'll cause some frames to be much slower, but the age of the update doesn't really affect that.&#xA;&#xA;## Summary&#xA;&#xA;Client-server latency doesn't usually increase the frame time, because the client doesn't wait for a server round-trip each frame." ContentLicense="CC BY-SA 4.0" />
  <row Id="28706" PostHistoryTypeId="5" PostId="8646" RevisionGUID="e10d91ba-4e33-4cef-9256-b09204f33014" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I want to utilize shaders to not only discard fragments if they are on one side of a predefined plane but also render a contour along the intersection. &#xA;&#xA;My fragment shader currently does something along the lines of: &#xA;&#xA;    float dot = dot(world_coordinate, normalize(clipping_normal.xyz)) - clipping_normal.w;&#xA;    if (dot &gt; 0.0f) &#xA;        discard;&#xA;&#xA;this works but without the desired contour. I tried comparing the dot product against values close to 0.0 but this results in a contour with varying width depending on view etc...&#xA;&#xA;This is what I am trying to achieve. Notice that the white contour/edge of where the plane intersects the sphere is of consistent width:&#xA;&#xA;[![cross-section][1]][1]&#xA;&#xA;  [1]: https://i.stack.imgur.com/omrFH.png&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28707" PostHistoryTypeId="5" PostId="8625" RevisionGUID="8a7283dc-3f1e-476d-81ef-526e150288d9" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I guess your question is how to compute the inertia tensor automatically. A parametric equation may not be always possible, but we could write a program to avoid hand calculations as much as possible.&#xA;&#xA;The inertia tensor $\mathbf{I}$ is defined as an integral over the object domain $\Omega$ (see [Inertia tensor](https://en.wikipedia.org/wiki/Moment_of_inertia#Inertia_tensor)):&#xA;$$&#xA;\newcommand{\V}[1]{\mathbf{#1}}&#xA;\begin{align}&#xA;\V{I} &amp;= \int_\Omega \rho (\V{r}\cdot\V{r} \delta - \V{r}\V{r}^T)\,dV&#xA;\end{align}&#xA;$$&#xA;where $\V{r}$ is the position relative to the center of mass (COM),$\rho$ is the density, and $\delta$ is the identity matrix.&#xA;&#xA;Note that $\text{tr}(\V{r}\V{r}^T) = \V{r}\cdot \V{r}$, the above definition  can be rearranged as&#xA;$$&#xA;\begin{align}&#xA;\V{T} &amp;= \V{r}\V{r}^T \\&#xA;\V{I} &amp;= \int_\Omega \rho (\text{tr} \V{T} \delta - \V{T})\,dV&#xA;\end{align}&#xA;$$&#xA;&#xA;## Analytic object&#xA;For analytic objects you can substitute their equations into the integral and do symbolic integration. This step can be automated with any symbolic computing software.&#xA;&#xA;## Object in tetrahedral mesh&#xA;We assume the object is simple and has a closed boundary.&#xA;An analytic solution is not possible in this case because we do not have an explicit equation for the object. But we could compute the inertia tensor numerically.&#xA;The only integral we have to compute is&#xA;$$&#xA;\begin{align}&#xA;\V{C} &amp;=&#xA;\int_\Omega \rho \V{r}\V{r}^T\,dV&#xA;\end{align}&#xA;$$&#xA;&#xA;To compute this integral, [this paper](http://number-none.com/blow/inertia/) could be helpful.&#xA;The general idea is to compute $\V{C}_t$ for each tetrahedron $t$, and sum $\V{C}_t$ to get $\V{C}$.&#xA;We first compute the integral for a canonical tetrahedron $t0$ whose vertices are&#xA;$(0,0,0)$, $(1,0,0)$, $(0,1,0)$, and $(0,0,1)$.&#xA;&#xA;In maple, this canonical integral $\V{C}_{t0}$ is (assume $\rho$ constant)&#xA;```&#xA;r:=&lt;x,y,z&gt;; &#xA;                                                    [x]&#xA;                                                    [ ]&#xA;                                               r := [y]&#xA;                                                    [ ]&#xA;                                                    [z]&#xA;&#xA;with(LinearAlgebra):                                &#xA;rrt:=r.Transpose(r);&#xA;                                             [ 2               ]&#xA;                                             [x      x y    x z]&#xA;                                             [                 ]&#xA;                                      rrt := [        2        ]&#xA;                                             [x y    y      y z]&#xA;                                             [                 ]&#xA;                                             [               2 ]&#xA;                                             [x z    y z    z  ]&#xA;&#xA;seq(seq(int(int(int(rrt[i,j],x=0..1-y-z),y=0..1-z),z=0..1),i=1..3),j=1..3);&#xA;                      1/60, 1/120, 1/120, 1/120, 1/60, 1/120, 1/120, 1/120, 1/60&#xA;```&#xA;&#xA;Then the integral $\V{C}_t$ can be computed by a change of variable.&#xA;Assume the coordinates of a world space tetrahedron can be represented as $\V{r}=\V{F}\V{r}_0 + \V{x}$, where $\V{F}$ and $\V{x}$ are constant.&#xA;We have&#xA;$$&#xA;\begin{align}&#xA;\V{C}_t &amp;= \rho \int_{\Omega_t} \V{r}\V{r}^T\,dV \\&#xA;&amp;= \rho \int_{\Omega_{t0}} (\V{F}\V{r}_0 + \V{x})(\V{F}\V{r}_0+\V{x})^T \det \V{F} \,dV_0 \\&#xA;&amp;= \rho \int_{\Omega_{t0}} (\V{F}\V{r}_0\V{r}_0^T\V{F}^T + \V{x}\V{x}^T + \V{F}\V{r}_0\V{x}^T + \V{x}\V{r}_0^T\V{F}^T) \det \V{F} \,dV_0 \\&#xA;&amp;= \det(\V{F}) \V{F}\V{C}_{t0}\V{F}^T + \det(\V{F}) m \V{x}\V{x}^T + \det(\V{F}) m \V{\bar{r}}\V{x}^T + \det(\V{F}) m \V{x}\V{\bar{r}}^T&#xA;\end{align}&#xA;$$&#xA;where $\V{\bar{r}}$ is the COM and $m$ is the mass.&#xA;&#xA;## Objects in other form ##&#xA;I did not use Inventor before but I suspect the part produced by it may have other formats, such as Bezier surface. For now I would suggest tetrahedralize the object and apply the above method.&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28708" PostHistoryTypeId="5" PostId="8491" RevisionGUID="d27eb553-f35b-43a1-8d39-632427c78047" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Read up on the basics for ray-tracing [here][1],&#xA;&#xA;Usually we don't mess up with viewports and stuff in raytracing, So I'm just telling you for the case where viewport equals the Image Width and Height.&#xA;&#xA;There are two cases when the field of view changes. Either you move the image plane back and forth or you increase the size. We choose to change $d$ ( former approach). &#xA;&#xA;Calculating ray is simple when the camera is aligned with the world, all you have to do is&#xA;&#xA;$d = 1/tan(\theta_{fov}/2))$&#xA;&#xA;$P_x = P_x + 0.5$  &#xA;$P_y = P_y + 0.5$&#xA;&#xA;$aspect\_ratio = width/height$&#xA;&#xA;$ray.dir.x = aspect\_ratio *(2*P_x/width) -1$&#xA;&#xA;$ray.dir.y = (2*P_y/height) - 1$&#xA;&#xA;$ray.dir.z = d$&#xA;&#xA;The $Z$ coordinate should be negative or positive depending on whether you are using a right handed or left handed coordinate system. $P_x$ and $P_y$ are pixel coordinates offset by $0.5$ to get the center of the pixel.&#xA;&#xA;The process is simple. You first map your image to NDC space (-1, 1). However to account for non-square images we scale the $X$ coordinate by Aspect ratio so it's $[-a, a]$ in $X$ and $[-1,1]$ in Y. The ray's direction through the pixel is then given by above formulas. You might have to flip the $Y$ coordinate if the image coordinate's origin is top left instead of bottom left.&#xA;&#xA;Note however the link bases all their coordinate systems and space names on RenderMan which is quite different from OpenGL. For camera that isn't aligned with the world coordinate you have to multiply by the transformation matrix as described by bernie in his answer&#xA;&#xA;EDIT:-&#xA;&#xA;First of all let's clear up on -ve and +ve $d$. For right handed coordinate systems you always set $ray.dir.z = -d$ and for left handed $ray.dir.z = d$ This is because in camera space there is no concept of half rays having -ve Z and half +ve, that happens in world space. When you multiply by the transformation matrix it takes care of these cases for you since the transformation matrix is designed keeping in mind whether you are working on a left handed or right handed system. I know i said that you always set it to +ve $d$ but i was wrong in the comments, sorry.&#xA;&#xA;Now coming to your other question. You need the vectors $b,v,t$ and $E$ for creating a transformation matrix. Usually in raytracing you create your camera and initialize its transformation matrix to the standard case (aligned with world space) Then when you move your mouse or something you create a respective rotation matrix and transform the original camera matrix to keep up with these changes. Then when calculating the ray you multiply it as I said above to get ray direction easily. So you probably need to manage your own Camera first.&#xA;&#xA;Since you aren't managing in this case you explicitly need to find these vectors. You mention you have the $w$ vector which is global up. $t$ is easy to find as you say&#xA;&#xA;$t = T-E$&#xA;&#xA;However remember this is the viewing direction not the basis vector. For right handed coordinate systems, the basis vector for $Z$ is $-V_{dir}$&#xA;&#xA;For $b$ which is Camera's right vector. You do,&#xA;$ w \times t = b$&#xA;&#xA;This gets you the Camera's up vector. Then you do,&#xA;&#xA;$ t \times b = v$&#xA;&#xA;to get the Camera's up vector. This works as long as $t$ doesn't equal $w$ which is the global up.&#xA;&#xA;So after you have these you can create a camera transformation matrix with $c_1, c_2, c_3, c_4 = b, v, t, E$ respectively.&#xA;&#xA;EDIT2:-&#xA;Instead of following above approach you can also do Gram-Schmidt orthogonalization which is more standard in this case. Using this you get the Camera's up vector $v$ as&#xA;&#xA;$v = w - (t.w)\hat{t}$&#xA;&#xA;Then side vector as,&#xA;&#xA;$b = v \times t$ &#xA;&#xA;For right handed systems. For left handed systems you need to change the ordering of cross products.&#xA;&#xA;  [1]: http://www.scratchapixel.com/index.php?redirect" ContentLicense="CC BY-SA 4.0" />
  <row Id="28709" PostHistoryTypeId="5" PostId="8373" RevisionGUID="987df20e-e717-4a0f-86ae-76c1493bb726" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I was following this tutorial on Vulkan https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer and I decided to do this bit:&#xA;&#xA;&gt; The buffer copy command requires a queue family that supports transfer operations, which is indicated using VK_QUEUE_TRANSFER_BIT. The good news is that any queue family with VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT capabilities already implicitly support VK_QUEUE_TRANSFER_BIT operations.&#xA;&gt;&#xA;&gt; The implementation is not required to explicitly list it in queueFlags in those cases.&#xA;&gt; If you like a challenge, then you can still try to use a different queue family specifically for transfer operations. It will require you to make the following modifications to your program:&#xA;&gt;&#xA;&gt; - Modify QueueFamilyIndices and findQueueFamilies to explicitly look for a queue family with the VK_QUEUE_TRANSFER bit, but not the VK_QUEUE_GRAPHICS_BIT.&#xA;&gt; - Modify createLogicalDevice to request a handle to the transfer queue&#xA;&gt; - Create a second command pool for command buffers that are submitted on the transfer queue family&#xA;&gt; - Change the sharingMode of resources to be VK_SHARING_MODE_CONCURRENT and specify both the graphics and transfer queue families&#xA;&gt; - Submit any transfer commands like vkCmdCopyBuffer (which we'll be using in this chapter) to the transfer queue instead of the graphics queue&#xA;&gt;&#xA;&gt; It's a bit of work, but it'll teach you a lot about how resources are shared between queue families.&#xA;&#xA;Are there any benefits of using a second queue only for transfer operations ?&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28710" PostHistoryTypeId="5" PostId="8285" RevisionGUID="c21f233f-58ab-479f-8749-1497d1c28c9a" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I'll point out that even if you did implement it correctly, at 1 sample per pixel with low roughness materials you'll still see heavy specular aliasing. It's not uncommon to see the firefly pattern on edges on low roughness materials.&#xA;&#xA;For reference see the Infiltrator demo without TAA&#xA;&gt; http://advances.realtimerendering.com/s2014/epic/TemporalAA_Compare.mov &#xA;&gt;&#xA;&gt; http://advances.realtimerendering.com/s2014/index.html#_HIGH-QUALITY_TEMPORAL_SUPERSAMPLING" ContentLicense="CC BY-SA 4.0" />
  <row Id="28711" PostHistoryTypeId="5" PostId="8238" RevisionGUID="5af3b2d6-39ae-4a48-9524-890e8400300c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="This depends on what function you're blending with. Since you don't say where you're doing this, I'll just take OpenGL as an example.&#xA;&#xA;As you can see in the [API][1], there are several ways of blending two colours (or rather how to interpret these two colours for a given blend function). &#xA;&#xA;You speak of a colour and a background colour, so let's say your result is $c_r$, your object in the foreground has colour $c_s$ (for Source, the new colour value being &quot;added&quot; someway) and your background has colour $c_d$ (for Destination, the old colour value that has been in the buffer already). &#xA;&#xA;Let $c_s = \left(\begin{array}{c} R_s\\G_s\\B_s\\A_s \end{array}\right)$ (and analogously for $c_r$ and $c_d$).&#xA;&#xA;&gt; To determine the blended RGBA values of a pixel, the system uses the following equations:&#xA;$R_d = min(k_{R'}, R_s s_R + R_d d_R) \ G_d = min(k_{G'}, G_s S_G + G_d d_G) \ B_d = min(k_{B'}, B_s s_B + B_d d_B) A_d = min(k_{A'}, A_s s_A + A_d d_A)$&#xA;&#xA;A bit confusing with the doubled $R_d$ and so forth, so I'll rewrite it to the denomination I defined earlier:&#xA;&#xA;$R_r = min(k_{R'}, R_s s_R + R_d d_R) \ G_r = min(k_{G'}, G_s S_G + G_d d_G) \ B_r = min(k_{B'}, B_s s_B + B_d d_B) A_r = min(k_{A'}, A_s s_A + A_d d_A)$&#xA;&#xA;The min function is there for not going above a certain constant (and $k_{R'},\ k_{G'},\ k_{B'},\ k_{A'}$ are simply constants). For our purposes, let's just assume that we don't surpass this threshold, so we end up with&#xA;&#xA;$R_r = R_s s_R + R_d d_R$ (and of course the same for the other channels).&#xA;&#xA;The rest of the components $s_R$ and $d_R$ which are some scaling factors for combining the two colours.&#xA;&#xA;&gt; Transparency is best implemented using blend function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) with primitives sorted from farthest to nearest.&#xA;&#xA;This helps, because now we know what the factors $s_R$ and $d_R$ actually are: the alpha values of the **Source**.&#xA;&#xA;This leaves us with &#xA;&#xA;$R_r = R_s A_s + (1 - R_d A_d)$&#xA;&#xA;Therefore, to come back to your example, we have (for the green channel, since that is not $255$):&#xA;&#xA;$G_r = 230$, an undefined $\alpha$ value for the source, the background green $G_d = 255$ and probably a solid background, meaning $A_d = 255$. We need the values to be in $\left[0, 1\right]$, therefore we get $G_r = \frac{230}{255} = 0.90196078431$, $G_d = 1$ and $A_d = 1$.&#xA;&#xA;Filling this in we get:&#xA;&#xA;$0.90196078431 = G_s A_s + (1 - 1 \cdot A_s)$&#xA;&#xA;Your question lets me believe, that you know $A_s$, thus only $G_s$ (and of course the same for the other colour channels) is missing. This can then be calculated by isolating the respective colour component.&#xA;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="28712" PostHistoryTypeId="5" PostId="8174" RevisionGUID="0134d3ae-7db6-420e-b27b-1f4ee7df02be" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I'm reading the [chapter 8](http://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter08.html) of the Cg tutorial and I could not understand 8.4.1 :&#xA;&#xA;&gt; Because all these coordinates lie in the plane of the same triangle, it is possible to derive plane equations for x, y, and z in terms of s and t:&#xA;&gt;&#xA;&gt; A_0 x + B_0 s + C_0 t + D_0 = 0&#xA;&gt;&#xA;&gt; A_1 y + B_1 s + C_1 t + D_1 = 0&#xA;&gt;&#xA;&gt; A_2 z + B_2 s + C_2 t + D_2 = 0&#xA;&#xA;How are these equations derived? " ContentLicense="CC BY-SA 4.0" />
  <row Id="28713" PostHistoryTypeId="5" PostId="8132" RevisionGUID="7dcbba54-e10e-474e-8430-fbd5e559d891" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="OpenGL is  is a cross-language, cross-platform application programming interface (API), and it acts as a bridge between your CPU and your GPU. &#xA;&#xA;It's not an input handling library, since that is something that is OS specific (on Windows for instance you would use DirectInput) and that has nothing to do with the GPU.&#xA;&#xA;Now, as stated by the other answers, you are probably using a framework to handle context creation, setting up the pixelFormatDescriptor and creating the OS window (you would use the Win32 api on Windows), like Freeglut.&#xA;&#xA;Freeglut at this point in time, is quite outdated (and probably not even supported anymore, i can't remember correctly). &#xA;GLFW on the other hand, is a very well maintained and documented library for both input and window handling (that also includes context creation). &#xA;In addition to that, the brand new Vulkan API is also avaiable for use.&#xA;Input and Window handling is done through callbacks with a very intuitive API.&#xA;&#xA;[GLFW][1] is written in C and licenced under the z-lib licence.&#xA;&#xA;[1]: https://www.glfw.org" ContentLicense="CC BY-SA 4.0" />
  <row Id="28714" PostHistoryTypeId="5" PostId="7469" RevisionGUID="966dfb16-bc77-4b6f-aa7a-c0efdc8ae61f" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="There are three principal ways to obtain a BRDF. We can &#xA;&#xA; 1. Derive an analytic formula using physical principles&#xA; 2. Use simulation given an assumed or measured model of the surface&#xA;    microgeometry&#xA; 3. Measure the BRDF based on empirical observation&#xA;&#xA;A number of analytic formulae have been proposed for BRDFs. Many Formulae have been derived from physical principles. A number of models such as the Torrance-Sparrow model have been derived from the distribution of microfacet orientations. One may postulate a certain microgeometry for the surface, and simulate the resulting BRDF by using a software raytracer. &#xA;&#xA;Once the scattering of light on a surface is understood how is a reflectance function derived? Can anyone recommend any resources on this topic? &#xA;&#xA;  [1]: http://cseweb.ucsd.edu/~viscomp/classes/cse274/wi18/readings/lect01_revised.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28715" PostHistoryTypeId="5" PostId="8785" RevisionGUID="dce3d68c-4c01-412f-b71a-2cc91ae6c0e2" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="When performing the unfolding the way you want, after you have unfolded one triangle in the plane, the next one should be one of the three triangles, adjacent to the unfolded one, i.e. the next triangle to be unfolded shares a common edge with the unfolded one. &#xA;&#xA;Assume you have a triangle $ABC$ in three space with vertices  $$A = [A_1, A_2, A_3], \,\, B = [B_1, B_2, B_3],\,\, C = [C_1, C_2, C_3]$$ which is one of the triangles from the 3D mesh. &#xA;&#xA;**If** $ABC$ is the first triangle you are starting the unfolding with, then: &#xA;&#xA;1. calculate $l_{AB} = ||A - B|| = \sqrt{(A_1 - B_1)^2 + (A_2 - B_2)^2 + (A_3 - B_3)^2}$; &#xA;2. set the 2D vertices $a = [0,0]$ and $b = [l_{AB}, 0]$ as well as $$l_{ab} = l_{AB};&#xA;&#xA;**Else if** $ABC$ is a next triangle to be unfolded in the plane, i.e. you have already unfolded one of $ABC$'s adjacent (neighboring) triangles, therefore one of $ABC$'s edges is already unfolded in the plane. Say that this edge is $AB$ and it is unfolded in the plane as the edge with vertices $a = [a_1, a_2]$ and $b = [b_1, b_2]$, where $l_{ab} = ||a-b|| = \sqrt{(a_1 - b_1)^2 + (a_2 - b_2)^2} = ||A-B|| = l_{AB}$.  &#xA;&#xA;Either way, for the triangle $ABC$ you already have the edge $AB$ unfolded as $ab$ in the plane, so that $l_{ab} = l_{AB}$ (i.e. you already know $a, \, b$ and $l_{ab}$). The question is, how do you find the coordinates of the third vertex $c = [c_1, c_2]$ so that $l_{bc} = l_{BC}$ and $l_{ca} = l_{CA}$? We impose the latter two conditions because two triangles that have pairwise equal edge-lengths are congruent (isometric, i.e. identical copies of each other).  &#xA;&#xA;For your information, I will write vectors like $B - A = [B_1 - A_1, \, B_2 - A_2, \, B_3 - A_3]$ and $C - A = [C_1 - A_1, \, C_2 - A_2, \, C_3 - A_3]$ and $b-a = [b_1 - a_1, b_2-a_2]$ and will use dot product $\cdot$ and cross product $\times$ between vectors. You already know what $||B-A|| = l_{AB}$ and $||C-A|| = l_{CA}$ are and that $l_{AB} = l_{ab} = \|b-a\|$.&#xA;&#xA;1. Calculate $$s = \frac{\|(B-A)\times(C-A)\|}{l_{ab}^2}$$&#xA;&#xA;2. Calculate $$c = \frac{(B-A)\cdot(C-A)}{l_{ab}^2}$$   &#xA;&#xA;3. Calculate both pairs of coordinates &#xA;\begin{align}&#xA;&amp;c'_1 = a_1 + c(b_1-a_1) - s(b_2 - a_2)\\&#xA;&amp;c'_2 = a_2 + c(b_2-a_2) + s(b_1 - a_1)&#xA;\end{align}&#xA;and &#xA;\begin{align}&#xA;&amp;c''_1 = a_1 + c(b_1-a_1) + s(b_2 - a_2)\\&#xA;&amp;c''_2 = a_2 + c(b_2-a_2) - s(b_1 - a_1)&#xA;\end{align}&#xA;&#xA;4. You have two candidate points $c' = [c'_1, c'_2]$ and $c'' = [c''_1, c''_2]$&#xA;&#xA;5. Perform a check whether $c'$ is on the same side of the edge $ab$ as the  triangle unfolded right before $ABC$. &#xA;&#xA;**If** it is not, then $c = c'$&#xA;&#xA;**else if** it is, then $c = c''$&#xA;&#xA;  As a result of this procedure, you have constructed the planar unfolding $abc$ of triangle $ABC$ and the next triangle from the 3D mesh to be unfolded (if any), should be the one that shares either edge $BC$ or $CA$ with $ABC$. Either way, for that next triangle, you already know the unfolding $bc$ of the edge $BC$ and the unfolding $ca$ of $CA$ (whichever is relevant), so you can apply the same procedure for that next triangle. And so on and so forth, until you have unfolded all triangles from the mesh. &#xA;&#xA;Have in mind that there are 3D meshes that do not posses unfolding that do not self overlap, no matter what you do. For such meshes there no greedy algorithms or any other algorithm that can do it.     " ContentLicense="CC BY-SA 4.0" />
  <row Id="28716" PostHistoryTypeId="5" PostId="8051" RevisionGUID="927dec85-5a07-4b0c-aa47-77d9b70ca682" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="You have a background color and the color of your line, an antialiased line has additional lines drawn on either side of the first that are simply part way between the color and brightness of your origonal line and the background. &#xA;&#xA;If the line you are drawing is horizontal or vertical the additional antialiasing lines (however many, depending upon the intended resulting line thickness) should be closer in color and brightness to the intended color - there is absolutely minimal antialiasing on such lines, that there is a tiny amount is due to offset [subpixel rendering][1] on ***some*** but not all matrixes.&#xA;&#xA;This shows the difficulty:&#xA;&#xA;[![Subpixels Matrix][2]][2]&#xA;&#xA;When the lines are not horizontal or vertical it gets more complicated ...&#xA;&#xA;If the additional lines drawn on each side of your line are drawn:&#xA;&#xA;- with color and brightness more **closely matching the background's color** then your **line remains sharper** and the **background color near your line is fuzzier**.&#xA;&#xA;  or&#xA;&#xA;- with color and brightness more **closely matching your line's color** then your **line becomes fuzzier** (wider) and the **background color near your line remains sharper**.&#xA;&#xA;&lt;!-- --&gt;&#xA;&#xA;1. That means that if you intend to draw a thin line, a single pixel wide line, you would use the first option. (Make the result skinny).&#xA;&#xA;2. If you want a two pixel wide line you would choose the second option but weigh the color of the background more towards the background's color and brightness. (Make the result not as skinny as a single line, with each of the two additional lines forming almost ~50% of the total width).&#xA;&#xA;3. If you want a three pixel wide line you still use the second option but would instead weigh the color of the background more towards the line's color and brightness. (Make the result clearly much fatter than a single line).&#xA;&#xA;4. For a four pixel wide line go back to the first method where you draw two lines of the intended color and brightness surrounded by two lines using the second method, making the two lines wider. (Sort of a blending of the first and second methods)&#xA;&#xA;5. For five pixel wide lines the center is exactly your intended color, the two nearest surrounding line are very close to the color and brightness of the center line, with the outer two fairly close to the color of the center line (but less than the ones immediately next to the center line)&#xA;&#xA;6. For a six pixel wide line there are two central lines of the intended drawing color and brightness, surrounded by two very similar lines, surrounded by another two less similar to the central two's color and brightness; but still very different from (lighter or darker) than the background color.&#xA;&#xA;7. A seven pixel line or greater follows number 5 or 6 above.&#xA;&#xA;The weighing of the additional lines more towards the intended color gives a sharper line, if you thought of it from a sideview analogy it would be top hat shaped. If you weighed additional lines more towards the background color the  (impossible) sideview analogy is that the profile of the 2D line would be rounded or triangular. If you are drawing 2D shapes it is in your interest to weigh towards the intended color. If you are rendering a 3D shape on a 2D screen then favoring the background color blends towards subsequent lines of a different Z depth.&#xA;&#xA;&#xA;A **simplistic** but effective algorithm with good speed is the [Xiaolin Wu][3] improvement to Bresenham's line drawing [algorithm to implement antialiasing][4].&#xA;&#xA;    // Pascal&#xA;    function plot(x, y, c) is&#xA;        plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1)&#xA;    &#xA;    // integer part of x&#xA;    function ipart(x) is&#xA;        return floor(x)&#xA;    &#xA;    function round(x) is&#xA;        return ipart(x + 0.5)&#xA;    &#xA;    // fractional part of x&#xA;    function fpart(x) is&#xA;        return x - floor(x)&#xA;    &#xA;    function rfpart(x) is&#xA;        return 1 - fpart(x)&#xA;    &#xA;    function drawLine(x0,y0,x1,y1) is&#xA;        boolean steep := abs(y1 - y0) &gt; abs(x1 - x0)&#xA;        &#xA;        if steep then&#xA;            swap(x0, y0)&#xA;            swap(x1, y1)&#xA;        end if&#xA;        if x0 &gt; x1 then&#xA;            swap(x0, x1)&#xA;            swap(y0, y1)&#xA;        end if&#xA;        &#xA;        dx := x1 - x0&#xA;        dy := y1 - y0&#xA;        gradient := dy / dx&#xA;        if dx == 0.0 then&#xA;            gradient := 1.0&#xA;        end if&#xA;    &#xA;        // handle first endpoint&#xA;        xend := round(x0)&#xA;        yend := y0 + gradient * (xend - x0)&#xA;        xgap := rfpart(x0 + 0.5)&#xA;        xpxl1 := xend // this will be used in the main loop&#xA;        ypxl1 := ipart(yend)&#xA;        if steep then&#xA;            plot(ypxl1,   xpxl1, rfpart(yend) * xgap)&#xA;            plot(ypxl1+1, xpxl1,  fpart(yend) * xgap)&#xA;        else&#xA;            plot(xpxl1, ypxl1  , rfpart(yend) * xgap)&#xA;            plot(xpxl1, ypxl1+1,  fpart(yend) * xgap)&#xA;        end if&#xA;        intery := yend + gradient // first y-intersection for the main loop&#xA;        &#xA;        // handle second endpoint&#xA;        xend := round(x1)&#xA;        yend := y1 + gradient * (xend - x1)&#xA;        xgap := fpart(x1 + 0.5)&#xA;        xpxl2 := xend //this will be used in the main loop&#xA;        ypxl2 := ipart(yend)&#xA;        if steep then&#xA;            plot(ypxl2  , xpxl2, rfpart(yend) * xgap)&#xA;            plot(ypxl2+1, xpxl2,  fpart(yend) * xgap)&#xA;        else&#xA;            plot(xpxl2, ypxl2,  rfpart(yend) * xgap)&#xA;            plot(xpxl2, ypxl2+1, fpart(yend) * xgap)&#xA;        end if&#xA;        &#xA;        // main loop&#xA;        if steep then&#xA;            for x from xpxl1 + 1 to xpxl2 - 1 do&#xA;               begin&#xA;                    plot(ipart(intery)  , x, rfpart(intery))&#xA;                    plot(ipart(intery)+1, x,  fpart(intery))&#xA;                    intery := intery + gradient&#xA;               end&#xA;        else&#xA;            for x from xpxl1 + 1 to xpxl2 - 1 do&#xA;               begin&#xA;                    plot(x, ipart(intery),  rfpart(intery))&#xA;                    plot(x, ipart(intery)+1, fpart(intery))&#xA;                    intery := intery + gradient&#xA;               end&#xA;        end if&#xA;    end function&#xA;&#xA;&#xA;  [1]: https://en.wikipedia.org/wiki/Subpixel_rendering&#xA;  [2]: https://i.stack.imgur.com/iBhZr.jpg&#xA;  [3]: http://www.ece.mcmaster.ca/~xwu/&#xA;  [4]: https://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="28717" PostHistoryTypeId="5" PostId="7973" RevisionGUID="f6215fef-5784-4828-881f-ee3ebbdc6c0e" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Thank you for the suggestions provided. As @gallickgunner mentioned, I shall rephrase the question will all the possible information which I could provide. I had attached also the schematic to depict my question.&#xA;&#xA;1)I need to rotate the vector V with the base point P by an angle and find the new vector V'. &#xA;2) The rotation axis is say for is about a local y axis at point P (which is parallel to global Y axis)&#xA;3) Subsequently, I need to rotate the initial vector V about x axis which is parallel to global Y axis. &#xA;The main reason for the rotation is to find the new vector V' at point P. Both the rotations are independent and each of the rotation provides a new V'.&#xA;[![enter image description here][1]][1]&#xA;&#xA;Thank you for the support. Looking forward for an answer at the earliest. &#xA;&#xA;  [1]: https://i.stack.imgur.com/MTiJX.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28718" PostHistoryTypeId="5" PostId="7953" RevisionGUID="ac8fc150-a62b-4d69-9fc8-1063c66aec99" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="## Your assumption is wrong&#xA;&#xA;[It actually *was* this way][1], in fact, things have changed *the other direction*. &#xA;&#xA;## History&#xA;&#xA;Currently ([pre nvidia link consumer graphics][2]) you've got to copy the memory over from separate GPUs to render in cross fire and SLI, as global memory transfer speeds will slow down scaling, and as far as I can tell it did not work as a general direct memory acessor, with only 2G/s bandwidth even with the [HB version](https://en.wikipedia.org/wiki/Scalable_Link_Interface), it is only meant to be a framebuffer copier.   You otherwise had to send the same information across all GPUs via PCIE.&#xA;&#xA;&gt;SLI allows two, three, or four graphics processing units (GPUs) to share the workload when rendering real-time 3D computer graphics. Ideally, identical GPUs are installed on the motherboard that contains enough PCI-Express slots, set up in a master-slave configuration. ***All graphics cards are given an equal workload to render, but the final output of each card is sent to the master card via a connector called the SLI Bridge***. For example, in a two graphics card setup, the master works on the top half of the scene, the slave the bottom half. Once the slave is done, it sends its render to the master to combine into one image before sending it to the monitor.&#xA;&#xA;(emphasis mine).&#xA;&#xA;But you didn't typically actually treat this set up as one GPU in the way *you* want in old times because if you wanted to *cooporate* work loads instead of merely *splitting workloads* that required GPU-&gt;GPU communication, which necessarily had to be done VIA pcie, which would be very slow. &#xA;&#xA;At least for opengl, SLI/Xfire rendering was handled via Driver treating the two as the same. https://stackoverflow.com/a/43812678/2036035 You didn't have the *option* of treating them as separate if they were linked.  &#xA;&#xA;&#xA;## Modern&#xA;&#xA;[Today however][3], vulkan and DX12 essentially give **more control**. &#xA;&#xA;&gt;One feature in particular goes a long way toward filling a Vulkan gap relative to Microsoft's API: explicit multi-GPU support, which allows one program to spread its work across multiple GPUs. ***Unlike SLI and Crossfire of old, where the task of divvying up the rendering between GPUs was largely handled by the driver***, this support gives control to the developer. With the addition, developers can create &quot;device groups&quot; that aggregate multiple physical GPUs into a single virtual device and choose how work is dispatched to the different physical GPUs. ***Resources from one physical GPU can be used by another GPU, different commands can be run on the different GPUs, and one GPU can show rendered images that were created by another GPU***.&#xA;&#xA;(emphasis mine)&#xA;&#xA;Today *you can* look at these GPUs separately. &#xA;&#xA;  [1]: https://stackoverflow.com/questions/43811699/opengl-multi-gpu-support&#xA;  [2]: https://en.wikipedia.org/wiki/NVLink&#xA;  [3]: https://arstechnica.com/gadgets/2018/03/vulkan-1-1-adds-multi-gpu-directx-compatibility-as-khronos-looks-to-the-future/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28719" PostHistoryTypeId="5" PostId="7851" RevisionGUID="b6a89a8a-4061-4996-a571-356e33d2d10d" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I am developping a voxel raytracer for global illumination. &#xA;&#xA;I have been successful in multiple aspects but there is a problem I am not sure how to solve.&#xA;&#xA;The model works as most other Voxelization based algorithms work. We use rasterization to store the scene in a 3D volumetric structure and then we raytrace inside of said 3D structure.&#xA;&#xA;In the &quot;pure&quot; model (only voxels) I can generate prety decent shadows (ignore the circular artifacts):&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;However when I try to create a combined scene (normal rendering for colors, voxels for shadows) I sometimes get self intersection based artifacts:&#xA;&#xA;[![enter image description here][2]][2]&#xA;&#xA;I can improve the image a bit by using an epsilon tolerance (considering that if we are too close to the original starting position we haven't collided with anything yet):&#xA;&#xA;[![enter image description here][3]][3]&#xA;&#xA;However doing this creates poor shadows by eliminating certain collissions (look at the archs for example, where the areas too close to the source should be darkened but are instead lightened).&#xA;&#xA;I want to know if there is a better way to check for self intersection, other than checking the original position?&#xA;&#xA;i.e I want to be able to get as close to the shadows in the first image as possible.&#xA;&#xA;  [1]: https://i.stack.imgur.com/b76Fa.jpg&#xA;  [2]: https://i.stack.imgur.com/sIamK.jpg&#xA;  [3]: https://i.stack.imgur.com/ngtYt.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28720" PostHistoryTypeId="5" PostId="7811" RevisionGUID="02390f9d-c75a-4c73-a6f6-98a9326e692c" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I am currently rendering a scene in the most standard fashion possible (triangle projection and Blinn-Phong for shading)&#xA;&#xA;However I am getting some artifacts:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;As you can see the lion head is not rendered properly. Moreover, the artifacts are flickering, but the proportion of how much they flicker is proportional to the distance to the lion. That is to say. If you are close to the lion there are no artifacts. But the farther away you go the more artifacts appear. I believe this is due to Z buffer imprecision. How can I solve this?&#xA;&#xA;  [1]: https://i.stack.imgur.com/n87Fg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28721" PostHistoryTypeId="5" PostId="7776" RevisionGUID="b947974f-1985-4e60-a73d-ac3529664c87" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="The memory layout of a (2D) array texture is pretty **similar to a 3D texture, with the individual image layers stored one after the other in a big 3D-array of pixels**. So that's also how you set them. You either load each individual image into a big `GLubyte` array one after the other and set it with `glTex(Sub)Image3D` or you load each image into its own `GLubyte` array and transmit that to the texture with `glTexSubImage3D` one after the other (or any other more complex process involving buffers or whatever, but you get the idea).&#xA;&#xA;So much to the theory. The problem here is the part where you say&#xA;&#xA;&gt; However there's no guarantee that the textures are the same dimensions.&#xA;&#xA;This contradicts with how array textures work. As the corresponding documentation you link to says:&#xA;&#xA;&gt; An **Array Texture** is a Texture where each mipmap level contains an array of images of the same size.&#xA;&#xA;So the **individual layers of an array texture *have* to be the same size**. Simplifyingly said, an array texture is really just a 3D texture without filtering along the z-axis. So you can't get different-sized textures into such a regular box of pixels.&#xA;&#xA;There's a few options you have here, though:&#xA;&#xA;- You could **scale every image to a common size**, depending on *how* different they really are and what rescaling means to your quality and/or memory demands.&#xA;- You could just **drop using array textures** and implement whatever you want to do with normal 2D textures and a likely more complicated process on the CPU side.&#xA;- You could use **[Bindless Textures](https://www.khronos.org/opengl/wiki/Bindless_Texture)**. This is a rather modern non-core feature (only usable through extensions yet) that is really flexible and allows you to **access textures in a shader by using a unique GPU handle** (a 64-bit ID, so to say). This allows you to use whatever and how many textures you want in a shader, depending on some arbitrarily input value (even a vertex attribute). &#xA;&#xA;  In this case you wouldn't just a have access to a continuous array of N textures, rather than the wealth of all the textures you have allocated. You would just use normal independent 2D textures and use their respective texture handles rather than an array index. Of course this comes with a few limitations and intricacies, too. But more about that in the corresponding documentation." ContentLicense="CC BY-SA 4.0" />
  <row Id="28722" PostHistoryTypeId="5" PostId="7698" RevisionGUID="045d8dd5-da0a-45db-9282-d0edcf0246b0" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have been working with a [file from the USGS][1] that is a heightmap of the Moon. I resized it to 65536 x 32768 px for use as a displacement map in Blender, and turned it into tiles. Then I created tiles from the original image and noticed that they were about a fifth of the file size of the ones from the resized image, even though they have twice the pixels. Image Magick had remapped the image using many tones of gray that weren't present in the original. Presumably this is why the files are now so much bigger.&#xA;&#xA;Original histogram:&#xA;[![enter image description here][2]][2]&#xA;&#xA;Resized histogram:&#xA;[![enter image description here][3]][3]&#xA;&#xA;Is there any way I can resize this image without the process creating new gray tones?&#xA;&#xA;  [1]: https://astrogeology.usgs.gov/search/map/Moon/LRO/LOLA/Lunar_LRO_LOLA_Global_LDEM_118m_Mar2014&#xA;  [2]: https://i.stack.imgur.com/pkN30.png&#xA;  [3]: https://i.stack.imgur.com/eYqMu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28723" PostHistoryTypeId="5" PostId="7674" RevisionGUID="32c3d53b-700c-4d36-8b9b-ea0a198e3fe5" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I'm trying to apply raymarching on top of 3D rasterization, ordering what 3D object gets displayed based on the depth of a rasterization pass and the raymarch depth.   After getting the transform right for *position* ([using the information here][1]) I was able to have the position of the raymarched spheres coherent with the rasterized cubes.   I ran into issues however with depth being different at the edges of the screen compared to the middle, despite position never changing.  &#xA;&#xA;These gifs should show what I'm talking about &#xA;&#xA;[![enter image description here][2]][2]&#xA;&#xA;[![enter image description here][3]][3]&#xA;&#xA;higher res versions&#xA;https://ibb.co/ebji0y&#xA;https://ibb.co/dhUGLy&#xA;&#xA;Something odd is going on with depth, but I don't understand what I'm doing wrong?  Here is my fragment shader for my depth texture render pass:&#xA;&#xA;    #version 330 core&#xA;    layout(location = 0) out vec4 FragColor;&#xA;    layout(location = 1) out float DepthColor;&#xA;    in vec2 TexCoord;&#xA;    &#xA;    // texture samplers&#xA;    uniform sampler2D texture0;&#xA;    uniform sampler2D texture1;&#xA;    uniform float near;&#xA;    uniform float far;&#xA;    &#xA;    float LinearizeDepth(float depth)&#xA;    {&#xA;        float z = depth * 2.0 - 1.0; // back to NDC&#xA;        return (2.0 * near * far) / (far + near - z * (far - near));&#xA;    }&#xA;    void main()&#xA;    {&#xA;    &#xA;        float depth = LinearizeDepth(gl_FragCoord.z);&#xA;        DepthColor = depth;&#xA;        FragColor = mix(texture(texture0, TexCoord), texture(texture1, TexCoord), 0.3);&#xA;    }&#xA;&#xA;and here is my shader for the final raymarch pass:&#xA;&#xA;    #version 330 core&#xA;    out vec4 FragColor;&#xA;    &#xA;    in vec2 TexCoords;&#xA;    &#xA;    uniform sampler2D u_screen_texture;&#xA;    uniform sampler2D u_depth_texture;&#xA;    uniform float u_fov;&#xA;    uniform vec3 u_rotation;&#xA;    uniform vec3 u_origin;&#xA;    uniform vec3 u_resolution;&#xA;    &#xA;    const float inf = uintBitsToFloat(0x7F800000u);&#xA;    &#xA;    vec3 rotVecX(in vec3 vector, in float theta){&#xA;        mat3 rotmat = mat3(1, 0, 0,&#xA;                           0, cos(theta), -sin(theta),&#xA;                           0, sin(theta), cos(theta));&#xA;        return vector * rotmat;&#xA;    }&#xA;    &#xA;    vec3 rotVecY(in vec3 vector, in float theta){&#xA;        mat3 rotmat = mat3(cos(theta), 0, sin(theta),&#xA;                           0, 1, 0,&#xA;                           -sin(theta), 0, cos(theta));&#xA;        return vector * rotmat;&#xA;    }&#xA;    &#xA;    vec3 calculateFragementRay(in vec2 fragCoord, in vec3 resolution){&#xA;        vec2 uv = fragCoord;&#xA;        uv.x = (uv.x * 2.0) - 1.0;&#xA;        uv.y = (2.0 * uv.y) - 1.0;&#xA;        if(resolution.x &gt;= resolution.y){&#xA;            uv.x *= resolution.x/resolution.y;&#xA;        }else{&#xA;            uv.y *= resolution.y/resolution.x;&#xA;        }&#xA;        float tan_fov = tan(u_fov/2.0);&#xA;        vec2 pxy = uv * tan_fov;&#xA;        vec3 ray_dir = normalize(vec3(pxy, 1));&#xA;        return ray_dir;&#xA;    }&#xA;    &#xA;    vec3 getRayDirection(in vec2 fragCoord, in vec3 resolution, in vec3 rotation){&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xA;    &#xA;        return ray_dir;&#xA;    }&#xA;    &#xA;    struct Ray{&#xA;        vec3 origin;&#xA;        vec3 direction;&#xA;    };&#xA;    &#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xA;        vec3 ray_dir = getRayDirection(fragCoord, resolution, rotation);&#xA;        vec3 ray_origin = origin;&#xA;        return Ray(ray_origin, ray_dir);&#xA;    }&#xA;    &#xA;    struct RayMarchSettings{&#xA;        int max_steps;&#xA;        float max_distance;&#xA;        float min_distance;&#xA;        float depth_weight;&#xA;    };&#xA;    &#xA;    struct Sphere{&#xA;        vec3 origin;&#xA;        float radius;&#xA;    };&#xA;    &#xA;    float signedDistance(vec3 p, in Sphere sphere){&#xA;        return (length(p - sphere.origin) - sphere.radius);&#xA;    }&#xA;    &#xA;    const int NULL_ID = -1;&#xA;    const int SPHERE_ID = 0;&#xA;    const int VSPHERE_ID = 1;&#xA;    &#xA;    Sphere test_sphere = Sphere(vec3(0.0, 4.0, 4.0),1.0);&#xA;    Sphere volume_sphere = Sphere(vec3(0.0, 1.0, 0.0),2.0);&#xA;    float signedDistance(vec3 ray_endpoint, out int obj_id){&#xA;        float d0 = signedDistance(ray_endpoint, test_sphere);&#xA;        float d1 = signedDistance(ray_endpoint, volume_sphere);&#xA;        float minval = min(d0, d1);&#xA;        obj_id = minval == d0 ? SPHERE_ID : VSPHERE_ID;&#xA;        return minval;&#xA;    }&#xA;    &#xA;    bool rayMarch(Ray ray, in RayMarchSettings settings, in float rasterized_depth, out float out_depth, out int out_obj_id){&#xA;        float depth = 0.0;&#xA;        for( int i = 0; i &lt; settings.max_steps; ++i){&#xA;            vec3 ray_endpoint = ray.origin + ray.direction * depth;&#xA;            int obj_id;&#xA;            float ray_distance = signedDistance(ray_endpoint, obj_id);&#xA;            depth += ray_distance * settings.depth_weight;&#xA;    &#xA;            if( depth &gt; rasterized_depth){&#xA;                break;&#xA;            }&#xA;            if(ray_distance &lt;= settings.min_distance){&#xA;                out_depth = depth;&#xA;                out_obj_id = obj_id;&#xA;                return true;&#xA;            }&#xA;    &#xA;            if(depth &gt; settings.max_distance){&#xA;                break;&#xA;            }&#xA;        }&#xA;        out_depth = inf;&#xA;        out_obj_id = NULL_ID;&#xA;        return false;&#xA;    }&#xA;    &#xA;    float checkerBoardTexture(in vec2 uv){&#xA;        vec2 q = floor(uv);&#xA;        return clamp(mod( q.x+q.y, 2.0 ), 0.25, 1.0);&#xA;    }&#xA;    float fogify(in float dist){&#xA;        return  1.0/ (1.0 + dist*dist * 0.1);&#xA;    }&#xA;    &#xA;    RayMarchSettings rm_settings = RayMarchSettings(128, 100000.0, 0.0001, 0.5);&#xA;    &#xA;    void main()&#xA;    {&#xA;    &#xA;        vec3 origin = vec3(u_origin.x, u_origin.y, u_origin.z);&#xA;        origin = origin.zyx;&#xA;        Ray ray = getRay(TexCoords, u_resolution, u_rotation, origin);&#xA;        vec3 texture_color = texture(u_screen_texture, TexCoords).rgb;&#xA;        float rasterized_depth = texture(u_depth_texture, TexCoords).r;&#xA;    &#xA;        float depth = inf;&#xA;        int obj_id = NULL_ID;&#xA;    &#xA;    &#xA;        vec3 color;&#xA;        if(rayMarch(ray, rm_settings,rasterized_depth,  depth, obj_id)){&#xA;            vec3 endpoint = ray.origin + ray.direction * depth;&#xA;            float pattern_value = checkerBoardTexture(endpoint.xz * 4.0);&#xA;    &#xA;            if(obj_id == SPHERE_ID){&#xA;                color = vec3(1.0)*pattern_value;&#xA;            }&#xA;            if(obj_id == VSPHERE_ID){&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xA;            }&#xA;    &#xA;            switch(obj_id){&#xA;                case SPHERE_ID:&#xA;                color = vec3(1.0)*pattern_value;&#xA;                break;&#xA;                case VSPHERE_ID:&#xA;                color = vec3(0.0,  1.0, 0.0)*pattern_value;&#xA;                break;&#xA;                default:&#xA;                color = vec3(1.0,0.0,1.0)*pattern_value;&#xA;            }&#xA;         }else{&#xA;            float re_rasterized_depth = rasterized_depth == inf ? 0.0 : rasterized_depth;&#xA;            color = texture_color +re_rasterized_depth/100.f;&#xA;         }&#xA;        FragColor = vec4(color, 1.0);&#xA;    }&#xA;&#xA;The `u_depth_texture` is where the depth comes from (and what `DepthColor` corresponds to)  The `u_screen_texture` is just a texture of the rasterization pass information (output of `FragColor`).  &#xA;&#xA;&#xA;# UPDATE:&#xA;&#xA;So [this answer][4] outlined exactly my problem.  I had to make the following changes:&#xA;&#xA;    vec3 getRotatedRayDirection(vec3 ray_dir, in vec3 rotation){&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xA;        //vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xA;        ray_dir = rotVecX(ray_dir, rotation.x);&#xA;        ray_dir = rotVecY(ray_dir, rotation.y);&#xA;        return ray_dir;&#xA;    }&#xA;    &#xA;    struct Ray{&#xA;        vec3 origin;&#xA;        vec3 direction;&#xA;        float cosA;&#xA;    };&#xA;    &#xA;    Ray getRay(in vec2 fragCoord, in vec3 resolution, in vec3 rotation, in vec3 origin){&#xA;    &#xA;        vec3 ray_dir = calculateFragementRay(fragCoord, resolution);&#xA;        vec3 rot_ray_dir = getRotatedRayDirection(ray_dir, rotation);&#xA;        vec3 ray_origin = origin;&#xA;        float cosA = ray_dir.z; // a.z/length(a), already normalized so length(a) == 1.0. &#xA;        return Ray(ray_origin, rot_ray_dir, cosA);&#xA;    }&#xA;&#xA;Above I basically added cosA as a seperate value onto the ray, as suggested by the linked answer, with the appropriate code changes to avoid re-running `calculateFragmentRay`.  However I needed to figure out which cosine corresponded to the one in thier picture, I knew it was a lateral dimension, it happened to be Z in this case, and I used the standard method of retrieving cosine from a normalized vector.&#xA;&#xA;After that I did exactly what the linked answer said and made the following change:&#xA;&#xA;    if( (depth * ray.cosA) &gt; rasterized_depth){&#xA;        break;&#xA;    }&#xA;&#xA;And here are the results! No depth artifacts!&#xA;&#xA;[![enter image description here][5]][5]&#xA;&#xA;[![enter image description here][6]][6]&#xA;&#xA;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays&#xA;  [2]: https://i.stack.imgur.com/rZakQ.gif&#xA;  [3]: https://i.stack.imgur.com/4fD5Z.gif&#xA;  [4]: https://computergraphics.stackexchange.com/a/7675/6530&#xA;  [5]: https://i.stack.imgur.com/IptJC.gif&#xA;  [6]: https://i.stack.imgur.com/kIzIU.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="28724" PostHistoryTypeId="5" PostId="7517" RevisionGUID="db9b3caa-0f37-4fa3-b48d-91a1e31fc7aa" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="To be honest, terms like these are very confusing as they aren't clear cut and on one side of the border. They are more grayish.&#xA;&#xA;I'm gonna tell you how I convinced myself, as I too had this confusion as soon as I read your question. But I managed to convince myself through this argument.&#xA;&#xA;First of all we are gonna clear up 4 terms, Radiance, Irradiance, Differential radiance and Differential Irradiance.&#xA;&#xA; **&quot;Radiance&quot; is what you say associated with a certain direction. To be more formal and according to wikipedia,**&#xA;&#xA;&gt;  It's the amount of radiant flux emitted/transmitted/received per unit&#xA;&gt; projected area, per unit solid angle.&#xA;&#xA;&#xA;&#xA;**Next is differential radiance. We can think of it as an infinitesimal quantity of radiance emitted or recieved in a very small solid angle $d\omega$.**&#xA;&#xA;**Next is Irradiance. Irradiance isn't normally associated with a direction. According to Wikipedia it's** &#xA;&#xA;&gt; Radiant flux received by a surface per unit area&#xA;&#xA;But more commonly and what makes more sense to me, and to the answer of your question, think of irradiance as the integration of radiances over a set of directions.&#xA;&#xA;So we can say&#xA;&#xA;$E = \displaystyle\int_{\Omega} L(\omega)\;  \omega.n \;d\omega\\\omega \in \Omega$&#xA;&#xA;So if we integrate the radiances from every direction that leads us to the original definition of irradiance where direction isn't of concern. However usually we are concerned with only a subset of all the directions such as the Upper hemisphere or the lower hemisphere. This means for example,&#xA;&#xA;$\Omega = \{ \omega : \omega.n \geq 0 \}$ &#xA;&#xA;As we can see here, we have limited the irradiance to a set of directions, the upper hemisphere. This doesn't necessarily change it into radiance which is associated by direction. Instead what this means is, when calculating irradiance we are concerned with the light coming only from these directions, although we haven't incorporated the directional quantity into the formula like with radiance.&#xA;&#xA;This is the difference between irradiance from a certain direction and radiance. Think of it like this. You are holding a paper and there are 2 light bulbs in front of you. You want to measure the irradiance. Normally it would just be the radiant flux received by both bulbs per unit area. But now let's say I limit the direction so I am only concerned with the first bulb. Note that I am still calculating the &quot;irradiance&quot;. If I move farther away the flux will decrease thus the irradiance even tho I am concerned with a specific direction. However this isn't the case with radiance where moving farther away won't change it since we divide by the solid angle too balancing the change.&#xA;&#xA;**The last quantity is differential irradiance. I thought of it as a tiny amount of irradiance from a specific direction. (Again direction gets involved)**&#xA;&#xA;If you think of irradiance as not assosciated with direction at all, even then when you try to think of differential irradiance you are gonna say it's a tiny amount of irradiance from a small range of direction or maybe a specific direction. That's the reason why it's small.&#xA;&#xA;But if you think of irradiance as the sum of all the radiances over a specific set of directions. You'll see that it makes things clearer and you'll naturally arrive at the conclusion that differential irradiance will then refer to an irradiance from a specific direction.&#xA;&#xA;So coming back to your question at last, I hope you might have gotten some intuition as to what &quot;irradiance in a direction means&quot;. &#xA;&#xA;Mathematically proving it is no hard feat tho. The answer [here][1] explains it quite well. I'm just gonna give a brief explanation. We know the rendering equation is given as&#xA;&#xA;$L_{outgoing} = L_{emission} + \displaystyle\int_{\Omega} L_{incoming} \;f_{BRDF}(\omega_i, \omega_o)\; \omega_i.n \; d\omega_i$&#xA;&#xA;&#xA;Assuming for the moment that emission part is zero. we end up with,&#xA;&#xA;$L_{outgoing} = \displaystyle\int_{\Omega} L_{incoming} \;f_{BRDF}(\omega_i, \omega_o)\; \omega_i.n \; d\omega_i$&#xA;&#xA;Now as I wrote before, if you forget the BRDF for the time being, we are just integrating the radiances over a given set of direction which is the same as irradiance. &#xA;&#xA;If we look at one instance of this summation/integration, it's gonna be&#xA;&#xA;$dL_{outgoing} =  L_{incoming} \; \omega_i.n \; d\omega_i \; f_{BRDF}(\omega_i, \omega_o)$&#xA;&#xA;$dL_{outgoing} =  dE \; f_{BRDF}(\omega_i, \omega_o)$&#xA;&#xA;We put $d$ with the outgoind radiance and irradiance because it's a very small part (we are looking at just one instance of that summation/integration)&#xA;&#xA;$f_{BRDF}(\omega_i, \omega_o) = \displaystyle\frac{dL_{outgoing}}{dE} $&#xA;&#xA;&#xA;Which is the ratio of the outgoing radiance to the incoming irradiance.&#xA;&#xA;Again this was just the way I convinced myself and might have some mistakes. Though this is the best I came up with.&#xA;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/3757/why-isnt-a-brdf-a-ratio-of-radiances" ContentLicense="CC BY-SA 4.0" />
  <row Id="28725" PostHistoryTypeId="5" PostId="7513" RevisionGUID="290d4745-1ce8-4806-96a8-066980d9d172" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I can easily make models by [Modeling with Distance Functions][1] but I need make mesh from It so I decide to use voxelizing and make triangles for my [signed distance field torus][2] like [this video][3].but I haven't Idea that how can I do this.&#xA;you can see this torus on [my github](https://github.com/smkplus/UnityRayMarching).&#xA;&#xA;[![torus][4]][4]&#xA;______________&#xA;&#xA;# Update&#xA;&#xA;[![Snail IQ][5]][5]&#xA;&#xA;[Snail SDF](https://www.shadertoy.com/view/ld3Gz2)&#xA;&#xA;I found a software as **SDF Mesher**.this is what I want but not released.&#xA;&#xA;[aiekick instagram](https://www.instagram.com/aiekick/),&#xA;[aiekick twitter](https://twitter.com/hashtag/sdfmesher)&#xA;&#xA;&#xA;he converted shader to mesh?! how could be Implemented!?&#xA;&#xA;[aiekick sketchfab](https://sketchfab.com/Aiekick)&#xA;__________________&#xA;&#xA;In short I need a way to convert sdf to mesh.for example this:&#xA;&#xA;Input : [SDF Model](https://www.shadertoy.com/view/4tc3WB)&#xA;&#xA;Output : [Mesh](https://sketchfab.com/models/e1ebf9fcd38444d88e45f84204781db9)&#xA;&#xA;&#xA;  [1]: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm&#xA;  [2]: https://www.gamasutra.com/blogs/DavidArppe/20170405/295240/How_to_get_Stunning_Graphics_with_Raymarching_in_Games.php&#xA;  [3]: https://www.youtube.com/watch?v=B_xk71YopsA&#xA;  [4]: https://i.stack.imgur.com/jF5Ng.png&#xA;  [5]: https://i.stack.imgur.com/YoSlj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28726" PostHistoryTypeId="5" PostId="7995" RevisionGUID="c0e38dbb-247f-47c2-9916-e25f1907c4a7" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="&gt; How do I calculate average hue, since the numbers loop around?&#xA;&gt;&#xA;&gt; I will get silly answers sometimes. For example, in HSB/HSL, the average of hue=10 (slightly orange red) and hue=350 (slightly blue red) would arithmetically be hue=(10+350)/2=180 (cyan).&#xA;&#xA;- [How to calculate mean and standard deviation for hue values from 0 to 360?&#xA;](https://stackoverflow.com/q/8169654/3648282) **and** [Averaging circular values (particularly Hues in HSL color scheme)](https://stackoverflow.com/q/13959276/3648282) which provides C++ source code.&#xA;&#xA;What if the values were 0° and 180°, then there are two answers: 90° and 270°; the same thing applies whenever the two inputs are opposite, there's two answers and no clear choice.&#xA;&#xA;- The program &quot;[Image Color Summarizer][1]&quot; (Linux version) has a file called &quot;peravg.pm&quot; which says: &quot;compute the average and median of a periodic data set, like a set of angles or hues&quot;. The [main page][2] offers a Windows version and a webpage image upload along with an API. &#xA;&#xA;The author explains:&#xA;&#xA;&gt; The colour summarizer will produce descriptive colour statistics for an image. Reported will be the average, median, minimum and maximum of each component of RGB, HSV, LCH and Lab. Average hues are calculated using [mean of circular quantities][3].&#xA;&gt;&#xA;&gt; Some of the questions the summarizer will answer are:&#xA;&gt;&#xA;&gt; - what is the average color hue, saturation and value in my image?&#xA;&gt; - what are the colours that are most representative of the image?&#xA;&gt; - what is the image's human readable colour description (e.g. dark pure blue)?&#xA;&gt; - what do the RGB, HSV, LCH and Lab histograms look like?&#xA;&gt; - what are the RGB, HSV, LCH and Lab pixel values? &#xA;&#xA;The paper: &quot;[Perceiving the average hue of color arrays][4]&quot; (May 1 2014), by Jacquelyn Webster, Paul Kay, and Michael A. Webster examines the subject from the viewpoint of an observer's perception of color.&#xA;&#xA;&#xA;[![HSL][5]][5]&#xA;&#xA;&#xA;  [1]: http://mkweb.bcgsc.ca/color-summarizer/?download&#xA;  [2]: http://mkweb.bcgsc.ca/color-summarizer/&#xA;  [3]: https://en.wikipedia.org/wiki/Mean_of_circular_quantities&#xA;  [4]: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3979548/&#xA;  [5]: https://i.stack.imgur.com/Dq2Ch.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28727" PostHistoryTypeId="5" PostId="8939" RevisionGUID="3e9b9ee2-41e9-41ca-ac71-f5f77bd87bbb" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="&gt; Starting from reading the data from a file to displaying the image on the screen.&#xA;&#xA;As was pointed out in the comments, this is an extremely broad question, and depends on what operating system you're using, and which tool sets for that OS you're using. That said, I think it is possible to talk generally about the process with much of it (if not all) being similar from machine to machine, and OS to OS.&#xA;&#xA;&gt;I am puzzled regarding which parts of this process are handled by the OS and which are handled by the GPU.&#xA;&#xA;I'll try to point out which parts are handled strictly by the OS, your program, and the graphics hardware, and I'll even provide C-like pseudo code. My pretend code will not be efficient, simply illustrative, and I'll be pretending to read [this example](https://en.wikipedia.org/wiki/Netpbm_format#PPM_example) image file.&#xA;&#xA;&gt;For example, how does a 1920x1080 image eventually get displayed on screens with higher or lower display resolutions?&#xA;&#xA;I think some of my pretend pseudo code will illustrate that, but the short answer is that you will manually resize your image to better fit the screen (or any other drawing area) inside your program.&#xA;&#xA;# The Long Answer&#xA;&#xA;The first step is to open the image file. It doesn't matter what the format of the image is, from the view of your program it'll simply be a list of bytes. Some languages have tools and libraries that can be used to open files in a generic (OS independent) way, but often this step is OS specific. However, even though the task of opening and/or reading the file is dependent on the operating system, once your program has copied the content into memory it's just bytes for your program to deal with however you desire.&#xA;&#xA;```&#xA;File imgFile = OS_OPEN_FILE(&quot;sample.ppm&quot;); // Ask the OS for a file.&#xA;byte buffer[imgFile.size()];               // Set aside memory to hold the file's content.&#xA;for(int i = 0; i &lt; imgFile.size(); ++i) {  // Start a reading loop.&#xA;    buffer[i] = OS_READ_BYTE(imgFile);     // Ask the OS for all bytes in the file, one by one.&#xA;}&#xA;```&#xA;&#xA;Once you have access to all of the bytes in the entire image file it is up to you, the programmer, to know what each byte means, then to make your program read and interpret them correctly. For example, the [portable bitmap format](https://en.wikipedia.org/wiki/Netpbm_format) starts with a couple of bytes letting you know if the picture file is color, gray scale, or black and white. There are bytes that let you know what size the picture is, bytes that should be ignored because they're comments intended for humans to read, and finally bytes that are the dots of color to be sent to the screen. It is up to the program to sort through all of that.&#xA;&#xA;```&#xA;int bufSize = imgFile.size();&#xA;for(int i = 0; i &lt; bufSize; ++i) {  // loop through all the bytes read earlier.&#xA;    if(buffer[i] == 'P' &amp;&amp; buffer[i+1] == '3') {  // Handle the image header.&#xA;        /* Do something */&#xA;    }&#xA;    else if(buffer[i] == '#') {  // Handle comments&#xA;        /* Do something */&#xA;    }&#xA;    else if(buffer[i] == /*...*/) {&#xA;        /* Do something */&#xA;    }&#xA;   /* ... etc. */&#xA;}&#xA;```&#xA;&#xA;The next task is OS specific. You'll need to somehow ask the operating system to give your program access to a &quot;drawing surface&quot;. Again, there are libraries such as [SDL](https://www.libsdl.org/) or [SFML](https://www.sfml-dev.org/) that provide surfaces in a generic way, but they are hiding the surface the system gave them behind an easy to use wrapper.&#xA;&#xA;Often the drawing surface given by the OS is just a big block of bytes and you can simply copy data into it. Again, it is up to you to know which byte does what (like, which bytes represent red, green, or blue), but the task itself is usually just to copy from one chunk of memory into another. This is known as a **Bl**ock **I**mage **T**ransfer, or a BLIT, and it's at this point that you may be handling memory inside the graphics card. Ultimately, it's up to the OS to decide where the drawing surface keeps the bytes that represent colors, but you can usually request that those bytes be on the GPU.&#xA;&#xA;```&#xA;Surface sampleImage = OS_GET_GPU_DRAWING_SURFACE();&#xA;if(sampleImage.good()) {&#xA;    /* Copy in bytes from buffer[], sorting or converting data as needed. */&#xA;}&#xA;```&#xA;&#xA;Depending on what tools you're using, and what task you're performing, a drawing surface you request from the OS can be the screen itself, and other times the screen is something that you can't touch directly but can only send surfaces to. Even when you *can* draw directly to the screen you will want to draw to a hidden surface, then blit the finished work over to the screen to prevent flickering and other visual problems. This is called [double buffering](https://gameprogrammingpatterns.com/double-buffer.html), and mostly applies to the screen because it's always visible to the user.&#xA;&#xA;Generally you will have many small drawing surfaces that represent things like, buttons, pieces of terrain in a game, letters, or whatever, and you'll use those to assemble a larger image on a bigger (usually screen sized) drawing surface that you will finally send to the screen as one big block.&#xA;&#xA;Just to reiterate, these steps are all being done by your program, but the way your program has to do them is OS specific, and much of the memory being handled at this late stage is *probably* on the GPU.&#xA;&#xA;```&#xA;// Ready the screen and a drawing area.&#xA;Surface * screen = OS_GET_SCREEN_SURFACE();&#xA;Surface * screenBuffer = OS_GET_GPU_DRAWING_SURFACE();&#xA;&#xA;// Make the image 800% bigger!&#xA;sampleImage.resize(8.0f);&#xA;// Copy the image to the screen sized buffer, centering it.&#xA;// blitTo(surface, x, y)&#xA;// I'm assuming that in this pretend code images draw from their top left corner.&#xA;sampleImage.blitTo(screenBuffer,&#xA;                   screenBuffer.width()/2 - sampleImage.width()/2,&#xA;                   screenBuffer.height()/2 - sampleImage.height()/2);&#xA;/* ... etc. */&#xA;/* Do more image drawing work. */&#xA;&#xA;// Finally, display all our complex behind the scenes work to the user.&#xA;// This is called a buffer swap.&#xA;Surface * temp = NULL;&#xA;temp = screen;&#xA;screen = screenBuffer;&#xA;screenBuffer = temp;&#xA;temp = NULL;&#xA;&#xA;```&#xA;&#xA;# The Short Answer&#xA;&#xA;In summary...&#xA;&#xA;Task your program needs to do (what's primarily in charge):&#xA;&#xA;1. Open a file (OS)&#xA;2. Read file (OS &amp; Program)&#xA;3. Interpret data (Program)&#xA;4. Get a drawing surface (OS &amp; GPU)&#xA;5. Fill the drawing surface with image data. (Program &amp; GPU)&#xA;6. Assemble your final picture. (Program &amp; GPU)&#xA;7. Gain access to the screen (OS)&#xA;8. Send your final picture to the screen. (OS and/or Program)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28728" PostHistoryTypeId="5" PostId="9886" RevisionGUID="35acdde1-4418-40ea-8220-4487c4491e19" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="First, [here is a link](https://graphicdesign.stackexchange.com/questions/21204/why-do-jpeg-files-blur-red-more-than-other-colors) to a related topic of the graphic design stack exchange site. &#xA;&#xA;Even though the discussion was more focussed around effects on an image with large homogeneous color areas, here are some quotes I think that are relevant for your case:&#xA;&#xA;&gt; JPEGs are best suited for **continuous tone** images like photographs or natural artwork; **not so well on sharp-edged** or flat-color art like lettering, simple cartoons, or line drawings&#xA;&gt;&#xA;&gt; JPEG is actually just a compression algorithm, not a file format. JPEG is designed to exploit certain properties of our eyes, namely, **that we are more sensitive to slow changes of brightness and color than we are to rapid changes** over a short distance&#xA;&gt;&#xA;&gt; Compression artifacts from **hard edges** are proportional to the contrast of the edges&#xA;&gt;&#xA;&gt; This loss of data is most often noticeable where colors transition from one field of solid color to another field of solid color. **There's no direct issue with any particular color specifically.** It is more about large areas of similar colors.&#xA;&#xA;Also [Wikipedia says](https://en.wikipedia.org/wiki/JPEG) in the articles &quot;JPEG compression&quot; section:&#xA;&#xA;&gt;  A perceptual model based loosely on the human psychovisual system discards high-frequency information, i.e. **sharp transitions in intensity**, and color hue.&#xA;&#xA;&#xA;&#xA;Building upon these quotes I conclude, that the compression artifacts do not depend on the color, as you already read in other sources. However, JPEGs are obviously not suited for high contrasts and sharp edges.&#xA;&#xA;Now when I look at your pictures, the rose blossoms and the red cake have complex/rough surfaces that cast a lot of shadows. So they have hard edges in their intensity/brightness and you can expect some artifacts there. Most of the other parts of those images don't have such a high density of sharp edges, this why you might think that red is particularly affected by the compression. The fact that the high contrast and brightness of the red attracts your eye's attention increases this impression. But if you look at other sharp edges, for example, the chocolate on top of the second cake or the yellow paper that is wrapped around the roses in the first picture, you can also see those compression artifacts. The lower density of sharp edges and the duller colors just don't make them so obvious.&#xA;&#xA;&gt; Can we do anything while photoshoot or post editing to fix these issues?&#xA;&#xA;If you have the option, the best thing would be to use an image format with loss-free compression -&gt; PNG. &#xA;&#xA;If this is not an option, the only thing I can come up with is avoiding high contrasts in your motives. Also, maybe you can use some photoshop filters to soften the hard edges a little bit before you compress the image. This will also reduce the image quality, but maybe it will give more acceptable results after compression (no guarantees here - might be worse).&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28729" PostHistoryTypeId="5" PostId="9835" RevisionGUID="97503fda-7c5c-4f93-86c8-a3e764df21bb" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="# Bounding Volumes&#xA;A bounding volume is for example an Axis-Aligned Bounding-Box (AABB), a generaal Bounding-Box not aligned with the major axes or a Bounding-Sphere. They differ in &#xA;&#xA;* how much memory they take (e.g. a sphere takes only 4 floats, AABB 6 floats)&#xA;* how good they enclose the object's geometry &#xA;* how fast are the related computations (mainly intersection tests).&#xA;&#xA;You will find an extensive overview at [Wikipedia](https://en.wikipedia.org/wiki/Bounding_volume).&#xA;&#xA;# Hierarchy of volumes&#xA;So in the hierarchy of bounding volumes, instead of whole meshes you will store only their bounding volumes. You choose a single type, e.g. a bounding sphere, and will use it to build the whole BVH. At the bottom level each bounding volume will probably enclose only a single object. You will build the hierarchy up by enclosing pairs or smaller groups of volumes in a larger volume.&#xA;&#xA;So using spheres you would enclose each object into a bounding sphere at first. Then at the higher levels of the hierarchy, you would always create a new sphere enclosing a few spheres from the previous level which are close to each other. You proceed until a single root sphere encloses all 3D objects in your scene.&#xA;&#xA;There are different [strategies to create BVH](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy). But all have in common that complex structures like triangle meshes are hierarchically clustered using very simple entities." ContentLicense="CC BY-SA 4.0" />
  <row Id="28730" PostHistoryTypeId="5" PostId="9798" RevisionGUID="fca043e2-da32-419e-b993-db500d1c0b22" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have a bezier curve and would like to draw it's stroke. To do that, I planned to approximate the stroke to a polygon and fill it with a scanline algorithm. While I feel confident about implementing the conversion and the scanline algorithm, I am unsure how to handle the situation when a polygon intersects itself.&#xA;&#xA;If I don't treat it specially, it will look like on this picture on the left side, but what I am actually looking for is something like on the right side. Is there a popular method how to do that?&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;  [1]: https://i.stack.imgur.com/uggRT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28731" PostHistoryTypeId="5" PostId="9691" RevisionGUID="d2b1aebe-e6a2-4720-bc5c-f2374507f8a2" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Let $h_j$ denote the image reconstruction filter of pixel $j$. &#xA;I'm estimating the color value $$I_j=\int h_jf\:{\rm d}\mu$$ of the $j$th pixel (see [[Veach, Section 8.2]](http://graphics.stanford.edu/papers/veach_thesis/thesis.pdf)) by an asymptotically consistent estimator whose asymptotic variance is given by $\sigma^2_j$. (This has to be understood in a component-wise sense, i.e. $\sigma_j^2$ is a 3-dimensional vector whose $i$th component is the asymptotic variance of the estimate of the $i$th component of $I_j$.&#xA;&#xA;&gt; **Question 1**: I want to compare different estimators which lead to different asymptotic variances and would like to visualize that one is superior to another (with respect to variance reduction). How can I do that? Simply writing the variances into an image doesn't seem to be sensible. (The problem is the scale of the values.)&#xA;&gt;&#xA;&gt; **Question 2**: For simplicity, assume a box filter with radius $\frac12$ so that the computation of $I_j$ only involves the $j$th pixel. Instead of considering the variances of each pixel, I've seen that we could consider the variances of a &quot;local window&quot; (for example a $3\times 3$ pixel window). Is this a better or worse metric for the total variance of the image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28732" PostHistoryTypeId="5" PostId="9601" RevisionGUID="dbb4f0a6-d103-4250-8b59-fd07c98b93a2" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="# TL;DR: &#xA;&#xA;The view frustum **is** the NDC box.  It's just that NDC space is nonlinear because it occurs **after** the perspective divide by w.  The tops and sides of the frustum are *parallel* in NDC space. All lines that project to the viewpoint are parallel in NDC space.&#xA;&#xA;# Explanation:&#xA;&#xA;I don't like math.  I dislike sites that try to explain all this with math and matrices and boring stuff like that.  I prefer pictures.  So I'll try to explain it with mainly pictures and descriptions.  Unfortunately the one thing that I must refer to mathematically is the fact that we have to _divide by Z_ to transform 3D points to 2D points according to the perspective transformation.  But &quot;divide by Z&quot; is as mathematical as I'll get, I promise.&#xA;&#xA;### The spaces&#xA;&#xA;Recall the different spaces.  The View and Projection matrices are all linear transformations.  World Space, Camera Space, and Homogeneous Clip Space are all linear spaces.  The Normalized Device Coordinates are in a non-linear (projective) space and the Divide by w is a non-linear transformation.  We reinterpret these coordinates as screen coordinates and do a linear transform from NDC to viewport coordinates.&#xA;&#xA;The whole point of clip space is to keep the space linear and defer dividing by Z until the very end.  The denominator of the perspective transformation is kept as its own coordinate in linear space and called W (it's the divisor for the homogeneous coordinates).  At some point we can no longer defer this divide because we need screen coordinates so we must ultimately go from (X,Y,Z,W) to (X/W, Y/W, Z/W) and wind up in NDC space.  (Technically we go from homogeneous coordinates to 3-space.)  &#xA;&#xA;&gt; So I think this is the mathematical part of the answer to your question:  `(X,Y,Z,W) → (X/W, Y/W, Z/W)` is called the **Perspective Divide by W** and it's the operation you're looking for that maps from Clip space to NDC.  &#xA;&#xA;### The transformations&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;### Visualizing NDC&#xA;&#xA;I've always hated how people draw the frustum with straight lines and draw the NDC box with straight lines but never show what's going on in the interior.  It really betrays our understanding of the non-linearity of relationship between the two spaces.  So here's a better diagram to help visualize the non-linearity of NDC space after the perspective projection.&#xA;&#xA;[![enter image description here][2]][2]&#xA;&#xA;Imagine you stand where the person with the camera is and take a picture.  The red lines are the boundaries of what the camera can see.&#xA;Some familiar properties:&#xA;&#xA; - All points along the top of the red frustum will be at the top of the camera image&#xA; - All points along the bottom of the red frustum will be at the bottom of the camera image.&#xA; - The side of the frustum closest to the camera (left of this diagram) is the near clipping plane&#xA; - The side of the frustum farthest from the camera (right of this diagram) is the far clipping plane. &#xA;&#xA;The top part of the diagram is World / View / Clip clip space. They are all linear transforms of one another, so for this diagram they are all basically the same.&#xA;&#xA;The bottom part of the diagram is Normalized Device Coordinate space. In NDC space the top and bottom of that frustum are _parallel_.  Notice the frustum in Clip space became a rectangle in NDC space.  Because the near clipping plane and the far clipping plane both become the same size as the camera image (camera sensor / camera frame).&#xA;&#xA;Note that any line that passes through the viewpoint is parallel to the top and bottom of this frustum in NDC space -- the magenta line is an example of this.   Notice that the magenta line passes just over the roof of the first (near) car and just over the back tire of the yellow (far) car.  Yet in NDC space, this line is parallel to the top of the frustum and the bottom of the frustum.  All the points along that magenta line will have the same coordinates in the final camera image (will appear at the same point on the screen in your rendering).  Cool, right?&#xA;&#xA;The frustum becomes a box in NDC space, which, I'll admit, is deceptively linear-seeming.  But you can tell the NDC space is non-linear (has that &quot;divides by Z&quot; property) because the lines of the sidewalk (which are parallel in world space or view/camera space) are not parallel in NDC space.  They follow that characteristic 1/x style curve in the diagram.&#xA;&#xA;In the diagram, for some distance away from the camera, everything is proportionally the same distance away from the top and bottom of the camera frustum in both Clip space, and NDC.  &#xA;&#xA;&#xA;  [1]: https://i.stack.imgur.com/qJyXv.png&#xA;  [2]: https://i.stack.imgur.com/zaLzI.png&#xA;&#xA;### Summary &#xA;&#xA;Hopefully this is a useful visual explanation of how to get between World / View / Clip space and NDC.  This is intended to supplement the mathematical descriptions you've already been given, not replace them.  Hopefully this gives you a visual with which you can ground your understanding of the non-linearity of projective transformations.&#xA;&#xA;Just remember:&#xA;&#xA; - That although all the camera boundaries (red lines in the diagram) match between&#xA;   World space and NDC, it's a **frustum in World space** and a **rectangle in NDC space**.  (So _yes_, the corners of the view frustum *are* the corners of the NDC &quot;cube&quot;)&#xA; - That straight lines (that run closer or farther to the camera and don't pass through the viewpoint) like the edges of the sidewalk are **straight in World space** but **may be curved in NDC space**. :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28733" PostHistoryTypeId="5" PostId="9597" RevisionGUID="9931b6b2-2215-442b-b00d-7411f606d296" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="**Note: This is a work in progress - working on LaTeX and useful illustrations.**&#xA;&#xA;---&#xA;&#xA;My derivation notes were based partially on the perspective projection matrix derivation in [`Computer Graphics: Principles and Practice (2nd Ed)`](https://www.amazon.com/Computer-Graphics-Principles-Practice-2nd/dp/0201848406). My understanding is that the 3rd edition takes a more contemporary approach with references to OpenGL and Direct3D. I haven't read this edition, and can't vouch for it.&#xA;&#xA;This derivation also assumes an understanding of homogeneous coordinates and the notion of a projective space. The wikipedia entry is concise, but lacks the intuition provided by a few good **2D** example illustrations. (If you're *really* keen, search for early articles on the subject by [Jim Blinn](http://www.jimblinn.com/)).&#xA;&#xA;First, we need to outline a few assertions and conventions:&#xA;&#xA;&#xA;- We always assume a ['right-handed' coordinate space](https://en.wikipedia.org/wiki/Right-hand_rule#Coordinates), unless otherwise stated. The 'eye' is at: `(0, 0, 0)`. `(+Z)` may be considered the direction pointing 'out' of the screen (or window / viewport), while `(X, Y)` are Cartesian coordinates, where: `(0, 0)` corresponds to the centre of that viewport.&#xA;&#xA;&lt;/br&gt;&#xA;&#xA;- The [**view frustum**](https://en.wikipedia.org/wiki/Viewing_frustum) has a near plane at: `Z = - N` and a far plane at: `Z = - F`, with normals in the `+Z` direction. The near plane: `Z = - N`, has `X: L &lt;= X &lt;= R`, and `Y: B &lt;= Y &lt;= T`, which will eventually map to a **3D viewport**. This frustum encapsulates all visible geometry. (Technically speaking, `R &lt; L`, `T &lt; B`, and `N &gt; F &gt; 0` are permitted by `glFrustum`. Arbitrary matrices are of course permitted in core profile OpenGL contexts.)&#xA;&#xA;&lt;/br&gt;&#xA;&#xA;- The mathematics will use what are somewhat misleadingly called 'row-major' matrices, but I insist on the use of column vectors when describing a system of transforms, i.e., the *column* vector is 'pre-multiplied' by the matrix: `v' = [M]v`. Disagree all you want - just know that you are sick and need help.&#xA;&#xA;  In all seriousness, either convention can be made to work; it's just a matter of being aware of the conventions and sticking with a choice. The 'column-vector' convention is typically the one taught in linear algebra. We apply *successive* transforms: `[A]`, `[B]`, `[C]` to a vector: `v`, like we would apply functions: `C(B(A(v)))`, hence: `v' = [C][B][A]v`.&#xA;&#xA;---&#xA;&#xA;Any view frustum (camera) in space can be transformed by pre-multiplying the (homogeneous) coordinates by an 'orientation matrix'. That's beyond your question, but typically requires a general **PRP** (camera eye point), **VRP** (the centre of the 'near' projection plane), and the **VUP** point, which references a point defining 'up'. In effect, it's sufficient to form a orthonormal coordinate system. This is the view coordinate space **(VCS)**.&#xA;&#xA;The orthonormal basis, along with the **PRP** translation, can be used to construct an inverse transform that 'premultiplies' geometry to world coordinate space **(WCS)**. Again, you can save the concept of orthonormal basis / coordinate system transforms for a rainy day...&#xA;&#xA;---&#xA;&#xA;We do not *assume* the view frustum is centred on the Z axis - although this is almost certainly the case for most projections. There are more exotic transforms (a mirror in a scene comes to mind); we'll concentrate on the general case.&#xA;&#xA;The direction of projection: $\small\\\mathbf{DOP}=\left[(R+L)/2,\: (T+B)/2,\: -N\right]\,^T$. The view frustum is typically symmetric about the Z axis s.t. `R = - L`, `T = - B`, yielding: $\small\\\mathbf{DOP}=\left[0,\: 0,\: -N\right]\,^T$.&#xA;&#xA;Of course, this is not *required*, so our first step in the perspective projection derivation is to apply a *shear* matrix that maps the $\small\\\mathbf{DOP}$ to the (negative) Z-axis:&#xA;&#xA;`(R + L) / 2 + shear.x (- N) = 0` =&gt; `shear.x = (R + L) / (2.N)`&lt;br/&gt;&#xA;`(T + B) / 2 + shear.y (- N) = 0` =&gt; `shear.y = (T + B) / (2.N)`&#xA;&#xA;Consider the shear transformation applied to the frustum's near-clipping plane vertex coordinates:&#xA;&#xA;$\tiny\begin{pmatrix}&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ 0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;R \\ T \\ -N \\ 1&#xA;\end{pmatrix}&#xA;= \begin{pmatrix}&#xA;(R-L)/2 \\ (T-B)/2 \\ -N \\ 1&#xA;\end{pmatrix}&#xA;\:,$&#xA;&#xA;$\tiny\begin{pmatrix}&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ 0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;L \\ B \\ -N \\ 1&#xA;\end{pmatrix}&#xA;= \begin{pmatrix}&#xA;(L-R)/2 \\ (B-T)/2 \\ -N \\1&#xA;\end{pmatrix}&#xA;$&#xA;&#xA;Following this transform, the $\small\\\mathbf{DOP}$ is in direction of the `- Z` axis; specifically, the centre of the near view plane: $\small\left((R+L)/2,\: (T+B)/2,\: -N,\: 1\right)\,^T$ has been mapped to: $\small\left(0,\: 0,\: -N,\: 1\right)\,^T$.&#xA;&#xA;Now we want to scale the perspective projection transform such that the `R, L, T, B` planes of the frustum have have a unit gradient. The current gradients are `(R - L) / (2.N)` (right and left), and `(T - B) / (2.N)` (top and bottom). The symmetry is due to the previous shearing transform.&#xA;&#xA;`(R - L) / (2.N) * scale.x = 1` =&gt; `scale.x = 2.N / (R - L)`&lt;br/&gt;&#xA;`(T - B) / (2.N) * scale.y = 1` =&gt; `scale.y = 2.N / (T - B)`&#xA;&#xA;Furthermore, we want to scale by `(1 / F)` s.t. the far clipping plane is mapped to: `Z = - 1`, while the unit slopes of the right, left, top, and bottom clipping planes are preserved. These scaling factors premultiply the perspective projection matrix:&#xA;&#xA;$&#xA;\tiny\begin{pmatrix}&#xA;2.N/(F(R-L)) &amp; 0 &amp; 0 &amp; 1 \\ 0 &amp; 2.N/(F(T-B)) &amp; 0 &amp; 1 \\ &#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;1 &amp; 0 &amp; (R+L)/(2.N) &amp; 0 \\ 0 &amp; 1 &amp; (T+B)/(2.N) &amp; 0 \\ &#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;=\\&#xA;\tiny\begin{pmatrix}&#xA;2.N/(F(R-L)) &amp; 0 &amp; (R+L)/(F(R-L)) &amp; 0 \\ &#xA;0 &amp; 2.N/(F(T-B)) &amp; (T+B)/(F(T-B)) &amp; 0 \\ &#xA;0 &amp; 0 &amp; 1/F &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;$&#xA;&#xA;This transform yields what may be considered *the normalized frustum*.&#xA;&#xA;**(TODO: need an image to show this transform)**&#xA;&#xA;The vertices of near clipping plane are mapped to: $\small\left(\pm N/F,\: \pm N/F,\: -N/F,\: 1\right)\,^T$, while the vertices of the far-clipping plane are mapped to: $\small\left(\pm 1,\: \pm 1,\: -1,\: 1\right)\,^T$.&#xA;&#xA;---&#xA;&#xA;**(TODO: perspective (projection) transform unification -&gt; CCS)**&#xA;&#xA;As a homogeneous transform, the matrix can be simplified by scaling all elements by `F`, since: $\small\left(X,\: Y,\: Z,\: W\right)\,^T \equiv \left(F.X,\: F.Y,\: F.Z,\: F.W\right)\,^T$ :&#xA;&#xA;$&#xA;\tiny\begin{pmatrix}&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; F&#xA;\end{pmatrix}&#xA;$&#xA;&#xA;The normalized perspective projection view volume can be transformed into a parallel projection view volume:&#xA;&#xA;**(TODO: partial justification for this step. Perspective projection is just another homogeneous transform. Final CCS / NDCS have exquisite clip test properties)**&#xA;&#xA;$&#xA;\tiny\begin{pmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; F/(F-N) &amp; N/(F-N) \\ 0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; F&#xA;\end{pmatrix}&#xA;=\\&#xA;\tiny\begin{pmatrix}&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xA;0 &amp; 0 &amp; F/(F-N) &amp; F.N/(F-N) \\ 0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{pmatrix}&#xA;$&#xA;&#xA;**(TODO: need an image to show this transform)**&#xA;&#xA;---&#xA;&#xA;Finally, we apply the following transforms to the current projection matrix:&#xA;&#xA;- Scale in `Z` by `(2)` to yield a cubic view volume.&#xA;- Translate by: $\small\left(0,\: 0,\: 1,\: 1\right)\,^T$ to centre the cube at the origin.&#xA;- Convert to a left-handed coordinate system to satisfy **NDCS** conventions.&#xA;&#xA;$&#xA;\tiny\begin{pmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -1 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 1 &amp; 1 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; 2 &amp; 0 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;=\&#xA;\begin{pmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -2 &amp; -1 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;$&#xA;&#xA;This yields:&#xA;&#xA;$&#xA;\tiny\begin{pmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 &amp; 0 \\ 0 &amp; 0 &amp; -2 &amp; -1 \\ 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{pmatrix}&#xA;\cdot&#xA;\begin{pmatrix}&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xA;0 &amp; 0 &amp; F/(F-N) &amp; F.N/(F-N) \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{pmatrix}&#xA;=\\&#xA;\tiny\begin{pmatrix}&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xA;0 &amp; 0 &amp; -(F+N)/(F-N) &amp; -2.F.N/(F-N) \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{pmatrix}&#xA;$&#xA;&#xA;**(TODO: need an image to show this transform)**&#xA;&#xA;**This is the canonical OpenGL perspective projection matrix:**&#xA;&#xA;$&#xA;\small\begin{pmatrix}&#xA;2.N/(R-L) &amp; 0 &amp; (R+L)/(R-L) &amp; 0 \\&#xA;0 &amp; 2.N/(T-B) &amp; (T+B)/(T-B) &amp; 0 \\&#xA;0 &amp; 0 &amp; -(F+N)/(F-N) &amp; -2.F.N/(F-N) \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{pmatrix}&#xA;$&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28734" PostHistoryTypeId="5" PostId="9589" RevisionGUID="9b460c44-5a47-49d8-912d-86c3f1331c78" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I don't understand why the PBR implementation of Metorpolis Light Transport scales the final image by `b / mutationsPerPixel`.&#xA;&#xA;The authors write:&#xA;&#xA;&gt; *Each Metropolis iteration within &quot;Run nChains Markov chains in parallel&quot; has splatted contributions with weighted unit luminance to the Film so that the final average film luminance before Film::WriteImage() is exactly equal to mutationsPerPixel.*&#xA;&#xA;(see http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Metropolis_Light_Transport.html at the very end of the page.)&#xA;&#xA;For simplicity, assume that we are considering a fixed path length $k\in\mathbb N$ and a single fixed $(s,t)$-strategy. Formally, let&#xA;&#xA; - $M$ denote the scene surface set, $\mathcal B(M)$ denote the Borel $\sigma$-algebra on $M$ and $\sigma_M$ denote the surface measure on $\mathcal B(M)$&#xA; - $E:=M^{\{0,\:\ldots\:,\:,k\}}$, $\mathcal E:={\mathcal B(M)}^{\otimes\{0,\:\ldots\:,\:,k\}}$ and $\lambda:=\sigma_M^{\otimes\{0,\:\ldots\:,\:,k\}}$&#xA; - $f:E\to[0,\infty)^3$ denote the measurement contribution function&#xA; - $q$ be the probability density on $(E,\mathcal E,\lambda)$ corresponding to the $(s,t)$-strategy satisfying $\{q=0\}\subseteq\{f=0\}$&#xA;&#xA;Once more, for simplicity, assume that the generated $(E,\mathcal E)$-valued chain $(X_n)_{n\in\mathbb N}$ is independent and $$X_n\sim q\lambda\;\;\;\text{for all }n\in\mathbb N.$$ If it's easier to understand for you, you might want to take a look at the `importance_sampling_integrator::render()` method in [this code](https://coliru.stacked-crooked.com/view?id=7f55a67c5e1dab10), where I've implemented these simplifications.&#xA;&#xA;Now let's consider the measurement of a single pixel value $$I:=\int hf\:{\rm d}\lambda,$$ where $h:E\to[0,\infty)$ is the image reconstruction filter corresponding to this pixel. Assume (as PBRT does) that $h$ is a Box filter with radius 1/2. So, if $\psi:E\to R$ is the canonical mapping from the path space $E$ to the raster space $R=[0,a)\times[0,b)$, where $a\in\mathbb N$ and $b\in\mathbb N$ are the vertical and horizontal resolution of the image, respectively, and the pixel we've fixed is pixel $(i,j)\in J:=\{0,\ldots,a-1\}\times\{0,\ldots,b-1\}$ then $h$ is simply the indicator function of the set $$B:=\left\{x\in E:\psi(x)\in\underbrace{[i,i+1)\times[j,j+1)}_{=:\:R_{(i,\:j)}}\right\},$$ i.e. $h=1_B$. Now let $$U_n:=\psi(X_n)\;\;\;\text{for }n\in\mathbb N$$ and note that, by construction of $q$, $$U_n\sim\mathcal U_R\;\;\;\text{for all }n\in\mathbb N\tag1,$$ where $\mathcal U_R$ denotes the uniform distribution on $R$. This immediately yields that $$(q\lambda)(B)=\mathcal U_R\left(R_{(i,\:j)}\right)=\frac1{|J|}\tag2.$$&#xA;&#xA;&gt; Let $$g(x):=h(x)\left.\begin{cases}\displaystyle\frac fq(x)&amp;\text{, if }q(x)&gt;0\\0&amp;\text{, otherwise}\end{cases}\right\}\;\;\;\text{for }x\in E.$$ Now the naive estimator for $I$ is $$\frac1n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty} I\;\;\;\text{almost surely}\tag3.$$ However, if I implement this (which corresponds to replacing `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_sampler-&gt;samplesPerPixel);` in the last line of `importance_sampling_integrator::render()` by `m_camera-&gt;film-&gt;WriteImage(pbrt::Float{ 1 } / m_n);`), I end up with a black image. This is not surprising, since due to the very small support of $h$ compared to the whole image, only very few terms contribute to the sum in $(3)$.&#xA;&#xA;So, it seems like that one needs to consider only the visits of $(X_n)_{n\in\mathbb N}$ to the set $B$, i.e. consider the process $$Y_k:=X_{\tau_k}\;\;\;\text{for }k\in\mathbb N$$ instead, where $\tau_0:=0$, $$\tau_k:=\inf\left\{n&gt;\tau_{k-1}:X_n\in B\right\}\;\;\;\text{for }k\in\mathbb N.$$ It's easy to see that $(Y_k)_{k\in\mathbb N}$ is independent with $$Y_n\sim (q\lambda)\left[\;\cdot\mid B\right]\;\;\;\text{for all }k\in\mathbb N\tag4.$$ Moreover, $$\frac1k\sum_{i=1}^kg(Y_i)\xrightarrow{k\to\infty}(q\lambda)\left[g\mid B\right]=|J|I\tag5$$ by $(2)$.&#xA;&#xA;&gt; Now what the code does is independently drawing $X_1,\ldots,X_n\sim q\lambda$, where $$n=n_0|J|\tag6$$ for some $n_0\in\mathbb N$ (called `mutationsPerPixel` in PBRT).&#xA;&#xA;We may consider the number $$N_n:=\sum_{i=1}^n1_B(X_i)$$ of visits to $B$ up to time $n$ and note that $$\operatorname E\left[N_n\right]=\frac n{|J|}\tag7$$ and $$\frac{N_n}n\xrightarrow{n\to\infty}\frac1{|J|}\;\;\;\text{almost surely}.\tag8$$&#xA;&#xA;&gt; Now PBRT (and the code I've provided above as well) uses the estimator $$\frac1{n_0}\sum_{i=1}^ng(X_i)=\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i),$$ but I absolutely don't understand why this works. From $(5)$ we should obtain $$\frac1{\operatorname E\left[N_n\right]}\sum_{i=1}^{N_n}g(Y_i)=\frac{|J|}n\sum_{i=1}^ng(X_i)\xrightarrow{n\to\infty}|J|I\tag9$$ almost surely, but the left-hand side of $(9)$, dividied by $|J|$, is once again the pracitcally not working estimator $(3)$.&#xA;&gt;&#xA;&gt; What am I missing?&#xA;&#xA;**EDIT**: Just to be completely sure I've built the image array by myself using the (supposed to be correct) estimator $(5)$:&#xA;&#xA;&lt;!-- language: lang-cpp --&gt;&#xA;&#xA;    void render(pbrt::Scene const&amp; scene)&#xA;    {&#xA;        auto const light_distribution = pbrt::ComputeLightPowerDistribution(scene);&#xA;    &#xA;        std::unordered_map&lt;pbrt::Light const*, std::size_t&gt; light_to_index;&#xA;        for (std::size_t i = 0; i &lt; scene.lights.size(); ++i)&#xA;            light_to_index[scene.lights[i].get()] = i;&#xA;    &#xA;        std::vector&lt;vertex&gt; z(m_t),&#xA;            y(m_s);&#xA;    &#xA;        std::size_t const a = m_camera-&gt;film-&gt;GetSampleBounds().pMax.y,&#xA;            b = m_camera-&gt;film-&gt;GetSampleBounds().pMax.x;&#xA;        std::vector&lt;pbrt::Spectrum&gt; image(a * b);&#xA;        std::vector&lt;std::size_t&gt; n(a * b);&#xA;    &#xA;        pbrt::MemoryArena arena;&#xA;        for (std::size_t i = 0; i &lt; m_n; ++i)&#xA;        {&#xA;            pbrt::Point2f raster_point;&#xA;            auto const contribution = sample_path(scene, *m_camera, *light_distribution, light_to_index,&#xA;                arena, m_k, m_s, *m_sampler, raster_point, z.data(), y.data());&#xA;            arena.Reset();&#xA;    &#xA;            std::size_t const index = static_cast&lt;std::size_t&gt;(raster_point.y) * b + static_cast&lt;std::size_t&gt;(raster_point.x);&#xA;    &#xA;            image[index] += contribution.value_or(0);&#xA;            ++n[index];&#xA;        }&#xA;    &#xA;        for (std::size_t i = 0; i &lt; n.size(); ++i)&#xA;        {&#xA;            if (n[i] &gt; 0)&#xA;                image[i] = image[i] / (n[i] /** a * b*/);&#xA;        }&#xA;        m_camera-&gt;film-&gt;SetImage(image.data());&#xA;        m_camera-&gt;film-&gt;WriteImage();&#xA;    }&#xA;&#xA;At the end, I should devide each pixel value by $|J|=ab$. However, if I uncomment the devision in the code, I end up with a black image again. So, my guess right now is that the values provided by `BxDF::Sample_f()` are not what I thought they are. Maybe they are &quot;normalized&quot; and maybe this is what they mean by &quot;*Each Metropolis iteration within &lt;&lt;Run nChains Markov chains in parallel&gt;&gt; has splatted contributions with weighted unit luminance*&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="28735" PostHistoryTypeId="5" PostId="9578" RevisionGUID="22bd1684-b211-410c-bd57-0ff566e99d85" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I coded loop subdivision and ran it on a cube with triangle faces. I noticed this:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;&#xA;I am using doubles to represent my vertex positions, I am not 100% sure these are caused by floating point imprecisions, but since the general shape looks ok I am not sure what else it could be.&#xA;&#xA;Any suggestions on how to find the cause? My linear algebra library is glm and I am coding this in C++.&#xA;&#xA;  [1]: https://i.stack.imgur.com/nGaiv.png&#xA;&#xA;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28736" PostHistoryTypeId="5" PostId="9544" RevisionGUID="dec77a09-cc2e-4ea1-b0f1-bf1fe950b6a7" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="Assume we have a mesh represented as a half edge datastructure.&#xA;&#xA;We want to subdivide faces without introducing unnecessary vertices (i.e the new number of vertices must be exactly V + E where V is the old number of vertices and E is the old number of edges).&#xA;&#xA;This is what a single subdivided triangle looks like:&#xA;[![enter image description here][1]][1]&#xA;&#xA;If I naively try to iterate over every edge and reconnect faces I get the following sequence&#xA;[![enter image description here][2]][2]&#xA;[![enter image description here][3]][3]&#xA;[![enter image description here][4]][4]&#xA;&#xA;Clearly this is wrong.&#xA;&#xA;If instead I iterate over the faces I get the following pattern:&#xA;&#xA;[![enter image description here][5]][5]&#xA;&#xA;This is happening because at every step I am trying to to:&#xA;&#xA; * Focus on only one simplex at a time, &#xA; * Maintain the connectivity information of the mesh in a valid state (every edge has &lt;2 faces, vertices only exist at the end of edges, faces only have 3 Half edges...), like for example, I am avoiding getting into this state:&#xA;&#xA;[![enter image description here][6]][6]&#xA;&#xA;Any suggestions?&#xA;&#xA;  [1]: https://i.stack.imgur.com/MYmhk.png&#xA;  [2]: https://i.stack.imgur.com/Jgn94.png&#xA;  [3]: https://i.stack.imgur.com/D4SZe.png&#xA;  [4]: https://i.stack.imgur.com/04SMi.png&#xA;  [5]: https://i.stack.imgur.com/vWp6b.png&#xA;  [6]: https://i.stack.imgur.com/4SexY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28737" PostHistoryTypeId="5" PostId="9496" RevisionGUID="c13e8170-338a-4468-8ef0-3c061d12aeef" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have a geometric shape (assuming that is a rectangle). I want to rotate it about it geometric center by an angle of 45° and plot the result using matplotlib with an equal aspect ratio, I get something like this:&#xA;&#xA;[![enter image description here][1]][1]&#xA;&#xA;However for some reason, I want to plot the result in a figure with a non-equal aspect, I am getting this result:&#xA;&#xA;[![enter image description here][2]][2]&#xA;&#xA;As you can see, the rotated shape is deformed (skewed). But the original shape seems to be scaled only in the y direction.&#xA;&#xA;I am trying to understand what kind of transformation is occuring to the orange shape from a linear algebra perspective: Is it a shear? a combination of scaling and shear (Affine transformation)? if not what kind of transformation is that?&#xA;&#xA;&#xA;My goal is to identify the type of transformation, then finding it's inverse to get the following result:&#xA;&#xA;[![enter image description here][3]][3]&#xA;&#xA;&#xA;I appreciate any help.&#xA;&#xA;  [1]: https://i.stack.imgur.com/iXe7B.png&#xA;  [2]: https://i.stack.imgur.com/3V3VD.png&#xA;  [3]: https://i.stack.imgur.com/yhn2Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28739" PostHistoryTypeId="5" PostId="9194" RevisionGUID="cb5044e3-8b3c-4f22-a81f-dc36e75d0d36" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I am solving an image segmentation problem. To increase the accuracy of the model, I came across the following preprocessing step-&#xA;&#xA;    &#xA;&#xA;&gt; First, the set of pixels of the exterior border of the ROI is de-&#xA;&gt; termined, i.e., pixels that are outside the ROI and are neighbors&#xA;&gt; (using four-neighborhood) to pixels inside it. Then, each pixel value&#xA;&gt; of this set is replaced with the mean value of its neighbors (this&#xA;&gt; time using eight-neighborhood) inside the ROI. Finally, the ROI is&#xA;&gt; expanded by inclusion of this altered set of pixels. This process is&#xA;&gt; repeated and can be seen as artificially increasing the ROI.&#xA;&#xA;The image after applying the following algorithm is below-&#xA;[![enter image description here][1]][1]&#xA;&#xA;Can anyone please help me how to approach this problem, I am pretty much clue-less how to do it, how to detect the boundary of the image.My image is of the following type-&#xA;[![enter image description here][2]][2]&#xA;&#xA;Any help in solving this kind of problem is highly appreciated.&#xA;&#xA;  [1]: https://i.stack.imgur.com/jgBZe.png&#xA;  [2]: https://i.stack.imgur.com/sbVhg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28740" PostHistoryTypeId="5" PostId="9096" RevisionGUID="d47807ae-1207-4583-a04e-876a9e0aea97" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="These are all good answers, and yet there is another way: (Isn't there always?)&#xA;&#xA;Due to the growing popularity of virtual reality, the folks at OculusVR have developed a trio of &quot;Multiview&quot; extensions called:&#xA;&#xA; 1. **OVR_multiview**,&#xA; 2. **OVR_multiview2**, &amp;&#xA; 3. **OVR_multiview_multisampled_render_to_texture**&#xA;&#xA;These extensions allow multiple views of the same scene to be rendered in a single draw call, eliminating the redundancy of rendering the same scene in the same state from the viewpoint of each eye. Although created for the purpose of VR, the developer is not necessarily limited to merely two views. Rather, this extension allows for as many views as **MAX_VIEWS_OVR** specifies.&#xA;&#xA;&#xA;Before using these extensions, the developer should check for their support in the user's graphics driver by adding the following code:&#xA;&#xA;    const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );&#xA;    char * found_extension = strstr( (const char*)extensions, &quot;GL_OVR_multiview&quot; );&#xA;    if (NULL == found_extension)&#xA;    {&#xA;         exit( EXIT_FAILURE );&#xA;    }&#xA;&#xA;From there, it is a matter of setting up your framebuffer to utilize this feature:&#xA;&#xA;    glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress(&quot;glFramebufferTextureMultisampleMultiviewOVR&quot;));&#xA;    glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);&#xA;&#xA;and likewise in the shader:&#xA;&#xA;    #version 300 es&#xA;    #extension GL_OVR_multiview : enable&#xA;&#xA;    layout(num_views = 2) in;&#xA;    in vec3 vertexPosition;&#xA;    uniform mat4 MVP[2];&#xA;&#xA;    void main(){&#xA;        gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);&#xA;    }&#xA;&#xA;In a CPU-bound application, this extension can *dramatically* reduce rendering time, *especially with more complex scenes*:&#xA;&#xA;[![Relative CPU time between multiview and regular stereo. The smaller the better, with the number of cubes on the x-axis and the relative time on the y-axis.][1]][1]&#xA;&#xA;  [1]: https://i.stack.imgur.com/6nrze.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28741" PostHistoryTypeId="5" PostId="9844" RevisionGUID="67e90ec1-da66-41a9-a6ec-54ebca5094b4" CreationDate="2020-06-18T08:32:12.800" UserId="-1" Comment="Commonmark migration" Text="I have to disagree with @jack11111, this is definitely not a clipping issue. I have two possible explanations which you can easily test and verify.&#xA;&#xA;### Clipping theory&#xA;* The patch looks pretty constant in color, clipping would be sort of a gradient (modulo 255) of full intensity in at least one channel (R/G/B).&#xA;* There is no direct light source to cause a strong specular highlight. According to the ground shading and the Lambert-shaded green balls a point light source is placed above, little bit in front of the camera. It seems to have normal intensity that should not cause any trouble. In fact I see in your code that you apply only basic Lambert `n . l` shading, so no specular highlights possible.&#xA;* There is no indirect source to cause such a peak. The rays reflect to towards ground that is rather dark. The bright spot on the ground is located else where. That is well visible on the red sphere where the error occurs closer than the next green sphere, but the highlight on the ground is even further away.&#xA;* It is a strange coincidence that the secondary color of the patch is exactly the same for both spheres.&#xA;&#xA;### Normals theory&#xA;* Normals seem to be computed correctly elsewhere, all your shading is consistent with nice gradients.&#xA;* You reflections are also correct elsewhere, that will be on problem.&#xA;&#xA;# It's a trap! (almost)&#xA;Looking closely at your image I believe I can explain what is happening there. The rays hitting the suspicious regions at the sphere will reflect towards ground in a direction very similar to the ground normal.&#xA;&#xA;You ground does not seem to be reflective, but if it were: The rays would reflect back in almost the exact opposite direction hitting back the ball and then heading towards the camera. So they would hit the ball twice which could cause its color to gain dominance. You can test this theory by comparing the rendering results with `maxDepth = 1`. If the discontinuity disappears then that is the problem.&#xA;&#xA;# Upside down&#xA;My second explanation is much more likely to be the case. It is also based on the observation that the rays reflected from the suspicious patches hit the ground in a direction pointing almost exactly down. I noticed a bit strange setup of your plane in your code. It has its normal pointing down!?&#xA;```lang-py&#xA;self.normal = Vec3(0,-1,0)&#xA;```&#xA;I am not sure how the Lambert shading of the ground works then (should be then all just ambient in fact), but assuming `Vec(0,1,0)` is your up then the intersection will in fact yield `None`&#xA;```lang-py&#xA;denom = ray.dot(self.normal) #something like 1e-6 in the suspicious area&#xA;if abs(denom) &gt; 0.0001: #evaluates to false&#xA;    #... true branch ignored&#xA;return None #false branch activated, returns no intersection&#xA;```&#xA;Having no intersection means that the hit point is shaded only with a constant color&#xA;&gt; ```lang-py&#xA;&gt; if closest_object == None:&#xA;&gt;    return Vec3(173/255, 216/255, 230/255)&#xA;&gt; ```&#xA;&#xA;So to test this explanation, just change the returned color for this case to black and see if the patch darkens.&#xA;```lang-py&#xA;if closest_object == None:&#xA;    return Vec3(0, 0, 0)&#xA;```&#xA;&#xA;I hope that helps. Please let me know the results.&#xA;&#xA;# Update&#xA;After the author confirmed my second explanation I found the reason in the code. The source of the problem is in the ray-plane intersection method. &#xA;&#xA;**Most important of all the epsilon in the comparison should be omitted, since that is causing the patch to be discontinuous.** As mentioned earlier, the incoming ray direction is almost `Vec3(0,-1,0)`. You have set your plane normal to exactly `Vec3(0,-1,0)` so the dot product yields something very close to `0`.&#xA;&#xA;So the quick fix would be:&#xA;```lang-py&#xA;denom = ray.dot(self.normal)&#xA;if abs(denom) &gt;= 0: #omit the epsilon&#xA;    #...&#xA;```&#xA;&#xA;Your plane normal is inconsistent with how a normal is usually defined. I believe your plane is not supposed to face down. It would be much better and correct to have the plane normal pointing **up** and then testing for a **negative** dot product.&#xA;&#xA;A front-face hit occurs when the face normal and the ray are pointing in opposite directions, i.e. their angle `θ` is smaller than `-π/2` or larger than `π/2`, so `cos(θ) &lt; 0`. Note that `denom` is in fact `cos(θ)`. If `|θ| &lt; π/2`, i.e. `cos(θ) &gt; 0`, then it is a back-face hit. You ignore such hits for now but once you add transparency to your raycaster you will need them as well.&#xA;&#xA;The correct way would be:&#xA;```lang-py&#xA;def __init__(self, color, y=0, specular=-1, reflective=0):&#xA;    # ...&#xA;    self.normal = Vec3(0,1,0) #pointing UP&#xA;&#xA;    def intersect_at_point(self, origin, ray):&#xA;        denom = ray.dot(self.normal) # denom == cos(θ)&#xA;&#xA;        if abs(denom) &lt;= 0: #is negative &lt;=&gt; |θ| &gt; π/2; omit the epsilon&#xA;            diff  = self.center - ray&#xA;            t = diff.dot(self.normal) / denom&#xA;&#xA;            if t &gt; 0: #I suggest to omit the epsilon here as well&#xA;                return t&#xA;        return None" ContentLicense="CC BY-SA 4.0" />
  <row Id="28742" PostHistoryTypeId="2" PostId="9951" RevisionGUID="695b8123-c57c-4468-b4aa-646e00a97846" CreationDate="2020-06-18T08:35:54.090" UserId="13095" Text="&gt; Is there a general rule with regard to using the inverse of the “camera” to world when using a homogeneous transform matrix?&#xD;&#xA;&#xD;&#xA;No, there is no general rule. You should always think about which approach is the best one for your specific use-case.&#xD;&#xA;&#xD;&#xA;&gt;Nothing else is ever done with the local-to-world matrix - other than taking its inverse. So I'm wondering if it would be easier just to define the world-to-local matrix directly? &#xD;&#xA;&#xD;&#xA;Don't forget, that the source you linked is a tutorial. It has a limited scope and avoids confusing the reader with additional information he might not understand at the time of reading. That said, if I have an isolated look at the rendering process, I can't think of a reason why you absolutely need the cam-to-world matrix there because you want to transform everything into camera space before continuing with other transformations (projection, clipping, etc.). Even though it seems to make no sense to transform something out of camera space just to transform it back later, there still might be some reasons to do exactly this. For example, if some renderable object is attached to the camera coordinate system. Using an extra shader or a branch statement just for objects defined in the camera system usually costs you much more performance than two obsolete transformations.&#xD;&#xA;&#xD;&#xA;If we now consider other operations, not just rendering, you might find some useful applications of the camera to world matrix, for example, the movement of a camera that always moves into view direction or orthogonal to it (free camera mode in an FPS). The target point of the movement can be easily determined in camera space. It is just a vector of the movement speeds in each principle direction. Use the camera to world matrix to transform the target point into world space and you have your new location (if no collisions occur).&#xD;&#xA;&#xD;&#xA;Lastly, another reason to take the &quot;inverse-route&quot; might be that it is just easier, less work, or more convenient. All objects, including the camera, usually have a world space coordinate and orientation. The transformation to world space is always the same series of operations. Scale-rotate-translate. Since it so common and frequently used, you probably have an optimized function that does not multiply 3 individual matrices but calculates all the entries of the resulting matrix directly. You can still do the same for the world-to-local transformation, but it is less frequently used and if you only need it for your world-to-camera transformation it might be just easier to calculate the inverse since every linear algebra library you might use should provide this function. If you do this not too frequently each frame, it shouldn't affect performance in any notable way.&#xD;&#xA;&#xD;&#xA;As I said in the beginning, you should always focus on what your program needs. If you have no use for the camera-to-world matrix other than to calculate the world-to-camera matrix, you can definitely skip this and calculate the world-to-camera matrix directly. Just ask yourself, if it is worth it to add some extra lines of code for that." ContentLicense="CC BY-SA 4.0" />
  <row Id="28743" PostHistoryTypeId="2" PostId="9952" RevisionGUID="685ed520-2e01-4845-a4fd-24a756879c16" CreationDate="2020-06-18T12:01:42.163" UserId="228" Text="I can see two ways of doing &quot;smoothing&quot;. The first one is smoothing what's mostly related to the appearance (in your case the normals). The other way is smoothing the geometry it self.&#xD;&#xA;&#xD;&#xA;In the first case you usually update the normals based on the neighbours. Say $\mathcal{M}$ is a mesh, $T$ is a triangle in $T$ and $n(T)$ is the normal at $T$. One dumb way of smoothing it could be simply &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{array}{l}&#xD;&#xA;n(T) \leftarrow \frac{1}{|\mathcal{N}(T)|}\left(n(T) + \sum_{Q \in \mathcal{N}(T)} n(Q) \right) \\&#xD;&#xA;n(T) \leftarrow n(T) / n(T).length()&#xD;&#xA;\end{array}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Here $\mathcal{N}(T)$ represent the list of triangles adjacent to $T$.&#xD;&#xA;The pair of equations as you can see don't really change the vertex count, the same argument could be applied to vertex normals. Essentially you don't delete or add anything you just adjust values.&#xD;&#xA;&#xD;&#xA;The second case is literally smoothing the geometry, which implies moving vertices around so you don't have sudden jumps in curvature. A couple of know examples are [laplacian smoothing][1] and [taubin smoothing][2], both have similar equations to the first case I described.&#xD;&#xA;&#xD;&#xA;If you start removing vertices this is usually called [decimation/simplification][3], if you add vertices is [subdivision][4]. The smoothing in this case is kind of side effect really, i.e. when you render the mesh it might look smoother. But the purpose of decimating or subdividing is usually removing/adding of details (like LOD).&#xD;&#xA;&#xD;&#xA;By the way... the terminology I'm using is standard in Mesh Processing (smoothing, decimation and subdivision are well defined in this context and this leads to the content of my answer).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Laplacian_smoothing&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs468-01-fall/Papers/taubin-smoothing.pdf&#xD;&#xA;  [3]: http://graphics.stanford.edu/courses/cs468-10-fall/LectureSlides/08_Simplification.pdf&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Subdivision_surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="28745" PostHistoryTypeId="5" PostId="9950" RevisionGUID="c3f5f80d-80d4-4a2d-a9de-2d087a792307" CreationDate="2020-06-18T12:23:43.807" UserId="13095" Comment="Put link into corresponding Markdown structure to hide the URL" Text="&#xD;&#xA;&#xD;&#xA;Not sure if this is just specific to [this article](https://www.scratchapixel.com/lessons/3d-basic-rendering/computing-pixel-coordinates-of-3d-point/mathematics-computing-2d-coordinates-of-3d-points) but it says:&#xD;&#xA;&#xD;&#xA;&gt; We learned how to convert points from world to any local coordinate&#xD;&#xA;&gt; system. If we know the local-to-world matrix, we can multiply the&#xD;&#xA;&gt; world coordinate of the point by the inverse of the local-to-world&#xD;&#xA;&gt; matrix (the world-to-local matrix).&#xD;&#xA;&#xD;&#xA;Nothing else is ever done with the local-to-world matrix - other than taking its inverse. So I'm wondering if it would be easier just to define the world-to-local matrix directly? Does taking the inverse make things like &quot;moving&quot; the camera more intuitive?&#xD;&#xA;&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 4.0" />
  <row Id="28746" PostHistoryTypeId="24" PostId="9950" RevisionGUID="c3f5f80d-80d4-4a2d-a9de-2d087a792307" CreationDate="2020-06-18T12:23:43.807" Comment="Proposed by 13095 approved by 13566 edit id of 531" ContentLicense="CC BY-SA 4.0" />
  <row Id="28747" PostHistoryTypeId="5" PostId="9952" RevisionGUID="387350f0-abef-479e-bb09-c4619cc0bf89" CreationDate="2020-06-18T16:07:05.937" UserId="228" Comment="deleted 1 character in body" Text="I can see two ways of doing &quot;smoothing&quot;. The first one is smoothing what's mostly related to the appearance (in your case the normals). The other way is smoothing the geometry itself.&#xD;&#xA;&#xD;&#xA;In the first case you usually update the normals based on the neighbours. Say $\mathcal{M}$ is a mesh, $T$ is a triangle in $T$ and $n(T)$ is the normal at $T$. One dumb way of smoothing it could be simply &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{array}{l}&#xD;&#xA;n(T) \leftarrow \frac{1}{|\mathcal{N}(T)|}\left(n(T) + \sum_{Q \in \mathcal{N}(T)} n(Q) \right) \\&#xD;&#xA;n(T) \leftarrow n(T) / n(T).length()&#xD;&#xA;\end{array}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Here $\mathcal{N}(T)$ represent the list of triangles adjacent to $T$.&#xD;&#xA;The pair of equations as you can see don't really change the vertex count, the same argument could be applied to vertex normals. Essentially you don't delete or add anything you just adjust values.&#xD;&#xA;&#xD;&#xA;The second case is literally smoothing the geometry, which implies moving vertices around so you don't have sudden jumps in curvature. A couple of know examples are [laplacian smoothing][1] and [taubin smoothing][2], both have similar equations to the first case I described.&#xD;&#xA;&#xD;&#xA;If you start removing vertices this is usually called [decimation/simplification][3], if you add vertices is [subdivision][4]. The smoothing in this case is kind of side effect really, i.e. when you render the mesh it might look smoother. But the purpose of decimating or subdividing is usually removing/adding of details (like LOD).&#xD;&#xA;&#xD;&#xA;By the way... the terminology I'm using is standard in Mesh Processing (smoothing, decimation and subdivision are well defined in this context and this leads to the content of my answer).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Laplacian_smoothing&#xD;&#xA;  [2]: https://graphics.stanford.edu/courses/cs468-01-fall/Papers/taubin-smoothing.pdf&#xD;&#xA;  [3]: http://graphics.stanford.edu/courses/cs468-10-fall/LectureSlides/08_Simplification.pdf&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Subdivision_surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="28748" PostHistoryTypeId="2" PostId="9953" RevisionGUID="b9fc7b8b-8f22-4b4f-a837-64a6a2547c13" CreationDate="2020-06-18T19:47:54.537" UserId="3123" Text="I am trying to compile some really simple shaders with DXC but, when creating PSO, I get:&#xD;&#xA;&#xD;&#xA;    D3D12 ERROR: ID3D12Device::CreateVertexShader: Vertex Shader is corrupt or in an unrecognized format. [ STATE_CREATION ERROR #67: CREATEVERTEXSHADER_INVALIDSHADERBYTECODE]&#xD;&#xA;    D3D12 ERROR: ID3D12Device::CreatePixelShader: Pixel Shader is corrupt or in an unrecognized format. [ STATE_CREATION ERROR #93: CREATEPIXELSHADER_INVALIDSHADERBYTECODE]&#xD;&#xA;    The parameter is incorrect.&#xD;&#xA;&#xD;&#xA;The shader I try to compile:&#xD;&#xA;&#xD;&#xA;    struct pixel_data&#xD;&#xA;    {&#xD;&#xA;    	float4 position : SV_POSITION;&#xD;&#xA;    	float2 uv : TEXCOORD0;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    pixel_data vs_main( uint vertexID : SV_VertexID )&#xD;&#xA;    {&#xD;&#xA;    	float2 vertexOffset = float2((vertexID &amp; 2) ? 1.f : -1.f, (vertexID &amp; 1) ? 1.f : -1.f);&#xD;&#xA;    &#xD;&#xA;    	pixel_data output;&#xD;&#xA;    	output.position = float4(vertexOffset, 1.f, 1.f);&#xD;&#xA;    	output.uv = vertexOffset * float2(0.5f, -0.5f) + 0.5f;&#xD;&#xA;    &#xD;&#xA;    	return output;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    float4 ps_main( pixel_data input ) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;    	return float4(input.uv, 1.f, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and code for compiling:&#xD;&#xA;&#xD;&#xA;    struct&#xD;&#xA;    {&#xD;&#xA;    	ShaderObj shaders[MAX_SHADER];&#xD;&#xA;    	uint lastShaderID;&#xD;&#xA;    &#xD;&#xA;    	#ifdef _PC_ &#xD;&#xA;    		IDxcLibrary *dxcLibrary;&#xD;&#xA;    		IDxcCompiler *dxcCompiler;&#xD;&#xA;    		IDxcValidator *dxcValidator;&#xD;&#xA;    	#endif // #ifdef _PC_ &#xD;&#xA;    } shadersObjects;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    #ifdef _PC_ &#xD;&#xA;    	void Shader::Init()&#xD;&#xA;    	{&#xD;&#xA;    		shadersObjects.lastShaderID = 0;&#xD;&#xA;    &#xD;&#xA;    		DX_RESULT( DxcCreateInstance( CLSID_DxcLibrary, IID_PPV_ARGS( &amp;shadersObjects.dxcLibrary ) ) );&#xD;&#xA;    		DX_RESULT( DxcCreateInstance( CLSID_DxcCompiler, IID_PPV_ARGS( &amp;shadersObjects.dxcCompiler ) ) );&#xD;&#xA;    		DX_RESULT( DxcCreateInstance( CLSID_DxcValidator, IID_PPV_ARGS( &amp;shadersObjects.dxcValidator ) ) );&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	inline static IDxcBlob *CompileShader(char const *const fileName, wchar_t const *const entryPoint, wchar_t const *const targetProfile)&#xD;&#xA;    	{&#xD;&#xA;    		uint const SHADER_PATH_LEN = wcslen( shadersPath );&#xD;&#xA;    &#xD;&#xA;    		uint fileNameLength = SHADER_PATH_LEN + strlen( fileName );&#xD;&#xA;    		wchar_t *wFileName = new wchar_t[fileNameLength + 1];&#xD;&#xA;    		memcpy( wFileName, shadersPath, sizeof( wchar_t ) * SHADER_PATH_LEN );&#xD;&#xA;    		Misc::CharToWchar( wFileName + SHADER_PATH_LEN, fileName );&#xD;&#xA;    &#xD;&#xA;    		wchar_t const *compileArguments[] =&#xD;&#xA;    		{			&#xD;&#xA;    			L&quot;/WX&quot;,							// Treat warnings as errors&#xD;&#xA;    			//L&quot;/Zi&quot;,						// Enable debug information&#xD;&#xA;    			//L&quot;/res_may_alias&quot;,			// Assume that UAVs/SRVs may alias,&#xD;&#xA;    &#xD;&#xA;    		};&#xD;&#xA;    &#xD;&#xA;    		uint codePage = CP_UTF8;&#xD;&#xA;    		IDxcBlobEncoding *sourceBlob;&#xD;&#xA;    		DX_RESULT( shadersObjects.dxcLibrary-&gt;CreateBlobFromFile( wFileName, &amp;codePage, &amp;sourceBlob));&#xD;&#xA;    &#xD;&#xA;    		IDxcIncludeHandler *includeHandler;&#xD;&#xA;    		DX_RESULT( shadersObjects.dxcLibrary-&gt;CreateIncludeHandler( &amp;includeHandler ) );&#xD;&#xA;    		IDxcOperationResult *compileResult;&#xD;&#xA;    		DX_RESULT( shadersObjects.dxcCompiler-&gt;Compile(&#xD;&#xA;    			sourceBlob, // pSource&#xD;&#xA;    			wFileName, // pSourceName&#xD;&#xA;    			entryPoint, // pEntryPoint&#xD;&#xA;    			targetProfile, // pTargetProfile&#xD;&#xA;    			compileArguments, 1, // pArguments, argCount&#xD;&#xA;    			nullptr, 0, // pDefines, defineCount&#xD;&#xA;    			includeHandler, // pIncludeHandler&#xD;&#xA;    			&amp;compileResult) // ppResult&#xD;&#xA;    		);&#xD;&#xA;    		includeHandler-&gt;Release();&#xD;&#xA;    &#xD;&#xA;    		HRESULT compileHResult;&#xD;&#xA;    		compileResult-&gt;GetStatus(&amp;compileHResult);&#xD;&#xA;    		if (FAILED(compileHResult))&#xD;&#xA;    		{&#xD;&#xA;    			if (compileResult)&#xD;&#xA;    			{&#xD;&#xA;    				IDxcBlobEncoding *errorsBlob;&#xD;&#xA;    				compileHResult = compileResult-&gt;GetErrorBuffer(&amp;errorsBlob);&#xD;&#xA;    				if (errorsBlob)&#xD;&#xA;    				{&#xD;&#xA;    					if (SUCCEEDED(compileHResult))&#xD;&#xA;    					{&#xD;&#xA;    						DebugPrint(&quot;%ls:%ls\n%s\n&quot;, wFileName, entryPoint, (const char *)errorsBlob-&gt;GetBufferPointer());&#xD;&#xA;    					}&#xD;&#xA;    &#xD;&#xA;    					errorsBlob-&gt;Release();&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				compileResult-&gt;Release();&#xD;&#xA;    				compileResult = nullptr;&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		delete[] wFileName;&#xD;&#xA;    		sourceBlob-&gt;Release();&#xD;&#xA;    		if (compileResult)&#xD;&#xA;    		{&#xD;&#xA;    			IDxcBlob *code;&#xD;&#xA;    			compileResult-&gt;GetResult( &amp;code );&#xD;&#xA;    			compileResult-&gt;Release();&#xD;&#xA;    &#xD;&#xA;    			IDxcOperationResult *validateResult;&#xD;&#xA;    			DX_RESULT( shadersObjects.dxcValidator-&gt;Validate( code, DxcValidatorFlags_InPlaceEdit, &amp;validateResult ) );&#xD;&#xA;    			HRESULT validateHResult;&#xD;&#xA;    			validateResult-&gt;GetStatus( &amp;validateHResult );&#xD;&#xA;    			if ( FAILED( validateHResult ) )&#xD;&#xA;    			{&#xD;&#xA;    				IDxcBlobEncoding *errorsBlob;&#xD;&#xA;    				validateHResult = validateResult-&gt;GetErrorBuffer( &amp;errorsBlob );&#xD;&#xA;    &#xD;&#xA;    				if ( errorsBlob )&#xD;&#xA;    				{&#xD;&#xA;    					if ( SUCCEEDED( validateHResult ) )&#xD;&#xA;    					{&#xD;&#xA;    						DebugPrint( &quot;%ls:%ls\n%s\n&quot;, wFileName, entryPoint, (const char *)errorsBlob-&gt;GetBufferPointer() );&#xD;&#xA;    					}&#xD;&#xA;    &#xD;&#xA;    					errorsBlob-&gt;Release();&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			validateResult-&gt;Release();&#xD;&#xA;    			return code;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return nullptr;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	ShaderObj* Shader::CreateShader(char const* vsFileName, char const* psFileName, ...)&#xD;&#xA;    	{&#xD;&#xA;    		IDxcBlob *vsCode = CompileShader( vsFileName, L&quot;vs_main&quot;, L&quot;vs_6_4&quot;);&#xD;&#xA;    		if ( !vsCode )&#xD;&#xA;    			return nullptr;&#xD;&#xA;    &#xD;&#xA;    		IDxcBlob *psCode = CompileShader( psFileName, L&quot;ps_main&quot;, L&quot;ps_6_4&quot; );&#xD;&#xA;    		if ( !psCode )&#xD;&#xA;    		{&#xD;&#xA;    			vsCode-&gt;Release();&#xD;&#xA;    			return nullptr;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		D3D12_GRAPHICS_PIPELINE_STATE_DESC descPso = {};&#xD;&#xA;    		descPso.pRootSignature = GfxDevice::GetGraphicsRootSignature();&#xD;&#xA;    &#xD;&#xA;    		descPso.VS.pShaderBytecode = vsCode-&gt;GetBufferPointer();&#xD;&#xA;    		descPso.VS.BytecodeLength = vsCode-&gt;GetBufferSize();&#xD;&#xA;    &#xD;&#xA;    		descPso.PS.pShaderBytecode = psCode-&gt;GetBufferPointer();&#xD;&#xA;    		descPso.PS.BytecodeLength = psCode-&gt;GetBufferSize();&#xD;&#xA;    &#xD;&#xA;    		descPso.RasterizerState = RasterizationState::shaded_NoMSAA;&#xD;&#xA;    &#xD;&#xA;    		descPso.DepthStencilState = DepthStencilState::disabled;&#xD;&#xA;    &#xD;&#xA;    		descPso.BlendState.AlphaToCoverageEnable = FALSE;&#xD;&#xA;    		descPso.BlendState.IndependentBlendEnable = FALSE;&#xD;&#xA;    		descPso.BlendState.RenderTarget[0] = BlendState::disabled;&#xD;&#xA;    &#xD;&#xA;    		descPso.InputLayout.NumElements = 0;&#xD;&#xA;    		descPso.InputLayout.pInputElementDescs = nullptr;&#xD;&#xA;    		descPso.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;&#xD;&#xA;    &#xD;&#xA;    		descPso.NumRenderTargets = 1;&#xD;&#xA;    		descPso.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;    		descPso.DSVFormat = DXGI_FORMAT_UNKNOWN;&#xD;&#xA;    &#xD;&#xA;    		descPso.SampleDesc.Count = 1;&#xD;&#xA;    		descPso.SampleMask = UINT_MAX;&#xD;&#xA;    &#xD;&#xA;    		ID3D12PipelineState *pso;&#xD;&#xA;    		HRESULT posCreateHresult = GfxDevice::GetGfxDevice()-&gt;CreateGraphicsPipelineState( &amp;descPso, IID_PPV_ARGS( &amp;pso ) );&#xD;&#xA;    		vsCode-&gt;Release();&#xD;&#xA;    		psCode-&gt;Release();&#xD;&#xA;    &#xD;&#xA;    		if ( FAILED( posCreateHresult ) )&#xD;&#xA;    		{&#xD;&#xA;    			DX_RESULT( posCreateHresult );&#xD;&#xA;    			return nullptr;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		ShaderObj *shader = &amp;shadersObjects.shaders[shadersObjects.lastShaderID];&#xD;&#xA;    		++shadersObjects.lastShaderID;&#xD;&#xA;    		shader-&gt;pso = pso;&#xD;&#xA;    &#xD;&#xA;    		return shader;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	void Shader::Release()&#xD;&#xA;    	{&#xD;&#xA;    		shadersObjects.dxcLibrary-&gt;Release();&#xD;&#xA;    		shadersObjects.dxcCompiler-&gt;Release();&#xD;&#xA;    		shadersObjects.dxcValidator-&gt;Release();&#xD;&#xA;    &#xD;&#xA;    		for (uint i = 0; i &lt; shadersObjects.lastShaderID; ++i)&#xD;&#xA;    		{&#xD;&#xA;    			shadersObjects.shaders[i].pso-&gt;Release();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    #endif // #ifdef _PC_ &#xD;&#xA;&#xD;&#xA;I have tried using ```CreateBlobWithEncodingFromPinned``` with source loaded from file and from char* array (in case there was some strange encoding in the file).&#xD;&#xA;&#xD;&#xA;Everything is ok until the PSO, shaders get compiled and validated.&#xD;&#xA;&#xD;&#xA;I tried to change some params in PSO description but it seems like Create*Shader are first in PSO creation.&#xD;&#xA;&#xD;&#xA;I have dev mode enabled in windows.&#xD;&#xA;&#xD;&#xA;Any idea?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28749" PostHistoryTypeId="1" PostId="9953" RevisionGUID="b9fc7b8b-8f22-4b4f-a837-64a6a2547c13" CreationDate="2020-06-18T19:47:54.537" UserId="3123" Text="DXC error when compiling PSO" ContentLicense="CC BY-SA 4.0" />
  <row Id="28750" PostHistoryTypeId="3" PostId="9953" RevisionGUID="b9fc7b8b-8f22-4b4f-a837-64a6a2547c13" CreationDate="2020-06-18T19:47:54.537" UserId="3123" Text="|shader|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28751" PostHistoryTypeId="2" PostId="9954" RevisionGUID="e7b4e24e-eb2e-4bf2-9276-bf1330b90d18" CreationDate="2020-06-19T09:50:48.827" UserId="11058" Text="With perspective projection we can unproject screen space coordinates of the cursor to the near and far plane of the frustum and calculate the direction of the ray through the cursor. &#xD;&#xA;&#xD;&#xA;            Vector4 cScreen0 = Vector4(cursorNormX, cursorNormY, -1, 1);&#xD;&#xA;			Vector4 cView0 = Inverse(projection)*cScreen0;&#xD;&#xA;			cView0 = cView0*(1/cView0.w);&#xD;&#xA;			Vector4 cWorld0 = Inverse(view) * cView0;&#xD;&#xA;&#xD;&#xA;			Vector4 cScreen1 = Vector4(cursorNormX, cursorNormY, 1, 1);&#xD;&#xA;			Vector4 cView1 = Inverse(projection)*cScreen1;&#xD;&#xA;			cView1 = cView1*(1/cView1.w);&#xD;&#xA;			Vector4 cWorld1 = Inverse(view) * cView1;&#xD;&#xA;&#xD;&#xA;			cursorDir = normalize(cWorld1.xyz()-cWorld0.xyz());&#xD;&#xA;&#xD;&#xA;Now however with orthographic projection the far and near plane are of the same size, so we can't really calculate the direction of the cursor (I haven't had much sleep so I hope this makes sense).&#xD;&#xA;&#xD;&#xA;So instead I calculated the cursor position by unprojecting the cursor with zeroed out z value. We can calculate the x and y coordinate and set the z coordinate as we like.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            Vector4 cScreen = vec4(cursorNormX, cursorNormY, 0, 0);&#xD;&#xA;			Vector4 cView = Inverse(projection)*cScreen;&#xD;&#xA;			cView = vec4(cView.x, cView.y, 0, 0);&#xD;&#xA;			Vector4 cWorld = Inverse(View) * cView;&#xD;&#xA;			cWorld = vec4(cWorld.x, cWorld.y, 0, 0);&#xD;&#xA;&#xD;&#xA;			cursorPos = cWorld.xyz();&#xD;&#xA;&#xD;&#xA;However I'm not getting the correct results from the projection. What am I missing?&#xD;&#xA;&#xD;&#xA;The purpose of this is to cast rays in the direction of the cursor." ContentLicense="CC BY-SA 4.0" />
  <row Id="28752" PostHistoryTypeId="1" PostId="9954" RevisionGUID="e7b4e24e-eb2e-4bf2-9276-bf1330b90d18" CreationDate="2020-06-19T09:50:48.827" UserId="11058" Text="How to unproject cursor with orthographic projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="28753" PostHistoryTypeId="3" PostId="9954" RevisionGUID="e7b4e24e-eb2e-4bf2-9276-bf1330b90d18" CreationDate="2020-06-19T09:50:48.827" UserId="11058" Text="|opengl|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28754" PostHistoryTypeId="5" PostId="9954" RevisionGUID="202b0ca0-bbd3-4cbb-b1a2-89b9090b4851" CreationDate="2020-06-19T09:57:52.587" UserId="11058" Comment="added 58 characters in body" Text="With perspective projection we can unproject screen space coordinates of the cursor to the near and far plane of the frustum and calculate the direction of the ray through the cursor. &#xD;&#xA;&#xD;&#xA;            Vector4 cScreen0 = Vector4(cursorNormX, cursorNormY, -1, 1);&#xD;&#xA;			Vector4 cView0 = Inverse(projection)*cScreen0;&#xD;&#xA;			cView0 = cView0*(1/cView0.w);&#xD;&#xA;			Vector4 cWorld0 = Inverse(view) * cView0;&#xD;&#xA;&#xD;&#xA;			Vector4 cScreen1 = Vector4(cursorNormX, cursorNormY, 1, 1);&#xD;&#xA;			Vector4 cView1 = Inverse(projection)*cScreen1;&#xD;&#xA;			cView1 = cView1*(1/cView1.w);&#xD;&#xA;			Vector4 cWorld1 = Inverse(view) * cView1;&#xD;&#xA;&#xD;&#xA;			Vector3 cursorDir = normalize(cWorld1.xyz()-cWorld0.xyz());&#xD;&#xA;&#xD;&#xA;Now however with orthographic projection the far and near plane are of the same size, so we can't calculate the direction of the cursor this way. The direction is going to be equal the world's z axis. (I haven't had much sleep so I hope this makes sense).&#xD;&#xA;&#xD;&#xA;So instead I calculated the cursor position by unprojecting the cursor with zeroed out z value. We can calculate the x and y coordinate and set the z coordinate as we like.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            Vector4 cScreen = Vector4(cursorNormX, cursorNormY, 0, 0);&#xD;&#xA;			Vector4 cView = Inverse(projection)*cScreen;&#xD;&#xA;			cView = Vector4(cView.x, cView.y, 0, 0);&#xD;&#xA;			Vector4 cWorld = Inverse(View) * cView;&#xD;&#xA;			cWorld = Vector4(cWorld.x, cWorld.y, 0, 0);&#xD;&#xA;&#xD;&#xA;			Vector3 cursorPos = cWorld.xyz();&#xD;&#xA;&#xD;&#xA;However I'm not getting the correct results from the projection. What am I missing?&#xD;&#xA;&#xD;&#xA;The purpose of this is to be able to cast rays in the direction of the cursor." ContentLicense="CC BY-SA 4.0" />
  <row Id="28755" PostHistoryTypeId="6" PostId="9954" RevisionGUID="202b0ca0-bbd3-4cbb-b1a2-89b9090b4851" CreationDate="2020-06-19T09:57:52.587" UserId="11058" Comment="added 58 characters in body" Text="|opengl|c++|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28756" PostHistoryTypeId="5" PostId="9954" RevisionGUID="12162b9b-fa5c-4479-882e-4fe69b47a72e" CreationDate="2020-06-19T10:03:21.767" UserId="11058" Comment="added 6 characters in body" Text="With perspective projection we can unproject screen space coordinates of the cursor to the near and far plane of the frustum and calculate the direction of the ray through the cursor. &#xD;&#xA;&#xD;&#xA;            Vector4 cScreen0 = Vector4(cursorNormX, cursorNormY, -1, 1);&#xD;&#xA;			Vector4 cView0 = Inverse(projection)*cScreen0;&#xD;&#xA;			cView0 = cView0*(1/cView0.w);&#xD;&#xA;			Vector4 cWorld0 = Inverse(view) * cView0;&#xD;&#xA;&#xD;&#xA;			Vector4 cScreen1 = Vector4(cursorNormX, cursorNormY, 1, 1);&#xD;&#xA;			Vector4 cView1 = Inverse(projection)*cScreen1;&#xD;&#xA;			cView1 = cView1*(1/cView1.w);&#xD;&#xA;			Vector4 cWorld1 = Inverse(view) * cView1;&#xD;&#xA;&#xD;&#xA;			Vector3 cursorDir = normalize(cWorld1.xyz()-cWorld0.xyz());&#xD;&#xA;&#xD;&#xA;Now however with orthographic projection the far and near plane are of the same size, so we can't calculate the direction of the cursor this way. The direction is going to be equal the world's z axis. (I haven't had much sleep so I hope this makes sense).&#xD;&#xA;&#xD;&#xA;So instead I calculated the cursor position by unprojecting the cursor with zeroed out z value. We can calculate the x and y coordinate and set the z coordinate later as we like.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            Vector4 cScreen = Vector4(cursorNormX, cursorNormY, 0, 0);&#xD;&#xA;			Vector4 cView = Inverse(projection)*cScreen;&#xD;&#xA;			cView = Vector4(cView.x, cView.y, 0, 0);&#xD;&#xA;			Vector4 cWorld = Inverse(View) * cView;&#xD;&#xA;			cWorld = Vector4(cWorld.x, cWorld.y, 0, 0);&#xD;&#xA;&#xD;&#xA;			Vector3 cursorPos = cWorld.xyz();&#xD;&#xA;&#xD;&#xA;However I'm not getting the correct results from the projection. What am I missing?&#xD;&#xA;&#xD;&#xA;The purpose of this is to be able to cast rays in the direction of the cursor." ContentLicense="CC BY-SA 4.0" />
  <row Id="28757" PostHistoryTypeId="2" PostId="9955" RevisionGUID="de9c0fec-0da3-4bab-81fe-8e3d692f28b9" CreationDate="2020-06-19T11:38:22.677" UserId="13574" Text="Have you considered using [SDL 2][1]?&#xD;&#xA;&#xD;&#xA;My use-case is basically identical to yours, and I've found this approach to work really well. They have a really nice C (and C++) API for drawing framebuffers to a window. It's also platform-agnostic, so you can share your implementation fairly easily between macOS, Linux and Windows.&#xD;&#xA;If you want to see an example, you can go check out [this][2] module here on GitHub. I do warn you though, while this implementation *works*, and I can easily run it at 60-120FPS, it likely does use more CPU than a fully optimised implementation.&#xD;&#xA;Specifically observe the `initDisplay()` and `drawWindow()` functions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.libsdl.org&#xD;&#xA;  [2]: https://github.com/vkoskiv/c-ray/blob/master/src/utils/ui.c" ContentLicense="CC BY-SA 4.0" />
  <row Id="28758" PostHistoryTypeId="2" PostId="9956" RevisionGUID="09e738db-e5c1-4a7f-b520-15b62dc39459" CreationDate="2020-06-19T13:13:36.067" UserId="523" Text="**I have written a deferred renderer that can use either a fragment shader or a compute shader to execute the shading pass.  Unfortunately, the compute shader implementation runs slower.  I'm trying to understand why.**&#xD;&#xA;&#xD;&#xA;I believe I understand the proximate cause: memory locality when accessing textures.  Somehow the fragment shader's accesses are significantly more coherent than the compute shader's.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To demonstrate that, I removed everything except the shadowmapping code and then changed that to sample randomly.  Something like (GLSL pseudocode):&#xD;&#xA;```cpp&#xD;&#xA;uniform sampler2D tex_shadowmap;&#xD;&#xA;&#xD;&#xA;uniform float param;&#xD;&#xA;&#xD;&#xA;#ifdef COMPUTE_SHADER&#xD;&#xA;layout(local_size_x=8, local_size_y=4, local_size_z=1) in;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;struct RNG { uint64_t state; uint64_t inc; } _rng;&#xD;&#xA;void rand_seed(ivec2 coord) { /*seed `_rng` with hash of `coord`*/ }&#xD;&#xA;float rand_float() { /*return random float in [0,1]*/ }&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;	rand_seed(/*pixel coordinate*/);&#xD;&#xA;&#xD;&#xA;	vec4 light_coord = /*vertex in scaled/biased light's NDC*/;&#xD;&#xA;	vec3 shadowmap_test_pos = light_coord.xyz / light_coord.w;&#xD;&#xA;&#xD;&#xA;	float rand_shadow = 0.0;&#xD;&#xA;	for (int i=0;i&lt;200;++i) {&#xD;&#xA;		vec2 coord = fract(mix( shadowmap_test_pos.xy, vec2(rand_float(),rand_float()), param ));&#xD;&#xA;		float tap = textureLod(tex_shadowmap,coord,0.0).r;&#xD;&#xA;		rand_shadow += clamp(shadowmap_test_pos.z,0.0,1.0)&lt;=tap+0.00001 ? 1.0 : 0.0;&#xD;&#xA;	}&#xD;&#xA;	vec4 color = vec4(vec3(rand_shadow)/200.0,1.0);&#xD;&#xA;&#xD;&#xA;	/*[set `color` into output]*/&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When `param` is set to `0`, the shadowmap is sampled at `shadowmap_test_pos`, and we get correct hard shadows for the scene.  In this case, the shadowmap texture lookup locations are somewhat correlated to the pixel coordinate, so we expect good performance.  When `param` is set to `1`, we get a completely random texture coordinate `vec2(rand_float(),rand_float())`, and so the texture lookups are not at all correlated to the pixel coordinate, and we expect bad performance.&#xD;&#xA;&#xD;&#xA;Something very interesting happens when we try some more values for `param` and measure the latency of the shading pass with a [timer query](http://www.lighthouse3d.com/tutorials/opengl-timer-query/):&#xD;&#xA;&#xD;&#xA;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[![plot of `param` vs. latency][1]][1]&#xD;&#xA;&#xD;&#xA;As one can see, when working with completely random coordinates (`param`=1, right side), the fragment shader and compute shader have the same performance. However, as the coordinates become less random, whatever the fragment shader is doing that makes it more coherent starts to come into play. When the coordinates are deterministic and correlated to screen position (`param`≈0, left side), the fragment shader wins by a factor of 2 (note: the `param`=0 case was omitted since the GLSL compiler optimizes out the loop).&#xD;&#xA;&#xD;&#xA;Both the sources and compiled codes of these shaders are essentially the same.   Apart from some setup and writing the data out (which one expects to vary a bit), the shaders are identical.  You can see a diff I made of the PTX disassemblies [here](http://www.mergely.com/oUOuCk97/).  Most of the loop body is taken up with the inlined RNG, but the salient point is that _it's the same loop_.&#xD;&#xA;&#xD;&#xA;Note: tested hardware was NVIDIA GTX 1080 with current (446.14) driver.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;My question is basically: what can I do about this?  I'm working in 8⨯4 tiles in the compute shader, but who knows what the fragment shader is doing.  Yet, I would not expect whatever magical secret shading order the fragment shader does to be *so much* better that you would get a &gt;2⨯ performance difference when you're running the same actual code.  (FWIW I've tried different group sizes, to no real change in the above behavior.)&#xD;&#xA;&#xD;&#xA;There are a few [general discussions](https://computergraphics.stackexchange.com/questions/54/when-is-a-compute-shader-more-efficient-than-a-pixel-shader-for-image-filtering) about how the different shaders work, but I haven't found anything that can explain this.  And, while in the past driver issues have caused weird behavior, compute shaders have now been in core GL for almost 8 years, and using them for deferred shading is an obvious, arguably common, use-case that I would expect to work well.&#xD;&#xA;&#xD;&#xA;What am I missing here?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uqvTM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28759" PostHistoryTypeId="1" PostId="9956" RevisionGUID="09e738db-e5c1-4a7f-b520-15b62dc39459" CreationDate="2020-06-19T13:13:36.067" UserId="523" Text="Performance of Compute Shaders vs. Fragment Shaders for Deferred Rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="28760" PostHistoryTypeId="3" PostId="9956" RevisionGUID="09e738db-e5c1-4a7f-b520-15b62dc39459" CreationDate="2020-06-19T13:13:36.067" UserId="523" Text="|performance|compute-shader|fragment-shader|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28761" PostHistoryTypeId="5" PostId="9956" RevisionGUID="2d97e5c4-05dd-4c07-9ec2-25ae14be1b14" CreationDate="2020-06-19T13:43:31.420" UserId="523" Comment="added 189 characters in body" Text="**I have written a deferred renderer that can use either a fragment shader or a compute shader to execute the shading pass.  Unfortunately, the compute shader implementation runs slower.  I'm trying to understand why.**&#xD;&#xA;&#xD;&#xA;I believe I understand the proximate cause: memory locality when accessing textures.  Somehow the fragment shader's accesses are significantly more coherent than the compute shader's.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;To demonstrate that, I removed everything except the shadowmapping code and then changed that to sample randomly.  Something like (GLSL pseudocode):&#xD;&#xA;```cpp&#xD;&#xA;uniform sampler2D tex_shadowmap;&#xD;&#xA;&#xD;&#xA;uniform float param;&#xD;&#xA;&#xD;&#xA;#ifdef COMPUTE_SHADER&#xD;&#xA;layout(local_size_x=8, local_size_y=4, local_size_z=1) in;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;struct RNG { uint64_t state; uint64_t inc; } _rng;&#xD;&#xA;void rand_seed(ivec2 coord) { /*seed `_rng` with hash of `coord`*/ }&#xD;&#xA;float rand_float() { /*return random float in [0,1]*/ }&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;	rand_seed(/*pixel coordinate*/);&#xD;&#xA;&#xD;&#xA;	vec4 light_coord = /*vertex in scaled/biased light's NDC*/;&#xD;&#xA;	vec3 shadowmap_test_pos = light_coord.xyz / light_coord.w;&#xD;&#xA;&#xD;&#xA;	float rand_shadow = 0.0;&#xD;&#xA;	for (int i=0;i&lt;200;++i) {&#xD;&#xA;		vec2 coord = fract(mix( shadowmap_test_pos.xy, vec2(rand_float(),rand_float()), param ));&#xD;&#xA;		float tap = textureLod(tex_shadowmap,coord,0.0).r;&#xD;&#xA;		rand_shadow += clamp(shadowmap_test_pos.z,0.0,1.0)&lt;=tap+0.00001 ? 1.0 : 0.0;&#xD;&#xA;	}&#xD;&#xA;	vec4 color = vec4(vec3(rand_shadow)/200.0,1.0);&#xD;&#xA;&#xD;&#xA;	/*[set `color` into output]*/&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When `param` is set to `0`, the shadowmap is sampled at `shadowmap_test_pos`, and we get correct hard shadows for the scene.  In this case, the shadowmap texture lookup locations are somewhat correlated to the pixel coordinate, so we expect good performance.  When `param` is set to `1`, we get a completely random texture coordinate `vec2(rand_float(),rand_float())`, and so the texture lookups are not at all correlated to the pixel coordinate, and we expect bad performance.&#xD;&#xA;&#xD;&#xA;Something very interesting happens when we try some more values for `param` and measure the latency of the shading pass with a [timer query](http://www.lighthouse3d.com/tutorials/opengl-timer-query/):&#xD;&#xA;&#xD;&#xA;[![plot of `param` vs. latency][1]][1]&#xD;&#xA;&#xD;&#xA;As one can see, when working with completely random coordinates (`param`=1, right side), the fragment shader and compute shader have the same performance. However, as the coordinates become less random, whatever the fragment shader is doing that makes it more coherent starts to come into play. When the coordinates are deterministic and correlated to screen position (`param`≈0, left side), the fragment shader wins by a factor of 2 (note: the `param`=0 case was omitted since the GLSL compiler optimizes out the loop).&#xD;&#xA;&#xD;&#xA;**What's especially weird is that the fragment shader being faster seems to depend on the texture sample coordinate being correlated to the pixel coordinate.**  For example, if instead of `shadowmap_test_pos.xy` I use `vec2(0.5)` as the deterministic coordinate, then the effect disappears, and the two shaders have the same performance for any `param`.&#xD;&#xA;&#xD;&#xA;Both the sources and compiled codes of these shaders are essentially the same.   Apart from some setup and writing the data out (which one expects to vary a bit), the shaders are identical.  You can see a diff I made of the PTX disassemblies [here](http://www.mergely.com/oUOuCk97/).  Most of the loop body is taken up with the inlined RNG, but the salient point is that _it's the same loop_.&#xD;&#xA;&#xD;&#xA;Note: tested hardware was NVIDIA GTX 1080 with current (446.14) driver.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;My question is basically: what can I do about this?  I'm working in 8⨯4 tiles in the compute shader, but who knows what the fragment shader is doing.  Yet, I would not expect whatever magical secret shading order the fragment shader does to be *so much* better that you would get a &gt;2⨯ performance difference when you're running the same actual code.  (FWIW I've tried different group sizes, to no real change in the above behavior.)&#xD;&#xA;&#xD;&#xA;There are a few [general discussions](https://computergraphics.stackexchange.com/questions/54/when-is-a-compute-shader-more-efficient-than-a-pixel-shader-for-image-filtering) about how the different shaders work, but I haven't found anything that can explain this.  And, while in the past driver issues have caused weird behavior, compute shaders have now been in core GL for almost 8 years, and using them for deferred shading is an obvious, arguably common, use-case that I would expect to work well.&#xD;&#xA;&#xD;&#xA;What am I missing here?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uqvTM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28762" PostHistoryTypeId="2" PostId="9957" RevisionGUID="d0f1c98d-809e-4c16-ba3e-34e40d6ab251" CreationDate="2020-06-19T17:25:26.657" UserId="13575" Text="I am more or less a complete novice in the field of 3D modeling. I understand the basics of a polygon mesh and a texture; however, it was always my understanding that 3D models were, effectively, &quot;hollow&quot; inside the mesh, in the same way that a plastic skeleton Halloween decoration is hollow. It possesses a surface, but no internal density. This understanding has always worked well for me, as I primarily work with photogrammetry-created 3D models, for which this is undoubtedly true. &#xD;&#xA;&#xD;&#xA;In my latest project, however, I am being asked to work with 3D models created using CT scan data and Slicer. Unlike photogrammetry images, CT scans *do* care about internal density and structure. I know Slicer can be used to create 3D models from CT scan images. What I'm uncertain about, however, is whether Slicer creates truly &quot;solid&quot; models from this data -- models which have internal density rather than simply a mesh &quot;skin&quot;, where the &quot;inside&quot; of the model is programmatically distinct from the &quot;outside&quot; -- or whether it simply create a multilayered but still fundamentally hollow mesh (or series of meshes) based on boundaries between areas of different densities. &#xD;&#xA;&#xD;&#xA;Is this a meaningful distinction? Am I fundamentally misunderstanding how the surface/internal geometry of 3D models works? Any advice is welcome. &#xD;&#xA;&#xD;&#xA;(I took my best guess as to where to ask this question -- if this is outside the purview of this site, please let me know! If you know another place where I could go asking for answers, I would also appreciate that information. Thank you so much!!!)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28763" PostHistoryTypeId="1" PostId="9957" RevisionGUID="d0f1c98d-809e-4c16-ba3e-34e40d6ab251" CreationDate="2020-06-19T17:25:26.657" UserId="13575" Text="Are some 3D objects &quot;solid&quot;? Do they have internal density? If so, when, and in which file formats?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28764" PostHistoryTypeId="3" PostId="9957" RevisionGUID="d0f1c98d-809e-4c16-ba3e-34e40d6ab251" CreationDate="2020-06-19T17:25:26.657" UserId="13575" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28765" PostHistoryTypeId="2" PostId="9958" RevisionGUID="456cb177-613d-44cf-8cac-5371385d988c" CreationDate="2020-06-19T20:08:33.160" UserId="506" Text="Assuming what you’re referring to is [this Slicer](https://slicer.org) and the models are the ones produced by its [Model Maker](https://www.slicer.org/wiki/Documentation/Nightly/Modules/ModelMaker) module: it looks like it’s creating hollow, surface-only models.&#xD;&#xA;&#xD;&#xA;![screenshot from the Model Maker module in Slicer](https://www.slicer.org/w/img_auth.php/3/36/Slicer4-ModelMaker-Output.jpeg)&#xD;&#xA;&#xD;&#xA;Specifically, judging by the crunchiness of the mesh shown in the top right of this screenshot, it looks like it’s using [marching cubes](https://en.wikipedia.org/wiki/Marching_cubes) to create a mesh from the [isosurfaces](https://en.wikipedia.org/wiki/Isosurface) at given density thresholds in the volume.&#xD;&#xA;&#xD;&#xA;Most 3D model formats—especially the ones used for real-time rendering—are surface-only; as graphics hardware gets more powerful, though, there’s been wider use of [volume rendering](https://en.wikipedia.org/wiki/Volume_rendering), often via [raymarching](https://en.wikipedia.org/wiki/Volume_ray_casting), to render volume data directly rather than having to go through the intermediate meshing step. One common format for volume data is [OpenVDB](https://www.openvdb.org/); it’s also possible to embed such data in [Alembic](http://www.alembic.io) files." ContentLicense="CC BY-SA 4.0" />
  <row Id="28766" PostHistoryTypeId="2" PostId="9959" RevisionGUID="66f7cee5-e433-48eb-809e-e70156b99205" CreationDate="2020-06-19T23:32:56.857" UserId="48" Text="This can be caused by the compiler creating unsigned bytecode. For the compiler to sign the bytecode, you have to have a copy of dxil.dll in the same folder as the dxcompiler.dll at runtime. See [Using the GitHub dxcompiler.dll](https://docs.microsoft.com/en-us/archive/blogs/marcelolr/using-the-github-dxcompiler-dll) for some more info. The dxil.dll is available in the [official DXC releases](https://github.com/microsoft/DirectXShaderCompiler/releases)." ContentLicense="CC BY-SA 4.0" />
  <row Id="28770" PostHistoryTypeId="52" PostId="9957" RevisionGUID="6d9fd5e2-48a5-444b-bbee-a0040146d4c4" CreationDate="2020-06-20T01:27:27.643" />
  <row Id="28771" PostHistoryTypeId="5" PostId="8985" RevisionGUID="3749b739-03b9-4ab0-a8b1-1436ee3f0c67" CreationDate="2020-06-20T13:10:56.007" UserId="9500" Comment="mentioned the original rpi can also do vulkan, somehow" Text="So, I'll start by saying I'm not a driver developer, but I have read many comments and docs in this regard. &#xD;&#xA;&#xD;&#xA;First of all, we can see how Khronos's own [slides][1] on presentation day were mentioning some rather vague &quot;any OpenGL ES 3.1 GPU&quot; (or desktop 4.X). This means [something][2] added around that mark would be the secret to it. Compute shaders are definitively [at least one of] the things, being confirmed [here][3], by an [Intel developer][4], and in [the spec][5] with no possible unsupported value for `MaxComputeWorkGroupSize` and this likely smoking gun: &#xD;&#xA;&gt; If an implementation exposes any queue family that supports graphics&#xD;&#xA;&gt; operations, at least one queue family of at least one physical device&#xD;&#xA;&gt; exposed by the implementation **must** support both graphics and&#xD;&#xA;&gt; compute operations.&#xD;&#xA;&#xD;&#xA;In addition to that though, it could *also* be there are other mandatory capabilities (such as indirect draws or load&amp;store, mentioned in the comments above too). But I have some slight difficulty interpreting the document. With the exception of [robustBufferAccess][6], it seems like just about anything else big you could imagine is optional (from anisotropic filter, to geometry and tessellation shaders, to any special number format other than good old float32)&#xD;&#xA;&#xD;&#xA;This being the most hypothetically simple case then, doesn't mean it's all fine and dandy. Not having [virtual memory][7] will make your life a hell for example, and lack of other [architectural features][8] may basically nullify whatever theoretical advantage in speed the API has. &#xD;&#xA;&#xD;&#xA;These links should also answer your wonders about ATi cards. Likely same story for NVidia then (aside of perhaps some microbenchmarks, I'm not sure how much *really* workable [Fermi's][9] 2-years-delayed bare-bones DX12 support eventually is). As for Intel, I don't know what you are talking about, Gen8 is supported since [Day1][10] and in fact even [Gen7][11] *shakily* works now.&#xD;&#xA;&#xD;&#xA;Going even further back, I guess if any the question becomes &quot;what's so special about compute shaders again&quot;. &#xD;&#xA;&#xD;&#xA;And, well, the thing isn't probably the very specific [feature][12] itself (because it's [not that][13] you couldn't already do some sort of general purpose calculation even before the unified shader model), but more like the whole general GPU architecture needed to support it. Check [this][14] for some backstory. &#xD;&#xA;&#xD;&#xA;Before DX11 raised [the bar][15] for example, just think that you [couldn't][16] even run more than a single &quot;task&quot; on a Tesla GPU, without having to call a context switch (with comparable limitations also likely existing for TeraScale 1 and Gen6). And may God save us from when pixel and vertex units were separated hardware. &#xD;&#xA;&#xD;&#xA;fun fact: it turns out that if you are a low-end [kind-of-modern][17] mobile gpu (rather than an old desktop card from a time when certain concepts hadn't even been invented yet), engineers can cut you down so much that even if you just sport D3D 9_3 feature level that's still potentially [enough][18] to support Vulkan.&#xD;&#xA;&#xD;&#xA;EDIT: for such somewhat twisted reasons, it can also [happen][19] that while you are just GLES 2.0 compliant (and compute shaders themselves aren't supported atm, even though the architecture would be capable) a restricted version of Vulkan could also be possible. It doesn't give you everything, but it can still lead to benefits over just &quot;old apis&quot;. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/assets/uploads/developers/library/overview/Vk_201602_Overview_Feb16.pdf#page=13&#xD;&#xA;  [2]: https://www.anandtech.com/show/7867/khronos-announces-opengl-es-31&#xD;&#xA;  [3]: https://pcper.com/2015/03/gdc-15-what-is-vulkan-glnext-spir-v-and-opencl-2-1/&#xD;&#xA;  [4]: https://youtu.be/2ryvYS47V0E?t=3176&#xD;&#xA;  [5]: https://www.khronos.org/registry/vulkan/specs/1.1/pdf/vkspec.pdf&#xD;&#xA;  [6]: https://www.khronos.org/registry/vulkan/specs/1.0/html/chap30.html#features-requirements&#xD;&#xA;  [7]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/open-source-amd-linux/1004192-r600-gallium3d-now-effectively-at-opengl-4-4-a-nudge-away-from-gl-4-5/page2#post1004523&#xD;&#xA;  [8]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/vulkan/845690-amd-s-vulkan-driver-will-only-work-with-the-amdgpu-kernel-driver/page3#post845731&#xD;&#xA;  [9]: https://techreport.com/news/32191/nvidia-finally-lets-fermi-gpu-owners-enjoy-directx-12/&#xD;&#xA;  [10]: https://01.org/linuxgraphics/blogs/jekstrand/2016/open-source-vulkan-drivers-intel-hardware&#xD;&#xA;  [11]: https://stackoverflow.com/questions/41497142/can-i-install-a-vulkan-driver-on-my-3rd-gen-intel-ivy-bridge-integrated-gpu-on-u&#xD;&#xA;  [12]: https://www.anandtech.com/show/2716/5&#xD;&#xA;  [13]: https://en.wikipedia.org/wiki/BrookGPU&#xD;&#xA;  [14]: https://www.gamedev.net/forums/topic/666419-what-are-your-opinions-on-dx12vulkanmantle/5215019/&#xD;&#xA;  [15]: https://stackoverflow.com/questions/3332782/can-directcompute-really-be-used-on-a-dx10-1-gpu&#xD;&#xA;  [16]: https://www.anandtech.com/show/2977/nvidia-s-geforce-gtx-480-and-gtx-470-6-months-late-was-it-worth-the-wait-/3&#xD;&#xA;  [17]: https://www.anandtech.com/show/8649/arm-announces-mali-800-series-gpus-t860-t830-t820&#xD;&#xA;  [18]: https://developer.arm.com/solutions/graphics/resources/faqs#vulkan_which&#xD;&#xA;  [19]: https://github.com/Yours3lf/rpi-vk-driver/issues/1" ContentLicense="CC BY-SA 4.0" />
  <row Id="28772" PostHistoryTypeId="2" PostId="9960" RevisionGUID="1d071439-7255-4951-93ef-6dba7556f1b9" CreationDate="2020-06-21T13:45:11.277" UserId="13095" Text="I am still not 100% sure, if I understood your question, because of this sentence:&#xD;&#xA;&#xD;&#xA;&gt; Now however with orthographic projection the far and near plane are of the same size, so we can't calculate the direction of the cursor this way. The direction is going to be equal the world's z axis. (I haven't had much sleep so I hope this makes sense).&#xD;&#xA;&#xD;&#xA;If I misunderstood you, let me know in the comments and I will adjust or remove my answer.&#xD;&#xA;&#xD;&#xA;However, if I understood your intention correctly and you want to cast a ray through your frustum (for example to pick objects), then your statement is wrong. The direction will be equal to the **view spaces'** negative z-direction. So all you need to do is to transform your vector or the near and far plane points to world space. To proof, that this works, I have implemented everything in a Python script, that you will find at the end of this answer. If you have a Python interpreter with MatPlotLib and NumPy installed, you can modify the setup parameters and experiment a little bit yourself.&#xD;&#xA;&#xD;&#xA;So let's have a look at the relevant implementation. First, we calculate the mouse position in clip space and the corresponding 2 points on the near and far plane.&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;mouse_pos_x_clip = mouse_pos_x_screen / screen_width * 2 - 1&#xD;&#xA;mouse_pos_y_clip = mouse_pos_y_screen / screen_height * 2 - 1&#xD;&#xA;&#xD;&#xA;mouse_pos_near_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, -1, 1], dtype=float)&#xD;&#xA;mouse_pos_far_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, 1, 1], dtype=float)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now we get the involved matrices. My notation here is as follows: I use two characters after `M_` that are abbreviations of the involved spaces. The first character is the source and the second the target space. The characters are `c` for clip space, `v` for view space, and `w` for world space. So `M_vc` is the view space to clip space transformation a.k.a the projection matrix.&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;M_wv = get_world_to_view_matrix(camera_pitch, camera_yaw, camera_position)&#xD;&#xA;if perspective:&#xD;&#xA;    M_vc = get_perspective_mat(field_of_view, z_near_plane, z_far_plane, aspect_ratio)&#xD;&#xA;else:&#xD;&#xA;    M_vc = get_orthogonal_mat(frustum_width, frustum_height, z_near_plane, z_far_plane)&#xD;&#xA;&#xD;&#xA;M_vw = np.linalg.inv(M_wv)&#xD;&#xA;M_cv = np.linalg.inv(M_vc)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now I simply use the correct transformation matrices to transform from clip to world space. Note that the perspective projection needs a division by `w` after the transformation to view space. This is not necessary for the orthographic projection, but performing it does not affect the result.&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;mouse_pos_near_view = np.matmul(M_cv, mouse_pos_near_clip)&#xD;&#xA;mouse_pos_far_view = np.matmul(M_cv, mouse_pos_far_clip)&#xD;&#xA;&#xD;&#xA;if perspective:&#xD;&#xA;    mouse_pos_near_view= mouse_pos_near_view / mouse_pos_near_view[3]&#xD;&#xA;    mouse_pos_far_view= mouse_pos_far_view / mouse_pos_far_view[3]&#xD;&#xA;&#xD;&#xA;mouse_pos_near_world = np.matmul(M_vw, mouse_pos_near_view)&#xD;&#xA;mouse_pos_far_world = np.matmul(M_vw, mouse_pos_far_view)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This is, as far as I can see, identical to your first code section. Now let's have a look a the result for perspective and orthographic projection with the following setup parameters:&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;screen_height = 1080&#xD;&#xA;screen_width = 1980&#xD;&#xA;&#xD;&#xA;mouse_pos_x_screen = 500&#xD;&#xA;mouse_pos_y_screen = 300&#xD;&#xA;&#xD;&#xA;camera_position = [3, 0, 1]&#xD;&#xA;camera_yaw = 20&#xD;&#xA;camera_pitch = 30&#xD;&#xA;&#xD;&#xA;z_near_plane = 0.5&#xD;&#xA;z_far_plane = 3&#xD;&#xA;&#xD;&#xA;# only orthogonal&#xD;&#xA;frustum_width = 3&#xD;&#xA;frustum_height = 2&#xD;&#xA;&#xD;&#xA;# only perspective&#xD;&#xA;field_of_view = 70&#xD;&#xA;aspect_ratio = screen_width / screen_height&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The screen space and clip space values are identical for both projections:&#xD;&#xA;&#xD;&#xA;[![screen space][1]][1]&#xD;&#xA;[![clip space][2]][2]&#xD;&#xA;&#xD;&#xA;The red line connects the two points on the near and far plane. The red dot is the point on the near plane, which is your &quot;screen&quot; in a 3d space. The green lines mark the borders of the frustum. In clip space, it is obviously just a cube. An important thing to realize is, that clip space is defined in a left-handed coordinate system while the other coordinate systems are usually right-handed (have a look at the images in [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html)). I mention it since I had some problems with the plots until I realized that.&#xD;&#xA;&#xD;&#xA;Now for perspective projection, I get the following plots:&#xD;&#xA;&#xD;&#xA;[![view space perspective][3]][3]&#xD;&#xA;[![world space perspective][4]][4]&#xD;&#xA;&#xD;&#xA;The blue dot is the camera position.&#xD;&#xA;If I just exchange the perspective matrix with an orthographic projection matrix, the results look like this:&#xD;&#xA;&#xD;&#xA;[![view space orthographic][5]][5]&#xD;&#xA;[![world space orthographic][6]][6]&#xD;&#xA;&#xD;&#xA;As you can see, the approach you used in your first code section works independently of the chosen projection. I don't know why you thought it wouldn't. An assumption of mine is, that you might have made a mistake during the implementation of the orthographic projection matrix. If you accidentally flipped rows and columns (transposed) of the orthographic projection matrix, you get total crap like this:&#xD;&#xA;&#xD;&#xA;[![transposed orthographic projection][7]][7]&#xD;&#xA;&#xD;&#xA;I know this looks like a wrong implementation of the perspective projection, but this is what I get when I transpose the orthographic projection matrix before the multiplication.&#xD;&#xA;&#xD;&#xA;So make sure you use the correct orthographic projection matrix ([source](http://www.songho.ca/opengl/gl_projectionmatrix.html)):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\frac{2}{w}&amp;0&amp;0&amp;0\\&#xD;&#xA;0&amp;\frac{2}{h}&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;\frac{-2}{f-n}&amp;-\frac{f+n}{f-n}\\&#xD;&#xA;0&amp;0&amp;0&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Here $w$ is the frustum width, $h$ the frustum height, $f$ the far plane z-value and $n$ the near plane z-value. This is the representation if you use column vectors and left multiplied matrices. For row vectors and right multiplied matrices, you need to transpose it.&#xD;&#xA;&#xD;&#xA;Your second approach:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;Vector4 cScreen = Vector4(cursorNormX, cursorNormY, 0, 0);&#xD;&#xA;Vector4 cView = Inverse(projection)*cScreen;&#xD;&#xA;cView = Vector4(cView.x, cView.y, 0, 0);&#xD;&#xA;Vector4 cWorld = Inverse(View) * cView;&#xD;&#xA;cWorld = Vector4(cWorld.x, cWorld.y, 0, 0);&#xD;&#xA;&#xD;&#xA;Vector3 cursorPos = cWorld.xyz();&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;has multiple issues and all are related to the z- and w-components of your vectors. Basically, you need to do the same transformations as in your first approach. So use `Vector4 cScreen = Vector4(cursorNormX, cursorNormY, -1, 1);` as initial vector. &#xD;&#xA;&#xD;&#xA;One problem of the line `cView = Vector4(cView.x, cView.y, 0, 0);` is, that your z-component should be identical to your near plane value and not zero. You might get away with that since it would just shift your point a little bit in the camera viewing direction in world space, but more problematic is that you set w to 0. This makes it impossible to apply any translation to the vector by $4 \times 4$ matrix multiplication. So when you transform to world space, you will always end up with a point that treats the camera to be located at the coordinate system origin, regardless of its true position. So you need to set the w-component to 1. However, if the previous lines are correct, you should automatically get the correct z- and w-values which makes this line obsolete. &#xD;&#xA;&#xD;&#xA;Lastly, the line `cWorld = Vector4(cWorld.x, cWorld.y, 0, 0);` doesn't make much sense either to me. Your camera is somewhere in 3d world space. Why do you remove the z-component you previously calculated? With this, you move the point into the XY-plane for no reason. Just remove this line.&#xD;&#xA;&#xD;&#xA;To get the cameras viewing direction without using the far plane point, just multiply the vector `[0, 0, -1, 0]` with the view-to-world matrix (`M_vw`). In this case, the w-component really has to be 0, since you do not want to apply translations to it because it is a direction vector and no point. The z-component needs to be -1 because the camera looks into the negative direction by definition. Notice, that the transformed vector is usually not of unit length anymore. So you might want to normalize it.&#xD;&#xA;&#xD;&#xA;**Additional Note**&#xD;&#xA;&#xD;&#xA;For an orthographic projection, there is no need to calculate the inverse projection matrix. You can simply calculate the x and y values directly by something like this (untested pseudo-code):&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;x_view = (x_screen / screen_width - 0.5) * frustum_width&#xD;&#xA;y_view = (y_screen / screen_height - 0.5) * frustum_height&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Then you get the screen space point in view space by setting (untested pseudo-code):&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;point_view_near = [x_view, y_view, -z_near, 1]&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Watch out to use the negative near plane z-value! For the far plane, you can do the same.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Full Python script**&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;import numpy as np&#xD;&#xA;from mpl_toolkits.mplot3d import Axes3D  # noqa: F401 unused import&#xD;&#xA;import matplotlib.pyplot as plt&#xD;&#xA;&#xD;&#xA;# setup --------------------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;screen_height = 1080&#xD;&#xA;screen_width = 1980&#xD;&#xA;&#xD;&#xA;mouse_pos_x_screen = 500&#xD;&#xA;mouse_pos_y_screen = 300&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;camera_position = [3, 0, 1]&#xD;&#xA;camera_yaw = 20&#xD;&#xA;camera_pitch = 30&#xD;&#xA;&#xD;&#xA;# ----------------&#xD;&#xA;# projection setup&#xD;&#xA;# ----------------&#xD;&#xA;perspective = False # set 'False' for orthogonal and 'True' for perspective projection&#xD;&#xA;&#xD;&#xA;z_near_plane = 0.5&#xD;&#xA;z_far_plane = 3&#xD;&#xA;&#xD;&#xA;# only orthogonal&#xD;&#xA;frustum_width = 3&#xD;&#xA;frustum_height = 2&#xD;&#xA;&#xD;&#xA;# only perspective&#xD;&#xA;field_of_view = 70&#xD;&#xA;aspect_ratio = screen_width / screen_height&#xD;&#xA;&#xD;&#xA;# functions ----------------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def render_frustum(points, camera_pos, ax, right_handed=True):&#xD;&#xA;    line_indices = [&#xD;&#xA;        [0, 1],&#xD;&#xA;        [0, 2],&#xD;&#xA;        [0, 4],&#xD;&#xA;        [1, 3],&#xD;&#xA;        [1, 5],&#xD;&#xA;        [2, 3],&#xD;&#xA;        [2, 6],&#xD;&#xA;        [3, 7],&#xD;&#xA;        [4, 5],&#xD;&#xA;        [4, 6],&#xD;&#xA;        [5, 7],&#xD;&#xA;        [6, 7],&#xD;&#xA;    ]&#xD;&#xA;    for idx_pair in line_indices:&#xD;&#xA;        line = np.transpose([points[idx_pair[0]], points[idx_pair[1]]])&#xD;&#xA;        ax.plot(line[2], line[0], line[1], &quot;g&quot;)&#xD;&#xA;    if right_handed:&#xD;&#xA;        ax.set_xlim([-5, 5])&#xD;&#xA;    else:&#xD;&#xA;        ax.set_xlim([5, -5])&#xD;&#xA;    ax.set_ylim([-5, 5])&#xD;&#xA;    ax.set_zlim([-5, 5])&#xD;&#xA;    ax.set_xlabel(&quot;z&quot;)&#xD;&#xA;    ax.set_ylabel(&quot;x&quot;)&#xD;&#xA;    ax.set_zlabel(&quot;y&quot;)&#xD;&#xA;    ax.plot([-5, 5], [0, 0], [0, 0], &quot;k&quot;)&#xD;&#xA;    ax.plot([0, 0], [-5, 5], [0, 0], &quot;k&quot;)&#xD;&#xA;    ax.plot([0, 0], [0, 0], [-5, 5], &quot;k&quot;)&#xD;&#xA;    if camera_pos is not None:&#xD;&#xA;        ax.scatter(&#xD;&#xA;            camera_pos[2], camera_pos[0], camera_pos[1], marker=&quot;o&quot;, color=&quot;b&quot;, s=30&#xD;&#xA;        )&#xD;&#xA;&#xD;&#xA;def render_ray(p0,p1,ax):&#xD;&#xA;    ax.plot([p0[2], p1[2]], [p0[0], p1[0]], [p0[1], p1[1]], color=&quot;r&quot;)&#xD;&#xA;    ax.scatter(p0[2], p0[0], p0[1], marker=&quot;o&quot;, color=&quot;r&quot;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_perspective_mat(fov_deg, z_near, z_far, aspect_ratio):&#xD;&#xA;    fov_rad = fov_deg * np.pi / 180&#xD;&#xA;    f = 1 / np.tan(fov_rad / 2)&#xD;&#xA;&#xD;&#xA;    return np.array(&#xD;&#xA;        [&#xD;&#xA;            [f / aspect_ratio, 0, 0, 0],&#xD;&#xA;            [0, f, 0, 0],&#xD;&#xA;            [&#xD;&#xA;                0,&#xD;&#xA;                0,&#xD;&#xA;                (z_far + z_near) / (z_near - z_far),&#xD;&#xA;                2 * z_far * z_near / (z_near - z_far),&#xD;&#xA;            ],&#xD;&#xA;            [0, 0, -1, 0],&#xD;&#xA;        ]&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_orthogonal_mat(width, height, z_near, z_far):&#xD;&#xA;    r = width / 2&#xD;&#xA;    t = height / 2&#xD;&#xA;&#xD;&#xA;    return np.array(&#xD;&#xA;        [&#xD;&#xA;            [1 / r, 0, 0, 0],&#xD;&#xA;            [0, 1 / t, 0, 0],&#xD;&#xA;            [&#xD;&#xA;                0,&#xD;&#xA;                0,&#xD;&#xA;                -2 / (z_far - z_near),&#xD;&#xA;                -(z_far + z_near) / (z_far - z_near),&#xD;&#xA;            ],&#xD;&#xA;            [0, 0, 0, 1],&#xD;&#xA;        ]&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_rotation_mat_x(angle_rad):&#xD;&#xA;    s = np.sin(angle_rad)&#xD;&#xA;    c = np.cos(angle_rad)&#xD;&#xA;    return np.array(&#xD;&#xA;        [[1, 0, 0, 0], [0, c, -s, 0], [0, s, c, 0], [0, 0, 0, 1]], dtype=float&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_rotation_mat_y(angle_rad):&#xD;&#xA;    s = np.sin(angle_rad)&#xD;&#xA;    c = np.cos(angle_rad)&#xD;&#xA;    return np.array(&#xD;&#xA;        [[c, 0, s, 0], [0, 1, 0, 0], [-s, 0, c, 0], [0, 0, 0, 1]], dtype=float&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_translation_mat(position):&#xD;&#xA;    return np.array(&#xD;&#xA;        [&#xD;&#xA;            [1, 0, 0, position[0]],&#xD;&#xA;            [0, 1, 0, position[1]],&#xD;&#xA;            [0, 0, 1, position[2]],&#xD;&#xA;            [0, 0, 0, 1],&#xD;&#xA;        ],&#xD;&#xA;        dtype=float,&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_world_to_view_matrix(pitch_deg, yaw_deg, position):&#xD;&#xA;    pitch_rad = np.pi / 180 * pitch_deg&#xD;&#xA;    yaw_rad = np.pi / 180 * yaw_deg&#xD;&#xA;&#xD;&#xA;    orientation_mat = np.matmul(&#xD;&#xA;        get_rotation_mat_x(-pitch_rad), get_rotation_mat_y(-yaw_rad)&#xD;&#xA;    )&#xD;&#xA;    translation_mat = get_translation_mat(-1 * np.array(position, dtype=float))&#xD;&#xA;    return np.matmul(orientation_mat, translation_mat)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# script -------------------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;mouse_pos_x_clip = mouse_pos_x_screen / screen_width * 2 - 1&#xD;&#xA;mouse_pos_y_clip = mouse_pos_y_screen / screen_height * 2 - 1&#xD;&#xA;&#xD;&#xA;mouse_pos_near_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, -1, 1], dtype=float)&#xD;&#xA;mouse_pos_far_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, 1, 1], dtype=float)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;M_wv = get_world_to_view_matrix(camera_pitch, camera_yaw, camera_position)&#xD;&#xA;if perspective:&#xD;&#xA;    M_vc = get_perspective_mat(field_of_view, z_near_plane, z_far_plane, aspect_ratio)&#xD;&#xA;else:&#xD;&#xA;    M_vc = get_orthogonal_mat(frustum_width, frustum_height, z_near_plane, z_far_plane)&#xD;&#xA;&#xD;&#xA;M_vw = np.linalg.inv(M_wv)&#xD;&#xA;M_cv = np.linalg.inv(M_vc)&#xD;&#xA;&#xD;&#xA;mouse_pos_near_view = np.matmul(M_cv,mouse_pos_near_clip)&#xD;&#xA;mouse_pos_far_view = np.matmul(M_cv,mouse_pos_far_clip)&#xD;&#xA;&#xD;&#xA;if perspective:&#xD;&#xA;    mouse_pos_near_view= mouse_pos_near_view / mouse_pos_near_view[3]&#xD;&#xA;    mouse_pos_far_view= mouse_pos_far_view / mouse_pos_far_view[3]&#xD;&#xA;&#xD;&#xA;mouse_pos_near_world = np.matmul(M_vw, mouse_pos_near_view)&#xD;&#xA;mouse_pos_far_world = np.matmul(M_vw, mouse_pos_far_view)&#xD;&#xA;&#xD;&#xA;# calculate view frustum ---------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;points_clip = np.array(&#xD;&#xA;    [&#xD;&#xA;        [-1, -1, -1, 1],&#xD;&#xA;        [ 1, -1, -1, 1],&#xD;&#xA;        [-1,  1, -1, 1],&#xD;&#xA;        [ 1,  1, -1, 1],&#xD;&#xA;        [-1, -1,  1, 1],&#xD;&#xA;        [ 1, -1,  1, 1],&#xD;&#xA;        [-1,  1,  1, 1],&#xD;&#xA;        [ 1,  1,  1, 1],&#xD;&#xA;    ],&#xD;&#xA;    dtype=float,&#xD;&#xA;)&#xD;&#xA;&#xD;&#xA;points_view = []&#xD;&#xA;points_world = []&#xD;&#xA;for i in range(8):&#xD;&#xA;    points_view.append(np.matmul(M_cv, points_clip[i]))&#xD;&#xA;    points_view[i] = points_view[i] / points_view[i][3]&#xD;&#xA;    points_world.append(np.matmul(M_vw, points_view[i]))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# plot everything ----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;plt.plot(mouse_pos_x_screen,mouse_pos_y_screen, marker=&quot;o&quot;, color=&quot;r&quot;)&#xD;&#xA;plt.xlim([0, screen_width])&#xD;&#xA;plt.ylim([0, screen_height])&#xD;&#xA;plt.xlabel(&quot;x&quot;)&#xD;&#xA;plt.ylabel(&quot;y&quot;)&#xD;&#xA;plt.title(&quot;screen space&quot;)&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;ax_clip_space = plt.gca(projection=&quot;3d&quot;)&#xD;&#xA;render_ray(mouse_pos_near_clip, mouse_pos_far_clip, ax_clip_space)&#xD;&#xA;render_frustum(points=points_clip, camera_pos=None, ax=ax_clip_space, right_handed=False)&#xD;&#xA;ax_clip_space.set_title(&quot;clip space&quot;)&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;ax_view = plt.gca(projection=&quot;3d&quot;)&#xD;&#xA;render_ray(mouse_pos_near_view, mouse_pos_far_view, ax_view)&#xD;&#xA;render_frustum(points=points_view, camera_pos=[0, 0, 0], ax=ax_view)&#xD;&#xA;ax_view.set_title(&quot;view space&quot;)&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;ax_world = plt.gca(projection=&quot;3d&quot;)&#xD;&#xA;render_ray(mouse_pos_near_world, mouse_pos_far_world, ax_world)&#xD;&#xA;render_frustum(points=points_world, camera_pos=camera_position, ax=ax_world)&#xD;&#xA;ax_world.set_title(&quot;world space&quot;)&#xD;&#xA;&#xD;&#xA;plt.show()&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZQ4q2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4R21Q.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/77GKT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/VAAVs.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/VxvEo.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4Nj7T.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/fWIcL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28773" PostHistoryTypeId="5" PostId="9960" RevisionGUID="bddb7e55-56cd-429a-b997-cba724bf8510" CreationDate="2020-06-21T13:51:09.393" UserId="13095" Comment="added 19 characters in body" Text="I am still not 100% sure, if I understood your question, because of this sentence:&#xD;&#xA;&#xD;&#xA;&gt; Now however with orthographic projection the far and near plane are of the same size, so we can't calculate the direction of the cursor this way. The direction is going to be equal the world's z axis. (I haven't had much sleep so I hope this makes sense).&#xD;&#xA;&#xD;&#xA;If I misunderstood you, let me know in the comments and I will adjust or remove my answer.&#xD;&#xA;&#xD;&#xA;However, if I understood your intention correctly and you want to cast a ray through your frustum (for example to pick objects), then your statement is wrong. The direction will be equal to the **view spaces'** negative z-direction, not the world spaces'. So all you need to do is to transform your direction vector or the near and far plane points to world space. To proof, that this works, I have implemented everything in a Python script, that you will find at the end of this answer. If you have a Python interpreter with MatPlotLib and NumPy installed, you can modify the setup parameters and experiment a little bit yourself.&#xD;&#xA;&#xD;&#xA;So let's have a look at the relevant implementation. First, we calculate the mouse position in clip space and the corresponding 2 points on the near and far plane.&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;mouse_pos_x_clip = mouse_pos_x_screen / screen_width * 2 - 1&#xD;&#xA;mouse_pos_y_clip = mouse_pos_y_screen / screen_height * 2 - 1&#xD;&#xA;&#xD;&#xA;mouse_pos_near_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, -1, 1], dtype=float)&#xD;&#xA;mouse_pos_far_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, 1, 1], dtype=float)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now we get the involved matrices. My notation here is as follows: I use two characters after `M_` that are abbreviations of the involved spaces. The first character is the source and the second the target space. The characters are `c` for clip space, `v` for view space, and `w` for world space. So `M_vc` is the view space to clip space transformation a.k.a the projection matrix.&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;M_wv = get_world_to_view_matrix(camera_pitch, camera_yaw, camera_position)&#xD;&#xA;if perspective:&#xD;&#xA;    M_vc = get_perspective_mat(field_of_view, z_near_plane, z_far_plane, aspect_ratio)&#xD;&#xA;else:&#xD;&#xA;    M_vc = get_orthogonal_mat(frustum_width, frustum_height, z_near_plane, z_far_plane)&#xD;&#xA;&#xD;&#xA;M_vw = np.linalg.inv(M_wv)&#xD;&#xA;M_cv = np.linalg.inv(M_vc)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now I simply use the correct transformation matrices to transform from clip to world space. Note that the perspective projection needs a division by `w` after the transformation to view space. This is not necessary for the orthographic projection, but performing it does not affect the result.&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;mouse_pos_near_view = np.matmul(M_cv, mouse_pos_near_clip)&#xD;&#xA;mouse_pos_far_view = np.matmul(M_cv, mouse_pos_far_clip)&#xD;&#xA;&#xD;&#xA;if perspective:&#xD;&#xA;    mouse_pos_near_view= mouse_pos_near_view / mouse_pos_near_view[3]&#xD;&#xA;    mouse_pos_far_view= mouse_pos_far_view / mouse_pos_far_view[3]&#xD;&#xA;&#xD;&#xA;mouse_pos_near_world = np.matmul(M_vw, mouse_pos_near_view)&#xD;&#xA;mouse_pos_far_world = np.matmul(M_vw, mouse_pos_far_view)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This is, as far as I can see, identical to your first code section. Now let's have a look a the result for perspective and orthographic projection with the following setup parameters:&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;screen_height = 1080&#xD;&#xA;screen_width = 1980&#xD;&#xA;&#xD;&#xA;mouse_pos_x_screen = 500&#xD;&#xA;mouse_pos_y_screen = 300&#xD;&#xA;&#xD;&#xA;camera_position = [3, 0, 1]&#xD;&#xA;camera_yaw = 20&#xD;&#xA;camera_pitch = 30&#xD;&#xA;&#xD;&#xA;z_near_plane = 0.5&#xD;&#xA;z_far_plane = 3&#xD;&#xA;&#xD;&#xA;# only orthogonal&#xD;&#xA;frustum_width = 3&#xD;&#xA;frustum_height = 2&#xD;&#xA;&#xD;&#xA;# only perspective&#xD;&#xA;field_of_view = 70&#xD;&#xA;aspect_ratio = screen_width / screen_height&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The screen space and clip space values are identical for both projections:&#xD;&#xA;&#xD;&#xA;[![screen space][1]][1]&#xD;&#xA;[![clip space][2]][2]&#xD;&#xA;&#xD;&#xA;The red line connects the two points on the near and far plane. The red dot is the point on the near plane, which is your &quot;screen&quot; in a 3d space. The green lines mark the borders of the frustum. In clip space, it is obviously just a cube. An important thing to realize is, that clip space is defined in a left-handed coordinate system while the other coordinate systems are usually right-handed (have a look at the images in [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html)). I mention it since I had some problems with the plots until I realized that.&#xD;&#xA;&#xD;&#xA;Now for perspective projection, I get the following plots:&#xD;&#xA;&#xD;&#xA;[![view space perspective][3]][3]&#xD;&#xA;[![world space perspective][4]][4]&#xD;&#xA;&#xD;&#xA;The blue dot is the camera position.&#xD;&#xA;If I just exchange the perspective matrix with an orthographic projection matrix, the results look like this:&#xD;&#xA;&#xD;&#xA;[![view space orthographic][5]][5]&#xD;&#xA;[![world space orthographic][6]][6]&#xD;&#xA;&#xD;&#xA;As you can see, the approach you used in your first code section works independently of the chosen projection. I don't know why you thought it wouldn't. An assumption of mine is, that you might have made a small mistake during the implementation of the orthographic projection matrix. For example, if you accidentally flipped rows and columns (transposed) of the orthographic projection matrix, you get total crap like this:&#xD;&#xA;&#xD;&#xA;[![transposed orthographic projection][7]][7]&#xD;&#xA;&#xD;&#xA;I know this looks like a wrong implementation of the perspective projection, but this is what I get when I transpose the orthographic projection matrix before the multiplication.&#xD;&#xA;&#xD;&#xA;So make sure you use the correct orthographic projection matrix ([source](http://www.songho.ca/opengl/gl_projectionmatrix.html)):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\frac{2}{w}&amp;0&amp;0&amp;0\\&#xD;&#xA;0&amp;\frac{2}{h}&amp;0&amp;0\\&#xD;&#xA;0&amp;0&amp;\frac{-2}{f-n}&amp;-\frac{f+n}{f-n}\\&#xD;&#xA;0&amp;0&amp;0&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Here $w$ is the frustum width, $h$ the frustum height, $f$ the far plane z-value and $n$ the near plane z-value. This is the representation if you use column vectors and left multiplied matrices. For row vectors and right multiplied matrices, you need to transpose it.&#xD;&#xA;&#xD;&#xA;Your second approach:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;Vector4 cScreen = Vector4(cursorNormX, cursorNormY, 0, 0);&#xD;&#xA;Vector4 cView = Inverse(projection)*cScreen;&#xD;&#xA;cView = Vector4(cView.x, cView.y, 0, 0);&#xD;&#xA;Vector4 cWorld = Inverse(View) * cView;&#xD;&#xA;cWorld = Vector4(cWorld.x, cWorld.y, 0, 0);&#xD;&#xA;&#xD;&#xA;Vector3 cursorPos = cWorld.xyz();&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;has multiple issues and all are related to the z- and w-components of your vectors. Basically, you need to do the same transformations as in your first approach. So use `Vector4 cScreen = Vector4(cursorNormX, cursorNormY, -1, 1);` as initial vector. &#xD;&#xA;&#xD;&#xA;One problem of the line `cView = Vector4(cView.x, cView.y, 0, 0);` is, that your z-component should be identical to your near plane value and not zero. You might get away with that since it would just shift your point a little bit in the camera viewing direction in world space, but more problematic is that you set w to 0. This makes it impossible to apply any translation to the vector by $4 \times 4$ matrix multiplication. So when you transform to world space, you will always end up with a point that treats the camera to be located at the coordinate system origin, regardless of its true position. So you need to set the w-component to 1. However, if the previous lines are correct, you should automatically get the correct z- and w-values which makes this line obsolete. &#xD;&#xA;&#xD;&#xA;Lastly, the line `cWorld = Vector4(cWorld.x, cWorld.y, 0, 0);` doesn't make much sense either to me. Your camera is somewhere in 3d world space. Why do you remove the z-component you previously calculated? With this, you move the point into the XY-plane for no reason. Just remove this line.&#xD;&#xA;&#xD;&#xA;To get the cameras viewing direction without using the far plane point, just multiply the vector `[0, 0, -1, 0]` with the view-to-world matrix (`M_vw`). In this case, the w-component really has to be 0, since you do not want to apply translations to it because it is a direction vector and no point. The z-component needs to be -1 because the camera looks into the negative direction by definition. Notice, that the transformed vector is usually not of unit length anymore. So you might want to normalize it.&#xD;&#xA;&#xD;&#xA;**Additional Note**&#xD;&#xA;&#xD;&#xA;For an orthographic projection, there is no need to calculate the inverse projection matrix. You can simply calculate the x and y values directly by something like this (untested pseudo-code):&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;x_view = (x_screen / screen_width - 0.5) * frustum_width&#xD;&#xA;y_view = (y_screen / screen_height - 0.5) * frustum_height&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Then you get the screen space point in view space by setting (untested pseudo-code):&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;point_view_near = [x_view, y_view, -z_near, 1]&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Watch out to use the negative near plane z-value! For the far plane, you can do the same.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Full Python script**&#xD;&#xA;&#xD;&#xA;~~~ Python&#xD;&#xA;import numpy as np&#xD;&#xA;from mpl_toolkits.mplot3d import Axes3D  # noqa: F401 unused import&#xD;&#xA;import matplotlib.pyplot as plt&#xD;&#xA;&#xD;&#xA;# setup --------------------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;screen_height = 1080&#xD;&#xA;screen_width = 1980&#xD;&#xA;&#xD;&#xA;mouse_pos_x_screen = 500&#xD;&#xA;mouse_pos_y_screen = 300&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;camera_position = [3, 0, 1]&#xD;&#xA;camera_yaw = 20&#xD;&#xA;camera_pitch = 30&#xD;&#xA;&#xD;&#xA;# ----------------&#xD;&#xA;# projection setup&#xD;&#xA;# ----------------&#xD;&#xA;perspective = False # set 'False' for orthogonal and 'True' for perspective projection&#xD;&#xA;&#xD;&#xA;z_near_plane = 0.5&#xD;&#xA;z_far_plane = 3&#xD;&#xA;&#xD;&#xA;# only orthogonal&#xD;&#xA;frustum_width = 3&#xD;&#xA;frustum_height = 2&#xD;&#xA;&#xD;&#xA;# only perspective&#xD;&#xA;field_of_view = 70&#xD;&#xA;aspect_ratio = screen_width / screen_height&#xD;&#xA;&#xD;&#xA;# functions ----------------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def render_frustum(points, camera_pos, ax, right_handed=True):&#xD;&#xA;    line_indices = [&#xD;&#xA;        [0, 1],&#xD;&#xA;        [0, 2],&#xD;&#xA;        [0, 4],&#xD;&#xA;        [1, 3],&#xD;&#xA;        [1, 5],&#xD;&#xA;        [2, 3],&#xD;&#xA;        [2, 6],&#xD;&#xA;        [3, 7],&#xD;&#xA;        [4, 5],&#xD;&#xA;        [4, 6],&#xD;&#xA;        [5, 7],&#xD;&#xA;        [6, 7],&#xD;&#xA;    ]&#xD;&#xA;    for idx_pair in line_indices:&#xD;&#xA;        line = np.transpose([points[idx_pair[0]], points[idx_pair[1]]])&#xD;&#xA;        ax.plot(line[2], line[0], line[1], &quot;g&quot;)&#xD;&#xA;    if right_handed:&#xD;&#xA;        ax.set_xlim([-5, 5])&#xD;&#xA;    else:&#xD;&#xA;        ax.set_xlim([5, -5])&#xD;&#xA;    ax.set_ylim([-5, 5])&#xD;&#xA;    ax.set_zlim([-5, 5])&#xD;&#xA;    ax.set_xlabel(&quot;z&quot;)&#xD;&#xA;    ax.set_ylabel(&quot;x&quot;)&#xD;&#xA;    ax.set_zlabel(&quot;y&quot;)&#xD;&#xA;    ax.plot([-5, 5], [0, 0], [0, 0], &quot;k&quot;)&#xD;&#xA;    ax.plot([0, 0], [-5, 5], [0, 0], &quot;k&quot;)&#xD;&#xA;    ax.plot([0, 0], [0, 0], [-5, 5], &quot;k&quot;)&#xD;&#xA;    if camera_pos is not None:&#xD;&#xA;        ax.scatter(&#xD;&#xA;            camera_pos[2], camera_pos[0], camera_pos[1], marker=&quot;o&quot;, color=&quot;b&quot;, s=30&#xD;&#xA;        )&#xD;&#xA;&#xD;&#xA;def render_ray(p0,p1,ax):&#xD;&#xA;    ax.plot([p0[2], p1[2]], [p0[0], p1[0]], [p0[1], p1[1]], color=&quot;r&quot;)&#xD;&#xA;    ax.scatter(p0[2], p0[0], p0[1], marker=&quot;o&quot;, color=&quot;r&quot;)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_perspective_mat(fov_deg, z_near, z_far, aspect_ratio):&#xD;&#xA;    fov_rad = fov_deg * np.pi / 180&#xD;&#xA;    f = 1 / np.tan(fov_rad / 2)&#xD;&#xA;&#xD;&#xA;    return np.array(&#xD;&#xA;        [&#xD;&#xA;            [f / aspect_ratio, 0, 0, 0],&#xD;&#xA;            [0, f, 0, 0],&#xD;&#xA;            [&#xD;&#xA;                0,&#xD;&#xA;                0,&#xD;&#xA;                (z_far + z_near) / (z_near - z_far),&#xD;&#xA;                2 * z_far * z_near / (z_near - z_far),&#xD;&#xA;            ],&#xD;&#xA;            [0, 0, -1, 0],&#xD;&#xA;        ]&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_orthogonal_mat(width, height, z_near, z_far):&#xD;&#xA;    r = width / 2&#xD;&#xA;    t = height / 2&#xD;&#xA;&#xD;&#xA;    return np.array(&#xD;&#xA;        [&#xD;&#xA;            [1 / r, 0, 0, 0],&#xD;&#xA;            [0, 1 / t, 0, 0],&#xD;&#xA;            [&#xD;&#xA;                0,&#xD;&#xA;                0,&#xD;&#xA;                -2 / (z_far - z_near),&#xD;&#xA;                -(z_far + z_near) / (z_far - z_near),&#xD;&#xA;            ],&#xD;&#xA;            [0, 0, 0, 1],&#xD;&#xA;        ]&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_rotation_mat_x(angle_rad):&#xD;&#xA;    s = np.sin(angle_rad)&#xD;&#xA;    c = np.cos(angle_rad)&#xD;&#xA;    return np.array(&#xD;&#xA;        [[1, 0, 0, 0], [0, c, -s, 0], [0, s, c, 0], [0, 0, 0, 1]], dtype=float&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_rotation_mat_y(angle_rad):&#xD;&#xA;    s = np.sin(angle_rad)&#xD;&#xA;    c = np.cos(angle_rad)&#xD;&#xA;    return np.array(&#xD;&#xA;        [[c, 0, s, 0], [0, 1, 0, 0], [-s, 0, c, 0], [0, 0, 0, 1]], dtype=float&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_translation_mat(position):&#xD;&#xA;    return np.array(&#xD;&#xA;        [&#xD;&#xA;            [1, 0, 0, position[0]],&#xD;&#xA;            [0, 1, 0, position[1]],&#xD;&#xA;            [0, 0, 1, position[2]],&#xD;&#xA;            [0, 0, 0, 1],&#xD;&#xA;        ],&#xD;&#xA;        dtype=float,&#xD;&#xA;    )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def get_world_to_view_matrix(pitch_deg, yaw_deg, position):&#xD;&#xA;    pitch_rad = np.pi / 180 * pitch_deg&#xD;&#xA;    yaw_rad = np.pi / 180 * yaw_deg&#xD;&#xA;&#xD;&#xA;    orientation_mat = np.matmul(&#xD;&#xA;        get_rotation_mat_x(-pitch_rad), get_rotation_mat_y(-yaw_rad)&#xD;&#xA;    )&#xD;&#xA;    translation_mat = get_translation_mat(-1 * np.array(position, dtype=float))&#xD;&#xA;    return np.matmul(orientation_mat, translation_mat)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# script -------------------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;mouse_pos_x_clip = mouse_pos_x_screen / screen_width * 2 - 1&#xD;&#xA;mouse_pos_y_clip = mouse_pos_y_screen / screen_height * 2 - 1&#xD;&#xA;&#xD;&#xA;mouse_pos_near_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, -1, 1], dtype=float)&#xD;&#xA;mouse_pos_far_clip = np.array([mouse_pos_x_clip, mouse_pos_y_clip, 1, 1], dtype=float)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;M_wv = get_world_to_view_matrix(camera_pitch, camera_yaw, camera_position)&#xD;&#xA;if perspective:&#xD;&#xA;    M_vc = get_perspective_mat(field_of_view, z_near_plane, z_far_plane, aspect_ratio)&#xD;&#xA;else:&#xD;&#xA;    M_vc = get_orthogonal_mat(frustum_width, frustum_height, z_near_plane, z_far_plane)&#xD;&#xA;&#xD;&#xA;M_vw = np.linalg.inv(M_wv)&#xD;&#xA;M_cv = np.linalg.inv(M_vc)&#xD;&#xA;&#xD;&#xA;mouse_pos_near_view = np.matmul(M_cv,mouse_pos_near_clip)&#xD;&#xA;mouse_pos_far_view = np.matmul(M_cv,mouse_pos_far_clip)&#xD;&#xA;&#xD;&#xA;if perspective:&#xD;&#xA;    mouse_pos_near_view= mouse_pos_near_view / mouse_pos_near_view[3]&#xD;&#xA;    mouse_pos_far_view= mouse_pos_far_view / mouse_pos_far_view[3]&#xD;&#xA;&#xD;&#xA;mouse_pos_near_world = np.matmul(M_vw, mouse_pos_near_view)&#xD;&#xA;mouse_pos_far_world = np.matmul(M_vw, mouse_pos_far_view)&#xD;&#xA;&#xD;&#xA;# calculate view frustum ---------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;points_clip = np.array(&#xD;&#xA;    [&#xD;&#xA;        [-1, -1, -1, 1],&#xD;&#xA;        [ 1, -1, -1, 1],&#xD;&#xA;        [-1,  1, -1, 1],&#xD;&#xA;        [ 1,  1, -1, 1],&#xD;&#xA;        [-1, -1,  1, 1],&#xD;&#xA;        [ 1, -1,  1, 1],&#xD;&#xA;        [-1,  1,  1, 1],&#xD;&#xA;        [ 1,  1,  1, 1],&#xD;&#xA;    ],&#xD;&#xA;    dtype=float,&#xD;&#xA;)&#xD;&#xA;&#xD;&#xA;points_view = []&#xD;&#xA;points_world = []&#xD;&#xA;for i in range(8):&#xD;&#xA;    points_view.append(np.matmul(M_cv, points_clip[i]))&#xD;&#xA;    points_view[i] = points_view[i] / points_view[i][3]&#xD;&#xA;    points_world.append(np.matmul(M_vw, points_view[i]))&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# plot everything ----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;plt.plot(mouse_pos_x_screen,mouse_pos_y_screen, marker=&quot;o&quot;, color=&quot;r&quot;)&#xD;&#xA;plt.xlim([0, screen_width])&#xD;&#xA;plt.ylim([0, screen_height])&#xD;&#xA;plt.xlabel(&quot;x&quot;)&#xD;&#xA;plt.ylabel(&quot;y&quot;)&#xD;&#xA;plt.title(&quot;screen space&quot;)&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;ax_clip_space = plt.gca(projection=&quot;3d&quot;)&#xD;&#xA;render_ray(mouse_pos_near_clip, mouse_pos_far_clip, ax_clip_space)&#xD;&#xA;render_frustum(points=points_clip, camera_pos=None, ax=ax_clip_space, right_handed=False)&#xD;&#xA;ax_clip_space.set_title(&quot;clip space&quot;)&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;ax_view = plt.gca(projection=&quot;3d&quot;)&#xD;&#xA;render_ray(mouse_pos_near_view, mouse_pos_far_view, ax_view)&#xD;&#xA;render_frustum(points=points_view, camera_pos=[0, 0, 0], ax=ax_view)&#xD;&#xA;ax_view.set_title(&quot;view space&quot;)&#xD;&#xA;&#xD;&#xA;plt.figure()&#xD;&#xA;ax_world = plt.gca(projection=&quot;3d&quot;)&#xD;&#xA;render_ray(mouse_pos_near_world, mouse_pos_far_world, ax_world)&#xD;&#xA;render_frustum(points=points_world, camera_pos=camera_position, ax=ax_world)&#xD;&#xA;ax_world.set_title(&quot;world space&quot;)&#xD;&#xA;&#xD;&#xA;plt.show()&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZQ4q2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4R21Q.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/77GKT.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/VAAVs.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/VxvEo.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4Nj7T.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/fWIcL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28774" PostHistoryTypeId="2" PostId="9961" RevisionGUID="d2a04c0c-4878-40ef-a5ea-fc07ccb70b09" CreationDate="2020-06-21T16:40:47.053" UserId="10370" Text="Real human anatomies look wet/ moist when operated. I am looking for some good methods for rendering anatomies in a virtual simulation, and hence I have done a literature survey on 'Rendering wet materials' using keywords like: &#xD;&#xA;1. Rendering wet materials.&#xD;&#xA;2. Rendering moist surfaces.&#xD;&#xA;3. Rendering wet surfaces.&#xD;&#xA;etc.&#xD;&#xA;&#xD;&#xA;What I observed is, in general, people use ray-tracing methods after modeling surface with a two-layer surface reflection model, for achieving realism for wet surfaces.&#xD;&#xA;&#xD;&#xA; What are some good rasterization methods/ approximations for the same keeping in mind real-time performance and unavailability of RTX gfx cards, as well as realism?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28775" PostHistoryTypeId="1" PostId="9961" RevisionGUID="d2a04c0c-4878-40ef-a5ea-fc07ccb70b09" CreationDate="2020-06-21T16:40:47.053" UserId="10370" Text="Rendering moist/wet materials like human anatomies for surgical simulators" ContentLicense="CC BY-SA 4.0" />
  <row Id="28776" PostHistoryTypeId="3" PostId="9961" RevisionGUID="d2a04c0c-4878-40ef-a5ea-fc07ccb70b09" CreationDate="2020-06-21T16:40:47.053" UserId="10370" Text="|opengl|raytracing|rendering|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28780" PostHistoryTypeId="2" PostId="9963" RevisionGUID="951f60b3-915f-4d1b-889d-dd0786a8f8d8" CreationDate="2020-06-21T19:00:43.753" UserId="13581" Text="I am writing a very simple rendering engine. I have already made a few tests, but somehow the images it creates look wrong. Objects that are further away from the camera look larger than objects closer to the camera. I have constructed this example:&#xD;&#xA;&#xD;&#xA;    pos = [-10, 0, 0] # Camera position&#xD;&#xA;    target = [1, 0, 0] # Camera looks at this point&#xD;&#xA;    up = [0, 0, 1] # z direction is &quot;up&quot;&#xD;&#xA;&#xD;&#xA;    fov_y = 25 * degree # field of view in y direction (camera y axis)&#xD;&#xA;    aspect_ratio = 1&#xD;&#xA;    near = 0.01 # Near clipping plane distance&#xD;&#xA;    far = 5000 # Far clipping plane distance&#xD;&#xA;&#xD;&#xA;I added two lines to the scene, a red one from `[1, 0, 0]` to `[1, 0, 1]` and a black one from `[4, 0, 0]` to `[4, 0, 1]`. The black one is clearly further away from the camera, but appears larger:&#xD;&#xA;&#xD;&#xA;[![Two overlapping vertical lines starting from the same bottom point. The red one is thicker and smaller than the black one.][1]][1]&#xD;&#xA;&#xD;&#xA;From the above description, at first I have constructed the view matrix&#xD;&#xA;   &#xD;&#xA;    V = [[0, -1, 0,   0],&#xD;&#xA;         [0,  0, 1,   0],&#xD;&#xA;         [1,  0, 0, -10],&#xD;&#xA;         [0,  0, 0,   1]]&#xD;&#xA;&#xD;&#xA;which seems to be correct. The perspective matrix I calculated is&#xD;&#xA;&#xD;&#xA;    P = [[4.5107,      0,         0,     0],&#xD;&#xA;         [0,      4.5107,         0,     0],&#xD;&#xA;         [0,           0, -1.000004, -0.02],&#xD;&#xA;         [0,           0,         -1,    0]]&#xD;&#xA;    &#xD;&#xA;I'm assuming the problem is somewhere here. The full transformation matrix is&#xD;&#xA;&#xD;&#xA;    T = P * V&#xD;&#xA;&#xD;&#xA;and I use numpy to calculate the transformed points:&#xD;&#xA;&#xD;&#xA;    p_transformed = numpy.dot(p_untransformed, T.T) # Transpose on the right hand side&#xD;&#xA;&#xD;&#xA;For example, `[1, 0, 1]` becomes `[0, 4.5107, 8.98, 9]` and `[4, 0, 1]` becomes `[0, 4.5107, 5.98, 6]` and since the last step is to divide the first three components by the last one, this results in the second line being larger than the first one. &#xD;&#xA;&#xD;&#xA;Is there a mistake somewhere? If so, where is it?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oCPAg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28781" PostHistoryTypeId="1" PostId="9963" RevisionGUID="951f60b3-915f-4d1b-889d-dd0786a8f8d8" CreationDate="2020-06-21T19:00:43.753" UserId="13581" Text="Why does my self-written rendering engine make further away objects look larger?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28782" PostHistoryTypeId="3" PostId="9963" RevisionGUID="951f60b3-915f-4d1b-889d-dd0786a8f8d8" CreationDate="2020-06-21T19:00:43.753" UserId="13581" Text="|rendering|transformations|mathematics|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28784" PostHistoryTypeId="5" PostId="9963" RevisionGUID="63d210bc-7248-476b-812d-30f21c7662ba" CreationDate="2020-06-21T20:11:53.250" UserId="13581" Comment="added 722 characters in body" Text="I am writing a very simple rendering engine. I have already made a few tests, but somehow the images it creates look wrong. Objects that are further away from the camera look larger than objects closer to the camera. I have constructed this example:&#xD;&#xA;&#xD;&#xA;    pos = [-10, 0, 0] # Camera position&#xD;&#xA;    target = [1, 0, 0] # Camera looks at this point&#xD;&#xA;    up = [0, 0, 1] # z direction is &quot;up&quot;&#xD;&#xA;&#xD;&#xA;    fov_y = 25 * degree # field of view in y direction (camera y axis)&#xD;&#xA;    aspect_ratio = 1&#xD;&#xA;    near = 0.01 # Near clipping plane distance&#xD;&#xA;    far = 5000 # Far clipping plane distance&#xD;&#xA;&#xD;&#xA;I added two lines to the scene, a red one from `[1, 0, 0]` to `[1, 0, 1]` and a black one from `[4, 0, 0]` to `[4, 0, 1]`. The black one is clearly further away from the camera, but appears larger:&#xD;&#xA;&#xD;&#xA;[![Two overlapping vertical lines starting from the same bottom point. The red one is thicker and smaller than the black one.][1]][1]&#xD;&#xA;&#xD;&#xA;From the above description, at first I have constructed the view matrix&#xD;&#xA;   &#xD;&#xA;    V = [[0, -1, 0,   0],&#xD;&#xA;         [0,  0, 1,   0],&#xD;&#xA;         [1,  0, 0, -10],&#xD;&#xA;         [0,  0, 0,   1]]&#xD;&#xA;&#xD;&#xA;which seems to be correct. The perspective matrix I calculated is&#xD;&#xA;&#xD;&#xA;    P = [[4.5107,      0,         0,     0],&#xD;&#xA;         [0,      4.5107,         0,     0],&#xD;&#xA;         [0,           0, -1.000004, -0.02],&#xD;&#xA;         [0,           0,         -1,    0]]&#xD;&#xA;    &#xD;&#xA;I'm assuming the problem is somewhere here. The full transformation matrix is (using numpy):&#xD;&#xA;&#xD;&#xA;    T = numpy.dot(P, V)&#xD;&#xA;&#xD;&#xA;and the transformed points:&#xD;&#xA;&#xD;&#xA;    p_transformed = numpy.dot(p_untransformed, T.T) # Transpose on the right hand side&#xD;&#xA;&#xD;&#xA;For example, `[1, 0, 1]` becomes `[0, 4.5107, 8.98, 9]` and `[4, 0, 1]` becomes `[0, 4.5107, 5.98, 6]` and since the last step is to divide the first three components by the last one, this results in the second line being larger than the first one. &#xD;&#xA;&#xD;&#xA;Is there a mistake somewhere? If so, where is it?&#xD;&#xA;&#xD;&#xA;Edit: Formulae&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;Here are the formulae I used:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;    d = normalized(target - pos) # direction vector of the camera&#xD;&#xA;    r = normalized(cross(d, up)) # x unit vector in camera space&#xD;&#xA;    u = normalized(cross(r, d)) # y unit vector in camera space&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Furthermore, the formula for P is &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;([Source][4])&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;    n, f # position of near an far clipping plane&#xD;&#xA;    t = n * tan(0.5 * radians(fov_y))&#xD;&#xA;    b = -t&#xD;&#xA;    r = t * aspect_ratio&#xD;&#xA;    l = -r&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oCPAg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/sAVdJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/nsPTz.png&#xD;&#xA;  [4]: http://www.songho.ca/opengl/gl_projectionmatrix.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="28785" PostHistoryTypeId="2" PostId="9964" RevisionGUID="dc636527-49c3-4f9c-a2d9-6ca4622a6937" CreationDate="2020-06-21T21:49:38.283" UserId="7462" Text="What are some state of the art methods/algorithms to find geodesics on arbitrary manifold meshes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28786" PostHistoryTypeId="1" PostId="9964" RevisionGUID="dc636527-49c3-4f9c-a2d9-6ca4622a6937" CreationDate="2020-06-21T21:49:38.283" UserId="7462" Text="Finding geodesics on a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28787" PostHistoryTypeId="3" PostId="9964" RevisionGUID="dc636527-49c3-4f9c-a2d9-6ca4622a6937" CreationDate="2020-06-21T21:49:38.283" UserId="7462" Text="|mathematics|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28788" PostHistoryTypeId="2" PostId="9965" RevisionGUID="744b7e09-43b2-4af5-8cc0-fe94bb1cc71b" CreationDate="2020-06-22T02:02:03.230" UserId="13472" Text="I found a paper from 1997 that addresses this subject: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.29.6799" ContentLicense="CC BY-SA 4.0" />
  <row Id="28792" PostHistoryTypeId="2" PostId="9967" RevisionGUID="abb80c34-4d09-49df-b609-843a8b82ad6e" CreationDate="2020-06-22T07:06:58.663" UserId="13305" Text="There can be much dispute on which work is considered best or state-of-the-art. It will depend on your application. However, I'd like to recommend to give a look at this paper by Keenan Crane et al. It is impressive in terms of computational speed. Also, It is simple to implement.&#xD;&#xA;&#xD;&#xA;Crane et al. Geodesics in heat: A new approach to computing distance based on heat flow. ACM TOG. 2013. (https://dl.acm.org/doi/10.1145/2516971.2516977)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28793" PostHistoryTypeId="2" PostId="9968" RevisionGUID="696ca26a-d92a-4858-807a-3f7470cea300" CreationDate="2020-06-22T09:30:25.160" UserId="13418" Text="The open source implementation [FreeGLUT](https://sourceforge.net/projects/freeglut/) has these functions.&#xD;&#xA;The geometry code can be found in [`freeglut/freeglut/src/fg_geometry.c`](https://sourceforge.net/p/freeglut/code/HEAD/tree/trunk/freeglut/freeglut/src/fg_geometry.c).&#xD;&#xA;&#xD;&#xA;For the dodecahedron, these are the values:&#xD;&#xA;```&#xD;&#xA;#define DODECAHEDRON_NUM_VERT           20&#xD;&#xA;#define DODECAHEDRON_NUM_FACES          12&#xD;&#xA;#define DODECAHEDRON_NUM_EDGE_PER_FACE  5&#xD;&#xA;#define DODECAHEDRON_VERT_PER_OBJ       (DODECAHEDRON_NUM_FACES*DODECAHEDRON_NUM_EDGE_PER_FACE)&#xD;&#xA;#define DODECAHEDRON_VERT_ELEM_PER_OBJ  (DODECAHEDRON_VERT_PER_OBJ*3)&#xD;&#xA;#define DODECAHEDRON_VERT_PER_OBJ_TRI   (DODECAHEDRON_VERT_PER_OBJ+DODECAHEDRON_NUM_FACES*4)    /* 4 extra edges per face when drawing pentagons as triangles */&#xD;&#xA;/* Vertex Coordinates */&#xD;&#xA;static GLfloat dodecahedron_v[DODECAHEDRON_NUM_VERT*3] =&#xD;&#xA;{&#xD;&#xA;               0.0f,  1.61803398875f,  0.61803398875f,&#xD;&#xA;    -          1.0f,            1.0f,            1.0f,&#xD;&#xA;    -0.61803398875f,            0.0f,  1.61803398875f,&#xD;&#xA;     0.61803398875f,            0.0f,  1.61803398875f,&#xD;&#xA;               1.0f,            1.0f,            1.0f,&#xD;&#xA;               0.0f,  1.61803398875f, -0.61803398875f,&#xD;&#xA;               1.0f,            1.0f, -          1.0f,&#xD;&#xA;     0.61803398875f,            0.0f, -1.61803398875f,&#xD;&#xA;    -0.61803398875f,            0.0f, -1.61803398875f,&#xD;&#xA;    -          1.0f,            1.0f, -          1.0f,&#xD;&#xA;               0.0f, -1.61803398875f,  0.61803398875f,&#xD;&#xA;               1.0f, -          1.0f,            1.0f,&#xD;&#xA;    -          1.0f, -          1.0f,            1.0f,&#xD;&#xA;               0.0f, -1.61803398875f, -0.61803398875f,&#xD;&#xA;    -          1.0f, -          1.0f, -          1.0f,&#xD;&#xA;               1.0f, -          1.0f, -          1.0f,&#xD;&#xA;     1.61803398875f, -0.61803398875f,            0.0f,&#xD;&#xA;     1.61803398875f,  0.61803398875f,            0.0f,&#xD;&#xA;    -1.61803398875f,  0.61803398875f,            0.0f,&#xD;&#xA;    -1.61803398875f, -0.61803398875f,            0.0f&#xD;&#xA;};&#xD;&#xA;/* Normal Vectors */&#xD;&#xA;static GLfloat dodecahedron_n[DODECAHEDRON_NUM_FACES*3] =&#xD;&#xA;{&#xD;&#xA;                0.0f,  0.525731112119f,  0.850650808354f,&#xD;&#xA;                0.0f,  0.525731112119f, -0.850650808354f,&#xD;&#xA;                0.0f, -0.525731112119f,  0.850650808354f,&#xD;&#xA;                0.0f, -0.525731112119f, -0.850650808354f,&#xD;&#xA;&#xD;&#xA;     0.850650808354f,             0.0f,  0.525731112119f,&#xD;&#xA;    -0.850650808354f,             0.0f,  0.525731112119f,&#xD;&#xA;     0.850650808354f,             0.0f, -0.525731112119f,&#xD;&#xA;    -0.850650808354f,             0.0f, -0.525731112119f,&#xD;&#xA;&#xD;&#xA;     0.525731112119f,  0.850650808354f,             0.0f,&#xD;&#xA;     0.525731112119f, -0.850650808354f,             0.0f,&#xD;&#xA;    -0.525731112119f,  0.850650808354f,             0.0f, &#xD;&#xA;    -0.525731112119f, -0.850650808354f,             0.0f,&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;/* Vertex indices */&#xD;&#xA;static GLubyte dodecahedron_vi[DODECAHEDRON_VERT_PER_OBJ] =&#xD;&#xA;{&#xD;&#xA;     0,  1,  2,  3,  4, &#xD;&#xA;     5,  6,  7,  8,  9, &#xD;&#xA;    10, 11,  3,  2, 12, &#xD;&#xA;    13, 14,  8,  7, 15, &#xD;&#xA;&#xD;&#xA;     3, 11, 16, 17,  4, &#xD;&#xA;     2,  1, 18, 19, 12, &#xD;&#xA;     7,  6, 17, 16, 15, &#xD;&#xA;     8, 14, 19, 18,  9, &#xD;&#xA;&#xD;&#xA;    17,  6,  5,  0,  4, &#xD;&#xA;    16, 11, 10, 13, 15, &#xD;&#xA;    18,  1,  0,  5,  9, &#xD;&#xA;    19, 14, 13, 10, 12&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As for the second part of your question, tools such as [renderdoc](https://renderdoc.org) allow you to export meshes which are used in a render. To do this, you must first take a capture, find the corresponding draw call in event browser, open the Mesh Viewer and click on the export icon. You can do this with almost any mesh input to a vertex shader drawn in a supported API.&#xD;&#xA;[![Export any mesh with renderdoc][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/O9wtV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28794" PostHistoryTypeId="2" PostId="9969" RevisionGUID="33b1a1e9-ca29-4a73-9c1e-04be16aacee7" CreationDate="2020-06-22T19:39:30.110" UserId="7035" Text="Is there a way to obtain a parametrized BRDF that smoothly interpolates between diffuse, glossy and mirror? For example, $\lambda = 0$ would be perfectly diffuse, $\lambda=0.5$ glossy and $\lambda = 1$ a perfect mirror. Linear interpolation seems very wrong here.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kMAIT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28795" PostHistoryTypeId="1" PostId="9969" RevisionGUID="33b1a1e9-ca29-4a73-9c1e-04be16aacee7" CreationDate="2020-06-22T19:39:30.110" UserId="7035" Text="BRDF that interpolates between diffuse, glossy and reflective?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28796" PostHistoryTypeId="3" PostId="9969" RevisionGUID="33b1a1e9-ca29-4a73-9c1e-04be16aacee7" CreationDate="2020-06-22T19:39:30.110" UserId="7035" Text="|pathtracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28797" PostHistoryTypeId="2" PostId="9970" RevisionGUID="13c9346e-53d5-4357-b517-53f5cc9799f9" CreationDate="2020-06-22T21:31:10.730" UserId="48" Text="Any microfacet BRDF with a roughness parameter will do something like this—for example using the GGX or Beckmann NDFs. When the roughness goes to zero it becomes a mirror; as roughness increases the reflection will be wider, and in the high-roughness limit should be essentially Lambert I think. Roughness is not necessarily limited to [0, 1] as roughness values higher than 1 are possible, but typically roughness = 1 will be very close to Lambert already.&#xD;&#xA;&#xD;&#xA;One thing to note about the roughness = 0 limit is that the NDF will become singular (a delta function), so will very likely break the shader code by producing infinite values or NaNs and such. So as a practical matter it might be necessary to special-case that, or clamp the roughness to some low minimum value like 0.0001." ContentLicense="CC BY-SA 4.0" />
  <row Id="28798" PostHistoryTypeId="2" PostId="9971" RevisionGUID="ada78496-a2c2-4587-bb13-6d9f3472c73d" CreationDate="2020-06-23T00:42:39.247" UserId="13370" Text="The reason why ray-tracing is often used for achieving as-realistic-as-possible wet appearance is their reflective behavior. A thin liquid film on the surface reflects photons like a mirror. If you target real-time rendering, you will have to fake the reflections (or rely on RTX :) There are two ways I can quickly think of: placing reflection probes in the scene using cube-maps or using screen space reflections.&#xD;&#xA;&#xD;&#xA;### Reflection probes with cube-maps&#xD;&#xA;&#xD;&#xA;* good for static scenes, you can pre-compute many of them&#xD;&#xA;* allow objects outside of the current viewing frustum to be seen in the mirrors&#xD;&#xA;* inaccurate due to limited number of probes&#xD;&#xA;&#xD;&#xA;There is a great [extensive tutorial](https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html) by Sébastien Lagarde on reflections which continues (what a coincidence) with [part B](https://www.fxguide.com/fxfeatured/game-environments-partb/) on wet surfaces and there is part C as well. Make sure to check them out!&#xD;&#xA;&#xD;&#xA;### Screen-space reflections&#xD;&#xA;&#xD;&#xA;* fine also for dynamic scenes&#xD;&#xA;* only objects in the current viewing frustum can be seen in the mirrors&#xD;&#xA;* accurate within the frustum&#xD;&#xA;&#xD;&#xA;Screen space reflections are explained as part of this [awesome series](https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html) by David Lettier.&#xD;&#xA;&#xD;&#xA;### Subsurface scattering&#xD;&#xA;&#xD;&#xA;Regarding the discussion on subsurface scattering, any organic tissue exposes this property. We just observe it the most on skin or leaves, but the same effect is observed inside the body. Just read section 3.3 of [this paper](http://www.cvg.ait.kyushu-u.ac.jp/papers/2014_2016/1-gridicp-cameraready.pdf):&#xD;&#xA;&#xD;&#xA;&gt; One significant casual effect under endoscopic environment is a strong subsurface scattering on the surface of internal organs.&#xD;&#xA;&#xD;&#xA;I suggest to use at least some [post-processing technique](https://therealmjp.github.io/posts/sss-intro/) for that." ContentLicense="CC BY-SA 4.0" />
  <row Id="28799" PostHistoryTypeId="52" PostId="9969" RevisionGUID="404dcaaa-6b4e-462f-ac44-a5b351702f20" CreationDate="2020-06-23T03:40:23.807" />
  <row Id="28800" PostHistoryTypeId="5" PostId="9971" RevisionGUID="ced70d21-66ea-4447-ab73-8878951fce42" CreationDate="2020-06-23T10:38:50.183" UserId="13370" Comment="Added a link to one of the basic papers." Text="The reason why ray-tracing is often used for achieving as-realistic-as-possible [wet appearance](http://graphics.ucsd.edu/~henrik/papers/egwr99/rendering_wet_materials_egwr99.pdf) is their reflective behavior. A thin liquid film on the surface reflects photons like a mirror. If you target real-time rendering, you will have to fake the reflections (or rely on RTX :) There are two ways I can quickly think of: placing reflection probes in the scene using cube-maps or using screen space reflections.&#xD;&#xA;&#xD;&#xA;### Reflection probes with cube-maps&#xD;&#xA;&#xD;&#xA;* good for static scenes, you can pre-compute many of them&#xD;&#xA;* allow objects outside of the current viewing frustum to be seen in the mirrors&#xD;&#xA;* inaccurate due to limited number of probes&#xD;&#xA;&#xD;&#xA;There is a great [extensive tutorial](https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html) by Sébastien Lagarde on reflections which continues (what a coincidence) with [part B](https://www.fxguide.com/fxfeatured/game-environments-partb/) on wet surfaces and there is part C as well. Make sure to check them out!&#xD;&#xA;&#xD;&#xA;### Screen-space reflections&#xD;&#xA;&#xD;&#xA;* fine also for dynamic scenes&#xD;&#xA;* only objects in the current viewing frustum can be seen in the mirrors&#xD;&#xA;* accurate within the frustum&#xD;&#xA;&#xD;&#xA;Screen space reflections are explained as part of this [awesome series](https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-reflection.html) by David Lettier.&#xD;&#xA;&#xD;&#xA;### Subsurface scattering&#xD;&#xA;&#xD;&#xA;Regarding the discussion on subsurface scattering, any organic tissue exposes this property. We just observe it the most on skin or leaves, but the same effect is observed inside the body. Just read section 3.3 of [this paper](http://www.cvg.ait.kyushu-u.ac.jp/papers/2014_2016/1-gridicp-cameraready.pdf):&#xD;&#xA;&#xD;&#xA;&gt; One significant casual effect under endoscopic environment is a strong subsurface scattering on the surface of internal organs.&#xD;&#xA;&#xD;&#xA;I suggest to use at least some [post-processing technique](https://therealmjp.github.io/posts/sss-intro/) for that." ContentLicense="CC BY-SA 4.0" />
  <row Id="28801" PostHistoryTypeId="2" PostId="9972" RevisionGUID="ccdd944b-668e-404d-a316-0e0f8773cf09" CreationDate="2020-06-23T12:12:11.673" UserId="10096" Text="Sometimes in CG literature a transformation is equated to a coordinate system change. This is fine as long as the transformation includes only a rotation and a translation. When scaling is involved, however, this seems like an incorrect interpretation. The problem is specifically with how lengths and angles are measured after the transformation. Angles and length are invariant to coordinate system change: $\langle a, b \rangle = \sum_{i,j}g_{ij}a^ib^j$. In graphics, this is often substituted with the expression valid only for orthonormal bases: $\langle a, b \rangle = \sum_{i}a_ib^i$, regardless of the supposed basis that $a,b$ are in (the index of $a$ is lowered as if the basis was orthonormal without involving the metric tensor). So while this makes sense as a transformation, I do not see how this is reconciled with the idea of a change of basis. Am I missing something, or is the interpretation wrong? (think of DX/GL's standard transformations between spaces in the rendering pipeline) " ContentLicense="CC BY-SA 4.0" />
  <row Id="28802" PostHistoryTypeId="1" PostId="9972" RevisionGUID="ccdd944b-668e-404d-a316-0e0f8773cf09" CreationDate="2020-06-23T12:12:11.673" UserId="10096" Text="Transformations and change of basis in CG" ContentLicense="CC BY-SA 4.0" />
  <row Id="28803" PostHistoryTypeId="3" PostId="9972" RevisionGUID="ccdd944b-668e-404d-a316-0e0f8773cf09" CreationDate="2020-06-23T12:12:11.673" UserId="10096" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28804" PostHistoryTypeId="2" PostId="9973" RevisionGUID="3e537b07-6652-4e3a-977c-c206cc5c9190" CreationDate="2020-06-23T16:58:44.563" UserId="13321" Text="Although microfacet bxdfs do this to some degree, a roughness of 1 is not really the same as a diffuse.&#xD;&#xA;&#xD;&#xA;I don't know of any single lobe which can properly blend between them. You would probably have to gradually ignore the reflection direction or include rays farther from it at a faster rate, which may make your glossy useless.&#xD;&#xA;&#xD;&#xA;Production renderer materials layer various lobes including a diffuse/specular so they can blend between them or combine them together.&#xD;&#xA;&#xD;&#xA;You can see how the arnolds blends thier lobes here:&#xD;&#xA;https://autodesk.github.io/standard-surface/" ContentLicense="CC BY-SA 4.0" />
  <row Id="28805" PostHistoryTypeId="2" PostId="9974" RevisionGUID="251a1a5b-c7a2-43f5-b625-edb61ce085ae" CreationDate="2020-06-23T18:21:18.097" UserId="13594" Text="This is how anti-aliasing works:&#xD;&#xA;&#xD;&#xA;1. render the outline in bilevel rendering at four times the size&#xD;&#xA;2. take the averages of each 4×4 block&#xD;&#xA;3. blend them with correct gamma between the foreground and background" ContentLicense="CC BY-SA 4.0" />
  <row Id="28806" PostHistoryTypeId="5" PostId="9918" RevisionGUID="67a5de25-7c7c-4844-bea1-16e8c5214864" CreationDate="2020-06-23T21:43:49.830" UserId="7462" Comment="added 155 characters in body" Text="In section 4.2 of this paper:&#xD;&#xA;&#xD;&#xA;http://cseweb.ucsd.edu/~ravir/274/15/papers/a209-xu.pdf&#xD;&#xA;&#xD;&#xA;Xu et al approximate the product of 2 anisotropic Gaussian distributions. I want to know if someone has found not an approximation but THE solution to what the resulting ASG distribution is after taking the product.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;The goal is to either show (or prove it's not possible) that given 2 arbitrary ASG's their product is a third ASG with specified lobe $\bar z$" ContentLicense="CC BY-SA 4.0" />
  <row Id="28807" PostHistoryTypeId="2" PostId="9975" RevisionGUID="fbb95550-5473-46e4-8085-f3f67abaf2ca" CreationDate="2020-06-24T10:41:56.160" UserId="11412" Text="Okay, so I'm currently using the IAGetVertexBuffers() method and I'd like to loop through some of the returned buffers to verify the contents. &#xD;&#xA;&#xD;&#xA;However, I'm kind of new to DirectX and C++ in general. I tried using a a simple C++ 11 loop:&#xD;&#xA;&#xD;&#xA;    for (const auto&amp; verts : veBuffer) {&#xD;&#xA;            std::cout &lt;&lt; verts &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;But I get an error saying this statement requires a suitable begin statement. Any suggestions would be appreciated at this point." ContentLicense="CC BY-SA 4.0" />
  <row Id="28808" PostHistoryTypeId="1" PostId="9975" RevisionGUID="fbb95550-5473-46e4-8085-f3f67abaf2ca" CreationDate="2020-06-24T10:41:56.160" UserId="11412" Text="How do you loop through the contents of a buffer in DX11?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28809" PostHistoryTypeId="3" PostId="9975" RevisionGUID="fbb95550-5473-46e4-8085-f3f67abaf2ca" CreationDate="2020-06-24T10:41:56.160" UserId="11412" Text="|c++|directx11|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28810" PostHistoryTypeId="2" PostId="9976" RevisionGUID="ec96a862-ef1e-4292-9ef8-ac7c831881ce" CreationDate="2020-06-24T12:55:58.213" UserDisplayName="user9485" Text="Consider $f(v) := S(v;z_1)\cdot S(v;z_2)$ with $z_1=z_2=&lt;1,0,0&gt;$. Then&#xD;&#xA;$$f(v) = \max(v_1,0)\cdot\max(v_1,0) = 0, \qquad \text{ if } v_1&lt;0, $$&#xD;&#xA;$$f(v) = \max(v_1,0)\cdot\max(v_1,0) = v_1^2 \qquad \text{ if } v_1\ge 0. $$&#xD;&#xA;&#xD;&#xA;We want to find a $\tilde z$ such that $f(v) \stackrel{!}{=} S(v;\tilde z) = \max(v\cdot\tilde z,0)$ for all unit vectors $v$. But $v=&lt;0,\pm 1,0&gt;$ implies $\tilde z_2 = 0$ and similarly $v=&lt;0,0,\pm 1&gt;$ implies $\tilde z_3=0$. Consequently, $S(v;\tilde z) = \max(v_1 \tilde z_1, 0)$ and it is not possible to choose $\tilde z_1$ such that&#xD;&#xA;$$\max(v_1\tilde z_1,0) = f(v)$$&#xD;&#xA;for all unit vectors $v$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28816" PostHistoryTypeId="2" PostId="9978" RevisionGUID="d40fb487-fad2-4539-953d-ff97d15ba22d" CreationDate="2020-06-25T08:32:33.937" UserId="13601" Text="My understanding is:&#xD;&#xA;&#xD;&#xA; 1. the 'framebuffer' in OpenGL is a collection of buffers: many (due to swapping or stereo rendering) color buffers, (only one?) z-buffer and (only one?) stencil buffer;&#xD;&#xA; 2. each OpenGL application has a 'default framebuffer', but can have more 'framebuffer objects';&#xD;&#xA; 3. a 'compositing window manager' aka 'compositor' only cares about an application's current front color buffer of its 'default framebuffer'. The compositor calls this buffer 'off screen buffer'.&#xD;&#xA; 4. the compositor reads all applications' 'off screen buffers' and composites them onto a single image called screen buffer' aka 'video buffer' aka 'regen(eration) buffer';&#xD;&#xA; 5. a display controller will read (scan?) the 'screen buffer' and convert it to a signal to be sent to the physical screen.&#xD;&#xA;&#xD;&#xA;Main question:&#xD;&#xA;&#xD;&#xA;Can it be (eg. if I run a video game full-screen) that the compositor could simply declare the application's off-screen buffer the same as its 'screen buffer' so that the same location in memory that fragments had their colors originally blended onto will actually be the location the display controller will read from?&#xD;&#xA;I.e. OpenGL will render to some area in either VRAM or RAM and without coincidence this same location will be read by the display controller even after any sort of compositor stage.&#xD;&#xA;&#xD;&#xA;Additionally:&#xD;&#xA;- Does the compositor designate the 'off screen buffer' for the application (or multiple locations for double/triple buffering or stereo) and it's up to the application to fill that area in memory and &quot;ring the compositor&quot; when its ready or&#xD;&#xA;- does the application create the buffer and the compositor is only told where to read from (eg. the app's OpenGL draws to a back buffer, designates it as the front and tells the compositor to read it)?&#xD;&#xA;- or is it a mix of the two?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28817" PostHistoryTypeId="1" PostId="9978" RevisionGUID="d40fb487-fad2-4539-953d-ff97d15ba22d" CreationDate="2020-06-25T08:32:33.937" UserId="13601" Text="Can the framebuffer in OpenGL jargon or its color buffer end up being the one and the same memory location as the one scanned by a display controller?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28818" PostHistoryTypeId="3" PostId="9978" RevisionGUID="d40fb487-fad2-4539-953d-ff97d15ba22d" CreationDate="2020-06-25T08:32:33.937" UserId="13601" Text="|opengl|buffers|frame-buffer|compositing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28819" PostHistoryTypeId="50" PostId="6085" RevisionGUID="a7331a4d-91fa-4c85-ae43-f890aa542f4d" CreationDate="2020-06-26T03:03:45.330" UserId="-1" />
  <row Id="28820" PostHistoryTypeId="50" PostId="6350" RevisionGUID="223f156e-3ea3-40b3-8dc7-4f99d851a523" CreationDate="2020-06-26T04:07:25.713" UserId="-1" />
  <row Id="28821" PostHistoryTypeId="2" PostId="9979" RevisionGUID="29803082-7b8a-4ede-b591-4d9bd124cc07" CreationDate="2020-06-26T07:57:59.233" UserId="11344" Text="There are a couple of issues.  First you need to make sure that `veBuffer` has the correct type, so that probably means you need to cast it to *pointer to vertex*:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const auto vertices = reinterpret_cast&lt;const Vertex*&gt;(reBuffer);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Second a range-based `for`-loop needs to know where the range ends and giving it a raw pointer does not provide that information, so you cannot use it here.  Instead you will need to know how many vertices there are and use a normal `for`-loop:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const size_t numVerts = 32;&#xD;&#xA;for (size_t i = 0; i &lt; numVerts; ++i) {&#xD;&#xA;    const Vertex&amp; vert = vertices[i];&#xD;&#xA;    ...&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="28824" PostHistoryTypeId="2" PostId="9980" RevisionGUID="9b007783-9bfd-4854-a2fa-2751e65c08b6" CreationDate="2020-06-26T17:40:15.377" UserId="48" Text="Yes. This is one of the things that &quot;fullscreen exclusive&quot; mode would do for you: it enables the application's swap buffers (front/back default framebuffers) to be directly scanned out by the GPU's display engine, without needing to go through a compositor first, saving a little bit of performance.&#xD;&#xA;&#xD;&#xA;Nowadays there is also support for &quot;borderless windowed fullscreen&quot; (see [Fullscreen Optimizations](https://devblogs.microsoft.com/directx/demystifying-full-screen-optimizations/) for Windows 10 for instance, though I expect other OSes have similar functionality). This is a mode where you still go through the compositor, but the compositor has a shortcut method when it detects that your app is covering the full screen with no other windows rendering on top of it. In that case it can skip the compositing steps and scan out directly from your framebuffers, while retaining the ability to seamlessly switch back to compositing mode if another window should pop up (such as an overlay, or if you Alt+Tab away from the game, etc.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28825" PostHistoryTypeId="5" PostId="9980" RevisionGUID="009a3ac9-5166-492b-826a-93f2b67f8892" CreationDate="2020-06-26T17:47:51.697" UserId="48" Comment="added 1060 characters in body" Text="&gt; Can it be (eg. if I run a video game full-screen) that the compositor could simply declare the application's off-screen buffer the same as its 'screen buffer'&#xD;&#xA;&#xD;&#xA;Yes. This is one of the things that &quot;fullscreen exclusive&quot; mode would do for you: it enables the application's swap buffers (front/back default framebuffers) to be directly scanned out by the GPU's display engine, without needing to go through a compositor first, saving a little bit of performance.&#xD;&#xA;&#xD;&#xA;Nowadays there is also support for &quot;borderless windowed fullscreen&quot; (see [Fullscreen Optimizations](https://devblogs.microsoft.com/directx/demystifying-full-screen-optimizations/) for Windows 10 for instance, though I expect other OSes have similar functionality). This is a mode where you still go through the compositor, but the compositor has a shortcut method when it detects that your app is covering the full screen with no other windows rendering on top of it. In that case it can skip the compositing steps and scan out directly from your swap buffers, while retaining the ability to seamlessly switch back to compositing mode if another window should pop up (such as an overlay, or if you Alt+Tab away from the game, etc.)&#xD;&#xA;&#xD;&#xA;&gt; Does the compositor designate the 'off screen buffer' for the application&#xD;&#xA;&#xD;&#xA;Also yes. When you set up an OpenGL context (or any other graphics API context) your app will request the number and format of swap buffers it wants (subject to the choices offered by the OS/driver); then the OS/driver will give you the buffers, and you render into them. You can create your own framebuffers as well, such as depth/stencil buffers or other offscreen buffers for whatever purpose, but ultimately your app will need to put the image you want to show up on the screen into the provided swap buffers. The buffers will be set up so the compositor can also access them. When you do a glSwapBuffers call, you're informing the OS/compositor that you finished a new frame and asking it to please show that on the screen (either by scanning it out directly or by including it in the next compositor frame)." ContentLicense="CC BY-SA 4.0" />
  <row Id="28828" PostHistoryTypeId="50" PostId="9199" RevisionGUID="e0c87e2d-bc93-4eb5-b130-e9e36b9513f4" CreationDate="2020-06-27T00:05:40.757" UserId="-1" />
  <row Id="28829" PostHistoryTypeId="50" PostId="9189" RevisionGUID="652e3f88-5618-4ac4-9785-2bbf8b9561d7" CreationDate="2020-06-27T05:01:50.190" UserId="-1" />
  <row Id="28830" PostHistoryTypeId="2" PostId="9981" RevisionGUID="b85e149b-2a95-4361-b3f3-7f84dc734970" CreationDate="2020-06-27T06:28:30.160" UserId="48" Text="You're correct, we don't usually worry about pulling the inner product through a change of basis in graphics. As a practical matter, calculations that depend on angles and distances, such as lighting and shading, are always done in world space or in a space orthonormally related to it (e.g. camera space).&#xD;&#xA;&#xD;&#xA;The place where non-orthonormal transformations show up is usually in local-to-world transforms of meshes—most frequently with skeletal animation, where things get deformed, or where bones are set up with non-orthonormal coordinates for rigging/animation reasons. However in those instances we are always bringing the vertices, normals, etc into world space or camera space to process. We neither push back the world inner product into the local spaces, nor do we want to pull a locally defined inner product into world space, as neither of those is really useful for the typical kinds of things we need to do.&#xD;&#xA;&#xD;&#xA;(And for the normals, we _do_ know how to use the inverse transpose matrix to transform those properly, thank goodness!)&#xD;&#xA;&#xD;&#xA;The other big non-orthonormal transformation in graphics is the projection matrix, but again, we don't really ever want to use the inner product in post-projective space, so the issue doesn't really arise. We just keep all our inner product-ing in world space." ContentLicense="CC BY-SA 4.0" />
  <row Id="28831" PostHistoryTypeId="2" PostId="9982" RevisionGUID="81e1c7de-8954-437b-88c0-780815b89e1b" CreationDate="2020-06-27T19:14:14.580" UserId="7462" Text="I am reading the 1987 paper on Geodesics on polyhedra and I am confused on something.&#xD;&#xA;&#xD;&#xA;The paper states:&#xD;&#xA;&#xD;&#xA;&gt; If $I1==NIL$, the channel is simply that part of $f’$ to the left of $\beta_2c_2$; and if&#xD;&#xA;&gt; $I2==NIL$, the channel is that to the right of $\beta_1c_1$.&#xD;&#xA;&#xD;&#xA;&quot;Right&quot; and &quot;left&quot; are pretty meaningless terms. So far I have at least 3 interpretations of the areas they mean:&#xD;&#xA;&#xD;&#xA;Orthogonal projection onto the opposite edge:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Angular projection based on some angular parameter:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Or the entire face.&#xD;&#xA;&#xD;&#xA;All of these can be thought of as &quot;the left&quot; of the red segment. Which one is the one the authors meant?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sWPxd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/8VCwU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28832" PostHistoryTypeId="1" PostId="9982" RevisionGUID="81e1c7de-8954-437b-88c0-780815b89e1b" CreationDate="2020-06-27T19:14:14.580" UserId="7462" Text="MMP Geodesic algorithm I need clarification" ContentLicense="CC BY-SA 4.0" />
  <row Id="28833" PostHistoryTypeId="3" PostId="9982" RevisionGUID="81e1c7de-8954-437b-88c0-780815b89e1b" CreationDate="2020-06-27T19:14:14.580" UserId="7462" Text="|computational-geometry|mesh|geometry|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28835" PostHistoryTypeId="50" PostId="9267" RevisionGUID="f00cb22b-1046-42fe-84ab-5ef9c452b125" CreationDate="2020-06-28T08:05:35.433" UserId="-1" />
  <row Id="28836" PostHistoryTypeId="2" PostId="9984" RevisionGUID="6c8e8a80-9c51-4fc3-9a96-db2f2194b307" CreationDate="2020-06-28T09:48:25.183" UserId="13618" Text="In math, geometry and physics it is common practice to use the coordinates $(u,v)$ to represent an arbitrary parameterizations, including those of a [surface][1] in a 3d Euclidean space. Since the coordinates of the parameterisation might be arbitrary (it could an angle, or a function of the Euclidean coordinates $(x,y,z)$, or something else), it is helpful to distinguish them from the coordinates used to represent the wider Euclidean space in which the surface exists.&#xD;&#xA;&#xD;&#xA;The $(u,v)$-notation caught on in computer graphics for the same reason: it clarifies that the surface that your texture is mapped onto is not necessarily aligned with the world space (or view) coordinates, but is a parameterisation of that space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Surface_(mathematics)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28837" PostHistoryTypeId="5" PostId="9984" RevisionGUID="9d4059ed-d282-4a38-a2d6-994e235ad944" CreationDate="2020-06-28T13:14:36.917" UserId="13618" Comment="deleted 1 character in body" Text="In math, geometry and physics it is common practice to use the coordinates $(u,v)$ to represent an arbitrary parameterization, including those of a [surface][1] in a 3d Euclidean space. Since the coordinates of the parameterisation might be arbitrary (it could an angle, or a function of the Euclidean coordinates $(x,y,z)$, or something else), it is helpful to distinguish them from the coordinates used to represent the wider Euclidean space in which the surface exists.&#xD;&#xA;&#xD;&#xA;The $(u,v)$-notation caught on in computer graphics for the same reason: it clarifies that the surface that your texture is mapped onto is not necessarily aligned with the world space (or view space) coordinates, but is a parameterisation of a surface in that space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Surface_(mathematics)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28838" PostHistoryTypeId="5" PostId="9984" RevisionGUID="e465867c-c413-40b1-ba37-4e9d0c208713" CreationDate="2020-06-28T13:19:58.030" UserId="13618" Comment="deleted 1 character in body" Text="In math, geometry and physics it is common practice to use the coordinates $(u,v)$ to represent an arbitrary parameterization, including those of a [surface][1] in a 3d Euclidean space. Since the coordinates of the parameterisation might be arbitrary (it could be an angle, or a function of the Euclidean coordinates $(x,y,z)$, or something else), it is helpful to distinguish them from the coordinates used to represent the wider Euclidean space in which the surface exists.&#xD;&#xA;&#xD;&#xA;The $(u,v)$-notation caught on in computer graphics for the same reason: it clarifies that the coordinates used to index into your texture do not necessarily align with the world space (or view space) coordinates $(x,y,z)$, but is an index into a parameterisation of a surface in that space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Surface_(mathematics)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28841" PostHistoryTypeId="50" PostId="9875" RevisionGUID="895a4b86-9c62-4655-92d6-67cc584adc07" CreationDate="2020-06-29T02:02:15.193" UserId="-1" />
  <row Id="28846" PostHistoryTypeId="2" PostId="9986" RevisionGUID="802ee0c4-c198-4ec7-84bb-8e78ed062590" CreationDate="2020-06-29T15:20:17.557" UserId="7035" Text="When implementing explicit light sampling, I am separating the monte-carlo approximation to two parts &#xD;&#xA;&#xD;&#xA;$$\frac{1}{N+M}(\sum^N \text{direct} + \sum^M \text{indirect})$$&#xD;&#xA;&#xD;&#xA;$$\text{direct} = \frac{\text{bsdf} \times C \times cos(\theta)}{p}$$&#xD;&#xA;&#xD;&#xA;I am confused as how to obtain $p$ for direct lightning. &#xD;&#xA;&#xD;&#xA;A solution was presented here: &lt;https://computergraphics.stackexchange.com/questions/4288/path-weight-for-direct-light-sampling&gt;&#xD;&#xA;&#xD;&#xA;$$\frac{A}{r^2} (N_\text{light} \cdot -L)$$&#xD;&#xA;&#xD;&#xA;Where does this come from?  I'm asking for a reference or a derivation. Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28847" PostHistoryTypeId="1" PostId="9986" RevisionGUID="802ee0c4-c198-4ec7-84bb-8e78ed062590" CreationDate="2020-06-29T15:20:17.557" UserId="7035" Text="Probability density for explicit light sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="28848" PostHistoryTypeId="3" PostId="9986" RevisionGUID="802ee0c4-c198-4ec7-84bb-8e78ed062590" CreationDate="2020-06-29T15:20:17.557" UserId="7035" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28849" PostHistoryTypeId="5" PostId="9986" RevisionGUID="fa6e51cc-05be-46f1-a33d-bffba3ff4cb3" CreationDate="2020-06-29T15:26:14.833" UserId="7035" Comment="added 61 characters in body" Text="When implementing explicit light sampling, I am separating the monte-carlo approximation to two parts &#xD;&#xA;&#xD;&#xA;$$\frac{1}{N+M}(\sum^N \text{direct} + \sum^M \text{indirect})$$&#xD;&#xA;&#xD;&#xA;$$\text{direct} = \frac{\text{bsdf} \times C \times cos(\theta)}{p}$$&#xD;&#xA;&#xD;&#xA;I am confused as how to obtain $p$ for direct lightning.  My light source is an arbitrary triangularized mesh.&#xD;&#xA;&#xD;&#xA;A solution was presented here: &lt;https://computergraphics.stackexchange.com/questions/4288/path-weight-for-direct-light-sampling&gt;&#xD;&#xA;&#xD;&#xA;$$\frac{A}{r^2} (N_\text{light} \cdot -L)$$&#xD;&#xA;&#xD;&#xA;Where does this come from?  I'm asking for a reference or a derivation. Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28850" PostHistoryTypeId="5" PostId="9986" RevisionGUID="c3b8df8d-a7a0-4db6-bd0d-4383b6746cac" CreationDate="2020-06-29T15:33:14.167" UserId="7035" Comment="added 50 characters in body" Text="When implementing explicit light sampling, I am separating the monte-carlo approximation to two parts &#xD;&#xA;&#xD;&#xA;$$\frac{1}{N+M}(\sum^N \text{direct} + \sum^M \text{indirect})$$&#xD;&#xA;&#xD;&#xA;$$\text{direct} = \frac{\text{bsdf} \times C \times cos(\theta)}{p}$$&#xD;&#xA;&#xD;&#xA;I am confused as how to obtain $p$ for direct lightning.  My light source is an arbitrary triangularized mesh and I am sampling random points from it's surface.&#xD;&#xA;&#xD;&#xA;A solution was presented here: &lt;https://computergraphics.stackexchange.com/questions/4288/path-weight-for-direct-light-sampling&gt;&#xD;&#xA;&#xD;&#xA;$$\frac{A}{r^2} (N_\text{light} \cdot -L)$$&#xD;&#xA;&#xD;&#xA;Where does this come from?  I'm asking for a reference or a derivation. Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28851" PostHistoryTypeId="2" PostId="9987" RevisionGUID="090e4791-f6b4-48ce-af18-deb6364d5d0b" CreationDate="2020-06-29T16:54:17.107" UserId="10096" Text="It comes from the relation between the area formulation and the solid angle formulation of the rendering equation: $d\omega = \frac{\cos\theta_L}{r^2}dA$:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;https://arxiv.org/abs/1205.4447" ContentLicense="CC BY-SA 4.0" />
  <row Id="28852" PostHistoryTypeId="2" PostId="9988" RevisionGUID="37d28bda-90d3-47c9-ab20-62af31cda5a6" CreationDate="2020-06-29T17:56:02.507" UserId="13625" Text="I am working on a small simulation software which has a 3D Renderer that is using OpenGL. I render objects to the screen as triangle meshes. To be able to select the triangles on the screen, I have implemented the Möller–Trumbore ray-triangle intersection algorithm. The algorithm works fine. However, I have another problem. My triangles are not static in the world. When I change the location of the triangle on the screen, I have to change the vertices of the triangle but I don't know how to do it mathematically. Is there a way to use this algorithm for dynamic objects?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28853" PostHistoryTypeId="1" PostId="9988" RevisionGUID="37d28bda-90d3-47c9-ab20-62af31cda5a6" CreationDate="2020-06-29T17:56:02.507" UserId="13625" Text="Dynamic Ray-Triangle Intersection" ContentLicense="CC BY-SA 4.0" />
  <row Id="28854" PostHistoryTypeId="3" PostId="9988" RevisionGUID="37d28bda-90d3-47c9-ab20-62af31cda5a6" CreationDate="2020-06-29T17:56:02.507" UserId="13625" Text="|opengl|c++|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28855" PostHistoryTypeId="5" PostId="9988" RevisionGUID="07eefebe-386a-4e28-bae8-4f71a64c483a" CreationDate="2020-06-29T18:21:40.340" UserId="13625" Comment="added 23 characters in body" Text="I am working on a small simulation software which has a 3D Renderer that is using OpenGL. I render objects to the screen as triangle meshes. To be able to select the triangles on the screen, I have implemented the Möller–Trumbore ray-triangle intersection algorithm. The algorithm works fine. However, I have another problem. My triangles are not static in the world. When I change the location of the triangle on the screen, I have to change the input vertices of the triangle in the algorithm but I don't know how to do it mathematically. Is there a way to use this algorithm for dynamic objects?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28858" PostHistoryTypeId="2" PostId="9989" RevisionGUID="5467c569-156f-45f0-81a9-1bba2757d5a3" CreationDate="2020-06-30T11:08:14.570" UserId="13632" Text="I have an isosurface/mesh (generated via marching cubes) of a micro-CT scan. Originally the surface looks very noisy, which becomes prevalent when the mean curvature is visualized:&#xD;&#xA;&#xD;&#xA;[![unedited surface][1]][1]&#xD;&#xA;&#xD;&#xA;To reduce the noise I've applied Gaussian smoothing to the imagedata and regenerated the mesh. This time, artificial looking rings appear:&#xD;&#xA;&#xD;&#xA;[![surface after smoothing][2]][2]&#xD;&#xA;&#xD;&#xA;I would like to reduce these circles/rings/terracing artifacts to obtain a more smooth distribution of the curvature values. &#xD;&#xA;&#xD;&#xA;I was wondering if anybody would know the name of this problem since I'm struggling to find anything similar online. All help is appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xa4aIm.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/NIsalm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28859" PostHistoryTypeId="1" PostId="9989" RevisionGUID="5467c569-156f-45f0-81a9-1bba2757d5a3" CreationDate="2020-06-30T11:08:14.570" UserId="13632" Text="Artificial rings in mean curvature of mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="28860" PostHistoryTypeId="3" PostId="9989" RevisionGUID="5467c569-156f-45f0-81a9-1bba2757d5a3" CreationDate="2020-06-30T11:08:14.570" UserId="13632" Text="|mesh|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28861" PostHistoryTypeId="4" PostId="9989" RevisionGUID="0b7db2a3-dbea-48a7-b161-2a3980c7baee" CreationDate="2020-06-30T12:17:38.423" UserId="13632" Comment="edited title" Text="Reducing artificial rings in mean curvature of mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="28862" PostHistoryTypeId="2" PostId="9990" RevisionGUID="51526d02-43b5-49f9-bc0f-84223828b060" CreationDate="2020-06-30T19:26:45.777" UserId="10096" Text="There are 2 ways to go about intersecting the triangle. Let the vertices of the triangle have positions $v_1, v_2, v_3$. Let the ray have origin $o$ and direction $d$. Let the model (4x4) matrix be $M$. &#xD;&#xA;&#xD;&#xA;To find the new vertex coordinates one extends the positions with a 1 (to allow for translations) and multiplies by the model matrix. Let $u_i = (v_i.x, v_i.y, v_i.z, 1)$ then $w_i = Mu_i'$. The resulting vertex positions are: $v_i' = (w_i.x, w_i.y, w_i.z)$.&#xD;&#xA;&#xD;&#xA;The other option is to transform the ray with the inverse matrix $M^{-1}$ and intersect with the non-transformed triangle. To achieve this extend $o$ with a 4th coord of 1 (to account for translation) and extend $d$ with a 4th coord of 0 (to ignore translation) then multiply both with $M^{-1}$:&#xD;&#xA;$$o' = M^{-1}(o.x, o.y, o.z, 1)$$&#xD;&#xA;$$d' = M^{-1}(d.x, d.y, d.z, 0)$$&#xD;&#xA;Drop the 4th coordinate of $o'$ and $d'$ then intersect with the triangle formed by $v_1, v_2, v_3$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28863" PostHistoryTypeId="5" PostId="9990" RevisionGUID="a1d6870d-7d67-46eb-9717-9e728b7c8474" CreationDate="2020-06-30T19:55:47.020" UserId="10096" Comment="added 12 characters in body" Text="There are 2 ways to go about intersecting the triangle. Let the vertices of the triangle have positions $v_1, v_2, v_3$. Let the ray have origin $o$ and direction $d$. Let the model (4x4) matrix be $M$. &#xD;&#xA;&#xD;&#xA;To find the new vertex coordinates one extends the positions with a 1 (to allow for translations) and multiplies by the model matrix. Let $u_i = (v_{i,x}, v_{i,y}, v_{i,z}, 1)$ then $w_i = Mu_i'$. The resulting vertex positions are: $v_i' = (w_{i,x}, w_{i,y}, w_{i,z})$.&#xD;&#xA;&#xD;&#xA;The other option is to transform the ray with the inverse matrix $M^{-1}$ and intersect with the non-transformed triangle. To achieve this extend $o$ with a 4th coord of 1 (to account for translation) and extend $d$ with a 4th coord of 0 (to ignore translation) then multiply both with $M^{-1}$:&#xD;&#xA;$$o' = M^{-1}(o_x, o_y, o_z, 1)$$&#xD;&#xA;$$d' = M^{-1}(d_x, d_y, d_z, 0)$$&#xD;&#xA;Drop the 4th coordinate of $o'$ and $d'$ then intersect with the triangle formed by $v_1, v_2, v_3$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28864" PostHistoryTypeId="5" PostId="9947" RevisionGUID="4a10f7f7-c384-48ff-a976-ae3edf181635" CreationDate="2020-07-01T09:29:54.890" UserId="209" Comment="Added link to the thesis" Text="This is not a definitive answer, but it is generally accepted that [Ed Catmull][1] introduced Texture Mapping in his 1974 thesis, &quot;[*A SUBDIVISION ALGORITHM FOR COMPUTER DISPLAY OF CURVED SURFACES*][2]&quot; &#xD;&#xA;&#xD;&#xA;In that, he uses (U,V) to access the image data (see the page labeled 36 in the above)&#xD;&#xA;&#xD;&#xA;&gt; MAPPING&lt;br&gt;&#xD;&#xA; Photographs, drawings, or any picture can be mapped onto bivariate patches. This&#xD;&#xA; is one of the most interesting consequences of the patch splitting algorithm. It&#xD;&#xA;gives a method for putting texture, drawings, or photographs onto surfaces....&lt;br&gt;&lt;br&gt;&#xD;&#xA;...If a photograph is scanned in at a resolution of x times y then every&#xD;&#xA;element can be referenced by u·x and v·y where 0&lt;=u,v&lt;=1. In general, one could think of the intensity as a function l(u,v) where I references a picture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I believe this thesis also introduced the concept of the Z-Buffer (Page 32)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Edwin_Catmull&#xD;&#xA;  [2]: https://ia801307.us.archive.org/2/items/DTIC_ADA004968/DTIC_ADA004968.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28865" PostHistoryTypeId="2" PostId="9991" RevisionGUID="03b516e2-5386-4915-9b54-9d445eeb02c2" CreationDate="2020-07-01T12:29:06.633" UserId="13637" Text="Recently I've been looking at Vulkan, and one thing that I noticed is that the application is responsible for choosing which buffer to render to in the case of multiple buffering.&#xD;&#xA;&#xD;&#xA;This got me thinking: since one of the benefits of multiple buffering is that the GPU can start rendering the next frame before the previous one is finished, is it worth it to create more offscreen buffers as well, like the G-Buffers or the HDR color buffers (especially in the older APIs like OpenGL and D3D11)? Will it have performance benefits? Is this common practice, or totally dumb?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28866" PostHistoryTypeId="1" PostId="9991" RevisionGUID="03b516e2-5386-4915-9b54-9d445eeb02c2" CreationDate="2020-07-01T12:29:06.633" UserId="13637" Text="OpenGL/D3D11 offscreen render multiple buffering" ContentLicense="CC BY-SA 4.0" />
  <row Id="28867" PostHistoryTypeId="3" PostId="9991" RevisionGUID="03b516e2-5386-4915-9b54-9d445eeb02c2" CreationDate="2020-07-01T12:29:06.633" UserId="13637" Text="|opengl|vulkan|directx11|directx|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28868" PostHistoryTypeId="5" PostId="9990" RevisionGUID="b49dc603-caec-41d3-83ee-4695079a5c21" CreationDate="2020-07-01T18:56:44.187" UserId="10096" Comment="typo $u_i'$" Text="There are 2 ways to go about intersecting the triangle. Let the vertices of the triangle have positions $v_1, v_2, v_3$. Let the ray have origin $o$ and direction $d$. Let the model (4x4) matrix be $M$. &#xD;&#xA;&#xD;&#xA;To find the new vertex coordinates one extends the positions with a 1 (to allow for translations) and multiplies by the model matrix. Let $u_i = (v_{i,x}, v_{i,y}, v_{i,z}, 1)$ then $w_i = Mu_i$. The resulting vertex positions are: $v_i' = (w_{i,x}, w_{i,y}, w_{i,z})$.&#xD;&#xA;&#xD;&#xA;The other option is to transform the ray with the inverse matrix $M^{-1}$ and intersect with the non-transformed triangle. To achieve this extend $o$ with a 4th coord of 1 (to account for translation) and extend $d$ with a 4th coord of 0 (to ignore translation) then multiply both with $M^{-1}$:&#xD;&#xA;$$o' = M^{-1}(o_x, o_y, o_z, 1)$$&#xD;&#xA;$$d' = M^{-1}(d_x, d_y, d_z, 0)$$&#xD;&#xA;Drop the 4th coordinate of $o'$ and $d'$ then intersect with the triangle formed by $v_1, v_2, v_3$." ContentLicense="CC BY-SA 4.0" />
  <row Id="28871" PostHistoryTypeId="2" PostId="9992" RevisionGUID="9db75a55-3f45-4b5f-a75d-6c2d6cd1bb85" CreationDate="2020-07-02T09:58:24.150" UserId="13639" Text="I've seen two diffrent perspective projection matrix being used but i want to know which one of these are the best i think that they both output the same but i'm not sure so if anyone can help me select one to use i would gladly appreciate it&#xD;&#xA;&#xD;&#xA;[![perspective projection matrix 1][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![perspective projection matrix 2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gVMit.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ycuEv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28872" PostHistoryTypeId="1" PostId="9992" RevisionGUID="9db75a55-3f45-4b5f-a75d-6c2d6cd1bb85" CreationDate="2020-07-02T09:58:24.150" UserId="13639" Text="Which perspective projection matrix to use" ContentLicense="CC BY-SA 4.0" />
  <row Id="28873" PostHistoryTypeId="3" PostId="9992" RevisionGUID="9db75a55-3f45-4b5f-a75d-6c2d6cd1bb85" CreationDate="2020-07-02T09:58:24.150" UserId="13639" Text="|matrix|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28875" PostHistoryTypeId="50" PostId="8888" RevisionGUID="610adafa-22e7-4740-8dc9-4eedc09188b8" CreationDate="2020-07-02T15:03:05.293" UserId="-1" />
  <row Id="28876" PostHistoryTypeId="2" PostId="9994" RevisionGUID="3420af02-ae89-45ec-bf61-641576b0d408" CreationDate="2020-07-02T16:41:19.427" UserId="13095" Text="Even though you can find multiple slightly different formulations for the perspective matrix on the internet, they all do more or less the same thing. They project everything inside a space with the shape of a truncated pyramid (your view frustum) into a space with the shape of a quad and a defined value range (clip space). &#xD;&#xA;&#xD;&#xA;Most differences are related to how you define the shape of your frustum. For example, your first matrix uses a height, a width, and an angle together with z-far and z-near value. The second one uses just an x- and y-FOV and the z-far and z-near values to describe the shape of the frustum. This explains the differences in the upper left section. &#xD;&#xA;&#xD;&#xA;So what about the lower right section? One big issue here is, that you can choose to use column or row vectors for your vertices/points. Column vectors are multiplied on the right-hand side and row vectors on the left-hand side. The choice you make determines if you have to transpose (switch columns and rows) your matrix or not. The matrices you presented are just targetting different vector representations. I can't tell you without testing/rereading which one is meant for which representation, but if you transpose one of them, they start looking quite similar. &#xD;&#xA;&#xD;&#xA;There are still some other minor differences like varying signs, different factors, or a missing addition. &#xD;&#xA;The derivation of your second matrix can be found [here](http://www.codinglabs.net/article_world_view_projection_matrix.aspx).&#xD;&#xA;I can't tell you exactly where those small differences in the first matrix come from, but you can find some possible explanations in [this link](https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/building-basic-perspective-projection-matrix) (Have a look into the &quot;Are There Different Ways of Building this Matrix?&quot; section).&#xD;&#xA;Another good read is [this link here](http://www.songho.ca/opengl/gl_projectionmatrix.html). &#xD;&#xA;&#xD;&#xA;Which matrix is &quot;correct&quot; depends on how your Graphic API defines its coordinate systems and it's clip space (For OpenGL - you can take the one from the last link I provided). However, there is no &quot;best&quot; choice because they all do more or less the same. Unless you have no special needs for your program (depth precision) or other fancy ideas I can't think of now, just pick the one suited for your API with the inputs (FOV vs width+height+angle) that you like most and start having fun. ;)" ContentLicense="CC BY-SA 4.0" />
  <row Id="28877" PostHistoryTypeId="5" PostId="1846" RevisionGUID="cf9b380d-bd6a-4bbc-84ae-266151b59103" CreationDate="2020-07-03T07:35:30.447" UserId="5778" Comment="grammar corrections, image resized" Text="&#xD;&#xA;[![ray tracing pseudocode][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KbrW7m.png&#xD;&#xA;&#xD;&#xA;I don't understand the `if (depth &gt; MAX) return Black` part. Does it have something to do with shadows, because in other algorithms they shoot a shadow ray towards the light source to check for shadows but they don't have it here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28878" PostHistoryTypeId="24" PostId="1846" RevisionGUID="cf9b380d-bd6a-4bbc-84ae-266151b59103" CreationDate="2020-07-03T07:35:30.447" Comment="Proposed by 5778 approved by 209, 2359 edit id of 522" ContentLicense="CC BY-SA 4.0" />
  <row Id="28879" PostHistoryTypeId="2" PostId="9995" RevisionGUID="b6259983-d3f8-48e7-ab62-f5944ee330cd" CreationDate="2020-07-03T14:43:10.617" UserId="13639" Text="As the title says, are you able to compose ViewMatrix and ProjectionMatrix into one instead of multitiply a vector by the induvidual matrices ex.&#xD;&#xA;&#xD;&#xA;Instead of this at run time for each item:&#xD;&#xA;Vector * ViewMatrix -&gt; Vector ProjectionMatrix&#xD;&#xA;&#xD;&#xA;Do this at the start of run time for all vectors:&#xD;&#xA;ViewMatrix * ProjectionMatrix -&gt; ComposedMatrix&#xD;&#xA;&#xD;&#xA;Then when drawing vectors&#xD;&#xA;Vector * ComposedMatrix&#xD;&#xA;&#xD;&#xA;This would minimise the amount of matrix multiplication needed to be done, is there any reason not to do this" ContentLicense="CC BY-SA 4.0" />
  <row Id="28880" PostHistoryTypeId="1" PostId="9995" RevisionGUID="b6259983-d3f8-48e7-ab62-f5944ee330cd" CreationDate="2020-07-03T14:43:10.617" UserId="13639" Text="Compose ViewMatrix and ProjectionMatrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="28881" PostHistoryTypeId="3" PostId="9995" RevisionGUID="b6259983-d3f8-48e7-ab62-f5944ee330cd" CreationDate="2020-07-03T14:43:10.617" UserId="13639" Text="|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28883" PostHistoryTypeId="5" PostId="9995" RevisionGUID="0545f689-3659-4743-bcb5-6f9bdb5533f1" CreationDate="2020-07-03T14:59:35.917" UserId="13639" Comment="added 1 character in body" Text="As the title says, are you able to compose ViewMatrix and ProjectionMatrix into one instead of multitiply a vector by the induvidual matrices ex.&#xD;&#xA;&#xD;&#xA;Instead of this at run time for each item:&#xD;&#xA;Vector * ViewMatrix -&gt; Vector ProjectionMatrix&#xD;&#xA;&#xD;&#xA;Do this at the start of run time for all vectors:&#xD;&#xA;ViewMatrix * ProjectionMatrix -&gt; ComposedMatrix&#xD;&#xA;&#xD;&#xA;Then when drawing vectors:&#xD;&#xA;Vector * ComposedMatrix&#xD;&#xA;&#xD;&#xA;This would minimise the amount of matrix multiplication needed to be done, is there any reason not to do this" ContentLicense="CC BY-SA 4.0" />
  <row Id="28885" PostHistoryTypeId="2" PostId="9996" RevisionGUID="8349eec7-ff4e-493f-9b8a-5fbc1c121d92" CreationDate="2020-07-04T00:22:06.763" UserDisplayName="user9485" Text="This is just an educated guess, but the artifacts in your visualization of the curvature values reminded me of [Moiré patterns][1]. The images in the Wikipedia article don't show circle patterns like the ones you are observing, but I have seen similar patterns before when I tried to visualize highly oscillating functions.&#xD;&#xA;&#xD;&#xA;For example, if you try to visualize the function $f(x,y) = |\cos((x^2+y^2)^2)|$ for $x$ and $y$ ranging from $-3.3$ to $3.3$ on a grid of $256\times 256$ pixels, what you get is the following image:&#xD;&#xA;&#xD;&#xA;[![Moiré pattern][2]][2]&#xD;&#xA;&#xD;&#xA;The Moiré patterns appear in this image since the function $f$ is only evaluated at a single point (x,y) for every pixel, although each pixel covers not just a single point but an area. A better visualization of the function $f$ would involve integrating over the corresponding area for each pixel, which would result in a uniform gray color near the image boundaries.&#xD;&#xA;&#xD;&#xA;My guess is that there is something similar happening in your situation. As for solving your problem, this essentially means that the curvature is computed in an erroneous way if the discretization is too coarse. So you could either try to improve the algorithm that is used for the computation of the curvature or simply use a finer discretization. Unless, of course, if the rings really are a feature of your surface, in which case they will not disappear as lightxbulb pointed out.&#xD;&#xA;&#xD;&#xA;In case you are interested, I have attached the C++ code that I used to generate the above image. Note that if you increase `X` and `Y` while keeping `lX` and `lY` constant, the discretization is refined and the Moiré patterns will disappear.&#xD;&#xA;&#xD;&#xA;``` lang-cpp&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;cmath&gt;&#xD;&#xA;&#xD;&#xA;using namespace std;&#xD;&#xA;&#xD;&#xA;void WriteGrayscalePPM(const std::string&amp; file, const std::vector&lt;unsigned char&gt;&amp; values, const unsigned int X) {&#xD;&#xA;  const unsigned int Y = values.size ( ) / X;&#xD;&#xA;  &#xD;&#xA;  std::ofstream image(file.c_str(), ios::out | ios::binary);&#xD;&#xA;  image &lt;&lt; &quot;P6\n&quot; &lt;&lt; X &lt;&lt; ' ' &lt;&lt; Y &lt;&lt; &quot;\n255\n&quot;;&#xD;&#xA;  for (unsigned int i=0; i&lt;X*Y; i++) {&#xD;&#xA;    unsigned char color[3] = {values[i], values[i], values[i]};&#xD;&#xA;    image.write((const char*)color, 3*sizeof(char));&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(int argc, char **argv) {&#xD;&#xA;  const int X = 256;&#xD;&#xA;  const int Y = 256;&#xD;&#xA;  const double lX = 3.3;&#xD;&#xA;  const double lY = 3.3;&#xD;&#xA;  &#xD;&#xA;  std::vector&lt;unsigned char&gt; values(X*Y, 0);&#xD;&#xA;  &#xD;&#xA;  for (int y=0; y&lt;Y; y++) for (int x=0; x&lt;X; x++) {&#xD;&#xA;    double xd = lX / (X/2) * (x - X/2);&#xD;&#xA;    double yd = lY / (Y/2) * (y - Y/2);&#xD;&#xA;    double d = sqrt(xd*xd + yd*yd);&#xD;&#xA;    &#xD;&#xA;    values[x + y*X] = 255*abs(cos(d*d*d*d));&#xD;&#xA;  }&#xD;&#xA;  &#xD;&#xA;  WriteGrayscalePPM(&quot;moire.ppm&quot;, values, X);&#xD;&#xA;  &#xD;&#xA;  return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Moir%C3%A9_pattern&#xD;&#xA;  [2]: https://i.stack.imgur.com/LIxCj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28886" PostHistoryTypeId="2" PostId="9997" RevisionGUID="f01292d2-7c97-4d1b-8fbb-4f726ca07f87" CreationDate="2020-07-04T05:05:07.630" UserId="7462" Text="The following is an excerpt from a [2005 paper][1] on geodesics on triangular meshes, taken from section 3.5&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In this case $p$ is a point on some arbitrary face in a mesh, $p'$ is a point on one of the 3 edges in the triangle and $D(p')$ is the geodesic distance to that point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am very confused as to how this minimization is achieved. The paper doesn't go into detail, so I assume it's trivial, but I am not seeing the solution of the top of my head.&#xD;&#xA;&#xD;&#xA;Given an arbitrary interval (segment) the shortest point to it is either the orthogonal projection of the point $p$ onto the segment or one of the end points of the segment (depending on where $p$ is located with respect to the segment).&#xD;&#xA;&#xD;&#xA;However, this is not necessarily the point that minimizes the expression $||p - p'|| + D(p')$ or in other words, $p'$ is not, in general, the orthogonal projection of $p$ onto the segment.&#xD;&#xA;&#xD;&#xA;The only algorithm I have is to naively check epsilon offsets along the segment and picking the shortest one. There has to be a better way than that.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://hhoppe.com/geodesics.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/lvE1X.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28887" PostHistoryTypeId="1" PostId="9997" RevisionGUID="f01292d2-7c97-4d1b-8fbb-4f726ca07f87" CreationDate="2020-07-04T05:05:07.630" UserId="7462" Text="Fast and exact Geodesics on meshes, Backtracking confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="28888" PostHistoryTypeId="3" PostId="9997" RevisionGUID="f01292d2-7c97-4d1b-8fbb-4f726ca07f87" CreationDate="2020-07-04T05:05:07.630" UserId="7462" Text="|mathematics|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28889" PostHistoryTypeId="5" PostId="9997" RevisionGUID="5806f6d4-2b9c-4a76-8a4f-5e8709957b01" CreationDate="2020-07-04T05:11:25.563" UserId="7462" Comment="added 530 characters in body" Text="The following is an excerpt from a [2005 paper][1] on geodesics on triangular meshes, taken from section 3.5&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In this case $p$ is a point on some arbitrary face in a mesh, $p'$ is a point on one of the 3 edges in the triangle and $D(p')$ is the geodesic distance to that point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I am very confused as to how this minimization is achieved. The paper doesn't go into detail, so I assume it's trivial, but I am not seeing the solution of the top of my head.&#xD;&#xA;&#xD;&#xA;Given an arbitrary interval (segment) the shortest point to it is either the orthogonal projection of the point $p$ onto the segment or one of the end points of the segment (depending on where $p$ is located with respect to the segment).&#xD;&#xA;&#xD;&#xA;However, this is not necessarily the point that minimizes the expression $||p - p'|| + D(p')$ or in other words, $p'$ is not, in general, the orthogonal projection of $p$ onto the segment.&#xD;&#xA;&#xD;&#xA;The only algorithm I have is to naively check epsilon offsets along the segment and picking the shortest one. There has to be a better way than that.  &#xD;&#xA;&#xD;&#xA;I have drawn a diagram on Geogebra to show the problem:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;$\overline{BA}$ is the segment, $C$ is the point we are looking to minimize the distance from. $D$ is the frontier point, which is the orthogonal projection of the Geodesic source (the source point of all geodesics in the mesh), $E$ is the orthogonal projection of $C$ onto $\overline{BA}$. Clearly the optimal point is somewhere between $E$ and $D$ but I don't know how to find it.&#xD;&#xA;&#xD;&#xA;  [1]: http://hhoppe.com/geodesics.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/lvE1X.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/FmfBf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28890" PostHistoryTypeId="5" PostId="9996" RevisionGUID="7be6f816-8c3b-4651-b57a-c0102b8c85b3" CreationDate="2020-07-04T09:18:52.043" UserDisplayName="user9485" Comment="added 284 characters in body" Text="This is just an educated guess, but the artifacts in your visualization of the curvature values reminded me of [Moiré patterns][1]. The images in the Wikipedia article don't show circle patterns like the ones you are observing, but I have seen similar patterns before when I tried to visualize highly oscillating functions. *(Edit: The function you are visualizing, i.e. the curvature, is likely not oscillating quickly. However, the following example still illustrates that it may not only be the discretization or mesh generation algorithm that is problematic, but also the computation of the curvature.)*&#xD;&#xA;&#xD;&#xA;For example, if you try to visualize the function $f(x,y) = |\cos((x^2+y^2)^2)|$ for $x$ and $y$ ranging from $-3.3$ to $3.3$ on a grid of $256\times 256$ pixels, what you get is the following image:&#xD;&#xA;&#xD;&#xA;[![Moiré pattern][2]][2]&#xD;&#xA;&#xD;&#xA;The Moiré patterns appear in this image since the function $f$ is only evaluated at a single point (x,y) for every pixel, although each pixel covers not just a single point but an area. A better visualization of the function $f$ would involve integrating over the corresponding area for each pixel, which would result in a uniform gray color near the image boundaries.&#xD;&#xA;&#xD;&#xA;My guess is that there is something similar happening in your situation. As for solving your problem, this essentially means that the curvature is computed in an erroneous way if the discretization is too coarse. So you could either try to improve the algorithm that is used for the computation of the curvature or simply use a finer discretization. Unless, of course, if the rings really are a feature of your surface, in which case they will not disappear as lightxbulb pointed out.&#xD;&#xA;&#xD;&#xA;In case you are interested, I have attached the C++ code that I used to generate the above image. Note that if you increase `X` and `Y` while keeping `lX` and `lY` constant, the discretization is refined and the Moiré patterns will disappear.&#xD;&#xA;&#xD;&#xA;``` lang-cpp&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;cmath&gt;&#xD;&#xA;&#xD;&#xA;using namespace std;&#xD;&#xA;&#xD;&#xA;void WriteGrayscalePPM(const std::string&amp; file, const std::vector&lt;unsigned char&gt;&amp; values, const unsigned int X) {&#xD;&#xA;  const unsigned int Y = values.size ( ) / X;&#xD;&#xA;  &#xD;&#xA;  std::ofstream image(file.c_str(), ios::out | ios::binary);&#xD;&#xA;  image &lt;&lt; &quot;P6\n&quot; &lt;&lt; X &lt;&lt; ' ' &lt;&lt; Y &lt;&lt; &quot;\n255\n&quot;;&#xD;&#xA;  for (unsigned int i=0; i&lt;X*Y; i++) {&#xD;&#xA;    unsigned char color[3] = {values[i], values[i], values[i]};&#xD;&#xA;    image.write((const char*)color, 3*sizeof(char));&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(int argc, char **argv) {&#xD;&#xA;  const int X = 256;&#xD;&#xA;  const int Y = 256;&#xD;&#xA;  const double lX = 3.3;&#xD;&#xA;  const double lY = 3.3;&#xD;&#xA;  &#xD;&#xA;  std::vector&lt;unsigned char&gt; values(X*Y, 0);&#xD;&#xA;  &#xD;&#xA;  for (int y=0; y&lt;Y; y++) for (int x=0; x&lt;X; x++) {&#xD;&#xA;    double xd = lX / (X/2) * (x - X/2);&#xD;&#xA;    double yd = lY / (Y/2) * (y - Y/2);&#xD;&#xA;    double d = sqrt(xd*xd + yd*yd);&#xD;&#xA;    &#xD;&#xA;    values[x + y*X] = 255*abs(cos(d*d*d*d));&#xD;&#xA;  }&#xD;&#xA;  &#xD;&#xA;  WriteGrayscalePPM(&quot;moire.ppm&quot;, values, X);&#xD;&#xA;  &#xD;&#xA;  return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Moir%C3%A9_pattern&#xD;&#xA;  [2]: https://i.stack.imgur.com/LIxCj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28891" PostHistoryTypeId="5" PostId="9996" RevisionGUID="b18d2035-72ed-4779-8bc4-13ec443d8dbc" CreationDate="2020-07-04T12:56:43.197" UserDisplayName="user9485" Comment="added 34 characters in body" Text="This is just an educated guess, but the artifacts in your visualization of the curvature values reminded me of [Moiré patterns][1]. The images in the Wikipedia article don't show circle patterns like the ones you are observing, but I have seen similar patterns before when I tried to visualize highly oscillating functions. *(Edit: The function you are visualizing, i.e. the curvature, is likely not oscillating quickly. However, the following example still illustrates that it may not only be the discretization or mesh generation algorithm that is problematic, but also the computation of the curvature.)*&#xD;&#xA;&#xD;&#xA;For example, if you try to visualize the function $f(x,y) = |\cos((x^2+y^2)^2)|$ for $x$ and $y$ ranging from $-3.3$ to $3.3$ on a grid of $256\times 256$ pixels, what you get is the following image:&#xD;&#xA;&#xD;&#xA;[![Moiré pattern][2]][2]&#xD;&#xA;&#xD;&#xA;The Moiré patterns appear in this image since the function $f$ is only evaluated at a single point (x,y) for every pixel, although each pixel covers not just a single point but an area. A better visualization of the function $f$ would involve integrating over the corresponding area for each pixel, which &lt;s&gt;would result in a uniform gray color near the image boundaries&lt;/s&gt; reduces the Moiré patterns.&#xD;&#xA;&#xD;&#xA;My guess is that there is something similar happening in your situation. As for solving your problem, this essentially means that the curvature is computed in an erroneous way if the discretization is too coarse. So you could either try to improve the algorithm that is used for the computation of the curvature or simply use a finer discretization. Unless, of course, if the rings really are a feature of your surface, in which case they will not disappear as lightxbulb pointed out.&#xD;&#xA;&#xD;&#xA;In case you are interested, I have attached the C++ code that I used to generate the above image. Note that if you increase `X` and `Y` while keeping `lX` and `lY` constant, the discretization is refined and the Moiré patterns will disappear.&#xD;&#xA;&#xD;&#xA;``` lang-cpp&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;#include &lt;string&gt;&#xD;&#xA;#include &lt;cmath&gt;&#xD;&#xA;&#xD;&#xA;using namespace std;&#xD;&#xA;&#xD;&#xA;void WriteGrayscalePPM(const std::string&amp; file, const std::vector&lt;unsigned char&gt;&amp; values, const unsigned int X) {&#xD;&#xA;  const unsigned int Y = values.size ( ) / X;&#xD;&#xA;  &#xD;&#xA;  std::ofstream image(file.c_str(), ios::out | ios::binary);&#xD;&#xA;  image &lt;&lt; &quot;P6\n&quot; &lt;&lt; X &lt;&lt; ' ' &lt;&lt; Y &lt;&lt; &quot;\n255\n&quot;;&#xD;&#xA;  for (unsigned int i=0; i&lt;X*Y; i++) {&#xD;&#xA;    unsigned char color[3] = {values[i], values[i], values[i]};&#xD;&#xA;    image.write((const char*)color, 3*sizeof(char));&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(int argc, char **argv) {&#xD;&#xA;  const int X = 256;&#xD;&#xA;  const int Y = 256;&#xD;&#xA;  const double lX = 3.3;&#xD;&#xA;  const double lY = 3.3;&#xD;&#xA;  &#xD;&#xA;  std::vector&lt;unsigned char&gt; values(X*Y, 0);&#xD;&#xA;  &#xD;&#xA;  for (int y=0; y&lt;Y; y++) for (int x=0; x&lt;X; x++) {&#xD;&#xA;    double xd = lX / (X/2) * (x - X/2);&#xD;&#xA;    double yd = lY / (Y/2) * (y - Y/2);&#xD;&#xA;    double d = sqrt(xd*xd + yd*yd);&#xD;&#xA;    &#xD;&#xA;    values[x + y*X] = 255*abs(cos(d*d*d*d));&#xD;&#xA;  }&#xD;&#xA;  &#xD;&#xA;  WriteGrayscalePPM(&quot;moire.ppm&quot;, values, X);&#xD;&#xA;  &#xD;&#xA;  return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Moir%C3%A9_pattern&#xD;&#xA;  [2]: https://i.stack.imgur.com/LIxCj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28895" PostHistoryTypeId="5" PostId="9995" RevisionGUID="144fc5f3-296d-4e03-852a-6e5b7210381b" CreationDate="2020-07-05T16:47:35.593" UserId="13095" Comment="Enhance grammar and spelling" Text="As the title says, you are able to compose the ViewMatrix and the ProjectionMatrix into one instead of multiplying a vector by the individual matrices.&#xD;&#xA;&#xD;&#xA;Instead of doing this at run time for each item:&#xD;&#xA;Vector * ViewMatrix -&gt; Vector ProjectionMatrix&#xD;&#xA;&#xD;&#xA;Do this at the start:&#xD;&#xA;ViewMatrix * ProjectionMatrix -&gt; ComposedMatrix&#xD;&#xA;&#xD;&#xA;Then when drawing vectors:&#xD;&#xA;Vector * ComposedMatrix&#xD;&#xA;&#xD;&#xA;This would minimize the number of necessary matrix multiplications. Is there any reason not to do this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28896" PostHistoryTypeId="24" PostId="9995" RevisionGUID="144fc5f3-296d-4e03-852a-6e5b7210381b" CreationDate="2020-07-05T16:47:35.593" Comment="Proposed by 13095 approved by 13639 edit id of 534" ContentLicense="CC BY-SA 4.0" />
  <row Id="28901" PostHistoryTypeId="2" PostId="10000" RevisionGUID="3570964d-5341-4392-9273-19a73f44ea9c" CreationDate="2020-07-06T00:08:13.977" UserId="7462" Text="The solution I found to this problem is to ALWAYS intersect the edge. In other words the distance to the geodesic source $v$ from a point $p$ is $||v-p'|| + ||p - p'||$ where $p'$ is the intersection of the line $\overline{vp}$ with the current edge. In cases where $p'$ is &quot;behind&quot; $p$ with respect to $v$ we set the distance to the edge to be infinity. &#xD;&#xA;&#xD;&#xA;The above seems to work in the simple tests I have generated at minimum.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="28902" PostHistoryTypeId="2" PostId="10001" RevisionGUID="5e1ccad1-243e-40f6-bfec-a6aad6be443c" CreationDate="2020-07-06T11:50:27.597" UserId="11769" Text="I have a setup where I'm rendering a bunch of characters on a canvas with an SDF font. The users can zoom in to see the details of the smaller texts, but currently the smaller characters are quite pixelated. (See the image below.) I'm looking for an approach to improve their quality.&#xD;&#xA;&#xD;&#xA;Based on these comments I believe SDF fonts are not really good for small text rendering:&#xD;&#xA;&#xD;&#xA;- https://computergraphics.stackexchange.com/a/9337/11769&#xD;&#xA;&#xD;&#xA;- https://gamedev.stackexchange.com/questions/71841/how-do-some-mobile-games-scale-graphics-so-beautifully/71850#comment129983_71850&#xD;&#xA;&#xD;&#xA;I'm wondering if there's any viable workaround. For example, would it make sense to somehow reuse the larger characters by rendering them in a separate texture and scaling them down? Because when I zoom out, the larger characters look a lot better as they get smaller, I believe the problem might be that the SDF font cannot be interpolated on a too small scale.&#xD;&#xA;&#xD;&#xA;My setup is based on these resources: &#xD;&#xA;- https://github.com/libgdx/libgdx/wiki/Distance-field-fonts&#xD;&#xA;- https://github.com/SaschaWillems/Vulkan/blob/master/examples/distancefieldfonts/distancefieldfonts.cpp&#xD;&#xA;&#xD;&#xA;I've already tried generating mipmaps which didn't really make any difference.&#xD;&#xA;&#xD;&#xA;[![Scale comparison][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q4Ldp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28903" PostHistoryTypeId="1" PostId="10001" RevisionGUID="5e1ccad1-243e-40f6-bfec-a6aad6be443c" CreationDate="2020-07-06T11:50:27.597" UserId="11769" Text="How to scale signed distance field fonts properly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28904" PostHistoryTypeId="3" PostId="10001" RevisionGUID="5e1ccad1-243e-40f6-bfec-a6aad6be443c" CreationDate="2020-07-06T11:50:27.597" UserId="11769" Text="|opengl|signed-distance-field|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28906" PostHistoryTypeId="2" PostId="10002" RevisionGUID="0b386443-eef1-49ce-bd0d-ec86195b2f56" CreationDate="2020-07-06T19:15:52.117" UserId="13655" Text="Considering a polygon with n vertices as input. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I need to calculate the integral of the form &#xD;&#xA;\\[\int_A p(y) dA \\] where $p(y)$ is a piecewise polynomial function of $y$.&#xD;&#xA;&#xD;&#xA;May be if I could find  the expression $b(y)$ then the integral can be calculated by:&#xD;&#xA;$$\int_{0}^{y_\max} p(y) b(y) dy $$&#xD;&#xA;&#xD;&#xA;The question is : &quot;is there a straightforward method to find $b(y)$ given the coordinates of the polygon vertices? Or is there a simpler manner to calculate the integral above?&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bWunO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28907" PostHistoryTypeId="1" PostId="10002" RevisionGUID="0b386443-eef1-49ce-bd0d-ec86195b2f56" CreationDate="2020-07-06T19:15:52.117" UserId="13655" Text="The ploygon width parallel to the x axis as a function of the y ordonate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28908" PostHistoryTypeId="3" PostId="10002" RevisionGUID="0b386443-eef1-49ce-bd0d-ec86195b2f56" CreationDate="2020-07-06T19:15:52.117" UserId="13655" Text="|polygon|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28913" PostHistoryTypeId="2" PostId="10004" RevisionGUID="544d239a-2afc-41bf-bfa0-de34648532c7" CreationDate="2020-07-07T10:44:03.997" UserId="10096" Text="While I was deriving expressions for perspective-correct linear interpolation on triangles, I reached the conclusion that the interpolation may be kept linear only if view-space $Z$ is available. However, computing view-space $Z$ requires nonlinear interpolation (it is a rational function based on my results). Is nonlinear interpolation performed in hardware to get perspective correct $Z$, or equivalently linear interpolation is performed on $\frac{1}{Z}$ but a division is required to get view-space $Z$ anyways? As far as I get it there is no way around that - a division is required per-pixel to get perspective-correct Z values - is that correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28914" PostHistoryTypeId="1" PostId="10004" RevisionGUID="544d239a-2afc-41bf-bfa0-de34648532c7" CreationDate="2020-07-07T10:44:03.997" UserId="10096" Text="Perspective correct interpolation z-buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="28915" PostHistoryTypeId="3" PostId="10004" RevisionGUID="544d239a-2afc-41bf-bfa0-de34648532c7" CreationDate="2020-07-07T10:44:03.997" UserId="10096" Text="|projections|perspective|interpolation|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28916" PostHistoryTypeId="5" PostId="10001" RevisionGUID="802edb41-d413-4682-8e9a-151aa5cf4e99" CreationDate="2020-07-07T12:44:23.980" UserId="11769" Comment="added 396 characters in body" Text="I have a setup where I'm rendering a bunch of characters on a canvas with an SDF font. The users can zoom in to see the details of the smaller texts, but currently the smaller characters are quite pixelated. (See the image below.) I'm looking for an approach to improve their quality.&#xD;&#xA;&#xD;&#xA;Based on these comments I believe SDF fonts are not really good for small text rendering:&#xD;&#xA;&#xD;&#xA;- https://computergraphics.stackexchange.com/a/9337/11769&#xD;&#xA;&#xD;&#xA;- https://gamedev.stackexchange.com/questions/71841/how-do-some-mobile-games-scale-graphics-so-beautifully/71850#comment129983_71850&#xD;&#xA;&#xD;&#xA;I'm wondering if there's any viable workaround. For example, would it make sense to somehow reuse the larger characters by rendering them in a separate texture and scaling them down? Because when I zoom out, the larger characters look a lot better as they get smaller, I believe the problem might be that the SDF font cannot be interpolated on a too small scale.&#xD;&#xA;&#xD;&#xA;My setup is based on these resources: &#xD;&#xA;- https://github.com/libgdx/libgdx/wiki/Distance-field-fonts&#xD;&#xA;- https://github.com/SaschaWillems/Vulkan/blob/master/examples/distancefieldfonts/distancefieldfonts.cpp&#xD;&#xA;&#xD;&#xA;I've already tried generating mipmaps which didn't really make any difference.&#xD;&#xA;&#xD;&#xA;[![Scale comparison][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q4Ldp.png&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;I've tried one possible workaround which solves the issue, but might not be the best solution performance-wise. Instead of scaling the canvas with the text content, I've decided to scale the character's quads and simulate the zoom in effect by enlarging them one-by-one. I'm not sure what are the performance trade-offs of this approach, so any other suggestion is appreciated!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28917" PostHistoryTypeId="6" PostId="10002" RevisionGUID="7d983475-905c-44b5-bc29-88115ecdd5cd" CreationDate="2020-07-07T17:57:22.590" UserId="13655" Comment="edited tags" Text="|geometry|polygon|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28918" PostHistoryTypeId="2" PostId="10005" RevisionGUID="c40f8196-619b-4dba-8a1b-9c4e89d4dc65" CreationDate="2020-07-08T00:38:53.620" UserId="11058" Text="I'm wondering why the orthographic projection we use in computer graphics is called a projection, if all it does is just scale and translate a mesh? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;According to wiki orthographic projection is `Orthographic projection (sometimes referred to as orthogonal projection, used to be called analemma[a]) is a means of representing three-dimensional objects in two dimensions`, but we don't use orthographic projection to project our mesh to 2d space, we just use it to transform the view box with arbitrarily defined dimensions (left, right, up, bottom, far and near) to a view box of (-1, 1, -1, 1, -1, 1) dimensions. So why do we call it an orthographic projection?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CUQe3.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28919" PostHistoryTypeId="1" PostId="10005" RevisionGUID="c40f8196-619b-4dba-8a1b-9c4e89d4dc65" CreationDate="2020-07-08T00:38:53.620" UserId="11058" Text="How is orthographic projection used in computer graphics technically classified as a projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28920" PostHistoryTypeId="3" PostId="10005" RevisionGUID="c40f8196-619b-4dba-8a1b-9c4e89d4dc65" CreationDate="2020-07-08T00:38:53.620" UserId="11058" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28921" PostHistoryTypeId="5" PostId="10005" RevisionGUID="99818d99-91c6-4ff4-a473-aee2ee5a4ce8" CreationDate="2020-07-08T00:46:37.447" UserId="11058" Comment="added 20 characters in body" Text="I'm wondering why the orthographic projection we use in computer graphics is called a projection, if all it does is just scale and translate a mesh? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;According to wiki orthographic projection is `Orthographic projection (sometimes referred to as orthogonal projection, used to be called analemma[a]) is a means of representing three-dimensional objects in two dimensions`, but we don't use orthographic projection to project our mesh to 2d space, we just use it to transform our mesh defined in the view box with arbitrarily defined dimensions (left, right, up, bottom, far and near) to a view box of (-1, 1, -1, 1, -1, 1) dimensions. So why do we call it an orthographic projection?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CUQe3.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="28922" PostHistoryTypeId="2" PostId="10006" RevisionGUID="3591c383-4226-41c1-b42b-23b9181a08e2" CreationDate="2020-07-08T01:31:22.623" UserId="13305" Text="I think it is more of a terminology shared specifically in the computer graphics community. The transformation $P$ results in a vector one-step-ahead from getting the actual projection. From a 3d position transformed with $P$, we can obtain both 1) the 2d-projected position in normalized device coordinate (NDC) (by obtaining xy component). 2) the depth (by obtaining the z component) in NDC. So I think it is a more generalized form of projection. &#xD;&#xA;&#xD;&#xA;This so-called projection matrix is designed specifically to satisfy the needs in the computer graphics pipeline. The key difference between an ordinary N-d-to-(N-1)-d projection is that the projection matrix results in 2D positions with &quot;depth&quot;, which is required for obtaining a depth map used for many purposes in the computer graphics pipeline.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28923" PostHistoryTypeId="2" PostId="10007" RevisionGUID="a6d2d15f-706b-475e-ba18-0eb07e538056" CreationDate="2020-07-08T05:35:08.267" UserId="13664" Text="Find the formulas of the middle point algorithm for drawing the parabola ? &lt;br&gt;&#xD;&#xA;x^2 = 4*(a+b)*y , a,b &gt; 0. &lt;br&gt;&#xD;&#xA;Solve it according to E(East) and NorthEast(NE) ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28924" PostHistoryTypeId="1" PostId="10007" RevisionGUID="a6d2d15f-706b-475e-ba18-0eb07e538056" CreationDate="2020-07-08T05:35:08.267" UserId="13664" Text="Find the formulas of the middle point algorithm for drawing the parabola?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28925" PostHistoryTypeId="3" PostId="10007" RevisionGUID="a6d2d15f-706b-475e-ba18-0eb07e538056" CreationDate="2020-07-08T05:35:08.267" UserId="13664" Text="|midpoint|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28926" PostHistoryTypeId="5" PostId="10007" RevisionGUID="2c82a085-34da-4029-9a85-15d5408aca20" CreationDate="2020-07-08T09:17:16.440" UserId="13664" Comment="added 59 characters in body" Text="This is the result i got (This is writen in java frame, so its the opposite on graph)&#xD;&#xA;&#xD;&#xA;[![My try][1]][1]  &#xD;&#xA;&lt;br&gt;&#xD;&#xA;This is my try, Ok in this problem the y increases y_{k+1} = y_k + 1 every time and x_{k+1} = x_k or x_k + 1 depending on the P_k value. Here is code i tried with: If P_{k} &gt; then ( p_{k+1} = p_k - 4*(a + b) + 2*x_k + 1; and x in increased by one x_{k+1} = x_k + 1;) else ( p_{k+1} = p_k - 4*(a + b);) , It doesn't look very well i think&#xD;&#xA;&#xD;&#xA;Find the formulas of the middle point algorithm for drawing the parabola ? &lt;br&gt;&#xD;&#xA;x^2 = 4*(a+b)*y , a,b &gt; 0. &lt;br&gt;&#xD;&#xA;Solve it according to E(East) and NorthEast(NE) ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OLfzY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28927" PostHistoryTypeId="2" PostId="10008" RevisionGUID="55bf8127-97e2-4a01-aa2d-f78e771cba19" CreationDate="2020-07-08T09:45:31.693" UserId="11769" Text="After some trials I've realized my problem was a programming error and not an actual issue with SDF fonts. &#xD;&#xA;&#xD;&#xA;Originally I was rendering the numbers on the texture of the canvas, which had a fixed scale. I thought that it will redraw the quads during the zoom but it wasn't the case. After I've separated the character drawing from the canvas and scaled them separately they finally look sharp.&#xD;&#xA;&#xD;&#xA;The linked comments about the small text rendering was slightly misleading. They do have some issues with smaller scale, but that's only the case when the view is zoomed out." ContentLicense="CC BY-SA 4.0" />
  <row Id="28928" PostHistoryTypeId="5" PostId="10001" RevisionGUID="a08ebd3c-5198-432e-8acc-2b7429140edd" CreationDate="2020-07-08T09:45:43.180" UserId="11769" Comment="deleted 394 characters in body" Text="I have a setup where I'm rendering a bunch of characters on a canvas with an SDF font. The users can zoom in to see the details of the smaller texts, but currently the smaller characters are quite pixelated. (See the image below.) I'm looking for an approach to improve their quality.&#xD;&#xA;&#xD;&#xA;Based on these comments I believe SDF fonts are not really good for small text rendering:&#xD;&#xA;&#xD;&#xA;- https://computergraphics.stackexchange.com/a/9337/11769&#xD;&#xA;&#xD;&#xA;- https://gamedev.stackexchange.com/questions/71841/how-do-some-mobile-games-scale-graphics-so-beautifully/71850#comment129983_71850&#xD;&#xA;&#xD;&#xA;I'm wondering if there's any viable workaround. For example, would it make sense to somehow reuse the larger characters by rendering them in a separate texture and scaling them down? Because when I zoom out, the larger characters look a lot better as they get smaller, I believe the problem might be that the SDF font cannot be interpolated on a too small scale.&#xD;&#xA;&#xD;&#xA;My setup is based on these resources: &#xD;&#xA;- https://github.com/libgdx/libgdx/wiki/Distance-field-fonts&#xD;&#xA;- https://github.com/SaschaWillems/Vulkan/blob/master/examples/distancefieldfonts/distancefieldfonts.cpp&#xD;&#xA;&#xD;&#xA;I've already tried generating mipmaps which didn't really make any difference.&#xD;&#xA;&#xD;&#xA;[![Scale comparison][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q4Ldp.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28929" PostHistoryTypeId="5" PostId="10006" RevisionGUID="d86ee292-1e9a-4692-baf7-410c462b608e" CreationDate="2020-07-08T10:59:32.887" UserId="13305" Comment="deleted 57 characters in body" Text="I think it is more of a terminology shared specifically in the computer graphics community. The transformation $P$ results in a vector one-step-ahead from getting the actual projection. From a 3d position transformed with $P$, we can obtain both 1) the 2d-projected position in normalized device coordinate (NDC) (by obtaining xy component). 2) the depth (by obtaining the z component) in NDC.&#xD;&#xA;&#xD;&#xA;This so-called projection matrix is designed specifically to satisfy the needs in the computer graphics pipeline. The key difference between an ordinary N-d-to-(N-1)-d projection is that the projection matrix results in 2D positions with &quot;depth&quot;, which is required for obtaining a depth map used for many purposes in the computer graphics pipeline.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28930" PostHistoryTypeId="2" PostId="10009" RevisionGUID="3f7a957f-5b5b-4957-b2f3-58283e0b529f" CreationDate="2020-07-08T13:20:51.607" UserDisplayName="user13665" Text="*For context:*&#xD;&#xA;&#xD;&#xA;I'm absolutely new to graphics programming and I've always had trouble getting the math.&#xD;&#xA;&#xD;&#xA;I had the task to write code for a crystal ball interface using OpenGL.&#xD;&#xA;There's an object in the center of the screen and by using arrow keys, the user can rotate around it.&#xD;&#xA;&#xD;&#xA;The code below is working and passed the grader. &#xD;&#xA;&#xD;&#xA;*The problem:*&#xD;&#xA;&#xD;&#xA;I don't get why this code is working. I'm reading up on linear algebra (vectors, matrices...) and I understand the operations that can be performed on those structures. But when it comes to applying, it all doesn't seem to make sense anymore.&#xD;&#xA;&#xD;&#xA;Maybe someone here can explain to me in simple terms why this part works:&#xD;&#xA;```&#xD;&#xA;    mat3 xmat(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    mat3 ymat(x * x, x * y, x * z, x * y, y * y, y * z, x * z, y * z, z * z);&#xD;&#xA;    mat3 zmat(0.0, z, -y, -z, 0.0, x, y, -x, 0.0);&#xD;&#xA;&#xD;&#xA;    // This part I &quot;understand&quot;&#xD;&#xA;    mat3 rotMat((cos(radians) * xmat) + ((1 - cos(radians)) * ymat) + (sin(radians) * (zmat)));&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;I feel like someone would have to explain me all of it with lots of pictures.&#xD;&#xA;But I hope that the above part will make the rest click for me.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// Helper rotation function.  Please implement this.  &#xD;&#xA;mat3 Transform::rotate(const float degrees, const vec3&amp; axis)&#xD;&#xA;{&#xD;&#xA;	// YOUR CODE HERE&#xD;&#xA;	vec3 normalAxis = glm::normalize(axis);&#xD;&#xA;	float radians = ((2 * pi) / 360) * degrees;&#xD;&#xA;	float x = axis.x;&#xD;&#xA;	float y = axis.y;&#xD;&#xA;	float z = axis.z;&#xD;&#xA;&#xD;&#xA;	mat3 xmat(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);&#xD;&#xA;	mat3 ymat(x * x, x * y, x * z, x * y, y * y, y * z, x * z, y * z, z * z);&#xD;&#xA;	mat3 zmat(0.0, z, -y, -z, 0.0, x, y, -x, 0.0);&#xD;&#xA;&#xD;&#xA;	mat3 rotMat((cos(radians) * xmat) + ((1 - cos(radians)) * ymat) + (sin(radians) * (zmat)));&#xD;&#xA;	return rotMat;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Transform::left(float degrees, vec3&amp; eye, vec3&amp; up) {&#xD;&#xA;	mat3 rotMat = rotate(degrees, up);&#xD;&#xA;	eye = rotMat * eye;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Transforms the camera up around the &quot;crystal ball&quot; interface&#xD;&#xA;void Transform::up(float degrees, vec3&amp; eye, vec3&amp; up) {&#xD;&#xA;	vec3 unit = glm::cross(eye, up);&#xD;&#xA;	vec3 unitNormal = glm::normalize(unit);&#xD;&#xA;&#xD;&#xA;	mat3 rotMat = rotate(degrees, unitNormal);&#xD;&#xA;	eye = (rotMat * eye);&#xD;&#xA;	up = glm::normalize(rotMat * up);&#xD;&#xA;&#xD;&#xA;	int dot1 = glm::dot(eye, up);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Thanks a lot and stay healthy,&#xD;&#xA;Cheers." ContentLicense="CC BY-SA 4.0" />
  <row Id="28931" PostHistoryTypeId="1" PostId="10009" RevisionGUID="3f7a957f-5b5b-4957-b2f3-58283e0b529f" CreationDate="2020-07-08T13:20:51.607" UserDisplayName="user13665" Text="Crystal ball rotation - I don't get why the code works" ContentLicense="CC BY-SA 4.0" />
  <row Id="28932" PostHistoryTypeId="3" PostId="10009" RevisionGUID="3f7a957f-5b5b-4957-b2f3-58283e0b529f" CreationDate="2020-07-08T13:20:51.607" UserDisplayName="user13665" Text="|opengl|matrix|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28933" PostHistoryTypeId="5" PostId="10009" RevisionGUID="ca4346f6-a861-49f2-8b38-e3159812305f" CreationDate="2020-07-08T13:37:49.757" UserDisplayName="user13665" Comment="added 264 characters in body" Text="*For context:*&#xD;&#xA;&#xD;&#xA;I'm absolutely new to graphics programming and I've always had trouble getting the math.&#xD;&#xA;&#xD;&#xA;I had the task to write code for a crystal ball interface using OpenGL.&#xD;&#xA;There's an object in the center of the screen and by using arrow keys, the user can rotate around it.&#xD;&#xA;&#xD;&#xA;The code below is working and passed the grader. &#xD;&#xA;&#xD;&#xA;*The problem:*&#xD;&#xA;&#xD;&#xA;I don't get why this code is working. I'm reading up on linear algebra (vectors, matrices...) and I understand the operations that can be performed on those structures. But when it comes to applying, it all doesn't seem to make sense anymore.&#xD;&#xA;&#xD;&#xA;Maybe someone here can explain to me in simple terms why this part works:&#xD;&#xA;```&#xD;&#xA;    mat3 xmat(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    mat3 ymat(x * x, x * y, x * z, x * y, y * y, y * z, x * z, y * z, z * z);&#xD;&#xA;    mat3 zmat(0.0, z, -y, -z, 0.0, x, y, -x, 0.0);&#xD;&#xA;&#xD;&#xA;    // This part I &quot;understand&quot;&#xD;&#xA;    mat3 rotMat((cos(radians) * xmat) + ((1 - cos(radians)) * ymat) + (sin(radians) * (zmat)));&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;I feel like someone would have to explain me all of it with lots of pictures.&#xD;&#xA;But I hope that the above part will make the rest click for me.&#xD;&#xA;&#xD;&#xA;Wouldn't this way be equivalent - it looks like it-?&#xD;&#xA;```&#xD;&#xA;    mat3 xmat(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    mat3 zmat(0.0, z, -y, -z, 0.0, x, y, -x, 0.0);&#xD;&#xA;&#xD;&#xA;    mat3 rotMat(xmat + zmat * sin(radians) + (zmat * zmat) * (1-cos(radians)));&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// Helper rotation function.  Please implement this.  &#xD;&#xA;mat3 Transform::rotate(const float degrees, const vec3&amp; axis)&#xD;&#xA;{&#xD;&#xA;	// YOUR CODE HERE&#xD;&#xA;	vec3 normalAxis = glm::normalize(axis);&#xD;&#xA;	float radians = ((2 * pi) / 360) * degrees;&#xD;&#xA;	float x = axis.x;&#xD;&#xA;	float y = axis.y;&#xD;&#xA;	float z = axis.z;&#xD;&#xA;&#xD;&#xA;	mat3 xmat(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);&#xD;&#xA;	mat3 ymat(x * x, x * y, x * z, x * y, y * y, y * z, x * z, y * z, z * z);&#xD;&#xA;	mat3 zmat(0.0, z, -y, -z, 0.0, x, y, -x, 0.0);&#xD;&#xA;&#xD;&#xA;	mat3 rotMat((cos(radians) * xmat) + ((1 - cos(radians)) * ymat) + (sin(radians) * (zmat)));&#xD;&#xA;	return rotMat;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Transform::left(float degrees, vec3&amp; eye, vec3&amp; up) {&#xD;&#xA;	mat3 rotMat = rotate(degrees, up);&#xD;&#xA;	eye = rotMat * eye;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Transforms the camera up around the &quot;crystal ball&quot; interface&#xD;&#xA;void Transform::up(float degrees, vec3&amp; eye, vec3&amp; up) {&#xD;&#xA;	vec3 unit = glm::cross(eye, up);&#xD;&#xA;	vec3 unitNormal = glm::normalize(unit);&#xD;&#xA;&#xD;&#xA;	mat3 rotMat = rotate(degrees, unitNormal);&#xD;&#xA;	eye = (rotMat * eye);&#xD;&#xA;	up = glm::normalize(rotMat * up);&#xD;&#xA;&#xD;&#xA;	int dot1 = glm::dot(eye, up);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Thanks a lot and stay healthy,&#xD;&#xA;Cheers." ContentLicense="CC BY-SA 4.0" />
  <row Id="28935" PostHistoryTypeId="5" PostId="10007" RevisionGUID="eda2cdce-cb3a-40fd-b3d8-643cb889580f" CreationDate="2020-07-09T07:24:11.323" UserId="13664" Comment="added 11 characters in body" Text="Find the formulas of the middle point algorithm for drawing the parabola ? &lt;br&gt;&#xD;&#xA;x^2 = 4*(a+b)*y , a,b &gt; 0. &lt;br&gt;&#xD;&#xA;Solve it according to E(East) and NorthEast(NE) ? &lt;br&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is the result i got (This is writen in java frame, so its the opposite on graph)&#xD;&#xA;&#xD;&#xA;[![My try][1]][1]  &#xD;&#xA;&lt;br&gt;&#xD;&#xA;This is my try, Ok in this problem the y increases y_{k+1} = y_k + 1 every time and x_{k+1} = x_k or x_k + 1 depending on the P_k value. Here is code i tried with: If P_{k} &gt; then ( p_{k+1} = p_k - 4*(a + b) + 2*x_k + 1; and x in increased by one x_{k+1} = x_k + 1;) else ( p_{k+1} = p_k - 4*(a + b);) , It doesn't look very well i think&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OLfzY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28936" PostHistoryTypeId="2" PostId="10010" RevisionGUID="47db0345-b678-4386-a012-b78289cf12d9" CreationDate="2020-07-09T22:32:31.940" UserId="13678" Text="I'm working on a 3D modeling tool and we use data from OpenLayers to construct a 3D mesh of some land. I want this behavior: you click on the mesh and it puts a point where you clicked on the mesh. Then, after the first point has been made, if you hover over the mesh with your mouse, a helper line will appear between the first point you made and where you mouse is currently. This helper line is drawn on the mesh, i.e. conforms to it's surface. This sounded like simple functionality but is proving quite complex.&#xD;&#xA;&#xD;&#xA;I've looked into geodesics, and shortest path algorithms but they seem really complex. I'm still fairly new to three.js. I've also read about UV mapping, or maybe casting a shadow to create this line.&#xD;&#xA;&#xD;&#xA;Does any one have any pointers for this? Or things to look into? Thank you! " ContentLicense="CC BY-SA 4.0" />
  <row Id="28937" PostHistoryTypeId="1" PostId="10010" RevisionGUID="47db0345-b678-4386-a012-b78289cf12d9" CreationDate="2020-07-09T22:32:31.940" UserId="13678" Text="Draw Line on Arbitrary Surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="28938" PostHistoryTypeId="3" PostId="10010" RevisionGUID="47db0345-b678-4386-a012-b78289cf12d9" CreationDate="2020-07-09T22:32:31.940" UserId="13678" Text="|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28939" PostHistoryTypeId="2" PostId="10011" RevisionGUID="8b4e5089-2a37-44a0-9231-0c7b6bd9662e" CreationDate="2020-07-09T23:27:31.250" UserId="11058" Text="I constructed an orthographic projection matrix from  [this](https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/orthographic-projection-matrix) article on scratchpixel.com:&#xD;&#xA;&#xD;&#xA;    void ortho(float l, float r, float b, float t, float n, float f) {&#xD;&#xA;       2/(r-l), 0, 0, -(r+l)/(r-l),&#xD;&#xA;       0, 2/(t-b), 0, -(t+b)/(t-b),&#xD;&#xA;	   0, 0, -2/(f-n), -(f+n)/(f-n),&#xD;&#xA;	   0, 0, 0, 1&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;, where `r, l, t, b, n, f` are right, left, top, bottom, near and far corners of the view box.&#xD;&#xA;&#xD;&#xA;Now I tested out this matrix using the default parameters of the view box `ortho(-1, 1, -1, 1, -1, 1)` to see if I get an identity matrix. However I'm getting:&#xD;&#xA;&#xD;&#xA;     1, 0, 0, 0,&#xD;&#xA;     0, 1, 0, 0,&#xD;&#xA;     0, 0, -1, 0,&#xD;&#xA;     0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;Basically this will result in z coordinate of every transformed point to be negated.&#xD;&#xA;&#xD;&#xA;Is it standard to negate the z coordinate when constructing projection matrix? What could be the purpose behind that?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28940" PostHistoryTypeId="1" PostId="10011" RevisionGUID="8b4e5089-2a37-44a0-9231-0c7b6bd9662e" CreationDate="2020-07-09T23:27:31.250" UserId="11058" Text="Why negate z when constructing projection matrix OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="28941" PostHistoryTypeId="3" PostId="10011" RevisionGUID="8b4e5089-2a37-44a0-9231-0c7b6bd9662e" CreationDate="2020-07-09T23:27:31.250" UserId="11058" Text="|opengl|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28942" PostHistoryTypeId="5" PostId="10011" RevisionGUID="0999f057-86fa-4517-8ba2-badf421e2f97" CreationDate="2020-07-09T23:34:31.230" UserId="11058" Comment="added 29 characters in body" Text="I constructed an orthographic projection matrix from  [this](https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/orthographic-projection-matrix) article on scratchpixel.com:&#xD;&#xA;&#xD;&#xA;    Matrix4 ortho(float l, float r, float b, float t, float n, float f) {&#xD;&#xA;       return Matrix4(&#xD;&#xA;           2/(r-l), 0, 0, -(r+l)/(r-l), //row 0&#xD;&#xA;           0, 2/(t-b), 0, -(t+b)/(t-b), //row 1&#xD;&#xA;	       0, 0, -2/(f-n), -(f+n)/(f-n), //row 2&#xD;&#xA;	       0, 0, 0, 1 //row 3&#xD;&#xA;       );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;, where `r, l, t, b, n, f` are right, left, top, bottom, near and far corners of the view box.&#xD;&#xA;&#xD;&#xA;Now I tested out this matrix using the default parameters of the view box `ortho(-1, 1, -1, 1, -1, 1)` to see if I get an identity matrix. However I'm getting:&#xD;&#xA;&#xD;&#xA;     1, 0, 0, 0,&#xD;&#xA;     0, 1, 0, 0,&#xD;&#xA;     0, 0, -1, 0,&#xD;&#xA;     0, 0, 0, 1&#xD;&#xA;&#xD;&#xA;Basically this will result in z coordinate of every transformed point to be negated.&#xD;&#xA;&#xD;&#xA;Is it standard to negate the z coordinate when constructing projection matrix? What could be the purpose behind that?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28943" PostHistoryTypeId="6" PostId="10011" RevisionGUID="00f79669-f96d-4374-877b-ea4b5ed15ec1" CreationDate="2020-07-10T03:24:48.430" UserId="11058" Comment="edited tags" Text="|opengl|c++|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28944" PostHistoryTypeId="2" PostId="10012" RevisionGUID="ce7794c9-ffac-4290-98f8-afb7777bf48c" CreationDate="2020-07-10T04:39:48.520" UserId="13305" Text="Assumption: The 3D scene in your application uses z-axis that goes inwards the screen. That is, in view-space, a position with larger z value means a farther point. (This can be inferred from your code. You specified n=-1, f=1).&#xD;&#xA;&#xD;&#xA;Answer: If you are using OpenGL, yes. If you are using Direct3D, no.&#xD;&#xA;&#xD;&#xA;In OpenGL screen-space (Normalized device coordinate), larger z value means closer points. Hence the implementation of `ortho()`. negates z value.&#xD;&#xA;&#xD;&#xA;Direct3D uses a z-axis that goes outwards the screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="28945" PostHistoryTypeId="5" PostId="10012" RevisionGUID="98e44857-7d8c-4dd4-b8cc-a4545a53a237" CreationDate="2020-07-10T04:44:50.523" UserId="13305" Comment="added 150 characters in body" Text="Assumption: The 3D scene in your application uses z-axis that goes inwards the screen. That is, in view-space, a position with larger z value means a farther point. (This can be inferred from your code. You specified n=-1, f=1).&#xD;&#xA;&#xD;&#xA;Answer: If you are using OpenGL, yes. If you are using Direct3D, no.&#xD;&#xA;&#xD;&#xA;In OpenGL screen-space (Normalized device coordinate), larger z value means closer points. Hence the implementation of `ortho()`. it negates z value when specified larger `f` than `n`.&#xD;&#xA;&#xD;&#xA;Direct3D uses a z-axis that goes outwards the screen. Implementations for Direct3D projection matrices will not produce negated z when coupled with your application." ContentLicense="CC BY-SA 4.0" />
  <row Id="28946" PostHistoryTypeId="2" PostId="10013" RevisionGUID="627182c8-2801-4bcb-a138-50c17887a030" CreationDate="2020-07-10T07:24:19.800" UserId="13095" Text="Have a look at the first lines and the first image in the Perspective Projection section of [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html). For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.&#xD;&#xA;&#xD;&#xA;The issue is how OpenGL defines its coordinate systems. The view/camera space coordinate system is a left-handed system with the camera looking down the negative x-axis (left image). Clip space is defined in a right-handed coordinate system. So if you transform between them, you need to swap the z-axis.&#xD;&#xA;&#xD;&#xA;You used `ortho(-1, 1, -1, 1, -1, 1)`. If you use the same input parameters as the coordinates of your frustum, your view space z-axis is defined from `-1` to `1`. So your camera is looking into the positive z-direction which violates the definition that the camera has to look down the negative z-axis.&#xD;&#xA;&#xD;&#xA;Also, read the first sentence from the Perspective Projection section in the link:&#xD;&#xA;&#xD;&#xA;&gt; In perspective projection, a 3D point in a truncated pyramid frustum (eye coordinates) is mapped to a cube (NDC); the range of x-coordinate from [l, r] to [-1, 1], the y-coordinate from [b, t] to [-1, 1] and the z-coordinate from [-n, -f] to [-1, 1].&#xD;&#xA;&#xD;&#xA;The important part here is &quot;from [**-n**, **-f**] to [-1, 1]&quot;. So use `ortho(l, r, b, t, -n, -f)`. Or with numbers `ortho(-1, 1, -1, 1, 1, -1)`" ContentLicense="CC BY-SA 4.0" />
  <row Id="28947" PostHistoryTypeId="5" PostId="10013" RevisionGUID="9c6b3715-114d-4e6f-9324-a480033d4b0f" CreationDate="2020-07-10T07:30:39.630" UserId="13095" Comment="added 81 characters in body" Text="Have a look at the first lines and the first image in the Perspective Projection section of [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html). For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.&#xD;&#xA;&#xD;&#xA;The issue is how OpenGL defines its coordinate systems. The view/camera space coordinate system is a left-handed system with the camera looking down the negative x-axis (left image). Clip space is defined in a right-handed coordinate system. So if you transform between them, you need to swap the z-axis.&#xD;&#xA;&#xD;&#xA;You used `ortho(-1, 1, -1, 1, -1, 1)`. If you use the same input parameters as the coordinates of your frustum, your view space z-axis is defined from `-1` to `1`. So your camera is looking into the positive z-direction which violates the definition that the camera has to look down the negative z-axis. So you have to flip your frustum z-axis to be in accordance with the definition.&#xD;&#xA;&#xD;&#xA;Also, read the first sentence from the Perspective Projection section in the link:&#xD;&#xA;&#xD;&#xA;&gt; In perspective projection, a 3D point in a truncated pyramid frustum (eye coordinates) is mapped to a cube (NDC); the range of x-coordinate from [l, r] to [-1, 1], the y-coordinate from [b, t] to [-1, 1] and the z-coordinate from [-n, -f] to [-1, 1].&#xD;&#xA;&#xD;&#xA;The important part here is &quot;from [**-n**, **-f**] to [-1, 1]&quot;. So use `ortho(l, r, b, t, -n, -f)`. Or with numbers `ortho(-1, 1, -1, 1, 1, -1)`" ContentLicense="CC BY-SA 4.0" />
  <row Id="28948" PostHistoryTypeId="50" PostId="9919" RevisionGUID="2e1f34ae-981f-4bfd-918d-0131e777e2a5" CreationDate="2020-07-10T11:01:25.193" UserId="-1" />
  <row Id="28949" PostHistoryTypeId="5" PostId="10013" RevisionGUID="8cd07cb0-85e4-491a-afa9-392c02018f21" CreationDate="2020-07-10T16:42:04.470" UserId="13095" Comment="edited body" Text="Have a look at the first lines and the first image in the Perspective Projection section of [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html). For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.&#xD;&#xA;&#xD;&#xA;The issue is how OpenGL defines its coordinate systems. The view/camera space coordinate system is a left-handed system with the camera looking down the negative z-axis (left image). Clip space is defined in a right-handed coordinate system. So if you transform between them, you need to swap the z-axis.&#xD;&#xA;&#xD;&#xA;You used `ortho(-1, 1, -1, 1, -1, 1)`. If you use the same input parameters as the coordinates of your frustum, your view space z-axis is defined from `-1` to `1`. So your camera is looking into the positive z-direction which violates the definition that the camera has to look down the negative z-axis. So you have to flip your frustum z-axis to be in accordance with the definition.&#xD;&#xA;&#xD;&#xA;Also, read the first sentence from the Perspective Projection section in the link:&#xD;&#xA;&#xD;&#xA;&gt; In perspective projection, a 3D point in a truncated pyramid frustum (eye coordinates) is mapped to a cube (NDC); the range of x-coordinate from [l, r] to [-1, 1], the y-coordinate from [b, t] to [-1, 1] and the z-coordinate from [-n, -f] to [-1, 1].&#xD;&#xA;&#xD;&#xA;The important part here is &quot;from [**-n**, **-f**] to [-1, 1]&quot;. So use `ortho(l, r, b, t, -n, -f)`. Or with numbers `ortho(-1, 1, -1, 1, 1, -1)`" ContentLicense="CC BY-SA 4.0" />
  <row Id="28950" PostHistoryTypeId="5" PostId="10013" RevisionGUID="5c4cc129-a2e5-47fe-b06f-5d11c1fd2953" CreationDate="2020-07-10T17:41:33.543" UserId="13095" Comment="edited body" Text="Have a look at the first lines and the first image in the Perspective Projection section of [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html). For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.&#xD;&#xA;&#xD;&#xA;The issue is how OpenGL defines its coordinate systems. The view/camera space coordinate system is a right-handed system with the camera looking down the negative z-axis (left image). Clip space is defined in a left-handed coordinate system. So if you transform between them, you need to swap the z-axis.&#xD;&#xA;&#xD;&#xA;You used `ortho(-1, 1, -1, 1, -1, 1)`. If you use the same input parameters as the coordinates of your frustum, your view space z-axis is defined from `-1` to `1`. So your camera is looking into the positive z-direction which violates the definition that the camera has to look down the negative z-axis. So you have to flip your frustum z-axis to be in accordance with the definition.&#xD;&#xA;&#xD;&#xA;Also, read the first sentence from the Perspective Projection section in the link:&#xD;&#xA;&#xD;&#xA;&gt; In perspective projection, a 3D point in a truncated pyramid frustum (eye coordinates) is mapped to a cube (NDC); the range of x-coordinate from [l, r] to [-1, 1], the y-coordinate from [b, t] to [-1, 1] and the z-coordinate from [-n, -f] to [-1, 1].&#xD;&#xA;&#xD;&#xA;The important part here is &quot;from [**-n**, **-f**] to [-1, 1]&quot;. So use `ortho(l, r, b, t, -n, -f)`. Or with numbers `ortho(-1, 1, -1, 1, 1, -1)`" ContentLicense="CC BY-SA 4.0" />
  <row Id="28951" PostHistoryTypeId="50" PostId="9926" RevisionGUID="7b128e4d-5ac9-4dd3-a047-2ed889f132ac" CreationDate="2020-07-10T23:01:20.143" UserId="-1" />
  <row Id="28955" PostHistoryTypeId="2" PostId="10014" RevisionGUID="5cb10e08-cb53-46ac-b278-a2acce0c4e02" CreationDate="2020-07-11T14:11:35.913" UserId="6470" Text="I am new to rendering and I would like to calcualte UV partial derivatives of a cylinder shape, which is parameterized by radius $R$ and length $L$.&#xD;&#xA;&#xD;&#xA;Using cylindrical coordinate mapping, for a surface point $\mathbf{p}=(x,y,z)$, the UV map (normalized to $[0,1]$) is:&#xD;&#xA;$$&#xD;&#xA;(u,v) = \Big(\frac{\phi}{2\pi}, \frac{z}{L}\Big)\qquad \text{where} \quad \phi = \arctan \frac{y}{x}&#xD;&#xA;$$&#xD;&#xA;Then I compute the derivatives with respect to $\mathbf{p}$, that is:&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\frac{\partial u}{\partial \mathbf{p}} &amp; = \frac{1}{2\pi R^2} \Big( -y, x, 0\Big) = \frac{1}{2\pi R} \Big( -\sin\phi, \cos\phi, 0\Big)\\&#xD;&#xA;\frac{\partial v}{\partial \mathbf{p}} &amp;= \Big( 0, 0, \frac{1}{L}\Big)&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;Or equivalently:&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\frac{\partial \mathbf{p}}{\partial u} &amp; = 2\pi R \Big( -\frac{1}{\sin\phi}, \frac{1}{\cos\phi}, 0\Big)\\&#xD;&#xA;\frac{\partial \mathbf{p}}{\partial v} &amp;= \Big( 0, 0, L\Big)&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;Everything looks good until now.&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;In [pbrt-3](https://github.com/mmp/pbrt-v3), the relevant part of [`cylinder.cpp`](https://github.com/mmp/pbrt-v3/blob/9f717d847a807793fa966cf0eaa366852efef167/src/shapes/cylinder.cpp#L105) is: (i) UV same as above; (ii) $\partial \mathbf{p}/\partial u$ however is different:&#xD;&#xA;```c++&#xD;&#xA;Float u = phi / phiMax;&#xD;&#xA;Float v = (pHit.z - zMin) / (zMax - zMin);&#xD;&#xA;&#xD;&#xA;// Compute cylinder $\dpdu$ and $\dpdv$&#xD;&#xA;Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0);&#xD;&#xA;Vector3f dpdv(0, 0, zMax - zMin);&#xD;&#xA;```&#xD;&#xA;What am I missing here?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="28956" PostHistoryTypeId="1" PostId="10014" RevisionGUID="5cb10e08-cb53-46ac-b278-a2acce0c4e02" CreationDate="2020-07-11T14:11:35.913" UserId="6470" Text="UV partial derivatives of a cylinder shape primitive" ContentLicense="CC BY-SA 4.0" />
  <row Id="28957" PostHistoryTypeId="3" PostId="10014" RevisionGUID="5cb10e08-cb53-46ac-b278-a2acce0c4e02" CreationDate="2020-07-11T14:11:35.913" UserId="6470" Text="|rendering|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28958" PostHistoryTypeId="2" PostId="10015" RevisionGUID="003a84ba-6a01-473a-80d2-7755e620a65c" CreationDate="2020-07-11T17:56:21.870" UserId="48" Text="Yes, that's correct. Perspective-correct interpolation works by (for some quantity $u$ to be interpolated) calculating $u/z$ and $1/z$ at each vertex, linearly interpolating those values in screen space, then calculating $u = (u/z) / (1/z)$ at each sample point. This is done by the GPU hardware behind the scenes." ContentLicense="CC BY-SA 4.0" />
  <row Id="28959" PostHistoryTypeId="2" PostId="10016" RevisionGUID="47ca754b-8d74-450e-976b-2ac6b5787257" CreationDate="2020-07-11T19:11:52.980" UserId="48" Text="I think it's easiest to get the tangent frame by writing the forward mapping from $(u,v)$ to $\mathbf{p}$:&#xD;&#xA;$$&#xD;&#xA;    \mathbf{p}(u,v) = \begin{bmatrix} R \, \cos (2\pi u) \\ R \, \sin (2\pi u) \\ vL \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;Then you can see that the derivatives are:&#xD;&#xA;$$&#xD;&#xA;    \frac{\partial\mathbf{p}}{\partial u} = \begin{bmatrix} -2\pi R \, \sin(2\pi u) \\ 2\pi R \, \cos(2\pi u) \\ 0\end{bmatrix} = \begin{bmatrix} -2\pi y \\ 2\pi x \\ 0\end{bmatrix}, \qquad&#xD;&#xA;    \frac{\partial\mathbf{p}}{\partial v} = \begin{bmatrix} 0 \\ 0 \\ L \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;which matches the pbrt code.&#xD;&#xA;&#xD;&#xA;I think your derivation went wrong by assuming that $\partial\mathbf{p}/\partial u$ was the component-wise reciprocal of $\partial u / \partial{\mathbf{p}}$. It's not so simple, because the latter object is really the gradient of $u$, where $u$ is now considered as a scalar field defined over all space (not just on the cylinder). To invert this properly we really need another coordinate running perpendicular to $u$ in the $xy$ plane, so that we have a locally invertible mapping; then we can take its Jacobian matrix and invert that. We can use the radius $R$ as such a coordinate. Then we have the inverse mapping,&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;    u(x,y) &amp;= \frac{1}{2\pi} \arctan(y,x) \\&#xD;&#xA;    R(x,y) &amp;= \sqrt{x^2 + y^2}&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;whose Jacobian is:&#xD;&#xA;$$&#xD;&#xA;    \frac{\partial(u,R)}{\partial(x,y)} =&#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;        \tfrac{\partial u}{\partial x} &amp; \tfrac{\partial u}{\partial y} \\&#xD;&#xA;        \tfrac{\partial R}{\partial x} &amp; \tfrac{\partial R}{\partial y}&#xD;&#xA;    \end{bmatrix} =&#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;        -y/(2\pi R^2) &amp; x/(2\pi R^2) \\&#xD;&#xA;        x/R &amp; y/R&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;and the inverse of that is:&#xD;&#xA;$$&#xD;&#xA;    \frac{\partial(x,y)}{\partial(u,R)} =&#xD;&#xA;    -2\pi R \begin{bmatrix}&#xD;&#xA;        y/R &amp; -x/(2\pi R^2) \\&#xD;&#xA;        -x/R &amp; -y/(2\pi R^2)&#xD;&#xA;    \end{bmatrix} =&#xD;&#xA;    \begin{bmatrix}&#xD;&#xA;        -2\pi y &amp; x/R \\&#xD;&#xA;        2\pi x &amp; y/R&#xD;&#xA;    \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;from which you can then read off $\partial{(x,y)}/\partial u$ as the first column, which matches the result obtained for $\partial\mathbf{p}/\partial u$ above." ContentLicense="CC BY-SA 4.0" />
  <row Id="28964" PostHistoryTypeId="5" PostId="10013" RevisionGUID="e66f158d-85f6-4cc6-840e-8bc90d67974e" CreationDate="2020-07-12T10:42:09.620" UserId="13095" Comment="added 133 characters in body" Text="&gt; What could be the purpose behind that?&#xD;&#xA;&#xD;&#xA;Have a look at the first lines and the first image in the Perspective Projection section of [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html). For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.&#xD;&#xA;&#xD;&#xA;The issue is how OpenGL defines its coordinate systems. The view/camera space coordinate system is a right-handed system with the camera looking down the negative z-axis (left image). Clip space is defined in a left-handed coordinate system. So if you transform between them, you need to swap the z-axis. This is the whole purpose behind it, switching the handedness of the coordinate systems.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;You used `ortho(-1, 1, -1, 1, -1, 1)`. If you use the same input parameters as the coordinates of your frustum, your view space z-axis is defined from `-1` to `1`. So your camera is looking into the positive z-direction which violates the definition that the camera has to look down the negative z-axis. So you have to flip your frustum z-axis to be in accordance with the definition.&#xD;&#xA;&#xD;&#xA;Also, read the first sentence from the Perspective Projection section in the link:&#xD;&#xA;&#xD;&#xA;&gt; In perspective projection, a 3D point in a truncated pyramid frustum (eye coordinates) is mapped to a cube (NDC); the range of x-coordinate from [l, r] to [-1, 1], the y-coordinate from [b, t] to [-1, 1] and the z-coordinate from [-n, -f] to [-1, 1].&#xD;&#xA;&#xD;&#xA;The important part here is &quot;from [**-n**, **-f**] to [-1, 1]&quot;. So use `ortho(l, r, b, t, -n, -f)`. Or with numbers `ortho(-1, 1, -1, 1, 1, -1)`" ContentLicense="CC BY-SA 4.0" />
  <row Id="28965" PostHistoryTypeId="5" PostId="10013" RevisionGUID="ef1d90be-37c8-4ab8-8821-1c36cf55bdcf" CreationDate="2020-07-12T11:21:19.150" UserId="13095" Comment="deleted 799 characters in body" Text="&gt; What could be the purpose behind that?&#xD;&#xA;&#xD;&#xA;Have a look at the first lines and the first image in the Perspective Projection section of [this link](http://www.songho.ca/opengl/gl_projectionmatrix.html). For the answer to your question, it is not important that you used an orthographic projection, even though there is also a corresponding section in the link.&#xD;&#xA;&#xD;&#xA;The issue is how OpenGL defines its coordinate systems. Quote from the link:&#xD;&#xA;&#xD;&#xA;&gt; Note that the eye coordinates are defined in the right-handed coordinate system, but NDC uses the left-handed coordinate system. That is, the camera at the origin is looking along -Z axis in eye space, but it is looking along +Z axis in NDC.&#xD;&#xA;&#xD;&#xA;So if you transform between them, you need to swap the z-axis. This is the whole purpose behind it, switching the handedness of the coordinate systems.&#xD;&#xA;&#xD;&#xA;&gt; Is it standard to negate the z coordinate when constructing projection matrix?&#xD;&#xA;&#xD;&#xA;Depends on your API and how the coordinate systems are defined. In OpenGL, you need to do this." ContentLicense="CC BY-SA 4.0" />
  <row Id="28971" PostHistoryTypeId="5" PostId="10012" RevisionGUID="405f7a0d-19b6-4d50-b5f3-246a64a27c4b" CreationDate="2020-07-13T02:52:21.510" UserId="13305" Comment="deleted 122 characters in body" Text="I'm assuming your scene is constructed based on right-handed coordinates.&#xD;&#xA;&#xD;&#xA;If you are using OpenGL, yes. If you are using Direct3D, no.&#xD;&#xA;&#xD;&#xA;The projection matrix maps [-n, -f] into [0, 1]. This weird property comes from the fact that the eye coordinates are right-handed, but the clip space (NDC) uses left-handed coordinates. Hence the implementation of `ortho()`.&#xD;&#xA;&#xD;&#xA;Direct3D uses a z-axis that goes outwards the screen. Implementations for Direct3D projection matrices will not produce negated z when coupled with your application." ContentLicense="CC BY-SA 4.0" />
  <row Id="28972" PostHistoryTypeId="2" PostId="10019" RevisionGUID="7f2297d9-568a-42d3-9b29-48d8d02fd21e" CreationDate="2020-07-13T12:14:46.363" UserId="13273" Text="I am trying to put multiple depthbuffers into one Framebuffer.&#xD;&#xA;I want to use VR and render both eyes at the same time:&#xD;&#xA;&#xD;&#xA;that means, in the geometry stage I want to clone the incoming triangle to two outgoing triangles with a shift of the eye offset for layered rendering. Therefore I would like to have two RGB textures / maybe one RGB texture 2d array and two depthbuffers / a depthbuffer array&#xD;&#xA;&#xD;&#xA;here is my program code so far, the error occurred at the second last line of code and it is a GL_INVALID_ENUM error.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	GLError();&#xD;&#xA;	glGenFramebuffers(1, &amp;m_sFrameBufferInfo.m_nFrameBuffer);&#xD;&#xA;	GLError();&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, m_sFrameBufferInfo.m_nFrameBuffer);&#xD;&#xA;&#xD;&#xA;	//Left eye&#xD;&#xA;	GLuint textureLeft;&#xD;&#xA;	glGenTextures(1, &amp;textureLeft);&#xD;&#xA;	GLError();&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, textureLeft);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_nWindowWidth, m_nWindowHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	GLError();&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;	GLError();&#xD;&#xA;	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureLeft, 0);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	//right eye&#xD;&#xA;	GLuint textureRight;&#xD;&#xA;	glGenTextures(1, &amp;textureRight);&#xD;&#xA;	GLError();&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D, textureRight);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_nWindowWidth, m_nWindowHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;	GLError();&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;	GLError();&#xD;&#xA;	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textureRight, 0);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	//depth buffer&#xD;&#xA;	GLuint textureDepth;&#xD;&#xA;&#xD;&#xA;	glGenTextures(1, &amp;textureDepth);&#xD;&#xA;	GLError();&#xD;&#xA;	glBindTexture(GL_TEXTURE_2D_ARRAY, textureDepth);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, m_nWindowWidth, m_nWindowHeight,2 , 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glFramebufferTexture3D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_ARRAY, textureDepth, 2, 0);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;	glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;	GLError();&#xD;&#xA;&#xD;&#xA;Thanks for your help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="28973" PostHistoryTypeId="1" PostId="10019" RevisionGUID="7f2297d9-568a-42d3-9b29-48d8d02fd21e" CreationDate="2020-07-13T12:14:46.363" UserId="13273" Text="OpenGL Framebuffer with multiple Depthbuffers inside" ContentLicense="CC BY-SA 4.0" />
  <row Id="28974" PostHistoryTypeId="3" PostId="10019" RevisionGUID="7f2297d9-568a-42d3-9b29-48d8d02fd21e" CreationDate="2020-07-13T12:14:46.363" UserId="13273" Text="|opengl|frame-buffer|virtual-reality|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28975" PostHistoryTypeId="2" PostId="10020" RevisionGUID="53e11d7d-dc3c-4d63-b6b2-1ccbe055f863" CreationDate="2020-07-13T13:23:54.060" UserId="2654" Text="FBOs can only use a single depth image, but that image *can* be layered. Broadly speaking, VR multi-eye rendering ought to be done through layered FBO images for both the color and depth buffers.&#xD;&#xA;&#xD;&#xA;The problem with your code is that you can't use `glFramebufferTexture3D` to attach a layered image. You must use `glFramebufferTexture`.&#xD;&#xA;&#xD;&#xA;Also, you need to use layers for the color image as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="28978" PostHistoryTypeId="2" PostId="10022" RevisionGUID="5766e149-051a-4618-9dae-7b56f8798890" CreationDate="2020-07-14T16:46:25.173" UserId="7952" Text="PCSS is looking less attractive as a real time shadowing technique since it has limited performance, largely due to the size of the shadow map and the number of samplers that must be taken in order to get acceptable results. I would recommend implementing it anyway largely because the same techniques are used in other shadow generation algorithms and it is very well documented, so it is easy to find information that will help you out if you run into an issue. Also, there are plenty of use cases where PCSS is &quot;good enough&quot; so you can spend your energy on other aspects of your application. Especially given the wide range hardware that any given game can find itself running on. A high end machine with PCSS may not be &quot;the best use of resources&quot; but it certainly gives extra bang for the rendering buck.&#xD;&#xA;&#xD;&#xA;Also, once implemented, it isn't to difficult to migrate it to another algorithm like VSSM (Variance Soft Shadow Mapping) which requires 32bit buffers but allows for the use of smaller shadow maps. But VSSM isn't documented as well so it is more difficult to write from scratch. Nvidia has a good paper on the subject:[Link to Nvidia VSSM Paper][1]. They also have an application with code so you can compare the two algorithms side by side. &#xD;&#xA;&#xD;&#xA;The book Real-Time Shadows is a good reference for shadow mapping. And can usually be picked up used for a reasonable price.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://developer.download.nvidia.com/SDK/10/direct3d/Source/VarianceShadowMapping/Doc/VarianceShadowMapping.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="28981" PostHistoryTypeId="19" PostId="4146" RevisionGUID="44d41a4c-d0d6-41d4-b815-559a65f0e6e3" CreationDate="2020-07-14T17:18:47.013" UserId="-1" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:-1,&quot;DisplayName&quot;:&quot;Community&quot;}]}" />
  <row Id="28988" PostHistoryTypeId="2" PostId="10025" RevisionGUID="192d042c-1bdd-42f5-b97d-79c204784941" CreationDate="2020-07-15T15:43:31.347" UserId="13696" Text="I'm working on an app that lets users construct a 3D house, with the ultimate goal of it being 3D printable. I use various materials in the form of a height map constructed from an image, like this brick texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I map the brightness of each pixel to a height, like so:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But when you start combining wall panels side by side and at different angles, it can quickly get messy and you can end up with a self-intersecting mesh, not to mention many more polygons than are really necessary, all of which contribute to something which the 3D Printer slicer can't cope with. It *looks* like this but the geometry isn't clean enough to print it:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, currently everything in the app itself works directly with polygons. Since all of this ultimately is generated from grid-like data (the source images) it seems to me that some kind of voxel-based approach would be very suitable, and could potentially yield much better quality results. I have tested the approach of populating a grid directly from the source images, and that bit can be done very efficiently. But I'm having a hard time finding the right algorithm to then turn that grid data back into polygons ready for 3D printing.&#xD;&#xA;&#xD;&#xA;Most algorithms for turning voxel data into a polygon isosurface assume two things, as far as I can tell:&#xD;&#xA;&#xD;&#xA;1. That you have no prior knowledge of the underlying geometry&#xD;&#xA;2. That the geometry is a scalar field, rather than a &quot;boolean&quot; grid where the grid lines genuinely do correspond to the final geometry&#xD;&#xA;&#xD;&#xA;Whereas in my case:&#xD;&#xA;&#xD;&#xA;1. I have huge empty patches inside the building, but I can easily ignore those because I have a list of bounding boxes of where each wall panel exists&#xD;&#xA;2. I would like to take advantage of the fact that my data actually *is* gridlike in nature. Note that I can have 'diagonals' - this simple brick texture shown here is probably a little too simplistic, e.g. some roof tile textures use a lot more in-between heights:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Obviously something as simple as marching cubes could be adapted to take advantage of point 1 easily enough (just skip over sections of the grid which aren't contained within any of my bounding boxes) but I feel like marching cubes will yield WAY more polygons than necessary.&#xD;&#xA;&#xD;&#xA;Can anybody recommend any specific algorithms that might suit this scenario (where we have prior knowledge about the underlying geometry) or give me some search terms that I can use to research? I've been searching algorithms for generating isosurfaces, but my instinct tells me that what I'm working with here is actually subtly different because of the grid-like nature of the problem - e.g. are these even really &quot;voxels&quot; at all?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/n6D9T.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/41Sk2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/u4Eg1.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/CJFJH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28989" PostHistoryTypeId="1" PostId="10025" RevisionGUID="192d042c-1bdd-42f5-b97d-79c204784941" CreationDate="2020-07-15T15:43:31.347" UserId="13696" Text="Efficiently generating mesh for self-generated voxel grid" ContentLicense="CC BY-SA 4.0" />
  <row Id="28990" PostHistoryTypeId="3" PostId="10025" RevisionGUID="192d042c-1bdd-42f5-b97d-79c204784941" CreationDate="2020-07-15T15:43:31.347" UserId="13696" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28991" PostHistoryTypeId="2" PostId="10026" RevisionGUID="07d1361e-93bb-493f-b21d-142a0fe04ace" CreationDate="2020-07-15T16:56:53.933" UserId="13698" Text="I'm writing my own mesh renderer, and I previously was able to apply a normal map to a sphere, so I understand the basic process of applying a normal map. But my understanding is that in order to apply it, you need a consistent tangent space at every point on the mesh. It's possible on a sphere because you can calculate the spherical coordinates and then pick orthogonal tangents parallel to lines of longitude/latitude, but as far as I can tell, there's no clear way to do that to a mesh.&#xD;&#xA;&#xD;&#xA;To give a specific example, I found [this free .obj file](https://www.cgtrader.com/free-3d-models/character/woman/juliette-10781-sport-girl-free-3dpeople-model) online, and I can render it with textures, just without normal mapping. But I can open up the model in the generic Windows &quot;3D Viewer&quot;, and in that program, it has normal mapping applied, so clearly it's possible. I couldn't find anything online, is there a way to do this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28992" PostHistoryTypeId="1" PostId="10026" RevisionGUID="07d1361e-93bb-493f-b21d-142a0fe04ace" CreationDate="2020-07-15T16:56:53.933" UserId="13698" Text="How do you apply a normal map to a 3d mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28993" PostHistoryTypeId="3" PostId="10026" RevisionGUID="07d1361e-93bb-493f-b21d-142a0fe04ace" CreationDate="2020-07-15T16:56:53.933" UserId="13698" Text="|mesh|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28994" PostHistoryTypeId="5" PostId="10025" RevisionGUID="59ec3e08-a6e6-49af-81ba-902b58915805" CreationDate="2020-07-15T18:06:55.100" UserId="13696" Comment="added 70 characters in body" Text="I'm working on an app that lets users construct a 3D house, with the ultimate goal of it being 3D printable. I use various materials in the form of a height map constructed from an image, like this brick texture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I map the brightness of each pixel to a height, like so:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But when you start combining wall panels side by side and at different angles, it can quickly get messy and you can end up with a self-intersecting mesh, not to mention many more polygons than are really necessary, all of which contribute to something which the 3D Printer slicer can't cope with. It *looks* like this but the geometry isn't clean enough to print it:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, currently everything in the app itself works directly with polygons. Since all of this ultimately is generated from grid-like data (the source images) it seems to me that some kind of voxel-based approach would be very suitable, and could potentially yield much better quality results. I have tested the approach of populating a grid directly from the source images, and that bit can be done very efficiently. But I'm having a hard time finding the right algorithm to then turn that grid data back into polygons ready for 3D printing.&#xD;&#xA;&#xD;&#xA;Most algorithms for turning voxel data into a polygon isosurface assume two things, as far as I can tell:&#xD;&#xA;&#xD;&#xA;1. That you have no prior knowledge of the underlying geometry&#xD;&#xA;2. That the geometry is a scalar field, rather than a &quot;boolean&quot; grid where the grid lines genuinely do correspond to the final geometry. There could be fine scaled details that fall between the grid lines.&#xD;&#xA;&#xD;&#xA;Whereas in my case:&#xD;&#xA;&#xD;&#xA;1. I have huge empty patches inside the building, but I can easily ignore those because I have a list of bounding boxes of where each wall panel exists&#xD;&#xA;2. I would like to take advantage of the fact that my data actually *is* gridlike in nature. Note that I can have 'diagonals' - this simple brick texture shown here is probably a little too simplistic, e.g. some roof tile textures use a lot more in-between heights:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Obviously something as simple as marching cubes could be adapted to take advantage of point 1 easily enough (just skip over sections of the grid which aren't contained within any of my bounding boxes) but I feel like marching cubes will yield WAY more polygons than necessary.&#xD;&#xA;&#xD;&#xA;Can anybody recommend any specific algorithms that might suit this scenario (where we have prior knowledge about the underlying geometry) or give me some search terms that I can use to research? I've been searching algorithms for generating isosurfaces, but my instinct tells me that what I'm working with here is actually subtly different because of the grid-like nature of the problem - e.g. are these even really &quot;voxels&quot; at all?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/n6D9T.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/41Sk2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/u4Eg1.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/CJFJH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="28996" PostHistoryTypeId="2" PostId="10027" RevisionGUID="adbd4d9a-67c7-4c63-8eeb-e088890c0749" CreationDate="2020-07-15T19:14:54.490" UserId="13701" Text="I am currently trying to find topics for my master's thesis. I would really like to do something in the field of computer graphics, but I've been having trouble finding what are some current problems people are trying to solve. I don't consider myself very good in this area, but I am willing to learn.&#xD;&#xA;&#xD;&#xA;If you could provide some direction it would be very helpful.&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 4.0" />
  <row Id="28997" PostHistoryTypeId="1" PostId="10027" RevisionGUID="adbd4d9a-67c7-4c63-8eeb-e088890c0749" CreationDate="2020-07-15T19:14:54.490" UserId="13701" Text="What's a good research topic in Computer Graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="28998" PostHistoryTypeId="3" PostId="10027" RevisionGUID="adbd4d9a-67c7-4c63-8eeb-e088890c0749" CreationDate="2020-07-15T19:14:54.490" UserId="13701" Text="|raytracing|rendering|3d|2d|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="28999" PostHistoryTypeId="5" PostId="7809" RevisionGUID="c32f67f4-a0c3-44de-b9f7-70078d13dad7" CreationDate="2020-07-15T20:16:33.050" UserId="8157" Comment="removed irrelevant intro" Text="  I have played around with CPU assembly programming like Nasm, Tasm or Masm, but I'm really curious to know how GPU works now.&#xD;&#xA;  However, i'm quite confused when I look on internet. I've heard about Cuda and OpenCL, but it is not what I'm looking for.&#xD;&#xA;  I'd like to know how GPUs instructions are in RAM... What are the Nasm and Masm for most GPUs? What is the x86 or Z80 of GPUs (What are the different families of GPU)? Do you know a constructor opcodes reference manual?&#xD;&#xA;  I think I really need something to compare between the two Processing Units to make it clear, because GPU assembly programming seems to be an even harder subject to learn from on internet that CPU asm programming. I've also read that &quot;NVIDIA never released details on the instructions actually understood by their hardware&quot;, but it seems pretty surprising to me. Full post there: https://stackoverflow.com/questions/4660974/how-to-create-or-manipulate-gpu-assembler?newreg=e31519279ce949f087df6322dbf2bf4d&#xD;&#xA;&#xD;&#xA;Thanks for your help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="29000" PostHistoryTypeId="24" PostId="7809" RevisionGUID="c32f67f4-a0c3-44de-b9f7-70078d13dad7" CreationDate="2020-07-15T20:16:33.050" Comment="Proposed by 8157 approved by 209, 48 edit id of 532" ContentLicense="CC BY-SA 4.0" />
  <row Id="29001" PostHistoryTypeId="5" PostId="10006" RevisionGUID="7d23be08-88c9-46f5-bfa5-84008d0bada7" CreationDate="2020-07-15T20:16:55.303" UserId="5353" Comment="formatting: enumeration on new line for improved readability, capital D for dimensions" Text="I think it is more of a terminology shared specifically in the computer graphics community. The transformation $P$ results in a vector one-step-ahead from getting the actual projection. From a 3D position transformed with $P$, we can obtain both &#xD;&#xA;&#xD;&#xA;1) the 2D-projected position in normalized device coordinate (NDC) (by obtaining xy component)&#xD;&#xA;2) the depth (by obtaining the z component) in NDC&#xD;&#xA;&#xD;&#xA;This so-called projection matrix is designed specifically to satisfy the needs in the computer graphics pipeline. The key difference between an ordinary N-D-to-(N-1)-D projection is that the projection matrix results in 2D positions with &quot;depth&quot;, which is required for obtaining a depth map used for many purposes in the computer graphics pipeline.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29002" PostHistoryTypeId="24" PostId="10006" RevisionGUID="7d23be08-88c9-46f5-bfa5-84008d0bada7" CreationDate="2020-07-15T20:16:55.303" Comment="Proposed by 5353 approved by 209, 48 edit id of 535" ContentLicense="CC BY-SA 4.0" />
  <row Id="29003" PostHistoryTypeId="5" PostId="9992" RevisionGUID="fe868a1b-4d9b-4362-b757-ad22055db691" CreationDate="2020-07-15T20:17:04.957" UserId="13095" Comment="Fix some typos and grammar" Text="I've seen two different perspective projection matrices being used but I want to know which one of them is the best. I think that they both output the same but I'm not sure. So if anyone can help me select which one to use I would greatly appreciate it&#xD;&#xA;&#xD;&#xA;[![perspective projection matrix 1][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![perspective projection matrix 2][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gVMit.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ycuEv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29004" PostHistoryTypeId="24" PostId="9992" RevisionGUID="fe868a1b-4d9b-4362-b757-ad22055db691" CreationDate="2020-07-15T20:17:04.957" Comment="Proposed by 13095 approved by 209, 48 edit id of 533" ContentLicense="CC BY-SA 4.0" />
  <row Id="29005" PostHistoryTypeId="2" PostId="10028" RevisionGUID="4af1536e-c663-415c-b450-9bf4b8108487" CreationDate="2020-07-16T00:10:32.193" UserId="48" Text="There are numerous approaches to setting up tangent bases on a mesh, and unfortunately, no totally universal standard for how they are calculated.&#xD;&#xA;&#xD;&#xA;Tangents are based on the mesh's UV mapping, so that the tangent vector points (at least roughly) along the U axis in texture space, and the bitangent along the V axis. This means each triangle in a mesh has its own tangent basis (as long as the UV mapping is nondegenerate). This often gets converted into a smoothed tangent basis per vertex, much like you can create smoothed normals by setting each vertex normal to an average over the normals of the surrounding triangles. Different tools and engines might do the smoothing in different ways, might handle UV seams and mirroring differently, might orthonormalize the basis per vertex or per pixel or not at all, etc. [Here is a nice article](https://medium.com/@bgolus/generating-perfect-normal-maps-for-unity-f929e673fc57) to read if you want to know more. And as noted there, there is a method for tangent spaces called [mikktspace](http://www.mikktspace.com/) that is gradually gaining widespread support and might become a de facto standard.&#xD;&#xA;&#xD;&#xA;Object/character models like the one you linked usually have normal maps baked out from a content creation tool (e.g. based on an ultra-high-detail source mesh); ideally, you need the tangent basis you use in your renderer to match the tangent basis used in the tool to do the bake. Sometimes there will be vertex tangents stored in the mesh, but the .obj format doesn't support tangents so you would need to see if the model has tangents in one of the other formats, like .fbx.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29006" PostHistoryTypeId="2" PostId="10029" RevisionGUID="83859ea9-0d8e-4bc1-b19b-0f6b9d509e7a" CreationDate="2020-07-16T01:22:36.547" UserId="7073" Text="I'm working with a js/wasm/c++ program that uses object oriented programming when updating the OpenGL state.  There are corresponding c++ classes for VBOs (vertex buffer) and VAOs (vertex array).  When we call `vao.unbind();`, it simply calls `glBindVertexArray(0);`.  I'm seeing that unbinding the VAO does not unbind the corresponding VBOs.  One of the VAO's VBOs was still set as ARRAY_BUFFER_BINDING target. &#xD;&#xA;&#xD;&#xA;My question is: is it best practice to automatically unset the associated VBOs when you unset the VAO?  Or should I write a separate function that unsets the VAO's VBOs?&#xD;&#xA;&#xD;&#xA;With WebGL I'm seeing that it does not unbind the VBO when you unset the VAO, despite what [this reddit post][1] is saying.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.reddit.com/r/opengl/comments/beioq1/do_you_need_to_also_unbind_the_vertex_buffer/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29007" PostHistoryTypeId="1" PostId="10029" RevisionGUID="83859ea9-0d8e-4bc1-b19b-0f6b9d509e7a" CreationDate="2020-07-16T01:22:36.547" UserId="7073" Text="When unsetting a VAO, should you also unbind the associated VBOs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29008" PostHistoryTypeId="3" PostId="10029" RevisionGUID="83859ea9-0d8e-4bc1-b19b-0f6b9d509e7a" CreationDate="2020-07-16T01:22:36.547" UserId="7073" Text="|opengl|webgl|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29009" PostHistoryTypeId="2" PostId="10030" RevisionGUID="e81b2a5d-dfa7-4bdf-bcd9-1b2df9942804" CreationDate="2020-07-16T04:40:09.100" UserId="10332" Text="I am creating a fast fourier transform algorithm for the compute shader - i am no expert on how GPUs really run optimally so thought i would ask here.&#xD;&#xA;&#xD;&#xA;I have the option to calculate on the fly or precompute a lot of the trig function (cos and sin) values and store it in a read only float buffer.&#xD;&#xA;&#xD;&#xA;My question is, though i am aware cos() and sin() is fast, how do they compare to simply getting the value precomputed in a buffer instead?&#xD;&#xA;&#xD;&#xA;I don't mean a LUT here i do not need to interpolate between values from the buffer so i just get them values directly. I don't know how to really bench test shaders properly so i am unsure which is faster.&#xD;&#xA;&#xD;&#xA;Perhaps some one knows more info on this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29010" PostHistoryTypeId="1" PostId="10030" RevisionGUID="e81b2a5d-dfa7-4bdf-bcd9-1b2df9942804" CreationDate="2020-07-16T04:40:09.100" UserId="10332" Text="Reading from buffer versus calculating on the fly performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="29011" PostHistoryTypeId="3" PostId="10030" RevisionGUID="e81b2a5d-dfa7-4bdf-bcd9-1b2df9942804" CreationDate="2020-07-16T04:40:09.100" UserId="10332" Text="|compute-shader|hlsl|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29012" PostHistoryTypeId="2" PostId="10031" RevisionGUID="54674de6-4ee1-4f2c-8b49-90f85dc30f85" CreationDate="2020-07-16T08:27:39.667" UserId="5353" Text="&gt; My question is, though i am aware cos() and sin() is fast, how do they compare to simply getting the value precomputed in a buffer instead?&#xD;&#xA;&#xD;&#xA;This will depend on your shader code. &#xD;&#xA;&#xD;&#xA;- GPUs utilize latency hiding by executing independent ALU instructions while waiting for data to arrive from memory. &#xD;&#xA;- Accessing memory is usually the slowest operation on a GPU. &#xD;&#xA;&#xD;&#xA;If your shader code allows for latency hiding, it *may* be faster.&#xD;&#xA;&#xD;&#xA;The best option here is to profile the shader performance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; I don't know how to really bench test shaders properly so i am unsure which is faster.&#xD;&#xA;&#xD;&#xA;I think the easiest way would be to download [RenderDoc](https://renderdoc.org/) and get a frame capture of your application.&#xD;&#xA;&#xD;&#xA;After that, you click on the timing icon (shown red) to get some measurements.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Although these are not super accurate measurements, they're good enough and sort of representative of the application performance.&#xD;&#xA;&#xD;&#xA;For precise measurements, you'll need your GPU vendor's graphics profiling tools.&#xD;&#xA;&#xD;&#xA; - AMD has [Radeon Graphics Profiler (RGP)](https://gpuopen.com/rgp/)&#xD;&#xA; - NVIDIA has [NSight](https://developer.nvidia.com/tools-overview)&#xD;&#xA; - INTEL has [Graphics Performance Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vbnXI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29013" PostHistoryTypeId="5" PostId="10031" RevisionGUID="91c03d22-ad24-4550-829d-2c5fc355c88d" CreationDate="2020-07-16T08:32:59.563" UserId="5353" Comment="added 14 characters in body" Text="&gt; My question is, though i am aware cos() and sin() is fast, how do they compare to simply getting the value precomputed in a buffer instead?&#xD;&#xA;&#xD;&#xA;This will depend on your shader code and GPU model. &#xD;&#xA;&#xD;&#xA;- GPUs utilize latency hiding by executing independent ALU instructions while waiting for data to arrive from memory. &#xD;&#xA;- Accessing memory is usually the slowest operation on a GPU. &#xD;&#xA;&#xD;&#xA;If your shader code allows for latency hiding, it *may* be faster.&#xD;&#xA;&#xD;&#xA;The best option here is to profile the shader performance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; I don't know how to really bench test shaders properly so i am unsure which is faster.&#xD;&#xA;&#xD;&#xA;I think the easiest way would be to download [RenderDoc](https://renderdoc.org/) and get a frame capture of your application.&#xD;&#xA;&#xD;&#xA;After that, you click on the timing icon (shown red) to get some measurements.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Although these are not super accurate measurements, they're good enough and sort of representative of the application performance.&#xD;&#xA;&#xD;&#xA;For precise measurements, you'll need your GPU vendor's graphics profiling tools.&#xD;&#xA;&#xD;&#xA; - AMD has [Radeon Graphics Profiler (RGP)](https://gpuopen.com/rgp/)&#xD;&#xA; - NVIDIA has [NSight](https://developer.nvidia.com/tools-overview)&#xD;&#xA; - INTEL has [Graphics Performance Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vbnXI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29014" PostHistoryTypeId="2" PostId="10032" RevisionGUID="3529904a-65f2-4d9e-ab31-dfb0b45d60c9" CreationDate="2020-07-16T09:10:12.830" UserId="13702" Text="What I am trying to do is to become able to compare with reasonable accuracy two real world fabric/textures (colorwise speaking) at two distinct locations. I cant move them into single place to observe them close to each other and in the same light conditions.&#xD;&#xA;&#xD;&#xA;I was thinking about such &quot;protocol&quot;:&#xD;&#xA;1. print some &quot;test pattern&quot; on white paper (reference object)&#xD;&#xA;2. go into location 1 and take picture of object A close to reference object&#xD;&#xA;3. go into location 2 and take picture of object B close to reference object&#xD;&#xA;4. use some application/library/own code, to adjust colors on photo B so the reference object look similar (colorwise) to reference object on A&#xD;&#xA;5. compare visualy or statistically (programmaticaly) objects A and B&#xD;&#xA;&#xD;&#xA;Does anyone know what is the easiest way to perform point 4? Is there applicatation for that step, or library or any other shortcut than implementing this on my own? &#xD;&#xA;&#xD;&#xA;Or, maybe anyone knows application for the whole process, not particularly point 4, which could help me, or another protocol for performing such comparison? &#xD;&#xA;&#xD;&#xA;Also please let me know it this cant be done this way, or rather, this is oversimplified solution to provide &quot;reasonable accuracy&quot;, and if so - why?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29015" PostHistoryTypeId="1" PostId="10032" RevisionGUID="3529904a-65f2-4d9e-ab31-dfb0b45d60c9" CreationDate="2020-07-16T09:10:12.830" UserId="13702" Text="Aligning (matching) colors (white balance, brightness) of two scenes based on reference object" ContentLicense="CC BY-SA 4.0" />
  <row Id="29016" PostHistoryTypeId="3" PostId="10032" RevisionGUID="3529904a-65f2-4d9e-ab31-dfb0b45d60c9" CreationDate="2020-07-16T09:10:12.830" UserId="13702" Text="|color|brightness|image-comparison|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29017" PostHistoryTypeId="2" PostId="10033" RevisionGUID="9fb25bad-5f26-4838-80e7-a2644f0dc2f7" CreationDate="2020-07-16T11:38:58.120" UserId="7724" Text="No, you do not need to unbind the VBO's. VBO's are only added to the state of the VAO when that VAO is bound. So any previously bound VBO's will not alter the state of the VAO that you are going to bind. The state of a bound VAO can be changed with the following calls:&#xD;&#xA;&#xD;&#xA; - glEnableVertexAttribArray&#xD;&#xA; - glDisableVertexAttribArray&#xD;&#xA; - glVertexAttribPointer&#xD;&#xA; - glBindBuffer&#xD;&#xA;&#xD;&#xA;You can bind and unbind VBO's without a currently bound VAO and even share them amongst VAO's. The VBO is simply a pointer to a data container that can be used for multiple purposes." ContentLicense="CC BY-SA 4.0" />
  <row Id="29018" PostHistoryTypeId="5" PostId="10033" RevisionGUID="72b98278-eedc-4188-9ea3-2f13ec931686" CreationDate="2020-07-16T14:47:20.923" UserId="2654" Comment="added 33 characters in body" Text="No, you do not need to unbind the VBO's. VBO's are only added to the state of the VAO when that VAO is bound. So any previously bound VBO's will not alter the state of the VAO that you are going to bind. The state of a bound VAO can be changed with the following calls:&#xD;&#xA;&#xD;&#xA; - `glEnableVertexAttribArray`&#xD;&#xA; - `glDisableVertexAttribArray`&#xD;&#xA; - `glVertexAttribPointer`&#xD;&#xA; - `glBindBuffer(GL_ELEMENT_ARRAY_BUFFER)`&#xD;&#xA;&#xD;&#xA;You can bind and unbind VBO's without a currently bound VAO and even share them amongst VAO's. The VBO is simply a pointer to a data container that can be used for multiple purposes." ContentLicense="CC BY-SA 4.0" />
  <row Id="29019" PostHistoryTypeId="5" PostId="8728" RevisionGUID="f1d4cb04-e7c7-4b8d-a02a-7e54d4929856" CreationDate="2020-07-16T20:01:41.413" UserId="7952" Comment="rewrite" Text="So,&#xD;&#xA;&#xD;&#xA;A lot of folks would tell you that a 4x4 matrix is used so you can get a translation component rolled into your linear transformation. Meaning that with a 3x3 matrix you can only compute rotations, scales, and shears. (and some would argue that a shear is really another type of rotation) This same person might also go into great detail about affine transformations and homogeneous coordinate systems. And they would be right.&#xD;&#xA;&#xD;&#xA;But that's not the reason.&#xD;&#xA;&#xD;&#xA;All this might leave the astute observer thinking, well wouldn't a 3x3 matrix get the transformation out of the way then just use vector math to add our translation on at the end saving lots of special math, hardware, and precious resources?&#xD;&#xA;&#xD;&#xA;Well this is perfectly plausible, and a little extra thinking would leave use with the idea of adding a 4th column/row to our matrix giving a 3x4 matrix. Now, a translation is suddenly perfectly plausible and would create a pretty world where you can do all the operations needed to move and deform objects all day long saving lots of math and resource. And you would be right. You can in fact&#xD;&#xA;do this very thing when computing your Model and View matrices. Handling vectors would require a little extra trickery but we could manage it.&#xD;&#xA;&#xD;&#xA;So, now, on this theoretical video card, since all this has to be implemented in hardware, we have gotten or world models/meshs/blobs whatnots and whathaveyous all into place and are ready to project them from our 3D world onto our 2D screen. And we think: this too isn't a problem since a projection is really just a non-linear scaling operation that squeezes things around so the stuff we want to see falls inside our clipping volume. &#xD;&#xA;&#xD;&#xA;A little bit of algebra later...&#xD;&#xA;&#xD;&#xA;We have mountains of triangles all of which are ready to have their attributes computed, and interpolations...well interpolated. We then use standard interpolation, check our work very carefully and what we get on our video monitor looks like some kind of star trek space anomaly got hold of it.&#xD;&#xA;&#xD;&#xA;This is where the problem comes up: It turns out that you can't just interpolate values directly after performing a perspective projection. Instead you must use a special form of interpolation called...wait for it...Perspective Correct Interpolation. And the solution to perspective correct interpolation leads use to the correct form of the projection matrix which has 4 rows and 4 columns. That matrix after being applied to a 4 component position vector results in a nonzero value in the w component of the vector. This value will be specific to each triangle depending on how it is oriented. And, at long last, the video card hardware can perform interpolation on all the values for our triangles, including colors, texture coordinates, normal vectors, ect. Then when that it is all done, hardware can perform the &quot;perspective divide&quot; resulting in correctly interpolated values for the triangles, along with correctly interpolated attributes.&#xD;&#xA;&#xD;&#xA;And that is the real reason everyone everywhere uses 4x4 matrices in hardware and why they are littered throughout API's like OpenGL. Hardware vendors could probably hack their way around some of the math related to translations and transformations but when it comes to projection, you really can't get away from the 4x4 matrix. (but you can sure optimize the heck out of it)&#xD;&#xA;&#xD;&#xA;The math for deriving the correct form of a projection isn't to terribly complicated, but the full explanation is fairly long so I will defer to a good book for that, and the best explanation I have seen for deriving a projection matrix that will allow perspective correct interpolation is chapter 6, section 6.2 of the Lengyel book, &quot;Foundations of Game Engine Development&quot;.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29020" PostHistoryTypeId="13" PostId="8728" RevisionGUID="3ff7ab76-241f-4661-bdc6-30b858b3debc" CreationDate="2020-07-16T20:01:56.793" UserId="7952" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7952,&quot;DisplayName&quot;:&quot;pmw1234&quot;}]}" />
  <row Id="29021" PostHistoryTypeId="5" PostId="10031" RevisionGUID="d7a2393e-ade5-4b2a-9e56-99a22d771daa" CreationDate="2020-07-16T21:38:22.350" UserId="5353" Comment="added latency hiding captures" Text="&gt; My question is, though i am aware cos() and sin() is fast, how do they compare to simply getting the value precomputed in a buffer instead?&#xD;&#xA;&#xD;&#xA;This will depend on your shader code and GPU model. &#xD;&#xA;&#xD;&#xA;- GPUs utilize latency hiding by executing independent ALU instructions while waiting for data to arrive from memory. &#xD;&#xA;- Accessing memory is usually the slowest operation on a GPU. &#xD;&#xA;&#xD;&#xA;If your shader code allows for latency hiding, it *may* be faster.&#xD;&#xA;&#xD;&#xA;The best option here is to profile the shader performance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt; I don't know how to really bench test shaders properly so i am unsure which is faster.&#xD;&#xA;&#xD;&#xA;I think the easiest way would be to download [RenderDoc](https://renderdoc.org/) and get a frame capture of your application.&#xD;&#xA;&#xD;&#xA;After that, you click on the timing icon (shown red) to get some measurements.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Although these are not super accurate measurements, they're good enough and sort of representative of the application performance.&#xD;&#xA;&#xD;&#xA;For precise measurements, you'll need your GPU vendor's graphics profiling tools.&#xD;&#xA;&#xD;&#xA; - AMD has [Radeon Graphics Profiler (RGP)](https://gpuopen.com/rgp/)&#xD;&#xA; - NVIDIA has [NSight](https://developer.nvidia.com/tools-overview)&#xD;&#xA; - INTEL has [Graphics Performance Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Update**: Below are some captures from RGP, showing GPU assembly instructions and instruction timings of various instruction types. You can see latency hiding in action below:&#xD;&#xA;&#xD;&#xA;- `vmem` : texture read&#xD;&#xA;- `smem` : constant buffer / descriptor&lt;texture/buffer&gt; read&#xD;&#xA;- `ALU`  : math ops (arithmetic / logic)&#xD;&#xA;- `sync` : waits for vmem/smem instructions to finish loading data from memory&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Another capture showing instruction timings while first two texture loads not having latency hiding.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vbnXI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RDs6a.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/CqrG1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29022" PostHistoryTypeId="2" PostId="10034" RevisionGUID="5391dcae-aa1c-49dd-9430-564b6b536321" CreationDate="2020-07-17T01:37:46.813" UserId="11058" Text="In most modeling software you can texture paint onto 3d models using so called stencil textures. They basically project a texture from the viewport view onto the model as seen for instance in the image below from Blender.&#xD;&#xA;&#xD;&#xA;What is the general technique used to project textures like this onto 3d models?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ByHK2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EFrxb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29023" PostHistoryTypeId="1" PostId="10034" RevisionGUID="5391dcae-aa1c-49dd-9430-564b6b536321" CreationDate="2020-07-17T01:37:46.813" UserId="11058" Text="How are textures projected onto 3d models in texture painting applications" ContentLicense="CC BY-SA 4.0" />
  <row Id="29024" PostHistoryTypeId="3" PostId="10034" RevisionGUID="5391dcae-aa1c-49dd-9430-564b6b536321" CreationDate="2020-07-17T01:37:46.813" UserId="11058" Text="|opengl|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29025" PostHistoryTypeId="2" PostId="10035" RevisionGUID="bb56e138-0b85-4190-b306-a13416908f01" CreationDate="2020-07-17T08:33:04.307" UserId="13095" Text="I don't know if there is a smarter/more efficient way to do it, but a possible approach is the following:&#xD;&#xA;&#xD;&#xA;**Step 1 - Projection volume**&#xD;&#xA;&#xD;&#xA;First, you calculate the &quot;projection volume&quot; where its near plane corners are identical to the texture corners on your screen. You can do this by transforming the screen coordinates of the textures' corners into the range [-1, 1]. Then you use those coordinates to create a quad in NDC by combining the transformed x-y coordinates with z=-1 (near plane) and z=1 (far plane).&#xD;&#xA;&#xD;&#xA;**Step 2 - Collision test**&#xD;&#xA;&#xD;&#xA;Now you need to have both, your model and your &quot;projection volume&quot;, in the same space. You can either transform the &quot;projection volume&quot; into your model space or your model into NDC. I think the second choice makes the next step a little bit easier.&#xD;&#xA;&#xD;&#xA;Now you have to find all triangles that are fully or partially inside the &quot;projection volume&quot;. This is basically a collision detection check (triangle vs. quad or frustum) and I won't go into the details here. For all triangles that are fully inside the volume, you now have a connection between each vertex and its position inside the texture you want to project. Simply transform the vertex position into screen space and from there to the textures pixel coordinates. The second transformation depends on where you positioned your texture on the screen and how you have scaled it. &#xD;&#xA;&#xD;&#xA;For all partially covered triangles, the basic procedure is the same, but you have to introduce extra &quot;helper vertices&quot; and to transform them too to separate the covered from the uncovered areas. Doesn't mean that you have to really split your triangles into multiple smaller ones, but at least you need the extra vertices as intermediate data for the final step.&#xD;&#xA;&#xD;&#xA;**Step 3 - Adjust model data**&#xD;&#xA;&#xD;&#xA;In the last step, you have to bake this information somehow into your model. This totally depends on your model's data structure and layout. You can for example just split partially covered triangles into new ones and then set the `texCoord` of every vertex that is inside the &quot;projection volume&quot; accordingly. &#xD;&#xA;&#xD;&#xA;If you have some kind of model-specific  UV-mapped textures, you would now use the information of the previous step to interpolate and copy the data of your projected texture to your model texture. For each vertex, you know where it is located inside the projected texture and inside its models UV texture. Now you basically cut out each triangle from your projected texture, and transform it into the corresponding triangle in your UV texture. Notice that this is not trivial since the triangle usually gets distorted and scaled. However, you can use the graphics pipeline for that by rendering directly to your UV-texture.&#xD;&#xA;&#xD;&#xA;There are probably a lot of other data representations that might require a different approach for this final step. However, the key here is the second step which establishes the connection between your vertices and the texture. Once you have this, it shouldn't be too hard to come up with a method to add the projected texture to your model." ContentLicense="CC BY-SA 4.0" />
  <row Id="29026" PostHistoryTypeId="5" PostId="10035" RevisionGUID="588fd37a-2a42-4104-886e-7b4b4bf6a2ab" CreationDate="2020-07-17T08:39:06.813" UserId="13095" Comment="added 214 characters in body" Text="I don't know if there is a smarter/more efficient way to do it, but a possible approach is the following:&#xD;&#xA;&#xD;&#xA;**Step 1 - Projection volume**&#xD;&#xA;&#xD;&#xA;First, you calculate the &quot;projection volume&quot; where its near plane corners are identical to the texture corners on your screen. You can do this by transforming the screen coordinates of the textures' corners into the range [-1, 1]. Then you use those coordinates to create a quad in NDC by combining the transformed x-y coordinates with z=-1 (near plane) and z=1 (far plane).&#xD;&#xA;&#xD;&#xA;**Step 2 - Collision test**&#xD;&#xA;&#xD;&#xA;Now you need to have both, your model and your &quot;projection volume&quot;, in the same space. You can either transform the &quot;projection volume&quot; into your model space or your model into NDC. I think the second choice makes the next step a little bit easier.&#xD;&#xA;&#xD;&#xA;Now you have to find all triangles that are fully or partially inside the &quot;projection volume&quot;. This is basically a collision detection check (triangle vs. quad or frustum) and I won't go into the details here. For all triangles that are fully inside the volume, you now have a connection between each vertex and its position inside the texture you want to project. Simply transform the vertex position into screen space and from there to the textures pixel coordinates. The second transformation depends on where you positioned your texture on the screen and how you have scaled it. &#xD;&#xA;&#xD;&#xA;For all partially covered triangles, the basic procedure is the same, but you have to introduce extra &quot;helper vertices&quot; and to transform them too to separate the covered from the uncovered areas. Doesn't mean that you have to really split your triangles into multiple smaller ones, but at least you need the extra vertices as intermediate data for the final step.&#xD;&#xA;&#xD;&#xA;**Step 3 - Adjust model data**&#xD;&#xA;&#xD;&#xA;In the last step, you have to bake this information somehow into your model. This totally depends on your model's data structure and layout. You can for example just split partially covered triangles into new ones and then set the `texCoord` of every vertex that is inside the &quot;projection volume&quot; accordingly. &#xD;&#xA;&#xD;&#xA;If you have some kind of model-specific  UV-mapped textures, you would now use the information of the previous step to interpolate and copy the data of your projected texture to your model texture. For each vertex, you know where it is located inside the projected texture and inside its models UV texture. Now you basically cut out each triangle from your projected texture, and transform it into the corresponding triangle in your UV texture. Notice that this is not trivial since the triangle usually gets distorted and scaled. However, you can use the graphics pipeline for that by rendering directly to your UV-texture.&#xD;&#xA;&#xD;&#xA;There are probably a lot of other data representations that might require a different approach for this final step. However, the key here is the second step which establishes the connection between your vertices and the texture. Once you have this, it shouldn't be too hard to come up with a method to add the projected texture to your model.&#xD;&#xA;&#xD;&#xA;**Further information**&#xD;&#xA;&#xD;&#xA;During the second step, you might also need to perform some kind of depth testing, so that only the closest area gets affected and not all sides that are inside the projection volume." ContentLicense="CC BY-SA 4.0" />
  <row Id="29027" PostHistoryTypeId="50" PostId="9549" RevisionGUID="4bcce2e5-f386-4300-a80b-44587e822404" CreationDate="2020-07-17T10:01:15.133" UserId="-1" />
  <row Id="29028" PostHistoryTypeId="2" PostId="10036" RevisionGUID="c1f581d8-cf90-4629-b6dc-7888ae415e5b" CreationDate="2020-07-17T11:45:47.250" UserId="523" Text="**After more analysis, the TL;DR here is that, yes, the slowdown is due to memory locality, and yes the pixel order is to blame.  More interestingly, by writing the shader differently, we can _greatly surpass_ the fragment shader's performance—though we obviously shouldn't _rely_ on being able to do that regularly.**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;First, to expand on the analysis: the best way to figure out what's going on in the GPU is to ask it.  In this case, the relevant tool is NVIDIA NSight.  After some fiddling, I got directly comparable results, which indicated that in both cases, memory is the bottleneck, and in the compute shader's case, it is worse.&#xD;&#xA;&#xD;&#xA;Since the actual shader code is substantively identical at the assembly level (see above), and (slightly-better-than-)equal performance can be achieved by removing memory from the equation by altering the shading code, we can be confident that the pixel shading order is to blame.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Perhaps we can find a better shading order?&#xD;&#xA;&#xD;&#xA;Spoiler alert: we can.  After some experimentation, consider a new shader where there is a global queue of tiles, and each warp grabs a tile and shades the pixels within it in scanline order.  This turns out to be 50% _faster_ than the fragment shader!&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here's an animation from [my HPG paper](https://graphics.geometrian.com/research/dacs_in_hw.html)'s presentation this week, which touched on this issue:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;(It can be embiggened, which you may wish to do if you're having trouble reading the text.)&#xD;&#xA;&#xD;&#xA;This summarizes the results of these experiments, along with the performance numbers for each and a visualization of what I surmise is going on behind the scenes (simplified: only one warp is shown, it is 8 wide, and latency-hiding is not visualized).&#xD;&#xA;&#xD;&#xA;On the left, we have the fragment shader, labeled &quot;Vendor Magic Goes Here&quot;.  We don't know what the vendor is doing for their fragment shader pixel traversal order (though we could get hints e.g. by writing out atomic variables, etc.), but overall it works really well.&#xD;&#xA;&#xD;&#xA;In the middle, we have the original compute shader I described (with `param` = `0`), which divides the framebuffer into rectangular work groups.  Notice that the work groups are probably executed in a mostly reasonable order exactly to mitigate these caching effects, but are not guaranteed to be in any order at all—and indeed will not be due to latency hiding: this explains why the groups are walking over the framebuffer in a mostly coherent fashion, but still skipping around a little bit.  This is half the speed of the fragment shader, and I believe the possible skipping around is a reasonable starting guess for the additional memory incoherency revealed within the profile.&#xD;&#xA;&#xD;&#xA;Finally, we have the tiles version.  Because tiles are processed in a queue of tiles (defined by a global counter, visualized above the tile), the tiles and pixels are processed more in order (neglecting latency hiding and other thread groups).  I believe this is a reasonable starting guess as to why this result turns out to be 50% _faster_ than the fragment shader.&#xD;&#xA;&#xD;&#xA;It is important to stress that, while these results are correct for this particular experiment, with these particular drivers, _these results do **not** necessarily generalize.  This is likely specific to this particular scene, view, and platform configuration, and this behavior may actually even be a bug.  This is definitely interesting to play with, but don't go ripping apart your renderer (only) because of one datapoint from a narrowly-defined experiment._&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Indeed, what kicked off this whole investigation was that the performance of a (more-complex) compute shader had declined in relative performance since it was last profiled in 2018, using the same code on the same hardware.  The only difference was an updated driver.&#xD;&#xA;&#xD;&#xA;The lesson is simple: pixel shading orders are hard, and as much as possible they are best left to the GPU vendor to determine.  Compute shaders give us the option to do shading-like operations, but we should not expect to be able to _reliably_ exceed the performance of fragment shaders (even if, occasionally, we spectacularly can) because our implementations are not based on insider knowledge of how to optimize for the particular GPU—even when there _is_ a single particular GPU at all.&#xD;&#xA;&#xD;&#xA;So, if you're thinking about shading orders, that's really something the GPU should be doing for you: take it up with the vendor.  The main reason to use a compute shader would be if you want the convenience or flexibility.  Of course, if you thoroughly profile and see a performance gain, and you have reason to expect that the GPU infrastructure you are building on top of will not shift beneath your feet (e.g. you are writing for a console), then maybe using a compute shader is the right choice.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NPvbf.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="29030" PostHistoryTypeId="2" PostId="10037" RevisionGUID="c8176c3b-5169-4a0d-8676-7266a9975ac2" CreationDate="2020-07-17T12:49:20.397" UserId="2372" Text="This is a quite wide subject which implies a lot of topics such as the platform or the compiler, but I think that it could be useful for everyone to know more about this.&#xD;&#xA;&#xD;&#xA;A common mistake is to think that conditionals are bad when writing shader but the real bad thing is branching, right ?&#xD;&#xA;&#xD;&#xA;I would love to know more about the difference between conditionals and branching with simple concrete examples and how to solve common issues.&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="29031" PostHistoryTypeId="1" PostId="10037" RevisionGUID="c8176c3b-5169-4a0d-8676-7266a9975ac2" CreationDate="2020-07-17T12:49:20.397" UserId="2372" Text="Conditionals and branching in shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="29032" PostHistoryTypeId="3" PostId="10037" RevisionGUID="c8176c3b-5169-4a0d-8676-7266a9975ac2" CreationDate="2020-07-17T12:49:20.397" UserId="2372" Text="|opengl|rendering|shader|optimisation|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29033" PostHistoryTypeId="2" PostId="10038" RevisionGUID="a0828587-5695-445e-959f-a7d2987e1054" CreationDate="2020-07-17T15:59:40.080" UserId="13273" Text="is it worse to do for each invocation an atomicAdd on the same memory location than doing for each invocation an atomicAdd to a unique memory location? (I know, atomicAdd does not make sense when each invocation writes to another location... but this is theoretically)&#xD;&#xA;&#xD;&#xA;I am asking, because I wrote the marching cubes algorithm and while creating the mesh I additionally want to calculate the center of mass as well.&#xD;&#xA;&#xD;&#xA;I am doing this by having four integers in the SSBO (centerX, centerY, centerZ and countTriangles)&#xD;&#xA;each of these 4 integers will be increased by the atomicAdd function within the GeometryShader.&#xD;&#xA;When everything is done, I only need to divide the centerX/Y/Z variable by countTriangles and I am done.&#xD;&#xA;&#xD;&#xA;if these atomics on one memory location would slow down my shader, I would outsource it to another maybe CPU function.&#xD;&#xA;&#xD;&#xA;Thanks in advance " ContentLicense="CC BY-SA 4.0" />
  <row Id="29034" PostHistoryTypeId="1" PostId="10038" RevisionGUID="a0828587-5695-445e-959f-a7d2987e1054" CreationDate="2020-07-17T15:59:40.080" UserId="13273" Text="Does atomic functions on same memory location cause an performance issue?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29035" PostHistoryTypeId="3" PostId="10038" RevisionGUID="a0828587-5695-445e-959f-a7d2987e1054" CreationDate="2020-07-17T15:59:40.080" UserId="13273" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29037" PostHistoryTypeId="2" PostId="10040" RevisionGUID="2c076d4c-cb94-4ae9-bf48-240eeff0fe83" CreationDate="2020-07-17T17:54:20.457" UserId="2654" Text="Will having all invocations incrementing the same atomic counter be slower than not doing that? Sure. How much slower? That depends on many factors, but it's hardly going to be a crippling performance issue.&#xD;&#xA;&#xD;&#xA;The whole point of atomic memory operations is that there is some hardware mechanism that allows them to work reasonably efficiently. Not as efficiently as bumping a local variable of course, but they shouldn't be assumed to cause a massive performance penalty.&#xD;&#xA;&#xD;&#xA;Obviously, the best thing you can do is profile on your hardware-of-choice, but failing that, I would see no reason not to use this mechanism as you see fit." ContentLicense="CC BY-SA 4.0" />
  <row Id="29039" PostHistoryTypeId="2" PostId="10041" RevisionGUID="6866272b-beee-4e5d-9577-9f0fc061bb85" CreationDate="2020-07-18T09:20:52.260" UserId="13711" Text="https://www.shadertoy.com/view/MldczM&#xD;&#xA;Is ANALYTIC intersection of a ray with a triangular b-spline , 3 quadratic bezier splines, 3 CVs foreach spline, 3 corner CVs are shared by 2 splines. All cv heights are orthogonal to thr triangle plane. It solves for &lt;=2 roots in barycentric coordinates. Thrres never 3 intersections, so this is surprisingly simöle tracing of a curved function.&#xD;&#xA;First derivative is super short, too.&#xD;&#xA;&#xD;&#xA;ESDF keys for camera movement&#xD;&#xA;The parent shader in the cömments has less optlmised less precise more repetitive naive simpler code.&#xD;&#xA;&#xD;&#xA;It szill has the error of rendering the negative surface iff the camera is inside the prism of the triangle (above or below triangle), this seems to be a simpler special case, with only 1 root, where it fails to ignore the other root. The branch to solve this may be rather somple." ContentLicense="CC BY-SA 4.0" />
  <row Id="29040" PostHistoryTypeId="50" PostId="9048" RevisionGUID="27966674-fc80-4350-98c0-034fb67e1b70" CreationDate="2020-07-18T18:07:35.750" UserId="-1" />
  <row Id="29041" PostHistoryTypeId="2" PostId="10042" RevisionGUID="18bab9ac-7701-42dd-bbfb-064206913d2c" CreationDate="2020-07-19T12:56:38.460" UserId="13717" Text="Classical Phong reflection model, as described on [wikipedia](https://en.wikipedia.org/wiki/Phong_reflection_model), computes diffuse and specular light as follows:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;vec3 diffuse = kd * dot(n, l) * i;&#xD;&#xA;vec3 specular = ks * pow(dot(r, v), a) * i;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Where `n`, `l`, `r`, `v` are the normal, light, reflection and view vectors, `kd`, `ks` are surface diffuse and specular color, `a` is gloss and `i` is incoming light intensity.&#xD;&#xA;&#xD;&#xA;I understand that the diffuse term is such as it is because 1) diffuse reflection is not dependent on viewer direction and 2) surfaces angled away from light recieve less light to scatter, thus the `dot(n, l)` term.&#xD;&#xA;&#xD;&#xA;However, shouldn't the specular term **also** be multiplied by `dot(n, l)` for the same reason? Is my assumtion that `dot(n, l)` computes incoming light wrong?&#xD;&#xA;&#xD;&#xA;I know that the Phong model is mostly a hack, but this seems like a simple and performant modification and I haven't found this issue discussed anywhere. I've also looked into the source code of the game Tesseract, which does seem to multiply the specular term by `dot(n, l)`." ContentLicense="CC BY-SA 4.0" />
  <row Id="29042" PostHistoryTypeId="1" PostId="10042" RevisionGUID="18bab9ac-7701-42dd-bbfb-064206913d2c" CreationDate="2020-07-19T12:56:38.460" UserId="13717" Text="Phong model: why no multiplication by N dot L in specular term?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29043" PostHistoryTypeId="3" PostId="10042" RevisionGUID="18bab9ac-7701-42dd-bbfb-064206913d2c" CreationDate="2020-07-19T12:56:38.460" UserId="13717" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29044" PostHistoryTypeId="5" PostId="10040" RevisionGUID="90a8caaa-eb0d-4557-a5ea-88381f2d0bd2" CreationDate="2020-07-19T13:55:58.750" UserId="2654" Comment="added 282 characters in body" Text="Will having all invocations incrementing the same atomic counter be slower than not doing that? Sure. How much slower? That depends on many factors, but it's hardly going to be a crippling performance issue.&#xD;&#xA;&#xD;&#xA;The whole point of atomic memory operations is that there is some hardware mechanism that allows them to work reasonably efficiently. Not as efficiently as bumping a local variable of course, but they shouldn't be assumed to cause a massive performance penalty.&#xD;&#xA;&#xD;&#xA;On some hardware, atomic counter operations aren't even memory operations. AMD implements them as specialized hardware within their shader system, such that atomic counter operations don't touch actual memory storage until after the rendering process that uses them is complete.&#xD;&#xA;&#xD;&#xA;Obviously, the best thing you can do is profile on your hardware-of-choice, but failing that, I would see no reason not to use this mechanism as you see fit." ContentLicense="CC BY-SA 4.0" />
  <row Id="29045" PostHistoryTypeId="2" PostId="10043" RevisionGUID="215a1f00-51cc-4dfb-8480-b507782bd0de" CreationDate="2020-07-20T03:06:33.380" UserId="11099" Text="I'm playing around with DirectX 12 ray tracing, and I'm  trying to read and write data to a 32-bit RGBA floating point RWTexture2DArray within a DirectX 12 HLSL shader. I'm getting weird corruption/noise when I read back values I've written to the texture.&#xD;&#xA;&#xD;&#xA;I've bound the texture as a UAV, and in my shader I've tagged it with the &quot;globallycoherent&quot; like so:&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;globallycoherent RWTexture2DArray&lt;float4&gt;	myTextureArray;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;I'm able to demonstrate the issue I'm seeing with a trivial bit of shader code:&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;myTextureArray[xIndex, yIndex, 0] = float4((float)xIndex / (float)xRes, (float)yIndex / (float)yRes, 0.0f, 1.0f);&#xD;&#xA;&#xD;&#xA;myOutputTexture[xIndex, yIndex] = myTextureArray[xIndex, yIndex, 0];&#xD;&#xA;````&#xD;&#xA;For the sake of a simple demonstration, I'm just writing increasing values of red along the x axis, and increasing values of green along the y axis, and storing them into the first slice of my 32-bit floating point RGBA RWTexture2DArray. Then, I'm immediately reading the values back from the same position.&#xD;&#xA;&#xD;&#xA;Unfortunately, even with this trivial bit of code, when I read the values back they're often garbled. I've got a screenshot of the results, notice the weird, speckled noise in the output:&#xD;&#xA;&#xD;&#xA;[![Notice the weird noise?d][1]][1]&#xD;&#xA;&#xD;&#xA;I'm relatively new to DirectX12/HLSL, and I have a feeling I'm likely missing something simple. I've consulted [the Microsoft documentation][2], which states you can both read and write to a RWTexture2DArray, and I'm using the &quot;globallycoherent&quot; prefix as instructed.&#xD;&#xA;&#xD;&#xA;I'm using NVidia Falcor as a wrapper for some DXR experiments, so it's possible either I've missed some specific configuration (or, there's a bug in their implementation). If you can think of anything I might have missed, or might not be understanding, I'd be very appreciative of your help! I'm trying to use an array of textures as a buffer to hold various data elements (positions, indexes, etc etc), so if there's an easier/better way, let me know!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/skXpD.jpg&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwtexture2darray" ContentLicense="CC BY-SA 4.0" />
  <row Id="29046" PostHistoryTypeId="1" PostId="10043" RevisionGUID="215a1f00-51cc-4dfb-8480-b507782bd0de" CreationDate="2020-07-20T03:06:33.380" UserId="11099" Text="Corrupt values when writing and reading from the same RWTexture2D in HLSL/DirectX?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29047" PostHistoryTypeId="3" PostId="10043" RevisionGUID="215a1f00-51cc-4dfb-8480-b507782bd0de" CreationDate="2020-07-20T03:06:33.380" UserId="11099" Text="|shader|texture|hlsl|directx12|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29048" PostHistoryTypeId="2" PostId="10044" RevisionGUID="f982ccbe-ebee-403a-8c74-b9a938748d9a" CreationDate="2020-07-20T21:10:34.923" UserId="523" Text="The $N \cdot L$ term (I've seen &quot;geometry term&quot; thrown around; not quite accurate, but good enough for here) is part of the rendering equation.  What you're looking at here is an estimate of the inside of the rendering equation—that is, the incoming radiance `i` times the geometry term `dot(n,l)` times the BRDF.&#xD;&#xA;&#xD;&#xA;The simple answer for why the Phong BRDF doesn't include the geometry term is &quot;Well, it probably should, but the Phong model predates the invention of the rendering equation by more than a decade.&quot;.&#xD;&#xA;&#xD;&#xA;&gt; Phong, B.T.: Illumination for computer generated pictures.  Communications of the ACM **18**(6), 311–317 (1975).&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&gt; Kajiya, J.T.: The rendering equation.  In: Proceedings of the 13th Annual Conference on Computer Graphics and Interactive Techniques, SIGGRAPH ’86, pp. 143–150.  ACM, New York, NY, USA (1986).&#xD;&#xA;&#xD;&#xA;This deficiency was fixed in what is now called the Modified Phong BRDF:&#xD;&#xA;&#xD;&#xA;&gt; Lewis, R.R.: Making Shaders More Physically Plausible.  Computer Graphics Forum **13**(2), 109–120 (1994)&#xD;&#xA;&#xD;&#xA;At the end of the day, whether the term is present or not isn't an issue of correctness per-se.  Not having the geometry term when you might expect it just means that the BRDF corresponds to a different surface reflection that doesn't foreshorten much at glancing angles.  Indeed, many other BRDFs have terms that look like reciprocal geometry terms, so that they cancel with the actual geometry term in the rendering equation.&#xD;&#xA;&#xD;&#xA;In code, the BRDFs look like:&#xD;&#xA;&#xD;&#xA;    vec3 f_phong    = rho_s/(TWO_PI/(a+1.0)) * pow(max(0.0,dot(r,v)),a) / dot(n,l);&#xD;&#xA;    vec3 f_modphong = rho_s/(TWO_PI/(a+2.0)) * pow(max(0.0,dot(r,v)),a);&#xD;&#xA;&#xD;&#xA;And so when multiplied by the light and geometry term in the rendering equation (i.e., `i * f * dot(n,l)`), you get:&#xD;&#xA;&#xD;&#xA;    vec3 spec_phong    = i * rho_s/(TWO_PI/(a+1.0)) * pow(max(0.0,dot(r,v)),a);&#xD;&#xA;    vec3 spec_modphong = i * rho_s/(TWO_PI/(a+2.0)) * pow(max(0.0,dot(r,v)),a) * dot(n,l);&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The obvious should be noted, however: while the Phong BRDF is simple to understand and implement, it is of limited accuracy on real-world materials.  It's not terrible, the way many people think it is, but it does lack important features that can be important on many materials.  It is not the state-of-the-art, and depending on your needs you may like to look elsewhere (GGX microfacet, etc.) for more modern BRDFs." ContentLicense="CC BY-SA 4.0" />
  <row Id="29049" PostHistoryTypeId="2" PostId="10045" RevisionGUID="b5a06023-2648-4cce-839a-3168b0438d9d" CreationDate="2020-07-20T23:20:04.790" UserId="10193" Text="This is standard Cook-Torrance BRDF in formulation for a single point light. No intergrals over a hemisphere, just a single direction to a source of incoming energy.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o = { \bigg (  (1-F) \frac{albedo  \cdot  (1-metallness)}{\pi} + \frac{F \cdot D \cdot G_2}{4 (n \cdot v)(n \cdot l_i) } \bigg )  \cdot L_i  \cdot  (n \cdot l_i ) }&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;* $L_o$ - outgoing pixel energy&#xD;&#xA;* $L_i$ - incoming energy&#xD;&#xA;* $l_i$ - direction to a light source&#xD;&#xA;* $n$ - pixel normal&#xD;&#xA;* $v$ - direction to the camera&#xD;&#xA;* $F$ - calculated Fresnel, ratio of specularly reflected energy, in range [0; 1]&#xD;&#xA;* $D$ - calculated integral of GGX NDF over some set of possible micronormal directions (depends on light source size), in range [0; 1]&#xD;&#xA;* $G_2$ - calculated Smith geometry masking factor, in range [0; 1]&#xD;&#xA;&#xD;&#xA;Usually $D$ in papers is just NDF sampled at one point, which is, of couse, won't give correct value, since it's a probablity density function and its values may exceed [0; 1] range.&#xD;&#xA;&#xD;&#xA;$G_2 = G_1(v) * G_1(l)$ doesn't go higher than 1 if we use this Smith $G_1$ formulation:&#xD;&#xA;&#xD;&#xA;$G_1(dir) = \frac{2 (n \cdot dir)}{(n \cdot dir)+ \sqrt{a^2 + (1 - a^2) (n \cdot dir)^2}}$ , so it's good as well as $F$.&#xD;&#xA;&#xD;&#xA;$(n \cdot l_i )$ in the denominator is cancelled out for the specular part.&#xD;&#xA;&#xD;&#xA;**Question 1:** what's wrong with the $(n \cdot v )$ in the specular denominator? At grazing angles why do we need to divide the specular part by some small value getting big values as result? Or should it be cancelled out due to the fact that we render on per-pixel basis and a pixel covers bigger area of surface at grazing angles and already takes whis divider into accout?&#xD;&#xA;&#xD;&#xA;**Question 2:** there are some &quot;approximation&quot; of Smith $G_2$ like this (Earl Hammon, PBR Diffuse Lighting for GGX + Smith Microsurfaces, GDC 2017):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{G_2}{4 (n \cdot v) (n \cdot l)} = \frac{0.5}{lerp((n \cdot v) \cdot (n \cdot l), (n \cdot v) + (n \cdot l), \alpha) }&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Again, why this one gives large values when dot products are close to zero?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29050" PostHistoryTypeId="1" PostId="10045" RevisionGUID="b5a06023-2648-4cce-839a-3168b0438d9d" CreationDate="2020-07-20T23:20:04.790" UserId="10193" Text="BRDF for point lights should not return values over 1" ContentLicense="CC BY-SA 4.0" />
  <row Id="29051" PostHistoryTypeId="3" PostId="10045" RevisionGUID="b5a06023-2648-4cce-839a-3168b0438d9d" CreationDate="2020-07-20T23:20:04.790" UserId="10193" Text="|brdf|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29052" PostHistoryTypeId="2" PostId="10046" RevisionGUID="c2039de2-6d58-4a76-a274-996447e4e41a" CreationDate="2020-07-21T00:31:45.437" UserId="7462" Text="I implemented Djikstra's shortest path algorithm to approximate Geodesics on arbitrary meshes. Djikstra's works, but I noticed a problem inherent to the discretization of my meshes.&#xD;&#xA;&#xD;&#xA;Consider the following figure squence:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is my current refinement algorithm which is the easiest/standard face subdivision. Now consider the approximation of a geodesic in 2 points:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The blue point is where I think the actual geodesic intersects that edge, which is quite far from where the approximated geodesic passes. However that path ISN'T wrong.&#xD;&#xA;&#xD;&#xA;Consider a square grid. The distance between any 2 points in the grid is the manhattan distance  |x| + |y|.&#xD;&#xA;&#xD;&#xA;So as far as Djikstra's is concerned, a path that goes all the way down and then to the left has the same length as a path that goes diagonally in a staircase pattern. Refining the mesh won't change the distance either. In other words, the limit of the shortest path found by Djikstra in a regular square grid as the size of the squares goes to 0 is NOT the straigtht line connecting 2 points.&#xD;&#xA;&#xD;&#xA;Now the actual question, does anyone know of a way to subdivide my surface that is fairly straightforward but will actually converge to the geodesic?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/T0yKn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XS7Mu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/5BIz1.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/aQ0Qp.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/6aRG4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29053" PostHistoryTypeId="1" PostId="10046" RevisionGUID="c2039de2-6d58-4a76-a274-996447e4e41a" CreationDate="2020-07-21T00:31:45.437" UserId="7462" Text="Approximating Geodesics in a half edge DS, how can I refine my mesh to get good approximations" ContentLicense="CC BY-SA 4.0" />
  <row Id="29054" PostHistoryTypeId="3" PostId="10046" RevisionGUID="c2039de2-6d58-4a76-a274-996447e4e41a" CreationDate="2020-07-21T00:31:45.437" UserId="7462" Text="|mathematics|computational-geometry|geometry|subdivision|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29055" PostHistoryTypeId="2" PostId="10047" RevisionGUID="db64e6fb-1a28-4690-bcd5-7a23c7daca8b" CreationDate="2020-07-21T15:50:25.393" UserDisplayName="user9485" Text="As you pointed out, the problem here is the discretization/subdivision of the mesh. If your mesh was made of quadrilaterals instead of triangles, the obvious subdivision strategy would be to split each quadliteral into four equally sized smaller quadliterals:&#xD;&#xA;&#xD;&#xA;$\hspace{2cm}$&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/DxKa5.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&#xD;&#xA;$\hspace{2cm}$&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/OANw2.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&#xD;&#xA;&#xD;&#xA;For any two points $P_1$ and $P_2$, Dijkstra's algorithm would yield sets of shortest paths between these points $P_1$ and $P_2$. The more you refine the discretization with this subdivision strategy, the more shortest paths you'll find between the two points. However, intuitively it is clear that for every subdivision level $l\in\mathbb{N}$ you could pick one of these shortest paths $p_l$ such that the sequence $(p_l)_{l\in\mathbb{N}}$ converges to the actual geodesic between $P_1$ and $P_2$ (with respect to some norm that has to be specified, for example the supremum norm).&#xD;&#xA;&#xD;&#xA;Unfortunately, the same is not true for the standard subdivision strategy of splitting a triangle into four smaller triangles, which you have proven with your example. I believe that, at its core, the problem is that there is no way to reach the center of the triangle with a straight line from each of its edges. This can be achieved by splitting a triangle in each subdivision step into 6 smaller triangles like this:&#xD;&#xA;&#xD;&#xA;$\hspace{2cm}$&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/ilB6v.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&#xD;&#xA;$\hspace{2cm}$&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/rF0LS.png&quot; width=&quot;200&quot; height=&quot;200&quot;&gt;&#xD;&#xA;&#xD;&#xA;I do not have a proof that this subdivision is more useful to compute geodesics with Dijkstra's algorithm, but it seems quite likely to me. I would be very interested to see what your results look like with this subdivision strategy! However, no matter what you do, in the end you may or may not end up with sets of shortest paths instead of a single shortest path. In this case you will need some kind of heuristic or additional algorithm to decide which path resembles the true geodesic most closely." ContentLicense="CC BY-SA 4.0" />
  <row Id="29056" PostHistoryTypeId="2" PostId="10048" RevisionGUID="b1bdd48e-2a06-4d22-8564-3f01eead82a7" CreationDate="2020-07-21T16:12:38.740" UserId="13729" Text="I'm looking for a way to generate curvature maps like this:&#xD;&#xA;&#xD;&#xA;[![curvature map][1]][1]&#xD;&#xA;&#xD;&#xA;The map stores the Convexity and Concavity of each pixel as a value from 0 to 1, where .5 is no curvature and 1 and 0 are the extremes.&#xD;&#xA;&#xD;&#xA;I searched for algorithms to calculate the curvature of meshes and found some questions:&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/1718/what-is-the-simplest-way-to-compute-principal-curvature-for-a-mesh-triangle&#xD;&#xA;&#xD;&#xA;https://gamedev.stackexchange.com/questions/92621/cavity-map-generation&#xD;&#xA;&#xD;&#xA;https://blender.stackexchange.com/questions/146819/is-there-a-way-to-calculate-mean-curvature-of-a-triangular-mesh&#xD;&#xA;&#xD;&#xA;But I'm not sure if these are actually what is used in the example.&#xD;&#xA;&#xD;&#xA;What algorithm is used to bake these maps, and where can I find more information about it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uE97h.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29057" PostHistoryTypeId="1" PostId="10048" RevisionGUID="b1bdd48e-2a06-4d22-8564-3f01eead82a7" CreationDate="2020-07-21T16:12:38.740" UserId="13729" Text="What algorithm is used for baking grayscale curvature maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="29058" PostHistoryTypeId="3" PostId="10048" RevisionGUID="b1bdd48e-2a06-4d22-8564-3f01eead82a7" CreationDate="2020-07-21T16:12:38.740" UserId="13729" Text="|texture|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29059" PostHistoryTypeId="5" PostId="10048" RevisionGUID="4ab3122c-00ae-4f7d-b2fa-4ec3bedcb624" CreationDate="2020-07-21T16:19:42.120" UserId="13729" Comment="added 23 characters in body" Text="I'm looking for a way to generate curvature maps like this:&#xD;&#xA;&#xD;&#xA;[![curvature map][1]][1]&#xD;&#xA;&#xD;&#xA;The map stores the Convexity and Concavity of each pixel as a value from 0 to 1, where .5 is no curvature and 1 and 0 are the extremes.&#xD;&#xA;&#xD;&#xA;I searched for how to calculate the curvature of meshes and found these questions on StackExchange:&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/1718/what-is-the-simplest-way-to-compute-principal-curvature-for-a-mesh-triangle&#xD;&#xA;&#xD;&#xA;https://gamedev.stackexchange.com/questions/92621/cavity-map-generation&#xD;&#xA;&#xD;&#xA;https://blender.stackexchange.com/questions/146819/is-there-a-way-to-calculate-mean-curvature-of-a-triangular-mesh&#xD;&#xA;&#xD;&#xA;But I'm not sure if these are about the method actually used in the example.&#xD;&#xA;&#xD;&#xA;What algorithm is used to bake these maps, and where can I find more information about it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uE97h.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29060" PostHistoryTypeId="4" PostId="10048" RevisionGUID="4ab3122c-00ae-4f7d-b2fa-4ec3bedcb624" CreationDate="2020-07-21T16:19:42.120" UserId="13729" Comment="added 23 characters in body" Text="What method is used for baking grayscale curvature maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="29061" PostHistoryTypeId="6" PostId="10048" RevisionGUID="4ab3122c-00ae-4f7d-b2fa-4ec3bedcb624" CreationDate="2020-07-21T16:19:42.120" UserId="13729" Comment="added 23 characters in body" Text="|texture|algorithm|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29062" PostHistoryTypeId="5" PostId="10041" RevisionGUID="8df40719-bc9a-4ea4-b7c3-ae2e8e47d743" CreationDate="2020-07-21T17:00:27.490" UserId="13095" Comment="Correct some spelling mistakes." Text="https://www.shadertoy.com/view/MldczM&#xD;&#xA;Is ANALYTIC intersection of a ray with a triangular b-spline, 3 quadratic bezier splines, 3 CVs for each spline, 3 corner CVs are shared by 2 splines. All cv heights are orthogonal to the triangle plane. It solves for &lt;=2 roots in barycentric coordinates. There's never 3 intersections, so this is a surprisingly simple tracing of a curved function.&#xD;&#xA;The first derivative is super short, too.&#xD;&#xA;&#xD;&#xA;ESDF keys for camera movement&#xD;&#xA;The parent shader in the comments has less optimized, less precise, more repetitive, naive simpler code.&#xD;&#xA;&#xD;&#xA;It still has the error of rendering the negative surface if the camera is inside the prism of the triangle (above or below triangle). This seems to be a simpler special case, with only 1 root, where it fails to ignore the other root. The branch to solve this may be rather simple." ContentLicense="CC BY-SA 4.0" />
  <row Id="29063" PostHistoryTypeId="24" PostId="10041" RevisionGUID="8df40719-bc9a-4ea4-b7c3-ae2e8e47d743" CreationDate="2020-07-21T17:00:27.490" Comment="Proposed by 13095 approved by 482, 209 edit id of 536" ContentLicense="CC BY-SA 4.0" />
  <row Id="29064" PostHistoryTypeId="5" PostId="10045" RevisionGUID="e3a38a1f-34a4-438c-919e-01d1171d3340" CreationDate="2020-07-21T17:40:08.727" UserId="10193" Comment="added 14 characters in body" Text="This is standard Cook-Torrance BRDF in formulation for a single point light. No intergrals over a hemisphere, just a single direction to a source of incoming energy.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o = { \bigg (  (1-F) \frac{albedo  \cdot  (1-metallness)}{\pi} + \frac{F \cdot D \cdot G_2}{4 (n \cdot v)(n \cdot l_i) } \bigg )  \cdot L_i  \cdot  (n \cdot l_i ) }&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;* $L_o$ - outgoing pixel energy&#xD;&#xA;* $L_i$ - incoming energy&#xD;&#xA;* $l_i$ - direction to a light source&#xD;&#xA;* $n$ - pixel normal&#xD;&#xA;* $v$ - direction to the camera&#xD;&#xA;* $F$ - calculated Fresnel, ratio of specularly reflected energy, in range [0; 1]&#xD;&#xA;* $D$ - calculated integral of GGX NDF over some set of possible micronormal directions (depends on light source size and direction), in range [0; 1]&#xD;&#xA;* $G_2$ - calculated Smith geometry masking factor, in range [0; 1]&#xD;&#xA;&#xD;&#xA;Usually $D$ in papers is just NDF sampled at one point, which is, of couse, won't give correct value, since it's a probablity density function and its values may exceed [0; 1] range.&#xD;&#xA;&#xD;&#xA;$G_2 = G_1(v) * G_1(l)$ doesn't go higher than 1 if we use this Smith $G_1$ formulation:&#xD;&#xA;&#xD;&#xA;$G_1(dir) = \frac{2 (n \cdot dir)}{(n \cdot dir)+ \sqrt{a^2 + (1 - a^2) (n \cdot dir)^2}}$ , so it's good as well as $F$.&#xD;&#xA;&#xD;&#xA;$(n \cdot l_i )$ in the denominator is cancelled out for the specular part.&#xD;&#xA;&#xD;&#xA;**Question 1:** what's wrong with the $(n \cdot v )$ in the specular denominator? At grazing angles why do we need to divide the specular part by some small value getting big values as result? Or should it be cancelled out due to the fact that we render on per-pixel basis and a pixel covers bigger area of surface at grazing angles and already takes whis divider into accout?&#xD;&#xA;&#xD;&#xA;**Question 2:** there are some &quot;approximation&quot; of Smith $G_2$ like this (Earl Hammon, PBR Diffuse Lighting for GGX + Smith Microsurfaces, GDC 2017):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{G_2}{4 (n \cdot v) (n \cdot l)} = \frac{0.5}{lerp((n \cdot v) \cdot (n \cdot l), (n \cdot v) + (n \cdot l), \alpha) }&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Again, why this one gives large values when dot products are close to zero?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29065" PostHistoryTypeId="2" PostId="10049" RevisionGUID="a7029fc7-7524-4f33-be23-c223f179b1b3" CreationDate="2020-07-21T18:32:24.050" UserId="13730" Text="I was wondering if anyone can point me in the direction of some research papers, or articles that describe a method for generating biological 3D models.&#xD;&#xA;&#xD;&#xA;I am drafting a prototype for a new game that would feature a near infinite number of creatures.&#xD;&#xA;&#xD;&#xA;I have laid out 2 possible types of procedural generation, the first is more complicated but more desirable.&#xD;&#xA;&#xD;&#xA;**1st idea**&#xD;&#xA;Each of these creatures should be entirely generated from a set of rules, for example:&#xD;&#xA;&#xD;&#xA;- Locomotion type = legged, limbless, rolling&#xD;&#xA;- Number of legs&#xD;&#xA;- Number of arms&#xD;&#xA;&#xD;&#xA;**2nd idea**&#xD;&#xA;A base template is used with parameters that modify the overal appearance of the final creature&#xD;&#xA;&#xD;&#xA;I realise its an incredibly complicated topic, I've also realised theres a severe lack of resources on the subject - it seems to be extremely cutting edge.&#xD;&#xA;&#xD;&#xA;For reference, they achieve something similar in this demo of No Man's Sky https://youtu.be/K0umGtw90Z4?t=96 (thats if its not just staged)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I found the following paper: &#xD;&#xA;https://link.springer.com/article/10.1007/s00371-018-1589-4 but am yet to pay the subscription fee in order to access it - if anyone has read it, I would love to hear if you think it would help me out.&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29066" PostHistoryTypeId="1" PostId="10049" RevisionGUID="a7029fc7-7524-4f33-be23-c223f179b1b3" CreationDate="2020-07-21T18:32:24.050" UserId="13730" Text="Procedural generation of biological models" ContentLicense="CC BY-SA 4.0" />
  <row Id="29067" PostHistoryTypeId="3" PostId="10049" RevisionGUID="a7029fc7-7524-4f33-be23-c223f179b1b3" CreationDate="2020-07-21T18:32:24.050" UserId="13730" Text="|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29068" PostHistoryTypeId="5" PostId="10049" RevisionGUID="445333cc-38d4-4ea5-8639-66027a5c4aba" CreationDate="2020-07-21T18:46:13.697" UserId="13730" Comment="added 227 characters in body" Text="I was wondering if anyone can point me in the direction of some research papers, or articles that describe a method for generating biological 3D models.&#xD;&#xA;&#xD;&#xA;I am drafting a prototype for a new game that would feature a near infinite number of creatures.&#xD;&#xA;&#xD;&#xA;I have laid out 2 possible types of procedural generation, the first is more complicated but more desirable.&#xD;&#xA;&#xD;&#xA;**1st idea**&#xD;&#xA;Each of these creatures should be entirely generated from a set of rules, for example:&#xD;&#xA;&#xD;&#xA;- Locomotion type = legged, limbless, rolling&#xD;&#xA;- Number of legs&#xD;&#xA;- Number of arms&#xD;&#xA;&#xD;&#xA;**2nd idea**&#xD;&#xA;A base template is used with parameters that modify the overal appearance of the final creature&#xD;&#xA;&#xD;&#xA;I realise its an incredibly complicated topic, I've also realised theres a severe lack of resources on the subject - it seems to be extremely cutting edge.&#xD;&#xA;&#xD;&#xA;For reference, they achieve something similar in this demo of No Man's Sky https://youtu.be/K0umGtw90Z4?t=96 (thats if its not just staged)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I found the following paper: &#xD;&#xA;https://link.springer.com/article/10.1007/s00371-018-1589-4 but am yet to pay the subscription fee in order to access it - if anyone has read it, I would love to hear if you think it would help me out.&#xD;&#xA;&#xD;&#xA;And this also seems like a valuable resource https://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc13/06/Jon%20Hudson%20Thesis.pdf&#xD;&#xA;&#xD;&#xA;If anyone has any experience with this subject , I would love to pick your brain.&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29069" PostHistoryTypeId="2" PostId="10050" RevisionGUID="ace53068-cce1-49c1-93be-c18681feeaec" CreationDate="2020-07-21T19:59:51.467" UserId="13321" Text="I think a single direction can be greater than 1.&#xD;&#xA;&#xD;&#xA;For a BRDF the integral over the hemisphere must be less than 1 for energy conservation.&#xD;&#xA;&#xD;&#xA;If you consider a specular brdf there is only one direction, where brdf &gt; 0 and all other directions return 0. Therefore when integrating over the hemisphere that direction must be much greater than 1." ContentLicense="CC BY-SA 4.0" />
  <row Id="29070" PostHistoryTypeId="50" PostId="6094" RevisionGUID="1f2b0c5f-e718-4980-8742-677869596a17" CreationDate="2020-07-21T20:06:40.580" UserId="-1" />
  <row Id="29071" PostHistoryTypeId="2" PostId="10051" RevisionGUID="c4a00fb4-1fec-4295-bdb3-e6ae2482488b" CreationDate="2020-07-21T22:20:21.793" UserId="13732" Text="I want to retrieve data that has created by the compute shader but have no clue how it works. After researching a few forums and articles on how it should work and this is what I came up with.&#xD;&#xA;&#xD;&#xA;**Compute Shader Code**&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;layout  (local_size_x  =  100)  in;&#xD;&#xA;&#xD;&#xA;layout(std430, binding=0) buffer Pos{&#xD;&#xA;    float Position[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;    Position[gl_GlobalInvocationID.x] = float(gl_GlobalInvocationID.x);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Program Code**&#xD;&#xA;```&#xD;&#xA;public float[] useProgram(int x_size, int y_size, int z_size){&#xD;&#xA;		&#xD;&#xA;		this.group_x_size = (int)Math.ceil(x_size/100);&#xD;&#xA;		this.group_y_size = (int)Math.ceil(y_size/100);&#xD;&#xA;		this.group_z_size = (int)Math.ceil(z_size/100);&#xD;&#xA;		float[] data = new float[x_size];&#xD;&#xA;		FloatBuffer buffer = BufferUtils.createFloatBuffer(x_size);&#xD;&#xA;		buffer.put(data);&#xD;&#xA;		int ssbo = GL15.glGenBuffers();// creates empty VBO as an object and stores it in OpenGl memory&#xD;&#xA;		GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo);&#xD;&#xA;		GL15.glBufferData(GL43.GL_SHADER_STORAGE_BUFFER,buffer,GL15.GL_DYNAMIC_COPY);&#xD;&#xA;		GL43.glBindBufferBase(GL43.GL_SHADER_STORAGE_BUFFER, 0, ssbo);&#xD;&#xA;		GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;		&#xD;&#xA;		GL20.glUseProgram(computeProgram);//start the shader program&#xD;&#xA;		GL43.glDispatchCompute(group_x_size, 1, 1);&#xD;&#xA;		GL43.glMemoryBarrier(GL43.GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;&#xD;&#xA;		GL15.glBindBuffer(GL43.GL_SHADER_STORAGE_BUFFER, ssbo);&#xD;&#xA;		String values = GL43.glMapBuffer(GL43.GL_SHADER_STORAGE_BUFFER, GL43.GL_WRITE_ONLY).asFloatBuffer().toString();&#xD;&#xA;		GL43.glUnmapBuffer(GL43.GL_SHADER_STORAGE_BUFFER);&#xD;&#xA;		System.out.println(values);&#xD;&#xA;		&#xD;&#xA;		return null;&#xD;&#xA;	}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However this code just simply will not work the way I want it to. When I go to print out the Values it comes up null. Is there something wrong with the code or is there a better way to do it. I've looked through many forums but most of them aren't written in java." ContentLicense="CC BY-SA 4.0" />
  <row Id="29072" PostHistoryTypeId="1" PostId="10051" RevisionGUID="c4a00fb4-1fec-4295-bdb3-e6ae2482488b" CreationDate="2020-07-21T22:20:21.793" UserId="13732" Text="How to retrieve data from Compute Shader to CPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29073" PostHistoryTypeId="3" PostId="10051" RevisionGUID="c4a00fb4-1fec-4295-bdb3-e6ae2482488b" CreationDate="2020-07-21T22:20:21.793" UserId="13732" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29074" PostHistoryTypeId="2" PostId="10052" RevisionGUID="a67600ce-b5b5-4a4b-8968-82feccca4240" CreationDate="2020-07-22T02:40:14.577" UserId="9749" Text="I am playing with L-Systems and with some thorough understanding of how they work I think you could manage to get something useful out of them. You can see [Paul Bourke's][1] site for a sneak peek of what they do and you can read the  book [The Algorithmic Beauty of Plants][2] by Przemyslaw Prusinkiewicz and Aristid Lindenmayer. I am going to try and explain what L-Systems do in case the links die, L-Systems are a way of creating simple rules that define the topology of plants/organisms/fractals by simple axioms, this axioms can be rewritten in terms of other rules that can create incredibly organic behaviours, originally this systems were abstract in the sense that they lacked geometric meaning, but over the years people have figured out how to transform this topologies into geometry through interpreting the rules as &quot;directions&quot; much like turtle graphics. I have this systems replace basic geometric rules such as &quot;draw a line between two points&quot; into create a complex building with &quot;A or C characteristics&quot; so I think you could define your interpreter in terms of biologically accurate creatures. &#xA;&#xA;&#xA;  [1]: http://paulbourke.net/fractals/lsys/&#xA;  [2]: https://www.google.com/url?sa=t&amp;source=web&amp;rct=j&amp;url=http://algorithmicbotany.org/papers/abop/abop.pdf&amp;ved=2ahUKEwjNnPO66N_qAhVPc98KHS-OAXMQFjAIegQIAxAB&amp;usg=AOvVaw2r9WRagwONeb1NTGPS7xVT" ContentLicense="CC BY-SA 4.0" />
  <row Id="29075" PostHistoryTypeId="50" PostId="9906" RevisionGUID="92cca17c-87b9-4d47-a7ca-082b65481761" CreationDate="2020-07-22T10:05:15.523" UserId="-1" />
  <row Id="29076" PostHistoryTypeId="5" PostId="10052" RevisionGUID="802ea834-905c-49b3-bb05-63da9ea127db" CreationDate="2020-07-22T17:55:27.480" UserId="9749" Comment="added 5 characters in body" Text="I am playing with L-Systems and with some thorough understanding of how they work I think you could manage to get something useful out of them. You can see [Paul Bourke's][1] site for a sneak peek of what they do and you can read the  book [The Algorithmic Beauty of Plants][2] by Przemyslaw Prusinkiewicz and Aristid Lindenmayer. I am going to try and explain what L-Systems do in case the links die, L-Systems are a way of creating simple rules that define the topology of plants/organisms/fractals by simple axioms, this axioms can be rewritten in terms of other rules that can create incredibly organic behaviours, originally this systems were abstract in the sense that they lacked geometric meaning, but over the years people have figured out how to transform this topologies into geometry through interpreting the rules as &quot;directions&quot; much like turtle graphics. I have seen this systems replace basic geometric rules such as &quot;draw a line between two points&quot; into create a complex building with &quot;A or C characteristics&quot; so I think you could define your interpreter in terms of biologically accurate creatures. &#xA;&#xA;&#xA;  [1]: http://paulbourke.net/fractals/lsys/&#xA;  [2]: https://www.google.com/url?sa=t&amp;source=web&amp;rct=j&amp;url=http://algorithmicbotany.org/papers/abop/abop.pdf&amp;ved=2ahUKEwjNnPO66N_qAhVPc98KHS-OAXMQFjAIegQIAxAB&amp;usg=AOvVaw2r9WRagwONeb1NTGPS7xVT" ContentLicense="CC BY-SA 4.0" />
  <row Id="29077" PostHistoryTypeId="2" PostId="10053" RevisionGUID="59ae6bb2-d135-4772-b9e6-a78cd0a246e9" CreationDate="2020-07-23T08:59:37.603" UserId="11058" Text="Say I have a mesh with two sets of uvs. And I have a texture made for the first set of uvs. I would like to create a second texture that has the same relationship between its pixels and the second set of uvs, as the first texture does with the first set of uvs. Such that if we change between the two different sets of uvs and apply the corresponding texture we see identical texturing on the model.&#xD;&#xA;&#xD;&#xA;What technique can we use do this? Can it be done on the GPU?&#xD;&#xA;&#xD;&#xA;Would we possibly need to transform each uv face of the first uv set into the corresponding face of second uvs set? Not sure where we would go from there." ContentLicense="CC BY-SA 4.0" />
  <row Id="29078" PostHistoryTypeId="1" PostId="10053" RevisionGUID="59ae6bb2-d135-4772-b9e6-a78cd0a246e9" CreationDate="2020-07-23T08:59:37.603" UserId="11058" Text="For two sets of uvs and a texture create a second corresponding texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="29079" PostHistoryTypeId="3" PostId="10053" RevisionGUID="59ae6bb2-d135-4772-b9e6-a78cd0a246e9" CreationDate="2020-07-23T08:59:37.603" UserId="11058" Text="|opengl|texture|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29080" PostHistoryTypeId="5" PostId="10053" RevisionGUID="00e821dd-8bea-4ee7-bf7b-62206c18a687" CreationDate="2020-07-23T09:07:51.883" UserId="11058" Comment="added 169 characters in body" Text="Say I have a mesh with two sets of uvs. And I have a texture made for the first set of uvs. I would like to create a second texture that has the same relationship between its pixels and the second set of uvs, as the first texture does with the first set of uvs. Such that if we change between the two different sets of uvs and apply the corresponding texture we see identical texturing on the model. And the only difference would be the texture density in different regions because of the differences in distortion and the area of the uv faces between the two uv sets.&#xD;&#xA;&#xD;&#xA;What technique can we use do this? Can it be done on the GPU?&#xD;&#xA;&#xD;&#xA;Would we possibly need to transform each uv face of the first uv set into the corresponding face of second uvs set? Not sure where we would go from there." ContentLicense="CC BY-SA 4.0" />
  <row Id="29081" PostHistoryTypeId="4" PostId="10053" RevisionGUID="140e8c32-2fcf-44cc-8150-9e1a635bd46c" CreationDate="2020-07-23T09:27:44.610" UserId="11058" Comment="edited title" Text="Transfer the texture between two different sets of uv" ContentLicense="CC BY-SA 4.0" />
  <row Id="29082" PostHistoryTypeId="2" PostId="10054" RevisionGUID="f3c5d166-a899-483d-91f7-d9d022aa016a" CreationDate="2020-07-23T11:56:05.263" UserId="7952" Text="Are the two sets well correlated? This would boil down to having a good set of vertex attributes for each set of uv's. If each set of uv's in mapping 1 has a know set of mappings in set 2 then it should be relatively straight forward to read from the first set of uv's and write to the second set.&#xD;&#xA;&#xD;&#xA;If this is as simple as vertex 1 has a mapping in uv set 1 and a different mapping for uv set 2 then read from set one then resample the texture for set 2.&#xD;&#xA;&#xD;&#xA;On the other hand if the two sets are completely uncorrelated then it gets more complex: &#xD;&#xA;A fully generic brute force solution would be to read 1 of the vertex attributes of the known mapping. Then search the entire set of uv's for set 2 filtering out those vertex positions that overlap with the current uv under consideration. Then use that list to read, resample and write the new texture.&#xD;&#xA;&#xD;&#xA;The first case is easier to implement on the gpu. The second case is more difficult and may be better to implement on the cpu for debugging then move to the gpu as performance requirements dictate." ContentLicense="CC BY-SA 4.0" />
  <row Id="29083" PostHistoryTypeId="5" PostId="10054" RevisionGUID="27d8f189-dda5-47d4-842c-ac285b649c2b" CreationDate="2020-07-23T12:29:31.487" UserId="7952" Comment="added 444 characters in body" Text="Are the two sets well correlated? This would boil down to having a good set of vertex attributes for each set of uv's. If each set of uv's in mapping 1 has a know set of mappings in set 2 then it should be relatively straight forward to read from the first set of uv's and write to the second set.&#xD;&#xA;&#xD;&#xA;If this is as simple as vertex 1 has a mapping in uv set 1 and a different mapping for uv set 2 then read from set one then resample the texture for set 2.&#xD;&#xA;&#xD;&#xA;On the other hand if the two sets are completely uncorrelated then it gets more complex: &#xD;&#xA;A fully generic brute force solution would be to read 1 of the vertex attributes of the known mapping. Then search the entire set of uv's for set 2 filtering out those vertex positions that overlap with the current uv under consideration. Then use that list to read, resample and write the new texture.&#xD;&#xA;&#xD;&#xA;The first case is easier to implement on the gpu. The second case is more difficult and may be better to implement on the cpu for debugging then move to the gpu as performance requirements dictate.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit for the first case:&#xD;&#xA;This is the easy case, Use the uv coords from set 1 on the gpu just like you would normally to read the texture. Then use the second set as actual vertex positions adding a z value that is some constant. Don't use a MVP matrix just go straight to clip space. The gpu will worry about the resampling. In the end you will have a fullscreen quad with the final mappings. Then just read the image back from the gpu. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29084" PostHistoryTypeId="5" PostId="10054" RevisionGUID="0f04c9c6-fa68-4743-9b9e-0526022d9674" CreationDate="2020-07-23T12:58:54.213" UserId="7952" Comment="added 407 characters in body" Text="Are the two sets well correlated? This would boil down to having a good set of vertex attributes for each set of uv's. If each set of uv's in mapping 1 has a know set of mappings in set 2 then it should be relatively straight forward to read from the first set of uv's and write to the second set.&#xD;&#xA;&#xD;&#xA;If this is as simple as vertex 1 has a mapping in uv set 1 and a different mapping for uv set 2 then read from set one then resample the texture for set 2.&#xD;&#xA;&#xD;&#xA;On the other hand if the two sets are completely uncorrelated then it gets more complex: &#xD;&#xA;A fully generic brute force solution would be to read 1 of the vertex attributes of the known mapping. Then search the entire set of uv's for set 2 filtering out those vertex positions that overlap with the current uv under consideration. Then use that list to read, resample and write the new texture.&#xD;&#xA;&#xD;&#xA;The first case is easier to implement on the gpu. The second case is more difficult and may be better to implement on the cpu for debugging then move to the gpu as performance requirements dictate.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit for the first case:&#xD;&#xA;This is the easy case, Use the uv coords from set 1 on the gpu just like you would normally to read the texture. Then use the second set as actual vertex positions adding a z value that is some constant. Don't use a MVP matrix just go straight to clip space. The gpu will worry about the resampling. In the end you will have a fullscreen quad with the final mappings. Then just read the image back from the gpu. &#xD;&#xA;&#xD;&#xA;More detail:&#xD;&#xA;&#xD;&#xA;The vertex attributes for this would be:&#xD;&#xA;&#xD;&#xA;    Vertex Position = vec2{u_set2, v_set2}&#xD;&#xA;    uv coords = vec2{u_set1, v_set1}&#xD;&#xA;&#xD;&#xA;The vertex shader:&#xD;&#xA;&#xD;&#xA;    vec2 remapping = vertex_position * 2.0 - 1.0; // remap x,y to -1 to 1&#xD;&#xA;    gl_position = vec4( remapping, 0.5, 1 ); &#xD;&#xA;    out texcoord = uv_coords_in;&#xD;&#xA;&#xD;&#xA;The fragment shader:&#xD;&#xA;&#xD;&#xA;    gl_color = texture( image_sampler, tex_coords);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29085" PostHistoryTypeId="2" PostId="10055" RevisionGUID="aa88f9d1-ebfa-43f8-ab63-62f6d38b60d8" CreationDate="2020-07-23T14:04:02.583" UserId="13740" Text="I'm looking for a compact representation of radiance over the hemisphere that is also performant to evaluate in realtime (in a pixel shader). The purpose of it is to compress surface lightfields so that they are also very performant to render in real-time (in a VR application).&#xD;&#xA;&#xD;&#xA;I found [Efficient Irradiance Normal Mapping][1] which is pretty neat, it proposes 6 cheap basis functions that produce the same error over the hemisphere as spherical harmonics up to l = 2.&#xD;&#xA;Now, l = 2 may be fine for irradiance, but for radiance it's too low frequency.&#xD;&#xA;Looking at the results of [Surface Light Field from Video Acquired in&#xD;&#xA;Uncontrolled Settings][2], l = 4 spherical harmonics (25 coefficients) and l = 3  [hemispherical harmonics][3] (16 coefficients) seem to be enough to recreate some highlights.&#xD;&#xA;&#xD;&#xA;What I'm looking now for is a basis that gives similar results like l = 4 SH or l = 3 HSH, but that is cheaper to evaluate at runtime.&#xD;&#xA;&#xD;&#xA;I haven't found any other research yet that goes into the direction I'm looking for, so I'm asking if someone has some good pointers?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://publik.tuwien.ac.at/files/PubDat_189085.pdf&#xD;&#xA;  [2]: http://vcg.isti.cnr.it/Publications/2013/PDCS13/&#xD;&#xA;  [3]: https://cgg.mff.cuni.cz/~jaroslav/papers/egsr2004/gautron-egsr2004-hemispherical.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29086" PostHistoryTypeId="1" PostId="10055" RevisionGUID="aa88f9d1-ebfa-43f8-ab63-62f6d38b60d8" CreationDate="2020-07-23T14:04:02.583" UserId="13740" Text="alternative to spherical harmonics to model radiance aproximation, optimized for real-time evaluation" ContentLicense="CC BY-SA 4.0" />
  <row Id="29087" PostHistoryTypeId="3" PostId="10055" RevisionGUID="aa88f9d1-ebfa-43f8-ab63-62f6d38b60d8" CreationDate="2020-07-23T14:04:02.583" UserId="13740" Text="|spherical-harmonics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29088" PostHistoryTypeId="5" PostId="10055" RevisionGUID="97d992ad-8cd1-4ff0-b0ab-58212d20ddd8" CreationDate="2020-07-23T16:01:33.413" UserId="13740" Comment="added 24 characters in body" Text="I'm looking for a compact representation of radiance over the hemisphere that is also performant to evaluate in realtime (in a pixel shader). The purpose of it is to compress surface lightfields so that they are also very performant to render in real-time (in a VR application).&#xD;&#xA;&#xD;&#xA;I found [Efficient Irradiance Normal Mapping][1] which is pretty neat, it proposes 6 cheap basis functions that produce the same error over the hemisphere as spherical harmonics up to l = 2.&#xD;&#xA;Now, l = 2 may be fine for irradiance, but for radiance it's too low frequency.&#xD;&#xA;Looking at the results of [Surface Light Field from Video Acquired in&#xD;&#xA;Uncontrolled Settings][2], l = 4 spherical harmonics (25 coefficients) and l = 3  [hemispherical harmonics][3] (16 coefficients) seem to be enough to recreate some highlights and thus look promising.&#xD;&#xA;&#xD;&#xA;What I'm looking now for is a basis that gives similar results like l = 4 SH or l = 3 HSH, but that is cheaper to evaluate at runtime.&#xD;&#xA;&#xD;&#xA;I haven't found any other research yet that goes into the direction I'm looking for, so I'm asking if someone has some good pointers?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://publik.tuwien.ac.at/files/PubDat_189085.pdf&#xD;&#xA;  [2]: http://vcg.isti.cnr.it/Publications/2013/PDCS13/&#xD;&#xA;  [3]: https://cgg.mff.cuni.cz/~jaroslav/papers/egsr2004/gautron-egsr2004-hemispherical.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29089" PostHistoryTypeId="4" PostId="7434" RevisionGUID="32655a91-fe40-457e-a7ac-70b108cdb287" CreationDate="2020-07-24T04:26:03.147" UserId="8435" Comment="edited title" Text="Is there an algorithm to bold an outline font?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29093" PostHistoryTypeId="2" PostId="10056" RevisionGUID="8e027368-5f64-449e-b0de-3be6823bcd68" CreationDate="2020-07-25T17:56:24.623" UserId="13748" Text="I want to send a series of integer to the geometry shader,&#xD;&#xA;while the data will be modified every frame.&#xD;&#xA;&#xD;&#xA;But when I try to retrive the sampleBuffer in geometry shader, it seems to keep output zero.&#xD;&#xA;&#xD;&#xA;Am I using Texture Buffer wrong, or the TBO itself just can't be used as GL_DYNAMIC_DRAW?&#xD;&#xA;&#xD;&#xA;**Init Texture Buffer**&#xD;&#xA;```&#xD;&#xA;void InitialTBO() {&#xD;&#xA;    int index_tbo_reserved_size = 5000;&#xD;&#xA;	glGenBuffers(1, &amp;index_tbo);&#xD;&#xA;	glBindBuffer(GL_TEXTURE_BUFFER, index_tbo);&#xD;&#xA;	glBufferData(GL_TEXTURE_BUFFER, index_tbo_reserved_size * sizeof(GLint), NULL, GL_DYNAMIC_DRAW);&#xD;&#xA;	glGenTextures(1, &amp;index_tbo_tex);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Render**&#xD;&#xA;```&#xD;&#xA;void RenderChunkDataCone(Primitive* primitive) {&#xD;&#xA;    Program* shaders = primitive-&gt;shaders;&#xD;&#xA;&#xD;&#xA;    shaders-&gt;use();&#xD;&#xA;&#xD;&#xA;	glActiveTexture(GL_TEXTURE0);	&#xD;&#xA;	glBindBuffer(GL_TEXTURE_BUFFER, this-&gt;index_tbo);&#xD;&#xA;	glBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(GLint)*index_tbo_data.size(), index_tbo_data.data());&#xD;&#xA;	glBindTexture(GL_TEXTURE_BUFFER, this-&gt;index_tbo_tex);&#xD;&#xA;	glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, this-&gt;index_tbo);&#xD;&#xA;	shaders-&gt;setUniform(&quot;index_tex&quot;, 0);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(primitive-&gt;vao);&#xD;&#xA;	glDrawElements(primitive-&gt;drawType, primitive-&gt;drawCount * primitive-&gt;drawCount_Inner, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;	shaders-&gt;stopUsing();&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Geometry Shader**&#xD;&#xA;```&#xD;&#xA;#version 460 core&#xD;&#xA;uniform samplerBuffer index_tex;&#xD;&#xA;vec3 render_primitive(vec3 position){&#xD;&#xA;	int status = int(texelFetch(index_tex, 0).r);&#xD;&#xA;	if(status==0)&#xD;&#xA;		return vec3(0,10,10);&#xD;&#xA;	else if(status==1)&#xD;&#xA;		return vec3(10,0,0);&#xD;&#xA;	else if(status==2)&#xD;&#xA;		return vec3(0,0,10);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;	vec4 position =gl_in[0].gl_Position;&#xD;&#xA;	vec3 returnedValue = render_primitive(position.xyz);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I've confirmed the index_tbo[0] is 1,&#xD;&#xA;But the returnedValue outputed by shader will always be (0,10,10) as the value index_tex[0] received seems to be 0." ContentLicense="CC BY-SA 4.0" />
  <row Id="29094" PostHistoryTypeId="1" PostId="10056" RevisionGUID="8e027368-5f64-449e-b0de-3be6823bcd68" CreationDate="2020-07-25T17:56:24.623" UserId="13748" Text="Is it possible to send Texture Buffer to shader dynamically?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29095" PostHistoryTypeId="3" PostId="10056" RevisionGUID="8e027368-5f64-449e-b0de-3be6823bcd68" CreationDate="2020-07-25T17:56:24.623" UserId="13748" Text="|opengl|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29096" PostHistoryTypeId="2" PostId="10057" RevisionGUID="3a903853-a58c-419f-86c7-e9138110a6ea" CreationDate="2020-07-25T20:25:23.607" UserId="2654" Text="These:&#xD;&#xA;&#xD;&#xA;&gt;     glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, this-&gt;index_tbo);&#xD;&#xA;&#xD;&#xA;&gt;     uniform samplerBuffer index_tex;&#xD;&#xA;&#xD;&#xA;Do not match. If the texture is a signed integer texture, then the sampler type needs to match. It should be `isamplerBuffer`, and you won't need to do the cast." ContentLicense="CC BY-SA 4.0" />
  <row Id="29097" PostHistoryTypeId="2" PostId="10058" RevisionGUID="b8b860e3-8cf1-4f6d-85b1-55b83d0112bb" CreationDate="2020-07-26T02:20:50.907" UserId="8925" Text="I've been looking at [Interface queries](https://www.khronos.org/opengl/wiki/Program_Introspection#Interface_query) in order to prevent common mistakes that are time consuming to debug, such as forgetting to bind a buffer, binding the wrong resource type, etc.&#xD;&#xA;&#xD;&#xA;However, I wasn't able to find what I wanted for images. I'd like to make sure that the type of the texture, the memory qualifier and the texture format are the same in the c++ code and in the shader :&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(index, texture, 0, true, 0, GL_READ_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;    layout(binding = 0, rgba32f) uniform writeonly iimage2D _heightmap;&#xD;&#xA;&#xD;&#xA;Using glGetProgramResourceiv with GL_UNIFORM and GL_TYPE, I was able to get the type of the image, iimage2D. But nothing for the memory qualifier and the image format.&#xD;&#xA;&#xD;&#xA;Is there a way to do that, other than parsing the shader?&#xD;&#xA;&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="29098" PostHistoryTypeId="1" PostId="10058" RevisionGUID="b8b860e3-8cf1-4f6d-85b1-55b83d0112bb" CreationDate="2020-07-26T02:20:50.907" UserId="8925" Text="OpenGL shader introspection/interface queries for images" ContentLicense="CC BY-SA 4.0" />
  <row Id="29099" PostHistoryTypeId="3" PostId="10058" RevisionGUID="b8b860e3-8cf1-4f6d-85b1-55b83d0112bb" CreationDate="2020-07-26T02:20:50.907" UserId="8925" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29100" PostHistoryTypeId="5" PostId="10032" RevisionGUID="94362549-efbc-4762-87dd-fb54e834d8b8" CreationDate="2020-07-26T05:19:52.230" UserId="5778" Comment="typos corrected" Text="What I am trying to do is to become able to compare with reasonable accuracy two real world fabric/textures (colorwise speaking) at two distinct locations. I can't move them into single place to observe them close to each other and in the same light conditions.&#xD;&#xA;&#xD;&#xA;I was thinking about such a &quot;protocol&quot;:&#xD;&#xA;1. print some &quot;test pattern&quot; on white paper (reference object)&#xD;&#xA;2. go into location 1 and take picture of object A close to reference object&#xD;&#xA;3. go into location 2 and take picture of object B close to reference object&#xD;&#xA;4. use some application/library/own code, to adjust colors on photo B so the reference object look similar (colorwise) to reference object on A&#xD;&#xA;5. compare visually or statistically (programmatica;ly) objects A and B&#xD;&#xA;&#xD;&#xA;Does anyone know what is the easiest way to perform point 4? Is there an application for that step, or library or any other shortcut than implementing this on my own? &#xD;&#xA;&#xD;&#xA;Or, maybe anyone knows application for the whole process, not particularly point 4, which could help me, or another protocol for performing such comparison? &#xD;&#xA;&#xD;&#xA;Also please let me know it this can't be done this way, or rather, this is an oversimplified solution to provide &quot;reasonable accuracy&quot;, and if so - why?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29101" PostHistoryTypeId="24" PostId="10032" RevisionGUID="94362549-efbc-4762-87dd-fb54e834d8b8" CreationDate="2020-07-26T05:19:52.230" Comment="Proposed by 5778 approved by -1 edit id of 537" ContentLicense="CC BY-SA 4.0" />
  <row Id="29102" PostHistoryTypeId="5" PostId="10032" RevisionGUID="743c781b-94f5-4f99-87b5-423aa9c9f057" CreationDate="2020-07-26T05:19:52.230" UserId="13702" Comment="typos corrected" Text="What I am trying to do is to become able to compare with reasonable accuracy two real world fabric/textures (colorwise speaking) at two distinct locations. I can't move them into single place to observe them close to each other and in the same light conditions.&#xD;&#xA;&#xD;&#xA;I was thinking about such a &quot;protocol&quot;:&#xD;&#xA;1. print some &quot;test pattern&quot; on white paper (reference object)&#xD;&#xA;2. go into location 1 and take picture of object A close to reference object&#xD;&#xA;3. go into location 2 and take picture of object B close to reference object&#xD;&#xA;4. use some application/library/own code, to adjust colors on photo B so the reference object look similar (colorwise) to reference object on A&#xD;&#xA;5. compare visually or statistically (programmatically) objects A and B&#xD;&#xA;&#xD;&#xA;Does anyone know what is the easiest way to perform point 4? Is there an application for that step, or library or any other shortcut than implementing this on my own? &#xD;&#xA;&#xD;&#xA;Or, maybe anyone knows application for the whole process, not particularly point 4, which could help me, or another protocol for performing such comparison? &#xD;&#xA;&#xD;&#xA;Also please let me know it this can't be done this way, or rather, this is an oversimplified solution to provide &quot;reasonable accuracy&quot;, and if so - why?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29103" PostHistoryTypeId="2" PostId="10059" RevisionGUID="e05dba41-6c18-484a-8c3d-979c88baa55e" CreationDate="2020-07-26T14:07:38.043" UserId="2654" Text="Those are not accessible via introspection. It should also be pointed out that some of them don't *have* to &quot;match&quot;.&#xD;&#xA;&#xD;&#xA;The shader-defined format doesn't have to be the same as the image-bound format. The image-bound format defines how writing from the image interprets the data provided by the shader. The shader-defined format determines how reading from the image interprets the data in the image. So the two values are fundamentally doing different things and need not match either each other or the texture's internal format. There are [rules for how conversion works between these and the image's actual format][1].&#xD;&#xA;&#xD;&#xA;For the access type, you could just pass `GL_READ_WRITE` for everything and let the shader decide how it's going to access the storage. Given that Vulkan has no equivalent to this value, it probably doesn't matter performance-wise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store#Format_conversion" ContentLicense="CC BY-SA 4.0" />
  <row Id="29104" PostHistoryTypeId="50" PostId="9616" RevisionGUID="94bb1dc2-046f-4561-b4c5-1abb14e17f32" CreationDate="2020-07-26T18:03:55.360" UserId="-1" />
  <row Id="29105" PostHistoryTypeId="2" PostId="10060" RevisionGUID="2bf00301-c0bd-46cc-b68b-53496101942a" CreationDate="2020-07-26T18:13:55.083" UserId="13751" Text="I am trying to implement clipping in my simple renderer, but i have a trouble with setting the boundaries. I used the same projection matrix that is in OpenGL. The problem is, the vertices that are behind the camera(z&lt;near) when mapped to NDC are bigger than 1(but they should be less than -1), so i can't use vertex.z &gt; w. ![enter image description here](https://i.stack.imgur.com/HZEAg.png)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29106" PostHistoryTypeId="1" PostId="10060" RevisionGUID="2bf00301-c0bd-46cc-b68b-53496101942a" CreationDate="2020-07-26T18:13:55.083" UserId="13751" Text="Clipping 3D Perspective matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="29107" PostHistoryTypeId="3" PostId="10060" RevisionGUID="2bf00301-c0bd-46cc-b68b-53496101942a" CreationDate="2020-07-26T18:13:55.083" UserId="13751" Text="|3d|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29111" PostHistoryTypeId="5" PostId="9421" RevisionGUID="91925a04-4310-4e30-90a5-9b75a121234e" CreationDate="2020-07-26T20:10:14.380" UserId="11598" Comment="added 212 characters in body" Text="As the title suggests I'm trying to implement the last images of the &quot;Microfacet Models for Refraction through Rough Surfaces&quot; Paper by Walter et al. in OpenGL[![see here for the picture][1]][1]&#xD;&#xA;&#xD;&#xA;I &quot;think&quot; (I had to put that into quotation marks) I know how the microfacet model should work and hopefully am only stuck on practical execution.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I started by implementing the GGX formulas for the Normal Distribution, Fresnel and Geometry Function.&#xD;&#xA;&#xD;&#xA;Initially and still I'm not so sure how to get the color of the object behind the glass into the formulas. My first thought was to create a cubemap around the slate of glass and then use the outgoing direction vectors (o_t and o_r) to sample the cubemap. But then I'm still not so sure how to incorporate that into the larger picture. Going by my first thought again I just multiplied the result of the BTFD with the sample of the o_t vector but apparently the BTDF was really big so the whole slate turned white (possible bug?). After dividing the result a few times some washed-up version of what was supposed to show up appeared.&#xD;&#xA;&#xD;&#xA;Also I think I read somewhere that the reflection and transmission should be handled seperatly depending on the result of the Fresnel formula.&#xD;&#xA;Or should it be handled at the same time (possibly somethink like : BRDF * sample_of_reflection + BTDF * sample_of_refraction)?&#xD;&#xA;&#xD;&#xA;And another thing I found curious is the given equation for sampling:&#xD;&#xA;&#xD;&#xA;$\theta = arctan(a * sqrt(rand1) / sqrt(1 - rand1))$&#xD;&#xA;&#xD;&#xA;$\phi = 2 * \pi * rand2$&#xD;&#xA;&#xD;&#xA;After some playing around with this function I noticed that is basically something akin to a gaussian distribution pointing towards the positive z-axis. But shouldn't the distribution give samples which are distributed around the surface normal? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm wondering if I have to add an additional pair of quotation marks to my earlier statement...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So anyway here is the pseudocode for my implementation until now:&#xD;&#xA;```glsl&#xD;&#xA;for(#samplecount)&#xD;&#xA;{&#xD;&#xA; //get a sample m&#xD;&#xA; vec3 m = drawsample();&#xD;&#xA; &#xD;&#xA; //calculate normal and incoming vector&#xD;&#xA; vec3 i = normalize(viewPosition - fragmentPosition);&#xD;&#xA; vec3 n = normalize(Normal); &#xD;&#xA; &#xD;&#xA; // calculate outgoing vector&#xD;&#xA; vec3 o_r = calculate_like_paper();&#xD;&#xA; vec3 o_t = calculate_like_paper();&#xD;&#xA;&#xD;&#xA; //sample cubemap&#xD;&#xA; vec3 reflection = sampleCubemap();&#xD;&#xA; vec3 refraction = sampleCubemap(); &#xD;&#xA;&#xD;&#xA; //calculate halfvectors&#xD;&#xA; vec3 h_r = calculate_like_paper();&#xD;&#xA; vec3 h_t = calculate_like_paper();&#xD;&#xA;&#xD;&#xA; //calculate NDF, Fresnel and Geometry&#xD;&#xA; float D = GGX_D(h_r);&#xD;&#xA; float G = GGX_G(i, o_r, h_r);&#xD;&#xA; float F = GGX_F(i, h_r);&#xD;&#xA;&#xD;&#xA; //calculate BSDF, BRDF &amp; BTDF&#xD;&#xA; float BRDF = F * G * D / (4.0 * abs(dot(i, n)) * abs(dot(o_r, n)));&#xD;&#xA; float BTDF = longFormula();&#xD;&#xA;&#xD;&#xA; float BSDF = BRDF + BTDF&#xD;&#xA; &#xD;&#xA; vec3 result += BRDF * reflection + BTDF * refraction //?&#xD;&#xA;}&#xD;&#xA;result /= #samplecount;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thank you if you take your time to answer and I'm relatively new to StackExchange so I could definitely do with some feedback to improve the way I ask questions.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;So if anyone found this question and has similar questions Epic Games has some nice notes on this topic: 	https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Xofnw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29112" PostHistoryTypeId="5" PostId="10059" RevisionGUID="f4ea92b9-3aaf-453b-873a-4614e6d86a16" CreationDate="2020-07-26T22:47:01.220" UserId="2654" Comment="added 223 characters in body" Text="Those are not accessible via introspection. It should also be pointed out that some of them don't *have* to &quot;match&quot;.&#xD;&#xA;&#xD;&#xA;The shader-defined format doesn't have to be the same as the image-bound format. The image-bound format defines how writing from the image interprets the data provided by the shader. The shader-defined format determines how reading from the image interprets the data in the image. So the two values are fundamentally doing different things and need not match either each other or the texture's internal format. There are [rules for how conversion works between these and the image's actual format][1].&#xD;&#xA;&#xD;&#xA;For the access type, you could just pass `GL_READ_WRITE` for everything and let the shader decide how it's going to access the storage. Given that Vulkan has no equivalent to this value, it probably doesn't matter performance-wise. Also, note that the multibind function `glBindImageTextures`, which binds multiple images in one call, always uses `GL_READ_WRITE`. Since the whole point of that function is performance, it almost certainly doesn't matter.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store#Format_conversion" ContentLicense="CC BY-SA 4.0" />
  <row Id="29113" PostHistoryTypeId="5" PostId="10059" RevisionGUID="71655cf2-c60d-4d11-ba6b-1855ed44613b" CreationDate="2020-07-26T22:54:05.370" UserId="2654" Comment="added 89 characters in body" Text="Those are not accessible via introspection. It should also be pointed out that some of them don't *have* to &quot;match&quot;.&#xD;&#xA;&#xD;&#xA;The shader-defined format doesn't have to be the same as the image-bound format. The image-bound format defines how writing from the image interprets the data provided by the shader. The shader-defined format determines how reading from the image interprets the data in the image. So the two values are fundamentally doing different things and need not match either each other or the texture's internal format. There are [rules for how conversion works between these and the image's actual format][1].&#xD;&#xA;&#xD;&#xA;For the access type, you could just pass `GL_READ_WRITE` for everything and let the shader decide how it's going to access the storage. Given that Vulkan has no equivalent to this value, it probably doesn't matter performance-wise. Also, note that the multibind function `glBindImageTextures`, which binds multiple images in one call, always uses `GL_READ_WRITE` (and doesn't have a specified format). Since the whole point of that function is performance, it almost certainly doesn't matter if you always use read-write from the binding side.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store#Format_conversion" ContentLicense="CC BY-SA 4.0" />
  <row Id="29118" PostHistoryTypeId="2" PostId="10063" RevisionGUID="3b0cda73-afde-4e1a-a1a0-ea7f066c1da1" CreationDate="2020-07-27T14:47:59.770" UserId="13757" Text="I do not know if reading directly from the frame buffer can work when you are not using the GLFW window at all. What you can do though, is create a texture which you can pass to your fragment or compute shaders and draw on it. But then methods like glDrawElements() (if i remember it correctly) will not work." ContentLicense="CC BY-SA 4.0" />
  <row Id="29119" PostHistoryTypeId="2" PostId="10064" RevisionGUID="fcd34e38-b91b-4cc3-9d4f-8f0c33b00e63" CreationDate="2020-07-28T13:47:02.583" UserId="13762" Text="As someone who is trying to dive into WebGL for parallelizing simulations, or Machine Learning, or typical IIR filters I've come to realize that for everything that I want to do requires the GPU to update itself and send &quot;gossip&quot; signals to the screen.&#xD;&#xA;&#xD;&#xA;Sending data to the screen is fairly straight forward, however having the GPU write to itself in order to step into the next time step for a simulation and then send that information to the screen is something I have no clue about doing. I don't know what it's called or if it's even possible.&#xD;&#xA;&#xD;&#xA;I hate asking a &quot;*is it possible to do X?*&quot; question, but sadly this is one of those because my knowledge regarding WebGL is so bad, and studying WebGL for a few months just to realize that it's not possible is not time I can afford right now. I have no one else to ask.&#xD;&#xA;&#xD;&#xA;However, to give this question some more meat to the bones I'll say that I assume that it is possible and it is just a matter of setting up two buffers and linking them together in some *special way*. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Here's the actual question:** I'm familiar with the fact that you set up pipelines in WebGL, does WebGL support pipelines to itself that never goes to the screen so it can modify its internal buffers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29120" PostHistoryTypeId="1" PostId="10064" RevisionGUID="fcd34e38-b91b-4cc3-9d4f-8f0c33b00e63" CreationDate="2020-07-28T13:47:02.583" UserId="13762" Text="Let GPU write to itself" ContentLicense="CC BY-SA 4.0" />
  <row Id="29121" PostHistoryTypeId="3" PostId="10064" RevisionGUID="fcd34e38-b91b-4cc3-9d4f-8f0c33b00e63" CreationDate="2020-07-28T13:47:02.583" UserId="13762" Text="|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29122" PostHistoryTypeId="2" PostId="10065" RevisionGUID="a266ff76-1ea4-45f4-8e88-467775c44147" CreationDate="2020-07-28T14:49:32.067" UserId="7724" Text="What you are talking about is transform feedback. With transform feedback you can capture primitives (vertices, triangles, lines) in a buffer such they can be used in subsequent draw calls. You don't have to grab the data from the GPU to the CPU and back again as you can directly use the GPU buffer you have just rendered to.&#xD;&#xA;&#xD;&#xA;I'm not exactly sure what your use-case exactly is, but you mention simulation and timesteps. Imagine a particle system where each particle has a position and a velocity at each time step of the simulation. We have two buffers A and B. A will be rendered from on even numbered frames and will be written to on odd-numbered frames and B that we write to on even numbered frames and render from on odd-numbered frames. We also have a simple vertex shader that updates the positions of vertices using the aforementioned position and velocity attributes.&#xD;&#xA;&#xD;&#xA;Then using some initial position and velocity for each particle we can start rendering from buffer A into buffer B. After having finished this process all particles will have an update position and we can render from buffer B into buffer A.&#xD;&#xA;&#xD;&#xA;With this you also have the option to not render to the at all screen by using the GL_RASTERIZER_DISCARD functionality.&#xD;&#xA;&#xD;&#xA;Take a look at the examples listed on [this][1] page under 'Transform Feedback'. Or at [this][2] example.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://webglsamples.org/WebGL2Samples/#transform_feedback_instanced&#xD;&#xA;  [2]: https://prideout.net/blog/old/blog/index.html@tag=opengl-transform-feedback.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="29123" PostHistoryTypeId="5" PostId="5687" RevisionGUID="fba0a5c9-eb0e-4bd2-9fc6-28ba51fb7c3c" CreationDate="2020-07-29T17:30:36.030" UserId="56" Comment="added 192 characters in body" Text="The problem turned out to be that you don't do the same number of candidates per point, but that if you have $n$ points already, you should generate $m*n$ candidates for the next point.&#xD;&#xA;&#xD;&#xA;$m$ is a tuneable parameter where in general higher values of $m$ will take longer to calculate, but will result in higher quality sampling.&#xD;&#xA;&#xD;&#xA;The reason that the candidate count should scale with the existing sample count is that it keeps statistics about the points constant, so lets you reason about how higher sample counts will look / behave by looking at lower sample counts.&#xD;&#xA;&#xD;&#xA;Values of $m$ that are too high will end up looking like the lower images of the question though, where the randomness is almost completely gone.&#xD;&#xA;&#xD;&#xA;The problem with the high sample counts is that they more fully cover all possible pixel locations, and since the best candidate is chosen, much randomness will go away leaving you with something a lot more deterministic.&#xD;&#xA;&#xD;&#xA;I personally choose to do $m*n+1$ samples to slightly simplify the logic and let it handle the first sample when $n=0$.&#xD;&#xA;&#xD;&#xA;This technique was described in this paper:&#xD;&#xA;&#xD;&#xA;&quot;Spectrally optimal sampling for distribution ray tracing&quot; Mitchell 1991.&#xD;&#xA;https://dl.acm.org/citation.cfm?id=122718.122736&#xD;&#xA;&#xD;&#xA;Below is the same setup as in the question where 455 black pixels are placed in a 64x64 image, showing the result for some values of $m$.  The quality is surprisingly good even for low values of $m$ and the execution time is much, much lower than the process described in the question.  I'm also limiting the candidate count to be at maximum 1/2 the number of pixels (an arbitrary limit I came up with) in the image to keep the candidate count from going too high for denser samplings in an effort to keep the quality and computation time decent.&#xD;&#xA;&#xD;&#xA;I've heard that storing points in grids can help in accelerating the calculation time of &quot;how far is this candidate from the closest point&quot; and I believe it should, but I haven't tried it yet.&#xD;&#xA;&#xD;&#xA;When $m=0$, it's equivelant to white noise and just randomly placing the dots.&#xD;&#xA;&#xD;&#xA;Note that when calculating the distance between two points I am treating the image as if it wraps around, so that dots on opposite edges are treated close  together.  If interested in details of how to calculate distance in wrap around (toroidal) space, check out this blog post:&#xD;&#xA;https://blog.demofox.org/2017/10/01/calculating-the-distance-between-points-in-wrap-around-toroidal-space/&#xD;&#xA;&#xD;&#xA;Here is a blog post on Mitchell's best candidate algorithm too I wrote up:&#xD;&#xA;https://blog.demofox.org/2017/10/20/generating-blue-noise-sample-points-with-mitchells-best-candidate-algorithm/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/blUaK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29124" PostHistoryTypeId="2" PostId="10066" RevisionGUID="b4ce30fe-6f73-4c59-a075-aa86981ad4f1" CreationDate="2020-07-29T22:32:41.873" UserId="8925" Text="I have an image and a sampler declared in a shader as follow&#xD;&#xA;&#xD;&#xA;    layout(binding = 5) uniform isampler2D heightmap;&#xD;&#xA;    layout(binding = 3) uniform writeonly uimage2D info;&#xD;&#xA;&#xD;&#xA;Which are correctly bound using the following code&#xD;&#xA;&#xD;&#xA;    glBindTextureUnit(5, heightmapId);&#xD;&#xA;    glBindImageTextures(3, 1, &amp;infoId);&#xD;&#xA;&#xD;&#xA;For introspection purposes, I am trying to retrieve the binding points of these objets, 5 and 3, but I didn't find any way to do this for uniforms. Is it possible using the API?&#xD;&#xA;&#xD;&#xA;I first tried to use glGetProgramResourceIndex, since it worked with storage buffers, but it doesn't the results are get are incorrect, as if the explicit binding was ignored.&#xD;&#xA;&#xD;&#xA;I then looked at glGetProgramResourceiv, but the binding related enums are only available for storage buffers and atomic counters.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29125" PostHistoryTypeId="1" PostId="10066" RevisionGUID="b4ce30fe-6f73-4c59-a075-aa86981ad4f1" CreationDate="2020-07-29T22:32:41.873" UserId="8925" Text="Get binding point of sampler/image in shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="29126" PostHistoryTypeId="3" PostId="10066" RevisionGUID="b4ce30fe-6f73-4c59-a075-aa86981ad4f1" CreationDate="2020-07-29T22:32:41.873" UserId="8925" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29127" PostHistoryTypeId="2" PostId="10067" RevisionGUID="915323da-b12f-4001-b27c-0983deee8389" CreationDate="2020-07-30T00:51:09.710" UserId="2654" Text="The `binding` value for uniforms of opaque types is, from the perspective of the OpenGL API, the uniform's *value*. You set it by using `glProgramUniform1i`.&#xD;&#xA;&#xD;&#xA;As such, you query it by querying the value of the uniform with `glGetUniformiv`." ContentLicense="CC BY-SA 4.0" />
  <row Id="29128" PostHistoryTypeId="2" PostId="10068" RevisionGUID="b12c1744-8eb3-4d44-9ddd-e3bd8f276694" CreationDate="2020-07-30T04:10:17.177" UserId="9749" Text="What's the proper of way of calculating the coords to apply decals by let's say linear interpolation? &#xA;My understanding is that you render your GBuffer albedo, specular, etc... and after that you do another pass (before the lighting calculations) in which you modify the albedo and normal maps (and anything you'd like to get information from the decal). My guess is you transform your vertices to NDC to be able to calculate the bbox (for simplicity, I understand you can use more complex geometry) in which you want to apply the decals, use those bounds to discard every other fragment and write the decal to the maps. Is my understanding correct? And what matrix should be passed for calculating the depth? Should I do a previous pass to get the depth? Can I use the depth from a point different than the camera (I am calculating shadow maps already so being able to skip this step would be awesome), or can I reuse the one that I feed my lighting pass with? " ContentLicense="CC BY-SA 4.0" />
  <row Id="29129" PostHistoryTypeId="1" PostId="10068" RevisionGUID="b12c1744-8eb3-4d44-9ddd-e3bd8f276694" CreationDate="2020-07-30T04:10:17.177" UserId="9749" Text="Deferred Decals" ContentLicense="CC BY-SA 4.0" />
  <row Id="29130" PostHistoryTypeId="3" PostId="10068" RevisionGUID="b12c1744-8eb3-4d44-9ddd-e3bd8f276694" CreationDate="2020-07-30T04:10:17.177" UserId="9749" Text="|rasterizer|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29131" PostHistoryTypeId="50" PostId="9591" RevisionGUID="839b94d3-f086-4429-b5ee-68c61c7bb915" CreationDate="2020-07-30T13:04:30.463" UserId="-1" />
  <row Id="29132" PostHistoryTypeId="2" PostId="10069" RevisionGUID="0b1aec7c-8589-4ba4-afad-a45ee828bcd0" CreationDate="2020-07-30T16:18:52.837" UserId="12073" Text="It seems that virtually all path tracers use eye-based or view-based path tracing. That is, the light rays originate from the camera rather than the light source. The reason given for this everywhere I have seen online is that if one begins from the light source, then it is quite unlikely that the ray will ever hit the camera. For instance, the [documentation](https://docs.blender.org/manual/en/latest/render/cycles/optimizations/reducing_noise.html) for Blender's cycles says &quot; we do not waste light rays that will not end up in the camera&quot;.&#xD;&#xA;&#xD;&#xA;This seems intuitive at first, but this seems only to reverse the problem because one will just trace a ray until it hits the light source now, and this ray may never hit a light source before the maximum number of bounces, so we will just waste that ray as well. I can see how this is an improvement though, because if we originate at the camera, the first bounce will tend to have a large weight associated with it, but if we flipped the path to start from the light, then this last bounce would tend to have a small weight because many bounces have preceded it. That seems like the answer, except for one thing.&#xD;&#xA;&#xD;&#xA;Most path tracers use next even estimation, which just means that at each bounce, the light path is connected directly to a light source as long as nothing occludes that path. This is always a valid path and greatly speeds up convergence. However, if one is going to use next event estimation, then I really can't understand how tracing rays from the camera is advantageous over tracing rays from the light source? In next event estimation, one should almost always get a complete light path either way. Is it related to the ambiguity about which pixel on the camera to connect to? There is a similar ambiguity about which point of an area light to connect to.&#xD;&#xA;&#xD;&#xA; I am sure there must be a reason for tracing from the camera because everybody seems to be doing it, so if someone could explain this for me, and/or point to recent papers which compare the approaches, that would be greatly appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="29133" PostHistoryTypeId="1" PostId="10069" RevisionGUID="0b1aec7c-8589-4ba4-afad-a45ee828bcd0" CreationDate="2020-07-30T16:18:52.837" UserId="12073" Text="Why is eye-based ray tracing preferred over light-based ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29134" PostHistoryTypeId="3" PostId="10069" RevisionGUID="0b1aec7c-8589-4ba4-afad-a45ee828bcd0" CreationDate="2020-07-30T16:18:52.837" UserId="12073" Text="|raytracing|pathtracing|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29135" PostHistoryTypeId="2" PostId="10070" RevisionGUID="bb9c164d-f5d4-4494-a6a2-7512e2e12d3a" CreationDate="2020-07-30T16:55:18.593" UserId="13321" Text="As you point out there is problems about which pixel on the camera to connect to. You probably wouldn't notice where you took the sample on an area light because generally the light is pretty uniform throughout, and even if it is textured you can just take a few samples and it will average to look ~correct. However if you connect to a random pixel, you would very easily notice that some pixels are black or have aliasing problems. By starting at the camera it's easier to ensure that all pixels are being sampled enough.&#xD;&#xA;&#xD;&#xA;You are also only considered the light from one bounce. If you also want to get indirect lighting then your statement about weights comes into play again, and you are more likely to get a good path by starting at the camera.&#xD;&#xA;&#xD;&#xA;Finally there are many techniques which start from the light! And techniques which start at both ends and try and connect. Try searching for photon mapping and bi-directional path tracing. It just turns out that forward path tracers generally work the best in most situations. Renderman has an integrator which combines all these techniques  which you can read about here https://rmanwiki.pixar.com/display/REN/PxrVCM ." ContentLicense="CC BY-SA 4.0" />
  <row Id="29137" PostHistoryTypeId="52" PostId="10069" RevisionGUID="f07ed6d5-7dab-49b6-b57f-629d3a734524" CreationDate="2020-07-31T00:43:50.383" />
  <row Id="29138" PostHistoryTypeId="2" PostId="10071" RevisionGUID="096b8c4d-c616-4796-9f95-2a1b910dfd34" CreationDate="2020-07-31T04:19:50.157" UserId="2654" Text="It is a matter of performance.&#xD;&#xA;&#xD;&#xA;From a particular point on any object, you cannot know precisely where any illumination is coming from. There could be a near-perfect mirrored surface nearby. There could be water which reflects some portion of light to that point on the surface. Answering this question would require a full solution to the rendering equation.&#xD;&#xA;&#xD;&#xA;However, from a particular point on any object in the scene, you can at least know whether or not any lights are *directly* casting light on that point. How? By firing a ray directly from the surface to that light. You know exactly where the lights are, so you can fire rays in those directions. If nothing opaque is in the way, then some portion of that light directly illuminates that point on the surface.&#xD;&#xA;&#xD;&#xA;If you start from the perspective of a light, you can fire a whole bunch of rays in every direction of the light and hit a whole bunch of objects. You can determine the direct illumination on all of those positions on all of those objects.&#xD;&#xA;&#xD;&#xA;But there is no guarantee that any of those objects are visible to the viewer. In this scenario, many rays and light computations get wasted.&#xD;&#xA;&#xD;&#xA;By contrast, if you start off from the perspective of all surfaces directly visible to the viewer, you can find all surfaces that are directly visible to the viewer. From there, you can compute the direct illumination for all of those points within the view.&#xD;&#xA;&#xD;&#xA;Exactly zero rays have been wasted in this scenario. Every ray you fire is contributing in some way to the image (even if a light is blocked, it's still contributing by not providing illumination from that surface).&#xD;&#xA;&#xD;&#xA;So in the case of purely direct illumination, there is no question that starting from the viewport uses fewer rays and fewer lighting computations. It is therefore faster.&#xD;&#xA;&#xD;&#xA;If you start firing doing reflection and refraction rays, these too are faster if you start from the viewer. Each reflection/refraction ray is fired from a position that we *know* contributes to the final image. Whereas if you're firing a bunch of rays due to rays that were fired from lights, you have no idea if they're going to meaningfully contribute to the scene.&#xD;&#xA;&#xD;&#xA;In view-based ray tracing, every ray you fire will contribute meaningfully to the scene being displayed. Well, until you start having to take into account more complex lighting, such as diffuse inter-reflection. That's the point where you can no longer know for certain where the source of lighting is, so you have to start firing rays speculatively.&#xD;&#xA;&#xD;&#xA;But even then, if you're going to fire rays speculatively, it's best to start from places that you *know* are going to be illuminated." ContentLicense="CC BY-SA 4.0" />
  <row Id="29139" PostHistoryTypeId="2" PostId="10072" RevisionGUID="af20cb51-e0f3-4fcb-840b-97b03d8dad85" CreationDate="2020-07-31T05:08:44.627" UserDisplayName="user13771" Text="I saw this question some where, I think Reddit, but I can't find it. I have same issue.&#xD;&#xA;Please see the screenshot beneath. I've uploaded [the PDF to mega.nz](https://mega.nz/file/3pZzEKJC) I'm using Adobe Acrobat Pro DC Version 2019.010.20064.&#xD;&#xA;&#xD;&#xA;I'm trying to convert the book's default (C, M, Y, K) = (99%, 98%, 18%, 6%) (ie dark purple) to [(90, 0, 90, 0) (green)](https://www.colorhexa.com/1aff1a). After I click 'OK' and click 'Fix', Adobe Acrobat executes the fixup, but the color fails to change. Why? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w5Pjt.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29140" PostHistoryTypeId="1" PostId="10072" RevisionGUID="af20cb51-e0f3-4fcb-840b-97b03d8dad85" CreationDate="2020-07-31T05:08:44.627" UserDisplayName="user13771" Text="Why isn't the 'Map Colors' fixup changing text colors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29141" PostHistoryTypeId="3" PostId="10072" RevisionGUID="af20cb51-e0f3-4fcb-840b-97b03d8dad85" CreationDate="2020-07-31T05:08:44.627" UserDisplayName="user13771" Text="|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29142" PostHistoryTypeId="2" PostId="10073" RevisionGUID="3a8699bb-3ef7-4f75-8dde-454fe31798fd" CreationDate="2020-07-31T19:08:47.500" UserId="7462" Text="Sobel edge detection is pretty much the quintessential way to get edges out of an image. It however suffers from certain quirks.&#xD;&#xA;&#xD;&#xA;One example is, because it's gradient, based certain surfaces exhibit weird appearances in certain saliency maps. For example, given a depth image, take a plane and start inclining it. You will notice that as the plane becomes more and more perpendicular to the view, a large section of it acquires a higher and higher gradient magnitude. Thus resulting in a major area of the plane being considered an edge by any thresholding mechanism. In other words, towards the horizon, the depth difference of ANY pair of adjacent pixels that contain a portion of the plane becomes significantly large, thus getting selected as edges, despite not being edges.&#xD;&#xA;&#xD;&#xA;This also means that regions with bigger z differences tend to have bigger edges. Consider a sphere placed in front of a near plane vs a sphere placed in front of a far plane, both spheres at the same distance from the camera. If any interpolation filtering is active, then the sphere in the near plane has less pixels with large deltas than the one in the far plane thus its outline is bigger.&#xD;&#xA;&#xD;&#xA;Canny addresses this problem by doing a per pixel local search and min maxing the gradient magnitude to guarantee a one pixel wide edge. However, this is not easily parrallelizable (not GPU friendly) and thus slow.&#xD;&#xA;&#xD;&#xA;Are there other algorithms that maintain edge width that are more suitable for real time applications? The width doesn't have to be perfectly one pixel wide, rather I am just looking to reducing the standard deviation of the edge with.&#xD;&#xA;They don;t have to be perge &#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="29143" PostHistoryTypeId="1" PostId="10073" RevisionGUID="3a8699bb-3ef7-4f75-8dde-454fe31798fd" CreationDate="2020-07-31T19:08:47.500" UserId="7462" Text="Are there algorithms besides Canny edge detection that can create consistent width edges?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29144" PostHistoryTypeId="3" PostId="10073" RevisionGUID="3a8699bb-3ef7-4f75-8dde-454fe31798fd" CreationDate="2020-07-31T19:08:47.500" UserId="7462" Text="|image-processing|mathematics|edge-detection|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29161" PostHistoryTypeId="50" PostId="7804" RevisionGUID="808a1f2d-e46c-4999-810b-dcef9130fda0" CreationDate="2020-08-01T16:05:10.460" UserId="-1" />
  <row Id="29162" PostHistoryTypeId="2" PostId="10078" RevisionGUID="11d5d047-c551-4815-8d01-85e670453ab2" CreationDate="2020-08-01T23:17:08.483" UserId="11058" Text="I have an image rendered to the screen, and based on the normalized device coordinates of the cursor I would like to pick the pixel of the image under the cursor.&#xD;&#xA;&#xD;&#xA;Say the image has four channels, I then define a pixel struct:&#xD;&#xA;&#xD;&#xA;    struct Pixel {&#xD;&#xA;      unsigned char r, g, b, a;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I can then get the closest index of the pixel under cursor like this:&#xD;&#xA;&#xD;&#xA;    int getPixel(float normalX, float normalY, float imageWidth, float imageHeight) {&#xD;&#xA;      return (int)(normalY*imHeight)*imageWidth + normalX*imageWidth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now how would I do it the other way around, basically given the pixel index get its normalized device coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29163" PostHistoryTypeId="1" PostId="10078" RevisionGUID="11d5d047-c551-4815-8d01-85e670453ab2" CreationDate="2020-08-01T23:17:08.483" UserId="11058" Text="Get normalized device coordinate of an image pixel" ContentLicense="CC BY-SA 4.0" />
  <row Id="29164" PostHistoryTypeId="3" PostId="10078" RevisionGUID="11d5d047-c551-4815-8d01-85e670453ab2" CreationDate="2020-08-01T23:17:08.483" UserId="11058" Text="|c++|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29165" PostHistoryTypeId="2" PostId="10079" RevisionGUID="30205101-03ff-482f-b603-1e698f6ebae6" CreationDate="2020-08-02T11:06:18.470" UserId="6686" Text="You can modulus by row length to retrieve the x coordinate (think about the x coordinate &quot;wrapping around&quot; after each line), and division by row length to get the y coordinate (inverting the multiply you have by imageWidth). We subtract one from the width and height to ensure the last pixel in the row/column maps to `1.0`. Note that this isn't &quot;Normalized Device Coordinates&quot;, since that implies a 3D quantity which also stores depth, and that all coordinates lie in `[-1,1]`. &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;struct Point2D { float x; float y; };&#xD;&#xA;&#xD;&#xA;Point2D GetNormalizedPixelCoords(int pixelIdx, int imageWidth, int imageHeight) {&#xD;&#xA;    Point2D point;&#xD;&#xA;    point.x = (pixelIdx % imageWidth) / (float)(imageWidth-1);&#xD;&#xA;    point.y = (pixelIdx / imageWidth) / (float)(imageHeight-1);&#xD;&#xA;    return point;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29166" PostHistoryTypeId="50" PostId="9626" RevisionGUID="95eebca4-2aa0-42ca-b945-1be61c6e7eae" CreationDate="2020-08-02T12:02:50.473" UserId="-1" />
  <row Id="29167" PostHistoryTypeId="2" PostId="10080" RevisionGUID="4f3a0bd0-c5c4-436a-89a2-5bc32adb3216" CreationDate="2020-08-02T12:44:21.243" UserId="13095" Text="The first step to achieving what you are asking for would be to find the normalized texture coordinates a.k.a UV-coordinates of the pixel. This can be done as described by AJ Weeks in his answer. However, I wouldn't divide by `width-1`/`height-1`, but instead, I would add `0.5` to the x- and y-coordinate and divide by the full width and height. This should give you the &quot;center&quot; of each pixel. As an example, say you have an 8x8 texture and index 10. This would yield `x=1` and `y=2`. After the addition, you get `x=1.5` and `y=2.5`. Dividing each of those by 8 gives you the normalized texture coordinates of `u=0.1875` and `v=0,3125`.&#xD;&#xA;&#xD;&#xA;Depending on how you render your image, the next step might be a little bit tricky. In general, if your texture is mapped onto an arbitrary mesh, you need to find the triangle that includes the UV-coordinates of the pixel by performing a 2d-point-in-triangle test against the triangles' vertices UV-coordinates. Notice, that depending on your mesh's texture coordinates, there might be more than one triangle or none if you use the texture repetitively or only a certain area of it. If this is not the case, there still might be multiple triangles that contain it, if the point lies on a boundary or vertex. In this case, pick an arbitrary triangle, since the result should be the same. &#xD;&#xA;&#xD;&#xA;Now if you have found the triangle determine the [barycentric coordinates](https://en.wikipedia.org/wiki/Barycentric_coordinate_system) of the pixel from its UV-coordinates and the vertices of the triangle. Then use those coordinates and multiply them with the vertices 3d coordinates to get the actual 3d coordinates of the pixel in model space.&#xD;&#xA;&#xD;&#xA;Finally, perform the usual transformations with your transformation matrices -&gt; model to world -&gt; world to camera -&gt; perspective projection. Then you have your NDC coordinates of the pixel.&#xD;&#xA;&#xD;&#xA;The determination of the 3d coordinates in model space can be simplified if your model is just a flat rectangular surface described by 4 vertices that has the one and only purpose to display the whole undistorted texture without repetitions, offsets or scaling (means the corner point vertices UV coordinates are either 0 or 1). Then you can perform a linear interpolation of the 3d coordinates in x and y direction where the UV-coordinate values of the pixel are the interpolation weights in the corresponding direction." ContentLicense="CC BY-SA 4.0" />
  <row Id="29168" PostHistoryTypeId="5" PostId="10080" RevisionGUID="7d473ef4-4231-449e-a7c3-559bfc183b67" CreationDate="2020-08-02T12:52:16.883" UserId="13095" Comment="added 268 characters in body" Text="The first step to achieving what you are asking for would be to find the normalized texture coordinates a.k.a UV-coordinates of the pixel. This can be done as described by AJ Weeks in his answer. However, I wouldn't divide by `width-1`/`height-1`, but instead, I would add `0.5` to the x- and y-coordinate and divide by the full width and height. This should give you the &quot;center&quot; of each pixel. As an example, say you have an 8x8 texture and index 10. This would yield `x=1` and `y=2`. After the addition, you get `x=1.5` and `y=2.5`. Dividing each of those by 8 gives you the normalized texture coordinates of `u=0.1875` and `v=0,3125`.&#xD;&#xA;&#xD;&#xA;Depending on how you render your image, the next step might be a little bit tricky. In general, if your texture is mapped onto an arbitrary mesh, you need to find the triangle that includes the UV-coordinates of the pixel by performing a 2d-point-in-triangle test against the triangles' vertices UV-coordinates. Notice, that depending on your mesh's texture coordinates, there might be more than one triangle or none if you use the texture repetitively or only a certain area of it. If this is not the case, there still might be multiple triangles that contain it, if the point lies on a boundary or vertex. In this case, pick an arbitrary triangle, since the result should be the same. &#xD;&#xA;&#xD;&#xA;Now if you have found the triangle determine the [barycentric coordinates](https://en.wikipedia.org/wiki/Barycentric_coordinate_system) of the pixel from its UV-coordinates and the vertices of the triangle. Then use those coordinates and multiply them with the vertices 3d coordinates to get the actual 3d coordinates of the pixel in model space.&#xD;&#xA;&#xD;&#xA;Finally, perform the usual transformations with your transformation matrices -&gt; model to world -&gt; world to camera -&gt; perspective projection. Then you have your NDC coordinates of the pixel.&#xD;&#xA;&#xD;&#xA;The determination of the 3d coordinates in model space can be simplified if your model is just a flat rectangular surface described by 4 vertices that has the one and only purpose to display the whole undistorted texture without repetitions, offsets or scaling (means the corner point vertices UV coordinates are either 0 or 1). Then you can perform a linear interpolation of the 3d coordinates in x and y direction where the UV-coordinate values of the pixel are the interpolation weights in the corresponding direction.&#xD;&#xA;&#xD;&#xA;It gets even easier if you render your texture as a full-screen image. Then you only need to subtract 0.5 from your UV-coordinates and multiply the result by 2. This transforms the UV-range [0,1] to the NDC range [-1,1]. The depth value can be chosen arbitrarily. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29169" PostHistoryTypeId="2" PostId="10081" RevisionGUID="86495f28-6145-4f37-8c78-214bb8b61d31" CreationDate="2020-08-02T13:05:06.013" UserId="11058" Text="I'm trying to create a simple painting application. And I was wondering about an efficient way to draw pixels on the screen.&#xD;&#xA;&#xD;&#xA;I have a pixel struct:&#xD;&#xA;&#xD;&#xA;    struct Pixel {&#xD;&#xA;     unsigned char r, g, b, a;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And I have two methods for converting between pixel coordinates and normalized pixel coordinates. `w` and `h` are image width and height respectively.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int getPixelIndex(float2 norm, int w, int h) {&#xD;&#xA;       return (int)(norm.x*h)*w + norm.y*h;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float2 getPixelNormCoords(int index, int w, int h) {&#xD;&#xA;       float2 norm;&#xD;&#xA;       norm.x = (index % w) / (float)(w-1);&#xD;&#xA;       norm.y = (index / h) / (float)(h-1);&#xD;&#xA;       return norm;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now if I want to draw a pixel under the cursor I could do it like this:&#xD;&#xA;&#xD;&#xA;    int pixelIndex = getPixelIndex(cursorNorm.x, cursorNorm.y, w, h);&#xD;&#xA;&#xD;&#xA;    pixels[pixelIndex] = {255, 0, 0, 255};&#xD;&#xA;&#xD;&#xA;However what if I want to fill more pixels around the cursor, to create different brushes. Say I want to create a square brush with a given offset `d`. One hacky way to do this would be:&#xD;&#xA;&#xD;&#xA;    float delta = 10e-4;&#xD;&#xA;    for (float i = -d; i &lt; d; i+=delta) {&#xD;&#xA;      for (float j = -d; j &lt; d; j+=delta) {&#xD;&#xA;        int pixelIndex = getPixel(cursorNorm.x+i, cursorNorm.y+j, w, h);&#xD;&#xA;        pixels[pixelIndex] = {255, 0, 0, 255};&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Another way would be to iterate over each pixel:&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; size(pixels); i++) {&#xD;&#xA;       float2 norm = getPixelNormCoords(i, w, h);&#xD;&#xA;&#xD;&#xA;       if (fabs(norm.x-cursorNorm.x) &lt; d &amp;&amp; fabs(norm.y-cursorNorm.y) &lt; d)&#xD;&#xA;          pixels[i] = {255, 0, 0, 255};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However this way seems to be extremely costly.&#xD;&#xA;&#xD;&#xA;Are there more efficient and less hacky methods to accomplish what I'm trying to do?&#xD;&#xA;     &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="29170" PostHistoryTypeId="1" PostId="10081" RevisionGUID="86495f28-6145-4f37-8c78-214bb8b61d31" CreationDate="2020-08-02T13:05:06.013" UserId="11058" Text="Paint pixels on the image around the cursor for painting application" ContentLicense="CC BY-SA 4.0" />
  <row Id="29171" PostHistoryTypeId="3" PostId="10081" RevisionGUID="86495f28-6145-4f37-8c78-214bb8b61d31" CreationDate="2020-08-02T13:05:06.013" UserId="11058" Text="|c++|image|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29172" PostHistoryTypeId="5" PostId="10081" RevisionGUID="ee010a0e-535e-451d-b17f-ee22e2456744" CreationDate="2020-08-02T13:12:13.990" UserId="11058" Comment="added 9 characters in body" Text="I'm trying to create a simple painting application. And I was wondering about an efficient way to draw pixels on the screen.&#xD;&#xA;&#xD;&#xA;I have a pixel struct:&#xD;&#xA;&#xD;&#xA;    struct Pixel {&#xD;&#xA;     unsigned char r, g, b, a;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And I have two methods for converting between pixel coordinates and normalized pixel coordinates. `w` and `h` are image width and height respectively.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    int getPixelIndex(float2 norm, int w, int h) {&#xD;&#xA;       return (int)(norm.x*h)*w + norm.y*h;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float2 getPixelNormCoords(int index, int w, int h) {&#xD;&#xA;       float2 norm;&#xD;&#xA;       norm.x = (index % w) / (float)(w-1);&#xD;&#xA;       norm.y = (index / h) / (float)(h-1);&#xD;&#xA;       return norm;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Now if I want to draw a red pixel under the cursor I could do it like this:&#xD;&#xA;&#xD;&#xA;    int pixelIndex = getPixelIndex(cursorNorm.x, cursorNorm.y, w, h);&#xD;&#xA;&#xD;&#xA;    pixels[pixelIndex] = {255, 0, 0, 255};&#xD;&#xA;&#xD;&#xA;However what if I want to fill more pixels around the cursor, to create different brushes. Say I want to create a square brush with a given offset `d`. One hacky way to do this would be:&#xD;&#xA;&#xD;&#xA;    float delta = 10e-4;&#xD;&#xA;    for (float i = -d; i &lt; d; i+=delta) {&#xD;&#xA;      for (float j = -d; j &lt; d; j+=delta) {&#xD;&#xA;        int pixelIndex = getPixelIndex(cursorNorm.x+i, cursorNorm.y+j, w, h);&#xD;&#xA;        pixels[pixelIndex] = {255, 0, 0, 255};&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Another way would be to iterate over each pixel:&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; size(pixels); i++) {&#xD;&#xA;       float2 norm = getPixelNormCoords(i, w, h);&#xD;&#xA;&#xD;&#xA;       if (fabs(norm.x-cursorNorm.x) &lt; d &amp;&amp; fabs(norm.y-cursorNorm.y) &lt; d)&#xD;&#xA;          pixels[i] = {255, 0, 0, 255};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However this way seems to be extremely costly.&#xD;&#xA;&#xD;&#xA;Are there more efficient and less hacky methods to accomplish what I'm trying to do?&#xD;&#xA;     &#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="29173" PostHistoryTypeId="2" PostId="10082" RevisionGUID="4be1f28c-e88d-4092-965a-37d4939d9379" CreationDate="2020-08-02T14:31:33.710" UserId="13095" Text="I don't know, why you consider your first approach hacky, but an alternative would be to analyze the shape of your brush and how it interacts with your underlying data structure. For example for your rectangle: &#xD;&#xA;&#xD;&#xA;Let's assume the brush's sides are parallel to the sides of the image. Then you can calculate how man pixels are covered by your offset `d`. Let's call be the number of pixels between two corners `n`. Then you can determine the index of the upper left pixel of your rectangle and fill the next `n` indices since they represent the left border of your rectangle. Then add `h` to the index of the upper left point to get to the pixel right of it. Fill the next `n` pixels. Repeat this `n` times and you have finished filling your rectangle. Here is some untested code that should demonstrate the approach:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;float left_x = cursorNorm.x - d;&#xD;&#xA;float upper_y = cursorNorm.y - d;&#xD;&#xA;float lower_y = cursorNorm.y + d;&#xD;&#xA;&#xD;&#xA;int index_upper_left = getPixelIndex(left_x, upper_y, w, h);&#xD;&#xA;int index_lower_left = getPixelIndex(left_x, lower_y, w, h);&#xD;&#xA;&#xD;&#xA;int n = index_lower_left - index_upper_left;&#xD;&#xA;&#xD;&#xA;for (int i=0; i &lt; n; ++i)&#xD;&#xA;    for (int j=0; j &lt; n; ++j)&#xD;&#xA;        int index = index_upper_left + j*h + i&#xD;&#xA;        pixels[index] = {255, 0, 0, 255};&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Since this is all symmetric, you can vary this to start at the center point, run i and j just up to `n/2` and do something like that:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;for (int i=0; i &lt; n/2; ++i)&#xD;&#xA;    for (int j=0; j &lt; n/2; ++j)&#xD;&#xA;        int index_left = index_center - j*h&#xD;&#xA;        int index_right = index_center + j*h&#xD;&#xA;&#xD;&#xA;        pixels[index_left + i] = {255, 0, 0, 255};&#xD;&#xA;        pixels[index_left - i] = {255, 0, 0, 255};&#xD;&#xA;        pixels[index_right + i] = {255, 0, 0, 255};&#xD;&#xA;        pixels[index_right - i] = {255, 0, 0, 255};&#xD;&#xA;~~~&#xD;&#xA;More complex shapes like circles get a little bit more complicated but you can calculate for each affected column of pixels the index of the upper and lower affected pixel and fill between them. Remember that you can abuse symmetry here. Meaning if you found the upper pixel of a column, the lower pixel has the same y distance to the y-value of the center point. Additionally, the bounds to the left and to the right of the center are also identical. A helpful algorithm to find the bounds might be [Bresenham’s circle drawing algorithm](https://www.geeksforgeeks.org/bresenhams-circle-drawing-algorithm/). " ContentLicense="CC BY-SA 4.0" />
  <row Id="29174" PostHistoryTypeId="50" PostId="9307" RevisionGUID="598eb5de-b815-460d-9ef3-3fb8407b948d" CreationDate="2020-08-02T19:00:25.030" UserId="-1" />
  <row Id="29175" PostHistoryTypeId="5" PostId="5517" RevisionGUID="22945a79-7250-468c-ae71-a9e310a5d4cd" CreationDate="2020-08-03T08:44:17.107" UserId="209" Comment="Added a quote from the Porter-Duff paper to back up my assumption" Text="I apologise for only skimming through your question/answer and the links you gave but I thought it would be a good idea to post what needs to be done to *correctly* do any blending and/or filtering on images with an alpha channel.&#xD;&#xA;&#xD;&#xA;The first thing to note is that all calculations should be done in a linear colour space, but the image data in PNGs and JPEGs is most likely to be in [sRGB][1] which is non-linear. You should convert this data to a linear form before doing any calculations. For example, the average of black (0,0,0) and white (255,255,255) in sRGB is not (127,127,127) but (off the top of my head) something like (186,186,186). The filtering of images, especially those with neighbouring, complementary, saturated colours (e.g. Yellow&amp;Blue), can look quite odd if you don't take gamma into account.&#xD;&#xA;&#xD;&#xA;The second part of this theory dates back to Porter and Duff's seminal 1984 paper, &quot;[Compositing Digital Images][2]&quot;, which introduces the concept of pre-multiplied alpha. Pre-multiplied alpha basically means that you multiply the RGBs by the alpha value before doing calculations. &#xD;&#xA;&#xD;&#xA;The Porter-Duff paper states...&#xD;&#xA;&gt; There are a few reasons to dismiss this proposal,&#xD;&#xA;the most severe being that all compositing operations&#xD;&#xA;will involve multiplying the 1 in the red channel by&#xD;&#xA;the .5 in the alpha channel to compute the red contribution&#xD;&#xA;of this object at this pixel. The desire to avoid this&#xD;&#xA;multiplication points up a better solution, storing the&#xD;&#xA;pre-multiplied value in the color component, so that&#xD;&#xA;(.5,0,0,.5) will indicate a full red object half covering a&#xD;&#xA;pixel.&#xD;&#xA;&#xD;&#xA;... which suggests this was initially done just to reduce computation costs, but in Jim Blinn's article [&quot;Compositing-Theory&quot;][3], he demonstrates that the correct way to do any filtering or compositing operations is to first convert everything to premultipled. &#xD;&#xA;&#xD;&#xA;Once you have linearised and then pre-multiplied your pixel data, do the filtering/blending and, finally, undo the pre-multiply and reapply the gamma function to map back to sRGB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SRGB&#xD;&#xA;  [2]: https://keithp.com/~keithp/porterduff/p253-porter.pdf&#xD;&#xA;  [3]: https://graphics.stanford.edu/courses/cs248-02/blinn_theory.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29180" PostHistoryTypeId="50" PostId="9303" RevisionGUID="4ab2830d-6c68-4fac-92c4-6fcdc84923ad" CreationDate="2020-08-04T14:06:10.660" UserId="-1" />
  <row Id="29181" PostHistoryTypeId="2" PostId="10084" RevisionGUID="d2106a26-eaf4-4db6-9716-b5e82904d121" CreationDate="2020-08-04T16:08:21.953" UserId="13790" Text="In many datasets in the literature of both Computer Vision and Computer Graphics there is the albedo map of a scene represented as RGB images, which in principle corresponds to the diffuse reflecting component. The diffuse reflectance factor though of a material/surface is represented a one value, usually as ρ (rho), e.g. in the radiosity formulation. Thus, I am trying to understand how to go from an RGB representation to the corresponding diffuse value. I saw some people averaging the RGB values of the albedo map, e.g. for a pixel value (0, 168, 170) this would give:&#xD;&#xA;&#xD;&#xA;((0/255) + (168/255) + (170/255)) / 3 = 0.441830065359477&#xD;&#xA;&#xD;&#xA;however is just averaging enough/correct or there is a specific formulation.&#xD;&#xA;&#xD;&#xA;I am puzzled quite some time now about it and I cannot really find a good answer. Thus, I would appreciate any feedback." ContentLicense="CC BY-SA 4.0" />
  <row Id="29182" PostHistoryTypeId="1" PostId="10084" RevisionGUID="d2106a26-eaf4-4db6-9716-b5e82904d121" CreationDate="2020-08-04T16:08:21.953" UserId="13790" Text="Albedo image map to color's Light Reflectance Value (LRV)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29183" PostHistoryTypeId="3" PostId="10084" RevisionGUID="d2106a26-eaf4-4db6-9716-b5e82904d121" CreationDate="2020-08-04T16:08:21.953" UserId="13790" Text="|rendering|radiosity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29184" PostHistoryTypeId="2" PostId="10085" RevisionGUID="ac1746cb-cd21-4953-9fc1-482a07a8da79" CreationDate="2020-08-04T17:19:20.050" UserId="10928" Text="Usually, if we want to interpolate some vertex attributes, say $A_1$, $A_2$ and $A_3$, we have to first divide them by their corresponding $z$ in view space, then we interpolate them using barycentric weights and finally we multiply them by the interpolated $z$ at the current pixel. To interpolate this $z$, we have to inverse the 3 $z$ of each vertex, then interpolate them and finally inverse the result to have the interpolated $z$.&#xD;&#xA;&#xD;&#xA;In other words, the interpolated attribute $A$ is equal to:&#xD;&#xA;$$&#xD;&#xA;A = z \left(w_0 \times \frac{A_1}{Z_1} + w_1 \times \frac{A_2}{Z_2} + w_2 \times \frac{A_3}{Z_3}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $w_i$ are the barycentric weights, $Z_i$ are the depths of each vertex and $z$ is the interpolated depth:&#xD;&#xA;$$&#xD;&#xA;z = \frac{1}{w_0 \times \frac{1}{Z_1} + w_1 \times \frac{1}{Z_2} + w_2 \times \frac{1}{Z_3}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now my question is: instead of going back and forth between attributes and their reciprocals, can we just use the vertices'$z$ in normalized device coordinates, that is, the $z$s that have been divided by $w$, after the perspective projection?&#xD;&#xA;&#xD;&#xA;If I understand correctly, we interpolate the reciprocal of vertex attributes, because it's linear in screen space, but what about the $z$ in NDC space, after the homogeneous divide? If we can manage to use it, we already have a $z$ that we can linearly interpolate, because it has been homogenized?&#xD;&#xA;&#xD;&#xA;In the book &quot;Game Engine Architecture&quot;, page 667, they say:&#xD;&#xA;&gt; with w-buffering, we cannot linearly interpolate depths directly. Depths must be inverted prior to interpolation and the re-inverted prior to being stored the w-buffer.&#xD;&#xA;&#xD;&#xA;In other words, we don't need to invert $z$ back and forth to find the interpolated depth: we just have to use the $z$ in NDC space, that has been divided by view-space $z$. So we can directly interpolate the $z$ in NDC space to have perspective-correct depth, but how can I use this interpolated depth to interpolate other vertex attributes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29185" PostHistoryTypeId="1" PostId="10085" RevisionGUID="ac1746cb-cd21-4953-9fc1-482a07a8da79" CreationDate="2020-08-04T17:19:20.050" UserId="10928" Text="Interpolate vertex attributes with $z$ AFTER homogeneous divide" ContentLicense="CC BY-SA 4.0" />
  <row Id="29186" PostHistoryTypeId="3" PostId="10085" RevisionGUID="ac1746cb-cd21-4953-9fc1-482a07a8da79" CreationDate="2020-08-04T17:19:20.050" UserId="10928" Text="|transformations|perspective|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29187" PostHistoryTypeId="50" PostId="9178" RevisionGUID="a8042e1d-b348-4b41-a277-d21baa04b144" CreationDate="2020-08-04T23:01:50.223" UserId="-1" />
  <row Id="29188" PostHistoryTypeId="50" PostId="9328" RevisionGUID="72441d8f-3d94-429b-aadf-c77bc58d3bf3" CreationDate="2020-08-05T01:05:00.457" UserId="-1" />
  <row Id="29190" PostHistoryTypeId="2" PostId="10086" RevisionGUID="f46b9b81-e39b-447a-a805-ca43aaf30b6c" CreationDate="2020-08-05T06:53:34.850" UserId="48" Text="The $Z$ of NDC space is related to $1/Z_\text{view}$ but not the same. With a typical projection matrix,  they're related by an affine remapping,&#xD;&#xA;$$&#xD;&#xA;Z_\text{NDC} = a \, \frac{1}{Z_\text{view}} + b&#xD;&#xA;$$&#xD;&#xA;where $a, b$ are some constants related to the near and far planes. So, in general you wouldn't be able to substitute $Z_\text{NDC}$ for $1/Z_\text{view}$ in the interpolation expressions. The $a$ factor isn't a problem, as it would factor out and cancel, but if $b \neq 0$ then it will produce some extra terms and throw off the interpolation.&#xD;&#xA;&#xD;&#xA;If I'm hearing you right, it sounds like you're concerned about the idea of needing to prepare every single vertex attribute value (multiplying by $1/Z_\text{view}$) before interpolation and then reverse that afterward. Well, there is an easier way: we can create perspective-corrected barycentric coordinates $w'_0, w'_1, w'_2$, defined by&#xD;&#xA;$$&#xD;&#xA;w'_i \equiv \frac{w_i / Z_i}{w_0/Z_0 + w_1/Z_1 + w_2/Z_2}&#xD;&#xA;$$&#xD;&#xA;Then we can interpolate any attributes by $w'_0 A_0 + w'_1 A_1 + w'_2 A_2$, and it will be perspective-correct interpolation. You can verify this is equivalent to your original interpolation formula in your question. If we have more than three scalar attributes to interpolate (which we usually do), this would be the cheaper way to do it." ContentLicense="CC BY-SA 4.0" />
  <row Id="29191" PostHistoryTypeId="50" PostId="5996" RevisionGUID="ccc9cfe1-0f2b-427c-a1e9-4c5811b4b393" CreationDate="2020-08-06T13:01:30.160" UserId="-1" />
  <row Id="29192" PostHistoryTypeId="2" PostId="10087" RevisionGUID="0ccc96bd-79a1-4aec-9b72-62d53019bc72" CreationDate="2020-08-06T21:09:46.227" UserId="13753" Text="I want to create my own 2D graphics library using signed distance functions where everything is drawn on the GPU. Browsing the web I quickly found [Inigo Quilez website][1] that describes how to draw basic shapes with signed distance functions. I can work out the math on my own and come up with toy examples using Shadertoy. The problem I have is that I do not understand how I could  I can call a function like drawCircle(...) from &quot;normal&quot; C code on the CPU to trigger the call to a function that draws a circle in a fragment shader. Of course I could draw the circle to a texture and send this to the GPU but that would not use the GPU for drawing. &#xD;&#xA;&#xD;&#xA;What would be a reasonable software design where one could invoke draw calls from the CPU using a painters model and then these would be executed on the GPU in a fragment shader?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm" ContentLicense="CC BY-SA 4.0" />
  <row Id="29193" PostHistoryTypeId="1" PostId="10087" RevisionGUID="0ccc96bd-79a1-4aec-9b72-62d53019bc72" CreationDate="2020-08-06T21:09:46.227" UserId="13753" Text="GPU accelerated 2D graphics library with signed distance functions" ContentLicense="CC BY-SA 4.0" />
  <row Id="29194" PostHistoryTypeId="3" PostId="10087" RevisionGUID="0ccc96bd-79a1-4aec-9b72-62d53019bc72" CreationDate="2020-08-06T21:09:46.227" UserId="13753" Text="|gpu|fragment-shader|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29195" PostHistoryTypeId="50" PostId="9631" RevisionGUID="0a17527a-7d8f-417e-9b3b-9151b9f40355" CreationDate="2020-08-07T09:01:55.257" UserId="-1" />
  <row Id="29196" PostHistoryTypeId="2" PostId="10088" RevisionGUID="4951eb3a-3526-4338-8c0c-0ede4a13123c" CreationDate="2020-08-07T15:49:15.550" UserId="13805" Text="I've been reading up on a vulkan tutorial online, here: &lt;https://vulkan-tutorial.com&gt;. This question should apply to any 3D rendering API however.&#xD;&#xA;&#xD;&#xA;In this lesson &lt;https://vulkan-tutorial.com/Vertex_buffers/Index_buffer&gt;, the tutorial had just covered using indexed rendering in order to reuse vertices when drawing the following simple two-triangle quad:&#xD;&#xA;&#xD;&#xA;![Text](https://vulkan-tutorial.com/images/indexed_rectangle.png)&#xD;&#xA;&#xD;&#xA;The four vertices were assigned red, green, blue and white colours as vertex attributes and the fragment shader had those colours interpolated across the triangles as expected. This leads to the ugly visual artefact on the diagonal where the two triangles meet. As I understand it, the interpolation will only be happening across each triangle, and so where the two triangles meet the interpolation doesn't cross the boundary.&#xD;&#xA;&#xD;&#xA;How could you, generally in any rendering api, have the colours smoothly interpolated over all four corners for a nice colour wheel affect without having this hard line? " ContentLicense="CC BY-SA 4.0" />
  <row Id="29197" PostHistoryTypeId="1" PostId="10088" RevisionGUID="4951eb3a-3526-4338-8c0c-0ede4a13123c" CreationDate="2020-08-07T15:49:15.550" UserId="13805" Text="How could I remove this colour interpolation artefact across a quad?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29198" PostHistoryTypeId="3" PostId="10088" RevisionGUID="4951eb3a-3526-4338-8c0c-0ede4a13123c" CreationDate="2020-08-07T15:49:15.550" UserId="13805" Text="|glsl|color|vulkan|interpolation|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29200" PostHistoryTypeId="2" PostId="10089" RevisionGUID="6597e6ce-234a-4634-91da-455fb8f2c198" CreationDate="2020-08-08T11:23:19.637" UserId="13807" Text="(I am new to Computer Graphics in general)&#xD;&#xA;&#xD;&#xA;I am learning how to ray trace from a book called ''Peter Shirley - Ray Tracing in One Weekend''. In the book, the code is written in C++. I have intermediate-advanced level understanding of good ol' C, but I've never written even simple programs in C++. I don't pretend everything the code says in the book. But, that is the fun part---figuring it out.&#xD;&#xA;&#xD;&#xA;But, for ray tracing, even C is slow. And writing GLSL fragment shaders is fast, even on my potato PC. And GLSL is closer to C than to C++. So, I'm trying to follow through the book using GLSL. But, GLSL has many limitations and I was hoping if you could teach me how to get around those limitations.&#xD;&#xA;&#xD;&#xA;1.  Pointers. GLSL doesn't have pointers. In the book, there is a function&#xD;&#xA;```bool hit_sphere(const vec3&amp; center, float radius, const ray&amp; r)```&#xD;&#xA;I believe that ''address of'' operator just points to the variable that is passed when the function is called. Without pointers, how to call a function by reference in GLSL?&#xD;&#xA;&#xD;&#xA;1. Late binding. In the book, every object is a class which exposes an interface function called `hit` which returns if a ray hits the object. How does one implement that in GLSL structs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29201" PostHistoryTypeId="1" PostId="10089" RevisionGUID="6597e6ce-234a-4634-91da-455fb8f2c198" CreationDate="2020-08-08T11:23:19.637" UserId="13807" Text="How to work around the pointer limitations of GLSL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29202" PostHistoryTypeId="3" PostId="10089" RevisionGUID="6597e6ce-234a-4634-91da-455fb8f2c198" CreationDate="2020-08-08T11:23:19.637" UserId="13807" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29203" PostHistoryTypeId="2" PostId="10090" RevisionGUID="c2f47058-548c-4a31-9398-06f31404f34d" CreationDate="2020-08-08T19:42:15.413" UserId="10928" Text="Clipping is down in homogeneous clip space, therefore after multiplying the vertices by the model-view matrix. But as we do clipping in clip space, the position of the new vertices that we interpolate is in clip space, so how can I translate back those new vertices coordinates into view space?&#xD;&#xA;&#xD;&#xA;I could perform the inverse transformation, but it seems costly. So how exactly do clipping work in the graphics pipeline? I mean, how can we get the position of the new generated vertices in view space?&#xD;&#xA;&#xD;&#xA;For example, with OpenGL, I would do the following in the vertex shader:&#xD;&#xA;&#xD;&#xA;```glsl &#xD;&#xA;layout (location = 0) in vec3 pos; // vertex position in model space&#xD;&#xA;&#xD;&#xA;out vec3 posViewSpace;&#xD;&#xA;&#xD;&#xA;// M V P are the model view projection matrices&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    posViewSpace = V * M * pos; // I want the pos in view space for shading&#xD;&#xA;    gl_Position = vec4(P * V * M * pos, 1.0); // Give OpenGL the position in clip space&#xD;&#xA;}&#xD;&#xA;``` &#xD;&#xA;&#xD;&#xA;But how can this work, because `posViewSpace` that will be given to the pixel shader has nothing to do with the _new vertices_ generated after clipping? Or maybe it doesn't matter, because `posViewSpace` will be interpolated from the _original_ vertices, but the pixel shader won't notice? Will the interpolation be correct and usable in the pixel shader, even if it's performed from the original vertices and not the new generated vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29204" PostHistoryTypeId="1" PostId="10090" RevisionGUID="c2f47058-548c-4a31-9398-06f31404f34d" CreationDate="2020-08-08T19:42:15.413" UserId="10928" Text="Using original vertices coordinates after clipping" ContentLicense="CC BY-SA 4.0" />
  <row Id="29205" PostHistoryTypeId="3" PostId="10090" RevisionGUID="c2f47058-548c-4a31-9398-06f31404f34d" CreationDate="2020-08-08T19:42:15.413" UserId="10928" Text="|opengl|clipping|pixel-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29206" PostHistoryTypeId="2" PostId="10091" RevisionGUID="d98e6342-99f8-42d5-9ebf-ec1729a26a0e" CreationDate="2020-08-08T19:54:14.060" UserId="2654" Text="A vertex consists of not just the position, but *all* of the values passed from the [vertex processing stage][1] to the rasterizer. So if a vertex gets clipped, the new vertices generated in that process must *generate* new values for those vertex processing outputs. It does this using the same math that it uses to generate the new vertex position.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Vertex_Processing" ContentLicense="CC BY-SA 4.0" />
  <row Id="29207" PostHistoryTypeId="2" PostId="10092" RevisionGUID="cf3f67c1-2ea0-486e-a898-ad4decc89363" CreationDate="2020-08-08T23:42:34.943" UserId="2654" Text="I'll get to the specifics of your question presently, but first it is important to discuss the broad thesis of your idea: porting C++ code as is to GLSL.&#xD;&#xA;&#xD;&#xA;This is a bad idea. The execution model of shaders is *fundamentally* different from the way a normal program (even a multi-threaded program) works. Attempting to port such code from one execution model to another is not a good idea. Your best bet is to try to make the algorithms involved fit the nature of the [rendering pipeline][1]. That is, you need to understand how rendering works, then try to apply the mechanics of rendering to the problem you're trying to solve.&#xD;&#xA;&#xD;&#xA;For example, in regular CPU code, you might implement a ray-tracer by iterating over a bunch of locations on the screen and doing ray-scene intersection tests for each of them. Doing that iteration on the GPU in GLSL code is wrong. Instead, you should map rendering concepts to the needs of a ray-tracing algorithm. You might have each fragment shader do a single ray/scene processing step, with the fragment shader inputs being a direction from the camera. There would be no explicit loop over the screen's pixels; the loop happens implicitly in the rasterizer. The rasterizer generates a fragment shader invocation for each pixel-sized area of a rendered object. You would simply render a single quad that covers the whole screen.&#xD;&#xA;&#xD;&#xA;Things like that are how you need to think of these kinds of problems in a GPU-centric computation model.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;GLSL does not have pointers. But it does have [shader storage buffer objects][2], which allow you to define arbitrarily large regions of memory that the shader can read from. A &quot;pointer&quot; in this model is just an index into an array of data structures. You have to do the indexing explicitly in GLSL code.&#xD;&#xA;&#xD;&#xA;Similarly, any form of &quot;late binding&quot; can just be a switch statement based on some value in a data structure. The different `case`es define which function to call.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 4.0" />
  <row Id="29211" PostHistoryTypeId="2" PostId="10094" RevisionGUID="33bde41f-5799-4bd2-8c9c-1189f16ad90f" CreationDate="2020-08-09T17:14:56.847" UserId="6562" Text="I have an octree containing different LODs of an [isosurface][1] that was extracted using [Marching Cubes][2].&#xD;&#xA;&#xD;&#xA;Neighbouring chunks show surfaces that do not line up if they have different LOD. See image below.&#xD;&#xA;&#xD;&#xA;I find that stitching them up is a hairy and complicated affair, so I am looking at alternatives to Marching Cubes, but I am not sure if this will solve my problem?&#xD;&#xA;&#xD;&#xA;[Dual Contouring][3] would be a candidate. Its main advantage seems to be sharp-edges, but it is unclear to me if different LODs of a Dual Contour surface would line up.&#xD;&#xA;&#xD;&#xA;Another is [Cubic Marching Squares][4]. But again it is unclear if LODs match up in here.&#xD;&#xA;&#xD;&#xA;To be clear: I do not use LOD to adaptively refine, based on geometry. I use LOD to have far away (from camera/vehicle) chunks in low resolution. &#xD;&#xA;&#xD;&#xA;So my question: Does moving from MC to either DC or CMS solve the issue of LOD cracks in the surface?&#xD;&#xA;&#xD;&#xA;[![iso-surface showing cracks][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Isosurface&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Marching_cubes&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Isosurface#Dual_Contouring&#xD;&#xA;  [4]: https://www.csie.ntu.edu.tw/~cyy/publications/papers/Ho2005CMS.pdf&#xD;&#xA;  [5]: https://i.stack.imgur.com/PB4tB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29212" PostHistoryTypeId="1" PostId="10094" RevisionGUID="33bde41f-5799-4bd2-8c9c-1189f16ad90f" CreationDate="2020-08-09T17:14:56.847" UserId="6562" Text="Isosurface with cracks between LODs" ContentLicense="CC BY-SA 4.0" />
  <row Id="29213" PostHistoryTypeId="3" PostId="10094" RevisionGUID="33bde41f-5799-4bd2-8c9c-1189f16ad90f" CreationDate="2020-08-09T17:14:56.847" UserId="6562" Text="|computational-geometry|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29214" PostHistoryTypeId="2" PostId="10095" RevisionGUID="94e22105-d7f7-44d5-8a43-ea5dc356150d" CreationDate="2020-08-09T18:52:48.773" UserId="13805" Text="From what I understand of Vulkan, we have a render pass with its associated image resources and subpasses, and each subpass accesses those resources and may synchronise with previous subpasses to process the scene. In a 3D scene, we will have some geometry and lighting and shaders etc. we can do depth pass, deferred shading and so on - and that can all be encapsulated in a single render pass, by chaining multiple subpasses and their results together.&#xD;&#xA;&#xD;&#xA;When would we ever need multiple render passes in a 3d scene? I understand that something like post processing or UI compositing could be implemented in a second render pass, as they need the result from the first 3d pass to present the final image. I am at a loss as to a situation whereby a game engine, let's say, would need multiple render passes, as all of its geometry and lighting and shading etc. can be drawn with the same render pass, and that render pass will contain all the final necessary buffers, like the final image. &#xD;&#xA;&#xD;&#xA;Other than using multiple render passes as you might use subpasses (each render pass relying on the previous one in some way and each render pass having only one subpass) - what is the point? &#xD;&#xA;&#xD;&#xA;I am very much a beginner to Vulkan and to all of these concepts so please forgive any errors in the question itself or naive notions.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="29215" PostHistoryTypeId="1" PostId="10095" RevisionGUID="94e22105-d7f7-44d5-8a43-ea5dc356150d" CreationDate="2020-08-09T18:52:48.773" UserId="13805" Text="What are the use cases for multiple render passes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29216" PostHistoryTypeId="3" PostId="10095" RevisionGUID="94e22105-d7f7-44d5-8a43-ea5dc356150d" CreationDate="2020-08-09T18:52:48.773" UserId="13805" Text="|rendering|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29217" PostHistoryTypeId="5" PostId="10095" RevisionGUID="3b2f48d5-3573-4d4d-8126-c71f52f2eb2d" CreationDate="2020-08-09T19:08:21.350" UserId="13805" Comment="added 42 characters in body" Text="From what I understand of Vulkan, we have a render pass with its associated image resources and subpasses, and each subpass accesses those resources and may synchronise with previous subpasses to process the scene. In a 3D scene, we will have some geometry and lighting and shaders etc. we can do depth pass, deferred shading and so on - and that can all be encapsulated in a single render pass, by chaining multiple subpasses and their results together.&#xD;&#xA;&#xA;Excluding the scenario of tiled rendering, when would we ever need multiple render passes in a 3d scene? I understand that something like post processing or UI compositing could be implemented in a second render pass, as they need the result from the first 3d pass to present the final image. I am at a loss as to a situation whereby a game engine, let's say, would need multiple render passes, as all of its geometry and lighting and shading etc. can be drawn with the same render pass, and that render pass will contain all the final necessary buffers, like the final image. &#xD;&#xA;&#xD;&#xA;Other than using multiple render passes as you might use subpasses (each render pass relying on the previous one in some way and each render pass having only one subpass) - what is the point? &#xD;&#xA;&#xD;&#xA;I am very much a beginner to Vulkan and to all of these concepts so please forgive any errors in the question itself or naive notions.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="29218" PostHistoryTypeId="5" PostId="10095" RevisionGUID="28628f62-98ad-43a1-9739-c810aee94655" CreationDate="2020-08-09T19:34:42.120" UserId="13805" Comment="added 59 characters in body" Text="From what I understand of Vulkan, we have a render pass with its associated image resources and subpasses, and each subpass accesses those resources and may synchronise with previous subpasses to process the scene. In a 3D scene, we will have some geometry and lighting and shaders etc. we can do depth pass, deferred shading and so on - and that can all be encapsulated in a single render pass, by chaining multiple subpasses and their results together.&#xD;&#xA;&#xA;Excluding the scenario of tiled rendering, or when we are rendering to multiple final render targets, when would we ever need multiple render passes in a 3d scene? I understand that something like post processing or UI compositing could be implemented in a second render pass, as they need the result from the first 3d pass to present the final image. I am at a loss as to a situation whereby a game engine, let's say, would need multiple render passes, as all of its geometry and lighting and shading etc. can be drawn with the same render pass, and that render pass will contain all the final necessary buffers, like the final image. &#xD;&#xA;&#xD;&#xA;Other than using multiple render passes as you might use subpasses (each render pass relying on the previous one in some way and each render pass having only one subpass) - what is the point? &#xD;&#xA;&#xD;&#xA;I am very much a beginner to Vulkan and to all of these concepts so please forgive any errors in the question itself or naive notions.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="29219" PostHistoryTypeId="50" PostId="8151" RevisionGUID="2bae9e44-c008-499f-a4f1-e84f5fd1b953" CreationDate="2020-08-10T01:04:30.463" UserId="-1" />
  <row Id="29220" PostHistoryTypeId="2" PostId="10096" RevisionGUID="63124128-20b2-49bb-95c3-5fef8d7577d5" CreationDate="2020-08-10T10:22:39.303" UserId="13813" Text="I am new to graphics programming and i'm learning opengl. I managed to make a really simple renderer where i can import models display theirs textures with all lighting. My goal is to make a simple painting software like **Substance painter** or **Mari** but much much simpler and i don't have any idea on how they work ? I googled but couldn't find a good answer.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="29221" PostHistoryTypeId="1" PostId="10096" RevisionGUID="63124128-20b2-49bb-95c3-5fef8d7577d5" CreationDate="2020-08-10T10:22:39.303" UserId="13813" Text="How 3D painting software works" ContentLicense="CC BY-SA 4.0" />
  <row Id="29222" PostHistoryTypeId="3" PostId="10096" RevisionGUID="63124128-20b2-49bb-95c3-5fef8d7577d5" CreationDate="2020-08-10T10:22:39.303" UserId="13813" Text="|opengl|texture|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29223" PostHistoryTypeId="2" PostId="10097" RevisionGUID="0c24b631-c1f9-45a7-b980-c75a56d442ee" CreationDate="2020-08-10T12:54:50.930" UserId="13095" Text="We had some related questions lately, so you might find them useful:&#xD;&#xA;&#xD;&#xA;- [Paint pixels on the image around the cursor for painting application](https://computergraphics.stackexchange.com/questions/10081/paint-pixels-on-the-image-around-the-cursor-for-painting-application)&#xD;&#xA;- [How are textures projected onto 3d models in texture painting applications](https://computergraphics.stackexchange.com/questions/10034/how-are-textures-projected-onto-3d-models-in-texture-painting-applications)&#xD;&#xA;- [Get normalized device coordinate of an image pixel](https://computergraphics.stackexchange.com/questions/10078/get-normalized-device-coordinate-of-an-image-pixel)&#xD;&#xA;&#xD;&#xA;I can't tell you how the named applications do it, since I don't have access to the code, but painting onto a 3d model could be achieved as follows:&#xD;&#xA;&#xD;&#xA;When you click the &quot;paint&quot; button, you cast a ray from the camera position into your 3d scene. For perspective projections, the direction depends on the mouse's screen position. You can look into my answer to [this question](https://computergraphics.stackexchange.com/questions/9954/how-to-unproject-cursor-with-orthographic-projection) to get an idea of how this is done.&#xD;&#xA;&#xD;&#xA;Now perform a collision check of the ray and your model to find the affected triangle/triangles and vertices. Calculate the [Barycentric coordinates](https://en.wikipedia.org/wiki/Barycentric_coordinate_system) where the ray hits the affected triangle. Use them to interpolate the texture coordinates of the intersection point. From the model data, you should know, which texture is used at the target location. &#xD;&#xA;&#xD;&#xA;Now you know where you want to paint in your models' texture. How to proceed depends on what you want to paint. In case you just want to paint a pixel, you have to overwrite the texture's pixel at this location. You can do this either on the CPU or on the GPU using the rendering pipeline.&#xD;&#xA;&#xD;&#xA;If you don't understand some things I mentioned yet, read the links I provided and continue [learning OpenGL](https://learnopengl.com/). Things will get clearer as soon as you know the rendering pipeline and get used to working with textures. If something is still not clear after that, feel free to ask.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29224" PostHistoryTypeId="2" PostId="10098" RevisionGUID="9d94d853-a306-408b-9eea-63cd7ad2e7ed" CreationDate="2020-08-10T13:48:59.700" UserId="13814" Text="Apparently most people use BVHs in their raytracers. The ray-AABB intersection code is very fast and and the BVHs also compresses empty space efficiently, working even with infinitely large objects, while octrees (a more uniform subtype of BVH) apparently have a problems with compressing large open worlds - no way you can insert into a finite grid that huge mountain in the distance, without making the grid cells overly large. So what are the best practices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29225" PostHistoryTypeId="1" PostId="10098" RevisionGUID="9d94d853-a306-408b-9eea-63cd7ad2e7ed" CreationDate="2020-08-10T13:48:59.700" UserId="13814" Text="Is BVH faster than the octree/kd-tree for raytracing the objects on a GPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29226" PostHistoryTypeId="3" PostId="10098" RevisionGUID="9d94d853-a306-408b-9eea-63cd7ad2e7ed" CreationDate="2020-08-10T13:48:59.700" UserId="13814" Text="|raytracing|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29227" PostHistoryTypeId="2" PostId="10099" RevisionGUID="229ea57c-821c-4852-862b-1a32f56be1b6" CreationDate="2020-08-10T14:02:56.263" UserId="2654" Text="Instead of listing specific use cases, I will explain the technical limitations of a render pass structure which would prevent someone from putting all of their rendering within it. The use cases naturally fall out from those limitations.&#xD;&#xA;&#xD;&#xA;The most important being this: you cannot arbitrarily access *any of the images* attached to the render pass throughout the entire render pass. It doesn't matter if a particular subpass doesn't use the image as a render target throughout that subpass; you cannot bind it as a texture/image and read from/write to it in a shader. This covers the entirety of the render pass from start to end.&#xD;&#xA;&#xD;&#xA;Now, there are input attachments. These are uses of attachments that allow you to read from them in the shader. However, they aren't textures (though [they are descriptors][1]); they have more limitations than textures. The most important limitation being that you can only read from a pixel that corresponds to the current fragment's location (and also, you can only read them from a fragment shader). You can't fetch data arbitrarily from the image. A particular FS invocation can only read the specific pixel that was written previously at this FS invocation's location.&#xD;&#xA;&#xD;&#xA;Now, you can do some things within that limitation. You can do programmatic blending, for example. You can do deferred lighting passes, since any particular FS invocation only needs to read gbuffer data from the specific pixel for that invocation's location.&#xD;&#xA;&#xD;&#xA;But the main point is this: *any effect* which requires arbitrarily reading from an image that was rendered to *must* be in a different render pass from the render pass that rendered that image.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/q/43632903/734069" ContentLicense="CC BY-SA 4.0" />
  <row Id="29228" PostHistoryTypeId="33" PostId="10072" RevisionGUID="9eb1b802-aeb4-4806-8623-8878ac82b57e" CreationDate="2020-08-11T02:50:58.537" UserDisplayName="user13771" Comment="62" />
  <row Id="29229" PostHistoryTypeId="2" PostId="10100" RevisionGUID="7398cc17-9759-464e-8b16-fa76677298ff" CreationDate="2020-08-11T03:00:31.707" UserDisplayName="user5681" Text="First, it is importante to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods, have quite different characteristics. Since the object is subdivided with volumes, these volumes may intersect, which has impact on the traversal schemes used. We cannot, for instance, stop traversing a BVH as soon as we find an intersection with a surface. Since the volumes overlap, we ay need to check other primitives before stopping the traversal. On the other hand, it may be easier to implement a BVH because we do have to *split* the object parts. Also, BVHs usually generate shallower structures (which may eventualy compesate the slower traversal). However, one of the most interesting aspects of the BVHs is that they dynamic geometry-friendly. If geometry changes (but not much, actually), we can just adjust the size and position of the corresponding volumes. These adjustments may generate the adjustment of parent volumes, that may culminate in a chain reaction that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~ O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;Since GPUs target the rendering of dynamic geometry most of the time, BVHs have been chosen as the preferable data structure for ray tracing acceleration. &#xD;&#xA;&#xD;&#xA;This answer is full of strong statements that should accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. &#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however." ContentLicense="CC BY-SA 4.0" />
  <row Id="29230" PostHistoryTypeId="5" PostId="10100" RevisionGUID="bda92484-5490-478f-a0bf-0772c80f3628" CreationDate="2020-08-11T03:09:57.660" UserDisplayName="user5681" Comment="added 84 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal may be more inefficient. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume. These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;Since GPUs target the rendering of dynamic geometry most of the time, BVHs have been chosen as the preferable data structure for ray tracing acceleration. &#xD;&#xA;&#xD;&#xA;This answer is full of strong statements that should accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. &#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however." ContentLicense="CC BY-SA 4.0" />
  <row Id="29231" PostHistoryTypeId="5" PostId="10100" RevisionGUID="f7cd9439-d6a7-4700-b8a0-bd56890b0619" CreationDate="2020-08-11T03:21:30.103" UserDisplayName="user5681" Comment="added 348 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal may be more inefficient. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;I think that several factors influence the popularity of BVHs in the context of GPU ray tracing. GPUs target the rendering of dynamic geometry most of the time. In this case, BVHs are the preferable data structure because they can be quickly adjusted through local operations (refitting). Additionaly, since they do not imply complex split operations on the geometry, if you choose an efficient heuristic for building a BVH, we can create BVHs from scratch in almost no time on the GPU.&#xD;&#xA;&#xD;&#xA;This answer is full of strong statements that should accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. &#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however." ContentLicense="CC BY-SA 4.0" />
  <row Id="29232" PostHistoryTypeId="5" PostId="10100" RevisionGUID="4ea688fd-6a94-478d-b70b-930c94e0543a" CreationDate="2020-08-11T14:37:24.317" UserDisplayName="user5681" Comment="added 4 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal may be more inefficient. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;I think that main factor that turns the BVH into a popular acceleration structure in the context of GPU ray tracing is that GPUs target the rendering of dynamic geometry most of the time. In this case, BVHs are the preferable data structure because they can be quickly adjusted through local operations (refitting). Additionaly, since they do not imply complex split operations on the geometry, if you choose an efficient heuristic for building a BVH, we can create BVHs from scratch in almost no time on the GPU.&#xD;&#xA;&#xD;&#xA;This answer is full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. &#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however." ContentLicense="CC BY-SA 4.0" />
  <row Id="29233" PostHistoryTypeId="5" PostId="10100" RevisionGUID="ea501864-b37a-427d-a481-54abbaebe0b7" CreationDate="2020-08-11T14:43:14.357" UserDisplayName="user5681" Comment="added 38 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal may be more inefficient. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;I think that main factor that turns the BVH into a popular acceleration structure in the context of GPU ray tracing is not its traversal speed, but the fact that GPUs target the rendering of dynamic geometry most of the time. In this case, BVHs are the preferable data structure because they can be quickly adjusted through local operations (refitting). Additionaly, since they do not imply complex split operations on the geometry, if you choose an efficient heuristic for building a BVH, we can create BVHs from scratch in almost no time on the GPU.&#xD;&#xA;&#xD;&#xA;This answer is full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. &#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however." ContentLicense="CC BY-SA 4.0" />
  <row Id="29234" PostHistoryTypeId="5" PostId="7978" RevisionGUID="25c60fa2-8da1-4ee1-9515-ee63ce44d774" CreationDate="2020-08-11T18:04:18.350" UserId="13819" Comment="Added a code example for Swift 5" Text="The “blend factors” are the amount that the specified component is multiplied by while blending. “Destination” is the existing content that’s being blended “on top of”, while “source” is the new content that’s being blended “onto” it. When the blend operation is set to “add”, the final pixel value is calculated like this:&#xD;&#xA;&#xD;&#xA;    value = source * sourceBlendFactor + destination * destinationBlendFactor&#xD;&#xA;&#xD;&#xA;…so a blend factor of “one” means the value is used unchanged (multiplied by 1), “[x]Alpha” means the value is multiplied by the alpha value of x (source or destination), and “oneMinus[x]Alpha” means the value is multiplied by (1 - the alpha value of x).&#xD;&#xA;&#xD;&#xA;For additive blending, you most likely want the following:&#xD;&#xA;&#xD;&#xA;Obj-C&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Swift 5:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].isBlendingEnabled = true&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].rgbBlendOperation = .add&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].alphaBlendOperation = .add&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].sourceAlphaBlendFactor = .one&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].destinationRGBBlendFactor = .one&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].destinationAlphaBlendFactor = .one&#xD;&#xA;&#xD;&#xA;There’s a really helpful tool for visualizing the different options [here](https://www.andersriggelsen.dk/glblendfunc.php)—it’s written for OpenGL, but the Metal stuff works the same way.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29235" PostHistoryTypeId="24" PostId="7978" RevisionGUID="25c60fa2-8da1-4ee1-9515-ee63ce44d774" CreationDate="2020-08-11T18:04:18.350" Comment="Proposed by 13819 approved by -1 edit id of 538" ContentLicense="CC BY-SA 4.0" />
  <row Id="29236" PostHistoryTypeId="5" PostId="7978" RevisionGUID="f8307686-5f5b-4443-a494-839efdab9c24" CreationDate="2020-08-11T18:04:18.350" UserId="506" Comment="Added a code example for Swift 5" Text="The “blend factors” are the amount that the specified component is multiplied by while blending. “Destination” is the existing content that’s being blended “on top of”, while “source” is the new content that’s being blended “onto” it. When the blend operation is set to “add”, the final pixel value is calculated like this:&#xD;&#xA;&#xD;&#xA;    value = source * sourceBlendFactor + destination * destinationBlendFactor&#xD;&#xA;&#xD;&#xA;…so a blend factor of “one” means the value is used unchanged (multiplied by 1), “[x]Alpha” means the value is multiplied by the alpha value of x (source or destination), and “oneMinus[x]Alpha” means the value is multiplied by (1 - the alpha value of x).&#xD;&#xA;&#xD;&#xA;For additive blending, you most likely want the following:&#xD;&#xA;&#xD;&#xA;Objective-C:&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments[0].blendingEnabled = YES;&#xD;&#xA;    descriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;&#xD;&#xA;    descriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;&#xD;&#xA;    descriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;&#xD;&#xA;    descriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;&#xD;&#xA;&#xD;&#xA;Swift 5:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].isBlendingEnabled = true&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].rgbBlendOperation = .add&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].alphaBlendOperation = .add&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].sourceAlphaBlendFactor = .one&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].destinationRGBBlendFactor = .one&#xD;&#xA;    descriptor.colorAttachments.colorAttachments[0].destinationAlphaBlendFactor = .one&#xD;&#xA;&#xD;&#xA;There’s a really helpful tool for visualizing the different options [here](https://www.andersriggelsen.dk/glblendfunc.php)—it’s written for OpenGL, but the Metal stuff works the same way.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29237" PostHistoryTypeId="2" PostId="10101" RevisionGUID="166e91b4-6e2c-4157-848e-45627fb03bd8" CreationDate="2020-08-12T10:37:12.353" UserId="13805" Text="I am not entirely sure that this is the right stack exchange, but I couldn't find any other suitable one - please redirect me if necessary.&#xD;&#xA;&#xD;&#xA;There exists mathematically defined colour spaces which help us represent colors with accuracy/efficiency in computers, and different color spaces will capture different ranges of the human visible colour gamut, and because our screens cannot represent colors as raw wavelengths we must use these spaces instead.(correct me if anything said there is wrong)&#xD;&#xA;&#xD;&#xA;How do these relate to how our computer screens actually show colour? From what I understand, our screens only take in N-bit RGB signals for their LCDs, so why do we worry about having all these complex, computationally expensive colourimetric spaces, when we want to do colour processing or storage etc. For example, the sRGB space has a gamma encoding, to represent more data with the same amount of bits... but that gamma cannot actually be displayed on screen. And CIE xyY might be excellent for spectrum based rendering and accurately producing and grading colours - but I understand that we cannot actually see their results, only RGB approximations. Again correct me if any of the above is wrong! I say none of this with much authority, which is mainly why I have to ask this question :) &#xD;&#xA;&#xD;&#xA;We are storing more data in this 8-bit channel format - but is that extra nuance is  lost as soon as we send it off to our raw RGB 8-bit channel screens, and if so, doesn't that loss invalidate (to some extent) all our extra measures to produce ever more accurate and wider gamuts?&#xD;&#xA;&#xD;&#xA;This question focusses on R8G8B8A8 displays, as I imagine HDR would have a different story." ContentLicense="CC BY-SA 4.0" />
  <row Id="29238" PostHistoryTypeId="1" PostId="10101" RevisionGUID="166e91b4-6e2c-4157-848e-45627fb03bd8" CreationDate="2020-08-12T10:37:12.353" UserId="13805" Text="What is the relation between colour spaces and what is actually displayed on our screens?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29239" PostHistoryTypeId="3" PostId="10101" RevisionGUID="166e91b4-6e2c-4157-848e-45627fb03bd8" CreationDate="2020-08-12T10:37:12.353" UserId="13805" Text="|color|color-science|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29240" PostHistoryTypeId="5" PostId="10101" RevisionGUID="a93982ce-6645-4b60-8a99-b2eab9c34bfb" CreationDate="2020-08-12T13:00:51.190" UserId="13805" Comment="added 59 characters in body" Text="I am not entirely sure that this is the right stack exchange, but I couldn't find any other suitable one - please redirect me if necessary.&#xD;&#xA;&#xD;&#xA;There exists mathematically defined colour spaces which help us represent colors with accuracy/efficiency in computers, and different color spaces will capture different ranges of the human visible colour gamut, and because our screens cannot represent colors as raw wavelengths we must use these spaces instead.(correct me if anything said there is wrong)&#xD;&#xA;&#xD;&#xA;How do these relate to how our computer screens actually show colour? From what I understand, our screens only take in N-bit RGB signals for their LCDs, so why do we worry about having all these complex, computationally expensive colourimetric spaces, when we want to do colour processing or storage etc. For example, the sRGB space has a gamma encoding, to represent a different data range with the same amount of bits... but that gamma encoding (for a greater range of dark tones?) cannot actually be displayed on screen. And CIE xyY might be excellent for spectrum based rendering and accurately producing and grading colours - but I understand that we cannot actually see their results, only RGB approximations. Again correct me if any of the above is wrong! I say none of this with much authority, which is mainly why I have to ask this question :) &#xD;&#xA;&#xD;&#xA;We are storing different, nuanced, &quot;perception correct&quot;, data in this 8-bit channel format - but is that extra nuance is  lost as soon as we send it off to our raw RGB 8-bit channel screens, and if so, doesn't that loss invalidate (to some extent) all our extra measures to produce ever more accurate and wider gamuts?&#xD;&#xA;&#xD;&#xA;This question focusses on R8G8B8A8 displays, as I imagine HDR would have a different story." ContentLicense="CC BY-SA 4.0" />
  <row Id="29241" PostHistoryTypeId="2" PostId="10102" RevisionGUID="914a3e2a-2508-489a-b48e-1092ad93334f" CreationDate="2020-08-12T16:17:34.777" UserId="38" Text="Several reasons. Im listing them in random order&#xD;&#xA;&#xD;&#xA;* There are entire industries that do other things than display things on computer screens. If you were to print a booklet, make a package, movie projection or paint a car you would probably be wise to be able to mathematically model it for design, quality control and documentation purposes.&#xD;&#xA;&#xD;&#xA;* Not all screen suck and not all are good. Quite many sreens out there can show wider color ranges than sRGB, or wider but still not entire sRGB. See sRGB is well suited for the designs it was designed for namely crt screens. But LCD screens have had  hard time coming to RGB gamut. So many screens can not even do sRGB and many now exceed it.&#xD;&#xA;&#xD;&#xA;    The RGB color on each screen is different! Unless you have a screen that has been calibrated to sRGB odds are low that it shows sRGB (even if it does bet goes off in few weeks). Now for most people this is ok they arent aware how much off their screen is (i remember calibrating for first time o was quite shocked). &#xD;&#xA;&#xD;&#xA;     Anyway point is that you might be interested is describing the color so that you can do same color, not just same numeric value, on a different screen or display technology.&#xD;&#xA;&#xD;&#xA;* You might be doing color science and communicating measurements to others, or calculate how fast humans can separate the colors.&#xD;&#xA;&#xD;&#xA;* You might be developing a light simulator, i dunno like for movie special effects and or technical design and your interested in the light spectrums.&#xD;&#xA;&#xD;&#xA;* You might need to do distributions of colors visually&#xD;&#xA;&#xD;&#xA;And so on...&#xD;&#xA;&#xD;&#xA;As for gamna encoding your screen is not linear. If your screen were tuned linear it would be crappy indeed. And in anycase good screens have 10 to 12 bits of color to work with so gamma correcting is no problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="29242" PostHistoryTypeId="5" PostId="10102" RevisionGUID="7c87c29c-35c1-4bb6-a4c0-0286b46ff236" CreationDate="2020-08-12T16:23:40.637" UserId="38" Comment="added 270 characters in body" Text="Several reasons. Im listing them in random order&#xD;&#xA;&#xD;&#xA;* There are entire industries that do other things than display things on computer screens. If you were to print a booklet, make a package, movie projection or paint a car you would probably be wise to be able to mathematically model it for design, quality control and documentation purposes.&#xD;&#xA;&#xD;&#xA;* Not all screen suck and not all are good. Quite many sreens out there can show wider color ranges than sRGB, or wider but still not entire sRGB. See sRGB is well suited for the designs it was designed for namely crt screens. But LCD screens have had  hard time coming to RGB gamut. So many screens can not even do sRGB and many now exceed it.&#xD;&#xA;&#xD;&#xA;    The RGB color on each screen is different! Unless you have a screen that has been calibrated to sRGB odds are low that it shows sRGB (even if it does bet goes off in few weeks). Now for most people this is ok they arent aware how much off their screen is (i remember calibrating for first time o was quite shocked). &#xD;&#xA;&#xD;&#xA;     Anyway point is that you might be interested is describing the color so that you can do same color, not just same numeric value, on a different screen or display technology.&#xD;&#xA;&#xD;&#xA;* You might be doing color science and communicating measurements to others, or calculate how fast humans can separate the colors.&#xD;&#xA;&#xD;&#xA;* You might be developing a light simulator, i dunno like for movie special effects and or technical design and your interested in the light spectrums.&#xD;&#xA;&#xD;&#xA;* You might need to do distributions of colors visually&#xD;&#xA;&#xD;&#xA;And so on...&#xD;&#xA;&#xD;&#xA;As for gamna encoding your screen is not linear. If your screen were tuned linear it would be crappy indeed. And in anycase good screens have 10 to 12 bits of color to work with so gamma correcting is no problem.&#xD;&#xA;&#xD;&#xA;As for spectral colors CIE is not dealing with spectrums... Not at all. All 3 component color is dealing with human perception. Spectrums are way different things, the thing you call orange on screen and what your physics book called wavelength are different things." ContentLicense="CC BY-SA 4.0" />
  <row Id="29243" PostHistoryTypeId="2" PostId="10103" RevisionGUID="4861f0dc-9494-4ae5-8e6f-bb05cc7de363" CreationDate="2020-08-12T17:06:09.847" UserId="13824" Text="I'm creating a primarily 2d game (platformer perspective) with 2d background parallax layers. The parallax effect falls out of the fact that I'm positioning a bunch of layers in 3d and using a perspective camera. I'm using Unity which has a left-handed coordinate system with camera pointing down positive Z (positive X rightwards, positive Y is upwards).&#xD;&#xA;&#xD;&#xA;I'd like to occasionally apply an effect that &quot;artificially raises up&quot; the parallax layers in the background. So that the layers further into the background increase their Y position as their Z position increases. Hopefully this diagram makes it clear:&#xD;&#xA;&#xD;&#xA;[![Diagram of parallax layers][1]][1]&#xD;&#xA;&#xD;&#xA;How would I construct a 4x4 matrix that I could multiply by my usual perspective matrix in order to produce this effect? (Is it calling shearing?) I thiiink (but I'm not 100% sure without seeing it) that I want the Y change of each layer in screen space to be proportional to `1/z`.&#xD;&#xA;&#xD;&#xA;(Note: I realise I could fake this by moving the background layers directly but I'd like to avoid that if possible!)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xvYfH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29244" PostHistoryTypeId="1" PostId="10103" RevisionGUID="4861f0dc-9494-4ae5-8e6f-bb05cc7de363" CreationDate="2020-08-12T17:06:09.847" UserId="13824" Text="Shear(?) matrix projection along Z (depth) axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="29245" PostHistoryTypeId="3" PostId="10103" RevisionGUID="4861f0dc-9494-4ae5-8e6f-bb05cc7de363" CreationDate="2020-08-12T17:06:09.847" UserId="13824" Text="|3d|perspective|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29247" PostHistoryTypeId="2" PostId="10104" RevisionGUID="5fde05a5-cf0d-401b-a010-e5100edb20d8" CreationDate="2020-08-13T03:06:35.360" UserId="7462" Text="I am starting to learn about the [laplacian operator][1] $\Delta = \nabla \cdot \nabla\phi(p)$&#xD;&#xA;&#xD;&#xA;Which can be described as the divergence of the gradient of a scalar function $\phi$. This is equivalent to the sum of the second order partial derivatives of the function.&#xD;&#xA;&#xD;&#xA;However, it seems its [graph equivalent][2] is just the sum of the differences of adjacent vertices. Am I reading that right? In my head that should be equivalent to the first order partial derivatives, not the second order ones.&#xD;&#xA;&#xD;&#xA;(I didn't know whether to ask here or in math, I decided here is more relevant because this is in the context of geometry processing)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Laplace_operator&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Discrete_Laplace_operator" ContentLicense="CC BY-SA 4.0" />
  <row Id="29248" PostHistoryTypeId="1" PostId="10104" RevisionGUID="5fde05a5-cf0d-401b-a010-e5100edb20d8" CreationDate="2020-08-13T03:06:35.360" UserId="7462" Text="Is the laplacian operator for meshes just the sum of the differences of neighbouring vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29249" PostHistoryTypeId="3" PostId="10104" RevisionGUID="5fde05a5-cf0d-401b-a010-e5100edb20d8" CreationDate="2020-08-13T03:06:35.360" UserId="7462" Text="|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29250" PostHistoryTypeId="16" PostId="10102" RevisionGUID="eab1204e-4cf5-4c69-b8c6-f48f2f195fb3" CreationDate="2020-08-13T05:47:46.650" UserId="38" />
  <row Id="29251" PostHistoryTypeId="5" PostId="10102" RevisionGUID="eab1204e-4cf5-4c69-b8c6-f48f2f195fb3" CreationDate="2020-08-13T05:47:46.650" UserId="38" Comment="added 24 characters in body" Text="Several reasons. Im listing them in random order&#xD;&#xA;&#xD;&#xA;* There are entire industries that do other things than display things on computer screens. If you were to print a booklet, make a package, movie projection or paint a car you would probably be wise to be able to mathematically model it for design, quality control and documentation purposes.&#xD;&#xA;&#xD;&#xA;* Not all screen suck and not all are good. Quite many screens out there can show wider color ranges than sRGB, or wider but still not entire sRGB. See sRGB is well suited for the designs it was designed for namely crt screens. LCD screens have had  hard time coming to sRGB gamut, but we are getting there. So many screens can not even do sRGB and many now exceed it.&#xD;&#xA;&#xD;&#xA;    The RGB color on each screen is different! Unless you have a screen that has been calibrated to sRGB odds are low that it shows sRGB (even if it does bet goes off in few weeks). Now for most people this is ok they arent aware how much off their screen is (i remember calibrating for first time o was quite shocked). &#xD;&#xA;&#xD;&#xA;     Anyway point is that you might be interested is describing the color so that you can do same color, not just same numeric value, on a different screen or display technology.&#xD;&#xA;&#xD;&#xA;* You might be doing color science and communicating measurements to others, or calculate how fast humans can separate the colors.&#xD;&#xA;&#xD;&#xA;* You might be developing a light simulator, i dunno like for movie special effects and or technical design and your interested in the light spectrums.&#xD;&#xA;&#xD;&#xA;* You might need to do distributions of colors visually&#xD;&#xA;&#xD;&#xA;And so on...&#xD;&#xA;&#xD;&#xA;As for gamna encoding your screen is not linear. If your screen were tuned linear it would be crappy indeed. And in anycase good screens have 10 to 12 bits of color to work with so gamma correcting is no problem.&#xD;&#xA;&#xD;&#xA;As for spectral colors CIE is not dealing with spectrums... Not at all. All 3 component color is dealing with human perception. Spectrums are way different things, the thing you call orange on screen and what your physics book called wavelength are different things." ContentLicense="CC BY-SA 4.0" />
  <row Id="29252" PostHistoryTypeId="2" PostId="10105" RevisionGUID="3af89ae1-9cb6-471a-b774-cc04fd1d2b78" CreationDate="2020-08-13T07:59:45.873" UserId="7647" Text="You can see why the sum of differences is giving a second derivative if you look at the derivative of a one-dimensional function $f$. The derivative of $f$ at $x_0$ is&#xD;&#xA;$$ \frac{df}{dx}(x_0) \approx \frac{f(x_0 + dx) - f(x_0)}{dx} $$&#xD;&#xA;The second derivative is then&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;\frac{d^2f}{dx^2}(x_0) &amp;\approx&amp; &#xD;&#xA;  \frac{df/dx(x_0) - df/dx(x_0-dx)}{dx} \\&#xD;&#xA;  &amp;\approx&amp; \frac{\left(f(x_0+dx) - f(x_0)\right) -&#xD;&#xA;                  \left(f(x_0) - f(x_0-dx)\right)}{dx^2} \\&#xD;&#xA;  &amp;=&amp; \frac{\left(f(x_0+dx) - f(x_0)\right) +&#xD;&#xA;                  \left(f(x_0-dx) - f(x_0)\right)}{dx^2},&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;i.e. the sum of the local differences, scaled by a distance factor $dx^2$. In a _graph_ Laplacian, you don't have any distances, just graph connections, so it's just the sum of the local differences.&#xD;&#xA;&#xD;&#xA;When working on meshes, though, we typically want to take the geometry of the mesh into account. There are many ways to do this, but the most popular seems to be the _cotangent Laplacian_, where the local difference for each edge is weighted by the sum of the cotangents of the angles opposite that edge." ContentLicense="CC BY-SA 4.0" />
  <row Id="29253" PostHistoryTypeId="2" PostId="10106" RevisionGUID="99688bdd-e12c-4c2e-96c8-89bcfb445612" CreationDate="2020-08-13T09:40:31.820" UserId="10129" Text="@Christian Pagot&#xD;&#xA;I think it is worth mentioning, that DXR is using Bottom Level Acceleration Structures (BLAS) as well as Top Level Acceleration Structures (TLAS):&#xD;&#xA;[![**Figure 3:** Overview of raytracing building blocks][1]][1]&#xD;&#xA;**Figure 3:** Overview of raytracing building blocks&#xD;&#xA;&#xD;&#xA;[![**Figure 4:** Acceleration Structure][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 4:** Overview of raytracing building blocks&#xD;&#xA;&#xD;&#xA;https://developer.nvidia.com/rtx/raytracing/dxr/DX12-Raytracing-tutorial-Part-1 - please refer for more informations. Image 3 and 4 are copied from chapter 7 and 8.&#xD;&#xA;&#xD;&#xA;You may also find some interesting bits in Microsoft DXR documentation - https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html I really hoped that I could find some more about rebuilding TLAS/BLAS. If I remember correctly there are two ways - if structures differ only slightly, you can do partial rebuild. When you get to the point, where structures differ too much from actual geometry, you have to do full rebuild. I don't have a source stating big O complexity, I am sorry.&#xD;&#xA;&#xD;&#xA;Due to some disadvantages of using BVH e.g.lack of front-to-back traversal, some methods were implemented to deal with that:&#xD;&#xA;&#xD;&#xA;&gt; [...]However, ordered traversal in a structure based on object partitioning, such as a BVH, is not achieved so easily. While an implementation based on a traversal priority queue (rather than a traversal stack) enables front-to-back traversal of a BVH [7], most publicly available, widely used production ray tracing APIs do not provide ordered BVH traversal variants.&#xD;&#xA;&#xD;&#xA;From http://www.realtimerendering.com/raytracinggems/unofficial_RayTracingGems_v1.7.pdf#page=147 - Chapter 9 *Multi-Hit Ray Tracing in DXR* by Christiaan Gribble and SURVICE Engineering&#xD;&#xA;&#xD;&#xA;I generally recommend this book, even though I've just read 1/3 of it. It contains a lot of state of the art articles about raytracing.&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;@lightxbulb &#xD;&#xA;I hope that I've managed to support part of Christian's Pagot statements with sources. I'm really disappointed that I couldn't find complexity of rebuilding BHV in DXR. Maybe somebody will have a link to that.&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;@Nash Gold&#xD;&#xA;https://www.amazon.com/Real-Time-Rendering-Tomas-Akenine-Mo%C2%A8ller-ebook/dp/B007COYODQ/ (I haven't read 4th edition) - you can find Collision Detection algorithms in chapter 17. Acceleration Algorithms in chapter 14. Also throughout the book, there is a lot of talking about intersection algorithms and even about usage of triangle fans, strips, meshes and pros, cons of all of them.&#xD;&#xA;&#xD;&#xA;I enjoyed this book at the beginning. But if you're seasoned graphics programmer, you know most of its content through other sources. Therefore I would only refer to mentioned chapters.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1kZZB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CJj8g.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29257" PostHistoryTypeId="2" PostId="10108" RevisionGUID="4f6436bd-40d5-4e4f-a03b-a51d2c6671f1" CreationDate="2020-08-13T13:17:07.570" UserId="10129" Text="I am working on ray/path-tracer using DXR and I'm starting with simple AO. In first pass, I am storing normal value and RayTCurrent():&#xD;&#xA;&#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHit(inout RayPayload payload, in Attributes attrib)&#xD;&#xA;    {&#xD;&#xA;    	// Calculate triangle normal code - unrelated, so I deleted it&#xD;&#xA;    	&#xD;&#xA;        // Store RayTCurrent value in payload&#xD;&#xA;    	payload.normalWithDepth = float4(triangleNormal, RayTCurrent());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGen()&#xD;&#xA;    {  &#xD;&#xA;    	RayDesc ray = { origin, 1e-4f, rayDir, 1e+38f};&#xD;&#xA;    	RayPayload payload;&#xD;&#xA;    	payload.worldPos = float4(0, 0, 0, 0);&#xD;&#xA;    	payload.normalWithDepth = float4(0, 0, 0, 0);&#xD;&#xA;    	&#xD;&#xA;    	TraceRay(SceneBVH, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload);&#xD;&#xA;&#xD;&#xA;        // Simply storing returned payload in RWTexture&lt;float4&gt;&#xD;&#xA;    	RTOutputNormal[DispatchRaysIndex().xy] = payload.normalWithDepth;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In AO pass I am using this information to calculate world space position of given pixel (i.e. transform from ndc to world space coordinate):&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGenAO()&#xD;&#xA;    {&#xD;&#xA;    	float2 pixelCenter = (float2) LaunchIndex / (float2) LaunchDimensions + float2(0.5f / (float) LaunchDimensions.x, 0.5f / (float) LaunchDimensions.y);&#xD;&#xA;    	float4 normalAndDepth = NormalTextureInput.SampleLevel(g_sampler, pixelCenter, 0);&#xD;&#xA;&#xD;&#xA;        // normalAndDepth.w is clamped to 1.0f, therefore information about distance to hit point is lost&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;You can see, that above code results in correct AO results (1 spp noise with no filtering or accumulation) for happy buddha model. However, any AO can be seen when camera is extremely close (max 1 unit from object). In other cases I am getting completely white, flat model. The problem is that texture is clamping value in first pass to 1, so I am losing information about real distance between ray origin and ray hit.&#xD;&#xA;&#xD;&#xA;Here is a hlsl code for AO generation. I don't think that any problem exists in there, apart from not enough information from texture. **Therefore, below code can be ignored:**&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGen()&#xD;&#xA;    {&#xD;&#xA;    	uint2 LaunchIndex = DispatchRaysIndex().xy;&#xD;&#xA;    	uint2 LaunchDimensions = DispatchRaysDimensions().xy;&#xD;&#xA;    &#xD;&#xA;    	// Figure out pixel world space position (using length of a primary ray found in previous pass)&#xD;&#xA;    	float3 primaryRayOrigin, primaryRayDirection; &#xD;&#xA;    	GenerateCameraRay(LaunchIndex, primaryRayOrigin, primaryRayDirection);&#xD;&#xA;    	&#xD;&#xA;    	float2 pixelCenter = (float2) LaunchIndex / (float2) LaunchDimensions + float2(0.5f / (float) LaunchDimensions.x, 0.5f / (float) LaunchDimensions.y);&#xD;&#xA;    	float4 normalAndDepth = NormalTextureInput.SampleLevel(g_sampler, pixelCenter, 0);&#xD;&#xA;    	float3 pixelWorldSpacePosition = primaryRayOrigin + (primaryRayDirection * normalAndDepth.w);&#xD;&#xA;    &#xD;&#xA;    	//RTOutput[LaunchIndex] = float4(normalAndDepth.w, normalAndDepth.w, normalAndDepth.w, 1.0f);&#xD;&#xA;    	//return;&#xD;&#xA;    	&#xD;&#xA;    	if (normalAndDepth.w == 0.0f)&#xD;&#xA;    	{&#xD;&#xA;            // Terminate if primary ray didn't hit anything&#xD;&#xA;    		RTOutput[LaunchIndex] = float4(0.0f, 0.2f, 0.4f, 1.0f);&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	uint seed = initRand(LaunchIndex.x + LaunchIndex.y * LaunchDimensions.x, g_cubeCB.frameCount);&#xD;&#xA;    	float3 worldDir = getCosHemisphereSample(seed.x, normalAndDepth.xyz);&#xD;&#xA;    	&#xD;&#xA;    	RayDesc aoRay;&#xD;&#xA;    	RayPayload payload;&#xD;&#xA;    	float3 aoSampleDirection = worldDir;&#xD;&#xA;    	float ao = 0.0f;&#xD;&#xA;    &#xD;&#xA;    	aoRay.Origin = pixelWorldSpacePosition;&#xD;&#xA;    	aoRay.TMin = g_aoCB.minT;&#xD;&#xA;    	aoRay.TMax = g_aoCB.aoRadius; //&lt; Set max ray length to AO radius for early termination&#xD;&#xA;    	aoRay.Direction = aoSampleDirection;&#xD;&#xA;    	&#xD;&#xA;    	payload.T = g_aoCB.aoRadius; //&lt; Set T to &quot;maximum&quot;, to produce no occlusion in case ray doesn't hit anything (miss shader won't modify this value)&#xD;&#xA;    &#xD;&#xA;    	// Trace the ray&#xD;&#xA;    	TraceRay(SceneBVH, RAY_FLAG_NONE, 0xFF, 0, 1, 0, aoRay, payload);&#xD;&#xA;    	ao = payload.T / g_aoCB.aoRadius;&#xD;&#xA;    	&#xD;&#xA;    	RTOutput[LaunchIndex.xy] = float4(ao, ao, ao, 1.0f); //&lt; Replace all cached AO with current result&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;        [shader(&quot;miss&quot;)]&#xD;&#xA;        void Miss(inout RayPayload payload : SV_RayPayload)&#xD;&#xA;        {&#xD;&#xA;        	// Empty&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        [shader(&quot;closesthit&quot;)]&#xD;&#xA;        void ClosestHit(inout RayPayload payload, in Attributes attrib)&#xD;&#xA;        {&#xD;&#xA;        	payload.T = RayTCurrent();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hIh5R.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29258" PostHistoryTypeId="1" PostId="10108" RevisionGUID="4f6436bd-40d5-4e4f-a03b-a51d2c6671f1" CreationDate="2020-08-13T13:17:07.570" UserId="10129" Text="Texture value clamped to 1" ContentLicense="CC BY-SA 4.0" />
  <row Id="29259" PostHistoryTypeId="3" PostId="10108" RevisionGUID="4f6436bd-40d5-4e4f-a03b-a51d2c6671f1" CreationDate="2020-08-13T13:17:07.570" UserId="10129" Text="|raytracing|texture|hlsl|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29270" PostHistoryTypeId="2" PostId="10111" RevisionGUID="4765c923-3978-4362-9e0f-1f0a3aae8721" CreationDate="2020-08-15T00:47:18.283" UserId="7952" Text="The real story here is actually very interesting and can be enlightening. So I offer this alternate answer to help better answer this question. Also, my answer below is a very specific to this question. The full story is too big to put here, but worth the trouble of learning.&#xD;&#xA;&#xD;&#xA;In the 1930-50's researchers started looking into the human visual system. These studies looked into the range and brightness of colors that humans can see. The results were surprising. Our color range is somewhat limited and that color range is effected by how bright the room is. While we can see 6 magnitudes of order with respect to brightness, the number of colors we can see at each of these 1 million brightness levels varies. In a moderately lit room we can see a heck of a lot more colors then we can in a very bright room.&#xD;&#xA;&#xD;&#xA;When the television was first being created it had to account for these differences. But a television outputs color at a fairly narrow range of brightness (especially the early television) which is about 1 to 100 nits. (with humans being able to see between 1 and 1 million nits) This is a fairly low lighting level and we see more colors (including black and white) in a dimly lit room. So the television needed to output more dim colors then bright colors at the same brightness and the logarithmic color curve was born.&#xD;&#xA;&#xD;&#xA;The sRGB color space is a direct result. It is our eye with its tricky ability to see lots of colors in dim lighting that forces this curve on the hardware.&#xD;&#xA;&#xD;&#xA;But, the technology behind monitors continues marching forward and today we have monitors that can produce upwards of 1,000 nits of brightness, not to mention that brightness can be varied much more broadly. Also, modern monitors can produces a wider range of colors then early monitors. Further, movie makers and game developers can not easily &quot;think&quot; in logarithmic space we mere humans tend to think much better in linear space. So there really needs to be a way to translate from logarithmic space to linear space so media creators can more easily reason and about and work with the colors they produce. Also, now that we have monitors that can produce colors at different levels it sure would be nice to be able to convert movies and games into the &quot;native&quot; space that any given monitor actually displays.&#xD;&#xA;&#xD;&#xA;In fact, it would be much better to &quot;ship&quot; all our media with the best possible colors and then convert it to whatever the display that media is being shown on is capable of. &#xD;&#xA;&#xD;&#xA;And that is exactly what a lot of modern media creators do. So the relationship between the color space and what is shown on your monitor is actually a fairly complex dance between what is shipped in the media, the capabilities of your video hardware and the capabilities of the monitor it is being shown on. An 8 bit color encoding may end up going through multiple translations before it makes it to your 8 bit monitor. While the same media being shown on a 10 bit monitor could go through a very different set of translations.&#xD;&#xA;&#xD;&#xA;With monitors showing colors in 8, 10, or 12 bits per color. Many can now easily represent most of the standard media color spaces and choosing one to work or visualize in is more a matter of personal taste or need then physical necessity.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29271" PostHistoryTypeId="2" PostId="10112" RevisionGUID="a0ac4384-c1b2-4696-8f0c-b1c2bbe07614" CreationDate="2020-08-15T04:57:16.493" UserDisplayName="user11739" Text="In HLSL, we have cbuffers and tbuffers.&#xD;&#xA;&#xD;&#xA;MSDN's description for tbuffers is the following:&#xD;&#xA;&#xD;&#xA;&gt; A texture buffer is a specialized buffer resource that is accessed&#xD;&#xA;&gt; like a texture. Texture access (as compared with buffer access) can&#xD;&#xA;&gt; have better performance for arbitrarily indexed data. You can bind up&#xD;&#xA;&gt; to 128 texture buffers per pipeline stage.&#xD;&#xA;&#xD;&#xA;what is the difference to cbuffers? in cbuffers i can access the data arbitrarily, too.&#xD;&#xA;When should i use a tbuffer and when should i use a cbuffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29272" PostHistoryTypeId="1" PostId="10112" RevisionGUID="a0ac4384-c1b2-4696-8f0c-b1c2bbe07614" CreationDate="2020-08-15T04:57:16.493" UserDisplayName="user11739" Text="What is a tbuffer and what is their use case?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29273" PostHistoryTypeId="3" PostId="10112" RevisionGUID="a0ac4384-c1b2-4696-8f0c-b1c2bbe07614" CreationDate="2020-08-15T04:57:16.493" UserDisplayName="user11739" Text="|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29277" PostHistoryTypeId="2" PostId="10114" RevisionGUID="03afb8df-3357-4bac-bcd8-31974fca5303" CreationDate="2020-08-15T15:07:36.587" UserId="13805" Text="Yet another question about colour space...&#xD;&#xA;&#xD;&#xA;In my research on CIE XYZ system, I found that it is based on the CIE RGB colour matching experiments, and that because the RGB system needed occasional negative values, XYZ was developed in order to have an entirely non-negative system. From this I infer that the x(), y() and z() colour matching functions are just transformations of the original r(), g() and b() functions, using exactly the same data. I also found online that the XYZ and RGB systems were completely interchangeable, and XYZ is just preferred for the lack of any negative components. &#xD;&#xA;&#xD;&#xA;If that is incorrect please correct me!&#xD;&#xA;&#xD;&#xA;However, if they are interchangeable and based off of the same data, why is it that Wikipedia's comparison of the two spaces shows a marked difference? Is the missing curvy section outside of that inner triangle just the areas where the CIE RGB system would have to be negative?&#xD;&#xA;&#xD;&#xA;[![Comparison of the two gamuts][1]][1]&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/qwqdc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29278" PostHistoryTypeId="1" PostId="10114" RevisionGUID="03afb8df-3357-4bac-bcd8-31974fca5303" CreationDate="2020-08-15T15:07:36.587" UserId="13805" Text="Why is there a difference between the CIE XYZ colour gamut vs CIE RGB?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29279" PostHistoryTypeId="3" PostId="10114" RevisionGUID="03afb8df-3357-4bac-bcd8-31974fca5303" CreationDate="2020-08-15T15:07:36.587" UserId="13805" Text="|color|color-science|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29285" PostHistoryTypeId="2" PostId="10116" RevisionGUID="2eb0b803-ae36-4010-967d-3a297b3a3f67" CreationDate="2020-08-16T09:02:24.307" UserId="10129" Text="**Keep in mind, that I'm still learning and I have no professional capacity in terms of graphics programming. So you might want to continue research with provided resources.**&#xD;&#xA;&#xD;&#xA;&gt; t*#*: A register for a texture buffer (**tbuffer**).[1]&#xD;&#xA;&#xD;&#xA;To start with - texture buffer is what you can see in hlsl code as: *Texture2D texName : register(t0)* or as *Texture2D&lt;float4&gt; texName : register(t0, space0)*. If I remember correctly, spaces were added in DirectX 12, maybe they're available in DX 11.3, but that's different discussion. Back to my point - you're using texture buffer every time you're binding texture to your shader and sending texture data to GPU. Therefore, using **PSSetShaderResources** [2] will be most trivial usage of texture buffer, espacially in DX11 code. You can use constant buffer to store pixel data and then send it to GPU, but why should you bother, when Texture2D or TextureCube and other data structures are already in hlsl?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**cbuffer (DX11/DX12) forces you to pack data in 32-bit groups** [3]. You might have experienced it, if not, I encourage you to experiment a little. In the past I didn't follow this rules, having that packed like this, which causes problem with incorrect data in your shader:&#xD;&#xA;&#xD;&#xA;    cbuffer buf : register(b0)&#xD;&#xA;    {&#xD;&#xA;        float3 a;&#xD;&#xA;        // Here is where problem occurs&#xD;&#xA;        float2 b;&#xD;&#xA;        float3 c;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Correct packing rule would be:&#xD;&#xA;&#xD;&#xA;    cbuffer buf : register(b0)&#xD;&#xA;    {&#xD;&#xA;        float3 a;&#xD;&#xA;        float padding_a;&#xD;&#xA;        float2 b;&#xD;&#xA;        float2 padding_b;&#xD;&#xA;        float3 c;&#xD;&#xA;        float padding_c;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Of course, I am using worst possible example here, because correct data is 8 bytes and you're sending additional 4 bytes (whole hlsl vector) as padding. But you get an idea. It might be easier to sort data with bigger buffers, especially if you're using uber buffer in your hobby project.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**Additional problem in DX12 is that cbuffer has to be 256-byte aligned** [4], unless you're using root constants, which allows you to send not aligned data, but they have other limitation. I was only talking about them with other developer, so I don't really have sources except [5]. There was something about size of buffer and that root constants are working magic in AMD drivers, but it isn't something that I really need right now, as I am focusing on learning, not extreme optimization of code.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Shader Model 5 allows you to use new data structures [6]. I wasn't working with compute shaders, but for DXR hlsl code, I am using RTTexture2D as UAV. However, I am passing indices, vertices and RaytracingAccelerationStructure as texture buffers. I didn't see anyone to use those three as cbuffer. I guess it's possible, at least for indices and vertices, but I don't see a reason to do so:&#xD;&#xA;&#xD;&#xA;    RaytracingAccelerationStructure SceneBVH : register(t0);&#xD;&#xA;    ByteAddressBuffer indices : register(t1);&#xD;&#xA;    StructuredBuffer&lt;Vertex&gt; vertices : register(t2);&#xD;&#xA;&#xD;&#xA;Indices are simply 16 or 32 bit index for accessing vertex data. I don't see a reason to hassle with creating cbuffer for single array and having to deal with padding and providing correct size of buffer. However, I am really interested if there is a reason to do it sometimes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Same with vertices - in rasterization, you're using structure which don't have to follow packing rules e.g.:&#xD;&#xA;&#xD;&#xA;    struct VertexInputType&#xD;&#xA;    {&#xD;&#xA;    	float3 position : POSITION;&#xD;&#xA;    	float3 normal : NORMAL;&#xD;&#xA;    	float3 tangent : TANGENT;&#xD;&#xA;    	float3 binormal : BINORMAL;&#xD;&#xA;    	float2 uv : TEXCOORD0;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;So for raytracing, I am just using struct with same data and I'm accesing it through structured buffer, regsitered as texture buffer:&#xD;&#xA;&#xD;&#xA;    struct Vertex&#xD;&#xA;    {&#xD;&#xA;    	float3 position;&#xD;&#xA;    	float3 normal;&#xD;&#xA;    	float3 tangent;&#xD;&#xA;    	float3 binormal;&#xD;&#xA;    	float2 uv;&#xD;&#xA;    };&#xD;&#xA;    StructuredBuffer&lt;Vertex&gt; vertices : register(t2);&#xD;&#xA;&#xD;&#xA;Regarding *RaytracingAccelerationStructure* - it's built-in hlsl type, no need to hassle with creating cbuffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;I'm sorry for speaking from DX12, DXR perspective, but that's something that I'm currently working on, so it's a simplest way to provide examples from that area.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[1] https://docs.microsoft.com/en-us/windows/win32/direct3dgetstarted/work-with-shaders-and-shader-resources#read-from-the-constant-buffers&#xD;&#xA;&#xD;&#xA;[2] https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-pssetshaderresources&#xD;&#xA;&#xD;&#xA;[3] https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules&#xD;&#xA;&#xD;&#xA;[4] https://social.msdn.microsoft.com/Forums/sqlserver/en-US/78dec419-6827-40fc-a048-01c3cccb92ef/directx-10-11-and-12-constant-buffer-alignment?forum=vsga&#xD;&#xA;&#xD;&#xA;[5] https://docs.microsoft.com/en-us/windows/win32/direct3d12/using-constants-directly-in-the-root-signature&#xD;&#xA;&#xD;&#xA;[6] https://docs.microsoft.com/en-us/windows/win32/direct3d11/direct3d-11-advanced-stages-cs-resources&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29286" PostHistoryTypeId="2" PostId="10117" RevisionGUID="061b1c5a-649a-435a-8fe2-fec2cc6bfaf0" CreationDate="2020-08-16T09:46:09.413" UserId="10129" Text="I am not aware of what LRV is and what is a usage of it. However, I can recommend using luma instead of simply averaging RGB values with equal weight:&#xD;&#xA;&#xD;&#xA; - https://en.wikipedia.org/wiki/Luma_(video)&#xD;&#xA; - https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA; - Example of using luma - http://blog.simonrodriguez.fr/articles/30-07-2016_implementing_fxaa.html&#xD;&#xA;&#xD;&#xA;Human eyes are more sensitive to green colors [1], that's why 16 bit (aka high color [2]) palettes, might prefer to use R5G6B5 format.&#xD;&#xA;&#xD;&#xA;[1] https://en.wikipedia.org/wiki/Color_vision &#xD;&#xA;&#xD;&#xA;[2] https://en.wikipedia.org/wiki/High_color&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29288" PostHistoryTypeId="2" PostId="10118" RevisionGUID="04c2258a-18be-4e91-be0a-4da3a3e3bda6" CreationDate="2020-08-16T09:57:33.377" UserId="10928" Text="When we clip in homogeneous clip space, we have to generate a new vertex located at the intersection between the edge and the clip plane. We thus have to interpolate the $(x , y, z , w)$ position of both vertices to generate the new vertex position. It seems all well and good, but what should I do when the generated vertex after interpolation has a w of 0?&#xD;&#xA;&#xD;&#xA;It doesn’t work because the a-divide makes the point go to infinity (division by zero).&#xD;&#xA;&#xD;&#xA;So should I ensure that I never generate vertices with a w of 0 (how?)? Or should I just deal with the null w (how?)?&#xD;&#xA;&#xD;&#xA;You might say that this situation never happen, but it actually does happen, especially when the z of the vertices are set to their w, for skyboxes for example. In this case, when we clip against the near plane (z = 0 in clip space) and interpolate the position, we will end up with a z of 0 but also a w of 0..." ContentLicense="CC BY-SA 4.0" />
  <row Id="29289" PostHistoryTypeId="1" PostId="10118" RevisionGUID="04c2258a-18be-4e91-be0a-4da3a3e3bda6" CreationDate="2020-08-16T09:57:33.377" UserId="10928" Text="How to interpolate vertices when clipping?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29290" PostHistoryTypeId="3" PostId="10118" RevisionGUID="04c2258a-18be-4e91-be0a-4da3a3e3bda6" CreationDate="2020-08-16T09:57:33.377" UserId="10928" Text="|interpolation|rasterizer|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29291" PostHistoryTypeId="5" PostId="10118" RevisionGUID="a4da5c6b-cd82-4420-b917-9f54f8846c3c" CreationDate="2020-08-16T10:06:23.110" UserId="10928" Comment="edited body" Text="When we clip in homogeneous clip space, we have to generate a new vertex located at the intersection between the edge and the clip plane. We thus have to interpolate the $(x , y, z , w)$ position of both vertices to generate the new vertex position. It seems all well and good, but what should I do when the generated vertex after interpolation has a w of 0?&#xD;&#xA;&#xD;&#xA;It doesn’t work because the w-divide makes the point go to infinity (division by zero).&#xD;&#xA;&#xD;&#xA;So should I ensure that I never generate vertices with a w of 0 (how?)? Or should I just deal with the null w (how?)?&#xD;&#xA;&#xD;&#xA;You might say that this situation never happen, but it actually does happen, especially when the z of the vertices are set to their w, for skyboxes for example. In this case, when we clip against the near plane (z = 0 in clip space) and interpolate the position, we will end up with a z of 0 but also a w of 0..." ContentLicense="CC BY-SA 4.0" />
  <row Id="29292" PostHistoryTypeId="2" PostId="10119" RevisionGUID="e5a1bba0-3885-4c4b-90c9-3f910d95ec61" CreationDate="2020-08-16T17:17:05.190" UserId="13842" Text="I'm using 2d signed distance fields in my current project for drawing shapes (example: https://www.shadertoy.com/view/4llXD7) and I want to add drop shadows to them. At first I thought I could exploit the sdfs distance property to achieve good enough looking drop shadows, but I found that in many cases this left undesirable results in the interior of the shapes where there is often a darker 'x' in center. &#xD;&#xA;&#xD;&#xA;I found this shadertoy https://www.shadertoy.com/view/tdSGDc which is produces exactly what I am looking for in terms of quality and performance, but I can't seem to figure out how I would combine this 1d box blur effect with arbitrary sdf shapes to achieve a nice looking drop shadow. Is there a way I can combine these two techniques to get great looking shadows?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29293" PostHistoryTypeId="1" PostId="10119" RevisionGUID="e5a1bba0-3885-4c4b-90c9-3f910d95ec61" CreationDate="2020-08-16T17:17:05.190" UserId="13842" Text="Combine box shadow with a signed distance field" ContentLicense="CC BY-SA 4.0" />
  <row Id="29294" PostHistoryTypeId="3" PostId="10119" RevisionGUID="e5a1bba0-3885-4c4b-90c9-3f910d95ec61" CreationDate="2020-08-16T17:17:05.190" UserId="13842" Text="|glsl|2d|unity|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29295" PostHistoryTypeId="5" PostId="10100" RevisionGUID="bdf5b905-1c12-46b6-a05a-3edb623f84be" CreationDate="2020-08-16T23:15:17.343" UserDisplayName="user5681" Comment="added 551 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][1] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;I think that main factor that turns the BVH into a popular acceleration structure in the context of GPU ray tracing is not its traversal speed, but the fact that GPUs target the rendering of dynamic geometry most of the time. In this case, BVHs are the preferable data structure because they can be quickly adjusted through local operations (refitting). Additionaly, since they do not imply complex split operations on the geometry, if you choose an efficient heuristic for building a BVH, we can create BVHs from scratch in almost no time on the GPU.&#xD;&#xA;&#xD;&#xA;This answer is full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. &#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/1189762.1206075" ContentLicense="CC BY-SA 4.0" />
  <row Id="29296" PostHistoryTypeId="5" PostId="10100" RevisionGUID="f1e3a282-8a01-46c1-a512-ac0fc0eaaeaf" CreationDate="2020-08-16T23:38:05.787" UserDisplayName="user5681" Comment="added 601 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][1] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;Actually there are several reasons that make the BVHs the preferred acceleration data structure for interactive ray tracing o GPUs. According to [Wodniok and Goesele][2], the main factors that have turned the BVH into a popular acceleration structure in the context of GPU ray tracing are its &quot;*memory footprint (...) efficient empty space cut-off, fast construction, and simple update procedure (...) while (...) offering similar (...) performance as kD-Trees*&quot;. Regarding fast BVH reconstruction, it may be interesting to take a look at the LBVH, by [Lauterbach *et. al.*][3], and the HLBVH, by [Pantaleoni&#xD;&#xA;and Luebke][4], that are capable to rebuild BVHs iteractively.&#xD;&#xA;&#xD;&#xA;This answer is still full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. I am still editing this answer, adding the proper references as time permits.&#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/1189762.1206075&#xD;&#xA;  [2]: https://www.sciencedirect.com/science/article/pii/S0097849316301376?casa_token=D0jTp_c1HngAAAAA:YCD31gt1rp4zR8wzE20vTxIEXAJR83pOZh0Bp_saqZChzCHOfgKwu0W7N0jT9dJGCvKjAVTdsQ&#xD;&#xA;  [3]: https://onlinelibrary.wiley.com/doi/full/10.1111/j.1467-8659.2009.01377.x?casa_token=s3kaFgXZt38AAAAA%3Ar1tdA-tx8aAclVsQeLTh8oUR5XDgEgI-twjAhezqDUWmBm8W2AaL8OzD0KU9s0EfZN5DHZFWHB8gZXM&#xD;&#xA;  [4]: https://research.nvidia.com/sites/default/files/pubs/2010-06_HLBVH-Hierarchical-LBVH/HLBVH-final.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29297" PostHistoryTypeId="5" PostId="10114" RevisionGUID="715a190d-d4c1-4809-a18a-c337498a1323" CreationDate="2020-08-17T12:59:42.647" UserId="13805" Comment="added 72 characters in body" Text="Yet another question about colour space...&#xD;&#xA;&#xD;&#xA;In my research on CIE XYZ system, I found that it is based on the CIE RGB colour matching experiments, and that because the RGB system needed occasional negative values, XYZ was developed in order to have an entirely non-negative system. From this I infer that the x(), y() and z() colour matching functions are just transformations of the original r(), g() and b() functions, using exactly the same data. I also found online that the XYZ and RGB systems were completely interchangeable, and XYZ is just preferred for the lack of any negative components. &#xD;&#xA;&#xD;&#xA;If that is incorrect please correct me!&#xD;&#xA;&#xD;&#xA;However, if they are interchangeable and based off of the same data, why is it that Wikipedia's comparison of the two spaces shows a marked difference? Is the missing curvy section outside of that inner triangle just the areas where the CIE RGB system would have to be negative?&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_RGB_color_space&#xD;&#xA;[![Comparison of the two gamuts][1]][1]&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/qwqdc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29298" PostHistoryTypeId="50" PostId="9645" RevisionGUID="4dfb07c9-746a-4bae-9947-68be5b76ff38" CreationDate="2020-08-17T16:04:30.510" UserId="-1" />
  <row Id="29299" PostHistoryTypeId="2" PostId="10120" RevisionGUID="50ea8732-b560-4f55-b0ae-dad37f4c8f7b" CreationDate="2020-08-17T19:49:32.320" UserId="13639" Text="I think all you have to do is to transform the back layers in the Y axis.&#xD;&#xA;FYI, a shear means to bend an object, see image bellow:&#xD;&#xA;&#xD;&#xA;[![sheer][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3LRVj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29300" PostHistoryTypeId="2" PostId="10121" RevisionGUID="21df6da9-d625-440b-835d-f04346ca8ca7" CreationDate="2020-08-17T22:38:29.650" UserId="7462" Text="The heat method is a very interesting paper for distance computation:&#xD;&#xA;&#xD;&#xA;https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf&#xD;&#xA;&#xD;&#xA;The idea behind the paper is that, heat travels along the surface of an object essentially in a geodesic like fashion. And so the time it takes for heat to travel from a hot spot to any point on a surface is irreconcilably correlated with the geodesic distance.&#xD;&#xA;&#xD;&#xA;The paper first considers the general, analytic case and then suggests discretization approaches. What I am very confused about is the mention of the heat flow function $u$ across the paper. Consider this equation for example:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;That is the discrete laplacian operator applied to $u$ or $\Delta u$. There are multiple other sections in the paper that mention $u$. From my reading, $u$ seems to be a suitable function that approximates heat flow on the surface of a manifold? &#xD;&#xA;&#xD;&#xA;I don't really see an equation of the form $u = \text{expression}$ nor do I see descriptions of its properties nor suggestions for a good $u$ function. What is $u$? Where did $u$ come from? Where did $u$ go? Where did $u$ come from? cotan, i, o? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e5uCy.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29301" PostHistoryTypeId="1" PostId="10121" RevisionGUID="21df6da9-d625-440b-835d-f04346ca8ca7" CreationDate="2020-08-17T22:38:29.650" UserId="7462" Text="Heat Method (Crane et Al) How do we pick u?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29302" PostHistoryTypeId="3" PostId="10121" RevisionGUID="21df6da9-d625-440b-835d-f04346ca8ca7" CreationDate="2020-08-17T22:38:29.650" UserId="7462" Text="|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29303" PostHistoryTypeId="2" PostId="10122" RevisionGUID="abcccaf8-d28d-40e5-bf46-04aff6912d6a" CreationDate="2020-08-18T03:36:55.743" UserId="38" Text="There is no such thing as negative light or light color. Having a model with negative values could give people funny ideas. So light behaves strictly like positive natural numbers.&#xD;&#xA;&#xD;&#xA;Offcourse as far as coordinates go they can have negative values. But this would rise the question that your having: Howcome you can have values outside the span. Well, its not a gamut plot like you are used to seeing is just the coordinate system used. It does not tell anything of the device like a plot of say sRGB. So might be a bit misleading to draw it the same way.&#xD;&#xA;&#xD;&#xA;Yes the values of a barycentric coordinate system outside a triangle neccessitates negative values." ContentLicense="CC BY-SA 4.0" />
  <row Id="29304" PostHistoryTypeId="2" PostId="10123" RevisionGUID="426d7b25-8466-4508-8677-efbf122245be" CreationDate="2020-08-18T06:59:42.547" UserId="7647" Text="Yes, the field $u$ is in this case an approximated heat diffusion across the surface. It's found by starting with the &quot;initial set&quot; of vertices; these will be the source of the diffusion, and end up as local minima in the distance field. An initial distribution $u_0$ is set up, with value 1 on the initial set and 0 everywhere else. (This is described on page 92 of the paper you linked, immediately under Algorithm 1.)&#xD;&#xA;&#xD;&#xA;The first step of the algorithm is to run a single step of the heat equation by solving the linear equation $(I - t\nabla)u = u_0$ (equation 3 in the paper). The field $u$ you get there is the approximated heat diffusion that you further process to get the distance field." ContentLicense="CC BY-SA 4.0" />
  <row Id="29305" PostHistoryTypeId="2" PostId="10124" RevisionGUID="e1acd250-4c67-4eff-9705-dfb9f7160b8a" CreationDate="2020-08-18T07:42:29.940" UserId="13095" Text="&gt;  From my reading, u seems to be a suitable function that approximates heat flow on the surface of a manifold?&#xD;&#xA;&#xD;&#xA;$u$ is the function that describes how your quantity behaves/evolves in a certain field. In the example the quantity is the temperature or heat flux, I guess. However, most of the time there is no analytical solution/formula for $u$. This is where methods like Finite Elements (FEM) come into play. By discretizing your field, you can piecewise approximate your function u. &#xD;&#xA;&#xD;&#xA;So in your case, you would use your mesh, which is already a surface approximation. Your elements are the triangles and you need to define how the nodal quantities are interpolated inside each triangle. --- Here, linear interpolation is probably the way to go. Otherwise, you need to remesh your geometry or introduce additional nodes for higher-order approximations.&#xD;&#xA;&#xD;&#xA;Then you have to assign to each Node/Vertex an initial value $u_0$  as written in the answer of gilgamec. Afterwards, you build and solve your finite element system and get the nodal distribution of $u$ that actually solves your equation or system of equations. The finer your mesh gets, the better the solution. Higher-order interpolations will also help with accuracy.&#xD;&#xA;&#xD;&#xA;So $u$ or its nodal values are what you are actually looking for as lightxbulb said in his comment. It's your unknown quantity.&#xD;&#xA;&#xD;&#xA;If this doesn't help, you might want to read some literature about the finite element method. Can't tell how helpful the following links are, but a short glimpse looked promising. You will see, that they use $u$ all over the place. So I hope one of them will help you:&#xD;&#xA;&#xD;&#xA;- [A gentle introduction to the Finite Element Method](http://arturo.imati.cnr.it/~marini/didattica/Metodi-engl/Intro2FEM.pdf)&#xD;&#xA;- [PE281 Finite Element Method Course Notes](https://web.stanford.edu/class/energy281/FiniteElementMethod.pdf)&#xD;&#xA;- [Introduction to the finite element method](https://homepages.cae.wisc.edu/~suresh/ME964Website/M964Notes/Notes/introfem.pdf)&#xD;&#xA;- [finite element analysis by hand](https://enterfea.com/finite-element-analysis-by-hand/)&#xD;&#xA;&#xD;&#xA;I also had a link to a good online tutorial similar to the last link I provided that helped me a lot in understanding the fundamentals. If I find the link, I ll add it to my answer." ContentLicense="CC BY-SA 4.0" />
  <row Id="29306" PostHistoryTypeId="5" PostId="10124" RevisionGUID="1860cc0e-8430-450d-b592-b925deaeef76" CreationDate="2020-08-18T07:47:32.433" UserId="13095" Comment="deleted 1 character in body" Text="&gt;  From my reading, u seems to be a suitable function that approximates heat flow on the surface of a manifold?&#xD;&#xA;&#xD;&#xA;$u$ is the function that describes how your quantity behaves/evolves in a certain field. In the paper, the quantity is the temperature or heat flux, I guess. However, most of the time there is no analytical solution/formula for $u$. This is where methods like Finite Elements (FEM) come into play. By discretizing your field, you can piecewise approximate your function $u$. &#xD;&#xA;&#xD;&#xA;In your case, you would use your mesh, which is already a surface approximation. Your elements are the triangles and you need to define how the nodal quantities are interpolated inside each triangle. --- Here, linear interpolation is probably the way to go. Otherwise, you need to remesh your geometry or introduce additional nodes for higher-order approximations.&#xD;&#xA;&#xD;&#xA;Then you have to assign to each Node/Vertex an initial value $u_0$ as written in the answer of gilgamec. Afterwards, you build and solve your finite element system and get the nodal distribution of $u$ that actually solves your equation or system of equations. The finer your mesh gets, the better the solution. Higher-order interpolations will also help with accuracy.&#xD;&#xA;&#xD;&#xA;So $u$ or its nodal values are what you are actually looking for as lightxbulb said in his comment. It's your unknown quantity.&#xD;&#xA;&#xD;&#xA;If this doesn't help, you might want to read some literature about the finite element method. Can't tell how helpful the following links are, but a short glimpse looked promising. You will see, that they use $u$ all over the place. So I hope one of them will help you:&#xD;&#xA;&#xD;&#xA;- [A gentle introduction to the Finite Element Method](http://arturo.imati.cnr.it/~marini/didattica/Metodi-engl/Intro2FEM.pdf)&#xD;&#xA;- [PE281 Finite Element Method Course Notes](https://web.stanford.edu/class/energy281/FiniteElementMethod.pdf)&#xD;&#xA;- [Introduction to the finite element method](https://homepages.cae.wisc.edu/~suresh/ME964Website/M964Notes/Notes/introfem.pdf)&#xD;&#xA;- [finite element analysis by hand](https://enterfea.com/finite-element-analysis-by-hand/)&#xD;&#xA;&#xD;&#xA;I also had a link to a good online tutorial similar to the last link I provided that helped me a lot in understanding the fundamentals. If I find the link, I ll add it to my answer." ContentLicense="CC BY-SA 4.0" />
  <row Id="29307" PostHistoryTypeId="2" PostId="10125" RevisionGUID="8589cf5a-d9f7-47aa-b24a-bbe1852eea01" CreationDate="2020-08-18T07:50:58.803" UserId="13847" Text="I am programming a microcontroller - a tiny 8 bit computer that has about 100Mhz - 300Mhz CPU clock speed and 64K application RAM (actually ROM), but only a tiny amount of RAM (6K) - nowhere near enough for a graphics frame buffer.&#xD;&#xA;&#xD;&#xA;So, I want to display an animated graphics demo on this machine.  It seems to have enough computing power to calculate animated graphics of some sort.&#xD;&#xA;&#xD;&#xA;To get animated graphics to display, I will somehow need to have a computer program that each time it is called, returns a single line of pixels of one image frame, which is then displayed.  The display controller program continues to do this, calling line after line until it has displayed a whole frame, then it starts at the top again for the next frame.&#xD;&#xA;&#xD;&#xA;Just to be clear, I'm not asking about the program that controls the display.  I'm asking about the demo program.  I need a demo program that yields its graphics one line at a time, which my display controller will then throw onto the screen.&#xD;&#xA;&#xD;&#xA;I'm trying to imagine what sort of graphics program could work this way?  Presumably the display of some sort of mathematical formula.  &#xD;&#xA;&#xD;&#xA;Can anyone suggest techniques for graphics programming that work in this way, in which a function can be called, which calculates and returns a line of the frame, only when requested to do so?  Are there existing programs that work like this that I could examine?&#xD;&#xA;&#xD;&#xA;I hope the question makes sense.  Any pointers in the right direction or hints would be appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="29308" PostHistoryTypeId="1" PostId="10125" RevisionGUID="8589cf5a-d9f7-47aa-b24a-bbe1852eea01" CreationDate="2020-08-18T07:50:58.803" UserId="13847" Text="How can I make a graphics demo without a frame buffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29309" PostHistoryTypeId="3" PostId="10125" RevisionGUID="8589cf5a-d9f7-47aa-b24a-bbe1852eea01" CreationDate="2020-08-18T07:50:58.803" UserId="13847" Text="|rendering|real-time|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29310" PostHistoryTypeId="5" PostId="10124" RevisionGUID="da22aef8-83de-4284-82fa-cc5a26d7c5c0" CreationDate="2020-08-18T07:54:37.370" UserId="13095" Comment="added 9 characters in body" Text="&gt;  From my reading, u seems to be a suitable function that approximates heat flow on the surface of a manifold?&#xD;&#xA;&#xD;&#xA;$u$ is the function that describes how your quantity behaves/evolves in a certain field. In the paper, the quantity is the temperature or heat flux, I guess. However, most of the time there is no analytical solution/formula for $u$. This is where methods like Finite Elements (FEM) come into play. By discretizing your field, you can piecewise approximate your function $u$. &#xD;&#xA;&#xD;&#xA;In your case, you would use your mesh, which is already a discretization of your surface. Your elements are the triangles and you need to define how the nodal quantities are interpolated inside each triangle. --- Here, linear interpolation is probably the way to go. Otherwise, you need to remesh your geometry or introduce additional nodes for higher-order approximations.&#xD;&#xA;&#xD;&#xA;Then you have to assign to each Node/Vertex an initial value $u_0$ as written in the answer of gilgamec. Afterwards, you build and solve your finite element system and get the nodal distribution of $u$ that actually solves your equation or system of equations. The finer your mesh gets, the better the solution. Higher-order interpolations will also help with accuracy.&#xD;&#xA;&#xD;&#xA;So $u$ or its nodal values are what you are actually looking for as lightxbulb said in his comment. It's your unknown quantity.&#xD;&#xA;&#xD;&#xA;If this doesn't help, you might want to read some literature about the finite element method. Can't tell how helpful the following links are, but a short glimpse looked promising. You will see, that they use $u$ all over the place. So I hope one of them will help you:&#xD;&#xA;&#xD;&#xA;- [A gentle introduction to the Finite Element Method](http://arturo.imati.cnr.it/~marini/didattica/Metodi-engl/Intro2FEM.pdf)&#xD;&#xA;- [PE281 Finite Element Method Course Notes](https://web.stanford.edu/class/energy281/FiniteElementMethod.pdf)&#xD;&#xA;- [Introduction to the finite element method](https://homepages.cae.wisc.edu/~suresh/ME964Website/M964Notes/Notes/introfem.pdf)&#xD;&#xA;- [finite element analysis by hand](https://enterfea.com/finite-element-analysis-by-hand/)&#xD;&#xA;&#xD;&#xA;I also had a link to a good online tutorial similar to the last link I provided that helped me a lot in understanding the fundamentals. If I find the link, I ll add it to my answer." ContentLicense="CC BY-SA 4.0" />
  <row Id="29314" PostHistoryTypeId="2" PostId="10127" RevisionGUID="1bf111c3-9b08-4f49-89a2-5546e459c7cb" CreationDate="2020-08-18T15:55:06.000" UserId="2654" Text="This is a case where looking at the [workings of more retro hardware][1] would be reasonable. Older hardware had strong limitations in both memory and processing power. Your 100+Mhz chip is far faster than most consumer-grade chips of the 80s and before. So while those CPUs needed dedicated graphics chips to be able to render, your much faster CPU can probably handle the task adequately.&#xD;&#xA;&#xD;&#xA;I would suggest starting with something like the NES's tilemap-and-sprite architecture. These architectures are designed to be both memory efficient (getting a lot out of limited storage space) and computationally efficient in a line-by-line output, as they generated pixel data and sent it directly to the display device at the expected speed of a CRT.&#xD;&#xA;&#xD;&#xA;The broad idea is this. A tilemap consists of two parts: a series of tiles and a 2D array of indices into the tile map that represents the image being created. The tiles are typically 8x8, and on the NES were 2-bits-per-pixel and the tiles used palettes. Or more specifically, the index into the tile map includes not just the index of a tile but also the index of the palette to use with that tile. So a tile is not inherently associated with a palette; the association is made at the point of use (technically, on the NES, the tile map and palette map were separate, as each 2x2 block of tiles all had to use the same palette).&#xD;&#xA;&#xD;&#xA;To allow for scrolling, the tile map is bigger than the visible screen, and there is an offset that represents where the top-left corner of the visible screen is within the tilemap. Let this offset be at position `Xoff` and `Yoff`.&#xD;&#xA;&#xD;&#xA;You can see how this makes row-by-row processing trivial. To generate a horizontal row for the horizontal position `Ypos` (in screen-space), you need to get the starting pixel within the tilemap. That requires transforming the XY position `(0, Ypos)` from screen-space to tilemap space. So you add to it the vector `(Xoff, Yoff)`, hielding the vector ``Xoff, Yoff + Ypos)`.&#xD;&#xA;&#xD;&#xA;Note that when doing any mapping from screen-space to tilemap space, that the tilemap space should wrap around in both the X and Y axes. So whenever you compute a new pixel in tilemap space, you have to wrap it around the size of the tilemap space.&#xD;&#xA;&#xD;&#xA;Now, we need to break down this tilemap pixel into two 2D components: the tile index within the tilemap that gives us this this pixel, and the pixel within that tile that we need to fetch for this pixel. The tile index is just the tilemap-space pixel integer-divided by the tile size. The pixel coordinate is the tilemap-space pixel integer-*modded* by the tile size. Given an 8x8 tile size, you're doing this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;ivec2 tilemap_pixel = ...; //Compute the tilemap starting pixel as above.&#xD;&#xA;ivec2 tilemap_tile = ivec2(tilemap_pixel.x &amp; ~0x7, tilemap_pixel.y &amp; ~0x7); //Mask off the lower 3 bits.&#xD;&#xA;ivec2 pixel_in_tile = ivec2(tilemap_pixel.x &amp; 0x7, tilemap_pixel.y &amp; 0x7); //Mask off all but the lower 3 bits.&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So given `tilemap_tile`, we now have the index of the tile we are currently working within. And `pixel_in_tile` gives us the pixel we're working in. So we can fetch that pixel, whose value can be mapped into a palette to produce the final color for that pixel. Or we can use it directly.&#xD;&#xA;&#xD;&#xA;To get the next pixel is pretty trivial. We just increment `pixel_in_tile.x` by 1, modulo the tile size. If the increment exceeded the tile size, then we also increment `tilemap_tile.x` by 1, modulo the tilemap size. And you keep going until you've filled out the row of pixels.&#xD;&#xA;&#xD;&#xA;There are many opportunities for performance optimization of such an algorithm.&#xD;&#xA;&#xD;&#xA;The tiles probably represent the largest data. A 128 element tile set of 8x8 tiles, even at 2bpp, is 2K. But the thing is, those can be stored in *ROM*, since you're probably not changing the tiles themselves. The size of the tile map (assuming it must be in RAM) depends on the desired output resolution and the tile size. A tile map for 8x8 tiles that can cover a 320x240 screen is 1,200 bytes. Not exactly tiny. You'll need to take up more memory if you want room for smooth scrolling (and thus a larger tile map).&#xD;&#xA;&#xD;&#xA;That being said, it's also important to note that the &quot;output size&quot; doesn't have to be the actual size of the *display device*. For example, if you intend to draw to a 1080p display device, you could still render to an internal resolution that's, for example, 8 times smaller, 240x135. It's easy to modify this algorithm to essentially generate the same pixel value 8 times in a row, as well as reusing the same line 8 times per 1080p line. Indeed, it wouldn't be too difficult to have this algorithm allow for subpixel scrolling (scrolling in 1080p space, not 135p space) and even adding some filtering between pixel values. A 240x135 &quot;output size&quot; tilemap would only require 510 bytes for the visible region, so you would have more room for a larger scrolling area.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://retrocomputing.stackexchange.com/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29318" PostHistoryTypeId="2" PostId="10129" RevisionGUID="544e90a7-eff8-4bd7-a21a-5fcd2f3a1cf1" CreationDate="2020-08-18T18:05:59.613" UserId="13814" Text="As I understand Euclideon haven't just rendered voxels for these infamous demos, since the amount of geometry is still too large for the 2010 PC with software raytracer and the model taking whole HDD and streaming non-stop, even with the prebaked lights. They instead did subreferencing inside their BVH to point to either dynamic generator or the instances of the pregenerated microgeometry (similar to reusing the same texture with polygonal graphics). So Euclideon could have even the dust particles on the ground. That is apparently very old trick. I remember it being used to prerender the backgrounds in Ecstatica (an old DOS video game). Am I correct? Then why have Euclideon generated so much hatred and controversy back then? The tech looks solid and was used previously for offline rendering. Euclideon people just brought it into realtime on consumer PCs." ContentLicense="CC BY-SA 4.0" />
  <row Id="29319" PostHistoryTypeId="1" PostId="10129" RevisionGUID="544e90a7-eff8-4bd7-a21a-5fcd2f3a1cf1" CreationDate="2020-08-18T18:05:59.613" UserId="13814" Text="Euclideon Unlimited Details Voxel Engine Architecture" ContentLicense="CC BY-SA 4.0" />
  <row Id="29320" PostHistoryTypeId="3" PostId="10129" RevisionGUID="544e90a7-eff8-4bd7-a21a-5fcd2f3a1cf1" CreationDate="2020-08-18T18:05:59.613" UserId="13814" Text="|raytracing|volumetric|voxelization|bounding-volume-hierarchy|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29324" PostHistoryTypeId="34" PostId="10072" RevisionGUID="59c11b7e-fe58-443b-b03c-5e8d2fec73bf" CreationDate="2020-08-19T04:09:56.000" UserId="-1" Comment="62" />
  <row Id="29325" PostHistoryTypeId="2" PostId="10131" RevisionGUID="52c9e5c8-7d7c-4f96-a82e-924ef35d9614" CreationDate="2020-08-19T07:55:58.697" UserId="13853" Text="I received a pdf from a client containing several invoices. Upon further inspecting, some lines on the invoice seem digitally produced. When I tried selecting the page, copying it then pasting it on paint, the lines that seemed suspicious disappeared. &#xD;&#xA;&#xD;&#xA;I should note that the source invoice paper are very thin. So before jumping to any conclusions, is it common that some printers or printing software compensate for blurry or lost lines and text and try to “enhance them”?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29326" PostHistoryTypeId="1" PostId="10131" RevisionGUID="52c9e5c8-7d7c-4f96-a82e-924ef35d9614" CreationDate="2020-08-19T07:55:58.697" UserId="13853" Text="Do scanners and scanning software compensate and enhance blurry sources?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29327" PostHistoryTypeId="3" PostId="10131" RevisionGUID="52c9e5c8-7d7c-4f96-a82e-924ef35d9614" CreationDate="2020-08-19T07:55:58.697" UserId="13853" Text="|image-processing|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29329" PostHistoryTypeId="2" PostId="10132" RevisionGUID="49f040db-7cdd-4526-87ea-5710e4b01f7d" CreationDate="2020-08-19T08:53:36.580" UserId="13850" Text="I'm re-writing an algorithm that I first wrote using matrix/vector operation into OpenGL kernels in order to try to maximiz the performances.&#xD;&#xA;&#xD;&#xA;I have a basic knowledge of OpenGL, so I was able to get the things working, but I have a lot of trouble when it come to make various choices offered by OpenGL, especially the buffer's parameters that I guess have a huge impact in my case where I read and write a lot of data.&#xD;&#xA;&#xD;&#xA;I call the three kernels sequencially :&#xD;&#xA;&lt;!-- language-all: glsl --&gt;&#xD;&#xA;**First :**&#xD;&#xA;```&#xD;&#xA;/* Generated constants (for all three shaders): &#xD;&#xA; *   #version 430&#xD;&#xA; *   const vec3 orig&#xD;&#xA; *   const float vx&#xD;&#xA; *   const ivec2 size&#xD;&#xA; *   const uint projections&#xD;&#xA; *   const uint subIterations&#xD;&#xA; */&#xD;&#xA;layout(local_size_x = 1, local_size_y = 1) in;&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer bufferA { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    uint bufferProjection[]; //Written and read (AtomicAdd) by this shader, read by the second kernel&#xD;&#xA;};&#xD;&#xA;layout(std430, binding = 1) readonly buffer bufferB { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    uint layer[]; //Written and read by the third kernel, read by this shader and by glGetNamedBufferSubData&#xD;&#xA;};&#xD;&#xA;layout(std140) uniform bufferMat { //GL_UNIFORM_BUFFER, GL_STATIC_DRAW&#xD;&#xA;    mat4 proj_mat[projections*subIterations]; //Read only by this shader and the third&#xD;&#xA;};&#xD;&#xA;layout(location = 0) uniform int z;&#xD;&#xA;layout(location = 1) uniform int subit;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 layer_coords = vec4(orig,1.0) + vec4(gl_GlobalInvocationID.x, z, gl_GlobalInvocationID.y, 0.0)*vx;&#xD;&#xA;    uint val = layer[gl_GlobalInvocationID.y*size.x + gl_GlobalInvocationID.x];&#xD;&#xA;    for(int i = 0; i &lt; projections; ++i) {&#xD;&#xA;        vec4 proj_coords = proj_mat[subit+i*subIterations]*layer_coords;&#xD;&#xA;        ivec2 tex_coords = ivec2(floor((proj_coords.xy*size)/(2.0*proj_coords.w)) + size/2);&#xD;&#xA;        bool valid = all(greaterThanEqual(tex_coords, ivec2(0,0))) &amp;&amp; all(lessThan(tex_coords, size));&#xD;&#xA;        atomicAdd(bufferProjection[tex_coords.y*size.x+tex_coords.x+i*(size.x*size.y)], valid?val:0);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Second:**&#xD;&#xA;```&#xD;&#xA;layout(local_size_x = 1, local_size_y = 1) in;&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) buffer bufferA { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    float updateProjection[]; //Written by this shader, read by the third kernel&#xD;&#xA;};&#xD;&#xA;layout(std430, binding = 1) readonly buffer bufferB { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    uint bufferProjection[]; //Written by the first, read by this shader&#xD;&#xA;};&#xD;&#xA;layout(std430, binding = 2) readonly buffer bufferC { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    uint originalProjection[]; //Only modified by glBufferSubData, read by this shader&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    for(int i = 0; i &lt; projections; ++i) {&#xD;&#xA;        updateProjection[gl_GlobalInvocationID.x+i*(size.x*size.y)] = float(originalProjection[gl_GlobalInvocationID.x+i*(size.x*size.y)])/float(bufferProjection[gl_GlobalInvocationID.x+i*(size.x*size.y)]);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Third:**&#xD;&#xA;```&#xD;&#xA;layout(local_size_x = 1, local_size_y = 1) in;&#xD;&#xA;&#xD;&#xA;layout(std430, binding = 0) readonly buffer bufferA { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    float updateProjection[]; //Written by the second kernel, read by this shader&#xD;&#xA;};&#xD;&#xA;layout(std430, binding = 1) buffer bufferB { //GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_READ&#xD;&#xA;    uint layer[]; //Written and read by this shader, read by the first kernel and by glGetNamedBufferSubData&#xD;&#xA;};&#xD;&#xA;layout(std140) uniform bufferMat { //GL_UNIFORM_BUFFER, GL_STATIC_DRAW&#xD;&#xA;    mat4 proj_mat[projections*subIterations]; //Read only by this shader and and the first&#xD;&#xA;};&#xD;&#xA;layout(location = 0) uniform int z;&#xD;&#xA;layout(location = 1) uniform int subit;&#xD;&#xA;layout(location = 2) uniform float weight;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 layer_coords = vec4(orig,1.0) + vec4(gl_GlobalInvocationID.x, z, gl_GlobalInvocationID.y, 0.0)*vx;&#xD;&#xA;    float acc = 0;&#xD;&#xA;    for(int i = 0; i &lt; projections; ++i) {&#xD;&#xA;        vec4 proj_coords = proj_mat[subit+i*subIterations]*layer_coords;&#xD;&#xA;        ivec2 tex_coords = ivec2(floor((proj_coords.xy*size)/(2.0*proj_coords.w)) + size/2);&#xD;&#xA;        bool valid = all(greaterThanEqual(tex_coords, ivec2(0,0))) &amp;&amp; all(lessThan(tex_coords, size));&#xD;&#xA;        acc += valid?updateProjection[tex_coords.y*size.x+tex_coords.x+i*(size.x*size.y)]:0;&#xD;&#xA;    }&#xD;&#xA;    float val = pow(float(layer[gl_GlobalInvocationID.y*size.x + gl_GlobalInvocationID.x])*(acc/projections), weight);&#xD;&#xA;    layer[gl_GlobalInvocationID.y*size.x + gl_GlobalInvocationID.x] = uint(val);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;What I came up by reading the OpenGL doc :&#xD;&#xA;&#xD;&#xA; - Some value that are the same for all the duration of the algorithm are generated as const before compiling the shader. Especially usefull for the for-loop boundary&#xD;&#xA; - bufferMat, which is very small compared to the other buffers, is put in an UBO, which should have better performance than SSBO. Do I could get event better perf by making it a compile-time constant ? It's small, but still a few hundreds mat4&#xD;&#xA; - The others buffer, being both read and written several times, should be better as SSBO&#xD;&#xA; - I have trouble understanding what could be the best value for the 'usage' parameters of the buffer. All buffers being written to  and read several time, I'm not sure what to put here.&#xD;&#xA; - If I understand correctly, the local_size is only usefull when sharing data between invocations, so I should keep it at one ?&#xD;&#xA;&#xD;&#xA;I would gladly take any recommendations or hints about where to look to optimize thoses kernels !" ContentLicense="CC BY-SA 4.0" />
  <row Id="29330" PostHistoryTypeId="1" PostId="10132" RevisionGUID="49f040db-7cdd-4526-87ea-5710e4b01f7d" CreationDate="2020-08-19T08:53:36.580" UserId="13850" Text="Using buffers correctly in OpenGL compute shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="29331" PostHistoryTypeId="3" PostId="10132" RevisionGUID="49f040db-7cdd-4526-87ea-5710e4b01f7d" CreationDate="2020-08-19T08:53:36.580" UserId="13850" Text="|opengl|compute-shader|optimisation|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29332" PostHistoryTypeId="2" PostId="10133" RevisionGUID="1c1cabb1-ed7d-4af7-8edd-0dd56947f0c3" CreationDate="2020-08-19T13:01:41.497" UserId="10129" Text="I decided to use R16B16G16A16_FLOAT format instead to avoid problems as I'm working on hobby/academic code and it isn't fully fledged game/graphics engine.&#xD;&#xA;&#xD;&#xA;I solves my problem. FYI, I've also tried using R8B8G8A8_SNORM instead of *_UNORM, but I failed to get correct results with that. Maybe it was due to other factors, so I don't fully blame format." ContentLicense="CC BY-SA 4.0" />
  <row Id="29333" PostHistoryTypeId="2" PostId="10134" RevisionGUID="401707ea-4c82-4477-a469-a816f4357170" CreationDate="2020-08-19T14:51:27.897" UserId="2654" Text="&gt; Do I could get event better perf by making it a compile-time constant ?&#xD;&#xA;&#xD;&#xA;You'll have to profile it. That being said, &quot;a few hundreds mat4&quot; is *not &quot;small&quot;*.&#xD;&#xA;&#xD;&#xA;&gt; I have trouble understanding what could be the best value for the 'usage' parameters of the buffer. All buffers being written to and read several time, I'm not sure what to put here.&#xD;&#xA;&#xD;&#xA;First, the usage parameters are about *your* usage of the buffer object, not OpenGL's usage of the memory behind them. That is, they're talking about functions like `glBufferSubData`, `glMapBufferRange`, and so forth. `READ` means that the CPU will read from the buffer, but not write to it. `DRAW` means that the CPU will write to the buffer, but not read from it.&#xD;&#xA;&#xD;&#xA;Second... you really shouldn't care. Usage hints are terrible, poorly specified, and have been so misused that many implementations flat-out *ignore* them. NVIDIA's GL implementation is probably the one that takes them the most seriously.&#xD;&#xA;&#xD;&#xA;Instead, use [immutable storage buffers][1]. Those &quot;usage hints&quot; are not *hints*; they're API requirements. If you don't use `GL_DYNAMIC_STORAGE_BIT`, then you *cannot* write to the buffer via `glBufferSubData`. And so forth.&#xD;&#xA;&#xD;&#xA;&gt; If I understand correctly, the local_size is only usefull when sharing data between invocations, so I should keep it at one ?&#xD;&#xA;&#xD;&#xA;No. In fact, never use 1. If all of the invocations are doing their own thing, with no execution barriers or the like, then you should pick a local size that is equivalent to the wavefront size of the hardware you're working on. Obviously that's implementation dependent, but 32 is certainly a better default than 1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object#Immutable_Storage" ContentLicense="CC BY-SA 4.0" />
  <row Id="29335" PostHistoryTypeId="2" PostId="10135" RevisionGUID="ef99093d-a990-43c1-82ed-3a9529d9a5bd" CreationDate="2020-08-19T22:19:40.507" UserId="2308" Text="I have a camera I have placed `z`units away from a billboarded rect. My goal is to discard all other geometry that is closer to the camera/in front of this rect.&#xA;&#xA;With perspective projection I have always set the near plane to 0.1 and called it a day however here I tried to set it to `z` thinking it would clip anything in front of this rect.&#xA;&#xA;No such luck. This ended up clipping that rect and seemingly even more. Z-1 also did not have the desired result.&#xA;&#xA;This leads me to think the near clipping plane might not be in the same coordinate space as the world? If not what space is it in?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29336" PostHistoryTypeId="1" PostId="10135" RevisionGUID="ef99093d-a990-43c1-82ed-3a9529d9a5bd" CreationDate="2020-08-19T22:19:40.507" UserId="2308" Text="Perspective projection near plane not in world coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="29337" PostHistoryTypeId="3" PostId="10135" RevisionGUID="ef99093d-a990-43c1-82ed-3a9529d9a5bd" CreationDate="2020-08-19T22:19:40.507" UserId="2308" Text="|matrix|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29339" PostHistoryTypeId="2" PostId="10136" RevisionGUID="649fea26-061a-49a3-b950-ef315f9cacdf" CreationDate="2020-08-20T07:35:18.573" UserId="13095" Text="The perspective projection matrix transforms from camera space to clip space. The near-plane value is the position of the near plane in camera space. So in case that your world space to camera space transformation does not use any scaling, only rotations and translations, then if you place the camera $z$ units away from the billboard surface and look directly onto it, a near plane value of $z$ will cause the billboard plane to lie on the near plane. Due to rounding errors, it might get clipped away, so your idea of setting it to $z-offset$ should solve the problem.&#xD;&#xA;&#xD;&#xA;Why it doesn't work is hard to tell without any code. Maybe your implementation of the perspective matrix is wrong. Maybe you have a hidden scaling when you transform between world and camera space. To debug this you can try to multiply $z$ with values between 0 and 1 until you get the desired result. The resulting factor might be a clue. For example if you get $0.5$ we know that there is either a 2 missing or too much in your transformation matrices. Also, make sure that your far plane value is larger than your near plane value (even though I think from your description that this isn't the problem - but who knows)&#xD;&#xA;&#xD;&#xA;In case you are using OpenGL, here is a [link to how the perspective projection matrix has to look like](http://www.songho.ca/opengl/gl_projectionmatrix.html). Maybe you have to transpose the matrix. That depends on your vector layout - column vectors or row vectors.&#xD;&#xA;&#xD;&#xA;[Here is a link to an answer of mine](https://computergraphics.stackexchange.com/a/9960/13095) to another question. It has a Python script at the end that you can use to visualize how the different values affect the view frustum in the different spaces. Some pictures are also included in the answer. Maybe that is already enough to help you out." ContentLicense="CC BY-SA 4.0" />
  <row Id="29340" PostHistoryTypeId="50" PostId="10045" RevisionGUID="a67c9c11-f2ae-4aaa-824b-a0395c038043" CreationDate="2020-08-20T20:03:15.350" UserId="-1" />
  <row Id="29342" PostHistoryTypeId="50" PostId="2146" RevisionGUID="f165b613-5779-425a-bb28-aed16370df66" CreationDate="2020-08-21T06:05:10.580" UserId="-1" />
  <row Id="29343" PostHistoryTypeId="50" PostId="9654" RevisionGUID="804b3d0f-dffc-4e4c-9e2a-0ddfb3dcebef" CreationDate="2020-08-21T07:02:40.317" UserId="-1" />
  <row Id="29344" PostHistoryTypeId="50" PostId="8701" RevisionGUID="8e949145-c468-436e-b74f-5ee078ae7341" CreationDate="2020-08-21T12:06:10.910" UserId="-1" />
  <row Id="29345" PostHistoryTypeId="50" PostId="8886" RevisionGUID="7421a8a0-7d80-4a4b-872b-73537e247266" CreationDate="2020-08-21T14:01:10.177" UserId="-1" />
  <row Id="29347" PostHistoryTypeId="2" PostId="10137" RevisionGUID="9af9f81c-bc47-4ab8-953d-5c88ae281b16" CreationDate="2020-08-21T21:51:54.577" UserId="7462" Text="I am trying to understand how to get the discrete gradient of a mesh that is being used as the input of some function $f$. In other words for every vertex $v$ there is a scalar quantity $s$ associated with it.&#xD;&#xA;&#xD;&#xA;I am trying to understand how to compute the discrete gradient of $f$ on the surface. For that purpose I was checking these slides:&#xD;&#xA;&#xD;&#xA;http://www.hao-li.com/cs599-ss2015/slides/Lecture04.1.pdf&#xD;&#xA;&#xD;&#xA;But it's not clicking. The piece wise notation I am assuming is just an attempt at formalizing &quot;we have no idea what the values at the triangles would be, so we are just going to linearly interpolate using Barycentric coordinates&quot;.&#xD;&#xA;&#xD;&#xA;But then the slides reach this final formula for the gradient:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I kinda understand the bottom part, which seems to say the gradient basis at $i$ is a vector orthogonal to the opposite edge divided by 2 times the area of the triangle (I assume), but how was the top formula derived?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Mx9hP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29348" PostHistoryTypeId="1" PostId="10137" RevisionGUID="9af9f81c-bc47-4ab8-953d-5c88ae281b16" CreationDate="2020-08-21T21:51:54.577" UserId="7462" Text="Discrete Gradient?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29349" PostHistoryTypeId="3" PostId="10137" RevisionGUID="9af9f81c-bc47-4ab8-953d-5c88ae281b16" CreationDate="2020-08-21T21:51:54.577" UserId="7462" Text="|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29350" PostHistoryTypeId="2" PostId="10138" RevisionGUID="b65deb51-1006-483d-bd02-e6bd256c9228" CreationDate="2020-08-21T22:14:53.263" UserId="13861" Text="I have this image below, I want to get rid of the text 'MSAR IDs' that is in the background. I am extracting the numbers from the image with OCR, the numbers that have a white background get extracted as is, however the numbers that have the text behind them don't get extracted properly and are not correct because they all have some part of the background text behind them. Can anyone please tell me how to get rid of the big text in background, any software will do for me.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29351" PostHistoryTypeId="1" PostId="10138" RevisionGUID="b65deb51-1006-483d-bd02-e6bd256c9228" CreationDate="2020-08-21T22:14:53.263" UserId="13861" Text="How to remove background text from an image file" ContentLicense="CC BY-SA 4.0" />
  <row Id="29352" PostHistoryTypeId="3" PostId="10138" RevisionGUID="b65deb51-1006-483d-bd02-e6bd256c9228" CreationDate="2020-08-21T22:14:53.263" UserId="13861" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29353" PostHistoryTypeId="5" PostId="10100" RevisionGUID="c2c87d0d-3d20-48a6-a46c-2ab736173406" CreationDate="2020-08-22T03:20:01.783" UserDisplayName="user5681" Comment="added 783 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][1] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;Actually there are several reasons that make the BVHs the preferred acceleration data structure for interactive ray tracing o GPUs. According to [Wodniok and Goesele][2], the main factors that have turned the BVH into a popular acceleration structure in the context of GPU ray tracing are its &quot;*memory footprint (...) efficient empty space cut-off, fast construction, and simple update procedure (...) while (...) offering similar (...) performance as kD-Trees*&quot;. Regarding fast BVH reconstruction, it may be interesting to take a look at the LBVH, by [Lauterbach *et. al.*][3], the HLBVH, by [Pantaleoni&#xD;&#xA;and Luebke][4], and the one by [Karras and Aila][5], that are capable to rebuild BVHs iteractively. Overlapping impacts the traversal procedure efficiency because, when a ray hit the overlap, it has to be tested against the two child nodes. SBVHs, by [Stich et. al.][5] is a hybrid structure that employs both spatial and object subdivisions such that overlap is minimized. The con, according to the paper, is that the SBVH do not handle dynamic scenes so easily and that it may increase memory consumption up to 30%. The SBVH building procedure is no as fast as for regular BVHs also. The current [NVidia RTX GPUs support the traditional BVH, the SBVH and Karras/Aila acceleration structure][6].&#xD;&#xA;&#xD;&#xA;This answer is still full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. I am still editing this answer, adding the proper references as time permits.&#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/1189762.1206075&#xD;&#xA;  [2]: https://www.sciencedirect.com/science/article/pii/S0097849316301376?casa_token=D0jTp_c1HngAAAAA:YCD31gt1rp4zR8wzE20vTxIEXAJR83pOZh0Bp_saqZChzCHOfgKwu0W7N0jT9dJGCvKjAVTdsQ&#xD;&#xA;  [3]: https://onlinelibrary.wiley.com/doi/full/10.1111/j.1467-8659.2009.01377.x?casa_token=s3kaFgXZt38AAAAA%3Ar1tdA-tx8aAclVsQeLTh8oUR5XDgEgI-twjAhezqDUWmBm8W2AaL8OzD0KU9s0EfZN5DHZFWHB8gZXM&#xD;&#xA;  [4]: https://research.nvidia.com/sites/default/files/pubs/2010-06_HLBVH-Hierarchical-LBVH/HLBVH-final.pdf&#xD;&#xA;  [5]: https://www.nvidia.in/docs/IO/77714/sbvh.pdf&#xD;&#xA;  [6]: https://raytracing-docs.nvidia.com/optix/guide/nvidia_optix_programming_guide.180313.A4.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29354" PostHistoryTypeId="5" PostId="10100" RevisionGUID="a5ebdcd2-488e-47f1-a04d-1d4f67dc8af8" CreationDate="2020-08-22T03:33:45.727" UserDisplayName="user5681" Comment="added 365 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][1] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;Actually there are several reasons that make the BVHs the preferred acceleration data structure for interactive ray tracing o GPUs. According to [Wodniok and Goesele][2], the main factors that have turned the BVH into a popular acceleration structure in the context of GPU ray tracing are its &quot;*memory footprint (...) efficient empty space cut-off, fast construction, and simple update procedure (...) while (...) offering similar (...) performance as kD-Trees*&quot;. Regarding fast BVH reconstruction, it may be interesting to take a look at the LBVH, by [Lauterbach *et. al.*][3], the HLBVH, by [Pantaleoni&#xD;&#xA;and Luebke][4], and the one by [Karras and Aila][5], that are capable to rebuild BVHs iteractively. Overlapping impacts the traversal procedure efficiency because, when a ray hit the overlap, it has to be tested against the two child nodes. SBVHs, by [Stich et. al.][5] is a hybrid structure that employs both spatial and object subdivisions such that overlap is minimized. The con, according to the paper, is that the SBVH does not handle dynamic scenes so easily and that it may increase memory consumption up to 30%. The SBVH building procedure is no as fast as for regular BVHs also. The current [NVidia RTX GPUs support the traditional BVH, the SBVH and Karras/Aila acceleration structure][6]. As pointed out by the @DirectX_Programmer [in his answer below][7], these structures are actually combined, by the RTX drivers, into a more flexible arrangement composed by two levels: a Top Level Acceleration Strucure, or TLAS, and a Bottom Level Acceleration Structure, or BLAS. You can find more details and references about that on the [@DirectX_Programmer's answer][7].&#xD;&#xA;&#xD;&#xA;This answer is still full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. I am still editing this answer, adding the proper references as time permits.&#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/1189762.1206075&#xD;&#xA;  [2]: https://www.sciencedirect.com/science/article/pii/S0097849316301376?casa_token=D0jTp_c1HngAAAAA:YCD31gt1rp4zR8wzE20vTxIEXAJR83pOZh0Bp_saqZChzCHOfgKwu0W7N0jT9dJGCvKjAVTdsQ&#xD;&#xA;  [3]: https://onlinelibrary.wiley.com/doi/full/10.1111/j.1467-8659.2009.01377.x?casa_token=s3kaFgXZt38AAAAA%3Ar1tdA-tx8aAclVsQeLTh8oUR5XDgEgI-twjAhezqDUWmBm8W2AaL8OzD0KU9s0EfZN5DHZFWHB8gZXM&#xD;&#xA;  [4]: https://research.nvidia.com/sites/default/files/pubs/2010-06_HLBVH-Hierarchical-LBVH/HLBVH-final.pdf&#xD;&#xA;  [5]: https://www.nvidia.in/docs/IO/77714/sbvh.pdf&#xD;&#xA;  [6]: https://raytracing-docs.nvidia.com/optix/guide/nvidia_optix_programming_guide.180313.A4.pdf&#xD;&#xA;  [7]: https://computergraphics.stackexchange.com/a/10106/5681" ContentLicense="CC BY-SA 4.0" />
  <row Id="29355" PostHistoryTypeId="5" PostId="10100" RevisionGUID="79bd0dd9-d6b0-447d-9bce-04a42b31a5a2" CreationDate="2020-08-22T03:48:48.347" UserDisplayName="user5681" Comment="deleted 94 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. &#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][1] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;Actually there are several reasons that make the BVHs the preferred acceleration data structure for interactive ray tracing o GPUs. According to [Wodniok and Goesele][2], the main factors that have turned the BVH into a popular acceleration structure in the context of GPU ray tracing are its &quot;*memory footprint (...) efficient empty space cut-off, fast construction, and simple update procedure (...) while (...) offering similar (...) performance as kD-Trees*&quot;. Regarding fast BVH reconstruction, it may be interesting to take a look at the LBVH, by [Lauterbach *et. al.*][3], the HLBVH, by [Pantaleoni&#xD;&#xA;and Luebke][4], and the one by [Karras and Aila][5], that are capable to rebuild BVHs iteractively. Overlapping impacts the traversal procedure efficiency because, when a ray hit the overlap, it has to be tested against the two child nodes. SBVHs, by [Stich et. al.][5] is a hybrid structure that employs both spatial and object subdivisions such that overlap is reduced. The cons, according to the paper, are the fact that SBVH does not handle dynamic scenes anymore, and that it may increase memory consumption up to 30%. The SBVH building procedure, also, is not as fast as for the regular BVHs.&#xD;&#xA;&#xD;&#xA;The current [NVidia RTX GPUs support the traditional BVH, the SBVH and Karras/Aila acceleration structure][6]. As well pointed out by [@DirectX_Programmer, in his answer below][7], these structures are actually combined, by the RTX drivers, into a more flexible arrangement composed by two levels. &#xD;&#xA;&#xD;&#xA;This answer is still full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. I am still editing this answer, adding the proper references as time permits.&#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/1189762.1206075&#xD;&#xA;  [2]: https://www.sciencedirect.com/science/article/pii/S0097849316301376?casa_token=D0jTp_c1HngAAAAA:YCD31gt1rp4zR8wzE20vTxIEXAJR83pOZh0Bp_saqZChzCHOfgKwu0W7N0jT9dJGCvKjAVTdsQ&#xD;&#xA;  [3]: https://onlinelibrary.wiley.com/doi/full/10.1111/j.1467-8659.2009.01377.x?casa_token=s3kaFgXZt38AAAAA%3Ar1tdA-tx8aAclVsQeLTh8oUR5XDgEgI-twjAhezqDUWmBm8W2AaL8OzD0KU9s0EfZN5DHZFWHB8gZXM&#xD;&#xA;  [4]: https://research.nvidia.com/sites/default/files/pubs/2010-06_HLBVH-Hierarchical-LBVH/HLBVH-final.pdf&#xD;&#xA;  [5]: https://www.nvidia.in/docs/IO/77714/sbvh.pdf&#xD;&#xA;  [6]: https://raytracing-docs.nvidia.com/optix/guide/nvidia_optix_programming_guide.180313.A4.pdf&#xD;&#xA;  [7]: https://computergraphics.stackexchange.com/a/10106/5681" ContentLicense="CC BY-SA 4.0" />
  <row Id="29356" PostHistoryTypeId="2" PostId="10139" RevisionGUID="603f8164-67a2-4419-b662-78850cf128bf" CreationDate="2020-08-22T07:42:44.697" UserId="13838" Text="An area consists of 2 components, the normalized gradient of the basis_i gives the constant rate in the direction of one of the components which only depends on vertices.&#xD;&#xA;&#xD;&#xA;The highlighted formula is the intermediate state of transforming the function  fully utilizes vertices. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29357" PostHistoryTypeId="2" PostId="10140" RevisionGUID="67b80474-c960-47e9-9ed4-f0509811b790" CreationDate="2020-08-22T08:06:03.360" UserId="13838" Text="It is all about filtering, you can see there are 4 colors, i.e. C_Font, C_Paper, C_Watermark_Paper, and C_Watermark_Font, the filter is just f(C_Watermark_Paper) = C_Paper and f(C_Watermark_Font) = C_Paper.&#xD;&#xA;&#xD;&#xA;Of course you can use GIMP and easily Google references, i.e. http://howto.nicubunu.ro/gimp-remove-watermark/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29358" PostHistoryTypeId="2" PostId="10141" RevisionGUID="15ba9b4a-66e6-4595-91e7-c675f0eeef81" CreationDate="2020-08-22T10:15:21.763" UserId="13095" Text="Hello, &#xD;&#xA;&#xD;&#xA;my name is Volker and I am an engineer from Germany. In my professional career, I do a lot of programming that isn't directly related to computer graphics. However, after work, I follow my true passion and work on my own game/graphics engine. This interest of mine lead me to this site.&#xD;&#xA;&#xD;&#xA;I enjoy helping others to solve their problems and sharing my knowledge. This motivates me to visit this site regularly, currently multiple times a day. So I can help to resolve new flags quickly. I also have a regular look into all the review queues that are available to me and review as many items as I can. &#xD;&#xA;&#xD;&#xA;If I think that a post has some issues and cast a corresponding vote, I always leave a comment expressing what I think is wrong. I am aware that moderator votes are binding so I would delay my vote on disputable cases and leave a comment until enough other users agree with me. However, I would close obvious spam and questions totally unrelated to CG immediately.&#xD;&#xA;&#xD;&#xA;In case you don't agree with one of my actions on this site, I am always open to arguments and will reconsider my decisions.&#xD;&#xA;&#xD;&#xA;This post has a character limit. Ask me anything you need to know in the comments." ContentLicense="CC BY-SA 4.0" />
  <row Id="29359" PostHistoryTypeId="2" PostId="10142" RevisionGUID="b0c4a022-e3c0-47b2-a51a-37849d5e1f50" CreationDate="2020-08-22T10:31:01.230" UserId="9194" Text="There is a good chance that you could just blur the image a tiny tad so that the noisy structure in the watermark disappears (it basically becomes its own grey color). Then maybe your OCR software can read it? It might help converting it into a greyscale image first.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29360" PostHistoryTypeId="5" PostId="10140" RevisionGUID="f45238c0-a416-4d23-95ac-84463bcd7ad1" CreationDate="2020-08-22T11:01:49.820" UserId="13838" Comment="deleted 1 character in body" Text="It is all about filtering, you can see there are 4 colors, i.e. C_Font, C_Paper, C_Watermark_Paper, and C_Watermark_Font, the filter is just f(C_Watermark_Paper) = C_Paper and f(C_Watermark_Font) = C_Font.&#xD;&#xA;&#xD;&#xA;Of course you can use GIMP and easily Google references, i.e. http://howto.nicubunu.ro/gimp-remove-watermark/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29367" PostHistoryTypeId="5" PostId="10100" RevisionGUID="b7556a79-eb9d-487b-845d-9de6efdfbe62" CreationDate="2020-08-23T01:25:40.487" UserDisplayName="user5681" Comment="added 188 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. More on the basics of space and object subdivision that can be found in the [PBRT v3 online book][1].&#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][2] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;Actually there are several reasons that make the BVHs the preferred acceleration data structure for interactive ray tracing o GPUs. According to [Wodniok and Goesele][3], the main factors that have turned the BVH into a popular acceleration structure in the context of GPU ray tracing are its &quot;*memory footprint (...) efficient empty space cut-off, fast construction, and simple update procedure (...) while (...) offering similar (...) performance as kD-Trees*&quot;. Regarding fast BVH reconstruction, it may be interesting to take a look at the LBVH, by [Lauterbach *et. al.*][4], the HLBVH, by [Pantaleoni&#xD;&#xA;and Luebke][5], and the one by [Karras and Aila][6], that are capable to rebuild BVHs iteractively. Overlapping impacts the traversal procedure efficiency because, when a ray hit the overlap, it has to be tested against the two child nodes. SBVHs, by [Stich et. al.][6] is a hybrid structure that employs both spatial and object subdivisions such that overlap is reduced. The cons, according to the paper, are the fact that SBVH does not handle dynamic scenes anymore, and that it may increase memory consumption up to 30%. The SBVH building procedure, also, is not as fast as for the regular BVHs.&#xD;&#xA;&#xD;&#xA;The current [NVidia RTX GPUs support the traditional BVH, the SBVH and Karras/Aila acceleration structure][7]. As well pointed out by [@DirectX_Programmer, in his answer below][8], these structures are actually combined, by the RTX drivers, into a more flexible arrangement composed by two levels. &#xD;&#xA;&#xD;&#xA;This answer is still full of strong statements that should be accepted with care. There are actually some techniques that explore the local update of space subdivision structures; techniques that aim to stop BVH traversal as soon as it finds an intersection point; and so on. I am still editing this answer, adding the proper references as time permits.&#xD;&#xA;&#xD;&#xA;I think that this answer gives the big picture, however.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Primitives_and_Intersection_Acceleration.html&#xD;&#xA;  [2]: https://dl.acm.org/doi/10.1145/1189762.1206075&#xD;&#xA;  [3]: https://www.sciencedirect.com/science/article/pii/S0097849316301376?casa_token=D0jTp_c1HngAAAAA:YCD31gt1rp4zR8wzE20vTxIEXAJR83pOZh0Bp_saqZChzCHOfgKwu0W7N0jT9dJGCvKjAVTdsQ&#xD;&#xA;  [4]: https://onlinelibrary.wiley.com/doi/full/10.1111/j.1467-8659.2009.01377.x?casa_token=s3kaFgXZt38AAAAA%3Ar1tdA-tx8aAclVsQeLTh8oUR5XDgEgI-twjAhezqDUWmBm8W2AaL8OzD0KU9s0EfZN5DHZFWHB8gZXM&#xD;&#xA;  [5]: https://research.nvidia.com/sites/default/files/pubs/2010-06_HLBVH-Hierarchical-LBVH/HLBVH-final.pdf&#xD;&#xA;  [6]: https://www.nvidia.in/docs/IO/77714/sbvh.pdf&#xD;&#xA;  [7]: https://raytracing-docs.nvidia.com/optix/guide/nvidia_optix_programming_guide.180313.A4.pdf&#xD;&#xA;  [8]: https://computergraphics.stackexchange.com/a/10106/5681" ContentLicense="CC BY-SA 4.0" />
  <row Id="29368" PostHistoryTypeId="50" PostId="8321" RevisionGUID="288e52b1-353d-43b4-8ad8-01ee71648c80" CreationDate="2020-08-23T04:06:35.610" UserId="-1" />
  <row Id="29369" PostHistoryTypeId="2" PostId="10144" RevisionGUID="dfa404c2-b5f7-422e-8490-ceafa0cfcde2" CreationDate="2020-08-23T05:28:21.847" UserId="13847" Text="I'd like to try to write some C code to create similar animated graphics to these, which are from a very old Commodore 64 game called &quot;The Sentinel&quot;.  I've been researching but I can't seem to find if there is terminology that would lead me to information/algorithms on how to implement this sort of thing.  Does anyone know what terminology relates to this sort of super low poly/resolution terrain generation?&#xD;&#xA;&#xD;&#xA;thanks&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/E11OT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A3Dw9.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/2xK65.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/anhVJ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29370" PostHistoryTypeId="1" PostId="10144" RevisionGUID="dfa404c2-b5f7-422e-8490-ceafa0cfcde2" CreationDate="2020-08-23T05:28:21.847" UserId="13847" Text="Is there a term for this sort of graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29371" PostHistoryTypeId="3" PostId="10144" RevisionGUID="dfa404c2-b5f7-422e-8490-ceafa0cfcde2" CreationDate="2020-08-23T05:28:21.847" UserId="13847" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29372" PostHistoryTypeId="50" PostId="8695" RevisionGUID="ee3fb21e-f5d2-45b2-b386-fdcef216abe0" CreationDate="2020-08-23T19:02:25.250" UserId="-1" />
  <row Id="29373" PostHistoryTypeId="2" PostId="10145" RevisionGUID="be69d165-a7db-49c9-a0f5-3bc84b500d9d" CreationDate="2020-08-23T21:39:44.260" UserId="13869" Text="If the terrain is indeed represented by a 3D mesh as it looks like in the images, then I'm not aware of any specific terminology (and I dont believe there might be one). &#xD;&#xA;&#xD;&#xA;I could say it was similar to a faceted shading model, but shading looks very rudimentary and lighting computations might not exist at all.&#xD;&#xA;&#xD;&#xA;In case you intend to replicate these looks, I'm afraid you already hinted how to proceed very low-polygon non-textured meshes and no lighting." ContentLicense="CC BY-SA 4.0" />
  <row Id="29374" PostHistoryTypeId="2" PostId="10146" RevisionGUID="4f56ddc1-5e70-44c9-9fa4-6f0fdafd88ab" CreationDate="2020-08-24T01:58:23.910" UserId="13864" Text="I was trying to do importance sampling on lambertian surface.At first I uniformly choose direction from unit sphere. &#xD;&#xA;    &#xD;&#xA;    vec3 direction = camera-&gt;genDirection();&#xD;&#xA;    ...&#xD;&#xA;    direction = random_in_unit_sphere();&#xD;&#xA;    float cosine = cosp(direction,surfaceNormal);&#xD;&#xA;    /*&#xD;&#xA;    float cosp(float val){&#xD;&#xA;    val = cos(val);&#xD;&#xA;    if(val&gt;0.0001f) return val;&#xD;&#xA;    else return 0.0001f;&#xD;&#xA;    }&#xD;&#xA;    */&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;//lambertian&#xD;&#xA;    vec3 pdf = 1.0f/(2.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;With 10 samples per pixel,yields:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;then I choose random direction from the unit hemisphere above the surface&#xD;&#xA;&#xD;&#xA;    direction = random_in_unit_hemisphere(surfaceNormal);&#xD;&#xA;    float cosine = cosp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = 1.0f/(1.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;the result is very similar,except for less noise&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and then I use the importance sampling method from (http://in1weekend.blogspot.com/)&#xD;&#xA;&#xD;&#xA;    	class onb {&#xD;&#xA;	public:&#xD;&#xA;		vec3 operator[](int i)const { return axis[i]; }&#xD;&#xA;		vec3 u()const { return axis[0]; }&#xD;&#xA;		vec3 v()const { return axis[1]; }&#xD;&#xA;		vec3 w()const { return axis[2]; }&#xD;&#xA;		vec3 local(float a, float b, float c) { return a * u() + b * v() + c * w(); }&#xD;&#xA;		vec3 local(const vec3&amp; a) { return a.x * u() + a.y * v() + a.z * w(); }&#xD;&#xA;		void buildFromNormal(const vec3&amp; n) {&#xD;&#xA;			axis[2] = normalize(n);&#xD;&#xA;			vec3 a;&#xD;&#xA;			if (std::abs(w().x) &gt; 0.9f)&#xD;&#xA;				a = vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;			else&#xD;&#xA;				a = vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;			axis[1] = normalize(cross(w(), a));&#xD;&#xA;			axis[0] = cross(w(), v());&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	private:&#xD;&#xA;		vec3 axis[3];&#xD;&#xA;	};&#xD;&#xA;	vec3 randCosDir() {&#xD;&#xA;		float r1 = randFloat01();&#xD;&#xA;		float r2 = randFloat01();&#xD;&#xA;		float z = sqrt(1.0f - r2);&#xD;&#xA;		float phi = 2.0f * Pi * r1;&#xD;&#xA;		float x = cos(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		float y = sin(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		return vec3(x, y, z);&#xD;&#xA;	}&#xD;&#xA;,&#xD;&#xA;&#xD;&#xA;    onb uvw;&#xD;&#xA;	uvw.buildFromNormal(surfaceNormal);&#xD;&#xA;	direction = normalize(uvw.local(randCosDir()));&#xD;&#xA;    float cosine = cosp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = dot(uvw.w(), direction)/Pi;&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;however the result is different:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The baseColor of the wall is vec3(0.8f,0.8f,0.8f),and the color of the dome light is vec3(1.0f,1.0f,1.0f).&#xD;&#xA;In some tutorial the cosine item is inside the lambertian brdf,and some are in the render equation,and in&#xD;&#xA;http://in1weekend.blogspot.com/ &quot;weekend one&quot; there is no cosine item at all.I really get messed with those concepts.Is there any one help me?thanks so much.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PCAdE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/OEcgs.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/klRtz.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29375" PostHistoryTypeId="1" PostId="10146" RevisionGUID="4f56ddc1-5e70-44c9-9fa4-6f0fdafd88ab" CreationDate="2020-08-24T01:58:23.910" UserId="13864" Text="issue with importance sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="29376" PostHistoryTypeId="3" PostId="10146" RevisionGUID="4f56ddc1-5e70-44c9-9fa4-6f0fdafd88ab" CreationDate="2020-08-24T01:58:23.910" UserId="13864" Text="|pathtracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29377" PostHistoryTypeId="5" PostId="10146" RevisionGUID="d208d2d4-1d2e-40c4-8d51-d1cd6c1710dd" CreationDate="2020-08-24T10:06:29.963" UserId="13864" Comment="added 1 character in body" Text="I was trying to do importance sampling on lambertian surface.At first I uniformly choose direction from unit sphere. &#xD;&#xA;    &#xD;&#xA;    vec3 direction = camera-&gt;genDirection();&#xD;&#xA;    ...&#xD;&#xA;    direction = random_in_unit_sphere();&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    /*&#xD;&#xA;    float dotp(float val){&#xD;&#xA;    val = dot(val);&#xD;&#xA;    if(val&gt;0.0001f) return val;&#xD;&#xA;    else return 0.0001f;&#xD;&#xA;    }&#xD;&#xA;    */&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;//lambertian&#xD;&#xA;    vec3 pdf = 1.0f/(2.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;With 10 samples per pixel,yields:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;then I choose random direction from the unit hemisphere above the surface&#xD;&#xA;&#xD;&#xA;    direction = random_in_unit_hemisphere(surfaceNormal);&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = 1.0f/(1.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;the result is very similar,except for less noise&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and then I use the importance sampling method from (http://in1weekend.blogspot.com/)&#xD;&#xA;&#xD;&#xA;    	class onb {&#xD;&#xA;	public:&#xD;&#xA;		vec3 operator[](int i)const { return axis[i]; }&#xD;&#xA;		vec3 u()const { return axis[0]; }&#xD;&#xA;		vec3 v()const { return axis[1]; }&#xD;&#xA;		vec3 w()const { return axis[2]; }&#xD;&#xA;		vec3 local(float a, float b, float c) { return a * u() + b * v() + c * w(); }&#xD;&#xA;		vec3 local(const vec3&amp; a) { return a.x * u() + a.y * v() + a.z * w(); }&#xD;&#xA;		void buildFromNormal(const vec3&amp; n) {&#xD;&#xA;			axis[2] = normalize(n);&#xD;&#xA;			vec3 a;&#xD;&#xA;			if (std::abs(w().x) &gt; 0.9f)&#xD;&#xA;				a = vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;			else&#xD;&#xA;				a = vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;			axis[1] = normalize(cross(w(), a));&#xD;&#xA;			axis[0] = cross(w(), v());&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	private:&#xD;&#xA;		vec3 axis[3];&#xD;&#xA;	};&#xD;&#xA;	vec3 randCosDir() {&#xD;&#xA;		float r1 = randFloat01();&#xD;&#xA;		float r2 = randFloat01();&#xD;&#xA;		float z = sqrt(1.0f - r2);&#xD;&#xA;		float phi = 2.0f * Pi * r1;&#xD;&#xA;		float x = cos(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		float y = sin(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		return vec3(x, y, z);&#xD;&#xA;	}&#xD;&#xA;,&#xD;&#xA;&#xD;&#xA;    onb uvw;&#xD;&#xA;	uvw.buildFromNormal(surfaceNormal);&#xD;&#xA;	direction = normalize(uvw.local(randCosDir()));&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = dotp(uvw.w(), direction)/Pi;&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;however the result is different:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The baseColor of the wall is vec3(0.8f,0.8f,0.8f),and the color of the dome light is vec3(1.0f,1.0f,1.0f).&#xD;&#xA;In some tutorial the cosine item is inside the lambertian brdf,and some are in the render equation,and in&#xD;&#xA;http://in1weekend.blogspot.com/ &quot;weekend one&quot; there is no cosine item at all.I really get messed with those concepts.Is there any one help me?thanks so much.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PCAdE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/OEcgs.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/klRtz.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29378" PostHistoryTypeId="5" PostId="10146" RevisionGUID="e7251fe8-d318-45be-b7ed-3c5d970fe589" CreationDate="2020-08-24T11:28:32.513" UserId="13864" Comment="added 85 characters in body" Text="I was trying to do importance sampling on lambertian surface.At first I uniformly choose direction from unit sphere. &#xD;&#xA;    &#xD;&#xA;    vec3 direction = camera-&gt;genDirection();&#xD;&#xA;    ...&#xD;&#xA;    direction = random_in_unit_sphere();&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    /*&#xD;&#xA;    float dotp(float val){&#xD;&#xA;    val = dot(val);&#xD;&#xA;    if(val&gt;0.0001f) return val;&#xD;&#xA;    else return 0.0001f;&#xD;&#xA;    }&#xD;&#xA;    */&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;//lambertian&#xD;&#xA;    vec3 pdf = 1.0f/(2.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;With 10 samples per pixel,yields:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;then I choose random direction from the unit hemisphere above the surface&#xD;&#xA;&#xD;&#xA;    direction = random_in_unit_hemisphere(surfaceNormal);&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = 1.0f/(1.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;the result is very similar,except for less noise&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and then I use the importance sampling method from (http://in1weekend.blogspot.com/)&#xD;&#xA;&#xD;&#xA;    	class onb {&#xD;&#xA;	public:&#xD;&#xA;		vec3 operator[](int i)const { return axis[i]; }&#xD;&#xA;		vec3 u()const { return axis[0]; }&#xD;&#xA;		vec3 v()const { return axis[1]; }&#xD;&#xA;		vec3 w()const { return axis[2]; }&#xD;&#xA;		vec3 local(float a, float b, float c) { return a * u() + b * v() + c * w(); }&#xD;&#xA;		vec3 local(const vec3&amp; a) { return a.x * u() + a.y * v() + a.z * w(); }&#xD;&#xA;		void buildFromNormal(const vec3&amp; n) {&#xD;&#xA;			axis[2] = normalize(n);&#xD;&#xA;			vec3 a;&#xD;&#xA;			if (std::abs(w().x) &gt; 0.9f)&#xD;&#xA;				a = vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;			else&#xD;&#xA;				a = vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;			axis[1] = normalize(cross(w(), a));&#xD;&#xA;			axis[0] = cross(w(), v());&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	private:&#xD;&#xA;		vec3 axis[3];&#xD;&#xA;	};&#xD;&#xA;	vec3 randCosDir() {&#xD;&#xA;		float r1 = randFloat01();&#xD;&#xA;		float r2 = randFloat01();&#xD;&#xA;		float z = sqrt(1.0f - r2);&#xD;&#xA;		float phi = 2.0f * Pi * r1;&#xD;&#xA;		float x = cos(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		float y = sin(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		return vec3(x, y, z);&#xD;&#xA;	}&#xD;&#xA;,&#xD;&#xA;&#xD;&#xA;    onb uvw;&#xD;&#xA;	uvw.buildFromNormal(surfaceNormal);&#xD;&#xA;	direction = normalize(uvw.local(randCosDir()));&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = dotp(uvw.w(), direction)/Pi;&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;however the result is different:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The baseColor of the wall is vec3(0.8f,0.8f,0.8f),and the color of the dome light is vec3(1.0f,1.0f,1.0f).&#xD;&#xA;In some tutorial the cosine item is inside the lambertian brdf,and some are in the render equation,and in&#xD;&#xA;http://in1weekend.blogspot.com/ &quot;weekend one&quot; there is no cosine item at all.I really get messed with those concepts.Is there any one help me?thanks so much.&#xD;&#xA;&#xD;&#xA;10,000 samples per pixel with uniform hemisphere sampling:&#xD;&#xA;[![][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PCAdE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/OEcgs.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/klRtz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/CcPDQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29379" PostHistoryTypeId="5" PostId="10138" RevisionGUID="f3276c7d-5692-45d6-acb3-ca72d9fd6d7a" CreationDate="2020-08-24T11:44:29.973" UserId="13861" Comment="added 258 characters in body" Text="I have this image below, I want to get rid of the text 'MSAR IDs' that is in the background. I am extracting the numbers from the image with OCR, the numbers that have a white background get extracted as is, however the numbers that have the text behind them don't get extracted properly and are not correct because they all have some part of the background text behind them. Can anyone please tell me how to get rid of the big text in background, any software will do for me.&#xD;&#xA;&#xD;&#xA;(edit)PS- I got information that MSAR IDs are intellectual property of a company so to be clear I got this as part of a freelance work, my work is to put the numbers in an excel, so I was thinking of making my work a bit easier hence put up this post&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29380" PostHistoryTypeId="5" PostId="10146" RevisionGUID="6da257f3-b145-4de0-af1d-71c16f40d0ca" CreationDate="2020-08-24T11:57:55.850" UserId="13864" Comment="added 299 characters in body" Text="I was trying to do importance sampling on lambertian surface.At first I uniformly choose direction from unit sphere. &#xD;&#xA;    &#xD;&#xA;    vec3 direction = camera-&gt;genDirection();&#xD;&#xA;    ...&#xD;&#xA;    direction = random_in_unit_sphere();&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    /*&#xD;&#xA;    float dotp(float val){&#xD;&#xA;    val = dot(val);&#xD;&#xA;    if(val&gt;0.0001f) return val;&#xD;&#xA;    else return 0.0001f;&#xD;&#xA;    }&#xD;&#xA;    */&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;//lambertian&#xD;&#xA;    vec3 pdf = 1.0f/(2.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;With 10 samples per pixel,yields:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;then I choose random direction from the unit hemisphere above the surface&#xD;&#xA;&#xD;&#xA;    direction = random_in_unit_hemisphere(surfaceNormal);&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = 1.0f/(1.0f*Pi);&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;the result is very similar,except for less noise&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and then I use the importance sampling method from (http://in1weekend.blogspot.com/)&#xD;&#xA;&#xD;&#xA;    	class onb {&#xD;&#xA;	public:&#xD;&#xA;		vec3 operator[](int i)const { return axis[i]; }&#xD;&#xA;		vec3 u()const { return axis[0]; }&#xD;&#xA;		vec3 v()const { return axis[1]; }&#xD;&#xA;		vec3 w()const { return axis[2]; }&#xD;&#xA;		vec3 local(float a, float b, float c) { return a * u() + b * v() + c * w(); }&#xD;&#xA;		vec3 local(const vec3&amp; a) { return a.x * u() + a.y * v() + a.z * w(); }&#xD;&#xA;		void buildFromNormal(const vec3&amp; n) {&#xD;&#xA;			axis[2] = normalize(n);&#xD;&#xA;			vec3 a;&#xD;&#xA;			if (std::abs(w().x) &gt; 0.9f)&#xD;&#xA;				a = vec3(0.0f, 1.0f, 0.0f);&#xD;&#xA;			else&#xD;&#xA;				a = vec3(1.0f, 0.0f, 0.0f);&#xD;&#xA;			axis[1] = normalize(cross(w(), a));&#xD;&#xA;			axis[0] = cross(w(), v());&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	private:&#xD;&#xA;		vec3 axis[3];&#xD;&#xA;	};&#xD;&#xA;	vec3 randCosDir() {&#xD;&#xA;		float r1 = randFloat01();&#xD;&#xA;		float r2 = randFloat01();&#xD;&#xA;		float z = sqrt(1.0f - r2);&#xD;&#xA;		float phi = 2.0f * Pi * r1;&#xD;&#xA;		float x = cos(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		float y = sin(phi) * 2.0f * sqrt(r2);&#xD;&#xA;		return vec3(x, y, z);&#xD;&#xA;	}&#xD;&#xA;,&#xD;&#xA;&#xD;&#xA;    onb uvw;&#xD;&#xA;	uvw.buildFromNormal(surfaceNormal);&#xD;&#xA;	direction = normalize(uvw.local(randCosDir()));&#xD;&#xA;    float cosine = dotp(direction,surfaceNormal);&#xD;&#xA;    vec3 brdf_result = material-&gt;baseColor/Pi;&#xD;&#xA;    vec3 pdf = dotp(uvw.w(), direction)/Pi;&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;however the result is different:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The baseColor of the wall is vec3(0.8f,0.8f,0.8f),and the color of the dome light is vec3(1.0f,1.0f,1.0f).&#xD;&#xA;In some tutorial the cosine item is inside the lambertian brdf,and some are in the render equation,and in&#xD;&#xA;http://in1weekend.blogspot.com/ &quot;weekend one&quot; there is no cosine item at all.I really get messed with those concepts.Is there any one help me?thanks so much.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;another rendering with baseColor = vec3(1.0f,1.0f,1.0f) and dome color = vec3(0.5f,0.5f,0.5f)  (importance sampling)&#xD;&#xA;the average color of the final image over all pixels is vec3(0.470884f,0.470884f,0.470884f).&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;10,000 samples per pixel with uniform hemisphere sampling:&#xD;&#xA;[![][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PCAdE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/OEcgs.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/klRtz.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/hWiHg.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/CcPDQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29381" PostHistoryTypeId="2" PostId="10147" RevisionGUID="267d55c4-cf20-4260-988e-f3d384d225d1" CreationDate="2020-08-24T12:34:51.123" UserId="13864" Text="I just found that if I use pdf = 1.0f/(4.0f * Pi) in unit sphere sampling or pdf = 1.0f/(2.0f * Pi) in unit hemisphere sampling,the result are almost the same as the importance sampling one(I also get the same result when set the baseColor to vec3(0.4f,0.4f,0.4f),the half of vec3(0.8f,0.8f,0.8f).&#xD;&#xA;   And the surface area of a unit sphere is just 4.0f * Pi(I forget why I use 2.0f * Pi before).I HAVE to come to two conclusions:&#xD;&#xA;&#xD;&#xA;1: the importance sampling one is correct!&#xD;&#xA;&#xD;&#xA;2: I'm too stupid!!!!!!&#xD;&#xA;&#xD;&#xA;hope this self-answering question was helpful to you:)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29382" PostHistoryTypeId="2" PostId="10148" RevisionGUID="07096797-440e-4deb-a1f7-0a751e09839f" CreationDate="2020-08-24T12:58:49.603" UserId="7462" Text="In my HE implementation, half edges are stored in an array. When I iterate over the edges, I color all the HE black, and when I do an operation on an edge (e.g edge splitting) I mark both the current half edge and its pair blue. And in the loop I skip blue edges. &#xD;&#xA;&#xD;&#xA;This essentially stops me from applying the same operation to an edge twice.&#xD;&#xA;This however requires O(n) additional memory and iterating over every edge twice (once for each of the HE that compose the edge.) &#xD;&#xA;&#xD;&#xA;        for(uint i=0; i &lt; edge_num; i++)&#xD;&#xA;        {&#xD;&#xA;            if(mesh.edges[i].color != BLUE)&#xD;&#xA;            {&#xD;&#xA;                /*Do stuff*/&#xD;&#xA;               mesh.edges[i].color = BLUE;&#xD;&#xA;               mesh.edges[i].pair.color = BLUE;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;I am wondering if there is a smarter way. In particular, a way that avoids branching. I know I could do something like depth first search or breath first search, but that's likely to be slower than just skipping over edges." ContentLicense="CC BY-SA 4.0" />
  <row Id="29383" PostHistoryTypeId="1" PostId="10148" RevisionGUID="07096797-440e-4deb-a1f7-0a751e09839f" CreationDate="2020-08-24T12:58:49.603" UserId="7462" Text="Smart half edge iteration?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29384" PostHistoryTypeId="3" PostId="10148" RevisionGUID="07096797-440e-4deb-a1f7-0a751e09839f" CreationDate="2020-08-24T12:58:49.603" UserId="7462" Text="|computational-geometry|geometry|mesh|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29385" PostHistoryTypeId="5" PostId="10147" RevisionGUID="e7f42bd1-2985-45f8-8732-a531049b7328" CreationDate="2020-08-24T14:02:13.610" UserId="13864" Comment="deleted 58 characters in body" Text="I just found that if I use pdf = 1.0f/(4.0f * Pi) in unit sphere sampling or pdf = 1.0f/(2.0f * Pi) in unit hemisphere sampling,the result are almost the same as the importance sampling one(I also get the same result when set the baseColor to vec3(0.4f,0.4f,0.4f),the half of vec3(0.8f,0.8f,0.8f).&#xD;&#xA;   And the surface area of a unit sphere is just 4.0f * Pi(I forget why I use 2.0f * Pi before).I HAVE to come to two conclusions:&#xD;&#xA;&#xD;&#xA;1: the importance sampling one is correct!&#xD;&#xA;&#xD;&#xA;2: I'm too stupid!!!!!!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29388" PostHistoryTypeId="50" PostId="8779" RevisionGUID="8cd29413-bf71-45a1-ac9e-1982ad6f6277" CreationDate="2020-08-24T19:02:15.183" UserId="-1" />
  <row Id="29389" PostHistoryTypeId="50" PostId="5697" RevisionGUID="80e8cfdb-c495-44a0-8d91-852e1a52f3e7" CreationDate="2020-08-25T04:07:40.917" UserId="-1" />
  <row Id="29390" PostHistoryTypeId="2" PostId="10150" RevisionGUID="b4b73a58-4506-44c7-8478-9074edd7a52b" CreationDate="2020-08-25T22:02:25.567" UserId="13879" Text="&#xD;&#xA;How can I compute the gradient for a tetrahedral mesh (3D)? For triangular mesh, I got an answer from the following post &lt;https://computergraphics.stackexchange.com/questions/8835/calculating-the-gradient-of-a-triangular-mesh&gt;&#xD;&#xA;&#xD;&#xA;How can I get a similar formula for 3D mesh?&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="29391" PostHistoryTypeId="1" PostId="10150" RevisionGUID="b4b73a58-4506-44c7-8478-9074edd7a52b" CreationDate="2020-08-25T22:02:25.567" UserId="13879" Text="Calculating the gradient of a tetrahedral mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="29392" PostHistoryTypeId="3" PostId="10150" RevisionGUID="b4b73a58-4506-44c7-8478-9074edd7a52b" CreationDate="2020-08-25T22:02:25.567" UserId="13879" Text="|computational-geometry|mesh|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29393" PostHistoryTypeId="50" PostId="9640" RevisionGUID="a6ae133b-430e-484f-ac5f-dd6b39a99b89" CreationDate="2020-08-26T00:05:15.553" UserId="-1" />
  <row Id="29394" PostHistoryTypeId="50" PostId="8721" RevisionGUID="03d629f0-29d3-48d3-a335-f8b686ffd196" CreationDate="2020-08-26T09:02:20.253" UserId="-1" />
  <row Id="29395" PostHistoryTypeId="5" PostId="9895" RevisionGUID="4e9b0a5c-d9e5-48ef-936a-0696c374b426" CreationDate="2020-08-26T16:03:48.453" UserId="2654" Comment="deleted 43 characters in body" Text="BC7 always effectively encodes 4 channels. That's part of the nature of the format. Turning on alpha means that the compressor will read and use the alpha value in your source image, but that's all.&#xD;&#xA;&#xD;&#xA;All BC7 compressed images of a given dimension have the same size, since BC7 compresses each 4x4 group of texels into 128-bits. But that doesn't mean they have the same *quality*.&#xD;&#xA;&#xD;&#xA;BC7 is an adaptive encoding format. While each block has a fixed size (both spatially and bit-wise), each block stores how many channels that block actually compresses and the way that they correlate with one another. The [specifics are complex][1], but the general upside is that the compressor figures out on a per-block basis what manner of compression works best for a particular block. If the compressor can look at a block and see that the alpha for all texels is 1.0, then it can spend more bits of the 128 bits on the colors and fewer on the alpha.&#xD;&#xA;&#xD;&#xA;As such, a texture &quot;without alpha&quot; is exactly like a texture with alpha where every texel has an alpha of 1. These blocks will spend the majority of their bits on the non-alpha parts of the texels, only wasting a few bits on a &quot;mode&quot; field that lets the decompressor know that the alpha is a constant 1.0.&#xD;&#xA;&#xD;&#xA;This also means that, if your texture has a varying alpha, but parts of it have a constant alpha, BC7 can encode these constant alpha areas with fewer bits, so that more bits can be spent on improved color encoding.&#xD;&#xA;&#xD;&#xA;So you shouldn't feel that there is a problem because the two compression switches came out with the same number of bytes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#bptc_bc7" ContentLicense="CC BY-SA 4.0" />
  <row Id="29396" PostHistoryTypeId="2" PostId="10151" RevisionGUID="1e56fa6b-b69c-44f9-9446-f983eeb3660c" CreationDate="2020-08-26T17:44:50.003" UserId="10129" Text="I am getting this error when creating RTPSO with multiple hit groups:&#xD;&#xA;&#xD;&#xA;    D3D12 ERROR: ID3D12Device::CreateStateObject: Export &quot;MissIndirect&quot; (mangled name: &quot;\01?MissIndirect@@YAXURayPayload@@@Z&quot;) already defined. [ STATE_CREATION ERROR #1194: CREATE_STATE_OBJECT_ERROR]&#xD;&#xA;&#xD;&#xA;With single hit group I am not getting any errors and code below works correctly:&#xD;&#xA;&#xD;&#xA;    void RaytracingResources::CreateRTPSO(ID3D12Device5* device, size_t maxPayloadSize)&#xD;&#xA;    {&#xD;&#xA;        // Need 11 subobjects:&#xD;&#xA;        // 1 for RGS program&#xD;&#xA;        // 1 for Miss program&#xD;&#xA;        // 1 for CHS program&#xD;&#xA;        // 1 for AHS program&#xD;&#xA;        // 1 for Hit Group&#xD;&#xA;        // 2 for RayGen Root Signature (root-signature and association)&#xD;&#xA;        // 2 for Shader Config (config and association)&#xD;&#xA;        // 1 for Global Root Signature&#xD;&#xA;        // 1 for Pipeline Config	&#xD;&#xA;        UINT index = 0;&#xD;&#xA;        std::vector&lt;D3D12_STATE_SUBOBJECT&gt; subobjects;&#xD;&#xA;        size_t size = 0;&#xD;&#xA;        size += 1; // rgs&#xD;&#xA;        for (auto&amp; hitGroup : m_hitGroups)&#xD;&#xA;        {&#xD;&#xA;            size += 2; // chs, miss&#xD;&#xA;            size += (hitGroup.hitShader.ahs.name != nullptr) ? 1 : 0; // ahs&#xD;&#xA;            size += 1; // hit group&#xD;&#xA;            size += 2; // payload + association&#xD;&#xA;            size += 2; // local root + association&#xD;&#xA;        }&#xD;&#xA;        size += 2; // global root + pipeline config&#xD;&#xA;        subobjects.resize(size);&#xD;&#xA;    &#xD;&#xA;        std::vector&lt;LPCWSTR&gt; usedNames;&#xD;&#xA;        std::vector&lt;IDxcBlob&gt; usedBlobs;&#xD;&#xA;    &#xD;&#xA;        // Add state subobject for the RGS&#xD;&#xA;        {&#xD;&#xA;            D3D12_EXPORT_DESC rgsExportDesc = { m_hitGroups[0].rayGenShader.name, nullptr, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;            D3D12_DXIL_LIBRARY_DESC	rgsLibDesc = {};&#xD;&#xA;            rgsLibDesc.DXILLibrary.BytecodeLength = m_hitGroups[0].rayGenShader.blob-&gt;GetBufferSize();&#xD;&#xA;            rgsLibDesc.DXILLibrary.pShaderBytecode = m_hitGroups[0].rayGenShader.blob-&gt;GetBufferPointer();&#xD;&#xA;            rgsLibDesc.NumExports = 1;&#xD;&#xA;            rgsLibDesc.pExports = &amp;rgsExportDesc;&#xD;&#xA;    &#xD;&#xA;            D3D12_STATE_SUBOBJECT rgs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;rgsLibDesc };&#xD;&#xA;            subobjects[index++] = rgs;&#xD;&#xA;            usedNames.push_back(m_hitGroups[0].rayGenShader.name);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (auto&amp; hitGroup : m_hitGroups)&#xD;&#xA;        {&#xD;&#xA;            //Add state subobject for the Miss shader&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC msExportDesc = { hitGroup.missShader.name, hitGroup.missShader.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	msLibDesc = {};&#xD;&#xA;                msLibDesc.DXILLibrary.BytecodeLength = hitGroup.missShader.blob-&gt;GetBufferSize();&#xD;&#xA;                msLibDesc.DXILLibrary.pShaderBytecode = hitGroup.missShader.blob-&gt;GetBufferPointer();&#xD;&#xA;                msLibDesc.NumExports = 1;&#xD;&#xA;                msLibDesc.pExports = &amp;msExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT ms = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;msLibDesc };&#xD;&#xA;                subobjects[index++] = ms;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add state subobject for the Closest Hit shader&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC chsExportDesc = { hitGroup.hitShader.chs.name, hitGroup.hitShader.chs.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	chsLibDesc = {};&#xD;&#xA;                chsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.chs.blob-&gt;GetBufferSize();&#xD;&#xA;                chsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.chs.blob-&gt;GetBufferPointer();&#xD;&#xA;                chsLibDesc.NumExports = 1;&#xD;&#xA;                chsLibDesc.pExports = &amp;chsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT chs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;chsLibDesc };&#xD;&#xA;                subobjects[index++] = chs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add state subobject for the Any Hit shader&#xD;&#xA;            if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC ahsExportDesc = { hitGroup.hitShader.ahs.name, hitGroup.hitShader.ahs.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	ahsLibDesc = {};&#xD;&#xA;                ahsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.ahs.blob-&gt;GetBufferSize();&#xD;&#xA;                ahsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.ahs.blob-&gt;GetBufferPointer();&#xD;&#xA;                ahsLibDesc.NumExports = 1;&#xD;&#xA;                ahsLibDesc.pExports = &amp;ahsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT ahs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;ahsLibDesc };&#xD;&#xA;                subobjects[index++] = ahs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the hit group&#xD;&#xA;            {&#xD;&#xA;                D3D12_HIT_GROUP_DESC hitGroupDesc = {};&#xD;&#xA;                hitGroupDesc.ClosestHitShaderImport = hitGroup.hitShader.chs.name;&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr) hitGroupDesc.AnyHitShaderImport = hitGroup.hitShader.ahs.name;&#xD;&#xA;                hitGroupDesc.HitGroupExport = hitGroup.hitGroupName;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT hitGroup = { D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &amp;hitGroupDesc };&#xD;&#xA;                subobjects[index++] = hitGroup;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the shader payload configuration&#xD;&#xA;            {&#xD;&#xA;                D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = { static_cast&lt;UINT&gt;(maxPayloadSize), D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES };&#xD;&#xA;                D3D12_STATE_SUBOBJECT shaderConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &amp;shaderDesc };&#xD;&#xA;                subobjects[index++] = shaderConfigObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Create a list of the shader export names that use the payload&#xD;&#xA;            {&#xD;&#xA;                D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr) {&#xD;&#xA;                    const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                    shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };&#xD;&#xA;                }&#xD;&#xA;                else {&#xD;&#xA;                    const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                    shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT shaderPayloadAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;shaderPayloadAssociation };&#xD;&#xA;                subobjects[index++] = shaderPayloadAssociationObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the shared root signature &#xD;&#xA;            {&#xD;&#xA;                D3D12_STATE_SUBOBJECT rayGenRootSigObject = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &amp;hitGroup.rayGenShader.pRootSignature };&#xD;&#xA;                subobjects[index++] = rayGenRootSigObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Create a list of the shader export names that use the root signature&#xD;&#xA;            {&#xD;&#xA;                D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION rayGenShaderRootSigAssociation = {};&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;                {&#xD;&#xA;                    const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                    rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                    rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT rayGenShaderRootSigAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;rayGenShaderRootSigAssociation };&#xD;&#xA;                subobjects[index++] = rayGenShaderRootSigAssociationObject;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Setup global root signature&#xD;&#xA;        {&#xD;&#xA;            D3D12_STATE_SUBOBJECT globalRootSig = { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &amp;m_hitGroups[0].missShader.pRootSignature };&#xD;&#xA;            subobjects[index++] = globalRootSig;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Add a state subobject for the ray tracing pipeline config&#xD;&#xA;        {&#xD;&#xA;            D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = { 1 }; // Max Trace Recursion Depth&#xD;&#xA;            D3D12_STATE_SUBOBJECT pipelineConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &amp;pipelineConfig };&#xD;&#xA;            subobjects[index++] = pipelineConfigObject; &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Finish rtpso creation and store in variable&#xD;&#xA;        {&#xD;&#xA;            // Describe RTPSO&#xD;&#xA;            D3D12_STATE_OBJECT_DESC pipelineDesc = { D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE, static_cast&lt;UINT&gt;(subobjects.size()), subobjects.data() };&#xD;&#xA;    &#xD;&#xA;            // Create the RT Pipeline State Object (RTPSO) / Get the RTPSO properties&#xD;&#xA;            ThrowIfFailed(device-&gt;CreateStateObject(&amp;pipelineDesc, IID_PPV_ARGS(&amp;m_rtpso)));&#xD;&#xA;            ThrowIfFailed(m_rtpso-&gt;QueryInterface(IID_PPV_ARGS(&amp;m_rtpsoInfo)));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am calling it with code below:&#xD;&#xA;&#xD;&#xA;    CreateRayGenShader(rayGenShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, 2, 1, 5, {}, L&quot;RayGen&quot;);&#xD;&#xA;    CreateMissShader(missShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, L&quot;Miss&quot;);&#xD;&#xA;    CreateClosestHitShader(hitShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, L&quot;ClosestHit&quot;);&#xD;&#xA;&#xD;&#xA;    CreateMissShader(missShader_new, m_shaderCompiler, L&quot;Shaders/RT_Lambertian_Indirect.hlsl&quot;, L&quot;MissIndirect&quot;);&#xD;&#xA;    CreateClosestHitShader(hitShader_new, m_shaderCompiler, L&quot;Shaders/RT_Lambertian_Indirect.hlsl&quot;, L&quot;ClosestHitIndirect&quot;);&#xD;&#xA;    &#xD;&#xA;    HitGroup group = { rayGenShader, missShader, hitShader, L&quot;GroupLambert&quot; };&#xD;&#xA;    HitGroup group_new = { rayGenShader, missShader_new, hitShader_new, L&quot;GroupLambert_new&quot; };&#xD;&#xA;    &#xD;&#xA;    m_raytracingLambert = std::shared_ptr&lt;RaytracingResources&gt;(new RaytracingResources(m_device.Get(), m_commandList, model, { group, group_new }));" ContentLicense="CC BY-SA 4.0" />
  <row Id="29397" PostHistoryTypeId="1" PostId="10151" RevisionGUID="1e56fa6b-b69c-44f9-9446-f983eeb3660c" CreationDate="2020-08-26T17:44:50.003" UserId="10129" Text="Hit group - export already defined" ContentLicense="CC BY-SA 4.0" />
  <row Id="29398" PostHistoryTypeId="3" PostId="10151" RevisionGUID="1e56fa6b-b69c-44f9-9446-f983eeb3660c" CreationDate="2020-08-26T17:44:50.003" UserId="10129" Text="|raytracing|c++|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29399" PostHistoryTypeId="5" PostId="10138" RevisionGUID="9fe1b507-b493-48fb-a781-a99daf45252a" CreationDate="2020-08-26T20:51:37.680" UserId="13861" Comment="deleted 71 characters in body" Text="I have this image below, I want to get rid of the text 'MSAR IDs' that is in the background. I am extracting the numbers from the image with OCR, the numbers that have a white background get extracted as is, however the numbers that have the text behind them don't get extracted properly and are not correct because they all have some part of the background text behind them. Can anyone please tell me how to get rid of the big text in background, any software will do for me.&#xD;&#xA;&#xD;&#xA;(edit)PS- I got information that MSAR IDs are intellectual property of a company so to be clear I got this as part of a freelance work, my work is to put the numbers in an excel, so I was thinking of making my work a bit easier hence put up this post" ContentLicense="CC BY-SA 4.0" />
  <row Id="29400" PostHistoryTypeId="2" PostId="10152" RevisionGUID="1a327035-5385-49fe-9eeb-e11c5a58acd6" CreationDate="2020-08-26T20:58:40.563" UserId="13861" Text="Got this resolved by using Google's API Vision&#xD;&#xA;https://cloud.google.com/vision" ContentLicense="CC BY-SA 4.0" />
  <row Id="29401" PostHistoryTypeId="50" PostId="8209" RevisionGUID="12124614-01a0-41d1-8534-05a42f064fef" CreationDate="2020-08-27T00:05:15.530" UserId="-1" />
  <row Id="29402" PostHistoryTypeId="5" PostId="10151" RevisionGUID="81557e63-0084-4552-8efa-c42479c045dd" CreationDate="2020-08-27T14:57:47.243" UserId="10129" Comment="added 1303 characters in body" Text="I am getting this error when creating RTPSO with multiple hit groups:&#xD;&#xA;&#xD;&#xA;    D3D12 ERROR: ID3D12Device::CreateStateObject: Export &quot;MissIndirect&quot; (mangled name: &quot;\01?MissIndirect@@YAXURayPayload@@@Z&quot;) already defined. [ STATE_CREATION ERROR #1194: CREATE_STATE_OBJECT_ERROR]&#xD;&#xA;&#xD;&#xA;With single hit group I am not getting any errors and code below works correctly:&#xD;&#xA;&#xD;&#xA;    void RaytracingResources::CreateRTPSO(ID3D12Device5* device, size_t maxPayloadSize)&#xD;&#xA;    {&#xD;&#xA;        // Need 11 subobjects:&#xD;&#xA;        // 1 for RGS program&#xD;&#xA;        // 1 for Miss program&#xD;&#xA;        // 1 for CHS program&#xD;&#xA;        // 1 for AHS program&#xD;&#xA;        // 1 for Hit Group&#xD;&#xA;        // 2 for RayGen Root Signature (root-signature and association)&#xD;&#xA;        // 2 for Shader Config (config and association)&#xD;&#xA;        // 1 for Global Root Signature&#xD;&#xA;        // 1 for Pipeline Config	&#xD;&#xA;        UINT index = 0;&#xD;&#xA;        std::vector&lt;D3D12_STATE_SUBOBJECT&gt; subobjects;&#xD;&#xA;        size_t size = 0;&#xD;&#xA;        size += 1; // rgs&#xD;&#xA;        for (auto&amp; hitGroup : m_hitGroups)&#xD;&#xA;        {&#xD;&#xA;            size += 2; // chs, miss&#xD;&#xA;            size += (hitGroup.hitShader.ahs.name != nullptr) ? 1 : 0; // ahs&#xD;&#xA;            size += 1; // hit group&#xD;&#xA;            size += 2; // payload + association&#xD;&#xA;            size += 2; // local root + association&#xD;&#xA;        }&#xD;&#xA;        size += 2; // global root + pipeline config&#xD;&#xA;        subobjects.resize(size);&#xD;&#xA;    &#xD;&#xA;        std::vector&lt;LPCWSTR&gt; usedNames;&#xD;&#xA;        std::vector&lt;IDxcBlob&gt; usedBlobs;&#xD;&#xA;    &#xD;&#xA;        // Add state subobject for the RGS&#xD;&#xA;        {&#xD;&#xA;            D3D12_EXPORT_DESC rgsExportDesc = { m_hitGroups[0].rayGenShader.name, nullptr, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;            D3D12_DXIL_LIBRARY_DESC	rgsLibDesc = {};&#xD;&#xA;            rgsLibDesc.DXILLibrary.BytecodeLength = m_hitGroups[0].rayGenShader.blob-&gt;GetBufferSize();&#xD;&#xA;            rgsLibDesc.DXILLibrary.pShaderBytecode = m_hitGroups[0].rayGenShader.blob-&gt;GetBufferPointer();&#xD;&#xA;            rgsLibDesc.NumExports = 1;&#xD;&#xA;            rgsLibDesc.pExports = &amp;rgsExportDesc;&#xD;&#xA;    &#xD;&#xA;            D3D12_STATE_SUBOBJECT rgs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;rgsLibDesc };&#xD;&#xA;            subobjects[index++] = rgs;&#xD;&#xA;            usedNames.push_back(m_hitGroups[0].rayGenShader.name);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (auto&amp; hitGroup : m_hitGroups)&#xD;&#xA;        {&#xD;&#xA;            //Add state subobject for the Miss shader&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC msExportDesc = { hitGroup.missShader.name, hitGroup.missShader.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	msLibDesc = {};&#xD;&#xA;                msLibDesc.DXILLibrary.BytecodeLength = hitGroup.missShader.blob-&gt;GetBufferSize();&#xD;&#xA;                msLibDesc.DXILLibrary.pShaderBytecode = hitGroup.missShader.blob-&gt;GetBufferPointer();&#xD;&#xA;                msLibDesc.NumExports = 1;&#xD;&#xA;                msLibDesc.pExports = &amp;msExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT ms = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;msLibDesc };&#xD;&#xA;                subobjects[index++] = ms;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add state subobject for the Closest Hit shader&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC chsExportDesc = { hitGroup.hitShader.chs.name, hitGroup.hitShader.chs.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	chsLibDesc = {};&#xD;&#xA;                chsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.chs.blob-&gt;GetBufferSize();&#xD;&#xA;                chsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.chs.blob-&gt;GetBufferPointer();&#xD;&#xA;                chsLibDesc.NumExports = 1;&#xD;&#xA;                chsLibDesc.pExports = &amp;chsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT chs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;chsLibDesc };&#xD;&#xA;                subobjects[index++] = chs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add state subobject for the Any Hit shader&#xD;&#xA;            if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC ahsExportDesc = { hitGroup.hitShader.ahs.name, hitGroup.hitShader.ahs.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	ahsLibDesc = {};&#xD;&#xA;                ahsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.ahs.blob-&gt;GetBufferSize();&#xD;&#xA;                ahsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.ahs.blob-&gt;GetBufferPointer();&#xD;&#xA;                ahsLibDesc.NumExports = 1;&#xD;&#xA;                ahsLibDesc.pExports = &amp;ahsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT ahs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;ahsLibDesc };&#xD;&#xA;                subobjects[index++] = ahs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the hit group&#xD;&#xA;            {&#xD;&#xA;                D3D12_HIT_GROUP_DESC hitGroupDesc = {};&#xD;&#xA;                hitGroupDesc.ClosestHitShaderImport = hitGroup.hitShader.chs.name;&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr) hitGroupDesc.AnyHitShaderImport = hitGroup.hitShader.ahs.name;&#xD;&#xA;                hitGroupDesc.HitGroupExport = hitGroup.hitGroupName;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT hitGroup = { D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &amp;hitGroupDesc };&#xD;&#xA;                subobjects[index++] = hitGroup;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the shader payload configuration&#xD;&#xA;            {&#xD;&#xA;                D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = { static_cast&lt;UINT&gt;(maxPayloadSize), D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES };&#xD;&#xA;                D3D12_STATE_SUBOBJECT shaderConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &amp;shaderDesc };&#xD;&#xA;                subobjects[index++] = shaderConfigObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Create a list of the shader export names that use the payload&#xD;&#xA;            {&#xD;&#xA;                D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr) {&#xD;&#xA;                    const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                    shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };&#xD;&#xA;                }&#xD;&#xA;                else {&#xD;&#xA;                    const WCHAR* shaderExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                    shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT shaderPayloadAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;shaderPayloadAssociation };&#xD;&#xA;                subobjects[index++] = shaderPayloadAssociationObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the shared root signature &#xD;&#xA;            {&#xD;&#xA;                D3D12_STATE_SUBOBJECT rayGenRootSigObject = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &amp;hitGroup.rayGenShader.pRootSignature };&#xD;&#xA;                subobjects[index++] = rayGenRootSigObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Create a list of the shader export names that use the root signature&#xD;&#xA;            {&#xD;&#xA;                D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION rayGenShaderRootSigAssociation = {};&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;                {&#xD;&#xA;                    const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                    rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                    rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT rayGenShaderRootSigAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;rayGenShaderRootSigAssociation };&#xD;&#xA;                subobjects[index++] = rayGenShaderRootSigAssociationObject;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Setup global root signature&#xD;&#xA;        {&#xD;&#xA;            D3D12_STATE_SUBOBJECT globalRootSig = { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &amp;m_hitGroups[0].missShader.pRootSignature };&#xD;&#xA;            subobjects[index++] = globalRootSig;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Add a state subobject for the ray tracing pipeline config&#xD;&#xA;        {&#xD;&#xA;            D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = { 1 }; // Max Trace Recursion Depth&#xD;&#xA;            D3D12_STATE_SUBOBJECT pipelineConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &amp;pipelineConfig };&#xD;&#xA;            subobjects[index++] = pipelineConfigObject; &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Finish rtpso creation and store in variable&#xD;&#xA;        {&#xD;&#xA;            // Describe RTPSO&#xD;&#xA;            D3D12_STATE_OBJECT_DESC pipelineDesc = { D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE, static_cast&lt;UINT&gt;(subobjects.size()), subobjects.data() };&#xD;&#xA;    &#xD;&#xA;            // Create the RT Pipeline State Object (RTPSO) / Get the RTPSO properties&#xD;&#xA;            ThrowIfFailed(device-&gt;CreateStateObject(&amp;pipelineDesc, IID_PPV_ARGS(&amp;m_rtpso)));&#xD;&#xA;            ThrowIfFailed(m_rtpso-&gt;QueryInterface(IID_PPV_ARGS(&amp;m_rtpsoInfo)));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am calling it with code below:&#xD;&#xA;&#xD;&#xA;    CreateRayGenShader(rayGenShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, 2, 1, 5, {}, L&quot;RayGen&quot;);&#xD;&#xA;    CreateMissShader(missShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, L&quot;Miss&quot;);&#xD;&#xA;    CreateClosestHitShader(hitShader, m_shaderCompiler, L&quot;Shaders/RT_Lambertian.hlsl&quot;, L&quot;ClosestHit&quot;);&#xD;&#xA;&#xD;&#xA;    CreateMissShader(missShader_new, m_shaderCompiler, L&quot;Shaders/RT_Lambertian_Indirect.hlsl&quot;, L&quot;MissIndirect&quot;);&#xD;&#xA;    CreateClosestHitShader(hitShader_new, m_shaderCompiler, L&quot;Shaders/RT_Lambertian_Indirect.hlsl&quot;, L&quot;ClosestHitIndirect&quot;);&#xD;&#xA;    &#xD;&#xA;    HitGroup group = { rayGenShader, missShader, hitShader, L&quot;GroupLambert&quot; };&#xD;&#xA;    HitGroup group_new = { rayGenShader, missShader_new, hitShader_new, L&quot;GroupLambert_new&quot; };&#xD;&#xA;    &#xD;&#xA;    m_raytracingLambert = std::shared_ptr&lt;RaytracingResources&gt;(new RaytracingResources(m_device.Get(), m_commandList, model, { group, group_new }));&#xD;&#xA;&#xD;&#xA;**However, even when I'm trying to create single group, but I am using std::vector to iterate over rgs, ms, chs - it causes same error:** (i.e. export &quot;name&quot; already defined [ STATE_CREATION ERROR #1194: CREATE_STATE_OBJECT_ERROR]). Therefore, I am using lengthy code which is called seperately for ms, rgs, chs (and ahs if present). &#xD;&#xA;&#xD;&#xA;    std::vector&lt;RtProgram&gt; rtPrograms;&#xD;&#xA;    HitGroup hitGroup = m_hitGroups[0];&#xD;&#xA;    rtPrograms.push_back(hitGroup.rayGenShader);&#xD;&#xA;    rtPrograms.push_back(hitGroup.missShader);&#xD;&#xA;    rtPrograms.push_back(hitGroup.hitShader.chs);&#xD;&#xA;&#xD;&#xA;    for (auto&amp; shader : rtPrograms)&#xD;&#xA;    {&#xD;&#xA;        D3D12_EXPORT_DESC exportDesc = { shader.name, shader.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;&#xD;&#xA;        D3D12_DXIL_LIBRARY_DESC	libDesc = {};&#xD;&#xA;        libDesc.DXILLibrary.BytecodeLength = shader.blob-&gt;GetBufferSize();&#xD;&#xA;        libDesc.DXILLibrary.pShaderBytecode = shader.blob-&gt;GetBufferPointer();&#xD;&#xA;        libDesc.NumExports = 1;&#xD;&#xA;        libDesc.pExports = &amp;exportDesc;&#xD;&#xA;&#xD;&#xA;        D3D12_STATE_SUBOBJECT stateSubobject = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;libDesc };&#xD;&#xA;        subobjects[index++] = stateSubobject;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Repo with this code can be found here - https://github.com/komilll/RTCP/blob/0b81a41f95ae3fa536324b27201a5fce94f92f24/RTCP/Renderer.cpp#L1039" ContentLicense="CC BY-SA 4.0" />
  <row Id="29403" PostHistoryTypeId="2" PostId="10153" RevisionGUID="70490b96-4f67-407d-a52f-de0227a2312c" CreationDate="2020-08-28T12:27:42.213" UserId="10129" Text="I don't know why, but using any loop while using D3D12_DXIL_LIBRARY_DESC is causing problems. It doesn't seem that it goes out of scope, because current code is seperate by blocks with seperate scops already. Therefore I don't think that's what causes problem.&#xD;&#xA;&#xD;&#xA;I've dealt with it by simply copy-pasting code and changing index of used data, guarded with (if array.size() &gt; 1). For now, I need only two arrays, but in future, I might add multiple copy-pastes like that. Ideal solution would be either using macros or reaching dxc developers to know what causes problem. **However, for my usage purposes** it is enough solution.&#xD;&#xA;&#xD;&#xA;Also, please take a look at this link - https://www.willusher.io/graphics/2019/11/20/the-sbt-three-ways - it turns to be very useful to understand indexing of miss shader/hit groups data." ContentLicense="CC BY-SA 4.0" />
  <row Id="29404" PostHistoryTypeId="2" PostId="10154" RevisionGUID="a6410fbd-99b1-42bb-a9da-bb30882c41e8" CreationDate="2020-08-28T14:17:42.337" UserId="11388" Text="I'm currently learning compute shaders and I'm trying to write an optimized [Game Of Life][1]. I have a first version working that uses a Shader Storage Buffer Object. I dispatch a thread per cell I want to update and that thread samples the SSBO 8 times to gather the cell's neighbors. This works fine.&#xD;&#xA;&#xD;&#xA;I'm now trying to optimize this by using shared memory. Every thread in a work group will now load a single cell in shared memory wait for the memory and execution barrier to resolve and then sample the shared memory 8 times to compute its cell's state. Of course some threads need to load more than 1 cell to shared memory because if they're on the 'border' of a workgroup no thread will load the data for some of its neighbors. ( See picture )&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I got this working as well. However, it is less performant than the brute force version. ( On an RTX 2070 and GTX 660M ) I'm very surprised. I'm using Vulkan and gpu queries to estimate how long the compute pass takes. Here is for example the numbers for a 4096x4096 grid. I dispatch 256x256 thread groups of size 16x16. On my old GTX 660M compute takes ~12ms in brute force mode but it takes ~17ms with TGSM. I can't test on the RTX right now but the TGSM version was less performant as well.&#xD;&#xA;&#xD;&#xA;I was definitely expecting to see some improvement with TGSM. I need to look into it more with tools like Nvidia Nsight but I would assume this shader is limited by memory and definitely not ALU.&#xD;&#xA;I guess my questions are:&#xD;&#xA;&#xD;&#xA; - Am I correct in assuming the TGSM version should run faster somehow? Search for Neighborhood Processing [here][3]&#xD;&#xA; - If my assumption is correct, what went wrong?&#xD;&#xA;&#xD;&#xA;Here is the brute force shader:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;&#xD;&#xA;layout (constant_id = 0) const uint CELLS_COUNT          = 4096;&#xD;&#xA;layout (constant_id = 1) const uint GRID_SIZE            = 64;        &#xD;&#xA;layout (constant_id = 2) const uint THREADS_PER_GROUP_X  = 8;&#xD;&#xA;layout (constant_id = 3) const uint THREADS_PER_GROUP_Y  = 8;&#xD;&#xA;layout (constant_id = 4) const uint THREADS_PER_GROUP    = 64;&#xD;&#xA;&#xD;&#xA;layout(local_size_x_id = 2, local_size_y_id = 3) in;&#xD;&#xA;&#xD;&#xA;layout(std430, set = 0, binding = 0) buffer SrcGrid {&#xD;&#xA;    uint state[CELLS_COUNT];&#xD;&#xA;} srcGrid;&#xD;&#xA;&#xD;&#xA;layout(std430, set = 0, binding = 1) buffer DstGrid {&#xD;&#xA;    uint state[CELLS_COUNT];&#xD;&#xA;} dstGrid;&#xD;&#xA;&#xD;&#xA;const ivec2 sampleXYOffsets[] = { &#xD;&#xA;    ivec2(-1, -1),   ivec2(0, -1),  ivec2(1, -1),&#xD;&#xA;    ivec2(-1,  0),                  ivec2(1,  0),&#xD;&#xA;    ivec2(-1,  1),   ivec2(0,  1),  ivec2(1,  1),&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    &#xD;&#xA;    const uint maxIdX = gl_WorkGroupSize.x * gl_NumWorkGroups.x;&#xD;&#xA;    const uint maxIdY = gl_WorkGroupSize.y * gl_NumWorkGroups.y;&#xD;&#xA;&#xD;&#xA;    uint aliveNeighbors = 0;&#xD;&#xA;    // Convert dispatch IDs into storage buffer id&#xD;&#xA;    const uint currentCellIndex = gl_GlobalInvocationID.y * maxIdX + gl_GlobalInvocationID.x;&#xD;&#xA;    // Convert storage buffer id into grid coordinates (x, y)&#xD;&#xA;    const uvec2 currentCoords = uvec2( currentCellIndex % GRID_SIZE, currentCellIndex / GRID_SIZE);&#xD;&#xA;    for( uint i = 0; i &lt; 8; i++ ){&#xD;&#xA;&#xD;&#xA;        uvec2 coords = currentCoords;&#xD;&#xA;        // Bring everything above 0 to be able to use the modulo operator&#xD;&#xA;        coords = (coords + sampleXYOffsets[i] + GRID_SIZE) % GRID_SIZE;&#xD;&#xA;        // Convert grid coordinates (x, y) into storage buffer id&#xD;&#xA;        uint neighborIndex = coords.x + coords.y * GRID_SIZE;&#xD;&#xA;        aliveNeighbors += srcGrid.state[neighborIndex];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    uint currentCellState = srcGrid.state[currentCellIndex];&#xD;&#xA;&#xD;&#xA;    if( currentCellState &lt; 1.0 &amp;&amp; aliveNeighbors == 3 )&#xD;&#xA;    {&#xD;&#xA;        // Dead cell comes back to life&#xD;&#xA;        dstGrid.state[currentCellIndex] = 1;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Alive cell dies&#xD;&#xA;    if( aliveNeighbors &lt; 2.0 || aliveNeighbors &gt; 3.0)&#xD;&#xA;    {&#xD;&#xA;        dstGrid.state[currentCellIndex] = 0;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    dstGrid.state[currentCellIndex] = currentCellState;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And the one using TGSM:&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;&#xD;&#xA;layout (constant_id = 0) const uint CELLS_COUNT          = 4096;&#xD;&#xA;layout (constant_id = 1) const uint GRID_SIZE            = 64;        &#xD;&#xA;layout (constant_id = 2) const uint THREADS_PER_GROUP_X  = 8;&#xD;&#xA;layout (constant_id = 3) const uint THREADS_PER_GROUP_Y  = 8;&#xD;&#xA;layout (constant_id = 4) const uint THREADS_PER_GROUP    = 64;&#xD;&#xA;&#xD;&#xA;layout(local_size_x_id = 2, local_size_y_id = 3) in;&#xD;&#xA;&#xD;&#xA;layout(std430, set = 0, binding = 0) buffer SrcGrid {&#xD;&#xA;    uint state[CELLS_COUNT];&#xD;&#xA;} srcGrid;&#xD;&#xA;&#xD;&#xA;layout(std430, set = 0, binding = 1) buffer DstGrid {&#xD;&#xA;    uint state[CELLS_COUNT];&#xD;&#xA;} dstGrid;&#xD;&#xA;&#xD;&#xA;uint getSSBODataFromWorldGridCoords( uint worldGridX, uint worldGridY )&#xD;&#xA;{&#xD;&#xA;    uvec2 worldGridCoords = uvec2( worldGridX, worldGridY );&#xD;&#xA;    worldGridCoords = (worldGridCoords + GRID_SIZE) % GRID_SIZE;&#xD;&#xA;    return srcGrid.state[ worldGridCoords.x + worldGridCoords.y  * GRID_SIZE ];&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;shared uint sharedData[ THREADS_PER_GROUP_X + 2 ][ THREADS_PER_GROUP_Y + 2 ];&#xD;&#xA;&#xD;&#xA;void main() &#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;    const uvec2 workGroupSize = uvec2( THREADS_PER_GROUP_X, THREADS_PER_GROUP_Y );&#xD;&#xA;&#xD;&#xA;    // Grid coords within a thead group&#xD;&#xA;    const uvec2 localGridCoords = gl_LocalInvocationID.xy;&#xD;&#xA;    // Coordinates of each thread group tile&#xD;&#xA;    const uvec2 worldGridOffset = gl_WorkGroupID.xy * workGroupSize.xy;&#xD;&#xA;    // Grid coords within the whole game &#xD;&#xA;    const uvec2 worldGridCoords = worldGridOffset + localGridCoords; &#xD;&#xA;&#xD;&#xA;    // Early out if not in the grid&#xD;&#xA;    if( worldGridCoords.x &gt;= GRID_SIZE || worldGridCoords.y &gt;= GRID_SIZE )&#xD;&#xA;    {&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Load data into TGSM&#xD;&#xA;    const uvec2 tgsmCoords = localGridCoords + uvec2( 1, 1 );&#xD;&#xA;&#xD;&#xA;    // Top left corner &#xD;&#xA;    if( localGridCoords.x == 0 &amp;&amp; localGridCoords.y == 0 )&#xD;&#xA;    {&#xD;&#xA;        // Top&#xD;&#xA;        sharedData[ tgsmCoords.x     ][ tgsmCoords.y - 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x,     worldGridCoords.y - 1 );&#xD;&#xA;        // Top Left&#xD;&#xA;        sharedData[ tgsmCoords.x - 1 ][ tgsmCoords.y - 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x - 1, worldGridCoords.y - 1 );&#xD;&#xA;        // Left&#xD;&#xA;        sharedData[ tgsmCoords.x - 1 ][ tgsmCoords.y     ] = getSSBODataFromWorldGridCoords( worldGridCoords.x - 1, worldGridCoords.y     );&#xD;&#xA;    }&#xD;&#xA;    // Top right corner &#xD;&#xA;    else if( localGridCoords.x == workGroupSize.x - 1 &amp;&amp; localGridCoords.y == 0 )&#xD;&#xA;    {&#xD;&#xA;        // Top&#xD;&#xA;        sharedData[ tgsmCoords.x     ][ tgsmCoords.y - 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x,     worldGridCoords.y - 1 );&#xD;&#xA;        // Top Right&#xD;&#xA;        sharedData[ tgsmCoords.x + 1 ][ tgsmCoords.y - 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x + 1, worldGridCoords.y - 1 );&#xD;&#xA;        // Right&#xD;&#xA;        sharedData[ tgsmCoords.x + 1 ][ tgsmCoords.y     ] = getSSBODataFromWorldGridCoords( worldGridCoords.x + 1, worldGridCoords.y     );&#xD;&#xA;    }&#xD;&#xA;    // Bottom left corner &#xD;&#xA;    else if( localGridCoords.x == 0 &amp;&amp; localGridCoords.y == workGroupSize.y - 1 )&#xD;&#xA;    {&#xD;&#xA;        // Bottom&#xD;&#xA;        sharedData[ tgsmCoords.x     ][ tgsmCoords.y + 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x,     worldGridCoords.y + 1 );&#xD;&#xA;        // Bottom Left&#xD;&#xA;        sharedData[ tgsmCoords.x - 1 ][ tgsmCoords.y + 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x - 1, worldGridCoords.y + 1 );&#xD;&#xA;        // Left&#xD;&#xA;        sharedData[ tgsmCoords.x - 1 ][ tgsmCoords.y     ] = getSSBODataFromWorldGridCoords( worldGridCoords.x - 1, worldGridCoords.y     );&#xD;&#xA;    }&#xD;&#xA;    // Bottom right corner &#xD;&#xA;    else if( localGridCoords.x == workGroupSize.x - 1 &amp;&amp; localGridCoords.y == workGroupSize.y - 1 )&#xD;&#xA;    {&#xD;&#xA;        // Bottom&#xD;&#xA;        sharedData[ tgsmCoords.x     ][ tgsmCoords.y + 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x,     worldGridCoords.y + 1 );&#xD;&#xA;        // Bottom Right&#xD;&#xA;        sharedData[ tgsmCoords.x + 1 ][ tgsmCoords.y + 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x + 1, worldGridCoords.y + 1 );&#xD;&#xA;        // Right&#xD;&#xA;        sharedData[ tgsmCoords.x + 1 ][ tgsmCoords.y     ] = getSSBODataFromWorldGridCoords( worldGridCoords.x + 1, worldGridCoords.y     );&#xD;&#xA;    }&#xD;&#xA;    // Left Edge&#xD;&#xA;    else if( localGridCoords.x == 0 )&#xD;&#xA;    {&#xD;&#xA;        sharedData[ tgsmCoords.x - 1 ][ tgsmCoords.y     ] = getSSBODataFromWorldGridCoords( worldGridCoords.x - 1, worldGridCoords.y     );&#xD;&#xA;    }&#xD;&#xA;    // Right Edge&#xD;&#xA;    else if( localGridCoords.x == workGroupSize.x - 1 )&#xD;&#xA;    {&#xD;&#xA;        sharedData[ tgsmCoords.x + 1 ][ tgsmCoords.y     ] = getSSBODataFromWorldGridCoords( worldGridCoords.x + 1, worldGridCoords.y     );&#xD;&#xA;    }&#xD;&#xA;    // Top Edge&#xD;&#xA;    else if( localGridCoords.y == 0 )&#xD;&#xA;    {&#xD;&#xA;        sharedData[ tgsmCoords.x     ][ tgsmCoords.y - 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x,     worldGridCoords.y - 1 );&#xD;&#xA;    }&#xD;&#xA;    // Bottom Edge&#xD;&#xA;    else if( localGridCoords.y == workGroupSize.y - 1 )&#xD;&#xA;    {&#xD;&#xA;        sharedData[ tgsmCoords.x     ][ tgsmCoords.y + 1 ] = getSSBODataFromWorldGridCoords( worldGridCoords.x,     worldGridCoords.y + 1 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // SSBO index for this thread&#xD;&#xA;    const uint ssboIndex = worldGridCoords.x + worldGridCoords.y * GRID_SIZE;&#xD;&#xA;    uint currentCellState = getSSBODataFromWorldGridCoords( worldGridCoords.x, worldGridCoords.y );&#xD;&#xA;&#xD;&#xA;    // Load current cell into TGSM.&#xD;&#xA;    sharedData[ tgsmCoords.x ][ tgsmCoords.y ] = currentCellState;&#xD;&#xA;&#xD;&#xA;    // Barrier&#xD;&#xA;    memoryBarrierShared();&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    // Count alive neighbors from TGSM&#xD;&#xA;    uint aliveNeighbors = 0;&#xD;&#xA;    const uvec2 sharedMemoryGridCoordinates = uvec2( localGridCoords.x + 1, localGridCoords.y + 1 );&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x - 1 ][ sharedMemoryGridCoordinates.y - 1 ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x     ][ sharedMemoryGridCoordinates.y - 1 ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x + 1 ][ sharedMemoryGridCoordinates.y - 1 ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x - 1 ][ sharedMemoryGridCoordinates.y     ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x + 1 ][ sharedMemoryGridCoordinates.y     ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x - 1 ][ sharedMemoryGridCoordinates.y + 1 ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x     ][ sharedMemoryGridCoordinates.y + 1 ];&#xD;&#xA;    aliveNeighbors += sharedData[ sharedMemoryGridCoordinates.x + 1 ][ sharedMemoryGridCoordinates.y + 1 ];&#xD;&#xA;&#xD;&#xA;    if( currentCellState &lt; 1.0 &amp;&amp; aliveNeighbors == 3 )&#xD;&#xA;    {&#xD;&#xA;        // Dead cell comes back to life&#xD;&#xA;        dstGrid.state[ssboIndex] = 1;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Alive cell dies&#xD;&#xA;    if( aliveNeighbors &lt; 2.0 || aliveNeighbors &gt; 3.0)&#xD;&#xA;    {&#xD;&#xA;        dstGrid.state[ssboIndex] = 0;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    dstGrid.state[ssboIndex] = currentCellState;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Any pointers towards articles or tools that could help me figure this out would be greatly appreciated :).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life&#xD;&#xA;  [2]: https://i.stack.imgur.com/3SQIn.png&#xD;&#xA;  [3]: https://gpuopen.com/learn/optimizing-gpu-occupancy-resource-usage-large-thread-groups/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29405" PostHistoryTypeId="1" PostId="10154" RevisionGUID="a6410fbd-99b1-42bb-a9da-bb30882c41e8" CreationDate="2020-08-28T14:17:42.337" UserId="11388" Text="Optimizing compute shader with thread group shared memory" ContentLicense="CC BY-SA 4.0" />
  <row Id="29406" PostHistoryTypeId="3" PostId="10154" RevisionGUID="a6410fbd-99b1-42bb-a9da-bb30882c41e8" CreationDate="2020-08-28T14:17:42.337" UserId="11388" Text="|gpu|performance|compute-shader|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29407" PostHistoryTypeId="2" PostId="10155" RevisionGUID="3f94bef3-dfda-405b-8dc2-f7b3393458eb" CreationDate="2020-08-28T14:34:28.567" UserId="13887" Text="I am looking for tools to generate video and audio output for my own codecs, in my search I found SDL, EGL, FFmpeg and OpenAL, but it is not clear to me if these APIs serve my purpose which is simply to generate the output, if so when should I use each one?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29408" PostHistoryTypeId="1" PostId="10155" RevisionGUID="3f94bef3-dfda-405b-8dc2-f7b3393458eb" CreationDate="2020-08-28T14:34:28.567" UserId="13887" Text="What APIs are used to output video and audio from a custom codec?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29409" PostHistoryTypeId="3" PostId="10155" RevisionGUID="3f94bef3-dfda-405b-8dc2-f7b3393458eb" CreationDate="2020-08-28T14:34:28.567" UserId="13887" Text="|pixel-graphics|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29410" PostHistoryTypeId="2" PostId="10156" RevisionGUID="801f79b3-8e8c-4d91-9bac-65dcc870ea11" CreationDate="2020-08-28T19:16:03.943" UserId="13888" Text="I have a mesh of an object enclosed in unit volume cube and I would like to sample points inside and outside the mesh surface. What are the different ways of doing it? Is there any sample code available? " ContentLicense="CC BY-SA 4.0" />
  <row Id="29411" PostHistoryTypeId="1" PostId="10156" RevisionGUID="801f79b3-8e8c-4d91-9bac-65dcc870ea11" CreationDate="2020-08-28T19:16:03.943" UserId="13888" Text="How to Sample 3D Points Outside and Inside the Mesh Surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="29412" PostHistoryTypeId="3" PostId="10156" RevisionGUID="801f79b3-8e8c-4d91-9bac-65dcc870ea11" CreationDate="2020-08-28T19:16:03.943" UserId="13888" Text="|3d|mesh|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29413" PostHistoryTypeId="33" PostId="10148" RevisionGUID="8c724e21-bd7d-46df-932f-58106cf80c9a" CreationDate="2020-08-28T20:18:07.357" UserId="7462" Comment="63" />
  <row Id="29414" PostHistoryTypeId="2" PostId="10157" RevisionGUID="b0b838c9-a111-4d63-a5b8-d02e7c67b540" CreationDate="2020-08-28T20:40:46.377" UserId="7952" Text="The original CIE RGB colors included luminance within the actual encoding, and the original basis colors chosen for CIE RGB were chosen because they were easy to reproduce at that time. This made it much easier and more accurate when doing color experiments that required people to classify colors when producing those colors with real physical equipment.&#xD;&#xA;&#xD;&#xA;But, because of these two choices, some of the colors required the red value (when plotted on a graph) to drop below zero. At the time having negative values was considered okay because the eye has a tough time in the 700nm range of colors so a little error here allowed for greater accuracy overall.&#xD;&#xA;&#xD;&#xA;But, this caused a problem when translating CIE RGB colors into real physical colors. So they convened a panel, then they argued (a lot) and came up with the CIE XYZ color space. CIE XYZ attempts to separate lumanance (perceived brightness) out of the color gamut by encoding it in the  Y channel, and it also removes those pesky negative values.&#xD;&#xA;&#xD;&#xA;But, they needed to represent all the colors in the original CIE RGB color space in the new CIE XYZ color space. So, the CIE panel created color matching functions (or matrix depending on how you look at it) that exactly represents the CIE RGB color gamut in CIE XYZ color gamut. So, when you map both gamuts to a 2D plot they will actually plot to different points within the same graph because they are represented by different values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Keep in mind that it is possible for two different wavelengths of light to be perceived as the same exact color so long as the weighted sum of the spectral distributions are equivalent. But that's a different story.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29415" PostHistoryTypeId="2" PostId="10158" RevisionGUID="73d1912f-5b6f-44a7-917d-074843c3ffd2" CreationDate="2020-08-28T22:54:12.950" UserId="6588" Text="What you want is something that can perform the [inside-outside test](https://en.wikipedia.org/wiki/Point_in_polygon) for meshes. The simplest solution would be to use [Trimesh](https://github.com/mikedh/trimesh)'s implementation which can be ran with Embree to accelerate ray queries. &#xD;&#xA;&#xD;&#xA;I recommend you check out recent literature on neural implicit representations if you want more alternatives. Your problem arises when one wants to learn 3D shapes using small neural networks; it is then necessary to sample points and their groundtruth attributes with respect to the mesh (signed distances or occupancies of points). [Here](https://github.com/zekunhao1995/DualSDF/blob/master/extensions/mesh2sdf2_cuda/mesh2sdf_kernel.cu)'s one example for SDFs written in CUDA. NVIDIA's [Kaolin](https://github.com/NVIDIAGameWorks/kaolin) also has a CUDA kernel for this IIRC.&#xD;&#xA;&#xD;&#xA;For more troublesome meshes, you can also use the [generalized winding number](https://www.dgp.toronto.edu/projects/fast-winding-numbers/), which has an implementation in [libigl](https://github.com/libigl/libigl) but I think their code is CPU-only." ContentLicense="CC BY-SA 4.0" />
  <row Id="29416" PostHistoryTypeId="2" PostId="10159" RevisionGUID="1a0ba366-02ec-43fd-8189-04f3175850ca" CreationDate="2020-08-28T23:36:48.080" UserId="48" Text="Correct, the missing curvy section in the green-cyan-blue area represents where the red component would have to go negative to express those colors in CIE RGB coordinates. &#xD;&#xA;&#xD;&#xA;RGB and XYZ are, at one level, just different coordinate systems covering the same color space—the space of all colors visible to typical human vision. In a mathematical sense, when used as coordinates, there's nothing wrong with negative RGB values (as long as the overall luminance of the color remains positive). But it does present a problem for storing or transmitting such values, as conventional image formats and display signal protocols like HDMI etc only allow for positive values.&#xD;&#xA;&#xD;&#xA;On another level, various RGB color spaces are used because they more or less directly represent the actual red, green, and blue subpixels on the display. Those can't emit negative light of course, and so the RGB triangle in color space represents the gamut of colors that can be produced by the display.&#xD;&#xA;&#xD;&#xA;Unfortunately because the spectral locus is curved, there's no way that 3 primaries can cover the whole thing. All RGB spaces inevitably cut off a big chunk of the highly saturated green/blue colors.&#xD;&#xA;&#xD;&#xA;The XYZ space sort of has the opposite problem. All visible colors can be represented using only positive values in XYZ, but the XYZ primaries themselves are not physically possible colors—they're well outside the visible gamut. So, there's a big chunk of XYZ space that is not valid as a color. And it's not trivial to determine exactly what values are or aren't valid, as you have to test whether they fall inside or outside of the curved spectral locus. This also means that you need more bits per component to get good precision, if you store/transmit images expressed in XYZ—8 bits won't do, probably not 10 bits either, maybe 12 bits would do the job.&#xD;&#xA;&#xD;&#xA;If we want to make displays that cover more of the visible gamut, we will eventually need to move to 4, 5, or more primaries. However, that doesn't mean we need 4- or 5-dimensional color spaces. A futuristic display device could be fed by images in XYZ space, for instance, and the device would decide how best to generate each color using the primaries it has available." ContentLicense="CC BY-SA 4.0" />
  <row Id="29417" PostHistoryTypeId="2" PostId="10160" RevisionGUID="b0216c80-a860-4083-8a78-4b5e60063798" CreationDate="2020-08-29T02:01:12.743" UserId="13559" Text="I'm implementing Peter Shirley's &quot;Raytracer in a Weekend: The next week&quot; and I'm having some trouble with rendering a scene with a light. I'm not sure if the issue is the background color or the light itself but the raytracer seems to be working fine in any scenes that have no lights.&#xD;&#xA;&#xD;&#xA;The image rendered is supposed to be:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;but it actually turns out as:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;When I try to troubleshoot and change the background color to blue the image is:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I'm not sure where the problem is so I'm not sure what code snippets to include.. but my github repository is here: [https://github.com/jallex/Raytracer/tree/master/src][4]&#xD;&#xA;&#xD;&#xA;Hopefully someone who has implemented this raytracer before or who has intuition about raytracing has an idea why this might be happening??&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aA4Nu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cmm6V.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/wTZdL.png&#xD;&#xA;  [4]: https://github.com/jallex/Raytracer/tree/master/src" ContentLicense="CC BY-SA 4.0" />
  <row Id="29418" PostHistoryTypeId="1" PostId="10160" RevisionGUID="b0216c80-a860-4083-8a78-4b5e60063798" CreationDate="2020-08-29T02:01:12.743" UserId="13559" Text="Raytracer help - Background color writing over some colors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29419" PostHistoryTypeId="3" PostId="10160" RevisionGUID="b0216c80-a860-4083-8a78-4b5e60063798" CreationDate="2020-08-29T02:01:12.743" UserId="13559" Text="|raytracing|c++|lighting|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29422" PostHistoryTypeId="2" PostId="10163" RevisionGUID="5bcffdf1-0511-4d79-98a5-a3bf5096015b" CreationDate="2020-08-29T07:46:21.940" UserId="10096" Text="I have a few suggestions:&#xD;&#xA;&#xD;&#xA;1) Partition the volume by using tetrahedra within the mesh, and outside of it (in the cube). Set the probability to sample each tetrahedron to its volume divided by the inside/outside volume of the mesh. Sample a tetrahedron based on the above probability, then sample a point (uniformly) within the chosen tetrahedron.&#xD;&#xA;&#xD;&#xA;2) Discretize your mesh to a grid, and then use a filling algorithm for the inside/outside. Keep arrays of the inside/outside cells and sample those randomly. Compared to (1) this introduces discretization error.&#xD;&#xA;&#xD;&#xA;3) Pick points uniformly in the cube, then shoot a ray in any direction and if it doesn't intersect the mesh then it is outside, otherwise it is inside.&#xD;&#xA;&#xD;&#xA;If the mesh is convex (or can be decomposed in convex pieces) then you can check plane half-space membership which allows an early out." ContentLicense="CC BY-SA 4.0" />
  <row Id="29424" PostHistoryTypeId="5" PostId="10163" RevisionGUID="a7c484d9-becd-4d88-98b8-2684a8bce807" CreationDate="2020-08-29T08:17:48.747" UserId="10096" Comment="added 17 characters in body" Text="I have a few suggestions:&#xD;&#xA;&#xD;&#xA;1) Partition the volume by using tetrahedra within the mesh, and outside of it (in the cube). Set the probability to sample each tetrahedron to its volume divided by the inside/outside volume of the mesh. Sample a tetrahedron based on the above probability, then sample a point (uniformly) within the chosen tetrahedron.&#xD;&#xA;&#xD;&#xA;2) Discretize your mesh to a grid, and then use a filling algorithm for the inside/outside. Keep arrays of the inside/outside cells and sample those randomly. Compared to (1) this introduces discretization error.&#xD;&#xA;&#xD;&#xA;3) Pick a point uniformly in the cube, then shoot a ray in any direction and if it intersect the mesh an even number of times then it is outside, otherwise it is inside.&#xD;&#xA;&#xD;&#xA;If the mesh is convex (or can be decomposed in convex pieces) then you can check plane half-space membership which allows an early out." ContentLicense="CC BY-SA 4.0" />
  <row Id="29426" PostHistoryTypeId="2" PostId="10164" RevisionGUID="cfce27fd-c47c-4a47-933a-8669f33e0676" CreationDate="2020-08-29T22:21:20.140" UserId="13891" Text="I'm in Blender and working with a pre-existing 3D model- I want to add more length to it, but I don't want to mess with the mesh- Is it possible to extend the texture beyond the mesh without changing it, or will I have to change the mesh anyways? Are there any shortcuts around changing the mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29427" PostHistoryTypeId="1" PostId="10164" RevisionGUID="cfce27fd-c47c-4a47-933a-8669f33e0676" CreationDate="2020-08-29T22:21:20.140" UserId="13891" Text="Wondering if it's possible to 'extend' a texture beyond the mesh without altering the mesh itself" ContentLicense="CC BY-SA 4.0" />
  <row Id="29428" PostHistoryTypeId="3" PostId="10164" RevisionGUID="cfce27fd-c47c-4a47-933a-8669f33e0676" CreationDate="2020-08-29T22:21:20.140" UserId="13891" Text="|mesh|model|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29429" PostHistoryTypeId="2" PostId="10165" RevisionGUID="25835f7d-44e4-4b6a-9bf9-ca4046b7dc4a" CreationDate="2020-08-29T23:24:24.387" UserId="48" Text="One way to do it: first find the maximum x using atomics on a shared variable. Then, have each thread compare its local version of x to the found maximum, and store to y only if they are equal.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;shared uint x, y;&#xD;&#xA;...&#xD;&#xA;uint localX, localY;&#xD;&#xA;// each thread computes its localX and localY&#xD;&#xA;atomicMax(x, localX);&#xD;&#xA;barrier();  // ensure all threads have done the atomicMax before going on&#xD;&#xA;if (x == localX)&#xD;&#xA;{&#xD;&#xA;    atomicExchange(y, localY);&#xD;&#xA;}&#xD;&#xA;barrier();&#xD;&#xA;// now you can read the final x and y values&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This should work even if there are multiple threads with the same maximum value of `x`, as the stores to `y` are atomic, so you'll just end up with an arbitrary one of them &quot;winning&quot;.&#xD;&#xA;&#xD;&#xA;A variation on this, which may be useful if `y` is a larger struct of multiple pieces of data and therefore can't be atomically stored natively, is to use the local invocation index to pick the &quot;winning&quot; thread.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;shared uint x, winningThread;&#xD;&#xA;shared MyStruct y;&#xD;&#xA;...&#xD;&#xA;uint localX;&#xD;&#xA;MyStruct localY;&#xD;&#xA;// each thread computes its localX and localY&#xD;&#xA;atomicMax(x, localX);&#xD;&#xA;barrier();  // ensure all threads have done the atomicMax before going on&#xD;&#xA;if (x == localX)&#xD;&#xA;{&#xD;&#xA;    atomicExchange(winningThread, gl_LocalInvocationIndex);&#xD;&#xA;}&#xD;&#xA;barrier();&#xD;&#xA;if (winningThread == gl_LocalInvocationIndex)&#xD;&#xA;{&#xD;&#xA;    y = localY;  // only one thread will ever do this store, so doesn't need to be atomic&#xD;&#xA;}&#xD;&#xA;barrier();&#xD;&#xA;// now you can read the final x and y values&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="29430" PostHistoryTypeId="2" PostId="10166" RevisionGUID="2f00f12b-b15b-4f14-bbbc-aa205dbc46db" CreationDate="2020-08-29T23:38:19.167" UserId="48" Text="One possibility would be to create a bit array with 1 bit per half-edge. When you start iterating, initialize them all to 1, then clear the bits of each half-edge and its partner as you iterate.&#xD;&#xA;&#xD;&#xA;The iteration can be done using [`__builtin_clz`](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fclz) (GCC, clang)  or [`_BitScanReverse`](https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64?view=vs-2019) (MSVC) to efficiently extract the next 1-bit without branching on every bit. Although you do then need a nested pair of loops, where you loop over the fields in your bit array, and then loop extracting bits until the current field is zero." ContentLicense="CC BY-SA 4.0" />
  <row Id="29431" PostHistoryTypeId="2" PostId="10167" RevisionGUID="64193433-cb13-40a7-a9c1-9413e1d92a40" CreationDate="2020-08-30T00:12:42.037" UserId="48" Text="Points in front of the camera have $w &gt; 0$ strictly, by definition. I would say that if clipping is giving you points with $w = 0$ then something is going wrong.&#xD;&#xA;&#xD;&#xA;Consider the left/right/top/bottom clip planes. There is no way that a triangle can span from part of the visible frustum, to the $w = 0$ camera plane or behind it, without also crossing outside one of the frustum side planes—or else the near plane, which lies at some positive distance $w_\text{near} &gt; 0$.&#xD;&#xA;&#xD;&#xA;You mentioned skyboxes and setting $z = w$ in the vertex shader output. Such geometry must cross the frustum side planes before it can get to the near plane. (How could part of a skybox get close enough to the camera to be clipped by the near plane only?) If you are correctly clipping it against _all_ of the frustum planes, you must end up with $w &gt; 0$ in the final vertex." ContentLicense="CC BY-SA 4.0" />
  <row Id="29432" PostHistoryTypeId="2" PostId="10168" RevisionGUID="6f90b995-d8a5-4811-ae71-6bf21e5fbb3a" CreationDate="2020-08-30T00:35:09.183" UserId="48" Text="There are some bugs in your math. You found the problem with the 2π and 4π in the hemisphere and sphere sampling functions already, but also, these lines in the cosine hemisphere sampling are wrong:&#xD;&#xA;&#xD;&#xA;    float x = cos(phi) * 2.0f * sqrt(r2);&#xD;&#xA;    float y = sin(phi) * 2.0f * sqrt(r2);&#xD;&#xA;&#xD;&#xA;There should not be a factor of 2 in these: this is distorting the cosine distribution.&#xD;&#xA;&#xD;&#xA;Also,&#xD;&#xA;&#xD;&#xA;    vec3 pdf = dotp(uvw.w(), direction)/Pi;&#xD;&#xA;    throughput = throughput * brdf_result * cosine / pdf;&#xD;&#xA;&#xD;&#xA;This isn't wrong, but it is unnecessary: the `pdf` cancels out the `cosine`, so it would be preferable to set `pdf` to just 1/π, and leave the cosine factor off. In fact, that also cancels the 1/π in the `brdf_result`, so you could leave off both of those pi factors and get rid of `pdf` entirely.&#xD;&#xA;&#xD;&#xA;More about the cosine factor: the whole idea of sampling with a cosine-weighted hemisphere is to avoid needing to have the cosine factor in the path throughput. Basically you only want the cosine in one place: either in the sampling distribution or in the throughput, but not both. It's preferable to put it in the sampling distribution because then the variance in the samples is lower (as they don't have the strongly varying cosine factor in their throughput), so the rendering converges faster.&#xD;&#xA;&#xD;&#xA;This is also a general maxim in path tracing: you generally want to move factors from the throughput into the ray distribution whenever practical. That's the idea of importance sampling of BRDFs (move factors from the BRDF into the ray distribution) and explicit light sampling (move parts of the incoming light distribution into the ray distribution) as well as more advanced things like multiple importance sampling or path guiding." ContentLicense="CC BY-SA 4.0" />
  <row Id="29433" PostHistoryTypeId="2" PostId="10169" RevisionGUID="e97c6e62-81e1-4634-85bb-6d16d3e5e972" CreationDate="2020-08-30T06:31:41.933" UserId="48" Text="Assuming a value is assigned to each vertex of the mesh and we use purely linear interpolation, then there will be a constant gradient vector within each tetrahedron.&#xD;&#xA;&#xD;&#xA;Linear interpolation can be expressed using barycentric coordinates, like&#xD;&#xA;$$&#xD;&#xA;f(x,y,z) = f_1 w_1(x,y,z) + f_2 w_2(x,y,z) + f_3 w_3(x,y,z) + f_4 w_4(x,y,z)&#xD;&#xA;$$&#xD;&#xA;where $f_1 \ldots f_4$ are the values of the function at the four vertices, and $w_1 \ldots w_4$ are the barycentric weights for each vertex. Then, finding the gradient of $f$ reduces to finding the gradients of all of the weights.&#xD;&#xA;&#xD;&#xA;This can be worked out geometrically by noting that each $w_i$ is 1 at the $i$th vertex, falling off to 0 at the plane formed by the other three vertices. The gradient vector will therefore be normal to that plane, pointing back towards the $i$th vertex, with a magnitude equal to 1 / the distance from the plane to the vertex.&#xD;&#xA;&#xD;&#xA;Once you've calculated those barycentric gradients, you can multiply them by $f_1 \ldots f_4$ and sum them up to arrive at the gradient of $f$ overall.&#xD;&#xA;&#xD;&#xA;This reasoning works for triangles too, by the way, only replace &quot;plane&quot; with &quot;line&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="29434" PostHistoryTypeId="2" PostId="10170" RevisionGUID="dac72f31-b047-44b6-b84f-095f5b642e9d" CreationDate="2020-08-30T16:49:05.823" UserId="13896" Text="I was recently trying to read some rendering papers and textbooks. The word 2D BRDF slice/lobe is often used while no official definition is provided. I know that BRDF is a 4D function of input direction and output direction. What is the 2D slice/lobe based on that? Are they the same concept? If not, what's the definition of each of them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29435" PostHistoryTypeId="1" PostId="10170" RevisionGUID="dac72f31-b047-44b6-b84f-095f5b642e9d" CreationDate="2020-08-30T16:49:05.823" UserId="13896" Text="What is 2D BRDF Slice/Lobe?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29436" PostHistoryTypeId="3" PostId="10170" RevisionGUID="dac72f31-b047-44b6-b84f-095f5b642e9d" CreationDate="2020-08-30T16:49:05.823" UserId="13896" Text="|rendering|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29437" PostHistoryTypeId="2" PostId="10171" RevisionGUID="54fd57d8-757c-41a1-87da-cd108aecbfb1" CreationDate="2020-08-30T19:03:37.757" UserId="48" Text="A BRDF is a 4D function, but as we cannot really visualize a 4D function in a comprehensible way, if we want to understand its behavior it can be instructive to fix 2 or 3 of the parameters and graph the others. This kind of graph can be called a &quot;slice&quot;. (The mental image I have is like: the BRDF is some oddly shaped fruit, and we're taking a knife and making a slice through it, to examine the shape of the cut area.)&#xD;&#xA;&#xD;&#xA;In particular, a common way to do this is to fix the incoming light direction; then the BRDF can be graphed as a function of the outgoing light direction, like this:&#xD;&#xA;&#xD;&#xA;![3D graph of outgoing light distribution of a BRDF][1]\&#xD;&#xA;(image from http://brdflab.sourceforge.net/)&#xD;&#xA;&#xD;&#xA;The orange line on the left represents the fixed incoming light direction. This is a polar graph, so the magnitude of outgoing light in each direction is graphed as the radius of the shape.&#xD;&#xA;&#xD;&#xA;In this case we can see that most of the light is going out along the specular reflection direction, to the upper right; but some is heading back toward the source as well (retroreflection). These are the &quot;lobes&quot;. Lobes are not precisely defined, but intuitively they are the visible features in the shape of the function. Here, we would say there is a &quot;specular lobe&quot; and a &quot;retroreflection lobe&quot;. In fact, this BRDF looks like it has two specular lobes, one long skinny one (which represents a tightly concentrated, bright highlight) and another short and fat one (a more spread-out, soft/rough highlight). There appears be a diffuse lobe as well, which shows up as a hemisphere around the origin in this type of graph.&#xD;&#xA;&#xD;&#xA;It's also common to simplify the graph even more by constraining the outgoing light directions to be coplanar with the normal and the incoming light, so now you're only graphing the (N, V) angle. That gets you a graph like this:&#xD;&#xA;&#xD;&#xA;![2D graph of coplanar outgoing light distribution][2]\&#xD;&#xA;(image from [Physically Based Rendering in Filament](https://google.github.io/filament/Filament.html#materialsystem/standardmodel))&#xD;&#xA;&#xD;&#xA;This is the one that's most likely to be called a &quot;slice&quot;. This diagram also shows two &quot;lobes&quot;, a specular one and a diffuse-ish one.&#xD;&#xA;&#xD;&#xA;Synthetic BRDFs (what we mostly use in graphics) are usually constructed by taking a weighted average of various lobes generated by different models, e.g. a Lambert diffuse lobe with one or more microfacet specular lobes, etc. When looking at measured BRDFs, we could try to identify the &quot;lobes&quot; by fitting some model lobes to the measured data.&#xD;&#xA;&#xD;&#xA;To sum up, &quot;slice&quot; is a type of graph that allows us to visualize the features of a BRDF, and &quot;lobe&quot; is the name for the typical kind of features that we see in the BRDF shape, or that we use to construct the BRDF in the first place.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ryiWI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5UYis.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29438" PostHistoryTypeId="2" PostId="10172" RevisionGUID="8fefdc49-366b-4e21-b258-48cd8b923627" CreationDate="2020-08-30T21:25:01.977" UserId="48" Text="Textures are applied to the faces of a mesh, so textures cannot be anywhere there isn't a face for it to appear on. &quot;Adding more length&quot; to a mesh pretty much implies moving some of the vertices. I don't think you're going to get around that.&#xA;&#xA;Now if you are assembling a game world, it's quite common to have modular mesh pieces that can be aligned end-to-end, or placed intersecting each other, to form larger structures—like a wall panel that can be duplicated several times to form a longer wall, for instance, without needing a new mesh to be built specifically for that wall." ContentLicense="CC BY-SA 4.0" />
  <row Id="29439" PostHistoryTypeId="50" PostId="8260" RevisionGUID="40b5deb8-9cad-48a1-a31c-1c034f898225" CreationDate="2020-08-31T06:05:30.687" UserId="-1" />
  <row Id="29443" PostHistoryTypeId="5" PostId="10124" RevisionGUID="643a1cf3-f84a-42e4-bf90-6ad8eafc608a" CreationDate="2020-08-31T10:28:54.210" UserId="13095" Comment="added 167 characters in body" Text="&gt;  From my reading, u seems to be a suitable function that approximates heat flow on the surface of a manifold?&#xD;&#xA;&#xD;&#xA;$u$ is the function that describes how your quantity behaves/evolves in a certain field. In the paper, the quantity is the temperature or heat flux, I guess. However, most of the time there is no analytical solution/formula for $u$. This is where methods like Finite Elements (FEM) come into play. By discretizing your field, you can piecewise approximate your function $u$. &#xD;&#xA;&#xD;&#xA;In your case, you would use your mesh, which is already a discretization of your surface. Your elements are the triangles and you need to define how the nodal quantities are interpolated inside each triangle. --- Here, linear interpolation is probably the way to go. Otherwise, you need to remesh your geometry or introduce additional nodes for higher-order approximations.&#xD;&#xA;&#xD;&#xA;Then you have to assign to each Node/Vertex an initial value $u_0$ as written in the answer of gilgamec. Afterwards, you build and solve your finite element system and get the nodal distribution of $u$ that actually solves your equation or system of equations. The finer your mesh gets, the better the solution. Higher-order interpolations will also help with accuracy.&#xD;&#xA;&#xD;&#xA;So $u$ or its nodal values are what you are actually looking for as lightxbulb said in his comment. It's your unknown quantity.&#xD;&#xA;&#xD;&#xA;If this doesn't help, you might want to read some literature about the finite element method. Can't tell how helpful the following links are, but a short glimpse looked promising. You will see, that they use $u$ all over the place. So I hope one of them will help you:&#xD;&#xA;&#xD;&#xA;- [A gentle introduction to the Finite Element Method](http://arturo.imati.cnr.it/~marini/didattica/Metodi-engl/Intro2FEM.pdf)&#xD;&#xA;- [PE281 Finite Element Method Course Notes](https://web.stanford.edu/class/energy281/FiniteElementMethod.pdf)&#xD;&#xA;- [Introduction to the finite element method](https://homepages.cae.wisc.edu/~suresh/ME964Website/M964Notes/Notes/introfem.pdf)&#xD;&#xA;- [finite element analysis by hand](https://enterfea.com/finite-element-analysis-by-hand/)&#xD;&#xA;&#xD;&#xA;I also had a link to a good online tutorial similar to the last link I provided that helped me a lot in understanding the fundamentals. If I find the link, I ll add it to my answer.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Found the link I was referring to. Unfortunately, it is in german:&#xD;&#xA;&#xD;&#xA;- [FEM Handrechnung](http://www.cae-wiki.info/wikiplus/index.php/FEM_Handrechnung_1_1)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29445" PostHistoryTypeId="2" PostId="10174" RevisionGUID="e704afeb-75b1-4c5d-b367-79a0a4602e8b" CreationDate="2020-08-31T13:22:40.503" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="29446" PostHistoryTypeId="1" PostId="10174" RevisionGUID="e704afeb-75b1-4c5d-b367-79a0a4602e8b" CreationDate="2020-08-31T13:22:40.503" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="29447" PostHistoryTypeId="2" PostId="10175" RevisionGUID="6aa3af18-f36f-43b1-af1e-3642245f16ee" CreationDate="2020-08-31T13:22:40.503" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="29448" PostHistoryTypeId="1" PostId="10175" RevisionGUID="6aa3af18-f36f-43b1-af1e-3642245f16ee" CreationDate="2020-08-31T13:22:40.503" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="29449" PostHistoryTypeId="2" PostId="10176" RevisionGUID="4bce0560-f1c5-4699-ac74-7d649ac924e1" CreationDate="2020-08-31T22:24:18.813" UserId="13874" Text="I am trying to add GGX and PBR textures to my GPU ray tracer. The result is very strange, it's getting darker for each frame.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1tA6Y.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/eJZmo.jpg&#xD;&#xA;&#xD;&#xA;            float ao = texAO.sample(textureSampler, hitRecord.uv).r;&#xD;&#xA;            &#xD;&#xA;            float3 albedo = texAlbedo.sample(textureSampler, hitRecord.uv).rgb;&#xD;&#xA;            albedo = pow(albedo, 2.2); //albedo = float3(1.0);&#xD;&#xA;            &#xD;&#xA;            float metallic = texMetallic.sample(textureSampler, hitRecord.uv).r;&#xD;&#xA;            float3 tNormal = texNormal.sample(textureSampler, hitRecord.uv).xyz;&#xD;&#xA;            tNormal = normalize(tNormal * 2 - 1);&#xD;&#xA;            &#xD;&#xA;            float roughness = texRoughness.sample(textureSampler, hitRecord.uv).r;&#xD;&#xA;            roughness = max(roughness, 0.001);&#xD;&#xA;            &#xD;&#xA;            float3 nx, ny;&#xD;&#xA;            CoordinateSystem(normal, nx, ny);&#xD;&#xA;            float3x3 stw = { nx, ny, normal };&#xD;&#xA;            &#xD;&#xA;            normal = stw * tNormal;&#xD;&#xA;            CoordinateSystem(normal, nx, ny);&#xD;&#xA;            stw = { nx, ny, normal };&#xD;&#xA;            &#xD;&#xA;            float3 wi, wh;&#xD;&#xA;            float3 wo = transpose(stw) * (ray.direction);&#xD;&#xA;        &#xD;&#xA;            auto pSpecular = 1/(2-metallic);&#xD;&#xA;            &#xD;&#xA;            auto r0 = randomF(seed);&#xD;&#xA;            auto r1 = randomF(seed);&#xD;&#xA;            &#xD;&#xA;            if (randomF(seed) &gt; pSpecular) {&#xD;&#xA;                &#xD;&#xA;                float sinTheta = sqrt(r0);&#xD;&#xA;                float cosTheta = sqrt(1-r0);&#xD;&#xA;                &#xD;&#xA;                float phi = 2.0 * M_PI_F * r1;&#xD;&#xA;                &#xD;&#xA;                float x = sinTheta * cos(phi);&#xD;&#xA;                float y = sinTheta * sin(phi);&#xD;&#xA;                float z = cosTheta;&#xD;&#xA;                &#xD;&#xA;                wi = { x, y, z };&#xD;&#xA;                wh = normalize(wo + wi); // not specular&#xD;&#xA;                &#xD;&#xA;            } else {&#xD;&#xA;            &#xD;&#xA;                auto a1 = roughness;&#xD;&#xA;                auto a2 = a1 * a1;&#xD;&#xA;                &#xD;&#xA;                auto theta = acos(sqrt((1-r0) / ((a2-1)*r0+1)));&#xD;&#xA;                auto phi = 2 * M_PI_F * r1;&#xD;&#xA;                &#xD;&#xA;                auto x = sin(theta) * cos(phi);&#xD;&#xA;                auto y = sin(theta) * sin(phi);&#xD;&#xA;                auto z = cos(theta) * 1;&#xD;&#xA;                &#xD;&#xA;                //wo = transpose(stw) * (ray.direction);&#xD;&#xA;                wh = normalize( {x, y, z} );&#xD;&#xA;                wi = reflect(wo, wh);&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            if (wi.z &lt;= 0 || dot(wh, wi) &lt;= 0) { return false; }&#xD;&#xA;        &#xD;&#xA;            auto D = NDF(wh, roughness);&#xD;&#xA;            auto G = GX(wo, wi, roughness);&#xD;&#xA;            auto F = FX(wi, wh, albedo, metallic);&#xD;&#xA;            &#xD;&#xA;            float denominator = 4.0f * abs(wo.z * wi.z);&#xD;&#xA;            &#xD;&#xA;            auto specular = D * G * F / max(FLT_MIN, denominator);&#xD;&#xA;            &#xD;&#xA;            auto diffuse = albedo / M_PI_F;&#xD;&#xA;            &#xD;&#xA;            auto kS = F;&#xD;&#xA;            auto kD = (1 - metallic) * (1.0f - kS);&#xD;&#xA;&#xD;&#xA;            ray = Ray(hitRecord.p, stw * wi);&#xD;&#xA;            scatRecord.attenuation = (kD * diffuse + specular) * ao;&#xD;&#xA;            &#xD;&#xA;            //auto pdf = PDF(wh, roughness);&#xD;&#xA;            //scatRecord.attenuation /= abs(pdf);&#xD;&#xA;            &#xD;&#xA;            return true;&#xD;&#xA;&#xD;&#xA;  ```&#xD;&#xA;// Normal Distribution Function&#xD;&#xA;float NDF(const thread float3&amp; h, float roughness) {&#xD;&#xA;    //  GGX / Trowbridge-Reitz&#xD;&#xA;    &#xD;&#xA;    float a1 = roughness;&#xD;&#xA;    float a2 = a1 * a1;&#xD;&#xA;    float NoH = abs(h.z);&#xD;&#xA;    &#xD;&#xA;    float d = (NoH * a2 - NoH) * NoH + 1;&#xD;&#xA;    return a2 / (d * d * M_PI_F);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Geometry Function&#xD;&#xA;float GX(const thread float3&amp; wo, const thread float3&amp; wi, float roughness) {&#xD;&#xA;    // Schlick, remap roughness and k&#xD;&#xA;&#xD;&#xA;    if (wo.z &gt;= 0 || wi.z &lt;= 0)&#xD;&#xA;        return 0;&#xD;&#xA;&#xD;&#xA;    float k = pow(roughness + 1, 2) / 8.f;&#xD;&#xA;    &#xD;&#xA;    k = pow(roughness, 4);&#xD;&#xA;    &#xD;&#xA;    float G1_wo = wo.z / (wo.z*(1 - k) + k);&#xD;&#xA;    float G1_wi = wi.z / (wi.z*(1 - k) + k);&#xD;&#xA;    return G1_wo * G1_wi;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Fresnel&#xD;&#xA;float3 FX(const thread float3&amp; wi, const thread float3&amp; h, const thread float3 albedo, float metallic) {&#xD;&#xA;    // Schlick’s approximation&#xD;&#xA;    // use a Spherical Gaussian approximation to replace the power.&#xD;&#xA;    // slightly more efficient to calculate and the difference is imperceptible&#xD;&#xA;    &#xD;&#xA;    float3 F0 = mix(float3(0.04f), albedo, metallic);&#xD;&#xA;    float HoWi = dot(h, wi);&#xD;&#xA;    return F0 + (float3(1.0f) - F0) * pow(2.0f, (-5.55473f * HoWi - 6.98316f) * HoWi);&#xD;&#xA;}" ContentLicense="CC BY-SA 4.0" />
  <row Id="29450" PostHistoryTypeId="1" PostId="10176" RevisionGUID="4bce0560-f1c5-4699-ac74-7d649ac924e1" CreationDate="2020-08-31T22:24:18.813" UserId="13874" Text="Ray Tracing, why does the GGX make my rendering result darker and darker for each frame?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29451" PostHistoryTypeId="3" PostId="10176" RevisionGUID="4bce0560-f1c5-4699-ac74-7d649ac924e1" CreationDate="2020-08-31T22:24:18.813" UserId="13874" Text="|raytracing|pbr|metal|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29453" PostHistoryTypeId="2" PostId="10177" RevisionGUID="7c94827d-190c-4a5c-b9ee-e617ac9f8933" CreationDate="2020-09-01T09:37:00.923" UserId="13904" Text="I'm using the ZED 2 camera, and although the API provides a means of getting a point cloud position from a specific pixel, for my project I need to be able to perform this calculation myself from the depth pass alone. According to the documentation:&#xD;&#xA;&#xD;&#xA;*&quot;Depth maps captured by the ZED store a distance value (Z) for each pixel (X, Y) in the image. The distance is expressed in metric units (meters for example) and calculated from the back of the left eye of the camera to the scene object.&quot;*&#xD;&#xA;&#xD;&#xA;So my question is, given a pixel index (therefore UV value) and a depth value, how can I work out the world location of the pixel/point? I suspect this has something to do with inverting a matrix (camera? projection?), and I have the following calibration values for the left sensor of the camera:&#xD;&#xA;```&#xD;&#xA;fx: 1057.1   fy: 1056.71&#xD;&#xA;cx: 979.01   cy: 531.934&#xD;&#xA;k1: -0.0412   k2: 0.0095   k3: -0.0047&#xD;&#xA;p1: -0.0005   p2: -0.0002&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;But matrices are far from my strong suit so I'm struggling to understand how to turn the above information into a matrix which I could use to extrapolate the position. Can anyone help me?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29454" PostHistoryTypeId="1" PostId="10177" RevisionGUID="7c94827d-190c-4a5c-b9ee-e617ac9f8933" CreationDate="2020-09-01T09:37:00.923" UserId="13904" Text="How to calculate position from depth pass of the ZED camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29455" PostHistoryTypeId="3" PostId="10177" RevisionGUID="7c94827d-190c-4a5c-b9ee-e617ac9f8933" CreationDate="2020-09-01T09:37:00.923" UserId="13904" Text="|matrix|camera-matrix|depth-map|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29464" PostHistoryTypeId="5" PostId="10174" RevisionGUID="a11630e3-e52f-4062-847f-7a7b8065f8df" CreationDate="2020-09-01T13:20:28.703" UserId="1586" Comment="remove unnecessary symbol &quot;&quot;" Text="The [Metal](https://developer.apple.com/documentation/metal) is an Apple's low-level graphics and compute API and llvm-based toolchain." ContentLicense="CC BY-SA 4.0" />
  <row Id="29465" PostHistoryTypeId="24" PostId="10174" RevisionGUID="a11630e3-e52f-4062-847f-7a7b8065f8df" CreationDate="2020-09-01T13:20:28.703" Comment="Proposed by 1586 approved by 209, -1 edit id of 540" ContentLicense="CC BY-SA 4.0" />
  <row Id="29466" PostHistoryTypeId="5" PostId="10174" RevisionGUID="a156ea86-ff21-4324-8330-80f896781bd4" CreationDate="2020-09-01T13:20:28.703" UserId="13095" Comment="remove unnecessary symbol &quot;&quot;" Text="[Metal](https://developer.apple.com/documentation/metal) is Apple's low-level graphics and compute API and LLVM-based toolchain." ContentLicense="CC BY-SA 4.0" />
  <row Id="29467" PostHistoryTypeId="5" PostId="10175" RevisionGUID="eefe3827-06ee-4516-9aec-c2a7dc89c780" CreationDate="2020-09-01T13:21:49.733" UserId="1586" Comment="remove unnecessary symbol &quot;&quot;" Text="For questions about the Metal graphics/compute API.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29468" PostHistoryTypeId="24" PostId="10175" RevisionGUID="eefe3827-06ee-4516-9aec-c2a7dc89c780" CreationDate="2020-09-01T13:21:49.733" Comment="Proposed by 1586 approved by 209, 13095 edit id of 541" ContentLicense="CC BY-SA 4.0" />
  <row Id="29472" PostHistoryTypeId="2" PostId="10179" RevisionGUID="b9f6fe62-499d-46dd-86dd-9280635de436" CreationDate="2020-09-01T15:21:56.833" UserId="3073" Text="In Lambertion::scatter there is a comment about attenuating light based on distance. &#xD;&#xA;&#xD;&#xA;For a raytracer this is not required as the distribution of rays themselves cause attenuation over distance. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29473" PostHistoryTypeId="2" PostId="10180" RevisionGUID="ca97378e-f672-4ef1-af4b-238a27ddac78" CreationDate="2020-09-01T19:49:47.657" UserId="13696" Text="Apologies if this is a dumb question... but given four arbitrary (non-coplanar) points in 3D space, there are obviously two different ways to triangulate the quad that they form. One triangulation may produce much more natural results than the other- but how can I determine which one to pick?&#xD;&#xA;&#xD;&#xA;Context: I’m doing Dual Contouring, and the quad forms part of an isosurface. I have access to the hermite/gradient data at that point." ContentLicense="CC BY-SA 4.0" />
  <row Id="29474" PostHistoryTypeId="1" PostId="10180" RevisionGUID="ca97378e-f672-4ef1-af4b-238a27ddac78" CreationDate="2020-09-01T19:49:47.657" UserId="13696" Text="How to decide which way to triangulate a quad?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29475" PostHistoryTypeId="3" PostId="10180" RevisionGUID="ca97378e-f672-4ef1-af4b-238a27ddac78" CreationDate="2020-09-01T19:49:47.657" UserId="13696" Text="|3d|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29476" PostHistoryTypeId="2" PostId="10181" RevisionGUID="ffd9c4e4-961d-40e0-96be-bbc6f2700858" CreationDate="2020-09-01T20:03:27.107" UserId="48" Text="A simple heuristic that many 3D content creation apps use is to split along the shorter of the two diagonals of the quad. This generally seems to work pretty well.&#xD;&#xA;&#xD;&#xA;See this article: [Deformation and Triangulation in Maya](https://noahalzayer.com/2017/04/11/deformation-and-triangulation-in-maya/) for some further discussion. In particular if you have a dynamically deforming mesh, you ideally want to retriangulate the quads based on the deformed geometry each frame, or you can get some pretty wonky artifacts if you stick with a fixed triangulation:&#xD;&#xA;&#xD;&#xA;![dynamic retriangulation based on shortest diagonal vs fixed triangulation][1]\&#xD;&#xA;(image from the above linked blog post)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/egHDt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29477" PostHistoryTypeId="5" PostId="10181" RevisionGUID="8f57524a-c9e6-4df9-9bcd-a2efcdb11867" CreationDate="2020-09-01T20:09:10.710" UserId="48" Comment="added 128 characters in body" Text="A simple heuristic that many 3D content creation apps use is to split along the shorter of the two diagonals of the quad. This generally seems to work pretty well. It minimizes the appearance of long, skinny triangles, which are generally undesirable both for visual and performance reasons.&#xD;&#xA;&#xD;&#xA;See this article: [Deformation and Triangulation in Maya](https://noahalzayer.com/2017/04/11/deformation-and-triangulation-in-maya/) for some further discussion. In particular if you have a dynamically deforming mesh, you ideally want to retriangulate the quads based on the deformed geometry each frame, or you can get some pretty wonky artifacts if you stick with a fixed triangulation:&#xD;&#xA;&#xD;&#xA;![dynamic retriangulation based on shortest diagonal vs fixed triangulation][1]\&#xD;&#xA;(image from the above linked blog post)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/egHDt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29478" PostHistoryTypeId="2" PostId="10182" RevisionGUID="a69c9569-7ee1-49d1-bf98-c1189bdf6857" CreationDate="2020-09-02T01:47:43.637" UserId="13838" Text="[zed2-camera-datasheet.pdf][1] tells the &#xD;&#xA;&#xD;&#xA; - Baseline is 120mm&#xD;&#xA; - Focal length is 2.12mm&#xD;&#xA;&#xD;&#xA;such that based on the fx,fy, you can find the pixel to mm ratio.&#xD;&#xA;&#xD;&#xA;You have the local length, baseline, the object coordinates, the principle coordinates. The triangulation is formed, and the depth estimation can be found using ZED depth formula&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.stereolabs.com/assets/datasheets/zed2-camera-datasheet.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29479" PostHistoryTypeId="2" PostId="10183" RevisionGUID="8fa2d624-99ef-41b0-a79d-7cea10dd805f" CreationDate="2020-09-02T04:47:26.980" UserId="13909" Text="i have this bresenham's code, but actually this work only to some cases, how can i complete to any cases?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        this.dx = dx;&#xD;&#xA;        this.dy = dy;&#xD;&#xA;&#xD;&#xA;        int m = dy / dx;&#xD;&#xA;        if (dx &gt;= 0 &amp;&amp; dy &gt;= 0) {&#xD;&#xA;            if (m &lt; 1) {&#xD;&#xA;                stepX = 1;&#xD;&#xA;                stepY = 1;&#xD;&#xA;                d = 2 * dy - dx;&#xD;&#xA;                de = 2 * dy;&#xD;&#xA;                dne = 2 * (dy - dx);&#xD;&#xA;            } else {&#xD;&#xA;                stepX = 1;&#xD;&#xA;                stepY = 1;&#xD;&#xA;                d = dy + (2 * (-dx));&#xD;&#xA;                de = 2 * (-dx);&#xD;&#xA;                dne = 2 * (dy - dx);&#xD;&#xA;                de = -de;&#xD;&#xA;                dne = -dne;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; will be that repeat this code 3 times over?&#xD;&#xA;to following cases?&#xD;&#xA;&#xD;&#xA;    if (dx &gt; 0 &amp;&amp; dy &lt; 0)&#xD;&#xA;    if (dx &lt;= 0 &amp;&amp; dy &lt;= 0)&#xD;&#xA;    if (dx &lt; 0 &amp;&amp; dy &gt; 0)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29480" PostHistoryTypeId="1" PostId="10183" RevisionGUID="8fa2d624-99ef-41b0-a79d-7cea10dd805f" CreationDate="2020-09-02T04:47:26.980" UserId="13909" Text="How can i use bresemhan to any cases?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29481" PostHistoryTypeId="3" PostId="10183" RevisionGUID="8fa2d624-99ef-41b0-a79d-7cea10dd805f" CreationDate="2020-09-02T04:47:26.980" UserId="13909" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29482" PostHistoryTypeId="2" PostId="10184" RevisionGUID="f098af38-387c-4874-9d3f-7d321c4fe514" CreationDate="2020-09-02T05:34:40.040" UserId="13909" Text="How can I remodel a line, i want to draw first a line then i want to remodel the line such as in paint software, which algorithm should I use? Are there several algorithms to achieve this? i am using the bresemhan algorithm&#xD;&#xA;&#xD;&#xA;For example i have this line, but when i will click in the center and with the mouse i want to pull &#xD;&#xA;&#xD;&#xA;    ---------------\/-----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29483" PostHistoryTypeId="1" PostId="10184" RevisionGUID="f098af38-387c-4874-9d3f-7d321c4fe514" CreationDate="2020-09-02T05:34:40.040" UserId="13909" Text="How can i stretch a line?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29484" PostHistoryTypeId="3" PostId="10184" RevisionGUID="f098af38-387c-4874-9d3f-7d321c4fe514" CreationDate="2020-09-02T05:34:40.040" UserId="13909" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29485" PostHistoryTypeId="5" PostId="10183" RevisionGUID="f1627be6-0d20-4024-b4ce-5276957b6e29" CreationDate="2020-09-02T05:38:32.160" UserId="13909" Comment="added 42 characters in body" Text="i have this bresenham's code, but actually this work only to some cases, how can i complete to any cases?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        this.dx = dx;&#xD;&#xA;        this.dy = dy;&#xD;&#xA;&#xD;&#xA;        int m = dy / dx;&#xD;&#xA;        if (dx &gt;= 0 &amp;&amp; dy &gt;= 0) {&#xD;&#xA;            if (m &lt; 1) {&#xD;&#xA;                stepX = 1;&#xD;&#xA;                stepY = 1;&#xD;&#xA;                d = 2 * dy - dx;&#xD;&#xA;                de = 2 * dy;&#xD;&#xA;                dne = 2 * (dy - dx);&#xD;&#xA;            } else {&#xD;&#xA;                stepX = 1;&#xD;&#xA;                stepY = 1;&#xD;&#xA;                d = dy + (2 * (-dx));&#xD;&#xA;                de = 2 * (-dx);&#xD;&#xA;                dne = 2 * (dy - dx);&#xD;&#xA;                de = -de;&#xD;&#xA;                dne = -dne;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; will be that repeat this code 3 times over?&#xD;&#xA;to following cases?&#xD;&#xA;&#xD;&#xA;    if (dx &gt; 0 &amp;&amp; dy &lt; 0)&#xD;&#xA;    if (dx &lt;= 0 &amp;&amp; dy &lt;= 0)&#xD;&#xA;    if (dx &lt; 0 &amp;&amp; dy &gt; 0)&#xD;&#xA;&#xD;&#xA;actually only works for the first quadrant&#xD;&#xA;&#xD;&#xA;           +&#xD;&#xA;           +   here worked&#xD;&#xA;           +&#xD;&#xA;    +++++++++++++++++&#xD;&#xA;           +&#xD;&#xA;           +" ContentLicense="CC BY-SA 4.0" />
  <row Id="29486" PostHistoryTypeId="50" PostId="8757" RevisionGUID="b9abf90b-7d1f-41dd-ab50-655af01cd0ae" CreationDate="2020-09-02T09:07:30.747" UserId="-1" />
  <row Id="29487" PostHistoryTypeId="2" PostId="10185" RevisionGUID="869debb4-7225-46bb-83b4-8a3c3f1dde06" CreationDate="2020-09-02T11:16:36.430" UserId="13912" Text="in my application, I needed to detect collision between 2 3D objects. To make it simple I can represent a object as a bounding box. So actually the task reduced to detect collision between 2 boxes in 3D space. The problem that I cannot make these bounding boxes to be axis aligned. &#xD;&#xA;The objects look like the following image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Unfortunately all the algorithms I've found in the Internet suppose that all the boxes are axis-aligned. It seems to me that this is a common mathematical problem and can be solved using some well known algorithms. Unfortunately I'm not a mathematician so I would be very grateful if someone can offer a solution to this problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6uVLS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29488" PostHistoryTypeId="1" PostId="10185" RevisionGUID="869debb4-7225-46bb-83b4-8a3c3f1dde06" CreationDate="2020-09-02T11:16:36.430" UserId="13912" Text="Detect collision for non axis-aligned bounding boxes" ContentLicense="CC BY-SA 4.0" />
  <row Id="29489" PostHistoryTypeId="3" PostId="10185" RevisionGUID="869debb4-7225-46bb-83b4-8a3c3f1dde06" CreationDate="2020-09-02T11:16:36.430" UserId="13912" Text="|3d|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29490" PostHistoryTypeId="2" PostId="10186" RevisionGUID="5573a791-1cae-432d-baf0-ea3212952da8" CreationDate="2020-09-02T11:44:10.013" UserId="13273" Text="I am creating a 3D spherical curved display (only a part of a sphere). The camera usually is inside of this sphere. This display has texture coordinates. The image below shows the display with its texture coordinates.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The method to generate the geometry (mesh) receives 4 parameters.&#xD;&#xA;These parameters are direction vectors which are pointing at the corners of the display.&#xD;&#xA;topLeftCorner, bottomLeftCorner, topRightCorner and bottomRightCorner.&#xD;&#xA;&#xD;&#xA;I calculated the position / normal / texture coordinates in the following way:&#xD;&#xA;&#xD;&#xA;    Eigen::Quaternionf topLeft(0,topLeftCorner.x(), topLeftCorner.y(), topLeftCorner.z());&#xD;&#xA;    Eigen::Quaternionf topRight(0,topRightCorner.x(), topRightCorner.y(), topRightCorner.z());&#xD;&#xA;    Eigen::Quaternionf bottomLeft(0,bottomLeftCorner.x(), bottomLeftCorner.y(), bottomLeftCorner.z());&#xD;&#xA;    Eigen::Quaternionf bottomRight(0,bottomRightCorner.x(), bottomRightCorner.y(), bottomRightCorner.z());&#xD;&#xA;&#xD;&#xA;    //calculate vertexData&#xD;&#xA;    unsigned long long counter = 0;&#xD;&#xA;    for (int y = 0; y &lt;= countSegmentsVertical; ++y)&#xD;&#xA;    {&#xD;&#xA;        Eigen::Quaternionf slerpedQuaternionHorizontalLeft = bottomLeft.slerp(static_cast&lt;float&gt;(y) / static_cast&lt;float&gt;(countSegmentsVertical), topLeft);&#xD;&#xA;        Eigen::Quaternionf slerpedQuaternionHorizontalRight = bottomRight.slerp(static_cast&lt;float&gt;(y) / static_cast&lt;float&gt;(countSegmentsVertical), topRight);&#xD;&#xA;&#xD;&#xA;        for (int x = 0; x &lt;= countSegmentsHorizontal; ++x)&#xD;&#xA;        {&#xD;&#xA;            Eigen::Quaternionf slerpedQuaternionVertical = slerpedQuaternionHorizontalRight.slerp(static_cast&lt;float&gt;(x) / static_cast&lt;float&gt;(countSegmentsHorizontal),slerpedQuaternionHorizontalLeft);&#xD;&#xA;            Eigen::Vector3f position = slerpedQuaternionVertical * Eigen::Vector3f(0,0,-1);&#xD;&#xA;            position.normalize();&#xD;&#xA;            position *= radius;&#xD;&#xA;&#xD;&#xA;            data[counter].positionX = position.x();&#xD;&#xA;            data[counter].positionY = position.y();&#xD;&#xA;            data[counter].positionZ = position.z();&#xD;&#xA;            data[counter].normalX = -position.x()/m_radius;&#xD;&#xA;            data[counter].normalY = -position.y()/m_radius;&#xD;&#xA;            data[counter].normalZ = -position.z()/m_radius;&#xD;&#xA;            data[counter].textureCoordinateU = 1 - static_cast&lt;float&gt;(x) / static_cast&lt;float&gt;(countSegmentsHorizontal);&#xD;&#xA;            data[counter].textureCoordinateV = static_cast&lt;float&gt;(y) / static_cast&lt;float&gt;(countSegmentsVertical);&#xD;&#xA;            counter++;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**short description:**&#xD;&#xA;by slerping between topLeft and bottomLeft, I receive the left position (P0).&#xD;&#xA;by slerping between topRight and bottomRight, I receive the right position (P1).&#xD;&#xA;by slerping between left and right position, I receive the final position (P2).&#xD;&#xA;The next image illustrates this&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3mTWM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/eZsgb.png&#xD;&#xA;&#xD;&#xA;so far, everything is working fine.&#xD;&#xA;Lets go to the problem:&#xD;&#xA;Now I need to invert the problematic: &#xD;&#xA;having the four corners and a 3D point on the sphere (P2 in world coordinates). Lets call this point P'.&#xD;&#xA;The result should be the P2 texture coordinates.&#xD;&#xA;&#xD;&#xA;My idea is to invert both vertical slerps with an quaternion (P') which is not lying exactly between the corners.&#xD;&#xA;If this is possible (I don't know), the next step would be to invert the horizontal slerp.&#xD;&#xA;the result should be the texture coordinate P2.&#xD;&#xA;&#xD;&#xA;I am not sure if this is possible in this way, so maybe there is an other maybe easier way to calculate the point P' in texture coordinates.&#xD;&#xA;&#xD;&#xA;BTW: The four corner vectors which form the geometry can be totally different than this image shows.&#xD;&#xA;So there is no way to say &quot;Okay, in world coordinates you first can look at the Y coordinate and somehow match the value to the corners&quot;, because this display can be rotated around each axis, scale in horizontal and vertical angle or even don't be &quot;rectangular&quot; at all.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29491" PostHistoryTypeId="1" PostId="10186" RevisionGUID="5573a791-1cae-432d-baf0-ea3212952da8" CreationDate="2020-09-02T11:44:10.013" UserId="13273" Text="Quaternion slerp inverse" ContentLicense="CC BY-SA 4.0" />
  <row Id="29492" PostHistoryTypeId="3" PostId="10186" RevisionGUID="5573a791-1cae-432d-baf0-ea3212952da8" CreationDate="2020-09-02T11:44:10.013" UserId="13273" Text="|c++|eigen|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29493" PostHistoryTypeId="2" PostId="10187" RevisionGUID="72d3a94e-74d6-4393-b37f-bf51e3a143e4" CreationDate="2020-09-02T12:23:22.900" UserId="4748" Text="Write two functions: (1) point in 3D box, and (2) segment intersect rectangle in 3D. Point in box is a conjunction of six left-of-plane checks. For (2), solve for the point of intersection between the line containing the segment and the plane containing the rectangle. Then check if that point is on the segment, and if so, in the rectangle.&#xD;&#xA;&#xD;&#xA;Then box B1 intersects box B2 if and corner of B1 is inside B2, or if any of the 12 edges of B1 intersects and of the six faces of B2." ContentLicense="CC BY-SA 4.0" />
  <row Id="29494" PostHistoryTypeId="5" PostId="10187" RevisionGUID="9b8b3c1d-e65c-455e-8b84-60461111de10" CreationDate="2020-09-02T14:28:46.693" UserId="4748" Comment="added 199 characters in body" Text="Write two functions: (1) point in 3D box, and (2) segment intersect rectangle in 3D. Point in box is a conjunction of six left-of-plane checks. For (2), solve for the point of intersection between the line containing the segment and the plane containing the rectangle. Then check if that point is on the segment, and if so, in the rectangle.&#xD;&#xA;&#xD;&#xA;Then box $B_1$ intersects box $B_2$ if any corner of $B_1$ is inside $B_2$, or if any of the $12$ edges of $B_1$ intersects any of the $6$ faces of $B_2$.&#xD;&#xA;This can be sped up a bit by ordering the tests (for example, if no edge of $B_1$ intersects a face of $B_2$, then you need only check one corner of $B_1$ inside/outside $B_2$)." ContentLicense="CC BY-SA 4.0" />
  <row Id="29495" PostHistoryTypeId="5" PostId="10184" RevisionGUID="6b7da6eb-c81a-4490-a6da-d01cfa13062d" CreationDate="2020-09-02T14:40:14.573" UserId="13909" Comment="added 51 characters in body" Text="How can I remodel a line, i want to draw first a line then i want to remodel the line such as in paint software, which algorithm should I use? Are there several algorithms to achieve this? i am using the bresemhan algorithm&#xD;&#xA;&#xD;&#xA;For example i have this line, but when i will click in the center and with the mouse i want to pull &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/n7LXS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29496" PostHistoryTypeId="4" PostId="10186" RevisionGUID="eff28729-035c-4720-8d35-bbf6b146f8b6" CreationDate="2020-09-02T15:39:47.897" UserId="13273" Comment="edited title" Text="multiple Quaternion slerp inverse to calculate relative coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="29497" PostHistoryTypeId="2" PostId="10188" RevisionGUID="d56e5856-d3eb-44f2-9c0e-1254428c7a72" CreationDate="2020-09-02T16:01:52.080" UserId="13273" Text="I am looking for a way to calculate the value of `t` of quaternion slerp by having three quaternions.&#xD;&#xA;&#xD;&#xA;**Forward direction:**&#xD;&#xA;&#xD;&#xA;    Eigen::Quaternionf q = q1.slerp(t, q2);&#xD;&#xA;&#xD;&#xA;where `q`, `q1` and `q2` are quaternions from the Eigen library. And `t` is a float which interpolates between `q1` and `q2`.&#xD;&#xA;&#xD;&#xA;I am interested in the backward calculation, where `q`, `q1` and `q2` is given and the output is t.&#xD;&#xA;To make it easier all quaternions are normalized and also lying on the same plane which crosses the origin.&#xD;&#xA;See the illustration below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;`q`does **NOT** need to be within `q1` and `q2`.&#xD;&#xA;&#xD;&#xA;I found this link [here][2] but I don't know how to use that.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qwYmt.png&#xD;&#xA;  [2]: https://math.stackexchange.com/questions/2346982/slerp-inverse-given-3-quaternions-find-t" ContentLicense="CC BY-SA 4.0" />
  <row Id="29498" PostHistoryTypeId="1" PostId="10188" RevisionGUID="d56e5856-d3eb-44f2-9c0e-1254428c7a72" CreationDate="2020-09-02T16:01:52.080" UserId="13273" Text="calculate quaternion slerp inverse by having three quaternions" ContentLicense="CC BY-SA 4.0" />
  <row Id="29499" PostHistoryTypeId="3" PostId="10188" RevisionGUID="d56e5856-d3eb-44f2-9c0e-1254428c7a72" CreationDate="2020-09-02T16:01:52.080" UserId="13273" Text="|eigen|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29500" PostHistoryTypeId="5" PostId="10188" RevisionGUID="b84fe53c-b50e-4fde-9efb-ea0748a86fec" CreationDate="2020-09-02T16:48:21.590" UserId="2654" Comment="added 1 character in body; edited title" Text="I am looking for a way to calculate the value of `t` of quaternion SLERP by having three quaternions.&#xD;&#xA;&#xD;&#xA;**Forward direction:**&#xD;&#xA;&#xD;&#xA;    Eigen::Quaternionf q = q1.slerp(t, q2);&#xD;&#xA;&#xD;&#xA;where `q`, `q1` and `q2` are quaternions from the Eigen library. And `t` is a float which interpolates between `q1` and `q2`.&#xD;&#xA;&#xD;&#xA;I am interested in the backward calculation, where `q`, `q1` and `q2` is given and the output is t.&#xD;&#xA;&#xD;&#xA;To make it easier all quaternions are normalized and also lying on the same plane which crosses the origin. See the illustration below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;`q`does **NOT** need to be within `q1` and `q2`.&#xD;&#xA;&#xD;&#xA;I found this link [here][2] but I don't know how to use that.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qwYmt.png&#xD;&#xA;  [2]: https://math.stackexchange.com/questions/2346982/slerp-inverse-given-3-quaternions-find-t" ContentLicense="CC BY-SA 4.0" />
  <row Id="29501" PostHistoryTypeId="4" PostId="10188" RevisionGUID="b84fe53c-b50e-4fde-9efb-ea0748a86fec" CreationDate="2020-09-02T16:48:21.590" UserId="2654" Comment="added 1 character in body; edited title" Text="Compute the interpolation factor between the SLERP of 2 quaternions, given those quaternions and the SLERP result" ContentLicense="CC BY-SA 4.0" />
  <row Id="29502" PostHistoryTypeId="2" PostId="10189" RevisionGUID="06d72531-b9c6-4450-b343-f7608739cdce" CreationDate="2020-09-02T17:57:42.323" UserId="10129" Text="http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.htm - here is reference with different geometry shading equations&#xD;&#xA;&#xD;&#xA;http://jcgt.org/published/0003/02/03/paper.pdf - paper explaining how G term works and on what assumptions it is build.&#xD;&#xA;____&#xD;&#xA;Looking again at your code, I'm not sure (based on first link to Karis blog) if your G term is calculated correctly. &#xD;&#xA;    &#xD;&#xA;      float k = pow(roughness + 1, 2) / 8.f; &#xD;&#xA;      k = pow(roughness, 4);&#xD;&#xA;&#xD;&#xA;You're overwritting **k** with roughness^4, which doesn't fall into any Schlick equation that can be seen in Karis blog and if I recall correctly, I haven't seen that in any papers. Another note is, that you're passing *ω*o and *ω*i to your geometry function, but based on your comment that this is Schlick G and overall context, I think that you should use NoL and NoV (dot first pointToLight direction and then viewDir).&#xD;&#xA;&#xD;&#xA;I was trying to do my own image, but I found [Blinn 1977] paper which sums up how Smith G model works (take a look at figure 1) - https://www.microsoft.com/en-us/research/wp-content/uploads/1977/01/p192-blinn.pdf#page=2&amp;zoom=auto,-264,459&#xD;&#xA;&#xD;&#xA;Some time ago, I was playing a little with different D, F, G equations - https://github.com/komilll/dxFramework/blob/master/dxFramework/Shaders/PS_BRDF.hlsl - take a look at **PS_BRDF.hlsl** and **PS_BRDF_Helper.hlsl** for further reference. I was basing my equations on Karis blog, some are modified base on other papers e.g. Frostbite and Disney diffuse are based on respective papers if I recall correctly.&#xD;&#xA;_____&#xD;&#xA;I'm not sure if that's causing a problem, but it's worth fixing for sure. Also I don't think that you're using for summing frames&#xD;&#xA;&#xD;&#xA;    (previous_average * frame_count + current_color) / (frame_count + 1) &#xD;&#xA;&#xD;&#xA;is correct, neither for uniform or importance GGX sampling. You should derive pdf in that case, it can be found in link that I've sent you before - http://cwyman.org/code/dxrTutors/tutors/Tutor14/tutorial14.md.html - it's generally nice tutorial, with good step by step introduction to DXR." ContentLicense="CC BY-SA 4.0" />
  <row Id="29503" PostHistoryTypeId="52" PostId="10185" RevisionGUID="88c59727-4f31-4661-85c1-a6aeb29b7b91" CreationDate="2020-09-02T19:20:29.643" />
  <row Id="29504" PostHistoryTypeId="2" PostId="10190" RevisionGUID="38217a16-942e-43a2-a90e-6db2d1297375" CreationDate="2020-09-02T21:06:17.673" UserId="13874" Text="Despite the discussion on `G`, there are 2 major problems. Fix them will fix the problem.&#xD;&#xA;&#xD;&#xA; 1. Float16 is limited to 65504. When multiplied by a large frame number, it will get overflow and become a small number, then never came back.&#xD;&#xA;https://en.wikipedia.org/wiki/Half-precision_floating-point_format&#xD;&#xA; 2. Vector `wo` and `wi` should be on the same hemisphere on normal direction. So one of them should be `reverse` ray direction. Most documents I saw simply ignored this part. While, whatsoever this chapter from PBRT-v3 helped me figuring it out. &#xD;&#xA;&#xD;&#xA;http://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bdsnA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29505" PostHistoryTypeId="5" PostId="9848" RevisionGUID="ddf041bb-21c4-4682-a3db-1a270a549a6c" CreationDate="2020-09-02T21:23:02.840" UserId="13095" Comment="Merged another answer from the same author into this one." Text="Even film/animation speeds are something that 3D content creation teams and studios try to increase.  Of course they don't mind adding minutes per frame if the output is much nicer, whereas games can add so much to graphics processing before FPS rates drop below an acceptable level, which I think coinsides with the point you are making.&#xD;&#xA;&#xD;&#xA;This difference isn't the reason that film/animation works in quads though.  Quads are easier to work with when creating rounded and organic shapes. In the end though, it is in fact triangulated, at rendertime.  The renderer just creates a new line, per quad, from opposite corners to cut the quad into 2 triangles. This doesn't happen to your model, but do the data streamed to the renderer.  The reason is that if your quad's  4 points are not coplanar, and on a larger percentage of your quads in many models, they won't be, you will have nonmanifold geometry.  The calculation of the area is basically undefined.  If you slice the quad into two tris, that solves the issue as any 3 points are always coplanar.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Response to comments**&#xD;&#xA;&#xD;&#xA;My point was for calculating a flat plane, that is formed by 4 points and linear equations for the sides.  If you move one point off the plane, forming a noncoplanar surface, you now have two planes, not one, and thus the only way to still calculate the original surface is to do it for the 2 triangular planes of the original rectangular plane. Now maybe this is only in Maya, but I think its math and thus universal.  The micropolygons that Renderman creates very well might use a method that can work with noncoplanar surfaces. I don't know that much about Renderman.  I've been told that everything turns into triangles in the end, even if you don't triangulate your meshes, because render engines (some if not all) require coplanar surfaces.&#xD;&#xA;&#xD;&#xA;https://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Polygons-overview-Planar-and-nonplanar-polygons-htm.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="29507" PostHistoryTypeId="5" PostId="10089" RevisionGUID="c4fb5b7e-25f3-4e75-b6d8-b7aee37b4dc6" CreationDate="2020-09-03T06:52:42.090" UserId="13915" Comment="Fixed two typos (dropped words, dashes)" Text="(I am new to Computer Graphics in general)&#xD;&#xA;&#xD;&#xA;I am learning how to ray trace from a book called ''Peter Shirley - Ray Tracing in One Weekend''. In the book, the code is written in C++. I have intermediate-advanced level understanding of good ol' C, but I've never written even simple programs in C++. I don't pretend to understand everything the code says in the book. But, that is the fun part -- figuring it out.&#xD;&#xA;&#xD;&#xA;But, for ray tracing, even C is slow. And writing GLSL fragment shaders is fast, even on my potato PC. And GLSL is closer to C than to C++. So, I'm trying to follow through the book using GLSL. But, GLSL has many limitations and I was hoping if you could teach me how to get around those limitations.&#xD;&#xA;&#xD;&#xA;1.  Pointers. GLSL doesn't have pointers. In the book, there is a function&#xD;&#xA;```bool hit_sphere(const vec3&amp; center, float radius, const ray&amp; r)```&#xD;&#xA;I believe that ''address of'' operator just points to the variable that is passed when the function is called. Without pointers, how to call a function by reference in GLSL?&#xD;&#xA;&#xD;&#xA;1. Late binding. In the book, every object is a class which exposes an interface function called `hit` which returns if a ray hits the object. How does one implement that in GLSL structs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29508" PostHistoryTypeId="24" PostId="10089" RevisionGUID="c4fb5b7e-25f3-4e75-b6d8-b7aee37b4dc6" CreationDate="2020-09-03T06:52:42.090" Comment="Proposed by 13915 approved by 13095 edit id of 542" ContentLicense="CC BY-SA 4.0" />
  <row Id="29509" PostHistoryTypeId="2" PostId="10191" RevisionGUID="92c7808e-22ad-4b11-a672-b81956b79d1d" CreationDate="2020-09-03T07:46:42.393" UserId="13874" Text="I am using the SAH-BVH from PBRT-v3, it works fine for triangle-mesh, especially for dense mesh.&#xD;&#xA;&#xD;&#xA;But here is a problem. If I added Cornell box while building the BVH tree, the BVH performance will drop to only 20% as before. The Cornell box is only 6 rectangles. Why does it behave in this way? Because it's a big box containing everything? How to improve it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29510" PostHistoryTypeId="1" PostId="10191" RevisionGUID="92c7808e-22ad-4b11-a672-b81956b79d1d" CreationDate="2020-09-03T07:46:42.393" UserId="13874" Text="BVH works fine, but why does it slow down a lot when using Cornell Box? How to improve it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29511" PostHistoryTypeId="3" PostId="10191" RevisionGUID="92c7808e-22ad-4b11-a672-b81956b79d1d" CreationDate="2020-09-03T07:46:42.393" UserId="13874" Text="|raytracing|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29512" PostHistoryTypeId="5" PostId="10166" RevisionGUID="56aca86d-1309-447a-a2e3-b81cab47be0c" CreationDate="2020-09-03T22:55:47.977" UserId="48" Comment="add reference to C++20 standard function for bit extraction" Text="One possibility would be to create a bit array with 1 bit per half-edge. When you start iterating, initialize them all to 1, then clear the bits of each half-edge and its partner as you iterate.&#xD;&#xA;&#xD;&#xA;The iteration can be done using [`__builtin_clz`](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fclz) (GCC, clang)  or [`_BitScanReverse`](https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64?view=vs-2019) (MSVC)  [edit: or [`std::countl_zero`](https://en.cppreference.com/w/cpp/numeric/countl_zero) in C++20!] to efficiently extract the next 1-bit without branching on every bit. Although you do then need a nested pair of loops, where you loop over the fields in your bit array, and then loop extracting bits until the current field is zero." ContentLicense="CC BY-SA 4.0" />
  <row Id="29517" PostHistoryTypeId="2" PostId="10193" RevisionGUID="19ee95c6-08cb-4d43-bbae-31f016dbdb1d" CreationDate="2020-09-04T15:44:29.167" UserId="13909" Text="What algorithm can i use to pull entere area?&#xD;&#xA;&#xD;&#xA;i have this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xhsyf.png&#xD;&#xA;&#xD;&#xA;are there many algorithms, which algorithm can you recommended me to implement?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29518" PostHistoryTypeId="1" PostId="10193" RevisionGUID="19ee95c6-08cb-4d43-bbae-31f016dbdb1d" CreationDate="2020-09-04T15:44:29.167" UserId="13909" Text="How can I pull up the whole area of the square?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29519" PostHistoryTypeId="3" PostId="10193" RevisionGUID="19ee95c6-08cb-4d43-bbae-31f016dbdb1d" CreationDate="2020-09-04T15:44:29.167" UserId="13909" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29520" PostHistoryTypeId="2" PostId="10194" RevisionGUID="dafd8585-c350-4067-94d9-fb1733b5420b" CreationDate="2020-09-05T00:38:34.707" UserId="48" Text="We can do this mostly by measuring angles between the quaternions, with a bit of sign flip to get the orientations right. Angles between normalized quaternions are given by the arccos of their dot product (as a 4D vector).&#xD;&#xA;$$&#xD;&#xA;t = \frac{\arccos(q_1 \cdot q)}{\arccos(q_1 \cdot q_2)} \ \text{sign}\bigl(q \cdot [q_2 - (q_1 \cdot q_2) q_1]\bigr)&#xD;&#xA;$$&#xD;&#xA;The first factor is measuring the angle from $q_1$ to $q$ as a fraction of the angle from $q_1$ to $q_2$. This ensures that $t$ will be 0 at $q_1$ and 1 at $q_2$. The other factor ensures that $t$ increases as you move from $q_1$ toward $q_2$ and goes negative on the other side. The quantity in brackets is the projection of $q_2$ on the (hyper)plane perpendicular to $q_1$, then we're dotting $q$ with that to decide which side of the circle we're on.&#xD;&#xA;&#xD;&#xA;Note that the point where $t$ swaps from negative to positive will be the point opposite $q_1$ on the circle (not a point centered across from $q_1$ and $q_2$ as your diagram has it)." ContentLicense="CC BY-SA 4.0" />
  <row Id="29521" PostHistoryTypeId="5" PostId="10194" RevisionGUID="084facbe-4e77-400f-8b3a-323bdb41a979" CreationDate="2020-09-05T00:44:00.940" UserId="48" Comment="added 379 characters in body" Text="We can do this mostly by measuring angles between the quaternions, with a bit of sign flip to get the orientations right. Angles between normalized quaternions are given by the arccos of their dot product (as a 4D vector).&#xD;&#xA;$$&#xD;&#xA;t = \frac{\arccos(q_1 \cdot q)}{\arccos(q_1 \cdot q_2)} \ \text{sign}\bigl(q \cdot [q_2 - (q_1 \cdot q_2) q_1]\bigr)&#xD;&#xA;$$&#xD;&#xA;The first factor is measuring the angle from $q_1$ to $q$ as a fraction of the angle from $q_1$ to $q_2$. This ensures that $t$ will be 0 at $q_1$ and 1 at $q_2$. The other factor ensures that $t$ increases as you move from $q_1$ toward $q_2$ and goes negative on the other side. The quantity in brackets is the projection of $q_2$ on the (hyper)plane perpendicular to $q_1$, then we're dotting $q$ with that to decide which side of the circle we're on.&#xD;&#xA;&#xD;&#xA;Note that the point where $t$ swaps from negative to positive will be the point opposite $q_1$ on the circle—not a point centered across from $q_1$ and $q_2$ as your diagram has it.&#xD;&#xA;&#xD;&#xA;(Also, it's worth noting that this boils down to essentially the same thing as the logarithm solution in the other answer. Their factor $\check p/\|\check p\|$ corresponds to our sign factor: all the quaternions in the problem are in the same plane and so will have $\check p$ along the same axis; the only thing that can differ between the normalized $\check p$s is the sign.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29522" PostHistoryTypeId="5" PostId="10193" RevisionGUID="45d07071-f1ff-49f0-9579-db7b3e7cf583" CreationDate="2020-09-05T18:48:36.100" UserId="13909" Comment="added 95 characters in body" Text="What algorithm can i use to pull entere area?&#xD;&#xA;&#xD;&#xA;i have this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xhsyf.png&#xD;&#xA;&#xD;&#xA;are there many algorithms, which algorithm can you recommended me to implement?&#xD;&#xA;&#xD;&#xA;Edit 1:&#xD;&#xA;&#xD;&#xA;my square was builded with lines (bresenham), i want to move to up in the Y axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="29523" PostHistoryTypeId="5" PostId="10193" RevisionGUID="3cecfbd3-eaa9-447a-b8a3-845ebe68aa9c" CreationDate="2020-09-05T18:58:55.447" UserId="13909" Comment="added 115 characters in body" Text="What algorithm can i use to pull entere area?&#xD;&#xA;&#xD;&#xA;i have this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;are there many algorithms, which algorithm can you recommended me to implement?&#xD;&#xA;&#xD;&#xA;Edit 1:&#xD;&#xA;&#xD;&#xA;my square was builded with lines (bresenham), i want to move to up in the Y axis&#xD;&#xA;&#xD;&#xA;i want to create this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xhsyf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/i58Bh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29524" PostHistoryTypeId="5" PostId="10193" RevisionGUID="8efeefd6-ae87-4d55-8d9d-243ca5872ddd" CreationDate="2020-09-05T19:14:08.093" UserId="13909" Comment="added 79 characters in body" Text="What algorithm can i use to pull entere area?&#xD;&#xA;&#xD;&#xA;i have this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;are there many algorithms, which algorithm can you recommended me to implement?&#xD;&#xA;&#xD;&#xA;Edit 1:&#xD;&#xA;&#xD;&#xA;my square was builded with lines (bresenham), i want to move to up in the Y axis (i am working without libraries, only math and java, i am using putpixel(x,y))&#xD;&#xA;&#xD;&#xA;i want to create this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xhsyf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/i58Bh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29525" PostHistoryTypeId="34" PostId="10148" RevisionGUID="63f28ebf-09ad-4e07-b5c2-a29b04d33642" CreationDate="2020-09-05T22:02:30.190" UserId="-1" Comment="63" />
  <row Id="29528" PostHistoryTypeId="10" PostId="10193" RevisionGUID="747ea787-df4b-4de2-a679-e3c554055e5b" CreationDate="2020-09-07T08:13:09.573" UserId="13095" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="29529" PostHistoryTypeId="2" PostId="10195" RevisionGUID="184a6eaf-47b3-4679-9d65-b1b2f5bfb281" CreationDate="2020-09-07T08:35:53.553" UserId="209" Text="One other, albeit more expensive approach, is to subdivide your quad into 4 triangles by putting a point at the centre of each quad. There are some advantages to this in that:&#xD;&#xA; 1. It will be more temporarily stable. If your quad vertices are moving and you were otherwise using the &quot;shortest diagonal&quot; approach Nathan has suggested, the tessellation will change pattern every now and then.  Maybe this won't matter *too* much geometrically, but remember that the UV texture coordinates are also linearly interpolated in world space (obviously hyperbolically in screen space) and so the texturing can jump.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA; 3. If the quad is quite distorted (e.g non-planar or non-convex),  I think the 4xtri approach will look much better than either of the two 2xtri options&#xD;&#xA;&#xD;&#xA; 4. If you instead are just chopping into triangles based on the order of the vertices of your quad, i.e. ABCD always becomes ABC and CDA, then if by chance the modelling package spits out another &quot;identical&quot; quad but ordered as BCDA, then the rendered versions won't match.&#xD;&#xA;&#xD;&#xA;Of course, the downside is that you have 2x the number of vertices and triangles, but it may be worth considering.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29531" PostHistoryTypeId="50" PostId="9354" RevisionGUID="a642ced8-ae62-42fb-ac88-ab94f59fb1e2" CreationDate="2020-09-08T08:00:30.053" UserId="-1" />
  <row Id="29532" PostHistoryTypeId="2" PostId="10196" RevisionGUID="f0522645-4284-4d52-ab68-80efb0a91b7c" CreationDate="2020-09-08T12:21:41.167" UserId="10129" Text="For anyone wondering how to deal with it, please refer to mjp (Matt Pettineo) github - https://github.com/TheRealMJP/DXRPathTracer/blob/master/SampleFramework12/v1.02/Graphics/Profiler.cpp&#xD;&#xA;&#xD;&#xA;MJP code is DX12. For DX11, you can refer to my github - https://github.com/komilll/dxFramework/blob/master/dxFramework/Profiler.cpp&#xD;&#xA;&#xD;&#xA;In both DX11 and DX12, you basically just creates timestamps at the beginning and at the end of some portion of code. Then you have to resolve it, based on GPU speed. GPU might work with different clock frequency based on current workload. When you have a full PBR engine with shadow or SSAO, you should already have no problem with changing clock. However, if you're just starting creating your engine/framework, keep in mind that time to execute might not be precise, because you're not using full GPU power.&#xD;&#xA;&#xD;&#xA;In DX12 there is **ID3D12Device::SetStablePowerState** but I've seen multiple times that people are recommending not to use it. Maybe there are some use cases, but for typical hobby usage, I won't bother with that." ContentLicense="CC BY-SA 4.0" />
  <row Id="29533" PostHistoryTypeId="2" PostId="10197" RevisionGUID="6390bee8-3541-4164-8633-63075d7e786a" CreationDate="2020-09-08T13:06:38.543" UserId="10129" Text="I have a problem with RTPSO creation. Using local root signatures for each of rgs (ray generation shader), chs (closest hit), miss is working correctly. However, for performance sake, I want to use global root signature with dummy/empty local root signatures.&#xD;&#xA;&#xD;&#xA;Below code works correctly:&#xD;&#xA;&#xD;&#xA;    void RaytracingResources::CreateRTPSO(ID3D12Device5* device, size_t maxPayloadSize)&#xD;&#xA;    {&#xD;&#xA;        // Need 11 subobjects:&#xD;&#xA;        // 1 for RGS program&#xD;&#xA;        // 1 for Miss program&#xD;&#xA;        // 1 for CHS program&#xD;&#xA;        // 1 for AHS program&#xD;&#xA;        // 1 for Hit Group&#xD;&#xA;        // 2 for RayGen Root Signature (root-signature and association)&#xD;&#xA;        // 2 for Shader Config (config and association)&#xD;&#xA;        // 1 for Global Root Signature&#xD;&#xA;        // 1 for Pipeline Config	&#xD;&#xA;        UINT index = 0;&#xD;&#xA;        std::vector&lt;D3D12_STATE_SUBOBJECT&gt; subobjects;&#xD;&#xA;        size_t size = 0;&#xD;&#xA;        size += 1; // rgs&#xD;&#xA;        for (auto&amp; hitGroup : m_hitGroups)&#xD;&#xA;        {&#xD;&#xA;            size += 2; // chs, miss&#xD;&#xA;            size += (hitGroup.hitShader.ahs.name != nullptr) ? 1 : 0; // ahs&#xD;&#xA;            size += 1; // hit group&#xD;&#xA;            size += 2; // payload + association&#xD;&#xA;            size += 2; // local root + association&#xD;&#xA;        }&#xD;&#xA;        size += 3; // global root + local root + pipeline config&#xD;&#xA;        subobjects.resize(size);&#xD;&#xA;    &#xD;&#xA;        ID3D12RootSignature* dummyLocalRootSignature;&#xD;&#xA;        ID3D12RootSignature* dummyGlobalRootSignature;&#xD;&#xA;        // Create dummy global and local root signature&#xD;&#xA;        {&#xD;&#xA;            HRESULT hr = 0;&#xD;&#xA;            D3D12_ROOT_SIGNATURE_DESC rootDesc = {};&#xD;&#xA;            rootDesc.NumParameters = 0;&#xD;&#xA;            rootDesc.pParameters = nullptr;&#xD;&#xA;            rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;&#xD;&#xA;            ID3DBlob* serializedRootSignature;&#xD;&#xA;            ID3DBlob* error;&#xD;&#xA;    &#xD;&#xA;            // Create the global root signature&#xD;&#xA;            ThrowIfFailed(D3D12SerializeRootSignature(&amp;rootDesc, D3D_ROOT_SIGNATURE_VERSION_1,&#xD;&#xA;                &amp;serializedRootSignature, &amp;error));&#xD;&#xA;    &#xD;&#xA;            ThrowIfFailed(device-&gt;CreateRootSignature(0, serializedRootSignature-&gt;GetBufferPointer(),&#xD;&#xA;                serializedRootSignature-&gt;GetBufferSize(),&#xD;&#xA;                IID_PPV_ARGS(&amp;dummyGlobalRootSignature)));&#xD;&#xA;    &#xD;&#xA;            serializedRootSignature-&gt;Release();&#xD;&#xA;    &#xD;&#xA;            rootDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE;&#xD;&#xA;            // Create the local root signature, reusing the same descriptor but altering the creation flag&#xD;&#xA;            ThrowIfFailed(D3D12SerializeRootSignature(&amp;rootDesc, D3D_ROOT_SIGNATURE_VERSION_1,&#xD;&#xA;                &amp;serializedRootSignature, &amp;error));&#xD;&#xA;    &#xD;&#xA;            ThrowIfFailed(device-&gt;CreateRootSignature(0, serializedRootSignature-&gt;GetBufferPointer(),&#xD;&#xA;                serializedRootSignature-&gt;GetBufferSize(),&#xD;&#xA;                IID_PPV_ARGS(&amp;dummyLocalRootSignature)));&#xD;&#xA;    &#xD;&#xA;            serializedRootSignature-&gt;Release();&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    #pragma region HitGroup creation - 1&#xD;&#xA;        {&#xD;&#xA;            HitGroup hitGroup = m_hitGroups[0];&#xD;&#xA;            // Add state subobject for the RGS&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC rgsExportDesc = { hitGroup.rayGenShader.name, nullptr, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	rgsLibDesc = {};&#xD;&#xA;                rgsLibDesc.DXILLibrary.BytecodeLength = hitGroup.rayGenShader.blob-&gt;GetBufferSize();&#xD;&#xA;                rgsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.rayGenShader.blob-&gt;GetBufferPointer();&#xD;&#xA;                rgsLibDesc.NumExports = 1;&#xD;&#xA;                rgsLibDesc.pExports = &amp;rgsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT rgs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;rgsLibDesc };&#xD;&#xA;                subobjects[index++] = rgs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            //Add state subobject for the Miss shader&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC msExportDesc = { hitGroup.missShader.name, hitGroup.missShader.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	msLibDesc = {};&#xD;&#xA;                msLibDesc.DXILLibrary.BytecodeLength = hitGroup.missShader.blob-&gt;GetBufferSize();&#xD;&#xA;                msLibDesc.DXILLibrary.pShaderBytecode = hitGroup.missShader.blob-&gt;GetBufferPointer();&#xD;&#xA;                msLibDesc.NumExports = 1;&#xD;&#xA;                msLibDesc.pExports = &amp;msExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT ms = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;msLibDesc };&#xD;&#xA;                subobjects[index++] = ms;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add state subobject for the Closest Hit shader&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC chsExportDesc = { hitGroup.hitShader.chs.name, hitGroup.hitShader.chs.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	chsLibDesc = {};&#xD;&#xA;                chsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.chs.blob-&gt;GetBufferSize();&#xD;&#xA;                chsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.chs.blob-&gt;GetBufferPointer();&#xD;&#xA;                chsLibDesc.NumExports = 1;&#xD;&#xA;                chsLibDesc.pExports = &amp;chsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT chs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;chsLibDesc };&#xD;&#xA;                subobjects[index++] = chs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add state subobject for the Any Hit shader&#xD;&#xA;            if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;            {&#xD;&#xA;                D3D12_EXPORT_DESC ahsExportDesc = { hitGroup.hitShader.ahs.name, hitGroup.hitShader.ahs.exportToRename, D3D12_EXPORT_FLAG_NONE };&#xD;&#xA;    &#xD;&#xA;                D3D12_DXIL_LIBRARY_DESC	ahsLibDesc = {};&#xD;&#xA;                ahsLibDesc.DXILLibrary.BytecodeLength = hitGroup.hitShader.ahs.blob-&gt;GetBufferSize();&#xD;&#xA;                ahsLibDesc.DXILLibrary.pShaderBytecode = hitGroup.hitShader.ahs.blob-&gt;GetBufferPointer();&#xD;&#xA;                ahsLibDesc.NumExports = 1;&#xD;&#xA;                ahsLibDesc.pExports = &amp;ahsExportDesc;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT ahs = { D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &amp;ahsLibDesc };&#xD;&#xA;                subobjects[index++] = ahs;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the hit group&#xD;&#xA;            {&#xD;&#xA;                D3D12_HIT_GROUP_DESC hitGroupDesc = {};&#xD;&#xA;                hitGroupDesc.ClosestHitShaderImport = hitGroup.hitShader.chs.name;&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr) hitGroupDesc.AnyHitShaderImport = hitGroup.hitShader.ahs.name;&#xD;&#xA;                hitGroupDesc.HitGroupExport = hitGroup.hitGroupName;&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT hitGroup = { D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &amp;hitGroupDesc };&#xD;&#xA;                subobjects[index++] = hitGroup;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the shader payload configuration&#xD;&#xA;            {&#xD;&#xA;                D3D12_RAYTRACING_SHADER_CONFIG shaderDesc = { static_cast&lt;UINT&gt;(maxPayloadSize), D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES };&#xD;&#xA;                D3D12_STATE_SUBOBJECT shaderConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &amp;shaderDesc };&#xD;&#xA;                subobjects[index++] = shaderConfigObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Create a list of the shader export names that use the payload&#xD;&#xA;            {&#xD;&#xA;                D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION shaderPayloadAssociation = {};&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr) {&#xD;&#xA;                    const WCHAR* shaderExports[] = { hitGroup.rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                    shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };&#xD;&#xA;                }&#xD;&#xA;                else {&#xD;&#xA;                    const WCHAR* shaderExports[] = { hitGroup.rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                    shaderPayloadAssociation = { &amp;subobjects[(index - 1)], _countof(shaderExports), shaderExports };&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT shaderPayloadAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;shaderPayloadAssociation };&#xD;&#xA;                subobjects[index++] = shaderPayloadAssociationObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Add a state subobject for the shared root signature &#xD;&#xA;            {&#xD;&#xA;                D3D12_STATE_SUBOBJECT rayGenRootSigObject = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &amp;hitGroup.rayGenShader.pRootSignature};&#xD;&#xA;                subobjects[index++] = rayGenRootSigObject;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Create a list of the shader export names that use the root signature&#xD;&#xA;            {&#xD;&#xA;                D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION rayGenShaderRootSigAssociation = {};&#xD;&#xA;                if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;                {&#xD;&#xA;                    const WCHAR* rootSigExports[] = { m_hitGroups[0].rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                    rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    const WCHAR* rootSigExports[] = { hitGroup.rayGenShader.name, hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                    rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                D3D12_STATE_SUBOBJECT rayGenShaderRootSigAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;rayGenShaderRootSigAssociation };&#xD;&#xA;                subobjects[index++] = rayGenShaderRootSigAssociationObject;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    #pragma endregion&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // Setup global root signature&#xD;&#xA;        {&#xD;&#xA;            D3D12_STATE_SUBOBJECT globalRootSig = { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &amp;dummyGlobalRootSignature };&#xD;&#xA;            subobjects[index++] = globalRootSig;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // The pipeline construction always requires an empty local root signature&#xD;&#xA;        {&#xD;&#xA;            D3D12_STATE_SUBOBJECT localRootSig = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &amp;dummyLocalRootSignature };&#xD;&#xA;            subobjects[index++] = localRootSig;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Add a state subobject for the ray tracing pipeline config&#xD;&#xA;        {&#xD;&#xA;            D3D12_RAYTRACING_PIPELINE_CONFIG pipelineConfig = { 2 }; // Max Trace Recursion Depth&#xD;&#xA;            D3D12_STATE_SUBOBJECT pipelineConfigObject = { D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &amp;pipelineConfig };&#xD;&#xA;            subobjects[index++] = pipelineConfigObject; &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Finish rtpso creation and store in variable&#xD;&#xA;        {&#xD;&#xA;            // Describe RTPSO&#xD;&#xA;            D3D12_STATE_OBJECT_DESC pipelineDesc = { D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE, static_cast&lt;UINT&gt;(subobjects.size()), subobjects.data() };&#xD;&#xA;    &#xD;&#xA;            // Create the RT Pipeline State Object (RTPSO) / Get the RTPSO properties&#xD;&#xA;            ThrowIfFailed(device-&gt;CreateStateObject(&amp;pipelineDesc, IID_PPV_ARGS(&amp;m_rtpso)));&#xD;&#xA;            ThrowIfFailed(m_rtpso-&gt;QueryInterface(IID_PPV_ARGS(&amp;m_rtpsoInfo)));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, replacing&#xD;&#xA;&#xD;&#xA;    // Setup global root signature&#xD;&#xA;    {&#xD;&#xA;        D3D12_STATE_SUBOBJECT globalRootSig = { D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &amp;dummyGlobalRootSignature };&#xD;&#xA;        subobjects[index++] = globalRootSig;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;with local signature from first code snippet that I've compiled with flag D3D12_ROOT_SIGNATURE_FLAG_NONE instead of D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE. Local signatures for:&#xD;&#xA;&#xD;&#xA;        // Add a state subobject for the shared root signature &#xD;&#xA;        {&#xD;&#xA;            D3D12_STATE_SUBOBJECT rayGenRootSigObject = { D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &amp;hitGroup.rayGenShader.pRootSignature };&#xD;&#xA;            subobjects[index++] = rayGenRootSigObject;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Create a list of the shader export names that use the root signature&#xD;&#xA;        {&#xD;&#xA;            D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION rayGenShaderRootSigAssociation = {};&#xD;&#xA;            if (hitGroup.hitShader.ahs.name != nullptr)&#xD;&#xA;            {&#xD;&#xA;                const WCHAR* rootSigExports[] = { hitGroup.missShader.name, hitGroup.hitShader.chs.name, hitGroup.hitShader.ahs.name };&#xD;&#xA;                rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                const WCHAR* rootSigExports[] = { hitGroup.missShader.name, hitGroup.hitShader.chs.name };&#xD;&#xA;                rayGenShaderRootSigAssociation = { &amp;subobjects[(index - 1)], _countof(rootSigExports), rootSigExports };&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            D3D12_STATE_SUBOBJECT rayGenShaderRootSigAssociationObject = { D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION, &amp;rayGenShaderRootSigAssociation };&#xD;&#xA;            subobjects[index++] = rayGenShaderRootSigAssociationObject;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;are replaced with dummy local signatures. However, every program run is causing error of device removal:&#xD;&#xA;&#xD;&#xA;    D3D12: Removing Device.&#xD;&#xA;    D3D12 ERROR: ID3D12Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_DEVICE_HUNG: The Device took an unreasonable amount of time to execute its commands, or the hardware crashed/hung. As a result, the TDR (Timeout Detection and Recovery) mechanism has been triggered. The current Device Context was executing commands when the hang occurred. The application may want to respawn and fallback to less aggressive use of the display hardware). [ EXECUTION ERROR #232: DEVICE_REMOVAL_PROCESS_AT_FAULT]&#xD;&#xA;&#xD;&#xA;Commenting out **TraceRay(...)** from hlsl is causing program to continue running without causing any errors. Is there problem with my understanding of binding global root signature?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29534" PostHistoryTypeId="1" PostId="10197" RevisionGUID="6390bee8-3541-4164-8633-63075d7e786a" CreationDate="2020-09-08T13:06:38.543" UserId="10129" Text="Global root signature crash" ContentLicense="CC BY-SA 4.0" />
  <row Id="29535" PostHistoryTypeId="3" PostId="10197" RevisionGUID="6390bee8-3541-4164-8633-63075d7e786a" CreationDate="2020-09-08T13:06:38.543" UserId="10129" Text="|raytracing|c++|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29536" PostHistoryTypeId="5" PostId="10196" RevisionGUID="9e1edc78-4774-45e0-b0ae-7666eef1705d" CreationDate="2020-09-08T16:46:11.357" UserId="10129" Comment="added 2 characters in body" Text="For anyone wondering how to deal with it, please refer to mjp (Matt Pettineo) github - https://github.com/TheRealMJP/DXRPathTracer/blob/master/SampleFramework12/v1.02/Graphics/Profiler.cpp&#xD;&#xA;&#xD;&#xA;MJP's code is DX12. For DX11, you can refer to my github - https://github.com/komilll/dxFramework/blob/master/dxFramework/Profiler.cpp&#xD;&#xA;&#xD;&#xA;In both DX11 and DX12, you basically just creates timestamps at the beginning and at the end of some portion of code. Then you have to resolve it, based on GPU speed. GPU might work with different clock frequency based on current workload. When you have a full PBR engine with shadow or SSAO, you should already have no problem with changing clock. However, if you're just starting creating your engine/framework, keep in mind that time to execute might not be precise, because you're not using full GPU power.&#xD;&#xA;&#xD;&#xA;In DX12 there is **ID3D12Device::SetStablePowerState** but I've seen multiple times that people are recommending not to use it. Maybe there are some use cases, but for typical hobby usage, I won't bother with that." ContentLicense="CC BY-SA 4.0" />
  <row Id="29537" PostHistoryTypeId="2" PostId="10198" RevisionGUID="b998e81d-3876-49fa-875f-d2e218ff3755" CreationDate="2020-09-08T17:00:59.060" UserId="10129" Text="I managed to create code, working correctly as Texture2DArray in hlsl by using single ID3D12Resource and binding it as D3D12_SRV_DIMENSION_TEXTURE2DARRAY with constant array size.&#xD;&#xA;&#xD;&#xA;    std::pair&lt;ComPtr&lt;ID3D12Resource&gt;, D3D12_SUBRESOURCE_DATA&gt; ModelClass::GetTextureFromModel(const aiScene* scene, std::string filename, ComPtr&lt;ID3D12Device2&gt; device, ComPtr&lt;ID3D12GraphicsCommandList4&gt; commandList, int index)&#xD;&#xA;    {&#xD;&#xA;    	D3D12_SUBRESOURCE_DATA textureDataSingle;&#xD;&#xA;    	std::unique_ptr&lt;uint8_t[]&gt; decodedData;&#xD;&#xA;    	ComPtr&lt;ID3D12Resource&gt; texture;&#xD;&#xA;    	m_uploadHeaps.push_back({});&#xD;&#xA;    &#xD;&#xA;    	std::string s = std::regex_replace(filename, std::regex(&quot;\\\\&quot;), &quot;/&quot;);&#xD;&#xA;    &#xD;&#xA;    	std::wstring ws(s.begin(), s.end());&#xD;&#xA;    	ThrowIfFailed(LoadWICTextureFromFileEx(device.Get(), ws.c_str(), 0, D3D12_RESOURCE_FLAG_NONE, WIC_LOADER_FORCE_RGBA32, texture.ReleaseAndGetAddressOf(), decodedData, textureDataSingle));&#xD;&#xA;    &#xD;&#xA;    	const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, 1);&#xD;&#xA;    &#xD;&#xA;    	// uploadHeap must outlive this function - until command list is closed&#xD;&#xA;    	ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;    		&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),&#xD;&#xA;    		D3D12_HEAP_FLAG_NONE,&#xD;&#xA;    		&amp;CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),&#xD;&#xA;    		D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;    		nullptr,&#xD;&#xA;    		IID_PPV_ARGS(&amp;m_uploadHeaps[m_uploadHeaps.size() - 1])&#xD;&#xA;    	));&#xD;&#xA;    &#xD;&#xA;    	UpdateSubresources(commandList.Get(), texture.Get(), m_uploadHeaps[m_uploadHeaps.size() - 1].Get(), 0, 0, 1, &amp;textureDataSingle);&#xD;&#xA;    &#xD;&#xA;    	if (texture-&gt;GetDesc().Width == 128 &amp;&amp; texture-&gt;GetDesc().Height == 128)&#xD;&#xA;    	{&#xD;&#xA;    		commandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE));&#xD;&#xA;    &#xD;&#xA;    		D3D12_TEXTURE_COPY_LOCATION dst{};&#xD;&#xA;    		dst.pResource = m_diffuseTextures[index].Get();&#xD;&#xA;    		dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;&#xD;&#xA;    		dst.SubresourceIndex = index;&#xD;&#xA;    &#xD;&#xA;    		D3D12_TEXTURE_COPY_LOCATION src{};&#xD;&#xA;    		src.pResource = texture.Get();&#xD;&#xA;    &#xD;&#xA;    		commandList-&gt;CopyTextureRegion(&amp;dst, 0, 0, 0, &amp;src, nullptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return { texture, textureDataSingle };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However it uses same resource description for all array slices (i.e. width and height). I replaced last &quot;if&quot; with code below:&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;		commandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE));&#xD;&#xA;&#xD;&#xA;		D3D12_RESOURCE_DESC textureDesc = {};&#xD;&#xA;		textureDesc.MipLevels = 1;&#xD;&#xA;		textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;		textureDesc.Width = texture-&gt;GetDesc().Width;&#xD;&#xA;		textureDesc.Height = texture-&gt;GetDesc().Height;&#xD;&#xA;		textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;&#xD;&#xA;		textureDesc.DepthOrArraySize = 1;&#xD;&#xA;		textureDesc.SampleDesc.Count = 1;&#xD;&#xA;		textureDesc.SampleDesc.Quality = 0;&#xD;&#xA;		textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;&#xD;&#xA;&#xD;&#xA;		ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;			&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),&#xD;&#xA;			D3D12_HEAP_FLAG_NONE,&#xD;&#xA;			&amp;textureDesc,&#xD;&#xA;			D3D12_RESOURCE_STATE_COPY_DEST,&#xD;&#xA;			nullptr,&#xD;&#xA;			IID_PPV_ARGS(&amp;m_diffuseTextures[index])&#xD;&#xA;		));&#xD;&#xA;&#xD;&#xA;		D3D12_TEXTURE_COPY_LOCATION dst{};&#xD;&#xA;		dst.pResource = m_diffuseTextures[index].Get();&#xD;&#xA;&#xD;&#xA;		D3D12_TEXTURE_COPY_LOCATION src{};&#xD;&#xA;		src.pResource = texture.Get();&#xD;&#xA;&#xD;&#xA;		commandList-&gt;CopyTextureRegion(&amp;dst, 0, 0, 0, &amp;src, nullptr);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I don't have any errors, so I assume that data is loaded correctly. However, how can I upload std::vector&lt;ID3D12Resource&gt; or std::array&lt;...&gt; to GPU and use it with Texture2D[]?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29538" PostHistoryTypeId="1" PostId="10198" RevisionGUID="b998e81d-3876-49fa-875f-d2e218ff3755" CreationDate="2020-09-08T17:00:59.060" UserId="10129" Text="Using array of textures in DX12" ContentLicense="CC BY-SA 4.0" />
  <row Id="29539" PostHistoryTypeId="3" PostId="10198" RevisionGUID="b998e81d-3876-49fa-875f-d2e218ff3755" CreationDate="2020-09-08T17:00:59.060" UserId="10129" Text="|texture|c++|hlsl|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29540" PostHistoryTypeId="2" PostId="10199" RevisionGUID="1b2d9cec-4e01-42c9-9763-4e979bcb2c0b" CreationDate="2020-09-08T23:35:51.777" UserId="13938" Text="Nowadays is less of an issue, i think SS got massaged a little bit, but you can still spot it. These happen with SS Reflections, SSAO and Bloom. When you move the camera, the effect starts to flciker rather than move smoothly with wtv object it's attached to. Why it happens?&#xD;&#xA;&#xD;&#xA;Example of what i'm talking about:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pXXya.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="29541" PostHistoryTypeId="1" PostId="10199" RevisionGUID="1b2d9cec-4e01-42c9-9763-4e979bcb2c0b" CreationDate="2020-09-08T23:35:51.777" UserId="13938" Text="Why Screen Space effects flicker?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29542" PostHistoryTypeId="3" PostId="10199" RevisionGUID="1b2d9cec-4e01-42c9-9763-4e979bcb2c0b" CreationDate="2020-09-08T23:35:51.777" UserId="13938" Text="|reflection|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29543" PostHistoryTypeId="2" PostId="10200" RevisionGUID="1204f6e0-222a-4735-9481-3dab7abd5284" CreationDate="2020-09-09T14:55:12.103" UserId="7462" Text="So I am doing a gradient descent like algorithm on the surface of a mesh and I just noticed something:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The above is the geodesic gradient (the distance to a single vertex)&#xD;&#xA;&#xD;&#xA;Look at where the ear connects with the head and notice how the discretized gradient behaves.&#xD;&#xA;It's almost pointing in opposite directions. This is not however an error, this occurs because the gradient at that region is fairly &quot;turbulent&quot;.&#xD;&#xA;&#xD;&#xA;My algorithm is fairly simple, grab a point in a triangle, compute its negative gradient, intersect the gradient with the triangle, move there, switch active triangle to the neighbour, repeat.&#xD;&#xA;&#xD;&#xA;In other words you just follow the gradient down towards the source. &#xD;&#xA;&#xD;&#xA;However, when I hit those turbulent regions, my algorithm gets stuck, because the gradient becomes essentially 0 and numerical errors prevent it from intersecting any of the edges of the triangle.&#xD;&#xA;&#xD;&#xA;In pictures:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The green points are the path taken by my gradient descent algorithm. The cyan ones are the centres of the faces of the triangles and the yellow arrow is the gradient at the last point.&#xD;&#xA;&#xD;&#xA;Notice that this result is correct.&#xD;&#xA;&#xD;&#xA;However, at the ears:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you can see the algorithm stops because the gradient is borderline 0.&#xD;&#xA;&#xD;&#xA;And worse there are regions in the ears where the turbulence makes the gradient bounce and start travelling in the opposite direction.&#xD;&#xA;&#xD;&#xA;Does anyone have tips on how I could handle the gradient in these regions?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/L3hx3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DgE3e.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/TVERW.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29544" PostHistoryTypeId="1" PostId="10200" RevisionGUID="1204f6e0-222a-4735-9481-3dab7abd5284" CreationDate="2020-09-09T14:55:12.103" UserId="7462" Text="Gradient descent (Not ML) on arbitrary meshes" ContentLicense="CC BY-SA 4.0" />
  <row Id="29545" PostHistoryTypeId="3" PostId="10200" RevisionGUID="1204f6e0-222a-4735-9481-3dab7abd5284" CreationDate="2020-09-09T14:55:12.103" UserId="7462" Text="|mathematics|computational-geometry|geometry|mesh|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29546" PostHistoryTypeId="2" PostId="10201" RevisionGUID="ce92dcb6-d1bc-418e-b009-3925d2d7c42a" CreationDate="2020-09-09T15:21:30.430" UserId="6281" Text="I am wondering why the texture of the following 3D model https://app.ignitionrobotics.org/GoogleResearch/fuel/models/Transformers_Age_of_Extinction_Mega_1Step_Bumblebee_Figure &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1vdYb.png&#xD;&#xA;&#xD;&#xA;Looks like the following:&#xD;&#xA;&#xD;&#xA;https://i.stack.imgur.com/A9Gd0.jpg&#xD;&#xA;&#xD;&#xA;How are these logically connected?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29547" PostHistoryTypeId="1" PostId="10201" RevisionGUID="ce92dcb6-d1bc-418e-b009-3925d2d7c42a" CreationDate="2020-09-09T15:21:30.430" UserId="6281" Text="How does the texture file should look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29548" PostHistoryTypeId="3" PostId="10201" RevisionGUID="ce92dcb6-d1bc-418e-b009-3925d2d7c42a" CreationDate="2020-09-09T15:21:30.430" UserId="6281" Text="|texture|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29549" PostHistoryTypeId="2" PostId="10202" RevisionGUID="ad6ce88e-ecc5-45c9-a8a3-60821ea34ca2" CreationDate="2020-09-09T15:53:45.680" UserId="13943" Text="I generate random directions from the pdf of D term in GGX BRDF. On the picture white dots are new directions and the cross is the light direction, with roughness = 1. What should I do with the directions that are generated below the hemisphere? Should and can i just discard them? Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![sampled directions][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UUAaT.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29550" PostHistoryTypeId="1" PostId="10202" RevisionGUID="ad6ce88e-ecc5-45c9-a8a3-60821ea34ca2" CreationDate="2020-09-09T15:53:45.680" UserId="13943" Text="What to do when new sampled direction is below normal oriented hemisphere?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29551" PostHistoryTypeId="3" PostId="10202" RevisionGUID="ad6ce88e-ecc5-45c9-a8a3-60821ea34ca2" CreationDate="2020-09-09T15:53:45.680" UserId="13943" Text="|raytracing|pathtracing|brdf|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29552" PostHistoryTypeId="2" PostId="10203" RevisionGUID="b75c3227-cd9c-4322-8a6e-79aa76b1006b" CreationDate="2020-09-09T16:47:00.620" UserId="2479" Text="Disclaimer: I am assuming that you are implementing a classical Monte Carlo estimator.&#xD;&#xA;&#xD;&#xA;Discarding samples will change PDF of your sampling technique. You are cutting off part of the sampled domain where PDF is non-zero, which effectively leads to a trimmed version of the original PDF but implicitly re-normalized so the remaining part integrates to 1. If you don't adjust the directly evaluated PDF accordingly, it will lead to a biased estimator.&#xD;&#xA;&#xD;&#xA;Practically speaking, implicit re-normalization increases the actual sampling PDF. Because in Monte Carlo integration you divide the integrand with $p$ - the actual PDF of the used sample, but in fact you use incorrect $p^*&lt;p$ yielding brighter values:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{p(x)} &gt; \frac{f(x)}{p^*(x)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Since adjusting the PDF isn't an easy thing to do, you will most likely need to **treat the under-surface samples as valid but with zero contribution**. Whether you handle this within your BRDF/BSDF or elsewhere in the renderer is your design decision." ContentLicense="CC BY-SA 4.0" />
  <row Id="29553" PostHistoryTypeId="5" PostId="10203" RevisionGUID="949e8b68-8cbc-4bfb-b77c-66c9a6b4535f" CreationDate="2020-09-09T17:07:28.863" UserId="2479" Comment="Expanded: structure, better solution" Text="Disclaimer: I am assuming that you are implementing a classical Monte Carlo estimator.&#xD;&#xA;&#xD;&#xA;## The Problem&#xD;&#xA;&#xD;&#xA;Discarding samples will change PDF of your sampling technique. You are cutting off part of the sampled domain where PDF is non-zero, which effectively leads to a trimmed version of the original PDF but implicitly re-normalized so the remaining part integrates to 1. If you don't adjust the directly evaluated PDF accordingly, it will lead to a biased estimator.&#xD;&#xA;&#xD;&#xA;Practically speaking, implicit re-normalization increases the actual sampling PDF $p$, but you use the old $p^*&lt;p$, so the resulting Monte Carlo estimator will yield brighter values:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{p^*(x)} &gt; \frac{f(x)}{p(x)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;## A solution&#xD;&#xA;&#xD;&#xA;Since adjusting the PDF isn't an easy thing to do, you will most likely need to **treat the under-surface samples as valid but with zero contribution**. Whether you handle this within your BRDF/BSDF or elsewhere in the renderer is your design decision.&#xD;&#xA;&#xD;&#xA;Zero-contribution samples will, obviously, introduce some efficiency in your renderer.&#xD;&#xA;&#xD;&#xA;## A better solution&#xD;&#xA;&#xD;&#xA;You can improve the efficiency of your estimator by using a better sampling technique which tries to avoid creating samples under the surface. n case of the GGX normal distribution, there have been proposed some solutions by Eric Heitz | Eugene d’Eon in paper [Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals][1]. I believe there was one improved version of this technique (other that the one mentioned in the &quot;Related Work&quot; section) but I cannot recall the name of it. Maybe someone else can add it here...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.eugenedeon.com/project/importance-sampling-microfacet-based-bsdfs-using-the-distribution-of-visible-normals/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29554" PostHistoryTypeId="5" PostId="10203" RevisionGUID="1578af13-2ab2-40c8-af33-ce38b2f4908f" CreationDate="2020-09-09T17:10:42.487" UserId="48" Comment="typo" Text="Disclaimer: I am assuming that you are implementing a classical Monte Carlo estimator.&#xD;&#xA;&#xD;&#xA;## The Problem&#xD;&#xA;&#xD;&#xA;Discarding samples will change PDF of your sampling technique. You are cutting off part of the sampled domain where PDF is non-zero, which effectively leads to a trimmed version of the original PDF but implicitly re-normalized so the remaining part integrates to 1. If you don't adjust the directly evaluated PDF accordingly, it will lead to a biased estimator.&#xD;&#xA;&#xD;&#xA;Practically speaking, implicit re-normalization increases the actual sampling PDF $p$, but you use the old $p^*&lt;p$, so the resulting Monte Carlo estimator will yield brighter values:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{p^*(x)} &gt; \frac{f(x)}{p(x)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;## A solution&#xD;&#xA;&#xD;&#xA;Since adjusting the PDF isn't an easy thing to do, you will most likely need to **treat the under-surface samples as valid but with zero contribution**. Whether you handle this within your BRDF/BSDF or elsewhere in the renderer is your design decision.&#xD;&#xA;&#xD;&#xA;Zero-contribution samples will, obviously, introduce some inefficiency in your renderer.&#xD;&#xA;&#xD;&#xA;## A better solution&#xD;&#xA;&#xD;&#xA;You can improve the efficiency of your estimator by using a better sampling technique which tries to avoid creating samples under the surface. n case of the GGX normal distribution, there have been proposed some solutions by Eric Heitz | Eugene d’Eon in paper [Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals][1]. I believe there was one improved version of this technique (other that the one mentioned in the &quot;Related Work&quot; section) but I cannot recall the name of it. Maybe someone else can add it here...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.eugenedeon.com/project/importance-sampling-microfacet-based-bsdfs-using-the-distribution-of-visible-normals/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29555" PostHistoryTypeId="5" PostId="10203" RevisionGUID="d5f95175-bc59-4443-9cd0-8a4c1f46c15b" CreationDate="2020-09-09T17:16:22.673" UserId="2479" Comment="Better PDF notation and formulation" Text="Disclaimer: I am assuming that you are implementing a classical Monte Carlo estimator.&#xD;&#xA;&#xD;&#xA;## The Problem&#xD;&#xA;&#xD;&#xA;Discarding samples will change PDF of your sampling technique. You are cutting off part of the sampled domain where PDF is non-zero, which effectively leads to a trimmed version of the original PDF but implicitly re-normalized so the remaining part integrates to 1. If you don't adjust the directly evaluated PDF accordingly, it will lead to a biased estimator.&#xD;&#xA;&#xD;&#xA;Practically speaking, implicit re-normalization increases the actual sampling PDF $p^{new}$, and if you use $p^{old}&lt;p^{new}$ in your computations instead, the resulting Monte Carlo estimator will yield brighter values than it should:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{p^{old}(x)} &gt; \frac{f(x)}{p^{new}(x)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;## A solution&#xD;&#xA;&#xD;&#xA;Since adjusting the PDF isn't an easy thing to do, you will most likely need to **treat the under-surface samples as valid but with zero contribution**. Whether you handle this within your BRDF/BSDF or elsewhere in the renderer is your design decision.&#xD;&#xA;&#xD;&#xA;Zero-contribution samples will, obviously, introduce some inefficiency in your renderer.&#xD;&#xA;&#xD;&#xA;## A better solution&#xD;&#xA;&#xD;&#xA;You can improve the efficiency of your estimator by using a better sampling technique which tries to avoid creating samples under the surface. In case of the GGX normal distribution, there have been proposed some solutions by Eric Heitz | Eugene d’Eon in paper [Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals][1]. I believe there was one improved version of this technique (other that the one mentioned in the &quot;Related Work&quot; section) but I cannot recall the name of it. Maybe someone else can add it here...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.eugenedeon.com/project/importance-sampling-microfacet-based-bsdfs-using-the-distribution-of-visible-normals/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29556" PostHistoryTypeId="2" PostId="10204" RevisionGUID="cb639609-0314-4dbe-b43f-381e4417f78f" CreationDate="2020-09-09T17:34:13.237" UserId="11058" Text="[This post](https://cs.stackexchange.com/questions/2450/how-do-i-construct-a-doubly-connected-edge-list-given-a-set-of-line-segments?newreg=1d611fc139b64175a8ba4ba0823ba6be) explains how to construct double connected edge list in 2d. One of the steps in the algorithm is to sort the halfedges around a vertex in clockwise order. However this will not work in 3d. We can project the halfedge coordinates onto 2d viewplane and sort them that way (if the construction is user interactive). However this would make the construction dependent on the user view.&#xD;&#xA;&#xD;&#xA;What sort of algorithm would we use for 3d case of double connected edge list?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29557" PostHistoryTypeId="1" PostId="10204" RevisionGUID="cb639609-0314-4dbe-b43f-381e4417f78f" CreationDate="2020-09-09T17:34:13.237" UserId="11058" Text="Algorithm for constructing doubly connected edge list in 3d" ContentLicense="CC BY-SA 4.0" />
  <row Id="29558" PostHistoryTypeId="3" PostId="10204" RevisionGUID="cb639609-0314-4dbe-b43f-381e4417f78f" CreationDate="2020-09-09T17:34:13.237" UserId="11058" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29559" PostHistoryTypeId="2" PostId="10205" RevisionGUID="8d46b9b3-d2f4-4106-aabe-5413ac484303" CreationDate="2020-09-09T18:28:09.170" UserId="48" Text="Maybe you can find a heuristic to detect when it gets stuck (e.g. gradient magnitude is too small, or it stays on the same triangle or returns to a recently visited triangle too many times in a row, or it hasn't moved at least X distance over the last N steps, etc) and just take a random step in some direction, e.g. to some randomly chosen neighboring triangle? That might help shake it out of the difficult region and get back to smooth descent.&#xD;&#xA;&#xD;&#xA;For an even lower-tech solution, if you don't mind some randomness you could just inject occasional random moves all the time (without attempting to detect whether it's stuck). Kind of like stochastic gradient descent in ML.&#xD;&#xA;&#xD;&#xA;If the gradient you're following is a geodesic distance, I think it can have saddle points, but not local minima (except for the global minimum), is that right? If that's a constraint you can rely on, you could try to use a second-order method, finding an estimate of the local Hessian and looking for eigenvectors with negative eigenvalues, which should be directions that will accelerate the gradient descent, and in particular, will pull you out of saddle points. I'm sure there must be a literature on such methods although I don't know much about it." ContentLicense="CC BY-SA 4.0" />
  <row Id="29560" PostHistoryTypeId="5" PostId="10198" RevisionGUID="022f3b4d-72e1-45e5-85fb-3630b77b5a4f" CreationDate="2020-09-09T18:34:47.643" UserId="10129" Comment="added 610 characters in body" Text="I managed to create code, working correctly as Texture2DArray in hlsl by using single ID3D12Resource and binding it as D3D12_SRV_DIMENSION_TEXTURE2DARRAY with constant array size.&#xD;&#xA;&#xD;&#xA;    std::pair&lt;ComPtr&lt;ID3D12Resource&gt;, D3D12_SUBRESOURCE_DATA&gt; ModelClass::GetTextureFromModel(const aiScene* scene, std::string filename, ComPtr&lt;ID3D12Device2&gt; device, ComPtr&lt;ID3D12GraphicsCommandList4&gt; commandList, int index)&#xD;&#xA;    {&#xD;&#xA;    	D3D12_SUBRESOURCE_DATA textureDataSingle;&#xD;&#xA;    	std::unique_ptr&lt;uint8_t[]&gt; decodedData;&#xD;&#xA;    	ComPtr&lt;ID3D12Resource&gt; texture;&#xD;&#xA;    	m_uploadHeaps.push_back({});&#xD;&#xA;    &#xD;&#xA;    	std::string s = std::regex_replace(filename, std::regex(&quot;\\\\&quot;), &quot;/&quot;);&#xD;&#xA;    &#xD;&#xA;    	std::wstring ws(s.begin(), s.end());&#xD;&#xA;    	ThrowIfFailed(LoadWICTextureFromFileEx(device.Get(), ws.c_str(), 0, D3D12_RESOURCE_FLAG_NONE, WIC_LOADER_FORCE_RGBA32, texture.ReleaseAndGetAddressOf(), decodedData, textureDataSingle));&#xD;&#xA;    &#xD;&#xA;    	const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, 1);&#xD;&#xA;    &#xD;&#xA;    	// uploadHeap must outlive this function - until command list is closed&#xD;&#xA;    	ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;    		&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),&#xD;&#xA;    		D3D12_HEAP_FLAG_NONE,&#xD;&#xA;    		&amp;CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),&#xD;&#xA;    		D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;    		nullptr,&#xD;&#xA;    		IID_PPV_ARGS(&amp;m_uploadHeaps[m_uploadHeaps.size() - 1])&#xD;&#xA;    	));&#xD;&#xA;    &#xD;&#xA;    	UpdateSubresources(commandList.Get(), texture.Get(), m_uploadHeaps[m_uploadHeaps.size() - 1].Get(), 0, 0, 1, &amp;textureDataSingle);&#xD;&#xA;    &#xD;&#xA;    	if (texture-&gt;GetDesc().Width == 128 &amp;&amp; texture-&gt;GetDesc().Height == 128)&#xD;&#xA;    	{&#xD;&#xA;    		commandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE));&#xD;&#xA;    &#xD;&#xA;    		D3D12_TEXTURE_COPY_LOCATION dst{};&#xD;&#xA;    		dst.pResource = m_diffuseTextures[index].Get();&#xD;&#xA;    		dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;&#xD;&#xA;    		dst.SubresourceIndex = index;&#xD;&#xA;    &#xD;&#xA;    		D3D12_TEXTURE_COPY_LOCATION src{};&#xD;&#xA;    		src.pResource = texture.Get();&#xD;&#xA;    &#xD;&#xA;    		commandList-&gt;CopyTextureRegion(&amp;dst, 0, 0, 0, &amp;src, nullptr);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return { texture, textureDataSingle };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However it uses same resource description for all array slices (i.e. width and height). I replaced last &quot;if&quot; with code below:&#xD;&#xA;&#xD;&#xA;    {&#xD;&#xA;		commandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_SOURCE));&#xD;&#xA;&#xD;&#xA;		D3D12_RESOURCE_DESC textureDesc = {};&#xD;&#xA;		textureDesc.MipLevels = 1;&#xD;&#xA;		textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;&#xD;&#xA;		textureDesc.Width = texture-&gt;GetDesc().Width;&#xD;&#xA;		textureDesc.Height = texture-&gt;GetDesc().Height;&#xD;&#xA;		textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;&#xD;&#xA;		textureDesc.DepthOrArraySize = 1;&#xD;&#xA;		textureDesc.SampleDesc.Count = 1;&#xD;&#xA;		textureDesc.SampleDesc.Quality = 0;&#xD;&#xA;		textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;&#xD;&#xA;&#xD;&#xA;		ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;			&amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),&#xD;&#xA;			D3D12_HEAP_FLAG_NONE,&#xD;&#xA;			&amp;textureDesc,&#xD;&#xA;			D3D12_RESOURCE_STATE_COPY_DEST,&#xD;&#xA;			nullptr,&#xD;&#xA;			IID_PPV_ARGS(&amp;m_diffuseTextures[index])&#xD;&#xA;		));&#xD;&#xA;&#xD;&#xA;		D3D12_TEXTURE_COPY_LOCATION dst{};&#xD;&#xA;		dst.pResource = m_diffuseTextures[index].Get();&#xD;&#xA;&#xD;&#xA;		D3D12_TEXTURE_COPY_LOCATION src{};&#xD;&#xA;		src.pResource = texture.Get();&#xD;&#xA;&#xD;&#xA;		commandList-&gt;CopyTextureRegion(&amp;dst, 0, 0, 0, &amp;src, nullptr);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;I don't have any errors, so I assume that data is loaded correctly. However, how can I upload std::vector&lt;ID3D12Resource&gt; or std::array&lt;...&gt; to GPU and use it with Texture2D[]?&#xD;&#xA;___&#xD;&#xA;Edit: @Nathan Reed I am trying to upload multiple textures to GPU, to use in shader code (hlsl). Currently I am using single ID3D12Resource with chosen value of &quot;DepthOrArraySize&quot; and fixed width and height for all subresources. Then I am treating it as Texture2DArray when creating SRV. As a result, I have **Texture2DArray&lt;float4&gt;** in my hlsl which works fine, but requirement of having fixed width/height for all elements is not convenient. I want to replace it with code, which enable me to use **Texture2D[]** in hlsl, where each texture may have different size. Dynamic indexing is not necessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="29561" PostHistoryTypeId="5" PostId="10205" RevisionGUID="8f8331b2-4b19-4f02-81dc-5c5a94a7adae" CreationDate="2020-09-09T21:20:11.080" UserId="48" Comment="added 124 characters in body" Text="Maybe you can find a heuristic to detect when it gets stuck (e.g. gradient magnitude is too small, or it stays on the same triangle or returns to a recently visited triangle too many times in a row, or it hasn't moved at least X distance over the last N steps, etc) and just take a random step in some direction, e.g. to some randomly chosen neighboring triangle? That might help shake it out of the difficult region and get back to smooth descent.&#xD;&#xA;&#xD;&#xA;For an even lower-tech solution, if you don't mind some randomness you could just inject occasional random moves all the time (without attempting to detect whether it's stuck). Kind of like stochastic gradient descent in ML.&#xD;&#xA;&#xD;&#xA;If the gradient you're following is a geodesic distance, I think it can have saddle points, but not local minima (except for the global minimum), is that right? If that's a constraint you can rely on, you could try to use a second-order method, finding an estimate of the local [Hessian](https://en.wikipedia.org/wiki/Hessian_matrix) and looking for eigenvectors with negative eigenvalues, which should be [directions of principal curvature](https://en.wikipedia.org/wiki/Principal_curvature) that will accelerate the gradient descent, and in particular, will pull you out of saddle points. I'm sure there must be a literature on such methods although I don't know much about it." ContentLicense="CC BY-SA 4.0" />
  <row Id="29562" PostHistoryTypeId="52" PostId="10202" RevisionGUID="c21447b4-e8dc-4d9e-b361-2b33f3d4fe1f" CreationDate="2020-09-09T23:56:22.320" />
  <row Id="29565" PostHistoryTypeId="5" PostId="10202" RevisionGUID="dffc2cb7-2860-46f7-b4cf-95431f6dc694" CreationDate="2020-09-10T05:38:59.453" UserId="3304" Comment="Fixed the question formation - missing auxiliary (or helping) verb - see e.g. &lt;https://www.youtube.com/watch?v=t4yWEt0OSpg&amp;t=1m49s&gt; (see also &lt;https://www.youtube.com/watch?v=kS5NfSzXfrI&gt; (QUASM)).  Removed meta information (this belongs in comments)." Text="I generate random directions from the pdf of D term in GGX BRDF. On the picture, white dots are new directions and the cross is the light direction, with roughness = 1. What should I do with the directions that are generated below the hemisphere? Should and can I just discard them?&#xD;&#xA;&#xD;&#xA;[![Sampled directions][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UUAaT.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29566" PostHistoryTypeId="4" PostId="10202" RevisionGUID="dffc2cb7-2860-46f7-b4cf-95431f6dc694" CreationDate="2020-09-10T05:38:59.453" UserId="3304" Comment="Fixed the question formation - missing auxiliary (or helping) verb - see e.g. &lt;https://www.youtube.com/watch?v=t4yWEt0OSpg&amp;t=1m49s&gt; (see also &lt;https://www.youtube.com/watch?v=kS5NfSzXfrI&gt; (QUASM)).  Removed meta information (this belongs in comments)." Text="What should I do when a new sampled direction is below a normal oriented hemisphere?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29567" PostHistoryTypeId="24" PostId="10202" RevisionGUID="dffc2cb7-2860-46f7-b4cf-95431f6dc694" CreationDate="2020-09-10T05:38:59.453" Comment="Proposed by 3304 approved by 13095 edit id of 543" ContentLicense="CC BY-SA 4.0" />
  <row Id="29568" PostHistoryTypeId="2" PostId="10207" RevisionGUID="c251fd08-8dfa-428d-868b-12c9b36ca7a9" CreationDate="2020-09-10T09:23:44.667" UserId="228" Text="I'm not sure this is the right place to ask for this reference but it's worth the shot since it is graphics related.&#xD;&#xA;&#xD;&#xA;I'm looking for the very first paper describing what &quot;Inverse Rendering&quot; - By that I mean a machine learning system that given some renderer and a deep learning model and an image as input will provide you one or more maps describing how to render the same image.&#xD;&#xA;&#xD;&#xA;I cannot manage to find anywhere a/the white paper the would describe how such system would work.&#xD;&#xA;&#xD;&#xA;Can anyone provide a reference? Maybe not the very first paper but a white paper that might describe the fundamentals (I'd rather prefer papers to web articles).&#xD;&#xA;&#xD;&#xA;Thank you" ContentLicense="CC BY-SA 4.0" />
  <row Id="29569" PostHistoryTypeId="1" PostId="10207" RevisionGUID="c251fd08-8dfa-428d-868b-12c9b36ca7a9" CreationDate="2020-09-10T09:23:44.667" UserId="228" Text="Reference for Inverse Rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="29570" PostHistoryTypeId="3" PostId="10207" RevisionGUID="c251fd08-8dfa-428d-868b-12c9b36ca7a9" CreationDate="2020-09-10T09:23:44.667" UserId="228" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29571" PostHistoryTypeId="6" PostId="10201" RevisionGUID="cdac1678-52a4-448a-9038-1ff8c710cdf3" CreationDate="2020-09-10T10:56:05.630" UserId="6" Comment="edited tags" Text="|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29572" PostHistoryTypeId="2" PostId="10208" RevisionGUID="6fb6e9fc-1208-4d66-8447-96105d7eaa0c" CreationDate="2020-09-10T13:33:43.793" UserId="7952" Text="For a mesh that is not closed then, by definition, there is no interior or exterior, only points on the surface and points that are not on the surface.&#xD;&#xA;&#xD;&#xA;So your first step is to make the hand a &quot;Closed Concave Polyhedron&quot; by closing any openings it has. This can be done relatively simply by defining a plane where the hand is open. (such as at the wrist)&#xD;&#xA;&#xD;&#xA;With that done your first test is to determine if a point is on the hand side of the plane or the non hand side of the plane. ( A more generic solution would be to require the polyhedron to be closed and solve the closure part as a separate problem). It sounds like this has already been done for you with the bounding box that the hand lies inside. If that is the case then your first step is to determine if the point is inside the bound box or outside the bounding box. If it is outside the bounding box you are done. If it is inside then you must now check to see if it is inside the hand.&#xD;&#xA;&#xD;&#xA;Note: If you don't close the polyhedron in some way, then there is no algorithm that can reliably determine interior/exterior. This is one of the things that lightxbulb was eluding to with the first suggestion. For example, I have taken biology classes that consider your entire digestive track to be &quot;outside&quot; your body.&#xD;&#xA;&#xD;&#xA;A very common and fast method to determine if a point is inside a concave polyhedron is called ray casting. (suggestion 3 from lightxbulb) Using this technique you pick a random point usually outside the enclosed area, I would recommend picking a point outside the unit cube since you know for certain that your are starting outside the mesh.&#xD;&#xA;&#xD;&#xA;The point your are testing and the random point you picked can be used to form a line. Do not use a line that is infinitely long, instead your line has a start (the point outside the mesh) and an end (the point you are testing)&#xD;&#xA;&#xD;&#xA;Now you just brute force test every triangle in the mesh to see if they intersect with the line. Along the way you are counting the number of intersections that occur. If your point is inside the mesh then the line will pass through an odd number of triangles if your point is outside the mesh then your line will pass through an even number of points.&#xD;&#xA;&#xD;&#xA;I recommend drawing simple hand shape on a piece of paper, picking the two points, draw the line then count the intersections with the hand. This should make it much more clear why this works.&#xD;&#xA;&#xD;&#xA;If you do not close the polyhedron then you can get unlucky and there will be a line that can get inside the mesh without passing through it and this algorithm will fail. So one of the &quot;triangles&quot; you must test against is the plane that closes the mesh and it must be counted as a pass through a triangle or you could end up with false positive/negative.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29574" PostHistoryTypeId="2" PostId="10209" RevisionGUID="be24594a-b31f-460c-be13-fbbba0d1a586" CreationDate="2020-09-11T07:41:25.353" UserId="10129" Text="I did only quick google search and found this PhD thesis - &quot;Inverse rendering for computer graphics&quot; by [Marschner1998] - http://graphics.stanford.edu/~srm/thesis/thesis.pdf&#xD;&#xA;&#xD;&#xA;Also two published papers - Ramamoorthi et al &quot;A Signal-Processing Framework for Inverse Rendering&quot; http://cseweb.ucsd.edu/~ravir/papers/invrend/invrend.pdf &#xD;&#xA;&#xD;&#xA;And Yu, Smith - &quot;InverseRenderNet: Learning Single image inverse - &#xD;&#xA;https://openaccess.thecvf.com/content_CVPR_2019/papers/Yu_InverseRenderNet_Learning_Single_Image_Inverse_Rendering_CVPR_2019_paper.pdf&#xD;&#xA;___&#xD;&#xA;Based on my experience, just follow prior works in this area and you'll get to the first or first worth mentioning paper in this area. With every paper in the area of raytracing, you'll get reference to [Whitted1980]. Every BRDF will get you back to &#xD;&#xA;[CT1967] and every Spherical Harmonics work to [Green2003].&#xD;&#xA;&#xD;&#xA;Based on what you wrote, you must be familiar with reading papers. Therefore, I would suggest to read &quot;Introduction&quot; and &quot;Prior work&quot; to find references to past works in this area of computer graphics." ContentLicense="CC BY-SA 4.0" />
  <row Id="29584" PostHistoryTypeId="2" PostId="10211" RevisionGUID="8b8cb26f-c098-49ad-8f58-9f78a519145a" CreationDate="2020-09-11T18:31:50.087" UserId="48" Text="I think what you want for this is to create a descriptor table which lists your textures. The individual textures would be created and uploaded as ordinary Texture2Ds. You'd set up the root signature of your shader to bind your `Texture2D[]` in HLSL to a contiguous range of SRV descriptors from a descriptor heap. Then, when you create the SRVs for your textures, put their descriptors into the corresponding slots in the heap.&#xD;&#xA;&#xD;&#xA;For the details, you can look at the [D3D12DynamicIndexing](https://github.com/microsoft/DirectX-Graphics-Samples/tree/master/Samples/Desktop/D3D12DynamicIndexing) sample in MS's DirectX Graphics Samples repository. I know you said you don't need dynamic indexing, but the strategy here would be the same." ContentLicense="CC BY-SA 4.0" />
  <row Id="29586" PostHistoryTypeId="2" PostId="10212" RevisionGUID="6f283f11-0987-4f46-9ac4-310fae73fd9f" CreationDate="2020-09-11T19:25:12.067" UserId="48" Text="The problem statement in the linked post says that only the vertices and edges are input to the algorithm, but I don't think it's possible to do this unambiguously in 3D without additional input about the faces of the mesh. In the 2D case, since the input is specified to be a planar graph, the faces are unambiguous: any region in the plane contained within an edge loop, and empty of edges in its interior, is a face. However, in 3D, you don't know which edge loops should be faces and which shouldn't. &#xD;&#xA;&#xD;&#xA;Consider a cube, represented as just vertices and edges: you would want the &quot;usual&quot; 6 sides of the cube to be treated as faces, but you wouldn't want the algorithm to create additional faces that stretch across the diagonal of the cube, internally. But there is no way for the algorithm to know that. Moreover, the vertex/edge mesh might not even be possible to assign faces to in a sensible way; it might have non-planar faces, might be non-orientable (e.g. Möbius strip) or non-manifold.&#xD;&#xA;&#xD;&#xA;Typically in 3D applications we would have the mesh faces already defined, and we can assume it to be a manifold, orientable mesh. With the face data as input to the algorithm, such as by lists of edges or vertices in counterclockwise order around each face, then it becomes straightforward (if tedious) to figure out the half-edge relationships." ContentLicense="CC BY-SA 4.0" />
  <row Id="29594" PostHistoryTypeId="2" PostId="10214" RevisionGUID="322742c3-441f-4f08-ab16-e9c9839650ec" CreationDate="2020-09-12T08:27:28.883" UserId="10129" Text="Thank you Nathan! I was basing my Texture2DArray solution on MS's sample repo that you've sent, but after your explanation it was much easier to convert code to Texture2D[]. For anyone wondering, here's code:&#xD;&#xA;&#xD;&#xA;    void RaytracingResources::CreateDxrPipelineAssets(ID3D12Device5* device, ModelClass* model, std::vector&lt;TextureWithDesc&gt; texturesWithDesc, D3D12_SHADER_RESOURCE_VIEW_DESC indexDesc, D3D12_SHADER_RESOURCE_VIEW_DESC vertexDesc, std::vector&lt;ResourceWithSize&gt; buffersWithSize, std::vector&lt;bool&gt; isUAV)&#xD;&#xA;    {&#xD;&#xA;        // Create descriptor heaps&#xD;&#xA;        {&#xD;&#xA;            D3D12_DESCRIPTOR_HEAP_DESC desc = {};&#xD;&#xA;            // Vertex + index + TLAS = 3&#xD;&#xA;            // Buffer count = y // buffersWithSize&#xD;&#xA;            // Number of textures = x // texturesWithDesc&#xD;&#xA;            int textureCount = 0;&#xD;&#xA;            for (const auto&amp; tex : texturesWithDesc) {&#xD;&#xA;                textureCount += tex.resources.size();&#xD;&#xA;            }&#xD;&#xA;            desc.NumDescriptors = 3 + static_cast&lt;UINT&gt;(buffersWithSize.size()) + static_cast&lt;UINT&gt;(textureCount);&#xD;&#xA;            desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;            desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;    &#xD;&#xA;            // Create the descriptor heap&#xD;&#xA;            ThrowIfFailed(device-&gt;CreateDescriptorHeap(&amp;desc, IID_PPV_ARGS(&amp;m_descriptorHeap)));&#xD;&#xA;    &#xD;&#xA;            // Get the descriptor heap handle and increment size&#xD;&#xA;            D3D12_CPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap-&gt;GetCPUDescriptorHandleForHeapStart();&#xD;&#xA;            UINT handleIncrement = device-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);&#xD;&#xA;    &#xD;&#xA;            // Create the CBV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the DXR output buffer UAV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the DXR Top Level Acceleration Structure SRV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the index buffer SRV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the vertex buffer SRV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create texture buffer SRV&#xD;&#xA;            for (auto&amp; tex : texturesWithDesc)&#xD;&#xA;            {&#xD;&#xA;                for (auto&amp; singleTextureResource : tex.resources)&#xD;&#xA;                {&#xD;&#xA;                    if (tex.isSRV)&#xD;&#xA;                    {&#xD;&#xA;                        handle.ptr += handleIncrement;&#xD;&#xA;                        device-&gt;CreateShaderResourceView(singleTextureResource.Get(), &amp;tex.srvDesc, handle);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As Nathan said. Each texture is a separate descriptor in HLSL, so I'm calculating number of textures to bind, based on passed data. I am using single space (default - space0) with assumption that Texture2D[] SRVs are the last element in the texture buffer space in HLSL." ContentLicense="CC BY-SA 4.0" />
  <row Id="29595" PostHistoryTypeId="5" PostId="10214" RevisionGUID="413d63ba-ee09-4ed7-ad0a-9663be344ea0" CreationDate="2020-09-12T08:41:13.937" UserId="10129" Comment="added 116 characters in body" Text="Thank you Nathan! I was basing my Texture2DArray solution on MS's sample repo that you've sent, but after your explanation it was much easier to convert code to Texture2D[]. For anyone wondering, here's code:&#xD;&#xA;&#xD;&#xA;    void RaytracingResources::CreateDxrPipelineAssets(ID3D12Device5* device, ModelClass* model, std::vector&lt;TextureWithDesc&gt; texturesWithDesc, D3D12_SHADER_RESOURCE_VIEW_DESC indexDesc, D3D12_SHADER_RESOURCE_VIEW_DESC vertexDesc, std::vector&lt;ResourceWithSize&gt; buffersWithSize, std::vector&lt;bool&gt; isUAV)&#xD;&#xA;    {&#xD;&#xA;        // Create descriptor heaps&#xD;&#xA;        {&#xD;&#xA;            D3D12_DESCRIPTOR_HEAP_DESC desc = {};&#xD;&#xA;            // Vertex + index + TLAS = 3&#xD;&#xA;            // Buffer count = y // buffersWithSize&#xD;&#xA;            // Number of textures = x // texturesWithDesc&#xD;&#xA;            int textureCount = 0;&#xD;&#xA;            for (const auto&amp; tex : texturesWithDesc) {&#xD;&#xA;                textureCount += tex.resources.size();&#xD;&#xA;            }&#xD;&#xA;            desc.NumDescriptors = 3 + static_cast&lt;UINT&gt;(buffersWithSize.size()) + static_cast&lt;UINT&gt;(textureCount);&#xD;&#xA;            desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;            desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;    &#xD;&#xA;            // Create the descriptor heap&#xD;&#xA;            ThrowIfFailed(device-&gt;CreateDescriptorHeap(&amp;desc, IID_PPV_ARGS(&amp;m_descriptorHeap)));&#xD;&#xA;    &#xD;&#xA;            // Get the descriptor heap handle and increment size&#xD;&#xA;            D3D12_CPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap-&gt;GetCPUDescriptorHandleForHeapStart();&#xD;&#xA;            UINT handleIncrement = device-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);&#xD;&#xA;    &#xD;&#xA;            // Create the CBV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the DXR output buffer UAV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the DXR Top Level Acceleration Structure SRV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the index buffer SRV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create the vertex buffer SRV&#xD;&#xA;            // ...&#xD;&#xA;    &#xD;&#xA;            // Create texture buffer SRV&#xD;&#xA;            for (auto&amp; tex : texturesWithDesc)&#xD;&#xA;            {&#xD;&#xA;                for (auto&amp; singleTextureResource : tex.resources)&#xD;&#xA;                {&#xD;&#xA;                    if (tex.isSRV)&#xD;&#xA;                    {&#xD;&#xA;                        handle.ptr += handleIncrement;&#xD;&#xA;                        device-&gt;CreateShaderResourceView(singleTextureResource.Get(), &amp;tex.srvDesc, handle);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As Nathan said. Each texture is a separate descriptor in HLSL, so I'm calculating number of textures to bind, based on passed data. I am using single space with assumption that Texture2D[] SRVs are the last element in the texture buffer space in HLSL. For now it works only for single texture array, so I'll need to add more spaces to make it possible to use multiple array of textures." ContentLicense="CC BY-SA 4.0" />
  <row Id="29596" PostHistoryTypeId="2" PostId="10215" RevisionGUID="721ef1cd-51bd-4c89-95d4-aaf4f50ec452" CreationDate="2020-09-12T22:31:38.747" UserId="7462" Text="I have been trying to understand a [paper in CG][1] for a while, called the Heat Method by Ken&#xD;&#xA;&#xD;&#xA;Many things have clicked but I don't fully understand it yet. In particular.&#xD;&#xA;&#xD;&#xA;In the following $u$ is a vector with dimensions equal to the number of vertices in a mesh.&#xD;&#xA;&#xD;&#xA;The paper states that solving $(id – t∆)u_t = u0$ is a time discretized approximation of the heat flow on a surface. Rewriting gives: $ut = u_0 + t\Delta u_t $ or in English, the heat flow at time $t$ is equal to the heat flow at time 0 plus the gradient of $u$ at time $t$. Which is just a backwards Euler method pretty straightforward.&#xD;&#xA;&#xD;&#xA;Then we get that: $(M –tL_C)u = δγ,$ which, to summarize, is the same as above except we have discretized the medium as a triangular mesh.&#xD;&#xA;&#xD;&#xA;$M$ is a square diagonal matrix where the entry $m_{i,i}$ is 2 times one third of the sum of the areas of the triangles that contain vertex $i$. In math $m_{i,i} = 2\sum A_j / 3$ where $A_j$ are the areas of the triangles containing vertex $i$. And $L_C$ is also a square diagonal matrix where $({l_c})_{i,i} = \sum (\cot \alpha_{ij} + \cot \beta_{ij})(u_j-u_i)$ which in short, is an approximation of the laplace operator at vertex $i$.&#xD;&#xA;&#xD;&#xA;Thus manipulating the formula: $(id –tM^{-1}L_C)u = M^{-1}δγ,$ Which is the spatially discretized form of: $(id – t∆)u_t = u0$.&#xD;&#xA;&#xD;&#xA;So, this makes sense algebraically, but now comes the part I don;t understand.&#xD;&#xA;&#xD;&#xA;Why does this work? Why would solving that equation give the correct heat diffusion? Let me explain what I mean. In my head, a geodesic distance (or heat flow, which for the purposes of this method are the same thing) is highly dependent on the shape of a mesh. So in order to know the geodesic distance at vertex $i$ I must first know the geodesic distance at the vertices that come before it relative to the source.&#xD;&#xA;&#xD;&#xA;This mehtod however seems to imply that, given an arbitrary mesh and an arbitrary point $p_0$ on that mesh. I can grab any arbitrary point $p_1$ on the mesh and tell you what the geodesic distance from $p_1$ to $p_2$ is without having to look at the full connectivity of the mesh to determine a connectivity graph.&#xD;&#xA;&#xD;&#xA;I am not entirely sure if what i am asking is clear. I understand the algebra of the problem, but I cannot link how solving this equation gives you the correct heat flow everywhere on a mesh. Why can you do it in parallel without any regards for the specific connectivity information?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29597" PostHistoryTypeId="1" PostId="10215" RevisionGUID="721ef1cd-51bd-4c89-95d4-aaf4f50ec452" CreationDate="2020-09-12T22:31:38.747" UserId="7462" Text="Mis understanding of the Heat Method" ContentLicense="CC BY-SA 4.0" />
  <row Id="29598" PostHistoryTypeId="3" PostId="10215" RevisionGUID="721ef1cd-51bd-4c89-95d4-aaf4f50ec452" CreationDate="2020-09-12T22:31:38.747" UserId="7462" Text="|mathematics|computational-geometry|mesh|geometry|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29599" PostHistoryTypeId="2" PostId="10216" RevisionGUID="497625ce-2c94-42a4-8036-ade55be3ede6" CreationDate="2020-09-13T09:07:07.793" UserId="10129" Text="I am using RT shader (DXR) to generate g-buffers with code below. There was no problems with smaller scene (pink room from cwyman tutorial - http://cwyman.org/code/dxrTutors/tutors/Tutor5/tutorial05.md.html ). However, when I moved to bigger scene (Sun Temple by Epic Games - https://developer.nvidia.com/ue4-sun-temple ), I've started noticing problems with texture sampling. Please compare textures at the end of this post. The greater the distance to world origin (0, 0, 0), the more jaggy artifacts appear and quality becomes worse.&#xD;&#xA;&#xD;&#xA;At the beginning, I was suspecting acceleration structures. But skybox quality is becoming worse, so it's probably unrelated to AS.&#xD;&#xA;&#xD;&#xA;    inline void GenerateCameraRay(uint2 index, uint2 dimensions, float4x4 projectionToWorld, inout  float3 origin, out float3 direction)&#xD;&#xA;    {&#xD;&#xA;    	float2 xy = index + float2(0.5f, 0.5f); // center in the middle of the pixel.&#xD;&#xA;    	float2 screenPos = (xy / (float2) dimensions) * 2.0 - 1.0;&#xD;&#xA;    &#xD;&#xA;        // Invert Y for DirectX-style coordinates.&#xD;&#xA;    	screenPos.y = -screenPos.y;&#xD;&#xA;    &#xD;&#xA;        // Unproject the pixel coordinate into a ray.&#xD;&#xA;    	float4 world = mul(float4(screenPos, 0, 1), projectionToWorld);&#xD;&#xA;    &#xD;&#xA;    	world.xyz /= world.w;&#xD;&#xA;    	direction = normalize(world.xyz - origin);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGen()&#xD;&#xA;    {&#xD;&#xA;    	float3 rayDir;&#xD;&#xA;    	float3 origin = g_sceneCB.cameraPosition.xyz;&#xD;&#xA;        &#xD;&#xA;        // Generate a ray for a camera pixel corresponding to an index from the dispatched 2D grid.&#xD;&#xA;    	GenerateCameraRay(DispatchRaysIndex().xy, DispatchRaysDimensions().xy, g_sceneCB.projectionToWorld, origin, rayDir);&#xD;&#xA;    &#xD;&#xA;    	RayDesc ray = { origin, 1e-4f, rayDir, 1e+38f };&#xD;&#xA;    	RayPayload payload = { 0 };&#xD;&#xA;    	TraceRay(SceneBVH, RAY_FLAG_NONE, 0xFF, 0, 1, 0, ray, payload);&#xD;&#xA;    }&#xD;&#xA;        &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void Miss(inout RayPayload payload)&#xD;&#xA;    {&#xD;&#xA;    	float3 rayDir = WorldRayDirection();&#xD;&#xA;    	rayDir.z = -rayDir.z;&#xD;&#xA;    &#xD;&#xA;    	RTOutputAlbedo[DispatchRaysIndex().xy] = float4(skyboxTexture.SampleLevel(g_sampler, rayDir, 0).rgb, 0);&#xD;&#xA;    	RTOutputNormal[DispatchRaysIndex().xy] = float4(0, 0, 0, 0);&#xD;&#xA;    	RTOutputSpecRoughness[DispatchRaysIndex().xy] = float4(0, 0, 0, 0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fIwbx.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7l9wO.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29600" PostHistoryTypeId="1" PostId="10216" RevisionGUID="497625ce-2c94-42a4-8036-ade55be3ede6" CreationDate="2020-09-13T09:07:07.793" UserId="10129" Text="Worsening sampling quality of raytracing with increasing distance from world origin" ContentLicense="CC BY-SA 4.0" />
  <row Id="29601" PostHistoryTypeId="3" PostId="10216" RevisionGUID="497625ce-2c94-42a4-8036-ade55be3ede6" CreationDate="2020-09-13T09:07:07.793" UserId="10129" Text="|raytracing|texture|hlsl|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29602" PostHistoryTypeId="50" PostId="9426" RevisionGUID="743d734c-29b5-47b1-b1c8-4fb60838765f" CreationDate="2020-09-13T11:00:25.123" UserId="-1" />
  <row Id="29603" PostHistoryTypeId="2" PostId="10217" RevisionGUID="86f8e46c-46ef-44db-bb7f-5939967d26aa" CreationDate="2020-09-13T11:42:06.830" UserId="13959" Text="If I have 360 images of an interior room from all different angles, would it be possible with current 3D software technology to create a **real** 3D representation of that room, where the camera could freely navigate to any part of it?&#xD;&#xA;&#xD;&#xA;So similar to Photoshop’s stitch, where you stitch a bunch of photos to create a single 360 photo, would you be able to stitch a bunch of 360 photos to create a 3D environment?&#xD;&#xA;&#xD;&#xA;I’m not looking to create graphics or photorealism out of the room, but rather the actual real room. Most of my research points either to one of the above or VR videos, which have limitations on camera direction.&#xD;&#xA;&#xD;&#xA;If it is possible, could you please point me to the right direction/software and/or examples of work that have achieved this?&#xD;&#xA;&#xD;&#xA;If it’s not possible, I would be very interested in knowing what the limitations are.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="29604" PostHistoryTypeId="1" PostId="10217" RevisionGUID="86f8e46c-46ef-44db-bb7f-5939967d26aa" CreationDate="2020-09-13T11:42:06.830" UserId="13959" Text="Real 3D interior room from 360 images" ContentLicense="CC BY-SA 4.0" />
  <row Id="29605" PostHistoryTypeId="3" PostId="10217" RevisionGUID="86f8e46c-46ef-44db-bb7f-5939967d26aa" CreationDate="2020-09-13T11:42:06.830" UserId="13959" Text="|3d|virtual-reality|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29606" PostHistoryTypeId="5" PostId="10215" RevisionGUID="0f1e5f36-fcd0-441b-8ba5-fce13398f97b" CreationDate="2020-09-13T16:07:26.410" UserId="48" Comment="formula cleanups" Text="I have been trying to understand a [paper in CG][1] for a while, called the Heat Method by Ken&#xD;&#xA;&#xD;&#xA;Many things have clicked but I don't fully understand it yet. In particular.&#xD;&#xA;&#xD;&#xA;In the following $u$ is a vector with dimensions equal to the number of vertices in a mesh.&#xD;&#xA;&#xD;&#xA;The paper states that solving $(id - t\Delta)u_t = u_0$ is a time discretized approximation of the heat flow on a surface. Rewriting gives: $u_t = u_0 + t\Delta u_t $ or in English, the heat flow at time $t$ is equal to the heat flow at time 0 plus the laplacian of $u$ at time $t$. Which is just a backwards Euler method pretty straightforward.&#xD;&#xA;&#xD;&#xA;Then we get that: $(M - tL_C)u = δγ,$ which, to summarize, is the same as above except we have discretized the medium as a triangular mesh.&#xD;&#xA;&#xD;&#xA;$M$ is a square diagonal matrix where the entry $m_{i,i}$ is 2 times one third of the sum of the areas of the triangles that contain vertex $i$. In math $m_{i,i} = 2\sum A_j / 3$ where $A_j$ are the areas of the triangles containing vertex $i$. And $L_C$ is also a square diagonal matrix where $({l_c})_{i,i} = \sum (\cot \alpha_{ij} + \cot \beta_{ij})(u_j-u_i)$ which in short, is an approximation of the laplace operator at vertex $i$.&#xD;&#xA;&#xD;&#xA;Thus manipulating the formula: $(id - tM^{-1}L_C)u = M^{-1}δγ,$ Which is the spatially discretized form of: $(id - t\Delta)u_t = u_0$.&#xD;&#xA;&#xD;&#xA;So, this makes sense algebraically, but now comes the part I don;t understand.&#xD;&#xA;&#xD;&#xA;Why does this work? Why would solving that equation give the correct heat diffusion? Let me explain what I mean. In my head, a geodesic distance (or heat flow, which for the purposes of this method are the same thing) is highly dependent on the shape of a mesh. So in order to know the geodesic distance at vertex $i$ I must first know the geodesic distance at the vertices that come before it relative to the source.&#xD;&#xA;&#xD;&#xA;This mehtod however seems to imply that, given an arbitrary mesh and an arbitrary point $p_0$ on that mesh. I can grab any arbitrary point $p_1$ on the mesh and tell you what the geodesic distance from $p_1$ to $p_2$ is without having to look at the full connectivity of the mesh to determine a connectivity graph.&#xD;&#xA;&#xD;&#xA;I am not entirely sure if what i am asking is clear. I understand the algebra of the problem, but I cannot link how solving this equation gives you the correct heat flow everywhere on a mesh. Why can you do it in parallel without any regards for the specific connectivity information?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29607" PostHistoryTypeId="5" PostId="10215" RevisionGUID="9c2677e9-3614-4d20-b3e9-1b8c440d7696" CreationDate="2020-09-13T16:25:38.170" UserId="48" Comment="formula correction to match the paper; deleted 9 characters in body" Text="I have been trying to understand a [paper in CG][1] for a while, called the Heat Method by Ken&#xD;&#xA;&#xD;&#xA;Many things have clicked but I don't fully understand it yet. In particular.&#xD;&#xA;&#xD;&#xA;In the following $u$ is a vector with dimensions equal to the number of vertices in a mesh.&#xD;&#xA;&#xD;&#xA;The paper states that solving $(id - t\Delta)u_t = u_0$ is a time discretized approximation of the heat flow on a surface. Rewriting gives: $u_t = u_0 + t\Delta u_t $ or in English, the heat flow at time $t$ is equal to the heat flow at time 0 plus the laplacian of $u$ at time $t$. Which is just a backwards Euler method pretty straightforward.&#xD;&#xA;&#xD;&#xA;Then we get that: $(M - tL_C)u = δγ,$ which, to summarize, is the same as above except we have discretized the medium as a triangular mesh.&#xD;&#xA;&#xD;&#xA;$M$ is a square diagonal matrix where the entry $m_{i,i}$ is 2 times one third of the sum of the areas of the triangles that contain vertex $i$. In math $m_{i,i} = 2\sum_j A_j / 3$ where $A_j$ are the areas of the triangles containing vertex $i$. And $L_C$ is also a square diagonal matrix where $(L_C u)_i = \sum_j (\cot \alpha_{ij} + \cot \beta_{ij})(u_j-u_i)$ which in short, is an approximation of the laplace operator at vertex $i$.&#xD;&#xA;&#xD;&#xA;Thus manipulating the formula: $(id - tM^{-1}L_C)u = M^{-1}δγ,$ Which is the spatially discretized form of: $(id - t\Delta)u_t = u_0$.&#xD;&#xA;&#xD;&#xA;So, this makes sense algebraically, but now comes the part I don;t understand.&#xD;&#xA;&#xD;&#xA;Why does this work? Why would solving that equation give the correct heat diffusion? Let me explain what I mean. In my head, a geodesic distance (or heat flow, which for the purposes of this method are the same thing) is highly dependent on the shape of a mesh. So in order to know the geodesic distance at vertex $i$ I must first know the geodesic distance at the vertices that come before it relative to the source.&#xD;&#xA;&#xD;&#xA;This mehtod however seems to imply that, given an arbitrary mesh and an arbitrary point $p_0$ on that mesh. I can grab any arbitrary point $p_1$ on the mesh and tell you what the geodesic distance from $p_1$ to $p_2$ is without having to look at the full connectivity of the mesh to determine a connectivity graph.&#xD;&#xA;&#xD;&#xA;I am not entirely sure if what i am asking is clear. I understand the algebra of the problem, but I cannot link how solving this equation gives you the correct heat flow everywhere on a mesh. Why can you do it in parallel without any regards for the specific connectivity information?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29608" PostHistoryTypeId="2" PostId="10218" RevisionGUID="ca9ebacf-e86e-4e3a-8af0-c935b37c3c0b" CreationDate="2020-09-13T20:11:37.520" UserId="7952" Text="A website devoted to prescanned photogrammetry is :[Quixel.com][1] They did (at least some of) the assets for the version 5 unreal engine [demo][2].&#xD;&#xA;&#xD;&#xA;I have gotten excellent results with software from [Agisoft][3] but it costs real money. &#xD;&#xA;For good free software try [3DF Zephyr][4]&#xD;&#xA;&#xD;&#xA;This software will just generate the mesh, they will provide only minimal navigation of the result which is outside the scope of generation.&#xD;&#xA;&#xD;&#xA;To navigate the mesh you can use something like windows 3D viewer.&#xD;&#xA;&#xD;&#xA;Or better yet, and way more fun, write your own!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://quixel.com&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=qC5KtatMcUw&#xD;&#xA;  [3]: https://www.agisoft.com&#xD;&#xA;  [4]: https://www.3dflow.net" ContentLicense="CC BY-SA 4.0" />
  <row Id="29609" PostHistoryTypeId="2" PostId="10219" RevisionGUID="addf99c1-294c-429f-a62f-5dce3ce72182" CreationDate="2020-09-13T21:28:14.253" UserId="13961" Text="I need the simplest route to programatically, via command line, through python or node, to create something like this using basic input of distance and 90 degree turn etc: https://i.stack.imgur.com/Ema7I.png&#xD;&#xA;&#xD;&#xA;I normally use blender for such graphics, but manually. I have bee told its over kill to use for my basic need via python, not sure where to start.&#xD;&#xA;&#xD;&#xA;I have been told three.js is the wrong choice to try and do something like that as its for browser use mainly and I just want to create rendered images to disk, from input, on the command line.&#xD;&#xA;&#xD;&#xA;any advice would be appreciated. I am building a fencing quote system and would like to have basic graphics accompany it. I feel like autocad/freecad would be perfect if it had such options.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29610" PostHistoryTypeId="1" PostId="10219" RevisionGUID="addf99c1-294c-429f-a62f-5dce3ce72182" CreationDate="2020-09-13T21:28:14.253" UserId="13961" Text="What is the simplest way to create basic 3d/isometric style images programatically like autocad/blender" ContentLicense="CC BY-SA 4.0" />
  <row Id="29611" PostHistoryTypeId="3" PostId="10219" RevisionGUID="addf99c1-294c-429f-a62f-5dce3ce72182" CreationDate="2020-09-13T21:28:14.253" UserId="13961" Text="|opengl|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29612" PostHistoryTypeId="2" PostId="10220" RevisionGUID="222b24a1-34ff-4efa-868f-e8dfd7b32b9a" CreationDate="2020-09-13T22:38:16.920" UserId="13896" Text="The description is going to be long and detailed, thanks in advance for your patience!&#xD;&#xA;&#xD;&#xA;I am learning the path integral form of light transport equation(LTE) to be able to follow recent rendering papers. The materials I am using are PBRT(chapter 14.4-14.5: [link](http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/The_Light_Transport_Equation.html)) and SIGGRAPH 2013 course: [link](https://cgg.mff.cuni.cz/~jaroslav/papers/2013-ltscourse/02%20-%20ltscourse%20-%20path%20integral%20-%20krivanek%20-%20notes.pdf).&#xD;&#xA;&#xD;&#xA;The path integral form of LTE is:&#xD;&#xA;&#xD;&#xA;$$ I(x) = \int_{\Omega}f(\overline{x})d\mu(\overline{x})$$&#xD;&#xA;&#xD;&#xA;From the SIGGRAPH course's slide, we know that we can estimate $I$ by randomly sampling a path, computing its contribution $f$, and dividing by its probability $p$:&#xD;&#xA;&#xD;&#xA;$$ \overline{I}(x) = \frac{f(\overline{x})}{p(\overline{x})} $$&#xD;&#xA;&#xD;&#xA;From the PBRT's notes and its implementation, it expands the path integral into an infinite sum of integrals on specific lengths of paths. This notation is well shown in the path tracing implementation since the i-th bounce computes the i-th integral and simply summing them up will the final estimate of $I$.&#xD;&#xA;&#xD;&#xA;$$ \overline{I}(x) = \sum_{i=0}^{\infty}\overline{I_{i}}(x) $$&#xD;&#xA;&#xD;&#xA;With these two notations based on the path form integral of LTE, my question is how to represent path tracing as the first one(the SIGGRAPH course notation) since most PT implementations I've seen so far is based either on the PBRT's notation(the sum notation) or other notations of LTE. &#xD;&#xA;&#xD;&#xA;I have one possible idea that is to follow the formula by generating a path and computing its pdf, but I am not sure about its practical implementation. Should I generate paths for different lengths and do this procedure over and over(since this looks more like the PBRT's notation), or a single path with the correct pdf will suffice?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29613" PostHistoryTypeId="1" PostId="10220" RevisionGUID="222b24a1-34ff-4efa-868f-e8dfd7b32b9a" CreationDate="2020-09-13T22:38:16.920" UserId="13896" Text="Path Integral Form with Path Tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="29614" PostHistoryTypeId="3" PostId="10220" RevisionGUID="222b24a1-34ff-4efa-868f-e8dfd7b32b9a" CreationDate="2020-09-13T22:38:16.920" UserId="13896" Text="|pathtracing|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29615" PostHistoryTypeId="5" PostId="10220" RevisionGUID="9e9ee8c1-84ea-4b43-b57e-b9797ed4ff46" CreationDate="2020-09-13T23:37:57.977" UserId="13896" Comment="added 266 characters in body" Text="The description is going to be long and detailed, thanks in advance for your patience!&#xD;&#xA;&#xD;&#xA;I am learning the path integral form of light transport equation(LTE) to be able to follow recent rendering papers. The materials I am using are PBRT(chapter 14.4-14.5: [link](http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/The_Light_Transport_Equation.html)) and SIGGRAPH 2013 course: [link](https://cgg.mff.cuni.cz/~jaroslav/papers/2013-ltscourse/02%20-%20ltscourse%20-%20path%20integral%20-%20krivanek%20-%20notes.pdf).&#xD;&#xA;&#xD;&#xA;The path integral form of LTE is:&#xD;&#xA;&#xD;&#xA;$$ I(x) = \int_{\Omega}f(\overline{x})d\mu(\overline{x})$$&#xD;&#xA;&#xD;&#xA;From the SIGGRAPH course's slide, we know that we can estimate $I$ by randomly sampling a path, computing its contribution $f$, and dividing by its probability $p$:&#xD;&#xA;&#xD;&#xA;$$ \overline{I}(x) = \frac{f(\overline{x})}{p(\overline{x})} $$&#xD;&#xA;&#xD;&#xA;From the PBRT's notes and its implementation, it expands the path integral into an infinite sum of integrals on specific lengths of paths. This notation is well shown in the path tracing implementation since the i-th bounce computes the i-th integral and simply summing them up will the final estimate of $I$.&#xD;&#xA;&#xD;&#xA;$$ \overline{I}(x) = \sum_{i=0}^{\infty}\overline{I_{i}}(x) $$&#xD;&#xA;&#xD;&#xA;With these two notations based on the path form integral of LTE, my question is how to represent path tracing as the first one(the SIGGRAPH course notation) since most PT implementations I've seen so far is based either on the PBRT's notation(the sum notation) or other notations of LTE. &#xD;&#xA;&#xD;&#xA;I have one possible idea that is to follow the formula by generating a path and computing its pdf, but I am not sure about its practical implementation. Should I generate paths for different lengths and do this procedure over and over(since this looks more like the PBRT's notation), or a single path with the correct pdf will suffice?&#xD;&#xA;&#xD;&#xA;Or, from another perspective, I think that to apply the SIGGRAPH course's notation in practice, one has to randomly generate paths with different lengths and sum their estimate up since each length corresponds to one term in the expanded notation. Is this correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29616" PostHistoryTypeId="2" PostId="10221" RevisionGUID="7ae8503d-a415-472b-828c-2814fd2a6b52" CreationDate="2020-09-14T00:51:31.607" UserId="48" Text="When solving the equation $(M - tL_C)u = \delta_\gamma$, you effectively have to invert the operator:&#xD;&#xA;$$&#xD;&#xA;u = (M - tL_C)^{-1} \delta_\gamma&#xD;&#xA;$$&#xD;&#xA;Note that while the individual operators $M$ and $L_C$ are only local, containing information about the individual vertices and edges of the mesh, the inverse operator is decidedly not local. Inversion is a global operation that incorporates information across the whole matrix being inverted, which means information across the whole mesh. (Note that $M$ has a trivial inverse since it's diagonal, but $L_C$ definitely doesn't.)&#xD;&#xA;&#xD;&#xA;In practice, you might not literally compute the inverse matrix but rather use Gaussian elimination or some such to solve the $u$ for a given $\delta_\gamma$. In that case, it's the solving process that integrates information across the whole mesh. Effectively $L_C$ is encoding a bunch of constraints between neighboring vertices, and the solver has to satisfy all the constraints across the whole mesh at once.&#xD;&#xA;&#xD;&#xA;(Note that it's not a trivially parallelizable job. There are methods for using parallelism to accelerate solving large linear systems, but they're going to be multi-pass methods that transfer information up and down between different &quot;scales&quot; of the problem. Think like parallel prefix scan, or FFT—that sort of thing.)&#xD;&#xA;&#xD;&#xA;BTW, another perspective on this equation is that it is solving for the fixed point of $u$ in&#xD;&#xA;$$&#xD;&#xA;u = M^{-1}(\delta_\gamma + tL_Cu)&#xD;&#xA;$$&#xD;&#xA;This is yet another way of algebraically rewriting that same equation. In this form it looks a lot like the rendering equation $L = L_e + \int L \, f_{\text{brdf}}$! It has a similar structure, where $\delta_\gamma$ is like the emitted radiance and $L_C$ is like the scattering at surfaces. Just as in the rendering equation, you're looking for a global equilibrium solution. (And if rendering was discretized, we could similarly solve it by turning the scattering operator into a matrix and throwing the whole thing into a linear solver.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29617" PostHistoryTypeId="2" PostId="10222" RevisionGUID="bbe99d2e-31dd-4eff-a274-c4ffb8f4f807" CreationDate="2020-09-14T01:13:04.747" UserId="13838" Text="**Q1**: how to represent path tracing as the first one...&#xD;&#xA;&#xD;&#xA;Your materials have brought enough information, the first formula, quoted from your material, presents as&#xD;&#xA;&#xD;&#xA;&gt; The path integral formulation of light transport formalizes the idea&#xD;&#xA;&gt; by writing the camera response as an integral over all light transport&#xD;&#xA;&gt; paths of all lengths in the scene, which given path encompasses &#xD;&#xA;&gt; 1. the “amount” of light emitted along the path, &#xD;&#xA;&gt; 2. the light carrying capacity of the path, and &#xD;&#xA;&gt; 3. the sensitivity of the sensor to light brought along the path.&#xD;&#xA;&#xD;&#xA;Can't interpret the formula better&#xD;&#xA;&#xD;&#xA;**Q2**: Should I generate paths for different lengths and do this procedure over and over...&#xD;&#xA;&#xD;&#xA;**Q3**: ...randomly generate paths with different lengths and sum their estimate up since each length...&#xD;&#xA;&#xD;&#xA;Quoted from your material, &#xD;&#xA;&#xD;&#xA;&gt; The Monte Carlo integration procedure consists in generating a&#xD;&#xA;&gt; ‘sample’, that is, a random x-value from the integration domain, ...&#xD;&#xA;&#xD;&#xA;I can't say the second one is a formula, it is just the Monte Carlo estimator of the path integral formulation of light transport or it is just a method for programming the formulation; or course you could have other methods.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29618" PostHistoryTypeId="2" PostId="10223" RevisionGUID="c6ea7a49-fdf7-4b57-b8ea-8b8f301f6a77" CreationDate="2020-09-14T03:47:23.673" UserId="13963" Text="I am trying to recreate positions in Viewspace from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I dont know what I am doing wrong, been trying many things, getting out of ideas. &#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong? I want to do the lighting in viewspace, that is what I am trying.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;/*  From prev shader stage */&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;/* Out */&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;&#xD;&#xA;/* In */&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return diffuseCos ;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= depth / near; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="29619" PostHistoryTypeId="1" PostId="10223" RevisionGUID="c6ea7a49-fdf7-4b57-b8ea-8b8f301f6a77" CreationDate="2020-09-14T03:47:23.673" UserId="13963" Text="OpenGL - Recreate position in viewspace from depth values" ContentLicense="CC BY-SA 4.0" />
  <row Id="29620" PostHistoryTypeId="3" PostId="10223" RevisionGUID="c6ea7a49-fdf7-4b57-b8ea-8b8f301f6a77" CreationDate="2020-09-14T03:47:23.673" UserId="13963" Text="|opengl|shader|glsl|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29621" PostHistoryTypeId="5" PostId="10223" RevisionGUID="1860cae6-a8cc-4691-9136-a0ca61c69a73" CreationDate="2020-09-14T03:58:58.857" UserId="13963" Comment="added 1 character in body" Text="I am trying to recreate positions in Viewspace from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I dont know what I am doing wrong, been trying many things, getting out of ideas. &#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong? I want to do the lighting in viewspace, that is what I am trying.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;/*  From prev shader stage */&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;/* Out */&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;&#xD;&#xA;/* In */&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return diffuseCos ;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / near; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="29622" PostHistoryTypeId="5" PostId="10223" RevisionGUID="07d1a27a-21e4-45cb-be11-8154971051f1" CreationDate="2020-09-14T04:27:05.263" UserId="13963" Comment="added 5 characters in body" Text="I am trying to recreate positions in Viewspace from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I dont know what I am doing wrong, been trying many things, getting out of ideas. &#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong? I want to do the lighting in viewspace, that is what I am trying.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;/*  From prev shader stage */&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;/* Out */&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;&#xD;&#xA;/* In */&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / near; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="29623" PostHistoryTypeId="2" PostId="10224" RevisionGUID="372b5e07-4ca0-4dff-a72b-1859997f063e" CreationDate="2020-09-14T05:08:06.293" UserId="13964" Text="i have the algorithm wu line antialising&#xD;&#xA;&#xD;&#xA;but i canot understand very well all of the lines of code.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    public static void drawLine(Graphics g, double x0, double y0, double x1, double y1, int value) {&#xD;&#xA;     &#xD;&#xA;            boolean steep = abs(y1 - y0) &gt; abs(x1 - x0);&#xD;&#xA;            if (steep)&#xD;&#xA;                drawLine(g, y0, x0, y1, x1, value);&#xD;&#xA;     &#xD;&#xA;            if (x0 &gt; x1)&#xD;&#xA;                drawLine(g, x1, y1, x0, y0, value);&#xD;&#xA;     &#xD;&#xA;            double dx = x1 - x0;&#xD;&#xA;            double dy = y1 - y0;&#xD;&#xA;            double gradient = dy / dx;&#xD;&#xA;     &#xD;&#xA;            // handle first endpoint&#xD;&#xA;            double xend = round(x0);&#xD;&#xA;            double yend = y0 + gradient * (xend - x0);&#xD;&#xA;            double xgap = rfpart(x0 + 0.5);&#xD;&#xA;            double xpxl1 = xend; // this will be used in the main loop&#xD;&#xA;            double ypxl1 = ipart(yend);&#xD;&#xA;     &#xD;&#xA;            if (steep) {&#xD;&#xA;                plot(g, ypxl1, xpxl1, rfpart(yend) * xgap);&#xD;&#xA;                plot(g, ypxl1 + 1, xpxl1, fpart(yend) * xgap);&#xD;&#xA;            } else {&#xD;&#xA;                plot(g, xpxl1, ypxl1, rfpart(yend) * xgap);&#xD;&#xA;                plot(g, xpxl1, ypxl1 + 1, fpart(yend) * xgap);&#xD;&#xA;            }&#xD;&#xA;     &#xD;&#xA;            // first y-intersection for the main loop&#xD;&#xA;            double intery = yend + gradient;&#xD;&#xA;     &#xD;&#xA;            // handle second endpoint&#xD;&#xA;            xend = round(x1);&#xD;&#xA;            yend = y1 + gradient * (xend - x1);&#xD;&#xA;            xgap = fpart(x1 + 0.5);&#xD;&#xA;            double xpxl2 = xend; // this will be used in the main loop&#xD;&#xA;            double ypxl2 = ipart(yend);&#xD;&#xA;     &#xD;&#xA;            if (steep) {&#xD;&#xA;                plot(g, ypxl2, xpxl2, rfpart(yend) * xgap);&#xD;&#xA;                plot(g, ypxl2 + 1, xpxl2, fpart(yend) * xgap);&#xD;&#xA;            } else {&#xD;&#xA;                plot(g, xpxl2, ypxl2, rfpart(yend) * xgap);&#xD;&#xA;                plot(g, xpxl2, ypxl2 + 1, fpart(yend) * xgap);&#xD;&#xA;            }&#xD;&#xA;     &#xD;&#xA;            // main loop &#xD;&#xA;            for (double x = xpxl1 + 1; x &lt;= xpxl2 - 1; x++) {&#xD;&#xA;                if (steep) {&#xD;&#xA;                    plot(g, ipart(intery), x, rfpart(intery));&#xD;&#xA;                    plot(g, ipart(intery) + 1, x, fpart(intery));&#xD;&#xA;                } else {&#xD;&#xA;                    plot(g, x, ipart(intery), rfpart(intery));&#xD;&#xA;                    plot(g, x, ipart(intery) + 1, fpart(intery));&#xD;&#xA;                }&#xD;&#xA;                intery = intery + gradient;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;i know this information:&#xD;&#xA;&#xD;&#xA;The intensity of the pixel above the line must be proportional to (1-a), and the intensity of the pixel below the line must be proportional to (1-b). I.E. the closer the line is to a pixel, the brighter it is.&#xD;&#xA;&#xD;&#xA;why is necesary the following:&#xD;&#xA;// handle first endpoint ?&#xD;&#xA;// handle second endpoint ?&#xD;&#xA; // main loop ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29624" PostHistoryTypeId="1" PostId="10224" RevisionGUID="372b5e07-4ca0-4dff-a72b-1859997f063e" CreationDate="2020-09-14T05:08:06.293" UserId="13964" Text="How can i understand the algorithm wu line?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29625" PostHistoryTypeId="3" PostId="10224" RevisionGUID="372b5e07-4ca0-4dff-a72b-1859997f063e" CreationDate="2020-09-14T05:08:06.293" UserId="13964" Text="|antialiasing|line-drawing|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29626" PostHistoryTypeId="5" PostId="10224" RevisionGUID="984dd278-5820-4291-bc7f-56f65ae591e9" CreationDate="2020-09-14T07:15:50.813" UserId="13095" Comment="Correct some gramma/spelling, apply c++ code highlighting and add itemization" Text="I have Wu's line algorithm but I don't understand all the lines of code very well.&#xD;&#xA;&#xD;&#xA;~~~cpp&#xD;&#xA;public static void drawLine(Graphics g, double x0, double y0, double x1, double y1, int value) {&#xD;&#xA;     &#xD;&#xA;        boolean steep = abs(y1 - y0) &gt; abs(x1 - x0);&#xD;&#xA;        if (steep)&#xD;&#xA;            drawLine(g, y0, x0, y1, x1, value);&#xD;&#xA;     &#xD;&#xA;        if (x0 &gt; x1)&#xD;&#xA;            drawLine(g, x1, y1, x0, y0, value);&#xD;&#xA;     &#xD;&#xA;        double dx = x1 - x0;&#xD;&#xA;        double dy = y1 - y0;&#xD;&#xA;        double gradient = dy / dx;&#xD;&#xA;     &#xD;&#xA;        // handle first endpoint&#xD;&#xA;        double xend = round(x0);&#xD;&#xA;        double yend = y0 + gradient * (xend - x0);&#xD;&#xA;        double xgap = rfpart(x0 + 0.5);&#xD;&#xA;        double xpxl1 = xend; // this will be used in the main loop&#xD;&#xA;        double ypxl1 = ipart(yend);&#xD;&#xA;     &#xD;&#xA;        if (steep) {&#xD;&#xA;            plot(g, ypxl1, xpxl1, rfpart(yend) * xgap);&#xD;&#xA;            plot(g, ypxl1 + 1, xpxl1, fpart(yend) * xgap);&#xD;&#xA;        } else {&#xD;&#xA;            plot(g, xpxl1, ypxl1, rfpart(yend) * xgap);&#xD;&#xA;            plot(g, xpxl1, ypxl1 + 1, fpart(yend) * xgap);&#xD;&#xA;        }&#xD;&#xA;     &#xD;&#xA;        // first y-intersection for the main loop&#xD;&#xA;        double intery = yend + gradient;&#xD;&#xA;     &#xD;&#xA;        // handle second endpoint&#xD;&#xA;        xend = round(x1);&#xD;&#xA;        yend = y1 + gradient * (xend - x1);&#xD;&#xA;        xgap = fpart(x1 + 0.5);&#xD;&#xA;        double xpxl2 = xend; // this will be used in the main loop&#xD;&#xA;        double ypxl2 = ipart(yend);&#xD;&#xA;     &#xD;&#xA;        if (steep) {&#xD;&#xA;            plot(g, ypxl2, xpxl2, rfpart(yend) * xgap);&#xD;&#xA;            plot(g, ypxl2 + 1, xpxl2, fpart(yend) * xgap);&#xD;&#xA;        } else {&#xD;&#xA;            plot(g, xpxl2, ypxl2, rfpart(yend) * xgap);&#xD;&#xA;            plot(g, xpxl2, ypxl2 + 1, fpart(yend) * xgap);&#xD;&#xA;        }&#xD;&#xA;     &#xD;&#xA;        // main loop &#xD;&#xA;        for (double x = xpxl1 + 1; x &lt;= xpxl2 - 1; x++) {&#xD;&#xA;            if (steep) {&#xD;&#xA;                plot(g, ipart(intery), x, rfpart(intery));&#xD;&#xA;                plot(g, ipart(intery) + 1, x, fpart(intery));&#xD;&#xA;            } else {&#xD;&#xA;                plot(g, x, ipart(intery), rfpart(intery));&#xD;&#xA;                plot(g, x, ipart(intery) + 1, fpart(intery));&#xD;&#xA;            }&#xD;&#xA;            intery = intery + gradient;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;~~~&#xD;&#xA;I know this information:&#xD;&#xA;&#xD;&#xA;The intensity of the pixel above the line must be proportional to (1-a), and the intensity of the pixel below the line must be proportional to (1-b). I.E. the closer the line is to a pixel, the brighter it is.&#xD;&#xA;&#xD;&#xA;Why are the following steps necessary:&#xD;&#xA;- handle the first endpoint?&#xD;&#xA;- handle the second endpoint?&#xD;&#xA;- main loop?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29627" PostHistoryTypeId="5" PostId="10223" RevisionGUID="ae4b4ef9-3727-453e-964d-2c6daadf98ac" CreationDate="2020-09-14T16:04:17.423" UserId="13963" Comment="deleted 109 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="29628" PostHistoryTypeId="5" PostId="10223" RevisionGUID="9b0274b4-1ef5-40d2-89b7-811c124ca2d4" CreationDate="2020-09-14T22:50:27.637" UserId="13963" Comment="added 502 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit:** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera.&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29629" PostHistoryTypeId="5" PostId="10223" RevisionGUID="da4f5e65-7900-49c4-aec8-f71cfa6c2b78" CreationDate="2020-09-15T01:01:20.603" UserId="13963" Comment="added 1330 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit:** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera.&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling." ContentLicense="CC BY-SA 4.0" />
  <row Id="29630" PostHistoryTypeId="2" PostId="10225" RevisionGUID="af7655e2-de07-41dd-b116-e6c0d9a5c934" CreationDate="2020-09-15T02:32:10.067" UserId="13967" Text="If I were to create a chainmail that has realistic reflections, where would I start learning about what mechanisms to use? Normal cloth seems too simple, and the reflections look bad (they have to be in the texture, or the cloth would have to be metalic). If I did it as a series of toroids, physics would have problems with colisions, or they would just overlap weirdly. Maybe there is a hybrid approach? Where can I read about this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29631" PostHistoryTypeId="1" PostId="10225" RevisionGUID="af7655e2-de07-41dd-b116-e6c0d9a5c934" CreationDate="2020-09-15T02:32:10.067" UserId="13967" Text="Realistic chainmail reflections for videogames" ContentLicense="CC BY-SA 4.0" />
  <row Id="29632" PostHistoryTypeId="3" PostId="10225" RevisionGUID="af7655e2-de07-41dd-b116-e6c0d9a5c934" CreationDate="2020-09-15T02:32:10.067" UserId="13967" Text="|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29633" PostHistoryTypeId="5" PostId="10223" RevisionGUID="26800871-1f25-4f0c-a14e-4acafc3ce7d5" CreationDate="2020-09-15T03:43:04.903" UserId="13963" Comment="added 121 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit:** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera.&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29634" PostHistoryTypeId="2" PostId="10226" RevisionGUID="e4bca95a-5b7e-467d-b8a3-1f5c5a97431c" CreationDate="2020-09-15T06:20:28.120" UserId="13968" Text="I have real time depth data coming from an iPhone and I want to identify flat objects within the point cloud so that I can highlight the Hard edges in the images. The objects can be at any angle and I'm only looking for flat faces. &#xD;&#xA;&#xD;&#xA;I'm not a math expert and just looking for ways that this could be done relatively easily so just looking for pointers to relevant algorithms that could achieve this. &#xD;&#xA;&#xD;&#xA;ty" ContentLicense="CC BY-SA 4.0" />
  <row Id="29635" PostHistoryTypeId="1" PostId="10226" RevisionGUID="e4bca95a-5b7e-467d-b8a3-1f5c5a97431c" CreationDate="2020-09-15T06:20:28.120" UserId="13968" Text="Finding a flat plane within iPhone depth data" ContentLicense="CC BY-SA 4.0" />
  <row Id="29636" PostHistoryTypeId="3" PostId="10226" RevisionGUID="e4bca95a-5b7e-467d-b8a3-1f5c5a97431c" CreationDate="2020-09-15T06:20:28.120" UserId="13968" Text="|mathematics|depth-map|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29637" PostHistoryTypeId="50" PostId="9071" RevisionGUID="b540b891-0a12-485a-ad3a-a203b85b980e" CreationDate="2020-09-15T08:04:55.590" UserId="-1" />
  <row Id="29638" PostHistoryTypeId="50" PostId="10084" RevisionGUID="07e3f28c-0aed-4876-9331-fedd8e476401" CreationDate="2020-09-15T10:06:35.657" UserId="-1" />
  <row Id="29639" PostHistoryTypeId="2" PostId="10227" RevisionGUID="f5e172fd-e249-4084-823d-dedf005cbee0" CreationDate="2020-09-15T13:08:01.490" UserId="10129" Text="It seems that you're mixing physics/engine programming with graphics programming. I wouldn't say that dealing with collisions is related to rendering.&#xD;&#xA;&#xD;&#xA;Also, I don't really understand your problem with toroids, but in case, I found one paper related to this term - &quot;3D ChainMail: A Fast Algorithm for Deforming Volumetric Objects&quot; by [Gibson1996]. I would say that if you're interested in creating clothing then you'll have to deal with deformations and animations and not only reflections. And, in case if you'd like to just work with reflections/rendering, then you don't need to deal with physics in any way. Static mesh would be enough, but I'm just speaking based on informations that you've provided until this point.&#xD;&#xA;___&#xD;&#xA;&gt;Normal cloth seems too simple, and the reflections look bad (they have to be in the texture, or the cloth would have to be metalic)&#xD;&#xA;&#xD;&#xA;I wouldn't agree with that and I don't really understand what you've meant by that. In many cases, reflections are indeed in the texture. Or more specifically - cubemap, local environment map, irradiance volume and many other names, used for explaining GI voxel-based methods. https://www.kostasvardis.com/files/research/PhD_Thesis_Kostas_Vardis_book_online_lowres.pdf - [Vardis2016] PhD thesis is nice place to check for methods that you might be interested in. I wouldn't say that normal cloths are too simple. I was never really interested in that area but there are number of papers and overall, creating realistic clothing in not an easy task.&#xD;&#xA;&#xD;&#xA;&gt;Normal cloth seems too simple, and the reflections look bad &#xD;&#xA;&#xD;&#xA;I can only guess that by &quot;bad&quot;, you've meant that there are little to none reflections. That's because most of clothing is rather rough and you've got little materials with big specular term in everyday life. That's why there is little reflection to it.&#xD;&#xA;&#xD;&#xA;I don't know what is your current level of knowledge. Also, I don't know if you're going to creating real-time interactive application or if you're going to create offline renderer. In any case - if you have Turing graphics card or newer, I would suggest using Ray Tracing for most realisting reflections. You can start with cwyman tutorials - http://cwyman.org/code/dxrTutors/dxr_tutors.md.html also you should read microsoft's and nvidia's introduction to DXR. Also, here is a relatively easy path-tracer, created by Matt Petineo - https://github.com/TheRealMJP/DXRPathTracer&#xD;&#xA;&#xD;&#xA;If you get through above tutorials, then you can start reading about denoising and state of the arts methods introduced in recent years - https://alain.xyz/blog/raytracing-denoising Raytracing is a subject, which exists since the begining of computer graphics, so there are a lot of papers related to that. But I think that MJP's example is good enough for start. Also, read related papers that he's stating in github and his code. They're mostly related to avoiding artifacts and fireflies." ContentLicense="CC BY-SA 4.0" />
  <row Id="29640" PostHistoryTypeId="5" PostId="10223" RevisionGUID="1ef62d95-4084-4f47-b361-253ac9bbc1ca" CreationDate="2020-09-15T15:01:42.233" UserId="13963" Comment="added 153 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit:** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29641" PostHistoryTypeId="5" PostId="10223" RevisionGUID="82840f60-1a7e-482e-a9a7-70103333d351" CreationDate="2020-09-15T15:28:05.557" UserId="13963" Comment="added 191 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29642" PostHistoryTypeId="5" PostId="10223" RevisionGUID="039b7d66-a611-4b19-940c-9b1b7b8f6bf4" CreationDate="2020-09-15T16:13:53.873" UserId="13963" Comment="added 477 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="29643" PostHistoryTypeId="2" PostId="10228" RevisionGUID="d0ccb8f9-0165-4bee-8f08-0571e700d8c7" CreationDate="2020-09-15T16:34:21.613" UserId="48" Text="You're not correctly inverting the mapping you used to store the depth value. When storing it you use:&#xA;&#xA;    vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xA;&#xA;Then you reconstruct it as:&#xA;&#xA;    const float depth = normalDepth.w * (FarPlane - NearPlane);&#xA;&#xA;but this misses both the offset by NearPlane, and the negative sign to flip the Z axis (since it points out of the screen in right-handed view space, but you want to store positive values). You're not getting back the same view space you started from—the space that your normals and light are in.&#xA;&#xA;The correct inversion should be:&#xA;&#xA;    const float depth = -(normalDepth.w * (FarPlane - NearPlane) + NearPlane);&#xA;&#xA;The depth values will be negative; this is correct since as mentioned Z points out of the screen in right-handed view space, so the Z values of everything you can see will be below zero. You'll have to tweak some other bits of your code to match—for instance, get rid of the negative sign when you calculate the position xy, and move the light to a negative Z value. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29644" PostHistoryTypeId="5" PostId="10228" RevisionGUID="0c6146fa-a01b-459b-b1c4-a6c9c49d99ea" CreationDate="2020-09-15T16:40:11.843" UserId="48" Comment="added 185 characters in body" Text="You're not correctly inverting the mapping you used to store the depth value. When storing it you use:&#xA;&#xA;    vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xA;&#xA;Then you reconstruct it as:&#xA;&#xA;    const float depth = normalDepth.w * (FarPlane - NearPlane);&#xA;&#xA;but this misses both the offset by NearPlane, and the negative sign to flip the Z axis (since it points out of the screen in right-handed view space, but you want to store positive values). You're not getting back the same view space you started from—the space that your normals and light are in.&#xA;&#xA;The correct inversion should be:&#xA;&#xA;    const float depth = -(normalDepth.w * (FarPlane - NearPlane) + NearPlane);&#xA;&#xA;The depth values will be negative; this is correct since as mentioned Z points out of the screen in right-handed view space, so the Z values of everything you can see will be below zero. You'll have to tweak some other bits of your code to match—for instance, get rid of the negative sign when you calculate the position xy, and move the light to a negative Z value. It's this attempting to work in a space where depths are positive, while using normals in a space where depth is negative, that is most likely causing the lighting issues when rotating." ContentLicense="CC BY-SA 4.0" />
  <row Id="29645" PostHistoryTypeId="5" PostId="10228" RevisionGUID="6a4ecb66-f239-4aec-9596-bdbfc60b43a7" CreationDate="2020-09-15T16:55:12.223" UserId="48" Comment="more about position unprojection" Text="You're not correctly inverting the mapping you used to store the depth value. When storing it you use:&#xD;&#xA;&#xD;&#xA;    vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;Then you reconstruct it as:&#xD;&#xA;&#xD;&#xA;    const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;but this misses both the offset by NearPlane, and the negative sign to flip the Z axis (since it points out of the screen in right-handed view space, but you want to store positive values). You're not getting back the same view space you started from—the space that your normals and light are in.&#xD;&#xA;&#xD;&#xA;The correct inversion should be:&#xD;&#xA;&#xD;&#xA;    const float depth = -(normalDepth.w * (FarPlane - NearPlane) + NearPlane);&#xD;&#xA;&#xD;&#xA;The depth values will be negative; this is correct since as mentioned Z points out of the screen in right-handed view space, so the Z values of everything you can see will be below zero. You'll have to tweak some other bits of your code to match—for instance, get rid of the negative sign when you calculate the position xy, and move the light to a negative Z value. It's this attempting to work in a space where depths are positive, while using normals in a space where depth is negative, that is most likely causing the lighting issues when rotating.&#xD;&#xA;&#xD;&#xA;Your unprojection looks like it's missing the fact that horizontal and vertical FOVs are not the same. You need the aspect ratio in there (same way as used to calculate the projection matrix). In fact, you can just use the scale factors from the projection matrix.&#xD;&#xA;&#xD;&#xA;    vec3 position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position *= depth;&#xD;&#xA;&#xD;&#xA;You could also precalculate those 1/ProjectionMatrix values in a separate uniform value if you liked.&#xD;&#xA;&#xD;&#xA;Finally, I'll just note that you don't need to store a depth value explicitly in a channel of a framebuffer somewhere. It's possible to bind the actual depth buffer as a texture and read that. It's stored using a nonlinear mapping so it takes a bit more code to recover a linear depth value from it, but this ends up being the best way as you get the full precision of the hardware depth buffer, and it doesn't consume a framebuffer channel that you could use for something else. For more information, see [MJP's Position from Depth 3 post](https://mynameismjp.wordpress.com/2010/09/05/position-from-depth-3/)." ContentLicense="CC BY-SA 4.0" />
  <row Id="29646" PostHistoryTypeId="5" PostId="10223" RevisionGUID="b8b30dc6-8c6a-463d-b56e-bc48552281ab" CreationDate="2020-09-15T18:36:53.413" UserId="13963" Comment="added 372 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with some rotation][11]][11]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/kYgJg.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/xVbuZ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29647" PostHistoryTypeId="5" PostId="10223" RevisionGUID="f1670a3d-3040-4844-a7da-70c24780c2d2" CreationDate="2020-09-15T18:57:05.697" UserId="13963" Comment="added 60 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29648" PostHistoryTypeId="5" PostId="10223" RevisionGUID="81f196a1-1039-4e6e-b13a-002290809de4" CreationDate="2020-09-15T19:06:44.867" UserId="13963" Comment="added 354 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/Zs5xE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29649" PostHistoryTypeId="5" PostId="10223" RevisionGUID="cd6c2f75-2215-410f-9dec-86801c0eb257" CreationDate="2020-09-15T20:18:18.457" UserId="13963" Comment="added 320 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/Zs5xE.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="29650" PostHistoryTypeId="5" PostId="10223" RevisionGUID="ad23e1f9-0f34-4455-9815-1e2f817ee628" CreationDate="2020-09-15T21:00:36.053" UserId="13963" Comment="added 272 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![Albedo (diffuse light)][17]][17]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/Zs5xE.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/K5nRa.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29651" PostHistoryTypeId="5" PostId="10223" RevisionGUID="363eeb66-bf55-4914-a446-8c4e78019ce2" CreationDate="2020-09-15T22:16:17.457" UserId="13963" Comment="added 20 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/Zs5xE.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29652" PostHistoryTypeId="5" PostId="10223" RevisionGUID="f02ee6fb-115b-4a72-b05a-eaf801012afb" CreationDate="2020-09-15T23:48:59.873" UserId="13963" Comment="added 577 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;`&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z  *= depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/Zs5xE.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29653" PostHistoryTypeId="5" PostId="10223" RevisionGUID="3f0820b0-aa78-49b4-8b60-62cf0f91fdbc" CreationDate="2020-09-16T00:04:54.413" UserId="13963" Comment="added 219 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;`&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z  *= depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29654" PostHistoryTypeId="5" PostId="10223" RevisionGUID="e1e5e2a0-4012-4ad9-bff0-e639d5d88d17" CreationDate="2020-09-16T01:21:32.590" UserId="13963" Comment="added 204 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29655" PostHistoryTypeId="5" PostId="10223" RevisionGUID="52aa6791-0b3e-4f96-a1e3-600d0c03201b" CreationDate="2020-09-16T02:13:48.873" UserId="13963" Comment="added 241 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 color, vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29656" PostHistoryTypeId="2" PostId="10229" RevisionGUID="d28e34cd-b7e4-4735-abef-63b5744c7294" CreationDate="2020-09-16T07:42:54.283" UserId="10129" Text="Problem was that perspective matrix had very short Z_NEAR and Z_FAR values (0.01f and 200.0f). By changing it to much higher range (10.0f, 20000.0f), problem with jaggies and artifacts disappears." ContentLicense="CC BY-SA 4.0" />
  <row Id="29657" PostHistoryTypeId="33" PostId="10223" RevisionGUID="cabbb7f7-58f6-404f-b3e0-7b96da01cb0a" CreationDate="2020-09-16T13:05:06.277" UserId="13963" Comment="64" />
  <row Id="29658" PostHistoryTypeId="5" PostId="10223" RevisionGUID="efe5b5ec-e14a-4fe3-b95c-fa5e61227294" CreationDate="2020-09-16T14:14:16.733" UserId="13963" Comment="deleted 12 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 1.0 * 1.0 * 1.0 (unitCube)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29659" PostHistoryTypeId="5" PostId="10223" RevisionGUID="1dd78ca5-10c1-4bb8-9037-14b127a2bb96" CreationDate="2020-09-16T18:19:36.207" UserId="13963" Comment="added 43 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 5.0 * 5.0 * 5.0 (actually each box is made up of 5x5x5 smaller boxes)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29660" PostHistoryTypeId="5" PostId="10223" RevisionGUID="cac0223b-a3e5-4ead-803a-bfedc3d151f8" CreationDate="2020-09-16T18:44:29.283" UserId="13963" Comment="added 977 characters in body" Text="I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 5.0 * 5.0 * 5.0 (actually each box is made up of 5x5x5 smaller boxes)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;**Edit 10**&#xD;&#xA;&#xD;&#xA;Still not giving up, learning alot, but getting abit crazy at this problem.&#xD;&#xA;So now when I look at the reconstructed using *fract(position)*. This below is what I get (right side is the fract part, left side is just the scene with diffuse point light moving around wrongly).&#xD;&#xA;&#xD;&#xA;the position seems to be correct now when I look at it, as each texture on left side is one unit. and that is matching the the reconstructed position:&#xD;&#xA;&#xD;&#xA;[![enter image description here][20]][20]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, as Nathan pointed out. I can look at *fract(vPos)* in the fist pass, that is how the reconstructed position also should look.&#xD;&#xA;&#xD;&#xA;And still, this is how it looks like, from the first pass:&#xD;&#xA;&#xD;&#xA;[![enter image description here][21]][21]&#xD;&#xA;&#xD;&#xA;That one makes less sence for me, should I not be able to see the fractions in the same way there? For me the reconstructed one makes more sence&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg&#xD;&#xA;  [20]: https://i.stack.imgur.com/OGmFp.jpg&#xD;&#xA;  [21]: https://i.stack.imgur.com/tEtux.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29661" PostHistoryTypeId="5" PostId="10223" RevisionGUID="fb34e8fe-3623-43d8-ba08-c9eb0c78c74e" CreationDate="2020-09-16T19:05:44.130" UserId="13963" Comment="added 546 characters in body" Text="**Current state:** &#xD;&#xA;&#xD;&#xA;I belive the reconstructed positions are correct. However, I still have the same problem as all the time. When I rotate around my single pointlight appears to be moving around also.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**The explanation**&#xD;&#xA;&#xD;&#xA;I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 5.0 * 5.0 * 5.0 (actually each box is made up of 5x5x5 smaller boxes)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;**Edit 10**&#xD;&#xA;&#xD;&#xA;Still not giving up, learning alot, but getting abit crazy at this problem.&#xD;&#xA;So now when I look at the reconstructed using *fract(position)*. This below is what I get (right side is the fract part, left side is just the scene with diffuse point light moving around wrongly).&#xD;&#xA;&#xD;&#xA;the position seems to be correct now when I look at it, as each texture on left side is one unit. and that is matching the the reconstructed position:&#xD;&#xA;&#xD;&#xA;[![enter image description here][20]][20]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, as Nathan pointed out. I can look at *fract(vPos)* in the fist pass, that is how the reconstructed position also should look.&#xD;&#xA;&#xD;&#xA;And still, this is how it looks like, from the first pass:&#xD;&#xA;&#xD;&#xA;[![enter image description here][21]][21]&#xD;&#xA;&#xD;&#xA;That one makes less sence for me, should I not be able to see the fractions in the same way there? For me the reconstructed one makes more sence&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 10**&#xD;&#xA;&#xD;&#xA;New findings!&#xD;&#xA;&#xD;&#xA;I did fract directly in the first pass, to see how it looks like. I did not think about the values getting changed when saved to texture, so I was not looking at what I though before.&#xD;&#xA;&#xD;&#xA;Anyways, it looks exactly the same as the reconstructed values, see below!&#xD;&#xA;&#xD;&#xA;[![enter image description here][22]][22]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I belive now I have the right constructed depth. But however, still having the same issues as always, light seems to rotate around when I am moving.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg&#xD;&#xA;  [20]: https://i.stack.imgur.com/OGmFp.jpg&#xD;&#xA;  [21]: https://i.stack.imgur.com/tEtux.png&#xD;&#xA;  [22]: https://i.stack.imgur.com/GQvMR.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29662" PostHistoryTypeId="5" PostId="10223" RevisionGUID="4f2ee739-bd53-42e7-86c6-1354057ed69e" CreationDate="2020-09-16T19:34:49.673" UserId="13963" Comment="edited body" Text="**Current state:** &#xD;&#xA;&#xD;&#xA;I belive the reconstructed positions are correct. However, I still have the same problem as all the time. When I rotate around my single pointlight appears to be moving around also.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**The explanation**&#xD;&#xA;&#xD;&#xA;I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 5.0 * 5.0 * 5.0 (actually each box is made up of 5x5x5 smaller boxes)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;**Edit 10**&#xD;&#xA;&#xD;&#xA;Still not giving up, learning alot, but getting abit crazy at this problem.&#xD;&#xA;So now when I look at the reconstructed using *fract(position)*. This below is what I get (right side is the fract part, left side is just the scene with diffuse point light moving around wrongly).&#xD;&#xA;&#xD;&#xA;the position seems to be correct now when I look at it, as each texture on left side is one unit. and that is matching the the reconstructed position:&#xD;&#xA;&#xD;&#xA;[![enter image description here][20]][20]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, as Nathan pointed out. I can look at *fract(vPos)* in the fist pass, that is how the reconstructed position also should look.&#xD;&#xA;&#xD;&#xA;And still, this is how it looks like, from the first pass:&#xD;&#xA;&#xD;&#xA;[![enter image description here][21]][21]&#xD;&#xA;&#xD;&#xA;That one makes less sence for me, should I not be able to see the fractions in the same way there? For me the reconstructed one makes more sence&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 11**&#xD;&#xA;&#xD;&#xA;New findings!&#xD;&#xA;&#xD;&#xA;I did fract directly in the first pass, to see how it looks like. I did not think about the values getting changed when saved to texture, so I was not looking at what I though before.&#xD;&#xA;&#xD;&#xA;Anyways, it looks exactly the same as the reconstructed values, see below!&#xD;&#xA;&#xD;&#xA;[![enter image description here][22]][22]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I belive now I have the right constructed depth. But however, still having the same issues as always, light seems to rotate around when I am moving.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg&#xD;&#xA;  [20]: https://i.stack.imgur.com/OGmFp.jpg&#xD;&#xA;  [21]: https://i.stack.imgur.com/tEtux.png&#xD;&#xA;  [22]: https://i.stack.imgur.com/GQvMR.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29663" PostHistoryTypeId="50" PostId="10103" RevisionGUID="0cb4180a-85fb-48f8-8517-12450d41dac2" CreationDate="2020-09-16T20:04:15.353" UserId="-1" />
  <row Id="29664" PostHistoryTypeId="2" PostId="10230" RevisionGUID="4cc4ca49-ad2f-41da-a2ca-ebb168933241" CreationDate="2020-09-16T20:23:31.983" UserId="13963" Text="Ok. So Finally, I have solved the problem. This problem I been working on for a couple of weeks. Had to go through several books in math, gamedev etc. Went through all my code, to see if I had something I did missunderstand.&#xD;&#xA;&#xD;&#xA;Finally I found the problem! I was trying to store normals in the texture, with values between [-1, 1], I did not think about the values stored in the texture has to be [0, 1].&#xD;&#xA;&#xD;&#xA;So I normalized them to [0, 1]. And then in the second pass I the normalize them back to [-1, 1], and finally, after many long nights of search, the problem has been found!&#xD;&#xA;&#xD;&#xA;SOLVED!" ContentLicense="CC BY-SA 4.0" />
  <row Id="29665" PostHistoryTypeId="5" PostId="10223" RevisionGUID="b614668d-75e0-42f4-806f-b7f1e1c3cd8c" CreationDate="2020-09-16T20:26:34.063" UserId="13963" Comment="added 76 characters in body" Text="**Current state:** &#xD;&#xA;&#xD;&#xA;I belive the reconstructed positions are correct. However, I still have the same problem as all the time. When I rotate around my single pointlight appears to be moving around also.&#xD;&#xA;&#xD;&#xA;I finally solved this! It was annoying, but I did learn alot on the way.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;**The explanation**&#xD;&#xA;&#xD;&#xA;I am trying to recreate viewspace positions from only a stored depth value, and then calculate the light in viewspace.&#xD;&#xA;&#xD;&#xA;In the first pass I store the Normals and the normalized depth in viewspace.&#xD;&#xA;In the second pass I try to build reconstruct the position in viewspace.&#xD;&#xA;&#xD;&#xA;I belive something is going wrong in the reconstruction, but I can't see what, or if it something else. I did try to reconstruct the position in different ways, always with the same not good result.&#xD;&#xA;&#xD;&#xA;The light initially looks fine, but when I start moving around the light seems to be moving around.&#xD;&#xA;When I go futher away, things get less lit. When rotating the light also rotates.&#xD;&#xA;Note: When I render out the actual depth values, it looks fine, so think the depth is fine.&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?&#xD;&#xA;&#xD;&#xA;Belove is code for the fragment &amp; vertex shader, first and second pass.&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;**First pass:**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;layout( location = 1 ) in vec3 VertexNormal;&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;uniform mat4 ProjectionMatrix;&#xD;&#xA;uniform mat3 NormalMatrix;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;&#xD;&#xA;out vec3 vNormal;&#xD;&#xA;out highp float vDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  mat4 vMVP = ProjectionMatrix * ViewMatrix;&#xD;&#xA;  gl_Position = vMVP * vec4( VertexPosition, 1.0 ); // Screenspace&#xD;&#xA;&#xD;&#xA;  vNormal = normalize(NormalMatrix  * normalize(VertexNormal));&#xD;&#xA;  vec3 vPos = (ViewMatrix * vec4( VertexPosition, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  // Save normalized depth [0, 1]&#xD;&#xA;  vDepth = -(vPos.z - NearPlane) / ( FarPlane - NearPlane);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;in vec3 vNormal;&#xD;&#xA;in highp float vDepth;&#xD;&#xA;&#xD;&#xA;layout (location = 0) out highp vec4 NormalDepth;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  NormalDepth = vec4(normalize(vNormal), vDepth);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Second pass** (off rendering to screen):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;--Vertex&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) in vec3 VertexPosition;&#xD;&#xA;&#xD;&#xA;out vec2 vTexCoord;&#xD;&#xA;out vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vDeviceCoords = 2.0 * ( VertexPosition.xy - 0.5 );// [-1, 1]&#xD;&#xA;  vTexCoord = VertexPosition.xy;//  [0, 1] // Just 2 triangles for the screen&#xD;&#xA;&#xD;&#xA;  gl_Position = vec4(vDeviceCoords, 1.0, 1.0 ); // [-1, 1]&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;--Fragment&#xD;&#xA;#version 460&#xD;&#xA;&#xD;&#xA;/* Uniforms */&#xD;&#xA;uniform float NearPlane;&#xD;&#xA;uniform float FarPlane;&#xD;&#xA;uniform mat4 ViewMatrix;&#xD;&#xA;&#xD;&#xA;in vec2 vTexCoord;&#xD;&#xA;in vec2 vDeviceCoords;&#xD;&#xA;&#xD;&#xA;layout( location = 0 ) out vec4 FragColor;&#xD;&#xA;layout( binding = 0 ) uniform highp sampler2D NormalDepthTex;&#xD;&#xA;&#xD;&#xA;vec3 diffuseValue( vec3 normal, vec3 position)&#xD;&#xA;{&#xD;&#xA;  // Light position. Here now for testing purposes&#xD;&#xA;  // Stationary point light, transformed to viewspace&#xD;&#xA;  vec3 vLightPos = (ViewMatrix * vec4( -10.0, 0.0, 2.0, 1.0 )).xyz;&#xD;&#xA;&#xD;&#xA;  normal = normalize(normal);&#xD;&#xA;  const vec3 lightDir = normalize(position - vLightPos);&#xD;&#xA;  const float diffuseCos = max( dot( normal, -lightDir ), 0.0 );&#xD;&#xA;&#xD;&#xA;  return vec3(diffuseCos);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  const vec4 normalDepth = texture2D( NormalDepthTex, vTexCoord );&#xD;&#xA;&#xD;&#xA;  // Normalize depth to [0, FarPlane]&#xD;&#xA;  const float depth = normalDepth.w * (FarPlane - NearPlane);&#xD;&#xA;&#xD;&#xA;  // Unproject&#xD;&#xA;  vec3 position;&#xD;&#xA;  position = vec3(vDeviceCoords.x, vDeviceCoords.y, NearPlane);&#xD;&#xA;  position.xy *= -depth / NearPlane; &#xD;&#xA;  position.z = depth;&#xD;&#xA;&#xD;&#xA;  // View space&#xD;&#xA;  vec3 diffuseValue = diffuseValue(normalDepth.xyz, position);&#xD;&#xA;&#xD;&#xA;  FragColor = vec4( diffuseValue.x, diffuseValue.y, diffuseValue.z, 1.0 );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Edit 1** &#xD;&#xA;&#xD;&#xA;Adding screenshot.&#xD;&#xA;&#xD;&#xA;for the normals, they looks correct, always pointing toward the camera. (also I can add, if I do the light in the first pass (not reconstructed depth), then the light is 100% fine).&#xD;&#xA;&#xD;&#xA;[![Rendering the normals][1]][1]&#xD;&#xA;&#xD;&#xA;If we look at the light, initially it looks good. I positioned the light so It should shade as seen. But it changes and becomes wrong when I rote the camera. Also the intensity changes when I go further/closer with the camera.&#xD;&#xA;&#xD;&#xA;[![The light (albedo value)][2]][2]&#xD;&#xA;&#xD;&#xA;If we slightly rotate left for example, then the light follows (I want it in position!):&#xD;&#xA;&#xD;&#xA;[![Light moved][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The viewspace depth [0, 1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2:** &#xD;&#xA;&#xD;&#xA;I have now reconstructed the depth in three different ways, all with the same result. I am starting to think There is something else I am doing wrong? Do I calculate the light wrong or something?&#xD;&#xA;&#xD;&#xA;The three ways I have rebuilt (or tryed to) are:&#xD;&#xA;&#xD;&#xA;*Option 1:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w; // Should be [0, 1]&#xD;&#xA;&#xD;&#xA;    // Create ray to FarPlane&#xD;&#xA;    // HalfVec is FarPlane * glm::tan( glm::radians( m_fov / 2.0f ) )&#xD;&#xA;    vec3 ray = vec3(vDeviceCoords * HalfVec, FarPlane);&#xD;&#xA;&#xD;&#xA;    // Unprojection&#xD;&#xA;    position.xy = ray.xy * -depth / NearPlane;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 2:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.w * FarPlane;&#xD;&#xA;&#xD;&#xA;    vec2 p = vDeviceCoords * NearPlane * tan(radians(Fov / 2.0));&#xD;&#xA;    vec2 p_ = (p / NearPlane) * -depth;&#xD;&#xA;&#xD;&#xA;   position = vec3(p_, depth);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;*Option 3:*&#xD;&#xA;```&#xD;&#xA;    depth  = normalDepth.z;&#xD;&#xA;&#xD;&#xA;    mat4 inversePrjMat = inverse( ProjectionMatrix );&#xD;&#xA;    vec4 viewPosH      = inversePrjMat * vec4( vDeviceCoords.x, vDeviceCoords.y, 1.0, 1.0 );&#xD;&#xA;    vec3 farPlaneRay   = viewPosH.xyz / viewPosH.w;&#xD;&#xA;&#xD;&#xA;    position = farPlaneRay;&#xD;&#xA;    position.xy *= -depth;&#xD;&#xA;    position.z = depth * FarPlane;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;These all options ends up the same. I have recalculated and went through the math over and over again, there is something else I am missing is my feeling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 3**&#xD;&#xA;&#xD;&#xA;was asked to upload image with the normals (R, G, B). When camera is abit rotated. &#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;**Edit 4**&#xD;&#xA;&#xD;&#xA;Adding some GIF animations that shows what is going on with the light. As you can see, if I dont rotate at all. just move around, then the light is as it should.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Moving around 1][6]][6]&#xD;&#xA;&#xD;&#xA;[![Moving around 2][7]][7]&#xD;&#xA;&#xD;&#xA;[![Moving around 3][8]][8]&#xD;&#xA;&#xD;&#xA;[![Moving around 4][9]][9]&#xD;&#xA;&#xD;&#xA;**Edit 5**&#xD;&#xA;&#xD;&#xA;I did the correction  Nathan Reed pointed out. Still with no better result.&#xD;&#xA;This is what it looks like when I render out fract(position).&#xD;&#xA;The boxes I render have a size 5.0 * 5.0 * 5.0 (actually each box is made up of 5x5x5 smaller boxes)&#xD;&#xA;&#xD;&#xA;[![fract(position)][10]][10]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and abit more angled view at the boxes&#xD;&#xA;&#xD;&#xA;[![fract(position) with angle][11]][11]&#xD;&#xA;&#xD;&#xA;**Edit 6**&#xD;&#xA;&#xD;&#xA;this is frontview, rendering ```vec4( fract(position.x), 0.0, 0.0, 1.0 );``` [![vec4( fract(position.x), 0.0, 0.0, 1.0 )][12]][12]&#xD;&#xA;&#xD;&#xA;This is with  vec4( fract(position.y), 0.0, 0.0, 1.0 )&#xD;&#xA;&#xD;&#xA;[![ vec4( fract(position.y), 0.0, 0.0, 1.0 )][13]][13]&#xD;&#xA;&#xD;&#xA;This is what it looks like when i render  vec4( VertexPosition, 1.0 ); (the 2 triangles making up the fullscreen in the second pass)&#xD;&#xA;&#xD;&#xA;[![enter image description here][14]][14]&#xD;&#xA;&#xD;&#xA;**edit 7**&#xD;&#xA;&#xD;&#xA;This is what is looks like if i render the fract(vPos) from the first pass. &#xD;&#xA;[![fract(vPos) from the first pass][15]][15]&#xD;&#xA;&#xD;&#xA;Here I render just vPos from the first pass&#xD;&#xA;[![enter image description here][16]][16]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 8**&#xD;&#xA;&#xD;&#xA;This is about how it should look like. This is when I do the light calculation directly in the first pass. It is stationary, and perfect, as it should be, in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][17]][17]&#xD;&#xA;&#xD;&#xA;**Edit 9**&#xD;&#xA;&#xD;&#xA;I just rendered the constructed positions, and noticed x,y-axies are flipped&#xD;&#xA;need to negate x,y when multiplying with depth, since depth is negate.&#xD;&#xA;Also we are saving the depth in viewspace, so use it straight for the z-component. That is correct, it can be noticed by the light not fading away when moving away futher with the position.z set to depth.&#xD;&#xA;Also, we are multiplying xy with depth since triangle similarity. To be more precise we should divide that with the nearplane, I will do that, but I am using nearplane = 1, so wont be any practical difference right now anyways.&#xD;&#xA;&#xD;&#xA;So I did this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    position = vec3(vDeviceCoords.x / ProjectionMatrix[0][0], vDeviceCoords.y / ProjectionMatrix[1][1], 1.0);&#xD;&#xA;    position.xy *= -depth / NearPlane;&#xD;&#xA;    position.z  = depth;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now the light calculated on the second pass looks very much correct, appart from rotating... The light don't even fade when going futher. As long as I dont rotate(!)&#xD;&#xA;&#xD;&#xA;Is there something else obvious I am missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;light, when moved, but not rotated at all:&#xD;&#xA;&#xD;&#xA;[![Moved, but rotated][18]][18]&#xD;&#xA;&#xD;&#xA;Reconstructed and Position looks the same when rendered. but when doing fract on the reconstructed position I still get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][19]][19]&#xD;&#xA;&#xD;&#xA;**Edit 10**&#xD;&#xA;&#xD;&#xA;Still not giving up, learning alot, but getting abit crazy at this problem.&#xD;&#xA;So now when I look at the reconstructed using *fract(position)*. This below is what I get (right side is the fract part, left side is just the scene with diffuse point light moving around wrongly).&#xD;&#xA;&#xD;&#xA;the position seems to be correct now when I look at it, as each texture on left side is one unit. and that is matching the the reconstructed position:&#xD;&#xA;&#xD;&#xA;[![enter image description here][20]][20]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, as Nathan pointed out. I can look at *fract(vPos)* in the fist pass, that is how the reconstructed position also should look.&#xD;&#xA;&#xD;&#xA;And still, this is how it looks like, from the first pass:&#xD;&#xA;&#xD;&#xA;[![enter image description here][21]][21]&#xD;&#xA;&#xD;&#xA;That one makes less sence for me, should I not be able to see the fractions in the same way there? For me the reconstructed one makes more sence&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit 11**&#xD;&#xA;&#xD;&#xA;New findings!&#xD;&#xA;&#xD;&#xA;I did fract directly in the first pass, to see how it looks like. I did not think about the values getting changed when saved to texture, so I was not looking at what I though before.&#xD;&#xA;&#xD;&#xA;Anyways, it looks exactly the same as the reconstructed values, see below!&#xD;&#xA;&#xD;&#xA;[![enter image description here][22]][22]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I belive now I have the right constructed depth. But however, still having the same issues as always, light seems to rotate around when I am moving.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ts4j7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/63LmJ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/NUm2I.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/BjdEy.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/AgUzI.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/RQGjW.gif&#xD;&#xA;  [7]: https://i.stack.imgur.com/G3reu.gif&#xD;&#xA;  [8]: https://i.stack.imgur.com/DzBFa.gif&#xD;&#xA;  [9]: https://i.stack.imgur.com/k0Xds.gif&#xD;&#xA;  [10]: https://i.stack.imgur.com/qg865.jpg&#xD;&#xA;  [11]: https://i.stack.imgur.com/s1lxj.jpg&#xD;&#xA;  [12]: https://i.stack.imgur.com/5l74u.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/DXys6.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/rksek.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/z3CJl.gif&#xD;&#xA;  [16]: https://i.stack.imgur.com/w7o1w.gif&#xD;&#xA;  [17]: https://i.stack.imgur.com/ss3y7.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/g3zm1.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/uMn0s.jpg&#xD;&#xA;  [20]: https://i.stack.imgur.com/OGmFp.jpg&#xD;&#xA;  [21]: https://i.stack.imgur.com/tEtux.png&#xD;&#xA;  [22]: https://i.stack.imgur.com/GQvMR.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29666" PostHistoryTypeId="5" PostId="10230" RevisionGUID="b930913f-9c68-48db-9e26-b205e6a548be" CreationDate="2020-09-16T20:35:01.003" UserId="13963" Comment="added 74 characters in body" Text="Ok. So Finally, I have solved the problem. This problem I been working on for a couple of weeks. Had to go through several books in math, gamedev etc. Went through all my code, to see if I had something I did missunderstand.&#xD;&#xA;&#xD;&#xA;Finally I found the problem! I was trying to store normals in the texture, with values between [-1, 1], I did not think about the values stored in the texture has to be [0, 1].&#xD;&#xA;&#xD;&#xA;So I normalized them to [0, 1]. And then in the second pass I the normalize them back to [-1, 1], and finally, after many long nights of search, the problem has been found!&#xD;&#xA;&#xD;&#xA;Hope this will help others also! And thanks everyone who had a look!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;SOLVED!" ContentLicense="CC BY-SA 4.0" />
  <row Id="29667" PostHistoryTypeId="2" PostId="10231" RevisionGUID="7e7fa1ea-1e8c-4f79-be62-2496f6d20a34" CreationDate="2020-09-16T20:55:20.040" UserId="11058" Text="I have searched this topic for very long time and have found basically no information on it.&#xD;&#xA;&#xD;&#xA;If we have a 3d model with a uv layout. What is the basic technique for 3d painting on said model with a brush? A brush stroke consists of the brush pixel data/image laid out in succession. So do we project each individual brush image onto the surface of the object? (Although in actuality to do this we would be projecting the object onto the image space instead). I have managed to project textures onto objects before. And projecting each individual brush image definitely seems feasible, but I'm not sure if it's practical from performance standpoint and whether there're better techniques.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sSfgM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29668" PostHistoryTypeId="1" PostId="10231" RevisionGUID="7e7fa1ea-1e8c-4f79-be62-2496f6d20a34" CreationDate="2020-09-16T20:55:20.040" UserId="11058" Text="How to paint onto 3d models" ContentLicense="CC BY-SA 4.0" />
  <row Id="29669" PostHistoryTypeId="3" PostId="10231" RevisionGUID="7e7fa1ea-1e8c-4f79-be62-2496f6d20a34" CreationDate="2020-09-16T20:55:20.040" UserId="11058" Text="|opengl|texture|image-processing|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29670" PostHistoryTypeId="2" PostId="10232" RevisionGUID="f61b4152-068a-40b4-8d12-267ba8d7e832" CreationDate="2020-09-16T20:57:30.947" UserId="13979" Text="For Nvidia GPUs there are several machine languages all of which can be read here:&#xD;&#xA;https://docs.nvidia.com/cuda/cuda-binary-utilities/index.html#instruction-set-ref&#xD;&#xA;&#xD;&#xA;Above the &quot;Instruction Set Reference&quot; section there are also some examples on SM70 variant of SASS code which is stored in ELF and dumped from there too so it's a machine code as ELF always was an unmanaged code container by historic reasons (apart from PE which could contain CIL managed code but even in this case it must be in data section while ELF does not support such confusing feature at all) and it's not managed/virtual bytecode or something as some users say so, it's a real native compiled device code for GPU. As a drawback, fatbin technique may be required if a distributor has chosen to publish the GPU program in precompiled form rather than source code or at least portable PTX. But that is very rare as there are not as much such programs around as binaries for CPU. Anyway such code is usually contained within cubin files which are dynamically loaded by calling &quot;cuModuleLoad&quot; then you rewrite pointer to device GPU function handle using &quot;cuModuleGetFunction&quot; and then call &quot;cuLaunchKernel&quot; which forces the driver to send binary code to the GPU and start execution from like 0 address as all the kernels start from 0 (actually ELF variant used by Nvidia contains many sections but the driver only sends the desired kernel code along with its subroutines and data such as switch data etc.). And what about the instructions itself, well, they are mostly RISC-fashioned. There is no div or mod, instead nvcc compiler must output sophisticated algorithm based on addition, subtraction, multiplication, shifts, bitwise logical operations (bitwise and mostly). Only addressing mode reminds some CISC presence like &quot;LD R2, [R2+0x1c];&quot; etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="29671" PostHistoryTypeId="5" PostId="10232" RevisionGUID="3288ad70-c7e9-4f45-91e2-76580cce18d2" CreationDate="2020-09-16T21:06:30.297" UserId="13979" Comment="added 226 characters in body" Text="For Nvidia GPUs there are several machine languages all of which can be read here:&#xD;&#xA;https://docs.nvidia.com/cuda/cuda-binary-utilities/index.html#instruction-set-ref&#xD;&#xA;&#xD;&#xA;Above the &quot;Instruction Set Reference&quot; section there are also some examples on SM70 variant of SASS code which is stored in ELF and dumped from there too so it's a machine code as ELF always was an unmanaged code container by historic reasons (apart from PE which could contain CIL managed code but even in this case it must be in data section while ELF does not support such confusing feature at all) and it's not managed/virtual bytecode or something as some users say so, it's a real native compiled device code for GPU. The correct instructions though are those which are written with capital letter and addresses in hexademical form (like /\*0000*/ MOV R1, c[0x0][0x28] ;), others are just PTX and they aren't actually relevant to the question. As a drawback, fatbin technique may be required if a distributor has chosen to publish the GPU program in precompiled form rather than source code or at least portable PTX. But that is very rare as there are not as much such programs around as binaries for CPU. Anyway such code is usually contained within cubin files which are dynamically loaded by calling &quot;cuModuleLoad&quot; then you rewrite pointer to device GPU function handle using &quot;cuModuleGetFunction&quot; and then call &quot;cuLaunchKernel&quot; which forces the driver to send binary code to the GPU and start execution from like 0 address as all the kernels start from 0 (actually ELF variant used by Nvidia contains many sections but the driver only sends the desired kernel code along with its subroutines and data such as switch data etc.). And what about the instructions itself, well, they are mostly RISC-fashioned. There is no div or mod, instead nvcc compiler must output sophisticated algorithm based on addition, subtraction, multiplication, shifts, bitwise logical operations (bitwise and mostly). Only addressing mode reminds some CISC presence like &quot;LD R2, [R2+0x1c];&quot; etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="29672" PostHistoryTypeId="2" PostId="10233" RevisionGUID="a61ee3cd-63df-44d0-be08-f0a4edcbfc08" CreationDate="2020-09-17T00:19:37.630" UserId="13963" Text="You could do it in different ways.&#xD;&#xA;&#xD;&#xA;But the most logical way for me is that there are points sampled along the path, then splines/benzier curves are used to make it smooth (additonal points can be interpolated), thereafter it is projected and saved on the texture. So no &quot;every&quot; point has to be sampled." ContentLicense="CC BY-SA 4.0" />
  <row Id="29673" PostHistoryTypeId="2" PostId="10234" RevisionGUID="30e7035f-2e5f-49fc-bb78-8e3ece5d4533" CreationDate="2020-09-17T00:27:18.857" UserId="13963" Text="I belive what you are looking for is a scale Matrix.&#xD;&#xA;&#xD;&#xA;Usually they look like this&#xD;&#xA;&#xD;&#xA;    Sx  0   0   0&#xD;&#xA;    0   Sy  0   0&#xD;&#xA;    0   0  Sz   0&#xD;&#xA;    0   0  0    1&#xD;&#xA;&#xD;&#xA;If you have no scaling, Sx, Sy, Sz represent the scaling in corresponding dimension.&#xD;&#xA;So put the to 1 for no scaling.&#xD;&#xA;&#xD;&#xA;But now you want to scale the height depending on the z value. So we want to modify it abit. If you would put Sx, Sy, Sz to the value one. And the put a higher value than one on Syz, then it would scale the height (Y), the futher away you are.&#xD;&#xA;&#xD;&#xA;    Sx  0    0   0&#xD;&#xA;    0   Sy  Syz  0&#xD;&#xA;    0   0   Sz   0&#xD;&#xA;    0   0   0    1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29674" PostHistoryTypeId="2" PostId="10235" RevisionGUID="652f3364-67ba-4817-b6fa-a009ec3f113c" CreationDate="2020-09-17T00:54:48.760" UserId="7462" Text="So to make it simple. I currently use a method I found online to compute the gradient of a scalar field of a mesh.&#xD;&#xA;&#xD;&#xA;To test how accurate this is, I made a sphere and followed the gradient direction of the geodesic field to construct a line. That is to say, pick $p$ on the sphere and define $\phi(X)$ the function that return the geodesic distance between $X$ and $p$.&#xD;&#xA; &#xD;&#xA;By a property of the exponential map described by Manfredo Do Carmo, the geodesic gradient (the tangent) at $X$ uniquely describes the geodesic containing both $X$ and $P$. &#xD;&#xA;&#xD;&#xA;In short, if you know the correct tangent at $X$ you can just follow that direction in the exponential map and eventually hit the source $p$.&#xD;&#xA;&#xD;&#xA;So I went and coded exactly that:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;In that image, the source $p$ is at the intersection of the 3 lines in the bottom part of the image. So my line passes very close to it, but it doesn't hit.&#xD;&#xA;&#xD;&#xA;My assumption is, this happens because my gradient approximation is quite linearly based and as such even small errors quickly have big effects, especially as the points grow farther apart.&#xD;&#xA;&#xD;&#xA;I am wondering  if people know of methods or algorithms that can improve the accuracy of the gradient.&#xD;&#xA;&#xD;&#xA;I got the formula for the discrete gradient at page 28 [here][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4BaIL.png&#xD;&#xA;  [2]: http://www.hao-li.com/cs599-ss2015/slides/Lecture04.1.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29675" PostHistoryTypeId="1" PostId="10235" RevisionGUID="652f3364-67ba-4817-b6fa-a009ec3f113c" CreationDate="2020-09-17T00:54:48.760" UserId="7462" Text="Improve accuracy of mesh gradient?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29676" PostHistoryTypeId="3" PostId="10235" RevisionGUID="652f3364-67ba-4817-b6fa-a009ec3f113c" CreationDate="2020-09-17T00:54:48.760" UserId="7462" Text="|mathematics|computational-geometry|geometry|gradient|differential|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29677" PostHistoryTypeId="2" PostId="10236" RevisionGUID="8cebdf78-428c-4f31-b686-b5676b1aa8ba" CreationDate="2020-09-17T01:18:11.827" UserId="13963" Text="I dont know what you are using to calculate the Cotan, the accuracy should different on the implementation. &#xD;&#xA;&#xD;&#xA;But you could do more accurate calculations yourself by approximating the values using taylor expansions. &#xD;&#xA;&#xD;&#xA;Or find some other librar that can do it more accurate.&#xD;&#xA;&#xD;&#xA;Also, make sure you are using high prec datatypes." ContentLicense="CC BY-SA 4.0" />
  <row Id="29678" PostHistoryTypeId="5" PostId="10234" RevisionGUID="dd9ae971-bdf0-4df8-ae62-24bf8551f519" CreationDate="2020-09-17T02:38:58.390" UserId="13963" Comment="added 60 characters in body" Text="I belive what you are looking for is a scale Matrix, or actually it will end upp with as a shear matrix for you.&#xD;&#xA;&#xD;&#xA;Usually they look like this&#xD;&#xA;&#xD;&#xA;    Sx  0   0   0&#xD;&#xA;    0   Sy  0   0&#xD;&#xA;    0   0  Sz   0&#xD;&#xA;    0   0  0    1&#xD;&#xA;&#xD;&#xA;If you have no scaling, Sx, Sy, Sz represent the scaling in corresponding dimension.&#xD;&#xA;So put the to 1 for no scaling.&#xD;&#xA;&#xD;&#xA;But now you want to scale the height depending on the z value. So we want to modify it abit. If you would put Sx, Sy, Sz to the value one. And the put a higher value than one on Syz, then it would scale the height (Y), the futher away you are.&#xD;&#xA;&#xD;&#xA;    Sx  0    0   0&#xD;&#xA;    0   Sy  Syz  0&#xD;&#xA;    0   0   Sz   0&#xD;&#xA;    0   0   0    1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29679" PostHistoryTypeId="50" PostId="8790" RevisionGUID="cee6b358-68ef-41ed-92c2-1bfb30fa1426" CreationDate="2020-09-17T09:03:35.400" UserId="-1" />
  <row Id="29680" PostHistoryTypeId="2" PostId="10237" RevisionGUID="125bf4d1-c958-450e-9278-6656f3757612" CreationDate="2020-09-17T16:46:34.577" UserId="6281" Text="Since there is a lot of cross-section between computer vision and computer graphics for 3D pose and shape estimation of non-rigid objects, I would like to know what &quot;blend shape&quot;, &quot;pose blend shape&quot; and &quot;shape blend shape,&quot; exactly mean in 3D modeling of human shape and pose?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29681" PostHistoryTypeId="1" PostId="10237" RevisionGUID="125bf4d1-c958-450e-9278-6656f3757612" CreationDate="2020-09-17T16:46:34.577" UserId="6281" Text="Blend Shape, Pose Blend Shape, and Shape Blend Shape" ContentLicense="CC BY-SA 4.0" />
  <row Id="29682" PostHistoryTypeId="3" PostId="10237" RevisionGUID="125bf4d1-c958-450e-9278-6656f3757612" CreationDate="2020-09-17T16:46:34.577" UserId="6281" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29683" PostHistoryTypeId="2" PostId="10238" RevisionGUID="97e05888-97e1-44c4-9c6f-b325ce1c3db4" CreationDate="2020-09-17T18:28:50.277" UserId="13963" Text="The terminology you are looking for is &quot;Volume Renderig&quot;&#xD;&#xA;&#xD;&#xA;A MRI scan scans a &quot;volume&quot; (object). You get a point close, with different density of different matter, for example skin/blood har different density. The you can use the point cloud to do volune rendering. &#xD;&#xA;&#xD;&#xA;So what you want to do is go make your mest Into a point cloud, with density, density depending on what matter the volume contains. Then you want to har that data for volume rendering.&#xD;&#xA;&#xD;&#xA;Then you can yourself decide how/what to render, slice through the data or whatever" ContentLicense="CC BY-SA 4.0" />
  <row Id="29684" PostHistoryTypeId="5" PostId="10238" RevisionGUID="f829dfb7-d610-4ae1-8940-c3e22c4ccad7" CreationDate="2020-09-17T19:57:54.240" UserId="13963" Comment="added 1 character in body" Text="The terminology you are looking for is &quot;Volume Renderig&quot;&#xD;&#xA;&#xD;&#xA;A MRI scan scans a &quot;volume&quot; (object). You get a point cloude, with different density of different matter, for example skin/blood har different density. The you can use the point cloud to do volune rendering. &#xD;&#xA;&#xD;&#xA;So what you want to do is go make your mest Into a point cloud, with density, density depending on what matter the volume contains. Then you want to har that data for volume rendering.&#xD;&#xA;&#xD;&#xA;Then you can yourself decide how/what to render, slice through the data or whatever" ContentLicense="CC BY-SA 4.0" />
  <row Id="29685" PostHistoryTypeId="2" PostId="10239" RevisionGUID="95d7713c-1f65-4adb-82b0-aad7babeb14c" CreationDate="2020-09-18T07:52:13.190" UserId="13273" Text="A way to create the image (texture) of just a slice can be done by positioning the camera orthogonal above the slice you want to create.&#xD;&#xA;The second step is to add two clipping planes very close to each other slightly above and below the slice and render the geometry (mesh) into a Frame Buffer Object (FBO).&#xD;&#xA;From the FBO you can load the texture to CPU side and save it as PNG file.&#xD;&#xA;&#xD;&#xA;The result you'll get is the silhouette of your 3D model of the slice.&#xD;&#xA;The result is of cause not perfect, because there is a small distance between the two clipping planes... But it is an very easy way to generate it." ContentLicense="CC BY-SA 4.0" />
  <row Id="29686" PostHistoryTypeId="2" PostId="10240" RevisionGUID="fa8046f1-b2c7-4962-aa82-d052400733c6" CreationDate="2020-09-18T08:13:41.680" UserId="13273" Text="As long as no pixel on the texture is used twice, you can render the geometry and display the uv-coordinates (texture coordinates). Usually they are a combination of red and green (2d).&#xD;&#xA;When using a brush, you only need to read out the uv-coordinates you've hit and color the texture at position (uv) in the desired color.&#xD;&#xA;&#xD;&#xA;**Hint:** &#xD;&#xA;paint onto a second texture, so you'll not destroy the original texture color.&#xD;&#xA;&#xD;&#xA;**Drawbacks:**&#xD;&#xA;Sometimes the texture resolution of different triangles within a geometry vary. So at some faces it will look nice, and on others it will be pixelated.&#xD;&#xA;&#xD;&#xA;As said before, if the mesh (geometry) uses the same part of a texture twice (two faces aiming at the same texture coordinates), and you draw on one of them, the other will be painted as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="29687" PostHistoryTypeId="2" PostId="10241" RevisionGUID="4b2ecb71-ce59-4e0c-b7a2-61fdd720d554" CreationDate="2020-09-18T08:18:03.573" UserId="13095" Text="I can't give you a &quot;better&quot; approach here, but I think that the approach to&#xD;&#xA;&#xD;&#xA;&gt; project each individual brush image onto the surface of the object&#xD;&#xA;&#xD;&#xA;is not really a performance issue if you implement that using the GPU. Especially in an editor environment, where not much is going on in comparison to a computer game. All you basically want to do is to render a single image per frame onto a limited set of textures. I can give you a draft of how I would approach the subject if I needed this feature. However, since I haven't implemented it myself yet, there might be some complications and problems I haven't thought of so let me know in the comments if something doesn't work as expected.&#xD;&#xA;&#xD;&#xA;1. Find the affected surfaces&#xD;&#xA;    - Use the corners of your brush texture and generate a reduced brush projection frustum&#xD;&#xA;    - Check all objects against it and find the closest surfaces -&gt; If you already use some kind of culling for your scene, reuse the already culled object list, since the brush can only &quot;see&quot; what the camera sees&#xD;&#xA;    - Identify the subsurfaces/triangles affected by the brush&#xD;&#xA;2. Gather all affected textures. You should know for each surface that is affected, which texture it possesses. Optimally, your whole object has just a single UV texture.&#xD;&#xA;&#xD;&#xA;3. Create a shader program to render to your texture.&#xD;&#xA;    - be careful, the vertex shader has to calculate the normalized UV coordinates and pass them down the pipeline as the vertex position, since they are the position in your texture. Check what additional information you need to pass down the pipeline.&#xD;&#xA;    - In the fragment shader, overwrite each pixel that is under the brush. You might need to use blending here for non-rectangular brushes.&#xD;&#xA;    - The brush position is a little bit tricky. You need it in the textures UV space in the fragment shader and I am not sure if you can calculate it in the vertex shader. So you might need to do that in the fragment shader or alternatively in a geometry shader. The problem I see is that the angle in which the brush projection hits the surface can't be calculated in the vertex shader and it is necessary to determine the covered area. The geometry shader has enough information to calculate the angle and the covered area. In the fragment shader, you can't calculate the angle either, but there you can simply check if and where it is located in the brush projection frustum.&#xD;&#xA;&#xD;&#xA;4. Now simply render to your textures.&#xD;&#xA;    - Bind your brush texture&#xD;&#xA;    - For each affected texture&#xD;&#xA;        - Bind the texture as render target&#xD;&#xA;        - Render all affected objects and let the GPU sort out which pixels need to be overwritten.&#xD;&#xA;&#xD;&#xA;5. (Optional) If you want to save your modifications, you need to read back the textures from the GPU and save it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Since the main work is done by the GPU, it should be quite fast. However, I can see some problems with the described approach when the brush hits multiple objects/textures that are partially overlapping. Sorting out which pixel of the brush affects which texture/object can get messy. There might be some stencil/depth buffer tricks one can apply, but I think this is a topic for another question. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29691" PostHistoryTypeId="12" PostId="9034" RevisionGUID="d8f20c2f-cb65-44f9-bf14-c3739f92abce" CreationDate="2020-09-18T14:35:31.767" UserId="10129" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:10129,&quot;DisplayName&quot;:&quot;DirectX_Programmer&quot;}]}" />
  <row Id="29692" PostHistoryTypeId="13" PostId="9034" RevisionGUID="c6e39dcb-473b-4664-a9d0-7d51f771a248" CreationDate="2020-09-18T14:58:25.723" UserId="10129" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:10129,&quot;DisplayName&quot;:&quot;DirectX_Programmer&quot;}]}" />
  <row Id="29696" PostHistoryTypeId="2" PostId="10242" RevisionGUID="174ee8f6-4e18-4bb1-bb68-ba189395ab7e" CreationDate="2020-09-19T12:08:24.423" UserId="10129" Text="I'm in process of creating progressive path tracer using DX12 + DXR. I managed to create working raytracing code + pathtracing code with multiple bounces but I'm experiencing problems stated below (after full RT code):&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGen()&#xD;&#xA;    {&#xD;&#xA;    	// Accumulate for limited amount of frames&#xD;&#xA;    	if (g_giCB.maxFrames &gt; 0 &amp;&amp; g_giCB.accFrames &gt;= g_giCB.maxFrames)&#xD;&#xA;    	{&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	uint2 LaunchIndex = DispatchRaysIndex().xy;&#xD;&#xA;    	uint2 LaunchDimensions = DispatchRaysDimensions().xy;&#xD;&#xA;    	float4 normalAndDepth = NormalTextureInput.Load(int3(LaunchIndex, 0));&#xD;&#xA;    &#xD;&#xA;    	// No geometry hit - skip pixel and use skybox data&#xD;&#xA;    	if (normalAndDepth.w == 0)&#xD;&#xA;    	{&#xD;&#xA;    		RTOutput[LaunchIndex] = albedoTexture.Load(int3(LaunchIndex, 0));&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	// Calculate primary ray direction&#xD;&#xA;    	uint seed = initRand(LaunchIndex.x + LaunchIndex.y * LaunchDimensions.x, g_sceneCB.frameCount, 16);&#xD;&#xA;    	uint seed2 = 0;&#xD;&#xA;    	float2 offset = float2(0, 0);&#xD;&#xA;    	if (g_giCB.samplingType == SAMPLE_UNIFORM)&#xD;&#xA;    	{&#xD;&#xA;    		seed2 = initRand(LaunchIndex.x + LaunchIndex.y * LaunchDimensions.x, g_sceneCB.frameCount, 17);&#xD;&#xA;    		offset = HammersleyDistribution(g_giCB.accFrames, g_giCB.maxFrames, uint2(seed, seed2));&#xD;&#xA;    	}&#xD;&#xA;    	else if (g_giCB.samplingType == SAMPLE_MJ)&#xD;&#xA;    	{&#xD;&#xA;    		const uint pixelIdx = LaunchIndex.y * LaunchDimensions.x + LaunchIndex.x;&#xD;&#xA;    		uint sampleSetIdx = 0;&#xD;&#xA;    		offset = SamplePoint(pixelIdx, sampleSetIdx);&#xD;&#xA;    		seed = pixelIdx;&#xD;&#xA;    		seed2 = sampleSetIdx;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	float3 primaryRayOrigin = g_sceneCB.cameraPosition.xyz;&#xD;&#xA;    	float3 primaryRayDirection;&#xD;&#xA;    	GenerateCameraRay(LaunchIndex, LaunchDimensions, g_sceneCB.projectionToWorld, primaryRayOrigin, primaryRayDirection, offset);&#xD;&#xA;    	&#xD;&#xA;    	// Prepare payload&#xD;&#xA;    	PayloadIndirect indirectPayload;&#xD;&#xA;    	indirectPayload.color = float3(0, 0, 0);&#xD;&#xA;    	indirectPayload.rndSeed = seed;&#xD;&#xA;    	indirectPayload.rndSeed2 = seed2;&#xD;&#xA;    	indirectPayload.pathLength = 0;&#xD;&#xA;    		&#xD;&#xA;    	// Calculate pixel color in current pass and merge with previous frames&#xD;&#xA;    	float4 finalColor = float4(shootIndirectRay(primaryRayOrigin, primaryRayDirection, 1e-3f, indirectPayload), 1.0f);&#xD;&#xA;    	float4 prevScene = RTOutput[LaunchIndex];&#xD;&#xA;    	finalColor = ((float) g_giCB.accFrames * prevScene + finalColor) / ((float) g_giCB.accFrames + 1.0f);&#xD;&#xA;    	RTOutput[LaunchIndex] = finalColor;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void Miss(inout RayPayload payload : SV_RayPayload)&#xD;&#xA;    {&#xD;&#xA;    	payload.vis = 1.0f;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHit(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void MissIndirect(inout PayloadIndirect payload : SV_RayPayload)&#xD;&#xA;    {&#xD;&#xA;    	// Use skybox as contribution if ray failed to hit geometry (right now, disabled for debug purposes)&#xD;&#xA;    	float3 rayDir = WorldRayDirection();&#xD;&#xA;    	rayDir.z = -rayDir.z;&#xD;&#xA;    	if (g_giCB.useSkybox)&#xD;&#xA;    	{&#xD;&#xA;    		payload.color += skyboxTexture.SampleLevel(g_sampler, rayDir, 0).rgb;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHitIndirect(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    	// Load hit data&#xD;&#xA;    	float3 hitPos = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();&#xD;&#xA;    	float3 triangleNormal, triangleTangent, triangleBitangent;&#xD;&#xA;    	loadHitData(triangleNormal, triangleTangent, triangleBitangent, attribs);&#xD;&#xA;    &#xD;&#xA;    	// Use white albedo for all textures (DEBUG version)&#xD;&#xA;    	float4 albedo = albedoTexture.Load(int3(DispatchRaysIndex().xy, 0));&#xD;&#xA;    	albedo = float4(1, 1, 1, 1);&#xD;&#xA;    	&#xD;&#xA;    	// Iterate over all lights&#xD;&#xA;    	float lightsCount = g_lightCB.lightPositionAndType[15].w;&#xD;&#xA;    	for (int i = 0; i &lt; lightsCount; i++)&#xD;&#xA;    	{&#xD;&#xA;    		// Calculate each light data&#xD;&#xA;    		float3 lightColor = g_lightCB.lightDiffuseColor[i].rgb;&#xD;&#xA;    		float3 toLight = g_lightCB.lightPositionAndType[i].xyz - hitPos;&#xD;&#xA;    		float distToLight = length(toLight);&#xD;&#xA;    		toLight = normalize(toLight);&#xD;&#xA;    		&#xD;&#xA;    		// Check visibility&#xD;&#xA;    		float NoL = saturate(dot(triangleNormal.xyz, toLight));&#xD;&#xA;    		float visibility = shadowRayVisibility(hitPos, toLight, 1e-3f, distToLight);&#xD;&#xA;    &#xD;&#xA;    		// Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;    		payload.color += visibility * NoL * albedo.rgb * INV_PI;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	if (g_giCB.useIndirect == 1)&#xD;&#xA;    	{&#xD;&#xA;    		// Continue spawning rays if path left has not reached maximum&#xD;&#xA;    		if (payload.pathLength &lt; g_giCB.bounceCount)&#xD;&#xA;    		{&#xD;&#xA;    			// Find next direction&#xD;&#xA;    			float3 rayDirWS = float3(0, 0, 0);&#xD;&#xA;    			if (g_giCB.samplingType == SAMPLE_UNIFORM)&#xD;&#xA;    			{&#xD;&#xA;    				float3x3 tangentToWorld = float3x3(triangleTangent, triangleBitangent, triangleNormal);&#xD;&#xA;    				float2 hammersley = HammersleyDistribution(payload.pathLength, g_giCB.bounceCount, uint2(payload.rndSeed, payload.rndSeed2));&#xD;&#xA;    				float3 rayDirTS = UniformSampleHemisphere(hammersley.x, hammersley.y);&#xD;&#xA;    				rayDirWS = normalize(mul(rayDirTS, tangentToWorld));&#xD;&#xA;    			}&#xD;&#xA;    			else if (g_giCB.samplingType == SAMPLE_MJ)&#xD;&#xA;    			{&#xD;&#xA;    				float3x3 tangentToWorld = float3x3(triangleTangent, triangleBitangent, triangleNormal);&#xD;&#xA;    				float2 brdfSample = SamplePoint(payload.rndSeed, payload.rndSeed2);&#xD;&#xA;    				float3 rayDirTS = SampleDirectionCosineHemisphere(brdfSample.x, brdfSample.y);&#xD;&#xA;    				rayDirWS = normalize(mul(rayDirTS, tangentToWorld));&#xD;&#xA;    			}&#xD;&#xA;    			else if (g_giCB.samplingType == SAMPLE_RANDOM)&#xD;&#xA;    			{&#xD;&#xA;    				rayDirWS = getCosHemisphereSample(payload.rndSeed, triangleNormal, triangleTangent, triangleBitangent);&#xD;&#xA;    				nextRand(payload.rndSeed);&#xD;&#xA;    			}&#xD;&#xA;    			&#xD;&#xA;    			// Prepare payload&#xD;&#xA;    			PayloadIndirect newPayload;&#xD;&#xA;    			newPayload.pathLength = payload.pathLength + 1;&#xD;&#xA;    			newPayload.rndSeed = payload.rndSeed;&#xD;&#xA;    			newPayload.rndSeed2 = payload.rndSeed2;&#xD;&#xA;    			newPayload.color = float3(0, 0, 0);&#xD;&#xA;    			&#xD;&#xA;    			// Calculate next ray bounce color contribution&#xD;&#xA;    			float3 bounceColor = shootIndirectRay(hitPos, rayDirWS, 1e-3f, newPayload);&#xD;&#xA;    			payload.color += bounceColor * albedo.rgb;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**1. Image doesn't converge to ground truth over time**&#xD;&#xA;&#xD;&#xA;I am using only Lambertian BRDF term in my code, while implementing multi sampling schemes (Multi-Jittered sampling, Uniform sampling and random direction sampling). All of them provides similar results, hardly possible to distinguish. Here is an image generated with almost 5000 frames. It doesn't differ from image generated with about 100 frames. I am using albedo = (1,1,1) for all textures, for debug purposes in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It looks even much more noisy when source of light is outside the window and the you can can never access light directly except primary ray (situation similar to described here - http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing.html ). Therefore I placed point light in the middle of room for simpler example.&#xD;&#xA;&#xD;&#xA;I'm not suspecting my equation to be incorrect, because:&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Monte Carlo equation above will be simplified, because I have single light with intensity = 1.0, so $L_i$ term will be terminated. BRDF for Lambertian diffuse is equal to NdotL (I'll be using notation $NoL$). PDF for sampling cosine hemisphere is $NoL / \pi$. Let's simplify equation for now:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ \cos \theta }{\pi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which is basically:&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ NoL }{\pi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And translates to code as:&#xD;&#xA;&#xD;&#xA;    color = NoL * INV_PI;&#xD;&#xA;&#xD;&#xA;However, we need to check if light $L$ that we're referring to is visible, therefore full equation, which could be seen in code is:&#xD;&#xA;&#xD;&#xA;    // Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;	payload.color += visibility * NoL * albedo.rgb * INV_PI;&#xD;&#xA;&#xD;&#xA;Regarding sampling, I've tried multiple method, especially I was hopeful about Multi-Jittered sampling [\[Kensler2013\]][2]. I am using native implementation, copied from [MJP's Path Tracer][3].&#xD;&#xA;&#xD;&#xA;**2. Oversaturation of albedo textures**&#xD;&#xA;&#xD;&#xA;[![Primary ray + single bounce image with albedo textures][4]][4]&#xD;&#xA;*Primary ray + single bounce image with albedo textures*&#xD;&#xA;&#xD;&#xA;[![Primary ray + 4 ray bounces image; Notice oversaturation of albedo textures][5]][5]&#xD;&#xA;*Primary ray + 4 ray bounces image; Notice oversaturation of albedo textures*&#xD;&#xA;&#xD;&#xA;If I simplify code to the maximum, then ray bounces boils down to very few lines of code used in practice. The problem might be adding albedo too many times but I checked it for sure, and both MJP and [cwyman][6] are using same code for calculating path tracing (multiple bounces of rays).&#xD;&#xA;&#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHitIndirect(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    	float4 albedo = // ...&#xD;&#xA;    	&#xD;&#xA;    	// Use single light&#xD;&#xA;    	float3 toLight = g_lightCB.lightPositionAndType[0].xyz - hitPos;&#xD;&#xA;    	float distToLight = length(toLight);&#xD;&#xA;    	toLight = normalize(toLight);&#xD;&#xA;    		&#xD;&#xA;    	// Check visibility&#xD;&#xA;    	float NoL = saturate(dot(triangleNormal.xyz, toLight));&#xD;&#xA;    	float visibility = shadowRayVisibility(hitPos, toLight, 1e-3f, distToLight);&#xD;&#xA;    &#xD;&#xA;    	// Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;    	payload.color += visibility * NoL * albedo.rgb * INV_PI;&#xD;&#xA;    	&#xD;&#xA;    	if (g_giCB.useIndirect == 1)&#xD;&#xA;    	{&#xD;&#xA;    		// Continue spawning rays if path left has not reached maximum&#xD;&#xA;    		if (payload.pathLength &lt; g_giCB.bounceCount)&#xD;&#xA;    		{&#xD;&#xA;    			// Find next direction&#xD;&#xA;    			float3 rayDirWS = // ... multiple lighting schemes, check full code above&#xD;&#xA;    			&#xD;&#xA;    			// Prepare payload&#xD;&#xA;    			PayloadIndirect newPayload;&#xD;&#xA;    			newPayload.pathLength = payload.pathLength + 1;&#xD;&#xA;    			newPayload.rndSeed = payload.rndSeed;&#xD;&#xA;    			newPayload.rndSeed2 = payload.rndSeed2;&#xD;&#xA;    			newPayload.color = float3(0, 0, 0);&#xD;&#xA;    			&#xD;&#xA;    			// Calculate next ray bounce color contribution&#xD;&#xA;    			float3 bounceColor = shootIndirectRay(hitPos, rayDirWS, 1e-3f, newPayload);&#xD;&#xA;    			payload.color += bounceColor * albedo.rgb;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For now, I'd like to creating converging diffuse path tracer. I'll continue with Specular GGX in order to have a ground truth reference for Bidirectional Path Tracing and other methods, which can speed up converging rate of an image. Thanks in advance for all your advices.&#xD;&#xA;&#xD;&#xA;Also, for future readers - I'd recommend checking questions below, which are related to the topic, but didn't manage to solve my problems:&#xD;&#xA;&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/3972/is-it-expected-that-a-naive-path-tracer-takes-many-many-samples-to-converge&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/245/non-real-time-raytracing&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/4394/path-tracing-the-cook-torrance-brdf?rq=1&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pBCoI.jpg&#xD;&#xA;  [2]: https://graphics.pixar.com/library/MultiJitteredSampling/paper.pdf&#xD;&#xA;  [3]: https://github.com/TheRealMJP/DXRPathTracer&#xD;&#xA;  [4]: https://i.stack.imgur.com/ywhkI.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/Lm27V.jpg&#xD;&#xA;  [6]: http://cwyman.org/code/dxrTutors/tutors/Tutor14/tutorial14.md.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="29697" PostHistoryTypeId="1" PostId="10242" RevisionGUID="174ee8f6-4e18-4bb1-bb68-ba189395ab7e" CreationDate="2020-09-19T12:08:24.423" UserId="10129" Text="Path tracing - cannot converge diffuse sampling + oversaturation" ContentLicense="CC BY-SA 4.0" />
  <row Id="29698" PostHistoryTypeId="3" PostId="10242" RevisionGUID="174ee8f6-4e18-4bb1-bb68-ba189395ab7e" CreationDate="2020-09-19T12:08:24.423" UserId="10129" Text="|raytracing|pathtracing|sampling|hlsl|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29699" PostHistoryTypeId="2" PostId="10243" RevisionGUID="580981f4-a783-47c1-a426-cf662633d9e2" CreationDate="2020-09-19T12:37:45.167" UserId="13991" Text="The problem is definitely a lack of linker flags.&#xD;&#xA;&#xD;&#xA;It can see that you want to include &lt;SDL/SDL2.h&gt;, which is a sort of promise that said functions contained in that header have been built and will be available; but when your linker looks to find the actual machine code, it needs a little more than the header. It needs the *library* itself.&#xD;&#xA;&#xD;&#xA;For SDL2, you would usually use something like:&#xD;&#xA;&#xD;&#xA;    gcc -g main.c -o ../ludo -lSDL2&#xD;&#xA;&#xD;&#xA;On Linux, this is more-or-less the same command, but for complete definitions it also instructs the compiler to look inside `/usr/lib/x86_64-linux-gnu/libSDL2.a` (or wherever it is on your system). Note that the `lib` prefix on the file name is assumed, and the extension is irrelevant.&#xD;&#xA;&#xD;&#xA;Do that, and your program should compile. Note that some SDL extensions, like Image and Mixer, require their own libraries. An SDL-specific shortcut to ensure that you've got everything is to use the handy `pkg-config`, like so:&#xD;&#xA;&#xD;&#xA;    gcc -g main.c -o ../ludo $(pkg-config --cflags --libs sdl2)&#xD;&#xA;&#xD;&#xA;Which will be interpreted by the terminal as&#xD;&#xA;&#xD;&#xA;    gcc -g main.c -o ../ludo -D_REENTRANT -I/usr/include/SDL2 -lSDL2&#xD;&#xA;&#xD;&#xA;This is less generic however, a bit more paranoid, and a bit of a cheat; but perhaps it will help you.&#xD;&#xA;&#xD;&#xA;The thing to remember with C is that a function needs to be *declared* to be used in code, and that's compiler-end; but to be built into an actual stand-alone program it also has to be *defined*, which is where the post-compiler linker comes in." ContentLicense="CC BY-SA 4.0" />
  <row Id="29700" PostHistoryTypeId="2" PostId="10244" RevisionGUID="4d8050c0-edf9-41d9-b31d-167f9b12b58c" CreationDate="2020-09-19T17:56:32.500" UserId="48" Text="One point: the Lambert BRDF is not $N\cdot L$, it's just the albedo divided by pi. The $N \cdot L$ factor comes from the $\cos \theta$ in the rendering equation. So, when sampling with a cosine-weighted distribution the $N \cdot L$s and pis will cancel out and you should just be accumulating $\frac{1}{N} \sum L_i * \text{albedo}$.&#xD;&#xA;&#xD;&#xA;It looks like in your code you're doing this correctly for the cosine-weighted distribution. But then in the case of the uniform hemispherical distribution you're not putting in the needed factor of $2(N \cdot L)$. (The factor of 2 comes from dividing by the uniform hemispherical pdf of 1/2π, and canceling the 1/π in the BRDF.) So I think that your uniform sampling method does not give quite correct results here.&#xD;&#xA;&#xD;&#xA;I'm not quite sure what you meant by &quot;image doesn't converge to ground truth&quot;. Do you mean that it's still noisy even after quite a lot of samples? The problem could be in your accumulation strategy. Depending on the bit depth of your framebuffer, after some number of frames the contribution of one more frame will be so small as to be smaller than the least-significant bit of the accumulated value. If you're using 16-bit float format for instance this will happen after about 1000 frames; if using R11G11B10_FLOAT then it will take only 30-60 frames before new accumulated values will no longer have any effect. The accumulation framebuffer should be 32-bit float at a minimum.&#xD;&#xA;&#xD;&#xA;With multiple bounces, it doesn't look like you're accounting for throughput along a path correctly. You have `payload.color += bounceColor * albedo.rgb`, but note that this only takes account of the albedo at the current surface. If this is the Nth bounce, the color should be multiplied by the albedos of all previous surfaces in the path—since that's how this light is getting to the camera, by bouncing through all of them. The path payload structure needs to include not just an accumulated color, but a value typically called &quot;throughput&quot;, that contains the product of all the (BRDF * cos(theta) / pdf) factors along the path so far. On each bounce you update the throughput by multiplying in the factor for the latest bounce, then update the color by multiplying the sampled radiance with the accumulated throughput." ContentLicense="CC BY-SA 4.0" />
  <row Id="29701" PostHistoryTypeId="5" PostId="10244" RevisionGUID="4e718160-bc7e-4c75-9045-31527327c8a2" CreationDate="2020-09-19T18:14:09.510" UserId="48" Comment="added 411 characters in body" Text="One point: the Lambert BRDF is not $N\cdot L$, it's just the albedo divided by pi. The $N \cdot L$ factor comes from the $\cos \theta$ in the rendering equation. So, when sampling with a cosine-weighted distribution the $N \cdot L$s and pis will cancel out and you should just be accumulating $\frac{1}{N} \sum L_i * \text{albedo}$.&#xD;&#xA;&#xD;&#xA;It looks like in your code you're doing this correctly for the cosine-weighted distribution. But then in the case of the uniform hemispherical distribution you're not putting in the needed factor of $2(N \cdot L)$. (The factor of 2 comes from dividing by the uniform hemispherical pdf of 1/2π, and canceling the 1/π in the BRDF.) So I think that your uniform sampling method does not give quite correct results here.&#xD;&#xA;&#xD;&#xA;I'm not quite sure what you meant by &quot;image doesn't converge to ground truth&quot;. Do you mean that it's still noisy even after quite a lot of samples? The problem could be in your accumulation strategy. Depending on the bit depth of your framebuffer, after some number of frames the contribution of one more frame will be so small as to be smaller than the least-significant bit of the accumulated value. If you're using 16-bit float format for instance this will happen after about 1000 frames; if using R11G11B10_FLOAT then it will take only 30-60 frames before new accumulated values will no longer have any effect. The accumulation framebuffer should be 32-bit float at a minimum.&#xD;&#xA;&#xD;&#xA;With multiple bounces, it doesn't look like you're accounting for throughput along a path correctly. You have `payload.color += bounceColor * albedo.rgb`, but note that this only takes account of the albedo at the current surface. If this is the Nth bounce, the color should be multiplied by the albedos of all previous surfaces in the path—since that's how this light is getting to the camera, by bouncing through all of them. The path payload structure needs to include not just an accumulated color, but a value typically called &quot;throughput&quot;, that contains the product of all the (BRDF * cos(theta) / pdf) factors along the path so far. On each bounce you update the throughput by multiplying in the factor for the latest bounce, then update the color by multiplying the sampled radiance with the accumulated throughput.&#xD;&#xA;&#xD;&#xA;Also, do you have any exposure control / tonemapping on the final image? An image with multiple bounces is expected to be brighter overall than the same scene with 1 bounce, as more light is being accumulated. If you don't adjust the exposure and apply a tone curve of some sort (and gamma correction), you can end up with things looking bad/wrong on screen, even if the internal HDR framebuffer is correct." ContentLicense="CC BY-SA 4.0" />
  <row Id="29702" PostHistoryTypeId="2" PostId="10245" RevisionGUID="32fbcf0c-4d2f-4565-b6ce-0e18290939c7" CreationDate="2020-09-19T19:25:53.073" UserId="48" Text="Blend shapes, also known as morph targets, are a widely used character animation technique that helps get around the limitations of linear-blend skinning (skeletal animation). A blend shape is defined as a set of per-vertex offset vectors, usually in a localized region of a character mesh, such as a neck or upper arm. The idea is that during animation, the basic pose produced by skinning is supplemented by adding these offset vectors, scaled by an animated weight factor, prior to applying the skinning transformations. This allows character artists to model such motions as the bulging/thinning of muscles when a limb is extended or contracted, or the shifting of soft tissue around the underlying rigid skeleton, which are not captured by skinning.&#xD;&#xA;&#xD;&#xA;Blend shapes are also commonly used for facial animation, with different blend shapes representing different motions of the facial muscles, such as raising/lowering eyebrows, squinting the eyes, flaring the nostrils, moving the lips in various ways, etc. These are very difficult to model realistically using linear-blend skinning alone. By manipulating the weight factors of all these blend shapes, the animator can produce various facial expressions. A captured performance of an actor can be &quot;solved&quot; into animation curves for a predefined set of facial blend shapes, as a means of compression, or for transferring performance to a different face.&#xD;&#xA;&#xD;&#xA;In the most basic version of blend shapes, their weight factors are animated by hand. But their weights can also be driven programmatically by some other set of parameters—for example, by the pose of the skeleton. Essentially, you can say something like &quot;whenever the elbow is bent, apply the bicep-bulging blend shape&quot;, so that will happen automatically based on whatever the skeletal animation is doing, without having to animate it manually. This is broadly called &quot;pose space deformation&quot;, since the blend shapes (deformations) are associated with regions in &quot;pose space&quot;, the high-dimensional space of all the joint rotations/translations. The slide deck you posted refers to this as &quot;pose blend shapes&quot;, however the more standard term is &quot;pose space deformation&quot; (and there's plenty of literature on it).&#xD;&#xA;&#xD;&#xA;The &quot;shape blend shapes&quot; in that slide deck appear to be something specific to the pipeline they're describing, for creating a parameterized human model that can output many different body shapes and proportions. The &quot;shape&quot; parameters in the model presumably index the range of individual variation in body shape—different heights, limb lengths, hip to waist ratios, etc. They attempt to do this by starting with a single generic human mesh and applying various blend shapes (as well as moving joints around) to parameterize this space of body shapes." ContentLicense="CC BY-SA 4.0" />
  <row Id="29703" PostHistoryTypeId="52" PostId="10242" RevisionGUID="1e649225-d533-43dc-bd37-1401c57a4bd5" CreationDate="2020-09-19T22:58:42.510" />
  <row Id="29704" PostHistoryTypeId="50" PostId="8431" RevisionGUID="cc862d04-5d0a-40b7-ba61-ea334fc59ef1" CreationDate="2020-09-20T00:05:10.500" UserId="-1" />
  <row Id="29705" PostHistoryTypeId="2" PostId="10246" RevisionGUID="a4743c26-a965-479a-b82b-d737424ed1cb" CreationDate="2020-09-20T05:42:58.013" UserId="11058" Text="I'm trying to figure out this problem for very long time and am no getting nowhere. I'm working on a simple 3d modeler that uses half-edge data structure.&#xD;&#xA;&#xD;&#xA;Say I have non-manifold geometry where two triangles share a common vertex, as shown in the image below. And I want to add another triangle such that now three triangles share a common vertex. Once we add the new triangle we need to reorder the half-edges around the common vertex. In 2d this ordering is done by sorting the half-edges from the common vertex clockwise, as explained in [this](https://cs.stackexchange.com/questions/2450/how-do-i-construct-a-doubly-connected-edge-list-given-a-set-of-line-segments?newreg=1d611fc139b64175a8ba4ba0823ba6be) post.&#xD;&#xA;&#xD;&#xA;However in 3d this becomes a nightmare. If the same three triangles share the common vertex but have an arbitrary orientation in 3d space and are not coplanar. How can one possibly sort the half-edges?&#xD;&#xA;&#xD;&#xA;I experimented with using the common vertex normal to construct a plane, and project all the half-edges around the vertex to that plane. After which we could sort them clockwise relative to the plane. But this approach has a lot of issues.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pQyab.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WHSSF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29706" PostHistoryTypeId="1" PostId="10246" RevisionGUID="a4743c26-a965-479a-b82b-d737424ed1cb" CreationDate="2020-09-20T05:42:58.013" UserId="11058" Text="Sort half-edges around common vertex in 3d" ContentLicense="CC BY-SA 4.0" />
  <row Id="29707" PostHistoryTypeId="3" PostId="10246" RevisionGUID="a4743c26-a965-479a-b82b-d737424ed1cb" CreationDate="2020-09-20T05:42:58.013" UserId="11058" Text="|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29708" PostHistoryTypeId="5" PostId="10246" RevisionGUID="10d2ca38-1b7d-402d-9b4d-071c8880ff08" CreationDate="2020-09-20T05:50:02.327" UserId="11058" Comment="added 45 characters in body" Text="I'm trying to figure out this problem for very long time and am no getting nowhere. I'm working on a simple 3d modeler that uses half-edge data structure.&#xD;&#xA;&#xD;&#xA;Say I have non-manifold geometry where two triangles share a common vertex, as shown in the image below. And I want to add another triangle such that now three triangles share a common vertex. Once we add the new triangle we need to reorder the half-edges around the common vertex. In 2d this ordering is done by sorting the half-edges from the common vertex clockwise, as explained in [this](https://cs.stackexchange.com/questions/2450/how-do-i-construct-a-doubly-connected-edge-list-given-a-set-of-line-segments?newreg=1d611fc139b64175a8ba4ba0823ba6be) post.&#xD;&#xA;&#xD;&#xA;However in 3d this becomes a nightmare. If the same three triangles share the common vertex but have an arbitrary orientation in 3d space and are not coplanar. How can one possibly sort the half-edges?&#xD;&#xA;&#xD;&#xA;I experimented with using the common vertex normal to construct a plane, and project all the half-edges around the vertex to that plane. After which we could sort them clockwise relative to the plane. But I've found this approach to have a lot of issues. And now I'm all out of ideas.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pQyab.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WHSSF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29709" PostHistoryTypeId="2" PostId="10247" RevisionGUID="7574b303-981f-4194-a573-72ce302b14e1" CreationDate="2020-09-20T18:14:03.060" UserId="13456" Text="I am writting a path tracer in [cuda](https://github.com/D-K-E/cuda-raytracer.git) following the Shirley's book. I am having a square pattern as an output. &#xD;&#xA;&#xD;&#xA;The size of the block change if I change the block dimensions. For this image, the block dimensions follow the aspect ratio, basically 16 * 9 is block size. I know that without actually showing the entire code, it is difficult to debug it. I am just asking if you have any idea where I should start debugging it. My hunch is that there is a problem with my random number generator. &#xD;&#xA;Here is its code in case I am doing something wrong. Here is the host code:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;int total_pixel_size = WIDTH * HEIGHT;&#xD;&#xA;size_t frameSize = 3 * total_pixel_size;&#xD;&#xA;&#xD;&#xA;// declare random state&#xD;&#xA;int SEED = time(NULL);&#xD;&#xA;thrust::device_ptr&lt;curandState&gt; randState1 = thrust::device_malloc&lt;curandState&gt;(frameSize);&#xD;&#xA;CUDA_CONTROL(cudaGetLastError());&#xD;&#xA;&#xD;&#xA;// declare random state 2&#xD;&#xA;thrust::device_ptr&lt;curandState&gt; randState2 = thrust::device_malloc&lt;curandState&gt;(1);&#xD;&#xA;CUDA_CONTROL(cudaGetLastError());&#xD;&#xA;rand_init&lt;&lt;&lt;1, 1&gt;&gt;&gt;(thrust::raw_pointer_cast(randState2),&#xD;&#xA;                      SEED);&#xD;&#xA;CUDA_CONTROL(cudaGetLastError());&#xD;&#xA;CUDA_CONTROL(cudaDeviceSynchronize());&#xD;&#xA;&#xD;&#xA;dim3 blocks(WIDTH / BLOCK_WIDTH + 1,&#xD;&#xA;              HEIGHT / BLOCK_HEIGHT + 1);&#xD;&#xA;  dim3 threads(BLOCK_WIDTH, BLOCK_HEIGHT);&#xD;&#xA;  render_init&lt;&lt;&lt;blocks, threads&gt;&gt;&gt;(&#xD;&#xA;      WIDTH, HEIGHT, thrust::raw_pointer_cast(randState1),&#xD;&#xA;      SEED);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here is the device code:&#xD;&#xA;```c++&#xD;&#xA;&#xD;&#xA;__global__ void rand_init(curandState *randState,&#xD;&#xA;                          int seed) {&#xD;&#xA;  if (threadIdx.x == 0 &amp;&amp; blockIdx.x == 0) {&#xD;&#xA;    curand_init(seed, 0, 0, randState);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;__global__ void render_init(int mx, int my,&#xD;&#xA;                            curandState *randState,&#xD;&#xA;                            int seed) {&#xD;&#xA;  if (threadIdx.x == 0 &amp;&amp; threadIdx.y == 0) {&#xD;&#xA;    curand_init(seed, 0, 0, randState);&#xD;&#xA;  }&#xD;&#xA;  int i = threadIdx.x + blockIdx.x * blockDim.x;&#xD;&#xA;  int j = threadIdx.y + blockIdx.y * blockDim.y;&#xD;&#xA;&#xD;&#xA;  if ((i &gt;= mx) || (j &gt;= my)) {&#xD;&#xA;    return;&#xD;&#xA;  }&#xD;&#xA;  int pixel_index = j * mx + i;&#xD;&#xA;  // same seed, different index&#xD;&#xA;  curand_init(seed + pixel_index, pixel_index, 0,&#xD;&#xA;              &amp;randState[pixel_index]);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I would really appreciate any pointers to the problem.&#xD;&#xA;&#xD;&#xA;[![cornell box with two blocks][2]][2].&#xD;&#xA;&#xD;&#xA;Here is another image with different block size and dimensions but with the same problem:&#xD;&#xA;[![another image with different dimensions][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xvhxw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Y3wTY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29710" PostHistoryTypeId="1" PostId="10247" RevisionGUID="7574b303-981f-4194-a573-72ce302b14e1" CreationDate="2020-09-20T18:14:03.060" UserId="13456" Text="Why does my image has a square pattern in cuda path tracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29711" PostHistoryTypeId="3" PostId="10247" RevisionGUID="7574b303-981f-4194-a573-72ce302b14e1" CreationDate="2020-09-20T18:14:03.060" UserId="13456" Text="|raytracing|rendering|pathtracing|cuda|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29712" PostHistoryTypeId="50" PostId="9364" RevisionGUID="123441f8-70c4-4b58-9108-5cf53f8de1e2" CreationDate="2020-09-20T21:05:25.493" UserId="-1" />
  <row Id="29713" PostHistoryTypeId="50" PostId="9744" RevisionGUID="30941899-42b9-44c8-8900-4b4149ba1139" CreationDate="2020-09-20T22:04:55.463" UserId="-1" />
  <row Id="29715" PostHistoryTypeId="50" PostId="8291" RevisionGUID="cbc921fc-5136-4184-b7a9-34fcf0372b78" CreationDate="2020-09-21T03:03:05.303" UserId="-1" />
  <row Id="29716" PostHistoryTypeId="50" PostId="10137" RevisionGUID="059e0e91-6b54-46b5-a094-ad47569008bc" CreationDate="2020-09-21T08:06:30.597" UserId="-1" />
  <row Id="29717" PostHistoryTypeId="5" PostId="10242" RevisionGUID="af02ebc2-84b1-421e-8095-fcc2fb0f2489" CreationDate="2020-09-21T10:41:25.580" UserId="10129" Comment="added 1428 characters in body" Text="I'm in process of creating progressive path tracer using DX12 + DXR. I managed to create working raytracing code + pathtracing code with multiple bounces but I'm experiencing problems stated below (after full RT code):&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGen()&#xD;&#xA;    {&#xD;&#xA;    	// Accumulate for limited amount of frames&#xD;&#xA;    	if (g_giCB.maxFrames &gt; 0 &amp;&amp; g_giCB.accFrames &gt;= g_giCB.maxFrames)&#xD;&#xA;    	{&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	uint2 LaunchIndex = DispatchRaysIndex().xy;&#xD;&#xA;    	uint2 LaunchDimensions = DispatchRaysDimensions().xy;&#xD;&#xA;    	float4 normalAndDepth = NormalTextureInput.Load(int3(LaunchIndex, 0));&#xD;&#xA;    &#xD;&#xA;    	// No geometry hit - skip pixel and use skybox data&#xD;&#xA;    	if (normalAndDepth.w == 0)&#xD;&#xA;    	{&#xD;&#xA;    		RTOutput[LaunchIndex] = albedoTexture.Load(int3(LaunchIndex, 0));&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	// Calculate primary ray direction&#xD;&#xA;    	uint seed = initRand(LaunchIndex.x + LaunchIndex.y * LaunchDimensions.x, g_sceneCB.frameCount, 16);&#xD;&#xA;    	uint seed2 = 0;&#xD;&#xA;    	float2 offset = float2(0, 0);&#xD;&#xA;    	if (g_giCB.samplingType == SAMPLE_UNIFORM)&#xD;&#xA;    	{&#xD;&#xA;    		seed2 = initRand(LaunchIndex.x + LaunchIndex.y * LaunchDimensions.x, g_sceneCB.frameCount, 17);&#xD;&#xA;    		offset = HammersleyDistribution(g_giCB.accFrames, g_giCB.maxFrames, uint2(seed, seed2));&#xD;&#xA;    	}&#xD;&#xA;    	else if (g_giCB.samplingType == SAMPLE_MJ)&#xD;&#xA;    	{&#xD;&#xA;    		const uint pixelIdx = LaunchIndex.y * LaunchDimensions.x + LaunchIndex.x;&#xD;&#xA;    		uint sampleSetIdx = 0;&#xD;&#xA;    		offset = SamplePoint(pixelIdx, sampleSetIdx);&#xD;&#xA;    		seed = pixelIdx;&#xD;&#xA;    		seed2 = sampleSetIdx;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	float3 primaryRayOrigin = g_sceneCB.cameraPosition.xyz;&#xD;&#xA;    	float3 primaryRayDirection;&#xD;&#xA;    	GenerateCameraRay(LaunchIndex, LaunchDimensions, g_sceneCB.projectionToWorld, primaryRayOrigin, primaryRayDirection, offset);&#xD;&#xA;    	&#xD;&#xA;    	// Prepare payload&#xD;&#xA;    	PayloadIndirect indirectPayload;&#xD;&#xA;    	indirectPayload.color = float3(0, 0, 0);&#xD;&#xA;    	indirectPayload.rndSeed = seed;&#xD;&#xA;    	indirectPayload.rndSeed2 = seed2;&#xD;&#xA;    	indirectPayload.pathLength = 0;&#xD;&#xA;    		&#xD;&#xA;    	// Calculate pixel color in current pass and merge with previous frames&#xD;&#xA;    	float4 finalColor = float4(shootIndirectRay(primaryRayOrigin, primaryRayDirection, 1e-3f, indirectPayload), 1.0f);&#xD;&#xA;    	float4 prevScene = RTOutput[LaunchIndex];&#xD;&#xA;    	finalColor = ((float) g_giCB.accFrames * prevScene + finalColor) / ((float) g_giCB.accFrames + 1.0f);&#xD;&#xA;    	RTOutput[LaunchIndex] = finalColor;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void Miss(inout RayPayload payload : SV_RayPayload)&#xD;&#xA;    {&#xD;&#xA;    	payload.vis = 1.0f;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHit(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void MissIndirect(inout PayloadIndirect payload : SV_RayPayload)&#xD;&#xA;    {&#xD;&#xA;    	// Use skybox as contribution if ray failed to hit geometry (right now, disabled for debug purposes)&#xD;&#xA;    	float3 rayDir = WorldRayDirection();&#xD;&#xA;    	rayDir.z = -rayDir.z;&#xD;&#xA;    	if (g_giCB.useSkybox)&#xD;&#xA;    	{&#xD;&#xA;    		payload.color += skyboxTexture.SampleLevel(g_sampler, rayDir, 0).rgb;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHitIndirect(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    	// Load hit data&#xD;&#xA;    	float3 hitPos = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();&#xD;&#xA;    	float3 triangleNormal, triangleTangent, triangleBitangent;&#xD;&#xA;    	loadHitData(triangleNormal, triangleTangent, triangleBitangent, attribs);&#xD;&#xA;    &#xD;&#xA;    	// Use white albedo for all textures (DEBUG version)&#xD;&#xA;    	float4 albedo = albedoTexture.Load(int3(DispatchRaysIndex().xy, 0));&#xD;&#xA;    	albedo = float4(1, 1, 1, 1);&#xD;&#xA;    	&#xD;&#xA;    	// Iterate over all lights&#xD;&#xA;    	float lightsCount = g_lightCB.lightPositionAndType[15].w;&#xD;&#xA;    	for (int i = 0; i &lt; lightsCount; i++)&#xD;&#xA;    	{&#xD;&#xA;    		// Calculate each light data&#xD;&#xA;    		float3 lightColor = g_lightCB.lightDiffuseColor[i].rgb;&#xD;&#xA;    		float3 toLight = g_lightCB.lightPositionAndType[i].xyz - hitPos;&#xD;&#xA;    		float distToLight = length(toLight);&#xD;&#xA;    		toLight = normalize(toLight);&#xD;&#xA;    		&#xD;&#xA;    		// Check visibility&#xD;&#xA;    		float NoL = saturate(dot(triangleNormal.xyz, toLight));&#xD;&#xA;    		float visibility = shadowRayVisibility(hitPos, toLight, 1e-3f, distToLight);&#xD;&#xA;    &#xD;&#xA;    		// Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;    		payload.color += visibility * NoL * albedo.rgb * INV_PI;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	if (g_giCB.useIndirect == 1)&#xD;&#xA;    	{&#xD;&#xA;    		// Continue spawning rays if path left has not reached maximum&#xD;&#xA;    		if (payload.pathLength &lt; g_giCB.bounceCount)&#xD;&#xA;    		{&#xD;&#xA;    			// Find next direction&#xD;&#xA;    			float3 rayDirWS = float3(0, 0, 0);&#xD;&#xA;    			if (g_giCB.samplingType == SAMPLE_UNIFORM)&#xD;&#xA;    			{&#xD;&#xA;    				float3x3 tangentToWorld = float3x3(triangleTangent, triangleBitangent, triangleNormal);&#xD;&#xA;    				float2 hammersley = HammersleyDistribution(payload.pathLength, g_giCB.bounceCount, uint2(payload.rndSeed, payload.rndSeed2));&#xD;&#xA;    				float3 rayDirTS = UniformSampleHemisphere(hammersley.x, hammersley.y);&#xD;&#xA;    				rayDirWS = normalize(mul(rayDirTS, tangentToWorld));&#xD;&#xA;    			}&#xD;&#xA;    			else if (g_giCB.samplingType == SAMPLE_MJ)&#xD;&#xA;    			{&#xD;&#xA;    				float3x3 tangentToWorld = float3x3(triangleTangent, triangleBitangent, triangleNormal);&#xD;&#xA;    				float2 brdfSample = SamplePoint(payload.rndSeed, payload.rndSeed2);&#xD;&#xA;    				float3 rayDirTS = SampleDirectionCosineHemisphere(brdfSample.x, brdfSample.y);&#xD;&#xA;    				rayDirWS = normalize(mul(rayDirTS, tangentToWorld));&#xD;&#xA;    			}&#xD;&#xA;    			else if (g_giCB.samplingType == SAMPLE_RANDOM)&#xD;&#xA;    			{&#xD;&#xA;    				rayDirWS = getCosHemisphereSample(payload.rndSeed, triangleNormal, triangleTangent, triangleBitangent);&#xD;&#xA;    				nextRand(payload.rndSeed);&#xD;&#xA;    			}&#xD;&#xA;    			&#xD;&#xA;    			// Prepare payload&#xD;&#xA;    			PayloadIndirect newPayload;&#xD;&#xA;    			newPayload.pathLength = payload.pathLength + 1;&#xD;&#xA;    			newPayload.rndSeed = payload.rndSeed;&#xD;&#xA;    			newPayload.rndSeed2 = payload.rndSeed2;&#xD;&#xA;    			newPayload.color = float3(0, 0, 0);&#xD;&#xA;    			&#xD;&#xA;    			// Calculate next ray bounce color contribution&#xD;&#xA;    			float3 bounceColor = shootIndirectRay(hitPos, rayDirWS, 1e-3f, newPayload);&#xD;&#xA;    			payload.color += bounceColor * albedo.rgb;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**1. Image doesn't converge to ground truth over time**&#xD;&#xA;&#xD;&#xA;I am using only Lambertian BRDF term in my code, while implementing multi sampling schemes (Multi-Jittered sampling, Uniform sampling and random direction sampling). All of them provides similar results, hardly possible to distinguish. Here is an image generated with almost 5000 frames. It doesn't differ from image generated with about 100 frames. I am using albedo = (1,1,1) for all textures, for debug purposes in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It looks even much more noisy when source of light is outside the window and the you can can never access light directly except primary ray (situation similar to described here - http://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing.html ). Therefore I placed point light in the middle of room for simpler example.&#xD;&#xA;&#xD;&#xA;I'm not suspecting my equation to be incorrect, because:&#xD;&#xA;$$&#xD;&#xA;L_o(\textbf{p}, \mathbf{w_o}) = L_e + \int_{\Omega} L_i(\textbf{p}, \mathbf{w_i}) fr(\mathbf{w_o}, \mathbf{w_i}) \cos \theta d\omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ L_i(\textbf{p}, \mathbf{w_k}) fr(\mathbf{w_k}, w_o) \cos \theta }{p(\mathbf{w_k})}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Monte Carlo equation above will be simplified, because I have single light with intensity = 1.0, so $L_i$ term will be terminated. BRDF for Lambertian diffuse is equal to NdotL (I'll be using notation $NoL$). PDF for sampling cosine hemisphere is $NoL / \pi$. Let's simplify equation for now:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ \cos \theta }{\pi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Which is basically:&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N} \sum_{k=1}^{N} \frac{ NoL }{\pi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And translates to code as:&#xD;&#xA;&#xD;&#xA;    color = NoL * INV_PI;&#xD;&#xA;&#xD;&#xA;However, we need to check if light $L$ that we're referring to is visible, therefore full equation, which could be seen in code is:&#xD;&#xA;&#xD;&#xA;    // Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;	payload.color += visibility * NoL * albedo.rgb * INV_PI;&#xD;&#xA;&#xD;&#xA;Regarding sampling, I've tried multiple method, especially I was hopeful about Multi-Jittered sampling [\[Kensler2013\]][2]. I am using native implementation, copied from [MJP's Path Tracer][3].&#xD;&#xA;&#xD;&#xA;**2. Oversaturation of albedo textures**&#xD;&#xA;&#xD;&#xA;[![Primary ray + single bounce image with albedo textures][4]][4]&#xD;&#xA;*Primary ray + single bounce image with albedo textures*&#xD;&#xA;&#xD;&#xA;[![Primary ray + 4 ray bounces image; Notice oversaturation of albedo textures][5]][5]&#xD;&#xA;*Primary ray + 4 ray bounces image; Notice oversaturation of albedo textures*&#xD;&#xA;&#xD;&#xA;If I simplify code to the maximum, then ray bounces boils down to very few lines of code used in practice. The problem might be adding albedo too many times but I checked it for sure, and both MJP and [cwyman][6] are using same code for calculating path tracing (multiple bounces of rays).&#xD;&#xA;&#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHitIndirect(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    	float4 albedo = // ...&#xD;&#xA;    	&#xD;&#xA;    	// Use single light&#xD;&#xA;    	float3 toLight = g_lightCB.lightPositionAndType[0].xyz - hitPos;&#xD;&#xA;    	float distToLight = length(toLight);&#xD;&#xA;    	toLight = normalize(toLight);&#xD;&#xA;    		&#xD;&#xA;    	// Check visibility&#xD;&#xA;    	float NoL = saturate(dot(triangleNormal.xyz, toLight));&#xD;&#xA;    	float visibility = shadowRayVisibility(hitPos, toLight, 1e-3f, distToLight);&#xD;&#xA;    &#xD;&#xA;    	// Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;    	payload.color += visibility * NoL * albedo.rgb * INV_PI;&#xD;&#xA;    	&#xD;&#xA;    	if (g_giCB.useIndirect == 1)&#xD;&#xA;    	{&#xD;&#xA;    		// Continue spawning rays if path left has not reached maximum&#xD;&#xA;    		if (payload.pathLength &lt; g_giCB.bounceCount)&#xD;&#xA;    		{&#xD;&#xA;    			// Find next direction&#xD;&#xA;    			float3 rayDirWS = // ... multiple lighting schemes, check full code above&#xD;&#xA;    			&#xD;&#xA;    			// Prepare payload&#xD;&#xA;    			PayloadIndirect newPayload;&#xD;&#xA;    			newPayload.pathLength = payload.pathLength + 1;&#xD;&#xA;    			newPayload.rndSeed = payload.rndSeed;&#xD;&#xA;    			newPayload.rndSeed2 = payload.rndSeed2;&#xD;&#xA;    			newPayload.color = float3(0, 0, 0);&#xD;&#xA;    			&#xD;&#xA;    			// Calculate next ray bounce color contribution&#xD;&#xA;    			float3 bounceColor = shootIndirectRay(hitPos, rayDirWS, 1e-3f, newPayload);&#xD;&#xA;    			payload.color += bounceColor * albedo.rgb;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For now, I'd like to creating converging diffuse path tracer. I'll continue with Specular GGX in order to have a ground truth reference for Bidirectional Path Tracing and other methods, which can speed up converging rate of an image. Thanks in advance for all your advices.&#xD;&#xA;&#xD;&#xA;Also, for future readers - I'd recommend checking questions below, which are related to the topic, but didn't manage to solve my problems:&#xD;&#xA;&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/3972/is-it-expected-that-a-naive-path-tracer-takes-many-many-samples-to-converge&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/245/non-real-time-raytracing&#xD;&#xA; - https://computergraphics.stackexchange.com/questions/4394/path-tracing-the-cook-torrance-brdf?rq=1&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;**Edit after [Nathan's Reed][7] answer:**&#xD;&#xA;&#xD;&#xA;The oversaturated image looks better now. It looks a bit dull after moving from linear to sRGB space (following Nathan's order of exposure -&gt; tone mapping -&gt; linear_To_sRGB):&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;*Primary ray + 4 ray bounces image; No skybox miss shader applied to fair comparison to oversaturated image before*&#xD;&#xA;&#xD;&#xA;However, I checked case with light source from the outside and I really like the result. There is a room for improvement, for sure, like adding some AA, moving to PBR (GGX). I doubt I'll have a time for that, but using BDPT and implementing soft shadows would definatelly improve case shown below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;**To sum up for future reference:** adding tone mapper (on top of existing exposure settings) and moving from linear to sRGB space helped with oversaturation. Using R16G16B16A16_FLOAT instead of R8B8G8A8_UNORM format for backbuffer and target output textures, solved problem with not converging images. In the future, R32G32B32A32_FLOAT might be used, but with my current DX12 setup, this format causes errors when used in backbuffer and I cannot change that for now. 4x16 format proved to be enough for now, so I'll stay with that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pBCoI.jpg&#xD;&#xA;  [2]: https://graphics.pixar.com/library/MultiJitteredSampling/paper.pdf&#xD;&#xA;  [3]: https://github.com/TheRealMJP/DXRPathTracer&#xD;&#xA;  [4]: https://i.stack.imgur.com/ywhkI.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/Lm27V.jpg&#xD;&#xA;  [6]: http://cwyman.org/code/dxrTutors/tutors/Tutor14/tutorial14.md.html&#xD;&#xA;  [7]: https://computergraphics.stackexchange.com/users/48/nathan-reed&#xD;&#xA;  [8]: https://i.stack.imgur.com/LdCy3.jpg&#xD;&#xA;  [9]: https://i.stack.imgur.com/MoQEu.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29718" PostHistoryTypeId="2" PostId="10248" RevisionGUID="7b015883-09b4-449a-8ee1-b72ca94d0abf" CreationDate="2020-09-21T22:30:39.627" UserId="14000" Text="I want to motion track a shot from my Sony HDR-HC7e camcorder and I am not quite sure about the horizontal sensor size(width).&#xD;&#xA;I set the focal length to minimum and the recording to HDV 16:9&#xD;&#xA;&#xD;&#xA;[This][1] manual(HC7e and HC7 are basically the same) states it is a 1/2.9&quot; sensor with a diagonal of 6.3mm (page 101). But if I do my calculations and multiply (1/2.9) with 25.4 to convert it to mm I get 8.75862069?&#xD;&#xA;&#xD;&#xA;The camcorder outputs a 1440*1080 interlaced .m2t file. The image in this file is squeezed by a factor of 1.33. as seen in this [example][2].&#xD;&#xA;So I suppose that the sensor has an aspect ratio of 4/3(1.33) So I did some math: (a^2 = b^2 +c2^2)&#xD;&#xA;a1 = 6.3&#xD;&#xA;a2 = 8.75862069&#xD;&#xA;b = x&#xD;&#xA;c = 1.33x&#xD;&#xA;&#xD;&#xA;6.3^2 = x^2 + (1.33x)^2&#xD;&#xA;x = 3.78605&#xD;&#xA;1.33x = 5.0354465&#xD;&#xA;horizontal1 = 5.0354465&#xD;&#xA;&#xD;&#xA;8.75862069^2 = x^2 + (1.33x)^2&#xD;&#xA;x = 5.26359&#xD;&#xA;1.33x = 7.0005747&#xD;&#xA;horizontal2 = 7.0005747&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I thoguth because ther alwaysy is a relation between sensorsize and focal length, I just take the sensorsize horizontal 35mm and the coresponding 35mm focal length equvilant of 49mm (manual page 101) and get the ration : 35 / 49 = 0.714285714 then multiply the true focal length of 5.4mm by that and get a horizontal sensor size of: 3.857142856&#xD;&#xA;&#xD;&#xA;So now I have got 3 posible horizontal sensor sizes. Now I want to calibrate my lense with a set of images like the linked one. Should I leave them with the 1.33 aspect ration and where would I spezify that in the OpenCV camera calibration or do I unsqueze them and then calibrate? And do I even need the sensor size and focal length for OpenCV camera calibration?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.sony.com/electronics/support/res/manuals/2319/23198061M.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/x2AvN.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29719" PostHistoryTypeId="1" PostId="10248" RevisionGUID="7b015883-09b4-449a-8ee1-b72ca94d0abf" CreationDate="2020-09-21T22:30:39.627" UserId="14000" Text="Sensorsize of Sony HDR-HC7e" ContentLicense="CC BY-SA 4.0" />
  <row Id="29720" PostHistoryTypeId="3" PostId="10248" RevisionGUID="7b015883-09b4-449a-8ee1-b72ca94d0abf" CreationDate="2020-09-21T22:30:39.627" UserId="14000" Text="|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29721" PostHistoryTypeId="2" PostId="10249" RevisionGUID="be14bb06-4c2f-4170-9ca1-ff674176c877" CreationDate="2020-09-22T04:23:06.220" UserId="11058" Text="I was looking into the ear-clipping algorithm for triangulating simple polygons. I have successfully implemented it on planar polygons. However if polygon is non-planar the algorithm breaks down. Specifically one step of the algorithm is to test if there're any polygon vertices inside each ear. However point triangle test only makes sense if the point lies in the same plane as the triangle.&#xD;&#xA;&#xD;&#xA;So does ear-clipping algorithm not work for non-planar polygons? If so what algorithm could I use instead? I need it to support simple polygons with potentially holes inside them." ContentLicense="CC BY-SA 4.0" />
  <row Id="29722" PostHistoryTypeId="1" PostId="10249" RevisionGUID="be14bb06-4c2f-4170-9ca1-ff674176c877" CreationDate="2020-09-22T04:23:06.220" UserId="11058" Text="Ear-clipping algorithm for non-planar polygons" ContentLicense="CC BY-SA 4.0" />
  <row Id="29723" PostHistoryTypeId="3" PostId="10249" RevisionGUID="be14bb06-4c2f-4170-9ca1-ff674176c877" CreationDate="2020-09-22T04:23:06.220" UserId="11058" Text="|computational-geometry|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29724" PostHistoryTypeId="5" PostId="10248" RevisionGUID="b23cedc9-1cf7-4ee7-8715-4cc3ce4ba34b" CreationDate="2020-09-22T07:30:28.837" UserId="13095" Comment="Correct grammar/spelling, apply matjax formatting and change tag; edited tags" Text="I want to motion track a shot from my Sony HDR-HC7e camcorder and I am not quite sure about the horizontal sensor size(width).&#xD;&#xA;I set the focal length to minimum and the recording to HDV 16:9&#xD;&#xA;&#xD;&#xA;[This][1] manual (HC7e and HC7 are basically the same) states it is a 1/2.9&quot; sensor with a diagonal of 6.3mm (page 101). But if I do my calculations and multiply (1/2.9) with 25.4 to convert it to mm I get 8.75862069?&#xD;&#xA;&#xD;&#xA;The camcorder outputs a 1440*1080 interlaced .m2t file. The image in this file is squeezed by a factor of 1.33. as seen in this [example][2].&#xD;&#xA;So I suppose that the sensor has an aspect ratio of 4/3(1.33) So I did some math:&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA; &#xD;&#xA;$$a^2 = b^2 +c^2$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;a_1 &amp;=&amp; 6.3\\&#xD;&#xA;a_2 &amp;=&amp; 8.75862069\\&#xD;&#xA;b &amp;=&amp; x\\&#xD;&#xA;c &amp;=&amp; 1.33x\\&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA; &#xD;&#xA;$$6.3^2 = x^2 + (1.33x)^2$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;x &amp;=&amp; 3.78605\\&#xD;&#xA;1.33x &amp;=&amp; 5.0354465\\&#xD;&#xA;\textrm{horizontal 1} &amp;=&amp; 5.0354465&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA; &#xD;&#xA;$$8.75862069^2 = x^2 + (1.33x)^2$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;x &amp;=&amp; 5.26359\\&#xD;&#xA;1.33x &amp;=&amp; 7.0005747\\&#xD;&#xA;\textrm{horizontal 2} &amp;=&amp; 7.0005747\\&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So I thought because there always is a relation between sensor size and focal length, I just take the sensor size horizontal 35mm and the corresponding 35mm focal length equivalent of 49mm (manual page 101) and get the ration: 35 / 49 = 0.714285714 then multiply the true focal length of 5.4mm by that and get a horizontal sensor size of 3.857142856&#xD;&#xA;&#xD;&#xA;So now I have got 3 possible horizontal sensor sizes. Now I want to calibrate my lens with a set of images like the linked one. Should I leave them with the 1.33 aspect ratio and where would I specify that in the OpenCV camera calibration or do I unsqueze them and then calibrate? And do I even need the sensor size and focal length for OpenCV camera calibration?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.sony.com/electronics/support/res/manuals/2319/23198061M.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/x2AvN.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29725" PostHistoryTypeId="4" PostId="10248" RevisionGUID="b23cedc9-1cf7-4ee7-8715-4cc3ce4ba34b" CreationDate="2020-09-22T07:30:28.837" UserId="13095" Comment="Correct grammar/spelling, apply matjax formatting and change tag; edited tags" Text="Sensor size of Sony HDR-HC7e" ContentLicense="CC BY-SA 4.0" />
  <row Id="29726" PostHistoryTypeId="6" PostId="10248" RevisionGUID="b23cedc9-1cf7-4ee7-8715-4cc3ce4ba34b" CreationDate="2020-09-22T07:30:28.837" UserId="13095" Comment="Correct grammar/spelling, apply matjax formatting and change tag; edited tags" Text="|camera|opencv|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29727" PostHistoryTypeId="5" PostId="173" RevisionGUID="cbee55e1-5894-4da5-94d6-10c1786ec08b" CreationDate="2020-09-22T07:57:17.580" UserId="13095" Comment="Copy tag wiki from Stack Overflow with some minor tweaks" Text="**OpenGL** (Open Graphics Library) is an API used to interact with GPUs (Graphics Processing Units). Originally developed by [SGI (Silicon Graphics Inc.)][1] in the early '90s, the current API is being developed by the [Khronos Group][2].&#xD;&#xA;&#xD;&#xA;OpenGL is platform-independent and available for desktop, workstation and mobile devices. It is designed to provide hardware-accelerated rendering and is typically used for applications such as CAD software and computer games.&#xD;&#xA;&#xD;&#xA;The [tag:opengl] tag should only be used for questions about desktop OpenGL. OpenGL ES (OpenGL for Embedded Systems) and WebGL have their own tags - [tag:opengl-es] and [tag:webgl]. &#xD;&#xA;### Official Documentation&#xD;&#xA;&#xD;&#xA;+ The Red Book - Tutorial GL&#xD;&#xA;+ The Orange Book - Tutorial for GLSL&#xD;&#xA;+ The Green Book - Tutorial for GLX&#xD;&#xA;+ The Blue Book - API references for GL (out of print; replaced by [online reference pages][3])&#xD;&#xA;+ The White Book - Tutorial for WGL&#xD;&#xA;&#xD;&#xA;### Successor&#xD;&#xA;Khronos Group announced [tag:Vulkan] API at GDC (Game Developers Conference) 2015. Vulkan, previously known as glNext or the &quot;Next Generation OpenGL Initiative&quot;, is widely thought of as the successor to OpenGL and shares many similarities to the [tag:mantle] API. It is a complete redesign aimed to unify the OpenGL and OpenGL-ES API's into one common API that will not be backward compatible. &#xD;&#xA;&#xD;&#xA;### External resources&#xD;&#xA;&#xD;&#xA; - [OpenGL.org][4], the home of OpenGL.&#xD;&#xA; - [The OpenGL Registry][5] is the source for OpenGL headers and specifications.&#xD;&#xA; - [The OpenGL Wiki][6], a wiki that contains OpenGL tutorials and documentation.&#xD;&#xA; - [The Khronos group][2], the consortium that controls the OpenGL standard.&#xD;&#xA; - [OpenGL Wikipedia Article][7]&#xD;&#xA; - [The Vulkan API (OpenGL successor)][8]&#xD;&#xA;&#xD;&#xA;### Unofficial Tutorials&#xD;&#xA;&#xD;&#xA;* [Learning Modern 3D Graphics Programming](https://alfonse.bitbucket.io/oldtut/)&#xD;&#xA;* [Learn OpenGL](http://learnopengl.com/)&#xD;&#xA;* [ogldev modern OpenGL tutorial](http://ogldev.atspace.co.uk/)&#xD;&#xA;* Overv's [OpenGL guide](http://open.gl/)&#xD;&#xA;* Joe Groff's [Intro to modern OpenGL](http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html)&#xD;&#xA;* [Yet another modern OpenGL tutorial](http://openglbook.com/)&#xD;&#xA;* [Lighthouse3D GLSL core tutorial](http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/)&#xD;&#xA;&#xD;&#xA;### Books&#xD;&#xA;&#xD;&#xA;* [OpenGL Programming Guide: The Official Guide to Learning OpenGL, Version 4.3 (8th Edition)](https://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321773039)&#xD;&#xA;&#xD;&#xA;* [OpenGL Shading Language (3rd Edition)](https://www.amazon.com/OpenGL-Shading-Language-Randi-Rost/dp/0321637631)&#xD;&#xA;&#xD;&#xA;* [OpenGL Superbible: Comprehensive Tutorial and Reference (7th Edition)](http://www.openglsuperbible.com/)&#xD;&#xA;&#xD;&#xA;* [OpenGL Data Visualization Cookbook](https://www.packtpub.com/application-development/opengl-data-visualization-cookbook)&#xD;&#xA;&#xD;&#xA;* [Computer Graphics Through OpenGL: From Theory to Experiments, Second Edition](https://www.crcpress.com/Computer-Graphics-Through-OpenGL-From-Theory-to-Experiments-Second-Edition/Guha/p/book/9781482258394)&#xD;&#xA;&#xD;&#xA;* [OpenGL Development Cookbook](https://www.packtpub.com/game-development/opengl-development-cookbook)&#xD;&#xA;&#xD;&#xA;* [OpenGL Graphics Through Applications](https://www.amazon.com/OpenGL-Graphics-Through-Applications-Whitrow/dp/1848000227)&#xD;&#xA;&#xD;&#xA;* [Computer Graphics with Open GL (4th Edition) ](https://www.amazon.com/Computer-Graphics-Open-GL-4th/dp/0136053580)&#xD;&#xA;&#xD;&#xA;* [Beginning OpenGL Game Programming, Second Edition](https://www.amazon.com/Beginning-OpenGL-Game-Programming-Second/dp/159863528X)&#xD;&#xA;&#xD;&#xA;### Release Dates&#xD;&#xA;&#xD;&#xA; + OpenGL 1.0 - January 1992&#xD;&#xA; + OpenGL 1.1 - January 1997&#xD;&#xA; + OpenGL 1.2.1 - October 1998&#xD;&#xA; + OpenGL 1.3 - August 2001&#xD;&#xA; + OpenGL 1.4 - July 2002&#xD;&#xA; + OpenGL 1.5 - July 2003&#xD;&#xA; + OpenGL 2.0 - September 2004&#xD;&#xA; + OpenGL 2.1 - July 2006&#xD;&#xA; + OpenGL 3.0 - August 2008&#xD;&#xA; + OpenGL 3.1 - March 2009&#xD;&#xA; + OpenGL 3.2 - August 2009&#xD;&#xA; + OpenGL 3.3 - March 2010&#xD;&#xA; + OpenGL 4.0 - March 2010&#xD;&#xA; + OpenGL 4.1 - July 2010&#xD;&#xA; + OpenGL 4.2 - August 2011&#xD;&#xA; + OpenGL 4.3 - August 2012&#xD;&#xA; + OpenGL 4.4 - July 2013&#xD;&#xA; + OpenGL 4.5 - August 2014&#xD;&#xA; + OpenGL 4.6 - July 31, 2017&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.sgi.com/&#xD;&#xA;  [2]: http://www.khronos.org/&#xD;&#xA;  [3]: http://www.opengl.org/sdk/docs/man/&#xD;&#xA;  [4]: http://www.opengl.org/&#xD;&#xA;  [5]: http://www.opengl.org/registry&#xD;&#xA;  [6]: http://www.opengl.org/wiki/Main_Page&#xD;&#xA;  [7]: http://en.wikipedia.org/wiki/OpenGL&#xD;&#xA;  [8]: https://www.khronos.org/vulkan/&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29728" PostHistoryTypeId="5" PostId="174" RevisionGUID="b08f2e00-3633-4171-a0a0-4acc7e7663ec" CreationDate="2020-09-22T07:57:17.580" UserId="13095" Comment="Copy tag wiki from Stack Overflow with some minor tweaks" Text="OpenGL (Open Graphics Library) is a graphics standard and API which is platform-independent and available for desktop, workstation and mobile devices. It is designed to provide hardware-accelerated rendering, and hence gives greatly improved performance over traditional software rendering.&#xD;&#xA;OpenGL is used for applications like CAD software and computer games. The OpenGL standard, as well as OpenGL ES, is controlled by the Khronos group." ContentLicense="CC BY-SA 4.0" />
  <row Id="29729" PostHistoryTypeId="2" PostId="10250" RevisionGUID="7592aaf0-96f7-4951-80e2-775c740e2ef0" CreationDate="2020-09-22T18:06:16.813" UserId="48" Text="It's defining the gradient in terms of barycentric coordinates. It is similar to the derivation in [this answer](https://computergraphics.stackexchange.com/a/10169/48), only rearranged a bit algebraically using the fact that the three barycentric coordinates sum to one." ContentLicense="CC BY-SA 4.0" />
  <row Id="29730" PostHistoryTypeId="2" PostId="10251" RevisionGUID="c26fa190-4d50-4b5c-a1d1-663b807991c5" CreationDate="2020-09-22T18:19:48.420" UserId="48" Text="If projecting them onto the plane of the vertex normal doesn't do the job, I'm not sure what would. There isn't any unambiguous way to do this in 3D. Imagine the new triangle that you are on there joining is perpendicular to the existing two triangles? What would you want the answer to be in that case?&#xD;&#xA;&#xD;&#xA;I suppose you could try &quot;voting&quot; by dotting the new triangle's normal with each of the existing triangle's normals. A positive dot is a vote to keep the current orientation, a negative dot is a vote to flip it. Maybe weight the votes by the triangles' areas, or their angles at that vertex. Of course you'd have to decide how to break ties, and this might just give you similar problems to the plane of the common vertex normal.&#xD;&#xA;&#xD;&#xA;This would make more sense if you were constructing a new triangle that shared an edge with one of the existing triangles. Then you could copy the orientation from the triangle that it was joined to. I'm not sure what kind of 3D modeling operation you're doing that produces this situation, but if there's any way you can accomplish it by building things in terms of common edges rather than common vertices, you'll probably have a much better time." ContentLicense="CC BY-SA 4.0" />
  <row Id="29731" PostHistoryTypeId="5" PostId="10250" RevisionGUID="567b94b8-5199-44e0-8145-a059d9fc8133" CreationDate="2020-09-22T18:26:25.573" UserId="48" Comment="added derivation" Text="It's defining the gradient in terms of barycentric coordinates. It is similar to the derivation in [this answer](https://computergraphics.stackexchange.com/a/10169/48), only rearranged a bit algebraically using the fact that the three barycentric coordinates sum to one.&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;f(\mathbf{u}) &amp;= f_i B_i(\mathbf{u}) + f_j B_j(\mathbf{u}) + f_k B_k(\mathbf{u}) \\&#xD;&#xA;&amp;= f_i (1 - B_j(\mathbf{u}) - B_k(\mathbf{u})) + f_j B_j(\mathbf{u}) + f_k B_k(\mathbf{u}) \\&#xD;&#xA;&amp;= f_i + (f_j - f_i) B_j(\mathbf{u}) + (f_k - f_i) B_k(\mathbf{u}) \\&#xD;&#xA;\nabla f(\mathbf{u}) &amp;= (f_j - f_i) \nabla B_j(\mathbf{u}) + (f_k - f_i) \nabla B_k(\mathbf{u}) \\&#xD;&#xA;\end{aligned}&#xD;&#xA;$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="29732" PostHistoryTypeId="2" PostId="10252" RevisionGUID="e68b4cbf-ba47-444e-8fc3-da0a03b7c632" CreationDate="2020-09-22T18:46:11.310" UserId="14000" Text="Answer over in Photography:&#xD;&#xA;https://photo.stackexchange.com/questions/119761/sensor-size-of-sony-hdr-hc7e/119764#119764&#xD;&#xA;It turns out to be Vertikal: 3.74 horizontal 4.98 and diagonal 6.23" ContentLicense="CC BY-SA 4.0" />
  <row Id="29733" PostHistoryTypeId="12" PostId="10249" RevisionGUID="ce56d134-7524-4349-ab98-209917d32e49" CreationDate="2020-09-22T19:21:11.750" UserId="11058" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:11058,&quot;DisplayName&quot;:&quot;Lenny White&quot;}]}" />
  <row Id="29734" PostHistoryTypeId="13" PostId="10249" RevisionGUID="80530f85-cb50-4d66-88a7-105edb785d1c" CreationDate="2020-09-22T19:21:34.430" UserId="11058" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:11058,&quot;DisplayName&quot;:&quot;Lenny White&quot;}]}" />
  <row Id="29735" PostHistoryTypeId="50" PostId="8807" RevisionGUID="05879f7c-227b-4051-9930-71e73b4e500d" CreationDate="2020-09-23T01:08:00.937" UserId="-1" />
  <row Id="29736" PostHistoryTypeId="5" PostId="7817" RevisionGUID="b42c6e77-d036-475b-b06e-2a5b924a4041" CreationDate="2020-09-23T08:46:58.240" UserId="209" Comment="added farctanc" Text="As others have said, GPUs expose a higher-level language, which allows multiple different architectures i.e. different vendors and different GPU generations, to all support the same applications.&#xD;&#xA;&#xD;&#xA;If, however, you're still curious, documentation for the [PowerVR *Series 6* instruction set is available][1] - my favourite opcodes being &quot;FRED&quot; and &quot;FARCTANC&quot; :-)&#xD;&#xA;&#xD;&#xA;Note that instructions sets can change from generation to generation so this is mainly for illustrative purposes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.imgtec.com/developers/powervr/documentation/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29737" PostHistoryTypeId="5" PostId="7817" RevisionGUID="2e210b61-70d7-4ad5-9145-207b465242b1" CreationDate="2020-09-23T08:54:53.390" UserId="209" Comment="Updated link to more recent documentation" Text="As others have said, GPUs expose a higher-level language, which allows multiple different architectures i.e. different vendors and different GPU generations, to all support the same applications.&#xD;&#xA;&#xD;&#xA;*[Update: Link to older ISA replaced with newer one]*&lt;br&gt;&#xD;&#xA;If, however, you're still curious, documentation for the recent [PowerVR instruction set is available][1] - my favourite opcodes being &quot;FRED&quot; and &quot;FARCTANC&quot; :-)&#xD;&#xA;&#xD;&#xA;Note that instructions sets can change from generation to generation so this is mainly for illustrative purposes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.imgtec.com/Architecture_Guides/PowerVR_ISR/topics/d0e75.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="29738" PostHistoryTypeId="2" PostId="10253" RevisionGUID="143cb178-b76d-49ec-abde-1db146ed6dfb" CreationDate="2020-09-23T08:58:07.413" UserId="38" Text="Since your actuallyu doing a PDF file you should do this as a vector drawing not a image format. This makes for way more clearer end results. I will generate a image in EPS, EPS is easy to build into your PDF file with say distiller, ghostscript, sent to printer or injected into TeX (though then you may want to use Tix or or PStricks) .&#xD;&#xA;&#xD;&#xA;Ok first you have to undertsand that EPS is a full programing language (Postscript), in addition to being a vector format (the Encapsulation part). I will be uisng the features to remove repetition. The file begins with a encapsulation marker so that you can more easily insert it programmatically.&#xD;&#xA;&#xD;&#xA;So frist draw the thing form a overhead view, then we will transform that into isometric with a affine transform:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Preview of listing 1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    %!PS-Adobe-3.0 EPSF-3.0 &#xD;&#xA;    %%BoundingBox: 0 0 538 300&#xD;&#xA;    %%Title: listing 1&#xD;&#xA;    %%Creator: joojaa&#xD;&#xA;    %%CreationDate:  2020-09-23&#xD;&#xA;    %%EndComments&#xD;&#xA;    &#xD;&#xA;    % postscript style shorthand relative&#xD;&#xA;    /m {moveto} def&#xD;&#xA;    /rm {rmoveto} def&#xD;&#xA;    /rl {rlineto} def&#xD;&#xA;    &#xD;&#xA;    10 10 translate % add some padding&#xD;&#xA;    72 25.4 div 100 div  dup scale  % draw in  1:100&#xD;&#xA;    70 setlinewidth %0.7 mm technical pen&#xD;&#xA;    &#xD;&#xA;    newpath  % coordinates and ops follow&#xD;&#xA;    0 4100 m&#xD;&#xA;    0 5500 rl&#xD;&#xA;    9000  0 rl&#xD;&#xA;    0 -4000 rl&#xD;&#xA;    4000 0 rl&#xD;&#xA;    0 -1300 rl&#xD;&#xA;    0 -800 rm&#xD;&#xA;    0 -1000 rl	&#xD;&#xA;    stroke&#xD;&#xA;    &#xD;&#xA;    %%EOF&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Ok then we transform the entire thing to isometric&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Image 2: Image after Listing 2. Only stroke changed&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    %!PS-Adobe-3.0 EPSF-3.0 &#xD;&#xA;    %%BoundingBox: 0 0 538 300&#xD;&#xA;    %%Title: listing &#xD;&#xA;    %%Creator: joojaa&#xD;&#xA;    %%CreationDate:  2020-09-23&#xD;&#xA;    %%EndComments&#xD;&#xA;    &#xD;&#xA;    % postscript style shorthand relative&#xD;&#xA;    /m {moveto} def&#xD;&#xA;    /rm {rmoveto} def&#xD;&#xA;    /rl {rlineto} def&#xD;&#xA;    &#xD;&#xA;    10 10 translate % add some padding&#xD;&#xA;    72 25.4 div 100 div  dup scale  % draw in  1:100&#xD;&#xA;    70 setlinewidth %0.7 mm technical pen&#xD;&#xA;    &#xD;&#xA;    newpath  % coordinates and ops follow&#xD;&#xA;    0 4100 m&#xD;&#xA;    &#xD;&#xA;    0 5500 rl&#xD;&#xA;    9000  0 rl&#xD;&#xA;    0 -4000 rl&#xD;&#xA;    4000 0 rl&#xD;&#xA;    0 -1300 rl&#xD;&#xA;    0 -800 rm&#xD;&#xA;    0 -1000 rl&#xD;&#xA;    &#xD;&#xA;    %changed stroke to this&#xD;&#xA;    gsave&#xD;&#xA;     false upath&#xD;&#xA;      9600 60 sin mul 0 translate &#xD;&#xA;      [60 sin 60 cos -60 sin -60 cos 0 0] concat&#xD;&#xA;      ustroke&#xD;&#xA;    grestore &#xD;&#xA;    %eof changed&#xD;&#xA;    &#xD;&#xA;    %%EOF&#xD;&#xA;&#xD;&#xA;Then we duplicate this and offset&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;*Image 3*: After offsetting&#xD;&#xA;&#xD;&#xA;	%!PS-Adobe-3.0 EPSF-3.0 &#xD;&#xA;	%%BoundingBox: 0 0 538 300&#xD;&#xA;	%%Title: listing 3&#xD;&#xA;	%%Creator: joojaa &#xD;&#xA;	%%CreationDate:  2020-09-23	&#xD;&#xA;	%%EndComments&#xD;&#xA;&#xD;&#xA;	% postscript style shorthand relative&#xD;&#xA;	/m {moveto} def&#xD;&#xA;	/rm {rmoveto} def&#xD;&#xA;	/rl {rlineto} def&#xD;&#xA;&#xD;&#xA;	10 10 translate % add some padding&#xD;&#xA;	72 25.4 div 100 div  dup scale  % draw in  1:100&#xD;&#xA;	70 setlinewidth %0.7 mm technical pen&#xD;&#xA;&#xD;&#xA;	newpath  % coordinates and ops follow&#xD;&#xA;	0 4100 m&#xD;&#xA;&#xD;&#xA;	0 5500 rl&#xD;&#xA;	9000  0 rl&#xD;&#xA;	0 -4000 rl&#xD;&#xA;	4000 0 rl&#xD;&#xA;	0 -1300 rl&#xD;&#xA;	0 -800 rm&#xD;&#xA;	0 -1000 rl&#xD;&#xA;&#xD;&#xA;	gsave&#xD;&#xA;	 false upath&#xD;&#xA;	  9600 60 sin mul -1100 translate &#xD;&#xA;	  [60 sin 60 cos -60 sin -60 cos 0 0] concat&#xD;&#xA;	  ustroke&#xD;&#xA;	grestore &#xD;&#xA;&#xD;&#xA;	gsave&#xD;&#xA;	 false upath&#xD;&#xA;	  9600 60 sin mul 10 translate &#xD;&#xA;	  [60 sin 60 cos -60 sin -60 cos 0 0] concat&#xD;&#xA;	  ustroke&#xD;&#xA;	grestore &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	%%EOF&#xD;&#xA;&#xD;&#xA;Next draw connecting lines&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;*Image 4*: Listing 4 result&#xD;&#xA;&#xD;&#xA;	%!PS-Adobe-3.0 EPSF-3.0 &#xD;&#xA;	%%BoundingBox: 0 0 538 300&#xD;&#xA;	%%Title: listing 4&#xD;&#xA;	%%Creator: joojaa &#xD;&#xA;	%%CreationDate:  2020-09-23	&#xD;&#xA;	%%EndComments&#xD;&#xA;&#xD;&#xA;	% postscript style shorthand relative&#xD;&#xA;	/m {moveto} def&#xD;&#xA;	/rm {rmoveto} def&#xD;&#xA;	/rl {rlineto} def&#xD;&#xA;	%draw connecting line&#xD;&#xA;&#xD;&#xA;	/tf { 9600 60 sin mul 10 translate &#xD;&#xA;		[60 sin 60 cos -60 sin -60 cos 0 0] concat} def&#xD;&#xA;&#xD;&#xA;	/dc {gsave &#xD;&#xA;		newpath &#xD;&#xA;		9600 60 sin mul 10 translate &#xD;&#xA;		[60 sin 60 cos -60 sin -60 cos 0 0] &#xD;&#xA;		concat m -1100 -1100 rl&#xD;&#xA;		stroke &#xD;&#xA;		grestore&#xD;&#xA;	     } def&#xD;&#xA;&#xD;&#xA;	10 10 translate % add some padding&#xD;&#xA;	72 25.4 div 100 div  dup scale  % draw in  1:100&#xD;&#xA;	70 setlinewidth %0.7 mm technical pen&#xD;&#xA;&#xD;&#xA;	newpath  % coordinates and ops follow&#xD;&#xA;&#xD;&#xA;	0 4100 m&#xD;&#xA;	0 5500 rl&#xD;&#xA;	9000  0 rl&#xD;&#xA;	0 -4000 rl&#xD;&#xA;	4000 0 rl&#xD;&#xA;	0 -1300 rl&#xD;&#xA;	0 -800 rm&#xD;&#xA;	0 -1000 rl&#xD;&#xA;	     &#xD;&#xA;	%drawing no need to change&#xD;&#xA;	gsave&#xD;&#xA;	 false upath&#xD;&#xA;	  tf&#xD;&#xA;	ustroke&#xD;&#xA;	grestore &#xD;&#xA;&#xD;&#xA;	gsave&#xD;&#xA;	 false upath&#xD;&#xA;	  0 -1100 translate&#xD;&#xA;	  tf&#xD;&#xA;	  ustroke&#xD;&#xA;	grestore &#xD;&#xA;&#xD;&#xA;	{dc} {dc} {} {} pathforall&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	%%EOF&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Todoo:&#xD;&#xA;&#xD;&#xA;* Change stroke to round &#xD;&#xA;* Draw in paperspace&#xD;&#xA;* Draw distances.&#xD;&#xA;* Compute bound and center&#xD;&#xA;* Etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I might return later&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rkY4O.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/EGRc0.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/XdkkJ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/XD1x1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29739" PostHistoryTypeId="2" PostId="10254" RevisionGUID="a2dd8b89-f938-4c83-9e06-d124ad5f2720" CreationDate="2020-09-23T09:02:40.223" UserId="13273" Text="I want to do some complicated stuff but have problems with my geometry shader / FBO bindings.&#xD;&#xA;To hold it as easy as possible I reduced the code to a minimum. If this works, I could continue the hard part. So don't wonder, why I am trying to do it in this way...&#xD;&#xA;&#xD;&#xA;**The &quot;easy&quot; thing:**&#xD;&#xA;&#xD;&#xA;I have two triangles (a quad) which are going over the whole screen from (-1,-1,0) to (1,1,0).&#xD;&#xA;Inside my geometry shader I want to copy these two triangles six times to cover all six faces of my cubemap. BTW: I don't need a depth or stencil buffer.&#xD;&#xA;&#xD;&#xA;**Lets look at the cubemap texture generation:**&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_cubeMapTexture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_CUBE_MAP, m_cubeMapTexture);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;    checkGLError();&#xD;&#xA;    // set textures&#xD;&#xA;    for (int i = 0; i &lt; 6; ++i)&#xD;&#xA;        glTexImage2D(static_cast&lt;GLenum&gt;(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), 0, GL_RGB, 2048, 2048, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);&#xD;&#xA;&#xD;&#xA;**This texture will be plugged into a frameBufferObject in the following way:**&#xD;&#xA;&#xD;&#xA;    glGenFramebuffers(1, &amp;m_cubeMapFBO);&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, m_cubeMapFBO);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, m_cubeMapTexture, 0);&#xD;&#xA;    &#xD;&#xA;    static const GLuint draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5 };&#xD;&#xA;    glDrawBuffers(6, draw_buffers);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**The vertex shader:**&#xD;&#xA;&#xD;&#xA;    #version 420&#xD;&#xA;    in vec3 POSITION;&#xD;&#xA;                                                                                    &#xD;&#xA;    out VS_OUT                                                            &#xD;&#xA;    {                                                                    &#xD;&#xA;       vec3 position;                                                     &#xD;&#xA;    } vs_out;                                                            &#xD;&#xA;                                                                                    &#xD;&#xA;    void main()                                                           &#xD;&#xA;    {                                                                   &#xD;&#xA;        vs_out.position = POSITION;  &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Just take the input and pass it to the geometry shader   &#xD;&#xA;&#xD;&#xA;**Lets continue with the geometry shader:**       &#xD;&#xA;                                                &#xD;&#xA;    #version 420                                                        &#xD;&#xA;    layout (triangles) in;                                               &#xD;&#xA;    layout (triangle_strip, max_vertices = 36) out;                     &#xD;&#xA;    uniform mat3 orientation[6];                                        &#xD;&#xA;                                                                                  &#xD;&#xA;    in VS_OUT                                                           &#xD;&#xA;    {                                                                   &#xD;&#xA;        vec3 position;                                                   &#xD;&#xA;    } gs_in[];                                                        &#xD;&#xA;                                                                                  &#xD;&#xA;    out GS_OUT                                                         &#xD;&#xA;    {                                                                   &#xD;&#xA;        vec3 position;                                                    &#xD;&#xA;    } gs_out;                                                          &#xD;&#xA;                                                                                  &#xD;&#xA;    void main()                                                          &#xD;&#xA;    {                                                                  &#xD;&#xA;        for (int i = 0; i &lt; 6; ++i)                                     &#xD;&#xA;        {                                                                &#xD;&#xA;            gl_Layer = i;                                              &#xD;&#xA;            gl_Position = vec4(gs_in[0].position, 1.0f);                &#xD;&#xA;            gs_out.position = orientation[i] * vec3(gs_in[0].position.xy, 1.0f);      &#xD;&#xA;            EmitVertex();                                               &#xD;&#xA;                                                                                  &#xD;&#xA;            gl_Layer = i;                                                &#xD;&#xA;            gl_Position = vec4(gs_in[1].position, 1.0f);                 &#xD;&#xA;            gs_out.position = orientation[i] * vec3(gs_in[1].position.xy, 1.0f);        &#xD;&#xA;            EmitVertex();                                              &#xD;&#xA;                                                                                  &#xD;&#xA;            gl_Layer = i;                                                &#xD;&#xA;            gl_Position = vec4(gs_in[2].position, 1.0f);                &#xD;&#xA;            gs_out.position = orientation[i] * vec3(gs_in[2].position.xy, 1.0f);        &#xD;&#xA;            EmitVertex();                                                &#xD;&#xA;                                                                                  &#xD;&#xA;            EndPrimitive();                                              &#xD;&#xA;        }                                                               &#xD;&#xA;    }     &#xD;&#xA;&#xD;&#xA;The for loop creates each triangle six times (one for each cubemap face &quot;gl_Layer = i&quot;).&#xD;&#xA;the gl_Position is the input quad without any transformations.&#xD;&#xA;the gs_out.position is rotated by the orientation matrix (a rotation matrix for each face). This gs_out.position should be interpolated within the fragment shader.&#xD;&#xA;&#xD;&#xA;**Last, but not least: The fragment shader**                                                                       &#xD;&#xA;&#xD;&#xA;    #version 420                                             &#xD;&#xA;    in GS_OUT                                              &#xD;&#xA;    {                                                    &#xD;&#xA;        vec3 position;                                       &#xD;&#xA;    } fs_in;                                                &#xD;&#xA;                                                                      &#xD;&#xA;    out vec4 color;                                     &#xD;&#xA;                                                                      &#xD;&#xA;    void main()                                            &#xD;&#xA;    {                                                      &#xD;&#xA;        color = vec4(fs_in.position, 1.0f);                &#xD;&#xA;    }          &#xD;&#xA;&#xD;&#xA;The interpolated fs_in.position will be stored into the cubemap.&#xD;&#xA;&#xD;&#xA;If you just look at the code and try to imagine what the output should be, you'll end up to say:&#xD;&#xA;&quot;That is the RGB cube + the minus part which is stored in the cubemap.&quot;&#xD;&#xA;&#xD;&#xA;**And now I'll show you the output:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My first intention was changing the &quot;orientation&quot; matrices but I noticed, that this is not the problem:&#xD;&#xA;By changing the for loop counter within my geometry shader to &quot;for (int i = 0; i &lt; **1**; ++i)&quot; I got the following output:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So there are only the two triangles, which are not copied anymore and each cubemap face is colored in the same way. gl_Layer was only set to zero but the other layers are also colored. How can that be?&#xD;&#xA;How can I change the code, so that only the face &quot;gl_Layer&quot; will be colored?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mfI4o.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/so8M2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29740" PostHistoryTypeId="1" PostId="10254" RevisionGUID="a2dd8b89-f938-4c83-9e06-d124ad5f2720" CreationDate="2020-09-23T09:02:40.223" UserId="13273" Text="draw on cubemap with help of geometry shader each triangle covers each cubemap face (why??)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29741" PostHistoryTypeId="3" PostId="10254" RevisionGUID="a2dd8b89-f938-4c83-9e06-d124ad5f2720" CreationDate="2020-09-23T09:02:40.223" UserId="13273" Text="|opengl|glsl|c++|frame-buffer|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29742" PostHistoryTypeId="2" PostId="10255" RevisionGUID="3d1e7c09-f9a2-4e29-ba00-94c4a88fbe1f" CreationDate="2020-09-23T12:37:13.023" UserId="13273" Text="After trying everything possible I found my mistake:&#xD;&#xA;&#xD;&#xA;The shaders are fine, the only thing which is wrong is the frameBufferObject binding. To be honest, the texture to FBO binding.&#xD;&#xA;&#xD;&#xA;**the only thing I replaced is this:**&#xD;&#xA;&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, m_cubeMapTexture, 0);&#xD;&#xA;    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT5, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, m_cubeMapTexture, 0);&#xD;&#xA;&#xD;&#xA;**by the correct method call:**&#xD;&#xA;&#xD;&#xA;    glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_cubeMapTexture, 0);&#xD;&#xA;        &#xD;&#xA;**The result of the changed code is this:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UB0s3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29743" PostHistoryTypeId="2" PostId="10256" RevisionGUID="3031db3f-ae51-444b-8c00-6d61448738d3" CreationDate="2020-09-24T03:17:24.137" UserId="7462" Text="So I recently learnt that supposedly for any mesh, and pretty much any scheme, the valence of regular vertices must be 6. It seems to be related to the Euler-Poincare formula but I have not been able to find the justification." ContentLicense="CC BY-SA 4.0" />
  <row Id="29744" PostHistoryTypeId="1" PostId="10256" RevisionGUID="3031db3f-ae51-444b-8c00-6d61448738d3" CreationDate="2020-09-24T03:17:24.137" UserId="7462" Text="Why is the valence of regular vertices 6?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29745" PostHistoryTypeId="3" PostId="10256" RevisionGUID="3031db3f-ae51-444b-8c00-6d61448738d3" CreationDate="2020-09-24T03:17:24.137" UserId="7462" Text="|computational-geometry|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29746" PostHistoryTypeId="2" PostId="10257" RevisionGUID="0cb91394-b9e3-4436-aab9-15a171f4f331" CreationDate="2020-09-24T10:00:21.543" UserId="7724" Text="If require that all faces have the same number of sides $s$ and require that all vertices also have a certain valency $t$. We see that the following relation between edges, and faces hold for an arbitrary mesh:&#xD;&#xA;&#xD;&#xA;$$s\cdot f = 2e,$$&#xD;&#xA;$$t\cdot v = 2e.$$ Substitution in the Euler-Poincare formula yields:&#xD;&#xA;&#xD;&#xA;$$\left(\frac{1}{s} + \frac{1}{t} - \frac{1}{2}\right)e = 1 - g$$&#xD;&#xA;&#xD;&#xA;If we then take for instance a regular plane which can be said to have the topology of a torus with genus $g = 1$. We then set the valency of faces $s = 3$ then&#xD;&#xA;&#xD;&#xA;$$\left(\frac{1}{3} + \frac{1}{t} - \frac{1}{2}\right)e = 0,$$&#xD;&#xA;$$\left(-\frac{1}{6} + \frac{1}{t}\right)e = 0.$$&#xD;&#xA;&#xD;&#xA;The solution for $t$ is $6$, which says the valency of a vertex in a regular triangulation is 6. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29747" PostHistoryTypeId="34" PostId="10223" RevisionGUID="0c8fe9d4-9bde-4e8d-8839-7c7fe1320398" CreationDate="2020-09-24T15:07:00.710" UserId="-1" Comment="64" />
  <row Id="29748" PostHistoryTypeId="5" PostId="10257" RevisionGUID="9ab7b2a5-8a82-4928-b1ac-2d370b55270a" CreationDate="2020-09-25T18:12:22.583" UserId="7724" Comment="deleted 3 characters in body" Text="If require that all faces have the same number of sides $s$ and require that all vertices also have a certain valency $t$. We see that the following relation between edges, and faces hold for a regular mesh:&#xD;&#xA;&#xD;&#xA;$$s\cdot f = 2e,$$&#xD;&#xA;$$t\cdot v = 2e.$$ Substitution in the Euler-Poincare formula yields:&#xD;&#xA;&#xD;&#xA;$$\left(\frac{1}{s} + \frac{1}{t} - \frac{1}{2}\right)e = 1 - g$$&#xD;&#xA;&#xD;&#xA;If we then take for instance a regular plane which can be said to have the topology of a torus with genus $g = 1$. We then set the valency of faces $s = 3$ then&#xD;&#xA;&#xD;&#xA;$$\left(\frac{1}{3} + \frac{1}{t} - \frac{1}{2}\right)e = 0,$$&#xD;&#xA;$$\left(-\frac{1}{6} + \frac{1}{t}\right)e = 0.$$&#xD;&#xA;&#xD;&#xA;The solution for $t$ is $6$, which says the valency of a vertex in a regular triangulation is 6. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29749" PostHistoryTypeId="2" PostId="10258" RevisionGUID="fbdd21da-d58c-4dde-87b0-f9b1e2eddf56" CreationDate="2020-09-25T20:08:02.893" UserId="7462" Text="If anyone ever runs into this. There is a mathematical property of the half edge, that makes it such that any proper half edge can be expressed as an even permutation of vertices.&#xD;&#xA;&#xD;&#xA;This sounds abstract but the gist of it is very simple. Since there is an even number of HE by definition, you can store your half edges such that if $n$ is even then $n + 1$ is its pair. As such you can just iterate through the actual edges by skipping every other edge.&#xD;&#xA;&#xD;&#xA;The drawback is that you need to ensure that your edges are indeed stored like that, which can be complex." ContentLicense="CC BY-SA 4.0" />
  <row Id="29750" PostHistoryTypeId="2" PostId="10259" RevisionGUID="d915b7cf-10c6-4ec4-8d5e-ac8d66218970" CreationDate="2020-09-25T22:05:24.093" UserId="13696" Text="So I've been all around the houses on this looking for an answer. In the end I found a combination of techniques worked quite well:&#xD;&#xA;&#xD;&#xA;1. To take advantage of all of the 'empty space', the concept of 'surface tracking' from the Octree Decimation paper useful - you can follow the surface from cell to cell and ignore all of the cells in the middle.&#xD;&#xA;&#xD;&#xA;2. The main advantage of generating the voxels ourselves is what we know two vital pieces of information: firstly, the exact position of each vertex within the cells on the 'front' surface; secondly, the 'orientation' of the mesh in each region and which way that 'front' is to be found.&#xD;&#xA;&#xD;&#xA;Putting all the pieces together I came up with this [Dual Marching Cuboids](https://github.com/andygeers/DualMarchingCuboids) algorithm, that has pretty good results in very reasonable time. " ContentLicense="CC BY-SA 4.0" />
  <row Id="29752" PostHistoryTypeId="2" PostId="10260" RevisionGUID="7cf5a5cf-9b92-420f-9912-c85d24980c7f" CreationDate="2020-09-26T13:38:28.473" UserId="14015" Text="Keeping alpha linear makes it unbiased towards source and destination color. It should not be gamma corrected, because it should not have been subjected to sRGB-encoding.&#xD;&#xA;&#xD;&#xA;A specialized application could of course ignore this, for example to get more control over the change in perceived brightness during a blending operation of a bright source color over a dark destination color (assuming alpha is stored in a byte with range 0-255 - which is how sRGB is commonly stored these days for the purpose of data compression - where you can only change the alpha in big steps)." ContentLicense="CC BY-SA 4.0" />
  <row Id="29753" PostHistoryTypeId="2" PostId="10261" RevisionGUID="c7a8cbc2-f824-45e3-b7a4-4e0a8a3910db" CreationDate="2020-09-27T02:40:28.717" UserId="7462" Text="[Cross posting][1] from SO because I didn;t know where to put this question.&#xD;&#xA;&#xD;&#xA;I have an implementation of the half edge and I am trying to sort the edges such that edge n+1 is the pair of edge n.&#xD;&#xA;&#xD;&#xA;# Setup&#xD;&#xA;I want to do this in place to save memory and I discovered a theoretical wall I am not sure how to solve.&#xD;&#xA;&#xD;&#xA;Let's assume the HE are stored in a list and that you can access their members through self defining getters like `.Pair()` or `.Next()`.&#xD;&#xA;&#xD;&#xA;The idea of the algorithm is very simple.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;for(uint i=0; i&lt;half_edges.size(); i+=2)&#xD;&#xA;{&#xD;&#xA;   swap(half_edges[i+1], half_edges[i].Pair()); // This is pseudo code, assume this works&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;That's the gist of the idea, merely swap the he right next to you with wherever your pair is.&#xD;&#xA;&#xD;&#xA;Now of course, you need to update your pointers, so for both the pair and the HE originally at $i + 1$ you have to go through this tedious process:&#xD;&#xA;&#xD;&#xA;        faces[old_pair_face].edge = i + 1;&#xD;&#xA;        verts[old_pair_vert].edge = i + 1;&#xD;&#xA;        edges[old_pair_prev].next = i + 1;&#xD;&#xA;        edges[old_pair_next].prev = i + 1;&#xD;&#xA;        edges[i].pair = i + 1;&#xD;&#xA;&#xD;&#xA;        faces[old_other_face].edge = old_pair_index;&#xD;&#xA;        verts[old_other_vert].edge = old_pair_index;&#xD;&#xA;        edges[old_other_prev].next = old_pair_index;&#xD;&#xA;        edges[old_other_next].prev = old_pair_index;&#xD;&#xA;        edges[old_other_pair].pair = old_pair_index;&#xD;&#xA;&#xD;&#xA;Essentially just update all the pointers that pointed to the original 2 elements.&#xD;&#xA;&#xD;&#xA;# BUG&#xD;&#xA;The above ALMOST works. However consider the following case. Assume we are at edge `i`. The pair of `i` is `j`, the `next` of `j` is `i+1`.&#xD;&#xA;&#xD;&#xA;So `i + 1` and `j` swap, so the pair of `i` is now at `i + 1`. You then want to update `next`, which points to `i + 1`, so inadvertently in this specific case, swap will accidentally make `next` point to yourself. Which is invalid as the Half edge does not allow an edge to point to itself.&#xD;&#xA;&#xD;&#xA;This is pretty rare so it took me a while to find, but it's clearly an error in my logic.&#xD;&#xA;&#xD;&#xA;The question is, given an already implemented half edge, how can you sort its edges such that the n and n+1 are pairs, while avoiding the pitfalll described above, in O(1) memory?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/64084221/in-place-sorting-of-a-half-edge-data-structure" ContentLicense="CC BY-SA 4.0" />
  <row Id="29754" PostHistoryTypeId="1" PostId="10261" RevisionGUID="c7a8cbc2-f824-45e3-b7a4-4e0a8a3910db" CreationDate="2020-09-27T02:40:28.717" UserId="7462" Text="In place sorting of a hafl edge DS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29755" PostHistoryTypeId="3" PostId="10261" RevisionGUID="c7a8cbc2-f824-45e3-b7a4-4e0a8a3910db" CreationDate="2020-09-27T02:40:28.717" UserId="7462" Text="|c++|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29759" PostHistoryTypeId="2" PostId="10263" RevisionGUID="1a6c9c3d-dba7-4e4d-b339-7d2210b5252a" CreationDate="2020-09-27T17:45:11.410" UserId="228" Text="I'm trying to render a cube and it's wireframe together using OpenGL&#xD;&#xA;&#xD;&#xA;The main function is this:&#xD;&#xA;&#xD;&#xA;    int main(int argc, char** argv)&#xD;&#xA;    {&#xD;&#xA;        GLFWwindow* window;&#xD;&#xA;    &#xD;&#xA;        /* Initialize the library */&#xD;&#xA;        if (!glfwInit())&#xD;&#xA;            return -1;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        /* Create a windowed mode window and its OpenGL context */&#xD;&#xA;        window = glfwCreateWindow(1024, 768, &quot;MyGL&quot;, NULL, NULL);&#xD;&#xA;        if (!window)&#xD;&#xA;        {&#xD;&#xA;            glfwTerminate();&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        /* Make the window's context current */&#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;        if (glewInit() != GLEW_OK) {&#xD;&#xA;            std::cout &lt;&lt; &quot;Error!&quot; &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        float positions[] = {&#xD;&#xA;                              -0.5f, -0.5f,  0.5f,      //0&#xD;&#xA;                               0.5f, -0.5f,  0.5f,      //1&#xD;&#xA;                               0.5f,  0.5f,  0.5f,      //2&#xD;&#xA;                              -0.5f,  0.5f,  0.5f,      //3&#xD;&#xA;                              -0.5f,  0.5f, -0.5f,      //4&#xD;&#xA;                               0.5f,  0.5f, -0.5f,      //5&#xD;&#xA;                              -0.5f, -0.5f, -0.5f,      //6&#xD;&#xA;                               0.5f, -0.5f, -0.5f       //7&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        unsigned int indices[] = {&#xD;&#xA;                                  0, 1, 2, 3,&#xD;&#xA;                                  4, 5, 6, 7,&#xD;&#xA;                                  2, 3, 4, 5,&#xD;&#xA;                                  2, 5, 7, 1,&#xD;&#xA;                                  1, 0, 6, 7,&#xD;&#xA;                                  0, 6, 3, 4&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        unsigned int w_indices[] = {&#xD;&#xA;                                    0, 1, 1, 2, 2, 3, 3, 0,     // fronte&#xD;&#xA;                                    0, 6, 6, 7, 7, 1, 1, 0,     // sotto&#xD;&#xA;                                    3, 2, 2, 5, 5, 4, 4, 3,     // sopra&#xD;&#xA;                                    4, 5, 5, 7, 7, 6, 6, 4,     // retro&#xD;&#xA;                                    2, 5, 5, 7, 7, 1, 1, 2,     // destra&#xD;&#xA;                                    3, 4, 4, 6, 6, 0, 0, 3      // sinistra&#xD;&#xA;    &#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        unsigned int buffer;&#xD;&#xA;        unsigned int index_buffer[2];&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(1, &amp;buffer);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(float), positions, GL_STATIC_DRAW);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;    &#xD;&#xA;        glGenBuffers(2, index_buffer);&#xD;&#xA;        &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer[0]);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 24 * sizeof(int), indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer[1]);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 48 * sizeof(int), w_indices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 proj = glm::ortho(-2.0f, 2.0f, -1.5f, 1.5f, -1.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;        glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-0.4, 0, 0));&#xD;&#xA;    &#xD;&#xA;        glm::mat4 view2 = glm::rotate(view, 30.0f, glm::vec3(0.0f, -1.0f, 1.0f));&#xD;&#xA;    &#xD;&#xA;        glm::mat4 mvp = proj * view2;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        ShaderProgramSource source = parseShader(&quot;C:\\Users\\Lukkio\\Documents\\Gildo\\res\\shader\\myShader.shader&quot;);&#xD;&#xA;    &#xD;&#xA;        unsigned int shader = createShader(source.vertex_source, source.fragment_source);&#xD;&#xA;        glUseProgram(shader);&#xD;&#xA;    &#xD;&#xA;        int location = glGetUniformLocation(shader, &quot;u_color&quot;);&#xD;&#xA;        int u_mvp = glGetUniformLocation(shader, &quot;u_MVP&quot;);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        glUniform4f(location, 0.0, 1.0, 1.0, 1.0);&#xD;&#xA;    &#xD;&#xA;        glUniformMatrix4fv(u_mvp, 1, GL_FALSE, &amp;mvp[0][0]);&#xD;&#xA;    &#xD;&#xA;        float r = 0.0f;&#xD;&#xA;        float g = 1.0f;&#xD;&#xA;        float b = 1.0f;&#xD;&#xA;    &#xD;&#xA;        /* Loop until the user closes the window */&#xD;&#xA;        while (!glfwWindowShouldClose(window))&#xD;&#xA;        {&#xD;&#xA;            glEnable(GL_DEPTH_TEST);&#xD;&#xA;            glDepthFunc(GL_LESS);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;            /* Render here */&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;            glUniform4f(location, r, g, b, 0);&#xD;&#xA;    &#xD;&#xA;            glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, nullptr);&#xD;&#xA;    &#xD;&#xA;            glUniform4f(location, 1.0, 0.0, 0.0, 0.0);&#xD;&#xA;    &#xD;&#xA;            glDrawElements(GL_LINES, 48, GL_UNSIGNED_INT, nullptr);&#xD;&#xA;    &#xD;&#xA;            /* Swap front and back buffers */&#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;    &#xD;&#xA;            /* Poll for and process events */&#xD;&#xA;            glfwPollEvents();&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glDeleteProgram(shader);&#xD;&#xA;    &#xD;&#xA;        glfwTerminate();&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm not an openGL expert, I know bits and pieces but I rarely practice so this is mostly for refreshing.&#xD;&#xA;&#xD;&#xA;The way I was trying to achieve this was to create two index buffers, but no matter what I do I can't manage.&#xD;&#xA;&#xD;&#xA;I also noticed the 4th argument of `glDrawElements` but however I cannot manage to find what exactly I would need to pass. Because I'm essentially rendering two different objects I read I might use `VAO` but regardless of whether or not this is the right approach I'd like to know what is wrong with my approach of two index buffers, and a single vertex buffer.&#xD;&#xA;&#xD;&#xA;So here the questions:&#xD;&#xA;&#xD;&#xA;1. Why isn't it working? What am I missing?&#xD;&#xA;2. For this specific task (object + wireframe) is there maybe a much simpler approach that I'm missing?&#xD;&#xA;&#xD;&#xA;Thank you" ContentLicense="CC BY-SA 4.0" />
  <row Id="29760" PostHistoryTypeId="1" PostId="10263" RevisionGUID="1a6c9c3d-dba7-4e4d-b339-7d2210b5252a" CreationDate="2020-09-27T17:45:11.410" UserId="228" Text="Drawing a cube and wireframe opengl" ContentLicense="CC BY-SA 4.0" />
  <row Id="29761" PostHistoryTypeId="3" PostId="10263" RevisionGUID="1a6c9c3d-dba7-4e4d-b339-7d2210b5252a" CreationDate="2020-09-27T17:45:11.410" UserId="228" Text="|opengl|rendering|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29763" PostHistoryTypeId="4" PostId="10261" RevisionGUID="c9b7c162-32ed-4655-bf5f-b9d8b6c391ec" CreationDate="2020-09-27T20:10:37.443" UserId="7462" Comment="edited title" Text="In place sorting of a half edge DS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29764" PostHistoryTypeId="2" PostId="10264" RevisionGUID="49ce70a6-0bb2-4438-a01f-2d149c5b7a6b" CreationDate="2020-09-27T20:18:00.013" UserId="7462" Text="My solution to this ended up being not sorting at all. Manipualting an already initialized HE is a nightmare, so instead I built the HE with this property from the get go.&#xD;&#xA;&#xD;&#xA;The initialization algorithm is pretty much:&#xD;&#xA;&#xD;&#xA; * Create a new half edge.&#xD;&#xA; * Check if the pair of the half edge exists.&#xD;&#xA; * If it exists, you are allocated at `index of pair + 1`&#xD;&#xA; * If it does not exist, increment an `offset` by 2 and store yourself at `offset - 2` (i.e. allocate 2 slots in the edge array and store yourself in the even slot).&#xD;&#xA;&#xD;&#xA;Doing it this way before setting `next` and `prev` and company guarantees that at any one time the HE is properly initialized." ContentLicense="CC BY-SA 4.0" />
  <row Id="29768" PostHistoryTypeId="50" PostId="9103" RevisionGUID="198375a0-92ca-4831-a8ef-c27b6b93d9c4" CreationDate="2020-09-27T23:02:35.327" UserId="-1" />
  <row Id="29769" PostHistoryTypeId="2" PostId="10266" RevisionGUID="86b45896-97ac-4baf-81ee-18be87d84912" CreationDate="2020-09-28T07:12:28.723" UserId="11058" Text="I'm trying to implement a voxelization algorithm. I successfully implemented cube triangle intersection test and made a basic voxel model from discrete box meshes. However I can't find any information on how the merging is done between the discrete box meshes. A naive approach I can think of is for each face of the cube check if it overlaps with any other face, delete both faces and stitch the edges around the faces between cubes. But this seems very crude.&#xD;&#xA;&#xD;&#xA;Is there an algorithm for doing this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29770" PostHistoryTypeId="1" PostId="10266" RevisionGUID="86b45896-97ac-4baf-81ee-18be87d84912" CreationDate="2020-09-28T07:12:28.723" UserId="11058" Text="How to merge voxels" ContentLicense="CC BY-SA 4.0" />
  <row Id="29771" PostHistoryTypeId="3" PostId="10266" RevisionGUID="86b45896-97ac-4baf-81ee-18be87d84912" CreationDate="2020-09-28T07:12:28.723" UserId="11058" Text="|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29772" PostHistoryTypeId="5" PostId="10266" RevisionGUID="e0b1b825-4cd2-4eb9-ae3b-7b1d3f8628c0" CreationDate="2020-09-28T07:24:36.127" UserId="11058" Comment="edited body" Text="I'm trying to implement a voxelization algorithm. I successfully implemented cube triangle intersection test and made a basic voxel model from discrete box meshes. However I can't find any information on how the merging is done between the separate box meshes to create a unified mesh. A naive approach I can think of is for each face of the cube check if it overlaps with any other face, delete both faces and stitch the edges around the faces between cubes. But this seems very crude.&#xD;&#xA;&#xD;&#xA;Is there an algorithm for doing this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29773" PostHistoryTypeId="2" PostId="10267" RevisionGUID="d32dcff8-506c-40fe-b236-411c931eca86" CreationDate="2020-09-28T08:28:02.570" UserId="13095" Text="&gt;  I'd like to know what is wrong with my approach of two index buffers, and a single vertex buffer.&#xD;&#xA;&#xD;&#xA;There is nothing wrong with that. Reusing resources and avoiding duplicate data is always a good thing.&#xD;&#xA;&#xD;&#xA;&gt; Why isn't it working? What am I missing?&#xD;&#xA;&#xD;&#xA;Basically, you already got the answer: &quot; I read I might use `VAO`&quot;&#xD;&#xA;&#xD;&#xA;In the Vertex Array Object section of [this tutorial](https://learnopengl.com/Getting-started/Hello-Triangle) there is a big red block stating:&#xD;&#xA;&#xD;&#xA;&gt; Core OpenGL requires that we use a VAO so it knows what to do with our vertex inputs. If we fail to bind a VAO, OpenGL will most likely refuse to draw anything. &#xD;&#xA;&#xD;&#xA;Can't tell if there are any other problems with your code, but the missing `VAO` is probably the main one.&#xD;&#xA;&#xD;&#xA;I suggest you read the whole text on the site I linked and follow the instructions to render a single triangle. Afterwards, add some more triangles and try to render them using an index buffer. If you got so far, it should be easy to get your approach working.&#xD;&#xA;&#xD;&#xA;&gt; For this specific task (object + wireframe) is there maybe a much simpler approach that I'm missing?&#xD;&#xA;&#xD;&#xA;I think there are many different ways to do this. One way would be to use a single draw call and check inside the fragment shader if the current pixel is close to one of the sides of the triangle. If this is the case, just overwrite the fragment's colour with your desired wireframe colour. [This answer on Stack Overflow](https://stackoverflow.com/a/33004265/6700329) shows you how to do that. You just need to modify it a little bit so that &quot;non-wireframe&quot; sections are rendered normally instead of being translucent.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29774" PostHistoryTypeId="5" PostId="10267" RevisionGUID="803d64da-8f3e-42bb-a56e-7f7ae8246073" CreationDate="2020-09-28T08:33:30.680" UserId="13095" Comment="added 108 characters in body" Text="&gt;  I'd like to know what is wrong with my approach of two index buffers, and a single vertex buffer.&#xD;&#xA;&#xD;&#xA;There is nothing wrong with that. Reusing resources and avoiding duplicate data is always a good thing.&#xD;&#xA;&#xD;&#xA;&gt; Why isn't it working? What am I missing?&#xD;&#xA;&#xD;&#xA;Basically, you already got the answer: &quot; I read I might use `VAO`&quot;&#xD;&#xA;&#xD;&#xA;In the Vertex Array Object section of [this tutorial](https://learnopengl.com/Getting-started/Hello-Triangle) there is a big red block stating:&#xD;&#xA;&#xD;&#xA;&gt; Core OpenGL requires that we use a VAO so it knows what to do with our vertex inputs. If we fail to bind a VAO, OpenGL will most likely refuse to draw anything. &#xD;&#xA;&#xD;&#xA;Can't tell if there are any other problems with your code, but the missing `VAO` is probably the main one.&#xD;&#xA;&#xD;&#xA;I suggest you read the whole text on the site I linked and follow the instructions to render a single triangle. Afterwards, add some more triangles and try to render them using an index buffer. If you got so far, it should be easy to get your approach working.&#xD;&#xA;&#xD;&#xA;&gt; For this specific task (object + wireframe) is there maybe a much simpler approach that I'm missing?&#xD;&#xA;&#xD;&#xA;I think there are many different ways to do this. One way would be to use a single draw call and check inside the fragment shader if the current pixel is close to one of the sides of the triangle. If this is the case, just overwrite the fragment's colour with your desired wireframe colour. [This answer on Stack Overflow](https://stackoverflow.com/a/33004265/6700329) shows you how to do that. You just need to modify it a little bit so that &quot;non-wireframe&quot; sections are rendered normally instead of being translucent.&#xD;&#xA;&#xD;&#xA;Also, check the other answers in the Stack Overflow link. There a lot of different approaches mentioned.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29775" PostHistoryTypeId="2" PostId="10268" RevisionGUID="a8b4baa0-a9f1-4893-9a98-14048bb81c57" CreationDate="2020-09-28T12:32:59.083" UserId="14025" Text="FFT spectra is not what is needed; what I need is a histogram showing which frequencies are there in image in horizontal direction, and which one is dominant  &#xD;&#xA;Such spatial frequency is usually known for a **sinusoidal grating**; I need the same property for grayscale raster image (in cycles per pixel)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29776" PostHistoryTypeId="1" PostId="10268" RevisionGUID="a8b4baa0-a9f1-4893-9a98-14048bb81c57" CreationDate="2020-09-28T12:32:59.083" UserId="14025" Text="How to calculate spatial frequency of an image just in one direction?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29777" PostHistoryTypeId="3" PostId="10268" RevisionGUID="a8b4baa0-a9f1-4893-9a98-14048bb81c57" CreationDate="2020-09-28T12:32:59.083" UserId="14025" Text="|image-processing|raster-image|spectral|fourier-transform|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29778" PostHistoryTypeId="2" PostId="10269" RevisionGUID="dc91102a-60be-412a-838f-66c924de5e6a" CreationDate="2020-09-28T12:45:14.770" UserId="13367" Text="I'm reading and implementing a paper about [Importance Sampling of Many Lights with Adaptive Tree Splitting][1]. In section 5.2 on *cluster importance for participating media*, there is a part that I don't understand: How do they compute the vectors o1, o2? I don't understand the paragraph explaining how to obtain this basis from v1, v2. Can anyone explain it?&#xD;&#xA;&#xD;&#xA;  [1]: http://aconty.com/pdf/many-lights-hpg2018.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29779" PostHistoryTypeId="1" PostId="10269" RevisionGUID="dc91102a-60be-412a-838f-66c924de5e6a" CreationDate="2020-09-28T12:45:14.770" UserId="13367" Text="&quot;Importance Sampling of Many Lights with Adaptive Tree Splitting&quot; - paper: participating media" ContentLicense="CC BY-SA 4.0" />
  <row Id="29780" PostHistoryTypeId="3" PostId="10269" RevisionGUID="dc91102a-60be-412a-838f-66c924de5e6a" CreationDate="2020-09-28T12:45:14.770" UserId="13367" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29781" PostHistoryTypeId="2" PostId="10270" RevisionGUID="40e51639-7a5d-4bfd-a155-69f0259f3fc4" CreationDate="2020-09-28T17:28:59.443" UserId="48" Text="You can take a 1D Fourier transform of a row of pixels from the image; it will give you the horizontal frequencies present in that row.&#xD;&#xA;&#xD;&#xA;You could sample one row out of the image, or else average all the rows together to get an overall picture of the horizontal frequencies." ContentLicense="CC BY-SA 4.0" />
  <row Id="29784" PostHistoryTypeId="50" PostId="10118" RevisionGUID="5e23b021-7559-449a-89ff-66e06669ade7" CreationDate="2020-09-29T01:00:20.047" UserId="-1" />
  <row Id="29785" PostHistoryTypeId="2" PostId="10271" RevisionGUID="50d2ee14-b31e-4b51-99e1-99e50774e4fd" CreationDate="2020-09-29T01:28:41.567" UserId="7462" Text="I have an obj parser that handles triangle meshes specifically. &#xD;&#xA;&#xD;&#xA;I want to extend it (and the rest of my system) to handle animations as well. However, I don't think I am ready to tackle the glTF format. Because it seems to encompass much more than what I want.&#xD;&#xA;&#xD;&#xA;I just need a simple file format that describes a mesh, some bones, and the skinning weights of the mesh vertices with respect to the bones. Plus a series of poses for the skeleton.&#xD;&#xA;&#xD;&#xA;What file format could I look into?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29786" PostHistoryTypeId="1" PostId="10271" RevisionGUID="50d2ee14-b31e-4b51-99e1-99e50774e4fd" CreationDate="2020-09-29T01:28:41.567" UserId="7462" Text="What's the simplest, open, animation format?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29787" PostHistoryTypeId="3" PostId="10271" RevisionGUID="50d2ee14-b31e-4b51-99e1-99e50774e4fd" CreationDate="2020-09-29T01:28:41.567" UserId="7462" Text="|rendering|mesh|animation|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29788" PostHistoryTypeId="2" PostId="10272" RevisionGUID="f28c2a89-00f8-4dfc-bdd2-400f8c56cbc5" CreationDate="2020-09-29T10:39:31.340" UserId="13983" Text="I'm trying to implement something like an &quot;inner glow&quot;.&#xD;&#xA;&#xD;&#xA;That is, I have an image which defines the shape of an object, and then&#xD;&#xA;I want to create overlay that is a gradient that goes from the edge of the shape&#xD;&#xA;and into the shape itself.&#xD;&#xA;In programs like Photoshop and Krita, this is called an inner glow.&#xD;&#xA;&#xD;&#xA;If I could first produce a texture which contained values that represented distance&#xD;&#xA;along the inward travel path from the edge, the rest would be easy.&#xD;&#xA;&#xD;&#xA;I want this to happen in a shader, but any general insights about the problem would be helpful, I guess.&#xD;&#xA;One idea that I was working with, was to just blur the outline, and call the result shades around the edges the &quot;distance&quot;, but this might be an unnecessarily expensive operation on the GPU, maybe not, I don't know.&#xD;&#xA;&#xD;&#xA;[![image outline][1]][1]&#xD;&#xA;&#xD;&#xA;A naive approach would be to check all distances to all other pixels, which comes out to something like 256⁴ square root calculations for a 256x256 pixel image. I believe that's not optimal. Also I don't know if that's even possible in a shader.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MjB2K.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29789" PostHistoryTypeId="1" PostId="10272" RevisionGUID="f28c2a89-00f8-4dfc-bdd2-400f8c56cbc5" CreationDate="2020-09-29T10:39:31.340" UserId="13983" Text="How do I efficiently calculate the distance to the edge of a shape?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29790" PostHistoryTypeId="3" PostId="10272" RevisionGUID="f28c2a89-00f8-4dfc-bdd2-400f8c56cbc5" CreationDate="2020-09-29T10:39:31.340" UserId="13983" Text="|shader|texture|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29791" PostHistoryTypeId="2" PostId="10273" RevisionGUID="1ff478f9-29b6-4c8e-a944-95780cb2c2c6" CreationDate="2020-09-29T13:52:50.560" UserId="1908" Text="For what it's worth, the [glTF Tutorials contain a section on Skinning](https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_020_Skins.md) that shows how the raw vertex and joint weight data feed into a vertex shader to distort the mesh.&#xD;&#xA;&#xD;&#xA;If you do design your own format to hold this, you'll need tooling to export it from 3D content creation software, as well as software to read the new format into your application.  Using an open format like glTF can grant access to existing tools, such as the [Blender glTF exporter](https://docs.blender.org/manual/en/2.90/addons/import_export/scene_gltf2.html), that can write all this data into the file, in a form that's ready to load into vertex attributes and shaders.&#xD;&#xA;&#xD;&#xA;[![How skins work](https://raw.githubusercontent.com/KhronosGroup/glTF-Tutorials/master/gltfTutorial/images/skinSkinMatrix.png)](https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_020_Skins.md)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29792" PostHistoryTypeId="2" PostId="10274" RevisionGUID="408bdb4e-a9e9-4356-aaf9-61f8e2a37340" CreationDate="2020-09-29T18:15:45.393" UserId="48" Text="A texture that stores distance from the edge of the shape, like you described, is called a &quot;distance field&quot; (you'll find lots of results if you google that phrase). Distance fields can be calculated efficiently on the GPU using the [jump flooding algorithm](https://www.comp.nus.edu.sg/~tants/jfa.html) (JFA).&#xD;&#xA;&#xD;&#xA;This is a multi-pass algorithm that works by sampling pixels at a distance of first ½ the image size, then ¼, then ⅛, and so on down to single pixels. At the end it comes out with a texture with the shortest distance from each pixel to any of the initial &quot;seed&quot; pixels you put in (which would be along the edge of your shape). For more details see the paper, or also check out [this blog post by Alan Wolfe](https://blog.demofox.org/2016/02/29/fast-voronoi-diagrams-and-distance-dield-textures-on-the-gpu-with-the-jump-flooding-algorithm/) which also has some shadertoys with example implementations.&#xD;&#xA;&#xD;&#xA;Another article which may interest you is [The Quest For Very Wide Outlines](https://medium.com/@bgolus/the-quest-for-very-wide-outlines-ba82ed442cd9) by Ben Golus, which addresses this exact issue, discusses a wide variety of GPU implementations (and settles on JFA), and addresses some of the implementation details such as using JFA on an antialiased edge." ContentLicense="CC BY-SA 4.0" />
  <row Id="29793" PostHistoryTypeId="50" PostId="9614" RevisionGUID="ba315d8b-1784-40ed-8024-2d67948cb904" CreationDate="2020-09-29T21:08:26.030" UserId="-1" />
  <row Id="29794" PostHistoryTypeId="50" PostId="9116" RevisionGUID="a8b3ed21-7e08-499b-bf5c-f6edd1da6b86" CreationDate="2020-09-30T09:06:40.657" UserId="-1" />
  <row Id="29795" PostHistoryTypeId="50" PostId="8462" RevisionGUID="48757687-1d34-4299-aed9-e4a229600014" CreationDate="2020-09-30T11:03:25.357" UserId="-1" />
  <row Id="29796" PostHistoryTypeId="2" PostId="10275" RevisionGUID="bb0f1caa-d939-40e8-80c9-076dfcbfdacc" CreationDate="2020-10-01T12:11:00.750" UserId="13273" Text="I've a question about surface deformation using Perlin noise or Simplex noise.&#xD;&#xA;You can see everywhere on google images how these results look like, if you calculate a 2D / 3D noise and move the surface in normal direction like the image in the following discussion on stackoverflow:&#xD;&#xA;https://stackoverflow.com/questions/53688083/using-analytical-perlin-noise-derivatives-on-a-3d-surface&#xD;&#xA;&#xD;&#xA;Using one noise calculation for a vertex seems to be fast, but caves can not appear. It is like generating a height map for a surface.&#xD;&#xA;&#xD;&#xA;But, has someone tried to use 3D Perlin/Simplex noise for each dimension? So that 3 times a 3D Noise is calculated and the vertex is moved in the dimension direction?&#xD;&#xA;&#xD;&#xA;I think that of cause caves can be appear and it maybe looks realistic as well.&#xD;&#xA;I've time pressure to implement some surface distortion and I am only interested in some resulting pictures, to decide using this technique or look for another one.&#xD;&#xA;&#xD;&#xA;So if someone has already implemented it, please post some resulting images. Thanks a lot!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29797" PostHistoryTypeId="1" PostId="10275" RevisionGUID="bb0f1caa-d939-40e8-80c9-076dfcbfdacc" CreationDate="2020-10-01T12:11:00.750" UserId="13273" Text="Perlin Noise, surface deformation NOT along the normal vector" ContentLicense="CC BY-SA 4.0" />
  <row Id="29798" PostHistoryTypeId="3" PostId="10275" RevisionGUID="bb0f1caa-d939-40e8-80c9-076dfcbfdacc" CreationDate="2020-10-01T12:11:00.750" UserId="13273" Text="|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29799" PostHistoryTypeId="2" PostId="10276" RevisionGUID="008bba5f-be38-4b5f-93ac-9299a47e6abd" CreationDate="2020-10-01T14:48:16.387" UserId="13321" Text="Someone else feel free to correct me as I am not 100% certain, but from what I can gather: &#xD;&#xA;&#xD;&#xA;They are describing all the normalized vectors v, which point at the ray between points v1 and v2.&#xD;&#xA;&#xD;&#xA;They are doing this using one parameter angle φ.&#xD;&#xA;&#xD;&#xA;They are essentially interpolating between two vectors o1 and o2, with the equation v = o1 cosφ + o2 sinφ&#xD;&#xA;&#xD;&#xA;o1 is simply the normalized v1. o2 is a vector at right angles with the o1 along the plane of the ray. (I think this would be calculated by cross product of o1 and N from the paper).&#xD;&#xA;&#xD;&#xA;Because this angle can sweep greater than the length of the ray defined by v1 and v2 they also define a limit Bmax so that φ always stays within the bounds of the ray.&#xD;&#xA;&#xD;&#xA;I've tried to annotate the diagram below (but I think I made a mistake and o2 would have an angle create than v1).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;They also discuss it briefly here: http://www.aconty.com/pdf/importance-sampling-lights-slides.pdf&#xD;&#xA;&#xD;&#xA;Might be worth mesaging the orinal authors to see if this is correct.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4Notm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29800" PostHistoryTypeId="2" PostId="10277" RevisionGUID="69f495ea-b867-455b-b706-d43d38e35697" CreationDate="2020-10-01T15:01:09.523" UserId="14038" Text="I copied my answer for the same OP at https://github.com/godotengine/godot/issues/19473. But this question differs slightly to the original issue report.&#xD;&#xA;&#xD;&#xA;In case you want to manually add support for VERTEX_ID, these are the changes I had to make in `3.2.3-stable` for `spatial` shaders. I wanted to use the vertex ID for creating procedural animations.&#xD;&#xA;&#xD;&#xA;In `drivers/gles3/shader_compiler_gles3.cpp` in the function `ShaderCompilerGLES3::ShaderCompilerGLES3()` :&#xD;&#xA;&#xD;&#xA;    actions[VS::SHADER_SPATIAL].renames[&quot;VERTEX_ID&quot;] = &quot;gl_VertexID&quot;;&#xD;&#xA;&#xD;&#xA;and `servers/visual/shader_types.cpp` in the function `ShaderTypes::ShaderTypes()`:&#xD;&#xA;&#xD;&#xA;    shader_modes[VS::SHADER_SPATIAL].functions[&quot;vertex&quot;].built_ins[&quot;VERTEX_ID&quot;] = constt(ShaderLanguage::TYPE_INT);&#xD;&#xA;&#xD;&#xA;Then compile the source and it should work. &#xD;&#xA;&#xD;&#xA;One caveat is that the vertex IDs reported by Godot are very different from those reported by other tools such as Blender. This is because vertices are duplicated and in a different order.&#xD;&#xA;&#xD;&#xA;I have a primitive tool working that can map the vertex animation texture generated in blender to one usable by Godot into another grayscale texture (n by 1 texture, where n is number of vertices in Godot). This saves texture memory as no data is duplicated for duplicated vertices. I first need to implement an octree before it will be usable for real-world meshes and not just a set of simple deforming cubes. Once I have that done in my spare time I will release it for free.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29801" PostHistoryTypeId="5" PostId="10277" RevisionGUID="73af1594-a781-4375-b3db-196f140bec67" CreationDate="2020-10-01T15:10:46.277" UserId="14038" Comment="added downside about using UV channel instead." Text="I copied my answer for the same OP at https://github.com/godotengine/godot/issues/19473. But this question differs slightly to the original issue report.&#xD;&#xA;&#xD;&#xA;In case you want to manually add support for VERTEX_ID, these are the changes I had to make in `3.2.3-stable` for `spatial` shaders. I wanted to use the vertex ID for creating procedural animations.&#xD;&#xA;&#xD;&#xA;In `drivers/gles3/shader_compiler_gles3.cpp` in the function `ShaderCompilerGLES3::ShaderCompilerGLES3()` :&#xD;&#xA;&#xD;&#xA;    actions[VS::SHADER_SPATIAL].renames[&quot;VERTEX_ID&quot;] = &quot;gl_VertexID&quot;;&#xD;&#xA;&#xD;&#xA;and `servers/visual/shader_types.cpp` in the function `ShaderTypes::ShaderTypes()`:&#xD;&#xA;&#xD;&#xA;    shader_modes[VS::SHADER_SPATIAL].functions[&quot;vertex&quot;].built_ins[&quot;VERTEX_ID&quot;] = constt(ShaderLanguage::TYPE_INT);&#xD;&#xA;&#xD;&#xA;Then compile the source and it should work. Some other primitives could probably be added in a similar fashion but I have not tested that yet.&#xD;&#xA;&#xD;&#xA;One caveat is that the vertex IDs reported by Godot are very different from those reported by other tools such as Blender. This is because vertices are duplicated and in a different order. Godot also only gives you two UV channels to work with. Using UV coordinates also means having a temporal component will require significantly more memory to implement as UVs will typically map sparsely onto a 2D texture, if the data is only used in the vertex shader.&#xD;&#xA;&#xD;&#xA;I have a primitive tool working that can map the vertex animation texture generated in blender to one usable by Godot into another grayscale texture (n by 1 texture, where n is number of vertices in Godot). This saves texture memory as no data is duplicated for duplicated vertices. I first need to implement an octree before it will be usable for real-world meshes and not just a set of simple deforming cubes. Once I have that done in my spare time I will release it for free.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29802" PostHistoryTypeId="2" PostId="10278" RevisionGUID="b57b8fe0-5083-4c13-a8d9-11362a210a31" CreationDate="2020-10-01T15:58:25.060" UserId="506" Text="You can do this, and the results can be interesting, but they’re pretty far from looking like realistic terrain. Here’s a plane deformed with 3D simplex noise (Perlin doesn’t look significantly better):&#xD;&#xA;&#xD;&#xA;![warped plane](https://i.stack.imgur.com/wNOb9.jpg)&#xD;&#xA;&#xD;&#xA;The issue is that there’s no volume to the surface, per se, and nothing preventing it from passing through itself. Deforming it only along the normal vector mostly avoids that. For a surface that looks like terrain, with actual caves, you’ll probably need some kind of voxel system like the one described in [this GPU Gems article](https://developer.nvidia.com/gpugems/gpugems3/part-i-geometry/chapter-1-generating-complex-procedural-terrains-using-gpu)." ContentLicense="CC BY-SA 4.0" />
  <row Id="29803" PostHistoryTypeId="50" PostId="9781" RevisionGUID="ad014e8a-a48c-4e4b-9774-151dfd9d67b9" CreationDate="2020-10-01T17:01:30.227" UserId="-1" />
  <row Id="29804" PostHistoryTypeId="2" PostId="10279" RevisionGUID="1fbc5dd5-2a93-4b4b-9ec1-f00784245d5b" CreationDate="2020-10-01T17:36:19.123" UserId="10129" Text="Let's take a look at this blog article - https://schuttejoe.github.io/post/ggximportancesamplingpart1/ and image presented as a result of implementing it:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Inside above link, you can see description for this image saying&#xD;&#xA;&#xD;&#xA;&gt; In order to have something to compare to on the left I generated an image by importance sampling a cosine distribution and on the right I generated an image using the technique described above. [...]&#xD;&#xA;&#xD;&#xA;Based on the fact that image on the right was derived based on GGX pdf, how was image on the left generated? I assume we have our standard equation but what does it mean that it's generated with *importance sampling a cosine distribution*?&#xD;&#xA;$$&#xD;&#xA;f(w_i,w_o) = \frac{F(w_i, w_m) ~ G_2(w_i,wo_,w_m) D(w_m)}{4 ~ |w_i \cdot w_g| ~ |w_o \cdot w_g|} * PDF[?]&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xzrCR.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29805" PostHistoryTypeId="1" PostId="10279" RevisionGUID="1fbc5dd5-2a93-4b4b-9ec1-f00784245d5b" CreationDate="2020-10-01T17:36:19.123" UserId="10129" Text="Importance sampling a cosine distribution" ContentLicense="CC BY-SA 4.0" />
  <row Id="29806" PostHistoryTypeId="3" PostId="10279" RevisionGUID="1fbc5dd5-2a93-4b4b-9ec1-f00784245d5b" CreationDate="2020-10-01T17:36:19.123" UserId="10129" Text="|raytracing|brdf|sampling|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29807" PostHistoryTypeId="2" PostId="10280" RevisionGUID="3df877a4-fb89-4893-af3a-4157387808c2" CreationDate="2020-10-01T19:25:27.477" UserId="48" Text="You can sample using absolutely any distribution you want, as long as you weight the results by dividing by the pdf of the sampled distribution. It will converge to the right answer (as long as the distribution is nonzero everywhere that you want to integrate). Different distributions will give different amounts of variance though. The trick with importance sampling is to find a distribution that minimizes variance while still being cheap to compute. A distribution similar to the shape of the function you're integrating, or equal to some factor of that function (so that it cancels when you divide), works best. In other words you try to guide the sampling toward areas that are more important to the result, hence, &quot;importance&quot; sampling.&#xD;&#xA;&#xD;&#xA;So what the author is saying is the image on the left was sampled with $\omega_o$ (or maybe $\omega_m$, I'm not sure) drawn from a cosine hemisphere distribution, just as an example of a distribution that does _not_ match the BRDF very well. Then they calculate the samples as $f(\omega_i, \omega_o) / p_{\cos}(\omega_o)$ where $p_{\cos}$ is the pdf for the cosine distribution. This is just to show you that it gives the &quot;correct&quot; result, but with a ton of variance. (Although it looks like there are some black areas on the left image that suggest it's not really converging to the correct answer...but let's assume that's a bug.)&#xD;&#xA;&#xD;&#xA;Then the image on the right is sampled with (presumably) $\omega_m$ drawn from a distribution matching the $D(\omega_m)$ term from the BRDF. Then when you calculate the BRDF you can leave out the $D$ factor since it's canceled by the $D$ factor in the pdf. (The pdf probably still has some normalization and some conversion of probability from $\omega_m$ to $\omega_o$, so you still have to divide by those factors.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29808" PostHistoryTypeId="2" PostId="10281" RevisionGUID="f9032687-eea6-4c19-aeae-7f05016df59c" CreationDate="2020-10-01T21:35:59.123" UserId="14040" Text="In an HSV model, the Hue is the color model. So when we split the image or remove H, should we get an image without rgb colors? &#xD;&#xA;&#xD;&#xA;Similarly, saturation is the gray shade. I read that images become more grey and faded in this case. So what should happen when we remove both, hue and saturation, leaving only the vue component behind? &#xD;&#xA;&#xD;&#xA;Any example images would be nice." ContentLicense="CC BY-SA 4.0" />
  <row Id="29809" PostHistoryTypeId="1" PostId="10281" RevisionGUID="f9032687-eea6-4c19-aeae-7f05016df59c" CreationDate="2020-10-01T21:35:59.123" UserId="14040" Text="splitting hue &amp; saturating and leaving value behind" ContentLicense="CC BY-SA 4.0" />
  <row Id="29810" PostHistoryTypeId="3" PostId="10281" RevisionGUID="f9032687-eea6-4c19-aeae-7f05016df59c" CreationDate="2020-10-01T21:35:59.123" UserId="14040" Text="|image-processing|color|image|color-science|color-separation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29811" PostHistoryTypeId="50" PostId="10177" RevisionGUID="c4c28eca-2ac2-4344-b9bc-1d62a34d49c1" CreationDate="2020-10-02T02:04:40.480" UserId="-1" />
  <row Id="29812" PostHistoryTypeId="2" PostId="10282" RevisionGUID="6570702b-7cf2-40b0-a98f-d7b40507c14b" CreationDate="2020-10-02T08:56:28.997" UserId="10129" Text="https://alloyui.com/examples/color-picker/hsv.html - it would be the best for you to play a little with HSV color picker.&#xD;&#xA;&#xD;&#xA;Problem of color picking with HSV boils down to 2D coordinates (H, S) with additional parameter V. Therefore, you are using H as x-axis value ans S as y-axis value. If you drop H and S (set them to 0), you basically have white color and with V, you can choose grey scale lying between white and black." ContentLicense="CC BY-SA 4.0" />
  <row Id="29813" PostHistoryTypeId="50" PostId="9789" RevisionGUID="869c62a7-4e74-4b2d-a396-312cb4003d9c" CreationDate="2020-10-02T18:08:45.960" UserId="-1" />
  <row Id="29814" PostHistoryTypeId="2" PostId="10283" RevisionGUID="251bfa2f-ee08-40a2-b428-ede1d84ffaa1" CreationDate="2020-10-02T18:21:15.477" UserId="48" Text="Removing hue and saturation (&quot;desaturating&quot;) leads to a grayscale image with the same luminance as the original colors, for instance:&#xD;&#xA;&#xD;&#xA;![original image][1]&#xD;&#xA;![grayscale image][2]\&#xD;&#xA;(source: my own photo)&#xD;&#xA;&#xD;&#xA;It is not possible to remove hue alone without removing saturation, as any saturated color must be saturated in some direction (hue). Nor is it possible to &quot;split&quot; the image into HSV &quot;components&quot; in quite the way you can split into RGB components. Hue works like an angle of rotation around the &quot;color wheel&quot;, while saturation is the radius from the center:&#xD;&#xA;&#xD;&#xA;![hue/saturation color wheel][3]\&#xD;&#xA;(image from [here](https://www.highend.com/pub/support/controllers/documents/html/en/sect-colour_matching.htm))&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/As70m.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/i9Lqz.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/WQRVt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29815" PostHistoryTypeId="50" PostId="9791" RevisionGUID="5174d275-9ab3-4fa3-ba94-a5b8f4821b3c" CreationDate="2020-10-02T21:00:50.083" UserId="-1" />
  <row Id="29816" PostHistoryTypeId="2" PostId="10284" RevisionGUID="2dab3163-4bdc-4dcf-98b2-8c2c4d4ef7b6" CreationDate="2020-10-03T16:44:52.613" UserId="7913" Text="I'm reading PBRT and am stuck in chapter 5.4 about radiometry. In particular:&#xD;&#xA;&#xD;&#xA;We define the _irradiance_ as the average density flux arriving at a surface with units $\frac{W}{m^2}$. So for a point light source, we have: $E = \frac{\Phi}{4 \pi r^2}$ since the area of a sphere is $4 \pi r^2$. Where $\Phi$ is the flux or power.&#xD;&#xA;&#xD;&#xA;A (to me) similar concept is _intensity_ which is the amount of power per angle. Again, for a sphere with a point light at the center, this is $I = \frac{\Phi}{4 \pi r^2}$ with the unit $[\frac{W}{sr}]$ (watt over steradian)&#xD;&#xA;&#xD;&#xA;Now, the book defines _radiance_ for a point $p$ as $L = \frac{d\Phi}{d\omega dA^\perp}$ in units $[\frac{W}{sr\cdot m^2}]$. Here, $\omega$ is the direction where the light comes from, $A^\perp$ is the projected are of $A$ as seen here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This means that practically, when I implement a point light source with a given power that shines at a point $p$, I need to do the following to arrive at radiance:&#xD;&#xA;- Divide by $4 \pi r^2$ to convert power into $[\frac{W}{sr}]$, or in other words, intensity.&#xD;&#xA;- Given intensity, I need to divide it by $4 \pi r^2$ and multiply by $\cos \theta$ to arrive at $[\frac{W}{sr\cdot m^2}]$, the final radiance. The multiplication by $\cos \theta$ is to project $A$ to $A^\perp$ and is the dot product of the surface normal $n$ with the direction $w$ (as both are normalized).&#xD;&#xA;&#xD;&#xA;For both calculations, $r$ is the distance between the light source and my point $p$.&#xD;&#xA;&#xD;&#xA;However, when I look at the source, this is not what happens. The point light returns intensity divided by $r^2$ as seen [here][2]:&#xD;&#xA;```&#xD;&#xA;return I / DistanceSquared(pLight, ref.p);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and the integrator then multiplies it with the dot product (and the brdf) [in the whitted integrator][3]&#xD;&#xA;```&#xD;&#xA;L += f * Li * AbsDot(wi, n) / pdf;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So what is wrong in my derivation? Why do we &quot;only&quot; divide once by $4\pi r^2$ (to get the Intensity I) and not twice? Aren't we missing either the power per area or the power per steradian? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;sources:&#xD;&#xA;http://www.pbr-book.org/3ed-2018/Color_and_Radiometry/Radiometry.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/co4VV.png&#xD;&#xA;  [2]: https://github.com/mmp/pbrt-v3/blob/master/src/lights/point.cpp#L44&#xD;&#xA;  [3]: https://github.com/mmp/pbrt-v3/blob/master/src/integrators/whitted.cpp#L79" ContentLicense="CC BY-SA 4.0" />
  <row Id="29817" PostHistoryTypeId="1" PostId="10284" RevisionGUID="2dab3163-4bdc-4dcf-98b2-8c2c4d4ef7b6" CreationDate="2020-10-03T16:44:52.613" UserId="7913" Text="Deriving radiance from irradiance and intensity" ContentLicense="CC BY-SA 4.0" />
  <row Id="29818" PostHistoryTypeId="3" PostId="10284" RevisionGUID="2dab3163-4bdc-4dcf-98b2-8c2c4d4ef7b6" CreationDate="2020-10-03T16:44:52.613" UserId="7913" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29819" PostHistoryTypeId="2" PostId="10285" RevisionGUID="5bb2952e-9229-4b99-ad7b-4fb6b538156b" CreationDate="2020-10-03T18:18:31.463" UserId="48" Text="Your definition for radiant intensity is wrong: it should be just $\Phi / 4\pi$. There are only $4\pi$ steradians in a sphere no matter how big it is, so $r$ doesn't come into it." ContentLicense="CC BY-SA 4.0" />
  <row Id="29820" PostHistoryTypeId="5" PostId="10285" RevisionGUID="0c24e352-6cbc-4809-8eb7-f3daff22b6b3" CreationDate="2020-10-03T18:28:36.483" UserId="48" Comment="added 453 characters in body; added 69 characters in body" Text="Your definition for radiant intensity is wrong: it should be just $\Phi / 4\pi$. There are only $4\pi$ steradians in a sphere no matter how big it is, so $r$ doesn't come into it.&#xA;&#xA;Also note that you can't calculate _radiance_ for a point source—it would be infinite, due to the fact the point source emits a finite amount of flux compressed into zero size. It subtends zero solid angle, from the receiver's point of view, so the $d\omega$ factor in the denominator of radiance would be zero. The usable quantities are radiant intensity in a certain direction from the point source (which could vary with direction, for a non-omnidirectional light), and irradiance in a certain direction and distance." ContentLicense="CC BY-SA 4.0" />
  <row Id="29821" PostHistoryTypeId="5" PostId="10285" RevisionGUID="a883c848-e5af-46fa-90b2-a0e6c65f9caa" CreationDate="2020-10-03T18:43:43.177" UserId="48" Comment="added 791 characters in body; added 246 characters in body" Text="Your definition for radiant intensity is wrong: it should be just $\Phi / 4\pi$. There are only $4\pi$ steradians in a sphere no matter how big it is, so $r$ doesn't come into it.&#xA;&#xA;Also note that you can't calculate _radiance_ for a point source—it would be infinite, due to the fact the point source emits a finite amount of flux compressed into zero size. It subtends zero solid angle, from the receiver's point of view, so the $d\omega$ factor in the denominator of radiance would be zero. The usable quantities are radiant intensity in a certain direction from the point source (which could vary with direction, for a non-omnidirectional light), and irradiance in a certain direction and distance. As you've seen, irradiance is obtained from radiant intensity by dividing by $r^2$—you could think of this as &quot;area per steradian&quot;, as it's the conversion factor from $4\pi$ steradians to $4\pi r^2$ area of a sphere; then the units work out.&#xA;&#xA;Where radiance would actually show up is when dealing with an area light rather than a point light. Then you would have the flux being distributed over a finite solid angle from the receiver's point of view, and you'd get the incident irradiance by integrating the light's radiance over that solid angle. The emitted radiance would be $\Phi/(2\pi A_\text{light})$, assuming it's emitted uniformly over the surface of the light and into all directions from each point. This is only $2\pi$ since it's only emitting into the outward-facing hemisphere. Also note that you don't do any division by $r^2$ for radiance—with area lights, the distance attenuation comes naturally as a result of the light subtending less solid angle from the receiver's point of view, when the receiver is farther away." ContentLicense="CC BY-SA 4.0" />
  <row Id="29826" PostHistoryTypeId="2" PostId="10287" RevisionGUID="c4f47fcd-8c34-4cff-87cf-b902dae5d20a" CreationDate="2020-10-04T12:59:38.320" UserId="14044" Text="Assuming I wanted to rasterize a scene of triangles that are all connected that is similar to the image below, what would be an efficient way to do it on a GPU and a CPU? The triangles can be of any size. Names of any methods utilized or any advice is appreciated!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/00UNC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29827" PostHistoryTypeId="1" PostId="10287" RevisionGUID="c4f47fcd-8c34-4cff-87cf-b902dae5d20a" CreationDate="2020-10-04T12:59:38.320" UserId="14044" Text="Efficient methods to rasterize a scene of connected triangles" ContentLicense="CC BY-SA 4.0" />
  <row Id="29828" PostHistoryTypeId="3" PostId="10287" RevisionGUID="c4f47fcd-8c34-4cff-87cf-b902dae5d20a" CreationDate="2020-10-04T12:59:38.320" UserId="14044" Text="|rasterizer|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29835" PostHistoryTypeId="2" PostId="10290" RevisionGUID="b66395c7-9080-4440-ad5f-9e479b0eafa8" CreationDate="2020-10-06T01:04:20.450" UserId="159" Text="It's an interesting question, because the advice changes over time. Having said that:&#xD;&#xA;&#xD;&#xA; - On a GPU, by far the most efficient way, as Nathan Reed said in the comment, is to use the rasterisation hardware because that is that it is designed for.&#xD;&#xA; - On a CPU, one of the most efficient ways is to more-or-less mimic what rasterisation hardware does.&#xD;&#xA;&#xD;&#xA;GPU vendors are understandably quiet about the specifics of their hardware design, but the basic idea hasn't changed for a few decades.&#xD;&#xA;&#xD;&#xA; 1. Conceptually split the screen into tiles, e.g. of 8 by 8 pixels.&#xD;&#xA; 2. Traverse the tiles which overlap with a triangle using some variant on [Pineda's method][1].&#xD;&#xA; 3. For each fragment, compute a bit mask to find the exact pixels (or samples, if you're subsampling) in the bucket which are inside the triangle, using half-plane calculations. In GPU speak, the samples in a tile which are inside the triangle are called a *fragment*.&#xD;&#xA; 4. Do whatever processing is needed on the fragment.&#xD;&#xA;&#xD;&#xA;On a modern CPU, fragment processing can be made extremely efficient by using vector instructions.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.drexel.edu/~david/Classes/Papers/comp175-06-pineda.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29836" PostHistoryTypeId="5" PostId="10290" RevisionGUID="d9c965c3-7f13-419d-b2af-8af284da9d28" CreationDate="2020-10-06T01:50:19.110" UserId="159" Comment="added 40 characters in body" Text="It's an interesting question, because the advice changes over time. Having said that:&#xD;&#xA;&#xD;&#xA; - On a GPU, by far the most efficient way, as Nathan Reed said in the comment, is to use the rasterisation hardware because that is that it is designed for.&#xD;&#xA; - On a CPU, one of the most efficient ways is to more-or-less mimic what rasterisation hardware does.&#xD;&#xA;&#xD;&#xA;GPU vendors are understandably quiet about the specifics of their hardware design, but the basic idea hasn't changed for a few decades.&#xD;&#xA;&#xD;&#xA; 1. Conceptually split the screen into tiles, e.g. of 8 by 8 pixels.&#xD;&#xA; 2. Traverse the tiles which overlap with a triangle using some variant on [Pineda's method][1].&#xD;&#xA; 3. For each fragment, compute a bit mask to find the exact pixels (or samples, if you're subsampling) in the bucket which are inside the triangle, using half-plane calculations. In GPU speak, the samples in a tile which are inside the triangle are called a *fragment*.&#xD;&#xA; 4. Do whatever processing is needed on the fragment.&#xD;&#xA;&#xD;&#xA;On a modern CPU, fragment processing (including the half-space calculations) can be made extremely efficient by using vector instructions.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.drexel.edu/~david/Classes/Papers/comp175-06-pineda.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29837" PostHistoryTypeId="2" PostId="10291" RevisionGUID="3892efba-45a4-4a6a-bc2f-54e0be4b684c" CreationDate="2020-10-06T07:03:27.517" UserId="14051" Text="I've been playing around with OpenGL and I'm trying to build out my own UI component library containing things like buttons, text views, labels, views, etc. Eventually I want to abstract it **similar** to iOS UIKit where I can just call `UIButton()` or `UIView()` and just generate that UI element. Before I let my imagination go, I am still trying to understand the most effective way to actually develop the initial library. Eventually I want it to be a combination of 2D and 3D graphics. Should I build all the components in say Blender and export the bmp file as a texture and use that? I don't think that's a viable option because eventually I want to add text in runtime to the UI elements and eventually re-shape the size based on constantly changing variables. Even better, is there already a library with this extracted? Similar to CoreGraphics/UIKit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29838" PostHistoryTypeId="1" PostId="10291" RevisionGUID="3892efba-45a4-4a6a-bc2f-54e0be4b684c" CreationDate="2020-10-06T07:03:27.517" UserId="14051" Text="Creating a UI component library from scratch" ContentLicense="CC BY-SA 4.0" />
  <row Id="29839" PostHistoryTypeId="3" PostId="10291" RevisionGUID="3892efba-45a4-4a6a-bc2f-54e0be4b684c" CreationDate="2020-10-06T07:03:27.517" UserId="14051" Text="|opengl|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29840" PostHistoryTypeId="2" PostId="10292" RevisionGUID="cd466a3e-83d1-4194-a3d6-d61a9da5e9b9" CreationDate="2020-10-06T09:54:39.123" UserId="10129" Text="https://schuttejoe.github.io/post/ggximportancesamplingpart1/ - I have problem implementing this method. Somebody asked question about this before ( https://computergraphics.stackexchange.com/questions/8465/cant-understand-the-importance-sampling-ggx ) but it doesn't fully answer my question/problem.&#xD;&#xA;&#xD;&#xA;Above blog post describe importance sampling method based on importance sampling NDF. Let's start with Cook-Torrance BRDF:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r = \frac{F(w_i, w_m) ~ G_2(w_i, w_o, w_m) ~ D(w_m)}{4 ~ |w_i \cdot w_g| ~ |w_o \cdot w_g|}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;After finding PDF for Normal Distribution Function and applying&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;|w_i \cdot w_g|&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;term from rendering equation + found PDF, we have final equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{F(w_i, w_m) ~ G_2(w_i, w_o, w_m) ~ |w_o \cdot w_m|}{|w_o \cdot w_g| ~ |w_m \cdot w_g|}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I'm adding final equation just for completion sake. All transformations are rather long and it's better to check blog post that I've sent. At the end of post, there is code that should be working correctly. However, it doesn't give correct results in my case and my suspicion is that I'm filling gaps in a wrong way:&#xD;&#xA;&#xD;&#xA;I'm using Correlated Multi-Jittered Sampling here:&#xD;&#xA;&#xD;&#xA;    float SmithGGXMaskingShadowing(float3 n, float3 l, float3 v, float a2)&#xD;&#xA;    {&#xD;&#xA;    	float dotNL = saturate(dot(n, l));&#xD;&#xA;    	float dotNV = saturate(dot(n, v));&#xD;&#xA;    &#xD;&#xA;    	float denomA = dotNV * sqrt(a2 + (1.0f - a2) * dotNL * dotNL);&#xD;&#xA;    	float denomB = dotNL * sqrt(a2 + (1.0f - a2) * dotNV * dotNV);&#xD;&#xA;    &#xD;&#xA;    	return 2.0f * dotNL * dotNV / (denomA + denomB);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float a2 = roughness * roughness;&#xD;&#xA;    float theta = acos(sqrt((1.0f - brdfSample.x) / ((a2 - 1.0f) * brdfSample.x + 1.0f)));&#xD;&#xA;    float phi = 2.0f * PI * brdfSample.y;&#xD;&#xA;    &#xD;&#xA;    float3 normalTS = float3(0, 1, 0);&#xD;&#xA;    &#xD;&#xA;    float3 wo = -incomingRayDirWS;&#xD;&#xA;    float3 wm = float3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));&#xD;&#xA;    float3 wi = 2.0f * dot(wo, wm) * wm - wo;&#xD;&#xA;    &#xD;&#xA;    float3 F = Specular_F_Schlick(specularAlbedo.rgb, saturate(dot(wi, wm)));&#xD;&#xA;    float G = SmithGGXMaskingShadowing(wm, wi, wo, a2);&#xD;&#xA;    float weight = abs(dot(wo, wm) / (dot(normalTS, wo) * dot(normalTS, wm)));&#xD;&#xA;    &#xD;&#xA;    rayDirWS = normalize(mul(wi, tangentToWorld));&#xD;&#xA;    &#xD;&#xA;    if (dot(normalTS, wi) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)&#xD;&#xA;    	throughput = F * G * weight;&#xD;&#xA;    else&#xD;&#xA;    	throughput = 0.0f;&#xD;&#xA;&#xD;&#xA;My main concern is - am I using normal in tangent space (w_g) in a correct way? Schutte Joe mentions in a comment that:&#xD;&#xA;&#xD;&#xA;&gt;   // -- Ensure our sample is in the upper hemisphere&#xD;&#xA;   // -- Since we are in tangent space with a y-up coordinate&#xD;&#xA;   // -- system BsdfNDot(wi) simply returns wi.y&#xD;&#xA;&#xD;&#xA;That's why I decided to use w_g (or normalTS) as float3(0, 1, 0). &#xD;&#xA;&#xD;&#xA;Here is how it looks for 1024 samples with path length equal 4:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In comparison, here is method based on visible normals described here - https://schuttejoe.github.io/post/ggximportancesamplingpart2/ ; For 1024 samples, path length 4, results are much better. However, based on data provide by author of the post, there shouldn't be that much difference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vIytn.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/8dGxb.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29841" PostHistoryTypeId="1" PostId="10292" RevisionGUID="cd466a3e-83d1-4194-a3d6-d61a9da5e9b9" CreationDate="2020-10-06T09:54:39.123" UserId="10129" Text="Importance sampling GGX NDF - fireflies and bright final result" ContentLicense="CC BY-SA 4.0" />
  <row Id="29842" PostHistoryTypeId="3" PostId="10292" RevisionGUID="cd466a3e-83d1-4194-a3d6-d61a9da5e9b9" CreationDate="2020-10-06T09:54:39.123" UserId="10129" Text="|raytracing|pathtracing|hlsl|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29843" PostHistoryTypeId="5" PostId="10292" RevisionGUID="07edb01b-fd4f-4f7a-8802-ca936fe3e72d" CreationDate="2020-10-06T13:21:42.520" UserId="10129" Comment="added 167 characters in body" Text="https://schuttejoe.github.io/post/ggximportancesamplingpart1/ - I have problem implementing this method. Somebody asked question about this before ( https://computergraphics.stackexchange.com/questions/8465/cant-understand-the-importance-sampling-ggx ) but it doesn't fully answer my question/problem.&#xD;&#xA;&#xD;&#xA;Above blog post describe importance sampling method based on importance sampling NDF. Let's start with Cook-Torrance BRDF:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r = \frac{F(w_i, w_m) ~ G_2(w_i, w_o, w_m) ~ D(w_m)}{4 ~ |w_i \cdot w_g| ~ |w_o \cdot w_g|}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;After finding PDF for Normal Distribution Function and applying&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;|w_i \cdot w_g|&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;term from rendering equation + found PDF, we have final equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{F(w_i, w_m) ~ G_2(w_i, w_o, w_m) ~ |w_o \cdot w_m|}{|w_o \cdot w_g| ~ |w_m \cdot w_g|}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I'm adding final equation just for completion sake. All transformations are rather long and it's better to check blog post that I've sent. At the end of post, there is code that should be working correctly. However, it doesn't give correct results in my case and my suspicion is that I'm filling gaps in a wrong way:&#xD;&#xA;&#xD;&#xA;I'm using Correlated Multi-Jittered Sampling here:&#xD;&#xA;&#xD;&#xA;    float SmithGGXMaskingShadowing(float3 n, float3 l, float3 v, float a2)&#xD;&#xA;    {&#xD;&#xA;    	float dotNL = saturate(dot(n, l));&#xD;&#xA;    	float dotNV = saturate(dot(n, v));&#xD;&#xA;    &#xD;&#xA;    	float denomA = dotNV * sqrt(a2 + (1.0f - a2) * dotNL * dotNL);&#xD;&#xA;    	float denomB = dotNL * sqrt(a2 + (1.0f - a2) * dotNV * dotNV);&#xD;&#xA;    &#xD;&#xA;    	return 2.0f * dotNL * dotNV / (denomA + denomB);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float a2 = roughness * roughness;&#xD;&#xA;    float theta = acos(sqrt((1.0f - brdfSample.x) / ((a2 - 1.0f) * brdfSample.x + 1.0f)));&#xD;&#xA;    float phi = 2.0f * PI * brdfSample.y;&#xD;&#xA;    &#xD;&#xA;    float3 normalTS = float3(0, 1, 0);&#xD;&#xA;    &#xD;&#xA;    float3 wo = -incomingRayDirTS;&#xD;&#xA;    float3 wm = float3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));&#xD;&#xA;    float3 wi = 2.0f * dot(wo, wm) * wm - wo;&#xD;&#xA;    &#xD;&#xA;    float3 F = Specular_F_Schlick(specularAlbedo.rgb, saturate(dot(wi, wm)));&#xD;&#xA;    float G = SmithGGXMaskingShadowing(wm, wi, wo, a2);&#xD;&#xA;    float weight = abs(dot(wo, wm) / (dot(normalTS, wo) * dot(normalTS, wm)));&#xD;&#xA;    &#xD;&#xA;    rayDirWS = normalize(mul(wi, tangentToWorld));&#xD;&#xA;    &#xD;&#xA;    if (dot(normalTS, wi) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)&#xD;&#xA;    	throughput = F * G * weight;&#xD;&#xA;    else&#xD;&#xA;    	throughput = 0.0f;&#xD;&#xA;&#xD;&#xA;My main concern is - am I using normal in tangent space (w_g) in a correct way? Schutte Joe mentions in a comment that:&#xD;&#xA;&#xD;&#xA;&gt;   // -- Ensure our sample is in the upper hemisphere&#xD;&#xA;   // -- Since we are in tangent space with a y-up coordinate&#xD;&#xA;   // -- system BsdfNDot(wi) simply returns wi.y&#xD;&#xA;&#xD;&#xA;That's why I decided to use w_g (or normalTS) as float3(0, 1, 0). &#xD;&#xA;&#xD;&#xA;Here is how it looks for 1024 samples with path length equal 4:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In comparison, here is method based on visible normals described here - https://schuttejoe.github.io/post/ggximportancesamplingpart2/ ; For 1024 samples, path length 4, results are much better. However, based on data provide by author of the post, there shouldn't be that much difference:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;Edit: @B_old is right, I mixed TS and WS. I present corrected results above -   image is slightly better but still has very high variance and some bright spots.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3qJ0l.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/8dGxb.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29844" PostHistoryTypeId="50" PostId="9146" RevisionGUID="51006c3e-c82a-4a4b-ba84-17e770020738" CreationDate="2020-10-06T17:05:15.547" UserId="-1" />
  <row Id="29845" PostHistoryTypeId="50" PostId="9409" RevisionGUID="47e5b563-d374-4e40-97de-776c539ae78e" CreationDate="2020-10-06T20:07:35.747" UserId="-1" />
  <row Id="29846" PostHistoryTypeId="5" PostId="10290" RevisionGUID="3d50c5dc-605b-4685-af6d-c365563a8510" CreationDate="2020-10-06T23:11:06.037" UserId="159" Comment="Fixing a typo" Text="It's an interesting question, because the advice changes over time. Having said that:&#xD;&#xA;&#xD;&#xA; - On a GPU, by far the most efficient way, as Nathan Reed said in the comment, is to use the rasterisation hardware because that is that it is designed for.&#xD;&#xA; - On a CPU, one of the most efficient ways is to more-or-less mimic what rasterisation hardware does.&#xD;&#xA;&#xD;&#xA;GPU vendors are understandably quiet about the specifics of their hardware design, but the basic idea hasn't changed for a few decades.&#xD;&#xA;&#xD;&#xA; 1. Conceptually split the screen into tiles, e.g. of 8 by 8 pixels.&#xD;&#xA; 2. Traverse the tiles which overlap with a triangle using some variant on [Pineda's method][1].&#xD;&#xA; 3. For each tile, compute a bit mask to find the exact pixels (or samples, if you're subsampling) in the bucket which are inside the triangle, using half-plane calculations. In GPU speak, the samples in a tile which are inside the triangle are called a *fragment*.&#xD;&#xA; 4. Do whatever processing is needed on the fragment.&#xD;&#xA;&#xD;&#xA;On a modern CPU, fragment processing (including the half-space calculations) can be made extremely efficient by using vector instructions.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.drexel.edu/~david/Classes/Papers/comp175-06-pineda.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="29847" PostHistoryTypeId="2" PostId="10293" RevisionGUID="2918906d-bb55-44af-9917-db389da11fe2" CreationDate="2020-10-08T02:30:57.013" UserId="13456" Text="I managed to fix it. It was indeed related to repeating random sequences. &#xD;&#xA;The problem was the following. `curandState* randState` is an array of `curandState`s, and most calls to `curand_*` require a pointer of a `curandState`.&#xD;&#xA;I was sending the `randState`, the array, to `curand_*` functions and not for example, a pointer of one of its members.&#xD;&#xA;Now most of my images are like this: [![current image output][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/asZM7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29848" PostHistoryTypeId="2" PostId="10294" RevisionGUID="dcb1f9be-79b9-4cc1-8ef8-09ffb7d70b23" CreationDate="2020-10-08T08:26:56.167" UserId="10129" Text="**Yes, throughput doesn't have to be in range [0, 1].** That's a reason why you have to use exposure settings, because for differente accumulation time, brightness of an image might differ. Nathan Reed described it in details here - https://computergraphics.stackexchange.com/a/10244/10129&#xD;&#xA;&#xD;&#xA;You final results and number of fireflies and bright surfaces, depends on PDF that you'll be using. By using Normal Distribution Function PDF, you'll get good results, because NDF is the most determining factor of BRDF shape. Relate to this blog post for details - https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;___&#xD;&#xA;Back to throughput range. Assuming that you're sampling based on NDF, you'll get fireflies in case of having values in specific range, when light source is shining from very low angle and you're looking directly at the object. Therefore, your denominator might be much greater than nominator and result in small PDF causing fireflies:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;p_i(w_m, w_o) = \frac{D(w_m)(w_g \cdot w_i)}{4|w_g \cdot w_m|}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Since 2014, Heitz was working on BSDFs, presenting good results in same year by sampling visible normals [2]. In 2017, he published much simpler, faster and better paper, improving his method [3]. There are also 2015 and 2016 papers in related field, but I haven't read them, but it might be beneficial if you're interested in BSDF. I would recommend checking his first 2014's work [1] where he explains physical assumption on which BRDF is based. It's worth knowing, what NDF and Geometry Shadowing exactly means in BRDF.&#xD;&#xA;&#xD;&#xA;Also, there is a lot of good reading in pbrt book, especially:&#xD;&#xA;&#xD;&#xA; - http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Sampling_Reflection_Functions.html#MicrofacetBxDFs&#xD;&#xA; - http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html&#xD;&#xA; - http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Importance_Sampling.html&#xD;&#xA; - For more advanced method, I think it'd be worth reading about Russian Roulette and more efficient Path Tracing algorithms like Bidirectional Path Tracing, Metropolis Light Tracing and Photon Mapping methods &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gg4J4.png&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;(1) Eric Heitz - Understanding the Masking-Shadowing Functionin Microfacet-Based BRDFs http://jcgt.org/published/0003/02/03/paper.pdf &#xD;&#xA;&#xD;&#xA;(2) Eric Heitz, Eugene d’Eon - Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals https://hal.inria.fr/hal-00996995v1/document &#xD;&#xA;&#xD;&#xA;(3) Eric Heitz - A Simpler and Exact Sampling Routine for the GGXDistribution of Visible Normals https://hal.archives-ouvertes.fr/hal-01509746/document " ContentLicense="CC BY-SA 4.0" />
  <row Id="29849" PostHistoryTypeId="5" PostId="9809" RevisionGUID="c441ee1c-f7f6-4af9-aeaa-c1da301b84d2" CreationDate="2020-10-08T08:32:16.083" UserId="13225" Comment="deleted 3 characters in body" Text="When ray tracing, I find it intuitively clear that deeper paths have a lower contribution to the overal picture than shorter paths. This is the main reason why it is generally okay to render a picture only to a certain depth, but I am currently not able to prove this.&#xD;&#xA;&#xD;&#xA;Formally, we can write the rendering equation as&#xD;&#xA;&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o(\vec{p}_0, \omega_0) &amp;= L_e(\vec{p}_0, \omega_0) \\&#xD;&#xA;    &amp;+ \int_{\Omega} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} L_e(\vec{p}_1, \omega_1) \text{d} \omega_1 \\&#xD;&#xA;    &amp;+ \int_{\Omega^2} f_r(\vec{p}_0, \omega_0, -\omega_1) \cos{\theta_1} f_r(\vec{p}_1, \omega_1, -\omega_2) \cos{\theta_2} L_e(\vec{p}_2, \omega_2) \text{d} \omega_1 \text{d} \omega_2 \\&#xD;&#xA;    &amp;+ \dots \,,&#xD;&#xA;\end{align*}&#xD;&#xA;where $\vec{p}_{j+1}$ is defined as the intersection of a ray with origin $\vec{p}_j$ and direction $-\omega_{j+1}$ and $\theta_{j+1}$ is the angle between the normal of the surface at $\vec{p}_j$ and $-\omega_{j+1}$. Each term represents the radiance contribution of respectively paths with depth 0, 1, 2, and so on. Let's denote the contribution of depth $d$ with $L_o^{(d)}(\vec{p}_0, \omega_0)$. **I suspect that, under mild conditions on the scene, the contributions of these terms will asymptotically decrease exponentially:** $$L_o^{(d)}(\vec{p}_0, \omega_0) = \mathcal{O}(t^d) \,\text{ as } d \rightarrow \infty$$ for some $t$ with $0 &lt; t &lt; 1$, where I have used the big-O notation.&#xD;&#xA;&#xD;&#xA;Of course, I expect this only to hold when the scene is somehow &quot;realistic&quot;, which I define as follows.&#xD;&#xA;&#xD;&#xA;Firstly, all light sources should have only a limited amount of power. Note that infinite radiances, like with point lights, should be permitted, as long as their power is finite. &#xD;&#xA;  &#xD;&#xA;1.  **The total power of all light sources should be finite.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/RbHvb.gif&quot; width=&quot;250&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Secondly, we should exclude scenes that consists only of mirrors or diffuse white materials, or any other material that perfectly conserves energy. In other words, the scene should always absorb a little energy. These materials should still be permitted though, as long as their reflected light eventually ends up in materials that do not conserve the energy. I tried to formalize this the following way.&#xD;&#xA;&#xD;&#xA;2. **There exists an integer $k$ with the following property: for every point $\vec{p}$ in the scene there should be a path of length $k$ that starts in $\vec{p}$ and which has a throughput smaller than 1.**&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/KzuU3.gif&quot; width=&quot;400&quot; /&gt;&#xD;&#xA;&#xD;&#xA;**Questions.**&#xD;&#xA;&#xD;&#xA;Using these assumptions, is it possible to prove my suspicion? How would you do it?&#xD;&#xA;&#xD;&#xA;If it isn't possible, are there other &quot;realistic&quot; conditions that will make it proveable? Any conditions you come up with should not limit scenes that are used in practice in any way. (I know, sometimes people create materials that transmit more light than what comes in. You can ignore these materials).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**What I tried so far.**&#xD;&#xA;&#xD;&#xA;I was able to prove this with some stronger conditions, namely&#xD;&#xA;&#xD;&#xA;1. There is an upper bound $L_{max}$ on emitted radiance $L_e$.&#xD;&#xA;2. There is an upper bound $t &lt; 1$ on the percentage of energy that materials conserve.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0oNkf.gif&quot; width=&quot;360&quot; /&gt;&#xD;&#xA;&#xD;&#xA;With these conditions, the prove is straightforward, but they do not allow point lights or perfectly white diffuse materials and such.&#xD;&#xA;&#xD;&#xA;*Proof.*&#xD;&#xA;\begin{align*}&#xD;&#xA;    L_o^{(d)}(\vec{p}_0, \omega_0) &amp;= \int_{\Omega^d} \left(\prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \right) L_e(\vec{p}_d, \omega_d) \text{d} \omega_1 \dots \text{d} \omega_d&#xD;&#xA;\end{align*}&#xD;&#xA;Using condition (1):&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} \int_{\Omega^d} \prod_{j=1}^d f_r(\vec{p}_{j-1}, \omega_{j-1}, -\omega_j) \cos{\theta_j} \text{d}\omega_j \\&#xD;&#xA;    &amp;= L_{max} \int_{\Omega} \text{d}\omega_1 f_r(\vec{p}_{0}, \omega_{0}, -\omega_1) \cos{\theta_1} \int_\Omega \dotsm \int_{\Omega} \text{d}\omega_d f_r(\vec{p}_{d-1}, \omega_{d-1}, -\omega_d) \cos{\theta_d}&#xD;&#xA;\end{align*}&#xD;&#xA;By applying condition (2) recursively on the innermost integral:&#xD;&#xA;\begin{align*}&#xD;&#xA;    &amp;\leq L_{max} t^d&#xD;&#xA;\end{align*}" ContentLicense="CC BY-SA 4.0" />
  <row Id="29850" PostHistoryTypeId="5" PostId="10294" RevisionGUID="ebc5a7c9-d2de-4c9f-bccd-803601104e64" CreationDate="2020-10-08T08:38:55.080" UserId="10129" Comment="edited body" Text="**Yes, throughput doesn't have to be in range [0, 1].** That's a reason why you have to use exposure settings, because for differente accumulation time, brightness of an image might differ. Nathan Reed described it in details here - https://computergraphics.stackexchange.com/a/10244/10129&#xD;&#xA;&#xD;&#xA;Your final results and number of fireflies and bright surfaces, depends on PDF that you'll be using. By using Normal Distribution Function PDF, you'll get good results, because NDF is the most determining factor of BRDF shape. Relate to this blog post for details - https://schuttejoe.github.io/post/ggximportancesamplingpart1/&#xD;&#xA;___&#xD;&#xA;Back to throughput range. Assuming that you're sampling based on NDF, you'll get fireflies in case of having values in specific range, when light source is shining from very low angle and you're looking directly at the object. Therefore, your denominator might be much greater than nominator and result in small PDF causing fireflies:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;p_i(w_m, w_o) = \frac{D(w_m)(w_g \cdot w_i)}{4|w_g \cdot w_m|}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Since 2014, Heitz was working on BSDFs, presenting good results in same year by sampling visible normals [2]. In 2017, he published much simpler, faster and better paper, improving his method [3]. There are also 2015 and 2016 papers in related field, but I haven't read them, but it might be beneficial if you're interested in BSDF. I would recommend checking his first 2014's work (1) where he explains physical assumption on which BRDF is based. It's worth knowing, what NDF and Geometry Shadowing exactly means in BRDF.&#xD;&#xA;&#xD;&#xA;Also, there is a lot of good reading in pbrt book, especially:&#xD;&#xA;&#xD;&#xA; - http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Sampling_Reflection_Functions.html#MicrofacetBxDFs&#xD;&#xA; - http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html&#xD;&#xA; - http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Importance_Sampling.html&#xD;&#xA; - For more advanced method, I think it'd be worth reading about Russian Roulette and more efficient Path Tracing algorithms like Bidirectional Path Tracing, Metropolis Light Tracing and Photon Mapping methods &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gg4J4.png&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;(1) Eric Heitz - Understanding the Masking-Shadowing Functionin Microfacet-Based BRDFs http://jcgt.org/published/0003/02/03/paper.pdf &#xD;&#xA;&#xD;&#xA;(2) Eric Heitz, Eugene d’Eon - Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals https://hal.inria.fr/hal-00996995v1/document &#xD;&#xA;&#xD;&#xA;(3) Eric Heitz - A Simpler and Exact Sampling Routine for the GGXDistribution of Visible Normals https://hal.archives-ouvertes.fr/hal-01509746/document " ContentLicense="CC BY-SA 4.0" />
  <row Id="29851" PostHistoryTypeId="2" PostId="10295" RevisionGUID="d08648be-e65e-403b-85fd-597d1fc67960" CreationDate="2020-10-08T11:20:47.103" UserId="13273" Text="I have a low-poly mesh and I want to add structure on the surface.&#xD;&#xA;&#xD;&#xA;**The setup:**&#xD;&#xA;The mesh consists of triangles. &#xD;&#xA;Within the TCS the pixel-length for each of the three edges will be calculated and subdivided according to the given allowed u_MAX_LENGTH_TRIANGLE_EDGE. This will be done in the following way: &#xD;&#xA;&#xD;&#xA;    vec4 vertexPosScreen[3];                                           &#xD;&#xA;    for (int i = 0; i &lt; 3; i++)                                   &#xD;&#xA;    {                                                            &#xD;&#xA;        vertexPosScreen[i] = vec4(mvp * gl_in[i].gl_Position);          &#xD;&#xA;        vertexPosScreen[i] = vertexPosScreen[i] / vertexPosScreen[i].w; &#xD;&#xA;        vertexPosScreen[i].x *= u_viewportWidth;                     &#xD;&#xA;        vertexPosScreen[i].y *= u_viewportHeight;                    &#xD;&#xA;    }         &#xD;&#xA;    float edgeLength[3];                                                                                                  &#xD;&#xA;    edgeLength[2] = length(vertexPosScreen[0].xy - vertexPosScreen[1].xy);&#xD;&#xA;    edgeLength[1] = length(vertexPosScreen[0].xy - vertexPosScreen[2].xy);&#xD;&#xA;    edgeLength[0] = length(vertexPosScreen[1].xy - vertexPosScreen[2].xy);           &#xD;&#xA;&#xD;&#xA;    float edgeLod[3];                                         &#xD;&#xA;    for (int i = 0; i &lt; 3; ++i)                           &#xD;&#xA;    {                                                       &#xD;&#xA;        edgeLod[i] = max(1.0, edgeLength[i] / u_MAX_LENGTH_TRIANGLE_EDGE;&#xD;&#xA;    }                                                           &#xD;&#xA;                                                                           &#xD;&#xA;    gl_TessLevelOuter[0] = edgeLod[0];                        &#xD;&#xA;    gl_TessLevelOuter[1] = edgeLod[1];                      &#xD;&#xA;    gl_TessLevelOuter[2] = edgeLod[2];                      &#xD;&#xA;                                                                           &#xD;&#xA;    gl_TessLevelInner[0] = max(edgeLod[0], max(edgeLod[1], edgeLod[2]));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This guarantees, that in the final image all triangles edges are smaller than u_MAX_LENGTH_TRIANGLE_EDGE.&#xD;&#xA;&#xD;&#xA;**But:**                        &#xD;&#xA;The GPU is not able to subdivide as mush as wanted. So if we are too close to a triangle, or a triangle is too tall at all, the TCS will subdivide it as mush as possible, but not enough.&#xD;&#xA;&#xD;&#xA;**My Idea:**                    &#xD;&#xA;After tessellation is done, the new generated triangles should be stored into a new VBO during the TES step. Afterwards the fresh stored triangles in the new VBO will be rendered again and subdivided as well until all of them are small enough.&#xD;&#xA;&#xD;&#xA;**Now the big question**   &#xD;&#xA;How are the tessellation limits defined? per edge division? And how can I ask for the maximum division on CPU? glGetInteger? Or is it limited during the number of generated vertices?&#xD;&#xA;&#xD;&#xA;I think the easiest solution would be check directly after &quot;edgeLod&quot; is calculated, if edgeLod is too high. If this is the case, write something into a SSBO and loop the shaderprogram again.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29852" PostHistoryTypeId="1" PostId="10295" RevisionGUID="d08648be-e65e-403b-85fd-597d1fc67960" CreationDate="2020-10-08T11:20:47.103" UserId="13273" Text="Tessellation Controll Shader how to get maximum subdivisions limit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29853" PostHistoryTypeId="3" PostId="10295" RevisionGUID="d08648be-e65e-403b-85fd-597d1fc67960" CreationDate="2020-10-08T11:20:47.103" UserId="13273" Text="|opengl|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29854" PostHistoryTypeId="2" PostId="10296" RevisionGUID="578fb1d7-432a-428c-b403-d7bd712f22f4" CreationDate="2020-10-08T14:04:48.023" UserId="7952" Text="The tessellation limit is GPU dependent..Any number above the GPU limit is technically an error but most gpu's just clamp to the upper limit. To get beyond the limit either use a Level Of Detail (LOD) approach where you have different models that are used based on distance, or save and recompute like you suggest.&#xD;&#xA;&#xD;&#xA;To get the max just set all the edges to the limit AND set all the internals to the limit in the tessellation control shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;&#xD;&#xA;      layout(vertices = 4) out;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;       gl_TessLevelOuter[0] = 64.0;&#xD;&#xA;       gl_TessLevelOuter[1] = 64.0;&#xD;&#xA;       gl_TessLevelOuter[2] = 64.0;&#xD;&#xA;       gl_TessLevelOuter[3] = 64.0;&#xD;&#xA;&#xD;&#xA;       gl_TessLevelInner[0] = 64.0;&#xD;&#xA;       gl_TessLevelInner[1] = 64.0;&#xD;&#xA;&#xD;&#xA;       gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&gt; And how can I ask for the maximum division on CPU?&#xD;&#xA;&#xD;&#xA;Yes use glGetInteger. At the bottom of this page is all the values you would be intrested in: [Khoronos Tessellation limits, search for tessellation on the page][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/GLAPI/glGet" ContentLicense="CC BY-SA 4.0" />
  <row Id="29855" PostHistoryTypeId="50" PostId="9354" RevisionGUID="a02efdcb-741b-4c69-afe6-e83bd1f8f138" CreationDate="2020-10-08T17:04:40.350" UserId="-1" />
  <row Id="29856" PostHistoryTypeId="2" PostId="10297" RevisionGUID="be9fb46d-7737-42c9-8072-4c9f463aec26" CreationDate="2020-10-09T02:05:03.753" UserId="14062" Text="Say that there you are taking pictures from a street like this one:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the picture is taken perpendicular to the direction of the street.&#xD;&#xA;&#xD;&#xA;The problem is that cars at the left look as if they are going East South:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And cars at the right look as if they are going East North:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Only when they're right in front of me, the cars look like going simply East:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As I understand, the name for this phenomena is called &quot;Horizontal Convergence&quot;. How could you remove this phenomena from a picture? That is, how can I transform the image so that all the cars look like going simply to the East no matter their horizontal position.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eLOfs.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7VpIt.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ndwxz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/eajgo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29857" PostHistoryTypeId="1" PostId="10297" RevisionGUID="be9fb46d-7737-42c9-8072-4c9f463aec26" CreationDate="2020-10-09T02:05:03.753" UserId="14062" Text="What's the name of the transformation that can remove horizontal convergence from a picture?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29858" PostHistoryTypeId="3" PostId="10297" RevisionGUID="be9fb46d-7737-42c9-8072-4c9f463aec26" CreationDate="2020-10-09T02:05:03.753" UserId="14062" Text="|transformations|camera|distortion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29859" PostHistoryTypeId="5" PostId="10297" RevisionGUID="9ed08eb4-abca-4a94-96a7-8778e7dc96d1" CreationDate="2020-10-09T02:13:49.943" UserId="14062" Comment="added 242 characters in body" Text="Say that there you are taking pictures from a street like this one:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the picture is taken perpendicular to the direction of the street.&#xD;&#xA;&#xD;&#xA;The problem is that cars at the left look as if they are going East South:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And cars at the right look as if they are going East North:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Only when they're right in front of me, the cars look like going simply East:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As I understand, the name for this phenomena is called &quot;Horizontal Convergence&quot;. How could you remove this phenomena from a picture? That is, how can I transform the image so that all the cars look like going simply to the East no matter their horizontal position.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To read about a &quot;vertical congergence&quot;: [https://digital-photography-school.com/how-to-overcome-the-problem-of-converging-verticals/][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eLOfs.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7VpIt.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ndwxz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/eajgo.png&#xD;&#xA;  [5]: https://digital-photography-school.com/how-to-overcome-the-problem-of-converging-verticals/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29863" PostHistoryTypeId="5" PostId="10297" RevisionGUID="5fe62160-a934-4f7a-9f76-59886d80ab69" CreationDate="2020-10-09T05:59:48.800" UserId="14062" Comment="deleted 6 characters in body" Text="Say that you are taking pictures from a street like this one:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the picture is taken perpendicular to the direction of the street.&#xD;&#xA;&#xD;&#xA;The problem is that cars at the left look as if they are going East South:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And cars at the right look as if they are going East North:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Only when they're right in front of you, the cars look like going simply East:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;As I understand, the name for this phenomena is called &quot;Horizontal Convergence&quot;. How could you remove this phenomena from a picture? That is, how can I transform the image so that all the cars look like going simply to the East no matter their horizontal position.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To read about a &quot;vertical congergence&quot;: [https://digital-photography-school.com/how-to-overcome-the-problem-of-converging-verticals/][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eLOfs.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7VpIt.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ndwxz.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/eajgo.png&#xD;&#xA;  [5]: https://digital-photography-school.com/how-to-overcome-the-problem-of-converging-verticals/" ContentLicense="CC BY-SA 4.0" />
  <row Id="29866" PostHistoryTypeId="50" PostId="9829" RevisionGUID="80713287-b878-4d41-9438-eae977cb8a1d" CreationDate="2020-10-10T16:05:40.560" UserId="-1" />
  <row Id="29867" PostHistoryTypeId="2" PostId="10299" RevisionGUID="3d3800e6-49ed-4f2d-af0d-545054c53916" CreationDate="2020-10-10T20:42:58.860" UserId="7952" Text="You are talking apples and oranges here. Copying memory to memory on the CPU is using completely different hardware then memory to memory copies on the GPU, even in a unified memory architecture GPU's tend to have specialized memory.&#xD;&#xA;&#xD;&#xA;The actual difference is going to depend heavily on the model of the GPU, a high end gddr5 gpu will easily beat DDR4 dual channel memory on the CPU.&#xD;&#xA;&#xD;&#xA;Also, the driver implementation is going to have an effect on the gpu copy since you are really asking the driver for the copy on the gpu, which it then translates into code that does the actual copy.&#xD;&#xA;&#xD;&#xA;The size of the chunk of memory also plays a major role in how fast the copy happens, as well as how large the cache on the cpu vs gpu is.&#xD;&#xA;&#xD;&#xA;You should generally expect copies that are GPU to GPU to be much faster then CPU to CPU copies. CPU to GPU along with GPU to CPU copies have to cross the AGP bus on the PC while unified architecture systems have an advantage they still have synchronization issues and all systems have to synchronize access and flush cache's.&#xD;&#xA;&#xD;&#xA;What are the actual differences?(very roughly) DDR4 runs from 1600 to 3200 MB per second and DDR5 run's at roughly 3200 to 6400 MB per second. So very roughly, a poorly balanced system will have up to 4x performance diffence, but you should expect about a 2x performance differnce with the GPU being faster. This difference fades somewhat(mostly) with unified systems. (But the gpu will probably still have memory set aside so it can work with framebuffers and what not in an efficient manner)&#xD;&#xA;&#xD;&#xA;QDR memory is nearing the market and GPU's tend to get the latest memory sooner then CPU's so that difference could double." ContentLicense="CC BY-SA 4.0" />
  <row Id="29868" PostHistoryTypeId="5" PostId="10299" RevisionGUID="b2a88a69-852d-43b1-8d54-4354df2b190b" CreationDate="2020-10-10T22:07:49.343" UserId="7952" Comment="deleted 125 characters in body" Text="You are talking apples and oranges here. Copying memory to memory on the CPU is using completely different hardware then memory to memory copies on the GPU, even in a unified memory architecture GPU's tend to have specialized memory.&#xD;&#xA;&#xD;&#xA;The actual difference is going to depend heavily on the model of the GPU, a high end gddr5 gpu will easily beat DDR4 dual channel memory on the CPU.&#xD;&#xA;&#xD;&#xA;Also, the driver implementation is going to have an effect on the gpu copy since you are really asking the driver for the copy on the gpu, which it then translates into code that does the actual copy.&#xD;&#xA;&#xD;&#xA;The size of the chunk of memory also plays a major role in how fast the copy happens, as well as how large the cache on the cpu vs gpu is.&#xD;&#xA;&#xD;&#xA;You should generally expect copies that are GPU to GPU to be much faster then CPU to CPU copies. CPU to GPU along with GPU to CPU copies have to cross the AGP bus on the PC while unified architecture systems have an advantage they still have synchronization issues and all systems have to synchronize access and flush cache's.&#xD;&#xA;&#xD;&#xA;What are the actual differences?(very roughly) DDR4 runs from 1600 to 3200 MB per second and DDR5 run's at roughly 3200 to 6400 MB per second. So very roughly, a poorly balanced system will have up to 4x performance diffence, but you should expect about a 2x performance differnce with the GPU being faster. This difference fades somewhat(mostly) with unified systems. (But the gpu will probably still have memory set aside so it can work with framebuffers and what not in an efficient manner)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29869" PostHistoryTypeId="50" PostId="10207" RevisionGUID="188b9618-c304-4cc6-ba69-60605c103807" CreationDate="2020-10-11T08:03:00.297" UserId="-1" />
  <row Id="29870" PostHistoryTypeId="50" PostId="10204" RevisionGUID="ac70d139-c90c-492c-9a7b-06fadfe417a5" CreationDate="2020-10-11T20:01:40.193" UserId="-1" />
  <row Id="29874" PostHistoryTypeId="2" PostId="10301" RevisionGUID="17385fd8-a48f-4d87-af26-d7658e8c3ed7" CreationDate="2020-10-11T23:01:00.937" UserId="14074" Text="Is there a way to take a random value (or set of values), and cause them to create a &quot;pretty&quot; pattern (as a thumbprint), and that array of thumbprints might have a rendering mask on just for aesthetic purposes.&#xD;&#xA;&#xD;&#xA;Since I don't know much about all that can be done in Photoshop and Illustrator, I hope someone can help clarify my terminology such as &quot;Random numbers (in the range of X/by way of formula Y) are best expressed in {Hue, Saturation, CMYK, RGB, chemically, theoretically}&quot; ... etc&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29875" PostHistoryTypeId="1" PostId="10301" RevisionGUID="17385fd8-a48f-4d87-af26-d7658e8c3ed7" CreationDate="2020-10-11T23:01:00.937" UserId="14074" Text="Could the Tetradic color pattern be expanded to allow /dev/random be &quot;pretty&quot; for cryptographic key purposes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29876" PostHistoryTypeId="3" PostId="10301" RevisionGUID="17385fd8-a48f-4d87-af26-d7658e8c3ed7" CreationDate="2020-10-11T23:01:00.937" UserId="14074" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29877" PostHistoryTypeId="5" PostId="9792" RevisionGUID="0e644565-c5de-4f50-bd6f-19ecbbe72066" CreationDate="2020-10-12T02:04:16.813" UserId="1988" Comment="added 3 characters in body" Text="## Defining the problem&#xD;&#xA;&#xD;&#xA;The weighted arithmetic mean $\mu$, of a set of vectors, minimizes squared L2 norm of the error ($v_i$) to all elements of the set.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;v_i &amp;= \mu - x_i \\&#xD;&#xA;\mu &amp;= \underset{\mu \in \mathbb{R^n}}{\text{argmin}} \; \frac{1}{2}\sum\limits_{v_i} w_i ||v_i||^2_2 \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This empowers us to define special means, where we use different notions of distance. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Specializing for rotations&#xD;&#xA;&#xD;&#xA;A reasonable notion of distance for SO(3) is the *angle* separating two rotations. That's $||\log(\mu \ q^{-1})||$ Your geometry library probably implements this $log$, and expressions for it can be found [here](http://ethaneade.com/lie.pdf). It is not the log one is accustomed to on the real numbers.&#xD;&#xA;&#xD;&#xA;Intuition: Recall that every sequence of rotations corresponds to [a single rotation about a single axis](https://en.wikipedia.org/wiki/Euler%27s_rotation_theorem), so the difference between a pair of rotations can always be summarized by a single angle.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;v_i &amp;= log(\mu \ x_i^{-1}) \\&#xD;&#xA;\mu &amp;= \underset{\mu \in \mathbb{SO3}}{\text{argmin}} \sum\limits_{v_i} w_i || v_i||^2_2 \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's no analytical form for this minimum for more than two rotations. We can, however, treat this as a [least squares problem](http://ethaneade.com/optimization.pdf) and compute the result by Gauss-Newton. &#xD;&#xA;&#xD;&#xA;To apply Gauss-Newton in general, for some error, we need to be able to find $\mathbf{J_i} = \frac{d}{d\mu}v_i(\mu)$, which requires differentiating $v_i$. Then we can take a step as&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;\Delta \mu &amp;= \sum\limits_{i}(w_i \mathbf{J_i}^T \mathbf{J_i})^{-1} \sum\limits_{i} w_i \mathbf{J_i}^T v_i&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Our error function cannot readily be differentiated, since its argument is a rotation $\mu$ and not a vector. We invent a parameter $\delta \in \mathbb{R^3}$ which we will $Exp$ into a rotation. This, we can differentiate&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;v_i &amp;= log(Exp(\delta)\; \mu \ x_i^{-1}) \\ &#xD;&#xA;\mathbf{J_i} &amp;= \frac{d}{d\delta} v_i = \mathbf{I} \\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So the update to $\mu$ is&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;\delta &amp;= \sum\limits_{i}(w_i \mathbf{J_i}^T \mathbf{J_i})^{-1} \sum\limits_{i} w_i \mathbf{J_i}^T v_i\\&#xD;&#xA;\delta &amp;= \sum\limits_{i} w_i \sum\limits_{i} w_i v_i \\&#xD;&#xA;\delta &amp;= \sum\limits_{i} w_i v_i&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Conclusion&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;\delta = \sum\limits_{i} w_i v_i &amp;= \sum\limits_{i}w_i log(\mu_{k}^{\mathstrut} x_{i}^{-1}) \\&#xD;&#xA;\mu_{k + 1} &amp;= Exp(\delta) \mu_{k}\\&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;This will converge quadratically to a mean.&#xD;&#xA;&#xD;&#xA;Caveat emptor: for rotations, there may be many &quot;means&quot;. By analogy: What is the average point, on Earth's surface, of the north and south poles? Every point on the equator has equal right to be called the average. This is the case for all equispaced rotations." ContentLicense="CC BY-SA 4.0" />
  <row Id="29878" PostHistoryTypeId="2" PostId="10302" RevisionGUID="6d5e2306-48e1-4001-9197-7cfc35462344" CreationDate="2020-10-12T15:21:01.570" UserId="10129" Text="I'm creating DXR PathTracer highly influence by Matt Pettineo's one - https://github.com/TheRealMJP/DXRPathTracer ; Relevant HLSL code below:&#xD;&#xA;&#xD;&#xA;    [shader(&quot;raygeneration&quot;)]&#xD;&#xA;    void RayGen()&#xD;&#xA;    {&#xD;&#xA;    	// Accumulate for limited amount of frames&#xD;&#xA;    	if (g_giCB.maxFrames &gt; 0 &amp;&amp; g_giCB.accFrames &gt;= g_giCB.maxFrames)&#xD;&#xA;    	{&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    	uint2 LaunchIndex = DispatchRaysIndex().xy;&#xD;&#xA;    	uint2 LaunchDimensions = DispatchRaysDimensions().xy;&#xD;&#xA;    	&#xD;&#xA;    	if (g_giCB.samplingType == SAMPLE_MJ)&#xD;&#xA;    	{&#xD;&#xA;    		const uint pixelIdx = LaunchIndex.y * LaunchDimensions.x + LaunchIndex.x;&#xD;&#xA;    		uint sampleSetIdx = 0;&#xD;&#xA;    		offset = SamplePoint(pixelIdx, sampleSetIdx);&#xD;&#xA;    		seed = pixelIdx;&#xD;&#xA;    		seed2 = sampleSetIdx;&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	float3 primaryRayOrigin = g_sceneCB.cameraPosition.xyz;&#xD;&#xA;    	float3 primaryRayDirection;&#xD;&#xA;    	GenerateCameraRay(LaunchIndex, LaunchDimensions, g_sceneCB.projectionToWorld, primaryRayOrigin, primaryRayDirection, offset);&#xD;&#xA;    	&#xD;&#xA;    	// Prepare payload&#xD;&#xA;    	PayloadIndirect indirectPayload;&#xD;&#xA;    	indirectPayload.color = float3(0, 0, 0);&#xD;&#xA;    	indirectPayload.roughness = 0;&#xD;&#xA;    	indirectPayload.rndSeed = seed;&#xD;&#xA;    	indirectPayload.rndSeed2 = seed2;&#xD;&#xA;    	indirectPayload.pathLength = 0;&#xD;&#xA;    	indirectPayload.diffusePath = false;&#xD;&#xA;    		&#xD;&#xA;    	// Calculate pixel color in current pass and merge with previous frames&#xD;&#xA;    	float4 finalColor = float4(shootIndirectRay(primaryRayOrigin, primaryRayDirection, 1e-3f, indirectPayload), 1.0f);&#xD;&#xA;    	bool colorsNan = any(isnan(finalColor));&#xD;&#xA;    	if (colorsNan)&#xD;&#xA;    	{&#xD;&#xA;    		finalColor = float4(0, 0, 0, 1);&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	const float FP16Max = 65000.0f;&#xD;&#xA;    	finalColor = clamp(finalColor, 0.0f, FP16Max);&#xD;&#xA;    	&#xD;&#xA;    	if (g_giCB.accFrames &gt; 0)&#xD;&#xA;    	{&#xD;&#xA;    		float4 prevScene = RTOutput[LaunchIndex];&#xD;&#xA;    		finalColor = ((float) g_giCB.accFrames * prevScene + finalColor) / ((float) g_giCB.accFrames + 1.0f);&#xD;&#xA;    	}&#xD;&#xA;    	RTOutput[LaunchIndex] = finalColor;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void Miss(inout RayPayload payload : SV_RayPayload)&#xD;&#xA;    {&#xD;&#xA;    	payload.vis = 1.0f;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHit(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;miss&quot;)]&#xD;&#xA;    void MissIndirect(inout PayloadIndirect payload : SV_RayPayload)&#xD;&#xA;    {&#xD;&#xA;    	// Use skybox as contribution if ray failed to hit geometry (right now, disabled for debug purposes)&#xD;&#xA;    	float3 rayDir = WorldRayDirection();&#xD;&#xA;    	rayDir.z = -rayDir.z;&#xD;&#xA;    	if (g_giCB.useSkybox)&#xD;&#xA;    	{&#xD;&#xA;    		payload.color += skyboxTexture.SampleLevel(g_sampler, rayDir, 0).rgb;&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;       &#xD;&#xA;    float3 CalcLighting(in float3 normal, in float3 lightDir, in float3 peakIrradiance,&#xD;&#xA;                        in float3 diffuseAlbedo, in float3 specularAlbedo, in float roughness,&#xD;&#xA;                        in float3 positionWS, in float3 cameraPosWS, in float3 msEnergyCompensation)&#xD;&#xA;    {&#xD;&#xA;    	float3 lighting = diffuseAlbedo * INV_PI;&#xD;&#xA;    &#xD;&#xA;    	float3 view = normalize(cameraPosWS - positionWS);&#xD;&#xA;    	const float NoL = saturate(dot(normal, lightDir));&#xD;&#xA;    	if (NoL &gt; 0.0f)&#xD;&#xA;    	{&#xD;&#xA;    		const float NoV = saturate(dot(normal, view));&#xD;&#xA;    		float3 h = normalize(view + lightDir);&#xD;&#xA;    &#xD;&#xA;    		float3 fresnel = Fresnel(specularAlbedo, h, lightDir);&#xD;&#xA;    &#xD;&#xA;    		float specular = GGXSpecular(roughness, normal, h, view, lightDir);&#xD;&#xA;    		lighting += specular * fresnel * msEnergyCompensation;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return lighting * NoL * peakIrradiance;&#xD;&#xA;    }&#xD;&#xA;        &#xD;&#xA;    float3 CalculateRadiance(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    	/* Prepare input data */&#xD;&#xA;    	float3 hitPos = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();&#xD;&#xA;    	float3 triangleNormal, triangleTangent, triangleBitangent;&#xD;&#xA;    	loadHitData(triangleNormal, triangleTangent, triangleBitangent, attribs);&#xD;&#xA;    &#xD;&#xA;    	float4 albedo = albedoTexture.Load(int3(DispatchRaysIndex().xy, 0));&#xD;&#xA;    &#xD;&#xA;    	float roughness = specularTexture.Load(int3(DispatchRaysIndex().xy, 0)).g;&#xD;&#xA;    	roughness = max(roughness, payload.roughness);&#xD;&#xA;    	float metallic = specularTexture.Load(int3(DispatchRaysIndex().xy, 0)).b;&#xD;&#xA;    	float3 normalTextureData = NormalTextureInput.Load(int3(DispatchRaysIndex().xy, 0)).rgb;&#xD;&#xA;    	float3x3 tangentToWorld = float3x3(triangleTangent, triangleBitangent, triangleNormal);&#xD;&#xA;    	float3 normalWS = triangleNormal;&#xD;&#xA;    &#xD;&#xA;    	bool enableDiffuse = metallic &lt; 1.0f;&#xD;&#xA;    	bool enableSpecular = !payload.diffusePath;&#xD;&#xA;    	&#xD;&#xA;    	if (enableDiffuse == false &amp;&amp; enableSpecular == false)&#xD;&#xA;    		return float3(0, 0, 0);&#xD;&#xA;    	&#xD;&#xA;    	const float3 diffuseAlbedo = lerp(albedo.rgb, 0.0f, metallic) * (enableDiffuse ? 1.0f : 0.0f);&#xD;&#xA;    	const float3 specularAlbedo = lerp(0.03f, albedo.rgb, metallic) * (enableSpecular ? 1.0f : 0.0f);&#xD;&#xA;    &#xD;&#xA;    	float3 msEnergyCompensation = float3(1, 1, 1);&#xD;&#xA;    	float2 DFG = dfgTexture.SampleLevel(g_sampler, float2(saturate(dot(triangleNormal, -WorldRayDirection())), roughness), 0.0f).xy;&#xD;&#xA;    	float Ess = DFG.x;&#xD;&#xA;    	msEnergyCompensation = float3(1, 1, 1) + specularAlbedo * (1.0f / Ess - 1.0f);&#xD;&#xA;    	float3 worldOrigin = WorldRayOrigin();	&#xD;&#xA;    	/*********************************************/&#xD;&#xA;    	&#xD;&#xA;    	// Calculate directional light&#xD;&#xA;    	{&#xD;&#xA;    		float3 V = g_sceneCB.cameraPosition.xyz;&#xD;&#xA;    		float3 N = triangleNormal.xyz;&#xD;&#xA;    		&#xD;&#xA;    		float3 L = normalize(g_giCB.sunDirection);&#xD;&#xA;    		float distToLight = 1e+38f;&#xD;&#xA;    		&#xD;&#xA;    		// Check visibility&#xD;&#xA;    		float NoL = saturate(dot(N, L));&#xD;&#xA;    		float visibility = shadowRayVisibility(hitPos, L, 1e-3f, distToLight);&#xD;&#xA;    		&#xD;&#xA;    		// Calculate light contribution to point in world (diffuse lambertian term)&#xD;&#xA;    		payload.color += CalcLighting(triangleNormal, L, 1.0f, diffuseAlbedo, specularAlbedo,&#xD;&#xA;    					roughness, hitPos, worldOrigin, msEnergyCompensation) * visibility;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	float2 brdfSample = SamplePoint(payload.rndSeed, payload.rndSeed2);&#xD;&#xA;    				&#xD;&#xA;    	float selector = brdfSample.x;&#xD;&#xA;    	if (enableSpecular == false)&#xD;&#xA;    		selector = 0.0f;&#xD;&#xA;    	else if (enableDiffuse == false)&#xD;&#xA;    		selector = 1.0f;&#xD;&#xA;    		&#xD;&#xA;    	if (g_giCB.useIndirect == 1)&#xD;&#xA;    	{&#xD;&#xA;    		float3 throughput = float3(0, 0, 0);&#xD;&#xA;    					&#xD;&#xA;    		// Find next direction&#xD;&#xA;    		float3 rayDirWS = float3(0, 0, 0);&#xD;&#xA;    		if (g_giCB.samplingType == SAMPLE_MJ)&#xD;&#xA;    		{&#xD;&#xA;    			if (selector &lt; 0.5f)&#xD;&#xA;    			{&#xD;&#xA;    				if (enableSpecular)&#xD;&#xA;    					brdfSample.x *= 2.0f;&#xD;&#xA;    				float3 rayDirTS = SampleDirectionCosineHemisphere(brdfSample.x, brdfSample.y);&#xD;&#xA;    				rayDirWS = normalize(mul(rayDirTS, tangentToWorld));&#xD;&#xA;    				throughput = diffuseAlbedo;&#xD;&#xA;    			}&#xD;&#xA;    			else&#xD;&#xA;    			{&#xD;&#xA;    				if (enableDiffuse)&#xD;&#xA;    					brdfSample.x = (brdfSample.x - 0.5f) * 2.0f;&#xD;&#xA;    &#xD;&#xA;    				float3 incomingRayDirWS = WorldRayDirection();&#xD;&#xA;    				float3 incomingRayDirTS = normalize(mul(incomingRayDirWS, transpose(tangentToWorld)));&#xD;&#xA;    &#xD;&#xA;    				float3 wo = incomingRayDirTS;&#xD;&#xA;    				float3 wm = SampleGGXVisibleNormal(-wo, roughness, roughness, brdfSample.x, brdfSample.y);&#xD;&#xA;    				float3 wi = reflect(wo, wm);&#xD;&#xA;    &#xD;&#xA;    				float3 normalTS = float3(0.0f, 0.0f, 1.0f);&#xD;&#xA;    &#xD;&#xA;    				float3 F = Fresnel(specularAlbedo.rgb, wm, wi);&#xD;&#xA;    				float G1 = SmithGGXMasking(normalTS, wi, -wo, roughness * roughness);&#xD;&#xA;    				float G2 = SmithGGXMaskingShadowing(normalTS, wi, -wo, roughness * roughness);&#xD;&#xA;    &#xD;&#xA;    				throughput = (F * (G2 / G1));&#xD;&#xA;    				float3 rayDirTS = wi;&#xD;&#xA;    				rayDirWS = normalize(mul(rayDirTS, tangentToWorld));&#xD;&#xA;    					&#xD;&#xA;    #if 1&#xD;&#xA;    				DFG = dfgTexture.SampleLevel(g_sampler, float2(saturate(dot(triangleNormal, -WorldRayDirection())), roughness), 0.0f).xy;&#xD;&#xA;    				Ess = DFG.x;&#xD;&#xA;    				throughput *= float3(1, 1, 1) + specularAlbedo * (1.0f / Ess - 1.0f);&#xD;&#xA;    #endif&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    			&#xD;&#xA;    		if (enableDiffuse &amp;&amp; enableSpecular)&#xD;&#xA;    			throughput *= 2.0f;&#xD;&#xA;    			&#xD;&#xA;    		if (payload.pathLength &lt; g_giCB.bounceCount)&#xD;&#xA;    		{&#xD;&#xA;    			// Prepare payload&#xD;&#xA;    			PayloadIndirect newPayload;&#xD;&#xA;    			newPayload.pathLength = payload.pathLength + 1;&#xD;&#xA;    			newPayload.rndSeed = payload.rndSeed;&#xD;&#xA;    			newPayload.rndSeed2 = payload.rndSeed2;&#xD;&#xA;    			newPayload.color = float3(0, 0, 0);&#xD;&#xA;    			newPayload.diffusePath = (selector &lt; 0.5f);&#xD;&#xA;    			newPayload.roughness = roughness;&#xD;&#xA;    			&#xD;&#xA;    			// Calculate next ray bounce color contribution&#xD;&#xA;    			float3 bounceColor = shootIndirectRay(hitPos, rayDirWS, 1e-3f, newPayload);&#xD;&#xA;    			&#xD;&#xA;    			// Check to make sure our randomly selected, normal mapped diffuse ray didn't go below the surface.&#xD;&#xA;    			if (dot(normalWS, rayDirWS) &lt;= 0.0f)&#xD;&#xA;    				bounceColor = float3(0, 0, 0);&#xD;&#xA;    			&#xD;&#xA;    			payload.color += bounceColor * throughput; //* albedo.rgb;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	return payload.color;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [shader(&quot;closesthit&quot;)]&#xD;&#xA;    void ClosestHitIndirect(inout PayloadIndirect payload, in BuiltInTriangleIntersectionAttributes attribs)&#xD;&#xA;    {&#xD;&#xA;    	payload.color = CalculateRadiance(payload, attribs);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Problem with my code occurs when using path of length more than 1 (indirect light bounces more than once). Shadows are starting to disappear and objects doesn't look grounded anymore. Series of images will occur now. Open full-size for better comparison. Points of interest marked in red in first image. Information about path length can be seen in GUI on the left. All images are generated with 1024 spp.&#xD;&#xA;&#xD;&#xA;Here is my render (1-4-8 indirect bounces in that order):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you can see, information about shadows are lost in the process of increasing path length. Now, I tried to skip skybox, so any miss shader will just return (0, 0, 0) instead of skybox values. Results are slightly better (4, 8 indirect bounces):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Here is reference from MJP's Path Tracer mentioned above (3-6 path length, but it's calculated differently. In my terms in 1-4 path length actually). No specular paths. Take a look at points of interest. Shadows are well grounded and you can see that creases are not getting many light:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;And here is ground truth reference created in MJP's Path Tracer with 5000 spp, 8 (in my terms - 6) path length:&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b21tq.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Urvp5.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/r2Y4V.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/3UQYK.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/31t8j.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/yEPdB.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/cmP1v.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/qGbFG.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29879" PostHistoryTypeId="1" PostId="10302" RevisionGUID="6d5e2306-48e1-4001-9197-7cfc35462344" CreationDate="2020-10-12T15:21:01.570" UserId="10129" Text="Pathtracing - many bounces reduce shadows" ContentLicense="CC BY-SA 4.0" />
  <row Id="29880" PostHistoryTypeId="3" PostId="10302" RevisionGUID="6d5e2306-48e1-4001-9197-7cfc35462344" CreationDate="2020-10-12T15:21:01.570" UserId="10129" Text="|raytracing|pathtracing|brdf|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29881" PostHistoryTypeId="2" PostId="10303" RevisionGUID="37b5254a-63b9-44da-8d87-0b0ae970f76d" CreationDate="2020-10-12T19:29:22.970" UserId="506" Text="It depends on how you define “pretty”, but there’s plenty of possibilities. Assembling a grid of shapes as in [Identicon](https://en.wikipedia.org/wiki/Identicon)s would be one example; using the numbers for coordinates and zoom levels on a fractal like the [Julia set](https://en.wikipedia.org/wiki/Julia_set) would be another. Our eyes aren’t good at measuring absolute values of anything—perception is heavily dependent on context and lighting, cf. [the dress](https://en.wikipedia.org/wiki/The_dress)—so you probably shouldn’t rely on color alone as the identifying factor." ContentLicense="CC BY-SA 4.0" />
  <row Id="29882" PostHistoryTypeId="2" PostId="10304" RevisionGUID="1ba8867c-8dc4-4fb3-9388-dc8022b669a5" CreationDate="2020-10-12T20:25:30.083" UserId="14079" Text="Following the instructions from [this post on Stack Overflow][1], I have been able to find points A, B, and C from points V1, V2, and V3 and a radius value (code below). I would like to be able to find a given number of subdivisions for the arc section labeled 'Arc B.' Can anyone help me find these position values of these points please?&#xD;&#xA;&#xD;&#xA;[![Finding Start and End Angles][2]][2]&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;    r = 106 #radius&#xD;&#xA;    V1 = Vector(50, 100, 0)&#xD;&#xA;    V2 = Vector(100, 300, 0)&#xD;&#xA;    V3 = Vector(350, 350, 0)&#xD;&#xA;    a = V2-V1&#xD;&#xA;    b = V2-V3&#xD;&#xA;    a.Normalize()&#xD;&#xA;    b.Normalize()&#xD;&#xA;    halfang = math.acos((a.Dot(b)))/2&#xD;&#xA;    ab = (a+b)/2&#xD;&#xA;    ab.Normalize()&#xD;&#xA;    A = V2 - r/math.tan(halfang)*a;&#xD;&#xA;    B = V2 - r/math.tan(halfang)*b;&#xD;&#xA;    C = V2 - r / math.sin(halfang) * ab&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/5918/14079&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ntvp.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hPu1A.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29883" PostHistoryTypeId="1" PostId="10304" RevisionGUID="1ba8867c-8dc4-4fb3-9388-dc8022b669a5" CreationDate="2020-10-12T20:25:30.083" UserId="14079" Text="Rounding a 3D corner with Subdivisions" ContentLicense="CC BY-SA 4.0" />
  <row Id="29884" PostHistoryTypeId="3" PostId="10304" RevisionGUID="1ba8867c-8dc4-4fb3-9388-dc8022b669a5" CreationDate="2020-10-12T20:25:30.083" UserId="14079" Text="|3d|algorithm|computational-geometry|geometry|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29885" PostHistoryTypeId="5" PostId="10304" RevisionGUID="5162ad79-6a81-4e8d-8d46-140511f10abc" CreationDate="2020-10-12T21:05:59.387" UserId="14079" Comment="deleted 6 characters in body" Text="Following the instructions from [this post on Stack Overflow][1], I have been able to find points A, B, and C from points V1, V2, and V3 and a radius value (code below). I would like to be able to find a given number of subdivisions for the arc section labeled 'Arc B.' Can anyone help me find these position values of these points please?&#xD;&#xA;&#xD;&#xA;[![Finding Start and End Angles][2]][2]&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;    r = 106 #radius&#xD;&#xA;    V1 = Vector(50, 100, 0)&#xD;&#xA;    V2 = Vector(100, 300, 0)&#xD;&#xA;    V3 = Vector(350, 350, 0)&#xD;&#xA;    a = V2-V1&#xD;&#xA;    b = V2-V3&#xD;&#xA;    a.Normalize()&#xD;&#xA;    b.Normalize()&#xD;&#xA;    halfang = math.acos((a.Dot(b)))/2&#xD;&#xA;    ab = (a+b)/2&#xD;&#xA;    ab.Normalize()&#xD;&#xA;    A = V2 - r/math.tan(halfang)*a&#xD;&#xA;    B = V2 - r/math.tan(halfang)*b&#xD;&#xA;    C = V2 - r/math.sin(halfang)*ab&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/5918/14079&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ntvp.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hPu1A.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29886" PostHistoryTypeId="5" PostId="10304" RevisionGUID="6a7038b0-c825-43f5-a240-a962bdcc1f89" CreationDate="2020-10-12T21:12:43.180" UserId="14079" Comment="added 4 characters in body" Text="Following the instructions from [this post on Stack Overflow][1], I have been able to find points A, B, and C from points V1, V2, and V3 and a radius value (code below). I would like to be able to find a specified number of subdivisions for the arc section labeled 'Arc B.' Can anyone help me find these position values of these points please?&#xD;&#xA;&#xD;&#xA;[![Finding Start and End Angles][2]][2]&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;    r = 106 #radius&#xD;&#xA;    V1 = Vector(50, 100, 0)&#xD;&#xA;    V2 = Vector(100, 300, 0)&#xD;&#xA;    V3 = Vector(350, 350, 0)&#xD;&#xA;    a = V2-V1&#xD;&#xA;    b = V2-V3&#xD;&#xA;    a.Normalize()&#xD;&#xA;    b.Normalize()&#xD;&#xA;    halfang = math.acos((a.Dot(b)))/2&#xD;&#xA;    ab = (a+b)/2&#xD;&#xA;    ab.Normalize()&#xD;&#xA;    A = V2 - r/math.tan(halfang)*a&#xD;&#xA;    B = V2 - r/math.tan(halfang)*b&#xD;&#xA;    C = V2 - r/math.sin(halfang)*ab&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/5918/14079&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ntvp.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/hPu1A.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29890" PostHistoryTypeId="2" PostId="10306" RevisionGUID="fc674815-cf3b-462f-b5ef-fa509900970f" CreationDate="2020-10-13T17:06:52.670" UserId="11058" Text="I want to load a vertex buffer with vertices of struct `Vertex`:&#xD;&#xA;&#xD;&#xA;    struct Vertex {&#xD;&#xA;       Vector3 position;&#xD;&#xA;	   Vector3 normal;&#xD;&#xA;       Vector2 uv;&#xD;&#xA;	   int groups[10];&#xD;&#xA;	   float weights[10];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;According to [khronos manual](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml), the number of elements in vertex attributes must be `1,2,3,4`. If that is the case how do I load the vertex attributes consisting of more elements, in this case 10?&#xD;&#xA;&#xD;&#xA;Is this not valid?&#xD;&#xA;&#xD;&#xA;      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);&#xD;&#xA;      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));  &#xD;&#xA;      glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));  &#xD;&#xA;      glVertexAttribIPointer(3, 10, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, groups));   &#xD;&#xA;      glVertexAttribPointer(4, 10, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, weights));&#xD;&#xA;        " ContentLicense="CC BY-SA 4.0" />
  <row Id="29891" PostHistoryTypeId="1" PostId="10306" RevisionGUID="fc674815-cf3b-462f-b5ef-fa509900970f" CreationDate="2020-10-13T17:06:52.670" UserId="11058" Text="Max number of elements in a vertex attribute" ContentLicense="CC BY-SA 4.0" />
  <row Id="29892" PostHistoryTypeId="3" PostId="10306" RevisionGUID="fc674815-cf3b-462f-b5ef-fa509900970f" CreationDate="2020-10-13T17:06:52.670" UserId="11058" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29893" PostHistoryTypeId="5" PostId="10306" RevisionGUID="442d4234-0b71-4b1b-b436-a5b5cec30180" CreationDate="2020-10-13T17:22:08.867" UserId="11058" Comment="added 70 characters in body" Text="I want to load a vertex buffer with vertices of struct `Vertex`:&#xD;&#xA;&#xD;&#xA;    struct Vertex {&#xD;&#xA;       Vector3 position;&#xD;&#xA;	   Vector3 normal;&#xD;&#xA;       Vector2 uv;&#xD;&#xA;	   int groups[10];&#xD;&#xA;	   float weights[10];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;According to [khronos manual](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml), the number of elements in vertex attributes must be `1,2,3,4`. If that is the case how do I load the vertex attributes consisting of more elements, in this case 10?&#xD;&#xA;&#xD;&#xA;Is this not valid?&#xD;&#xA;&#xD;&#xA;      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);&#xD;&#xA;      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));  &#xD;&#xA;      glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));  &#xD;&#xA;      glVertexAttribIPointer(3, 10, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, groups));   &#xD;&#xA;      glVertexAttribPointer(4, 10, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, weights));&#xD;&#xA;        &#xD;&#xA;I need groups and weight vertex attributes for skeletal deformation." ContentLicense="CC BY-SA 4.0" />
  <row Id="29894" PostHistoryTypeId="6" PostId="10306" RevisionGUID="442d4234-0b71-4b1b-b436-a5b5cec30180" CreationDate="2020-10-13T17:22:08.867" UserId="11058" Comment="added 70 characters in body" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29895" PostHistoryTypeId="2" PostId="10307" RevisionGUID="fc4ba8dd-d682-44a5-90e1-7b71d2adab31" CreationDate="2020-10-13T19:13:47.390" UserId="7952" Text="One very simple way to do it is to just find the straight line distance between the points A and C. Divide that distance by the number of points you want to subdivide+1. Then starting at A moving along the line formed between A and C add that distance for each subdivision. This gives a nice even subdivision without having to argue with PI.&#xD;&#xA;&#xD;&#xA;To get the point on the circle, just take the normalized vector between B and your new point and multiply it by the radius of the circle. The result is a subdivision point on your circle/sphere.&#xD;&#xA;&#xD;&#xA;    float distanceAC = length(C-A);&#xD;&#xA;    float stepLength = distanceAC/(SubdivisionsCount+1); // 4 in this case&#xD;&#xA;    vector v = C-A; // gives a vector pointing from A to C&#xD;&#xA;    v = normalize(v);&#xD;&#xA;    for( int i=1; i&lt;SubdivisionCount+1; i++ ){&#xD;&#xA;         point pointOnLine = A + v*i*stepLength; // Need steplength*i steps along v&#xD;&#xA;         point subdivisionLocation = normalize(pointOnLine-B)*radius;&#xD;&#xA;         // save the subdivision location&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This has the plus of being simple, but the negative is that if you want to do to many steps or you want your steps to be extremely accurate, or you want to subdivide over a very large arc, then accuracy suffers.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29902" PostHistoryTypeId="2" PostId="10309" RevisionGUID="d5f94b41-a067-4250-a23d-e761414f2676" CreationDate="2020-10-14T14:04:41.617" UserId="6496" Text="Using Open 3D Model Viewer, I have converted an OBJ file to an STL file. &#xD;&#xA;In the source file, the Vertex Normals are specified and in the destination, the face normal of the triangles are present which are different than the normals one would get by (a-b) x (a-c), where a, b, c are the vertex coordinates and x is the cross product. How one would compute the face normal in the presence of vertex normals? &#xD;&#xA;&#xD;&#xA;Also, I am given to understand that STL format has a positive octant rule which requires all vertex coordinates to be positive. When the OBJ file has negative vertex coordinates, what should be done in the conversion process?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29903" PostHistoryTypeId="1" PostId="10309" RevisionGUID="d5f94b41-a067-4250-a23d-e761414f2676" CreationDate="2020-10-14T14:04:41.617" UserId="6496" Text="Vertices, Vertex Normals and Face Normals" ContentLicense="CC BY-SA 4.0" />
  <row Id="29904" PostHistoryTypeId="3" PostId="10309" RevisionGUID="d5f94b41-a067-4250-a23d-e761414f2676" CreationDate="2020-10-14T14:04:41.617" UserId="6496" Text="|3d|geometry|mesh|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29909" PostHistoryTypeId="2" PostId="10311" RevisionGUID="423a4d35-10e6-40b8-8081-e62a40f12183" CreationDate="2020-10-14T16:45:47.670" UserId="2654" Text="The standard solution is to reduce the amount of per-vertex data by only specifying the 4 indices that have the highest weights (and rescaling the weights to add up to 1.0). That way, you can pass 4 weights as a `vec4` and 4 indices as a `uvec4`. Also, you should pass the weights as normalized shorts (or bytes if you can accept the quality loss) and indices as bytes if at all possible, to further reduce the per-vertex data storage.&#xD;&#xA;&#xD;&#xA;Most real-time rendering systems are happy with these limitations.&#xD;&#xA;&#xD;&#xA;If that's not acceptable for your needs, then you're going to have to use multiple attributes to send the data. Each attribute can only have 4 components. And while attributes can be arrayed, arraying them like your C struct would waste a bunch of attribute locations, since each array element is considered a *separate* location.&#xD;&#xA;&#xD;&#xA;So you need to send values in multiples of 4. Instead of sending 10 weights/indices, send 12, grouped into 4-element groupings. So the GLSL would look like this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;layout(location = X) uvec4 indices[3];    //Stores 12 indices, consumes 3 locations.&#xD;&#xA;layout(location = X + 3) vec4 weights[3]; //Stores 12 weights, consumes 3 locations.&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The C data structure ought to also store 12 elements for each array.&#xD;&#xA;&#xD;&#xA;To specify them in the vertex format, you would do this (where `X` is the location given above):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glVertexAttribIPointer(3, 4, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, groups) + 0);&#xD;&#xA;glVertexAttribIPointer(4, 4, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, groups) + 16);&#xD;&#xA;glVertexAttribIPointer(5, 4, GL_INT, sizeof(Vertex), (void*)offsetof(Vertex, groups) + 32);&#xD;&#xA;glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, weights) + 0);&#xD;&#xA;glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, weights) + 16);&#xD;&#xA;glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, weights) + 32);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29911" PostHistoryTypeId="2" PostId="10312" RevisionGUID="b6f21e95-a0b8-49b8-99d0-c4ca81cc2d4d" CreationDate="2020-10-15T04:39:18.040" UserId="10250" Text="**Can someone explain the math behind converting a direction-vector or lookAt-vector into a quaternion rotation?**&#xD;&#xA;&#xD;&#xA;**What I am trying to do?**&#xD;&#xA;I am trying to create a custom aim-constraint for a DCC (Maya. Also, Maya already provides one but I have reason to write a custom one). I have the world-space positions of eye and destination using which I can calculate direction vector but I need to calculate quaternion/euler rotation to rotate the object so that I can look at the destination.&#xD;&#xA;&#xD;&#xA;**What I found so far?**&#xD;&#xA;There are couple of thread I found and read so far but some provide engine based approach, some do not provide explanation of math behind it and a few didn't work when converted into code.&#xD;&#xA;I am listing few of them here (for reference)&#xD;&#xA;&#xD;&#xA;1. https://gamedev.stackexchange.com/questions/149006/direction-vector-to-quaternion&#xD;&#xA;2. https://stackoverflow.com/questions/15873996/converting-a-direction-vector-to-a-quaternion-rotation&#xD;&#xA;3. https://answers.unity.com/questions/631836/how-i-can-converting-a-direction-vector-to-quatern.html&#xD;&#xA;4. http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/&#xD;&#xA;5. https://math.stackexchange.com/questions/1765799/convert-direction-vector-to-euler-angles&#xD;&#xA;&#xD;&#xA;**What I am Not looking for?**&#xD;&#xA;- way of calculating quaternion rotation from a (transformation) matrix.&#xD;&#xA;- engine based approach eg: `Quaternion.LookRotation(relativePos, Vector3.up)`&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29912" PostHistoryTypeId="1" PostId="10312" RevisionGUID="b6f21e95-a0b8-49b8-99d0-c4ca81cc2d4d" CreationDate="2020-10-15T04:39:18.040" UserId="10250" Text="Explanation of converting a look-at / direction vector to quaternion rotation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29913" PostHistoryTypeId="3" PostId="10312" RevisionGUID="b6f21e95-a0b8-49b8-99d0-c4ca81cc2d4d" CreationDate="2020-10-15T04:39:18.040" UserId="10250" Text="|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29914" PostHistoryTypeId="5" PostId="10312" RevisionGUID="2475c1ff-73ca-4ea3-be34-26b0b1bc6cac" CreationDate="2020-10-15T05:27:52.510" UserId="10250" Comment="added 7 characters in body" Text="**Can someone please explain the math behind converting a direction-vector or lookAt-vector into a quaternion rotation?**&#xD;&#xA;&#xD;&#xA;**What I am trying to do?**&#xD;&#xA;I am trying to create a custom aim-constraint for a DCC (Maya. Also, Maya already provides one but I have reason to write a custom one). I have the world-space positions of eye and destination using which I can calculate direction vector but I need to calculate quaternion/euler rotation to rotate the object so that I can look at the destination.&#xD;&#xA;&#xD;&#xA;**What I found so far?**&#xD;&#xA;There are couple of thread I found and read so far but some provide engine based approach, some do not provide explanation of math behind it and a few didn't work when converted into code.&#xD;&#xA;I am listing few of them here (for reference)&#xD;&#xA;&#xD;&#xA;1. https://gamedev.stackexchange.com/questions/149006/direction-vector-to-quaternion&#xD;&#xA;2. https://stackoverflow.com/questions/15873996/converting-a-direction-vector-to-a-quaternion-rotation&#xD;&#xA;3. https://answers.unity.com/questions/631836/how-i-can-converting-a-direction-vector-to-quatern.html&#xD;&#xA;4. http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/&#xD;&#xA;5. https://math.stackexchange.com/questions/1765799/convert-direction-vector-to-euler-angles&#xD;&#xA;&#xD;&#xA;**What I am Not looking for?**&#xD;&#xA;- way of calculating quaternion rotation from a (transformation) matrix.&#xD;&#xA;- engine based approach eg: `Quaternion.LookRotation(relativePos, Vector3.up)`&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29915" PostHistoryTypeId="2" PostId="10313" RevisionGUID="e489be3a-40ae-4126-9c93-f77b9a653368" CreationDate="2020-10-15T08:31:11.677" UserId="10129" Text="**To follow up my question and provide partial answer:** &#xD;&#xA;First of all, I'd like to thank [lightxbulb][1] for providing comments which helped me to find solution.&#xD;&#xA;&#xD;&#xA;So here is a basic image, 4 light bounces with 1024 spp:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Problem here is that everything is rather light. Why? Because I've based this part of my HLSL code on **MJP's path tracer** ( https://github.com/TheRealMJP/DXRPathTracer ) which **assumes that if path allows both diffuse and specular then** throughput *= 2.0. However, specular term is allowed only for first bounce with 50% chance probability. I decided that this multiplying was based on testing in his engine and it doesn't have physical basis so I got rid of it and got better results. Specular/metal parts are basically the same, but you can see darkenings in the background which grounds objects in their place.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;However I noticed that throughput is not mutiplied. MJP's algorithm is that throughput = 0, then throughput += diffuse/specular BRDF. He doesn't multiply BRDF results in the fashion presented in PBRT book ( http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html ). So I've added throughput to the payload. **It starts with value (1.0, 1.0, 1.0) and is multiplied by BRDF at each point in the path resulting in below image:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**Based on my knowledge, last image should be closest to ground truth in physics terms.** Also, I think that it's closest to my reference that I've created in MJP's engine and I find it most pleasing. I am aware of the flaws. One is that for many samples (3000-5000 spp), diffuse textures starts having weird contrast and I don't know the reason yet.&#xD;&#xA;&#xD;&#xA;Also russian roulette turned out to be workin poorly in my progressive path tracing. http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Russian_Roulette_and_Splitting.html - maybe after trying to optimize it to reduce variance it would be worth but I'm afraid that it'll still introduce too much noise with very little speedup. It might be worth giving it a try after adding denoiser I think, but for now, I don't think it's a good idea.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/users/10096/lightxbulb&#xD;&#xA;  [2]: https://i.stack.imgur.com/5qtrm.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/4EVAD.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/kxWAH.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29916" PostHistoryTypeId="2" PostId="10314" RevisionGUID="7a670522-58dd-4146-8cb0-20bd529fbaf3" CreationDate="2020-10-15T12:08:28.770" UserId="10129" Text="I've made a few changes in my code, so let's start with basic image that I had problem we that we'll state as a problem at the beginning:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After changing part of the code from:&#xD;&#xA;&#xD;&#xA;    float weight = abs(dot(wo, wm) / (dot(normalTS, wo) * dot(normalTS, wm)));&#xD;&#xA;    if (dot(normalTS, wi) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)&#xD;&#xA;&#xD;&#xA;To this (i.e. moving part of calculations to world-space):&#xD;&#xA;&#xD;&#xA;    float weight = abs(dot(wo, wm) / (dot(triangleNormal, incomingRayDirWS) * dot(normalTS, wm)));&#xD;&#xA;    if (dot(triangleNormal, rayDirWS) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)&#xD;&#xA;&#xD;&#xA;I am getting better results. Here are series of images with different settings:&#xD;&#xA;&#xD;&#xA;1024 spp, 4 bounces&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;5000 spp, 4 bounces&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;5000 spp, 1 bounce&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Notice that 4 bounces version is having more fireflies and noise. Long specular paths might be a reason of introducing noise. Also, 5000 spp are getting darker than 1000 spp. Reason is that path is probably introducing no changes, therefore average color is getting darker. You can see it in the last line of main post. I'm going to put it below for reference:&#xD;&#xA;&#xD;&#xA;    if (dot(triangleNormal, rayDirWS) &gt; 0.0f &amp;&amp; dot(wi, wm) &gt; 0.0f)&#xD;&#xA;    	throughput *= F * G * weight;&#xD;&#xA;    else&#xD;&#xA;    	throughput *= 0;&#xD;&#xA;&#xD;&#xA;Last thing. Here is image generated with better method ( https://schuttejoe.github.io/post/ggximportancesamplingpart2/ ). 1024 spp, 4 bounces:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;&#xD;&#xA;Overall, I got rid of weird noise and artifacts. Algorithm got closer to better method and I think it can be treated as fixed.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M8inp.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/8wAKt.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/AHymQ.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/UQ8fG.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/P2dDQ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29917" PostHistoryTypeId="2" PostId="10315" RevisionGUID="f9c62514-b2ff-4c7c-8df0-37326e43754b" CreationDate="2020-10-15T22:00:02.773" UserId="7571" Text="There is something about these concepts I'm not understanding.  I thought the point of gamma correcting images is to make sure that the values in linear space map correctly when displayed on screen:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tXBqa.png&#xD;&#xA;&#xD;&#xA;It seems from this picture that the camera stops are all getting the same representation (code words) when mapped to the output (purple line).  If this is the case, we shouldn't need tone mapping, but obviously we do.  There is something not right in my thinking and am hoping someone in the internets help me fill in the gap.  Thanks!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29918" PostHistoryTypeId="1" PostId="10315" RevisionGUID="f9c62514-b2ff-4c7c-8df0-37326e43754b" CreationDate="2020-10-15T22:00:02.773" UserId="7571" Text="Tone Mapping vs Gamma Correction" ContentLicense="CC BY-SA 4.0" />
  <row Id="29919" PostHistoryTypeId="3" PostId="10315" RevisionGUID="f9c62514-b2ff-4c7c-8df0-37326e43754b" CreationDate="2020-10-15T22:00:02.773" UserId="7571" Text="|mapping|gamma|tone|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29920" PostHistoryTypeId="2" PostId="10316" RevisionGUID="76670873-75d6-4974-9444-4f697926882b" CreationDate="2020-10-15T22:05:43.480" UserId="13742" Text="I have an image and I want to draw an arbitrary number of objects on that image. The center coordinates of those objects are calculated inside a fragment shader after series of image processing operations. However, because fragment shader gets executed per-fragment, I cannot draw objects centered on those points in the same shader in a reasonably fast way. Somehow, I need to pass those center coordinates that I calculated in my fragment shader to another fragment shader in a second render pass, preferably as uniforms. Then I can use those coordinates in the second fragment shader to draw my objects in an efficient way.&#xD;&#xA;&#xD;&#xA;I thought maybe I can render those points as white spots on a black texture, and after the first pass, I can search the raw data of the texture on the CPU side, then add those white points' coordinates into an array, and send them as uniforms. However, I guess it would be very inefficient as it is a very sparse data (a lot of black pixels and very few white pixels), and I would be doing thousands of iterations (even for a simple 720p image) on that raw data. So, I'm not sure if this should be the way to go. &#xD;&#xA;&#xD;&#xA;How can I do this in an efficient way, in OpenGL ES 2.0 &amp; Metal?&#xD;&#xA;&#xD;&#xA;P.S. I'm new to this area, please enlighten me if I made no sense.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29921" PostHistoryTypeId="1" PostId="10316" RevisionGUID="76670873-75d6-4974-9444-4f697926882b" CreationDate="2020-10-15T22:05:43.480" UserId="13742" Text="How to pass only the needed portion of the data calculated in a fragment shader to another fragment shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29922" PostHistoryTypeId="3" PostId="10316" RevisionGUID="76670873-75d6-4974-9444-4f697926882b" CreationDate="2020-10-15T22:05:43.480" UserId="13742" Text="|rendering|image-processing|fragment-shader|opengl-es|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29923" PostHistoryTypeId="2" PostId="10317" RevisionGUID="0af96640-19fd-48d0-861e-986061dde7d9" CreationDate="2020-10-15T22:37:27.460" UserId="14079" Text="Thank you for the responses! This solution using quadratic bezier interpolation wound up working for me.&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;def ArcPoints(node):&#xD;&#xA;    points = node.GetAllPoints()&#xD;&#xA;    if len(points) &lt; 3:&#xD;&#xA;        return&#xD;&#xA;&#xD;&#xA;    # The first three points of the point object.&#xD;&#xA;    a, b, c = points[:3]&#xD;&#xA;&#xD;&#xA;    samples = 6&#xD;&#xA;    arcPoints = list()&#xD;&#xA;    for i in range(samples):&#xD;&#xA;        t = float(i)/(samples - 1)&#xD;&#xA;        # The quadratic bezier interpolation at t.&#xD;&#xA;        p = a * (1-t) ** 2 + b * 2 * (1-t) * t + c * t ** 2&#xD;&#xA;        arcPoints.append(p)&#xD;&#xA;&#xD;&#xA;    return arcPoints&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29924" PostHistoryTypeId="5" PostId="10316" RevisionGUID="9e6863da-930f-4375-a8fb-02a3a3f3c750" CreationDate="2020-10-16T09:34:56.433" UserId="13742" Comment="deleted 8 characters in body" Text="I have an image and I want to draw an arbitrary number of objects on that image. The center coordinates of those objects are calculated inside a fragment shader after series of image processing operations. However, because fragment shader gets executed per-fragment, I cannot draw objects centered on those points in the same shader in a reasonably fast way. Somehow, I need to pass those center coordinates that I calculated in my fragment shader to another fragment shader in a second render pass, preferably as uniforms. Then I can use those coordinates in the second fragment shader to draw my objects in an efficient way.&#xD;&#xA;&#xD;&#xA;I thought maybe I can render those points as white spots on a black texture, and after the first pass, I can search the raw data of the texture on the CPU side, then add those white points' coordinates into an array, and send them as uniforms. However, I guess it would be very inefficient as it is a very sparse data (a lot of black pixels and very few white pixels), and I would be doing thousands of iterations (even for a simple 720p image) on that raw data. So, I'm not sure if this should be the way to go. &#xD;&#xA;&#xD;&#xA;How can I do this in an efficient way, in OpenGL ES 2.0?&#xD;&#xA;&#xD;&#xA;P.S. I'm new to this area, please enlighten me if I made no sense.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29925" PostHistoryTypeId="2" PostId="10318" RevisionGUID="10c91c78-23f0-4f18-8cfe-e36545ce780b" CreationDate="2020-10-16T13:05:18.193" UserId="4908" Text="I think it would be a good idea to get back to the basics. It's a large post, so there's a recap at the end.&#xD;&#xA;&#xD;&#xA;Colour can be represented in a couple of ways. We can have Red, Green and Blue (RGB). We could have CMYK (used in printing). There's also YCbCr/YUV (one for luminance and two for colour) and similar flavours of that. We have HSV/HSL/HSB (hue, saturation, value/luminance/brightness). And even more. These are called **colour models** (or color models, depending on where you live). RGB is the most popular model in terms of computer graphics. It's how colour film stock, digital sensors, monitors and roughly our eyes work. So, from now I'll be using the RGB colour model. The things in the rest of this post will have equivalents for the other models, but for simplicity it's just RGB for now.&#xD;&#xA;&#xD;&#xA;We have three values, R G and B, but that raises the question. If we have 100% red, 0% green and 0% blue, what kind of red is it? The answer is, we don't know. So, we have to define what kind of red red is, what kind of green green is, what kind of blue blue is and what kind of white white is. White is also important to define. This definition is called the **colour gamut**. The colour gamut defines the chromaticities for red, green, blue and white. Chromaticity is colour but without the luminance (basically just the hue and saturation). By defining the colour gamut, we will know exactly what colour we have for any given RGB value.&#xD;&#xA;&#xD;&#xA;But there's another thing. If we want to send an image to our monitor or save it to a file on our drive, we don't want to have to send over or save a lot of data. We basically want to use the least amount of bits we can. We found out that having 8 bits for the red, green and blue values is enough. However! Our eyes are more sensitive to changes in brightness in dark areas and less sensitive in bright areas of an image. So, while 8 bits is enough for the bright areas, in the darker areas we can really see that we only have 256 possible values for red, green and blue. We fix this by moving around the values in order to use more of those 256 values for the darker areas and less on the brighter areas. Right now I am using 8 bits as an example, but this is the same for any amount of bits (10 and 12 bits is also popular but has the same problem). We do this using a **transfer function**. In short, a transfer function redistributes the values in order to more efficiently use a limited amount of bits.&#xD;&#xA;&#xD;&#xA;**Gamma correction** (or just gamma) is a form of a transfer function. As you can see in your graph (the blue line) it nudges the values upwards which means that the range [0,0.5] becomes [0,0.73]. This means that we have almost 50% more bits for the darker areas of our image! That's what we want. Gamma isn't the only kind of transfer function. Another popular one is log, which is an umbrella term for transfer functions (or colour spaces using transfer functions) that make use of logarithms. With logarithms, each stop of light gets roughly the same amount of bits, which is really useful for images that have a very high dynamic range (like what comes out of a cinema camera). Perceptual quantizer (SMPTE ST 2084) is another transfer function that is used a lot in HDR video (like HDR10 and Dolby Vision) and it's made to take advantage of how our eyes perceive brightness (which falls somewhere between a logarithmic curve and cube-root curve). Values that haven't been transformed by a transfer function are called linear.&#xD;&#xA;&#xD;&#xA;When you combine a colour model, colour gamut and transfer function, you get a **colour space**. A colour space specifies how the colours are represented (what colour is what). There is one very important thing however, you **do not need** a transfer function for a colour space. sRGB is a very popular colour space which is used by practically every computer monitor. It uses the RGB colour model with the sRGB colour gamut (Rec.709 uses the same gamut) and the transfer function is generally a gamma of 2.2 (although it actually isn't, but most use the gamma for simplicity, go look at its Wikipedia page). But you also have linear-sRGB which is also a colour space that just like sRGB, uses the RGB model and sRGB gamut, but doesn't have a transfer function. The values are in linear (often referred to as &quot;scene linear&quot;).&#xD;&#xA;&#xD;&#xA;To try and make things a bit more clear, here's an example showing how a transfer function works when displaying an image that is either CGI or a video game being rendered. The first thing that is important is that both the computer/program and the display need to agree on the colour space to use. In this example, we use sRGB. Basically, the program sends the sRGB image to the display and the display takes that sRGB image and converts it to the actual electronic signals to send to the pixels.&#xD;&#xA;[![Image being sent to display][1]][1]&#xD;&#xA;&#xD;&#xA;And now we finally get to tone mapping. A **tone mapper** is a function that takes in a large, generally infinite, range of values and compresses it to a smaller, often limited, range of values. Tone mapping is generally used to apply a &quot;look&quot;. A very popular tone mapping is the filmic s-curve, which is called a &quot;film characteristic curve&quot; or &quot;Hurter–Driffield curve&quot;. It adds some contrast in the shadows and instead of the highlights clipping once they reach 100% brightness, it adds a nice roll-off that gradually brings it to 100%. This tone mapper is used in a lot of places. It's how film stock behaves, it's what digital cinema cameras often do, in video games they use this curve. Basically, because it looks good and with it we can see values above 100% (because the tone mapper maps it to something below 100%).&#xD;&#xA;&#xD;&#xA;However, you **don't need** a tone mapper. If you take a cheap camcorder, DSLR, your phone (depending on the settings) or a broadcast camera they use to film the news and such (especially before the 2010s), then all of them don't do any kind of tone mapping. They just apply the sRGB or Rec.709 colour space (and thus also the transfer function) and that's it. What you often do see is that parts of the image go to 100% white very quickly and then clips Here's a picture that I took with my phone. It's just normal average sRGB and no tonemapping. [![Image of clipped highlights][2]][2]&#xD;&#xA;You can see that the cloud is completely white and the trees are quite dark. Using a tone mapper, I could bring those values closer together and not have the clouds be 100% white without any detail, while still being able to see detail in the trees.&#xD;&#xA;&#xD;&#xA;## To recap ##&#xD;&#xA;* Gamma correction is a type of transfer function, which is part of a colour space.&#xD;&#xA;* A colour space tells us how to represent and store colours.&#xD;&#xA;* When we want to send images to our display, we need to apply the transfer function.&#xD;&#xA;* The display will undo that transfer function (and will do it no matter what, so you have to apply the transfer function on your end to get the correct values when displayed).&#xD;&#xA;* A tone mapper is both to apply a look and to compress the range of RGB values to a smaller range so that we can see a high dynamic range image on a standard dynamic range monitor.&#xD;&#xA;* While you need to apply a transfer function when sending the image to the display, you don't need to apply a tone mapper. Only if you want to.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MTQ4u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gv7ed.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29926" PostHistoryTypeId="6" PostId="10316" RevisionGUID="6f358435-215d-4447-a547-cef3b8cf90a9" CreationDate="2020-10-16T13:19:46.723" UserId="2654" Comment="edited tags" Text="|rendering|image-processing|fragment-shader|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29927" PostHistoryTypeId="5" PostId="10318" RevisionGUID="72fd90b0-fb5e-4c13-9f36-0051e6606820" CreationDate="2020-10-16T16:28:44.570" UserId="4908" Comment="added a sentence I forgot to write, that still adds value to the answer" Text="I think it would be a good idea to get back to the basics. It's a large post, so there's a recap at the end.&#xD;&#xA;&#xD;&#xA;Colour can be represented in a couple of ways. We can have Red, Green and Blue (RGB). We could have CMYK (used in printing). There's also YCbCr/YUV (one for luminance and two for colour) and similar flavours of that. We have HSV/HSL/HSB (hue, saturation, value/luminance/brightness). And even more. These are called **colour models** (or color models, depending on where you live). RGB is the most popular model in terms of computer graphics. It's how colour film stock, digital sensors, monitors and roughly our eyes work. So, from now I'll be using the RGB colour model. The things in the rest of this post will have equivalents for the other models, but for simplicity it's just RGB for now.&#xD;&#xA;&#xD;&#xA;We have three values, R G and B, but that raises the question. If we have 100% red, 0% green and 0% blue, what kind of red is it? The answer is, we don't know. So, we have to define what kind of red red is, what kind of green green is, what kind of blue blue is and what kind of white white is. White is also important to define. This definition is called the **colour gamut**. The colour gamut defines the chromaticities for red, green, blue and white. Chromaticity is colour but without the luminance (basically just the hue and saturation). By defining the colour gamut, we will know exactly what colour we have for any given RGB value.&#xD;&#xA;&#xD;&#xA;But there's another thing. If we want to send an image to our monitor or save it to a file on our drive, we don't want to have to send over or save a lot of data. We basically want to use the least amount of bits we can. We found out that having 8 bits for the red, green and blue values is enough. However! Our eyes are more sensitive to changes in brightness in dark areas and less sensitive in bright areas of an image. So, while 8 bits is enough for the bright areas, in the darker areas we can really see that we only have 256 possible values for red, green and blue. We fix this by moving around the values in order to use more of those 256 values for the darker areas and less on the brighter areas. Right now I am using 8 bits as an example, but this is the same for any amount of bits (10 and 12 bits is also popular but has the same problem). We do this using a **transfer function**. In short, a transfer function redistributes the values in order to more efficiently use a limited amount of bits.&#xD;&#xA;&#xD;&#xA;**Gamma correction** (or just gamma) is a form of a transfer function. As you can see in your graph (the blue line) it nudges the values upwards which means that the range [0,0.5] becomes [0,0.73]. This means that we have almost 50% more bits for the darker areas of our image! That's what we want. Gamma isn't the only kind of transfer function. Another popular one is log, which is an umbrella term for transfer functions (or colour spaces using transfer functions) that make use of logarithms. With logarithms, each stop of light gets roughly the same amount of bits, which is really useful for images that have a very high dynamic range (like what comes out of a cinema camera). Perceptual quantizer (SMPTE ST 2084) is another transfer function that is used a lot in HDR video (like HDR10 and Dolby Vision) and it's made to take advantage of how our eyes perceive brightness (which falls somewhere between a logarithmic curve and cube-root curve). Values that haven't been transformed by a transfer function are called linear.&#xD;&#xA;&#xD;&#xA;When you combine a colour model, colour gamut and transfer function, you get a **colour space**. A colour space specifies how the colours are represented (what colour is what). There is one very important thing however, you **do not need** a transfer function for a colour space. sRGB is a very popular colour space which is used by practically every computer monitor. It uses the RGB colour model with the sRGB colour gamut (Rec.709 uses the same gamut) and the transfer function is generally a gamma of 2.2 (although it actually isn't, but most use the gamma for simplicity, go look at its Wikipedia page). But you also have linear-sRGB which is also a colour space that just like sRGB, uses the RGB model and sRGB gamut, but doesn't have a transfer function. The values are in linear (often referred to as &quot;scene linear&quot;).&#xD;&#xA;&#xD;&#xA;To try and make things a bit more clear, here's an example showing how a transfer function works when displaying an image that is either CGI or a video game being rendered. The first thing that is important is that both the computer/program and the display need to agree on the colour space to use. In this example, we use sRGB. Basically, the program sends the sRGB image to the display and the display takes that sRGB image and converts it to the actual electronic signals to send to the pixels.&#xD;&#xA;[![Image being sent to display][1]][1]&#xD;&#xA;&#xD;&#xA;And now we finally get to tone mapping. A **tone mapper** is a function that takes in a large, generally infinite, range of values and compresses it to a smaller, often limited, range of values. Tone mapping is generally used to apply a &quot;look&quot;. A very popular tone mapping is the filmic s-curve, which is called a &quot;film characteristic curve&quot; or &quot;Hurter–Driffield curve&quot;. It adds some contrast in the shadows and instead of the highlights clipping once they reach 100% brightness, it adds a nice roll-off that gradually brings it to 100%. This tone mapper is used in a lot of places. It's how film stock behaves, it's what digital cinema cameras often do, in video games they use this curve. Basically, because it looks good and with it we can see values above 100% (because the tone mapper maps it to something below 100%). If you want to tone map your image, it should be done before the transfer function/colour space conversion (for example converting from linear-sRGB to sRGB), because tone mapping isn't part of a colour space and is basically a look (just like applying a filter over an image).&#xD;&#xA;&#xD;&#xA;However, you **don't need** a tone mapper. If you take a cheap camcorder, DSLR, your phone (depending on the settings) or a broadcast camera they use to film the news and such (especially before the 2010s), then all of them don't do any kind of tone mapping. They just apply the sRGB or Rec.709 colour space (and thus also the transfer function) and that's it. What you often do see is that parts of the image go to 100% white very quickly and then clips Here's a picture that I took with my phone. It's just normal average sRGB and no tone mapping. [![Image of clipped highlights][2]][2]&#xD;&#xA;You can see that the cloud is completely white and the trees are quite dark. Using a tone mapper, I could bring those values closer together and not have the clouds be 100% white without any detail, while still being able to see detail in the trees.&#xD;&#xA;&#xD;&#xA;## To recap ##&#xD;&#xA;* Gamma correction is a type of transfer function, which is part of a colour space.&#xD;&#xA;* A colour space tells us how to represent and store colours.&#xD;&#xA;* When we want to send images to our display, we need to apply the transfer function.&#xD;&#xA;* The display will undo that transfer function (and will do it no matter what, so you have to apply the transfer function on your end to get the correct values when displayed).&#xD;&#xA;* A tone mapper is both to apply a look and to compress the range of RGB values to a smaller range so that we can see a high dynamic range image on a standard dynamic range monitor.&#xD;&#xA;* While you need to apply a transfer function when sending the image to the display, you don't need to apply a tone mapper. Only if you want to.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MTQ4u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gv7ed.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29929" PostHistoryTypeId="50" PostId="10235" RevisionGUID="d37ee2f2-1b94-4217-8129-e2dc4d119a95" CreationDate="2020-10-17T02:05:10.483" UserId="-1" />
  <row Id="29930" PostHistoryTypeId="2" PostId="10319" RevisionGUID="69856d93-cc04-4ac5-ace6-9614d11f246b" CreationDate="2020-10-17T03:35:26.687" UserId="14079" Text="I am trying to create a spherical interpolation with 3 points. I'm currently using Quadratic Bezier Interpolation but [have been told][1] I should use Rational Quadratic Bezier Curve in order to get a perfectly circular curve. I have tried implementing this based on the formula I found [here][2] (3 control points A,B and C, 3 weights W1, W2, W3 and a time t):&#xD;&#xA;&#xD;&#xA;`CurvePoint = (A*W1*(1-t)^2 + B*W2*2t(1-t) + C*W3*t^2) / (W1*(1-t)^2 + W2*2t(1-t) + W3*t^2).`&#xD;&#xA;&#xD;&#xA;How do I determine the correct weight values for this to work as a circle? Is that even possible without moving the middle point? Thank you.&#xD;&#xA;&#xD;&#xA;Here is the code I am using (with all weights set to 1.0) and the curve it produces:&#xD;&#xA;```python&#xD;&#xA;&#xD;&#xA;def ArcPoints(node):&#xD;&#xA;    points = node.GetAllPoints()&#xD;&#xA;&#xD;&#xA;    # The three points of the point object&#xD;&#xA;    a, b, c = points[:3]&#xD;&#xA;&#xD;&#xA;    samples = 6&#xD;&#xA;    arcPoints = list()&#xD;&#xA;    for i in range(samples):&#xD;&#xA;        t = float(i)/(samples - 1)&#xD;&#xA;        w1 = 1&#xD;&#xA;        w2 = 1&#xD;&#xA;        w3 = 1&#xD;&#xA;        p2 = (a * w1 * (1-t) ** 2 + b * w2 * 2*t * (1-t) + c * w3 * t ** 2 ) / (w1 * (1-t) ** 2 + w2 * 2*t * (1-t) + w3 * t**2)&#xD;&#xA;        arcPoints.append(p)&#xD;&#xA;&#xD;&#xA;    return arcPoints&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;[![Rational Quadratic Bezier Curve][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/10317/14079&#xD;&#xA;  [2]: http://demofox.org/bezquadrational.html&#xD;&#xA;  [3]: https://i.stack.imgur.com/yQEbu.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="29931" PostHistoryTypeId="1" PostId="10319" RevisionGUID="69856d93-cc04-4ac5-ace6-9614d11f246b" CreationDate="2020-10-17T03:35:26.687" UserId="14079" Text="Determining Rational Quadratic Bezier Curve Weights for Circle" ContentLicense="CC BY-SA 4.0" />
  <row Id="29932" PostHistoryTypeId="3" PostId="10319" RevisionGUID="69856d93-cc04-4ac5-ace6-9614d11f246b" CreationDate="2020-10-17T03:35:26.687" UserId="14079" Text="|mathematics|interpolation|curve|bezier-curve|nurbs|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29933" PostHistoryTypeId="5" PostId="10160" RevisionGUID="12fb994a-9533-4b47-81b1-b0b84f1288de" CreationDate="2020-10-17T12:41:11.953" UserId="13559" Comment="deleted 236 characters in body" Text="I'm implementing Peter Shirley's &quot;Raytracer in a Weekend: The next week&quot; and I'm having some trouble with rendering a scene with a light. I'm not sure if the issue is the background color or the light itself but the raytracer seems to be working fine in any scenes that have no lights.&#xD;&#xA;&#xD;&#xA;The image rendered is supposed to be:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;but it actually turns out as:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;When I try to troubleshoot and change the background color to blue the image is:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Hopefully someone who has implemented this raytracer before or who has intuition about raytracing has an idea why this might be happening??&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aA4Nu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cmm6V.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/wTZdL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29934" PostHistoryTypeId="2" PostId="10320" RevisionGUID="4ce86332-84a7-4c74-9f7c-9ffbf17dfa75" CreationDate="2020-10-17T18:00:21.963" UserId="2287" Text="**Unbound descriptor tables**&#xD;&#xA;&#xD;&#xA;If a `D3D12_VERSIONED_ROOT_SIGNATURE_DESC` defines *N* `D3D12_ROOT_PARAMETER`s (with `ParameterType` set to `D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE`) that are each visible to a single (non-compute) shader stage, does each of these require a corresponding `ID3D12GraphicsCommandList::SetGraphicsRootDescriptorTable` invocation (with an allocated shader visible descriptor range) after binding the `ID3D12RootSignature` and `ID3D12PipelineState`, even if the latter does only use a subset of the (non-compute) shader stages (e.g., no geometry shader, etc.)? Stated differently, does `ID3D12GraphicsCommandList::SetGraphicsRootDescriptorTable` need to be invoked for root parameters associated with shader stages that are **not** defined for the `ID3D12PipelineState` **but** are part of the `ID3D12RootSignature`?&#xD;&#xA;&#xD;&#xA;**Unbound descriptors**&#xD;&#xA;&#xD;&#xA;If a shader uses say 2 SRVs, but up to 64 SRVs could be potentially bound for the `ID3D12RootSignature`, is it necessary that the 62 unused SRVs, which are part of the same shader visible descriptor range(s), are actually associated with an **existing** SRV of a resource that is still **alive** (which is not automatically guaranteed if the shader visible descriptor heaps are used in a ring buffer fashion, as initially the descriptors are unused and later on could be reused)? Or does one for example need to use an SRV of a dummy resource that is kept alive?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29935" PostHistoryTypeId="1" PostId="10320" RevisionGUID="4ce86332-84a7-4c74-9f7c-9ffbf17dfa75" CreationDate="2020-10-17T18:00:21.963" UserId="2287" Text="Unbound descriptor tables and descriptors for fat root signatures" ContentLicense="CC BY-SA 4.0" />
  <row Id="29936" PostHistoryTypeId="3" PostId="10320" RevisionGUID="4ce86332-84a7-4c74-9f7c-9ffbf17dfa75" CreationDate="2020-10-17T18:00:21.963" UserId="2287" Text="|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29937" PostHistoryTypeId="2" PostId="10321" RevisionGUID="74d283af-f241-433f-8ff0-5cd330748be1" CreationDate="2020-10-17T18:11:17.000" UserId="2287" Text="The CBV (constant buffer view) `SizeInBytes` is required to be 256-byte aligned. (Cref.: https://docs.microsoft.com/en-us/windows/win32/direct3d12/creating-descriptors​ ).&#xD;&#xA;&#xD;&#xA;Should the associated `ID3D12Resource` have a `Width` (i.e. `D3D12_RESOURCE_DESC`) equal to/greater than that same size or may it be smaller, as the additional padding of the CBV won't be accessed/used in the shaders anyway? For example, is it allowed to create a CBV with `SizeInBytes` equal to 256 bytes for a `ID3D12Resource` with `Width` equal to 64 bytes?&#xD;&#xA;&#xD;&#xA;Are there constraints for the IBV (index buffer view) and VBV (vertex buffer view) `SizeInBytes` as well?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29938" PostHistoryTypeId="1" PostId="10321" RevisionGUID="74d283af-f241-433f-8ff0-5cd330748be1" CreationDate="2020-10-17T18:11:17.000" UserId="2287" Text="CBV, IBV and VBV byte alignment" ContentLicense="CC BY-SA 4.0" />
  <row Id="29939" PostHistoryTypeId="3" PostId="10321" RevisionGUID="74d283af-f241-433f-8ff0-5cd330748be1" CreationDate="2020-10-17T18:11:17.000" UserId="2287" Text="|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29940" PostHistoryTypeId="2" PostId="10322" RevisionGUID="e183b24a-1569-42f0-8c0c-ff851834fd17" CreationDate="2020-10-17T19:40:33.637" UserId="15099" Text="For sampling a uniform volume you use the mean free path of a photon:&#xD;&#xA;&#xD;&#xA;```float dt = -logf(1.0f - Xi) / uT;```&#xD;&#xA;&#xD;&#xA;where:&#xD;&#xA;* Xi is a random variable in [0, 1]&#xD;&#xA;* uT is the extinction coefficient (sum of out-scattering and absorption)&#xD;&#xA;&#xD;&#xA;The pdf of a raytime (t) in this uniform volume is given by:&#xD;&#xA;&#xD;&#xA;```float pdf = uT * expf(-t * uT);```&#xD;&#xA;&#xD;&#xA;In your case, you do not have a uniform volume, but instead one whose density is exponentially decreasing according to the distance from the surface of a sphere.&#xD;&#xA;&#xD;&#xA;Approaches for solving this typically involve raymarching which samples a density at each step and treats the step as a uniform volume. This is approximate and introduces some bias, but there are ways of reducing the bias.&#xD;&#xA;&#xD;&#xA;I recommend reading Monte Carlo Methods for Physically Based Volume Rendering:&#xD;&#xA;* https://jannovak.info/publications/VolumeCourse/index.html&#xD;&#xA;&#xD;&#xA;Another good resource is pbrtv3, particularly chapters 11 and 15:&#xD;&#xA;* http://www.pbr-book.org/3ed-2018/Volume_Scattering.html&#xD;&#xA;* http://www.pbr-book.org/3ed-2018/Light_Transport_II_Volume_Rendering.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="29941" PostHistoryTypeId="50" PostId="8790" RevisionGUID="22b6dc22-056d-4001-a1e9-8e798a5513c0" CreationDate="2020-10-18T08:03:55.500" UserId="-1" />
  <row Id="29945" PostHistoryTypeId="2" PostId="10324" RevisionGUID="8278465a-f2ba-4acd-93ed-cdcace6a1b67" CreationDate="2020-10-19T17:07:51.867" UserId="48" Text="Everything is allowed to be left unbound / invalid / uninitialized as long as the shader doesn't try to look at it. However, if the shader _does_ try to look at it, it could trigger a GPU crash / TDR.&#xD;&#xA;&#xD;&#xA;In practice, it may be a good idea to explicitly clear out descriptors that you know aren't going to be valid: either setting them to a null descriptor, or pointing to a dummy resource. Loading/sampling from a null SRV/UAV descriptor in a descriptor table is defined to just return 0 and not crash. Likewise, stores to a null UAV descriptor are dropped on the floor without crashing.&#xD;&#xA;&#xD;&#xA;However, this guarantee doesn't apply to descriptors directly in the root signature; trying to load/sample from a null root descriptor can crash the GPU. Likewise trying to read from a null descriptor table can crash. See the [D3D12 functional spec](https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html#null-descriptors) for more." ContentLicense="CC BY-SA 4.0" />
  <row Id="29946" PostHistoryTypeId="5" PostId="10321" RevisionGUID="cb6d3e3a-df65-4dfa-bbae-bb4b53f37018" CreationDate="2020-10-19T20:17:53.307" UserId="2287" Comment="deleted 91 characters in body" Text="The CBV (constant buffer view) `SizeInBytes` is required to be 256-byte aligned.&#xD;&#xA;&#xD;&#xA;Should the associated `ID3D12Resource` have a `Width` (i.e. `D3D12_RESOURCE_DESC`) equal to/greater than that same size or may it be smaller, as the additional padding of the CBV won't be accessed/used in the shaders anyway? For example, is it allowed to create a CBV with `SizeInBytes` equal to 256 bytes for a `ID3D12Resource` with `Width` equal to 64 bytes?&#xD;&#xA;&#xD;&#xA;Are there constraints for the IBV (index buffer view) and VBV (vertex buffer view) `SizeInBytes` as well?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29948" PostHistoryTypeId="2" PostId="10325" RevisionGUID="f417433e-ca7c-4568-ac9b-59ce1bc3300c" CreationDate="2020-10-20T07:27:08.530" UserId="7647" Text="Check out the section on [Circular Arcs and Circles](https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS/RB-circles.html), from [Ching-Kuang Shene's excellent computational geometry course notes](https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/notes.html):&#xD;&#xA;&#xD;&#xA;&gt; [G]iven three control points P0, P1 and P2 such that P0P1 = P1P2 holds, if we choose w, the weight for P1, to be sin(a), where a is the half angle at control point P1, the resulting rational Bézier curve is a circle.&#xD;&#xA;&#xD;&#xA;The second diagram on that page is particularly useful. If P0 is at (0,0), P1 is at (1,0), and P2 is at (1,1), then the angle at P1 is 90 degrees; half that is 45, so assigning weights w0 = w2 = 1 and w1 = sin(45) = 1/sqrt(2) will produce a circle." ContentLicense="CC BY-SA 4.0" />
  <row Id="29949" PostHistoryTypeId="2" PostId="10326" RevisionGUID="6eacbb64-eda9-4dd1-ba8e-8d788e81af85" CreationDate="2020-10-20T15:00:35.723" UserId="14025" Text="I need to draw some shapes filled with linear gradients starting from every point and blending smoothly between points, like an OpenGL standard shading (I guess it is called `GL_LINEAR` or `VERTEX_COLOR`), i.e. GIMP / Illustrator / Krita / Paint3D, etc. Something fast and simple.  &#xD;&#xA;required result:  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/O6X3T.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29950" PostHistoryTypeId="1" PostId="10326" RevisionGUID="6eacbb64-eda9-4dd1-ba8e-8d788e81af85" CreationDate="2020-10-20T15:00:35.723" UserId="14025" Text="Is there a tool capable of drawing a triangular linear gradient fill?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29951" PostHistoryTypeId="3" PostId="10326" RevisionGUID="6eacbb64-eda9-4dd1-ba8e-8d788e81af85" CreationDate="2020-10-20T15:00:35.723" UserId="14025" Text="|opengl|texture|geometry|pixel-shader|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29952" PostHistoryTypeId="2" PostId="10327" RevisionGUID="ced387f6-5819-42b2-b9e6-9cdba9876e98" CreationDate="2020-10-20T17:56:50.360" UserId="48" Text="Most 2D graphics programs are able to do linear gradients with arbitrary orientations. If you don't mind a little work, it is possible to set this up to imitate the 2D linear interpolation across a triangle.&#xD;&#xA;&#xD;&#xA;Set up two layers:&#xD;&#xA;&#xD;&#xA;* Pick two of the colors, say red and green, and set up a linear gradient between those two colors along the red-green edge.&#xD;&#xA;* In a second layer, set up a linear gradient between blue and transparent-blue (i.e. the same color with alpha = 0). Orient it perpendicular to the red-green edge." ContentLicense="CC BY-SA 4.0" />
  <row Id="29958" PostHistoryTypeId="2" PostId="10329" RevisionGUID="717acbae-c7e2-4a95-b16f-427ca80c3636" CreationDate="2020-10-21T22:12:09.440" UserId="14025" Text="a quick working wrapper for OpenGL from R:  &#xD;&#xA;```&#xD;&#xA;require(rgl)&#xD;&#xA;tr.points &lt;- matrix(c(1,0,0, cos(60/180*pi),sin(60/180*pi),0, 0,0,0),&#xD;&#xA;                    ncol=3, byrow=TRUE)&#xD;&#xA;triangles3d(tr.points, col=c('red', 'green', 'blue'),&#xD;&#xA;            lit=FALSE, smooth=TRUE, textype='rgb',&#xD;&#xA;            lwd=1.0,&#xD;&#xA;            depth_mask=TRUE, depth_test='always')&#xD;&#xA;rgl.viewpoint(theta=0, phi=0,&#xD;&#xA;              fov=0, zoom=1,&#xD;&#xA;              interactive=FALSE)&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="29959" PostHistoryTypeId="2" PostId="10330" RevisionGUID="1d6e584e-78f6-4922-bbcd-a91c2d0e1c79" CreationDate="2020-10-22T04:58:04.003" UserId="7571" Text="I need a point clarified.  According to [wikipedia](https://en.wikipedia.org/wiki/High-dynamic-range_video), SMPT ST 2084 EOTF is this:  [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/M8d5a.png&#xD;&#xA;&#xD;&#xA;I've seen this equation implemented in game engines where for **L** they feed the channels **RGB**, each of which is 0 to 10,000 and normalize them.  Am confused because luminance from what I understand is supposed to be one quantity instead of 3.  I understood luminance to be kind'a like speed in physics, and the RGB is the &quot;direction&quot; vector. Is it really correct to plug the RGB linear channels in into **L** (the &quot;linear optical luminance&quot;) in this equation, or am I misunderstanding something? The way I think of it, we need to compute the luminance from the RGB triplet, and then plug that value into L, then from V we compute colors.  &#xD;&#xA;&#xD;&#xA;Where is my thinking wrong? &#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="29960" PostHistoryTypeId="1" PostId="10330" RevisionGUID="1d6e584e-78f6-4922-bbcd-a91c2d0e1c79" CreationDate="2020-10-22T04:58:04.003" UserId="7571" Text="Luminace, RGB, and SMPT ST 2084 EOTF" ContentLicense="CC BY-SA 4.0" />
  <row Id="29961" PostHistoryTypeId="3" PostId="10330" RevisionGUID="1d6e584e-78f6-4922-bbcd-a91c2d0e1c79" CreationDate="2020-10-22T04:58:04.003" UserId="7571" Text="|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29962" PostHistoryTypeId="2" PostId="10331" RevisionGUID="43d97ed7-9e27-45b7-970f-edefe6214049" CreationDate="2020-10-22T11:31:15.807" UserId="4908" Text="I fully understand the confusion (I was also a bit confused when I saw it). So, I decided to look at the ACES implementation of the ST 2084 EOTF. https://github.com/ampas/aces-dev/blob/v1.0.3/transforms/ctl/lib/ACESlib.Utilities_Color.ctl#L402&#xD;&#xA;&#xD;&#xA;From there it is very clear: You perform the transfer function on the R, G and B values separately and not by first calculating the luminance. The confusion most likely comes from the fact that we are talking about two different kinds of luminance.&#xD;&#xA;&#xD;&#xA;We have [*relative luminance*][1], which is the luminance we use when talking about colours and can be calculated with $Y=0.2126R+0.7152G+0.0722B$&#xD;&#xA;&#xD;&#xA;We also have [*luminance*][2] for which the SI unit is cd/m2 and basically means how bright something is.&#xD;&#xA;&#xD;&#xA;You, and I when I first read your post, were thinking about *relative luminance*, but the Wikipedia article was talking about just *luminance*. In this case, it talks about the luminance of red light, green light and blue light separately (since a camera captures it separately and a monitor produces it separately). I'm pretty sure the ST 2048 spec is more clear about this, but that's behind a paywall.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Relative_luminance&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luminance" ContentLicense="CC BY-SA 4.0" />
  <row Id="29963" PostHistoryTypeId="2" PostId="10332" RevisionGUID="1923260b-0139-4f30-a6d9-aa4c96edc6d8" CreationDate="2020-10-22T16:44:37.143" UserId="228" Text="I'm reading through [Learn OpenGL][1] to refresh the basic concepts as I haven't touched in quite some time.&#xD;&#xA;&#xD;&#xA;Specifically I still think I cannot quite understand the meaning of VAO and VBO, the book mainly proceeds through examples it doesn't really give rigorous definitions.&#xD;&#xA;&#xD;&#xA;About the VBO:&#xD;&#xA;&#xD;&#xA;&gt; With the vertex data defined we’d like to send it as input to the&#xD;&#xA;&gt; first process of the graphics pipeline: the vertex shader. This is&#xD;&#xA;&gt; done by creating memory on the GPU where we store the vertex data,&#xD;&#xA;&gt; configure how OpenGL should interpret the memory and specify how to&#xD;&#xA;&gt; send the data to the graphics card. The vertex shader then processes&#xD;&#xA;&gt; as much vertices as we tell it to from its memory.&#xD;&#xA;&gt; We manage this memory via so called vertex buffer objects (VBO) that&#xD;&#xA;&gt; can store a large number of vertices in the GPU’s memory. The&#xD;&#xA;&gt; advantage of using those buffer objects is that we can send large&#xD;&#xA;&gt; batches of data all at once to the graphics card, and keep it there if&#xD;&#xA;&gt; there’s enough memory left, without having to send data one vertex at&#xD;&#xA;&gt; a time. Sending data to the graphics card from the CPU is relatively&#xD;&#xA;&gt; slow, so wherever we can we try to send as much data as possible at&#xD;&#xA;&gt; once. Once the data is in the graphics card’s memory the vertex shader&#xD;&#xA;&gt; has almost instant access to the vertices making it extremely fast&#xD;&#xA;&#xD;&#xA;So my understanding of VBO they're essentially Buffer objects (bunch of bytes to be sent to the GPU) with the difference that VBO are specifically dedicated to Vertex Data. Is this correct?&#xD;&#xA;&#xD;&#xA;About the VAO:&#xD;&#xA;&#xD;&#xA;Here instead I don't really understand.&#xD;&#xA;&#xD;&#xA;&gt; A **vertex array object** (also known as **VAO**) can be bound just&#xD;&#xA;&gt; like a vertex buffer object and any subsequent vertex attribute calls&#xD;&#xA;&gt; from that point on will be stored inside the VAO. &#xD;&#xA;&#xD;&#xA;What does it mean *any subsequent vertex attribute calls from that point on will be stored inside the VAO*, I don't understand the &quot;call be stored&quot; bit, does it mean somewhere in the opengl context created we store like some data related to the vertex attribute calls (like the pair input output of the call? the output of the call? something related to the call?).&#xD;&#xA;&#xD;&#xA;&gt; This has the advantage that when configuring vertex attribute pointers you only&#xD;&#xA;&gt; have to make those calls once and whenever we want to draw the object,&#xD;&#xA;&gt; we can just bind the corresponding VAO. This makes switching between&#xD;&#xA;&gt; different vertex data and attribute configurations as easy as binding&#xD;&#xA;&gt; a different VAO. All the state we just set is stored inside the VAO.&#xD;&#xA;&#xD;&#xA;I don't understand the advantage here. I understand the &quot;call made once&quot;, because they're stored in the VAO (whatever the &quot;stored part means&quot;). The switching part does maybe mean I can create multiple VAO each one capturing different Vertex Attributes calls and I can just bind each one of these when I need without calling again the vertex attribute?&#xD;&#xA;&#xD;&#xA;For reference I've also found [this question][2] which I thought had an interesting answer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/book/book_pdf.pdf&#xD;&#xA;  [2]: https://stackoverflow.com/questions/21652546/what-is-the-role-of-glbindvertexarrays-vs-glbindbuffer-and-what-is-their-relatio" ContentLicense="CC BY-SA 4.0" />
  <row Id="29964" PostHistoryTypeId="1" PostId="10332" RevisionGUID="1923260b-0139-4f30-a6d9-aa4c96edc6d8" CreationDate="2020-10-22T16:44:37.143" UserId="228" Text="Understanding VAO and VBO" ContentLicense="CC BY-SA 4.0" />
  <row Id="29965" PostHistoryTypeId="3" PostId="10332" RevisionGUID="1923260b-0139-4f30-a6d9-aa4c96edc6d8" CreationDate="2020-10-22T16:44:37.143" UserId="228" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29966" PostHistoryTypeId="2" PostId="10333" RevisionGUID="bee06ee3-2b4b-4943-aa63-825f8d985a6e" CreationDate="2020-10-22T18:05:02.800" UserId="2654" Text="&gt; So my understanding of VBO they're essentially Buffer objects (bunch of bytes to be sent to the GPU) with the difference that VBO are specifically dedicated to Vertex Data. Is this correct?&#xD;&#xA;&#xD;&#xA;A &quot;VBO&quot; is not really a thing, and I really wish tutorials would stop pretending that they are.&#xD;&#xA;&#xD;&#xA;You are correct in that there exist [buffer objects][1]. These are linear arrays of unformatted data that the GPU stores and can access for various processes. One of those &quot;various processes&quot; that the GPU can use them for is providing array data for vertex rendering operations.&#xD;&#xA;&#xD;&#xA;But the buffer *itself* isn't special. It doesn't become a different thing just because you use it for vertex data, and there is no rule that says that a buffer you're currently using for vertex data cannot be used for other buffer usages too.&#xD;&#xA;&#xD;&#xA;Note that this is different from how textures work. When you create a texture object and bind it as a 2D texture, that texture object *forever* becomes a 2D texture. You cannot later bind it as a 1D or a cubemap or whatever. Buffer objects aren't like that; where you bind them defines only how you're *currently* using them.&#xD;&#xA;&#xD;&#xA;&gt; What does it mean &quot;any subsequent vertex attribute calls from that point on will be stored inside the VAO&quot;&#xD;&#xA;&#xD;&#xA;This is yet another annoying tutorial trope: that objects &quot;store calls&quot; or are macros or other such nonsense.&#xD;&#xA;&#xD;&#xA;[Objects in OpenGL][2] don't store calls; they store *state*. They're like structs; they have data members. Binding an object to the OpenGL context allows OpenGL operations that access certain state to find that state within the bound object. So if you call a function that modifies certain state that is from a bound object, that function will modify the state within the object.&#xD;&#xA;&#xD;&#xA;When you bind a VAO, you are binding an object that stores the state used for vertex arrays. When you call a function that modifies the state for vertex arrays, that function will modify the state stored in the VAO currently bound. When you render, the rendering system will use the vertex array state found in the currently bound VAO.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/OpenGL_Object" ContentLicense="CC BY-SA 4.0" />
  <row Id="29967" PostHistoryTypeId="50" PostId="10246" RevisionGUID="cc0a2f36-9062-4dbb-85f2-294c99037046" CreationDate="2020-10-22T19:03:45.340" UserId="-1" />
  <row Id="29969" PostHistoryTypeId="50" PostId="10248" RevisionGUID="8894a0c3-d2fe-4869-9173-fbf2b6c57738" CreationDate="2020-10-22T20:02:00.203" UserId="-1" />
  <row Id="29970" PostHistoryTypeId="2" PostId="10334" RevisionGUID="e40ab02b-79b7-4cde-9448-91ab9381f7b0" CreationDate="2020-10-22T22:08:37.680" UserId="11058" Text="In this video https://youtu.be/0ckE-CZpXAo?t=445, it's suggested to render onto a sphere instead of screen quad to save computation time on lighting calculations. So you create a bounding sphere for each light and render onto it.&#xD;&#xA;&#xD;&#xA;But I can't make sense of it. How can we render the scene around the light by rendering it onto a sphere?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29971" PostHistoryTypeId="1" PostId="10334" RevisionGUID="e40ab02b-79b7-4cde-9448-91ab9381f7b0" CreationDate="2020-10-22T22:08:37.680" UserId="11058" Text="Rendering part of the scene inside bounding sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="29972" PostHistoryTypeId="3" PostId="10334" RevisionGUID="e40ab02b-79b7-4cde-9448-91ab9381f7b0" CreationDate="2020-10-22T22:08:37.680" UserId="11058" Text="|opengl|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29973" PostHistoryTypeId="2" PostId="10335" RevisionGUID="f5798f33-c9ef-4c38-b290-5e5eda9752ce" CreationDate="2020-10-23T00:31:46.323" UserId="2654" Text="&gt; How can we render the scene around the light by rendering it onto a sphere?&#xD;&#xA;&#xD;&#xA;Well, answer me this: how do you render a scene around a like by rendering a &quot;screen quad&quot;?&#xD;&#xA;&#xD;&#xA;We're ultimately talking about deferred rendering, and what is being done is rendering the lighting pass. During the lighting pass, you read data from the gbuffers that tell you that pixel's position, normal, and any other information used by the lighting equation. The texel location you read this data from those gbuffers is just the fragment's location.&#xD;&#xA;&#xD;&#xA;The point being made by the video is that the geometry you render to do a lighting pass *does not matter*. You are *only* using it to invoke the fragment shader over a region of the image. This is why rendering a full-screen quad works; you're executing the fragment shader over all of the pixels in the screen.&#xD;&#xA;&#xD;&#xA;While that works, it does mean you're executing more fragment shader invocations than are strictly necessary for any particular light. Points that correspond to distances outside of the light's useful effect still have to have an FS executed on them.&#xD;&#xA;&#xD;&#xA;A sphere is a useful way to pre-cull such fragments. The sphere's radius represents the useful range of effect for a light. Any fragments horizontally or vertically outside of this range don't get produced, since fragments are only produced by rasterizing the sphere. And because the sphere's vertices will be transformed by the same transformation matrix as the scene, and because you will turn on depth tests, you *also* can cull out cases that are outside of the light's useful range in depth (or at least, if they're closer to the camera than the light's effect).&#xD;&#xA;&#xD;&#xA;But there are downsides of this approach. Spheres are complex objects, so there will typically be some overlap in terms of the number of helper fragment shader invocations being executed for a particular pixel. Of greater concern is using relatively high resolution spheres that appear very small on the screen.&#xD;&#xA;&#xD;&#xA;Also, you can only execute a single light per FS invocation, instead of being able to bundle lots of lights together. This is especially important for deferred rendering on tile-based renderers." ContentLicense="CC BY-SA 4.0" />
  <row Id="29974" PostHistoryTypeId="5" PostId="10325" RevisionGUID="833331c2-0c0b-47d8-8c87-1305e93aa294" CreationDate="2020-10-23T07:40:48.993" UserId="7647" Comment="Added implementation ideas." Text="Check out the section on [Circular Arcs and Circles](https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS/RB-circles.html), from [Ching-Kuang Shene's excellent computational geometry course notes](https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/notes.html):&#xD;&#xA;&#xD;&#xA;&gt; [G]iven three control points P0, P1 and P2 such that P0P1 = P1P2 holds, if we choose w, the weight for P1, to be sin(a), where a is the half angle at control point P1, the resulting rational Bézier curve is a circle.&#xD;&#xA;&#xD;&#xA;The second diagram on that page is particularly useful. If P0 is at (0,0), P1 is at (1,0), and P2 is at (1,1), then the angle at P1 is 90 degrees; half that is 45, so assigning weights w0 = w2 = 1 and w1 = sin(45) = 1/sqrt(2) will produce a circle.&#xD;&#xA;&#xD;&#xA;**EDIT**: To actually implement this from your code: The three points are `[a,b,c]`. If you know that the distance from `a` to `b` is the same as the distance from `b` to `c`, then you can set `w1` and `w3` to 1, and `w2` to the sine of half the angle between them. Look up the [half-angle formula](https://mathworld.wolfram.com/Half-AngleFormulas.html) for sine to see that `sin(x/2) = sqrt((1 - cos x) / 2)`. The cosine of the angle between two vectors is the normalized dot product, i.e. `cos x = dot(a-b,c-b) / (a-b)^2`. Thus, you can do something like&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;ba = a - b&#xD;&#xA;bc = c - b&#xD;&#xA;cosx = ba.Dot(bc) / ba.Dot(ba);&#xD;&#xA;w2 = math.sqrt(0.5 * (1 - cosx));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Again, this will only work if the distances `ba` and `bc` are the same. (You can still make a circle otherwise, but the weights will be more compilcated.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="29975" PostHistoryTypeId="2" PostId="10336" RevisionGUID="ef6b46de-b242-4807-a0b3-579261343750" CreationDate="2020-10-23T12:53:13.380" UserId="137" Text="A VBO is a buffer of memory which the gpu can access. That's all it is.&#xD;&#xA;&#xD;&#xA;A VAO is an object that stores vertex bindings. This means that when you call glVertexAttribPointer and friends to describe your vertex format that format information gets stored into the currently bound VAO. And when you draw it will use the vertex bindings in the currently bound VAO.&#xD;&#xA;&#xD;&#xA;Pretending it replays the binding calls is misleading. It is a relic from why the VAO were created because prior to VAOs you did need to redo the vertex bindings every time you changed which mesh you were drawing. A VAO lets you do that in a single call." ContentLicense="CC BY-SA 4.0" />
  <row Id="29976" PostHistoryTypeId="2" PostId="10337" RevisionGUID="34e22a6b-df26-441b-b5c7-43142b72a0f2" CreationDate="2020-10-23T18:04:40.813" UserId="15121" Text="I am developing a software that needs to interact with a mesh processing program, using tetrahedral meshes, however I am finding difficulties in this.&#xD;&#xA;&#xD;&#xA;The program requires all tetrahedrons to have **right handed orientation**, and this is not the hard part, as given a list of vertices $\{ v_0, v_1, v_2, v_3 \}$, I need to check that&#xD;&#xA;&#xD;&#xA;$h := ( \; (v_0 - v_1) \times (v_0 - v_2) \;) \cdot (v_0  - v_3) &gt; 0$&#xD;&#xA;&#xD;&#xA;In case $h &lt; 0$, any odd permutation will be correct, as $\{ v_0, v_1, v_3, v_2 \}$.&#xD;&#xA;&#xD;&#xA;The problem is that, as they told me, the program requires that **all faces are oriented with the right hand rule**. &#xD;&#xA;&#xD;&#xA;This requirement puzzles me, and I do not understand it completely.&#xD;&#xA;&#xD;&#xA;Can anyone point me in the right direction?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29977" PostHistoryTypeId="1" PostId="10337" RevisionGUID="34e22a6b-df26-441b-b5c7-43142b72a0f2" CreationDate="2020-10-23T18:04:40.813" UserId="15121" Text="Tetrahedron orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="29978" PostHistoryTypeId="3" PostId="10337" RevisionGUID="34e22a6b-df26-441b-b5c7-43142b72a0f2" CreationDate="2020-10-23T18:04:40.813" UserId="15121" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29979" PostHistoryTypeId="2" PostId="10338" RevisionGUID="4806b20b-1ec2-47c4-9f38-ce3eb05adafd" CreationDate="2020-10-23T19:45:58.633" UserId="48" Text="This refers to the order of vertices within a face. Typically in 3D graphics, faces are wound counterclockwise, so that if you're looking from outside of the tetrahedron/mesh, all the front faces will have their vertices in counterclockwise order. (See [here](https://www.khronos.org/opengl/wiki/Face_Culling#Winding_order) and [here](https://www.gamasutra.com/view/news/126352/Opinion_Backface_Culling_101.php) for more explanation.) This is a &quot;right-hand rule&quot; in that if the fingers of your right hand curl in the winding direction of the vertices, then your thumb points toward the outside of the mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="29980" PostHistoryTypeId="2" PostId="10339" RevisionGUID="bd0ec4a7-6b88-49ae-8ca1-f36fcefdba38" CreationDate="2020-10-23T20:33:05.220" UserId="13154" Text="Some search terms that might benefit you: &quot;image decomposition&quot; and &quot;image segmentation.&quot;&#xD;&#xA;&#xD;&#xA;For a good overview of some techniques, see [Decomposition of binary images — A survey and comparison](http://library.utia.cas.cz/separaty/2012/ZOI/suk-0381722.pdf), by Suk et. al.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29982" PostHistoryTypeId="50" PostId="9199" RevisionGUID="62f84aec-5341-4f68-9cfc-9d60ad93241f" CreationDate="2020-10-25T01:07:25.793" UserId="-1" />
  <row Id="29983" PostHistoryTypeId="50" PostId="9189" RevisionGUID="dbc6f0c5-8f4a-4372-ae99-cdb4ff4b5c45" CreationDate="2020-10-25T05:02:45.283" UserId="-1" />
  <row Id="29984" PostHistoryTypeId="5" PostId="10337" RevisionGUID="2115f12f-76d5-491c-bf87-91c868f6db63" CreationDate="2020-10-25T07:44:01.093" UserId="15121" Comment="added 922 characters in body" Text="I am developing a software that needs to interact with a mesh processing program, using tetrahedral meshes, however I am finding difficulties in this.&#xD;&#xA;&#xD;&#xA;The program requires all tetrahedrons to have **right handed orientation**, and this is not the hard part, as given a list of vertices $\{ v_0, v_1, v_2, v_3 \}$, I need to check that&#xD;&#xA;&#xD;&#xA;$h := ( \; (v_0 - v_1) \times (v_0 - v_2) \;) \cdot (v_0  - v_3) &gt; 0$&#xD;&#xA;&#xD;&#xA;In case $h &lt; 0$, any odd permutation will be correct, as $\{ v_0, v_1, v_3, v_2 \}$.&#xD;&#xA;&#xD;&#xA;The problem is that, as they told me, the program requires that **all faces are oriented with the right hand rule**. &#xD;&#xA;&#xD;&#xA;This requirement puzzles me, and I do not understand it completely.&#xD;&#xA;&#xD;&#xA;Can anyone point me in the right direction?&#xD;&#xA;&#xD;&#xA;### Code&#xD;&#xA;&#xD;&#xA;    class tetrahedron:&#xD;&#xA;        def __init__(self, vertices):&#xD;&#xA;            # compute handedness&#xD;&#xA;            c = numpy.cross(vertices[0].coords-vertices[1].coords, vertices[0].coords-vertices[2].coords)&#xD;&#xA;            h = numpy.inner( c, vertices[0].coords-vertices[3].coords )&#xD;&#xA;    &#xD;&#xA;            # vertex indices with correct right-handed orientation&#xD;&#xA;            if h &gt; 0:&#xD;&#xA;                self.vertices = vertices&#xD;&#xA;            else:&#xD;&#xA;                s = &quot;old h = %f&quot; % (h)&#xD;&#xA;                # swap last two vertices&#xD;&#xA;                self.vertices = [vertices[0], vertices[1], vertices[3], vertices[2]]&#xD;&#xA;                vertices = self.vertices&#xD;&#xA;                c = numpy.cross(vertices[0].coords-vertices[1].coords, vertices[0].coords-vertices[2].coords)&#xD;&#xA;                h = numpy.inner( c, vertices[0].coords-vertices[3].coords )&#xD;&#xA;                s = s + &quot; new h = %f&quot; % (h)&#xD;&#xA;                print(s)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29985" PostHistoryTypeId="2" PostId="10340" RevisionGUID="52ba5a75-39c7-40db-b1b5-00c125979c80" CreationDate="2020-10-25T15:47:29.217" UserId="7462" Text="I am using tinyGLTF to parse gltf files and then render them in my program.&#xD;&#xA;&#xD;&#xA;I am currently during the third example in [this page][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In particular I am trying to extract the 2 animation buffers:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;MeshMap LoadGltf(const std::string&amp; path)&#xD;&#xA;{&#xD;&#xA;    Model model;&#xD;&#xA;    TinyGLTF loader;&#xD;&#xA;    std::string err;&#xD;&#xA;    std::string warn;&#xD;&#xA;&#xD;&#xA;    bool ret = loader.LoadASCIIFromFile(&amp;model, &amp;err, &amp;warn, path);&#xD;&#xA;&#xD;&#xA;    if(!warn.empty()) { cout &lt;&lt; warn &lt;&lt; endl; }&#xD;&#xA;&#xD;&#xA;    if(!err.empty()) { cout &lt;&lt; err &lt;&lt; endl; }&#xD;&#xA;&#xD;&#xA;    if(!ret) { cout &lt;&lt; &quot;Failed to parse glTF&quot; &lt;&lt; endl; }&#xD;&#xA;&#xD;&#xA;    MeshMap mesh_map;&#xD;&#xA;    for(auto&amp; mesh: model.meshes)&#xD;&#xA;    {&#xD;&#xA;        if(mesh.name.empty())&#xD;&#xA;            mesh.name = &quot;unnamed mesh &quot; + to_string(global_mesh_index++);&#xD;&#xA;        // TODO(low): implement this functionality as needed&#xD;&#xA;        assert(mesh.primitives.size() == 1);&#xD;&#xA;        GetPrimitiveData(model, mesh, mesh_map);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if(model.animations.size())&#xD;&#xA;    {&#xD;&#xA;        cout &lt;&lt; &quot;model.animations.size() &quot; &lt;&lt; model.animations.size() &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; &quot;model.animations[0].channels.size() &quot; &lt;&lt; model.animations[0].channels.size() &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; &quot;model.animations[0].channels[0].sampler &quot; &lt;&lt; model.animations[0].channels[0].sampler &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; &quot;model.animations[0].samplers[0].input &quot; &lt;&lt; model.animations[0].samplers[0].input &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; &quot;model.animations[0].samplers[0].output &quot; &lt;&lt; model.animations[0].samplers[0].output &lt;&lt; endl;&#xD;&#xA;&#xD;&#xA;        const int input = model.animations[0].samplers[0].input;&#xD;&#xA;        const int output = model.animations[0].samplers[0].output;&#xD;&#xA;&#xD;&#xA;        vector&lt;float&gt; time = ExtractDataFromAccessor&lt;float&gt;(model, input);&#xD;&#xA;        for(auto f : time) cout &lt;&lt; f &lt;&lt; &quot; &quot;;&#xD;&#xA;        cout &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; time.size() &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; model.accessors[input].name &lt;&lt; endl;&#xD;&#xA;        vector&lt;float&gt; rot = ExtractDataFromAccessor&lt;float&gt;(model, output);&#xD;&#xA;        for(auto f : rot) cout &lt;&lt; f &lt;&lt; &quot; &quot;;&#xD;&#xA;        cout &lt;&lt; endl;&#xD;&#xA;&#xD;&#xA;        cout &lt;&lt; model.animations[0].channels[0].target_node &lt;&lt; endl;&#xD;&#xA;        cout &lt;&lt; model.animations[0].channels[0].target_path &lt;&lt; endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    return mesh_map;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;template&lt;typename T&gt;&#xD;&#xA;std::vector&lt;T&gt; ExtractDataFromAccessor(&#xD;&#xA;    Model&amp; model,&#xD;&#xA;    const int accessor_index)&#xD;&#xA;{&#xD;&#xA;    const int buffer_view_index = model.accessors[accessor_index].bufferView;&#xD;&#xA;    const int buffer_index = model.bufferViews[buffer_view_index].buffer;&#xD;&#xA;    const int buffer_length = model.bufferViews[buffer_view_index].byteLength;&#xD;&#xA;    const int buffer_offset = model.bufferViews[buffer_view_index].byteOffset;&#xD;&#xA;    const int buffer_stride = model.bufferViews[buffer_view_index].byteStride;&#xD;&#xA;    const vector&lt;unsigned char&gt; data = model.buffers[buffer_index].data;&#xD;&#xA;&#xD;&#xA;    //TODO(low): extend functionality to handle this as needed.&#xD;&#xA;    assert(buffer_stride == 0);&#xD;&#xA;&#xD;&#xA;    std::vector&lt;T&gt; holder(buffer_length / sizeof(T));&#xD;&#xA;    memcpy(&#xD;&#xA;        holder.data(),&#xD;&#xA;        data.data() + buffer_offset,&#xD;&#xA;        buffer_length);&#xD;&#xA;&#xD;&#xA;    return holder;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Output&#xD;&#xA;```&#xD;&#xA;model.animations.size() 1&#xD;&#xA;model.animations[0].channels.size() 1&#xD;&#xA;model.animations[0].channels[0].sampler 0&#xD;&#xA;model.animations[0].samplers[0].input 2&#xD;&#xA;model.animations[0].samplers[0].output 3&#xD;&#xA;0 0.25 0.5 0.75 1 0 0 0 1 0 0 0.707 0.707 0 0 1 0 0 0 0.707 -0.707 0 0 0 1 &#xD;&#xA;25&#xD;&#xA;&#xD;&#xA;0 0.25 0.5 0.75 1 0 0 0 1 0 0 0.707 0.707 0 0 1 0 0 0 0.707 -0.707 0 0 0 1 &#xD;&#xA;0&#xD;&#xA;rotation&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I am very confused in that `in` and `out` seem to be equal, and that they are the concatenation of the 2 animation buffers, rather than what I expected. Which was `in` to be the time buffer and `out` to be the rotation buffer.&#xD;&#xA;&#xD;&#xA;Where is the data that lets you separate them?&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0&#xD;&#xA;  [2]: https://i.stack.imgur.com/YIfYs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="29986" PostHistoryTypeId="1" PostId="10340" RevisionGUID="52ba5a75-39c7-40db-b1b5-00c125979c80" CreationDate="2020-10-25T15:47:29.217" UserId="7462" Text="Why are these 2 buffers joint while extracting glTF information?" ContentLicense="CC BY-SA 4.0" />
  <row Id="29987" PostHistoryTypeId="3" PostId="10340" RevisionGUID="52ba5a75-39c7-40db-b1b5-00c125979c80" CreationDate="2020-10-25T15:47:29.217" UserId="7462" Text="|c++|animation|model|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29988" PostHistoryTypeId="2" PostId="10341" RevisionGUID="5cdde6fd-be9e-4ebf-9e1d-55b90429077d" CreationDate="2020-10-25T16:25:27.953" UserId="15131" Text="If I have an *output* device, for which I have a known spectrum data for each of it's primaries, I should be able to calculate the CIEXYZ of its primaries using using the integral equations together with the CIE color matching functions. I can then calculate its respective CIExyY values, which for output device are always inside the boundary if the xyY spectral locus - the chromaticity diagram.&#xD;&#xA;&#xD;&#xA;My question relates to calculating xyY of primaries of *input* device.&#xD;&#xA;&#xD;&#xA;Suppose I have a known spectrum data for the primaries of some input device - be it a digital scanner or a digital camera or any other input device. It's color filters are not perfect, this means that even a pure spectrum color is represented as non-zero values in its own RGB color space. That means that (if I'm correct) that the whole chromaticity diagram should lie inside of the device RGB color space, and it's primaries lie outside of the diagram and be represented by imaginary colors.&#xD;&#xA;&#xD;&#xA;**How do I calculate those imaginary primaries for the input device given known spectrum for its primaries?** If I'm not mistaken, I cannot simply use the integral formula, because that seems to be only for output devices and the resulting primaries would lie in the locus." ContentLicense="CC BY-SA 4.0" />
  <row Id="29989" PostHistoryTypeId="1" PostId="10341" RevisionGUID="5cdde6fd-be9e-4ebf-9e1d-55b90429077d" CreationDate="2020-10-25T16:25:27.953" UserId="15131" Text="Determining input color space primaries from spectrum data" ContentLicense="CC BY-SA 4.0" />
  <row Id="29990" PostHistoryTypeId="3" PostId="10341" RevisionGUID="5cdde6fd-be9e-4ebf-9e1d-55b90429077d" CreationDate="2020-10-25T16:25:27.953" UserId="15131" Text="|color|color-science|color-management|spectral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="29997" PostHistoryTypeId="2" PostId="10343" RevisionGUID="bfb2ed5a-7786-4269-9e75-e862c0ca89e1" CreationDate="2020-10-25T18:54:35.897" UserId="1908" Text="The accessor (`model.accessors[accessor_index]`) has its own `byteOffset` and `count` values that you need to account for here.&#xD;&#xA;&#xD;&#xA;The input and output accessors are allowed to share a bufferView, and your output is showing a dump of the same entire bufferView twice.  The first five values in that dump are the input accessor with the times (in seconds, since the start of the animation) and the remainder of the bufferView is pointed at by the output accessor.  If you account for the additional settings on the accessor itself, it should allow you to pick apart this bufferView correctly.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="29998" PostHistoryTypeId="50" PostId="10025" RevisionGUID="c1c7e97b-ec6e-45aa-9f2d-fc703bba6aa6" CreationDate="2020-10-25T23:00:55.120" UserId="-1" />
  <row Id="29999" PostHistoryTypeId="52" PostId="10340" RevisionGUID="74fba4d7-aaa9-427a-9b18-465045bd37f4" CreationDate="2020-10-25T23:47:52.600" />
  <row Id="30004" PostHistoryTypeId="50" PostId="9267" RevisionGUID="5b7b6dbc-57ca-4c87-be9f-20dce8f208b8" CreationDate="2020-10-26T08:07:00.737" UserId="-1" />
  <row Id="30005" PostHistoryTypeId="5" PostId="10337" RevisionGUID="78ff8021-99a0-4e22-a59d-ce4c422492cd" CreationDate="2020-10-26T09:49:15.600" UserId="15121" Comment="Updated code" Text="I am developing a software that needs to interact with a mesh processing program, using tetrahedral meshes, however I am finding difficulties in this.&#xD;&#xA;&#xD;&#xA;The program requires all tetrahedrons to have **right handed orientation**, and this is not the hard part, as given a list of vertices $\{ v_0, v_1, v_2, v_3 \}$, I need to check that&#xD;&#xA;&#xD;&#xA;$h := ( \; (v_0 - v_1) \times (v_0 - v_2) \;) \cdot (v_0  - v_3) &gt; 0$&#xD;&#xA;&#xD;&#xA;In case $h &lt; 0$, any odd permutation will be correct, as $\{ v_0, v_1, v_3, v_2 \}$.&#xD;&#xA;&#xD;&#xA;The problem is that, as they told me, the program requires that **all faces are oriented with the right hand rule**. &#xD;&#xA;&#xD;&#xA;This requirement puzzles me, and I do not understand it completely.&#xD;&#xA;&#xD;&#xA;Can anyone point me in the right direction?&#xD;&#xA;&#xD;&#xA;### Code&#xD;&#xA;&#xD;&#xA;    class tetrahedron:&#xD;&#xA;        def __init__(self, vertices):&#xD;&#xA;            # compute handedness&#xD;&#xA;            c = numpy.cross(vertices[0].coords-vertices[1].coords, vertices[0].coords-vertices[2].coords)&#xD;&#xA;            h = numpy.inner( c, vertices[0].coords-vertices[3].coords )&#xD;&#xA;    &#xD;&#xA;            # vertex indices with correct right-handed orientation&#xD;&#xA;            if h &gt; 0:&#xD;&#xA;                self.vertices = vertices&#xD;&#xA;            else:&#xD;&#xA;                s = &quot;old h = %f&quot; % (h)&#xD;&#xA;                # swap last two vertices&#xD;&#xA;                self.vertices = [vertices[0], vertices[1], vertices[3], vertices[2]]&#xD;&#xA;                vertices = self.vertices&#xD;&#xA;                c = numpy.cross(vertices[0].coords-vertices[1].coords, vertices[0].coords-vertices[2].coords)&#xD;&#xA;                h = numpy.inner( c, vertices[0].coords-vertices[3].coords )&#xD;&#xA;                s = s + &quot; new h = %f&quot; % (h)&#xD;&#xA;                print(s)&#xD;&#xA;&#xD;&#xA;### Updated Code&#xD;&#xA;&#xD;&#xA;I have updated my code according to the suggestions, but apparently faces are still a problem, the error it gives is&#xD;&#xA;&#xD;&#xA;    Two elements connect to the same side of the shared element face. Coordinates: 12.3669, -61.573, 81.0725&#xD;&#xA;&#xD;&#xA;My code is now as follows:&#xD;&#xA;&#xD;&#xA;    import numpy&#xD;&#xA;    &#xD;&#xA;    def handedness(vertices):&#xD;&#xA;        c = numpy.cross(vertices[1].coords-vertices[0].coords, \&#xD;&#xA;                        vertices[2].coords-vertices[0].coords)&#xD;&#xA;        h = numpy.inner( c, vertices[3].coords-vertices[0].coords )&#xD;&#xA;        return h&#xD;&#xA;    &#xD;&#xA;    class tetrahedron:&#xD;&#xA;        def __init__(self, vertices):&#xD;&#xA;            h = handedness(vertices)&#xD;&#xA;&#xD;&#xA;            if h &gt; 0:&#xD;&#xA;                self.vertices = vertices&#xD;&#xA;            else:&#xD;&#xA;                s = &quot;old h = %f&quot; % (h)&#xD;&#xA;                # swap last two vertices&#xD;&#xA;                self.vertices = [vertices[0], vertices[1], vertices[3], vertices[2]]&#xD;&#xA;                vertices = self.vertices&#xD;&#xA;                h = handedness(self.vertices)&#xD;&#xA;                s = s + &quot; new h = %f&quot; % (h)&#xD;&#xA;                print(s)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30006" PostHistoryTypeId="2" PostId="10345" RevisionGUID="eebe9b31-a15c-4889-b70d-5bc67e2632d2" CreationDate="2020-10-26T13:52:29.043" UserId="15133" Text="The specific chapter about this is here - [Sampling Theory][1]&lt;br&gt;&#xD;&#xA;Unlike what I read anywhere else, it defines Shah as: $$Ш_T(x)=T\sum\nolimits_i{\delta{(x-Ti)}}$$&#xD;&#xA;Elsewhere it's always simply: $$s_T{(x)}=\sum\nolimits_i{\delta{(x-Ti)}}$$&#xD;&#xA;And the T is still present in the reconstructed function: $$f\tilde(x)=T\sum\limits_{i=-\infty}^\infty{f(iT)r(x-iT)}$$&#xD;&#xA;where r(x) is a reconstruction filter.&lt;br&gt;&#xD;&#xA;Can someone work out the maths for me to understand?&#xD;&#xA;&#xD;&#xA;I haven't been doing maths for years, and even back in my school days, I don't think I was a good student, so please be gentle.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Sampling_Theory.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30007" PostHistoryTypeId="1" PostId="10345" RevisionGUID="eebe9b31-a15c-4889-b70d-5bc67e2632d2" CreationDate="2020-10-26T13:52:29.043" UserId="15133" Text="Why is there a T factor in the definition of Shah given in Matt Pharr's Physically Based Rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30008" PostHistoryTypeId="3" PostId="10345" RevisionGUID="eebe9b31-a15c-4889-b70d-5bc67e2632d2" CreationDate="2020-10-26T13:52:29.043" UserId="15133" Text="|pbrt|pbrt-v3|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30009" PostHistoryTypeId="5" PostId="10345" RevisionGUID="995fce9a-903e-4ec9-b314-a1fa983e8b10" CreationDate="2020-10-26T13:59:44.897" UserId="15133" Comment="added 17 characters in body" Text="The specific chapter about this is here - [Sampling Theory][1]&lt;br&gt;&#xD;&#xA;Unlike what I read anywhere else, it defines Shah as: $$Ш_T(x)=T\sum\nolimits_i{\delta{(x-Ti)}}$$&#xD;&#xA;And the T is still present in the reconstructed function: $$f\tilde(x)=T\sum\limits_{i=-\infty}^\infty{f(iT)r(x-iT)}$$&#xD;&#xA;where r(x) is a reconstruction filter.&lt;br&gt;&#xD;&#xA;Everywhere else I can find gives: $$s_T{(x)}=\sum\nolimits_i{\delta{(x-Ti)}}$$&#xD;&#xA;Can someone work out the maths for me? Why is the difference?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I haven't been doing maths for years, and even back in my school days, I don't think I was a good student, so please be gentle.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Sampling_Theory.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30010" PostHistoryTypeId="2" PostId="10346" RevisionGUID="4c029c24-f35c-4f53-87d7-a85cf5bc8a4c" CreationDate="2020-10-26T15:33:01.940" UserId="228" Text="The question is simple, I have this diagram from the Khronos page:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this diagram from the [Learn OpenGL page][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In the first picture the **Primitive assembly** is executed for example **after** the Geometry shader, in the second the execution happens **before**.&#xD;&#xA;&#xD;&#xA;I'm a bit confused cause I can't figure what that module and the Geometry shader takes as input, I'd be more prone to say the first diagram is correct. But maybe there's an interpretation I'm missing here.&#xD;&#xA;&#xD;&#xA;When is the Primitive assembly executed then?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ru6dz.png&#xD;&#xA;  [2]: https://learnopengl.com/book/book_pdf.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/3mDKB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30011" PostHistoryTypeId="1" PostId="10346" RevisionGUID="4c029c24-f35c-4f53-87d7-a85cf5bc8a4c" CreationDate="2020-10-26T15:33:01.940" UserId="228" Text="OpenGL pipeline stages, when is the primitive assembly executed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30012" PostHistoryTypeId="3" PostId="10346" RevisionGUID="4c029c24-f35c-4f53-87d7-a85cf5bc8a4c" CreationDate="2020-10-26T15:33:01.940" UserId="228" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30013" PostHistoryTypeId="5" PostId="10346" RevisionGUID="9f70b96e-93c6-462f-837c-0fca1a006b9b" CreationDate="2020-10-26T16:44:34.363" UserId="228" Comment="added 647 characters in body" Text="The question is simple, I have this diagram from the Khronos page:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And this diagram from the [Learn OpenGL page][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In the first picture the **Primitive assembly** is executed for example **after** the Geometry shader, in the second the execution happens **before**.&#xD;&#xA;&#xD;&#xA;For the latter picture I took the relevant bit from the tutorial:&#xD;&#xA;&#xD;&#xA;&gt; The primitive assembly stage takes as input all the vertices (or vertex if GL_POINTS is chosen) from the vertex shader that form a primitive and assembles all the point(s) in the primitive shape given; in this case a triangle.&#xD;&#xA;The output of the primitive assembly stage is passed to the geometry shader. The geometry shader takes as input a collection of vertices that form a primitive and has the ability to generate other shapes by emitting new vertices to form new (or other) primitive(s). In this example case, it generates a second triangle out of the given shape.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I'm a bit confused cause I can't figure what that module and the Geometry shader takes as input, I'd be more prone to say the first diagram is correct. But maybe there's an interpretation I'm missing here.&#xD;&#xA;&#xD;&#xA;When is the Primitive assembly executed then?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ru6dz.png&#xD;&#xA;  [2]: https://learnopengl.com/book/book_pdf.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/3mDKB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30014" PostHistoryTypeId="2" PostId="10347" RevisionGUID="5e4bc709-3416-423e-8ad4-367ef8958a2a" CreationDate="2020-10-26T17:03:23.780" UserId="2654" Text="For a diagram to be comprehensive, it'd have to show way too much detail. It's just a simple tool.&#xD;&#xA;&#xD;&#xA;[Primitive assembly][1] is the process of taking a sequence of vertices for a particular [rendering primitive][2] type, and generating a sequence of base primitives (points, lines, triangles) from them.&#xD;&#xA;&#xD;&#xA;This process does indeed happen after vertex post-processing, as the input to the rasterizer is a sequence of base primitives. After all, you don't rasterize a triangle strip; you rasterize a triangle.&#xD;&#xA;&#xD;&#xA;*However*, the input to a [geometry shader][3] invocation is a single base primitive, taken from the sequence of vertices provided up to that point. As such, a form of primitive assembly *also* must happen before the GS, to convert the vertex sequence into a sequence of base primitives.&#xD;&#xA;&#xD;&#xA;This is also one reason why GS's are *slow*. If there is no GS, then this primitive assembly doesn't happen.&#xD;&#xA;&#xD;&#xA;The output of the geometry shader is a bunch of vertex sequences, which still later undergo primitive assembly based on the output primitive type of the GS. A GS can output triangle strips, so there has to be primitive assembly to turn those strips into individual triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Primitive_Assembly&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Primitive&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Geometry_Shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="30015" PostHistoryTypeId="50" PostId="9875" RevisionGUID="de439522-eb82-4424-88f5-22f99cef73b3" CreationDate="2020-10-27T03:07:55.737" UserId="-1" />
  <row Id="30016" PostHistoryTypeId="2" PostId="10348" RevisionGUID="56f0ff2d-dc8e-457a-8628-47d8f45a5042" CreationDate="2020-10-27T07:56:59.950" UserId="9044" Text="Suppose that I have some world-space volume (which we may assume is a convex polyhedron with a small number of vertices), and I want to render its intersection with the view frustum, such that every relevant pixel gets rendered exactly once. *My use-case is rendering light influence volumes for a deferred renderer, but I guess there may be other uses for this*.&#xD;&#xA;&#xD;&#xA;Everything is fine as long as the volume is completely behind the near clipping plane: rendering with back-face culling does the job, thanks to convexity of the volume. If, on the other hand, the volume intersects the near z-plane a bit, the intersection area gets clipped, but there are still parts of the volume behind this area that didn't get rendered. We could switch to front-face culling, but that breaks if the volume intersects the far z-plane. The volume could theoretically intersect both z-planes, so this problem cannot be solved simply by adjusting the culling mode. The volume could as well completely embody the view frustum, in which case nothing will be draw at all (all triangles outside the frustum), while in reality I'd like it to be rendered as if I'm rendering a fullscreen quad (since the intersection of the volume and the frustum equals the frustum).&#xD;&#xA;&#xD;&#xA;Right now my solution is to check if any of the volume's vertices are in front of the near z-plane and resort to a fullscreen quad in this case. It works fine, but I'm curious whether there is a better solution.&#xD;&#xA;&#xD;&#xA;One solution that I don't particularly like is actually computing the mesh of the intersection of volume and the view frustum (both are convex polyhedrons, which should simplify the job a bit). It has the following disadvantages:&#xD;&#xA;&#xD;&#xA;* I have to either find a good enough library for mesh intersection, which means adding another dependency for the engine, or write the intersection code myself&#xD;&#xA;* More importantly, even if the intersection is computed with maximal possible precision, it still goes through the vertex shader, gets multiplied by the view-projection matrix, with numerical errors inevitably introduced. Then, a vertex at z=near may appear at z=near+/-error, and it might still be erroneously clipped." ContentLicense="CC BY-SA 4.0" />
  <row Id="30017" PostHistoryTypeId="1" PostId="10348" RevisionGUID="56f0ff2d-dc8e-457a-8628-47d8f45a5042" CreationDate="2020-10-27T07:56:59.950" UserId="9044" Text="Rendering a volume that might be completely clipped in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="30018" PostHistoryTypeId="3" PostId="10348" RevisionGUID="56f0ff2d-dc8e-457a-8628-47d8f45a5042" CreationDate="2020-10-27T07:56:59.950" UserId="9044" Text="|opengl|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30019" PostHistoryTypeId="5" PostId="10348" RevisionGUID="61164ee1-9b95-410b-aa94-a2c4d5562289" CreationDate="2020-10-27T19:03:50.330" UserId="9044" Comment="added 80 characters in body" Text="Suppose that I have some world-space volume (which we may assume is a convex polyhedron with a small number of vertices), and I want to render its intersection with the view frustum, such that every relevant pixel gets rendered exactly once. *My use-case is rendering light influence volumes for a deferred renderer, but I guess there may be other uses for this*.&#xD;&#xA;&#xD;&#xA;Everything is fine as long as the volume is completely behind the near clipping plane (i.e. isn't clipped by the near z-plane): rendering with back-face culling does the job, thanks to convexity of the volume. If, on the other hand, the volume intersects the near z-plane a bit, the intersection area gets clipped, but there are still parts of the volume behind this area that didn't get rendered. We could switch to front-face culling, but that breaks if the volume intersects the far z-plane. The volume could theoretically intersect both z-planes, so this problem cannot be solved simply by adjusting the culling mode. The volume could as well completely embody the view frustum, in which case nothing will be draw at all (all triangles outside the frustum), while in reality I'd like it to be rendered as if I'm rendering a fullscreen quad (since the intersection of the volume and the frustum equals the frustum).&#xD;&#xA;&#xD;&#xA;Right now my solution is to check if any of the volume's vertices are in front of the near z-plane (i.e. are clipped by the near z-plane) and resort to a fullscreen quad in this case. It works fine, but I'm curious whether there is a better solution.&#xD;&#xA;&#xD;&#xA;One solution that I don't particularly like is actually computing the mesh of the intersection of volume and the view frustum (both are convex polyhedrons, which should simplify the job a bit). It has the following disadvantages:&#xD;&#xA;&#xD;&#xA;* I have to either find a good enough library for mesh intersection, which means adding another dependency for the engine, or write the intersection code myself&#xD;&#xA;* More importantly, even if the intersection is computed with maximal possible precision, it still goes through the vertex shader, gets multiplied by the view-projection matrix, with numerical errors inevitably introduced. Then, a vertex at z=near may appear at z=near+/-error, and it might still be erroneously clipped." ContentLicense="CC BY-SA 4.0" />
  <row Id="30020" PostHistoryTypeId="50" PostId="10261" RevisionGUID="42acb2e6-b817-4370-a825-1c2f1ab1e79b" CreationDate="2020-10-27T21:02:10.273" UserId="-1" />
  <row Id="30021" PostHistoryTypeId="50" PostId="10263" RevisionGUID="d6bb1c0b-ff63-4343-96e5-dffcbeeb2715" CreationDate="2020-10-28T09:07:00.680" UserId="-1" />
  <row Id="30022" PostHistoryTypeId="50" PostId="10268" RevisionGUID="ca369db5-e1f7-4dd9-9c15-89b3b35e958e" CreationDate="2020-10-28T18:06:30.720" UserId="-1" />
  <row Id="30026" PostHistoryTypeId="2" PostId="10350" RevisionGUID="f9a90bf0-777b-4d6c-b754-cfce88064c69" CreationDate="2020-10-29T17:24:49.330" UserId="15147" Text="Using Unity I've been producing sculptural forms that look like this. It's made of patterns of cubes that twist around each other. I'm trying to get it into a 3D printable format.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;From unity I export a PLY that is a list of the co-ords of each cube that looks like:&#xD;&#xA;```&#xD;&#xA;ply&#xD;&#xA;format ascii 1.0&#xD;&#xA;element vertex 17500&#xD;&#xA;property float x&#xD;&#xA;property float y&#xD;&#xA;property float z&#xD;&#xA;end_header&#xD;&#xA;35 2.521441 0&#xD;&#xA;34.72401 -2.06799 4.386663&#xD;&#xA;33.90041 3.202552 8.704146&#xD;&#xA;...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then I've imported that into meshlab and run `Filters &gt; Remeshing, Simplification and Reconstruction &gt; Surface Reconstruction: Ball Pivoting` with the default parameters.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is the result (different iteration so doesn't match top image but similar) which is ok, but obviously not 3d printable.&#xD;&#xA;&#xD;&#xA;Is there a better way of doing this to either wrap around as if I were wrapping cling film (saran wrap) over the whole thing? Or to preserve the chains of cubes and print the skeleton?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xvZ8x.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Akdad.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30027" PostHistoryTypeId="1" PostId="10350" RevisionGUID="f9a90bf0-777b-4d6c-b754-cfce88064c69" CreationDate="2020-10-29T17:24:49.330" UserId="15147" Text="Wrapping a point cloud skeleton with a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="30028" PostHistoryTypeId="3" PostId="10350" RevisionGUID="f9a90bf0-777b-4d6c-b754-cfce88064c69" CreationDate="2020-10-29T17:24:49.330" UserId="15147" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30029" PostHistoryTypeId="2" PostId="10351" RevisionGUID="8e9b3e35-866a-4313-9ea2-296194753618" CreationDate="2020-10-30T02:59:20.243" UserId="15152" Text="I'm trying to reduce a thick line, in raster space, down to a thin line, preferably one pixel wide (or thick).&#xD;&#xA;&#xD;&#xA;Does anybody know of an algorithm that can do this?&#xD;&#xA;&#xD;&#xA;Imagine you draw with a marker on a piece of paper, scribbling here and there.  Then you scan this paper into a grey-scale or black-and-white raster image.  How can I produce another black-and-white image the same size but the lines you drew are very thin instead of thick?&#xD;&#xA;&#xD;&#xA;Surely this must be a solved problem, right?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30030" PostHistoryTypeId="1" PostId="10351" RevisionGUID="8e9b3e35-866a-4313-9ea2-296194753618" CreationDate="2020-10-30T02:59:20.243" UserId="15152" Text="Algorithm for thinning a thick line" ContentLicense="CC BY-SA 4.0" />
  <row Id="30031" PostHistoryTypeId="3" PostId="10351" RevisionGUID="8e9b3e35-866a-4313-9ea2-296194753618" CreationDate="2020-10-30T02:59:20.243" UserId="15152" Text="|2d-graphics|pixel-graphics|bitmap-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30032" PostHistoryTypeId="50" PostId="8888" RevisionGUID="38634489-8c4d-43fb-82a4-44dc7fb19efe" CreationDate="2020-10-30T15:06:15.743" UserId="-1" />
  <row Id="30033" PostHistoryTypeId="2" PostId="10352" RevisionGUID="847f3596-1664-44e8-80e3-11361968db15" CreationDate="2020-10-30T16:02:36.283" UserId="15155" Text="the canny algorithm is a great start.&#xD;&#xA;&#xD;&#xA;it takes a sobel input like so.&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HeYpF.jpg&#xD;&#xA;&#xD;&#xA;Computes its gradient. Then depending on the gradient orientation it compares all neighbouring pixels aligned with it. If its a local maximum the pixel remains black otherwise it is set to white.&#xD;&#xA;&#xD;&#xA;this article will probably explain it a lot better.&#xD;&#xA;https://towardsdatascience.com/canny-edge-detection-step-by-step-in-python-computer-vision-b49c3a2d8123&#xD;&#xA;&#xD;&#xA;Ive tried to implement my own version using the algorithm provided however I'm struggling to port it to glsl as I think the interpolation might be causing an issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="30034" PostHistoryTypeId="5" PostId="10352" RevisionGUID="1a9549b3-dccc-4403-bcfe-a72c2fef72aa" CreationDate="2020-10-30T16:25:59.520" UserId="15155" Comment="added 135 characters in body" Text="the canny algorithm is a great start.&#xD;&#xA;&#xD;&#xA;it takes a sobel input like so.&#xD;&#xA; [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HeYpF.jpg&#xD;&#xA;&#xD;&#xA;Computes its gradient. Then depending on the gradient orientation it compares all neighbouring pixels aligned with it. If its a local maximum the pixel remains black otherwise it is set to white.&#xD;&#xA;&#xD;&#xA;this article will probably explain it a lot better.&#xD;&#xA;https://towardsdatascience.com/canny-edge-detection-step-by-step-in-python-computer-vision-b49c3a2d8123&#xD;&#xA;&#xD;&#xA;Ive tried to implement my own version using the algorithm provided however I'm struggling to port it to glsl as I think the interpolation might be causing an issue.&#xD;&#xA;&#xD;&#xA;here is a working one in shatertoy though, just a beginner though so a bit complex for me.&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/wl2cW3" ContentLicense="CC BY-SA 4.0" />
  <row Id="30049" PostHistoryTypeId="2" PostId="10356" RevisionGUID="560fa0ec-948d-4926-9b94-1b7416a62092" CreationDate="2020-10-31T15:54:39.073" UserId="11058" Text="With the help of instanced arrays we can specify an array of transforms and render a number of objects with a single render call. I'm wondering if using instanced arrays make sense in situations where the transforms of the objects need to be updated on each frame? In that case we would need to reupload the buffer with transforms on every frame. Is this practical or should we use individual rendering or `gl_Instance_ID` (if the number of instances is not too high) instead?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30050" PostHistoryTypeId="1" PostId="10356" RevisionGUID="560fa0ec-948d-4926-9b94-1b7416a62092" CreationDate="2020-10-31T15:54:39.073" UserId="11058" Text="Using instanced arrays for dynamic objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="30051" PostHistoryTypeId="3" PostId="10356" RevisionGUID="560fa0ec-948d-4926-9b94-1b7416a62092" CreationDate="2020-10-31T15:54:39.073" UserId="11058" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30058" PostHistoryTypeId="2" PostId="10359" RevisionGUID="08e49135-af3e-4b23-bc13-749df808b977" CreationDate="2020-11-01T06:49:49.993" UserId="2654" Text="If you need to update data, then you need to update data *regardless* of the mechanism you use to render the object. If you have 3000 objects to be rendered, and each frame they will be rendered with a different matrix transform, then you will have to send 192,000 bytes of memory (64-bytes-per-matrix) every frame. Whether explicitly through a write to buffer object storage or implicitly through setting uniform values, 192,000 bytes of data are going to have to find their way from CPU-space to GPU-space.&#xD;&#xA;&#xD;&#xA;So long as you use reasonable [buffer object streaming techniques][1], performance due to sending data shouldn't be a problem relative to other ways to send the data. Especially for fairly small data like per-model transforms. Of course, good buffer streaming does require having two buffers, but that's a memory storage tradeoff, not a runtime performance cost.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming" ContentLicense="CC BY-SA 4.0" />
  <row Id="30064" PostHistoryTypeId="2" PostId="10360" RevisionGUID="2b04248f-16e2-44a5-a096-5cb5939fe248" CreationDate="2020-11-01T17:39:57.610" UserId="15159" Text="Let `image1` be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And `mask` be:&#xD;&#xA;&#xD;&#xA;(45, 78, 251, 102)&#xD;&#xA;&#xD;&#xA;Apply `mask` on top of `image1` to get `image2`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I need to do the reverse thing, given `image1` and `image2`, is there a formula or an algorithm (there has to be right?) to find the `mask`?&#xD;&#xA;&#xD;&#xA;Thanks in advance, first post in here I might lack vocabulary I'm sorry about that, my tags might be completely off.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yhc6R.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VIOvh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30065" PostHistoryTypeId="1" PostId="10360" RevisionGUID="2b04248f-16e2-44a5-a096-5cb5939fe248" CreationDate="2020-11-01T17:39:57.610" UserId="15159" Text="How to retrieve RGBA mask used to transform image1 into image2" ContentLicense="CC BY-SA 4.0" />
  <row Id="30066" PostHistoryTypeId="3" PostId="10360" RevisionGUID="2b04248f-16e2-44a5-a096-5cb5939fe248" CreationDate="2020-11-01T17:39:57.610" UserId="15159" Text="|filtering|masking|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30067" PostHistoryTypeId="5" PostId="10360" RevisionGUID="d478f74c-a852-432c-b492-5ba735babb9b" CreationDate="2020-11-01T17:45:52.587" UserId="15159" Comment="added 5 characters in body" Text="Let `image1` be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And RGBA `mask` be:&#xD;&#xA;&#xD;&#xA;(45, 78, 251, 102)&#xD;&#xA;&#xD;&#xA;Apply `mask` on top of `image1` to get `image2`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I need to do the reverse thing, given `image1` and `image2`, is there a formula or an algorithm (there has to be right?) to find the `mask`?&#xD;&#xA;&#xD;&#xA;Thanks in advance, first post in here I might lack vocabulary I'm sorry about that, my tags might be completely off.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yhc6R.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VIOvh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30068" PostHistoryTypeId="2" PostId="10361" RevisionGUID="50bae79d-5525-4374-bfe5-c58f2879ec55" CreationDate="2020-11-02T04:08:55.497" UserId="38" Text="2D application users seem to be using transparency as a proxy for coverage more often than not. However they are not the same, although nearly everybody makes the assumption that they are.&#xD;&#xA;&#xD;&#xA;Given that we do more coverage based assumptions than actual alpha based assumptions. Wouldnt it make more sense to formulate coverage somehow instead? Is it even possible to somehow do coverage based compositing?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30069" PostHistoryTypeId="1" PostId="10361" RevisionGUID="50bae79d-5525-4374-bfe5-c58f2879ec55" CreationDate="2020-11-02T04:08:55.497" UserId="38" Text="coverage vs transparency" ContentLicense="CC BY-SA 4.0" />
  <row Id="30070" PostHistoryTypeId="3" PostId="10361" RevisionGUID="50bae79d-5525-4374-bfe5-c58f2879ec55" CreationDate="2020-11-02T04:08:55.497" UserId="38" Text="|transparency|theory|compositing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30071" PostHistoryTypeId="5" PostId="10360" RevisionGUID="2fd9019c-bfe3-4413-bf9f-5268da68125b" CreationDate="2020-11-02T07:09:29.840" UserId="15159" Comment="added 119 characters in body" Text="Let `image1` be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And RGBA `mask` be:&#xD;&#xA;&#xD;&#xA;(45, 78, 251, 102)&#xD;&#xA;&#xD;&#xA;Apply `mask` on top of `image1` to get `image2`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I need to do the reverse thing, given `image1` and `image2`, is there a formula or an algorithm (there has to be right?) to find the `mask`?&#xD;&#xA;&#xD;&#xA;Thanks in advance, first post in here I might lack vocabulary I'm sorry about that, my tags might be completely off.&#xD;&#xA;&#xD;&#xA;EDIT: I get image2 by printing image1 on some Windows native frame and then printing the mask on top of that image.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yhc6R.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VIOvh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30072" PostHistoryTypeId="2" PostId="10362" RevisionGUID="103d5d66-b9da-4c21-99f4-aa3fc74a2b3b" CreationDate="2020-11-02T08:19:47.237" UserId="7525" Text="I want to set a transformation matrix to an object upon creation and then control it by position, rotation and scale, but while changing the matrix does change the object in world space, it's position parameter still remains 0, 0, 0.&#xD;&#xA;&#xD;&#xA;    let mesh =  new THREE.Mesh(&#xD;&#xA;        new THREE.BoxGeometry(),&#xD;&#xA;        new THREE.MeshPhongMaterial({color:0xf15728})&#xD;&#xA;    )&#xD;&#xA;    this.scene.add(mesh)&#xD;&#xA;&#xD;&#xA;    let pos = new THREE.Vector3().setFromMatrixPosition(m)&#xD;&#xA;&#xD;&#xA;    mesh.matrixAutoUpdate = false&#xD;&#xA;    mesh.matrix.copy(m)&#xD;&#xA;&#xD;&#xA;    // ***************//&#xD;&#xA;    mesh.updateMatrix()&#xD;&#xA;    // ***************//&#xD;&#xA;    &#xD;&#xA;    console.log(&quot;mesh.position&quot;, mesh.position)&#xD;&#xA;    console.log(&quot;pos&quot;, pos)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the output for the values of both `pos` and `mesh.position`&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rpyoR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30073" PostHistoryTypeId="1" PostId="10362" RevisionGUID="103d5d66-b9da-4c21-99f4-aa3fc74a2b3b" CreationDate="2020-11-02T08:19:47.237" UserId="7525" Text="THREEjs: updating an object's matrix doesnt change it's position and rotation params" ContentLicense="CC BY-SA 4.0" />
  <row Id="30074" PostHistoryTypeId="3" PostId="10362" RevisionGUID="103d5d66-b9da-4c21-99f4-aa3fc74a2b3b" CreationDate="2020-11-02T08:19:47.237" UserId="7525" Text="|transformations|matrix|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30075" PostHistoryTypeId="2" PostId="10363" RevisionGUID="3fc6c4d2-c7ba-4854-8caa-81980907c78c" CreationDate="2020-11-02T18:09:46.543" UserId="13309" Text="I am trying to learn about 3d graphics from first principles, so i have decided to implement a simple thing, create a circle in 3d space &amp; rotate it along some axis. I understand the basics theory.&#xD;&#xA;1) position circle somewhere in 3d space.&#xD;&#xA;2) calculate its projection on some plane.&#xD;&#xA;&#xD;&#xA;Once i can get this i can use rotation matrix to calculate the new position of vertices. but i am a bit stuck at 2nd step.&#xD;&#xA;this is my code:&#xD;&#xA;&#xD;&#xA;    import pygame&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    (width, height) = (600, 500)&#xD;&#xA;    screen = pygame.display.set_mode((width, height))&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    running = True&#xD;&#xA;    &#xD;&#xA;    K = 8   # view plane distance&#xD;&#xA;    cz = 10 # z location of circle initially.&#xD;&#xA;    &#xD;&#xA;    # Pyagme 0.0 is at top left , but i want to center it at window?? is this even coorect to do or is should just continue using top left.&#xD;&#xA;&#xD;&#xA;    def translate_coords_to_center(x , y):&#xD;&#xA;        return (width/2 - x, height/2 - y)&#xD;&#xA;    &#xD;&#xA;    # plots a pixel&#xD;&#xA;    def pixel(x,y,color=(100,20,30)):&#xD;&#xA;        s = pygame.Surface((1,1))&#xD;&#xA;        s.fill(color)&#xD;&#xA;        r,r.x,r.y = s.get_rect(),x,y&#xD;&#xA;        screen.blit(s,r)&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    # Draw the circle&#xD;&#xA;    def circle(cx, cy, cz, radius):&#xD;&#xA;        N = 100&#xD;&#xA;        PI = 3.14&#xD;&#xA;        angle = 360 / N&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;    &#xD;&#xA;            pixel(x2, y2)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    while running:&#xD;&#xA;        x, y = translate_coords_to_center(0,0)&#xD;&#xA;        circle(x, y, cz, 50)&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;When i change the z position of circle, i get something like the below image, I am expecting the circle to not change its position but only its size, ( i know this cant be true as i am dividing by `z` ), am i missing some translation step? :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rQrsr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30076" PostHistoryTypeId="1" PostId="10363" RevisionGUID="3fc6c4d2-c7ba-4854-8caa-81980907c78c" CreationDate="2020-11-02T18:09:46.543" UserId="13309" Text="peojecting 3d onto 2d plane is not showing up correctly" ContentLicense="CC BY-SA 4.0" />
  <row Id="30077" PostHistoryTypeId="3" PostId="10363" RevisionGUID="3fc6c4d2-c7ba-4854-8caa-81980907c78c" CreationDate="2020-11-02T18:09:46.543" UserId="13309" Text="|3d|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30078" PostHistoryTypeId="5" PostId="10360" RevisionGUID="a69efb2d-8da9-42d0-8201-2bd0287e446a" CreationDate="2020-11-02T18:58:35.003" UserId="15159" Comment="added 107 characters in body; edited tags" Text="Let `image1` be:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And RGBA `mask` be:&#xD;&#xA;&#xD;&#xA;(45, 78, 251, 102)&#xD;&#xA;&#xD;&#xA;Apply `mask` on top of `image1` to get `image2`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now I need to do the reverse thing, given `image1` and `image2`, is there a formula or an algorithm (there has to be right?) to find the `mask`?&#xD;&#xA;&#xD;&#xA;Thanks in advance, first post in here I might lack vocabulary I'm sorry about that, my tags might be completely off.&#xD;&#xA;&#xD;&#xA;EDIT: i program in Java. I get image2 by drawing image1 on some Windows native frame using Graphics#drawImage and then drawing the filter made of (45, 78, 251, 102) RGBA pixels on top of that image using the same function.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yhc6R.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/VIOvh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30079" PostHistoryTypeId="6" PostId="10360" RevisionGUID="a69efb2d-8da9-42d0-8201-2bd0287e446a" CreationDate="2020-11-02T18:58:35.003" UserId="15159" Comment="added 107 characters in body; edited tags" Text="|filtering|masking|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30080" PostHistoryTypeId="2" PostId="10364" RevisionGUID="9940dc84-a861-432b-bf16-4cddeba4f631" CreationDate="2020-11-03T07:56:04.907" UserId="3073" Text="Your translate_coords_to_center(0,0) function should be done after you have done the projection from 3d to 2d. &#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;    &#xD;&#xA;            sx, sy = translate_coords_to_center(x2, y2)&#xD;&#xA;    &#xD;&#xA;            pixel(sy, sy)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30081" PostHistoryTypeId="5" PostId="10364" RevisionGUID="9d7250d8-ac21-4631-bdf4-73b44e224f41" CreationDate="2020-11-03T10:30:30.580" UserId="3073" Comment="added 387 characters in body" Text="Your translate_coords_to_center(0,0) function should be done after you have done the projection from 3d to 2d. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;    &#xD;&#xA;            sx, sy = translate_coords_to_center(x2, y2)&#xD;&#xA;    &#xD;&#xA;            pixel(sy, sy)&#xD;&#xA;&#xD;&#xA;    while running:&#xD;&#xA;        circle(0, 0, cz, 50)&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;The effect you are seeing is caused by 2 things.&#xD;&#xA; 1) Because a constant x/y offset is incorrectly added in 3d world space the array of circles will appear to the left and below of the camera's position.&#xD;&#xA; 2) Because the 0,0 origin of view/camera space is not the centre of the display, instead it's at the top-left (Adding the window centre coords AFTER projection fixes that)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30082" PostHistoryTypeId="5" PostId="10364" RevisionGUID="575b8024-16f8-4822-9f8c-13a9ef7748fb" CreationDate="2020-11-03T10:35:38.030" UserId="3073" Comment="added 387 characters in body" Text="Your translate_coords_to_center(0,0) function should be done after you have done the projection from 3d to 2d. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;    &#xD;&#xA;            sx, sy = translate_coords_to_center(x2, y2)&#xD;&#xA;    &#xD;&#xA;            pixel(sy, sy)&#xD;&#xA;&#xD;&#xA;    while running:&#xD;&#xA;        circle(0, 0, cz, 50)&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;The effect you are seeing is caused by 2 things.&#xD;&#xA; 1) Because a constant x/y offset is incorrectly added in 3d world space the array of circles will appear to the right and below of the camera's position.&#xD;&#xA; 2) Because the 0,0 origin of view/camera space is not the centre of the display, instead it's at the top-left (Adding the window centre coords AFTER projection fixes that)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30083" PostHistoryTypeId="5" PostId="10363" RevisionGUID="df0b8bfa-a6fc-4234-ae6f-842df0274663" CreationDate="2020-11-03T10:58:59.273" UserId="13309" Comment="added 1310 characters in body" Text="I am trying to learn about 3d graphics from first principles, so i have decided to implement a simple thing, create a circle in 3d space &amp; rotate it along some axis. I understand the basics theory.&#xD;&#xA;1) position circle somewhere in 3d space.&#xD;&#xA;2) calculate its projection on some plane.&#xD;&#xA;&#xD;&#xA;Once i can get this i can use rotation matrix to calculate the new position of vertices. but i am a bit stuck at 2nd step.&#xD;&#xA;this is my code:&#xD;&#xA;&#xD;&#xA;    import pygame&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    (width, height) = (600, 500)&#xD;&#xA;    screen = pygame.display.set_mode((width, height))&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    running = True&#xD;&#xA;    &#xD;&#xA;    K = 8   # view plane distance&#xD;&#xA;    cz = 10 # z location of circle initially.&#xD;&#xA;    &#xD;&#xA;    # Pyagme 0.0 is at top left , but i want to center it at window?? is this even coorect to do or is should just continue using top left.&#xD;&#xA;&#xD;&#xA;    def translate_coords_to_center(x , y):&#xD;&#xA;        return (width/2 - x, height/2 - y)&#xD;&#xA;    &#xD;&#xA;    # plots a pixel&#xD;&#xA;    def pixel(x,y,color=(100,20,30)):&#xD;&#xA;        s = pygame.Surface((1,1))&#xD;&#xA;        s.fill(color)&#xD;&#xA;        r,r.x,r.y = s.get_rect(),x,y&#xD;&#xA;        screen.blit(s,r)&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    # Draw the circle&#xD;&#xA;    def circle(cx, cy, cz, radius):&#xD;&#xA;        N = 100&#xD;&#xA;        PI = 3.14&#xD;&#xA;        angle = 360 / N&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;    &#xD;&#xA;            pixel(x2, y2)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    while running:&#xD;&#xA;        x, y = translate_coords_to_center(0,0)&#xD;&#xA;        circle(x, y, cz, 50)&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;When i change the z position of circle, i get something like the below image, I am expecting the circle to not change its position but only its size, ( i know this cant be true as i am dividing by `z` ), am i missing some translation step? :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rQrsr.png&#xD;&#xA;&#xD;&#xA;**EDIT:  Adding the translation after projection is also not working:**&#xD;&#xA;&#xD;&#xA;    import pygame&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    (width, height) = (600, 500)&#xD;&#xA;    screen = pygame.display.set_mode((width, height))&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    running = True&#xD;&#xA;    &#xD;&#xA;    K = 8   &#xD;&#xA;    cz = 10 &#xD;&#xA;    &#xD;&#xA;    def translate_coords_to_center(x , y):&#xD;&#xA;        return (width/2 - x, height/2 - y)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def pixel(x,y,color=(100,20,30)):&#xD;&#xA;        s = pygame.Surface((1,1))&#xD;&#xA;        s.fill(color)&#xD;&#xA;        r,r.x,r.y = s.get_rect(),x,y&#xD;&#xA;        screen.blit(s,r)&#xD;&#xA;    &#xD;&#xA;    def circle(cx, cy, cz, radius):&#xD;&#xA;        N = 100&#xD;&#xA;        PI = 3.14&#xD;&#xA;        angle = 360 / N&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;            sx, sy = translate_coords_to_center(x2, y2)&#xD;&#xA;    &#xD;&#xA;            pixel(sx, sy)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    while running:&#xD;&#xA;        x, y = translate_coords_to_center(0,0)&#xD;&#xA;        circle(x, y, cz, 50)&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30084" PostHistoryTypeId="4" PostId="10363" RevisionGUID="89981df6-175e-4dd4-988f-f36e2eb55ec0" CreationDate="2020-11-03T10:59:43.770" UserId="209" Comment="Fixed spelling in title" Text="projecting 3d onto 2d plane is not showing up correctly" ContentLicense="CC BY-SA 4.0" />
  <row Id="30085" PostHistoryTypeId="5" PostId="10363" RevisionGUID="a6c9139f-9978-4090-b9a2-c52105df2929" CreationDate="2020-11-03T11:03:30.327" UserId="13309" Comment="added 40 characters in body" Text="I am trying to learn about 3d graphics from first principles, so i have decided to implement a simple thing, create a circle in 3d space &amp; rotate it along some axis. I understand the basics theory.&#xD;&#xA;1) position circle somewhere in 3d space.&#xD;&#xA;2) calculate its projection on some plane.&#xD;&#xA;&#xD;&#xA;Once i can get this i can use rotation matrix to calculate the new position of vertices. but i am a bit stuck at 2nd step.&#xD;&#xA;this is my code:&#xD;&#xA;&#xD;&#xA;    import pygame&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    (width, height) = (600, 500)&#xD;&#xA;    screen = pygame.display.set_mode((width, height))&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    running = True&#xD;&#xA;    &#xD;&#xA;    K = 8   # view plane distance&#xD;&#xA;    cz = 10 # z location of circle initially.&#xD;&#xA;    &#xD;&#xA;    # Pyagme 0.0 is at top left , but i want to center it at window?? is this even coorect to do or is should just continue using top left.&#xD;&#xA;&#xD;&#xA;    def translate_coords_to_center(x , y):&#xD;&#xA;        return (width/2 - x, height/2 - y)&#xD;&#xA;    &#xD;&#xA;    # plots a pixel&#xD;&#xA;    def pixel(x,y,color=(100,20,30)):&#xD;&#xA;        s = pygame.Surface((1,1))&#xD;&#xA;        s.fill(color)&#xD;&#xA;        r,r.x,r.y = s.get_rect(),x,y&#xD;&#xA;        screen.blit(s,r)&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    # Draw the circle&#xD;&#xA;    def circle(cx, cy, cz, radius):&#xD;&#xA;        N = 100&#xD;&#xA;        PI = 3.14&#xD;&#xA;        angle = 360 / N&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;    &#xD;&#xA;            pixel(x2, y2)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    while running:&#xD;&#xA;        x, y = translate_coords_to_center(0,0)&#xD;&#xA;        circle(x, y, cz, 50)&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;When i change the z position of circle, i get something like the below image, I am expecting the circle to not change its position but only its size, ( i know this cant be true as i am dividing by `z` ), am i missing some translation step? :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rQrsr.png&#xD;&#xA;&#xD;&#xA;**EDIT:  Adding the translation after projection is also not working:**&#xD;&#xA;&#xD;&#xA;    import pygame&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    (width, height) = (600, 500)&#xD;&#xA;    screen = pygame.display.set_mode((width, height))&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    running = True&#xD;&#xA;    &#xD;&#xA;    K = 8   &#xD;&#xA;    cz = 10 &#xD;&#xA;    &#xD;&#xA;    def translate_coords_to_center(x , y):&#xD;&#xA;        return (width/2 - x, height/2 - y)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    def pixel(x,y,color=(100,20,30)):&#xD;&#xA;        s = pygame.Surface((1,1))&#xD;&#xA;        s.fill(color)&#xD;&#xA;        r,r.x,r.y = s.get_rect(),x,y&#xD;&#xA;        screen.blit(s,r)&#xD;&#xA;    &#xD;&#xA;    def circle(cx, cy, cz, radius):&#xD;&#xA;        N = 100&#xD;&#xA;        PI = 3.14&#xD;&#xA;        angle = 360 / N&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        for i in range(N):&#xD;&#xA;            x2 = cx + radius * math.cos(PI* angle * i / 180)&#xD;&#xA;            y2 = cy + radius * math.sin(PI* angle * i / 180)&#xD;&#xA;    &#xD;&#xA;            # Do a 2d projection&#xD;&#xA;            x2 = K* x2 / cz&#xD;&#xA;            y2 = K* y2 / cz&#xD;&#xA;            sx, sy = translate_coords_to_center(x2, y2)&#xD;&#xA;    &#xD;&#xA;            pixel(sx, sy)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    while running:&#xD;&#xA;        &#xD;&#xA;        circle(0,0, cz, 50) # this works correctly, but circles are centered at top left corner of screen,&#xD;&#xA;        cz += 1&#xD;&#xA;        pygame.display.flip()&#xD;&#xA;        for event in pygame.event.get():&#xD;&#xA;            if event.type == pygame.QUIT:&#xD;&#xA;                running = False&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30086" PostHistoryTypeId="2" PostId="10365" RevisionGUID="bb181add-ebee-45c0-b3a5-d28d1e99a48a" CreationDate="2020-11-03T18:27:11.003" UserId="15171" Text="I am writing a Vulkan video manipulation engine which has the following layers:&#xD;&#xA;1. Foreground (2D)&#xD;&#xA;2. Scene (3D)&#xD;&#xA;3. Background (2D)&#xD;&#xA;&#xD;&#xA;Note that each layer may have multiple objects, some of which may be transparent. For 2D objects (foreground and background), I want to preserve the relative between objects. Therefore, I thought about the following technique, in order to execute the FS the least amount of times possible:&#xD;&#xA;&#xD;&#xA;1. Draw the opaque foreground objects backwards, writing 0x02 at the stencil buffer.&#xD;&#xA;2. Draw the opaque scene objects backwards (sorted by average depth), writing and testing 0x01 at the stencil buffer and writing and testing at the depth buffer.&#xD;&#xA;3. Draw the opaque background objects backwards, writing and testing 0x00 at the stencil buffer.&#xD;&#xA;4. Draw the transparent background forwards, writing and testing 0x00 at the stencil buffer.&#xD;&#xA;5. Draw the transparent scene objects forwards (sorted by average depth), writing and testing 0x01 at the stencil buffer and writing and testing at the depth buffer.&#xD;&#xA;6. Draw the transparent foreground forwards, writing and testing 0x02 at the stencil buffer.&#xD;&#xA;&#xD;&#xA;However, this technique does not work as specified, as the relative order between transparent and opaque objects at the background and foreground won't be preserved. This other technique would satisfy the condition (regardless of cherry picking OIT issues) although it is not efficient:&#xD;&#xA;&#xD;&#xA;1. Draw the all the background objects forwards&#xD;&#xA;2. Draw the opaque scene objects backwards (sorted by average depth), writing and testing at the depth buffer.&#xD;&#xA;3. Draw the transparent scene objects forwards (sorted by average depth), writing and testing at the depth buffer.&#xD;&#xA;4. Draw the all the foreground objects forwards&#xD;&#xA;&#xD;&#xA;I would like to know if there is any technique with Vulkan that lets me implement the first algorithm without the mentioned problems. I've thought about a secondary depth buffer in which the relative order between 2D layers gets written (write and test a constant), but this leads me to a new concern:&#xD;&#xA;&#xD;&#xA; According to some posts, if gl_FragDepth gets written from a shader (remember that I pretend to write a constant value from an uniform buffer to the depth value), fragment shader gets fully executed, which throws away the purpose of this optimization." ContentLicense="CC BY-SA 4.0" />
  <row Id="30087" PostHistoryTypeId="1" PostId="10365" RevisionGUID="bb181add-ebee-45c0-b3a5-d28d1e99a48a" CreationDate="2020-11-03T18:27:11.003" UserId="15171" Text="Layer rendering in Vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="30088" PostHistoryTypeId="3" PostId="10365" RevisionGUID="bb181add-ebee-45c0-b3a5-d28d1e99a48a" CreationDate="2020-11-03T18:27:11.003" UserId="15171" Text="|vulkan|z-buffer|stencil-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30089" PostHistoryTypeId="2" PostId="10366" RevisionGUID="cc1ba04f-236e-4c76-bb48-6e863b6e58b4" CreationDate="2020-11-03T22:57:48.650" UserId="9505" Text="I'm implementing ERPT-style energy redistribution of primary samples within a pathtracer. Specifically, to improve the sampling of defocused areas.&#xD;&#xA;&#xD;&#xA;The core algorithm does two things:&#xD;&#xA;&#xD;&#xA;- If sample luminance is higher than threshold, I redistribute the sample energy over many backwards fired rays. This is stored in a framebuffer. The result of this is super clean!&#xD;&#xA;&#xD;&#xA;- I also store all non-redistributed samples in a separate framebuffer.&#xD;&#xA;&#xD;&#xA;My question is about how I should recombine these two framebuffers. Which probabilities should I be using? I've tried a variety of approaches but none of them have worked perfectly. I cannot just remove the samples-to-be-redistributed and sum the redistributed samples on top. This results in discontinuities. I think I need to be using a certain weighting.&#xD;&#xA;&#xD;&#xA;Any help would be appreciated!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30090" PostHistoryTypeId="1" PostId="10366" RevisionGUID="cc1ba04f-236e-4c76-bb48-6e863b6e58b4" CreationDate="2020-11-03T22:57:48.650" UserId="9505" Text="Energy redistribution sample re-integration" ContentLicense="CC BY-SA 4.0" />
  <row Id="30091" PostHistoryTypeId="3" PostId="10366" RevisionGUID="cc1ba04f-236e-4c76-bb48-6e863b6e58b4" CreationDate="2020-11-03T22:57:48.650" UserId="9505" Text="|rendering|pathtracing|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30092" PostHistoryTypeId="2" PostId="10367" RevisionGUID="d0c7c17a-a1e8-4b58-ad3d-9b5ddceee285" CreationDate="2020-11-04T03:31:36.533" UserId="15172" Text="I've taken a class about ray-plane intersection on this: https://www.khanacademy.org/computing/pixar/rendering/rendering1/v/rendering-1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose we shoot a ray at the scene and this scene contains millions of triangles. How can we know if the ray intersected one of the triangle? Do we just run a check on this millions of triangle and check if it intersects with the ray? That would be inefficient!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30093" PostHistoryTypeId="1" PostId="10367" RevisionGUID="d0c7c17a-a1e8-4b58-ad3d-9b5ddceee285" CreationDate="2020-11-04T03:31:36.533" UserId="15172" Text="How do we know if a ray intersected a triangle in one in a million" ContentLicense="CC BY-SA 4.0" />
  <row Id="30094" PostHistoryTypeId="3" PostId="10367" RevisionGUID="d0c7c17a-a1e8-4b58-ad3d-9b5ddceee285" CreationDate="2020-11-04T03:31:36.533" UserId="15172" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30095" PostHistoryTypeId="5" PostId="10367" RevisionGUID="2a0ba0a8-51c2-4a7b-a0fa-9709743a818b" CreationDate="2020-11-04T03:45:41.370" UserId="15172" Comment="deleted 10 characters in body" Text="I've taken a class about ray-plane intersection on this: https://www.khanacademy.org/computing/pixar/rendering/rendering1/v/rendering-1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose we shoot a ray at the scene and this scene contains millions of triangles. How can we know if the ray intersected one of the triangle? Do we just run a check on this millions of triangle if it intersects with the ray? That would be inefficient!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30096" PostHistoryTypeId="2" PostId="10368" RevisionGUID="f8e6a9dc-c8e5-40df-8ca5-baf8f66dedbb" CreationDate="2020-11-04T08:58:57.007" UserId="13095" Text="If you want to know all triangles that are hit by the ray, you have to check all of them. However, that doesn't mean that you have to check each of them individually. Usually, you apply some sort of [space partitioning](https://en.wikipedia.org/wiki/Space_partitioning) to your scene and group related objects in a [bounding volume hierarchy](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy). Then it gets a lot more efficient because you can drop multiple triangles with a single check. &#xD;&#xA;&#xD;&#xA;For example, consider a scene with a rectangular area. You might subdivide this area into a 10x10 grid. Now check which parts of the grid are hit by the ray. All objects located in grid cells that aren't hit by the ray can be discarded and you only need to check the remaining objects. Now let's say that one of the hit objects is a human. Before you test the individual triangles, you narrow down the affected area in multiple substeps by checking against its [bounding volume hierarchy](https://en.wikipedia.org/wiki/Bounding_volume_hierarchy). The traversal of the hierarchy might look like this: upper body hit -&gt; left arm hit -&gt; hand hit -&gt; thumb hit. So with 4 checks, you can discard all triangles of the humans' mesh that do not belong to the thumb.&#xD;&#xA;&#xD;&#xA;In case you only want to find the first triangle that is hit by the ray, you can also sort all hit cells and objects by distance before performing detailed tests. Then you start your checks at the closest object and continue until you get the first hit.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="30097" PostHistoryTypeId="5" PostId="10366" RevisionGUID="2c60d871-b00e-40aa-a47c-ef37bed091a7" CreationDate="2020-11-04T09:57:13.820" UserId="9505" Comment="added 551 characters in body" Text="I'm implementing ERPT-style energy redistribution of primary samples within a pathtracer. Specifically, to improve the sampling of defocused areas.&#xD;&#xA;&#xD;&#xA;The core algorithm does two things:&#xD;&#xA;&#xD;&#xA;- If sample luminance is higher than threshold, I redistribute the sample energy over many backwards fired rays. This is stored in a framebuffer. The result of this is super clean!&#xD;&#xA;&#xD;&#xA;- I also store all non-redistributed samples in a separate framebuffer.&#xD;&#xA;&#xD;&#xA;My question is about how I should recombine these two framebuffers. Which probabilities should I be using? I've tried a variety of approaches but none of them have worked perfectly. I cannot just remove the samples-to-be-redistributed and sum the redistributed samples on top. This results in discontinuities. I think I need to be using a certain weighting.&#xD;&#xA;&#xD;&#xA;An example scenario is as follows:&#xD;&#xA;&#xD;&#xA;Pathtraced result I start with:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Take a selection of the samples to redistribute:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Redistributing these high intensity samples in separate framebuffer:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How can I re-combine the redistributed &amp; unredistributed results?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any help would be appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NoPss.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/odXV8.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/BsFVp.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30098" PostHistoryTypeId="2" PostId="10369" RevisionGUID="b556ebf5-6e02-4903-8824-f8bf4ebba749" CreationDate="2020-11-04T10:16:52.430" UserId="11598" Text="While porting [this project](https://github.com/progschj/OpenGL-Examples/blob/master/12shader_image_load_store.cpp) with slightly modified code to Linux I ran into some weird behaviour.&#xD;&#xA;&#xD;&#xA;On Windows it runs just fine (https://youtu.be/xH6Dc6xOuow).&#xD;&#xA;&#xD;&#xA;But on Ubuntu it shows some [weird behaviour](https://youtu.be/BrZtWHw1Wmk).&#xD;&#xA;Aside from the much higher speed, the colors start to overlap near the end.&#xD;&#xA;&#xD;&#xA;The code is exactly the same for both examples (aside from the paths to the shaders, see below).&#xD;&#xA;On Ubuntu I did try different drivers for my graphics card, but this problem remained. &#xD;&#xA;Something which still comes to my mind, that could be wrong is the CMakeLists.txt file, as I am new to cmake.&#xD;&#xA;&#xD;&#xA;So why does this behaviour occur and how can I solve it?&#xD;&#xA;&#xD;&#xA;The code:&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    #include &lt;glad/glad.h&gt;&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    #include &lt;glm/gtc/noise.hpp&gt; &#xD;&#xA;    &#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;string&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;shader.h&quot;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int main() {&#xD;&#xA;        int width = 640;&#xD;&#xA;        int height = 480;&#xD;&#xA;    &#xD;&#xA;        if (glfwInit() == GL_FALSE) {&#xD;&#xA;            std::cerr &lt;&lt; &quot;failed to init GLFW&quot; &lt;&lt; std::endl;&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // select opengl version&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);&#xD;&#xA;    &#xD;&#xA;        // create a window&#xD;&#xA;        GLFWwindow* window;&#xD;&#xA;        if ((window = glfwCreateWindow(width, height, &quot;12shader_image_load_store&quot;, 0, 0)) == 0) {&#xD;&#xA;            std::cerr &lt;&lt; &quot;failed to open window&quot; &lt;&lt; std::endl;&#xD;&#xA;            glfwTerminate();&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;        // glad: load all OpenGL function pointers&#xD;&#xA;        // ---------------------------------------&#xD;&#xA;        if (!gladLoadGLLoader(reinterpret_cast&lt;GLADloadproc&gt;(glfwGetProcAddress)))&#xD;&#xA;        {&#xD;&#xA;            std::cout &lt;&lt; &quot;Failed to initialize GLAD&quot; &lt;&lt; std::endl;&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        //glfwSwapInterval(1);&#xD;&#xA;    &#xD;&#xA;        Shader shader1(&quot;source.vert&quot;, &quot;source1.frag&quot;);&#xD;&#xA;        Shader shader2(&quot;source.vert&quot;, &quot;source2.frag&quot;);&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;        // vao and vbo handle&#xD;&#xA;        GLuint vao, vbo, ibo;&#xD;&#xA;    &#xD;&#xA;        // generate and bind the vao&#xD;&#xA;        glGenVertexArrays(1, &amp;vao);&#xD;&#xA;        glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;        // generate and bind the vertex buffer object&#xD;&#xA;        glGenBuffers(1, &amp;vbo);&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    &#xD;&#xA;        // data for a fullscreen quad&#xD;&#xA;        GLfloat vertexData[] = {&#xD;&#xA;            //  X     Y     Z&#xD;&#xA;               1.0f, 1.0f, 0.0f, // vertex 0&#xD;&#xA;              -1.0f, 1.0f, 0.0f, // vertex 1&#xD;&#xA;               1.0f,-1.0f, 0.0f, // vertex 2&#xD;&#xA;              -1.0f,-1.0f, 0.0f, // vertex 3&#xD;&#xA;        }; // 4 vertices with 3 components (floats) each&#xD;&#xA;    &#xD;&#xA;        // fill with data&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 3, vertexData, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // set up generic attrib pointers&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (char*)0 + 0 * sizeof(GLfloat));&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // generate and bind the index buffer object&#xD;&#xA;        glGenBuffers(1, &amp;ibo);&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);&#xD;&#xA;    &#xD;&#xA;        GLuint indexData[] = {&#xD;&#xA;            0,1,2, // first triangle&#xD;&#xA;            2,1,3, // second triangle&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        // fill with data&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * 2 * 3, indexData, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;        // texture handle&#xD;&#xA;        GLuint texture;&#xD;&#xA;    &#xD;&#xA;        // generate texture&#xD;&#xA;        glGenTextures(1, &amp;texture);&#xD;&#xA;    &#xD;&#xA;        // bind the texture&#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, texture);&#xD;&#xA;    &#xD;&#xA;        // create some image data&#xD;&#xA;        std::vector&lt;GLfloat&gt; image(4 * width * height);&#xD;&#xA;        for (int j = 0; j &lt; height; ++j) {&#xD;&#xA;            for (int i = 0; i &lt; width; ++i) {&#xD;&#xA;                size_t index = j * width + i;&#xD;&#xA;                image[4 * index + 0] = 0.0f;&#xD;&#xA;                image[4 * index + 1] = 0.0f;&#xD;&#xA;                image[4 * index + 2] = 0.0f;&#xD;&#xA;                image[4 * index + 3] = 20.0f * glm::clamp(glm::perlin(0.006f * glm::vec2(i, j + 150)), 0.0f, 0.1f);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // set texture parameters&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);&#xD;&#xA;    &#xD;&#xA;        // set texture content&#xD;&#xA;        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &amp;image[0]);&#xD;&#xA;    	&#xD;&#xA;        float t = 0;&#xD;&#xA;        float dt = 1.0f / 60.0f;&#xD;&#xA;        while (!glfwWindowShouldClose(window)) {&#xD;&#xA;            glfwPollEvents();&#xD;&#xA;    &#xD;&#xA;            t += dt;&#xD;&#xA;    &#xD;&#xA;            // reset time every 10 seconds to repeat the sequence&#xD;&#xA;            if (t &gt; 20) t = 0;&#xD;&#xA;    &#xD;&#xA;            // clear first&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;            glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;    &#xD;&#xA;            // bind the vao&#xD;&#xA;            glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;            int substeps = 5;&#xD;&#xA;    &#xD;&#xA;            shader1.use();&#xD;&#xA;    &#xD;&#xA;            shader1.setIVec2(&quot;image_size&quot;, width, height);&#xD;&#xA;            shader1.setInt(&quot;image&quot;, 0);&#xD;&#xA;            shader1.setFloat(&quot;dt&quot;, static_cast&lt;float&gt;(50 * dt / substeps));&#xD;&#xA;    &#xD;&#xA;            shader2.use();&#xD;&#xA;    &#xD;&#xA;            shader2.setIVec2(&quot;image_size&quot;, width, height);&#xD;&#xA;            shader2.setInt(&quot;image&quot;, 0);&#xD;&#xA;            shader2.setFloat(&quot;dt&quot;, static_cast&lt;float&gt;(50 * dt / substeps));&#xD;&#xA;    &#xD;&#xA;        	&#xD;&#xA;            glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);&#xD;&#xA;            int i = 0;&#xD;&#xA;            for (; i &lt; substeps - 1; ++i) {&#xD;&#xA;                shader1.use();&#xD;&#xA;    &#xD;&#xA;                glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;    &#xD;&#xA;                shader2.use();&#xD;&#xA;                shader2.setFloat(&quot;t&quot;, static_cast&lt;float&gt;(t + i * dt / substeps));&#xD;&#xA;    &#xD;&#xA;                glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        	&#xD;&#xA;            shader1.use();&#xD;&#xA;    &#xD;&#xA;            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;    &#xD;&#xA;            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;            shader2.use();&#xD;&#xA;            shader2.setFloat(&quot;t&quot;, static_cast&lt;float&gt;(t + i * dt / substeps));&#xD;&#xA;    &#xD;&#xA;            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);&#xD;&#xA;    &#xD;&#xA;            // check for errors&#xD;&#xA;            GLenum error = glGetError();&#xD;&#xA;            if (error != GL_NO_ERROR) {&#xD;&#xA;                std::cerr &lt;&lt; error &lt;&lt; std::endl;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        	&#xD;&#xA;            // finally swap buffers&#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // delete the created objects&#xD;&#xA;    &#xD;&#xA;        glDeleteTextures(1, &amp;texture);&#xD;&#xA;    &#xD;&#xA;        glDeleteVertexArrays(1, &amp;vao);&#xD;&#xA;        glDeleteBuffers(1, &amp;vbo);&#xD;&#xA;        glDeleteBuffers(1, &amp;ibo);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        glfwDestroyWindow(window);&#xD;&#xA;        glfwTerminate();&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;shader.h&#xD;&#xA;&#xD;&#xA;    #ifndef SHADER_H&#xD;&#xA;    #define SHADER_H&#xD;&#xA;    &#xD;&#xA;    #include &lt;glad/glad.h&gt;&#xD;&#xA;    #include &lt;glm/glm.hpp&gt;&#xD;&#xA;    &#xD;&#xA;    #include &lt;string&gt;&#xD;&#xA;    #include &lt;fstream&gt;&#xD;&#xA;    #include &lt;sstream&gt;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    class Shader&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;    	unsigned int ID;&#xD;&#xA;    	// default constructor&#xD;&#xA;    	// -------------------&#xD;&#xA;    	Shader() { ID = -1; }&#xD;&#xA;    	// constructor generates the shader on the fly&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)&#xD;&#xA;    	{&#xD;&#xA;    		// 1. retrieve the vertex/fragment source code from filePath&#xD;&#xA;    		std::string vertexCode;&#xD;&#xA;    		std::string fragmentCode;&#xD;&#xA;    		std::string geometryCode;&#xD;&#xA;    		std::ifstream vShaderFile;&#xD;&#xA;    		std::ifstream fShaderFile;&#xD;&#xA;    		std::ifstream gShaderFile;&#xD;&#xA;    		// ensure ifstream objects can throw exceptions:&#xD;&#xA;    		vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);&#xD;&#xA;    		fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);&#xD;&#xA;    		gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);&#xD;&#xA;    		try&#xD;&#xA;    		{&#xD;&#xA;    			// open files&#xD;&#xA;    			vShaderFile.open(vertexPath);&#xD;&#xA;    			fShaderFile.open(fragmentPath);&#xD;&#xA;    			std::stringstream vShaderStream, fShaderStream;&#xD;&#xA;    			// read file's buffer contents into streams&#xD;&#xA;    			vShaderStream &lt;&lt; vShaderFile.rdbuf();&#xD;&#xA;    			fShaderStream &lt;&lt; fShaderFile.rdbuf();&#xD;&#xA;    			// close file handlers&#xD;&#xA;    			vShaderFile.close();&#xD;&#xA;    			fShaderFile.close();&#xD;&#xA;    			// convert stream into string&#xD;&#xA;    			vertexCode = vShaderStream.str();&#xD;&#xA;    			fragmentCode = fShaderStream.str();&#xD;&#xA;    			// if geometry shader path is present, also load a geometry shader&#xD;&#xA;    			if (geometryPath != nullptr)&#xD;&#xA;    			{&#xD;&#xA;    				gShaderFile.open(geometryPath);&#xD;&#xA;    				std::stringstream gShaderStream;&#xD;&#xA;    				gShaderStream &lt;&lt; gShaderFile.rdbuf();&#xD;&#xA;    				gShaderFile.close();&#xD;&#xA;    				geometryCode = gShaderStream.str();&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    		catch (std::ifstream::failure const&amp; e)&#xD;&#xA;    		{&#xD;&#xA;    			std::cout &lt;&lt; &quot;ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ&quot; &lt;&lt; std::endl;&#xD;&#xA;    		}&#xD;&#xA;    		const char* vShaderCode = vertexCode.c_str();&#xD;&#xA;    		const char* fShaderCode = fragmentCode.c_str();&#xD;&#xA;    		// 2. compile shaders&#xD;&#xA;    		unsigned int vertex, fragment;&#xD;&#xA;    		// vertex shader&#xD;&#xA;    		vertex = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    		glShaderSource(vertex, 1, &amp;vShaderCode, NULL);&#xD;&#xA;    		glCompileShader(vertex);&#xD;&#xA;    		checkCompileErrors(vertex, &quot;VERTEX&quot;);&#xD;&#xA;    		// fragment Shader&#xD;&#xA;    		fragment = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    		glShaderSource(fragment, 1, &amp;fShaderCode, NULL);&#xD;&#xA;    		glCompileShader(fragment);&#xD;&#xA;    		checkCompileErrors(fragment, &quot;FRAGMENT&quot;);&#xD;&#xA;    		// if geometry shader is given, compile geometry shader&#xD;&#xA;    		unsigned int geometry;&#xD;&#xA;    		if (geometryPath != nullptr)&#xD;&#xA;    		{&#xD;&#xA;    			const char* gShaderCode = geometryCode.c_str();&#xD;&#xA;    			geometry = glCreateShader(GL_GEOMETRY_SHADER);&#xD;&#xA;    			glShaderSource(geometry, 1, &amp;gShaderCode, NULL);&#xD;&#xA;    			glCompileShader(geometry);&#xD;&#xA;    			checkCompileErrors(geometry, &quot;GEOMETRY&quot;);&#xD;&#xA;    		}&#xD;&#xA;    		// shader Program&#xD;&#xA;    		ID = glCreateProgram();&#xD;&#xA;    		glAttachShader(ID, vertex);&#xD;&#xA;    		glAttachShader(ID, fragment);&#xD;&#xA;    		if (geometryPath != nullptr)&#xD;&#xA;    			glAttachShader(ID, geometry);&#xD;&#xA;    		glLinkProgram(ID);&#xD;&#xA;    		checkCompileErrors(ID, &quot;PROGRAM&quot;);&#xD;&#xA;    		// delete the shaders as they're linked into our program now and no longer necessery&#xD;&#xA;    		glDeleteShader(vertex);&#xD;&#xA;    		glDeleteShader(fragment);&#xD;&#xA;    		if (geometryPath != nullptr)&#xD;&#xA;    			glDeleteShader(geometry);&#xD;&#xA;    &#xD;&#xA;    	}&#xD;&#xA;    	// activate the shader&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void use()&#xD;&#xA;    	{&#xD;&#xA;    		glUseProgram(ID);&#xD;&#xA;    	}&#xD;&#xA;    	// utility uniform functions&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setBool(const std::string&amp; name, bool value) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setInt(const std::string&amp; name, int value) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform1i(glGetUniformLocation(ID, name.c_str()), value);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setFloat(const std::string&amp; name, float value) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform1f(glGetUniformLocation(ID, name.c_str()), value);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setVec2(const std::string&amp; name, const glm::vec2&amp; value) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]);&#xD;&#xA;    	}&#xD;&#xA;    	void setVec2(const std::string&amp; name, float x, float y) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);&#xD;&#xA;    	}&#xD;&#xA;    	void setIVec2(const std::string&amp; name, int x, int y) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform2i(glGetUniformLocation(ID, name.c_str()), x, y);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setVec3(const std::string&amp; name, const glm::vec3&amp; value) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]);&#xD;&#xA;    	}&#xD;&#xA;    	void setVec3(const std::string&amp; name, float x, float y, float z) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setVec4(const std::string&amp; name, const glm::vec4&amp; value) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &amp;value[0]);&#xD;&#xA;    	}&#xD;&#xA;    	void setVec4(const std::string&amp; name, float x, float y, float z, float w)&#xD;&#xA;    	{&#xD;&#xA;    		glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setMat2(const std::string&amp; name, const glm::mat2&amp; mat) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setMat3(const std::string&amp; name, const glm::mat3&amp; mat) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]);&#xD;&#xA;    	}&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void setMat4(const std::string&amp; name, const glm::mat4&amp; mat) const&#xD;&#xA;    	{&#xD;&#xA;    		glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &amp;mat[0][0]);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    private:&#xD;&#xA;    	// utility function for checking shader compilation/linking errors.&#xD;&#xA;    	// ------------------------------------------------------------------------&#xD;&#xA;    	void checkCompileErrors(GLuint shader, std::string type)&#xD;&#xA;    	{&#xD;&#xA;    		GLint success;&#xD;&#xA;    		GLchar infoLog[1024];&#xD;&#xA;    		if (type != &quot;PROGRAM&quot;)&#xD;&#xA;    		{&#xD;&#xA;    			glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;success);&#xD;&#xA;    			if (!success)&#xD;&#xA;    			{&#xD;&#xA;    				glGetShaderInfoLog(shader, 1024, NULL, infoLog);&#xD;&#xA;    				std::cout &lt;&lt; &quot;ERROR::SHADER_COMPILATION_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; infoLog &lt;&lt; &quot;\n -- --------------------------------------------------- -- &quot; &lt;&lt; std::endl;&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			glGetProgramiv(shader, GL_LINK_STATUS, &amp;success);&#xD;&#xA;    			if (!success)&#xD;&#xA;    			{&#xD;&#xA;    				glGetProgramInfoLog(shader, 1024, NULL, infoLog);&#xD;&#xA;    				std::cout &lt;&lt; &quot;ERROR::PROGRAM_LINKING_ERROR of type: &quot; &lt;&lt; type &lt;&lt; &quot;\n&quot; &lt;&lt; infoLog &lt;&lt; &quot;\n -- --------------------------------------------------- -- &quot; &lt;&lt; std::endl;&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    };&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;source.vert&#xD;&#xA;&#xD;&#xA;    #version 420&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) in vec4 vposition;&#xD;&#xA;    &#xD;&#xA;    void main() &#xD;&#xA;    {&#xD;&#xA;    	gl_Position = vposition;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;source1.frag&#xD;&#xA;&#xD;&#xA;    #version 420&#xD;&#xA;    &#xD;&#xA;    uniform float dt;&#xD;&#xA;    uniform ivec2 image_size;&#xD;&#xA;    uniform layout(rgba32f) image2D image;&#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    void main() &#xD;&#xA;    {&#xD;&#xA;       ivec2 coords = ivec2(gl_FragCoord.xy);&#xD;&#xA;    	vec4 HE = imageLoad(image, coords);&#xD;&#xA;    	float Ezdx = HE.z-imageLoad(image, coords-ivec2(1, 0)).z;&#xD;&#xA;    	float Ezdy = HE.z-imageLoad(image, coords-ivec2(0, 1)).z;&#xD;&#xA;       HE.xy += dt*vec2(-Ezdy, Ezdx);&#xD;&#xA;       imageStore(image, coords, HE);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;source2.frag&#xD;&#xA;&#xD;&#xA;    #version 420&#xD;&#xA;    &#xD;&#xA;    uniform float t;&#xD;&#xA;    uniform float dt;&#xD;&#xA;    uniform ivec2 image_size;&#xD;&#xA;    uniform layout(rgba32f) image2D image;&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    void main() &#xD;&#xA;    {&#xD;&#xA;       ivec2 coords = ivec2(gl_FragCoord.xy);&#xD;&#xA;    &#xD;&#xA;    	float e = 1;&#xD;&#xA;    	vec4 HE = imageLoad(image, coords);&#xD;&#xA;    	float r = HE.w;&#xD;&#xA;    	float Hydx = imageLoad(image, coords+ivec2(1, 0)).y&#xD;&#xA;    				-HE.y;&#xD;&#xA;    	float Hxdy = imageLoad(image, coords+ivec2(0, 1)).x&#xD;&#xA;    				-HE.x;&#xD;&#xA;    &#xD;&#xA;    	float Eout = dt*(Hydx-Hxdy)/(e);&#xD;&#xA;       HE.z = HE.z*(1-dt*r/e) + Eout;&#xD;&#xA;    &#xD;&#xA;    // add source at image center&#xD;&#xA;       if(coords.x == image_size.x/2 &amp;&amp; coords.y == image_size.y/2) &#xD;&#xA;    	{&#xD;&#xA;       		HE.z += 30*sin(15*t)*exp(-20*(t-2)*(t-2));&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;       imageStore(image, coords, HE);&#xD;&#xA;       FragColor = vec4(HE.z, HE.w, -HE.z, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;CMakeLists.txt (in root of project)&#xD;&#xA;&#xD;&#xA;    cmake_minimum_required(VERSION 3.15)&#xD;&#xA;    &#xD;&#xA;    # Define the project.&#xD;&#xA;    project(hello-opengl&#xD;&#xA;        LANGUAGES C CXX)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    ## 2. Targets&#xD;&#xA;    ## ==========&#xD;&#xA;    add_subdirectory(src)&#xD;&#xA;&#xD;&#xA;CMakeLists.txt (in src)&#xD;&#xA;&#xD;&#xA;    cmake_minimum_required(VERSION 3.15)&#xD;&#xA;    &#xD;&#xA;    # package dependencies&#xD;&#xA;    find_package(CMakeshift 3.5 REQUIRED)&#xD;&#xA;    find_package(glfw3 3.3.2 REQUIRED)&#xD;&#xA;    find_package(glm REQUIRED)&#xD;&#xA;    find_package(OpenGL 4.2 REQUIRED)&#xD;&#xA;    &#xD;&#xA;    #add glad library&#xD;&#xA;    add_library(glad &quot;../include/glad/glad.h&quot; &quot;glad.c&quot;)&#xD;&#xA;    target_include_directories(glad PUBLIC &quot;../include&quot;)&#xD;&#xA;    &#xD;&#xA;    # target&#xD;&#xA;    add_executable(hello-opengl&#xD;&#xA;        &quot;main.cpp&quot;)&#xD;&#xA;    &#xD;&#xA;    # include directory&#xD;&#xA;    target_include_directories(hello-opengl PRIVATE &quot;../include&quot;)&#xD;&#xA;    &#xD;&#xA;    # properties&#xD;&#xA;    target_compile_features(hello-opengl&#xD;&#xA;        PRIVATE&#xD;&#xA;            cxx_std_20)&#xD;&#xA;    &#xD;&#xA;    # compiler settings&#xD;&#xA;    include(CMakeshift/TargetCompileSettings)&#xD;&#xA;    cmakeshift_target_compile_settings(hello-opengl&#xD;&#xA;        PRIVATE&#xD;&#xA;            default)&#xD;&#xA;    &#xD;&#xA;    # target dependencies&#xD;&#xA;    target_link_libraries(hello-opengl&#xD;&#xA;        PRIVATE&#xD;&#xA;            OpenGL::GL&#xD;&#xA;            glad&#xD;&#xA;            glfw&#xD;&#xA;            glm)&#xD;&#xA;    &#xD;&#xA;    # installation&#xD;&#xA;    install(&#xD;&#xA;        TARGETS hello-opengl)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To the file structure.&#xD;&#xA;&#xD;&#xA;On Windows all files are in the same directory.&#xD;&#xA;&#xD;&#xA;On Ubuntu:&#xD;&#xA;&#xD;&#xA;CMakeLists.txt&#xD;&#xA; - inlcude -- shader.h, glad, KHR&#xD;&#xA; - shaders -- sourcer.vert, source1.frag, source2.frag&#xD;&#xA; - src     -- CMakeLists.txt, main.cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="30099" PostHistoryTypeId="1" PostId="10369" RevisionGUID="b556ebf5-6e02-4903-8824-f8bf4ebba749" CreationDate="2020-11-04T10:16:52.430" UserId="11598" Text="Different OpenGL behaviour on Windows and Ubuntu" ContentLicense="CC BY-SA 4.0" />
  <row Id="30100" PostHistoryTypeId="3" PostId="10369" RevisionGUID="b556ebf5-6e02-4903-8824-f8bf4ebba749" CreationDate="2020-11-04T10:16:52.430" UserId="11598" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30101" PostHistoryTypeId="2" PostId="10370" RevisionGUID="cc6705d8-e509-44ff-b0ec-b70abe2b04b4" CreationDate="2020-11-04T11:42:53.337" UserId="15175" Text="It sounds like you yet have to adjust the importance function of the Markov Chain according to the way you assign paths to each of the two estimators, path tracing and ERPT.&#xD;&#xA;&#xD;&#xA;If you think about it in the framework of MIS, you have two estimators with binary weights (according to your threshold). Now, the simplest (but inefficient) option to combine them would be to always run ERPT and path tracing for all paths, applying the weight to the splats only (this weighting is what I understand you do by separating them into different framebuffers).&#xD;&#xA;&#xD;&#xA;In your case, however, you only enter the ERPT chain for the paths that you want to further explore, therefore you do not actually enter the chain in a stationary distribution proportional to the measurement contribution. This breaks ERPT, as the startup bias removal no longer works correctly. To fix it, you need to additionally account for your path selection strategy in the importance function such that it matches the initial distribution of paths entering ERPT: The MIS weight of the ERPT estimator needs to become a part of its targeted distribution, preventing energy from running off into paths that would never actually trigger an ERPT run. Thus, you should be able to make the startup bias removal work with your path selection strategy." ContentLicense="CC BY-SA 4.0" />
  <row Id="30102" PostHistoryTypeId="5" PostId="10365" RevisionGUID="14f075da-4934-4147-997f-210224438749" CreationDate="2020-11-04T18:33:15.200" UserId="15171" Comment="deleted 8 characters in body" Text="I am writing a Vulkan video manipulation engine which has the following layers:&#xD;&#xA;1. Foreground (2D)&#xD;&#xA;2. Scene (3D)&#xD;&#xA;3. Background (2D)&#xD;&#xA;&#xD;&#xA;Note that each layer may have multiple objects, some of which may be transparent. For 2D objects (foreground and background), I want to preserve the relative between objects. Therefore, I thought about the following technique, in order to execute the FS the least amount of times possible:&#xD;&#xA;&#xD;&#xA;1. Draw the opaque foreground objects backwards, writing 0x02 at the stencil buffer.&#xD;&#xA;2. Draw the opaque scene objects backwards (sorted by average depth), writing and testing 0x01 at the stencil buffer and writing and testing at the depth buffer.&#xD;&#xA;3. Draw the opaque background objects backwards, writing and testing 0x00 at the stencil buffer.&#xD;&#xA;4. Draw the transparent background forwards, writing and testing 0x00 at the stencil buffer.&#xD;&#xA;5. Draw the transparent scene objects forwards (sorted by average depth), writing and testing 0x01 at the stencil buffer and writing and testing at the depth buffer.&#xD;&#xA;6. Draw the transparent foreground forwards, writing and testing 0x02 at the stencil buffer.&#xD;&#xA;&#xD;&#xA;However, this technique does not work as specified, as the relative order between transparent and opaque objects at the background and foreground won't be preserved. This other technique would satisfy the condition (regardless of cherry picking OIT issues) although it is not efficient:&#xD;&#xA;&#xD;&#xA;1. Draw all the background objects forwards&#xD;&#xA;2. Draw the opaque scene objects backwards (sorted by average depth), writing and testing at the depth buffer.&#xD;&#xA;3. Draw the transparent scene objects forwards (sorted by average depth), writing and testing at the depth buffer.&#xD;&#xA;4. Draw all the foreground objects forwards&#xD;&#xA;&#xD;&#xA;I would like to know if there is any technique with Vulkan that lets me implement the first algorithm without the mentioned problems. I've thought about a secondary depth buffer in which the relative order between 2D layers gets written (write and test a constant), but this leads me to a new concern:&#xD;&#xA;&#xD;&#xA; According to some posts, if gl_FragDepth gets written from a shader (remember that I pretend to write a constant value from an uniform buffer to the depth value), fragment shader gets fully executed, which throws away the purpose of this optimization." ContentLicense="CC BY-SA 4.0" />
  <row Id="30103" PostHistoryTypeId="2" PostId="10371" RevisionGUID="5187b261-da6f-40db-a83c-ca7e53d45f93" CreationDate="2020-11-04T20:37:14.003" UserId="48" Text="First, regarding the specific problem of bits of the geometry being lost to the near and far planes, this can be solved by using [depth clamping](https://www.khronos.org/opengl/wiki/Vertex_Post-Processing#Depth_clamping) instead of depth clipping. This disables clipping against the near and far planes, in favor of clamping the output depth values to [0, 1]. (Geometry behind the camera will still be clipped though.) Given this, instead of a fullscreen quad you could render the light volume with inverted culling, depth testing inverted (to cull pixels behind the volume), and use depth clamping to prevent losing parts of the volume to the far clip plane.&#xD;&#xA;&#xD;&#xA;(Depth clamping is also handy for shadow maps, as it lets you contract the shadow map depth bounds to bracket the view frustum, without losing geometry between the view frustum and the light source.)&#xD;&#xA;&#xD;&#xA;In a broader sense, though, this doesn't really solve the problem of shading pixels within a given convex volume. The problem is that you need two depth tests: front of volume &lt; pixel depth &lt; back of volume. The approaches discussed so far can only do one of these tests at a time. You can switch which one you're doing by swapping culling and depth-testing modes, but you can't do both at once, which leaves performance on the table.&#xD;&#xA;&#xD;&#xA;One approach to address this is to [use the stencil buffer in concert with depth testing](https://kayru.org/articles/deferred-stencil/). Basically this works by testing scene depth against the front of the light volume first, storing that to the stencil buffer, then doing a second pass that tests scene depth against the back of the light volume, and combining that with the stencil result from the first pass. This has the advantage of getting tight culling (no pixels shaded outside the volume), but you need to draw each light volume twice, plus making a lot of state changes to switch back and forth, which can be inefficient for both CPU and GPU (though you can batch up to 8 lights together using 1 stencil bit per light).&#xD;&#xA;&#xD;&#xA;Finally, using [EXT_depth_bounds_test](https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_depth_bounds_test.txt), if available, can be a good solution. This enables a form of depth test that checks whether the pixel already in the framebuffer (not the geometry being rasterized) is within a certain range. With this, you set the depth bounds to the min/max depth of your light volume, then draw the geometry with inverted culling, no depth test, and depth clamping enabled. This will shade all pixels within a sort of prism aligned with the view frustum, that bounds the actual volume reasonably tightly in most cases (though long narrow spotlights can be bad), and it does it in only one pass. However, this extension isn't universally available; it seems to be found on current NVIDIA and AMD GPUs, but not Intel ones (see [OpenGL Hardware Database](http://opengl.gpuinfo.org/listreports.php?extension=GL_EXT_depth_bounds_test)).&#xD;&#xA;&#xD;&#xA;All of this difficulty is one reason that most game engines since the early 2010s have switched to [compute-shader tiled culling](https://johanmedestrom.wordpress.com/2016/03/30/tiled-deferred-shading-in-opengl-using-compute-shaders/) instead of using the rasterizer to decide which lights to shade at which pixel." ContentLicense="CC BY-SA 4.0" />
  <row Id="30104" PostHistoryTypeId="5" PostId="10367" RevisionGUID="04dbfb31-cf5f-4d98-98bb-a005990f5a81" CreationDate="2020-11-05T00:57:22.887" UserId="15172" Comment="Replaced link with the correct one." Text="I've taken a class about ray-plane intersection on this: https://www.khanacademy.org/computing/pixar/rendering/rendering-2/v/rendering-5&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose we shoot a ray at the scene and this scene contains millions of triangles. How can we know if the ray intersected one of the triangle? Do we just run a check on this millions of triangle if it intersects with the ray? That would be inefficient!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30105" PostHistoryTypeId="2" PostId="10372" RevisionGUID="25f9e939-b6c9-4eaa-a402-b0fdaa1ff0dc" CreationDate="2020-11-05T15:05:37.820" UserId="15183" Text="According to [Phong's reflection model][1], there are different reflection constants (**k**) and different intensities of the light source (**i**) for ambient, diffuse, and specular terms:&#xD;&#xA;&#xD;&#xA;$I_p=k_ai_a+\sum_{m \in lights} \left(k_d(\hat{L}_m \cdot \hat{N})i_{m,d} + k_s(\hat{R}_m \cdot \hat{V})^\alpha i_{m,s} \right)$&#xD;&#xA;&#xD;&#xA;I had some questions about this model:&#xD;&#xA;&#xD;&#xA; 1. When a pixel is under shadow (umbra), does the equation become this way:&#xD;&#xA;     $I_p=k_ai_a$ ?&#xD;&#xA; 2. Suppose we only have one major light source. So the equation can be something like this: $I_p \approx k_ai_a+ k_d(\hat{L} \cdot \hat{N})i_{d} + k_s(\hat{R} \cdot \hat{V})^\alpha i_{s} $&#xD;&#xA;   &#xD;&#xA;    Can the ambient portion of pixels ($k_ai_a$) become larger than the rest (even with no specular reflection)?&#xD;&#xA;&#xD;&#xA;    Basically, can this happen: $k_ai_a \stackrel{?}{\geq} k_d(\hat{L} \cdot \hat{N})i_{d}$&#xD;&#xA;&#xD;&#xA; 3. Is there any relationship between $k_a, k_d, k_s$ and $i_a, i_d, i_s$ of one point in a scene?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Phong_reflection_model" ContentLicense="CC BY-SA 4.0" />
  <row Id="30106" PostHistoryTypeId="1" PostId="10372" RevisionGUID="25f9e939-b6c9-4eaa-a402-b0fdaa1ff0dc" CreationDate="2020-11-05T15:05:37.820" UserId="15183" Text="Can ambient light reflection of a surface be larger than diffuse reflection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30107" PostHistoryTypeId="3" PostId="10372" RevisionGUID="25f9e939-b6c9-4eaa-a402-b0fdaa1ff0dc" CreationDate="2020-11-05T15:05:37.820" UserId="15183" Text="|rendering|lighting|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30113" PostHistoryTypeId="5" PostId="5538" RevisionGUID="9209435e-4a8d-46af-a19c-8b408d9ff95c" CreationDate="2020-11-06T08:55:36.630" UserId="13095" Comment="Add a clarification mentioned in a deleted comment and fix some typos" Text="I have asked this question on [ru.stackoverflow.com][1] and have no valid answers.&#xD;&#xA;&#xD;&#xA;Specification:&#xD;&#xA;&#xD;&#xA;1. [Coordinate system][2]&#xD;&#xA;2. Cube spins around its center on all three axes.&#xD;&#xA;3. Turn angle is not known previously.&#xD;&#xA;4. Parallel projection calculated by:&#xD;&#xA;&gt; x`` = x;&#xD;&#xA;&gt;&#xD;&#xA;&gt; y`` = y + z / 4;&#xD;&#xA;5. Per unit of time only 3 sides, closest to the projection plane, are visible.&#xD;&#xA;&#xD;&#xA;Question:&#xD;&#xA;&#xD;&#xA;**How to determine which are the closest sides?**&#xD;&#xA;&#xD;&#xA;I'm going this way: take pairs of sides left and right, front and back, top and bottom, then determine closest and farthest points in (Z) axis, determine the equation of a line, take the second farthest point in (Z) axis, and substitute into this equation - so determine the inclination of the side. Based on this choose which side is closer. I want to draw only the visible faces.&#xD;&#xA;&#xD;&#xA;This code don't work:&#xD;&#xA;&#xD;&#xA;&lt;!-- begin snippet: js hide: true console: true babel: false --&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-js --&gt;&#xD;&#xA;&#xD;&#xA;    // Получаем параллельную проекцию кубика на плоскость экрана&#xD;&#xA;    function getParallelProjection(arr) {&#xD;&#xA;&#xD;&#xA;    var i, j, k;&#xD;&#xA;&#xD;&#xA;    var arr_new = [];&#xD;&#xA;&#xD;&#xA;    // Попарно работаем с гранями&#xD;&#xA;    // Левая и правая&#xD;&#xA;    arr_new[0] = getSideParallelProjection(arr[0], arr[1], arr[6]);&#xD;&#xA;    // Задняя и передняя&#xD;&#xA;    arr_new[1] = getSideParallelProjection(arr[2], arr[3], arr[6]);&#xD;&#xA;    // Верхняя и нижняя&#xD;&#xA;    arr_new[2] = getSideParallelProjection(arr[4], arr[5], arr[6]);&#xD;&#xA;&#xD;&#xA;    return arr_new;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Параллельная проекция грани&#xD;&#xA;    function getSideParallelProjection(side1, side2, cubeCenter) {&#xD;&#xA;&#xD;&#xA;        // Сначала выясним какая пара нам попалась&#xD;&#xA;        var centralProjection1 = getPointParallelProjection(side1[4]);&#xD;&#xA;        var centralProjection2 = getPointParallelProjection(side2[4]);&#xD;&#xA;&#xD;&#xA;        var coordinate = {&#xD;&#xA;            x:Math.abs(side1[4].x - side2[4].x),&#xD;&#xA;            y:Math.abs(side1[4].y - side2[4].y),&#xD;&#xA;            z:Math.abs(side1[4].z - side2[4].z)};&#xD;&#xA;&#xD;&#xA;        var i;&#xD;&#xA;&#xD;&#xA;        // Найдем дальнюю (1) и ближнюю (2) от экрана точки&#xD;&#xA;        // по оси (Z) и посчитаем их проекции&#xD;&#xA;        var point1 = {z:10000},&#xD;&#xA;        point2 = {z:-10000},&#xD;&#xA;        point3 = {z:10000};&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 4; i++) {&#xD;&#xA;            if (point1.z &gt; side1[i].z) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point1.z == side1[i].z&#xD;&#xA;                &amp;&amp; point1.x &gt; side1[i].x) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point1.z == side1[i].z&#xD;&#xA;                &amp;&amp; point1.x == side1[i].x&#xD;&#xA;                &amp;&amp; point1.y &lt; side1[i].y) {&#xD;&#xA;                point1 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z &lt; side1[i].z) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z == side1[i].z&#xD;&#xA;                &amp;&amp; point2.x &lt; side1[i].x) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point2.z == side1[i].z&#xD;&#xA;                &amp;&amp; point2.x == side1[i].x&#xD;&#xA;                &amp;&amp; point2.y &gt; side1[i].y) {&#xD;&#xA;                point2 = side1[i];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        for (i = 0; i &lt; 4; i++) {&#xD;&#xA;            if (point3.z &gt; side1[i].z&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point3.z == side1[i].z&#xD;&#xA;                &amp;&amp; point3.x &gt; side1[i].x&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;            if (point3.z == side1[i].z&#xD;&#xA;                &amp;&amp; point3.x == side1[i].x&#xD;&#xA;                &amp;&amp; point3.y &lt; side1[i].y&#xD;&#xA;                &amp;&amp; point1 != side1[i]) {&#xD;&#xA;                point3 = side1[i];&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                      - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;        var projection = [];&#xD;&#xA;&#xD;&#xA;        // (X) Правая и левая грани&#xD;&#xA;        if (coordinate.x &gt; coordinate.y &amp;&amp; coordinate.x &gt; coordinate.z) {&#xD;&#xA;&#xD;&#xA;            point1 = getPointParallelProjection(point1);&#xD;&#xA;            point2 = getPointParallelProjection(point2);&#xD;&#xA;            point3 = getPointParallelProjection(point3);&#xD;&#xA;&#xD;&#xA;            var direction = (point3.x - point1.x) / (point2.x - point1.x)&#xD;&#xA;                          - (point3.y - point1.y) / (point2.y - point1.y);&#xD;&#xA;&#xD;&#xA;            var selected;&#xD;&#xA;&#xD;&#xA;            if (point1.x &gt;= point2.x) {&#xD;&#xA;                if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            } else {&#xD;&#xA;                if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (selected.length &lt; 6) {&#xD;&#xA;                for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                    projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                }&#xD;&#xA;                projection[4] = 'rgb(200,200,0)';&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // (Z) Передняя и задняя грани&#xD;&#xA;        else if (coordinate.z &gt; coordinate.x &amp;&amp; coordinate.z &gt; coordinate.y) {&#xD;&#xA;&#xD;&#xA;            var selected;&#xD;&#xA;&#xD;&#xA;            if (point1.x &gt;= point2.x &amp;&amp; direction &lt; 0) {&#xD;&#xA;                if (centralProjection1.x &gt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            } else {&#xD;&#xA;                if (centralProjection1.x &lt;= centralProjection2.x) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (selected.length &lt; 6) {&#xD;&#xA;                for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                    projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                }&#xD;&#xA;                projection[4] = 'rgb(200,0,0)';&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // (Y) Верхняя и нижняя грани&#xD;&#xA;        else {&#xD;&#xA;&#xD;&#xA;            var selected;&#xD;&#xA;&#xD;&#xA;            if (point1.y &lt;= point2.y) {&#xD;&#xA;                if (centralProjection1.y &lt;= centralProjection2.y) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            } else {&#xD;&#xA;                if (centralProjection1.y &gt;= centralProjection2.y) {&#xD;&#xA;                    selected = side1;&#xD;&#xA;                } else {&#xD;&#xA;                    selected = side2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (selected.length &lt; 6) {&#xD;&#xA;                for (i = 0; i &lt; 4; i++) {&#xD;&#xA;                    projection[i] = getPointParallelProjection(selected[i]);&#xD;&#xA;                }&#xD;&#xA;                projection[4] = 'rgb(0,0,0)';&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return projection;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Параллельная проекция точки&#xD;&#xA;    function getPointParallelProjection(point) {&#xD;&#xA;    return {&#xD;&#xA;        x:point.x,&#xD;&#xA;        y:point.y + point.z / 4};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;canvas id=&quot;animation&quot; width=&quot;300&quot; height=&quot;300&quot;&gt;&#xD;&#xA;        &lt;p&gt;Your browser does not support Canvas&lt;/p&gt;&#xD;&#xA;    &lt;/canvas&gt;&#xD;&#xA;&#xD;&#xA;&lt;!-- end snippet --&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://ru.stackoverflow.com/questions/705286/%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D1%82%D0%BE%D1%80%D0%BE%D0%BD-%D0%BA%D1%83%D0%B1%D0%B0-%D0%BE%D1%82-%D0%BF%D0%BB%D0%BE%D1%81%D0%BA%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%86%D0%B8%D0%B8&#xD;&#xA;  [2]: https://i.stack.imgur.com/bKXyI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30114" PostHistoryTypeId="2" PostId="10374" RevisionGUID="72c4ed9a-0afb-4e74-a05a-50804889fe5d" CreationDate="2020-11-06T09:26:05.077" UserId="10615" Text="What is a good algorithm for rendering a particle system as a coherent mesh, in realtime? I am running a smoothed-particle hydrodynamics fluid simulation, and I would like to render the particles not as balls but as a body of water.&#xD;&#xA;&#xD;&#xA;I understand that the basis is to find all places where the combined density of the particle system is equal to a certain boundary value, which will yield a surface which is smooth. However, how do you actually do so quickly and translate it into vertices and triangles to render?&#xD;&#xA;&#xD;&#xA;Another option is raytracing, raymarching specifically. Just march until the density reaches the boundary value. However, I'm still stuck on how to get the surface normal in this case, as well as how to make it performant. Surely you don't need to iterate through all particles, the far away particles won't have any effect, but I don't know how to spatially cull particles.&#xD;&#xA;&#xD;&#xA; 1. What are some algorithms for spatially culling far away particles with no local contribution?&#xD;&#xA; 2. What are some algorithms for getting the surface normal of a body of water made of particles?&#xD;&#xA; 3. What are some algorithms for getting the surface of a body of water made of particles, in the form of a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30115" PostHistoryTypeId="1" PostId="10374" RevisionGUID="72c4ed9a-0afb-4e74-a05a-50804889fe5d" CreationDate="2020-11-06T09:26:05.077" UserId="10615" Text="Rendering a particle system as a smooth blob" ContentLicense="CC BY-SA 4.0" />
  <row Id="30116" PostHistoryTypeId="3" PostId="10374" RevisionGUID="72c4ed9a-0afb-4e74-a05a-50804889fe5d" CreationDate="2020-11-06T09:26:05.077" UserId="10615" Text="|rasterizer|raymarching|particles|fluid-sim|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30124" PostHistoryTypeId="50" PostId="10247" RevisionGUID="e4a5dab2-342b-4f44-97dd-8f979531db1d" CreationDate="2020-11-07T03:02:40.247" UserId="-1" />
  <row Id="30129" PostHistoryTypeId="2" PostId="10376" RevisionGUID="8c2f425b-8525-483c-98c5-00bf03779fff" CreationDate="2020-11-07T04:51:15.923" UserId="48" Text="For culling faraway particles: as lightxbulb said, the keyword to search for is &quot;acceleration structure&quot;. There are a variety of options: BVH, octree, kd-tree, uniform grid, or some combination of these. Which one will be most suitable is going to depend on the details of your situation—how large/dense is the simulation, how much you care about performance vs memory vs implementation complexity, and so on.&#xD;&#xA;&#xD;&#xA;They all work by subdividing space into volumes in some fashion and keeping track of which particles are in each volume. Then, when you're marching you only need to keep track of which volume you're in, and that will tell you which particles can potentially contribute to the density at that point. For instance if it's a uniform grid, you only need to look at the current cell and possibly some of its immediate neighbors if they're within the maximum particle radius of your current point.&#xD;&#xA;&#xD;&#xA;For getting the surface normal: assuming you've defined a density field for your particles, the surface normal is just the gradient vector of the density field. This can be calculated by finite differences between nearby points in the field, or analytically by adding up gradient contributions from each particle.&#xD;&#xA;&#xD;&#xA;For getting the surface in the form of a mesh: the keyword to search for is &quot;isosurface extraction&quot;. Marching cubes is one example of such an algorithm, as lightxbulb mentioned. It evaluates the density field at evenly spaced grid points, uses those values to estimate where the intersection of the surface with the cubes' edges will be, and constructs from that a tiny mesh within each cube. Stitching all those meshes together yields a representation of the full surface. Naturally, the accuracy of it depends on the size of the grid used.&#xD;&#xA;&#xD;&#xA;There is also a variant that uses tetahedra instead of cubes, and another similar algorithm called &quot;dual contouring&quot;. [Here's a nice article](https://wordsandbuttons.online/interactive_explanation_of_marching_cubes_and_dual_contouring.html) showing how these work interactively (in 2D). There's also a great deal of literature on how to improve accuracy, performance, etc. with these kinds of methods." ContentLicense="CC BY-SA 4.0" />
  <row Id="30131" PostHistoryTypeId="50" PostId="9919" RevisionGUID="eadbd980-d1d5-4859-9e7c-719d1afc7a06" CreationDate="2020-11-07T11:04:40.493" UserId="-1" />
  <row Id="30132" PostHistoryTypeId="50" PostId="9926" RevisionGUID="7d66e2a9-22d2-415a-a26d-07e55b1cd059" CreationDate="2020-11-07T23:02:00.177" UserId="-1" />
  <row Id="30133" PostHistoryTypeId="2" PostId="10377" RevisionGUID="9c5285e9-6c6d-4432-a408-bf8af09f19ac" CreationDate="2020-11-08T07:22:56.420" UserId="15191" Text="I am wondering about techniques for rendering a rotated and or scaled raster image. Currently I use the following algorithm&#xD;&#xA;&#xD;&#xA;1. Render everything at double resolution and store the result in `A`&#xD;&#xA;2. For each pixel in output image, assign it the value of the average of the four pixels in `A`&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;img(col, row) = 0.25f * (tmp(2 * col, 2 * row) + tmp(2 * col + 1, 2 * row) + tmp(2 * col, 2 * row + 1) + tmp(2 * col + 1, 2 * row + 1));&#xD;&#xA;```&#xD;&#xA;I think it works sufficiently well for rotated images, but it has no impact on scaled images.&#xD;&#xA;&#xD;&#xA;Current sampler looks like this:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;			auto const loc_ret = vec2_t{static_cast&lt;double&gt;(col), static_cast&lt;double&gt;(row)};&#xD;&#xA;			auto const src_pos =&#xD;&#xA;			    scale_factor * transform(loc_ret - loc_src_ret_coord, rot_x, rot_y) + origin_src;&#xD;&#xA;			if(src_pos[0] &gt;= 0 &amp;&amp; src_pos[0] &lt; src.width() &amp;&amp; src_pos[1] &gt;= 0&#xD;&#xA;			   &amp;&amp; src_pos[1] &lt; src.height())&#xD;&#xA;			{&#xD;&#xA;				auto const src_pixel =&#xD;&#xA;				    src(static_cast&lt;uint32_t&gt;(src_pos[0]), static_cast&lt;uint32_t&gt;(src_pos[1]));&#xD;&#xA;				auto&amp; ret_pixel =&#xD;&#xA;				    ret((col + ret.width()) % ret.width(), (row + ret.height()) % ret.height());&#xD;&#xA;				ret_pixel = blend(ret_pixel, src_pixel, opacity);&#xD;&#xA;			}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;auto const scale_factor = 1.0 / (scale * layer.scaleFactor());&#xD;&#xA;```&#xD;&#xA;and scale is the scale used to down-sample the image once completed." ContentLicense="CC BY-SA 4.0" />
  <row Id="30134" PostHistoryTypeId="1" PostId="10377" RevisionGUID="9c5285e9-6c6d-4432-a408-bf8af09f19ac" CreationDate="2020-11-08T07:22:56.420" UserId="15191" Text="How to render a rotated raster image with lesser aliasing" ContentLicense="CC BY-SA 4.0" />
  <row Id="30135" PostHistoryTypeId="3" PostId="10377" RevisionGUID="9c5285e9-6c6d-4432-a408-bf8af09f19ac" CreationDate="2020-11-08T07:22:56.420" UserId="15191" Text="|image-processing|raster-image|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30136" PostHistoryTypeId="5" PostId="10377" RevisionGUID="73fee6eb-8c02-4f2c-a136-bcc740cd1505" CreationDate="2020-11-08T07:49:34.347" UserId="15191" Comment="added 20 characters in body" Text="I am wondering about techniques for rendering a rotated and or scaled raster image. Currently I use the following algorithm&#xD;&#xA;&#xD;&#xA;1. Render everything at double resolution and store the result in `A`&#xD;&#xA;2. For each pixel in output image, assign it the value of the average of the four pixels in `A`&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;img(col, row) = 0.25f * (tmp(2 * col, 2 * row) + tmp(2 * col + 1, 2 * row) + tmp(2 * col, 2 * row + 1) + tmp(2 * col + 1, 2 * row + 1));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Current sampler looks like this:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;			auto const loc_ret = vec2_t{static_cast&lt;double&gt;(col), static_cast&lt;double&gt;(row)};&#xD;&#xA;			auto const src_pos =&#xD;&#xA;			    scale_factor * transform(loc_ret - loc_src_ret_coord, rot_x, rot_y) + origin_src;&#xD;&#xA;			if(src_pos[0] &gt;= 0 &amp;&amp; src_pos[0] &lt; src.width() &amp;&amp; src_pos[1] &gt;= 0&#xD;&#xA;			   &amp;&amp; src_pos[1] &lt; src.height())&#xD;&#xA;			{&#xD;&#xA;				auto const src_pixel =&#xD;&#xA;				    src(static_cast&lt;uint32_t&gt;(src_pos[0]), static_cast&lt;uint32_t&gt;(src_pos[1]));&#xD;&#xA;				auto&amp; ret_pixel =&#xD;&#xA;				    ret((col + ret.width()) % ret.width(), (row + ret.height()) % ret.height());&#xD;&#xA;				ret_pixel = blend(ret_pixel, src_pixel, opacity);&#xD;&#xA;			}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;auto const scale_factor = 1.0 / (scale * layer.scaleFactor());&#xD;&#xA;```&#xD;&#xA;and scale is the scale used to down-sample the image once completed.&#xD;&#xA;&#xD;&#xA;The algorithm works for rotated and down-scaled sources, however, it has no effect when the source is upscaled." ContentLicense="CC BY-SA 4.0" />
  <row Id="30137" PostHistoryTypeId="2" PostId="10378" RevisionGUID="babd6ba1-2c04-4a86-a5a0-b81b89ec6c84" CreationDate="2020-11-08T13:51:35.277" UserId="15196" Text="I'm practicing GLSL on ShaderToy&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord ) {&#xD;&#xA;&#xD;&#xA;    vec2 coord = fragCoord.xy/iResolution.xy;&#xD;&#xA;   &#xD;&#xA;    vec3 background = vec3(1.);&#xD;&#xA;    &#xD;&#xA;    vec3 axesColor = vec3(1.,0.,0.);&#xD;&#xA;    vec3 gridColor = vec3(0.85);&#xD;&#xA;    &#xD;&#xA;    vec3 color = background;&#xD;&#xA;    &#xD;&#xA;    const float tickWidth = 0.1;&#xD;&#xA;    for(float i = 0.0 ; i &lt; 1.0 ; i += tickWidth)&#xD;&#xA;    {&#xD;&#xA;   		if(abs(coord.x - i) &lt; 0.002) color = gridColor;&#xD;&#xA;        if(abs(coord.y - i) &lt; 0.002) color = gridColor;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if(abs(coord.x) &lt; 0.005) color = axesColor;&#xD;&#xA;    **if(abs(coord.y) &lt; 0.005) color = axesColor;**&#xD;&#xA;    **//color = abs(coord.y) &lt; 0.005 ? axesColor : background;**&#xD;&#xA;&#xD;&#xA;    fragColor = vec4(color,1.0);  }&#xD;&#xA;&#xD;&#xA;my question is on last 3 lines.&#xD;&#xA;&#xD;&#xA;First, I used ternary operator for branch, but it made weird result that only drawing &quot;x axes&quot;.&#xD;&#xA;&#xD;&#xA;However, when I changed the operator to if, it works well. The code drew x, y axes and all grids as I wanted.&#xD;&#xA;&#xD;&#xA;So I wonder is there different between if and ternary operation in GLSL?&#xD;&#xA;If that, how can I choose correctly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30138" PostHistoryTypeId="1" PostId="10378" RevisionGUID="babd6ba1-2c04-4a86-a5a0-b81b89ec6c84" CreationDate="2020-11-08T13:51:35.277" UserId="15196" Text="Is there different between 'if' and 'ternary operator' in GLSL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30139" PostHistoryTypeId="3" PostId="10378" RevisionGUID="babd6ba1-2c04-4a86-a5a0-b81b89ec6c84" CreationDate="2020-11-08T13:51:35.277" UserId="15196" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30140" PostHistoryTypeId="2" PostId="10379" RevisionGUID="c8aba32f-b427-4f45-ab81-397d00ddf32d" CreationDate="2020-11-08T15:00:21.450" UserId="2654" Text="The difference is obvious. The ternary operator *will* return one of the two alternative values it is given; that's what it is for. An `if` condition that doesn't have an `else` block won't do anything if the condition is false.&#xD;&#xA;&#xD;&#xA;The ternary operator version *will set* `color` to `axesColor` or `background`. But by that point in your code, you've gone past 3 other conditions that may have changed the value of `color` from its initial value of `background`. But the ternary operator doesn't care. It will *overwrite* whatever is in `color` with either `axesColor` or `background`.&#xD;&#xA;&#xD;&#xA;What you probably wanted was `color = abs(coord.y) &lt; 0.005 ? axesColor : color;`, so that the value will be preserved if the condition is false." ContentLicense="CC BY-SA 4.0" />
  <row Id="30149" PostHistoryTypeId="52" PostId="10378" RevisionGUID="43330405-595d-4d12-b0fd-3df6cf182e8f" CreationDate="2020-11-08T21:54:18.603" />
  <row Id="30151" PostHistoryTypeId="2" PostId="10382" RevisionGUID="19bbfc66-2735-4716-8031-aea2e9012168" CreationDate="2020-11-09T17:16:41.163" UserId="14003" Text="I have been working on recreating some of the scenes from Peter Shirley's raytracing books using compute shaders and the new Metal raytracing API.  It is going well but I am having some trouble with the glass material.&#xD;&#xA;&#xD;&#xA;I've read Pete's blog post on this - http://psgraphics.blogspot.com/2020/04/deugging-refraction-in-sphre.html &#xD;&#xA;&#xD;&#xA;But I am still unsure as to what is the cause of the issue that you can see in the pictures I have attached.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The glass appears grainy and you get an effect similar to z-fighting when you move the camera around.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is the code for the glass material:&#xD;&#xA;&#xD;&#xA;    else if (instances.materials[instanceIndex] == glass)&#xD;&#xA;    {&#xD;&#xA;        bool front_face = dot(normalize(ray.direction), worldSpaceSurfaceNormal) &lt; 0.0 ? true : false;&#xD;&#xA;                &#xD;&#xA;        float kEtaRatio = front_face ? kEtaAir / kEtaGlass&#xD;&#xA;                                     : kEtaGlass / kEtaAir;&#xD;&#xA;              &#xD;&#xA;        ray.origin = worldSpaceIntersectionPoint;&#xD;&#xA;        ray.direction = refract(normalize(ray.direction), worldSpaceSurfaceNormal, kEtaRatio);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have implemented all the code for the full material with Schlick approximation etc, however it appears that it is this first step shown here that is causing the issue.&#xD;&#xA;&#xD;&#xA;I am only using one sample per pixel at the moment but I'm unsure why that would only cause problems with the glass and not the other materials?&#xD;&#xA;&#xD;&#xA;Any advice would be greatly appreciated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/y1H8E.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/K7cVN.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/syI0w.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30152" PostHistoryTypeId="1" PostId="10382" RevisionGUID="19bbfc66-2735-4716-8031-aea2e9012168" CreationDate="2020-11-09T17:16:41.163" UserId="14003" Text="Debugging refraction in a sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="30153" PostHistoryTypeId="3" PostId="10382" RevisionGUID="19bbfc66-2735-4716-8031-aea2e9012168" CreationDate="2020-11-09T17:16:41.163" UserId="14003" Text="|raytracing|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30154" PostHistoryTypeId="50" PostId="9354" RevisionGUID="970cdfdb-9c99-4c16-96d9-a08db43d04d3" CreationDate="2020-11-09T23:04:25.410" UserId="-1" />
  <row Id="30158" PostHistoryTypeId="5" PostId="10376" RevisionGUID="4117f010-1a27-4f26-9afc-eede817a6b27" CreationDate="2020-11-10T19:09:35.943" UserId="48" Comment="add definitions of density field and gradient" Text="For culling faraway particles: as lightxbulb said, the keyword to search for is &quot;acceleration structure&quot;. There are a variety of options: BVH, octree, kd-tree, uniform grid, or some combination of these. Which one will be most suitable is going to depend on the details of your situation—how large/dense is the simulation, how much you care about performance vs memory vs implementation complexity, and so on.&#xD;&#xA;&#xD;&#xA;They all work by subdividing space into volumes in some fashion and keeping track of which particles are in each volume. Then, when you're marching you only need to keep track of which volume you're in, and that will tell you which particles can potentially contribute to the density at that point. For instance if it's a uniform grid, you only need to look at the current cell and possibly some of its immediate neighbors if they're within the maximum particle radius of your current point.&#xD;&#xA;&#xD;&#xA;Getting a smoothed mesh with surface normals etc. is usually done by defining a density field for the particle system. This is a function on 3D space that consists of summing up a falloff function for each particle over a defined radius:&#xD;&#xA;$$&#xD;&#xA;D(\vec r) = \sum_{i \in \text{particles}} f \left(\frac{|\vec r - \vec r_i|}{R_i} \right)&#xD;&#xA;$$&#xD;&#xA;where $f(u)$ is some function that falls off smoothly from $f(0) = 1$ to $f(1) = 0$ (for example, a simple cubic falloff: $f(u) = 1 - 3u^2 + 2u^3$), and $\vec r_i, R_i$ are the position and radius of the $i$th particle. Then you set some threshold density value and let the surface be defined by all the points where $D(\vec r) = \text{threshold}$.&#xD;&#xA;&#xD;&#xA;For getting the surface normal: the surface normal is just the (normalized) gradient vector of the density field. This can be calculated by finite differences between nearby points in the field:&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\nabla D(\vec r) &amp;= \left( \frac{\partial D}{\partial x}, \frac{\partial D}{\partial y}, \frac{\partial D}{\partial z} \right) \\&#xD;&#xA;&amp;\approx \left( D(\vec r + \epsilon \vec x) - D(\vec r), D(\vec r + \epsilon \vec y) - D(\vec r), D(\vec r + \epsilon \vec z) - D(\vec r) \right)&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;or analytically by adding up gradient contributions from each particle.&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\nabla D(\vec r) &amp;= \sum_i \nabla \left( f \left(\frac{|\vec r - \vec r_i|}{R_i} \right) \right) \\&#xD;&#xA;&amp;= \sum_i \text{normalize}(\vec r - \vec r_i) \frac{1}{R_i} \frac{df}{du}&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;For getting the surface in the form of a mesh: the keyword to search for is &quot;isosurface extraction&quot;. Marching cubes is one example of such an algorithm, as lightxbulb mentioned. It evaluates the density field at evenly spaced grid points, uses those values to estimate where the intersection of the surface with the cubes' edges will be, and constructs from that a tiny mesh within each cube. Stitching all those meshes together yields a representation of the full surface. Naturally, the accuracy of it depends on the size of the grid used.&#xD;&#xA;&#xD;&#xA;There is also a variant that uses tetahedra instead of cubes, and another similar algorithm called &quot;dual contouring&quot;. [Here's a nice article](https://wordsandbuttons.online/interactive_explanation_of_marching_cubes_and_dual_contouring.html) showing how these work interactively (in 2D). There's also a great deal of literature on how to improve accuracy, performance, etc. with these kinds of methods." ContentLicense="CC BY-SA 4.0" />
  <row Id="30159" PostHistoryTypeId="2" PostId="10384" RevisionGUID="de8d50ef-f368-402c-bcbd-c4f7f8ae9ee8" CreationDate="2020-11-10T19:13:09.650" UserId="10178" Text="I have a CT scan of a portion of a human body, with each point describing density. The data file provides X, Y, Z, and density values.  I want to know how to visualize this data, using OpenGL or a library based on OpenGL." ContentLicense="CC BY-SA 4.0" />
  <row Id="30160" PostHistoryTypeId="1" PostId="10384" RevisionGUID="de8d50ef-f368-402c-bcbd-c4f7f8ae9ee8" CreationDate="2020-11-10T19:13:09.650" UserId="10178" Text="How to visualize density data as volume using OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30161" PostHistoryTypeId="3" PostId="10384" RevisionGUID="de8d50ef-f368-402c-bcbd-c4f7f8ae9ee8" CreationDate="2020-11-10T19:13:09.650" UserId="10178" Text="|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30162" PostHistoryTypeId="5" PostId="10376" RevisionGUID="05f67e34-bb6a-496d-af49-71d55692bc47" CreationDate="2020-11-10T19:22:29.533" UserId="48" Comment="added 19 characters in body" Text="For culling faraway particles: as lightxbulb said, the keyword to search for is &quot;acceleration structure&quot;. There are a variety of options: BVH, octree, kd-tree, uniform grid, or some combination of these. Which one will be most suitable is going to depend on the details of your situation—how large/dense is the simulation, how much you care about performance vs memory vs implementation complexity, and so on.&#xD;&#xA;&#xD;&#xA;They all work by subdividing space into volumes in some fashion and keeping track of which particles are in each volume. Then, when you're marching you only need to keep track of which volume you're in, and that will tell you which particles can potentially contribute to the density at that point. For instance if it's a uniform grid, you only need to look at the current cell and possibly some of its immediate neighbors if they're within the maximum particle radius of your current point.&#xD;&#xA;&#xD;&#xA;Getting a smoothed mesh with surface normals etc. is usually done by defining a density field for the particle system. This is a function on 3D space that consists of summing up a falloff function for each particle over a defined radius:&#xD;&#xA;$$&#xD;&#xA;D(\vec r) = \sum_{i \in \text{particles}} f \left(\frac{|\vec r - \vec r_i|}{R_i} \right)&#xD;&#xA;$$&#xD;&#xA;where $f(u)$ is some function that falls off smoothly from $f(0) = 1$ to $f(1) = 0$ (for example, a simple cubic falloff: $f(u) = 1 - 3u^2 + 2u^3$), and $\vec r_i, R_i$ are the position and radius of the $i$th particle. Then you set some threshold density value and let the surface be defined by all the points where $D(\vec r) = \text{threshold}$.&#xD;&#xA;&#xD;&#xA;For getting the surface normal: the surface normal is just the (normalized) gradient vector of the density field. This can be calculated by finite differences between nearby points in the field:&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\nabla D(\vec r) &amp;= \left( \frac{\partial D}{\partial x}, \frac{\partial D}{\partial y}, \frac{\partial D}{\partial z} \right) \\&#xD;&#xA;&amp;\approx \frac{1}{\epsilon} \left( D(\vec r + \epsilon \vec x) - D(\vec r), D(\vec r + \epsilon \vec y) - D(\vec r), D(\vec r + \epsilon \vec z) - D(\vec r) \right)&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;or analytically by adding up gradient contributions from each particle.&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\nabla D(\vec r) &amp;= \sum_i \nabla \left( f \left(\frac{|\vec r - \vec r_i|}{R_i} \right) \right) \\&#xD;&#xA;&amp;= \sum_i \text{normalize}(\vec r - \vec r_i) \frac{1}{R_i} \frac{df}{du}&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;For getting the surface in the form of a mesh: the keyword to search for is &quot;isosurface extraction&quot;. Marching cubes is one example of such an algorithm, as lightxbulb mentioned. It evaluates the density field at evenly spaced grid points, uses those values to estimate where the intersection of the surface with the cubes' edges will be, and constructs from that a tiny mesh within each cube. Stitching all those meshes together yields a representation of the full surface. Naturally, the accuracy of it depends on the size of the grid used.&#xD;&#xA;&#xD;&#xA;There is also a variant that uses tetahedra instead of cubes, and another similar algorithm called &quot;dual contouring&quot;. [Here's a nice article](https://wordsandbuttons.online/interactive_explanation_of_marching_cubes_and_dual_contouring.html) showing how these work interactively (in 2D). There's also a great deal of literature on how to improve accuracy, performance, etc. with these kinds of methods." ContentLicense="CC BY-SA 4.0" />
  <row Id="30163" PostHistoryTypeId="2" PostId="10385" RevisionGUID="a7658a5e-5c2d-48b9-b0d1-b3a636dfc6f4" CreationDate="2020-11-10T20:01:33.613" UserId="10615" Text="What you're looking for is &quot;volumetric rendering&quot;, here is one resource with code that takes data in the form of images of the layers:&#xD;&#xA;&#xD;&#xA;[Getting started with Volume Rendering using OpenGL][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/articles/352270/getting-started-with-volume-rendering&#xD;&#xA;  [2]: https://github.com/jcouet/VolumeRendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="30164" PostHistoryTypeId="2" PostId="10386" RevisionGUID="d4055c57-5aa7-48c5-8a38-30bfee15ed44" CreationDate="2020-11-10T20:18:43.787" UserId="10615" Text="You need to make use of a discriminant, also when dealing with floating point comparisons it is wise to use an epsilon (small value for accommodating fp-error).&#xD;&#xA;&#xD;&#xA;Also keep in mind that it matters whether the surface normal is pointing along the ray, or against it.&#xD;&#xA;&#xD;&#xA;Below is a function which I use in my own raytracer, also based on the same book. It is written in C and refracts a given vector3. You would assign the return value to your `ray.direction` in your case.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// vector*vector means dot product here&#xD;&#xA;&#xD;&#xA;#define EPSILON = 0.000001f&#xD;&#xA;&#xD;&#xA;static inline vec3 refract(&#xD;&#xA;	vec3 dir, // direction of incoming light ray&#xD;&#xA;	vec3 n, // surface normal of refracting surface, pointing outwards (so roughly in the against the direction of light ray)&#xD;&#xA;	float ni_over_nt // refractive indices fraction&#xD;&#xA;){&#xD;&#xA;	float dt = dir*n; // dot prod.&#xD;&#xA;	float discriminant = 1.f - ni_over_nt*ni_over_nt*(1.f-dt*dt);&#xD;&#xA;	if (discriminant &gt; EPSILON){&#xD;&#xA;		return (dir - n*dt)*ni_over_nt - n*sqrtf(discriminant);&#xD;&#xA;	} else {&#xD;&#xA;		return (vec3){0,0,0};&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/// USAGE:&#xD;&#xA;&#xD;&#xA;if (direction*normal) &gt; EPSILON) // dot prod. of ray dir. and surf. normal&#xD;&#xA;{&#xD;&#xA;	// ray is entering the object&#xD;&#xA;	nOut = -normal; &#xD;&#xA;	ni_over_nt = mat-&gt;IOR; // surface material index of refraction.&#xD;&#xA;} else {&#xD;&#xA;	// ray is exiting the object&#xD;&#xA;	nOut = normal;&#xD;&#xA;	ni_over_nt = 1.f/mat-&gt;IOR;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 refracted = refract(direction, nOut, ni_over_nt);&#xD;&#xA;// this is your refracted ray direction" ContentLicense="CC BY-SA 4.0" />
  <row Id="30165" PostHistoryTypeId="5" PostId="10386" RevisionGUID="0afc0e06-5b27-4959-b583-5cec25ef9d50" CreationDate="2020-11-10T20:26:06.987" UserId="10615" Comment="total internal reflection" Text="You need to make use of a discriminant, also when dealing with floating point comparisons it is wise to use an epsilon (small value for accommodating fp-error).&#xD;&#xA;&#xD;&#xA;Also keep in mind that it matters whether the surface normal is pointing along the ray, or against it.&#xD;&#xA;&#xD;&#xA;Below is a function which I use in my own raytracer, also based on the same book. It is written in C and refracts a given vector3. You would assign the return value to your `ray.direction` in your case.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// vector*vector means dot product here&#xD;&#xA;&#xD;&#xA;#define EPSILON = 0.000001f&#xD;&#xA;&#xD;&#xA;static inline vec3 refract(&#xD;&#xA;	vec3 dir, // direction of incoming light ray&#xD;&#xA;	vec3 n, // surface normal of refracting surface, pointing outwards (so roughly in the against the direction of light ray)&#xD;&#xA;	float ni_over_nt // refractive indices fraction&#xD;&#xA;){&#xD;&#xA;	float dt = dir*n; // dot prod.&#xD;&#xA;	float discriminant = 1.f - ni_over_nt*ni_over_nt*(1.f-dt*dt);&#xD;&#xA;	if (discriminant &gt; EPSILON){&#xD;&#xA;		return (dir - n*dt)*ni_over_nt - n*sqrtf(discriminant);&#xD;&#xA;	} else {&#xD;&#xA;		// total internal reflection&#xD;&#xA;		// reflect the direction against the surface normal&#xD;&#xA;		return reflect(direction, normal);&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;Usage of the function is as follows:&#xD;&#xA;```&#xD;&#xA;if (direction*normal) &gt; EPSILON) // dot prod. of ray dir. and surf. normal&#xD;&#xA;{&#xD;&#xA;	// ray is entering the object&#xD;&#xA;	nOut = -normal; &#xD;&#xA;	ni_over_nt = mat-&gt;IOR; // surface material index of refraction.&#xD;&#xA;} else {&#xD;&#xA;	// ray is exiting the object&#xD;&#xA;	nOut = normal;&#xD;&#xA;	ni_over_nt = 1.f/mat-&gt;IOR;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 refracted = refract(direction, nOut, ni_over_nt);&#xD;&#xA;// this is your refracted ray direction&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30166" PostHistoryTypeId="5" PostId="10386" RevisionGUID="bf7d57c3-0e9f-49fb-8da4-79acba1592e7" CreationDate="2020-11-10T20:35:13.820" UserId="10615" Comment="reflect3, code" Text="You need to make use of a discriminant, also when dealing with floating point comparisons it is wise to use an epsilon (small value for accommodating fp-error).&#xD;&#xA;&#xD;&#xA;Also keep in mind that it matters whether the surface normal is pointing along the ray, or against it.&#xD;&#xA;&#xD;&#xA;Below is a function which I use in my own raytracer, also based on the same book. It is written in C and refracts a given vector3. You would assign the return value to your `ray.direction` in your case.&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;// vector*vector means dot product here&#xD;&#xA;&#xD;&#xA;#define EPSILON = 0.000001f&#xD;&#xA;&#xD;&#xA;static inline vec3 refract(&#xD;&#xA;	vec3 dir, // direction of incoming light ray&#xD;&#xA;	vec3 n, // surface normal of refracting surface, pointing outwards (so roughly in the against the direction of light ray)&#xD;&#xA;	float ni_over_nt // refractive indices fraction&#xD;&#xA;){&#xD;&#xA;	float dt = dir*n; // dot prod.&#xD;&#xA;	float discriminant = 1.f - ni_over_nt*ni_over_nt*(1.f-dt*dt);&#xD;&#xA;	if (discriminant &gt; EPSILON){&#xD;&#xA;		return (dir - n*dt)*ni_over_nt - n*sqrtf(discriminant);&#xD;&#xA;	} else {&#xD;&#xA;		// total internal reflection&#xD;&#xA;		// reflect the direction against the surface normal&#xD;&#xA;		return reflect(direction, normal);&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Usage of the function is as follows:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;if (direction*normal) &gt; EPSILON) // dot prod. of ray dir. and surf. normal&#xD;&#xA;{&#xD;&#xA;	// ray is entering the object&#xD;&#xA;	nOut = -normal; &#xD;&#xA;	ni_over_nt = mat-&gt;IOR; // surface material index of refraction.&#xD;&#xA;} else {&#xD;&#xA;	// ray is exiting the object&#xD;&#xA;	nOut = normal;&#xD;&#xA;	ni_over_nt = 1.f/mat-&gt;IOR;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 refracted = refract(direction, nOut, ni_over_nt);&#xD;&#xA;// this is your refracted ray direction&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Added bonus: reflection function used in the refraction:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;static inline vec3 reflect3(vec3 v, vec3 n){&#xD;&#xA;	// reflect a vector v off of a plane with normal n&#xD;&#xA;	return  v -n*2*(v*n); //v*n = dot prod.&#xD;&#xA;}" ContentLicense="CC BY-SA 4.0" />
  <row Id="30167" PostHistoryTypeId="2" PostId="10387" RevisionGUID="93d5e58a-21e2-491a-86df-368f92b13d10" CreationDate="2020-11-11T01:04:52.393" UserId="15206" Text="Using deep learning to estimate surface normals from monocular RGB images is a common task. The resulting image generally looks like this:&#xD;&#xA;&#xD;&#xA;![RBG to surface normal map][1]&#xD;&#xA;&#xD;&#xA;My question is how can I use this map to actually draw a normal vector (arrow) for any given point on the image? For example, I want to draw a line on the countertop that points up. &#xD;&#xA;&#xD;&#xA;Most relevant tidbit I found on the topic: &quot;The RGB color channels (red, green, and blue) in a normal map correspond to the respective X, Y, and Z coordinates of surface normals.&quot; &#xD;&#xA;&#xD;&#xA;But I don't get what this means. The values are standard RGB, i.e., for each coordinate, you get three numbers in range [0, 255]. Just by how color changes between surfaces, it is clearly related to normals (obviously) but when I tried quiver plots using matlab I couldn't get reasonable results. &#xD;&#xA;&#xD;&#xA;TLDR: What is the relation between surface normal maps and actual normal vectors? How can I draw a 3d line given a point on the image which represents the normal vector perpendicular to that surface at that point?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/StN14.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30168" PostHistoryTypeId="1" PostId="10387" RevisionGUID="93d5e58a-21e2-491a-86df-368f92b13d10" CreationDate="2020-11-11T01:04:52.393" UserId="15206" Text="How to draw surface normals from surface normal maps?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30169" PostHistoryTypeId="3" PostId="10387" RevisionGUID="93d5e58a-21e2-491a-86df-368f92b13d10" CreationDate="2020-11-11T01:04:52.393" UserId="15206" Text="|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30174" PostHistoryTypeId="2" PostId="10388" RevisionGUID="977e11e4-6752-40b0-96b1-1bbe1190ff2b" CreationDate="2020-11-11T05:11:26.547" UserId="48" Text="Typically the normal vector, which has XYZ components in [−1, 1] is linearly mapped to the RGB range [0, 255]. You can retrieve the normal vector by reversing this mapping.&#xD;&#xA;&#xD;&#xA;For completeness, the encoding is:\&#xD;&#xA;$$&#xD;&#xA;r = \text{round}((0.5x + 0.5) \cdot 255) \\&#xD;&#xA;g = \text{round}((0.5y + 0.5) \cdot 255) \\&#xD;&#xA;b = \text{round}((0.5z + 0.5) \cdot 255)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Decoding is:&#xD;&#xA;$$&#xD;&#xA;x = (r/255) \cdot 2 - 1 \\&#xD;&#xA;y = (g/255) \cdot 2 - 1 \\&#xD;&#xA;z = (b/255) \cdot 2 - 1&#xD;&#xA;$$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30175" PostHistoryTypeId="50" PostId="10301" RevisionGUID="27ff9746-c32d-4aed-bf76-e6c222158fd2" CreationDate="2020-11-11T20:01:00.110" UserId="-1" />
  <row Id="30179" PostHistoryTypeId="2" PostId="10390" RevisionGUID="6630b8fb-6182-4f72-8a5f-beb9e9359711" CreationDate="2020-11-11T22:22:08.903" UserId="6172" Text="I have made a program that samples uniformly an environment map and computes the lighting using the GGX BRDF.&#xD;&#xA;&#xD;&#xA;I have made a small example that reproduces the issue I'm having. You can check it out online: [shorturl.at/oAJNW][1]&#xD;&#xA;&#xD;&#xA;The algorithm works as follows:&#xD;&#xA;&#xD;&#xA; 1. We compute `V`, the unit vector that points from the surface to the camera. `FPosition` is the position of the fragment in camera space so we can use that to compute `V`.&#xD;&#xA; 2. We will take a few sample directions `L` in uniform random directions. These samples are taken inside a hemisphere in the direction of the normal `N`.&#xD;&#xA; 3. In the real program, we would use `L` to sample the environment map but, for simplicity, in the provided example, I'm just assuming a complitely white environment (the issue happens anyways).&#xD;&#xA; 4. For each of these samples we compute the rendering equation with the GGX BRDF, and we accumulate that into a variable.&#xD;&#xA; 5. And finally we divide by the number of samples.&#xD;&#xA;&#xD;&#xA;I'm using the formulas for GGX I found in this site: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;&#xD;&#xA;The problem I'm having is that it doesn't look right. If you open the link you will see this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;That's with roughness = 0.1, metallic = 1.0, and numSamples = 10.&#xD;&#xA;&#xD;&#xA;In the top right corner, switch to the sphere. And you will see this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;You see those bright spots, the number of them correlates with the number of samples. That could make sense, maybe. But when I increment the number of samples to 100, we get this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;There are more spots but they are also smaller and blurrier. I think I must be doing something wrong because it doesn't look like a metal. Or is it just because of the uniform sampling? Even with 1000 samples per pixel it doesn't look right to me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://shorturl.at/dyNQ3&#xD;&#xA;  [2]: https://i.stack.imgur.com/czf1m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/72sZr.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3a96c.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30180" PostHistoryTypeId="1" PostId="10390" RevisionGUID="6630b8fb-6182-4f72-8a5f-beb9e9359711" CreationDate="2020-11-11T22:22:08.903" UserId="6172" Text="Problem sampling uniformly envmap with GGX" ContentLicense="CC BY-SA 4.0" />
  <row Id="30181" PostHistoryTypeId="3" PostId="10390" RevisionGUID="6630b8fb-6182-4f72-8a5f-beb9e9359711" CreationDate="2020-11-11T22:22:08.903" UserId="6172" Text="|opengl|glsl|lighting|ggx|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30182" PostHistoryTypeId="5" PostId="10390" RevisionGUID="889ca28d-02ca-426f-9dc0-2570be72c6b1" CreationDate="2020-11-11T22:29:04.727" UserId="6172" Comment="change link" Text="I have made a program that samples uniformly an environment map and computes the lighting using the GGX BRDF.&#xD;&#xA;&#xD;&#xA;I have made a small example that reproduces the issue I'm having. You can check it out online: [shorturl.at/tvzGY][1]&#xD;&#xA;&#xD;&#xA;The algorithm works as follows:&#xD;&#xA;&#xD;&#xA; 1. We compute `V`, the unit vector that points from the surface to the camera. `FPosition` is the position of the fragment in camera space so we can use that to compute `V`.&#xD;&#xA; 2. We will take a few sample directions `L` in uniform random directions. These samples are taken inside a hemisphere in the direction of the normal `N`.&#xD;&#xA; 3. In the real program, we would use `L` to sample the environment map but, for simplicity, in the provided example, I'm just assuming a complitely white environment (the issue happens anyways).&#xD;&#xA; 4. For each of these samples we compute the rendering equation with the GGX BRDF, and we accumulate that into a variable.&#xD;&#xA; 5. And finally we divide by the number of samples.&#xD;&#xA;&#xD;&#xA;I'm using the formulas for GGX I found in this site: http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;&#xD;&#xA;The problem I'm having is that it doesn't look right. If you open the link you will see this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;That's with roughness = 0.1, metallic = 1.0, and numSamples = 10.&#xD;&#xA;&#xD;&#xA;In the top right corner, switch to the sphere. And you will see this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;You see those bright spots, the number of them correlates with the number of samples. That could make sense, maybe. But when I increment the number of samples to 100, we get this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;There are more spots but they are also smaller and blurrier. I think I must be doing something wrong because it doesn't look like a metal. Or is it just because of the uniform sampling? Even with 1000 samples per pixel it doesn't look right to me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://shorturl.at/tvzGY&#xD;&#xA;  [2]: https://i.stack.imgur.com/czf1m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/72sZr.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3a96c.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30183" PostHistoryTypeId="2" PostId="10391" RevisionGUID="6b81cea7-53e9-4708-b2eb-41d8f31d2e39" CreationDate="2020-11-11T23:03:58.377" UserId="9779" Text="I'm decoding an `.mp4` to use as a texture on a tristrip. It's easy enough to use an unsigned byte array of RGB triplets to create this texture, but frames come out of an `.mp4` as three separate buffers. One for each channel. In other words, instead of having `uint8_t * buf = {RGBRGBRGBRGB.....}`, I have `uint8_t * r_buf = {RRRRR....}; uint8_t * g_buf = {GGGGG....}; uint8_t * b_buf = {BBBBBB....};` Can I pack all of this into one texture so my fragment shader just treats it the same as it did the current texture? I don't have any great objection to having three separate 1-channel textures that I mix in the shader, but that'll ugly up my shader code a bit." ContentLicense="CC BY-SA 4.0" />
  <row Id="30184" PostHistoryTypeId="1" PostId="10391" RevisionGUID="6b81cea7-53e9-4708-b2eb-41d8f31d2e39" CreationDate="2020-11-11T23:03:58.377" UserId="9779" Text="Packing a GL_RGB from three separate buffers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30185" PostHistoryTypeId="3" PostId="10391" RevisionGUID="6b81cea7-53e9-4708-b2eb-41d8f31d2e39" CreationDate="2020-11-11T23:03:58.377" UserId="9779" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30186" PostHistoryTypeId="2" PostId="10392" RevisionGUID="570d1804-f796-4d35-915c-01894ffe8ac3" CreationDate="2020-11-11T23:10:13.870" UserId="48" Text="How are you randomizing the samples you take? It looks to me like maybe the random values are the same across all pixels in the image, which would explain why you see 10 coherent bright spots when you have 10 samples.&#xD;&#xA;&#xD;&#xA;The samples should be re-randomized for each pixel. This should produce a noisy result, with a single blurred-out bright spot instead of 10 (or however many) coherent bright spots." ContentLicense="CC BY-SA 4.0" />
  <row Id="30187" PostHistoryTypeId="5" PostId="10385" RevisionGUID="daf60a69-14f2-49b9-bd7e-0844913eac03" CreationDate="2020-11-12T00:06:24.287" UserId="10615" Comment="added 60 characters in body" Text="What you're looking for is &quot;volumetric rendering&quot;, here is one resource with code that takes data in the form of images of the layers:&#xD;&#xA;&#xD;&#xA;[Getting started with Volume Rendering using OpenGL][1]&#xD;&#xA;&#xD;&#xA;A quick hack would be to use a grid of particles/&quot;billboards&quot;, and make them transparent based on the density.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/articles/352270/getting-started-with-volume-rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="30192" PostHistoryTypeId="6" PostId="1769" RevisionGUID="cd7787c6-654b-499d-99ae-d2c28eb2adc7" CreationDate="2020-11-13T18:04:46.110" UserId="8434" Comment="Tag added (3d)" Text="|3d|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30193" PostHistoryTypeId="24" PostId="1769" RevisionGUID="cd7787c6-654b-499d-99ae-d2c28eb2adc7" CreationDate="2020-11-13T18:04:46.110" Comment="Proposed by 8434 approved by 13095 edit id of 546" ContentLicense="CC BY-SA 4.0" />
  <row Id="30194" PostHistoryTypeId="2" PostId="10394" RevisionGUID="db1bf1e9-3aa6-4d81-bcc0-af2c681069c6" CreationDate="2020-11-13T19:43:26.313" UserId="4958" Text="I have a ```rgba16f``` texture that I fill with values using nvidia ```GL_NV_shader_atomic_fp16_vector``` extension, which allows to perform ```imageAtomicAdd``` on half float RGBA images, with multiple shader threads using same ```index```. However, it doesn't support ```rgba32f```.&#xD;&#xA;&#xD;&#xA;Can I use ```imageLoad```/```imageStore``` to perform same thing with such image buffer as written below?&#xD;&#xA;```&#xD;&#xA;vec4 prevVal = imageLoad(tex, index);&#xD;&#xA;prevVal += currVal;&#xD;&#xA;imageStore(tex, index, prevVal);&#xD;&#xA;```&#xD;&#xA;I'm not sure how correctly set the coherency of such operations with correct barriers usage because I have not found any example. Or if it is even possible.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30195" PostHistoryTypeId="1" PostId="10394" RevisionGUID="db1bf1e9-3aa6-4d81-bcc0-af2c681069c6" CreationDate="2020-11-13T19:43:26.313" UserId="4958" Text="Using imageLoad/imageStore to read modify write" ContentLicense="CC BY-SA 4.0" />
  <row Id="30196" PostHistoryTypeId="3" PostId="10394" RevisionGUID="db1bf1e9-3aa6-4d81-bcc0-af2c681069c6" CreationDate="2020-11-13T19:43:26.313" UserId="4958" Text="|opengl|glsl|compute-shader|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30197" PostHistoryTypeId="4" PostId="10394" RevisionGUID="0ec9e80c-fe4b-473a-9d1a-dcecdbe880a8" CreationDate="2020-11-13T19:52:12.087" UserId="4958" Comment="edited title" Text="Using imageLoad/imageStore to perform atomic add" ContentLicense="CC BY-SA 4.0" />
  <row Id="30198" PostHistoryTypeId="2" PostId="10395" RevisionGUID="7978d628-08a3-4461-bf92-691c18884c6c" CreationDate="2020-11-13T22:24:25.237" UserId="2654" Text="If you could use `imageLoad/Store` to do atomic operations, there would be no need for atomic operations as a distinct class of operations. So no, you can't. There is no correct set of barriers or other properties that will allow this to work generally the way atomic operations do." ContentLicense="CC BY-SA 4.0" />
  <row Id="30221" PostHistoryTypeId="50" PostId="9549" RevisionGUID="ad131d87-a6a5-4049-853d-f9b73e2d3509" CreationDate="2020-11-14T11:01:10.130" UserId="-1" />
  <row Id="30222" PostHistoryTypeId="2" PostId="10396" RevisionGUID="a8612a1f-5ddf-495a-b350-e61a6f39cda4" CreationDate="2020-11-14T17:58:59.407" UserId="6496" Text="While studying [Peter Shirley's Ray Tracing:The Next Week][1], I came across an issue that I cannot quite figure out:&#xD;&#xA;&#xD;&#xA;Stepping through the `random_scene()` case of the code, found out that once a leaf of the BVH tree is reached, the aabb of the object is checked for a hit; even when the object is a sphere. &#xD;&#xA;&#xD;&#xA;The check for a hit against the `bounding_box` of a sphere (aabb) is necessary but not sufficient; there are parts of the `bounding_box` which is not a part of a sphere. &#xD;&#xA;&#xD;&#xA;Shouldn't it invoke the specific `hit()` function of the object when the leaf is reached?&#xD;&#xA;&#xD;&#xA;Yet the code works somehow.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/RayTracing/raytracing.github.io" ContentLicense="CC BY-SA 4.0" />
  <row Id="30223" PostHistoryTypeId="1" PostId="10396" RevisionGUID="a8612a1f-5ddf-495a-b350-e61a6f39cda4" CreationDate="2020-11-14T17:58:59.407" UserId="6496" Text="BVH uses aabb for a sphere in Ray Tracing: The Next Week" ContentLicense="CC BY-SA 4.0" />
  <row Id="30224" PostHistoryTypeId="3" PostId="10396" RevisionGUID="a8612a1f-5ddf-495a-b350-e61a6f39cda4" CreationDate="2020-11-14T17:58:59.407" UserId="6496" Text="|raytracing|debugging|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30234" PostHistoryTypeId="2" PostId="10399" RevisionGUID="2361c0a7-e983-4838-a31f-64ee9532fe8b" CreationDate="2020-11-15T00:29:57.883" UserId="11224" Text="I used a version of the following code to draw a triangle using glDrawArrays with GL_TRIANGLE, per Anton Gerdelan's very nice tutorial here:&#xD;&#xA;&#xD;&#xA;[Hello Triangle !][1]&#xD;&#xA;&#xD;&#xA;It draws a nice triangle.&#xD;&#xA;&#xD;&#xA;I have modified the code as explained in the code comments below, attempting to use glDrawArrays with GL_TRIANGLE to draw two triangles, making a square, as suggested in the section &quot;Experimenting&quot; on the webpage, but it still just gives the same triangle, even though I added 3 more vertices to the triangle_vertices array, doubled the size of the data in the glBufferData command, and replaced glDrawArrays(GL_TRIANGLES, 0, 3) by glDrawArrays(GL_TRIANGLES, 0, 6).&#xD;&#xA;&#xD;&#xA;Why is that ?&#xD;&#xA;&#xD;&#xA;By using GL_TRIANGLE_FAN I have succeeded in drawing the square I want (actually a rectangle because of the aspect ratio), but I would like to be able to get the same result using GL_TRIANGLE. I also don't want to use any alternative to glDrawArrays, even though I know that options are available that allow clever re-use of vertex data, when distinct triangles share common vertices.&#xD;&#xA;&#xD;&#xA;    #define GLEW_STATIC&#xD;&#xA;    #include &quot;GL/glew.h&quot;&#xD;&#xA;    #define GLFW_DLL&#xD;&#xA;    #include &quot;GLFW/glfw3.h&quot;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        printf(&quot;Hello world !\n&quot;);&#xD;&#xA;    &#xD;&#xA;        GLFWwindow* window;&#xD;&#xA;    &#xD;&#xA;        /* Initialize the library */&#xD;&#xA;        if (!glfwInit())&#xD;&#xA;        {&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        /* Create a windowed mode window and its OpenGL context */&#xD;&#xA;        window = glfwCreateWindow(2048, 1536, &quot;Hello !&quot;, NULL, NULL);&#xD;&#xA;        if (!window)&#xD;&#xA;        {&#xD;&#xA;            glfwTerminate();&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        /* Make the window's context current */&#xD;&#xA;        glewExperimental = GL_TRUE;&#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;        GLenum ret = glewInit();&#xD;&#xA;        if (GLEW_OK != ret)&#xD;&#xA;        {&#xD;&#xA;            // Problem: glewInit failed, something is seriously wrong.&#xD;&#xA;            fprintf(stderr, &quot;Error: %s\n&quot;, glewGetErrorString(ret));&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // One triangle:&#xD;&#xA;        //float triangle_vertices[] = {&#xD;&#xA;        //-0.5f, 0.5f, 0.0f, // top left point&#xD;&#xA;        //0.5f, 0.5f, 0.0f, // top right point&#xD;&#xA;        //0.5f, -0.5f, 0.0f, // bottom right point&#xD;&#xA;        //};&#xD;&#xA;&#xD;&#xA;        // Two triangles:&#xD;&#xA;        float triangle_vertices[] = {&#xD;&#xA;        -0.5f, 0.5f, 0.0f, // top left point&#xD;&#xA;        0.5f, 0.5f, 0.0f, // top right point&#xD;&#xA;        0.5f, -0.5f, 0.0f, // bottom right point&#xD;&#xA;        0.5f, -0.5f, 0.0f, // bottom right point&#xD;&#xA;        -0.5f, -0.5f, 0.0f // bottom left point&#xD;&#xA;        -0.5f, 0.5f, 0.0f, // top left point&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        GLuint vertex_buffer_object = 0; // VBO&#xD;&#xA;        glGenBuffers(1, &amp;vertex_buffer_object);&#xD;&#xA;        {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);&#xD;&#xA;    &#xD;&#xA;            //glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 3, triangle_vertices, GL_STATIC_DRAW);&#xD;&#xA;            // The previous command was for drawing a triangle, while the following one is intended for &#xD;&#xA;            // drawing a square, although it doesn't yet work !&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 6, triangle_vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        GLuint vertex_array_object = 0;&#xD;&#xA;        glGenVertexArrays(1, &amp;vertex_array_object);&#xD;&#xA;        {&#xD;&#xA;            glBindVertexArray(vertex_array_object);&#xD;&#xA;    &#xD;&#xA;            glEnableVertexAttribArray(0); // enable the first input variable (vertex position)&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);&#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;            glBindVertexArray(0);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;  &#xD;&#xA;        GLuint shader_program_object = 0;&#xD;&#xA;        { // SHADERS&#xD;&#xA;    &#xD;&#xA;            const char* vertex_shader_str =&#xD;&#xA;                &quot;#version 410\n&quot;&#xD;&#xA;                &quot;in vec3 a_position;\n&quot;&#xD;&#xA;                &quot;void main() {\n&quot;&#xD;&#xA;                &quot;gl_Position = vec4(a_position, 1.0);\n&quot;&#xD;&#xA;                &quot;}&quot;;&#xD;&#xA;    &#xD;&#xA;            const char* fragment_shader_str =&#xD;&#xA;                &quot;#version 410\n&quot;&#xD;&#xA;                &quot;out vec4 o_frag_colour;\n&quot;&#xD;&#xA;                &quot;void main() {\n&quot;&#xD;&#xA;                &quot;o_frag_colour = vec4(0.5, 0.0, 0.5, 1.0);\n&quot;&#xD;&#xA;                &quot;}\n&quot;;&#xD;&#xA;    &#xD;&#xA;            GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;            glShaderSource(vertex_shader_object, 1, &amp;vertex_shader_str, NULL);&#xD;&#xA;            glCompileShader(vertex_shader_object);&#xD;&#xA;    &#xD;&#xA;            GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;            glShaderSource(fragment_shader_object, 1, &amp;fragment_shader_str, NULL);&#xD;&#xA;            glCompileShader(fragment_shader_object);&#xD;&#xA;    &#xD;&#xA;            shader_program_object = glCreateProgram();&#xD;&#xA;            glBindAttribLocation(shader_program_object, 0, &quot;a_position&quot;);&#xD;&#xA;    &#xD;&#xA;            glAttachShader(shader_program_object, vertex_shader_object);&#xD;&#xA;            glAttachShader(shader_program_object, fragment_shader_object);&#xD;&#xA;            glLinkProgram(shader_program_object);&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);&#xD;&#xA;    &#xD;&#xA;        while (!glfwWindowShouldClose(window))&#xD;&#xA;        {&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;            glUseProgram(shader_program_object);&#xD;&#xA;            {&#xD;&#xA;                glBindVertexArray(vertex_array_object);&#xD;&#xA;                {&#xD;&#xA;                    //glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;                    glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;                }&#xD;&#xA;                glBindVertexArray(0);&#xD;&#xA;            }&#xD;&#xA;            glUseProgram(0);&#xD;&#xA;    &#xD;&#xA;            glfwPollEvents();&#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://antongerdelan.net/opengl/hellotriangle.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30235" PostHistoryTypeId="1" PostId="10399" RevisionGUID="2361c0a7-e983-4838-a31f-64ee9532fe8b" CreationDate="2020-11-15T00:29:57.883" UserId="11224" Text="Drawing a square using glDrawArrays with GL_TRIANGLE" ContentLicense="CC BY-SA 4.0" />
  <row Id="30236" PostHistoryTypeId="3" PostId="10399" RevisionGUID="2361c0a7-e983-4838-a31f-64ee9532fe8b" CreationDate="2020-11-15T00:29:57.883" UserId="11224" Text="|opengl|c++|polygon|drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30240" PostHistoryTypeId="5" PostId="10399" RevisionGUID="a9dc021d-7795-49cc-aaf5-41988d694c52" CreationDate="2020-11-15T14:17:43.623" UserId="11224" Comment="Fixed several typos where I'd written GL_TRIANGLE instead of GL_TRIANGLES." Text="I used a version of the following code to draw a triangle using glDrawArrays with GL_TRIANGLES, per Anton Gerdelan's very nice tutorial here:&#xD;&#xA;&#xD;&#xA;[Hello Triangle !][1]&#xD;&#xA;&#xD;&#xA;It draws a nice triangle.&#xD;&#xA;&#xD;&#xA;I have modified the code as explained in the code comments below, attempting to use glDrawArrays with GL_TRIANGLES to draw two triangles, making a square, as suggested in the section &quot;Experimenting&quot; on the webpage, but it still just gives the same triangle, even though I added 3 more vertices to the triangle_vertices array, doubled the size of the data in the glBufferData command, and replaced glDrawArrays(GL_TRIANGLES, 0, 3) by glDrawArrays(GL_TRIANGLES, 0, 6).&#xD;&#xA;&#xD;&#xA;Why is that ?&#xD;&#xA;&#xD;&#xA;By using GL_TRIANGLE_FAN I have succeeded in drawing the square I want (actually a rectangle because of the aspect ratio), but I would like to be able to get the same result using GL_TRIANGLES. I also don't want to use any alternative to glDrawArrays, even though I know that options are available that allow clever re-use of vertex data, when distinct triangles share common vertices.&#xD;&#xA;&#xD;&#xA;    #define GLEW_STATIC&#xD;&#xA;    #include &quot;GL/glew.h&quot;&#xD;&#xA;    #define GLFW_DLL&#xD;&#xA;    #include &quot;GLFW/glfw3.h&quot;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        printf(&quot;Hello world !\n&quot;);&#xD;&#xA;    &#xD;&#xA;        GLFWwindow* window;&#xD;&#xA;    &#xD;&#xA;        /* Initialize the library */&#xD;&#xA;        if (!glfwInit())&#xD;&#xA;        {&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);&#xD;&#xA;        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        /* Create a windowed mode window and its OpenGL context */&#xD;&#xA;        window = glfwCreateWindow(2048, 1536, &quot;Hello !&quot;, NULL, NULL);&#xD;&#xA;        if (!window)&#xD;&#xA;        {&#xD;&#xA;            glfwTerminate();&#xD;&#xA;            return -1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        /* Make the window's context current */&#xD;&#xA;        glewExperimental = GL_TRUE;&#xD;&#xA;        glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;        GLenum ret = glewInit();&#xD;&#xA;        if (GLEW_OK != ret)&#xD;&#xA;        {&#xD;&#xA;            // Problem: glewInit failed, something is seriously wrong.&#xD;&#xA;            fprintf(stderr, &quot;Error: %s\n&quot;, glewGetErrorString(ret));&#xD;&#xA;            return 1;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // One triangle:&#xD;&#xA;        //float triangle_vertices[] = {&#xD;&#xA;        //-0.5f, 0.5f, 0.0f, // top left point&#xD;&#xA;        //0.5f, 0.5f, 0.0f, // top right point&#xD;&#xA;        //0.5f, -0.5f, 0.0f, // bottom right point&#xD;&#xA;        //};&#xD;&#xA;&#xD;&#xA;        // Two triangles:&#xD;&#xA;        float triangle_vertices[] = {&#xD;&#xA;        -0.5f, 0.5f, 0.0f, // top left point&#xD;&#xA;        0.5f, 0.5f, 0.0f, // top right point&#xD;&#xA;        0.5f, -0.5f, 0.0f, // bottom right point&#xD;&#xA;        0.5f, -0.5f, 0.0f, // bottom right point&#xD;&#xA;        -0.5f, -0.5f, 0.0f // bottom left point&#xD;&#xA;        -0.5f, 0.5f, 0.0f, // top left point&#xD;&#xA;        };&#xD;&#xA;    &#xD;&#xA;        GLuint vertex_buffer_object = 0; // VBO&#xD;&#xA;        glGenBuffers(1, &amp;vertex_buffer_object);&#xD;&#xA;        {&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);&#xD;&#xA;    &#xD;&#xA;            //glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 3, triangle_vertices, GL_STATIC_DRAW);&#xD;&#xA;            // The previous command was for drawing a triangle, while the following one is intended for &#xD;&#xA;            // drawing a square, although it doesn't yet work !&#xD;&#xA;            glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 6, triangle_vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        GLuint vertex_array_object = 0;&#xD;&#xA;        glGenVertexArrays(1, &amp;vertex_array_object);&#xD;&#xA;        {&#xD;&#xA;            glBindVertexArray(vertex_array_object);&#xD;&#xA;    &#xD;&#xA;            glEnableVertexAttribArray(0); // enable the first input variable (vertex position)&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object);&#xD;&#xA;            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);&#xD;&#xA;            glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;            glBindVertexArray(0);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;  &#xD;&#xA;        GLuint shader_program_object = 0;&#xD;&#xA;        { // SHADERS&#xD;&#xA;    &#xD;&#xA;            const char* vertex_shader_str =&#xD;&#xA;                &quot;#version 410\n&quot;&#xD;&#xA;                &quot;in vec3 a_position;\n&quot;&#xD;&#xA;                &quot;void main() {\n&quot;&#xD;&#xA;                &quot;gl_Position = vec4(a_position, 1.0);\n&quot;&#xD;&#xA;                &quot;}&quot;;&#xD;&#xA;    &#xD;&#xA;            const char* fragment_shader_str =&#xD;&#xA;                &quot;#version 410\n&quot;&#xD;&#xA;                &quot;out vec4 o_frag_colour;\n&quot;&#xD;&#xA;                &quot;void main() {\n&quot;&#xD;&#xA;                &quot;o_frag_colour = vec4(0.5, 0.0, 0.5, 1.0);\n&quot;&#xD;&#xA;                &quot;}\n&quot;;&#xD;&#xA;    &#xD;&#xA;            GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;            glShaderSource(vertex_shader_object, 1, &amp;vertex_shader_str, NULL);&#xD;&#xA;            glCompileShader(vertex_shader_object);&#xD;&#xA;    &#xD;&#xA;            GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;            glShaderSource(fragment_shader_object, 1, &amp;fragment_shader_str, NULL);&#xD;&#xA;            glCompileShader(fragment_shader_object);&#xD;&#xA;    &#xD;&#xA;            shader_program_object = glCreateProgram();&#xD;&#xA;            glBindAttribLocation(shader_program_object, 0, &quot;a_position&quot;);&#xD;&#xA;    &#xD;&#xA;            glAttachShader(shader_program_object, vertex_shader_object);&#xD;&#xA;            glAttachShader(shader_program_object, fragment_shader_object);&#xD;&#xA;            glLinkProgram(shader_program_object);&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);&#xD;&#xA;    &#xD;&#xA;        while (!glfwWindowShouldClose(window))&#xD;&#xA;        {&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;            glUseProgram(shader_program_object);&#xD;&#xA;            {&#xD;&#xA;                glBindVertexArray(vertex_array_object);&#xD;&#xA;                {&#xD;&#xA;                    //glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;                    glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;                }&#xD;&#xA;                glBindVertexArray(0);&#xD;&#xA;            }&#xD;&#xA;            glUseProgram(0);&#xD;&#xA;    &#xD;&#xA;            glfwPollEvents();&#xD;&#xA;            glfwSwapBuffers(window);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://antongerdelan.net/opengl/hellotriangle.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30241" PostHistoryTypeId="4" PostId="10399" RevisionGUID="a9dc021d-7795-49cc-aaf5-41988d694c52" CreationDate="2020-11-15T14:17:43.623" UserId="11224" Comment="Fixed several typos where I'd written GL_TRIANGLE instead of GL_TRIANGLES." Text="Drawing a square using glDrawArrays with GL_TRIANGLES" ContentLicense="CC BY-SA 4.0" />
  <row Id="30244" PostHistoryTypeId="50" PostId="9048" RevisionGUID="22a799cd-ca5f-41d0-bc8f-81dfe4dfc54b" CreationDate="2020-11-15T19:00:25.040" UserId="-1" />
  <row Id="30248" PostHistoryTypeId="2" PostId="10402" RevisionGUID="727dc04b-3e3b-4c37-b98e-242cf89c7349" CreationDate="2020-11-15T20:10:49.443" UserId="11224" Text="Doh !!! It was simply a typo ! A missing comma at the end of the line&#xD;&#xA;&#xD;&#xA;    -0.5f, -0.5f, 0.0f // bottom left point&#xD;&#xA;&#xD;&#xA;What a relief !" ContentLicense="CC BY-SA 4.0" />
  <row Id="30251" PostHistoryTypeId="2" PostId="10403" RevisionGUID="2f3f5321-9fee-4c80-90c6-b9fcf7a92773" CreationDate="2020-11-16T04:06:04.950" UserId="15206" Text="Excuse my wording. I will use the picture below to explain what I mean. I want to use the surface normals for each arrow shown like below to draw lines parallel to each plane like the image shown below the first one. Therefore I want to obtain point coordinates given in black dots.&#xD;&#xA;&#xD;&#xA;Assuming I have a unit normal (u, v, w) to each plane, how can this be accomplished? &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gNw3x.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4zPy7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30252" PostHistoryTypeId="1" PostId="10403" RevisionGUID="2f3f5321-9fee-4c80-90c6-b9fcf7a92773" CreationDate="2020-11-16T04:06:04.950" UserId="15206" Text="Can surface normal be used for obtaining points on a plane?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30253" PostHistoryTypeId="3" PostId="10403" RevisionGUID="2f3f5321-9fee-4c80-90c6-b9fcf7a92773" CreationDate="2020-11-16T04:06:04.950" UserId="15206" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30254" PostHistoryTypeId="2" PostId="10404" RevisionGUID="45841277-c0b7-49aa-ac9f-ad03f128b8bb" CreationDate="2020-11-16T07:00:34.733" UserId="8757" Text="I have a few short question regarding operations happening in the rendering pipeline (OpenGL, Vulkan, I'd expect for all questions to have similar answers for these two frameworks while DirectX might work a bit different). &#xD;&#xA;&#xD;&#xA;Is the division of the coordinates `x/w`,`y/w`,`z/w` the last operation that happens on the GPU? Or are there other operations that happen afterwards? I wasn't really able to find any information on that, could anyone point me into the right direction?&#xD;&#xA;&#xD;&#xA;Furthermore, concerning the depth of fragments, as far as I understand a quantization takes place to discrete units of depth, but I couldn't find anything detailed if these operations follow some kind of IEEE standard or if they have their own standards, maybe even depending on the manufacturer. Does anyone know more detail about this or could point me into the right direction?&#xD;&#xA;&#xD;&#xA;In general are there some, more or less, complete information about the possible operations (besides of course programmable operations during the programmable shader stages), the error bounds, etc. for operations on the GPU?&#xD;&#xA;&#xD;&#xA;Kind regards and thank you in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="30255" PostHistoryTypeId="1" PostId="10404" RevisionGUID="45841277-c0b7-49aa-ac9f-ad03f128b8bb" CreationDate="2020-11-16T07:00:34.733" UserId="8757" Text="Operations in the Rendering Pipeline" ContentLicense="CC BY-SA 4.0" />
  <row Id="30256" PostHistoryTypeId="3" PostId="10404" RevisionGUID="45841277-c0b7-49aa-ac9f-ad03f128b8bb" CreationDate="2020-11-16T07:00:34.733" UserId="8757" Text="|opengl|gpu|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30257" PostHistoryTypeId="2" PostId="10405" RevisionGUID="5ac9b54c-10b2-4dcf-924d-6d02755da9c7" CreationDate="2020-11-16T07:21:39.847" UserId="10642" Text="It does indeed do exactly what you described. Have a close look at how the bvh is constructed, it is a passed a list of concrete shapes that implement `hittable`, e.g. `xy_rect`, `sphere`, etc. The base cases for the recursive bvh construction create leaf nodes that directly reference the concrete shapes that make up the scene. &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;bvh_node::bvh_node(&#xD;&#xA;    const std::vector&lt;shared_ptr&lt;hittable&gt;&gt;&amp; src_objects,&#xD;&#xA;    size_t start, size_t end, double time0, double time1&#xD;&#xA;) {&#xD;&#xA;    auto objects = src_objects; // Create a modifiable array of the source scene objects&#xD;&#xA;    ...&#xD;&#xA;    size_t object_span = end - start;&#xD;&#xA;&#xD;&#xA;    // **create leaf nodes, concrete shapes referenced here**&#xD;&#xA;    if (object_span == 1) {&#xD;&#xA;        left = right = objects[start]; &#xD;&#xA;    } else if (object_span == 2) {&#xD;&#xA;        if (comparator(objects[start], objects[start+1])) {&#xD;&#xA;            left = objects[start];&#xD;&#xA;            right = objects[start+1];&#xD;&#xA;        } else {&#xD;&#xA;            left = objects[start+1];&#xD;&#xA;            right = objects[start];&#xD;&#xA;        }&#xD;&#xA;    } else {&#xD;&#xA;       // create internal bvh_node&#xD;&#xA;       ...&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When `bvh_node::hit` is called and the ray/aabb test passes, the left and right child nodes have their hit functions called recursively. Eventually when this recursion bottoms out the concrete shapes referenced by the leaf nodes will have their hit functions called as you would expect. &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;bool bvh_node::hit(const ray&amp; r, double t_min, double t_max, hit_record&amp; rec) const {&#xD;&#xA;    if (!box.hit(r, t_min, t_max))&#xD;&#xA;        return false;&#xD;&#xA;&#xD;&#xA;    bool hit_left = left-&gt;hit(r, t_min, t_max, rec);&#xD;&#xA;    bool hit_right = right-&gt;hit(r, t_min, hit_left ? rec.t : t_max, rec);&#xD;&#xA;&#xD;&#xA;    return hit_left || hit_right;&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30258" PostHistoryTypeId="2" PostId="10406" RevisionGUID="10107153-67bd-467b-b101-ba30310dd5a7" CreationDate="2020-11-16T08:53:49.303" UserId="10615" Text="I agree with [@xasp's answer][1], but to understand *why* you would do it like that:&#xD;&#xA;&#xD;&#xA;Checking for ray-circle intersections is not the most expensive in terms of cpu-time required, but a ray-aabb intersection is frighteningly faster. Apparently Shirley found that in his scenes, checking the leaf's AABB first led to better results, because in a &quot;sparse bounding volume tree&quot;, you might recurse down to a leaf node, but still not hit it.&#xD;&#xA;&#xD;&#xA;So why is the AABB faster than a sphere intersection? Well for spheres in 3d you need to square 3 numbers (will be compiled to a single vector instruction most likely) and you need to then take the square root, which is a traditionally expensive operation. See this answer: https://stackoverflow.com/a/12304868/11359454&#xD;&#xA;&#xD;&#xA;In AABB intersection you just need to do some larger/smaller than checks and divide your rays x y and z components to get the inverse (single vector divide instruction).&#xD;&#xA;&#xD;&#xA;Infamously in quake, to get faster lighting, an approximation hack was used to get a fast root-ish. Nowadays that hack is actually slower than a call to `sqrtf`, because the floating point parts of processors have gotten faster and more advanced.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/10405/10615" ContentLicense="CC BY-SA 4.0" />
  <row Id="30259" PostHistoryTypeId="2" PostId="10407" RevisionGUID="6aab1b1d-d783-4200-90fc-06ddf170d659" CreationDate="2020-11-16T10:37:57.023" UserId="10615" Text="I  think you can make a graph of the entire surface and have your algorithm &quot;walk&quot; over it. Your planes would be hugging the surface but it would be the shortest. You could fix the hugging by a local upward translation on the plane.&#xD;&#xA;&#xD;&#xA;If you have a weird maze-like structure, you might want to &quot;cross the gaps&quot;, so you need to adapt the algorithm to be able to cross air gaps, you could do this by just iterating all triangles and connecting them to all other triangles (thus creating a graph). Of course, you can't pass through the walls, so you need to take into account the surface normals. If you construct the lines between two surfaces, and you compare the surface normals to the direction of that line, it can tell you whether you are going through the surface (forbidden) or away from it (crossing air gaps). If the 2 surfaces are direct neighbors you don't need to do the line-normal check, and you can assume your algorithm can walk from one triangle to the other.&#xD;&#xA;&#xD;&#xA;Most 3d model files reuse the same vertices for multiple triangles so it's easy to check whether they are neighbors: just check if they have vertices in common.&#xD;&#xA;&#xD;&#xA;Once you have constructed the final graph, you can just use a pathfinding algorithm to find the shortest path to traverse the graph." ContentLicense="CC BY-SA 4.0" />
  <row Id="30260" PostHistoryTypeId="2" PostId="10408" RevisionGUID="22ce1e4b-072c-4a3b-bb01-afefe6302de4" CreationDate="2020-11-16T10:43:08.873" UserId="10615" Text="I think you need to call `setFromMatrixPosition(m)` again after updating the matrix. After all, you need to update both the position and matrix, not just the matrix.&#xD;&#xA;&#xD;&#xA;`mesh.position.setFromMatrixPosition(mesh.matrix)` or `mesh.position = new THREE.Vector3().setFromMatrixPosition(mesh.matrix)` right after `mesh.updateMatrix()`" ContentLicense="CC BY-SA 4.0" />
  <row Id="30261" PostHistoryTypeId="2" PostId="10409" RevisionGUID="d45bc96d-13dc-4990-a0cf-cc46f68c9695" CreationDate="2020-11-16T12:59:34.500" UserId="7952" Text="&gt; Is the division of the coordinates x/w,y/w,z/w the last operation that happens on the GPU?&#xD;&#xA;&#xD;&#xA;The division you are referring to is generally called &quot;The Perspective Divide&quot;. You can google it and get information overload on helpful documentation. The division itself happens after the geometry shader before the fragment shader as part of rasterization. And is part of the process that creates the fragments that the pixel shader is run on. It is also an important part of vertex attribute interpolation. All of OpenGL, Vulkan, DirectX perform the perspective divide in the same place which is done by the GPU's hardware.&#xD;&#xA;&#xD;&#xA;The most adopted floating point standard is IEEE 754 and yes virtually all vendors implement and follow these standards. I highly recommend (slowly) wrapping your mind around this standard to get a deeper understanding of how floats are processed. Here is a good first factoid to memorize (if you want): The standard put the sign bit for floating point numbers in the same place as the sign bit for integers to make conversion between and understanding both easier.&#xD;&#xA;&#xD;&#xA; Quantization in this context refers to the accuracy of floating point numbers. There are many numbers that can not be fully represented in floating point math on the GPU, such as 1/3. Quantization is the process of representing that number as closely as possible within the limitations of the hardware. But minor difference in hardware implementations that are still standards compliant can and often will produce slightly different results.&#xD;&#xA;&#xD;&#xA;Rather then focus on the limits of floating point numbers or attempting to write code that operates at the edge of these limits, coders generally use techniques that avoid the issue altogether like utilizing hardware offset capabilities to side step the issue completely is one method. (but is situation specific, like when applying decals)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30263" PostHistoryTypeId="2" PostId="10411" RevisionGUID="ec460b38-7ed7-4576-9e76-0c4fc4195232" CreationDate="2020-11-16T18:17:26.647" UserId="6041" Text="I want to render the transient shadows due to the sunlight over a day in one image. So I placed all the suns, as directional light, in the scene. However the shadows in the rendered image(a raytraced image) are too bright and so they look very much faded(below image). This is understandable as there is just too much light from all those suns. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Basically I am trying to achieve an image similar to the below one, where all shadows are distinguishable and not that soft. However I cannot think of any way to achieve this. I appreciate anyone's help.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/76tcL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/UivIy.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30264" PostHistoryTypeId="1" PostId="10411" RevisionGUID="ec460b38-7ed7-4576-9e76-0c4fc4195232" CreationDate="2020-11-16T18:17:26.647" UserId="6041" Text="Too soft shadows from multiple suns" ContentLicense="CC BY-SA 4.0" />
  <row Id="30265" PostHistoryTypeId="3" PostId="10411" RevisionGUID="ec460b38-7ed7-4576-9e76-0c4fc4195232" CreationDate="2020-11-16T18:17:26.647" UserId="6041" Text="|shadow|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30268" PostHistoryTypeId="2" PostId="10412" RevisionGUID="ee2c4a01-3542-46e5-b169-cee3298d41bd" CreationDate="2020-11-16T19:22:06.620" UserDisplayName="user15232" Text="As noted [here][1], when rendering using the GL_POINTS primitive, there is an implementation dependent limit to the point size range.&#xD;&#xA;&#xD;&#xA;I intend to use GL_POINTS for fast billboard rendering of particles, so I am dependent on the point size range to be sufficiently large to visualize perspective scaling.&#xD;&#xA;&#xD;&#xA;I would consider for example the range provided by my graphics card (1-255), to be sufficient, since usually, particles are not close enough to the camera to exceed 255 pixels in diameter.&#xD;&#xA;&#xD;&#xA;Are there any commonly used graphics cards that do not provide such a large range of points sizes?&#xD;&#xA;&#xD;&#xA;Are there any (reasonably modern) graphics cards that do not allow for points larger than one pixel at all?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPointSize.xml#notes" ContentLicense="CC BY-SA 4.0" />
  <row Id="30269" PostHistoryTypeId="1" PostId="10412" RevisionGUID="ee2c4a01-3542-46e5-b169-cee3298d41bd" CreationDate="2020-11-16T19:22:06.620" UserDisplayName="user15232" Text="What sort of implementation dependent limits for glPointSize can one expect from modern graphics cards?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30270" PostHistoryTypeId="3" PostId="10412" RevisionGUID="ee2c4a01-3542-46e5-b169-cee3298d41bd" CreationDate="2020-11-16T19:22:06.620" UserDisplayName="user15232" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30271" PostHistoryTypeId="50" PostId="5520" RevisionGUID="2c0906a3-8714-4f4b-bcb3-ebc4a1334951" CreationDate="2020-11-16T20:00:30.047" UserId="-1" />
  <row Id="30272" PostHistoryTypeId="2" PostId="10413" RevisionGUID="344bce33-c712-4f27-9e4b-47c742582648" CreationDate="2020-11-16T20:28:03.970" UserId="15233" Text="I'm trying to create a camera using matrix transforms, the gist as follows:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Transform =&#xD;&#xA;                Matrix.CreateRotationZ(Rotation) *&#xD;&#xA;                 Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0)) *&#xD;&#xA;                Matrix.CreateScale(Zoom) *&#xD;&#xA;                Matrix.CreateTranslation(new Vector3(Bounds.Width * 0.5f, Bounds.Height * 0.5f, 0));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;It works but with one issue. The rotation origin remains at the starting (-Position.X, -Position.Y) while the zoom works fine (at the center screen) which is obvious from the code. I'd like the rotation to occur at the center screen as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="30273" PostHistoryTypeId="1" PostId="10413" RevisionGUID="344bce33-c712-4f27-9e4b-47c742582648" CreationDate="2020-11-16T20:28:03.970" UserId="15233" Text="Matrix transforming with translation/rotation/scale at center of screen" ContentLicense="CC BY-SA 4.0" />
  <row Id="30274" PostHistoryTypeId="3" PostId="10413" RevisionGUID="344bce33-c712-4f27-9e4b-47c742582648" CreationDate="2020-11-16T20:28:03.970" UserId="15233" Text="|opengl|transformations|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30280" PostHistoryTypeId="2" PostId="10415" RevisionGUID="57e6fb1c-d16d-4fd5-8863-716979df889c" CreationDate="2020-11-17T13:19:01.110" UserId="15238" Text="I wrote a C program [which prints a heartbeat (heart star) animation][1].&#xD;&#xA;&#xD;&#xA;The key is to print a heart of stars, which looks like this&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;consists of line of stars and blanks.&#xD;&#xA;&#xD;&#xA;        * * * *           * * * * &#xD;&#xA;      * * * * * *       * * * * * * &#xD;&#xA;    * * * * * * * *   * * * * * * * * &#xD;&#xA;    * * * * * * * * * * * * * * * * * &#xD;&#xA;      * * * * * * * * * * * * * * * &#xD;&#xA;        * * * * * * * * * * * * * &#xD;&#xA;          * * * * * * * * * * * &#xD;&#xA;            * * * * * * * * * &#xD;&#xA;              * * * * * * * &#xD;&#xA;                * * * * * &#xD;&#xA;                  * * * &#xD;&#xA;                    * &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there an existing method to make it more like a heart? For example, how many lines should I use to draw the top half of the heart shape? &#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/albert10jp/c_learning/blob/main/heart_star_animation.c&#xD;&#xA;  [2]: https://i.stack.imgur.com/9CzFS.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30281" PostHistoryTypeId="1" PostId="10415" RevisionGUID="57e6fb1c-d16d-4fd5-8863-716979df889c" CreationDate="2020-11-17T13:19:01.110" UserId="15238" Text="Is there an existing method to draw a heart of stars that looks more like a heart?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30282" PostHistoryTypeId="3" PostId="10415" RevisionGUID="57e6fb1c-d16d-4fd5-8863-716979df889c" CreationDate="2020-11-17T13:19:01.110" UserId="15238" Text="|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30283" PostHistoryTypeId="2" PostId="10416" RevisionGUID="b4207d9b-49c1-4365-87ff-f280f27430a6" CreationDate="2020-11-17T21:13:36.903" UserId="4958" Text="Instead of using compute shader with atomic operations, I used instanced draw call with additive blending." ContentLicense="CC BY-SA 4.0" />
  <row Id="30284" PostHistoryTypeId="2" PostId="10417" RevisionGUID="a546af07-2f3b-4f75-a632-b1dad549b46c" CreationDate="2020-11-17T22:41:57.033" UserId="6172" Text="I'm making a program that illuminates a sphere using an environment map. For each fragment in the sphere, I compute a many random directions in the hemisphere along the surface normal (no importance sampling), and then sample the environment map. Then I evaluate the GGX BRDF for each sample.&#xD;&#xA;&#xD;&#xA;The problem I have is that it looks too dark, and I'm not sure why.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is for a metallic sphere with low roughness. For such a low roughness, it could make sense that the GGX lobe is so narrow that we are missing it. But things don't improve with higher roughness.&#xD;&#xA;&#xD;&#xA;When I increase the roughness it goes completely dark:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;If I multiply the resulting color by 10 I can tell there is something:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This is my main shader function:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;vec3 bruteForce()&#xD;&#xA;{&#xD;&#xA;    vec3 N = normalize(v_normal);&#xD;&#xA;    vec3 V = normalize(u_camPos - v_pos);&#xD;&#xA;    float NoV = max(0.0001, dot(N, V));&#xD;&#xA;&#xD;&#xA;    vec3 F0 = mix(vec3(0.04), u_albedo, u_metallic);&#xD;&#xA;    vec3 F = fresnelSchlick(NoV, F0);&#xD;&#xA;    vec3 k_spec = F;&#xD;&#xA;    vec3 k_diff = (1 - k_spec) * (1 - u_metallic);&#xD;&#xA;&#xD;&#xA;    vec3 specular = vec3(0.0, 0.0, 0.0);&#xD;&#xA;    for(uint iSample = 0u; iSample &lt; u_numSamples; iSample++)&#xD;&#xA;    {&#xD;&#xA;        uvec3 seedUInt = pcg_uvec3_uvec3(uvec3(gl_FragCoord.x, gl_FragCoord.y, iSample));&#xD;&#xA;        vec2 seed2 = vec2(makeFloat01(seedUInt.x), makeFloat01(seedUInt.y));&#xD;&#xA;        vec3 L = uniformSample(seed2, N);&#xD;&#xA;        vec3 H = normalize(V + L);&#xD;&#xA;        vec3 env = texture(u_envTex, L).rgb;&#xD;&#xA;&#xD;&#xA;        float NoL = max(0.0001, dot(N, L));&#xD;&#xA;        float NoH = max(0.0001, dot(N, H));&#xD;&#xA;        float NoH2 = NoH * NoH;&#xD;&#xA;        float rough4 = u_rough2*u_rough2;&#xD;&#xA;        float q = NoH2 * (rough4 - 1.0) + 1.0;&#xD;&#xA;        float D = rough4 / (PI * q*q);&#xD;&#xA;        float G = ggx_G_smith(NoV, NoL, u_rough2);&#xD;&#xA;        vec3 fr = F * G * D / (4 * NoV * NoL);&#xD;&#xA;        specular += fr * env * NoL;&#xD;&#xA;    }&#xD;&#xA;    specular /= float(u_numSamples);&#xD;&#xA;&#xD;&#xA;    return specular;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here are the other helper functions:&#xD;&#xA;```glsl&#xD;&#xA;vec3 fresnelSchlick(float NoV, vec3 F0)&#xD;&#xA;{&#xD;&#xA;    return F0 + (1.0 - F0) * pow(1.0 - NoV, 5.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float ggx_G(float NoV, float rough2)&#xD;&#xA;{&#xD;&#xA;  float rough4 = rough2 * rough2;&#xD;&#xA;  return 2.0 * (NoV) /&#xD;&#xA;    (NoV + sqrt(rough4 + (1.0 - rough4) * NoV*NoV));&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// geometry term&#xD;&#xA;float ggx_G_smith(float NoV, float NoL, float rough2)&#xD;&#xA;{&#xD;&#xA;  return ggx_G(NoV, rough2) * ggx_G(NoL, rough2);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// this is a hash function for generating pseudo-random numbers. Taken from here: http://jcgt.org/published/0009/03/02/&#xD;&#xA;uvec3 pcg_uvec3_uvec3(uvec3 v)&#xD;&#xA;{&#xD;&#xA;    v = v * 1664525u + 1013904223u;&#xD;&#xA;    v.x += v.y*v.z;&#xD;&#xA;    v.y += v.z*v.x;&#xD;&#xA;    v.z += v.x*v.y;&#xD;&#xA;    v = v ^ (v&gt;&gt;16u);&#xD;&#xA;    v.x += v.y*v.z;&#xD;&#xA;    v.y += v.z*v.x;&#xD;&#xA;    v.z += v.x*v.y;&#xD;&#xA;    return v;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Construct a float with half-open range [0:1] using low 23 bits.&#xD;&#xA;// All zeroes yields 0.0, all ones yields the next smallest representable value below 1.0.&#xD;&#xA;// https://stackoverflow.com/a/17479300/1754322&#xD;&#xA;float makeFloat01( uint m ) {&#xD;&#xA;    const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask&#xD;&#xA;    const uint ieeeOne      = 0x3F800000u; // 1.0 in IEEE binary32&#xD;&#xA;&#xD;&#xA;    m &amp;= ieeeMantissa;                     // Keep only mantissa bits (fractional part)&#xD;&#xA;    m |= ieeeOne;                          // Add fractional part to 1.0&#xD;&#xA;&#xD;&#xA;    float  f = uintBitsToFloat( m );       // Range [1:2]&#xD;&#xA;    return f - 1.0;                        // Range [0:1]&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can you help me find the problem please?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nxoy9.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5FxOI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ynC7W.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30285" PostHistoryTypeId="1" PostId="10417" RevisionGUID="a546af07-2f3b-4f75-a632-b1dad549b46c" CreationDate="2020-11-17T22:41:57.033" UserId="6172" Text="IBL looks too dark with uniform sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="30286" PostHistoryTypeId="3" PostId="10417" RevisionGUID="a546af07-2f3b-4f75-a632-b1dad549b46c" CreationDate="2020-11-17T22:41:57.033" UserId="6172" Text="|glsl|lighting|brdf|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30287" PostHistoryTypeId="2" PostId="10418" RevisionGUID="601d120c-654a-43c4-8db2-ae2439a6a7fa" CreationDate="2020-11-17T23:31:19.647" UserId="445" Text="I'm not familiar with the exact nuances of the STL format, but here are some answers on general computer graphics principles:&#xD;&#xA;&#xD;&#xA;&gt; In the source file, the Vertex Normals are specified and in the destination, the face normal of the triangles are present which are different than the normals one would get by (a-b) x (a-c), where a, b, c are the vertex coordinates and x is the cross product. How one would compute the face normal in the presence of vertex normals?&#xD;&#xA;&#xD;&#xA;There is no general method to convert vertex normals to face normals. Vertex normals (that are not all equal) can express the normals *of a curved surface*, which face normals cannot. Thus, converting to a format with only a normal vector per face, rather than per triangle vertex, is a *lossy* process — some information was discarded. The converter must make a compromise.&#xD;&#xA;&#xD;&#xA;That said, from some quick research, it seems that the intent of the STL file format is that the normal _is_ the normal perpendicular to the triangle (that can be computed as you specified), not a chosen vector, even though that makes it redundant. So perhaps your converter is wrong (though I can't say much as you didn't say _how_ it was different).&#xD;&#xA;&#xD;&#xA;&gt; Also, I am given to understand that STL format has a positive octant rule which requires all vertex coordinates to be positive. When the OBJ file has negative vertex coordinates, what should be done in the conversion process?&#xD;&#xA;&#xD;&#xA;The only option is to choose some offset by which to translate all of the vertices so that they are positive. This also loses some information — what the origin of the original model was. That's easier to recover if needed, though, since it's just a 3D vector that you could translate back by when loading the model." ContentLicense="CC BY-SA 4.0" />
  <row Id="30288" PostHistoryTypeId="2" PostId="10419" RevisionGUID="ab1c9e71-23e5-4299-b040-50970576c45a" CreationDate="2020-11-18T00:35:11.983" UserId="445" Text="The problem is that if you have 8 light sources (as your test image appears to have), then anything that is under only one shadow will be 7/8ths of full brightness, which is a fairly small change. Anything other than that is *unphysical*, so it'll be hard to convince your raytracer to produce a different result by changing the lighting.&#xD;&#xA;&#xD;&#xA;Instead, after rendering the image, you can apply some kind of **nonlinear** processing of the image colors so that that 1/8th difference stands out more. In your second image, this seems to have been done by directly replacing the light gray fully-lit areas with white, but a more proportionate, yet still very visible, result could be achieved with a simple &quot;levels&quot; color edit applied to the whole image, as I've done for this version of your first image:&#xD;&#xA;&#xD;&#xA;[![Levels edit][1]][1]&#xD;&#xA;&#xD;&#xA;Of course, this is fairly ugly and does not show the building shapes well. To fix that, you could render your buildings without any ground, then layer that on top of the color-edited image:&#xD;&#xA;&#xD;&#xA;[![Levels edit with original buildings overlaid][2]][2]&#xD;&#xA;&#xD;&#xA;It might be a good idea to use color to help distinguish the buildings from the shadows. In particular, I'd suggest avoiding making buildings _gray_ (or, more generally, colored the same as the sunlight). Here I've used a &quot;color temperature&quot; edit on the above to make the buildings bluer and the shadowed ground yellower (probably too much):&#xD;&#xA;&#xD;&#xA;[![Color temperature edit][3]][3]&#xD;&#xA;&#xD;&#xA;Of course, this is all rough examples based on quickly editing your sample image; I think you can produce very legible and elegant results by taking these ideas and doing them better (by being able to adjust your raytracer lighting _as well as_ postprocessing the image, and rendering a separate buildings-without-ground image as I suggested).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5dj8o.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RwjlZ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/98ESc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30290" PostHistoryTypeId="2" PostId="10420" RevisionGUID="e7cddfa9-9971-4463-abbd-53d4f36d262b" CreationDate="2020-11-18T12:42:51.337" UserId="9903" Text="Usual reprojection finds UV of current visible point into previous frame. For opaque objects it simply adds motion vector: ```vec2 UV_reprojected = UV + motion;``` &#xD;&#xA;&#xD;&#xA;But for mirror-like surfaces it doesn't work, because we see not object (mirror) itself but what reflects in mirror (virtual object). The general idea to reproject reflected point is: &#xD;&#xA;1. Find world space position for reflected point visible in reflector (Here we need to know reflected path length).&#xD;&#xA;2. Substract world space delta between frames, so we found previous world position.&#xD;&#xA;3. Project this point into reflector using previous camera position.&#xD;&#xA;4. Project world space reflector point back to the screen.&#xD;&#xA;&#xD;&#xA;The most hardest part is p.3, and is not easy analytically find this point, because reflector can change normal. Some interesting links about this topic: &#xD;&#xA;* [Reflection reprojection in Uncharted][1]. Here we assume that reflector is plane that changes transform, both camera and receiver are also dynamic.&#xD;&#xA;* [Ray Tracing Gems chapter 32][2]. (32.4.3) Theoretical approach that finds reflector position in terms of least squares. And interesting geometrical optic approach (here we assume that reflector point is locally sphere-like).&#xD;&#xA;&#xD;&#xA;  [1]: https://www.jpgrenier.org/reflections.html&#xD;&#xA;  [2]: https://link.springer.com/content/pdf/10.1007%2F978-1-4842-4427-2_32.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="30291" PostHistoryTypeId="5" PostId="10415" RevisionGUID="f9117068-d874-45ba-92b6-0fbec007bc59" CreationDate="2020-11-18T13:44:28.557" UserId="15238" Comment="added 136 characters in body" Text="I wrote a C program [which prints a heartbeat (heart star) animation][1].&#xD;&#xA;&#xD;&#xA;The key is to print a heart of stars, which looks like this&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;consists of line of stars and blanks.&#xD;&#xA;&#xD;&#xA;        * * * *           * * * * &#xD;&#xA;      * * * * * *       * * * * * * &#xD;&#xA;    * * * * * * * *   * * * * * * * * &#xD;&#xA;    * * * * * * * * * * * * * * * * * &#xD;&#xA;      * * * * * * * * * * * * * * * &#xD;&#xA;        * * * * * * * * * * * * * &#xD;&#xA;          * * * * * * * * * * * &#xD;&#xA;            * * * * * * * * * &#xD;&#xA;              * * * * * * * &#xD;&#xA;                * * * * * &#xD;&#xA;                  * * * &#xD;&#xA;                    * &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there an existing method to make it more like a heart? For example, how many lines should I use to draw the top half of the heart shape? &#xD;&#xA;&#xD;&#xA;By &quot;more like&quot;, I mean more roundish, like this&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;and this&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/albert10jp/c_learning/blob/main/heart_star_animation.c&#xD;&#xA;  [2]: https://i.stack.imgur.com/9CzFS.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/9iu35.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/YPbHx.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30292" PostHistoryTypeId="5" PostId="10419" RevisionGUID="46894905-c107-49c3-b067-cbbc73d6ae64" CreationDate="2020-11-18T14:52:52.673" UserId="445" Comment="added 296 characters in body" Text="The problem is that if you have 8 light sources (as your test image appears to have), then anything that is under only one shadow will be 7/8ths of full brightness, which is a fairly small change. Anything other than that is *unphysical*, so it'll be hard to convince your raytracer to produce a different result by changing the lighting.&#xD;&#xA;&#xD;&#xA;Instead, after rendering the image, you can apply some kind of **nonlinear** processing of the image colors so that that 1/8th difference stands out more. In your second image, this seems to have been done by directly replacing the light gray fully-lit areas with white, but a more proportionate, yet still very visible, result could be achieved with a simple &quot;levels&quot; color edit applied to the whole image to increase contrast, as I've done for this version of your first image:&#xD;&#xA;&#xD;&#xA;[![Levels edit][1]][1]&#xD;&#xA;&#xD;&#xA;By pushing light gray to white, and darker grays more to black, the contrast in the image is greatly increased. The cost is that the building shapes are dark and hard to see.&#xD;&#xA;&#xD;&#xA;To make the buildings look better and stand out, you could render your buildings a second time without any ground (so the resulting image has a transparent background), then layer that on top of the color-edited image, so that they are unaffected by the contrast adjustment.&#xD;&#xA;&#xD;&#xA;[![Levels edit with original buildings overlaid][2]][2]&#xD;&#xA;&#xD;&#xA;It might be a good idea to use color to help distinguish the buildings from the shadows. In particular, I'd suggest avoiding making buildings _gray_ (or, more generally, colored the same as the sunlight). Here I've used a &quot;color temperature&quot; edit on the above to make the buildings layer bluer and the shadowed ground layer yellower (probably too much):&#xD;&#xA;&#xD;&#xA;[![Color temperature edit][3]][3]&#xD;&#xA;&#xD;&#xA;Of course, this is all rough examples based on quickly editing your sample image; I think you can produce very legible and elegant results by taking these ideas and doing them better (by being able to adjust your raytracer lighting _as well as_ postprocessing the image, and rendering a separate buildings-without-ground image as I suggested).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5dj8o.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RwjlZ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/98ESc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30293" PostHistoryTypeId="5" PostId="10420" RevisionGUID="de12aa8d-9f8c-4fa7-ad80-493f396f32ad" CreationDate="2020-11-19T14:08:21.353" UserId="9903" Comment="added 38 characters in body" Text="Usual reprojection finds UV of current visible point into previous frame. For diffuse and rough objects it simply adds motion vector: ```vec2 UV_reprojected = UV + motion;``` &#xD;&#xA;&#xD;&#xA;But for mirror-like surfaces it doesn't work, because we see not object (mirror) itself but what reflects in mirror (virtual object). The general idea to reproject reflected point is: &#xD;&#xA;1. Find world space position for reflected point visible in reflector (Here we need to know reflected path length).&#xD;&#xA;2. Substract world space delta between frames, so we found previous world position.&#xD;&#xA;3. Project this point into reflector using previous camera position.&#xD;&#xA;4. Project world space reflector point back to the screen.&#xD;&#xA;&#xD;&#xA;The most hardest part is p.3, and is not easy analytically find this point, because reflector can change normal. Some interesting links about this topic: &#xD;&#xA;* [Reflection reprojection in Uncharted][1]. Here we assume that reflector is plane that changes transform, both camera and receiver are also dynamic.&#xD;&#xA;* [Ray Tracing Gems chapter 32][2]. (32.4.3) Theoretical approach that finds reflector position in terms of least squares. And interesting geometrical optic approach (here we assume that reflector point is locally sphere-like).&#xD;&#xA;&#xD;&#xA;  [1]: http://bitsquid.blogspot.com/2017/06/reprojecting-reflections_22.html&#xD;&#xA;  [2]: https://link.springer.com/content/pdf/10.1007%2F978-1-4842-4427-2_32.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="30294" PostHistoryTypeId="5" PostId="10416" RevisionGUID="c9f58265-72d6-453e-a85e-7b6afc57bd4c" CreationDate="2020-11-19T17:07:35.663" UserId="4958" Comment="added 195 characters in body" Text="Instead of using compute shader with atomic operations, I used instanced draw call with additive blending.&#xD;&#xA;In compute shader I had X as destination texels and Y as different sample directions for each texel. Now in instanced screen quad draw each instance is sample direction added to output texture." ContentLicense="CC BY-SA 4.0" />
  <row Id="30306" PostHistoryTypeId="2" PostId="10423" RevisionGUID="46e1dda6-02d6-45e1-9f81-e536fbd45ab0" CreationDate="2020-11-22T08:49:06.830" UserId="6496" Text="I am extending [Roger Allen's Ray Tracing in One Weekend in CUDA][1] (and also [here][2]) by following [Peter Shirley's Ray Tracing: The Next Week][3]; specifically Image Texture Mapping.&#xD;&#xA;&#xD;&#xA;The image I obtain from CUDA is not as sharp as the CPU version. Shirley's book uses `double` and Allen restricts to `float` but could that be the only reason?&#xD;&#xA;&#xD;&#xA;The texture source for both is a 24 bit depth jpeg file. &#xD;&#xA;&#xD;&#xA;In both cases 100x sampling per pixel used for antialiasing.&#xD;&#xA;&#xD;&#xA;Is there anything to be done in the kernel to improve the image quality?&#xD;&#xA;```&#xD;&#xA;    class imageTextureX :public textureX {&#xD;&#xA;public:&#xD;&#xA;	__device__ imageTextureX(uint32_t width, uint32_t height, cudaTextureObject_t textureObject) :_width(width), _height(height), _textureObj(textureObject) {}&#xD;&#xA;	__forceinline__ __device__  vec3 value(float u, float v, const vec3&amp; p) const override {&#xD;&#xA;		//Flip Y-Coordinate;&#xD;&#xA;		v = 1.0f - v;&#xD;&#xA;		//De-normalize coordinate(s)&#xD;&#xA;		uint32_t X = u * _width;&#xD;&#xA;		//Re-normalize&#xD;&#xA;		constexpr float pixelOffset{ 0.5f };&#xD;&#xA;		const float denominator = 1.0f / (float)(3 * _width);&#xD;&#xA;		u = (float)(3 * X + pixelOffset);&#xD;&#xA;&#xD;&#xA;		vec3 colorVal;&#xD;&#xA;		colorVal.e[0] = (float)tex2D&lt;uint8_t&gt;(_textureObj, u++ * denominator, v);&#xD;&#xA;		colorVal.e[1] = (float)tex2D&lt;uint8_t&gt;(_textureObj, u++ * denominator, v);&#xD;&#xA;		colorVal.e[2] = (float)tex2D&lt;uint8_t&gt;(_textureObj, u * denominator, v);&#xD;&#xA;		return colorVal / 255.0f;&#xD;&#xA;	}&#xD;&#xA;private:&#xD;&#xA;	cudaTextureObject_t _textureObj;&#xD;&#xA;	uint32_t _width;&#xD;&#xA;	uint32_t _height;&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Texture definition code&#xD;&#xA;&#xD;&#xA;    //Load Texture Image from Disk&#xD;&#xA;    	cudaArray* cuArray;&#xD;&#xA;    	cudaTextureObject_t textureObject;&#xD;&#xA;    	int32_t textureWidth, textureHeight;&#xD;&#xA;    	{&#xD;&#xA;    		Timer tim(&quot;Prepare Image Texture&quot;);&#xD;&#xA;    		const static uint32_t bytesPerPixel{ 3u };&#xD;&#xA;    		uint8_t* pHostData;&#xD;&#xA;    		uint32_t bytesPerScanline;&#xD;&#xA;    		cudaChannelFormatDesc channelFormatDesc;&#xD;&#xA;    		cudaResourceDesc  resourceDesc{};&#xD;&#xA;    		cudaTextureDesc textureDesc{};&#xD;&#xA;    		int32_t componentsPerPixel = bytesPerPixel;&#xD;&#xA;    		pHostData = stbi_load(textureFilename.c_str(), &amp;textureWidth, &amp;textureHeight, &amp;componentsPerPixel, componentsPerPixel);&#xD;&#xA;    		if (nullptr == pHostData) {&#xD;&#xA;    			std::cerr &lt;&lt; &quot;ERROR: Could not load texture image file '&quot; &lt;&lt; textureFilename &lt;&lt; std::endl;&#xD;&#xA;    			return;&#xD;&#xA;    		}&#xD;&#xA;    		bytesPerScanline = bytesPerPixel * textureWidth;&#xD;&#xA;    &#xD;&#xA;    		channelFormatDesc = cudaCreateChannelDesc(8, 0, 0, 0, cudaChannelFormatKindUnsigned);&#xD;&#xA;    		checkCudaErrors(cudaMallocArray(&amp;cuArray, &amp;channelFormatDesc, bytesPerScanline, textureHeight));&#xD;&#xA;    		checkCudaErrors(cudaMemcpyToArray(cuArray, 0, 0, pHostData, bytesPerScanline * textureHeight * sizeof(uint8_t), cudaMemcpyHostToDevice));&#xD;&#xA;    		&#xD;&#xA;    		resourceDesc.resType = cudaResourceTypeArray;&#xD;&#xA;    		resourceDesc.res.array.array = cuArray;&#xD;&#xA;    &#xD;&#xA;    		textureDesc.normalizedCoords = true;&#xD;&#xA;    		textureDesc.filterMode = cudaFilterModePoint;&#xD;&#xA;    		textureDesc.addressMode[0] = cudaAddressModeWrap;&#xD;&#xA;    		textureDesc.addressMode[1] = cudaAddressModeWrap;&#xD;&#xA;    		textureDesc.readMode = cudaReadModeElementType;&#xD;&#xA;    		checkCudaErrors(cudaCreateTextureObject(&amp;textureObject, &amp;resourceDesc, &amp;textureDesc, nullptr));&#xD;&#xA;    		STBI_FREE(pHostData);&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;The output images were ppm and converted to pgm for upload purposes&#xD;&#xA;[![From CPU code][4]][4]&#xD;&#xA;&#xD;&#xA;[![From CUDA code][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/rogerallen/raytracinginoneweekendincuda&#xD;&#xA;  [2]: https://developer.nvidia.com/blog/accelerated-ray-tracing-cuda/&#xD;&#xA;  [3]: https://raytracing.github.io/books/RayTracingTheNextWeek.html#imagetexturemapping&#xD;&#xA;  [4]: https://i.stack.imgur.com/IpNXb.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/w7eY7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30307" PostHistoryTypeId="1" PostId="10423" RevisionGUID="46e1dda6-02d6-45e1-9f81-e536fbd45ab0" CreationDate="2020-11-22T08:49:06.830" UserId="6496" Text="Why is the image from the CUDA version not as sharp as the CPU version?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30308" PostHistoryTypeId="3" PostId="10423" RevisionGUID="46e1dda6-02d6-45e1-9f81-e536fbd45ab0" CreationDate="2020-11-22T08:49:06.830" UserId="6496" Text="|raytracing|rendering|texture|antialiasing|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30312" PostHistoryTypeId="2" PostId="10425" RevisionGUID="d1c29de4-9c1f-46d0-8c62-d47895cff535" CreationDate="2020-11-23T05:50:20.813" UserId="15172" Text="I've sucessfully implemented a ray tracer from scratch in C and it's marvelous:&#xD;&#xA;[![sphere1][1]][1]&#xD;&#xA;&#xD;&#xA;The surface normal on this sphere is taken by computing the intersection point, A, and treating this as a euclidean vector with origin, B, the center of the sphere. To normalize it, I first subtracted A with B, yielding C: &#xD;&#xA;&#xD;&#xA;C = (Ax-Bx,Ay-By)&#xD;&#xA;&#xD;&#xA;From this, it's divided by the magnitude:&#xD;&#xA;&#xD;&#xA;N = C/|C|&#xD;&#xA;&#xD;&#xA;When I tried setting the light source to (0.0, 0.0, -1.0), it produce something like this:&#xD;&#xA;[![sphere2][2]][2]&#xD;&#xA;&#xD;&#xA;I expected the shade to be something like it's brighter on the middle and becoming more dimmer on the side.&#xD;&#xA;&#xD;&#xA;Anyone know what's causing the problem?&#xD;&#xA;&#xD;&#xA;Source code: https://gist.github.com/harieamjari/6297a35400460edbabbd8e39720ed0f5&#xD;&#xA;&#xD;&#xA;This can be compiled if you already have libpng16.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QL1ix.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dhNtj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30313" PostHistoryTypeId="1" PostId="10425" RevisionGUID="d1c29de4-9c1f-46d0-8c62-d47895cff535" CreationDate="2020-11-23T05:50:20.813" UserId="15172" Text="Lambertian shading illuminates all the front of a sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="30314" PostHistoryTypeId="3" PostId="10425" RevisionGUID="d1c29de4-9c1f-46d0-8c62-d47895cff535" CreationDate="2020-11-23T05:50:20.813" UserId="15172" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30315" PostHistoryTypeId="5" PostId="10425" RevisionGUID="f4add073-8101-4996-b6e4-1b94cbf99449" CreationDate="2020-11-23T05:59:24.873" UserId="15172" Comment="added 214 characters in body" Text="I've sucessfully implemented a ray tracer from scratch in C and it's marvelous:&#xD;&#xA;[![sphere1][1]][1]&#xD;&#xA;&#xD;&#xA;The surface normal on this sphere is taken by computing the intersection point, A, and treating this as a euclidean vector with origin, B, the center of the sphere. To normalize it, I first subtracted A with B, yielding C: &#xD;&#xA;&#xD;&#xA;C = (Ax-Bx,Ay-By)&#xD;&#xA;&#xD;&#xA;From this, it's divided by the magnitude:&#xD;&#xA;&#xD;&#xA;N = C/|C|&#xD;&#xA;&#xD;&#xA;The illumination is calculated by taking the dot product of N and LIGHT_SOURCE and multiplying it with 255:&#xD;&#xA;```&#xD;&#xA;if (dot_product&lt;0.0) dot_product = 0.0;&#xD;&#xA;illumination = (unsigned char)(dot_product*255.0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;When I tried setting the light source to (0.0, 0.0, -1.0), it produce something like this:&#xD;&#xA;[![sphere2][2]][2]&#xD;&#xA;&#xD;&#xA;I expected the shade to be something like it's brighter on the middle and becoming more dimmer on the side.&#xD;&#xA;&#xD;&#xA;Anyone know what's causing the problem?&#xD;&#xA;&#xD;&#xA;Source code: https://gist.github.com/harieamjari/6297a35400460edbabbd8e39720ed0f5&#xD;&#xA;&#xD;&#xA;This can be compiled if you already have libpng16.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QL1ix.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/dhNtj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30316" PostHistoryTypeId="2" PostId="10426" RevisionGUID="a82d1571-c2d9-4a2a-bbfc-83e2dd89fd30" CreationDate="2020-11-23T07:52:45.430" UserId="6046" Text="I think there is a problem with your ray-sphere intersection.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;sphere_normal = ray.origin - sphere_center;&#xD;&#xA;b = dot(sphere_normal , ray.normalized_dir);&#xD;&#xA;c = dot(sphere_normal , sphere_normal ) - sphere_radius*spheres_radius;&#xD;&#xA;float disc = b * b - c;&#xD;&#xA;&#xD;&#xA;float t = -1.0f;&#xD;&#xA;if(disc &gt;= 0.0f)&#xD;&#xA;t = -b - sqrt(disc);&#xD;&#xA;&#xD;&#xA;if(t &gt;= 0) // means ray intersects...&#xD;&#xA;     &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Check out scratchapixel to understand how I got this.&#xD;&#xA;https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30317" PostHistoryTypeId="5" PostId="10426" RevisionGUID="905293f0-e5a1-4115-b6aa-bc889ffb310e" CreationDate="2020-11-23T09:07:44.297" UserId="6046" Comment="added 1 character in body" Text="I think there is a problem with your ray-sphere intersection.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;sphere_normal = ray.origin - sphere_center;&#xD;&#xA;b = dot(sphere_normal , ray.normalized_dir);&#xD;&#xA;c = dot(sphere_normal , sphere_normal ) - sphere_radius*spheres_radius;&#xD;&#xA;float disc = b * b - c;&#xD;&#xA;&#xD;&#xA;float t = -1.0f;&#xD;&#xA;if(disc &gt;= 0.0f)&#xD;&#xA;t = -b +- sqrt(disc);&#xD;&#xA;&#xD;&#xA;if(t &gt;= 0) // means ray intersects...&#xD;&#xA;     &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Check out scratchapixel to understand how I got this.&#xD;&#xA;https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30318" PostHistoryTypeId="2" PostId="10427" RevisionGUID="6cde66bb-3093-459d-b589-b17fd5026337" CreationDate="2020-11-23T12:36:09.147" UserDisplayName="user15232" Text="In my application, there is no inherent 2D or 3D structure to the computer shader instances. So having multiple dimensions doesn't benefit me semantically in any way. I am wondering, whether it still might be beneficial to split up my workload over three dimensions to increase performance.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30319" PostHistoryTypeId="1" PostId="10427" RevisionGUID="6cde66bb-3093-459d-b589-b17fd5026337" CreationDate="2020-11-23T12:36:09.147" UserDisplayName="user15232" Text="Is glDispatchCompute(a,b,c) any faster than glDispatchCompute(a*b*c,1,1)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30320" PostHistoryTypeId="3" PostId="10427" RevisionGUID="6cde66bb-3093-459d-b589-b17fd5026337" CreationDate="2020-11-23T12:36:09.147" UserDisplayName="user15232" Text="|performance|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30321" PostHistoryTypeId="2" PostId="10428" RevisionGUID="1b7f753c-f3fd-4c9a-875b-18c246582210" CreationDate="2020-11-23T14:50:52.830" UserId="2654" Text="Broadly speaking, no, these won't really matter.&#xD;&#xA;&#xD;&#xA;In *specific* cases, it could, but only because it might influence the order in which work groups are processed. And that would mean that it might influence cache behavior and the like, which could matter if neighboring work groups access related memories.&#xD;&#xA;&#xD;&#xA;But even in such a case, which one is better would depend entirely on the nature of the shader's memory access patterns and the driver's decisions about ordering work groups. One shader might run slightly faster with a linear ordering, while a different shader might run faster with a multi-dimensional ordering. It all depends on what the shader is doing (and how the driver handles it), so you can't say that one is inherently better than the other." ContentLicense="CC BY-SA 4.0" />
  <row Id="30322" PostHistoryTypeId="33" PostId="10417" RevisionGUID="f2e3a3fc-54d3-4bec-8fa3-6ef83f55649d" CreationDate="2020-11-23T16:25:06.210" UserId="6172" Comment="66" />
  <row Id="30323" PostHistoryTypeId="5" PostId="8875" RevisionGUID="893c338d-23bc-4326-9541-e476589ca906" CreationDate="2020-11-23T16:37:02.947" UserId="2654" Comment="added 2 characters in body" Text="&gt; since that is the case for window-space coordinates in the vertex stage.&#xD;&#xA;&#xD;&#xA;There are no &quot;window-space coordinates in the vertex stage&quot;. Or at least, not in the vertex *shader*.&#xD;&#xA;&#xD;&#xA;Window-space is not relative to the viewport; it's relative to the *window* (or framebuffer, in this case). The viewport transform is used to convert from NDC-coordinates (which are relative to the viewport) to window coordinates (which are not).&#xD;&#xA;&#xD;&#xA;If you need your fragment shader to have viewport-relative coordinates, then you need to either compute them in the fragment shader (by providing the viewport as a `uniform`) or pass NDC coordinates from the vertex shader as an `in`/`out` variable pair (just compute `gl_Position.xy/gl_Position.w`)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30324" PostHistoryTypeId="50" PostId="9616" RevisionGUID="86278f20-db8e-40f1-8f0e-58f8898a522f" CreationDate="2020-11-23T18:08:00.867" UserId="-1" />
  <row Id="30325" PostHistoryTypeId="5" PostId="10426" RevisionGUID="a7648eab-ea1f-45b2-b573-a14d6188d5e5" CreationDate="2020-11-23T23:27:54.973" UserId="6046" Comment="added 24 characters in body" Text="I think there is a problem with your ray-sphere intersection.&#xD;&#xA;&#xD;&#xA;It should go like this&#xD;&#xA;```&#xD;&#xA;sphere_normal = ray.origin - sphere_center;&#xD;&#xA;b = dot(sphere_normal , ray.normalized_dir);&#xD;&#xA;c = dot(sphere_normal , sphere_normal ) - sphere_radius*spheres_radius;&#xD;&#xA;float disc = b * b - c;&#xD;&#xA;&#xD;&#xA;float t = -1.0f;&#xD;&#xA;if(disc &gt;= 0.0f)&#xD;&#xA;t = -b +- sqrt(disc);&#xD;&#xA;&#xD;&#xA;if(t &gt;= 0) // means ray intersects...&#xD;&#xA;     &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Check out scratchapixel to understand how I got this.&#xD;&#xA;https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30326" PostHistoryTypeId="2" PostId="10429" RevisionGUID="ab4fef48-914a-4ffe-9fc8-99b3e679296b" CreationDate="2020-11-24T04:27:35.893" UserId="15172" Text="It turns out, the problem was because the sphere was placed very far away and the radius is too big. This produces a normal with a high value z.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A solution for me was to place the sphere very close to the origin—about z=0.25, and set the radius of the sphere less than z— about r=0.125.&#xD;&#xA;&#xD;&#xA;light_source (-1,0,0)&#xD;&#xA;![-1,0,0](https://i.stack.imgur.com/TnOTu.png)&#xD;&#xA;light_source (0,0,-1)&#xD;&#xA;![0,0,-1](https://i.stack.imgur.com/Guz4I.png)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30327" PostHistoryTypeId="2" PostId="10430" RevisionGUID="6b97af85-2ea0-481f-accf-7e2f85cca252" CreationDate="2020-11-25T12:11:08.917" UserId="15268" Text="I am trying to build a VR tracking system with a laptop webcam, and I have succeeded in identifying, and tracking paper markers I put in front of my webcam. For context I am using OpenCV with the latest OpenCVSharp wrapper in .Net 5.&#xD;&#xA;&#xD;&#xA;Currently I can track all 4 corners of an object (ordered, so orientation is accounted for) as a 2d quad on the webcam's image, so long as I am provided with a reference image before hand. I know the exact measurements of the reference object, and now I want to use both the 4 corners I calculate, and the measurements of the object in order to determine the position and rotation of that object relative to my webcam.&#xD;&#xA;&#xD;&#xA;In the future I would also like to add additional cameras to the setup to allow for more precision and reducing dead zones. They would know the positions relative to the other sensors for the sake of simplicity.&#xD;&#xA;&#xD;&#xA;How would I go about calculating both the position and rotation of an object given its' measurements, and 4 ordered corners on an image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30328" PostHistoryTypeId="1" PostId="10430" RevisionGUID="6b97af85-2ea0-481f-accf-7e2f85cca252" CreationDate="2020-11-25T12:11:08.917" UserId="15268" Text="Calculate the position and rotation of a quad in 3d space given a 2d projection of that quad from a camera" ContentLicense="CC BY-SA 4.0" />
  <row Id="30329" PostHistoryTypeId="3" PostId="10430" RevisionGUID="6b97af85-2ea0-481f-accf-7e2f85cca252" CreationDate="2020-11-25T12:11:08.917" UserId="15268" Text="|image-processing|mathematics|virtual-reality|opencv|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30330" PostHistoryTypeId="2" PostId="10431" RevisionGUID="3649c829-d175-43b6-9821-f7fcc57f2a20" CreationDate="2020-11-26T01:40:06.617" UserId="15275" Text="I am interested in a scientific application in which ray tracing is necessary, but also where the light itself alters the geometry of the surface mesh (imagine perhaps that the beams of light have enough energy to damage the surface). Right now I am writing everything from scratch and not using any existing libraries, and thus my (obviously naive) implementation is extremely slow. As I understand it, this boils down to clever methods by which to update the BVH, interleaved with each rendering step.&#xD;&#xA;&#xD;&#xA;While I'm interested in the algorithmic problem, what I'm more interested in is whether or not there is a graphics library that is well suited to this task, so that I don't have to re-invent the wheel, or dive too deep into the literature. I am quite a beginner when it comes to available software libraries so please forgive me, I can provide some information if it is necessary to answer this question adequately." ContentLicense="CC BY-SA 4.0" />
  <row Id="30331" PostHistoryTypeId="1" PostId="10431" RevisionGUID="3649c829-d175-43b6-9821-f7fcc57f2a20" CreationDate="2020-11-26T01:40:06.617" UserId="15275" Text="Ray tracing where illumination itself affects the geometry" ContentLicense="CC BY-SA 4.0" />
  <row Id="30332" PostHistoryTypeId="3" PostId="10431" RevisionGUID="3649c829-d175-43b6-9821-f7fcc57f2a20" CreationDate="2020-11-26T01:40:06.617" UserId="15275" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30333" PostHistoryTypeId="2" PostId="10432" RevisionGUID="8166fb76-2cf1-4e39-a0c9-264089b49877" CreationDate="2020-11-26T04:34:19.600" UserId="48" Text="You might look into [Mitsuba][1], which is a physically based path tracing renderer that's designed to be easy to extend with plugins. It might be useful as a base for you to build on, implementing your own algorithms as plugins or by modifying its code.&#xD;&#xA;&#xD;&#xA;It already contains facilities for measuring the amount of light falling on some geometry, in the form of the &quot;[irradiance meter][2]&quot; object. I'm not sure how much it can help you with geometry modification as it's not really designed for that (it just imports geometry from a file and renders it), but maybe you can find some other libraries to help with that part, depending on what kind of geometry operations you need to do.&#xD;&#xA;&#xD;&#xA;[1]: https://www.mitsuba-renderer.org/&#xD;&#xA;[2]: https://mitsuba2.readthedocs.io/en/latest/generated/plugins.html#irradiance-meter-irradiancemeter" ContentLicense="CC BY-SA 4.0" />
  <row Id="30334" PostHistoryTypeId="2" PostId="10433" RevisionGUID="1e875722-9ef1-4d9d-a962-53f585be04ea" CreationDate="2020-11-26T14:10:47.153" UserId="4768" Text="Hello Djgaven588 and welcome to the forums!&#xD;&#xA;&#xD;&#xA;This is not a computer graphics question, but a computer vision one. The answer to it is a little bit involved and I cannot make it justice on a forum post. However, I can point you in the right direction so that you are able to find the answer by yourself.&#xD;&#xA;&#xD;&#xA;Here's a helpful link: https://docs.opencv.org/master/d9/db7/tutorial_py_table_of_contents_calib3d.html&#xD;&#xA;&#xD;&#xA;The process is somewhat straightforward, but it depends on how much you know about projections and solving systems of equations.&#xD;&#xA;&#xD;&#xA;First you need to find key points on a known object in your image through some kind of image-processing algorithm. It seems you already did that. By known object, I mean that you know its exact measurements in the real world with regards to the selected key points.&#xD;&#xA;&#xD;&#xA;Secondly, you need to &quot;unproject&quot; your 2D image points onto 3D space, by reversing the projection math from 3D to 2D. This requires building a projection matrix containing intrinsic and extrinsic camera parameters, as well as finding coefficients modelling the camera lens distortion. This process is known as camera calibration.&#xD;&#xA;&#xD;&#xA;Thirdly, when using a single camera, you can unproject the points only up to a scale factor, because the depth coordinate has been lost during the original projection. In order to figure out the scale, rotation, and position of the object, you can set up a system of equations relating the image key points to the known key points in the real world at a specific position and rotation of the known object. Solving this system will let you figure out the transform. Note that it is important to have a reasonable amount of key points (even redundant ones) so that the error can be minimised.&#xD;&#xA;&#xD;&#xA;OpenCV has methods and functions for doing all of these procedures, and there are many tutorials on the web, like the one I linked above.&#xD;&#xA;&#xD;&#xA;I hope you can figure it out! :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30335" PostHistoryTypeId="2" PostId="10434" RevisionGUID="86724773-e213-4426-b919-fd9d897df6b8" CreationDate="2020-11-26T15:10:43.927" UserId="15278" Text="I have just started learning how to use and create shaders in ThreeJS and, while going through some shaders in the example folder, I have come across a bokeh shader. Inside the shader, blur is computed using a formula, but I dont really understand where does this formula come from and what it really computes. Here is some code:&#xD;&#xA;```&#xD;&#xA;float f = focalLength; // focal length in mm&quot;,&#xD;&#xA;		&quot;		float d = fDepth*1000.0; // focal plane in mm&quot;,&#xD;&#xA;		&quot;		float o = depth*1000.0; // depth in mm&quot;,&#xD;&#xA;&#xD;&#xA;		&quot;		float a = (o*f)/(o-f);&quot;,&#xD;&#xA;		&quot;		float b = (d*f)/(d-f);&quot;,&#xD;&#xA;		&quot;		float c = (d-f)/(d*fstop*CoC);&quot;,&#xD;&#xA;&#xD;&#xA;		&quot;		blur = abs(a-b)*c;&quot;,&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;What I don't understand is what c is and how I can then use it to compute the blur. For reference, the shader I am talking about is BokehShader2 by Martins Upitis.&#xD;&#xA;Can anyone help me out?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30336" PostHistoryTypeId="1" PostId="10434" RevisionGUID="86724773-e213-4426-b919-fd9d897df6b8" CreationDate="2020-11-26T15:10:43.927" UserId="15278" Text="Blur calculation in shader with fixed CoC" ContentLicense="CC BY-SA 4.0" />
  <row Id="30337" PostHistoryTypeId="3" PostId="10434" RevisionGUID="86724773-e213-4426-b919-fd9d897df6b8" CreationDate="2020-11-26T15:10:43.927" UserId="15278" Text="|shader|post-processing|three.js|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30342" PostHistoryTypeId="2" PostId="10436" RevisionGUID="c08a6d80-4624-4784-8330-d55f60a56c01" CreationDate="2020-11-26T22:02:13.277" UserDisplayName="user4801" Text="I'm trying to understand how to implement an algorithm similar to the one used by Magics' mark surface tool, you can see such behaviour on this [video](https://youtu.be/XVrRbGNBtVc?t=145).&#xD;&#xA;&#xD;&#xA;Quoting the video: &quot;Basically with this tool you're able to select surfaces, which unlike planes, surfaces take curvature into account.&quot;&#xD;&#xA;&#xD;&#xA;The first idea that come to my mind to implement something similar was starting by considering the adjacency information of the mesh and consider on the computation the angle adjacent triangle normals. My idea was that if such an angle wasn't on the range [pi/2-tol, pi/2+tol] two adjacent triangles would be &quot;smooth&quot;. This thought was too naive and the idea would just work for a very limited of cases and it'd start fail for many of them.&#xD;&#xA;&#xD;&#xA;After that, I've spent a little bit of time reading some papers talking about mesh segmentation and it seems this has been an area of research for many years... But before even considering implementing any of these one I'd like to ask here if you knew some basic&amp;good enough algorithm I could implement that could behave in a similar fashion to Magic's.&#xD;&#xA;&#xD;&#xA;So yeah, that's my question basically, assuming a triangular mesh that has adjacency information built (ie: you can check adjacent triangles from any given face) and a starting selected triangle, how would you detect the &quot;surface&quot; region associated to it?&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="30343" PostHistoryTypeId="1" PostId="10436" RevisionGUID="c08a6d80-4624-4784-8330-d55f60a56c01" CreationDate="2020-11-26T22:02:13.277" UserDisplayName="user4801" Text="Algorithm to select regions based on curvature on a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="30344" PostHistoryTypeId="3" PostId="10436" RevisionGUID="c08a6d80-4624-4784-8330-d55f60a56c01" CreationDate="2020-11-26T22:02:13.277" UserDisplayName="user4801" Text="|computational-geometry|mesh|geometry|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30345" PostHistoryTypeId="6" PostId="10436" RevisionGUID="b07b13b4-3e4c-4601-80c3-9673815fb81d" CreationDate="2020-11-26T22:31:38.780" UserDisplayName="user4801" Comment="edited tags" Text="|3d|computational-geometry|mesh|geometry|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30346" PostHistoryTypeId="5" PostId="10431" RevisionGUID="d01beff5-f9ef-4eba-a3d4-5a9c7ebda290" CreationDate="2020-11-27T07:30:32.687" UserId="15275" Comment="added 353 characters in body" Text="I am interested in a scientific application in which ray tracing is necessary, but also where the light itself alters the geometry of the surface mesh (imagine perhaps that the beams of light have enough energy to damage the surface). Right now I am writing everything from scratch and not using any existing libraries, and thus my (obviously naive) implementation is extremely slow. As I understand it, this boils down to clever methods by which to update the BVH, interleaved with each rendering step.&#xD;&#xA;&#xD;&#xA;Some slight elaboration on the problem: when a ray of light hits a surface, we consider two possibilities: either it reflects off the surface (as is typical in a ray tracer), or it impacts the surface and essentially burns a hole into the surface. This alters the geometry  of the mesh and affects any future light rays, and thus forces an update of the boundary volume hierarchy. The surface deformation is usually local but *can* be global-scale, for example if the hole is large enough it may cause the structure to collapse or break off. Thus ray tracing affects the geometry &quot;in real time&quot;, but simultaneously geometry is necessary to perform ray tracing at each step as well.&#xD;&#xA;&#xD;&#xA;While I'm interested in the algorithmic problem, what I'm more interested in is whether or not there is a graphics library that is well suited to this task, so that I don't have to re-invent the wheel, or dive too deep into the literature. I am quite a beginner when it comes to available software libraries so please forgive me." ContentLicense="CC BY-SA 4.0" />
  <row Id="30347" PostHistoryTypeId="50" PostId="9591" RevisionGUID="3aa3e78d-1bf5-459e-89cf-411eefc2f7c5" CreationDate="2020-11-27T14:03:30.483" UserId="-1" />
  <row Id="30348" PostHistoryTypeId="2" PostId="10437" RevisionGUID="3fd1e9ec-5b45-4081-92fc-0b16d051820c" CreationDate="2020-11-27T22:49:48.050" UserId="48" Text="The function $h_j$ is going to be a low-pass filter of some type. Its role is to turn the infinite-resolution image $f$ into a band-limited one so that it can be sampled to produce pixel values without aliasing. Typical shapes for $h_j$ in practice could be like a box, tent, bicubic, or Gaussian function.&#xD;&#xA;&#xD;&#xA;Such a filter would generally be expected to have the following properties:&#xD;&#xA;&#xD;&#xA;* Defined over the image plane, $h_j: \mathbb{R}^2 \to \mathbb{R}$&#xD;&#xA;* Is an area density, i.e. has units of inverse area (and scales accordingly under changes of coordinates)&#xD;&#xA;* Compactly supported, with its region of support commensurate with the pixel spacing (typically having a radius of 1–2 pixels in all directions)&#xD;&#xA;* Smooth, or at least piecewise smooth&#xD;&#xA;* Finite-valued&#xD;&#xA;* Integrates to 1, $\int_{\mathbb{R}^2} h_j(x) \, dx^2 = 1$&#xD;&#xA;* The filters for different pixels $j$ differ only by translation, $h_j(x) = h(x - x_j)$ where $h$ is the filter centered at 0, and $x_j$ is the center of the $j$th pixel. &#xD;&#xA;* Symmetric, $h(-x) = h(x)$&#xD;&#xA;* Factors into 1D filters along the x and y axes, $h(x, y) = h(x)h(y)$&#xD;&#xA;&#xD;&#xA;(The last three properties might not be true for some exotic cases, such as rendering to a curved or nonlinearly warped display, but would be expected to hold for rendering an ordinary 2D image.)&#xD;&#xA;&#xD;&#xA;You'll note one property I didn't mention was $h_j \geq 0$. That's because it is actually convenient to use filters with negative lobes sometimes, as they can improve image sharpness. See for example the [Mitchell–Netravali filters](https://en.wikipedia.org/wiki/Mitchell-Netravali_filters). Nor do we necessarily have $h_j \leq 1$ everywhere. Actually the values of $h_j$ depend on the coordinate system, since it's an area density, so a statement like $h_j \leq 1$ is meaningless without specifying some particular coordinates.&#xD;&#xA;&#xD;&#xA;Regarding your properties, for (a), yes the norm of the filter should be bounded. As mentioned, the filter integrates to 1. Without negative lobes, the 1-norm of the filter should be exactly 1. The 1-norm of a filter with negative lobes would be expected to be somewhat greater than 1 but still finite.&#xD;&#xA;&#xD;&#xA;For property (b), I'm not 100% sure but I think that this is indeed guaranteed by the fact that $h_j$ is (piecewise) smooth and has a support that doesn't get arbitrarily small. The size of the filter is on the order of the pixel spacing (otherwise it doesn't work for antialiasing), so the variance within a single pixel's filter footprint can't be much more than (variance of entire image * number of pixels). You could probably formalize that with Chebyshev's inequality or some such." ContentLicense="CC BY-SA 4.0" />
  <row Id="30350" PostHistoryTypeId="2" PostId="10438" RevisionGUID="a6455470-0aee-4b17-bcf2-6f1989a2c794" CreationDate="2020-11-28T14:57:19.127" UserId="15293" Text="I have a mesh made up of several tetrahedrons, I know for sure that there are intersections between some of them: how can I remove these intersections, without generating others?&#xD;&#xA;In other terms: if between a couple of tetrahedrons there is an intersection, how can I remove it?&#xD;&#xA;&#xD;&#xA;I found these articles: the [Method of Separating Axes][1], the [Tetrahedron Overlap Algorithm][2]. &#xD;&#xA;But they are only useful for checking if there are intersections or not.   &#xD;&#xA;&#xD;&#xA;Is there an algorithm to solve this problem?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.geometrictools.com/Documentation/MethodOfSeparatingAxes.pdf&#xD;&#xA;  [2]: http://vcg.isti.cnr.it/Publications/2003/GPR03/fast_tetrahedron_tetrahedron_overlap_algorithm.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="30351" PostHistoryTypeId="1" PostId="10438" RevisionGUID="a6455470-0aee-4b17-bcf2-6f1989a2c794" CreationDate="2020-11-28T14:57:19.127" UserId="15293" Text="Is There an algorithm to remove intersections between two tetrahedrons?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30352" PostHistoryTypeId="3" PostId="10438" RevisionGUID="a6455470-0aee-4b17-bcf2-6f1989a2c794" CreationDate="2020-11-28T14:57:19.127" UserId="15293" Text="|algorithm|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30353" PostHistoryTypeId="33" PostId="10436" RevisionGUID="8cab0846-ae20-4f6f-be95-2204d03fef61" CreationDate="2020-11-28T22:43:14.273" UserDisplayName="user4801" Comment="67" />
  <row Id="30354" PostHistoryTypeId="2" PostId="10439" RevisionGUID="673a5802-5551-4885-b588-e31307ab3d76" CreationDate="2020-11-29T11:36:36.540" UserId="15297" Text="I have to admit that, while watching footage of the enhanced 2020 version of the 2018 game *Forza Horizon 4*, when they are driving fast, I have to sometimes remind myself that I am watching a video game and not a video recording of reality. It's the closest I've ever seen to photo realism, but as soon as the car stops, or they go too slowly, or they do something slightly not expected, the illusion quickly falls apart.&#xD;&#xA;&#xD;&#xA;It's just a bunch of smoke and mirrors and dead polygon objects after all. Not an actual photo-realistic 3D version of England where I can &quot;drive anywhere and do anything&quot;. But for small moments, it can fool me. Example **gameplay footage**: https://youtu.be/PqwQDRersIM?t=42&#xD;&#xA;&#xD;&#xA;What exactly is the &quot;missing piece&quot; at this point? It's impossible for me to not be impressed by the game, but I still don't want to play it. I can tell that I would very quickly get bored of the illusion, and just grow ever more frustrated by the limitations of the reality as presented in the game.&#xD;&#xA;&#xD;&#xA;For me, it's largely knowing that it's all dead 3D objects. There are no detailed rooms inside all of those buildings which I could enter and go through. There are no people either, or, if there are, they don't look or behave anything like real humans would. There are many visual details which just look &quot;off&quot;, and the more photo-realistic it looks overall, the more demanding my brain becomes and the more eager I am to point out any flaw.&#xD;&#xA;&#xD;&#xA;If you then take a look at this random **actual video**, even that game looks like garbage in comparison: https://youtu.be/FMOb5-e3J7Y?t=49 (yes, I know that the settings/locations are quite different, but that doesn't really matter).&#xD;&#xA;&#xD;&#xA;Something about reality is so much &quot;richer&quot; and &quot;real&quot; than what they can do with a 3D world, but I don't quite understand what exactly. I feel as if I should be more impressed than I actually am by that car game. It looks objectively amazing, yet at the same time, I have *very* little interest in actually playing it. And keep in mind that I'm a person who has been hunting for photo-realistic 3D simulations my entire life and who is endlessly fascinated by the concept.&#xD;&#xA;&#xD;&#xA;One thing I can say for sure: it has almost nothing to do with the resolution of the game/camera. Even if you take a very old and cheap camera and go filming reality, it will look a million times better than the 8K game.&#xD;&#xA;&#xD;&#xA;Can you explain to me why we don't have a simulation that looks and behaves just like the actual video I just linked to?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30355" PostHistoryTypeId="1" PostId="10439" RevisionGUID="673a5802-5551-4885-b588-e31307ab3d76" CreationDate="2020-11-29T11:36:36.540" UserId="15297" Text="What exactly is it about reality that is so difficult to recreate in a 3D simulation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30356" PostHistoryTypeId="3" PostId="10439" RevisionGUID="673a5802-5551-4885-b588-e31307ab3d76" CreationDate="2020-11-29T11:36:36.540" UserId="15297" Text="|3d|real-time|simulation|photo-realistic|realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30357" PostHistoryTypeId="2" PostId="10440" RevisionGUID="1a015230-b7a2-4c6e-b17c-ada853a4d919" CreationDate="2020-11-29T14:58:37.780" UserId="13095" Text="As @AnnoyinC already mentioned in his comment, we are simply lacking computational power and storage requirements (RAM). &#xD;&#xA;&#xD;&#xA;For the visual effects, you need to calculate every ray of light that somehow ends up in the observer's eye after an arbitrary number of reflections on different surfaces. The reflections depend on the surface's microstructure. This alone is so extremely demanding that is far from possible to calculate it in real-time with current consumer hardware. The first steps into this direction are already taken with ray tracing support of modern graphic cards but it is still very limited.&#xD;&#xA;And that's just the &quot;easy part&quot;. &#xD;&#xA;&#xD;&#xA;It gets way more complicated if you want to have objects and fluids that behave physically correct. While each ray of light is more or less independent of other rays, physical objects influence each other. Also, simulating the correct reaction of an arbitrary object to an external force can already take days and weeks for a single timestep/frame since you need to solve extremely large equation systems that are often non-linear. If you want to know why I would suggest searching for a &quot;Finite-Element-Method&quot; or &quot;Computational Fluid Dynamics&quot; tutorial. These techniques are commonly used by engineers and separate a structure into a mesh of smaller interacting substructures. The results get closer to the behavior of the real structure/fluid the denser the mesh. However, doubling the mesh density in each of the 3 spatial directions comes at the price of needing 8 times more computational power and RAM. Now think of a tree waving in the wind with thousands of leaves where each leaf alone is a complex physical object... I think you get the picture.&#xD;&#xA;&#xD;&#xA;To get around all these problems, a lot of approximations are used. While most of them are quite good illusions they will give wrong results at some point. However, that doesn't necessarily mean that we realize it." ContentLicense="CC BY-SA 4.0" />
  <row Id="30358" PostHistoryTypeId="50" PostId="7804" RevisionGUID="dc65d557-721b-40bf-9d30-c761b0c5fb20" CreationDate="2020-11-29T17:03:50.577" UserId="-1" />
  <row Id="30359" PostHistoryTypeId="2" PostId="10441" RevisionGUID="f789239f-c21b-466a-b225-e44d3db664bb" CreationDate="2020-11-29T18:44:41.443" UserId="15299" Text="I built a simple Ray Tracer which takes use of OpenGL's Compute Shader and traces &quot;.obj&quot; Files.&#xD;&#xA;The results are passed to the Host-Program via glMapBufferRange after finishing computing.&#xD;&#xA;From there I will output the result as png to validate the result...&#xD;&#xA;When I change the dimensions for the output the computation will obviously take longer.&#xD;&#xA;&#xD;&#xA;Now to the problem/question:&#xD;&#xA;---------&#xD;&#xA;Let's say the computation works fine with a 300x300 .png image file and I get the result I want.&#xD;&#xA;When I increase the size of the image to something like 500x500 I'll get a GL_OUT_OF_MEMORY Error after some time. And only when I try to copy data with glMapBufferRange.&#xD;&#xA;&#xD;&#xA;When I'm using a BVH-Structure to accelerate the computation it works with 500x500 and larger images within a shorter time period.&#xD;&#xA;&#xD;&#xA;So I think that the Operating System is shutting down the GPU after some time and thus resulting into a invalid Memory Access.  Not sure though.&#xD;&#xA;&#xD;&#xA;I've been using Ubuntu 20.04 for the program.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can anyone explain why I get an GL_OUT_OF_MEMORY?&#xD;&#xA;Is it more likly that I just have some Memory Leaks?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;the probably critical part of the Code:&#xD;&#xA;&#xD;&#xA;    /* Some ssbo's and glsl-program defined above */&#xD;&#xA;    	glDispatchCompute(workgroup_x, workgroup_y, 1);&#xD;&#xA;    	glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    	glBindBuffer(GL_SHADER_STORAGE_BARRIER_BIT, defined_ssbo_buffer_idx);&#xD;&#xA;        // Error occurs here when computation took around 5 sec or longer&#xD;&#xA;    	void* gpuData = glMapBufferRange(GL_SHADER_STORAGE_BARRIER_BIT, 0, size_of_buffer, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);&#xD;&#xA;    	memcpy(copyDestination, gpuData, size_of_buffer);&#xD;&#xA;        &#xD;&#xA;        glUnmapBuffer(GL_SHADER_STORAGE_BARRIER_BIT)&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BARRIER_BIT, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really appreciate any help!&#xD;&#xA;Thank you very much and have a great day!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30360" PostHistoryTypeId="1" PostId="10441" RevisionGUID="f789239f-c21b-466a-b225-e44d3db664bb" CreationDate="2020-11-29T18:44:41.443" UserId="15299" Text="GL_OUT_OF_MEMORY Error when glDispatchCompute takes longer" ContentLicense="CC BY-SA 4.0" />
  <row Id="30361" PostHistoryTypeId="3" PostId="10441" RevisionGUID="f789239f-c21b-466a-b225-e44d3db664bb" CreationDate="2020-11-29T18:44:41.443" UserId="15299" Text="|opengl|raytracing|gpu|compute-shader|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30362" PostHistoryTypeId="5" PostId="10441" RevisionGUID="7d3c8207-a912-4d94-bd93-371d965356c5" CreationDate="2020-11-30T11:54:28.467" UserId="15299" Comment="added 1 character in body" Text="I built a simple Ray Tracer which takes use of OpenGL's Compute Shader and traces &quot;.obj&quot; Files.&#xD;&#xA;The results are passed to the Host-Program via glMapBufferRange after finishing computing.&#xD;&#xA;From there I will output the result as png to validate the result...&#xD;&#xA;When I change the dimensions for the output the computation will obviously take longer.&#xD;&#xA;&#xD;&#xA;Now to the problem/question:&#xD;&#xA;---------&#xD;&#xA;Let's say the computation works fine with a 300x300 .png image file and I get the result I want.&#xD;&#xA;When I increase the size of the image to something like 500x500 I'll get a GL_OUT_OF_MEMORY Error after some time. And only when I try to copy data with glMapBufferRange.&#xD;&#xA;&#xD;&#xA;When I'm using a BVH-Structure to accelerate the computation it works with 500x500 and larger images within a shorter time period.&#xD;&#xA;&#xD;&#xA;So I think that the Operating System is shutting down the GPU after some time and thus resulting into a invalid Memory Access.  Not sure though.&#xD;&#xA;&#xD;&#xA;I've been using Ubuntu 20.04 for the program.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Can someone explain why I get an GL_OUT_OF_MEMORY?&#xD;&#xA;Is it more likly that I just have some Memory Leaks?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;the probably critical part of the Code:&#xD;&#xA;&#xD;&#xA;    /* Some ssbo's and glsl-program defined above */&#xD;&#xA;    	glDispatchCompute(workgroup_x, workgroup_y, 1);&#xD;&#xA;    	glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    	glBindBuffer(GL_SHADER_STORAGE_BARRIER_BIT, defined_ssbo_buffer_idx);&#xD;&#xA;        // Error occurs here when computation took around 5 sec or longer&#xD;&#xA;    	void* gpuData = glMapBufferRange(GL_SHADER_STORAGE_BARRIER_BIT, 0, size_of_buffer, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);&#xD;&#xA;    	memcpy(copyDestination, gpuData, size_of_buffer);&#xD;&#xA;        &#xD;&#xA;        glUnmapBuffer(GL_SHADER_STORAGE_BARRIER_BIT)&#xD;&#xA;        glBindBuffer(GL_SHADER_STORAGE_BARRIER_BIT, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I really appreciate any help!&#xD;&#xA;Thank you very much and have a great day!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30363" PostHistoryTypeId="2" PostId="10442" RevisionGUID="3f409ec8-a02f-4b04-9552-a61db11fbd23" CreationDate="2020-11-30T11:55:37.950" UserId="15305" Text="I am developing a script that will determine a minimal voxel size in a mesh. My first thought was to caculate the area of given face. Another approach would be to calculate minimal line length and maximum curvature, but I'm unsure what to do after that.&#xD;&#xA;I couldn't find anything related to that online. I was hoping someone will point me in te right direction." ContentLicense="CC BY-SA 4.0" />
  <row Id="30364" PostHistoryTypeId="1" PostId="10442" RevisionGUID="3f409ec8-a02f-4b04-9552-a61db11fbd23" CreationDate="2020-11-30T11:55:37.950" UserId="15305" Text="Calculating minimal voxel size in a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="30365" PostHistoryTypeId="3" PostId="10442" RevisionGUID="3f409ec8-a02f-4b04-9552-a61db11fbd23" CreationDate="2020-11-30T11:55:37.950" UserId="15305" Text="|mesh|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30369" PostHistoryTypeId="50" PostId="9626" RevisionGUID="ba8a73f3-6fa2-4e3b-9469-77a5fb6408a7" CreationDate="2020-11-30T12:06:50.740" UserId="-1" />
  <row Id="30370" PostHistoryTypeId="2" PostId="10444" RevisionGUID="bbc37aa9-0dce-4702-b8a2-21fdc9c7ad81" CreationDate="2020-11-30T14:22:08.963" UserId="159" Text="One of the thing that breaks the illusion in that video for me is the cinematography. During the fast moments, the camera is more physically plausible, in that it could have been filmed from a camera mounted to a vehicle following the hero car. When stopped, the player moves the third-person camera around in a way that doesn't mimic physical camera rigs.&#xD;&#xA;&#xD;&#xA;It's also worth noting that motion blur is blur, and the loss of resolution caused by high speed motion covers up a lot of sins." ContentLicense="CC BY-SA 4.0" />
  <row Id="30371" PostHistoryTypeId="50" PostId="9307" RevisionGUID="bc3ee203-7163-4e90-9d5c-61e13ead9ba9" CreationDate="2020-11-30T19:01:15.233" UserId="-1" />
  <row Id="30372" PostHistoryTypeId="2" PostId="10445" RevisionGUID="5eb59db3-a5dc-491f-a46a-c933679a261f" CreationDate="2020-11-30T21:53:36.240" UserId="15306" Text="I have the following .fx file for my shader:&#xD;&#xA;&#xD;&#xA;    // Parameters that should be set from the program&#xD;&#xA;    float4x4 World; // World Matrix&#xD;&#xA;    float4x4 View; // View Matrix&#xD;&#xA;    float4x4 Projection; // Projection Matrix&#xD;&#xA;    float3 LightPosition; // in world space&#xD;&#xA;    float3 CameraPosition; // in world space&#xD;&#xA;    float Shininess; // scalar value&#xD;&#xA;    float3 AmbientColor;&#xD;&#xA;    float3 DiffuseColor;&#xD;&#xA;    float3 SpecularColor;&#xD;&#xA;    texture DiffuseTexture;&#xD;&#xA;    &#xD;&#xA;    sampler DiffuseSampler = sampler_state&#xD;&#xA;    {&#xD;&#xA;    	Texture = &lt;DiffuseTexture&gt;;&#xD;&#xA;    	AddressU = Wrap;&#xD;&#xA;    	AddressV = Wrap;&#xD;&#xA;    };&#xD;&#xA;    // We create structs to help us manage the inputs/outputs&#xD;&#xA;    // to vertex and pixel shaders&#xD;&#xA;    struct VertexInput&#xD;&#xA;    {&#xD;&#xA;        float4 Position : POSITION0; // Here, POSITION0 and NORMAL0&#xD;&#xA;    	float3 Normal : NORMAL0; // are called mnemonics&#xD;&#xA;    	float2 UV: TEXCOORD0;&#xD;&#xA;    };&#xD;&#xA;    // --- Per Vertex technique - Gouraud&#xD;&#xA;    // We will create an output struct for this technique&#xD;&#xA;    struct GouraudVertexOutput&#xD;&#xA;    {&#xD;&#xA;        float4 Position : POSITION0;&#xD;&#xA;    	float3 Color : COLOR0;&#xD;&#xA;    };&#xD;&#xA;    // The Vertex shader&#xD;&#xA;    // We will perform all the lighting calculations here&#xD;&#xA;    GouraudVertexOutput GouraudVertex(VertexInput input)&#xD;&#xA;    {&#xD;&#xA;    	GouraudVertexOutput output; // create the output struct&#xD;&#xA;    	// First, do the transformations&#xD;&#xA;        float4 worldPosition = mul(input.Position, World);&#xD;&#xA;        float4 viewPosition = mul(worldPosition, View);&#xD;&#xA;        output.Position = mul(viewPosition, Projection);&#xD;&#xA;    	// Now do the lighting computation. First calculate the directions&#xD;&#xA;    	float3 lightDirection = normalize(LightPosition - worldPosition.xyz);&#xD;&#xA;    	float3 viewDirection = normalize(CameraPosition - worldPosition.xyz);&#xD;&#xA;    	float3 worldNormal = mul(input.Normal, World);&#xD;&#xA;    	float3 reflectDirection = -reflect(lightDirection, worldNormal);&#xD;&#xA;    	// Now compute the light components&#xD;&#xA;    	float diffuse = max(dot(lightDirection, worldNormal), 0);&#xD;&#xA;    	float specular = pow(max(dot(reflectDirection, viewDirection), 0), Shininess);&#xD;&#xA;    	// Finally, save the color to the output struct&#xD;&#xA;    	output.Color = AmbientColor + diffuse * DiffuseColor + specular * SpecularColor;&#xD;&#xA;        return output;&#xD;&#xA;    }&#xD;&#xA;    // The Pixel Shader&#xD;&#xA;    // All this function does is to pass through the color through &#xD;&#xA;    float4 GouraudPixel(GouraudVertexOutput input) : COLOR0&#xD;&#xA;    {&#xD;&#xA;        return float4(input.Color, 1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // --- Per Pixel techniques - Phong, Blinn, Schlick&#xD;&#xA;    // We will need a different output struct for this&#xD;&#xA;    struct PhongVertexOutput&#xD;&#xA;    {&#xD;&#xA;    	float4 Position : POSITION0;&#xD;&#xA;    	float2 UV: TEXCOORD0;&#xD;&#xA;    	float4 WorldPosition : TEXCOORD1;&#xD;&#xA;    	float3 WorldNormal : TEXCOORD2;&#xD;&#xA;    };&#xD;&#xA;    // A common vertex shader for all the different techniques&#xD;&#xA;    PhongVertexOutput PhongVertex(VertexInput input)&#xD;&#xA;    {&#xD;&#xA;    	PhongVertexOutput output;&#xD;&#xA;    	// Do the transformations as before&#xD;&#xA;    	// Save the world position for use in the pixel shader&#xD;&#xA;    	output.WorldPosition = mul(input.Position, World);&#xD;&#xA;    	float4 viewPosition = mul(output.WorldPosition, View);&#xD;&#xA;    	output.Position = mul(viewPosition, Projection);&#xD;&#xA;    	// as well as the normal in world space&#xD;&#xA;    	output.WorldNormal = mul(input.Normal, World);&#xD;&#xA;    	output.UV = input.UV * 10;&#xD;&#xA;    	return output;&#xD;&#xA;    }&#xD;&#xA;    // The pixel shader performs the lighting&#xD;&#xA;    float4 PhongPixel(PhongVertexOutput input) : COLOR0&#xD;&#xA;    {&#xD;&#xA;    	// The lighting operation, same as in the Gouraud vertex method&#xD;&#xA;    	float3 lightDirection = normalize(LightPosition - input.WorldPosition.xyz);&#xD;&#xA;    	float3 viewDirection = normalize(CameraPosition - input.WorldPosition.xyz);&#xD;&#xA;    	// Need to normalize my incoming normal, length could be less than 1&#xD;&#xA;    	input.WorldNormal = normalize(input.WorldNormal);&#xD;&#xA;    	float3 reflectDirection = -reflect(lightDirection, input.WorldNormal);&#xD;&#xA;    	// Now, compute the lighint components&#xD;&#xA;    	float diffuse = max(dot(lightDirection, input.WorldNormal), 0) * tex2D(DiffuseSampler, input.UV);&#xD;&#xA;    	float specular = pow(max(dot(reflectDirection, viewDirection), 0), Shininess);&#xD;&#xA;    	return float4(AmbientColor + diffuse * DiffuseColor + specular * SpecularColor, 1);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Now the different techniques&#xD;&#xA;    technique Gouraud&#xD;&#xA;    {&#xD;&#xA;        pass Pass1&#xD;&#xA;        {&#xD;&#xA;    		VertexShader = compile vs_4_0 GouraudVertex();&#xD;&#xA;    		PixelShader = compile ps_4_0 GouraudPixel();&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    technique Phong&#xD;&#xA;    {&#xD;&#xA;    	pass Pass1&#xD;&#xA;    	{&#xD;&#xA;    		VertexShader = compile vs_4_0 PhongVertex();&#xD;&#xA;    		PixelShader = compile ps_4_0 PhongPixel();&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What I'm trying to do is change this file so that the 3D objects I apply it to are green in color. What parts of the above code do I need to change in order to do this? I am using the Monogame software in Visual Studio (c# coding language). Any help would be greatly appreciated!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30373" PostHistoryTypeId="1" PostId="10445" RevisionGUID="5eb59db3-a5dc-491f-a46a-c933679a261f" CreationDate="2020-11-30T21:53:36.240" UserId="15306" Text="Changing shader color" ContentLicense="CC BY-SA 4.0" />
  <row Id="30374" PostHistoryTypeId="3" PostId="10445" RevisionGUID="5eb59db3-a5dc-491f-a46a-c933679a261f" CreationDate="2020-11-30T21:53:36.240" UserId="15306" Text="|3d|shader|shading|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30375" PostHistoryTypeId="2" PostId="10446" RevisionGUID="65818c49-17ac-4a0e-a0c9-38fde689188f" CreationDate="2020-12-01T10:34:40.743" UserId="15310" Text="I'm working on a simple software renderer and have a working implementation so far. I'm curious as to why it's actually working since I would expect the multiplication ordering for my world, view and projection matrices to be reversed. When working with DirectX and OpenGL in the past I have multiplied them as projection * view * world, but with my implementation it's working with worldMatrix * viewMatrix * projectionMatrix. Some code:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void SceneRenderer::DrawMesh(Mesh&amp; mesh, const SRGraphicsContext&amp; gfx)&#xD;&#xA;{&#xD;&#xA;	const Mat4x4f&amp; worldMatrix = mesh.GetWorldMatrix();&#xD;&#xA;	const Mat4x4f&amp; viewMatrix = camera-&gt;GetViewMatrix();&#xD;&#xA;	const Mat4x4f&amp; projectionMatrix = camera-&gt;GetProjectionMatrix();&#xD;&#xA;	const Mat4x4f&amp; wvp = worldMatrix * viewMatrix * projectionMatrix;&#xD;&#xA;&#xD;&#xA;	const Vert3df&amp; cameraPos = camera-&gt;GetPosition();&#xD;&#xA;&#xD;&#xA;	const float screenWidth = static_cast&lt;float&gt;(gfx.frameBuffer-&gt;GetWidth());&#xD;&#xA;	const float screenHeight = static_cast&lt;float&gt;(gfx.frameBuffer-&gt;GetHeight());&#xD;&#xA;&#xD;&#xA;	Tri2di rasterTri;&#xD;&#xA;	for (Tri3df&amp; tri : mesh.GetTriangles())&#xD;&#xA;	{&#xD;&#xA;		Vert4df p1c =  Vert4df(tri.p1, 1),&#xD;&#xA;				p2c = Vert4df(tri.p2, 1),&#xD;&#xA;				p3c = Vert4df(tri.p3, 1);&#xD;&#xA;&#xD;&#xA;		p1c = wvp * p1c;&#xD;&#xA;		p2c = wvp * p2c;&#xD;&#xA;		p3c = wvp * p3c;&#xD;&#xA;		&#xD;&#xA;		p1c.DivideByW();&#xD;&#xA;		p2c.DivideByW();&#xD;&#xA;		p3c.DivideByW();&#xD;&#xA;&#xD;&#xA;		rasterTri.p1.x = static_cast&lt;int&gt;((p1c.x + 1.0f) / 2.0f * screenWidth);&#xD;&#xA;		rasterTri.p1.y = static_cast&lt;int&gt;((p1c.y + 1.0f) / 2.0f * screenHeight);&#xD;&#xA;&#xD;&#xA;		rasterTri.p2.x = static_cast&lt;int&gt;((p2c.x + 1.0f) / 2.0f * screenWidth);&#xD;&#xA;		rasterTri.p2.y = static_cast&lt;int&gt;((p2c.y + 1.0f) / 2.0f * screenHeight);&#xD;&#xA;&#xD;&#xA;		rasterTri.p3.x = static_cast&lt;int&gt;((p3c.x + 1.0f) / 2.0f * screenWidth);&#xD;&#xA;		rasterTri.p3.y = static_cast&lt;int&gt;((p3c.y + 1.0f) / 2.0f * screenHeight);&#xD;&#xA;&#xD;&#xA;		rasterizer-&gt;DrawTriangle(rasterTri, gfx);&#xD;&#xA;	}&#xD;&#xA;```&#xD;&#xA;Any idea why the ordering might be reversed in my case? I've compared my Mat4x4f implementation to DirectX's XMMAtrix and get the same results when multiplying 2 arbitrary matrices." ContentLicense="CC BY-SA 4.0" />
  <row Id="30376" PostHistoryTypeId="1" PostId="10446" RevisionGUID="65818c49-17ac-4a0e-a0c9-38fde689188f" CreationDate="2020-12-01T10:34:40.743" UserId="15310" Text="Model View Projection Matrix Multiplcation Order" ContentLicense="CC BY-SA 4.0" />
  <row Id="30377" PostHistoryTypeId="3" PostId="10446" RevisionGUID="65818c49-17ac-4a0e-a0c9-38fde689188f" CreationDate="2020-12-01T10:34:40.743" UserId="15310" Text="|transformations|mathematics|projections|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30378" PostHistoryTypeId="34" PostId="10417" RevisionGUID="64fce988-c2d5-4fbc-8317-f75f090813a3" CreationDate="2020-12-01T18:02:45.643" UserId="-1" Comment="66" />
  <row Id="30379" PostHistoryTypeId="2" PostId="10447" RevisionGUID="5608ab66-133f-42a5-9d70-9d0e8d983dad" CreationDate="2020-12-01T20:13:06.497" UserId="8807" Text="Let me first state what I think I know and please correct me if I'm too inaccurate or plainly wrong.&#xD;&#xA;&#xD;&#xA;When you use a function like [texture][1], you're requesting a texel value given a pair (u,v) of texture parameters. However, depending on the pixel size / texel size ratio, there's a filtering and resampling prior to returning the texel value, which you can actually configure in the corresponding API (OpenGL, Vulkan, etc).&#xD;&#xA;&#xD;&#xA;As I understand it, this filtering and resampling occurs because either:&#xD;&#xA;&#xD;&#xA;a) Many texels affect a pixel. This happens because the texture resolution is too low for the area on screen to be covered (i.e. the pixel resolution). So in order to avoid artifacts, the texture needs to be downsampled, which consists of applying a minification filter and resampling at a lower rate.  &#xD;&#xA;&#xD;&#xA;b) The same texel can affect many pixels. The texture resolution is bigger than the pixel resolution. In this case, a magnification filter is used and the texture is upsampled.&#xD;&#xA;&#xD;&#xA;Assuming the above explanations are correct, my question is: how does the GPU know which of these two scenarios are happening.&#xD;&#xA;&#xD;&#xA;I reckon that it does by projecting the pixel area in texture space, as it is done for selecting the mipmap level. But even if that's the answer, how is this projection achieved? I'm failing to visualize it.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/texture.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="30380" PostHistoryTypeId="1" PostId="10447" RevisionGUID="5608ab66-133f-42a5-9d70-9d0e8d983dad" CreationDate="2020-12-01T20:13:06.497" UserId="8807" Text="How does the GPU know whether to magnify/minify?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30381" PostHistoryTypeId="3" PostId="10447" RevisionGUID="5608ab66-133f-42a5-9d70-9d0e8d983dad" CreationDate="2020-12-01T20:13:06.497" UserId="8807" Text="|texture|sampling|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30382" PostHistoryTypeId="5" PostId="10447" RevisionGUID="b3411ffc-7470-412a-8840-2c0525e27506" CreationDate="2020-12-01T20:19:30.327" UserId="8807" Comment="edited body" Text="Let me first state what I think I know and please correct me if I'm too inaccurate or plainly wrong.&#xD;&#xA;&#xD;&#xA;When you use a function like [texture][1], you're requesting a texel value given a pair (u,v) of texture parameters. However, depending on the pixel size / texel size ratio, there's a filtering and resampling prior to returning the texel value, which you can actually configure in the corresponding API (OpenGL, Vulkan, etc).&#xD;&#xA;&#xD;&#xA;As I understand it, this filtering and resampling occurs because either:&#xD;&#xA;&#xD;&#xA;a) Many texels affect a pixel. This happens because the texture resolution is too high for the area on screen to be covered (i.e. the pixel resolution). So in order to avoid artifacts, the texture needs to be downsampled, which consists of applying a minification filter and resampling at a lower rate.  &#xD;&#xA;&#xD;&#xA;b) The same texel can affect many pixels. The texture resolution is lower than the pixel resolution. In this case, a magnification filter is used and the texture is upsampled.&#xD;&#xA;&#xD;&#xA;Assuming the above explanations are correct, my question is: how does the GPU know which of these two scenarios are happening.&#xD;&#xA;&#xD;&#xA;I reckon that it does by projecting the pixel area in texture space, as it is done for selecting the mipmap level. But even if that's the answer, how is this projection achieved? I'm failing to visualize it.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/texture.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="30383" PostHistoryTypeId="2" PostId="10448" RevisionGUID="9f86ea85-555e-4619-87e4-9f2a6a496cf7" CreationDate="2020-12-01T20:55:22.450" UserId="48" Text="Minification vs magnification is an extension of mipmap selection. When you calculate the desired mip level, it can come out to be less than 0 (or in general, less than the sampler's configured minimum LOD). In that case you're doing magnification of the lowest mip level. If the desired level comes out to a value greater than 0 then you're doing minification.&#xD;&#xA;&#xD;&#xA;Mipmap selection works by calculating differences of the UV coordinates between adjacent pixels on screen (see [shader derivative functions](http://www.aclockworkberry.com/shader-derivative-functions/)). Since the GPU is always shading pixels in 2×2 quads, it can look at the set of UVs input to the sampling operation across all those pixels. Those derivative vectors establish what the pixel footprint in texel space is, and their lengths are used to calculate which mip level to sample.&#xD;&#xA;&#xD;&#xA;The details of how these calculations work exactly can be found in [the OpenGL spec, section 8.14 &quot;Texture Minification&quot;](https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf#section.8.14)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30385" PostHistoryTypeId="2" PostId="10450" RevisionGUID="f0c6ed2d-3003-4d8d-96fe-1bf43dfe1503" CreationDate="2020-12-02T06:28:58.240" UserId="9169" Text="There are some 3D applications which can cast shadow or silhouette below 3D models. They render pretty fast and smooth. I wonder what kind of technology is the standard procedure to get 3D model shadow/silhouette.&#xD;&#xA;&#xD;&#xA;For example is there any C++ library like [libigl](https://github.com/libigl/libigl) or [CGAL](https://github.com/CGAL/cgal) to get shadow/silhouette pretty fast? Or maybe GLSL shading is used? Any hint would be appreciated on the standard technology stack.&#xD;&#xA;&#xD;&#xA;[![Screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9QPWG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30386" PostHistoryTypeId="1" PostId="10450" RevisionGUID="f0c6ed2d-3003-4d8d-96fe-1bf43dfe1503" CreationDate="2020-12-02T06:28:58.240" UserId="9169" Text="Silhouette below 3D model" ContentLicense="CC BY-SA 4.0" />
  <row Id="30387" PostHistoryTypeId="3" PostId="10450" RevisionGUID="f0c6ed2d-3003-4d8d-96fe-1bf43dfe1503" CreationDate="2020-12-02T06:28:58.240" UserId="9169" Text="|3d|computational-geometry|mesh|shadow|silhouette|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30391" PostHistoryTypeId="12" PostId="10450" RevisionGUID="6d5dddbe-e964-4ff6-bd2d-792cb0c5ffb1" CreationDate="2020-12-02T07:40:19.690" UserId="9169" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:9169,&quot;DisplayName&quot;:&quot;user3405291&quot;}]}" />
  <row Id="30392" PostHistoryTypeId="13" PostId="10450" RevisionGUID="b5f76e3a-05bd-4993-94a3-c2f868511cc0" CreationDate="2020-12-02T07:41:29.610" UserId="9169" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:9169,&quot;DisplayName&quot;:&quot;user3405291&quot;}]}" />
  <row Id="30395" PostHistoryTypeId="2" PostId="10452" RevisionGUID="5a5a7c1a-29c6-4503-b933-e5b780571ac3" CreationDate="2020-12-02T13:35:31.493" UserDisplayName="user15232" Text="In a particle simulation, I am rendering particles as &quot;spheres&quot; using GL_POINTS instead of a mesh for efficiency. With `glEnable(GL_PROGRAM_POINT_SIZE)` I can use `gl_PointSize` from the vertex shader to set the size of my resulting 2D point in screen space pixels.&#xD;&#xA;&#xD;&#xA;I have the projection matrix, view matrix and the particle position in my vertex shader.&#xD;&#xA;&#xD;&#xA;My current approach has been&#xD;&#xA;&#xD;&#xA;    vec4 pos = proj * view * vec4(position, 1.0);&#xD;&#xA;    gl_PointSize = POINT_RADIUS / pos.w;&#xD;&#xA;&#xD;&#xA;, which works, but `POINT_RADIUS` is not in world space, but rather the pixel size on my near plane (of the perspective projection).&#xD;&#xA;&#xD;&#xA;How would I calculate the point size in screen space from a given radius in world space? I can only think of kinda hacky solutions. Is there some mathematically clean or obvious approach to this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30396" PostHistoryTypeId="1" PostId="10452" RevisionGUID="5a5a7c1a-29c6-4503-b933-e5b780571ac3" CreationDate="2020-12-02T13:35:31.493" UserDisplayName="user15232" Text="What is the best way to calculate the projected size of a point" ContentLicense="CC BY-SA 4.0" />
  <row Id="30397" PostHistoryTypeId="3" PostId="10452" RevisionGUID="5a5a7c1a-29c6-4503-b933-e5b780571ac3" CreationDate="2020-12-02T13:35:31.493" UserDisplayName="user15232" Text="|shader|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30398" PostHistoryTypeId="50" PostId="9303" RevisionGUID="6580c88f-b62f-4580-87b8-60ab105c058d" CreationDate="2020-12-02T15:04:25.460" UserId="-1" />
  <row Id="30399" PostHistoryTypeId="2" PostId="10453" RevisionGUID="58d556d7-4c03-4fc2-973c-ac303f840bb3" CreationDate="2020-12-02T15:29:17.403" UserId="15320" Text="I am a new learner in 3d graphics. So forgive me if I seem to ask something very basic. I am confused how obj files are textured. So far I have seen:&#xD;&#xA;&#xD;&#xA;- obj + jpg&#xD;&#xA;- obj + mtl + jpg&#xD;&#xA;&#xD;&#xA;When I look online, most say that they are textured by UV mapping. But when I look into the files, I find no specification of the UV mappings, i.e. how to map a pixel in the jpg file to a vertex (or maybe face?) in the obj file? I suppose there is some rule that is used by default. But I really need to know what it is.&#xD;&#xA;&#xD;&#xA;Any reference, such as official documents, blogs, textbooks, online learning materials would be of great help. Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30400" PostHistoryTypeId="1" PostId="10453" RevisionGUID="58d556d7-4c03-4fc2-973c-ac303f840bb3" CreationDate="2020-12-02T15:29:17.403" UserId="15320" Text="How are obj files textured?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30401" PostHistoryTypeId="3" PostId="10453" RevisionGUID="58d556d7-4c03-4fc2-973c-ac303f840bb3" CreationDate="2020-12-02T15:29:17.403" UserId="15320" Text="|3d|texture|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30402" PostHistoryTypeId="2" PostId="10454" RevisionGUID="42ddee73-7f88-4fcf-b5ff-1c0c27b1d1e7" CreationDate="2020-12-02T16:34:44.530" UserId="15321" Text="I have a question regarding how the Gaussian blur works. A pixel consists on the combination of 3 colors: R,G and B. I have read that the Gaussian kernel is multiplied by the input image &#xD;&#xA;by placing the center pixel of the kernel on the image pixel and multiplying the values in the original image with the pixels in the kernel that overlap. What I am not sure about is how the multiplication is carried out. For instance, lets suppose the pixel is composed as follows(I have chosen arbitrary numbers):&#xD;&#xA;&#xD;&#xA;R: 10100010&#xD;&#xA;G: 01000110&#xD;&#xA;B: 10001110&#xD;&#xA;&#xD;&#xA;My question is how the multiplication implemented:&#xD;&#xA;1- The three colors are &quot;concatenated&quot; meaning that the value in the kernel is multiplied by the concatenation of R,G and B. In this case the concatenation would be 10100010 01000110 10001110&#xD;&#xA;2- Multiply the value of each color independently by the kernel. This would imply multiplying first R by the kernel, then G by the kernel and then B by the kernel. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30403" PostHistoryTypeId="1" PostId="10454" RevisionGUID="42ddee73-7f88-4fcf-b5ff-1c0c27b1d1e7" CreationDate="2020-12-02T16:34:44.530" UserId="15321" Text="How is the multiplication in Gaussian Blur implemented" ContentLicense="CC BY-SA 4.0" />
  <row Id="30404" PostHistoryTypeId="3" PostId="10454" RevisionGUID="42ddee73-7f88-4fcf-b5ff-1c0c27b1d1e7" CreationDate="2020-12-02T16:34:44.530" UserId="15321" Text="|image-processing|gaussian-blur|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30405" PostHistoryTypeId="2" PostId="10455" RevisionGUID="a7ceedb1-a4ed-450e-83e2-b0f6925fe713" CreationDate="2020-12-02T18:40:15.117" UserId="506" Text="Each color is conceptually treated independently. If they were concatenated, multiplying a value with a color close to the maximum possible value for one channel could cause it to overflow into the lower bits of the next.&#xD;&#xA;&#xD;&#xA;That said, if you’re asking for performance purposes, a lot of the hardware that does this kind of work can perform all of the per-channel multiplies in a single operation." ContentLicense="CC BY-SA 4.0" />
  <row Id="30406" PostHistoryTypeId="2" PostId="10456" RevisionGUID="6307b0ab-5ae2-4917-997d-d168740a7c8f" CreationDate="2020-12-02T18:52:01.127" UserId="48" Text="If you look closely at the edge of the sphere, in the first image it is sharp, and in the second image it's blurry, blending into the background color. This suggests to me that it's not the texture, but the ray distribution on the image plane that's the issue. The second image might be distributing rays over a larger area per pixel, for instance by using a wider AA filter, or a wider lens aperture (defocus blur)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30407" PostHistoryTypeId="2" PostId="10457" RevisionGUID="fd35ea4a-6521-4436-a279-86eeb2c073f3" CreationDate="2020-12-02T22:11:02.063" UserId="48" Text="OBJ files typically contain vertex positions, texture coordinates (also known as UVs), and normals, as well as face data. There are other kinds of things they can contain but those are the most common (see [here](http://paulbourke.net/dataformats/obj/) for a fuller specification).&#xD;&#xA;&#xD;&#xA;Vertex positions are specified with the `v` command, texture coordinates with `vt`, and normals with `vn`. The faces then reference those values by index using something like `f 1/2/3 4/5/6 7/8/9`, where each grouping of values represents a vertex on the face, and the numbers separated by slashes are the position/texture/normal indices.&#xD;&#xA;&#xD;&#xA;The texture coordinates are the part that tell you what point in the texture image (jpg) goes with that vertex. If you've downloaded or exported a model that has a texture mapping, you should be able to see those `vt` commands in the obj file." ContentLicense="CC BY-SA 4.0" />
  <row Id="30408" PostHistoryTypeId="5" PostId="10457" RevisionGUID="65e525bd-1a8d-4431-ad1e-aaba7a6d376b" CreationDate="2020-12-02T22:20:18.703" UserId="48" Comment="added 373 characters in body" Text="OBJ files typically contain vertex positions, texture coordinates (also known as UVs), and normals, as well as face data. There are other kinds of things they can contain but those are the most common (see [here](http://paulbourke.net/dataformats/obj/) for a fuller specification).&#xD;&#xA;&#xD;&#xA;Vertex positions are specified with the `v` command, texture coordinates with `vt`, and normals with `vn`. The faces then reference those values by index using something like `f 1/2/3 4/5/6 7/8/9`, where each grouping of values represents a vertex on the face, and the numbers separated by slashes are the position/texture/normal indices.&#xD;&#xA;&#xD;&#xA;The texture coordinates are the part that tell you what point in the texture image (jpg) goes with that vertex. If you've downloaded or exported a model that has a texture mapping, you should be able to see those `vt` commands in the obj file.&#xD;&#xA;&#xD;&#xA;If a model doesn't have texture coordinates, though, then it most likely needs the help of a human 3D modeler. It is not easy to create usable texture coordinates for a model automatically (this is a big research topic). 3D modeling applications have various tools to help the modeler set up a texture layout, but it still usually needs some hand-tweaking to work well." ContentLicense="CC BY-SA 4.0" />
  <row Id="30409" PostHistoryTypeId="50" PostId="9178" RevisionGUID="4677c4ca-9e55-4072-8abc-774f0bd77105" CreationDate="2020-12-03T00:06:15.610" UserId="-1" />
  <row Id="30410" PostHistoryTypeId="5" PostId="10453" RevisionGUID="d4196d5e-4fe1-4245-9f41-77eb2f29e06b" CreationDate="2020-12-03T06:11:24.860" UserId="15320" Comment="added 949 characters in body" Text="I am a new learner in 3d graphics. So forgive me if I seem to ask something very basic. I am confused how obj files are textured. So far I have seen:&#xD;&#xA;&#xD;&#xA;- obj + jpg&#xD;&#xA;- obj + mtl + jpg&#xD;&#xA;&#xD;&#xA;When I look online, most say that they are textured by UV mapping. But when I look into the files, I find no specification of the UV mappings, i.e. how to map a pixel in the jpg file to a vertex (or maybe face?) in the obj file? I suppose there is some rule that is used by default. But I really need to know what it is.&#xD;&#xA;&#xD;&#xA;Any reference, such as official documents, blogs, textbooks, online learning materials would be of great help. Thanks!&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**Update**&#xD;&#xA;I came across an example [here][1], called &quot;texture mapped square&quot;&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;# A 2 x 2 square mapped with a 1 x 1 square&#xD;&#xA;# texture stretched to fit the square exactly.&#xD;&#xA;mtllib master.mtl&#xD;&#xA;v  0.000000 2.000000 0.000000&#xD;&#xA;v  0.000000 0.000000 0.000000&#xD;&#xA;v  2.000000 0.000000 0.000000&#xD;&#xA;v  2.000000 2.000000 0.000000&#xD;&#xA;vt 0.000000 1.000000 0.000000&#xD;&#xA;vt 0.000000 0.000000 0.000000&#xD;&#xA;vt 1.000000 0.000000 0.000000&#xD;&#xA;vt 1.000000 1.000000 0.000000&#xD;&#xA;# 4 vertices&#xD;&#xA;usemtl wood&#xD;&#xA;# The first number is the point,&#xD;&#xA;# then the slash,&#xD;&#xA;# and the second is the texture point&#xD;&#xA;f 1/1 2/2 3/3 4/4&#xD;&#xA;# 1 element&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I assume that the coordinates following `vt` commands are the UV coordinates of the corresponding pixels in the texture image. Exactly what do the values mean? Are they normalized coordinates, that is, is the image normalized to have a coordinate system [0,1]x[0,1]?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.fileformat.info/format/wavefrontobj/egff.htm" ContentLicense="CC BY-SA 4.0" />
  <row Id="30411" PostHistoryTypeId="5" PostId="8270" RevisionGUID="25e3fd25-1474-4de8-9afc-3e6556228253" CreationDate="2020-12-03T08:57:55.350" UserId="209" Comment="Whoops! Mistyped the M^−1_UB*MCR  matrix!" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, i.e. a *total* of $4n-12$ control points , but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the correct matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; -2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;-4 &amp; 13 &amp; -26 &amp; 11\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;First consider trying to go from BSpline to CR. If we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\begin{bmatrix}CR_0\\CR_1\\ ...\\CR_{n-1} \end{bmatrix} = M_{NxBtoCR}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;M_{NxBtoCR}= \frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;If we invert that matrix to get $M_{NxBtoCR}^{-1}$, one should then be able to map the other way. &#xD;&#xA;&#xD;&#xA;Using a maths package such as Maple, one finds that each row of $M_{NxBtoCR}^{-1}$ consists of the same set of values, all non-zero, which are progressively offset in each row. If we ignore the smaller terms, it suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;.&#xD;&#xA;&#xD;&#xA;*Update* Those weights don't *quite* sum to 1.0 - you'll need to normalise them slightly.&#xD;&#xA;&#xD;&#xA;Obviously, this has assumed the curve is a loop. It's probably possible to adjust the weights for the end points but I'll leave that as an exercise for the reader." ContentLicense="CC BY-SA 4.0" />
  <row Id="30412" PostHistoryTypeId="5" PostId="8270" RevisionGUID="1a8a1eb7-16e8-4f2e-a2d1-915a7c76d7e2" CreationDate="2020-12-03T09:05:43.413" UserId="209" Comment="Added note for coefficient fix" Text="Quoting the comments above for context:&#xD;&#xA;&gt; Just to confirm, are you asking, given a set of $N$ CatRom control points, &#xD;&#xA;$$\{CR_0, CR_1, CR_2, CR_3 ... CR_{n-1}\}$$&#xD;&#xA; forming a piecewise curve, what is the equivalent $N$ points, $$\{B_0,B_1,B_2...B_{n-1}\}$$ for a matching piecewise uniform cubic bspline?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;*Exactly. That is what I'm looking for. I think conversion to cubic bezier's are easy. But I would like to know if this is even possible/doable with bsplines*&#xD;&#xA;&#xD;&#xA;I think it's a bit complicated: Using the approach you described above, i.e. $$ V_{targetformat} = M_{targetformat}^{-1} . M_{sourceformat}.V_{sourceformat}$$&#xD;&#xA;you can easily go from a sequence of $n$ control points of Catmull-Rom to  $(n-3)$ *sets* of 4 Uniform BSpline control points, i.e. a *total* of $4n-12$ control points , but I can't see that this will allow you to stitch them together to obtain just $n$ points...&#xD;&#xA;&#xD;&#xA;_Assuming_ I've got the correct matrices for the 'typical' Catmull-Rom,&#xD;&#xA;$$M_{CR}=\frac{1}{2}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;2 &amp; -5 &amp; 4 &amp; -1 \\&#xD;&#xA;-1 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 2 &amp; 0 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;and uniform B-Spline:&#xD;&#xA;$$M_{UB}=\frac{1}{6}\begin{bmatrix} &#xD;&#xA;-1 &amp; 3 &amp; -3 &amp; 1\\&#xD;&#xA;3 &amp; -6 &amp; 3 &amp; 0 \\&#xD;&#xA;-3 &amp; 0 &amp; 3 &amp; 0 \\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;then $M^{-1}_{UB}.M_{CR}$ should be &lt;br/&gt;&#xD;&#xA;*[UPDATE: Fixed errors in coefficents]*&#xD;&#xA;$$\frac{1}{6}\begin{bmatrix} &#xD;&#xA;7 &amp; -4 &amp; 5 &amp; -2\\&#xD;&#xA;-2 &amp; 11 &amp; -4 &amp; 1 \\&#xD;&#xA;1 &amp; -4 &amp; 11 &amp; -2 \\&#xD;&#xA;-4 &amp; 13 &amp; -26 &amp; 11\\&#xD;&#xA; \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;It seems to me that, in any batch of four points, every output vertex thus depends on *every* input vertex, so it seems the neighbouring points can't be shared.&#xD;&#xA;&#xD;&#xA;Having said this, I think perhaps there *might* be a way of getting an *approximate* solution (but I've not tried rendering it myself to check it so take with a grain of salt) &#xD;&#xA;&#xD;&#xA;We know that a Catmull-Rom spline defined by $(CR_A, CR_B, CR_C, CR_D)$, passes through $CR_B$ and $CR_C$ at t=0 and t=1 respectively.&#xD;&#xA;&#xD;&#xA;Similarly, using $\begin{bmatrix}t^3 &amp; t^2 &amp; t &amp; 1\end{bmatrix}.M_{UB}$, we should see that at t=0 and t=1, a B-spline passes through $\frac{B_A + 4 B_B + B_C}{6}$ and $\frac{B_B + 4 B_C + B_D}{6}$.&#xD;&#xA;&#xD;&#xA;First consider trying to go from BSpline to CR. If we had a 'loop' formed by N control points one would map from BSpline to CR with...&#xD;&#xA;$$\begin{bmatrix}CR_0\\CR_1\\ ...\\CR_{n-1} \end{bmatrix} = M_{NxBtoCR}.\begin{bmatrix}B_0\\B_1\\ ...\\B_{n-1} \end{bmatrix}$$&#xD;&#xA;where&#xD;&#xA;$$&#xD;&#xA;M_{NxBtoCR}= \frac{1}{6}.\begin{bmatrix}&#xD;&#xA;4 &amp; 1 &amp; 0 &amp; 0 &amp; ... &amp; 0 &amp; 1\\&#xD;&#xA;1 &amp; 4 &amp; 1 &amp; 0 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 1 &amp; 4 &amp; 1 &amp; ... &amp; 0 &amp; 0\\&#xD;&#xA;: &amp; : &amp;   &amp;   &amp; ... &amp; : &amp; :\\&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 &amp; ... &amp; 1 &amp; 4\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;If we invert that matrix to get $M_{NxBtoCR}^{-1}$, one should then be able to map the other way. &#xD;&#xA;&#xD;&#xA;Using a maths package such as Maple, one finds that each row of $M_{NxBtoCR}^{-1}$ consists of the same set of values, all non-zero, which are progressively offset in each row. If we ignore the smaller terms, it suggests that $$B_i \approx 1.732 CR_i -0.464 (CR_{i-1}+CR_{i+1}) + 0.1243 (CR_{i-2}+CR_{i+2}) - 0.033(CR_{i-3}+CR_{i+3}) $$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There's probably some nice algebraic expression for this but I hope this might &quot;do the trick&quot;.&#xD;&#xA;&#xD;&#xA;*Update* Those weights don't *quite* sum to 1.0 - you'll need to normalise them slightly.&#xD;&#xA;&#xD;&#xA;Obviously, this has assumed the curve is a loop. It's probably possible to adjust the weights for the end points but I'll leave that as an exercise for the reader." ContentLicense="CC BY-SA 4.0" />
  <row Id="30413" PostHistoryTypeId="2" PostId="10458" RevisionGUID="68b85577-7957-4d31-9a98-6e3ecd43af35" CreationDate="2020-12-03T10:36:28.993" UserId="13095" Text="I can't tell you how exactly each 3d modeling software calculates shadows since I don't know their implementations. However, I guess the usual candidates for real-time shadow calculations are used. These are:&#xD;&#xA;&#xD;&#xA;- [Shadow mapping](https://de.wikipedia.org/wiki/Shadow_Mapping)&#xD;&#xA;- [Shadow Volumes](https://en.wikipedia.org/wiki/Shadow_volume)&#xD;&#xA;&#xD;&#xA;To my knowledge, the second one isn't that popular since it is more complicated and usually computationally more expensive. If you just want to cast a silhouette as a shadow onto a flat surface without caring about the correct lighting of other objects that lie in the shadows you can use a simple [stencil buffer](https://learnopengl.com/Advanced-OpenGL/Stencil-testing) approach like this:&#xD;&#xA;&#xD;&#xA;Draw all your objects &quot;looking from the top&quot; and populate your stencil buffer while doing this. In the end, you should have a buffer filled with all silhouettes. You can now either use it as a shadow map during light calculations of the flat surface or simply render it as a black translucent stencil on top of the surface.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30414" PostHistoryTypeId="2" PostId="10459" RevisionGUID="fc0fae0b-ff62-4b90-a463-77b8afbe2568" CreationDate="2020-12-04T01:35:59.153" UserId="15325" Text="I am currently experimenting with some atmospheric scattering in glsl in my OpenGL engine.&#xD;&#xA;I am experiencing a strange phenomena where a strange band / separation artifact appears along the middle of the screen:&#xD;&#xA;&#xD;&#xA;[Artifact from low altitude][1]&#xD;&#xA;&#xD;&#xA;[Artifact from mid altitude][2]&#xD;&#xA;&#xD;&#xA;[Artifact from high altitude][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sovGD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/3FcnL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/w7uJD.png&#xD;&#xA;&#xD;&#xA;Here is the code responsible for the actual scattering:&#xD;&#xA;&#xD;&#xA;    #define PI 3.1415926535897932384626433832795&#xD;&#xA;    #define iSteps 16&#xD;&#xA;    #define jSteps 8&#xD;&#xA;    &#xD;&#xA;    vec2 rsi(vec3 r0, vec3 rd, float sr) {&#xD;&#xA;        // ray-sphere intersection that assumes&#xD;&#xA;        // the sphere is centered at the origin.&#xD;&#xA;        // No intersection when result.x &gt; result.y&#xD;&#xA;        float a = dot(rd, rd);&#xD;&#xA;        float b = 2.0 * dot(rd, r0);&#xD;&#xA;        float c = dot(r0, r0) - (sr * sr);&#xD;&#xA;        float d = (b*b) - 4.0*a*c;&#xD;&#xA;        if (d &lt; 0.0) return vec2(1e5,-1e5);&#xD;&#xA;        return vec2(&#xD;&#xA;            (-b - sqrt(d))/(2.0*a),&#xD;&#xA;            (-b + sqrt(d))/(2.0*a)&#xD;&#xA;        );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 atmosphere(vec3 r, vec3 r0, vec3 pSun, float iSun, float rPlanet, float rAtmos, vec3 kRlh, float kMie, float shRlh, float shMie, float g) {&#xD;&#xA;        // Normalize the sun and view directions.&#xD;&#xA;        pSun = normalize(pSun);&#xD;&#xA;        r = normalize(r);&#xD;&#xA;    &#xD;&#xA;        // Calculate the step size of the primary ray.&#xD;&#xA;        vec2 p = rsi(r0, r, rAtmos);&#xD;&#xA;        if (p.x &gt; p.y) return vec3(0,0,0);&#xD;&#xA;        p.y = min(p.y, rsi(r0, r, rPlanet).x);&#xD;&#xA;        float iStepSize = (p.y - p.x) / float(iSteps);&#xD;&#xA;    &#xD;&#xA;        // Initialize the primary ray time.&#xD;&#xA;        float iTime = 0.0;&#xD;&#xA;    &#xD;&#xA;        // Initialize accumulators for Rayleigh and Mie scattering.&#xD;&#xA;        vec3 totalRlh = vec3(0,0,0);&#xD;&#xA;        vec3 totalMie = vec3(0,0,0);&#xD;&#xA;    &#xD;&#xA;        // Initialize optical depth accumulators for the primary ray.&#xD;&#xA;        float iOdRlh = 0.0;&#xD;&#xA;        float iOdMie = 0.0;&#xD;&#xA;    &#xD;&#xA;        // Calculate the Rayleigh and Mie phases.&#xD;&#xA;        float mu = dot(r, pSun);&#xD;&#xA;        float mumu = mu * mu;&#xD;&#xA;        float gg = g * g;&#xD;&#xA;        float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);&#xD;&#xA;        float pMie = 3.0 / (8.0 * PI) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * g, 1.5) * (2.0 + gg));&#xD;&#xA;    &#xD;&#xA;        // Sample the primary ray.&#xD;&#xA;        for (int i = 0; i &lt; iSteps; i++) {&#xD;&#xA;    &#xD;&#xA;            // Calculate the primary ray sample position.&#xD;&#xA;            vec3 iPos = r0 + r * (iTime + iStepSize * 0.5);&#xD;&#xA;    &#xD;&#xA;            // Calculate the height of the sample.&#xD;&#xA;            float iHeight = length(iPos) - rPlanet;&#xD;&#xA;    &#xD;&#xA;            // Calculate the optical depth of the Rayleigh and Mie scattering for this step.&#xD;&#xA;            float odStepRlh = exp(-iHeight / shRlh) * iStepSize;&#xD;&#xA;            float odStepMie = exp(-iHeight / shMie) * iStepSize;&#xD;&#xA;    &#xD;&#xA;            // Accumulate optical depth.&#xD;&#xA;            iOdRlh += odStepRlh;&#xD;&#xA;            iOdMie += odStepMie;&#xD;&#xA;    &#xD;&#xA;            // Calculate the step size of the secondary ray.&#xD;&#xA;            float jStepSize = rsi(iPos, pSun, rAtmos).y / float(jSteps);&#xD;&#xA;    &#xD;&#xA;            // Initialize the secondary ray time.&#xD;&#xA;            float jTime = 0.0;&#xD;&#xA;    &#xD;&#xA;            // Initialize optical depth accumulators for the secondary ray.&#xD;&#xA;            float jOdRlh = 0.0;&#xD;&#xA;            float jOdMie = 0.0;&#xD;&#xA;    &#xD;&#xA;            &#xD;&#xA;            // Sample the secondary ray.&#xD;&#xA;            for (int j = 0; j &lt; jSteps; j++) {&#xD;&#xA;    &#xD;&#xA;                // Calculate the secondary ray sample position.&#xD;&#xA;                vec3 jPos = iPos + pSun * (jTime + jStepSize * 0.5);&#xD;&#xA;    &#xD;&#xA;                // Calculate the height of the sample.&#xD;&#xA;                float jHeight = length(jPos) - rPlanet;&#xD;&#xA;    &#xD;&#xA;                // Accumulate the optical depth.&#xD;&#xA;                jOdRlh += exp(-jHeight / shRlh) * jStepSize;&#xD;&#xA;                jOdMie += exp(-jHeight / shMie) * jStepSize;&#xD;&#xA;    &#xD;&#xA;                // Increment the secondary ray time.&#xD;&#xA;                jTime += jStepSize;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // Calculate attenuation.&#xD;&#xA;            vec3 attn = exp(-(kMie * (iOdMie + jOdMie) + kRlh * (iOdRlh + jOdRlh)));&#xD;&#xA;    &#xD;&#xA;            // Accumulate scattering.&#xD;&#xA;            totalRlh += odStepRlh * attn;&#xD;&#xA;            totalMie += odStepMie * attn;&#xD;&#xA;    &#xD;&#xA;            // Increment the primary ray time.&#xD;&#xA;            iTime += iStepSize;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Calculate and return the final color.&#xD;&#xA;        return iSun * (pRlh * kRlh * totalRlh + pMie * kMie * totalMie);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The function is called as so per fragment in the main function:&#xD;&#xA;&#xD;&#xA;    vec3 color = atmosphere(&#xD;&#xA;            normalize(position),          &#xD;&#xA;            vec3(0.0, 6372e3 + camPos.y, 0.0), &#xD;&#xA;            vec3(0.0, 2.0, -1.0),              &#xD;&#xA;            48.0,                           &#xD;&#xA;            6371e3,                         &#xD;&#xA;            6471e3,                         &#xD;&#xA;            vec3(5.5e-6, 13.0e-6, 22.4e-6), &#xD;&#xA;            21e-6,                          &#xD;&#xA;            8e3,                            &#xD;&#xA;            1.2e3,                          &#xD;&#xA;            0.758                           &#xD;&#xA;        );&#xD;&#xA;    &#xD;&#xA;        // Apply exposure.&#xD;&#xA;        color = 1.0 - exp(-1.0 * color);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is causing these artifacts? Or is this intended behaviour?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30415" PostHistoryTypeId="1" PostId="10459" RevisionGUID="fc0fae0b-ff62-4b90-a463-77b8afbe2568" CreationDate="2020-12-04T01:35:59.153" UserId="15325" Text="Atmospheric scattering band/seperation artifact" ContentLicense="CC BY-SA 4.0" />
  <row Id="30416" PostHistoryTypeId="3" PostId="10459" RevisionGUID="fc0fae0b-ff62-4b90-a463-77b8afbe2568" CreationDate="2020-12-04T01:35:59.153" UserId="15325" Text="|opengl|3d|glsl|c++|atmospherics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30417" PostHistoryTypeId="5" PostId="10458" RevisionGUID="ae251737-a268-470c-b6ec-d5300326c348" CreationDate="2020-12-04T08:37:44.113" UserId="13095" Comment="added 628 characters in body" Text="I can't tell you how exactly each 3d modeling software calculates shadows since I don't know their implementations. However, I guess the usual candidates for real-time shadow calculations are used. These are:&#xD;&#xA;&#xD;&#xA;- [Shadow mapping](https://de.wikipedia.org/wiki/Shadow_Mapping)&#xD;&#xA;- [Shadow Volumes](https://en.wikipedia.org/wiki/Shadow_volume)&#xD;&#xA;&#xD;&#xA;To my knowledge, the second one isn't that popular since it is more complicated and usually computationally more expensive. If you just want to cast a silhouette as a shadow onto a flat surface without caring about the correct lighting of other objects that lie in the shadows you can use a simple approach like this:&#xD;&#xA;&#xD;&#xA;Select a (single-channel) texture as your render target and clear its content. Now draw all your objects from the top without perspective projection. The fragment shader returns always the same color that must be different from the clear color. In the end, you have a texture that contains all the silhouettes from your objects. Now you only need to render a quad that uses this texture at the correct position into your scene slightly above the flat surface. Set the output color of the fragment shader to black. The alpha channel is either set to 0 if the texture color at the current fragment is equal to the clear color or to a value of your liking if it is not. (This requires blending to be enabled)&#xD;&#xA;&#xD;&#xA;This is basically a very specialized and simplified shadow mapping special case that uses a texture instead of a z-buffer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Note:**&#xD;&#xA;&#xD;&#xA;I originally suggested using the stencil buffer for this, but it would add an unnecessary indirection, and getting it working as intended can be quite a pain (at least in OpenGL)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30418" PostHistoryTypeId="50" PostId="5996" RevisionGUID="e471035e-cf2e-411d-b53d-0e26c136aebe" CreationDate="2020-12-04T13:04:15.637" UserId="-1" />
  <row Id="30419" PostHistoryTypeId="2" PostId="10460" RevisionGUID="8f47aa35-b006-43bb-bfd9-b42e5e96a5d4" CreationDate="2020-12-04T16:26:13.537" UserId="38" Text="There is a trick to shadows like this, but only this exact usecase. While you can certainly draw a true shadow using many techniques. The trick is you can just scale the object flat onto the floor plane. &#xD;&#xA;&#xD;&#xA;So all you need to do is draw the object 2 times one time with a matrix that is scaled to zero on the floor axis. You can also use this technique to draw shadows that arent entirely top down by adding skew to counter the now rotated shadow.&#xD;&#xA;&#xD;&#xA;This is super easy to implement. No extra cameras. But works only on one plane. This is a special case of shadow volumes without the need to draw the volumes." ContentLicense="CC BY-SA 4.0" />
  <row Id="30420" PostHistoryTypeId="2" PostId="10461" RevisionGUID="de213e88-73a4-49d3-be8b-7453b7fad5d9" CreationDate="2020-12-04T16:34:47.120" UserId="6041" Text="I am trying to derive the material reflectance values from a color picker tool(say MS Paint).&#xD;&#xA;My understanding is to first gamma decode(raise to the power of 2.2) the RGB values from the color picker, so to bring it back to linear space, and then use it in Radiance mat definition.&#xD;&#xA;&#xD;&#xA;However in the [“Rendering with Radiance” book by Greg Ward][1] section 5.1.4 &quot;Estimating Surface Color&quot;&#xD;&#xA;&#xD;&#xA; [page 294][2] and [page 295][3], the rgb values from the color picker are raised to the power of inverse of gamma (1/2.2) and then used as in the material definition.&#xD;&#xA;&#xD;&#xA;Here is a cropped snapshot of the formula from the above links to the scan copied of the two pages.&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;My question is, should the sRGB values from the color picker not be raised to the power of 2.2(decoding) rather than 1/2.2(encoding)?&#xD;&#xA;&#xD;&#xA;For example for BS4800 “18-B-25 Dark admiralty grey / Merlin” colour sample, [this webpage][5] shows sRGB=104,112,116 and LRV value as approx. 16%. This matches closely to my understanding of (112/256) ^ 2.2 = 0.16 (just for the green component).&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://floyd.lbl.gov/radiance/book/&#xD;&#xA;  [2]: https://ibb.co/mcxVZVn&#xD;&#xA;  [3]: https://ibb.co/ZWZZzCB&#xD;&#xA;  [4]: https://i.stack.imgur.com/wfxSJ.png&#xD;&#xA;  [5]: https://www.e-paint.co.uk/Lab_values.asp&#xD;&#xA;  [6]: https://i.stack.imgur.com/ToXyh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30421" PostHistoryTypeId="1" PostId="10461" RevisionGUID="de213e88-73a4-49d3-be8b-7453b7fad5d9" CreationDate="2020-12-04T16:34:47.120" UserId="6041" Text="Converting from RGB Color Picker to Surface Reflectance" ContentLicense="CC BY-SA 4.0" />
  <row Id="30422" PostHistoryTypeId="3" PostId="10461" RevisionGUID="de213e88-73a4-49d3-be8b-7453b7fad5d9" CreationDate="2020-12-04T16:34:47.120" UserId="6041" Text="|reflection|material|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30424" PostHistoryTypeId="2" PostId="10462" RevisionGUID="9c947bc3-6562-42e3-aaf6-052afaa90275" CreationDate="2020-12-04T19:19:50.897" UserId="48" Text="Yes, I think you're right. The values from a typical color picker would be in a gamma encoding or sRGB encoding and would need to be converted to linear to use as reflectance. This is probably just a mistake in the book.&#xD;&#xA;&#xD;&#xA;(BTW, in case you're not aware, sRGB isn't actually gamma 2.2 but [a more complicated transfer function](https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation).)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30426" PostHistoryTypeId="50" PostId="9631" RevisionGUID="a9bbe7fa-27a3-4af7-b9d0-1d2b8a76c761" CreationDate="2020-12-05T09:02:35.260" UserId="-1" />
  <row Id="30431" PostHistoryTypeId="2" PostId="10464" RevisionGUID="105ab887-59bf-41f6-8254-ecd7a2cdace1" CreationDate="2020-12-05T21:18:52.850" UserId="7913" Text="I want to add spectral rendering and dispersion to my pathtracer. I found the [Hero Wavelength paper][1] but I have trouble implementing this. This is how I understand the process and where I am stuck:&#xD;&#xA;&#xD;&#xA;- When generating a ray, randomly sample a hero wavelength $\lambda_h$ with probability $p(\lambda_h)$. Is uniform sampling good enough?&#xD;&#xA;- Now, generate $C$ other wavelengths (a spectrum) using the rotation function $r_j$. Do we generate $C$ others, or $C-1$ so that in total there are $C$ wavelengths?&#xD;&#xA;- In the integrator when the BSDF contribution is evaluated, sample _one_ of those $C$ wavelengths and call it $\lambda_s$. Does this include the hero wavelength? Are they sampled uniformly?&#xD;&#xA;- Evaluate the BSDF for $\lambda_s$ and add the contribution, weighted by the MIS weight and the probability of choosing this wavelength. How is the MIS weight computed? The paper says: $w_s(X_i, \lambda_i^s) = \frac{p(\lambda_i^h) p(X_i | \lambda_i^h)}{\sum_{k=1}^C p(\lambda_i^k) p(X_i | \lambda_i^k)}$ but where does the probability $p(X_i | \lambda_i^k)$ come from? Do I have to evaluate the BSDF direction for each wavelength to get a probability of choosing this path?&#xD;&#xA;- Generate the next path direction based on the BSDF and the hero wavelength.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My current implementation doesn't really differ from the single wavelength per ray model and has lots of coloured noise. As for the dielectric, I do:&#xD;&#xA;&#xD;&#xA;- compute IOR based on wavelength and the dispersion formula for a given material&#xD;&#xA;- compute fresnel with this new IOR&#xD;&#xA;- use a wavelength to RGB conversion to compute the material contribution&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://cgg.mff.cuni.cz/~wilkie/Website/EGSR_14_files/WNDWH14HWSS.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/mRtIn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30432" PostHistoryTypeId="1" PostId="10464" RevisionGUID="105ab887-59bf-41f6-8254-ecd7a2cdace1" CreationDate="2020-12-05T21:18:52.850" UserId="7913" Text="Hero wavelength multiple importance sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="30433" PostHistoryTypeId="3" PostId="10464" RevisionGUID="105ab887-59bf-41f6-8254-ecd7a2cdace1" CreationDate="2020-12-05T21:18:52.850" UserId="7913" Text="|pathtracing|importance-sampling|spectral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30434" PostHistoryTypeId="2" PostId="10465" RevisionGUID="a7d1f23e-412e-4088-b012-ac50cd35b1ed" CreationDate="2020-12-06T09:50:00.090" UserId="13729" Text="This is how I ended up doing it:&#xD;&#xA;&#xD;&#xA;Instead of using vertex colors like most of the solutions I found online, I calculated the angle of each edge, and then used a shader to draw the lines in UV space. This Also gives me control over how thick the lines should be.&#xD;&#xA;&#xD;&#xA;In some cases the angle calculated isn't right, but that should be easy to fix.&#xD;&#xA;&#xD;&#xA;[![Curvature map applied to a model][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the project: https://github.com/Jummit/curvature-baker&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yoqrt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30438" PostHistoryTypeId="2" PostId="10467" RevisionGUID="d89c47dd-6ec4-4c0b-ad65-eec06080d468" CreationDate="2020-12-06T18:01:39.860" UserId="15340" Text="Unsure if this is the right network to post this, but maybe someone can help...&#xD;&#xA;&#xD;&#xA;I'm working on a personal project where, with the help of AI, I want to automatically estimate the perspective of a given image.&#xD;&#xA;&#xD;&#xA;I've been able to programatically estimate and draw the position of the horizon, as seen below. This is based on how &quot;quickly&quot; cars farther away shrink in the image.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Not sure the above is useful, but now I want to draw a grid on the plane. Something like:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is where it's getting too complicated for me. I have no idea how to solve this. Not the drawing per se, but the mathematics behind it. Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q7fKtm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9LOFgm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30439" PostHistoryTypeId="1" PostId="10467" RevisionGUID="d89c47dd-6ec4-4c0b-ad65-eec06080d468" CreationDate="2020-12-06T18:01:39.860" UserId="15340" Text="Project grid on 2d plane based on camera perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="30440" PostHistoryTypeId="3" PostId="10467" RevisionGUID="d89c47dd-6ec4-4c0b-ad65-eec06080d468" CreationDate="2020-12-06T18:01:39.860" UserId="15340" Text="|projections|perspective|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30441" PostHistoryTypeId="34" PostId="10436" RevisionGUID="d31969c4-1e92-42a9-90b3-dc8c8ce1c08a" CreationDate="2020-12-07T00:02:35.273" UserId="-1" Comment="67" />
  <row Id="30442" PostHistoryTypeId="2" PostId="10468" RevisionGUID="8b8e7353-06d8-4d33-8f28-fde4246f04cb" CreationDate="2020-12-07T23:21:05.330" UserId="6562" Text="I wrote a rather elegant and compact [Photon Mapper][1] in [CUDA][2]. But I treat all my photons they same, and ignore their colour.&#xD;&#xA;&#xD;&#xA;This simplicity has some nice properties: e.g. I can just count them with one integer value for each little subdivision patch on the surface.&#xD;&#xA;&#xD;&#xA;However, to properly model the global illumination, I should take into account the colour, after a photon bounces from a surface. (A red carpet, reflects red light onto a nearby wall, not white light.)&#xD;&#xA;&#xD;&#xA;An obvious approach would be to replace the single integer count with three floating point counters, for R, G and B.&#xD;&#xA;&#xD;&#xA;But I feel there must be a more elegant solution to this? Russian roulette on the R/G/B channels perhaps? Although this would create more noise? But it would mean fewer data per photon, and thus better use of the cache?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Photon_mapping&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/CUDA" ContentLicense="CC BY-SA 4.0" />
  <row Id="30443" PostHistoryTypeId="1" PostId="10468" RevisionGUID="8b8e7353-06d8-4d33-8f28-fde4246f04cb" CreationDate="2020-12-07T23:21:05.330" UserId="6562" Text="How to count the photons when Photon Mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="30444" PostHistoryTypeId="3" PostId="10468" RevisionGUID="8b8e7353-06d8-4d33-8f28-fde4246f04cb" CreationDate="2020-12-07T23:21:05.330" UserId="6562" Text="|global-illumination|photon-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30449" PostHistoryTypeId="2" PostId="10470" RevisionGUID="8c850ace-c006-4f70-b3de-1e29f8e856fe" CreationDate="2020-12-08T01:43:56.263" UserId="48" Text="I'm assuming that you don't know how many objects there will be or have any way to index them until the image processing operations are completed, i.e. you have some final pass that determines for each pixel &quot;do I want to put an object here, or no&quot;.&#xD;&#xA;&#xD;&#xA;OpenGL ES 2.0 is pretty limiting. There may be no better way to do this than what you described: output from the fragment shader to a texture, pull it back to the CPU to extract the points, then put those into a uniform buffer for the second pass.&#xD;&#xA;&#xD;&#xA;One thing you could attempt, though I'm unsure if it could be fully made to work in ES 2.0, is to do a [parallel prefix sum](https://developer.nvidia.com/gpugems/gpugems3/part-vi-gpu-computing/chapter-39-parallel-prefix-sum-scan-cuda) over the output texture from the first pass. This would involve recursive fragment shader reduction passes (a little bit like generating mipmaps) that would first count up the number of objects within each region of the image, starting with 2×2 regions and doubling at each step until you've covered the full image, then go back down the mip chain and calculate the prefix sums, which are the number of objects &quot;before&quot; each region (using some defined ordering). At the end of that, you would have the exact index where to store each object into an output buffer.&#xD;&#xA;&#xD;&#xA;FYI, in GL ES 3.1 and other more fully-featured APIs, there are shader atomic counters, which allow implementing an &quot;append buffer&quot;; your first fragment shader pass could output directly to this buffer, then turn around and use it for an input buffer, or for indirect draw parameters, on the next pass." ContentLicense="CC BY-SA 4.0" />
  <row Id="30450" PostHistoryTypeId="50" PostId="8151" RevisionGUID="ef772847-5920-48ea-8007-5c6ebfc97c2b" CreationDate="2020-12-08T02:00:40.090" UserId="-1" />
  <row Id="30452" PostHistoryTypeId="2" PostId="10471" RevisionGUID="50e2316f-aeae-4a7b-ba01-f0cb9f94c193" CreationDate="2020-12-08T09:00:02.000" UserId="15345" Text="I don't know if you just didn't write it or really intended not to do it, but in general it's now enough to check the velocity vectors for inersection. First off, the vectors might intersect but the balls pass the intersection point on different times, resulting in no collision. Second, you do not take the radius of each ball into consideration. &#xD;&#xA;&#xD;&#xA;From my (limited) experience, contiuous collision detection is either done with a technique called *conservative advancement*, *signed distance field* or (which would apply for your case) solving for a mathmatical equation dependent on time $t\in[0,1]$. Even with bent trajectories you are able to do this.&#xD;&#xA;&#xD;&#xA;Once you have solved for $t$ and computed all pair-wise collisions (all 16 balls with each other and possibly the edges in some way), you can sort them by their collision time $t_i$ (earliest collisions should be handled first) and solve the collision restrains with some phyiscal response. Because of the nature of continuous collision detection, you will not have an actual intersection where you would get the contact normal and penetration depth from. Usually you will have some distance of two balls that qualify (numerically) as a collision, like $d(B_1, B_2) &lt; \varepsilon$. But there are mutliple easy ways to fix this, particularly for you scenario.&#xD;&#xA;&#xD;&#xA;After you have solved all the collisions and updated all velocities, you have to repeat the whole process because there might now be different collisions between different balls. In theory, you would have to repeat this until all collisions have been properly solved. However, there might be cases where there are somewhat cyclic collisions (think [Newton's cradle][1]) and these will be tough to properly handle. Again, this is up to implementation but a good start (at least to avoid infite collisions) would be to use a limited number of iterations per frame for this.&#xD;&#xA;&#xD;&#xA;Then, after finishing all collisions for one frame, you finally can render you scene.&#xD;&#xA;&#xD;&#xA;Good luck with your project! I know how tough it can be to implement a proper collision detection, let alone a continuous collision detection.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Newton%27s_cradle" ContentLicense="CC BY-SA 4.0" />
  <row Id="30453" PostHistoryTypeId="50" PostId="10378" RevisionGUID="334bb66a-58e0-4b13-b24c-44869f4da650" CreationDate="2020-12-08T15:06:30.800" UserId="-1" />
  <row Id="30454" PostHistoryTypeId="2" PostId="10472" RevisionGUID="8f4c1bcb-94c6-45df-b618-a01b5122eea0" CreationDate="2020-12-09T07:01:02.123" UserId="9779" Text="I have a pretty basic widget rendering, largely based upon the learnopengl.com &quot;hello triangle.&quot; I'm actually using a tristrip to create two triangles, forming a semi-opaque square over the top of the other stuff in my window. In this square, I'm using the fragment shader to set the semi-opaque background color and an arrow that points in the direction of flight. What I want to do next is render a `GL_LINES` vertex buffer that contains the historical position of the aircraft.&#xD;&#xA;&#xD;&#xA;It seems easy enough to set up a second vertex attribute object and vertex buffer, but what is unclear to me is whether it's possible to use a single vertex &amp; fragment shader pair to handle this second dataset. It wouldn't be terribly difficult to set up a group of widgets to render the opaque square, then the historical course information, then the arrow, but I already have the first and third stages working.... and breaking everything up would mean 3 vertex and 3 fragment shaders.&#xD;&#xA;&#xD;&#xA;I'm guessing that it's impossible to deal with the semi-opaque background, the historic course, and the arrow all in one vertex/fragment shader pair, but it'd be obtuse to just make that assumption and make a mess out of some tolerably organized code before I got an informed answer. " ContentLicense="CC BY-SA 4.0" />
  <row Id="30455" PostHistoryTypeId="1" PostId="10472" RevisionGUID="8f4c1bcb-94c6-45df-b618-a01b5122eea0" CreationDate="2020-12-09T07:01:02.123" UserId="9779" Text="Rendering different array types in the same vertex/fragment shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30456" PostHistoryTypeId="3" PostId="10472" RevisionGUID="8f4c1bcb-94c6-45df-b618-a01b5122eea0" CreationDate="2020-12-09T07:01:02.123" UserId="9779" Text="|shader|fragment-shader|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30460" PostHistoryTypeId="2" PostId="10474" RevisionGUID="deacc117-2d32-41a9-bd96-084bc1924bef" CreationDate="2020-12-09T18:46:43.253" UserId="7913" Text="I'm not sure if I understand your question correctly and don't know what you mean by &quot;counting&quot; and how you want to replace this by &quot;color&quot;. A simple photon mapper looks like this: 1) photon tracing: emit, scatter, store photons 2) path tracing: gather photons in a given radius and approximate radiance using this density.&#xD;&#xA;&#xD;&#xA;To be more precise, in pseudocode (with russian roulette) this would look like:&#xD;&#xA;&#xD;&#xA;`xi` is the position, `wo` the outgoing direction, `W` the photon power. All three are vectors of length 3. `p` is the probability of the Russian roulette. A photon is a struct that stores the power, direction, and position.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;xi, wo, W = emitter.sample()&#xD;&#xA;while(true)&#xD;&#xA;   xi = traceRay(xi, wo)&#xD;&#xA;   if(isDiffuse(xi))&#xD;&#xA;      storePhoton(xi, wo, W)&#xD;&#xA;&#xD;&#xA;   if(rand &lt; p)&#xD;&#xA;      break&#xD;&#xA;    W /= p;&#xD;&#xA;    &#xD;&#xA;    wo = bsdf.sample(xi)&#xD;&#xA;    W *= bsdf(wo)/pdf(wo)*cos&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;You repeatedly call this function for a random emitter until you stored a predefined amount of photons (e.g. 500'000). After this, you _build_ the photonmap, such as a k-d tree to make querying easy. As you can see, the &quot;color&quot; is stored in the power of the photon.&#xD;&#xA;&#xD;&#xA;The next step is the gathering the photons, and it's normal path tracing but when you hit a diffuse surface, you gather all the photons in a fixed radius (other kernels can also be used). Here, `t` is the throughput, `wi` the incoming direction, the `photon_map` is the datastructure that we build before and populated with photons, and `total_photons` is the total amount of photons that we emitted.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;if(isDiffuse(xi))&#xD;&#xA;   for photon: photon_map.get(xi, radius)&#xD;&#xA;      radiance *= t*bsdf(xi, wi, photon.wo) * photon.power / (pi*radius^2 * total_photons)&#xD;&#xA;   break&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30461" PostHistoryTypeId="2" PostId="10475" RevisionGUID="fc3a589c-60a6-4961-97d9-2593af622ab9" CreationDate="2020-12-09T20:34:00.587" UserId="7913" Text="Since you already have convex shapes and started looking at the &quot;Method of separating axis&quot;, then the [GJK][1] algorithm is probably what you're looking for. This is commonly used in physics simulations to find collisions (for games, I don't know about computational science).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When you say &quot;remove intersections without generating others&quot;, then you're asking for collision response. Multiple collision response is actually a tough beast. [Here][2] (Reflections on Simultaneous Impact) is a paper that goes into more detail, but a very good introduction to this are course notes from Baraff:&#xD;&#xA;[An Introduction to Physically Based Modeling: Rigid Body Simulation I—Unconstrained Rigid Body Dynamics][3] and part 2. [Rigid Body Simulation II-Nonpenetration Constraints][4]&#xD;&#xA;&#xD;&#xA;Lastly, you can always use a physics engine for this, such as [Bullet3d][5].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gilbert%E2%80%93Johnson%E2%80%93Keerthi_distance_algorithm&#xD;&#xA;  [2]: http://www.cs.columbia.edu/cg/rosi/rosi.pdf&#xD;&#xA;  [3]: https://www.cs.cmu.edu/~baraff/sigcourse/notesd1.pdf&#xD;&#xA;  [4]: https://www.cs.cmu.edu/~baraff/sigcourse/notesd2.pdf&#xD;&#xA;  [5]: https://github.com/bulletphysics/bullet3" ContentLicense="CC BY-SA 4.0" />
  <row Id="30463" PostHistoryTypeId="10" PostId="9303" RevisionGUID="f815c409-feb2-491d-bd9f-2fd0a385d33c" CreationDate="2020-12-10T08:47:16.817" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="30464" PostHistoryTypeId="2" PostId="10476" RevisionGUID="af050b0f-c397-4cb3-a6b2-4cf54585cfd1" CreationDate="2020-12-10T11:40:00.203" UserId="15361" Text="I'm trying to write a little program with a bouncing cube but I can't find the right x, y, z and angle for it. I have these lines:&#xD;&#xA;&#xD;&#xA;    modelMatrix = glm::mat4(1)&#xD;&#xA;&#xD;&#xA;    modelMatrix *= Translate(x, y, z)&#xD;&#xA;&#xD;&#xA;    modelMatrix *= RotateOZ(angle)&#xD;&#xA;&#xD;&#xA;    RenderMesh(mesh[&quot;cube&quot;], shaders[&quot;V&quot;], modelMatrix)&#xD;&#xA;&#xD;&#xA;I added a picture to make it easier to understand. My cube will start at x0, y0, z0(we can leave the z out of this because for now I want the cube to move only in the OX axis and OY). I added a arrow the cube so I can represent the rotation better. First he will move forward on the OX and OY axis while rotating in the range of [0 - 90] grades when he will hit X1(which is X / 2) and Y1 then he will rotate in the range of [90 - 180] grades while moving forward on the OX and descending on the OY. I hope that made sense.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r0yU7.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My problem is that I can't find the right x, y and angle to give to these transformations so I can get the animation that I want. I tried to add to x, y and angle the same value such as 0.1 and the result is close but not perfect.&#xD;&#xA;RotateOZ return a mat4:&#xD;&#xA;&#xD;&#xA;    return glm::mat4(&#xD;&#xA;			cos(angle), -sin(angle), 0, 0,&#xD;&#xA;			sin(angle), cos(angle), 0, 0,&#xD;&#xA;			0, 0, 1, 0,&#xD;&#xA;			0, 0, 0, 1&#xD;&#xA;		);&#xD;&#xA;&#xD;&#xA;Thank you for your time!&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30465" PostHistoryTypeId="1" PostId="10476" RevisionGUID="af050b0f-c397-4cb3-a6b2-4cf54585cfd1" CreationDate="2020-12-10T11:40:00.203" UserId="15361" Text="3D Bouncing Cube" ContentLicense="CC BY-SA 4.0" />
  <row Id="30466" PostHistoryTypeId="3" PostId="10476" RevisionGUID="af050b0f-c397-4cb3-a6b2-4cf54585cfd1" CreationDate="2020-12-10T11:40:00.203" UserId="15361" Text="|3d|transformations|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30467" PostHistoryTypeId="2" PostId="10477" RevisionGUID="17a076c6-87fd-48ad-8248-d4d396957bc0" CreationDate="2020-12-10T12:26:47.010" UserId="13273" Text="I would like to implement a random placement for objects like trees stones etc. on a triangles surface.&#xD;&#xA;The important part is to have an equally probability to place an object on this surface. That means, that for example to randomly place a tree in the middle should not be higher than placing it at a corner / edge.&#xD;&#xA;&#xD;&#xA;The second requirement is to program this placement algorithm onto the GPU by using OpenGL/GLSL. So randomly generate a position and loop as long as it is not inside the triangle is no option because of branching...  I need to place tons of objects per frame...&#xD;&#xA;&#xD;&#xA;I had the idea of using Barycentric coordinates where the three scalars are randomly generated. but it turned out, that the middle and the lines from the middle to the middle of an edge is more probably than hitting a corner. The good thing about Barycentric coordinates is, that the surface of the 3D triangle is always hit, so the generated position is not above or outside the triangle. Another plus is, that to calculate the Barycentric coordinate is extremely fast during using multiplication of 3D vectors with scalars and addition of vectors with vectors.&#xD;&#xA;&#xD;&#xA;here is my C++ code to generate random positions on the triangles' surface.&#xD;&#xA;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	#include &lt;fstream&gt;&#xD;&#xA;	#include &lt;string&gt;&#xD;&#xA;	#include &lt;vector&gt;&#xD;&#xA;	#include &lt;stdlib.h&gt;&#xD;&#xA;&#xD;&#xA;	struct Vector3D&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;&#xD;&#xA;		Vector3D()&#xD;&#xA;		{&#xD;&#xA;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D(double x, double y, double z)&#xD;&#xA;		{&#xD;&#xA;			this-&gt;x = x;&#xD;&#xA;			this-&gt;y = y;&#xD;&#xA;			this-&gt;z = z;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		void operator*=(double factor)&#xD;&#xA;		{&#xD;&#xA;			x *= factor;&#xD;&#xA;			y *= factor;&#xD;&#xA;			z *= factor;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		void operator+=(double factor)&#xD;&#xA;		{&#xD;&#xA;			x += factor;&#xD;&#xA;			y += factor;&#xD;&#xA;			z += factor;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D operator*(double factor)&#xD;&#xA;		{&#xD;&#xA;			Vector3D result;&#xD;&#xA;			result.x = x * factor;&#xD;&#xA;			result.y = y * factor; &#xD;&#xA;			result.z = z * factor; &#xD;&#xA;			return result;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D operator+(Vector3D v2)&#xD;&#xA;		{&#xD;&#xA;			Vector3D result;&#xD;&#xA;			result.x = x + v2.x;&#xD;&#xA;			result.y = y + v2.y;&#xD;&#xA;			result.z = z + v2.z;&#xD;&#xA;			return result;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		double x;&#xD;&#xA;		double y;&#xD;&#xA;		double z;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	Vector3D getBarycentricPosition(Vector3D p0, Vector3D p1, Vector3D p2, double scalar0, double scalar1, double scalar2)&#xD;&#xA;	{&#xD;&#xA;		return (p0 * scalar0) + (p1 * scalar1) + (p2 * scalar2);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		Vector3D p0(1, 0, 0);&#xD;&#xA;		Vector3D p1(0, 1, 0);&#xD;&#xA;		Vector3D p2(0, 0, 1);&#xD;&#xA;&#xD;&#xA;		std::ofstream writefile(&quot;C:/Data[![enter image description here][1]][1]/barycentricTest.obj&quot;);&#xD;&#xA;		if (writefile.is_open())&#xD;&#xA;		{&#xD;&#xA;			for (unsigned int i = 0; i &lt; 100000; ++i)&#xD;&#xA;			{&#xD;&#xA;				//generate random values&#xD;&#xA;				double random0 = rand() % 1000;&#xD;&#xA;				double random1 = rand() % 1000;&#xD;&#xA;				double random2 = rand() % 1000;&#xD;&#xA;&#xD;&#xA;                //&#xD;&#xA;                double powFactor = 1.0f;&#xD;&#xA;				random0 = pow(random0, powFactor);&#xD;&#xA;				random1 = pow(random1, powFactor);&#xD;&#xA;				random2 = pow(random2, powFactor);&#xD;&#xA;&#xD;&#xA;				int sum = random0 + random1 + random2;&#xD;&#xA;&#xD;&#xA;				//scalar0 + scalar1 + scalar2 = 1 !!&#xD;&#xA;				double scalar0 = static_cast&lt;double&gt;(random0) / static_cast&lt;double&gt;(sum);&#xD;&#xA;				double scalar1 = static_cast&lt;double&gt;(random1) / static_cast&lt;double&gt;(sum);&#xD;&#xA;				double scalar2 = static_cast&lt;double&gt;(random2) / static_cast&lt;double&gt;(sum);&#xD;&#xA;&#xD;&#xA;				Vector3D p = getBarycentricPosition(p0, p1, p2, scalar0, scalar1, scalar2);&#xD;&#xA;       &#xD;&#xA;                //write to .obj file to see results in blender&#xD;&#xA;				writefile &lt;&lt; &quot;v &quot; &lt;&lt; p.x &lt;&lt; &quot; &quot; &lt;&lt; p.y &lt;&lt; &quot; &quot; &lt;&lt; p.z &lt;&lt; std::endl;&#xD;&#xA;			}&#xD;&#xA;			writefile.close();&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;By looking at the code, you'll recognize, that there is the double *powFactor*. I tried to bring the probability of the corners a little bit up.&#xD;&#xA;&#xD;&#xA;Here are some images with different *powFactor* values.&#xD;&#xA;&#xD;&#xA;**powFactor = 1.0   So without influencing the algorithm**&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**powFactor = 1.3**&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Like you can see, to pow with 1.3 looks good inside, but the corners / edges are over weighted...&#xD;&#xA;&#xD;&#xA;Is there a fast algorithm (branching free) which gives good results?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gsTyd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/lEua0.jpg&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30468" PostHistoryTypeId="1" PostId="10477" RevisionGUID="17a076c6-87fd-48ad-8248-d4d396957bc0" CreationDate="2020-12-10T12:26:47.010" UserId="13273" Text="Equally distribution on triangle surfaces" ContentLicense="CC BY-SA 4.0" />
  <row Id="30469" PostHistoryTypeId="3" PostId="10477" RevisionGUID="17a076c6-87fd-48ad-8248-d4d396957bc0" CreationDate="2020-12-10T12:26:47.010" UserId="13273" Text="|opengl|glsl|distribution|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30470" PostHistoryTypeId="2" PostId="10478" RevisionGUID="5e5081f5-d307-478b-bf48-b2555677c9b8" CreationDate="2020-12-10T19:47:13.923" UserId="48" Text="Barycentric coordinates need to sum to 1.0, so pick two of them (say $u, v$) randomly from [0, 1] and then set the third as $w = 1 - u - v$. This will give you random points that are evenly distributed with respect to area, in a parallelogram consisting of two copies of the triangle. Then, you can reflect across the triangle edge to bring both copies of the triangle together. This can be done by checking if $u + v &gt; 1$, and if so, reflect by setting $u' = 1-u,\, v' = 1-v$ and then recalculate $w$.&#xD;&#xA;&#xD;&#xA;See also: [Generate random points in a triangle](https://blogs.sas.com/content/iml/2020/10/19/random-points-in-triangle.html)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30471" PostHistoryTypeId="2" PostId="10479" RevisionGUID="900a0eb9-fc41-4d8a-8ccb-00b7ea410e89" CreationDate="2020-12-11T06:05:49.823" UserId="15364" Text="In a passive-matrix LCD we have horizontal and vertical conductors. The intersection points are pixels which are  cells of liquid crystal molecules . For drawing a frame, we provide the necessary voltages to specific conductors.&#xD;&#xA;But once we have provided the voltages and the picture has been drawn on the screen ,why do we need to refresh.&#xD;&#xA;As long as the voltage is on ,the picture is still there ....it's not like a CRT where the emission from phosphorus atoms decays.&#xD;&#xA;If the reason is video or animation, then we are changing the frame buffer and then drawing the new frame buffer.&#xD;&#xA;But do we need to refresh the same frame buffer at some rate ? &#xD;&#xA;If so , why ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30472" PostHistoryTypeId="1" PostId="10479" RevisionGUID="900a0eb9-fc41-4d8a-8ccb-00b7ea410e89" CreationDate="2020-12-11T06:05:49.823" UserId="15364" Text="Why refresh rate is needed in a passive-matrix LCD?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30473" PostHistoryTypeId="3" PostId="10479" RevisionGUID="900a0eb9-fc41-4d8a-8ccb-00b7ea410e89" CreationDate="2020-12-11T06:05:49.823" UserId="15364" Text="|pixel-graphics|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30477" PostHistoryTypeId="2" PostId="10481" RevisionGUID="93dc36ae-fd6a-45f1-a003-d7375ec5a840" CreationDate="2020-12-11T12:46:28.477" UserId="15366" Text="gl_VertexID Is the way to go, you quickly run out of attribs if you need a normal mapped skeletal character, there’s only room for 2-3 blend shapes to fit in 16 attribs" ContentLicense="CC BY-SA 4.0" />
  <row Id="30485" PostHistoryTypeId="50" PostId="10384" RevisionGUID="d51013ad-8021-4556-9750-c64169c43245" CreationDate="2020-12-12T01:01:15.113" UserId="-1" />
  <row Id="30486" PostHistoryTypeId="2" PostId="10483" RevisionGUID="e8a429c6-62a3-4be4-843c-549c79d658e7" CreationDate="2020-12-12T01:56:10.497" UserId="7462" Text="Subdivision schemes work by considering the vertices and their connectivity information to calculate averaging weights.&#xD;&#xA;&#xD;&#xA;However, other than specifying which vertices are connected, and perhaps which weights to use (in the case of loop subdivision for example), edges don;t really play a role.&#xD;&#xA;&#xD;&#xA;Same as faces. I am wondering if there is a subdivision scheme that attaches &quot;weights&quot; (and weights could be either scalars or matrices or similar vector fields) and has the faces and edges have a controllable effect on the convergence.&#xD;&#xA;&#xD;&#xA;For example in the case of meshes, consider a cube. If the weights of the faces are 0, then the subdivision is just a regular subdivision. But if the weights of each face go towards infinity, then the limit of the convergence should be the original cube.&#xD;&#xA;&#xD;&#xA;I am trying to find something like this, but I cannot find any associated literature with the topic." ContentLicense="CC BY-SA 4.0" />
  <row Id="30487" PostHistoryTypeId="1" PostId="10483" RevisionGUID="e8a429c6-62a3-4be4-843c-549c79d658e7" CreationDate="2020-12-12T01:56:10.497" UserId="7462" Text="Subdivision scheme where the faces and edges have weights (not necessarily scalar weights)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30488" PostHistoryTypeId="3" PostId="10483" RevisionGUID="e8a429c6-62a3-4be4-843c-549c79d658e7" CreationDate="2020-12-12T01:56:10.497" UserId="7462" Text="|algorithm|mathematics|computational-geometry|geometry|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30489" PostHistoryTypeId="2" PostId="10484" RevisionGUID="ee2439e8-52cf-45f4-ba99-667f8065d518" CreationDate="2020-12-12T07:28:03.977" UserId="6046" Text="There are many methods to go about visualizing volume data. Two famous ones are texture slices and ray marching. Texture slices intends to render 3D textures with volume data. Refer to the wiki page for Volume Rendering for more approaches. Ray marching shoots rays through the volume and composites values as the ray progresses through. This is a very simple explanation.&#xD;&#xA;&#xD;&#xA;Now you can code raymarching in a fragment shader or a compute shader or even on the cpu.&#xD;&#xA;If you are interested in Raymarching, you can use my project as a reference (I used a compute shader approach)&#xD;&#xA;https://github.com/gallickgunner/Volume-Renderer&#xD;&#xA;&#xD;&#xA;Also these tutorials might come in handy.&#xD;&#xA;&#xD;&#xA;http://graphicsrunner.blogspot.com/2009/01/volume-rendering-101.html&#xD;&#xA;&#xD;&#xA;For an in-depth explanation to these topics, refer to the book &quot;Real time Volume Graphics&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30490" PostHistoryTypeId="2" PostId="10485" RevisionGUID="1530f698-fc00-4ebe-9d04-3a871b37249c" CreationDate="2020-12-12T10:37:58.530" UserId="7724" Text="What you are looking for is semi-sharp creases. You can find it in section 3 of this paper: https://graphics.pixar.com/library/Geri/paper.pdf&#xD;&#xA;&#xD;&#xA;Basically, each edge is given a sharpness value $s$. This can either be a integer or a floating point value. This value signifies how many subdivision steps this edge will be left alone, meaning that the associated vertices will remain in the same position. When subdividing an edge with sharpness $s$ will have subdivide the edge into two edges with sharpness level $s-1$. Until $s$ is 0 and the edge will be subdivided as normal.&#xD;&#xA;&#xD;&#xA;For fractional levels the last subdivision with $s \in [0,1]$ the vertices will obtain a blended position between the subdivided $p$ and the original position in the control mesh $v$, i.e. $(1-s)*p + s*v$.     " ContentLicense="CC BY-SA 4.0" />
  <row Id="30491" PostHistoryTypeId="5" PostId="10485" RevisionGUID="dec0403f-83bb-4428-8faf-6f2d3248e50d" CreationDate="2020-12-12T10:43:07.537" UserId="7724" Comment="deleted 56 characters in body" Text="What you are looking for is semi-sharp creases. You can find it in section 3 of this paper: https://graphics.pixar.com/library/Geri/paper.pdf&#xD;&#xA;&#xD;&#xA;Basically, each edge is given a sharpness value $s$. This can either be a integer or a floating point value. This value signifies how many subdivision steps this edge will be subdivided using sharp-subdivision rules. When subdividing an edge with sharpness $s$, it subdivide into two edges with sharpness level $s-1$. Until $s$ is 0 and the edge will be subdivided as normal.For fractional levels the last subdivision with $s \in [0,1]$ the vertices will obtain a blended position between the subdivided $p$ and the sharp position $p_s$, i.e. $(1-s)p + s p_s$.     &#xD;&#xA;&#xD;&#xA;The sharp subdivision rules boil down to the following. Vertices at the end of an sharpness tagged edge will remain in the same position and vertices on the sharp edge are refined using the stencil [1, 6, 1]/8 applied to previous and next points on the tagged curve." ContentLicense="CC BY-SA 4.0" />
  <row Id="30492" PostHistoryTypeId="5" PostId="10485" RevisionGUID="0ea9c5ee-644f-40b4-9e2f-f91fb35ea698" CreationDate="2020-12-12T11:16:38.663" UserId="7724" Comment="added 171 characters in body" Text="What you are looking for is semi-sharp creases. You can find it in section 3 of this paper: https://graphics.pixar.com/library/Geri/paper.pdf&#xD;&#xA;&#xD;&#xA;Basically, each edge is given a sharpness value $s$. This can either be a integer or a floating point value. This value signifies how many subdivision steps this edge will be subdivided using sharp-subdivision rules. When subdividing an edge with sharpness $s$, it subdivide into two edges with sharpness level $s-1$. Until $s$ is 0 and the edge will be subdivided as normal.For fractional levels the last subdivision with $s \in [0,1]$ the vertices will obtain a blended position between the subdivided $p$ and the sharp position $p_s$, i.e. $(1-s)p + s p_s$.     &#xD;&#xA;&#xD;&#xA;The sharp subdivision rules boil down to the following. Vertices at the end of an sharpness tagged edge will remain in the same position and vertices on the sharp edge are refined using the stencil [1, 6, 1]/8 applied to previous, current and next points on the tagged curve respectively. New points are inserted at midpoints of edges.&#xD;&#xA;&#xD;&#xA;This scheme can be generalized to faces by propagating the sharpness value of a face to its edges." ContentLicense="CC BY-SA 4.0" />
  <row Id="30493" PostHistoryTypeId="36" PostId="10486" RevisionGUID="ff158dae-99ed-4a81-affd-6d169f658e11" CreationDate="2020-12-13T18:59:05.693" UserId="-1" Comment="from https://photo.stackexchange.com/questions/121766/does-an-object-spanning-percentage-of-the-cameras-fov-correlate-with-the-object" />
  <row Id="30494" PostHistoryTypeId="2" PostId="10486" RevisionGUID="52f4b1db-3921-43ed-8e36-c65ed79bc1db" CreationDate="2020-12-13T18:00:33.930" UserDisplayName="Physician" Text="I am working on a virtual camera inside a game engine, which provides me with an FoV control, but no Focal length control (and no filming sensor dimensions short of aspect ratio), and I am less than a beginner in photography.&#xD;&#xA;&#xD;&#xA;Now when I position the Camera in a specific location in the world, and I position an object in front of the camera such that the object covers 50 degrees of the camera field horizontally. The camera FoV is 100 degrees horizontally.[see image please].&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Then I measure the object in the image and I find it covering around 40% of the image width instead of 50%.&#xD;&#xA;&#xD;&#xA;What is the most expected mistake that I am making here?&#xD;&#xA;&#xD;&#xA;Relevant information: I don't know the position of the virtual camera is the position in the middle of the lens itself, the position of the sensory retina, or the position in between.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ulFNH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30495" PostHistoryTypeId="1" PostId="10486" RevisionGUID="52f4b1db-3921-43ed-8e36-c65ed79bc1db" CreationDate="2020-12-13T18:00:33.930" UserDisplayName="Physician" Text="Does an object spanning percentage of the Camera's FoV correlate with the object's image percentage?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30496" PostHistoryTypeId="3" PostId="10486" RevisionGUID="52f4b1db-3921-43ed-8e36-c65ed79bc1db" CreationDate="2020-12-13T18:00:33.930" UserDisplayName="Physician" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30497" PostHistoryTypeId="36" PostId="10487" RevisionGUID="f06744bd-96b7-49b4-b11f-8110fa4b8213" CreationDate="2020-12-13T18:59:05.693" UserId="-1" Comment="from https://photo.stackexchange.com/questions/121766/does-an-object-spanning-percentage-of-the-cameras-fov-correlate-with-the-object/121768#121768" />
  <row Id="30498" PostHistoryTypeId="2" PostId="10487" RevisionGUID="dc4ae330-e368-41f5-a1bc-30c6d08877d6" CreationDate="2020-12-13T18:37:43.327" UserDisplayName="szulat" Text="You are probably assuming that the apparent screen size of an object is proportional to the angle, while in fact it is proportional to the [tangent][1] of half angle.&#xD;&#xA;&#xD;&#xA;The difference is small for small angles but big enough at your 100°, try sketching your example for 179° FOV camera and 89.5° (half FOV) object to see how deep the rabbit hole goes.&#xD;&#xA;&#xD;&#xA;  [1]: https://mathworld.wolfram.com/Tangent.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30499" PostHistoryTypeId="2" PostId="10488" RevisionGUID="6764bc1a-1ad6-4e8f-ba41-19e6bdbd75a3" CreationDate="2020-12-14T01:27:34.287" UserId="15374" Text="When we calculate the field of view of a lens mounted on a camera, we can evaluate three different unique angles. These are height, width, and diagonal. As an example, if we mount a 46mm lens on a 35mm full frame camera with a format of 24mm by 36mm, the angles of view are 29° height, by 42° length, and 50° diagonal. While likely the last value, the diagonal is value most often given. If you think this is bizarre, consider that TV sets are sized by their diagonal measure.&#xD;&#xA;&#xD;&#xA;We can trace an object triangle, a trace from its boundary points to a point at the center of the lens. We can also trace an image triangle, inside the camera, beginning from its boundaries to the center of the lens.&#xD;&#xA;  &#xD;&#xA;These two triangles will be “similar”.  Their angles will be identical; their sides will be in ratio. Likely the field of view you are using is in reality the diagonal angle of view, and the image length you are referencing corresponds to the hormonal angle of view.  &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30500" PostHistoryTypeId="2" PostId="10489" RevisionGUID="01dad061-aca3-4168-a325-82cf96300f63" CreationDate="2020-12-14T04:45:59.667" UserId="5909" Text="I'd like to add some practical perspective to this.&#xD;&#xA;&#xD;&#xA;Let me preface that I'm operating on limited information here:&#xD;&#xA;- I don't know how many objects you are dealing with.&#xD;&#xA;- I don't know what exactly your acceleration structure is used for. Frustum culling? Ray tracing? Collision detection between objects in the BVH?&#xD;&#xA;&#xD;&#xA;Going forward I'm going to assume you are talking about frustum culling a few thousand objects.&#xD;&#xA;&#xD;&#xA;&gt; The number of objects will be too large to render without a hierarchy,&#xD;&#xA;&gt; but for the same reason I expect building the hierarchy to be time&#xD;&#xA;&gt; consuming.&#xD;&#xA;&#xD;&#xA;I'd argue that if you have to visit every object every frame in order to calculate a BVH, culling them directly and without a BVH is actually faster.&#xD;&#xA;This of course depends on your frustum culling implementation. The bounding volumes of all objects should be stored contiguously in memory. This results in more efficient CPU cache utilization and allows for further optimization using SIMD instructions.&#xD;&#xA;**DICE has a whole presentation on this subject: [Culling the Battlefield: Data Oriented Design in Practice][1]**  &#xD;&#xA;The presentation also mentions speeding culling up even more, using a simple grid.&#xD;&#xA;&#xD;&#xA;Since I assume most 3D/simulation/game code bases already have some kind of BVH class and I don't know how critical it is for you to get the BEST culling performance, I'd like to present some arguments for sticking with a BVH:&#xD;&#xA;&#xD;&#xA;Depending on what method you use, constructing a BVH can be fast and simple.&#xD;&#xA;&#xD;&#xA;My current implementation of a binary BVH (each node can only have zero or two children and each leaf node only stores one item)&#xD;&#xA;that is designed for quick **construction takes around 0.18ms for 1137 objects on a single thread of an i7-5960X @ 3.89GHz**. I'm sure it can be faster.&#xD;&#xA;Construction is performed without reallocating memory in the process (this doubled the construction performance).&#xD;&#xA;&#xD;&#xA;While SAH might generate the best BVH, it takes a long time. SAH is good for things you can precompute, like collision meshes.&#xD;&#xA;At runtime you can then put the collision meshes into a BVH that is more suited for real-time construction.&#xD;&#xA;&#xD;&#xA;A fast and simple BVH construction approach (the one I'm using currently) is to sort all objects on an axis (for example the parent AABB's longest axis) and split the collection in the middle.&#xD;&#xA;&#xD;&#xA;To speed things up even more, calculate the node AABBs AFTER constructing the tree, by combining the two child node AABBs of a parent node. This avoids iterating through all objects (another 2x speedup).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.ea.com/frostbite/news/culling-the-battlefield-data-oriented-design-in-practice" ContentLicense="CC BY-SA 4.0" />
  <row Id="30501" PostHistoryTypeId="5" PostId="10489" RevisionGUID="d3be30d3-ae28-4ce9-8987-cb31eb091b61" CreationDate="2020-12-14T06:38:46.077" UserId="5909" Comment="added 93 characters in body" Text="I'd like to add some practical perspective to this.&#xD;&#xA;&#xD;&#xA;Let me preface that I'm operating on limited information here:&#xD;&#xA;- I don't know how many objects you are dealing with.&#xD;&#xA;- I don't know what exactly your acceleration structure is used for. Frustum culling? Ray tracing? Collision detection between objects in the BVH?&#xD;&#xA;&#xD;&#xA;Going forward I'm going to assume you are talking about frustum culling a few thousand objects.&#xD;&#xA;&#xD;&#xA;&gt; The number of objects will be too large to render without a hierarchy,&#xD;&#xA;&gt; but for the same reason I expect building the hierarchy to be time&#xD;&#xA;&gt; consuming.&#xD;&#xA;&#xD;&#xA;I'd argue that if you have to visit every object every frame in order to calculate a BVH, culling them directly and without a BVH is actually faster.&#xD;&#xA;This of course depends on your frustum culling implementation. The bounding volumes of all objects should be stored contiguously in memory. This results in more efficient CPU cache utilization and allows for further optimization using SIMD instructions.&#xD;&#xA;**DICE has a whole presentation on this subject: [Culling the Battlefield: Data Oriented Design in Practice][1]**  &#xD;&#xA;The presentation also mentions speeding culling up even more, using a simple grid.&#xD;&#xA;&#xD;&#xA;Since I assume most 3D/simulation/game code bases already have some kind of BVH class and I don't know how critical it is for you to get the BEST culling performance, I'd like to present some arguments for sticking with a BVH:&#xD;&#xA;&#xD;&#xA;Depending on what method you use, constructing a BVH can be fast and simple.&#xD;&#xA;&#xD;&#xA;My current implementation of a binary BVH (each node can only have zero or two children and each leaf node only stores one item)&#xD;&#xA;that is designed for quick **construction takes around 0.18ms for 1137 objects on a single thread of an i7-5960X @ 3.89GHz**. I'm sure it can be faster.&#xD;&#xA;Construction is performed without reallocating memory in the process (this doubled the construction performance).&#xD;&#xA;&#xD;&#xA;While SAH might generate the best BVH, it takes a long time. SAH is good for things you can precompute, like collision meshes.&#xD;&#xA;At runtime you can then put the collision meshes into a BVH that is more suited for real-time construction.&#xD;&#xA;&#xD;&#xA;A fast and simple BVH construction approach (the one I'm using currently) is to sort all objects on an axis (for example the parent AABB's longest axis) and split the collection in the middle.&#xD;&#xA;&#xD;&#xA;To speed things up even more, calculate the node AABBs AFTER constructing the tree, by combining the two child node AABBs of a parent node. This avoids iterating through all objects (another 2x speedup). This however is only possible if your splitting criterion doesn't rely on the parent's AABB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.ea.com/frostbite/news/culling-the-battlefield-data-oriented-design-in-practice" ContentLicense="CC BY-SA 4.0" />
  <row Id="30502" PostHistoryTypeId="2" PostId="10490" RevisionGUID="5f88a799-b89d-4f98-9cde-2a02f0bc34e2" CreationDate="2020-12-14T14:56:43.277" UserId="15372" Text="If we have an object at certain distance D in front of a camera. The object has a horizontal diameter d, giving us an angular diameter theta (2*arctan(d/2D)) of 50 degrees (converted from radians). And a camera of 100 FoV, horizontally.&#xD;&#xA;&#xD;&#xA;Given those figures, does that mean that the horizontal image size of the object will be exactly 50 % of the image width?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30503" PostHistoryTypeId="1" PostId="10490" RevisionGUID="5f88a799-b89d-4f98-9cde-2a02f0bc34e2" CreationDate="2020-12-14T14:56:43.277" UserId="15372" Text="Does angular diameter to FoV ratio equal object's image to total image ratio?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30504" PostHistoryTypeId="3" PostId="10490" RevisionGUID="5f88a799-b89d-4f98-9cde-2a02f0bc34e2" CreationDate="2020-12-14T14:56:43.277" UserId="15372" Text="|projections|perspective|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30505" PostHistoryTypeId="2" PostId="10491" RevisionGUID="5d5c7130-be1e-4b32-974f-f92c7dfdea43" CreationDate="2020-12-14T16:53:56.257" UserId="15377" Text="@ Physician --- We can use trigonometry and set-up a condition whereby the horizontal angle of view will be 100° &#xD;&#xA;  &#xD;&#xA;On a full frame 35mm camera format demotions 24mm by 36mm, mount a 15mm lens and horizontal angle of view will be 100°&#xD;&#xA;&#xD;&#xA;On an APS-C compact, the frame size is 16mm by 24mm. Mount a 10mm lens and the horizontal angle of view is 100° &#xD;&#xA;&#xD;&#xA;In other words, the angle of view of camera system intertwines focal length and format dimension.&#xD;&#xA;&#xD;&#xA;For the full frame camera above:&#xD;&#xA;The image plane falls 15mm downstream from the lens.  The Image triangle has a height of 15mm. The size of the angle at the apex of this triangle is 50°. We bisect this triangle creating two right triangles. The angle at the apex is 25°. The height of this triangle is 15mm. If you draw this triangle, the height is the adjacent side and the base is the opposite size. The tan of 25° = 0.4663. Thus Opposite / Adjacent = 0.4663. Thus Opposite side = 15mm X 0.4663 = 6.9946mm. The length of the image of the object will be 2X this value = 14mm.&#xD;&#xA;&#xD;&#xA;For the APS-C format:  The image plane falls 10mm downstream. Such as lash-up delivers a 100° horizontal angle of view. The image triangle angles are the same as for the full frame. Bisecting the image triangle, we get two right triangles each with a 25° apex. The tan of this angle = 0.4663. The height of this triangle is the focal length of the lens = 10mm. 10mm X 0.4663 = 4.66mm X 2 = 9.33mm. The image of the object will be 9.33mm long. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30507" PostHistoryTypeId="2" PostId="10492" RevisionGUID="e8c408cd-3cae-411a-8103-6f0c8c44f488" CreationDate="2020-12-14T18:47:20.677" UserId="15379" Text="@ Physician --- There are three flies in the ointment, all miniscule: The object distance is a measurement taken from a point within the optical system called the front nodal. The image distance is the focal length, a measurement taken from a point in the optical system called the rear nodal. The focal length is a measurement taken from the rear nodal to the image when the camera is focused on an object at infinity.&#xD;&#xA;&#xD;&#xA;In a multi element lens system the distance between front and rear nodal points will be unknown unless we run some tests. This could change the value we are using for the height of the image triangle. Additionally, if the object being imaged is closer than infinity, the height of the image triangle will be elongated. We are using the focal length as this value. &#xD;&#xA; &#xD;&#xA;Suppose a 10mm focal length lens is deployed. Suppose the object being imaged is 1 meter distant. What is the height of the image triangle? 1/10 x1000 = power of camera lens in diopters = 0.1 x 1000 = 100d. The object distance can be express in diopter units as 1/1000 x 1000 = 1d.&#xD;&#xA;&#xD;&#xA;We can calculate the image distance as 100d – 1d = 99d. Convert to millimeters = 1/99 x 1000 = 10.1mm. In other words, the fact that the object is not at infinity, elongates the image distance. If the object is 1 meter from the lens, using a 10mm lens, the image forms 10.1mm downstream from the lens. We were using 10mm as the height of the image triangle. In actually this should be 10.1mm &#xD;&#xA;Nothing is easy! &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30508" PostHistoryTypeId="2" PostId="10493" RevisionGUID="fd6216fc-e296-4cc4-b2aa-f6a4af7b0cf1" CreationDate="2020-12-14T20:27:20.003" UserId="13698" Text="I've been working through PBRT, implementing my own version of it in Rust. Right now I'm working on shadow rays, and it looks like pbrt doesn't do anything to account for specular behavior, and treats materials like perfect glass as opaque with respect to shadows. I decided to try to implement a version that accounts for this behavior, but I don't see a difference visually. Ignoring the bug that causes some of my threads to get stuck, the top one is my attempt at accounting for specular behavior and the bottom one is the 'normal' implementation that casts a single ray to see if it hits the light or not. &#xD;&#xA;&#xD;&#xA;[![mine][1]][1]&#xD;&#xA;&#xD;&#xA;[![normal][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/97xXs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/PQ7BV.png&#xD;&#xA;&#xD;&#xA;I can't see any difference in how the ground looks, and I don't believe that's how it should look for a perfectly specular glass model. My implementation is as follows  (it's in Rust, so I've commented to get the general idea across):&#xD;&#xA;&#xD;&#xA;```rust&#xD;&#xA;pub fn occlusion_intersects(&amp;self, ray: &amp;Ray, tmin: f64, tmax: f64, depth: i32) -&gt; Option&lt;HitRecord&gt; {&#xD;&#xA;    // find intersection with scene&#xD;&#xA;    let ans = self.intersects(ray, tmin, tmax);&#xD;&#xA;    // if no intersection was found, return None&#xD;&#xA;    if ans.is_none() {&#xD;&#xA;        return None&#xD;&#xA;    }&#xD;&#xA;    let mut ans = ans.unwrap(); // rust stuff, ignore this&#xD;&#xA;    // compute the bsdf for the material&#xD;&#xA;    Material::compute_scattering_default(&amp;mut ans);&#xD;&#xA;    // we only want to specular transmission or reflection&#xD;&#xA;    let bsdf_type = BSDF_TRANSMISSION | BSDF_REFLECTION | BSDF_SPECULAR;&#xD;&#xA;    // sample_f returns a new outgoing direction according to a bsdf that matches&#xD;&#xA;    // one of the types above, or (0, 0, 0) if no matching bsdfs.&#xD;&#xA;    let (wi, .. ) = ans.bsdf.sample_f(&amp;ans.wo, bsdf_type);&#xD;&#xA;    // if there was no specular bsdf or we've recursed too many times:&#xD;&#xA;    if (wi == util::zero_vector() || depth == MAX_DEPTH {&#xD;&#xA;        // then return the current intersection to check if it&#xD;&#xA;        // hit the expected light object&#xD;&#xA;        return Some(ans);&#xD;&#xA;    }&#xD;&#xA;    // otherwise make a new ray going in the new specular direction&#xD;&#xA;    let new_ray = ans.spawn_ray(&amp;wi);&#xD;&#xA;    // and return that answer&#xD;&#xA;    return self.occlusion_intersects(&amp;new_ray, tmin, tmax, depth + 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And for reference, the default implementation would be:&#xD;&#xA;&#xD;&#xA;```rust&#xD;&#xA;pub fn occlusion_intersects(&amp;self, ray: &amp;Ray, tmin: f64, tmax: f64, depth: i32) -&gt; Option&lt;HitRecord&gt; {&#xD;&#xA;    // return the first intersection, ignore all specular behavior&#xD;&#xA;    return self.intersects(ray, tmin, tmax);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Is there something wrong with my implementation? I kind of guessed as to how it would work, but the logic written in the comments makes sense to me." ContentLicense="CC BY-SA 4.0" />
  <row Id="30509" PostHistoryTypeId="1" PostId="10493" RevisionGUID="fd6216fc-e296-4cc4-b2aa-f6a4af7b0cf1" CreationDate="2020-12-14T20:27:20.003" UserId="13698" Text="How can I account for specular interactions in shadow rays?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30510" PostHistoryTypeId="3" PostId="10493" RevisionGUID="fd6216fc-e296-4cc4-b2aa-f6a4af7b0cf1" CreationDate="2020-12-14T20:27:20.003" UserId="13698" Text="|pathtracing|shadow|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30511" PostHistoryTypeId="2" PostId="10494" RevisionGUID="43dd6055-5f55-4ed5-aeb7-6396c28fe784" CreationDate="2020-12-14T23:39:59.277" UserId="48" Text="Shadow rays that hit a glass surface or similar are stopped because there's no _direct_ path from the light source to the shading point—there's a piece of glass in the way.&#xD;&#xA;&#xD;&#xA;&gt; for perfectly specular transmission/reflection, you can continue tracing the shadow ray because there's only one possible outgoing vector for a given incoming vector&#xD;&#xA;&#xD;&#xA;That won't work, because the transmission/reflection will change the direction of the ray. The shadow ray was presumably created by pointing it at a light source, but after transmission/reflection, it's most likely not going to hit the light source anymore.&#xD;&#xA;&#xD;&#xA;The idea of firing rays directly at light sources can be seen as a sampling strategy designed to exploit knowledge of which directions light is most likely to come from, and put your rays into those directions. If you're receiving light via a specular interaction rather than directly from the source, you don't know anymore which directions you should sample in.&#xD;&#xA;&#xD;&#xA;I imagine for simple cases like a glass sphere, etc, you could algebraically solve for a light path that would refract toward a chosen point on a light source. Then you could trace shadow rays along that path. But when you get into geometry as complex as the dragon, there's no realistic way to calculate which directions the light is going to come in from.&#xD;&#xA;&#xD;&#xA;When specular surfaces like glass or metal focus light onto a diffuse surface, that produces a caustic. Caustics are a notorious pain point for vanilla path tracing due to this problem—there is no way to know where to concentrate your samples to make your rays hit light sources, so the best you can do is fire rays in all directions (or sample from the BRDF) and hope that enough of them will find their way to a light source. Technically, path tracing can render caustics correctly, but it takes an _extremely_ large number of samples to do it.&#xD;&#xA;&#xD;&#xA;More practically, this issue can be solved by using photon mapping (which was invented precisely to deal with caustics), or some kind of path guiding methods like Metropolis and friends that can &quot;discover&quot; the caustics and dynamically concentrate samples around them." ContentLicense="CC BY-SA 4.0" />
  <row Id="30512" PostHistoryTypeId="2" PostId="10495" RevisionGUID="ce075abd-c96b-4685-a168-d30d2bc748d1" CreationDate="2020-12-15T05:36:32.843" UserId="11058" Text="I'm rendering an image onto a mesh. And I need to render fragments with uv coordinates that fall outside (0,1) range with full transparency. In the code below I'm specifying a border color with zero alpha. However I'm getting fully opaque border. Am I doing something wrong?&#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);&#xD;&#xA;    float border[] = {1, 1, 1, 0};&#xD;&#xA;	glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);&#xD;&#xA;&#xD;&#xA;Here is the fragment shader code:&#xD;&#xA;&#xD;&#xA;    out vec4 color;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        color = texture(tex, uv);&#xD;&#xA;    }&#xD;&#xA;I enabled alpha blending like this:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); &#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30513" PostHistoryTypeId="1" PostId="10495" RevisionGUID="ce075abd-c96b-4685-a168-d30d2bc748d1" CreationDate="2020-12-15T05:36:32.843" UserId="11058" Text="Render fragments with uvs outside (0,1) range as transparent" ContentLicense="CC BY-SA 4.0" />
  <row Id="30514" PostHistoryTypeId="3" PostId="10495" RevisionGUID="ce075abd-c96b-4685-a168-d30d2bc748d1" CreationDate="2020-12-15T05:36:32.843" UserId="11058" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30515" PostHistoryTypeId="5" PostId="10495" RevisionGUID="01946af0-1413-4fa7-b248-aece0b721aff" CreationDate="2020-12-15T07:45:29.463" UserId="11058" Comment="added 147 characters in body" Text="I'm rendering an image onto a mesh. And I need to render fragments with uv coordinates that fall outside (0,1) range with full transparency. In the code below I'm specifying a border color with zero alpha. However I'm getting fully opaque border. That is when texture itself does not have alpha channel. Is it possible to use a texture without alpha channel but still render fragments outside of the range as transparent?&#xD;&#xA;&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);&#xD;&#xA;	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);&#xD;&#xA;    float border[] = {1, 1, 1, 0};&#xD;&#xA;	glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);&#xD;&#xA;&#xD;&#xA;Here is the fragment shader code:&#xD;&#xA;&#xD;&#xA;    out vec4 color;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    uniform sampler2D tex;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        color = texture(tex, uv);&#xD;&#xA;    }&#xD;&#xA;I enabled alpha blending like this:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); &#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30516" PostHistoryTypeId="50" PostId="9645" RevisionGUID="c411ff7d-829b-4561-b76e-88cce8f9cfed" CreationDate="2020-12-15T17:07:20.723" UserId="-1" />
  <row Id="30517" PostHistoryTypeId="2" PostId="10496" RevisionGUID="c302621d-1122-459a-80a6-af033957cc42" CreationDate="2020-12-16T04:27:37.800" UserId="9749" Text="One approach for stuff like this that  I just heard is to do raymarching on simple analytical shapes that approximate the mesh, so you basically create an abstract coarse SDF representation of the mesh in question and raymarch some shadows. I have heard Iñigo Quilez mention it and talking on how he gave a conference about it once but I haven't found it, I think it was either Gamescon or SIGGRAPH." ContentLicense="CC BY-SA 4.0" />
  <row Id="30518" PostHistoryTypeId="50" PostId="9549" RevisionGUID="0a468cd9-eb4a-4e7d-8ed4-50cf1781ce3a" CreationDate="2020-12-16T11:00:15.077" UserId="-1" />
  <row Id="30519" PostHistoryTypeId="5" PostId="4141" RevisionGUID="bd888941-521a-4af3-b60e-835b9913a34e" CreationDate="2020-12-16T17:52:25.930" UserId="15262" Comment="Update dead link." Text="When I implemented real-time area lighting, there were two documents I kept referring to: &quot;[Moving Frostbite to PBR][1]&quot; by Sebastien Lagarde and &quot;[Real Shading in Unreal Engine 4][2]&quot; by Brian Karis. Also &quot;[Lighting of Killzone Shadow Fall][3]&quot; by Michal Drobot is an interesting read on the topic. None of these documents deal with area shadows though but focus on energy conserving approximation of the lighting integral. While there are some code snippets, these documents lack quite a bit of details of how to implement area lighting though, so you need to do fair amount of research on your own. For example I posted a question and an answer [here][4] related to implementing rectangular area lights.&#xD;&#xA;&#xD;&#xA;A very valuable tool I used was to implement a Monte Carlo reference model to easily compare different approximations to the ground truth. Some people also use [Mitsuba renderer][5] to validate their implementations. I think this ground truth reference is extremely important so that you know if there are mistakes in your implementation and also to see where/how these approximations fail and if you can somehow try to improve them. Implementing Monte Carlo integration is also quite a good exercise to understand the underlying problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf&#xD;&#xA;  [2]: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf&#xD;&#xA;  [3]: https://www.guerrilla-games.com/read/killzone-shadow-fall-creating-art-tools-for-a-new-generation&#xD;&#xA;  [4]: https://math.stackexchange.com/questions/1438242/finding-ray-direction-with-smallest-angle-from-a-ray-to-a-rectangle-in-3d&#xD;&#xA;  [5]: http://www.mitsuba-renderer.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="30520" PostHistoryTypeId="24" PostId="4141" RevisionGUID="bd888941-521a-4af3-b60e-835b9913a34e" CreationDate="2020-12-16T17:52:25.930" Comment="Proposed by 15262 approved by 13095 edit id of 547" ContentLicense="CC BY-SA 4.0" />
  <row Id="30521" PostHistoryTypeId="2" PostId="10497" RevisionGUID="f187f1eb-e66e-4c27-b79e-7316aff8377c" CreationDate="2020-12-17T04:38:03.870" UserId="7462" Text="I wonder if someone knows of a paper that tries to mimic how mathematicians draw diagrams.&#xD;&#xA;&#xD;&#xA;For example Look at this shirt:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RJiSv.png&#xD;&#xA;&#xD;&#xA;The diagrams represent 2D and 3D shapes, however they have things characterisitc of human drawings. The curves are not perfect and exhibit lot's of noise and waviness that a computer rendering would normally not have.&#xD;&#xA;&#xD;&#xA;As a side not and perhaps somewhat off topic. Is there a C++ library that can do tex rendering onto textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30522" PostHistoryTypeId="1" PostId="10497" RevisionGUID="f187f1eb-e66e-4c27-b79e-7316aff8377c" CreationDate="2020-12-17T04:38:03.870" UserId="7462" Text="Stylized math like rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30523" PostHistoryTypeId="3" PostId="10497" RevisionGUID="f187f1eb-e66e-4c27-b79e-7316aff8377c" CreationDate="2020-12-17T04:38:03.870" UserId="7462" Text="|rendering|shader|mathematics|shading|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30524" PostHistoryTypeId="2" PostId="10498" RevisionGUID="41c7f400-fb14-44b2-95d8-5a2ac9ac4ace" CreationDate="2020-12-18T02:52:28.893" UserId="15133" Text="I was trying to follow this http://foundationsofgameenginedev.com/FGED2-sample.pdf&#xD;&#xA;&#xD;&#xA;But had problem understanding formula 7.33.&#xD;&#xA;$$p_i-p_j=(u_i-u_j)\mathrm{t}+(v_i-v_j)\mathrm{b}$$ &#xD;&#xA;\* $p_i,p_j$ being vertices on a triangle, and $u_*,v_*$ being their texture coordiniates, and $M_{tangent}=\left[\mathrm{t}\space\mathrm{b}\space\mathrm{n}\right]$&#xD;&#xA;&#xD;&#xA;If the matrix has to be orthogonal (why though?), then if I'm not mistaken, all its vectors have to measure 1 in magnitude. It surely looks like there lacks constraints on $p_i$ and $p_j$ - they can be at any distance from each other while $\left|u_i-u_j\right|&lt;1$.&#xD;&#xA;&#xD;&#xA;Where did I get it wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30525" PostHistoryTypeId="1" PostId="10498" RevisionGUID="41c7f400-fb14-44b2-95d8-5a2ac9ac4ace" CreationDate="2020-12-18T02:52:28.893" UserId="15133" Text="Help me understand the derivation of this tangent space to object space matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="30526" PostHistoryTypeId="3" PostId="10498" RevisionGUID="41c7f400-fb14-44b2-95d8-5a2ac9ac4ace" CreationDate="2020-12-18T02:52:28.893" UserId="15133" Text="|transformations|shading|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30527" PostHistoryTypeId="2" PostId="10499" RevisionGUID="30fc74a9-bf2a-4810-ac34-99ebc9ab5115" CreationDate="2020-12-18T19:32:42.160" UserId="15403" Text="I hope this is the correct place to ask this question. It feels to me that I should ask people who have had to program graphics as there’s a lot of confusion about color depth in general.&#xD;&#xA;&#xD;&#xA;I’m sure a lot of people are aware that Adobe Photoshop can render OpenGL to 10bpc/30bit displays as long as the graphics card, divers and monitor support it.&#xD;&#xA;&#xD;&#xA;My question is, now that we have monitors that can display HDR, are these HDR monitors also capable of doing rendering in Photoshop 10-bit?&#xD;&#xA;&#xD;&#xA;I apologise if I’m not allowed to ask this question here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks to all taking the time to reply,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Phaethon&#xD;&#xA;&#xD;&#xA;(I tried to drive my dad’s car and it didn’t end well)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30528" PostHistoryTypeId="1" PostId="10499" RevisionGUID="30fc74a9-bf2a-4810-ac34-99ebc9ab5115" CreationDate="2020-12-18T19:32:42.160" UserId="15403" Text="Colour Depth in Hardware" ContentLicense="CC BY-SA 4.0" />
  <row Id="30529" PostHistoryTypeId="3" PostId="10499" RevisionGUID="30fc74a9-bf2a-4810-ac34-99ebc9ab5115" CreationDate="2020-12-18T19:32:42.160" UserId="15403" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30530" PostHistoryTypeId="50" PostId="10045" RevisionGUID="468e907b-d862-4e88-9ac1-0b59feae8b03" CreationDate="2020-12-18T20:04:40.557" UserId="-1" />
  <row Id="30531" PostHistoryTypeId="6" PostId="8824" RevisionGUID="16731d10-bf70-4158-b2b4-55bfbc996f27" CreationDate="2020-12-18T23:02:41.210" UserId="2289" Comment="new tags describing content of the question" Text="|c++|image-processing|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30532" PostHistoryTypeId="24" PostId="8824" RevisionGUID="16731d10-bf70-4158-b2b4-55bfbc996f27" CreationDate="2020-12-18T23:02:41.210" Comment="Proposed by 2289 approved by 13095 edit id of 548" ContentLicense="CC BY-SA 4.0" />
  <row Id="30533" PostHistoryTypeId="5" PostId="10499" RevisionGUID="48aed280-e31b-4cef-8617-36a16ee0ff7a" CreationDate="2020-12-18T23:07:58.437" UserId="13095" Comment="Remove unnecessary text" Text="I hope this is the correct place to ask this question. It feels to me that I should ask people who have had to program graphics as there’s a lot of confusion about color depth in general.&#xD;&#xA;&#xD;&#xA;I’m sure a lot of people are aware that Adobe Photoshop can render OpenGL to 10bpc/30bit displays as long as the graphics card, divers and monitor support it.&#xD;&#xA;&#xD;&#xA;My question is, now that we have monitors that can display HDR, are these HDR monitors also capable of doing rendering in Photoshop 10-bit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30535" PostHistoryTypeId="50" PostId="2146" RevisionGUID="e93a9e89-afa7-4ca4-b86a-1f17cf0754d1" CreationDate="2020-12-19T07:00:25.037" UserId="-1" />
  <row Id="30539" PostHistoryTypeId="5" PostId="10497" RevisionGUID="36baa22d-caf0-4b31-b2ac-2e61ce052eb8" CreationDate="2020-12-19T13:29:52.133" UserId="13095" Comment="Modify question to be on-topic" Text="I wonder if someone knows of a paper that tries to mimic how mathematicians draw diagrams.&#xD;&#xA;&#xD;&#xA;How can I render plots and graphics that mimic how mathematicians draw diagrams?&#xD;&#xA;&#xD;&#xA;For example Look at this shirt:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RJiSv.png&#xD;&#xA;&#xD;&#xA;The diagrams represent 2D and 3D shapes, however they have characteristics of human drawings. The curves are not perfect and exhibit lot's of noise and waviness that a computer rendering would normally not have.&#xD;&#xA;If you know any papers regarding this topic, please add them as reference to your answer.&#xD;&#xA;&#xD;&#xA;As a side note and perhaps somewhat off topic: Is there a C++ library that can do tex rendering onto textures?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30541" PostHistoryTypeId="5" PostId="10497" RevisionGUID="87152169-8014-4587-ae41-e25572c587f0" CreationDate="2020-12-19T13:41:12.013" UserId="13095" Comment="deleted 94 characters in body" Text="How can I render plots and graphics that mimic how mathematicians draw diagrams?&#xD;&#xA;&#xD;&#xA;For example Look at this shirt:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RJiSv.png&#xD;&#xA;&#xD;&#xA;The diagrams represent 2D and 3D shapes, however they have characteristics of human drawings. The curves are not perfect and exhibit lot's of noise and waviness that a computer rendering would normally not have.&#xD;&#xA;If you know any papers regarding this topic, please add them as reference to your answer.&#xD;&#xA;&#xD;&#xA;As a side note and perhaps somewhat off topic: Is there a C++ library that can do tex rendering onto textures?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30542" PostHistoryTypeId="50" PostId="8886" RevisionGUID="f6eef9f0-a3a9-4a58-b2a4-374a09849b53" CreationDate="2020-12-19T14:04:45.523" UserId="-1" />
  <row Id="30543" PostHistoryTypeId="5" PostId="6240" RevisionGUID="731ca328-141e-4f7d-92f6-e8f0cc0a66ee" CreationDate="2020-12-19T15:06:24.307" UserId="8009" Comment="fixed minor typo." Text="I took a few days and wrote something to do this.  It was not really as straightforward as I was expecting so I'll share what I learned.&#xD;&#xA;&#xD;&#xA;# What was hard&#xD;&#xA;&#xD;&#xA;Here are the major headaches I encountered.&#xD;&#xA;&#xD;&#xA;### Dealing with JPEG Compression Artifacts&#xD;&#xA;&#xD;&#xA;When sampling the values for the legend, I encountered many JPEG compression artifacts. This required me to apply a median filter.  The median filter width needed to be a parameter of the function (needs different values depending on how big the legend is.)&#xD;&#xA;&#xD;&#xA;### Dealing with &quot;bands&quot; in the legend&#xD;&#xA;&#xD;&#xA;The legend in your first example is divided into discrete sections (bands) and the numeric quantity desired is probably the middle of the range that the colour spans.  For example, the left-most box covers values from -6500 to -6000 and should probably return &quot;-6250&quot; when trying to sample a single colour of that value.  Also, consequently, no pixel will return the value &quot;0&quot;.  There is no colour representation for &quot;0&quot; (in that first map anyway.)&#xD;&#xA;&#xD;&#xA;### Dealing with differences in tone / value.&#xD;&#xA;&#xD;&#xA;Sometimes the exact colour in the map doesn't exist in the legend, especially due to the text labels, so you have to do a &quot;closest&quot; matching algorithm and the hue seems to be more important than the value (black&amp;white-ness) so it was better to evaluate &quot;distance&quot; between colours in a colourspace other than RGB. &#xD;&#xA;&#xD;&#xA;### Text overwrites data&#xD;&#xA;&#xD;&#xA;There are plenty of black pixels in the map due to the labels, but these need to be ignored somehow.  It makes sense to try to infer what the value behind the text is, and only colours that are not in the legend qualify for this kind of inference.&#xD;&#xA;&#xD;&#xA;### Manually selecting points on the legend is not precise&#xD;&#xA;&#xD;&#xA;Each time I eye-balled it and manually found a point that looked like approximately the end-point, I'd choose a slightly different pixel, resulting in slightly different values between attempts.  Perhaps a snapping technique would be better where I could &quot;hint&quot; where the legend is, but it would find the high-contrast edge markings and snap the hint point to the exact point.&#xD;&#xA;&#xD;&#xA;### Most maps don't have continuous legends.&#xD;&#xA;&#xD;&#xA;Most other images that I went searching for with test data had discontinuities in their legend (discrete boxes of colour) as opposed to a nice continuous linear gradient like you provided.  This makes it extra difficult to automatically come up with the mapping from colour to value just by analyzing the positions of the colours in the legend.  I was disappointed when trying to apply it to most maps.&#xD;&#xA;&#xD;&#xA;### Visualization tips&#xD;&#xA;&#xD;&#xA;It was very useful (especially while debugging) to visually show the point on the legend that it thought best corresponded to the colour being picked in the map.&#xD;&#xA;&#xD;&#xA;### Persistence&#xD;&#xA;&#xD;&#xA;It's useful to persist the location of the endpoints of the linear gradient portion of the legend and the values that are associated with them between runs of the application.  Don't underestimate the value of this.  It's annoying to have to specify all that stuff every time.&#xD;&#xA;&#xD;&#xA;# What worked well&#xD;&#xA;&#xD;&#xA;### Represent the legend as all the pixels along a line segment&#xD;&#xA;&#xD;&#xA;Specify two (x,y) locations of the start and end of a linear gradient (the legend) and manually define the values that are associated with them.&#xD;&#xA;&#xD;&#xA;### build up a discrete sample set for the gradient&#xD;&#xA;&#xD;&#xA;Sample all the pixels in between the start and end points to build a linear gradient dataset.&#xD;&#xA;&#xD;&#xA;### Median filter&#xD;&#xA;&#xD;&#xA;Apply a median filter to the linear gradient dataset to filter out JPEG noise.&#xD;&#xA;&#xD;&#xA;### Quantize the dataset to locate centroids&#xD;&#xA;&#xD;&#xA;Optionally filter out bands (long runs of samples in the linear gradient dataset that have approximately the same colour) and replace them with a single sample at the centroid (average position).&#xD;&#xA;&#xD;&#xA;### Use bilinear sampling when picking a pixel&#xD;&#xA;&#xD;&#xA;Pick a pixel in the map and perform a bilinear sample to smooth out pixellation.  This seems to help improve the smoothness and resolution of the map.&#xD;&#xA;&#xD;&#xA;### Linear search is fine&#xD;&#xA;&#xD;&#xA;Linearly search for the data point in the linear gradient for the closest colour.  For an interactive picker working from mouse clicks, you have lots of time to perform a linear search.  No fancy hashing, indexing or optimized searching was required.&#xD;&#xA;&#xD;&#xA;### Hue is important in the colour distance function&#xD;&#xA;&#xD;&#xA;Compare distance between colours using a distance function in a colourspace that tolerates brightness difference more than hue difference.  (like YUV, for example)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30544" PostHistoryTypeId="2" PostId="10501" RevisionGUID="8bcfc3e9-48b9-457f-9a25-cf4bba019eea" CreationDate="2020-12-19T19:37:35.990" UserId="15410" Text="I have saw a clip where a guy talked about the art of squeezing some nice graphics into a very small space that was available on old computers. Come to think of it, it sounded something like today's git, where the changes were being saved, between the scenes, and the way it was rendered on screen. I have been searching for hours on YT and google and I couldn't find it, please help.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The game was from 80's or early 90's, and the scene I vaguely remember is a car parking in front of a building (probably a bar or a house) at night. The graphics was pretty dark, it was dark blue, indigo or purple, or some shades of those, but the headlights were bright yellow I think. The thing I remember about the clip was describing this scene in much detail, how it would use much more space if not for nifty tricks used by programmers.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have tried searching google and YT for this keywords: old, game, noir, adventure, mystery, car, graphics, compression, methods, space, techniques, etc. Google didn't give me a screenshot I could recognize, I am not sure if it was YT or an example in a tutorial about computer graphics on some learning platform, sorry.&#xD;&#xA;I even tried drawing the scene and searching by image on google, didn't help. Here is my drawing.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;It was a great clip and inability to find it again is driving me mad, please help me if what i described seems familiar, that clip is a keeper really, I think most of the people here would enjoy it.&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9kWgp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30545" PostHistoryTypeId="1" PostId="10501" RevisionGUID="8bcfc3e9-48b9-457f-9a25-cf4bba019eea" CreationDate="2020-12-19T19:37:35.990" UserId="15410" Text="I am trying to find a clip about the art of old computer graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="30546" PostHistoryTypeId="3" PostId="10501" RevisionGUID="8bcfc3e9-48b9-457f-9a25-cf4bba019eea" CreationDate="2020-12-19T19:37:35.990" UserId="15410" Text="|rendering|lighting|performance|optimisation|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30547" PostHistoryTypeId="2" PostId="10502" RevisionGUID="b8128800-fc4b-4cc4-ad89-6c8f802bfc17" CreationDate="2020-12-19T20:14:56.807" UserId="48" Text="Maybe. HDR monitors are typically going to be some approximation of the [DCI-P3](https://en.wikipedia.org/wiki/DCI-P3) color space, while Adobe's wide-color rendering is the [Adobe RGB](https://en.wikipedia.org/wiki/Adobe_RGB_color_space) color space. The two are similar but not quite the same; in particular, Adobe RGB extends a bit further into the green-cyan range than DCI-P3 does:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/no6dI.png&quot; width=&quot;558&quot; height=&quot;633&quot; alt=&quot;Adobe RGB and DCI-P3 on CIE chromaticity diagram&quot;&gt;&#xD;&#xA;&#xD;&#xA;That said, these are only idealized color spaces, and the gamut of a given actual monitor is going to differ somewhat from these. That's why you'll see monitors advertised as having &quot;99% Adobe RGB coverage&quot; or &quot;99% DCI-P3&quot; or some such.&#xD;&#xA;&#xD;&#xA;So, a typical HDR monitor can probably reproduce _most_ of the Adobe space but maybe not quite all of it, but in practice it might be just about as good as an actual Adobe-supporting monitor.&#xD;&#xA;&#xD;&#xA;That said, I don't know whether Photoshop and the drivers/OS/etc will actually cooperate to let you turn on Adobe RGB rendering on a DCI-P3 HDR monitor. If Photoshop is outputting 10-bit color in Adobe RGB space, but the monitor doesn't actually take that format, then it would need to be converted somewhere along the line to a color space and encoding that the monitor can take as input. That can certainly be done by the graphics card/drivers/OS, but I don't know whether the support for doing such conversions is actually there." ContentLicense="CC BY-SA 4.0" />
  <row Id="30548" PostHistoryTypeId="2" PostId="10503" RevisionGUID="6004e961-c623-481f-a890-d028af34a6ba" CreationDate="2020-12-20T11:47:18.603" UserId="15415" Text="I am unable to visualize what is principal vanishing point w.r.t to x axis ,y axis z axis  do someone can post some simple  diagram to understand what is it? Also I have question in my text book &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rR8lw.jpg&#xD;&#xA; Now the question is how to calculate vanishing point and what is the line A' B' ![enter image description here](https://i.stack.imgur.com/Y7F04.jpg)![enter image description here](https://i.stack.imgur.com/5CNai.jpg) please help" ContentLicense="CC BY-SA 4.0" />
  <row Id="30549" PostHistoryTypeId="1" PostId="10503" RevisionGUID="6004e961-c623-481f-a890-d028af34a6ba" CreationDate="2020-12-20T11:47:18.603" UserId="15415" Text="What is principal vanishing point in perspective projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30550" PostHistoryTypeId="3" PostId="10503" RevisionGUID="6004e961-c623-481f-a890-d028af34a6ba" CreationDate="2020-12-20T11:47:18.603" UserId="15415" Text="|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30551" PostHistoryTypeId="2" PostId="10504" RevisionGUID="babaddab-7775-4c82-bc3b-1c73edf94835" CreationDate="2020-12-20T11:59:06.283" UserId="15413" Text="You might want to check [matplotlib-cpp][1]. You'll find a &quot;funny-looking xkcd-styled example&quot; in the README. &#xD;&#xA;&#xD;&#xA;I also saw xkcd related entries on matplotlib's Python documentation. So it should be available in Python too. However I did not use these libraries myself. I just stumbled upon this matplotlib-cpp library while I was looking for a plotting library for C++.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/lava/matplotlib-cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="30552" PostHistoryTypeId="5" PostId="10503" RevisionGUID="8a535c24-dcce-4aaf-803f-c00538fc37b6" CreationDate="2020-12-20T12:03:34.337" UserId="15415" Comment="added 245 characters in body" Text="I am unable to visualize what is principal vanishing point w.r.t to x axis ,y axis z axis  do someone can post some simple  diagram to understand what is it? Also I have question in my text book &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rR8lw.jpg&#xD;&#xA; Now the question is how to calculate vanishing point and what is the line A' B' ![enter image description here](https://i.stack.imgur.com/Y7F04.jpg)![enter image description here](https://i.stack.imgur.com/5CNai.jpg) solution is also given which is (0,0,0) as vanishing point but I am unable to understand how do they get it figure shows it as (0,0,2) ,also what is d in the solution here is the solution ![enter image description here](https://i.stack.imgur.com/1R8tk.jpg)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30553" PostHistoryTypeId="2" PostId="10505" RevisionGUID="6263c819-b700-485f-81ea-9e733db77cc9" CreationDate="2020-12-20T16:24:07.567" UserId="6046" Text="Basically whenever you project a set of parallel lines in 3D space on a 2D image plane, you'll see that these lines don't remain parallel in 2D space and tend to meet at a certain point which is the so called vanishing point. Picture a long railway, both the rail lines meet at the horizon.&#xD;&#xA;&#xD;&#xA;Now one confusion arises that the question doesnt give you a set of parallel lines, But it doesn't matter as long as a single line segment is provided. All you need to do is just picture the line segment extending to infinity. So for example, picture the point $B$ at infinity and imagine drawing a line $BE$. The point at which this line intersects the image plane will be your vanishing point.&#xD;&#xA;&#xD;&#xA;There is a simple pattern that applies to every case like this. Just shoot a ray in the direction of the vector $\vec{AB}$ from the point $E$. The point at which this ray intersects the image plane will be your vanishing point which as you can see is $(0,0,0)$. &#xD;&#xA;&#xD;&#xA;Now imagine why this works. Picture the point $B$ extending up, and at each instance start drawing segments $BE$. You'll see that this line segment is moving towards the $Z$ axis.&#xD;&#xA;So if you are projecting a point $B$ at infinity then the projecting line or segment $BE$ gonna become parallel to the line $AB$. However, it can't go past the $Z$ axis, as this will start going in the opposite direction.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30554" PostHistoryTypeId="2" PostId="10506" RevisionGUID="66805484-7b48-4a04-9914-86e7d718e5e1" CreationDate="2020-12-20T20:06:03.867" UserId="15417" Text="i dont know if i can create a virtual server (with vmware, virtual box or with something like that), and if i can use the full power of my graph (i have a nvidia rtx 2080 super) or if I'm going to lose some power of this gpu.&#xD;&#xA;&#xD;&#xA;or which tools can i use?&#xD;&#xA;&#xD;&#xA;    print('please dont close this i need to know the answer')&#xD;&#xA;&#xD;&#xA;So, can i connect a rtx 2080 super to my server, and create a virtual server with the full power of the graph?? i need to know if I can use the full power of the graph or not, for example, i want to create a virtual server for play videogames in every place, so i only have to connect to this server and play (this is only an example) so this server will use the full power of the graph nvidai rtx 2080 super or not?? Thanks so much, and i cant try this if i dont know if it will works, because i have to buy the graph." ContentLicense="CC BY-SA 4.0" />
  <row Id="30555" PostHistoryTypeId="1" PostId="10506" RevisionGUID="66805484-7b48-4a04-9914-86e7d718e5e1" CreationDate="2020-12-20T20:06:03.867" UserId="15417" Text="Create a virtual server which use the full power of my GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="30556" PostHistoryTypeId="3" PostId="10506" RevisionGUID="66805484-7b48-4a04-9914-86e7d718e5e1" CreationDate="2020-12-20T20:06:03.867" UserId="15417" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30557" PostHistoryTypeId="5" PostId="10504" RevisionGUID="176621f2-dc68-4908-904d-beb4244ec7b2" CreationDate="2020-12-20T21:25:16.777" UserId="15413" Comment="Fixed grammar." Text="You might want to check [matplotlib-cpp][1]. You'll find a &quot;funny-looking xkcd-styled example&quot; in the README. &#xD;&#xA;&#xD;&#xA;I also saw xkcd related entries on matplotlib's Python documentation. So, it should be available in Python too. However I did not use these libraries myself. I just stumbled upon matplotlib-cpp while I was looking for a plotting library for C++.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/lava/matplotlib-cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="30558" PostHistoryTypeId="6" PostId="10486" RevisionGUID="50ca4e65-da25-4d60-aeca-fb36c7c9ef76" CreationDate="2020-12-20T21:47:30.787" UserId="5778" Comment="tags edited" Text="|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30559" PostHistoryTypeId="24" PostId="10486" RevisionGUID="50ca4e65-da25-4d60-aeca-fb36c7c9ef76" CreationDate="2020-12-20T21:47:30.787" Comment="Proposed by 5778 approved by 13095 edit id of 549" ContentLicense="CC BY-SA 4.0" />
  <row Id="30560" PostHistoryTypeId="5" PostId="2326" RevisionGUID="0d177944-8582-4b57-a6d9-2c92ea66c979" CreationDate="2020-12-20T21:48:55.710" UserId="5778" Comment="broken image fixed (click 'rendered output' or 'side-by-side' to see the difference); for more info, see https://gist.github.com/Glorfindel83/9d954d34385d2ac2597bbe864466259f" Text="I'm interested in virtual reality, but according to some sources, less than 1% of computers in use today have the necessary performance to run modern VR games, granted many of them are not intended for gaming, that's still a huge barrier for the widespread adoption of VR headsets into the market. So I was wondering what could be done to reduce the performance requirements of a VR game that hasn't been implemented with such optimizations in mind.&#xD;&#xA;&#xD;&#xA;I'm talking about technologies like foveated rendering, which (ab)uses the fact that we only ever perceive a few degrees in the center of our field of vision as sharp while everything else is blurry. This can be combined with eye tracking so that only the areas where the player is looking are rendered in full quality, while we can reduce the render quality and therefore the performance requirements everywhere else.&#xD;&#xA;This seems like a great advantage and I honestly wonder why none of the major VR companies have implemented eye tracking into their headsets and foveated rendering into their SDKs into their headsets. The technology exists and I can't imagine that it would add much to the price tag.&#xD;&#xA;[Paper about foveated rendering][2]&#xD;&#xA;	&#xD;&#xA;There's also instanced stereo rendering which basically renders things to both eyes at the same time rather than rendering it for each eye individually.&#xD;&#xA;[![Example gif for Instanced Stero Rendering - Epic Games, Unreal Engine 4.11 release notes][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It's also possible to use just one frustum for both eyes rather than two as discussed here.&#xD;&#xA;[VR and frustum culling](https://computergraphics.stackexchange.com/questions/1736/vr-and-frustum-culling)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But are there other approaches to the performane problem?&#xA;&#xA; [1]: https://web.archive.org/web/20160712094453/https://docs.unrealengine.com/latest/images/Support/Builds/ReleaseNotes/2016/4_11/image_16.gif&#xA; [2]: https://www.microsoft.com/en-us/research/publication/foveated-3d-graphics/?from=http://research.microsoft.com/pubs/176610/foveated_final15.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="30561" PostHistoryTypeId="24" PostId="2326" RevisionGUID="0d177944-8582-4b57-a6d9-2c92ea66c979" CreationDate="2020-12-20T21:48:55.710" Comment="Proposed by 5778 approved by 13095 edit id of 550" ContentLicense="CC BY-SA 4.0" />
  <row Id="30562" PostHistoryTypeId="2" PostId="10507" RevisionGUID="30a24efd-2081-4bd0-9513-b05806e03660" CreationDate="2020-12-21T02:03:20.927" UserId="7462" Text="I have the following challenge. I am given a black and white image with rasterized lines.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Given this input, I want to extend the edges to cover more than one pixel and antialias the edges.&#xD;&#xA;&#xD;&#xA;My first attempt was to pass a morphological dilation followed by a gaussian filter. But that straight up did not work, all i got is for the image to look blurry.&#xD;&#xA;&#xD;&#xA;I instead tried combining both effects into a single shader and go the following:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This is decent, but you can still see a lot of the original aliasing of the edges.&#xD;&#xA;&#xD;&#xA;Assuming that I only have the input image, are there any image based / screen space based AA techniques I can use to make the edges look smooth?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d5k2P.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DuACy.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/V4QmM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30563" PostHistoryTypeId="1" PostId="10507" RevisionGUID="30a24efd-2081-4bd0-9513-b05806e03660" CreationDate="2020-12-21T02:03:20.927" UserId="7462" Text="Screen Space anti aliasing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30564" PostHistoryTypeId="3" PostId="10507" RevisionGUID="30a24efd-2081-4bd0-9513-b05806e03660" CreationDate="2020-12-21T02:03:20.927" UserId="7462" Text="|rendering|shader|antialiasing|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30565" PostHistoryTypeId="50" PostId="8321" RevisionGUID="0e1a762d-cfdf-4128-8306-fc6a45908814" CreationDate="2020-12-21T05:07:15.663" UserId="-1" />
  <row Id="30566" PostHistoryTypeId="5" PostId="10503" RevisionGUID="bf526235-e33f-49f4-9af3-0b647be922b9" CreationDate="2020-12-21T07:53:28.433" UserId="15415" Comment="deleted 9 characters in body" Text="I am unable to visualize what is principal vanishing point w.r.t to x axis ,y axis z axis  do someone can post some simple  diagram to understand what is it? Also I have question in my text book &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rR8lw.jpg&#xD;&#xA; ' ![enter image description here](https://i.stack.imgur.com/Y7F04.jpg)![enter image description here](https://i.stack.imgur.com/5CNai.jpg)       Now the question is how to calculate vanishing point and what is the line A' B ?Solution is also given which is (0,0,0) as vanishing point but I am unable to understand how do they get it , figure (k)shows it as (0,0,2) ,also what is d in the solution?![enter image description here](https://i.stack.imgur.com/yjCta.jpg)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30567" PostHistoryTypeId="33" PostId="10467" RevisionGUID="624f9d05-23db-4c0e-9f8c-cd38801d2fdd" CreationDate="2020-12-21T11:15:00.397" UserId="15340" Comment="68" />
  <row Id="30568" PostHistoryTypeId="5" PostId="10504" RevisionGUID="805b4d73-008b-4876-b0fc-b13cc3e909f6" CreationDate="2020-12-21T13:24:05.973" UserId="15413" Comment="punctuation" Text="You might want to check [matplotlib-cpp][1]. You'll find a &quot;funny-looking xkcd-styled example&quot; in the README. &#xD;&#xA;&#xD;&#xA;I also saw xkcd related entries on matplotlib's Python documentation. So, it should be available in Python too. However, I did not use these libraries myself. I just stumbled upon matplotlib-cpp while I was looking for a plotting library for C++.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/lava/matplotlib-cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="30569" PostHistoryTypeId="50" PostId="8695" RevisionGUID="5c005af4-fd20-43aa-a13e-9ba1cdd30b4d" CreationDate="2020-12-21T19:02:35.387" UserId="-1" />
  <row Id="30570" PostHistoryTypeId="2" PostId="10508" RevisionGUID="58e8a32a-5976-4692-88bc-80a7ac547159" CreationDate="2020-12-22T13:09:26.683" UserId="10096" Text="The easiest way to deal with this would be to provide thickness for the edges in the continuous setting. That is, make your edges out of solid capsules/cylinders, then you would not have this issue. Technically, this is is neither a supersampling nor a filtering technique, but rather a reformulation of the problem in the continuous setting. Another equivalent reformulation is considering only the vertices and then your reconstruction function being thick edges between those (using a thick line algorithm). &#xD;&#xA;&#xD;&#xA;This doesn't seem to be your setting however? Since you mentioned that you only have the raster (aliased) image already, in which case you have already introduced the error so it is hard to get rid off. If you can &quot;access&quot; the continuous model it is a lot easier to fix. If you cannot, then I could recommend using a different reconstruction filter than the dilation that you are using. For instance you can do a thickening based on distance to pixels (sdf) with a step function. This should remove the issues you are having, at least for the example you showed." ContentLicense="CC BY-SA 4.0" />
  <row Id="30571" PostHistoryTypeId="50" PostId="8779" RevisionGUID="c6d30da3-68d9-49bb-9e66-cad68378fb88" CreationDate="2020-12-22T19:04:35.363" UserId="-1" />
  <row Id="30572" PostHistoryTypeId="2" PostId="10509" RevisionGUID="eea8838f-2526-4c21-83c6-62477fee99d8" CreationDate="2020-12-22T21:02:05.077" UserId="15427" Text="I've been following the OpenGL tutorials from ThinMatrix and I've been able to load and render his stall.obj model along with his stall.png texture just fine. But when I try with my own  models and textures from Blender, the texture appears &quot;distorted&quot; and I can't seem to find the problem. I'm guessing the problem is with my texture, but I can't find anything that would cause this problem. What could be the cause of this problem?&#xD;&#xA;&#xD;&#xA;[![Blender][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![OpenGL][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wuDZL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4MD8Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30573" PostHistoryTypeId="1" PostId="10509" RevisionGUID="eea8838f-2526-4c21-83c6-62477fee99d8" CreationDate="2020-12-22T21:02:05.077" UserId="15427" Text="PNG textures render correctly in Blender, but not in OpenGL program" ContentLicense="CC BY-SA 4.0" />
  <row Id="30574" PostHistoryTypeId="3" PostId="10509" RevisionGUID="eea8838f-2526-4c21-83c6-62477fee99d8" CreationDate="2020-12-22T21:02:05.077" UserId="15427" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30575" PostHistoryTypeId="5" PostId="10509" RevisionGUID="3c80cc5c-3c53-45fa-af87-3b5a00641b09" CreationDate="2020-12-22T23:57:05.183" UserId="15427" Comment="Added code" Text="I've been following the OpenGL tutorials from ThinMatrix and I've been able to load and render his stall.obj model along with his stall.png texture just fine. But when I try with my own  models and textures from Blender, the texture appears &quot;distorted&quot; and I can't seem to find the problem. I'm guessing the problem is with my texture, but I can't find anything that would cause this problem. What could be the cause of this problem?&#xD;&#xA;&#xD;&#xA;[![Blender][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![OpenGL][2]][2]&#xD;&#xA;&#xD;&#xA;Here's how I load the .obj file:&#xD;&#xA;&#xD;&#xA;    void OBJLoader::load_file(const std::string&amp; filename, std::vector&lt;float&gt;&amp; vertices, std::vector&lt;float&gt;&amp; uvs, std::vector&lt;float&gt;&amp; normals, std::vector&lt;int&gt;&amp; indices)&#xD;&#xA;    {&#xD;&#xA;    std::vector&lt;float&gt; temp_uvs;&#xD;&#xA;    std::vector&lt;float&gt; temp_normals;&#xD;&#xA;&#xD;&#xA;    std::ifstream myfile(filename);&#xD;&#xA;    std::string line;&#xD;&#xA;    if(myfile.is_open())&#xD;&#xA;    {&#xD;&#xA;        while(std::getline(myfile, line))&#xD;&#xA;        {&#xD;&#xA;            if(std::string(&quot;#os&quot;).find(line.front()) != std::string::npos) // Ignore lines which starts with #, o, s&#xD;&#xA;                continue;&#xD;&#xA;&#xD;&#xA;            std::vector&lt;std::string&gt; line_split = split(line, ' ');&#xD;&#xA;            std::string data_type = line_split[0];&#xD;&#xA;            line_split.erase(line_split.begin()); // Keep only numerical data&#xD;&#xA;&#xD;&#xA;            if(data_type == &quot;v&quot;)&#xD;&#xA;            {&#xD;&#xA;                store_float_in_vector(vertices, line_split);&#xD;&#xA;            }&#xD;&#xA;            else if(data_type == &quot;vt&quot;)&#xD;&#xA;            {&#xD;&#xA;                store_float_in_vector(temp_uvs, line_split);&#xD;&#xA;            }&#xD;&#xA;            else if(data_type == &quot;vn&quot;)&#xD;&#xA;            {&#xD;&#xA;                store_float_in_vector(temp_normals, line_split);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if(data_type == &quot;f&quot;)&#xD;&#xA;            {&#xD;&#xA;                for(std::string&amp; vertex: line_split)&#xD;&#xA;                {&#xD;&#xA;                    std::vector&lt;std::string&gt; data_split = split(vertex, '/');&#xD;&#xA;                    int v = std::stoi(data_split[0]);&#xD;&#xA;                    int vt = std::stoi(data_split[1]);&#xD;&#xA;                    int vn = std::stoi(data_split[2]);&#xD;&#xA;&#xD;&#xA;                    if(uvs.size() &lt; (unsigned)(v-1)*2+2)&#xD;&#xA;                        uvs.resize((v-1)*2+2);&#xD;&#xA;                    if(normals.size() &lt; (unsigned)(v-1)*3+3)&#xD;&#xA;                        normals.resize((v-1)*3+3);&#xD;&#xA;&#xD;&#xA;                    indices.push_back(v-1); // Indices in .obj files start at 1&#xD;&#xA;&#xD;&#xA;                    uvs[(v-1)*2] =  temp_uvs[(vt-1)*2];&#xD;&#xA;                    uvs[(v-1)*2+1] = 1.0f - temp_uvs[(vt-1)*2+1]; // Blender ¯\_(ツ)_/¯&#xD;&#xA;&#xD;&#xA;                    normals[(v-1)*3] = temp_normals[(vn-1)*3];&#xD;&#xA;                    normals[(v-1)*3+1] = temp_normals[(vn-1)*3+1];&#xD;&#xA;                    normals[(v-1)*3+2] = temp_normals[(vn-1)*3+2];&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        myfile.close();&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;        std::cout &lt;&lt; &quot;Can't open: &quot; &lt;&lt; filename &lt;&lt; std::endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the obj file:&#xD;&#xA;&#xD;&#xA;    # Blender v2.82 (sub 7) OBJ File: ''&#xD;&#xA;    # www.blender.org&#xD;&#xA;    o Cube&#xD;&#xA;    v 1.000000 1.000000 -1.000000&#xD;&#xA;    v 1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 1.000000 1.000000&#xD;&#xA;    v 1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 1.000000 -1.000000&#xD;&#xA;    v -1.000000 -1.000000 -1.000000&#xD;&#xA;    v -1.000000 1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 1.000000&#xD;&#xA;    vt 0.875000 0.500000&#xD;&#xA;    vt 0.625000 0.750000&#xD;&#xA;    vt 0.625000 0.500000&#xD;&#xA;    vt 0.375000 1.000000&#xD;&#xA;    vt 0.375000 0.750000&#xD;&#xA;    vt 0.625000 0.000000&#xD;&#xA;    vt 0.375000 0.250000&#xD;&#xA;    vt 0.375000 0.000000&#xD;&#xA;    vt 0.375000 0.500000&#xD;&#xA;    vt 0.125000 0.750000&#xD;&#xA;    vt 0.125000 0.500000&#xD;&#xA;    vt 0.625000 0.250000&#xD;&#xA;    vt 0.875000 0.750000&#xD;&#xA;    vt 0.625000 1.000000&#xD;&#xA;    vn 0.0000 1.0000 0.0000&#xD;&#xA;    vn 0.0000 0.0000 1.0000&#xD;&#xA;    vn -1.0000 0.0000 0.0000&#xD;&#xA;    vn 0.0000 -1.0000 0.0000&#xD;&#xA;    vn 1.0000 0.0000 0.0000&#xD;&#xA;    vn 0.0000 0.0000 -1.0000&#xD;&#xA;    s off&#xD;&#xA;    f 5/1/1 3/2/1 1/3/1&#xD;&#xA;    f 3/2/2 8/4/2 4/5/2&#xD;&#xA;    f 7/6/3 6/7/3 8/8/3&#xD;&#xA;    f 2/9/4 8/10/4 6/11/4&#xD;&#xA;    f 1/3/5 4/5/5 2/9/5&#xD;&#xA;    f 5/12/6 2/9/6 6/7/6&#xD;&#xA;    f 5/1/1 7/13/1 3/2/1&#xD;&#xA;    f 3/2/2 7/14/2 8/4/2&#xD;&#xA;    f 7/6/3 5/12/3 6/7/3&#xD;&#xA;    f 2/9/4 4/5/4 8/10/4&#xD;&#xA;    f 1/3/5 3/2/5 4/5/5&#xD;&#xA;    f 5/12/6 1/3/6 2/9/6&#xD;&#xA;&#xD;&#xA;And here's the png file I used for the texture:&#xD;&#xA;[![texture][3]][3]&#xD;&#xA;&#xD;&#xA;And here's how I load the texture with SDL:&#xD;&#xA;&#xD;&#xA;    void Texture::load(const std::string&amp; filename)&#xD;&#xA;    {&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture_id);&#xD;&#xA;&#xD;&#xA;    GLenum gl_format;&#xD;&#xA;    SDL_Surface* surface_texture = IMG_Load(filename.c_str());&#xD;&#xA;    if(surface_texture == nullptr)&#xD;&#xA;        std::cout &lt;&lt; &quot;IMG_Load error: &quot;  &lt;&lt; IMG_GetError() &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    if(surface_texture-&gt;format-&gt;BytesPerPixel == 4)&#xD;&#xA;    {&#xD;&#xA;        if(surface_texture-&gt;format-&gt;Rmask == 0x000000FF)&#xD;&#xA;            gl_format = GL_RGBA;&#xD;&#xA;        else&#xD;&#xA;            gl_format = GL_BGRA;&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        if(surface_texture-&gt;format-&gt;Rmask == 0x000000FF)&#xD;&#xA;            gl_format = GL_RGB;&#xD;&#xA;        else&#xD;&#xA;            gl_format = GL_BGR;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, gl_format, surface_texture-&gt;w, surface_texture-&gt;h, 0, gl_format, GL_UNSIGNED_BYTE, surface_texture-&gt;pixels);&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;    SDL_FreeSurface(surface_texture); // Free SDL_Surface memory&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wuDZL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4MD8Z.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yoCbp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30576" PostHistoryTypeId="5" PostId="10509" RevisionGUID="7bc7239f-d1e3-48c2-8fb6-492ff7611e5d" CreationDate="2020-12-23T00:06:10.460" UserId="15427" Comment="Added more code" Text="I've been following the OpenGL tutorials from ThinMatrix and I've been able to load and render his stall.obj model along with his stall.png texture just fine. But when I try with my own  models and textures from Blender, the texture appears &quot;distorted&quot; and I can't seem to find the problem. I'm guessing the problem is with my texture, but I can't find anything that would cause this problem. What could be the cause of this problem?&#xD;&#xA;&#xD;&#xA;[![Blender][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![OpenGL][2]][2]&#xD;&#xA;&#xD;&#xA;Here's how I load the .obj file:&#xD;&#xA;&#xD;&#xA;    void OBJLoader::load_file(const std::string&amp; filename, std::vector&lt;float&gt;&amp; vertices, std::vector&lt;float&gt;&amp; uvs, std::vector&lt;float&gt;&amp; normals, std::vector&lt;int&gt;&amp; indices)&#xD;&#xA;    {&#xD;&#xA;    std::vector&lt;float&gt; temp_uvs;&#xD;&#xA;    std::vector&lt;float&gt; temp_normals;&#xD;&#xA;&#xD;&#xA;    std::ifstream myfile(filename);&#xD;&#xA;    std::string line;&#xD;&#xA;    if(myfile.is_open())&#xD;&#xA;    {&#xD;&#xA;        while(std::getline(myfile, line))&#xD;&#xA;        {&#xD;&#xA;            if(std::string(&quot;#os&quot;).find(line.front()) != std::string::npos) // Ignore lines which starts with #, o, s&#xD;&#xA;                continue;&#xD;&#xA;&#xD;&#xA;            std::vector&lt;std::string&gt; line_split = split(line, ' ');&#xD;&#xA;            std::string data_type = line_split[0];&#xD;&#xA;            line_split.erase(line_split.begin()); // Keep only numerical data&#xD;&#xA;&#xD;&#xA;            if(data_type == &quot;v&quot;)&#xD;&#xA;            {&#xD;&#xA;                store_float_in_vector(vertices, line_split);&#xD;&#xA;            }&#xD;&#xA;            else if(data_type == &quot;vt&quot;)&#xD;&#xA;            {&#xD;&#xA;                store_float_in_vector(temp_uvs, line_split);&#xD;&#xA;            }&#xD;&#xA;            else if(data_type == &quot;vn&quot;)&#xD;&#xA;            {&#xD;&#xA;                store_float_in_vector(temp_normals, line_split);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if(data_type == &quot;f&quot;)&#xD;&#xA;            {&#xD;&#xA;                for(std::string&amp; vertex: line_split)&#xD;&#xA;                {&#xD;&#xA;                    std::vector&lt;std::string&gt; data_split = split(vertex, '/');&#xD;&#xA;                    int v = std::stoi(data_split[0]);&#xD;&#xA;                    int vt = std::stoi(data_split[1]);&#xD;&#xA;                    int vn = std::stoi(data_split[2]);&#xD;&#xA;&#xD;&#xA;                    if(uvs.size() &lt; (unsigned)(v-1)*2+2)&#xD;&#xA;                        uvs.resize((v-1)*2+2);&#xD;&#xA;                    if(normals.size() &lt; (unsigned)(v-1)*3+3)&#xD;&#xA;                        normals.resize((v-1)*3+3);&#xD;&#xA;&#xD;&#xA;                    indices.push_back(v-1); // Indices in .obj files start at 1&#xD;&#xA;&#xD;&#xA;                    uvs[(v-1)*2] =  temp_uvs[(vt-1)*2];&#xD;&#xA;                    uvs[(v-1)*2+1] = 1.0f - temp_uvs[(vt-1)*2+1]; // Blender ¯\_(ツ)_/¯&#xD;&#xA;&#xD;&#xA;                    normals[(v-1)*3] = temp_normals[(vn-1)*3];&#xD;&#xA;                    normals[(v-1)*3+1] = temp_normals[(vn-1)*3+1];&#xD;&#xA;                    normals[(v-1)*3+2] = temp_normals[(vn-1)*3+2];&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        myfile.close();&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;        std::cout &lt;&lt; &quot;Can't open: &quot; &lt;&lt; filename &lt;&lt; std::endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the obj file:&#xD;&#xA;&#xD;&#xA;    # Blender v2.82 (sub 7) OBJ File: ''&#xD;&#xA;    # www.blender.org&#xD;&#xA;    o Cube&#xD;&#xA;    v 1.000000 1.000000 -1.000000&#xD;&#xA;    v 1.000000 -1.000000 -1.000000&#xD;&#xA;    v 1.000000 1.000000 1.000000&#xD;&#xA;    v 1.000000 -1.000000 1.000000&#xD;&#xA;    v -1.000000 1.000000 -1.000000&#xD;&#xA;    v -1.000000 -1.000000 -1.000000&#xD;&#xA;    v -1.000000 1.000000 1.000000&#xD;&#xA;    v -1.000000 -1.000000 1.000000&#xD;&#xA;    vt 0.875000 0.500000&#xD;&#xA;    vt 0.625000 0.750000&#xD;&#xA;    vt 0.625000 0.500000&#xD;&#xA;    vt 0.375000 1.000000&#xD;&#xA;    vt 0.375000 0.750000&#xD;&#xA;    vt 0.625000 0.000000&#xD;&#xA;    vt 0.375000 0.250000&#xD;&#xA;    vt 0.375000 0.000000&#xD;&#xA;    vt 0.375000 0.500000&#xD;&#xA;    vt 0.125000 0.750000&#xD;&#xA;    vt 0.125000 0.500000&#xD;&#xA;    vt 0.625000 0.250000&#xD;&#xA;    vt 0.875000 0.750000&#xD;&#xA;    vt 0.625000 1.000000&#xD;&#xA;    vn 0.0000 1.0000 0.0000&#xD;&#xA;    vn 0.0000 0.0000 1.0000&#xD;&#xA;    vn -1.0000 0.0000 0.0000&#xD;&#xA;    vn 0.0000 -1.0000 0.0000&#xD;&#xA;    vn 1.0000 0.0000 0.0000&#xD;&#xA;    vn 0.0000 0.0000 -1.0000&#xD;&#xA;    s off&#xD;&#xA;    f 5/1/1 3/2/1 1/3/1&#xD;&#xA;    f 3/2/2 8/4/2 4/5/2&#xD;&#xA;    f 7/6/3 6/7/3 8/8/3&#xD;&#xA;    f 2/9/4 8/10/4 6/11/4&#xD;&#xA;    f 1/3/5 4/5/5 2/9/5&#xD;&#xA;    f 5/12/6 2/9/6 6/7/6&#xD;&#xA;    f 5/1/1 7/13/1 3/2/1&#xD;&#xA;    f 3/2/2 7/14/2 8/4/2&#xD;&#xA;    f 7/6/3 5/12/3 6/7/3&#xD;&#xA;    f 2/9/4 4/5/4 8/10/4&#xD;&#xA;    f 1/3/5 3/2/5 4/5/5&#xD;&#xA;    f 5/12/6 1/3/6 2/9/6&#xD;&#xA;&#xD;&#xA;And here's the png file I used for the texture:&#xD;&#xA;[![texture][3]][3]&#xD;&#xA;&#xD;&#xA;And here's how I load the texture with SDL:&#xD;&#xA;&#xD;&#xA;    void Texture::load(const std::string&amp; filename)&#xD;&#xA;    {&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, texture_id);&#xD;&#xA;&#xD;&#xA;    GLenum gl_format;&#xD;&#xA;    SDL_Surface* surface_texture = IMG_Load(filename.c_str());&#xD;&#xA;    if(surface_texture == nullptr)&#xD;&#xA;        std::cout &lt;&lt; &quot;IMG_Load error: &quot;  &lt;&lt; IMG_GetError() &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    if(surface_texture-&gt;format-&gt;BytesPerPixel == 4)&#xD;&#xA;    {&#xD;&#xA;        if(surface_texture-&gt;format-&gt;Rmask == 0x000000FF)&#xD;&#xA;            gl_format = GL_RGBA;&#xD;&#xA;        else&#xD;&#xA;            gl_format = GL_BGRA;&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        if(surface_texture-&gt;format-&gt;Rmask == 0x000000FF)&#xD;&#xA;            gl_format = GL_RGB;&#xD;&#xA;        else&#xD;&#xA;            gl_format = GL_BGR;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, gl_format, surface_texture-&gt;w, surface_texture-&gt;h, 0, gl_format, GL_UNSIGNED_BYTE, surface_texture-&gt;pixels);&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);&#xD;&#xA;&#xD;&#xA;    SDL_FreeSurface(surface_texture); // Free SDL_Surface memory&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here's the code for rendering the model:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void Model::create_EBO(int indices[], size_t s_indices)&#xD;&#xA;{&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, s_indices, indices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Unbind buffer&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Model::create_VBO(float data[], size_t s_data, unsigned int index, unsigned int coord_format)&#xD;&#xA;{&#xD;&#xA;    vbos.push_back(0); // Declare new vbo&#xD;&#xA;    GLuint&amp; vbo = vbos.back();&#xD;&#xA;&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, s_data, data, GL_STATIC_DRAW);&#xD;&#xA;    glVertexAttribPointer(index, coord_format, GL_FLOAT, GL_FALSE, 0, (void*)0);&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind buffer&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Model::load(float vertices[], size_t s_vertices, float uvs[], size_t s_uvs, float normals[], size_t s_normals, int indices[], size_t s_indices)&#xD;&#xA;{&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    create_EBO(indices, s_indices);&#xD;&#xA;&#xD;&#xA;    create_VBO(vertices, s_vertices, 0, 3);&#xD;&#xA;    create_VBO(uvs, s_uvs, 1, 2);&#xD;&#xA;    create_VBO(normals, s_normals, 2, 3);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(0); // Unbind VAO and associated VBOs&#xD;&#xA;&#xD;&#xA;    vertex_count = s_indices/sizeof(indices[0]);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Model::render()&#xD;&#xA;{&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;    glEnableVertexAttribArray(2);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, 0);&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Unbind EBO&#xD;&#xA;    glDisableVertexAttribArray(0);&#xD;&#xA;    glDisableVertexAttribArray(1);&#xD;&#xA;    glDisableVertexAttribArray(2);&#xD;&#xA;    glBindVertexArray(0); // Unbind VAO&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wuDZL.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4MD8Z.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yoCbp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30577" PostHistoryTypeId="50" PostId="5697" RevisionGUID="5c1922d8-dce0-4bac-8bcb-862487091a29" CreationDate="2020-12-23T05:03:15.313" UserId="-1" />
  <row Id="30578" PostHistoryTypeId="2" PostId="10510" RevisionGUID="f161f3b8-472b-4b89-bbfe-6f709b2e2e1f" CreationDate="2020-12-23T13:29:02.830" UserId="15429" Text="You could add the variable as code when you upload the shader code.&#xD;&#xA;&#xD;&#xA;    sprintf (string, &quot;const int size = %u;\n&quot;, pointLights.size());&#xD;&#xA;&#xD;&#xA;Then add the string to the code at the top before you do:&#xD;&#xA;&#xD;&#xA;    glShaderSource(shader, 1, (const GLchar **)&amp;source, NULL);&#xD;&#xA;    ..&#xD;&#xA;&#xD;&#xA;That way you can vary the size and add it to the shader in the fly.&#xD;&#xA;Bit of a hack, but I think it gets you what you want.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30579" PostHistoryTypeId="5" PostId="10510" RevisionGUID="e6e9bca1-3d87-422b-ba41-f9c7a7cbc411" CreationDate="2020-12-23T13:51:16.293" UserId="15429" Comment="better example" Text="You could add the variable as code when you upload the shader code.&#xD;&#xA;&#xD;&#xA;    char header[64];&#xD;&#xA;    sprintf (header, &quot;const int size = %u;\n&quot;, pointLights.size());&#xD;&#xA;&#xD;&#xA;Then add the header (assuming your code is in `char code[]`):&#xD;&#xA;&#xD;&#xA;    GLchar  *source[2] = {(GLchar  *)header, (GLchar  *)code};&#xD;&#xA;    glShaderSource(shader, 2, (const GLchar **)source, NULL);&#xD;&#xA;    ..&#xD;&#xA;&#xD;&#xA;That way you can vary the size and add it to the shader in the fly.&#xD;&#xA;Bit of a hack, but it's the way I did it.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30580" PostHistoryTypeId="5" PostId="10510" RevisionGUID="ac457209-08cd-4c3a-905d-62a25223402b" CreationDate="2020-12-23T13:59:22.590" UserId="15429" Comment="edited body" Text="You could add the variable as code when you upload the shader code.&#xD;&#xA;&#xD;&#xA;    char header[64];&#xD;&#xA;    sprintf (header, &quot;const int size = %u;\n&quot;, pointLights.size());&#xD;&#xA;&#xD;&#xA;Then add the header (assuming your code is in `char code[]`):&#xD;&#xA;&#xD;&#xA;    GLchar  *source[2] = {(GLchar  *)header, (GLchar  *)code};&#xD;&#xA;    glShaderSource(shader, 2, (const GLchar **)source, NULL);&#xD;&#xA;    ..&#xD;&#xA;&#xD;&#xA;That way you can vary the size and add it to the shader on the fly.&#xD;&#xA;Bit of a hack, but it's the way I did it.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30584" PostHistoryTypeId="2" PostId="10512" RevisionGUID="06d56670-8d7f-4d60-827d-44f90ef95b73" CreationDate="2020-12-24T00:26:23.013" UserId="10615" Text="When a source of colored light is very bright, it's center appears white. What is the term I need to look for so I can implement this in my shader? I have added an image which is an example of what I mean. Obviously there is also some bloom going on but that alone doesn't cut it. The search results for &quot;opengl glow&quot; don't seem vey promising either, that just gives me more bloom, not white centers.&#xD;&#xA;&#xD;&#xA;I have thought about blending a white emission with the desired color. However, when I try to recreate a red light saber it turns out pink (but the center is at least white). &#xD;&#xA;&#xD;&#xA;So what I'm really after is a tinted light, glowed, with high (color) contrast.&#xD;&#xA;&#xD;&#xA;[![example of effect][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V6GAK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30585" PostHistoryTypeId="1" PostId="10512" RevisionGUID="06d56670-8d7f-4d60-827d-44f90ef95b73" CreationDate="2020-12-24T00:26:23.013" UserId="10615" Text="&quot;whiteness&quot; in center of bright colored lights - what is it called?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30586" PostHistoryTypeId="3" PostId="10512" RevisionGUID="06d56670-8d7f-4d60-827d-44f90ef95b73" CreationDate="2020-12-24T00:26:23.013" UserId="10615" Text="|lighting|color|brightness|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30587" PostHistoryTypeId="5" PostId="10512" RevisionGUID="a655a56f-2c96-4fa6-9392-17f26e5fe744" CreationDate="2020-12-24T00:34:40.973" UserId="10615" Comment="added 111 characters in body" Text="When a source of colored light is very bright, it's center appears white. What is the term I need to look for so I can implement this in my shader? I have added an image which is an example of what I mean. Obviously there is also some bloom going on but that alone doesn't cut it. The search results for &quot;opengl glow&quot; don't seem vey promising either, that just gives me more bloom, not white centers.&#xD;&#xA;&#xD;&#xA;I have thought about [blending a white emission with the desired color like in this question/answer.][1] However, as you can see that turns the emission pink, not red.&#xD;&#xA;&#xD;&#xA;So what I'm really after is a tinted light, glowed, with high (color) contrast.&#xD;&#xA;&#xD;&#xA;[![example of effect][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/4361023/opengl-es-1-1-how-to-change-texture-color-without-losing-luminance&#xD;&#xA;  [2]: https://i.stack.imgur.com/V6GAK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30588" PostHistoryTypeId="2" PostId="10513" RevisionGUID="1c8c6200-fb10-4dea-8ed4-8be23a4feb8a" CreationDate="2020-12-24T01:33:22.200" UserId="48" Text="In general this is caused by HDR tone mapping. Tonemap curves typically decrease saturation as the input light gets brighter, so that very bright lights are rendered closer to white on the display. If bloom is rendered in HDR (prior to tonemapping) then the bloom around the light can still be highly saturated since it is of a lower intensity than the light itself, and so doesn't get desaturated by tonemapping as much.&#xD;&#xA;&#xD;&#xA;You can see some good examples of this on the [UE4 Color Grading and Filmic Tonemapper](https://docs.unrealengine.com/en-US/RenderingAndGraphics/PostProcessEffects/ColorGrading/index.html) docs page. Unreal uses the [ACES tone mapping curve](https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/), which is a pretty good default tone curve that you can easily hook up in your own shader code as well.&#xD;&#xA;&#xD;&#xA;That said, lightsabers in Star Wars games are probably a special case visual effect that's tuned specifically to reproduce how they look in the movies. :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30589" PostHistoryTypeId="50" PostId="10425" RevisionGUID="bb6578ae-b150-438f-9e0e-787e8086015b" CreationDate="2020-12-24T05:00:05.247" UserId="-1" />
  <row Id="30590" PostHistoryTypeId="2" PostId="10514" RevisionGUID="f9cbc9ec-6787-4e69-99e8-421fe5f7ac28" CreationDate="2020-12-24T08:27:51.093" UserId="15434" Text="This is my first post on this website so i have put in a lot of research to get my point across to everyone as clearly as possible.&#xD;&#xA;&#xD;&#xA;Based on a question i [posted](https://stackoverflow.com/questions/65410883/bezier-curve-forcing-a-curve-of-4-points-to-pass-through-control-points-in-3d) on stack overflow i have successfully derived the control points for an bezier curve.Recently i have learned from an [article](http://graphics.stanford.edu/courses/cs148-09/lectures/splines.pdf) that curves can be represented in matrix form as well so as an practise i decided to derive the bezier control points again but from it's matrix form.&#xD;&#xA;&#xD;&#xA;If we refer to slide 4 for the basis matrix  and slide 14 from the article for the bezier functions we will find all the parameters needed to construct an bezier curve in the matrix form.&#xD;&#xA;&#xD;&#xA;Equation 1&#xD;&#xA;&#xD;&#xA;    [a]=  [2  -2   1   1][f(0)]&#xD;&#xA;    [b]=  [-3  3  -2  -1][f(1)]&#xD;&#xA;    [c]=  [0   0   1   0][f'(0)]&#xD;&#xA;    [d]=  [1   0   0   0][f'(1)]&#xD;&#xA;    &#xD;&#xA;    where for an bezier curve&#xD;&#xA;    f(0)=P0&#xD;&#xA;    f(1)=P3&#xD;&#xA;    f'(0)=T0=3(P1-P0)&#xD;&#xA;    f'(1)=T1=3(P3-P2)&#xD;&#xA;&#xD;&#xA;    and finally a point on the curve is&#xD;&#xA;    p=at^3+bt^2+ct+d where t is normalized time ranging from 0--&gt;1&#xD;&#xA;&#xD;&#xA;Now from my related post i want to derive the control points so i have to work backwards. I want to find at times t1=1/3 and t2=2/3 what should be the new control points such that they pass through the current control points P0 and P1.&#xD;&#xA;&#xD;&#xA;This is what i have worked out&#xD;&#xA;&#xD;&#xA;    //We want the bezier curve to pass through p1 and p2. Let us consider only the x axis and equate both sides&#xD;&#xA;    &#xD;&#xA;    p1.x=a*(1/3^3)+b(1/3^2)+c*(1/3)+d    (2)&#xD;&#xA;    p2.x=a*(2/3^3)+b(2/3^2)+c*(2/3)+d    (3)&#xD;&#xA;    &#xD;&#xA;    Now writing equation 1 only for x axis we have&#xD;&#xA;    [a]=  [2  -2   1   1][P0.x]&#xD;&#xA;    [b]=  [-3  3  -2  -1][P3.X]&#xD;&#xA;    [c]=  [0   0   1   0][3(P1.x-P0.x)]&#xD;&#xA;    [d]=  [1   0   0   0][3(P3.x-P2.x)]&#xD;&#xA;    &#xD;&#xA;    on solving we have our abcd values which are&#xD;&#xA;    &#xD;&#xA;    a=2P0.x-2P3.x+3(P1.x-P0.x)+3(P3.x-P2.x)&#xD;&#xA;    b=-3P0.X+3P3.X-6(P1.x-P0.x)-3(P3.x-P2.x)&#xD;&#xA;    c=3(P1.x-P0.x)&#xD;&#xA;    d=3(P3.x-P2.x)&#xD;&#xA;    &#xD;&#xA;    Upon further simplifying and keeping P1.x and P2.x as the unknowns as those are the new control points we want to find out we have&#xD;&#xA;    &#xD;&#xA;    a= -P0.x+3P1.x-3P2.x+P3.x&#xD;&#xA;    b= 3P0.x-6P1.x+3P2.x&#xD;&#xA;    c= 3P1.x-3P0.x&#xD;&#xA;    d= 3P3.x-3P2.x&#xD;&#xA;    &#xD;&#xA;    Upon substituting the values in equation 2 we have&#xD;&#xA;    p1.x=(-P0.x+3P1.x-3P2.x+P3.x)(1/3^3) + (3P0.x-6P1.x+3P2.x)(1/3^2) + (3P1.x-3P0.x)(1/3) + 3P3.x-3P2.x&#xD;&#xA;    &#xD;&#xA;    rearranging all the constants[P0 and P3] to the left hand side we have&#xD;&#xA;    p1.x + ((P0.x-P3.x)*(1/3^3)) + (-3P0.x*(1/3^2)) + (3P0.x*1/3) -3P3.x = 3(P1.x-P2.x)(1/3^3)-3(2P1.x-P2.x)(1/3^2) + 3P1.x*1/3 - 3P2.x&#xD;&#xA;    &#xD;&#xA;    We will call the constant on left hand side as c1 for now. Upon furthur rearranging P1 and P2 terms&#xD;&#xA;    c1=(3*(1/3^3) - 6*(1/3^2) + 3(1/3))P1.x + (-3*(1/3^3) +3*(1/3^2) -3)P2.x&#xD;&#xA;    &#xD;&#xA;    we will call 1/3 as t1 as we might change this to make the curve look diffrent then we have&#xD;&#xA;    &#xD;&#xA;    c1=(3t1^3-6t1^2+3t1)P1.x + (-3t1^3+3t1^2-3)P2.x&#xD;&#xA;    &#xD;&#xA;    Or&#xD;&#xA;    c1=a1P1.x+b1P2.x   (4)&#xD;&#xA;    &#xD;&#xA;    similarly doing the exact same stuff for equation 3 but using p2.x and t2=2/3 we have&#xD;&#xA;    c2=a2P1.x+b2P2.x   (5)&#xD;&#xA;    &#xD;&#xA;     upon writing in matrix form we have&#xD;&#xA;    &#xD;&#xA;     [c1]=[a1  b1][P1.x]&#xD;&#xA;     [c2]=[a2  b2][P2.x]&#xD;&#xA;    &#xD;&#xA;      Or&#xD;&#xA;      C=BP BP=C &#xD;&#xA;    &#xD;&#xA;      and&#xD;&#xA;    &#xD;&#xA;      P=inverse(B)C&#xD;&#xA;&#xD;&#xA;Here is the java pseudo code i have implemented for this. I have used an float array as i want to use bezier curve for any dimension.&#xD;&#xA;&#xD;&#xA;     public static void bezierAdjust(float[] p0,float[] p1,float[] p2,float[] p3)&#xD;&#xA;     {&#xD;&#xA;      float&#xD;&#xA;      t1=1.0f/3.0f,&#xD;&#xA;      t2=2.0f/3.0f; &#xD;&#xA;      &#xD;&#xA;      Matrix2f solver=new Matrix2f();&#xD;&#xA;     &#xD;&#xA;      for(int i=0;i&lt;p0.length;i++) //i=0 x axis,i=1 y axis,i=2 z axis&#xD;&#xA;      {&#xD;&#xA;       //solve for t1 and p1&#xD;&#xA;       double&#xD;&#xA;       a1=((3*Math.pow(t1,3))-(6*Math.pow(t1,2))+(3*t1)),&#xD;&#xA;       b1=(-(3*Math.pow(t1,3))+(3*Math.pow(t1,2))-3), &#xD;&#xA;       c1=p1[i]+((p0[i]-p3[i])*Math.pow(t1,3))+((-3*p0[i])*Math.pow(t1,2))+(3*p0[i]*t1)-(3*p3[i]);&#xD;&#xA;       &#xD;&#xA;       //solve for t2 and p2&#xD;&#xA;       double&#xD;&#xA;       a2=((3*Math.pow(t2,3))-(6*Math.pow(t2,2))+(3*t2)),&#xD;&#xA;       b2=(-(3*Math.pow(t2,3))+(3*Math.pow(t2,2))-3), &#xD;&#xA;       c2=p2[i]+((p0[i]-p3[i])*Math.pow(t2,3))+((-3*p0[i])*Math.pow(t2,2))+(3*p0[i]*t2)-(3*p3[i]);&#xD;&#xA;      &#xD;&#xA;       solver.load(FloatBuffer.wrap(new float[]{(float)a1,(float)a2,(float)b1,(float)b2})); //load column wise&#xD;&#xA;       solver.invert();&#xD;&#xA;       Vector2f abSolved=Matrix2f.transform(solver,new Vector2f((float)c1,(float)c2),new Vector2f());&#xD;&#xA;       &#xD;&#xA;       p1[i]=abSolved.x;&#xD;&#xA;       p2[i]=abSolved.y;&#xD;&#xA;      }&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;Unfortunatly all that hard work turned my bezier curve from looking like this without any control point modification&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To this.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LxQ8D.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xmDUk.png&#xD;&#xA;&#xD;&#xA;I have posted the same question on stackoverflow but i haven't got any answers yet. Can someone guide me as to where i went wrong if it's my code or calculation or both?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30591" PostHistoryTypeId="1" PostId="10514" RevisionGUID="f9cbc9ec-6787-4e69-99e8-421fe5f7ac28" CreationDate="2020-12-24T08:27:51.093" UserId="15434" Text="Bezier curve : Problem deriving control points from matrix form" ContentLicense="CC BY-SA 4.0" />
  <row Id="30592" PostHistoryTypeId="3" PostId="10514" RevisionGUID="f9cbc9ec-6787-4e69-99e8-421fe5f7ac28" CreationDate="2020-12-24T08:27:51.093" UserId="15434" Text="|matrix|bezier-curve|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30593" PostHistoryTypeId="50" PostId="8721" RevisionGUID="9a295944-70d5-487e-9f37-388bf81dbd72" CreationDate="2020-12-24T09:03:30.253" UserId="-1" />
  <row Id="30597" PostHistoryTypeId="2" PostId="10516" RevisionGUID="5d94e9b6-6444-498b-9ad5-e19adea9885a" CreationDate="2020-12-24T17:49:52.370" UserId="271" Text="I just saw this post by NVIDIA:&#xD;&#xA;[RTX Global Illumination][1]&#xD;&#xA;&#xD;&#xA;The images shown seem to be rendered in realtime which got me thinking about when games will achieve full photorealism and become indistinguishable from reality (or CGI). Games have only begun to use Ray tracing, and even a fully photorealistic engine may not be purely Ray tracing based but it looks like the way forward. A cursory search could not find any related 'moore's law' of photorealism which i find a bit odd since the simulation part has already been worked out (we've had ray tracing since the beginning of computer graphics) and the programmers seem to be waiting for improvements in hardware.&#xD;&#xA;&#xD;&#xA;Ignoring how other aspects of game development like tooling and artistic input, clumsy physics, uncanny valley etc. will cope with high visual fidelity, when, if ever, will we be able to move around and interact in a world that looks just like the real world.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://twitter.com/CasualEffects/status/1341818541532655621" ContentLicense="CC BY-SA 4.0" />
  <row Id="30598" PostHistoryTypeId="1" PostId="10516" RevisionGUID="5d94e9b6-6444-498b-9ad5-e19adea9885a" CreationDate="2020-12-24T17:49:52.370" UserId="271" Text="How many years till photorealistic games?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30599" PostHistoryTypeId="3" PostId="10516" RevisionGUID="5d94e9b6-6444-498b-9ad5-e19adea9885a" CreationDate="2020-12-24T17:49:52.370" UserId="271" Text="|raytracing|photo-realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30600" PostHistoryTypeId="10" PostId="10516" RevisionGUID="212cade9-7d82-4af6-9d43-1b89569cfe07" CreationDate="2020-12-24T22:13:02.223" UserId="13095" Comment="105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="30601" PostHistoryTypeId="50" PostId="8209" RevisionGUID="421adaf2-5f74-4446-a50a-5c164433f0c4" CreationDate="2020-12-25T01:00:10.037" UserId="-1" />
  <row Id="30605" PostHistoryTypeId="2" PostId="10517" RevisionGUID="f5cd488a-dc89-4adf-b4f8-e441364f308c" CreationDate="2020-12-26T13:47:20.563" UserId="8263" Text="I am working on a pure java implementation of OpenGL 1 called [jGL][1].&#xD;&#xA;&#xD;&#xA;I am [missing glPolygonOffsetFill][2] and am looking for an example implementation in java, c/c++ example of this GL function in order to integrate it in jGL.&#xD;&#xA;&#xD;&#xA;Would anyone suggest a direction?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/jzy3d/jGL&#xD;&#xA;  [2]: https://github.com/jzy3d/jGL/issues/3" ContentLicense="CC BY-SA 4.0" />
  <row Id="30606" PostHistoryTypeId="1" PostId="10517" RevisionGUID="f5cd488a-dc89-4adf-b4f8-e441364f308c" CreationDate="2020-12-26T13:47:20.563" UserId="8263" Text="OpenGL Polygon Offset Fill implementation example code" ContentLicense="CC BY-SA 4.0" />
  <row Id="30607" PostHistoryTypeId="3" PostId="10517" RevisionGUID="f5cd488a-dc89-4adf-b4f8-e441364f308c" CreationDate="2020-12-26T13:47:20.563" UserId="8263" Text="|opengl|polygon|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30608" PostHistoryTypeId="50" PostId="10430" RevisionGUID="7e50ab8b-f437-406b-9401-0906f4364197" CreationDate="2020-12-26T15:03:50.350" UserId="-1" />
  <row Id="30609" PostHistoryTypeId="2" PostId="10518" RevisionGUID="6e12abdb-d690-4fcd-ae44-d4ff3d1a151a" CreationDate="2020-12-27T01:17:47.640" UserId="15444" Text="I am working with the cosine function with a very large input, like `cos(a* t)`, where `t` varies between  `1` and `~ 200`; and `a` can be as large as `10^8`-&#xD;&#xA;&#xD;&#xA;I come across, as expected, the artifact error. If I sample `t` with a stepsize of `0.01` with `a` 100, I get a plot like this : &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Notice, that for large value of `a`, the sampling of `t` needs to be fine, otherwise, you will not get regular cosine shape from `-1` to `1`. Sometimes, wave peaks, and other times wave troughs will be missed, due to low granularity, and you will end up with a different shape of the wave than the theoritical value. &#xD;&#xA;&#xD;&#xA;Now, increase `a` to be `100000`, and as expected, the effect is much more pronounced. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My question : Is there a formula / algorithm, to avoid this effect? Is there a formula, that tells you the correct step size for a large value of `a` ?&#xD;&#xA;&#xD;&#xA;I tried to google the following keywords : `large input cosine function computer graphics`, but that did not help.&#xD;&#xA;&#xD;&#xA;Thank you. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/H496n.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YjEcf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30610" PostHistoryTypeId="1" PostId="10518" RevisionGUID="6e12abdb-d690-4fcd-ae44-d4ff3d1a151a" CreationDate="2020-12-27T01:17:47.640" UserId="15444" Text="Algorithm for proper drawing of cosine function" ContentLicense="CC BY-SA 4.0" />
  <row Id="30611" PostHistoryTypeId="3" PostId="10518" RevisionGUID="6e12abdb-d690-4fcd-ae44-d4ff3d1a151a" CreationDate="2020-12-27T01:17:47.640" UserId="15444" Text="|sampling|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30612" PostHistoryTypeId="2" PostId="10519" RevisionGUID="514d39cd-5740-4666-92cd-f4f9fe3c9fb4" CreationDate="2020-12-27T06:54:58.417" UserId="15446" Text="There is in fact a way to avoid this effect and it is outlined by the NYQUIST sampling theorem - which states that the sampling rate should be at least twice as high as the maximum frequency of the function of interest. &lt;br&gt;&#xD;&#xA;In this case where `cos(a * t)` is the function of interest, the frequency is `a/(2*pi)` - therefore your sampling rate should be greater than `2 * a/(2*pi)` (in this case you may even want the sampling rate to be even higher so that the cosine function has a nice curve to it). &lt;br&gt;&#xD;&#xA;To get the step size from this sampling rate just use `t = 1/(sampling rate)` &lt;br&gt;&#xD;&#xA;Hope this helps :) " ContentLicense="CC BY-SA 4.0" />
  <row Id="30616" PostHistoryTypeId="2" PostId="10521" RevisionGUID="bd5691d7-d8e9-434d-a278-bfbbeecc6ee0" CreationDate="2020-12-27T12:09:25.237" UserId="15446" Text="This is an interesting question, as intuitively we would think that the image size of the object will be 50% of the image width. However, upon some playing around with triangles, I found this to not be the case. &lt;br&gt;&lt;br&gt;&#xD;&#xA;For example, take a look at the diagram below. Here we have two overlapping triangles, one with angular diameter of 50 degrees (representing the object's angular diameter), and one with angular diameter 100 degrees (representing the camera's FoV). As we can see, the object has a width of 1 unit as seen from the camera, however the image width is around 3 units - therefore in this case the horizontal image size of the object will be around 33% of the image width.&#xD;&#xA;[![enter image description here][1]][1]&lt;br&gt;&lt;br&gt;&#xD;&#xA;If you were to play around with different values for D and d, you would find that the angular diameter ratios would vary. There would be a way to calculate this ratio directly with some trigonometry, however I do not know of how much use that would be to you. &lt;br&gt;&lt;br&gt;&#xD;&#xA;Hope this helps in some way :)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mCLjh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30617" PostHistoryTypeId="2" PostId="10522" RevisionGUID="93463d2a-c617-45d3-8025-9dc1d8e4380b" CreationDate="2020-12-27T12:19:58.097" UserId="15225" Text="I'm trying to understand a go library for Delaunay triangulation and found out this function to calculate the pseudo angle &#xD;&#xA;&#xD;&#xA;Here is the implementation of the psuedo angle &#xD;&#xA;```&#xD;&#xA;    func pseudoAngle(dx, dy float64) float64 {&#xD;&#xA;    	p := dx / (math.Abs(dx) + math.Abs(dy))&#xD;&#xA;    	if dy &gt; 0 {&#xD;&#xA;    		p = (3 - p) / 4&#xD;&#xA;    	} else {&#xD;&#xA;    		p = (1 + p) / 4&#xD;&#xA;    	}&#xD;&#xA;    	return math.Max(0, math.Min(1-eps, p))&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here is were it have been used : &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;func (t *triangulator) hashKey(point r3.Point) int {&#xD;&#xA;&#xD;&#xA;	d := point.Sub(t.center)&#xD;&#xA;	return int(pseudoAngle(d[0], d[1]) * float64(len(t.hash)))&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Do you have any idea of where this implementation is coming from mathematically ?   &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30618" PostHistoryTypeId="1" PostId="10522" RevisionGUID="93463d2a-c617-45d3-8025-9dc1d8e4380b" CreationDate="2020-12-27T12:19:58.097" UserId="15225" Text="understand a pseudo angle implementation" ContentLicense="CC BY-SA 4.0" />
  <row Id="30619" PostHistoryTypeId="3" PostId="10522" RevisionGUID="93463d2a-c617-45d3-8025-9dc1d8e4380b" CreationDate="2020-12-27T12:19:58.097" UserId="15225" Text="|implementation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30620" PostHistoryTypeId="2" PostId="10523" RevisionGUID="e736b324-fa52-4b45-a28e-85ab31c87724" CreationDate="2020-12-27T18:17:19.957" UserId="48" Text="The &quot;pseudo-angle&quot; this function defines runs from 0 to 1 counterclockwise around the circle, with 0 at the negative x-axis, and each 25% of the range mapping to one quadrant (so 0.25 at the negative y-axis, 0.5 at the positive x-axis, etc).&#xD;&#xA;&#xD;&#xA;First, the expression `dx / (math.Abs(dx) + math.Abs(dy))`, can be seen as normalizing the vector in the 1-norm or [taxicab norm](https://en.wikipedia.org/wiki/Norm_(mathematics)#Taxicab_norm_or_Manhattan_norm) as opposed to the usual Euclidean norm. In other words, it's projecting the vector onto the unit diamond:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/0ZDNf.png&quot; width=&quot;400&quot; height=&quot;400&quot; alt=&quot;unit ball in the 1-norm&quot;/&gt;&#xD;&#xA;&#xD;&#xA;After that, it looks at the sign of y and remaps x accordingly. For the lower half of the diamond (negative y), it maps x linearly from [−1, 1] to [0, 0.5]. For the top half it maps x from [1, –1] to [0.5, 1] (reversing the direction of the mapping this time). So, as you start from the point (−1, 0) and go counterclockwise around the diamond, the pseudo-angle result will increase from 0 to 1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It is probably used because the system wants to sort vectors by their angle (or in this case, incorporate the angle in a hash apparently), but it doesn't need the actual Euclidean angle which would require an expensive atan2 function to calculate. It just needs something monotonically related to the angle but cheap to calculate, and this pseudo-angle fits the bill.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0ZDNf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30621" PostHistoryTypeId="50" PostId="9591" RevisionGUID="22168888-3f36-43ba-8195-6b7134566c9c" CreationDate="2020-12-27T23:06:15.603" UserId="-1" />
  <row Id="30622" PostHistoryTypeId="2" PostId="10524" RevisionGUID="b5db2d89-3cbf-4d5e-9596-b4b9f346e98d" CreationDate="2020-12-28T00:49:26.563" UserId="10450" Text="[![cell renderer][1]][1]&#xD;&#xA;&#xD;&#xA;I am interested how that image on the right of the slider (just albedo) can produce such a realistic looking scene as the scene on the left.&#xD;&#xA;What effects (at a minimum) does this scene seem to be using. ie. what rendering features would be necessary to reproduce this scene?&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;Apologies for the poor quality screenshot, for reference, it is taken from [Joey de Vries 2017 tech reel](https://www.youtube.com/watch?v=2uSWEc-O8wk&amp;t=65s) at about the 1:05 mark.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zI0cS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30623" PostHistoryTypeId="1" PostId="10524" RevisionGUID="b5db2d89-3cbf-4d5e-9596-b4b9f346e98d" CreationDate="2020-12-28T00:49:26.563" UserId="10450" Text="What effects are used to light this scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30624" PostHistoryTypeId="3" PostId="10524" RevisionGUID="b5db2d89-3cbf-4d5e-9596-b4b9f346e98d" CreationDate="2020-12-28T00:49:26.563" UserId="10450" Text="|rendering|lighting|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30625" PostHistoryTypeId="2" PostId="10525" RevisionGUID="347eb313-cffa-49aa-afed-460490d9964a" CreationDate="2020-12-28T02:50:35.287" UserId="15446" Text="The rendering engine that rendered this image is using a technique called deferred rendering, which first writes scene information (as seen from the camera) to seperate buffers (such as position, normal, and albedo buffers) and then calculates lighting for the image based off this information. It is important that we have position and normal buffers on top of the albedo buffer so that lighting can be calculated at each pixel (these buffers are not visible in your example, but they are there under the hood). As an example, take a look at the image below that shows the different buffers of an engine I worked on - it may help to better understand what is going on. &lt;br&gt;&lt;br&gt;&#xD;&#xA;[![Deferred Rendering Buffers][1]][1] &lt;br&gt;&lt;br&gt;&#xD;&#xA;&#xD;&#xA;Once a buffer has been made with all of the lighting calculations, you can then achieve post processing effects by processing the buffer with various algorithms to produce the final image. Some post processing effects that are visible in your image are bloom (which adds &quot;glow&quot; to bright spots), motion blur and an implementation of screen space ambient occlusion (SSAO). &lt;br&gt;&lt;br&gt;&#xD;&#xA;A full list of the rendering features can actually be found at the 1:02 mark of the video, I have attached the image here to make it easy to see. It may be worth googling what each individual post-processing effect does so that you can better understand the effect they have on the overall image.&lt;br&gt;&lt;br&gt;&#xD;&#xA;[![Rendering features][2]][2]&#xD;&#xA;&lt;br&gt;&lt;br&gt;&#xD;&#xA;Hope this was of help :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HkUQk.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ncf3Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30631" PostHistoryTypeId="2" PostId="10527" RevisionGUID="dee2ab47-97ea-44f5-9721-192fb7ad5952" CreationDate="2020-12-28T17:45:38.180" UserId="6041" Text="I want to use IES profile with an area light. However I am not sure of &#xD;&#xA;1) the irradiance equation. Is the below formula correct (for calculating the irradiance from the light source in the form of the integral over the area, when we have the intensities) ?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am little bit uncertain on the solid angle formulation. Is this correct?&#xD;&#xA;&#xD;&#xA;2) well if the above is correct, I am not clear how this fits in a monte carlo ray tracer ? Are we sampling intensities here? What is the pdf? also currently in my ray tracer all light sources methods and properties needs radiance values of the light source instead of intensity how would this fit in?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NnbRR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30632" PostHistoryTypeId="1" PostId="10527" RevisionGUID="dee2ab47-97ea-44f5-9721-192fb7ad5952" CreationDate="2020-12-28T17:45:38.180" UserId="6041" Text="How to use IES Light Profile with an area light source?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30633" PostHistoryTypeId="3" PostId="10527" RevisionGUID="dee2ab47-97ea-44f5-9721-192fb7ad5952" CreationDate="2020-12-28T17:45:38.180" UserId="6041" Text="|pathtracing|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30634" PostHistoryTypeId="5" PostId="10527" RevisionGUID="517b15ea-320d-4268-a943-9506900d805c" CreationDate="2020-12-28T20:25:39.153" UserId="6041" Comment="added 419 characters in body" Text="I want to use IES profile with an area light. My understanding is that the IES file assume the source to be a point light. That is in case of (large)area light the measurements are taken at a distance(normally 5 times the major dimension of the light source) that even an area light can be considered as a point light. However I am confused on how a measurement taken at say 12m can be used to calculate the contribution of the luminaire at shorter distances?&#xD;&#xA;&#xD;&#xA;Also as the IES file has intensities values rather than the radiance,&#xD;&#xA;&#xD;&#xA;1) Is the below formula correct for calculating the irradiance from the light source in the form of the integral over the area, when we have the intensities ?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am little bit uncertain on the solid angle formulation. Is this correct?&#xD;&#xA;&#xD;&#xA;2) well if the above is correct, I am not clear how this fits in a monte carlo ray tracer ? Are we sampling intensities here? What is the pdf? also currently in my ray tracer all light sources methods and properties needs radiance values of the light source instead of intensity how would this fit in?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NnbRR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30636" PostHistoryTypeId="2" PostId="10528" RevisionGUID="94daa060-9bfd-4d79-a954-b8243d475398" CreationDate="2020-12-29T02:28:14.663" UserId="445" Text="*[Disclaimer: I'm a hobbyist, not well-read in computer graphics techniques. I may be unfamiliar with common terminology or methods.]*&#xD;&#xA;&#xD;&#xA;It's possible to explain and reproduce this effect entirely in a “physically-based” manner, simulating the imperfections of physical objects:&#xD;&#xA;&#xD;&#xA;* Many objects do not emit or reflect single wavelengths of light, but some spectrum, even if one wavelength dominates.&#xD;&#xA;* Light sensors, whether they are cameras or the human eye, do not have perfect RGB color filters which reject all light outside of non-overlapping bands.&#xD;&#xA;&#xD;&#xA;These two effects combined mean that **if we make an object bright enough, well past the point of “overexposing” the image, all colors will become perceptually white.** All you need to do to implement this is:&#xD;&#xA;&#xD;&#xA;* Specify the monochromatic color of your glow such that none of its color channels are exactly zero.&#xD;&#xA;* While you're doing your floating-point color calculations in your fragment shader, multiply your glow by a number much greater than 1, causing clipping in the final output image.&#xD;&#xA;&#xD;&#xA;A potential disadvantage of this technique is that, if the hue of the glow is not one of the six primary or secondary colors, then there will be a hue shift in the segment between where one color channel saturates and two do; it'll shift some amount towards cyan/magenta/yellow before proceeding to white. This is not unrealistic, but it might be unaesthetic.&#xD;&#xA;&#xD;&#xA;Even if there is not a hue shift, the points where individual color channels saturate might be noticeable due to the sharp change in the spatial derivative; this could be improved by introducing a “soft clipping” nonlinearity that slows down the approach to the maximum value of each channel (which is a form of global tone mapping).&#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;As an example of the results of this strategy, here is a simple simulation of a CRT oscilloscope trace that I programmed. The algorithm is:&#xD;&#xA;1. Draw many dim 1-pixel points overlaid with additive blending.&#xD;&#xA;&#xD;&#xA;    (It would be more efficient and precise to use a line with variable brightness, but throwing lots of points at the problem was easy to implement, though it produces artifacts such as dotted lines which are visible in this example.)&#xD;&#xA;2. Blur.&#xD;&#xA;3. Multiply by (R=0.1 G=1.0 B=0.5) × a configurable brightness parameter.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Notice that the dark areas (vertical lines) are mostly green and the bright areas (horizontal lines and peaks, where the simulated beam moves slower) have a white core.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rXNTA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30638" PostHistoryTypeId="50" PostId="8260" RevisionGUID="5ef2ad26-b038-40a5-acc5-b9108a0b0082" CreationDate="2020-12-29T07:01:55.273" UserId="-1" />
  <row Id="30639" PostHistoryTypeId="2" PostId="10529" RevisionGUID="b50c3e91-588f-419f-be23-3cabfdb165bc" CreationDate="2020-12-29T08:14:19.890" UserId="7072" Text="Recently I have been trying to create a shader that imitates a shader within Affinity Photo. It is used in the radial gradient fill and essentially you set your endpoint colors and then set the midpoint to a percent.&#xD;&#xA;&#xD;&#xA;[![Showing toggling of effect][1]][1]&#xD;&#xA;&#xD;&#xA;What is interesting here is that with a midpoint set to 0 everything is not just one color. Same with 100. So it does not appear to be a trivial function.&#xD;&#xA;&#xD;&#xA;I exported some images of this gradient at percent of 0%, 50% and 100% and graphed the red pixel values from the center pixel going to the end. Below are the results.&#xD;&#xA;&#xD;&#xA;[![Results graphed][2]][2]&#xD;&#xA;&#xD;&#xA;Unfortunately even after seeing it graphed I am unable to determine the f(x,a) where a goes from 0-100 that would recreate this graph in order to replicate the shader. Any tips that might get me closer to this formula?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8tBPH.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/pyzFY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30640" PostHistoryTypeId="1" PostId="10529" RevisionGUID="b50c3e91-588f-419f-be23-3cabfdb165bc" CreationDate="2020-12-29T08:14:19.890" UserId="7072" Text="Determining the function of a radial gradient fill with midpoint" ContentLicense="CC BY-SA 4.0" />
  <row Id="30641" PostHistoryTypeId="3" PostId="10529" RevisionGUID="b50c3e91-588f-419f-be23-3cabfdb165bc" CreationDate="2020-12-29T08:14:19.890" UserId="7072" Text="|mathematics|shading|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30642" PostHistoryTypeId="2" PostId="10530" RevisionGUID="dc11841c-4b05-4485-8a2d-7a8305bd5a6a" CreationDate="2020-12-29T11:44:13.600" UserId="8263" Text="I found a workaround suggested [at the bottom of this page][1] : to deal with coplanar lines and polygons, one can apply a different glDepthRange to polygon face and polygon wireframe.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl.org/archives/resources/faq/technical/polygonoffset.htm" ContentLicense="CC BY-SA 4.0" />
  <row Id="30643" PostHistoryTypeId="2" PostId="10531" RevisionGUID="df506bbe-4882-42d2-8b2e-54f66d81e515" CreationDate="2020-12-29T12:24:34.220" UserId="7724" Text="It seems to be just a scalar Bezier function to me, where the second coefficient is determined by $a$&#xD;&#xA;&#xD;&#xA;$$(1-x)^2 + a 2 (1-x) x,$$&#xD;&#xA;&#xD;&#xA;here $a \in [0, 1]$ is a normalized percentage. This gets you pretty close to the function that is graphed, but the function will not be as flat for $a = 0$ and $a = 1$. I suspect the function is of a higher degree:&#xD;&#xA;&#xD;&#xA;$$(1-x)^3 + a 3(1-x)^2 x + a 3(1-x) x^2$$&#xD;&#xA;&#xD;&#xA;or even&#xD;&#xA;&#xD;&#xA;$$(1-x)^4 + a 4(1-x)^3 x + a 6(1-x)^2 x^2 + a 4 (1-x) x^3$$&#xD;&#xA;&#xD;&#xA;With increasing degree comes increased flatness (dragging out the colour of the midpoint). However, these higher order function are not exactly straight at $a = 0.5$. Using the coefficients $\frac{2}{3}$ $\frac{1}{3}$ in the cubic equation will get you a straight line for the cubic version&#xD;&#xA;&#xD;&#xA;$$(1-x)^3 + \frac{2}{3} 3(1-x)^2 x + \frac{1}{3} 3(1-x) x^2.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30644" PostHistoryTypeId="34" PostId="10467" RevisionGUID="f56e7ac8-1f2a-44ac-8b47-4e4e3fe9f34e" CreationDate="2020-12-29T13:03:25.180" UserId="-1" Comment="68" />
  <row Id="30645" PostHistoryTypeId="5" PostId="10531" RevisionGUID="157dae91-0bdd-4230-966a-cf5aa1e8a43e" CreationDate="2020-12-29T15:27:15.200" UserId="7724" Comment="added 444 characters in body" Text="It seems to be just a scalar Bezier function to me, where the second coefficient is determined by $a$&#xD;&#xA;&#xD;&#xA;$$(1-x)^2 + a 2 (1-x) x,$$&#xD;&#xA;&#xD;&#xA;here $a \in [0, 1]$ is a normalized percentage. This gets you pretty close to the function that is graphed, but the function will not be as flat for $a = 0$ and $a = 1$. I suspect the function is of a higher degree:&#xD;&#xA;&#xD;&#xA;$$(1-x)^3 + a 3(1-x)^2 x + a 3(1-x) x^2$$&#xD;&#xA;&#xD;&#xA;or even&#xD;&#xA;&#xD;&#xA;$$(1-x)^4 + a 4(1-x)^3 x + a 6(1-x)^2 x^2 + a 4 (1-x) x^3$$&#xD;&#xA;&#xD;&#xA;With increasing degree comes increased flatness (dragging out the colour of the midpoint). However, these higher order function are not exactly straight at $a = 0.5$. Using the coefficients $\frac{2}{3}$ $\frac{1}{3}$ in the cubic equation will get you a straight line for the cubic version&#xD;&#xA;&#xD;&#xA;$$(1-x)^3 + \frac{2}{3} 3(1-x)^2 x + \frac{1}{3} 3(1-x) x^2.$$&#xD;&#xA;&#xD;&#xA;For the cubic version you can create two additional functions&#xD;&#xA;&#xD;&#xA;$$q(a) = 0.975 2 (1-x) x + x^2$$&#xD;&#xA;$$r(a) = 0.025 2 (1-x) x + x^2$$ &#xD;&#xA;&#xD;&#xA;and then replace the second and fourth coefficents in the quartic function with these&#xD;&#xA;&#xD;&#xA;$$(1-x)^4 + q(a) 4(1-x)^3 x + a 6(1-x)^2 x^2 + r(a) 4 (1-x) x^3$$&#xD;&#xA;&#xD;&#xA;this will preserve flatness at extremes and (approximate) linearity at $a=0.5$. You can view it here: https://www.desmos.com/calculator/hwj7jyozv9&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30647" PostHistoryTypeId="2" PostId="10532" RevisionGUID="00fba2fb-41d4-41ea-9ffe-d629a96f7498" CreationDate="2020-12-30T06:23:59.403" UserId="15470" Text="Fellow 15-year-old here.&#xD;&#xA;As far as I have read, you would usually implement an Area light by combining multiple things:&#xD;&#xA;&#xD;&#xA; - A point or directional light at the position for BRDF calculations.&#xD;&#xA; - Using the size of the light for a specular highlight.&#xD;&#xA; - PCSS or another technique for soft shadows." ContentLicense="CC BY-SA 4.0" />
  <row Id="30648" PostHistoryTypeId="2" PostId="10533" RevisionGUID="98ea403f-4e2a-49a2-b6d3-4828be394ca3" CreationDate="2020-12-30T18:58:57.533" UserId="15225" Text="I'm wondering how to compute a bounding tetrahedron from a set of points so i can initialize a delaunay triangulation &#xD;&#xA;&#xD;&#xA;My first approach was to find the bounding box to my set of points and then compute a tetrahedron going from the bounding box . &#xD;&#xA;&#xD;&#xA;I'm searching for a robust method for doing it .    &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30649" PostHistoryTypeId="1" PostId="10533" RevisionGUID="98ea403f-4e2a-49a2-b6d3-4828be394ca3" CreationDate="2020-12-30T18:58:57.533" UserId="15225" Text="How to compute a bounding tetrahedron" ContentLicense="CC BY-SA 4.0" />
  <row Id="30650" PostHistoryTypeId="3" PostId="10533" RevisionGUID="98ea403f-4e2a-49a2-b6d3-4828be394ca3" CreationDate="2020-12-30T18:58:57.533" UserId="15225" Text="|computational-geometry|geometry|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30651" PostHistoryTypeId="50" PostId="8757" RevisionGUID="166ecdc7-0c03-4cc2-850d-1d2215a86841" CreationDate="2020-12-31T10:05:40.583" UserId="-1" />
  <row Id="30657" PostHistoryTypeId="5" PostId="10531" RevisionGUID="a6e98f91-edb6-48f7-88de-d25a535ac112" CreationDate="2021-01-02T12:14:01.880" UserId="7724" Comment="added 12 characters in body" Text="It seems to be just a scalar Bezier function to me, where the second coefficient is determined by $a$&#xD;&#xA;&#xD;&#xA;$$(1-x)^2 + a 2 (1-x) x,$$&#xD;&#xA;&#xD;&#xA;here $a \in [0, 1]$ is a normalized percentage. This gets you pretty close to the function that is graphed, but the function will not be as flat for $a = 0$ and $a = 1$. I suspect the function is of a higher degree:&#xD;&#xA;&#xD;&#xA;$$(1-x)^3 + a 3(1-x)^2 x + a 3(1-x) x^2$$&#xD;&#xA;&#xD;&#xA;or even&#xD;&#xA;&#xD;&#xA;$$(1-x)^4 + a 4(1-x)^3 x + a 6(1-x)^2 x^2 + a 4 (1-x) x^3$$&#xD;&#xA;&#xD;&#xA;With increasing degree comes increased flatness (dragging out the colour of the midpoint). However, these higher order function are not exactly straight at $a = 0.5$. Using the coefficients $\frac{2}{3}$ $\frac{1}{3}$ in the cubic equation will get you a straight line for the cubic version&#xD;&#xA;&#xD;&#xA;$$(1-x)^3 + \frac{2}{3} 3(1-x)^2 x + \frac{1}{3} 3(1-x) x^2.$$&#xD;&#xA;&#xD;&#xA;For the cubic version you can create two additional functions&#xD;&#xA;&#xD;&#xA;$$q(a) = 0.975 \cdot 2 (1-x) x + x^2$$&#xD;&#xA;$$r(a) = 0.025 \cdot 2 (1-x) x + x^2$$ &#xD;&#xA;&#xD;&#xA;and then replace the second and fourth coefficents in the quartic function with these&#xD;&#xA;&#xD;&#xA;$$(1-x)^4 + q(a) 4(1-x)^3 x + a 6(1-x)^2 x^2 + r(a) 4 (1-x) x^3$$&#xD;&#xA;&#xD;&#xA;this will preserve flatness at extremes and (approximate) linearity at $a=0.5$. You can view it here: https://www.desmos.com/calculator/hwj7jyozv9&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30658" PostHistoryTypeId="2" PostId="10535" RevisionGUID="3986884a-c300-442b-8764-79db3ed9b7fc" CreationDate="2021-01-02T14:23:50.977" UserDisplayName="user15232" Text="I have a situation, where I have an array of vertices on the CPU side, for which, besides rendering-relevant data, like their position, I have a lot of other data at each vertex. All vertex data is updated (more or less) every frame, requiring transferring the changes over to the GPU every time.&#xD;&#xA;&#xD;&#xA;So far I have used two approaches, neither of which I am particularly happy with:&#xD;&#xA;&#xD;&#xA;**Approach 1**&#xD;&#xA;&#xD;&#xA;Just copy everything over to the GPU. This might seem silly, but my application does not use a significant amount of VRAM overall, so this is no issue in that regard, but of course, when the vertex count increases, so does the amount of data needlessly transferred to the GPU every frame, which does become a performance issue.&#xD;&#xA;&#xD;&#xA;**Approach 2**&#xD;&#xA;&#xD;&#xA;Keep separate arrays for the GPU-relevant vertex data and the non-relevant vertex data. While this solves the unnecessary transfer issue, I find it very clunky to work with on the CPU side, since I at all times have to keep two arrays in sync. Ideally I would like to have one clean struct per vertex, which I can easily work with.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Is there some other approach to this?&#xD;&#xA;&#xD;&#xA;Something I could think of, which unfortunately doesn't seem to exist in OpenGL, is a variant of `glBufferData`, which I could tell some stride and offset, like with `glVertexAttribPointer`, which parts of each data block I want to transfer to the buffer in VRAM.&#xD;&#xA;&#xD;&#xA;There also might be some way to neatly solve this with some C++ features that I am not aware off. Some way to have two arrays act as one, or something like that.&#xD;&#xA;&#xD;&#xA;Any ideas and suggestions are appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="30659" PostHistoryTypeId="1" PostId="10535" RevisionGUID="3986884a-c300-442b-8764-79db3ed9b7fc" CreationDate="2021-01-02T14:23:50.977" UserDisplayName="user15232" Text="Efficiently transferring only neede parts of the vertex data to the GPU (C++/OpenGL)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30660" PostHistoryTypeId="3" PostId="10535" RevisionGUID="3986884a-c300-442b-8764-79db3ed9b7fc" CreationDate="2021-01-02T14:23:50.977" UserDisplayName="user15232" Text="|opengl|c++|vertex-buffer-object|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30661" PostHistoryTypeId="5" PostId="10535" RevisionGUID="3ec92db6-57eb-41da-bf3f-acfc2c24f83f" CreationDate="2021-01-02T14:55:00.967" UserId="13095" Comment="Fix some typos in title and question" Text="I have a situation, where I have an array of vertices on the CPU side, for which, besides rendering-relevant data, like their position, I have a lot of other data at each vertex. All vertex data is updated (more or less) every frame, requiring transferring the changes over to the GPU every time.&#xD;&#xA;&#xD;&#xA;So far I have used two approaches, neither of which I am particularly happy with:&#xD;&#xA;&#xD;&#xA;**Approach 1**&#xD;&#xA;&#xD;&#xA;Just copy everything over to the GPU. This might seem silly, but my application does not use a significant amount of VRAM overall, so this is no issue in that regard, but of course, when the vertex count increases, so does the amount of data needlessly transferred to the GPU every frame, which does become a performance issue.&#xD;&#xA;&#xD;&#xA;**Approach 2**&#xD;&#xA;&#xD;&#xA;Keep separate arrays for the GPU-relevant vertex data and the non-relevant vertex data. While this solves the unnecessary transfer issue, I find it very clunky to work with on the CPU side, since I at all times have to keep two arrays in sync. Ideally, I would like to have one clean struct per vertex, which I can easily work with.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Is there some other approach to this?&#xD;&#xA;&#xD;&#xA;Something I could think of, which unfortunately doesn't seem to exist in OpenGL, is a variant of `glBufferData`, which I could tell some stride and offset, like with `glVertexAttribPointer`, which parts of each data block I want to transfer to the buffer in VRAM.&#xD;&#xA;&#xD;&#xA;There also might be some way to neatly solve this with some C++ features that I am not aware of. Some way to have two arrays act as one, or something like that.&#xD;&#xA;&#xD;&#xA;Any ideas and suggestions are appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="30662" PostHistoryTypeId="4" PostId="10535" RevisionGUID="3ec92db6-57eb-41da-bf3f-acfc2c24f83f" CreationDate="2021-01-02T14:55:00.967" UserId="13095" Comment="Fix some typos in title and question" Text="Efficiently transferring only needed parts of the vertex data to the GPU (C++/OpenGL)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30666" PostHistoryTypeId="5" PostId="2412" RevisionGUID="8e07c6d6-8b5a-453b-bd4a-3744425972ec" CreationDate="2021-01-03T15:52:41.400" UserId="3305" Comment="deleted 3 characters in body" Text="In perspective projection, group of parallel lines have the same vanishing point. I am interesting about the reverse calculation: Getting the group of parallel lines equations that their vanishing point specific point.&#xD;&#xA;&#xD;&#xA;Say I know that the camera is perspective camera at $(0,0,0)$ and it's direction $(0,0,1)$, the view plane is $z = 1$ and I am interesting about the lines in plane $y= y_0$ that their vanishing point is $P = (p_x,p_y,p_z)$.&#xD;&#xA;&#xD;&#xA;I have tried to calculate the projection point of some point $(x,y_0,z)$ and get the equations:  &#xD;&#xA;(i) $p_x = x(\frac1z)$  &#xD;&#xA;(ii) $p_y = y_0(\frac1z)$  &#xD;&#xA;(iii) $p_z = 1$&#xD;&#xA;&#xD;&#xA;But it seems wrong because if the vanishing point is like $(x_0,0,*)$ then form (ii) we will get $z\rightarrow \infty$ but then (i) is wrong because $x(\frac1z)\rightarrow0$ but it need to be equals to $x_0$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So how can I get the group of parallel lines have the same vanishing point in these conditions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30667" PostHistoryTypeId="2" PostId="10537" RevisionGUID="4dd87dc8-7cc7-4490-a7db-b56c06d5beda" CreationDate="2021-01-03T22:36:28.013" UserId="9154" Text="I am reading Physically Based Rendering [section 2.2.2 on RGB color][1].&#xD;&#xA;&#xD;&#xA;I am trying to understand how, given a display spectral response curves for rgb intensities, we can choose the intensities so that the display will emit an equivalent spectrum (a metamer cie xyz) &#xD;&#xA;&#xD;&#xA;It is my understanding that the following section tries to explain exactly that.&#xD;&#xA;&#xD;&#xA;&gt; Given an *(x,y,z)* representation of an SPD, we can convert it to corresponding&#xD;&#xA;&gt; RGB coefficients, given the choice of a particular set of SPDs that&#xD;&#xA;&gt; define red, green, and blue for a display of interest. Given the&#xD;&#xA;&gt; spectral response curves *R(lambda)*, *G(lambda)*, and *B(lambda)*, for a particular display, RGB&#xD;&#xA;&gt; coefficients can be computed by integrating the response curves with&#xD;&#xA;&gt; the SPD *S(lambda)* and using the tristimulus theory of color perception:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I can't understand this formula. Why it is considered correct? Why choosing r this way makes the display emit the correct / equivalent SPD?&#xD;&#xA;&#xD;&#xA;Can someone break it down for me? &#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Color_and_Radiometry/The_SampledSpectrum_Class.html#RGBColor&#xD;&#xA;  [2]: https://i.stack.imgur.com/32Yww.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30668" PostHistoryTypeId="1" PostId="10537" RevisionGUID="4dd87dc8-7cc7-4490-a7db-b56c06d5beda" CreationDate="2021-01-03T22:36:28.013" UserId="9154" Text="How to determine RGB values given a display spectral response curve?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30669" PostHistoryTypeId="3" PostId="10537" RevisionGUID="4dd87dc8-7cc7-4490-a7db-b56c06d5beda" CreationDate="2021-01-03T22:36:28.013" UserId="9154" Text="|color|physically-based|color-science|spectral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30670" PostHistoryTypeId="2" PostId="10538" RevisionGUID="747635ea-ea7b-4144-a021-ebaee14ef8f0" CreationDate="2021-01-03T22:38:17.140" UserId="15493" Text="First off, this may not be the right group, however, it is the closest one I can think of.&#xD;&#xA;&#xD;&#xA;I took a few pictures of a computer panel at a known distance, but the angle to a corner would require the use of the 3D Pythagoras theorem (*√(x^2 + y^2 + z^2)*) See [Pythagoras theorem in 3D][1].&#xD;&#xA;&#xD;&#xA;So my questions are thus:&#xD;&#xA;&#xD;&#xA; 1. What is the first step?&#xD;&#xA; 2. Will this be possible instead of measuring EVERYTHING?&#xD;&#xA;&#xD;&#xA;Pictures will be attached:&#xD;&#xA;&#xD;&#xA; 1. [![Rear Panel - Zoom in to get the exact mm measurement][2]][2]&#xD;&#xA; 2. [![Rear Panel][3]][3]&#xD;&#xA; 3. [![Rear Panel][4]][4]&#xD;&#xA; 4. [![Rear Panel][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.mathsisfun.com/geometry/pythagoras-3d.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/iGyX2.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/Xgina.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/iywFV.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/z3Kpq.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30671" PostHistoryTypeId="1" PostId="10538" RevisionGUID="747635ea-ea7b-4144-a021-ebaee14ef8f0" CreationDate="2021-01-03T22:38:17.140" UserId="15493" Text="How to extrapolate an object from a photo taken with an iPhone" ContentLicense="CC BY-SA 4.0" />
  <row Id="30672" PostHistoryTypeId="3" PostId="10538" RevisionGUID="747635ea-ea7b-4144-a021-ebaee14ef8f0" CreationDate="2021-01-03T22:38:17.140" UserId="15493" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30673" PostHistoryTypeId="5" PostId="10537" RevisionGUID="4b7df5cf-f7bd-4e34-8135-17c2d821a598" CreationDate="2021-01-03T22:52:25.023" UserId="9154" Comment="added 2 characters in body" Text="I am reading Physically Based Rendering [section 2.2.2 on RGB color][1].&#xD;&#xA;&#xD;&#xA;I am trying to understand how, given a display spectral response curves for rgb intensities, we can choose the intensities so that the display will emit an equivalent spectrum (a CIE xyz metamer) &#xD;&#xA;&#xD;&#xA;It is my understanding that the following section tries to explain exactly that.&#xD;&#xA;&#xD;&#xA;&gt; Given an *(x,y,z)* representation of an SPD, we can convert it to corresponding&#xD;&#xA;&gt; RGB coefficients, given the choice of a particular set of SPDs that&#xD;&#xA;&gt; define red, green, and blue for a display of interest. Given the&#xD;&#xA;&gt; spectral response curves *R(lambda)*, *G(lambda)*, and *B(lambda)*, for a particular display, RGB&#xD;&#xA;&gt; coefficients can be computed by integrating the response curves with&#xD;&#xA;&gt; the SPD *S(lambda)* and using the tristimulus theory of color perception:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I can't understand this formula. Why it is considered correct? Why choosing *r* this way makes the display emit the correct / equivalent SPD?&#xD;&#xA;&#xD;&#xA;Can someone break it down for me? &#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Color_and_Radiometry/The_SampledSpectrum_Class.html#RGBColor&#xD;&#xA;  [2]: https://i.stack.imgur.com/32Yww.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30676" PostHistoryTypeId="2" PostId="10539" RevisionGUID="d30c9e98-8c48-4bb7-b88a-dab282d9bf27" CreationDate="2021-01-06T02:43:18.757" UserId="10450" Text="I exported an example from Blender to replicate the issue, with the most basic project (unwrap, simple image texture in shader editor) and found it looked exactly like what your expected image shows.&#xD;&#xA;&#xD;&#xA;I exported it to some simple model-loading code and it textured it correctly.&#xD;&#xA;When I used your OBJ file (after adding `mtllib cube.mtl` and a `map_Kd cube.png` to `cube.mtl`), it was showing the similar texture problems. Then,I saw that the working OBJ file was generating less faces (didn't have triangulate vertices checked) and the UVs were generated differently. &#xD;&#xA;&#xD;&#xA;Alas, I would say it is an issue with how you process your vertices, whether importing as quads or triangles, and would suggest having a look at that (either leaving triangulate vertices unchecked or fixing the code)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30681" PostHistoryTypeId="2" PostId="10541" RevisionGUID="33a5c24e-a870-43ee-ad58-f6b6311d311e" CreationDate="2021-01-06T16:08:12.230" UserId="15519" Text="I'm new to learning about ray tracing, but have been fairly confused by the mathematical foundations of it all. Specifically of radiometry/radiative transfer. I've internet searched a lot and skimmed a ton of references, but still very confused.&#xD;&#xA;&#xD;&#xA;Here is a list of some of the things I have had to struggle a lot to understand:&#xD;&#xA;&#xD;&#xA;1. Irradiance is a function of 3 variables $E(p,n, \mathrm{in}/\mathrm{out})$ and it's not really the derivative of anything with respect to anything else (in the function sense)&#xD;&#xA;&#xD;&#xA;2. If $p$ is a point on an actual surface in a scene, irradiance doesn't make sense in directions that aren't the surface normal, except perhaps as limit.&#xD;&#xA;&#xD;&#xA;3. Radiance is not meaningfully the derivative of irradiance (Wikipedia says it's the derivative w.r.t. étendue, which is a great way to get more confused).&#xD;&#xA;&#xD;&#xA;4. Radiance can be defined without ever using the words &quot;projected area&quot;, &quot;solid angle&quot; or &quot;subtend&quot;.&#xD;&#xA;&#xD;&#xA;5. You don't need to draw pictures with infinitesimals to think about radiance. I see infinitesimals in pictures a lot, e.g. [Figures 1 and 2 Wikipedia's Lambert's cosine law article][1].&#xD;&#xA;&#xD;&#xA;6. Radiance is preserved along paths (in vacuum). Is this an axiom of the theory or a theorem?&#xD;&#xA;&#xD;&#xA;I've  found the following approach more insightful than the usual presentations:&#xD;&#xA;&#xD;&#xA;1. If you have an oriented surface, you can define the flux entering it $\Phi(S)$.&#xD;&#xA;2. Irradiance is something that's integrated into flux:&#xD;&#xA;$$ \Phi(S) = \int_SE(p, n_p, \mathrm{in}) \mathrm{d}S(p)$$&#xD;&#xA;3. For two surfaces, we can define direct flux transport between them: the power that exist $S_1$ and directly enters $S_2$, $\Phi(S_1, S_2)$.&#xD;&#xA;4. &quot;Flux transport density&quot; (not sure if correct term) is something that's integrated into flux transport. It is the function of 4 variables $K(p_\text{source}, n_\text{source}, p_\text{target}, n_\text{target})$&#xD;&#xA;$$ \Phi(S_1,S_2) = \int_{S_2} \int_{S_1} K(p, n_p, q, n_q) \mathrm{d}S_1(p) \mathrm{d}S_2(q)$$&#xD;&#xA;5. &quot;Light hull principle&quot; consider two oriented disks $D_p = D(p, n_p, r_p)$ and $D_q = D(q, n_q, r_q)$ that are sufficiently small.&#xD;&#xA;&#xD;&#xA;   1. If $(q-p) \cdot n_p \le 0$ then $\Phi(D_p, D_q) = 0$&#xD;&#xA;   2. Taking the limit $r_p \to 0$ shows that $(q-p) \cdot n_p$ implies $K(p, n_p, q, n_q) = 0$&#xD;&#xA;   3. If $(p-q) \cdot n_q \le 0$ then $\Phi(D_p, D_q) = 0$&#xD;&#xA;   4. Taking the limit $r_q \to 0$ shows that $(p-q) \cdot n_q$ implies $K(p, n_p, q, n_q) = 0$&#xD;&#xA;   5. Let's assume $(q-p) \cdot n_p &gt; 0$ and $(p-q) \cdot n_q &gt; 0$ going forward. Maybe it's simplier to write $|\cos(\theta_p)| &lt; \pi/2$, $|\cos(\theta_q)| &lt; \pi/2$&#xD;&#xA;   6. Let's form the &quot;light hull&quot; of $D_p$ and $D_q$. This is a funny truncated cone like shape defined by $$H(D_p, D_q) = \{ t p' + (1-t) q' | p' \in D_p, q' \in D_q, t \in [0, 1] \}$$ [![enter image description here][2]][2] It may later make sense to allow  $t$ to go negative/greater than 1, extending the hull a bit.&#xD;&#xA;   7. Let $a$ be a point on the segment $pq$. Intersecting the light hull with a plane through $a$ gives as circular shaped section:&#xD;&#xA;$$H(a, n_a, D_p, D_q) = \{ b | (b - a) \cdot n_a = 0 \} \cap H(D_p, D_q) $$&#xD;&#xA;&#xD;&#xA;   8. In free space we have $$\Phi(D_p, D_q) = \Phi(D_p, H(a, n_a, D_p, D_q)) = \Phi(H(a, n_a, D_p, D_q), D_q)$$ I call this the *light hull principle* and is basically just geometry saying &quot;if I put a transparent screen in the light's way, all the light will go through it&quot;.&#xD;&#xA;&#xD;&#xA;   9. Using the light hull principle, we see that we can replace $D_q$ with a similar disk-ish shape that's orthogonal to $pq$: $$ \Phi(D_p, D_q) = \Phi(D_p, H(q, p-q, D_p, D_q))$$ Let's call this shape $D_q'$.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;For small $r_p^2$, $r_q^2$, the left hand side is&#xD;&#xA;$$ \Phi(D_p, D_q) \approx K(p, n_p, q, n_q) \pi^2 r_p^2 r_q^2$$&#xD;&#xA;Or more formally&#xD;&#xA;$$ \frac{\partial^4 \Phi(D_p, D_q) }{(\partial r_p)^2 (\partial r_q)^2} \bigg|_{r_p = r_q = 0} = 4 \pi^2 K(p, n_p, q, n_q) $$&#xD;&#xA;I don't want to go into too much detail here, but it's possible to prove for the right hand side that $$ \frac{\partial^4 \Phi(D_p, H(q, p-q, D_p, D_q)) }{(\partial r_p)^2 (\partial r_q)^2} \bigg|_{r_p = r_q = 0} = 4 \pi^2 \cos(\theta_q) K\left(p, n_p, q, \frac{p-q}{||p-q||} \right) $$&#xD;&#xA;It follows that $$ K(p, n_p, q, n_q) = \cos(\theta_q) K\left(p, n_p, q, \frac{p-q}{||p-q||} \right)$$&#xD;&#xA;    10. Repeating the same argument at $p$ instead of $q$, we get&#xD;&#xA;$$ K(p, n_p, q, n_q) = \cos(\theta_p) \cos(\theta_q) K\left(p, \frac{q-p}{||p-q||}, q, \frac{p-q}{||p-q||} \right)$$&#xD;&#xA;    11. Assuming now that the two disks are directly facing each other, i.e. $n_p = \frac{q-p}{||p-q||} = -n_q$, we can apply the light hull principle and take a limit/derivative as $r_p, r_q \to 0$ to show the inverse square law&#xD;&#xA;$$ K(p, n_p, p+r n_p, -n_p) = \frac{1}{r^2} K(p, n_p, p+n_p, - n_p)$$&#xD;&#xA;&#xD;&#xA;6. Let $r = ||p-q||$ and $n = \frac{q-p}{r}$. We now know that&#xD;&#xA;$$ \begin{aligned}&#xD;&#xA;K(p, n_p, q, n_q) &amp;= K(p, n, p+n, -n) \frac{\cos(\theta_p) \cos(\theta_q)}{r^2} \\&#xD;&#xA;&amp;=: L(p,n,\mathrm{out}) \frac{\cos(\theta_p) \cos(\theta_q)}{r^2} \\&#xD;&#xA;&amp;=: L(q,-n,\mathrm{in}) \frac{\cos(\theta_p) \cos(\theta_q)}{r^2}&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;Where $L$ is the defined by the equation above. We call $L$ radiance.&#xD;&#xA;&#xD;&#xA;7. Taking the limit $p \to q$ shows that $L(q, n, \mathrm{out}) = L(q, -n, \mathrm{in}) = L(p, n, \mathrm{out})$. Therefore radiance is constant along rays (and $K$ is translation invariant).&#xD;&#xA;&#xD;&#xA;The significance of this is that we have defined radiance and proved it invariant by using a simple geometric principle on finite (non-infinitesimal) surfaces and taking appropriate limits. It's a lot more work than saying irradiance over projected surface area times solid angle, but to me much more intuitive.&#xD;&#xA;&#xD;&#xA;The light hull principle is an axiom/key &quot;physical&quot; fact, and everything else is a theorem.&#xD;&#xA;&#xD;&#xA;My question is; is there a reference that deals with radiative transfer in general in a similar way as I've just dealt with radiance?&#xD;&#xA;&#xD;&#xA;The closest thing I could find is [Veach's PhD thesis][4] where he defines some interesting concepts using measure theory in Chapter 3 and its appendix. The idea is that a scene is a system of $N$ non-interacting photons moving around. Radiometric quantities can then be defined by a snapshot of this system in time. I think it's a really cool idea and would love to see more of this. To me these are the true foundations. Sadly, I don't think Veach develops them in enough detail. (And I also don't see how a finite number of photons as Veach models them could create equilibrium in the sense that irradiance is independent of time)&#xD;&#xA;&#xD;&#xA;Also, in Chapter 6, he presents a novel argument for the symmetry of the BRDF that's much more satisfying than &quot;physical objects have symmetric BRDFs, now moving on...&quot; that I've seen everywhere else. &#xD;&#xA;&#xD;&#xA;I also found [this paper by Lessig and Castro][5] that says:&#xD;&#xA;&#xD;&#xA;&gt; Radiative transfer describes the transport of electromagnetic energy&#xD;&#xA;&gt; in macroscopicenvironments, classically when polarization effects are&#xD;&#xA;&gt; neglected [37]. The theory originates in work by Bouguer [6, 7] and&#xD;&#xA;&gt; Lambert [22] in the 18thcentury where light intensity and its&#xD;&#xA;&gt; measurement were first studied systematically, cf. Fig. 1. In the&#xD;&#xA;&gt; 19thand early 20thcentury the theory was then extended to include&#xD;&#xA;&gt; transport and scattering effects [26, 9, 42, 43]. To this day, however,&#xD;&#xA;&gt; radiative transfer is a phenomenological theory with a mathematical&#xD;&#xA;&gt; formulation that still employs the concepts introduced by Lambert in&#xD;&#xA;&gt; the 18thcentury—and this despite the importance of the theory in a&#xD;&#xA;&gt; multitude of fields, such as medical imaging, remote sensing,computer&#xD;&#xA;&gt; graphics, atmospheric science, climate modelling, and astrophysics.&#xD;&#xA;&#xD;&#xA;I don't know any physics so the paper is way over my head, but maybe it's the holy grail?&#xD;&#xA;&#xD;&#xA;Please flood me with references!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Lambert%27s_cosine_law#Details_of_equal_brightness_effect&#xD;&#xA;  [2]: https://i.stack.imgur.com/qTJlU.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/or5th.png&#xD;&#xA;  [4]: https://graphics.stanford.edu/papers/veach_thesis/&#xD;&#xA;  [5]: https://arxiv.org/pdf/1206.3301.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="30682" PostHistoryTypeId="1" PostId="10541" RevisionGUID="33a5c24e-a870-43ee-ad58-f6b6311d311e" CreationDate="2021-01-06T16:08:12.230" UserId="15519" Text="Mathematical Foundations of Radiative Transfer" ContentLicense="CC BY-SA 4.0" />
  <row Id="30683" PostHistoryTypeId="3" PostId="10541" RevisionGUID="33a5c24e-a870-43ee-ad58-f6b6311d311e" CreationDate="2021-01-06T16:08:12.230" UserId="15519" Text="|raytracing|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30684" PostHistoryTypeId="2" PostId="10542" RevisionGUID="56c1bd1d-10ed-45ec-954f-fa3d0340529a" CreationDate="2021-01-06T18:03:12.803" UserId="10096" Text="This is almost verbatim from Veach. Let the trajectory space be $\mathbb{P} = \mathbb{R} \times \mathcal{M} \times \mathcal{S}^2 \times \mathbb{R}^+$, corresponding respectively to: time, set of points of all scene surfaces, unit sphere (directions), wavelength. Let $\mathcal{P}$ be the measurable subsets of $\mathbb{P}$ and we have a measure $\rho$. Let $\rho = l \times A \times \sigma^{\perp} \times l^+$. Where $l, l^+$ are the Lebesgue measures on $\mathbb{R}$ and $\mathbb{R}^+$, $A$ is the Lebesgue measure on $\mathcal{M}$, and $\sigma$ is the projected solid angle measure $(d\sigma^{\perp}(\omega) = |\cos\theta|\sin\theta\,d\theta\,d\phi$). Then given the radiant energy measure $Q(\mathcal{T}, \mathcal{D}, \Omega, \Lambda) \in [0,\infty]$ ($\mathcal{T} \times \mathcal{D} \times \Omega \times \Lambda \subseteq \mathcal{P}$), we can define the density $L_{\lambda}$ of $Q$ with respect to the measure $\rho$ as:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Lambda}\int_{\Omega}\int_{\mathcal{D}}\int_{\mathcal{T}}L_{\lambda}(t, x, \omega,\lambda)d\rho(t,x,\omega,\lambda).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Then the density $L_{\lambda}$ is the Radon-Nikodym derivative of $Q$ w.r.t. $\rho$: $\frac{dQ}{d\rho}(t, x, \omega,\lambda) := L_{\lambda}(t, x, \omega,\lambda)$.&#xD;&#xA;&#xD;&#xA;We can do a similar thing with respect to the appropriate measures:&#xD;&#xA;&#xD;&#xA;Radiant flux:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_1 = l \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\mathcal{T}}\Phi(t, \mathcal{D}, \Omega, \mathcal{\Lambda})\,d\rho_1(t) \\&#xD;&#xA;\frac{dQ}{d\rho_1}(t, \mathcal{D}, \Omega, \mathcal{\Lambda}) := \Phi(t, \mathcal{D}, \mathcal{\Omega}, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Irradiance:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_2 = l\times A \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\mathcal{D}}\int_{\mathcal{T}}E(t, x, \Omega, \mathcal{\Lambda})\,d\rho_2(t,x) \\&#xD;&#xA;\frac{dQ}{d\rho_2}(t, x, \Omega, \mathcal{\Lambda}) := E(t, x, \Omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Intensity:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_3 = l\times \sigma \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Omega}\int_{\mathcal{T}}I(t, \mathcal{D}, \omega, \mathcal{\Lambda})\,d\rho_3(t,\omega) \\&#xD;&#xA;\frac{dQ}{d\rho_3}(t, \mathcal{D}, \omega, \mathcal{\Lambda}) := I(t, \mathcal{D}, \omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Radiance:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_4 = l\times A \times \sigma^{\perp} \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Omega}\int_{\mathcal{D}}\int_{\mathcal{T}}L(t, x, \omega, \mathcal{\Lambda})\,d\rho_3(t,x,\omega) \\&#xD;&#xA;\frac{dQ}{d\rho_4}(t, x, \omega, \mathcal{\Lambda}) := L(t, x, \omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30685" PostHistoryTypeId="5" PostId="10542" RevisionGUID="21a1863a-1711-458b-9a40-bd5f483fcaa3" CreationDate="2021-01-06T18:11:37.070" UserId="10096" Comment="added 8 characters in body" Text="This is almost verbatim from Veach. Let the trajectory space be $\mathbb{P} = \mathbb{R} \times \mathcal{M} \times \mathcal{S}^2 \times \mathbb{R}^+$, corresponding respectively to: time, set of points of all scene surfaces, unit sphere (directions), wavelength. Let $\mathcal{P}$ be the measurable subsets of $\mathbb{P}$ and we have a measure $\rho$. Let $\rho = l \times A \times \sigma^{\perp} \times l^+$. Where $l, l^+$ are the Lebesgue measures on $\mathbb{R}$ and $\mathbb{R}^+$, $A$ is the Lebesgue measure on $\mathcal{M}$, and $\sigma^{\perp}$ is the projected solid angle measure $(d\sigma^{\perp}(\omega) = |\cos\theta|\sin\theta\,d\theta\,d\phi$). Then given the radiant energy measure $Q(\mathcal{T}, \mathcal{D}, \Omega, \Lambda) \in [0,\infty]$ ($\mathcal{T} \times \mathcal{D} \times \Omega \times \Lambda \subseteq \mathcal{P}$), we can define the density $L_{\lambda}$ of $Q$ with respect to the measure $\rho$ as:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Lambda}\int_{\Omega}\int_{\mathcal{D}}\int_{\mathcal{T}}L_{\lambda}(t, x, \omega,\lambda)d\rho(t,x,\omega,\lambda).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Then the density $L_{\lambda}$ is the Radon-Nikodym derivative of $Q$ w.r.t. $\rho$: &#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;\frac{dQ}{d\rho}(t, x, \omega,\lambda) := L_{\lambda}(t, x, \omega,\lambda).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;We can do a similar thing with respect to the appropriate measures:&#xD;&#xA;&#xD;&#xA;Radiant flux:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_1 = l \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\mathcal{T}}\Phi(t, \mathcal{D}, \Omega, \mathcal{\Lambda})\,d\rho_1(t) \\&#xD;&#xA;\frac{dQ}{d\rho_1}(t, \mathcal{D}, \Omega, \mathcal{\Lambda}) := \Phi(t, \mathcal{D}, \mathcal{\Omega}, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Irradiance:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_2 = l\times A \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\mathcal{D}}\int_{\mathcal{T}}E(t, x, \Omega, \mathcal{\Lambda})\,d\rho_2(t,x) \\&#xD;&#xA;\frac{dQ}{d\rho_2}(t, x, \Omega, \mathcal{\Lambda}) := E(t, x, \Omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Intensity:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_3 = l\times \sigma \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Omega}\int_{\mathcal{T}}I(t, \mathcal{D}, \omega, \mathcal{\Lambda})\,d\rho_3(t,\omega) \\&#xD;&#xA;\frac{dQ}{d\rho_3}(t, \mathcal{D}, \omega, \mathcal{\Lambda}) := I(t, \mathcal{D}, \omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Radiance:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_4 = l\times A \times \sigma^{\perp} \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Omega}\int_{\mathcal{D}}\int_{\mathcal{T}}L(t, x, \omega, \mathcal{\Lambda})\,d\rho_4(t,x,\omega) \\&#xD;&#xA;\frac{dQ}{d\rho_4}(t, x, \omega, \mathcal{\Lambda}) := L(t, x, \omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30686" PostHistoryTypeId="5" PostId="10542" RevisionGUID="32b71045-5aec-4352-9ae6-ecb47c75d16f" CreationDate="2021-01-06T18:39:54.513" UserId="10096" Comment="deleted 6 characters in body" Text="This is almost verbatim from Veach. Let the trajectory space be $\mathbb{P} = \mathbb{R} \times \mathcal{M} \times \mathcal{S}^2 \times \mathbb{R}^+$, corresponding respectively to: time, set of points of all scene surfaces, unit sphere (directions), wavelength. Let $\mathcal{P}$ be the set of measurable subsets of $\mathbb{P}$ and we have a measure $\rho$. Let $\rho = l \times A \times \sigma^{\perp} \times l^+$. Where $l, l^+$ are the Lebesgue measures on $\mathbb{R}$ and $\mathbb{R}^+$, $A$ is the Lebesgue measure on $\mathcal{M}$, and $\sigma^{\perp}$ is the projected solid angle measure $(d\sigma^{\perp}(\omega) = |\cos\theta|\sin\theta\,d\theta\,d\phi$). Then given the radiant energy measure $Q(\mathcal{T}, \mathcal{D}, \Omega, \Lambda) \in [0,\infty]$ ($\mathcal{T} \times \mathcal{D} \times \Omega \times \Lambda \in \mathcal{P}$), we can define the density $L_{\lambda}$ of $Q$ with respect to the measure $\rho$ as:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Lambda}\int_{\Omega}\int_{\mathcal{D}}\int_{\mathcal{T}}L_{\lambda}(t, x, \omega,\lambda)d\rho(t,x,\omega,\lambda).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Then the density $L_{\lambda}$ is the Radon-Nikodym derivative of $Q$ w.r.t. $\rho$: &#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;\frac{dQ}{d\rho}(t, x, \omega,\lambda) := L_{\lambda}(t, x, \omega,\lambda).&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;We can do a similar thing with respect to the appropriate measures:&#xD;&#xA;&#xD;&#xA;Radiant flux:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_1 = l \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\mathcal{T}}\Phi(t, \mathcal{D}, \Omega, \mathcal{\Lambda})\,d\rho_1(t) \\&#xD;&#xA;\frac{dQ}{d\rho_1}(t, \mathcal{D}, \Omega, \mathcal{\Lambda}) := \Phi(t, \mathcal{D}, \mathcal{\Omega}, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Irradiance:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_2 = l\times A \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\mathcal{D}}\int_{\mathcal{T}}E(t, x, \Omega, \mathcal{\Lambda})\,d\rho_2(t,x) \\&#xD;&#xA;\frac{dQ}{d\rho_2}(t, x, \Omega, \mathcal{\Lambda}) := E(t, x, \Omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Intensity:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_3 = l\times \sigma \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Omega}\int_{\mathcal{T}}I(t, \mathcal{D}, \omega, \mathcal{\Lambda})\,d\rho_3(t,\omega) \\&#xD;&#xA;\frac{dQ}{d\rho_3}(t, \mathcal{D}, \omega, \mathcal{\Lambda}) := I(t, \mathcal{D}, \omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;&#xD;&#xA;Radiance:&#xD;&#xA;\begin{gather}&#xD;&#xA;\rho_4 = l\times A \times \sigma^{\perp} \\&#xD;&#xA;Q(\mathcal{T}, \mathcal{D}, \Omega, \mathcal{\Lambda}) = \int_{\Omega}\int_{\mathcal{D}}\int_{\mathcal{T}}L(t, x, \omega, \mathcal{\Lambda})\,d\rho_4(t,x,\omega) \\&#xD;&#xA;\frac{dQ}{d\rho_4}(t, x, \omega, \mathcal{\Lambda}) := L(t, x, \omega, \mathcal{\Lambda}).&#xD;&#xA;\end{gather}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30687" PostHistoryTypeId="2" PostId="10543" RevisionGUID="c3eac1f6-a04a-4d67-bbc6-e660afd8c3e1" CreationDate="2021-01-06T20:15:52.023" UserId="15541" Text="Assuming that alpha works properly in the rest of the code it can be solved on shader level:&#xD;&#xA;    &#xD;&#xA;    out vec4 color;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    uniform sampler2D tex;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        color = texture(tex, uv);&#xD;&#xA;        if (all(greaterThan(uv, vec2(0.0))) &amp;&amp; all(lessThan(uv, vec2(1.0)))) {&#xD;&#xA;            color.a = 0.0;&#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="30688" PostHistoryTypeId="2" PostId="10544" RevisionGUID="1d342752-69a2-4cc4-9f88-ee0acc1f7c90" CreationDate="2021-01-07T04:54:02.530" UserId="13456" Text="I'll try my best to give an overview of the subject, and english is not my first language so feel free to ask more detailed information in comments etc.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Here are some terms, light is an electro magnetic radiation. When the power of this radiation falls between a certain wave length, it becomes visible for human beings. `S` is the function that takes wave length value as input and gives a power value as output and is called a s(pectral) p(ower) d(istribution).&#xD;&#xA;&#xD;&#xA;Color on the other hand means different things to different people. We can define color based on our perception of it, or based on the measured spectral power distribution, based on the average physical capacity of human eye etc.&#xD;&#xA;&#xD;&#xA;The thing is spectral distributions change over time constantly, but the color does not change at the same speed. This means that variations in the spectral distribution does not map to color one to one, which shows that there must be a transformation happening between what we perceive as color and what we measure as spectral distribution.&#xD;&#xA;&#xD;&#xA;Now the needs for an accurate and standardised representation of color was quite important for daily life (think of colors around road signs, lamps, etc), the CIE defined its trichomatic system for this purpose. The main idea behind the trichromatic system was that given a carefully chosen three reference spectral distribution, we can represent all of the perceivable colors by mixing these three spds. &#xD;&#xA;&#xD;&#xA;Notice that I did two things over there. I passed from mixing spds, which should produce an spd at the end, to color values which are generally represented with trichromatic system, and I added perceived. The last one is to signal that this is an experimental procedure, that is people did a lot of experiments to come up to this idea of mixing reference spds. &#xD;&#xA;&#xD;&#xA;How do we arrive from mixing spds which should produce an spd to a color value in rgb ? Simple by summing all the power values of the spd resulting from the mix.&#xD;&#xA;The mix is $R(\lambda)S(\lambda)$ part where `R` is the reference spd and `S` is any given spd. $\int$ indicates that we are summing the resulting multiplication.&#xD;&#xA;$\lambda$ is the wave length.&#xD;&#xA;&#xD;&#xA;A great reference on the subject is McCluney 1994, Introduction to Radiometry, chapter 11. Read through 11.2 and then 11.4, that should clarify anything and everything with respect to spds and their transformation to trichromatic values" ContentLicense="CC BY-SA 4.0" />
  <row Id="30689" PostHistoryTypeId="2" PostId="10545" RevisionGUID="094e38d2-c5fe-4351-b017-063b3201883c" CreationDate="2021-01-07T06:28:59.810" UserId="13456" Text="I vaguely understand your question, so this response should be taken more of a long comment rather than an answer.&#xD;&#xA;&#xD;&#xA;&gt; If I have an output device, for which I have a known spectrum data for each of it's primaries, I should be able to calculate the CIEXYZ of its primaries using using the integral equations together with the CIE color matching functions. I can then calculate its respective CIExyY values, which for output device are always inside the boundary if the xyY spectral locus - the chromaticity diagram.&#xD;&#xA;&#xD;&#xA;This is correct in general but note that reference CIE spectral power distribtions are defined for a standard illuminant's spd. &#xD;&#xA;&#xD;&#xA;The term input primaries is a little vague, are you refering to the spd of the light source inside the input device or the combined result produced by the object's spectral reflectance factor (also an spd) multiplied by the spd of the light source of the input device ?&#xD;&#xA;If you know the spectral reflectance factor of the object and the color matching function and the resulting trichromatic value, you should be able to express the spd of the light source as a vector equation something like:&#xD;&#xA;$x_1 \begin{matrix}a_1 \\ a_2 \\ \vdots \\ a_{\lambda}\end{matrix}+x_2 \begin{matrix}a_1 \\ a_2 \\ \vdots \\ a_{\lambda}\end{matrix}+...+x_{\lambda} \begin{matrix}a_1 \\ a_2 \\ \vdots \\ a_{\lambda}\end{matrix} = \begin{matrix}b_1 \\ b_2 \\ \vdots \\ b_{\lambda}\end{matrix}$ where $x$ is from your light source spd and the others are obtained from the remaining (you can for example distribute trichromatic value uniformly to $b$ vector, and fill $a$'s with zeros for non corresponding wave lengths and use the multiplied value for the corresponding wave length), but this is more or less an educated guess rather than a tested solution. &#xD;&#xA;Notice that the expression is a linear system which might help you finding a solution." ContentLicense="CC BY-SA 4.0" />
  <row Id="30690" PostHistoryTypeId="2" PostId="10546" RevisionGUID="e608d39c-e832-4770-90f6-0102246d6170" CreationDate="2021-01-07T06:47:41.070" UserId="13456" Text="I know this is an old question. I did write a spectrum-&gt;rgb converter, however all of its relevant parts for this question come from pbr-book source [code](https://github.com/mmp/pbrt-v3/blob/master/src/core/spectrum.cpp). &#xD;&#xA;&#xD;&#xA;Specifically though, the answer is no. Constant index of refraction (which is actually a wave length dependent number, so taking it as a constant is more of an approximation really) does not produce a grayscale color value. Since the final spectral distribution of your object, aka its color, is determined by the spectral distribution of the light source and the spectral reflectance factor of the surface. If your surface is transmissive, there should also be a spectral transmission factor. Though IOR is constant the value of from the factor and the light source should produce enough change to create a perceived color difference." ContentLicense="CC BY-SA 4.0" />
  <row Id="30691" PostHistoryTypeId="5" PostId="10546" RevisionGUID="a0619f90-b74d-4069-8cee-89fe89f875b4" CreationDate="2021-01-07T07:03:40.393" UserId="13456" Comment="transmission -&gt; transmittance" Text="I know this is an old question. I did write a spectrum-&gt;rgb converter, however all of its relevant parts for this question come from pbr-book source [code](https://github.com/mmp/pbrt-v3/blob/master/src/core/spectrum.cpp). &#xD;&#xA;&#xD;&#xA;Specifically though, the answer is no. Constant index of refraction (which is actually a wave length dependent number, so taking it as a constant is more of an approximation really) does not produce a grayscale color value. Since the final spectral distribution of your object, aka its color, is determined by the spectral distribution of the light source and the spectral reflectance factor of the surface. If your surface is transmissive, there should also be a spectral transmittance factor. Though IOR is constant the value of from the factor and the light source should produce enough change to create a perceived color difference." ContentLicense="CC BY-SA 4.0" />
  <row Id="30692" PostHistoryTypeId="5" PostId="10543" RevisionGUID="2d115cbb-85d6-42ec-8726-5129fcbd2a35" CreationDate="2021-01-07T09:00:42.217" UserId="15541" Comment="Inverted solution, my bad :D" Text="Assuming that alpha works properly in the rest of the code it can be solved on shader level:&#xD;&#xA;    &#xD;&#xA;    out vec4 color;&#xD;&#xA;    in vec2 uv;&#xD;&#xA;    uniform sampler2D tex;&#xD;&#xA;    &#xD;&#xA;    void main() {&#xD;&#xA;        color = texture(tex, uv);&#xD;&#xA;        color.a = 0.0;&#xD;&#xA;        if (all(greaterThan(uv, vec2(0.0))) &amp;&amp; all(lessThan(uv, vec2(1.0)))) {&#xD;&#xA;            color.a = 1.0;&#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="30693" PostHistoryTypeId="2" PostId="10547" RevisionGUID="ff8ed741-5666-4de5-8643-56a1ba21ab4c" CreationDate="2021-01-07T18:09:05.117" UserId="9894" Text="# The Context&#xD;&#xA;I am exploring the idea of making a DIY spectrometer(and colorimeter) for testing various material samples for interior visualization. It's sort of a hobby project for my curiosity and pleasure that might end up useful for my actual work with CG.&#xD;&#xA;&#xD;&#xA;# The Question&#xD;&#xA;I am struggling to find a trustworthy information source for light wavelengths sRGB color space primaries are supposed to be. They are supposed to be the same as in REC.709 as far as I understand. **Are the actual wavelengths of sRGB RGB primaries defined and if so what are they in nanometers?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30694" PostHistoryTypeId="1" PostId="10547" RevisionGUID="ff8ed741-5666-4de5-8643-56a1ba21ab4c" CreationDate="2021-01-07T18:09:05.117" UserId="9894" Text="What wavelengths(dominant) the primary RGB colors are supposed to be in sRGB color space in nanometers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30695" PostHistoryTypeId="3" PostId="10547" RevisionGUID="ff8ed741-5666-4de5-8643-56a1ba21ab4c" CreationDate="2021-01-07T18:09:05.117" UserId="9894" Text="|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30696" PostHistoryTypeId="2" PostId="10548" RevisionGUID="df6503d8-0c56-45df-a504-e3c8e0e6f068" CreationDate="2021-01-08T00:17:45.667" UserId="13456" Text="Trichromatic color system is based on using 3 carefully selected reference spds as you imagine. CIE uses its own reference spds, but there are others who prefer using other spds as reference. So the answer to the question&#xD;&#xA;&#xD;&#xA;&gt; Are the actual wavelengths of sRGB RGB primaries defined and if so what are they in nanometers?&#xD;&#xA;&#xD;&#xA;differs, or might differ, with respect to institutions. As for thrustworthy ressources:&#xD;&#xA;&#xD;&#xA;Scott Burns had kindly provided some reference spds in his [website](http://scottburns.us/fast-rgb-to-spectrum-conversion-for-reflectances/).&#xD;&#xA;&#xD;&#xA;For illuminants and observers etc you can check the [website](https://www.rit.edu/cos/colorscience/rc_useful_data.php) of munsell color science lab." ContentLicense="CC BY-SA 4.0" />
  <row Id="30697" PostHistoryTypeId="5" PostId="10446" RevisionGUID="8a53b72a-63c3-42ee-87db-a40cac40e1b2" CreationDate="2021-01-08T01:18:02.177" UserId="15310" Comment="added 1248 characters in body" Text="I'm working on a simple software renderer and have a working implementation so far. I'm curious as to why it's actually working since I would expect the multiplication ordering for my world, view and projection matrices to be reversed. When working with DirectX and OpenGL in the past I have multiplied them as projection * view * world, but with my implementation it's working with worldMatrix * viewMatrix * projectionMatrix. Some code:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void SceneRenderer::DrawMesh(Mesh&amp; mesh, const SRGraphicsContext&amp; gfx)&#xD;&#xA;{&#xD;&#xA;	const Mat4x4f&amp; worldMatrix = mesh.GetWorldMatrix();&#xD;&#xA;	const Mat4x4f&amp; viewMatrix = camera-&gt;GetViewMatrix();&#xD;&#xA;	const Mat4x4f&amp; projectionMatrix = camera-&gt;GetProjectionMatrix();&#xD;&#xA;	const Mat4x4f&amp; wvp = worldMatrix * viewMatrix * projectionMatrix;&#xD;&#xA;&#xD;&#xA;	const Vert3df&amp; cameraPos = camera-&gt;GetPosition();&#xD;&#xA;&#xD;&#xA;	const float screenWidth = static_cast&lt;float&gt;(gfx.frameBuffer-&gt;GetWidth());&#xD;&#xA;	const float screenHeight = static_cast&lt;float&gt;(gfx.frameBuffer-&gt;GetHeight());&#xD;&#xA;&#xD;&#xA;	Tri2di rasterTri;&#xD;&#xA;	for (Tri3df&amp; tri : mesh.GetTriangles())&#xD;&#xA;	{&#xD;&#xA;		Vert4df p1c =  Vert4df(tri.p1, 1),&#xD;&#xA;				p2c = Vert4df(tri.p2, 1),&#xD;&#xA;				p3c = Vert4df(tri.p3, 1);&#xD;&#xA;&#xD;&#xA;		p1c = wvp * p1c;&#xD;&#xA;		p2c = wvp * p2c;&#xD;&#xA;		p3c = wvp * p3c;&#xD;&#xA;		&#xD;&#xA;		p1c.DivideByW();&#xD;&#xA;		p2c.DivideByW();&#xD;&#xA;		p3c.DivideByW();&#xD;&#xA;&#xD;&#xA;		rasterTri.p1.x = static_cast&lt;int&gt;((p1c.x + 1.0f) / 2.0f * screenWidth);&#xD;&#xA;		rasterTri.p1.y = static_cast&lt;int&gt;((p1c.y + 1.0f) / 2.0f * screenHeight);&#xD;&#xA;&#xD;&#xA;		rasterTri.p2.x = static_cast&lt;int&gt;((p2c.x + 1.0f) / 2.0f * screenWidth);&#xD;&#xA;		rasterTri.p2.y = static_cast&lt;int&gt;((p2c.y + 1.0f) / 2.0f * screenHeight);&#xD;&#xA;&#xD;&#xA;		rasterTri.p3.x = static_cast&lt;int&gt;((p3c.x + 1.0f) / 2.0f * screenWidth);&#xD;&#xA;		rasterTri.p3.y = static_cast&lt;int&gt;((p3c.y + 1.0f) / 2.0f * screenHeight);&#xD;&#xA;&#xD;&#xA;		rasterizer-&gt;DrawTriangle(rasterTri, gfx);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;void Camera::LookAt(const Vert3df&amp; at)&#xD;&#xA;{&#xD;&#xA;	lookAt = at;&#xD;&#xA;&#xD;&#xA;	auto zAxis = (lookAt - position).Normalize();&#xD;&#xA;	auto xAxis = up.Cross(zAxis).Normalize();&#xD;&#xA;	auto yAxis = zAxis.Cross(xAxis);&#xD;&#xA;&#xD;&#xA;	viewMatrix.Zero();&#xD;&#xA;	viewMatrix(0, 0) = xAxis.x;&#xD;&#xA;	viewMatrix(0, 1) = yAxis.x;&#xD;&#xA;	viewMatrix(0, 2) = zAxis.x;&#xD;&#xA;	viewMatrix(0, 3) = 0.0f;&#xD;&#xA;	viewMatrix(1, 0) = xAxis.y;&#xD;&#xA;	viewMatrix(1, 1) = yAxis.y;&#xD;&#xA;	viewMatrix(1, 2) = zAxis.y;&#xD;&#xA;	viewMatrix(1, 3) = 0.0f;&#xD;&#xA;	viewMatrix(2, 0) = xAxis.z;&#xD;&#xA;	viewMatrix(2, 1) = yAxis.z;&#xD;&#xA;	viewMatrix(2, 2) = zAxis.z;&#xD;&#xA;	viewMatrix(2, 3) = 0.0f;&#xD;&#xA;	viewMatrix(3, 0) = -xAxis.Dot(position);&#xD;&#xA;	viewMatrix(3, 1) = -yAxis.Dot(position);&#xD;&#xA;	viewMatrix(3, 2) = -zAxis.Dot(position);&#xD;&#xA;	viewMatrix(3, 3) = 1.0f;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Camera::UpdateProjectionMatrix()&#xD;&#xA;{&#xD;&#xA;	const float aspectRatio = screenWidth / (float)screenHeight;&#xD;&#xA;&#xD;&#xA;	float tanHalfFOV = std::tan(fov / 2.0f);&#xD;&#xA;	float zRange = nearPlane - farPlane;&#xD;&#xA;&#xD;&#xA;	projectionMatrix.Zero();&#xD;&#xA;	projectionMatrix(0, 0) = 1.0f / (tanHalfFOV * aspectRatio);&#xD;&#xA;	projectionMatrix(1, 1) = 1.0f / tanHalfFOV;&#xD;&#xA;	projectionMatrix(2, 2) = (-nearPlane - farPlane) / zRange;&#xD;&#xA;	projectionMatrix(2, 3) = 1; // Left handed, invert for right handed&#xD;&#xA;	projectionMatrix(3, 2) = (2 * nearPlane * farPlane) / zRange;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;Any idea why the ordering might be reversed in my case? I've compared my Mat4x4f implementation to DirectX's XMMAtrix and get the same results when multiplying 2 arbitrary matrices." ContentLicense="CC BY-SA 4.0" />
  <row Id="30698" PostHistoryTypeId="2" PostId="10549" RevisionGUID="3c2a4dc2-0313-43a9-830d-99f6863c73af" CreationDate="2021-01-08T02:34:06.770" UserId="48" Text="The primaries of sRGB are not pure wavelengths, they are color mixtures. Their true definition is in terms of CIE chromaticity coordinates. That said, for sRGB, the red primary is close-ish to 610nm, green is very roughly 555nm, and blue is close-ish to 465nm.&#xD;&#xA;&#xD;&#xA;The Rec. 2020 RGB space, by the way, is actually defined using pure wavelengths for the primaries: R=630nm, G=532nm, and B=467nm.&#xD;&#xA;&#xD;&#xA;[![Various RGB gamuts plotted in CIE chromaticity coordinates][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GaIIs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30699" PostHistoryTypeId="2" PostId="10550" RevisionGUID="4f0aa7e2-d0f8-4070-9f8e-1b44fa73feaf" CreationDate="2021-01-08T05:50:20.167" UserId="48" Text="I think you may be overcomplicating things with your idea of using the stencil. In 2D graphics layers, we usually do not need to use the depth buffer to resolve depth order between 2D elements (their depth order is determined by draw order instead). Therefore, we can reserve the nearest depth value for all the foreground elements, and the farthest depth value for all background elements.&#xD;&#xA;&#xD;&#xA;This would work as follows, assuming depth 0.0 is the far plane and depth 1.0 is the near plane.&#xD;&#xA;&#xD;&#xA;1. Render opaque foreground elements in front-to-back order, using depth test `VK_COMPARE_OP_GREATER`, and arranging in the vertex shader for all elements to be placed at depth 1.0.&#xD;&#xA;2. Render opaque scene objects roughly front-to-back.&#xD;&#xA;3. Render opaque background elements in front-to-back order, placing them at depth 0.0.&#xD;&#xA;4. Render transparent background elements back-to-front, now using depth test `VK_COMPARE_OP_GREATER_OR_EQUAL`, disabling depth writes, and placing them at depth 0.0.&#xD;&#xA;5. Render transparent scene objects back-to-front.&#xD;&#xA;6. Render transparent foreground elements back-to-front, placing them at depth 1.0.&#xD;&#xA;&#xD;&#xA;The switch from `GREATER` to `GREATER_OR_EQUAL` is important here. Since the opaque elements are going front-to-back, you want to exclude the &quot;equal&quot; case, since you want later elements to be occluded by earlier elements. Then, when coming back-to-front for the transparents, you want to include the &quot;equal&quot; so that later elements will correctly render on top of earlier ones in the foreground/background layers." ContentLicense="CC BY-SA 4.0" />
  <row Id="30700" PostHistoryTypeId="5" PostId="10550" RevisionGUID="1eb574e6-14b2-457c-8e71-88db4a54fdc2" CreationDate="2021-01-08T06:18:09.540" UserId="48" Comment="added 506 characters in body" Text="I think you may be overcomplicating things with your idea of using the stencil. In 2D graphics layers, we usually do not need to use the depth buffer to resolve depth order between 2D elements (their depth order is determined by draw order instead). Therefore, we can reserve the nearest depth value for all the foreground elements, and the farthest depth value for all background elements.&#xD;&#xA;&#xD;&#xA;This would work as follows, assuming depth 0.0 is the far plane and depth 1.0 is the near plane.&#xD;&#xA;&#xD;&#xA;1. Render opaque foreground elements in front-to-back order, using depth test `VK_COMPARE_OP_GREATER`, and arranging in the vertex shader for all elements to be placed at depth 1.0.&#xD;&#xA;2. Render opaque scene objects roughly front-to-back.&#xD;&#xA;3. Render opaque background elements in front-to-back order, placing them at depth 0.0.&#xD;&#xA;4. Render transparent background elements back-to-front, now using depth test `VK_COMPARE_OP_GREATER_OR_EQUAL`, disabling depth writes, and placing them at depth 0.0.&#xD;&#xA;5. Render transparent scene objects back-to-front.&#xD;&#xA;6. Render transparent foreground elements back-to-front, placing them at depth 1.0.&#xD;&#xA;&#xD;&#xA;The switch from `GREATER` to `GREATER_OR_EQUAL` is important here. Since the opaque elements are going front-to-back, you want to exclude the &quot;equal&quot; case, since you want later elements to be occluded by earlier elements. Then, when coming back-to-front for the transparents, you want to include the &quot;equal&quot; so that later elements will correctly render on top of earlier ones in the foreground/background layers.&#xD;&#xA;&#xD;&#xA;Edit: Now that I'm thinking about this more, this may not work since transparent elements in foreground/background won't be able to be occluded by opaque elements in the same layer. This could be addressed by pre-clipping the transparent element geometry, or if this is important to support on the GPU, it could be addressed by rendering opaque elements depth-only (no fragment shader) in the first passes and then rendering all elements, both opaque and transparent, back-to-front in the later passes." ContentLicense="CC BY-SA 4.0" />
  <row Id="30701" PostHistoryTypeId="2" PostId="10551" RevisionGUID="b1a23751-17df-4e8a-9156-114bd1c28dc5" CreationDate="2021-01-08T11:52:18.317" UserId="15415" Text="I want to know how do take derivative of beizier curve function I visited this website https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html but unable to figure out how do they did it please help !!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30702" PostHistoryTypeId="1" PostId="10551" RevisionGUID="b1a23751-17df-4e8a-9156-114bd1c28dc5" CreationDate="2021-01-08T11:52:18.317" UserId="15415" Text="How to take derivative of beizier curve function?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30703" PostHistoryTypeId="3" PostId="10551" RevisionGUID="b1a23751-17df-4e8a-9156-114bd1c28dc5" CreationDate="2021-01-08T11:52:18.317" UserId="15415" Text="|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30704" PostHistoryTypeId="2" PostId="10552" RevisionGUID="33b27029-07a7-48c8-b631-d13d7962401e" CreationDate="2021-01-08T19:11:34.137" UserId="7724" Text="A simple example of taking a the derivative of a B\'ezier curve can be shown using a cubic curve.&#xD;&#xA;&#xD;&#xA;$$C(u) = \sum_{i=0}^3 B_{3,i}(u) P_i$$&#xD;&#xA;&#xD;&#xA;written out it is:&#xD;&#xA;&#xD;&#xA;$$C(u) = (1-u)^3 P_0 + 3(1-u)^2 u P_1 + 3 (1-u)u^2 P_2 + u^3 P_3$$&#xD;&#xA;&#xD;&#xA;we can differentiate this with respect to u&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C(u) = -3(1-u)^2 P_0 - 6(1-u) u P_1 + 3(1-u)^2 P_1 - 3 u^2 P_2 + 6 (1-u)u P_2 + 3u^2 P_3. $$&#xD;&#xA;&#xD;&#xA;Now we can rearrange the terms&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C(u) =  3 \left((1-u)^2 (P_1-P_0) + 2(1-u) u (P_2 - P_1)  +  u^2 (P_3 - P_2) \right), $$ or&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C(u) = n (\sum_{i=0}^2 B_{2,i}(u) (P_{i+1} - P_i))$$ &#xD;&#xA;&#xD;&#xA;We obtain a quadratic B\'ezier curve where the control points are the vectors between the initial control points, scaled by a factor $3$. Therefore the derivative of a Bezier curve of degree $n$ is a B\'ezier curve of degree $n-1$, where the control points are difference between initial control points scaled by $n$.&#xD;&#xA;&#xD;&#xA;so:&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} \sum_{i=0}^n B_{n,i}(u) P_i = n (\sum_{i=0}^2 B_{n-1,i}(u) (P_{i+1} - P_i))$$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="30705" PostHistoryTypeId="50" PostId="10438" RevisionGUID="f864d8dc-aec6-4e39-87bf-e60059c30011" CreationDate="2021-01-08T21:07:30.797" UserId="-1" />
  <row Id="30706" PostHistoryTypeId="2" PostId="10553" RevisionGUID="13908034-212d-4050-abbd-8f58161d75d7" CreationDate="2021-01-08T21:47:41.513" UserId="15556" Text="My first question in this community.&#xD;&#xA;&#xD;&#xA; I have following code.The code is shortened for clarity, error checks skipped:&#xD;&#xA;&#xD;&#xA;    int creat_ssbo_buf(uint32_t *ssbo, size_t size, size_t unit_size){&#xD;&#xA;      glGenBuffers(1, ssbo);&#xD;&#xA;      glBindBuffer(GL_SHADER_STORAGE_BUFFER, *ssbo);&#xD;&#xA;      glBufferData(GL_SHADER_STORAGE_BUFFER, &#xD;&#xA;                   size * unit_size, &#xD;&#xA;                   NULL, &#xD;&#xA;                   GL_DYNAMIC_READ);&#xD;&#xA;      glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *ssbo);&#xD;&#xA;      glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);&#xD;&#xA;      return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int read_ssbo(uint32_t  ssbo,&#xD;&#xA;                  void     *pbuf,&#xD;&#xA;                  size_t    size,&#xD;&#xA;                  intptr_t  off)&#xD;&#xA;    {&#xD;&#xA;     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);&#xD;&#xA;     glGetBufferSubData(GL_SHADER_STORAGE_BUFFER,&#xD;&#xA;                        off, &#xD;&#xA;                        size, &#xD;&#xA;                        pbuf);&#xD;&#xA;     glBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 );&#xD;&#xA;     return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int compute(...){ /* runs the GLSL code */&#xD;&#xA;     ...&#xD;&#xA;     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);&#xD;&#xA;     return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main(){&#xD;&#xA;     ...&#xD;&#xA;     size_t buf_size = w * h;     &#xD;&#xA;     uint32_t *pbuf = /* some raster image with the size of above */;&#xD;&#xA;     uint32_t  ssbo;&#xD;&#xA;&#xD;&#xA;     creat_ssbo_buf(&amp;ssbo, buf_size, sizeof(uint32_t));&#xD;&#xA;     compute(...);&#xD;&#xA;     read_ssbo(ssbo, pbuf, buf_size, 0);&#xD;&#xA;     &#xD;&#xA;     printf(&quot; 0 : %u\n&quot;, pbuf[0]);&#xD;&#xA;     printf(&quot; 1 : %u\n&quot;, pbuf[1]);&#xD;&#xA;     printf(&quot; 2 : %u\n&quot;, pbuf[2]);&#xD;&#xA;     printf(&quot; 3 : %u\n&quot;, pbuf[3]);&#xD;&#xA;     printf(&quot; 4 : %u\n&quot;, pbuf[4]);&#xD;&#xA;&#xD;&#xA;     return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;With the GLSL code as below.&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 0) writeonly buffer layout0&#xD;&#xA;    {&#xD;&#xA;     uint data[];&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    void main(){&#xD;&#xA;     uvec2 pos  = uvec2(gl_GlobalInvocationID.xy);&#xD;&#xA;    &#xD;&#xA;     if(pos == uvec2(0,0)){&#xD;&#xA;      data[0] = pos.x;&#xD;&#xA;      data[1] = pos.y;&#xD;&#xA;      data[2] = 1;&#xD;&#xA;      data[3] = 1;&#xD;&#xA;      data[4] = 1;&#xD;&#xA;     }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Now that outputs `0,0,1,1,1` as expected. What I want is to read from buffer with some offset. Below is a `C` and `GLSL` code with changes:&#xD;&#xA;&#xD;&#xA;    /* GLSL */&#xD;&#xA;    layout(std430, binding = 0) writeonly buffer layout0&#xD;&#xA;    {&#xD;&#xA;     uint pad[1]; /* add some padding */&#xD;&#xA;     uint data[];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    /* C */&#xD;&#xA;    ...&#xD;&#xA;    size_t buf_size = w * h + 1;&#xD;&#xA;    ...&#xD;&#xA;    read_ssbo(ssbo, pbuf, buf_size, sizeof(uint32_t)); /* note the offset */&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA; And with the offset added, I get an error: `invalid value`. The error fires up after `glGetBufferSubData` call. What am I doing wrong here?&#xD;&#xA;&#xD;&#xA;P.S Also, if offset is left as `zero` and the indices of `pbuf` in the `printf`'s are changed to one index greater, the output is correct.&#xD;&#xA;&#xD;&#xA;Ask away what code I should add to make things clearer." ContentLicense="CC BY-SA 4.0" />
  <row Id="30707" PostHistoryTypeId="1" PostId="10553" RevisionGUID="13908034-212d-4050-abbd-8f58161d75d7" CreationDate="2021-01-08T21:47:41.513" UserId="15556" Text="OpenGL: &quot;invalid value&quot; error after call to `glGetBufferSubData`" ContentLicense="CC BY-SA 4.0" />
  <row Id="30708" PostHistoryTypeId="3" PostId="10553" RevisionGUID="13908034-212d-4050-abbd-8f58161d75d7" CreationDate="2021-01-08T21:47:41.513" UserId="15556" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30709" PostHistoryTypeId="5" PostId="10548" RevisionGUID="09e84499-1a35-4b5a-8951-faf7cbe5b486" CreationDate="2021-01-08T22:16:00.737" UserId="9894" Comment="Explained SPD abbreviation as it may not be immediately clear." Text="Trichromatic color system is based on using 3 carefully selected reference spectral power distributions(SPD) as you imagine. CIE uses its own reference SPDs, but there are others who prefer using other SPDs as reference. So the answer to the question&#xD;&#xA;&#xD;&#xA;&gt; Are the actual wavelengths of sRGB RGB primaries defined and if so what are they in nanometers?&#xD;&#xA;&#xD;&#xA;differs, or might differ, with respect to institutions. As for trustworthy resources:&#xD;&#xA;&#xD;&#xA;Scott Burns had kindly provided some reference SPDs in his [website](http://scottburns.us/fast-rgb-to-spectrum-conversion-for-reflectances/).&#xD;&#xA;&#xD;&#xA;For illuminants and observers etc. you can check the [website](https://www.rit.edu/cos/colorscience/rc_useful_data.php) of Munsell Color Science Lab." ContentLicense="CC BY-SA 4.0" />
  <row Id="30710" PostHistoryTypeId="24" PostId="10548" RevisionGUID="09e84499-1a35-4b5a-8951-faf7cbe5b486" CreationDate="2021-01-08T22:16:00.737" Comment="Proposed by 9894 approved by 13095 edit id of 552" ContentLicense="CC BY-SA 4.0" />
  <row Id="30712" PostHistoryTypeId="2" PostId="10554" RevisionGUID="84a27d1d-7d99-4616-8f82-9537ccd1a401" CreationDate="2021-01-09T06:38:49.983" UserId="13456" Text="This would be a response to why is it possible to use the Fresnel equations in an RGB path tracer. Though evaluating Fresnel equation directly requires some what more information about the environment in which the rendering takes place, it certainly is possible to use it in an RGB path tracer. Here is why:&#xD;&#xA;&#xD;&#xA;TLDR: see last two paragraphs.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The goal of Fresnel equations is to describe the relationship between the incident, reflected and transmitted planar light waves. In its most general form, it can describe this relationship even at the boundary of an interface (think of them as the zone of contact between one object and air or water).&#xD;&#xA;&#xD;&#xA;Notice that we are considering lightwaves as plane waves which is an approximation.&#xD;&#xA;Now let's define the incident light as the uniform plane sinusoidal electromagnetic wave whose electric field is defined as &#xD;&#xA;$ \vec{E_i} = \vec{E_{0i}} e^{i(\vec{k} \cdot \vec{r} - \omega_i t)} $ since $e^{i\theta} = \cos(\theta) + i\sin(\theta)$ and since we are dealing with measurable quantities we can let go of the complex part and simply write the incident light as $ \vec{E_i} = \vec{E_{0i}} \cos(\vec{k} \cdot \vec{r} - \omega_i t)$. $\vec{E_i}$ is an electric field. Mathematically it is a vector field. Notice that once we get rid of the imaginary part the whole equation is just a cosine wave now with $\vec{E_{0i}}$ as the amplitude. $\vec{k} \cdot \vec{r}$ is the phase and $\omega_i t$ is the frequency. For surfaces with constant phase the $\vec{k} \cdot \vec{r}$ would be constant where $\vec{r}$ would designate the point/position in space and $\vec{k}$ the direction of the propagation of the wave.&#xD;&#xA;&#xD;&#xA;We are interested in the relationship between $\vec{E_i}$, $\vec{E_t}$ and $\vec{E_r}$. With no knowledge about direction, frequency, phase, etc we can describe the reflected wave as $\vec{E_r} = \vec{E_0r} \cos(\vec{k_r} \cdot \vec{r} - \omega_r t + \epsilon_r)$ where $\epsilon_r$ is the phase constant with respect to $\vec{E_i}$. The transimited wave is defined the same way with $\vec{k_t}$, $\omega_t$, $\epsilon_t$ and $E_{0t}$. The $\epsilon$ is introduced because we have not specified the origin of the $\vec{E_i}$.&#xD;&#xA;&#xD;&#xA;Well, after a lot of math which you can read from pages 122 - 124, we learn that they, $\epsilon$s, don't really matter and we can consider them as 0 throughout the discussion and that frequencies, $\omega$ of all three of them are equal (unless there is a doppler effect) and that phases of all three of them are related.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The relationship that is described by Fresnel equations is the amplitude of waves.&#xD;&#xA;Here are the full Fresnel equations from E. Hecht 2017, Optics, p. 124-125:&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0r}}{E_{0i}})_{\perp} = \frac{\frac{n_i}{\mu_i}\cos(\theta_i) - \frac{n_t}{\mu_t}\cos(\theta_t)}{\frac{n_i}{\mu_i}\cos(\theta_i) + \frac{n_t}{\mu_t}\cos(\theta_t)}$$&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0t}}{E_{0i}})_{\perp} = \frac{2\frac{n_i}{\mu_i}\cos(\theta_i)}{\frac{n_i}{\mu_i}\cos(\theta_i) + \frac{n_t}{\mu_t}\cos(\theta_t)}$$&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0r}}{E_{0i}})_{||} =\frac{\frac{n_t}{\mu_t}\cos(\theta_i) - \frac{n_i}{\mu_i}\cos(\theta_t)}{\frac{n_i}{\mu_i}\cos(\theta_t) + \frac{n_t}{\mu_t}\cos(\theta_i)}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0t}}{E_{0i}})_{||} = \frac{2\frac{n_i}{\mu_i}\cos(\theta_i)}{\frac{n_i}{\mu_i}\cos(\theta_t) + \frac{n_t}{\mu_t}\cos(\theta_i)}$$&#xD;&#xA;&#xD;&#xA;These are completely general statements, that is it applies to linear, isotropic, homogenous, even magnetic media. Using certain assumptions you can eliminate some of the terms. For example if you consider $\mu_t \approx \mu_i$ you can simply simply ignore them which would give you the common form of the equations, for example those that are used by PBRT.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Here are the terms of the equation:&#xD;&#xA;&#xD;&#xA;- $\mu$ is the permeability: $\mu_i$ accounts for the magnetic effect of the incident media, $\mu_t$ accounts for the transmitted media&#xD;&#xA;- $n$ is the index of refraction: $n_i$ for incident media, $n_t$ for transmitted media. It is related to k in discussion above.&#xD;&#xA;- $\theta$ the angle is defined under the following constraints: &#xD;&#xA;  - $\vec{E_i}$ is perpendicular to the plane of incidence. &#xD;&#xA;  - $\vec{B_i}$, magnetic field, is parallel to the plane of incidence.&#xD;&#xA;  - With these constraints it can be proven that $k$s of all planes are coplanar, that is they are all defined on the plane of incidence which is perpendicular to the surface, and that $\theta$ is angle between the normal of the surface and the coplanar direction vectors.&#xD;&#xA;[![Relationship between plane of incidence and other fields][1]][1](image from, Hecht, Eugene. 2017. Optics. 5 ed/fifth edition, Global edition. Pearson Global Edition. Boston Columbus Indianapolis: Pearson, p. 123)&#xD;&#xA;&#xD;&#xA;Now all of the terms and their are related concepts are given, yet we have not defined anywhere a term that relates directly to wavelength. Notice that we CAN include the wavelength to the frequency term of the cosine wave but we chose to define it in another way. That is why we can side step the whole spectral distributions machinary and still have visually plausable results.&#xD;&#xA;&#xD;&#xA;Here are some approximations that can be done.&#xD;&#xA;You can approximate the $k$ and $r$ with incoming ray's direction and origin, the plane of incidence with collided surface normal, keep the phase constant for all fields. For the majority of surfaces, the approximation $\mu_i \approx \mu_t$ holds as well. For other case they need to be looked up. IOR is also a material property so one has to look that up as well. If they are defined in a wavelength dependent manner, you can make an average and use that as an approximation as well.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3B455.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30713" PostHistoryTypeId="5" PostId="10545" RevisionGUID="34098e47-0d68-43db-a4c1-ebae8c811ee1" CreationDate="2021-01-09T06:43:01.463" UserId="13456" Comment="standard illuminant to standard observer" Text="I vaguely understand your question, so this response should be taken more of a long comment rather than an answer.&#xD;&#xA;&#xD;&#xA;&gt; If I have an output device, for which I have a known spectrum data for each of it's primaries, I should be able to calculate the CIEXYZ of its primaries using using the integral equations together with the CIE color matching functions. I can then calculate its respective CIExyY values, which for output device are always inside the boundary if the xyY spectral locus - the chromaticity diagram.&#xD;&#xA;&#xD;&#xA;This is correct in general but note that reference CIE spectral power distribtions are defined for a standard observer. &#xD;&#xA;&#xD;&#xA;The term input primaries is a little vague, are you refering to the spd of the light source inside the input device or the combined result produced by the object's spectral reflectance factor (also an spd) multiplied by the spd of the light source of the input device ?&#xD;&#xA;If you know the spectral reflectance factor of the object and the color matching function and the resulting trichromatic value, you should be able to express the spd of the light source as a vector equation something like:&#xD;&#xA;$x_1 \begin{matrix}a_1 \\ a_2 \\ \vdots \\ a_{\lambda}\end{matrix}+x_2 \begin{matrix}a_1 \\ a_2 \\ \vdots \\ a_{\lambda}\end{matrix}+...+x_{\lambda} \begin{matrix}a_1 \\ a_2 \\ \vdots \\ a_{\lambda}\end{matrix} = \begin{matrix}b_1 \\ b_2 \\ \vdots \\ b_{\lambda}\end{matrix}$ where $x$ is from your light source spd and the others are obtained from the remaining (you can for example distribute trichromatic value uniformly to $b$ vector, and fill $a$'s with zeros for non corresponding wave lengths and use the multiplied value for the corresponding wave length), but this is more or less an educated guess rather than a tested solution. &#xD;&#xA;Notice that the expression is a linear system which might help you finding a solution." ContentLicense="CC BY-SA 4.0" />
  <row Id="30714" PostHistoryTypeId="5" PostId="10554" RevisionGUID="79c9f36e-54d6-446c-9f04-51b63d51257e" CreationDate="2021-01-09T09:56:52.173" UserId="13456" Comment="keep the frequency constant, phase is already k dot r" Text="This would be a response to why is it possible to use the Fresnel equations in an RGB path tracer. Though evaluating Fresnel equation directly requires some what more information about the environment in which the rendering takes place, it certainly is possible to use it in an RGB path tracer. Here is why:&#xD;&#xA;&#xD;&#xA;TLDR: see last two paragraphs.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The goal of Fresnel equations is to describe the relationship between the incident, reflected and transmitted planar light waves. In its most general form, it can describe this relationship even at the boundary of an interface (think of them as the zone of contact between one object and air or water).&#xD;&#xA;&#xD;&#xA;Notice that we are considering lightwaves as plane waves which is an approximation.&#xD;&#xA;Now let's define the incident light as the uniform plane sinusoidal electromagnetic wave whose electric field is defined as &#xD;&#xA;$ \vec{E_i} = \vec{E_{0i}} e^{i(\vec{k} \cdot \vec{r} - \omega_i t)} $ since $e^{i\theta} = \cos(\theta) + i\sin(\theta)$ and since we are dealing with measurable quantities we can let go of the complex part and simply write the incident light as $ \vec{E_i} = \vec{E_{0i}} \cos(\vec{k} \cdot \vec{r} - \omega_i t)$. $\vec{E_i}$ is an electric field. Mathematically it is a vector field. Notice that once we get rid of the imaginary part the whole equation is just a cosine wave now with $\vec{E_{0i}}$ as the amplitude. $\vec{k} \cdot \vec{r}$ is the phase and $\omega_i t$ is the frequency. For surfaces with constant phase the $\vec{k} \cdot \vec{r}$ would be constant where $\vec{r}$ would designate the point/position in space and $\vec{k}$ the direction of the propagation of the wave.&#xD;&#xA;&#xD;&#xA;We are interested in the relationship between $\vec{E_i}$, $\vec{E_t}$ and $\vec{E_r}$. With no knowledge about direction, frequency, phase, etc we can describe the reflected wave as $\vec{E_r} = \vec{E_0r} \cos(\vec{k_r} \cdot \vec{r} - \omega_r t + \epsilon_r)$ where $\epsilon_r$ is the phase constant with respect to $\vec{E_i}$. The transimited wave is defined the same way with $\vec{k_t}$, $\omega_t$, $\epsilon_t$ and $E_{0t}$. The $\epsilon$ is introduced because we have not specified the origin of the $\vec{E_i}$.&#xD;&#xA;&#xD;&#xA;Well, after a lot of math which you can read from pages 122 - 124, we learn that they, $\epsilon$s, don't really matter and we can consider them as 0 throughout the discussion and that frequencies, $\omega$ of all three of them are equal (unless there is a doppler effect) and that phases of all three of them are related.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The relationship that is described by Fresnel equations is the amplitude of waves.&#xD;&#xA;Here are the full Fresnel equations from E. Hecht 2017, Optics, p. 124-125:&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0r}}{E_{0i}})_{\perp} = \frac{\frac{n_i}{\mu_i}\cos(\theta_i) - \frac{n_t}{\mu_t}\cos(\theta_t)}{\frac{n_i}{\mu_i}\cos(\theta_i) + \frac{n_t}{\mu_t}\cos(\theta_t)}$$&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0t}}{E_{0i}})_{\perp} = \frac{2\frac{n_i}{\mu_i}\cos(\theta_i)}{\frac{n_i}{\mu_i}\cos(\theta_i) + \frac{n_t}{\mu_t}\cos(\theta_t)}$$&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0r}}{E_{0i}})_{||} =\frac{\frac{n_t}{\mu_t}\cos(\theta_i) - \frac{n_i}{\mu_i}\cos(\theta_t)}{\frac{n_i}{\mu_i}\cos(\theta_t) + \frac{n_t}{\mu_t}\cos(\theta_i)}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0t}}{E_{0i}})_{||} = \frac{2\frac{n_i}{\mu_i}\cos(\theta_i)}{\frac{n_i}{\mu_i}\cos(\theta_t) + \frac{n_t}{\mu_t}\cos(\theta_i)}$$&#xD;&#xA;&#xD;&#xA;These are completely general statements, that is it applies to linear, isotropic, homogenous, even magnetic media. Using certain assumptions you can eliminate some of the terms. For example if you consider $\mu_t \approx \mu_i$ you can simply simply ignore them which would give you the common form of the equations, for example those that are used by PBRT.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Here are the terms of the equation:&#xD;&#xA;&#xD;&#xA;- $\mu$ is the permeability: $\mu_i$ accounts for the magnetic effect of the incident media, $\mu_t$ accounts for the transmitted media&#xD;&#xA;- $n$ is the index of refraction: $n_i$ for incident media, $n_t$ for transmitted media. It is related to k in discussion above.&#xD;&#xA;- $\theta$ the angle is defined under the following constraints: &#xD;&#xA;  - $\vec{E_i}$ is perpendicular to the plane of incidence. &#xD;&#xA;  - $\vec{B_i}$, magnetic field, is parallel to the plane of incidence.&#xD;&#xA;  - With these constraints it can be proven that $k$s of all planes are coplanar, that is they are all defined on the plane of incidence which is perpendicular to the surface, and that $\theta$ is angle between the normal of the surface and the coplanar direction vectors.&#xD;&#xA;[![Relationship between plane of incidence and other fields][1]][1](image from, Hecht, Eugene. 2017. Optics. 5 ed/fifth edition, Global edition. Pearson Global Edition. Boston Columbus Indianapolis: Pearson, p. 123)&#xD;&#xA;&#xD;&#xA;Now all of the terms and their are related concepts are given, yet we have not defined anywhere a term that relates directly to wavelength. Notice that we CAN include the wavelength to the frequency term of the cosine wave but we chose to define it in another way. That is why we can side step the whole spectral distributions machinary and still have visually plausable results.&#xD;&#xA;&#xD;&#xA;Here are some approximations that can be done.&#xD;&#xA;You can approximate the $k$ and $r$ with incoming ray's direction and origin, the plane of incidence with collided surface normal, keep the frequency constant for all fields. For the majority of surfaces, the approximation $\mu_i \approx \mu_t$ holds as well. For other case they need to be looked up. IOR is also a material property so one has to look that up as well. If they are defined in a wavelength dependent manner, you can make an average and use that as an approximation as well.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3B455.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30715" PostHistoryTypeId="2" PostId="10555" RevisionGUID="a9de4628-6aa6-428c-8454-5d3092da4bd1" CreationDate="2021-01-09T10:14:39.737" UserId="13456" Text="I am suprised that it was only mentioned in comments but yes you can use variable length arrays through SSBO.&#xD;&#xA;Here is the excerpt from [wiki](https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object):&#xD;&#xA;&#xD;&#xA;On the host side:&#xD;&#xA;```cpp&#xD;&#xA;int data[SOME_SIZE];&#xD;&#xA;...&#xD;&#xA;GLuint ssbo;&#xD;&#xA;glGenBuffers(1, &amp;ssbo);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);&#xD;&#xA;glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data​, GLenum usage); //sizeof(data) only works for statically sized C/C++ arrays.&#xD;&#xA;glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); // unbind&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;On the glsl side:&#xD;&#xA;```c&#xD;&#xA;layout(std430, binding = 3) buffer layoutName&#xD;&#xA;{&#xD;&#xA;    int data_SSBO[];&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;Note that it has to be the last element in an SSBO:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;layout(std430, binding = 2) buffer anotherLayoutName&#xD;&#xA;{&#xD;&#xA;    int some_int;&#xD;&#xA;    float fixed_array[42];&#xD;&#xA;    float variable_array[];&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If you would like to upload vec3 arrays for example you should use 3 SSBO's where each of them contains dynamic array for a vector component." ContentLicense="CC BY-SA 4.0" />
  <row Id="30716" PostHistoryTypeId="5" PostId="10555" RevisionGUID="eaa2030b-ce69-4231-813a-2ff6a09523d6" CreationDate="2021-01-10T10:10:55.820" UserId="13456" Comment="removed last statement as per requested" Text="I am suprised that it was only mentioned in comments but yes you can use variable length arrays through SSBO.&#xD;&#xA;Here is the excerpt from [wiki](https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object):&#xD;&#xA;&#xD;&#xA;On the host side:&#xD;&#xA;```cpp&#xD;&#xA;int data[SOME_SIZE];&#xD;&#xA;...&#xD;&#xA;GLuint ssbo;&#xD;&#xA;glGenBuffers(1, &amp;ssbo);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);&#xD;&#xA;glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data​, GLenum usage); //sizeof(data) only works for statically sized C/C++ arrays.&#xD;&#xA;glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); // unbind&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;On the glsl side:&#xD;&#xA;```c&#xD;&#xA;layout(std430, binding = 3) buffer layoutName&#xD;&#xA;{&#xD;&#xA;    int data_SSBO[];&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;Note that it has to be the last element in an SSBO:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;layout(std430, binding = 2) buffer anotherLayoutName&#xD;&#xA;{&#xD;&#xA;    int some_int;&#xD;&#xA;    float fixed_array[42];&#xD;&#xA;    float variable_array[];&#xD;&#xA;};&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="30717" PostHistoryTypeId="5" PostId="10555" RevisionGUID="9fdb0d0d-a3f1-40fd-9e18-d15c4fdde473" CreationDate="2021-01-10T13:05:58.397" UserId="13456" Comment="Limitation of SSBO" Text="I am suprised that it was only mentioned in comments but yes you can use variable length arrays through SSBO.&#xD;&#xA;Here is the excerpt from [wiki](https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object):&#xD;&#xA;&#xD;&#xA;On the host side:&#xD;&#xA;```cpp&#xD;&#xA;int data[SOME_SIZE];&#xD;&#xA;...&#xD;&#xA;GLuint ssbo;&#xD;&#xA;glGenBuffers(1, &amp;ssbo);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);&#xD;&#xA;glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data​, GLenum usage); //sizeof(data) only works for statically sized C/C++ arrays.&#xD;&#xA;glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); // unbind&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;On the glsl side:&#xD;&#xA;```c&#xD;&#xA;layout(std430, binding = 3) buffer layoutName&#xD;&#xA;{&#xD;&#xA;    int data_SSBO[];&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;Note that it has to be the last element in an SSBO:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;layout(std430, binding = 2) buffer anotherLayoutName&#xD;&#xA;{&#xD;&#xA;    int some_int;&#xD;&#xA;    float fixed_array[42];&#xD;&#xA;    float variable_array[];&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;The only limitation is that you can use one variable array per SSBO. You can use multiple SSBO's in a shader though." ContentLicense="CC BY-SA 4.0" />
  <row Id="30723" PostHistoryTypeId="2" PostId="10557" RevisionGUID="81ff2936-34ab-4e74-8e76-3e5464672715" CreationDate="2021-01-10T19:16:54.517" UserId="6172" Text="I have made a demo that shades a sphere with an environment map. I wanted to compare 3 different ways of sampling the environment.&#xD;&#xA;&#xD;&#xA; 1. Uniform sampling.&#xD;&#xA; 2. Importance sampling with the NDF as suggested in this article: [Real Shading in Unreal Engine 4 (2013)][1]&#xD;&#xA; 3. Importance sampling with the VNDF (distribution of visible normals) as explained in this article: [Sampling the GGX Distribution of Visible Normals (2018)][2]&#xD;&#xA;&#xD;&#xA;The program I wrote allows me to compare all those the sampling methods.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;All sampling methods seem to work and look okay to me. But they look different to each other, so I was hoping someone can help me figure out why (could be that I made some mistake or it's just how it works).&#xD;&#xA;&#xD;&#xA;First I'm going to show a comparison of how they look. After that, I will explain how I implemented each of them. Also, I have made a small [project][4] so you try it yourselves.&#xD;&#xA;&#xD;&#xA;The program is implemented as an iterative path-tracer, so it takes about 20 seconds for it to start to look great (specially for uniform sampling).&#xD;&#xA;&#xD;&#xA;With low roughness, it's alright, they all look the same. In the following image it's using roughness = 0.1. On the left, uniform sampling. On the right, NDF importance sampling.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Things start to look different with higher roughness.&#xD;&#xA;&#xD;&#xA;Roughness = 0.35&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Roughness = 0.6&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;The one that differs the most is the one that samples according to the NDF (Unreal article). It looks brighter at the center and darker on the borders.&#xD;&#xA;&#xD;&#xA;Uniform sampling vs importance sampling the VNDF look more similar, but still not the same. This comparison really bothers me because, in the article, they claim that the sampling method should be exact. In order to better appreciate the difference we can flip the images.&#xD;&#xA;&#xD;&#xA;[![flip][8]][8]&#xD;&#xA;&#xD;&#xA;**Implementation**&#xD;&#xA;&#xD;&#xA;You can find all the code in [this repo][4]. I put all the relevant code in the [main.cpp][9].&#xD;&#xA;&#xD;&#xA;Now I'm going to explain how I implemented each method. The code is written in GLSL.&#xD;&#xA;&#xD;&#xA;**Uniform sampling**&#xD;&#xA;&#xD;&#xA;For generating uniform samples I have the following function. It takes a couple of pseudo-random numbers between 0 and 1 (seed), and the normal of the surface ($\vec{N}$). The samples that it generates are inside the hemisphere in the direction of $\vec N$.&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;vec3 uniformSample(vec2 seed, vec3 N)&#xD;&#xA;{&#xD;&#xA;    float phi = 2 * PI * seed.x;&#xD;&#xA;    float r = sqrt(1 - seed.y*seed.y);&#xD;&#xA;    vec3 v = vec3(r*cos(phi), seed.y, r*sin(phi));&#xD;&#xA;    v = normalize(v);&#xD;&#xA;    vec3 up = vec3(0, 1, 0);&#xD;&#xA;    if(dot(up, N) &gt; 0.99)&#xD;&#xA;        up = vec3(1, 0, 0);&#xD;&#xA;    vec3 X = normalize(cross(N, up));&#xD;&#xA;    vec3 Z = cross(X, N);&#xD;&#xA;    return X * v.x + N * v.y + Z * v.z;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And this is how I integrate all those uniform samples applying the Cook-Torrance formula. I'm reusing the same samples for computing the diffuse term. In this case the PDF is just the constant value $\frac{1}{2 \pi}$. So we just multiply by $2\pi$.&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;vec3 diffuse = vec3(0, 0, 0);&#xD;&#xA;// uniform sampling&#xD;&#xA;{&#xD;&#xA;    vec3 specular = vec3(0.0, 0.0, 0.0);&#xD;&#xA;    for(uint iSample = 0u; iSample &lt; u_numSamples; iSample++)&#xD;&#xA;    {&#xD;&#xA;        uint sampleId = iSample + u_numSamples * u_numFramesWithoutChanging;&#xD;&#xA;        uvec3 seedUInt = pcg_uvec3_uvec3(uvec3(gl_FragCoord.x, gl_FragCoord.y, sampleId));&#xD;&#xA;        vec2 seed2 = vec2(makeFloat01(seedUInt.x), makeFloat01(seedUInt.y));&#xD;&#xA;        vec3 L = uniformSample(seed2, N);&#xD;&#xA;        vec3 H = normalize(V + L);&#xD;&#xA;        vec3 env = textureLod(u_convolutedEnv, L, 0.0).rgb;&#xD;&#xA;&#xD;&#xA;        float NoL = max(0.0001, dot(N, L));&#xD;&#xA;        float NoH = max(0.0001, dot(N, H));&#xD;&#xA;        float NoH2 = NoH * NoH;&#xD;&#xA;        float rough4 = u_rough2*u_rough2;&#xD;&#xA;        float q = NoH2 * (rough4 - 1.0) + 1.0;&#xD;&#xA;        float D = rough4 / (PI * q*q);&#xD;&#xA;        float G = ggx_G_smith(NoV, NoL, u_rough2);&#xD;&#xA;        vec3 fr = F * G * D / (4 * NoV * NoL);&#xD;&#xA;        diffuse += env * NoL;&#xD;&#xA;        specular += env * fr * NoL;&#xD;&#xA;    }&#xD;&#xA;    diffuse *= 2 * k_diff * u_albedo / float(u_numSamples);&#xD;&#xA;    specular *= 2 * PI / float(u_numSamples);&#xD;&#xA;    o_uniform = vec4(diffuse + specular, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Importance sampling the NDF**&#xD;&#xA;&#xD;&#xA;In this case I've just copied the code in the article (Unreal 2013) and adapted it to the OpenGL coordinate system. Unlike in the previous implementation, the sampling function doesn't output the sampling direction but the half vector. We will have to compute the sampling direction $\vec{L}$ by reflecting the view direction $\vec V$.&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;vec3 importanceSampleGgxD(vec2 seed, float rough2, vec3 N)&#xD;&#xA;{&#xD;&#xA;    float phi = 2.0 * PI * seed.x;&#xD;&#xA;    float cosTheta = sqrt((1.0 - seed.y) / (1 + (rough2*rough2 - 1) * seed.y));&#xD;&#xA;    float sinTheta = sqrt(1.0 - cosTheta*cosTheta);&#xD;&#xA;    vec3 h;&#xD;&#xA;    h.x = sinTheta * cos(phi);&#xD;&#xA;    h.y = cosTheta;&#xD;&#xA;    h.z = sinTheta * sin(phi);&#xD;&#xA;    vec3 up = abs(N.y) &lt; 0.999 ? vec3(0, 1, 0) : vec3(1, 0, 0);&#xD;&#xA;    vec3 tangentX = normalize(cross(up, N));&#xD;&#xA;    vec3 tangentZ = cross(tangentX, N);&#xD;&#xA;    return h.x * tangentX + h.y * N + h.z * tangentZ;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;For the integration, since we are using importance sampling, we use a different normalization factor according to the new PDF $ \frac{D (\vec N \cdot \vec H)} {4 (\vec V \cdot \vec H)}$.&#xD;&#xA; &#xD;&#xA;```glsl&#xD;&#xA;// importance sampling NDF&#xD;&#xA;{&#xD;&#xA;    vec3 specular = vec3(0.0, 0.0, 0.0);&#xD;&#xA;    for(uint iSample = 0u; iSample &lt; u_numSamples; iSample++)&#xD;&#xA;    {&#xD;&#xA;        uint sampleId = iSample + u_numSamples * u_numFramesWithoutChanging;&#xD;&#xA;        uvec3 seedUInt = pcg_uvec3_uvec3(uvec3(gl_FragCoord.x, gl_FragCoord.y, sampleId));&#xD;&#xA;        seedUInt.xy += seedUInt.x;&#xD;&#xA;        vec2 seed2 = vec2(makeFloat01(seedUInt.x), makeFloat01(seedUInt.y));&#xD;&#xA;        vec3 H = importanceSampleGgxD(seed2, u_rough2, N);&#xD;&#xA;        vec3 L = reflect(-V, H);&#xD;&#xA;        if(dot(N, L) &gt; 0) {&#xD;&#xA;            vec3 env = textureLod(u_convolutedEnv, L, 0.0).rgb;&#xD;&#xA;            float NoL = max(0.0001, dot(N, L));&#xD;&#xA;            float NoH = max(0.0001, dot(N, H));&#xD;&#xA;            float G = ggx_G_smith(NoV, NoL, u_rough2);&#xD;&#xA;            specular += env * F*G* dot(L, H) / (NoL * NoH);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    specular /= float(u_numSamples);&#xD;&#xA;    o_importanceNDF = vec4(diffuse + specular, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Importance sampling the VNDF**&#xD;&#xA;&#xD;&#xA;This one attempts to sample considering the visibility of micro-normals, that means the geometry term $G$ of the Cook-Torrance equation is also cosidered. In the article, the code they provide assumes that the surface normal is aligned with the vertical axis (Z in the paper, and Y in my code). So I had to rotate the vectors accordingly.&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;vec3 importanceSampleGgxVD(vec2 seed, float rough2, vec3 N, vec3 V)&#xD;&#xA;{&#xD;&#xA;    mat3 orthoBasis; // build an ortho normal basis with N as the up direction&#xD;&#xA;    orthoBasis[1] = N;&#xD;&#xA;    orthoBasis[0] = abs(dot(N, vec3(0, 0, 1))) &lt; 0.001 ?&#xD;&#xA;                        cross(N, vec3(1, 0, 0)) :&#xD;&#xA;                        cross(N, vec3(0, 0, 1));&#xD;&#xA;    orthoBasis[0] = normalize(orthoBasis[0]);&#xD;&#xA;    orthoBasis[2] = cross(orthoBasis[0], N);&#xD;&#xA;&#xD;&#xA;    mat3 invOrthoBasis = transpose(orthoBasis);&#xD;&#xA;    V = invOrthoBasis * V;&#xD;&#xA;&#xD;&#xA;    // stretch view&#xD;&#xA;    V = normalize(vec3(rough2*V.x, V.y, rough2*V.z));&#xD;&#xA;    // orthonormal basis&#xD;&#xA;    vec3 T1 = (V.y &lt; 0.999) ? normalize(cross(V, vec3(0,0,1))) : vec3(1,0,0);&#xD;&#xA;    vec3 T2 = cross(T1, V);&#xD;&#xA;    // sample point with polar coordinates (r, phi)&#xD;&#xA;    float a = 1.0 / (1.0 + V.y);&#xD;&#xA;    float r = sqrt(seed.x);&#xD;&#xA;    float phi = (seed.y&lt;a) ? seed.y/a * PI : PI + (seed.y-a)/(1.0-a) * PI;&#xD;&#xA;    float P1 = r*cos(phi);&#xD;&#xA;    float P2 = r*sin(phi)*((seed.y&lt;a) ? 1.0 : V.y);&#xD;&#xA;    // compute normal&#xD;&#xA;    vec3 h = P1*T1 + P2*T2 + sqrt(max(0.0, 1.0 - P1*P1 - P2*P2))*V;&#xD;&#xA;    // unstretch&#xD;&#xA;    h = normalize(vec3(rough2*h.x, max(0.0, h.y), rough2*h.z));&#xD;&#xA;    return orthoBasis * h;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf&#xD;&#xA;  [2]: http://jcgt.org/published/0007/04/01/&#xD;&#xA;  [3]: https://i.stack.imgur.com/Lw8Fv.jpg&#xD;&#xA;  [4]: https://github.com/tuket/ggx_importance_sampling&#xD;&#xA;  [5]: https://i.stack.imgur.com/a1Wmd.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/r513Q.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/adrnO.png&#xD;&#xA;  [8]: https://i.ibb.co/TBk7G0W/flip.webp&#xD;&#xA;  [9]: https://github.com/tuket/ggx_importance_sampling/blob/master/main.cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="30724" PostHistoryTypeId="1" PostId="10557" RevisionGUID="81ff2936-34ab-4e74-8e76-3e5464672715" CreationDate="2021-01-10T19:16:54.517" UserId="6172" Text="Comparing different sampling methods for GGX IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="30725" PostHistoryTypeId="3" PostId="10557" RevisionGUID="81ff2936-34ab-4e74-8e76-3e5464672715" CreationDate="2021-01-10T19:16:54.517" UserId="6172" Text="|opengl|glsl|pbr|ggx|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30726" PostHistoryTypeId="5" PostId="10552" RevisionGUID="11472c9a-b373-47f8-a5dc-0b4fb403a8a1" CreationDate="2021-01-10T20:16:42.940" UserId="7724" Comment="added 148 characters in body" Text="A simple example of taking a the derivative of a B\'ezier curve can be shown using a cubic curve.&#xD;&#xA;&#xD;&#xA;$$C(u) = \sum_{i=0}^3 B_{3,i}(u) P_i,$$ where $u \in [0,1]$ and $B_{n,i} = {n \choose i} u^i (1-u)^{n-i}$ is the $i$-th Bernstein polynomial of degree $n$. $P_i$ are the control points. &#xD;&#xA;&#xD;&#xA;written out it is:&#xD;&#xA;&#xD;&#xA;$$C(u) = (1-u)^3 P_0 + 3(1-u)^2 u P_1 + 3 (1-u)u^2 P_2 + u^3 P_3$$&#xD;&#xA;&#xD;&#xA;we can differentiate this with respect to u&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C(u) = -3(1-u)^2 P_0 - 6(1-u) u P_1 + 3(1-u)^2 P_1 - 3 u^2 P_2 + 6 (1-u)u P_2 + 3u^2 P_3. $$&#xD;&#xA;&#xD;&#xA;Now we can rearrange the terms&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C(u) =  3 \left((1-u)^2 (P_1-P_0) + 2(1-u) u (P_2 - P_1)  +  u^2 (P_3 - P_2) \right), $$ or&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C(u) = n (\sum_{i=0}^2 B_{2,i}(u) (P_{i+1} - P_i))$$ &#xD;&#xA;&#xD;&#xA;We obtain a quadratic B\'ezier curve where the control points are the vectors between the initial control points, scaled by a factor $3$. Therefore the derivative of a Bezier curve of degree $n$ is a B\'ezier curve of degree $n-1$, where the control points are difference between initial control points scaled by $n$.&#xD;&#xA;&#xD;&#xA;so:&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} \sum_{i=0}^n B_{n,i}(u) P_i = n (\sum_{i=0}^2 B_{n-1,i}(u) (P_{i+1} - P_i))$$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="30728" PostHistoryTypeId="50" PostId="10384" RevisionGUID="6076bd57-46c8-4a46-8752-99e86e7b27f3" CreationDate="2021-01-11T08:03:35.460" UserId="-1" />
  <row Id="30729" PostHistoryTypeId="50" PostId="9426" RevisionGUID="19da0c2e-bb18-4c47-b1a4-0488481ad9ca" CreationDate="2021-01-11T11:04:55.513" UserId="-1" />
  <row Id="30730" PostHistoryTypeId="5" PostId="10554" RevisionGUID="587d0546-8cbb-47d7-96b2-82c50d9a69a1" CreationDate="2021-01-11T12:22:59.623" UserId="13456" Comment="more specific information about frequency and its relation to spectral distributions" Text="This would be a response to why is it possible to use the Fresnel equations in an RGB path tracer. Though evaluating Fresnel equation directly requires some what more information about the environment in which the rendering takes place, it certainly is possible to use it in an RGB path tracer. Here is why:&#xD;&#xA;&#xD;&#xA;TLDR: see last two paragraphs.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The goal of Fresnel equations is to describe the relationship between the incident, reflected and transmitted planar light waves. In its most general form, it can describe this relationship even at the boundary of an interface (think of them as the zone of contact between one object and air or water).&#xD;&#xA;&#xD;&#xA;Notice that we are considering lightwaves as plane waves which is an approximation.&#xD;&#xA;Now let's define the incident light as the uniform plane sinusoidal electromagnetic wave whose electric field is defined as &#xD;&#xA;$ \vec{E_i} = \vec{E_{0i}} e^{i(\vec{k} \cdot \vec{r} - \omega_i t)} $ since $e^{i\theta} = \cos(\theta) + i\sin(\theta)$ and since we are dealing with measurable quantities we can let go of the complex part and simply write the incident light as $ \vec{E_i} = \vec{E_{0i}} \cos(\vec{k} \cdot \vec{r} - \omega_i t)$. $\vec{E_i}$ is an electric field. Mathematically it is a vector field. Notice that once we get rid of the imaginary part the whole equation is just a cosine wave now with $\vec{E_{0i}}$ as the amplitude. $\vec{k} \cdot \vec{r}$ is the phase and $\omega_i t$ is the frequency. For surfaces with constant phase the $\vec{k} \cdot \vec{r}$ would be constant where $\vec{r}$ would designate the point/position in space and $\vec{k}$ the direction of the propagation of the wave.&#xD;&#xA;&#xD;&#xA;We are interested in the relationship between $\vec{E_i}$, $\vec{E_t}$ and $\vec{E_r}$. With no knowledge about direction, frequency, phase, etc we can describe the reflected wave as $\vec{E_r} = \vec{E_0r} \cos(\vec{k_r} \cdot \vec{r} - \omega_r t + \epsilon_r)$ where $\epsilon_r$ is the phase constant with respect to $\vec{E_i}$. The transimited wave is defined the same way with $\vec{k_t}$, $\omega_t$, $\epsilon_t$ and $E_{0t}$. The $\epsilon$ is introduced because we have not specified the origin of the $\vec{E_i}$.&#xD;&#xA;&#xD;&#xA;Well, after a lot of math which you can read from pages 122 - 124, we learn that they, $\epsilon$s, don't really matter and we can consider them as 0 throughout the discussion and that frequencies, $\omega$ of all three of them are equal (unless there is a doppler effect) and that phases of all three of them are related.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The relationship that is described by Fresnel equations is the amplitude of waves.&#xD;&#xA;Here are the full Fresnel equations from E. Hecht 2017, Optics, p. 124-125:&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0r}}{E_{0i}})_{\perp} = \frac{\frac{n_i}{\mu_i}\cos(\theta_i) - \frac{n_t}{\mu_t}\cos(\theta_t)}{\frac{n_i}{\mu_i}\cos(\theta_i) + \frac{n_t}{\mu_t}\cos(\theta_t)}$$&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0t}}{E_{0i}})_{\perp} = \frac{2\frac{n_i}{\mu_i}\cos(\theta_i)}{\frac{n_i}{\mu_i}\cos(\theta_i) + \frac{n_t}{\mu_t}\cos(\theta_t)}$$&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0r}}{E_{0i}})_{||} =\frac{\frac{n_t}{\mu_t}\cos(\theta_i) - \frac{n_i}{\mu_i}\cos(\theta_t)}{\frac{n_i}{\mu_i}\cos(\theta_t) + \frac{n_t}{\mu_t}\cos(\theta_i)}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$(\frac{E_{0t}}{E_{0i}})_{||} = \frac{2\frac{n_i}{\mu_i}\cos(\theta_i)}{\frac{n_i}{\mu_i}\cos(\theta_t) + \frac{n_t}{\mu_t}\cos(\theta_i)}$$&#xD;&#xA;&#xD;&#xA;These are completely general statements, that is it applies to linear, isotropic, homogenous, even magnetic media. Using certain assumptions you can eliminate some of the terms. For example if you consider $\mu_t \approx \mu_i$ you can simply simply ignore them which would give you the common form of the equations, for example those that are used by PBRT.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;Here are the terms of the equation:&#xD;&#xA;&#xD;&#xA;- $\mu$ is the permeability: $\mu_i$ accounts for the magnetic effect of the incident media, $\mu_t$ accounts for the transmitted media&#xD;&#xA;- $n$ is the index of refraction: $n_i$ for incident media, $n_t$ for transmitted media. It is related to k in discussion above.&#xD;&#xA;- $\theta$ the angle is defined under the following constraints: &#xD;&#xA;  - $\vec{E_i}$ is perpendicular to the plane of incidence. &#xD;&#xA;  - $\vec{B_i}$, magnetic field, is parallel to the plane of incidence.&#xD;&#xA;  - With these constraints it can be proven that $k$s of all planes are coplanar, that is they are all defined on the plane of incidence which is perpendicular to the surface, and that $\theta$ is angle between the normal of the surface and the coplanar direction vectors.&#xD;&#xA;[![Relationship between plane of incidence and other fields][1]][1](image from, Hecht, Eugene. 2017. Optics. 5 ed/fifth edition, Global edition. Pearson Global Edition. Boston Columbus Indianapolis: Pearson, p. 123)&#xD;&#xA;&#xD;&#xA;Now all of the terms and their are related concepts are given, yet we have not defined anywhere a term that relates directly to wavelength. Notice that we CAN include the wavelength to the frequency term of the cosine wave but since frequencies of all waves (incident, transmitted, reflected) are equal, we abstract it away from the relationship that we are trying to describe. That is why we can side step the whole spectral distributions machinary and still have visually plausable results.&#xD;&#xA;&#xD;&#xA;Here are some approximations that can be done.&#xD;&#xA;You can approximate the $k$ and $r$ with incoming ray's direction and origin, the plane of incidence with collided surface normal, keep the frequency constant for all fields. For the majority of surfaces, the approximation $\mu_i \approx \mu_t$ holds as well. For other case they need to be looked up. IOR is also a material property so one has to look that up as well. If they are defined in a wavelength dependent manner, you can make an average and use that as an approximation as well.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3B455.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30731" PostHistoryTypeId="5" PostId="10552" RevisionGUID="e528569e-3cb5-4038-9281-59e0624f7fda" CreationDate="2021-01-11T18:54:44.863" UserId="7724" Comment="added 10 characters in body" Text="A simple example of taking a the derivative of a B\'ezier curve can be shown using a cubic curve.&#xD;&#xA;&#xD;&#xA;$$C_3(u) = \sum_{i=0}^3 B_{3,i}(u) P_i,$$ where $u \in [0,1]$ and $B_{n,i} = {n \choose i} u^i (1-u)^{n-i}$ is the $i$-th Bernstein polynomial of degree $n$. $P_i$ are the control points. &#xD;&#xA;&#xD;&#xA;written out it is:&#xD;&#xA;&#xD;&#xA;$$C_3(u) = (1-u)^3 P_0 + 3(1-u)^2 u P_1 + 3 (1-u)u^2 P_2 + u^3 P_3$$&#xD;&#xA;&#xD;&#xA;we can differentiate this with respect to u&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C_3(u) = -3(1-u)^2 P_0 - 6(1-u) u P_1 + 3(1-u)^2 P_1 - 3 u^2 P_2 + 6 (1-u)u P_2 + 3u^2 P_3. $$&#xD;&#xA;&#xD;&#xA;Now we can rearrange the terms&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C_3(u) =  3 \left((1-u)^2 (P_1-P_0) + 2(1-u) u (P_2 - P_1)  +  u^2 (P_3 - P_2) \right), $$ or&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} C_3(u) = 3 (\sum_{i=0}^2 B_{2,i}(u) (P_{i+1} - P_i))$$ &#xD;&#xA;&#xD;&#xA;We obtain a quadratic B\'ezier curve where the control points are the vectors between the initial control points, scaled by a factor $3$. Therefore the derivative of a Bezier curve of degree $n$ is a B\'ezier curve of degree $n-1$, where the control points are difference between initial control points scaled by $n$.&#xD;&#xA;&#xD;&#xA;so:&#xD;&#xA;&#xD;&#xA;$$\frac{\partial}{\partial u} \sum_{i=0}^n B_{n,i}(u) P_i = n (\sum_{i=0}^2 B_{n-1,i}(u) (P_{i+1} - P_i))$$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="30737" PostHistoryTypeId="5" PostId="4794" RevisionGUID="a51500f6-3539-45fa-9e23-e090f445e09c" CreationDate="2021-01-12T11:53:56.443" UserId="5852" Comment="added 1 character in body" Text="Nearest interpolation between 2 texels means to take the texel whose center is nearest to a given coordinate to draw or, in other words, the texel the coordinate is matching.&#xD;&#xA;&#xD;&#xA;Linear interpolation between 2 texels means to mix the colors of them using more of the nearest texel and less of the others according to the distance to a certain coordinate.&#xD;&#xA;&#xD;&#xA;Nearest interpolation between 2 mipmap levels consist in taking the mipmap whose size fits better the size of the image to draw&#xD;&#xA;&#xD;&#xA;But I cannot understand how linear interpolation works with mipmap levels. " ContentLicense="CC BY-SA 4.0" />
  <row Id="30739" PostHistoryTypeId="2" PostId="10559" RevisionGUID="53bf1709-7aa2-48b0-8e25-62f2bdc092b7" CreationDate="2021-01-12T22:42:08.397" UserId="15572" Text="I have a Dell monitor with 60 Hz refresh rate and therefore games playing on it are not very smooth as compared to 120 hz. &#xA;But when I open videos on YouTube of the same game on the same monitor, some of those videos run extremely smoothly as if it's a 120hz display.&#xA;&#xA;Why is that so ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30740" PostHistoryTypeId="1" PostId="10559" RevisionGUID="53bf1709-7aa2-48b0-8e25-62f2bdc092b7" CreationDate="2021-01-12T22:42:08.397" UserId="15572" Text="Why do some videos look smoother and others don't on the same monitor" ContentLicense="CC BY-SA 4.0" />
  <row Id="30741" PostHistoryTypeId="3" PostId="10559" RevisionGUID="53bf1709-7aa2-48b0-8e25-62f2bdc092b7" CreationDate="2021-01-12T22:42:08.397" UserId="15572" Text="|rendering|3d|gpu|pixel-graphics|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30745" PostHistoryTypeId="2" PostId="10560" RevisionGUID="0c680de5-1da9-4afe-833e-719d9c4c2ed6" CreationDate="2021-01-13T06:15:10.853" UserId="38" Text="Humans dont really see  anything beyond 20-25 fps. Even less is often sufficient animation at 12 frames a second work quite well too. So when you watch tv the fps of your image is 25-30, and yet you dont generally accuse of them being nonsmooth.&#xD;&#xA;&#xD;&#xA;Why do games require more? Well, because they are fast paced. There is generally a slight benefit from going to 30 to 60. But mainly it comes down to:&#xD;&#xA;&#xD;&#xA;* Games do not generally have temporal antialiasig, aka motion blur its expensive.&#xD;&#xA;* The game simulation is locked to the rendering loop so that your input reactions now have a higher rate of feedback (wetware is not digital, reflexes do react faster)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30746" PostHistoryTypeId="2" PostId="10561" RevisionGUID="608b07fb-4eaa-4475-a1ac-ddf8a140a072" CreationDate="2021-01-13T09:17:33.673" UserId="15574" Text="Does using box or gaussian filter introduce bias to the image when reconstructing the pixel?&#xD;&#xA;&#xD;&#xA;Bias does not seem to be talked in the [Chapter 7.8 of PBRT](http://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Image_Reconstruction.html#sec:image-reconstruction)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30747" PostHistoryTypeId="1" PostId="10561" RevisionGUID="608b07fb-4eaa-4475-a1ac-ddf8a140a072" CreationDate="2021-01-13T09:17:33.673" UserId="15574" Text="Does film filter introduce bias in path tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30748" PostHistoryTypeId="3" PostId="10561" RevisionGUID="608b07fb-4eaa-4475-a1ac-ddf8a140a072" CreationDate="2021-01-13T09:17:33.673" UserId="15574" Text="|raytracing|pathtracing|sampling|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30749" PostHistoryTypeId="2" PostId="10562" RevisionGUID="84a5476b-e7a7-4f4c-afa5-4938d32c4ab3" CreationDate="2021-01-13T10:44:20.797" UserId="15415" Text="Here in my book they have shown interpolation using parametric equation of line but I am unable to figure out how do they found out t=|y1-ys|/y1-y2 , t=|AD|/|AB| , t=|CE|/CB ,t=|EP|/|DE| here is the  pic [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/njcYV.jpg&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/5URZg.jpg)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30750" PostHistoryTypeId="1" PostId="10562" RevisionGUID="84a5476b-e7a7-4f4c-afa5-4938d32c4ab3" CreationDate="2021-01-13T10:44:20.797" UserId="15415" Text="How to do linear interpolation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30751" PostHistoryTypeId="3" PostId="10562" RevisionGUID="84a5476b-e7a7-4f4c-afa5-4938d32c4ab3" CreationDate="2021-01-13T10:44:20.797" UserId="15415" Text="|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30752" PostHistoryTypeId="2" PostId="10563" RevisionGUID="4ef14b70-d9bc-46b0-8209-f62c0b64d16a" CreationDate="2021-01-13T13:28:23.660" UserId="7724" Text="Since this is linear interpolation it boils down to solving a linear equation&#xD;&#xA;&#xD;&#xA;$y = a + b x$&#xD;&#xA;&#xD;&#xA;You can substitute the following $y = y_s$, $a = y_1$(intercept) and $b = y_2 - y_1$ (slope) and $x = t$ to get the following&#xD;&#xA;&#xD;&#xA;$$y_s = y_1 + t(y_2 - y_1)$$&#xD;&#xA;$$y_s - y_1 = t(y_2 - y_1)$$&#xD;&#xA;$$\frac{y_s - y_1}{y_2 - y_1} = t$$&#xD;&#xA;&#xD;&#xA;The same thing happens for points where you can write&#xD;&#xA;&#xD;&#xA;$$D = A + (B-A)t$$&#xD;&#xA;&#xD;&#xA;$$ (D-A) = (B-A)\cdot t$$&#xD;&#xA;$$ (D-A)^2 = ((B-A)\cdot t)^2$$&#xD;&#xA;$$ \sqrt{(D-A)^2} = \sqrt{((B-A)\cdot t)^2}$$&#xD;&#xA;$$ \sqrt{(D-A)^2} = \sqrt{(B-A)^2 \cdot t^2}$$&#xD;&#xA;$$ \sqrt{(D-A)^2} = \sqrt{(B-A)^2} \cdot\sqrt{ t^2}$$&#xD;&#xA;$$ |D-A| = |B-A| \cdot t$$&#xD;&#xA;$$ t = \frac{|D-A|}{|B-A|}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="30753" PostHistoryTypeId="2" PostId="10564" RevisionGUID="710d0b8a-7b9a-4db2-a6ad-14a7dd18c380" CreationDate="2021-01-13T16:30:26.287" UserId="15576" Text="everyone!&#xD;&#xA;I am currently developing a program that converts a 3D model to 2D isometric pixel art. Part of my program extracts the texture from an FBX file (as FBX files can have textures built in), and then the texture will be used when converting to vox (which is then converted to a sprite sheet). So, I have a 3D model of a bed here:&#xD;&#xA;[![bed model][1]][1]&#xD;&#xA;&#xD;&#xA;And then I extract the texture programatically, which leaves us with a jpg:&#xD;&#xA;&#xD;&#xA;[![bed texture][2]][2]&#xD;&#xA;&#xD;&#xA;But then, when converting the 3D model to vox, I need to get the color from the specific locations on the bed where the model is being converted to voxels, to apply to each voxel. To do this, my thoughts are that I'll calculate where on this texture sheet would map to my current point on the 3D model, and get the color at that pixel.&#xD;&#xA;&#xD;&#xA;The trouble is calculating this. My question is, how do I calculate how a 2D texture sheet is mapped to a 3D model? Thanks in advance for your answers!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oTDmB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/3MX2O.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30754" PostHistoryTypeId="1" PostId="10564" RevisionGUID="710d0b8a-7b9a-4db2-a6ad-14a7dd18c380" CreationDate="2021-01-13T16:30:26.287" UserId="15576" Text="Calculating Material/Texture Placement from Bitmap to 3D Model" ContentLicense="CC BY-SA 4.0" />
  <row Id="30755" PostHistoryTypeId="3" PostId="10564" RevisionGUID="710d0b8a-7b9a-4db2-a6ad-14a7dd18c380" CreationDate="2021-01-13T16:30:26.287" UserId="15576" Text="|3d|texture|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30756" PostHistoryTypeId="5" PostId="10563" RevisionGUID="ffd2b759-8028-4af4-a3db-e41fdb3b216f" CreationDate="2021-01-13T16:50:41.103" UserId="7724" Comment="deleted 12 characters in body" Text="Since this is linear interpolation it boils down to solving a linear equation&#xD;&#xA;&#xD;&#xA;$y = a + b t$&#xD;&#xA;&#xD;&#xA;You can substitute the following $y = y_s$, $a = y_1$(intercept) and $b = y_2 - y_1$ (slope) to get the following&#xD;&#xA;&#xD;&#xA;$$y_s = y_1 + t(y_2 - y_1)$$&#xD;&#xA;$$y_s - y_1 = t(y_2 - y_1)$$&#xD;&#xA;$$\frac{y_s - y_1}{y_2 - y_1} = t$$&#xD;&#xA;&#xD;&#xA;The same thing happens for points where you can write&#xD;&#xA;&#xD;&#xA;$$D = A + (B-A)t$$&#xD;&#xA;&#xD;&#xA;$$ (D-A) = (B-A)\cdot t$$&#xD;&#xA;$$ (D-A)^2 = ((B-A)\cdot t)^2$$&#xD;&#xA;$$ \sqrt{(D-A)^2} = \sqrt{((B-A)\cdot t)^2}$$&#xD;&#xA;$$ \sqrt{(D-A)^2} = \sqrt{(B-A)^2 \cdot t^2}$$&#xD;&#xA;$$ \sqrt{(D-A)^2} = \sqrt{(B-A)^2} \cdot\sqrt{ t^2}$$&#xD;&#xA;$$ |D-A| = |B-A| \cdot t$$&#xD;&#xA;$$ t = \frac{|D-A|}{|B-A|}$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="30757" PostHistoryTypeId="2" PostId="10565" RevisionGUID="00e97079-2693-4af8-b9b8-547ee46460af" CreationDate="2021-01-13T21:47:04.763" UserId="15541" Text="For each visible voxel side you need to iterate over all triangles and find if ray from voxel side normal intersects that particular triangle. Having intersection point you can then calculate [barycentric][1] coordinates of this point within intersected triangle. And with barycentric coordinates you can calculate UV of intersection point and therefore sample color from original texture. If you need more than one pixel per voxel side then you can cast more rays.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://mathworld.wolfram.com/BarycentricCoordinates.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30758" PostHistoryTypeId="2" PostId="10566" RevisionGUID="632d990c-21bb-4961-9278-4ae55a187700" CreationDate="2021-01-14T16:40:04.530" UserId="13994" Text="If I reflect a vector over a mirror, I expect it to end up on the other side of the mirror, even if there's a bit of numerical error. More precisely, if I run the GLSL code&#xD;&#xA;```&#xD;&#xA;float dot_before = dot(v, mirror)&#xD;&#xA;vec3 v_reflected = reflect(v, mirror)&#xD;&#xA;float dot_after = dot(v_reflected, mirror)&#xD;&#xA;```&#xD;&#xA;on a given `vec3 v` and `vec3 mirror`, I expect `dot_before` and `dot_after` to have opposite signs, even if `dot_after` isn't exactly equal to `-dot_before`.&#xD;&#xA;&#xD;&#xA;When I replicate the code above in Python, using NumPy float32 vectors, I get the behavior I expect. In GLSL, however, when the vector is very close to the mirror, `dot_before` and `dot_after` often come out with the same sign. (See minimal working example below.) My graphics processor is an Intel HD Graphics 520.&#xD;&#xA;&#xD;&#xA;This could happen because the second term in the reflection formula `v - 2*dot(v, mirror)*mirror` is small enough to be rounded off—but why would that round-off affect GLSL but not NumPy at the same floating point precision?&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA; - Why doesn't reflection act like I expect in GLSL?&#xD;&#xA; - Can I write a reflection function that does act like I expect in GLSL?&#xD;&#xA; - If not, is there a good way to identify vectors which are close enough to the mirror that reflection won't put them on the other side? I can choose a threshold that works case-by-case, but it would be nice to have a general principle.&#xD;&#xA;&#xD;&#xA;**Minimal working example**&#xD;&#xA;&#xD;&#xA;In Python 3, using VisPy. The blue and white columns in the output window show vectors where `dot_before` and `dot_after` have the same sign.&#xD;&#xA;```&#xD;&#xA;import sys&#xD;&#xA;from vispy import app, gloo&#xD;&#xA;from math import cos, sin, pi&#xD;&#xA;&#xD;&#xA;vertex = '''&#xD;&#xA;attribute vec2 position;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  gl_Position = vec4(position, 0., 1.);&#xD;&#xA;}&#xD;&#xA;'''&#xD;&#xA;&#xD;&#xA;fragment = '''&#xD;&#xA;uniform vec2 resolution;&#xD;&#xA;uniform vec3 mirror;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  // set up vector&#xD;&#xA;  vec2 u = 2.*gl_FragCoord.xy/resolution - vec2(1.);&#xD;&#xA;  float r_sq = u.x*u.x;&#xD;&#xA;  vec3 v = vec3(2.*u.x, -2.*u.x, 1.+r_sq) / (1.-r_sq);&#xD;&#xA;  &#xD;&#xA;  // do reflection&#xD;&#xA;  float slope_before = dot(mirror, v);&#xD;&#xA;  vec3 v_refl = reflect(v, mirror);&#xD;&#xA;  float slope_after = dot(mirror, v_refl);&#xD;&#xA;  &#xD;&#xA;  // show graph&#xD;&#xA;  vec3 color = vec3(0.);&#xD;&#xA;  if (sign(slope_before) == sign(slope_after)) {&#xD;&#xA;    float level = u.y*1e-6;&#xD;&#xA;    if (level &lt; slope_before) {&#xD;&#xA;      color.r = 1.;&#xD;&#xA;    }&#xD;&#xA;    if (level &lt; slope_after) {&#xD;&#xA;      color.g = 1.;&#xD;&#xA;    }&#xD;&#xA;    color.b = 1.;&#xD;&#xA;  }&#xD;&#xA;  gl_FragColor = vec4(color, 1.);&#xD;&#xA;}&#xD;&#xA;'''&#xD;&#xA;&#xD;&#xA;class TestCanvas(app.Canvas):&#xD;&#xA;  def __init__(self, *args, **kwargs):&#xD;&#xA;    app.Canvas.__init__(self, *args, **kwargs)&#xD;&#xA;    self.program = gloo.Program(vertex, fragment, count = 6) # we'll always send 6 vertices&#xD;&#xA;    &#xD;&#xA;    # draw a rectangle that covers the canvas&#xD;&#xA;    self.program['position'] = [&#xD;&#xA;      (-1, -1), (-1, 1), (1, 1), # northwest triangle&#xD;&#xA;      (-1, -1), (1, 1), (1, -1)  # southeast triangle&#xD;&#xA;    ]&#xD;&#xA;    &#xD;&#xA;    # initialize mirror and signature&#xD;&#xA;    self.program['mirror'] = (-sin(pi/4), -cos(pi/4), 0)&#xD;&#xA;    &#xD;&#xA;    # initialize settings&#xD;&#xA;    self.update_resolution()&#xD;&#xA;    self.title = 'Vector reflection test'&#xD;&#xA;  &#xD;&#xA;  def update_resolution(self):&#xD;&#xA;    width, height = self.physical_size&#xD;&#xA;    gloo.set_viewport(0, 0, width, height)&#xD;&#xA;    self.program['resolution'] = [width, height]&#xD;&#xA;  &#xD;&#xA;  def on_draw(self, event):&#xD;&#xA;    self.program.draw()&#xD;&#xA;  &#xD;&#xA;  def on_resize(self, event):&#xD;&#xA;    self.update_resolution()&#xD;&#xA;&#xD;&#xA;if __name__ == '__main__' and sys.flags.interactive == 0:&#xD;&#xA;  TestCanvas(size = (500, 500)).show()&#xD;&#xA;  app.run()&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="30759" PostHistoryTypeId="1" PostId="10566" RevisionGUID="632d990c-21bb-4961-9278-4ae55a187700" CreationDate="2021-01-14T16:40:04.530" UserId="13994" Text="Numerical error in GLSL vector reflection" ContentLicense="CC BY-SA 4.0" />
  <row Id="30760" PostHistoryTypeId="3" PostId="10566" RevisionGUID="632d990c-21bb-4961-9278-4ae55a187700" CreationDate="2021-01-14T16:40:04.530" UserId="13994" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30761" PostHistoryTypeId="2" PostId="10567" RevisionGUID="2e8761ad-5215-45c1-b167-f4ebfce84a96" CreationDate="2021-01-14T19:31:49.517" UserId="15415" Text="Let's take line AB apart from triangle &#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/eckUT.jpg)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30762" PostHistoryTypeId="5" PostId="10567" RevisionGUID="bfcf289f-78fb-45d3-b685-a47d02236e62" CreationDate="2021-01-14T20:01:18.040" UserId="15415" Comment="added 96 characters in body" Text="I4=I1( 1-t ) + t.I2 ; from parametric equation of line&#xD;&#xA;&#xD;&#xA;I4=I1 - I1.t + t. I2&#xD;&#xA;&#xD;&#xA;I4=I1+ t (I2-I1)&#xD;&#xA;Let's take line AB apart from triangle &#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/eckUT.jpg)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30766" PostHistoryTypeId="5" PostId="10567" RevisionGUID="d86c7e40-4457-48a5-82ca-c23e5fafd1b4" CreationDate="2021-01-15T18:51:18.780" UserId="15415" Comment="edited body" Text="I4=I1( 1-t ) + t.I2 ; from parametric equation of line&#xD;&#xA;&#xD;&#xA;I4=I1 - I1.t + t. I2&#xD;&#xA;&#xD;&#xA;I4=I1+ t (I2-I1)&#xD;&#xA;Let's take line AB apart from triangle &#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/cqxtR.jpg)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30767" PostHistoryTypeId="2" PostId="10569" RevisionGUID="2da52d6e-bcfe-45b3-8b92-d66e6b22cf97" CreationDate="2021-01-15T20:39:58.737" UserId="5717" Text="You have not provided much information but a likely explanation is that your computer can't actually keep up with 60Hz refresh for the game. If forced to vsync, it could be giving you only 30Hz. Even occasional dropped frames can make animation look not smooth, although you'd still technically be getting well over 50 frames per second.&#xD;&#xA;&#xD;&#xA;Playing back 60Hz video is less demanding than most modern games." ContentLicense="CC BY-SA 4.0" />
  <row Id="30768" PostHistoryTypeId="5" PostId="10569" RevisionGUID="d115c724-f649-41c4-ae4f-214809fb85ed" CreationDate="2021-01-15T21:11:17.920" UserId="5717" Comment="new information, completely different explanation" Text="As you have now mentionned that your computer can actually keep up (at 150 fps no less), I suspect you have a case of temporal aliasing.&#xD;&#xA;&#xD;&#xA;The problem is that 150 is not a multiple of 60. Let's say we look at one tenth of a second. That's 15 frames generated by your computer but only 6 can be shown on your screen. The frames you will see will probably be something like:&#xD;&#xA;&#xD;&#xA;#1 - #3 - #6 - #8 - #11 - #13&#xD;&#xA;&#xD;&#xA;Notice how the increment is +2, +3, +2, +3. This will cause animation to not look smooth. There is no steady increment which will let you display 60 frames out of 150.&#xD;&#xA;&#xD;&#xA;As I wrote in the comments below, forcing the game to run at &quot;only&quot; 120Hz should help as the screen should show every other frame.&#xD;&#xA;&#xD;&#xA;Enabling vsync is even more reliable but it seems your game does not deal well with latency then.&#xD;&#xA;&#xD;&#xA;By the way, that's why serious gaming monitors now have adaptive refresh rates. They just show the frames when they're ready and have none of the above issues." ContentLicense="CC BY-SA 4.0" />
  <row Id="30773" PostHistoryTypeId="5" PostId="10498" RevisionGUID="94e348f4-ae94-430a-b0fd-a1c4448d016a" CreationDate="2021-01-16T02:29:05.370" UserId="15133" Comment="added 1690 characters in body" Text="I was trying to follow this http://foundationsofgameenginedev.com/FGED2-sample.pdf&#xD;&#xA;&#xD;&#xA;But had problem understanding formula 7.33.&#xD;&#xA;$$p_i-p_j=(u_i-u_j)\mathrm{t}+(v_i-v_j)\mathrm{b}$$ &#xD;&#xA;\* $p_i,p_j$ being vertices on a triangle, and $u_*,v_*$ being their texture coordiniates, and $M_{tangent}=\left[\mathrm{t}\space\mathrm{b}\space\mathrm{n}\right]$&#xD;&#xA;&#xD;&#xA;If the matrix has to be orthogonal (why though?), then if I'm not mistaken, all its vectors have to measure 1 in magnitude. It surely looks like there lacks constraints on $p_i$ and $p_j$ - they can be at any distance from each other while $\left|u_i-u_j\right|&lt;1$.&#xD;&#xA;&#xD;&#xA;Where did I get it wrong?&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;@pmw1234 &#xD;&#xA;Please read the following and do elaborate a little. &#xD;&#xA;I'm all confused here, whether or not the textbooks I have are good enough.&#xD;&#xA;&#xD;&#xA;The textbook definition of an orthogonal matrix is $${M^T}{M}={M}{M^T}=I$$ or $${M^T}={M^{-1}}$$&#xD;&#xA;&#xD;&#xA;From the definition follows one of the properties:&#xD;&#xA;&#xD;&#xA;A matrix is orthogonal if and only if its rows/cols are orthonormal vectors.&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\text{Because}\\&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\\&#xD;&#xA;\mathrm{r}_{2}\\&#xD;&#xA;\vdots\\&#xD;&#xA;\mathrm{r}_{n}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T&amp;=&amp;\begin{bmatrix}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}^T\end{bmatrix}\\&#xD;&#xA;M\times{M^T}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\mathrm{r}_{1}^T&amp;\mathrm{r}_{1}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{1}\mathrm{r}_{n}^T\\&#xD;&#xA;\mathrm{r}_{2}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{2}\mathrm{r}_{n}^T\\&#xD;&#xA;\vdots&amp;\vdots&amp;\ddots&amp;\vdots\\&#xD;&#xA;\mathrm{r}_{n}\mathrm{r}_{1}^T&amp;\mathrm{r}_{n}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}\mathrm{r}_{n}^T&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\\&#xD;&#xA;\text{Therefore}\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{j}^T&amp;=&amp;0&amp;(i\neq{j})\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{i}^T&amp;=&amp;\left|\mathrm{r}_{i}\right|=1\\&#xD;&#xA;\\&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;i.d. the rows form an orthonormal basis.&#xD;&#xA;&#xD;&#xA;Q.E.D.&#xD;&#xA;&#xD;&#xA;If the book calls M orthogonal isn't enough, the book also says M's transpose is the reverse transformation of M. I assume it means the inverse, otherwise I don't see a way the &quot;reverse transformation&quot; is meaningful.&#xD;&#xA;&#xD;&#xA;A trivial example is.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2&amp;0&amp;0\\&#xD;&#xA;0&amp;1&amp;0\\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T&amp;=&amp;M\\&#xD;&#xA;V&amp;=&amp;\begin{bmatrix}&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T\times{M}\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;4\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;I can't see how $M^T$ reverses anything.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30774" PostHistoryTypeId="5" PostId="10498" RevisionGUID="9a74b12d-d138-451b-a6ce-752cfdb42294" CreationDate="2021-01-16T02:35:10.780" UserId="15133" Comment="added 3 characters in body" Text="I was trying to follow this http://foundationsofgameenginedev.com/FGED2-sample.pdf&#xD;&#xA;&#xD;&#xA;But had problem understanding formula 7.33.&#xD;&#xA;$$p_i-p_j=(u_i-u_j)\mathrm{t}+(v_i-v_j)\mathrm{b}$$ &#xD;&#xA;\* $p_i,p_j$ being vertices on a triangle, and $u_*,v_*$ being their texture coordiniates, and $M_{tangent}=\left[\mathrm{t}\space\mathrm{b}\space\mathrm{n}\right]$&#xD;&#xA;&#xD;&#xA;If the matrix has to be orthogonal (why though?), then if I'm not mistaken, all its vectors have to measure 1 in magnitude. It surely looks like there lacks constraints on $p_i$ and $p_j$ - they can be at any distance from each other while $\left|u_i-u_j\right|&lt;1$.&#xD;&#xA;&#xD;&#xA;Where did I get it wrong?&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;@pmw1234 &#xD;&#xA;Please read the following and do elaborate a little. &#xD;&#xA;I'm all confused here. Whether or not the textbooks I have are good enough.&#xD;&#xA;&#xD;&#xA;The book says because M is orthogonal, $M^T$ is the reverse transformation.&#xD;&#xA;&#xD;&#xA;The textbook definition of an orthogonal matrix is $${M^T}{M}={M}{M^T}=I$$ or $${M^T}={M^{-1}}$$&#xD;&#xA;&#xD;&#xA;From the definition follows one of the properties:&#xD;&#xA;&#xD;&#xA;A matrix is orthogonal if and only if its rows/cols are orthonormal vectors.&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\text{Because}\\&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\\&#xD;&#xA;\mathrm{r}_{2}\\&#xD;&#xA;\vdots\\&#xD;&#xA;\mathrm{r}_{n}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T&amp;=&amp;\begin{bmatrix}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}^T\end{bmatrix}\\&#xD;&#xA;M\times{M^T}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\mathrm{r}_{1}^T&amp;\mathrm{r}_{1}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{1}\mathrm{r}_{n}^T\\&#xD;&#xA;\mathrm{r}_{2}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{2}\mathrm{r}_{n}^T\\&#xD;&#xA;\vdots&amp;\vdots&amp;\ddots&amp;\vdots\\&#xD;&#xA;\mathrm{r}_{n}\mathrm{r}_{1}^T&amp;\mathrm{r}_{n}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}\mathrm{r}_{n}^T&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\\&#xD;&#xA;\text{Therefore}\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{j}^T&amp;=&amp;0&amp;(i\neq{j})\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{i}^T&amp;=&amp;\left|\mathrm{r}_{i}\right|=1\\&#xD;&#xA;\\&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;i.d. the rows form an orthonormal basis.&#xD;&#xA;&#xD;&#xA;Q.E.D.&#xD;&#xA;&#xD;&#xA;If the book calling **M** orthogonal isn't enough, and the rows are merely literally &quot;orthogonal&quot; to each other, I don't see how the &quot;reverse transformation&quot; is meaningful.&#xD;&#xA;&#xD;&#xA;A trivial example is.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2&amp;0&amp;0\\&#xD;&#xA;0&amp;1&amp;0\\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}&amp;\text{the rows being perfectly &quot;orthogonal&quot;}\\&#xD;&#xA;M^T&amp;=&amp;M\\&#xD;&#xA;V&amp;=&amp;\begin{bmatrix}&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T\times{M}\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;4\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;I can't see how $M^T$ reverses anything.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30775" PostHistoryTypeId="5" PostId="10498" RevisionGUID="4c5d6d4b-6771-447b-8e34-2e6f2c9f4c3e" CreationDate="2021-01-16T02:46:26.700" UserId="15133" Comment="added 1 character in body" Text="I was trying to follow this http://foundationsofgameenginedev.com/FGED2-sample.pdf&#xD;&#xA;&#xD;&#xA;But had problem understanding formula 7.33.&#xD;&#xA;$$p_i-p_j=(u_i-u_j)\mathrm{t}+(v_i-v_j)\mathrm{b}$$ &#xD;&#xA;\* $p_i,p_j$ being vertices on a triangle, and $u_*,v_*$ being their texture coordiniates, and $M_{tangent}=\left[\mathrm{t}\space\mathrm{b}\space\mathrm{n}\right]$&#xD;&#xA;&#xD;&#xA;If the matrix has to be orthogonal (why though?), then if I'm not mistaken, all its vectors have to measure 1 in magnitude. It surely looks like there lacks constraints on $p_i$ and $p_j$ - they can be at any distance from each other while $\left|u_i-u_j\right|&lt;1$.&#xD;&#xA;&#xD;&#xA;Where did I get it wrong?&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;@pmw1234 &#xD;&#xA;Please read the following and do elaborate a little. &#xD;&#xA;I'm all confused here. Whether or not the textbooks I have are good enough.&#xD;&#xA;&#xD;&#xA;The book says because M is orthogonal, $M^T$ is the reverse transformation.&#xD;&#xA;&#xD;&#xA;The textbook definition of an orthogonal matrix is $${M^T}{M}={M}{M^T}=I$$ or $${M^T}={M^{-1}}$$&#xD;&#xA;&#xD;&#xA;From the definition follows one of the properties:&#xD;&#xA;&#xD;&#xA;A matrix is orthogonal if and only if its rows/cols are orthonormal vectors.&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\text{Because}\\&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\\&#xD;&#xA;\mathrm{r}_{2}\\&#xD;&#xA;\vdots\\&#xD;&#xA;\mathrm{r}_{n}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T&amp;=&amp;\begin{bmatrix}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}^T\end{bmatrix}\\&#xD;&#xA;M\times{M^T}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\mathrm{r}_{1}^T&amp;\mathrm{r}_{1}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{1}\mathrm{r}_{n}^T\\&#xD;&#xA;\mathrm{r}_{2}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{2}\mathrm{r}_{n}^T\\&#xD;&#xA;\vdots&amp;\vdots&amp;\ddots&amp;\vdots\\&#xD;&#xA;\mathrm{r}_{n}\mathrm{r}_{1}^T&amp;\mathrm{r}_{n}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}\mathrm{r}_{n}^T&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\\&#xD;&#xA;\text{Therefore}\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{j}^T&amp;=&amp;0&amp;(i\neq{j})\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{i}^T&amp;=&amp;\left|\mathrm{r}_{i}\right|=1\\&#xD;&#xA;\\&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;i.d. the rows form an orthonormal basis.&#xD;&#xA;&#xD;&#xA;Q.E.D.&#xD;&#xA;&#xD;&#xA;If the book calling **M** orthogonal isn't enough, and the rows are merely literally &quot;orthogonal&quot; to each other, I don't see how the &quot;reverse transformation&quot; is meaningful.&#xD;&#xA;&#xD;&#xA;A trivial example is.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2&amp;0&amp;0\\&#xD;&#xA;0&amp;1&amp;0\\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}\textrm{the rows being perfectly &quot;orthogonal&quot;}\\&#xD;&#xA;M^T&amp;=&amp;M\\&#xD;&#xA;V&amp;=&amp;\begin{bmatrix}&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T\times{M}\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;4\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;I can't see how $M^T$ reverses anything.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30776" PostHistoryTypeId="5" PostId="10498" RevisionGUID="c1a0f33a-e95e-4f14-a3e0-bb3d091c0f84" CreationDate="2021-01-16T02:52:55.370" UserId="15133" Comment="added 1 character in body" Text="I was trying to follow this http://foundationsofgameenginedev.com/FGED2-sample.pdf&#xD;&#xA;&#xD;&#xA;But had problem understanding formula 7.33.&#xD;&#xA;$$p_i-p_j=(u_i-u_j)\mathrm{t}+(v_i-v_j)\mathrm{b}$$ &#xD;&#xA;\* $p_i,p_j$ being vertices on a triangle, and $u_*,v_*$ being their texture coordiniates, and $M_{tangent}=\left[\mathrm{t}\space\mathrm{b}\space\mathrm{n}\right]$&#xD;&#xA;&#xD;&#xA;If the matrix has to be orthogonal (why though?), then if I'm not mistaken, all its vectors have to measure 1 in magnitude. It surely looks like there lacks constraints on $p_i$ and $p_j$ - they can be at any distance from each other while $\left|u_i-u_j\right|&lt;1$.&#xD;&#xA;&#xD;&#xA;Where did I get it wrong?&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;@pmw1234 &#xD;&#xA;Please read the following and do elaborate a little. &#xD;&#xA;I'm all confused here. Whether or not the textbooks I have are good enough.&#xD;&#xA;&#xD;&#xA;The book says because **M** is orthogonal, $M^T$ is the reverse transformation.&#xD;&#xA;&#xD;&#xA;The textbook definition of an orthogonal matrix is $$\begin{equation}{M^T}{M}={M}{M^T}=I\end{equation}$$ or $${M^T}={M^{-1}}$$&#xD;&#xA;&#xD;&#xA;From the definition follows one of the properties:&#xD;&#xA;&#xD;&#xA;A matrix is orthogonal if and only if its rows/cols are orthonormal vectors.&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\text{Because}\\&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\\&#xD;&#xA;\mathrm{r}_{2}\\&#xD;&#xA;\vdots\\&#xD;&#xA;\mathrm{r}_{n}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T&amp;=&amp;\begin{bmatrix}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}^T\end{bmatrix}\\&#xD;&#xA;M\times{M^T}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\mathrm{r}_{1}^T&amp;\mathrm{r}_{1}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{1}\mathrm{r}_{n}^T\\&#xD;&#xA;\mathrm{r}_{2}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{2}\mathrm{r}_{n}^T\\&#xD;&#xA;\vdots&amp;\vdots&amp;\ddots&amp;\vdots\\&#xD;&#xA;\mathrm{r}_{n}\mathrm{r}_{1}^T&amp;\mathrm{r}_{n}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}\mathrm{r}_{n}^T&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\\&#xD;&#xA;\text{Therefore}\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{j}^T&amp;=&amp;0&amp;(i\neq{j})\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{i}^T&amp;=&amp;\left|\mathrm{r}_{i}\right|=1\\&#xD;&#xA;\\&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;i.d. the rows form an orthonormal basis.&#xD;&#xA;&#xD;&#xA;Q.E.D.&#xD;&#xA;&#xD;&#xA;If the book calling **M** orthogonal isn't enough, and the rows are merely literally &quot;orthogonal&quot; to each other, I don't see how the &quot;reverse transformation&quot; is meaningful.&#xD;&#xA;&#xD;&#xA;A trivial example is.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2&amp;0&amp;0\\&#xD;&#xA;0&amp;1&amp;0\\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}\textrm{the rows being perfectly &quot;orthogonal&quot;}\\&#xD;&#xA;M^T&amp;=&amp;M\\&#xD;&#xA;V&amp;=&amp;\begin{bmatrix}&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T\times{M}\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;4\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;I can't see how $M^T$ reverses anything.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30777" PostHistoryTypeId="5" PostId="10498" RevisionGUID="0fdd6ccb-592f-4e42-bf33-ea70c2f5b8ec" CreationDate="2021-01-16T03:07:37.213" UserId="15133" Comment="edited body" Text="I was trying to follow this http://foundationsofgameenginedev.com/FGED2-sample.pdf&#xD;&#xA;&#xD;&#xA;But had problem understanding formula 7.33.&#xD;&#xA;$$p_i-p_j=(u_i-u_j)\mathrm{t}+(v_i-v_j)\mathrm{b}$$ &#xD;&#xA;\* $p_i,p_j$ being vertices on a triangle, and $u_*,v_*$ being their texture coordiniates, and $M_{tangent}=\left[\mathrm{t}\space\mathrm{b}\space\mathrm{n}\right]$&#xD;&#xA;&#xD;&#xA;If the matrix has to be orthogonal (why though?), then if I'm not mistaken, all its vectors have to measure 1 in magnitude. It surely looks like there lacks constraints on $p_i$ and $p_j$ - they can be at any distance from each other while $\left|u_i-u_j\right|&lt;1$.&#xD;&#xA;&#xD;&#xA;Where did I get it wrong?&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;@pmw1234 &#xD;&#xA;Please read the following and do elaborate a little. &#xD;&#xA;I'm all confused here. Whether or not the textbooks I have are good enough.&#xD;&#xA;&#xD;&#xA;The book says because **M** is orthogonal, $M^T$ is the reverse transformation.&#xD;&#xA;&#xD;&#xA;The textbook definition of an orthogonal matrix is $$\begin{equation}{M^T}{M}={M}{M^T}=I\end{equation}$$ or $${M^T}={M^{-1}}$$&#xD;&#xA;&#xD;&#xA;From the definition follows one of the properties:&#xD;&#xA;&#xD;&#xA;A matrix is orthogonal if and only if its rows/cols are orthonormal vectors.&#xD;&#xA;&#xD;&#xA;Proof:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;\text{Because}\\&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\\&#xD;&#xA;\mathrm{r}_{2}\\&#xD;&#xA;\vdots\\&#xD;&#xA;\mathrm{r}_{n}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T&amp;=&amp;\begin{bmatrix}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}^T\end{bmatrix}\\&#xD;&#xA;M\times{M^T}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;\mathrm{r}_{1}\mathrm{r}_{1}^T&amp;\mathrm{r}_{1}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{1}\mathrm{r}_{n}^T\\&#xD;&#xA;\mathrm{r}_{2}\mathrm{r}_{1}^T&amp;\mathrm{r}_{2}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{2}\mathrm{r}_{n}^T\\&#xD;&#xA;\vdots&amp;\vdots&amp;\ddots&amp;\vdots\\&#xD;&#xA;\mathrm{r}_{n}\mathrm{r}_{1}^T&amp;\mathrm{r}_{n}\mathrm{r}_{2}^T&amp;\ldots&amp;\mathrm{r}_{n}\mathrm{r}_{n}^T&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\\&#xD;&#xA;\text{Therefore}\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{j}^T&amp;=&amp;0&amp;(i\neq{j})\\&#xD;&#xA;\mathrm{r}_{i}\mathrm{r}_{i}^T&amp;=&amp;\left|\mathrm{r}_{i}\right|=1\\&#xD;&#xA;\\&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;i.e. the rows form an orthonormal basis.&#xD;&#xA;&#xD;&#xA;Q.E.D.&#xD;&#xA;&#xD;&#xA;If the book calling **M** orthogonal isn't enough, and the rows are merely literally &quot;orthogonal&quot; to each other, I don't see how the &quot;reverse transformation&quot; is meaningful.&#xD;&#xA;&#xD;&#xA;A trivial example is.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray}&#xD;&#xA;M&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2&amp;0&amp;0\\&#xD;&#xA;0&amp;1&amp;0\\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}\textrm{the rows being perfectly &quot;orthogonal&quot;}\\&#xD;&#xA;M^T&amp;=&amp;M\\&#xD;&#xA;V&amp;=&amp;\begin{bmatrix}&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;2\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;M^T\times{M}\times{V}&amp;=&amp;\begin{bmatrix}&#xD;&#xA;4\\&#xD;&#xA;1\\&#xD;&#xA;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{eqnarray}&#xD;&#xA;$$&#xD;&#xA;I can't see how $M^T$ reverses anything.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30778" PostHistoryTypeId="50" PostId="4895" RevisionGUID="67209a0c-d878-4d88-ad50-b4d1d447154b" CreationDate="2021-01-16T05:04:30.513" UserId="-1" />
  <row Id="30779" PostHistoryTypeId="10" PostId="10246" RevisionGUID="be98fdf5-d264-4fef-b404-200ebb80366f" CreationDate="2021-01-16T16:08:08.017" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="30780" PostHistoryTypeId="2" PostId="10570" RevisionGUID="f839a61d-35a8-4d95-8090-05ac3a308e77" CreationDate="2021-01-16T17:17:38.573" UserId="7869" Text="Foveated rendering, is definitely one of the newest fields of real-time graphics rendering. The main goal of foveated rendering is reducing rendering cost to increase frame-rate without perception difference to the user from full-rendering. Eye-tracker is a great help here, as technology has exponentially evolved over years. &#xD;&#xA;&#xD;&#xA;When we use an eye tracker, can gradually decrease the rendering qualities in peripheral zones. The decreased graphics parameters could be, for example, the color quality. Spatial frequency decrease (e.g. text) in the peripheral does not help much in special applications as decrease such quality will increase the reading time.  Could you give me some ideas about the graphics parameters which can be decreased from the angular distance of the gaze point? " ContentLicense="CC BY-SA 4.0" />
  <row Id="30781" PostHistoryTypeId="1" PostId="10570" RevisionGUID="f839a61d-35a8-4d95-8090-05ac3a308e77" CreationDate="2021-01-16T17:17:38.573" UserId="7869" Text="What can be reduce in peripheral circle and increase in foveated cirle?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30782" PostHistoryTypeId="3" PostId="10570" RevisionGUID="f839a61d-35a8-4d95-8090-05ac3a308e77" CreationDate="2021-01-16T17:17:38.573" UserId="7869" Text="|rendering|real-time|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30783" PostHistoryTypeId="5" PostId="10566" RevisionGUID="26a0175e-0ba2-4cc1-9441-f8224b1a85d6" CreationDate="2021-01-17T18:50:55.303" UserId="13994" Comment="Correct mirror normalization in test code" Text="If I reflect a vector over a mirror, I expect it to end up on the other side of the mirror, even if there's a bit of numerical error. More precisely, if I run the GLSL code&#xD;&#xA;```&#xD;&#xA;float dot_before = dot(v, mirror)&#xD;&#xA;vec3 v_reflected = reflect(v, mirror)&#xD;&#xA;float dot_after = dot(v_reflected, mirror)&#xD;&#xA;```&#xD;&#xA;on a given `vec3 v` and `vec3 mirror`, I expect `dot_before` and `dot_after` to have opposite signs, even if `dot_after` isn't exactly equal to `-dot_before`.&#xD;&#xA;&#xD;&#xA;When I replicate the code above in Python, using NumPy float32 vectors, I get the behavior I expect. In GLSL, however, when the vector is very close to the mirror, `dot_before` and `dot_after` often come out with the same sign. (See minimal working example below.) My graphics processor is an Intel HD Graphics 520.&#xD;&#xA;&#xD;&#xA;This could happen because the second term in the reflection formula `v - 2*dot(v, mirror)*mirror` is small enough to be rounded off—but why would that round-off affect GLSL but not NumPy at the same floating point precision?&#xD;&#xA;&#xD;&#xA;**Questions**&#xD;&#xA;&#xD;&#xA; - Why doesn't reflection act like I expect in GLSL?&#xD;&#xA; - Can I write a reflection function that does act like I expect in GLSL?&#xD;&#xA; - If not, is there a good way to identify vectors which are close enough to the mirror that reflection won't put them on the other side? I can choose a threshold that works case-by-case, but it would be nice to have a general principle.&#xD;&#xA;&#xD;&#xA;**Minimal working example**&#xD;&#xA;&#xD;&#xA;In Python 3, using VisPy. The blue and white columns in the output window show vectors where `dot_before` and `dot_after` have the same sign.&#xD;&#xA;```&#xD;&#xA;import sys&#xD;&#xA;from vispy import app, gloo&#xD;&#xA;from math import cos, sin, pi&#xD;&#xA;&#xD;&#xA;vertex = '''&#xD;&#xA;attribute vec2 position;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  gl_Position = vec4(position, 0., 1.);&#xD;&#xA;}&#xD;&#xA;'''&#xD;&#xA;&#xD;&#xA;fragment = '''&#xD;&#xA;uniform vec2 resolution;&#xD;&#xA;uniform vec3 mirror;&#xD;&#xA;&#xD;&#xA;const float COS45 = 0.7071067811865475;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  // set up vector&#xD;&#xA;  vec2 u = COS45 * (2.*gl_FragCoord.xy/resolution - vec2(1.));&#xD;&#xA;  float r_sq = 2.*u.x*u.x;&#xD;&#xA;  vec3 v = vec3(2.*u.x, -2.*u.x, 1.-r_sq) / (1.+r_sq);&#xD;&#xA;  &#xD;&#xA;  // do reflection&#xD;&#xA;  float dot_before = dot(mirror, v);&#xD;&#xA;  vec3 v_refl = reflect(v, mirror);&#xD;&#xA;  float dot_after = dot(mirror, v_refl);&#xD;&#xA;  &#xD;&#xA;  // show graph&#xD;&#xA;  vec3 color = vec3(0.);&#xD;&#xA;  if (sign(dot_before) == sign(dot_after)) {&#xD;&#xA;    float level = u.y*1e-6;&#xD;&#xA;    if (level &lt; dot_before) {&#xD;&#xA;      color.r = 1.;&#xD;&#xA;    }&#xD;&#xA;    if (level &lt; dot_after) {&#xD;&#xA;      color.g = 1.;&#xD;&#xA;    }&#xD;&#xA;    color.b = 1.;&#xD;&#xA;  }&#xD;&#xA;  gl_FragColor = vec4(color, 1.);&#xD;&#xA;}&#xD;&#xA;'''&#xD;&#xA;&#xD;&#xA;class TestCanvas(app.Canvas):&#xD;&#xA;  def __init__(self, *args, **kwargs):&#xD;&#xA;    app.Canvas.__init__(self, *args, **kwargs)&#xD;&#xA;    self.program = gloo.Program(vertex, fragment, count = 6) # we'll always send 6 vertices&#xD;&#xA;    &#xD;&#xA;    # draw a rectangle that covers the canvas&#xD;&#xA;    self.program['position'] = [&#xD;&#xA;      (-1, -1), (-1, 1), (1, 1), # northwest triangle&#xD;&#xA;      (-1, -1), (1, 1), (1, -1)  # southeast triangle&#xD;&#xA;    ]&#xD;&#xA;    &#xD;&#xA;    # initialize mirror and signature&#xD;&#xA;    self.program['mirror'] = (-sin(pi/4), -cos(pi/4), 0)&#xD;&#xA;    &#xD;&#xA;    # initialize settings&#xD;&#xA;    self.update_resolution()&#xD;&#xA;    self.title = 'Vector reflection test'&#xD;&#xA;  &#xD;&#xA;  def update_resolution(self):&#xD;&#xA;    width, height = self.physical_size&#xD;&#xA;    gloo.set_viewport(0, 0, width, height)&#xD;&#xA;    self.program['resolution'] = [width, height]&#xD;&#xA;  &#xD;&#xA;  def on_draw(self, event):&#xD;&#xA;    self.program.draw()&#xD;&#xA;  &#xD;&#xA;  def on_resize(self, event):&#xD;&#xA;    self.update_resolution()&#xD;&#xA;&#xD;&#xA;if __name__ == '__main__' and sys.flags.interactive == 0:&#xD;&#xA;  TestCanvas(size = (500, 500)).show()&#xD;&#xA;  app.run()&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="30784" PostHistoryTypeId="2" PostId="10571" RevisionGUID="8574e46d-6f03-49fe-8dfb-d91a6578ad3a" CreationDate="2021-01-18T00:19:35.293" UserId="15591" Text="In cases of Laptops, some will have two GPUs. One is built-in (e.g. Intel) and another one attachable (e.g. Nvidia). &#xD;&#xA;&#xD;&#xA;Is it better to have each of them operate different software to divide the load? &#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;is it better to have one of them operate everything because the switching between GPUs might cause slower performance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30785" PostHistoryTypeId="1" PostId="10571" RevisionGUID="8574e46d-6f03-49fe-8dfb-d91a6578ad3a" CreationDate="2021-01-18T00:19:35.293" UserId="15591" Text="is utilizing multiple GPUs better than using one for all software?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30786" PostHistoryTypeId="3" PostId="10571" RevisionGUID="8574e46d-6f03-49fe-8dfb-d91a6578ad3a" CreationDate="2021-01-18T00:19:35.293" UserId="15591" Text="|gpu|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30787" PostHistoryTypeId="50" PostId="8431" RevisionGUID="767af167-c584-4bba-b3bb-f1f8e6a1b107" CreationDate="2021-01-18T01:05:30.543" UserId="-1" />
  <row Id="30789" PostHistoryTypeId="5" PostId="4875" RevisionGUID="c45c3a35-48fe-4044-b8ca-5b8f387bfb6f" CreationDate="2021-01-18T08:37:03.180" UserId="5852" Comment="deleted 4 characters in body" Text="If you clear the color buffer and draw a triangle, you have nothing in the buffer that is shown in the screen and a triangle in the other buffer, so you have to swap buffers to show the triangle. If you swap buffers, you have a triangle in your screen and a empty color buffer in the other side. If you swap buffers again you should see and empty screen because you changed the buffer with the triangle by the other empty buffer. Instead of this, the triangle is shown again. Why?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30790" PostHistoryTypeId="2" PostId="10572" RevisionGUID="0c4b2e57-96f9-4cbd-bff3-92ce8d01afc9" CreationDate="2021-01-18T15:27:10.897" UserId="8009" Text="Actually it's not that new of an idea -- it goes back to at least 1996.  I strongly suggest reading Microsoft Research's [Foveated 3D Graphics](https://www.microsoft.com/en-us/research/publication/foveated-3d-graphics/).  (click 'View publication' and read the full pdf)&#xD;&#xA;&#xD;&#xA;In a nutshell, human visual acuity is different near the center of vision compared to the peripheral.  The middle of the eye is packed more tightly with cone receptors making it more sensitive to detail and color.  In contrast, humans are quite sensitive to motion in their peripheral vision.  Evolutionarily speaking, it's a good idea to maybe take a look at that tiger sneaking up on you from the side.  Your motion perception will trigger a shift in your gaze so you can make sense of exactly what's trying to eat you.&#xD;&#xA;&#xD;&#xA;The most obvious thing that's different is your ability to perceive detail (angular size).  Numerous things can be adjusted with the rendering to economize on detail.&#xD;&#xA;&#xD;&#xA;* Resolution can be reduced.&#xD;&#xA;* Texture sizes can be reduced.&#xD;&#xA;* Geometric (polygonal) detail can be reduced&#xD;&#xA;&#xD;&#xA;[Color perception is reduced](https://jov.arvojournals.org/article.aspx?articleid=2193447#:~:text=Color%20perception%20changes%20across%20the,luminance%20or%20blue%E2%80%93yellow%20colors.) in the periphery as well, therefore:&#xD;&#xA;&#xD;&#xA;* Texture maps with lower bit-depth can be used.&#xD;&#xA;* Precision of color calculations can be reduced.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CAUTION**: There are nuances to making effective use of all of these techniques.  You have to be especially careful not to change the silhouette of the objects because the outer visual region is actually _more_ sensitive to the motion differences that may be perceived by an edge jumping around.  It may also be tempting to turn off antialiasing, but artifacts introduced by crawling pixels are tantamount to motion and draw the eye to these artifacts.  Anti-aliasing sometimes needs to be *increased* negating the effects of foveated rendering.  A blended blurring technique is used that allows seamless transition between regions rendered at high-resolution and low-resolution. **It's a complex subject -- read the paper**.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30791" PostHistoryTypeId="2" PostId="10573" RevisionGUID="527b11ba-1042-49fe-933b-fbc149c372a2" CreationDate="2021-01-18T17:00:05.250" UserId="13456" Text="This is more of a long comment than an answer. &#xD;&#xA;&#xD;&#xA;As with most yes or no questions in graphics, the answer is &quot;it depends on the task&quot;. However, one particular task that you might find having multiple gpu's useful is debugging. For example if you are using cuda-gdb for debugging your CUDA application, it would be nice to have multiple gpu's, one for your application, the other for the display manager of your system. Note that cuda-gdb also works on a single gpu as well, but I had problems with it when I run the debugger and the display manager of the system on a single gpu (screen tends to freeze, no response from the system, etc)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30792" PostHistoryTypeId="50" PostId="9364" RevisionGUID="b9838099-bb5a-4010-81a6-ac4633e71182" CreationDate="2021-01-18T22:00:20.070" UserId="-1" />
  <row Id="30793" PostHistoryTypeId="50" PostId="9744" RevisionGUID="4019225f-fea5-4294-b9af-5dac2942cb79" CreationDate="2021-01-18T23:00:16.040" UserId="-1" />
  <row Id="30794" PostHistoryTypeId="50" PostId="8291" RevisionGUID="81f2ee42-f8b1-45d2-a931-5c3e081192b3" CreationDate="2021-01-19T03:04:50.453" UserId="-1" />
  <row Id="30795" PostHistoryTypeId="5" PostId="10573" RevisionGUID="48814004-3c95-45dd-ba5f-734707073ceb" CreationDate="2021-01-19T10:58:54.910" UserId="13456" Comment="updated the answer conforming to comment" Text="This is more of a long comment than an answer. &#xD;&#xA;&#xD;&#xA;As with most yes or no questions in graphics, the answer is &quot;it depends on the task&quot;. However, one particular task that you might find having multiple gpu's useful is debugging. For example if you are using cuda-gdb for debugging your CUDA application, it would be nice to have multiple gpu's, one for your application, the other for the display manager of your system. Note that cuda-gdb also works on a single gpu as well, but I had problems with it when I run the debugger and the display manager of the system on a single gpu (screen tends to freeze, no response from the system, etc).&#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;Update 19-01-2021 with respect to comment.&#xD;&#xA;&#xD;&#xA;Here is the main criteria that I would use for deciding if the use of single or multiple gpus are better for the task. &#xD;&#xA;&#xD;&#xA;GPUs simply execute one task after another, so if you send a heavy task, it will do only that during the process and you won't be able to do anything else with it. &#xD;&#xA;This usually means that your system would freeze until the gpu is done with your task. &#xD;&#xA;If you are going to launch the task and won't plan to do anything with the machine until it is finished, then sure, the use of multiple gpus would get it done quicker. If you plan to use the machine during the process for other stuff, then it would be more reasonable to allocate a single gpu for the task.&#xD;&#xA;&#xD;&#xA;If you are setting up some kind of rendering server where the server would do only gpu related computation, it depends on the type of request you are planning to process by the server.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="30796" PostHistoryTypeId="50" PostId="9799" RevisionGUID="91862471-2f27-43d4-86ca-d260a961fc78" CreationDate="2021-01-19T12:03:10.337" UserId="-1" />
  <row Id="30798" PostHistoryTypeId="4" PostId="9744" RevisionGUID="96949f99-f449-47fb-bf27-c494b1dde707" CreationDate="2021-01-19T17:46:25.880" UserId="506" Comment="corrected typo in subject, added lighting tag" Text="What is wrong with my metallic PBR shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30799" PostHistoryTypeId="6" PostId="9744" RevisionGUID="96949f99-f449-47fb-bf27-c494b1dde707" CreationDate="2021-01-19T17:46:25.880" UserId="506" Comment="corrected typo in subject, added lighting tag" Text="|glsl|lighting|webgl|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30800" PostHistoryTypeId="50" PostId="10503" RevisionGUID="4c3bde3a-07c9-4324-9e59-ee7509a2218f" CreationDate="2021-01-20T08:02:55.257" UserId="-1" />
  <row Id="30801" PostHistoryTypeId="2" PostId="10574" RevisionGUID="9ac50b23-7d9a-42b6-b653-cd5cf058ddc1" CreationDate="2021-01-20T17:49:28.143" UserId="15604" Text="I was looking at the Raspberry Pi 4 specs and realized that running a software renderer on the pi could get some decent graphics. By using USB ports and Ethernet ports, I think I might be able to send graphics data to the pi, using it as an external graphics card.&#xD;&#xA;\&#xD;&#xA;While the graphics of the external pi card would obviously not approach an RTX, would this work?&#xD;&#xA;Is there a software renderer that I could run on all 4 cores of the Rpi 4?&#xD;&#xA;\&#xD;&#xA;I realize that I may have to create this myself, and I would like to make a custom, real-time Vulkan driver that uses the pi's cpu to do most of the rendering. It would only use the on-board graphics card to do simple, repetitive tasks that it can do efficiently.&#xD;&#xA;\&#xD;&#xA;By installing a special driver, I could output graphics data from a computer into the pi via USB or Ethernet; the pi would then solve it and output it through its own display ports.&#xD;&#xA;\&#xD;&#xA;Does anyone have info that could help me?&#xD;&#xA;I'm a graphics noob and the only help I can get right now is from my dad, but he is quite busy." ContentLicense="CC BY-SA 4.0" />
  <row Id="30802" PostHistoryTypeId="1" PostId="10574" RevisionGUID="9ac50b23-7d9a-42b6-b653-cd5cf058ddc1" CreationDate="2021-01-20T17:49:28.143" UserId="15604" Text="Using Software Rendering to make an External GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="30803" PostHistoryTypeId="3" PostId="10574" RevisionGUID="9ac50b23-7d9a-42b6-b653-cd5cf058ddc1" CreationDate="2021-01-20T17:49:28.143" UserId="15604" Text="|rendering|gpu|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30804" PostHistoryTypeId="6" PostId="10574" RevisionGUID="329ccd58-3453-4a20-b3f6-1ea3ba4a92b0" CreationDate="2021-01-21T05:00:35.670" UserId="2654" Comment="edited tags" Text="|rendering|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30805" PostHistoryTypeId="2" PostId="10575" RevisionGUID="151e590b-28ca-4d68-9f14-98662ab3f8d4" CreationDate="2021-01-21T08:57:52.107" UserId="13456" Text="Theoraticaly this can work, but I am not sure if it would be very efficient. Modern GPU's are tailored for doing low level graphics operations and the drivers that manage them are also tailored for efficiently overseeing these operations to render your scene. &#xD;&#xA;&#xD;&#xA;Now you can ask all the hardware questions related to using Raspberry Pi, how to access its cpu etc to [Raspberry Pi SO](https://raspberrypi.stackexchange.com/).&#xD;&#xA;As per software side, I think P. Shirley's books on &#xD;&#xA;[ray tracing](https://raytracing.github.io/) should get you started on rendering on cpu's rather than gpus. Using multiple threads is extensively discussed in the [following issue](https://github.com/RayTracing/raytracing.github.io/issues/148) of the source code of the book. So once you had written your single threaded cpu ray tracer, you can adapt it easily to execute in multiple threads.&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="30807" PostHistoryTypeId="2" PostId="10576" RevisionGUID="538289c1-4750-42ec-ae1d-daf4e4adf765" CreationDate="2021-01-21T15:52:40.220" UserId="15608" Text="I am following [https://vulkan-tutorial.com/Introduction][1] to get myself familiar with the Vulkan API. I have gotten to the point where my application is able to draw a triangle. But for some reason the clear color is way brighter than the RGB value that i specified in my code. I am setting the color like this: &#xD;&#xA;&#xD;&#xA;		VkClearValue clearColor = {0.2f, 0.2f, 0.2f, 1.0f};&#xD;&#xA;&#xD;&#xA;		VkRenderPassBeginInfo renderPassBeginInfo = {&#xD;&#xA;			.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,&#xD;&#xA;			.renderPass = renderPass,&#xD;&#xA;			.framebuffer = swapChainFramebuffers[i],&#xD;&#xA;			.renderArea = {&#xD;&#xA;				.offset = {&#xD;&#xA;					.x = 0,&#xD;&#xA;					.y = 0&#xD;&#xA;				},&#xD;&#xA;				.extent = swapChainExtent&#xD;&#xA;			},&#xD;&#xA;			.clearValueCount = 1,&#xD;&#xA;			.pClearValues = &amp;clearColor&#xD;&#xA;		};&#xD;&#xA;&#xD;&#xA;An RGB value of [0.2, 0.2, 0.2, 1.0] or [50, 50, 50, 255] should be a very dark gray, almost black. Instead i am getting is this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any idea what might cause this issue?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan-tutorial.com/Introduction&#xD;&#xA;  [2]: https://i.stack.imgur.com/IWHW1.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30808" PostHistoryTypeId="1" PostId="10576" RevisionGUID="538289c1-4750-42ec-ae1d-daf4e4adf765" CreationDate="2021-01-21T15:52:40.220" UserId="15608" Text="Vulkan clear color is wrong" ContentLicense="CC BY-SA 4.0" />
  <row Id="30809" PostHistoryTypeId="3" PostId="10576" RevisionGUID="538289c1-4750-42ec-ae1d-daf4e4adf765" CreationDate="2021-01-21T15:52:40.220" UserId="15608" Text="|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30810" PostHistoryTypeId="5" PostId="10576" RevisionGUID="4c80ecfb-95c1-4ba0-8faa-7523679ad11c" CreationDate="2021-01-21T15:57:50.327" UserId="15608" Comment="added 264 characters in body" Text="I am following [https://vulkan-tutorial.com/Introduction][1] to get myself familiar with the Vulkan API. I have gotten to the point where my application is able to draw a triangle. But for some reason the clear color is way brighter than the RGB value that i specified in my code. I am setting the color like this: &#xD;&#xA;&#xD;&#xA;		VkClearValue clearColor = {0.2f, 0.2f, 0.2f, 1.0f};&#xD;&#xA;&#xD;&#xA;		VkRenderPassBeginInfo renderPassBeginInfo = {&#xD;&#xA;			.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,&#xD;&#xA;			.renderPass = renderPass,&#xD;&#xA;			.framebuffer = swapChainFramebuffers[i],&#xD;&#xA;			.renderArea = {&#xD;&#xA;				.offset = {&#xD;&#xA;					.x = 0,&#xD;&#xA;					.y = 0&#xD;&#xA;				},&#xD;&#xA;				.extent = swapChainExtent&#xD;&#xA;			},&#xD;&#xA;			.clearValueCount = 1,&#xD;&#xA;			.pClearValues = &amp;clearColor&#xD;&#xA;		};&#xD;&#xA;&#xD;&#xA;An RGB value of [0.2, 0.2, 0.2, 1.0] or [50, 50, 50, 255] should be a very dark gray, almost black. Instead i am getting is this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This looks more like an RGB value of [150,150,150,255]. To get a color close to what i want i have to instead go with something like this:&#xD;&#xA;&#xD;&#xA;    VkClearValue clearColor = {0.02f, 0.02f, 0.02f, 1.0f};&#xD;&#xA;&#xD;&#xA;So it almost seems like everything is shifted by a decimal. Any idea what might cause this issue?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan-tutorial.com/Introduction&#xD;&#xA;  [2]: https://i.stack.imgur.com/IWHW1.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30811" PostHistoryTypeId="2" PostId="10577" RevisionGUID="24cd0787-2bbb-4e5c-a04c-737f78119285" CreationDate="2021-01-21T17:54:14.177" UserId="11832" Text="a 3D model is a collection of points, and basically a 3D software has algorithm to find out how those points connect to make surfaces.  &#xD;&#xA;  &#xD;&#xA;I'm searching for what those algorithms are called, that can use a set of points and properly fill in the dots to create the accurate 3D model from the set of points to create the 3D object intended.   &#xD;&#xA;  &#xD;&#xA;Please mention the name of the algorithm if it's a general approach, if it's file specific then please assume for `.obj` files. Any links or references would also be highly appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="30812" PostHistoryTypeId="1" PostId="10577" RevisionGUID="24cd0787-2bbb-4e5c-a04c-737f78119285" CreationDate="2021-01-21T17:54:14.177" UserId="11832" Text="algorithm that openGL uses to construct 3D surface from vertices" ContentLicense="CC BY-SA 4.0" />
  <row Id="30813" PostHistoryTypeId="3" PostId="10577" RevisionGUID="24cd0787-2bbb-4e5c-a04c-737f78119285" CreationDate="2021-01-21T17:54:14.177" UserId="11832" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30814" PostHistoryTypeId="2" PostId="10578" RevisionGUID="14013df2-3b45-4f7e-97b0-9b64a28d9ea2" CreationDate="2021-01-21T19:33:03.237" UserId="506" Text="Most 3D models are not just collections of points; they’re also the information about how those points are connected. Those are [polygon meshes](https://en.wikipedia.org/wiki/Polygon_mesh). What you’re describing sounds like a [point cloud](https://en.wikipedia.org/wiki/Point_cloud), which is what processes like 3D scanning often produce. That article has a “conversion to 3D surfaces” section; if you search for “point cloud meshing” elsewhere you should also find a bunch of information about ways to do this. One new-ish technique worth looking at, which is more robust than a lot of older approaches to the problem: [Fast Winding Numbers for Soups and Clouds](https://www.dgp.toronto.edu/projects/fast-winding-numbers/)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30815" PostHistoryTypeId="2" PostId="10579" RevisionGUID="7d8538c5-7ad0-4c6b-b138-9537532232af" CreationDate="2021-01-21T22:59:43.630" UserId="14079" Text="I would like to rotate an bitmap image using math. I have two issues with [my current implementation][1]: the pixel-by-pixel rotation of the copied bitmap is extremely slow and it is leaving gaps between the pixels.&#xD;&#xA;&#xD;&#xA;[![Rotated Image][2]][2]&#xD;&#xA;&#xD;&#xA;Is there a faster method for copying the bitmap data at an angle that would not have the gaps? This does not have to be specific to Javascript, so any algorithms in any languages are welcome. Please let me know if you have any questions. Thank you.&#xD;&#xA;&#xD;&#xA;```javascript&#xD;&#xA;  cos = Math.cos(-rotation);&#xD;&#xA;  sin = Math.sin(-rotation);&#xD;&#xA;&#xD;&#xA;  //setting the center of rotation&#xD;&#xA;  cx = canvas.width/2;&#xD;&#xA;  cy = canvas.height/2;&#xD;&#xA;&#xD;&#xA;  for (x = 0; x &lt; canvas.width; x++)&#xD;&#xA;  {&#xD;&#xA;    for (y = 0; y &lt; canvas.height; y++)&#xD;&#xA;    {&#xD;&#xA;      //looping through the original bitmap's pixels&#xD;&#xA;      var imgd = ctx.getImageData(x, y, 1, 1); //getting the pixels' colors 1-by-1&#xD;&#xA;      var pix = imgd.data;&#xD;&#xA;      var red = pix[0];&#xD;&#xA;      var green = pix[1];&#xD;&#xA;      var blue = pix[2];&#xD;&#xA;      var alpha = pix[3];&#xD;&#xA;      //rotating and offsetting the pixels by the new rotated dimensions&#xD;&#xA;      nx = ((cos * (x-cx)) + (sin * (y - cy))+canvas2.width/2); &#xD;&#xA;      ny = ((cos * (y-cy)) - (sin * (x - cx))+canvas2.height/2);&#xD;&#xA;      //putting the transformed pixel in the new bitmap&#xD;&#xA;      ctx2.putImageData(imgd, nx, ny);&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://codepen.io/blastframe/pen/jOMRNKE&#xD;&#xA;  [2]: https://i.stack.imgur.com/HkrpJ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30816" PostHistoryTypeId="1" PostId="10579" RevisionGUID="7d8538c5-7ad0-4c6b-b138-9537532232af" CreationDate="2021-01-21T22:59:43.630" UserId="14079" Text="Rotating a Bitmap" ContentLicense="CC BY-SA 4.0" />
  <row Id="30817" PostHistoryTypeId="3" PostId="10579" RevisionGUID="7d8538c5-7ad0-4c6b-b138-9537532232af" CreationDate="2021-01-21T22:59:43.630" UserId="14079" Text="|transformations|algorithm|2d|rasterizer|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30818" PostHistoryTypeId="5" PostId="10575" RevisionGUID="6385d807-c629-4c07-9da8-304702117847" CreationDate="2021-01-21T23:02:17.287" UserId="13456" Comment="updated the answer conforming to comment" Text="Theoraticaly this can work, but I am not sure if it would be very efficient. Modern GPU's are tailored for doing low level graphics operations and the drivers that manage them are also tailored for efficiently overseeing these operations to render your scene. &#xD;&#xA;&#xD;&#xA;Now you can ask all the hardware questions related to using Raspberry Pi, how to access its cpu etc to [Raspberry Pi SO](https://raspberrypi.stackexchange.com/).&#xD;&#xA;As per software side, I think P. Shirley's books on &#xD;&#xA;[ray tracing](https://raytracing.github.io/) should get you started on rendering on cpu's rather than gpus. Using multiple threads is extensively discussed in the [following issue](https://github.com/RayTracing/raytracing.github.io/issues/148) of the source code of the book. So once you had written your single threaded cpu ray tracer, you can adapt it easily to execute in multiple threads.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Update 21-01-2021&#xD;&#xA;&#xD;&#xA;I noticed that there is already a driver for Raspberry Pi 4 provided by [mesa](https://docs.mesa3d.org/drivers/v3d.html), which gives you access to OpenGLES 3 functionality. I think it is a decent trade off, I was even surprised to see that there is actually a graphics driver for Pi.&#xD;&#xA; &#xD;&#xA;Unless you insist on ray tracing your scenes, I would suggest to use that for your experiments." ContentLicense="CC BY-SA 4.0" />
  <row Id="30819" PostHistoryTypeId="2" PostId="10580" RevisionGUID="071d8484-1fc6-4f83-916f-a74f0dac54b1" CreationDate="2021-01-21T23:24:21.087" UserId="15541" Text="You have to loop over destination pixels instead of source ones (gaps are the result of looping over source). For each destination pixel you can calculate position in source data, your code for pixel rotation should be inverted. For source pixel you will then get float x and y, on this step you can either round values and sample color from source (and get a bit distorted image), or you can treat fractional parts as parameters for neighbour pixel color interpolation (you get 4 source pixels for each destination pixel and with fractional part you can calculate color in between those pixels). Here is similar question on SO: https://stackoverflow.com/questions/695080/how-do-i-rotate-an-image&#xD;&#xA;&#xD;&#xA;And the reason why your algorithm is slow is because you use heavy functions to read and write data for each pixel independently. It is generally more favorable to extract source data into some array (it could be same slow function but callng it once is not a problem) and use second array for data writing. This second array can then be copied to destination image. " ContentLicense="CC BY-SA 4.0" />
  <row Id="30820" PostHistoryTypeId="2" PostId="10581" RevisionGUID="b9b0e71a-f26c-4045-83ca-45d79888b8a2" CreationDate="2021-01-22T02:27:42.860" UserId="7952" Text="This looks like the VkFormat being selected for the VkSurfaceFormat, most likekly VK_FORMAT_R8G8B8A8_SRGB. Try VK_FORMAT_R8G8B8A8_UNORM for the VkFormat with a corresponding colorspace (like VK_COLOR_SPACE_SRGB_NONLINEAR_KHR). That should give the dark color you are expecting." ContentLicense="CC BY-SA 4.0" />
  <row Id="30821" PostHistoryTypeId="5" PostId="10578" RevisionGUID="40cfe090-7a5a-4af1-a3ce-a0af32d330fb" CreationDate="2021-01-22T04:31:17.797" UserId="11832" Comment="added information" Text="Most 3D models are not just collections of points; they’re also the information about how those points are connected. Those are [polygon meshes](https://en.wikipedia.org/wiki/Polygon_mesh). What you’re describing sounds like a [point cloud](https://en.wikipedia.org/wiki/Point_cloud), which is what processes like 3D scanning often produce. That article has a “conversion to 3D surfaces” section; if you search for “point cloud meshing” elsewhere you should also find a bunch of information about ways to do this. One new-ish technique worth looking at, which is more robust than a lot of older approaches to the problem: [Fast Winding Numbers for Soups and Clouds](https://www.dgp.toronto.edu/projects/fast-winding-numbers/).  &#xD;&#xA;  &#xD;&#xA;For .obj files in specific, the .obj format specifies the `f` command to tell which vertices make up a face, other formats might have similar things. Some information is [here][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://all3dp.com/1/obj-file-format-3d-printing-cad/" ContentLicense="CC BY-SA 4.0" />
  <row Id="30822" PostHistoryTypeId="24" PostId="10578" RevisionGUID="40cfe090-7a5a-4af1-a3ce-a0af32d330fb" CreationDate="2021-01-22T04:31:17.797" Comment="Proposed by 11832 approved by -1 edit id of 554" ContentLicense="CC BY-SA 4.0" />
  <row Id="30823" PostHistoryTypeId="5" PostId="10578" RevisionGUID="9158ac95-7ff0-4190-9a9a-2787ec347754" CreationDate="2021-01-22T04:31:17.797" UserId="506" Comment="added OBJ detail as suggested" Text="Most 3D models are not just collections of points; they’re also the information about how those points are connected. Those are [polygon meshes](https://en.wikipedia.org/wiki/Polygon_mesh). What you’re describing sounds like a [point cloud](https://en.wikipedia.org/wiki/Point_cloud), which is what processes like 3D scanning often produce. That article has a “conversion to 3D surfaces” section; if you search for “point cloud meshing” elsewhere you should also find a bunch of information about ways to do this. One new-ish technique worth looking at, which is more robust than a lot of older approaches to the problem: [Fast Winding Numbers for Soups and Clouds](https://www.dgp.toronto.edu/projects/fast-winding-numbers/).  &#xD;&#xA;  &#xD;&#xA;For OBJ files in particular, polygons are specified with a list of vertices using the `f` command as described [here](https://en.wikipedia.org/wiki/Wavefront_.obj_file#Face_elements)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30824" PostHistoryTypeId="2" PostId="10582" RevisionGUID="87abe8e9-9a19-49a7-b3ac-ee959bfb7758" CreationDate="2021-01-22T18:23:59.100" UserId="15519" Text="[I will try to keep this answer updated as I learn more]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The best reference on the foundations of light transport seems to be Arvo's [Transfer Equations in Global Illumination][1] (~30 pages)&#xD;&#xA;&#xD;&#xA;Some things he doesn't cover:&#xD;&#xA; - Argument for symmetry of BRDF (see Veach)&#xD;&#xA; - Transfer in anisotropic media&#xD;&#xA;&#xD;&#xA;The state of the art model for Light Transport seems to be [Christian Lessig's PhD thesis][2] (~600 pages). The theory is developed in terms of differentiable manifolds and Hilbert spaces and is much more technical than Arvo's note.&#xD;&#xA;&#xD;&#xA;Lessig carries out translation from the mathematical theory to algorithms (e.g. path tracing, photon mapping) in Section 4.3. &#xD;&#xA;&#xD;&#xA;  [1]: http://www0.cs.ucl.ac.uk/research/vr/Projects/VLF/vlfpapers/sampling/Arvo_J__Transfer_Equations_in_Global_Illumination__SIGGRAPH_course_notes_1993.pdf&#xD;&#xA;  [2]: http://isgwww.cs.uni-magdeburg.de/graphics/projects/dissertation/index.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30825" PostHistoryTypeId="2" PostId="10583" RevisionGUID="221fd997-0e2c-48aa-bdb0-8d83a54ced93" CreationDate="2021-01-22T18:57:04.557" UserId="13456" Text="This is a rather late reply but it might interest others who come up to this question. &#xD;&#xA;Your question assumes that your ray tracing platform does not support double precision. This is unlikely. &#xD;&#xA;&#xD;&#xA;If you are using [CUDA](https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#built-in-vector-types) or [OpenCL](http://man.opencl.org/vectorDataTypes.html) they both support double precision vectors. &#xD;&#xA;&#xD;&#xA;If you are using [Vulkan](https://www.khronos.org/registry/vulkan/specs/1.2/html/vkspec.html#spirvenv-precision-operation) things are a little more complicated due to specification saying: &quot;The precision of double-precision instructions is at least that of single precision.&quot;&#xD;&#xA;&#xD;&#xA;Though not a ray tracing platform OpenGL also supports double precision vectors from OpenGL 4.0 and on.&#xD;&#xA;&#xD;&#xA;If you are tracing on CPU, chances are you can define a double precision vector data type, if it is not already defined.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;If, in the unlikely case that your ray tracing platform does not support double precision, or you are obliged to use single precision in any way, the only thing that I can think of is using [pseudo-remainder sequences](https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#pseudo-remainder) for `rem`- i.e. euclidean division. &#xD;&#xA;Particularly you might want to check out `Subresultant pseudo-remainder sequence` from the wikipedia section in the link. I am adding the pseudocode of the algorithm in here in case the link changes:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;r_0 = a&#xD;&#xA;r_1 = b&#xD;&#xA;for (i:= 1;r_i not equal to 0; i := i+1)&#xD;&#xA;    d_i := degree_of(r_{i-1}) - degree_of(r_i)&#xD;&#xA;    g_i := leading_coefficient_of(r_i)&#xD;&#xA;    if i = 1 then&#xD;&#xA;        b_1 := (-1)^{d_1 + 1}&#xD;&#xA;        p_1 := -1&#xD;&#xA;    else&#xD;&#xA;        b_i := -g_{i-1} (p_i)^d_i&#xD;&#xA;        p_i := ((-g_{i-1})^d_{i-1}) / (p_{i-1}^{d_{i-1}-1}&#xD;&#xA;    end if&#xD;&#xA;    r_i := rem((g_i)^{d_i+1} r_{i-1}, r_i) / b_i&#xD;&#xA;end for&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30826" PostHistoryTypeId="5" PostId="10582" RevisionGUID="f1da4ba5-4997-4ef9-b8e5-b6cb519bb9b7" CreationDate="2021-01-22T20:16:31.343" UserId="15519" Comment="added 31 characters in body" Text="[I will try to keep this answer updated as I learn more]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The best reference on the foundations of light transport seems to be Arvo's [Transfer Equations in Global Illumination][1] (~30 pages)&#xD;&#xA;&#xD;&#xA;Some things he doesn't cover:&#xD;&#xA; - Argument for symmetry of BRDF (see Veach)&#xD;&#xA; - Transfer in media with continuously varying refractive index&#xD;&#xA;&#xD;&#xA;The state of the art model for Light Transport seems to be [Christian Lessig's PhD thesis][2] (~600 pages). The theory is developed in terms of differentiable manifolds and Hilbert spaces and is much more technical than Arvo's note.&#xD;&#xA;&#xD;&#xA;Lessig carries out translation from the mathematical theory to algorithms (e.g. path tracing, photon mapping) in Section 4.3. &#xD;&#xA;&#xD;&#xA;  [1]: http://www0.cs.ucl.ac.uk/research/vr/Projects/VLF/vlfpapers/sampling/Arvo_J__Transfer_Equations_in_Global_Illumination__SIGGRAPH_course_notes_1993.pdf&#xD;&#xA;  [2]: http://isgwww.cs.uni-magdeburg.de/graphics/projects/dissertation/index.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="30827" PostHistoryTypeId="5" PostId="5995" RevisionGUID="c40928fd-6674-419d-b2bf-f085f124f44a" CreationDate="2021-01-22T20:55:28.677" UserId="6202" Comment="added 5 characters in body" Text="This is general question.&#xD;&#xA;In the multitude of video-games that are not specialized in scoped warfare (like Sniper Elite), I've noticed that when you zoom in with a scope, the textures and normal maps won't &quot;update&quot;.&#xD;&#xA;&#xD;&#xA;You're standing on coordinate $(0,0,0)$ and the textures will load in full quality to some other $R^3$ coordinate, let's say $(10,10,10)$.    &#xD;&#xA;If you look through a scope from $(0,0,0)$ past the &quot;Max quality&quot; distance, let's say $(10+n1,10+n2,10+n3)$ (where $n_i$ is the zoom in factor), the zoomed in textures will not updated as if you were standing on the coordinate $(n,n,n)$.    &#xD;&#xA;The best example is the Fallout 4 scope zoom-in.    &#xD;&#xA;If you zoom in anywhere, the distant textures to which you zoom in will look washed out.   &#xD;&#xA;What are the solutions to such problems? Are they engine related? I've just started to dabble in OpenGL and noticed that problem on the multitude of games which share the same game engine." ContentLicense="CC BY-SA 4.0" />
  <row Id="30829" PostHistoryTypeId="2" PostId="10584" RevisionGUID="44996291-4b9c-4309-83b0-21d8b8e50f6c" CreationDate="2021-01-23T04:07:26.143" UserId="7462" Text="There is a way to move a selected point in a mesh with a cursor(assuming a camera that doesn;t change between frames).&#xD;&#xA;&#xD;&#xA;The way I remember the algorithm (but seems to be wrong) is:&#xD;&#xA;&#xD;&#xA; * Unproject the cursor position onto the world position&#xD;&#xA; * Use this and the camera position to create a ray $R$&#xD;&#xA; * for every vertex in the mesh, see if $R$ intersects a small sphere centered at the vertex.&#xD;&#xA; * If you find a valid vertex, mark it as selected&#xD;&#xA; * project the selected vertex onto the screen using the view_projection transformation of the camera&#xD;&#xA; * store the resulting depth (z component) into a variable.&#xD;&#xA; * Now when you move the mouse, you create a fabricated position consisting of the cursor position and the stored projected depth, then you unproject that.&#xD;&#xA;&#xD;&#xA;The resulting point should be constrained on a plane in 3D that is parallel to the screen. I have coded the procedure but it seems I am mathematically wrong. So I am not entirely sure if I forgot a step.&#xD;&#xA;&#xD;&#xA;To be clear, the objective is to drag the mouse around and have the selected point move in 3D such that it is rendered at the same position as the cursor is on the screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="30830" PostHistoryTypeId="1" PostId="10584" RevisionGUID="44996291-4b9c-4309-83b0-21d8b8e50f6c" CreationDate="2021-01-23T04:07:26.143" UserId="7462" Text="Moving a vertex through the cursor" ContentLicense="CC BY-SA 4.0" />
  <row Id="30831" PostHistoryTypeId="3" PostId="10584" RevisionGUID="44996291-4b9c-4309-83b0-21d8b8e50f6c" CreationDate="2021-01-23T04:07:26.143" UserId="7462" Text="|raytracing|mathematics|geometry|projections|ui|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30832" PostHistoryTypeId="2" PostId="10585" RevisionGUID="c9556a15-4a37-4d91-9d21-7bc25e918566" CreationDate="2021-01-23T04:57:41.543" UserId="7462" Text="Figured it out, I did skip a step, you are supposed to multiply by the homogeneous coordinate.&#xD;&#xA;&#xD;&#xA;Basically the actually projected point is (courtesy of GLM):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;        vec&lt;4, T, Q&gt; tmp = vec&lt;4, T, Q&gt;(obj, static_cast&lt;T&gt;(1));&#xD;&#xA;		tmp = model * tmp;&#xD;&#xA;		tmp = proj * tmp;&#xD;&#xA;&#xD;&#xA;		tmp /= tmp.w;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Kinda obvious in hindsight." ContentLicense="CC BY-SA 4.0" />
  <row Id="30833" PostHistoryTypeId="5" PostId="10583" RevisionGUID="9ba89b0d-ca6f-49f2-9d66-cb5a0c8aaaa0" CreationDate="2021-01-23T10:32:47.887" UserId="13456" Comment="better wording" Text="This is a rather late reply but it might interest others who come up to this question. &#xD;&#xA;Your question assumes that your ray tracing platform does not support double precision. This is unlikely. &#xD;&#xA;&#xD;&#xA;If you are using [CUDA](https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#built-in-vector-types) or [OpenCL](http://man.opencl.org/vectorDataTypes.html) they both support double precision vectors. &#xD;&#xA;&#xD;&#xA;If you are using [Vulkan](https://www.khronos.org/registry/vulkan/specs/1.2/html/vkspec.html#spirvenv-precision-operation) things are a little more complicated due to specification saying: &quot;The precision of double-precision instructions is at least that of single precision.&quot;&#xD;&#xA;&#xD;&#xA;Though not a ray tracing platform OpenGL also supports double precision vectors from OpenGL 4.0 and on.&#xD;&#xA;&#xD;&#xA;If you are tracing on CPU, chances are you can define a double precision vector data type, if it is not already defined.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;If, in the unlikely case that your ray tracing platform does not support double precision, or you are obliged to use single precision in any way, the only thing that I can think of is using [pseudo-remainder sequences](https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#pseudo-remainder) for `rem`- i.e. euclidean division. &#xD;&#xA;Particularly you might want to check out `Subresultant pseudo-remainder sequence` from the wikipedia section in the link. I am adding the pseudocode of the algorithm in here:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;r_0 = a&#xD;&#xA;r_1 = b&#xD;&#xA;for (i:= 1;r_i not equal to 0; i := i+1)&#xD;&#xA;    d_i := degree_of(r_{i-1}) - degree_of(r_i)&#xD;&#xA;    g_i := leading_coefficient_of(r_i)&#xD;&#xA;    if i = 1 then&#xD;&#xA;        b_1 := (-1)^{d_1 + 1}&#xD;&#xA;        p_1 := -1&#xD;&#xA;    else&#xD;&#xA;        b_i := -g_{i-1} (p_i)^d_i&#xD;&#xA;        p_i := ((-g_{i-1})^d_{i-1}) / (p_{i-1}^{d_{i-1}-1}&#xD;&#xA;    end if&#xD;&#xA;    r_i := rem((g_i)^{d_i+1} r_{i-1}, r_i) / b_i&#xD;&#xA;end for&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30834" PostHistoryTypeId="2" PostId="10586" RevisionGUID="82d3efda-041f-4c86-9779-fa15d283e9d5" CreationDate="2021-01-23T13:42:27.890" UserId="13456" Text="This more or less a long comment than an answer.&#xD;&#xA;&#xD;&#xA;Some other options that come to mind are the following:&#xD;&#xA;&#xD;&#xA;- A little old school, but you can create an interface with one of the texture objects. You can query different mipmap levels for your needs inside the shader. Textures are one of the better cached objects in OpenGL.&#xD;&#xA;&#xD;&#xA;- You can defer the lightening process by rendering everything to a framebuffer with multiple rendering targets. The first pass would filter out the relevant parts of your data and create a geometry buffer. You can use the g-buffer for lightening pass afterwards.&#xD;&#xA;&#xD;&#xA;- You can create a flat array where your relevant and non relevant data are divided in equal strides, then use the indices of the relevant parts stored in your Element Array Buffer object in `glDrawElements` call. Basically you can use something like the following:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;struct MyRealData {&#xD;&#xA;vec3 myRelevantData&#xD;&#xA;float myNotSoRelevantData&#xD;&#xA;};&#xD;&#xA;void to_drawable(MyRealData[20] ds, vec3[40] flat_drawable_array){&#xD;&#xA;  for (int i = 0; i &lt; 40; i+=2){&#xD;&#xA;    flat_drawable_array[i] = ds[i].myRelevantData;&#xD;&#xA;    flat_drawable_array[i+1] = vec3(ds[i].myNotSoRelevantData, 0, 0);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;std::vector&lt;unsigned int&gt; indices[] = { &#xD;&#xA;  0, 2, 4, // first triangle&#xD;&#xA;  2, 6, 4, // second triangle&#xD;&#xA;  4, 6, 8, // third triangle&#xD;&#xA;// ... etc&#xD;&#xA;}; &#xD;&#xA;.&#xD;&#xA;. // later in the code&#xD;&#xA;.&#xD;&#xA;glDrawElements(GL_TRIANGLES, indices.size() , GL_UNSIGNED_INT, (GLvoid *)indices​.data());&#xD;&#xA;&#xD;&#xA;``` " ContentLicense="CC BY-SA 4.0" />
  <row Id="30835" PostHistoryTypeId="5" PostId="10586" RevisionGUID="9e7eec83-b155-427f-8571-d9d0e3a08a9e" CreationDate="2021-01-23T14:30:40.097" UserId="13456" Comment="rendering-&gt;sending" Text="This more or less a long comment than an answer.&#xD;&#xA;&#xD;&#xA;Some other options that come to mind are the following:&#xD;&#xA;&#xD;&#xA;- A little old school, but you can create an interface with one of the texture objects. You can query different mipmap levels for your needs inside the shader. Textures are one of the better cached objects in OpenGL.&#xD;&#xA;&#xD;&#xA;- You can defer the lightening process by sending everything to a framebuffer with multiple rendering targets. The first pass would filter out the relevant parts of your data and create a geometry buffer. You can use the g-buffer for lightening pass afterwards.&#xD;&#xA;&#xD;&#xA;- You can create a flat array where your relevant and non relevant data are divided in equal strides, then use the indices of the relevant parts stored in your Element Array Buffer object in `glDrawElements` call. Basically you can use something like the following:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;struct MyRealData {&#xD;&#xA;vec3 myRelevantData&#xD;&#xA;float myNotSoRelevantData&#xD;&#xA;};&#xD;&#xA;void to_drawable(MyRealData[20] ds, vec3[40] flat_drawable_array){&#xD;&#xA;  for (int i = 0; i &lt; 40; i+=2){&#xD;&#xA;    flat_drawable_array[i] = ds[i].myRelevantData;&#xD;&#xA;    flat_drawable_array[i+1] = vec3(ds[i].myNotSoRelevantData, 0, 0);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;std::vector&lt;unsigned int&gt; indices[] = { &#xD;&#xA;  0, 2, 4, // first triangle&#xD;&#xA;  2, 6, 4, // second triangle&#xD;&#xA;  4, 6, 8, // third triangle&#xD;&#xA;// ... etc&#xD;&#xA;}; &#xD;&#xA;.&#xD;&#xA;. // later in the code&#xD;&#xA;.&#xD;&#xA;glDrawElements(GL_TRIANGLES, indices.size() , GL_UNSIGNED_INT, (GLvoid *)indices​.data());&#xD;&#xA;&#xD;&#xA;``` " ContentLicense="CC BY-SA 4.0" />
  <row Id="30843" PostHistoryTypeId="2" PostId="10589" RevisionGUID="320eda7c-e89b-453b-b201-92167e8ead60" CreationDate="2021-01-24T13:27:59.693" UserId="15620" Text="I'm just starting to work with framebuffer objects and am having trouble trying to figure out why I can't blit my framebuffer to my viewport.  I know my framebuffer has data drawn to it since I can read its pixel using glReadPixels and save it as an image.  However, when I try to draw it to my back buffer so that I can see it in the window, it draws nothing at all - all I see is the color I cleared the viewport to.&#xD;&#xA;&#xD;&#xA;What am I doing wrong?&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;void DocumentPanel::paintGL()&#xD;&#xA;{&#xD;&#xA;    QOpenGLFunctions_3_3_Core *f = QOpenGLContext::currentContext()-&gt;versionFunctions&lt;QOpenGLFunctions_3_3_Core&gt;();&#xD;&#xA;&#xD;&#xA;    //Setup framebuffer&#xD;&#xA;    setupFramebuffer();&#xD;&#xA;&#xD;&#xA;    //Render to framebuffer&#xD;&#xA;    f-&gt;glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferID);&#xD;&#xA;    f-&gt;glClearColor(0, 0, 1, 0);&#xD;&#xA;&#xD;&#xA;    f-&gt;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    drawShapes();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    //--------------------------------------------&#xD;&#xA;&#xD;&#xA;    f-&gt;glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;    if (!_oneShot)&#xD;&#xA;    {&#xD;&#xA;        dumpFramebuffer();&#xD;&#xA;        _oneShot = true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    f-&gt;glClearColor(0, 0.5, .5, 0);&#xD;&#xA;    f-&gt;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    f-&gt;glDisable(GL_DEPTH_TEST);&#xD;&#xA;    f-&gt;glDisable(GL_STENCIL_TEST);&#xD;&#xA;&#xD;&#xA;    int w = width();&#xD;&#xA;    int h = height();&#xD;&#xA;    f-&gt;glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBufferID);&#xD;&#xA;    f-&gt;glReadBuffer(GL_COLOR_ATTACHMENT0);&#xD;&#xA;    f-&gt;glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);&#xD;&#xA;    f-&gt;glDrawBuffer(GL_BACK);&#xD;&#xA;    f-&gt;glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);&#xD;&#xA;    checkForErrors();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void DocumentPanel::setupFramebuffer()&#xD;&#xA;{&#xD;&#xA;    QOpenGLFunctions_3_3_Core *f = QOpenGLContext::currentContext()-&gt;versionFunctions&lt;QOpenGLFunctions_3_3_Core&gt;();&#xD;&#xA;&#xD;&#xA;    int w = width();&#xD;&#xA;    int h = height();&#xD;&#xA;    int samples = 4;&#xD;&#xA;    bool multisample = false;&#xD;&#xA;&#xD;&#xA;    if (_frameBufferID == 0)&#xD;&#xA;    {&#xD;&#xA;        f-&gt;glGenFramebuffers(1, &amp;_frameBufferID);&#xD;&#xA;        f-&gt;glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferID);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (_renderBufferColorID == 0)&#xD;&#xA;    {&#xD;&#xA;        f-&gt;glGenRenderbuffers(1, &amp;_renderBufferColorID);&#xD;&#xA;        f-&gt;glBindRenderbuffer(GL_RENDERBUFFER, _renderBufferColorID);&#xD;&#xA;&#xD;&#xA;        if (!multisample)&#xD;&#xA;            f-&gt;glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, w, h);&#xD;&#xA;        else&#xD;&#xA;            f-&gt;glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA, w, h);&#xD;&#xA;        f-&gt;glBindRenderbuffer(GL_RENDERBUFFER, 0);&#xD;&#xA;&#xD;&#xA;        f-&gt;glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBufferColorID);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (_renderBufferDepthStencilID == 0)&#xD;&#xA;    {&#xD;&#xA;        f-&gt;glGenRenderbuffers(1, &amp;_renderBufferDepthStencilID);&#xD;&#xA;        f-&gt;glBindRenderbuffer(GL_RENDERBUFFER, _renderBufferDepthStencilID);&#xD;&#xA;        if (!multisample)&#xD;&#xA;            f-&gt;glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);&#xD;&#xA;        else&#xD;&#xA;            f-&gt;glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, w, h);&#xD;&#xA;        f-&gt;glBindRenderbuffer(GL_RENDERBUFFER, 0);&#xD;&#xA;&#xD;&#xA;        f-&gt;glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBufferDepthStencilID);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLenum status = f-&gt;glCheckFramebufferStatus(GL_FRAMEBUFFER);&#xD;&#xA;    if (status != GL_FRAMEBUFFER_COMPLETE)&#xD;&#xA;    {&#xD;&#xA;        //error&#xD;&#xA;        QString err;&#xD;&#xA;&#xD;&#xA;        switch (status)&#xD;&#xA;        {&#xD;&#xA;        case GL_FRAMEBUFFER_UNDEFINED:&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_UNDEFINED&quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT&quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT &quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER :&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER &quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER :&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER &quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_UNSUPPORTED :&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_UNSUPPORTED &quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE :&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE &quot;;&#xD;&#xA;        break;&#xD;&#xA;        case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS  :&#xD;&#xA;            err = &quot;GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS  &quot;;&#xD;&#xA;        break;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        f-&gt;glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;        qDebug() &lt;&lt; &quot;Error building frambuffer: &quot; &lt;&lt; err;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Rendering to window again&#xD;&#xA;    f-&gt;glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="30844" PostHistoryTypeId="1" PostId="10589" RevisionGUID="320eda7c-e89b-453b-b201-92167e8ead60" CreationDate="2021-01-24T13:27:59.693" UserId="15620" Text="Can’t blit framebuffer to backbuffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="30845" PostHistoryTypeId="3" PostId="10589" RevisionGUID="320eda7c-e89b-453b-b201-92167e8ead60" CreationDate="2021-01-24T13:27:59.693" UserId="15620" Text="|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30846" PostHistoryTypeId="2" PostId="10590" RevisionGUID="03ef520e-2d8c-4734-a080-5da06dd60ebe" CreationDate="2021-01-24T21:05:56.710" UserId="15620" Text="Looks like I misunderstood how my windowing system was handling rendering.  It had created an offscreen buffer that was being used to update the window.  When I use ```glBlitFramebuffer``` with the buffer id ```QOpenGLWdget``` gives me, my image appears." ContentLicense="CC BY-SA 4.0" />
  <row Id="30847" PostHistoryTypeId="2" PostId="10591" RevisionGUID="4b8cf9c7-2c3a-47c0-94f7-1e59b46a4e71" CreationDate="2021-01-24T21:25:08.563" UserId="15622" Text="Not a direct answer, but I can shed light on adding and removing pink control points using the GUI:&#xD;&#xA;&#xD;&#xA;* initially PowerStrok gives you 3 pink control points.&#xD;&#xA;* CTRL-Click on one of them duplicates it. Drag it along the path to a new position.&#xD;&#xA;* CTRL-ALT-Click removes the clicked one (don't remove all)&#xD;&#xA;* ALT-Click on a pink control point opens a text entry for exact coordinates.&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="30848" PostHistoryTypeId="2" PostId="10592" RevisionGUID="e3da603b-b394-477e-8c51-b8da2e913ce2" CreationDate="2021-01-24T21:30:27.007" UserId="15622" Text="My guess on the math question is, that there is no straight forward formula to compute &quot;the width&quot; at a given position. &#xD;&#xA;&#xD;&#xA;The pink control points seem to create a spline and you would need proper spline interpolation to predict an exact width at a given position. They can even be dragged out of order, so that the boundary spline would do crazy self-overlapping things. That results in &quot;multiple widths&quot; at some positions." ContentLicense="CC BY-SA 4.0" />
  <row Id="30849" PostHistoryTypeId="2" PostId="10593" RevisionGUID="8ba13353-f2ca-481b-b66b-cb5e0d9f44ff" CreationDate="2021-01-25T10:44:59.310" UserId="11832" Text="The part confusing  about opengl during studying the projection was that the focal length, top, left, bottom, right, wasn't declared, and it magically did it with FOV and image aspect ration.   I found the wonderful maths in [this amazing site][1], and found out how it is calculated based on FOV and focal length.  &#xD;&#xA; Two points I noted for my confusion was:  &#xD;&#xA;- near clipping plane is the plane which limits the projected coordinates, and &#xD;&#xA;- focal length is the distance from the point of projection to the optical center( (0,0,0) in our case )  &#xD;&#xA; &#xD;&#xA;Now, the question is, is the focal length always equal to the distance of the near clipping plane from the optical center, i.e. in other words, is the image *always* projected on the near clipping plane (or at least in openGL)? Yet in other words, is the near clipping plane and the plane of projection the same thing just with different terms.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="30850" PostHistoryTypeId="1" PostId="10593" RevisionGUID="8ba13353-f2ca-481b-b66b-cb5e0d9f44ff" CreationDate="2021-01-25T10:44:59.310" UserId="11832" Text="is focal length equal to the distance from the optical center to the near clipping plane- openGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="30851" PostHistoryTypeId="3" PostId="10593" RevisionGUID="8ba13353-f2ca-481b-b66b-cb5e0d9f44ff" CreationDate="2021-01-25T10:44:59.310" UserId="11832" Text="|opengl|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30852" PostHistoryTypeId="5" PostId="5395" RevisionGUID="3c06b7a6-180d-4397-9e58-79999b0842be" CreationDate="2021-01-25T11:45:22.043" UserId="7008" Comment="removed redundant word, fixed an angle layout error" Text="I finally figured out a flaw in my argumentation to use the half vector for the diffuse part.&#xD;&#xA;&#xD;&#xA;**tl;dr version:**&#xD;&#xA;==================&#xD;&#xA;&#xD;&#xA;$\alpha_{hi}$ and $\alpha_{ho}$ are not equal, this assumption only works for the specular part. Therefore the energyconservation is not given.&#xD;&#xA;&#xD;&#xA;*More correct: Per definition $\alpha_{hi} = \alpha_{ho}$, but you are not allowed to use them in the equation, you need to use the microfacet normals instead of the half vectors. The microfacet normal and the half vector are however not generally equal.*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;long version:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The diffuse BRDF (like the specular one) is an integration over all possible microfacet normals. The generalized BRDF form is:&#xD;&#xA;&#xD;&#xA;**(1)**&#xD;&#xA;&#xD;&#xA;$f = \int_{\Omega} \frac{\rho_m * D * G * \cos(\alpha_{hi}) * \cos(\alpha_{ho})}{ \cos(\theta_i) * \cos(\theta_o)}$&#xD;&#xA;&#xD;&#xA;where $\rho_m$ is the behaviour of light when it reaches a microfacet, $D$ is the normal distribution function, $G$ is the geometry function and the rest is normalization [PBR, p.16-25][HEI, p.61f.]&#xD;&#xA;&#xD;&#xA;Now for the specular BRDF, the behaviour is perfect reflection. This means, only microfacets where the microfacet normal $\omega_m$ equals the half vector $\omega_h$ between light ($\omega_i$) and view ($\omega_o$) direction reflect light from the light direction to the view direction. Mathematically, this translates to a Dirac Delta function $\delta(\omega_h)$. The amount of light reflected is determined by Fresnel $F$. With accounting for integration domain changes[PBR, p.31-41], this leads to ($\rho_{m,s}$ being the specular specific reaction of microfacets for the specular part):&#xD;&#xA;&#xD;&#xA;**(2)**&#xD;&#xA;&#xD;&#xA;$\rho_{m,s} = \frac{\delta(\omega_h) * F }{4*\alpha_{hi}*\alpha_{ho}}$&#xD;&#xA;&#xD;&#xA;Plug this into **(1)** and you integrate over any $\omega_m$, but the dirac delta function makes you ignore anything where $\omega_m \neq \omega_h$. This is the nice thing about those dirac delta functions, the &quot;cancel&quot; the integral. Therefore, you come to the well known BRDF [PBR, p.43]&#xD;&#xA;&#xD;&#xA;**(3)**&#xD;&#xA;&#xD;&#xA;$f_s = \frac{F * D * G}{4 * \cos(\theta_i) * \cos(\theta_o)}$&#xD;&#xA;&#xD;&#xA;and here you can savely assume $\alpha_{hi} = \alpha_{ho}$. The Fresnel part makes this one side of a linear interpolation (seeing as this is the ratio of light being specularly reflected).&#xD;&#xA;&#xD;&#xA;On the other side though, you still have an integral and you can't &quot;cancel&quot; it with anything. Let $\theta_{mi}$ be the angle between the microfacet normal and the light dir, $\theta_{mo}$ between the microfacet normal and the view dir (as opposed to $\alpha_{hi}$ and $\alpha_{ho}$, which specifically are defined for the half angle!).That means 2 important things:&#xD;&#xA;&#xD;&#xA;**(4)**&#xD;&#xA;&#xD;&#xA;$\theta_{mi} \neq \alpha_{hi} = \alpha_h = \alpha_{ho} \neq \theta_{mo} \forall \omega_m \neq \omega_h$&#xD;&#xA;&#xD;&#xA;and $\rho_{m,d}$ (as the diffuse reaction of light when reaching microfacets) is depended upon Fresnel, it can only use non reflected parts, but you cannot just assume EVERY microfacet normal diffusley reflects all the light that was not specularly reflected (i.e. $(1-F(\alpha_h))$).&#xD;&#xA;&#xD;&#xA;So the problem now is, you have one side of that linear interpolation being the analytically solvable specular BRDF without an integral. On the other side, you have the interpolation factor within the integral, and thus you would use it for any microfacet normal. This is not energy conserving anymore, if you model $\rho_{m,d}$ with a lambertian term. &#xD;&#xA;&#xD;&#xA;If you manage to pull the $1-F$ part out of the integral, then and only then can you use the half vector for both specular and diffuse BRDFs, otherwise you need to handle it differently.&#xD;&#xA;&#xD;&#xA;If you still want to use the half vector for the &quot;Fresnelinterpolation&quot;, then you need to normalize.&#xD;&#xA;&#xD;&#xA;$f = F(\alpha_h) * r_s + (1-F(\alpha_h)) * r_d * k$&#xD;&#xA;&#xD;&#xA;With $k$ being chosen, such that&#xD;&#xA;&#xD;&#xA;$r_d * k = 1$&#xD;&#xA;&#xD;&#xA;Note that $r_d$ still includes an integral over all possible microfacet normals.&#xD;&#xA;&#xD;&#xA;Using $\theta_i$ and $\theta_o$&#xD;&#xA;-------------------------&#xD;&#xA;I guess I should add a sentence about the actually used angles, because the question I originally posed was not just &quot;why not $\alpha_h$&quot; but also &quot;why $\theta_i$ and $\theta_o$&quot;. So for the poeple wondering if this is correct: No. It is just an approximation.&#xD;&#xA;&#xD;&#xA;&gt; Instead, we can modify the matte term to be a simple approximation that captures the important qualitative angular behavior[...].&#xD;&#xA;&gt; &#xD;&#xA;&gt; [SHI, p.46]&#xD;&#xA;&#xD;&#xA;Discussion on why this is so hard to figure out&#xD;&#xA;-----------------------------------------------&#xD;&#xA;&#xD;&#xA;Now [DIS, p.14] and [PBR, p.100,184] quoted [SHI] and [ASH] on this, where [ASH] uses [SHI], so it boils down to the model of the latter. And seeing as [DIS] and [PBR] are non-scientific (though pretty well thought through) publications, I can't fault them too much, but really, a better way of quoting papers or an extra explanation might have helped and saved me about 2 weeks of thinking, reading and almost starting a paper on why everybody is (supposedly) wrong. &#xD;&#xA;&#xD;&#xA;Furthermore, neither of them really explains their diffuse approximations, [PBR, p.193] just mentions trying different functions until he saw one he liked.&#xD;&#xA;&#xD;&#xA;Additionally, [SHI, p.46] actually quoted [SCH, p.10f.] who used the linear interpolation between $F(\alpha_h)$ and $1-F(\alpha_h)$. However, [SHI, p.46] quoted him incorrectly, they said he used $F(\theta_i)$ and $1-F(\alpha_h)$. Assuming this, they are of course right in thinking [SCH] is not energy conserving, but this lead me to believe that $F(\alpha_h)$ and $1-F(\alpha_h)$ would be. Their mistake might've come from them using $F(\theta_i)$ themselves, I can't say.&#xD;&#xA;&#xD;&#xA;Literature&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA; - [ASH] An anisotropic phong BRDF model, in Journal of Graphics Tools Vol. 5, No. 2, Michael Ashikhmin and Peter Shirley, 2000&#xD;&#xA; - [SCH] An Inexpsensive BRDF Model for Physically-based Rendering, in Computer Graphics Forum Vol. 13, No. 3, Christophe Schlick, 1994&#xD;&#xA; - [SHI] A Practitioners' Assessment of Light Reflection Models, in The Fifth Pacific Conference on Computer Graphics and Applications, 1997. Proceedings, Peter Shirley,  Helen Hu, Brian Smits and Eric Lafortune, 1997&#xD;&#xA; - [DIS] Physically-Based Shading at Disney, at SIGGRAPH 2012 Course: Physically Based Shading in Film and Game Production, Brent Burley, 2012&#xD;&#xA; - [HEI] Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, in Journal of Computer Graphics Techniques Vol. 3, No. 2, Eric Heitz, 2014&#xD;&#xA; - [PBR] PBR Diffuse Lighting for GGX+Smith Microsurfaces, at GDC2017, Earl Hammon Jr., 2017&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30856" PostHistoryTypeId="2" PostId="10595" RevisionGUID="44b02f21-a9e0-49e2-bdc4-d5a70b7c2466" CreationDate="2021-01-26T01:27:39.060" UserId="15632" Text="Would someone be able to explain why a sphere when projected with the pinhole projection model has its projected 2D image be an ellipsis. IN particular when the sphere is not directly in front of the center of projections why is the image of the sphere skewed? Any diagrams explaining this or formula would be greatly appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="30857" PostHistoryTypeId="1" PostId="10595" RevisionGUID="44b02f21-a9e0-49e2-bdc4-d5a70b7c2466" CreationDate="2021-01-26T01:27:39.060" UserId="15632" Text="Pinhole Projection &amp; Spheres" ContentLicense="CC BY-SA 4.0" />
  <row Id="30858" PostHistoryTypeId="3" PostId="10595" RevisionGUID="44b02f21-a9e0-49e2-bdc4-d5a70b7c2466" CreationDate="2021-01-26T01:27:39.060" UserId="15632" Text="|image-processing|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30863" PostHistoryTypeId="2" PostId="10597" RevisionGUID="77650c2b-71f1-4fc4-887b-a059f830a569" CreationDate="2021-01-26T16:13:20.340" UserId="11832" Text="I know how to rotate objects around the center and there are rotation matrices for that as well, but, how do we rotate the object like a trackball, below is the example:  &#xD;&#xA;  &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;firstly I rotate around the y axis, and then the x axis, then I rotate it like a trackball, how is the third rotation achieved?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7Toy2.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="30864" PostHistoryTypeId="1" PostId="10597" RevisionGUID="77650c2b-71f1-4fc4-887b-a059f830a569" CreationDate="2021-01-26T16:13:20.340" UserId="11832" Text="rotate objects like a trackball" ContentLicense="CC BY-SA 4.0" />
  <row Id="30865" PostHistoryTypeId="3" PostId="10597" RevisionGUID="77650c2b-71f1-4fc4-887b-a059f830a569" CreationDate="2021-01-26T16:13:20.340" UserId="11832" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30866" PostHistoryTypeId="2" PostId="10598" RevisionGUID="511e28c4-49c2-4f58-8a6f-07d4e4fa16c7" CreationDate="2021-01-26T18:34:37.193" UserId="7952" Text="For some reason most sites choose to leave the projection plane out of the visualization of the view frustum. The focal length often labeled &quot;g&quot; is the distance from the camera to the projection plane. The projection plane (which is blue in the attached image) is almost always placed at a distance from the camera such that the distance from the center to the top and bottom is 1. This image from the fged website shows it well: [![enter image description here][1]][1] This choice is a matter of convenience since it makes the math all work out nice and neat. As you can see the near plane can, and often is, behind the projection plane. (the green plane in the image is the near plane)&#xD;&#xA;&#xD;&#xA;For your second confusion: One goal of the projection matrix is to force coordinates with a z value less then that of the near plane to fall outside of the near clipping region which is -1 in OpenGL. So any coordinate that has a z value less then near value will result in a z value below -1. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6wEgR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30867" PostHistoryTypeId="5" PostId="10598" RevisionGUID="a37dbabb-f311-4f60-9f36-40361ae40988" CreationDate="2021-01-26T18:39:37.597" UserId="7952" Comment="added 16 characters in body" Text="For some reason most sites choose to leave the projection plane out of the visualization of the view frustum. The focal length often labeled &quot;g&quot; is the distance from the camera to the projection plane. The projection plane (which is blue in the attached image) is almost always placed at a distance from the camera such that the distance from the center to the top and bottom is 1. This image from the fged website shows it well: [![enter image description here][1]][1] This choice is a matter of convenience since it makes the math all work out nice and neat. As you can see the near plane can, and often is, behind the projection plane. (the green plane in the image is the near plane)&#xD;&#xA;&#xD;&#xA;For your second confusion: One goal of the projection matrix is to force coordinates with a z value less then that of the near plane to fall outside of the near clipping region which is -1 in OpenGL. So any coordinate that has a z value less then near value will result in a z value below -1 after projection.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6wEgR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30868" PostHistoryTypeId="2" PostId="10599" RevisionGUID="6a8d8ee9-4c8e-4cc8-8aa6-a3224454ddb3" CreationDate="2021-01-26T22:41:32.267" UserId="14079" Text="I am rotating a bitmap using the the three shear algorithm documented in these articles [[1][1]][[2][2]].&#xD;&#xA;&#xD;&#xA;From about 0-90°, the quality is acceptable, but beyond that it gets progressively more distorted until it's unintelligible.&#xD;&#xA;[![Bitmap Image Rotations][3]][3]&#xD;&#xA;&#xD;&#xA;Can anyone help me locate what is going wrong? Thank you!&#xD;&#xA;&#xD;&#xA;This is my shear function:&#xD;&#xA;```python&#xD;&#xA;def shear(angle,x,y):&#xD;&#xA;    '''&#xD;&#xA;    |1  -tan(/2) |  |1        0|  |1  -tan(/2) |&#xD;&#xA;    |0      1     |  |sin()   1|  |0      1     |&#xD;&#xA;&#xD;&#xA;    '''&#xD;&#xA;    # shear 1&#xD;&#xA;    tangent=math.tan(angle/2)&#xD;&#xA;    new_x=round(x-y*tangent)&#xD;&#xA;    new_y=y&#xD;&#xA;&#xD;&#xA;    #shear 2&#xD;&#xA;    new_y=round(new_x*math.sin(angle)+new_y)      #since there is no change in new_x according to the shear matrix&#xD;&#xA;&#xD;&#xA;    #shear 3&#xD;&#xA;    new_x=round(new_x-new_y*tangent)              #since there is no change in new_y according to the shear matrix&#xD;&#xA;&#xD;&#xA;    return new_x,new_y&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is the code in the draw function:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;cos = math.cos(self.rotation)&#xD;&#xA;sin = math.sin(self.rotation)&#xD;&#xA;&#xD;&#xA;# Define the width and height of the destination image&#xD;&#xA;newWidth = round(abs(w*cos)+abs(h*sin))+1&#xD;&#xA;newHeight = round(abs(h*cos)+abs(w*sin))+1&#xD;&#xA;&#xD;&#xA;# Find the center of the source image for rotation&#xD;&#xA;origCenterWidth  = round(((w+1)/2)-1)    #with respect to the source image&#xD;&#xA;origCenterHeight = round(((h+1)/2)-1)    #with respect to the source image&#xD;&#xA;&#xD;&#xA;# Find the center of the destination image&#xD;&#xA;newCenterWidth  = round(((newWidth+1)/2)-1)  #with respect to the destination image&#xD;&#xA;newCenterHeight = round(((newHeight)/2)-1)  #with respect to the destination image&#xD;&#xA;&#xD;&#xA;for i in range(h):&#xD;&#xA;    for j in range(w):&#xD;&#xA;        #co-ordinates of pixel with respect to the center of source image&#xD;&#xA;        x = w-1-j-origCenterWidth&#xD;&#xA;        y = h-1-i-origCenterHeight&#xD;&#xA;&#xD;&#xA;        #Applying the Shear Transformation&#xD;&#xA;        new_x,new_y = shear(self.rotation,x,y)&#xD;&#xA;&#xD;&#xA;        #with rotation, the center will change so new_x and new_y will be the new center&#xD;&#xA;        new_y = newCenterHeight-new_y&#xD;&#xA;        new_x = newCenterWidth-new_x&#xD;&#xA;&#xD;&#xA;        alphaValue = sourceBmp.GetAlphaPixel(alphaChannel, j, i) #gets the source image pixel's alpha&#xD;&#xA;        col = sourceBmp.GetPixelDirect(j, i) #gets the source image pixel's color as a Color Vector&#xD;&#xA;        destBmp.SetAlphaPixel(nBmpAlpha, int(new_x), int(new_y), alphaValue) #sets the destination image pixel's alpha&#xD;&#xA;        destBmp.SetPixel(int(new_x), int(new_y), int(col.x), int(col.y), int(col.z)) #sets the destination image pixel's color&#xD;&#xA;```&#xD;&#xA;  [1]: https://datagenetics.com/blog/august32013/index.html&#xD;&#xA;  [2]: https://medium.com/@gautamnagrawal/rotating-image-by-any-angle-shear-transformation-using-only-numpy-d28d16eb5076&#xD;&#xA;  [3]: https://i.stack.imgur.com/eKfDz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30869" PostHistoryTypeId="1" PostId="10599" RevisionGUID="6a8d8ee9-4c8e-4cc8-8aa6-a3224454ddb3" CreationDate="2021-01-26T22:41:32.267" UserId="14079" Text="Rotate a Bitmap with Shearing" ContentLicense="CC BY-SA 4.0" />
  <row Id="30870" PostHistoryTypeId="3" PostId="10599" RevisionGUID="6a8d8ee9-4c8e-4cc8-8aa6-a3224454ddb3" CreationDate="2021-01-26T22:41:32.267" UserId="14079" Text="|transformations|algorithm|matrix|2d|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30871" PostHistoryTypeId="5" PostId="10599" RevisionGUID="7d426768-a297-4495-81d1-4517880ec197" CreationDate="2021-01-27T16:22:07.713" UserId="14079" Comment="deleted 4 characters in body" Text="I am rotating a bitmap using the three shear algorithm documented in these articles [[1][1]][[2][2]].&#xD;&#xA;&#xD;&#xA;From about 0-90°, the quality is acceptable, but beyond that it gets progressively more distorted until it's unintelligible.&#xD;&#xA;[![Bitmap Image Rotations][3]][3]&#xD;&#xA;&#xD;&#xA;Can anyone help me locate what is going wrong? Thank you!&#xD;&#xA;&#xD;&#xA;This is my shear function:&#xD;&#xA;```python&#xD;&#xA;def shear(angle,x,y):&#xD;&#xA;    '''&#xD;&#xA;    |1  -tan(/2) |  |1        0|  |1  -tan(/2) |&#xD;&#xA;    |0      1     |  |sin()   1|  |0      1     |&#xD;&#xA;&#xD;&#xA;    '''&#xD;&#xA;    # shear 1&#xD;&#xA;    tangent=math.tan(angle/2)&#xD;&#xA;    new_x=round(x-y*tangent)&#xD;&#xA;    new_y=y&#xD;&#xA;&#xD;&#xA;    #shear 2&#xD;&#xA;    new_y=round(new_x*math.sin(angle)+new_y)      #since there is no change in new_x according to the shear matrix&#xD;&#xA;&#xD;&#xA;    #shear 3&#xD;&#xA;    new_x=round(new_x-new_y*tangent)              #since there is no change in new_y according to the shear matrix&#xD;&#xA;&#xD;&#xA;    return new_x,new_y&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is the code in the draw function:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;cos = math.cos(self.rotation)&#xD;&#xA;sin = math.sin(self.rotation)&#xD;&#xA;&#xD;&#xA;# Define the width and height of the destination image&#xD;&#xA;newWidth = round(abs(w*cos)+abs(h*sin))+1&#xD;&#xA;newHeight = round(abs(h*cos)+abs(w*sin))+1&#xD;&#xA;&#xD;&#xA;# Find the center of the source image for rotation&#xD;&#xA;origCenterWidth  = round(((w+1)/2)-1)    #with respect to the source image&#xD;&#xA;origCenterHeight = round(((h+1)/2)-1)    #with respect to the source image&#xD;&#xA;&#xD;&#xA;# Find the center of the destination image&#xD;&#xA;newCenterWidth  = round(((newWidth+1)/2)-1)  #with respect to the destination image&#xD;&#xA;newCenterHeight = round(((newHeight)/2)-1)  #with respect to the destination image&#xD;&#xA;&#xD;&#xA;for i in range(h):&#xD;&#xA;    for j in range(w):&#xD;&#xA;        #co-ordinates of pixel with respect to the center of source image&#xD;&#xA;        x = w-1-j-origCenterWidth&#xD;&#xA;        y = h-1-i-origCenterHeight&#xD;&#xA;&#xD;&#xA;        #Applying the Shear Transformation&#xD;&#xA;        new_x,new_y = shear(self.rotation,x,y)&#xD;&#xA;&#xD;&#xA;        #with rotation, the center will change so new_x and new_y will be the new center&#xD;&#xA;        new_y = newCenterHeight-new_y&#xD;&#xA;        new_x = newCenterWidth-new_x&#xD;&#xA;&#xD;&#xA;        alphaValue = sourceBmp.GetAlphaPixel(alphaChannel, j, i) #gets the source image pixel's alpha&#xD;&#xA;        col = sourceBmp.GetPixelDirect(j, i) #gets the source image pixel's color as a Color Vector&#xD;&#xA;        destBmp.SetAlphaPixel(nBmpAlpha, int(new_x), int(new_y), alphaValue) #sets the destination image pixel's alpha&#xD;&#xA;        destBmp.SetPixel(int(new_x), int(new_y), int(col.x), int(col.y), int(col.z)) #sets the destination image pixel's color&#xD;&#xA;```&#xD;&#xA;  [1]: https://datagenetics.com/blog/august32013/index.html&#xD;&#xA;  [2]: https://medium.com/@gautamnagrawal/rotating-image-by-any-angle-shear-transformation-using-only-numpy-d28d16eb5076&#xD;&#xA;  [3]: https://i.stack.imgur.com/eKfDz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30875" PostHistoryTypeId="50" PostId="9614" RevisionGUID="50f4963d-6623-412e-8989-537908834ba8" CreationDate="2021-01-27T22:01:10.137" UserId="-1" />
  <row Id="30876" PostHistoryTypeId="2" PostId="10601" RevisionGUID="63efd2f4-3f5c-4b33-8ee3-a39a66fbc0a0" CreationDate="2021-01-28T01:22:55.150" UserId="113" Text="I don't know the specifics of what looks to be blender. But I would grab the view matrix of the camera. The rows of which should be orthonormal and give you forward, up, and right. Or columns depending on row or col major (technically its the inverse of the view, but that's just the transpose). Then just do some axes angle rotations around that. Something like this:&#xD;&#xA;&#xD;&#xA;    Vec3 dx = scale * (currPosX - prevPosX)&#xD;&#xA;    Vec3 dy = scale * (currPosY - prevPosY)&#xD;&#xA;    Matrix4x4 m1 = axesAngleRot(dx, camera up)&#xD;&#xA;    Matrix4x4 m2 = axesAngleRot(dy, camera right)&#xD;&#xA;    &#xD;&#xA;    Matrix4x4 deltaRot = m1 * m2&#xD;&#xA;&#xD;&#xA;Where scale is defined by you, and dx and dy give the delta coords of the mouse.&#xD;&#xA;&#xD;&#xA;Then apply that to the object. You may have to tack on an extra transform to move back to origin (however you have that transform defined) before doing rotations. The cube you showed is at origin though.&#xD;&#xA;&#xD;&#xA;    Matrix4x4 finalTransform = inverseFinalTransform * deltaRot * finalTransform" ContentLicense="CC BY-SA 4.0" />
  <row Id="30877" PostHistoryTypeId="50" PostId="9116" RevisionGUID="a019f907-b9b3-479b-9285-463048583ef4" CreationDate="2021-01-28T09:07:25.813" UserId="-1" />
  <row Id="30879" PostHistoryTypeId="2" PostId="10602" RevisionGUID="8be35820-7630-4e5a-b8c4-66f277b23a1b" CreationDate="2021-01-28T22:46:41.223" UserId="15655" Text="as paulHK said:&#xD;&#xA;&#xD;&#xA;&gt; One fundamental issue here is you're rotating in destination space rather than source space (e.g. apply the shear on source coordinates and output a rectangle). This way you can guarantee every pixel in the output is drawn once and only once and there are no gaps in between.&#xD;&#xA;&#xD;&#xA;and the line that's causing the 180 problem is this line:&#xD;&#xA;&#xD;&#xA;`tangent=math.tan(angle/2)`&#xD;&#xA;&#xD;&#xA;If the angle is 180, the tan of 90 will be basically infinity.&#xD;&#xA;&#xD;&#xA;This is a graph of 1 / (cos(rotation) ^ 2), one of the shearing calculations the narrator at datagenetics.com uses:&#xD;&#xA;[![graph showing extreme peaks of function][3]][3]&#xD;&#xA;&#xD;&#xA;That means his method stalls at certain angles.&#xD;&#xA;&#xD;&#xA;In all the code i wrote, I never needed to call tan(x).&#xD;&#xA;Use cos(x) and sin(x) instead, also use as few divisions as possible that could create infinity. Most rendering engines tackle this problem by limiting the angle of the camera to 89 degrees.&#xD;&#xA;&#xD;&#xA;To get unaliased rotated images, i suggest a better drawing method, which computer graphics use today:&#xD;&#xA;&#xD;&#xA;Use a 3x3 [rotation matrix][1] and a [translation matrix][2] , and loop over the pixels image that you want to draw on:&#xD;&#xA;&#xD;&#xA;cos(angle) -sin(angle) + offset x &lt;br&gt;&#xD;&#xA;sin(angle) cos(angle)  + offset y &lt;br&gt;&#xD;&#xA;0          0           1 &lt;br&gt;&#xD;&#xA;&#xD;&#xA;to get this matrix, multiply first: &lt;br&gt;&#xD;&#xA;&#xD;&#xA;1 0 -[rotation centre x]  &lt;br&gt;&#xD;&#xA;0 1 -[rotation centre y]  &lt;br&gt;&#xD;&#xA;0 0 1 &lt;br&gt;&#xD;&#xA;&#xD;&#xA;then: &lt;br&gt;&#xD;&#xA;&#xD;&#xA;cos(angle) -sin(angle) 0 &lt;br&gt;&#xD;&#xA;sin(angle) cos(angle)  0 &lt;br&gt;&#xD;&#xA;0          0           1&#xD;&#xA;&#xD;&#xA;and then: &lt;br&gt;&#xD;&#xA;1 0 [rotation centre x]  &lt;br&gt;&#xD;&#xA;0 1 [rotation centre y]  &lt;br&gt;&#xD;&#xA;0 0 1 &lt;br&gt;&#xD;&#xA;&#xD;&#xA;and then(if needed to translate): &lt;br&gt;&#xD;&#xA;1 0 [translation x]  &lt;br&gt;&#xD;&#xA;0 1 [translation y]  &lt;br&gt;&#xD;&#xA;0 0 1 &lt;br&gt;&#xD;&#xA;&#xD;&#xA;Multiply the position on the target image by the **INVERSE** of the combined matrix to get the position on the source image.&#xD;&#xA;&#xD;&#xA;If the position is in the bounds of the source image,&#xD;&#xA;fill the target pixel with the source pixel at that location.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rotation_matrix&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Translation_(geometry)#Matrix_representation&#xD;&#xA;  [3]: https://i.stack.imgur.com/c2roH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30880" PostHistoryTypeId="2" PostId="10603" RevisionGUID="650fbcbd-e371-4216-ad04-d72fcda1f293" CreationDate="2021-01-29T05:55:21.440" UserId="15632" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S5SD0.png&#xD;&#xA;&#xD;&#xA;Stuck with this questions could I get some help. &#xD;&#xA;&#xD;&#xA;where uA and vA are two orthonormal vectors indicating the two axes, and oA is the origin.  Suppose that all  three  frames  of  reference  shown  in  Figure  3  are  orthonormal,  and  suppose  that A and B are  related through  the  affine  transformation N,  and A and C are  related  through  the  affine  transformation M.   In particular,B=AN,and C=AM.Derive an expression of M using only the symbolsθ,d, andφ(in Figure 3) (i.e., matrix M is the function of θ,d, andφ )." ContentLicense="CC BY-SA 4.0" />
  <row Id="30881" PostHistoryTypeId="1" PostId="10603" RevisionGUID="650fbcbd-e371-4216-ad04-d72fcda1f293" CreationDate="2021-01-29T05:55:21.440" UserId="15632" Text="Changing Coordinate Frames with Affine Transformations" ContentLicense="CC BY-SA 4.0" />
  <row Id="30882" PostHistoryTypeId="3" PostId="10603" RevisionGUID="650fbcbd-e371-4216-ad04-d72fcda1f293" CreationDate="2021-01-29T05:55:21.440" UserId="15632" Text="|computational-geometry|geometry|vector-graphics|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30883" PostHistoryTypeId="2" PostId="10604" RevisionGUID="815cfd66-6d5a-43f5-8d9e-5960ba1f56af" CreationDate="2021-01-29T10:27:35.980" UserId="15656" Text="I am interested in how much a GPU can actually calculate. When learning about rendering, it seems like a good idea as well.&#xD;&#xA;&#xD;&#xA;My Question:&#xD;&#xA;**WHAT EXACTLY is a Floating Point Operation?**&#xD;&#xA;&#xD;&#xA;I know what a floating point number is.&#xD;&#xA;&#xD;&#xA;Now, when reading other questions and articles about it, they always say, any simple operation, + - * / , would be a floating point operation, which makes sense in terms of the word itself&#xD;&#xA;&#xD;&#xA;BUT:   *A multiplication is (obviously) often &quot;far&quot; more (calculating) than an addition, isn't it?!*&#xD;&#xA;(Apart from the sheer size of the calculation)&#xD;&#xA;&#xD;&#xA;Following, just a simple example for demonstration:&#xD;&#xA;&#xD;&#xA;5+5=       5+5&#xD;&#xA;&#xD;&#xA;5*5=       5+5+5+5+5&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So does the term &quot;flop&quot; actually just describe additions and subtractions&#xD;&#xA;or is a flop in the end just a very rough definition?&#xD;&#xA;Or is the GPU somehow equally fast at all of those calculations?&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="30884" PostHistoryTypeId="1" PostId="10604" RevisionGUID="815cfd66-6d5a-43f5-8d9e-5960ba1f56af" CreationDate="2021-01-29T10:27:35.980" UserId="15656" Text="FLOP - exact definition" ContentLicense="CC BY-SA 4.0" />
  <row Id="30885" PostHistoryTypeId="3" PostId="10604" RevisionGUID="815cfd66-6d5a-43f5-8d9e-5960ba1f56af" CreationDate="2021-01-29T10:27:35.980" UserId="15656" Text="|gpu|hardware|theory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30886" PostHistoryTypeId="2" PostId="10605" RevisionGUID="2e4c020e-1b73-47b9-aa00-7cda92c7efd1" CreationDate="2021-01-29T10:39:38.597" UserId="13273" Text="is it possible to calculate a &quot;projection matrix&quot; which is sheered as well?&#xD;&#xA;the usual perspective projection matrix forms a pyramid where the near clipping plane is rectangular.&#xD;&#xA;I have 4 lines which represents the edges of the pyramid in general. But the clipping plane is not orthogonal to the view direction (see picture 1)&#xD;&#xA;&#xD;&#xA;**Picture 1: view onto the projected area from above. Also from the side direction it will look like this**&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;By looking from the view position to the near clipping plane / image plane it would look like picture 2.&#xD;&#xA;&#xD;&#xA;**Picture 2: the view from the view position onto the scene**&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The image plane is restricted to be rectangular. Only from the view position its shape will look non rectangular. &#xD;&#xA;&#xD;&#xA;Now lets look at the parameters which are known:&#xD;&#xA;&#xD;&#xA; 1. all 4 corners of the image plane&#xD;&#xA; 2. the view position&#xD;&#xA; 3. the far plane distance&#xD;&#xA; &#xD;&#xA;so my task is to calculate this projection matrix, but I've no idea how to start or if it is possible at all.&#xD;&#xA;Thanks for your help in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/08M8I.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/etMwM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30887" PostHistoryTypeId="1" PostId="10605" RevisionGUID="2e4c020e-1b73-47b9-aa00-7cda92c7efd1" CreationDate="2021-01-29T10:39:38.597" UserId="13273" Text="computing sheered perspective projection matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="30888" PostHistoryTypeId="3" PostId="10605" RevisionGUID="2e4c020e-1b73-47b9-aa00-7cda92c7efd1" CreationDate="2021-01-29T10:39:38.597" UserId="13273" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30889" PostHistoryTypeId="5" PostId="10605" RevisionGUID="c5112d33-73f2-46ee-b603-eea8ea87136a" CreationDate="2021-01-29T10:51:06.760" UserId="13273" Comment="edited body; edited title" Text="is it possible to calculate a &quot;projection matrix&quot; which is sheared as well?&#xD;&#xA;the usual perspective projection matrix forms a pyramid where the near clipping plane is rectangular.&#xD;&#xA;I have 4 lines which represents the edges of the pyramid in general. But the clipping plane is not orthogonal to the view direction (see picture 1)&#xD;&#xA;&#xD;&#xA;**Picture 1: view onto the projected area from above. Also from the side direction it will look like this**&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;By looking from the view position to the near clipping plane / image plane it would look like picture 2.&#xD;&#xA;&#xD;&#xA;**Picture 2: the view from the view position onto the scene**&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The image plane is restricted to be rectangular. Only from the view position its shape will look non rectangular. &#xD;&#xA;&#xD;&#xA;Now lets look at the parameters which are known:&#xD;&#xA;&#xD;&#xA; 1. all 4 corners of the image plane&#xD;&#xA; 2. the view position&#xD;&#xA; 3. the far plane distance&#xD;&#xA; &#xD;&#xA;so my task is to calculate this projection matrix, but I've no idea how to start or if it is possible at all.&#xD;&#xA;Thanks for your help in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/08M8I.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/etMwM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30890" PostHistoryTypeId="4" PostId="10605" RevisionGUID="c5112d33-73f2-46ee-b603-eea8ea87136a" CreationDate="2021-01-29T10:51:06.760" UserId="13273" Comment="edited body; edited title" Text="computing sheared perspective projection matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="30891" PostHistoryTypeId="2" PostId="10606" RevisionGUID="23f75267-ec94-4da2-a2cb-e174f293ae03" CreationDate="2021-01-29T12:05:16.953" UserId="13095" Text="&gt; Now, when reading other questions and articles about it, they always say, any simple operation, + - * / , would be a floating-point operation, which makes sense in terms of the word itself&#xD;&#xA;&#xD;&#xA;This is basically what is meant when talking about floating-point operations although I would exclude the division since it takes much longer than the other operations (see below).&#xD;&#xA;&#xD;&#xA;&gt; BUT: A multiplication is (obviously) often &quot;far&quot; more (calculating) than an addition, isn't it?! (Apart from the sheer size of the calculation)&#xD;&#xA;&#xD;&#xA;Most modern processors can usually calculate additions and multiplications equally fast. Even though the numbers are for CPUs and not for GPUs, you can take a look at the corresponding commands in the [Intel intrinsics guide](https://software.intel.com/sites/landingpage/IntrinsicsGuide/). A GPU shouldn't behave too different in this matter. Here are some examples:&#xD;&#xA;&#xD;&#xA;- [addition](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_ps&amp;expand=3928,3928,133)&#xD;&#xA;- [subtraction](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_ps&amp;expand=3928,3928,133,5727)&#xD;&#xA;- [multiplication](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_ps&amp;expand=3928,3928)&#xD;&#xA;- [division](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_div_ps&amp;expand=3928,3928,133,5727,2156)&#xD;&#xA;&#xD;&#xA;As you can see, the numbers of the Skylake processor are all identical except for the division. &#xD;&#xA;&#xD;&#xA;In case you wonder what those numbers mean: Latency is the number of cycles that are necessary to calculate the result and throughput is the inverse number of operations you can start per cycle. So for addition, subtraction and multiplication, a skylake processor can start the calculation of 2 operations per cycle and get the results 4 cycles later. This means that you can actually have 8 of those operations in progress if they do not depend on each other. &#xD;&#xA;&#xD;&#xA;Knowing this it is easy to see, that divisions take much longer to compute. This is why you should always calculate the inverse and multiply it instead if you need to divide a bunch of numbers by the same value.&#xD;&#xA;&#xD;&#xA;&gt; BUT: A multiplication is (obviously) often &quot;far&quot; more (calculating) than an addition, isn't it?! (Apart from the sheer size of the calculation)&#xD;&#xA;&gt;&#xD;&#xA;&gt;Following, just a simple example for demonstration:&#xD;&#xA;&gt;&#xD;&#xA;&gt;5+5= 5+5&#xD;&#xA;&gt;&#xD;&#xA;&gt;5*5= 5+5+5+5+5&#xD;&#xA;&#xD;&#xA;Well, this would be very inefficient. If you are curious how a computer actually performs a multiplication efficiently, take a look into [this question](https://stackoverflow.com/questions/3060064/how-computer-multiplies-2-numbers)" ContentLicense="CC BY-SA 4.0" />
  <row Id="30892" PostHistoryTypeId="2" PostId="10607" RevisionGUID="74a731b2-782d-4434-a816-34b7daf60c93" CreationDate="2021-01-29T12:20:23.573" UserId="15658" Text="# Context&#xD;&#xA;I am working on project for implementing and user test a World-in-Miniature (WIM) interface for VR. A WIM essentially is a replica of the scene the user is currently in, but in miniature. &#xD;&#xA;&#xD;&#xA;# Features&#xD;&#xA;&#xD;&#xA;- the user can have control over the WIMs position, orientation, scale. Thus, allowing to dynamically view the scene from multiple viewpoints.&#xD;&#xA;- the user can choose from different methods to remove geometry from the scene, particularly to remove occluders such as wall of building floor, to view the objects in the room. &#xD;&#xA;- the user can interact with certain objects objects in the scene, by simply interacting with the proxy objects in the WIM replica.&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;What I am interested in is a way to take a scene of relatively complex geometry and automatically render a miniature replica of it for example in a small rectangle in from of the user (i.e sort of like a 3D map). It would have to be real-time, and performed during run-time, as the viewpoint of the user towards the WIM will change during interaction (e.g. if he for example rotates, or scales up, or down the current rendered selection).&#xD;&#xA;&#xD;&#xA;# Examples&#xD;&#xA;&#xD;&#xA;- Original Paper: https://www.youtube.com/watch?v=Ytc3ix-He4E&#xD;&#xA;- An example I found running on an Oculus: https://www.youtube.com/watch?v=zOTx_CWsR7g&amp;t=105s&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30893" PostHistoryTypeId="1" PostId="10607" RevisionGUID="74a731b2-782d-4434-a816-34b7daf60c93" CreationDate="2021-01-29T12:20:23.573" UserId="15658" Text="Render Duplicate Miniature Scene Replica" ContentLicense="CC BY-SA 4.0" />
  <row Id="30894" PostHistoryTypeId="3" PostId="10607" RevisionGUID="74a731b2-782d-4434-a816-34b7daf60c93" CreationDate="2021-01-29T12:20:23.573" UserId="15658" Text="|geometry|mesh|virtual-reality|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30895" PostHistoryTypeId="2" PostId="10608" RevisionGUID="a5de8fcc-b807-4a3f-9b43-59b14d065bdd" CreationDate="2021-01-29T14:18:11.680" UserId="209" Text="Just to add to [whychmaster's reply][1], in my experience, on a GPU, a floating-point operation, when used in quoting FLOPS (floating-point operations per second) benchmark figures will refer to Addition (equiv subtraction) and Multiplication.&#xD;&#xA;&#xD;&#xA;The other standard IEEE operators, division + sqrt, are more computationally expensive and so unlikely to be included in the figure. *(Note that, there is often HW support in GPUs for accelerating operations like 1/x, 1/sqrt(x) etc, perhaps to make them as (or nearly as) fast as muls &amp; adds)*&#xD;&#xA;&#xD;&#xA;Having said that, it is very likely that a GPU will actually implement a Fused Multipy-Add operation, FMAD, i.e. do  A * B + C in &quot;one step&quot; as this is &#xD;&#xA;&#xD;&#xA; 1. more accurate than doing separate multiply and add instructions&#xD;&#xA; 2. is faster than separate ops&#xD;&#xA; 3. is about the same silicon cost&#xD;&#xA; 4. is a very common building block of CG operations (e.g dot products, convolutions)&#xD;&#xA;&#xD;&#xA;I suspect that in quoted figures, though, an FMAD would be considered 2 operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/10606/209" ContentLicense="CC BY-SA 4.0" />
  <row Id="30897" PostHistoryTypeId="2" PostId="10610" RevisionGUID="54b837a4-36eb-441a-9177-691bd217652a" CreationDate="2021-01-29T15:28:15.677" UserId="13456" Text="This is an answer to your comment rather than the title of your question. It can be considered as a partial answer.&#xD;&#xA;&#xD;&#xA;The bias in path tracers are introduced by the estimators.&#xD;&#xA;For example, think of the following two equations: &#xD;&#xA;$$ I = \int_{\Omega} f(\omega) d\omega $$&#xD;&#xA;$$ F = \frac{1}{N} \sum_{i}^{N} \frac{f(\omega)}{p(\omega)}$$ where $p: \Omega \to R$.&#xD;&#xA;It should be evident that as the number of samples N increases, the function $F$, ie the estimator, outputs values that are closer to $I$.&#xD;&#xA;&#xD;&#xA;The unbiased estimator satisfies the following $E[F_N] \approx I$ or $\lim_{N\to\infty}F_N=I$, that is the expected value of the estimator matches the desired outcome in $I$ as the number of samples goes to infinity.&#xD;&#xA;The biased estimator does not offer such a guarantee.&#xD;&#xA;You can read more from [D. Van Antwerpen's master thesis](http://resolver.tudelft.nl/uuid:4a5be464-dc52-4bd0-9ede-faefdaff8be6.), I am giving the full citation in case the link goes away:&#xD;&#xA; &#xD;&#xA;Van Antwerpen, Dietger. “Unbiased Physically Based Rendering on the GPU.” Master of Science in Computer Science, Delft University of Technology, 2010.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30900" PostHistoryTypeId="2" PostId="10611" RevisionGUID="d6eac6bd-e838-4849-9a0a-a4da7788bc83" CreationDate="2021-01-29T16:10:38.590" UserId="7952" Text="The first thing that jumped into my head when I saw this was Multiview. You are probably already using it to render the scene if you are rendering to VR anyway. (if not...you should)&#xD;&#xA;&#xD;&#xA;For those that don't know about Multiview:&#xD;&#xA;This is a way to cast the same draw calls to multiple layers of a framebuffer image with a single draw call. It allows you to use a mask for which layers to broadcast to, so it is easy to turn broadcasting on and off (making it quick and easy to turn the WIM on and off). A new variable is available in shaders that allows the code to make adjustments for the view/projection matrix usually but the code can get much more sophisticated as needed. Its only downside is it requires relatively modern hardware.&#xD;&#xA;&#xD;&#xA;Using multiview the cpu would set up 4 view matrices, two for the VR left and right eye, and two for the WIM left and right eye. The view could then add a constant scale factor so the WIM is sized to fit, and the camera can be positioned as needed.&#xD;&#xA;&#xD;&#xA;To improve performance you will probably want to break it up into multiple passes where one pass renders everything that is common to both scenes and the second pass renders more expensive effects for the main scene. Again, as needed.&#xD;&#xA;&#xD;&#xA;I won't go into the details of implementing multivew but googling multiview for the API you are using should give some good tutorials." ContentLicense="CC BY-SA 4.0" />
  <row Id="30901" PostHistoryTypeId="5" PostId="10611" RevisionGUID="5526a1b4-4078-4b09-ba38-4a729e279be4" CreationDate="2021-01-29T16:20:51.187" UserId="7952" Comment="added 100 characters in body" Text="The first thing that jumped into my head when I saw this was Multiview. You are probably already using it to render the scene if you are rendering to VR anyway. (if not...you should)&#xD;&#xA;&#xD;&#xA;For those that don't know about Multiview:&#xD;&#xA;This is a way to cast the same draw calls to multiple layers of a framebuffer image with a single draw call. It allows you to use a mask for which layers to broadcast to, so it is easy to turn broadcasting on and off (making it quick and easy to turn the WIM on and off). A new variable is available in shaders that allows the code to make adjustments for the view/projection matrix usually but the code can get much more sophisticated as needed. Its only downside is it requires relatively modern hardware.&#xD;&#xA;&#xD;&#xA;Using multiview the cpu would set up 4 view matrices, two for the VR left and right eye, and two for the WIM left and right eye. The view could then add a constant scale factor so the WIM is sized to fit, and the camera can be positioned as needed.&#xD;&#xA;&#xD;&#xA;To improve performance you will probably want to break it up into multiple passes where one pass renders everything that is common to both scenes and the second pass renders more expensive effects for the main scene. Again, as needed.&#xD;&#xA;&#xD;&#xA;The last step would be merging the two scenes, probably just by bliting the WIM over the main scene using a unique background color of the WIM as a clear alpha color.&#xD;&#xA;&#xD;&#xA;I won't go into the details of implementing multivew but googling multiview for the API you are using should give some good tutorials.&#xD;&#xA;&#xD;&#xA;I just noticed that multiview is a opengl/vulkanism I'm not sure what the directx equivalent is." ContentLicense="CC BY-SA 4.0" />
  <row Id="30902" PostHistoryTypeId="5" PostId="10611" RevisionGUID="5d31fdb9-3bc6-46c8-ab8d-7de235bc8384" CreationDate="2021-01-29T16:52:21.040" UserId="7952" Comment="added 304 characters in body" Text="The first thing that jumped into my head when I saw this was Multiview. You are probably already using it to render the scene if you are rendering to VR anyway. (if not...you should)&#xD;&#xA;&#xD;&#xA;For those that don't know about Multiview:&#xD;&#xA;This is a way to cast the same draw calls to multiple layers of a framebuffer image with a single draw call. It allows you to use a mask for which layers to broadcast to, so it is easy to turn broadcasting on and off (making it quick and easy to turn the WIM on and off). A new variable is available in shaders that allows the code to make adjustments for the view/projection matrix usually but the code can get much more sophisticated as needed. Its only downside is it requires relatively modern hardware.&#xD;&#xA;&#xD;&#xA;Using multiview the cpu would set up 4 view matrices, two for the VR left and right eye, and two for the WIM left and right eye. The view could then add a constant scale factor so the WIM is sized to fit, and the camera can be positioned as needed.&#xD;&#xA;&#xD;&#xA;To improve performance you will probably want to break it up into multiple passes where one pass renders everything that is common to both scenes and the second pass renders more expensive effects for the main scene. Again, as needed.&#xD;&#xA;&#xD;&#xA;The last step would be merging the two scenes, probably just by bliting the WIM over the main scene using a unique background color of the WIM as a clear alpha color.&#xD;&#xA;&#xD;&#xA;I won't go into the details of implementing multivew but googling multiview for the API you are using should give some good tutorials.&#xD;&#xA;&#xD;&#xA;Scene interaction is simplified since the CPU only really ever works with a single scene and the only tricky part is figuring out whether the user is interacting with the WIM or the main scene. This would effect how the ray is being cast into the scene (if you use ray casting for selecting objects).&#xD;&#xA;&#xD;&#xA;I just noticed that multiview is a opengl/vulkanism I'm not sure what the directx equivalent is." ContentLicense="CC BY-SA 4.0" />
  <row Id="30903" PostHistoryTypeId="50" PostId="9781" RevisionGUID="1dc47902-2314-4c22-8c9a-250280f98a14" CreationDate="2021-01-29T17:08:10.870" UserId="-1" />
  <row Id="30906" PostHistoryTypeId="50" PostId="10177" RevisionGUID="d60cdd23-166e-4256-af41-28346b12f420" CreationDate="2021-01-30T02:07:05.680" UserId="-1" />
  <row Id="30907" PostHistoryTypeId="50" PostId="9791" RevisionGUID="ac988997-cf32-4dbf-8dfb-13bf2b2191f5" CreationDate="2021-01-30T21:04:10.557" UserId="-1" />
  <row Id="30909" PostHistoryTypeId="2" PostId="10612" RevisionGUID="14f0ff93-9933-4422-8ca7-dfc854ad0235" CreationDate="2021-01-31T11:40:33.157" UserId="9169" Text="I have a 2D layer/section containing the 2D polygons colored in shades of **green**. &#xD;&#xA;I have another layer containing the 2D polygons colored in shades of **blue**.&#xD;&#xA;&#xD;&#xA;[![Two layers of 2D polygons][1]][1]&#xD;&#xA;&#xD;&#xA;I intend to figure out how different are the two layers. Maybe extracting the layers differential. Can anybody provide an **algorithm**, **library** or a **hint**? I took a look at [CGAL](https://doc.cgal.org/latest/Manual/packages.html), but not quite sure which package to try out. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/87ESC.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="30910" PostHistoryTypeId="1" PostId="10612" RevisionGUID="14f0ff93-9933-4422-8ca7-dfc854ad0235" CreationDate="2021-01-31T11:40:33.157" UserId="9169" Text="Differential or intersection of islands of 2D polygons in different layers" ContentLicense="CC BY-SA 4.0" />
  <row Id="30911" PostHistoryTypeId="3" PostId="10612" RevisionGUID="14f0ff93-9933-4422-8ca7-dfc854ad0235" CreationDate="2021-01-31T11:40:33.157" UserId="9169" Text="|algorithm|computational-geometry|geometry|mesh|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30912" PostHistoryTypeId="2" PostId="10613" RevisionGUID="6855bfe2-6362-4ae7-b1d3-cc0d65472c92" CreationDate="2021-01-31T16:11:06.033" UserId="15668" Text="I am writing a Raytracer and generating rays from the camera. I have a working program but slightly confused about the linear algebra concepts involved in transforming the ray from camera space to world space. I already have the camera position in world coordinates. So, only need to transform the direction vector. I think there are two ways to achieve this, &#xD;&#xA;&#xD;&#xA;**a) Directly transforming the direction vector:**&#xD;&#xA;&#xD;&#xA; The direction vector can be built as, &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;`direction vector = point on film - camera position`&#xD;&#xA;&#xD;&#xA;The camera is at the origin, so the above would reduce to the coordinates of the point on the film. Now, we can write this direction vector in homogeneous form and apply the camera to world transformation. This should give us the direction vector for the ray in world space. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**b) Transform the origin and point on film:**&#xD;&#xA;&#xD;&#xA;The origin's position vector is at zero and the position vector of a point on the film is the point's coordinates. We can apply the camera to world transformation to these and this would give us two position vectors in world space: the camera's position vector and the film point's position vector. Then, the direction vector in world space can be directly built as,&#xD;&#xA;&#xD;&#xA;`direction vector = point on film (world space) - camera position (world space)`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Mathematically, the first approach is to multiply the direction vector in camera space by the camera to the world (4x4) matrix, and this would be my answer. However, based on the second approach, I should do the same thing (multiply by 4x4 matrix) and then subtract by the camera's position in world space. &#xD;&#xA;&#xD;&#xA;I tried programming both strategies and the second approach seems to give the right answer. What's wrong with my first approach?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30913" PostHistoryTypeId="1" PostId="10613" RevisionGUID="6855bfe2-6362-4ae7-b1d3-cc0d65472c92" CreationDate="2021-01-31T16:11:06.033" UserId="15668" Text="Transforming a ray from camera space to world space" ContentLicense="CC BY-SA 4.0" />
  <row Id="30914" PostHistoryTypeId="3" PostId="10613" RevisionGUID="6855bfe2-6362-4ae7-b1d3-cc0d65472c92" CreationDate="2021-01-31T16:11:06.033" UserId="15668" Text="|raytracing|transformations|pathtracing|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30915" PostHistoryTypeId="2" PostId="10614" RevisionGUID="4e717c57-c8a3-4c01-ac43-a38eafc4044e" CreationDate="2021-01-31T20:19:27.370" UserId="10370" Text="Have been searching a lot for a good spline interpolation library in cpp, came across one, which is the famous Eigen library , having the unsupported counterpart for spline fitting.&lt;[Here][1]&gt;.&#xD;&#xA;I need spline fitting API that also accepts derivatives.&#xD;&#xA;&#xD;&#xA;Eigen's **InterpolateWithDerivatives** API claim to offer that but it is not without bugs. What alternatives do I have?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://eigen.tuxfamily.org/dox/unsupported/structEigen_1_1SplineFitting.html#a7bd937fdcfa168dbdc27932886a4da9f" ContentLicense="CC BY-SA 4.0" />
  <row Id="30916" PostHistoryTypeId="1" PostId="10614" RevisionGUID="4e717c57-c8a3-4c01-ac43-a38eafc4044e" CreationDate="2021-01-31T20:19:27.370" UserId="10370" Text="Spline interpolation library in cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="30917" PostHistoryTypeId="3" PostId="10614" RevisionGUID="4e717c57-c8a3-4c01-ac43-a38eafc4044e" CreationDate="2021-01-31T20:19:27.370" UserId="10370" Text="|c++|geometry|interpolation|curve|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30918" PostHistoryTypeId="2" PostId="10615" RevisionGUID="c5ff46c2-8751-4245-b720-29821fc1a83e" CreationDate="2021-02-01T08:23:42.407" UserId="11747" Text="In CGAL, there is the [Arrangement package][1] that allows to build a topologically valid planar partition given a set of segments, and the [Regularized Boolean Set-Operations][2] that provides boolean operations between polygons. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://doc.cgal.org/latest/Arrangement_on_surface_2/index.html#Chapter_2D_Arrangements&#xD;&#xA;  [2]: https://doc.cgal.org/latest/Boolean_set_operations_2/index.html#Chapter_2D_Regularized_Boolean_Set-Operations" ContentLicense="CC BY-SA 4.0" />
  <row Id="30919" PostHistoryTypeId="2" PostId="10616" RevisionGUID="32202837-215a-4466-a5ce-caf91e4997b6" CreationDate="2021-02-01T15:24:17.770" UserId="4766" Text="[The OpenGL spec](https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf) section 14.6.1 spells it out&#xD;&#xA;&#xD;&#xA;&gt; ## 14.6.1 Basic Polygon Rasterization&#xD;&#xA;&gt;&#xD;&#xA;&gt; The first step of polygon rasterization is to determine if the polygon is back-facing&#xD;&#xA;or front-facing. This determination is made based on the sign of the (clipped or&#xD;&#xA;unclipped) polygon’s area computed in window coordinates. One way to compute&#xD;&#xA;this area is&#xD;&#xA;&gt;&#xD;&#xA;&gt; [![enter image description here][1]][1]&#xD;&#xA;&gt;&#xD;&#xA;&gt; where  = 1 when the clip control origin is `LOWER_LEFT` and  = −1 when the&#xD;&#xA;origin is `UPPER_LEFT`, *x&lt;sup&gt;i&lt;/sup&gt;&lt;sub&gt;w&lt;/sub&gt;* and *y&lt;sup&gt;i&lt;/sup&gt;&lt;sub&gt;w&lt;/sub&gt;* are the *x* and *y* window coordinates of the *i*th&#xD;&#xA;vertex of the *n*-vertex polygon (vertices are numbered starting at zero for purposes&#xD;&#xA;of this computation) and *i* ⊕ 1 is (*i* + 1) mod *n*. The interpretation of the sign of&#xD;&#xA;this value is controlled with&#xD;&#xA;&gt;&#xD;&#xA;&gt; ```&#xD;&#xA;&gt; void FrontFace( enum dir );&#xD;&#xA;&gt; ```&#xD;&#xA;&gt;&#xD;&#xA;&gt; Setting *dir* to `CCW` (corresponding to counter-clockwise orientation of the projected polygon in window coordinates) uses *a* as computed above. Setting *dir* to&#xD;&#xA;`CW` (corresponding to clockwise orientation) indicates that the sign of *a* should be&#xD;&#xA;reversed prior to use. Front face determination requires one bit of state, and is&#xD;&#xA;initially set to `CCW`.&#xD;&#xA;&gt;&#xD;&#xA;&gt; If the sign of *a* (including the possible reversal of this sign as determined by&#xD;&#xA;**FrontFace**) is positive, the polygon is front-facing; otherwise, it is back-facing.&#xD;&#xA;This determination is used in conjunction with the **CullFace** enable bit and mode&#xD;&#xA;value to decide whether or not a particular polygon is rasterized. The **CullFace**&#xD;&#xA;mode is set by calling&#xD;&#xA;&gt;&#xD;&#xA;&gt; ```&#xD;&#xA;&gt; void CullFace( enum mode );&#xD;&#xA;&gt; ```&#xD;&#xA;&gt;&#xD;&#xA;&gt; *mode* must be `FRONT`, `BACK` or `FRONT_AND_BACK`. Culling is enabled or disabled&#xD;&#xA;by calling **Enable** or **Disable** with target `CULL_FACE`. Front-facing polygons are&#xD;&#xA;rasterized if either culling is disabled or the **CullFace** mode is `BACK` while back facing polygons are rasterized only if either culling is disabled or the **CullFace**&#xD;&#xA;mode is `FRONT`. The initial setting of the **CullFace** mode is `BACK`. Initially, culling&#xD;&#xA;is disabled&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tFs8W.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30920" PostHistoryTypeId="2" PostId="10617" RevisionGUID="5d959e5d-9f2f-446f-8be7-66846fd21548" CreationDate="2021-02-02T09:06:54.083" UserId="209" Text="So you have a series of points and, at each point, a supplied derivative?&#xD;&#xA; &#xD;&#xA;Is a piecewise cubic sufficient or does it need higher derivative continuity?  If the former is ok, then [Cubic Hermite Splines][1] will do the job. (If you need, they can be trivially mapped into cubic Beziers)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline" ContentLicense="CC BY-SA 4.0" />
  <row Id="30921" PostHistoryTypeId="2" PostId="10618" RevisionGUID="8f98da27-e7c4-4af0-836b-41a821016570" CreationDate="2021-02-02T09:50:05.823" UserId="13154" Text="Perhaps this is more computational geometry, but here goes:&#xD;&#xA;&#xD;&#xA;I have a 2D [SDF][1] describing my shape, but it's fine to think of it as a black/white image (black=&quot;inside&quot; white=&quot;outside&quot;).&#xD;&#xA;&#xD;&#xA;I want to generate a small set of rectangles (say, 8 of them) covering the image, which are allowed to overlap, and which minimize the amount of error. Error would be any leftover &quot;black&quot; areas of the image that are not covered.&#xD;&#xA;&#xD;&#xA;The image could be convex, have holes, etc. It is general.&#xD;&#xA;&#xD;&#xA;I realize that minimal rectangle covering is NP-hard, though that's not exactly what I'm asking for: I'm asking for minimizing error given a finite set of rectangles to work with. Maybe it's just as hard though; not sure.&#xD;&#xA;&#xD;&#xA;Anyway, I do not need to find the perfect solution; decent heuristics would be fine.&#xD;&#xA;&#xD;&#xA;I could imagine some pretty general &quot;greedy search&quot; traversal of the state space, but wondered if there were any tricks anyone knows of.&#xD;&#xA;&#xD;&#xA;Aside: I've also looked at several papers for &quot;rectangular decomposition&quot;, and &quot;minimal dissection&quot;, but those problems generally assume I want disjoint rectangles. Disjoint would be okay, but really I want maximal coverage while allowing overlap.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Signed_distance_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="30922" PostHistoryTypeId="1" PostId="10618" RevisionGUID="8f98da27-e7c4-4af0-836b-41a821016570" CreationDate="2021-02-02T09:50:05.823" UserId="13154" Text="Good rectangular covering of an SDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="30923" PostHistoryTypeId="3" PostId="10618" RevisionGUID="8f98da27-e7c4-4af0-836b-41a821016570" CreationDate="2021-02-02T09:50:05.823" UserId="13154" Text="|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30924" PostHistoryTypeId="2" PostId="10619" RevisionGUID="53ae5ff0-2f6f-4894-ad6e-7d5864272bae" CreationDate="2021-02-02T11:23:56.593" UserId="15679" Text="I need to create a decaling into a surface like a mesh, and to avoid Z-fighting I've been using Stencil Buffer to Turn-off depth test and make the decaling over the surface the Stencil Op permits. In fact that decaling fails when we turn the camera in a such way that the viewer has more than one surface point &quot;competing&quot; for the same pixel. This happens when the surface isn't a plane, in our example we have a mesh representing a terrain. The problem is that we turn-off the depth test and the decaling object is always visible, even when we have a surface point closer to the camera. Is there someone here that had the same problem ? Do I have to quit stencil solution to avoid Z-fighting ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30925" PostHistoryTypeId="1" PostId="10619" RevisionGUID="53ae5ff0-2f6f-4894-ad6e-7d5864272bae" CreationDate="2021-02-02T11:23:56.593" UserId="15679" Text="Problem using Decaling with Stencil to avoid Z-fighting" ContentLicense="CC BY-SA 4.0" />
  <row Id="30926" PostHistoryTypeId="3" PostId="10619" RevisionGUID="53ae5ff0-2f6f-4894-ad6e-7d5864272bae" CreationDate="2021-02-02T11:23:56.593" UserId="15679" Text="|opengl|rendering|z-buffer|stencil-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30927" PostHistoryTypeId="10" PostId="10595" RevisionGUID="1ec4cbb2-445c-4729-8843-69520b934ba7" CreationDate="2021-02-02T11:28:45.857" UserId="13095" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[1493],&quot;Voters&quot;:[{&quot;Id&quot;:209,&quot;DisplayName&quot;:&quot;Simon F&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="30928" PostHistoryTypeId="2" PostId="10620" RevisionGUID="f991d914-2800-4a96-bb38-3dc0bb4ea242" CreationDate="2021-02-02T14:36:53.533" UserId="9581" Text="I am a bit novice in C++ so I apologize in advance if my question is a bit simple.&#xD;&#xA;&#xD;&#xA;I want to use Intel Open Image Denoise (OIDN) in a path tracing program that I am writing/executing in Qt Creator but I'm not sure how to do it. I would appreciate if someone can write the steps I should follow in order to use OIDN for denoising. Also, how can I convert an image stored in an Eigen 1-D array to the format that OIDN uses?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30929" PostHistoryTypeId="1" PostId="10620" RevisionGUID="f991d914-2800-4a96-bb38-3dc0bb4ea242" CreationDate="2021-02-02T14:36:53.533" UserId="9581" Text="How to use Intel Open Image Denoise in Qt Creator to denoise noisy Monte Carlo renderings?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30930" PostHistoryTypeId="3" PostId="10620" RevisionGUID="f991d914-2800-4a96-bb38-3dc0bb4ea242" CreationDate="2021-02-02T14:36:53.533" UserId="9581" Text="|raytracing|rendering|pathtracing|c++|denoise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30935" PostHistoryTypeId="2" PostId="10622" RevisionGUID="a925b700-349b-4d92-95ee-aa6aade295c7" CreationDate="2021-02-02T20:40:57.513" UserId="9581" Text="Given a surface `Normal` vector of an intersection point, how can one generate a random direction vector that is guaranteed to be in the visible hemisphere? The way I am currently doing this is to sample a random direction vector `d` and `dot` it with the `Normal` and keep that vector if the `dot` product is greater than 0. This method is not guaranteed to generate a vector in the visible hemisphere of BRDF as ~50% of the random vectors would have a `0` `dot` product result. &#xD;&#xA;&#xD;&#xA;I saw somewhere that there is a way to transform the randomly generated vector `d` to place it in the visible hemisphere using a transformation matrix but I don't know how to do it. Can someone write a [pseudo]code for how one generate a direction vector using the transformation method?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30936" PostHistoryTypeId="1" PostId="10622" RevisionGUID="a925b700-349b-4d92-95ee-aa6aade295c7" CreationDate="2021-02-02T20:40:57.513" UserId="9581" Text="Path tracing: How to ensure we are sampling a direction vector within the visible hemisphere of a surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30937" PostHistoryTypeId="3" PostId="10622" RevisionGUID="a925b700-349b-4d92-95ee-aa6aade295c7" CreationDate="2021-02-02T20:40:57.513" UserId="9581" Text="|rendering|transformations|pathtracing|brdf|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30938" PostHistoryTypeId="5" PostId="10622" RevisionGUID="53c556a0-6d5a-462f-bd32-b19f9e1c4ba7" CreationDate="2021-02-02T20:50:28.557" UserId="9581" Comment="added 12 characters in body" Text="Given a surface `Normal` vector of an intersection point, how can one generate a random direction vector that is guaranteed to be in the visible hemisphere? The way I am currently doing this is to sample a random direction vector `d` and `dot` it with the `Normal` and keep that vector if the `dot` product is greater than 0. This method is not guaranteed to generate a vector in the visible hemisphere of BRDF as ~50% of the random vectors would have a `0` or negative `dot` product result. &#xD;&#xA;&#xD;&#xA;I saw somewhere that there is a way to transform the randomly generated vector `d` to place it in the visible hemisphere using a transformation matrix but I don't know how to do it. Can someone write a [pseudo]code for how one generate a direction vector using the transformation method?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30939" PostHistoryTypeId="2" PostId="10623" RevisionGUID="1f859d4b-9a8d-4f9d-af64-9d528fbdb20a" CreationDate="2021-02-02T20:57:33.453" UserId="506" Text="If it’s on the wrong side of the normal, you don’t have to throw it away—negating it will give you a vector that’s in the visible hemisphere." ContentLicense="CC BY-SA 4.0" />
  <row Id="30940" PostHistoryTypeId="5" PostId="10623" RevisionGUID="fae2302f-134e-4bcf-b72a-4e743ba86595" CreationDate="2021-02-02T21:37:58.557" UserId="506" Comment="added direction example" Text="If it’s on the wrong side of the normal, you don’t have to throw it away—negating it will give you a vector that’s in the visible hemisphere.&#xD;&#xA;&#xD;&#xA;Answering your comment, to get a vector that’s within some angle θ of the normal, this should work (GLSL):&#xD;&#xA;&#xD;&#xA;    vec3 direction(vec3 normal, vec2 randomValues, float maxTheta) {&#xD;&#xA;        // pick an orthogonal tangent vector using the method described here: http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts&#xD;&#xA;        vec3 tangent = (normal.x &gt; normal.z) ? vec3(-normal.y, normal.x, 0.0) : vec3(0.0, -normal.z, normal.y);&#xD;&#xA;        // and a bitangent vector orthogonal to both&#xD;&#xA;        vec3 bitangent = cross(normal, tangent);&#xD;&#xA;&#xD;&#xA;        float phi = 2.0 * PI * randomValues.x;&#xD;&#xA;        float theta = randomValues.y * maxTheta;&#xD;&#xA;        float sinTheta = sin(theta);&#xD;&#xA;        return tangent * cos(phi) * sinTheta + bitangent * sin(phi) * sinTheta + normal * cos(theta);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="30944" PostHistoryTypeId="5" PostId="10618" RevisionGUID="0c21dec3-bf85-4130-ae3d-ef794273422a" CreationDate="2021-02-03T02:02:37.040" UserId="13154" Comment="add image" Text="Perhaps this is more computational geometry, but here goes:&#xD;&#xA;&#xD;&#xA;I have a 2D [SDF][1] describing my shape, but it's fine to think of it as a black/white image (black=&quot;inside&quot; white=&quot;outside&quot;).&#xD;&#xA;&#xD;&#xA;I want to generate a small set of rectangles (say, 8 of them) covering the image, which are allowed to overlap, and which minimize the amount of error. Error would be any leftover &quot;black&quot; areas of the image that are not covered.&#xD;&#xA;&#xD;&#xA;The image could be convex, have holes, etc. It is general.&#xD;&#xA;&#xD;&#xA;I realize that minimal rectangle covering is NP-hard, though that's not exactly what I'm asking for: I'm asking for minimizing error given a finite set of rectangles to work with. Maybe it's just as hard though; not sure.&#xD;&#xA;&#xD;&#xA;Anyway, I do not need to find the perfect solution; decent heuristics would be fine.&#xD;&#xA;&#xD;&#xA;I could imagine some pretty general &quot;greedy search&quot; traversal of the state space, but wondered if there were any tricks anyone knows of.&#xD;&#xA;&#xD;&#xA;Aside: I've also looked at several papers for &quot;rectangular decomposition&quot;, and &quot;minimal dissection&quot;, but those problems generally assume I want disjoint rectangles. Disjoint would be okay, but really I want maximal coverage while allowing overlap.&#xD;&#xA;&#xD;&#xA;**Edit** Here is an example:&#xD;&#xA;&#xD;&#xA;Target image:&#xD;&#xA;&#xD;&#xA;[![target image][2]][2]&#xD;&#xA;&#xD;&#xA;Covering with 4 rectangles (red, green, blue, yellow):&#xD;&#xA;&#xD;&#xA;[![covered image][3]][3]&#xD;&#xA;&#xD;&#xA;Any uncovered black pixels are the &quot;error&quot;.&#xD;&#xA;No white pixels are allowed to get covered.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Signed_distance_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/0AGpl.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/neYfG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30947" PostHistoryTypeId="2" PostId="10625" RevisionGUID="76e88668-10bf-43e2-bdde-0518172fcd6a" CreationDate="2021-02-03T05:35:57.397" UserId="15470" Text="&gt; Now, we can write this direction vector in homogeneous form and apply the camera to world transformation. This should give us the direction vector for the ray in world space.&#xD;&#xA;&#xD;&#xA;That is the problem. When transforming a *direction*, you must ensure the `w` coordinate is 0, so that it doesn't get translated by your camera-to-world matrix. What you're doing in the second method is that you're transforming the direction vector as a point, and then subtracting the camera's position, which effectively undoes the translation." ContentLicense="CC BY-SA 4.0" />
  <row Id="30948" PostHistoryTypeId="5" PostId="10619" RevisionGUID="8bcd1722-e6ce-4271-8d99-20685167efce" CreationDate="2021-02-03T11:24:01.233" UserId="15679" Comment="added 208 characters in body" Text="I need to create a decaling into a surface like a mesh, and to avoid Z-fighting I've been using Stencil Buffer to Turn-off depth test and make the decaling over the surface the Stencil Op permits. In fact that decaling fails when we turn the camera in a such way that the viewer has more than one surface point &quot;competing&quot; for the same pixel. This happens when the surface isn't a plane, in our example we have a mesh representing a terrain. The problem is that we turn-off the depth test and the decaling object is always visible, even when we have a surface point closer to the camera. Is there someone here that had the same problem ? Do I have to quit stencil solution to avoid Z-fighting ?&#xD;&#xA;&#xD;&#xA;Without problem: [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The Problem: [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3cGwK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zhVEv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30950" PostHistoryTypeId="2" PostId="10626" RevisionGUID="047d1dd7-c48e-43e4-acde-ae5b18b1141f" CreationDate="2021-02-03T14:37:31.590" UserId="7952" Text="It sounds like this code is using the stencil buffer to mask off the locations to draw the line. This isn't a &quot;typical&quot; decal approach. Normally the decal is draw directly into the scene and &quot;depth bias&quot; is turned on for the graphics state (OpenGL) or the graphics pipeline (Vulkan). Then turned off when done, again for OpenGL.&#xD;&#xA;&#xD;&#xA;A solution that doesn't change the current rendering approach (which i guessed at) is to use a depth buffer when rendering the terrain. Then pass that depth buffer as an input to your decal shader, read the depth buffer and compare it to the depth of your current fragment. Then discard the fragment if the depth test fails. Basically, it is doing depth buffering by hand. It isn't to hard to set up and there are lots of tutorials out there to help get you going.&#xD;&#xA;&#xD;&#xA;It also might be possible to just change the stencil buffer based on depth values this would be dependent on how the stencil is being generated. If it is regenerated each frame this could be a quick and easy solution.&#xD;&#xA;&#xD;&#xA;On the other hand, if you are drawing lines or polygons directly, then you really should look into using depth bias settings. Assuming you are using OpenGL this is turned on before rendering the decal then turned off after rendering it. The hardware then computes an offset depending on how far the camera is away from the object up to some limit (which is also programable). This approach would allow the depth testing to be left on, it is view independent so it works from any direction, and it would allow the decal to be textured.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30951" PostHistoryTypeId="5" PostId="10626" RevisionGUID="91693365-7e68-4d2b-81ea-c8ac5e732ee8" CreationDate="2021-02-03T14:50:04.190" UserId="7952" Comment="added 352 characters in body" Text="It sounds like this code is using the stencil buffer to mask off the locations to draw the line. This isn't a &quot;typical&quot; decal approach. Normally the decal is draw directly into the scene and &quot;depth bias&quot; is turned on for the graphics state (OpenGL) or the graphics pipeline (Vulkan). Then turned off when done, again for OpenGL.&#xD;&#xA;&#xD;&#xA;A solution that doesn't change the current rendering approach (which i guessed at) is to use a depth buffer when rendering the terrain. Then pass that depth buffer as an input to your decal shader, read the depth buffer and compare it to the depth of your current fragment. Then discard the fragment if the depth test fails. Basically, it is doing depth buffering by hand. It isn't to hard to set up and there are lots of tutorials out there to help get you going.&#xD;&#xA;&#xD;&#xA;It also might be possible to just change the stencil buffer based on depth values this would be dependent on how the stencil is being generated. If it is regenerated each frame this could be a quick and easy solution.&#xD;&#xA;&#xD;&#xA;On the other hand, if you are drawing lines or polygons directly, then you really should look into using depth bias settings. Assuming you are using OpenGL this is turned on before rendering the decal then turned off after rendering it. The hardware then computes an offset depending on how far the camera is away from the object up to some limit (which is also programable). This approach would allow the depth testing to be left on, it is view independent so it works from any direction, and it would allow the decal to be textured.&#xD;&#xA;&#xD;&#xA;Also: The issue described here isn't really z fighting. Z fighting usually occurs when two fragments are being rendered to the same location and quantization causes the fragments to &quot;fight&quot; for visibility. As the camera moves one of the two fragments wins the &quot;fight&quot;, but the winner keeps changing depending how much floating point error there is.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30955" PostHistoryTypeId="2" PostId="10628" RevisionGUID="5feceb1f-ce21-4575-b7a2-a94867f710f5" CreationDate="2021-02-03T15:19:30.807" UserId="13273" Text="I want to render a scene from multiple positions and orientations. I think the geometry shader is a good choice to not use the Vertex and tessellation shaders for each camera position again. So I want to do layered rendering. I already did that once, but this time I simultaneously want to use additional clip planes. Each camera position has its own clip planes, which should not be visible from other cameras. &#xD;&#xA;My question: is it possible to define clipPlanes (glClipPlane) for a specific layer? Or is it better to do that during the fragment shader step, by doing dot-product, check the sign and discard if necessary?&#xD;&#xA;Does I have other options (except: rendering the scene in a loop for each position / orientation)?&#xD;&#xA;&#xD;&#xA;Thanks a lot!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30956" PostHistoryTypeId="1" PostId="10628" RevisionGUID="5feceb1f-ce21-4575-b7a2-a94867f710f5" CreationDate="2021-02-03T15:19:30.807" UserId="13273" Text="OpenGL layered rendering with multiple additional clip planes per view" ContentLicense="CC BY-SA 4.0" />
  <row Id="30957" PostHistoryTypeId="3" PostId="10628" RevisionGUID="5feceb1f-ce21-4575-b7a2-a94867f710f5" CreationDate="2021-02-03T15:19:30.807" UserId="13273" Text="|opengl|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30958" PostHistoryTypeId="2" PostId="10629" RevisionGUID="d72bde29-09fc-437a-8425-3e64ffcfc1ea" CreationDate="2021-02-03T15:30:15.483" UserId="7952" Text="I spent many years doing hardware work creating CPU's for the &quot;big iron&quot; market. We considered a FLOP to be any instruction that requires the &quot;floating point execution unit&quot; inside the CPU to perform the calculation that another instruction has a dependency on. This unit used to be considered one of the most complex, slowest, and one of the most power hungry units inside the CPU. It could result in long stalls, lots of NOPS being inserted into the pipeline, lots of heat being generated, and the electric bill to go sky high.&#xD;&#xA;&#xD;&#xA;Much research later, the floating point units are much less power hungry, and can often be compared to the performance of a good integer execution unit. (last I heard research was combining the two into a flexible integer/floating unit)&#xD;&#xA;&#xD;&#xA;This all lead to measuring how many FLOPS a CPU (and nowadays the GPU) can perform in any given second, and more generally an entire system with many CPU's and GPU's working together. This measurement is still relevant because GPU's have turned number crunching into a fine art and while throughput is often dependent on memory architecture the raw number of FLOPs still tends to be a good measurement but can be very workflow dependent." ContentLicense="CC BY-SA 4.0" />
  <row Id="30959" PostHistoryTypeId="50" PostId="9146" RevisionGUID="bf177796-fb76-4602-b3d6-ea5054bdb193" CreationDate="2021-02-03T18:01:55.360" UserId="-1" />
  <row Id="30963" PostHistoryTypeId="2" PostId="10631" RevisionGUID="bc182fdd-9b35-4508-a64b-37f7e44e1188" CreationDate="2021-02-03T21:49:28.497" UserId="2654" Text="The GS is responsible for assigning a particular primitive to a particular layer. The GS is also responsible for writing values for `gl_ClipPlane` for a particular primitive. So the GS is perfectly capable of doing both of those things: assigning a primitive to a layer and doing the clip-plane computations for that layer.&#xD;&#xA;&#xD;&#xA;And if you need to &quot;deactivate&quot; a clip plane for a particular primitive assigned to a particular layer, just assign the `gl_ClipPlane[i]` for that to 1.0 for all of its vertices." ContentLicense="CC BY-SA 4.0" />
  <row Id="30969" PostHistoryTypeId="2" PostId="10633" RevisionGUID="6361fbd0-4a63-4aa7-88fb-dc8e148ad035" CreationDate="2021-02-04T00:03:52.813" UserId="15690" Text="I've been playing around with an idea, but I'm struggling with some of the math involved.&#xD;&#xA;&#xD;&#xA;Now, each face of a mesh has a normal vector, and that the normal map fragment shader modifies that face normal, based on the RBG pixel of the normal map. This, in turn modifies the brightness of a rendered mesh, giving the impression of height and depth. Correct me if I'm mistaken, of course.&#xD;&#xA;&#xD;&#xA;So, based on this, if you managed to split up a mesh, to add extra edges that correspond to individual pixel boundaries - with each boundary containing portions of one or more of the original faces, you could then apply the normal modification of the corresponding normal map's pixel, as rotation. &#xD;&#xA;&#xD;&#xA;Then, it would simply be a matter of reconnecting the vertices, to make the mesh cohesive again&#xD;&#xA;&#xD;&#xA;While I can find plenty of sources on how normal maps affect the normal vectors of a mesh, I'm a bit lost on how to take that effect, and apply it to physically rotating the face, so the original normal vector matches its modified vector. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30970" PostHistoryTypeId="1" PostId="10633" RevisionGUID="6361fbd0-4a63-4aa7-88fb-dc8e148ad035" CreationDate="2021-02-04T00:03:52.813" UserId="15690" Text="How do I figure rotation from the difference between two vectors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30971" PostHistoryTypeId="3" PostId="10633" RevisionGUID="6361fbd0-4a63-4aa7-88fb-dc8e148ad035" CreationDate="2021-02-04T00:03:52.813" UserId="15690" Text="|mathematics|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30975" PostHistoryTypeId="2" PostId="10634" RevisionGUID="ad96a5f2-9454-4758-997c-0506502ac2c9" CreationDate="2021-02-04T10:02:55.007" UserId="15694" Text="**Background:** &#xD;&#xA;&#xD;&#xA;I am extracting the textures for a model with Assimp and sampling those textures in the fragment shader.  I have multiple ```uniform sampler2D textureN``` declarations in my fragment shader and call ```glUniform1i(location, textureN)```, ```glActiveTexture(GL_TEXTUREN)``` and ```glBindTexture(GL_TEXTURE_2D, textureN_ref)``` for each texture.  This is working correctly.&#xD;&#xA;&#xD;&#xA;The following Mesh drawing function from [learnopengl.com][1] binds multiple textures.  However, as shown below, the fragment shader only contains one sampler.&#xD;&#xA;&#xD;&#xA;    void Draw(Shader &amp;shader) &#xD;&#xA;    {&#xD;&#xA;        unsigned int diffuseNr = 1;&#xD;&#xA;        unsigned int specularNr = 1;&#xD;&#xA;        for(unsigned int i = 0; i &lt; textures.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            glActiveTexture(GL_TEXTURE0 + i); // activate proper texture unit before binding&#xD;&#xA;            // retrieve texture number (the N in diffuse_textureN)&#xD;&#xA;            string number;&#xD;&#xA;            string name = textures[i].type;&#xD;&#xA;            if(name == &quot;texture_diffuse&quot;)&#xD;&#xA;                number = std::to_string(diffuseNr++);&#xD;&#xA;            else if(name == &quot;texture_specular&quot;)&#xD;&#xA;                number = std::to_string(specularNr++);&#xD;&#xA;    &#xD;&#xA;            shader.setFloat((&quot;material.&quot; + name + number).c_str(), i);&#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, textures[i].id);&#xD;&#xA;        }&#xD;&#xA;        glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    &#xD;&#xA;        // draw mesh&#xD;&#xA;        glBindVertexArray(VAO);&#xD;&#xA;        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);&#xD;&#xA;        glBindVertexArray(0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 TexCoords;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D texture_diffuse1;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {    &#xD;&#xA;        FragColor = texture(texture_diffuse1, TexCoords);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;Surely for the ```void Draw(Shader &amp;shader)``` function to work you would have to define multiple samplers in the fragment shader?  The linked article does in fact seem to state this in the paragraph prior to the function.&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Model-Loading/Mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="30976" PostHistoryTypeId="1" PostId="10634" RevisionGUID="ad96a5f2-9454-4758-997c-0506502ac2c9" CreationDate="2021-02-04T10:02:55.007" UserId="15694" Text="Using multiple textures in a shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="30977" PostHistoryTypeId="3" PostId="10634" RevisionGUID="ad96a5f2-9454-4758-997c-0506502ac2c9" CreationDate="2021-02-04T10:02:55.007" UserId="15694" Text="|opengl|shader|texture|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30978" PostHistoryTypeId="5" PostId="10551" RevisionGUID="150da8f8-4341-4c82-aeb4-2bbd0ad2714c" CreationDate="2021-02-04T11:04:36.067" UserId="7724" Comment="Cleaned up the question" Text="I want to know how do take the derivative of a Bézier curve. I visited this website https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html, but I am unable to figure out how do they did it. Please help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30979" PostHistoryTypeId="4" PostId="10551" RevisionGUID="150da8f8-4341-4c82-aeb4-2bbd0ad2714c" CreationDate="2021-02-04T11:04:36.067" UserId="7724" Comment="Cleaned up the question" Text="How to take the derivative of a Bézier curve?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30980" PostHistoryTypeId="24" PostId="10551" RevisionGUID="150da8f8-4341-4c82-aeb4-2bbd0ad2714c" CreationDate="2021-02-04T11:04:36.067" Comment="Proposed by 7724 approved by 209, -1 edit id of 553" ContentLicense="CC BY-SA 4.0" />
  <row Id="30981" PostHistoryTypeId="5" PostId="10551" RevisionGUID="e58431fa-16cf-4b42-b893-31588686d275" CreationDate="2021-02-04T11:04:36.067" UserId="13095" Comment="Cleaned up the question" Text="I want to know how to take the derivative of a Bézier curve. I visited this website https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html, but I am unable to figure out how they did it. Please help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="30982" PostHistoryTypeId="5" PostId="8105" RevisionGUID="850f4082-9c6d-47da-9b8d-0fc85abe1466" CreationDate="2021-02-04T11:25:41.800" UserId="5778" Comment="PLEASE REJECT - script gone hayware" Text="I've watched the [Pixar In A Box, Maths of Rendering Tutorial][1] on Khan Academy. I've started writing a raytracing program and have come to the point where I must solve for `t` (the parameter for the parametric ray through the camera and a point on the view plane). &#xD;&#xA;&#xD;&#xA;In the tutorial, this is done through simply substituting each the parametric formula for each `x`, `y`, and `z` into the equation of the plane that the triangle lies on. This leaves a single unknown (`t`).&#xD;&#xA;&#xD;&#xA;However, in all the examples and exercises that are given by the tutorial the camera is located at [0,0,0]. As I'm sure you'll understand, this is in many cases unrealistic. Because the camera is at 0, they simplify as follows:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?i=\frac{1}{t}C&amp;plus;tP&quot; title=&quot;i=\frac{1}{t}C+tP&quot; /&gt;&#xD;&#xA;&#xD;&#xA;becomes simply:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?tP&quot; title=&quot;tP&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Which makes for an easy solve. My question is when the camera is not at [0,0,0] should I:&#xD;&#xA;&#xD;&#xA; 1. Calculate the coordinates of the plane relative to the camera. (So the camera acts as if it is [0,0,0]&#xD;&#xA; 2. Solve the equation as a quadratic. I'm still confused a bit about why this is a quadratic in the first place. Could someone explain this? And which solution do I use?&#xD;&#xA;&#xD;&#xA;Of the two options, which is more acceptable for use in this community? Why? Is one more computationally efficient?&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;I think I have found a solution as follows:&#xD;&#xA;The parametric equation (which is effectively just a weighted average) is represented like this in the tutorial:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://latex.codecogs.com/gif.latex?x(t)&amp;space;=&amp;space;\frac{1}{t}C_{x}&amp;plus;tP_{x}&quot; title=&quot;x(t) = \frac{1}{t}C_{x}+tP_{x}&quot; /&gt;&#xD;&#xA;&#xD;&#xA;But I realize now that is the same as:&#xD;&#xA;&#xD;&#xA;[![][2]][2]&#xD;&#xA;&lt;!-- source: https://latex.codecogs.com/gif.latex?x(t)&amp;space;=C_{x}&amp;space;&amp;plus;t(P_{x}-C_{x}) --&gt;&#xD;&#xA;&#xD;&#xA;Which is dramatically easier to solve. &#xD;&#xA;&#xD;&#xA;So my final question is, which of the three is the most acceptable way to solve for t? I'm assuming the third one.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khanacademy.org/computing/pixar/rendering/rendering-2/a/rendering-lesson-brief&#xD;&#xA; [2]: https://i.stack.imgur.com/6ndPF.gif &quot;x(t) =C_{x} +t(P_{x}-C_{x})&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30983" PostHistoryTypeId="24" PostId="8105" RevisionGUID="850f4082-9c6d-47da-9b8d-0fc85abe1466" CreationDate="2021-02-04T11:25:41.800" Comment="Proposed by 5778 approved by 209, -1 edit id of 551" ContentLicense="CC BY-SA 4.0" />
  <row Id="30984" PostHistoryTypeId="5" PostId="8105" RevisionGUID="70d09189-1f97-4fc0-9687-d581a72255b7" CreationDate="2021-02-04T11:25:41.800" UserId="13095" Comment="Replace equation images with matjax equations and fix some minor mistakes" Text="I've watched the [Pixar In A Box, Maths of Rendering Tutorial][1] on Khan Academy. I've started writing a raytracing program and have come to the point where I must solve for `t` (the parameter for the parametric ray through the camera and a point on the view plane). &#xD;&#xA;&#xD;&#xA;In the tutorial, this is done by simply substituting the parametric formula for each `x`, `y`, and `z` into the equation of the plane that the triangle lies on. This leaves a single unknown (`t`).&#xD;&#xA;&#xD;&#xA;However, in all the examples and exercises that are given by the tutorial the camera is located at [0,0,0]. As I'm sure you'll understand, this is in many cases unrealistic. Because the camera is at 0, they simplify as follows:&#xD;&#xA;&#xD;&#xA;$$i=\frac{1}{t}C+tP$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;becomes simply:&#xD;&#xA;&#xD;&#xA;$$tP$$&#xD;&#xA;&#xD;&#xA;Which makes for an easy solve. My question is when the camera is not at [0,0,0] should I:&#xD;&#xA;&#xD;&#xA; 1. Calculate the coordinates of the plane relative to the camera. (So the camera acts as if it is [0,0,0]&#xD;&#xA; 2. Solve the equation as a quadratic. I'm still confused a bit about why this is quadratic in the first place. Could someone explain this? And which solution do I use?&#xD;&#xA;&#xD;&#xA;Of the two options, which is more acceptable for use in this community? Why? Is one more computationally efficient?&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;I think I have found a solution as follows:&#xD;&#xA;The parametric equation (which is effectively just a weighted average) is represented like this in the tutorial:&#xD;&#xA;&#xD;&#xA;$$x(t) = \frac{1}{t}C_{x}+tP_{x}$$&#xD;&#xA;&#xD;&#xA;But I realize now that is the same as:&#xD;&#xA;&#xD;&#xA;$$x(t)=C_{x}+t(P_{x}-C_{x})$$&#xD;&#xA;&#xD;&#xA;Which is dramatically easier to solve. &#xD;&#xA;&#xD;&#xA;So my final question is, which of the three is the most acceptable way to solve for t? I'm assuming the third one.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khanacademy.org/computing/pixar/rendering/rendering-2/a/rendering-lesson-brief" ContentLicense="CC BY-SA 4.0" />
  <row Id="30989" PostHistoryTypeId="5" PostId="10631" RevisionGUID="af87874f-8330-4c7a-a2ff-229145d61f53" CreationDate="2021-02-04T14:27:07.443" UserId="2654" Comment="added 6 characters in body" Text="The GS is responsible for assigning a particular primitive to a particular layer. The GS is also responsible for writing values for `gl_ClipDistance` for a particular primitive. So the GS is perfectly capable of doing both of those things: assigning a primitive to a layer and doing the clip-plane computations for that layer.&#xD;&#xA;&#xD;&#xA;And if you need to &quot;deactivate&quot; a clip plane for a particular primitive assigned to a particular layer, just assign the `gl_ClipDistance[i]` for that to 1.0 for all of its vertices." ContentLicense="CC BY-SA 4.0" />
  <row Id="30990" PostHistoryTypeId="2" PostId="10636" RevisionGUID="8325bdb9-212b-40e8-8cb2-786efcd2a7b2" CreationDate="2021-02-04T15:01:55.113" UserId="15697" Text="I want to try making small clips with realistic environment with the lighting in the KDA music video...&#xD;&#xA;Any ideas what kind of program to use?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30991" PostHistoryTypeId="1" PostId="10636" RevisionGUID="8325bdb9-212b-40e8-8cb2-786efcd2a7b2" CreationDate="2021-02-04T15:01:55.113" UserId="15697" Text="What software was used to make KDA - Villain?" ContentLicense="CC BY-SA 4.0" />
  <row Id="30992" PostHistoryTypeId="3" PostId="10636" RevisionGUID="8325bdb9-212b-40e8-8cb2-786efcd2a7b2" CreationDate="2021-02-04T15:01:55.113" UserId="15697" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="30993" PostHistoryTypeId="5" PostId="10636" RevisionGUID="083840ac-8166-4db9-81ac-7f7ccdc21469" CreationDate="2021-02-04T15:15:51.523" UserId="15697" Comment="added 76 characters in body" Text="[![Here's an example][1]][1]&#xD;&#xA;I want to try making small clips with realistic environment with the lighting in the KDA music video...&#xD;&#xA;Any ideas what kind of program to use?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gG0bE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="30995" PostHistoryTypeId="2" PostId="10637" RevisionGUID="83b083cd-41eb-4127-a4f0-b03b1df29975" CreationDate="2021-02-04T19:08:32.987" UserId="506" Text="The video was created by a studio called Trizz; you can see their page about the project [here](https://www.trizz.tv/portfolio/kdavillain). The site doesn’t have any information about what software they used, but you can achieve this look (with enough work) in pretty much any modern renderer. If you use [Blender](https://blender.org), [Cycles](https://www.cycles-renderer.org) is a good one; with other 3D software, [Redshift](https://redshift3d.com), [Octane](https://home.otoy.com/render/octane-render/), and [Arnold](https://arnoldrenderer.com) are popular options.&#xD;&#xA;&#xD;&#xA;If you’re also looking to make the kind of physics-based animation—cloth, fire, snakes, etc.—that appears in the video, you’ll probably also want to check out [Houdini](https://www.sidefx.com/products/houdini/)." ContentLicense="CC BY-SA 4.0" />
  <row Id="30997" PostHistoryTypeId="2" PostId="10639" RevisionGUID="accdd000-4124-4177-bb9a-8211778bd98d" CreationDate="2021-02-05T00:11:49.530" UserId="14079" Text="I'm trying to plot some points along a 3D line segment and could really use some help. In 2D, I've found success getting the angle of the line, the sine &amp; cosine of the angle, and then adding the cosine &amp; sine to the starting point of the line's x &amp; y respectively.&#xD;&#xA;&#xD;&#xA;In 3D I think I'm getting the angle correctly and thus x &amp; y using cosine and sine, but I'm not sure what to do for z. Can anyone please advise on how this is derived? Thank you!&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;def GetAngle(line):&#xD;&#xA;    fCrossX = line.p1.y * line.p2.z - line.p1.z * line.p2.y&#xD;&#xA;    fCrossY = line.p1.z * line.p2.x - line.p1.x * line.p2.z&#xD;&#xA;    fCrossZ = line.p1.x * line.p2.y - line.p1.y * line.p2.x&#xD;&#xA;    fCross = math.sqrt(fCrossX * fCrossX +&#xD;&#xA;        fCrossY * fCrossY + fCrossZ * fCrossZ)&#xD;&#xA;    fDot = line.p1.x * line.p2.x + line.p1.y * line.p2.y + line.p1.z + line.p2.z&#xD;&#xA;    return math.atan2(fCross, fDot)&#xD;&#xA;&#xD;&#xA;v1 = Vector(100,0,0)&#xD;&#xA;v2 = Vector(500,0,0)&#xD;&#xA;line = Line(v1,v2)&#xD;&#xA;angle = GetAngle(line)&#xD;&#xA;sin = math.sin(angle)&#xD;&#xA;cos = math.cos(angle)&#xD;&#xA;points = list()&#xD;&#xA;for i in range(int(line.length)):&#xD;&#xA;    x = line.p1.x+(cos*i)&#xD;&#xA;    y = line.p1.y+(sin*i)&#xD;&#xA;    # what do I do for z???&#xD;&#xA;    pt = Vector(x,y)&#xD;&#xA;    points.append(pt)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="30998" PostHistoryTypeId="1" PostId="10639" RevisionGUID="accdd000-4124-4177-bb9a-8211778bd98d" CreationDate="2021-02-05T00:11:49.530" UserId="14079" Text="Plotting points along a 3D line segment" ContentLicense="CC BY-SA 4.0" />
  <row Id="30999" PostHistoryTypeId="3" PostId="10639" RevisionGUID="accdd000-4124-4177-bb9a-8211778bd98d" CreationDate="2021-02-05T00:11:49.530" UserId="14079" Text="|3d|mathematics|vectors|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31001" PostHistoryTypeId="2" PostId="10640" RevisionGUID="d98b703d-126d-4028-beb6-ba173c3ae1bb" CreationDate="2021-02-05T01:09:59.500" UserId="506" Text="You shouldn’t need to use any trigonometry here at all. If you get the vector from v1 to v2 and divide it by the number of points you want along the line, each subsequent point is v1 + (that vector) × (the index of the point). Works in any number of dimensions, faster than the trigonometric approach.&#xD;&#xA;&#xD;&#xA;    v1 = Vector(100, 200, 300)&#xD;&#xA;    v2 = Vector(500, 400, 300)&#xD;&#xA;    steps = 25 # or however many subdivisions you want: int(length(Line(v1, v2))) if you want an equivalent to the original&#xD;&#xA;    stepAmount = Vector((v2.x - v1.x) / steps, (v2.y - v1.y) / steps, (v2.z - v1.z) / steps)&#xD;&#xA;    points = list()&#xD;&#xA;    for i in range(steps + 1)&#xD;&#xA;        x = v1.x + stepAmount.x * i&#xD;&#xA;        y = v1.y + stepAmount.y * i&#xD;&#xA;        z = v1.z + stepAmount.z * i&#xD;&#xA;        points.append(Vector(x, y, z))" ContentLicense="CC BY-SA 4.0" />
  <row Id="31003" PostHistoryTypeId="50" PostId="10509" RevisionGUID="5a109845-94af-4a59-97dc-8395033d5710" CreationDate="2021-02-05T03:03:10.247" UserId="-1" />
  <row Id="31004" PostHistoryTypeId="2" PostId="10641" RevisionGUID="33b06b74-529e-4186-bbb2-746af4e90f1a" CreationDate="2021-02-05T10:15:33.203" UserId="6496" Text="Is there a way to influence the behavior of `imageLoad()` for accessing an `image2D` or `uimage2D` with an out-of-bounds texel coordinate; for example repeat the last *good* texel instead of returning 0s?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="31005" PostHistoryTypeId="1" PostId="10641" RevisionGUID="33b06b74-529e-4186-bbb2-746af4e90f1a" CreationDate="2021-02-05T10:15:33.203" UserId="6496" Text="imageLoad() behavior for non-existent texel" ContentLicense="CC BY-SA 4.0" />
  <row Id="31006" PostHistoryTypeId="3" PostId="10641" RevisionGUID="33b06b74-529e-4186-bbb2-746af4e90f1a" CreationDate="2021-02-05T10:15:33.203" UserId="6496" Text="|opengl|glsl|vulkan|image-load-store|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31007" PostHistoryTypeId="2" PostId="10642" RevisionGUID="996e1f66-352f-4758-8015-6dba8dc1cdea" CreationDate="2021-02-05T14:43:00.280" UserId="2654" Text="No. When you use image load/store, you don't get to play &quot;texture&quot; games like playing with the border color, doing filtering on values, etc. You are fetching a texel from a particular location.&#xD;&#xA;&#xD;&#xA;If you want this, you will have to detect the out-of-bounds access and choose to substitute an alternate value. You can query the image's size, so it should be easy enough to detect." ContentLicense="CC BY-SA 4.0" />
  <row Id="31016" PostHistoryTypeId="50" PostId="10537" RevisionGUID="1d2ad15a-900f-456d-b5d1-c215d096dd2d" CreationDate="2021-02-06T05:05:20.517" UserId="-1" />
  <row Id="31017" PostHistoryTypeId="50" PostId="5547" RevisionGUID="b65b196d-28f5-4ceb-aeec-bcdc7df0141c" CreationDate="2021-02-06T08:01:15.117" UserId="-1" />
  <row Id="31018" PostHistoryTypeId="2" PostId="10645" RevisionGUID="9b5d8ebc-8fff-45b5-ae4c-6391678c4c46" CreationDate="2021-02-06T15:19:04.663" UserId="15710" Text="I am not sure if I understood it correctly, but OpenGL is high-level like Java and Metal is low-level like Assembly, aren't they? Apple seems to have abandoned OpenGL in favour of Metal, but there still are a few popular applications that use OpenGL like Blender. I think I have read that because of Apple's lack of support for OpenGL, Blender development is hindered.&#xD;&#xA;&#xD;&#xA;Then, I wondered if some developers could implement an OpenGL library using Metal, and Blender could use that library. Then the developers of individual applications like Blender would not have to waste their time rewriting the applications in Metal. Is that kind of library plausible? I have searched Google for that, but all I could find was an OpenGL-ES-to-Metal project. I don't know whether OpenGL and OpenGL ES have similar architecture or not, so I am not sure the existence of that library means such a library for OpenGL is possible or not." ContentLicense="CC BY-SA 4.0" />
  <row Id="31019" PostHistoryTypeId="1" PostId="10645" RevisionGUID="9b5d8ebc-8fff-45b5-ae4c-6391678c4c46" CreationDate="2021-02-06T15:19:04.663" UserId="15710" Text="Is OpenGL to Metal translation layer plausible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31020" PostHistoryTypeId="3" PostId="10645" RevisionGUID="9b5d8ebc-8fff-45b5-ae4c-6391678c4c46" CreationDate="2021-02-06T15:19:04.663" UserId="15710" Text="|opengl|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31022" PostHistoryTypeId="2" PostId="10646" RevisionGUID="ba6dccc5-8be3-46ff-bd2c-531a277a8831" CreationDate="2021-02-06T20:03:34.343" UserId="15714" Text="I've come across this problem several times now and I can't really understand what causes it; my background is in Wordpress, not really in computer graphics.&#xD;&#xA;&#xD;&#xA;I hope this is the right place to ask, I was in doubt with https://graphicdesign.stackexchange.com/. &#xD;&#xA;&#xD;&#xA;I have a big initial image, say 1500x1017 at 300ppi, 566 KB. I upload it in my Wordpress site: the browser resizes it to a fixed width that depends on the site (in this case 718px), and it looks nice and crispy. See two screenshots. &#xD;&#xA;&#xD;&#xA;[![Crispy image, resized by the browser][1]][1]&#xD;&#xA;[![Browser resizing][2]][2]&#xD;&#xA;&#xD;&#xA;In general you don't want to upload oversized images and let the browser do the resizing for you: I'm sure everybody here is familiar with the concept of [Serving scaled images][3] to optimise site performance. In a few words, &#xD;&#xA;&#xD;&#xA;&gt; Serving appropriately-sized images can save many bytes of data and improve the performance of your webpage, especially on low-powered (eg. mobile) devices.&#xD;&#xA;&gt; You should use an image editor to scale images to match the largest size needed in your page.&#xD;&#xA;&#xD;&#xA;Enter Photoshop (or `sips` or any other resizing tool). I open the image, resize it to 718px width, save **without optimisation**, i.e. to max `jpg` quality. I would expect this image to look as crispy as the big one once uploaded: I am just doing the resizing instead of letting the browser do it, right?&#xD;&#xA;&#xD;&#xA;Not quite. The image's size matches the displayed size, but the image looks blurry.&#xD;&#xA;[![Blurry image, intrinsic width = displayed width][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;What's the deal? Am I resizing with the wrong procedure? Is this about Wordpress media management with its billion of thumbnails? &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BgeBR.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/qTZpJ.jpg&#xD;&#xA;  [3]: https://gtmetrix.com/serve-scaled-images.html&#xD;&#xA;  [4]: https://i.stack.imgur.com/kNIKR.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/SO3AA.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31023" PostHistoryTypeId="1" PostId="10646" RevisionGUID="ba6dccc5-8be3-46ff-bd2c-531a277a8831" CreationDate="2021-02-06T20:03:34.343" UserId="15714" Text="Why is browser-resized image crispy and manually-resized image blurry?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31024" PostHistoryTypeId="3" PostId="10646" RevisionGUID="ba6dccc5-8be3-46ff-bd2c-531a277a8831" CreationDate="2021-02-06T20:03:34.343" UserId="15714" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31025" PostHistoryTypeId="50" PostId="10365" RevisionGUID="5431ac3f-a5a7-4f8a-a24d-164325c31c98" CreationDate="2021-02-07T07:01:45.207" UserId="-1" />
  <row Id="31026" PostHistoryTypeId="2" PostId="10647" RevisionGUID="0e82fbab-9043-4626-b523-d03163819d7e" CreationDate="2021-02-07T09:44:15.120" UserId="15717" Text="I don't really know where I should ask this, so I decided to come here.&#xD;&#xA;I want to send multiple 3D files to several computers to render, and for that I need to approximately determine when each system will finish the render operation (I know the stats of the computers).&#xD;&#xA;My question is, based on any information you could get from a system (CPU, GPU, OS, ...),&#xD;&#xA;is it possible to determine (approximately) when the system will be done rendering a project?&#xD;&#xA;(Assume we are talking about a specific software and project so that we can compare the cmputers).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="31027" PostHistoryTypeId="1" PostId="10647" RevisionGUID="0e82fbab-9043-4626-b523-d03163819d7e" CreationDate="2021-02-07T09:44:15.120" UserId="15717" Text="Efficiency of different Processors and GPUs" ContentLicense="CC BY-SA 4.0" />
  <row Id="31028" PostHistoryTypeId="3" PostId="10647" RevisionGUID="0e82fbab-9043-4626-b523-d03163819d7e" CreationDate="2021-02-07T09:44:15.120" UserId="15717" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31030" PostHistoryTypeId="5" PostId="10647" RevisionGUID="b90de83e-007c-4fd5-a423-1b9e11d16f55" CreationDate="2021-02-07T14:58:18.423" UserId="15717" Comment="added 121 characters in body" Text="I don't really know where I should ask this, so I decided to come here.&#xD;&#xA;I want to send multiple 3D files to several computers to render, and for that I need to approximately determine when each system will finish the render operation (I know the stats of the computers).&#xD;&#xA;My question is, based on any information you could get from a system (CPU, GPU, OS, ...),&#xD;&#xA;is it possible to determine (approximately) when the system will be done rendering a project?&#xD;&#xA;(Assume we are talking about a specific software and project so that we can compare the cmputers).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Update:**&#xD;&#xA;I'm looking for something like FLOPS, but I don't know how that would work in terms of rendering things.&#xD;&#xA;&#xD;&#xA;Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="31031" PostHistoryTypeId="50" PostId="9829" RevisionGUID="c8dd0e95-416c-43e4-be6a-bb51a04a9fc8" CreationDate="2021-02-07T17:05:10.467" UserId="-1" />
  <row Id="31032" PostHistoryTypeId="2" PostId="10648" RevisionGUID="5fbf6b9e-f783-4021-aa5c-e5a660469fb9" CreationDate="2021-02-07T19:21:54.697" UserId="15723" Text="I followed along with *Ray Tracing in One Weekend* and managed to get the final output but I wanted to understand more about creating a camera and &quot;painting&quot; the screen since he didn't go over it much. &#xD;&#xA;&#xD;&#xA;When I tried using a different way of creating a camera by spheres actually get elongated, making them look like more like ellipses. I've tried modifying the x and y assignments in `screenCords` but I've only managed to make more errors (such as objects wrapping around to the opposite side)  &#xD;&#xA;&#xD;&#xA;Camera.h:&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    #include &quot;../Matrix.h&quot;&#xD;&#xA;    #include &quot;../Defs.h&quot;&#xD;&#xA;    #include &quot;Defs.h&quot;&#xD;&#xA;    &#xD;&#xA;    template&lt;typename O&gt;&#xD;&#xA;    using Point3 = Vec3&lt;O&gt;;&#xD;&#xA;    &#xD;&#xA;    template&lt;typename O&gt;&#xD;&#xA;    using Color = Vec3&lt;O&gt;;&#xD;&#xA;    &#xD;&#xA;    template &lt;typename O&gt;&#xD;&#xA;    class Camera{&#xD;&#xA;      O Height;&#xD;&#xA;      O Width;&#xD;&#xA;      Vec3&lt;O&gt; Forward, Right, Up;&#xD;&#xA;      Point3&lt;O&gt; Origin;&#xD;&#xA;    &#xD;&#xA;    public:&#xD;&#xA;      Camera(O fov, O aspect_ratio, Point3&lt;O&gt; origin, Point3&lt;O&gt; target, Vec3&lt;O&gt; upguide) {&#xD;&#xA;        Height = atan(degrees_to_radians(fov));&#xD;&#xA;        Width = Height * aspect_ratio;&#xD;&#xA;        &#xD;&#xA;        Origin = origin;&#xD;&#xA;    &#xD;&#xA;        Forward = target - origin;&#xD;&#xA;        Forward.normalize();&#xD;&#xA;        Right = Forward.cross(upguide);&#xD;&#xA;        Right.normalize();&#xD;&#xA;        Up = Right.cross(Forward);&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        Ray&lt;O&gt; get_raydir(O right, O up){&#xD;&#xA;          Vec3&lt;O&gt; result(Forward + right * Width * Right + up * Height * Up); result.normalize();&#xD;&#xA;    &#xD;&#xA;          return Ray&lt;O&gt;(Origin, result);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        void screenCords(O &amp;x, O &amp;y, O width, O height){&#xD;&#xA;          x = ((2.0f * x) / width) -1.0f;&#xD;&#xA;          y = ((2.0f * y) / height); &#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Main.cpp &#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &quot;../Matrix.h&quot;&#xD;&#xA;    #include &quot;Camera.h&quot;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #include &quot;Image.h&quot;&#xD;&#xA;    #include &quot;Shapes.h&quot;&#xD;&#xA;    #include &quot;Tracer.h&quot;&#xD;&#xA;    #include &quot;../Defs.h&quot;&#xD;&#xA;    &#xD;&#xA;    template&lt;typename O&gt;&#xD;&#xA;    using Point3 = Vec3&lt;O&gt;;&#xD;&#xA;    &#xD;&#xA;    template&lt;typename O&gt;&#xD;&#xA;    using Color = Vec3&lt;O&gt;;&#xD;&#xA;    &#xD;&#xA;    int main(){&#xD;&#xA;      const int img_ratio = 2;&#xD;&#xA;      const int img_width = 640;&#xD;&#xA;      const int img_height = 480;&#xD;&#xA;      const int depth = 50; float t_Max = infinity; float t_Min = 0.001;&#xD;&#xA;    &#xD;&#xA;      float inv_width = 1 / float(img_width);&#xD;&#xA;      float inv_height = 1 / float(img_height);&#xD;&#xA;    &#xD;&#xA;      std::vector&lt;Sphere&lt;float&gt;&gt; shapes;&#xD;&#xA;    &#xD;&#xA;      Camera&lt;float&gt; cam1(20.0f, img_ratio, Point3&lt;float&gt;(0.0f, 0.0f, 0.0f), Point3&lt;float&gt;(0.0f, 0.0f, -1.0f), Vec3&lt;float&gt;(0.0f, 1.0f, 0.0f));&#xD;&#xA;    &#xD;&#xA;      Sphere&lt;float&gt; cir1(0.2f, Point3&lt;float&gt;(0.2f, 0.0f, -1.0f));&#xD;&#xA;      Sphere&lt;float&gt; cir2(7.0f, Point3&lt;float&gt;(0.0f, -7.0f, -1.0f));&#xD;&#xA;      Sphere&lt;float&gt; cir3(0.5f, Point3&lt;float&gt;(1.0f, 0.0f, -1.0f));&#xD;&#xA;      shapes.push_back(cir1);&#xD;&#xA;      //shapes.push_back(cir2);&#xD;&#xA;      //shapes.push_back(cir3);&#xD;&#xA;    &#xD;&#xA;      Tracer&lt;float&gt; tracer(shapes);&#xD;&#xA;    &#xD;&#xA;      std::cout &lt;&lt; &quot;P3\n&quot; &lt;&lt; img_width &lt;&lt; ' ' &lt;&lt; img_height &lt;&lt; &quot;\n255&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;      Ray&lt;float&gt; ray(Point3&lt;float&gt;(0.0f), Vec3&lt;float&gt;(0.0f));&#xD;&#xA;    &#xD;&#xA;      for (int j = 0; j &lt; img_height; j++)&#xD;&#xA;      {&#xD;&#xA;        std::cerr &lt;&lt; &quot;\rScanlines remaining: &quot; &lt;&lt; j &lt;&lt; ' ' &lt;&lt; std::flush;&#xD;&#xA;        for (int i = 0; i &lt; img_width; i++){&#xD;&#xA;    &#xD;&#xA;            float x = i;&#xD;&#xA;            float y = j;&#xD;&#xA;    &#xD;&#xA;            cam1.screenCords(x, y, img_width, img_height);&#xD;&#xA;    &#xD;&#xA;            ray = cam1.get_raydir(x, y);&#xD;&#xA;            //ray = Ray&lt;float&gt;(Vec3&lt;float&gt;(x1, y1, 1), Point3&lt;float&gt;(0.0f, 0.0f, 0.0f));&#xD;&#xA;            tracer.iterator(ray, depth, t_Max, t_Min);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;      std::cerr &lt;&lt; &quot;\n done &quot; &lt;&lt; std::endl;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I suspect the error is in one of these files since the spheres are actually being drawn with the colors based on normals (with the top and bottom normal colors unsurprisingly being bugged)&#xD;&#xA;&#xD;&#xA;Here are a few examples of the output:&#xD;&#xA;&#xD;&#xA;[![With one sphere centered at the origin][1]][1]&#xD;&#xA;&#xD;&#xA;[![More spheres][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OFf42.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Bj1GH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31033" PostHistoryTypeId="1" PostId="10648" RevisionGUID="5fbf6b9e-f783-4021-aa5c-e5a660469fb9" CreationDate="2021-02-07T19:21:54.697" UserId="15723" Text="(Ray tracing) Trouble converting to screen coordinates, objects being stretched" ContentLicense="CC BY-SA 4.0" />
  <row Id="31034" PostHistoryTypeId="3" PostId="10648" RevisionGUID="5fbf6b9e-f783-4021-aa5c-e5a660469fb9" CreationDate="2021-02-07T19:21:54.697" UserId="15723" Text="|raytracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31042" PostHistoryTypeId="50" PostId="10341" RevisionGUID="d164c9f3-af76-4824-95f6-299ff3487982" CreationDate="2021-02-08T07:07:55.803" UserId="-1" />
  <row Id="31043" PostHistoryTypeId="5" PostId="8314" RevisionGUID="bb3a13b1-1652-471e-843b-14a3026b10b2" CreationDate="2021-02-08T07:11:53.833" UserId="9306" Comment="added 2 characters in body" Text="There's no such thing as a Vulkan _context_, the way there is with OpenGL.  There are a number of things that _kind of_ correspond to an OpenGL context.  &#xD;&#xA;&#xD;&#xA;There's a `VkInstance`.  This encapsulates access to the Vulkan libraries on the system, including the extensions.  &#xD;&#xA;&#xD;&#xA;There's a physical device `VkPhysicalDevice` and a `VkDevice`.  The former encapsulates all the information about a piece of hardware, typically your GPU.  The latter is a handle that lets you actually interact with it.  &#xD;&#xA;&#xD;&#xA;However, since you're focused on windows, what you're probably interested in is `VkSurfaceKHR`.  This encapsulates interaction with a windowing system.  On Windows, to interact with a window, you need to have an existing `VkInstance`, and you need to call [`vkCreateWin32SurfaceKHR`](https://vulkan.lunarg.com/doc/view/1.0.33.0/linux/vkspec.chunked/ch29s02.html) and pass it a structure containing an `HWND` and an `HINSTANCE`.  If it succeeds then you have a surface to which you can then present images.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31044" PostHistoryTypeId="5" PostId="8314" RevisionGUID="e672026f-98b1-4841-a216-f98e8a8edc5f" CreationDate="2021-02-08T07:24:12.743" UserId="9306" Comment="expand on the distinction" Text="There's no such thing as a Vulkan _context_, the way there is with OpenGL.  This is because Vulkan is a lower level API and an OpenGL context ties together a number of concepts that are distinct in the Vulkan API.  &#xD;&#xA;&#xD;&#xA;For example, the OpenGL context ties together the concept of extension management, memory management, draw commands and surface presentation.  In Vulkan those are all managed through independent interfaces.&#xD;&#xA;&#xD;&#xA;There are a number of things in Vulkan that _kind of_ correspond to an OpenGL context in different ways, depending on what you're trying to do.&#xD;&#xA;&#xD;&#xA;`VkInstance` encapsulates access to the Vulkan libraries on the system, including enumerating the global extensions.&#xD;&#xA;&#xD;&#xA;`VkPhysicalDevice` lets you query the hardware capabilities and hardware specific extensions.  &#xD;&#xA;&#xD;&#xA;`VkDevice` lets you actually interact with the hardware to do things like allocate memory.  &#xD;&#xA;&#xD;&#xA;`VkCommandBuffer` is the interface for setting up and executing draw calls.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, since you're focused on windows, what you're probably interested in is `VkSurfaceKHR`.  This encapsulates interaction with a windowing system, including initializing a surface from the OS specific window handles and doing presentation calls.  &#xD;&#xA;&#xD;&#xA;On Windows, to interact with a window, you need to have an existing `VkInstance`, and you need to call [`vkCreateWin32SurfaceKHR`](https://vulkan.lunarg.com/doc/view/1.0.33.0/linux/vkspec.chunked/ch29s02.html) and pass it a structure containing an `HWND` and an `HINSTANCE`.  If it succeeds then you have a surface to which you can then present images.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31045" PostHistoryTypeId="50" PostId="10207" RevisionGUID="84af4c28-0834-41a1-9d9c-bb90f5ec0a58" CreationDate="2021-02-08T08:05:55.627" UserId="-1" />
  <row Id="31046" PostHistoryTypeId="2" PostId="10651" RevisionGUID="a9bd2f94-49bb-4128-865e-04a4b7bf33a4" CreationDate="2021-02-08T14:10:42.177" UserId="7952" Text="The answer to this question is: it depends.&#xD;&#xA;&#xD;&#xA;If the software is a black box that you have no control over then the best you will be able to do is measure wall clock run time on the host systems. That will give you general numbers in terms of wall clock time and is the most common way to gather this type of performance data. But will be affected by other processes running on the systems and a host of other variables. Repeated runs generally give better info.&#xD;&#xA;&#xD;&#xA;Making assumptions about CPU count isn't a good measure of expected performance because it depends heavily on the software. Will it utilize extra CPU's, will it have good cache coherency?&#xD;&#xA;&#xD;&#xA;You would be better off just gathering hardware data and comparing expected performance. &#xD;&#xA;&#xD;&#xA;From what you have describe doing both may be about as good as you will get. That is gather hardware data about the system, CPU, GPU, memory, etc. Run the render process as often as you can, such as render the same file 100 times in a loop measure how long it takes for each render operation, and take the average. Then use the combined info to make generalizations about similar hardware configurations.&#xD;&#xA;&#xD;&#xA;I've done this technique on server farms that had thousands of systems, all with similar hardware and gotten wildly different results. Measuring performance accurately is tricky business." ContentLicense="CC BY-SA 4.0" />
  <row Id="31047" PostHistoryTypeId="5" PostId="10620" RevisionGUID="8adc51f5-f411-470d-9a65-28990047c8b8" CreationDate="2021-02-08T15:02:18.090" UserId="9581" Comment="added 842 characters in body; edited title" Text="I've been trying to link my the Intel Open Image Denoise libraries for about a week and still have no luck as of now. This could partly be because I am also novice in C++ stuff. So I need some help in getting it to work.&#xD;&#xA;&#xD;&#xA;Here's what I've done so far: after compiling OIDN I moved the oidn directory to the directory where my path tracer code is and did the following in my code (C++11) which I'm working on in Qt Creator.&#xD;&#xA;&#xD;&#xA;    #include &quot;oidn/include/OpenImageDenoise/oidn.hpp&quot;&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    oidn::DeviceRef device = oidn::newDevice(); // this is where things break&#xD;&#xA;    device.commit();&#xD;&#xA;&#xD;&#xA;Note that doing `#include &quot;oidn/include/OpenImageDenoise/oidn.hpp&quot;` seems to work fine because autocomplete works for oidn and shows its members. However I get the following errors which seems to be due to not linking oidn libraries.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried linking the libraries via `LIBS += -L&quot;oidn/build/&quot;` or `LIBS += -L&quot;oidn/build/libOpenImageDenoise.so&quot;` (as shown in the image) but I get the same errors. I also appended `-loidn` but got an error saying `&quot;cannot find -loidn&quot;`. I am now pretty confused on what I'm supposed to do. I would really appreciate if someone can help me figure out how I should link OIDN libraries to my program.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tyl6q.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31048" PostHistoryTypeId="4" PostId="10620" RevisionGUID="8adc51f5-f411-470d-9a65-28990047c8b8" CreationDate="2021-02-08T15:02:18.090" UserId="9581" Comment="added 842 characters in body; edited title" Text="How to link Intel Open Image Denoise in Qt Creator and use it to denoise noisy Monte Carlo path tracing renderings?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31049" PostHistoryTypeId="5" PostId="10620" RevisionGUID="ed9acadb-a262-4f95-90e8-d886e5e9259f" CreationDate="2021-02-08T15:08:47.160" UserId="9581" Comment="added 155 characters in body" Text="I've been trying to link my the Intel Open Image Denoise libraries for about a week and still have no luck as of now. This could partly be because I am also novice in C++ stuff. So I need some help in getting it to work.&#xD;&#xA;&#xD;&#xA;Here's what I've done so far: after compiling OIDN I moved the oidn directory to the directory where my path tracer code is and did the following in my code (C++11) which I'm working on in Qt Creator.&#xD;&#xA;&#xD;&#xA;    #include &quot;oidn/include/OpenImageDenoise/oidn.hpp&quot;&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    oidn::DeviceRef device = oidn::newDevice(); // this is where things break&#xD;&#xA;    device.commit();&#xD;&#xA;&#xD;&#xA;Note that doing `#include &quot;oidn/include/OpenImageDenoise/oidn.hpp&quot;` seems to work fine because autocomplete works for oidn and shows its members. However I get the following errors which seems to be due to not linking oidn libraries.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried linking the libraries via `LIBS += -L&quot;oidn/build/&quot;` or `LIBS += -L&quot;oidn/build/libOpenImageDenoise.so&quot;` (as shown in the image) but I get the same errors. I also appended `-loidn` but got an error saying `&quot;cannot find -loidn&quot;`. I am now pretty confused on what I'm supposed to do. I'm not even sure if the errors are due to not properly linking libraries because I see people generally link libraries in C++ the same way I am trying to do it here. I would really appreciate if someone can help me figure out what I need to do to get OIDN work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tyl6q.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31051" PostHistoryTypeId="50" PostId="10204" RevisionGUID="7f155abb-97eb-44cc-be52-1c278260e4d5" CreationDate="2021-02-08T20:04:50.490" UserId="-1" />
  <row Id="31052" PostHistoryTypeId="2" PostId="10653" RevisionGUID="a33d90d2-5c40-42e1-818d-ae4f0bba860c" CreationDate="2021-02-09T05:12:28.817" UserId="6496" Text="Is it possible to set the size of the shared memory of a compute shader workgroup from the host code? There is a way to do this in CUDA and I am suspecting that, since there is an GLSL extension to set the size of a workgroup during launch, there might be a way to do this, as the shared memory size is typically related to workgroup size." ContentLicense="CC BY-SA 4.0" />
  <row Id="31053" PostHistoryTypeId="1" PostId="10653" RevisionGUID="a33d90d2-5c40-42e1-818d-ae4f0bba860c" CreationDate="2021-02-09T05:12:28.817" UserId="6496" Text="GLSL Compute Shader Setting &quot;shared&quot; memory buffer size" ContentLicense="CC BY-SA 4.0" />
  <row Id="31054" PostHistoryTypeId="3" PostId="10653" RevisionGUID="a33d90d2-5c40-42e1-818d-ae4f0bba860c" CreationDate="2021-02-09T05:12:28.817" UserId="6496" Text="|opengl|glsl|vulkan|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31057" PostHistoryTypeId="2" PostId="10654" RevisionGUID="60dc36b3-cb04-4be7-bb36-a3b2f3c79de1" CreationDate="2021-02-09T16:45:20.023" UserId="2654" Text="GLSL has no mechanism to change the &quot;size&quot; of shared memory. Indeed, GLSL is *structurally* incapable of such a thing.&#xD;&#xA;&#xD;&#xA;You can't get a pointer to shared memory. Indeed, &quot;shared memory&quot; doesn't really exist in GLSL; there are only shared *variables*. And variables have a compile-time fixed size. So GLSL wouldn't even have a good way of allowing you to affect how much &quot;shared memory&quot; gets used from outside of the shader.&#xD;&#xA;&#xD;&#xA;The closest you might get to this is to have some kind of shared variable array whose size is determined from outside of the shader. But even then, you're not influencing the size of memory in total; you're influencing the size of just that *array*.&#xD;&#xA;&#xD;&#xA;And you can sort of do that. SPIR-V in OpenGL allows specialization constants. These are values specified by the outside world during the compilation process for the shader object. Such constants can be used as the size for a shared variable array. Of course, this means that changing it requires a full recompile/relink process." ContentLicense="CC BY-SA 4.0" />
  <row Id="31058" PostHistoryTypeId="2" PostId="10655" RevisionGUID="b7a009cf-4c34-4e1a-9612-da1b99a051b6" CreationDate="2021-02-09T19:55:43.373" UserId="15740" Text="I'm trying to implement PCSS in OpenGL/GLSL, but I have problems understanding the details especially the conversions between the coordinate spaces. The existing implementations are so different from each other and I'm just more confused. I'm sure they all good implementations I just don't understand them.&#xD;&#xA;## Other implementations ##&#xD;&#xA;- [pboechat's implementation](https://github.com/pboechat/PCSS)&#xD;&#xA;- [diharaw's implementation](https://github.com/diharaw/PercentageCloserSoftShadows)&#xD;&#xA;- [asylum2010's implementation](https://github.com/asylum2010/Asylum_Tutorials/blob/master/Media/ShadersDX/shadow_pcf.fx)&#xD;&#xA;- [Nvidia DirectX implementation](http://developer.download.nvidia.com/SDK/10.5/direct3d/samples.html)&#xD;&#xA;## My implementation ##&#xD;&#xA;In the vertex shader I don't do anything special, I just compute positions in different coordinate spaces.&#xD;&#xA;```&#xD;&#xA;#version 460 core&#xD;&#xA;&#xD;&#xA;layout(location=0) in vec3 i_position;&#xD;&#xA;layout(location=1) in vec3 i_normal;&#xD;&#xA;&#xD;&#xA;uniform mat4 u_model;&#xD;&#xA;uniform mat4 u_view;&#xD;&#xA;uniform mat4 u_projection;&#xD;&#xA;&#xD;&#xA;uniform mat4 u_light_view;&#xD;&#xA;uniform mat4 u_light_projection;&#xD;&#xA;&#xD;&#xA;out vec3 io_position;&#xD;&#xA;out vec3 io_normal;&#xD;&#xA;out vec4 io_lvs_position;&#xD;&#xA;out vec4 io_lcs_position;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;	io_position = vec3(u_model * vec4(i_position, 1.0));            //world space position&#xD;&#xA;	gl_Position = u_projection * u_view * vec4(io_position, 1.0);   //clip space position&#xD;&#xA;	io_normal = mat3(u_model) * i_normal;                           //world space normal&#xD;&#xA;	io_lvs_position = u_light_view * vec4(io_position, 1.0);        //light view space position&#xD;&#xA;	io_lcs_position = u_light_projection * io_lvs_position;         //light clip space position&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;In the fragment shader I compute the shadow factor like this:&#xD;&#xA;```&#xD;&#xA;float compute_pcss_shadow(){&#xD;&#xA;	float search_region_width = compute_search_region_width();&#xD;&#xA;	float average_blocker_depth = compute_average_blocker_depth(search_region_width);&#xD;&#xA;	if(average_blocker_depth == -1.0){&#xD;&#xA;		return 1.0;&#xD;&#xA;	}&#xD;&#xA;	float blocker_distance = compute_blocker_distance(average_blocker_depth);&#xD;&#xA;	float penumbra_width = compute_penumbra_width(blocker_distance);&#xD;&#xA;	float pcf_width = compute_pcf_width(penumbra_width);&#xD;&#xA;	return compute_pcss(pcf_width);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I imagine the ```compute_search_region_width``` function something like this:&#xD;&#xA;[![compute_search_region_width][1]][1]&#xD;&#xA;&#xD;&#xA;We basically project the light's width into the near plane and we assume everything inside the triangle is a blocker. Because of the 2 similar triangles ```search_region_width / u_light_width``` and ```(lvs_distance - u_near_plane) / lvs_distance``` are equal, so I can compute ```search_region_width```. However 3 out of 4 implementations (except diharaw's) divide the light's width by the frustum's width. I think they do that to convert the width from light view space to the (0;1) interval because in the next function we'll use this value in texture space. But if it's true it makes more sense to me computing the width in light view space and then dividing, rather than dividing the light's width. This is my implementation:&#xD;&#xA;```&#xD;&#xA;float compute_search_region_width(){&#xD;&#xA;	float lvs_distance = -io_lvs_position.z;  //shaded point's distance from the light in light view space&#xD;&#xA;	return u_light_size * (lvs_distance - u_near_plane) / lvs_distance / u_frustum_width;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;**Am I right or wrong with that ```u_frustum_width``` division?**&#xD;&#xA;&#xD;&#xA;The ```compute_average_blocker_depth``` function is just sampling the shadow map in the search region and averaging the blockers' depth.&#xD;&#xA;```&#xD;&#xA;float compute_average_blocker_depth(float search_region_width){&#xD;&#xA;	vec3 uv = io_lcs_position.xyz / io_lcs_position.w;  //conversion from clip space to NDC&#xD;&#xA;	uv = uv * 0.5 + 0.5;                                //conversion from the (-1;1) interval to the (0;1)&#xD;&#xA;	float real_depth = uv.z;&#xD;&#xA;	int blocker_count = 0;&#xD;&#xA;	float blocker_depth_sum = 0;&#xD;&#xA;&#xD;&#xA;	int step_count = u_kernel_size / 2;&#xD;&#xA;	float step_uv = search_region_width / step_count;&#xD;&#xA;	for(float x=-step_count;x&lt;=step_count;x++){&#xD;&#xA;		for(float y=-step_count;y&lt;=step_count;y++){&#xD;&#xA;			vec2 offset = vec2(x, y) * step_uv;&#xD;&#xA;			float depth = texture(u_shadow_map, uv.xy + offset).r;&#xD;&#xA;			if(depth &lt; real_depth){&#xD;&#xA;				blocker_count++;&#xD;&#xA;				blocker_depth_sum += depth;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;	if(blocker_count == 0){&#xD;&#xA;		return -1.0;&#xD;&#xA;	}else{&#xD;&#xA;		return blocker_depth_sum / blocker_count;&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;In the ```compute_blocker_distance``` function we convert the average blocker depth from the (0;1) interval to light view space. My implementation is pretty simple and similar to diharaw's and asylum2010's implementation.&#xD;&#xA;```&#xD;&#xA;float compute_blocker_distance(float average_blocker_depth){&#xD;&#xA;	return average_blocker_depth * (u_far_plane - u_near_plane) + u_near_plane;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;However in pboechat's implementation this step is completely missing and in the Nvidia implementation it looks like this:&#xD;&#xA;```&#xD;&#xA;float ZClipToZEye(float zClip)&#xD;&#xA;{&#xD;&#xA;	return g_LightZFar*g_LightZNear / (g_LightZFar - zClip*(g_LightZFar-g_LightZNear));   &#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;This piece of code doesn't make any sense to me, maybe this is because this is the only HLSL code.&#xD;&#xA;&#xD;&#xA;In the ```compute_penumbra_width``` function we determine the shadow penumbra's width in light view space, again based on similar triangles. This is how I imagine it:&#xD;&#xA;&#xD;&#xA;[![compute_penumbra_width][2]][2] &#xD;&#xA;&#xD;&#xA;Because ```penumbra_width / u_light_width``` and ```(lvs_distance - average_blocker_depth) / average_blocker_depth``` are equal, we can compute ```penumbra_width``` in light view space. My implementation is similar to asylum2010' and the Nvidia implementation:&#xD;&#xA;```&#xD;&#xA;float compute_penumbra_width(float blocker_distance){&#xD;&#xA;	float lvs_distance = -io_lvs_position.z; //shaded point's distance from the light in light view space&#xD;&#xA;	return u_light_size * (lvs_distance - blocker_distance) / blocker_distance / u_frustum_width;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I'm not entirely sure why we divide by the frustum width, but later we'll use the result in texture space rather than in light view space, so maybe this is that conversion again. In pboechat's implementation we use the shaded point's depth in the (0;1) interval, not the distance in light view space, which doesn't make any sense to me. In diharaw's implementation the computation is something like this: ```abs(zReceiver - zBlocker) / zBlocker``` and I don't understand it.&#xD;&#xA;&#xD;&#xA;The ```compute_pcf_width``` is the function what I don't understand at all. At this point I think ```penumbra_width``` is in texture space because of the division by ```u_frustum_width```. So what's the point of more conversions? But this is the point where the other implementations are very similar. Multiply the penumbra's width with the near plane and then divide by the shaded point's light view space distance (in pboechat's implementation divide by the depth). My implementation is like this:&#xD;&#xA;```&#xD;&#xA;float compute_pcf_width(float penumbra_width){&#xD;&#xA;	vec3 uv = io_lcs_position.xyz / io_lcs_position.w;  //conversion from clip space to NDC&#xD;&#xA;    uv = uv * 0.5 + 0.5;                                //conversion from the (-1;1) interval to the (0;1)&#xD;&#xA;	float real_depth = uv.z;&#xD;&#xA;	return penumbra_width * u_near_plane / real_depth;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I'm using the depth and not the light view space distance, because it looks better, but I don't understand the multiplication and the division in this function. **So what is the point of the ```compute_pcf_width``` function and how to implement it properly?**&#xD;&#xA;&#xD;&#xA;The last function, ```compute_pcss``` is a variable kernel sized PCF filter.&#xD;&#xA;```&#xD;&#xA;float compute_pcss(float pcf_width){&#xD;&#xA;	vec3 uv = io_lcs_position.xyz / io_lcs_position.w;&#xD;&#xA;	uv = uv * 0.5 + 0.5;&#xD;&#xA;	float real_depth = uv.z;&#xD;&#xA;	float result = 0;&#xD;&#xA;&#xD;&#xA;	int step_count = u_kernel_size / 2;&#xD;&#xA;	float step_uv = pcf_width / step_count;&#xD;&#xA;	for(float x=-step_count;x&lt;=step_count;x++){&#xD;&#xA;		for(float y=-step_count;y&lt;=step_count;y++){&#xD;&#xA;			vec2 offset = vec2(x, y) * step_uv;&#xD;&#xA;			float depth = texture(u_shadow_map, uv.xy + offset).r + bias;&#xD;&#xA;			if(depth &gt; real_depth){&#xD;&#xA;				result += 1.0;&#xD;&#xA;			}else{&#xD;&#xA;				result += 0.5;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;	return result / (u_kernel_size * u_kernel_size);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;This is the result with ```u_kernel_size = 27```:&#xD;&#xA;[![PCSS shadow][3]][3]&#xD;&#xA;&#xD;&#xA;The shadow is getting blurrier with distance, but the edge of the shadow looks a little strange. Also you can see some sort of issue on the right side, maybe blurred shadow acne. **So if you read all this, please tell me what is the correct implementation of PCSS and why.**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I0ks7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ESJDg.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/pj2Ia.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31059" PostHistoryTypeId="1" PostId="10655" RevisionGUID="b7a009cf-4c34-4e1a-9612-da1b99a051b6" CreationDate="2021-02-09T19:55:43.373" UserId="15740" Text="How to implement PCSS correctly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31060" PostHistoryTypeId="3" PostId="10655" RevisionGUID="b7a009cf-4c34-4e1a-9612-da1b99a051b6" CreationDate="2021-02-09T19:55:43.373" UserId="15740" Text="|opengl|shader|glsl|mathematics|shadow|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31066" PostHistoryTypeId="2" PostId="10657" RevisionGUID="2082577d-3864-4661-8042-edee5c75bd0f" CreationDate="2021-02-10T14:34:29.107" UserId="9581" Text="All the previous answers/comments were correct. The weird thing about my case was the symlinks of the libraries in the `build` directory were not valid and were not pointing to the right files. The output of `ls -lh /home/Warrior/Desktop/pathtracer/oidn/build` was as follow:&#xD;&#xA;&#xD;&#xA;    total 160K&#xD;&#xA;    drwxrwxr-x 4 amir amir 4.0K Feb  4 00:09 apps&#xD;&#xA;    -rw-rw-r-- 1 amir amir  19K Feb  4 00:09 CMakeCache.txt&#xD;&#xA;    drwxrwxr-x 7 amir amir 4.0K Feb  4 00:09 CMakeFiles&#xD;&#xA;    -rw-rw-r-- 1 amir amir 6.5K Feb  4 00:09 cmake_install.cmake&#xD;&#xA;    drwxrwxr-x 3 amir amir 4.0K Feb  4 00:09 common&#xD;&#xA;    -rw-r--r-- 1 amir amir 3.6K Feb  4 00:09 CPackConfig.cmake&#xD;&#xA;    -rw-r--r-- 1 amir amir 4.0K Feb  4 00:09 CPackSourceConfig.cmake&#xD;&#xA;    -rw-rw-r-- 1 amir amir 103K Feb  4 00:09 Makefile&#xD;&#xA;    drwxrwxr-x 3 amir amir 4.0K Feb  4 00:08 mkl-dnn&#xD;&#xA;    -rw-r--r-- 1 amir amir 1.6K Feb  4 00:09 OpenImageDenoiseConfigVersion.cmake&#xD;&#xA;&#xD;&#xA;But when I would go to the directory I would see the following:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What I did was instead of cloning the oidn repo somewhere else and building it, I cloned the oidn repo in `/home/Warrior/Desktop/pathtracer/` and built it there. After that I could see the correct file names/symlinks via `ls -lh` as follow. Now my program compiles and things work fine. I just had to use `LIBS += -L&quot;oidn/build/&quot; -lOpenImageDenoise` when compiling my code:&#xD;&#xA;&#xD;&#xA;    total 51M&#xD;&#xA;    drwxrwxr-x 4 amir amir 4.0K Feb  9 10:14 apps&#xD;&#xA;    -rw-rw-r-- 1 amir amir  19K Feb  9 10:14 CMakeCache.txt&#xD;&#xA;    drwxrwxr-x 7 amir amir 4.0K Feb  9 10:19 CMakeFiles&#xD;&#xA;    -rw-rw-r-- 1 amir amir 5.6K Feb  9 10:14 cmake_install.cmake&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.5K Feb  9 10:17 color_ispc_avx2.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.5K Feb  9 10:17 color_ispc_avx512skx.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 3.1K Feb  9 10:17 color_ispc.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.5K Feb  9 10:17 color_ispc_sse4.h&#xD;&#xA;    drwxrwxr-x 3 amir amir 4.0K Feb  9 10:14 common&#xD;&#xA;    -rw-r--r-- 1 amir amir 3.3K Feb  9 10:14 CPackConfig.cmake&#xD;&#xA;    -rw-r--r-- 1 amir amir 3.7K Feb  9 10:14 CPackSourceConfig.cmake&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.6K Feb  9 10:17 input_reorder_ispc_avx2.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.6K Feb  9 10:17 input_reorder_ispc_avx512skx.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 3.1K Feb  9 10:17 input_reorder_ispc.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.6K Feb  9 10:17 input_reorder_ispc_sse4.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir  41K Feb  9 10:14 libcommon.a&#xD;&#xA;    -rw-rw-r-- 1 amir amir  16M Feb  9 10:17 libdnnl.a&#xD;&#xA;    lrwxrwxrwx 1 amir amir   24 Feb  9 10:19 libOpenImageDenoise.so -&gt; libOpenImageDenoise.so.0&#xD;&#xA;    lrwxrwxrwx 1 amir amir   28 Feb  9 10:19 libOpenImageDenoise.so.0 -&gt; libOpenImageDenoise.so.1.3.0&#xD;&#xA;    -rwxrwxr-x 1 amir amir  34M Feb  9 10:19 libOpenImageDenoise.so.1.3.0&#xD;&#xA;    -rw-rw-r-- 1 amir amir  37K Feb  9 10:19 libutils.a&#xD;&#xA;    drwxrwxr-x 2 amir amir 4.0K Feb  9 10:17 local__core&#xD;&#xA;    -rw-rw-r-- 1 amir amir 104K Feb  9 10:14 Makefile&#xD;&#xA;    drwxrwxr-x 3 amir amir 4.0K Feb  9 10:14 mkl-dnn&#xD;&#xA;    -rwxrwxr-x 1 amir amir 181K Feb  9 10:19 oidnBenchmark&#xD;&#xA;    -rwxrwxr-x 1 amir amir  59K Feb  9 10:19 oidnDenoise&#xD;&#xA;    -rwxrwxr-x 1 amir amir 882K Feb  9 10:19 oidnTest&#xD;&#xA;    -rw-r--r-- 1 amir amir 1.6K Feb  9 10:14 OpenImageDenoiseConfigVersion.cmake&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.5K Feb  9 10:17 output_copy_ispc_avx2.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.5K Feb  9 10:17 output_copy_ispc_avx512skx.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.9K Feb  9 10:17 output_copy_ispc.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.5K Feb  9 10:17 output_copy_ispc_sse4.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.5K Feb  9 10:17 output_reorder_ispc_avx2.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.5K Feb  9 10:17 output_reorder_ispc_avx512skx.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 3.1K Feb  9 10:17 output_reorder_ispc.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 2.5K Feb  9 10:17 output_reorder_ispc_sse4.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.5K Feb  9 10:17 upsample_ispc_avx2.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.5K Feb  9 10:17 upsample_ispc_avx512skx.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.8K Feb  9 10:17 upsample_ispc.h&#xD;&#xA;    -rw-rw-r-- 1 amir amir 1.5K Feb  9 10:17 upsample_ispc_sse4.h&#xD;&#xA;    drwxrwxr-x 2 amir amir 4.0K Feb  9 10:17 weights&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8PzFE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31071" PostHistoryTypeId="2" PostId="10659" RevisionGUID="cb028268-a0f7-44ee-998d-da3c12e2f12b" CreationDate="2021-02-11T08:49:37.570" UserId="15434" Text="I have read this [article](https://learnopengl.com/PBR/Theory)&#xD;&#xA;On PBR  and in it we have NDF function defined as follows&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I have read this [article](http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html) on random vector generation&#xD;&#xA;&#xD;&#xA;Here are what I feel are the important bits.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now jump to [Importance sampling](https://learnopengl.com/PBR/IBL/Specular-IBL) here is the function&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Xi is the random vector returned from Hammersley function.&#xD;&#xA;&#xD;&#xA;Notice how I have left the theory on top of the function. He clearly says &quot;We combine the NDF with the Hammersley equation in spherical space&quot;&#xD;&#xA;&#xD;&#xA;This is my question. How did he do that? I have read the epic games real shading pdf and they don't provide any explanation whatsoever&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fG7mB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/zCxSa.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/5EY56.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/xoOUW.jpg&#xD;&#xA;&#xD;&#xA;All I need to understand is how did they derive the cosTheta and sinTheta terms.&#xD;&#xA;&#xD;&#xA;Any explanation even a one liner as an comment would be immensely appreciated.&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 4.0" />
  <row Id="31072" PostHistoryTypeId="1" PostId="10659" RevisionGUID="cb028268-a0f7-44ee-998d-da3c12e2f12b" CreationDate="2021-02-11T08:49:37.570" UserId="15434" Text="PBR : Understanding importance sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="31073" PostHistoryTypeId="3" PostId="10659" RevisionGUID="cb028268-a0f7-44ee-998d-da3c12e2f12b" CreationDate="2021-02-11T08:49:37.570" UserId="15434" Text="|pbr|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31075" PostHistoryTypeId="2" PostId="10660" RevisionGUID="dd03afb1-747a-476c-84ba-c59e13937900" CreationDate="2021-02-11T10:00:04.210" UserId="3073" Text="It looks like the parameters to your camera class are not correct&#xD;&#xA;&#xD;&#xA;     const int img_ratio = 2;&#xD;&#xA;     ...&#xD;&#xA;     Camera&lt;float&gt; cam1(20.0f, img_ratio, Point3&lt;float&gt;(0.0f, 0.0f, 0.0f), Point3&lt;float&gt;(0.0f, 0.0f, -1.0f), Vec3&lt;float&gt;(0.0f, 1.0f, 0.0f));&#xD;&#xA;&#xD;&#xA;In your code you set img_ratio to 2, I would expect it should be something like img_width/img_height (or the reverse img_height/img_width). img_ratio should also be also be a floating point to match the &lt;float&gt; type the camera class is being instantiated with.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31076" PostHistoryTypeId="2" PostId="10661" RevisionGUID="4fe172b8-465a-4261-9b26-b763e2c05bb2" CreationDate="2021-02-11T12:07:12.280" UserId="13321" Text="Generally to importance sample a funtion, you calculate it using the inverse cdf method.&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Inverse_transform_sampling &#xD;&#xA;&#xD;&#xA;From when I remember, you basically take the integral/cdf of your function and normalize it. Then you know that your random number will be proportional to the the distribution, so you inverse it so that you are calculaiting x from f(x), where f(x) will be your random number.&#xD;&#xA;&#xD;&#xA;Here it looks like they are inversing to generate n.h, which is the CosTheta. SinTheta is then just being calucated by the identity sqrt(1 - costheta^2)." ContentLicense="CC BY-SA 4.0" />
  <row Id="31082" PostHistoryTypeId="2" PostId="10663" RevisionGUID="eb31f7a0-d50d-4ca9-bd63-dec6deaa9d8e" CreationDate="2021-02-11T16:32:54.070" UserId="13456" Text="Leaving the actual derivation of mathematics aside, I'll try to give a general description of how can we combine the NDF with importance sampling in spherical coordinates.&#xD;&#xA;&#xD;&#xA;## What is NDF ?&#xD;&#xA;&#xD;&#xA;The problem is the following. Intiutively, we need the NDF for &quot;zooming in&quot; from the realm of macrosurfaces to that of microfacets.&#xD;&#xA;&#xD;&#xA;Mathematically it is needed for the following equivalence:&#xD;&#xA;&#xD;&#xA;$$dA_h = NDF(h) dw_{h} A$$.&#xD;&#xA;&#xD;&#xA;- $A$: flat macrosurface patch&#xD;&#xA;&#xD;&#xA;- $dw_{h}$: is the area of a portion of a unit spherical cap defined by the orientation $h$ &#xD;&#xA;&#xD;&#xA;- $dA_{h}$: is the total area that is being approximated by the orientation $h$&#xD;&#xA;&#xD;&#xA;see [here](http://www.reedbeta.com/blog/hows-the-ndf-really-defined/) for more.&#xD;&#xA;&#xD;&#xA;These terms are understood better when we considere the following equivalence:&#xD;&#xA;$$d\Omega = 4\pi (\frac{dS}{A})(\hat{r} \cdot \hat{n})$$&#xD;&#xA;&#xD;&#xA;You can read this equivalence as the following:&#xD;&#xA;One can approximate a solid angle subtended by a flat surface whose area equals $dS$, orientation $\hat{n}$, and distance from the viewer $r$ where $\hat{r} = \frac{\vec{r}}{r}$ and $A = 4\pi r^2$. The $\vec{r}$ is a position vector of the surface area $dS$ with respect to the center of the sphere. You can read more about it in [wikipedia](https://en.wikipedia.org/wiki/Solid_angle)&#xD;&#xA;&#xD;&#xA;The point here is that whenever we consider approximating solid angles with projected surfaces, we need that direction and distance term.&#xD;&#xA;Whether we consider solid angles over microfacets or macrosurfaces don't make a difference. From this perspective, you can think of $NDF$ as &quot;regulation&quot; term for two different granularities involved in approximating the same solid angle over the macrosurface.&#xD;&#xA;&#xD;&#xA;Since we are modeling the same structure from two different granularities, we can't &quot;touch&quot; properties that coincides with physical/geometric properties of the surfaces, but we can &quot;touch&quot; the regulation term, hence different ways of computing ndf are provided by different researchers.&#xD;&#xA;&#xD;&#xA;Whatever it maybe though, it has to satisfy the following equivalence for unit sphere:&#xD;&#xA;$$1=\frac{1}{A}\int_{S} (n \cdot h) dA_{h} = \int_{\Omega} NDF(h) (n \cdot h) dw_{h}$$&#xD;&#xA;&#xD;&#xA;Where S is the domain of the area of the macrosurface patch. This reads simply as the following: The area we are calculating as a spherical cap using solid angle bits, and the area we are calculating as a macrosurface patch using macro surface patch bits has to be the same.  &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## What is Importance Sampling ?&#xD;&#xA;&#xD;&#xA;Here is the second bit of information necessary to understand the procedure.&#xD;&#xA;Let X be a random variable $X: M \to R $ where $M$ is the sample space and $R$ is the set of real numbers. Expected value $E[X]$ is given under the probability distribution $P$ as the following $E[X;P] = \frac{1}{n} \sum_{i=1}^n x_i$ where n is the total number of samples drawn from the distribution and $x_i$ is sample generated from $X$ using the distribution P.&#xD;&#xA;&#xD;&#xA;The precision of the estimate calculated this way depends on the variance of the random variable $X$ under the probability distribution $P$. If we have infinite number of samples, then its okay to use low precision estimates, but we never do. In fact, it would be great if we have a small number of samples, with a more precise way of computing the estimate.&#xD;&#xA;&#xD;&#xA;Now think of the following, we have some random variable X, that outputs values according to some distribution, and we want to understand how X works under that distribution. Wouldn't it be better to select the input values for X so that the graph made by the output values look more like the actual graph of the X under distribution P. This is what we are trying to do with importance sampling. The key here is to understand that though we may not know how X maps values in its domain to its codomain, we may know how the probability distribution for choosing samples works. Hence if we choose a function that is similar to random variable's actual probability distribution, we can significantly reduce variance.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## How they interact ?&#xD;&#xA;&#xD;&#xA;Now coming to your question. We have seen that in order to use importance sampling we need to use function that resembles to the actual probability distribution used for sampling the spherical cap area. So if our function is $f=NDF(h) (n \cdot h)$, we need use a function that is similar to the actual probability distribution of this function to sample values from it in order to get an estimate with higher precision.&#xD;&#xA;&#xD;&#xA;Since we are dealing with points on unit sphere, we are dealing with [spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system#Integration_and_differentiation_in_spherical_coordinates). The vectors associated with these points are also in spherical coordinates. Now spherical coordinates are defined using two angles and a distance to the center of the sphere. In unit sphere the distance is 1. This leaves us with&#xD;&#xA;the two angles when considering vectors.&#xD;&#xA;&#xD;&#xA;The probability distribution that determines the output of $f$ then has two parameters, $\theta$ and $\phi$ due to using spherical coordinates.&#xD;&#xA;&#xD;&#xA;Now the [probability density function](https://en.wikipedia.org/wiki/Probability_density_function) (pdf) of $f$ is given in [here](https://www.tobias-franke.eu/log/2014/03/30/notes_on_importance_sampling.html). From that we calculate its [cumulative distribution function](https://en.wikipedia.org/wiki/Cumulative_distribution_function) (cdf) which is also given in [here](https://www.tobias-franke.eu/log/2014/03/30/notes_on_importance_sampling.html).&#xD;&#xA;&#xD;&#xA;We need the cdf because of the following property: If $T$ is a continuous random variable with cumulative distribution function $cdf(T)$, then the random variable $Y = cdf(T)$ has a uniform distribution on [0, 1]. Meaning that the inverse of $cdf(T)$ whose input would come from a uniform distribution on [0, 1] would output a value according to the probability distribution of $T$. More on that on [wikipedia](https://en.wikipedia.org/wiki/Inverse_transform_sampling) as suggested by [peter](https://computergraphics.stackexchange.com/a/10661/13456).&#xD;&#xA;&#xD;&#xA;Coming back to our point. We are looking for function closer to the actual probability distribution of $f$. Why ? Because it is the actual probability distribution that &quot;causes&quot; $f$ to output $x_i$, since the probability distribution of $f$ takes two parameters, the angles of spherical coordinate, we need to adapt pdf and cdf to deal with two parameters.&#xD;&#xA;&#xD;&#xA;It turns out, we can sample one of the angles uniformly, hence &#xD;&#xA;`phi = X_i.x * 2 * PI` given that `X_i.x` is a random number between [0,1].&#xD;&#xA;&#xD;&#xA;Then we only need to deal with pdf and cdf of a single parameter.&#xD;&#xA;If we can find out manually the inverse of cdf of that parameter, we can map a random value between [0, 1] to a value according to correct distribution of that parameter. The piece of code that deal with `X_i.y` represents that manually found inverse of cdf.&#xD;&#xA;&#xD;&#xA;You can read about the involved mathematics from: &#xD;&#xA;&#xD;&#xA;- [Here](https://www.tobias-franke.eu/log/2014/03/30/notes_on_importance_sampling.html)&#xD;&#xA;&#xD;&#xA;- [Here](https://agraphicsguynotes.com/posts/sample_microfacet_brdf/). This gives the full derivation&#xD;&#xA;&#xD;&#xA;- and [Here](http://www.reedbeta.com/blog/hows-the-ndf-really-defined/)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31084" PostHistoryTypeId="5" PostId="10663" RevisionGUID="fe7d7fd9-d215-4486-bfaf-992b00718385" CreationDate="2021-02-12T15:21:17.303" UserId="13456" Comment="improved terminology, and corrected some wording" Text="Leaving the actual derivation of mathematics aside, I'll try to give a general description of how can we combine the NDF with importance sampling in spherical coordinates.&#xD;&#xA;&#xD;&#xA;## What is NDF ?&#xD;&#xA;&#xD;&#xA;The problem is the following. Intiutively, we need the NDF for &quot;zooming in&quot; from the realm of macrosurfaces to that of microfacets.&#xD;&#xA;&#xD;&#xA;Mathematically it is needed for the following equivalence:&#xD;&#xA;&#xD;&#xA;$$dA_h = NDF(h) dw_{h} A$$.&#xD;&#xA;&#xD;&#xA;- $A$: flat macrosurface patch&#xD;&#xA;&#xD;&#xA;- $dw_{h}$: is the area of a portion of a unit spherical cap defined by the orientation $h$ &#xD;&#xA;&#xD;&#xA;- $dA_{h}$: is the total area that is being approximated by the orientation $h$&#xD;&#xA;&#xD;&#xA;see [here](http://www.reedbeta.com/blog/hows-the-ndf-really-defined/) for more.&#xD;&#xA;&#xD;&#xA;These terms are understood better when we considere the following equivalence:&#xD;&#xA;$$d\Omega = 4\pi (\frac{dS}{A})(\hat{r} \cdot \hat{n})$$&#xD;&#xA;&#xD;&#xA;You can read this equivalence as the following:&#xD;&#xA;One can approximate a solid angle subtended by a flat surface whose area equals $dS$, orientation $\hat{n}$, and distance from the viewer $r$ where $\hat{r} = \frac{\vec{r}}{r}$ and $A = 4\pi r^2$. The $\vec{r}$ is a position vector of the surface area $dS$ with respect to the center of the sphere. You can read more about it in [wikipedia](https://en.wikipedia.org/wiki/Solid_angle)&#xD;&#xA;&#xD;&#xA;The point here is that whenever we consider approximating solid angles with projected surfaces, we need that direction and distance term.&#xD;&#xA;Whether we consider solid angles over microfacets or macrosurfaces don't make a difference. From this perspective, you can think of $NDF$ as &quot;regulation&quot; term for two different granularities involved in approximating the same structure.&#xD;&#xA;&#xD;&#xA;Since we are modeling the same structure from two different granularities, we can't &quot;touch&quot; properties that coincides with physical/geometric properties of the structure, but we can &quot;touch&quot; the regulation term, hence different ways of computing ndf are provided by different researchers.&#xD;&#xA;&#xD;&#xA;Whatever it maybe though, it has to satisfy the following equivalence for unit sphere:&#xD;&#xA;$$1=\frac{1}{A}\int_{S} (n \cdot h) dA_{h} = \int_{\Omega} NDF(h) (n \cdot h) dw_{h}$$&#xD;&#xA;&#xD;&#xA;Where S is the domain of the area of the macrosurface patch. This reads simply as the following: The area we are calculating as a spherical cap using solid angle bits, and the area we are calculating as a macrosurface patch using macro surface patch bits has to be the same.  &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## What is Importance Sampling ?&#xD;&#xA;&#xD;&#xA;Here is the second bit of information necessary to understand the procedure.&#xD;&#xA;Let X be a random variable, ie a function whose signature is $X: M \to R $, where $M$ is the sample space and $R$ is the set of real numbers. Expected value $E[X]$ is given under the probability distribution $P$ as the following $E[X;P] = \frac{1}{n} \sum_{i=1}^n x_i$ where n is the total number of samples drawn from the distribution and $x_i$ is sample generated from $X$ using the distribution P.&#xD;&#xA;&#xD;&#xA;The precision of the estimate calculated this way depends on the variance of the random variable $X$ under the probability distribution $P$. If we have infinite number of samples, then its okay to use low precision estimates, but we never do. In fact, it would be great if we have a small number of samples, with a more precise way of computing the estimate.&#xD;&#xA;&#xD;&#xA;Now think of the following, we have some random variable X, that outputs values according to some distribution, and we want to understand how X works under that distribution. Wouldn't it be better to select the input values for X so that the graph made by the output values look more like the actual graph of the X under distribution P. This is what we are trying to do with importance sampling. The key here is to understand that though we may not know how X maps values in its domain to its codomain, we may know how the probability distribution for choosing samples works. Hence if we choose a function that is similar to random variable's actual probability distribution, we can significantly reduce variance.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## How they interact ?&#xD;&#xA;&#xD;&#xA;Now coming to your question. We have seen that in order to use importance sampling we need to use function that resembles to the actual probability distribution used for sampling the spherical cap area. So if our function is $f=NDF(h) (n \cdot h)$, we need use a function that is similar to the actual probability distribution of this function to sample values from it in order to get an estimate with higher precision.&#xD;&#xA;&#xD;&#xA;Since we are dealing with points on unit sphere, we are dealing with [spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system#Integration_and_differentiation_in_spherical_coordinates). The vectors associated with these points are also in spherical coordinates. Now spherical coordinates are defined using two angles and a distance to the center of the sphere. In unit sphere the distance is 1. This leaves us with&#xD;&#xA;the two angles when considering vectors.&#xD;&#xA;&#xD;&#xA;The probability distribution associated with $f$ then has two parameters, $\theta$ and $\phi$ due to using spherical coordinates.&#xD;&#xA;&#xD;&#xA;Now the [probability density function](https://en.wikipedia.org/wiki/Probability_density_function) (pdf) of $f$ is given in [here](https://www.tobias-franke.eu/log/2014/03/30/notes_on_importance_sampling.html). From that we calculate its [cumulative distribution function](https://en.wikipedia.org/wiki/Cumulative_distribution_function) (cdf) which is also given in [here](https://www.tobias-franke.eu/log/2014/03/30/notes_on_importance_sampling.html).&#xD;&#xA;&#xD;&#xA;We need the cdf because of the following property: If $T$ is a continuous random variable with cumulative distribution function $cdf(T)$, then the random variable $Y = cdf(T)$ has a uniform distribution on [0, 1]. Meaning that the inverse of $cdf(T)$ whose input would come from a uniform distribution on [0, 1] would output a value according to the probability distribution of $T$. More on that on [wikipedia](https://en.wikipedia.org/wiki/Inverse_transform_sampling) as suggested by [peter](https://computergraphics.stackexchange.com/a/10661/13456).&#xD;&#xA;&#xD;&#xA;Coming back to our point. We are looking for function closer to the actual probability distribution of $f$. Why ? Because it is the actual probability distribution that &quot;causes&quot; $f$ to output $x_i$ (sample generated in accordance with the probability distribution of random variable as stated in importance sampling section), since the probability distribution of $f$ takes two parameters, the angles of spherical coordinate, we need to adapt pdf and cdf to deal with two parameters.&#xD;&#xA;&#xD;&#xA;It turns out, we can sample one of the angles uniformly, hence &#xD;&#xA;`phi = X_i.x * 2 * PI` given that `X_i.x` is a random number between [0,1].&#xD;&#xA;&#xD;&#xA;Then we only need to deal with pdf and cdf of a single parameter.&#xD;&#xA;If we can find out manually the inverse of cdf of that parameter, we can map a random value between [0, 1] to a value according to correct distribution of that parameter. The piece of code that deal with `X_i.y` represents that manually found inverse of cdf.&#xD;&#xA;&#xD;&#xA;You can read about the involved mathematics from: &#xD;&#xA;&#xD;&#xA;- [Here](https://www.tobias-franke.eu/log/2014/03/30/notes_on_importance_sampling.html)&#xD;&#xA;&#xD;&#xA;- [Here](https://agraphicsguynotes.com/posts/sample_microfacet_brdf/). This gives the full derivation&#xD;&#xA;&#xD;&#xA;- and [Here](http://www.reedbeta.com/blog/hows-the-ndf-really-defined/)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31091" PostHistoryTypeId="2" PostId="10665" RevisionGUID="694ff23a-322d-4a6a-af98-b7ecb02b0d98" CreationDate="2021-02-14T01:58:41.020" UserId="7952" Text="There are many filters that can be used when resizing images. These filters have names like &quot;box&quot;, &quot;tent&quot;, &quot;gaussian&quot;, &quot;sinc&quot;, &quot;lanczos&quot;, and many others. Believe it or not scaling an image down in size is actually much more challenging then scaling it up in size. It is easy to lose high frequency information when resampling an image. Look for the filters in the scaling software, but most software does a good job of choosing default filters so unless you changed the filter then the issue might be...&#xD;&#xA;&#xD;&#xA;The next possible issue: jpg is not a lossless format and choosing the right size to compression setting is a trade off. Usually with jpg images a medium quality setting gives the best compression to quality ratio and only makes the image a few k bigger. This is a potential culprit. Try a &quot;high quality&quot; setting for the jpg to see if that helps, or even try a lossless format to remove image format as a potential problem.&#xD;&#xA;&#xD;&#xA;&quot;Optimized&quot; jpg's only affect the size of the file, making it slightly smaller in size.&#xD;&#xA;&#xD;&#xA;But serving images up from the web has a lot of middleware getting involved, and if these suggestions don't fix the problem then it may be the middleware which is beyond the scope of this forum.&#xD;&#xA;&#xD;&#xA;BTW: the two images look almost identical in my browser." ContentLicense="CC BY-SA 4.0" />
  <row Id="31092" PostHistoryTypeId="50" PostId="10235" RevisionGUID="d2bc8d66-70b0-4809-bdb7-a255847eb7cd" CreationDate="2021-02-14T02:07:00.720" UserId="-1" />
  <row Id="31093" PostHistoryTypeId="5" PostId="10665" RevisionGUID="eec54260-3ca6-4425-a3a7-1de2842c0da3" CreationDate="2021-02-14T02:14:10.487" UserId="7952" Comment="added 290 characters in body" Text="There are many filters that can be used when resizing images. These filters have names like &quot;box&quot;, &quot;tent&quot;, &quot;gaussian&quot;, &quot;sinc&quot;, &quot;lanczos&quot;, and many others. Believe it or not scaling an image down in size is actually much more challenging then scaling it up in size. It is easy to lose high frequency information when resampling an image. Look for the filters in the scaling software, but most software does a good job of choosing default filters so unless you changed the filter then the issue might be...&#xD;&#xA;&#xD;&#xA;The next possible issue: jpg is not a lossless format and choosing the right size to compression setting is a trade off. Usually with jpg images a medium quality setting gives the best compression to quality ratio and only makes the image a few k bigger. This is a potential culprit. Try a &quot;high quality&quot; setting for the jpg to see if that helps, or even try a lossless format to remove image format as a potential problem.&#xD;&#xA;&#xD;&#xA;To be more direct...the jpg is being sent at a larger size, with more info in it, the browser resamples giving a nice crispy image. But if you resize then that extra info is thrown away and isn't available for the browser to resample it. This is why using a higher quality jpg may help.&#xD;&#xA;&#xD;&#xA;&quot;Optimized&quot; jpg's only affect the size of the file, making it slightly smaller in size.&#xD;&#xA;&#xD;&#xA;But serving images up from the web has a lot of middleware getting involved, and if these suggestions don't fix the problem then it may be the middleware which is beyond the scope of this forum.&#xD;&#xA;&#xD;&#xA;BTW: the two images look almost identical in my browser." ContentLicense="CC BY-SA 4.0" />
  <row Id="31095" PostHistoryTypeId="2" PostId="10666" RevisionGUID="60e3fa13-9739-459f-8ba6-ab3882c8a847" CreationDate="2021-02-14T09:03:24.023" UserId="15434" Text="Most of the PBR tutorials out there use HDR maps loaded from disk. But in games these maps need to be generated by taking snapshots of the scene from the objects location which is where problems arise.&#xD;&#xA;&#xD;&#xA;Let's say there are just 2 objects with PBR material a sphere and a cube.&#xD;&#xA;&#xD;&#xA;Here are 2 problems I come across&#xD;&#xA;&#xD;&#xA;1)Each of these 2 objects need an full 360 degree view of the scene around them stored in an cubemap for proper IBL implementation which means for just 2 objects we have to render our scene 12 times!!![6 times to fill the cube map of each object] which is ridiculously expensive and this is just for 2 objects.&#xD;&#xA;Is there an alternative to this especially in dynamic scenes where objects move around all the time?&#xD;&#xA;&#xD;&#xA;2)If the sphere and the cube are very close to each other then the color of one object will depend on the light reflected from the other and this light can bounce an infinite number of times between the objects. This can be solved using recursive ray tracing where we control the bounces using an depth variable. Is there an similar recursive approach for the raserization pipeline ?[Similar to 2 mirrors facing each other and reflecting each other problem]&#xD;&#xA;&#xD;&#xA;Some theory, ideas or maybe  some linked articles would be of great help" ContentLicense="CC BY-SA 4.0" />
  <row Id="31096" PostHistoryTypeId="1" PostId="10666" RevisionGUID="60e3fa13-9739-459f-8ba6-ab3882c8a847" CreationDate="2021-02-14T09:03:24.023" UserId="15434" Text="PBR : generating dynamic HDR maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="31097" PostHistoryTypeId="3" PostId="10666" RevisionGUID="60e3fa13-9739-459f-8ba6-ab3882c8a847" CreationDate="2021-02-14T09:03:24.023" UserId="15434" Text="|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31098" PostHistoryTypeId="2" PostId="10667" RevisionGUID="eedbe89c-4ab4-452a-924f-42632a29cb7a" CreationDate="2021-02-14T20:07:25.047" UserId="7952" Text="There are no easy answers here, if you are serious then it is possible to replace cubemaps with hemispherical maps, which result in just 2 offscreen renders each instead of 6. They are not popular because the math and setup are nontrivial. RTR4 has references to papers. If you get that working do a writeup here please! Look for Dual-paraboloid shadow mapping.&#xD;&#xA;&#xD;&#xA;Another solution is to only update your maps every other frame, or every third frame. So if you have say 12 maps, then update 4 of them each frame round robin style. Also frugal culling can greatly reduce the number of faces that have to be rendered but quality is reduced. I see so many implementations that render all the geometry in the scene to every face when much of that geometry is outside the frustum of that face. This alone can increase performance but scene complexity will play a major role in overall performance.&#xD;&#xA;&#xD;&#xA;As far as infinite reflections is concerned, think about that for a second, infinite rays is going to take infinity to render no matter what your technique is. If you manage to trap photon's in a perfect reflector in real life then you can't observe it because observing it destroys the perfect reflector. I'm not trying to be sarcastic, I'm just giving a reality check.&#xD;&#xA;&#xD;&#xA;But simple techniques can get good reflections in real time. Screen Space reflections are tricky little buggers to get right but when done well can yield very nice results. You don't see many implementations around because there are a lot of corner cases to consider. Again if you get a good implementation of this working, please share it here!&#xD;&#xA;&#xD;&#xA;What you are implying in your post sounds like you would, at the very least, have to do reflections against all the cube faces, this too is not realistic, even on the best hardware, your computes are better spent someplace else, like ray tracing...&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31099" PostHistoryTypeId="2" PostId="10668" RevisionGUID="31808e51-895a-457c-8965-2a946d0ef6bc" CreationDate="2021-02-14T23:39:12.583" UserId="48" Text="Your browser and/or device are zooming the whole page by a factor of 2. The image that is supposedly 718 pixels wide on screen, is actually 1436 pixels wide in your screenshot (I measured). Probably it's an Apple device using a retina display? In any case, that's why it looks so blurry when you serve up an image that's only 718 pixels wide. In this instance, the original size of 1500 is actually much closer to the ideal resolution to serve for this device." ContentLicense="CC BY-SA 4.0" />
  <row Id="31100" PostHistoryTypeId="5" PostId="10668" RevisionGUID="c675ba17-a171-4ecc-8f91-6ec3134826e8" CreationDate="2021-02-14T23:46:28.460" UserId="48" Comment="added 233 characters in body" Text="Your browser and/or device are zooming the whole page by a factor of 2. The image that is supposedly 718 pixels wide on screen, is actually 1436 pixels wide in your screenshot (I measured). Probably it's an Apple device using a retina display? In any case, that's why it looks so blurry when you serve up an image that's only 718 pixels wide. In this instance, the original size of 1500 is actually much closer to the ideal resolution to serve for this device.&#xD;&#xA;&#xD;&#xA;More broadly speaking, pixel sizes reported in browsers (for images and everything else) don't necessarily correspond to actual physical pixels on your display. They are a sort of virtual pixel that's independent of zoom and DPI." ContentLicense="CC BY-SA 4.0" />
  <row Id="31101" PostHistoryTypeId="5" PostId="10668" RevisionGUID="46afc11b-cab0-4dd4-96d8-95df5134653e" CreationDate="2021-02-14T23:52:47.483" UserId="48" Comment="added 233 characters in body" Text="Your browser and/or device are zooming the whole page by a factor of 2. The image that is supposedly 718 pixels wide on screen, is actually 1436 pixels wide in your screenshot (I measured). Probably it's an Apple device using a retina display? In any case, that's why it looks so blurry when you serve up an image that's only 718 pixels wide. In this instance, the original size of 1500 is actually much closer to the ideal resolution to serve for this device.&#xD;&#xA;&#xD;&#xA;More broadly speaking, pixel sizes reported in browsers (for images and everything else) don't necessarily correspond to actual physical pixels on your display. They are a sort of virtual pixel that's independent of zoom and DPI. This is one reason why modern practice is to use an image with the [`srcset`](https://css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/) attribute to provide all the resolutions and let the browser choose which one to download—it will figure out the best resolution given the actual pixels on the screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="31102" PostHistoryTypeId="2" PostId="10669" RevisionGUID="ceaa2ac3-9585-44e2-9bfc-4866e179ce22" CreationDate="2021-02-15T13:55:33.157" UserId="15773" Text="I want to have separate files for common things for shaders precompiled into a spirv. &#xD;&#xA;&#xD;&#xA;For example PBR, I've got these functions and implementations for them&#xD;&#xA;```&#xD;&#xA;float NDFGGX(float NdotH, float roughness);&#xD;&#xA;float GeometrySchlickGGX(float NdotV, float k);&#xD;&#xA;float GeometrySmith(float NdotL, float NdotV, float roughness);&#xD;&#xA;vec3 FresnelSchlick(float cosTheta, vec3 F0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and I don't want to generate binaries for them every time I use it in a new shader.&#xD;&#xA;What I want is to generate a SPIRV binary file once and do whatever I want with it.&#xD;&#xA;Is this possible?&#xD;&#xA;What I've tried is to use `shaderc` library and create the binary as if it were a vertex shader, but it then needs glsl version and I don't want to always specify the glsl version. " ContentLicense="CC BY-SA 4.0" />
  <row Id="31103" PostHistoryTypeId="1" PostId="10669" RevisionGUID="ceaa2ac3-9585-44e2-9bfc-4866e179ce22" CreationDate="2021-02-15T13:55:33.157" UserId="15773" Text="Is there a way to compile part of a shader into a spirv?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31104" PostHistoryTypeId="3" PostId="10669" RevisionGUID="ceaa2ac3-9585-44e2-9bfc-4866e179ce22" CreationDate="2021-02-15T13:55:33.157" UserId="15773" Text="|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31105" PostHistoryTypeId="5" PostId="10669" RevisionGUID="15e2b1d1-0efd-4448-b8f2-84b606e9ec0a" CreationDate="2021-02-15T14:56:51.240" UserId="15773" Comment="added 4 characters in body" Text="I want to have separate files for common things for shaders precompiled into a spirv. &#xD;&#xA;&#xD;&#xA;For example PBR, I've got these functions and implementations for them&#xD;&#xA;```&#xD;&#xA;float NDFGGX(float NdotH, float roughness);&#xD;&#xA;float GeometrySchlickGGX(float NdotV, float k);&#xD;&#xA;float GeometrySmith(float NdotL, float NdotV, float roughness);&#xD;&#xA;vec3 FresnelSchlick(float cosTheta, vec3 F0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and I don't want to generate binaries for them every time I use it in a new shader.&#xD;&#xA;What I want is to generate a SPIRV binary file once and do whatever I want with it.&#xD;&#xA;Is this possible?&#xD;&#xA;What I've tried is to use `shaderc` library and create the binary as if it were a vertex shader, but it then needs glsl version and entry point. Not every file'd have entry point, doe. " ContentLicense="CC BY-SA 4.0" />
  <row Id="31106" PostHistoryTypeId="2" PostId="10670" RevisionGUID="d5c11adc-ab97-4c33-ad5d-92adcba27198" CreationDate="2021-02-15T15:03:06.880" UserId="2654" Text="What you want is generally not possible for OpenGL's SPIR-V support. SPIR-V compiles to shader objects, and shader objects theoretically allow you to link multiple objects of the same stage in a program. However, OpenGL's usage of SPIR-V [*requires* that each SPIR-V shader be a complete shader stage with its entrypoint function][1].&#xD;&#xA;&#xD;&#xA;So the requirement of shaderc mirrors the requirements of OpenGL.&#xD;&#xA;&#xD;&#xA;The best you could do is combine multiple SPIR-V binaries into a single binary *before* handing it off to OpenGL. But that's a non-trivial process, since you basically have to renumber every reference in at least one of them, and combine any references that map to the same type.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/SPIR-V#Entry_points_and_specialization" ContentLicense="CC BY-SA 4.0" />
  <row Id="31111" PostHistoryTypeId="2" PostId="10672" RevisionGUID="cd7e9ed6-c83e-4a2d-b947-da74a6f1fc26" CreationDate="2021-02-16T11:30:37.187" UserDisplayName="user15776" Text="I'm very new to computer graphics and trying to implement a raytracer based on the book *[Computer Graphics from Scratch][1]*. When I tried to add specular reflection, I don't get the output that look like on the book. I don't know how to debug this, I mean running a debugger stepwise doesn't seems to helpful. I look at the code on the book, compare the formulas, they looks like the same. Kind apologies for the long code:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;#include &lt;cmath&gt;&#xD;&#xA;#include &lt;cstdint&gt;&#xD;&#xA;#include &lt;limits&gt;&#xD;&#xA;#include &lt;utility&gt;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;&#xD;&#xA;#define STBI_ONLY_PNG        // decode only for PNG format&#xD;&#xA;#define STBI_FAILURE_USERMSG // for better image load failure messages&#xD;&#xA;#define STB_IMAGE_WRITE_IMPLEMENTATION&#xD;&#xA;#include &quot;3rdparty/stb/stb_image_write.h&quot;&#xD;&#xA;&#xD;&#xA;namespace {&#xD;&#xA;&#xD;&#xA;struct point {&#xD;&#xA;  double x{}, y{}, z{};&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct vec3d {&#xD;&#xA;  double x{}, y{}, z{};&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec3d operator-(const point p, const point q) { return vec3d{p.x - q.x, p.y - q.y, p.z - q.z}; }&#xD;&#xA;point operator+(const vec3d v, const point p) { return point{v.x + p.x, v.y + p.y, v.z + p.z}; }&#xD;&#xA;vec3d operator+(const vec3d v, const vec3d w) { return vec3d{v.x + w.x, v.y + w.y, v.z + w.z}; }&#xD;&#xA;vec3d operator-(const vec3d v, const vec3d w) { return vec3d{v.x - w.x, v.y - w.y, v.z - w.z}; }&#xD;&#xA;vec3d operator-(const vec3d v) { return vec3d{-1.0 * v.x, -1.0 * v.y, -1.0 * v.z}; }&#xD;&#xA;bool operator==(const vec3d v, const vec3d w) { return v.x == w.x &amp;&amp; v.y == w.y &amp;&amp; v.z == w.z; }&#xD;&#xA;vec3d operator*(const double k, const vec3d v) { return vec3d{k * v.x, k * v.y, k * v.z}; }&#xD;&#xA;double length(const vec3d v) { return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); }&#xD;&#xA;vec3d normalize(vec3d v) { return (1.0 / length(v)) * v; }&#xD;&#xA;double dot(const vec3d v, const vec3d w) { return (v.x * w.x) + (v.y * w.y) + (v.z * w.z); }&#xD;&#xA;&#xD;&#xA;vec3d cross(const vec3d v, const vec3d w) {&#xD;&#xA;  vec3d r;&#xD;&#xA;  r.x = v.y * w.z - v.z * w.y;&#xD;&#xA;  r.y = v.z * w.x - v.x * w.z;&#xD;&#xA;  r.z = v.x * w.y - v.y * w.x;&#xD;&#xA;&#xD;&#xA;  return r;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;} // namespace&#xD;&#xA;&#xD;&#xA;int main() {&#xD;&#xA;  using namespace std;&#xD;&#xA;&#xD;&#xA;  constexpr size_t canvas_width = 600;&#xD;&#xA;  constexpr size_t canvas_height = 600;&#xD;&#xA;  constexpr size_t channels = 4; // r,g,b,a&#xD;&#xA;&#xD;&#xA;  constexpr size_t viewport_width = 1;&#xD;&#xA;  constexpr size_t viewport_height = 1;&#xD;&#xA;  constexpr size_t viewport_distance = 1;&#xD;&#xA;&#xD;&#xA;  constexpr double minus_inf = numeric_limits&lt;double&gt;::min();&#xD;&#xA;  constexpr double plus_inf = numeric_limits&lt;double&gt;::max();&#xD;&#xA;&#xD;&#xA;  using canvas_t = uint8_t[canvas_width][canvas_height][channels];&#xD;&#xA;  using point_t = point;&#xD;&#xA;&#xD;&#xA;  struct color_t {&#xD;&#xA;    uint8_t r{}, g{}, b{}, a{};&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  enum class light_type { ambient, directional, point };&#xD;&#xA;&#xD;&#xA;  struct light {&#xD;&#xA;    light_type type;&#xD;&#xA;    double intensity;&#xD;&#xA;    point_t position;&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  struct sphere {&#xD;&#xA;    double radius;&#xD;&#xA;    point_t center;&#xD;&#xA;    color_t color;&#xD;&#xA;    int specular;&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  canvas_t canvas;&#xD;&#xA;  point_t O{0.0, 0.0, 0.0}; // camera position&#xD;&#xA;&#xD;&#xA;  const sphere sphere_1{1.0, point_t{0, -1, 3}, color_t{255, 0, 0, 255}, 500};&#xD;&#xA;  const sphere sphere_2{1.0, point_t{2, 0, 4}, color_t{255, 0, 255, 255}, 500};&#xD;&#xA;  const sphere sphere_3{1.0, point_t{-2, 0, 4}, color_t{0, 255, 0, 255}, 10};&#xD;&#xA;  const vector spheres{sphere_1, sphere_2, sphere_3};&#xD;&#xA;&#xD;&#xA;  const light light_1{light_type::ambient, 0.2};&#xD;&#xA;  const light light_2{light_type::point, 0.6, point_t{2, 1, 0}};&#xD;&#xA;  const light light_3{light_type::directional, 0.2, point_t{1, 4, 4}};&#xD;&#xA;  const vector lights{light_1, light_2, light_3};&#xD;&#xA;&#xD;&#xA;  auto canvas2viewport = [=](const double x, const double y) -&gt; vec3d {&#xD;&#xA;    const double Vx = (x * viewport_width) / canvas_width;&#xD;&#xA;    const double Vy = (y * viewport_height) / canvas_height;&#xD;&#xA;&#xD;&#xA;    return vec3d{Vx, Vy, double(viewport_distance)};&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  auto computeLighting = [&amp;](const point_t P, const vec3d N, const vec3d V, const int specular) {&#xD;&#xA;    double total_intensity = 0;&#xD;&#xA;&#xD;&#xA;    for (const auto light : lights) {&#xD;&#xA;      if (light.type == light_type::ambient) {&#xD;&#xA;        total_intensity += light.intensity;&#xD;&#xA;      } else {&#xD;&#xA;        vec3d L;&#xD;&#xA;        if (light.type == light_type::point) {&#xD;&#xA;          L = light.position - P;&#xD;&#xA;        } else {&#xD;&#xA;          L = light.position - point_t{0, 0, 0};&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (const double n_dot_l = dot(N, L); n_dot_l &gt; 0) { // diffuse reflection&#xD;&#xA;          total_intensity += light.intensity * n_dot_l / (length(N) * length(L));&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if (specular != -1) { // specular reflection&#xD;&#xA;          const vec3d R = (2 * dot(N, L) * N) - L;&#xD;&#xA;&#xD;&#xA;          if (const double r_dot_v = dot(R, V); r_dot_v &gt; 0) {&#xD;&#xA;            total_intensity += light.intensity + pow((r_dot_v / (length(R) * length(V))), specular);&#xD;&#xA;          }&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    return total_intensity;&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  auto intersectRaySphere = [=](const point_t O, const vec3d D, const sphere s) -&gt; auto {&#xD;&#xA;    const double r = s.radius;&#xD;&#xA;    const vec3d OC = O - s.center;&#xD;&#xA;&#xD;&#xA;    const double a = dot(D, D);&#xD;&#xA;    const double b = 2 * dot(OC, D);&#xD;&#xA;    const double c = dot(OC, OC) - r * r;&#xD;&#xA;&#xD;&#xA;    const double discriminant = b * b - 4 * a * c;&#xD;&#xA;&#xD;&#xA;    if (discriminant &lt; 0) {&#xD;&#xA;      return make_pair(plus_inf, plus_inf);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    const double t1 = (-b + sqrt(discriminant)) / (2 * a);&#xD;&#xA;    const double t2 = (-b - sqrt(discriminant)) / (2 * a);&#xD;&#xA;&#xD;&#xA;    return pair{t1, t2};&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  auto traceRay = [&amp;](const point_t O, const vec3d D, const int min, const int max) -&gt; color_t {&#xD;&#xA;    double closest_t = plus_inf;&#xD;&#xA;    sphere closest_sphere;&#xD;&#xA;    bool sphere_changed = false;&#xD;&#xA;&#xD;&#xA;    for (const sphere &amp;sp : spheres) {&#xD;&#xA;      const auto [t1, t2] = intersectRaySphere(O, D, sp);&#xD;&#xA;      if ((t1 &gt; min &amp;&amp; t1 &lt; max) &amp;&amp; t1 &lt; closest_t) {&#xD;&#xA;        closest_t = t1;&#xD;&#xA;        closest_sphere = sp;&#xD;&#xA;        sphere_changed = true;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      if ((t2 &gt; min &amp;&amp; t2 &lt; max) &amp;&amp; t2 &lt; closest_t) {&#xD;&#xA;        closest_t = t2;&#xD;&#xA;        closest_sphere = sp;&#xD;&#xA;        sphere_changed = true;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (!sphere_changed) {&#xD;&#xA;      return color_t{255, 255, 255, 255}; // white&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    const point_t P = closest_t * D + O;&#xD;&#xA;    vec3d N = P - closest_sphere.center;&#xD;&#xA;    N = normalize(N);&#xD;&#xA;&#xD;&#xA;    const double total_light = computeLighting(P, N, -D, closest_sphere.specular);&#xD;&#xA;&#xD;&#xA;    return color_t{uint8_t(closest_sphere.color.r * total_light),&#xD;&#xA;                   uint8_t(closest_sphere.color.g * total_light),&#xD;&#xA;                   uint8_t(closest_sphere.color.b * total_light), 255};&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  // x in [-300, 300)&#xD;&#xA;  // y in [-300, 300)&#xD;&#xA;  auto put_pixel = [&amp;](const int x, const int y, const color_t p) {&#xD;&#xA;    const size_t sx = (canvas_width / 2) + x;&#xD;&#xA;    const size_t sy = ((canvas_height / 2) - y) - 1;&#xD;&#xA;&#xD;&#xA;    if (sx &lt; 0 || sx &gt;= canvas_width || sy &lt; 0 || sy &gt;= canvas_height)&#xD;&#xA;      return;&#xD;&#xA;&#xD;&#xA;    canvas[sy][sx][0] = p.r;&#xD;&#xA;    canvas[sy][sx][1] = p.g;&#xD;&#xA;    canvas[sy][sx][2] = p.b;&#xD;&#xA;    canvas[sy][sx][3] = 255;&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  for (int y = -300; y &lt; 300; ++y) {&#xD;&#xA;    for (int x = -300; x &lt; 300; ++x) {&#xD;&#xA;      vec3d D = canvas2viewport(x, y);&#xD;&#xA;      color_t c = traceRay(O, D, 1, 100'000);&#xD;&#xA;      put_pixel(x, y, c);&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  stbi_write_png(&quot;specular_light.png&quot;, canvas_width, canvas_height, channels, canvas,&#xD;&#xA;                 canvas_width * channels);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;My output is look like this [![this][2]][2] &#xD;&#xA;&#xD;&#xA;and this [![and this][3]][3] &#xD;&#xA;&#xD;&#xA;the output on the book is :[![like this][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gabrielgambetta.com/computer-graphics-from-scratch/&#xD;&#xA;  [2]: https://i.stack.imgur.com/ifEVI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kwQ4h.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/uBRZk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31112" PostHistoryTypeId="1" PostId="10672" RevisionGUID="cd7e9ed6-c83e-4a2d-b947-da74a6f1fc26" CreationDate="2021-02-16T11:30:37.187" UserDisplayName="user15776" Text="Buggy behavior when applying specular reflection" ContentLicense="CC BY-SA 4.0" />
  <row Id="31113" PostHistoryTypeId="3" PostId="10672" RevisionGUID="cd7e9ed6-c83e-4a2d-b947-da74a6f1fc26" CreationDate="2021-02-16T11:30:37.187" UserDisplayName="user15776" Text="|raytracing|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31114" PostHistoryTypeId="2" PostId="10673" RevisionGUID="af8ec29d-4b86-48f9-9da2-c47adb34da54" CreationDate="2021-02-16T13:55:38.043" UserId="3073" Text="This code below can cause an 8bit overflow.&#xD;&#xA;&#xD;&#xA;    return color_t{uint8_t(closest_sphere.color.r * total_light),&#xD;&#xA;                       uint8_t(closest_sphere.color.g * total_light),&#xD;&#xA;                       uint8_t(closest_sphere.color.b * total_light), 255};&#xD;&#xA;&#xD;&#xA;Here values above 255 will wrap around to 0 as the upper bits are lost (e.g. 255 + 1 = 0x100, but as an 8 bit value it is 0x00). This is what is causing the banding in your image.&#xD;&#xA;&#xD;&#xA;To fix this you should check if each element of closest_sphere.color * total_light is below the maximum uint8_t value before casting from double to uint8 occurs.&#xD;&#xA;&#xD;&#xA;for example: &#xD;&#xA;&#xD;&#xA;    return color_t{uint8_t(std::min(closest_sphere.color.r * total_light, 255.0)),&#xD;&#xA;                       uint8_t(std::min(closest_sphere.color.g * total_light, 255.0)),&#xD;&#xA;                       uint8_t(std::min(closest_sphere.color.b * total_light, 255.0)), 255};&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31115" PostHistoryTypeId="5" PostId="10673" RevisionGUID="d735bf99-60a8-4b05-88b4-ea0d33eadbf9" CreationDate="2021-02-16T14:06:21.820" UserId="3073" Comment="added 113 characters in body" Text="This code below can cause an 8bit overflow.&#xD;&#xA;&#xD;&#xA;    auto traceRay = [&amp;](const point_t O, const vec3d D, const int min, const int max) -&gt; color_t {&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    return color_t{uint8_t(closest_sphere.color.r * total_light),&#xD;&#xA;                       uint8_t(closest_sphere.color.g * total_light),&#xD;&#xA;                       uint8_t(closest_sphere.color.b * total_light), 255};&#xD;&#xA;&#xD;&#xA;Here values above 255 will wrap around to 0 as the upper bits are lost (e.g. 255 + 1 = 0x100, but as an 8 bit value it is 0x00). This is what is causing the banding in your image.&#xD;&#xA;&#xD;&#xA;To fix this you should check if each element of closest_sphere.color * total_light is below the maximum uint8_t value before casting from double to uint8 occurs.&#xD;&#xA;&#xD;&#xA;for example: &#xD;&#xA;&#xD;&#xA;    return color_t{uint8_t(std::min(closest_sphere.color.r * total_light, 255.0)),&#xD;&#xA;                       uint8_t(std::min(closest_sphere.color.g * total_light, 255.0)),&#xD;&#xA;                       uint8_t(std::min(closest_sphere.color.b * total_light, 255.0)), 255};&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31119" PostHistoryTypeId="2" PostId="10675" RevisionGUID="6b93b93d-fd5f-4f62-bd1b-33ca08c0a606" CreationDate="2021-02-17T08:50:19.343" UserId="15781" Text="Absolutely there is, the Bresenham's Algorithm, modified.&#xD;&#xA;&#xD;&#xA;Instead of drawing from (x0,y0) to (x1,y1), one can use Bresenham's algorithm to draw lines from `(x0,y0*256)` to `(x1, y1*256)` still in x1-x0+1 steps, meaning that the delta_y is also multiplied by a factor of 256.&#xD;&#xA;&#xD;&#xA;At each step  `plot(x, y &gt;&gt; 256, y ^ 255); plot(x, sign(y1-y0)+(y&gt;&gt;256), y &amp; 255);`&#xD;&#xA;&#xD;&#xA;This is similarly fast, as it would use Bresenham's middle point algorithm with better error handing than Wu's algorithm (given that it suffers from error accumulation due to DDA) while also calculating the distance properly rounded. This approach of course adds one shift `y &gt;&gt; 8` one `xor` and two pixel writings. `y &amp; 255` is typically free.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31122" PostHistoryTypeId="2" PostId="10676" RevisionGUID="b55903d8-c849-4080-9863-a072c9d7261f" CreationDate="2021-02-18T12:12:52.457" UserId="7952" Text="Consider #include.&#xD;&#xA;&#xD;&#xA;We use the tools provided by [Khronos][1] to make our own compiler that is part of a larger tool providing lots specific functionality. Like handing out binding numbers, compiling spirv into linkable objects (with the restriction noted above), and others to numerous to mention here. If linking smaller SPIRV code snippets into a larger SPIRV program is something you really need then these tools could support the type of environment you are talking about, but it would take some programming. We haven't needed to go there...yet...because:&#xD;&#xA;&#xD;&#xA;Or, you could use the google include directive:&#xD;&#xA;&#xD;&#xA;    #extension GL_GOOGLE_include_directive : enable&#xD;&#xA;&#xD;&#xA;If that extension is available in your environment, which you can find out just by throwing at the top of a shader that already compiles correctly then recompiling. Then that might be &quot;good enough&quot;. But if your environment is a long term project then it may be worth the effort to dig into the tools....happy programming!&#xD;&#xA;&#xD;&#xA;If there is interest in this question I will add more specifics on using the khronos tools. Like linking, getting info about shaders, setting info in shaders, the list is long and mighty.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/SPIRV-Tools" ContentLicense="CC BY-SA 4.0" />
  <row Id="31123" PostHistoryTypeId="5" PostId="10676" RevisionGUID="3fa2e461-96df-4110-be53-bde9dc7e2f3c" CreationDate="2021-02-18T12:21:15.717" UserId="7952" Comment="added 3 characters in body" Text="Consider #include.&#xD;&#xA;&#xD;&#xA;We use the tools provided by [Khronos][1] to make our own compiler that is part of a larger tool providing lots of specific functionality. Like handing out binding numbers, compiling spirv into linkable objects (with the restriction noted above), and others to numerous to mention here. If linking smaller SPIRV code snippets into a larger SPIRV program is something you really need then these tools could support the type of environment you are talking about, but it would take some programming. We haven't needed to go there...yet...because:&#xD;&#xA;&#xD;&#xA;Or, you could use the google include directive:&#xD;&#xA;&#xD;&#xA;    #extension GL_GOOGLE_include_directive : enable&#xD;&#xA;&#xD;&#xA;If that extension is available in your environment, which you can find out just by throwing at the top of a shader that already compiles correctly then recompiling. Then that might be &quot;good enough&quot;. But if your environment is a long term project then it may be worth the effort to dig into the tools....happy programming!&#xD;&#xA;&#xD;&#xA;If there is interest in this question I will add more specifics on using the khronos tools. Like linking, getting info about shaders, setting info in shaders, the list is long and mighty. Also Khronos provides tutorials for using the tools on GitHub at the link above, though some of them are a bit hard to follow, but all in all these tools are outstanding.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/SPIRV-Tools" ContentLicense="CC BY-SA 4.0" />
  <row Id="31124" PostHistoryTypeId="5" PostId="10676" RevisionGUID="b09de783-af2f-430a-a8af-063b6ae48b24" CreationDate="2021-02-18T13:47:41.207" UserId="7952" Comment="added 485 characters in body" Text="Consider #include.&#xD;&#xA;&#xD;&#xA;We use the tools provided by [Khronos][1] to make our own compiler that is part of a larger tool providing lots of specific functionality. Like handing out binding numbers, compiling spirv into linkable objects (with the restriction noted above), and others to numerous to mention here. If linking smaller SPIRV code snippets into a larger SPIRV program is something you really need then these tools could support the type of environment you are talking about, but it would take some programming. We haven't needed to go there...yet...because:&#xD;&#xA;&#xD;&#xA;Or, you could use the google include directive:&#xD;&#xA;&#xD;&#xA;    #extension GL_GOOGLE_include_directive : enable&#xD;&#xA;&#xD;&#xA;If that extension is available in your environment, which you can find out just by throwing at the top of a shader that already compiles correctly then recompiling. Then that might be &quot;good enough&quot;. But if your environment is a long term project then it may be worth the effort to dig into the tools....happy programming!&#xD;&#xA;&#xD;&#xA;If there is interest in this question I will add more specifics on using the khronos tools. Like linking, getting info about shaders, setting info in shaders, the list is long and mighty. Also Khronos provides tutorials for using the tools on GitHub at the link above, though some of them are a bit hard to follow, but all in all these tools are outstanding.&#xD;&#xA;&#xD;&#xA;Also spirv-link.exe will combine existing SPIRV modules into a library with the --create-library option. The entry points need to have unique names and can't all be &quot;main&quot;. Then when loaded the code specifies the entry point for the module. Here is an example command line to help get anyone reading this going:&#xD;&#xA;&#xD;&#xA;    spirv-link.exe -o libraryname.spv --target-env spv1.5 input1.spv input2.spv&#xD;&#xA;&#xD;&#xA;Add --create-library to make an spv library.(which requires unique entry point names)&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/SPIRV-Tools" ContentLicense="CC BY-SA 4.0" />
  <row Id="31125" PostHistoryTypeId="5" PostId="10676" RevisionGUID="e9bae374-ee99-488a-9d3c-152ee4df7fb8" CreationDate="2021-02-18T14:12:20.327" UserId="7952" Comment="added 126 characters in body" Text="Consider #include.&#xD;&#xA;&#xD;&#xA;We use the tools provided by [Khronos][1] to make our own compiler that is part of a larger tool providing lots of specific functionality. Like handing out binding numbers, compiling spirv into linkable objects (with the restriction noted above), and others to numerous to mention here. If linking smaller SPIRV code snippets into a larger SPIRV program is something you really need then these tools could support the type of environment you are talking about, but it would take some programming. We haven't needed to go there...yet...because:&#xD;&#xA;&#xD;&#xA;Or, you could use the google include directive:&#xD;&#xA;&#xD;&#xA;    #extension GL_GOOGLE_include_directive : enable&#xD;&#xA;&#xD;&#xA;If that extension is available in your environment, which you can find out just by throwing at the top of a shader that already compiles correctly then recompiling. Then that might be &quot;good enough&quot;. But if your environment is a long term project then it may be worth the effort to dig into the tools....happy programming!&#xD;&#xA;&#xD;&#xA;If there is interest in this question I will add more specifics on using the khronos tools. Like linking, getting info about shaders, setting info in shaders, the list is long and mighty. Also Khronos provides tutorials for using the tools on GitHub at the link above, though some of them are a bit hard to follow, but all in all these tools are outstanding.&#xD;&#xA;&#xD;&#xA;Also spirv-link.exe will combine existing SPIRV modules into a library with the --create-library option. The entry points need to have unique names and can't all be &quot;main&quot;. Then when loaded the code specifies the entry point for the module. Here is an example command line to help get anyone reading this going:&#xD;&#xA;&#xD;&#xA;    spirv-link.exe -o libraryname.spv --target-env spv1.5 input1.spv input2.spv&#xD;&#xA;&#xD;&#xA;Add --create-library to make an spv library.(which requires unique entry point names)&#xD;&#xA;&#xD;&#xA;Here is a [link][2] explaining how to set the entry points in opengl.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/SPIRV-Tools&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/SPIR-V" ContentLicense="CC BY-SA 4.0" />
  <row Id="31126" PostHistoryTypeId="2" PostId="10677" RevisionGUID="59adeb35-360c-46dd-a27a-f6d9852b2809" CreationDate="2021-02-19T13:20:35.177" UserId="15574" Text="Simple question: is there a source that precedes the idea of presenting graphical application or 3D scene in a scene graph? &#xD;&#xA;&#xD;&#xA;I came across [Hierarchical geometric models for visible surface algorithms][1] which introduces the idea of having the geometry in easily searchable and cullable format. So I wonder if this is the father of the idea of having scene graph, or has there been something published earlier with this idea.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/360349.360354" ContentLicense="CC BY-SA 4.0" />
  <row Id="31127" PostHistoryTypeId="1" PostId="10677" RevisionGUID="59adeb35-360c-46dd-a27a-f6d9852b2809" CreationDate="2021-02-19T13:20:35.177" UserId="15574" Text="When and who introduced the idea of a scene graph?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31128" PostHistoryTypeId="3" PostId="10677" RevisionGUID="59adeb35-360c-46dd-a27a-f6d9852b2809" CreationDate="2021-02-19T13:20:35.177" UserId="15574" Text="|gltf|bounding-volume-hierarchy|scene-graph|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31129" PostHistoryTypeId="2" PostId="10678" RevisionGUID="52025b84-aad2-4cc8-bd61-0091d49fed17" CreationDate="2021-02-19T15:42:21.857" UserId="9581" Text="I'm implementing some mesh operations (e.g. collapse, split, flip, vertex move etc) and need to ensure applying such operations does not cause the mesh to become non-manifold. However, I'm not sure how what things I should check for to ensure my geometry doesn't become non-manifold. Can someone tell me what those conditions/checks are?&#xD;&#xA;Also, how can I apply the same operation that causes the mesh to become non-manifold so that the manifoldness of the mesh is still preserved?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31130" PostHistoryTypeId="1" PostId="10678" RevisionGUID="52025b84-aad2-4cc8-bd61-0091d49fed17" CreationDate="2021-02-19T15:42:21.857" UserId="9581" Text="Under what conditions does a mesh operation cause the mesh become non-manifold and how to avoid it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31131" PostHistoryTypeId="3" PostId="10678" RevisionGUID="52025b84-aad2-4cc8-bd61-0091d49fed17" CreationDate="2021-02-19T15:42:21.857" UserId="9581" Text="|3d|c++|algorithm|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31135" PostHistoryTypeId="2" PostId="10680" RevisionGUID="2e6bd27c-ee3e-4c12-8d6c-a05540430f50" CreationDate="2021-02-19T19:29:20.717" UserId="15795" Text="In a homework we were tasked to calculate the gradient of a triangle respective to a corner vertex. The instructions didn't say what to calculate and mentioned, one could derive it by a derivative of the triangle area using the corner vertex coordinates. I exactly came to the same formula explained by Futurologist.&#xD;&#xA;&#xD;&#xA;In case someone wants to know, this is the derivation:&#xD;&#xA;&#xD;&#xA;Let $\vec{x},\vec{y}, \vec{z} \in \mathcal{V}$ be the vertex corners of the triangle.&#xD;&#xA;&#xD;&#xA;First, the area of a triangle is the length of the cross product between two sides of it divided by 2 (because the determinant calculates the area of a parallelogram which is twice the area of the triangle):&#xD;&#xA;$A(\vec{x}) = \left|(\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right|/2 = \sqrt{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}/2$&#xD;&#xA;&#xD;&#xA;The multiplication of vectors should be the dot product whose meaning depends on the operands left and right to it. Using differential calculus rules for vectors, this is what I get:&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}} = \frac{\frac{\partial \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}{\partial \vec{x}}}{4\sqrt{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}}$&#xD;&#xA;$= \frac{\frac{\partial \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)}{\partial \vec{x}} \cdot 2\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{4A}$&#xD;&#xA;&#xD;&#xA;How to calculate the gradient of a cross product? If we would look for the divergence, we would get the determinant $\text{det}(\nabla_\vec{x},\vec{y}-\vec{x},\vec{z}-\vec{x})$ but that's not the gradient. The gradient $\partial A/\partial \vec{c}$ must be a vector itself so that $\partial(\vec{a}\times\vec{b})/\partial \vec{b}$ must be a matrix!&#xD;&#xA;Now, just think of $M \times \vec{b}$ like a matrix product but using $M_i \times \vec{b}$ to replace the dot product $M_i \cdot \vec{b}$ of a normal matrix multiplication (each result component will now be a row vector, not a scalar).&#xD;&#xA;&#xD;&#xA;Next step is to split those cross products up into a sum:&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}}= \frac{\frac{\partial \left(\vec{y}\times\vec{z}-\vec{x}\times\vec{z} - \vec{y}\times\vec{x} + \vec{x}\times\vec{x}\right)}{\partial \vec{x}} \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;&#xD;&#xA;$\vec{y}\times\vec{z}$ does not depend on $\vec{x}$, $\vec{x}\times\vec{x}$ is $\vec{0}$. It now is used that $\partial(\vec{a}\times\vec{b})/\partial \vec{b} = \vec{a}\times I$, where $I$ is the eye matrix. It is a fact that $Y_\times = \vec{y}\times I$ is the (left) cross product matrix from $\vec{y}$ so that $I \times \vec{z} = -\vec{z} \times I$ is the right cross product matrix from $\vec{z}$. Hence&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}}= \frac{\frac{\partial \left(\vec{x}\times\vec{y}-\vec{x}\times\vec{z}\right)}{\partial \vec{x}} \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left(I\times\vec{y}-I\times\vec{z}\right) \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left(I\times(\vec{y}-\vec{z})\right) \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{(\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\times(\vec{y}-\vec{z}) }{2A}$&#xD;&#xA;&#xD;&#xA;So this result is exactly the same formula as $\frac{\mathcal{J}\vec{e_{j_i}}}{2} = \frac{\vec{n}\times\vec{e_{j_i}}}{2}$ where $\vec{e_{j_i}} = \vec{y}-\vec{z}$, $i = \vec{x}$ and the direction will always show towards the opposite edge of $\vec{x}$ indepent of which vertex is chosen to be $\vec{y}$ and which is $\vec{z}$. That's the reason, why the $2$ in the original formula for $(\text{grad} f)(j)$ is needed, to divide away the factor of $2$ within the $\vec{e_{j_i}}$.&#xD;&#xA;&#xD;&#xA;If you work with parallelograms instead of triangles you can remove the $2$ entirely.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31136" PostHistoryTypeId="5" PostId="10680" RevisionGUID="ceae2707-f23d-4098-809b-f3712f901e66" CreationDate="2021-02-19T19:36:46.387" UserId="15795" Comment="added interpretation" Text="In a homework we were tasked to calculate the gradient of a triangle respective to a corner vertex. The instructions didn't say what to calculate and mentioned, one could derive it by a derivative of the triangle area using the corner vertex coordinates. I exactly came to the same formula explained by Futurologist.&#xD;&#xA;&#xD;&#xA;In case someone wants to know, this is the derivation:&#xD;&#xA;&#xD;&#xA;Let $\vec{x},\vec{y}, \vec{z} \in \mathcal{V}$ be the vertex corners of the triangle.&#xD;&#xA;&#xD;&#xA;First, the area of a triangle is the length of the cross product between two sides of it divided by 2 (because the determinant calculates the area of a parallelogram which is twice the area of the triangle):&#xD;&#xA;$A(\vec{x}) = \left|(\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right|/2 = \sqrt{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}/2$&#xD;&#xA;&#xD;&#xA;The multiplication of vectors should be the dot product whose meaning depends on the operands left and right to it. Using differential calculus rules for vectors, this is what I get:&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}} = \frac{\frac{\partial \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}{\partial \vec{x}}}{4\sqrt{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}}$&#xD;&#xA;$= \frac{\frac{\partial \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)}{\partial \vec{x}} \cdot 2\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{4A}$&#xD;&#xA;&#xD;&#xA;How to calculate the gradient of a cross product? If we would look for the divergence, we would get the determinant $\text{det}(\nabla_\vec{x},\vec{y}-\vec{x},\vec{z}-\vec{x})$ but that's not the gradient. The gradient $\partial A/\partial \vec{c}$ must be a vector itself so that $\partial(\vec{a}\times\vec{b})/\partial \vec{b}$ must be a matrix!&#xD;&#xA;Now, just think of $M \times \vec{b}$ like a matrix product but using $M_i \times \vec{b}$ to replace the dot product $M_i \cdot \vec{b}$ of a normal matrix multiplication (each result component will now be a row vector, not a scalar).&#xD;&#xA;&#xD;&#xA;Next step is to split those cross products up into a sum:&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}}= \frac{\frac{\partial \left(\vec{y}\times\vec{z}-\vec{x}\times\vec{z} - \vec{y}\times\vec{x} + \vec{x}\times\vec{x}\right)}{\partial \vec{x}} \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;&#xD;&#xA;$\vec{y}\times\vec{z}$ does not depend on $\vec{x}$, $\vec{x}\times\vec{x}$ is $\vec{0}$. It now is used that $\partial(\vec{a}\times\vec{b})/\partial \vec{b} = \vec{a}\times I$, where $I$ is the eye matrix. It is a fact that $Y_\times = \vec{y}\times I$ is the (left) cross product matrix from $\vec{y}$ so that $I \times \vec{z} = -\vec{z} \times I$ is the right cross product matrix from $\vec{z}$. Hence&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}}= \frac{\frac{\partial \left(\vec{x}\times\vec{y}-\vec{x}\times\vec{z}\right)}{\partial \vec{x}} \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left(I\times\vec{y}-I\times\vec{z}\right) \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left(I\times(\vec{y}-\vec{z})\right) \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{(\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\times(\vec{y}-\vec{z}) }{2A}$&#xD;&#xA;&#xD;&#xA;So this result is exactly the same as $\frac{\mathcal{J}\vec{e_{j_i}}}{2} = \frac{\vec{n}\times\vec{e_{j_i}}}{2}$ where $\vec{e_{j_i}} = \vec{y}-\vec{z}$, $i = \vec{x}$ and the direction will always show towards the opposite edge of $\vec{x}$ indepent of which vertex is chosen to be $\vec{y}$ and which is $\vec{z}$. That's the reason, why the $2$ in the original formula for $(\text{grad} f)(j)$ is needed, to divide away the factor of $2$ within the $\vec{e_{j_i}}$.&#xD;&#xA;&#xD;&#xA;If you work with parallelograms instead of triangles you can remove the $2$ entirely.&#xD;&#xA;&#xD;&#xA;What does the gradient of a triangle mean after all? The triangle gradient is the direction, where -- if you move $\vec{x}$ in that direction -- the triangle experiences the biggest change in area. You can add together the gradient of multiple triangles from $\vec{x}$ to use it for minimizing surface area of a discrete 3D surface.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31137" PostHistoryTypeId="50" PostId="10248" RevisionGUID="a49ed619-09a2-4123-93f5-dcca10288d67" CreationDate="2021-02-19T20:03:45.407" UserId="-1" />
  <row Id="31138" PostHistoryTypeId="5" PostId="10678" RevisionGUID="5581979e-4385-4ef4-818c-05f577f39765" CreationDate="2021-02-19T21:56:24.693" UserId="9581" Comment="deleted 13 characters in body" Text="I'm implementing some mesh operations (e.g. edge collapse, edge split, edge flip etc) and need to ensure applying such operations does not cause the mesh to become non-manifold. However, I'm not sure how what things I should check for to ensure my geometry doesn't become non-manifold. Can someone tell me what those conditions/checks are?&#xD;&#xA;Also, how can I apply the same operation that causes the mesh to become non-manifold so that the manifoldness of the mesh is still preserved?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31139" PostHistoryTypeId="5" PostId="10680" RevisionGUID="2554d4f1-9d5b-409a-8391-dd0bb2c8d81d" CreationDate="2021-02-20T00:38:32.060" UserId="15795" Comment="correcting the statement about the cross product matrix which I swapped." Text="In a homework we were tasked to calculate the gradient of a triangle respective to a corner vertex. The instructions didn't say what to calculate and mentioned, one could derive it by a derivative of the triangle area using the corner vertex coordinates. I exactly came to the same formula explained by Futurologist.&#xD;&#xA;&#xD;&#xA;In case someone wants to know, this is the derivation:&#xD;&#xA;&#xD;&#xA;Let $\vec{x},\vec{y}, \vec{z} \in \mathcal{V}$ be the vertex corners of the triangle.&#xD;&#xA;&#xD;&#xA;First, the area of a triangle is the length of the cross product between two sides of it divided by 2 (because the determinant calculates the area of a parallelogram which is twice the area of the triangle):&#xD;&#xA;$A(\vec{x}) = \left|(\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right|/2 = \sqrt{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}/2$&#xD;&#xA;&#xD;&#xA;The multiplication of vectors should be the dot product whose meaning depends on the operands left and right to it. Using differential calculus rules for vectors, this is what I get:&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}} = \frac{\frac{\partial \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}{\partial \vec{x}}}{4\sqrt{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)^2}}$&#xD;&#xA;$= \frac{\frac{\partial \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)}{\partial \vec{x}} \cdot 2\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{4A}$&#xD;&#xA;&#xD;&#xA;How to calculate the gradient of a cross product? If we would look for the divergence, we would use the determinant $\text{det}(\nabla_\vec{x},\vec{y}-\vec{x},\vec{z}-\vec{x})$ but that's not the gradient. The gradient $\partial A/\partial \vec{c}$ must be a vector itself so that $\partial(\vec{a}\times\vec{b})/\partial \vec{b}$ must be a matrix!&#xD;&#xA;Now, just think of $M \times \vec{b}$ like a matrix product but using $M_i \times \vec{b}$ to replace the dot product $M_i \cdot \vec{b}$ of a normal matrix multiplication (each result component will now be a row vector, not a scalar).&#xD;&#xA;&#xD;&#xA;Next step is to split those cross products up into a sum:&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}}= \frac{\frac{\partial \left(\vec{y}\times\vec{z}-\vec{x}\times\vec{z} - \vec{y}\times\vec{x} + \vec{x}\times\vec{x}\right)}{\partial \vec{x}} \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;&#xD;&#xA;$\vec{y}\times\vec{z}$ does not depend on $\vec{x}$, $\vec{x}\times\vec{x}$ is $\vec{0}$. It now is used that $\partial(\vec{a}\times\vec{b})/\partial \vec{a} = I\times\vec{b}$, where $I$ is the eye matrix. It is a fact that $Y_\times = I\times\vec{y}$ is the (left) cross product matrix from $\vec{y}$ so that $\left(I \times \vec{z}\right)^T = \left(I\times(-\vec{z})\right)$ is the right cross product matrix from $\vec{z}$. Hence&#xD;&#xA;&#xD;&#xA;$\frac{\partial A}{\partial \vec{x}}= \frac{\frac{\partial \left(\vec{x}\times\vec{y}-\vec{x}\times\vec{z}\right)}{\partial \vec{x}} \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left(I\times\vec{y}-I\times\vec{z}\right) \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left(I\times(\vec{y}-\vec{z})\right) \cdot \left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right) }{2A}$&#xD;&#xA;$= \frac{\left((\vec{y}-\vec{x})\times(\vec{z}-\vec{x})\right)\times(\vec{z}-\vec{y}) }{2A}$&#xD;&#xA;&#xD;&#xA;So this result is exactly the same as $-\frac{\mathcal{J}\vec{e_{j_i}}}{2} = \frac{(-\vec{n})\times\vec{e_{j_i}}}{2}$ where $\vec{e_{j_i}} = \vec{z}-\vec{y}$, $i = \vec{x}$ and the direction will always show towards the opposite edge of $\vec{x}$ indepent of which vertex is chosen to be $\vec{y}$ and which is $\vec{z}$. That's the reason, why the $2$ in the original formula for $(\text{grad} f)(j)$ is needed, to divide away the factor of $2$ within the $\vec{e_{j_i}}$.&#xD;&#xA;&#xD;&#xA;If you work with parallelograms instead of triangles you can remove the $2$ entirely.&#xD;&#xA;&#xD;&#xA;What does the gradient of a triangle mean after all? The triangle gradient is the direction, where -- if you move $\vec{x}$ in that direction -- the triangle experiences the biggest change in area. You can add together the gradient of multiple triangles from $\vec{x}$ to use it for minimizing surface area of a discrete 3D surface.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31140" PostHistoryTypeId="2" PostId="10681" RevisionGUID="89e766b3-8c82-4182-80c1-c9761e1e9e79" CreationDate="2021-02-20T08:22:06.700" UserId="15800" Text="Physically Based Rendering  https://github.com/mmp/pbrt-v3&#xD;&#xA;&#xD;&#xA;in this book, Kd Ks is diffuse albeo(diffuse color) and specular albedo(specular color)." ContentLicense="CC BY-SA 4.0" />
  <row Id="31141" PostHistoryTypeId="2" PostId="10682" RevisionGUID="5250ec62-b779-461d-88b4-d9192f7f9b09" CreationDate="2021-02-20T16:45:08.983" UserId="15802" Text="I'm new to shaders and I have been experimenting with them in shadertoy. I'm trying to get a deeper understanding of the graphics pipeline and I want to implement some features using shaders. I want to start off simple and draw a line on the screen using shaders. I wrote two-line algorithms from scratch&#xD;&#xA;```&#xD;&#xA;struct Vertex {&#xD;&#xA;    vec2 p;&#xD;&#xA;    vec4 c;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec4 overlay(vec4 c1, vec4 c2) {&#xD;&#xA;    return vec4((1.0 - c2.w) * c1.xyz + c2.w * c2.xyz, 1.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 drawLineA(Vertex v1, Vertex v2, vec2 pos) {&#xD;&#xA;    vec2 a = v1.p;&#xD;&#xA;    vec2 b = v2.p;&#xD;&#xA;    vec2 r = floor(pos);&#xD;&#xA;    &#xD;&#xA;    vec2 diff = b - a;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if (abs(diff.y) &lt; abs(diff.x)) {&#xD;&#xA;        if (diff.x &lt; 0.0) {&#xD;&#xA;            Vertex temp1 = v1;&#xD;&#xA;            Vertex temp2 = v2;&#xD;&#xA;            &#xD;&#xA;            v1 = temp2;&#xD;&#xA;            v2 = temp1;&#xD;&#xA;            &#xD;&#xA;            a = v1.p;&#xD;&#xA;            b = v2.p;&#xD;&#xA;            diff = b - a;&#xD;&#xA;        &#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        float m = diff.y / diff.x;&#xD;&#xA;        float q = r.x - a.x;&#xD;&#xA;        &#xD;&#xA;        if (floor(m * q + a.y) == r.y &amp;&amp; a.x &lt;= r.x &amp;&amp; r.x &lt;= b.x) {&#xD;&#xA;            float h = q / diff.x;&#xD;&#xA;            return vec4((1.0 - h) * v1.c + h * v2.c);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    } else {&#xD;&#xA;        if (diff.y &lt; 0.0) {&#xD;&#xA;            Vertex temp1 = v1;&#xD;&#xA;            Vertex temp2 = v2;&#xD;&#xA;            &#xD;&#xA;            v1 = temp2;&#xD;&#xA;            v2 = temp1;&#xD;&#xA;            &#xD;&#xA;            a = v1.p;&#xD;&#xA;            b = v2.p;&#xD;&#xA;            diff = b - a;&#xD;&#xA;        &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        float m =  diff.x / diff.y;&#xD;&#xA;        float q = r.y - a.y;&#xD;&#xA;        &#xD;&#xA;        if (floor(m * q + a.x) == r.x &amp;&amp; a.y &lt;= r.y &amp;&amp; r.y &lt;= b.y) {&#xD;&#xA;            float h = q / diff.y;&#xD;&#xA;            return vec4((1.0 - h) * v1.c + h * v2.c);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    return vec4(0,0,0,0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 drawLineB(Vertex v1, Vertex v2, vec2 pos) {&#xD;&#xA;    vec2 a = v1.p;&#xD;&#xA;    vec2 b = v2.p;&#xD;&#xA;    &#xD;&#xA;    vec2 l = b - a;&#xD;&#xA;    vec2 r = pos - a;&#xD;&#xA;    float h = dot(l,r) / dot (l,l);&#xD;&#xA;    &#xD;&#xA;    vec2 eC = a + h * l;&#xD;&#xA;    &#xD;&#xA;    if (floor(pos) == floor(eC) &amp;&amp; 0.0 &lt;= h &amp;&amp; h &lt;= 1.0 ) {&#xD;&#xA;       return vec4((1.0 - h) * v1.c + h * v2.c); &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    return vec4(0,0,0,0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;    float t = iTime;&#xD;&#xA;    float r = 300.0;&#xD;&#xA;    Vertex v1 = Vertex(vec2(400,225), vec4(1,0,0,1));&#xD;&#xA;    Vertex v2 = Vertex(vec2(400.0 + r*cos(t) ,225.0 + r*sin(t)), vec4(0,1,0,1));&#xD;&#xA;    &#xD;&#xA;    vec4 col = vec4(0,0,0,1);&#xD;&#xA;    col = overlay(col,drawLineA(v1, v2, fragCoord));&#xD;&#xA;    col = overlay(col,drawLineB(v1, v2, fragCoord));&#xD;&#xA;    // Output to screen&#xD;&#xA;    fragColor = col;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However, they are both quite slow, is there a more efficient line algorithm that I can use that outputs a color based on whether the pixel is in the line or not. If there is how can I implement it into my code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31142" PostHistoryTypeId="1" PostId="10682" RevisionGUID="5250ec62-b779-461d-88b4-d9192f7f9b09" CreationDate="2021-02-20T16:45:08.983" UserId="15802" Text="What is the most efficient line algorithm using a shader program" ContentLicense="CC BY-SA 4.0" />
  <row Id="31143" PostHistoryTypeId="3" PostId="10682" RevisionGUID="5250ec62-b779-461d-88b4-d9192f7f9b09" CreationDate="2021-02-20T16:45:08.983" UserId="15802" Text="|shader|fragment-shader|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31144" PostHistoryTypeId="2" PostId="10683" RevisionGUID="07c79f39-4e7b-4f02-bfcd-fa332218d03c" CreationDate="2021-02-21T01:07:18.400" UserId="7952" Text="Here is a (mostly) minimal version of an SDF for a line segment using a signed distance field as suggested in the comments. I take no credit for this code, it is your function pieced together with IQ's SDF function done in the style you listed above.&#xD;&#xA;&#xD;&#xA;Be sure to go to IQ's website, it is one of the best learning resource out there for this material. Though it can be hard to digest till you get all the basics down. [IQ's Index Page.][1]&#xD;&#xA;&#xD;&#xA;    float udSegment( in vec2 p, in vec2 a, in vec2 b )&#xD;&#xA;    {&#xD;&#xA;       vec2 ba = b-a;&#xD;&#xA;       vec2 pa = p-a;&#xD;&#xA;       float h =clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;       return length(pa-h*ba);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;	   vec2 p = ((2.0*fragCoord-iResolution.xy)/iResolution.y)*1.4;&#xD;&#xA;    &#xD;&#xA;        // give it some spin&#xD;&#xA;        vec2 v1 = iResolution.xy * vec2(cos(iTime),sin(iTime));&#xD;&#xA;    &#xD;&#xA;        vec2 v2 = vec2(0,0); // set the start point&#xD;&#xA;        float th = 0.004; // Controls line thickness&#xD;&#xA;    &#xD;&#xA;	    float d = udSegment( p, v1, v2 ) - th; // compute sdf&#xD;&#xA;    &#xD;&#xA;        vec3 col = vec3(1.0) - sign(d);&#xD;&#xA;	    fragColor = vec4(col,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://www.iquilezles.org/index.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="31145" PostHistoryTypeId="5" PostId="10682" RevisionGUID="0d4f8fd0-606b-41f1-8b0f-2f8ed463e27e" CreationDate="2021-02-21T03:36:50.187" UserId="15802" Comment="Acknowledging other line algorithms" Text="I'm new to shaders and I have been experimenting with them in shadertoy. I'm trying to get a deeper understanding of the graphics pipeline and I want to implement some features using shaders. I want to start off simple and draw a line on the screen using shaders. I wrote two-line algorithms from scratch&#xD;&#xA;```&#xD;&#xA;struct Vertex {&#xD;&#xA;    vec2 p;&#xD;&#xA;    vec4 c;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec4 overlay(vec4 c1, vec4 c2) {&#xD;&#xA;    return vec4((1.0 - c2.w) * c1.xyz + c2.w * c2.xyz, 1.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 drawLineA(Vertex v1, Vertex v2, vec2 pos) {&#xD;&#xA;    vec2 a = v1.p;&#xD;&#xA;    vec2 b = v2.p;&#xD;&#xA;    vec2 r = floor(pos);&#xD;&#xA;    &#xD;&#xA;    vec2 diff = b - a;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    if (abs(diff.y) &lt; abs(diff.x)) {&#xD;&#xA;        if (diff.x &lt; 0.0) {&#xD;&#xA;            Vertex temp1 = v1;&#xD;&#xA;            Vertex temp2 = v2;&#xD;&#xA;            &#xD;&#xA;            v1 = temp2;&#xD;&#xA;            v2 = temp1;&#xD;&#xA;            &#xD;&#xA;            a = v1.p;&#xD;&#xA;            b = v2.p;&#xD;&#xA;            diff = b - a;&#xD;&#xA;        &#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        float m = diff.y / diff.x;&#xD;&#xA;        float q = r.x - a.x;&#xD;&#xA;        &#xD;&#xA;        if (floor(m * q + a.y) == r.y &amp;&amp; a.x &lt;= r.x &amp;&amp; r.x &lt;= b.x) {&#xD;&#xA;            float h = q / diff.x;&#xD;&#xA;            return vec4((1.0 - h) * v1.c + h * v2.c);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    } else {&#xD;&#xA;        if (diff.y &lt; 0.0) {&#xD;&#xA;            Vertex temp1 = v1;&#xD;&#xA;            Vertex temp2 = v2;&#xD;&#xA;            &#xD;&#xA;            v1 = temp2;&#xD;&#xA;            v2 = temp1;&#xD;&#xA;            &#xD;&#xA;            a = v1.p;&#xD;&#xA;            b = v2.p;&#xD;&#xA;            diff = b - a;&#xD;&#xA;        &#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        float m =  diff.x / diff.y;&#xD;&#xA;        float q = r.y - a.y;&#xD;&#xA;        &#xD;&#xA;        if (floor(m * q + a.x) == r.x &amp;&amp; a.y &lt;= r.y &amp;&amp; r.y &lt;= b.y) {&#xD;&#xA;            float h = q / diff.y;&#xD;&#xA;            return vec4((1.0 - h) * v1.c + h * v2.c);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    return vec4(0,0,0,0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 drawLineB(Vertex v1, Vertex v2, vec2 pos) {&#xD;&#xA;    vec2 a = v1.p;&#xD;&#xA;    vec2 b = v2.p;&#xD;&#xA;    &#xD;&#xA;    vec2 l = b - a;&#xD;&#xA;    vec2 r = pos - a;&#xD;&#xA;    float h = dot(l,r) / dot (l,l);&#xD;&#xA;    &#xD;&#xA;    vec2 eC = a + h * l;&#xD;&#xA;    &#xD;&#xA;    if (floor(pos) == floor(eC) &amp;&amp; 0.0 &lt;= h &amp;&amp; h &lt;= 1.0 ) {&#xD;&#xA;       return vec4((1.0 - h) * v1.c + h * v2.c); &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    return vec4(0,0,0,0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;    float t = iTime;&#xD;&#xA;    float r = 300.0;&#xD;&#xA;    Vertex v1 = Vertex(vec2(400,225), vec4(1,0,0,1));&#xD;&#xA;    Vertex v2 = Vertex(vec2(400.0 + r*cos(t) ,225.0 + r*sin(t)), vec4(0,1,0,1));&#xD;&#xA;    &#xD;&#xA;    vec4 col = vec4(0,0,0,1);&#xD;&#xA;    col = overlay(col,drawLineA(v1, v2, fragCoord));&#xD;&#xA;    col = overlay(col,drawLineB(v1, v2, fragCoord));&#xD;&#xA;    // Output to screen&#xD;&#xA;    fragColor = col;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However, they are both quite slow, is there a more efficient line algorithm that I can use that outputs a color based on whether the pixel is in the line or not. I've heard that Bresenham's line algorithm is the fastest however I don't know how to use shaders to speed up the algorithm because it needs the previous y value to compute the next. Can line algorithms be sped up by shaders or is it already the fastest it can be on the CPU. If there is a optimised line drawing algorithm using the GPU (where the GPU would out-perform the cpu) how can I implement it into my code?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="31146" PostHistoryTypeId="5" PostId="10681" RevisionGUID="fa9af563-cbe4-4f18-9354-6f5ff9a010cf" CreationDate="2021-02-21T12:19:39.613" UserId="13095" Comment="Wrap link and reformulate sentence" Text="In [Physically Based Rendering](https://github.com/mmp/pbrt-v3) Kd is the diffuse albedo (diffuse color) and Ks the specular albedo (specular color)." ContentLicense="CC BY-SA 4.0" />
  <row Id="31147" PostHistoryTypeId="5" PostId="10683" RevisionGUID="9f4f5960-909c-4e56-ad60-4e03660f4bd7" CreationDate="2021-02-21T13:28:45.543" UserId="7952" Comment="added 1557 characters in body" Text="Here is a (mostly) minimal version of an SDF for a line segment using a signed distance field as suggested in the comments. I take no credit for this code, it is your function pieced together with IQ's SDF function done in the style you listed above.&#xD;&#xA;&#xD;&#xA;Be sure to go to IQ's website, it is one of the best learning resource out there for this material. Though it can be hard to digest till you get all the basics down. [IQ's Index Page.][1]&#xD;&#xA;&#xD;&#xA;    float udSegment( in vec2 p, in vec2 a, in vec2 b )&#xD;&#xA;    {&#xD;&#xA;       vec2 ba = b-a;&#xD;&#xA;       vec2 pa = p-a;&#xD;&#xA;       float h =clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );&#xD;&#xA;       //return length(pa-h*ba); // use actual length&#xD;&#xA;&#xD;&#xA;       // or use length squared&#xD;&#xA;       vec2 sqrd = pa-h*ba;&#xD;&#xA;       sqrd = sqrd * sqrd;&#xD;&#xA;       return sqrd.x+sqrd.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;	   vec2 p = ((2.0*fragCoord-iResolution.xy)/iResolution.y)*1.4;&#xD;&#xA;    &#xD;&#xA;        // give it some spin&#xD;&#xA;        vec2 v1 = iResolution.xy * vec2(cos(iTime),sin(iTime));&#xD;&#xA;    &#xD;&#xA;        vec2 v2 = vec2(0,0); // set the start point&#xD;&#xA;        float th = 0.004; // Controls line thickness&#xD;&#xA;    &#xD;&#xA;	    float d = udSegment( p, v1, v2 ) - th; // compute sdf&#xD;&#xA;    &#xD;&#xA;        vec3 col = vec3(1.0) - sign(d);&#xD;&#xA;	    fragColor = vec4(col,1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If all this is doing is drawing a line, then there is no need to compute the actual length, so don't...just return lenght squared. I made an edit to the code above that skips the sqrt, but line thickness is now squared.&#xD;&#xA;&#xD;&#xA;Bresenham's algorithm was intended to be used for drawing individual pixels and is often implemented directly in the hardware of GPU's. So it drives which pixels to draw in its own loop and tells the hardware which pixel to draw.&#xD;&#xA;&#xD;&#xA;ShaderToy is drawing the entire screen, so every pixel is covered probably by drawing a fullscreen triangle, then calling the mainImage function in the fragement shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To implement Bresenham's algorithm in ShaderToy the code would need to determine if a particular fragment was actually on the line and in so doing we lose any advantage gained by this clever line drawing technique.&#xD;&#xA;&#xD;&#xA;The most efficient way to draw a line on a GPU is not to use ShaderToy at all but write our own bit of code that tells the hardware to just draw a line, this is where graphics API's like OpenGL come into play. Which ultimately would call a fragment shader but unlike ShaderToy, the fragment shader would only be called for those fragments which are actually on the line and our fragment shader would then be reduced to something ultra simple like:&#xD;&#xA;&#xD;&#xA;    void main(){ return vec4(1,1,1,1); }&#xD;&#xA;&#xD;&#xA;Which would result in a pure white line being drawn on screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.iquilezles.org/index.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="31148" PostHistoryTypeId="50" PostId="9199" RevisionGUID="10f56ab8-3ddf-451e-bd5d-0a7d3c8ce687" CreationDate="2021-02-22T02:02:30.333" UserId="-1" />
  <row Id="31149" PostHistoryTypeId="50" PostId="9189" RevisionGUID="6f4dc963-9a7f-49ea-aa15-068040308152" CreationDate="2021-02-22T05:05:10.807" UserId="-1" />
  <row Id="31150" PostHistoryTypeId="50" PostId="10584" RevisionGUID="72d286e0-f771-4a97-a750-7c5d029626e6" CreationDate="2021-02-22T06:01:45.113" UserId="-1" />
  <row Id="31151" PostHistoryTypeId="50" PostId="8136" RevisionGUID="5582570e-42be-451f-8c0e-937513f875fd" CreationDate="2021-02-22T11:02:40.197" UserId="-1" />
  <row Id="31152" PostHistoryTypeId="2" PostId="10684" RevisionGUID="75de855a-0485-45cc-bfdb-20e007695b17" CreationDate="2021-02-22T11:18:56.807" UserId="15811" Text="I am in the process of making a 'Game' using the Unity game engine which features pre-rendered 3d background images. Currently we are using JPegs but I thought it would be nice to get some movement in them. I remembered  final Fantacy VII having really neat pre-rendered images with movement in them and researched it and they [still look great][1]. the images on this site are gifs but im not sure what compression would have been used back then, very possibly gif.I seem to recollect that animated gifs only update the area of the image which actually changes which helps with compression. My question is; Is there a modern equivalent to animated gifs which would allow me to create high quality background images with small areas of movement in them? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uMQOI.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31153" PostHistoryTypeId="1" PostId="10684" RevisionGUID="75de855a-0485-45cc-bfdb-20e007695b17" CreationDate="2021-02-22T11:18:56.807" UserId="15811" Text="Creating high quality background images for a game which have small areas of moving detail" ContentLicense="CC BY-SA 4.0" />
  <row Id="31154" PostHistoryTypeId="3" PostId="10684" RevisionGUID="75de855a-0485-45cc-bfdb-20e007695b17" CreationDate="2021-02-22T11:18:56.807" UserId="15811" Text="|rendering|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31155" PostHistoryTypeId="5" PostId="7512" RevisionGUID="aded2742-59c1-4762-94ec-2b65ee28168d" CreationDate="2021-02-22T12:10:53.687" UserId="15810" Comment="fix grammar" Text="First of all, **irradiance** at a certain point of a surface is the density of radiant flux (power) per unit of surface area, while **radiance** at a certain point of a surface in a certain direction is the density of radiant flux per unit of surface area and unit of solid angle. Vaguely speaking, **irradiance** is the amount of light incoming to a certain point from possibly all directions, while **radiance** is the amount of light incoming to a point from a single direction. Why on Earth do we talk about irradiance from a direction then?&#xD;&#xA;&#xD;&#xA;The thing is that the BRDF definition assumes that there is radiance $L_i\left(\omega_i\right)$ incoming to point $x$ through an infinitesimal cone $\mathrm{d}\omega_{i}$ around the direction $\omega_i$ with solid angle size denoted $\mathrm{d}\sigma\left(\omega_{i}\right)$, which then generates some irradiance on the surface. This &quot;partial&quot; irradiance is then denoted $\mathrm{d}E\left(\omega_{i}\right)$. This incident light can be partially absorbed by the surface and partially scattered in all directions. The out-scattered contribution of $\mathrm{d}E\left(\omega_{i}\right)$ to radiance outgoing in direction $\omega_o$ is denoted as $\mathrm{d}L_{o}\left(\omega_{o}\right)$.&#xD;&#xA;&#xD;&#xA;It can be shown experimentally that the amount of outgoing radiance $\mathrm{d}L_{o}\left(\omega_{o}\right)$ is proportional to the incoming irradiance $\mathrm{d}E\left(\omega_{i}\right)$ and the BRDF is then defined simply as the ratio between the two:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_{r}\left(\omega_{i}\rightarrow\omega_{o}\right) = \frac{\mathrm{d}L_{o}\left(\omega_{o}\right)}{\mathrm{d}E\left(\omega_{i}\right)}&#xD;&#xA;$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="31156" PostHistoryTypeId="24" PostId="7512" RevisionGUID="aded2742-59c1-4762-94ec-2b65ee28168d" CreationDate="2021-02-22T12:10:53.687" Comment="Proposed by 15810 approved by 2479 edit id of 555" ContentLicense="CC BY-SA 4.0" />
  <row Id="31157" PostHistoryTypeId="2" PostId="10685" RevisionGUID="ce2fbe98-aa9f-45a7-83ab-9070cfb1511d" CreationDate="2021-02-22T12:38:28.353" UserId="13273" Text="First of all I have a struct which looks like the following:&#xD;&#xA;&#xD;&#xA;    struct structName&#xD;&#xA;    {&#xD;&#xA;        vec3 position;&#xD;&#xA;        float radius;&#xD;&#xA;        float type;&#xD;&#xA;        ...some more information which are definitely needed! Not sure how many, but most probably less than 10&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;there are like 200 of these struct elements within my scene. When rendering the scene these objects are fixed. That mean, that they don't change during rendering the scene. They only change after rendering the scene.&#xD;&#xA;Right now I am using a SSBO to store the elements.&#xD;&#xA;Inside my vertex shader (of another geometry) I am reading out all 200 struct elements, iterate over them and make a calculation. This is slowing down my shader...&#xD;&#xA;I am trying to improve the speed of the shader. So I am looking for a better way to read the data.&#xD;&#xA;&#xD;&#xA;Lets talk about the limitations:&#xD;&#xA;&#xD;&#xA; 1. Within the shader I NEVER change any value of any element within the struct (read only).&#xD;&#xA; 2. All vertices within my other geometry need all 200 of these struct elements.&#xD;&#xA; 3. The iterated calculation result for each vertex is different (has something to do with the vertex position) So the calculation can not be outsourced.&#xD;&#xA; 4. The 200 elements will not be rendered at all. They are only information which is needed for other geometry&#xD;&#xA; 5. Each of the 200 struct elements will be changed after each render call (60 FPS =&gt; 60 times each of the elements have been changed).&#xD;&#xA; 6. The new values of the elements are calculated within another shader program (shader2). So they are &quot;read only&quot; during the render call, and &quot;read/write&quot; during the calculation in shader2.&#xD;&#xA; 7. The elements need some atomic operation functions during the calculation in shader2 (atomic add).&#xD;&#xA;&#xD;&#xA;I think to store it as a SSBO slows down my shader, because shaders are able to read/write to SSBOs so the elements are lying down on some global memory which is slow. Maybe some other buffer type is the correct one... but which one? uniform buffer objects sounds good, because uniforms are const. So maybe when using it as uniform buffer a copy will be put to a local GPU memory so that each shader instruction can access these memory faster.&#xD;&#xA;&#xD;&#xA;Which buffer type is needed to increase the FPS of my program under these circumstances?&#xD;&#xA;&#xD;&#xA;An alternative may be to read the whole buffer within the vertex shader at once? (not sure if this is possible) The size is already known (200 * sizeof(structName)). For me it is also okay, if the data is stored in an float array each value next to each other.&#xD;&#xA;&#xD;&#xA;Thanks a lot!" ContentLicense="CC BY-SA 4.0" />
  <row Id="31158" PostHistoryTypeId="1" PostId="10685" RevisionGUID="ce2fbe98-aa9f-45a7-83ab-9070cfb1511d" CreationDate="2021-02-22T12:38:28.353" UserId="13273" Text="fastest way to &quot;read only&quot; from buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="31159" PostHistoryTypeId="3" PostId="10685" RevisionGUID="ce2fbe98-aa9f-45a7-83ab-9070cfb1511d" CreationDate="2021-02-22T12:38:28.353" UserId="13273" Text="|opengl|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31160" PostHistoryTypeId="2" PostId="10686" RevisionGUID="31c1dbfe-a791-49c2-bd5a-ee6dcd1d36e7" CreationDate="2021-02-22T20:17:56.493" UserId="15817" Text="For a vision research experiment, I have a monitor that supports 10bit/channel (=30bit color). I want to render a triangle mesh in a simple scene that uses the full bit depth, and I want to save this rendering as a .png file. The rendering is just for single, static images, and doesn't need to happen lightning fast. &#xD;&#xA;&#xD;&#xA;For the triangle mesh, I have:&#xD;&#xA;&#xD;&#xA; - List of vertices in xyz coordinates&#xD;&#xA; - List of triangles containing the indices of the vertices&#xD;&#xA; - List of the vertex normals&#xD;&#xA; - List of the triangle/face normals&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My hardware includes (possibly irrelevant)&#xD;&#xA;&#xD;&#xA; - Dell UP3218K monitor - 8k and 10bits/channel&#xD;&#xA; - GeForce RTX 2080 Super (but can get a better one if needed)&#xD;&#xA;&#xD;&#xA;I tried using the pyrender library, but it outputs the rendered scene as uint8 (limiting it to 8bit). &#xD;&#xA;&#xD;&#xA;I can't find any code examples of OpenGL or PyOpenGL rendering meshes at 10bits or higher. With the increasing popularity of &gt;8bit monitors, surely this is possible?&#xD;&#xA;&#xD;&#xA;What can I use to render a mesh at 10 bit/channel depth?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31161" PostHistoryTypeId="1" PostId="10686" RevisionGUID="31c1dbfe-a791-49c2-bd5a-ee6dcd1d36e7" CreationDate="2021-02-22T20:17:56.493" UserId="15817" Text="How can I render a triangle mesh at 10bit (or 12bit or 16bit) channel depth color?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31162" PostHistoryTypeId="3" PostId="10686" RevisionGUID="31c1dbfe-a791-49c2-bd5a-ee6dcd1d36e7" CreationDate="2021-02-22T20:17:56.493" UserId="15817" Text="|opengl|rendering|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31163" PostHistoryTypeId="2" PostId="10687" RevisionGUID="ccb9d63d-7f1c-4ee6-8154-9cf44a50ff1a" CreationDate="2021-02-22T22:55:48.060" UserId="2654" Text="The &quot;modern equivalent&quot; of animated GIFs is... MPEG. Or really, any decent movie compression format. These techniques are designed to spend fewer bits on static areas and more bits on moving ones. And better still, they're designed to be dynamic, allowing motion in any are at any time, rather than only in fixed areas.&#xD;&#xA;&#xD;&#xA;So just make a short, looping movie of the &quot;background image&quot; you're trying to build. You may want to get into the details of the compression system you're working with, so that you can give lots of bits to the initial frame and fewer bits to moving areas." ContentLicense="CC BY-SA 4.0" />
  <row Id="31164" PostHistoryTypeId="50" PostId="10025" RevisionGUID="0e862787-d65a-48f2-a267-d9b177edc96b" CreationDate="2021-02-22T23:04:45.443" UserId="-1" />
  <row Id="31165" PostHistoryTypeId="2" PostId="10688" RevisionGUID="84aecfd3-43a4-4775-89f6-9e45cb4a1790" CreationDate="2021-02-22T23:42:54.843" UserId="48" Text="I think you may be focusing on the wrong thing here. Moving the data from an SSBO to a uniform buffer might give some speedup, sure, but that is a micro-optimization.&#xD;&#xA;&#xD;&#xA;I would search for algorithmic optimizations first. As noted in the comments, processing all 200 records for every vertex is both a lot of data to read, and a lot of computation to do if there's a lot of vertices. Also note that in the course of rendering, vertices will sometimes be processed more than once as they are used by multiple triangles (the vertex cache helps with this, but it can't eliminate all duplicate processing). So you will be re-doing this expensive computation multiple times for the same vertex, sometimes.&#xD;&#xA;&#xD;&#xA;Does every vertex really need to process every data element? I see that your data elements have a position and radius. If they represent some kind of mesh deformation that happens within a localized volume of space, then it might be beneficial to store those in an acceleration structure. This would allow each vertex to efficiently narrow down its processing to only those elements that affect it. For example, you could create a regular grid spanning the bounding box of your mesh, and in each grid cell store a list of indices into the main data array for the elements that intersect that grid cell. The creation of this grid could be done in a compute shader earlier in the frame, and should be quite fast. Then, when drawing the mesh, the vertex shader would look up which grid cell the vertex is in, and process those data elements. This is very similar to how we do tiled/clustered shading for light sources in many game engines.&#xD;&#xA;&#xD;&#xA;If spatial subdivision like that doesn't get the job done (for example if many of the elements are of large radius, so that most/all of the vertices really do need to process most/all of the elements), then are the elements' influences on the vertices parallelizable in any way? For instance, are you summing a perturbation generated by each element, to arrive at a total displacement for the vertex, or something along those lines? If so, you could run compute shader passes to pre-calculate the displacements and store them into a buffer to be read later by the vertex shader. The compute passes could be set up with work groups that distribute jointly over the vertices and the work elements (the exact distribution and mapping of compute threads would have to be experimented with). Each work group might, for instance, load a small chunk of vertices and a chunk of displacement elements into shared memory, calculate the displacements, then store them out to the per-vertex displacement buffer using atomic adds. Or, they might store out to various intermediate buffers (to avoid atomic contention) and have another set of compute shaders that sum up the intermediate values to obtain the final values. It would take some experimentation to see how to do it most efficiently, but you could likely get some big speedups here." ContentLicense="CC BY-SA 4.0" />
  <row Id="31169" PostHistoryTypeId="2" PostId="10690" RevisionGUID="bc3a8226-d6a6-4e8d-9f4d-6ae91db53b36" CreationDate="2021-02-23T06:36:51.613" UserId="15434" Text="We can create header files in C/C++ which we can include in our project using #include directive but when I use this keyword in my shader it gives the error  reserved keyword. If let's say I create an simple text file for adding two numbers and I want to include this file &amp; code in my vertex/fragment shader is it possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31170" PostHistoryTypeId="1" PostId="10690" RevisionGUID="bc3a8226-d6a6-4e8d-9f4d-6ae91db53b36" CreationDate="2021-02-23T06:36:51.613" UserId="15434" Text="Opengl : GLSL utility files" ContentLicense="CC BY-SA 4.0" />
  <row Id="31171" PostHistoryTypeId="3" PostId="10690" RevisionGUID="bc3a8226-d6a6-4e8d-9f4d-6ae91db53b36" CreationDate="2021-02-23T06:36:51.613" UserId="15434" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31172" PostHistoryTypeId="50" PostId="9267" RevisionGUID="64cc6251-21e6-4561-a462-81b1301f433f" CreationDate="2021-02-23T09:03:05.337" UserId="-1" />
  <row Id="31173" PostHistoryTypeId="2" PostId="10691" RevisionGUID="a13830e7-61e2-48b6-a04d-92e3adbce0c1" CreationDate="2021-02-23T09:14:31.653" UserId="7008" Text="Yes, that is possible. It is pretty much the same as in C++. Let's assume you have a file util.glsl, vertex.glsl and fragment.glsl, all in the same folder.&#xD;&#xA;&#xD;&#xA;    //in util.glsl&#xD;&#xA;    float add(float a, float b)&#xD;&#xA;    {&#xD;&#xA;        return a + b;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Then you can call that function, as if it were in your shader file&#xD;&#xA;&#xD;&#xA;    //in either vertex.glsl or fragment.glsl&#xD;&#xA;    #include &quot;util.glsl&quot;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        float result = add(1, 2);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your result would then be 3. Of course, if you have the file in a different folder, you need to adjust the path, but again, that is pretty much the same as in C++.&#xD;&#xA;&#xD;&#xA;The only caveat is with debugging. Without having tested it right now, as far as I remember compiler errors will not display your util.glsl as the source of your error. Rather it will put the contents of util.glsl at the position, where your include call is and then say you have an error in that line in vertex.glsl / fragment.glsl, so this might be a bit confusing" ContentLicense="CC BY-SA 4.0" />
  <row Id="31177" PostHistoryTypeId="50" PostId="8935" RevisionGUID="d129db85-050e-4998-8a0a-8f68a3249f8e" CreationDate="2021-02-23T22:03:45.390" UserId="-1" />
  <row Id="31179" PostHistoryTypeId="50" PostId="9875" RevisionGUID="8b0a90b9-85a8-4dfe-87c2-6d839c3041d7" CreationDate="2021-02-24T03:09:20.880" UserId="-1" />
  <row Id="31180" PostHistoryTypeId="5" PostId="10691" RevisionGUID="5f5c145c-a9e2-4dd7-99b9-b7878b7c10ba" CreationDate="2021-02-24T11:26:43.727" UserId="7008" Comment="Corrected the answer, since it was not entirely correct." Text="&lt;s&gt;Yes, &lt;/s&gt; [With a certain OpenGL extension][1], that is possible (thanks to NicolBolas for pointing that out). It is pretty much the same as in C++. Let's assume you have a file util.glsl, vertex.glsl and fragment.glsl, all in the same folder.&#xD;&#xA;&#xD;&#xA;    //in util.glsl&#xD;&#xA;    float add(float a, float b)&#xD;&#xA;    {&#xD;&#xA;        return a + b;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Then you can call that function, as if it were in your shader file&#xD;&#xA;&#xD;&#xA;    //in either vertex.glsl or fragment.glsl&#xD;&#xA;    #include &quot;util.glsl&quot;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        float result = add(1, 2);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your result would then be 3. Of course, if you have the file in a different folder, you need to adjust the path, but again, that is pretty much the same as in C++.&#xD;&#xA;&#xD;&#xA;The only caveat is with debugging. Without having tested it right now, as far as I remember compiler errors will not display your util.glsl as the source of your error. Rather it will put the contents of util.glsl at the position, where your include call is and then say you have an error in that line in vertex.glsl / fragment.glsl, so this might be a bit confusing&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://opengl.gpuinfo.org/listreports.php?extension=GL_ARB_shading_language_include" ContentLicense="CC BY-SA 4.0" />
  <row Id="31181" PostHistoryTypeId="5" PostId="10691" RevisionGUID="8c51fcb5-c717-4a34-a3a2-7ebf69c99ade" CreationDate="2021-02-24T12:06:58.557" UserId="7008" Comment="Striked out and annotad another incorrect part, linked to more information." Text="&lt;s&gt;Yes, &lt;/s&gt; [With a certain OpenGL extension][1], that is possible (thanks to NicolBolas for pointing that out). &lt;s&gt;It is pretty much the same as in C++. Let's assume you have a file util.glsl, vertex.glsl and fragment.glsl, all in the same folder.&lt;/s&gt; $^1$&#xD;&#xA;&#xD;&#xA;    //in util.glsl&#xD;&#xA;    float add(float a, float b)&#xD;&#xA;    {&#xD;&#xA;        return a + b;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Then you can call that function, as if it were in your shader file&#xD;&#xA;&#xD;&#xA;    //in either vertex.glsl or fragment.glsl&#xD;&#xA;    #include &quot;util.glsl&quot;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        float result = add(1, 2);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Your result would then be 3. Of course, if you have the file in a different folder, you need to adjust the path, but again, that is pretty much the same as in C++.&#xD;&#xA;&#xD;&#xA;The only caveat is with debugging. Without having tested it right now, as far as I remember compiler errors will not display your util.glsl as the source of your error. Rather it will put the contents of util.glsl at the position, where your include call is and then say you have an error in that line in vertex.glsl / fragment.glsl, so this might be a bit confusing&#xD;&#xA;&#xD;&#xA;$^1$Actually, this is incorrect (by default at least). In a project we used it like that, but since I did not do that setup myself, I assume it was either setup to work like that by a collegue or by OpenSceneGraph, which we used. In any case, I cannot (yet) answer this myself. I want to add this part, as soon as I understand it myself. Until then, I will simply link to a similar question with answer from NicolBolas, which hints at what you have to do: https://stackoverflow.com/questions/10754437/how-to-using-the-include-in-glsl-support-arb-shading-language-include&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://opengl.gpuinfo.org/listreports.php?extension=GL_ARB_shading_language_include" ContentLicense="CC BY-SA 4.0" />
  <row Id="31182" PostHistoryTypeId="5" PostId="10684" RevisionGUID="0123100a-04ed-44fd-b0fe-4840b8195260" CreationDate="2021-02-24T12:55:29.207" UserId="13095" Comment="Fix some typos" Text="I am in the process of making a 'Game' using the Unity game engine which features pre-rendered 3d background images. Currently, we are using JPegs but I thought it would be nice to get some movement in them. I remembered Final Fantasy VII having really neat pre-rendered images with movement in them and researched it and they [still look great][1]. the images on this site are gifs but I'm not sure what compression would have been used back then, very possibly gif. I seem to recollect that animated gifs only update the area of the image which actually changes which helps with compression. My question is: Is there a modern equivalent to animated gifs that would allow me to create high-quality background images with small areas of movement in them? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uMQOI.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31183" PostHistoryTypeId="2" PostId="10693" RevisionGUID="cb42e0cb-14d3-464b-aa8c-0cd3248186b5" CreationDate="2021-02-25T03:23:50.297" UserId="12081" Text="I've been reading [this](https://www.gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf) article on how to extract the plane equations from the view and projection matrices. And I can understand most of it. However, the only thing that is unclear to me (and that might be for lack of mathematical knowledge), is the part where they transform their inequality `0 &lt; v * (row4 + row1)` into the equality ` v * (row4 + row1) = 0` (that is for calculating the plane in the x negative side). &#xD;&#xA;&#xD;&#xA;Usually, to convert inequality to equality you use a [slack variable](https://en.wikipedia.org/wiki/Slack_variable), but in their approach, none was used. How can we be sure that ` v * (row4 + row1)` will always be zero on that frustum plane? All we know is that the resulting value of ` v * (row4 + row1)`  **has** to be positive to be on the right side of that frustum plane.&#xD;&#xA;&#xD;&#xA;I also know how the plane equation is constructed. How we use the dot product of two vectors (any vector in the plane and the normal a,b,c) must be equal to zero: `ax + by + cz + d = 0`. I can see that the resulting expression from `v * (row4 + row1) &gt; 0` results into a identical plane equation. My only doubts are in the conversion from inequality to equality.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31184" PostHistoryTypeId="1" PostId="10693" RevisionGUID="cb42e0cb-14d3-464b-aa8c-0cd3248186b5" CreationDate="2021-02-25T03:23:50.297" UserId="12081" Text="Understanding inequality to equality in the Hartmann &amp; Gribbs frustum planes extraction method" ContentLicense="CC BY-SA 4.0" />
  <row Id="31185" PostHistoryTypeId="3" PostId="10693" RevisionGUID="cb42e0cb-14d3-464b-aa8c-0cd3248186b5" CreationDate="2021-02-25T03:23:50.297" UserId="12081" Text="|opengl|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31186" PostHistoryTypeId="12" PostId="10693" RevisionGUID="63346112-a248-4f0f-a229-ba69b0410f62" CreationDate="2021-02-25T03:34:21.177" UserId="12081" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:12081,&quot;DisplayName&quot;:&quot;Hirosam&quot;}]}" />
  <row Id="31187" PostHistoryTypeId="13" PostId="10693" RevisionGUID="43d4b6db-5a08-4879-978b-a10573fb89d7" CreationDate="2021-02-25T03:35:44.087" UserId="12081" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:12081,&quot;DisplayName&quot;:&quot;Hirosam&quot;}]}" />
  <row Id="31188" PostHistoryTypeId="50" PostId="10263" RevisionGUID="f5124585-dc16-4437-b220-10365b8bff50" CreationDate="2021-02-25T10:01:25.137" UserId="-1" />
  <row Id="31192" PostHistoryTypeId="6" PostId="10693" RevisionGUID="baf2cde9-0cc6-481a-9da3-fbdc0eb40909" CreationDate="2021-02-25T17:37:37.597" UserId="12081" Comment="edited tags" Text="|opengl|mathematics|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31193" PostHistoryTypeId="2" PostId="10695" RevisionGUID="af5fd73f-c9fa-45ca-ab62-58ea9e70cec2" CreationDate="2021-02-25T18:00:47.460" UserId="48" Text="The volume _inside_ of the frustum is defined by a set of inequalities, and since we are trying to find the _boundaries_ of the frustum, we set the inequalities to equalities. That's really all it is.&#xD;&#xA;&#xD;&#xA;To take a 1D example, if we have a &quot;frustum&quot; defined by 0 &lt; x &lt; 5, then of course the bounding points of it are defined by x = 0 and x = 5. Replacing each inequality by an equality, in turn, gives you the most extreme point you can get to in that direction.&#xD;&#xA;&#xD;&#xA;Slack variables, BTW, don't really convert inequalities to equalities. They just transform the inequality into a standardized form &quot;x &gt; 0&quot; (or &quot;x ≥ 0&quot;) for some slack variable x." ContentLicense="CC BY-SA 4.0" />
  <row Id="31194" PostHistoryTypeId="2" PostId="10696" RevisionGUID="2cc64ca3-b726-4c2f-beb0-399d708b333d" CreationDate="2021-02-25T19:07:52.243" UserId="15849" Text="I'm trying to create an infinitely panable grid using fragment shaders (C++/OpenGL/GLSL), and I'm having a bit of difficulty understanding the coordinate system.&#xD;&#xA;&#xD;&#xA;This is my fragment shader code, ported over from an example on [ShaderToy][1]: &#xD;&#xA;```glsl&#xD;&#xA;#version 460 core&#xD;&#xA;&#xD;&#xA;layout(location = 0) out vec4 color;&#xD;&#xA;&#xD;&#xA;in vec2 v_Resolution;   // window size in pixels             [1000, 618]&#xD;&#xA;in vec3 v_CamPos;       // camera position in pixels         [0, 0, 0]&#xD;&#xA;in float v_CellSize;    // grid cell size in pixels          [50]&#xD;&#xA;&#xD;&#xA;// TODO: make these variables in&#xD;&#xA;float lineWidth      = 1.f;			// The width of each line (in pixels).&#xD;&#xA;float darkenMultiple = 5.f;			// Multiple of which lines are darkened (e.g. every 5th line).&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;&#xD;&#xA;	float width = lineWidth / v_CellSize;&#xD;&#xA;&#xD;&#xA;    vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y / v_Resolution.y + v_Resolution.y / 2 - v_CellSize / 2);&#xD;&#xA;&#xD;&#xA;	uv.x *= 1.0 / v_CellSize;&#xD;&#xA;	uv.y /= v_CellSize;&#xD;&#xA;&#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;	// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= gl_FragCoord.y / v_CellSize;&#xD;&#xA;&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;	uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;	&#xD;&#xA;	float grid = 0.0;&#xD;&#xA;	grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;	grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	&#xD;&#xA;	if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} else {&#xD;&#xA;		// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;		col.a = 0.0;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	color = col;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding `v_Resolution.x / 2` to `uv.x`.&#xD;&#xA;&#xD;&#xA;I believe the part that's tripping me up is when I normalize `gl_FragCoord` to `uv` by dividing it by the screen size (`v_Resolution`).&#xD;&#xA;&#xD;&#xA;From [this question][2] I know why `gl_FragCoord` is normalized, but I don't understand why in this case `uv.x = gl_FragCoord.x` while `uv.y = gl_FragCoord.y / v_Resolution.y`. Why would I divide the y-component by the screen height, but not the x-component by the screen width? If I try to divide `gl_FragCoord.x` by the screen width, the entire shader breaks, and the grid columns are not rendered. This is especially strange to me, because in the [ShaderToy][1] example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;The entire code can be downloaded and compiled (Windows, OpenGL 4.5) from my GitHub repo: https://github.com/wooandrew/boomerang/tree/develop&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/4sj3DG&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/5724/glsl-can-someone-explain-why-gl-fragcoord-xy-screensize-is-performed-and-for" ContentLicense="CC BY-SA 4.0" />
  <row Id="31195" PostHistoryTypeId="1" PostId="10696" RevisionGUID="2cc64ca3-b726-4c2f-beb0-399d708b333d" CreationDate="2021-02-25T19:07:52.243" UserId="15849" Text="Understanding fragment shader coordinate system" ContentLicense="CC BY-SA 4.0" />
  <row Id="31196" PostHistoryTypeId="3" PostId="10696" RevisionGUID="2cc64ca3-b726-4c2f-beb0-399d708b333d" CreationDate="2021-02-25T19:07:52.243" UserId="15849" Text="|opengl|glsl|c++|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31200" PostHistoryTypeId="5" PostId="10567" RevisionGUID="5b904085-701a-4717-a0bc-1db794c5357a" CreationDate="2021-02-26T09:17:25.783" UserId="15415" Comment="added 64 characters in body" Text="I4=I1( 1-t ) + t.I2 ; from parametric equation of line&#xD;&#xA;&#xD;&#xA;I4=I1 - I1.t + t. I2&#xD;&#xA;&#xD;&#xA;I4=I1+ t (I2-I1)&#xD;&#xA;Let's take line AB apart from triangle &#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/cqxtR.jpg)&#xD;&#xA;below in the equation I multiply t&lt;sup&gt;2&lt;/sup&gt; to numerator an denominator" ContentLicense="CC BY-SA 4.0" />
  <row Id="31201" PostHistoryTypeId="5" PostId="10567" RevisionGUID="571383b5-df5c-47b7-bbc9-5a75ee329d10" CreationDate="2021-02-26T09:25:16.783" UserId="15415" Comment="added 64 characters in body" Text="I&lt;sub&gt;4&lt;/sub&gt;=I&lt;sub&gt;1&lt;/sub&gt;  ( 1-t ) + t.I&lt;sub&gt;2&lt;/sub&gt;  ; from parametric equation of line&#xD;&#xA;&#xD;&#xA;I4=I1 - I1.t + t. I2&#xD;&#xA;&#xD;&#xA;I4=I1+ t (I2-I1)&#xD;&#xA;Let's take line AB apart from triangle &#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/cqxtR.jpg)&#xD;&#xA;below in the equation I multiply t&lt;sup&gt;2&lt;/sup&gt; to numerator an denominator" ContentLicense="CC BY-SA 4.0" />
  <row Id="31208" PostHistoryTypeId="2" PostId="10698" RevisionGUID="c245a847-e4ac-4275-a835-7fb0c832bb42" CreationDate="2021-02-27T08:12:19.107" UserId="10332" Text="How do you allow a function to accept a reference of a double array ? For example:&#xD;&#xA;&#xD;&#xA;    MyFunc(uint x, uint y, float2[][] myArray) {}&#xD;&#xA;&#xD;&#xA;I get `unexpected [` error does it allow reference passes like this?&#xD;&#xA;&#xD;&#xA;I am trying to pass this to my function:&#xD;&#xA;&#xD;&#xA;    float2 _switchBuffer[2][128]&#xD;&#xA;    float2 _switchBuffer[2][256]`&#xD;&#xA;&#xD;&#xA;This is declared as one of my properties that the entire shader has access to so i need the kernel to pass the relevant switchbuffer to the functions.&#xD;&#xA;&#xD;&#xA;So i have something like:&#xD;&#xA;&#xD;&#xA;    void FFT128 (uint3 id : SV_DispatchThreadID)  { Test(id.xy, 3, _switchBuffer128); }&#xD;&#xA;    void FFT256 (uint3 id : SV_DispatchThreadID)  { FFT1D(id.xy, 3, _swotchBuffer256); }" ContentLicense="CC BY-SA 4.0" />
  <row Id="31209" PostHistoryTypeId="1" PostId="10698" RevisionGUID="c245a847-e4ac-4275-a835-7fb0c832bb42" CreationDate="2021-02-27T08:12:19.107" UserId="10332" Text="How to pass a 2D array to a function" ContentLicense="CC BY-SA 4.0" />
  <row Id="31210" PostHistoryTypeId="3" PostId="10698" RevisionGUID="c245a847-e4ac-4275-a835-7fb0c832bb42" CreationDate="2021-02-27T08:12:19.107" UserId="10332" Text="|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31214" PostHistoryTypeId="50" PostId="8888" RevisionGUID="0c387f9f-7583-4406-b9e8-875d090c3173" CreationDate="2021-02-27T16:07:10.720" UserId="-1" />
  <row Id="31215" PostHistoryTypeId="2" PostId="10700" RevisionGUID="e92b6c51-3b83-44a4-9782-792a50291630" CreationDate="2021-02-27T21:37:37.063" UserId="15856" Text="I am working with a PWP3D-like algorithm that renders silhouettes of a mesh in order to segment a frame of video and update an object's pose. Because it is only the silhouettes of the mesh that matter, it would be nice to automatically generate simpler meshes where the indents/concavities that do not affect the silhouette are removed. That is, I want to generate a simpler mesh that has the exact same silhouette as the original when viewed at any angle from any position outside of the mesh's convex hull.&#xD;&#xA;&#xD;&#xA;Is there an existing technique for doing this? Or even just some definitions other than &quot;indent&quot; that better describe this problem that might aid in a web search for this? I've currently found mesh simplification/decimation techniques that aim to preserve silhouettes, but these are not exactly what I'm looking for right now, and they generally seem to just simplify indents rather than outright removing/filling them. I have an idea for an algorithm that I think would work, but I want to check if anything else already exists.&#xD;&#xA;&#xD;&#xA;As a visual example of what I mean, below is a mesh that, if such a technique were applied, would have the orange-highlighted faces removed and be turned into an ordinary cube.&#xD;&#xA;&#xD;&#xA;[![An example of a mesh that would become a cube if such a technique were applied][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZgizM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31216" PostHistoryTypeId="1" PostId="10700" RevisionGUID="e92b6c51-3b83-44a4-9782-792a50291630" CreationDate="2021-02-27T21:37:37.063" UserId="15856" Text="Existing method to automatically fill in this sort of concavity in meshes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31217" PostHistoryTypeId="3" PostId="10700" RevisionGUID="e92b6c51-3b83-44a4-9782-792a50291630" CreationDate="2021-02-27T21:37:37.063" UserId="15856" Text="|algorithm|computational-geometry|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31218" PostHistoryTypeId="2" PostId="10701" RevisionGUID="26661782-f2a8-40c6-b474-8ac015da61e6" CreationDate="2021-02-27T23:48:51.543" UserId="48" Text="Unsized arrays aren't implemented in HLSL. You can pass fixed-size arrays into functions like&#xD;&#xA;&#xD;&#xA;    void foo(float2 x[2][4])&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;(Note the brackets go after the parameter name, not after the type—just like declaring a variable.)&#xD;&#xA;&#xD;&#xA;However, having different array sizes that can be passed into the same function won't work in HLSL the way it would in C/C++. For variable-size data, better to use a buffer resource, such as a constant buffer, structured buffer, etc (depending on what you're doing with this data). Or if it's in `groupshared` memory, you'll have to specify a maximum size and allocate the array for that." ContentLicense="CC BY-SA 4.0" />
  <row Id="31219" PostHistoryTypeId="5" PostId="10700" RevisionGUID="847baadb-7697-4e9b-8a9c-9ea97198cc57" CreationDate="2021-02-28T00:10:20.270" UserId="15856" Comment="added 227 characters in body" Text="I am working with a PWP3D-like algorithm that renders silhouettes of a mesh in order to segment a frame of video and update an object's pose. Because it is only the silhouettes of the mesh that matter, it would be nice to automatically generate simpler meshes where the indents/concavities that do not affect the silhouette are removed. That is, I want to generate a simpler mesh that has the exact same silhouette as the original when viewed at any angle from any position outside of the mesh's convex hull.&#xD;&#xA;&#xD;&#xA;Is there an existing technique for doing this? Or even just some definitions other than &quot;indent&quot; that better describe this problem that might aid in a web search for this? I've currently found mesh simplification/decimation techniques that aim to preserve silhouettes, but these are not exactly what I'm looking for right now, and they generally seem to just simplify indents rather than outright removing/filling them. I have an idea for an algorithm that I think would work, but I want to check if anything else already exists.&#xD;&#xA;&#xD;&#xA;As a visual example of what I mean, below is a mesh that, if such a technique were applied, would have the orange-highlighted faces removed and be turned into an ordinary cube.&#xD;&#xA;&#xD;&#xA;[![An example of a mesh that would become a cube if such a technique were applied][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At the same time, though, the problem is not as simple as just taking the convex hull, because this mesh, for example, is fine as it is.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZgizM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cg6p5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31220" PostHistoryTypeId="5" PostId="10700" RevisionGUID="7b01c85f-2ae0-4a57-a6c7-c1f8cbb91b33" CreationDate="2021-02-28T00:38:10.683" UserId="15856" Comment="added 4 characters in body" Text="I am working with a PWP3D-like algorithm that renders silhouettes of a mesh in order to segment a frame of video and update an object's pose. Because it is only the silhouettes of the mesh that matter, it would be nice to automatically generate simpler meshes where the indents/concavities that do not affect the silhouette are removed. That is, I want to generate a simpler mesh that has the exact same silhouette as the original when viewed at any angle from any position outside of the mesh's convex hull.&#xD;&#xA;&#xD;&#xA;Is there an existing technique for doing this? Or even just some definitions other than &quot;indent&quot; that better describe this problem that might aid in a web search for this? I've currently found mesh simplification/decimation techniques that aim to preserve silhouettes, but these are not exactly what I'm looking for right now, and they generally seem to just simplify indents rather than outright removing/filling them. I have an idea for an algorithm that I think would work, but I want to check if anything else already exists.&#xD;&#xA;&#xD;&#xA;As a visual example of what I mean, below is a mesh that, if such a technique were applied, would have the orange-highlighted faces removed and be turned into an ordinary cube.&#xD;&#xA;&#xD;&#xA;[![An example of a mesh that would become a cube if such a technique were applied][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At the same time, though, the problem is not as simple as just taking the convex hull, because this mesh, for example, is fine as it is.&#xD;&#xA;[![A mesh shaped like a 3D letter C][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZgizM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Cg6p5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31222" PostHistoryTypeId="50" PostId="10561" RevisionGUID="1c12c27f-df0b-417c-9504-582c099527cc" CreationDate="2021-02-28T16:03:00.317" UserId="-1" />
  <row Id="31223" PostHistoryTypeId="50" PostId="10607" RevisionGUID="8651fc98-e7ba-42c8-9564-0c3f03a6ce29" CreationDate="2021-02-28T17:02:10.210" UserId="-1" />
  <row Id="31224" PostHistoryTypeId="2" PostId="10702" RevisionGUID="0f380a82-b0ca-44a9-9477-168dc48bba9c" CreationDate="2021-02-28T20:27:57.833" UserId="15860" Text="What is the name of the style of the line graphics used in the image below? The line patterns seem to envelope the shape of the woman maybe algorithmically somehow, becoming denser and yellow on the chest. &#xD;&#xA;&#xD;&#xA;Are there other artists that employ this technique, or where it was borrowed from?&#xD;&#xA;&#xD;&#xA;Besides the line patterns, the coloring of the lines gives a holographic sort of feeling. Is there also a distinct style name for the coloring scheme used for the lines?&#xD;&#xA;&#xD;&#xA;Any ideas overall on which software and computer graphics/machine learning techniques were used to create the line patterns and colors?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YGc7x.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31225" PostHistoryTypeId="1" PostId="10702" RevisionGUID="0f380a82-b0ca-44a9-9477-168dc48bba9c" CreationDate="2021-02-28T20:27:57.833" UserId="15860" Text="Name and influence of style used for futuristic line patterns?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31226" PostHistoryTypeId="3" PostId="10702" RevisionGUID="0f380a82-b0ca-44a9-9477-168dc48bba9c" CreationDate="2021-02-28T20:27:57.833" UserId="15860" Text="|color|line-drawing|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31227" PostHistoryTypeId="2" PostId="10703" RevisionGUID="e99e1cbb-cc2b-4bfa-acaf-b533db9aa2b4" CreationDate="2021-02-28T21:05:49.297" UserId="506" Text="That looks a lot like it’s based on the [straight skeleton](https://en.wikipedia.org/wiki/Straight_skeleton) of some outline shapes drawn on the image. You can see similar structures in the middle one of these diagrams from [a research page](https://www.sthu.org/research/straightskeleton/) by Stefan Huber, one of the researchers who’s published a lot of work on straight skeletons:&#xD;&#xA;![a series of images of Tux, the Linux penguin mascot, one with skeletal patterns overlaid and one with isocontours derived from those patterns](https://i.stack.imgur.com/lsY7C.png)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31228" PostHistoryTypeId="5" PostId="10696" RevisionGUID="aa60d9ea-1fd1-4f6b-bceb-041ab0a8be25" CreationDate="2021-03-01T20:33:25.207" UserId="15849" Comment="added 551 characters in body" Text="I'm trying to create an infinitely panable grid using fragment shaders (C++/OpenGL/GLSL), and I'm having a bit of difficulty understanding the coordinate system.&#xD;&#xA;&#xD;&#xA;This is my fragment shader code, ported over from an example on [ShaderToy][1]: &#xD;&#xA;```glsl&#xD;&#xA;#version 460 core&#xD;&#xA;&#xD;&#xA;layout(location = 0) out vec4 color;&#xD;&#xA;&#xD;&#xA;in vec2 v_Resolution;   // window size in pixels             [1000, 618]&#xD;&#xA;in vec3 v_CamPos;       // camera position in pixels         [0, 0, 0]&#xD;&#xA;in float v_CellSize;    // grid cell size in pixels          [50]&#xD;&#xA;&#xD;&#xA;// TODO: make these variables in&#xD;&#xA;float lineWidth      = 1.f;			// The width of each line (in pixels).&#xD;&#xA;float darkenMultiple = 5.f;			// Multiple of which lines are darkened (e.g. every 5th line).&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;&#xD;&#xA;	float width = lineWidth / v_CellSize;&#xD;&#xA;&#xD;&#xA;    vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y / v_Resolution.y + v_Resolution.y / 2 - v_CellSize / 2);&#xD;&#xA;&#xD;&#xA;	uv.x *= 1.0 / v_CellSize;&#xD;&#xA;	uv.y /= v_CellSize;&#xD;&#xA;&#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;	// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= gl_FragCoord.y / v_CellSize;&#xD;&#xA;&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;	uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;	&#xD;&#xA;	float grid = 0.0;&#xD;&#xA;	grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;	grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	&#xD;&#xA;	if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} else {&#xD;&#xA;		// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;		col.a = 0.0;&#xD;&#xA;	}&#xD;&#xA;	&#xD;&#xA;	color = col;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding `v_Resolution.x / 2` to `uv.x`.&#xD;&#xA;&#xD;&#xA;I believe the part that's tripping me up is when I normalize `gl_FragCoord` to `uv` by dividing it by the screen size (`v_Resolution`).&#xD;&#xA;&#xD;&#xA;From [this question][2] I know why `gl_FragCoord` is normalized, but I don't understand why in this case `uv.x = gl_FragCoord.x` while `uv.y = gl_FragCoord.y / v_Resolution.y`. Why would I divide the y-component by the screen height, but not the x-component by the screen width? If I try to divide `gl_FragCoord.x` by the screen width, the entire shader breaks, and the grid columns are not rendered. This is especially strange to me, because in the [ShaderToy][1] example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;The entire code can be downloaded and compiled (Windows, OpenGL 4.5) from my GitHub repo: https://github.com/wooandrew/boomerang/tree/develop&#xD;&#xA;&#xD;&#xA;EDIT:&lt;br&gt;&#xD;&#xA;Okay, I was able to get the translation working as intended, but I'm still confused on the normalized UV as well as the coordinate system of UV.&#xD;&#xA;&#xD;&#xA;My solution (simplified):&#xD;&#xA;```glsl&#xD;&#xA;vec2 uv = vec2(gl_FragCoord.x - (v_Resolution.x / 2.f), (gl_FragCoord.y / v_Resolution.y) + (v_Resolution.y / 2.f));&#xD;&#xA;```&#xD;&#xA;Now, if I remember correctly, the origin in a GLSL fragment shader is bottom left, so why do I have to *subtract* `v_Resolution.x / 2.f` instead of *adding* it? (also, why is the x-component not normalized, like the y-component?)&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/4sj3DG&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/5724/glsl-can-someone-explain-why-gl-fragcoord-xy-screensize-is-performed-and-for" ContentLicense="CC BY-SA 4.0" />
  <row Id="31229" PostHistoryTypeId="2" PostId="10704" RevisionGUID="de83ef78-07bf-498b-9d03-4519833ab422" CreationDate="2021-03-02T02:07:11.033" UserId="15856" Text="After a fair bit of reading and skimming through papers, I have yet to find a good definition other than &quot;indent&quot; for what I want to remove, but I *have* found answers to pretty much everything else.&#xD;&#xA;&#xD;&#xA;The concept of a &quot;[Visual Hull][4]&quot; is what I was looking for regarding a mesh that doesn't have these indents. While the Wikipedia page, and a bunch of other resources, usually just refer to visual hulls created from a finite set of viewpoints, e.g. a set of real-life cameras, Laurentini, who introduced the term &quot;Visual Hull&quot;, also introduces a term &quot;External Visual Hull&quot; to refer to one created using *every* possible viewpoint outside of the convex hull [1]. This will have the exact same silhouette as the original mesh when viewed from any position outside the convex hull at any angle, so it was exactly what I was looking for.&#xD;&#xA;&#xD;&#xA;[1] also contains an algorithm for computing the external visual hull for polyhedra, but it is sorta brute-force and is $O(n^{12})$. In [2], Petitjean introduces a much more efficient algorithm for polyhedra, and Bottino and Laurentini also describe a more efficient algorithm in [3]. In addition to these algorithms for polyhedra, other works by Laurentini also discuss algorithms for doing the same for curved objects, surfaces of revolution, etc. I have yet to come across anyone actually *implementing* these algorithms, though.&#xD;&#xA;&#xD;&#xA;I'd like to describe all of these in more detail, but I still need to finish reading through them, and based on some deadlines coming up, I do not think I will have the time to do so for a little while. I hope to eventually come back to this post and edit it to actually describe at least one of the algorithms. However, if someone reading this wants to look these up for themselves, then in addition to the below citations, I would like to note that even if you don't normally have access to papers, e.g. through a post-secondary institution, all of these seem to be publicly available. You can download [1] from ResearchGate [here][5], download [2] from ResearchGate [here][6] (though I have no clue why different authors are listed for it than Petitjean), and [3] can be found in Google Books. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Citations:&#xD;&#xA;&#xD;&#xA;[1] Laurentini, Aldo. (1994). The Visual Hull Concept for Silhouette-Based Image Understanding. Pattern Analysis and Machine Intelligence, IEEE Transactions on. 16. 150-162. 10.1109/34.273735. &#xD;&#xA;&#xD;&#xA;[2] Petitjean, S. (1998). A computational geometric approach to visual hulls. International Journal of Computational Geometry &amp; Applications, 8(04), 407-436.&#xD;&#xA;&#xD;&#xA;[3] Bottino, Andrea &amp; Laurentini, Aldo. (2006). Retrieval of Shape from Silhouette. 10.1016/S1076-5670(05)39001-X.&#xD;&#xA;&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Visual_hull&#xD;&#xA;  [5]: https://www.researchgate.net/publication/3192242_The_Visual_Hull_Concept_for_Silhouette-Based_Image_Understanding&#xD;&#xA;  [6]: https://www.researchgate.net/publication/2781058_A_Computational_Geometric_Approach_To_Visual_Hulls" ContentLicense="CC BY-SA 4.0" />
  <row Id="31230" PostHistoryTypeId="2" PostId="10705" RevisionGUID="3b1e21e1-cfbe-4c45-b76c-54314d92d418" CreationDate="2021-03-02T09:01:58.910" UserId="209" Text="Not 3D as such, but it seems in 1963 [Ivan Sutherland's][1] seminal [&quot;Sketchpad&quot;][2] (and [wikipedia][3]) had instancing. eg. See &quot;*Chapter VI RECURSIVE FUNCTIONS*&quot; of the 2nd reference.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.icetcs.ru.is/SutherlandPOCHannes.pdf&#xD;&#xA;  [2]: https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-574.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Sketchpad" ContentLicense="CC BY-SA 4.0" />
  <row Id="31231" PostHistoryTypeId="5" PostId="10705" RevisionGUID="ec6b0795-f718-4ee3-b1d7-18eac3692227" CreationDate="2021-03-02T09:08:14.350" UserId="209" Comment="added 182 characters in body" Text="Not 3D as such, but it seems in 1963 [Ivan Sutherland's][1] seminal [&quot;Sketchpad&quot;][2] (and [wikipedia][3]) had instancing. eg. See &quot;*Chapter VI RECURSIVE FUNCTIONS*&quot; of the 2nd reference.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;IIRC somewhere there's a video of it in action - it made me annoyed as to how today's vector drawing tools don't seem to be able to do some of what sketchpad appeared to support.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.icetcs.ru.is/SutherlandPOCHannes.pdf&#xD;&#xA;  [2]: https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-574.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Sketchpad" ContentLicense="CC BY-SA 4.0" />
  <row Id="31232" PostHistoryTypeId="2" PostId="10706" RevisionGUID="72a2eb15-8a9c-4208-8149-1f38e5e8b44f" CreationDate="2021-03-02T10:59:26.550" UserId="13095" Text="&gt;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding v_Resolution.x / 2 to uv.x.&#xD;&#xA;&#xD;&#xA;Not sure what your intention is here since the Shadertoy example you referenced generates an infinite grid. So maybe you can clarify that.&#xD;&#xA;&#xD;&#xA;However, I think I can help you with this problem:&#xD;&#xA;&#xD;&#xA;&gt;  ... the ShaderToy example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;I think the basic problem here is, that you do not really understand how the mesh is generated and why the Shadertoy example isn't normalizing the uv-coordinates. If I can help you understand it, you can probably fix your other problems by yourself.&#xD;&#xA;&#xD;&#xA;So let's walk through the Shadertoy code and what it actually does:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;vec2 uv = fragCoord.xy;&#xD;&#xA;	&#xD;&#xA;// Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;uv.x *= 1.0 / spacing;&#xD;&#xA;uv.y /= spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here you first copy the frag coordinates into `uv` and afterward divide it by the spacing of your lines. Not sure why the author used those 'complicated' last two lines, but you can replace them simply with `uv /= spacing;`.&#xD;&#xA;The purpose of this step is to transform into a new space where the lines of your grid are located at every whole number. If your spacing is 20, like in the shader toy example, only the fragments with one of its frag coordinates being one of 0, 20, 40, etc. would produce a whole number and would be located on a line. Maybe you can already see where this is going.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;// Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;uv.y -= (iResolution.y - 600.0) / spacing;&#xD;&#xA;	&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x -= translation.x / spacing;&#xD;&#xA;uv.y += translation.y / spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here he is just translating the grid to consider several things like line thickness and camera position. The camera position is probably what you are interested in. I have no clue, about the purpose of the second line, even though the comment specifies it, but it is just a y-shift of your grid. However, note that all translations must be in the &quot;grid-space&quot; like the uv coordinates. Hence he always divides by `spacing`. For `width`, he already applied the transformation several lines above -&gt; `float width   = float(lineWidth)   / spacing;`&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;float grid = 0.0;&#xD;&#xA;grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;&#xD;&#xA;vec4 col = vec4(grid);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now here comes the magic that actually produces the grid. Let's dissect the second line. `fract(uv.x)` just [returns the fractional part](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/fract.xhtml) of `uv.x`. So a value of `12.125` is reduced to `0.125`. The [step function](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/step.xhtml) returns 0 if the second value is smaller than the first and 1 otherwise. So the point of `step(fract(uv.x), width)` frac is to get a `1` if the uv coordinate is on a vertical line and 0 if not. The `max` in this line is pretty pointless since `grid` (which is set to `0.0`) is either equal to the returned value or less. The third line does the same thing for horizontal lines, but here the `max` is actually needed.&#xD;&#xA;So to sum it up, `grid` is `1` if the fragment lies on a horizontal and/or vertical line and `0` if not.&#xD;&#xA;The last line just turns that into a vector. So you either get pure white (`(1.0, 1.0, 1.0, 1.0)`) as pixel color if the fragment is part of a line or pure black (`(0.0, 0.0, 0.0, 0.0)`) if not. Note that if alpha blending is enabled, black is actually translucent since the alpha channel is also `0`.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;	float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;	// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;	col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;} else {&#xD;&#xA;	// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;	col.a = 0.0;&#xD;&#xA;}&#xD;&#xA;	&#xD;&#xA;col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;fragColor = col;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This just adjusting the color of the grid and plotting the cat and not relevant to your question.&#xD;&#xA;&#xD;&#xA;I optimized the shader from the shadertoy example a little bit by removing obsolete instructions, postponing the transformation into &quot;grid space&quot; after applying the translations, and vectorizing some operations. Maybe it makes it easier for you to understand what is happening. I kept the original comments:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord ) {&#xD;&#xA;	// Simulate camera translation, just for this example.&#xD;&#xA;	vec2 velocity = vec2(-30.0, 10.0);	&#xD;&#xA;	translation += scale * iTime * velocity;&#xD;&#xA;	&#xD;&#xA;	float spacing = float(lineSpacing) * scale;&#xD;&#xA;	float width   = float(lineWidth)   / spacing;&#xD;&#xA;		&#xD;&#xA;&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	vec2 uv = fragCoord - translation;&#xD;&#xA;    &#xD;&#xA;    // Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= (iResolution.y - 600.0);&#xD;&#xA;    &#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv += (lineWidth &gt; 1) ? float(lineWidth) * 0.5 : float(lineWidth);&#xD;&#xA;    &#xD;&#xA;    // Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;    uv /= spacing;&#xD;&#xA;    &#xD;&#xA;	&#xD;&#xA;	float grid =     step(fract(uv.x), width)       ; // X lines (horizontal)&#xD;&#xA;	grid       = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	&#xD;&#xA;	if (grid != 0.0) {&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));        &#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} &#xD;&#xA;	&#xD;&#xA;	col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;	fragColor = col;&#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In this version, you can simply add your translations in pixels without any need to transform them to &quot;grid space&quot; or to normalize them. Hope that helps." ContentLicense="CC BY-SA 4.0" />
  <row Id="31233" PostHistoryTypeId="5" PostId="10706" RevisionGUID="1fa3da2c-53af-4e73-a525-257e7a81b828" CreationDate="2021-03-02T11:37:03.267" UserId="13095" Comment="added 916 characters in body" Text="&gt;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding v_Resolution.x / 2 to uv.x.&#xD;&#xA;&#xD;&#xA;Not sure what your intention is here since the Shadertoy example you referenced generates an infinite grid. So maybe you can clarify that.&#xD;&#xA;&#xD;&#xA;However, I think I can help you with this problem:&#xD;&#xA;&#xD;&#xA;&gt;  ... the ShaderToy example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;I think the basic problem here is, that you do not really understand how the mesh is generated and why the Shadertoy example isn't normalizing the uv-coordinates. If I can help you understand it, you can probably fix your other problems by yourself.&#xD;&#xA;&#xD;&#xA;So let's walk through the Shadertoy code and what it actually does:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;vec2 uv = fragCoord.xy;&#xD;&#xA;	&#xD;&#xA;// Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;uv.x *= 1.0 / spacing;&#xD;&#xA;uv.y /= spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here you first copy the frag coordinates into `uv` and afterward divide it by the spacing of your lines. Not sure why the author used those 'complicated' last two lines, but you can replace them simply with `uv /= spacing;`.&#xD;&#xA;The purpose of this step is to transform into a new space where the lines of your grid are located at every whole number. If your spacing is 20, like in the shader toy example, only the fragments with one of its frag coordinates being one of 0, 20, 40, etc. would produce a whole number and would be located on a line. Maybe you can already see where this is going.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;// Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;uv.y -= (iResolution.y - 600.0) / spacing;&#xD;&#xA;	&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x -= translation.x / spacing;&#xD;&#xA;uv.y += translation.y / spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here he is just translating the grid to consider several things like line thickness and camera position. The camera position is probably what you are interested in. I have no clue, about the purpose of the second line, even though the comment specifies it, but it is just a y-shift of your grid. However, note that all translations must be in the &quot;grid-space&quot; like the uv coordinates. Hence he always divides by `spacing`. For `width`, he already applied the transformation several lines above -&gt; `float width   = float(lineWidth)   / spacing;`&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;float grid = 0.0;&#xD;&#xA;grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;&#xD;&#xA;vec4 col = vec4(grid);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now here comes the magic that actually produces the grid. Let's dissect the second line. `fract(uv.x)` just [returns the fractional part](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/fract.xhtml) of `uv.x`. So a value of `12.125` is reduced to `0.125`. The [step function](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/step.xhtml) returns 0 if the second value is smaller than the first and 1 otherwise. So the point of `step(fract(uv.x), width)` frac is to get a `1` if the uv coordinate is on a vertical line and 0 if not. The `max` in this line is pretty pointless since `grid` (which is set to `0.0`) is either equal to the returned value or less. The third line does the same thing for horizontal lines, but here the `max` is actually needed.&#xD;&#xA;So to sum it up, `grid` is `1` if the fragment lies on a horizontal and/or vertical line and `0` if not.&#xD;&#xA;The last line just turns that into a vector. So you either get pure white (`(1.0, 1.0, 1.0, 1.0)`) as pixel color if the fragment is part of a line or pure black (`(0.0, 0.0, 0.0, 0.0)`) if not. Note that if alpha blending is enabled, black is actually translucent since the alpha channel is also `0`.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;	float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;	// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;	col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;} else {&#xD;&#xA;	// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;	col.a = 0.0;&#xD;&#xA;}&#xD;&#xA;	&#xD;&#xA;col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;fragColor = col;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This just adjusting the color of the grid and plotting the cat and not relevant to your question.&#xD;&#xA;&#xD;&#xA;I optimized the shader from the Shadertoy example a little bit by removing obsolete instructions, postponing the transformation into &quot;grid space&quot; after applying the translations, and vectorizing some operations. Maybe it makes it easier for you to understand what is happening. I kept the original comments and added some own ones:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord ) {&#xD;&#xA;    // Define some variables we use ---------------------------------------------&#xD;&#xA;	// Simulate camera translation, just for this example.&#xD;&#xA;	vec2 velocity = vec2(-30.0, 10.0);	&#xD;&#xA;	translation += scale * iTime * velocity;&#xD;&#xA;	&#xD;&#xA;	float spacing = float(lineSpacing) * scale;&#xD;&#xA;	float width   = float(lineWidth)   / spacing;&#xD;&#xA;		&#xD;&#xA;    // Add all translations to uv -----------------------------------------------&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	vec2 uv = fragCoord - translation;&#xD;&#xA;    &#xD;&#xA;    // Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= (iResolution.y - 600.0);&#xD;&#xA;    &#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv += (lineWidth &gt; 1) ? float(lineWidth) * 0.5 : float(lineWidth);&#xD;&#xA;&#xD;&#xA;    // Transform to &quot;grid space&quot; ------------------------------------------------    &#xD;&#xA;    // Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;    uv /= spacing;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    // Identify if pixel is on a line -------------------------------------------&#xD;&#xA;	float grid =     step(fract(uv.x), width)       ; // X lines (horizontal)&#xD;&#xA;	grid       = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;    // Set the correct color ----------------------------------------------------&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	if (grid != 0.0) {&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));        &#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} &#xD;&#xA;	&#xD;&#xA;    // Plot the cat -------------------------------------------------------------&#xD;&#xA;	col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;	fragColor = col;&#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In this version, you can simply add your translations in pixels without any need to transform them to &quot;grid space&quot; or to normalize them. Hope that helps. You can copy it into the Shadertoy example to see that the results are the same.&#xD;&#xA;&#xD;&#xA;&gt; Now, if I remember correctly, the origin in a GLSL fragment shader is bottom left, so why do I have to subtract v_Resolution.x / 2.f instead of adding it? &#xD;&#xA;&#xD;&#xA;Probably because you use different signs here:&#xD;&#xA;~~~&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;~~~" ContentLicense="CC BY-SA 4.0" />
  <row Id="31234" PostHistoryTypeId="5" PostId="10706" RevisionGUID="f01ef72f-7173-408b-a6a2-ea7e2253df26" CreationDate="2021-03-02T11:44:07.310" UserId="13095" Comment="added 916 characters in body" Text="&gt;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding v_Resolution.x / 2 to uv.x.&#xD;&#xA;&#xD;&#xA;Not sure what your intention is here since the Shadertoy example you referenced generates an infinite grid. So maybe you can clarify that.&#xD;&#xA;&#xD;&#xA;However, I think I can help you with this problem:&#xD;&#xA;&#xD;&#xA;&gt;  ... the ShaderToy example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;I think the basic problem here is, that you do not really understand how the mesh is generated and why the Shadertoy example isn't normalizing the uv-coordinates. If I can help you understand it, you can probably fix your other problems by yourself.&#xD;&#xA;&#xD;&#xA;So let's walk through the Shadertoy code and what it actually does:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;vec2 uv = fragCoord.xy;&#xD;&#xA;	&#xD;&#xA;// Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;uv.x *= 1.0 / spacing;&#xD;&#xA;uv.y /= spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here you first copy the frag coordinates into `uv` and afterward divide it by the spacing of your lines. Not sure why the author used those 'complicated' last two lines, but you can replace them simply with `uv /= spacing;`.&#xD;&#xA;The purpose of this step is to transform into a new space where the lines of your grid are located at every whole number. If your spacing is 20, like in the shader toy example, only the fragments with one of its frag coordinates being one of 0, 20, 40, etc. would produce a whole number and would be located on a line. Maybe you can already see where this is going.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;// Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;uv.y -= (iResolution.y - 600.0) / spacing;&#xD;&#xA;	&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x -= translation.x / spacing;&#xD;&#xA;uv.y += translation.y / spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here he is just translating the grid to consider several things like line thickness and camera position. The camera position is probably what you are interested in. I have no clue, about the purpose of the second line, even though the comment specifies it, but it is just a y-shift of your grid. However, note that all translations must be in the &quot;grid-space&quot; like the uv coordinates. Hence he always divides by `spacing`. For `width`, he already applied the transformation several lines above -&gt; `float width   = float(lineWidth)   / spacing;`&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;float grid = 0.0;&#xD;&#xA;grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;&#xD;&#xA;vec4 col = vec4(grid);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now here comes the magic that actually produces the grid. Let's dissect the second line. `fract(uv.x)` just [returns the fractional part](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/fract.xhtml) of `uv.x`. So a value of `12.125` is reduced to `0.125`. The [step function](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/step.xhtml) returns 0 if the second value is smaller than the first and 1 otherwise. So the point of `step(fract(uv.x), width)` frac is to get a `1` if the uv coordinate is on a vertical line and 0 if not. The `max` in this line is pretty pointless since `grid` (which is set to `0.0`) is either equal to the returned value or less. The third line does the same thing for horizontal lines, but here the `max` is actually needed.&#xD;&#xA;So to sum it up, `grid` is `1` if the fragment lies on a horizontal and/or vertical line and `0` if not.&#xD;&#xA;The last line just turns that into a vector. So you either get pure white (`(1.0, 1.0, 1.0, 1.0)`) as pixel color if the fragment is part of a line or pure black (`(0.0, 0.0, 0.0, 0.0)`) if not. Note that if alpha blending is enabled, black is actually translucent since the alpha channel is also `0`.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;	float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;	// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;	col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;} else {&#xD;&#xA;	// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;	col.a = 0.0;&#xD;&#xA;}&#xD;&#xA;	&#xD;&#xA;col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;fragColor = col;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This just adjusting the color of the grid and plotting the cat and not relevant to your question.&#xD;&#xA;&#xD;&#xA;I optimized the shader from the Shadertoy example a little bit by removing obsolete instructions, postponing the transformation into &quot;grid space&quot; after applying the translations, and vectorizing some operations. Maybe it makes it easier for you to understand what is happening. I kept the original comments and added some own ones:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord ) {&#xD;&#xA;    // Define some variables we use ---------------------------------------------&#xD;&#xA;	// Simulate camera translation, just for this example.&#xD;&#xA;	vec2 velocity = vec2(-30.0, 10.0);	&#xD;&#xA;	translation += scale * iTime * velocity;&#xD;&#xA;	&#xD;&#xA;	float spacing = float(lineSpacing) * scale;&#xD;&#xA;	float width   = float(lineWidth)   / spacing;&#xD;&#xA;		&#xD;&#xA;    // Add all translations to uv -----------------------------------------------&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	vec2 uv = fragCoord - translation;&#xD;&#xA;    &#xD;&#xA;    // Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= (iResolution.y - 600.0);&#xD;&#xA;    &#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv += (lineWidth &gt; 1) ? float(lineWidth) * 0.5 : float(lineWidth);&#xD;&#xA;&#xD;&#xA;    // Transform to &quot;grid space&quot; ------------------------------------------------    &#xD;&#xA;    // Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;    uv /= spacing;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    // Identify if pixel is on a line -------------------------------------------&#xD;&#xA;	float grid =     step(fract(uv.x), width)       ; // X lines (horizontal)&#xD;&#xA;	grid       = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;    // Set the correct color ----------------------------------------------------&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	if (grid != 0.0) {&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));        &#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} &#xD;&#xA;	&#xD;&#xA;    // Plot the cat -------------------------------------------------------------&#xD;&#xA;	col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;	fragColor = col;&#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In this version, you can simply add your translations in pixels without any need to transform them to &quot;grid space&quot; or to normalize them. Hope that helps. You can copy it into the Shadertoy example to see that the results are the same.&#xD;&#xA;&#xD;&#xA;&gt; Now, if I remember correctly, the origin in a GLSL fragment shader is bottom left, so why do I have to subtract v_Resolution.x / 2.f instead of adding it? &#xD;&#xA;&#xD;&#xA;Probably because you use different signs here:&#xD;&#xA;~~~&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;&gt; (also, why is the x-component not normalized, like the y-component?)&#xD;&#xA;&#xD;&#xA;I guess you fiddled around until &quot;something&quot; produced the expected image rather than knowing what happens. I see no point in investigating the &quot;why&quot; here. Understand the Shadertoy code (or my version) and then apply your changes while actually knowing what you are doing. If you use my version, all you have to add are the translations in pixels that you want to apply." ContentLicense="CC BY-SA 4.0" />
  <row Id="31235" PostHistoryTypeId="5" PostId="10705" RevisionGUID="77a8d91f-b518-4e20-b3ae-25d3f1bbe0a0" CreationDate="2021-03-03T07:09:50.523" UserId="209" Comment="Added &quot;some of&quot; qualify to appease joojaa :-)" Text="Not 3D as such, but it seems in 1963 [Ivan Sutherland's][1] seminal [&quot;Sketchpad&quot;][2] (and [wikipedia][3]) had instancing. eg. See &quot;*Chapter VI RECURSIVE FUNCTIONS*&quot; of the 2nd reference.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;IIRC somewhere there's a video of it in action - it made me annoyed as to how some of today's vector drawing tools don't seem to be able to do some of what sketchpad appeared to support.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.icetcs.ru.is/SutherlandPOCHannes.pdf&#xD;&#xA;  [2]: https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-574.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Sketchpad" ContentLicense="CC BY-SA 4.0" />
  <row Id="31236" PostHistoryTypeId="5" PostId="10705" RevisionGUID="638210a5-8ff6-4384-8fe7-f7ebce02db29" CreationDate="2021-03-03T07:18:34.520" UserId="209" Comment="added 117 characters in body" Text="Not 3D as such, but it seems in 1963 [Ivan Sutherland's][1] seminal [&quot;Sketchpad&quot;][2] (and [wikipedia][3]) had instancing. eg. See &quot;*Chapter VI RECURSIVE FUNCTIONS*&quot; of the 2nd reference.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;IIRC somewhere there's a video of it in action - it made me annoyed as to how some of today's vector drawing tools don't seem to be able to do some of what sketchpad appeared to support.&#xD;&#xA;&#xD;&#xA;Update: @Joojaa has kindly [located a video][4]   or [this][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.icetcs.ru.is/SutherlandPOCHannes.pdf&#xD;&#xA;  [2]: https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-574.pdf&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Sketchpad&#xD;&#xA;  [4]: https://www.youtube.com/watch?app=desktop&amp;v=57wj8diYpgY&#xD;&#xA;  [5]: https://www.youtube.com/watch?v=6orsmFndx_o" ContentLicense="CC BY-SA 4.0" />
  <row Id="31238" PostHistoryTypeId="2" PostId="10707" RevisionGUID="3da76c85-17db-4910-b655-31aa62f9ddc3" CreationDate="2021-03-03T12:40:55.883" UserId="9169" Text="### Background&#xD;&#xA;&#xD;&#xA;I need to remesh by OpenVDB, like what [Blender remesh](https://docs.blender.org/manual/en/dev/modeling/modifiers/generate/remesh.html) does:&#xD;&#xA;&#xD;&#xA;[![Blender screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;&gt; Voxel&#xD;&#xA;&gt;&#xD;&#xA;&gt; Uses an OpenVDB to generate a new manifold mesh from the current geometry while trying to preserve the mesh’s original volume.&#xD;&#xA;&#xD;&#xA;### Problem&#xD;&#xA;&#xD;&#xA;The problem is that OpenVDB gets a constant *voxel size*. But I have meshes with varying polygon density/granularity, i.e. high-detail and low-detail components. To preserve the topology of high-detail components, the *voxel size* has to be too small for the whole 3d model.&#xD;&#xA;&#xD;&#xA;[![Polygon granularity/density][2]][2]&#xD;&#xA;&#xD;&#xA;### Possible workaround&#xD;&#xA;&#xD;&#xA;A mesh might be broken down into distinct components of higher detail and lower detail.&#xD;&#xA;&#xD;&#xA;### Question&#xD;&#xA;&#xD;&#xA;Is there any algorithm or library to help me break down the mesh into distinct components according to level of detail? I looked at [CGAL](https://doc.cgal.org/latest/Polygon_mesh_processing/index.html), but I couldn't figure out.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CJikC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jdt0F.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31239" PostHistoryTypeId="1" PostId="10707" RevisionGUID="3da76c85-17db-4910-b655-31aa62f9ddc3" CreationDate="2021-03-03T12:40:55.883" UserId="9169" Text="Divide mesh according to level of detail" ContentLicense="CC BY-SA 4.0" />
  <row Id="31240" PostHistoryTypeId="3" PostId="10707" RevisionGUID="3da76c85-17db-4910-b655-31aa62f9ddc3" CreationDate="2021-03-03T12:40:55.883" UserId="9169" Text="|algorithm|computational-geometry|geometry|mesh|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31244" PostHistoryTypeId="50" PostId="10614" RevisionGUID="33ff43cb-e891-4fe9-a9a9-0536594aed61" CreationDate="2021-03-04T10:07:35.840" UserId="-1" />
  <row Id="31245" PostHistoryTypeId="2" PostId="10709" RevisionGUID="9a3b20aa-af0b-4fa6-81c8-f78359acf871" CreationDate="2021-03-04T11:18:20.407" UserId="15574" Text="Some background of my scenario: I have two images of indirect radiance, both are from an animation. I will reproject an pixel from the previous frame to current frame, and I want to do comparisons with them. Both have been path traced with quite high sample count, but some noise still remains.&#xD;&#xA;&#xD;&#xA;I want to focus on reprojecting, so two questions:&#xD;&#xA;1. Does it make sense applying a denoising filter to the images prior to comparing them, to lower the variance? Frankly, I don't see a reason why not, but not completely sure.&#xD;&#xA;2. What filter would give the highest quality (PSNR/SSIM against higher spp count) results? I have stumbled upon gaussian, blackman-harris and bilateral filters, but they have been used on final (indirect + direct) colors.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31246" PostHistoryTypeId="1" PostId="10709" RevisionGUID="9a3b20aa-af0b-4fa6-81c8-f78359acf871" CreationDate="2021-03-04T11:18:20.407" UserId="15574" Text="What denoising filter gives highest quality for indirect light image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31247" PostHistoryTypeId="3" PostId="10709" RevisionGUID="9a3b20aa-af0b-4fa6-81c8-f78359acf871" CreationDate="2021-03-04T11:18:20.407" UserId="15574" Text="|pathtracing|filtering|gaussian-blur|denoise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31248" PostHistoryTypeId="2" PostId="10710" RevisionGUID="485ad98f-6b55-44a4-b7a9-e7ed76075221" CreationDate="2021-03-04T20:20:08.087" UserId="15877" Text="Modern operating systems support a wide range of resolutions. Mine ranges from 800x600 to 1920x1080. They also support multi-displays. I've never tried it but I have seen other users with 2 or 3 monitors.&#xD;&#xA;&#xD;&#xA;I'd like to know some details about how this is all supported. The trivial way is to size the graphics card buffer for the largest possible display, and then crop off any unused parts before sending it out the video port. But a little math, so 1920x1080, 24 bit color, is about 6.2 MB, which is not that big at all for a piece of VRAM. However, then we get to multi-display. What is a reasonable max number for displays? 4? 8? And then don't forget you want to support high frame rates of at least 60 fps, maybe 120 or even 240. Then remember you should support double- or even triple-buffering.&#xD;&#xA;&#xD;&#xA;Not to mention, I have seen bigger rez monitors online that advertise themselves as compatible with Windows 7 and 10. So it seems to me that just providing the max possible buffer size is not feasible. The &quot;max&quot; changes too rapidly these days.&#xD;&#xA;&#xD;&#xA;**TLDR:** I can understand if every monitor and GPU comes with its own driver. What I'm trying to understand is how **one set of hardware** can support a very wide range of screen resolutions **without being trivially wasteful**. Is there some clever way of doing this?&#xD;&#xA;&#xD;&#xA;Disclaimer: I'm a CS guy and don't keep up with modern hardware. I used to read a little about various hardware back in late 90s / early 00s, but never worked on it career-wise or hobby-wise. I can build my own comp and understand basic specs of most parts, but the graphics capabilities are the biggest mystery and &quot;dark arts&quot; to me (other than RAM timings)." ContentLicense="CC BY-SA 4.0" />
  <row Id="31249" PostHistoryTypeId="1" PostId="10710" RevisionGUID="485ad98f-6b55-44a4-b7a9-e7ed76075221" CreationDate="2021-03-04T20:20:08.087" UserId="15877" Text="How does the OS + hardware support multiple screen resolutions and multi-display?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31250" PostHistoryTypeId="3" PostId="10710" RevisionGUID="485ad98f-6b55-44a4-b7a9-e7ed76075221" CreationDate="2021-03-04T20:20:08.087" UserId="15877" Text="|gpu|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31251" PostHistoryTypeId="2" PostId="10711" RevisionGUID="4b7c9c70-582b-4bac-8899-ce3af409bc8b" CreationDate="2021-03-05T01:40:02.880" UserId="2654" Text="&gt; Any hardware in the graphics card is fixed.&#xD;&#xA;&#xD;&#xA;No, the *storage* of a graphics card is fixed. How that storage gets used, particularly on any semi-modern graphics card, is flexible.&#xD;&#xA;&#xD;&#xA;Essentially, what a graphics display device has is a mechanism for being told, &quot;the bytes of video memory starting at address X is in format Y and size Z; send it at the next vblank period to display device W&quot;. Really old graphics cards had specific memory structures for holding framebuffers, which imposed strict limits on how things could work. But that hasn't been the case on PCs for a good decade at least.&#xD;&#xA;&#xD;&#xA;There may be limitations on how many display devices a particular piece of hardware could hypothetically output to, or the sizes and formats which the hardware can use. Some hardware devices may only be able to use non-virtualized GPU addresses (which I'd guess is why NVIDIA has special memory types for allocating render targets) or somesuch, but even that is a matter of the user interface, not what the internal hardware is doing. As far as the display device's output is concerned, it could use more or less any GPU memory address.&#xD;&#xA;&#xD;&#xA;So, what happens when you plug in a new display device? The OS allocates a framebuffer's (or two) worth of video memory for that display device's video output. If you change the resolution of a display device, the OS allocates a differently-sized slice of memory and frees the prior framebuffer allocation. And so forth." ContentLicense="CC BY-SA 4.0" />
  <row Id="31252" PostHistoryTypeId="2" PostId="10712" RevisionGUID="57c4e638-5484-4f7a-9fa8-55d10d4c3dcb" CreationDate="2021-03-05T05:30:57.340" UserId="15434" Text="This topic would contain a lot of sub questions because I have one for each shape but for today I just want to understand the function for a torus and a capped torus&#xD;&#xA;&#xD;&#xA;[This](https://iquilezles.org/www/articles/distfunctions/distfunctions.htm) is the article for all shapes and I am trying to understand the code for torus&#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)- &#xD;&#xA;      t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;and capped torus&#xD;&#xA;&#xD;&#xA;     float sdCappedTorus(in vec3 p, &#xD;&#xA;      in vec2 sc, in float ra, in &#xD;&#xA;      float rb)&#xD;&#xA;    {&#xD;&#xA;      p.x = abs(p.x);&#xD;&#xA;&#xD;&#xA;      float k = (sc.y*p.x&gt;sc.x*p.y) ? &#xD;&#xA;      dot(p.xy,sc) : length(p.xy);&#xD;&#xA;&#xD;&#xA;       return sqrt( dot(p,p) + ra*ra &#xD;&#xA;     - 2.0*ra*k ) - rb;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have so many questions. I know parameter P is the point for testing but what is t? what is ra and rb? what calculations are they doing what are the mathematics?&#xD;&#xA;&#xD;&#xA;Just a theoretical explanation or some images explaining the general formula would be greatly appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="31253" PostHistoryTypeId="1" PostId="10712" RevisionGUID="57c4e638-5484-4f7a-9fa8-55d10d4c3dcb" CreationDate="2021-03-05T05:30:57.340" UserId="15434" Text="understanding SDF[Signed Distance Functions] for a torus" ContentLicense="CC BY-SA 4.0" />
  <row Id="31254" PostHistoryTypeId="3" PostId="10712" RevisionGUID="57c4e638-5484-4f7a-9fa8-55d10d4c3dcb" CreationDate="2021-03-05T05:30:57.340" UserId="15434" Text="|mathematics|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31255" PostHistoryTypeId="2" PostId="10713" RevisionGUID="32d94e7a-72b1-41d6-a3ea-c45debb8a185" CreationDate="2021-03-05T09:49:04.787" UserId="15879" Text="The folllowing video discusses the SDFs of various primitives (linked to torus section):&#xD;&#xA;&#xD;&#xA;https://youtu.be/Ff0jJyyiVyw?t=491&#xD;&#xA;&#xD;&#xA;It discusses a torus but not the capped variant. The rest of the channel has useful content as well. &#xD;&#xA;&#xD;&#xA;Additionally, iq has videos on detailed derivations of some primitives and techniques, sometimes hidden in the long livestreams, which are well worth a watch if you want to learn more about graphics methods and demoscene tricks:&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/c/InigoQuilez/videos " ContentLicense="CC BY-SA 4.0" />
  <row Id="31256" PostHistoryTypeId="5" PostId="10713" RevisionGUID="3780a9b5-894d-4a24-8743-b459fe49b805" CreationDate="2021-03-05T10:22:18.027" UserId="15879" Comment="deleted 1 character in body" Text="The following video discusses the SDFs of various primitives (linked to torus section):&#xD;&#xA;&#xD;&#xA;https://youtu.be/Ff0jJyyiVyw?t=491&#xD;&#xA;&#xD;&#xA;It discusses a torus but not the capped variant. The rest of the channel has useful content as well. &#xD;&#xA;&#xD;&#xA;Additionally, iq has videos on detailed derivations of some primitives and techniques, sometimes hidden in the long livestreams, which are well worth a watch if you want to learn more about graphics methods and demoscene tricks:&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/c/InigoQuilez/videos " ContentLicense="CC BY-SA 4.0" />
  <row Id="31257" PostHistoryTypeId="2" PostId="10714" RevisionGUID="05bec76a-1dc2-4dca-9840-be197a5f3109" CreationDate="2021-03-05T13:30:26.897" UserId="15705" Text="Should I expect that every invocation/fragment within a subgroup, when using something like `subgroupBroadcast()`, will belong to the same triangle?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31258" PostHistoryTypeId="1" PostId="10714" RevisionGUID="05bec76a-1dc2-4dca-9840-be197a5f3109" CreationDate="2021-03-05T13:30:26.897" UserId="15705" Text="How do fragment shader invocations subgroups map onto triangles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31259" PostHistoryTypeId="3" PostId="10714" RevisionGUID="05bec76a-1dc2-4dca-9840-be197a5f3109" CreationDate="2021-03-05T13:30:26.897" UserId="15705" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31260" PostHistoryTypeId="2" PostId="10715" RevisionGUID="95aabc18-72a4-4c2d-b665-26686fb4066e" CreationDate="2021-03-05T15:02:18.727" UserId="2654" Text="Fragment shader subgroups are not required to be restricted to a single primitive (and such a restriction would negatively impact performance). So subgroup broadcasting can cross primitive boundaries.&#xD;&#xA;&#xD;&#xA;Oddly, even the quad scope does not explicitly state that they're required to come from the same primitive." ContentLicense="CC BY-SA 4.0" />
  <row Id="31261" PostHistoryTypeId="2" PostId="10716" RevisionGUID="de0e4610-0753-4383-8ace-d3f34972cee2" CreationDate="2021-03-05T15:06:07.707" UserId="7952" Text="This turned into a rabbit hole for me hopefully it helps answer your question, I recommend trying out the various functions on the [ShaderToy][1] website. Just drop them in and change the call to &quot;sdCircle&quot;. I used the values R=0.75 and r=0.35 to test them out.&#xD;&#xA;&#xD;&#xA;**Part 1: Defining what an SDF means**&#xD;&#xA;&#xD;&#xA;Signed Distance Field or SDF, in this context, is a function that returns the signed distance from a point to a primitive. The returned value is always a float that can take on 3 context specific meanings. &#xD;&#xA;&#xD;&#xA; - zero: This is on the surface, while it is rare to hit exactly on the surface of the primitive we can approximate a hit with a simple inequality like `abs(d)&lt;sigma` where d is the signed distance and sigma is some small value like 0.001. &#xD;&#xA; - negative: In this context negative values represent hits inside the primitive but choosing the meaning of a negative return value is context specific. Smaller (more negative) values represent values that are deeper in the interior of the primitive.&#xD;&#xA; - positive: Again this is context specific, but in this case this is a hit outside the primitive and larger values mean it is farther away from the primitive.&#xD;&#xA;&#xD;&#xA;Stop for a second and take another look at the first case, &quot;zero&quot;. This may seem unimportant at first glance but it turns out that by defining a generic base primitive and then changing the value of sigma we can easily compute a primitive of any size. In the case of a torus we could have a very thin torus or one that is so big it envelopes itself. Then by adding one more variable representing the large Radius of the torus, the torus can now be changed to fit our needs as desired just by controlling two variables.&#xD;&#xA;&#xD;&#xA;**Part 2: Defining the primitive**&#xD;&#xA;&#xD;&#xA;Take a look at IQ's 2D function for a circle.&#xD;&#xA;&#xD;&#xA;    float sdCircle( vec2 p, float r ){ return length(p) - r; }&#xD;&#xA;&#xD;&#xA;All this function is doing is computing the &quot;distance&quot; using the length function of our point &quot;p&quot; from our circle (which is sitting at the origin) then subtracting our radius &quot;r&quot;. And easy as that any point greater then radius is positive, any point less then radius is negative.&#xD;&#xA;&#xD;&#xA;This is almost a torus already, we are just missing the signed distance for the inside diameter of the 2D torus. But we already know that is really just some sigma value from our original circle, so all we have to do is add a second radius and compute the sigma.&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;    float sdTorus2D( vec2 p, float R, float r )&#xD;&#xA;    {&#xD;&#xA;      float q = length(p)-R;&#xD;&#xA;      return abs(q)-r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;No need to recalculate the distance, so just figure out sigma to our second circle with `abs(q)-r`.&#xD;&#xA;&#xD;&#xA;**Part 3: Going 3D**&#xD;&#xA;&#xD;&#xA;If you stop and think about it for a second (ok...maybe more then a second) then it is easy to realize that our 2D torus is just a slice of a 3D torus. When you think about it like that then we can take another slice of our torus in 2D on its edge just by rotating our torus 90 degrees. This should result in two SDF circles side by side.&#xD;&#xA;&#xD;&#xA;But turning the torus on its side is really just a matter of computing our signed distances in the opposite order...lets try:&#xD;&#xA;&#xD;&#xA;    float sdTorus2DSide( vec2 p, float R, float r )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(abs(p.x)-R,p.y);&#xD;&#xA;      return length(q)-r;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The two different views essentially compute the distance in two different ways, so by combining them we should be able to view our torus in 3D from any angle just by adding an extra component &quot;z&quot; so that both computations can be independent of each other. Then combine our two radii into a vec2 and we end up with a function that looks just like IQ's. &#xD;&#xA;&#xD;&#xA;    float sdTorus( vec3 p, vec2 t )&#xD;&#xA;    {&#xD;&#xA;      vec2 q = vec2(length(p.xz)-t.x,p.y);&#xD;&#xA;      return length(q)-t.y;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This would still look two dimensional in the &quot;circle&quot; shadertoy, but now we can vary z to look at the torus slices. Or rotate our view point and see it emerge from the 2D world.  Neat stuff!&#xD;&#xA;&#xD;&#xA;BTW you can go through this same process with many primitives and get many different shapes as IQ has demonstrated on his website.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/3ltSW2" ContentLicense="CC BY-SA 4.0" />
  <row Id="31262" PostHistoryTypeId="50" PostId="10619" RevisionGUID="b689866c-c390-4837-87df-bf36592ce824" CreationDate="2021-03-05T15:06:30.663" UserId="-1" />
  <row Id="31265" PostHistoryTypeId="2" PostId="10717" RevisionGUID="e562f8cf-d9f1-42b3-b6aa-8d0b3be55c84" CreationDate="2021-03-06T15:47:16.393" UserId="15882" Text="In [smallpt's](https://www.kevinbeason.com/smallpt/) source at line 90 the direction is multiplied by `140` and I was wondering where that number is coming from. I was hoping for it to be explained in the [slides](https://drive.google.com/file/d/0B8g97JkuSSBwUENiWTJXeGtTOHFmSm51UC01YWtCZw/view) attached to the source but I couldn't find an explanation for where that number is coming from.&#xD;&#xA;&#xD;&#xA;If I increase the number(to `160.0` for example) it starts giving some kind of weird zoom-out effect:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And if I decrease the number(in this example to `125.0`) I get this partially black picture:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As I understand it, after I've simplified smallpt a little bit, in the `main` function we get a random point in each subpixel normalized by the width/height between `-0.5` and `0.5`, and then calculate the new ray direction by multiplying the x and y axis by these offsets, then adding everything together to obtain the new direction, something like this:&#xD;&#xA;```&#xD;&#xA;fov_scale = 2.0 * tan(vertical_fov / 2.0)&#xD;&#xA;cam_x_axis = vec3(aspect_ratio * fov_scale, 0, 0)&#xD;&#xA;cam_y_axis = normalize(cross(cam_x_axis, cam_direction))&#xD;&#xA;&#xD;&#xA;for x, y:&#xD;&#xA;    for sx, sy, samps:&#xD;&#xA;        // not using smallpt's tent filter&#xD;&#xA;        x_in_subpixel = x + sx * 0.5 + erand48(Xi) * 0.5&#xD;&#xA;        y_in_subpixel = y + sy * 0.5 + erand48(Xi) * 0.5&#xD;&#xA;        // normalize them between -0.5 and 0.5&#xD;&#xA;        new_x = x_in_subpixel / w - 0.5&#xD;&#xA;        new_y = y_in_subpixel / h - 0.5&#xD;&#xA;&#xD;&#xA;        offset_x = cam_x_axis * new_x&#xD;&#xA;        offset_y = cam_y_axis * new_y&#xD;&#xA;        new_direction = cam_direction + offset_x + offset_y&#xD;&#xA;        // here we can see that magic number&#xD;&#xA;        new_ray = ray(cam_position + new_direction * 140, normalize(new_direction))&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So my questions are:&#xD;&#xA;* What does this number mean?&#xD;&#xA;* Can I calculate it programmatically to be exactly what is expected(maybe depending on the field of view, width/height of the image)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/o9XWE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7KkJ2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31266" PostHistoryTypeId="1" PostId="10717" RevisionGUID="e562f8cf-d9f1-42b3-b6aa-8d0b3be55c84" CreationDate="2021-03-06T15:47:16.393" UserId="15882" Text="Magic number meaning in smallpt's camera ray calculation" ContentLicense="CC BY-SA 4.0" />
  <row Id="31267" PostHistoryTypeId="3" PostId="10717" RevisionGUID="e562f8cf-d9f1-42b3-b6aa-8d0b3be55c84" CreationDate="2021-03-06T15:47:16.393" UserId="15882" Text="|pathtracing|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31268" PostHistoryTypeId="6" PostId="10717" RevisionGUID="3dd25ff0-9d27-4b40-bda9-2245b86a9cea" CreationDate="2021-03-06T16:31:07.800" UserId="15882" Comment="edited tags" Text="|raytracing|pathtracing|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31269" PostHistoryTypeId="5" PostId="10706" RevisionGUID="f41a630e-8b8c-449d-b789-ad212bf21d4b" CreationDate="2021-03-06T18:10:26.133" UserId="13095" Comment="Answer a comment question" Text="&gt;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding v_Resolution.x / 2 to uv.x.&#xD;&#xA;&#xD;&#xA;Not sure what your intention is here since the Shadertoy example you referenced generates an infinite grid. So maybe you can clarify that.&#xD;&#xA;&#xD;&#xA;However, I think I can help you with this problem:&#xD;&#xA;&#xD;&#xA;&gt;  ... the ShaderToy example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;I think the basic problem here is, that you do not really understand how the mesh is generated and why the Shadertoy example isn't normalizing the uv-coordinates. If I can help you understand it, you can probably fix your other problems by yourself.&#xD;&#xA;&#xD;&#xA;So let's walk through the Shadertoy code and what it actually does:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;vec2 uv = fragCoord.xy;&#xD;&#xA;	&#xD;&#xA;// Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;uv.x *= 1.0 / spacing;&#xD;&#xA;uv.y /= spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here you first copy the frag coordinates into `uv` and afterward divide it by the spacing of your lines. Not sure why the author used those 'complicated' last two lines, but you can replace them simply with `uv /= spacing;`.&#xD;&#xA;The purpose of this step is to transform into a new space where the lines of your grid are located at every whole number. If your spacing is 20, like in the shader toy example, only the fragments with one of its frag coordinates being one of 0, 20, 40, etc. would produce a whole number and would be located on a line. Maybe you can already see where this is going.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;// Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;uv.y -= (iResolution.y - 600.0) / spacing;&#xD;&#xA;	&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x -= translation.x / spacing;&#xD;&#xA;uv.y += translation.y / spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here he is just translating the grid to consider several things like line thickness and camera position. The camera position is probably what you are interested in. I have no clue, about the purpose of the second line, even though the comment specifies it, but it is just a y-shift of your grid. However, note that all translations must be in the &quot;grid-space&quot; like the uv coordinates. Hence he always divides by `spacing`. For `width`, he already applied the transformation several lines above -&gt; `float width   = float(lineWidth)   / spacing;`&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;float grid = 0.0;&#xD;&#xA;grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;&#xD;&#xA;vec4 col = vec4(grid);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now here comes the magic that actually produces the grid. Let's dissect the second line. `fract(uv.x)` just [returns the fractional part](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/fract.xhtml) of `uv.x`. So a value of `12.125` is reduced to `0.125`. The [step function](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/step.xhtml) returns 0 if the second value is smaller than the first and 1 otherwise. So the point of `step(fract(uv.x), width)` frac is to get a `1` if the uv coordinate is on a vertical line and 0 if not. The `max` in this line is pretty pointless since `grid` (which is set to `0.0`) is either equal to the returned value or less. The third line does the same thing for horizontal lines, but here the `max` is actually needed.&#xD;&#xA;So to sum it up, `grid` is `1` if the fragment lies on a horizontal and/or vertical line and `0` if not.&#xD;&#xA;The last line just turns that into a vector. So you either get pure white (`(1.0, 1.0, 1.0, 1.0)`) as pixel color if the fragment is part of a line or pure black (`(0.0, 0.0, 0.0, 0.0)`) if not. Note that if alpha blending is enabled, black is actually translucent since the alpha channel is also `0`.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;	float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;	// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;	col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;} else {&#xD;&#xA;	// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;	col.a = 0.0;&#xD;&#xA;}&#xD;&#xA;	&#xD;&#xA;col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;fragColor = col;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This just adjusting the color of the grid and plotting the cat and not relevant to your question.&#xD;&#xA;&#xD;&#xA;I optimized the shader from the Shadertoy example a little bit by removing obsolete instructions, postponing the transformation into &quot;grid space&quot; after applying the translations, and vectorizing some operations. Maybe it makes it easier for you to understand what is happening. I kept the original comments and added some own ones:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord ) {&#xD;&#xA;    // Define some variables we use ---------------------------------------------&#xD;&#xA;	// Simulate camera translation, just for this example.&#xD;&#xA;	vec2 velocity = vec2(-30.0, 10.0);	&#xD;&#xA;	translation += scale * iTime * velocity;&#xD;&#xA;	&#xD;&#xA;	float spacing = float(lineSpacing) * scale;&#xD;&#xA;	float width   = float(lineWidth)   / spacing;&#xD;&#xA;		&#xD;&#xA;    // Add all translations to uv -----------------------------------------------&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	vec2 uv = fragCoord - translation;&#xD;&#xA;    &#xD;&#xA;    // Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= (iResolution.y - 600.0);&#xD;&#xA;    &#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv += (lineWidth &gt; 1) ? float(lineWidth) * 0.5 : float(lineWidth);&#xD;&#xA;&#xD;&#xA;    // Transform to &quot;grid space&quot; ------------------------------------------------    &#xD;&#xA;    // Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;    uv /= spacing;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    // Identify if pixel is on a line -------------------------------------------&#xD;&#xA;	float grid =     step(fract(uv.x), width)       ; // X lines (horizontal)&#xD;&#xA;	grid       = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;    // Set the correct color ----------------------------------------------------&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	if (grid != 0.0) {&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));        &#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} &#xD;&#xA;	&#xD;&#xA;    // Plot the cat -------------------------------------------------------------&#xD;&#xA;	col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;	fragColor = col;&#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In this version, you can simply add your translations in pixels without any need to transform them to &quot;grid space&quot; or to normalize them. Hope that helps. You can copy it into the Shadertoy example to see that the results are the same.&#xD;&#xA;&#xD;&#xA;&gt; Now, if I remember correctly, the origin in a GLSL fragment shader is bottom left, so why do I have to subtract v_Resolution.x / 2.f instead of adding it? &#xD;&#xA;&#xD;&#xA;Probably because you use different signs here:&#xD;&#xA;~~~&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;&gt; (also, why is the x-component not normalized, like the y-component?)&#xD;&#xA;&#xD;&#xA;I guess you fiddled around until &quot;something&quot; produced the expected image rather than knowing what happens. I see no point in investigating the &quot;why&quot; here. Understand the Shadertoy code (or my version) and then apply your changes while actually knowing what you are doing. If you use my version, all you have to add are the translations in pixels that you want to apply.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Update&#xD;&#xA;&#xD;&#xA;Regarding the comment of Andrew Woo:&#xD;&#xA;&#xD;&#xA;&gt; I really appreciate the in-depth explanation, it helped a lot in my understanding, however it doesn't really answer my [original] question, which was why the x-component of uv isn't normalized. &#xD;&#xA;&#xD;&#xA;I was addressing that at the end of the original answer when I said that you fiddled around until &quot;something&quot; worked and I didn't saw any point in investigating why &quot;obviously wrong&quot; code produces the correct result.&#xD;&#xA;&#xD;&#xA;Well, let's get something clear: uv coordinates are not screen coordinates. So `gl_FragCoord.y / v_Resolution.y` is not the general definition of `v`. I would rather call them &quot;normalized screen coordinates&quot;. uv coordinates are (usually) used to map regular 2-dimensional data like an image onto a surface. You can read more about them on [Wikipedia](https://en.wikipedia.org/wiki/UV_mapping). Don't be fooled by the fact that the author of the question you linked used the &quot;normalized screen coordinates&quot; as uv coordinates. They might be the same if you want to map an image to your screen, but usually, they are not. &#xD;&#xA;&#xD;&#xA;In the shadertoy example, the uv coordinates are used to map a single cell of your grid. You start using uv coordinates of the grid after you divided the frag coordinates by the cell size in pixels. Before that, they are no uv coordinates, at least not in relation to the grid.&#xD;&#xA;&#xD;&#xA;So let's summarize what the shader does: You start with pixel coordinates inside your shader with values between 0 and the screen resolution in either direction and you want to calculate the uv coordinates of the grid in order to draw it. That's the whole purpose of the code we discussed. Do we need to divide by the screen resolution for that? No, we don't. We could if it would make our life easier to get from A to B, but we simply do not need it here and the original shadertoy algorithm doesn't do it.&#xD;&#xA;&#xD;&#xA;So the question shouldn't be &quot;why the x-component of uv isn't normalized&quot; but: &#xD;&#xA;&#xD;&#xA;&quot;Why do I get the correct result when I use normalized screen coordinates instead of fragment coordinates for the y-component and wrong ones if not&quot;? &#xD;&#xA;&#xD;&#xA;I have not tested your code, but by just looking at it, I would say by normalizing the y component here: `(gl_FragCoord.y / v_Resolution.y) + (v_Resolution.y / 2.f)` you are more or less &quot;removing&quot; them from the line. Just insert the numbers: &#xD;&#xA;&#xD;&#xA;- `gl_FragCoord.y / v_Resolution.y` is a number between 0 and 1 &#xD;&#xA;- `v_Resolution.y / 2.f` is 309&#xD;&#xA;&#xD;&#xA;So at this point, you have v-values between 309 and 310. It is almost a constant. Simply remove `gl_FragCoord.y / v_Resolution.y` and you should still get the same result. Now the question arises, why is the grid still rendered correctly? I guess because of this line:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;    uv.y -= gl_FragCoord.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Note that you use `gl_FragCoord.y` while the Shadertoy code used `iResolution.y`, which is a constant. What you do here is correcting the effective removal of gl_FragCoord.y I explained before. You need to divide by `v_CellSize` because the uv coordinates were also divided by `v_CellSize` 2 instructions before (`uv.y /= v_CellSize;`).&#xD;&#xA;&#xD;&#xA;**How to correct it?**&#xD;&#xA;&#xD;&#xA;Simply remove this line:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;uv.y -= gl_FragCoord.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Then remove the division through `v_Resolution.y` from here:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y / v_Resolution.y + v_Resolution.y / 2 - v_CellSize / 2);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;It should look like this:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;void main() {&#xD;&#xA;&#xD;&#xA;    float width = lineWidth / v_CellSize;&#xD;&#xA;&#xD;&#xA;    vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y + v_Resolution.y / 2 - v_CellSize / 2);&#xD;&#xA;&#xD;&#xA;    uv.x *= 1.0 / v_CellSize;&#xD;&#xA;    uv.y /= v_CellSize;&#xD;&#xA;&#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;    uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    // Apply camera translation.&#xD;&#xA;    uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;    uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;    &#xD;&#xA;    float grid = 0.0;&#xD;&#xA;    grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;    grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;    &#xD;&#xA;    vec4 col = vec4(grid);&#xD;&#xA;&#xD;&#xA;    // ... insert rest of your code &#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now you should have the &quot;correct&quot; result and the x and y components are treated identically." ContentLicense="CC BY-SA 4.0" />
  <row Id="31270" PostHistoryTypeId="5" PostId="10706" RevisionGUID="e028e0f3-faa3-46b7-a653-49e3b840e819" CreationDate="2021-03-06T18:18:24.877" UserId="13095" Comment="deleted 10 characters in body" Text="&gt;Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding v_Resolution.x / 2 to uv.x.&#xD;&#xA;&#xD;&#xA;Not sure what your intention is here since the Shadertoy example you referenced generates an infinite grid. So maybe you can clarify that.&#xD;&#xA;&#xD;&#xA;However, I think I can help you with this problem:&#xD;&#xA;&#xD;&#xA;&gt;  ... the ShaderToy example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.&#xD;&#xA;&#xD;&#xA;I think the basic problem here is, that you do not really understand how the mesh is generated and why the Shadertoy example isn't normalizing the uv-coordinates. If I can help you understand it, you can probably fix your other problems by yourself.&#xD;&#xA;&#xD;&#xA;So let's walk through the Shadertoy code and what it actually does:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;vec2 uv = fragCoord.xy;&#xD;&#xA;	&#xD;&#xA;// Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;uv.x *= 1.0 / spacing;&#xD;&#xA;uv.y /= spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here you first copy the frag coordinates into `uv` and afterward divide it by the spacing of your lines. Not sure why the author used those 'complicated' last two lines, but you can replace them simply with `uv /= spacing;`.&#xD;&#xA;The purpose of this step is to transform into a new space where the lines of your grid are located at every whole number. If your spacing is 20, like in the shader toy example, only the fragments with one of its frag coordinates being one of 0, 20, 40, etc. would produce a whole number and would be located on a line. Maybe you can already see where this is going.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;// Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;	&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;uv.y -= (iResolution.y - 600.0) / spacing;&#xD;&#xA;	&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x -= translation.x / spacing;&#xD;&#xA;uv.y += translation.y / spacing;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Here he is just translating the grid to consider several things like line thickness and camera position. The camera position is probably what you are interested in. I have no clue, about the purpose of the second line, even though the comment specifies it, but it is just a y-shift of your grid. However, note that all translations must be in the &quot;grid-space&quot; like the uv coordinates. Hence he always divides by `spacing`. For `width`, he already applied the transformation several lines above -&gt; `float width   = float(lineWidth)   / spacing;`&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;float grid = 0.0;&#xD;&#xA;grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;&#xD;&#xA;vec4 col = vec4(grid);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now here comes the magic that actually produces the grid. Let's dissect the second line. `fract(uv.x)` just [returns the fractional part](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/fract.xhtml) of `uv.x`. So a value of `12.125` is reduced to `0.125`. The [step function](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/step.xhtml) returns 0 if the second value is smaller than the first and 1 otherwise. So the point of `step(fract(uv.x), width)` frac is to get a `1` if the uv coordinate is on a vertical line and 0 if not. The `max` in this line is pretty pointless since `grid` (which is set to `0.0`) is either equal to the returned value or less. The third line does the same thing for horizontal lines, but here the `max` is actually needed.&#xD;&#xA;So to sum it up, `grid` is `1` if the fragment lies on a horizontal and/or vertical line and `0` if not.&#xD;&#xA;The last line just turns that into a vector. So you either get pure white (`(1.0, 1.0, 1.0, 1.0)`) as pixel color if the fragment is part of a line or pure black (`(0.0, 0.0, 0.0, 0.0)`) if not. Note that if alpha blending is enabled, black is actually translucent since the alpha channel is also `0`.&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;if (col.r != 0.0 &amp;&amp; col.g != 0.0 &amp;&amp; col.b != 0.0) {&#xD;&#xA;	float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;	float my = mod(uv.y, float(darkenMultiple));&#xD;&#xA;		&#xD;&#xA;	// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;	col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;} else {&#xD;&#xA;	// Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.&#xD;&#xA;	col.a = 0.0;&#xD;&#xA;}&#xD;&#xA;	&#xD;&#xA;col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;fragColor = col;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;This just adjusting the color of the grid and plotting the cat and not relevant to your question.&#xD;&#xA;&#xD;&#xA;I optimized the shader from the Shadertoy example a little bit by removing obsolete instructions, postponing the transformation into &quot;grid space&quot; after applying the translations, and vectorizing some operations. Maybe it makes it easier for you to understand what is happening. I kept the original comments and added some own ones:&#xD;&#xA;&#xD;&#xA;~~~ glsl&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord ) {&#xD;&#xA;    // Define some variables we use ---------------------------------------------&#xD;&#xA;	// Simulate camera translation, just for this example.&#xD;&#xA;	vec2 velocity = vec2(-30.0, 10.0);	&#xD;&#xA;	translation += scale * iTime * velocity;&#xD;&#xA;	&#xD;&#xA;	float spacing = float(lineSpacing) * scale;&#xD;&#xA;	float width   = float(lineWidth)   / spacing;&#xD;&#xA;		&#xD;&#xA;    // Add all translations to uv -----------------------------------------------&#xD;&#xA;	// Apply camera translation.&#xD;&#xA;	vec2 uv = fragCoord - translation;&#xD;&#xA;    &#xD;&#xA;    // Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;	uv.y -= (iResolution.y - 600.0);&#xD;&#xA;    &#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;	uv += (lineWidth &gt; 1) ? float(lineWidth) * 0.5 : float(lineWidth);&#xD;&#xA;&#xD;&#xA;    // Transform to &quot;grid space&quot; ------------------------------------------------    &#xD;&#xA;    // Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).&#xD;&#xA;    uv /= spacing;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    // Identify if pixel is on a line -------------------------------------------&#xD;&#xA;	float grid =     step(fract(uv.x), width)       ; // X lines (horizontal)&#xD;&#xA;	grid       = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;	&#xD;&#xA;    // Set the correct color ----------------------------------------------------&#xD;&#xA;	vec4 col = vec4(grid);&#xD;&#xA;	if (grid != 0.0) {&#xD;&#xA;		float mx = mod(uv.x, float(darkenMultiple));&#xD;&#xA;		float my = mod(uv.y, float(darkenMultiple));        &#xD;&#xA;		&#xD;&#xA;		// Make lines that are a multiple of `darkenMultiple` darker than the rest.&#xD;&#xA;		col.a = (mx &lt; width || my &lt; width) ? 0.2 : 0.15;&#xD;&#xA;	} &#xD;&#xA;	&#xD;&#xA;    // Plot the cat -------------------------------------------------------------&#xD;&#xA;	col = showNyanCat(col, fragCoord);&#xD;&#xA;	&#xD;&#xA;	fragColor = col;&#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;In this version, you can simply add your translations in pixels without any need to transform them to &quot;grid space&quot; or to normalize them. Hope that helps. You can copy it into the Shadertoy example to see that the results are the same.&#xD;&#xA;&#xD;&#xA;&gt; Now, if I remember correctly, the origin in a GLSL fragment shader is bottom left, so why do I have to subtract v_Resolution.x / 2.f instead of adding it? &#xD;&#xA;&#xD;&#xA;Probably because you use different signs here:&#xD;&#xA;~~~&#xD;&#xA;// Apply camera translation.&#xD;&#xA;uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;&gt; (also, why is the x-component not normalized, like the y-component?)&#xD;&#xA;&#xD;&#xA;I guess you fiddled around until &quot;something&quot; produced the expected image rather than knowing what happens. I see no point in investigating the &quot;why&quot; here. Understand the Shadertoy code (or my version) and then apply your changes while actually knowing what you are doing. If you use my version, all you have to add are the translations in pixels that you want to apply.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Update&#xD;&#xA;&#xD;&#xA;Regarding the comment of Andrew Woo:&#xD;&#xA;&#xD;&#xA;&gt; I really appreciate the in-depth explanation, it helped a lot in my understanding, however it doesn't really answer my [original] question, which was why the x-component of uv isn't normalized. &#xD;&#xA;&#xD;&#xA;I was addressing that at the end of the original answer when I said that you fiddled around until &quot;something&quot; worked and I didn't saw any point in investigating why &quot;obviously wrong&quot; code produces the correct result.&#xD;&#xA;&#xD;&#xA;Well, let's get something clear: uv coordinates are not screen coordinates. So `gl_FragCoord.y / v_Resolution.y` is not the general definition of `v`. I would rather call them &quot;normalized screen coordinates&quot;. uv coordinates are (usually) used to map regular 2-dimensional data like an image onto a surface. You can read more about them on [Wikipedia](https://en.wikipedia.org/wiki/UV_mapping). Don't be fooled by the fact that the author of the question you linked used the &quot;normalized screen coordinates&quot; as uv coordinates. They might be the same if you want to map an image to your screen, but usually, they are not. &#xD;&#xA;&#xD;&#xA;In the shadertoy example, the uv coordinates are used to map a single cell of your grid. You start using uv coordinates of the grid after you divided the frag coordinates by the cell size. Before that, they are no uv coordinates, at least not in relation to the grid.&#xD;&#xA;&#xD;&#xA;So let's summarize what the shader does: You start with pixel coordinates inside your shader with values between 0 and the screen resolution in either direction and you want to calculate the uv coordinates of the grid in order to draw it. That's the whole purpose of the code we discussed. Do we need to divide by the screen resolution for that? No, we don't. We could if it would make our life easier to get from A to B, but we simply do not need it here and the original shadertoy algorithm doesn't do it.&#xD;&#xA;&#xD;&#xA;So the question shouldn't be &quot;why the x-component of uv isn't normalized&quot; but: &#xD;&#xA;&#xD;&#xA;&quot;Why do I get the correct result when I use normalized screen coordinates instead of fragment coordinates for the y-component and wrong ones if not&quot;? &#xD;&#xA;&#xD;&#xA;I have not tested your code, but by just looking at it, I would say by normalizing the y component here: `(gl_FragCoord.y / v_Resolution.y) + (v_Resolution.y / 2.f)` you are more or less &quot;removing&quot; them from the line. Just insert the numbers: &#xD;&#xA;&#xD;&#xA;- `gl_FragCoord.y / v_Resolution.y` is a number between 0 and 1 &#xD;&#xA;- `v_Resolution.y / 2.f` is 309&#xD;&#xA;&#xD;&#xA;So at this point, you have v-values between 309 and 310. It is almost a constant. Simply remove `gl_FragCoord.y / v_Resolution.y` and you should still get the same result. Now the question arises, why is the grid still rendered correctly? I guess because of this line:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.&#xD;&#xA;    uv.y -= gl_FragCoord.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Note that you use `gl_FragCoord.y` while the Shadertoy code used `iResolution.y`, which is a constant. What you do here is correcting the effective removal of gl_FragCoord.y I explained before. You need to divide by `v_CellSize` because the uv coordinates were also divided by `v_CellSize` 2 instructions before (`uv.y /= v_CellSize;`).&#xD;&#xA;&#xD;&#xA;**How to correct it?**&#xD;&#xA;&#xD;&#xA;Simply remove this line:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;uv.y -= gl_FragCoord.y / v_CellSize;&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Then remove the division through `v_Resolution.y` from here:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y / v_Resolution.y + v_Resolution.y / 2 - v_CellSize / 2);&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;It should look like this:&#xD;&#xA;&#xD;&#xA;~~~ GLSL&#xD;&#xA;void main() {&#xD;&#xA;&#xD;&#xA;    float width = lineWidth / v_CellSize;&#xD;&#xA;&#xD;&#xA;    vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y + v_Resolution.y / 2 - v_CellSize / 2);&#xD;&#xA;&#xD;&#xA;    uv.x *= 1.0 / v_CellSize;&#xD;&#xA;    uv.y /= v_CellSize;&#xD;&#xA;&#xD;&#xA;    // Adjust the origin of each line thicker than one pixel to its center.&#xD;&#xA;    uv.xy += (lineWidth &gt; 1) ? width * 0.5 : width;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    // Apply camera translation.&#xD;&#xA;    uv.x += v_CamPos.x / v_CellSize;&#xD;&#xA;    uv.y -= v_CamPos.y / v_CellSize;&#xD;&#xA;    &#xD;&#xA;    float grid = 0.0;&#xD;&#xA;    grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)&#xD;&#xA;    grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)&#xD;&#xA;    &#xD;&#xA;    vec4 col = vec4(grid);&#xD;&#xA;&#xD;&#xA;    // ... insert rest of your code &#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Now you should have the &quot;correct&quot; result and the x and y components are treated identically." ContentLicense="CC BY-SA 4.0" />
  <row Id="31271" PostHistoryTypeId="50" PostId="9919" RevisionGUID="71f28c61-499d-427b-b316-1f2b9e661e77" CreationDate="2021-03-07T12:06:50.870" UserId="-1" />
  <row Id="31272" PostHistoryTypeId="2" PostId="10718" RevisionGUID="93c61fb3-a9c0-4fc6-bff2-574ccca837f5" CreationDate="2021-03-07T14:00:24.417" UserId="15888" Text="Recently I've switched from FXC to DXC to compile shader model 6.0. It compiles well without errors (and runs well) but I can't debug shaders because on my netbook PIX says &quot;failed to load PDB file&quot;, and on my main laptop PIX can't even start analysis and it shows the error &quot;Timing Data Error&quot;.&#xD;&#xA;&#xD;&#xA;[![PIX error][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9HiGI.jpg&#xD;&#xA;&#xD;&#xA;What am I missing? The compilation generates PDB files (I can see them in the folder with the .exe) but PIX can't find them for some reason. I compile shaders like this:&#xD;&#xA;&#xD;&#xA;	&#xD;&#xA;&#xD;&#xA;        // Create compiler and utils.&#xD;&#xA;    	CComPtr&lt;IDxcUtils&gt; pUtils;&#xD;&#xA;    	CComPtr&lt;IDxcCompiler3&gt; pCompiler;&#xD;&#xA;    	DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&amp;pUtils));&#xD;&#xA;    	DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&amp;pCompiler));&#xD;&#xA;    &#xD;&#xA;    	// Create default include handler.&#xD;&#xA;    	CComPtr&lt;IDxcIncludeHandler&gt; pIncludeHandler;&#xD;&#xA;    	pUtils-&gt;CreateDefaultIncludeHandler(&amp;pIncludeHandler);&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    	std::vector&lt;LPCWSTR&gt; vArgs;&#xD;&#xA;    	vArgs.push_back(sPathToShader.c_str());&#xD;&#xA;    	vArgs.push_back(L&quot;-E&quot;);&#xD;&#xA;    	vArgs.push_back(sShaderEntryPoint.c_str());&#xD;&#xA;    	vArgs.push_back(L&quot;-T&quot;);&#xD;&#xA;    	vArgs.push_back(sShaderModel.c_str());&#xD;&#xA;        vArgs.push_back(DXC_ARG_DEBUG);&#xD;&#xA;    	vArgs.push_back(DXC_ARG_SKIP_OPTIMIZATIONS);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Open source file.  &#xD;&#xA;    	CComPtr&lt;IDxcBlobEncoding&gt; pSource = nullptr;&#xD;&#xA;    	pUtils-&gt;LoadFile(sPathToShader.c_str(), nullptr, &amp;pSource);&#xD;&#xA;    	DxcBuffer Source;&#xD;&#xA;    	Source.Ptr = pSource-&gt;GetBufferPointer();&#xD;&#xA;    	Source.Size = pSource-&gt;GetBufferSize();&#xD;&#xA;    	Source.Encoding = DXC_CP_ACP;&#xD;&#xA;    &#xD;&#xA;    	// Compile it with specified arguments.&#xD;&#xA;    	CComPtr&lt;IDxcResult&gt; pResults;&#xD;&#xA;    	pCompiler-&gt;Compile(&#xD;&#xA;    		&amp;Source,&#xD;&#xA;    		vArgs.data(),&#xD;&#xA;    		vArgs.size(),&#xD;&#xA;    		pIncludeHandler,&#xD;&#xA;    		IID_PPV_ARGS(&amp;pResults)&#xD;&#xA;    	);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Print errors if present.&#xD;&#xA;    	CComPtr&lt;IDxcBlobUtf8&gt; pErrors = nullptr;&#xD;&#xA;    	pResults-&gt;GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&amp;pErrors), nullptr);&#xD;&#xA;    	if (pErrors != nullptr &amp;&amp; pErrors-&gt;GetStringLength() != 0)&#xD;&#xA;    	{&#xD;&#xA;    		OutputDebugStringA(pErrors-&gt;GetStringPointer());&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Quit if the compilation failed.&#xD;&#xA;    	HRESULT hrStatus;&#xD;&#xA;    	pResults-&gt;GetStatus(&amp;hrStatus);&#xD;&#xA;    	if (FAILED(hrStatus))&#xD;&#xA;    	{&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Save shader binary.&#xD;&#xA;    	CComPtr&lt;IDxcBlob&gt; pShader = nullptr;&#xD;&#xA;    	CComPtr&lt;IDxcBlobUtf16&gt; pShaderName = nullptr;&#xD;&#xA;    	pResults-&gt;GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&amp;pShader), &amp;pShaderName);&#xD;&#xA;    	if (pShader == nullptr)&#xD;&#xA;    	{&#xD;&#xA;    		return;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // Save pdb.&#xD;&#xA;    	CComPtr&lt;IDxcBlob&gt; pPDB = nullptr;&#xD;&#xA;    	CComPtr&lt;IDxcBlobUtf16&gt; pPDBName = nullptr;&#xD;&#xA;    	pResults-&gt;GetOutput(DXC_OUT_PDB, IID_PPV_ARGS(&amp;pPDB), &amp;pPDBName);&#xD;&#xA;    	{&#xD;&#xA;    		FILE* fp = NULL;&#xD;&#xA;    		_wfopen_s(&amp;fp, pPDBName-&gt;GetStringPointer(), L&quot;wb&quot;);&#xD;&#xA;    		fwrite(pPDB-&gt;GetBufferPointer(), pPDB-&gt;GetBufferSize(), 1, fp);&#xD;&#xA;    		fclose(fp);&#xD;&#xA;    	}&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31273" PostHistoryTypeId="1" PostId="10718" RevisionGUID="93c61fb3-a9c0-4fc6-bff2-574ccca837f5" CreationDate="2021-03-07T14:00:24.417" UserId="15888" Text="Weird PIX behavior with DXC" ContentLicense="CC BY-SA 4.0" />
  <row Id="31274" PostHistoryTypeId="3" PostId="10718" RevisionGUID="93c61fb3-a9c0-4fc6-bff2-574ccca837f5" CreationDate="2021-03-07T14:00:24.417" UserId="15888" Text="|c++|hlsl|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31275" PostHistoryTypeId="2" PostId="10719" RevisionGUID="e011bfa4-57b7-448f-bb9f-94018d3b3f5f" CreationDate="2021-03-07T17:35:07.293" UserId="15886" Text="While I'll try my best to give all relevant info in all possible brevity below, please refer to the spoiler and link at the bottom of the post for the (more lengthy) original description if needed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose for a buch of triangles, I put each triangle's surface area (along with a reference to the tri itself) into the nodes of a binary search tree.&#xD;&#xA;Each internal node always contains the summed area of it's children. By consequence, the root node contains the summed area of all the tris at hand.&#xD;&#xA;&#xD;&#xA;Now the topological connectivity-info and the area-values of the binary tree are used to construct a kd-tree in the unit square which (the unit square) we call sample-space.  &#xD;&#xA;The kd-tree's root node corresponds to the whole unit square.&#xD;&#xA;The sample-space is divided by an axis-aligned split line into two subsets (one for each child-node) such as to partition it by the same ratio by which the (mesh-triangle-) area-value of the aforementioned binary tree's root-node is partitioned by those of it's child-nodes. &#xD;&#xA;This way, at each level, the kd-tree subdivides the sample-space into two subsets, the area of which is proportional to the area covered by the mesh triangles represented by the corresponding nodes in the binary tree. &#xD;&#xA;&#xD;&#xA;[![source:Umenhoffer, Szécsi, Szirmay-Kalos - Hatching for Motion Picture Production (2011)][1]][1]  &#xD;&#xA;source:Umenhoffer, Szécsi, Szirmay-Kalos - [Hatching for Motion Picture Production (2011)](https://www.researchgate.net/publication/220506553_Hatching_for_Motion_Picture_Production)&#xD;&#xA;&#xD;&#xA;All of this serves as a means of mapping the sample-space onto the mesh triangles in object space in an area-preserving way.&#xD;&#xA;It is used to perform quasi Monte-Carlo sampling in the sample space and use the datastructures outlined above to transform the samples from sample-space to the triangle's object space.&#xD;&#xA;&#xD;&#xA;I have omitted the details of how the algorithm effectively translates a (u,v) sample-position in sample-space into barycentric triangle-coordinates by traversing the kd-tree here for brevity.&#xD;&#xA;(see the spoiler)&#xD;&#xA;&gt;!When we need to transform samples into the object-space,&#xD;&#xA;&gt;!we use the kd-tree. Given the (u,v)coordinates of the sam-&#xD;&#xA;&gt;!pled point, we start from the root of the tree, comparing the&#xD;&#xA;&gt;!coordinate of the splitting axis to the splitting ratio. Depend-&#xD;&#xA;&gt;!ing on the result of the comparison, we continue recursively&#xD;&#xA;&gt;!with one of the branches, normalizing the coordinate to the&#xD;&#xA;&gt;!cell’s [0,1]range. At a leaf, the (u,v)coordinates we get are&#xD;&#xA;&gt;!interpreted according to the natural parametrization of the&#xD;&#xA;&gt;!quadrilateral, or as two of the unit-sum barycentric coordi-&#xD;&#xA;&gt;!nates on the triangle (or (1−u,1−v)if u+v&gt;1).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**The question is this**: Does the order of the leaf-nodes in the binary tree matter at all for this mapping (to preserve the properties of the QMC sampling during the transformation)?&#xD;&#xA;&#xD;&#xA;My intuition tells me 'no, it doesn't matter at all, a random order is as good as any other'. On the other hand, the authors of the [paper](https://www.researchgate.net/publication/220506553_Hatching_for_Motion_Picture_Production) from which I've taken the algorithm outlined above state (section 4.1.1, §3)(bold typeface added by me for emphasis):&#xD;&#xA;&gt;The faces of the model of the mesh are roughly arranged in a 1D&#xD;&#xA;&gt;face array **by proximity**. In typical cases, this naturally arises&#xD;&#xA;&gt;from the modeling process. Otherwise, mesh optimization&#xD;&#xA;&gt;algorithms (e.g. stripification) [DGGP05] can be applied.&#xD;&#xA;&gt;First, we build a balanced binary tree, called the *summed*&#xD;&#xA;&gt;*area tree*, in which leaf values are triangle surface areas **in**&#xD;&#xA;&gt;**the same order as** they appear **in the face array**.&#xD;&#xA;&#xD;&#xA;The fact the authors seem to bother about the order of the leafs in the binary tree (which they call summed area tree) and even suggest using an explicit stripification-algorithm might suggest otherwise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here a spoiler where you can read up the algorithm as described by the authors:&#xD;&#xA;&gt;!In order to deﬁne a mapping from sample-space to object-&#xD;&#xA;&gt;!space, we need to place the mesh faces into the sample-space&#xD;&#xA;&gt;!without distorting face area ratios, and be able to locate the&#xD;&#xA;&gt;!face containing sample point (u,v). This is a typical prox-&#xD;&#xA;&gt;!imity search problem, which is well supported by a kd-tree.&#xD;&#xA;&gt;!The data structures required for the build and search pro-&#xD;&#xA;&gt;!cesses are depicted in Figure 4.&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!The faces of the model mesh are roughly arranged in a 1D&#xD;&#xA;&gt;!face array by proximity. In typical cases, this naturally arises&#xD;&#xA;&gt;!from the modeling process. Otherwise, mesh optimization&#xD;&#xA;&gt;!algorithms (e.g. stripiﬁcation) [DGGP05] can be applied.&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!First, we build a balanced binary tree, called the summed&#xD;&#xA;&gt;!area tree, in which leaf values are triangle surface areas in&#xD;&#xA;&gt;!the same order as they appear in the face array. Any branch&#xD;&#xA;&gt;!node contains the summed area of its children. The root node&#xD;&#xA;&gt;!will contain the surface area of the complete object.&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!Then, we partition the sample-space with a kd-tree that&#xD;&#xA;&gt;!has the same balanced topology. Every node in the kd-tree&#xD;&#xA;&gt;!corresponds to a node in the area tree. The unit square cell in&#xD;&#xA;&gt;!sample-space is assigned to the root node, which is split re-&#xD;&#xA;&gt;!cursively along the coordinate axes resulting in a binary tree&#xD;&#xA;&gt;!of cells. At a given node, the splitting ratio is selected so that&#xD;&#xA;&gt;!the areas of the two new cells are proportional to the summed&#xD;&#xA;&gt;!surface areas stored in the corresponding child nodes of the&#xD;&#xA;&gt;!area tree. Thus, the sample-space area that belongs to a set of&#xD;&#xA;&gt;!faces will be proportional to their surface area. Where the set&#xD;&#xA;&gt;!reduces to a single face, the face is mapped to the cell. This&#xD;&#xA;&gt;!is trivial for quadrilateral faces, but also works well with tri-&#xD;&#xA;&gt;!angles if we represent each triangle twice and arrange each&#xD;&#xA;&gt;!pair as a quad (right of Figure 4).&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!When we need to transform samples into the object-space,&#xD;&#xA;&gt;!we use the kd-tree. Given the (u,v)coordinates of the sam-&#xD;&#xA;&gt;!pled point, we start from the root of the tree, comparing the&#xD;&#xA;&gt;!coordinate of the splitting axis to the splitting ratio. Depend-&#xD;&#xA;&gt;!ing on the result of the comparison, we continue recursively&#xD;&#xA;&gt;!with one of the branches, normalizing the coordinate to the&#xD;&#xA;&gt;!cell’s [0,1]range. At a leaf, the (u,v)coordinates we get are&#xD;&#xA;&gt;!interpreted according to the natural parametrization of the&#xD;&#xA;&gt;!quadrilateral, or as two of the unit-sum barycentric coordi-&#xD;&#xA;&gt;!nates on the triangle (or (1−u,1−v)if u+v&gt;1).&#xD;&#xA;&#xD;&#xA;Link to the full text of the paper: [Hatching for Motion Picture Production](https://www.researchgate.net/publication/220506553_Hatching_for_Motion_Picture_Production).&#xD;&#xA;&#xD;&#xA;Thank you for any input.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FUAiH.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31276" PostHistoryTypeId="1" PostId="10719" RevisionGUID="e011bfa4-57b7-448f-bb9f-94018d3b3f5f" CreationDate="2021-03-07T17:35:07.293" UserId="15886" Text="Is this way of transforming QMC samples into barycentric tri coordinates agnostic to mesh-topology?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31277" PostHistoryTypeId="3" PostId="10719" RevisionGUID="e011bfa4-57b7-448f-bb9f-94018d3b3f5f" CreationDate="2021-03-07T17:35:07.293" UserId="15886" Text="|algorithm|mathematics|computational-geometry|sampling|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31278" PostHistoryTypeId="5" PostId="10719" RevisionGUID="f018fa95-3135-41ab-a226-631b2d00d32e" CreationDate="2021-03-07T17:45:36.593" UserId="15886" Comment="added 41 characters in body" Text="While I'll try my best to give all relevant info in all possible brevity below, please refer to the spoiler and link at the bottom of the post for the (more lengthy) original description if needed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Suppose for a buch of triangles, I put each triangle's surface area (along with a reference to the tri itself) into the nodes of a binary search tree.&#xD;&#xA;Each internal node always contains the summed area of it's children. By consequence, the root node contains the summed area of all the tris at hand.&#xD;&#xA;&#xD;&#xA;Now the topological connectivity-info and the area-values of the binary tree are used to construct a kd-tree in the unit square which (the unit square) we call sample-space.  &#xD;&#xA;The kd-tree's root node corresponds to the whole unit square.&#xD;&#xA;The sample-space is divided by an axis-aligned split line into two subsets (one for each child-node) such as to partition it by the same ratio by which the (mesh-triangle-) area-value of the aforementioned binary tree's root-node is partitioned by those of it's child-nodes. &#xD;&#xA;This way, at each level, the kd-tree subdivides the sample-space into two subsets, the area of which is proportional to the area covered by the mesh triangles represented by the corresponding nodes in the binary tree. &#xD;&#xA;&#xD;&#xA;[![source:Umenhoffer, Szécsi, Szirmay-Kalos - Hatching for Motion Picture Production (2011)][1]][1]  &#xD;&#xA;source:Umenhoffer, Szécsi, Szirmay-Kalos - [Hatching for Motion Picture Production (2011)](https://www.researchgate.net/publication/220506553_Hatching_for_Motion_Picture_Production)&#xD;&#xA;&#xD;&#xA;All of this serves as a means of mapping the sample-space onto the mesh triangles in object space in an area-preserving way.&#xD;&#xA;It is used to perform quasi Monte-Carlo sampling in the sample space and use the datastructures outlined above to transform the samples from sample-space to the triangle's object space.&#xD;&#xA;&#xD;&#xA;I have omitted the details of how the algorithm effectively translates a (u,v) sample-position in sample-space into barycentric triangle-coordinates by traversing the kd-tree here for brevity.&#xD;&#xA;(see the spoiler)&#xD;&#xA;&gt;!When we need to transform samples into the object-space,&#xD;&#xA;&gt;!we use the kd-tree. Given the (u,v)coordinates of the sam-&#xD;&#xA;&gt;!pled point, we start from the root of the tree, comparing the&#xD;&#xA;&gt;!coordinate of the splitting axis to the splitting ratio. Depend-&#xD;&#xA;&gt;!ing on the result of the comparison, we continue recursively&#xD;&#xA;&gt;!with one of the branches, normalizing the coordinate to the&#xD;&#xA;&gt;!cell’s [0,1]range. At a leaf, the (u,v)coordinates we get are&#xD;&#xA;&gt;!interpreted according to the natural parametrization of the&#xD;&#xA;&gt;!quadrilateral, or as two of the unit-sum barycentric coordi-&#xD;&#xA;&gt;!nates on the triangle (or (1−u,1−v)if u+v&gt;1).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**The question is this**: Does the order of the leaf-nodes in the binary tree matter at all for this mapping (to preserve the properties of the QMC sampling during the transformation)?&#xD;&#xA;&#xD;&#xA;My intuition tells me 'no, it doesn't matter at all, a random order is as good as any other'. On the other hand, the authors of the [paper](https://www.researchgate.net/publication/220506553_Hatching_for_Motion_Picture_Production) from which I've taken the algorithm outlined above state (section 4.1.1, §3)(bold typeface added by me for emphasis):&#xD;&#xA;&gt;The faces of the model of the mesh are roughly arranged in a 1D&#xD;&#xA;&gt;face array **by proximity**. In typical cases, this naturally arises&#xD;&#xA;&gt;from the modeling process. Otherwise, mesh optimization&#xD;&#xA;&gt;algorithms (e.g. stripification) [DGGP05] can be applied.&#xD;&#xA;&gt;First, we build a balanced binary tree, called the *summed*&#xD;&#xA;&gt;*area tree*, in which leaf values are triangle surface areas **in**&#xD;&#xA;&gt;**the same order as** they appear **in the face array**.&#xD;&#xA;&#xD;&#xA;The fact the authors seem to bother about the order of the leafs in the binary tree (which they call summed area tree) and even suggest using an explicit stripification-algorithm might suggest otherwise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here a spoiler where you can read up the algorithm as described by the authors:&#xD;&#xA;&gt;!In order to deﬁne a mapping from sample-space to object-&#xD;&#xA;&gt;!space, we need to place the mesh faces into the sample-space&#xD;&#xA;&gt;!without distorting face area ratios, and be able to locate the&#xD;&#xA;&gt;!face containing sample point (u,v). This is a typical prox-&#xD;&#xA;&gt;!imity search problem, which is well supported by a kd-tree.&#xD;&#xA;&gt;!The data structures required for the build and search pro-&#xD;&#xA;&gt;!cesses are depicted in Figure 4.&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!The faces of the model mesh are roughly arranged in a 1D&#xD;&#xA;&gt;!face array by proximity. In typical cases, this naturally arises&#xD;&#xA;&gt;!from the modeling process. Otherwise, mesh optimization&#xD;&#xA;&gt;!algorithms (e.g. stripiﬁcation) [DGGP05] can be applied.&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!First, we build a balanced binary tree, called the summed&#xD;&#xA;&gt;!area tree, in which leaf values are triangle surface areas in&#xD;&#xA;&gt;!the same order as they appear in the face array. Any branch&#xD;&#xA;&gt;!node contains the summed area of its children. The root node&#xD;&#xA;&gt;!will contain the surface area of the complete object.&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!Then, we partition the sample-space with a kd-tree that&#xD;&#xA;&gt;!has the same balanced topology. Every node in the kd-tree&#xD;&#xA;&gt;!corresponds to a node in the area tree. The unit square cell in&#xD;&#xA;&gt;!sample-space is assigned to the root node, which is split re-&#xD;&#xA;&gt;!cursively along the coordinate axes resulting in a binary tree&#xD;&#xA;&gt;!of cells. At a given node, the splitting ratio is selected so that&#xD;&#xA;&gt;!the areas of the two new cells are proportional to the summed&#xD;&#xA;&gt;!surface areas stored in the corresponding child nodes of the&#xD;&#xA;&gt;!area tree. Thus, the sample-space area that belongs to a set of&#xD;&#xA;&gt;!faces will be proportional to their surface area. Where the set&#xD;&#xA;&gt;!reduces to a single face, the face is mapped to the cell. This&#xD;&#xA;&gt;!is trivial for quadrilateral faces, but also works well with tri-&#xD;&#xA;&gt;!angles if we represent each triangle twice and arrange each&#xD;&#xA;&gt;!pair as a quad (right of Figure 4).&#xD;&#xA;&gt;!&#xD;&#xA;&gt;!When we need to transform samples into the object-space,&#xD;&#xA;&gt;!we use the kd-tree. Given the (u,v)coordinates of the sam-&#xD;&#xA;&gt;!pled point, we start from the root of the tree, comparing the&#xD;&#xA;&gt;!coordinate of the splitting axis to the splitting ratio. Depend-&#xD;&#xA;&gt;!ing on the result of the comparison, we continue recursively&#xD;&#xA;&gt;!with one of the branches, normalizing the coordinate to the&#xD;&#xA;&gt;!cell’s [0,1]range. At a leaf, the (u,v)coordinates we get are&#xD;&#xA;&gt;!interpreted according to the natural parametrization of the&#xD;&#xA;&gt;!quadrilateral, or as two of the unit-sum barycentric coordi-&#xD;&#xA;&gt;!nates on the triangle (or (1−u,1−v)if u+v&gt;1).&#xD;&#xA;&#xD;&#xA;Link to the full text of the paper: [Hatching for Motion Picture Production](https://www.researchgate.net/publication/220506553_Hatching_for_Motion_Picture_Production). The relevant part is only section 4.1.1.&#xD;&#xA;&#xD;&#xA;Thank you for any input.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FUAiH.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31279" PostHistoryTypeId="50" PostId="9926" RevisionGUID="5efc22cd-8c57-47c7-8dff-82073b6d8040" CreationDate="2021-03-07T23:02:45.330" UserId="-1" />
  <row Id="31284" PostHistoryTypeId="2" PostId="10721" RevisionGUID="62143976-5e07-4b4c-9996-7945f2ec3b6a" CreationDate="2021-03-10T20:03:03.150" UserId="15910" Text="[![probe vs cubemap in blender][1]][1]&#xD;&#xA;&#xD;&#xA;the **cubemaps** which have this cube shape in blender store a **360 image** of that point that can be used for reflections, world texture images...&#xD;&#xA;&#xD;&#xA;**probes** which are the circles store only **light info** (am i getting white raylights? yellow?)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BUlnf.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31285" PostHistoryTypeId="5" PostId="10721" RevisionGUID="c9403742-d6d6-413b-84ca-ea2a8199d866" CreationDate="2021-03-10T20:08:27.147" UserId="15910" Comment="added 45 characters in body" Text="[![probe vs cubemap in blender][1]][1]&#xD;&#xA;&#xD;&#xA;the **cubemaps** which have this cube shape in blender store a **360 image** of that point that can be used for reflections, world texture images...&#xD;&#xA;&#xD;&#xA;**probes** which are the circles store only **light info** (am i getting white raylights? yellow?)&#xD;&#xA;&#xD;&#xA;*I might be wrong, in that case correct me*&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BUlnf.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31286" PostHistoryTypeId="5" PostId="10721" RevisionGUID="6bbdce2b-bc96-491a-92d7-ae5fd81bf866" CreationDate="2021-03-10T20:23:23.297" UserId="15910" Comment="added 66 characters in body" Text="[![probe vs cubemap in blender][1]][1]&#xD;&#xA;&#xD;&#xA;the **cubemaps** which have this cube shape in blender store a **360 image** of that point that can be used for reflections, world texture images...&#xD;&#xA;&#xD;&#xA;also seems like cubemap can be called reflection probe sometimes to add to the confussion, so seems like cubemaps are a type of probe too more specific to remapping&#xD;&#xA;&#xD;&#xA;**probes** which are the circles store only **light info** (am i getting white raylights? yellow?)&#xD;&#xA;&#xD;&#xA;*I might be wrong, in that case correct me*&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BUlnf.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="31287" PostHistoryTypeId="2" PostId="10722" RevisionGUID="aacafbd9-786b-4f15-afb2-3e1aac04fb53" CreationDate="2021-03-11T02:45:59.883" UserId="523" Text="I have written a software rasterizer, and have encountered a (literal) edge case.&#xD;&#xA;&#xD;&#xA;At the silhouette edge of a typical object, you have two triangles—the front face and the back face.  They are not coplanar, but they of course share that single edge.  Say the pixel center / subpixel sample happens to lie very close to this edge—so close that the depth value computed for both triangles is actually *exactly*, bit-for-bit, identical.&#xD;&#xA;&#xD;&#xA;Without special handling for this case, sometimes the &quot;wrong&quot; fragment will get through.  For example, with the `&lt;` depth function, if the backface renders first, then the depth test for the frontface will fail and the backface will show through.   If the frontface renders first, then the depth test for the backface will fail and the frontface will show.  The former case produces the wrong image—sometimes quite objectionably so.&#xD;&#xA;&#xD;&#xA;I have thought about hacks to fix this like trying to handle the &quot;equals&quot; case explicitly, depending upon the depth function and whether the fragment came from a front face, but it's not clear, especially for the `≤` and `≥` depth functions, what the &quot;right&quot; answer is.  Still, it's about the only thing I can think of trying.&#xD;&#xA;&#xD;&#xA;This is basically Z-fighting, but *unlike* the usual Z-fighting graphics newbies encounter when they don't set the clipping planes right or whatever (and which makes this issue almost ungoogleable), existing hardware *definitely does* provide *some* kind of solution to handle this particular case, because this problem does *not* occur on real GPUs.&#xD;&#xA;&#xD;&#xA;So my question is—how *is* this handled by real GPUs?  If that's unanswerable, then how *can* it be handled consistently?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31288" PostHistoryTypeId="1" PostId="10722" RevisionGUID="aacafbd9-786b-4f15-afb2-3e1aac04fb53" CreationDate="2021-03-11T02:45:59.883" UserId="523" Text="Rasterization: How does hardware disambiguate identical Z values at silhouette edges?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31289" PostHistoryTypeId="3" PostId="10722" RevisionGUID="aacafbd9-786b-4f15-afb2-3e1aac04fb53" CreationDate="2021-03-11T02:45:59.883" UserId="523" Text="|rasterizer|hardware|silhouette|z-fighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31290" PostHistoryTypeId="2" PostId="10723" RevisionGUID="ada69c50-e82e-4b66-ad24-d9b03226ddca" CreationDate="2021-03-11T03:17:27.293" UserId="2654" Text="The way this is &quot;handled by real GPUs&quot; is that most models are closed. As such, surfaces facing away from the camera are definitely not closer than some other surface of that object. To prevent throwing away performance rasterizing triangles that definitely do not contribute to the final image, most users turn on backface culling.&#xD;&#xA;&#xD;&#xA;And thus, there is no problem.&#xD;&#xA;&#xD;&#xA;In the absence of backface culling, what you describe is effectively just a form of z-fighting. But note that z-fighting almost always happens very far away from the camera and/or with co-planar objects that are very close together. To achieve the circumstance you describe, the angle between the two triangles would have to be extremely small, very close to 0.0. And they have to be so far away that the depth buffer lacks sufficient precision to deal with it.&#xD;&#xA;&#xD;&#xA;So, in order for the phenomenon you describe to even be possible, you would need for all three of these to be the case:&#xD;&#xA;&#xD;&#xA;1. Turning off backface culling.&#xD;&#xA;2. Two triangles that share an edge, with the angle between those triangles being *extremely* small.&#xD;&#xA;3. The shared edge being very far away from the camera.&#xD;&#xA;&#xD;&#xA;This intersection of models and rendering state is vanishingly uncommon." ContentLicense="CC BY-SA 4.0" />
  <row Id="31294" PostHistoryTypeId="2" PostId="10725" RevisionGUID="5a2229a6-abfb-4f71-a024-f3b8148531af" CreationDate="2021-03-11T13:14:39.890" UserId="7952" Text="If you are taking about this occurring within a single draw call for a single object then you are talking about rasterization not Z fighting.  So the real question is, &quot;how are two triangles rasterized that are right next to each other&quot;. And the answer to that question boils down to rasterization rules. Which must be enforced, on GPU's that happens in hardware, for your software rasterizer you need to pick a rule set, then enforce it in code. Generically a rasterizer can leave no holes, and each pixel is only drawn once. You may want to always add colors when drawing your triangles, start with a color of zero and just add new colors drawn to that pixel, this will make your overdraw stand out like a sore thumb.&#xD;&#xA;&#xD;&#xA;The most widely know rule set for handling this is the &quot;top left rule&quot; which states: The center of every pixel must lie completely inside the triangle, (you are computing pixel centers right?) or it center lies *exactly* on a triangle edge or on multiple edges in the case of corners, and a left edge is a non-horizontal edge that is on the left side of the triangle.&#xD;&#xA;&#xD;&#xA;This last bit is directly from [Wikipedia][1]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rasterisation" ContentLicense="CC BY-SA 4.0" />
  <row Id="31295" PostHistoryTypeId="12" PostId="10723" RevisionGUID="7e9cb9ab-5f60-463c-a867-00c213504d85" CreationDate="2021-03-11T14:33:03.513" UserId="2654" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;}]}" />
  <row Id="31296" PostHistoryTypeId="13" PostId="10723" RevisionGUID="e4904b61-64ea-400c-8226-2a5a85150edb" CreationDate="2021-03-11T14:33:57.147" UserId="2654" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;}]}" />
  <row Id="31297" PostHistoryTypeId="2" PostId="10726" RevisionGUID="f288c1b0-3894-4702-be2d-dead02c7ff39" CreationDate="2021-03-11T15:00:19.243" UserId="10333" Text="If you have a shader pipeline in OpenGL that goes something like the following:&#xD;&#xA;&#xD;&#xA;    // Pseudocode&#xD;&#xA;    &#xD;&#xA;    // FragmentShader&#xD;&#xA;    // in vec3 inVertexPosition;&#xD;&#xA;    // in vec2 inTexCoords&#xD;&#xA;    // &#xD;&#xA;    // int main()&#xD;&#xA;    {&#xD;&#xA;        // Sample texture coordinate and write to fragment out&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Then you have another fragment shader that does something a little different:&#xD;&#xA;&#xD;&#xA;    // int main()&#xD;&#xA;    {&#xD;&#xA;          // Sample texture, calculate noise and mix with texture colour&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In OpenGL if you want to execute this second shader you only compile this second shader and bind to the fragment shader stage of the shader pipeline. You can then create another a different vertex shader and attach that to the vertex shader stage whenever you need it. &#xD;&#xA;&#xD;&#xA;Let's just say I have 5 vertex shaders and 5 fragment shaders, in OpenGL (because it supports separable shader objects) you only need to compile 5 x 2 = 10 shaders. However, as in Vulkan, as far as I know it doesn't support it, which means you have to compile 25 programs if you want to use each combination. &#xD;&#xA;&#xD;&#xA;Does Vulkan have the equivalent of the OpenGL separable shader objects, or are there any plans for it? They seem just so much more flexible. &#xD;&#xA;&#xD;&#xA;I've thought about being able to bind shader stages in my code, and then every combination of shader stages could be mapped to a single compiled program, however I don't think the mapping could be searched efficiently. I'm not sure. It seems being forced to compile an entirely new pipeline when inserting a shader stage is wasteful when you make many shaders. " ContentLicense="CC BY-SA 4.0" />
  <row Id="31298" PostHistoryTypeId="1" PostId="10726" RevisionGUID="f288c1b0-3894-4702-be2d-dead02c7ff39" CreationDate="2021-03-11T15:00:19.243" UserId="10333" Text="Does Vulkan have the equivalent of OpenGL's separable shader program and pipeline?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31299" PostHistoryTypeId="3" PostId="10726" RevisionGUID="f288c1b0-3894-4702-be2d-dead02c7ff39" CreationDate="2021-03-11T15:00:19.243" UserId="10333" Text="|opengl|shader|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31300" PostHistoryTypeId="5" PostId="10726" RevisionGUID="45316a3c-cd62-456f-be41-18b9b41f7eb4" CreationDate="2021-03-11T15:26:44.917" UserId="10333" Comment="added 102 characters in body" Text="If you have a shader pipeline in OpenGL that goes something like the following:&#xD;&#xA;&#xD;&#xA;    // Pseudocode&#xD;&#xA;    &#xD;&#xA;    // FragmentShader&#xD;&#xA;    // in vec3 inVertexPosition;&#xD;&#xA;    // in vec2 inTexCoords&#xD;&#xA;    // &#xD;&#xA;    // int main()&#xD;&#xA;    {&#xD;&#xA;        // Sample texture coordinate and write to fragment out&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Then you have another fragment shader that does something a little different:&#xD;&#xA;&#xD;&#xA;    // int main()&#xD;&#xA;    {&#xD;&#xA;          // Sample texture, calculate noise and mix with texture colour&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In OpenGL if you want to execute this second shader you only compile this second shader and bind to the fragment shader stage of the shader pipeline. You can then create another a different vertex shader and attach that to the vertex shader stage whenever you need it. &#xD;&#xA;&#xD;&#xA;Let's just say I have 5 vertex shaders and 5 fragment shaders, in OpenGL (because it supports separable shader objects) you only need to compile 5 x 2 = 10 shaders. However, as in Vulkan, as far as I know it doesn't support it, which means you have to compile 25 programs if you want to use each combination. &#xD;&#xA;&#xD;&#xA;Does Vulkan have the equivalent of the OpenGL separable shader objects, or are there any plans for it? They seem just so much more flexible. &#xD;&#xA;&#xD;&#xA;I've thought about being able to bind shader stages in my code, and then every combination of shader stages could be mapped to a single compiled program, however I don't think the mapping could be searched efficiently. I'm not sure. It seems being forced to compile an entirely new pipeline when inserting a shader stage is wasteful when you make many shaders. &#xD;&#xA;&#xD;&#xA;It seems in principle this is like compiling a new program every time you created a new function. " ContentLicense="CC BY-SA 4.0" />
  <row Id="31301" PostHistoryTypeId="2" PostId="10727" RevisionGUID="e8f875bc-78e8-444f-bc9b-7825d5550106" CreationDate="2021-03-11T16:06:07.710" UserId="2654" Text="&gt; Does Vulkan have the equivalent of the OpenGL separable shader objects, or are there any plans for it? They seem just so much more flexible.&#xD;&#xA;&#xD;&#xA;It would be &quot;so much more flexible&quot;. But Vulkan is a low-level rendering API. It's job is to give you access to the hardware as close to the metal as possible; user-convenience isn't even in the top-5 goals for the API.&#xD;&#xA;&#xD;&#xA;Putting all of the context state into one gigantic, immutable (more or less) object gives the implementation all the power it needs to make your code fast. Forcing implementations to deal with stitching together shaders would make implementations more complicated (and another goal of Vulkan is to be relatively easy to implement).&#xD;&#xA;&#xD;&#xA;The best way to solve this (where possible) is to just have fewer shader variations. Use uniforms/push-constants to detect what variations you want to use, then have conditionals based on them. Obviously this can't be done in every situation, but the uber-shader approach is the way to handle it to the degree possible/reasonable." ContentLicense="CC BY-SA 4.0" />
  <row Id="31302" PostHistoryTypeId="50" PostId="10301" RevisionGUID="932affcd-a362-4444-9822-e68a07c5e298" CreationDate="2021-03-11T20:03:30.327" UserId="-1" />
  <row Id="31303" PostHistoryTypeId="2" PostId="10728" RevisionGUID="485424ff-c1b2-49bf-aaaa-5ee65402b42e" CreationDate="2021-03-11T21:46:42.883" UserId="5891" Text="I want to plot the [Gaussian filter of pbrt-v4](https://github.com/mmp/pbrt-v4/blob/08418214e4df767a4e6aa95230821e05f3621da9/src/pbrt/filters.h#L80) with a radius $(100,100)$ and a standard deviation ($\sigma$) of $0.5$. &#xD;&#xA;&#xD;&#xA;I would expect something like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When I plot the pbrt-v4 Gaussian filter with radius $(100,100)$ and $\sigma=0.5$ I get:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Is the 2nd plot correct? I varied the radius form $1$ to $1000$ but the the filter size changes only 2 pixels in total (I get a similar results).&#xD;&#xA;Any ideas?&#xD;&#xA;How does the correct plot look like?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4vlMD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/amEEn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31304" PostHistoryTypeId="1" PostId="10728" RevisionGUID="485424ff-c1b2-49bf-aaaa-5ee65402b42e" CreationDate="2021-03-11T21:46:42.883" UserId="5891" Text="Plotting pbrt-v3 Gaussian filter" ContentLicense="CC BY-SA 4.0" />
  <row Id="31305" PostHistoryTypeId="3" PostId="10728" RevisionGUID="485424ff-c1b2-49bf-aaaa-5ee65402b42e" CreationDate="2021-03-11T21:46:42.883" UserId="5891" Text="|rendering|filtering|gaussian-blur|pbrt|pbrt-v3|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31306" PostHistoryTypeId="2" PostId="10729" RevisionGUID="813d6979-6b02-4e7b-9c86-feb4d921147a" CreationDate="2021-03-11T22:52:59.343" UserId="15845" Text="I'm trying to learn OpenGL in c++ (I used it in Java) but I have a problem, I make a triangle, but it doesn't draw on GL_FILL and in GL_LINE it just draw a line, I can't find my mistake, I guess my bug is in vertex buffers, but I can't detect it, can anyone help me please?&#xD;&#xA;&#xD;&#xA;CglApp.cpp:&#xD;&#xA;&#xD;&#xA;        CglApp::CglApp() {&#xD;&#xA;&#xD;&#xA;        glm::vec3 vertices[] = {&#xD;&#xA;                {0.5f,  0.5f, 0.0f} ,  // top right&#xD;&#xA;                {0.5f, -0.5f, 0.0f},  // bottom right&#xD;&#xA;                {-0.5f, -0.5f, 0.0f},  // bottom left&#xD;&#xA;                {-0.5f,  0.5f, 0.0f}   // top left&#xD;&#xA;        };&#xD;&#xA;        unsigned int indices[] = {  // note that we start from 0!&#xD;&#xA;                0, 1, 3,  // first Triangle&#xD;&#xA;                //1, 2, 3   // second Triangle&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        glm::vec3 vertices2[] = {&#xD;&#xA;                //{0.5f,  0.5f, 0.0f} ,  // top right&#xD;&#xA;                {0.5f, -0.5f, 0.0f},  // bottom right&#xD;&#xA;                {-0.5f, -0.5f, 0.0f},  // bottom left&#xD;&#xA;                {-0.5f,  0.5f, 0.0f}   // top left&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        unsigned int indices2[] = {  // note that we start from 0!&#xD;&#xA;                //0, 1, 3,  // first Triangle&#xD;&#xA;                1, 2, 3   // second Triangle&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        cglSolidModel.loadModels(vertices,indices);&#xD;&#xA;        cglSolidModel1.loadModels(vertices2,indices2);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    CglApp::~CglApp() {&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void CglApp::run() {&#xD;&#xA;&#xD;&#xA;        while (!cglWindow.shouldClose()){&#xD;&#xA;&#xD;&#xA;            // input&#xD;&#xA;            // -----&#xD;&#xA;            inputManager.processInput(cglWindow.getWindow());&#xD;&#xA;&#xD;&#xA;            // render&#xD;&#xA;            // ------&#xD;&#xA;            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;            cglSolidModel.bind(cglShaders.getDefaultShader());&#xD;&#xA;            cglSolidModel1.bind(cglShaders.getDefaultShader());&#xD;&#xA;&#xD;&#xA;            // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)&#xD;&#xA;            // -------------------------------------------------------------------------------&#xD;&#xA;            glfwSwapBuffers(cglWindow.getWindow());&#xD;&#xA;            glfwPollEvents();&#xD;&#xA;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;CglShaders.cpp&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    CglShaders::CglShaders() {&#xD;&#xA;        createDefaultShader();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    CglShaders::~CglShaders() {&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void CglShaders::createDefaultShader() {&#xD;&#xA;&#xD;&#xA;        const char *vertexShaderSource = &quot;#version 330 core\n&quot;&#xD;&#xA;                                         &quot;layout (location = 0) in vec3 aPos;\n&quot;&#xD;&#xA;                                         &quot;void main()\n&quot;&#xD;&#xA;                                         &quot;{\n&quot;&#xD;&#xA;                                         &quot;   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n&quot;&#xD;&#xA;                                         &quot;}\0&quot;;&#xD;&#xA;        const char *fragmentShaderSource = &quot;#version 330 core\n&quot;&#xD;&#xA;                                           &quot;out vec4 FragColor;\n&quot;&#xD;&#xA;                                           &quot;void main()\n&quot;&#xD;&#xA;                                           &quot;{\n&quot;&#xD;&#xA;                                           &quot;   FragColor = vec4(1.0f, 0.9f, 0.2f, 1.0f);\n&quot;&#xD;&#xA;                                           &quot;}\n\0&quot;;&#xD;&#xA;&#xD;&#xA;        createShader(vertexShaderSource,fragmentShaderSource);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void CglShaders::createShader(const char *vertexShaderSource, const char *fragmentShaderSource) {&#xD;&#xA;&#xD;&#xA;        // build and compile our shader program&#xD;&#xA;        // ------------------------------------&#xD;&#xA;        // vertex shader&#xD;&#xA;        unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;        glShaderSource(vertexShader, 1, &amp;vertexShaderSource, NULL);&#xD;&#xA;        glCompileShader(vertexShader);&#xD;&#xA;        // check for shader compile errors&#xD;&#xA;        int success;&#xD;&#xA;        char infoLog[512];&#xD;&#xA;        glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;success);&#xD;&#xA;        if (!success)&#xD;&#xA;        {&#xD;&#xA;            glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);&#xD;&#xA;            std::cout &lt;&lt; &quot;ERROR::SHADER::VERTEX::COMPILATION_FAILED\n&quot; &lt;&lt; infoLog &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;        // fragment shader&#xD;&#xA;        unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;        glShaderSource(fragmentShader, 1, &amp;fragmentShaderSource, NULL);&#xD;&#xA;        glCompileShader(fragmentShader);&#xD;&#xA;        // check for shader compile errors&#xD;&#xA;        glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;success);&#xD;&#xA;        if (!success)&#xD;&#xA;        {&#xD;&#xA;            glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);&#xD;&#xA;            std::cout &lt;&lt; &quot;ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n&quot; &lt;&lt; infoLog &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;        // link shaders&#xD;&#xA;        unsigned int shaderProgram = glCreateProgram();&#xD;&#xA;        glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;        glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;        glLinkProgram(shaderProgram);&#xD;&#xA;        // check for linking errors&#xD;&#xA;        glGetProgramiv(shaderProgram, GL_LINK_STATUS, &amp;success);&#xD;&#xA;        if (!success) {&#xD;&#xA;            glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);&#xD;&#xA;            std::cout &lt;&lt; &quot;ERROR::SHADER::PROGRAM::LINKING_FAILED\n&quot; &lt;&lt; infoLog &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;        glDeleteShader(vertexShader);&#xD;&#xA;        glDeleteShader(fragmentShader);&#xD;&#xA;&#xD;&#xA;        shaderPrograms.push_back(shaderProgram);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;CglSolidModel.cpp&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    CglSolidModel::CglSolidModel() {&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    CglSolidModel::~CglSolidModel() {&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void CglSolidModel::loadModels(glm::vec3 vertices[], unsigned int indices[]) {&#xD;&#xA;&#xD;&#xA;        glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;        glGenBuffers(1, &amp;VBO);&#xD;&#xA;        glGenBuffers(1, &amp;EBO);&#xD;&#xA;        // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).&#xD;&#xA;        glBindVertexArray(VAO);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)nullptr);&#xD;&#xA;        glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;        // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind&#xD;&#xA;        glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;        // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.&#xD;&#xA;        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);&#xD;&#xA;&#xD;&#xA;        // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other&#xD;&#xA;        // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.&#xD;&#xA;        glBindVertexArray(1);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // uncomment this call to draw in wireframe polygons.&#xD;&#xA;        //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void CglSolidModel::bind(unsigned int shaderProgram) {&#xD;&#xA;&#xD;&#xA;        // draw our first triangle&#xD;&#xA;        glUseProgram(shaderProgram);&#xD;&#xA;        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized&#xD;&#xA;        //glDrawArrays(GL_TRIANGLES, 0, 6);&#xD;&#xA;        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);&#xD;&#xA;        // glBindVertexArray(0); // no need to unbind it every time&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Im creating the VBO, EBO and VBA inside each SolidModel.&#xD;&#xA;&#xD;&#xA;[Only two lines for two different triangles with GL_LINE][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EmiYD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31307" PostHistoryTypeId="1" PostId="10729" RevisionGUID="813d6979-6b02-4e7b-9c86-feb4d921147a" CreationDate="2021-03-11T22:52:59.343" UserId="15845" Text="My OpenGL program is not drawing filled polygons" ContentLicense="CC BY-SA 4.0" />
  <row Id="31308" PostHistoryTypeId="3" PostId="10729" RevisionGUID="813d6979-6b02-4e7b-9c86-feb4d921147a" CreationDate="2021-03-11T22:52:59.343" UserId="15845" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31309" PostHistoryTypeId="2" PostId="10730" RevisionGUID="dc692b7e-7f02-4a66-99ac-a021447b2169" CreationDate="2021-03-12T07:01:05.773" UserId="3073" Text="&#xD;&#xA;A problem is see in your code is that your take the sizeof() of an unsized array, which yields the size of the POINTER to that array and not the size of array itself.&#xD;&#xA;&#xD;&#xA;    void CglSolidModel::loadModels(glm::vec3 vertices[], unsigned int indices[]) {&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a small test case that demonstrates the issue.&#xD;&#xA;&#xD;&#xA;    void func(int array[]) {&#xD;&#xA;        printf(&quot;sizeof(array) = %d\n&quot;, sizeof(array));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int myArray[10];&#xD;&#xA;    func(myArray);&#xD;&#xA;&#xD;&#xA;Output when compiled for x64:&#xD;&#xA;&#xD;&#xA;    sizeof(array) = 8  &#xD;&#xA;&#xD;&#xA;This is the size of the 64bit pointer to the array. You would expect 10*sizeof(int) = 40 but in your case it only sends 8 bytes of the vertice array to the VBO, which is less than a vertice worth of data. That goes some way to explaining why you only see 1 partial triangle.&#xD;&#xA;&#xD;&#xA;In this case it's not possible for C++ to determine the size of the array (var[] is equivalent to a pointer). &#xD;&#xA;&#xD;&#xA;I would recommend you pass another variable which contains the size of the array or use a container like std::vector which embeds the size along with the array.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31310" PostHistoryTypeId="2" PostId="10731" RevisionGUID="f88447e8-b79f-41d0-9b24-98a8c928a439" CreationDate="2021-03-12T08:59:46.673" UserId="13273" Text="I implemented the curved PN triangles algorithm described in [this][1] paper to smooth geometry in real time. After the implementation was finished (in glsl) I realized, that this algorithm smooth the geometry but there are still edges visible. To better debug I converted the program to C++ and inserted a unit cube. Important: the unit cubes faces share their vertices... so we have 8 vertices with 8 normal vectors (no flat shading). &#xD;&#xA;&#xD;&#xA;**The used obj file (cube.obj):**&#xD;&#xA;    &#xD;&#xA;    v -1 -1 -1&#xD;&#xA;    v 1 -1 -1&#xD;&#xA;    v -1 1 -1&#xD;&#xA;    v 1 1 -1&#xD;&#xA;    v -1 -1 1&#xD;&#xA;    v 1 -1 1&#xD;&#xA;    v -1 1 1&#xD;&#xA;    v 1 1 1&#xD;&#xA;    vn -1 -1 -1&#xD;&#xA;    vn 1 -1 -1&#xD;&#xA;    vn -1 1 -1&#xD;&#xA;    vn 1 1 -1&#xD;&#xA;    vn -1 -1 1&#xD;&#xA;    vn 1 -1 1&#xD;&#xA;    vn -1 1 1&#xD;&#xA;    vn 1 1 1&#xD;&#xA;    f 1//1 2//2 3//3&#xD;&#xA;    f 3//3 2//2 4//4&#xD;&#xA;    f 2//2 6//6 4//4&#xD;&#xA;    f 4//4 6//6 8//8&#xD;&#xA;    f 3//3 4//4 7//7&#xD;&#xA;    f 7//7 4//4 8//8&#xD;&#xA;    f 1//1 5//5 2//2&#xD;&#xA;    f 2//2 5//5 6//6&#xD;&#xA;    f 1//1 3//3 5//5&#xD;&#xA;    f 5//5 3//3 7//7&#xD;&#xA;    f 5//5 7//7 6//6&#xD;&#xA;    f 6//6 7//7 8//8&#xD;&#xA;&#xD;&#xA;as you can see the normal vectors (vn) are not normalized. This is no problem, because they will be normalized during filling the buffer.&#xD;&#xA;&#xD;&#xA;The following code reads the mesh file and subdivides each face with respect to the `edgeDivisionCount` variable. Here it is set to 100. That means each edge is subdivided into 100 vertices.&#xD;&#xA;&#xD;&#xA;**Code:**&#xD;&#xA;	&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;	#include &lt;vector&gt;&#xD;&#xA;	#include &lt;fstream&gt;&#xD;&#xA;	#include &lt;sstream&gt;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	#include &lt;thread&gt;&#xD;&#xA;&#xD;&#xA;	struct Vector3D&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;		Vector3D()&#xD;&#xA;		{&#xD;&#xA;			x = 0;&#xD;&#xA;			y = 0;&#xD;&#xA;			z = 0;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D(float x, float y, float z)&#xD;&#xA;		{&#xD;&#xA;			this-&gt;x = x;&#xD;&#xA;			this-&gt;y = y;&#xD;&#xA;			this-&gt;z = z;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D operator*(float scalar) const&#xD;&#xA;		{&#xD;&#xA;			return Vector3D(x * scalar, y * scalar, z * scalar);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D operator+(const Vector3D&amp; v2) const&#xD;&#xA;		{&#xD;&#xA;			return Vector3D(x + v2.x, y + v2.y, z + v2.z);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D operator-(const Vector3D&amp; v2) const&#xD;&#xA;		{&#xD;&#xA;			return Vector3D(x - v2.x, y - v2.y, z - v2.z);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D operator-() const&#xD;&#xA;		{&#xD;&#xA;			return Vector3D(-x, -y, -z);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		float dot(const Vector3D&amp; v2) const&#xD;&#xA;		{&#xD;&#xA;			return x*v2.x + y*v2.y + z*v2.z;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		float length() const&#xD;&#xA;		{&#xD;&#xA;			return sqrt(x*x + y*y + z*z);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		Vector3D normalize() const&#xD;&#xA;		{&#xD;&#xA;			float l = length();&#xD;&#xA;			return Vector3D(x / l, y / l, z / l);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		float x;&#xD;&#xA;		float y;&#xD;&#xA;		float z;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	void saveOBJ(std::string file, std::vector&lt;Vector3D&gt;* vertices, std::vector&lt;std::tuple&lt;int, int, int&gt;&gt;* faces)&#xD;&#xA;	{&#xD;&#xA;		std::ofstream myfile;&#xD;&#xA;		myfile.open(file);	&#xD;&#xA;		if (vertices != nullptr)&#xD;&#xA;		{&#xD;&#xA;			for (std::vector&lt;Vector3D&gt;::iterator it = vertices-&gt;begin(); it != vertices-&gt;end(); ++it)&#xD;&#xA;			{&#xD;&#xA;				myfile &lt;&lt; &quot;v &quot; &lt;&lt; it-&gt;x &lt;&lt; &quot; &quot; &lt;&lt; it-&gt;y &lt;&lt; &quot; &quot; &lt;&lt; it-&gt;z &lt;&lt; &quot;\n&quot;;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (faces != nullptr)&#xD;&#xA;		{&#xD;&#xA;			for (std::vector&lt;std::tuple&lt;int, int, int&gt;&gt;::iterator it = faces-&gt;begin(); it != faces-&gt;end(); ++it)&#xD;&#xA;			{&#xD;&#xA;				myfile &lt;&lt; &quot;f &quot; &lt;&lt; std::get&lt;0&gt;(*it) + 1 &lt;&lt; &quot; &quot; &lt;&lt; std::get&lt;1&gt;(*it) + 1 &lt;&lt; &quot; &quot; &lt;&lt; std::get&lt;2&gt;(*it) + 1 &lt;&lt; &quot;\n&quot;;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		myfile.close();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	Vector3D curvedPNVertex(Vector3D b300, Vector3D b030, Vector3D b003, Vector3D n200, Vector3D n020, Vector3D n002, Vector3D b210, Vector3D b120, Vector3D b021, Vector3D b012, Vector3D b102, Vector3D b201, Vector3D b111, float scalar0, float scalar1, float scalar2)&#xD;&#xA;	{&#xD;&#xA;		float u = scalar1;&#xD;&#xA;		float v = scalar2;&#xD;&#xA;		float w = scalar0;&#xD;&#xA;		float u2 = pow(u,2);&#xD;&#xA;		float v2 = pow(v,2);&#xD;&#xA;		float w2 = pow(w,2);&#xD;&#xA;		float u3 = pow(u,3);&#xD;&#xA;		float v3 = pow(v,3);&#xD;&#xA;		float w3 = pow(w,3);&#xD;&#xA;&#xD;&#xA;		return b003*v3 + b102*3*w*v2 + b012*3*u*v2 + b201*3*w2*v + b111*6*w*u*v + b021*3*u2*v + b300*w3 + b210*3*w2*u + b120*3*w*u2 + b030*u3;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	std::vector&lt;Vector3D&gt; curvedPNTriangle(int divisionCount, Vector3D v0, Vector3D v1, Vector3D v2, Vector3D n0, Vector3D n1, Vector3D n2)&#xD;&#xA;	{&#xD;&#xA;		std::vector&lt;Vector3D&gt; result;&#xD;&#xA;&#xD;&#xA;		Vector3D b300 = v0;&#xD;&#xA;		Vector3D b030 = v1;&#xD;&#xA;		Vector3D b003 = v2;&#xD;&#xA;&#xD;&#xA;		Vector3D n200 = n0.normalize();&#xD;&#xA;		Vector3D n020 = n1.normalize();&#xD;&#xA;		Vector3D n002 = n2.normalize();&#xD;&#xA;&#xD;&#xA;		Vector3D b210 = (b300 * 2.0f + b030 - (n200 * (b030 - b300).dot(n200))) * (1.0f / 3.0f);&#xD;&#xA;		Vector3D b120 = (b030 * 2.0f + b300 - (n020 * (b300 - b030).dot(n020))) * (1.0f / 3.0f);&#xD;&#xA;		Vector3D b021 = (b030 * 2.0f + b003 - (n020 * (b003 - b030).dot(n020))) * (1.0f / 3.0f);&#xD;&#xA;		Vector3D b012 = (b003 * 2.0f + b030 - (n002 * (b030 - b003).dot(n002))) * (1.0f / 3.0f);&#xD;&#xA;		Vector3D b102 = (b003 * 2.0f + b300 - (n002 * (b300 - b003).dot(n002))) * (1.0f / 3.0f);&#xD;&#xA;		Vector3D b201 = (b300 * 2.0f + b003 - (n200 * (b003 - b300).dot(n200))) * (1.0f / 3.0f);&#xD;&#xA;		Vector3D e = (b210+b120+b201+b102+b012+b021) * (1.0f / 6.0f);&#xD;&#xA;		Vector3D b111 = e + (e - (b300+b030+b003) * (1.0f / 3.0f)) * (1.0f / 2.0f);&#xD;&#xA;&#xD;&#xA;		//divide triangle face&#xD;&#xA;		for (unsigned int i = 0; i &lt; divisionCount; ++i)&#xD;&#xA;		{&#xD;&#xA;			for (unsigned int j = 0; j &lt; divisionCount - i; ++j)&#xD;&#xA;			{&#xD;&#xA;				float scalar1 = static_cast&lt;float&gt;(i) / divisionCount;&#xD;&#xA;				float scalar0 = static_cast&lt;float&gt;(j) / divisionCount;&#xD;&#xA;				float scalar2 = 1 - (scalar0 + scalar1);&#xD;&#xA;				Vector3D vertex = curvedPNVertex(b300, b030, b003, n200, n020, n002, b210, b120, b021, b012, b102, b201, b111, scalar0, scalar1, scalar2);&#xD;&#xA;				result.push_back(vertex);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return result;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	std::vector&lt;int&gt; getIntOutOfString(std::string text)&#xD;&#xA;	{&#xD;&#xA;		std::vector&lt;int&gt; result;&#xD;&#xA;&#xD;&#xA;		std::string subtext = &quot;&quot;;&#xD;&#xA;		for (unsigned int i = 0; i &lt; text.size(); ++i)&#xD;&#xA;		{&#xD;&#xA;			if ((text.at(i) &gt;= '0' &amp;&amp; text.at(i) &lt;= '9'))&#xD;&#xA;			{&#xD;&#xA;				subtext += text.at(i);&#xD;&#xA;			}&#xD;&#xA;			else if (subtext.size() == 0 &amp;&amp; text.at(i) == '-')&#xD;&#xA;			{&#xD;&#xA;				subtext += text.at(i);&#xD;&#xA;			}&#xD;&#xA;			else if (subtext.size() &gt; 0)&#xD;&#xA;			{&#xD;&#xA;				//end of a int reached! Save int into list!&#xD;&#xA;				result.push_back(std::stoi(subtext));&#xD;&#xA;				subtext = &quot;&quot;;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (subtext != &quot;&quot;)&#xD;&#xA;		{&#xD;&#xA;			result.push_back(std::stoi(subtext));&#xD;&#xA;		}&#xD;&#xA;		return result;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	std::vector&lt;double&gt; getDoublesOutOfString(std::string text)&#xD;&#xA;	{&#xD;&#xA;		std::vector&lt;double&gt; result;&#xD;&#xA;&#xD;&#xA;		std::string subtext = &quot;&quot;;&#xD;&#xA;		for (unsigned int i = 0; i &lt; text.size(); ++i)&#xD;&#xA;		{&#xD;&#xA;			if ((text.at(i) &gt;= '0' &amp;&amp; text.at(i) &lt;= '9') || text.at(i) == '.')&#xD;&#xA;			{&#xD;&#xA;				subtext += text.at(i);&#xD;&#xA;			}&#xD;&#xA;			else if (subtext.size() == 0 &amp;&amp; text.at(i) == '-')&#xD;&#xA;			{&#xD;&#xA;				subtext += text.at(i);&#xD;&#xA;			}&#xD;&#xA;			else if (subtext.size() &gt; 0)&#xD;&#xA;			{&#xD;&#xA;				//end of a double reached! Save double into list!&#xD;&#xA;				result.push_back(std::stod(subtext));&#xD;&#xA;				subtext = &quot;&quot;;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		if (subtext != &quot;&quot;)&#xD;&#xA;		{&#xD;&#xA;			result.push_back(std::stod(subtext));&#xD;&#xA;		}&#xD;&#xA;		return result;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	bool readOBJ(std::string file, std::vector&lt;Vector3D&gt;* positions, std::vector&lt;Vector3D&gt;* normals, std::vector&lt;std::tuple&lt;int, int, int, int, int, int&gt;&gt;* faces)&#xD;&#xA;	{&#xD;&#xA;		std::string line;&#xD;&#xA;		std::ifstream myfile(file);&#xD;&#xA;		if (myfile.is_open())&#xD;&#xA;		{&#xD;&#xA;			while (std::getline(myfile, line))&#xD;&#xA;			{&#xD;&#xA;				if (line.size() &gt; 1)&#xD;&#xA;				{&#xD;&#xA;					if (line[0] == 'v' &amp;&amp; line[1] == ' ')&#xD;&#xA;					{&#xD;&#xA;						std::vector&lt;double&gt; vertexValues = getDoublesOutOfString(line);&#xD;&#xA;						if (vertexValues.size() == 3)&#xD;&#xA;						{&#xD;&#xA;							Vector3D position = Vector3D(vertexValues[0], vertexValues[1], vertexValues[2]);&#xD;&#xA;							positions-&gt;push_back(position);&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;					if (line[0] == 'v' &amp;&amp; line[1] == 'n')&#xD;&#xA;					{&#xD;&#xA;						std::vector&lt;double&gt; vertexValues = getDoublesOutOfString(line);&#xD;&#xA;						if (vertexValues.size() == 3)&#xD;&#xA;						{&#xD;&#xA;							Vector3D normal = Vector3D(vertexValues[0], vertexValues[1], vertexValues[2]).normalize();&#xD;&#xA;							normals-&gt;push_back(normal);&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;					if (line[0] == 'f' &amp;&amp; line[1] == ' ')&#xD;&#xA;					{&#xD;&#xA;						std::vector&lt;int&gt; faceValues = getIntOutOfString(line);&#xD;&#xA;						if (faceValues.size() == 6)&#xD;&#xA;						{&#xD;&#xA;							std::tuple&lt;int, int, int, int, int, int &gt; face = std::tuple&lt;int, int, int, int, int, int&gt;(faceValues[0], faceValues[1], faceValues[2], faceValues[3], faceValues[4], faceValues[5]);&#xD;&#xA;							faces-&gt;push_back(face);&#xD;&#xA;						}&#xD;&#xA;						else if (faceValues.size() == 9)&#xD;&#xA;						{&#xD;&#xA;							std::tuple&lt;int, int, int, int, int, int &gt; face = std::tuple&lt;int, int, int, int, int, int&gt;(faceValues[0], faceValues[2], faceValues[3], faceValues[5], faceValues[6], faceValues[8]);&#xD;&#xA;							faces-&gt;push_back(face);&#xD;&#xA;						}&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			myfile.close();&#xD;&#xA;			return true;&#xD;&#xA;		}&#xD;&#xA;		return false;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		std::vector&lt;Vector3D&gt; positions;&#xD;&#xA;		std::vector&lt;Vector3D&gt; normals;&#xD;&#xA;		std::vector&lt;std::tuple&lt;int, int, int, int, int, int&gt;&gt; faces;&#xD;&#xA;	&#xD;&#xA;		readOBJ(&quot;meshes/cube.obj&quot;, &amp;positions, &amp;normals, &amp;faces);&#xD;&#xA;&#xD;&#xA;		std::vector&lt;Vector3D&gt; curvedResult;&#xD;&#xA;		int edgeDivisionCount = 100;&#xD;&#xA;		for (std::vector&lt;std::tuple&lt;int, int, int, int, int, int&gt;&gt;::iterator it = faces.begin(); it != faces.end(); ++it)&#xD;&#xA;		{&#xD;&#xA;			std::vector&lt;Vector3D&gt; triangleResult = curvedPNTriangle(edgeDivisionCount, positions[std::get&lt;0&gt;(*it) - 1], positions[std::get&lt;2&gt;(*it) - 1], positions[std::get&lt;4&gt;(*it) - 1], normals[std::get&lt;1&gt;(*it) - 1], normals[std::get&lt;3&gt;(*it) - 1], normals[std::get&lt;5&gt;(*it) - 1]);&#xD;&#xA;			for (std::vector&lt;Vector3D&gt;::iterator itVertex = triangleResult.begin(); itVertex != triangleResult.end(); ++itVertex)&#xD;&#xA;			{&#xD;&#xA;				curvedResult.push_back(*itVertex);&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		saveOBJ(&quot;meshes/cubeCurved.obj&quot;, &amp;curvedResult, nullptr);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;Okay, so lets see the results:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This discontinuity of the neighboring normal directions of the faces need to be avoided. Now I am not sure, if this is an implementation mistake on my side, or is the curved PN-triangles algorithm the wrong choice to solve my problem. I thought this algorithm would avoid these effects because the results in figure 1 of the [paper][1] don't show any of these effects.&#xD;&#xA;&#xD;&#xA;In case of correct implementation I would like to ask which algorithm would be a better choice for me?&#xD;&#xA;&#xD;&#xA;My requirements are:&#xD;&#xA;&#xD;&#xA; 1. real time (it must be fast! Calculation per frame)&#xD;&#xA; 2. the algorithm must be able to calculate the result within one step (only one shader call need to be enough)&#xD;&#xA; 3. supports calculation of normal vectors per vertex (I am not interested in an algorithm which don't deliver the correct normal vector)&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://alex.vlachos.com/graphics/CurvedPNTriangles.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/XO1rw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31311" PostHistoryTypeId="1" PostId="10731" RevisionGUID="f88447e8-b79f-41d0-9b24-98a8c928a439" CreationDate="2021-03-12T08:59:46.673" UserId="13273" Text="results of Curved PN-Triangles algorithm has visible edges" ContentLicense="CC BY-SA 4.0" />
  <row Id="31312" PostHistoryTypeId="3" PostId="10731" RevisionGUID="f88447e8-b79f-41d0-9b24-98a8c928a439" CreationDate="2021-03-12T08:59:46.673" UserId="13273" Text="|algorithm|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31313" PostHistoryTypeId="5" PostId="10730" RevisionGUID="0dd7dd58-8589-4ecf-862d-9feb5d800382" CreationDate="2021-03-12T09:06:41.357" UserId="3073" Comment="added 279 characters in body" Text="&#xD;&#xA;A problem is see in your code is that your take the sizeof() of an unsized array, which yields the size of the POINTER to that array and not the size of array itself.&#xD;&#xA;&#xD;&#xA;    void CglSolidModel::loadModels(glm::vec3 vertices[], unsigned int indices[]) {&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a small test case that demonstrates the issue.&#xD;&#xA;&#xD;&#xA;    void func(int array[]) {&#xD;&#xA;        printf(&quot;sizeof(array) = %d\n&quot;, sizeof(array));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int myArray[10];&#xD;&#xA;    func(myArray);&#xD;&#xA;&#xD;&#xA;Output when compiled for x64:&#xD;&#xA;&#xD;&#xA;    sizeof(array) = 8  &#xD;&#xA;&#xD;&#xA;This is the size of the 64bit pointer to the array. You would expect 10*sizeof(int) = 40. In your code (assuming x64) it only sends 8 bytes of the vertice array to the VBO, which comes to 1 &quot;NDC&quot; space vertex. That goes some way to explaining why you only see 1 partial triangle, I would guess the other vertices in the triangle where at 0 or some other random uninitialised VRAM value.&#xD;&#xA;&#xD;&#xA;It's not possible for C++ to determine the size of an unsized array. In C++ `int array[];` is equivalent to `const int *array;` and so `sizeof(array)` is the same in both cases. This isn't the case for sized arrays, `int array[10];` would give you 40 bytes as you would expect. &#xD;&#xA;&#xD;&#xA;I would recommend you pass another parameter which contains the size of the array or use a container like std::vector which stores the size along with the array.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31314" PostHistoryTypeId="5" PostId="10730" RevisionGUID="4cb6afc4-cbcb-4dfa-8e58-3ceb040a3230" CreationDate="2021-03-12T09:12:23.427" UserId="3073" Comment="added 279 characters in body" Text="&#xD;&#xA;A problem is see in your code is that your take the sizeof() of an unsized array, which yields the size of the POINTER to that array and not the size of array itself.&#xD;&#xA;&#xD;&#xA;    void CglSolidModel::loadModels(glm::vec3 vertices[], unsigned int indices[]) {&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a small test case that demonstrates the issue.&#xD;&#xA;&#xD;&#xA;    void func(int array[]) {&#xD;&#xA;        printf(&quot;sizeof(array) = %d\n&quot;, sizeof(array));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int myArray[10];&#xD;&#xA;    func(myArray);&#xD;&#xA;&#xD;&#xA;Output when compiled for x64:&#xD;&#xA;&#xD;&#xA;    sizeof(array) = 8  &#xD;&#xA;&#xD;&#xA;This is the size of the 64bit pointer to the array. You would expect 10*sizeof(int) = 40. In your code (assuming x64) it only sends 8 bytes of the vertice array to the VBO, which is enough to fill the XY coordinates for the first vertex. That goes some way to explaining why you only see 1 partial triangle.&#xD;&#xA;&#xD;&#xA;It's not possible for C++ to determine the size of an unsized array. In C++ `int array[];` is equivalent to `const int *array;` and so `sizeof(array)` is the same in both cases. This isn't the case for sized arrays, `int array[10];` would give you 40 bytes as you would expect. &#xD;&#xA;&#xD;&#xA;I would recommend you pass another parameter which contains the size of the array or use a container like std::vector which stores the size along with the array. Be aware that std::vector returns the number of elements and not the number of bytes which glBufferData expects.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31315" PostHistoryTypeId="5" PostId="10730" RevisionGUID="10fc10fd-b7a7-4641-8e61-df341bdae807" CreationDate="2021-03-12T10:04:53.037" UserId="3073" Comment="formatting and spelling" Text="&#xD;&#xA;A problem I see in your code is that you take the `sizeof()` an unsized array, which yields the size of the *pointer* to that array and not the size of array itself.&#xD;&#xA;&#xD;&#xA;    void CglSolidModel::loadModels(glm::vec3 vertices[], unsigned int indices[]) {&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a small test case that demonstrates the issue.&#xD;&#xA;&#xD;&#xA;    void func(int array[]) {&#xD;&#xA;        printf(&quot;sizeof(array) = %d\n&quot;, sizeof(array));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int myArray[10];&#xD;&#xA;    func(myArray);&#xD;&#xA;&#xD;&#xA;Output when compiled for x64:&#xD;&#xA;&#xD;&#xA;    sizeof(array) = 8  &#xD;&#xA;&#xD;&#xA;This is the size of the 64bit pointer to the array. You would expect 10*sizeof(int) = 40. In your code (assuming x64) it only sends 8 bytes of the vertice array to the VBO, which is enough to fill the XY coordinates for the first vertex. That goes some way to explaining why you only see 1 partial triangle.&#xD;&#xA;&#xD;&#xA;It's not possible for C++ to determine the size of an unsized array. In C++ `int array[];` is equivalent to `const int *array;` and so `sizeof(array)` is the same in both cases. This isn't the case for sized arrays, `int array[10];` would give you 40 bytes as you would expect. &#xD;&#xA;&#xD;&#xA;I would recommend you pass another parameter which contains the size of the array or use a container like `std::vector` which stores the size along with the array. Be aware that `std::vector` returns the number of elements and not the number of bytes which `glBufferData` expects.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31316" PostHistoryTypeId="2" PostId="10732" RevisionGUID="db6fecd3-ca2d-4a51-a4f7-022ef2bd88c7" CreationDate="2021-03-12T11:52:09.783" UserId="7724" Text="As mentioned in the paper PN-triangles are only $C^0$ smooth with respect to adjacent triangles (although they are $G^1$ at vertices). This means that a PN triangle mesh is continuous in position, but are discontinuous in tangent plane and thus in the neighbouring normals on the shared edge of two adjacent triangles. The reason that the surface appears smooth in Figure 1 of the paper is because an additional fake normal field is used (see section 2.1 of the paper). This normal field is continuous and gives the illusion of a smooth surface. &#xD;&#xA;&#xD;&#xA;I can point you to a few techniques that might satisfy your requirements&#xD;&#xA;&#xD;&#xA; 1. [Triangular Gregory patches][1], here the patches will become $G^1$ or tangent plane continous. It able to be implemented in real-time (using for instance tessellation shaders), but it can be quite hard to wrap your head around the Chiyokura-Kimura technique of joining two patches smoothly. The Gregory patch is a triangular B\'ezier patch where certain control points are blended between two positions using a rational function. The normal could be analytically determined, but due to the rational functions it becomes hard to take derivatives.&#xD;&#xA; 2. [Quadratic Approximation of Subdivision surfaces][2]. This technique is able to be implemented in realtime. Although it does not interpolate normal vectors at vertices, it gives smoother results than PN-triangles. It tries to approximate a Loop-subdivision surface with quadratic B\'ezier patches.&#xD;&#xA;3. [PNG1 triangles][3] Comparable to Gregory patches, but in this case a lot of control points are allowed to shift position. I would advise against implementing this technique as it is very complicated and does not give better results than the standard Gregory patch.&#xD;&#xA;4. [Loop subdivision][4], you can pair PN-triangles with several iterations of Loop subdivision to pre-smooth your mesh. The sharp edges of the triangles will become less and less apparent, but at the cost of increased work to do the subdivision.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www2.eecs.berkeley.edu/Pubs/TechRpts/1987/CSD-87-313.pdf&#xD;&#xA;  [2]: https://hal.inria.fr/inria-00260834/document&#xD;&#xA;  [3]: https://graphicsinterface.org/proceedings/gi2008/gi2008-28/&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Loop_subdivision_surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="31317" PostHistoryTypeId="2" PostId="10733" RevisionGUID="75113e2d-f870-45e7-b7f0-cc2c361151d3" CreationDate="2021-03-12T17:47:41.650" UserId="13179" Text="My question follows directly [this one](https://gamedev.stackexchange.com/questions/59758/microfacet-model-brdf-obtain-extreme-values-at-grazing-angles?noredirect=1&amp;lq=1).&#xD;&#xA;&#xD;&#xA;Reading the famous [paper](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf) of Walter, it comes that the plotted curves of figure 13 (in question in the related topic) are not directly the brdf but rather the brdf times the cosines of the reflected angle.&#xD;&#xA;&#xD;&#xA;Because the divergence at grazing angle (shown in the related post) is due to the division by the cosines of the reflected angle (commun to all microfacets models), I wonder if this is always the case ?&#xD;&#xA;&#xD;&#xA;Is there microfacet models with a well shaped brdf lobe at grazing angle ?&#xD;&#xA;&#xD;&#xA;Do you know references on this topic ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31318" PostHistoryTypeId="1" PostId="10733" RevisionGUID="75113e2d-f870-45e7-b7f0-cc2c361151d3" CreationDate="2021-03-12T17:47:41.650" UserId="13179" Text="Do all microfacet brdf models diverge at grazing angle?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31319" PostHistoryTypeId="3" PostId="10733" RevisionGUID="75113e2d-f870-45e7-b7f0-cc2c361151d3" CreationDate="2021-03-12T17:47:41.650" UserId="13179" Text="|brdf|microfacet|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31320" PostHistoryTypeId="2" PostId="10734" RevisionGUID="afde0600-078c-42fe-8ff2-e13e57edb857" CreationDate="2021-03-12T18:13:02.840" UserId="48" Text="On current GPU architectures, at the machine level, compilation of a shader program can depend on which other pipeline stages are active, what the inputs/outputs to those shaders are, as well as what the inputs and outputs of the overall pipeline are (vertex inputs and fragment outputs, for example). There's a lot of complicated architectural reasons why this can be true, for instance that some &quot;builtin&quot; inputs to the FS might actually need to be generated by an earlier stage, that VSes might need to output values differently depending on whether they're going to the FS or to a GS or tessellation shaders, etc.&#xD;&#xA;&#xD;&#xA;In OpenGL, the driver is doing a lot of work under the hood to take care of these details. From your perspective, you may be only compiling 5 VS and 5 FS and using them in different combinations, but the driver is very likely actually compiling distinct programs (transparently to you) for every combination of VS/FS you use, and moreover also sometimes compiling distinct programs based on other OpenGL state that you wouldn't think was part of the shader at all.&#xD;&#xA;&#xD;&#xA;With Vulkan, one of the major design goals of the API is to make the driver less &quot;smart&quot; and &quot;magic&quot;, and move a lot of the driver's responsibilities into the app. This was done because OpenGL drivers became increasingly complex and opaque over time, and often caused performance issues that were unpredictable or burdensome to app developers—such as needing to suddenly compile new shaders in the background when a draw call was issued with a not-before-seen combination of shaders and state, causing stalls. The thinking is that by giving the app visibility into and control over such things, it can better manage how shader compilation work is done (e.g. compiling all needed combinations up front, compiling things on a background thread and not stalling rendering, etc). This philosophy extends to many other aspects of the API, such as memory management, command buffers, resource binding, synchronization between CPU and GPU, etc.&#xD;&#xA;&#xD;&#xA;So, rather than thinking about it like &quot;Vulkan is inconvenient and wasteful&quot; I would suggest taking the attitude that &quot;Vulkan makes clearer how much work is actually needed to set things up properly for the GPU, and gives me the control over how that work is done.&quot;&#xD;&#xA;&#xD;&#xA;BTW,&#xD;&#xA;&#xD;&#xA;&gt; I've thought about being able to bind shader stages in my code, and then every combination of shader stages could be mapped to a single compiled program, however I don't think the mapping could be searched efficiently.&#xD;&#xA;&#xD;&#xA;This sort of thing can totally be done with a hash table; you just have to make a key struct that includes pointers to (or another identifier for) the individual VSes/FSes. But then you have to solve the same problem as the OpenGL driver had to solve, which is that you have to stop and create a new pipeline every time a new combination of VS/FS is seen, and that can result in stalls. It's better, if possible, to pre-create all the combinations you're going to need up front.&#xD;&#xA;&#xD;&#xA;FWIW, in practice, I think in most applications you don't actually create a lot of combinations of different VSes and FSes. Most rendering engines only have a single VS, or a small handful of VSes, for each FS, so there's not usually going to be a huge combinatoric explosion of different combinations." ContentLicense="CC BY-SA 4.0" />
  <row Id="31321" PostHistoryTypeId="2" PostId="10735" RevisionGUID="c5d426c2-f7a7-42d3-8773-ea2070ee5de7" CreationDate="2021-03-12T19:53:16.763" UserId="48" Text="You probably want to set sigma to be a fraction of the radius, rather than a fixed value. Sigma controls the actual shape of the filter, while radius just controls how far out the filter gets cut off (as Gaussians truly have infinite radius, so we have to cut them off somewhere to use them in practice). With sigma set to 0.5, you're making a filter that's very sharply peaked within a radius of 0.5 pixels, which is consistent with the image you're getting.&#xD;&#xA;&#xD;&#xA;Instead, try setting sigma = 0.25 or 0.3 times the radius. Or alternatively, make sigma your main parameter and then set the radius to 3 or 4 times sigma." ContentLicense="CC BY-SA 4.0" />
  <row Id="31322" PostHistoryTypeId="5" PostId="10734" RevisionGUID="ab57985d-c123-4ee6-885a-d2fcdd730fe9" CreationDate="2021-03-12T22:49:45.060" UserId="48" Comment="added 3 characters in body" Text="On current GPU architectures, at the machine level, compilation of a shader program can depend on which other pipeline stages are active, what the inputs/outputs to those shaders are, as well as what the inputs and outputs of the overall pipeline are (vertex inputs and fragment outputs, for example). There's a lot of complicated architectural reasons why this can be true, for instance that some &quot;builtin&quot; inputs to the FS might actually need to be generated by an earlier stage, that VSes might need to output values differently depending on whether they're going to the FS or to a GS or tessellation shaders, etc.&#xD;&#xA;&#xD;&#xA;In OpenGL, the driver is doing a lot of work under the hood to take care of these details. From your perspective, you may be only compiling 5 VS and 5 FS and using them in different combinations, but the driver is very likely actually compiling distinct programs (transparently to you) for every combination of VS/FS you use, and moreover also sometimes compiling distinct programs based on other OpenGL state that you wouldn't think was part of the shader at all.&#xD;&#xA;&#xD;&#xA;With Vulkan, one of the major design goals of the API is to make the driver less &quot;smart&quot; and &quot;magic&quot;, and move a lot of the driver's responsibilities into the app. This was done because OpenGL drivers became increasingly complex and opaque over time, and often caused performance issues that were unpredictable or burdensome to app developers—such as needing to suddenly compile new shaders in the background when a draw call was issued with a not-before-seen combination of shaders and state, causing stalls. The thinking is that by giving the app visibility into and control over such things, it can better manage how shader compilation work is done (e.g. compiling all needed combinations up front, compiling things on a background thread and not stalling rendering, etc). This philosophy extends to many other aspects of the API, such as memory management, command buffers, resource binding, synchronization between CPU and GPU, etc.&#xD;&#xA;&#xD;&#xA;So, rather than thinking about it like &quot;Vulkan is inconvenient and wasteful&quot; I would try to see it more like &quot;Vulkan makes clearer how much work is actually needed to set things up properly for the GPU, and gives me the control over how that work is done.&quot;&#xD;&#xA;&#xD;&#xA;BTW,&#xD;&#xA;&#xD;&#xA;&gt; I've thought about being able to bind shader stages in my code, and then every combination of shader stages could be mapped to a single compiled program, however I don't think the mapping could be searched efficiently.&#xD;&#xA;&#xD;&#xA;This sort of thing can totally be done with a hash table; you just have to make a key struct that includes pointers to (or another identifier for) the individual VSes/FSes. But then you have to solve the same problem as the OpenGL driver had to solve, which is that you have to stop and create a new pipeline every time a new combination of VS/FS is seen, and that can result in stalls. It's better, if possible, to pre-create all the combinations you're going to need up front.&#xD;&#xA;&#xD;&#xA;FWIW, in practice, I think in most applications you don't actually create a lot of combinations of different VSes and FSes. Most rendering engines only have a single VS for each FS (or a small handful of VSes for each FS), so there's not usually going to be a huge combinatoric explosion of different combinations." ContentLicense="CC BY-SA 4.0" />
  <row Id="31323" PostHistoryTypeId="5" PostId="10733" RevisionGUID="2cf6c74f-828a-482e-9835-0218f15e0aff" CreationDate="2021-03-13T09:29:31.697" UserId="13179" Comment="edited body" Text="My question follows directly [this one](https://gamedev.stackexchange.com/questions/59758/microfacet-model-brdf-obtain-extreme-values-at-grazing-angles?noredirect=1&amp;lq=1).&#xD;&#xA;&#xD;&#xA;Reading the famous [paper](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf) of Walter, it comes that the plotted curves of figure 13 (in question in the related topic) are not directly the brdf but rather the brdf times the cosines of the reflected angle.&#xD;&#xA;&#xD;&#xA;Because the divergence at grazing angle (shown in the related post) is due to the division by the cosines of the reflected angle (common to all microfacets models), I wonder if this is always the case ?&#xD;&#xA;&#xD;&#xA;Is there microfacet models with a well shaped brdf lobe at grazing angle ?&#xD;&#xA;&#xD;&#xA;Do you know references on this topic ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31325" PostHistoryTypeId="2" PostId="10736" RevisionGUID="9f8b8f91-0175-4f3e-9823-0eebe8640a4b" CreationDate="2021-03-13T22:46:05.087" UserId="15920" Text="I am attempting to use a compute shader to calculate joint transforms for animations.&#xD;&#xA;&#xD;&#xA;I use a loop to calculate the global joint transforms from the local transforms. Relevant code below: &#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;layout(set = 0, binding = 2) readonly buffer LocalTransforms {&#xD;&#xA;    Similarity local_transforms[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(set = 0, binding = 3) buffer GlobalTransforms {&#xD;&#xA;    mat4 global_transforms[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct NodeAndParent {&#xD;&#xA;    uint node_index;&#xD;&#xA;    int parent_index;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(set = 0, binding = 4) readonly buffer DepthFirstNodes {&#xD;&#xA;    NodeAndParent depth_first_nodes[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    uint index = gl_GlobalInvocationID.x;&#xD;&#xA;&#xD;&#xA;    uint nodes_offset = index * num_nodes;&#xD;&#xA;&#xD;&#xA;    if (nodes_offset &gt;= global_transforms.length()) {&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    for (uint i = 0; i &lt; num_nodes; i++) {&#xD;&#xA;        NodeAndParent indices = depth_first_nodes[i];&#xD;&#xA;&#xD;&#xA;        uint node_index = nodes_offset + indices.node_index;&#xD;&#xA;        mat4 local_transform = similarity_to_mat4(local_transforms[node_index]);&#xD;&#xA;&#xD;&#xA;        if (indices.parent_index != -1) {&#xD;&#xA;            mat4 parent_transform = global_transforms[nodes_offset + indices.parent_index];&#xD;&#xA;            global_transforms[node_index] = parent_transform * local_transform;&#xD;&#xA;        } else {&#xD;&#xA;            global_transforms[node_index] = local_transform;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;There is a bug somewhere and I have been attempting to use renderdoc to debug it. I have realised that on the first iteration, one matrix is written to index 3 of of the buffer (right side image), but when it is read back as the parent transform on the second iteration (left image), the values reported in renderdoc are incorrect.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Note that the section of the buffer is not being used by any other thread, and I have an early-exit for threads that would be out-of-bounds of `global_transforms`. I've tested other threads and they all return early.&#xD;&#xA;&#xD;&#xA;My question is this:&#xD;&#xA;* A) Is it possibly that renderdoc is reporting this incorrectly?&#xD;&#xA;* B) Is the value stored in the buffer really like that in that point in time? Would using a barrier help? What kind of barrier?&#xD;&#xA;* C) Is there some other problem with the code that could be causing this?&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ktkNY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31326" PostHistoryTypeId="1" PostId="10736" RevisionGUID="9f8b8f91-0175-4f3e-9823-0eebe8640a4b" CreationDate="2021-03-13T22:46:05.087" UserId="15920" Text="Mat4 that is written to a storage buffer in a compute shader has an altered value when read back" ContentLicense="CC BY-SA 4.0" />
  <row Id="31327" PostHistoryTypeId="3" PostId="10736" RevisionGUID="9f8b8f91-0175-4f3e-9823-0eebe8640a4b" CreationDate="2021-03-13T22:46:05.087" UserId="15920" Text="|glsl|vulkan|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31328" PostHistoryTypeId="2" PostId="10737" RevisionGUID="e04a734e-4fff-4003-8304-ccf781aa55d3" CreationDate="2021-03-13T23:44:14.813" UserId="15920" Text="It appears that this is indeed a bug within renderdoc. I have encountered the bug I was debugging for in only 1 model, while all the others work fine. In every instance of using the renderdoc debugger, I get the same problem though." ContentLicense="CC BY-SA 4.0" />
  <row Id="31329" PostHistoryTypeId="2" PostId="10738" RevisionGUID="3db76e4f-e9e7-43cc-a26e-fd3fd1a91cbf" CreationDate="2021-03-14T13:36:32.607" UserId="15705" Text="What I want is a function like `imageStore`, but instead of replacing a value - applying a blend operation to it, e.g. addition. It is not possible to do something like this with atomics due to them only operating on 32bit integers. &#xD;&#xA;&#xD;&#xA;If there is no such function, why have noone made an extension for this yet? It seems rather useful for compute shader lighting, and some post-processing effects." ContentLicense="CC BY-SA 4.0" />
  <row Id="31330" PostHistoryTypeId="1" PostId="10738" RevisionGUID="3db76e4f-e9e7-43cc-a26e-fd3fd1a91cbf" CreationDate="2021-03-14T13:36:32.607" UserId="15705" Text="Is there an efficient way to achieve color blending in compute shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31331" PostHistoryTypeId="3" PostId="10738" RevisionGUID="3db76e4f-e9e7-43cc-a26e-fd3fd1a91cbf" CreationDate="2021-03-14T13:36:32.607" UserId="15705" Text="|opengl|glsl|vulkan|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31332" PostHistoryTypeId="2" PostId="10739" RevisionGUID="c65fcbd3-99bc-426a-9237-394934c9d59b" CreationDate="2021-03-14T13:39:21.030" UserId="15922" Text="I need something to be cleared up for me, and I hope this is the right place to ask my question:&#xD;&#xA;&#xD;&#xA;I intend to attempt stochastic transparency, where I will draw glass panes and smoke particles onto the g-buffer for deferred shading.&#xD;&#xA;For every 2x2 cell of pixels, I will allow up to 3 of the 4 pixels to be used for glass or smoke. The last pixel is always the opaque background. But say we have this situation:&#xD;&#xA;&#xD;&#xA;- Camera&#xD;&#xA;- (Near clip plane)&#xD;&#xA;- Smoke particle&#xD;&#xA;- Glass pane&#xD;&#xA;- Solid wall&#xD;&#xA;- (Far clip plane)&#xD;&#xA;&#xD;&#xA;The smoke particle is in front of the glass pane, and would occupy all 3 pixels. This I do not want, and therefore I will need to check whether neighbouring pixels in that 2x2 cell already have 'smoke' or 'glass' written to them, rather than just the simple Z-check.&#xD;&#xA;&#xD;&#xA;I therefore wish to sample neighbouring pixels from the same g-buffer that I'm currently writing to, but this seems not possible, am I right? And why do the depth &amp; stencil buffers seem to be exceptions to this, or does this have something to do with only reading the exact pixel you are about to write to?&#xD;&#xA;&#xD;&#xA;I hope the way I formulated the question(s) make sense, and is sufficiently detailed." ContentLicense="CC BY-SA 4.0" />
  <row Id="31333" PostHistoryTypeId="1" PostId="10739" RevisionGUID="c65fcbd3-99bc-426a-9237-394934c9d59b" CreationDate="2021-03-14T13:39:21.030" UserId="15922" Text="Reading neighbouring pixels during object draw call" ContentLicense="CC BY-SA 4.0" />
  <row Id="31334" PostHistoryTypeId="3" PostId="10739" RevisionGUID="c65fcbd3-99bc-426a-9237-394934c9d59b" CreationDate="2021-03-14T13:39:21.030" UserId="15922" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31335" PostHistoryTypeId="2" PostId="10740" RevisionGUID="9d2e46ef-e9ed-4391-83cc-0c63178d0b5e" CreationDate="2021-03-14T14:16:36.297" UserId="2654" Text="&gt; If there is no such function, why have noone made an extension for this yet?&#xD;&#xA;&#xD;&#xA;Just because something might be &quot;useful&quot; doesn't mean it would be possible or cheap.&#xD;&#xA;&#xD;&#xA;GPU hardware achieves blending by using an *entirely separate* piece of hardware, one that preserves the order of the fragment values generated by unordered fragment shader executions. These [execution units, commonly called &quot;ROPs&quot;](https://en.wikipedia.org/wiki/Render_output_unit), are distinct hardware from fragment shaders.&#xD;&#xA;&#xD;&#xA;CS's can't just do that. They have a fundamentally unordered execution model, and what you're talking about requires at least some ordering between them. That's not simple or cheap to implement, even if it's *possible* at all.&#xD;&#xA;&#xD;&#xA;The closest you can get to that is [fragment_shader_interlock][1], which can force parts of FS execution to be ordered by primitive order and to execute critical sections that prevent overlapping executions. But as the name suggests, that's a feature of fragment shaders (and not one universally supported), not a feature of compute shaders.&#xD;&#xA;&#xD;&#xA;Also, it doesn't really make sense to use a compute shader for post-processing effects, since FS's are perfectly capable of dealing with that sort of thing, and actually have access to ROPs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_fragment_shader_interlock.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="31336" PostHistoryTypeId="2" PostId="10741" RevisionGUID="5b404c40-483f-4267-b4d4-838e95cbbdc8" CreationDate="2021-03-14T17:59:20.273" UserId="48" Text="You can always just do an image load, apply whatever math you want to the value, and then store it back out. This only works if you can ensure multiple CS invocations aren't trying to modify the same pixel—otherwise you get a race condition—but that limitation is fine for most lighting and postprocessing applications, where you're running a single CS dispatch across a whole framebuffer (or some tiles within a framebuffer), with one invocation per pixel." ContentLicense="CC BY-SA 4.0" />
  <row Id="31337" PostHistoryTypeId="2" PostId="10742" RevisionGUID="3539381b-de24-48c0-9e2d-1c1cf44f1153" CreationDate="2021-03-14T18:34:22.383" UserId="48" Text="In general you can't safely read from neighboring pixels in the render target you're currently writing to. You can sample from them, but there's no guarantees about how other pixels are scheduled on the GPU, so it's a race condition—you might get the neighboring pixel value either before or after modification, and it might change frame to frame due to unpredictable scheduling differences.&#xD;&#xA;&#xD;&#xA;You can read from the same pixel you're about to write to, but only if your geometry is set up to ensure that nothing is overlapping in screen space (e.g. a full-screen pass). If other triangles in the same render pass are overlapping the same area on screen, then you have a race condition again, similar to the neighboring-pixels case. (You can use fragment_shader_interlock or equivalent functionality to address this case, but it is not universally supported across all GPU vendors, and it can also be slow.)&#xD;&#xA;&#xD;&#xA;The depth and stencil buffers, as well as fixed-function blending (additive, alpha, etc) can get around this because they have special-purpose hardware that sorts the fragments in submission order in order to apply those simple fixed operations.&#xD;&#xA;&#xD;&#xA;I believe the way stochastic transparency usually works is to randomize the set of pixels output and use spatial/temporal filtering to clean up the noise afterward. So you wouldn't have such fine-grained control like &quot;within each 2x2 block, there will be N pixels of this, and M pixels of that&quot;. It would be more probablistic, like &quot;on average, X% of the pixels will be this, and Y% of the pixels will be that&quot;, with the exact outputs being randomly chosen each frame." ContentLicense="CC BY-SA 4.0" />
  <row Id="31338" PostHistoryTypeId="2" PostId="10743" RevisionGUID="b9828dbf-b7db-48c0-b426-21555eb45bf3" CreationDate="2021-03-14T23:09:50.293" UserId="15926" Text="In short words, VBO is an array of raw data, when VAO is an array of ATTRIBUTES - an instruction for shader program how to use the data.&#xD;&#xA;&#xD;&#xA;Before, in OpenGL ES 2.0 for example, VAO wasn't introduced yet at all and VBO was optional. You still could pass to your shader your data RAM addresses. Still this data had to pass CPU-to-GPU &quot;bridge&quot; on each call, but this process wasn't exposed to you. VBO allows to keep data on GPU side, which saves transfer time, you just need to know VBO's id.&#xD;&#xA;&#xD;&#xA;But VBO by itself is not enough. You have to instruct GPU how to use it. You have to define &quot;Vertex Attribute Pointers&quot; (command glVertexAttribPointer) for each attribute (input data variable) of your shader. Before VAO you had to define attributes for each glDrawArrays call (it's a lot), in every frame (like 30+ times per second). VAO allows to attach an entire array of attributes by just VAO's id. So, when VBO is relatively independent, the VAO is VBO+shader-specific.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31339" PostHistoryTypeId="2" PostId="10744" RevisionGUID="7900aafc-6a48-4f76-bf73-34a4c3205a64" CreationDate="2021-03-15T06:34:12.310" UserId="15207" Text="I have been told their is no performance difference if you are skilled enough when it comes to gpu computing . And cuda only performs better because nvidia wants it to. I have also read graphic api's compute shaders are not as good as opencl/cuda. I don't understand how are compute shader different from Cuda/opencl and why would they be slow(If they are). I wanted it know this because opencl is difficult to understand and setup for me. Will their be a performance hit on using opengl copute shader and will vulkan compute shader perform better than opengl's.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="31340" PostHistoryTypeId="1" PostId="10744" RevisionGUID="7900aafc-6a48-4f76-bf73-34a4c3205a64" CreationDate="2021-03-15T06:34:12.310" UserId="15207" Text="Performance difference in Opengl compute shader vs Vulkan Compute Shader vs Cuda/opencl and others" ContentLicense="CC BY-SA 4.0" />
  <row Id="31341" PostHistoryTypeId="3" PostId="10744" RevisionGUID="7900aafc-6a48-4f76-bf73-34a4c3205a64" CreationDate="2021-03-15T06:34:12.310" UserId="15207" Text="|opengl|compute-shader|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31342" PostHistoryTypeId="2" PostId="10745" RevisionGUID="75b7664b-bd66-49ad-8b6c-cd70c4a459d2" CreationDate="2021-03-15T16:50:22.037" UserId="506" Text="In general, you should not see significant performance differences running identical compute shaders via one API vs. another; in the end they’re running the same instructions on the same hardware. It’s possible for vendor-provided toolkits like CUDA or [MetalPerformanceShaders](https://developer.apple.com/documentation/metalperformanceshaders) to have more efficient implementations of a given algorithm on that vendor’s hardware than a more generic version of the algorithm, because they’ve been designed and tuned for the strengths of that hardware, but there’s nothing in principle that would prevent you from developing the same efficiencies on your own with enough optimization work.&#xD;&#xA;&#xD;&#xA;Long story short: work with whichever API you find easiest to use, and invest some time in learning how to profile and tune your code for the hardware you plan to run it on." ContentLicense="CC BY-SA 4.0" />
  <row Id="31343" PostHistoryTypeId="50" PostId="9048" RevisionGUID="78a54534-3aeb-4c9a-98ad-6f27a614f53b" CreationDate="2021-03-15T19:02:25.283" UserId="-1" />
  <row Id="31344" PostHistoryTypeId="5" PostId="8913" RevisionGUID="9f8c51b0-145f-48e2-97c0-24c19b35c4a7" CreationDate="2021-03-15T19:43:57.083" UserId="10771" Comment="added 6 characters in body" Text="As we know, tiles can make it quicker to update large portions of the display at once, as compared with a bitmap. To put, say a letter, on the screen, the Commodore 64 typically does two writes (the screencode and the attribute), but the ZX Spectrum typically does 9 (eight bytes which make up an 8x8 bitmap, plus 1 for the attribute).&#xD;&#xA;&#xD;&#xA;Recently, a demo for the SEGA Genesis was released called Red Eyes. My understanding is that the 3D scenes were rendered on a PC, and some kind of program converted these animations to a tileset so that each frame can quickly be written into VRAM. &#xD;&#xA;&#xD;&#xA;But, however hard I search I cannot find any contemporaneous games for these retro systems which use a tileset to render (an approximation of) three-dimensional graphics. So is there a technical reason for that?&#xD;&#xA;&#xD;&#xA;I am asking because of a game I'm trying to write for the Commodore 64. My choice of platform has meant that the compute budget really is quite miserly, so of course I need to cut down on the amount of time spent pushing pixels to the framebuffer, and tile-based graphics are an obvious solution to that problem on this platform. Also I need to keep in mind the amount of time spent in 3D projection, and I believe this problem can also be solved with tile graphics, since for example a raycaster could cast one ray tile instead of one ray per pixel. But I'm unsure about that.&#xD;&#xA;&#xD;&#xA;So the camera in my game is restricted to movement in one plane in the same way that the camera in DOOM is. It pans left and right only, and moves forward and sometimes backward. Plus I know that the walls in my game always are East-West or North-South. No diagonal walls. I think that this will mean that a manageably small number of pre-computed tiles will be enough to show the walls at various angles depending on how the camera is positioned. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;The nature of this question is such that it could be answered in the following ways:&#xD;&#xA;&#xD;&#xA; * It wouldn't work because ...&#xD;&#xA; * You obviously weren't looking hard enough because here's an example of a game that does that. Here's a disassembly or source code so you can figure out how it worked&#xD;&#xA; * It might be possible, but you'd have to watch out for ...&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31345" PostHistoryTypeId="5" PostId="4811" RevisionGUID="7a6fa524-92e1-4369-9846-0038ed46962d" CreationDate="2021-03-15T20:20:27.937" UserId="2479" Comment="better variable naming" Text="It's not that hard. If you have just planar or angular light sources, you can think of them as one light source split into multiple chunks and the only thing to deal with is how to sample this multi-light and how to compute the PDF of the resulting samples.&#xD;&#xA;&#xD;&#xA;Picking probability&#xD;&#xA;---------------------&#xD;&#xA;&#xD;&#xA;First, you need to setup the picking probability $P(l)$ for each light source $l$. The picking probabilities can be any non-negative numbers, you just have to make sure that are always non-zero if the contributions of the respective lights are non-zero. However, the closer the probabilities are to the actual (relative) light contribution, the better the overall performance of your Monte Carlo estimator will be.&#xD;&#xA;&#xD;&#xA;Contribution estimates may be:&#xD;&#xA;&#xD;&#xA; - $1$: naive, uniform probability; good to start with; used by PBRT&#xD;&#xA; - $power$: better&#xD;&#xA; - $power / distance^2$: even better; closer light sources have greater contributions&#xD;&#xA; - &amp;hellip;and other improvements: make zero if not visible at all, multiply by the cosine of the inclination angle, etc.&#xD;&#xA;&#xD;&#xA;Note that to get the light-picking probabilities, you need to normalise the contribution estimates to the sum of all of them:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;P(l)=&#xD;&#xA;  \frac&#xD;&#xA;    {ContribEst_l}&#xD;&#xA;    {\sum_{a\in\mathrm{Lights}}&#xD;&#xA;      {ContribEst_a}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;You could even use more different picking strategies if you find they work just for certain type of scenes and combine them using multiple importance sampling technique&amp;hellip;&#xD;&#xA;&#xD;&#xA;Sampling&#xD;&#xA;--------&#xD;&#xA;&#xD;&#xA;When sampling the lights, you just select one light $l$ with the appropriate probability $P(l)$ and then sample the light surface/angle with its own sampling strategy (with PDF $p_l$). The resulting PDF $p$ will be:&#xD;&#xA;$$&#xD;&#xA;p(x)=P(l) * p_l(x)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Evaluating PDF&#xD;&#xA;--------------&#xD;&#xA;&#xD;&#xA;When computing the light sampling PDF for given direction (as needed for multiple importance sampling), you just find the light source at the direction, evaluate the PDF of the lights own strategy and, again, multiply it by the probability of picking this particular light.&#xD;&#xA;&#xD;&#xA;Conclusion&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Now you have a sampling strategy which gives you PDF which can be used in the Monte Carlo estimators (e.g. $f(x)/p(x)$) and the resulting estimator will be unbiased." ContentLicense="CC BY-SA 4.0" />
  <row Id="31346" PostHistoryTypeId="2" PostId="10746" RevisionGUID="a646c29a-ad15-4652-aab8-ad4b9a31c4e6" CreationDate="2021-03-16T13:59:28.137" UserId="209" Text="This is not really an answer to the latter parts of your question but more to address&#xD;&#xA;&gt; As we know, tiles can make it quicker to update large portions of the display at once, as compared with a bitmap. To put, say a letter, on the screen, the Commodore 64 typically does two writes (the screencode and the attribute)&#xD;&#xA;&#xD;&#xA;What you are effectively describing is a compressed framebuffer where you are directly writing/storing compressed data and letting the display pipeline decompress on the fly. &#xD;&#xA;&#xD;&#xA;I would say that such things &quot;still exist&quot; in today's games/hardware, but not perhaps in form you are expecting.&#xD;&#xA;&#xD;&#xA;1) Compressed frame buffers do still exist. Mobile devices certainly do (for example Imagination/PowerVR have [PVRIC][1], and I believe ARM devices have their own scheme)&#xD;&#xA;These compression schemes are generally &quot;transparent&quot; to the programmer, but it does mean the GPU and display pipeline does less reading and writing of external memory.&#xD;&#xA;&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;2) A display decompression system like PCG  (Programmable Character Generator) is effectively a precursor to (and effectively a subset of) some texture compression schemes, e.g. such as S3TC/DXT1. In that sense, therefore it still exists, but users don't typically write directly to them, but certainly take advantage of the bandwidth savings.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.imgtec.com/blog/reducing-bandwidth-pvric/" ContentLicense="CC BY-SA 4.0" />
  <row Id="31347" PostHistoryTypeId="5" PostId="8504" RevisionGUID="542795c2-bd67-4f85-8c15-f0a2d4153ee5" CreationDate="2021-03-16T19:28:58.373" UserId="9881" Comment="added 16 characters in body" Text="GPU friendly - full formulas&#xD;&#xA;-&#xD;&#xA;&#xD;&#xA;**IDEA**: lets find position of center of each pixel $P_{ij}$ which allows us to easily find ray which starts at $E$ and go thought that pixel. To do it we find first $P_{1m}$ and find others by move on vievports plane.&#xD;&#xA;&#xD;&#xA;**ASSUMPTION**: Below we introduce formulas which includes distance $d$ between eye and viewport however this value will be reduced during ray $r_{ij}$ normalization (so you might as well accept that $d=1$ and remove it from calculations).&#xD;&#xA;&#xD;&#xA;**PRECALCULATIONS**: First we calculate normalized vectors $v_n, b_n$ from picutre (which are parallel to viewport plane and give as direction for shifting)&#xD;&#xA;&#xD;&#xA;$$t = T-E, \qquad b = w\times t  $$&#xD;&#xA;&#xD;&#xA;$$ &#xD;&#xA;t_n = \frac{t}{||t||}, \qquad&#xD;&#xA;b_n = \frac{b}{||b||}, \qquad&#xD;&#xA;v_n = t_n\times b_n \\ &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;notice: $C=E+t_nd$, then we calculate viewport size divided by 2 and including aspect ratio $\frac{m}{k}$&#xD;&#xA;&#xD;&#xA;$$g_x=\frac{h_x}{2} =d \tan \frac{\theta}{2}, \qquad  g_y =\frac{h_y}{2} = g_x \frac{m}{k}$$&#xD;&#xA;&#xD;&#xA;and then we calculate shifting vectors $q_x,q_y$ on viewport $x,y$ direction and viewport left upper pixel&#xD;&#xA;&#xD;&#xA;$$ q_x = \frac{2g_x}{k-1}b_n, \qquad&#xD;&#xA;q_y = \frac{2g_y}{m-1}v_n, \qquad&#xD;&#xA;p_{1m} = t_n d - g_xb_n - g_yv_n$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**CALCULATIONS**: notice that $P_{ij} = E + p_{ij}$ and ray $R_{ij} = P_{ij} -E = p_{ij}$ so normalized ray $r_{ij}$ is &#xD;&#xA;&#xD;&#xA;$$ p_{ij} = p_{1m} + q_x(i-1) + q_y(j-1)$$&#xD;&#xA;$$ r_{ij} = \frac{p_{ij}}{||p_{ij}||} $$&#xD;&#xA;&#xD;&#xA;**TEST**: above formulas wast tested [HERE][1] (works in browser)&#xD;&#xA;&#xD;&#xA;**SUMMARY**: The above form is convenient to use it in shaders where in shader kernel we perform only final calculation based on prcarculated $q_x,q_y$ and $p_{1m}$. Wiki [here][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://kamil-kielczewski.github.io/fractals/mandelbulb.html&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Ray_tracing_(graphics)#Calculate_rays_for_rectangular_viewport" ContentLicense="CC BY-SA 4.0" />
  <row Id="31348" PostHistoryTypeId="2" PostId="10747" RevisionGUID="d04f4c61-7538-4e3e-b6d2-78f07cd56e85" CreationDate="2021-03-16T19:53:30.773" UserId="2654" Text="&gt; But, however hard I search I cannot find any contemporaneous games for these retro systems which use a tileset to render (an approximation of) three-dimensional graphics. So is there a technical reason for that?&#xD;&#xA;&#xD;&#xA;That all depends on your definition of &quot;an approximation of&quot;. Games that use pre-rendered sprites were hardly unheard-of in the 16-bit era. You could consider that &quot;an approximation of&quot; 3D graphics.&#xD;&#xA;&#xD;&#xA;Would you consider a game like [Marble Madness][1] to be &quot;an approximation of&quot; 3D graphics? It doesn't render polygons, but it is polygonal in aesthetics. And it is 3D-ish. What of a game like [Captain Skyhawk][2], which uses a similar polygonal backdrop and is even more 3D-ish?&#xD;&#xA;&#xD;&#xA;But a first-person kind of game like what you're trying to describe is a different beast. Those games just use tiles to generate a background that appears polygonal, a static background at that. You want to do real 3D.&#xD;&#xA;&#xD;&#xA;The SNES was capable of Doom because the SNES had enough video RAM for the CPU to basically use the tile data as the framebuffer. And it had a CPU fast enough to compute the pixels for that tile framebuffer every frame or so. That is also what the example you gave is doing: the PPU of the Genesis was just being given a bunch of tile bitmaps (generated externally and therefore can be fast), and they formed a single image.&#xD;&#xA;&#xD;&#xA;It's just building a framebuffer, chopping it up into tile-sized blocks, and shoving that into a graphics chip designed to render tiles. It's not that impressive, is it? It's just a matter of having enough tile memory to give each location on the screen a separate tile.&#xD;&#xA;&#xD;&#xA;Attempts have been made to do Doom on the C64, but they were only successful by giving it a faster CPU. It's simply not feasible to do the kind of thing you're trying. Not generally at any rate.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Marble_Madness&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=ZONUS-iFf18" ContentLicense="CC BY-SA 4.0" />
  <row Id="31349" PostHistoryTypeId="50" PostId="5520" RevisionGUID="e04e5588-b118-4451-9731-6a8ee02fcae3" CreationDate="2021-03-16T20:01:20.150" UserId="-1" />
  <row Id="31350" PostHistoryTypeId="50" PostId="10666" RevisionGUID="8a36ab11-9de0-427e-89e0-f0803c5c36e4" CreationDate="2021-03-16T21:01:10.117" UserId="-1" />
  <row Id="31351" PostHistoryTypeId="5" PostId="10560" RevisionGUID="eaf675d7-b0ed-4467-ab79-84595947a570" CreationDate="2021-03-17T07:31:26.260" UserId="5778" Comment="typos corrected" Text="Humans don't really see  anything beyond 20-25 fps. Even less is often sufficient; animation at 12 frames a second work quite well too. So when you watch TV, the fps of your image is 25-30, and yet you don't generally accuse of them being not smooth.&#xD;&#xA;&#xD;&#xA;Why do games require more? Well, because they are fast paced. There is generally a slight benefit from going to 30 to 60. But mainly it comes down to:&#xD;&#xA;&#xD;&#xA;* Games do not generally have temporal antialiasing, aka motion blur; it's expensive.&#xD;&#xA;* The game simulation is locked to the rendering loop so that your input reactions now have a higher rate of feedback (wetware is not digital, reflexes do react faster)" ContentLicense="CC BY-SA 4.0" />
  <row Id="31352" PostHistoryTypeId="24" PostId="10560" RevisionGUID="eaf675d7-b0ed-4467-ab79-84595947a570" CreationDate="2021-03-17T07:31:26.260" Comment="Proposed by 5778 approved by 13095 edit id of 556" ContentLicense="CC BY-SA 4.0" />
  <row Id="31354" PostHistoryTypeId="2" PostId="10748" RevisionGUID="44a47247-cf6d-400d-91dc-0735f5bae99c" CreationDate="2021-03-17T14:02:03.690" UserId="10928" Text="I don't understand how OpenGL performs the blending of a texture on the screen. By default, the clear color is set to (0, 0, 0, 0). If we use the default blending equation GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA, it means that if our texture is all (1, 0, 0, 0.3), the resulting RGB will be (1, 0, 0)×0.3 + (0, 0, 0)×0.7 = (0.3, 0, 0) BUT the alpha component will be 0.3×0.3 + 0×(1 - 0.3) = 0.3, so we then have a color of (0.3, 0, 0, 0.09) which is not correct, what we want to see on the screen is rather (0.3, 0, 0, 1).&#xD;&#xA;&#xD;&#xA;So how does OpenGL manages the final blending with the framebuffer? Does it drop the alpha component (because the screen can only display RGB colors)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31355" PostHistoryTypeId="1" PostId="10748" RevisionGUID="44a47247-cf6d-400d-91dc-0735f5bae99c" CreationDate="2021-03-17T14:02:03.690" UserId="10928" Text="OpenGL blending with the screen" ContentLicense="CC BY-SA 4.0" />
  <row Id="31356" PostHistoryTypeId="3" PostId="10748" RevisionGUID="44a47247-cf6d-400d-91dc-0735f5bae99c" CreationDate="2021-03-17T14:02:03.690" UserId="10928" Text="|opengl|blending|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31357" PostHistoryTypeId="2" PostId="10749" RevisionGUID="bba38f55-9cfa-4c0f-8462-759086d4c60d" CreationDate="2021-03-17T15:08:15.953" UserId="2654" Text="&gt; BUT the alpha component will be 0.3×0.3 + 0×(1 - 0.3) = 0.3, so we then have a color of (0.3, 0, 0, 0.09) which is not correct, what we want to see on the screen is rather (0.3, 0, 0, 1).&#xD;&#xA;&#xD;&#xA;Your blending function did not use the destination alpha. So &quot;correct&quot; or &quot;not correct&quot;, its value is entirely *irrelevant*.&#xD;&#xA;&#xD;&#xA;However, if you want to make the alpha more accurate in some way, you can provide a [different set of blending factors][1], and even a [different blend equation][2], for the alpha component.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Blending#Blending_Parameters&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Blending#Blend_Equations" ContentLicense="CC BY-SA 4.0" />
  <row Id="31358" PostHistoryTypeId="2" PostId="10750" RevisionGUID="53a87d05-d80a-4acf-bdb1-87a91690f5b8" CreationDate="2021-03-17T21:58:35.687" UserId="11058" Text="If we have a quad that is non-planar. Why do most 3d modeling packages choose to use a single normal for the quad ([by using cross product of two edges vectors that do not share a vertex](https://blender.stackexchange.com/questions/47656/how-does-blender-implement-flat-shading-non-planar-polygons), [like this](https://math.stackexchange.com/questions/3049969/calculate-surface-normal-and-area-for-a-non-planar-quadrilateral)). Instead of viewing it as two triangles, and using a separate normal for each triangle?&#xD;&#xA;&#xD;&#xA;Normally we calculate a vertex normal as the normalized average of all polygons the vertex is part of. If we have a quad consisting of two triangles, then the two vertices that are part of both triangles, get the average of the two triangle normals. This results in smooth shading across the non-planar quad. Instead of the uniform shading we would get if we were to use a single normal for the whole quad.&#xD;&#xA;&#xD;&#xA;This also extends to polygons in general. In 3d modeling sofware a single normal is calculated for the whole polygon (with Newell's method), instead of individual normals for each triangle it consists of.&#xD;&#xA;&#xD;&#xA;To build on top of this, if we have a mesh with flat shading, each polygon gets a single normal as described above. Flat shading means that the shared vertices are split. And each vertex gets the normal of the polygons it's part of. However what happens if we want to apply a smooth shading on the mesh? Are the vertex normals calculated as average of all *polygons* it is part of? This doesn't seem right. Do we instead triangulate the mesh, and calculate the vertices as the average of all triangles it's part of?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31359" PostHistoryTypeId="1" PostId="10750" RevisionGUID="53a87d05-d80a-4acf-bdb1-87a91690f5b8" CreationDate="2021-03-17T21:58:35.687" UserId="11058" Text="Why do 3d modeling packages use a single normal for a polygon instead of a separate normal for each triangle it consists of" ContentLicense="CC BY-SA 4.0" />
  <row Id="31360" PostHistoryTypeId="3" PostId="10750" RevisionGUID="53a87d05-d80a-4acf-bdb1-87a91690f5b8" CreationDate="2021-03-17T21:58:35.687" UserId="11058" Text="|shading|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31361" PostHistoryTypeId="5" PostId="10750" RevisionGUID="faeff738-46cb-4fcf-94ba-94b1833b43ef" CreationDate="2021-03-17T22:20:20.083" UserId="11058" Comment="added 33 characters in body; edited title" Text="If we have a quad that is non-planar. Why do most 3d modeling packages choose to use a single normal for the quad (Specifically for Blender3d [by using cross product of two edges vectors that do not share a vertex](https://blender.stackexchange.com/questions/47656/how-does-blender-implement-flat-shading-non-planar-polygons), [here's the math](https://math.stackexchange.com/questions/3049969/calculate-surface-normal-and-area-for-a-non-planar-quadrilateral)). Instead of viewing it as two triangles, and using a separate normal for each triangle?&#xD;&#xA;&#xD;&#xA;Normally we calculate a vertex normal as the normalized average of all polygons the vertex is part of. If we have a quad consisting of two triangles, then the two vertices that are part of both triangles, get the average of the two triangle normals. This results in smooth shading across the non-planar quad. Instead of the uniform shading we would get if we were to use a single normal for the whole quad.&#xD;&#xA;&#xD;&#xA;This also extends to polygons in general. In 3d modeling sofware a single normal is calculated for the whole polygon (for Blender3d with Newell's method), instead of individual normals for each triangle it consists of.&#xD;&#xA;&#xD;&#xA;To build on top of this, if we have a mesh with flat shading, each polygon gets a single normal as described above. Flat shading means that the shared vertices are split. And each vertex gets the normal of the polygons it's part of. However what happens if we want to apply a smooth shading on the mesh? Are the vertex normals calculated as average of all *polygons* it is part of? This doesn't seem right. Do we instead triangulate the mesh, and calculate the vertices as the average of all triangles it's part of?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31362" PostHistoryTypeId="4" PostId="10750" RevisionGUID="faeff738-46cb-4fcf-94ba-94b1833b43ef" CreationDate="2021-03-17T22:20:20.083" UserId="11058" Comment="added 33 characters in body; edited title" Text="Why do 3d modeling packages use a single normal per polygon and how is this viable for smooth shading" ContentLicense="CC BY-SA 4.0" />
  <row Id="31363" PostHistoryTypeId="5" PostId="10750" RevisionGUID="6ae1ca6c-edf8-4293-9983-ee5f59ed423a" CreationDate="2021-03-17T22:26:37.323" UserId="11058" Comment="added 2 characters in body" Text="If we have a quad that is non-planar. Why do most 3d modeling packages choose to use a single normal for the quad (Specifically for Blender3d [by using cross product of two edges vectors that do not share a vertex](https://blender.stackexchange.com/questions/47656/how-does-blender-implement-flat-shading-non-planar-polygons), [here's the math](https://math.stackexchange.com/questions/3049969/calculate-surface-normal-and-area-for-a-non-planar-quadrilateral)). Instead of viewing it as two triangles, and using a separate normal for each triangle?&#xD;&#xA;&#xD;&#xA;Normally we calculate a vertex normal as the normalized average of all polygons the vertex is part of. If we have a quad consisting of two triangles, then the two vertices that are part of both triangles, get the average of the two triangle normals. This results in smooth shading across the non-planar quad. Instead of the uniform shading we would get if we were to use a single normal for the whole quad.&#xD;&#xA;&#xD;&#xA;This also extends to polygons in general. In 3d modeling sofware a single normal is calculated for the whole polygon (for Blender3d with Newell's method), instead of individual normals for each triangle it consists of.&#xD;&#xA;&#xD;&#xA;To build on top of this, if we have a mesh with flat shading, each polygon gets a single normal as described above. Flat shading means that the shared vertices are split. And each vertex gets the normal of the polygons it's part of. However what happens if we want to apply a smooth shading on the mesh? Are the vertex normals calculated as average of all *polygons* it is part of? This doesn't seem right. Do we instead *triangulate the mesh*, and calculate the vertices as the average of all triangles it's part of?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31364" PostHistoryTypeId="5" PostId="10750" RevisionGUID="6238c530-edc4-45cc-b6a4-5494e27ffe56" CreationDate="2021-03-17T22:41:12.533" UserId="11058" Comment="added 113 characters in body" Text="If we have a quad that is non-planar. Why do most 3d modeling packages choose to use a single normal for the quad (Specifically for Blender3d [by using cross product of two edge's vectors that do not share a vertex](https://blender.stackexchange.com/questions/47656/how-does-blender-implement-flat-shading-non-planar-polygons), [here's the math](https://math.stackexchange.com/questions/3049969/calculate-surface-normal-and-area-for-a-non-planar-quadrilateral)). Instead of viewing it as two triangles, and using a separate normal for each triangle?&#xD;&#xA;&#xD;&#xA;Normally we calculate a vertex normal as the normalized average of all polygons the vertex is part of. If we have a quad consisting of two triangles, then the two vertices that are part of both triangles, get the average of the two triangle normals. This results in smooth shading across the non-planar quad. Instead of the uniform shading we would get if we were to use a single normal for the whole quad.&#xD;&#xA;&#xD;&#xA;This also extends to polygons in general. In 3d modeling sofware a single normal is calculated for the whole polygon (for Blender3d [with Newell's method](https://blender.stackexchange.com/questions/47656/how-does-blender-implement-flat-shading-non-planar-polygons)), instead of individual normals for each triangle it consists of.&#xD;&#xA;&#xD;&#xA;To build on top of this, if we have a mesh with flat shading, each polygon gets a single normal as described above. Flat shading means that the shared vertices are split. And each vertex gets the normal of the polygons it's part of. However what happens if we want to apply a smooth shading on the mesh? Are the vertex normals calculated as average of all *polygons* it is part of? This doesn't seem right. Do we instead *triangulate the mesh*, and calculate the vertices as the average of all triangles it's part of?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31365" PostHistoryTypeId="2" PostId="10751" RevisionGUID="a1f9545c-9fd0-4633-a606-53049120c4db" CreationDate="2021-03-18T01:19:06.740" UserId="2654" Text="I think the problem comes from this starting assumption:&#xD;&#xA;&#xD;&#xA;&gt; If we have a quad that is non-planar.&#xD;&#xA;&#xD;&#xA;A non-planar quad *does not have* a normal. It's not a flat surface, so you can't talk about what its normal would be. You can't talk about the normal of a sphere, a cone, or any other non-flat surface. You can talk about what the normal might be at any particular point on that surface, but there is no normal for the surface in its entirety.&#xD;&#xA;&#xD;&#xA;You are asking a question for which there is no correct answer. But there are many incorrect answers, and they're all *equally* wrong. So there's no reason to pick one wrong answer over another.&#xD;&#xA;&#xD;&#xA;If you're talking about computing vertex normals, a non-planar quad is still not a valid surface. The two triangulations for a non-planar quad represent *very* different surfaces, which would have very different vertex normals. Neither answer can claim legitimacy over the other, so both answers are equally wrong.&#xD;&#xA;&#xD;&#xA;So why choose that particular method? Because it's no more wrong than any other method you might pick.&#xD;&#xA;&#xD;&#xA;It does not make sense to talk about the vertex or face normals for non-planar polygons. So if you want an answer that makes sense, fix *that* problem first." ContentLicense="CC BY-SA 4.0" />
  <row Id="31366" PostHistoryTypeId="2" PostId="10752" RevisionGUID="f107d0b5-50e0-4f3b-890b-e44f772e068e" CreationDate="2021-03-18T15:42:46.173" UserId="11058" Text="If I have a mesh consisting of polygons that are not necessarily triangles and not necessarily planar. As answered in the previous [question](https://computergraphics.stackexchange.com/questions/10750/why-do-3d-modeling-packages-use-a-single-normal-per-polygon-and-how-is-this-viab/10751?noredirect=1#comment16864_10751) I asked, there's no correct answer to calculating normals for such polygons. So I'm wondering instead no matter how wrong, what are some of the strategies used in 3d modeling to calculate the vertex normals for such a mesh, *specifically for smooth shading*? " ContentLicense="CC BY-SA 4.0" />
  <row Id="31367" PostHistoryTypeId="1" PostId="10752" RevisionGUID="f107d0b5-50e0-4f3b-890b-e44f772e068e" CreationDate="2021-03-18T15:42:46.173" UserId="11058" Text="Popular approaches to calculate vertex normals on a mesh with non-planar polygons" ContentLicense="CC BY-SA 4.0" />
  <row Id="31368" PostHistoryTypeId="3" PostId="10752" RevisionGUID="f107d0b5-50e0-4f3b-890b-e44f772e068e" CreationDate="2021-03-18T15:42:46.173" UserId="11058" Text="|shading|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31369" PostHistoryTypeId="2" PostId="10753" RevisionGUID="26f111a9-3005-44b6-8456-c49a1e3d00c9" CreationDate="2021-03-18T16:49:44.920" UserId="13273" Text="for smooth shading you usually store the normal vectors per vertex and not per face (flat shading). The normal vector on a specific point on a face will then be calculated by interpolating the normal vectors of the vertices (corners) of the face.&#xD;&#xA;&#xD;&#xA;**For example when having a triangle:**&#xD;&#xA;you would use an interpolation which uses the barycentric coordinates of three normal vectors like discribed [here][1].&#xD;&#xA;&#xD;&#xA;For non planar polygons, of cause you don't have a specific defined surface. &#xD;&#xA;Therefore it depend on you, which kind of interpolation you are using. But it should interpolate with respect to the corners distance.&#xD;&#xA;&#xD;&#xA;And don't forget to normalize the vector at the end!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://15462.courses.cs.cmu.edu/fall2015/lecture/texture/slide_019" ContentLicense="CC BY-SA 4.0" />
  <row Id="31370" PostHistoryTypeId="2" PostId="10754" RevisionGUID="0104383b-36f7-403b-b533-a01591baadc2" CreationDate="2021-03-18T20:56:28.980" UserId="15940" Text="I am trying to implement next/prev of edges in half-edge data structure. But I ran into this question. If there are two holes with a common vertex, will the closed loop of the edges run as in the first picture? Or will it be two separate cycles, as in the second picture?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mYM61.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In 3ds Max, when the border tool is used, it selects the edge loop as in the first image. Please help me to understand this." ContentLicense="CC BY-SA 4.0" />
  <row Id="31371" PostHistoryTypeId="1" PostId="10754" RevisionGUID="0104383b-36f7-403b-b533-a01591baadc2" CreationDate="2021-03-18T20:56:28.980" UserId="15940" Text="Half-Edge Data Structure with holes" ContentLicense="CC BY-SA 4.0" />
  <row Id="31372" PostHistoryTypeId="3" PostId="10754" RevisionGUID="0104383b-36f7-403b-b533-a01591baadc2" CreationDate="2021-03-18T20:56:28.980" UserId="15940" Text="|c++|edge-detection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31373" PostHistoryTypeId="6" PostId="10752" RevisionGUID="5c1c012c-c355-46bf-a9f5-d136397a79e3" CreationDate="2021-03-18T23:18:59.907" UserId="11058" Comment="edited tags" Text="|opengl|shading|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31374" PostHistoryTypeId="2" PostId="10755" RevisionGUID="b4744301-9f25-4650-8d36-2a75019a5a68" CreationDate="2021-03-19T17:27:05.687" UserId="48" Text="If you're interested in vertex normals specifically, there's an easy answer even for non-planar polygons that avoids the question of defining what the exact surface is: for each vertex, calculate the normal of the plane formed by the two edges entering and leaving that vertex.&#xD;&#xA;&#xD;&#xA;More formally, given vertices $\mathbf{v}_1, \mathbf{v}_2, \ldots \mathbf{v}_n$ with counterclockwise winding, define the normal at the $i$th vertex as:&#xD;&#xA;$$&#xD;&#xA;\mathbf{n}_i = (\mathbf{v}_i - \mathbf{v}_{i-1}) \times (\mathbf{v}_{i+1} - \mathbf{v}_i)&#xD;&#xA;$$&#xD;&#xA;(where the indices wrap around).&#xD;&#xA;&#xD;&#xA;You can then proceed to accumulate normals calculated this way from all the faces that share a given vertex, as usual for smooth shading.&#xD;&#xA;&#xD;&#xA;As has been discussed, there are multiple ways to define a smooth surface corresponding to a non-planar polygon, but _any_ reasonable way of defining such a surface must converge to the normals as defined here near the vertices, or else the surface can not both be smooth (locally flat) and meet the straight-line edges between the vertices.&#xD;&#xA;&#xD;&#xA;A caveat to this approach, though, is that it won't define a normal for collinear vertices (where the entering and exiting edges are parallel), since the cross product goes to zero there. If this is a problem, it might work to patch up such vertices by interpolating normals to them from the surrounding non-collinear vertices." ContentLicense="CC BY-SA 4.0" />
  <row Id="31378" PostHistoryTypeId="4" PostId="10752" RevisionGUID="9623f44c-8027-4c94-9958-fcc4574265a9" CreationDate="2021-03-19T17:47:50.257" UserId="11058" Comment="edited title" Text="How to calculate vertex normals on a mesh with non-planar polygons" ContentLicense="CC BY-SA 4.0" />
  <row Id="31380" PostHistoryTypeId="2" PostId="10757" RevisionGUID="e216bdac-9f60-4a8a-92ff-9cae072aa6ba" CreationDate="2021-03-20T14:55:23.503" UserId="15950" Text=" I was reading the wiki article about homogeneous coordinates , I learned that it has it's advantages when it comes to performing affine transformation, since you can represent it only matrices. But I couldn't understand what is the additional third component compared to  Cartesian coordinates.   In the image below  we see additional 1(which  I am trying to understand)  added to convert it to  homogeneous coordinates. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e4gAx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="31381" PostHistoryTypeId="1" PostId="10757" RevisionGUID="e216bdac-9f60-4a8a-92ff-9cae072aa6ba" CreationDate="2021-03-20T14:55:23.503" UserId="15950" Text="What is exactly the third component in homogeneous coordinate system?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31382" PostHistoryTypeId="3" PostId="10757" RevisionGUID="e216bdac-9f60-4a8a-92ff-9cae072aa6ba" CreationDate="2021-03-20T14:55:23.503" UserId="15950" Text="|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31383" PostHistoryTypeId="2" PostId="10758" RevisionGUID="96b6f787-5ea1-4eb6-97e2-16f6a490e5fa" CreationDate="2021-03-20T16:22:22.873" UserId="10096" Text="The relationship between standard coordinates $(x,y)$ and homogeneous coordinates $(X,Y,Z)$ is $x = X / Z, y = Y/Z$. Homogeneous coordinates are a type of [projective coordinates][1]. All points on the line $(Z x, Z y, Z)$ are equivalent to the point $(x,y)$ in 2D (the same thing can be applied for 3D). So technically 2D points are represented as 3D lines passing though the origin, and 2D lines are represented as 3D planes passing through the origin. &#xD;&#xA;&#xD;&#xA;In computer graphics the above interpretation is largely irrelevant, however, since homogeneous coordinates are used mostly for convenience. A translation is of the form $x' = x+t_x, y' = y+t_y$. If one uses homogeneous coordinates, then this can be achieved through $X' = 1 \cdot X + 0 \cdot Y + t_x \cdot Z$, $Y' = 0 \cdot X + 1 \cdot Y + t_y \cdot Z$, and $Z' = 0 \cdot X + 0\cdot Y + 1 \cdot Z$.  If you set $Z=1$ then you get exactly the expression for translation, and you can use the matrix induced from the 3 equations above. For directions you can set $Z=0$ so that translation would not be applied to those. &#xD;&#xA;&#xD;&#xA;In 3D the homogeneous coordinates $W$ also plays a role in the perspective projection, since the projection matrix modifies it to hold the relevant value by which the other coordinates must be divided, and the division is typically carried out by the hardware.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Homogeneous_coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="31384" PostHistoryTypeId="2" PostId="10759" RevisionGUID="161de14c-da34-4549-9173-25d04668b0c3" CreationDate="2021-03-21T08:35:25.510" UserId="15320" Text="I have a very simple obj file:&#xD;&#xA;```&#xD;&#xA;v -2.22045e-16 -0.291306 -2.22045e-16&#xD;&#xA;v -0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 -0.24339&#xD;&#xA;v -2.22045e-16 -2.22045e-16 -0.24339&#xD;&#xA;v 0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -0.291306 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 -0.24339&#xD;&#xA;v -0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 0.291306 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 -0.24339&#xD;&#xA;v -2.22045e-16 0.291306 -2.22045e-16&#xD;&#xA;v 0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -0.291306 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 0.24339&#xD;&#xA;v -0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v 0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 0.24339&#xD;&#xA;v -2.22045e-16 -0.291306 -2.22045e-16&#xD;&#xA;v -0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 0.24339&#xD;&#xA;v -2.22045e-16 0.291306 -2.22045e-16&#xD;&#xA;v 0.24339 -2.22045e-16 -2.22045e-16&#xD;&#xA;v -2.22045e-16 0.291306 -2.22045e-16&#xD;&#xA;v -2.22045e-16 -2.22045e-16 0.24339&#xD;&#xA;f 3 2 1&#xD;&#xA;f 6 5 4&#xD;&#xA;f 9 8 7&#xD;&#xA;f 12 11 10&#xD;&#xA;f 15 14 13&#xD;&#xA;f 18 17 16&#xD;&#xA;f 21 20 19&#xD;&#xA;f 24 23 22&#xD;&#xA;```&#xD;&#xA;As you can see, there is no `vn` command. However, if I open it in meshlab and turn on the vertex normal rendering, it shows vertex normals (and some normals not attached to vertices).&#xD;&#xA;&#xD;&#xA;Why does this happen?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31385" PostHistoryTypeId="1" PostId="10759" RevisionGUID="161de14c-da34-4549-9173-25d04668b0c3" CreationDate="2021-03-21T08:35:25.510" UserId="15320" Text="How does OBJ formats determine vertex normals?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31386" PostHistoryTypeId="3" PostId="10759" RevisionGUID="161de14c-da34-4549-9173-25d04668b0c3" CreationDate="2021-03-21T08:35:25.510" UserId="15320" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31387" PostHistoryTypeId="4" PostId="10759" RevisionGUID="e6961338-8231-470f-bac5-e764998ea67c" CreationDate="2021-03-21T12:15:43.477" UserId="15320" Comment="edited title" Text="How does OBJ format determine vertex normals?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31388" PostHistoryTypeId="2" PostId="10760" RevisionGUID="e932cf4d-79d7-413c-9f72-3f13396d690a" CreationDate="2021-03-21T13:30:40.087" UserId="7952" Text="It is common for modeling software to compute the normals when they aren't included in the loaded file (regardless of the format). This is usually highly dependent on the settings chosen when the file is loaded. Vertex normals can be computed fairly easily. The software can also compute smooth or faceted normals so you can switch between the two. &#xD;&#xA;&#xD;&#xA;Your example includes faces...the `f 3 2 1` is a face. Each number refers to  one of the vertex values which are numbered starting from the top. `v -2.22045e-16 -0.291306 -2.22045e-16` is vertex number 1 in this case. The software can easily use that information to compute normals.&#xD;&#xA;&#xD;&#xA;I loaded this file into Blender and it is well behaved, so odds are meshlab has some options turned on that are showing split normals or vertex normals or one of the many other possible variants out there.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31389" PostHistoryTypeId="2" PostId="10761" RevisionGUID="c0c1e745-2d35-4b0e-9eab-a2c4f044c204" CreationDate="2021-03-21T13:32:14.083" UserId="9438" Text="&gt; Why does this happen?&#xD;&#xA;&#xD;&#xA;If no normals are supplied, meshlab probably generates them. This is common behaviour of many 3D applications. &#xD;&#xA;&#xD;&#xA;There are various techniques for generating normals (per-vertex, per-face, weighted, non-weighted etc) depending on the desired appearance (smooth/flat shading).&#xD;&#xA;&#xD;&#xA;&gt; (and some normals not attached to vertices).&#xD;&#xA;&#xD;&#xA;Sound possibly like a bug on meshlab's part. Can you post a screen-shot?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31390" PostHistoryTypeId="5" PostId="10760" RevisionGUID="f306c413-2d8b-4eed-a465-818ea50bd454" CreationDate="2021-03-21T15:05:23.017" UserId="7952" Comment="added 475 characters in body" Text="It is common for modeling software to compute the normals when they aren't included in the loaded file (regardless of the format). This is usually highly dependent on the settings chosen when the file is loaded. Vertex normals can be computed fairly easily. The software can also compute smooth or faceted normals so you can switch between the two. &#xD;&#xA;&#xD;&#xA;Your example includes faces...the `f 3 2 1` is a face. Each number refers to  one of the vertex values which are numbered starting from the top. `v -2.22045e-16 -0.291306 -2.22045e-16` is vertex number 1 in this case. The software can easily use that information to compute normals.&#xD;&#xA;&#xD;&#xA;A normal is computed from the cross product of the edge vectors. Stictly speaking the obj format doesn't compute the actual normals, it just provides the information that Meshlab needs so that Meshlab can compute the normals. which looks something along the lines of:&#xD;&#xA;&#xD;&#xA; `facted_normal = normalize( cross( 2-3, 1-3))`&#xD;&#xA;&#xD;&#xA;Where the numbers for 1, 2 and 3 are replaced with the actual values for those vertices. Other types of normals are usually computed based of that.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I loaded this file into Blender and it is well behaved, so odds are meshlab has some options turned on that are showing split normals or vertex normals or one of the many other possible variants out there.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31391" PostHistoryTypeId="2" PostId="10762" RevisionGUID="8fb85407-0f0a-46a4-965a-48ec4bf1433e" CreationDate="2021-03-21T17:57:29.423" UserId="15954" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out `{a,b,c}` as an output. I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="31392" PostHistoryTypeId="1" PostId="10762" RevisionGUID="8fb85407-0f0a-46a4-965a-48ec4bf1433e" CreationDate="2021-03-21T17:57:29.423" UserId="15954" Text="Given two vectors, find the rotation matrix between the two" ContentLicense="CC BY-SA 4.0" />
  <row Id="31393" PostHistoryTypeId="3" PostId="10762" RevisionGUID="8fb85407-0f0a-46a4-965a-48ec4bf1433e" CreationDate="2021-03-21T17:57:29.423" UserId="15954" Text="|raytracing|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31394" PostHistoryTypeId="5" PostId="10762" RevisionGUID="851afd64-4648-40f2-9f1e-0b7cb2952bb7" CreationDate="2021-03-21T18:06:13.557" UserId="15954" Comment="added 11 characters in body" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another normalized camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out `{a,b,c}` as an output. I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="31395" PostHistoryTypeId="5" PostId="10762" RevisionGUID="42e82406-7fb0-4679-b1b6-982bebd6b800" CreationDate="2021-03-21T18:18:17.320" UserId="15954" Comment="added 327 characters in body" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out a normalized `{a,b,c}` as an output. &#xD;&#xA;Then I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;I am in a similar situation than [the person aksing this question][2] except that he seems to know already what needs be done and is just asking &#xD;&#xA;about if his rationale is good and it does not help.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/10613/transforming-a-ray-from-camera-space-to-world-space?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="31396" PostHistoryTypeId="2" PostId="10763" RevisionGUID="06b49029-5c0e-4eed-a1a2-1ffdf48945ba" CreationDate="2021-03-21T18:21:53.030" UserId="15955" Text="Good evening!&#xD;&#xA;I would like a help to understand the following line of code:&#xD;&#xA;&#xD;&#xA;    return float3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));&#xD;&#xA;&#xD;&#xA;I've seen some places calling it gamma correction, but I don't know if it's correct.&#xD;&#xA;&#xD;&#xA;If it really is a gamma correction how does it work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31397" PostHistoryTypeId="1" PostId="10763" RevisionGUID="06b49029-5c0e-4eed-a1a2-1ffdf48945ba" CreationDate="2021-03-21T18:21:53.030" UserId="15955" Text="Doubt about function for color" ContentLicense="CC BY-SA 4.0" />
  <row Id="31398" PostHistoryTypeId="3" PostId="10763" RevisionGUID="06b49029-5c0e-4eed-a1a2-1ffdf48945ba" CreationDate="2021-03-21T18:21:53.030" UserId="15955" Text="|brdf|color|hlsl|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31399" PostHistoryTypeId="2" PostId="10764" RevisionGUID="5194b537-9424-4c40-9acb-ddd3db18a9b8" CreationDate="2021-03-22T07:08:15.693" UserId="3073" Text="You can construct an axis to make a rotation matrix. This is done by producing the 3 direction (normalized) vectors for the 3 axis of our new rotated coordinate system, they are forward, up and right vectors.&#xD;&#xA;&#xD;&#xA;In your case let's say we have 2 vectors called v1 and v2.&#xD;&#xA;&#xD;&#xA;we can produce a direction from them via (glsl psuedo code):&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v1 - v2);&#xD;&#xA;&#xD;&#xA;Then for our up vector we can pick the world-up axis (e.g. 0,1,0), although this may give you problems if the forward vector is very close to the up axis, in the case you can pick another axis like {0,0,1}. For simplicity in this example we'll stick to the world up axis.&#xD;&#xA;&#xD;&#xA;The last vector can be produced from the other 2 vectors using a cross product.&#xD;&#xA;&#xD;&#xA;so now we should have something like:&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v1 - v2);&#xD;&#xA;    vec3 upVector = vec3(0,1,0);&#xD;&#xA;    vec3 rightVector = cross(forwardVector, upVector);&#xD;&#xA;&#xD;&#xA;These 3 vectors can be directly plugged into a 3x3 matrix to form the rotation matrix.&#xD;&#xA;&#xD;&#xA;    f.x f.y f.z &#xD;&#xA;    u.x u.y u.z &#xD;&#xA;    r.x r.y r.z&#xD;&#xA;&#xD;&#xA;where f=forwardVector, u=upVector and r=rightVector.&#xD;&#xA;&#xD;&#xA;This is similar to an openGL &quot;LookAt&quot; matrix. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31400" PostHistoryTypeId="5" PostId="10764" RevisionGUID="fd88f6a0-0aa7-4aee-8ee0-ec6fddb90bbc" CreationDate="2021-03-22T07:16:45.617" UserId="3073" Comment="added 12 characters in body" Text="You can construct a rotation matrix from an &quot;axis&quot;, or 3 vectors. This is done by calculating 3 direction (normalized) vectors for the 3 axis of our new rotated coordinate system, they are forward, up and right vectors. &#xD;&#xA;&#xD;&#xA;In your case let's say we have 2 vectors called v1 and v2.&#xD;&#xA;&#xD;&#xA;we can produce a direction from them via (glsl psuedo code):&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v1 - v2);&#xD;&#xA;&#xD;&#xA;Then for our up vector we can pick the world-up axis (e.g. 0,1,0), although this may give you problems if the forward vector is very close to the up axis, in the case you can pick another axis like {0,0,1}. For simplicity in this example we'll stick to the world up axis.&#xD;&#xA;&#xD;&#xA;The last vector can be produced from the other 2 vectors using a cross product.&#xD;&#xA;&#xD;&#xA;so now we should have something like:&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v1 - v2);&#xD;&#xA;    vec3 upVector = vec3(0,1,0);&#xD;&#xA;    vec3 rightVector = cross(forwardVector, upVector);&#xD;&#xA;&#xD;&#xA;These 3 vectors can be directly plugged into a 3x3 matrix to form the rotation matrix.&#xD;&#xA;&#xD;&#xA;    f.x f.y f.z &#xD;&#xA;    u.x u.y u.z &#xD;&#xA;    r.x r.y r.z&#xD;&#xA;&#xD;&#xA;where f=forwardVector, u=upVector and r=rightVector.&#xD;&#xA;&#xD;&#xA;This is similar to an openGL &quot;LookAt&quot; matrix. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31401" PostHistoryTypeId="5" PostId="10764" RevisionGUID="6284f538-631e-442f-9339-2fb59c067c0e" CreationDate="2021-03-22T07:23:00.213" UserId="3073" Comment="added 12 characters in body" Text="You can construct a rotation matrix from an &quot;axis&quot;, or 3 vectors. This is done by calculating 3 direction (normalized) vectors for the 3 axis of our new rotated coordinate system, they are forward, up and right vectors. &#xD;&#xA;&#xD;&#xA;In your case let's say we have 2 vectors called v1 and v2.&#xD;&#xA;&#xD;&#xA;we can produce a direction from them via (glsl psuedo code):&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v1 - v2);&#xD;&#xA;&#xD;&#xA;Then for our up vector we can pick the world-up axis (e.g. 0,1,0), although this may give you problems if the forward vector is very close to the up axis, in that case you can pick another arbitrary axis that's not nearby, like {0,0,1}. For the sake of simplicity we'll stick to the world up axis of {0,1,0}.&#xD;&#xA;&#xD;&#xA;The last vector can be produced from the other 2 vectors using a cross product.&#xD;&#xA;&#xD;&#xA;so now we should have something like:&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v1 - v2);&#xD;&#xA;    vec3 upVector = vec3(0,1,0);&#xD;&#xA;    vec3 rightVector = cross(forwardVector, upVector);&#xD;&#xA;&#xD;&#xA;These 3 vectors can be directly plugged into a 3x3 matrix to form the rotation matrix.&#xD;&#xA;&#xD;&#xA;    f.x f.y f.z &#xD;&#xA;    u.x u.y u.z &#xD;&#xA;    r.x r.y r.z&#xD;&#xA;&#xD;&#xA;where f=forwardVector, u=upVector and r=rightVector.&#xD;&#xA;&#xD;&#xA;This is similar to an openGL &quot;LookAt&quot; matrix. &#xD;&#xA;&#xD;&#xA;Be aware that there isn't a single valid rotation matrix for 2 vectors, there are lots of rotation matrices that are valid solutions because 2 vectors cannot describe rotation along the v1-&gt;v2 axis.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31402" PostHistoryTypeId="5" PostId="10764" RevisionGUID="982b93ea-790a-465a-95b5-279c55d56884" CreationDate="2021-03-22T08:30:09.247" UserId="3073" Comment="added 4 characters in body" Text="You can construct a rotation matrix from an &quot;axis&quot;, or 3 vectors. This is done by calculating 3 direction (normalized) vectors for the 3 axis of our new rotated coordinate system, they are forward, up and right vectors. &#xD;&#xA;&#xD;&#xA;In your case let's say we have 2 vectors called v1 and v2.&#xD;&#xA;&#xD;&#xA;we can produce a direction from them via (glsl psuedo code):&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v2 - v1);&#xD;&#xA;&#xD;&#xA;Then for our up vector we can pick the world-up axis (e.g. 0,1,0), although this may give you problems if the forward vector is very close to the up axis, in that case you can pick another arbitrary axis that's not nearby, like {0,0,1}. For the sake of simplicity we'll stick to the world up axis of {0,1,0}.&#xD;&#xA;&#xD;&#xA;The last vector can be produced from the other 2 vectors using a cross product.&#xD;&#xA;&#xD;&#xA;so now we should have something like:&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v2 - v1);&#xD;&#xA;    vec3 upVector = vec3(0,1,0);&#xD;&#xA;    vec3 rightVector = normalize(cross(forwardVector, upVector));&#xD;&#xA;&#xD;&#xA;These 3 vectors can be directly plugged into a 3x3 matrix to form the rotation matrix.&#xD;&#xA;&#xD;&#xA;    r.x r.y r.z&#xD;&#xA;    u.x u.y u.z &#xD;&#xA;    f.x f.y f.z &#xD;&#xA;&#xD;&#xA;where f=forwardVector, u=upVector and r=rightVector.&#xD;&#xA;&#xD;&#xA;This is similar to an openGL &quot;LookAt&quot; matrix. &#xD;&#xA;&#xD;&#xA;Be aware there are many rotation matrices that are valid solutions because 2 vectors cannot describe what the rotation is along the v1-&gt;v2 axis (That's what the 'up' axis fixes in this case).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31403" PostHistoryTypeId="5" PostId="10764" RevisionGUID="c79e877f-dbd1-4038-a68d-91a5d3ec8bbc" CreationDate="2021-03-22T08:46:45.830" UserId="3073" Comment="added 13 characters in body" Text="You can construct a rotation matrix from an &quot;axis&quot;, or 3 vectors. This is done by calculating 3 direction (normalized) vectors for the 3 axis of our new rotated coordinate system, they are forward, up and right vectors. &#xD;&#xA;&#xD;&#xA;In your case let's say we have 2 vectors called v1 and v2.&#xD;&#xA;&#xD;&#xA;we can produce a direction from them via (glsl psuedo code):&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v2 - v1);&#xD;&#xA;&#xD;&#xA;Then for our up vector we can pick the world-up axis (e.g. 0,1,0), although this may give you problems if the forward vector is very close to the up axis, in that case you can pick another arbitrary axis that's not nearby, like {0,0,1}. For the sake of simplicity we'll stick to the world up axis of {0,1,0}.&#xD;&#xA;&#xD;&#xA;The last vector can be derived automatically from the other 2 vectors using a cross product.&#xD;&#xA;&#xD;&#xA;so now we should have something like:&#xD;&#xA;&#xD;&#xA;    vec3 forwardVector = normalize(v2 - v1);&#xD;&#xA;    vec3 upVector = vec3(0,1,0);&#xD;&#xA;    vec3 rightVector = normalize(cross(forwardVector, upVector));&#xD;&#xA;&#xD;&#xA;These 3 vectors can be directly plugged into a 3x3 matrix to form the rotation matrix.&#xD;&#xA;&#xD;&#xA;    r.x r.y r.z&#xD;&#xA;    u.x u.y u.z &#xD;&#xA;    f.x f.y f.z &#xD;&#xA;&#xD;&#xA;where f=forwardVector, u=upVector and r=rightVector.&#xD;&#xA;&#xD;&#xA;This is similar to an openGL &quot;LookAt&quot; matrix. &#xD;&#xA;&#xD;&#xA;Be aware there are many rotation matrices that are valid solutions because 2 vectors cannot describe what the rotation is along the v1-&gt;v2 axis (That's what the 'up' axis fixes in this case).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31404" PostHistoryTypeId="2" PostId="10765" RevisionGUID="2f0d4aa6-7acb-4e88-afdf-8aad7e3e14a7" CreationDate="2021-03-22T10:43:32.767" UserId="9420" Text="To understand the $w$ component, it'll be easier to understand how *homogeneous coordinates* come about in the first place. The follow example will be in 2D for the sake of simplicity, but the same can be extended to 3D. Let's try to &quot;invent&quot; homogeneous coordinates for the first time.&#xD;&#xA;&#xD;&#xA;We start with the high school line equation, $ax + by + c = 0$. This line lies on a 2D plane (or more formally, in $\mathbb R^2$). We can quite easily see that a point $x$ in $\mathbb R^2$, represented by $x = [x_1, x_2]$, lies on our line if the line equation still holds (i.e., $ax_1 + bx_2 + c = 0$). Notice that our &quot;line&quot; is really just defined by the values $a$, $b$, and $c$, so lets write that in row-vector form: $l =[a\ b\ c]$. Let's just define this 3-component vector that represents our line in 2D as the homogeneous representation of a line in 2D space. This is the first building block of our &quot;homogeneous coordinates&quot; system.&#xD;&#xA;&#xD;&#xA;To test if a point lies on this line line, we're really just doing component-wise multiplication between $l$ and $x$, ($a \times x_1 + b \times x_2 + ... = 0$), so we can now re-write our line equation as a dot product of $x$ and $l$ *if* we add a 1 as the 3rd component of our 2D points: $x' = [x_1, x_2, 1]$. Now:&#xD;&#xA;&#xD;&#xA;$$ l.x' = [a\ b\ c] \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] = ax_1 + bx_2 + c = 0 $$&#xD;&#xA;&#xD;&#xA;That gets us back our original line equation exactly! Now we call our new 3-component point $x'$ as the normalized homogeneous representation of a 2D point. That &quot;1&quot; in the third component is the so called $w$ component. You might also have noticed that lines and points are not distinguished here. This is true in homogeneous coordinates, lines and points are *duals* of each other.&#xD;&#xA;&#xD;&#xA;We can also see that it doesn't matter what are the exact values of $a$, $b$, and $c$ (or conversely, $x_1, x_2, w$), but rather it is the 2 independent *ratios* ($a : b$ and $b : c$) that really matters. In other words,&#xD;&#xA;&#xD;&#xA;$$w(ax_1 + bx_2 + c) = 0$$&#xD;&#xA;&#xD;&#xA;will hold for all values of $w$ (except for $w = 0$ for reasons to be explained later). This means that in our homogeneous coordinate system, the following all represents the same points:&#xD;&#xA;&#xD;&#xA;$$w \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] \equiv \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] \equiv \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       wx_1\\&#xD;&#xA;       wx_2\\&#xD;&#xA;       w&#xD;&#xA;       \end{array}&#xD;&#xA;\right] $$&#xD;&#xA;&#xD;&#xA;At this point, we've defined a new homogeneous coordinate system with a point $x'$ in this coordinate system. How do we get back $x$, the original 2D point? I hope it is simple to see that we just have to divide by $w$ and drop the $w$ component to get back the original point (this is &quot;perspective division&quot;!).&#xD;&#xA;&#xD;&#xA;$$ x = \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1/w\\&#xD;&#xA;       x_2/w\\&#xD;&#xA;       \end{array}&#xD;&#xA;\right] $$&#xD;&#xA;&#xD;&#xA;Notice how we can't divide by $w$ if $w = 0$? As a side note, this property is actually exploited in projective space, for us to represent points at infinity by having 0 in the $w$ component.&#xD;&#xA;&#xD;&#xA;So to answer the original question of &quot;what is the $w$ component?&quot;, it is just a scale factor for homogeneous coordinates. It may or may not be 1, but if it isn't 1, you have to normalize it by dividing the $w$ component as described above." ContentLicense="CC BY-SA 4.0" />
  <row Id="31405" PostHistoryTypeId="5" PostId="10765" RevisionGUID="136587db-0e2f-42ea-acf1-93bd4306cc58" CreationDate="2021-03-22T10:48:54.413" UserId="9420" Comment="deleted 1 character in body" Text="To understand the $w$ component, it'll be easier to understand how *homogeneous coordinates* come about in the first place. The follow example will be in 2D for the sake of simplicity, but the same can be extended to 3D. Let's try to &quot;invent&quot; homogeneous coordinates for the first time.&#xD;&#xA;&#xD;&#xA;We start with the high school line equation, $ax + by + c = 0$. This line lies on a 2D plane (or more formally, in $\mathbb R^2$). We can quite easily see that a point $x$ in $\mathbb R^2$, represented by $x = [x_1, x_2]$, lies on our line if the line equation still holds (i.e., $ax_1 + bx_2 + c = 0$). Notice that our &quot;line&quot; is really just defined by the values $a$, $b$, and $c$, so lets write that in row-vector form: $l =[a\ b\ c]$. Let's just define this 3-component vector that represents our line in 2D as the homogeneous representation of a line in 2D space. This is the first building block of our &quot;homogeneous coordinates&quot; system.&#xD;&#xA;&#xD;&#xA;To test if a point lies on this line line, we're really just doing component-wise multiplication between $l$ and $x$, ($a \times x_1 + b \times x_2 + ... = 0$), so we can now re-write our line equation as a dot product of $x$ and $l$ *if* we add a 1 as the 3rd component of our 2D points: $x' = [x_1, x_2, 1]$. Now:&#xD;&#xA;&#xD;&#xA;$$ l.x' = [a\ b\ c] \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] = ax_1 + bx_2 + c = 0 $$&#xD;&#xA;&#xD;&#xA;That gets us back our original line equation exactly! Now we call our new 3-component point $x'$ as the normalized homogeneous representation of a 2D point. That &quot;1&quot; in the third component is the so called $w$ component. You might also have noticed that lines and points are not distinguished here. This is true in homogeneous coordinates, lines and points are *duals* of each other.&#xD;&#xA;&#xD;&#xA;We can also see that it doesn't matter what are the exact values of $a$, $b$, and $c$ (or conversely, $x_1, x_2, w$), but rather it is the 2 independent *ratios* ($a : b$ and $b : c$) that really matters. In other words,&#xD;&#xA;&#xD;&#xA;$$w(ax_1 + bx_2 + c) = 0$$&#xD;&#xA;&#xD;&#xA;will hold for all values of $w$ (except for $w = 0$ for reasons to be explained later). This means that in our homogeneous coordinate system, the following all represents the same point:&#xD;&#xA;&#xD;&#xA;$$w \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] \equiv \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] \equiv \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       wx_1\\&#xD;&#xA;       wx_2\\&#xD;&#xA;       w&#xD;&#xA;       \end{array}&#xD;&#xA;\right] $$&#xD;&#xA;&#xD;&#xA;By now, we've defined a new homogeneous coordinate system with a point $x'$ in this coordinate system. How do we get back $x$, the original 2D point? I hope it is simple to see that we just have to divide by $w$ and drop the $w$ component to get back the original point (this is in fact, &quot;perspective division&quot;!).&#xD;&#xA;&#xD;&#xA;$$ x = \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1/w\\&#xD;&#xA;       x_2/w\\&#xD;&#xA;       \end{array}&#xD;&#xA;\right] $$&#xD;&#xA;&#xD;&#xA;Notice how we can't divide by $w$ if $w = 0$? As a side note, this property is actually exploited in projective space, for us to represent points at infinity by having 0 in the $w$ component. In computer graphics, we also exploit this to represent vectors. You cannot get back a 2D point from a vector in homogeneous coordinates, which makes sense.&#xD;&#xA;&#xD;&#xA;So to answer the original question of &quot;what is the $w$ component?&quot;, it is just a scale factor for homogeneous coordinates. It may or may not be 1, but if it isn't 1, you have to normalize it by dividing the $w$ component as described above." ContentLicense="CC BY-SA 4.0" />
  <row Id="31406" PostHistoryTypeId="5" PostId="10765" RevisionGUID="533b382d-5992-40e9-9a78-2a0be24fda3d" CreationDate="2021-03-22T10:54:17.460" UserId="9420" Comment="added 3 characters in body" Text="To understand the $w$ component, it'll be easier to understand how *homogeneous coordinates* come about in the first place. The following example will be in 2D for the sake of simplicity, but the same can be extended to 3D. Let's try to &quot;invent&quot; homogeneous coordinates for the first time.&#xD;&#xA;&#xD;&#xA;We start with the high school line equation, $ax + by + c = 0$. This line lies on a 2D plane (or more formally, in $\mathbb R^2$). We can quite easily see that a point $x$ in $\mathbb R^2$, represented by $x = [x_1, x_2]$, lies on our line if the line equation still holds (i.e., $ax_1 + bx_2 + c = 0$). Notice that our &quot;line&quot; is really just defined by the values $a$, $b$, and $c$, so lets write that in row-vector form: $l =[a\ b\ c]$. Let us define this 3-component vector that represents our line in 2D as our &quot;homogeneous representation&quot; of a line in 2D space. This is the first building block of our &quot;homogeneous coordinates&quot; system.&#xD;&#xA;&#xD;&#xA;To test if a point lies on this line line, we're really just doing component-wise multiplication between $l$ and $x$, ($a \times x_1 + b \times x_2 + ... = 0$), so we can now re-write our line equation as a dot product of $x$ and $l$ *if* we add a 1 as the 3rd component of our 2D points: $x' = [x_1, x_2, 1]$. Now:&#xD;&#xA;&#xD;&#xA;$$ l.x' = [a\ b\ c] \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] = ax_1 + bx_2 + c = 0 $$&#xD;&#xA;&#xD;&#xA;That gets us back our original line equation exactly! Now we call our new 3-component point $x'$ as the normalized homogeneous representation of a 2D point. That &quot;1&quot; in the third component is the so called $w$ component. You might also have noticed that lines and points are not distinguished here. This is true in homogeneous coordinates, lines and points are *duals* of each other.&#xD;&#xA;&#xD;&#xA;We can also see that it doesn't matter what are the exact values of $a$, $b$, and $c$ (or conversely, $x_1, x_2, w$), but rather it is the 2 independent *ratios* ($a : b$ and $b : c$) that really matters. In other words,&#xD;&#xA;&#xD;&#xA;$$w(ax_1 + bx_2 + c) = 0$$&#xD;&#xA;&#xD;&#xA;will hold for all values of $w$ (except for $w = 0$ for reasons to be explained later). This means that in our homogeneous coordinate system, the following all represents the same point:&#xD;&#xA;&#xD;&#xA;$$w \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] \equiv \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1\\&#xD;&#xA;       x_2\\&#xD;&#xA;       1&#xD;&#xA;       \end{array}&#xD;&#xA;\right] \equiv \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       wx_1\\&#xD;&#xA;       wx_2\\&#xD;&#xA;       w&#xD;&#xA;       \end{array}&#xD;&#xA;\right] $$&#xD;&#xA;&#xD;&#xA;By now, we've defined a new homogeneous coordinate system with a point $x'$ in this coordinate system. How do we get back $x$, the original 2D point? I hope it is simple to see that we just have to divide by $w$ and drop the $w$ component to get back the original point (this is in fact, &quot;perspective division&quot;!).&#xD;&#xA;&#xD;&#xA;$$ x = \left[&#xD;&#xA;       \begin{array}{c}&#xD;&#xA;       x_1/w\\&#xD;&#xA;       x_2/w\\&#xD;&#xA;       \end{array}&#xD;&#xA;\right] $$&#xD;&#xA;&#xD;&#xA;Notice how we can't divide by $w$ if $w = 0$? As a side note, this property is actually exploited in projective space, for us to represent points at infinity by having 0 in the $w$ component. In computer graphics, we also exploit this to represent vectors. You cannot get back a 2D point from a vector in homogeneous coordinates, which makes sense.&#xD;&#xA;&#xD;&#xA;So to answer the original question of &quot;what is the $w$ component?&quot;, it is just a scale factor for homogeneous coordinates. It may or may not be 1, but if it isn't 1, you have to normalize it by dividing the $w$ component as described above." ContentLicense="CC BY-SA 4.0" />
  <row Id="31411" PostHistoryTypeId="2" PostId="10767" RevisionGUID="b4cdf130-08d1-4e22-aee8-8eb063daa102" CreationDate="2021-03-22T14:41:07.580" UserId="7952" Text="Gamma correction originated as a way of correcting the output of a CRT to be better fit for the human visual system. Modern monitors don't need to do it, but, they followed the CRT and there were millions of CRT's that all had gamma correction and most signals already had gamma correction in them. Today we have a chicken and egg problem...but reversed. Millions of clucking hardware chickens all speaking gamma...&#xD;&#xA;&#xD;&#xA;The flip side is that us humans don't think well in the land of exponential values, but we do think well in terms of linear values. So software for graphics code tends to remove the gamma then we can multiply add and manipulate in an intuitive manner, and convert it back to gamma for display.&#xD;&#xA;&#xD;&#xA;Modern hardware has specialty components that do this on the fly so the generally accepted practice is to set up the graphics hardware to handle this so we don't have to worry about as programmers. But sometimes it can be useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="31412" PostHistoryTypeId="5" PostId="10762" RevisionGUID="471e0357-93bc-4ccb-9fb5-e9add17fc2db" CreationDate="2021-03-22T15:23:49.427" UserId="15954" Comment="deleted 21 characters in body; edited tags; edited title" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out a normalized `{a,b,c}` as an output. &#xD;&#xA;Then I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;I am in a similar situation than [the person aksing this question][2] except that he seems to know already what needs be done and is just asking &#xD;&#xA;about if his rationale is good.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/10613/transforming-a-ray-from-camera-space-to-world-space?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="31413" PostHistoryTypeId="4" PostId="10762" RevisionGUID="471e0357-93bc-4ccb-9fb5-e9add17fc2db" CreationDate="2021-03-22T15:23:49.427" UserId="15954" Comment="deleted 21 characters in body; edited tags; edited title" Text="Given two 3d vectors, find the rotation matrix between the two" ContentLicense="CC BY-SA 4.0" />
  <row Id="31414" PostHistoryTypeId="6" PostId="10762" RevisionGUID="471e0357-93bc-4ccb-9fb5-e9add17fc2db" CreationDate="2021-03-22T15:23:49.427" UserId="15954" Comment="deleted 21 characters in body; edited tags; edited title" Text="|raytracing|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31418" PostHistoryTypeId="5" PostId="10762" RevisionGUID="835f576a-ec24-4adf-a444-e0605d1dc5be" CreationDate="2021-03-22T16:57:06.850" UserId="15954" Comment="Added a warning" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out a normalized `{a,b,c}` as an output. &#xD;&#xA;Then I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;I am in a similar situation than [the person aksing this question][2] except that he seems to know already what needs be done and is just asking &#xD;&#xA;about if his rationale is good.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;EDIT : The answer below is valid considering how I framed my problem but note that if you were like me trying to compute a camera to world rotation matrix and expected the viewport of your camera to follow along, you need an additional step because the answer below only gives you a shear matrix. In order to get a rotation matrix you need to comput the `upVector` with `normalize(cross_product(rightVector, forwardVector))` and feed its coordinates into the matrix instead of `{0,1,0}`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/10613/transforming-a-ray-from-camera-space-to-world-space?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="31419" PostHistoryTypeId="2" PostId="10769" RevisionGUID="f2b6bdae-0b7d-41f8-b01d-c592ca8234a0" CreationDate="2021-03-22T19:00:12.677" UserId="7724" Text="The cube-like mesh shown in the images is a non-manifold mesh. Officially half edge data structures do not support such a topology. However, this case can be supported by continuing the boundary half edges through the non-manifold node. This is apparently the way it is done in 3DS Max, and also Blender. You can look at [this][1] article for several extension to the data structure to support non-manifold meshes. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm" ContentLicense="CC BY-SA 4.0" />
  <row Id="31420" PostHistoryTypeId="5" PostId="10762" RevisionGUID="541e5554-48c3-4383-8aa9-4d1b1925da43" CreationDate="2021-03-23T11:40:45.263" UserId="15954" Comment="added 25 characters in body" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out a normalized `{a,b,c}` as an output. &#xD;&#xA;Then I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;I am in a similar situation than [the person aksing this question][2] except that he seems to know already what needs be done and is just asking &#xD;&#xA;about if his rationale is good.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;EDIT : The answer below is valid considering how I framed my problem but note that if you were like me trying to compute a camera to world rotation matrix and expected the viewport of your camera to follow along, you need an additional step because the answer below only gives you a shear matrix. In order to get a rotation matrix you need to comput the `upVector` with `normalize(cross_product(rightVector, forwardVector))` (in a right hand system) and feed its coordinates into the matrix instead of `{0,1,0}`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/10613/transforming-a-ray-from-camera-space-to-world-space?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="31422" PostHistoryTypeId="50" PostId="9616" RevisionGUID="edfc86b1-1222-48d8-9a19-59791bc1d73a" CreationDate="2021-03-23T19:02:10.223" UserId="-1" />
  <row Id="31423" PostHistoryTypeId="2" PostId="10771" RevisionGUID="296ee8d4-49c3-439c-850e-5cb177a2ada5" CreationDate="2021-03-23T19:21:18.920" UserId="15976" Text="I have successfully completed a working program that draw a rotating sphere with a map of the world as the texture, simulating the earth in space.  However, the texture is bound on it's side, i.e. all the continents are on their sides and the poles are shown as the sphere spins on the y-axis.  I used the following reference to build the rotating sphere:&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_sphere.html#:~:text=In%20order%20to%20draw%20the,triangle%20strip%20cannot%20be%20used.&#xD;&#xA;&#xD;&#xA;and the stb_image library (https://github.com/nothings/stb) to load a JPEG image for the texture.&#xD;&#xA;&#xD;&#xA;I've tried a couple of things like:&#xD;&#xA;actual rotation of the JPEG image, &#xD;&#xA;rotating the array that holds the texture coordinates, &#xD;&#xA;rotating the array that holds the indices&#xD;&#xA;&#xD;&#xA;Everything is good apart from the orientation of the image bound for texturing.  Any advice/pointers would be appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="31424" PostHistoryTypeId="1" PostId="10771" RevisionGUID="296ee8d4-49c3-439c-850e-5cb177a2ada5" CreationDate="2021-03-23T19:21:18.920" UserId="15976" Text="How can I bind my texture in the correct orientation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31425" PostHistoryTypeId="3" PostId="10771" RevisionGUID="296ee8d4-49c3-439c-850e-5cb177a2ada5" CreationDate="2021-03-23T19:21:18.920" UserId="15976" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31426" PostHistoryTypeId="2" PostId="10772" RevisionGUID="b5dbf02e-a4cd-4d7b-b9ef-7f8063ceaf18" CreationDate="2021-03-23T22:39:33.557" UserId="7952" Text="Binding the image is unrelated to its orientation. A shot in the dark is that your texture coordinates are either reversed or computed with the orientation in the wrong direction. You could just rotate the image as a work around. The main issue here is whether the upper left corner is your origin, or the lower left corner is the origin. But neither of these explain the image being sideways. At any rate, look at your texture coordinates, how the image is being copied into memory, how is is being passed to opengl, and the texture coordinates." ContentLicense="CC BY-SA 4.0" />
  <row Id="31427" PostHistoryTypeId="5" PostId="10762" RevisionGUID="5133aabf-623c-4c61-999e-87662aa28efa" CreationDate="2021-03-23T22:57:56.140" UserId="15954" Comment="added 1 character in body" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambettta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out a normalized `{a,b,c}` as an output. &#xD;&#xA;Then I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;I am in a similar situation than [the person aksing this question][2] except that he seems to know already what needs be done and is just asking &#xD;&#xA;about if his rationale is good.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;EDIT : The answer below is valid considering how I framed my problem but note that if you were like me trying to compute a camera to world rotation matrix and expected the viewport of your camera to follow along, you need an additional step because the answer below only gives you a shear matrix. In order to get a rotation matrix you need to compute the `upVector` with `normalize(cross_product(rightVector, forwardVector))` (in a right hand system) and feed its coordinates into the matrix instead of `{0,1,0}`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/10613/transforming-a-ray-from-camera-space-to-world-space?rq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="31431" PostHistoryTypeId="4" PostId="10201" RevisionGUID="8a46b8e1-f1de-4d1b-9333-55ee397c75b4" CreationDate="2021-03-24T00:44:01.010" UserId="6281" Comment="edited title" Text="How should the texture file look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31432" PostHistoryTypeId="2" PostId="10774" RevisionGUID="1b1ec948-1fdc-4945-b803-fb6be4e79034" CreationDate="2021-03-24T02:44:42.290" UserId="15978" Text="I'd like to know if the following technology already exists, and if not, how feasible it would be to create something like this:&#xD;&#xA;&#xD;&#xA;I came up with an idea for creating a higher-res image that is put together from multiple lower-res images.  More specifically, from a video (animated, multiple frames) source.  The best way to explain it would be to explain what would happen using an example:&#xD;&#xA;&#xD;&#xA;Let's say that there's video footage from a security camera of a van driving by.  The van has a logo on it.  Based on the entire video (using all applicable frames to gather data), object recognition code is used to recognize that an object has moved in the video.  Using the raster data in the frames along with the object recognition, a vector is generated that represents the moving object.  Interpolation can be used to show where this object is during all timeslices, including those between frames.  So for example, if played in slow motion, you would see (just for example's sake) a vector rectangle moving along with the van's logo (let's say the logo is rectangular just to make the example simpler to conceptualize).  As the frames play by one at a time, the rectangle smoothly follows the logo, always matching the location of the logo in each frame, but smoothly moving between those locations between the rendering of each frame, yet always matching the location of the logo when each frame actually shows up (let's say we play it at 1fps, to better imagine what's happening).  This interpolation would allow for the tracking of the object based on limited data (frame rates can't be infinite, so picking any timestamp between the frames would allow interpolation to determine where that logo would be between the frames, based on the motion that the frames depict).&#xD;&#xA;&#xD;&#xA;Having explained the situation above, now let's apply the general idea of the interpolation but in a different way..&#xD;&#xA;&#xD;&#xA;The rectangular vector is split up into a grid.  This grid can represent a raster image.  However, its resolution would be higher than that of the video's resolution - the higher-res more-detailed version of the logo that we're trying to capture.  So now, let's build the high-res logo...&#xD;&#xA;&#xD;&#xA;Finding the first frame of the video in which the logo is visible, each pixel of the higher-res logo is filled in based on the pixels of the logo in the video's frame.  When processing the first frame, the resulting higher-res logo looks the same as the logo in the frame.  The only difference is that it looks like a blown-up pixelized version of the logo in the frame.  So far, no 'enhancement' is done.&#xD;&#xA;&#xD;&#xA;However, as we go further frame-by-frame, we now have some extra data to work with.  Even though the video has limited resolution, with each pixel representing a blend of all the colors within its bounds, the fact that its motion is being tracked allows each subsequent frame's representation of the logo to slightly add some more detail to the higher-res logo.  Since the location of the logo as it's moving across the video is interpolated, the higher-res pixel grid can be placed between pixels (using floating-point coordinates), as it's able to determine a more exact placement of where the logo is, beyond the resolution of the video.&#xD;&#xA;&#xD;&#xA;With each subsequent frame, the visible pixels of the logo gradually add more and more detail to the higher-res logo, eventually making it look less and less pixelized.  With enough video footage of the moving logo, it could be possible to eventually generate a much more detailed version of the logo than any one of the frames can individually provide.&#xD;&#xA;&#xD;&#xA;I hope that my explanation of this tech was sufficient to provide an idea of what I'm trying to describe.  You may have to extrapolate and interpolate this imaginary concept in your mind and intuitively fill in some details (similar to what this tech attempts to do), to fully conceptualize how this tech would work.&#xD;&#xA;&#xD;&#xA;Having explained it, I'd like to know if something like this exists.  If it does, what is this kind of technology called?  And if it doesn't, how difficult would it be to create something like it?  I imagine that utilizing machine learning would make it even more effective in filling in details.&#xD;&#xA;&#xD;&#xA;If you've read this far, thank you for your time.  I'd like to know what you think." ContentLicense="CC BY-SA 4.0" />
  <row Id="31433" PostHistoryTypeId="1" PostId="10774" RevisionGUID="1b1ec948-1fdc-4945-b803-fb6be4e79034" CreationDate="2021-03-24T02:44:42.290" UserId="15978" Text="Building a higher-res detailed image from a video" ContentLicense="CC BY-SA 4.0" />
  <row Id="31434" PostHistoryTypeId="3" PostId="10774" RevisionGUID="1b1ec948-1fdc-4945-b803-fb6be4e79034" CreationDate="2021-03-24T02:44:42.290" UserId="15978" Text="|image-processing|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31438" PostHistoryTypeId="5" PostId="10763" RevisionGUID="c3a72445-11bb-4a50-836a-f71a975e9bca" CreationDate="2021-03-25T14:25:17.253" UserId="13095" Comment="appended answer 10770 as supplemental" Text="Good evening!&#xD;&#xA;I would like a help to understand the following line of code:&#xD;&#xA;&#xD;&#xA;    return float3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));&#xD;&#xA;&#xD;&#xA;I've seen some places calling it gamma correction, but I don't know if it's correct.&#xD;&#xA;&#xD;&#xA;If it really is a gamma correction how does it work?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;[![No Correction][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![With Correction][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fnpRg.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ggIev.jpg&#xD;&#xA;With Correction&#xD;&#xA;&#xD;&#xA;I liked the artistic result of this, I will keep it. I asked the question to understand better. Thank you all!" ContentLicense="CC BY-SA 4.0" />
  <row Id="31440" PostHistoryTypeId="2" PostId="10776" RevisionGUID="9acff6f0-4cc3-49a0-ac61-4d9bcaf039cc" CreationDate="2021-03-25T14:36:40.860" UserId="15999" Text="I am an amateur game developer, and I've been reading a lot on how computer graphics rendering works lately. I was reading on the Z-buffer recently and I can't quite seem to be able to wrap my head around what exactly the Z-buffer looks like in terms of memory. It's described to contain depth information for each fragment that will be drawn on-screen, and that modern Z-buffers have 32-bits, so would that mean that on a, let's say, 1920x1080 screen it'd be just above 8MB (1920 * 1080 * 32) per frame?&#xD;&#xA;&#xD;&#xA;I still don't quite understand what this value would be to a GPU (maybe it can crunch it easily), or if this value is even correct. Most demostrative implementations I found implement the Z-buffer as a simple array with size (height * width), so I'm basing myself off of that. " ContentLicense="CC BY-SA 4.0" />
  <row Id="31441" PostHistoryTypeId="1" PostId="10776" RevisionGUID="9acff6f0-4cc3-49a0-ac61-4d9bcaf039cc" CreationDate="2021-03-25T14:36:40.860" UserId="15999" Text="What does the z-buffer like in memory?" ContentLicense="CC BY-SA 4.0" />
  <row Id="31442" PostHistoryTypeId="3" PostId="10776" RevisionGUID="9acff6f0-4cc3-49a0-ac61-4d9bcaf039cc" CreationDate="2021-03-25T14:36:40.860" UserId="15999" Text="|performance|memory|buffers|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31443" PostHistoryTypeId="2" PostId="10777" RevisionGUID="10ae0ac5-7a19-4ecc-ac29-b62c2ff96e23" CreationDate="2021-03-25T17:38:40.677" UserId="7952" Text="The Z buffer used to be specialized memory set aside for a single purpose, some web sites still explain it like that, but no longer.&#xD;&#xA;&#xD;&#xA;Now the Z buffer is just a chunk of memory you allocate, or an API like OpenGL allocates on your behalf.&#xD;&#xA;&#xD;&#xA;The size of that chunk of memory will depend on the type of the Z buffer values, in the example you gave it is a 32bit [floating point] values, but 24 bits is also very common. Always choose the smallest size the program needs as it can have a large effect on the performance of the application. It is indeed multiplied by the size of framebuffer so 8mb is correct for the example you gave.&#xD;&#xA;&#xD;&#xA;The values that get stored in it are the depth values for any geometry drawn to the associated framebuffer. It is important to realize that these values are NOT the linear values of the MVP matrix computed in the vertex shader so the Z buffer can not be used for things like shadow maps.&#xD;&#xA;&#xD;&#xA;Fragments resulting from each draw call have their depth values tested against existing values in the Z buffer and if the test passes the GPU will write that fragment and update the Z buffer with the new value, if not the fragment gets discarded and the Z buffer is left untouched.&#xD;&#xA;&#xD;&#xA;A few other little details:&#xD;&#xA;&#xD;&#xA;The Z buffer is generally cleared at the beginning of each frame with a clear value that can be set (or must be set) via the API. This becomes the default value that writes to the Z buffer are tested against.&#xD;&#xA;&#xD;&#xA;GPU's have specialized hardware for writing the Z buffer, this hardware can speed up writing to memory by a factor of 2 or more and can be leveraged when creating things like shadow maps, so it is not limited for use with just the Z buffer.&#xD;&#xA;&#xD;&#xA;Depth testing can be turned off/on for each draw call, which can be useful.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31444" PostHistoryTypeId="2" PostId="10778" RevisionGUID="58de1228-ded6-4034-be79-103436d1a2b5" CreationDate="2021-03-25T19:35:39.463" UserId="16001" Text="I hope this is the right forum to ask this question.&#xD;&#xA;&#xD;&#xA;I want to experiment with procedurally generating some buildings, and as a first step I want to generate a 2D shape to use as a foundation for the building.&#xD;&#xA;&#xD;&#xA;My plan would be to create a union of an arbitrary (but probably quite small) amount of shapes.&#xD;&#xA;It seems simple enough, but I wonder what algorithms there are available for breaking up such a union into simple line shapes? (that can be used to place walls)" ContentLicense="CC BY-SA 4.0" />
  <row Id="31445" PostHistoryTypeId="1" PostId="10778" RevisionGUID="58de1228-ded6-4034-be79-103436d1a2b5" CreationDate="2021-03-25T19:35:39.463" UserId="16001" Text="getting the outline of an arbitrary set of shape unions" ContentLicense="CC BY-SA 4.0" />
  <row Id="31446" PostHistoryTypeId="3" PostId="10778" RevisionGUID="58de1228-ded6-4034-be79-103436d1a2b5" CreationDate="2021-03-25T19:35:39.463" UserId="16001" Text="|algorithm|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="31450" PostHistoryTypeId="2" PostId="10780" RevisionGUID="a5daa21b-af7e-4573-919d-2e4cac87ec6d" CreationDate="2021-03-26T18:24:17.893" UserId="10129" Text="My problem is exactly what titles and screenshot below says - rendered object depth value is 0.0 in depth buffer. I'm using DirectX 12.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Matrices:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;    // VS code&#xD;&#xA;    PixelInputType main(VertexInputType input)&#xD;&#xA;    {&#xD;&#xA;    	PixelInputType output;&#xD;&#xA;    	&#xD;&#xA;    	float4 position = float4(input.position, 1.0f);&#xD;&#xA;    	position = mul(position, g_worldMatrix);&#xD;&#xA;    	position = mul(position, g_viewMatrix);&#xD;&#xA;    	position = mul(position, g_projMatrix);&#xD;&#xA;    	output.position = position;&#xD;&#xA;&#xD;&#xA;    	return output;&#xD;&#xA;    }&#xD;&#xA;    // PS code&#xD;&#xA;    float4 main(PixelInputType input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;    	return float4(g_texture.Sample(g_sampler, input.uv).rgb, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am rendering single object for now, so world matrix is just identity matrix.&#xD;&#xA;Regarding view/proj matrix - they're updated each frame and saved to the CB:&#xD;&#xA;&#xD;&#xA;    void Renderer::CreateViewAndPerspective()&#xD;&#xA;    {&#xD;&#xA;        const DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.f);&#xD;&#xA;        constexpr float conv{ 0.0174532925f };&#xD;&#xA;    &#xD;&#xA;        // Create the rotation matrix from the yaw, pitch, and roll values.&#xD;&#xA;        const XMMATRIX rotationMatrix = XMMatrixRotationRollPitchYaw(m_cameraRotation.x * conv, m_cameraRotation.y * conv, m_cameraRotation.z * conv);&#xD;&#xA;    &#xD;&#xA;        const DirectX::XMVECTOR eye = DirectX::XMVectorSet(m_cameraPosition.x, m_cameraPosition.y, m_cameraPosition.z, 0.0f);&#xD;&#xA;    &#xD;&#xA;        //Setup target (look at object position)&#xD;&#xA;        XMVECTOR target = XMVector3TransformCoord(DirectX::XMVECTOR{ 0, 0, 1, 0 }, rotationMatrix);&#xD;&#xA;        target = XMVector3Normalize(target);&#xD;&#xA;        target = { m_cameraPosition.x + target.m128_f32[0], m_cameraPosition.y + target.m128_f32[1], m_cameraPosition.z + target.m128_f32[2], 0.0f };  &#xD;&#xA;    &#xD;&#xA;        //Create view matrix&#xD;&#xA;        m_constantBuffer.value.view = DirectX::XMMatrixTranspose(DirectX::XMMatrixLookAtLH(eye, target, up));&#xD;&#xA;    &#xD;&#xA;        //Create perspective matrix&#xD;&#xA;        constexpr float FOV = 3.14f / 4.0f;&#xD;&#xA;        float aspectRatio = m_windowSize.x / m_windowSize.y /* 1280 x 720 */;&#xD;&#xA;        m_constantBuffer.value.projection = DirectX::XMMatrixTranspose(DirectX::XMMatrixPerspectiveFovLH(FOV, aspectRatio, Z_NEAR /* 0.5f */, Z_FAR /* 100.0f */));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jTTnm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Gcfrh.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="31451" PostHistoryTypeId="1" PostId="10780" RevisionGUID="a5daa21b-af7e-4573-919d-2e4cac87ec6d" CreationDate="2021-03-26T18:24:17.893" UserId="10129" Text="Objects in depth buffer are always black (0.0)" ContentLicense="CC BY-SA 4.0" />
  <row Id="31452" PostHistoryTypeId="3" PostId="10780" RevisionGUID="a5daa21b-af7e-4573-919d-2e4cac87ec6d" CreationDate="2021-03-26T18:24:17.893" UserId="10129" Text="|directx12|camera-matrix|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32454" PostHistoryTypeId="5" PostId="10780" RevisionGUID="cea10ab0-be95-4614-b6bd-59a7357af466" CreationDate="2021-03-27T09:44:28.127" UserId="10129" Comment="Add details of depth buffer implementation" Text="My problem is exactly what titles and screenshot below says - rendered object depth value is 0.0 in depth buffer. I'm using DirectX 12.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Matrices:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;    // VS code&#xD;&#xA;    PixelInputType main(VertexInputType input)&#xD;&#xA;    {&#xD;&#xA;    	PixelInputType output;&#xD;&#xA;    	&#xD;&#xA;    	float4 position = float4(input.position, 1.0f);&#xD;&#xA;    	position = mul(position, g_worldMatrix);&#xD;&#xA;    	position = mul(position, g_viewMatrix);&#xD;&#xA;    	position = mul(position, g_projMatrix);&#xD;&#xA;    	output.position = position;&#xD;&#xA;&#xD;&#xA;    	return output;&#xD;&#xA;    }&#xD;&#xA;    // PS code&#xD;&#xA;    float4 main(PixelInputType input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;    	return float4(g_texture.Sample(g_sampler, input.uv).rgb, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am rendering single object for now, so world matrix is just identity matrix.&#xD;&#xA;Regarding view/proj matrix - they're updated each frame and saved to the CB:&#xD;&#xA;&#xD;&#xA;    void Renderer::CreateViewAndPerspective()&#xD;&#xA;    {&#xD;&#xA;        const DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.f);&#xD;&#xA;        constexpr float conv{ 0.0174532925f };&#xD;&#xA;    &#xD;&#xA;        // Create the rotation matrix from the yaw, pitch, and roll values.&#xD;&#xA;        const XMMATRIX rotationMatrix = XMMatrixRotationRollPitchYaw(m_cameraRotation.x * conv, m_cameraRotation.y * conv, m_cameraRotation.z * conv);&#xD;&#xA;    &#xD;&#xA;        const DirectX::XMVECTOR eye = DirectX::XMVectorSet(m_cameraPosition.x, m_cameraPosition.y, m_cameraPosition.z, 0.0f);&#xD;&#xA;    &#xD;&#xA;        //Setup target (look at object position)&#xD;&#xA;        XMVECTOR target = XMVector3TransformCoord(DirectX::XMVECTOR{ 0, 0, 1, 0 }, rotationMatrix);&#xD;&#xA;        target = XMVector3Normalize(target);&#xD;&#xA;        target = { m_cameraPosition.x + target.m128_f32[0], m_cameraPosition.y + target.m128_f32[1], m_cameraPosition.z + target.m128_f32[2], 0.0f };  &#xD;&#xA;    &#xD;&#xA;        //Create view matrix&#xD;&#xA;        m_constantBuffer.value.view = DirectX::XMMatrixTranspose(DirectX::XMMatrixLookAtLH(eye, target, up));&#xD;&#xA;    &#xD;&#xA;        //Create perspective matrix&#xD;&#xA;        constexpr float FOV = 3.14f / 4.0f;&#xD;&#xA;        float aspectRatio = m_windowSize.x / m_windowSize.y /* 1280 x 720 */;&#xD;&#xA;        m_constantBuffer.value.projection = DirectX::XMMatrixTranspose(DirectX::XMMatrixPerspectiveFovLH(FOV, aspectRatio, Z_NEAR /* 0.5f */, Z_FAR /* 100.0f */));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;Edit: Depth buffer implementation details below (full code - https://github.com/komilll/YARE/blob/main/YARE/Renderer.cpp#L131 ):&#xD;&#xA;&#xD;&#xA;    // Create DSV&#xD;&#xA;    D3D12_DESCRIPTOR_HEAP_DESC desc{};&#xD;&#xA;    desc.NumDescriptors = 1;&#xD;&#xA;    desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;&#xD;&#xA;    desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;&#xD;&#xA;    device-&gt;CreateDescriptorHeap(&amp;desc, IID_PPV_ARGS(&amp;heap));&#xD;&#xA;&#xD;&#xA;    // Create Depth Stencil&#xD;&#xA;    D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};&#xD;&#xA;    depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT;&#xD;&#xA;    depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;&#xD;&#xA;    depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;&#xD;&#xA;    &#xD;&#xA;    D3D12_CLEAR_VALUE depthOptimizedClearValue = {};&#xD;&#xA;    depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;&#xD;&#xA;    depthOptimizedClearValue.DepthStencil.Depth = 1.0f;&#xD;&#xA;    depthOptimizedClearValue.DepthStencil.Stencil = 0;&#xD;&#xA;    &#xD;&#xA;    ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;        &amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),&#xD;&#xA;        D3D12_HEAP_FLAG_NONE,&#xD;&#xA;        &amp;CD3DX12_RESOURCE_DESC::Tex2D(format, width, height, 1, 0, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),&#xD;&#xA;        D3D12_RESOURCE_STATE_DEPTH_WRITE,&#xD;&#xA;        &amp;depthOptimizedClearValue,&#xD;&#xA;        IID_PPV_ARGS(&amp;depthStencil)&#xD;&#xA;    ));&#xD;&#xA;    &#xD;&#xA;    device-&gt;CreateDepthStencilView(depthStencil.Get(), &amp;depthStencilDesc, dsvHeap-&gt;GetCPUDescriptorHandleForHeapStart());&#xD;&#xA;&#xD;&#xA;    /* ... */&#xD;&#xA;    // Usage of DSV&#xD;&#xA;    const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };&#xD;&#xA;    m_commandList-&gt;ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);&#xD;&#xA;    m_commandList-&gt;ClearDepthStencilView(m_dsvHeap-&gt;GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);&#xD;&#xA;    m_commandList-&gt;IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);&#xD;&#xA;    m_commandList-&gt;IASetVertexBuffers(0, 1, &amp;m_modelSphere-&gt;GetVertexBufferView());&#xD;&#xA;    m_commandList-&gt;DrawInstanced(m_modelSphere-&gt;GetIndicesCount(), 1, 0, 0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jTTnm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Gcfrh.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32458" PostHistoryTypeId="2" PostId="10782" RevisionGUID="26c6fd03-ff3a-4371-9b6b-86b59179d98d" CreationDate="2021-03-27T19:28:31.723" UserId="7952" Text="Draw it twice, first time at full size and the color you want for the outline, draw it filled. The second time you draw it scaled down in both the x and y directions. The second time you draw it the color is the same as the background color, and draw it filled again. What will be left is the outline. Is this what you had in mind?&#xD;&#xA;&#xD;&#xA;You can get more elaborate with the stencil buffer if needed." ContentLicense="CC BY-SA 4.0" />
  <row Id="32459" PostHistoryTypeId="5" PostId="10762" RevisionGUID="a1c303d8-8545-4d66-9bf4-1fb2dfeb6e16" CreationDate="2021-03-28T11:21:10.310" UserId="5778" Comment="typos corrected" Text="So I am making a raytracer following the very helpful [online book of Gabriel Gambetta][1] but I stumble on the rotation matrix part. &#xD;&#xA;&#xD;&#xA;My linear algebra background is 3Blue1Brown video series &quot;The essence of Linear Algebra&quot;.&#xD;&#xA;&#xD;&#xA;I simulate a camera placed at the origin that's looking forward ie whose direction is the vector `{0,0,1}`. &#xD;&#xA;Let's say I am given another camera direction with direction `{a,b,c}`. &#xD;&#xA;From what I understand if I find the rotation matrix R that takes as an input `{0,0,1}` and spits out a normalized `{a,b,c}` as an output. &#xD;&#xA;Then I can apply that rotation matrix to all my rays in order to rotate them. &#xD;&#xA;I can't get my head around on how to find R. Any help/explanation/correction much welcome.&#xD;&#xA;&#xD;&#xA;I am in a similar situation than [the person asking this question][2] except that he seems to know already what needs be done and is just asking &#xD;&#xA;about if his rationale is good.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;EDIT : The answer below is valid considering how I framed my problem but note that if you were like me trying to compute a camera to world rotation matrix and expected the viewport of your camera to follow along, you need an additional step because the answer below only gives you a shear matrix. In order to get a rotation matrix you need to compute the `upVector` with `normalize(cross_product(rightVector, forwardVector))` (in a right hand system) and feed its coordinates into the matrix instead of `{0,1,0}`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gabrielgambetta.com/computer-graphics-from-scratch/05-extending-the-raytracer.html&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/questions/10613/transforming-a-ray-from-camera-space-to-world-space" ContentLicense="CC BY-SA 4.0" />
  <row Id="32460" PostHistoryTypeId="24" PostId="10762" RevisionGUID="a1c303d8-8545-4d66-9bf4-1fb2dfeb6e16" CreationDate="2021-03-28T11:21:10.310" Comment="Proposed by 5778 approved by 13095 edit id of 557" ContentLicense="CC BY-SA 4.0" />
  <row Id="32463" PostHistoryTypeId="4" PostId="10776" RevisionGUID="972d86f4-02f5-4616-8b28-740f6b461248" CreationDate="2021-03-29T10:34:48.240" UserId="209" Comment="Fixed title" Text="What does the z-buffer look like in memory?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32464" PostHistoryTypeId="2" PostId="10783" RevisionGUID="d5a7e583-b494-4850-a06f-908cef5b732b" CreationDate="2021-03-29T11:00:01.550" UserId="209" Text="&gt; Most demostrative[SIC] implementations I found implement the Z-buffer as a simple array with size (height * width), so I'm basing myself off of that.&#xD;&#xA;&#xD;&#xA;I suspect a purely linear (i.e., scanline-by-scanline) arrangement for the Z-buffer, at least for HW systems, is unlikely as that would tend to lead to a *lot* of DRAM &quot;[page-break][1]s&quot;. This is because each triangle tends to get rendered in its entirety, which means that as you go from one scanline of pixels to the next, the memory addresses are likely to jump dramatically. &#xD;&#xA;&#xD;&#xA;Tiled/Morton(Twiddled) layouts for the Z-buffer are probably more likely (along with a more tile-based rendering order.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.anandtech.com/show/3851/everything-you-always-wanted-to-know-about-sdram-memory-but-were-afraid-to-ask/5" ContentLicense="CC BY-SA 4.0" />
  <row Id="32465" PostHistoryTypeId="5" PostId="10782" RevisionGUID="0dc3b4a6-7ed2-47ae-9b35-992ffd38511c" CreationDate="2021-03-29T14:47:10.593" UserId="7952" Comment="added 963 characters in body" Text="Draw it twice, first time at full size and the color you want for the outline, draw it filled. The second time you draw it scaled down in both the x and y directions. The second time you draw it the color is the same as the background color, and draw it filled again. What will be left is the outline. Is this what you had in mind?&#xD;&#xA;&#xD;&#xA;Per your comment, I add more info:&#xD;&#xA;&#xD;&#xA;Generating an array of exterior edges can be done in a few ways. The easiest one to implement (but also the slowest) is to count the number polygons that share a given edge. The exterior is all the edges which only have a single polygon using that edge. And the two vertices that make up that edge become part of the array of &quot;lines&quot;( an actual line can be computed from two vertices). Also, this will count &quot;holes&quot; as part of the exterior. For example if a building surrounds a courtyard, then the courtyard would be counted as exterior.&#xD;&#xA;&#xD;&#xA;This can be implemented by creating an array of unique vertices, then each polygon is formed by indexing into the list. (just like indexed triangle draw lists). Finally pick a single polygon off the list, takes its first edge, and search all the other polygons for that edge. &#xD;&#xA;&#xD;&#xA;Another method using a doubly connected edge list is given [here][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/26103138/find-the-outline-of-adjacent-polygons" ContentLicense="CC BY-SA 4.0" />
  <row Id="32467" PostHistoryTypeId="2" PostId="10784" RevisionGUID="dbe785a0-f4a1-45cb-96be-56b7a9fe5d2c" CreationDate="2021-03-29T15:38:56.660" UserId="16024" Text="I wrote a program to render a simple triangle with colors, the triangle is there but there's no color.&#xD;&#xA;```&#xD;&#xA;GLfloat vertices[] = {&#xD;&#xA;        0.6f,0.4f , 0.3f,0.5f, 0.1f,0.3f, 0.8f,0.2f, 0.1f,-0.4f, 0.9f,0.3f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    unsigned int program;&#xD;&#xA;    if (!loadShader(program))&#xD;&#xA;        return -1;&#xD;&#xA;&#xD;&#xA;    unsigned int VAO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    &#xD;&#xA;    unsigned int buffer;&#xD;&#xA;    /* GENERATE THE BUFFER (1 BUUFER) */&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /* SELECT THAT BUFFER TO WORK WITH */&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;&#xD;&#xA;    //glBufferData(GL_ARRAY_BUFFER, RealPositions.size()*sizeof(float), RealPositions.data(), GL_STATIC_DRAW);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;    /* Loop until the user closes the window */&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;    {&#xD;&#xA;        /* Render here */&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;        glUseProgram(program);&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(VAO);&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;&#xD;&#xA;        /* Swap front and back buffers */&#xD;&#xA;        glfwSwapBuffers(window);&#xD;&#xA;&#xD;&#xA;        /* Poll for and process events */&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;and this the vertex shader:&#xD;&#xA;```&#xD;&#xA;#version 440&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 vertices;&#xD;&#xA;layout (location = 1) in vec3 vertex_color;&#xD;&#xA;out vec3 vs_color;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	gl_Position=vec4(vertices, 1.f);&#xD;&#xA;	vs_color=vertex_color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;```&#xD;&#xA;#version 440&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 vertices;&#xD;&#xA;layout (location = 1) in vec3 vertex_color;&#xD;&#xA;out vec3 vs_color;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	gl_Position=vec4(vertices, 1.f);&#xD;&#xA;	vs_color=vertex_color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;what am i doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32468" PostHistoryTypeId="1" PostId="10784" RevisionGUID="dbe785a0-f4a1-45cb-96be-56b7a9fe5d2c" CreationDate="2021-03-29T15:38:56.660" UserId="16024" Text="rendering a triangle has no color" ContentLicense="CC BY-SA 4.0" />
  <row Id="32469" PostHistoryTypeId="3" PostId="10784" RevisionGUID="dbe785a0-f4a1-45cb-96be-56b7a9fe5d2c" CreationDate="2021-03-29T15:38:56.660" UserId="16024" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32472" PostHistoryTypeId="2" PostId="10785" RevisionGUID="210873eb-1bf1-414d-b766-2cafb7405a8d" CreationDate="2021-03-29T17:56:03.480" UserId="10703" Text="According to the source (https://github.com/assimp/assimp/blob/b7df376836e36c4b6998ce95d97626e30f61c2f0/code/AssetLib/Obj/ObjFileImporter.cpp#L594) only illum values of 0, 1, 2 are supported:&#xD;&#xA;&#xD;&#xA;        // convert illumination model&#xD;&#xA;        int sm = 0;&#xD;&#xA;        switch (pCurrentMaterial-&gt;illumination_model) {&#xD;&#xA;        case 0:&#xD;&#xA;            sm = aiShadingMode_NoShading;&#xD;&#xA;            break;&#xD;&#xA;        case 1:&#xD;&#xA;            sm = aiShadingMode_Gouraud;&#xD;&#xA;            break;&#xD;&#xA;        case 2:&#xD;&#xA;            sm = aiShadingMode_Phong;&#xD;&#xA;            break;&#xD;&#xA;        default:&#xD;&#xA;            sm = aiShadingMode_Gouraud;&#xD;&#xA;            ASSIMP_LOG_ERROR(&quot;OBJ: unexpected illumination model (0-2 recognized)&quot;);&#xD;&#xA;        }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32473" PostHistoryTypeId="50" PostId="7804" RevisionGUID="52454edd-3ee4-4fb0-a3ed-4d00b0f11f8f" CreationDate="2021-03-29T18:03:50.400" UserId="-1" />
  <row Id="32475" PostHistoryTypeId="2" PostId="10786" RevisionGUID="f1dfc874-270a-44cb-a8a1-794e988c7106" CreationDate="2021-03-30T00:52:26.677" UserId="16028" Text="I am trying to transfer some mocap data from one skeleton to another one. However, the skeletons have different rest poses (one has T-pose, and the other some other one), so I am trying to convert the euler angles from being relative to one rest pose to another. I have the relative transform between the second skeleton and a T-pose in Unity. The issue is that Unity uses a different angle convention to Blender/BVH, and I really cannot figure it out.&#xD;&#xA;&#xD;&#xA;Trying to debug this, I've isolated one point of confusion, which is what I'm mainly asking about here. You can see [in this video](https://streamable.com/80nyoj) that for all joints up to the spine3, changing the X Euler angle, rotates arond X, but after the collar joints, changing the X Euler angle, it rotates around some other axis (even though all of its parents have near 0 rotation). I don't understand why this would be. Anyone could explain this?&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="32476" PostHistoryTypeId="1" PostId="10786" RevisionGUID="f1dfc874-270a-44cb-a8a1-794e988c7106" CreationDate="2021-03-30T00:52:26.677" UserId="16028" Text="Understanding rig joint angle definitions in Blender" ContentLicense="CC BY-SA 4.0" />
  <row Id="32477" PostHistoryTypeId="3" PostId="10786" RevisionGUID="f1dfc874-270a-44cb-a8a1-794e988c7106" CreationDate="2021-03-30T00:52:26.677" UserId="16028" Text="|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32478" PostHistoryTypeId="5" PostId="10784" RevisionGUID="48a1c758-fdbf-4c37-b119-554548bab098" CreationDate="2021-03-30T09:09:34.177" UserId="16024" Comment="deleted 67 characters in body" Text="I wrote a program to render a simple triangle with colors, the triangle is there but there's no color.&#xD;&#xA;```&#xD;&#xA;GLfloat vertices[] = {&#xD;&#xA;        0.6f,0.4f , 0.3f,0.5f, 0.1f,0.3f, 0.8f,0.2f, 0.1f,-0.4f, 0.9f,0.3f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    unsigned int program;&#xD;&#xA;    if (!loadShader(program))&#xD;&#xA;        return -1;&#xD;&#xA;&#xD;&#xA;    unsigned int VAO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    &#xD;&#xA;    unsigned int buffer;&#xD;&#xA;    /* GENERATE THE BUFFER (1 BUUFER) */&#xD;&#xA;    glGenBuffers(1, &amp;buffer);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    /* SELECT THAT BUFFER TO WORK WITH */&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, buffer);&#xD;&#xA;&#xD;&#xA;    //glBufferData(GL_ARRAY_BUFFER, RealPositions.size()*sizeof(float), RealPositions.data(), GL_STATIC_DRAW);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;    glBindVertexArray(0);&#xD;&#xA;    /* Loop until the user closes the window */&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;    {&#xD;&#xA;        /* Render here */&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;        glUseProgram(program);&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;        glBindVertexArray(VAO);&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;&#xD;&#xA;        /* Swap front and back buffers */&#xD;&#xA;        glfwSwapBuffers(window);&#xD;&#xA;&#xD;&#xA;        /* Poll for and process events */&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;and this the vertex shader:&#xD;&#xA;```&#xD;&#xA;#version 440&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec3 vertices;&#xD;&#xA;layout (location = 1) in vec3 vertex_color;&#xD;&#xA;out vec3 vs_color;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	gl_Position=vec4(vertices, 1.f);&#xD;&#xA;	vs_color=vertex_color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;and this is the fragment shader:&#xD;&#xA;```&#xD;&#xA;#version 440 core  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;in vec4 vs_pos;&#xD;&#xA;in vec3 vs_color;&#xD;&#xA;out vec4 fs_color;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;	fs_color=vec4(vs_color, 1.f);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;what am i doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32479" PostHistoryTypeId="50" PostId="9626" RevisionGUID="c4e5bfa6-8e5e-440a-a991-ff925201175f" CreationDate="2021-03-30T13:02:00.210" UserId="-1" />
  <row Id="32480" PostHistoryTypeId="2" PostId="10787" RevisionGUID="d68558e2-ab47-4733-b13d-9d9647ee5162" CreationDate="2021-03-30T13:32:41.910" UserId="7952" Text="Your inputs and outputs still don't line up.&#xD;&#xA;&#xD;&#xA;    #version 440 core  &#xD;&#xA;&#xD;&#xA;    // Comment out the line below&#xD;&#xA;    // in vec4 vs_pos;    &lt;----- No corresponding output in the vertex shader&#xD;&#xA;    in vec3 vs_color; &#xD;&#xA;   &#xD;&#xA;    out vec4 fs_color;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        fs_color=vec4(vs_color, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The gl_Position output is consumed and does not need a specific input in the fragment shader. Only variable declared as &quot;out&quot; in the vertex shader need a corresponding &quot;in&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="32481" PostHistoryTypeId="5" PostId="10787" RevisionGUID="6cf6c1f7-593b-45f9-9aed-b390bddf7e45" CreationDate="2021-03-30T15:49:05.843" UserId="7952" Comment="added 573 characters in body" Text="Your inputs and outputs still don't line up.&#xD;&#xA;&#xD;&#xA;    #version 440 core  &#xD;&#xA;&#xD;&#xA;    // Comment out the line below&#xD;&#xA;    // in vec4 vs_pos;    &lt;----- No corresponding output in the vertex shader&#xD;&#xA;    in vec3 vs_color; &#xD;&#xA;   &#xD;&#xA;    out vec4 fs_color;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        fs_color=vec4(vs_color, 1.f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The gl_Position output is consumed and does not need a specific input in the fragment shader. Only variable declared as &quot;out&quot; in the vertex shader need a corresponding &quot;in&quot;.&#xD;&#xA;&#xD;&#xA;The next issue is the vertices need to have colors in them. The way it is setup now all the components are consumed before even a single triangle is drawn.&#xD;&#xA;&#xD;&#xA;The vertex buffer needs to be setup:&#xD;&#xA;vertex,color, vertex,color, vertex,color&#xD;&#xA;&#xD;&#xA;where each vertex and color has 3 floating point values.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    GLfloat vertices[] = {&#xD;&#xA;&#xD;&#xA;    //    vertex           color&#xD;&#xA;    -0.5f, -0.5f, 0.0f,  1.0f,0.0f,0.0f&#xD;&#xA;     0.5f, -0.5f, 0.0f,  0.0f,1.0f,0.0f&#xD;&#xA;     0.0f,  0.5f, 0.0f,  0.0f,0.0f,1.0f &#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Something like the above. Is what you need for the vertices.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32485" PostHistoryTypeId="50" PostId="9307" RevisionGUID="02e00684-c275-491f-a071-5083dd574fd8" CreationDate="2021-03-30T19:06:10.587" UserId="-1" />
  <row Id="32488" PostHistoryTypeId="2" PostId="10789" RevisionGUID="6a759fee-d74d-46e9-9878-f31bff9a1862" CreationDate="2021-03-30T23:00:06.150" UserId="15860" Text="https://superrare.co/artwork-v2/spring-22267&#xD;&#xA;&#xD;&#xA;The artwork in the link seems to be based on a painting of a woman, but effects have been added that assign a pixel to each block of the painting that shift in color and contrast across a certain number of frames as part of a gif animation, although the original painting itself doesn't move underneath. &#xD;&#xA;&#xD;&#xA; - is there a name for this effect?&#xD;&#xA; - and could someone breifly outline the steps of how it can be achieved&#xD;&#xA;   in software?&#xD;&#xA; - any popular examples where this effect is used or first introduced?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32489" PostHistoryTypeId="1" PostId="10789" RevisionGUID="6a759fee-d74d-46e9-9878-f31bff9a1862" CreationDate="2021-03-30T23:00:06.150" UserId="15860" Text="What is the name of this moving color pixels effect, for animating a painting?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32490" PostHistoryTypeId="3" PostId="10789" RevisionGUID="6a759fee-d74d-46e9-9878-f31bff9a1862" CreationDate="2021-03-30T23:00:06.150" UserId="15860" Text="|color|animation|pixels|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32491" PostHistoryTypeId="2" PostId="10790" RevisionGUID="15843a19-2c6f-4743-bd16-adc6c81e1a69" CreationDate="2021-03-30T23:57:37.173" UserId="506" Text="It looks like it’s based on a [halftone](https://en.wikipedia.org/wiki/Halftone) technique, with the grid warped using a few sine waves. Not sure about how the colors are being assigned, but there’s some kind of [quantization](https://en.wikipedia.org/wiki/Color_quantization) going on." ContentLicense="CC BY-SA 4.0" />
  <row Id="32493" PostHistoryTypeId="2" PostId="10791" RevisionGUID="81ad4f1f-72dc-4fce-8497-00bc9f5981f7" CreationDate="2021-03-31T05:29:02.207" UserId="15434" Text="[This](https://learnopengl.com/PBR/IBL/Specular-IBL) is the website I am learning from.&#xD;&#xA;&#xD;&#xA;In the specular part of IBL this is the split sum approximation&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now the left part of the equation I have asked in  [This](https://computergraphics.stackexchange.com/questions/10659/pbr-understanding-importance-sampling/10663#10663) post and I have understood everything now this question is about the right part.&#xD;&#xA;&#xD;&#xA;On simplifying the right part of the equation with the procedure shown in the website we get this &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And on translating this to code we get this &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YhB0C.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/WiOBt.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/zb0ZG.jpg&#xD;&#xA;&#xD;&#xA;I have so many questions about this code.&#xD;&#xA;&#xD;&#xA;1)What is the V vector? How did they compute that&#xD;&#xA;&#xD;&#xA;2)Why have they assumed N=(0,0,1)?&#xD;&#xA;&#xD;&#xA;3)why is NDotL=max(L.z,0)? How did they simplifying a dot product to an min/max Operation same question I have for NDotH&#xD;&#xA;&#xD;&#xA;4)G_Vis=G*VDoth/(NDotH*NDotL) why the division by (NDOTH*NDOTL)? that was nowhere in the equation.&#xD;&#xA;&#xD;&#xA;5)what is vector L? it looks like they have reflected vector V about H to get this but why?&#xD;&#xA;&#xD;&#xA;These are just some of the questions I have come up with so far but if there are any other important parts I should not know about A general explanation on how they derived this code would be appreciated" ContentLicense="CC BY-SA 4.0" />
  <row Id="32494" PostHistoryTypeId="1" PostId="10791" RevisionGUID="81ad4f1f-72dc-4fce-8497-00bc9f5981f7" CreationDate="2021-03-31T05:29:02.207" UserId="15434" Text="PBR : Understanding the right part of Split sum integration of specular IBL" ContentLicense="CC BY-SA 4.0" />
  <row Id="32495" PostHistoryTypeId="3" PostId="10791" RevisionGUID="81ad4f1f-72dc-4fce-8497-00bc9f5981f7" CreationDate="2021-03-31T05:29:02.207" UserId="15434" Text="|pbr|specular|integral|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32497" PostHistoryTypeId="2" PostId="10792" RevisionGUID="f5297eb0-787f-40f9-bb89-01dd40542185" CreationDate="2021-03-31T19:25:32.110" UserId="10129" Text="That's how I used to initialize viewport (CD3DX12_VIEWPORT). But I didn't realize that there are two additional fields *minDepth* and *maxDepth*. Therefore, I have min/max depth set to 0.0 and objects rendered to depth buffer are always black:&#xD;&#xA;&#xD;&#xA;    m_viewport.TopLeftY = 0.0f;&#xD;&#xA;    m_viewport.TopLeftX = 0.0f;&#xD;&#xA;    m_viewport.Width = static_cast&lt;float&gt;(m_windowSize.x);&#xD;&#xA;    m_viewport.Height = static_cast&lt;float&gt;(m_windowSize.y);&#xD;&#xA;&#xD;&#xA;Fixed that by simply using constructor which default *minDepth* to 0.0 and *maxDepth* to 1.0:&#xD;&#xA;&#xD;&#xA;    m_viewport = CD3DX12_VIEWPORT{ 0.0f, 0.0f, static_cast&lt;float&gt;(m_windowSize.x), static_cast&lt;float&gt;(m_windowSize.y) };&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32498" PostHistoryTypeId="2" PostId="10793" RevisionGUID="52356594-63ec-43fe-82a6-dd7e6c8a40e8" CreationDate="2021-04-01T08:12:56.073" UserId="9420" Text="This is often referred to as &quot;[Color Cycling][1]&quot; or &quot;Palette Shifting&quot;. Mark Ferrari has a great [GDC talk][2] where he demonstrates and explains the entire technique. You can view a bunch of his artwork based on this technique [here][3].&#xD;&#xA;&#xD;&#xA;The main idea is that each pixel is painted not with a single color, but as values of a look-up table to a palette of colors. The entire image then cycles through the palettes frame by frame. Assigning colors to each palette to create the illusion of movement requires a fair bit of artistry. Mark Ferrari does this in a software called Pro Motion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_cycling&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=aMcJ1Jvtef0&#xD;&#xA;  [3]: http://www.effectgames.com/demos/canvascycle/" ContentLicense="CC BY-SA 4.0" />
  <row Id="32499" PostHistoryTypeId="5" PostId="10793" RevisionGUID="36cfd341-5640-4237-a16d-c4288b7bc199" CreationDate="2021-04-01T08:18:22.163" UserId="9420" Comment="deleted 9 characters in body" Text="This effect is called [Color Cycling][1] (or Palette Shifting). Mark Ferrari has a great [GDC talk][2] where he demonstrates and explains the entire technique. You can view a bunch of his artwork based on this technique [here][3].&#xD;&#xA;&#xD;&#xA;The main idea is that each pixel is painted not with a single color, but as values of a look-up table to a palette of colors. The entire image then cycles through the palettes frame by frame. Assigning colors to each palette to create the illusion of movement requires a fair bit of artistry. Mark Ferrari does this in a software called Pro Motion, but this can be coded in a shader pretty easily.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_cycling&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=aMcJ1Jvtef0&#xD;&#xA;  [3]: http://www.effectgames.com/demos/canvascycle/" ContentLicense="CC BY-SA 4.0" />
  <row Id="32500" PostHistoryTypeId="2" PostId="10794" RevisionGUID="e27587b1-66af-4298-afe0-517b5c80bc8c" CreationDate="2021-04-01T12:34:35.677" UserId="16070" Text="I was trying to understand what exactly is 'binding'. I found an [answer on quora](https://www.quora.com/What-is-binding-in-graphics) on this. From this, binding basically sounds like sending data from to GPU with help from CPU. I got to know more about 'bindless' things as there is something called bindless textures in OpenGL. But how does GPU access the data in this case? &#xD;&#xA;&#xD;&#xA;[NVIDIA article](https://www.nvidia.com/en-us/drivers/bindless-graphics/) on bindless graphics talks about how the driver does not need to &#xD;&#xA;&#xD;&#xA;&gt; dereference a vertex buffer or constant buffer on the CPU in order for&#xD;&#xA;&gt; the GPU to use it.&#xD;&#xA;&#xD;&#xA;in the case of bindless graphics.&#xD;&#xA;&#xD;&#xA;So is this dereferencing thing the major difference? How does this help in hugely speeding up the application?&#xD;&#xA;&#xD;&#xA;In a nutshell, what is the difference between graphics using binding and 'bindless' graphics?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32501" PostHistoryTypeId="1" PostId="10794" RevisionGUID="e27587b1-66af-4298-afe0-517b5c80bc8c" CreationDate="2021-04-01T12:34:35.677" UserId="16070" Text="Binding vs bindless" ContentLicense="CC BY-SA 4.0" />
  <row Id="32502" PostHistoryTypeId="3" PostId="10794" RevisionGUID="e27587b1-66af-4298-afe0-517b5c80bc8c" CreationDate="2021-04-01T12:34:35.677" UserId="16070" Text="|gpu|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32503" PostHistoryTypeId="2" PostId="10795" RevisionGUID="fe31bc60-2f30-4518-8894-de7a5066a6fb" CreationDate="2021-04-01T14:09:50.977" UserId="2654" Text="When a shader accesses a resource (buffer or texture), it needs some information about that resource to be able to do so correctly. On a modern GPU, that information will generally just be some kind of number. It could be something as simple as a GPU virtual memory address (with the particular details of what kind of resource is being used defined by the shading language), or it may be an index into a table of resources.&#xD;&#xA;&#xD;&#xA;But all modern GPUs need is a number.&#xD;&#xA;&#xD;&#xA;From the CPU side, a resource is defined by some API-defined object. To bind a resource (API-agnosticly) means that you tell the API that you want to state that the given API object's resource will be used by the shader through some resource binding location.&#xD;&#xA;&#xD;&#xA;This process therefore requires the API to take that object and convert it into the number that the shader will receive. The object itself cannot just be that integer because the API needs ancillary information for managing the resource. But when you're *rendering* with the resource, the integer is all you really need.&#xD;&#xA;&#xD;&#xA;So let's say you're rendering a complex scene. You may be rendering 100,000 different objects. That could mean 100,000 different binding operations per-frame. Each bind operation has to dereference an object pointer and fetch a single 64-bit integer from the object behind that pointer. And often, the nature of the API object requires *multiple* dereferences to get this integer.&#xD;&#xA;&#xD;&#xA;This is not a cache-friendly operation, as you're fetching a piece of data from storage that has a bunch of *unrelated* data near it. So not only is the read likely to be a cache-miss, you're doing a whole memory fetch for *just* 64-bits of data, that will not be used for anything else before that cache line gets evicted. This represents poor cache coherency.&#xD;&#xA;&#xD;&#xA;Across 100,000 objects at 60fps (or greater), that can add up.&#xD;&#xA;&#xD;&#xA;A bindless API allows the user to store the integer themselves and marshal it to the shader in whatever way they see fit. Any resource integers for an object's rendering call can be stored near other data that is relevant to the rendering process, thus improving cache coherency.&#xD;&#xA;&#xD;&#xA;It should also be noted that a bindless API means that any shader could access any information about any object, so long as it has been given access to the integers that represent those resources. This is rather important when doing something like ray-tracing.&#xD;&#xA;&#xD;&#xA;So it's not *just* about performance." ContentLicense="CC BY-SA 4.0" />
  <row Id="32504" PostHistoryTypeId="2" PostId="10796" RevisionGUID="6a7424c5-123d-4ac2-9fa6-173a2e3102a3" CreationDate="2021-04-01T15:32:46.370" UserId="15860" Text="[https://foundation.app/mg/20210227-3lau-makes-history-1790][1]&#xD;&#xA;&#xD;&#xA;The link above shows a video animation that has a rainbow wave distortion effect applied to it, that ripples across the video. how, and in which software, can this effect be applied to a video? or a step-by-step guess on how to replicate the effect&#xD;&#xA;&#xD;&#xA;  [1]: https://foundation.app/mg/20210227-3lau-makes-history-1790" ContentLicense="CC BY-SA 4.0" />
  <row Id="32505" PostHistoryTypeId="1" PostId="10796" RevisionGUID="6a7424c5-123d-4ac2-9fa6-173a2e3102a3" CreationDate="2021-04-01T15:32:46.370" UserId="15860" Text="Animated rainbow distortion wave effect" ContentLicense="CC BY-SA 4.0" />
  <row Id="32506" PostHistoryTypeId="3" PostId="10796" RevisionGUID="6a7424c5-123d-4ac2-9fa6-173a2e3102a3" CreationDate="2021-04-01T15:32:46.370" UserId="15860" Text="|color|animation|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32507" PostHistoryTypeId="5" PostId="10795" RevisionGUID="1a660cb9-0404-4c4b-9730-b55f2b01d687" CreationDate="2021-04-01T16:20:03.943" UserId="2654" Comment="deleted 24 characters in body" Text="When a shader accesses a resource (buffer or texture), it needs some information about that resource to be able to do so correctly. On a modern GPU, that information will generally just be some kind of number. It could be something as simple as a GPU virtual memory address (with the particular details of what kind of resource is being used defined by the shading language), or it may be an index into a table of resources.&#xD;&#xA;&#xD;&#xA;But all modern GPUs need is a number.&#xD;&#xA;&#xD;&#xA;From the CPU side, a resource is defined by some API-defined object. To bind a resource (API-agnosticly) means that you tell the API that you the given API object's resource to used by the shader through some resource binding location.&#xD;&#xA;&#xD;&#xA;This process therefore requires the API to take that object and convert it into the number that the shader will receive. The object itself cannot just be that integer because the API needs ancillary information for managing the resource. But when you're *rendering* with the resource, the integer is all you really need.&#xD;&#xA;&#xD;&#xA;So let's say you're rendering a complex scene. You may be rendering 100,000 different objects. That could mean 100,000 different binding operations per-frame. Each bind operation has to dereference an object pointer and fetch a single 64-bit integer from the object behind that pointer. And often, the nature of the API object requires *multiple* dereferences to get this integer.&#xD;&#xA;&#xD;&#xA;This is not a cache-friendly operation, as you're fetching a piece of data from storage that has a bunch of *unrelated* data near it. So not only is the read likely to be a cache-miss, you're doing a whole memory fetch for *just* 64-bits of data, that will not be used for anything else before that cache line gets evicted. This represents poor cache coherency.&#xD;&#xA;&#xD;&#xA;Across 100,000 objects at 60fps (or greater), that can add up.&#xD;&#xA;&#xD;&#xA;A bindless API allows the user to store the integer themselves and marshal it to the shader in whatever way they see fit. Any resource integers for an object's rendering call can be stored near other data that is relevant to the rendering process, thus improving cache coherency.&#xD;&#xA;&#xD;&#xA;It should also be noted that a bindless API means that any shader could access any information about any object, so long as it has been given access to the integers that represent those resources. This is rather important when doing something like ray-tracing.&#xD;&#xA;&#xD;&#xA;So it's not *just* about performance." ContentLicense="CC BY-SA 4.0" />
  <row Id="32508" PostHistoryTypeId="2" PostId="10797" RevisionGUID="ea2690e0-6756-4567-afd3-a148e9d35e36" CreationDate="2021-04-01T17:10:12.950" UserId="506" Text="The effect is called [chromatic aberration](https://en.wikipedia.org/wiki/Chromatic_aberration); the way it’s usually done in games, and what’s being done there, is by reading the red / green / blue channels of an image at different offset positions. As with your [other question](https://computergraphics.stackexchange.com/questions/10789/what-is-the-name-of-this-moving-color-pixels-effect-for-animating-a-painting) (you’re looking to get into the NFT market, I’m guessing?), there are most likely plugins for After Effects that will let you create something along these lines, but the original author probably used a tool like Processing or Shadertoy." ContentLicense="CC BY-SA 4.0" />
  <row Id="32509" PostHistoryTypeId="2" PostId="10798" RevisionGUID="1fa5fd0a-a90d-4f62-a67d-031e42d2001f" CreationDate="2021-04-01T18:42:11.127" UserId="10129" Text="I'm still a junior when it comes to computer graphics so you may want to take my opinion with a grain of salt:&#xD;&#xA;&#xD;&#xA;To start with - I used to learn/implement stuff using website that you've sent (OpenGL) and I don't recommend that. After few months of learning I knew barely anything. Then I start reading original papers and implementing them on my own to better understand PBR, what N * G * F means in Cook-Torrance shading model and I got much better understanding of basics. I was recommend by many graphics programmers to avoid tutorial pages and straight read and implement papers. In case if you don't understand something in the paper you're reading, you found paper on subject that you don't understand and read about it.&#xD;&#xA;&#xD;&#xA;1). As I said - avoid this site or use only to get interesting papers - here are original notes from [Karis2013] UE4 presentation - https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf ; Please notice comment &quot;/sin&quot; &quot;/cos&quot; in listing at page 7 and usage of *Pythagorean trigonometric identity*. Maybe it's position on the hemishpere, I don't really want to dig in, I'm sorry. But I would recommend checking Epic Games repository on Github if you want to see how they're using it.&#xD;&#xA;&#xD;&#xA;2.) In the same paper [Karis2013] there is listing at the page 4. and function **ImportanceSampleGGX**. It uses N to determine orientation of the world and returns either float3(0,0,1) or float3(1,0,0) based on N.z value.&#xD;&#xA;&#xD;&#xA;3).&#xD;&#xA;$$N = (0, 0, 1)$$&#xD;&#xA;$$L = (x, y, z)$$ &#xD;&#xA;$$ dot(N, L) = (0 * x, 0 * y, 1 * z) = (0, 0, z) = L.z$$&#xD;&#xA;&#xD;&#xA;4). &#xD;&#xA;http://jcgt.org/published/0003/02/03/paper.pdf#page=30&#xD;&#xA;&#xD;&#xA;http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;&#xD;&#xA;https://www.microsoft.com/en-us/research/wp-content/uploads/1977/01/p192-blinn.pdf&#xD;&#xA;&#xD;&#xA;These links might be helpful to understand BRDF better. Why there are strange division? I don't know, it's probably due to optimization, I don't know what NDF is being used. However, what happens here is you're multiplying D and G component, so you can do split multiplication with Fresnel. It doesn't matter how you write it. You can just create function NDF_GGX(...) and multiply it by G, add pdf and it'll work the same. &#xD;&#xA;You can take a look at modern UE4 code - https://github.com/EpicGames/UnrealEngine/blob/2bf1a5b83a7076a0fd275887b373f8ec9e99d431/Engine/Shaders/Private/AmbientCubemapComposite.usf#L255 to understand it better. That's why I'm saying to write your own code. I would say that [Karis2013] is omitting a lot of code and uses many optimizations without saying WHY.&#xD;&#xA;&#xD;&#xA;5). It's just light direction. When you already calculated V and H, it is easy to get L by using reflection. Take a look at the picture here - https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model#Description" ContentLicense="CC BY-SA 4.0" />
  <row Id="32510" PostHistoryTypeId="50" PostId="9178" RevisionGUID="c0a7a06c-fa81-4297-a0b0-d33251dd1ea5" CreationDate="2021-04-02T01:00:55.120" UserId="-1" />
  <row Id="32515" PostHistoryTypeId="2" PostId="10800" RevisionGUID="e6b581e8-d643-40aa-973f-7e07d7df2741" CreationDate="2021-04-02T12:52:47.157" UserId="7952" Text="All of these projections fall under the generic group of projections called &quot;Axonometric&quot; projections. The general goal of an axonometric projection is to manipulate the object using rotations and translations such that at least three adjacent faces of the projected object are shown. The result is projected from the center at infinity onto one of the coordinate planes usually the Z=0 plane. There are three common types of axonometric projections, trimetric, dimetric and isometric. With trimetric being the most general, dimetric is a specialization of trimetric with two of the three foreshortening factors being equal to each other, and isometric is a specialization of dimetric with the third foreshortening factor set equal to the other two (so all three are equal). Also note that the projection plane in this case is the Z plane. The matrix show below can be modified to use any of the X, Y or Z planes as the projection plane.&#xD;&#xA;&#xD;&#xA;The general matrix form of all three (since dimetric and isometric are specializations of trimetric) is:&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; &amp;cos\phi   &amp;sin\phi sin\theta  &amp;0 &amp;0 \\ &#xD;&#xA; &amp;0  &amp;cos\theta  &amp;0 &amp;0 \\ &#xD;&#xA; &amp;sin\phi  &amp;-cos\phi sin\theta  &amp;0 &amp;0 \\ &#xD;&#xA; &amp;0  &amp;0  &amp;0 &amp;1 &#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;Where phi is the rotation around the y axis and theta is the rotation around the x axis. The foreshortening length of each axis can be computed just by taking the sum of the squares of each row. Then take the square root to get the length. For the X axis this would be:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;f_{x}^{2} = cos^{2}\phi + sin^{2}\phi sin^{2}\theta&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;A little bit of algebra will yield the values needed to compute the lengths of the other 2.&#xD;&#xA;&#xD;&#xA;To determine a trimetric projection all we need are the two viewing angles. For a diametric or isometric view we need to set the foreshortening factors equal to either two or three of the axis. By using the lengths of the rows and setting them equal to one another then solving we can compute any of the values needed for either projection.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32516" PostHistoryTypeId="2" PostId="10801" RevisionGUID="7690caaa-8052-4ee2-9992-99dd2a2fe2cd" CreationDate="2021-04-02T17:13:45.617" UserId="15860" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Some underlying portrait above is glazed over with a series of vertical lines that neatly follow the contours of the face. What is this effect called and how can it be replicated, step-by-step, in Adobe Photoshop or other software? plus, how can the gap between the lines be controlled? &#xD;&#xA;&#xD;&#xA;Also is the color scheme due to chromatic aberration, or just simple RGB channel separation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8ZOxz.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="32517" PostHistoryTypeId="1" PostId="10801" RevisionGUID="7690caaa-8052-4ee2-9992-99dd2a2fe2cd" CreationDate="2021-04-02T17:13:45.617" UserId="15860" Text="What is this vertical line contour effect in glitch art called?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32518" PostHistoryTypeId="3" PostId="10801" RevisionGUID="7690caaa-8052-4ee2-9992-99dd2a2fe2cd" CreationDate="2021-04-02T17:13:45.617" UserId="15860" Text="|line-drawing|photometric|color-separation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32519" PostHistoryTypeId="5" PostId="10100" RevisionGUID="3ca2a8a5-9d86-410b-94fa-87fe8bbd4548" CreationDate="2021-04-02T22:06:37.853" UserDisplayName="user5681" Comment="deleted 411 characters in body" Text="First, it is important to observe that there are basically two different &quot;classes&quot; of methods for building accelerations structures for ray tracing: 1) space subdivision methods (e.g. BSP, kD-Tree, Octree, etc.); and 2) object subdivision methods (e.g. BVH). While space subdivison methods work by recursively subdividing the *space* with planes, without sticking to the geometry embedded into that space, object subdivison methods work by subdividing the geometry recursively into smaller and smaller parts, wrapping each part with a, usually tight, volume. More on the basics of space and object subdivision that can be found in the [PBRT v3 online book][1].&#xD;&#xA;&#xD;&#xA;Each method (space or object sudivision) has its own pros and cons. In the case of space subdivision methods, since the subspaces do not overlap, we can usually traverse the structure in front-to-back, or back-to-front, order more easily. When a ray is traversing such structure, as soon as it hits a surface, we can stop the traversal. This usually leads to faster traversal schemes. Several software renderers take advantage of the traversal efficiency given by the space subdivision schemes. On the other hand, space subdivision schemes may be more intricate to implement (usually you have to tweak some epsilons) and may lead to deeper trees. Also, they do not like very much dynamic geometry. If the geometry encoded into a space subdivision acceleration structure changes, we usually have to rebuild the acceleration structure from scratch. &#xD;&#xA;&#xD;&#xA;Object subdivision methods have quite different characteristics. Since the object is subdivided with volumes, and these volumes may overlap, the traversal is traditionally slower. We cannot, for instance, stop traversing a BVH as soon as a ray finds an intersection with a surface. Since the volumes overlap, we may need to check for potential intersections with nearby primitives before quitting the traversal. On the other hand, it may be easier to implement a BVH because we do not have to *split* the object parts with planes. Also, BVHs usually generate shallower structures (which may eventually compensate the slower traversal). However, one of the most interesting aspects of the BVHs is that they are *dynamic geometry*-friendly. If geometry changes (but not much, actually), we can simply locally adjust the size and position of the corresponding bounding volume (i.e. refitting). These adjustments may cause the need to adjust the parent volumes, a procedure that may culminate in a *chain reaction* that may reach the root node of the BVH. All in all, assuming that we have a reasonably balanced BVH, these operations will be ~O(log n), which is really fast and cool.&#xD;&#xA;&#xD;&#xA;The above paragraph describes the traditional characteristics of the BVHs. There is currently lots of research going on on the topic, and several of its ineficiencies have been significantly reduced over time. It should be noted, for instance, that still in 2007, [Wald, Boulos and Shirley][2] have designed a very efficient BVH-based acceleration structure, for interactive ray tracing on GPUs, that rivals with space subdivision schemes such as kD-Trees. This work was very influential.&#xD;&#xA;&#xD;&#xA;Actually there are several reasons that make the BVHs the preferred acceleration data structure for interactive ray tracing o GPUs. According to [Wodniok and Goesele][3], the main factors that have turned the BVH into a popular acceleration structure in the context of GPU ray tracing are its &quot;*memory footprint (...) efficient empty space cut-off, fast construction, and simple update procedure (...) while (...) offering similar (...) performance as kD-Trees*&quot;. Regarding fast BVH reconstruction, it may be interesting to take a look at the LBVH, by [Lauterbach *et. al.*][4], the HLBVH, by [Pantaleoni&#xD;&#xA;and Luebke][5], and the one by [Karras and Aila][6], that are capable to rebuild BVHs iteractively. Overlapping impacts the traversal procedure efficiency because, when a ray hit the overlap, it has to be tested against the two child nodes. SBVHs, by [Stich et. al.][6] is a hybrid structure that employs both spatial and object subdivisions such that overlap is reduced. The cons, according to the paper, are the fact that SBVH does not handle dynamic scenes anymore, and that it may increase memory consumption up to 30%. The SBVH building procedure, also, is not as fast as for the regular BVHs.&#xD;&#xA;&#xD;&#xA;The current [NVidia RTX GPUs support the traditional BVH, the SBVH and Karras/Aila acceleration structure][7]. As pointed out and detailed by [@DirectX_Programmer, in his answer below][8], these structures are actually combined, by the RTX drivers, into a more flexible arrangement composed by two levels. &#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Primitives_and_Intersection_Acceleration.html&#xD;&#xA;  [2]: https://dl.acm.org/doi/10.1145/1189762.1206075&#xD;&#xA;  [3]: https://www.sciencedirect.com/science/article/pii/S0097849316301376?casa_token=D0jTp_c1HngAAAAA:YCD31gt1rp4zR8wzE20vTxIEXAJR83pOZh0Bp_saqZChzCHOfgKwu0W7N0jT9dJGCvKjAVTdsQ&#xD;&#xA;  [4]: https://onlinelibrary.wiley.com/doi/full/10.1111/j.1467-8659.2009.01377.x?casa_token=s3kaFgXZt38AAAAA%3Ar1tdA-tx8aAclVsQeLTh8oUR5XDgEgI-twjAhezqDUWmBm8W2AaL8OzD0KU9s0EfZN5DHZFWHB8gZXM&#xD;&#xA;  [5]: https://research.nvidia.com/sites/default/files/pubs/2010-06_HLBVH-Hierarchical-LBVH/HLBVH-final.pdf&#xD;&#xA;  [6]: https://www.nvidia.in/docs/IO/77714/sbvh.pdf&#xD;&#xA;  [7]: https://raytracing-docs.nvidia.com/optix/guide/nvidia_optix_programming_guide.180313.A4.pdf&#xD;&#xA;  [8]: https://computergraphics.stackexchange.com/a/10106/5681" ContentLicense="CC BY-SA 4.0" />
  <row Id="32520" PostHistoryTypeId="2" PostId="10802" RevisionGUID="612c458a-f14c-423c-b419-e88d21706b85" CreationDate="2021-04-02T22:09:15.727" UserId="15955" Text="Good Morning. I'm testing Path Tracing techniques with unity, following this tutorial.&#xD;&#xA;http://three-eyed-games.com/2019/03/18/gpu-path-tracing-in-unity-part-3/&#xD;&#xA;But I'm in trouble.&#xD;&#xA;&#xD;&#xA;Whenever I try to run the compute shader it crashes the system.&#xD;&#xA;&#xD;&#xA;I was erasing some lines and found that the problem happens when I try to change the values ​​of the hit.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        void IntersectMeshObject(int index, CameraRay ray, inout CameraRayHit bestHit)&#xD;&#xA;    {&#xD;&#xA;        int offset = _Objects[index].indices_offset;&#xD;&#xA;        int count = offset + _Objects[index].indices_count;&#xD;&#xA;    &#xD;&#xA;        for (int i = offset; i &lt; count; i += 3)&#xD;&#xA;        {&#xD;&#xA;           float3 v0 = (mul(_Objects[index].localToWorldMatrix, float4(_Vertices[_Indices[i]], 1))).xyz;&#xD;&#xA;           float3 v1 = (mul(_Objects[index].localToWorldMatrix, float4(_Vertices[_Indices[i + 1]], 1))).xyz;&#xD;&#xA;           float3 v2 = (mul(_Objects[index].localToWorldMatrix, float4(_Vertices[_Indices[i + 2]], 1))).xyz;&#xD;&#xA;    &#xD;&#xA;           float t, u, v;&#xD;&#xA;    &#xD;&#xA;            if (IntersectTriangle(ray, v0, v1, v2, t, u, v))&#xD;&#xA;            {&#xD;&#xA;                if (t &gt; 0 &amp;&amp; t &lt; bestHit.rayHitDistance)&#xD;&#xA;                {&#xD;&#xA;                    bestHit.rayHitDistance = t; //&lt;--That makes it crash&#xD;&#xA;                    bestHit.rayHitPosition = ray.raySource + t * ray.rayDirection;//&lt;--That makes it crash&#xD;&#xA;                    bestHit.rayHitNormal = float3(0.0f, 1.0f, 0.0f);//&lt;--That makes it crash&#xD;&#xA;    &#xD;&#xA;                    bestHit.viewDirection = normalize(_WorldSpaceCameraPos - bestHit.rayHitPosition);//&lt;--That makes it crash&#xD;&#xA;                    bestHit.lightDirection = _DirectionalLightDirection;//&lt;--That makes it crash&#xD;&#xA;    &#xD;&#xA;                    bestHit.rayHitAlbedo = float4(0.6, 0.6, 0.6, 1);//&lt;--That makes it crash&#xD;&#xA;                    bestHit.rayHitEmission = float4(0, 0, 0, 0);//&lt;--That makes it crash&#xD;&#xA;                    bestHit.rayHitSmoothness = 0.6;//&lt;--That makes it crash&#xD;&#xA;                    bestHit.rayHitMetallic = 0.6;//&lt;--That makes it crash&#xD;&#xA;                    bestHit.rayHitAnisotropy = 0;//&lt;--That makes it crash&#xD;&#xA;    &#xD;&#xA;                    bestHit.hitRenderType = 0;//&lt;--That makes it crash&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When executing only with sphere hits&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VJMFZ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xnMVu.jpg&#xD;&#xA;&#xD;&#xA;When I leave the if without instructions it works normally.&#xD;&#xA;&#xD;&#xA;All codes:&#xD;&#xA;https://gist.github.com/MatheusMarkies/3a334b97d3ee4330c335143e496ded67&#xD;&#xA;&#xD;&#xA;Can someone help me find out where the problem is?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32521" PostHistoryTypeId="1" PostId="10802" RevisionGUID="612c458a-f14c-423c-b419-e88d21706b85" CreationDate="2021-04-02T22:09:15.727" UserId="15955" Text="Unity path tracing faz o pc crash Unity path tracing makes the pc crash" ContentLicense="CC BY-SA 4.0" />
  <row Id="32522" PostHistoryTypeId="3" PostId="10802" RevisionGUID="612c458a-f14c-423c-b419-e88d21706b85" CreationDate="2021-04-02T22:09:15.727" UserId="15955" Text="|raytracing|pathtracing|compute-shader|hlsl|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32525" PostHistoryTypeId="2" PostId="10803" RevisionGUID="d4ec8bc0-0add-406a-8939-dce69d7c2b75" CreationDate="2021-04-03T12:48:46.983" UserId="11077" Text="Seems like a simple problem, but I just cant wrap my head around it.&#xD;&#xA;&#xD;&#xA;I have a config file in which I declare a few functions. It looks like this:&#xD;&#xA;&#xD;&#xA;    &quot;bandDefinitions&quot; : [&#xD;&#xA;        {&#xD;&#xA;            &quot;0&quot;: [&quot;x^2 + 2*x + 5 - y&quot;, &quot;ABOVE&quot;]&#xD;&#xA;        },&#xD;&#xA;        {&#xD;&#xA;            &quot;0&quot;: [&quot;sin(6*x) - y&quot;, &quot;UNDER&quot;]&#xD;&#xA;        },&#xD;&#xA;        {&#xD;&#xA;            &quot;0&quot;: [&quot;tan(x) - y&quot;, &quot;ABOVE&quot;]&#xD;&#xA;        }&#xD;&#xA;    ]&#xD;&#xA;&#xD;&#xA;These functions should generate 3 images. Every image should be filled depending on solution of equations, and provided position (Under or Above). I need to move the coordinate system to the center of the image, so I'm adding `-y` into the equation. Part of image which should be filled should be colored white, and the other part should be colored black.&#xD;&#xA;&#xD;&#xA;To explain what I mean, I'm providing images for quadratic and sin functions.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![sin][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/17nU8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/aMeOh.png&#xD;&#xA;&#xD;&#xA;What I'm doing is solve the equation for `x in [-W/2, W/2]` and store the solutions into the array, like this:&#xD;&#xA;&#xD;&#xA;    #Generates X axis dots and solves an expression which defines a band&#xD;&#xA;    #Coordinate system is moved to the center of the image&#xD;&#xA;    def __solveKernelDefinition(self, f):&#xD;&#xA;        xAxis = range(-kernelSize, kernelSize)&#xD;&#xA;        dots = []&#xD;&#xA;&#xD;&#xA;        for x in xAxis:&#xD;&#xA;            sol = f(x, kernelSize/2)&#xD;&#xA;            dots.append(sol)&#xD;&#xA;&#xD;&#xA;        print(dots)&#xD;&#xA;        return dots&#xD;&#xA;&#xD;&#xA;I'm testing if some pixel should be colored white like this:&#xD;&#xA;&#xD;&#xA;    def shouldPixelGetNoise(y, x, i, currentBand):&#xD;&#xA;        shouldGetNoise = True&#xD;&#xA;&#xD;&#xA;        for bandKey in currentBand.bandDefinition.keys():&#xD;&#xA;            if shouldGetNoise:&#xD;&#xA;                pixelSol = currentBand.bandDefinition[bandKey][2](x, y)&#xD;&#xA;                renderPos = currentBand.bandDefinition[bandKey][1]&#xD;&#xA;                bandSol = currentBand.bandDefinition[bandKey][0]&#xD;&#xA;                shouldGetNoise = shouldGetNoise and pixelSol &lt;= bandSol[i] if renderPos == Position.UNDER else pixelSol &gt;= bandSol[i]&#xD;&#xA;            else:&#xD;&#xA;                break&#xD;&#xA;&#xD;&#xA;        return shouldGetNoise&#xD;&#xA;&#xD;&#xA;    def kernelNoise(kernelSize, num_octaves, persistence, currentBand, dimensions=2):&#xD;&#xA;        simplex = SimplexNoise(num_octaves, persistence, dimensions)&#xD;&#xA;        data = []&#xD;&#xA;&#xD;&#xA;        for i in range(kernelSize):&#xD;&#xA;            data.append([])&#xD;&#xA;            i1 = i - int(kernelSize / 2)&#xD;&#xA;&#xD;&#xA;            for j in range(kernelSize):&#xD;&#xA;                j1 = j - int(kernelSize / 2)&#xD;&#xA;                if(shouldPixelGetNoise(i1, j1, i, currentBand)):&#xD;&#xA;                    noise = normalize(simplex.fractal(i, j, hgrid=kernelSize))&#xD;&#xA;                    data[i].append(noise * 255)&#xD;&#xA;                else:&#xD;&#xA;                    data[i].append(0)&#xD;&#xA;&#xD;&#xA;I'm only getting good output for convex quadratic functions. If I try to combine them, I get a black image. `Sin` just doesn't work at all. I see that this bruteforce approach won't lead me anywhere, so I was wondering what algorithm should I use to generate these kinds of images?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32526" PostHistoryTypeId="1" PostId="10803" RevisionGUID="d4ec8bc0-0add-406a-8939-dce69d7c2b75" CreationDate="2021-04-03T12:48:46.983" UserId="11077" Text="Filling pixels under or above some function" ContentLicense="CC BY-SA 4.0" />
  <row Id="32527" PostHistoryTypeId="3" PostId="10803" RevisionGUID="d4ec8bc0-0add-406a-8939-dce69d7c2b75" CreationDate="2021-04-03T12:48:46.983" UserId="11077" Text="|image-processing|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32528" PostHistoryTypeId="50" PostId="5996" RevisionGUID="fdc03bea-c82a-4933-bf50-602be52f2016" CreationDate="2021-04-03T14:04:25.483" UserId="-1" />
  <row Id="32529" PostHistoryTypeId="4" PostId="10802" RevisionGUID="8174a1e8-ebc4-472a-8e6b-b490fc22e609" CreationDate="2021-04-03T14:17:53.093" UserId="15955" Comment="edited title" Text="Unity path tracing makes the pc crash" ContentLicense="CC BY-SA 4.0" />
  <row Id="32530" PostHistoryTypeId="2" PostId="10804" RevisionGUID="f5fff23d-0a76-4428-8af5-1ce839f72382" CreationDate="2021-04-04T10:00:50.397" UserId="7952" Text="Compute the tangent to the line at that point, Use it to make a tangent vector, then use the point on the line, the point being tested and the new point to create two vectors. Take the dot product of the vectors. Positive values are on one side of the line, negative are on the other side. (above and below)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32531" PostHistoryTypeId="2" PostId="10805" RevisionGUID="f5e06904-3521-41ed-88e2-be06fc46e86c" CreationDate="2021-04-04T18:49:48.140" UserId="48" Text="&gt; 1)What is the V vector? How did they compute that&#xD;&#xA;&#xD;&#xA;It's the vector toward the camera (view vector), i.e. direction of the reflected ray. The lookup table they're building is parameterized in terms of NdotV, so they are working backward from NdotV to obtain a corresponding V vector. For purposes of doing this integration it doesn't matter what N and V are exactly, just that they have the correct NdotV. So, just to make things concrete, they assume that $N = (0,0,1)$ and V is aligned with the positive x-axis (i.e. in the positive xz half-plane). Then you have $V = (\sin θ, 0, \cos θ)$ where θ is the angle from N to V (this is just the equation for a circular arc from z down to x). Now $N \cdot V = \cos θ$, so by a standard trig identity $\sin θ = \sqrt{1 - \cos^2 θ} = \sqrt{1 - (N \cdot V)^2}$.&#xD;&#xA;&#xD;&#xA;&gt; 2)Why have they assumed N=(0,0,1)?&#xD;&#xA;&#xD;&#xA;This whole thing is a pre-integration of the BRDF alone, it doesn't depend on any scene or lighting environment. So it doesn't matter where the BRDF is or how it is oriented in space, only the relative orientation between the N, L, and V vectors is important. So just for the sake of convenience they have chosen to fix N = (0, 0, 1), let V vary only in the xz half-plane as mentioned above, and let L vary over the whole hemisphere. To put it another way, they have chosen to set the coordinate system to be aligned with N and V.&#xD;&#xA;&#xD;&#xA;&gt; 3)why is NDotL=max(L.z,0)? How did they simplifying a dot product to an min/max Operation same question I have for NDotH&#xD;&#xA;&#xD;&#xA;Since N = (0, 0, 1), dotting N with any vector just takes the z component of that vector. $N \cdot L = 0L_x + 0L_y + 1L_z = L_z$. (This is why it's convenient to assume a coordinate system in which N = (0, 0, 1).) Taking the max with 0 clamps it to the upper hemisphere, otherwise the dot product would go negative if the vector happens to be pointing below the hemisphere. This clamp is a standard thing to do when dealing with opaque BRDFs to avoid accidentally getting unwanted negative values in your calculations— although it is not really necessary here since they check `if (NdotL &gt; 0.0)` immediately afterward.&#xD;&#xA;&#xD;&#xA;&gt; 4)G_Vis=GVDoth/(NDotHNDotL) why the division by (NDOTH*NDOTL)? that was nowhere in the equation.&#xD;&#xA;&#xD;&#xA;It is a standard part of the microfacet BRDF formulation:&#xD;&#xA;$$&#xD;&#xA;f_r(p, w_i, w_o) = \frac{DFG}{4(\omega_o \cdot n)(\omega_i \cdot n)}&#xD;&#xA;$$&#xD;&#xA;Note that $\omega_o = V$, and $\omega_i = L$, these are just different notations/names for the incoming and outgoing light vectors.&#xD;&#xA;However I think there is a typo in the code, the denominator should contain NdotV rather than NdotH. I am also not sure why there is a multiplication by VdotH in the numerator, or where the factor of 4 went, but perhaps they have accounted for it elsewhere. I would probably double-check the BRDF equations here against some other sources as I don't think it's entirely correct.&#xD;&#xA;&#xD;&#xA;&gt; 5)what is vector L? it looks like they have reflected vector V about H to get this but why?&#xD;&#xA;&#xD;&#xA;As noted, L is the vector toward the incoming light. H is the &quot;half-angle&quot; vector exactly halfway between L and V, so reflecting V around H will give you L, or vice versa. The significance of H is that in microfacet BRDFs, it is the normal vector of those microfacets that are &quot;active&quot; for a given L and V. So, to importance-sample a BRDF, we sample a random normal vector from the NDF, and use that as H. Since H and V are specified, we then calculate L from those." ContentLicense="CC BY-SA 4.0" />
  <row Id="32532" PostHistoryTypeId="5" PostId="10798" RevisionGUID="c66afa8e-8917-40d7-bc76-8efb464ba1b0" CreationDate="2021-04-05T11:01:01.613" UserId="10129" Comment="added 169 characters in body" Text="**I recommend to ignore my post (however I consider papers that I've sent valueable) and read post of Nathan Reed, which is much better in explaining this problem!**&#xD;&#xA;&#xD;&#xA;I'm still a junior when it comes to computer graphics so you may want to take my opinion with a grain of salt:&#xD;&#xA;&#xD;&#xA;To start with - I used to learn/implement stuff using website that you've sent (OpenGL) and I don't recommend that. After few months of learning I knew barely anything. Then I start reading original papers and implementing them on my own to better understand PBR, what N * G * F means in Cook-Torrance shading model and I got much better understanding of basics. I was recommend by many graphics programmers to avoid tutorial pages and straight read and implement papers. In case if you don't understand something in the paper you're reading, you found paper on subject that you don't understand and read about it.&#xD;&#xA;&#xD;&#xA;1). As I said - avoid this site or use only to get interesting papers - here are original notes from [Karis2013] UE4 presentation - https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf ; Please notice comment &quot;/sin&quot; &quot;/cos&quot; in listing at page 7 and usage of *Pythagorean trigonometric identity*. Maybe it's position on the hemishpere, I don't really want to dig in, I'm sorry. But I would recommend checking Epic Games repository on Github if you want to see how they're using it.&#xD;&#xA;&#xD;&#xA;2.) In the same paper [Karis2013] there is listing at the page 4. and function **ImportanceSampleGGX**. It uses N to determine orientation of the world and returns either float3(0,0,1) or float3(1,0,0) based on N.z value.&#xD;&#xA;&#xD;&#xA;3).&#xD;&#xA;$$N = (0, 0, 1)$$&#xD;&#xA;$$L = (x, y, z)$$ &#xD;&#xA;$$ dot(N, L) = (0 * x, 0 * y, 1 * z) = (0, 0, z) = L.z$$&#xD;&#xA;&#xD;&#xA;4). &#xD;&#xA;http://jcgt.org/published/0003/02/03/paper.pdf#page=30&#xD;&#xA;&#xD;&#xA;http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html&#xD;&#xA;&#xD;&#xA;https://www.microsoft.com/en-us/research/wp-content/uploads/1977/01/p192-blinn.pdf&#xD;&#xA;&#xD;&#xA;These links might be helpful to understand BRDF better. Why there are strange division? I don't know, it's probably due to optimization, I don't know what NDF is being used. However, what happens here is you're multiplying D and G component, so you can do split multiplication with Fresnel. It doesn't matter how you write it. You can just create function NDF_GGX(...) and multiply it by G, add pdf and it'll work the same. &#xD;&#xA;You can take a look at modern UE4 code - https://github.com/EpicGames/UnrealEngine/blob/2bf1a5b83a7076a0fd275887b373f8ec9e99d431/Engine/Shaders/Private/AmbientCubemapComposite.usf#L255 to understand it better. That's why I'm saying to write your own code. I would say that [Karis2013] is omitting a lot of code and uses many optimizations without saying WHY.&#xD;&#xA;&#xD;&#xA;5). It's just light direction. When you already calculated V and H, it is easy to get L by using reflection. Take a look at the picture here - https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model#Description" ContentLicense="CC BY-SA 4.0" />
  <row Id="32534" PostHistoryTypeId="2" PostId="10806" RevisionGUID="fd66fbae-be97-4e16-be48-e6017a287307" CreationDate="2021-04-06T06:19:32.317" UserId="15544" Text="Lets assume, we have two depth maps with us and their corresponding color maps. Now, our task is to populate a final image that will be displayed.&#xD;&#xA;&#xD;&#xA;Each pixel in the final image needs to be calculated from the given 4 maps - two color and corresponding depth. I am simply aiming to create a final image considering the occlusion of one depth map over the other.&#xD;&#xA;&#xD;&#xA;My idea is to just compare the depth values and then take the color value from the map whichever is closer to the camera.&#xD;&#xA;&#xD;&#xA;Is this a right way to approach the problem?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: This problem popped up as part of a hybrid rendering solution am working on - combining ray marching and rasterization to get triangles as well as metaballs working. So, one of the pair of maps above comes from rasterization and the other comes from ray marching." ContentLicense="CC BY-SA 4.0" />
  <row Id="32535" PostHistoryTypeId="1" PostId="10806" RevisionGUID="fd66fbae-be97-4e16-be48-e6017a287307" CreationDate="2021-04-06T06:19:32.317" UserId="15544" Text="Combining two images based on their depth maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="32536" PostHistoryTypeId="3" PostId="10806" RevisionGUID="fd66fbae-be97-4e16-be48-e6017a287307" CreationDate="2021-04-06T06:19:32.317" UserId="15544" Text="|raytracing|rendering|rasterizer|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32538" PostHistoryTypeId="2" PostId="10807" RevisionGUID="8ec5c734-1d39-4f63-8076-206f274a6b8c" CreationDate="2021-04-06T18:39:13.173" UserId="8009" Text="The technique is called **halftone**.  Achieving continuity must be done through subsampling / super-sampling, but the essence of the algorithm goes like this.&#xD;&#xA;&#xD;&#xA;Imagine walking across a horizontal line of the image accumulating energy from each input pixel as you go.  Once you have accumulated some threshold amount of energy in the accumulator, emit a single pixel, and then reduce the energy stored in the accumulator by a constant amount.&#xD;&#xA;&#xD;&#xA;In code, that would be something like:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;for (int y = 0; y &lt; height; ++y) {&#xD;&#xA;    double accumulator = 0.0;&#xD;&#xA;    for (int x = 0; x &lt; width; ++x) {&#xD;&#xA;        accumulator += input[x, y];&#xD;&#xA;        if (accumulator &gt;= 0.0) {&#xD;&#xA;            output[x, y] = 1.0;&#xD;&#xA;            accumulator -= K; // try values like 5.0 or more for K.&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The larger `K` is, the more energy must be accumulated before outputting a pixel, and hence, the more horizontal distance there will be between the lines.  If K is 1, that's actually a naïve approach to the *dither* algorithm.&#xD;&#xA;&#xD;&#xA;Supersample to achieve continuity.  You can also emit discrete (x,y) points instead of rendering an output pixel directly and then render a new image by rendering a vertical curve passing through the nth point generated of each scanline.&#xD;&#xA;&#xD;&#xA;Perform the operation discretely on separate colour channels to get what you described as the &quot;chromatic aberration&quot; effect.&#xD;&#xA;&#xD;&#xA;The effect degenerates the more complexity you encounter in the image on a single line.  For example, after just two eyes on the same line, the lines are extremely wavy at the right of your example image.  [Here is the effect exaggerated even more](https://www.shutterstock.com/image-vector/vector-oscilloscope-color-glitch-art-illustration-1753357889).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32544" PostHistoryTypeId="50" PostId="10378" RevisionGUID="703a05ed-88f1-4303-9023-13d2f8da0085" CreationDate="2021-04-07T16:00:10.443" UserId="-1" />
  <row Id="32548" PostHistoryTypeId="2" PostId="10810" RevisionGUID="74f8fd32-611b-4f9c-a9c8-246152e42b1f" CreationDate="2021-04-08T12:41:28.710" UserId="11840" Text="I am currently porting the atmosphere algorithm used by the UE4 engine to my engine.&#xD;&#xA;&#xD;&#xA;As the original algorithm from Bruneton is in Kilometers i had to adapt it to my engine which uses meters. Everything is working and its correctly scaled now but i am having some z precision issues on the horizon when drawing the fog. This, i believe, i due to the following math:&#xD;&#xA;&#xD;&#xA;    float DepthBufferValue = texture(ViewDepthTexture, depthValueUV).r;&#xD;&#xA;    vec3 depthClipSpace = vec3(pixPos / vec2(gResolution) * vec2(2.0f) - vec2(1.0f), DepthBufferValue);&#xD;&#xA;    vec4 DepthBufferWorldPos = gInvViewProjMat * vec4(depthClipSpace, 1.0);&#xD;&#xA;    DepthBufferWorldPos /= DepthBufferWorldPos.w; // perspective division&#xD;&#xA;    DepthBufferWorldPos.xyz *= 0.001; &#xD;&#xA;&#xD;&#xA;Here, i am basically reading the depth texture, getting the real world position value and scaling it to be in KMs. Due to this scaling (and the inverse multiplication) i am getting some shimmering in the horizon (where the z distance is the greatest)&#xD;&#xA;&#xD;&#xA;Since the depth equation is equal to:&#xD;&#xA;&#xD;&#xA;     d = a * (1/z) + b &#xD;&#xA;&#xD;&#xA;(with a = near, b = far clip and z the distance from camera) is there any mathematical way to scale the DepthBufferValue to a value where the world position would be in kilometers?&#xD;&#xA;&#xD;&#xA;In a more practical way, imagining that we have a World Position of (0, 1000, 0) and that gives us a DepthBufferValue of 0.998, can we scale that 0.998 value to the value that we would obtain if we had used the World Position (0, 1, 0) ? (Assuming of course the same near and far clips) &#xD;&#xA;&#xD;&#xA;Many thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="32549" PostHistoryTypeId="1" PostId="10810" RevisionGUID="74f8fd32-611b-4f9c-a9c8-246152e42b1f" CreationDate="2021-04-08T12:41:28.710" UserId="11840" Text="Scale Sampled Depth Value" ContentLicense="CC BY-SA 4.0" />
  <row Id="32550" PostHistoryTypeId="3" PostId="10810" RevisionGUID="74f8fd32-611b-4f9c-a9c8-246152e42b1f" CreationDate="2021-04-08T12:41:28.710" UserId="11840" Text="|glsl|hlsl|depth-map|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32559" PostHistoryTypeId="50" PostId="10722" RevisionGUID="06f59a3a-2f6e-4a96-971d-e9b0834e7262" CreationDate="2021-04-10T14:03:10.293" UserId="-1" />
  <row Id="32560" PostHistoryTypeId="2" PostId="10812" RevisionGUID="26cf66f1-819e-40d6-af03-bc4ae6bd092a" CreationDate="2021-04-10T15:05:54.557" UserId="13975" Text="I'd like to simulate a 4-dimensional cloth in the web browser, since browsers don't offer great ressources for numerical computation, I'd like to know which algorithm uses the least amount of operations per frame / vertex.&#xD;&#xA;&#xD;&#xA;[Here](https://codepen.io/fweth/pen/poRjMKg?editors=0010) is some naive first draft using explicit Euler.  I found [this](https://www.cs.utah.edu/~ladislav/liu13fast/liu13fast.pdf) paper discussing a fast method for finding approximate solutions of the implicit Euler method.  What I gathered from the discussion is that implicit Euler is numerically more stable in certain scenarios, but it looks like it uses more operations than explicit Euler since it is built around iterations.  Is that correct?&#xD;&#xA;&#xD;&#xA;Also, are there any libraries using WebGL to accelerate numerical computations which might be useful for this project?  I thought about looking into TensorFlow.js." ContentLicense="CC BY-SA 4.0" />
  <row Id="32561" PostHistoryTypeId="1" PostId="10812" RevisionGUID="26cf66f1-819e-40d6-af03-bc4ae6bd092a" CreationDate="2021-04-10T15:05:54.557" UserId="13975" Text="Fastest Simulation Of Mass Spring Systems" ContentLicense="CC BY-SA 4.0" />
  <row Id="32562" PostHistoryTypeId="3" PostId="10812" RevisionGUID="26cf66f1-819e-40d6-af03-bc4ae6bd092a" CreationDate="2021-04-10T15:05:54.557" UserId="13975" Text="|webgl|real-time|physics|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32563" PostHistoryTypeId="2" PostId="10813" RevisionGUID="495d80ac-fc4a-48bb-8590-a2ed1d21f5be" CreationDate="2021-04-10T17:38:43.773" UserId="48" Text="Algebraically speaking, it's not too hard to modify $d$ in order to scale $z$. If you want to scale $z$ by a factor of $c$, giving $z' = cz$, then&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;d' &amp;= a \frac{1}{z'} + b \\&#xD;&#xA;&amp;= a \frac{1}{cz} + b \\&#xD;&#xA;(d' - b)c &amp;= a \frac{1}{z} \\&#xD;&#xA;&amp;= d - b \\&#xD;&#xA;d' &amp;= \frac{d - b}{c} + b&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;In short, to scale $z$ by a factor of $c$, you would take the depth value and subtract $b$, scale by $1/c$, then add $b$ back again.&#xD;&#xA;&#xD;&#xA;Note that if you use a projection with reversed Z and an infinite far plane, then $b = 0$, which simplifies this to just $d' = d/c$." ContentLicense="CC BY-SA 4.0" />
  <row Id="32573" PostHistoryTypeId="2" PostId="10817" RevisionGUID="398a2875-afda-4847-aa6e-a838c7b4f524" CreationDate="2021-04-11T21:41:26.297" UserId="9548" Text="Sorry for the general question, I don't even know how to tag it:&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=61UkkpsASwQ&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In this video, the effect is such as if there were a laser cutting a shape with a light source behind it, and then the cut is closed again (like some trail effect).&#xD;&#xA;&#xD;&#xA;How is this made and with which kind of software/programming? Is 3D involved here or can this be achieved with procedural 2D programming and shaders?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UzXr2m.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="32574" PostHistoryTypeId="1" PostId="10817" RevisionGUID="398a2875-afda-4847-aa6e-a838c7b4f524" CreationDate="2021-04-11T21:41:26.297" UserId="9548" Text="How's this laser cutting effect with backlight achieved?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32575" PostHistoryTypeId="3" PostId="10817" RevisionGUID="398a2875-afda-4847-aa6e-a838c7b4f524" CreationDate="2021-04-11T21:41:26.297" UserId="9548" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32578" PostHistoryTypeId="5" PostId="10810" RevisionGUID="6a1b22b9-ec70-448d-baae-e08566ec199f" CreationDate="2021-04-12T12:07:06.927" UserId="11840" Comment="added 113 characters in body" Text="I am currently porting the atmosphere algorithm used by the UE4 engine to my engine.&#xD;&#xA;&#xD;&#xA;As the original algorithm from Bruneton is in Kilometers i had to adapt it to my engine which uses meters. Everything is working and its correctly scaled now but i am having some z precision issues on the horizon when drawing the fog. This, i believe, i due to the following math:&#xD;&#xA;&#xD;&#xA;    float DepthBufferValue = texture(ViewDepthTexture, depthValueUV).r;&#xD;&#xA;    vec3 depthClipSpace = vec3(pixPos / vec2(gResolution) * vec2(2.0f) - vec2(1.0f), DepthBufferValue);&#xD;&#xA;    vec4 DepthBufferWorldPos = gInvViewProjMat * vec4(depthClipSpace, 1.0);&#xD;&#xA;    DepthBufferWorldPos /= DepthBufferWorldPos.w; // perspective division&#xD;&#xA;    DepthBufferWorldPos.xyz *= 0.001; &#xD;&#xA;&#xD;&#xA;Here, i am basically reading the depth texture, getting the real world position value and scaling it to be in KMs. Due to this scaling (and the inverse multiplication) i am getting some shimmering in the horizon (where the z distance is the greatest)&#xD;&#xA;&#xD;&#xA;Since the depth equation is equal to:&#xD;&#xA;&#xD;&#xA;     d = a * (1/z) + b &#xD;&#xA;&#xD;&#xA;(with a = near, b = far clip and z the distance from camera) is there any mathematical way to scale the DepthBufferValue to a value where the world position would be in kilometers?&#xD;&#xA;&#xD;&#xA;In a more practical way, imagining that we have a World Position of (0, 1000, 0) and that gives us a DepthBufferValue of 0.998, can we scale that 0.998 value to the value that we would obtain if we had used the World Position (0, 1, 0) ? (Assuming of course the same near and far clips) &#xD;&#xA;&#xD;&#xA;Many thanks!&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;This is the DepthBufferWorldPos outputed to the screen:&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=kEaU72NWq8I" ContentLicense="CC BY-SA 4.0" />
  <row Id="32579" PostHistoryTypeId="2" PostId="10818" RevisionGUID="11ddfb16-eba4-4ffa-895e-d1c526427d89" CreationDate="2021-04-12T16:10:32.180" UserId="16171" Text="I've tried using the classic formula of calculating barycentric coordinates.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VDSQP.png&#xD;&#xA;&#xD;&#xA;When the plane on which you are projecting the texture is collinear to any of the base vectors it crashes with a division on zero error.&#xD;&#xA;&#xD;&#xA;Is there any way to avoid this problem? " ContentLicense="CC BY-SA 4.0" />
  <row Id="32580" PostHistoryTypeId="1" PostId="10818" RevisionGUID="11ddfb16-eba4-4ffa-895e-d1c526427d89" CreationDate="2021-04-12T16:10:32.180" UserId="16171" Text="UV coordinates calculation broken" ContentLicense="CC BY-SA 4.0" />
  <row Id="32581" PostHistoryTypeId="3" PostId="10818" RevisionGUID="11ddfb16-eba4-4ffa-895e-d1c526427d89" CreationDate="2021-04-12T16:10:32.180" UserId="16171" Text="|3d|uv-mapping|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32582" PostHistoryTypeId="2" PostId="10819" RevisionGUID="6a5b1717-9804-43a5-b1d6-c1de7b744b51" CreationDate="2021-04-12T17:52:42.533" UserId="13095" Text="Time integration with implicit Euler is unconditionally stable. This means you can choose arbitrary large time steps without worrying that your solution &quot;explodes&quot;. In contrast to explicit Euler, it requires you to solve a linear equation system at least once, which is generally much slower than simple matrix-vector multiplication. If the problem is non-linear, you also need to iterate until your error is minimized. This obviously takes even longer. &#xD;&#xA;&#xD;&#xA;However, stability issues can be a pain to deal with and all explicit methods have limitations regarding their stability. Solving stability problems might force you to reduce your time step size drastically and to calculate so many intermediate steps that the implicit version gets more effective. An additional factor is the size of the system you want to simulate. If I remember correctly, the finer your mesh (smaller cells), the smaller are the timesteps you need to maintain stability.&#xD;&#xA;&#xD;&#xA;&gt; I'd like to know which algorithm uses the least amount of operations per frame / vertex.&#xD;&#xA;&#xD;&#xA;I think there is no general answer to the question because it depends on many factors like the mesh size, target FPS and the maximum local velocity that might occur. You need to evaluate all relevant factors and pick a method based on your exact problem.&#xD;&#xA;&#xD;&#xA;In case you want raw speed and do not encounter any stability problems, the explicit Euler method should be one of the fastest methods but it usually blows up rather quickly.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Additional info**  &#xD;&#xA;&#xD;&#xA;A time-integration method that is quite popular in real-time engines is Runge-Kutta 4. It is also an explicit method and doesn't require you to solve a linear system. It has a good balance of stability and speed, so you might have a look at it. I have never simulated cloth myself, nor have I programmed an RK4, so I can't tell if it is a good choice here.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32583" PostHistoryTypeId="2" PostId="10820" RevisionGUID="a5213844-b49d-44d1-81c3-86499ab83717" CreationDate="2021-04-13T01:02:23.587" UserId="159" Text="This question may be off-topic here, but this is almost certainly a 2D effect, and it's achievable without much difficulty in After Effects or any similar package once you've broken the effect down into individual elements.&#xD;&#xA;&#xD;&#xA;This isn't exactly the same effect, but it gives most of the ideas: https://www.youtube.com/watch?v=uHFmWu__Q4k" ContentLicense="CC BY-SA 4.0" />
  <row Id="32584" PostHistoryTypeId="5" PostId="10820" RevisionGUID="758f5566-383c-4b29-8f48-87dd69c73e6a" CreationDate="2021-04-13T01:08:12.313" UserId="159" Comment="added 167 characters in body" Text="This question may be off-topic here, but this is almost certainly a 2D effect, and it's achievable without much difficulty in After Effects or any similar package once you've broken the effect down into individual elements.&#xD;&#xA;&#xD;&#xA;This isn't exactly the same effect, but it gives most of the ideas: https://www.youtube.com/watch?v=uHFmWu__Q4k&#xD;&#xA;&#xD;&#xA;The key point here is that you need to look not at the effect as a whole, but break it down into the individual elements that make it up. The parts make the whole." ContentLicense="CC BY-SA 4.0" />
  <row Id="32585" PostHistoryTypeId="5" PostId="10767" RevisionGUID="fbabaa68-841b-40e1-9ebc-342f3fb920f2" CreationDate="2021-04-13T12:10:40.277" UserId="7952" Comment="Added information based on comments" Text="Gamma correction originated as a way of correcting the output of a CRT to be a better fit for the human visual system. Modern monitors don't need to do it, but, they followed the CRT and there were millions of CRT's that all had gamma correction and most signals already had gamma correction in them. Today we have a chicken and egg problem...but reversed. Millions of clucking hardware chickens all speaking gamma...&#xD;&#xA;&#xD;&#xA;The flip side is that us humans don't think well in the land of exponential values, but we do think well in terms of linear values. So software for graphics code tends to remove the gamma then we can multiply add and manipulate in an intuitive manner, and convert it back to gamma for display.&#xD;&#xA;&#xD;&#xA;Modern hardware has specialty components that do this on the fly so the generally accepted practice is to set up the graphics hardware to handle this so we don't have to worry about it as programmers. But sometimes it can be useful.&#xD;&#xA;&#xD;&#xA;-------&#xD;&#xA;Updates based on comments&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Gamma correction has a second benefit for low precision formats like the common sRGB 8 bit format. (invented in the 90's to match hardware of the day) It redistributes the available values placing more values in the &quot;dim&quot; region where human's can better perceive changes in *brightness*. This redistribution is why gamma correction is often called gamma *compression*.&#xD;&#xA;&#xD;&#xA;This is not a correction for human vision, it is a correction for the limitations of the 8 bit format. Higher precision formats do not need to store gamma correction and (generally) have gamma applied to them only when converting to a lower precision format.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The very amazing human eye can perceive 1,000,000 nits of difference in brightness by dynamically adapting itself to the available lighting. But is especially adapted to see more changes in *brightness* in dark situations. The CRT when it was invented struggled to display 100 nits of brightness. Leaving 999,900 nits on the table. So gamma was applied to the signal to take advantage of our ability to see better in low lighting. This was a limitation of the CRT not our vision.&#xD;&#xA;&#xD;&#xA;It is common for modern monitors to reach 300-500 nits, with some models getting up to 1000 nits or more. That extra available brightness means that gamma is not really needed for anything but historical compatibility.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;When working with image data it is best to configure the hardware to handle gamma correction for us and use methods such as tone mapping to achieve a specialized appearance. This allows the hardware to load images that are stored as a variety of color formats such as sRGB and HDR into a common space that is well defined, where code can then perform its calculations and send that result to the hardware where it is converted to a format that is specific to the device being used to display it. (which is often a gamma corrected format)&#xD;&#xA;&#xD;&#xA;I am not tying to say that this image is &quot;wrong&quot;, everyone should take the time to create images like this to better understand gamma correction." ContentLicense="CC BY-SA 4.0" />
  <row Id="32586" PostHistoryTypeId="2" PostId="10821" RevisionGUID="a0bf946e-f8e3-47dc-914e-9473b7976ed8" CreationDate="2021-04-13T13:20:19.617" UserId="2287" Text="The actual color of a pixel, outputted on a monitor, does not linearly depend on the applied voltage signal for that pixel. For CRT monitors, the actual color is approximately proportional to the applied voltage raised to the power of a so-called *gamma* value, which depends on the monitor. This gamma value typically lies between 2.2 and 2.5 for CRT monitors. (*Hence, the ubiquitous appearances of the magical constant 2.2 in rendering applications.*) &#xD;&#xA;&#xD;&#xA;$$L_\mathrm{actual} \sim V^\gamma$$&#xD;&#xA;&#xD;&#xA;To bypass this gamma value in your computations, you need to [*gamma correct*](https://en.wikipedia.org/wiki/Gamma_correction) the computed colors of each pixel before presenting. By raising the computed color to a power of the reciprocal of that same gamma value, the computed color becomes proportional to the actual color.&#xD;&#xA;&#xD;&#xA;$$V \sim L_\mathrm{computed}^{1/\gamma} \\&#xD;&#xA;L_\mathrm{actual} \sim L_\mathrm{computed}$$&#xD;&#xA;&#xD;&#xA;So in general gamma correction is a technique that adapts the computed colors to the transfer function of the monitor used for outputting. Both CRT and non-CRT monitors each have their own transfer function. This means that the final rendering pass should adapt the computed colors, based on the used monitor, to obtain correct actual colors.&#xD;&#xA;&#xD;&#xA;These linear-to-gamma color space conversions seem like unnecessary overhead from a monitor construction point of view. It is physically perfectly possible to construct a CRT monitor with a gamma value of exactly one, ensuring that the computed color is already proportional to the actual color, and eliminating the need for gamma correction.&#xD;&#xA;&#xD;&#xA;From a perceptual point of view, removing the need for gamma correction and using a monitor where computed colors are proportional to the corresponding actual colors is actually a bad idea. Typically, actual colors are represented with 8 (or 10) bits for each of the red, green and blue channel. This quantization only supports 256 (or 1024) different colors. Here, a 0 value represents completely black and a 255 (or a 1023) value represents completely white. But what about the intermediate values? If a linear encoding is used (*i.e. a gamma value of 1*), the majority of values would be perceptually very close to white and a very small minority would be perceptually close to black. By using a gamma encoding (*e.g., a gamma value of 2.2*), the distribution is perceptually more linear (*i.e. equidistant intervals between black and white*).&#xD;&#xA;&#xD;&#xA;&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/2464019/38454812-917ffe76-3a6e-11e8-9776-262e1e229f4c.png&quot;&gt;&lt;/div&gt;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32587" PostHistoryTypeId="5" PostId="10715" RevisionGUID="ef88660e-7708-4a12-a959-26e6186a4a85" CreationDate="2021-04-13T15:05:43.067" UserId="2654" Comment="added 49 characters in body" Text="Fragment shader subgroups are not required to be restricted to a single primitive (and such a restriction would negatively impact performance). So subgroup broadcasting can cross primitive boundaries.&#xD;&#xA;&#xD;&#xA;Note that the most recent version of the Vulkan standard states that invocations in the same quad scopes are required to be within the same primitive scope." ContentLicense="CC BY-SA 4.0" />
  <row Id="32588" PostHistoryTypeId="2" PostId="10822" RevisionGUID="0a035ea7-2c6b-41e0-b023-b188c90ea766" CreationDate="2021-04-14T01:47:36.140" UserId="16184" Text="Recently I‘m working on a Precomputed GI Project&#xD;&#xA;&#xD;&#xA;I'm trying to use a technique called AHD, Amibent Highlight Direction, rendering my project;&#xD;&#xA;I use Unity and my target platform is Android.&#xD;&#xA;&#xD;&#xA;First: &#xD;&#xA;	Unity SH is the result of Encoded and Scaled, I want to get the original SH&#xD;&#xA;	I'm trying try to decode it, but there are several problems with the sixth coefficient;&#xD;&#xA;	 I found some documents that said unity moved the constant part of  L6(band l = 2,order m = 0) to the L0(band l = 0, order m = 0), is that true?&#xD;&#xA;	If that's right, how can I get the right original SH?&#xD;&#xA;&#xD;&#xA;There are some trying of myself, I have tried to calculate the constant part and recalculate the L0 and L6, but it seem not to be correct, in fact, I don't know how to verify it.&#xD;&#xA;&#xD;&#xA;    #define k01 0.2820947918 // sqrt(  1/PI)/2&#xD;&#xA;    #define k02 0.4886025119 // sqrt(  3/PI)/2&#xD;&#xA;    #define k03 1.0925484306 // sqrt( 15/PI)/2&#xD;&#xA;    #define k04 0.3153915652 // sqrt(  5/PI)/4&#xD;&#xA;    #define k05 0.5462742153 // sqrt( 15/PI)/4&#xD;&#xA;&#xD;&#xA;    float3 SampleRawSH9(float4 SHCoefficients[7], float3 N) {&#xD;&#xA;        float3 n = N.zxy;&#xD;&#xA;    float4 shAr = SHCoefficients[0];&#xD;&#xA;    float4 shAg = SHCoefficients[1];&#xD;&#xA;    float4 shAb = SHCoefficients[2];&#xD;&#xA;    float4 shBr = SHCoefficients[3];&#xD;&#xA;    float4 shBg = SHCoefficients[4];&#xD;&#xA;    float4 shBb = SHCoefficients[5];&#xD;&#xA;    float4 shCr = SHCoefficients[6];&#xD;&#xA;&#xD;&#xA;    //band0&#xD;&#xA;    //l0 + l6 constant part&#xD;&#xA;    float3 L0 = float3(shAr.w, shAg.w, shAb.w);&#xD;&#xA;    float3 L6c = -float3(shBr.z, shBg.z, shBb.z)* k04/4.;&#xD;&#xA;    L6c = 0;&#xD;&#xA;    L0 = (L0 - L6c) / k01;&#xD;&#xA;&#xD;&#xA;    //band1&#xD;&#xA;    //m=-1&#xD;&#xA;    float3 L1 = float3(shAr.y * n.y, shAg.y * n.y, shAb.y * n.y);&#xD;&#xA;    L1 = L1 * 1.5 / (-k02);&#xD;&#xA;    //m=0&#xD;&#xA;    float3 L2 = float3(shAr.z * n.z, shAg.z * n.z, shAb.z * n.z);&#xD;&#xA;    L2 = L2 * 1.5 / (k02);&#xD;&#xA;    //m=1&#xD;&#xA;    float3 L3 = float3(shAr.x * n.x, shAg.x * n.x, shAb.x * n.x);&#xD;&#xA;    L3 = L3 * 1.5 / (-k02);&#xD;&#xA;&#xD;&#xA;    //band2&#xD;&#xA;    //m=-2&#xD;&#xA;    float3 L4 = float3(shBr.x * n.x * n.y, shBg.x * n.x * n.y, shBb.x * n.x * n.y);&#xD;&#xA;    L4 = L4 * 4. / (k03);&#xD;&#xA;    //m=-1&#xD;&#xA;    float3 L5 = float3(shBr.y * n.y * n.z, shBg.y * n.y * n.z, shBb.y * n.y * n.z);&#xD;&#xA;    L5 = L5 * 4. / (-k03);&#xD;&#xA;    //m=0&#xD;&#xA;    float3 L6cos = float3(shBr.z * n.z * n.z, shBg.z * n.z * n.z, shBb.z * n.z * n.z);&#xD;&#xA;    float3 L6 = L6cos * 4. / (k04 * 3.0) + L6c * 4. / (k04);&#xD;&#xA;    //m=1&#xD;&#xA;    float3 L7 = float3(shBr.w * n.x * n.z, shBg.w * n.x * n.z, shBb.w * n.x * n.z);&#xD;&#xA;    L7 = L7 * 4. / (-k03);&#xD;&#xA;    //m=2&#xD;&#xA;    float3 L8 = shCr.rgb * (n.x * n.x - n.y * n.y);&#xD;&#xA;    L8 = L8 * 4. / (k05);&#xD;&#xA;&#xD;&#xA;    return L0 + L1 + L2 + L3 + L4 + L5 + L6 + L7 + L8;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Second:&#xD;&#xA;I try to rebuild my AHD from SH.&#xD;&#xA;I'm confused with amibentColor part. Does it contain the part of Directional Light Diffuse term?&#xD;&#xA;The results look strange;&#xD;&#xA;Same as the previous one,  I still can't verify the correctness of my calculation&#xD;&#xA;&#xD;&#xA;    void SampleRawSHAHD(float3 normalWS, out float highLightFactor, out float3 highLightDir, out float3 highLightColor, out float3 ambientColor) {&#xD;&#xA;            real4 SHCoefficients[7];&#xD;&#xA;            SHCoefficients[0] = unity_SHAr;&#xD;&#xA;            SHCoefficients[1] = unity_SHAg;&#xD;&#xA;            SHCoefficients[2] = unity_SHAb;&#xD;&#xA;            SHCoefficients[3] = unity_SHBr;&#xD;&#xA;            SHCoefficients[4] = unity_SHBg;&#xD;&#xA;            SHCoefficients[5] = unity_SHBb;&#xD;&#xA;            SHCoefficients[6] = unity_SHC;&#xD;&#xA;        highLightDir = SampleRawSHDir(SHCoefficients, normalWS);&#xD;&#xA;        highLightFactor = length(highLightDir) * PI * 16 / 17;&#xD;&#xA;        highLightDir = normalize(highLightDir);&#xD;&#xA;        highLightColor = highLightFactor * SampleRawSH(highLightDir) * 867. / (316. * PI);&#xD;&#xA;        ambientColor = (SampleRawSH(0) - highLightColor * 8. * sqrt(PI) / 17.) * sqrt(PI) / 2.;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;I really appreciate someone who can give me some guidance!&#xD;&#xA;&#xD;&#xA;My reference：&#xD;&#xA;&#xD;&#xA;https://www.ppsloan.org/publications/StupidSH36.pdf&#xD;&#xA;&#xD;&#xA;http://graphics.stanford.edu/papers/envmap/envmap.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32589" PostHistoryTypeId="1" PostId="10822" RevisionGUID="0a035ea7-2c6b-41e0-b023-b188c90ea766" CreationDate="2021-04-14T01:47:36.140" UserId="16184" Text="Questions about caculate the highlight direction from spherical harmonics functions" ContentLicense="CC BY-SA 4.0" />
  <row Id="32590" PostHistoryTypeId="3" PostId="10822" RevisionGUID="0a035ea7-2c6b-41e0-b023-b188c90ea766" CreationDate="2021-04-14T01:47:36.140" UserId="16184" Text="|shader|spherical-harmonics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32591" PostHistoryTypeId="2" PostId="10823" RevisionGUID="4c202b2b-a382-4525-bcc9-3d8be5b1b43d" CreationDate="2021-04-14T22:49:51.913" UserId="7462" Text="I am trying to model heat diffusion on the surface of a mesh. I annexed the most important bits of theory about this topic as screenshots on the question see the bottom.&#xD;&#xA;&#xD;&#xA;The crux of the issue is we are solving a linear system $(M - tL_C)u = \delta_y$. In this case $M$ is a diagonal matrix, $L_C$ is the discrete Laplace operator, $t$ is a constant time step equal to some epsilon and $\delta_y$ is a sparse vector with only one non-zero entry which is equal to 1.&#xD;&#xA;&#xD;&#xA;My expectation is that, upon solving this system and drawing the resulting vertex distances, I get a fading from white to black starting at the source vertex and slowly fading away as the vertices go away from the source. I am however seeing this:&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;Which looks like random noise to me, as if I messed up the calculation.&#xD;&#xA;&#xD;&#xA;I implemented the solver using Eigen, this is the snippet:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Eigen::DiagonalMatrix&lt;float, Eigen::Dynamic&gt; areas(sources.size());&#xD;&#xA;    Eigen::SparseMatrix&lt;float&gt; laplace_operator(sources.size(), sources.size());&#xD;&#xA;&#xD;&#xA;    for(uint i = 0; i &lt; sources.size(); i++)&#xD;&#xA;        laplace_operator.insert(i, i) = 0;&#xD;&#xA;&#xD;&#xA;    areas.setZero();&#xD;&#xA;&#xD;&#xA;    for(uint e = 0; e &lt; mesh.Edges().size(); e += 2)&#xD;&#xA;    {&#xD;&#xA;        const auto&amp; edge = mesh.Edges()[e];&#xD;&#xA;        const uint i = edge.Vert().ID();&#xD;&#xA;        const uint j = edge.Pair().Vert().ID();&#xD;&#xA;&#xD;&#xA;        const Eigen::Vector3f e1 = -edge.Next().Dir().normalized();&#xD;&#xA;        const Eigen::Vector3f e2 = edge.Prev().Dir().normalized();&#xD;&#xA;&#xD;&#xA;        const float alpha = acos(e1.dot(e2));&#xD;&#xA;&#xD;&#xA;        const Eigen::Vector3f p1 = -edge.Pair().Next().Dir().normalized();&#xD;&#xA;        const Eigen::Vector3f p2 = edge.Pair().Prev().Dir().normalized();&#xD;&#xA;&#xD;&#xA;        const float beta = acos(p1.dot(p2));&#xD;&#xA;&#xD;&#xA;        const float laplace_coeff = -0.5f * ((1.f / tan(alpha)) + (1.f / tan(beta)));&#xD;&#xA;&#xD;&#xA;        laplace_operator.insert(i, j) = laplace_coeff;&#xD;&#xA;        laplace_operator.insert(j, i) = laplace_coeff;&#xD;&#xA;&#xD;&#xA;        laplace_operator.coeffRef(i, i) -= laplace_coeff;&#xD;&#xA;        laplace_operator.coeffRef(j, j) -= laplace_coeff;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    uint count = 0;&#xD;&#xA;    for(auto&amp; v: mesh.Verts())&#xD;&#xA;    {&#xD;&#xA;        std::vector&lt;HMesh&lt;VertexData&gt;::MFace*&gt; faces = v.ContainingFaces();&#xD;&#xA;        for(auto f: faces)&#xD;&#xA;        {&#xD;&#xA;            areas.diagonal()[count] += f-&gt;Area();&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        areas.diagonal()[count] /= 3.f;&#xD;&#xA;&#xD;&#xA;        count++;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    SparseLU&lt;SparseMatrix&lt;float&gt;, COLAMDOrdering&lt;int&gt; &gt; solver;&#xD;&#xA;&#xD;&#xA;    const Eigen::SparseMatrix&lt;float&gt; a =&#xD;&#xA;        Eigen::SparseMatrix&lt;float&gt;(areas) - 0.01 * laplace_operator;&#xD;&#xA;    solver.analyzePattern(a);&#xD;&#xA;    solver.factorize(a);&#xD;&#xA;&#xD;&#xA;    return solver.solve(sources);&#xD;&#xA; ```&#xD;&#xA;&#xD;&#xA;I have checked and `sources` is indeed a sparse vector with a singular source vertex set to 1 so the input is correct. The mesh operations that fetch values are very tested and they are returning what is expected, so I know the error is in the logic of this function.&#xD;&#xA;&#xD;&#xA;I suspect my mistake might be creating the laplace operator, but I am not sure.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/j22KI.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9fusI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/WXeUW.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/GE9OR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32592" PostHistoryTypeId="1" PostId="10823" RevisionGUID="4c202b2b-a382-4525-bcc9-3d8be5b1b43d" CreationDate="2021-04-14T22:49:51.913" UserId="7462" Text="Computing heat diffusion creates weird results" ContentLicense="CC BY-SA 4.0" />
  <row Id="32593" PostHistoryTypeId="3" PostId="10823" RevisionGUID="4c202b2b-a382-4525-bcc9-3d8be5b1b43d" CreationDate="2021-04-14T22:49:51.913" UserId="7462" Text="|mathematics|computational-geometry|geometry|mesh|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32594" PostHistoryTypeId="5" PostId="101" RevisionGUID="ce74102a-a7bc-401d-a43c-101aa24d4742" CreationDate="2021-04-15T09:13:43.097" UserId="100" Comment="added 76 characters in body" Text="As far as I know there are no tools that allows you to steps through code in a shader (also, in that case you would have to be able to select just a pixel/vertex you want to &quot;debug&quot;, the execution is likely to vary depending on that). &#xD;&#xA;(NOTE: Renderdoc allows you to do so by selecting a specific thread/pixel)&#xD;&#xA;&#xD;&#xA;What I personally do is a very hacky &quot;colourful debugging&quot;. So I sprinkle a bunch of dynamic branches with &lt;code&gt;#if DEBUG / #endif&lt;/code&gt; guards that basically say &#xD;&#xA; &#xD;&#xA;    &#xD;&#xA;	#if DEBUG&#xD;&#xA;	if( condition ) &#xD;&#xA;		outDebugColour = aColorSignal;&#xD;&#xA;	#endif&#xD;&#xA;	&#xD;&#xA;	.. rest of code .. &#xD;&#xA;	&#xD;&#xA;	// Last line of the pixel shader&#xD;&#xA;	#if DEBUG&#xD;&#xA;	OutColor = outDebugColour;&#xD;&#xA;	#endif&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So you can &quot;observe&quot; debug info this way. I usually do various tricks like lerping or blending between various &quot;colour codes&quot; to test various more complex events or non-binary stuff. &#xD;&#xA;&#xD;&#xA;In this &quot;framework&quot; I also find useful to have a set of fixed conventions for common cases so that if I don't have to constantly go back and check what colour I associated with what. &#xD;&#xA;The important thing is have a good support for hot-reloading of shader code, so you can almost interactively change your tracked data/event and switch easily on/off the debug visualization. &#xD;&#xA;&#xD;&#xA;If need to debug something that you cannot display on screen easily, you can always do the same and use one frame analyser tool to inspect your results. I've listed a couple of them [as answer of this other question.][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Obv, it goes without saying that if I am not &quot;debugging&quot; a pixel shader or compute shader, I pass this &quot;debugColor&quot; info throughout the pipeline without interpolating it (in GLSL with &lt;code&gt; flat &lt;/code&gt; keyword ) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Again, this is very hacky and far from proper debugging, but is what I am stuck with not knowing any proper alternative.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/23/how-can-i-debug-what-is-being-rendered-to-a-frame-buffer-object-in-opengl/25#25" ContentLicense="CC BY-SA 4.0" />
  <row Id="32595" PostHistoryTypeId="2" PostId="10824" RevisionGUID="c0d92c4a-5e3e-4a97-975d-48ddfb99b8c6" CreationDate="2021-04-15T09:55:49.457" UserId="16193" Text="beginner here.&#xD;&#xA;&#xD;&#xA;I am implementing importance sampling for environment maps in Scotty3D, a CMU CS project (but I am not a student).&#xD;&#xA;&#xD;&#xA;The task can be found [here][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://cmu-graphics.github.io/Scotty3D/pathtracer/environment_lighting&#xD;&#xA;&#xD;&#xA;I have a problem with the sample's pdf, it is unusually small and that results in the object being rendered white even if its albedo is not white.&#xD;&#xA;&#xD;&#xA;Here is how I construct the CDF:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Calculate Lsintheta across the image. Accumulate to normalize the pdf to 1 later.&#xD;&#xA;    for (size_t j = 0; j &lt; h; j++) {&#xD;&#xA;        for (size_t i = 0; i &lt; w; i++) {&#xD;&#xA;            // 0.5f at the pixel center. Else we never sample top and bottom rows&#xD;&#xA;            float Lsintheta = image.at(i, j).luma() * sin(PI_F*(j + 0.5f)/h);&#xD;&#xA;            total += Lsintheta;&#xD;&#xA;            cdf.push_back(total); // Joint Cdf. P(theta, phi)&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So `total` would have all the pixels' luminosities. `cdf` would actually be the cumulative luminosity.&#xD;&#xA;&#xD;&#xA;Next is the sampling and calculating the actual pdf.&#xD;&#xA;&#xD;&#xA;    float Xi = RNG::unit(); // [0, 1]&#xD;&#xA;    auto lower = std::lower_bound(cdf.begin(), cdf.end(), Xi*total); // cdf is not normalized yet. Scale the RV&#xD;&#xA;    auto index = std::distance(cdf.begin(), lower);&#xD;&#xA;    out_pdf = *lower;&#xD;&#xA;    if (index &gt; 0) out_pdf -= cdf[index - 1]; // pdf[index] = cdf[index] - cdf[index - 1]&#xD;&#xA;    out_pdf /= total;&#xD;&#xA;&#xD;&#xA;`Xi` is a uniformly sampled real number from 0 to 1. Then it is multiplied by the `total` luminosity in the image to get the sampled accumulated luminosity. Use `std::lower_bound` to get the nearest accumulated luminosity greater than or equal to it. Find the index of this nearest accumulated luminosity using `std::distance`. Then minus with the previous accumulated luminosity to get the actual luminosity in this pixel. Divide by `total` to get the `pdf`.&#xD;&#xA;&#xD;&#xA;This doesn't work, but if I just do `out_pdf = lower/total` it can at least show the right color.&#xD;&#xA;What am I doing/understanding wrong?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32596" PostHistoryTypeId="1" PostId="10824" RevisionGUID="c0d92c4a-5e3e-4a97-975d-48ddfb99b8c6" CreationDate="2021-04-15T09:55:49.457" UserId="16193" Text="Environment map importance sampling (beginner)" ContentLicense="CC BY-SA 4.0" />
  <row Id="32597" PostHistoryTypeId="3" PostId="10824" RevisionGUID="c0d92c4a-5e3e-4a97-975d-48ddfb99b8c6" CreationDate="2021-04-15T09:55:49.457" UserId="16193" Text="|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32598" PostHistoryTypeId="2" PostId="10825" RevisionGUID="92b4f750-4dfc-41cd-9495-be46bc430445" CreationDate="2021-04-15T10:51:05.813" UserId="13321" Text="From all other implementations I have seen, you generally sample twice, once in the Y dimension to select a row and then once in the X dimension to selct the pixel from this row.&#xD;&#xA;&#xD;&#xA;I am not sure if this is necissary, maybe you're one dimensional sampling is fine.&#xD;&#xA;&#xD;&#xA;I think you also need to multiply your pdf so that it is relative to solid angle (so it's total sums to 4pi).&#xD;&#xA;&#xD;&#xA;You should be able to do this by dividing by (2 * Pi * Pi * sinTheta).&#xD;&#xA;&#xD;&#xA;PBRT is probably the best textbook to help you. You can find it online here:&#xD;&#xA;&#xD;&#xA;http://www.pbr-book.org/&#xD;&#xA;&#xD;&#xA;The source code is also available. Here is the code for the environment light:&#xD;&#xA;&#xD;&#xA;https://github.com/mmp/pbrt-v3/blob/aaa552a4b9cbf9dccb71450f47b268e0ed6370e2/src/lights/infinite.cpp&#xD;&#xA;&#xD;&#xA;and the code for the Distribution2D sampler:&#xD;&#xA;&#xD;&#xA;https://github.com/mmp/pbrt-v3/blob/aaa552a4b9cbf9dccb71450f47b268e0ed6370e2/src/core/sampling.h&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32599" PostHistoryTypeId="50" PostId="9549" RevisionGUID="86971a33-62a4-4545-b526-4334f66dd431" CreationDate="2021-04-15T12:48:41.857" UserId="-1" />
  <row Id="32600" PostHistoryTypeId="50" PostId="2516" RevisionGUID="1d8a487f-c09c-4159-8b0c-b78a767b9e6a" CreationDate="2021-04-15T14:59:02.820" UserId="-1" />
  <row Id="32601" PostHistoryTypeId="2" PostId="10826" RevisionGUID="a69503da-1a81-4987-b53d-2b60ee34c2c7" CreationDate="2021-04-15T16:05:54.700" UserId="15211" Text="I'm trying to extrude a face from a selected mesh in babylonjs using the ExtrudeShape but can't figure out why i got flipped faces.&#xD;&#xA;&#xD;&#xA;The bottom extrusions always comes flipped for a reason i ignore &#xD;&#xA;&#xD;&#xA;Since the extrudeShape method only extrudes corresponding to the xy plane, i rotate them and extrudes them but i can't figure why sometimes my normals are wrong &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is [my code on the babylonjs playground][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://playground.babylonjs.com/#X3UQ4P#19" ContentLicense="CC BY-SA 4.0" />
  <row Id="32602" PostHistoryTypeId="1" PostId="10826" RevisionGUID="a69503da-1a81-4987-b53d-2b60ee34c2c7" CreationDate="2021-04-15T16:05:54.700" UserId="15211" Text="How to extrude a face from a selected mesh in babylonjs using the ExtrudeShape method" ContentLicense="CC BY-SA 4.0" />
  <row Id="32603" PostHistoryTypeId="3" PostId="10826" RevisionGUID="a69503da-1a81-4987-b53d-2b60ee34c2c7" CreationDate="2021-04-15T16:05:54.700" UserId="15211" Text="|3d|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32604" PostHistoryTypeId="2" PostId="10827" RevisionGUID="7826ba62-1d6e-4ce8-b735-fd49330f05e6" CreationDate="2021-04-15T19:45:29.213" UserId="7462" Text="I messed up I am doing a double negative and that is causing the problem:&#xD;&#xA;&#xD;&#xA;`const float laplace_coeff = -0.5f * ((1.f / tan(alpha)) + (1.f / tan(beta)));`&#xD;&#xA;&#xD;&#xA;This should be positive." ContentLicense="CC BY-SA 4.0" />
  <row Id="32605" PostHistoryTypeId="50" PostId="8913" RevisionGUID="e6fa477a-934b-456d-a5cf-0691c7e2c833" CreationDate="2021-04-15T20:58:15.463" UserId="-1" />
  <row Id="32609" PostHistoryTypeId="5" PostId="5716" RevisionGUID="06d26c7a-f596-432e-ab94-64a583522e92" CreationDate="2021-04-16T15:42:02.770" UserId="6968" Comment="Fixed spelling" Text="I understand de Casteljau's algorithm and I am familiar although not fully experienced with B-Splines. I am trying to understand the geometric interpretation of B-splines through the algorithm (just like how de Casteljau's algorithm shows the geometric interpretation of Bézier curves). Thank you in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="32610" PostHistoryTypeId="4" PostId="5716" RevisionGUID="06d26c7a-f596-432e-ab94-64a583522e92" CreationDate="2021-04-16T15:42:02.770" UserId="6968" Comment="Fixed spelling" Text="How does the Lane Riesenfeld algorithm work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32611" PostHistoryTypeId="24" PostId="5716" RevisionGUID="06d26c7a-f596-432e-ab94-64a583522e92" CreationDate="2021-04-16T15:42:02.770" Comment="Proposed by 6968 approved by 7462 edit id of 559" ContentLicense="CC BY-SA 4.0" />
  <row Id="32612" PostHistoryTypeId="50" PostId="10748" RevisionGUID="4ecdee0d-378e-4f2d-8e37-94cce07fcbd1" CreationDate="2021-04-16T15:47:23.870" UserId="-1" />
  <row Id="32615" PostHistoryTypeId="5" PostId="10826" RevisionGUID="d96ddf23-4fb6-4e84-bbc6-01cb461f2196" CreationDate="2021-04-17T14:37:01.147" UserId="5778" Comment="capitalization" Text="I'm trying to extrude a face from a selected mesh in Babylon.js using the ExtrudeShape but can't figure out why I got flipped faces.&#xD;&#xA;&#xD;&#xA;The bottom extrusions always comes flipped for a reason I ignore.&#xD;&#xA;&#xD;&#xA;Since the extrudeShape method only extrudes corresponding to the xy plane, I rotate them and extrudes them but I can't figure why sometimes my normals are wrong &#xD;&#xA;&#xD;&#xA;Here is [my code on the Babylon.js playground][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://playground.babylonjs.com/#X3UQ4P#19" ContentLicense="CC BY-SA 4.0" />
  <row Id="32616" PostHistoryTypeId="4" PostId="10826" RevisionGUID="d96ddf23-4fb6-4e84-bbc6-01cb461f2196" CreationDate="2021-04-17T14:37:01.147" UserId="5778" Comment="capitalization" Text="How to extrude a face from a selected mesh in Babylon,js using the ExtrudeShape method?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32617" PostHistoryTypeId="24" PostId="10826" RevisionGUID="d96ddf23-4fb6-4e84-bbc6-01cb461f2196" CreationDate="2021-04-17T14:37:01.147" Comment="Proposed by 5778 approved by 13095 edit id of 560" ContentLicense="CC BY-SA 4.0" />
  <row Id="32618" PostHistoryTypeId="50" PostId="10045" RevisionGUID="05ec74b9-6a44-4653-a1f5-95584b648b32" CreationDate="2021-04-17T20:47:29.397" UserId="-1" />
  <row Id="32619" PostHistoryTypeId="50" PostId="2146" RevisionGUID="9e4e1d0d-a88a-4d74-82e0-68b5c8a0dcad" CreationDate="2021-04-18T08:46:44.733" UserId="-1" />
  <row Id="32620" PostHistoryTypeId="50" PostId="8886" RevisionGUID="571affc1-6b6e-4cc5-ad1a-bd6b9f02287e" CreationDate="2021-04-18T15:46:24.983" UserId="-1" />
  <row Id="32621" PostHistoryTypeId="2" PostId="10829" RevisionGUID="264666b4-5389-4ad8-b5cf-612c05990a3a" CreationDate="2021-04-18T20:53:58.537" UserId="16209" Text="I need to rewrite a short utility library, to get it working with the Brave browser (My actual question isn't about brave per se.)&#xD;&#xA;&#xD;&#xA;[canvas-color-tracker](https://github.com/vasturiano/canvas-color-tracker) - [example of it being used](https://vasturiano.github.io/canvas-color-tracker/example/canvas-medium.html) and [src/index.js](https://github.com/vasturiano/canvas-color-tracker/blob/master/src/index.js)  is short&#xD;&#xA;&#xD;&#xA;**The HTML canvas is used for mouse over and clicks to determine what object is under the cursor.**&#xD;&#xA;&#xD;&#xA;To use it with circles, you register your circle to get a color, then draw the circle in that color. Then to determine what is under the cursor, you get the color with [getImageData](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData).&#xD;&#xA;&#xD;&#xA;The trouble is what to do about anti-aliasing, the browser doesn't allow that to be turned off, and I want to be able to return nothing rather than collide with another uninvolved circle when it's edges blend into another color)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**Assuming the anti-aliasing blends linearly** How to create an ordering of points in 8bit RGB space, such that the minimum number of points are colinear without knowing the final total number of points? **What is a reasonable heuristic for this?**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Addendum, I am doing this because Brave will choose a color channel at random and randomly vary the lowest bit of it - [bit fiddling](https://github.com/brave/brave-browser/issues/9591) as a privacy feature prevent fingerprinting.&#xD;&#xA;&#xD;&#xA;I figure that if I improve on the algorithm as well as drop the lowest bits for Brave, the maintainer will be happy to use my version (or I will just use my fork anyway)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32622" PostHistoryTypeId="1" PostId="10829" RevisionGUID="264666b4-5389-4ad8-b5cf-612c05990a3a" CreationDate="2021-04-18T20:53:58.537" UserId="16209" Text="Using the HTML canvas and colors to track objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="32623" PostHistoryTypeId="3" PostId="10829" RevisionGUID="264666b4-5389-4ad8-b5cf-612c05990a3a" CreationDate="2021-04-18T20:53:58.537" UserId="16209" Text="|linear-algebra|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32627" PostHistoryTypeId="2" PostId="10831" RevisionGUID="f4ad8e95-8a2f-44f5-ba49-f738316ce231" CreationDate="2021-04-19T15:21:12.197" UserId="12025" Text="I am trying to use constructive solid geometry (CSG) and boolean operators to combine various shapes and get the outer (possibly concave) hull. This seems to work okay when using primitive shapes like cubes and spheres but I cannot figure out how to use other shapes.&#xD;&#xA;&#xD;&#xA;Can I get a signed distance to a mesh? How would I calculate it?&#xD;&#xA;&#xD;&#xA;I found https://www.iquilezles.org/www/articles/sdfbounding/sdfbounding.htm which seems like it might be what I want, specifically the section where they use an `sdMesh` method, but I do not understand where the `sdTriangles` method comes from. The only `sdTriangle` method that I found is on the 2D Distance Functions page. Do I use that somehow? Will that give a negative number if the point is &quot;behind&quot; the triangle in 3D space (i.e. inside the mesh)?&#xD;&#xA;&#xD;&#xA;I am working in Unity / C#, but can translate from other languages." ContentLicense="CC BY-SA 4.0" />
  <row Id="32628" PostHistoryTypeId="1" PostId="10831" RevisionGUID="f4ad8e95-8a2f-44f5-ba49-f738316ce231" CreationDate="2021-04-19T15:21:12.197" UserId="12025" Text="How can I get a signed distance (SDF) from a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32629" PostHistoryTypeId="3" PostId="10831" RevisionGUID="f4ad8e95-8a2f-44f5-ba49-f738316ce231" CreationDate="2021-04-19T15:21:12.197" UserId="12025" Text="|3d|algorithm|mesh|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32630" PostHistoryTypeId="2" PostId="10832" RevisionGUID="fa44ef75-8bd0-48ce-bff7-15b02402775e" CreationDate="2021-04-19T16:53:25.107" UserId="482" Text="# luser droog&#xD;&#xA;&#xD;&#xA;Howdy, I've done graphics programming primarily in PostScript, but have also used OpenGL and sdl, as well as raw X11 and xcb.&#xD;&#xA;&#xD;&#xA;I think the task of moderation in a smaller site like this one will be primarily focused on removing spam, guiding new users concerning SE rules and the community rules, migrating comment discussions to chat, and raising larger issues on meta or with other mods and SE.&#xD;&#xA;&#xD;&#xA;I try to be patient and fair, never downvote without a comment, and use the bounty mechanism to reward outstanding answers. I've been active on multiple sites for many years, including music, codegolf, and stackoverflow. I'm also active in the \[comp.lang.postscript\](https://groups.google.com/g/comp.lang.postscript) newsgroup." ContentLicense="CC BY-SA 4.0" />
  <row Id="32631" PostHistoryTypeId="5" PostId="10763" RevisionGUID="ea8bdeab-751f-4bb8-b3e4-6a2fb31810c6" CreationDate="2021-04-19T16:54:55.763" UserId="2287" Comment="formatting" Text="I would like a help to understand the following line of code:&#xD;&#xA;&#xD;&#xA;    return float3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));&#xD;&#xA;&#xD;&#xA;I've seen some places calling it gamma correction, but I don't know if it's correct.&#xD;&#xA;&#xD;&#xA;If it really is a gamma correction how does it work?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;[![No Correction][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![With Correction][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fnpRg.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ggIev.jpg&#xD;&#xA;With Correction&#xD;&#xA;&#xD;&#xA;I liked the artistic result of this, I will keep it. I asked the question to understand better." ContentLicense="CC BY-SA 4.0" />
  <row Id="32632" PostHistoryTypeId="24" PostId="10763" RevisionGUID="ea8bdeab-751f-4bb8-b3e4-6a2fb31810c6" CreationDate="2021-04-19T16:54:55.763" Comment="Proposed by 2287 approved by -1 edit id of 558" ContentLicense="CC BY-SA 4.0" />
  <row Id="32633" PostHistoryTypeId="4" PostId="10763" RevisionGUID="d38bce05-e257-4243-9f77-b42db2089561" CreationDate="2021-04-19T16:54:55.763" UserId="482" Comment="formatting, replace &quot;doubt&quot; with &quot;question&quot;" Text="Question about function for color" ContentLicense="CC BY-SA 4.0" />
  <row Id="32635" PostHistoryTypeId="2" PostId="10833" RevisionGUID="1ab05e6e-60de-4a27-a327-059d60b11774" CreationDate="2021-04-19T18:55:26.427" UserId="113" Text="Generally it boils down to finding the nearest element. Computing distance to it. Checking the normal to tell if inside or out. There are a number of edge cases. Also you usually compute the &quot;angle weighted psuedonormal&quot; as its called.&#xD;&#xA;&#xD;&#xA;Here's the usual reference &quot;Signed Distance Computation using the Angle&#xD;&#xA;Weighted Pseudo-normal&quot; by J. Bærentzen.&#xD;&#xA;&#xD;&#xA;There are many such libraries with the implementation if you don't want to write it yourself. I personally use [ImplicitPolyDataDistance][1] function in VTK. Also a fan of [LibIGLs][2]. But there are many lighter weight ones to do it as well, https://github.com/Magnus2/MeshSdf.&#xD;&#xA;&#xD;&#xA;It's also worth mentioning that you can compute SDFs in other less accurate ways for more performance. Namely, another popular approach is to voxelize/binarize a shape and compute the SDF of the binary image instead. The distances at the boundary of the shape won't be exact but it is a good estimate and often faster.&#xD;&#xA;&#xD;&#xA;EDIT: Also worth mentioning narrow bands and hierarchical SDFs. Those are very popular as well. Instead of computing SDF values for every element. Say in an image. We can compute SDF values only near the boundary of the shape. With an octree you can compute it at each vertex and interpolate to get inbetween estimates. There are special methods for computing these as well and libraries such as OpenVDB.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vtk.org/doc/nightly/html/classvtkImplicitPolyDataDistance.html&#xD;&#xA;  [2]: https://libigl.github.io/tutorial/#signed-distances" ContentLicense="CC BY-SA 4.0" />
  <row Id="32636" PostHistoryTypeId="2" PostId="10834" RevisionGUID="88d26d4b-da4c-4435-8179-8ddcd76c47b6" CreationDate="2021-04-19T22:13:12.213" UserId="8009" Text="Welcome to the world of 8-bit graphics!  Other answers here are excellent, and most of what you need to know is described well on [Wikipedia](https://en.wikipedia.org/wiki/Gamma_correction) but let me take you on a human-friendly journey of understanding that I wish someone would have taken me on when I was younger.&#xD;&#xA;&#xD;&#xA;The first realization that you need to make is that a pixel with RGB values 128, 128, 128 isn't &quot;half as bright&quot; as a pixel that is outputting 255, 255, 255 (white).  **It's not even close!**&#xD;&#xA;&#xD;&#xA;You can check this by making a checkerboard image of black and white pixels (which, on average, will be 50% as bright as a white image, by definition) and compare the brightness of that to a swatch of 128, 128, 128.  You'll find the swatch is much too dark.  A value that is closest to 50% is actually somewhere between 188 and 189 but also depends on your display.&#xD;&#xA;&#xD;&#xA;[![a test pattern that reveals the gamma issue][1]][1]&#xD;&#xA;&#xD;&#xA;_It's very important to look at this picture with 1:1 scaling._&#xD;&#xA;&#xD;&#xA;If you can &quot;get&quot; this (notice the effect) then you are ready to begin understanding why the 128, 128, 128 swatch seems too dark.&#xD;&#xA;&#xD;&#xA;Most software developers discover this property by accident. If you just perform arithmetic on RGB color values in the intuitive (but naïve) way, like for example to compute an average color of two pixels as in `(a+b)/2`, you'll find that it doesn't work.  Things look too dark.  :( In fact, you can completely finish that awesome first-person shooter 3D engine you've always aspired to create, only to discover that all your graphics look too dark and shadowy.&#xD;&#xA;&#xD;&#xA;___This is because the RGB codes do not correspond to brightness levels in a linear way.___&#xD;&#xA;&#xD;&#xA;RGB codes are non-linear.  You should have the moment of realization where you ask yourself, &quot;but wait, `(a+b)/2` is the formula for _average_, so why doesn't it produce an _average_ color?&quot;  Or maybe it will occur to you by asking &quot;Why, when I compute (0+255)/2 and get 128 (rounding up of course) do I not get a color that is half as bright as white?&quot;&#xD;&#xA;&#xD;&#xA;Once you get that feeling where it ___seems like arithmetic is broken___, you'll be ready to understand that the encoding used for all pictures in typical image files are actually encoded in a **non-linear color space** such as sRGB.  To do arithmetic on colors correctly you must:&#xD;&#xA;&#xD;&#xA;1. convert the non-linear RGB color codes to a linear color space&#xD;&#xA;2. *then* you can do normal arithmetic, like computing averages or whatever&#xD;&#xA;3. then you must finally convert the result back to the original non-linear RGB encoding to be displayed by your display device or stored in your image file or texture or whatever.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Ever notice how it's easy to tell the difference between 1 pound and 2 pounds, but it's hard to tell the difference between having 101 pounds and 102 pounds?  They're both different by 1 pound, but the __relative__ difference is twice as heavy for the small weights, but 102 is barely a 1% relative increase from 101 -- very difficult to notice.&#xD;&#xA;&#xD;&#xA;Well your eyes work the same way with light!  It's very easy to tell the difference (in a room with no other light sources) between the brightness from 1 light bulb vs the light from 2 light bulbs. But it's much harder to tell the difference in brightness between 101 light bulbs and 102 light bulbs.&#xD;&#xA;&#xD;&#xA;Here's where engineers got clever with 8-bit graphics...&#xD;&#xA;&#xD;&#xA;Since, with 8-bit graphics, we only have 256 different codes we can store, why waste so many of those different codes on intensities people can't even tell apart?  Instead, the designers choose 256 different codes where each successive code is an equal relative increase in brightness compared to the previous code.  All codes are equally useful, and it's much more efficient, right?&#xD;&#xA;&#xD;&#xA;If you want to get a tiny bit mathematical now, it means that the intensity of light you get from using intensity `n+1` divided by the intensity of light you get from using an intensity of `n` is a **constant**.  (obviously something special happens for 0.  _Any_ amount of light will always be _infinitely_ brighter than no light, relatively speaking).&#xD;&#xA;&#xD;&#xA;And now that we have our toe dipped into the waters of the mathematical ocean, you're finally ready to at least get a hint of what the word **gamma** means.&#xD;&#xA;&#xD;&#xA;The actual term **gamma** refers to the __gamma function__, which is a function with that nifty property where `f(x+1) = k * f(x)`.  To go get from an intensity to a code you first raise the linear intensity (a number between 0 and 1) to the power of 2.2, which will also be a number between 0 and 1, then spread that range out over the 256 code values available to you.  To perform the reverse conversion, you first convert your RGB coded number between 0 to 255 to a number between 0 and 1, and then &quot;undo&quot; the gamma function by raising it to the power of 1/2.2 to arrive at a linear intensity between 0.0 and 1.0.  Historically the exponent 2.2 was chosen because it coincidentally matches some properties of old CRT monitors (the ratio of power of the electron beam to intensity of the light produced is similarly non-linear).&#xD;&#xA;&#xD;&#xA;In practice the internet actually uses a slightly smarter color space called *sRGB*.  It's still a non-linear function and it's very close to gamma 2.2, but has some nice properties where there aren't so many really dark values in the low end -- again, trying to make more efficient use of the 256 levels of intensity available to us in 8-bit graphics.&#xD;&#xA;&#xD;&#xA;So let's circle back to your actual question:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;return float3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is **half** of a color conversion.  It is assuming that we have linear intensity values stored in `color` and it is applying the gamma function (raising it to the power of 2.2) to get closer to the Normalized (0.0 to 1.0) encoded values that are suitable for putting into a picture file or displaying on the screen.  OpenGL will unnormalize these values and write a corresponding 8-bit integer representation of that value in the range 0-255.&#xD;&#xA;&#xD;&#xA;This works great for what I would call &quot;synthetic&quot; colors.  Like if you are simulating some light source or the attenuation from angle of incidence or something.  But if you were reading values from an image file, then you would furthermore need to use a sampler that performed the inverse of this correction.  It's important to get the sampler to do it because there's hardware built in to your GPU to do things like bi-linear interpolation (sample 4 pixels and compute an intermediate value).  Without activating that inverse correction factor, you are at risk of doing the _broken arithmetic_ on your color values and textures get weird artifacts in them caused by introducing colors that are too dark.&#xD;&#xA;&#xD;&#xA;Here's an example of reducing that previous image in size ever so slightly using an **incorrect** technique - that is quite frankly found everywhere in the world even though it's wrong.  &#xD;&#xA;&#xD;&#xA;[![Incorrectly scaled image][2]][2]&#xD;&#xA;&#xD;&#xA;_This image was rescaled naïvely without gamma correction and will look bad, with artifacts that are too dark._&#xD;&#xA;&#xD;&#xA;So the next generation of graphics developers all have a responsibility to learn the basics so that we don't get dark looking graphics everywhere that are filled with artifacts.  My personal pet peeve is sci-fi movies where the stars in the black sky throb bright and dark as the camera pans slowly because the people that rendered it didn't get the gamma conversions correct!&#xD;&#xA;&#xD;&#xA;I hope this helps.  I need to give a disclaimer:  I've intentionally used some terms incorrectly like _brightness_ and _intensity_ (just think &quot;shades of gray&quot;) because you need to begin your journey with familiar language -- then learn the scientifically correct terms later where you will learn about things like _luma_, _luminosity_, _luminous intensity_, _brightness_, _perceived brightness_, etc. etc.  After you get the terminology right, the next dragon you face is named **color**.  Color is hard to get right and human perception makes it especially complex.  I've only scratched the surface here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KXT20.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Y00Ah.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32637" PostHistoryTypeId="50" PostId="8321" RevisionGUID="58083e60-b993-4d26-ab28-483e5f2a17d6" CreationDate="2021-04-20T06:04:49.893" UserId="-1" />
  <row Id="32638" PostHistoryTypeId="5" PostId="10834" RevisionGUID="57302b60-84a4-439d-8536-8bafe73ff3a9" CreationDate="2021-04-20T14:19:39.597" UserId="8009" Comment="minor change, removed extraneous word" Text="Welcome to the world of 8-bit graphics!  Other answers here are excellent, and most of what you need to know is described well on [Wikipedia](https://en.wikipedia.org/wiki/Gamma_correction) but let me take you on a human-friendly journey of understanding that I wish someone would have taken me on when I was younger.&#xD;&#xA;&#xD;&#xA;The first realization that you need to make is that a pixel with RGB values 128, 128, 128 isn't &quot;half as bright&quot; as a pixel that is outputting 255, 255, 255 (white).  **It's not even close!**&#xD;&#xA;&#xD;&#xA;You can check this by making a checkerboard image of black and white pixels (which, on average, will be 50% as bright as a white image, by definition) and compare the brightness of that to a swatch of 128, 128, 128.  You'll find the swatch is much too dark.  A value that is closest to 50% is actually somewhere between 188 and 189 but also depends on your display.&#xD;&#xA;&#xD;&#xA;[![a test pattern that reveals the gamma issue][1]][1]&#xD;&#xA;&#xD;&#xA;_It's very important to look at this picture with 1:1 scaling._&#xD;&#xA;&#xD;&#xA;If you can &quot;get&quot; this (notice the effect) then you are ready to begin understanding why the 128, 128, 128 swatch seems too dark.&#xD;&#xA;&#xD;&#xA;Most software developers discover this property by accident. If you just perform arithmetic on RGB color values in the intuitive (but naïve) way, like for example to compute an average color of two pixels as in `(a+b)/2`, you'll find that it doesn't work.  Things look too dark.  :( In fact, you can completely finish that awesome first-person shooter 3D engine you've always aspired to create, only to discover that all your graphics look too dark and shadowy.&#xD;&#xA;&#xD;&#xA;___This is because the RGB codes do not correspond to brightness levels in a linear way.___&#xD;&#xA;&#xD;&#xA;RGB codes are non-linear.  You should have the moment of realization where you ask yourself, &quot;but wait, `(a+b)/2` is the formula for _average_, so why doesn't it produce an _average_ color?&quot;  Or maybe it will occur to you by asking &quot;Why, when I compute (0+255)/2 and get 128 (rounding up of course) do I not get a color that is half as bright as white?&quot;&#xD;&#xA;&#xD;&#xA;Once you get that feeling where it ___seems like arithmetic is broken___, you'll be ready to understand that the encoding used for all pictures in typical image files are actually encoded in a **non-linear color space** such as sRGB.  To do arithmetic on colors correctly you must:&#xD;&#xA;&#xD;&#xA;1. convert the non-linear RGB color codes to a linear color space&#xD;&#xA;2. *then* you can do normal arithmetic, like computing averages or whatever&#xD;&#xA;3. then you must finally convert the result back to the original non-linear RGB encoding to be displayed by your display device or stored in your image file or texture or whatever.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Ever notice how it's easy to tell the difference between 1 pound and 2 pounds, but it's hard to tell the difference between having 101 pounds and 102 pounds?  They're both different by 1 pound, but the __relative__ difference is twice as heavy for the small weights, but 102 is barely a 1% relative increase from 101 -- very difficult to notice.&#xD;&#xA;&#xD;&#xA;Well your eyes work the same way with light!  It's very easy to tell the difference (in a room with no other light sources) between the brightness from 1 light bulb vs the light from 2 light bulbs. But it's much harder to tell the difference in brightness between 101 light bulbs and 102 light bulbs.&#xD;&#xA;&#xD;&#xA;Here's where engineers got clever with 8-bit graphics...&#xD;&#xA;&#xD;&#xA;Since, with 8-bit graphics, we only have 256 different codes we can store, why waste so many of those different codes on intensities people can't even tell apart?  Instead, the designers choose 256 different codes where each successive code is an equal relative increase in brightness compared to the previous code.  All codes are equally useful, and it's much more efficient, right?&#xD;&#xA;&#xD;&#xA;If you want to get a tiny bit mathematical now, it means that the intensity of light you get from using intensity `n+1` divided by the intensity of light you get from using an intensity of `n` is a **constant**.  (obviously something special happens for 0.  _Any_ amount of light will always be _infinitely_ brighter than no light, relatively speaking).&#xD;&#xA;&#xD;&#xA;And now that we have our toe dipped into the waters of the mathematical ocean, you're finally ready to at least get a hint of what the word **gamma** means.&#xD;&#xA;&#xD;&#xA;The actual term **gamma** refers to the __gamma function__, which is a function with that nifty property where `f(x+1) = k * f(x)`.  To get from an intensity to a code you first raise the linear intensity (a number between 0 and 1) to the power of 2.2, which will also be a number between 0 and 1, then spread that range out over the 256 code values available to you.  To perform the reverse conversion, you first convert your RGB coded number between 0 to 255 to a number between 0 and 1, and then &quot;undo&quot; the gamma function by raising it to the power of 1/2.2 to arrive at a linear intensity between 0.0 and 1.0.  Historically the exponent 2.2 was chosen because it coincidentally matches some properties of old CRT monitors (the ratio of power of the electron beam to intensity of the light produced is similarly non-linear).&#xD;&#xA;&#xD;&#xA;In practice the internet actually uses a slightly smarter color space called *sRGB*.  It's still a non-linear function and it's very close to gamma 2.2, but has some nice properties where there aren't so many really dark values in the low end -- again, trying to make more efficient use of the 256 levels of intensity available to us in 8-bit graphics.&#xD;&#xA;&#xD;&#xA;So let's circle back to your actual question:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;return float3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is **half** of a color conversion.  It is assuming that we have linear intensity values stored in `color` and it is applying the gamma function (raising it to the power of 2.2) to get closer to the Normalized (0.0 to 1.0) encoded values that are suitable for putting into a picture file or displaying on the screen.  OpenGL will unnormalize these values and write a corresponding 8-bit integer representation of that value in the range 0-255.&#xD;&#xA;&#xD;&#xA;This works great for what I would call &quot;synthetic&quot; colors.  Like if you are simulating some light source or the attenuation from angle of incidence or something.  But if you were reading values from an image file, then you would furthermore need to use a sampler that performed the inverse of this correction.  It's important to get the sampler to do it because there's hardware built in to your GPU to do things like bi-linear interpolation (sample 4 pixels and compute an intermediate value).  Without activating that inverse correction factor, you are at risk of doing the _broken arithmetic_ on your color values and textures get weird artifacts in them caused by introducing colors that are too dark.&#xD;&#xA;&#xD;&#xA;Here's an example of reducing that previous image in size ever so slightly using an **incorrect** technique - that is quite frankly found everywhere in the world even though it's wrong.  &#xD;&#xA;&#xD;&#xA;[![Incorrectly scaled image][2]][2]&#xD;&#xA;&#xD;&#xA;_This image was rescaled naïvely without gamma correction and will look bad, with artifacts that are too dark._&#xD;&#xA;&#xD;&#xA;So the next generation of graphics developers all have a responsibility to learn the basics so that we don't get dark looking graphics everywhere that are filled with artifacts.  My personal pet peeve is sci-fi movies where the stars in the black sky throb bright and dark as the camera pans slowly because the people that rendered it didn't get the gamma conversions correct!&#xD;&#xA;&#xD;&#xA;I hope this helps.  I need to give a disclaimer:  I've intentionally used some terms incorrectly like _brightness_ and _intensity_ (just think &quot;shades of gray&quot;) because you need to begin your journey with familiar language -- then learn the scientifically correct terms later where you will learn about things like _luma_, _luminosity_, _luminous intensity_, _brightness_, _perceived brightness_, etc. etc.  After you get the terminology right, the next dragon you face is named **color**.  Color is hard to get right and human perception makes it especially complex.  I've only scratched the surface here.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KXT20.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Y00Ah.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32639" PostHistoryTypeId="5" PostId="10767" RevisionGUID="dc600a0e-812d-4b08-b0fd-eed7f3a8cb7f" CreationDate="2021-04-20T17:07:19.870" UserId="7952" Comment="Added a list of formats and a few comments." Text="Gamma correction originated as a way of correcting the output of a CRT to be a better fit for the human visual system. Modern monitors don't need to do it, but, they followed the CRT and there were millions of CRT's that all had gamma correction and most signals already had gamma correction in them. Today we have a chicken and egg problem...but reversed. Millions of clucking hardware chickens all speaking gamma...&#xD;&#xA;&#xD;&#xA;The flip side is that us humans don't think well in the land of exponential values, but we do think well in terms of linear values. So software for graphics code tends to remove the gamma then we can multiply add and manipulate in an intuitive manner, and convert it back to gamma for display.&#xD;&#xA;&#xD;&#xA;Modern hardware has specialty components that do this on the fly so the generally accepted practice is to set up the graphics hardware to handle this so we don't have to worry about it as programmers. But sometimes it can be useful.&#xD;&#xA;&#xD;&#xA;-------&#xD;&#xA;Updates based on comments (after rereading this I added a few more updates)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Gamma correction has a second benefit for low precision formats like the common sRGB 8 bit format. (invented in the 90's to match hardware of the day) It redistributes the available values placing more values in the &quot;dim&quot; region where human's can better perceive changes in *brightness*. This redistribution is why gamma correction is often called gamma *compression*.&#xD;&#xA;&#xD;&#xA;This is not a correction for human vision, it is a correction for the limitations of the 8 bit format. Higher precision formats do not need to store gamma correction and (generally) have gamma applied to them only when converting to a lower precision format.&#xD;&#xA;&#xD;&#xA;Here is a breakdown of common formats with respect to gamma:&#xD;&#xA;&#xD;&#xA; - 8 bit formats like sRGB - Gamma is an essential component of this format&#xD;&#xA; - 10 bit formats like HRD10 - Usable without gamma, but adding gamma improves this format considerably.&#xD;&#xA; - 12 bit formats like Dolby Vision - Gamma is starting to be redundant from 12 bits and up. There is enough separation between linear color brightness that it is increasingly difficult for to see the color separation, but most people can still detect some banding in the dark colors.&#xD;&#xA; - 14 bits formats like RAW formats from professional cameras. Professional quality monitors that use 3D look up tables to do color matching begin to give truly magnificent images. At this point most specs include phrases like &quot;A gamma of 2.2 is applied since it is expected that images will be viewed on gamma corrected devices&quot;. An 8 bit image next to a 14 bit can be perspective changing for viewers.&#xD;&#xA; - 16 bit I don't have a hardware example, but some software allow images to be edited in 16bit formats.&#xD;&#xA;&#xD;&#xA;The very amazing human eye can perceive 1,000,000 nits of difference in brightness by dynamically adapting itself to the available lighting. But is especially adapted to see more changes in *brightness* in dark situations. The CRT when it was invented struggled to display 100 nits of brightness. Leaving 999,900 nits on the table. So gamma was applied to the signal to take advantage of our ability to see better in low lighting. This was a limitation of the CRT not our vision.&#xD;&#xA;&#xD;&#xA;It is common for modern monitors to reach 300-500 nits, with some models getting up to 1000 nits or more. That extra available brightness means that gamma is not really needed for anything but historical compatibility. (this is a bit of an overstatement, monitors really need to get into the 10,000 nit range before gamma starts becoming redundant)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;When working with image data it is best to configure the hardware to handle gamma correction for us and use methods such as tone mapping to achieve a specialized appearance. This allows the hardware to load images that are stored as a variety of color formats such as sRGB and HDR into a common space that is well defined, where code can then perform its calculations and send that result to the hardware where it is converted to a format that is specific to the device being used to display it. (which is often a gamma corrected format)&#xD;&#xA;&#xD;&#xA;I am not tying to say that this image is &quot;wrong&quot;, everyone should take the time to create images like this to better understand gamma correction." ContentLicense="CC BY-SA 4.0" />
  <row Id="32640" PostHistoryTypeId="50" PostId="8695" RevisionGUID="660dfc93-0191-4158-ae63-763f64647773" CreationDate="2021-04-20T20:46:53.550" UserId="-1" />
  <row Id="32641" PostHistoryTypeId="2" PostId="10835" RevisionGUID="e7c560bb-88b1-494c-924a-b878b924731c" CreationDate="2021-04-21T08:35:49.247" UserId="16224" Text="First of all I have to say that I am really new in the world of Computer Graphics. I apologise if some of my questions may appear trivial.&#xD;&#xA;I am currently using a non-commercial ray tracing and physically based rendering software. I didn't have any problems with this until now : I have a scene where an .obj file representing a satellite is placed surrounded by a environment map light.&#xD;&#xA;Here is an exemple of my problem appearing on the solar pannels :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have no idea where these strange forms could come from. I have to say that for this picture, the .obj file representating the solar pannel is a very simple parallelepiped. I also tried to suppress the other face of the object but nothing changed.&#xD;&#xA;&#xD;&#xA;I saw this exchange (https://computergraphics.stackexchange.com/questions/2192/cause-of-shadow-acne) that could maybe be related to my problem, but if someone has an idea of what could be the cause, I would be happy to hear it!&#xD;&#xA;&#xD;&#xA;Thank you to all and have a nice day.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KTHlk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32642" PostHistoryTypeId="1" PostId="10835" RevisionGUID="e7c560bb-88b1-494c-924a-b878b924731c" CreationDate="2021-04-21T08:35:49.247" UserId="16224" Text="What can be the cause of some strange ray shadows artefacts on a perfect flat surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32643" PostHistoryTypeId="3" PostId="10835" RevisionGUID="e7c560bb-88b1-494c-924a-b878b924731c" CreationDate="2021-04-21T08:35:49.247" UserId="16224" Text="|raytracing|shadow|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32644" PostHistoryTypeId="2" PostId="10836" RevisionGUID="0ac3b49f-c5fc-42a9-8ad1-ad232a6f8b24" CreationDate="2021-04-21T09:37:28.503" UserId="16224" Text="It appeared that it was exactly the problem explained in the link of my original post (https://computergraphics.stackexchange.com/questions/2192/cause-of-shadow-acne).&#xD;&#xA;The shadow function offset has been increased and the problem is solved!" ContentLicense="CC BY-SA 4.0" />
  <row Id="32645" PostHistoryTypeId="4" PostId="10835" RevisionGUID="5491116a-3366-4230-bc12-350e37abe741" CreationDate="2021-04-21T09:38:30.913" UserId="16224" Comment="edited title" Text="What can be the cause of some strange ray shadows artefacts on a perfectly flat surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32646" PostHistoryTypeId="2" PostId="10837" RevisionGUID="f283574e-6ae0-44df-9f5c-076af30956dd" CreationDate="2021-04-21T13:38:35.433" UserId="9749" Text="What you want is a Distance Transform algorithm which can be computed very fast using [JFA][1], the steps are basically:&#xA;&#xA; &#xA; - Define where you want your seeds (I guess points that make up your mesh.&#xA; &#xA; - At each log iteration find wether or not the current position is better than the last one, if it is add it to a texture (3d in this case).&#xA;&#xA;Not sure of the details but in this video [Ryan Brucks][2] shows the Distance Field of a mesh computed by JFA using (a compute shader I guess?) on UE4.&#xA;&#xA;Also check [this link by Alan Wolfe][3].&#xA;&#xA;&#xA;  [1]: http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf&#xA;  [2]: https://youtu.be/GvI7qt3kmz4&#xA;  [3]: https://blog.demofox.org/2016/02/29/fast-voronoi-diagrams-and-distance-dield-textures-on-the-gpu-with-the-jump-flooding-algorithm/" ContentLicense="CC BY-SA 4.0" />
  <row Id="32647" PostHistoryTypeId="2" PostId="10838" RevisionGUID="5f31f8e7-6824-4df6-b8d0-9e8f9d875ca3" CreationDate="2021-04-21T13:44:19.387" UserId="38" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="32648" PostHistoryTypeId="1" PostId="10838" RevisionGUID="5f31f8e7-6824-4df6-b8d0-9e8f9d875ca3" CreationDate="2021-04-21T13:44:19.387" UserId="38" ContentLicense="CC BY-SA 4.0" />
  <row Id="32649" PostHistoryTypeId="2" PostId="10839" RevisionGUID="ea8e0c6a-68b8-4b61-9887-cfef63935779" CreationDate="2021-04-21T13:44:19.387" UserId="38" Text="An SDF is a function which takes a position as an input, and outputs the distance from that position to the nearest part of a shape." ContentLicense="CC BY-SA 4.0" />
  <row Id="32650" PostHistoryTypeId="1" PostId="10839" RevisionGUID="ea8e0c6a-68b8-4b61-9887-cfef63935779" CreationDate="2021-04-21T13:44:19.387" UserId="38" ContentLicense="CC BY-SA 4.0" />
  <row Id="32651" PostHistoryTypeId="2" PostId="10840" RevisionGUID="1b710821-ec51-4187-bc90-b0e2998ffa8e" CreationDate="2021-04-21T13:46:52.047" UserId="38" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="32652" PostHistoryTypeId="1" PostId="10840" RevisionGUID="1b710821-ec51-4187-bc90-b0e2998ffa8e" CreationDate="2021-04-21T13:46:52.047" UserId="38" ContentLicense="CC BY-SA 4.0" />
  <row Id="32653" PostHistoryTypeId="2" PostId="10841" RevisionGUID="640fb966-7aba-48a2-94bf-2b3f1ea5c15a" CreationDate="2021-04-21T13:46:52.047" UserId="38" Text="NonUniform B-Spline (NURBS) is a method to describe parametric curves/surfece. TYpically used as base poriniteves in CAD modelling." ContentLicense="CC BY-SA 4.0" />
  <row Id="32654" PostHistoryTypeId="1" PostId="10841" RevisionGUID="640fb966-7aba-48a2-94bf-2b3f1ea5c15a" CreationDate="2021-04-21T13:46:52.047" UserId="38" ContentLicense="CC BY-SA 4.0" />
  <row Id="32655" PostHistoryTypeId="50" PostId="10754" RevisionGUID="ad48afd5-1ab6-4d7a-a32e-ea38a423274f" CreationDate="2021-04-21T20:03:45.343" UserId="-1" />
  <row Id="32656" PostHistoryTypeId="50" PostId="5697" RevisionGUID="42e36561-e8c9-4704-9dae-45e12b4de04d" CreationDate="2021-04-22T06:02:30.270" UserId="-1" />
  <row Id="32660" PostHistoryTypeId="50" PostId="10425" RevisionGUID="38afbc33-8166-4e26-b7d2-2267604f1114" CreationDate="2021-04-23T05:44:04.160" UserId="-1" />
  <row Id="32661" PostHistoryTypeId="50" PostId="8721" RevisionGUID="4de908bd-3ece-4486-a496-734d00a97487" CreationDate="2021-04-23T09:04:50.457" UserId="-1" />
  <row Id="32668" PostHistoryTypeId="50" PostId="8209" RevisionGUID="a5914e9d-b4e1-47a0-a01a-c41ad4c9af26" CreationDate="2021-04-24T01:36:08.547" UserId="-1" />
  <row Id="32669" PostHistoryTypeId="2" PostId="10844" RevisionGUID="1666e559-9383-4a12-b00e-17f7b2edc1fe" CreationDate="2021-04-24T17:49:38.940" UserId="16243" Text="I am implementing a pathtracer with both indirect and direct light sampling at each intersection (I believe the &quot;direct light sampling&quot; part is also referred to as &quot;next event estimation&quot;). I am trying to compute both direct-diffuse and direct-specular contributions of the light sources.&#xD;&#xA;&#xD;&#xA;For that, I use a normalized Phong BRDF (formula taken from [here][1]), in which the contribution of each light source at an intersection is defined as (pseudo-code) :&#xD;&#xA;```&#xD;&#xA;directLighting = diffuse() + specular() / (intersection.location - light.location).lengthSquared();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;diffuse() {&#xD;&#xA;    normalization = 1.0f / PI;&#xD;&#xA;    return material.metal ? Color::BLACK :&#xD;&#xA;                            lightDotN * lightIntensity * lightColor * material.albedo * normalization;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;specular() {&#xD;&#xA;    if (observerDotReflected &lt;= 0.0f) {&#xD;&#xA;        return Color::BLACK;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    normalization = (material.smoothness + 1.0f) / (2.0f * PI);&#xD;&#xA;    return (observerDotReflected ^ material.smoothness) * lightIntensity * lightColor *&#xD;&#xA;           (material.metal ? material.albedo : material.specularity) * normalization;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This works well as long as I have pretty rough objects in my scene (below, a rough metallic sphere with `smoothness = 25.0f`, and a rough diffuse sphere with `smoothness = 2.0f`).&#xD;&#xA;[![clean][2]][2]&#xD;&#xA;&#xD;&#xA;However, as soon as I introduce a very smooth and reflective object (below, a metallic sphere with `smoothness = 10'000.0f`), two problems appear : the specular lobe on the sphere is very ugly (we can see the individual points that resulted in non-zero specular contribution), and hot pixels/fireflies appear everywhere in the scene.&#xD;&#xA;[![fireflies][3]][3]&#xD;&#xA;&#xD;&#xA;I think I understand why these exist : when the smoothness is high, the specular Phong BRDF returns ~0 almost all the time (when `observerDotReflected` is not very close to 1), but sometimes returns extremely bright values, which cause fireflies at other points in the scene when they are the result of an indirect bounce.&#xD;&#xA;&#xD;&#xA;Note that the same effect appears whether I use point lights, or sphere lights (with a non-zero volume that I randomly sample).&#xD;&#xA;&#xD;&#xA;Is there a conventional way to solve this problem ? I have seen [this answer][4] where the author indicates that for mirror-like specular surfaces (i.e. smoothness -&gt; infinity), you should not directly sample specular lighting, but rather rely on indirect bounces intersecting light objects. Is this the only way to go about direct specular lighting ? Are there other solutions to this variance problem ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.farbrausch.de/~fg/stuff/phong.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/N4S8X.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ojuqM.png&#xD;&#xA;  [4]: https://computergraphics.stackexchange.com/a/5153/16243" ContentLicense="CC BY-SA 4.0" />
  <row Id="32670" PostHistoryTypeId="1" PostId="10844" RevisionGUID="1666e559-9383-4a12-b00e-17f7b2edc1fe" CreationDate="2021-04-24T17:49:38.940" UserId="16243" Text="Path tracing : fireflies/hot pixels when directly sampling lights" ContentLicense="CC BY-SA 4.0" />
  <row Id="32671" PostHistoryTypeId="3" PostId="10844" RevisionGUID="1666e559-9383-4a12-b00e-17f7b2edc1fe" CreationDate="2021-04-24T17:49:38.940" UserId="16243" Text="|raytracing|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32672" PostHistoryTypeId="50" PostId="10430" RevisionGUID="7a80b696-9049-4354-b027-f51e51c8a5f0" CreationDate="2021-04-25T15:06:30.760" UserId="-1" />
  <row Id="32673" PostHistoryTypeId="2" PostId="10845" RevisionGUID="018d8c84-e9fa-4810-bb6e-f5c94046aeb8" CreationDate="2021-04-25T18:18:53.747" UserId="15772" Text="I'm a super beginner to GFX. So far I've learned about 3 shading models when rendering meshes&#xD;&#xA;The first is **Flat Shading**. I seem to understand this, from my understanding, you take the normal of the face/polygon, apply your lighting model based on that, and the light angle, and other parameters and based on what you get, shade your polygon with  a single color, done.&#xD;&#xA;&#xD;&#xA;I've learned about Phong Shading as well. Apparently Phong Shading takes the normals of the vertices of the polygon, and interpolates them for each pixel, thus sort of 'creating' a normal per every pixel, and shade accordingly. It is shaded per pixel, and as such you get smooth results&#xD;&#xA;&#xD;&#xA;Gouraud shading is what I am most confused by. I referred to many online sources including this [one][1] and what I dont understand is how exactly the polygon is shaded? Is it shaded per pixel?&#xD;&#xA;&#xD;&#xA;From my understanding, Gouraud is the same as Phong shading except that unlike Phong interpolating vertex normals, and creates normals  for every pixel and shading each pixel, Gouraud interpolates just the vertex normals of the polygon.&#xD;&#xA;&#xD;&#xA;Im not quite sure what it does after that. Does it take these interpolated vertex normals and shade the polygon in a single color? Does it shade pixel by pixel just like Phong? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.javatpoint.com/computer-graphics-gouraud-shading&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32674" PostHistoryTypeId="1" PostId="10845" RevisionGUID="018d8c84-e9fa-4810-bb6e-f5c94046aeb8" CreationDate="2021-04-25T18:18:53.747" UserId="15772" Text="How exactly does Gouraud shading apply color across a polygon? Does it do it by pixel or is it some other method?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32675" PostHistoryTypeId="3" PostId="10845" RevisionGUID="018d8c84-e9fa-4810-bb6e-f5c94046aeb8" CreationDate="2021-04-25T18:18:53.747" UserId="15772" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32676" PostHistoryTypeId="2" PostId="10846" RevisionGUID="1715d185-99a9-41fa-b7b5-a3751fed3543" CreationDate="2021-04-25T19:15:57.837" UserId="113" Text="The difference is in the number of lighting calculations done. Where the lighting calculation produces some color.&#xD;&#xA;&#xD;&#xA;Flat does one per face, uses the color across the face.&#xD;&#xA;&#xD;&#xA;Gourand does 3 (for a triangle, one for each vertex), interpolates the color across the face.&#xD;&#xA;&#xD;&#xA;Phong does a light calculation for every pixel/fragment (where the normal is interpolated across the face)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32677" PostHistoryTypeId="5" PostId="10846" RevisionGUID="78396b26-cd99-4099-8373-c85827cab91b" CreationDate="2021-04-25T21:39:53.277" UserId="113" Comment="added 91 characters in body" Text="The difference is in the number of lighting calculations done. Where the lighting calculation produces some color.&#xD;&#xA;&#xD;&#xA;Flat does one per face, uses the color across the face.&#xD;&#xA;&#xD;&#xA;Gourand does 3 (for a triangle, one for each vertex), interpolates the color across the face.&#xD;&#xA;&#xD;&#xA;Phong does a light calculation for every pixel/fragment (where the normal is interpolated across the face).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fyAFK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="32678" PostHistoryTypeId="52" PostId="10845" RevisionGUID="176275b2-7567-4a30-8eea-1ec5e17515d7" CreationDate="2021-04-26T05:03:50.673" />
  <row Id="32679" PostHistoryTypeId="2" PostId="10847" RevisionGUID="af6d38d3-4117-46c4-ae03-c2c3ff0a9cff" CreationDate="2021-04-26T09:50:36.643" UserId="1810" Text="Beside, note that the pow 2.2 is for *decoding* some sRGB encoded texture.&#xD;&#xA;The final encoding to sRGB at the end of shader would be pow 1./2.2 .&#xD;&#xA;&#xD;&#xA;Also, note that gamma correction is an approximation of the sRGB correction.&#xD;&#xA;But in practice even doing square and sqrt instead is quite good (and cheaper than pow ) ;-)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32680" PostHistoryTypeId="2" PostId="10848" RevisionGUID="e7e9ab69-0ecb-439d-bd74-3dfb60291c9f" CreationDate="2021-04-26T13:16:09.510" UserId="16253" Text="[![The parameters of the rational Bezier curve have been converted into a discrete representation of points using this formula.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rOJfe.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have to extrude this 2d representation into 3d. I have not found anything regarding this which doesn't use high utility libraries. Any leads or explanations will be highly appreciated. " ContentLicense="CC BY-SA 4.0" />
  <row Id="32681" PostHistoryTypeId="1" PostId="10848" RevisionGUID="e7e9ab69-0ecb-439d-bd74-3dfb60291c9f" CreationDate="2021-04-26T13:16:09.510" UserId="16253" Text="How do I extrude a 2D Bezier curve representation into a 3D solid using Python?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32682" PostHistoryTypeId="3" PostId="10848" RevisionGUID="e7e9ab69-0ecb-439d-bd74-3dfb60291c9f" CreationDate="2021-04-26T13:16:09.510" UserId="16253" Text="|3d|2d|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32683" PostHistoryTypeId="50" PostId="9591" RevisionGUID="517cdcb3-fb9a-4860-8fb5-7fb27c09d367" CreationDate="2021-04-27T00:04:40.463" UserId="-1" />
  <row Id="32684" PostHistoryTypeId="5" PostId="10848" RevisionGUID="c373ba9f-0f87-4581-9f92-a0d5138d4dcf" CreationDate="2021-04-27T17:02:49.967" UserId="16253" Comment="added 362 characters in body; edited tags" Text="[![The parameters of the rational Bezier curve have been converted into a discrete representation of points using this formula.][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rOJfe.png&#xD;&#xA;&#xD;&#xA;Where P is the control point, w is weight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I plan to extrude this 2d representation into 3d. I have a discrete 2D representation (array which has [n_points, 2, 1] for each sample) of an airfoil that has to be extruded to form a wing along the z axis which has parameters like Span and variation on chord length. In theory, this seems easy, however, in code, I can't find any basis on how to implement it. &#xD;&#xA;&#xD;&#xA;I have not found anything regarding this which doesn't use high utility libraries. Any leads or explanations will be highly appreciated. " ContentLicense="CC BY-SA 4.0" />
  <row Id="32685" PostHistoryTypeId="6" PostId="10848" RevisionGUID="c373ba9f-0f87-4581-9f92-a0d5138d4dcf" CreationDate="2021-04-27T17:02:49.967" UserId="16253" Comment="added 362 characters in body; edited tags" Text="|3d|2d|bezier-curve|parametrization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32689" PostHistoryTypeId="50" PostId="8260" RevisionGUID="89a643cb-32c4-4660-88bd-f3068c2d54e7" CreationDate="2021-04-28T07:07:05.650" UserId="-1" />
  <row Id="32690" PostHistoryTypeId="2" PostId="10850" RevisionGUID="3d3c1d8a-f5c3-49a1-899d-67d95c836d86" CreationDate="2021-04-28T08:13:45.360" UserId="13273" Text="I have a mesh, each face (triangle) of the mesh needs to read some information out of a SSBO object.&#xD;&#xA;Is there a way to read out a block (lets say 100 floats) at once? Or do I need to iterate over the 100 floats? The number of floats is not fixed. They vary for each triangle.&#xD;&#xA;During this stage the 100 floats are not changing at all... So to iterate over them would make no change in the logic. But I think it takes to mush time to read them after each other.&#xD;&#xA;&#xD;&#xA;I also have a second question:&#xD;&#xA;when reading lets say 128 floats from SSBO iteratively does it takes longer than reading 32 vec4 iteratively? in principle both is the same (128 floats)" ContentLicense="CC BY-SA 4.0" />
  <row Id="32691" PostHistoryTypeId="1" PostId="10850" RevisionGUID="3d3c1d8a-f5c3-49a1-899d-67d95c836d86" CreationDate="2021-04-28T08:13:45.360" UserId="13273" Text="SSBO get block of data instead of iterating" ContentLicense="CC BY-SA 4.0" />
  <row Id="32692" PostHistoryTypeId="3" PostId="10850" RevisionGUID="3d3c1d8a-f5c3-49a1-899d-67d95c836d86" CreationDate="2021-04-28T08:13:45.360" UserId="13273" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32693" PostHistoryTypeId="2" PostId="10851" RevisionGUID="3f6a11c5-7c3e-4372-9f41-2c2ff3d17b07" CreationDate="2021-04-28T11:44:45.300" UserId="7952" Text="yes, and no. Loading the floats into the SSBO *is* loading them for the shader so yes you still have to iterate over them. And GPU's generally are good at latency hiding so whether or not you read floats or vec4's the GPU should be able to read them in just as fast. But processing them as vec4's instead of 1 float at a time *will* be faster since the code is taking advantage of the GPU's vector processing." ContentLicense="CC BY-SA 4.0" />
  <row Id="32694" PostHistoryTypeId="2" PostId="10852" RevisionGUID="2999daa0-70a4-415e-b72f-f4435035b368" CreationDate="2021-04-28T17:01:37.633" UserId="16019" Text="&#xD;&#xA;I have the impression that there is a problem with anti-aliasing in a 2D GUI framework using opengl. To demonstrate the problem I made a program that draws gray ramps. The result is shown below. &#xD;&#xA;&#xD;&#xA;[![anti-aliasing rendering test][1]][1]&#xD;&#xA;&#xD;&#xA;The top and bottom gray ramps are identical and considered the reference ramps. It is a copy from [&quot;What every coder should know about gamma&quot;](https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/). This is what I currently assume that we should see when gray colors are correctly encoded. There seam to be a rounding error in this ramp, so an exact match is not required. The right most rectangle is not perfectly white. &#xD;&#xA;&#xD;&#xA;The second gray ramp counting from the top is produced by drawing each rectangle as a stack of black lines not thicker than a pixel on a white background. The thickness of the lines reduces linearly as we go from black to white. The gray color result thus purely from anti-aliasing. &#xD;&#xA;&#xD;&#xA;The third gray ramp is simply a sequence of rectangles filled with linearly increasing gray values. &#xD;&#xA;&#xD;&#xA;I was expecting that all gray ramps would look identical, but clearly the second gray ramp is not. It seam that a gamma correction has been applied to it while I think it should not. &#xD;&#xA;&#xD;&#xA;It generates artifacts which are strongly visible in font rendering as shown below.&#xD;&#xA;&#xD;&#xA;[![This is a test comparison][2]][2]&#xD;&#xA;&#xD;&#xA;The text *a* has been produced with the library in question, and the text *b* has been produced with another font rendering library.&#xD;&#xA;&#xD;&#xA;Another test I did to put in evidence the artifacts resulting from the anti-aliasing color processing is to draw slightly slanted lines. &#xD;&#xA;&#xD;&#xA;[![slightly slanted lines][3]][3]&#xD;&#xA;&#xD;&#xA;The lines above are produced by the library in question and the lines below by another library. The thickness of the lines below look more uniform. The lines above look wrong and distorted. &#xD;&#xA;&#xD;&#xA;The author of the 2D graphic library claims that his color processing with anti-aliasing and filled rectangle is correct. &#xD;&#xA;&#xD;&#xA;Who is right ? What argument could I use to resolve this disagreement ? &#xD;&#xA;&#xD;&#xA;The more I work on this subject, the more I get confused. For instance, by using a color picker I see that the color in the center of the ramp of the reference image is close to 0x7F. Is the color picker giving the color in linear space or the [sRGB color value](https://medium.com/game-dev-daily/the-srgb-learning-curve-773b7f68cf7a) ? The screen color picker is Gpick (Gnome Linux). &#xD;&#xA;&#xD;&#xA;I know that we should work in linear color space when performing operations on images. What is unclear is what am I looking at ? The color values I gave to rectangles where linear, not sRGB, or not gamma corrected. The color ramp I see seam linear. The values given by the color picker seam to match the linear value I gave. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/u63fw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/qi77z.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/GeVh5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32695" PostHistoryTypeId="1" PostId="10852" RevisionGUID="2999daa0-70a4-415e-b72f-f4435035b368" CreationDate="2021-04-28T17:01:37.633" UserId="16019" Text="Is anti-aliasing color processing correct in this image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32696" PostHistoryTypeId="3" PostId="10852" RevisionGUID="2999daa0-70a4-415e-b72f-f4435035b368" CreationDate="2021-04-28T17:01:37.633" UserId="16019" Text="|antialiasing|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32697" PostHistoryTypeId="2" PostId="10853" RevisionGUID="bc3a7018-67a4-4f6a-aee4-511f9b604f77" CreationDate="2021-04-29T00:35:53.440" UserId="6046" Text="I'm working on a scientific visualization project and need to create a transfer function widget. The volume data is either in range `0-255` or it can be 16 bit i.e. `0-65535`. Now the main problem is in order to color certain sections, the user needs to be able to define certain control points with varying colors and the colors need to be smoothly transitioned between those control points. Then during rendering, we find the color for every isovalue through a texture lookup in a ramp texture and color the volume data.&#xD;&#xA;&#xD;&#xA;I've decided to do cubic spline interpolation between these control points. My question is, how do I actually render and store this gradient in an Nx1 ramp texture. Firstly, regarding the rendering part. I'm using OpenGL but also Dear-ImGui for GUI. So I don't have low level access to rendering like vertex/fragment shader for rendering this gradient. Just low level functions like rendering lines/rectangles etc.&#xD;&#xA;&#xD;&#xA;For 8 bit volumes, I could render 256 lines of thickness `gradient_width_in_pixels/256`. I think this would give me the look of a rectangular gradient? However suppose I have a 16 bit volume. The max value now is 65k. I could go on and convert it to `0-255` but let's say I don't because there would be a loss of precision as in the `0-255` scale 1 value represents approximately 256 values of `0-65535` scale. What if the user wanted to color within that range? ***What's the proper way to handle this scenario now?***&#xD;&#xA;&#xD;&#xA;Secondly, regarding storing the gradient information. For 8bit datasets, again it'd seem pretty simple to just create an `256x1` texture. However the problem again rises for 16 bit datasets. 65k pixels don't sound good." ContentLicense="CC BY-SA 4.0" />
  <row Id="32698" PostHistoryTypeId="1" PostId="10853" RevisionGUID="bc3a7018-67a4-4f6a-aee4-511f9b604f77" CreationDate="2021-04-29T00:35:53.440" UserId="6046" Text="How to render and store a color gradient in a ramp texture for 16bit dataset?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32699" PostHistoryTypeId="3" PostId="10853" RevisionGUID="bc3a7018-67a4-4f6a-aee4-511f9b604f77" CreationDate="2021-04-29T00:35:53.440" UserId="6046" Text="|rendering|texture|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32700" PostHistoryTypeId="2" PostId="10854" RevisionGUID="8735d752-41c0-4686-ad8f-a7e7fcb16730" CreationDate="2021-04-29T12:49:26.853" UserId="7952" Text="It may be easier to compute the gradient on the CPU, even with 16bit precision the CPU can grind out a texture quickly. Then just upload that to the GPU as an image. Also, it doesn't sound like users will be able to pick a new color set every frame so its sounds a lot more natural to have a work flow of: Pick colors -&gt; Generate Image -&gt; upload to the GPU -&gt; use new palette to render.&#xD;&#xA;&#xD;&#xA;Are the picked colors RGB choices? If yes then it does make sense to spread the color palette out as wide as possible (maybe even more then 16bits) 65536 pixels is just a drop in the bucket. And a nice wide color range could lead to less banding in the final image.&#xD;&#xA;&#xD;&#xA;At some  level the code will have to narrow the range down to whatever the current precision is. If that is the table, and the table has 65536 positions, then the table might contain a lot of repeating colors, but it is easy to compute the table with a new range." ContentLicense="CC BY-SA 4.0" />
  <row Id="32701" PostHistoryTypeId="50" PostId="10784" RevisionGUID="2dcca8f5-c7b5-4077-a8fd-c336e392c93f" CreationDate="2021-04-29T16:01:41.143" UserId="-1" />
  <row Id="32702" PostHistoryTypeId="50" PostId="8757" RevisionGUID="04a5642d-24ef-452c-9f5c-c4caf710f2c2" CreationDate="2021-04-30T11:07:50.697" UserId="-1" />
  <row Id="32703" PostHistoryTypeId="2" PostId="10855" RevisionGUID="3c67f461-32d0-4201-a4c9-494d82474fb8" CreationDate="2021-04-30T12:52:42.933" UserId="16273" Text="I have a QOpenGLWidget where I use camera transformation matrix(4,4), FOV and vectors Position(4), Up(4), Forward(4). I also have an ArcBall which I can use. I managed to implement zoom and pan by modifying the Position vector. Now I want to implement rotation with arcball. &#xD;&#xA;&#xD;&#xA;On mouseMove I compute the rotation matrix with arcball. Then I need to use this matrix for rotating the camera. Now how do I do that?&#xD;&#xA;&#xD;&#xA;I tried multiplying or summing the camera matrix and arcball matrix but it is not working for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="32704" PostHistoryTypeId="1" PostId="10855" RevisionGUID="3c67f461-32d0-4201-a4c9-494d82474fb8" CreationDate="2021-04-30T12:52:42.933" UserId="16273" Text="How to use trackball for rotating an camera matrix in eye frame" ContentLicense="CC BY-SA 4.0" />
  <row Id="32705" PostHistoryTypeId="3" PostId="10855" RevisionGUID="3c67f461-32d0-4201-a4c9-494d82474fb8" CreationDate="2021-04-30T12:52:42.933" UserId="16273" Text="|transformations|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32706" PostHistoryTypeId="2" PostId="10856" RevisionGUID="909e8d30-7fd6-4e23-bc55-740751b44019" CreationDate="2021-04-30T15:01:18.250" UserId="16274" Text="This isn't coming from graphics but more from some simple synthetic data generation problem but I have a hunch there are tricks from landscape generation to use here. &#xD;&#xA;&#xD;&#xA;Consider the line (1d) for simplicity. I want to generate random points on the line in some interval of interest. But then I want to also be able to generate those points in another interval and when I &quot;grow&quot; the interval, the generation should be consistent. For example, if I generate exponential intervals I have a kind of Poisson random measure. &#xD;&#xA;&#xD;&#xA;But how can I do this efficiently without just hard-coded some &quot;origina&quot; and simulating from there? I can pick a coarse grid I suppose and do some messing around but keeping the distribution consistent is tricky. &#xD;&#xA;&#xD;&#xA;I am interested in tricks that just work and also anything that actually guarantees the correct simulating distribution (whatever we were using to generate the sequences).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32707" PostHistoryTypeId="1" PostId="10856" RevisionGUID="909e8d30-7fd6-4e23-bc55-740751b44019" CreationDate="2021-04-30T15:01:18.250" UserId="16274" Text="Efficiently generating consistent procedural sequences from random see and a start point?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32708" PostHistoryTypeId="3" PostId="10856" RevisionGUID="909e8d30-7fd6-4e23-bc55-740751b44019" CreationDate="2021-04-30T15:01:18.250" UserId="16274" Text="|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32709" PostHistoryTypeId="2" PostId="10857" RevisionGUID="9b388f0e-5328-4172-a8ef-3f503125dda7" CreationDate="2021-04-30T17:11:16.833" UserId="16019" Text="The anti-aliasing rendering is correct.&#xD;&#xA;&#xD;&#xA;The reference gray ramp (top and bottom) is linear in sRGB color, not in brightness. &#xD;&#xA;&#xD;&#xA;The second gray ramp made with anti-aliasing is linear in brightness. The rectangle color (black in color sRGB space) is mapped to linear space (remains black), then anti-aliasing is computed, and the resulting image is converted back to sRGB. It is thus not linear in sRGB value anymore. &#xD;&#xA;&#xD;&#xA;The RGB values given by a screen color picker are in  sRGB color space, and the color values of a screen capture are in the sRGB color space. &#xD;&#xA;&#xD;&#xA;SVG and nearly all browser graphic library (skia and cairo) are doing it wrong. They compute anti-aliasing over sRGB instead of linear color. They thus don't convert back from linear to sRGB. The same mistreatment  is also visible on Windows, MacOs and iOS. &#xD;&#xA;&#xD;&#xA;The filled rectangle gray ramp doesn't have this problem because the conversion from sRGB to linear and its inverse cancel out. " ContentLicense="CC BY-SA 4.0" />
  <row Id="32710" PostHistoryTypeId="2" PostId="10858" RevisionGUID="fad384c5-36df-4677-907d-bd90583c6f2c" CreationDate="2021-04-30T18:21:12.343" UserId="482" Text="Transform the Up and Left vectors through the rotation and the recreate the camera transform using the new vectors." ContentLicense="CC BY-SA 4.0" />
  <row Id="32715" PostHistoryTypeId="5" PostId="10853" RevisionGUID="decb80db-d625-4cf9-b4f6-54f86ed9c6b3" CreationDate="2021-05-01T14:48:13.493" UserId="6046" Comment="added 463 characters in body" Text="I'm working on a scientific visualization project and need to create a transfer function widget. The volume data is either in range `0-255` or it can be 16 bit i.e. `0-65535`. Now the main problem is in order to color certain sections, the user needs to be able to define certain control points with varying colors and the colors need to be smoothly transitioned between those control points. Then during rendering, we find the color for every isovalue through a texture lookup in a ramp texture and color the volume data.&#xD;&#xA;&#xD;&#xA;I've decided to do cubic spline interpolation between these control points. My question is, how do I actually render and store this gradient in an Nx1 ramp texture. Firstly, regarding the rendering part. I'm using OpenGL but also Dear-ImGui for GUI. So I don't have low level access to rendering like vertex/fragment shader for rendering this gradient. Just low level functions like rendering lines/rectangles etc.&#xD;&#xA;&#xD;&#xA;For 8 bit volumes, I could render 256 lines of thickness `gradient_width_in_pixels/256`. I think this would give me the look of a rectangular gradient? However suppose I have a 16 bit volume. The max value now is 65k. I could go on and convert it to `0-255` but let's say I don't because there would be a loss of precision as in the `0-255` scale 1 value represents approximately 256 values of `0-65535` scale. What if the user wanted to color within that range? ***What's the proper way to handle this scenario now?***&#xD;&#xA;&#xD;&#xA;Secondly, regarding storing the gradient information. For 8bit datasets, again it'd seem pretty simple to just create an `256x1` texture. However the problem again rises for 16 bit datasets. 65k pixels don't sound good or are they okay? I know `65k x 1` texture is just a `256x256` texture but dunno if increasing only 1 dimension will cause problems.&#xD;&#xA;&#xD;&#xA;EDIT:- I thought I should clarify regarding rendering the gradient part and ask the question differently. What I wanna know is given a color control point at pixel coord (x1,y) and another point at (x2, y), how many lines of any thickness should I render to get a color gradient with smooth transition between those two colors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32716" PostHistoryTypeId="5" PostId="10311" RevisionGUID="4ffa8542-1647-4a5d-8c5f-abc1f45cc35c" CreationDate="2021-05-01T18:31:11.870" UserId="10783" Comment="syntax correction" Text="The standard solution is to reduce the amount of per-vertex data by only specifying the 4 indices that have the highest weights (and rescaling the weights to add up to 1.0). That way, you can pass 4 weights as a `vec4` and 4 indices as a `uvec4`. Also, you should pass the weights as normalized shorts (or bytes if you can accept the quality loss) and indices as bytes if at all possible, to further reduce the per-vertex data storage.&#xD;&#xA;&#xD;&#xA;Most real-time rendering systems are happy with these limitations.&#xD;&#xA;&#xD;&#xA;If that's not acceptable for your needs, then you're going to have to use multiple attributes to send the data. Each attribute can only have 4 components. And while attributes can be arrayed, arraying them like your C struct would waste a bunch of attribute locations, since each array element is considered a *separate* location.&#xD;&#xA;&#xD;&#xA;So you need to send values in multiples of 4. Instead of sending 10 weights/indices, send 12, grouped into 4-element groupings. So the GLSL would look like this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;layout(location = X) uvec4 indices[3];    //Stores 12 indices, consumes 3 locations.&#xD;&#xA;layout(location = X + 3) vec4 weights[3]; //Stores 12 weights, consumes 3 locations.&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The C data structure ought to also store 12 elements for each array.&#xD;&#xA;&#xD;&#xA;To specify them in the vertex format, you would do this (where `X` is the location given above):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glVertexAttribIPointer(3, 4, GL_INT, sizeof(Vertex), (void*)(offsetof(Vertex, groups) + 0));&#xD;&#xA;glVertexAttribIPointer(4, 4, GL_INT, sizeof(Vertex), (void*)(offsetof(Vertex, groups) + 16));&#xD;&#xA;glVertexAttribIPointer(5, 4, GL_INT, sizeof(Vertex), (void*)(offsetof(Vertex, groups) + 32));&#xD;&#xA;glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(offsetof(Vertex, weights) + 0));&#xD;&#xA;glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(offsetof(Vertex, weights) + 16));&#xD;&#xA;glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(offsetof(Vertex, weights) + 32));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32717" PostHistoryTypeId="24" PostId="10311" RevisionGUID="4ffa8542-1647-4a5d-8c5f-abc1f45cc35c" CreationDate="2021-05-01T18:31:11.870" Comment="Proposed by 10783 approved by 2654 edit id of 561" ContentLicense="CC BY-SA 4.0" />
  <row Id="32721" PostHistoryTypeId="12" PostId="10858" RevisionGUID="b67f5798-754c-4d4b-8a23-a78fe4b990f3" CreationDate="2021-05-01T23:50:41.393" UserId="482" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}]}" />
  <row Id="32723" PostHistoryTypeId="50" PostId="9178" RevisionGUID="841f0708-5837-4705-a7ab-f55fd3208a37" CreationDate="2021-05-02T13:07:35.677" UserId="-1" />
  <row Id="32733" PostHistoryTypeId="6" PostId="10855" RevisionGUID="1ae968ae-6eec-433d-83c1-06d1e60f756b" CreationDate="2021-05-03T08:16:35.350" UserId="16273" Comment="edited tags" Text="|opengl|transformations|c++|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32736" PostHistoryTypeId="2" PostId="10864" RevisionGUID="9f4ea700-41d9-42ad-872f-de7839f66ac8" CreationDate="2021-05-03T15:51:06.563" UserId="16290" Text="{0,8,7,6} and {4,3,2} are called &quot;left bounds&quot; because if you look at both these bounds, the polygon interior is to the right of them:&#xD;&#xA;&#xD;&#xA;[![image1][1]][1]&#xD;&#xA;&#xD;&#xA;Likewise, {0,1,2} and {4,5,6} are &quot;right bounds&quot; because the polygon interior is at their left:&#xD;&#xA;&#xD;&#xA;[![image2][2]][2]&#xD;&#xA;&#xD;&#xA;For reference, this example comes from: http://what-when-how.com/computer-graphics-and-geometric-modeling/clipping-basic-computer-graphics-part-5/&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GhMNp.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/idwor.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32737" PostHistoryTypeId="2" PostId="10865" RevisionGUID="c9140cb8-be98-486c-9210-4639a5a4db8e" CreationDate="2021-05-03T18:04:30.033" UserId="16300" Text="Based on the article, it seems like, when it adds &quot;directional lighting information&quot;, the program tries to infer a location of a light source and base the normals on the colors with the added information of the directional lighting from the pixel to the inferred light source. I feel like I'm making no sense right now, so here's an example using their pictures:&#xD;&#xA;&#xD;&#xA;[![Sample image][1]][1]&#xD;&#xA;&#xD;&#xA;[![Normal map *with* shape recognition][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see, on the far right of the normal map, it's very pink, just like how the sample image is completely white. I would assume this is the case because the inferred light is directly on top of it, with all the normals (in sort of a curved fashion, resulting in the gradient) pointing right at it. In contrast...&#xD;&#xA;&#xD;&#xA;[![Normal map *without* shape recognition][3]][3]&#xD;&#xA;&#xD;&#xA;This normal map isn't trying to figure out a light source, and instead just kind of uses the sample texture as a heightmap of sorts.&#xD;&#xA;&#xD;&#xA;Late reply, but hope this helps! :)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YFApT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/kLyJQ.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/o56xq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32738" PostHistoryTypeId="2" PostId="10866" RevisionGUID="e15dfb55-04a3-4ba4-b332-114ab38b6218" CreationDate="2021-05-03T22:43:37.767" UserId="16302" Text="I am currently working on tetrahedral meshes and I want to downsample the mesh using techniques like Qslim but there is not much about tetrahedral meshes in the literature. I try to use it as a pooling layer in a neural network so computation cost is also important. I wonder if there is a open-source code available for this task." ContentLicense="CC BY-SA 4.0" />
  <row Id="32739" PostHistoryTypeId="1" PostId="10866" RevisionGUID="e15dfb55-04a3-4ba4-b332-114ab38b6218" CreationDate="2021-05-03T22:43:37.767" UserId="16302" Text="Is there any open source code available for simplification of tetrahedral mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32740" PostHistoryTypeId="3" PostId="10866" RevisionGUID="e15dfb55-04a3-4ba4-b332-114ab38b6218" CreationDate="2021-05-03T22:43:37.767" UserId="16302" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32747" PostHistoryTypeId="5" PostId="10853" RevisionGUID="2fa5bbc7-1f51-4f59-8e16-87849d184953" CreationDate="2021-05-05T05:29:22.697" UserId="6046" Comment="deleted 1 character in body" Text="I'm working on a scientific visualization project and need to create a transfer function widget. The volume data is either in range `0-255` or it can be 16 bit i.e. `0-65535`. Now the main problem is in order to color certain sections, the user needs to be able to define certain control points with varying colors and the colors need to be smoothly transitioned between those control points. Then during rendering, we find the color for every isovalue through a texture lookup in a ramp texture and color the volume data.&#xD;&#xA;&#xD;&#xA;I've decided to do cubic spline interpolation between these control points. My question is, how do I actually render and store this gradient in an Nx1 ramp texture. Firstly, regarding the rendering part. I'm using OpenGL but also Dear-ImGui for GUI. So I don't have low level access to rendering like vertex/fragment shader for rendering this gradient. Just low level functions like rendering lines/rectangles etc.&#xD;&#xA;&#xD;&#xA;For 8 bit volumes, I could render 256 lines of thickness `gradient_width_in_pixels/256`. I think this would give me the look of a rectangular gradient? However suppose I have a 16 bit volume. The max value now is 65k. I could go on and convert it to `0-255` but let's say I don't because there would be a loss of precision as in the `0-255` scale 1 value represents approximately 256 values of `0-65535` scale. What if the user wanted to color within that range? ***What's the proper way to handle this scenario now?***&#xD;&#xA;&#xD;&#xA;Secondly, regarding storing the gradient information. For 8bit datasets, again it'd seem pretty simple to just create an `256x1` texture. However the problem again rises for 16 bit datasets. 65k pixels don't sound good or are they okay? I know `65k x 1` texture is just a `256x256` texture but dunno if increasing only 1 dimension will cause problems.&#xD;&#xA;&#xD;&#xA;EDIT: I thought I should clarify regarding rendering the gradient part and ask the question differently. What I wanna know is given a color control point at pixel coord (x1,y) and another point at (x2, y), how many lines of any thickness should I render to get a color gradient with smooth transition between those two colors?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32748" PostHistoryTypeId="2" PostId="10868" RevisionGUID="b49e41e5-2813-4efe-b447-3eee2da65306" CreationDate="2021-05-05T17:24:32.797" UserId="16313" Text="I am using Fournier's midpoint algorithm (recursive subdivision) to construct a landscape of 1025 x 1025 gridpoints, then I am using an advanced version of box counting to find fractal dimension, D. No matter what Hurst exponent I use in Fournier's algorithm, I get D = 2.0. Has anyone checked Fournier's algorithm for fractal dimension? Does it actually produce a fractal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32749" PostHistoryTypeId="1" PostId="10868" RevisionGUID="b49e41e5-2813-4efe-b447-3eee2da65306" CreationDate="2021-05-05T17:24:32.797" UserId="16313" Text="Fractal dimension of landscape generated with Fournier's midpoint algorithm (recursive subdivision) is 2.0 no matter what. Why?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32750" PostHistoryTypeId="3" PostId="10868" RevisionGUID="b49e41e5-2813-4efe-b447-3eee2da65306" CreationDate="2021-05-05T17:24:32.797" UserId="16313" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32754" PostHistoryTypeId="2" PostId="10870" RevisionGUID="80ee364f-711f-4ab0-a755-58c6ea1d8724" CreationDate="2021-05-06T01:09:35.560" UserId="159" Text="There are plenty of algorithms for generating meshes from point clouds. I am going to suggest looking at the libraries [CGAL][1] and [PCL][2], if only because their documentation has excellent references which should give you ideas on where to look in the literature if you need to roll your own.&#xD;&#xA;&#xD;&#xA;[Jonathan Shewchuk][3] also has some more 2.5D-ish algorithms that may suit your needs.&#xD;&#xA;&#xD;&#xA;  [1]: https://doc.cgal.org/latest/Manual/tuto_reconstruction.html&#xD;&#xA;  [2]: https://pointclouds.org/documentation/tutorials/greedy_projection.html&#xD;&#xA;  [3]: http://www.cs.cmu.edu/~quake/triangle.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="32755" PostHistoryTypeId="5" PostId="10870" RevisionGUID="106725d5-cb5c-4b1f-bfeb-e606f46bc00e" CreationDate="2021-05-06T01:14:43.213" UserId="159" Comment="deleted 4 characters in body" Text="There are plenty of algorithms for generating meshes from point clouds. I am going to suggest looking at the libraries [CGAL][1] and [PCL][2], if only because their documentation has excellent references which should give you ideas on where to look in the literature if you need to roll your own.&#xD;&#xA;&#xD;&#xA;[Jonathan Shewchuk][3] also has some more 2.5D-ish algorithms that may suit your needs.&#xD;&#xA;&#xD;&#xA;  [1]: https://doc.cgal.org/latest/Manual/tuto_reconstruction.html&#xD;&#xA;  [2]: https://pointclouds.org/documentation/tutorials/greedy_projection.html&#xD;&#xA;  [3]: https://people.eecs.berkeley.edu/~jrs/" ContentLicense="CC BY-SA 4.0" />
  <row Id="32758" PostHistoryTypeId="4" PostId="10856" RevisionGUID="cb595d0b-89e1-445f-9731-f805d9c0221b" CreationDate="2021-05-06T12:53:08.790" UserId="7952" Comment="Fixed spelling of word &quot;seed&quot; in description" Text="Efficiently generating consistent procedural sequences from random seed and a start point?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32759" PostHistoryTypeId="24" PostId="10856" RevisionGUID="cb595d0b-89e1-445f-9731-f805d9c0221b" CreationDate="2021-05-06T12:53:08.790" Comment="Proposed by 7952 approved by 16274 edit id of 562" ContentLicense="CC BY-SA 4.0" />
  <row Id="32760" PostHistoryTypeId="5" PostId="10858" RevisionGUID="78401b50-23e8-4987-a74a-f3293c8d9d23" CreationDate="2021-05-06T16:43:41.407" UserId="482" Comment="corrected (?)" Text="I'm assuming the rotation matrix generated from the arcball is 2D, so I think there are a few clear top level steps. But I'm not sure about the details of some of them.&#xD;&#xA;&#xD;&#xA;First you'll need to extend the 2D rotation to 3D which should be easy.&#xD;&#xA;&#xD;&#xA;Next you'll need to rotate the rotation matrix itself so its axis aligns with your Forward vector. I'm not certain how to do this step.&#xD;&#xA;&#xD;&#xA;Then, use the resulting matrix to transform the Up vector and reconstruct the camera matrix using the new vector and the other values and vectors." ContentLicense="CC BY-SA 4.0" />
  <row Id="32761" PostHistoryTypeId="13" PostId="10858" RevisionGUID="45791cab-5dd8-4be7-a760-217f8e776041" CreationDate="2021-05-06T16:43:46.140" UserId="482" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}]}" />
  <row Id="32762" PostHistoryTypeId="2" PostId="10872" RevisionGUID="6685051d-4404-4e19-9310-673b5b683171" CreationDate="2021-05-06T20:00:06.673" UserId="16319" Text="Recently I've became an intern in `company-name` and my internship task is(for now) create rasterization using rays. &#xD;&#xA;&#xD;&#xA;I'm mostly interested in pure math, so basic ideas on how to do it I've caught up really fast: I need to find an intersection of a ray that starts in center of a pixel with a plane of a triangle, compute barycentric coordinates in order to understand whether the intersection point is in the triangle or not.  &#xD;&#xA;&#xD;&#xA;But when it comes to code realization, I'm getting stuck. &#xD;&#xA;&#xD;&#xA;First of all, and probably my main &quot;problem&quot; is that I can't really understand what &quot;camera&quot; is really about. I know it might have a lot of different properties(so called &quot;intrinsic&quot; and &quot;extrinsic&quot;), but I just need a basic one. For now I understand this as an &quot;eye&quot; located somewhere in the space. &#xD;&#xA;&#xD;&#xA;And here is the second &quot;problem&quot;: I said, &quot;eye&quot; is located somewhere in the space, but *where is it really located*? I mean, I'm not quite sure that I can put it really at any point.  Also, I need to put the &quot;screen&quot; somewhere in the space as well, preferably between the &quot;eye&quot; and object/scene. For now, I do the following: I identify &quot;eye&quot; and &quot;screen&quot; as one object(going down to biology, &quot;screen&quot; is something like the cornea of a human eye). I scale my object/scene in $[-1,1]^3$, and put my &quot;eye&quot;/&quot;screen&quot; on the 2-sphere of radius $2\sqrt3$, because $[-1,1]^3$ is inside of this sphere. Therefore I can move my &quot;camera&quot; on the sphere, getting different camera positions. But I'm not quite sure that this is how it should be done. &#xD;&#xA;&#xD;&#xA;Also, for rendering an object, I drop $z$-coordinate and just work with $2D$ vectors, so basically I make a projection of my object onto $XY$ plane. I'm not sure, that if I put my camera on position $(0,0,2\sqrt3)$ with direction $(0,0,-1)$, I will get the same picture: I really should just get the view &quot;above the object&quot;, but I get the normal one. &#xD;&#xA;&#xD;&#xA;So this are my problems, basically about the essence of camera(and so of screen) and its positions in the space. I hope someone will help me to tackle my confusion. Thanks. " ContentLicense="CC BY-SA 4.0" />
  <row Id="32763" PostHistoryTypeId="1" PostId="10872" RevisionGUID="6685051d-4404-4e19-9310-673b5b683171" CreationDate="2021-05-06T20:00:06.673" UserId="16319" Text="Silly questions about ray casting and computer graphics in general" ContentLicense="CC BY-SA 4.0" />
  <row Id="32764" PostHistoryTypeId="3" PostId="10872" RevisionGUID="6685051d-4404-4e19-9310-673b5b683171" CreationDate="2021-05-06T20:00:06.673" UserId="16319" Text="|raytracing|physically-based|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32765" PostHistoryTypeId="4" PostId="10872" RevisionGUID="4b407bcc-0e3b-4ded-b1c3-0f63d18ea3e4" CreationDate="2021-05-06T21:44:29.843" UserId="16319" Comment="edited title" Text="Silly questions about camera and screen position in space, ray casting and rasterization" ContentLicense="CC BY-SA 4.0" />
  <row Id="32766" PostHistoryTypeId="2" PostId="10873" RevisionGUID="cb65b158-367e-42dd-8ff4-aa5e7d908895" CreationDate="2021-05-07T08:09:12.003" UserId="16335" Text="I like to know the technical aspects of it. Game developers use APIs like OpenGL or DirectX. The functions provided by these APIs, i would asume, work flawlessly with all graphic cards because they are fixed and do not change - except if there is a new version of it - and are of some sort mathematically correct. So how does it come that Nvidia and AMD have to update their drivers to fix visual bugs or performances. What are the problems? Furthermore i would like to know if Nvidia and AMD are providing these improvements on their on behalf or if the game developers cooperate with them by making some sort of paid contracts." ContentLicense="CC BY-SA 4.0" />
  <row Id="32767" PostHistoryTypeId="1" PostId="10873" RevisionGUID="cb65b158-367e-42dd-8ff4-aa5e7d908895" CreationDate="2021-05-07T08:09:12.003" UserId="16335" Text="Why do Nvidia and AMD have to update their drivers for game releases?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32768" PostHistoryTypeId="3" PostId="10873" RevisionGUID="cb65b158-367e-42dd-8ff4-aa5e7d908895" CreationDate="2021-05-07T08:09:12.003" UserId="16335" Text="|opengl|directx|driver|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32769" PostHistoryTypeId="5" PostId="10873" RevisionGUID="952a3bfa-debc-4636-bde9-d999ad039560" CreationDate="2021-05-07T10:14:55.330" UserId="13095" Comment="Fix some typos" Text="I like to know the technical aspects of it. Game developers use APIs like OpenGL or DirectX. The functions provided by these APIs, I would assume, work flawlessly with all graphic cards because they are fixed and do not change - except if there is a new version of it - and are of some sort mathematically correct. So how does it come that Nvidia and AMD have to update their drivers to fix visual bugs or performances? What are the problems? Furthermore, I would like to know if Nvidia and AMD are providing these improvements on their own behalf or if the game developers cooperate with them by making some sort of paid contracts." ContentLicense="CC BY-SA 4.0" />
  <row Id="32770" PostHistoryTypeId="2" PostId="10874" RevisionGUID="1ef80d4d-2a03-46da-ab8c-754faca07770" CreationDate="2021-05-07T10:59:14.450" UserId="13095" Text="Nvidia uses a technique called [DLSS (deep learning super sampling)](https://www.nvidia.com/en-gb/geforce/technologies/dlss/) with their latest graphic cards. It basically uses AI to upscale your image. So for example, you render in a resolution of 1080p and get an upscaled image in 4k that is barely distinguishable from a native 4k render. They train the AI with a lot of image samples from the corresponding game and distribute the training data with the drivers. From the source I linked:&#xD;&#xA;&#xD;&#xA;&gt; DLSS uses the power of NVIDIA’s supercomputers to train and improve its AI model. The updated models are delivered to your GeForce RTX PC through Game Ready Drivers.&#xD;&#xA;&#xD;&#xA;I can't tell you if this is the sole reason, but it is certainly one of them. Not sure if AMD does something similar (I guess they do). &#xD;&#xA;&#xD;&#xA;I can't answer your second question, but I guess it is some sort of cooperation between Nvidia/AMD and the big players in the game industry since both benefit from it to sell their products. " ContentLicense="CC BY-SA 4.0" />
  <row Id="32771" PostHistoryTypeId="2" PostId="10875" RevisionGUID="cef76111-6c40-457d-9e85-f7f924d3c7f7" CreationDate="2021-05-07T13:38:21.237" UserId="7952" Text="Games, Triple A games in particular, tend to push graphics cards to their limits, computation capabilities, bandwidth, and drivers all get stressed heavily. This tends to cause even the smallest bug, or inefficiency in the driver to become a glaring problem resulting in &quot;glitches&quot;, slow frame rates, game crashes and rendering quality issues.&#xD;&#xA;&#xD;&#xA;These &quot;bugs&quot; and inefficiencies can be very specific and often only occur when certain sequences of operations happen, which are often specific to a particular game. The range of issues that they run into tend to run the gamut from simple brain dead bugs, to show stopping monsters that everyone spends weeks agonizing over, to minor tweaks that improve visuals.&#xD;&#xA;&#xD;&#xA;During game development vendors will provide driver updates that address these issues directly to game developers, or put the updates in a &quot;beta&quot; driver and release it publicly so anyone, including the developers, can install it. This allows games to be tested, developed and updated before being released.&#xD;&#xA;&#xD;&#xA;How closely a vendor works with a game developer is going to depend heavily on the size of the project and the issues they are encountering. Sometimes this will mean going so far as having engineers from the GPU vendor actually join the game development team, and spend time on site working through the various problems that come up. Other times it can be just an updated driver dropped on the public beta website.&#xD;&#xA;&#xD;&#xA;When the game is nearing release game developers and vendors will work together to release the updated driver with the game, this sometimes even includes shipping the updated driver with the actual game. For smaller projects vendors might no be as accommodating. It is in the best interest of both game developers and GPU vendors to work together, especially on large projects.&#xD;&#xA;&#xD;&#xA;It would be naïve to assume that the two don't come to some sort of monetary agreement when developing a game, especially when a game gets advertised with statements like &quot;Made for XYZ gpu vendor.&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32772" PostHistoryTypeId="5" PostId="10872" RevisionGUID="6f5f5e05-6ae9-47b2-bb7d-f54537a8230b" CreationDate="2021-05-07T18:30:02.427" UserId="16319" Comment="deleted 315 characters in body; edited title" Text="Recently I've became an intern in `company-name` and my internship task is(for now) create rasterization using rays. &#xD;&#xA;&#xD;&#xA;I'm mostly interested in pure math, so basic ideas on how to do it I've caught up really fast: I need to find an intersection of a ray that starts in center of a pixel with a plane of a triangle, compute barycentric coordinates in order to understand whether the intersection point is in the triangle or not.  &#xD;&#xA;&#xD;&#xA;But when it comes to code realization, I'm getting stuck. &#xD;&#xA;&#xD;&#xA;First of all, and probably my main &quot;problem&quot; is that I can't really understand what &quot;camera&quot; is really about. I know it might have a lot of different properties(so called &quot;intrinsic&quot; and &quot;extrinsic&quot;), but I just need a basic one. For now I understand this as an &quot;eye&quot; located somewhere in the space. &#xD;&#xA;&#xD;&#xA;And here is the second &quot;problem&quot;: I said, the camera is located somewhere in the space, but *where is it really located*? I really can't get how to put in in the space.  Also, I need to put the &quot;screen&quot; somewhere in the space as well, preferably between the &quot;eye&quot; and object/scene(I'm considering pinhole camera as a primer model). &#xD;&#xA;&#xD;&#xA;For now, I do the following: I identify &quot;eye&quot; and &quot;screen&quot; as one object(going down to biology, &quot;screen&quot; is something like the cornea of a human eye). I scale my object/scene in $[-1,1]^3$, and put my &quot;eye&quot;/&quot;screen&quot; on the 2-sphere of radius $2\sqrt3$, because $[-1,1]^3$ is inside of this sphere. Therefore I can move my &quot;camera&quot; on the sphere, getting different camera positions. But I'm not quite sure that this is how it should be done. &#xD;&#xA;&#xD;&#xA;So this are my problems, basically about the essence of camera(and so of screen) and its positions in the space. I hope someone will help me to tackle my confusion. Thanks. " ContentLicense="CC BY-SA 4.0" />
  <row Id="32773" PostHistoryTypeId="4" PostId="10872" RevisionGUID="6f5f5e05-6ae9-47b2-bb7d-f54537a8230b" CreationDate="2021-05-07T18:30:02.427" UserId="16319" Comment="deleted 315 characters in body; edited title" Text="Ray casting and rasterization 101" ContentLicense="CC BY-SA 4.0" />
  <row Id="32776" PostHistoryTypeId="2" PostId="10876" RevisionGUID="6f16f186-d1bd-438f-9c68-cc9f070b7007" CreationDate="2021-05-08T01:53:17.493" UserId="16341" Text="Just like the question, I am wondering are there any limitations and benefits for these two techniques? " ContentLicense="CC BY-SA 4.0" />
  <row Id="32777" PostHistoryTypeId="1" PostId="10876" RevisionGUID="6f16f186-d1bd-438f-9c68-cc9f070b7007" CreationDate="2021-05-08T01:53:17.493" UserId="16341" Text="What are the limitations and benefits of anti-aliasing and subpixel rendering respectively?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32778" PostHistoryTypeId="3" PostId="10876" RevisionGUID="6f16f186-d1bd-438f-9c68-cc9f070b7007" CreationDate="2021-05-08T01:53:17.493" UserId="16341" Text="|antialiasing|subpixel-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32780" PostHistoryTypeId="50" PostId="10438" RevisionGUID="4640b376-4a4c-4163-ab73-e21873e647db" CreationDate="2021-05-08T22:05:00.433" UserId="-1" />
  <row Id="32784" PostHistoryTypeId="2" PostId="10879" RevisionGUID="f3c516e7-79e6-45c6-8200-ca62dbacfafd" CreationDate="2021-05-09T10:16:31.543" UserId="16350" Text="I'm interested in direct3d game programming and I'm just a beginner.&#xD;&#xA;I'm familiar with the Win32 API and i was wondering...&#xD;&#xA;how to put a certain pixel somewhere in the window&#xD;&#xA;is there like a function or anythting?&#xD;&#xA;thank you..." ContentLicense="CC BY-SA 4.0" />
  <row Id="32785" PostHistoryTypeId="1" PostId="10879" RevisionGUID="f3c516e7-79e6-45c6-8200-ca62dbacfafd" CreationDate="2021-05-09T10:16:31.543" UserId="16350" Text="how to put a pixel somewhere in a window(directx)" ContentLicense="CC BY-SA 4.0" />
  <row Id="32786" PostHistoryTypeId="3" PostId="10879" RevisionGUID="f3c516e7-79e6-45c6-8200-ca62dbacfafd" CreationDate="2021-05-09T10:16:31.543" UserId="16350" Text="|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32788" PostHistoryTypeId="2" PostId="10880" RevisionGUID="80f264d3-60dd-4d34-a5ca-036a6d87b9cf" CreationDate="2021-05-09T17:46:24.443" UserId="16352" Text="this is my first post on the Computer Graphics Stackexchange forum. Apologies in advance if I am doing something wrong.&#xD;&#xA;&#xD;&#xA;I have the problem that I have a scene with overlapping geometries. To be more precise, my scene is a Cornell Box, where the ceiling and the area light are quads that are lying in the same plane, e.g. are having the same height value:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;This image is rendered by our &quot;home renderer&quot; and I am working on the integration of Intel's Embree framework into it, to accelerate the ray casting process.&#xD;&#xA;&#xD;&#xA;When I render the scene with the help of Embree, it looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;(There is nothing wrong with Embree itself, but probably with what I am doing with it)&#xD;&#xA;What is immediately visible is that the ceiling looks more &quot;grainy&quot; or noisy and that pixels in the area light have the colour of the ceiling. &#xD;&#xA;&#xD;&#xA;I strongly believe that this has something to do with the fact that the ceiling and the&#xD;&#xA;area light are lying in the same plane. &#xD;&#xA;So my question is: when such overlapping geometries are intersected with a ray, how does one choose which of the two geometries should be prioritized? &#xD;&#xA;&#xD;&#xA;I did a short experiment in Blender with two cubes with different materials:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Then I moved the green cube &quot;into&quot; the red one, meaning I assigned the same position, such that the two cubes are overlapping.&#xD;&#xA;&#xD;&#xA;This is what the Cycles renderer gave me:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Does anyone know what is going on? How can I handle the situation of overlapping geometry in my ray tracer? &#xD;&#xA;Many thanks in advance for your help and support. Have a nice Weekend!&#xD;&#xA;&#xD;&#xA;Kind regards&#xD;&#xA;Sebastian&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qjJfD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ruuES.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/rX9Lk.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/6uRaL.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="32789" PostHistoryTypeId="1" PostId="10880" RevisionGUID="80f264d3-60dd-4d34-a5ca-036a6d87b9cf" CreationDate="2021-05-09T17:46:24.443" UserId="16352" Text="Ray tracing geometries with same position, translation and scale" ContentLicense="CC BY-SA 4.0" />
  <row Id="32790" PostHistoryTypeId="3" PostId="10880" RevisionGUID="80f264d3-60dd-4d34-a5ca-036a6d87b9cf" CreationDate="2021-05-09T17:46:24.443" UserId="16352" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32791" PostHistoryTypeId="2" PostId="10881" RevisionGUID="e6307082-c52b-4389-a3d7-c17001af8b65" CreationDate="2021-05-10T12:37:41.837" UserId="7952" Text="This is more of a comment then an answer:&#xD;&#xA;&#xD;&#xA;I have resolved this problem in a ray tracer using Constructive Solid Geometry(CSG). Which was done by adding operators that allowed us to create objects that are the union, difference, and intersection of a combination of objects. [Here is a wiki page on the subject.][1]&#xD;&#xA;&#xD;&#xA;CSG sounds difficult to implement, but it is actually surprisingly straight forward.&#xD;&#xA;&#xD;&#xA;But, this system was added for other reasons, it just turned out that we could &quot;subtract&quot; the light from the box (using your post as an example), then the intersection for the light itself falls out naturally since it can no longer hit the box where the two intersect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Constructive_solid_geometry" ContentLicense="CC BY-SA 4.0" />
  <row Id="32792" PostHistoryTypeId="5" PostId="10881" RevisionGUID="50181e0e-4cda-4ec5-9038-2e7e7537dbf6" CreationDate="2021-05-10T12:54:53.393" UserId="7952" Comment="added 288 characters in body" Text="This is more of a comment then an answer:&#xD;&#xA;&#xD;&#xA;I have resolved this problem in a ray tracer using Constructive Solid Geometry(CSG). Which was done by adding operators that allowed us to create objects that are the union, difference, and intersection of a combination of objects. [Here is a wiki page on the subject.][1]&#xD;&#xA;&#xD;&#xA;CSG sounds difficult to implement, but it is actually surprisingly straight forward.&#xD;&#xA;&#xD;&#xA;But, this system was added for other reasons, it just turned out that we could &quot;subtract&quot; the light from the box (using your post as an example), then the intersection for the light itself falls out naturally since it can no longer hit the box where the two intersect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This really is just reiterating what everyone has been saying in the comments, every solution is either done by creating real geometry that avoids the problem (like CSG) or use some sort of hack. I posted the CSG answer because it resolves the problem so naturally if it is available.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Constructive_solid_geometry" ContentLicense="CC BY-SA 4.0" />
  <row Id="32797" PostHistoryTypeId="50" PostId="10384" RevisionGUID="97155fab-c67c-46b2-90fe-3645b5a36ece" CreationDate="2021-05-11T08:08:20.840" UserId="-1" />
  <row Id="32798" PostHistoryTypeId="2" PostId="10883" RevisionGUID="9a4af7e7-9a7f-4d83-a022-60f9321fbcaf" CreationDate="2021-05-11T10:06:38.040" UserId="16382" Text="    unsigned int histogram[256]={0};&#xD;&#xA;    for(int i=0;i&lt;width*height;i++)  //to iterate over pixels&#xD;&#xA;      ++histogram[image[i]];&#xD;&#xA;&#xD;&#xA;    const float cutoffpercentage = 0.05;  //To cut off lower and upper values&#xD;&#xA;    unsigned char lowerbound,upperbound;&#xD;&#xA;    unsigned int histAccu =0;  //pixel entries &lt; 5% =lower bound&#xD;&#xA;    const unsigned int lowerpercentile = cutoffpercentage * width*height;&#xD;&#xA;    const unsigned int upperpercentile = (1-cutoffpercentage)*width*height;&#xD;&#xA;&#xD;&#xA;    for(int h =0;h &lt;256;h++){&#xD;&#xA;    histAccu += histogram[h];&#xD;&#xA;&#xD;&#xA;    if(histAccu &lt;= lowerpercentile){&#xD;&#xA;    lowerbound = h;&#xD;&#xA;    continue;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if(histAccu &gt;= upperpercentile){&#xD;&#xA;    upperbound = h;&#xD;&#xA;    break;&#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;Then assign new gray values. Can I write this program to equalize the histogram of an image on a gpu shader memory and programs for image segmentation, blurring, sharpening etc...as a shader program using openGL ?? Can we write shader programs just like a normal application program in C ?? Kindly help me on this, as I'm new to shader programming." ContentLicense="CC BY-SA 4.0" />
  <row Id="32799" PostHistoryTypeId="1" PostId="10883" RevisionGUID="9a4af7e7-9a7f-4d83-a022-60f9321fbcaf" CreationDate="2021-05-11T10:06:38.040" UserId="16382" Text="Can I write histogram equalization, blurring, sharpening grayscale image etc.. as shader programs with openGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32800" PostHistoryTypeId="3" PostId="10883" RevisionGUID="9a4af7e7-9a7f-4d83-a022-60f9321fbcaf" CreationDate="2021-05-11T10:06:38.040" UserId="16382" Text="|opengl|shader|c++|image-processing|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32801" PostHistoryTypeId="50" PostId="9426" RevisionGUID="6a1ea4a1-0681-483b-ad2f-a07627e326aa" CreationDate="2021-05-11T12:00:40.043" UserId="-1" />
  <row Id="32802" PostHistoryTypeId="2" PostId="10884" RevisionGUID="fca91578-80fd-4eef-9ae3-7067ad0695f9" CreationDate="2021-05-12T07:36:11.637" UserId="8830" Text="You can't create a solid by extruding a single curve or set of curves. Even if they are closed. Think about a circle on on the XY plane. If you extrude the circle along the Z axis you have an uncapped cylinder.&#xD;&#xA;&#xD;&#xA;Let's walk it back a bit though. If you have a single Bezier curve and extrude it you create a Bezier surface. You can quickly get your head around a Bezier surface if you understand a Bezier curve.&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/B%C3%A9zier_surface&#xD;&#xA;&#xD;&#xA;You can think of the Bezier surface as a blend through a set of curves. To extrude the curve you simply duplicate your original curve, and set the control points Z value to your extrusion distance. The original curve and new extruded curve create the control points for your surface.&#xD;&#xA;&#xD;&#xA;I actually have a Bezier surface example I wrote in Python. The only dependencies are Numpy and Matplotlib. It also uses the Bernstein Basis function imported from another file in the repository. You can play with the control points to see how modifying them effects the resulting surface. There's no error checking so you'll have to know what you're doing.&#xD;&#xA;&#xD;&#xA;https://github.com/jrz371/IntroToNurbsPython/blob/master/BezierSurface.py&#xD;&#xA;&#xD;&#xA;As for parameterizing the span and chord length you'll have to derive those yourself. I'm unfamiliar with your requirements. Understanding the Bezier curves and surfaces thoroughly should help you resolve that.&#xD;&#xA;&#xD;&#xA;Some of the comment suggest evaluating the curve and creating triangles. This is a bad approach. Tessellating a Bezier surface causes you to lose a lot of information. The Bezier surface is smooth whereas a set of triangles is not. For drawing a Bezier surface they are ultimately tessellated for the display, but they are kept in the original Bezier representation for modification.&#xD;&#xA;&#xD;&#xA;Bezier curves are also not the best representation for curves and surfaces. BSplines and NURBS are able to represent more complex surfaces and curves. Understanding Beziers is fundamental prerequisite before tackling those.&#xD;&#xA;&#xD;&#xA;Good luck!" ContentLicense="CC BY-SA 4.0" />
  <row Id="32807" PostHistoryTypeId="2" PostId="10886" RevisionGUID="f8915f86-ce28-4c6c-ba0c-eda5f8ec1aea" CreationDate="2021-05-12T18:07:52.633" UserId="16398" Text="&#xD;&#xA;there is no direct way to place a pixel on a window I am afraid.&#xD;&#xA;An indirect way would be to draw a small quad equal to the size of a pixel in relation to your window&#xD;&#xA;&#xD;&#xA;and essential y d3d 11 and 12 are most useful to draw geometry &#xD;&#xA;So I recommend you start from there and take your creativity ahead&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32808" PostHistoryTypeId="2" PostId="10887" RevisionGUID="e3ca059b-1890-403d-95ee-98774149e1eb" CreationDate="2021-05-13T03:10:10.107" UserId="16401" Text="I am looking for some way to estimate the amount of overlap between a rectangular prism(not axis aligned) and a frustum. The rectangular prism is probably always going to be larger than the frustum itself. Basically if the prism overlaps the frustum completely the overlap function should output 1, and if the prism is completely outside the frustum it should output 0. And hopefully if it partially overlaps it outputs a value between 0-1 that is the amount of overlap. It doesn't need to be a perfect estimate I think, but it should get close and should be correct for cases where its completely overlapping or completely separate.&#xD;&#xA;&#xD;&#xA;This will be used to voxelize the prism into a view frustum aligned 3D texture, where each entry in the 3D texture is a small frustum itself.&#xD;&#xA;&#xD;&#xA;Any ideas?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32809" PostHistoryTypeId="1" PostId="10887" RevisionGUID="e3ca059b-1890-403d-95ee-98774149e1eb" CreationDate="2021-05-13T03:10:10.107" UserId="16401" Text="Way to estimate the amount of overlap between a rectangular prism and a frustum?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32810" PostHistoryTypeId="3" PostId="10887" RevisionGUID="e3ca059b-1890-403d-95ee-98774149e1eb" CreationDate="2021-05-13T03:10:10.107" UserId="16401" Text="|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32811" PostHistoryTypeId="2" PostId="10888" RevisionGUID="565ee6b8-7b0d-407b-a8bb-44f1f380270a" CreationDate="2021-05-13T11:14:04.520" UserId="7952" Text="The typical prism/obb/aabb is made up of 6 planes, and the frustum is also typically made up of 6 planes.&#xD;&#xA;&#xD;&#xA;To generate a new volume that is the intersection of the two original volumes, use plane clipping to clip one against the other. This technique is generic enough that it can be used with any object like a mesh.&#xD;&#xA;&#xD;&#xA;That is take all the planes from the frustum then clip them one by one against the prism. After each clip operation, the new volume becomes the input to the next clipping operation.&#xD;&#xA;&#xD;&#xA;What is left will be the clipped volume representing the intersection of the two. Compute the volume of the new shape and divide it by the original volume and you will get a value that is somewhere between [0,1].&#xD;&#xA;&#xD;&#xA;This technique is often used to generate decals in games (though the volume computation is not done). Searching the web for decal generation alogorithms/tutorials should help you with the implementation details.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32812" PostHistoryTypeId="5" PostId="10888" RevisionGUID="d7e90771-51aa-46c0-a159-f30323e0eee0" CreationDate="2021-05-13T18:42:22.177" UserId="7952" Comment="added 85 characters in body" Text="The typical prism/obb/aabb is made up of 6 planes, and the frustum is also typically made up of 6 planes.&#xD;&#xA;&#xD;&#xA;To generate a new volume that is the intersection of the two original volumes, use plane clipping to clip one against the other. This technique is generic enough that it can be used with any object like a mesh.&#xD;&#xA;&#xD;&#xA;That is take all the planes from the frustum then clip them one by one against the prism. After each clip operation, the new volume becomes the input to the next clipping operation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is left will be the clipped volume representing the intersection of the two. Compute the volume of the new shape and divide it by the original volume and you will get a value that is somewhere between [0,1].&#xD;&#xA;&#xD;&#xA;This technique is often used to generate decals in games (though the volume computation is not done). Searching the web for decal generation alogorithms/tutorials should help you with the implementation details.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And if you have specific questions I am happy to add more details to this answer.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32824" PostHistoryTypeId="2" PostId="10890" RevisionGUID="d501204b-8071-4d52-9465-4bd942f94459" CreationDate="2021-05-15T09:06:48.280" UserId="16352" Text="I am working on the integration of Intel's Embree library into our home renderer to accelerate its rendering time. Our renderer supports various geometry types, such as quads, triangles, but also spheres, hyperbolas and tori. &#xD;&#xA;&#xD;&#xA;For ray casting triangles, triangle meshes and quads I am using Embree's build-in triangle- and quad-primitives. However, for the more complicated geometries I am using what's called User Defined Geometries (one passes functions for calculating bounding boxes, for intersection calculation and occlusion testing to Embree). &#xD;&#xA;&#xD;&#xA;For scenes with triangles, triangle meshes and quads, Embree really is faster (about twice as fast). My problem is that for scenes with User Defined Geometries, Embree takes about the same amount of time and often is even slower (if only for seconds).&#xD;&#xA;&#xD;&#xA;As an example, I have this scene:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is the output of the renderer when rendering this scene with 200 spp and without Embree support:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;sebastian@sebastian-N551JX ~/ART_Gallery/BRDF_Showcase $ artist OrenNayarSpheres.arm -DSAMPLES=200 -o normal200&#xD;&#xA;&#xD;&#xA;artist - photorealistic renderer&#xD;&#xA;ART version 2.0.4-dev, 8 cores detected&#xD;&#xA;(c) 1996-2020 by the ART development team &#xD;&#xA;&#xD;&#xA;reading scene description                                           0.82 sec&#xD;&#xA;optimising scene graph for raycasting                               0.00 sec&#xD;&#xA;identifying and analysing lightsources                              0.89 sec&#xD;&#xA;---   interactive mode on, goal are 200 spp   ---&#xD;&#xA;image sampling: path tracing, 200 spp                             328.34 sec&#xD;&#xA;---   interactive mode off   ---&#xD;&#xA;converting raw image to colour space                                0.09 sec&#xD;&#xA;applying interactive calibration tone mapping operator              0.13 sec&#xD;&#xA;luminance and chroma reduction for L &gt; 100.0                        0.11 sec&#xD;&#xA;converting to 8 bpc sRGB TIFF                                       0.08 sec&#xD;&#xA;opening result image in external viewer &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;... and here with Embree support:&#xD;&#xA;```&#xD;&#xA;sebastian@sebastian-N551JX ~/ART_Gallery/BRDF_Showcase $ artist OrenNayarSpheres.arm -DSAMPLES=200 -o embree200 -e&#xD;&#xA;&#xD;&#xA;artist - photorealistic renderer&#xD;&#xA;ART version 2.0.4-dev, 8 cores detected&#xD;&#xA;(c) 1996-2020 by the ART development team &#xD;&#xA;&#xD;&#xA;embree support enabled&#xD;&#xA;reading scene description                                           0.81 sec&#xD;&#xA;optimising scene graph for raycasting                               0.03 sec&#xD;&#xA;identifying and analysing lightsources                              0.90 sec&#xD;&#xA;---   interactive mode on, goal are 200 spp   ---&#xD;&#xA;image sampling: path tracing, 200 spp                             322.82 sec&#xD;&#xA;---   interactive mode off   ---&#xD;&#xA;converting raw image to colour space                                0.09 sec&#xD;&#xA;applying interactive calibration tone mapping operator              0.12 sec&#xD;&#xA;luminance and chroma reduction for L &gt; 100.0                        0.12 sec&#xD;&#xA;converting to 8 bpc sRGB TIFF                                       0.08 sec&#xD;&#xA;opening result image in external viewer &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As you can see, the rendering time with Embree is technically faster, but only about 4 seconds. &#xD;&#xA;Now, I wouldn't call myself an experienced programmer. I followed the provided Embree &quot;User Geometry Tutorial&quot; as good as I could. What I am asking myself is, what can I do to make this faster.&#xD;&#xA;&#xD;&#xA;I am quite aware of the fact that the information I am providing is probably too vague for a definite solution (and I am apologizing for that). My problem is that I don't know how to debug this issue and to determine, whether I am doing something wrong or if an improvement is not possible because of the internal workings of our renderer.&#xD;&#xA;The Renderer used (for everyone interested, its name is ART (Advanced Rendering Toolkit), it is Open Source and available [here][2]), does some things differently than other &quot;mainstream&quot; renderers. &#xD;&#xA;&#xD;&#xA;What I did do far was counting the intersection function calls and I have the suspicion that the renderer does more intersection calculations with Embree than without.&#xD;&#xA;&#xD;&#xA;Does anybody know any cases where Embree did not speed-up the rendering process? Does someone have any hints or tips for me, despite the little information I give? &#xD;&#xA;&#xD;&#xA;Thank you very much in advance for your help and have a nice day!&#xD;&#xA;&#xD;&#xA;-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;PS: I am not sure if it helps, but here is my intersection calculation function that I pass to Embree as a callback function. The renderer itself is written in C and Objective-C and so is the intersect function.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;    // intersection callback function&#xD;&#xA;    void embree_intersect_geometry(const int * valid,&#xD;&#xA;                                   void * geometryUserPtr,&#xD;&#xA;                                   unsigned int geomID,&#xD;&#xA;                                   unsigned int instID,&#xD;&#xA;                                   struct RTCRay * rtc_ray,&#xD;&#xA;                                   struct RTCHit * rtc_hit)&#xD;&#xA;    {&#xD;&#xA;        if(!valid[0])&#xD;&#xA;            return;&#xD;&#xA;    &#xD;&#xA;        // retreive raycaster and geometry data&#xD;&#xA;        ArnEmbree * embree = [ArnEmbree embreeManager];&#xD;&#xA;        ArnRayCaster * rayCaster = [embree getRayCasterFromRayCasterArray];&#xD;&#xA;        UserGeometryData * geometryData = (UserGeometryData *) geometryUserPtr;&#xD;&#xA;    &#xD;&#xA;        // perform the intersection&#xD;&#xA;        ArIntersectionList intersectionList = ARINTERSECTIONLIST_EMPTY;&#xD;&#xA;        [geometryData-&gt;_combinedAttributes&#xD;&#xA;                getIntersectionList&#xD;&#xA;                : rayCaster&#xD;&#xA;                : RANGE( ARNRAYCASTER_EPSILON(rayCaster), MATH_HUGE_DOUBLE)&#xD;&#xA;                : &amp;intersectionList&#xD;&#xA;        ];&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // if no intersection is found, return&#xD;&#xA;        if(!intersectionList.head)&#xD;&#xA;            return;&#xD;&#xA;    &#xD;&#xA;        // if the prev intersection is closer, free intersection list and return&#xD;&#xA;        ArcIntersection * prevIsect = ARINTERSECTIONLIST_HEAD(*rayCaster-&gt;embreeIntersectionList);&#xD;&#xA;        if(prevIsect &amp;&amp; prevIsect-&gt;t &lt; intersectionList.head-&gt;t) {&#xD;&#xA;            arintersectionlist_free_contents(&amp;intersectionList,&#xD;&#xA;                                             ARNRAYCASTER_INTERSECTION_FREELIST(rayCaster));&#xD;&#xA;            return;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        // update embree components&#xD;&#xA;        rtc_ray-&gt;tfar = (float) intersectionList.head-&gt;t;&#xD;&#xA;        rtc_hit-&gt;geomID = geomID;&#xD;&#xA;        rtc_hit-&gt;primID = 0;&#xD;&#xA;    &#xD;&#xA;        // since this function is called mutlple times in one go, clear out already existing&#xD;&#xA;        // intersection list, since we are only interested in nearest hit&#xD;&#xA;        arintersectionlist_free_contents(ARNRAYCASTER_EMBREE_INTERSECTIONLIST(rayCaster),&#xD;&#xA;                                         ARNRAYCASTER_INTERSECTION_FREELIST(rayCaster));&#xD;&#xA;    &#xD;&#xA;        // set intersection list&#xD;&#xA;        *rayCaster-&gt;embreeIntersectionList = intersectionList;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Some explanation of the code above:  The line &quot;ArnEmbree * embree = [ArnEmbree embreeManager];&quot; returns a singleton object with functionality concerning Embree. &quot;ArnRayCaster * rayCaster&quot; is an object that is used for traversing the scene graph. Since the renderer is multithreaded, one of such ArnRayCaster object is created for each thread. I am storing the relevant ArnRayCaster in an array and I am using the thread ID as the key. Finally, &quot;UserGeometryData&quot; is a struct that holds apart from the representation of the shape in memory, other information that is needed for the intersection calculation:&#xD;&#xA;``` &#xD;&#xA;typedef struct UserGeometryData {&#xD;&#xA;    ArNode * _shape;&#xD;&#xA;    ArTraversalState _traversalState;&#xD;&#xA;    AraCombinedAttributes * _combinedAttributes;&#xD;&#xA;    BOOL _isUserGeometry;&#xD;&#xA;}&#xD;&#xA;UserGeometryData;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Again, thank you very much in advance for your help!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e9Y4W.png&#xD;&#xA;  [2]: https://cgg.mff.cuni.cz/ART/download/" ContentLicense="CC BY-SA 4.0" />
  <row Id="32825" PostHistoryTypeId="1" PostId="10890" RevisionGUID="d501204b-8071-4d52-9465-4bd942f94459" CreationDate="2021-05-15T09:06:48.280" UserId="16352" Text="Embree: Performance issue when ray casting User Defined Geometry" ContentLicense="CC BY-SA 4.0" />
  <row Id="32826" PostHistoryTypeId="3" PostId="10890" RevisionGUID="d501204b-8071-4d52-9465-4bd942f94459" CreationDate="2021-05-15T09:06:48.280" UserId="16352" Text="|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32827" PostHistoryTypeId="50" PostId="10824" RevisionGUID="3ec8c6db-11e1-428d-ba2b-10e8f39e0624" CreationDate="2021-05-15T11:04:50.407" UserId="-1" />
  <row Id="32835" PostHistoryTypeId="2" PostId="10893" RevisionGUID="4f37a72e-4fac-4745-b8ad-ae7c9bcd368c" CreationDate="2021-05-16T16:38:38.757" UserId="16426" Text="I have a fairly complex-shaped object I've modeled, and in creating the LOD meshes, I've merged some verts, deleted some and even added some after in cases where this manipulation produced an n-gon. The UVs look fine, but these meshes have slightly different topology and vertex placement in some spots. Is this okay? What are the ramifications?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32836" PostHistoryTypeId="1" PostId="10893" RevisionGUID="4f37a72e-4fac-4745-b8ad-ae7c9bcd368c" CreationDate="2021-05-16T16:38:38.757" UserId="16426" Text="Is there a Performance Penalty for LOD objects with different topology?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32837" PostHistoryTypeId="3" PostId="10893" RevisionGUID="4f37a72e-4fac-4745-b8ad-ae7c9bcd368c" CreationDate="2021-05-16T16:38:38.757" UserId="16426" Text="|3d|performance|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32839" PostHistoryTypeId="2" PostId="10894" RevisionGUID="e5c64545-1a02-4b9c-8ee8-b97dd950fc3b" CreationDate="2021-05-17T14:41:24.680" UserId="13321" Text="My best guess at why you are not seeing a speed up with your user geometry, is that your example does not contain much BVH traversal.&#xD;&#xA;&#xD;&#xA;With traversing a triangle/quad mesh more time is spent traversing the BVH to decide which triangle you want to test than actually testing triangles. This is where embree really shines.&#xD;&#xA;&#xD;&#xA;It looks like your user geometry is just one primitive, compared with a triangle mesh which can be divided into many primitives/triangles (which the BVH can reduce to just the primitives you need to test).&#xD;&#xA;&#xD;&#xA;Considering the image you shared above, each ray will intersect the bounding box of your shape, and then call the same intersection function your non-embree version was calling. Comparing the two the non-embree version really isn't doing much more work.&#xD;&#xA;&#xD;&#xA;You will probably get better speedups using embree if you try scattering hundreds of your shapes or if you can find a way to divide your work into primitives." ContentLicense="CC BY-SA 4.0" />
  <row Id="32840" PostHistoryTypeId="50" PostId="8431" RevisionGUID="0787ec21-0a96-4929-b26c-fe0e5f09ba79" CreationDate="2021-05-18T02:06:40.600" UserId="-1" />
  <row Id="32845" PostHistoryTypeId="50" PostId="9364" RevisionGUID="4a217ce9-b46c-4683-b0dd-a33b7059f542" CreationDate="2021-05-18T22:08:30.870" UserId="-1" />
  <row Id="32846" PostHistoryTypeId="50" PostId="8291" RevisionGUID="903b9e52-c6f1-4b29-818d-4221557c8c01" CreationDate="2021-05-19T03:06:50.633" UserId="-1" />
  <row Id="32847" PostHistoryTypeId="2" PostId="10896" RevisionGUID="83afed92-0a88-482b-b963-696473dee419" CreationDate="2021-05-19T09:16:00.040" UserId="386" Text="There's a similar question [Why do identical polygons not z-fight in OpenGL?&#xD;&#xA;](https://computergraphics.stackexchange.com/questions/8940/why-do-identical-polygons-not-z-fight-in-opengl) but I believe I have a different setup.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As can be seen in the picture the vertices for the planes are different and on the left side, there's a clearly visible artifact. On the right side, there's no z-fighting even in movement. Why?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I5uA5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32848" PostHistoryTypeId="1" PostId="10896" RevisionGUID="83afed92-0a88-482b-b963-696473dee419" CreationDate="2021-05-19T09:16:00.040" UserId="386" Text="Why there's no z-fighting for coincident planes if the camera look perpendicular at them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32849" PostHistoryTypeId="3" PostId="10896" RevisionGUID="83afed92-0a88-482b-b963-696473dee419" CreationDate="2021-05-19T09:16:00.040" UserId="386" Text="|z-fighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32850" PostHistoryTypeId="5" PostId="10896" RevisionGUID="c2cca72d-0a47-4c78-8ecf-0093a0d05481" CreationDate="2021-05-19T10:40:46.163" UserId="386" Comment="added 54 characters in body" Text="There's a similar question [Why do identical polygons not z-fight in OpenGL?&#xD;&#xA;](https://computergraphics.stackexchange.com/questions/8940/why-do-identical-polygons-not-z-fight-in-opengl) but I believe I have a different setup.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As can be seen in the picture the vertices for the planes are different and on the left side, there's a clearly visible artifact. On the right side, there's no z-fighting even in movement. Why?&#xD;&#xA;&#xD;&#xA;Update: the white plane draw call submitted first.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I5uA5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32851" PostHistoryTypeId="2" PostId="10897" RevisionGUID="888626dc-bdf0-4e4d-9ca6-00f744793f62" CreationDate="2021-05-19T10:52:46.770" UserId="7952" Text="Even if two triangles aren't coincident...&#xD;&#xA;&#xD;&#xA;Z fighting happens because of floating point quantization, this results from all the math the shader does to compute vertex positions such as: $glPosition = Projection*View*Model*vertex\_position$&#xD;&#xA;&#xD;&#xA;When the vertices are all the same distance and angle from the camera then all the floating points values are effectively the same and the tiny error that crops up is so close that the Z fighting *appears* to go away.&#xD;&#xA;&#xD;&#xA;On the other hand if you change the angle of the camera even a little bit then all the floating point values for each vertex are now slightly different and so is the quantization. This results in the z fighting that you are seeing.&#xD;&#xA;&#xD;&#xA;But keep moving the camera back, and the results for the perfectly aligned camera will eventually begin to exhibit the same behavior. The camera position is also a floating point value and subject to floating point error so no matter how perfectly the camera is aligned, it will still, eventually, have enough error to cause the same issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="32852" PostHistoryTypeId="5" PostId="10896" RevisionGUID="aa5fb01d-2c41-4932-8ce0-d42a44023f5c" CreationDate="2021-05-19T12:01:33.293" UserId="386" Comment="added 62 characters in body" Text="There's a similar question [Why do identical polygons not z-fight in OpenGL?&#xD;&#xA;](https://computergraphics.stackexchange.com/questions/8940/why-do-identical-polygons-not-z-fight-in-opengl) but I believe I have a different setup.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As can be seen in the picture the vertices for the planes are different and on the left side, there's a clearly visible artifact. On the right side, there's no z-fighting even in movement. Why?&#xD;&#xA;&#xD;&#xA;Update: the white plane draw call submitted first. The depth compare operation is `VK_COMPARE_OP_LESS_OR_EQUAL`.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I5uA5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32861" PostHistoryTypeId="50" PostId="10503" RevisionGUID="d96f1b0b-7ee2-49c5-a894-6d6cf8d9aeb8" CreationDate="2021-05-20T09:07:45.787" UserId="-1" />
  <row Id="32862" PostHistoryTypeId="2" PostId="10900" RevisionGUID="4b698cec-a8bc-4224-9607-b4ca3dceb19e" CreationDate="2021-05-21T03:54:36.393" UserId="16387" Text="In many resources the BRDF is defined like $$f_{r}(\omega_{i},\omega_{r}) = \frac{\mathrm{d}L_{r}(\omega_{r})}{L_{i}(\omega_{i})\,\cos{\theta_{i}}\,\mathrm{d}\omega_{i}}.$$ The index $r$ might be replaced by $o$ but overall the equation looks something like this. However, in some other resources I see the definition $$f_{r}(\theta_{i},\phi_{i};\theta_{r},\phi_{r}) \equiv \frac{\mathrm{d}L_{r}(\theta_{i},\phi_{i};\theta_{r},\phi_{r};E_{i})}{L_{i}(\theta_{i},\phi_{i})\,\cos{\theta_{i}}\,\mathrm{d}\omega_{i}}.$$ The second definition seems more precise to me as it – besides other things – clearly states that the BRDF in its purest form is a 4-dimensional function of two directions and clearly differentiates between the direction $(\theta_{i},\phi_{i})$ and the solid angle $\omega_{i}$.&#xD;&#xA;&#xD;&#xA;It seems to me as if the first definition mixes up the direction of incidence and the solid angle in the direction of incidence. The symbol $\omega_{i}$ stands for the direction – at least I hope so as the BRDF is not a function of solid angles – to economize on writing, I understand that, but what is $\mathrm{d}\omega_{i}$ then? It must be the solid angle but $\omega_{i}$ is a direction, not a solid angle. Is $\mathrm{d}\omega_{i}$ simply a common way to express the solid angle in a specific direction? May I have misunderstood something?&#xD;&#xA;&#xD;&#xA;Another thing I've noticed is that the solid angle in the definitions of radiance, luminance and basically all other radiometric and photometric quantities that deal with a solid angle is symbolized with $\Omega$, i.e. a big omega. Actually, as far as I can tell, solid angles are usually symbolized with $\Omega$. Why is it different in the definition of the BRDF? Am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32863" PostHistoryTypeId="1" PostId="10900" RevisionGUID="4b698cec-a8bc-4224-9607-b4ca3dceb19e" CreationDate="2021-05-21T03:54:36.393" UserId="16387" Text="Why is the symbol for solid angle a small omega in the definition of the BRDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32864" PostHistoryTypeId="3" PostId="10900" RevisionGUID="4b698cec-a8bc-4224-9607-b4ca3dceb19e" CreationDate="2021-05-21T03:54:36.393" UserId="16387" Text="|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32865" PostHistoryTypeId="2" PostId="10901" RevisionGUID="5626d682-6f74-4fb1-9fdc-cdf00fb253f3" CreationDate="2021-05-21T08:14:58.737" UserId="10096" Text="The $\omega$ is a direction. Whether you parametrise this direction in spherical coordinates $(\phi, \theta)$, in Cartesian coordinates $(x,y,z)$, or some other coordinate system is irrelevant. Thus one uses $\omega$ to represent directions. $dx$ typically refers to a differential. In the current case it is w.r.t. the solid angle measure $\sigma$, so it would be more precise to write $d\sigma(\omega)$. This is still informal and handwavy however. The meaning of the expression $\frac{dL}{d\omega}$ is formalised in the PhD thesis of Eric Veach." ContentLicense="CC BY-SA 4.0" />
  <row Id="32869" PostHistoryTypeId="2" PostId="10903" RevisionGUID="baa87a9e-2571-4807-abda-b97fec940e2d" CreationDate="2021-05-22T17:46:25.067" UserId="13456" Text="Yes you can. There are basically two approaches:&#xD;&#xA;&#xD;&#xA;- You draw everything to a framebuffer object. Then you apply image processing fragment shaders to resulting texture of the previous draw call, where the shaders take the pervious texture with a sampler.&#xD;&#xA;&#xD;&#xA;or if you have a particular image and you would like to have more control on the numeric precision, the number of neighbours available to you while working on pixel etc:  &#xD;&#xA;&#xD;&#xA;- You apply compute shaders directly to image.&#xD;&#xA;&#xD;&#xA;For the first approach, see [Learn OpenGL](https://learnopengl.com/Advanced-OpenGL/Framebuffers), for compute shaders, see [Anton's tutorial](https://antongerdelan.net/opengl/compute.html)  " ContentLicense="CC BY-SA 4.0" />
  <row Id="32870" PostHistoryTypeId="2" PostId="10904" RevisionGUID="913a65b8-80d1-480b-bc7d-ea7ec500023d" CreationDate="2021-05-23T13:00:26.533" UserId="16243" Text="I know this is a pretty old question, but I am wondering if the problem does not come from sampling the whole hemisphere of the light, instead of only the visible portion of it from the hit location's point of view (see this : schuttejoe.github.io/post/arealightsampling) ? The visible solid angle is only 2*PI*(1 - cos(theta)) instead of 2*PI." ContentLicense="CC BY-SA 4.0" />
  <row Id="32871" PostHistoryTypeId="2" PostId="10905" RevisionGUID="fd155b43-49a8-47c9-b486-10591825e463" CreationDate="2021-05-23T19:16:35.920" UserId="48" Text="The use of spherical coordinates like $(\theta, \phi)$ is kind of an implementation detail that isn't an essential part of the definition of a BRDF, or other functions defined over a spherical domain generally.&#xD;&#xA;&#xD;&#xA;It's a lot like how in vector math, we will often express a point or vector by a single symbol like $v$, understanding that &quot;under the hood&quot; it's going to be expressed as coordinates $(v_x, v_y, v_z)$ in some coordinate system. Writing out all the coordinates in every equation would make notation very verbose and would often obscure the vectorial relationships we really care about.&#xD;&#xA;&#xD;&#xA;Similarly, with functions defined over a sphere or hemisphere, we will often express a direction by $\omega$, understanding that when we get to actually writing code this will stand in for some coordinates on the sphere, but the exact choice of representation is not relevant to the math.&#xD;&#xA;&#xD;&#xA;The symbol $\mathrm{d}\omega$ represents a differential quantity of solid angle—this is an abuse of notation for sure, but it serves the same purpose of abstracting away the implementation details; in spherical coordinates that would be $\sin(\theta) \, \mathrm{d}\theta \, \mathrm{d}\phi$ for example, but it's kind of assumed as background knowledge that you know how to integrate things over a sphere in whatever coordinate representation you're using.&#xD;&#xA;&#xD;&#xA;Differentials as seen in calculus sort of aren't actual values themselves, but are things that can be either integrated over (in which case they specify the measure of the integration), or you can take a ratio of two differentials, which defines a density function (kind of a generalized derivative).&#xD;&#xA;&#xD;&#xA;The symbol $\Omega$ is most often used to represent the hemisphere in my experience, not solid angles generically. You'll see something like $\int_\Omega \text{...stuff...}\, \mathrm{d}\omega$ to mean integrate that function over the normal-facing hemisphere with respect to the solid angle measure (i.e. area on the unit sphere)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32872" PostHistoryTypeId="5" PostId="10744" RevisionGUID="87ac534b-a718-4af9-85c2-764bfb11c0fb" CreationDate="2021-05-24T06:01:47.620" UserId="67" Comment="Grammar and other fixes" Text="I have been told there is no performance difference if you are skilled enough when it comes to gpu computing. And cuda only performs better because nvidia wants it to. I have also read graphic api's compute shaders are not as good as OpenCL/cuda. I don't understand how are compute shader different from Cuda/OpenCL and why would they be slow (if they are). I wanted to know this because OpenCL is difficult to understand and setup for me. Will there be a performance hit on using OpenGL compute shader and will Vulkan compute shader perform better than OpenGL's? " ContentLicense="CC BY-SA 4.0" />
  <row Id="32873" PostHistoryTypeId="4" PostId="10744" RevisionGUID="87ac534b-a718-4af9-85c2-764bfb11c0fb" CreationDate="2021-05-24T06:01:47.620" UserId="67" Comment="Grammar and other fixes" Text="Performance difference in OpenGL compute shader vs Vulkan Compute Shader vs Cuda/OpenCL and others" ContentLicense="CC BY-SA 4.0" />
  <row Id="32874" PostHistoryTypeId="24" PostId="10744" RevisionGUID="87ac534b-a718-4af9-85c2-764bfb11c0fb" CreationDate="2021-05-24T06:01:47.620" Comment="Proposed by 67 approved by 482 edit id of 563" ContentLicense="CC BY-SA 4.0" />
  <row Id="32884" PostHistoryTypeId="2" PostId="10907" RevisionGUID="92174325-694e-4628-91cf-f7e6ac4eb555" CreationDate="2021-05-24T15:52:41.407" UserId="13375" Text="I was watching this trailer:&#xD;&#xA;https://www.youtube.com/watch?v=pWh5388AEHw&#xD;&#xA;&#xD;&#xA;and at 1:22, the player used a magic trick that created a sphere that warped the projection of the scene.&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;Does anyone know what is this effect?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vUcJ1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32885" PostHistoryTypeId="1" PostId="10907" RevisionGUID="92174325-694e-4628-91cf-f7e6ac4eb555" CreationDate="2021-05-24T15:52:41.407" UserId="13375" Text="What is this graphical effect called?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32886" PostHistoryTypeId="3" PostId="10907" RevisionGUID="92174325-694e-4628-91cf-f7e6ac4eb555" CreationDate="2021-05-24T15:52:41.407" UserId="13375" Text="|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32887" PostHistoryTypeId="2" PostId="10908" RevisionGUID="bbce21e1-d6f2-48a9-9656-3cd98dbeece8" CreationDate="2021-05-24T18:03:56.687" UserId="506" Text="I don’t think there’s a formally established name for it, but it’s generally known as distortion, warping, or refraction. It works by taking an already rendered version of the current frame, sampling it with warped/stretched texture coordinates, and, usually, compositing the result back in with the rest of the scene. One of the first games I know of that used it was Half-Life 2, for an effect when the Strider enemies fired their cannon:&#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/SkTl5.jpg)&#xD;&#xA;&#xD;&#xA;For an example of what this looks like in a modern game engine, check out [Unreal’s documentation](https://docs.unrealengine.com/en-US/RenderingAndGraphics/Materials/HowTo/Refraction/index.html)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32888" PostHistoryTypeId="5" PostId="10904" RevisionGUID="79a8dbc8-47e7-476a-a9d4-b29c7335e213" CreationDate="2021-05-24T19:34:00.800" UserId="16243" Comment="typo" Text="I know this is a pretty old question, but I am wondering if the problem does not come from sampling the whole hemisphere of the light, instead of only the visible portion of it from the hit location's point of view (see this : schuttejoe.github.io/post/arealightsampling) ? The visible solid angle is only 2\*PI\*(1 - cos(theta)) instead of 2*PI." ContentLicense="CC BY-SA 4.0" />
  <row Id="32890" PostHistoryTypeId="52" PostId="10907" RevisionGUID="1a4b5d2b-9f35-4a3e-aebb-2bbc2938ca08" CreationDate="2021-05-24T23:52:45.773" />
  <row Id="32891" PostHistoryTypeId="2" PostId="10909" RevisionGUID="70f1f659-9773-46aa-98fc-94d8c370b4d9" CreationDate="2021-05-25T14:26:39.907" UserId="1650" Text="When scaling an image with bicubic interpolation, the [Cubic Hermite spline interpolation][1] is used.  `smoothstep` is one of the four basis functions of this kind of interpolation.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f(x) = 3x^2 - 2x^3&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I'm trying to better understand the use of `smoothstep` by itself.  I've seen a trick used in quite a few places in Computer Graphics.  Say something is interpolated linearly&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L(t) = (1-t)A + t(B - A)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;What people often do to make it interesting is remap the interpolation parameter with `smoothstep` and then do regular lerp&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;u = smoothstep(t) \\&#xD;&#xA;L(u) = (1-u)A + u(B - A)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The result (interpolant) is still linear interpolation but the speed at which the object moves varies: starts slow and ends up slow, speeds up in the middle.&#xD;&#xA;&#xD;&#xA;Some examples&#xD;&#xA;&#xD;&#xA;* [Linear interpolation of position but smooth timestepping][2]&#xD;&#xA;* [Faking smoothness with bilinear texture look-ups][3]&#xD;&#xA;* [Fake smootheness in Perlin Noise when bilinear interpolation][4]&#xD;&#xA;&#xD;&#xA;When interpolating a value, by remapping the interpolation parameter, an illusion of non-linear output is achived since the linearly increasing parameter was looped through `smoothstep` (non-linear).&#xD;&#xA;&#xD;&#xA;**Is this just a remapping trick or is there some mathematical concept behind it?**&#xD;&#xA;&#xD;&#xA;When I looked up [`smoothstep` in Wikipedia][5], it says&#xD;&#xA;&#xD;&#xA;&gt; In HLSL and GLSL, smoothstep implements the $S_1(x)$ the cubic [Hermite interpolation][6] after clamping&#xD;&#xA;&#xD;&#xA;However, [Hermite interpolation][6] it links to is different from [Cubic Hermite spline][1] interpolation; they're two different articles.  [Former seems to be a kind of Polynomial Interpolation][7].  I'm confused as to what this function really is/does at a deeper level.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline&#xD;&#xA;  [2]: https://sol.gfxile.net/interpolation/index.html#c4&#xD;&#xA;  [3]: https://iquilezles.org/www/articles/texture/texture.htm&#xD;&#xA;  [4]: https://web.archive.org/web/20151103105506/http://www.noisemachine.com/talk1/15.html&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Smoothstep&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Hermite_interpolation&#xD;&#xA;  [7]: http://fyzikazeme.sk/mainpage/stud_mat/nm/lecture5.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="32892" PostHistoryTypeId="1" PostId="10909" RevisionGUID="70f1f659-9773-46aa-98fc-94d8c370b4d9" CreationDate="2021-05-25T14:26:39.907" UserId="1650" Text="Fake cubic Hermite spline interpolation with smoothstep" ContentLicense="CC BY-SA 4.0" />
  <row Id="32893" PostHistoryTypeId="3" PostId="10909" RevisionGUID="70f1f659-9773-46aa-98fc-94d8c370b4d9" CreationDate="2021-05-25T14:26:39.907" UserId="1650" Text="|interpolation|animation|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32894" PostHistoryTypeId="5" PostId="10909" RevisionGUID="7a8eeac5-e89d-4be0-955b-cc7ba95f8947" CreationDate="2021-05-25T14:33:40.750" UserId="1650" Comment="Add detail about optimisation" Text="When scaling an image with [Bicubic Interpolation][1], the [Cubic Hermite spline][2] interpolation is used.  `smoothstep` is one of the four basis functions of this kind of interpolation.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f(x) = 3x^2 - 2x^3&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I'm trying to better understand the use of `smoothstep` by itself.  I've seen a trick used in quite a few places in Computer Graphics.  Say something is interpolated linearly&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L(t) = (1-t)A + t(B - A)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;What people often do to make it interesting is remap the interpolation parameter with `smoothstep` and then do regular lerp&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;u = smoothstep(t) \\&#xD;&#xA;L(u) = (1-u)A + u(B - A)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The result (interpolant) is still linear interpolation but the speed at which the object moves varies: starts slow and ends up slow, speeds up in the middle.&#xD;&#xA;&#xD;&#xA;When interpolating a value, by remapping the interpolation parameter, an illusion of non-linear output is achived since the linearly increasing parameter was looped through `smoothstep` (non-linear).&#xD;&#xA;&#xD;&#xA;Some examples&#xD;&#xA;&#xD;&#xA;* [Linear interpolation of position but smooth movement][3]&#xD;&#xA;* [Faking smoothness with bilinear texture look-ups][4]&#xD;&#xA;* [Faking smootheness in Perlin Noise when bilinearly interpolating][5]&#xD;&#xA;&#xD;&#xA;I think this trick is done to avoid doing a full blown Cubic Hermite spline interpolation which involves looking up 16 values and evaluating the cubic Hermite spline equation 5 times.  **Is this just a remapping trick or is there some mathematical concept behind it?**&#xD;&#xA;&#xD;&#xA;When I looked up [`smoothstep` in Wikipedia][6], it says&#xD;&#xA;&#xD;&#xA;&gt; In HLSL and GLSL, smoothstep implements the $S_1(x)$ the cubic [Hermite interpolation][7] after clamping&#xD;&#xA;&#xD;&#xA;However, [Hermite interpolation][7] it links to is different from [Cubic Hermite spline][2] interpolation; they're two different articles.  [Former seems to be a kind of Polynomial Interpolation][8].  I'm confused as to what this function really is/does at a deeper level.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bicubic_interpolation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline&#xD;&#xA;  [3]: https://sol.gfxile.net/interpolation/index.html#c4&#xD;&#xA;  [4]: https://iquilezles.org/www/articles/texture/texture.htm&#xD;&#xA;  [5]: https://web.archive.org/web/20151103105506/http://www.noisemachine.com/talk1/15.html&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Smoothstep&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Hermite_interpolation&#xD;&#xA;  [8]: http://fyzikazeme.sk/mainpage/stud_mat/nm/lecture5.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="32895" PostHistoryTypeId="6" PostId="10909" RevisionGUID="5bbc87e2-41bb-4829-b2ab-f401f0703ece" CreationDate="2021-05-25T14:43:48.270" UserId="1650" Comment="Add math tag" Text="|mathematics|interpolation|animation|curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32896" PostHistoryTypeId="5" PostId="10909" RevisionGUID="cf0fa4ca-d317-47c8-a3cf-a50a3c101099" CreationDate="2021-05-26T00:57:26.683" UserId="1650" Comment="Refine question" Text="When scaling an image with [Bicubic Interpolation][1], the [Cubic Hermite spline][2] interpolation is used.  `smoothstep` is one of the four basis/blend functions of this kind of interpolation.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f(x) = 3x^2 - 2x^3&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I've seen a trick used in quite a few places in Computer Graphics.  Say something is interpolated linearly&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L(t) = (1-t)A + t(B - A)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;What people often do to make it interesting is remap the interpolation parameter $t$ with `smoothstep` and then lerp&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;u = smoothstep(t) \\&#xD;&#xA;L(u) = (1-u)A + u(B - A)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The result (interpolant) is still linear but the speed at which the output varies isn't constant: starts slow and ends up slow, speeds up in the middle.  When interpolating a value, by remapping the interpolation parameter, an illusion of non-linear output is achived since the linearly increasing parameter was looped through `smoothstep` (non-linear).&#xD;&#xA;&#xD;&#xA;Some examples&#xD;&#xA;&#xD;&#xA;* [Linear interpolation of position but smooth movement][3]&#xD;&#xA;* [Faking smoothness with bilinear texture look-ups][4]&#xD;&#xA;* [Faking smootheness in Perlin Noise when bilinearly interpolating gradient vectors][5]&#xD;&#xA;&#xD;&#xA;I'm trying to better understand this trick.  I think this trick is done to avoid doing a full blown Cubic Hermite spline interpolation which involves looking up 16 values and evaluating the cubic Hermite spline equation 5 times.  **Is this just a remapping trick or is there some mathematical concept behind it?**&#xD;&#xA;&#xD;&#xA;When I looked up [`smoothstep` in Wikipedia][6], it says&#xD;&#xA;&#xD;&#xA;&gt; In HLSL and GLSL, smoothstep implements the $S_1(x)$ the cubic [Hermite interpolation][7] after clamping&#xD;&#xA;&#xD;&#xA;However, [Hermite interpolation][7] it links to is different from [Cubic Hermite spline][2] interpolation; they're two different articles.  [Former seems to be a kind of Polynomial Interpolation][8].  I'm confused as to what this function really is/does at a deeper level.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bicubic_interpolation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline&#xD;&#xA;  [3]: https://sol.gfxile.net/interpolation/index.html#c4&#xD;&#xA;  [4]: https://iquilezles.org/www/articles/texture/texture.htm&#xD;&#xA;  [5]: https://web.archive.org/web/20151103105506/http://www.noisemachine.com/talk1/15.html&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Smoothstep&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Hermite_interpolation&#xD;&#xA;  [8]: http://fyzikazeme.sk/mainpage/stud_mat/nm/lecture5.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="32897" PostHistoryTypeId="2" PostId="10910" RevisionGUID="241e6913-a5c3-4320-b90d-922338d71727" CreationDate="2021-05-26T14:24:25.377" UserId="6496" Text="Why are there very similar yet distinct arrays: `gl_ClipDistance[]` vs `gl_CullDistance[]`?&#xD;&#xA;&#xD;&#xA;What would be some use cases where their need become apparent? " ContentLicense="CC BY-SA 4.0" />
  <row Id="32898" PostHistoryTypeId="1" PostId="10910" RevisionGUID="241e6913-a5c3-4320-b90d-922338d71727" CreationDate="2021-05-26T14:24:25.377" UserId="6496" Text="gl_ClipDistance vs gl_CullDistance" ContentLicense="CC BY-SA 4.0" />
  <row Id="32899" PostHistoryTypeId="3" PostId="10910" RevisionGUID="241e6913-a5c3-4320-b90d-922338d71727" CreationDate="2021-05-26T14:24:25.377" UserId="6496" Text="|shader|glsl|rasterizer|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32900" PostHistoryTypeId="5" PostId="10910" RevisionGUID="3bf2c68b-4365-4cb0-ab2a-07f60fae47e5" CreationDate="2021-05-26T14:36:31.883" UserId="6496" Comment="added 24 characters in body" Text="Why are there very similar yet distinct arrays: `gl_ClipDistance[]` vs `gl_CullDistance[]`?&#xD;&#xA;&#xD;&#xA;What would be some use cases where the need for two distinct entities become apparent? " ContentLicense="CC BY-SA 4.0" />
  <row Id="32901" PostHistoryTypeId="2" PostId="10911" RevisionGUID="c63f6c5d-b072-4e73-9c27-8fe2ad6e443f" CreationDate="2021-05-26T16:06:40.600" UserId="2654" Text="The two are difference because they do different things. Clipping and culling aren't the same thing at all. If an edge crosses a clip plane, the primitive has to be clipped to be within that plane. This means generating new primitives from the old one.&#xD;&#xA;&#xD;&#xA;If any vertex of a primitive is outside of a cull plane, then the entire primitive is culled.&#xD;&#xA;&#xD;&#xA;You use the cull planes when you want the VS to be able to cull out primitives based on some calculation. You use clip primitives when you want primitive rendering to be bounded to some non-clip-space region (though line and point width can violate those borders)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32905" PostHistoryTypeId="2" PostId="10913" RevisionGUID="68bbc9c7-954b-47da-98b4-34ea7d0e4cb8" CreationDate="2021-05-26T16:52:34.243" UserId="13716" Text="I am trying to port my simple app from D3D12 to Metal and I am stuck at rendering a simple triangle.&#xD;&#xA;&#xD;&#xA;The window does not show any primitives; only the clear color is visible.&#xD;&#xA;&#xD;&#xA;Debugging my application, I noticed, that all primitives are clipped (Performance &gt; Primitives &gt; Primitives Clipped: 100%). I fail to understand why this happens, as these are my coordinates:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;struct vertex { float x, y, z; };&#xD;&#xA;static const struct vertex vertices[] =&#xD;&#xA;{&#xD;&#xA;    { 0.0f, 0.5f, 0.0f },&#xD;&#xA;    { 0.5f, -0.5f, 0.0f },&#xD;&#xA;    { -0.5f, -0.5f, 0.0f }&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;What I have tried so far:&#xD;&#xA;- Explicitly setting the viewport `{0, 0, 800, 600, 0, 1}`.&#xD;&#xA;- Explicitly setting scissors `{0, 0, 800, 600}`.&#xD;&#xA;- Setting the cull mode to `MTLCullModeNone`.&#xD;&#xA;- Setting the fill mode to `MTLTriangleFillModeFill`.&#xD;&#xA;- Changing the winding order.&#xD;&#xA;- Altering the vertex input layout; but I am confident, that mine matches the input.&#xD;&#xA;&#xD;&#xA;Are there any pitfalls of Metal that I am missing? (i.e. setting the sample mask like in D3D12?)&#xD;&#xA;&#xD;&#xA;My pipeline for reference:&#xD;&#xA;```&#xD;&#xA;    MTLRenderPipelineDescriptor* descriptor = [MTLRenderPipelineDescriptor new];&#xD;&#xA;    descriptor.vertexFunction   = desc-&gt;vertex-&gt;handle;&#xD;&#xA;    descriptor.fragmentFunction = desc-&gt;pixel-&gt;handle;&#xD;&#xA;    descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;&#xD;&#xA;    &#xD;&#xA;    MTLVertexDescriptor* vs = descriptor.vertexDescriptor;&#xD;&#xA;    vs.attributes[0].format = MTLVertexFormatFloat3;&#xD;&#xA;    vs.attributes[0].offset = 0;&#xD;&#xA;    vs.attributes[0].bufferIndex = 0;&#xD;&#xA;    &#xD;&#xA;    vs.layouts[0].stride        = sizeof(float) * 3;&#xD;&#xA;    vs.layouts[0].stepFunction  = MTLVertexStepFunctionPerVertex;&#xD;&#xA;    vs.layouts[0].stepRate      = 1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Note, that I am NOT using `MTKView`.&#xD;&#xA;&#xD;&#xA;The following is my shader used:&#xD;&#xA;```metal&#xD;&#xA;struct Out &#xD;&#xA;{&#xD;&#xA;    float4 pos [[position]];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vertex Out vertexShader(&#xD;&#xA;    const device float3* vertices [[buffer(0)]],&#xD;&#xA;    unsigned int idx [[vertex_id]]&#xD;&#xA;) {&#xD;&#xA;    Out out;&#xD;&#xA;    out.pos = float4(vertices[idx], 1.0);&#xD;&#xA;    return out;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;fragment float4 fragmentShader(Out in [[stage_in]])&#xD;&#xA;{&#xD;&#xA;    // TODO: Write fragment shader&#xD;&#xA;    return float4(1, 0, 0, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32906" PostHistoryTypeId="1" PostId="10913" RevisionGUID="68bbc9c7-954b-47da-98b4-34ea7d0e4cb8" CreationDate="2021-05-26T16:52:34.243" UserId="13716" Text="Metal API clips all primitives?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32907" PostHistoryTypeId="3" PostId="10913" RevisionGUID="68bbc9c7-954b-47da-98b4-34ea7d0e4cb8" CreationDate="2021-05-26T16:52:34.243" UserId="13716" Text="|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32908" PostHistoryTypeId="5" PostId="10911" RevisionGUID="aa1e5fc4-400b-49d2-adee-a54f0b8d91d6" CreationDate="2021-05-26T17:11:39.090" UserId="2654" Comment="deleted 1 character in body" Text="The two are different because they do different things. Clipping and culling aren't the same thing at all. If an edge crosses a clip plane, the primitive has to be clipped to be within that plane. This means generating new primitives from the old one.&#xD;&#xA;&#xD;&#xA;If any vertex of a primitive is outside of a cull plane, then the entire primitive is culled.&#xD;&#xA;&#xD;&#xA;You use the cull planes when you want the VS to be able to cull out primitives based on some calculation. You use clip primitives when you want primitive rendering to be bounded to some non-clip-space region (though line and point width can violate those borders)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32909" PostHistoryTypeId="5" PostId="10913" RevisionGUID="2fc5e415-0c4f-4abc-ac65-d9df0eceb6da" CreationDate="2021-05-26T17:14:36.643" UserId="13716" Comment="Supplied more informations" Text="I am trying to port my simple app from D3D12 to Metal and I am stuck at rendering a simple triangle.&#xD;&#xA;&#xD;&#xA;The window does not show any primitives; only the clear color is visible.&#xD;&#xA;&#xD;&#xA;Debugging my application, I noticed, that all primitives are clipped (Performance &gt; Primitives &gt; Primitives Clipped: 100%). I fail to understand why this happens, as these are my coordinates:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;struct vertex { float x, y, z; };&#xD;&#xA;static const struct vertex vertices[] =&#xD;&#xA;{&#xD;&#xA;    { 0.0f, 0.5f, 0.0f },&#xD;&#xA;    { 0.5f, -0.5f, 0.0f },&#xD;&#xA;    { -0.5f, -0.5f, 0.0f }&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;What I have tried so far:&#xD;&#xA;- Explicitly setting the viewport `{0, 0, 800, 600, 0, 1}`.&#xD;&#xA;- Explicitly setting scissors `{0, 0, 800, 600}`.&#xD;&#xA;- Setting the cull mode to `MTLCullModeNone`.&#xD;&#xA;- Setting the fill mode to `MTLTriangleFillModeFill`.&#xD;&#xA;- Changing the winding order.&#xD;&#xA;- Altering the vertex input layout; but I am confident, that mine matches the input.&#xD;&#xA;&#xD;&#xA;Are there any pitfalls of Metal that I am missing? (i.e. setting the sample mask like in D3D12?)&#xD;&#xA;&#xD;&#xA;My pipeline for reference:&#xD;&#xA;```&#xD;&#xA;    MTLRenderPipelineDescriptor* descriptor = [MTLRenderPipelineDescriptor new];&#xD;&#xA;    descriptor.vertexFunction   = desc-&gt;vertex-&gt;handle;&#xD;&#xA;    descriptor.fragmentFunction = desc-&gt;pixel-&gt;handle;&#xD;&#xA;    descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;&#xD;&#xA;    &#xD;&#xA;    MTLVertexDescriptor* vs = descriptor.vertexDescriptor;&#xD;&#xA;    vs.attributes[0].format = MTLVertexFormatFloat3;&#xD;&#xA;    vs.attributes[0].offset = 0;&#xD;&#xA;    vs.attributes[0].bufferIndex = 0;&#xD;&#xA;    &#xD;&#xA;    vs.layouts[0].stride        = sizeof(float) * 3;&#xD;&#xA;    vs.layouts[0].stepFunction  = MTLVertexStepFunctionPerVertex;&#xD;&#xA;    vs.layouts[0].stepRate      = 1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Note, that I am NOT using `MTKView`.&#xD;&#xA;&#xD;&#xA;The following is my shader used:&#xD;&#xA;```metal&#xD;&#xA;struct Out &#xD;&#xA;{&#xD;&#xA;    float4 pos [[position]];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vertex Out vertexShader(&#xD;&#xA;    const device float3* vertices [[buffer(0)]],&#xD;&#xA;    unsigned int idx [[vertex_id]]&#xD;&#xA;) {&#xD;&#xA;    Out out;&#xD;&#xA;    out.pos = float4(vertices[idx], 1.0);&#xD;&#xA;    return out;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;fragment float4 fragmentShader(Out in [[stage_in]])&#xD;&#xA;{&#xD;&#xA;    // TODO: Write fragment shader&#xD;&#xA;    return float4(1, 0, 0, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;I made following changes and my triangle is finally being rendered:&#xD;&#xA;```c&#xD;&#xA;struct vertex { float x, y, z, w; };&#xD;&#xA;static const struct vertex vertices[] =&#xD;&#xA;{&#xD;&#xA;    { 0.0f, 0.5f, 0.0f, 1.f },&#xD;&#xA;    { 0.5f, -0.5f, 0.0f, 1.f},&#xD;&#xA;    { -0.5f, -0.5f, 0.0f, 1.f }&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;// Vertex Descriptor&#xD;&#xA;    MTLVertexDescriptor* vs = descriptor.vertexDescriptor;&#xD;&#xA;    vs.attributes[0].format = MTLVertexFormatFloat4;&#xD;&#xA;    vs.attributes[0].offset = 0;&#xD;&#xA;    vs.attributes[0].bufferIndex = 0;&#xD;&#xA;    &#xD;&#xA;    vs.layouts[0].stride        = sizeof(float) * 4;&#xD;&#xA;    vs.layouts[0].stepFunction  = MTLVertexStepFunctionPerVertex;&#xD;&#xA;    vs.layouts[0].stepRate      = 1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Shader:&#xD;&#xA;```&#xD;&#xA;struct Out &#xD;&#xA;{&#xD;&#xA;    float4 pos [[position]];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vertex Out vertexShader(&#xD;&#xA;    const device float4* vertices [[buffer(0)]],&#xD;&#xA;    unsigned int idx [[vertex_id]]&#xD;&#xA;) {&#xD;&#xA;    Out out;&#xD;&#xA;    out.pos = vertices[idx];&#xD;&#xA;    return out;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;fragment float4 fragmentShader(Out in [[stage_in]])&#xD;&#xA;{&#xD;&#xA;    // TODO: Write fragment shader&#xD;&#xA;    return float4(1, 0, 0, 1);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't understand why my application fails, when using 3D vectors instead of 4D ones. Any ideas?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32910" PostHistoryTypeId="2" PostId="10914" RevisionGUID="5dac86d3-d7c1-48c4-b205-4b0597cbcdc2" CreationDate="2021-05-26T17:17:52.070" UserId="506" Text="`float3` in Metal Shading Language has the same size/alignment as `float4`, i.e. 16 bytes. I think your original code would have worked using `packed_float3` (12 bytes) in the vertex shader." ContentLicense="CC BY-SA 4.0" />
  <row Id="32911" PostHistoryTypeId="2" PostId="10915" RevisionGUID="b5d37d0f-7430-4f1c-be1c-5c473c5820f3" CreationDate="2021-05-26T20:20:22.027" UserId="16509" Text="I was able to solve the **#include** issue by linking both the **shaderc/glslc** and **shaderc/shaderc_util** libraries and using file_includer.h and file_finder.h as suggested in a comment by ACskyline.&#xD;&#xA;```&#xD;&#xA;  #include &lt;shaderc/glslc/src/file_includer.h&gt;&#xD;&#xA;  #include &lt;shaderc/libshaderc_util/include/libshaderc_util/file_finder.h&gt;&#xD;&#xA;&#xD;&#xA;  // [...]&#xD;&#xA;  &#xD;&#xA;  // somewhere before using the compiler&#xD;&#xA;  shaderc_util::FileFinder fileFinder;&#xD;&#xA;  options.SetIncluder(std::make_unique&lt;glslc::FileIncluder&gt;(&amp;fileFinder));&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="32913" PostHistoryTypeId="2" PostId="10916" RevisionGUID="8c7bb7c1-b4e9-4f31-bf5c-a2f1801e8961" CreationDate="2021-05-27T15:30:03.520" UserId="11058" Text="I have done some tests in OpenGL with multisampling, by specifying a multisample buffer as the default framebuffer. I used forward shading for rendering. From what I've observed the more primitives I have on the screen the higher the performance hit by multisampling. Is this because that the built-in MSAA does multisampling in the fragment shader for each primitive we specify, even if its fragments are discarded because of depth testing? In order to fix this problem we could use deferred shading, but then we would have do multisampling ourselves. Does this mean then that in practice for scenes with overlapping objects the built-in MSAA is pretty much never going to be used?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32914" PostHistoryTypeId="1" PostId="10916" RevisionGUID="8c7bb7c1-b4e9-4f31-bf5c-a2f1801e8961" CreationDate="2021-05-27T15:30:03.520" UserId="11058" Text="MSAA performance with forward shading" ContentLicense="CC BY-SA 4.0" />
  <row Id="32915" PostHistoryTypeId="3" PostId="10916" RevisionGUID="8c7bb7c1-b4e9-4f31-bf5c-a2f1801e8961" CreationDate="2021-05-27T15:30:03.520" UserId="11058" Text="|sampling|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32916" PostHistoryTypeId="5" PostId="10916" RevisionGUID="ad264779-f208-4102-a6a2-663a6c705bfa" CreationDate="2021-05-27T15:35:08.870" UserId="11058" Comment="added 3 characters in body" Text="I have done some tests in OpenGL with multisampling, by specifying a multisample buffer as the default framebuffer. I used forward shading for rendering. From what I've observed the more primitives I have on the screen the higher the performance hit by multisampling. Is this because that the built-in MSAA does multisampling in the fragment shader for each primitive we specify, even if its fragments are discarded because of depth testing? In order to fix this problem we could use deferred shading, but then we would have do multisampling ourselves.&#xD;&#xA;&#xD;&#xA;Does this mean then that in practice for scenes with overlapping objects the built-in MSAA is pretty much never going to be used?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32917" PostHistoryTypeId="2" PostId="10917" RevisionGUID="c11d0b9d-ea60-4e0e-8905-12f714af978e" CreationDate="2021-05-27T15:56:20.667" UserId="2654" Text="There is nothing surprising about this.&#xD;&#xA;&#xD;&#xA;The biggest cost of multisampling is that you're rendering to larger buffers and therefore require more bandwidth to cover the same pixel-space area. This is especially true for doing depth tests, as the fragment's depth has to be computed and compared per-sample, not per-fragment. The more primitives you send, the more depth tests you're going to have, and therefore the more bandwidth you're going to use.&#xD;&#xA;&#xD;&#xA;So if your shaders aren't doing much, your performance is going to be governed by framebuffer bandwidth.&#xD;&#xA;&#xD;&#xA;Early depth tests are generally orthogonal to multisampling. But since multisampling typically executes the fragment shader at a lower frequency than the depth test, all of the depth samples that represent a fragment have to fail in order to cull the fragment itself. So I could imagine that some implementations turn off early tests for multisampling, but I rather doubt that this is the case." ContentLicense="CC BY-SA 4.0" />
  <row Id="32918" PostHistoryTypeId="5" PostId="10916" RevisionGUID="e7cbef86-e111-4380-9ba1-c1996f6dfbc3" CreationDate="2021-05-27T15:59:48.397" UserId="11058" Comment="deleted 5 characters in body" Text="I have done some tests in OpenGL with multisampling, by specifying a multisample buffer as the default framebuffer. I used forward shading for rendering. From what I've observed the more primitives I have on the screen the higher the performance hit by multisampling. Is this because the built-in MSAA does multisampling in the fragment shader for each primitive we specify, even if its fragments are discarded because of depth testing? In order to fix this problem we could use deferred shading, but then we would have do multisampling ourselves.&#xD;&#xA;&#xD;&#xA;Does this mean then that in practice for scenes with overlapping objects the built-in MSAA is pretty much never going to be used?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32919" PostHistoryTypeId="5" PostId="10916" RevisionGUID="510411a4-2a37-49dd-b723-f5db08ad5f99" CreationDate="2021-05-27T16:39:32.433" UserId="11058" Comment="added 14 characters in body" Text="I have done some tests in OpenGL with multisampling, by specifying a multisample buffer as the default framebuffer. I used forward shading for rendering. From what I've observed the more primitives I have on the screen the higher the performance hit by multisampling. Is this because the built-in MSAA does multisampling in the fragment shader for each primitive we specify, even if its fragments are discarded because of depth testing? In order to fix this problem we could use deferred shading, &lt;s&gt;but then we would have do multisampling ourselves.&lt;/s&gt;&#xD;&#xA;&#xD;&#xA;&lt;s&gt;Does this mean then that in practice for scenes with overlapping objects the built-in MSAA is pretty much never going to be used?&lt;/s&gt;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32920" PostHistoryTypeId="50" PostId="9614" RevisionGUID="7025d296-8515-4922-80d3-288d7eddf576" CreationDate="2021-05-27T22:02:45.207" UserId="-1" />
  <row Id="32921" PostHistoryTypeId="2" PostId="10918" RevisionGUID="d6e33ba4-b9e6-45ae-8310-9a0529f4a6b1" CreationDate="2021-05-28T02:26:00.327" UserId="16523" Text="I am writing a raycasting engine. At this point, I have added sprites, and I am using a z-buffer, with one stored length to a wall for the x coordinate of each ray. Below is an image of a sprite which is fully visible.&#xD;&#xA;&#xD;&#xA;[![Image 1][1]][1]&#xD;&#xA;&#xD;&#xA;Z-buffering works fine when my vertical height is zero, as seen below.&#xD;&#xA;&#xD;&#xA;[![Image 2][2]][2]&#xD;&#xA;&#xD;&#xA;However, when I change my vertical height and stand on top of a wall, as seen below, my sprite becomes only half-visible. I understand why this is true; the Z-buffer is only accounting for the first level of vertical height, and so it seems like the sprite should be partially obscured, even when it is not.  However, there also cases when most of a sprite is obscured except for the top. In that case, I could not simply have a z-buffer for each level of vertical height. Does anyone know of an algorithm that can determine the visible area of a billboard sprite in a raycasting environment?&#xD;&#xA;&#xD;&#xA;[![Image 3][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6H5kA.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZASqq.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sYGg5.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="32922" PostHistoryTypeId="1" PostId="10918" RevisionGUID="d6e33ba4-b9e6-45ae-8310-9a0529f4a6b1" CreationDate="2021-05-28T02:26:00.327" UserId="16523" Text="A solution to sprite visibility in a raycasting engine with variable wall heights?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32923" PostHistoryTypeId="3" PostId="10918" RevisionGUID="d6e33ba4-b9e6-45ae-8310-9a0529f4a6b1" CreationDate="2021-05-28T02:26:00.327" UserId="16523" Text="|depth-map|z-buffer|occlusion|scanline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32925" PostHistoryTypeId="50" PostId="9116" RevisionGUID="ea3f88f8-f859-4ac1-9c22-9be21b71d80a" CreationDate="2021-05-28T10:01:35.150" UserId="-1" />
  <row Id="32926" PostHistoryTypeId="2" PostId="10919" RevisionGUID="b6c1091d-72ab-4766-9197-8b7e8515f529" CreationDate="2021-05-28T16:30:37.947" UserId="16525" Text="I'm learning OpenGL and I'm trying to understand things properly. If my understanding is incorrect at **any** point, please correct me.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# Introduction&#xD;&#xA;&#xD;&#xA;So let's say we have a triangle. This triangle has its vertices. Let's say these vertices only have the position set - no color, not anything else. These vertices are passed to the shaders using a buffer - let's call it VB (VBO in tutorials).&#xD;&#xA;&#xD;&#xA;The shaders are the following:&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;```cpp&#xD;&#xA;#version 330 core&#xD;&#xA;layout (location = 0) in vec3 aPos;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;```cpp&#xD;&#xA;#version 330 core&#xD;&#xA;out vec4 FragColor;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The VB is an non-formatted array of data. For example, if we wanted to pass 3 one-byte values to this buffer (0, 255, 16), the data would look like this:&#xD;&#xA;&#xD;&#xA;`00FFF0`&#xD;&#xA;&#xD;&#xA;However, the shaders do not know how to read the data, so we need to &quot;instruct&quot; them by telling them what is what. To do this we use Vertex Array Objects. Let's call our Vertex Array Object VA.&#xD;&#xA;&#xD;&#xA;To pass data to the buffer, `glBufferData` is used. When calling the function like this:&#xD;&#xA;```c++&#xD;&#xA;glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;We inform OpenGL that we want to buffer `sizeof(vertices)` elements from array `vertices` to the buffer currently bound to `GL_ARRAY_BUFFER` for static drawing.&#xD;&#xA;&#xD;&#xA;Then, we inform VA how to use the data like this:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;glEnableVertexAttribArray(0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This way we tell VA to get 3 floating point values from active buffer at the offset 0 while not normalizing coordinates and set this data to the vertex attribute at location 0.&#xD;&#xA;&#xD;&#xA;This way, the shaders finally get all the data they need to work and our triangle is drawn.&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;However, what if we wanted to change one vertex **after** we've already passed the data to the buffer?&#xD;&#xA;&#xD;&#xA;In my understanding, we'd need to call `glBufferData` the same way as before. But how does it influence the data that was originally in the buffer? Does it overwrite it?&#xD;&#xA;&#xD;&#xA;If it does overwrite it, how do we pass another data, let's say colors, without overwriting the positions?&#xD;&#xA;&#xD;&#xA;If it doesn't, how does VA know the data it's &quot;pointing&quot; to is no longer up to date?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32927" PostHistoryTypeId="1" PostId="10919" RevisionGUID="b6c1091d-72ab-4766-9197-8b7e8515f529" CreationDate="2021-05-28T16:30:37.947" UserId="16525" Text="How does a Vertex Buffer manage memory?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32928" PostHistoryTypeId="3" PostId="10919" RevisionGUID="b6c1091d-72ab-4766-9197-8b7e8515f529" CreationDate="2021-05-28T16:30:37.947" UserId="16525" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32929" PostHistoryTypeId="2" PostId="10920" RevisionGUID="4165d696-7219-4761-aad5-ccf7177fbce7" CreationDate="2021-05-28T17:10:17.843" UserId="2485" Text="### The setup&#xD;&#xA;&#xD;&#xA;I have a working bloom shader implemented which creates a fbo with two textures attached to it.&#xD;&#xA;&#xD;&#xA;1. The first texture holds the entire scene&#xD;&#xA;2. The other only displays objects which are supposed to be bloomed in a postprocessing (ping pong) step&#xD;&#xA;&#xD;&#xA;At the and the end both textures are added. &#xD;&#xA;&#xD;&#xA;Here is the code which creates the according fbo:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;    void CreateHdrBloomFBO(GLuint &amp;hdr_fbo, GLuint *color_buffers, GLuint *pingpong_fbo, GLuint *pingpong_color_buffers, GLuint &amp;rbo_depth, float width, float height)&#xD;&#xA;    {&#xD;&#xA;        glGenFramebuffers(1, &amp;hdr_fbo);&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);&#xD;&#xA;        glGenTextures(2, color_buffers);&#xD;&#xA;&#xD;&#xA;        for (unsigned int i = 0; i &lt; 2; i++)&#xD;&#xA;        {&#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, color_buffers[i]);&#xD;&#xA;            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, color_buffers[i], 0);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        glGenRenderbuffers(1, &amp;rbo_depth);&#xD;&#xA;        glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth);&#xD;&#xA;        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);&#xD;&#xA;        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_depth);&#xD;&#xA;        GLuint attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};&#xD;&#xA;        glDrawBuffers(2, attachments);&#xD;&#xA;&#xD;&#xA;        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)&#xD;&#xA;            std::cout &lt;&lt; &quot;CORE::CREATE_FRAMEBUFFER_FAIL - Failed creating HDR/BLOOM buffers.&quot; &lt;&lt; std::endl;&#xD;&#xA;        glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;        glGenFramebuffers(2, pingpong_fbo);&#xD;&#xA;        glGenTextures(2, pingpong_color_buffers);&#xD;&#xA;        for (unsigned int i = 0; i &lt; 2; i++)&#xD;&#xA;        {&#xD;&#xA;            glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[i]);&#xD;&#xA;            glBindTexture(GL_TEXTURE_2D, pingpong_color_buffers[i]);&#xD;&#xA;            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpong_color_buffers[i], 0);&#xD;&#xA;&#xD;&#xA;            if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)&#xD;&#xA;                std::cout &lt;&lt; &quot;CORE::CREATE_FRAMEBUFFER_FAIL - Failed creating HDR/BLOOM-pingpong buffers.&quot; &lt;&lt; std::endl;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So my renderloop looks something like this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// 1. Bind fbo&#xD;&#xA;// 2. Render scene &#xD;&#xA;// 3. Blur cube and earth fragments with two-pass Gaussian Blur&#xD;&#xA;bool horizontal = true, first_iteration = true;&#xD;&#xA;unsigned int amount = 10;&#xD;&#xA;blur_shader.use();&#xD;&#xA;for (unsigned int i = 0; i &lt; amount; i++)&#xD;&#xA;{&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[horizontal]);&#xD;&#xA;    blur_shader.set_int(&quot;horizontal&quot;, horizontal);&#xD;&#xA;    // Note on the first iteration I take the second texture from above, which holds the objects which are supposed to get bloomed.&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, first_iteration ? color_buffers[1] : pingpong_color_buffers[!horizontal]);&#xD;&#xA;    core::RenderQuad(&amp;quad_geometry);&#xD;&#xA;    horizontal = !horizontal;&#xD;&#xA;    if (first_iteration)&#xD;&#xA;        first_iteration = false;&#xD;&#xA;}&#xD;&#xA;glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;&#xD;&#xA;// 4. Combine normal and bloom textures&#xD;&#xA;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;bloom_final_shader.use();&#xD;&#xA;glActiveTexture(GL_TEXTURE0);&#xD;&#xA;glBindTexture(GL_TEXTURE_2D, color_buffers[0]);&#xD;&#xA;glActiveTexture(GL_TEXTURE1);&#xD;&#xA;glBindTexture(GL_TEXTURE_2D, pingpong_color_buffers[!horizontal]);&#xD;&#xA;bloom_final_shader.set_int(&quot;bloom&quot;, use_bloom);&#xD;&#xA;bloom_final_shader.set_float(&quot;exposure&quot;, exposure);&#xD;&#xA;core::RenderQuad(&amp;quad_geometry);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is what the output of the scene render looks like. The are the scene and the blooming targets:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the first blooming step the correct image is passed and &quot;ping ponged&quot; afterwards.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The final image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;### The problem&#xD;&#xA;&#xD;&#xA;I want to implement antialiasing on top of the given process. Therfore I create a multisample fbo which also holds two textures:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;void CreateMsaaFBO(GLuint &amp;target_fbo, GLuint *target_fbo_textures, GLuint &amp;rbo_depth_stencil, float width, float height)&#xD;&#xA;{&#xD;&#xA;    glGenFramebuffers(1, &amp;target_fbo);&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, target_fbo);&#xD;&#xA;    glGenTextures(2, target_fbo_textures);&#xD;&#xA;    for (unsigned int i = 0; i &lt; 2; i++)&#xD;&#xA;    {&#xD;&#xA;        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, target_fbo_textures[i]);&#xD;&#xA;        glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, width, height, GL_TRUE);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D_MULTISAMPLE,target_fbo_textures[i], 0);&#xD;&#xA;    }&#xD;&#xA;    glGenRenderbuffers(1, &amp;rbo_depth_stencil);&#xD;&#xA;    glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth_stencil);&#xD;&#xA;    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);&#xD;&#xA;    glBindRenderbuffer(GL_RENDERBUFFER, 0);&#xD;&#xA;    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,rbo_depth_stencil);&#xD;&#xA;    GLuint attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};&#xD;&#xA;    glDrawBuffers(2, attachments);&#xD;&#xA;    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)&#xD;&#xA;        std::cout &lt;&lt; &quot;CORE::CREATE_FRAMEBUFFER_FAIL - Failed creating MSAA buffer.&quot; &lt;&lt; std::endl;&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER_COMPLETE, 0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So my Plan is to draw the scene as above this time using my msaa_fbo and use `glBlitFramebuffer` to copy antialiased textures to my original fbo:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// 1. Bind msaa_fbo&#xD;&#xA;// 2. Render scene &#xD;&#xA;    glBindFramebuffer(GL_READ_FRAMEBUFFER, msaa_fbo);&#xD;&#xA;    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdr_fbo);&#xD;&#xA;    glBlitFramebuffer(0, 0, viewport_width, viewport_height, 0, 0, viewport_width, viewport_height,GL_COLOR_BUFFER_BIT, GL_NEAREST);&#xD;&#xA;    glBindFramebuffer(GL_FRAMEBUFFER, 0);&#xD;&#xA;// 3. blur bright fragments with two-pass Gaussian Blur as above&#xD;&#xA;// ...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;It seems that only the first texture gets copied to the `hdr_fbo` and therfore the entire image is bloomed.&#xD;&#xA;&#xD;&#xA;The output of the `msaa_fbo` looks correct:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This is the `glBindFramebuffer` in renderdoc which seems to target only one texture (the scene):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;That is why the input of the pingpong loop is the entire scene:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;As far as I get it should copy both textures (scene + bloom) to my target `hdr_fbo` buffer. Why doesn't it? I started learning those concept, so I am not ruling out that I am missing something fundamental.&#xD;&#xA;&#xD;&#xA;Also note that a lot of the code is taken from [learnopengl.com](https://learnopengl.com/).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KScSk.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/h9ic3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/FS3nH.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/p1cwW.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/P9MK1.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/DjS5T.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32930" PostHistoryTypeId="1" PostId="10920" RevisionGUID="4165d696-7219-4761-aad5-ccf7177fbce7" CreationDate="2021-05-28T17:10:17.843" UserId="2485" Text="glBindFramebuffer does not copy all textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="32931" PostHistoryTypeId="3" PostId="10920" RevisionGUID="4165d696-7219-4761-aad5-ccf7177fbce7" CreationDate="2021-05-28T17:10:17.843" UserId="2485" Text="|opengl|antialiasing|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32932" PostHistoryTypeId="2" PostId="10921" RevisionGUID="5c470b04-8420-4e87-b3e3-5ce1e27df01f" CreationDate="2021-05-28T20:09:14.603" UserId="10370" Text="as the question suggests I have to identify all the faces that are visible from the camera's view and do some processing with them. I have a single mesh.&#xD;&#xA;&#xD;&#xA;I am thinking of giving individual faces a different colour and do a blind render. This will enable me to read the FBO. Then I have to traverse all the pixel and find the unique faces by their colour.&#xD;&#xA;&#xD;&#xA;Are there any faster way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32933" PostHistoryTypeId="1" PostId="10921" RevisionGUID="5c470b04-8420-4e87-b3e3-5ce1e27df01f" CreationDate="2021-05-28T20:09:14.603" UserId="10370" Text="List all faces of a mesh visible from the view of the camera Opengl" ContentLicense="CC BY-SA 4.0" />
  <row Id="32934" PostHistoryTypeId="3" PostId="10921" RevisionGUID="5c470b04-8420-4e87-b3e3-5ce1e27df01f" CreationDate="2021-05-28T20:09:14.603" UserId="10370" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32935" PostHistoryTypeId="2" PostId="10922" RevisionGUID="d18af62e-59a8-405f-94f0-1b38070935f4" CreationDate="2021-05-28T20:24:54.800" UserId="8776" Text="Congratulations for having progressed so far.&#xD;&#xA;&#xD;&#xA;## Context, first analysis&#xD;&#xA;&#xD;&#xA;Your explanation:&#xD;&#xA;&#xD;&#xA;&gt; I am using a z-buffer, with one stored length to a wall for the x coordinate of each ray.&#xD;&#xA;&#xD;&#xA;Means the z-buffer is currently one-dimension.&#xD;&#xA;&#xD;&#xA;One dimension is enough in the first case (your first two images) but not in the second case. To see why, imagine that the red tomato sprite was closer to the player, such that the left half of it would be partially obscured by the first wall (bottom left). Since the top of that wall is projected to a diagonal line, it means that the property &quot;is pixel P of the sprite obscured?&quot; does not only depend on X but also on Y.&#xD;&#xA;&#xD;&#xA;So, in the exact setup you have, a 1D Z-buffer is definitely not capable of performing the clipping you want.&#xD;&#xA;&#xD;&#xA;## Options&#xD;&#xA;&#xD;&#xA;From that on, here are a few options:&#xD;&#xA;&#xD;&#xA;* switch to a 2D z-buffer (slower)&#xD;&#xA;* switch to painter's algorithm (slower)&#xD;&#xA;* switch to a 2D-based occlusion algorithm&#xD;&#xA;* study how Doom did it&#xD;&#xA;&#xD;&#xA;Your geometry seems similar to Doom. It is probably a very good investment for you to study how the Doom rendering engine works. It clips sprites (called &quot;things&quot;) using a 1D criterion, then refines. One area has only one floor height and one ceiling height. This is very important and it looks like your geometry is similar.&#xD;&#xA;&#xD;&#xA;## Solution&#xD;&#xA;&#xD;&#xA;The solution, to summarize, is to keep not only a 1D z-buffer, but actually a structure keeping for each sector (in doom parlance) the lines that make the limit and their parameters (like the a and b in y=ax+b).&#xD;&#xA;Then, when you want to draw the sprite, clip X with 1D criterion but **depending on the sector the sprite is in**, and then limit the Y range of pixels drawn based on the y=ax+b of the sector just in front of it.&#xD;&#xA;&#xD;&#xA;I don't know what data structure you currently have in your program. If this seems totally unreachable, then you need to rethink the data structure you keep while drawing.&#xD;&#xA;&#xD;&#xA;If you haven't yet, you should read (sorry if you did already) https://doomwiki.org/wiki/Doom_rendering_engine#Rendering and the pages behind the links there, perhaps run their code in slow motion or see a video where someone shows/explains how it works.  This one lacks explanations but might help your intuition: https://www.youtube.com/watch?v=gfM6NpxmVGg .&#xD;&#xA;&#xD;&#xA;Hope this helps.  Keep up the good work!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32939" PostHistoryTypeId="2" PostId="10924" RevisionGUID="27f20d83-f893-43f1-a905-baab223f6d64" CreationDate="2021-05-29T01:13:21.693" UserId="16527" Text="One of the first things I learned about computer graphics lighting (and light in general) is that when a ray of light hits a surface, the surface absorbs certain colors and the light retains the rest.  If this is true, then why do most computer graphics examples and tutorials I've seen use two different colors for ambient and diffuse color for a material?  If both ambient and diffuse light waves come from the same light source, with the same color, then shouldn't the material reflect the same color for both types of light?  Note that I'm fairly new to computer graphics, so I've barely scratched the surface of complex lighting and etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="32940" PostHistoryTypeId="1" PostId="10924" RevisionGUID="27f20d83-f893-43f1-a905-baab223f6d64" CreationDate="2021-05-29T01:13:21.693" UserId="16527" Text="Why do materials have both an ambient color and a diffuse color?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32941" PostHistoryTypeId="3" PostId="10924" RevisionGUID="27f20d83-f893-43f1-a905-baab223f6d64" CreationDate="2021-05-29T01:13:21.693" UserId="16527" Text="|3d|lighting|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32942" PostHistoryTypeId="2" PostId="10925" RevisionGUID="142c4694-401d-44bf-83c0-698bc8341535" CreationDate="2021-05-29T06:15:37.840" UserId="9749" Text="Rasterizers will probably handle it as a post processing effect. While doing ray tracing/marching it's possible to bend the rays while incrementing at each step." ContentLicense="CC BY-SA 4.0" />
  <row Id="32943" PostHistoryTypeId="50" PostId="9781" RevisionGUID="e41c4248-7527-4145-bc75-941f53186fa7" CreationDate="2021-05-29T18:01:05.133" UserId="-1" />
  <row Id="32944" PostHistoryTypeId="50" PostId="10177" RevisionGUID="0b7573e3-66e1-477c-92e6-6f45e92752fe" CreationDate="2021-05-30T03:02:25.130" UserId="-1" />
  <row Id="32945" PostHistoryTypeId="5" PostId="10911" RevisionGUID="109c9dcc-d59f-43c1-a2d0-e28871f0860e" CreationDate="2021-05-30T15:26:05.090" UserId="2654" Comment="added 3 characters in body" Text="The two are different because they do different things. Clipping and culling aren't the same thing at all. If an edge crosses a clip plane, the primitive has to be clipped to be within that plane. This means generating new primitives from the old one.&#xD;&#xA;&#xD;&#xA;If all vertices of a primitive are outside of a cull plane, then the entire primitive is culled.&#xD;&#xA;&#xD;&#xA;You use the cull planes when you want the VS to be able to cull out primitives based on some calculation. You use clip primitives when you want primitive rendering to be bounded to some non-clip-space region (though line and point width can violate those borders)." ContentLicense="CC BY-SA 4.0" />
  <row Id="32946" PostHistoryTypeId="50" PostId="10852" RevisionGUID="261efa87-e9d8-41e1-83c0-42430bf65018" CreationDate="2021-05-30T18:02:50.230" UserId="-1" />
  <row Id="32947" PostHistoryTypeId="50" PostId="9791" RevisionGUID="b232f9f2-5c5b-4555-93f1-9afdf51fde6e" CreationDate="2021-05-30T22:08:05.813" UserId="-1" />
  <row Id="32954" PostHistoryTypeId="2" PostId="10928" RevisionGUID="27a8ef37-15aa-49f9-9a53-ab477e605e04" CreationDate="2021-05-31T11:30:58.457" UserId="7952" Text="The data sent to the GPU *is* formatted. The GPU has to be programmed to know what that format is. If you want to add more data to the vertex attributes then the entire pipeline has to be reprogrammed, this includes overwriting the vertex attributes, changing the shaders, and reprogramming the GPU to know the data sizes.&#xD;&#xA;&#xD;&#xA;If you change just the data, the GPU will have no clue, and will happily process garbage.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="32955" PostHistoryTypeId="5" PostId="10928" RevisionGUID="29ef5a23-0c89-4db8-984e-f82a52812684" CreationDate="2021-05-31T11:50:58.660" UserId="7952" Comment="Added a bit about sbo's" Text="The data sent to the GPU *is* formatted. The GPU has to be programmed to know what that format is. If you want to add more data to the vertex attributes then the entire pipeline has to be reprogrammed, this includes overwriting the vertex attributes, changing the shaders, and reprogramming the GPU to know the data sizes.&#xD;&#xA;&#xD;&#xA;If you change just the data, the GPU will have no clue, and will happily process garbage. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The are of course other ways to get data to a shader such as the so called &quot;shader buffer object&quot;. But that seems to be outside the scope of your question." ContentLicense="CC BY-SA 4.0" />
  <row Id="32956" PostHistoryTypeId="4" PostId="10920" RevisionGUID="d9b0200b-9cb5-4868-8387-943e3d439b91" CreationDate="2021-05-31T16:29:39.000" UserId="2485" Comment="Correct title" Text="glBlitFramebuffer does not copy all textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="32957" PostHistoryTypeId="33" PostId="10920" RevisionGUID="da472eca-fe3d-4f14-ba30-0055f12eac4e" CreationDate="2021-05-31T16:32:14.740" UserId="2485" Comment="69" />
  <row Id="32958" PostHistoryTypeId="2" PostId="10929" RevisionGUID="52f7251b-ce9c-4cf9-8723-9655f814cde2" CreationDate="2021-05-31T19:52:33.623" UserId="16549" Text="I implemented catmul clark based on [this][1] Wikipedia article.&#xD;&#xA;And it seems to work fine for meshes where the edge point count is equal to the face point count, but not for planes where the corners have 2 edge points and 1 face point.&#xD;&#xA;&#xD;&#xA;The article states the following for this formula&#xD;&#xA;&#xD;&#xA;$$ \frac{F + 2R + (n-3)P}{n} $$&#xD;&#xA;&#xD;&#xA;&gt; (Note that from the perspective of a vertex P, the number of edges&#xD;&#xA;&gt; neighboring P is also the number of adjacent faces, hence n)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And that seems to be true for cube-like shapes, but not for planes.&#xD;&#xA;&#xD;&#xA;[![point count][2]][2]&#xD;&#xA;&#xD;&#xA;Does this implementation not work for planes, or am I doing something wrong?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface&#xD;&#xA;  [2]: https://i.stack.imgur.com/XUIAu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32959" PostHistoryTypeId="1" PostId="10929" RevisionGUID="52f7251b-ce9c-4cf9-8723-9655f814cde2" CreationDate="2021-05-31T19:52:33.623" UserId="16549" Text="Catmull–Clark issue with plane corners" ContentLicense="CC BY-SA 4.0" />
  <row Id="32960" PostHistoryTypeId="3" PostId="10929" RevisionGUID="52f7251b-ce9c-4cf9-8723-9655f814cde2" CreationDate="2021-05-31T19:52:33.623" UserId="16549" Text="|mesh|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32961" PostHistoryTypeId="2" PostId="10930" RevisionGUID="aca6469d-5e84-4024-b9d6-1b943246f98d" CreationDate="2021-06-01T08:29:19.517" UserId="16224" Text="I am currently working on BRDF and their associated probability density functions (PDF). It is really hard for me to find the correct way to compute the PDF of a BRDF. I know some characteristics that the PDF should verify (the integral must be equal to 1...) but I have really no idea about how to do it.&#xD;&#xA;&#xD;&#xA;I am now working on the Oren-Nayar BRDF.&#xD;&#xA;&#xD;&#xA;If someone knows a generic way to do it or has any good resources to propose, I will be happy to read that!&#xD;&#xA;&#xD;&#xA;Thank you very much by advance," ContentLicense="CC BY-SA 4.0" />
  <row Id="32962" PostHistoryTypeId="1" PostId="10930" RevisionGUID="aca6469d-5e84-4024-b9d6-1b943246f98d" CreationDate="2021-06-01T08:29:19.517" UserId="16224" Text="How to find a probability density function for a specified BRDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32963" PostHistoryTypeId="3" PostId="10930" RevisionGUID="aca6469d-5e84-4024-b9d6-1b943246f98d" CreationDate="2021-06-01T08:29:19.517" UserId="16224" Text="|brdf|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32964" PostHistoryTypeId="2" PostId="10931" RevisionGUID="e92184dc-1e9e-4160-bf07-989d83835c0b" CreationDate="2021-06-01T14:26:03.063" UserId="7724" Text="The procedure only works for closed meshes or closed parts of a mesh with boundaries.&#xD;&#xA;&#xD;&#xA;For vertices $V_{i}$ on the boundary of an mesh you have to use the following rules:&#xD;&#xA;&#xD;&#xA;$$V_i = \frac{V_{i-1} + 6 V_{i} + V_{i+1}}{8},$$ where $V_{i-1}$ and $V_{i+1}$ are previous and next vertex on the boundary with respect to $V_i$. New positions on edges of the boundary are inserted as the midpoint between two subsequent vertices. This will nicely smooth the boundaries of the mesh and the generated boundary curve will reproduce a uniform cubic B-spline curve in the limit.&#xD;&#xA;&#xD;&#xA;You can also interpolate the corners of your plane if you do not apply this update step to the corners, but let them remain stationary. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32965" PostHistoryTypeId="5" PostId="10931" RevisionGUID="02a82abf-ccd3-4f32-b7c7-53404825d023" CreationDate="2021-06-01T15:23:05.533" UserId="7724" Comment="added 70 characters in body" Text="The procedure only works for closed meshes or closed parts of a mesh with boundaries.&#xD;&#xA;&#xD;&#xA;For vertices $V_{i}$ on the boundary of an mesh you have to use the following rules:&#xD;&#xA;&#xD;&#xA;$$V_i = \frac{V_{i-1} + 6 V_{i} + V_{i+1}}{8},$$ where $V_{i-1}$ and $V_{i+1}$ are previous and next vertex on the boundary with respect to $V_i$. In your case it would be:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$P = \frac{e_2 + 6 P + e_1}{8}.$$ New positions on edges of the boundary are inserted as the midpoint between two subsequent vertices. This will nicely smooth the boundaries of the mesh and the generated boundary curve will reproduce a uniform cubic B-spline curve in the limit.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can also interpolate the corners of your plane if you do not apply this update step to the corners, but let them remain stationary. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32966" PostHistoryTypeId="2" PostId="10932" RevisionGUID="ec0811e4-58e1-4999-9b73-111c6aadeb27" CreationDate="2021-06-01T17:22:27.823" UserId="6046" Text="I think you misunderstood the use of `glBlitFrameBuffer`. When using this to blit Color Buffers, according to the [docs][1],&#xD;&#xA;&#xD;&#xA;&gt; One thing to keep in mind is this: when using GL_COLOR_BUFFER_BIT​,&#xD;&#xA;&gt; the only colors read will come from the *read color buffer* in the read&#xD;&#xA;&gt; FBO, *specified by glReadBuffer*. The colors written will only go to the&#xD;&#xA;&gt; draw color buffers in the write FBO, specified by glDrawBuffers. If&#xD;&#xA;&gt; multiple draw buffers are specified, then multiple color buffers are&#xD;&#xA;&gt; updated with the same data.&#xD;&#xA;&#xD;&#xA;So simply speaking, when blitting color buffers, you need to specify what `ReadBuffer` by using [glReadBuffer][2] which takes in color attachment number when dealing with FBOs.&#xD;&#xA;&#xD;&#xA;So in short, you can't expect to copy both the attachments or textures with a single blit call. &#xD;&#xA;&#xD;&#xA;Also, can't you just render the anti-aliased scene once, blit this single texture to get a working copy of it usable in shaders and then extract the second texture which is essentially just the environment subtracted from it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Framebuffer#Blitting&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Framebuffer#Read_color_buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="32967" PostHistoryTypeId="2" PostId="10933" RevisionGUID="69328602-e23d-42dc-ad64-5b87e5695641" CreationDate="2021-06-02T00:08:39.070" UserId="3160" Text="Is there any directX FVF(Flexible Vertex Format ) equivalent in OpenGL/Vulkan." ContentLicense="CC BY-SA 4.0" />
  <row Id="32968" PostHistoryTypeId="1" PostId="10933" RevisionGUID="69328602-e23d-42dc-ad64-5b87e5695641" CreationDate="2021-06-02T00:08:39.070" UserId="3160" Text="DirectX FVF(Flexible Vertex Format ) equivalent in OpenGL/Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32969" PostHistoryTypeId="3" PostId="10933" RevisionGUID="69328602-e23d-42dc-ad64-5b87e5695641" CreationDate="2021-06-02T00:08:39.070" UserId="3160" Text="|opengl|vulkan|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32975" PostHistoryTypeId="5" PostId="10930" RevisionGUID="8c86f5e6-cf44-42b2-ac5b-59e9b725c231" CreationDate="2021-06-02T07:35:12.600" UserId="16224" Comment="added 22 characters in body" Text="I am currently working on BRDF and their associated probability density functions (PDF) in order to sample them. It is really hard for me to find the correct way to compute the PDF of a BRDF. I know some characteristics that the PDF should verify (the integral must be equal to 1...) but I have really no idea about how to do it.&#xD;&#xA;&#xD;&#xA;I am now working on the Oren-Nayar BRDF.&#xD;&#xA;&#xD;&#xA;If someone knows a generic way to do it or has any good resources to propose, I will be happy to read that!&#xD;&#xA;&#xD;&#xA;Thank you very much by advance," ContentLicense="CC BY-SA 4.0" />
  <row Id="32976" PostHistoryTypeId="2" PostId="10935" RevisionGUID="52c110aa-b717-49de-a274-4362c9a4bb68" CreationDate="2021-06-02T07:59:32.963" UserId="10654" Text="I'm reading section 5.2 of pbrt 3rd edition and came across the part where they explain the concept of RGB colors.&#xD;&#xA;&#xD;&#xA;&gt; When we display an RGB color on a display, the spectrum that is&#xD;&#xA;&gt; actually displayed is basically determined by **the weighted sum of&#xD;&#xA;&gt; three spectral response curves**, one for each of red, green, and blue,&#xD;&#xA;&gt; as emitted by the display’s phosphors, LED or LCD elements, or plasma&#xD;&#xA;&gt; cells.&#xD;&#xA;&#xD;&#xA;Then there's also this part.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So my understanding so far is this.&#xD;&#xA;&#xD;&#xA;Just like a SPD can be expressed from the weighted sum of spectral matching curves $X(\lambda), Y(\lambda), Z(\lambda)$ as in $S(\lambda) = x_{\lambda}X(\lambda) + y_{\lambda}Y(\lambda) + z_{\lambda}Z(\lambda)$, it can also be expressed with the weighted sum of spectral response curves: $S(\lambda) = rR(\lambda) + gG(\lambda) + bB(\lambda)$&#xD;&#xA;&#xD;&#xA;Is my understanding correct? If it's so, the point I don't get is why the book is using all sorts of mixed, confusing terms like &quot;spectral matching curves&quot;, &quot;spectral power distribution&quot;, and &quot;spectral response curves&quot;. I would really appreciate if someone could clear my confusion. Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lwbT4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32977" PostHistoryTypeId="1" PostId="10935" RevisionGUID="52c110aa-b717-49de-a274-4362c9a4bb68" CreationDate="2021-06-02T07:59:32.963" UserId="10654" Text="Is spectral response curve and spectral power distribution the same thing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32978" PostHistoryTypeId="3" PostId="10935" RevisionGUID="52c110aa-b717-49de-a274-4362c9a4bb68" CreationDate="2021-06-02T07:59:32.963" UserId="10654" Text="|lighting|color|color-science|spectral|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32979" PostHistoryTypeId="2" PostId="10936" RevisionGUID="ba951962-f844-4d09-a52f-16ddb6db90b6" CreationDate="2021-06-02T08:46:41.990" UserId="386" Text="Afaik, in alpha premultiplied color the components stored so:&#xD;&#xA;&#xD;&#xA;    [r * a, g * a, b * a, a]&#xD;&#xA;&#xD;&#xA;So the fully opaque white color is:&#xD;&#xA;&#xD;&#xA;    [1 * 1, 1 * 1, 1 * 1, 1] = [1, 1, 1, 1]&#xD;&#xA;&#xD;&#xA;Fully transparent white color is:&#xD;&#xA;&#xD;&#xA;    [1 * 0, 1 * 0, 1 * 0, 0] = [0, 0, 0, 0]&#xD;&#xA;&#xD;&#xA;Half transparent white color is:&#xD;&#xA;&#xD;&#xA;    [1 * 0.5, 1 * 0.5, 1 * 0.5, 0.5] = [0.5, 0.5, 0.5, 0.5]&#xD;&#xA;&#xD;&#xA;So I can't see a color channel that can be greater than the alpha. I'm asking because I have rendering artifacts and the library I'm using claims that textures stored as `textures as sRGBA premultiplied pixels` though I see values like&#xD;&#xA;&#xD;&#xA;    [0.4784314, 0.4784314, 0.4784314, 0.19607845]" ContentLicense="CC BY-SA 4.0" />
  <row Id="32980" PostHistoryTypeId="1" PostId="10936" RevisionGUID="ba951962-f844-4d09-a52f-16ddb6db90b6" CreationDate="2021-06-02T08:46:41.990" UserId="386" Text="In alpha premultiplied sRGB a color component can't be greater than the alpha, right?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32981" PostHistoryTypeId="3" PostId="10936" RevisionGUID="ba951962-f844-4d09-a52f-16ddb6db90b6" CreationDate="2021-06-02T08:46:41.990" UserId="386" Text="|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32982" PostHistoryTypeId="2" PostId="10937" RevisionGUID="01331f6f-0825-4b9e-884e-9f41a097ba75" CreationDate="2021-06-02T11:23:43.950" UserId="7952" Text="Vulkan uses vertex attributes. Here is an example:&#xD;&#xA;&#xD;&#xA;	const VkVertexInputAttributeDescription vertexAttributes[] = {&#xD;&#xA;		// location, binding, format, offset&#xD;&#xA;		{ 0, 		0,		VK_FORMAT_R32G32B32_SFLOAT,		0 }, // inPosition&#xD;&#xA;		{ 1, 		0,		VK_FORMAT_R32G32B32_SFLOAT,		12 }, // inNormal&#xD;&#xA;		{ 2, 		0,		VK_FORMAT_R32G32B32A32_SFLOAT,		24 }, // inTangent&#xD;&#xA;		{ 3, 		0,		VK_FORMAT_R32G32_SFLOAT,		40 }, // inTexCoord&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;And a description:&#xD;&#xA;&#xD;&#xA;	const VkVertexInputBindingDescription vertexInputBindings[] = { &#xD;&#xA;		// binding, stride, inputRate&#xD;&#xA;		{ 0, 48, VK_VERTEX_INPUT_RATE_VERTEX} &#xD;&#xA;	};" ContentLicense="CC BY-SA 4.0" />
  <row Id="32986" PostHistoryTypeId="5" PostId="10930" RevisionGUID="d6fbb7ff-5b06-4eee-9ddb-1f9b70d4af3f" CreationDate="2021-06-02T15:36:18.003" UserId="48" Comment="clarify about importance sampling" Text="I am currently working on BRDF and their associated probability density functions (PDF) in order to importance-sample them. It is really hard for me to find the correct way to compute the PDF of a BRDF. I know some characteristics that the PDF should verify (the integral must be equal to 1...) but I have really no idea about how to do it.&#xD;&#xA;&#xD;&#xA;I am now working on the Oren-Nayar BRDF.&#xD;&#xA;&#xD;&#xA;If someone knows a generic way to do it or has any good resources to propose, I will be happy to read that!&#xD;&#xA;&#xD;&#xA;Thank you very much by advance," ContentLicense="CC BY-SA 4.0" />
  <row Id="32987" PostHistoryTypeId="4" PostId="10930" RevisionGUID="d6fbb7ff-5b06-4eee-9ddb-1f9b70d4af3f" CreationDate="2021-06-02T15:36:18.003" UserId="48" Comment="clarify about importance sampling" Text="How to find the importance sampling function for a specified BRDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32988" PostHistoryTypeId="2" PostId="10939" RevisionGUID="41505a9b-e842-460b-be84-3c593108222e" CreationDate="2021-06-02T17:01:09.443" UserId="16566" Text="I remember hearing about an algorithm to calculate some property of each pixel of an image which represents how noticeable that pixel is to a human, and so how likely they are to notice if that pixel was modified. I seem to remember the word sounded similar to the word &quot;latency&quot;. Any ideas?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32989" PostHistoryTypeId="1" PostId="10939" RevisionGUID="41505a9b-e842-460b-be84-3c593108222e" CreationDate="2021-06-02T17:01:09.443" UserId="16566" Text="What's the word for &quot;how noticeable a particular part or pixel of an image is to a human&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="32990" PostHistoryTypeId="3" PostId="10939" RevisionGUID="41505a9b-e842-460b-be84-3c593108222e" CreationDate="2021-06-02T17:01:09.443" UserId="16566" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="32991" PostHistoryTypeId="2" PostId="10940" RevisionGUID="537194db-d15e-44c1-8417-145009dc4748" CreationDate="2021-06-02T17:19:15.120" UserId="7724" Text="What you are looking for is [saliency][1] and in the context of computer vision/image processing [saliency maps][2] provide a measure of this on a per-pixel basis. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Salience_(neuroscience)&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Saliency_map" ContentLicense="CC BY-SA 4.0" />
  <row Id="32993" PostHistoryTypeId="5" PostId="10935" RevisionGUID="00f99921-2cb1-4ede-93aa-aff59e532978" CreationDate="2021-06-03T00:23:34.357" UserId="10654" Comment="edited body" Text="I'm reading section 5.2 of pbrt 3rd edition and came across the part where they explain the concept of RGB colors.&#xD;&#xA;&#xD;&#xA;&gt; When we display an RGB color on a display, the spectrum that is&#xD;&#xA;&gt; actually displayed is basically determined by **the weighted sum of&#xD;&#xA;&gt; three spectral response curves**, one for each of red, green, and blue,&#xD;&#xA;&gt; as emitted by the display’s phosphors, LED or LCD elements, or plasma&#xD;&#xA;&gt; cells.&#xD;&#xA;&#xD;&#xA;Then there's also this part.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So my understanding so far is this.&#xD;&#xA;&#xD;&#xA;Just like a SPD can be expressed from the weighted sum of spectral matching curves $X(\lambda), Y(\lambda), Z(\lambda)$ as in $S(\lambda) = x_{\lambda}X(\lambda) + y_{\lambda}Y(\lambda) + z_{\lambda}Z(\lambda)$, it can also be expressed with the weighted sum of spectral response curves: $S(\lambda) = rR(\lambda) + gG(\lambda) + bB(\lambda)$&#xD;&#xA;&#xD;&#xA;Is my understanding correct? If it's so, the point I don't get is why the book is using all sorts of mixed, confusing terms like &quot;spectral matching curves&quot;, &quot;spectral power distribution&quot;, and &quot;spectral response curves&quot;. I would really appreciate if someone could clear my confusion. Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lwbT4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="32996" PostHistoryTypeId="50" PostId="9146" RevisionGUID="5aa3c681-4121-4bcc-a7da-f952dcdb6ac5" CreationDate="2021-06-03T18:05:50.510" UserId="-1" />
  <row Id="32997" PostHistoryTypeId="2" PostId="10941" RevisionGUID="dfaf003f-6f94-41b0-a99c-076a88e6bda0" CreationDate="2021-06-03T18:13:15.853" UserId="13321" Text="PBRT3 is a really good resource and has a lot of brdfs in it. The book and source code are available for free online.&#xD;&#xA;&#xD;&#xA;Regarding oren-nayar, from what I can gather they are just using cosine weighted hemisphere sampling. &#xD;&#xA;&#xD;&#xA;https://pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Sampling_Reflection_Functions&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="32999" PostHistoryTypeId="2" PostId="10942" RevisionGUID="e201cec1-363f-4070-9d02-b2fcb8c89b7f" CreationDate="2021-06-03T23:01:47.253" UserId="6165" Text="as promised, here my answer to your question.&#xD;&#xA;&#xD;&#xA;As I can't follow your code completely (I spend most of my time implementing my code :D ) I can only explain to you what the last step is.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So why do we do interpolation here at all? Well the article already describes well that this piece helps creating a smoother geometry. This works, because we take into account _how much part of the blob is within a grid block_. Looking at the first picture above, take a look into the first block and the second block. The bottom right point has on the left side a scalar value of 2 and on the right side a value of 5. Taking the explanation here into account this must mean that the right block contains more &quot;blob&quot; than the left block which can be seen as the line in the right block is nearly cutting the block in half (see picture below).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now how does this interpolation work? We simply try to calculate a weight which drags the point more up or down, depending on how the scalar values between the two points are. E.g. if you have a value of 0 for a top point and a value of 2 for a bottom point we expect the resulting point on the line between these points to be exactly in the middle. If you now increase the value of the bottom point from 2 to e.g. 10, we expect the resulting point on the line to be much nearer to the bottom point as it &quot;weights&quot; more.&#xD;&#xA;&#xD;&#xA;More mathematically spoken:&#xD;&#xA;Important to note here is that the `exLerp` function is returning the relative value for the `y` value of `Q`. This is always expected to be a value between `0.0` to `1.0`. This property is also guranteed as long as you don't mess up with supplying only pairs of values to your `exLerp` function with one of the values being below `1.0` (our treshold value) and the other value being above `1.0`.&#xD;&#xA;&#xD;&#xA;If you wonder why this is guranteed, just take the formula you implemented (which is correct btw) and supply for x arbitrary values which are greater than 1.0 and for y values which are less than 1.0. The return value will always be between `0.0` and `1.0`. If you violate these properties this doesn't hold anymore because the bottom part of the division becomes smaller than the upper part (thus the value will always be greater than 1).&#xD;&#xA;&#xD;&#xA;So as soon as you have a surface transition, you need to call the exLerp function with the scalar value which is inside of the volume, e.g. in this case the scalar value of the point D (speaking of voxels) and the scalar value of the vertex which is outside of the volume (in this case point B).&#xD;&#xA;&#xD;&#xA;For your algorithm this means you need to find out at the code position when you call `interpolate` whether the return value regarding a specific point is meant to replace the `x` or `y` value of the point you're returning. I guess one variant could be here to check which of the values is `0.5` (if it would be relative position values) because this is always the value you want to replace if you're coming from the non interpolated variant.&#xD;&#xA;&#xD;&#xA;Below you can find some F# code which correctly implements the algorithm. I tried to not optimise that much and made use of more descriptive types so the code better represents what the intention is.&#xD;&#xA;&#xD;&#xA;PS: I suspect that you will have questions as I wrote this answer pretty late (and as soon as it's late one makes more faults and explains less good but I had a promise to keep ;) ).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;``` lang-fsharp&#xD;&#xA;type Position = { x: float; y: float}&#xD;&#xA;    &#xD;&#xA;type Metaball = { radius: float; position: Position }&#xD;&#xA;    &#xD;&#xA;let calculateOccupiedPoints (metaballs: Metaball[]) width height gridDensity =&#xD;&#xA;    Map [|  for x in 0..width - 1 do&#xD;&#xA;                for y in 0.. height - 1 do&#xD;&#xA;                    // The grid density specifies how big a point is, e.g. 1.0 means one block, 0.5 means half a block&#xD;&#xA;                    let xF, yF = float x * gridDensity, float y * gridDensity&#xD;&#xA;                    yield (x, y), metaballs  |&gt; Array.sumBy(fun metaball -&gt; metaball.radius ** 2.0 / ((metaball.position.x - xF) ** 2.0 + (metaball.position.y - yF) ** 2.0))&#xD;&#xA;    |]&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;type Line = { Start: Position; End: Position }&#xD;&#xA;    &#xD;&#xA;type Direction =&#xD;&#xA;    | Top&#xD;&#xA;    | Bottom&#xD;&#xA;    | Left&#xD;&#xA;    | Right&#xD;&#xA;    &#xD;&#xA;// The second half of the table is the frist half of the table but only reversed.&#xD;&#xA;let marchingSquaresTable =&#xD;&#xA;    let firstHalf =&#xD;&#xA;        [|&#xD;&#xA;            (false,false,false,false), [||]&#xD;&#xA;            (false,false,false,true), [| Left, Bottom |]&#xD;&#xA;            (false,false,true,false), [| Bottom , Right|]&#xD;&#xA;            (false,false,true,true), [| Left, Right |]&#xD;&#xA;            (false,true,false,false), [| Top, Right |]&#xD;&#xA;            (false,true,false,true), [| Left, Top; Bottom, Right |]&#xD;&#xA;            (false,true,true,false), [| Top, Bottom |]&#xD;&#xA;            (false,true,true,true), [| Left, Top |] |]&#xD;&#xA;    let secondHalf =&#xD;&#xA;        [|&#xD;&#xA;            (true,false,false,false), [| |]&#xD;&#xA;            (true,false,false,true), [| |]&#xD;&#xA;            (true,false,true,false), [| |]&#xD;&#xA;            (true,false,true,true), [| |]&#xD;&#xA;            (true,true,false,false), [| |]&#xD;&#xA;            (true,true,false,true), [| |]&#xD;&#xA;            (true,true,true,false), [| |]&#xD;&#xA;            (true,true,true,true), [| |]&#xD;&#xA;        |] |&gt; Array.mapi(fun i (_case, _) -&gt; (_case, firstHalf.[7 - i] |&gt; (fun (_, dirs: (Direction * Direction) []) -&gt; dirs)))&#xD;&#xA;    Map.ofArray (firstHalf |&gt; Array.append secondHalf)&#xD;&#xA;    &#xD;&#xA;let calculatePointsViaLinearInterpolation (points: Map&lt;int * int, float&gt;) height width dontInterpolate =&#xD;&#xA;    [|&#xD;&#xA;        for x in 0..(width - 4) do&#xD;&#xA;            for y in 0..(height - 4) do&#xD;&#xA;                let edges =&#xD;&#xA;                    [|&#xD;&#xA;                        0, 0 // A&#xD;&#xA;                        1, 0 // B&#xD;&#xA;                        1, 1 // D&#xD;&#xA;                        0, 1 // C&#xD;&#xA;                    |]&#xD;&#xA;                let xF, yF = float x, float y&#xD;&#xA;                let edgePositions = edges |&gt; Array.map(fun (x0, y0) -&gt; (x0 + x, y0 + y))&#xD;&#xA;                let edgeValues = edgePositions |&gt; Array.map(fun key -&gt; points.[key])&#xD;&#xA;                let [| va; vb; vd; vc |] = edgeValues&#xD;&#xA;                let edgeConfiguration =&#xD;&#xA;                    let [| a; b; d; c |] = edgeValues |&gt; Array.map(fun value -&gt; value &gt;= 1.0)&#xD;&#xA;                    marchingSquaresTable.[(a, b, d, c)]&#xD;&#xA;                let inline mkPoint x y = { x = x; y = y }&#xD;&#xA;                let inline tupleToPoint (x, y) = mkPoint x y&#xD;&#xA;                let getPosForDirection dir =&#xD;&#xA;                    match dir with&#xD;&#xA;                    | Top -&gt; mkPoint 0.5 0.0&#xD;&#xA;                    | Bottom -&gt; mkPoint 0.5 1.0&#xD;&#xA;                    | Left -&gt; mkPoint 0.0 0.5&#xD;&#xA;                    | Right -&gt; mkPoint 1.0 0.5&#xD;&#xA;                let pointValuesForDirection = function&#xD;&#xA;                    | Top -&gt; va, vb&#xD;&#xA;                    | Left -&gt; va, vc&#xD;&#xA;                    | Right -&gt; vb, vd&#xD;&#xA;                    | Bottom -&gt; vc, vd&#xD;&#xA;    &#xD;&#xA;                yield!&#xD;&#xA;                    edgeConfiguration&#xD;&#xA;                    |&gt; Array.map(fun (dirA, dirB) -&gt;&#xD;&#xA;                        let applyInterpolation direction =&#xD;&#xA;                            let (x, y) = pointValuesForDirection direction&#xD;&#xA;                            let pos = getPosForDirection direction&#xD;&#xA;                            let factor =&#xD;&#xA;                                if dontInterpolate then&#xD;&#xA;                                    match direction with&#xD;&#xA;                                    | Left | Right -&gt; pos.y&#xD;&#xA;&#xD;&#xA;                                    | Top | Bottom -&gt; pos.x&#xD;&#xA;                                else&#xD;&#xA;                                    match direction with&#xD;&#xA;                                    | Right | Left -&gt;&#xD;&#xA;                                        0.0 + ((1.0 - x) / (y - x)) * (1.0 - 0.0)&#xD;&#xA;                                    | Top | Bottom -&gt;&#xD;&#xA;                                        0.0 + ((1.0 - x) / (y - x)) * (1.0 - 0.0)&#xD;&#xA;                            match direction with&#xD;&#xA;                            | Top | Bottom -&gt; factor + xF, pos.y + yF&#xD;&#xA;                            | Left | Right -&gt; pos.x + xF, factor + yF&#xD;&#xA;                            |&gt; tupleToPoint&#xD;&#xA;    &#xD;&#xA;                        (applyInterpolation dirA, applyInterpolation dirB)&#xD;&#xA;                    )&#xD;&#xA;    |]&#xD;&#xA;    &#xD;&#xA;let width, height = 64, 64&#xD;&#xA;    &#xD;&#xA;let metaballs =&#xD;&#xA;    [| { radius = 3.4564; position = { x = 7.5; y = 8.0 } }&#xD;&#xA;        { radius = 2.225433; position = { x = 5.5; y = 3.6 } }|]&#xD;&#xA;    &#xD;&#xA;let points = calculateOccupiedPoints metaballs width height (1./4.)&#xD;&#xA;let lines = calculatePointsViaLinearInterpolation points width height false&#xD;&#xA;let lines2 = calculatePointsViaLinearInterpolation points width height true&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I draw the results one get's this (ignore the slight artifacts, the underlying lib Avalonia probably has a bug).&#xD;&#xA;First pic shows the non interpolated variant, second the interpolated variant.&#xD;&#xA;&#xD;&#xA;[![non interpolated][3]][3]&#xD;&#xA;[![interpolated][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/atula.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FtXMR.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/mlQB1.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NN8NS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33001" PostHistoryTypeId="50" PostId="10853" RevisionGUID="e889a6dd-a602-4283-aa83-1cd78894b11f" CreationDate="2021-06-04T06:06:00.577" UserId="-1" />
  <row Id="33002" PostHistoryTypeId="2" PostId="10943" RevisionGUID="27d3986e-9aa6-4bb4-9586-e001ba223d65" CreationDate="2021-06-04T07:02:29.037" UserId="8830" Text="Your edit is correct. In this context 0/0=0. This definition is repeated by David F. Rogers on page 45 of [An Introduction to NURBS with Historical Perspective][1]. Even luckier the page is available on Google Books. If you look at the references for the webpage you linked you'll see he is also cited there.&#xD;&#xA;&#xD;&#xA;As a side note, this recursive B-spline function is known as [De Boor's Algorithm][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.fi/books?id=MaW4XiScJ7cC&amp;lpg=PP1&amp;pg=PA45#v=onepage&amp;q&amp;f=false&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/De_Boor%27s_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="33004" PostHistoryTypeId="50" PostId="10509" RevisionGUID="32b0927d-7157-4480-b306-b0843f22f0d4" CreationDate="2021-06-05T04:02:55.267" UserId="-1" />
  <row Id="33005" PostHistoryTypeId="2" PostId="10944" RevisionGUID="4811df59-22c5-45c4-97e1-e02335447098" CreationDate="2021-06-05T11:06:50.197" UserId="16575" Text="I have published it, in several versions, and it's not difficult to do it. Simplex noise is a lot easier to differentiate because it's a sum of polynomials, rather than a nested polynomial interpolation as in classic Perlin noise.&#xD;&#xA;&#xD;&#xA;GLSL code for 2-D and 3-D simplex noise with derivatives is here:&#xD;&#xA;&#xD;&#xA;https://github.com/ashima/webgl-noise/tree/master/src&#xD;&#xA;&#xD;&#xA;The 3-D version is in the file &quot;noise3Dgrad.glsl&quot;. The 2-D version in &quot;psrdnoise2D.glsl&quot; additionally reimplements Perlin and Neyret's &quot;flow noise&quot; gradient rotations and can be made to tile over integer-sized rectangles. (Well, even-sized integer rectangles. The triangular/heaxagonal simplex grid placed some restrictions on tiling.)&#xD;&#xA;&#xD;&#xA;I am currently working on a tiling version of 3-D simplex noise with rotating gradients as well (and analytical derivatives), and I will submit it for a more formal publication shortly, to hopefully make it more visible to implementers.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33006" PostHistoryTypeId="2" PostId="10945" RevisionGUID="9b4d33df-55f0-4014-a0d8-d3cae1541980" CreationDate="2021-06-05T13:06:53.847" UserId="159" Text="The book distinguishes a spectral power distribution from a spectral response curve because they are not the same, they are *adjoint*.&#xD;&#xA;&#xD;&#xA;The thing about adjoints that makes them a little tricky to wrap your head around is that they typically have the same representation in software, but keeping them distinct is extremely important in computer graphics.&#xD;&#xA;&#xD;&#xA;Another example is that the the adjoint of a *photon* is a *ray*. A photon and a ray have almost the same data: an origin, a direction, and something that represents a spectrum; in the case of a photon, it &quot;carries&quot; spectral power, but in the case of a ray, it &quot;carries&quot; importance, which is a spectral response curve.&#xD;&#xA;&#xD;&#xA;(Note that PBRT's ray implementation doesn't actually &quot;carry&quot; importance, rather this is calculated in the integrators. See `beta` in pbrt-v3's PathIntegrator, for example.)&#xD;&#xA;&#xD;&#xA;In the real world, photons are emitted from light sources, and bounce around the universe until some of them hit your eye or a camera. In modern ray tracing, we reverse this, emitting importance from the camera and bouncing it around the scene until we hit a light source.&#xD;&#xA;&#xD;&#xA;The term &quot;adjoint&quot; [comes from linear algebra][1]. If $A$ is a matrix and $x$ and $y$ are vectors, then $A^\dagger$ is the adjoint of $A$. It has the property that:&#xD;&#xA;&#xD;&#xA;$$ x \cdot (Ay) = (A^\dagger x) \cdot y$$&#xD;&#xA;&#xD;&#xA;Intuitively, the adjoint lets you shift a transformation from one side of a dot product to the other, just like how ray tracing shifts the interaction calculations from the &quot;light&quot; side to the &quot;camera&quot; side.&#xD;&#xA;&#xD;&#xA;This is covered in [Per Christiansen's 2003 paper][2], which is worth a read and a re-read.&#xD;&#xA;&#xD;&#xA;Just as an aside, one more example that occasionally comes up is from differential geometry: the adjoint of a *vector* is a *1-form*. If you implemented this in code, a 1-form has exactly the same representation as a vector: it's three floats. But it means something different.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Adjugate_matrix&#xD;&#xA;  [2]: https://graphics.pixar.com/library/Adjoints/" ContentLicense="CC BY-SA 4.0" />
  <row Id="33007" PostHistoryTypeId="2" PostId="10946" RevisionGUID="48bd41d8-5bac-4f53-ac6b-ac853cc8853c" CreationDate="2021-06-06T05:00:32.473" UserId="13468" Text="Thanks @realvictorprm I figured out how to properly adjust the code:&#xD;&#xA;&#xD;&#xA;    extends Node2D&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Blob:&#xD;&#xA;    	var pos_x&#xD;&#xA;    	var pos_y&#xD;&#xA;    	var radius&#xD;&#xA;    	var velocity&#xD;&#xA;    	func _init(x, y, r, v):&#xD;&#xA;    		pos_x = x&#xD;&#xA;    		pos_y = y&#xD;&#xA;    		radius = r&#xD;&#xA;    		velocity = v&#xD;&#xA;    &#xD;&#xA;    const cell_size = 16&#xD;&#xA;    const blobs_count = 10&#xD;&#xA;    const blob_size = [20, 40]&#xD;&#xA;    var screen_size&#xD;&#xA;    var blobs&#xD;&#xA;    var allowUpdate = true&#xD;&#xA;    #var font = DynamicFont.new()&#xD;&#xA;    &#xD;&#xA;    const drawMap = {&#xD;&#xA;    	0: null,&#xD;&#xA;    	1: [-0.5, 0, 0, -0.5], &#xD;&#xA;    	2: [-0.5, -1, 0, -0.5], &#xD;&#xA;    	3: [-0.5, 0, -0.5, -1], &#xD;&#xA;    	4: [-1, -0.5, -0.5, -1], &#xD;&#xA;    	5: [-1, -0.5, -0.5, 0, -0.5, -1, 0, -0.5],&#xD;&#xA;    	6: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	7: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	8: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	9: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	10: [-1, -0.5, -0.5, -1, -0.5, 0, 0, -0.5],&#xD;&#xA;    	11: [-1, -0.5, -0.5, -1],&#xD;&#xA;    	12: [-0.5, -1, -0.5, 0],&#xD;&#xA;    	13: [-0.5, -1, 0, -0.5],&#xD;&#xA;    	14: [-0.5, 0, 0, -0.5],&#xD;&#xA;    	15: null&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func calcIsoSurface(x1, x2, y1, y2, r):&#xD;&#xA;    	var dx = abs(x1 - x2)&#xD;&#xA;    	var dy = abs(y1 - y2)&#xD;&#xA;    	var sd = dx*dx + dy*dy&#xD;&#xA;    	var res = float(r*r) / float(sd)&#xD;&#xA;    	return res&#xD;&#xA;    &#xD;&#xA;    # Called when the node enters the scene tree for the first time.&#xD;&#xA;    func _ready():&#xD;&#xA;    	#font.font_data = load(&quot;res://font.ttf&quot;)&#xD;&#xA;    	#font.size = 7&#xD;&#xA;    	screen_size = get_viewport().size&#xD;&#xA;    	blobs = Array()&#xD;&#xA;    	var rng = RandomNumberGenerator.new()&#xD;&#xA;    	var r = rng.randi_range(blob_size[0], blob_size[1])&#xD;&#xA;    	var x = rng.randi_range(r, screen_size.x - r)&#xD;&#xA;    	var y = rng.randi_range(r, screen_size.y - r)&#xD;&#xA;    	for n in range(blobs_count):&#xD;&#xA;    		blobs.push_back(&#xD;&#xA;    			Blob.new(&#xD;&#xA;    				x, &#xD;&#xA;    				y, &#xD;&#xA;    				r, &#xD;&#xA;    				Vector2(rng.randf_range(-3, 3), rng.randf_range(-3, 3))&#xD;&#xA;    			)&#xD;&#xA;    		)&#xD;&#xA;    	print(screen_size)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func formDrawIndex(x, y, sum, vertexes):&#xD;&#xA;    	var drawIndex = 0&#xD;&#xA;    	var corners = []&#xD;&#xA;    	if x &gt; 0 &amp;&amp; y &gt; 0:&#xD;&#xA;    		var vertex = vertexes.pop_front()&#xD;&#xA;    		&#xD;&#xA;    		if sum &gt;= 1:&#xD;&#xA;    			drawIndex |= 1&#xD;&#xA;    &#xD;&#xA;    		if vertexes.back() &gt;= 1:&#xD;&#xA;    			drawIndex |= 2&#xD;&#xA;    			&#xD;&#xA;    		if vertex &gt;= 1:&#xD;&#xA;    			drawIndex |= 4  &#xD;&#xA;    &#xD;&#xA;    		if vertexes.front() &gt;= 1:&#xD;&#xA;    			drawIndex |= 8&#xD;&#xA;    		&#xD;&#xA;    		corners.push_back(sum)&#xD;&#xA;    		corners.push_back(vertexes.back())&#xD;&#xA;    		corners.push_back(vertex)&#xD;&#xA;    		corners.push_back(vertexes.front())&#xD;&#xA;    	return  {&quot;draw_index&quot;: drawIndex, &quot;corners&quot;: corners}   &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func exLerp(oneSum, zeroSum):&#xD;&#xA;    	if oneSum == zeroSum:&#xD;&#xA;    		return null&#xD;&#xA;    	return -(1-((1 - oneSum) / (zeroSum - oneSum)))&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func interpolateLines(lines, corners):&#xD;&#xA;    	if lines == null:&#xD;&#xA;    		return lines&#xD;&#xA;    	for i in range(0, lines.size(), 2):&#xD;&#xA;    		var x = lines[i]&#xD;&#xA;    		var y = lines[i+1]&#xD;&#xA;    		&#xD;&#xA;    		if (x == 0 || x == -1) &amp;&amp; (y == 0 || y == -1):&#xD;&#xA;    			continue&#xD;&#xA;    		if (x == 0 || x == -1):&#xD;&#xA;    			lines[i+1] = exLerp(corners[1], corners[0]) if x == 0 else exLerp(corners[2], corners[3])&#xD;&#xA;    		if (y == 0 || y == -1):&#xD;&#xA;    			lines[i] = exLerp(corners[3], corners[0]) if y == 0 else exLerp(corners[2], corners[1])&#xD;&#xA;    	&#xD;&#xA;    	return lines&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func drawLines(x, y, lines):&#xD;&#xA;    	if lines != null &amp;&amp; lines.size() &gt;= 4:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[0]), y + (cell_size*lines[1])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[2]), y + (cell_size*lines[3])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    &#xD;&#xA;    	if lines != null &amp;&amp; lines.size() == 8:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[4]), y + (cell_size*lines[5])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[6]), y + (cell_size*lines[7])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    # Called after update() in the _process()&#xD;&#xA;    func _draw():&#xD;&#xA;    	var vertexes = []&#xD;&#xA;    	for x in range(0, screen_size.x, cell_size):&#xD;&#xA;    		for y in range(0, screen_size.y, cell_size):&#xD;&#xA;    			var sum = 0&#xD;&#xA;    			for blob in blobs:&#xD;&#xA;    				sum += calcIsoSurface(x, blob.pos_x, y, blob.pos_y, blob.radius)&#xD;&#xA;    				#var c = Color.blue&#xD;&#xA;    				#c.a = 0.0001&#xD;&#xA;    				#draw_circle(Vector2(blob.pos_x,blob.pos_y), blob.radius, c)&#xD;&#xA;    			&#xD;&#xA;    			#if sum &gt;= 1:	&#xD;&#xA;    			#	draw_rect(Rect2(x, y, 1, 1), Color.red)&#xD;&#xA;    			#else:&#xD;&#xA;    			#	draw_rect(Rect2(x, y, 1, 1), Color.black)&#xD;&#xA;    		&#xD;&#xA;    			#draw_string(font, Vector2(x, y), &quot;%s&quot; % sum, Color.black)&#xD;&#xA;    &#xD;&#xA;    			var indexies = formDrawIndex(x, y, sum, vertexes)&#xD;&#xA;    			var lines = drawMap[indexies[&quot;draw_index&quot;]]&#xD;&#xA;    			var corners = indexies[&quot;corners&quot;]&#xD;&#xA;    			lines = interpolateLines(lines, corners)&#xD;&#xA;    			&#xD;&#xA;    			drawLines(x, y, lines)&#xD;&#xA;    			vertexes.push_back(sum)&#xD;&#xA;    &#xD;&#xA;    		if x &gt; 0:&#xD;&#xA;    			vertexes.pop_front()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func _input(event):&#xD;&#xA;    	if event is InputEventMouseButton &amp;&amp; event.is_pressed():&#xD;&#xA;    		allowUpdate = !allowUpdate&#xD;&#xA;    		print(allowUpdate)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    # Called every frame. 'delta' is the elapsed time since the previous frame.&#xD;&#xA;    &#xD;&#xA;    func _process(delta):&#xD;&#xA;    	if !allowUpdate:        &#xD;&#xA;    		return      &#xD;&#xA;    	update()&#xD;&#xA;    &#xD;&#xA;    	for blob in blobs:&#xD;&#xA;    		blob.pos_x += blob.velocity.x&#xD;&#xA;    		blob.pos_y += blob.velocity.y&#xD;&#xA;    		if blob.pos_x &gt; screen_size.x || blob.pos_x &lt; 0:&#xD;&#xA;    			blob.velocity.x *= -1&#xD;&#xA;    		if blob.pos_y &gt; screen_size.y || blob.pos_y &lt; 0:&#xD;&#xA;    			blob.velocity.y *= -1&#xD;&#xA;    &#xD;&#xA;First calculation of corners weight has to be float not integer:&#xD;&#xA;    &#xD;&#xA;        func calcIsoSurface(x1, x2, y1, y2, r):&#xD;&#xA;            var dx = abs(x1 - x2)&#xD;&#xA;            var dy = abs(y1 - y2)&#xD;&#xA;            var sd = dx*dx + dy*dy&#xD;&#xA;            var res = float(r*r) / float(sd)&#xD;&#xA;            return res &#xD;&#xA;    &#xD;&#xA;The second lerp has to use inversion (since my coordinate system from right to left and from bottom to top):&#xD;&#xA;&#xD;&#xA;    func exLerp(oneSum, zeroSum):&#xD;&#xA;        if oneSum == zeroSum:&#xD;&#xA;            return null&#xD;&#xA;        return -(1-((1 - oneSum) / (zeroSum - oneSum)))&#xD;&#xA;&#xD;&#xA;And finally interpolation itself:&#xD;&#xA;&#xD;&#xA;    func interpolateLines(lines, corners):&#xD;&#xA;        if lines == null:&#xD;&#xA;            return lines&#xD;&#xA;        for i in range(0, lines.size(), 2):&#xD;&#xA;            var x = lines[i]&#xD;&#xA;            var y = lines[i+1]&#xD;&#xA;    &#xD;&#xA;            if (x == 0 || x == -1) &amp;&amp; (y == 0 || y == -1):&#xD;&#xA;                continue&#xD;&#xA;            if (x == 0 || x == -1):&#xD;&#xA;                lines[i+1] = exLerp(corners[1], corners[0]) if x == 0 else exLerp(corners[2], corners[3])&#xD;&#xA;            if (y == 0 || y == -1):&#xD;&#xA;                lines[i] = exLerp(corners[3], corners[0]) if y == 0 else exLerp(corners[2], corners[1])&#xD;&#xA;    &#xD;&#xA;        return lines&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;But I still not fully understand how it works. Why ratio of metaball radius and distance from centre of metaball to corner of marching square is correctly affect x or y coordinate for interpolation when we apply lerp? I can't fully understand it visually. Another word how `calcIsoSurface` relate to `exLerp` in order to figure out correct `x` or `y` for interpolation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33008" PostHistoryTypeId="5" PostId="10946" RevisionGUID="b5cb140e-fabd-431c-b3b3-fc8b33166436" CreationDate="2021-06-06T05:19:23.523" UserId="13468" Comment="added 178 characters in body" Text="Thanks @realvictorprm I figured out how to properly adjust the code:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;    extends Node2D&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class Blob:&#xD;&#xA;    	var pos_x&#xD;&#xA;    	var pos_y&#xD;&#xA;    	var radius&#xD;&#xA;    	var velocity&#xD;&#xA;    	func _init(x, y, r, v):&#xD;&#xA;    		pos_x = x&#xD;&#xA;    		pos_y = y&#xD;&#xA;    		radius = r&#xD;&#xA;    		velocity = v&#xD;&#xA;    &#xD;&#xA;    const cell_size = 16&#xD;&#xA;    const blobs_count = 10&#xD;&#xA;    const blob_size = [20, 40]&#xD;&#xA;    var screen_size&#xD;&#xA;    var blobs&#xD;&#xA;    var allowUpdate = true&#xD;&#xA;    #var font = DynamicFont.new()&#xD;&#xA;    &#xD;&#xA;    const drawMap = {&#xD;&#xA;    	0: null,&#xD;&#xA;    	1: [-0.5, 0, 0, -0.5], &#xD;&#xA;    	2: [-0.5, -1, 0, -0.5], &#xD;&#xA;    	3: [-0.5, 0, -0.5, -1], &#xD;&#xA;    	4: [-1, -0.5, -0.5, -1], &#xD;&#xA;    	5: [-1, -0.5, -0.5, 0, -0.5, -1, 0, -0.5],&#xD;&#xA;    	6: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	7: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	8: [-1, -0.5, -0.5, 0],&#xD;&#xA;    	9: [-1, -0.5, 0, -0.5],&#xD;&#xA;    	10: [-1, -0.5, -0.5, -1, -0.5, 0, 0, -0.5],&#xD;&#xA;    	11: [-1, -0.5, -0.5, -1],&#xD;&#xA;    	12: [-0.5, -1, -0.5, 0],&#xD;&#xA;    	13: [-0.5, -1, 0, -0.5],&#xD;&#xA;    	14: [-0.5, 0, 0, -0.5],&#xD;&#xA;    	15: null&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func calcIsoSurface(x1, x2, y1, y2, r):&#xD;&#xA;    	var dx = abs(x1 - x2)&#xD;&#xA;    	var dy = abs(y1 - y2)&#xD;&#xA;    	var sd = dx*dx + dy*dy&#xD;&#xA;    	var res = float(r*r) / float(sd)&#xD;&#xA;    	return res&#xD;&#xA;    &#xD;&#xA;    # Called when the node enters the scene tree for the first time.&#xD;&#xA;    func _ready():&#xD;&#xA;    	#font.font_data = load(&quot;res://font.ttf&quot;)&#xD;&#xA;    	#font.size = 7&#xD;&#xA;    	screen_size = get_viewport().size&#xD;&#xA;    	blobs = Array()&#xD;&#xA;    	var rng = RandomNumberGenerator.new()&#xD;&#xA;    	var r = rng.randi_range(blob_size[0], blob_size[1])&#xD;&#xA;    	var x = rng.randi_range(r, screen_size.x - r)&#xD;&#xA;    	var y = rng.randi_range(r, screen_size.y - r)&#xD;&#xA;    	for n in range(blobs_count):&#xD;&#xA;    		blobs.push_back(&#xD;&#xA;    			Blob.new(&#xD;&#xA;    				x, &#xD;&#xA;    				y, &#xD;&#xA;    				r, &#xD;&#xA;    				Vector2(rng.randf_range(-3, 3), rng.randf_range(-3, 3))&#xD;&#xA;    			)&#xD;&#xA;    		)&#xD;&#xA;    	print(screen_size)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func formDrawIndex(x, y, sum, vertexes):&#xD;&#xA;    	var drawIndex = 0&#xD;&#xA;    	var corners = []&#xD;&#xA;    	if x &gt; 0 &amp;&amp; y &gt; 0:&#xD;&#xA;    		var vertex = vertexes.pop_front()&#xD;&#xA;    		&#xD;&#xA;    		if sum &gt;= 1:&#xD;&#xA;    			drawIndex |= 1&#xD;&#xA;    &#xD;&#xA;    		if vertexes.back() &gt;= 1:&#xD;&#xA;    			drawIndex |= 2&#xD;&#xA;    			&#xD;&#xA;    		if vertex &gt;= 1:&#xD;&#xA;    			drawIndex |= 4  &#xD;&#xA;    &#xD;&#xA;    		if vertexes.front() &gt;= 1:&#xD;&#xA;    			drawIndex |= 8&#xD;&#xA;    		&#xD;&#xA;    		corners.push_back(sum)&#xD;&#xA;    		corners.push_back(vertexes.back())&#xD;&#xA;    		corners.push_back(vertex)&#xD;&#xA;    		corners.push_back(vertexes.front())&#xD;&#xA;    	return  {&quot;draw_index&quot;: drawIndex, &quot;corners&quot;: corners}   &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func exLerp(oneSum, zeroSum):&#xD;&#xA;    	if oneSum == zeroSum:&#xD;&#xA;    		return null&#xD;&#xA;    	return -(1-((1 - oneSum) / (zeroSum - oneSum)))&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func interpolateLines(lines, corners):&#xD;&#xA;    	if lines == null:&#xD;&#xA;    		return lines&#xD;&#xA;    	for i in range(0, lines.size(), 2):&#xD;&#xA;    		var x = lines[i]&#xD;&#xA;    		var y = lines[i+1]&#xD;&#xA;    		&#xD;&#xA;    		if (x == 0 || x == -1) &amp;&amp; (y == 0 || y == -1):&#xD;&#xA;    			continue&#xD;&#xA;    		if (x == 0 || x == -1):&#xD;&#xA;    			lines[i+1] = exLerp(corners[1], corners[0]) if x == 0 else exLerp(corners[2], corners[3])&#xD;&#xA;    		if (y == 0 || y == -1):&#xD;&#xA;    			lines[i] = exLerp(corners[3], corners[0]) if y == 0 else exLerp(corners[2], corners[1])&#xD;&#xA;    	&#xD;&#xA;    	return lines&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func drawLines(x, y, lines):&#xD;&#xA;    	if lines != null &amp;&amp; lines.size() &gt;= 4:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[0]), y + (cell_size*lines[1])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[2]), y + (cell_size*lines[3])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    &#xD;&#xA;    	if lines != null &amp;&amp; lines.size() == 8:&#xD;&#xA;    		draw_line(&#xD;&#xA;    			Vector2(x + (cell_size*lines[4]), y + (cell_size*lines[5])), &#xD;&#xA;    			Vector2(x + (cell_size*lines[6]), y + (cell_size*lines[7])), &#xD;&#xA;    			Color.green&#xD;&#xA;    		)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    # Called after update() in the _process()&#xD;&#xA;    func _draw():&#xD;&#xA;    	var vertexes = []&#xD;&#xA;    	for x in range(0, screen_size.x, cell_size):&#xD;&#xA;    		for y in range(0, screen_size.y, cell_size):&#xD;&#xA;    			var sum = 0&#xD;&#xA;    			for blob in blobs:&#xD;&#xA;    				sum += calcIsoSurface(x, blob.pos_x, y, blob.pos_y, blob.radius)&#xD;&#xA;    				#var c = Color.blue&#xD;&#xA;    				#c.a = 0.0001&#xD;&#xA;    				#draw_circle(Vector2(blob.pos_x,blob.pos_y), blob.radius, c)&#xD;&#xA;    			&#xD;&#xA;    			#if sum &gt;= 1:	&#xD;&#xA;    			#	draw_rect(Rect2(x, y, 1, 1), Color.red)&#xD;&#xA;    			#else:&#xD;&#xA;    			#	draw_rect(Rect2(x, y, 1, 1), Color.black)&#xD;&#xA;    		&#xD;&#xA;    			#draw_string(font, Vector2(x, y), &quot;%s&quot; % sum, Color.black)&#xD;&#xA;    &#xD;&#xA;    			var indexies = formDrawIndex(x, y, sum, vertexes)&#xD;&#xA;    			var lines = drawMap[indexies[&quot;draw_index&quot;]]&#xD;&#xA;    			var corners = indexies[&quot;corners&quot;]&#xD;&#xA;    			lines = interpolateLines(lines, corners)&#xD;&#xA;    			&#xD;&#xA;    			drawLines(x, y, lines)&#xD;&#xA;    			vertexes.push_back(sum)&#xD;&#xA;    &#xD;&#xA;    		if x &gt; 0:&#xD;&#xA;    			vertexes.pop_front()&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    func _input(event):&#xD;&#xA;    	if event is InputEventMouseButton &amp;&amp; event.is_pressed():&#xD;&#xA;    		allowUpdate = !allowUpdate&#xD;&#xA;    		print(allowUpdate)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    # Called every frame. 'delta' is the elapsed time since the previous frame.&#xD;&#xA;    &#xD;&#xA;    func _process(delta):&#xD;&#xA;    	if !allowUpdate:        &#xD;&#xA;    		return      &#xD;&#xA;    	update()&#xD;&#xA;    &#xD;&#xA;    	for blob in blobs:&#xD;&#xA;    		blob.pos_x += blob.velocity.x&#xD;&#xA;    		blob.pos_y += blob.velocity.y&#xD;&#xA;    		if blob.pos_x &gt; screen_size.x || blob.pos_x &lt; 0:&#xD;&#xA;    			blob.velocity.x *= -1&#xD;&#xA;    		if blob.pos_y &gt; screen_size.y || blob.pos_y &lt; 0:&#xD;&#xA;    			blob.velocity.y *= -1&#xD;&#xA;    &#xD;&#xA;First calculation of corners weight has to be float not integer:&#xD;&#xA;    &#xD;&#xA;        func calcIsoSurface(x1, x2, y1, y2, r):&#xD;&#xA;            var dx = abs(x1 - x2)&#xD;&#xA;            var dy = abs(y1 - y2)&#xD;&#xA;            var sd = dx*dx + dy*dy&#xD;&#xA;            var res = float(r*r) / float(sd)&#xD;&#xA;            return res &#xD;&#xA;    &#xD;&#xA;The second lerp has to use inversion (since my coordinate system from right to left and from bottom to top):&#xD;&#xA;&#xD;&#xA;    func exLerp(oneSum, zeroSum):&#xD;&#xA;        if oneSum == zeroSum:&#xD;&#xA;            return null&#xD;&#xA;        return -(1-((1 - oneSum) / (zeroSum - oneSum)))&#xD;&#xA;&#xD;&#xA;And finally interpolation itself:&#xD;&#xA;&#xD;&#xA;    func interpolateLines(lines, corners):&#xD;&#xA;        if lines == null:&#xD;&#xA;            return lines&#xD;&#xA;        for i in range(0, lines.size(), 2):&#xD;&#xA;            var x = lines[i]&#xD;&#xA;            var y = lines[i+1]&#xD;&#xA;    &#xD;&#xA;            if (x == 0 || x == -1) &amp;&amp; (y == 0 || y == -1):&#xD;&#xA;                continue&#xD;&#xA;            if (x == 0 || x == -1):&#xD;&#xA;                lines[i+1] = exLerp(corners[1], corners[0]) if x == 0 else exLerp(corners[2], corners[3])&#xD;&#xA;            if (y == 0 || y == -1):&#xD;&#xA;                lines[i] = exLerp(corners[3], corners[0]) if y == 0 else exLerp(corners[2], corners[1])&#xD;&#xA;    &#xD;&#xA;        return lines&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;But I still not fully understand how it works. Why ratio of metaball radius and distance from centre of metaball to corner of marching square is correctly affect x or y coordinate for interpolation when we apply lerp? I can't fully understand it visually. Another word how `calcIsoSurface` relate to `exLerp` in order to figure out correct `x` or `y` for interpolation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gpM9s.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/jIJoM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33009" PostHistoryTypeId="50" PostId="10537" RevisionGUID="17471642-c2b3-4120-8516-52456cde4a78" CreationDate="2021-06-06T06:03:35.320" UserId="-1" />
  <row Id="33010" PostHistoryTypeId="50" PostId="5547" RevisionGUID="3f5d0a9c-ee8c-4ef8-8487-3d29dea32461" CreationDate="2021-06-06T08:02:20.290" UserId="-1" />
  <row Id="33012" PostHistoryTypeId="5" PostId="10942" RevisionGUID="a90c6aac-f878-45eb-8cb3-421b901099e6" CreationDate="2021-06-06T10:43:16.150" UserId="6165" Comment="Added more visuals" Text="as promised, here my answer to your question.&#xD;&#xA;&#xD;&#xA;As I can't follow your code completely (I spend most of my time implementing my code :D ) I can only explain to you what the last step is.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So why do we do interpolation here at all? Well the article already describes well that this piece helps creating a smoother geometry. This works, because we take into account _how much part of the blob is within a grid block_. Looking at the first picture above, take a look into the first block and the second block. The bottom right point has on the left side a scalar value of 2 and on the right side a value of 5. Taking the explanation here into account this must mean that the right block contains more &quot;blob&quot; than the left block which can be seen as the line in the right block is nearly cutting the block in half (see picture below).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now how does this interpolation work? We simply try to calculate a weight which drags the point more up or down, depending on how the scalar values between the two points are. E.g. if you have a value of 0 for a top point and a value of 2 for a bottom point we expect the resulting point on the line between these points to be exactly in the middle. If you now increase the value of the bottom point from 2 to e.g. 10, we expect the resulting point on the line to be much nearer to the bottom point as it &quot;weights&quot; more.&#xD;&#xA;&#xD;&#xA;More mathematically spoken:&#xD;&#xA;Important to note here is that the `exLerp` function is returning the relative value for the `y` value of `Q`. This is always expected to be a value between `0.0` to `1.0`. This property is also guranteed as long as you don't mess up with supplying only pairs of values to your `exLerp` function with one of the values being below `1.0` (our treshold value) and the other value being above `1.0`.&#xD;&#xA;&#xD;&#xA;If you wonder why this is guranteed, just take the formula you implemented (which is correct btw) and supply for x arbitrary values which are greater than 1.0 and for y values which are less than 1.0. The return value will always be between `0.0` and `1.0`. If you violate these properties this doesn't hold anymore because the bottom part of the division becomes smaller than the upper part (thus the value will always be greater than 1).&#xD;&#xA;&#xD;&#xA;So as soon as you have a surface transition, you need to call the exLerp function with the scalar value which is inside of the volume, e.g. in this case the scalar value of the point D (speaking of voxels) and the scalar value of the vertex which is outside of the volume (in this case point B).&#xD;&#xA;&#xD;&#xA;For your algorithm this means you need to find out at the code position when you call `interpolate` whether the return value regarding a specific point is meant to replace the `x` or `y` value of the point you're returning. I guess one variant could be here to check which of the values is `0.5` (if it would be relative position values) because this is always the value you want to replace if you're coming from the non interpolated variant.&#xD;&#xA;&#xD;&#xA;Below you can find some F# code which correctly implements the algorithm. I tried to not optimise that much and made use of more descriptive types so the code better represents what the intention is.&#xD;&#xA;&#xD;&#xA;PS: I suspect that you will have questions as I wrote this answer pretty late (and as soon as it's late one makes more faults and explains less good but I had a promise to keep ;) ).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;``` lang-fsharp&#xD;&#xA;type Position = { x: float; y: float}&#xD;&#xA;    &#xD;&#xA;type Metaball = { radius: float; position: Position }&#xD;&#xA;    &#xD;&#xA;let calculateOccupiedPoints (metaballs: Metaball[]) width height gridDensity =&#xD;&#xA;    Map [|  for x in 0..width - 1 do&#xD;&#xA;                for y in 0.. height - 1 do&#xD;&#xA;                    // The grid density specifies how big a point is, e.g. 1.0 means one block, 0.5 means half a block&#xD;&#xA;                    let xF, yF = float x * gridDensity, float y * gridDensity&#xD;&#xA;                    yield (x, y), metaballs  |&gt; Array.sumBy(fun metaball -&gt; metaball.radius ** 2.0 / ((metaball.position.x - xF) ** 2.0 + (metaball.position.y - yF) ** 2.0))&#xD;&#xA;    |]&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;type Line = { Start: Position; End: Position }&#xD;&#xA;    &#xD;&#xA;type Direction =&#xD;&#xA;    | Top&#xD;&#xA;    | Bottom&#xD;&#xA;    | Left&#xD;&#xA;    | Right&#xD;&#xA;    &#xD;&#xA;// The second half of the table is the frist half of the table but only reversed.&#xD;&#xA;let marchingSquaresTable =&#xD;&#xA;    let firstHalf =&#xD;&#xA;        [|&#xD;&#xA;            (false,false,false,false), [||]&#xD;&#xA;            (false,false,false,true), [| Left, Bottom |]&#xD;&#xA;            (false,false,true,false), [| Bottom , Right|]&#xD;&#xA;            (false,false,true,true), [| Left, Right |]&#xD;&#xA;            (false,true,false,false), [| Top, Right |]&#xD;&#xA;            (false,true,false,true), [| Left, Top; Bottom, Right |]&#xD;&#xA;            (false,true,true,false), [| Top, Bottom |]&#xD;&#xA;            (false,true,true,true), [| Left, Top |] |]&#xD;&#xA;    let secondHalf =&#xD;&#xA;        [|&#xD;&#xA;            (true,false,false,false), [| |]&#xD;&#xA;            (true,false,false,true), [| |]&#xD;&#xA;            (true,false,true,false), [| |]&#xD;&#xA;            (true,false,true,true), [| |]&#xD;&#xA;            (true,true,false,false), [| |]&#xD;&#xA;            (true,true,false,true), [| |]&#xD;&#xA;            (true,true,true,false), [| |]&#xD;&#xA;            (true,true,true,true), [| |]&#xD;&#xA;        |] |&gt; Array.mapi(fun i (_case, _) -&gt; (_case, firstHalf.[7 - i] |&gt; (fun (_, dirs: (Direction * Direction) []) -&gt; dirs)))&#xD;&#xA;    Map.ofArray (firstHalf |&gt; Array.append secondHalf)&#xD;&#xA;    &#xD;&#xA;let calculatePointsViaLinearInterpolation (points: Map&lt;int * int, float&gt;) height width dontInterpolate =&#xD;&#xA;    [|&#xD;&#xA;        for x in 0..(width - 4) do&#xD;&#xA;            for y in 0..(height - 4) do&#xD;&#xA;                let edges =&#xD;&#xA;                    [|&#xD;&#xA;                        0, 0 // A&#xD;&#xA;                        1, 0 // B&#xD;&#xA;                        1, 1 // D&#xD;&#xA;                        0, 1 // C&#xD;&#xA;                    |]&#xD;&#xA;                let xF, yF = float x, float y&#xD;&#xA;                let edgePositions = edges |&gt; Array.map(fun (x0, y0) -&gt; (x0 + x, y0 + y))&#xD;&#xA;                let edgeValues = edgePositions |&gt; Array.map(fun key -&gt; points.[key])&#xD;&#xA;                let [| va; vb; vd; vc |] = edgeValues&#xD;&#xA;                let edgeConfiguration =&#xD;&#xA;                    let [| a; b; d; c |] = edgeValues |&gt; Array.map(fun value -&gt; value &gt;= 1.0)&#xD;&#xA;                    marchingSquaresTable.[(a, b, d, c)]&#xD;&#xA;                let inline mkPoint x y = { x = x; y = y }&#xD;&#xA;                let inline tupleToPoint (x, y) = mkPoint x y&#xD;&#xA;                let getPosForDirection dir =&#xD;&#xA;                    match dir with&#xD;&#xA;                    | Top -&gt; mkPoint 0.5 0.0&#xD;&#xA;                    | Bottom -&gt; mkPoint 0.5 1.0&#xD;&#xA;                    | Left -&gt; mkPoint 0.0 0.5&#xD;&#xA;                    | Right -&gt; mkPoint 1.0 0.5&#xD;&#xA;                let pointValuesForDirection = function&#xD;&#xA;                    | Top -&gt; va, vb&#xD;&#xA;                    | Left -&gt; va, vc&#xD;&#xA;                    | Right -&gt; vb, vd&#xD;&#xA;                    | Bottom -&gt; vc, vd&#xD;&#xA;    &#xD;&#xA;                yield!&#xD;&#xA;                    edgeConfiguration&#xD;&#xA;                    |&gt; Array.map(fun (dirA, dirB) -&gt;&#xD;&#xA;                        let applyInterpolation direction =&#xD;&#xA;                            let (x, y) = pointValuesForDirection direction&#xD;&#xA;                            let pos = getPosForDirection direction&#xD;&#xA;                            let factor =&#xD;&#xA;                                if dontInterpolate then&#xD;&#xA;                                    match direction with&#xD;&#xA;                                    | Left | Right -&gt; pos.y&#xD;&#xA;&#xD;&#xA;                                    | Top | Bottom -&gt; pos.x&#xD;&#xA;                                else&#xD;&#xA;                                    match direction with&#xD;&#xA;                                    | Right | Left -&gt;&#xD;&#xA;                                        0.0 + ((1.0 - x) / (y - x)) * (1.0 - 0.0)&#xD;&#xA;                                    | Top | Bottom -&gt;&#xD;&#xA;                                        0.0 + ((1.0 - x) / (y - x)) * (1.0 - 0.0)&#xD;&#xA;                            match direction with&#xD;&#xA;                            | Top | Bottom -&gt; factor + xF, pos.y + yF&#xD;&#xA;                            | Left | Right -&gt; pos.x + xF, factor + yF&#xD;&#xA;                            |&gt; tupleToPoint&#xD;&#xA;    &#xD;&#xA;                        (applyInterpolation dirA, applyInterpolation dirB)&#xD;&#xA;                    )&#xD;&#xA;    |]&#xD;&#xA;    &#xD;&#xA;let width, height = 64, 64&#xD;&#xA;    &#xD;&#xA;let metaballs =&#xD;&#xA;    [| { radius = 3.4564; position = { x = 7.5; y = 8.0 } }&#xD;&#xA;        { radius = 2.225433; position = { x = 5.5; y = 3.6 } }|]&#xD;&#xA;    &#xD;&#xA;let points = calculateOccupiedPoints metaballs width height (1./4.)&#xD;&#xA;let lines = calculatePointsViaLinearInterpolation points width height false&#xD;&#xA;let lines2 = calculatePointsViaLinearInterpolation points width height true&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I draw the results one get's this (ignore the slight artifacts, the underlying lib Avalonia probably has a bug).&#xD;&#xA;First pic shows the non interpolated variant, second the interpolated variant.&#xD;&#xA;&#xD;&#xA;[![non interpolated][3]][3]&#xD;&#xA;[![interpolated][4]][4]&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;So visually you can better see what happens if you show the values with interpolated colors for each tile.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This one is using linear interpolation for the color values with every iso surface value above 1.0 being just blue.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/atula.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FtXMR.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/mlQB1.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NN8NS.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/lbUvY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33013" PostHistoryTypeId="5" PostId="10942" RevisionGUID="443b1ebf-f56a-4a71-8fa0-6733f3ec6902" CreationDate="2021-06-06T11:27:54.490" UserId="6165" Comment="add another pic" Text="as promised, here my answer to your question.&#xD;&#xA;&#xD;&#xA;As I can't follow your code completely (I spend most of my time implementing my code :D ) I can only explain to you what the last step is.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So why do we do interpolation here at all? Well the article already describes well that this piece helps creating a smoother geometry. This works, because we take into account _how much part of the blob is within a grid block_. Looking at the first picture above, take a look into the first block and the second block. The bottom right point has on the left side a scalar value of 2 and on the right side a value of 5. Taking the explanation here into account this must mean that the right block contains more &quot;blob&quot; than the left block which can be seen as the line in the right block is nearly cutting the block in half (see picture below).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now how does this interpolation work? We simply try to calculate a weight which drags the point more up or down, depending on how the scalar values between the two points are. E.g. if you have a value of 0 for a top point and a value of 2 for a bottom point we expect the resulting point on the line between these points to be exactly in the middle. If you now increase the value of the bottom point from 2 to e.g. 10, we expect the resulting point on the line to be much nearer to the bottom point as it &quot;weights&quot; more.&#xD;&#xA;&#xD;&#xA;More mathematically spoken:&#xD;&#xA;Important to note here is that the `exLerp` function is returning the relative value for the `y` value of `Q`. This is always expected to be a value between `0.0` to `1.0`. This property is also guranteed as long as you don't mess up with supplying only pairs of values to your `exLerp` function with one of the values being below `1.0` (our treshold value) and the other value being above `1.0`.&#xD;&#xA;&#xD;&#xA;If you wonder why this is guranteed, just take the formula you implemented (which is correct btw) and supply for x arbitrary values which are greater than 1.0 and for y values which are less than 1.0. The return value will always be between `0.0` and `1.0`. If you violate these properties this doesn't hold anymore because the bottom part of the division becomes smaller than the upper part (thus the value will always be greater than 1).&#xD;&#xA;&#xD;&#xA;So as soon as you have a surface transition, you need to call the exLerp function with the scalar value which is inside of the volume, e.g. in this case the scalar value of the point D (speaking of voxels) and the scalar value of the vertex which is outside of the volume (in this case point B).&#xD;&#xA;&#xD;&#xA;For your algorithm this means you need to find out at the code position when you call `interpolate` whether the return value regarding a specific point is meant to replace the `x` or `y` value of the point you're returning. I guess one variant could be here to check which of the values is `0.5` (if it would be relative position values) because this is always the value you want to replace if you're coming from the non interpolated variant.&#xD;&#xA;&#xD;&#xA;Below you can find some F# code which correctly implements the algorithm. I tried to not optimise that much and made use of more descriptive types so the code better represents what the intention is.&#xD;&#xA;&#xD;&#xA;PS: I suspect that you will have questions as I wrote this answer pretty late (and as soon as it's late one makes more faults and explains less good but I had a promise to keep ;) ).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;``` lang-fsharp&#xD;&#xA;type Position = { x: float; y: float}&#xD;&#xA;    &#xD;&#xA;type Metaball = { radius: float; position: Position }&#xD;&#xA;    &#xD;&#xA;let calculateOccupiedPoints (metaballs: Metaball[]) width height gridDensity =&#xD;&#xA;    Map [|  for x in 0..width - 1 do&#xD;&#xA;                for y in 0.. height - 1 do&#xD;&#xA;                    // The grid density specifies how big a point is, e.g. 1.0 means one block, 0.5 means half a block&#xD;&#xA;                    let xF, yF = float x * gridDensity, float y * gridDensity&#xD;&#xA;                    yield (x, y), metaballs  |&gt; Array.sumBy(fun metaball -&gt; metaball.radius ** 2.0 / ((metaball.position.x - xF) ** 2.0 + (metaball.position.y - yF) ** 2.0))&#xD;&#xA;    |]&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;type Line = { Start: Position; End: Position }&#xD;&#xA;    &#xD;&#xA;type Direction =&#xD;&#xA;    | Top&#xD;&#xA;    | Bottom&#xD;&#xA;    | Left&#xD;&#xA;    | Right&#xD;&#xA;    &#xD;&#xA;// The second half of the table is the frist half of the table but only reversed.&#xD;&#xA;let marchingSquaresTable =&#xD;&#xA;    let firstHalf =&#xD;&#xA;        [|&#xD;&#xA;            (false,false,false,false), [||]&#xD;&#xA;            (false,false,false,true), [| Left, Bottom |]&#xD;&#xA;            (false,false,true,false), [| Bottom , Right|]&#xD;&#xA;            (false,false,true,true), [| Left, Right |]&#xD;&#xA;            (false,true,false,false), [| Top, Right |]&#xD;&#xA;            (false,true,false,true), [| Left, Top; Bottom, Right |]&#xD;&#xA;            (false,true,true,false), [| Top, Bottom |]&#xD;&#xA;            (false,true,true,true), [| Left, Top |] |]&#xD;&#xA;    let secondHalf =&#xD;&#xA;        [|&#xD;&#xA;            (true,false,false,false), [| |]&#xD;&#xA;            (true,false,false,true), [| |]&#xD;&#xA;            (true,false,true,false), [| |]&#xD;&#xA;            (true,false,true,true), [| |]&#xD;&#xA;            (true,true,false,false), [| |]&#xD;&#xA;            (true,true,false,true), [| |]&#xD;&#xA;            (true,true,true,false), [| |]&#xD;&#xA;            (true,true,true,true), [| |]&#xD;&#xA;        |] |&gt; Array.mapi(fun i (_case, _) -&gt; (_case, firstHalf.[7 - i] |&gt; (fun (_, dirs: (Direction * Direction) []) -&gt; dirs)))&#xD;&#xA;    Map.ofArray (firstHalf |&gt; Array.append secondHalf)&#xD;&#xA;    &#xD;&#xA;let calculatePointsViaLinearInterpolation (points: Map&lt;int * int, float&gt;) height width dontInterpolate =&#xD;&#xA;    [|&#xD;&#xA;        for x in 0..(width - 4) do&#xD;&#xA;            for y in 0..(height - 4) do&#xD;&#xA;                let edges =&#xD;&#xA;                    [|&#xD;&#xA;                        0, 0 // A&#xD;&#xA;                        1, 0 // B&#xD;&#xA;                        1, 1 // D&#xD;&#xA;                        0, 1 // C&#xD;&#xA;                    |]&#xD;&#xA;                let xF, yF = float x, float y&#xD;&#xA;                let edgePositions = edges |&gt; Array.map(fun (x0, y0) -&gt; (x0 + x, y0 + y))&#xD;&#xA;                let edgeValues = edgePositions |&gt; Array.map(fun key -&gt; points.[key])&#xD;&#xA;                let [| va; vb; vd; vc |] = edgeValues&#xD;&#xA;                let edgeConfiguration =&#xD;&#xA;                    let [| a; b; d; c |] = edgeValues |&gt; Array.map(fun value -&gt; value &gt;= 1.0)&#xD;&#xA;                    marchingSquaresTable.[(a, b, d, c)]&#xD;&#xA;                let inline mkPoint x y = { x = x; y = y }&#xD;&#xA;                let inline tupleToPoint (x, y) = mkPoint x y&#xD;&#xA;                let getPosForDirection dir =&#xD;&#xA;                    match dir with&#xD;&#xA;                    | Top -&gt; mkPoint 0.5 0.0&#xD;&#xA;                    | Bottom -&gt; mkPoint 0.5 1.0&#xD;&#xA;                    | Left -&gt; mkPoint 0.0 0.5&#xD;&#xA;                    | Right -&gt; mkPoint 1.0 0.5&#xD;&#xA;                let pointValuesForDirection = function&#xD;&#xA;                    | Top -&gt; va, vb&#xD;&#xA;                    | Left -&gt; va, vc&#xD;&#xA;                    | Right -&gt; vb, vd&#xD;&#xA;                    | Bottom -&gt; vc, vd&#xD;&#xA;    &#xD;&#xA;                yield!&#xD;&#xA;                    edgeConfiguration&#xD;&#xA;                    |&gt; Array.map(fun (dirA, dirB) -&gt;&#xD;&#xA;                        let applyInterpolation direction =&#xD;&#xA;                            let (x, y) = pointValuesForDirection direction&#xD;&#xA;                            let pos = getPosForDirection direction&#xD;&#xA;                            let factor =&#xD;&#xA;                                if dontInterpolate then&#xD;&#xA;                                    match direction with&#xD;&#xA;                                    | Left | Right -&gt; pos.y&#xD;&#xA;&#xD;&#xA;                                    | Top | Bottom -&gt; pos.x&#xD;&#xA;                                else&#xD;&#xA;                                    match direction with&#xD;&#xA;                                    | Right | Left -&gt;&#xD;&#xA;                                        0.0 + ((1.0 - x) / (y - x)) * (1.0 - 0.0)&#xD;&#xA;                                    | Top | Bottom -&gt;&#xD;&#xA;                                        0.0 + ((1.0 - x) / (y - x)) * (1.0 - 0.0)&#xD;&#xA;                            match direction with&#xD;&#xA;                            | Top | Bottom -&gt; factor + xF, pos.y + yF&#xD;&#xA;                            | Left | Right -&gt; pos.x + xF, factor + yF&#xD;&#xA;                            |&gt; tupleToPoint&#xD;&#xA;    &#xD;&#xA;                        (applyInterpolation dirA, applyInterpolation dirB)&#xD;&#xA;                    )&#xD;&#xA;    |]&#xD;&#xA;    &#xD;&#xA;let width, height = 64, 64&#xD;&#xA;    &#xD;&#xA;let metaballs =&#xD;&#xA;    [| { radius = 3.4564; position = { x = 7.5; y = 8.0 } }&#xD;&#xA;        { radius = 2.225433; position = { x = 5.5; y = 3.6 } }|]&#xD;&#xA;    &#xD;&#xA;let points = calculateOccupiedPoints metaballs width height (1./4.)&#xD;&#xA;let lines = calculatePointsViaLinearInterpolation points width height false&#xD;&#xA;let lines2 = calculatePointsViaLinearInterpolation points width height true&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I draw the results one get's this (ignore the slight artifacts, the underlying lib Avalonia probably has a bug).&#xD;&#xA;First pic shows the non interpolated variant, second the interpolated variant.&#xD;&#xA;&#xD;&#xA;[![non interpolated][3]][3]&#xD;&#xA;[![interpolated][4]][4]&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;So visually you can better see what happens if you show the values with interpolated colors for each tile.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;This one is using linear interpolation for the color values with every iso surface value above 1.0 being just blue.&#xD;&#xA;&#xD;&#xA;Below the same picture without line.&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/atula.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FtXMR.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/mlQB1.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/NN8NS.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/lbUvY.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/10nbk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33017" PostHistoryTypeId="2" PostId="10948" RevisionGUID="23e37825-b1bd-484c-b6d8-3b35dac42738" CreationDate="2021-06-06T15:59:19.743" UserId="13391" Text="I am trying to do ray tracing in python *(following the tutorial given in [Ray Tracing in a weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html#diffusematerials))*. Basically I am shooting rays from eye and the recursively bounce around, each time they hit something they become weaker *(actually this is reverse ray casting but you get the idea)*. The output I am getting is **incorrect**.&#xD;&#xA;&#xD;&#xA;My output:&#xD;&#xA;&#xD;&#xA;![bug1](https://i.stack.imgur.com/Leabe.png)&#xD;&#xA;&#xD;&#xA;Expected output:&#xD;&#xA;&#xD;&#xA;![expected](https://raytracing.github.io/images/img-1.08-gamma-correct.png)&#xD;&#xA;&#xD;&#xA;The shadows are messed up. What could be wrong?&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;```&#xD;&#xA;import numpy as np&#xD;&#xA;import sys&#xD;&#xA;import random&#xD;&#xA;from PIL import Image&#xD;&#xA;from math import * &#xD;&#xA;from util import *&#xD;&#xA;&#xD;&#xA;width  = 60&#xD;&#xA;height = 60&#xD;&#xA;&#xD;&#xA;samples = 20&#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def reflected(vector, axis):&#xD;&#xA;    return vector - axis * 2 * vector.dot(axis)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def RandomPointInSphere():&#xD;&#xA;    p = None&#xD;&#xA;    while True:&#xD;&#xA;        p = Vector(random.uniform(0,1),random.uniform(0,1),random.uniform(0,1))*2 - Vector(1,1,1)&#xD;&#xA;        if(p.dot(p) &lt; 1):&#xD;&#xA;            break&#xD;&#xA;    return p&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;def GetNearestObject(objects, ray):&#xD;&#xA;    nearest_obj = None&#xD;&#xA;    min_hit = Intersection(None, INF, None, None)&#xD;&#xA;    &#xD;&#xA;    for obj in objects:&#xD;&#xA;        hit = obj.intersect(ray)&#xD;&#xA;        if(hit.distance &lt; min_hit.distance):&#xD;&#xA;            nearest_obj = obj&#xD;&#xA;            min_hit = hit&#xD;&#xA;    &#xD;&#xA;    return min_hit&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def RayColor(objects, ray):&#xD;&#xA;    # Part 1: Diffuse Material&#xD;&#xA;    result = GetNearestObject(objects, ray)&#xD;&#xA;    if(result.point != None):&#xD;&#xA;        P = result.point&#xD;&#xA;        N = result.normal&#xD;&#xA;        E = RandomPointInSphere()&#xD;&#xA;        target = P + N + E&#xD;&#xA;        &#xD;&#xA;        newRay = Ray(ray.origin, (target - ray.origin).normalize())&#xD;&#xA;        return RayColor(objects, newRay)*0.5&#xD;&#xA;    else:&#xD;&#xA;        t = 0.5 * (ray.direction.y + 1.0);&#xD;&#xA;        color = Vector(1.0, 1.0, 1.0)*(1.0 - t) + Vector(0.5, 0.7, 1.0)*t&#xD;&#xA;        color.x = min(color.x,1.0)&#xD;&#xA;        color.y = min(color.y,1.0)&#xD;&#xA;        color.z = min(color.z,1.0)&#xD;&#xA;        return Vector(1,1,1)&#xD;&#xA;    &#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;def main():&#xD;&#xA;    global bitmap&#xD;&#xA;    &#xD;&#xA;    eye    = Vector(0,0,1)&#xD;&#xA;    ratio  = float(width) / height&#xD;&#xA;    screen = Screen(-1, 1 / ratio, 1, -1 / ratio, 0)&#xD;&#xA;    &#xD;&#xA;    objects = []&#xD;&#xA;    objects.append(Sphere(Vector(-0.2,0,-1),  0.7, Material(Vector(0.1,0,0),  Vector(0.7,0,0),    Vector(1,1,1), 100, 0.5)))&#xD;&#xA;    &#xD;&#xA;    objects.append(Sphere(Vector(0,-9000,0),  9000-0.7, Material(Vector(0.1,0.1,0.1),Vector(0.6,0.6,0.6),Vector(1,1,1), 100, 0.5)))&#xD;&#xA;    &#xD;&#xA;    light = Light(Vector(5,5,5), Material(Vector(1,1,1),Vector(1,1,1),Vector(1,1,1)))&#xD;&#xA;    &#xD;&#xA;    for frame in range(1):&#xD;&#xA;    &#xD;&#xA;        img    = Image.new(mode = &quot;RGB&quot;, size=(width, height), color=Color.WHITE)&#xD;&#xA;        bitmap = img.load() # create the pixel data&#xD;&#xA;&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#---                    YOUR CODE HERE                      ---&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;        sys.setrecursionlimit(10000)&#xD;&#xA;        &#xD;&#xA;        #breakpoint()&#xD;&#xA;        &#xD;&#xA;        deltaX = (screen.right - screen.left)/(width-1)&#xD;&#xA;        deltaY = (screen.top - screen.bottom)/(height-1)&#xD;&#xA;&#xD;&#xA;        for y in range(height):&#xD;&#xA;            for x in range(width):&#xD;&#xA;                pixel     = Vector(screen.left+x*deltaX, screen.top-y*deltaY, screen.z)&#xD;&#xA;                direction = (pixel - eye).normalize()&#xD;&#xA;                pixelRay = Ray(eye, direction)                &#xD;&#xA;&#xD;&#xA;                # Part 1: Diffuse Material&#xD;&#xA;                color = Vector(0,0,0)&#xD;&#xA;                for s in range(samples):&#xD;&#xA;                    color += RayColor(objects, pixelRay)&#xD;&#xA;                &#xD;&#xA;                color *= 1.0/samples&#xD;&#xA;                #color = Vector(sqrt(color.x), sqrt(color.y), sqrt(color.z))&#xD;&#xA;                bitmap[x,y] = (int(color.x*255), int(color.y*255), int(color.z*255))&#xD;&#xA;&#xD;&#xA;            print(&quot;progress: %d %%&quot; % ((y+1)/height*100.0))&#xD;&#xA;            &#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;        img.show()&#xD;&#xA;        img.save(&quot;pic1.png&quot;)&#xD;&#xA;        #img.save(&quot;images/fig&quot; + f'{frame:06}' + &quot;.png&quot;)&#xD;&#xA;        #print(&quot;Saving ---&gt; images/fig&quot; + f'{frame:06}' + &quot;.png&quot;)&#xD;&#xA;        #img.close()&#xD;&#xA;&#xD;&#xA;main()&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="33018" PostHistoryTypeId="1" PostId="10948" RevisionGUID="23e37825-b1bd-484c-b6d8-3b35dac42738" CreationDate="2021-06-06T15:59:19.743" UserId="13391" Text="Ray tracing Bug with Diffuse material" ContentLicense="CC BY-SA 4.0" />
  <row Id="33019" PostHistoryTypeId="3" PostId="10948" RevisionGUID="23e37825-b1bd-484c-b6d8-3b35dac42738" CreationDate="2021-06-06T15:59:19.743" UserId="13391" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33020" PostHistoryTypeId="6" PostId="10948" RevisionGUID="4d7b35bd-9f70-4783-b06d-56ac77f89702" CreationDate="2021-06-06T16:35:31.370" UserId="13391" Comment="edited tags" Text="|raytracing|rendering|lighting|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33021" PostHistoryTypeId="50" PostId="10365" RevisionGUID="27421d3c-5233-46de-8071-e55c5d9b7319" CreationDate="2021-06-07T08:05:05.420" UserId="-1" />
  <row Id="33022" PostHistoryTypeId="34" PostId="10920" RevisionGUID="85e8a8d7-0533-4f88-a9a3-29b7c72f5b12" CreationDate="2021-06-07T16:16:43.343" UserId="2485" Comment="69" />
  <row Id="33023" PostHistoryTypeId="50" PostId="9829" RevisionGUID="8bf2982b-53fd-45c5-b73a-63bf376afbfc" CreationDate="2021-06-07T17:05:15.433" UserId="-1" />
  <row Id="33024" PostHistoryTypeId="2" PostId="10949" RevisionGUID="ab50a627-ac2e-45e1-a4bf-8641405aa344" CreationDate="2021-06-07T17:07:04.067" UserId="2494" Text="    Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(),           DIFF),//Frnt&#xD;&#xA;&#xD;&#xA;The sphere with index 3 would intersect each ray if the ray origin would no be shifted forward.&#xD;&#xA;&#xD;&#xA;You can easily verify this be returning surface normals from radiance and not shifting the ray origin. (or just remove this one sphere). It also will look like tunnel behind the camera ;)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33025" PostHistoryTypeId="2" PostId="10950" RevisionGUID="cf933fd9-7c00-4935-8504-399d20269208" CreationDate="2021-06-07T17:12:08.387" UserId="2494" Text="I see a couple of problems by scanning quickly over your code.&#xD;&#xA;&#xD;&#xA; 1. You are using ray.origin as new origin when scattering the ray off the surface, you should however use the hit point as origin of the new ray. This might also explain why you see a kind of &quot;screen aligned&quot; shadow.&#xD;&#xA; 2. The new ray direction is just the direction ray.origin to target.&#xD;&#xA; 3. Is result.point actually the center of the sphere or the point of intersection on the surface? I can't say for sure as I don't have the rest of your code.&#xD;&#xA;&#xD;&#xA;There is a lot that is not right, or seemingly unintentional.&#xD;&#xA;&#xD;&#xA;What you can do however to debug such things is to return a debug color like e.g. normal at point, depth (normalized to some maximum), scatter direction, etc." ContentLicense="CC BY-SA 4.0" />
  <row Id="33026" PostHistoryTypeId="5" PostId="10948" RevisionGUID="1e58298b-a16b-4fd9-80f9-adee377d40ca" CreationDate="2021-06-07T18:54:40.243" UserId="13391" Comment="added 4278 characters in body" Text="I am trying to do ray tracing in python *(following the tutorial given in [Ray Tracing in a weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html#diffusematerials))*. Basically I am shooting rays from eye and the recursively bounce around, each time they hit something they become weaker *(actually this is reverse ray casting but you get the idea)*. The output I am getting is **incorrect**.&#xD;&#xA;&#xD;&#xA;My output:&#xD;&#xA;&#xD;&#xA;![bug1](https://i.stack.imgur.com/Leabe.png)&#xD;&#xA;&#xD;&#xA;Expected output:&#xD;&#xA;&#xD;&#xA;![expected](https://raytracing.github.io/images/img-1.08-gamma-correct.png)&#xD;&#xA;&#xD;&#xA;The shadows are messed up. What could be wrong?&#xD;&#xA;&#xD;&#xA;My code:&#xD;&#xA;```&#xD;&#xA;import numpy as np&#xD;&#xA;import sys&#xD;&#xA;import random&#xD;&#xA;from PIL import Image&#xD;&#xA;from math import * &#xD;&#xA;from util import *&#xD;&#xA;&#xD;&#xA;width  = 60&#xD;&#xA;height = 60&#xD;&#xA;&#xD;&#xA;samples = 20&#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def reflected(vector, axis):&#xD;&#xA;    return vector - axis * 2 * vector.dot(axis)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def RandomPointInSphere():&#xD;&#xA;    p = None&#xD;&#xA;    while True:&#xD;&#xA;        p = Vector(random.uniform(0,1),random.uniform(0,1),random.uniform(0,1))*2 - Vector(1,1,1)&#xD;&#xA;        if(p.dot(p) &lt; 1):&#xD;&#xA;            break&#xD;&#xA;    return p&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;def GetNearestObject(objects, ray):&#xD;&#xA;    nearest_obj = None&#xD;&#xA;    min_hit = Intersection(None, INF, None, None)&#xD;&#xA;    &#xD;&#xA;    for obj in objects:&#xD;&#xA;        hit = obj.intersect(ray)&#xD;&#xA;        if(hit.distance &lt; min_hit.distance):&#xD;&#xA;            nearest_obj = obj&#xD;&#xA;            min_hit = hit&#xD;&#xA;    &#xD;&#xA;    return min_hit&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def RayColor(objects, ray):&#xD;&#xA;    # Part 1: Diffuse Material&#xD;&#xA;    result = GetNearestObject(objects, ray)&#xD;&#xA;    if(result.point != None):&#xD;&#xA;        P = result.point&#xD;&#xA;        N = result.normal&#xD;&#xA;        E = RandomPointInSphere()&#xD;&#xA;        target = P + N + E&#xD;&#xA;        &#xD;&#xA;        newRay = Ray(ray.origin, (target - ray.origin).normalize())&#xD;&#xA;        return RayColor(objects, newRay)*0.5&#xD;&#xA;    else:&#xD;&#xA;        t = 0.5 * (ray.direction.y + 1.0);&#xD;&#xA;        color = Vector(1.0, 1.0, 1.0)*(1.0 - t) + Vector(0.5, 0.7, 1.0)*t&#xD;&#xA;        color.x = min(color.x,1.0)&#xD;&#xA;        color.y = min(color.y,1.0)&#xD;&#xA;        color.z = min(color.z,1.0)&#xD;&#xA;        return Vector(1,1,1)&#xD;&#xA;    &#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;def main():&#xD;&#xA;    global bitmap&#xD;&#xA;    &#xD;&#xA;    eye    = Vector(0,0,1)&#xD;&#xA;    ratio  = float(width) / height&#xD;&#xA;    screen = Screen(-1, 1 / ratio, 1, -1 / ratio, 0)&#xD;&#xA;    &#xD;&#xA;    objects = []&#xD;&#xA;    objects.append(Sphere(Vector(-0.2,0,-1),  0.7, Material(Vector(0.1,0,0),  Vector(0.7,0,0),    Vector(1,1,1), 100, 0.5)))&#xD;&#xA;    &#xD;&#xA;    objects.append(Sphere(Vector(0,-9000,0),  9000-0.7, Material(Vector(0.1,0.1,0.1),Vector(0.6,0.6,0.6),Vector(1,1,1), 100, 0.5)))&#xD;&#xA;    &#xD;&#xA;    light = Light(Vector(5,5,5), Material(Vector(1,1,1),Vector(1,1,1),Vector(1,1,1)))&#xD;&#xA;    &#xD;&#xA;    for frame in range(1):&#xD;&#xA;    &#xD;&#xA;        img    = Image.new(mode = &quot;RGB&quot;, size=(width, height), color=Color.WHITE)&#xD;&#xA;        bitmap = img.load() # create the pixel data&#xD;&#xA;&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#---                    YOUR CODE HERE                      ---&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;        sys.setrecursionlimit(10000)&#xD;&#xA;        &#xD;&#xA;        #breakpoint()&#xD;&#xA;        &#xD;&#xA;        deltaX = (screen.right - screen.left)/(width-1)&#xD;&#xA;        deltaY = (screen.top - screen.bottom)/(height-1)&#xD;&#xA;&#xD;&#xA;        for y in range(height):&#xD;&#xA;            for x in range(width):&#xD;&#xA;                pixel     = Vector(screen.left+x*deltaX, screen.top-y*deltaY, screen.z)&#xD;&#xA;                direction = (pixel - eye).normalize()&#xD;&#xA;                pixelRay = Ray(eye, direction)                &#xD;&#xA;&#xD;&#xA;                # Part 1: Diffuse Material&#xD;&#xA;                color = Vector(0,0,0)&#xD;&#xA;                for s in range(samples):&#xD;&#xA;                    color += RayColor(objects, pixelRay)&#xD;&#xA;                &#xD;&#xA;                color *= 1.0/samples&#xD;&#xA;                #color = Vector(sqrt(color.x), sqrt(color.y), sqrt(color.z))&#xD;&#xA;                bitmap[x,y] = (int(color.x*255), int(color.y*255), int(color.z*255))&#xD;&#xA;&#xD;&#xA;            print(&quot;progress: %d %%&quot; % ((y+1)/height*100.0))&#xD;&#xA;            &#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;        img.show()&#xD;&#xA;        img.save(&quot;pic1.png&quot;)&#xD;&#xA;        #img.save(&quot;images/fig&quot; + f'{frame:06}' + &quot;.png&quot;)&#xD;&#xA;        #print(&quot;Saving ---&gt; images/fig&quot; + f'{frame:06}' + &quot;.png&quot;)&#xD;&#xA;        #img.close()&#xD;&#xA;&#xD;&#xA;main()&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;util.py file:&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;from math import * &#xD;&#xA;from abc import ABC, abstractmethod&#xD;&#xA;&#xD;&#xA;PI  = 3.14159265&#xD;&#xA;INF = 9999999999&#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;class Color:&#xD;&#xA;    BLACK = (0,0,0)&#xD;&#xA;    RED   = (245,23,32)&#xD;&#xA;    BLUE  = (46,139,192)&#xD;&#xA;    GREEN = (24,165,88)&#xD;&#xA;    PINK  = (250,38,160)&#xD;&#xA;    GOLD  = (248,210,16)&#xD;&#xA;    TEAL  = (43,124,133)&#xD;&#xA;    WHITE = (255,255,255)&#xD;&#xA;    CHROMA= (0,255,0)&#xD;&#xA;    &#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def dot(a, b):&#xD;&#xA;    return a.x*b.x + a.y*b.y + a.z*b.z&#xD;&#xA;&#xD;&#xA;def normalize(a):&#xD;&#xA;    mag = a.magnitude()&#xD;&#xA;    return Vector(a.x/mag,a.y/mag,a.z/mag)&#xD;&#xA;&#xD;&#xA;class Vector:&#xD;&#xA;    def __init__(self,x,y,z):&#xD;&#xA;        self.x = x&#xD;&#xA;        self.y = y&#xD;&#xA;        self.z = z&#xD;&#xA;        self.w = 1&#xD;&#xA;&#xD;&#xA;    def toString(self):&#xD;&#xA;        return &quot;S:[&quot;+&quot;{:.3f}&quot;.format(self.x)+&quot;, &quot;+&quot;{:.3f}&quot;.format(self.y)+&quot;, &quot;+&quot;{:.3f}&quot;.format(self.z)+&quot;]&quot;&#xD;&#xA;&#xD;&#xA;    def dot(self, b):&#xD;&#xA;        return self.x*b.x + self.y*b.y + self.z*b.z&#xD;&#xA;    &#xD;&#xA;    def cross(self, b):&#xD;&#xA;        return Vector(self.y*b.z-self.z*b.y, self.z*b.x-self.x*b.z, self.x*b.y-self.y*b.x)&#xD;&#xA;        &#xD;&#xA;    def magnitude(self):&#xD;&#xA;        return sqrt(self.x*self.x + self.y*self.y + self.z*self.z)&#xD;&#xA;&#xD;&#xA;    def normalize(self):&#xD;&#xA;        mag = self.magnitude()&#xD;&#xA;        return Vector(self.x/mag, self.y/mag, self.z/mag)&#xD;&#xA;&#xD;&#xA;    # Provide &quot;overridden methods via the &quot;__operation__&quot; notation; allows you to do, for example, a+b, a-b, a*b&#xD;&#xA;    def __add__(self, b):&#xD;&#xA;        return Vector(self.x + b.x, self.y+b.y, self.z+b.z)&#xD;&#xA;&#xD;&#xA;    def __sub__(self, b):&#xD;&#xA;        return Vector(self.x-b.x, self.y-b.y, self.z-b.z)&#xD;&#xA;&#xD;&#xA;    def __mul__(self, b):&#xD;&#xA;        if type(b) == float or type(b) == int:&#xD;&#xA;            return Vector(self.x*b, self.y*b, self.z*b)&#xD;&#xA;        elif type(b) == Vector:&#xD;&#xA;            return Vector(self.x*b.x, self.y*b.y, self.z*b.z)&#xD;&#xA;        else:&#xD;&#xA;            print(type(b))&#xD;&#xA;            assert False&#xD;&#xA;&#xD;&#xA;class Material:&#xD;&#xA;    def __init__(self, ambient, diffuse, specular, shininess = 0.0, reflection = 0.0):&#xD;&#xA;        self.ambient   = ambient    # 3D Vector&#xD;&#xA;        self.diffuse   = diffuse    # 3D Vector&#xD;&#xA;        self.specular  = specular   # 3D Vector&#xD;&#xA;        self.shininess = shininess  #   0 - 100&#xD;&#xA;        self.reflection= reflection # 0.0 - 1.0&#xD;&#xA;&#xD;&#xA;class Light:&#xD;&#xA;    def __init__(self, position, material):&#xD;&#xA;        self.position = position&#xD;&#xA;        self.material  = material&#xD;&#xA;&#xD;&#xA;class Hittable(ABC):&#xD;&#xA;    @abstractmethod&#xD;&#xA;    def intersect(self, ray):&#xD;&#xA;        pass&#xD;&#xA;&#xD;&#xA;class Sphere(Hittable):&#xD;&#xA;    def __init__(self,center, radius, material):&#xD;&#xA;        self.center   = center&#xD;&#xA;        self.radius   = radius&#xD;&#xA;        self.material = material&#xD;&#xA;        &#xD;&#xA;    def intersect(self, ray):&#xD;&#xA;        OC = ray.origin - self.center&#xD;&#xA;        a = ray.direction.dot(ray.direction)&#xD;&#xA;        b = 2.0 * ray.direction.dot(OC)&#xD;&#xA;        c = OC.dot(OC) - self.radius*self.radius&#xD;&#xA;        descriminant = b*b - 4*a*c&#xD;&#xA;        if(descriminant &gt; 0):&#xD;&#xA;            t1 = (-b + sqrt(descriminant))/2&#xD;&#xA;            t2 = (-b - sqrt(descriminant))/2&#xD;&#xA;            if t1 &gt; 0 and t2 &gt; 0:&#xD;&#xA;                dist = min(t1,t2)&#xD;&#xA;                point = ray.pointAtParameter(dist)&#xD;&#xA;                normal = (point - self.center).normalize()&#xD;&#xA;                return Intersection(point, dist, normal, self)&#xD;&#xA;        return Intersection(None, INF, None, None)&#xD;&#xA;        &#xD;&#xA;                &#xD;&#xA;    def normal(self, b):&#xD;&#xA;        return (b - self.center).normalize()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;class Ray:&#xD;&#xA;    def __init__(self, origin, direction):&#xD;&#xA;        self.origin    = origin&#xD;&#xA;        self.direction = direction&#xD;&#xA;&#xD;&#xA;    def pointAtParameter(self, t):&#xD;&#xA;        return self.origin + self.direction*t&#xD;&#xA;    &#xD;&#xA;    def toString(self):&#xD;&#xA;        return &quot;R-&gt;{ &quot;+ self.origin.toString() + &quot; -- &quot; + self.direction.toString() +&quot; }&quot;&#xD;&#xA;       &#xD;&#xA;class Intersection:&#xD;&#xA;	def __init__(self, point, distance, normal, object):&#xD;&#xA;		self.point    = point&#xD;&#xA;		self.distance = distance&#xD;&#xA;		self.normal   = normal&#xD;&#xA;		self.object   = object&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;class Screen:&#xD;&#xA;    def __init__(self,  left, top, right, bottom, z):&#xD;&#xA;        self.left   = left&#xD;&#xA;        self.top    = top&#xD;&#xA;        self.right  = right&#xD;&#xA;        self.bottom = bottom&#xD;&#xA;        self.z      = z&#xD;&#xA;        &#xD;&#xA;class Camera:&#xD;&#xA;    def __init__(self):&#xD;&#xA;        pass  &#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="33027" PostHistoryTypeId="5" PostId="10949" RevisionGUID="15e527d5-b6f5-4109-8f51-bfb7e843c33f" CreationDate="2021-06-07T23:31:58.770" UserId="7952" Comment="spelling and clarity " Text="    Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(),           DIFF),//Frnt&#xD;&#xA;&#xD;&#xA;The sphere with index 3 would intersect each ray if the ray origin would not be shifted forward.&#xD;&#xA;&#xD;&#xA;You can easily verify this by returning surface normals from the radiance and not shifting the ray origin. (or just remove this one sphere). It also will look like a tunnel behind the camera ;)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33028" PostHistoryTypeId="24" PostId="10949" RevisionGUID="15e527d5-b6f5-4109-8f51-bfb7e843c33f" CreationDate="2021-06-07T23:31:58.770" Comment="Proposed by 7952 approved by 482 edit id of 565" ContentLicense="CC BY-SA 4.0" />
  <row Id="33029" PostHistoryTypeId="2" PostId="10951" RevisionGUID="0c57502b-a8ca-45e5-9ee6-a03f4881494f" CreationDate="2021-06-07T23:55:52.753" UserId="482" Text="[Physically Based Rendering: From Theory to Implementation](https://www.pbrt.org/)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33030" PostHistoryTypeId="1" PostId="10951" RevisionGUID="0c57502b-a8ca-45e5-9ee6-a03f4881494f" CreationDate="2021-06-07T23:55:52.753" UserId="482" ContentLicense="CC BY-SA 4.0" />
  <row Id="33031" PostHistoryTypeId="2" PostId="10952" RevisionGUID="08416c1c-902a-4703-b872-57e1e8cbe7c1" CreationDate="2021-06-07T23:55:52.753" UserId="482" Text="For questions related to techniques described in the book *Physically Based Rendering: From Theory to Implementation*" ContentLicense="CC BY-SA 4.0" />
  <row Id="33032" PostHistoryTypeId="1" PostId="10952" RevisionGUID="08416c1c-902a-4703-b872-57e1e8cbe7c1" CreationDate="2021-06-07T23:55:52.753" UserId="482" ContentLicense="CC BY-SA 4.0" />
  <row Id="33033" PostHistoryTypeId="50" PostId="10207" RevisionGUID="5d3b9cc7-b5f6-4ead-a5c0-cdc9c9882c9f" CreationDate="2021-06-08T08:06:25.597" UserId="-1" />
  <row Id="33034" PostHistoryTypeId="50" PostId="10341" RevisionGUID="3d148ca4-66a2-43a0-9504-2e9976adcb2f" CreationDate="2021-06-08T09:05:25.440" UserId="-1" />
  <row Id="33035" PostHistoryTypeId="2" PostId="10953" RevisionGUID="068cbd85-9a80-44c4-b388-5eefb600bcf8" CreationDate="2021-06-08T17:07:40.360" UserId="386" Text="As it turned out, the premultiplied color data was [transformed](https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation) to sRGB. Alpha stays linear. In that case, a component can be greater than the alpha. For example, with alpha 0.5 and color 1.0, the premultiplied value (0.5) is fed to the `forward transformation (CIE XYZ to sRGB)` formula that returns ~0.74." ContentLicense="CC BY-SA 4.0" />
  <row Id="33036" PostHistoryTypeId="50" PostId="10204" RevisionGUID="e877b220-c2c9-4181-85c4-37aee61e46b9" CreationDate="2021-06-08T21:00:14.143" UserId="-1" />
  <row Id="33040" PostHistoryTypeId="2" PostId="10955" RevisionGUID="4095edfb-5cf7-42f2-9ce7-b2e8c139a04d" CreationDate="2021-06-09T20:08:06.800" UserId="16627" Text="I have points that are obtained by sampling a mesh(which is not watertight). Now, I would like to convert that mesh into voxel?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Does anyone have any suggestions for solving this problem?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33041" PostHistoryTypeId="1" PostId="10955" RevisionGUID="4095edfb-5cf7-42f2-9ce7-b2e8c139a04d" CreationDate="2021-06-09T20:08:06.800" UserId="16627" Text="Convert point clouds into voxels" ContentLicense="CC BY-SA 4.0" />
  <row Id="33042" PostHistoryTypeId="3" PostId="10955" RevisionGUID="4095edfb-5cf7-42f2-9ce7-b2e8c139a04d" CreationDate="2021-06-09T20:08:06.800" UserId="16627" Text="|3d|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33044" PostHistoryTypeId="2" PostId="10956" RevisionGUID="40890393-6493-40f2-a7c8-b013e26b8811" CreationDate="2021-06-10T12:08:39.780" UserId="13874" Text="Following some documents on internet, I divide my ray tracing result by PDF. Then it seem the D and G terms disappeared. Only F term is still visible, it looks like Fresnel only.&#xD;&#xA;&#xD;&#xA;`color = D(wh) * G(wo, wi) * F / (4 * wi.z * wo.z);`&#xD;&#xA;&#xD;&#xA;`pdf = D(wi) * G1(wo) * abs(dot(wo, wi)) / (abs(wo.z) * 4 * dot(wo, wh))`&#xD;&#xA;&#xD;&#xA;`color / pdf` looks very similar to F term. That's strange, I don't know what's wrong.&#xD;&#xA;&#xD;&#xA;IMO, the `pdf` also has `D` and `G` term. If I divide the result by PDF, it's likely to neutralized the effect of `D` and `G`. But that's obviously wrong. &#xD;&#xA;&#xD;&#xA;So, how to use the PDF in correct way. Do I have the correct form of PDF? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33045" PostHistoryTypeId="1" PostId="10956" RevisionGUID="40890393-6493-40f2-a7c8-b013e26b8811" CreationDate="2021-06-10T12:08:39.780" UserId="13874" Text="Raytracing, divide by PDF neutralized the effect of D and G terms, what is the problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33046" PostHistoryTypeId="3" PostId="10956" RevisionGUID="40890393-6493-40f2-a7c8-b013e26b8811" CreationDate="2021-06-10T12:08:39.780" UserId="13874" Text="|raytracing|ggx|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33048" PostHistoryTypeId="2" PostId="10957" RevisionGUID="230bbe59-bc32-4653-aa53-fb3699f65944" CreationDate="2021-06-10T15:45:18.640" UserId="13273" Text="I am trying to only change the near clipping plane of a given perspective projection matrix for OpenGL.&#xD;&#xA;My problem is, that the near clipping plane is way too close, and the far clipping plane is very far away. That causes depth buffer precision problems, which are visible (see image)&#xD;&#xA;&#xD;&#xA;**Visualization of the artefacts**&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;The wrong parts are marked with red circles.&#xD;&#xA;&#xD;&#xA;I would like to solve this issue by only changing the near clipping plane.&#xD;&#xA;Is there a fast and easy way to keep all parameter the same except the near clipping plane?&#xD;&#xA;I don't have any of the parameters. The only input I have is the ProjectionMatrix which should be changed&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Sq07C.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33049" PostHistoryTypeId="1" PostId="10957" RevisionGUID="230bbe59-bc32-4653-aa53-fb3699f65944" CreationDate="2021-06-10T15:45:18.640" UserId="13273" Text="how to change the near clipping plane of a perspective projection matrix for OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="33050" PostHistoryTypeId="3" PostId="10957" RevisionGUID="230bbe59-bc32-4653-aa53-fb3699f65944" CreationDate="2021-06-10T15:45:18.640" UserId="13273" Text="|opengl|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33051" PostHistoryTypeId="2" PostId="10958" RevisionGUID="b394de11-0ed1-43b4-bba7-e0e402fcfe77" CreationDate="2021-06-10T17:01:04.043" UserId="9581" Text="My goal is to update camera parameters given a velocity vector so that the camera points in the direction of the velocity vector. How should one compute the update matrix for the camera parameters?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33052" PostHistoryTypeId="1" PostId="10958" RevisionGUID="b394de11-0ed1-43b4-bba7-e0e402fcfe77" CreationDate="2021-06-10T17:01:04.043" UserId="9581" Text="How compute new camera parameters given a velocity vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33053" PostHistoryTypeId="3" PostId="10958" RevisionGUID="b394de11-0ed1-43b4-bba7-e0e402fcfe77" CreationDate="2021-06-10T17:01:04.043" UserId="9581" Text="|3d|transformations|mathematics|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33054" PostHistoryTypeId="2" PostId="10959" RevisionGUID="ba1ffe25-4d37-486f-8658-0d259ac31428" CreationDate="2021-06-11T10:00:03.220" UserId="11058" Text="In 2d and 3d environment we can select primitives like lines and polygons by performing point/ray intersection test with the respective primitive. However how does one approach the selection of quadratic/cubic spline curves?&#xD;&#xA;&#xD;&#xA;Is this problem often dealt by using an approximate solution, where we perform an intersection test with lines formed by control points of the spline curve? Or is there a more precise solution to the problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33055" PostHistoryTypeId="1" PostId="10959" RevisionGUID="ba1ffe25-4d37-486f-8658-0d259ac31428" CreationDate="2021-06-11T10:00:03.220" UserId="11058" Text="Dealing with selection of spline/bezier curves in graphical software" ContentLicense="CC BY-SA 4.0" />
  <row Id="33056" PostHistoryTypeId="3" PostId="10959" RevisionGUID="ba1ffe25-4d37-486f-8658-0d259ac31428" CreationDate="2021-06-11T10:00:03.220" UserId="11058" Text="|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33057" PostHistoryTypeId="2" PostId="10960" RevisionGUID="37505283-d2ca-449d-8d2b-c9021fe2b7c6" CreationDate="2021-06-11T11:35:50.833" UserId="7952" Text="The velocity vector becomes your forward vector, just normalize it. The up direction doesn't change, use whatever version up the camera usually uses. The last vector (call it the &quot;right hand&quot; vector) is the cross product of up, and forward. Then, do a second cross with the forward vector and the right hand vector to guarantee an orthonormal basis.&#xD;&#xA;&#xD;&#xA;The last  bit needed is the translation which will have to come from somewhere.&#xD;&#xA;&#xD;&#xA;The exact ordering of all the operations is going to depend on the setup you are using. Is up direction y or z ect.&#xD;&#xA;&#xD;&#xA;Once the matrix if formed, find its inverse. (Since you went through the trouble of making sure it is orthonormal, the inverse is equivalent to the transpose.)&#xD;&#xA;&#xD;&#xA;This is the new view matrix." ContentLicense="CC BY-SA 4.0" />
  <row Id="33058" PostHistoryTypeId="50" PostId="10879" RevisionGUID="f8c5c301-1496-41a4-bca8-5cd84add2c8d" CreationDate="2021-06-11T19:03:40.317" UserId="-1" />
  <row Id="33059" PostHistoryTypeId="2" PostId="10961" RevisionGUID="de48cfce-bc2c-4df2-88e9-384e4a756f1b" CreationDate="2021-06-12T03:01:36.750" UserId="16664" Text="Are there any fundamental drawbacks/limitations of rasterization as compared to ray-tracing? When I search on the internet, I get vague explanations like rasterization does not provide lighting effects as good as ray-tracing. It means that rasterization can do it, but not as good as ray-tracing. &#xD;&#xA;&#xD;&#xA;However, I'm looking for some cases which rasterization cannot handle at all, but ray-tracing can. I thought rasterization may fail to handle reflections from mirror or water surfaces, but [I found out that there are techniques to handle these in rasterization][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/a/4589/16664" ContentLicense="CC BY-SA 4.0" />
  <row Id="33060" PostHistoryTypeId="1" PostId="10961" RevisionGUID="de48cfce-bc2c-4df2-88e9-384e4a756f1b" CreationDate="2021-06-12T03:01:36.750" UserId="16664" Text="Fundamental drawbacks of rasterization over ray tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="33061" PostHistoryTypeId="3" PostId="10961" RevisionGUID="de48cfce-bc2c-4df2-88e9-384e4a756f1b" CreationDate="2021-06-12T03:01:36.750" UserId="16664" Text="|raytracing|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33062" PostHistoryTypeId="2" PostId="10962" RevisionGUID="12a9bd68-f1ce-4d7d-a0c4-14330fa0679b" CreationDate="2021-06-12T08:02:23.020" UserId="38" Text="It is generally not so much about the fact  that rasterisation couldn't do the things. It probably could, but it would most likely need several rendering passes and all kinds of dirty tricks to accomplish things that depend on nonlocal effects.&#xD;&#xA;&#xD;&#xA;Its simply easier to think in terms of allong path of a ray than  per layer of total effect. Meaning its also easier to implement. Tracing is also significantly faster than multiple layers of rerendering of the scene once complexity needs become high enough.&#xD;&#xA;&#xD;&#xA;But obviously theres no thing that you technically could not do with rasterisation because its essentially just a different way of doing the same thing. Its just that some things are not feasible." ContentLicense="CC BY-SA 4.0" />
  <row Id="33063" PostHistoryTypeId="5" PostId="10962" RevisionGUID="94b5db4f-5075-4c90-9555-baf0f48c4ead" CreationDate="2021-06-12T09:55:52.207" UserId="38" Comment="added 9 characters in body" Text="It is generally not so much about the fact  that rasterisation couldn't do the things. It probably could, but it would most likely need several rendering passes and all kinds of dirty tricks to accomplish things that depend on nonlocal effects.&#xD;&#xA;&#xD;&#xA;Its simply easier to think in terms of allong path of a ray than  per layer of total effect. Meaning its also easier to implement. Tracing is also significantly faster than multiple layers of rerendering of the scene once complexity needs become high enough.&#xD;&#xA;&#xD;&#xA;But obviously theres no thing that you technically could not do with rasterisation because its essentially just a different way of doing the same thing. Its just that some things are not feasible that way." ContentLicense="CC BY-SA 4.0" />
  <row Id="33064" PostHistoryTypeId="2" PostId="10963" RevisionGUID="660fc9a3-c31b-4531-b3f9-1f45ac438ddd" CreationDate="2021-06-12T13:30:20.697" UserId="10096" Text="Raserization is based on the idea of projecting some primitives (e.g. triangles, line segments, points, quads, maybe even some curved surfaces like bezier patches) on the screen and then rasterizing those in 2D (the rasterization is the discretisation step of the otherwise continuous primitive). For a certain class of primitives (e.g. triangles) a perspective or an orthographic projection is cheap to compute, as is the subsequent rasterization step (additionally there is specialized hardware for that in GPUs), which explains the popularity of rasterization in the early days of real-time computer graphics. Note that ray-tracing is quite old too however, as [Appel's paper][1] dates back to 1968, albeit the idea can be traced to long before that.&#xD;&#xA;&#xD;&#xA;This projection and rasterization step already impose some constraints such as the admissible camera model (although with much effort those [may be relaxed somewhat][2]). In contrast in ray-tracing one can pick an arbitrary camera model, with potentially a curved film and a whole sequence of lenses (a camera may even be a sphere or a mesh). Also the aperture can be modeled trivially in ray-tracing, achieving effects such as depth of field with ease, which is not the case for rasterization (even though some hacks may be employed). Furthermore, ray-tracing can work rather naturally with acceleration structures such as bvh and kd-trees, while this is not as natural for rasterization (albeit feasible in some sense).&#xD;&#xA;&#xD;&#xA;Additionally, the class of primitives that can be intersected with a ray is much larger than the class of primitives that can be projected easily on the film (e.g. fractals can be ray-marched against, as well as other implicit surfaces). Furthermore, volumes can be marched through with a ray, achieving realistic participating media effects, which is much harder to do with rasterization. Following this, refraction and transparency are trivial in ray-tracing, while quite problematic (and even expensive) with rasterization.&#xD;&#xA;&#xD;&#xA;The restrictions listed above are by no means complete, and those were only concerning what one would consider primary rays/direct visibility effects (somewhat arguable what lens systems, volumetric, transparency, and refraction effects should be classified as however). &#xD;&#xA;&#xD;&#xA;When we get to lighting, the restrictions are even more severe, as most of real-time rasterized computer graphics rely on what's known as the [Utah approximation][3] (see Section 3). The Utah approximation considers only direct illumination, and ignores indirect illumination (global illumination) effects. The direct illumination considered is rather limited, in the sense that occlusion of light sources is ignored (i.e. no shadows), and the considered light sources are typically Dirac delta lights (those are non-physical) which allow avoiding integration (i.e. point light, directional light, spot light). Various hacks need to be used to put back in some approximations of the removed effects: e.g. shadow maps, ambient occlusion, ambient term, radiance probes, etc. In ray-tracing all of those effects arise rather naturally. This is not surprising, as ray-tracing is used in the modelling of geometric optics: how light is transported in the real world (albeit with some assumptions that do not hold in the real world).&#xD;&#xA;&#xD;&#xA;In conclusion, you can see ray-tracing as a generalization of rasterized 3d graphics, where the latter is used because of efficiency considerations (although it is less efficient for some effects).&#xD;&#xA;&#xD;&#xA;  [1]: https://cg.informatik.uni-freiburg.de/intern/seminar/raytracing_1968_Appel.pdf&#xD;&#xA;  [2]: https://cg.ivd.kit.edu/publications/p2012/3dr/gi2012.pdf&#xD;&#xA;  [3]: http://www.cse.chalmers.se/edu/year/2011/course/TDA361/2007/rend_eq.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="33065" PostHistoryTypeId="52" PostId="10961" RevisionGUID="288b7916-63e9-48db-a177-5fba262d9504" CreationDate="2021-06-12T13:41:09.243" />
  <row Id="33066" PostHistoryTypeId="5" PostId="10963" RevisionGUID="08f821c5-d448-4b97-911c-7533dcef995f" CreationDate="2021-06-12T13:55:05.213" UserId="10096" Comment="added 542 characters in body" Text="Raserization is based on the idea of projecting some primitives (e.g. triangles, line segments, points, quads, maybe even some curved surfaces like bezier patches) on the screen and then rasterizing those in 2D (the rasterization is the discretisation step of the otherwise continuous primitive). For a certain class of primitives (e.g. triangles) a perspective or an orthographic projection is cheap to compute, as is the subsequent rasterization step (additionally there is specialized hardware for that in GPUs), which explains the popularity of rasterization in the early days of real-time computer graphics. Note that ray-tracing is quite old too however, as [Appel's paper][1] dates back to 1968, albeit the idea can be traced to long before that.&#xD;&#xA;&#xD;&#xA;This projection and rasterization step already impose some constraints such as the admissible camera model (although with much effort those [may be relaxed somewhat][2]). In contrast in ray-tracing one can pick an arbitrary camera model, with potentially a curved film and a whole sequence of lenses (a camera may even be a sphere or a mesh). Also the aperture can be modeled trivially in ray-tracing, achieving effects such as depth of field with ease, which is not the case for rasterization (even though some hacks may be employed). Furthermore, ray-tracing can work rather naturally with acceleration structures such as bvh and kd-trees, while this is not as natural for rasterization (albeit feasible in some sense).&#xD;&#xA;&#xD;&#xA;Additionally, the class of primitives that can be intersected with a ray is much larger than the class of primitives that can be projected easily on the film (e.g. fractals can be ray-marched against, as well as other implicit surfaces). Furthermore, volumes can be marched through with a ray, achieving realistic participating media effects, which is much harder to do with rasterization. Following this, refraction and transparency are trivial in ray-tracing, while quite problematic (and even expensive) with rasterization.&#xD;&#xA;&#xD;&#xA;The restrictions listed above are by no means complete, and those were only concerning what one would consider primary rays/direct visibility effects (somewhat arguable what lens systems, volumetric, transparency, and refraction effects should be classified as however). &#xD;&#xA;&#xD;&#xA;When we get to lighting, the restrictions are even more severe, as most of real-time rasterized computer graphics rely on what's known as the [Utah approximation][3] (see Section 3). The Utah approximation considers only direct illumination, and ignores indirect illumination (global illumination) effects. The direct illumination considered is rather limited, in the sense that occlusion of light sources is ignored (i.e. no shadows), and the considered light sources are typically Dirac delta lights (those are non-physical) which allow avoiding integration (i.e. point light, directional light, spot light). Various hacks need to be used to put back in some approximations of the removed effects: e.g. shadow maps, ambient occlusion, ambient term, radiance probes, etc. In ray-tracing all of those effects arise rather naturally. This is not surprising, as ray-tracing is used in the modelling of geometric optics: how light is transported in the real world (albeit with some assumptions that do not hold in the real world).&#xD;&#xA;&#xD;&#xA;In conclusion, you can see ray-tracing as a generalization of rasterized 3d graphics, where the latter is used because of efficiency considerations (although it is less efficient for some effects).&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;That is to say, if the hardware was more powerful, I wouldn't see a reason for using projection based rasterized graphics over ray-tracing. Unfortunately, hardware patents belonging to tech giants lock out potential competitors, which I assume leads to a slower rate of improvement of hardware. Even worse, tech giants have been able to get patents over basic mathematics that clearly do not &quot;belong&quot; to them (e.g. [Image generation using low-discrepancy sequences][4]).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://cg.informatik.uni-freiburg.de/intern/seminar/raytracing_1968_Appel.pdf&#xD;&#xA;  [2]: https://cg.ivd.kit.edu/publications/p2012/3dr/gi2012.pdf&#xD;&#xA;  [3]: http://www.cse.chalmers.se/edu/year/2011/course/TDA361/2007/rend_eq.pdf&#xD;&#xA;  [4]: https://patents.google.com/patent/US7453461B2/en" ContentLicense="CC BY-SA 4.0" />
  <row Id="33067" PostHistoryTypeId="2" PostId="10964" RevisionGUID="4706186f-e078-4511-9a5d-98140438c5f9" CreationDate="2021-06-12T14:59:27.527" UserId="7952" Text="It is probably easier just to write your own projection matrix function, check out this derivation [from the code guru website][1].&#xD;&#xA;&#xD;&#xA;But you can also modify the near plane of an existing projection. There are easier methods of going about it (then the function below) but this one is easier to understand as it makes each step clear (or at least that is my intent):&#xD;&#xA;&#xD;&#xA;    void RecreateProjection( Matrix4x4 &amp;projection, float new_near_distance)&#xD;&#xA;    {&#xD;&#xA;        // extract the current settings&#xD;&#xA;        // NOTE: the array operator here assume matrix[column][row] indexing&#xD;&#xA;		float fovy_rads = atan(1.0f / projection[1][1])) * 2.0f;&#xD;&#xA;		float aspect =  projection[0][0] * (1.0f/projection[1][1]);&#xD;&#xA;		aspect  = 1.0f / aspect;&#xD;&#xA;		float  near = -projection[3][2] / projection[2][2];&#xD;&#xA;		float k = projection[2][2]; &#xD;&#xA;		float far = -(near * k) / (1.0f - k );&#xD;&#xA;&#xD;&#xA;        // Now that we have all the settings for the current projection&#xD;&#xA;        // Just call your favorite projection creation function to get your modified projection&#xD;&#xA;        projection = GenerateProjection( fovy_rads, aspect, new_near_distance, far);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeguru.com/cpp/misc/misc/graphics/article.php/c10123/Deriving-Projection-Matrices.htm#page-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="33068" PostHistoryTypeId="5" PostId="10964" RevisionGUID="f924a3ba-5e6c-45ec-9bff-5c766be0fad4" CreationDate="2021-06-12T15:20:06.570" UserId="7952" Comment="added 121 characters in body" Text="It is probably easier just to write your own projection matrix function, check out this derivation [from the code guru website][1].&#xD;&#xA;&#xD;&#xA;But you can also modify the near plane of an existing projection. There are easier methods of going about it (then the function below) but this one is easier to understand as it makes each step clear (or at least that is my intent):&#xD;&#xA;&#xD;&#xA;It occurs to me that this function assumes a clip volume where zmin=0, zmax=1 and default opengl has zmin=-1 zmax=1.0&#xD;&#xA;&#xD;&#xA;    void RecreateProjection( Matrix4x4 &amp;projection, float new_near_distance)&#xD;&#xA;    {&#xD;&#xA;        // extract the current settings&#xD;&#xA;        // NOTE: the array operator here assume matrix[column][row] indexing&#xD;&#xA;		float fovy_rads = atan(1.0f / projection[1][1])) * 2.0f;&#xD;&#xA;		float aspect =  projection[0][0] * (1.0f/projection[1][1]);&#xD;&#xA;		aspect  = 1.0f / aspect;&#xD;&#xA;		float  near = -projection[3][2] / projection[2][2];&#xD;&#xA;		float k = projection[2][2]; &#xD;&#xA;		float far = -(near * k) / (1.0f - k );&#xD;&#xA;&#xD;&#xA;        // Now that we have all the settings for the current projection&#xD;&#xA;        // Just call your favorite projection creation function to get your modified projection&#xD;&#xA;        projection = GenerateProjection( fovy_rads, aspect, new_near_distance, far);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeguru.com/cpp/misc/misc/graphics/article.php/c10123/Deriving-Projection-Matrices.htm#page-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="33075" PostHistoryTypeId="2" PostId="10967" RevisionGUID="1041f3d5-b000-42d0-8ccd-8213a8ece728" CreationDate="2021-06-12T21:36:42.240" UserId="16677" Text="I am fairly new to CG and 3d art. I'm trying to learn to make good game assets (ie. Low poly count, clean looking) in a cartoon style.&#xD;&#xA;&#xD;&#xA;I'm making this character as pictured. But his eye is a separate mesh. If I want to join it together I need to add extra edges to the whole model that otherwise aren't needed.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For this particular game, the eyes, mouth etc doesn't need any animation.&#xD;&#xA;&#xD;&#xA;My question is, should I find a way to join the eye hemi-sphere to the face mesh, or is it fine just to leave it like this?&#xD;&#xA;&#xD;&#xA;Also I am about to start UV mapping him. Is it best practice to have just one texture file mapped to do all of him, or can i do one material for trousers, another for T-shirt and another for hair for example?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks for any help&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GKVMo.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="33076" PostHistoryTypeId="1" PostId="10967" RevisionGUID="1041f3d5-b000-42d0-8ccd-8213a8ece728" CreationDate="2021-06-12T21:36:42.240" UserId="16677" Text="Character Creation. Cartoon look, Eyes and Extra Parts. Should I ensure it is all one mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33077" PostHistoryTypeId="3" PostId="10967" RevisionGUID="1041f3d5-b000-42d0-8ccd-8213a8ece728" CreationDate="2021-06-12T21:36:42.240" UserId="16677" Text="|texture|uv-mapping|model|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33078" PostHistoryTypeId="5" PostId="10963" RevisionGUID="7151bffd-1398-4294-8b2a-941fa0537caa" CreationDate="2021-06-12T22:52:17.490" UserId="6968" Comment="Spelling typos corrected" Text="Rasterization is based on the idea of projecting various primitives (e.g. triangles, line segments, points, quads, maybe even some curved surfaces like bezier patches) on the screen and then rasterizing those in 2D (the rasterization is the discretisation step of the otherwise continuous primitive). For a certain class of primitives (e.g. triangles) a perspective or an orthographic projection is cheap to compute, as is the subsequent rasterization step (additionally there is specialized hardware for that in GPUs), which explains the popularity of rasterization in the early days of real-time computer graphics. Note that ray-tracing is quite old too however, as [Appel's paper][1] dates back to 1968, albeit the idea can be traced to long before that. &#xD;&#xA;&#xD;&#xA;This projection and rasterization step already impose some constraints such as the admissible camera model (although with much effort those [may be relaxed somewhat][2]). In contrast in ray-tracing one can pick an arbitrary camera model, with potentially a curved film and a whole sequence of lenses (a camera may even be a sphere or a mesh). Also the aperture can be modeled trivially in ray-tracing, achieving effects such as depth of field with ease, which is not the case for rasterization (even though some hacks may be employed). Furthermore, ray-tracing can work rather naturally with acceleration structures such as bvh and kd-trees, while this is not as natural for rasterization (albeit feasible in some sense).&#xD;&#xA;&#xD;&#xA;Additionally, the class of primitives that can be intersected with a ray is much larger than the class of primitives that can be projected easily on the film (e.g. fractals can be ray-marched against, as well as other implicit surfaces). Furthermore, volumes can be marched through with a ray, achieving realistic participating media effects, which is much harder to do with rasterization. Following this, refraction and transparency are trivial in ray-tracing, while quite problematic (and even expensive) with rasterization. &#xD;&#xA;&#xD;&#xA;The restrictions listed above are by no means complete, and those were only concerning what one would consider primary rays/direct visibility effects (somewhat arguable what lens systems, volumetric, transparency, and refraction effects should be classified as however).&#xD;&#xA;&#xD;&#xA;When we get to lighting, the restrictions are even more severe, as most of real-time rasterized computer graphics rely on what's known as the [Utah approximation][3] (see Section 3). The Utah approximation considers only direct illumination, and ignores indirect illumination (global illumination) effects. The direct illumination considered is rather limited, in the sense that occlusion of light sources is ignored (i.e. no shadows), and the considered light sources are typically Dirac delta lights (those are non-physical) which allow avoiding integration (i.e. point light, directional light, spot light). Various hacks need to be used to put back in some approximations of the removed effects: e.g. shadow maps, ambient occlusion, ambient term, radiance probes, etc. In ray-tracing all of those effects arise rather naturally. This is not surprising, as ray-tracing is used in the modelling of geometric optics: how light is transported in the real world (albeit with some assumptions that do not hold in the real world).&#xD;&#xA;&#xD;&#xA;In conclusion, you can see ray-tracing as a generalization of rasterized 3d graphics, where the latter is used because of efficiency considerations (although it is less efficient for some effects).&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;That is to say, if the hardware was more powerful, I wouldn't see a reason for using projection-based rasterized graphics over ray-tracing. Unfortunately, hardware patents belonging to tech giants lock out potential competitors, which I assume leads to a slower rate of improvement of hardware. Even worse, tech giants have been able to get patents over basic mathematics that clearly does not &quot;belong&quot; to them (e.g. [Image generation using low-discrepancy sequences][4]).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://cg.informatik.uni-freiburg.de/intern/seminar/raytracing_1968_Appel.pdf&#xD;&#xA;  [2]: https://cg.ivd.kit.edu/publications/p2012/3dr/gi2012.pdf&#xD;&#xA;  [3]: http://www.cse.chalmers.se/edu/year/2011/course/TDA361/2007/rend_eq.pdf&#xD;&#xA;  [4]: https://patents.google.com/patent/US7453461B2/en" ContentLicense="CC BY-SA 4.0" />
  <row Id="33079" PostHistoryTypeId="24" PostId="10963" RevisionGUID="7151bffd-1398-4294-8b2a-941fa0537caa" CreationDate="2021-06-12T22:52:17.490" Comment="Proposed by 6968 approved by 10096 edit id of 566" ContentLicense="CC BY-SA 4.0" />
  <row Id="33080" PostHistoryTypeId="2" PostId="10968" RevisionGUID="6d4f898d-884b-48ce-9489-d29505861516" CreationDate="2021-06-13T02:14:19.850" UserId="16183" Text="Since we're comparing against ray-tracing, let's assume the argument is restricted to 3D rendering based (at least somewhat) on real physics.&#xD;&#xA;&#xD;&#xA;A comparison of ray-tracing and rasterization at a high level:&#xD;&#xA;&#xD;&#xA;## Ray-tracing:&#xD;&#xA; The foundation is to **replicate the behaviour of the real physical process of imaging/vision**. Namely, the travel and interaction of light. It follows that any effects existing in real imaging (reflection, lighting, diffusion, etc.) can be created in ray-tracing by making the simulation more sophisticated.&#xD;&#xA;&#xD;&#xA;## Rasterization:&#xD;&#xA;The foundation is taking advantages of the *outcomes* of real imaging, under certain idealized circumstances. As a starting point in rasterization, we assume that the environment and resulting image follow certain regular constraints. Building on this assumption, we find a process which **despite not being based on the real physics processes of imaging/vision**, still produces &quot;correct&quot; results within the given constraints. It follows that any effects existing in real imaging *that don't fall nicely in these constraints*, will be difficult or impossible to create correctly with rasterization.&#xD;&#xA;&#xD;&#xA;**What are the constraints?** (note that not everything is necessarily a hard constraint in every rasterization-based renderer, I'm just giving it as a starting point to demonstrate which problems don't play nicely).&#xD;&#xA;&#xD;&#xA; - Any renderable thing can be defined (at least in its bounds) by a primitive shape&#xD;&#xA; - For each object in 3d space (primitives), we can project that form it into the resulting image to create a region, which within, all of that object's image information lies.&#xD;&#xA; - There is a calculable mapping between the points in projection of an object in an image, and the points in the object in 3d space.&#xD;&#xA;&#xD;&#xA;(further constraints in most real systems)&#xD;&#xA; - Primitives in both 3D and image space only consist of polygons, lines and points.&#xD;&#xA; - 3D to screen projection is only usable in perspective matrix or orthographic matrix.&#xD;&#xA; - The mapping between projected points and &quot;real&quot; points is based only on simple linear/bi-linear interpolation.&#xD;&#xA;&#xD;&#xA;As a result, these kinds of effects are difficult to implement accurately:&#xD;&#xA;&#xD;&#xA; - Non-parallel projections such as [stereographic projection][1]&#xD;&#xA; - Projections which create an effective &quot;field of view&quot; that spans near or greater than 180 degrees.&#xD;&#xA; - Non-local visual effects, where the visual information in a point of the image is not only determined by objects which project to that point.&#xD;&#xA;   - Lighting and shadows&#xD;&#xA;   - Reflections&#xD;&#xA; - Non-planar surfaces (bumpy, etc.)&#xD;&#xA; - Other effects resulting in non-linear path of light such as refraction.&#xD;&#xA;&#xD;&#xA;These effects aren't necessarily impossible, and most have well known approximation methods in rasterization-based rendering. These approximations don't necessarily use &quot;rasterization&quot; per-se, they may just happen to be compatible with it, and usually still within considerable constraints.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Stereographic_projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="33083" PostHistoryTypeId="50" PostId="10235" RevisionGUID="a2a29d5b-2476-4fb4-9322-7df22cb37cfb" CreationDate="2021-06-14T03:01:45.140" UserId="-1" />
  <row Id="33084" PostHistoryTypeId="5" PostId="10967" RevisionGUID="740c81a6-fa2d-4090-ae80-aa5bf811e680" CreationDate="2021-06-14T16:33:49.347" UserId="16677" Comment="deleted 186 characters in body; edited title" Text="I am fairly new to CG and 3d art. I'm trying to learn to make good game assets (ie. Low poly count, clean looking) in a cartoon style.&#xD;&#xA;&#xD;&#xA;I'm making this character as pictured. But his eye is a separate mesh. If I want to join it together I need to add extra edges to the whole model that otherwise aren't needed.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For this particular game, the eyes, mouth etc doesn't need any animation.&#xD;&#xA;&#xD;&#xA;My question is, are there any advantages to finding a way to join the eye hemi-sphere to the face mesh, or is it fine just to leave it like this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks for any help&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GKVMo.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="33085" PostHistoryTypeId="4" PostId="10967" RevisionGUID="740c81a6-fa2d-4090-ae80-aa5bf811e680" CreationDate="2021-06-14T16:33:49.347" UserId="16677" Comment="deleted 186 characters in body; edited title" Text="Character Creation. Cartoon look, Eyes and Extra Parts. What advantages are the combining to one mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33086" PostHistoryTypeId="2" PostId="10969" RevisionGUID="6c51379c-59a9-4ad1-89b2-2778470ce331" CreationDate="2021-06-15T15:40:00.597" UserId="16126" Text="Let's say I want to pass some kind of value to a pixel shader in HLSL. I can either make a cbuffer and pass the value directly to the pixel shader, or I can make a cbuffer in the vertex shader and pass the value into the pixel shader through the vertex shader output. What is the difference between these two methods and in which scenario is it better to use one or the other? Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="33087" PostHistoryTypeId="1" PostId="10969" RevisionGUID="6c51379c-59a9-4ad1-89b2-2778470ce331" CreationDate="2021-06-15T15:40:00.597" UserId="16126" Text="Passing variable through cbuffer vs. shader input in HLSL" ContentLicense="CC BY-SA 4.0" />
  <row Id="33088" PostHistoryTypeId="3" PostId="10969" RevisionGUID="6c51379c-59a9-4ad1-89b2-2778470ce331" CreationDate="2021-06-15T15:40:00.597" UserId="16126" Text="|shader|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33089" PostHistoryTypeId="2" PostId="10970" RevisionGUID="29658b63-b090-4c14-9ef4-c74e814c7b13" CreationDate="2021-06-15T17:00:35.380" UserId="16696" Text="I've watched a few videos about raytracing vs pathtracing, and one thing that consistently pops up is the idea that pathtracing seems to be able to do global illumination, whilst raytracing is not. &#xD;&#xA;Here's an example of what I mean (timestamp linked):&#xD;&#xA;https://youtu.be/LAsnQoBUG4Q?t=320&#xD;&#xA;&#xD;&#xA;If the rays in Raytracing still bounces, why does it not create Global Illumination like Pathtracing does?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33090" PostHistoryTypeId="1" PostId="10970" RevisionGUID="29658b63-b090-4c14-9ef4-c74e814c7b13" CreationDate="2021-06-15T17:00:35.380" UserId="16696" Text="Can someone explain why raytracing isn't able to make Global Illumination?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33091" PostHistoryTypeId="3" PostId="10970" RevisionGUID="29658b63-b090-4c14-9ef4-c74e814c7b13" CreationDate="2021-06-15T17:00:35.380" UserId="16696" Text="|raytracing|pathtracing|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33092" PostHistoryTypeId="2" PostId="10971" RevisionGUID="1425abff-444f-455a-938b-2b457cf722b9" CreationDate="2021-06-15T19:44:55.067" UserId="13321" Text="From the ray tracing wikipedia page https://en.wikipedia.org/wiki/Ray_tracing_(graphics):&#xD;&#xA;&#xD;&#xA;&quot;Path tracing is a form of ray tracing that can produce soft shadows, depth of field, motion blur, caustics, ambient occlusion, and indirect lighting.&quot;&#xD;&#xA;&#xD;&#xA;So a path tracer is a ray tracer, but not all ray tracers are path tracers." ContentLicense="CC BY-SA 4.0" />
  <row Id="33094" PostHistoryTypeId="2" PostId="10972" RevisionGUID="d9741337-94f8-44f5-9418-0db050be442c" CreationDate="2021-06-16T02:26:28.257" UserId="16699" Text="What is an efficient way to calculate the volume of intersection of two arbitrary volumes described as closed surfaces? That is, with two meshes, A and B, how do I calculate the intersection of A and B? Is Sutherland Hodgman clipping applicable to arbitrary 3D volumes?&#xD;&#xA;&#xD;&#xA;To be clear, the volumes in question are not necessarily simple, nor are they necessarily convex. Some could be described as parametric equations, others not so much." ContentLicense="CC BY-SA 4.0" />
  <row Id="33095" PostHistoryTypeId="1" PostId="10972" RevisionGUID="d9741337-94f8-44f5-9418-0db050be442c" CreationDate="2021-06-16T02:26:28.257" UserId="16699" Text="Calculating the intersection of two volumes" ContentLicense="CC BY-SA 4.0" />
  <row Id="33096" PostHistoryTypeId="3" PostId="10972" RevisionGUID="d9741337-94f8-44f5-9418-0db050be442c" CreationDate="2021-06-16T02:26:28.257" UserId="16699" Text="|opengl|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33097" PostHistoryTypeId="2" PostId="10973" RevisionGUID="6442caf9-0bcb-4f59-a1c7-12da9c5a87fd" CreationDate="2021-06-16T05:54:25.103" UserId="6046" Text="This question is the result of the modern era using the blanket word ray-tracing to denote every similar technique as it's based off of it. Just wanted to give a more historical answer if anybody is interested.&#xD;&#xA;&#xD;&#xA;As lightxbulb said, historically, Turner Whitted was the first person to come up with the raytracing technique but it only had a limited number of rays. Reflection/Refraction and these secondary rays got terminated when they hit a diffuse surface since no GI rays were shot. &#xD;&#xA;&#xD;&#xA;The problem of Global Illumination is recursive and as you might've guessed it requires many many rays. The math wasn't that complex and sophisticated in pure raytracing. Then later on, [Radiosity][1] method was introduced by Goral which accounted for GI but only for diffuse surfaces using the Finite element method. This was a major step ahead and helped in laying the foundation for pathtracing.&#xD;&#xA;&#xD;&#xA;After that Pathtracing got introduced by Kajiya which accounted for all types of surfaces, He used Monte-Carlo Integration to solve the recursive integral related to the GI problem.&#xD;&#xA;&#xD;&#xA;As time went by, the word raytracing somehow overshadowed the other words in this field. And recently, with NVIDIA dishing out their RTX technology pretty much sealed the fact. So raytracing in today's era doesn't necessarily mean whitted-style raytracing which was the original raytracing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Radiosity_(computer_graphics)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33098" PostHistoryTypeId="2" PostId="10974" RevisionGUID="6275fa53-0780-45a5-ba2f-2c8ec1d87ef9" CreationDate="2021-06-16T11:23:09.747" UserId="16702" Text="Let's suppose that we have a light source. Which of the following are correct for the tree of recursive ray-tracing (ray tree) that create when we make the colors for each pixel in the screen. Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) if scene contains of one non-convex polyhedron (random shape and position) then we can't have a bound for the height of tree in general. (Even the camera is outside of object)&#xD;&#xA;&#xD;&#xA;b) if scene contains of two convex polyhedrons then the height of tree can be at most 2 independent of the position of camera and the position of objects (the camera is outside two objects)&#xD;&#xA;&#xD;&#xA;c) if scene contains of two non-convex polyhedrons (random shape and position) then we can't have a bound for the height of tree in general. (Even the camera is outside of object)&#xD;&#xA;&#xD;&#xA;d) if scene contains of one convex polyhedron then the height of tree can be at most 1 independent of the position of camera and the position of objects (the camera is outside of object)&#xD;&#xA;&#xD;&#xA;e) if scene contains of one non-convex polyhedron then the height of tree can be at most 1 independent of the position of camera and the position of object (the camera is outside of object)&#xD;&#xA;&#xD;&#xA;My thoughts are the following:&#xD;&#xA;&#xD;&#xA;if a ray R1 inserts into a convex polyhedron object from front then always leave from the back another ray R2.So for convex objects i believe that we can define a height for the tree.&#xD;&#xA;&#xD;&#xA;if the object is non-convex then we can have multiple different rays that insert and leave in the object. Because there are parts of object that if we get a line are not all in this object. So can we define as upper bound the number of vertices (or something else) of the object as the maximum number of possible rays ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33099" PostHistoryTypeId="1" PostId="10974" RevisionGUID="6275fa53-0780-45a5-ba2f-2c8ec1d87ef9" CreationDate="2021-06-16T11:23:09.747" UserId="16702" Text="Ray tracing tree" ContentLicense="CC BY-SA 4.0" />
  <row Id="33100" PostHistoryTypeId="3" PostId="10974" RevisionGUID="6275fa53-0780-45a5-ba2f-2c8ec1d87ef9" CreationDate="2021-06-16T11:23:09.747" UserId="16702" Text="|raytracing|rendering|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33104" PostHistoryTypeId="5" PostId="10960" RevisionGUID="08bf1e29-7336-40a0-9dc8-2ffd497aa575" CreationDate="2021-06-16T11:52:46.600" UserId="7952" Comment="Added info on extracting azimuth/elevation from a vector, updating camera, and camera following." Text="The velocity vector becomes your forward vector, just normalize it. The up direction doesn't change, use whatever version up the camera usually uses. The last vector (call it the &quot;right hand&quot; vector) is the cross product of up, and forward. Then, do a second cross with the forward vector and the right hand vector to guarantee an orthonormal basis.&#xD;&#xA;&#xD;&#xA;The last  bit needed is the translation which will have to come from somewhere.&#xD;&#xA;&#xD;&#xA;The exact ordering of all the operations is going to depend on the setup you are using. Is up direction y or z ect.&#xD;&#xA;&#xD;&#xA;Once the matrix if formed, find its inverse. (Since you went through the trouble of making sure it is orthonormal, the inverse is equivalent to the transpose.)&#xD;&#xA;&#xD;&#xA;This is the new view matrix.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;When dealing with Azimuth and Elevation you can extract the angles from a vector using the geometric asin and acos functions. For example:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;    vec3d fwd = target_point - camera_point; // generate a vector somehow&#xD;&#xA;    fwd = normalize(fwd); // normalize it&#xD;&#xA;    float azimuth = acos( fwd.x );&#xD;&#xA;    float elevation = asin( fwd.y );  // extract angles&#xD;&#xA;    if( fwd.z &lt; 0 ) { elevation = -elevation; } // fix quadrant based sgn(z)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The above assumes that y is the up axis, and that azimuth/elevation are given in radians.&#xD;&#xA;&#xD;&#xA;Now that the look direction is decided. Save it off to the side, and begin turning the camera. A good approach to turning the camera is to have a &quot;radians per a second&quot; turn rate. Get the time delta between updates from the system. And use those values to compute how much the camera should turn each frame just by computing the total number of radians that is needed for each direction.&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;    float time_delta_in_seconds = elapsed_seconds_since_last_frame();&#xD;&#xA;    const float radians_per_second = 0.1; // slowish&#xD;&#xA;    float turn_amount = time_delta_in_seconds * radians_per_second;&#xD;&#xA;    float turn_amount = min(radians_to_turn, turn_amount); // don't overlook&#xD;&#xA;    radians_to_turn -= turn_amount; // update  - converges on zero&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So each frame:&#xD;&#xA;&#xD;&#xA; 1. update the velocity vector&#xD;&#xA; 2. compute the new camera settings but don't use them, save them&#xD;&#xA; 3. compute your camera turn amount and update the camera with the new values&#xD;&#xA;&#xD;&#xA; Make the 3 steps independent and the camera will just keep turning, chasing the velocity vector. &#xD;&#xA;&#xD;&#xA;Handling user intervention seems self evident, if the user turns the camera disable the auto camera turning. If you want the camera to start turning after some preset amount of time, then just set a timer that enables auto turning and reset it every time the user moves the camera.&#xD;&#xA;&#xD;&#xA;While this isn't the best system for auto camera following, it works and should (hopefully) get you going. The camera turning will be very mechanical since the turn rate is fixed. But once its all set its not to hard to add acceleration using the same ideas.&#xD;&#xA;&#xD;&#xA;It just occurred to me that this is like 3 separate questions in one, really these should have been asked separately. At any rate, this should help some I hope." ContentLicense="CC BY-SA 4.0" />
  <row Id="33107" PostHistoryTypeId="5" PostId="10960" RevisionGUID="111a0519-5c13-4755-b930-968e83a293c2" CreationDate="2021-06-17T11:22:37.937" UserId="7952" Comment="edited body" Text="The velocity vector becomes your forward vector, just normalize it. The up direction doesn't change, use whatever version up the camera usually uses. The last vector (call it the &quot;right hand&quot; vector) is the cross product of up, and forward. Then, do a second cross with the forward vector and the right hand vector to guarantee an orthonormal basis.&#xD;&#xA;&#xD;&#xA;The last  bit needed is the translation which will have to come from somewhere.&#xD;&#xA;&#xD;&#xA;The exact ordering of all the operations is going to depend on the setup you are using. Is up direction y or z ect.&#xD;&#xA;&#xD;&#xA;Once the matrix if formed, find its inverse. (Since you went through the trouble of making sure it is orthonormal, the inverse is equivalent to the transpose.)&#xD;&#xA;&#xD;&#xA;This is the new view matrix.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;When dealing with Azimuth and Elevation you can extract the angles from a vector using the geometric asin and acos functions. For example:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;    vec3d fwd = target_point - camera_point; // generate a vector somehow&#xD;&#xA;    fwd = normalize(fwd); // normalize it&#xD;&#xA;    float azimuth = acos( fwd.x );&#xD;&#xA;    float elevation = asin( fwd.y );  // extract angles&#xD;&#xA;    if( fwd.z &lt; 0 ) { elevation = -elevation; } // fix quadrant based sgn(z)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The above assumes that z is the up axis, and that azimuth/elevation are given in radians.&#xD;&#xA;&#xD;&#xA;Now that the look direction is decided. Save it off to the side, and begin turning the camera. A good approach to turning the camera is to have a &quot;radians per a second&quot; turn rate. Get the time delta between updates from the system. And use those values to compute how much the camera should turn each frame just by computing the total number of radians that is needed for each direction.&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;    float time_delta_in_seconds = elapsed_seconds_since_last_frame();&#xD;&#xA;    const float radians_per_second = 0.1; // slowish&#xD;&#xA;    float turn_amount = time_delta_in_seconds * radians_per_second;&#xD;&#xA;    float turn_amount = min(radians_to_turn, turn_amount); // don't overlook&#xD;&#xA;    radians_to_turn -= turn_amount; // update  - converges on zero&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So each frame:&#xD;&#xA;&#xD;&#xA; 1. update the velocity vector&#xD;&#xA; 2. compute the new camera settings but don't use them, save them&#xD;&#xA; 3. compute your camera turn amount and update the camera with the new values&#xD;&#xA;&#xD;&#xA; Make the 3 steps independent and the camera will just keep turning, chasing the velocity vector. &#xD;&#xA;&#xD;&#xA;Handling user intervention seems self evident, if the user turns the camera disable the auto camera turning. If you want the camera to start turning after some preset amount of time, then just set a timer that enables auto turning and reset it every time the user moves the camera.&#xD;&#xA;&#xD;&#xA;While this isn't the best system for auto camera following, it works and should (hopefully) get you going. The camera turning will be very mechanical since the turn rate is fixed. But once its all set its not to hard to add acceleration using the same ideas.&#xD;&#xA;&#xD;&#xA;It just occurred to me that this is like 3 separate questions in one, really these should have been asked separately. At any rate, this should help some I hope." ContentLicense="CC BY-SA 4.0" />
  <row Id="33108" PostHistoryTypeId="2" PostId="10976" RevisionGUID="82c8e71e-8818-4884-8e01-4584effb3102" CreationDate="2021-06-18T06:32:36.120" UserId="10212" Text="As [this question and its answers point out][1], projecting a sphere on a flat picture plane may result in a ellipse, not a circle, and my understanding is that the only way a sphere can be projected as a circle is when its center perfectly align with the center of vision, in other words, when the viewer's eye or the camera is oriented so that the sphere is smack-dab at the center of the rendered image. But in pretty much all 3D programs imaginable out there, the image of a sphere is always a circle, not matter where the sphere is in the image, left, right, top, bottom. The only time a sphere looks stretched is when it exceeds the bound of the image.&#xD;&#xA;&#xD;&#xA;So my question is: how does 3D graphic software adjust for distortion (such as a sphere being projected as an ellipse)? What are the possible different solutions for minimize distortion when you're working on a scene (for example, through a viewport, when you're placing objects, modeling, simulating, etc.) as opposed to when you render (in which case, factors such as the camera's sensor size, focal length, etc. are taken into consideration)? Is it possible that 3D software doesn't actually project image onto a picture plane, but some sort of picture sphere instead, which I figure will cause no distortion? And does the way 3D graphic software adjusts for distortion relate to how real-life camera adjust?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/1493/does-a-sphere-projected-into-2d-space-always-result-in-an-ellipse" ContentLicense="CC BY-SA 4.0" />
  <row Id="33109" PostHistoryTypeId="1" PostId="10976" RevisionGUID="82c8e71e-8818-4884-8e01-4584effb3102" CreationDate="2021-06-18T06:32:36.120" UserId="10212" Text="How does 3D graphic software adjust for distortion inherent in perspective projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33110" PostHistoryTypeId="3" PostId="10976" RevisionGUID="82c8e71e-8818-4884-8e01-4584effb3102" CreationDate="2021-06-18T06:32:36.120" UserId="10212" Text="|3d|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33116" PostHistoryTypeId="2" PostId="10978" RevisionGUID="468d7d7c-a8ba-4363-a594-8f56791d00c1" CreationDate="2021-06-18T21:54:07.327" UserId="38" Text="It does project but does so with a parallel projection. In most cases a orthographic view. Although other parallel projections are possible too like dimetric, trimetric and so on... &#xD;&#xA;&#xD;&#xA;What is common to all of these is that there is no perspective. Your question obviously only applies to perspective projections. And only super noticable with wide lenses. But essentially lack of perspective means that the projected shape of the circle is constant (not necceserily round, if thats what the projction intends but same across the field). So in essence it was never distirted to begin with." ContentLicense="CC BY-SA 4.0" />
  <row Id="33117" PostHistoryTypeId="5" PostId="10978" RevisionGUID="264e04f2-d656-41d9-be98-8e1893a7b046" CreationDate="2021-06-18T22:00:02.347" UserId="38" Comment="added 417 characters in body" Text="It does project but does so with a parallel projection. In most cases a orthographic view. Although other parallel projections are possible too like dimetric, trimetric and so on... &#xD;&#xA;&#xD;&#xA;What is common to all of these is that there is no perspective. Your question obviously only applies to perspective projections. And only super noticable with wide lenses. But essentially lack of perspective means that the projected shape of the circle is constant (not necceserily round, if thats what the projection intends but same across the field). So in essence it was never distorted to begin with.&#xD;&#xA;&#xD;&#xA;Yes many programs show orthographical views when designing, since that is useful. Ideed 3D objects were designed with orthographic projections way before computers existed let alone 3D geraphics software. The draftsman would draw manually the orthographic projection into the technical drawing (which you call a blueprint. Because the replication technology in mid 1800's. But these drawings exsisted before that)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33118" PostHistoryTypeId="5" PostId="10976" RevisionGUID="6f8b34b6-0269-427b-ae5f-ac8c667a6a50" CreationDate="2021-06-19T02:03:17.860" UserId="10212" Comment="added 33 characters in body" Text="As [this question and its answers point out][1], projecting a sphere on a flat picture plane, with **perspective projection**, may result in a ellipse, not a circle, and my understanding is that the only way a sphere can be projected as a circle is when its center perfectly align with the center of vision, in other words, when the viewer's eye or the camera is oriented so that the sphere is smack-dab at the center of the rendered image. But in pretty much all 3D programs imaginable out there, the image of a sphere is always a circle, not matter where the sphere is in the image, left, right, top, bottom. The only time a sphere looks stretched is when it exceeds the bound of the image.&#xD;&#xA;&#xD;&#xA;So my question is: how does 3D graphic software adjust for distortion (such as a sphere being projected as an ellipse)? What are the possible different solutions for minimize distortion when you're working on a scene (for example, through a viewport, when you're placing objects, modeling, simulating, etc.) as opposed to when you render (in which case, factors such as the camera's sensor size, focal length, etc. are taken into consideration)? Is it possible that 3D software doesn't actually project image onto a picture plane, but some sort of picture sphere instead, which I figure will cause no distortion? And does the way 3D graphic software adjusts for distortion relate to how real-life camera adjust?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/1493/does-a-sphere-projected-into-2d-space-always-result-in-an-ellipse" ContentLicense="CC BY-SA 4.0" />
  <row Id="33119" PostHistoryTypeId="12" PostId="10978" RevisionGUID="9bff6954-82a6-4294-845c-706e0bfd0ec2" CreationDate="2021-06-19T08:54:09.960" UserId="38" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;}]}" />
  <row Id="33120" PostHistoryTypeId="5" PostId="10978" RevisionGUID="250461a9-e6e8-4e52-a863-e1b3f05a3d2a" CreationDate="2021-06-19T09:29:05.743" UserId="38" Comment="deleted 83 characters in body" Text="They dont. The distortion of a perfect pinhole camera at any smaller view angle is really minimal. Whether the projection plane is flat or spherical does not matter.&#xD;&#xA;&#xD;&#xA;It is vey unlikely that any nonspecialized software would do a spherical projection since you cant do that with homogenous coordinates that form the basis of most 3D engines that dont rely on software implementation or raytracing.&#xD;&#xA;&#xD;&#xA; Normally the human brain constructs a corrected model of the world. Your brain simply corrects ovals as a circle as long as the perspective is within the ballpark of what people experience normally. &#xD;&#xA;&#xD;&#xA;(We had a discussion on orthographic views. People who do  CAD work get used to seing in orthographic very quickly.  But beginners actually see a reverse illusion of what is there when rotating the view. So beginners often experience orthographic as having upside down perspective untill their brain adjusts its model)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33121" PostHistoryTypeId="13" PostId="10978" RevisionGUID="ecaabfdf-7057-4e1c-85f7-d22ec96593d3" CreationDate="2021-06-19T09:29:11.757" UserId="38" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;}]}" />
  <row Id="33122" PostHistoryTypeId="5" PostId="10978" RevisionGUID="9db30a9e-d593-4db7-a165-7402a4d83bbb" CreationDate="2021-06-19T09:51:58.333" UserId="38" Comment="added 1 character in body" Text="They dont. The distortion of a perfect pinhole camera at any smaller view angle is really minimal. Whether the projection plane is flat or spherical does not matter.&#xD;&#xA;&#xD;&#xA;It is vey unlikely that any nonspecialized software would do a spherical projection since you cant do that with homogeneous coordinates that form the basis of most 3D engines that dont rely on software implementation or raytracing.&#xD;&#xA;&#xD;&#xA; Normally the human brain constructs a corrected model of the world. Your brain simply corrects ovals as a circle as long as the perspective is within the ballpark of what people experience normally. &#xD;&#xA;&#xD;&#xA;(We had a discussion on orthographic views. People who do  modeling work get used to seeing in orthographic very quickly.  But beginners actually see a reverse illusion of what is there when rotating the view. So beginners often experience orthographic as having upside down perspective untill their brain adjusts its model)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33123" PostHistoryTypeId="2" PostId="10979" RevisionGUID="1492cd24-d77f-43e1-8479-f45e3ea3d157" CreationDate="2021-06-19T18:48:45.800" UserId="9581" Text="I spawn a camera in a scene using random coordinates for `x` and `y` and setting `z=0` and orient the camera so that it looks on the point (0, 0, 0). My goal is to move the camera forward using randomly-generated velocity vectors on the ground (so `z` stays `0`). I want to ensure that the new position of the camera is within a valid range after moving it forward, defined in degrees with respect to the current focus point/direction. More specifically, the way I determine &quot;valid range&quot; is by ensuring that the new position is within 45 degrees of the old camera's focus point (-45 degrees to the left and +45 degrees to the right). Can someone write a pseudocode on how I can achieve this?&#xD;&#xA;&#xD;&#xA;Here's my attempt to do this but this doesn't seem to be the correct way to help me achieve what I want:&#xD;&#xA;&#xD;&#xA;    camera_dir = (0, 0, 0) - current_cam_pos&#xD;&#xA;    while True:&#xD;&#xA;        vel_vec=[uniform(-max_vel, max_vel), uniform(-max_vel, max_vel)] # generate a random velocity vector&#xD;&#xA;        new_pos = camera_dir + vel_vec # compute a new position (and camera direction vector) for the camera&#xD;&#xA;        if (compute_angle(new_pos, camera_dir) &lt; 45 or compute_angle(new_pos, camera_dir) &gt; 315):&#xD;&#xA;            break " ContentLicense="CC BY-SA 4.0" />
  <row Id="33124" PostHistoryTypeId="1" PostId="10979" RevisionGUID="1492cd24-d77f-43e1-8479-f45e3ea3d157" CreationDate="2021-06-19T18:48:45.800" UserId="9581" Text="How to ensure that a randomly-generated velocity vectors moves the camera forward within a valid arc?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33125" PostHistoryTypeId="3" PostId="10979" RevisionGUID="1492cd24-d77f-43e1-8479-f45e3ea3d157" CreationDate="2021-06-19T18:48:45.800" UserId="9581" Text="|3d|2d|camera|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33126" PostHistoryTypeId="50" PostId="10248" RevisionGUID="4b51c649-b970-44b4-8218-dbb87bcbcfbb" CreationDate="2021-06-19T20:09:35.913" UserId="-1" />
  <row Id="33127" PostHistoryTypeId="4" PostId="10979" RevisionGUID="3f0a0f2d-ef98-4d6b-a9c3-eb2d6f166419" CreationDate="2021-06-19T20:18:58.117" UserId="9581" Comment="edited title" Text="How to ensure that a randomly-generated velocity vector moves the camera forward within a valid arc?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33132" PostHistoryTypeId="2" PostId="10981" RevisionGUID="fdc2ab98-3973-4f56-9940-7a11c01b4f56" CreationDate="2021-06-21T00:18:24.940" UserId="506" Text="Something like this should work:&#xD;&#xA;&#xD;&#xA;    forward_direction = normalize(-current_cam_pos)&#xD;&#xA;    right_direction = (forward_direction.y, -forward_direction.x, 0)&#xD;&#xA;    angle = uniform(-pi/4, pi/4)&#xD;&#xA;    new_direction = (cos(angle) * forward) + (sin(angle) * right)&#xD;&#xA;    new_pos = new_direction * how_far_you_want_to_move&#xD;&#xA;&#xD;&#xA;Some notes:&#xD;&#xA;- The `normalize` will blow up due to a division by 0 if your camera position is ever (0,0,0), so you may want to check for that case and use a default direction value instead.&#xD;&#xA;- This also gets more complicated if your camera moves in Z: the (y, -x) trick for picking `right_direction` only works in a 2D plane.&#xD;&#xA;- This doesn’t take care of aiming the camera back at the origin, since your sample code doesn’t mention how that works in your system, so after one move you’ll need to re-do that for the `forward_direction` (or `camera_dir` in your example) calculation to be correct." ContentLicense="CC BY-SA 4.0" />
  <row Id="33133" PostHistoryTypeId="2" PostId="10982" RevisionGUID="8ca7779d-1b7f-4c73-b3e6-b2e5e07ae3af" CreationDate="2021-06-21T20:03:02.563" UserId="16729" Text="I am new to CG and I need to draw a wall clock using bresenhams circle algo . I have drawn a circle using this algo but how do I add minute and hour needle in it basically how do i add lines inside a circle ? I am using C language to code. Below is the code that i am using to draw a circle by this algo &#xD;&#xA;#include &lt;graphics.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;conio.h&gt;&#xD;&#xA;#include &lt;math.h&gt;&#xD;&#xA;&#xD;&#xA;    void    EightWaySymmetricPlot(int xc,int yc,int x,int y)&#xD;&#xA;   {&#xD;&#xA;    putpixel(x+xc,y+yc,RED);&#xD;&#xA;    putpixel(x+xc,-y+yc,RED);&#xD;&#xA;    putpixel(-x+xc,-y+yc,RED);&#xD;&#xA;    putpixel(-x+xc,y+yc,RED);&#xD;&#xA;    putpixel(y+xc,x+yc,6);&#xD;&#xA;    putpixel(y+xc,-x+yc,6);&#xD;&#xA;    putpixel(-y+xc,-x+yc,6);&#xD;&#xA;    putpixel(-y+xc,x+yc,6);&#xD;&#xA;   }&#xD;&#xA;&#xD;&#xA;    void BresenhamCircle(int xc,int yc,int r)&#xD;&#xA;   {&#xD;&#xA;    int x=0,y=r,d=3-(2*r);&#xD;&#xA;    EightWaySymmetricPlot(xc,yc,x,y);&#xD;&#xA;&#xD;&#xA;    while(x&lt;=y)&#xD;&#xA;     {&#xD;&#xA;      if(d&lt;=0)&#xD;&#xA;             {&#xD;&#xA;        d=d+(4*x)+6;&#xD;&#xA;      }&#xD;&#xA;     else&#xD;&#xA;      {&#xD;&#xA;        d=d+(4*x)-(4*y)+10;&#xD;&#xA;        y=y-1;&#xD;&#xA;      }&#xD;&#xA;       x=x+1;&#xD;&#xA;       EightWaySymmetricPlot(xc,yc,x,y);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int  main(void)&#xD;&#xA;   {&#xD;&#xA;    /* request auto detection */&#xD;&#xA;    int xc,yc,r,gdriver = DETECT, gmode, errorcode;&#xD;&#xA;    /* initialize graphics and local variables */&#xD;&#xA;     initgraph(&amp;gdriver, &amp;gmode, &quot; &quot;);&#xD;&#xA;&#xD;&#xA;     /* read result of initialization */&#xD;&#xA;     errorcode = graphresult();&#xD;&#xA;&#xD;&#xA;      if (errorcode != grOk)  /* an error occurred */&#xD;&#xA;     {&#xD;&#xA;        printf(&quot;Graphics error: %s\n&quot;, grapherrormsg(errorcode));&#xD;&#xA;        printf(&quot;Press any key to halt:&quot;);&#xD;&#xA;        getch();&#xD;&#xA;        exit(1); /* terminate with an error code */&#xD;&#xA;     }&#xD;&#xA;       printf(&quot;Enter the values of xc and yc :&quot;);&#xD;&#xA;       scanf(&quot;%d%d&quot;,&amp;xc,&amp;yc);&#xD;&#xA;       printf(&quot;Enter the value of radius  :&quot;);&#xD;&#xA;       scanf(&quot;%d&quot;,&amp;r);&#xD;&#xA;       BresenhamCircle(xc,yc,r);&#xD;&#xA;     getch();&#xD;&#xA;     closegraph();&#xD;&#xA;     return 0;&#xD;&#xA;    }&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33134" PostHistoryTypeId="1" PostId="10982" RevisionGUID="8ca7779d-1b7f-4c73-b3e6-b2e5e07ae3af" CreationDate="2021-06-21T20:03:02.563" UserId="16729" Text="wall clock using bresenhams circle drawing algo" ContentLicense="CC BY-SA 4.0" />
  <row Id="33135" PostHistoryTypeId="3" PostId="10982" RevisionGUID="8ca7779d-1b7f-4c73-b3e6-b2e5e07ae3af" CreationDate="2021-06-21T20:03:02.563" UserId="16729" Text="|algorithm|2d-graphics|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33136" PostHistoryTypeId="50" PostId="9199" RevisionGUID="74eb750d-ff69-4ba1-9fdb-927cf310ad09" CreationDate="2021-06-22T02:04:50.560" UserId="-1" />
  <row Id="33137" PostHistoryTypeId="50" PostId="10584" RevisionGUID="ac05ee6f-f670-4a7d-b01e-66a47218d187" CreationDate="2021-06-22T06:04:00.367" UserId="-1" />
  <row Id="33138" PostHistoryTypeId="50" PostId="9189" RevisionGUID="0ab009f8-55a7-4621-8b98-40307dd3e713" CreationDate="2021-06-22T07:07:55.740" UserId="-1" />
  <row Id="33139" PostHistoryTypeId="50" PostId="8136" RevisionGUID="0b1d458a-8428-45f9-b8a9-243f9e2f098c" CreationDate="2021-06-22T12:07:45.627" UserId="-1" />
  <row Id="33140" PostHistoryTypeId="2" PostId="10983" RevisionGUID="712ec127-c1c0-49ca-af59-fe25e095ef6d" CreationDate="2021-06-22T13:54:10.097" UserId="13874" Text="As the title above. I am trying to sampling direct light and indirect light. But I have many transparent objects in scene, it's very likely to block the testing ray. To my understanding, it's not good to give up the testing ray if the blocking object is transparent. Because it still have very large chance to hit light source after coming out from transparent object. But I don't know what exactly should I do to make it correct and unbiased.  &#xD;&#xA;&#xD;&#xA;So, what is the best practice for direct light and transparent object?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33141" PostHistoryTypeId="1" PostId="10983" RevisionGUID="712ec127-c1c0-49ca-af59-fe25e095ef6d" CreationDate="2021-06-22T13:54:10.097" UserId="13874" Text="When sampling direct light, what to do if testing ray been blocked by transparent object?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33142" PostHistoryTypeId="3" PostId="10983" RevisionGUID="712ec127-c1c0-49ca-af59-fe25e095ef6d" CreationDate="2021-06-22T13:54:10.097" UserId="13874" Text="|raytracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33143" PostHistoryTypeId="50" PostId="10025" RevisionGUID="7fa36857-1ac9-4763-b14e-b8c57ccab489" CreationDate="2021-06-22T23:07:30.653" UserId="-1" />
  <row Id="33145" PostHistoryTypeId="2" PostId="10984" RevisionGUID="4bf457a4-1007-433a-8993-38e579d44539" CreationDate="2021-06-23T08:09:33.087" UserId="10096" Text="If a ray intersect a transparent object (regardless of the order) multiply by the colour to get proper attenuation, then continue. Note that the order does not matter. The other options is to ignore transparent objects and check for occlusion. Only if there's no occlusion intersect the set of transparent objects only without caring about order once again, and at each such intersection attenuating by the respective colour." ContentLicense="CC BY-SA 4.0" />
  <row Id="33146" PostHistoryTypeId="50" PostId="9267" RevisionGUID="f386a869-9d4b-4add-be90-c29aeb22af9f" CreationDate="2021-06-23T09:06:40.623" UserId="-1" />
  <row Id="33147" PostHistoryTypeId="5" PostId="10984" RevisionGUID="082b04ed-8121-4a2c-8402-537ec4f27333" CreationDate="2021-06-23T10:50:00.217" UserId="10096" Comment="added 201 characters in body" Text="If a ray intersect a transparent object (regardless of the order) multiply by the colour to get proper attenuation, then continue. Note that the order does not matter. The other options is to ignore transparent objects and check for occlusion. Only if there's no occlusion intersect the set of transparent objects only without caring about order once again, and at each such intersection attenuating by the respective colour.&#xD;&#xA;&#xD;&#xA;If the transparent object is a dielectric then you need to trace in order with refraction. See for example: https://graphics.stanford.edu/courses/cs148-10-summer/docs/2006--degreve--reflection_refraction.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="33148" PostHistoryTypeId="2" PostId="10985" RevisionGUID="10763348-bc82-45e4-a802-f277df5c9bef" CreationDate="2021-06-23T11:17:43.160" UserId="7952" Text="The usual method is to just draw over the circle with your lines. The clock is behind the minute hand and the minute hand is behind the hour hand so the drawing order would be. Draw the clock face, then draw the minute hand, then draw the  hour hand.&#xD;&#xA;&#xD;&#xA;This is the basic idea behind Z buffering. &#xD;&#xA;&#xD;&#xA;Drawing the lines is basically the same idea as the circle, just write a function that draws a line it would take a start point and an end point as the parameters. Then another function figures out the start point and end points of each line based on the current time.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33149" PostHistoryTypeId="5" PostId="10985" RevisionGUID="503073eb-9952-408d-b1c0-d47705850554" CreationDate="2021-06-23T11:25:41.023" UserId="7952" Comment="added 405 characters in body" Text="The usual method is to just draw over the circle with your lines. The clock is behind the minute hand and the minute hand is behind the hour hand so the drawing order would be. Draw the clock face, then draw the minute hand, then draw the  hour hand.&#xD;&#xA;&#xD;&#xA;This is the basic idea behind Z buffering. &#xD;&#xA;&#xD;&#xA;Drawing the lines is basically the same idea as the circle, just write a function that draws a line it would take a start point and an end point as the parameters. Then another function figures out the start point and end points of each line based on the current time.&#xD;&#xA;&#xD;&#xA;Figuring out the start and end points of the line is surprisingly simple. The start point is always the center of the circle. The end points are&#xD;&#xA;&#xD;&#xA;    clock_size *(cos(time_rads),sin(time_rads)) &#xD;&#xA;&#xD;&#xA;Where the clock_size is the size of your clock, and time_rads is the current time converted to radians. ( time_in_hours*60 + time_in_minutes gives minutes on the clock face, 2pi radians in a circle.....)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33150" PostHistoryTypeId="5" PostId="10982" RevisionGUID="0476e981-67f8-46f5-94ab-091891f051be" CreationDate="2021-06-23T11:31:57.283" UserId="7952" Comment="Add code markers so it would display correctly" Text="I am new to CG and I need to draw a wall clock using bresenhams circle algo . I have drawn a circle using this algo but how do I add minute and hour needle in it basically how do i add lines inside a circle ? I am using C language to code. Below is the code that i am using to draw a circle by this algo &#xD;&#xA;```c&#xD;&#xA;#include &lt;graphics.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;conio.h&gt;&#xD;&#xA;#include &lt;math.h&gt;&#xD;&#xA;&#xD;&#xA;    void    EightWaySymmetricPlot(int xc,int yc,int x,int y)&#xD;&#xA;   {&#xD;&#xA;    putpixel(x+xc,y+yc,RED);&#xD;&#xA;    putpixel(x+xc,-y+yc,RED);&#xD;&#xA;    putpixel(-x+xc,-y+yc,RED);&#xD;&#xA;    putpixel(-x+xc,y+yc,RED);&#xD;&#xA;    putpixel(y+xc,x+yc,6);&#xD;&#xA;    putpixel(y+xc,-x+yc,6);&#xD;&#xA;    putpixel(-y+xc,-x+yc,6);&#xD;&#xA;    putpixel(-y+xc,x+yc,6);&#xD;&#xA;   }&#xD;&#xA;&#xD;&#xA;    void BresenhamCircle(int xc,int yc,int r)&#xD;&#xA;   {&#xD;&#xA;    int x=0,y=r,d=3-(2*r);&#xD;&#xA;    EightWaySymmetricPlot(xc,yc,x,y);&#xD;&#xA;&#xD;&#xA;    while(x&lt;=y)&#xD;&#xA;     {&#xD;&#xA;      if(d&lt;=0)&#xD;&#xA;             {&#xD;&#xA;        d=d+(4*x)+6;&#xD;&#xA;      }&#xD;&#xA;     else&#xD;&#xA;      {&#xD;&#xA;        d=d+(4*x)-(4*y)+10;&#xD;&#xA;        y=y-1;&#xD;&#xA;      }&#xD;&#xA;       x=x+1;&#xD;&#xA;       EightWaySymmetricPlot(xc,yc,x,y);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int  main(void)&#xD;&#xA;   {&#xD;&#xA;    /* request auto detection */&#xD;&#xA;    int xc,yc,r,gdriver = DETECT, gmode, errorcode;&#xD;&#xA;    /* initialize graphics and local variables */&#xD;&#xA;     initgraph(&amp;gdriver, &amp;gmode, &quot; &quot;);&#xD;&#xA;&#xD;&#xA;     /* read result of initialization */&#xD;&#xA;     errorcode = graphresult();&#xD;&#xA;&#xD;&#xA;      if (errorcode != grOk)  /* an error occurred */&#xD;&#xA;     {&#xD;&#xA;        printf(&quot;Graphics error: %s\n&quot;, grapherrormsg(errorcode));&#xD;&#xA;        printf(&quot;Press any key to halt:&quot;);&#xD;&#xA;        getch();&#xD;&#xA;        exit(1); /* terminate with an error code */&#xD;&#xA;     }&#xD;&#xA;       printf(&quot;Enter the values of xc and yc :&quot;);&#xD;&#xA;       scanf(&quot;%d%d&quot;,&amp;xc,&amp;yc);&#xD;&#xA;       printf(&quot;Enter the value of radius  :&quot;);&#xD;&#xA;       scanf(&quot;%d&quot;,&amp;r);&#xD;&#xA;       BresenhamCircle(xc,yc,r);&#xD;&#xA;     getch();&#xD;&#xA;     closegraph();&#xD;&#xA;     return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33151" PostHistoryTypeId="24" PostId="10982" RevisionGUID="0476e981-67f8-46f5-94ab-091891f051be" CreationDate="2021-06-23T11:31:57.283" Comment="Proposed by 7952 approved by 13095 edit id of 567" ContentLicense="CC BY-SA 4.0" />
  <row Id="33158" PostHistoryTypeId="50" PostId="8935" RevisionGUID="c8df85b6-3749-4961-b4aa-117592955623" CreationDate="2021-06-23T23:00:20.047" UserId="-1" />
  <row Id="33160" PostHistoryTypeId="2" PostId="10987" RevisionGUID="7d32ba26-f3ca-4128-868c-993201310175" CreationDate="2021-06-24T01:26:41.920" UserId="11058" Text="I have made use of degenerative triangles when rendering a mesh. While the degenerative triangles are not rasterized when using `GL_FILL` polygon mode, they are when I do mesh debugging with `GL_LINE` mode.&#xD;&#xA;&#xD;&#xA;Why is this the case? Are there any options to prevent rasterization in `GL_LINE` mode?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33161" PostHistoryTypeId="1" PostId="10987" RevisionGUID="7d32ba26-f3ca-4128-868c-993201310175" CreationDate="2021-06-24T01:26:41.920" UserId="11058" Text="Why are degenerative triangles rasterized when using GL_LINE polygon mode" ContentLicense="CC BY-SA 4.0" />
  <row Id="33162" PostHistoryTypeId="3" PostId="10987" RevisionGUID="7d32ba26-f3ca-4128-868c-993201310175" CreationDate="2021-06-24T01:26:41.920" UserId="11058" Text="|opengl|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33163" PostHistoryTypeId="50" PostId="9875" RevisionGUID="5591fc75-6cd9-4c42-805c-254bf5b4b7db" CreationDate="2021-06-24T04:02:45.220" UserId="-1" />
  <row Id="33170" PostHistoryTypeId="2" PostId="10989" RevisionGUID="5901febc-3e55-4c45-8ddb-292b9d1d70b0" CreationDate="2021-06-24T13:02:17.653" UserId="16224" Text="I am having troubles making a BRDF that has both specular and diffuse part. Each one is weighted by a coefficient and the sum of coefficients should be equal to one.&#xD;&#xA;&#xD;&#xA;I want this layered BRDF to be the simplest possible and physically right.&#xD;&#xA;&#xD;&#xA;What I am doing for the moment is:&#xD;&#xA;```&#xD;&#xA;Vector3f sampleBRDF(Vector3f&amp; wi) {&#xD;&#xA;    float randomNumber = generateUniform();&#xD;&#xA;    if (randomNumber &lt; 0.5f) {&#xD;&#xA;        // We will create a specular ray&#xD;&#xA;        return reflectZUp(wi);&#xD;&#xA;    }&#xD;&#xA;    else {&#xD;&#xA;        // We will create a diffuse ray&#xD;&#xA;        float phi = 2_PI * generateUniform();&#xD;&#xA;        float cosTheta = sqrt(generateUniform());&#xD;&#xA;        float theta = acos(cosTheta);&#xD;&#xA;        &#xD;&#xA;        Vector3f wo = toCarthesian(Vector2f(phi, theta));&#xD;&#xA;        wo.z = isSameHemisphereZUp(wi, wo) ? wo.z : -wo.z;&#xD;&#xA;        &#xD;&#xA;        return wo;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float brdf(Vector3f&amp; wi, Vector3f&amp; wo, float diffuseProbability) {&#xD;&#xA;    if (isSpecular(wi, wo))&#xD;&#xA;        return 2.f * (1.f - diffuseProbability);&#xD;&#xA;    else&#xD;&#xA;        return 2.f * abs(wo.z) / PI;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float pdf(wi, wo) {&#xD;&#xA;    if (isSpecular(wi, wo))&#xD;&#xA;        return (1.f - diffuseProbability);&#xD;&#xA;    else&#xD;&#xA;        return diffuseProbability * abs(wo.z) / PI;&#xD;&#xA;}&#xD;&#xA;    &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I am pretty sure my sampling method is right, because it is a very common one. But there may have mistakes in my BRDF et and PDF methods. The results that I obtain from this BRDF don't satisfy me.&#xD;&#xA;&#xD;&#xA;If you have any ideas, advices or questions, I would be happy to read/answer you !&#xD;&#xA;&#xD;&#xA;Have a good day.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33171" PostHistoryTypeId="1" PostId="10989" RevisionGUID="5901febc-3e55-4c45-8ddb-292b9d1d70b0" CreationDate="2021-06-24T13:02:17.653" UserId="16224" Text="How can I make the simplest physically based mixed specular-diffuse BRDF (and how to properly sample it)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33172" PostHistoryTypeId="3" PostId="10989" RevisionGUID="5901febc-3e55-4c45-8ddb-292b9d1d70b0" CreationDate="2021-06-24T13:02:17.653" UserId="16224" Text="|brdf|importance-sampling|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33173" PostHistoryTypeId="2" PostId="10990" RevisionGUID="1ab616d9-71c2-4ec0-b60f-53d67de1e2da" CreationDate="2021-06-24T13:50:18.717" UserId="13321" Text="A common way of combining diffuse and specular brdfs is by using a fresnel equation.&#xD;&#xA;&#xD;&#xA;Essentially, for some specular materials, the amount reflected and transmitted (passed through the object) depends on the angle you view it. For example water will reflect more if you look at it from one angle, but you can see through it if you look at it from another.&#xD;&#xA;&#xD;&#xA;A fresnel equation is an approximation of how much is reflected vs transmitted.&#xD;&#xA;&#xD;&#xA;One way of using this is to model a thin specular layer, and any light transmitted through this layer hits a diffuse layer underneath. Look up clear coat materials if you want to see some examples.&#xD;&#xA;&#xD;&#xA;Essentially you calcuale fr = &quot;fresnel equation of your view angle&quot;, and then weight your reflection bxdf with fr and your diffuse bxdf with (1 - fr).&#xD;&#xA;&#xD;&#xA;Here are some resources that might help you:&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Schlick%27s_approximation&#xD;&#xA;&#xD;&#xA;https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel" ContentLicense="CC BY-SA 4.0" />
  <row Id="33174" PostHistoryTypeId="2" PostId="10991" RevisionGUID="ea608b3d-827d-4b15-808a-17d622ac0be6" CreationDate="2021-06-24T16:48:41.760" UserId="48" Text="I assume you're talking about triangles with two vertices equal, and a third vertex at a different point. They don't appear in filled polygon mode because such triangles have zero area and don't cover any pixel centers. It's not that there's a special rule &quot;degenerate triangles are dropped&quot;, it's that they naturally don't generate any fragments when rasterized. (GPUs may still detect and drop degenerate triangles early in the pipeline as an optimization.)&#xD;&#xA;&#xD;&#xA;But when drawn as lines, there is no reason why the lines would be dropped. The rasterization rules for lines always produce a line of the specified width in pixels, and when you draw the triangle's edges as lines, if the edges are nonzero length then they will show up.&#xD;&#xA;&#xD;&#xA;There is no mode to control this that I'm aware of. There used to be a thing called &quot;edge flags&quot; that could control which edges of each triangle were rasterized or not, but that was deprecated from GPU APIs long ago.&#xD;&#xA;&#xD;&#xA;For other options, you could try to use [primitive restart](https://www.khronos.org/opengl/wiki/Vertex_Rendering#Primitive_Restart) to avoid needing degenerate triangles at all, or you could create a separate index buffer for wireframe rendering that doesn't include the degenerate triangles." ContentLicense="CC BY-SA 4.0" />
  <row Id="33175" PostHistoryTypeId="5" PostId="10987" RevisionGUID="b7eb9d6d-82f9-4400-9252-a4a2678384f0" CreationDate="2021-06-25T00:49:40.273" UserId="48" Comment="degenerative -&gt; degenerate" Text="I have made use of degenerate triangles when rendering a mesh. While the degenerate triangles are not rasterized when using `GL_FILL` polygon mode, they are when I do mesh debugging with `GL_LINE` mode.&#xD;&#xA;&#xD;&#xA;Why is this the case? Are there any options to prevent rasterization in `GL_LINE` mode?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33176" PostHistoryTypeId="4" PostId="10987" RevisionGUID="b7eb9d6d-82f9-4400-9252-a4a2678384f0" CreationDate="2021-06-25T00:49:40.273" UserId="48" Comment="degenerative -&gt; degenerate" Text="Why are degenerate triangles rasterized when using GL_LINE polygon mode" ContentLicense="CC BY-SA 4.0" />
  <row Id="33177" PostHistoryTypeId="50" PostId="10263" RevisionGUID="9aa5ff8c-6fff-45d5-bfeb-f5d7a32c4af1" CreationDate="2021-06-25T11:00:20.103" UserId="-1" />
  <row Id="33180" PostHistoryTypeId="2" PostId="10992" RevisionGUID="c0a26b75-9ce6-40cb-a6d4-d24f817e89f2" CreationDate="2021-06-26T22:45:41.980" UserId="5344" Text="We have an internal CSG (Constructive Solid Geometry) format.Converting/Ingesting other CSG-based files to our internal format is straightforward. We also managed to convert some polygon (mesh) based geometries to our internal format.&#xD;&#xA;&#xD;&#xA;But we also want to support **B-Rep** files such as ***Step*** and ***Parasolid***.We want to able to use a library that &#xD;&#xA; - Supports .NET/ c#  (ideally .NET standard)&#xD;&#xA; - Can import Step and Parasolid and also can do meshing on these surfaces and faces..&#xD;&#xA; - Can import Solidworks and ideally as many as possible CAD/CAM/CAE file formats&#xD;&#xA; - Extensible&#xD;&#xA;&#xD;&#xA;*OpenCascade*,*C3D*, and *CadExchanger* are some options but are there more options in this space?&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="33181" PostHistoryTypeId="1" PostId="10992" RevisionGUID="c0a26b75-9ce6-40cb-a6d4-d24f817e89f2" CreationDate="2021-06-26T22:45:41.980" UserId="5344" Text="Cad ingesting SDK that supports STEP , Parasolid and Solidworks filetypes and Also Meshing" ContentLicense="CC BY-SA 4.0" />
  <row Id="33182" PostHistoryTypeId="3" PostId="10992" RevisionGUID="c0a26b75-9ce6-40cb-a6d4-d24f817e89f2" CreationDate="2021-06-26T22:45:41.980" UserId="5344" Text="|mesh|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33183" PostHistoryTypeId="2" PostId="10993" RevisionGUID="8034d260-6d8d-4105-9863-10a94a112e48" CreationDate="2021-06-27T12:50:45.587" UserId="226" Text="How accurate it is to estimate rendering equation using wavelengths and then convert result to CIE XYZ to accumulate samples temporally by averaging them over time?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33184" PostHistoryTypeId="1" PostId="10993" RevisionGUID="8034d260-6d8d-4105-9863-10a94a112e48" CreationDate="2021-06-27T12:50:45.587" UserId="226" Text="Does CIE XYZ preserve spectral accuracy when used for progressive rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33185" PostHistoryTypeId="3" PostId="10993" RevisionGUID="8034d260-6d8d-4105-9863-10a94a112e48" CreationDate="2021-06-27T12:50:45.587" UserId="226" Text="|colorspace|spectral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33186" PostHistoryTypeId="2" PostId="10994" RevisionGUID="b2b0d5a0-ff26-4d4f-bc0b-44ab73c5fdf4" CreationDate="2021-06-27T13:42:47.223" UserId="6165" Text="I'm just trying to figure out, how rounded corners are usual drawn for user interfaces in a performant way &amp; as insight also try to figure out how it's done in Browser, as they allow for variable round corners (without being blurry) :)&#xD;&#xA;&#xD;&#xA;In the end I try to use some of this information for the implementation of the user-interface of my game." ContentLicense="CC BY-SA 4.0" />
  <row Id="33187" PostHistoryTypeId="1" PostId="10994" RevisionGUID="b2b0d5a0-ff26-4d4f-bc0b-44ab73c5fdf4" CreationDate="2021-06-27T13:42:47.223" UserId="6165" Text="How are rounded corners of user interfaces usually rendered in modern applications like browsers?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33188" PostHistoryTypeId="3" PostId="10994" RevisionGUID="b2b0d5a0-ff26-4d4f-bc0b-44ab73c5fdf4" CreationDate="2021-06-27T13:42:47.223" UserId="6165" Text="|rendering|ui|gui|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33192" PostHistoryTypeId="2" PostId="10996" RevisionGUID="2da96b61-cca6-4588-9302-0d1eadef4d86" CreationDate="2021-06-27T16:50:44.233" UserId="16774" Text="I wish to determine the path taken by a light ray between two points, $a$ and $b$, through an *anisotropic* medium. More specifically, this medium has an index of refraction which varies as an exponential function of depth.&#xD;&#xA;&#xD;&#xA;I'm not terribly familiar with the methods of raytracing in computer graphics, however I understand that such problems are within the domain of raytracing. Algorithmically, how might such a path be determined (ideally, more efficiently than writing and solving systems of differential equations)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33193" PostHistoryTypeId="1" PostId="10996" RevisionGUID="2da96b61-cca6-4588-9302-0d1eadef4d86" CreationDate="2021-06-27T16:50:44.233" UserId="16774" Text="How is raytracing performed in anisotropic media?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33194" PostHistoryTypeId="3" PostId="10996" RevisionGUID="2da96b61-cca6-4588-9302-0d1eadef4d86" CreationDate="2021-06-27T16:50:44.233" UserId="16774" Text="|raytracing|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33195" PostHistoryTypeId="50" PostId="8888" RevisionGUID="676e0e95-6a35-43f8-a8d6-cf218ba696e3" CreationDate="2021-06-27T17:03:10.310" UserId="-1" />
  <row Id="33196" PostHistoryTypeId="2" PostId="10997" RevisionGUID="863ecfb3-1900-4540-af22-fa3860a1aa54" CreationDate="2021-06-27T21:53:43.420" UserId="48" Text="I think the term for this would be &quot;medium with a varying index of refraction&quot;; the term &quot;anisotropic medium&quot; more typically refers to scattering media where the scattering coefficients depend on the direction of the ray (e.g. microflake models). Anyway, there seem to be a few papers on the topic that I was able to find with a quick web search.&#xD;&#xA;&#xD;&#xA;* [Stam and Languénou, Ray Tracing in Non-Constant Media (1996)](https://d2f99xq7vri1nk.cloudfront.net/legacy_app_files/pdf/wobble.pdf) - derives a differential equation to bend the ray's path, which can be numerically integrated along it using ray marching&#xD;&#xA;&#xD;&#xA;* [Pediredla et al, Path Tracing Estimators for Refractive Radiative Transfer (2020)](https://imaging.cs.cmu.edu/rrte/) - uses Monte Carlo volumetric path tracing, and extends it to handle varying refractive index, using a gradient descent approach to solve the eikonal equation along sampled path segments&#xD;&#xA;&#xD;&#xA;* [Zhang et al, Ray Tracing Method of Gradient Refractive Index Medium Based on Refractive Index Step (2021)](https://res.mdpi.com/d_attachment/applsci/applsci-11-00912/article_deploy/applsci-11-00912-v2.pdf) - approximates the continuously-varying refractive index as piecewise constant slices and treats the interfaces between slices using the usual Snell's law of refraction. It is adaptive to how rapidly the refractive index is changing, taking longer steps where it is nearly constant and short steps where it is rapidly varying" ContentLicense="CC BY-SA 4.0" />
  <row Id="33197" PostHistoryTypeId="2" PostId="10998" RevisionGUID="2fceb3ac-36b9-4d50-b818-2c551b8fb602" CreationDate="2021-06-28T09:26:55.440" UserId="13456" Text="&gt;How accurate it is to estimate rendering equation using wavelengths&#xD;&#xA;&#xD;&#xA;This is probably as accurate as it gets if you are using with the full form of Fresnel equation.&#xD;&#xA;&#xD;&#xA;&gt;then convert result to CIE XYZ&#xD;&#xA;&#xD;&#xA;This brings in two problems with respect to accuracy.&#xD;&#xA;&#xD;&#xA;If the spectral distribution of your illuminant is different from the one that is used by CIE, you would need to interpolate your illuminant's spd to that of CIE. This would probably give you a consistent result whether you average it over time or not, but your values would not be accurate due to the interpolation. &#xD;&#xA;&#xD;&#xA;If you are going to use the same spd for illuminants, then your accuracy depend on how you generate the wavelength. If you are sending wavelengths in same order at all times to your spectral distribution function, the final spectral curve would be the same at all times and converting that to XYZ and averaging it over time etc should not make much of a difference. However if you are generating wavelengths at random as it is mostly the case for reproducing real illuminant behavior, then your XYZ values might have slight variations due to variation of incoming wavelength over time. I am not sure if these variations are visually noticable though.&#xD;&#xA;&#xD;&#xA;&gt; to accumulate samples temporally by averaging them over time&#xD;&#xA;&#xD;&#xA;If you are using the same wavelength order, or anything that ensures that the spectral curve would be same at each time or that the spectral curve upon average would be the same, then it should be okay I guess." ContentLicense="CC BY-SA 4.0" />
  <row Id="33198" PostHistoryTypeId="2" PostId="10999" RevisionGUID="8c7dd04b-2ef9-470f-84a8-4da89d85d77c" CreationDate="2021-06-28T12:43:18.113" UserId="15955" Text="I'm studying path tracing, at the moment I created a compute shader that aims to calculate the intersection of rays with meshes.&#xD;&#xA;However, when I run the code the unity crashes, displaying a graphics card error.&#xD;&#xA;&#xD;&#xA;The error is in the detection of intersection with the meshes.&#xD;&#xA;When I put the lines of code responsible for writing a new ray.&#xD;&#xA;&#xD;&#xA;But I'm not managing to fix it. I also don't understand if it could be a problem with my video card or my code.&#xD;&#xA;I tested it with only 1 mesh triangle and got a lot of lag.&#xD;&#xA;&#xD;&#xA;To send the vertices to the video card I did the following. I got the stitches from the scene. Then I took the indices and vertices arrays and merged them with the other meshes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    public void buildObjectList()&#xD;&#xA;            {&#xD;&#xA;                int indicesCount = 0;&#xD;&#xA;                int verticesCount = 0;&#xD;&#xA;    &#xD;&#xA;                foreach (PathTracingObject pto in pathTracingObjects)&#xD;&#xA;                {&#xD;&#xA;                    int[] triangles;&#xD;&#xA;                    Vector3[] vertices;&#xD;&#xA;    &#xD;&#xA;                    triangles = pto.objectMesh.triangles;//Take a sequence of vertices that form a triangle.&#xD;&#xA;                    vertices = pto.objectMesh.vertices;//Take vertex list&#xD;&#xA;    &#xD;&#xA;                    pto._pathTracingObject.indicesOffset = indicesCount;//Offset: Where the list of indices belonging to the object starts. | indicesCount: How many indices were added before these.&#xD;&#xA;                    pto._pathTracingObject.indicesCount = triangles.Length;//How many indexes does this object have.&#xD;&#xA;    &#xD;&#xA;                    foreach (Vector3 vertice in vertices)&#xD;&#xA;                        this.vertices.Add(vertice);&#xD;&#xA;    &#xD;&#xA;                    for (int i = 0; i &lt; triangles.Length; i++)&#xD;&#xA;                    {&#xD;&#xA;                        this.indices.Add(triangles[i] + verticesCount + 1);//Variable containing all indices of all objects in the scene. | triangles[i] (take an index) +verticesCount(Add to the amount of vetices already added) + 1&#xD;&#xA;    &#xD;&#xA;                        /*Example:&#xD;&#xA;                        If the previous object has 270 vertices.&#xD;&#xA;                        The first triangle of the next objects will be connected to the vertices(271, 272, 273) instead of(0,1,2).&#xD;&#xA;                        +1 because vertex 270 belongs to a different object.*/&#xD;&#xA;                    }&#xD;&#xA;    &#xD;&#xA;                    indicesCount += triangles.Length;//update index&#xD;&#xA;                    verticesCount += vertices.Length;//update index&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;In compute shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    /*&#xD;&#xA;    http://www.graphics.cornell.edu/pubs/1997/MT97.html&#xD;&#xA;    https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates&#xD;&#xA;    */&#xD;&#xA;    bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)&#xD;&#xA;    {&#xD;&#xA;        float3 edge1 = vert1 - vert0;&#xD;&#xA;        float3 edge2 = vert2 - vert0;&#xD;&#xA;        float3 pvec = cross(ray.rayDirection, edge2);&#xD;&#xA;        float det = dot(edge1, pvec);&#xD;&#xA;        if (det &lt; EPSILON)&#xD;&#xA;            return false;&#xD;&#xA;        float inv_det = 1.0f / det;&#xD;&#xA;        float3 tvec = ray.raySource - vert0;&#xD;&#xA;        u = dot(tvec, pvec) * inv_det;&#xD;&#xA;        if (u &lt; 0.0 || u &gt; 1.0f)&#xD;&#xA;            return false;&#xD;&#xA;        float3 qvec = cross(tvec, edge1);&#xD;&#xA;        v = dot(ray.rayDirection, qvec) * inv_det;&#xD;&#xA;        if (v &lt; 0.0 || u + v &gt; 1.0f)&#xD;&#xA;            return false;&#xD;&#xA;        t = dot(edge2, qvec) * inv_det;&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    void IntersectMeshObject(pathTracingObject pto, Ray ray, inout RayHit bestHit)&#xD;&#xA;    {&#xD;&#xA;        for (int i = 0; i &lt; pto.indicesCount; i += 3) {&#xD;&#xA;            float3 v0 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i]], 1))).xyz;&#xD;&#xA;            float3 v1 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 1]], 1))).xyz;&#xD;&#xA;            float3 v2 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 2]], 1))).xyz;&#xD;&#xA;    &#xD;&#xA;            float t, u, v;&#xD;&#xA;            if (IntersectTriangle(ray, v0, v1, v2, t, u, v))&#xD;&#xA;            {&#xD;&#xA;                if (t &gt; 0 &amp;&amp; t &lt; bestHit.hitDistance)&#xD;&#xA;                {&#xD;&#xA;                    /*           &#xD;&#xA;                    bestHit.hitDistance = t; // makes unity crash&#xD;&#xA;                    bestHit.hitPosition = ray.raySource + t * ray.rayDirection; // makes unity crash&#xD;&#xA;                    bestHit.hitNormal = normalize(bestHit.hitPosition); // makes unity crash&#xD;&#xA;    &#xD;&#xA;                    bestHit.hitAlbedo = float3(1,1,1); // makes unity crash&#xD;&#xA;                    */&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Message information: We detected driver timeout on your system. A bug report was generated. this report can help AMD resolve the issue.&#xD;&#xA;&#xD;&#xA;Full code:&#xD;&#xA;&#xD;&#xA;    // Each #kernel tells which function to compile; you can have many kernels&#xD;&#xA;    #pragma kernel CSMain&#xD;&#xA;    &#xD;&#xA;    #define PI 3.14159265359&#xD;&#xA;    #define EPSILON 0.0000001&#xD;&#xA;    &#xD;&#xA;    RWTexture2D&lt;float4&gt; Result;&#xD;&#xA;    &#xD;&#xA;    struct pathTracingObject&#xD;&#xA;    {&#xD;&#xA;        float4 Position;&#xD;&#xA;    &#xD;&#xA;        int indicesCount;&#xD;&#xA;        int indicesOffset;&#xD;&#xA;    &#xD;&#xA;        float4x4 localToWorldMatrix;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    StructuredBuffer&lt;pathTracingObject&gt; _pathTracingObject;&#xD;&#xA;    StructuredBuffer&lt;float3&gt; _Vertices;&#xD;&#xA;    StructuredBuffer&lt;int&gt; _Indices;&#xD;&#xA;    &#xD;&#xA;    int _pathTracingObjectCount;&#xD;&#xA;    &#xD;&#xA;    float4x4 _CameraToWorld;&#xD;&#xA;    float4x4 _CameraInverseProjection;&#xD;&#xA;     &#xD;&#xA;    struct Ray {&#xD;&#xA;        float3 raySource;&#xD;&#xA;        float3 rayDirection;&#xD;&#xA;        float3 rayColor;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    Ray CreateRay(float3 source, float3 direction)&#xD;&#xA;    {&#xD;&#xA;        Ray ray;&#xD;&#xA;        ray.raySource = source;&#xD;&#xA;        ray.rayDirection = direction;&#xD;&#xA;    &#xD;&#xA;        return ray;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Ray CreateCameraRay(float2 uv)&#xD;&#xA;    {&#xD;&#xA;        float3 source = mul(_CameraToWorld, float4(0.0f, 0.0f, 0.0f, 1.0f)).xyz;&#xD;&#xA;    &#xD;&#xA;        float3 direction = mul(_CameraInverseProjection, float4(uv, 0.0f, 1.0f)).xyz;&#xD;&#xA;        direction = mul(_CameraToWorld, float4(direction, 0.0f)).xyz;&#xD;&#xA;        direction = normalize(direction);&#xD;&#xA;        return CreateRay(source, direction);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    struct RayHit&#xD;&#xA;    {&#xD;&#xA;        float3 hitPosition;&#xD;&#xA;        float hitDistance;&#xD;&#xA;        float3 hitNormal;&#xD;&#xA;    &#xD;&#xA;        float3 hitAlbedo;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    RayHit CreateRayHit()&#xD;&#xA;    {&#xD;&#xA;        RayHit hit;&#xD;&#xA;    &#xD;&#xA;        hit.hitPosition = float3(0.0f, 0.0f, 0.0f);&#xD;&#xA;        hit.hitDistance = 1.#INF;&#xD;&#xA;        hit.hitNormal = float3(0.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;        hit.hitAlbedo = float3(0.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;        return hit;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    /*&#xD;&#xA;    http://www.graphics.cornell.edu/pubs/1997/MT97.html&#xD;&#xA;    https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates&#xD;&#xA;    */&#xD;&#xA;    bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)&#xD;&#xA;    {&#xD;&#xA;        float3 edge1 = vert1 - vert0;&#xD;&#xA;        float3 edge2 = vert2 - vert0;&#xD;&#xA;        float3 pvec = cross(ray.rayDirection, edge2);&#xD;&#xA;        float det = dot(edge1, pvec);&#xD;&#xA;        if (det &lt; EPSILON)&#xD;&#xA;            return false;&#xD;&#xA;        float inv_det = 1.0f / det;&#xD;&#xA;        float3 tvec = ray.raySource - vert0;&#xD;&#xA;        u = dot(tvec, pvec) * inv_det;&#xD;&#xA;        if (u &lt; 0.0 || u &gt; 1.0f)&#xD;&#xA;            return false;&#xD;&#xA;        float3 qvec = cross(tvec, edge1);&#xD;&#xA;        v = dot(ray.rayDirection, qvec) * inv_det;&#xD;&#xA;        if (v &lt; 0.0 || u + v &gt; 1.0f)&#xD;&#xA;            return false;&#xD;&#xA;        t = dot(edge2, qvec) * inv_det;&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void IntersectMeshObject(pathTracingObject pto, Ray ray, inout RayHit bestHit)&#xD;&#xA;    {&#xD;&#xA;        for (int i = 0; i &lt; pto.indicesCount; i += 3) {&#xD;&#xA;            float3 v0 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i]], 1))).xyz;&#xD;&#xA;            float3 v1 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 1]], 1))).xyz;&#xD;&#xA;            float3 v2 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 2]], 1))).xyz;&#xD;&#xA;    &#xD;&#xA;            float t, u, v;&#xD;&#xA;            if (IntersectTriangle(ray, v0, v1, v2, t, u, v))&#xD;&#xA;            {&#xD;&#xA;                if (t &gt; 0 &amp;&amp; t &lt; bestHit.hitDistance)&#xD;&#xA;                {&#xD;&#xA;                               &#xD;&#xA;                    bestHit.hitDistance = t; // makes unity crash&#xD;&#xA;                    bestHit.hitPosition = ray.raySource + t * ray.rayDirection; // makes unity crash&#xD;&#xA;                    bestHit.hitNormal = normalize(bestHit.hitPosition); // makes unity crash&#xD;&#xA;    &#xD;&#xA;                    bestHit.hitAlbedo = float3(1,1,1); // makes unity crash&#xD;&#xA;                 &#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RayHit Trace(Ray ray)&#xD;&#xA;    {&#xD;&#xA;        RayHit bestHit = CreateRayHit();&#xD;&#xA;    &#xD;&#xA;        for (int i = 0; i &lt; _pathTracingObjectCount; i++) {&#xD;&#xA;            pathTracingObject pto = _pathTracingObject[i];&#xD;&#xA;            IntersectMeshObject(pto, ray, bestHit);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        return bestHit;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [numthreads(8,8,1)]&#xD;&#xA;    void CSMain (uint3 id : SV_DispatchThreadID)&#xD;&#xA;    {&#xD;&#xA;        // TODO: insert actual code here!&#xD;&#xA;        float3 result = float3(0, 0, 0);&#xD;&#xA;    &#xD;&#xA;        int width, height;&#xD;&#xA;        Result.GetDimensions(width, height);&#xD;&#xA;        float2 uv = float2((id.xy + float2(0.5f, 0.5f)) / float2(width, height) * 2.0f - 1.0f);&#xD;&#xA;    &#xD;&#xA;        for(int i = 0; i &lt; 1;i++) {&#xD;&#xA;            Ray ray = CreateCameraRay(id.xy);&#xD;&#xA;            RayHit hit = Trace(ray);&#xD;&#xA;            result += hit.hitAlbedo;&#xD;&#xA;        }&#xD;&#xA;        result /= float3(5,5,5);&#xD;&#xA;    &#xD;&#xA;        Result[id.xy] = float4(result, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;C#&#xD;&#xA;&#xD;&#xA;    using System.Collections;&#xD;&#xA;    using System.Collections.Generic;&#xD;&#xA;    using UnityEngine;&#xD;&#xA;    using UnityEngine.Rendering;&#xD;&#xA;    &#xD;&#xA;    [System.Serializable]&#xD;&#xA;    class PathTracing&#xD;&#xA;    {&#xD;&#xA;     &#xD;&#xA;        [SerializeField]&#xD;&#xA;        ComputeShader computeShader;&#xD;&#xA;        [SerializeField]&#xD;&#xA;        GameObject[] pathTracingObjects;&#xD;&#xA;      &#xD;&#xA;        class PathTracingComputeShader&#xD;&#xA;        {&#xD;&#xA;            PathTracingObject[] pathTracingObjects;&#xD;&#xA;    &#xD;&#xA;            public List&lt;Vector3&gt; vertices = new List&lt;Vector3&gt;();&#xD;&#xA;            public List&lt;int&gt; indices = new List&lt;int&gt;();&#xD;&#xA;    &#xD;&#xA;            RenderTexture RT;&#xD;&#xA;            public void loadRenderTexture()&#xD;&#xA;            {&#xD;&#xA;                RT = new RenderTexture(Mathf.CeilToInt(Screen.width / 4), Mathf.CeilToInt(Screen.height / 4), 0, RenderTextureFormat.DefaultHDR);&#xD;&#xA;                RT.enableRandomWrite = true;&#xD;&#xA;                RT.Create();&#xD;&#xA;            }&#xD;&#xA;            public RenderTexture OnRenderComputeShader(ComputeShader computeShader)&#xD;&#xA;            {&#xD;&#xA;                loadRenderTexture();&#xD;&#xA;    &#xD;&#xA;                #region Mesh Forwarding&#xD;&#xA;    &#xD;&#xA;                computeShader.SetInt(&quot;_pathTracingObjectCount&quot;, pathTracingObjects.Length);&#xD;&#xA;    &#xD;&#xA;                foreach (PathTracingObject pto in pathTracingObjects)&#xD;&#xA;                   pto.OnExecutePathTracing();&#xD;&#xA;    &#xD;&#xA;                buildObjectList();&#xD;&#xA;    &#xD;&#xA;                ComputeBuffer objectsBuffer = new ComputeBuffer(pathTracingObjects.Length, 88) { name = &quot;Scenes Objects Buffer&quot; };&#xD;&#xA;                ComputeBuffer vertexBuffer = new ComputeBuffer(vertices.Count, 12) { name = &quot;Vertices Buffer&quot; };&#xD;&#xA;                ComputeBuffer indexBuffer = new ComputeBuffer(indices.Count, 4) { name = &quot;Indices Buffer&quot; };&#xD;&#xA;    &#xD;&#xA;                PathTracingObject.pathTracingObject[] sceneObjects = new PathTracingObject.pathTracingObject[pathTracingObjects.Length];&#xD;&#xA;                for (int i = 0; i &lt; pathTracingObjects.Length; i++)&#xD;&#xA;                {&#xD;&#xA;                    sceneObjects[i] = pathTracingObjects[i]._pathTracingObject;&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;                objectsBuffer.SetData(sceneObjects);&#xD;&#xA;                vertexBuffer.SetData(vertices);&#xD;&#xA;                indexBuffer.SetData(indices);&#xD;&#xA;    &#xD;&#xA;                computeShader.SetBuffer(0, &quot;_pathTracingObject&quot;, objectsBuffer);&#xD;&#xA;                computeShader.SetBuffer(0, &quot;_Vertices&quot;, vertexBuffer);&#xD;&#xA;                computeShader.SetBuffer(0, &quot;_Indices&quot;, indexBuffer);&#xD;&#xA;                #endregion&#xD;&#xA;    &#xD;&#xA;                computeShader.SetMatrix(&quot;_CameraToWorld&quot;, Camera.main.cameraToWorldMatrix);&#xD;&#xA;                computeShader.SetMatrix(&quot;_CameraInverseProjection&quot;, Camera.main.projectionMatrix.inverse);&#xD;&#xA;    &#xD;&#xA;                computeShader.SetTexture(0, &quot;Result&quot;, RT);&#xD;&#xA;                computeShader.Dispatch(0, RT.width, RT.height, 24);&#xD;&#xA;    &#xD;&#xA;                return RT;&#xD;&#xA;            }&#xD;&#xA;            public void buildObjectList()&#xD;&#xA;            {&#xD;&#xA;                int indicesCount = 0;&#xD;&#xA;                int verticesCount = 0;&#xD;&#xA;    &#xD;&#xA;                foreach (PathTracingObject pto in pathTracingObjects)&#xD;&#xA;                {&#xD;&#xA;                    int[] triangles;&#xD;&#xA;                    Vector3[] vertices;&#xD;&#xA;    &#xD;&#xA;                    triangles = pto.objectMesh.triangles;//Take a sequence of vertices that form a triangle.&#xD;&#xA;                    vertices = pto.objectMesh.vertices;//Take vertex list&#xD;&#xA;    &#xD;&#xA;                    pto._pathTracingObject.indicesOffset = indicesCount;//Offset: Where the list of indices belonging to the object starts. | indicesCount: How many indices were added before these.&#xD;&#xA;                    pto._pathTracingObject.indicesCount = triangles.Length;//How many indexes does this object have.&#xD;&#xA;    &#xD;&#xA;                    foreach (Vector3 vertice in vertices)&#xD;&#xA;                        this.vertices.Add(vertice);&#xD;&#xA;    &#xD;&#xA;                    for (int i = 0; i &lt; triangles.Length; i++)&#xD;&#xA;                    {&#xD;&#xA;                        this.indices.Add(triangles[i] + verticesCount + 1);//Variable containing all indices of all objects in the scene. | triangles[i] (take an index) +verticesCount(Add to the amount of vetices already added) + 1&#xD;&#xA;    &#xD;&#xA;                        /*Example:&#xD;&#xA;                        If the previous object has 270 vertices.&#xD;&#xA;                        The first triangle of the next objects will be connected to the vertices(271, 272, 273) instead of(0,1,2).&#xD;&#xA;                        +1 because vertex 270 belongs to a different object.*/&#xD;&#xA;                    }&#xD;&#xA;    &#xD;&#xA;                    indicesCount += triangles.Length;//update index&#xD;&#xA;                    verticesCount += vertices.Length;//update index&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            public void setPathTracingObjects(PathTracingObject[] pto) { pathTracingObjects = pto; }&#xD;&#xA;        }&#xD;&#xA;        public RenderTexture preProcessing()&#xD;&#xA;        {&#xD;&#xA;            PathTracingComputeShader pathTracingCompute = new PathTracingComputeShader();&#xD;&#xA;    &#xD;&#xA;            PathTracingObject[] objs = new PathTracingObject[pathTracingObjects.Length];&#xD;&#xA;            for (int i = 0; i &lt; pathTracingObjects.Length; i++)&#xD;&#xA;                objs[i] = pathTracingObjects[i].GetComponent&lt;PathTracingObject&gt;();&#xD;&#xA;    &#xD;&#xA;            pathTracingCompute.setPathTracingObjects(objs);&#xD;&#xA;            return pathTracingCompute.OnRenderComputeShader(computeShader);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I believe it could be 2 things.&#xD;&#xA;Or my video card doesn't count for work.&#xD;&#xA;Or there is a problem with the vertex array.&#xD;&#xA;(index out of range maybe?)&#xD;&#xA;&#xD;&#xA;But I'm not sure, since it just crashes without an error message or something.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OYL2N.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33199" PostHistoryTypeId="1" PostId="10999" RevisionGUID="8c7dd04b-2ef9-470f-84a8-4da89d85d77c" CreationDate="2021-06-28T12:43:18.113" UserId="15955" Text="Unity crashes when running path tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="33200" PostHistoryTypeId="3" PostId="10999" RevisionGUID="8c7dd04b-2ef9-470f-84a8-4da89d85d77c" CreationDate="2021-06-28T12:43:18.113" UserId="15955" Text="|pathtracing|compute-shader|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33201" PostHistoryTypeId="2" PostId="11000" RevisionGUID="3dd10e2c-4d5e-4313-aed6-50684a094a8d" CreationDate="2021-06-28T18:10:38.067" UserId="48" Text="The choice of various tristimulus color spaces or spectral rendering matters when you're doing _multiplicative_ color operations, like multiplying a light source color by a material reflectance. For these operations, the spectral approach is most accurate, and multiplying tristimulus color values is a pretty coarse approximation (and also depends a lot on the color space).&#xD;&#xA;&#xD;&#xA;However, for _linear_ color operations like adding, scaling, and averaging it shouldn't matter which color space you're in or whether you do it on the full spectrum or not. The operations of converting between color spaces, or reducing a spectrum to a tristimulus color space like XYZ, are all linear operations, so they distribute over linear color operations.&#xD;&#xA;&#xD;&#xA;In other words, averaging a bunch of spectra and then converting to XYZ should give the exact same results (up to numerical precision) as converting all the spectra to XYZ and then averaging." ContentLicense="CC BY-SA 4.0" />
  <row Id="33205" PostHistoryTypeId="50" PostId="10919" RevisionGUID="d94622cf-81ca-4358-be73-5818cc3b5c03" CreationDate="2021-06-30T12:02:30.227" UserId="-1" />
  <row Id="33206" PostHistoryTypeId="2" PostId="11002" RevisionGUID="d68978a6-d2e6-4446-8391-ff91558c0599" CreationDate="2021-06-30T12:36:58.793" UserId="7952" Text="Speaking from my own experience...&#xD;&#xA;&#xD;&#xA;There is no one answer to the question of &quot;how is this UI interface element drawn&quot;.&#xD;&#xA;&#xD;&#xA;Under windows you can get them as freebies where the OS gives you a helping hand but windows tends to be very inflexible with its ready made UI element and tends to boil down to &quot;styles&quot;. But windows also provides its own graphics environment which is powerful enough that the text CGP&amp;P uses it to introduce graphics programming.&#xD;&#xA;&#xD;&#xA;Linux is similar but with its own strange and wonderful quirks. But without the manufacturer provided graphics environment.&#xD;&#xA;&#xD;&#xA;Beyond that, browser designers are on their own and can use a variety of techniques, here are some:&#xD;&#xA;&#xD;&#xA;Bitmap graphics: This is a bit old in terms of windows... but you can just save your own &quot;bitmaps&quot; rendered however you like, then load them up and blast them to the screen just like any other texture map. But the usual caveats apply.&#xD;&#xA;&#xD;&#xA;Just draw them on the fly: Basically create functions that have all the details of drawing the UI the way the project demands. Then when a UI element is needed the function provides the details on drawing the element. This approach can be kept simple or you can go crazy and end up with a vast and complex interface that only the designer understands.&#xD;&#xA;&#xD;&#xA;Many graphics environments provide some sort of help with all this, but it sounds like you are writing that environment.&#xD;&#xA;&#xD;&#xA;There are some new techniques that are emerging, the [slug][1] library (which is a font rendering algorithm but can be used to draw many other UI elements) allow &quot;glyphs&quot; to be drawn. Using glyphs you can draw beautifully rounded and even complex corners that render surprisingly fast, scale almost perfectly, look great from any angle, the list goes on. But the algorithm behind slug is patented so you have to pay for the privilege.&#xD;&#xA;&#xD;&#xA;For a simple rounded edge that looks good as a 2d element you can draw a circle at each corner, then connect the corners with straight lines. For a &quot;shadow&quot; draw 2 circles slightly offset from one another, draw the shadow circle slightly darker. Then draw a rectangle inside the entire works, and then the text or whatever is needed inside the rectangle. I know this sounds simplistic, but if done well it can look really nice, is straight forward to implement and performant. Be sure to draw the UI first and use depth buffering to help with whatever is drawn behind the UI.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://sluglibrary.com" ContentLicense="CC BY-SA 4.0" />
  <row Id="33207" PostHistoryTypeId="2" PostId="11003" RevisionGUID="ed8eec94-9b1a-47a7-9018-902f3b6f242c" CreationDate="2021-06-30T15:12:10.943" UserId="16789" Text="**situation:**&#xD;&#xA;&#xD;&#xA;I've implemented a Whitted style ray tracing in C. Everything appear to works except the shadow cast by small object on big far objects&#xD;&#xA;&#xD;&#xA;**The problem :**&#xD;&#xA;&#xD;&#xA;red sphere have radius 0.5&#xD;&#xA;orange sphere have radius 200&#xD;&#xA;[![example][1]][1]&#xD;&#xA;zooming:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;more:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;So fare, I could only suspect rounding error due to the fact that I use float.&#xD;&#xA;In &quot;normal&quot; situation, the shadows work great.&#xD;&#xA;Have you already encounter that kind of error ? Is my guess correct, or could that be something else ? &#xD;&#xA;&#xD;&#xA;Not sure the code could help because messy, but there it is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;static inline uint8_t	diffuse(const struct s_bvh *bvh,&#xD;&#xA;	const t_lght *lght, const t_hinfo *hi, t_vec3f diff)&#xD;&#xA;{&#xD;&#xA;	t_vec3f			light;&#xD;&#xA;	struct s_hit	h;&#xD;&#xA;	float			dp;&#xD;&#xA;	float			length;&#xD;&#xA;&#xD;&#xA;	sub_(lght-&gt;pts, hi-&gt;r-&gt;o, hi-&gt;r-&gt;d);&#xD;&#xA;	length = norm(hi-&gt;r-&gt;d);&#xD;&#xA;	h.min = 0.001f;&#xD;&#xA;	h.t = length;&#xD;&#xA;	normalize(hi-&gt;r-&gt;d);&#xD;&#xA;	dp = dotp(hi-&gt;n, hi-&gt;r-&gt;d);&#xD;&#xA;	if (dp &gt; 0.0f)&#xD;&#xA;	{&#xD;&#xA;		invert_(hi-&gt;r-&gt;d, hi-&gt;r-&gt;inv_d);&#xD;&#xA;		traverser(bvh, hi-&gt;r, &amp;h, 1);&#xD;&#xA;		if (h.t &lt; length)&#xD;&#xA;			return (0);&#xD;&#xA;		s_scale(lght-&gt;color, dp, light);&#xD;&#xA;		add_(light, diff, diff);&#xD;&#xA;		return (1);&#xD;&#xA;	}&#xD;&#xA;	return (0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void	diffusel(const struct s_bvhl *s, const t_hinfo *hi, t_vec3f color)&#xD;&#xA;{&#xD;&#xA;	t_vec3f			ambi;&#xD;&#xA;	t_vec3f			diff;&#xD;&#xA;	uint32_t		i;&#xD;&#xA;&#xD;&#xA;	i = 0;&#xD;&#xA;	mult_(s-&gt;lghts.amb, color, ambi);&#xD;&#xA;	set_vector(diff, 0.f, 0.f, 0.f);&#xD;&#xA;	while (i &lt; s-&gt;lghts.count)&#xD;&#xA;	{&#xD;&#xA;		diffuse(&amp;s-&gt;bvh, s-&gt;lghts.lghts + i, hi, diff);&#xD;&#xA;		++i;&#xD;&#xA;	}&#xD;&#xA;	mult_(color, diff, color);&#xD;&#xA;	add_(ambi, color, color);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/siIfu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2BAk1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uaVmE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33208" PostHistoryTypeId="1" PostId="11003" RevisionGUID="ed8eec94-9b1a-47a7-9018-902f3b6f242c" CreationDate="2021-06-30T15:12:10.943" UserId="16789" Text="ray racing (Whitted) bad shadow on far objects (artifact)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33209" PostHistoryTypeId="3" PostId="11003" RevisionGUID="ed8eec94-9b1a-47a7-9018-902f3b6f242c" CreationDate="2021-06-30T15:12:10.943" UserId="16789" Text="|raytracing|shadow|artifacts|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33210" PostHistoryTypeId="2" PostId="11004" RevisionGUID="8f181d35-74fd-434b-92cb-1f5ba0c62ed0" CreationDate="2021-06-30T16:24:45.277" UserId="13391" Text="Spheres with shadows work fine. But when I try to include triangles with shadows, they are shaded incorrectly (i.e completely black):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But when I disable shadows Blinn shading on triangles work fine (comment lines 128, 129, 130 in **main.py** file attached below):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am following [this article][3] for triangle / ray intersection.&#xD;&#xA;&#xD;&#xA;main.py:&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;import sys&#xD;&#xA;from PIL import Image&#xD;&#xA;from math import * &#xD;&#xA;from util import *&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;width  = 600&#xD;&#xA;height = 400&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def GetNearestIntersection(objects, ray):&#xD;&#xA;    nearestObj = None&#xD;&#xA;    minHit = Intersection(None, INF, None, None)&#xD;&#xA;    &#xD;&#xA;    for obj in objects:&#xD;&#xA;        hit = obj.intersect(ray)&#xD;&#xA;        if hit.distance &lt; minHit.distance:&#xD;&#xA;            nearestObj = obj&#xD;&#xA;            minHit = hit&#xD;&#xA;            &#xD;&#xA;    return minHit&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def Blinn(light, hit, eye):&#xD;&#xA;    ka = hit.object.material.ambient&#xD;&#xA;    kd = hit.object.material.diffuse&#xD;&#xA;    ks = hit.object.material.specular&#xD;&#xA;    la = light.material.ambient&#xD;&#xA;    ld = light.material.diffuse&#xD;&#xA;    ls = light.material.specular&#xD;&#xA;    L  = (light.position - hit.point).normalize()&#xD;&#xA;    N  = hit.normal&#xD;&#xA;    V  = (eye - hit.point).normalize()&#xD;&#xA;    a  = hit.object.material.shininess&#xD;&#xA;    &#xD;&#xA;    A = ka*la&#xD;&#xA;    D = kd*ld*L.dot(N)&#xD;&#xA;    S = ks*ls*pow(N.dot((L+V).normalize()) ,a/4)  &#xD;&#xA;    p = A + D + S&#xD;&#xA;    &#xD;&#xA;    return p&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def main():&#xD;&#xA;    global bitmap&#xD;&#xA;    &#xD;&#xA;    eye = Vector(0,0,1)&#xD;&#xA;    ratio = float(width) / height&#xD;&#xA;    screen = Screen(-1, 1 / ratio, 1, -1 / ratio, 0)&#xD;&#xA;    &#xD;&#xA;    objects = []&#xD;&#xA;    objects.append(Sphere(Vector(-0.2,0,-1),  0.7,      Material(Vector(0.1, 0, 0),Vector(1,0,0),Vector(1,1,1), 100, 0.5, -1)))&#xD;&#xA;    #objects.append(Sphere(Vector( 0.1,-0.3,0),0.1,      Material(Vector(0,0,0),Vector(0,1,0),Vector(1,1,1), 100, 0.2, 1.5)))&#xD;&#xA;    #objects.append(Sphere(Vector(-0.3,0.15,0),0.15,     Material(Vector(0,0,0),Vector(0,0,1),Vector(1,1,1), 100, 0.8, -1)))&#xD;&#xA;&#xD;&#xA;    objects.append(Sphere(Vector(0,-9000,0),  9000-0.7, Material(Vector(0,0,0),Vector(0.71,0.71,0.71),Vector(0,0,0), 100, 0.01, -1)))   &#xD;&#xA;&#xD;&#xA;    #cube = Mesh(Material(Vector(0.1, 0, 0),Vector(1,0,0),Vector(1,1,1), 100, 0.5, -1));&#xD;&#xA;    #cube.load(&quot;cube3.obj&quot;)&#xD;&#xA;    #print(&quot;Object loaded&quot;)&#xD;&#xA;&#xD;&#xA;    #objects.append(cube)&#xD;&#xA;&#xD;&#xA;    t1 = Triangle((Vector(2.001539, 2.006154, -0.2), Vector(2.001539, 0.006154, -0.2), Vector(0.001539, 0.006154, -0.4)), (Vector(0, 0, 1), Vector(0, 0, 1), Vector(0, 0, 1)), Material(Vector(0.1, 0, 0),Vector(1,0,0),Vector(1,1,1), 100, 0.5, -1))&#xD;&#xA;    &#xD;&#xA;    #t2 = Triangle((Vector(2.001539, -0.003401, -2.006154), Vector(2.001539, -0.003401, -0.006154), Vector(0.001539, -0.003401, -0.006154)), (Vector(0.0000, -1.0000, 0.0000), Vector(0.0000, -1.0000, 0.0000), Vector(0.0000, -1.0000, 0.0000)), Material(Vector(0.1, 0, 0),Vector(1,0,0),Vector(1,1,1), 100, 0.5, -1))&#xD;&#xA;    &#xD;&#xA;    objects.append(t1)&#xD;&#xA;    #objects.append(t2)&#xD;&#xA;&#xD;&#xA;    light = Light(Vector(5,5,5), Material(Vector(1,1,1),Vector(1,1,1),Vector(1,1,1), -1, -1))&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    for frame in range(1):&#xD;&#xA;    &#xD;&#xA;        img = Image.new(mode = &quot;RGB&quot;, size=(width, height), color=Color.WHITE)&#xD;&#xA;        bitmap = img.load() # create the pixel data&#xD;&#xA;&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#---                    YOUR CODE HERE                      ---&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;        sys.setrecursionlimit(10000)&#xD;&#xA;        &#xD;&#xA;        #breakpoint()&#xD;&#xA;        &#xD;&#xA;        deltaX = (screen.right - screen.left)/(width-1)&#xD;&#xA;        deltaY = (screen.top - screen.bottom)/(height-1)&#xD;&#xA;&#xD;&#xA;        for y in range(height):&#xD;&#xA;            for x in range(width):&#xD;&#xA;                pixel = Vector(screen.left+x*deltaX, screen.top-y*deltaY, screen.z)&#xD;&#xA;                direction = (pixel - eye).normalize()&#xD;&#xA;                pixelRay = Ray(eye, direction)&#xD;&#xA;    &#xD;&#xA;                bitmap[x,y] = Color.WHITE&#xD;&#xA;                &#xD;&#xA;                hit = GetNearestIntersection(objects, pixelRay)&#xD;&#xA;                if hit.point != None:&#xD;&#xA;                    #bcolor = hit.object.material.diffuse&#xD;&#xA;                    &#xD;&#xA;                    bcolor = Blinn(light, hit, eye)&#xD;&#xA;                    &#xD;&#xA;                    color = (int(bcolor.x*256), int(bcolor.y*256), int(bcolor.z*256))&#xD;&#xA;                    &#xD;&#xA;                    #  Shoot extra rays:&#xD;&#xA;                    #1) Shadow Ray:&#xD;&#xA;                    shadowed = False&#xD;&#xA;                    shiftedPoint = hit.point + hit.normal * 1e-5&#xD;&#xA;                    #shiftedPoint = Vector(hit.point.x,hit.point.y, 0.01)&#xD;&#xA;                    #print(hit.point.toString() + &quot;  --  &quot; + shiftedPoint.toString())&#xD;&#xA;                    shadowRay = Ray(shiftedPoint, (light.position - shiftedPoint).normalize())&#xD;&#xA;                    result = GetNearestIntersection(objects, shadowRay)&#xD;&#xA;                    #print(result.point.toString())&#xD;&#xA;                    if result.point != None:&#xD;&#xA;                    #    print(result.object.name)&#xD;&#xA;                        shadowed = True&#xD;&#xA;                    &#xD;&#xA;                    #2) Reflection Rays:&#xD;&#xA;                    reflectionBounces = 3&#xD;&#xA;                    for i in range(reflectionBounces):&#xD;&#xA;                        pass&#xD;&#xA;                    &#xD;&#xA;                    #if(shadowed):&#xD;&#xA;                    #    bitmap[x,y] = Color.BLACK&#xD;&#xA;                    #else:&#xD;&#xA;                        bitmap[x,y] = color&#xD;&#xA;                                &#xD;&#xA;            print(&quot;progress: %d %%&quot; % ((y+1)/height*100.0))&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;#--------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;        img.show()&#xD;&#xA;        img.save(&quot;pic1.png&quot;)&#xD;&#xA;        #img.save(&quot;images/fig&quot; + f'{frame:06}' + &quot;.png&quot;)&#xD;&#xA;        #print(&quot;Saving ---&gt; images/fig&quot; + f'{frame:06}' + &quot;.png&quot;)&#xD;&#xA;        #img.close()&#xD;&#xA;&#xD;&#xA;main()&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;util.py:&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;from math import * &#xD;&#xA;&#xD;&#xA;PI  = 3.14159265&#xD;&#xA;INF = 9999999999&#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;class Color:&#xD;&#xA;    BLACK = (0,0,0)&#xD;&#xA;    RED   = (245,23,32)&#xD;&#xA;    BLUE  = (46,139,192)&#xD;&#xA;    GREEN = (24,165,88)&#xD;&#xA;    PINK  = (250,38,160)&#xD;&#xA;    GOLD  = (248,210,16)&#xD;&#xA;    TEAL  = (43,124,133)&#xD;&#xA;    WHITE = (255,255,255)&#xD;&#xA;    CHROMA= (0,255,0)&#xD;&#xA;    &#xD;&#xA;#-----------------------------------------------------------------------&#xD;&#xA;&#xD;&#xA;def dot(a, b):&#xD;&#xA;    return a.x*b.x + a.y*b.y + a.z*b.z&#xD;&#xA;&#xD;&#xA;def normalize(a):&#xD;&#xA;    mag = a.magnitude()&#xD;&#xA;    return Vector(a.x/mag,a.y/mag,a.z/mag)&#xD;&#xA;&#xD;&#xA;class Vector:&#xD;&#xA;    def __init__(self,x,y,z):&#xD;&#xA;        self.x = x&#xD;&#xA;        self.y = y&#xD;&#xA;        self.z = z&#xD;&#xA;        self.w = 1&#xD;&#xA;&#xD;&#xA;    def toString(self):&#xD;&#xA;        return &quot;S:[&quot;+&quot;{:.3f}&quot;.format(self.x)+&quot;, &quot;+&quot;{:.3f}&quot;.format(self.y)+&quot;, &quot;+&quot;{:.3f}&quot;.format(self.z)+&quot;]&quot;&#xD;&#xA;&#xD;&#xA;    def dot(self, b):&#xD;&#xA;        return self.x*b.x + self.y*b.y + self.z*b.z&#xD;&#xA;    &#xD;&#xA;    def cross(self, b):&#xD;&#xA;        return Vector(self.y*b.z-self.z*b.y, self.z*b.x-self.x*b.z, self.x*b.y-self.y*b.x)&#xD;&#xA;        &#xD;&#xA;    def magnitude(self):&#xD;&#xA;        return sqrt(self.x*self.x + self.y*self.y + self.z*self.z)&#xD;&#xA;&#xD;&#xA;    def normalize(self):&#xD;&#xA;        mag = self.magnitude()&#xD;&#xA;        return Vector(self.x/mag, self.y/mag, self.z/mag)&#xD;&#xA;&#xD;&#xA;    # Provide &quot;overridden methods via the &quot;__operation__&quot; notation; allows you to do, for example, a+b, a-b, a*b&#xD;&#xA;    def __add__(self, b):&#xD;&#xA;        return Vector(self.x + b.x, self.y+b.y, self.z+b.z)&#xD;&#xA;&#xD;&#xA;    def __sub__(self, b):&#xD;&#xA;        return Vector(self.x-b.x, self.y-b.y, self.z-b.z)&#xD;&#xA;&#xD;&#xA;    def __mul__(self, b):&#xD;&#xA;        if type(b) == float or type(b) == int:&#xD;&#xA;            return Vector(self.x*b, self.y*b, self.z*b)&#xD;&#xA;        elif type(b) == Vector:&#xD;&#xA;            return Vector(self.x*b.x, self.y*b.y, self.z*b.z)&#xD;&#xA;        else:&#xD;&#xA;            print(type(b))&#xD;&#xA;            assert False&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;class Material:&#xD;&#xA;    def __init__(self, ambient, diffuse, specular, shininess = 0, reflection = 0, refractiveIndex = -1):&#xD;&#xA;        self.ambient    = ambient               # Vector(r,g,b)&#xD;&#xA;        self.diffuse    = diffuse               # Vector(r,g,b)&#xD;&#xA;        self.specular   = specular              # Vector(r,g,b)&#xD;&#xA;        self.shininess  = shininess             # Integer between 0 and 100&#xD;&#xA;        self.reflection = reflection            # Real number between 0 and 1.0&#xD;&#xA;        self.refractiveIndex = refractiveIndex  # Real number. -1 means it is a solid object&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;class Intersectable:&#xD;&#xA;    def intersect(self, ray):&#xD;&#xA;        assert False, &quot;Error: You must override this method&quot;&#xD;&#xA;&#xD;&#xA;class Sphere(Intersectable):&#xD;&#xA;    def __init__(self,center, radius, material):&#xD;&#xA;        self.center   = center&#xD;&#xA;        self.radius   = radius&#xD;&#xA;        self.material = material&#xD;&#xA;        &#xD;&#xA;    def intersect(self, ray):&#xD;&#xA;        OC = ray.origin - self.center&#xD;&#xA;        a = ray.direction.dot(ray.direction)&#xD;&#xA;        b = 2.0 * ray.direction.dot(OC)&#xD;&#xA;        c = OC.dot(OC) - self.radius*self.radius&#xD;&#xA;        descriminant = b*b - 4*a*c&#xD;&#xA;        if(descriminant &gt; 0):&#xD;&#xA;            t1 = (-b + sqrt(descriminant))/2&#xD;&#xA;            t2 = (-b - sqrt(descriminant))/2&#xD;&#xA;            if t1 &gt; 0 and t2 &gt; 0:&#xD;&#xA;                dist = min(t1, t2)&#xD;&#xA;                point = ray.pointAtParameter(dist)&#xD;&#xA;                normal = (point - self.center).normalize()&#xD;&#xA;                return Intersection(point, dist, normal, self)&#xD;&#xA;        return Intersection(None, INF, None, None)&#xD;&#xA;        &#xD;&#xA;                &#xD;&#xA;    def normal(self, b):&#xD;&#xA;        return (b - self.center).normalize()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;class Ray:&#xD;&#xA;    def __init__(self, origin, direction):&#xD;&#xA;        self.origin    = origin&#xD;&#xA;        self.direction = direction&#xD;&#xA;&#xD;&#xA;    def pointAtParameter(self, t):&#xD;&#xA;        return self.origin + self.direction*t&#xD;&#xA;    &#xD;&#xA;    def toString(self):&#xD;&#xA;        return &quot;R-&gt;{ &quot;+ self.origin.toString() + &quot; -- &quot; + self.direction.toString() +&quot; }&quot;&#xD;&#xA;       &#xD;&#xA;class Intersection:&#xD;&#xA;	def __init__(self, point, distance, normal, object):&#xD;&#xA;		self.point    = point&#xD;&#xA;		self.distance = distance&#xD;&#xA;		self.normal   = normal&#xD;&#xA;		self.object   = object&#xD;&#xA;		&#xD;&#xA;		&#xD;&#xA;class Screen:&#xD;&#xA;    def __init__(self,  left, top, right, bottom, z):&#xD;&#xA;        self.left   = left&#xD;&#xA;        self.top    = top&#xD;&#xA;        self.right  = right&#xD;&#xA;        self.bottom = bottom&#xD;&#xA;        self.z      = z&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;class Light:&#xD;&#xA;    def __init__(self, position, material):&#xD;&#xA;        self.position = position&#xD;&#xA;        self.material = material&#xD;&#xA;&#xD;&#xA;class Triangle(Intersectable):&#xD;&#xA;    def __init__(self, verts, normals, material):&#xD;&#xA;        self.verts     = verts     # tuple of 3 vertices&#xD;&#xA;        self.normals   = normals   # tuple of 3 normals&#xD;&#xA;        self.material  = material&#xD;&#xA;        self.name      = &quot;triangle&quot;&#xD;&#xA;   &#xD;&#xA;    def intersect(self, ray):&#xD;&#xA;        A = self.verts[0]&#xD;&#xA;        B = self.verts[1]&#xD;&#xA;        C = self.verts[2]&#xD;&#xA;        &#xD;&#xA;        # Compute normal Vector:&#xD;&#xA;        num    = (B-A).cross(C-A)&#xD;&#xA;        den    = num.magnitude()&#xD;&#xA;        invDen = 1.0/den&#xD;&#xA;        n = (num * invDen).normalize()&#xD;&#xA;        &#xD;&#xA;        d = ray.direction&#xD;&#xA;        P = ray.origin&#xD;&#xA;        &#xD;&#xA;        dconst = n.dot(A)&#xD;&#xA;        t = (dconst - n.dot(P)) * (1.0/(n.dot(d)))&#xD;&#xA;        &#xD;&#xA;        Q = ray.pointAtParameter(t)&#xD;&#xA;&#xD;&#xA;        if ((B-A).cross(Q-A)).dot(n) &lt; 0:&#xD;&#xA;            return Intersection(None, INF, None, None)&#xD;&#xA;        if ((C-B).cross(Q-B)).dot(n) &lt; 0:&#xD;&#xA;            return Intersection(None, INF, None, None)&#xD;&#xA;        if ((A-C).cross(Q-C)).dot(n) &lt; 0:&#xD;&#xA;            return Intersection(None, INF, None, None)&#xD;&#xA;        &#xD;&#xA;        dist = t&#xD;&#xA;        normal = self.normals[0]&#xD;&#xA;        point = Q&#xD;&#xA;        &#xD;&#xA;        return Intersection(point, dist, normal, self)&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;class Mesh(Intersectable):&#xD;&#xA;    def __init__(self, material):&#xD;&#xA;        self.material = material&#xD;&#xA;        self.vertices = []      # each vertex is a Vector3D&#xD;&#xA;        self.normals  = []      # each normal is a Vector3D&#xD;&#xA;        self.faces    = []      # each face is a list of 3 pairs [ (v, vn), (v, vn), (v, vn) ]&#xD;&#xA;        &#xD;&#xA;    def load(self, fileName):&#xD;&#xA;        fo = open(fileName, &quot;r+&quot;)&#xD;&#xA;        &#xD;&#xA;        lines = fo.readlines()&#xD;&#xA;        &#xD;&#xA;        for i in range(len(lines)):&#xD;&#xA;            prefix = lines[i][0:2]&#xD;&#xA;            if prefix == 'v ':&#xD;&#xA;                v = lines[i].split()&#xD;&#xA;                self.vertices.append(Vector(float(v[1]), float(v[2]), float(v[3])))&#xD;&#xA;            elif prefix == 'vn':&#xD;&#xA;                vn = lines[i].split()&#xD;&#xA;                self.normals.append(Vector(float(vn[1]), float(vn[2]), float(vn[3])))&#xD;&#xA;            elif prefix == 'f ':&#xD;&#xA;                f = lines[i].split()&#xD;&#xA;                triangle = []&#xD;&#xA;&#xD;&#xA;                for j in range(1,4):&#xD;&#xA;                    vindex = int(f[j].split('/')[0]) - 1&#xD;&#xA;                    nindex = int(f[j].split('/')[2]) - 1&#xD;&#xA;                    pair = (vindex, nindex)&#xD;&#xA;                    triangle.append(pair)&#xD;&#xA;&#xD;&#xA;                self.faces.append(triangle)&#xD;&#xA;                &#xD;&#xA;               #v1 = self.vertices[vindex]&#xD;&#xA;               #n1 = self.normals[nindex]&#xD;&#xA;            &#xD;&#xA;               # vindex = float(f[2].split('/')[0])&#xD;&#xA;               # nindex = float(f[2].split('/')[2])&#xD;&#xA;               # v2 = self.vertices[vindex]&#xD;&#xA;               # n2 = self.normals[nindex]&#xD;&#xA;&#xD;&#xA;               # vindex = float(f[3].split('/')[0])&#xD;&#xA;               # nindex = float(f[3].split('/')[2])&#xD;&#xA;               # v3 = self.vertices[vindex]&#xD;&#xA;               # n3 = self.normals[nindex]&#xD;&#xA;&#xD;&#xA;               # triangle = Triangle()                    &#xD;&#xA;&#xD;&#xA;        fo.close()&#xD;&#xA;&#xD;&#xA;    def intersect(self, ray):&#xD;&#xA;        &#xD;&#xA;        for f in self.faces:&#xD;&#xA;            v1 = self.vertices[f[0][0]]&#xD;&#xA;            n1 = self.vertices[f[0][1]]&#xD;&#xA;            v2 = self.vertices[f[1][0]]&#xD;&#xA;            n2 = self.vertices[f[1][1]]&#xD;&#xA;            v3 = self.vertices[f[2][0]]&#xD;&#xA;            n3 = self.vertices[f[2][1]]&#xD;&#xA;            &#xD;&#xA;            trig = Triangle((v1, v2, v3), (n1, n2, n3), self.material)&#xD;&#xA;            &#xD;&#xA;            hit = trig.intersect(ray)&#xD;&#xA;            &#xD;&#xA;            if(hit.point != None):&#xD;&#xA;                return hit&#xD;&#xA;                &#xD;&#xA;        return Intersection(None, INF, None, None)&#xD;&#xA;        &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1su4T.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/uCPh3.png&#xD;&#xA;  [3]: https://courses.cs.washington.edu/courses/csep557/10au/lectures/triangle_intersection.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="33211" PostHistoryTypeId="1" PostId="11004" RevisionGUID="8f181d35-74fd-434b-92cb-1f5ba0c62ed0" CreationDate="2021-06-30T16:24:45.277" UserId="13391" Text="Shadow Bug when Raytracing Triangles" ContentLicense="CC BY-SA 4.0" />
  <row Id="33212" PostHistoryTypeId="3" PostId="11004" RevisionGUID="8f181d35-74fd-434b-92cb-1f5ba0c62ed0" CreationDate="2021-06-30T16:24:45.277" UserId="13391" Text="|raytracing|shadow|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33213" PostHistoryTypeId="2" PostId="11005" RevisionGUID="cd043e3d-dcf2-4502-8e68-682af8461d85" CreationDate="2021-07-01T19:19:11.647" UserId="16793" Text="I bumped into the flowing when reading paper. Can anyone help to explain what does filter means in glint rendering and texture mapping? Thanks a lot!&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XkSKc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33214" PostHistoryTypeId="1" PostId="11005" RevisionGUID="cd043e3d-dcf2-4502-8e68-682af8461d85" CreationDate="2021-07-01T19:19:11.647" UserId="16793" Text="What does filter mean in glint rendering and texture mapping?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33215" PostHistoryTypeId="3" PostId="11005" RevisionGUID="cd043e3d-dcf2-4502-8e68-682af8461d85" CreationDate="2021-07-01T19:19:11.647" UserId="16793" Text="|rendering|filtering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33216" PostHistoryTypeId="2" PostId="11006" RevisionGUID="7ea20ccc-f964-4833-95e4-ef67017107e0" CreationDate="2021-07-02T06:02:49.030" UserId="15940" Text="I need to, starting from one face, iterate over the rest of the faces until I reach the first facet. For this I can use twin, start, end or other info of halfedges, faces, vertex. That is, I need to switch to another face at each iteration until I go through all the faces.&#xD;&#xA;&#xD;&#xA;Please, help" ContentLicense="CC BY-SA 4.0" />
  <row Id="33217" PostHistoryTypeId="1" PostId="11006" RevisionGUID="7ea20ccc-f964-4833-95e4-ef67017107e0" CreationDate="2021-07-02T06:02:49.030" UserId="15940" Text="HalfEdge: How to get list of all faces from one face" ContentLicense="CC BY-SA 4.0" />
  <row Id="33218" PostHistoryTypeId="3" PostId="11006" RevisionGUID="7ea20ccc-f964-4833-95e4-ef67017107e0" CreationDate="2021-07-02T06:02:49.030" UserId="15940" Text="|pathtracing|computational-geometry|polygon|edge-detection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33219" PostHistoryTypeId="2" PostId="11007" RevisionGUID="28826d08-ce1b-423c-a821-7ea698cedb1e" CreationDate="2021-07-02T09:19:19.227" UserId="7724" Text="Observe that you can construct another graph by connecting the centroids of faces with centroids of adjacent faces. This is known as the dual. The edges of the graph between the centroids can be represented as the twin relation between halfedges. Then you can use something like Depth First Search to visit all the faces:&#xD;&#xA;&#xD;&#xA;    function visit(f)&#xD;&#xA;       mark f as visited&#xD;&#xA;       for(edge e in f) &#xD;&#xA;           if(!e-&gt;twin-&gt;face-&gt;visited) &#xD;&#xA;               faces.append(e-&gt;twin-&gt;face) &#xD;&#xA;               visit(f) &#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="33220" PostHistoryTypeId="50" PostId="10614" RevisionGUID="3bcc646a-7b1b-43d8-a1cd-5505c1f0447c" CreationDate="2021-07-02T12:04:40.603" UserId="-1" />
  <row Id="33221" PostHistoryTypeId="50" PostId="10933" RevisionGUID="bb9fb55e-250a-49b5-a004-4faa5050ece0" CreationDate="2021-07-02T13:02:10.237" UserId="-1" />
  <row Id="33222" PostHistoryTypeId="50" PostId="10619" RevisionGUID="00eaaa41-3f42-4fa8-83a1-fd2b409437cc" CreationDate="2021-07-03T16:01:00.097" UserId="-1" />
  <row Id="33223" PostHistoryTypeId="2" PostId="11008" RevisionGUID="eeb79e0e-0fcc-4a6c-a600-9eac06d0d293" CreationDate="2021-07-03T18:19:51.773" UserId="48" Text="Filtering refers to image processing operations that generate a new image by applying a [filter kernel](https://en.wikipedia.org/wiki/Kernel_(image_processing)) to an existing image. This is used for many purposes, but one of the most common is to resample images without aliasing. For example, when generating mipmaps for a color texture, you will resample it to smaller sizes. The mipmaps are filtered versions of the original texture, where each texel in the mipmap represents a weighted average of a group of texels in the original.&#xD;&#xA;&#xD;&#xA;In context of the paper, they're talking about applying mipmapping to NDFs (normal distribution functions). Just as you generate mipmaps for an ordinary color texture, you can map NDF parameters such as roughness into a texture and then generate mipmaps for those, in such a way that each texel in the mipmap represents an NDF that is representative of the range of normals in a region of the original normal map. You could describe this as filtering the NDFs. You can check out [the Olano and Baker paper on LEAN mapping](https://www.csee.umbc.edu/~olano/papers/lean/) for more details about one such approach." ContentLicense="CC BY-SA 4.0" />
  <row Id="33228" PostHistoryTypeId="2" PostId="11010" RevisionGUID="b16ecf16-3d93-4d3f-8942-e5bd98f00028" CreationDate="2021-07-04T07:27:58.360" UserId="6046" Text="I'm asking this question on behalf of a friend so can't provide any images for now. The problem is to simulate a car paint material with some flakes or graininess in it. This is first done in blender by creating a material. The flakes are added by using flakes normal map which simulates all the perturbed normals. I suppose this causes micro variations which causes the base color to drop at random locations giving the effect of graininess.&#xD;&#xA;&#xD;&#xA;Now blender provides a [normal map node][1] which is used in the shader graph. This has a strength parameter. When the strength is 0, there are no flakes. I searched around the net and found that this effect is probably achieved by lerping between the sampled normal from the normal map and the vector `0.5, 0.5, 1` which seems to be a null or flat normal as it maps to `0,0,1` in the tangent space which means no change.&#xD;&#xA;&#xD;&#xA;The question is, as I understood, changing normals should affect the reflections on the surface, however when I change the strength in blender between 0 and 1, only the graininess changes and the reflection remains the same. When I say the reflection should change, I mean the position of the reflection should change, since the reflection vector would change based on the normal. This doesn't seem to happen in blender. Are they using the plain original normals for reflection and the perturbed ones for other kind of shading?&#xD;&#xA;&#xD;&#xA;He implemented the same technique in threejs and it seems the reflections don't change there as well. However, instead of lerping between the sampled normal and `0.5, 0.5, 1` when we lerped between the sampled normal (after converting it to -1 to 1) and the original geometric normal based on the strength, the reflections on the surface moved as I expected. Can anybody explain what happened? What's the difference between the 2 approaches and why in only the second approach the reflections move or change their position?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.blender.org/manual/en/latest/render/shader_nodes/vector/normal_map.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="33229" PostHistoryTypeId="1" PostId="11010" RevisionGUID="b16ecf16-3d93-4d3f-8942-e5bd98f00028" CreationDate="2021-07-04T07:27:58.360" UserId="6046" Text="Normal mapping should affect specular reflections?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33230" PostHistoryTypeId="3" PostId="11010" RevisionGUID="b16ecf16-3d93-4d3f-8942-e5bd98f00028" CreationDate="2021-07-04T07:27:58.360" UserId="6046" Text="|reflection|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33235" PostHistoryTypeId="2" PostId="11012" RevisionGUID="39b620bc-84d7-4b25-a924-d8c1b0dc90ad" CreationDate="2021-07-05T12:30:31.297" UserId="6092" Text="Because scaling operations are prohibitively expensive in my current rendering stack, I have to pre-render my images in all desired sizes and cache the result on disk. At the moment, I do this by dumping one PNG file per image size. However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content." ContentLicense="CC BY-SA 4.0" />
  <row Id="33236" PostHistoryTypeId="1" PostId="11012" RevisionGUID="39b620bc-84d7-4b25-a924-d8c1b0dc90ad" CreationDate="2021-07-05T12:30:31.297" UserId="6092" Text="Space efficient storage/compression of multiple scaled values (mip maps)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33237" PostHistoryTypeId="3" PostId="11012" RevisionGUID="39b620bc-84d7-4b25-a924-d8c1b0dc90ad" CreationDate="2021-07-05T12:30:31.297" UserId="6092" Text="|image|compression|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33238" PostHistoryTypeId="50" PostId="9919" RevisionGUID="93278224-9b26-4a81-bfb6-9b6529ce545f" CreationDate="2021-07-05T13:05:40.633" UserId="-1" />
  <row Id="33239" PostHistoryTypeId="2" PostId="11013" RevisionGUID="65d6b4ea-3f57-4dab-8770-c017dd621792" CreationDate="2021-07-05T16:56:10.850" UserId="48" Text="You could look into wavelet image compression, which effectively stores a mip pyramid &quot;top down&quot; with each level storing only the diffs from the next-smaller level. This would effectively let you reconstruct whichever mip level you wanted from the same file at load time, with the file being the same overall size as only the base mip. However, it is likely more expensive to decompress than PNG for the same reason.&#xD;&#xA;&#xD;&#xA;The JPEG2000 format implements a wavelet compression method (as well as quantization and bitstream coding like other JPEG formats). I'm not sure if there are JPEG2000 libraries that support efficiently reconstructing multiple resolutions of the image while loading though.&#xD;&#xA;&#xD;&#xA;In honesty, if disk space is the concern, I would probably reach for the standard GPU compression formats used by the game industry such as BC1 or BC7 first, rather than wavelet stuff which is not widely used." ContentLicense="CC BY-SA 4.0" />
  <row Id="33240" PostHistoryTypeId="2" PostId="11014" RevisionGUID="d94839d1-c2e9-4e50-959d-4d2fc8821c43" CreationDate="2021-07-05T17:56:07.040" UserId="2654" Text="&gt; However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content.&#xD;&#xA;&#xD;&#xA;There is. It's called... scaling the largest mipmap to produce the smaller ones. That's essentially what's happening when you generate mipmaps directly: you are &quot;compressing&quot; the lower mipmaps by taking advantage of the fact that all these images are algorithmically built from the largest mipmap. Since you only store the largest mipmap, the other mipmaps take up zero bytes. Then you &quot;decompress&quot; them by scaling them as they are loaded.&#xD;&#xA;&#xD;&#xA;If you've got access to a GPU, you ought to be able to scale it there with rendering operations or even just linearly-interpolated blitting operations." ContentLicense="CC BY-SA 4.0" />
  <row Id="33241" PostHistoryTypeId="5" PostId="11014" RevisionGUID="2b44cc4a-55b6-4fb9-98b0-bfb15ca69a3c" CreationDate="2021-07-05T18:01:52.140" UserId="2654" Comment="added 369 characters in body" Text="&gt; However, this gets fairly large quickly and I'd like to know whether there is a possibility to take advantage of the fact that all these images are basically showing the same content.&#xD;&#xA;&#xD;&#xA;There is. It's called... scaling the largest mipmap to produce the smaller ones. That's essentially what's happening when you generate mipmaps directly: you are &quot;compressing&quot; the lower mipmaps by taking advantage of the fact that all these images are algorithmically built from the largest mipmap. Since you only store the largest mipmap, the other mipmaps take up zero bytes. Then you &quot;decompress&quot; them by scaling them as they are loaded.&#xD;&#xA;&#xD;&#xA;The principle cost of CPU scaling is not the computation of the lower-mipmap level itself. It's the memory bandwidth costs of reading from the higher mipmap and writing to the lower one. It doesn't really matter what your algorithm for computing the lower one is; if it requires reading every pixel of the higher mipmap, it's basically going to cost the same thing.&#xD;&#xA;&#xD;&#xA;If you've got access to a GPU, you ought to be able to scale it there with rendering operations or even just linearly-interpolated blitting operations." ContentLicense="CC BY-SA 4.0" />
  <row Id="33242" PostHistoryTypeId="2" PostId="11015" RevisionGUID="58e92895-7921-42bf-8f12-111542c9fa5e" CreationDate="2021-07-05T20:52:34.800" UserId="16793" Text="I was reading this [slope space integral][1] paper. Can anyone help to explain slope space and slope distribution mentioned in this paper, and why we can use normal and half vector to represent 2D positions in slope space? Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://rgl.s3.eu-central-1.amazonaws.com/media/papers/Loubet2020Slope.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="33243" PostHistoryTypeId="1" PostId="11015" RevisionGUID="58e92895-7921-42bf-8f12-111542c9fa5e" CreationDate="2021-07-05T20:52:34.800" UserId="16793" Text="What is slope distribution" ContentLicense="CC BY-SA 4.0" />
  <row Id="33244" PostHistoryTypeId="3" PostId="11015" RevisionGUID="58e92895-7921-42bf-8f12-111542c9fa5e" CreationDate="2021-07-05T20:52:34.800" UserId="16793" Text="|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33245" PostHistoryTypeId="50" PostId="9926" RevisionGUID="c671cac3-1c96-4f11-9748-c8f7d33d64c0" CreationDate="2021-07-06T00:02:20.190" UserId="-1" />
  <row Id="33246" PostHistoryTypeId="2" PostId="11016" RevisionGUID="d08901ce-584f-4245-9a15-c6b45917bc69" CreationDate="2021-07-06T00:13:18.757" UserId="16818" Text="I've been trying to get my cascaded shadow maps looking right for a while. I managed to fix the shimmering and most of the quantization artifacts, but for some reason the shadows still look really blocky. I'm using a resolution of 1024x1024. Here are images of the bounding boxes used for the orthographic matrices, the camera frustum, and the resulting shadows:&#xD;&#xA;&#xD;&#xA;[![Bounding boxes for frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Camera frustum][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Resulting shadows][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e9845.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/bpXAc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/MJ3io.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a snippet of the code I'm using to generate the bounds for the orthographic matrix:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;       for (int i = 0; i &lt; numShadowCascades; i++) {&#xD;&#xA;                tempShadowBounds[4 * i + 0] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+0], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 1] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+1], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 2] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+2], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 3] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+3], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 4] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+4], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 5] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+5], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 6] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+6], 1.0f);&#xD;&#xA;                tempShadowBounds[4 * i + 7] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+7], 1.0f);&#xD;&#xA;                glm::vec3 frustumCenter = glm::vec3(0.0f);&#xD;&#xA;                for (int j = 4 * i; j &lt; ((4 * i) + 8); j++) {&#xD;&#xA;                    frustumCenter += tempShadowBounds[j];&#xD;&#xA;                }&#xD;&#xA;                frustumCenter /= 8.0f;&#xD;&#xA;&#xD;&#xA;                dirLightViews[i] = glm::lookAt(frustumCenter, frustumCenter - lightDir, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;                float maxX = std::numeric_limits&lt;float&gt;::lowest(); float maxY = maxX; &#xD;&#xA;                float maxZ = maxX;&#xD;&#xA;                float minX = std::numeric_limits&lt;float&gt;::max(); float minY = minX; &#xD;&#xA;                float minZ = minX;&#xD;&#xA;                using std::max; using std::min;&#xD;&#xA;                for (int j = 4 * i; j &lt; ((4 * i) + 8); j++) {&#xD;&#xA;                    glm::vec3 temp = dirLightViews[i] * glm::vec4(tempShadowBounds[j], 1.0f);&#xD;&#xA;                    maxX = max(maxX, temp.x);&#xD;&#xA;                    minX = min(minX, temp.x);&#xD;&#xA;                    maxY = max(maxY, temp.y);&#xD;&#xA;                    minY = min(minY, temp.y);&#xD;&#xA;                    maxZ = max(maxZ, temp.z);&#xD;&#xA;                    minZ = min(minZ, temp.z);&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                glm::mat4 cascadedOrtho = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);&#xD;&#xA;                cascadedShadowMatrices[i] = cascadedOrtho * dirLightViews[i];&#xD;&#xA;       }&#xD;&#xA;```&#xD;&#xA;The code is somewhat rough right now, but that's the gist of how I'm generating the bounding boxes. Another big problem is that you can see the transition between the shadow maps as you move the camera, and I'm not sure how to smooth that transition." ContentLicense="CC BY-SA 4.0" />
  <row Id="33247" PostHistoryTypeId="1" PostId="11016" RevisionGUID="d08901ce-584f-4245-9a15-c6b45917bc69" CreationDate="2021-07-06T00:13:18.757" UserId="16818" Text="Reducing Cascaded Shadow Mapping Artifacts" ContentLicense="CC BY-SA 4.0" />
  <row Id="33248" PostHistoryTypeId="3" PostId="11016" RevisionGUID="d08901ce-584f-4245-9a15-c6b45917bc69" CreationDate="2021-07-06T00:13:18.757" UserId="16818" Text="|opengl|c++|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33249" PostHistoryTypeId="5" PostId="11016" RevisionGUID="6ae750b2-cca2-4434-b2c6-a476ee700c79" CreationDate="2021-07-06T00:19:04.080" UserId="16818" Comment="added 199 characters in body" Text="I've been trying to get my cascaded shadow maps looking right for a while. I managed to fix the shimmering and most of the quantization artifacts, but for some reason the shadows still look really blocky. I'm using a resolution of 1024x1024. Here are images of the bounding boxes used for the orthographic matrices, the camera frustum, and the resulting shadows:&#xD;&#xA;&#xD;&#xA;[![Bounding boxes for frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Camera frustum][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Resulting shadows][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e9845.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/bpXAc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/MJ3io.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a snippet of the code I'm using to generate the bounds for the orthographic matrix:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;       for (int i = 0; i &lt; numShadowCascades; i++) {&#xD;&#xA;                //transform camera frustum split corners to world space&#xD;&#xA;                tempShadowBounds[4 * i + 0] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+0], 1.0f); //upper left&#xD;&#xA;                tempShadowBounds[4 * i + 1] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+1], 1.0f); //upper right&#xD;&#xA;                tempShadowBounds[4 * i + 2] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+2], 1.0f); //bottom left&#xD;&#xA;                tempShadowBounds[4 * i + 3] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+3], 1.0f); //bottom right&#xD;&#xA;                tempShadowBounds[4 * i + 4] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+4], 1.0f); //next upper left&#xD;&#xA;                tempShadowBounds[4 * i + 5] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+5], 1.0f); //next upper right&#xD;&#xA;                tempShadowBounds[4 * i + 6] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+6], 1.0f); //next bottom left&#xD;&#xA;                tempShadowBounds[4 * i + 7] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+7], 1.0f); //next bottom right&#xD;&#xA;                glm::vec3 frustumCenter = glm::vec3(0.0f);&#xD;&#xA;                for (int j = 4 * i; j &lt; ((4 * i) + 8); j++) {&#xD;&#xA;                    frustumCenter += tempShadowBounds[j];&#xD;&#xA;                }&#xD;&#xA;                frustumCenter /= 8.0f;&#xD;&#xA;&#xD;&#xA;                dirLightViews[i] = glm::lookAt(frustumCenter, frustumCenter - lightDir, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;                float maxX = std::numeric_limits&lt;float&gt;::lowest(); float maxY = maxX; &#xD;&#xA;                float maxZ = maxX;&#xD;&#xA;                float minX = std::numeric_limits&lt;float&gt;::max(); float minY = minX; &#xD;&#xA;                float minZ = minX;&#xD;&#xA;                using std::max; using std::min;&#xD;&#xA;                for (int j = 4 * i; j &lt; ((4 * i) + 8); j++) {&#xD;&#xA;                    glm::vec3 temp = dirLightViews[i] * glm::vec4(tempShadowBounds[j], 1.0f);&#xD;&#xA;                    maxX = max(maxX, temp.x);&#xD;&#xA;                    minX = min(minX, temp.x);&#xD;&#xA;                    maxY = max(maxY, temp.y);&#xD;&#xA;                    minY = min(minY, temp.y);&#xD;&#xA;                    maxZ = max(maxZ, temp.z);&#xD;&#xA;                    minZ = min(minZ, temp.z);&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                glm::mat4 cascadedOrtho = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);&#xD;&#xA;                cascadedShadowMatrices[i] = cascadedOrtho * dirLightViews[i];&#xD;&#xA;       }&#xD;&#xA;```&#xD;&#xA;The code is somewhat rough right now, but that's the gist of how I'm generating the bounding boxes. Another big problem is that you can see the transition between the shadow maps as you move the camera, and I'm not sure how to smooth that transition." ContentLicense="CC BY-SA 4.0" />
  <row Id="33250" PostHistoryTypeId="5" PostId="11016" RevisionGUID="f7036d26-f366-484d-b785-759d65ca65c2" CreationDate="2021-07-06T04:29:48.817" UserId="16818" Comment="added 240 characters in body" Text="I've been trying to get my cascaded shadow maps looking right for a while. I managed to fix the shimmering and most of the quantization artifacts, but for some reason the shadows still look really blocky. I'm using a resolution of 1024x1024. Here are images of the bounding boxes used for the orthographic matrices, the camera frustum, and the resulting shadows:&#xD;&#xA;&#xD;&#xA;[![Bounding boxes for frustum][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Camera frustum][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Resulting shadows][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e9845.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/bpXAc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/MJ3io.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is a snippet of the code I'm using to generate the bounds for the orthographic matrix:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;       for (int i = 0; i &lt; numShadowCascades; i++) {&#xD;&#xA;                //transform camera frustum split corners to world space&#xD;&#xA;                tempShadowBounds[4 * i + 0] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+0], 1.0f); //upper left&#xD;&#xA;                tempShadowBounds[4 * i + 1] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+1], 1.0f); //upper right&#xD;&#xA;                tempShadowBounds[4 * i + 2] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+2], 1.0f); //bottom left&#xD;&#xA;                tempShadowBounds[4 * i + 3] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+3], 1.0f); //bottom right&#xD;&#xA;                tempShadowBounds[4 * i + 4] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+4], 1.0f); //next upper left&#xD;&#xA;                tempShadowBounds[4 * i + 5] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+5], 1.0f); //next upper right&#xD;&#xA;                tempShadowBounds[4 * i + 6] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+6], 1.0f); //next bottom left&#xD;&#xA;                tempShadowBounds[4 * i + 7] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+7], 1.0f); //next bottom right&#xD;&#xA;                glm::vec3 frustumCenter = glm::vec3(0.0f);&#xD;&#xA;                for (int j = 4 * i; j &lt; ((4 * i) + 8); j++) {&#xD;&#xA;                    frustumCenter += tempShadowBounds[j];&#xD;&#xA;                }&#xD;&#xA;                frustumCenter /= 8.0f;&#xD;&#xA;&#xD;&#xA;                dirLightViews[i] = glm::lookAt(frustumCenter, frustumCenter - lightDir, glm::vec3(0.0f, 1.0f, 0.0f));&#xD;&#xA;                float maxX = std::numeric_limits&lt;float&gt;::lowest(); float maxY = maxX; &#xD;&#xA;                float maxZ = maxX;&#xD;&#xA;                float minX = std::numeric_limits&lt;float&gt;::max(); float minY = minX; &#xD;&#xA;                float minZ = minX;&#xD;&#xA;                using std::max; using std::min;&#xD;&#xA;                for (int j = 4 * i; j &lt; ((4 * i) + 8); j++) {&#xD;&#xA;                    glm::vec3 temp = dirLightViews[i] * glm::vec4(tempShadowBounds[j], 1.0f);&#xD;&#xA;                    maxX = max(maxX, temp.x);&#xD;&#xA;                    minX = min(minX, temp.x);&#xD;&#xA;                    maxY = max(maxY, temp.y);&#xD;&#xA;                    minY = min(minY, temp.y);&#xD;&#xA;                    maxZ = max(maxZ, temp.z);&#xD;&#xA;                    minZ = min(minZ, temp.z);&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                glm::mat4 cascadedOrtho = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);&#xD;&#xA;                cascadedShadowMatrices[i] = cascadedOrtho * dirLightViews[i];&#xD;&#xA;       }&#xD;&#xA;```&#xD;&#xA;The code is somewhat rough right now, but that's the gist of how I'm generating the bounding boxes. Another big problem is that you can see the transition between the shadow maps as you move the camera, and I'm not sure how to smooth that transition.&#xD;&#xA;&#xD;&#xA;The seams seem hard to eliminate. On a side note why don't people divide the world space into directional light chunks where each shadow map is assigned a section of world space, as opposed to cascaded shadow maps? Or am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33251" PostHistoryTypeId="5" PostId="11013" RevisionGUID="3c244d7d-afec-48b2-ba65-e02d49f984a1" CreationDate="2021-07-06T04:57:23.173" UserId="48" Comment="remove note about BC compression which was unhelpful" Text="You could look into wavelet image compression, which effectively stores a mip pyramid &quot;top down&quot; with each level storing only the diffs from the next-smaller level. This would effectively let you reconstruct whichever mip level you wanted from the same file at load time, with the file being the same overall size as only the base mip. However, it is likely more expensive to decompress than PNG for the same reason.&#xD;&#xA;&#xD;&#xA;The JPEG2000 format implements a wavelet compression method (as well as quantization and bitstream coding like other JPEG formats). I'm not sure if there are JPEG2000 libraries that support efficiently reconstructing multiple resolutions of the image while loading though." ContentLicense="CC BY-SA 4.0" />
  <row Id="33252" PostHistoryTypeId="2" PostId="11017" RevisionGUID="bf42a8d0-3e9c-4beb-8661-e0857e247488" CreationDate="2021-07-06T05:49:39.327" UserId="48" Text="If we have a vector in the upper hemisphere in tangent space, $(x, y, z)$ with $z &gt; 0$, then the slopes of the vector are $(\tilde x, \tilde y) = (-x/z, -y/z)$. These values are the slopes (derivatives), along $x$ and $y$, of a surface that is normal to the given vector. See also equation (4) in the paper, which is the conversion back and forth between slopes and vectors. &#xD;&#xA;&#xD;&#xA;The 2D space of slope values is called &quot;slope space&quot;. It is an unbounded space, so any $(\tilde x, \tilde y)$ point represents  a valid vector in tangent space (such as a microfacet normal). Geometrically, you can picture it like the intersection of the vector with the $z = 1$ plane. It produces an invertible, one-to-one mapping (bijection) between the upper hemisphere and the plane.&#xD;&#xA;&#xD;&#xA;Slope space is often used in microfacet BRDF theory because of its desirable properties. Since it is unbounded, it can be more convenient to define functions and do mathematics in slope space than in spherical coordinates, or directly on the normals. Geometric transformations on the microfacet surface, such as scaling and shearing, have straightforward expressions in slope space. The most common NDFs, Beckmann and GGX, also have a simpler expressions in slope space: Beckmann is a Gaussian distribution in slope space, while [GGX is a Student's t-distribution in slope space](https://mribar03.bitbucket.io/projects/eg_2017/distribution.pdf)." ContentLicense="CC BY-SA 4.0" />
  <row Id="33253" PostHistoryTypeId="5" PostId="11003" RevisionGUID="0ce3d172-8fc6-42f1-bdb6-7b52b7b79d89" CreationDate="2021-07-06T11:33:49.550" UserId="16789" Comment="added 414 characters in body" Text="**situation:**&#xD;&#xA;&#xD;&#xA;I've implemented a Whitted style ray tracing in C. Everything appear to works except the shadow cast by small object on big far objects&#xD;&#xA;&#xD;&#xA;**The problem :**&#xD;&#xA;&#xD;&#xA;red sphere have radius 0.5&#xD;&#xA;orange sphere have radius 200&#xD;&#xA;[![example][1]][1]&#xD;&#xA;zooming:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;more:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;increasing the distance and the radius of the orange sphere:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;So fare, I could only suspect rounding error due to the fact that I use float.&#xD;&#xA;In &quot;normal&quot; situation, the shadows work great.&#xD;&#xA;Have you already encounter that kind of error ? Is my guess correct, or could that be something else ? &#xD;&#xA;&#xD;&#xA;Not sure the code could help because messy, but there it is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;static inline uint8_t	diffuse(const struct s_bvh *bvh,&#xD;&#xA;	const t_lght *lght, const t_hinfo *hi, t_vec3f diff)&#xD;&#xA;{&#xD;&#xA;	t_vec3f			light;&#xD;&#xA;	struct s_hit	h;&#xD;&#xA;	float			dp;&#xD;&#xA;	float			length;&#xD;&#xA;    &#xD;&#xA;    //make the [hit_pts -&gt; light_pts] vector&#xD;&#xA;	sub_(lght-&gt;pts, hi-&gt;r-&gt;o, hi-&gt;r-&gt;d);&#xD;&#xA;	length = norm(hi-&gt;r-&gt;d);&#xD;&#xA;    //minimum to avoid self intersection&#xD;&#xA;	h.min = 0.001f;&#xD;&#xA;    //maximum &#xD;&#xA;	h.t = length;&#xD;&#xA;	normalize(hi-&gt;r-&gt;d);&#xD;&#xA;	dp = dotp(hi-&gt;n, hi-&gt;r-&gt;d);&#xD;&#xA;	if (dp &gt; 0.0f)&#xD;&#xA;	{&#xD;&#xA;        //invertion fo the ray_direction and traverse the BVH tree&#xD;&#xA;		invert_(hi-&gt;r-&gt;d, hi-&gt;r-&gt;inv_d);&#xD;&#xA;		traverser(bvh, hi-&gt;r, &amp;h, 1);&#xD;&#xA;        //if in shadow, return (0)&#xD;&#xA;		if (h.t &lt; length)&#xD;&#xA;			return (0);&#xD;&#xA;        // else apply the light&#xD;&#xA;		s_scale(lght-&gt;color, dp, light);&#xD;&#xA;		add_(light, diff, diff);&#xD;&#xA;		return (1);&#xD;&#xA;	}&#xD;&#xA;	return (0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void	diffusel(const struct s_bvhl *s, const t_hinfo *hi, t_vec3f color)&#xD;&#xA;{&#xD;&#xA;	t_vec3f			ambi;&#xD;&#xA;	t_vec3f			diff;&#xD;&#xA;	uint32_t		i;&#xD;&#xA;&#xD;&#xA;	i = 0;&#xD;&#xA;	mult_(s-&gt;lghts.amb, color, ambi);&#xD;&#xA;	set_vector(diff, 0.f, 0.f, 0.f);&#xD;&#xA;    //for each light&#xD;&#xA;	while (i &lt; s-&gt;lghts.count)&#xD;&#xA;	{&#xD;&#xA;		diffuse(&amp;s-&gt;bvh, s-&gt;lghts.lghts + i, hi, diff);&#xD;&#xA;		++i;&#xD;&#xA;	}&#xD;&#xA;	mult_(color, diff, color);&#xD;&#xA;	add_(ambi, color, color);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/siIfu.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2BAk1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uaVmE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/rzCnQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33254" PostHistoryTypeId="2" PostId="11018" RevisionGUID="fb01ec5c-b567-41cb-aa13-c200510db0b4" CreationDate="2021-07-06T13:31:02.190" UserId="16821" Text="I am new to this awesome community, I am currently writing a ray tracer but I hit a problem...&#xD;&#xA;&#xD;&#xA;Let's say I have a surface(material doesn't matter) of colour [1, 0, 0] in RGB, and the radiance reaching a point on the surface is say 2000 units.&#xD;&#xA;&#xD;&#xA;So my question is, after all the simulation, just before writing an output file(for example png), what operation or algorithm do I use to modify the colour using the radiance value, to give an perception of brightness.&#xD;&#xA;If the radiance is to high, the output should give a somewhat white-ish colour, and if the radiance is less, it has to give a dark-ish colour.&#xD;&#xA;&#xD;&#xA;Is there anyway I can do this easily and efficiently, or is it a complex process?&#xD;&#xA;&#xD;&#xA;This is a rendered image from Blender...&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see in the image, the place closer to the light is white-ish(due to higher radiance reaching it) and rest is red or darker red, so what do I do to get a result like that?&#xD;&#xA;&#xD;&#xA;I have no idea how to actually perform something like to get the expected RGB value...&#xD;&#xA;&#xD;&#xA;Note: I want to generate a PNG image and not a .HDR or .EXR image&#xD;&#xA;&#xD;&#xA;I hope the question is clear, and hopefully isn't a duplicate because I couldn't find my answer anywhere else...&#xD;&#xA;&#xD;&#xA;Any help would be highly appreciated, thanks :)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dEVz8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33255" PostHistoryTypeId="1" PostId="11018" RevisionGUID="fb01ec5c-b567-41cb-aa13-c200510db0b4" CreationDate="2021-07-06T13:31:02.190" UserId="16821" Text="How to change a RGB value using a luminance value?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33256" PostHistoryTypeId="3" PostId="11018" RevisionGUID="fb01ec5c-b567-41cb-aa13-c200510db0b4" CreationDate="2021-07-06T13:31:02.190" UserId="16821" Text="|raytracing|color|physically-based|image|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33257" PostHistoryTypeId="4" PostId="11018" RevisionGUID="c3ab0978-cab0-481e-8742-8240252b9494" CreationDate="2021-07-06T13:54:29.570" UserId="16821" Comment="edited title" Text="How to change a RGB value using a radiance value?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33258" PostHistoryTypeId="2" PostId="11019" RevisionGUID="7b04ec3a-1903-47e0-b3b3-1ae56f065d17" CreationDate="2021-07-06T14:00:55.350" UserId="7952" Text="Getting high quality shadows from Cascade Shadow maps with (relatively) low resolution shadow maps is a process. I recommend taking on different aspects one at a time.&#xD;&#xA;&#xD;&#xA;Here are few generic suggestions...&#xD;&#xA;Shadow transitions between cascade zones can be handled by allowing the cascades to overlap by a small amount then computing a lerp value for each zone. The zone near the camera goes from 1 to 0 inside the overlap region and the next zone goes from 0 to 1 inside the overlap region. Then tweaking the size of overlap to get the best visuals to performance.&#xD;&#xA;&#xD;&#xA;Allow the number of cascades to vary depending on the region, and/or quality setting. Once you have the basic algorithm working, changing the number of cascades (usually between 3 and 6) can help and isn't to hard to add. This is especially helpful with large open world areas.&#xD;&#xA;&#xD;&#xA;PCSS can be implemented reasonably easily with cascade maps, enabling hardware interpolation and hardware bias settings will help and can get you down to the minimum samples while still getting good performance. This is another place that a quality setting can be handy.&#xD;&#xA;&#xD;&#xA;Computing a best fit for the cascade frustums can help considerably, but there are as many ways to do this as there are people writing cascade shadow maps.&#xD;&#xA;&#xD;&#xA;Here is a link to a [Microsoft web][1] site that has some good tips on dealing with aliasing issues.&#xD;&#xA;&#xD;&#xA;Also, I recommend asking specific question regarding specific issues with some of the techniques described above (or others that you find). It's hard to give a good answer to such a broad question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/dxtecharts/common-techniques-to-improve-shadow-depth-maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="33259" PostHistoryTypeId="2" PostId="11020" RevisionGUID="1946ccb6-ed05-4723-bba6-28283d29f28c" CreationDate="2021-07-06T18:55:18.797" UserId="48" Text="What you're looking for is called *tone mapping*, which is the process of mapping from HDR color values generated by a physically based renderer, to LDR color values suitable for display on a screen. It also incorporates changes in saturation, such as desaturating the color when the values get very bright. You will likely also need *exposure compensation* prior to tone mapping, in order to set the overall brightness of the image to an appropriate level.&#xD;&#xA;&#xD;&#xA;There are many different tone mapping curves out there; it's an aesthetic choice, so there's no &quot;right answer&quot;, but a good one to start with might be the [ACES curve, with analytic approximation given by &#xD;&#xA;Krzysztof Narkowicz](https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float3 ACESFilm(float3 x)&#xD;&#xA;{&#xD;&#xA;    float a = 2.51f;&#xD;&#xA;    float b = 0.03f;&#xD;&#xA;    float c = 2.43f;&#xD;&#xA;    float d = 0.59f;&#xD;&#xA;    float e = 0.14f;&#xD;&#xA;    return saturate((x*(a*x+b))/(x*(c*x+d)+e));&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;See also [this blog post](https://bruop.github.io/tonemapping/) for more background and comparisons of different tone mapping approaches.&#xD;&#xA;&#xD;&#xA;You'll want to apply an exposure scaling, and limit the saturation of colors to slightly less than 100% (otherwise, perfectly saturated colors like (1, 0, 0) will not desaturate to white, but will remain saturated). Then apply this curve, and finally gamma encoding ([linear to sRGB](https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation)) to get the final output values in [0, 1]. In code, something like:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float3 LinearToSRGB(float3 x)&#xD;&#xA;{&#xD;&#xA;    return (x &lt; 0.0031308f) ?&#xD;&#xA;                x * 12.92f :&#xD;&#xA;                pow(x, 1.0f/2.4f) * 1.055f - 0.055f;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float3 HDRToOutput(float3 hdr, float exposure)&#xD;&#xA;{&#xD;&#xA;    // Exposure (tune the value to set the overall brightness;&#xD;&#xA;    // positive makes it brighter, while negative makes it darker)&#xD;&#xA;    hdr *= exp2(exposure);&#xD;&#xA;&#xD;&#xA;    // Limit saturation to 99% - maps pure colors like (1, 0, 0) to (1, 0.01, 0.01)&#xD;&#xA;    float maxComp = max(hdr.r, hdr.g, hdr.b);&#xD;&#xA;    hdr = max(hdr, 0.01 * maxComp);&#xD;&#xA;&#xD;&#xA;    // Apply tonemapping curve&#xD;&#xA;    float3 ldrLinear = ACESFilm(hdr);&#xD;&#xA;&#xD;&#xA;    // Convert to sRGB&#xD;&#xA;    float3 ldrSRGB = LinearToSRGB(hdr);&#xD;&#xA;    return ldrSRGB;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33260" PostHistoryTypeId="2" PostId="11021" RevisionGUID="0f60c594-c97e-4b04-a6e0-4fe044825c83" CreationDate="2021-07-07T00:53:27.620" UserId="48" Text="The blockiness of the shadows in your screenshot looks to me like the expected results from using the hardware bilinear PCF to sample the shadow map. Unfortunately this is just not a very good filter. It's necessary to use a wider filter to get smooth shadows. This could be as simple as doing multiple bilinear PCF samples at offset locations, and averaging the results. This will blur out the shadows a lot, but you could then apply a sharpening function to the result to obtain sharper shadows with smoother boundaries.&#xD;&#xA;&#xD;&#xA;Shadow map filtering is a big topic and can get very complicated (just google &quot;shadow map filtering&quot; and you'll find plenty of reading material)." ContentLicense="CC BY-SA 4.0" />
  <row Id="33261" PostHistoryTypeId="2" PostId="11022" RevisionGUID="13c45482-5801-4005-98e2-8b3cb2a97d14" CreationDate="2021-07-07T02:09:28.960" UserId="16793" Text="I'm recently looking into how slope space is used in microfacet BRDF. Can anyone help to explain how Beckmann is a Gaussian distribution in slope space? Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="33262" PostHistoryTypeId="1" PostId="11022" RevisionGUID="13c45482-5801-4005-98e2-8b3cb2a97d14" CreationDate="2021-07-07T02:09:28.960" UserId="16793" Text="How to understand Beckmann is a Gaussian distribution in slope space" ContentLicense="CC BY-SA 4.0" />
  <row Id="33263" PostHistoryTypeId="3" PostId="11022" RevisionGUID="13c45482-5801-4005-98e2-8b3cb2a97d14" CreationDate="2021-07-07T02:09:28.960" UserId="16793" Text="|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33265" PostHistoryTypeId="5" PostId="11010" RevisionGUID="ee9c1347-06e3-4542-b329-fbd5ce3f81b9" CreationDate="2021-07-08T06:00:49.690" UserId="6046" Comment="added 345 characters in body" Text="I'm asking this question on behalf of a friend so can't provide any images for now. The problem is to simulate a car paint material with some flakes or graininess in it. This is first done in blender by creating a material. The flakes are added by using flakes normal map which simulates all the perturbed normals. I suppose this causes micro variations which causes the base color to drop at random locations giving the effect of graininess.&#xD;&#xA;&#xD;&#xA;Now blender provides a [normal map node][1] which is used in the shader graph. This has a strength parameter. When the strength is 0, there are no flakes. I searched around the net and found that this effect is probably achieved by lerping between the sampled normal from the normal map and the vector `0.5, 0.5, 1` which seems to be a null or flat normal as it maps to `0,0,1` in the tangent space which means no change.&#xD;&#xA;&#xD;&#xA;The question is, as I understood, changing normals should affect the reflections on the surface, however when I change the strength in blender between 0 and 1, only the graininess changes and the reflection remains the same. When I say the reflection should change, I mean the position of the reflection should change, since the reflection vector would change based on the normal. This doesn't seem to happen in blender. Are they using the plain original normals for reflection and the perturbed ones for other kind of shading?&#xD;&#xA;&#xD;&#xA;He implemented the same technique in threejs and it seems the reflections don't change there as well. However, instead of lerping between the sampled normal and `0.5, 0.5, 1` when we lerped between the sampled normal (after converting it to -1 to 1) and the original geometric normal based on the strength, the reflections on the surface moved as I expected. Can anybody explain what happened? What's the difference between the 2 approaches and why in only the second approach the reflections move or change their position?&#xD;&#xA;&#xD;&#xA;UPDATE:- Turns out there was a slight error in triplanar mapping. After fixing it, the reflections do change positions slightly when implemented in threejs. So now the reflection change position in threejs implementation both ways but I still don't understand why the same doesn't happen in blender. Will update if I figure it out eventually&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.blender.org/manual/en/latest/render/shader_nodes/vector/normal_map.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="33267" PostHistoryTypeId="2" PostId="11024" RevisionGUID="4084a4b3-f360-4d11-84e3-6162384bc470" CreationDate="2021-07-08T13:32:36.310" UserId="16853" Text="Being faced with a design decision, I have to choose between supporting anisotropic surfaces or not in my ray tracer. Is there any common use case of this feature other than simulating velvet (that may motivate me to go with the former choice)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33268" PostHistoryTypeId="1" PostId="11024" RevisionGUID="4084a4b3-f360-4d11-84e3-6162384bc470" CreationDate="2021-07-08T13:32:36.310" UserId="16853" Text="Examples of anisotropic surfaces" ContentLicense="CC BY-SA 4.0" />
  <row Id="33269" PostHistoryTypeId="3" PostId="11024" RevisionGUID="4084a4b3-f360-4d11-84e3-6162384bc470" CreationDate="2021-07-08T13:32:36.310" UserId="16853" Text="|raytracing|material|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33270" PostHistoryTypeId="5" PostId="11024" RevisionGUID="cd57fb16-14b3-4d28-92d2-116fd45ddaf5" CreationDate="2021-07-08T13:52:50.033" UserId="16853" Comment="deleted 5 characters in body" Text="Being faced with a design choice, I have to decide between supporting anisotropic surfaces or not in my ray tracer. Is there any common use case of this feature other than velvet (so that I may be motivated to go with the former decision)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33271" PostHistoryTypeId="2" PostId="11025" RevisionGUID="58a6ec18-f865-47bb-906b-9d6ca25c4c3e" CreationDate="2021-07-08T16:20:25.303" UserId="72" Text="A really common case in the real world are industrially fabricated metal surfaces which often contain patterns (due to their creation process) with strongly anisotropic normal distributions, especially if they haven't been polished. &#xD;&#xA;&#xD;&#xA;Some of these patterns may only occur at the macro scale from common viewpoints (i.e. irrelevant for your BRDF), but on a lot of them this will happen at the microfacet scale.&#xD;&#xA;&#xD;&#xA;Look at the horizontal stripes in this pan (random google result) for example.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In a common virtual scene where this pan covers a few dozen square pixels, these will be way too small to be modeled as detail in something like a normal map or geometric detail. Some of the patterns are already hard to see in the image, but undoubtedly contribute to the overall look of the material.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LUkZm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="33272" PostHistoryTypeId="5" PostId="11025" RevisionGUID="d90e1eae-a939-45a1-9c32-6e447de0e158" CreationDate="2021-07-08T16:34:15.543" UserId="72" Comment="added 1 character in body" Text="A really common case in the real world are industrially fabricated metal surfaces which often contain patterns (due to their creation process) with strongly anisotropic surface distributions, especially if they haven't been polished. &#xD;&#xA;&#xD;&#xA;Some of these patterns may only occur at the macro scale from common viewpoints (i.e. irrelevant for your BRDF), but on a lot of them this will happen at the microfacet scale.&#xD;&#xA;&#xD;&#xA;Look at the horizontal stripes in this pan (random google result) for example.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In a common virtual scene where this pan covers a few dozen square pixels, these will be way too small to be modeled as detail in something like a normal map or geometric detail. Some of the patterns are already hard to see in the image, but undoubtedly contribute to the overall look of the material.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LUkZm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="33278" PostHistoryTypeId="2" PostId="11027" RevisionGUID="89feccf4-5cae-4a01-9afb-9ba6feb5e9f9" CreationDate="2021-07-09T05:54:02.600" UserId="38" Text="* Most manufactured items that are made by grinder, milling, shaper or lathe that have not been polished. Due to tiny grooves caused by the cutting head.&#xD;&#xA;* Intentionally brushed surfaces. Mainly to make it harder to see scratching. Used for example on mesh panels of elevators, escalators etc.&#xD;&#xA;* Hair, animal or human. Hair has a microstructure much like a surface that has been lathed. But also a surface covered by small hair has a anisotropic behaviour even without this as you mention in your velvet example.&#xD;&#xA;* Many Fabrics are anisotropic on account of them being made out of strands etc.&#xD;&#xA;* Wood grain causes wooden structures to be anisotropic. Although the effect is subtle as they are usually not terribly reflective and can probably be modeled by macroscale bumpmapping in closeup shots only.&#xD;&#xA;* 3D printed items etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see a designer of industrial goods might be super interested in seeing anisotropic materisls in their scenes." ContentLicense="CC BY-SA 4.0" />
  <row Id="33280" PostHistoryTypeId="5" PostId="11027" RevisionGUID="9945673a-7f5d-4193-b795-9fd9a05d8f3f" CreationDate="2021-07-09T16:14:37.457" UserId="38" Comment="added 1 character in body" Text="* Most manufactured items that are made by grinder, milling, shaper or lathe that have not been polished. Due to tiny grooves caused by the cutting head.&#xD;&#xA;* Intentionally brushed surfaces. Mainly to make it harder to see scratching. Used for example on metal panels of elevators, escalators etc.&#xD;&#xA;* Hair, animal or human. Hair has a microstructure much like a surface that has been lathed. But also a surface covered by small hair has a anisotropic behaviour even without this as you mention in your velvet example.&#xD;&#xA;* Many Fabrics are anisotropic on account of them being made out of strands etc.&#xD;&#xA;* Wood grain causes wooden structures to be anisotropic. Although the effect is subtle as they are usually not terribly reflective and can probably be modeled by macroscale bumpmapping in closeup shots only.&#xD;&#xA;* 3D printed items etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see a designer of industrial goods might be super interested in seeing anisotropic materisls in their scenes." ContentLicense="CC BY-SA 4.0" />
  <row Id="33281" PostHistoryTypeId="5" PostId="11027" RevisionGUID="bb247f01-58d4-4bd7-b81e-1e3eb6cdb62f" CreationDate="2021-07-09T19:37:03.173" UserId="38" Comment="added 13 characters in body" Text="* Most manufactured items that are made by grinder, milling, shaper or lathe that have not been polished. Due to tiny grooves caused by the cutting head.&#xD;&#xA;* Intentionally brushed surfaces. Mainly to make it harder to see scratching. Used for example on metal panels of elevators, escalators etc.&#xD;&#xA;* Hair, animal or human. Hair has a microstructure much like a surface that has been turned with a lathe. But also a surface covered by small hair has a anisotropic behaviour even without this as you mention in your velvet example.&#xD;&#xA;* Many Fabrics are anisotropic on account of them being made out of strands etc.&#xD;&#xA;* Wood grain causes wooden structures to be anisotropic. Although the effect is subtle as they are usually not terribly reflective and can probably be modeled by macroscale bumpmapping in closeup shots only.&#xD;&#xA;* 3D printed items etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As you can see a designer of industrial goods might be super interested in seeing anisotropic materisls in their scenes." ContentLicense="CC BY-SA 4.0" />
  <row Id="33282" PostHistoryTypeId="50" PostId="10301" RevisionGUID="9f6a91d1-0cbe-496e-b98d-9d8875084c8f" CreationDate="2021-07-09T21:08:50.860" UserId="-1" />
  <row Id="33284" PostHistoryTypeId="2" PostId="11028" RevisionGUID="714159fc-9409-4a12-b189-77bd539ee382" CreationDate="2021-07-10T03:25:28.210" UserId="7462" Text="Let me explain what I am doing. I am trying to reduce the memory footprint of a voxel based algorithm by storing the voxel data as a hash map in an SSBO, as opposed to a 3D image.&#xD;&#xA;&#xD;&#xA;I am visualizing the complexity of rendering each voxel and that creates this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The more white a voxel is, the more expensive to compute it is. So most voxels are dark grey and a few are a little more clear. This means my algorithm seems to be working quite well. This represents a reduction from 128^3 to about 25 000 buckets of total memory used (i.e. the ssbo hash table only has 25k allocated indices). And it is rendering at about 40 fps on average (depends on view port location).&#xD;&#xA;&#xD;&#xA;The logic for my hash table is encapsulated by these shader functions:&#xD;&#xA;&#xD;&#xA;hash_function.glsl&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;layout(binding = 3) uniform VoxelData&#xD;&#xA;{&#xD;&#xA;    int resolution;&#xD;&#xA;    uint display_width;&#xD;&#xA;    uint display_height;&#xD;&#xA;    float scale;&#xD;&#xA;    vec3 locus;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct Node&#xD;&#xA;{&#xD;&#xA;    ivec4 key;&#xD;&#xA;    vec4 value;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(scalar, binding = 4) buffer hash_tree_ssbo&#xD;&#xA;{&#xD;&#xA;    int depth;&#xD;&#xA;    int depth_size;&#xD;&#xA;    int size;&#xD;&#xA;    int pad2;&#xD;&#xA;    Node hash_tree[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;int HashFunction(ivec3 coord, int m)&#xD;&#xA;{&#xD;&#xA;    const int p1 = 7979;&#xD;&#xA;    const int p2 = 3229;&#xD;&#xA;    const int p3 = 7877;&#xD;&#xA;&#xD;&#xA;    return abs(coord.x * p3 + coord.y * p2 + coord.z * p1) % 25000;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 ReadValue(ivec3 coord, int lod)&#xD;&#xA;{&#xD;&#xA;    int offset = 0;&#xD;&#xA;&#xD;&#xA;    const int local_size = int(size &gt;&gt; lod);&#xD;&#xA;    int hash = HashFunction(coord, local_size);&#xD;&#xA;    vec4 read_hash = hash_tree[hash + offset].value;&#xD;&#xA;&#xD;&#xA;    uint safety = 0;&#xD;&#xA;    while(read_hash.a != 0.f &amp;&amp; hash_tree[hash + offset].key.xyz != coord)&#xD;&#xA;    {&#xD;&#xA;        hash = (hash * 7) % local_size;&#xD;&#xA;        read_hash = hash_tree[hash + offset].value;&#xD;&#xA;        if(safety++ &gt; 10) return vec4(0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if(hash_tree[hash + offset].key.xyz == coord)&#xD;&#xA;        return hash_tree[hash + offset].value;&#xD;&#xA;&#xD;&#xA;    return vec4(0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void StoreValue(vec4 val, ivec3 coord, int lod)&#xD;&#xA;{&#xD;&#xA;    int offset = 0;&#xD;&#xA;&#xD;&#xA;    const int local_size = int(size &gt;&gt; lod);&#xD;&#xA;    int hash = HashFunction(coord, local_size);&#xD;&#xA;    float read_hash = hash_tree[hash + offset].value.a;&#xD;&#xA;&#xD;&#xA;    uint safety = 0;&#xD;&#xA;    while(read_hash != 0.f &amp;&amp; hash_tree[hash + offset].key.xyz != coord)&#xD;&#xA;    {&#xD;&#xA;        hash = (hash * 7) % local_size;&#xD;&#xA;        read_hash = hash_tree[hash + offset].value.a;&#xD;&#xA;        if(safety++ &gt; 10) return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    val = vec4(vec3(float(safety + 1)) / 10.f, 1);&#xD;&#xA;&#xD;&#xA;    hash_tree[hash + offset].value = val;&#xD;&#xA;    hash_tree[hash + offset].key = ivec4(coord, 0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec3 WorldPositionToVoxelCoords(vec3 position, int lod)&#xD;&#xA;{&#xD;&#xA;    const uint lod_resolution = resolution &gt;&gt; lod;&#xD;&#xA;    const vec3 relative_pos = position - locus;&#xD;&#xA;    ivec3 texel = ivec3( (vec3(0.5) + relative_pos / (2.f * scale) ) * lod_resolution );&#xD;&#xA;    texel.y = int(lod_resolution) - texel.y;&#xD;&#xA;&#xD;&#xA;    return texel;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ivec3 NormalizedPositionToVoxelCoords(vec3 position, int lod)&#xD;&#xA;{&#xD;&#xA;    const uint lod_resolution = resolution &gt;&gt; lod;&#xD;&#xA;    vec3 final = (position + vec3(1)) * (lod_resolution / 2.f);&#xD;&#xA;    final.y = lod_resolution - final.y;&#xD;&#xA;&#xD;&#xA;    return ivec3(final);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As said before, this logic works. Now observer what happens if I change offset from 0 to `offset = 1;`&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now almost every voxel that requires multiple hashes disappears. And yet, the logic when offset = 1 and when offset = 0 should be identical, save that the SSBO accesses should be shifted by a little (I am changing BOTH instances of offset = 1, I did not forget to update one but not the other).&#xD;&#xA;&#xD;&#xA;If I eliminate the modulus operation from the hash function and merely return `return abs(coord.x * p3 + coord.y * p2 + coord.z * p1)`, I get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Because now I am using the entire allocated span of the SSBO (128^3). So no collisions happen.&#xD;&#xA;&#xD;&#xA;I am puzzled, how can a simple addition royally break shader logic like this?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GVl6A.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/JbDWn.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hLjC4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33285" PostHistoryTypeId="1" PostId="11028" RevisionGUID="714159fc-9409-4a12-b189-77bd539ee382" CreationDate="2021-07-10T03:25:28.210" UserId="7462" Text="Offsetting value in shader causes unexpected/wrong logic" ContentLicense="CC BY-SA 4.0" />
  <row Id="33286" PostHistoryTypeId="3" PostId="11028" RevisionGUID="714159fc-9409-4a12-b189-77bd539ee382" CreationDate="2021-07-10T03:25:28.210" UserId="7462" Text="|shader|vulkan|compute-shader|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33288" PostHistoryTypeId="2" PostId="11030" RevisionGUID="fd9a38b7-3ca8-44c7-b558-a118420b9d3d" CreationDate="2021-07-10T17:54:12.083" UserId="11058" Text="I need to create a ray to pick objects in 3d environment using cursor.&#xD;&#xA;&#xD;&#xA;For orthogonal projection we accomplish this by taking the cursor position, and we unproject it to the near and far plane on of the view frustum. The direction of the ray is then the difference of the unprojected points $p_{far}-p_{near}$. The origin of the ray should be $p_{near}$. &#xD;&#xA;&#xD;&#xA;However I'm not completely sure about how we should approach this problem for perspective projection. Should we consider the camera position as the ray origin or should it be $p_{near}$? And should the direction then be `$p_{far}-p_{near}$ or $p_{far}-p_{camera}$?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33289" PostHistoryTypeId="1" PostId="11030" RevisionGUID="fd9a38b7-3ca8-44c7-b558-a118420b9d3d" CreationDate="2021-07-10T17:54:12.083" UserId="11058" Text="What should be considered the origin of a ray used for object picking" ContentLicense="CC BY-SA 4.0" />
  <row Id="33290" PostHistoryTypeId="3" PostId="11030" RevisionGUID="fd9a38b7-3ca8-44c7-b558-a118420b9d3d" CreationDate="2021-07-10T17:54:12.083" UserId="11058" Text="|projections|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33291" PostHistoryTypeId="5" PostId="11030" RevisionGUID="d8c09cca-a7d5-4670-96e3-1db105ba6c63" CreationDate="2021-07-10T17:59:35.537" UserId="11058" Comment="added 109 characters in body" Text="I need to create a ray to pick objects in 3d environment using cursor.&#xD;&#xA;&#xD;&#xA;I'm not going to go into detailed math for this question. There's tons of information on that. In short terms, for orthogonal projection we accomplish this by taking the cursor position, and we unproject it to the near and far plane of the view frustum. The direction of the ray is then the normalized difference of the unprojected points $p_{far}-p_{near}$. The origin of the ray should be $p_{near}$. &#xD;&#xA;&#xD;&#xA;However I'm not completely sure about how we should approach this problem for perspective projection. Should we consider the camera position as the ray origin or should it be $p_{near}$? And should the direction then be the normalized difference `$p_{far}-p_{near}$ or $p_{far}-p_{camera}$?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33292" PostHistoryTypeId="4" PostId="11030" RevisionGUID="b7ae5839-81cb-420a-8a41-19b4c0e0a749" CreationDate="2021-07-10T18:55:53.037" UserId="11058" Comment="edited title" Text="What should be considered the origin of a ray used for object picking with perspective projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="33296" PostHistoryTypeId="2" PostId="11032" RevisionGUID="f0f85b5d-77d4-4e3b-b450-be3cde8f4ec4" CreationDate="2021-07-11T21:41:38.483" UserId="16867" Text="I am implementing Jerry Tessendorf's ocean waves as described in his [paper](https://www.researchgate.net/publication/264839743_Simulating_Ocean_Water) in c++ and OpenGL.&#xD;&#xA;&#xD;&#xA;I implemented two compute shaders, one for the h_tilde_0 and its conjugate, and one for the frequency function for the IFFT.&#xD;&#xA;&#xD;&#xA;After performing the real to complex IFFT using [GLFFT](https://github.com/Themaister/GLFFT) I obtain the following height map after normalizing the obtained values between 0 and 255:&#xD;&#xA;&#xD;&#xA;[![height map][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The first 20 values of the height map before normalizing are:&#xD;&#xA;&#xD;&#xA; - \[0] = {float} -24667.7344&#xD;&#xA; - \[1] = {float} 23987.6855&#xD;&#xA; - \[2] = {float} -22951.1094&#xD;&#xA; - \[3] = {float} 22144.1914&#xD;&#xA; - \[4] = {float} -21596.2676&#xD;&#xA; - \[5] = {float} 22228.2578&#xD;&#xA; - \[6] = {float} -23422.1855&#xD;&#xA; - \[7] = {float} 23971.5117&#xD;&#xA; - \[8] = {float} -24944.8633&#xD;&#xA; - \[9] = {float} 26373.8594&#xD;&#xA; - \[10] = {float} -28082.5977&#xD;&#xA; - \[11] = {float} 29593.1387&#xD;&#xA; - \[12] = {float} -30536.7344&#xD;&#xA; - \[13] = {float} 31605.7578&#xD;&#xA; - \[14] = {float} -33134.7813&#xD;&#xA; - \[15] = {float} 34946.293&#xD;&#xA; - \[16] = {float} -36430.6445&#xD;&#xA; - \[17] = {float} 37443.6523&#xD;&#xA; - \[18] = {float} -38190.6758&#xD;&#xA; - \[19] = {float} 39565.5781&#xD;&#xA; - \[20] = {float} -41436.6563&#xD;&#xA;&#xD;&#xA;So the values I get after the inverse fourier transform are with inverted signs in an interleaved fashion. &#xD;&#xA;And if I were to skip every odd value I get the following height map:&#xD;&#xA;&#xD;&#xA;[![height map][2]][2]&#xD;&#xA;&#xD;&#xA;And skipping even values (same IFFT):&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;It looks like the previous image contains the height map and the opposite sign version of itself. Since it looks like the height field is somehow encoded I don't think that the error is on the generation of the spectrum. I think of two possibilities:&#xD;&#xA;&#xD;&#xA; 1. I have wrong coordinates in the frequency domain and somehow produce this result.&#xD;&#xA; 2. I am not understanding how GLFFT expects the input and how the output is given. I have been reading the glsl files in the GLFFT repository and I can't find any mistakes.&#xD;&#xA;&#xD;&#xA;I understand that the question is very broad and I am maybe not giving enough information (please tell me if I should upload any other code of result). I have been trying to debug the problem but I am not making any progress. &#xD;&#xA;&#xD;&#xA;Thanks in advance for any help!&#xD;&#xA;&#xD;&#xA;Appendice:&#xD;&#xA;&#xD;&#xA;How I am performing the IFFT:&#xD;&#xA;&#xD;&#xA;    std::shared_ptr&lt;abstractions::SSBO&gt; update_fft_texture(ssbo_pointer&amp; h_k_t, int N){&#xD;&#xA;        GLFFT::FFTOptions options;&#xD;&#xA;        options.type.fp16 = false;&#xD;&#xA;        options.type.output_fp16 = false;&#xD;&#xA;        options.type.input_fp16 = false;&#xD;&#xA;        GLFFT::GLContext context;&#xD;&#xA;&#xD;&#xA;        GLFFT::FFT fft(&amp;context, N, N, GLFFT::ComplexToReal, GLFFT::Inverse, GLFFT::SSBO, GLFFT::SSBO, std::make_shared&lt;GLFFT::ProgramCache&gt;(), options);&#xD;&#xA;&#xD;&#xA;        GLuint output_texture, input_texture;&#xD;&#xA;&#xD;&#xA;        std::shared_ptr&lt;abstractions::SSBO&gt; out(new abstractions::SSBO(nullptr, 4*N*N, GL_DYNAMIC_COPY));&#xD;&#xA;&#xD;&#xA;        input_texture = (*h_k_t).GetRendererId();&#xD;&#xA;        output_texture = (*out).GetRendererId();&#xD;&#xA;&#xD;&#xA;        // Adapt raw GL types to types which GLContext uses internally.&#xD;&#xA;        GLFFT::GLBuffer adaptor_output(output_texture);&#xD;&#xA;        GLFFT::GLBuffer adaptor_input(input_texture);&#xD;&#xA;&#xD;&#xA;        GLCall(&#xD;&#xA;                {&#xD;&#xA;                    // Do the FFT&#xD;&#xA;                    GLFFT::CommandBuffer *cmd = context.request_command_buffer();&#xD;&#xA;                    fft.process(cmd, &amp;adaptor_output, &amp;adaptor_input);&#xD;&#xA;                    context.submit_command_buffer(cmd);&#xD;&#xA;                }&#xD;&#xA;                )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        GLCall(glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT));&#xD;&#xA;&#xD;&#xA;        return out;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Frequency domain function where red channel represents the real part and green the imaginary (it is not normalized and the values exceed the 0-255 range):&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I omitted the h_tidle_0 and frequency shaders' code since it looks to me that the problem is not there.&#xD;&#xA;&#xD;&#xA;Two relevant links:&#xD;&#xA;&#xD;&#xA;This implementation that uses GLFFT:&#xD;&#xA;https://arm-software.github.io/opengl-es-sdk-for-android/ocean_f_f_t.html&#xD;&#xA;&#xD;&#xA;This paper that obtains spectrum and frequency textures similar to mines:&#xD;&#xA;https://tore.tuhh.de/bitstream/11420/1439/1/GPGPU_FFT_Ocean_Simulation.pdf&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NcFuP.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hrTPp.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/SioLa.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/qIhq7.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33297" PostHistoryTypeId="1" PostId="11032" RevisionGUID="f0f85b5d-77d4-4e3b-b450-be3cde8f4ec4" CreationDate="2021-07-11T21:41:38.483" UserId="16867" Text="Problem when performing IFFT for Tessendorf's ocean waves" ContentLicense="CC BY-SA 4.0" />
  <row Id="33298" PostHistoryTypeId="3" PostId="11032" RevisionGUID="f0f85b5d-77d4-4e3b-b450-be3cde8f4ec4" CreationDate="2021-07-11T21:41:38.483" UserId="16867" Text="|opengl|c++|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33299" PostHistoryTypeId="2" PostId="11033" RevisionGUID="0a74b951-e676-4c4c-be6a-d929af9e6e6d" CreationDate="2021-07-12T00:06:57.197" UserId="16864" Text="For educational purposes I'm trying to simulate what a scene would look like with a perspective matrix deformation (before everything is brought to NDC) but I'm unsure how to do this.&#xD;&#xA;&#xD;&#xA;I'd like to do this only with matrices transformations if that is possible. A cube would then deform depending on where the perspective camera is set up.&#xD;&#xA;&#xD;&#xA;I've set up two cameras, the perspective camera and the observer camera.&#xD;&#xA;&#xD;&#xA;This, in theory, could be achieved by applying the perspective camera perspetive-view matrix on the observer camera's cube, right? I've tried this with no luck. Wouldn't this supposed make all vertices to fit the perspective camera homogenous coordinates?&#xD;&#xA;&#xD;&#xA;The effect I'm trying to achieve is this one ([source][1]): &#xD;&#xA;![Frustum in homogenous coordinates](https://www.opengl-tutorial.org/assets/images/tuto-3-matrix/homogeneous.png) &#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;  &#xD;&#xA;[1]: https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/" ContentLicense="CC BY-SA 4.0" />
  <row Id="33300" PostHistoryTypeId="1" PostId="11033" RevisionGUID="0a74b951-e676-4c4c-be6a-d929af9e6e6d" CreationDate="2021-07-12T00:06:57.197" UserId="16864" Text="Simulate projection matrix deformation in two camera setup" ContentLicense="CC BY-SA 4.0" />
  <row Id="33301" PostHistoryTypeId="3" PostId="11033" RevisionGUID="0a74b951-e676-4c4c-be6a-d929af9e6e6d" CreationDate="2021-07-12T00:06:57.197" UserId="16864" Text="|opengl|transformations|matrix|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33303" PostHistoryTypeId="2" PostId="11034" RevisionGUID="6dd53997-fc62-40ef-81cd-859f95cace19" CreationDate="2021-07-12T13:23:15.813" UserId="8125" Text="As far as I know, OpenGL specifies that you cannot rely on precise rounding of vertex and edge coordinates for rasterization - which means that T-vertices may cause small artifacts: a continuous and a subdivided edge which should coincide perfectly in world space may in fact leave a small gap when rasterized.&#xD;&#xA;&#xD;&#xA;Such an issue could appear regularly on older graphics cards with aggressive floating point optimizations or fixed-point coordinates, which accumulate rounding biases.&#xD;&#xA;&#xD;&#xA;**Is this, however, still an issue with modern graphics drivers?**&#xD;&#xA;&#xD;&#xA;Say that I could generate my meshes most efficiently *with* T-vertices, would it be viable to do so by default and give users an option to use closed (but sub-optimal) meshes if they observe rendering artifacts?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33304" PostHistoryTypeId="1" PostId="11034" RevisionGUID="6dd53997-fc62-40ef-81cd-859f95cace19" CreationDate="2021-07-12T13:23:15.813" UserId="8125" Text="How widespread are T-vertex artifacts nowadays?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33305" PostHistoryTypeId="3" PostId="11034" RevisionGUID="6dd53997-fc62-40ef-81cd-859f95cace19" CreationDate="2021-07-12T13:23:15.813" UserId="8125" Text="|opengl|rasterizer|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33306" PostHistoryTypeId="5" PostId="11033" RevisionGUID="e067e12f-158f-4098-924b-d4f41e87c616" CreationDate="2021-07-13T01:00:07.693" UserId="16864" Comment="added 816 characters in body" Text="For educational purposes I'm trying to simulate what a scene would look like with a perspective matrix deformation (before everything is brought to NDC) but I'm unsure how to do this.&#xD;&#xA;&#xD;&#xA;I'd like to do this only with matrices transformations if that is possible. A cube would then deform depending on where the perspective camera is set up.&#xD;&#xA;&#xD;&#xA;I've set up two cameras, the perspective camera and the observer camera.&#xD;&#xA;&#xD;&#xA;This, in theory, could be achieved by applying the perspective camera perspetive-view matrix on the observer camera's cube, right? I've tried this with no luck. Wouldn't this supposed make all vertices to fit the perspective camera homogenous coordinates?&#xD;&#xA;&#xD;&#xA;The effect I'm trying to achieve is this one ([source][1]): &#xD;&#xA;![Frustum in homogenous coordinates](https://www.opengl-tutorial.org/assets/images/tuto-3-matrix/homogeneous.png) &#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // model translate&#xD;&#xA;    model = perspective_camera-&gt;projection * perspective_camera-&gt;view * model;&#xD;&#xA;    shaders[&quot;scene&quot;].setBool(&quot;second_camera&quot;, true);&#xD;&#xA;    // draw model&#xD;&#xA;&#xD;&#xA;and the shader:&#xD;&#xA;&#xD;&#xA;     if(second_camera) {&#xD;&#xA;      vec4 model_div_w = model * model_coefficients;&#xD;&#xA;      model_div_w = model_div_w/model_div_w.w;&#xD;&#xA;      gl_Position = projection * view * model_div_w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This is what I got from this code: &#xD;&#xA;[![Two camera setup][2]][2]&#xD;&#xA;&#xD;&#xA;Panning the perspective camera **slightly to the left** gets me this, shouldn't the blocks pan to the **other side**? They are actually accompanying the camera. (Moving the camera further has the same effect but more even pronounced)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/&#xD;&#xA;  [2]: https://i.stack.imgur.com/Md3aS.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ojg1M.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/kWjEP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33308" PostHistoryTypeId="2" PostId="11035" RevisionGUID="a8f62915-23ca-4c41-b491-629b4235877b" CreationDate="2021-07-13T12:33:00.073" UserId="16730" Text="In a real-time rendering program, when a light hit a plane and reflected, how to calculate the attenuation(by distance) for the reflected light? " ContentLicense="CC BY-SA 4.0" />
  <row Id="33309" PostHistoryTypeId="1" PostId="11035" RevisionGUID="a8f62915-23ca-4c41-b491-629b4235877b" CreationDate="2021-07-13T12:33:00.073" UserId="16730" Text="What is the attenuation function for a reflected light" ContentLicense="CC BY-SA 4.0" />
  <row Id="33310" PostHistoryTypeId="3" PostId="11035" RevisionGUID="a8f62915-23ca-4c41-b491-629b4235877b" CreationDate="2021-07-13T12:33:00.073" UserId="16730" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33311" PostHistoryTypeId="2" PostId="11036" RevisionGUID="c502c7e0-194d-4138-9429-fa49f24228fa" CreationDate="2021-07-13T14:11:53.750" UserId="15574" Text="In deferred rendering, I first write world position to G-Buffer, and then in shading part, I want to use that information to reproject in the previous frame and then write the final color.&#xD;&#xA;&#xD;&#xA;However, the world position buffer wont have any values for fragments that are not touching geometry. How can I recognize these fragments without valid world position info in deferred lighting shader? E.g. I should be displaying environment instead of black parts in world pos buffer." ContentLicense="CC BY-SA 4.0" />
  <row Id="33312" PostHistoryTypeId="1" PostId="11036" RevisionGUID="c502c7e0-194d-4138-9429-fa49f24228fa" CreationDate="2021-07-13T14:11:53.750" UserId="15574" Text="Is fragment shader run on fragments that are outside of rasterized geometry?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33313" PostHistoryTypeId="3" PostId="11036" RevisionGUID="c502c7e0-194d-4138-9429-fa49f24228fa" CreationDate="2021-07-13T14:11:53.750" UserId="15574" Text="|shader|fragment-shader|buffers|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33314" PostHistoryTypeId="2" PostId="11037" RevisionGUID="ac25a82b-b1a2-405f-9edd-c8d132d4e00e" CreationDate="2021-07-13T16:13:49.753" UserId="2654" Text="Broadly speaking, the way to deal with this is to check the depth value for that position on the screen. If the value is the value you cleared the depth buffer to, then you didn't write anything to that fragment." ContentLicense="CC BY-SA 4.0" />
  <row Id="33315" PostHistoryTypeId="2" PostId="11038" RevisionGUID="f261736b-e327-4c6b-b440-aedddca1cfc4" CreationDate="2021-07-13T19:01:44.733" UserId="16879" Text="What is the state of the art in global illumination algorithms in real time applications? &#xD;&#xA;&#xD;&#xA;Which algorithms or categories of algorithms are actually used in the wild and what are their characteristics (fully dynamic vs baked, special use vs. all-around GI solution, performance characteristics, other advantages/disadvantages)?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33316" PostHistoryTypeId="1" PostId="11038" RevisionGUID="f261736b-e327-4c6b-b440-aedddca1cfc4" CreationDate="2021-07-13T19:01:44.733" UserId="16879" Text="State of the art in real-time global illumination algorithms" ContentLicense="CC BY-SA 4.0" />
  <row Id="33317" PostHistoryTypeId="3" PostId="11038" RevisionGUID="f261736b-e327-4c6b-b440-aedddca1cfc4" CreationDate="2021-07-13T19:01:44.733" UserId="16879" Text="|rendering|physically-based|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33318" PostHistoryTypeId="50" PostId="9048" RevisionGUID="bbcc91cb-a6d5-4292-8d7f-ceb95a458127" CreationDate="2021-07-13T19:03:30.237" UserId="-1" />
  <row Id="33319" PostHistoryTypeId="2" PostId="11039" RevisionGUID="ef83d32d-aa32-4485-a292-6bb89ab9ac3f" CreationDate="2021-07-13T19:35:03.297" UserId="38" Text="This is conceptually a bit perplexing because irs a bit counter intuitive. You do not account for it. Why not?&#xD;&#xA;&#xD;&#xA;Lets assume the plane covers atleast one pixel at the furthest distance. It is true that the light attenuates like a point light. But see there is another point light right next to it, and another point. This cancels the effect. So yes individual point of reflection contributes less but you see more points \*&#xD;&#xA;&#xD;&#xA; Smaller than pixels its the job of the aa and filtering.So the only thing you really need to account for is participating media. In other words most often just atmospheric haze which is mostly just distance to target.&#xD;&#xA;&#xD;&#xA;Another way to look at it is that a ray does not atenuate. Its the samplig of the rays that handles the attenuation.&#xD;&#xA;&#xD;&#xA;\* in a way this is lucky for us. If it werent then we would fail to see a lot of things." ContentLicense="CC BY-SA 4.0" />
  <row Id="33320" PostHistoryTypeId="5" PostId="11039" RevisionGUID="63e321db-22eb-46c0-8315-19cb821bfae2" CreationDate="2021-07-13T23:49:13.363" UserId="38" Comment="added 2 characters in body" Text="This is conceptually a bit perplexing because it is a bit counter intuitive. You do not account for it. Why not?&#xD;&#xA;&#xD;&#xA;Lets assume the plane covers atleast one pixel at the furthest distance. It is true that the light attenuates like a point light. But see there is another point light right next to it, and another point. This cancels the effect. So yes individual point of reflection contributes less but you see more points \*&#xD;&#xA;&#xD;&#xA; Smaller than pixels its the job of the aa and filtering.So the only thing you really need to account for is participating media. In other words most often just atmospheric haze which is mostly just distance to target.&#xD;&#xA;&#xD;&#xA;Another way to look at it is that a ray does not atenuate. Its the samplig of the rays that handles the attenuation.&#xD;&#xA;&#xD;&#xA;\* in a way this is lucky for us. If it werent then we would fail to see a lot of things." ContentLicense="CC BY-SA 4.0" />
  <row Id="33326" PostHistoryTypeId="2" PostId="11041" RevisionGUID="506e0cde-8d2c-4451-a7b5-8adf3ea90987" CreationDate="2021-07-14T07:49:13.610" UserId="13456" Text="This question is too general to be answered in a Q&amp;A site like SE. It would be better to consult to a recent thesis, or a text book. Here are couple of suggestions that come to my mind:&#xD;&#xA;&#xD;&#xA;Chapter 11 of&#xD;&#xA;Möller, T. (2018) Real-time rendering. Fourth edition. Boca Raton: Taylor &amp; Francis, CRC Press. &#xD;&#xA;&#xD;&#xA;Engel, W. F. (ed.) (2018) GPU pro 360 guide to lighting. First edition. Boca Raton, FL: CRC Press/Taylor &amp; Francis Group.&#xD;&#xA;&#xD;&#xA;Part 7 of&#xD;&#xA;Haines, E. and Akenine-Möller, T. (2019) Ray Tracing Gems: High-Quality and Real-Time Rendering with DXR and Other APIs. Available at: https://doi.org/10.1007/978-1-4842-4427-2 (Accessed: 22 July 2020).&#xD;&#xA;&#xD;&#xA;The fourth version of [pbrt](https://www.pbrt.org/).&#xD;&#xA;&#xD;&#xA;The list goes on and on...&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33327" PostHistoryTypeId="10" PostId="11038" RevisionGUID="303d3270-0fda-420e-b282-ce88461c0350" CreationDate="2021-07-14T09:34:26.380" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="33328" PostHistoryTypeId="2" PostId="11042" RevisionGUID="5d34fde8-abd1-4d11-8368-60ecfb5b361c" CreationDate="2021-07-14T13:27:21.353" UserId="16883" Text="What's the difference between the terms Gray-Level &amp; Gray-Scale ?  &#xD;&#xA;I think that Gray-Level refers to the matrix of light-intensities of the Black-White digital image itself whilst Gray-Scale refers to a Black-White Image only ( without reference to the matrix )" ContentLicense="CC BY-SA 4.0" />
  <row Id="33329" PostHistoryTypeId="1" PostId="11042" RevisionGUID="5d34fde8-abd1-4d11-8368-60ecfb5b361c" CreationDate="2021-07-14T13:27:21.353" UserId="16883" Text="Difference between Gray-Level and Gray-Scale?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33330" PostHistoryTypeId="3" PostId="11042" RevisionGUID="5d34fde8-abd1-4d11-8368-60ecfb5b361c" CreationDate="2021-07-14T13:27:21.353" UserId="16883" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33331" PostHistoryTypeId="2" PostId="11043" RevisionGUID="d4dafab2-0f91-46f2-94b6-6597f3881b4b" CreationDate="2021-07-14T15:01:14.383" UserId="8009" Text="_Grayscale_ images measure only the intensity of light, like for images that appear black-and white with monochromatic shades of gray.&#xD;&#xA;&#xD;&#xA;_Gray level_ refers to the actual level.  e.g.: A pixel might be given a coded gray level of 128 where values range from 0 to 255.&#xD;&#xA;&#xD;&#xA;There are terminology analogs to a temperature scale like _Celsius_.  _Grayscale_ could be like the word _Celsius_ itself that tells you what you are measuring (temperature), but a _gray level_ would be analogous to an actual temperature, e.g.: 37°C." ContentLicense="CC BY-SA 4.0" />
  <row Id="33337" PostHistoryTypeId="2" PostId="11045" RevisionGUID="63991df2-a86d-4625-843c-0ca5ced8d6b3" CreationDate="2021-07-15T08:03:14.170" UserId="16888" Text="I started out writing my Color class as just containing R, G, B triplets. Adding colors in this situation turns out to be fairly simple.&#xD;&#xA;&#xD;&#xA;    R = (1, 0, 0)&#xD;&#xA;    G = (0, 1, 0)&#xD;&#xA;    R + G = (1, 1, 0)&#xD;&#xA;&#xD;&#xA;Now I'm looking at adding alpha, making it R, G, B, A.&#xD;&#xA;&#xD;&#xA;The case where alpha = 1 for both has to match the previous behaviour since it was implicitly 1 before implementing alpha:&#xD;&#xA;&#xD;&#xA;    R = (1, 0, 0, 1)&#xD;&#xA;    G = (0, 1, 0, 1)&#xD;&#xA;    R + G = (1, 1, 0, 1)&#xD;&#xA;&#xD;&#xA;The case where either value has alpha = 0 also seems fairly straightforward - the color with alpha = 0 contributes nothing to the sum:&#xD;&#xA;&#xD;&#xA;    R = (1, 0, 0, 1)&#xD;&#xA;    H = (0, 1, 0, 0)&#xD;&#xA;    R + H = (1, 0, 0, 1)&#xD;&#xA;&#xD;&#xA;In the case where one color has alpha = 1, it _seems_ like I can just use the alpha of the other value to scale how much it contributes, and the result still has alpha = 1.&#xD;&#xA;&#xD;&#xA;    R = (1, 0, 0, 1)&#xD;&#xA;    g = (0, 1, 0, 0.5)&#xD;&#xA;    R + g = (1, 0.5, 0, 1)&#xD;&#xA;&#xD;&#xA;Now what I can't seem to figure out is, what to do when both values have fractional alpha. e.g.,&#xD;&#xA;&#xD;&#xA;    R = (1, 0, 0, 0.4)&#xD;&#xA;    G = (0, 1, 0, 0.6)&#xD;&#xA;    R + G + ?&#xD;&#xA;&#xD;&#xA;First I thought, let's assume we're drawing on a black background K = (0, 0, 0, 1). Assuming that addition is associative, &#xD;&#xA;&#xD;&#xA;    R + G + K = R + (G + K)&#xD;&#xA;              = (1, 0, 0, 0.4) + ((0, 1, 0, 0.6) + (0, 0, 0, 1))&#xD;&#xA;              = (1, 0, 0, 0.4) + (0, 0.6, 0, 1)&#xD;&#xA;              = (0.4, 0.6, 0, 1)&#xD;&#xA;&#xD;&#xA;So R + G is some value that when added to K gives (0.4, 0.6, 0, 1), but there are many possible solutions to that. For example, (0.4, 0.6, 0, 1) would be one valid solution, but it intuitively seems wrong because we started with two transparent color values and ended up with an opaque one. Qualitatively, I don't know what the result should be like. If I have two values with alpha 0.5, do they sum to a new value with alpha 0.5, or 0.75?&#xD;&#xA;&#xD;&#xA;Searching around for this, I find a lot of documents on alpha _blending_, but descriptions of additive blending I've found haven't mentioned what to do with the alpha value.&#xD;&#xA;&#xD;&#xA;I feel like I'll probably hit a similar problem with multiplication down the track.&#xD;&#xA;&#xD;&#xA;What's the expected behaviour here?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33338" PostHistoryTypeId="1" PostId="11045" RevisionGUID="63991df2-a86d-4625-843c-0ca5ced8d6b3" CreationDate="2021-07-15T08:03:14.170" UserId="16888" Text="How do I add two color values containing alpha?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33339" PostHistoryTypeId="3" PostId="11045" RevisionGUID="63991df2-a86d-4625-843c-0ca5ced8d6b3" CreationDate="2021-07-15T08:03:14.170" UserId="16888" Text="|color|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33342" PostHistoryTypeId="2" PostId="11046" RevisionGUID="9caaf1c0-d1df-4aaf-bf11-01926bfea40f" CreationDate="2021-07-15T10:44:56.217" UserId="7647" Text="First, you have to consider what having an alpha value less than one means. You can consider an RGBA colour like $(1,0,0,0.5)$ as &quot;a red object that is 50% transparent&quot;; but an equivalent way, which I think is more useful for reasoning about, is to think of it as &quot;an opaque red object that covers half of the pixel&quot;. Then a pixel with an alpha of 1, say $(0,1,0,1)$, is &quot;a green object that covers the entire pixel&quot;.&#xD;&#xA;&#xD;&#xA;This suggests one thing immediately: that the colour that results from overlaying two pixels is going to depend on the order they appear. If the fully opaque object (with alpha 1) is on top, you won't be able to see the bottom object at all; $(0,1,0,1)$ over $(1,0,0,0.5)$ is just $(0,1,0,1)$. If, on the other hand, the object that covers only half the pixel is on top, then it takes up half the result, and the bottom object takes up the rest; $(1,0,0,0.5)$ over $(0,1,0,1)$ is $(0.5,0.5,0,1)$. If you have two partially-visible objects overlaying each other, then the resulting alpha will be higher than either of their alphas, because the result covers up more of the pixel; $(1,0,0,0.5)$ over $(0,0,1,0.5)$ is $(0.5,0,0.25,0.75)$.&#xD;&#xA;(You can see the exact formulas on the Wikipedia page for [&quot;Alpha compositing&quot;](https://en.wikipedia.org/wiki/Alpha_compositing).)&#xD;&#xA;&#xD;&#xA;This is not at all what you had done in your simple &quot;adding colours&quot; example. What does &quot;adding colours&quot; mean? If you're writing something like a raytracer, then you can represent the colour of a ray of light by an RGB colour, and combine the influence of differently-coloured rays by adding those colours. In this case, adding, say, red to red and getting a colour of $(2,0,0)$ can make sense; it's a red light with a brightness twice that of your &quot;standard&quot; red $(1,0,0)$.&#xD;&#xA;&#xD;&#xA;An RGBA colour, on the other hand, doesn't represent a light ray any more; it's explicitly a colour with a transparency, and &quot;adding colours&quot; doesn't really make sense any more; you can _blend_ them, or maybe _average_ them, but adding red to red to get $(2,0,0)$ doesn't make any sense if you're talking about the RGB values of pixels on a screen." ContentLicense="CC BY-SA 4.0" />
  <row Id="33343" PostHistoryTypeId="2" PostId="11047" RevisionGUID="d28713f6-3fa2-496a-a400-0774a89613ab" CreationDate="2021-07-15T13:13:22.373" UserId="38" Text="Well, its not as defined as you would like it to be. There is no definitive answers to this. It really depends on what you model with alpha and RGB values.&#xD;&#xA;&#xD;&#xA;Generally we can model one of 2 things with alpha. We can model transparency or we can model coverage. Because coverage is a bit pesky to deal with most often we just model the aggreagate of coverage and transparency as transparency.&#xD;&#xA;&#xD;&#xA;So from getgo it is to be understood that there is no definitive answer for the question. The simplest interpretation is that the color and alpha produce somesort of ideal filter where 1- alpha of the underlying material shines through. But what the exact interpretation should be depends on your exact definitions, and sorry we can not help you there.&#xD;&#xA;&#xD;&#xA;Second adding things seem to imply that you are dealing with natural numbers or floating point numbers that are linear. So in general when you deal with color calculations you should not assume 0.5+0.5 equals to 1. Simply because RGB color as a general rule is not a linear quantity. &#xD;&#xA;&#xD;&#xA;But all of this really depends on what your doing. If your just doing a graphics program just do what you naively feel. Why not after all photoshop does too (although it has a option to do it as if it was linearized first). But if you build a raytracer this becomes quite critical to deal with so that the physics get consisten.&#xD;&#xA;&#xD;&#xA;But yes this means entire industries are inconsistent. Something as simple as rendering in SVG does not bother to define how to do many operations should be done. Dont expect two different svg renderers to get same results anytime soon.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33344" PostHistoryTypeId="5" PostId="11047" RevisionGUID="4b9202dd-7813-4c3e-8ee7-19f24ca01682" CreationDate="2021-07-15T13:19:11.820" UserId="38" Comment="added 188 characters in body" Text="Well, its not as defined as you would like it to be. There is no definitive answers to this. It really depends on what you model with alpha and RGB values.&#xD;&#xA;&#xD;&#xA;Generally we can model one of 2 things with alpha. We can model transparency or we can model coverage. Because coverage is a bit pesky to deal with most often we just model the aggreagate of coverage and transparency as transparency.&#xD;&#xA;&#xD;&#xA;So from getgo it is to be understood that there is no definitive answer for the question. The simplest interpretation is that the color and alpha produce somesort of ideal filter where 1- alpha of the underlying material shines through. But what the exact interpretation should be depends on your exact definitions, and sorry we can not help you there.&#xD;&#xA;&#xD;&#xA;Second adding things seem to imply that you are dealing with natural numbers or floating point numbers that are linear. So in general when you deal with color calculations you should not assume 0.5+0.5 equals to 1. Simply because RGB color as a general rule is not a linear quantity. &#xD;&#xA;&#xD;&#xA;But all of this really depends on what your doing. If your just doing a graphics program just do what you naively feel. Why not after all photoshop does too (although it has a option to do it as if it was linearized first). But if you build a raytracer this becomes quite critical to deal with so that the physics get consisten.&#xD;&#xA;&#xD;&#xA;But yes this means entire industries are inconsistent. Something as simple as rendering in SVG does not bother to define how to do many operations should be done. Dont expect two different svg renderers to get same results anytime soon.&#xD;&#xA;&#xD;&#xA;If you feel all of this is deeply troublesome, then all i can say is: I feel your pain. But the world is not allways very scientifically rigoriously correct as we would like it to be. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33345" PostHistoryTypeId="52" PostId="11045" RevisionGUID="b1834da7-d676-41ce-9c77-b9614d83f269" CreationDate="2021-07-15T16:06:19.407" />
  <row Id="33346" PostHistoryTypeId="2" PostId="11048" RevisionGUID="fbc28643-9e5b-419c-8a83-c2f65b8d1eee" CreationDate="2021-07-16T01:27:20.170" UserId="16890" Text="I am trying to use the techniques discussed in [this][1] paper to implement a BTF into PBRT. I am stuck on how to actually interpolate the weights of the four closest sampling directions.&#xD;&#xA;&#xD;&#xA;At the BTF, I have converted $w_o$ and $w_i$ from cartesian to spherical coordinates in order to do a lookup in the table of BTFs. The samples are taken with the following properties:&#xD;&#xA;&#xD;&#xA;$\theta$ light (and view angles) range from 0 to 75 in 15 degree increments. $\Delta\phi$ at each $\theta$ goes from 0 to (360 - $\Delta\phi$) at -, 60, 30, 20, 18 and 5 degree increments respectively. In a table:&#xD;&#xA;&#xD;&#xA;| $\theta$ | $\Delta\phi$ (0 - (360 - $\Delta\phi$))|&#xD;&#xA;|:---------|:--------------------------------------:|&#xD;&#xA;|0|-|&#xD;&#xA;|15|60|&#xD;&#xA;|30|30|&#xD;&#xA;|45|20|&#xD;&#xA;|60|18|&#xD;&#xA;|75|5|&#xD;&#xA;&#xD;&#xA;How can I determine the four closest sampling directions given $w_o$ and $w_i$? Retrieving the values/weights seems trivial, but I don't really have a clue on how to determine the four nearest directions and just don't know where to start.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://diglib.eg.org/bitstream/handle/10.2312/EGWR.EGWR03.167-177/167-177.pdf?sequence=1&amp;isAllowed=y" ContentLicense="CC BY-SA 4.0" />
  <row Id="33347" PostHistoryTypeId="1" PostId="11048" RevisionGUID="fbc28643-9e5b-419c-8a83-c2f65b8d1eee" CreationDate="2021-07-16T01:27:20.170" UserId="16890" Text="BTF Find Four Closest Sampling Directions" ContentLicense="CC BY-SA 4.0" />
  <row Id="33348" PostHistoryTypeId="3" PostId="11048" RevisionGUID="fbc28643-9e5b-419c-8a83-c2f65b8d1eee" CreationDate="2021-07-16T01:27:20.170" UserId="16890" Text="|brdf|sampling|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33349" PostHistoryTypeId="2" PostId="11049" RevisionGUID="daf00ff9-39b3-4e68-ad67-7cd160e7d8ee" CreationDate="2021-07-16T09:44:37.497" UserId="16892" Text="When deriving the Jacobian of the reflection transformation in [Walter et. al's 2007 paper][1]:&#xD;&#xA;&#xD;&#xA;First we have a macrosurface BSDF which is:&#xD;&#xA;&#xD;&#xA;$f_{s}(\mathbf{i}, \mathbf{o}, \mathbf{n})=\int\left|\frac{\mathbf{i} \cdot \mathbf{m}}{\mathbf{i} \cdot \mathbf{n}}\right| f_{s}^{m}(\mathbf{i}, \mathbf{o}, \mathbf{m})\left|\frac{\mathbf{o} \cdot \mathbf{m}}{\mathbf{o} \cdot \mathbf{n}}\right| G(\mathbf{i}, \mathbf{o}, \mathbf{m}) D(\mathbf{m}) d \omega_{m}$&#xD;&#xA;&#xD;&#xA;Then we need an equation for $f_s^m$, the microsurface BSDF. And the paper gives:&#xD;&#xA;&#xD;&#xA;$f_{s}^{m}(\mathbf{i}, \mathbf{o}, \mathbf{m})=\rho \frac{\delta_{\omega_{o}}(\mathbf{s}, \mathbf{o})}{|\mathbf{o} \cdot \mathbf{m}|}$&#xD;&#xA;&#xD;&#xA;Then they rewrite it to fit in the macrosurface BSDF by changing the associated measure of the Dirac delta function:&#xD;&#xA;&#xD;&#xA;$f_{s}^{m}(\mathbf{i}, \mathbf{o}, \mathbf{m})=\rho(\mathbf{i}, \mathbf{m}) \frac{\delta_{\omega_{m}}(\mathbf{h}(\mathbf{i}, \mathbf{o}), \mathbf{m})}{|\mathbf{o} \cdot \mathbf{m}|}\left\|\frac{\partial \omega_{\mathbf{h}}}{\partial \omega_{\mathbf{0}}}\right\|$.&#xD;&#xA;&#xD;&#xA;And my question is, why should the jacobian be a $\left\|\frac{\partial \omega_{\mathbf{h}}}{\partial \omega_{\mathbf{o}}}\right\|$ instead of a $\left\|\frac{\partial \omega_{\mathbf{m}}}{\partial \omega_{\mathbf{o}}}\right\|$? I noticed that the associated mesure changed from $\omega_{\mathbf{o}}$ to $\omega_{\mathbf{m}}$, instead of $\omega_{\mathbf{h}}$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="33350" PostHistoryTypeId="1" PostId="11049" RevisionGUID="daf00ff9-39b3-4e68-ad67-7cd160e7d8ee" CreationDate="2021-07-16T09:44:37.497" UserId="16892" Text="Confusion of deriving the Jacobian of the reflection transformation in Walter et. al's 2007 paper" ContentLicense="CC BY-SA 4.0" />
  <row Id="33351" PostHistoryTypeId="3" PostId="11049" RevisionGUID="daf00ff9-39b3-4e68-ad67-7cd160e7d8ee" CreationDate="2021-07-16T09:44:37.497" UserId="16892" Text="|brdf|pbr|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33352" PostHistoryTypeId="2" PostId="11050" RevisionGUID="8009f08d-a1c3-4ad5-920b-7479999e513d" CreationDate="2021-07-16T15:47:40.217" UserId="16867" Text="I found the problem. Maybe this answer helps someone since there isn't much discussion on the topic.&#xD;&#xA;&#xD;&#xA;I was doing the following change of coordinates in the frequency domain to fit the values on the 256x256 matrix:&#xD;&#xA;&#xD;&#xA;(n, m) = (x-N/2, y-N/2)&#xD;&#xA;&#xD;&#xA;where N, n and m appear in the ocean waves' paper and x, y are the coordinates of the matrix.&#xD;&#xA;&#xD;&#xA;Then I modified the change of coordinates as is done in this [implementation](https://arm-software.github.io/opengl-es-sdk-for-android/ocean_f_f_t.html):&#xD;&#xA;&#xD;&#xA;(n, m) = (alias(x), alias(y))&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;    int alias(int a){&#xD;&#xA;        if(a &gt; N/2) a -= N;&#xD;&#xA;        return N;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Then immediately got the correct result (different seed):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zy8xJ.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33354" PostHistoryTypeId="2" PostId="11051" RevisionGUID="7929a9bb-578b-42a0-acfe-93ef5eb0cbee" CreationDate="2021-07-17T13:23:31.313" UserId="7952" Text="A simple table could be a good choice. There are a few approach's the suggestion I'll put here is just my take on the description, but it can be tweaked to your needs. In psuedocode:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const float table[6] = {0,60,30,20,18,5};&#xD;&#xA;int table_index = asInt(floor(theta/15.0));&#xD;&#xA;float result = table[table_index] * (theta &gt; range);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The above is implemented as the step function in increments of 15. The last bit of the result is a range check that can be used to zap out of range values. ```(theta&gt;range)``` evaluates to zero or one.&#xD;&#xA;&#xD;&#xA;If this is a total miss on what you need let me know and I'll tweak it to help get closer." ContentLicense="CC BY-SA 4.0" />
  <row Id="33355" PostHistoryTypeId="2" PostId="11052" RevisionGUID="5c468d73-afa6-4406-be4b-2da959ea7d2d" CreationDate="2021-07-17T16:40:26.960" UserId="48" Text="There is a functional relationship between $\mathbf{h}$ and $\mathbf{o}$ (and also $\mathbf{i}$) whose Jacobian is being taken. But there's no prior functional relationship between $\mathbf{m}$ and $\mathbf{o}$; they are unrelated variables, until $\mathbf{m}$ is constrained to equal $\mathbf{h}$ by the delta function $\delta(\mathbf{h}, \mathbf{m})$.&#xD;&#xA;&#xD;&#xA;So, really you could write the Jacobian either way, but in my mind it makes a little more sense to write it as $\| \partial \omega_\mathbf{h} / \partial \omega_\mathbf{o} \|$ as that's the underlying functional relationship." ContentLicense="CC BY-SA 4.0" />
  <row Id="33356" PostHistoryTypeId="5" PostId="11017" RevisionGUID="fbc9ffec-0eca-43eb-b03d-30f2b51a0073" CreationDate="2021-07-17T16:58:38.357" UserId="48" Comment="add diagram and link" Text="If we have a vector in the upper hemisphere in tangent space, $(x, y, z)$ with $z &gt; 0$, then the slopes of the vector are $(\tilde x, \tilde y) = (-x/z, -y/z)$. These values are the slopes (derivatives), along $x$ and $y$, of a surface that is normal to the given vector. See also equation (4) in the paper, which is the conversion back and forth between slopes and vectors. &#xD;&#xA;&#xD;&#xA;The 2D space of slope values is called &quot;slope space&quot;. It is an unbounded space, so any $(\tilde x, \tilde y)$ point represents  a valid vector in tangent space (such as a microfacet normal). Geometrically, you can picture it like the intersection of the vector with the $z = 1$ plane. It produces an invertible, one-to-one mapping (bijection) between the upper hemisphere and the plane.&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/ogKi5.png&quot; width=&quot;400&quot; alt=&quot;diagram of normal vector intersecting z=1 plane&quot; /&gt;&#xD;&#xA;&#xD;&#xA;Slope space is often used in microfacet BRDF theory because of its desirable properties. Since it is unbounded, it can be more convenient to define functions and do mathematics in slope space than in spherical coordinates, or directly on the normals. Geometric transformations on the microfacet surface, such as scaling and shearing, have straightforward expressions in slope space. The most common NDFs, Beckmann and GGX, also have a simpler expressions in slope space: Beckmann is a Gaussian distribution in slope space, while [GGX is a Student's t-distribution in slope space](https://mribar03.bitbucket.io/projects/eg_2017/distribution.pdf).&#xD;&#xA;&#xD;&#xA;Edit: I wrote a [more in-depth blog post on this topic](https://www.reedbeta.com/blog/slope-space-in-brdf-theory/) in case more explanation is needed." ContentLicense="CC BY-SA 4.0" />
  <row Id="33357" PostHistoryTypeId="2" PostId="11053" RevisionGUID="b68ce5cc-3546-41e2-9e75-3fdeeb829152" CreationDate="2021-07-17T20:30:17.367" UserId="15772" Text="I have  a question about how colors are stored in computer graphics. I had watched this video previously which had explained about why colors are stored and displayed differently than one would assume in computer graphics : https://www.youtube.com/watch?v=LKnqECcg6Gw&#xD;&#xA;&#xD;&#xA;They explain that, as a consequence of camera capturing color values, but storing the color values as roots instead, 1) more space is saved 2) more black colors are crammed in with 8 bits than white colors, and I heard this topic was important for computer graphics as I heard quite a few apps dont take the square rooting into consideration when performing blurring operations&#xD;&#xA;&#xD;&#xA;Here is where I am extremely confused. I have little intuition for why it works this way. Just because we store square roots, why is more space saved?&#xD;&#xA;&#xD;&#xA;And mainly, how do we store more blacks just because we store square roots? I decided to calculate the root of values from 0 to 255 in Python and I found out the the difference between the root of x and the root of x+1 becomes smaller and smaller the larger x is&#xD;&#xA;&#xD;&#xA;Should this not logically mean that since we try to be more precise storing the higher or whiter values since the difference between square roots of white values is smaller and smaller, thus we would have MORE white values than more black values?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33358" PostHistoryTypeId="1" PostId="11053" RevisionGUID="b68ce5cc-3546-41e2-9e75-3fdeeb829152" CreationDate="2021-07-17T20:30:17.367" UserId="15772" Text="Why do computers more efficiently store black colors than white colors in computer graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33359" PostHistoryTypeId="3" PostId="11053" RevisionGUID="b68ce5cc-3546-41e2-9e75-3fdeeb829152" CreationDate="2021-07-17T20:30:17.367" UserId="15772" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33360" PostHistoryTypeId="2" PostId="11054" RevisionGUID="ad5fe7cf-435f-4728-9bcb-67274c9ceb2e" CreationDate="2021-07-17T22:11:59.047" UserId="4908" Text="In Computer Graphics, we most often represent colours using a red, green, and blue value, also known as RGB. And, in Computer Graphics, we generally represent those red, green, and blue values with numbers ranging from 0 to 1. A value of 0.0 means 0% brightness or pure black. A value of 1.0 means 100% brightness or pure white.&#xD;&#xA;&#xD;&#xA;Now, you might think that middle gray, what we see as precisely in the middle between black and white, would be a value of 0.5 or 50% brightness. However, this is actually not how our eyes perceive the world. Our eyes perceive the world in a non-linear fashion. So, middle gray is actually 18% brightness or a value of 0.18 (and some might even say it's 12% brightness). An object that is middle gray, reflects 18% of the incoming light.&#xD;&#xA;&#xD;&#xA;This isn't problematic, but storing decimal numbers ranging from 0 to 1 does take up quite a bit of space. So, we can store it as a whole number using a few bits. Using 8 bit numbers ranging from 0 to 255 is very populair, mainly because it works nice with computers and in the vast majority of the cases we cannot see that the image only had 256 possible values for red, green, and blue. And that's where we get into trouble.&#xD;&#xA;&#xD;&#xA;Our eyes roughly perceive the same amount of tonalities between pure black and middle gray and between middle gray and pure white. However, 18% middle gray converted to an 8 bit number is 46. Which means that for all values between pure black and middle gray, we have 46 possible values and from middle gray to pure white we have 210 possible values. That is a huge difference. What's going to happen is that all values above middle gray are going to look perfectly fine, but values below middle gray are going to get banding artifacts. Here's a foto from pexels by Frans van Heerden. On the left is what it should look like and on the right is what it might look like if we just convert it to an 8 bit number directly. [![Image showing quantization artifacts][1]][1] You can see that the brighter parts of the image stay about the same, however the darker parts of the image are heavily distorted and you can see that there are only a few possible values. Clearly, this isn't what we want.&#xD;&#xA;&#xD;&#xA;So, how do we fix this? Well, the answer is to have values between pure black and middle gray to have about the same amount of possible values as values between middle gray and pure white. How do we do that? We use a transfer function (also called OETF or inverse-EOTF). A transfer function simply remaps the input values to output values. In our case, the transfer function will make sure that values above and below middle gray will get the same amount of possible values. Two flavours of transfer functions are very popular, gamma (like sRGB and Rec.709) and log (mostly from cinema cameras) based functions. The square root that you saw in the video is essentially a gamma transfer function. Here are a few graphs showing linear, gamma and log transfer functions.[![Various transfer functions][2]][2] You can see that gamma and log will more evenly distribute the 256 possible values that we have between pure black and middle gray, and middle gray and pure white. One thing you might notice is that transfer functions actually operate on the 0 to 1 numbers, and that is true. You first apply the transfer function and then you convert them from 0 to 1, to the 8 bit number ranging from 0 to 255.&#xD;&#xA;&#xD;&#xA;In a mathematically correct program, we want to use numbers ranging from 0 to 1 whenever we are doing things with the RGB values (like changing exposure, white balance, curves, saturation, and so on), since the formulas that we use assume that. Whenever we want to store the image to a file (like a PNG or JPEG file) or when we want to send it to your monitor, we will apply the transfer function and then convert it to an 8 bit number ranging from 0 to 255, in order to save space. &#xD;&#xA;&#xD;&#xA;When it comes to which transfer function to use, we look at colour spaces. Colour spaces define how to interpret the RGB values. An RGB value of 255 red, 0 green, and 0 blue is obviously red, but what kind of red? There are a lot of reds that all look red, but they are different. The same is for green, blue, and even white. Additionally, is a value of 128 for red, green, and blue middle gray or maybe some other brightness? Colour spaces define all of this. They say what kind of red red is, what kind of green green is, what kind of blue blue is, what kind of white white is and what the transfer function used is. So, all we need to make sure is that we use the transfer function from the same colour space as our monitor or image file and the resulting image will look correct.&#xD;&#xA;&#xD;&#xA;So, why does Photoshop give the wrong results according to that video and why does it say that computer colour is broken? Well, computer colour isn't broken. However, all of the formulas that we (and Photoshop) use, all want linear values between 0 and 1. But, Photoshop doesn't do that. It uses the 8 bit numbers directly, but those have that transfer function applied. This means that the resulting values aren't mathematically correct.&#xD;&#xA;&#xD;&#xA;But, why does Photoshop do that? Well, most likely, it's because Photoshop was created a long time ago, when computers were slow. So, to take the 8 bit numbers, convert to numbers between 0 and 1, then apply the inverse of the transfer function, then whatever colour operation (like blurring), then apply the transfer function, and lastly convert it back to 8 bit numbers, well that is going to make it unbearably slow. So, they simply didn't do that and performed the colour operations on the 8 bit numbers directly. The results, while incorrect, looked good enough, so they never bothered to fix it. Nowadays, Photoshop is such a large application that to try and fix this now, would be out of the question. Computer colours aren't broken, Photoshop just does it the wrong way.&#xD;&#xA;&#xD;&#xA;To conclude, when actually working with the RGB values themselves, we use values between 0 and 1. However, when storing them to a file or sending them to our displays, we use 8 bit (or sometimes 10 bit) numbers in order to save space. To make sure that the images still look good, we have to make use of transfer functions. Some applications decide to do things the mathematically wrong way, just because it is faster and they think the results are good enough (but not as good as doing it the right way).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sARrb.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/Jwbn2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33361" PostHistoryTypeId="2" PostId="11055" RevisionGUID="eb9935c5-95a2-431c-a945-6ee0bbc04672" CreationDate="2021-07-17T23:51:25.027" UserId="7952" Text="The video is over simplifying a problem that has a long history and is far more complex then just &quot;how a camera captures images&quot;. Especially today when we have cameras that can capture flat out amazing amounts of data.&#xD;&#xA;&#xD;&#xA;If someone shows you a red card, that never changes, then starts changing the brightness of the light illuminating that red card, and you press a button every time you see a difference on the card, you will press the button more often when the lights are dim, then when they are bright. It's simple physiology, so doesn't it seems reasonable to capture, then subsequently reproduce more dark colors then bright colors with our cameras and monitors? &#xD;&#xA;&#xD;&#xA;The bias is intentional, it is built into the system on purpose to make up for the short comings of technology, and take advantage of properties of our eyes. Yeah, modern equipment has over come many of they limitations but the vast majority of installed monitors in the world still have 8 bits of color built into them.&#xD;&#xA;&#xD;&#xA;And that is the reason for the &quot;square roots&quot;, its actually not square roots but lets not go there.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33362" PostHistoryTypeId="2" PostId="11056" RevisionGUID="b32b9085-ebc0-4468-9c0e-280d8f9433f9" CreationDate="2021-07-17T23:53:22.493" UserId="8009" Text="If by ___adding two colour values with alpha___ you mean to ___combine them for the purposes of blending___ then here's the answer you need.  I'll show the full derivation too.&#xD;&#xA;&#xD;&#xA;Feel free to scroll down to the **TL;DR** indicator if you're in a hurry.&#xD;&#xA;&#xD;&#xA;## Luminance-alpha formats&#xD;&#xA;&#xD;&#xA;Let’s simplify this by considering an image using the monochrome luminance-alpha format.  Pixels in this format have two components: a luminance value (L), ranging from 0.0 to 1.0, and an alpha component (α) also ranging from 0.0 to 1.0.&#xD;&#xA;&#xD;&#xA;## Blending&#xD;&#xA;&#xD;&#xA;Pixels with alpha components typically support a ___blend___ operation.  Let’s use the symbol **⊕** to denote the blend operation.  This operator takes as its left-hand side operand, a single-channel luminance-only value that is “opaque” (no alpha).  But the right-hand side operand takes a two-channel luminance-alpha pixel.  And this operator outputs a single-channel luminance-only value.&#xD;&#xA;&#xD;&#xA;Let’s suppose we start with a pixel value B stored in the framebuffer.  You can also think of it as the “background” value onto which we can blend new semi-transparent luminance-alpha pixels.&#xD;&#xA;&#xD;&#xA;Let’s assume as want to blend a semi-transparent luminance-alpha pixel value P over top of that and write the resultant value back into the framebuffer.  We are “painting” onto the background.  You could think of this as modifying B, but we’ll write the new value of B as B’.&#xD;&#xA;&#xD;&#xA;B’ = B ⊕ P&#xD;&#xA;&#xD;&#xA;The definition of ⊕ looks like this:&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt;' = B&lt;sub&gt;L&lt;/sub&gt; (1 - P&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;This says that the output is the luminance value in the buffer (background) times one-minus-alpha, plus the semi-transparent luminance value times alpha.  This should be an alpha blending operation you’re familiar with.&#xD;&#xA;&#xD;&#xA;## Composing two blend operations&#xD;&#xA;&#xD;&#xA;One way to consider how to combine two semi-transparent pixel values, P and Q is to construct a new value R (standing for “result”) such that:&#xD;&#xA;&#xD;&#xA;(B ⊕ P) ⊕ Q = B ⊕ R&#xD;&#xA;&#xD;&#xA;What I’ve written there, is that we perform two distinct, successive, blend operations one after the other.  First, we blend P with the background B to arrive at (B ⊕ P) then we blend Q with that result to arrive at (B ⊕ P) ⊕ Q.  Furthermore, we’d like this two-step operation to be equivalent to a one-step operation of blending a single semitransparent pixel R with the original background B.&#xD;&#xA;&#xD;&#xA;Now we can define R in terms of an “alpha compose” operator of our own design that operates on P and Q, for which we will use the symbol **⊙**, and we will define it to work like this &#xD;&#xA;&#xD;&#xA;R = P ⊙ Q&#xD;&#xA;&#xD;&#xA;We want to define it such that:&#xD;&#xA;&#xD;&#xA;(B ⊕ P) ⊕ Q = B ⊕ (P ⊙ Q)&#xD;&#xA;&#xD;&#xA;If we simply expand the definitions of these operators as before in terms of modifying a background pixel, then we’d like to define B’’ which is the result of having blended Q over B’.  And recall that B’ was the result of having blended P over the background B.&#xD;&#xA;&#xD;&#xA;B'' = (B ⊕ P) ⊕ Q&#xD;&#xA;&#xD;&#xA;B'' = B' ⊕ Q&#xD;&#xA;&#xD;&#xA;### Derive the formula&#xD;&#xA;&#xD;&#xA;Here's the _show your work_ portion.&#xD;&#xA;&#xD;&#xA;We can substitute (B ⊕ P) with what we’ve shown B’ to be equal to.&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt;'' = (B&lt;sub&gt;L&lt;/sub&gt; (1 - P&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;) ⊕ Q&#xD;&#xA;&#xD;&#xA;And now we can keep expanding to show what happens after we blend Q with that intermediate result.  This gets a little cluttered, but it equals this:&#xD;&#xA;&#xD;&#xA;(B&lt;sub&gt;L&lt;/sub&gt; (1 - P&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;)(1 - Q&lt;sub&gt;α&lt;/sub&gt;) + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;We want to rearrange this to be of the form of the original blend operator definition.&#xD;&#xA;&#xD;&#xA;Let’s start by simplifying:&#xD;&#xA;&#xD;&#xA;(B&lt;sub&gt;L&lt;/sub&gt; - B&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;)(1 - Q&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; (1 - Q&lt;sub&gt;α&lt;/sub&gt;) + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt; - B&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - B&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + B&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;And now remember it has to end up looking like this:&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt; (1 - R&lt;sub&gt;α&lt;/sub&gt;) + R&lt;sub&gt;L&lt;/sub&gt; R&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;Let’s rearrange to accomplish that:&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt; (1 - (P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;We now know that:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;α&lt;/sub&gt; = P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;We just need to figure out what R&lt;sub&gt;L&lt;/sub&gt; equals.&#xD;&#xA;&#xD;&#xA;We know from what’s left over in that equation that:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; R&lt;sub&gt;α&lt;/sub&gt; = P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;And therefore, if R&lt;sub&gt;α&lt;/sub&gt; is non-zero, we can divide to isolate R&lt;sub&gt;L&lt;/sub&gt;.&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; = (P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)/R&lt;sub&gt;α&lt;/sub&gt; &#xD;&#xA;&#xD;&#xA;Substituting the value we arrived at for R&lt;sub&gt;α&lt;/sub&gt; we get:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; = (P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)/(P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)&#xD;&#xA;&#xD;&#xA;This is an expression entirely in terms of components of P and Q, which means we're done.  And the final definition you've been waiting for is written below...&#xD;&#xA;&#xD;&#xA;# TL;DR (here's the answer you want)&#xD;&#xA;&#xD;&#xA;Given **R = P ⊙ Q**, we can define the _alpha compose_ operator **⊙** such that:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;α&lt;/sub&gt; = P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; = (P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)/R&lt;sub&gt;α&lt;/sub&gt; &#xD;&#xA;&#xD;&#xA;Note that our formula for R&lt;sub&gt;L&lt;/sub&gt; is only valid in the case when the alpha values of P and Q are not both zero.  That’s because if the alpha is zero, then the luminance channel can be anything.  Therefore, in the case where R&lt;sub&gt;α&lt;/sub&gt; is zero, we can simply define R&lt;sub&gt;L&lt;/sub&gt; also to be zero.&#xD;&#xA;&#xD;&#xA;Now fortunately, for an RGBA format pixel, by symmetry, we can simply substitute the name “red”, “green” or “blue” for the “luminance” channel in the formulae we derived above.  The RGB streams never cross; the values don’t contaminate each other.  You can work with each colour channel independently.  The red component of a composite operation obviously depends on the red components of both P and Q, but it doesn’t depend on the green or blue channels of the either pixel, but it does depend on the alpha value of both pixels.  Simply substitute L above with R G or B for RGBA formats.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Important: order matters!&#xD;&#xA;&#xD;&#xA;I want to take a moment to observe that the expression for R&lt;sub&gt;α&lt;/sub&gt; has some symmetry, in that it doesn’t seem to matter whether P or Q happens first. But the expression for R&lt;sub&gt;L&lt;/sub&gt; lacks this symmetry.  There’s a term -P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; that is unbalanced and has a Luminance contribution from P but not Q.  So, this is a big warning that the composition operator we have defined is **not commutative**.  &#xD;&#xA;&#xD;&#xA;P ⊙ Q ≠ Q ⊙ P&#xD;&#xA;&#xD;&#xA;This means that the order in which we blend pixels matters.  More fundamentally, the same thing can be expressed as:&#xD;&#xA;&#xD;&#xA;(B ⊕ P) ⊕ Q ≠ (B ⊕ Q) ⊕ P&#xD;&#xA;&#xD;&#xA;It matters whether you blend P first and then Q second, vs blending Q first and blending Q second.  In this regard, the composition operation is unlike regular addition or multiplication where a + b = b + a.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33363" PostHistoryTypeId="5" PostId="11055" RevisionGUID="77f585ea-8d25-45fc-ae22-6e784f26a305" CreationDate="2021-07-18T00:07:51.370" UserId="7952" Comment="changed red card to color wheel" Text="The video is over simplifying a problem that has a long history and is far more complex then just &quot;how a camera captures images&quot;. Especially today when we have cameras that can capture flat out amazing amounts of data.&#xD;&#xA;&#xD;&#xA;If someone shows you a [color wheel][1], that never changes, then starts changing the brightness of the light illuminating that color wheel, and you press a button every time you see a difference on the wheel, you will press the button more often when the lights are dim, then when they are bright. It's simple physiology, so doesn't it seems reasonable to capture, then subsequently reproduce more dark colors then bright colors with our cameras and monitors? &#xD;&#xA;&#xD;&#xA;The bias is intentional, it is built into the system on purpose to make up for the short comings of technology, and take advantage of properties of our eyes. Yeah, modern equipment has over come many of they limitations but the vast majority of installed monitors in the world still have 8 bits of color built into them.&#xD;&#xA;&#xD;&#xA;And that is the reason for the &quot;square roots&quot;, its actually not square roots but lets not go there.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_wheel" ContentLicense="CC BY-SA 4.0" />
  <row Id="33364" PostHistoryTypeId="5" PostId="11055" RevisionGUID="abe582e8-0ad0-454e-bb6e-cafc65989cab" CreationDate="2021-07-18T12:01:52.167" UserId="7952" Comment="added 1531 characters in body" Text="The video is over simplifying a problem that has a long history and is far more complex then just &quot;how a camera captures images&quot;. Especially today when we have cameras that can capture flat out amazing amounts of data.&#xD;&#xA;&#xD;&#xA;If someone shows you a [color wheel][1], that never changes, then starts changing the brightness of the light illuminating that color wheel, and you press a button every time you see a difference on the wheel, you will press the button more often when the lights are dim, then when they are bright. It's simple physiology, so doesn't it seems reasonable to capture, then subsequently reproduce more dark colors then bright colors with our cameras and monitors? &#xD;&#xA;&#xD;&#xA;The bias is intentional, it is built into the system on purpose to make up for the short comings of technology, and take advantage of properties of our eyes. Yeah, modern equipment has over come many of they limitations but the vast majority of installed monitors in the world still have 8 bits of color built into them.&#xD;&#xA;&#xD;&#xA;And that is the reason for the &quot;square roots&quot;, its actually not square roots but lets not go there.&#xD;&#xA;&#xD;&#xA;Here is a fairly detailed explanation of how the &quot;compression&quot; works:&#xD;&#xA;&#xD;&#xA;To understand the compression, first lets normalize the range of values to be between 0 and 1. And knowing that the normalized values between 0.0 and 0.25 will have more visual impact then values between 0.75 and 1.0. Then what math function will &quot;stretch&quot; out the space for lower values, and &quot;compress&quot; larger values? Exponents do this quite neatly. For example $0.1^2=0.01$ while $0.2^2 = 0.04$  for a difference of $0.03$ so the values only moved a little bit along the number line. But closer to $1$ at say $0.8^2=0.64$ and then $0.9^2=0.81$ for a difference of $0.17$ so values close to 1 move a lot more then values close to zero. But the input values had the exact same difference of $0.1$. This is the opposite of what we want, so instead use the sqrt for our &quot;compression&quot; and then square the compressed values for &quot;decompression&quot;. Here is an example:&#xD;&#xA;&#xD;&#xA;Divide the range between 0 and 1 into 10 equally sized sections, call them buckets, then each bucket will be 0.1 in size. (computers use 256 buckets for each color) And we can compute a bucket. $sqrt(.1) = 0.316$ and $sqrt(.2)= 0.447$ so the nearest buckets are 1 and 2 respectively. While for $sqrt(.8)=0.894$ and $sqrt(.9)=0.948$ they both have the nearest bucket of 9! And that's it, the dark values are spread out into more buckets then the bright values.&#xD;&#xA;&#xD;&#xA;It really is that simple, the computers aren't actually doing any compression, they are just doing some math on each value. .&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_wheel" ContentLicense="CC BY-SA 4.0" />
  <row Id="33365" PostHistoryTypeId="5" PostId="11055" RevisionGUID="c74e6e99-21c8-4b1c-bd50-c9d66a6ffe48" CreationDate="2021-07-18T12:07:32.103" UserId="7952" Comment="oops buckets were wrong" Text="The video is over simplifying a problem that has a long history and is far more complex then just &quot;how a camera captures images&quot;. Especially today when we have cameras that can capture flat out amazing amounts of data.&#xD;&#xA;&#xD;&#xA;If someone shows you a [color wheel][1], that never changes, then starts changing the brightness of the light illuminating that color wheel, and you press a button every time you see a difference on the wheel, you will press the button more often when the lights are dim, then when they are bright. It's simple physiology, so doesn't it seems reasonable to capture, then subsequently reproduce more dark colors then bright colors with our cameras and monitors? &#xD;&#xA;&#xD;&#xA;The bias is intentional, it is built into the system on purpose to make up for the short comings of technology, and take advantage of properties of our eyes. Yeah, modern equipment has over come many of they limitations but the vast majority of installed monitors in the world still have 8 bits of color built into them.&#xD;&#xA;&#xD;&#xA;And that is the reason for the &quot;square roots&quot;, its actually not square roots but lets not go there.&#xD;&#xA;&#xD;&#xA;Here is a fairly detailed explanation of how the &quot;compression&quot; works:&#xD;&#xA;&#xD;&#xA;To understand the compression, first lets normalize the range of values to be between 0 and 1. And knowing that the normalized values between 0.0 and 0.25 will have more visual impact then values between 0.75 and 1.0. Then what math function will &quot;stretch&quot; out the space for lower values, and &quot;compress&quot; larger values? Exponents do this quite neatly. For example $0.1^2=0.01$ while $0.2^2 = 0.04$  for a difference of $0.03$ so the values only moved a little bit along the number line. But closer to $1$ at say $0.8^2=0.64$ and then $0.9^2=0.81$ for a difference of $0.17$ so values close to 1 move a lot more then values close to zero. But the input values had the exact same difference of $0.1$. This is the opposite of what we want, so instead use the sqrt for our &quot;compression&quot; and then square the compressed values for &quot;decompression&quot;. Here is an example:&#xD;&#xA;&#xD;&#xA;Divide the range between 0 and 1 into 10 equally sized sections, call them buckets, then each bucket will be 0.1 in size. (computers use 256 buckets for each color) And we can compute a bucket. $sqrt(.1) = 0.316$ and $sqrt(.2)= 0.447$ so the nearest buckets are 3 and 4 respectively. While for $sqrt(.8)=0.894$ and $sqrt(.9)=0.948$ they both have the nearest bucket of 9! And that's it, the dark values are spread out into more buckets then the bright values.&#xD;&#xA;&#xD;&#xA;It really is that simple, the computers aren't actually doing any compression, they are just doing some math on each value. .&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Color_wheel" ContentLicense="CC BY-SA 4.0" />
  <row Id="33366" PostHistoryTypeId="2" PostId="11057" RevisionGUID="07ad6b9e-5063-43a2-b242-f03cbaf31302" CreationDate="2021-07-19T00:20:59.827" UserId="506" Text="I’m trying to render a 2D image something like this:&#xD;&#xA;&#xD;&#xA;![a circle with its edge illuminated by a line](https://i.stack.imgur.com/vkZB6.png)&#xD;&#xA;&#xD;&#xA;…where an arbitrary shape has its border illuminated by a line in a relatively physically accurate way, i.e. with less illumination reaching the shape at points that the line is farther away from. I’m generally familiar with some of the existing approximations in 3D, e.g. [linearly transformed cosines](https://eheitzresearch.wordpress.com/757-2/); as far as I can tell, though, there’s no literature on ways to do the same in 2D. It seems like there might even be a way to solve the actual integral analytically, but I’m not sure where to start. Any ideas?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33367" PostHistoryTypeId="1" PostId="11057" RevisionGUID="07ad6b9e-5063-43a2-b242-f03cbaf31302" CreationDate="2021-07-19T00:20:59.827" UserId="506" Text="Area-light approximation in 2D" ContentLicense="CC BY-SA 4.0" />
  <row Id="33368" PostHistoryTypeId="3" PostId="11057" RevisionGUID="07ad6b9e-5063-43a2-b242-f03cbaf31302" CreationDate="2021-07-19T00:20:59.827" UserId="506" Text="|lighting|geometry|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33369" PostHistoryTypeId="2" PostId="11058" RevisionGUID="65f0b9e7-fd21-41f2-9715-ecbbf8e86430" CreationDate="2021-07-19T05:11:33.897" UserId="506" Text="Found a solution—it may not be strictly accurate for 2D, but it produces the look that I’m after. “Linear Light Shading with Linearly Transformed Cosines”, in section 1.3, describes a closed-form solution to this integral; transforming the line’s endpoints into a space local to the surface and then running them through the `I_diffuse_line` function from listing 1.6 (modified to use 2-component vectors) yields reasonable-looking lighting.&#xD;&#xA;&#xD;&#xA;![a diagram of a sphere with a line projected onto it](https://i.stack.imgur.com/kNkMB.png)&#xD;&#xA;&#xD;&#xA;There’s a copy of the paper available [here](https://blog.unity.com/technology/linear-light-shading-with-linearly-transformed-cosines)." ContentLicense="CC BY-SA 4.0" />
  <row Id="33370" PostHistoryTypeId="2" PostId="11059" RevisionGUID="173f5040-6d2f-49e9-83db-448b8128cbac" CreationDate="2021-07-19T09:58:34.580" UserId="10096" Text="To reproduce the distortion in the image you would have to apply the model-view-projection matrix and then divide by $w$. If you use a projection matrix that flips $Z$ then you would get an inverted version. For more details on the transformations that occur for a perspective projection to happen see:&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_projectionmatrix.html&#xD;&#xA;http://www.songho.ca/opengl/gl_transform.html&#xD;&#xA;https://learnopengl.com/Getting-started/Transformations" ContentLicense="CC BY-SA 4.0" />
  <row Id="33371" PostHistoryTypeId="5" PostId="11059" RevisionGUID="b240fcab-609a-487e-89ad-bcaa27aa2091" CreationDate="2021-07-19T11:01:39.350" UserId="10096" Comment="added 6 characters in body" Text="To reproduce the distortion in the image you would have to apply the model-view-projection matrix and then divide by $w$. If you use a projection matrix that flips $Z$ then you would get an inverted version. For more details on the transformations that occur for a perspective projection to happen see:&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_projectionmatrix.html&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_transform.html&#xD;&#xA;&#xD;&#xA;https://learnopengl.com/Getting-started/Transformations&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33372" PostHistoryTypeId="2" PostId="11060" RevisionGUID="f6d9ef0a-0462-4b0b-a6b0-315fca09cf14" CreationDate="2021-07-19T14:00:59.003" UserId="16879" Text="I've seen several references to this and related concepts now but I can't find any hard details about these systems, and how they are implemented.&#xD;&#xA;&#xD;&#xA;The earliest reference I can find is from the [&quot;GPU-driven rendering pipelines&quot;][1] talk by Sebastian Altonen. &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But I was made aware of the topic from Nanite information that has surface recently, for example Brian Karis talks about it [in the presentation here][3], but not with many details:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Alex Evans also talked about the concept a bit in his [High Performance Graphics 2021 conference keynote][5], but Dreams (which he worked on) doesn't use triangle meshes, it's a signed distance field system instead:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;To summarize what I think I understand: &#xD;&#xA;&#xD;&#xA;Mesh vertices, or more generally the geometry representations you have, are apparently grouped in some form ( though I don't know by what algorithm that is done exactly ) into clusters, then culled on the GPU based on bounding volumes of those clusters.&#xD;&#xA;&#xD;&#xA;Apparently this concept  is well suited for GPU-driven occlusion and frustum culling (why and how?), dynamic LOD (why and how?), and makes it possible to create hierarchical representations of meshes where you can pick the LOD to render not for the whole mesh, but based on single clusters &#xD;&#xA;at rendering time (why and how?). Apparently, Nanite pushes this far enough that you can't see any transition between different LODs. &#xD;&#xA;&#xD;&#xA;What algorithms are used here for generating these clusters, culling them (particularly occlusion culling), representing them hierarchically, and picking LODs from them?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://advances.realtimerendering.com/s2015/aaltonenhaar_siggraph2015_combined_final_footer_220dpi.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/YrHgk.png&#xD;&#xA;  [3]: https://youtu.be/TMorJX3Nj6U?t=3592&#xD;&#xA;  [4]: https://i.stack.imgur.com/0Mhg5.jpg&#xD;&#xA;  [5]: https://youtu.be/eGfX1iWzkh0?t=2686&#xD;&#xA;  [6]: https://i.stack.imgur.com/hZhLw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33373" PostHistoryTypeId="1" PostId="11060" RevisionGUID="f6d9ef0a-0462-4b0b-a6b0-315fca09cf14" CreationDate="2021-07-19T14:00:59.003" UserId="16879" Text="What are 'mesh clusters' / hierarchical cluster culling (with LOD?) / triangle cluster culling and how do they relate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33374" PostHistoryTypeId="3" PostId="11060" RevisionGUID="f6d9ef0a-0462-4b0b-a6b0-315fca09cf14" CreationDate="2021-07-19T14:00:59.003" UserId="16879" Text="|rendering|geometry|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33375" PostHistoryTypeId="2" PostId="11061" RevisionGUID="4fa92b36-8788-4f13-bc95-e2680f5fb69e" CreationDate="2021-07-19T23:14:14.917" UserId="16702" Text="A bezier curve B(t) has 4 control points P0 = (0,0,0) , P1 = (1,0,0), P2 = (1,1,1) , P3 = (0,1,1). Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) B(-2) is not defined&#xD;&#xA;b) B(-1) = (-1,-1,-1)&#xD;&#xA;c) C(t) , t in [0,1] is in the surface that P0,P1,P2 define.&#xD;&#xA;&#xD;&#xA;I don't know if t can have values in a range not in [0,1]. The Bezier curves are parametric relations in general. We can define parametric equations that describe curves and t not in [0,1], but i never have read about Bezier Curves with t not in [0,1] so i am confused. For c) i believe that the surface of Bezier Curve is this that ALL control points must define and not a some of them. &#xD;&#xA;&#xD;&#xA;Again we have a Bezier curve B(t) with 4 control points but now in 2-dimensions. &#xD;&#xA;&#xD;&#xA;The P0 = (1,0) and the P1 = (0,1)&#xD;&#xA;The curve must be tangent at P0 in y-axis and tangent at P3 at x-axis [*].&#xD;&#xA;When t = 0.5 must pass from the point A(4,4).&#xD;&#xA;&#xD;&#xA;Find control points P1 and P2.&#xD;&#xA;&#xD;&#xA;In the equation that describe the cubic Bezier curve we set t =0.5. Then we create two relations one for the x and one for the y. But if P1(x1,y1) and P2 = (x2,y2) we have 4 unknowns and 2 relations. So we need another 2. Here i am confused about the *. Especially * means that derivative of the equation that describe the cubic bezier curve must be 0 in x coordinate, for t = 0 ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="33376" PostHistoryTypeId="1" PostId="11061" RevisionGUID="4fa92b36-8788-4f13-bc95-e2680f5fb69e" CreationDate="2021-07-19T23:14:14.917" UserId="16702" Text="Cubic Bezier Curve - General Questions" ContentLicense="CC BY-SA 4.0" />
  <row Id="33377" PostHistoryTypeId="3" PostId="11061" RevisionGUID="4fa92b36-8788-4f13-bc95-e2680f5fb69e" CreationDate="2021-07-19T23:14:14.917" UserId="16702" Text="|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33378" PostHistoryTypeId="5" PostId="11061" RevisionGUID="14b49b8f-5801-4dcf-a0b4-2c4a12f174ca" CreationDate="2021-07-20T03:53:22.360" UserId="16702" Comment="deleted 10 characters in body" Text="A bezier curve B(t) has 4 control points P0 = (0,0,0) , P1 = (1,0,0), P2 = (1,1,1) , P3 = (0,1,1). Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) B(-2) is not defined&#xD;&#xA;b) B(-1) = (-1,-1,-1)&#xD;&#xA;c) C(t) , t in [0,1] is in the plane that P0,P1,P2 define.&#xD;&#xA;&#xD;&#xA;I don't know if t can have values in a range not in [0,1]. The Bezier curves are parametric relations in general. We can define parametric equations that describe curves and t not in [0,1], but i never have read about Bezier Curves with t not in [0,1] so i am confused. For c) i believe that the Bezier Curve is in the plain that ALL control points define and not a some of them. &#xD;&#xA;&#xD;&#xA;Again we have a Bezier curve B(t) with 4 control points but now in 2-dimensions. &#xD;&#xA;&#xD;&#xA;The P0 = (1,0) and the P1 = (0,1)&#xD;&#xA;The curve must be tangent at P0 in y-axis and tangent at P3 at x-axis [*].&#xD;&#xA;When t = 0.5 must pass from the point A(4,4).&#xD;&#xA;&#xD;&#xA;Find control points P1 and P2.&#xD;&#xA;&#xD;&#xA;In the equation that describe the cubic Bezier curve we set t =0.5. Then we create two relations one for the x and one for the y. But if P1(x1,y1) and P2 = (x2,y2) we have 4 unknowns and 2 relations. So we need another 2. Here i am confused about the *. Especially * means that derivative of the equation that describe the cubic bezier curve must be 0 in x coordinate, for t = 0 ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="33379" PostHistoryTypeId="2" PostId="11062" RevisionGUID="58837dd1-3c27-417b-ad86-f6f30ed8f49f" CreationDate="2021-07-20T05:03:59.743" UserId="2695" Text="Regarding the first question: a bezier curve is defined as linear combinations of control points and basis function (Bernstein polynomials). Although usually one considers a unit interval as parametrization you can also evaluate the polynomials with e.g. negative numbers. So i guess b) is right (i did not do the math, but the other two answers cannot be right).&#xD;&#xA;&#xD;&#xA;Regarding the second question: you are right that you are looking for 4 unknowns. The tangent constraints constitute 2 equations (one for P0 one for P3). The other constraint that the curve needs to pass A make up 2 more equations,so the problem should be well defined." ContentLicense="CC BY-SA 4.0" />
  <row Id="33380" PostHistoryTypeId="5" PostId="11061" RevisionGUID="63632798-7f49-4568-b742-8361003f14df" CreationDate="2021-07-20T05:10:39.240" UserId="16702" Comment="added 79 characters in body" Text="A bezier curve B(t) has 4 control points P0 = (0,0,0) , P1 = (1,0,0), P2 = (1,1,1) , P3 = (0,1,1). Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) B(-2) is not defined&#xD;&#xA;b) B(-1) = (-1,-1,-1)&#xD;&#xA;c) C(t) , t in [0,1] is in the plane that P0,P1,P2 define.&#xD;&#xA;&#xD;&#xA;I don't know if t can have values in a range not in [0,1]. The Bezier curves are parametric relations in general. We can define parametric equations that describe curves and t not in [0,1], but i never have read about Bezier Curves with t not in [0,1] so i am confused. For c) i believe that the Bezier Curve is in the plain that ALL control points define and not a some of them. &#xD;&#xA;&#xD;&#xA;Again we have a Bezier curve B(t) with 4 control points but now in 2-dimensions. &#xD;&#xA;&#xD;&#xA;The P0 = (1,0) and the P1 = (0,1)&#xD;&#xA;The curve must be tangent at P0 in y-axis and tangent at P3 at x-axis [*].&#xD;&#xA;When t = 0.5 must pass from the point A(4,4).&#xD;&#xA;&#xD;&#xA;Find control points P1 and P2.&#xD;&#xA;&#xD;&#xA;In the equation that describe the cubic Bezier curve we set t =0.5. Then we create two relations one for the x and one for the y. But if P1(x1,y1) and P2 = (x2,y2) we have 4 unknowns and 2 relations. So we need another 2. Here i am confused about the *. Especially * means that derivative of the equation that describe the cubic bezier curve must be 0 in x coordinate, for t = 0 ? How i can create the other two equations that we help me to solve the problem ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33381" PostHistoryTypeId="5" PostId="11061" RevisionGUID="72ed1a04-866d-4373-8c6d-7c29fc1dac51" CreationDate="2021-07-20T05:20:29.497" UserId="16702" Comment="edited body" Text="A bezier curve B(t) has 4 control points P0 = (0,0,0) , P1 = (1,0,0), P2 = (1,1,1) , P3 = (0,1,1). Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) B(-2) is not defined&#xD;&#xA;b) B(-1) = (-1,-1,-1)&#xD;&#xA;c) B(t) , t in [0,1] is in the plane that P0,P1,P2 define.&#xD;&#xA;&#xD;&#xA;I don't know if t can have values in a range not in [0,1]. The Bezier curves are parametric relations in general. We can define parametric equations that describe curves and t not in [0,1], but i never have read about Bezier Curves with t not in [0,1] so i am confused. For c) i believe that the Bezier Curve is in the plain that ALL control points define and not a some of them. &#xD;&#xA;&#xD;&#xA;Again we have a Bezier curve B(t) with 4 control points but now in 2-dimensions. &#xD;&#xA;&#xD;&#xA;The P0 = (1,0) and the P1 = (0,1)&#xD;&#xA;The curve must be tangent at P0 in y-axis and tangent at P3 at x-axis [*].&#xD;&#xA;When t = 0.5 must pass from the point A(4,4).&#xD;&#xA;&#xD;&#xA;Find control points P1 and P2.&#xD;&#xA;&#xD;&#xA;In the equation that describe the cubic Bezier curve we set t =0.5. Then we create two relations one for the x and one for the y. But if P1(x1,y1) and P2 = (x2,y2) we have 4 unknowns and 2 relations. So we need another 2. Here i am confused about the *. Especially * means that derivative of the equation that describe the cubic bezier curve must be 0 in x coordinate, for t = 0 ? How i can create the other two equations that we help me to solve the problem ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33382" PostHistoryTypeId="2" PostId="11063" RevisionGUID="a85187ee-0076-4e7e-b369-433809f04598" CreationDate="2021-07-21T01:25:17.810" UserId="16914" Text="I have an old renderer from years ago written with OpenGL immediate mode. I've decided to learn Vulkan and I'm converting my old project as a way to learn the new concepts.&#xD;&#xA;&#xD;&#xA;One of the things my old renderer did is display a 'glow' around a star that planets and other objects could pass through (see screenshot).  This was done by using a greyscale texture and using some additive blending with colours - it created a nice effect.&#xD;&#xA;&#xD;&#xA;I'm wondering if there's a modern/better looking technique that I can investigate to make this look even better 10 years on.  It feels like something an 'ambient spherical volume light' around the sun could achieve, with the volume filled with fog?  &#xD;&#xA;&#xD;&#xA;I'm not sure if the approach I wrote makes any sense, just looking for ideas!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kT6Cz.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="33383" PostHistoryTypeId="1" PostId="11063" RevisionGUID="a85187ee-0076-4e7e-b369-433809f04598" CreationDate="2021-07-21T01:25:17.810" UserId="16914" Text="Modern ways to implement a glow that encompasses a volume" ContentLicense="CC BY-SA 4.0" />
  <row Id="33384" PostHistoryTypeId="3" PostId="11063" RevisionGUID="a85187ee-0076-4e7e-b369-433809f04598" CreationDate="2021-07-21T01:25:17.810" UserId="16914" Text="|opengl|lighting|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33385" PostHistoryTypeId="5" PostId="11062" RevisionGUID="35137e6a-7573-448a-a72d-5e440d15004b" CreationDate="2021-07-21T01:54:16.933" UserId="2695" Comment="Clarified how derivatives are computed as requested by the OP." Text="Regarding the first question: a bezier curve is defined as linear combinations of control points and basis function (Bernstein polynomials). Although usually one considers a unit interval as parametrization you can also evaluate the polynomials with e.g. negative numbers. So i guess b) is right (i did not do the math, but the other two answers cannot be right).&#xD;&#xA;&#xD;&#xA;Regarding the second question: you are right that you are looking for 4 unknowns. The tangent constraints constitute 2 equations (one for P0 one for P3). The other constraint that the curve needs to pass A make up 2 more equations,so the problem should be well defined. &#xD;&#xA;&#xD;&#xA;One property of Bezier curves is that at its end points the curve is tangent to the control polygon. So in your example you have the additional conditions P1 - P0 = (0,a) and P3 - P2 = (b, 0). " ContentLicense="CC BY-SA 4.0" />
  <row Id="33386" PostHistoryTypeId="2" PostId="11064" RevisionGUID="33b2fac9-a820-423c-9f52-8201b27726da" CreationDate="2021-07-21T02:42:54.917" UserId="16730" Text="Given a plane, assuming that view direction and light direction are both fixed, there must be point which is the brightest point on that plane(where half vector equals to the normal vector).What is the terminology for that point?(Assuming we are using GGX)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33387" PostHistoryTypeId="1" PostId="11064" RevisionGUID="33b2fac9-a820-423c-9f52-8201b27726da" CreationDate="2021-07-21T02:42:54.917" UserId="16730" Text="What is the terminology for the brightest point on a plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="33388" PostHistoryTypeId="3" PostId="11064" RevisionGUID="33b2fac9-a820-423c-9f52-8201b27726da" CreationDate="2021-07-21T02:42:54.917" UserId="16730" Text="|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33389" PostHistoryTypeId="4" PostId="11063" RevisionGUID="fbc13c36-b80b-4fd3-a75a-2ffd2349f745" CreationDate="2021-07-21T03:38:08.273" UserId="16914" Comment="edited title" Text="Techniques to implement a glow that encompasses a volume" ContentLicense="CC BY-SA 4.0" />
  <row Id="33390" PostHistoryTypeId="5" PostId="11061" RevisionGUID="df184a49-235a-46c5-b76a-14312375dc82" CreationDate="2021-07-21T09:48:01.477" UserId="209" Comment="improved formatting" Text="A bezier curve B(t) has 4 control points P0 = (0,0,0) , P1 = (1,0,0), P2 = (1,1,1) , P3 = (0,1,1). Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) B(-2) is not defined&lt;br/&gt;&#xD;&#xA;b) B(-1) = (-1,-1,-1)&lt;br/&gt;&#xD;&#xA;c) B(t) , t in [0,1] is in the plane that P0,P1,P2 define.&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;I don't know if t can have values in a range not in [0,1]. The Bezier curves are parametric relations in general. We can define parametric equations that describe curves and t not in [0,1], but i never have read about Bezier Curves with t not in [0,1] so i am confused. For c) i believe that the Bezier Curve is in the plain that ALL control points define and not a some of them. &#xD;&#xA;&#xD;&#xA;Again we have a Bezier curve B(t) with 4 control points but now in 2-dimensions. &#xD;&#xA;&#xD;&#xA;The P0 = (1,0) and the P1 = (0,1)&#xD;&#xA;The curve must be tangent at P0 in y-axis and tangent at P3 at x-axis [*].&#xD;&#xA;When t = 0.5 must pass from the point A(4,4).&#xD;&#xA;&#xD;&#xA;Find control points P1 and P2.&#xD;&#xA;&#xD;&#xA;In the equation that describe the cubic Bezier curve we set t =0.5. Then we create two relations one for the x and one for the y. But if P1(x1,y1) and P2 = (x2,y2) we have 4 unknowns and 2 relations. So we need another 2. Here i am confused about the *. Especially * means that derivative of the equation that describe the cubic bezier curve must be 0 in x coordinate, for t = 0 ? How i can create the other two equations that we help me to solve the problem ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33391" PostHistoryTypeId="2" PostId="11065" RevisionGUID="139f7c92-1e84-46d4-b20f-8d46722bed65" CreationDate="2021-07-21T10:15:48.690" UserId="15772" Text="I am struggling to understand as to why fundamentally triangles shaded through Gouraud shading and ones shaded through Phong shading look different.&#xD;&#xA;&#xD;&#xA;From my understanding, Gouraud Shading, takes the vertices of a triangle. It calculates the color at each vertex with the help of vertex normals, and interpolates that color across the triangle per-pixel. Phong Shading calculates the normal at each vertex, and interpolates the normals across the triangle per-pixel and shades the said pixels using interpolated normals&#xD;&#xA;&#xD;&#xA;Both involve interpolation. Why is it that interpolating normals produces a more realistic results, while interpolating the colors directly does not? What is it about the interpolation of colors that makes it less accurate?&#xD;&#xA;&#xD;&#xA;Under the hood, isn't interpolating just a color similar to interpolating the normal and finding the color at every point? If not, intuitively how are they both different then?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33392" PostHistoryTypeId="1" PostId="11065" RevisionGUID="139f7c92-1e84-46d4-b20f-8d46722bed65" CreationDate="2021-07-21T10:15:48.690" UserId="15772" Text="Gouraud Shading interpolates color across a triangle using vertex normals. Phong Shading interpolates normals. How are their end-results different?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33393" PostHistoryTypeId="3" PostId="11065" RevisionGUID="139f7c92-1e84-46d4-b20f-8d46722bed65" CreationDate="2021-07-21T10:15:48.690" UserId="15772" Text="|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33394" PostHistoryTypeId="2" PostId="11066" RevisionGUID="b8d820a4-247a-45d4-b705-664828751e6e" CreationDate="2021-07-21T12:09:18.440" UserId="7952" Text="A simple spherical light volume can be computed as a post processing effect by drawing a cube with the face winding direction reversed (left hand winding vs right hand winding). This displays the interior of the cube. This gives a nice &quot;halo&quot; effect to lights.&#xD;&#xA;&#xD;&#xA;Compute the intersection of a ray with a sphere that is fitted to the cube inside the fragment shader. The distance between the two intersection points are used to compute the halo's brightness. Usually the halo is assumed to have constant density so there is no ray casting just a straight forward sphere intersection.&#xD;&#xA;&#xD;&#xA;Lastly, the depth buffer is used after computing the halo intersections to account for objects both inside, or in front of the halo.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33395" PostHistoryTypeId="2" PostId="11067" RevisionGUID="6ceb67a0-53b6-4344-aed9-5a684bb3f1fb" CreationDate="2021-07-21T12:38:22.793" UserId="9943" Text="I'm new to programming raster graphics and trying to build a simple app, and I want to make sure lines have a smooth anti-aliased look. I am wondering if this can be achieved simply by having a brush that stamps circle gradients that look like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In other words, does a simple gradient satisfy the needs of anti-aliasing or is there a more complex algorithm involved?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/h3qGu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33396" PostHistoryTypeId="1" PostId="11067" RevisionGUID="6ceb67a0-53b6-4344-aed9-5a684bb3f1fb" CreationDate="2021-07-21T12:38:22.793" UserId="9943" Text="Is a simple circle gradient enough to make an anti-aliased brush?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33397" PostHistoryTypeId="3" PostId="11067" RevisionGUID="6ceb67a0-53b6-4344-aed9-5a684bb3f1fb" CreationDate="2021-07-21T12:38:22.793" UserId="9943" Text="|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33398" PostHistoryTypeId="5" PostId="11067" RevisionGUID="5f51b2df-bd59-49c7-a87a-e7d28b636792" CreationDate="2021-07-21T13:21:56.340" UserId="9943" Comment="added 77 characters in body" Text="I'm new to programming raster graphics and trying to build a simple app, and I want to make sure lines have a smooth anti-aliased look. I am wondering if this can be achieved simply by having a brush that stamps circle gradients that look like this, where the outer color could be any color but most importantly an alpha of 0:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In other words, does a simple gradient satisfy the needs of anti-aliasing or is there a more complex algorithm involved?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/h3qGu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33399" PostHistoryTypeId="2" PostId="11068" RevisionGUID="c870e5b1-4855-4c00-af5e-6bf445f06a8c" CreationDate="2021-07-21T14:32:29.557" UserId="7952" Text="RGB &quot;Colors&quot; contain chromaticity(color) and luminance(brightness), normal vectors contain direction and magnitude. &#xD;&#xA;&#xD;&#xA;Gouraud shading approximates color gradients.&#xD;&#xA;&#xD;&#xA;Phong shading approximates surface gradients.&#xD;&#xA;&#xD;&#xA;Imagine a large triangle with a small specular highlight at the center and all 3 vertex positions have normal vectors pointing away from the highlight so are only dimly lit.&#xD;&#xA;&#xD;&#xA;Interpolating the color will completely miss the highlight and only give values between those at the 3 vertex positions.&#xD;&#xA;&#xD;&#xA;Interpolating the normal vectors will force a change of direction in the vector so that the highlight is visible. &#xD;&#xA;&#xD;&#xA;Also, interpolation of normal vectors changes their length which can be recalculated in the fragment shader to help improve the approximation.  But there is very little we can do to help correct interpolated colors.&#xD;&#xA;&#xD;&#xA;Additionally, interpolated colors tend have a nice perfect change from one color to another across the surface of the triangle, this causes an effect called &quot;mach banding&quot; where it looks like there are color bands when the transition is actually smooth." ContentLicense="CC BY-SA 4.0" />
  <row Id="33400" PostHistoryTypeId="5" PostId="11061" RevisionGUID="ee07cc58-b323-4a0f-88d3-520c12967380" CreationDate="2021-07-21T14:45:28.290" UserId="16702" Comment="edited body" Text="A bezier curve B(t) has 4 control points P0 = (0,0,0) , P1 = (1,0,0), P2 = (1,1,1) , P3 = (0,1,1). Which of the following are correct:&#xD;&#xA;&#xD;&#xA;a) B(-2) is not defined&lt;br/&gt;&#xD;&#xA;b) B(-1) = (-1,-1,-1)&lt;br/&gt;&#xD;&#xA;c) B(t) , t in [0,1] is in the plane that P0,P1,P2 define.&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;I don't know if t can have values in a range not in [0,1]. The Bezier curves are parametric relations in general. We can define parametric equations that describe curves and t not in [0,1], but i never have read about Bezier Curves with t not in [0,1] so i am confused. For c) i believe that the Bezier Curve is in the plain that ALL control points define and not in some of them. &#xD;&#xA;&#xD;&#xA;Again we have a Bezier curve B(t) with 4 control points but now in 2-dimensions. &#xD;&#xA;&#xD;&#xA;The P0 = (1,0) and the P3 = (0,1)&#xD;&#xA;The curve must be tangent at P0 in y-axis and tangent at P3 at x-axis [*].&#xD;&#xA;When t = 0.5 must pass from the point A(4,4).&#xD;&#xA;&#xD;&#xA;Find control points P1 and P2.&#xD;&#xA;&#xD;&#xA;In the equation that describe the cubic Bezier curve we set t =0.5. Then we create two relations one for the x and one for the y. But if P1(x1,y1) and P2 = (x2,y2) we have 4 unknowns and 2 relations. So we need another 2. Here i am confused about the *. Especially * means that derivative of the equation that describe the cubic bezier curve must be 0 in x coordinate, for t = 0 ? How i can create the other two equations that we help me to solve the problem ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33401" PostHistoryTypeId="2" PostId="11069" RevisionGUID="0ab1740f-1908-439e-8ea0-1119a4c54af2" CreationDate="2021-07-21T16:47:14.470" UserId="48" Text="Yes, this will work. You'll want to have the length of the gradient be short, like 0.5-1 pixels. As long as it produces a slight region of falloff around the edges of the shape, it will suffice for antialiasing.&#xD;&#xA;&#xD;&#xA;A somewhat more efficient approach than literally stamping out zillions of brushes would be to evaluate the distance of each pixel center (in the area being drawn) to the shape being drawn, such as a line, stroke, rectangle, etc. and then applying the gradient as a function based on the distance. That's how the classic [Fast Prefiltered Lines](https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-22-fast-prefiltered-lines) article works." ContentLicense="CC BY-SA 4.0" />
  <row Id="33402" PostHistoryTypeId="2" PostId="11070" RevisionGUID="1a862704-cb08-4c00-b8fc-3b34c8f10533" CreationDate="2021-07-21T16:49:32.543" UserId="48" Text="I don't know if there's a specific standardized term for that point, but the general bright area is called the &quot;highlight&quot; or &quot;specular highlight&quot;, and so the brightest point on it could be called the highlight peak or highlight center." ContentLicense="CC BY-SA 4.0" />
  <row Id="33403" PostHistoryTypeId="50" PostId="9616" RevisionGUID="845f7029-624f-4aec-ab00-00eb191e1ec5" CreationDate="2021-07-21T20:02:00.190" UserId="-1" />
  <row Id="33404" PostHistoryTypeId="2" PostId="11071" RevisionGUID="95325239-52e5-4c43-a0bf-55d036c8a934" CreationDate="2021-07-21T21:40:35.283" UserId="48" Text="[GLTF](https://www.khronos.org/gltf/) is a standardized 3D file format from the Khronos group, the same people behind OpenGL and Vulkan. It has both text and binary formats (the latter called GLB) and is a full-featured format, including support for vertex colors.&#xD;&#xA;&#xD;&#xA;[tinygltf](https://github.com/syoyo/tinygltf) is an example of a C++ library for loading and saving GLTF/GLB files, but there are many others, I'm sure." ContentLicense="CC BY-SA 4.0" />
  <row Id="33405" PostHistoryTypeId="2" PostId="11072" RevisionGUID="7a5dad6a-49f8-42cf-ab3d-faab6b6ab2f0" CreationDate="2021-07-21T22:04:52.813" UserId="7462" Text="I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not entirely sure where they are coming from, as I am using nothing but linear operations to render this.&#xD;&#xA;&#xD;&#xA;This is how I generate a ray:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;    {&#xD;&#xA;        vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;        r.y /= aspect_ratio;&#xD;&#xA;    &#xD;&#xA;        return normalize(r);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And after that all I do is ray march until I am inside the volume.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TDJyE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33406" PostHistoryTypeId="1" PostId="11072" RevisionGUID="7a5dad6a-49f8-42cf-ab3d-faab6b6ab2f0" CreationDate="2021-07-21T22:04:52.813" UserId="7462" Text="How to avoid curvature artifact in raytracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33407" PostHistoryTypeId="3" PostId="11072" RevisionGUID="7a5dad6a-49f8-42cf-ab3d-faab6b6ab2f0" CreationDate="2021-07-21T22:04:52.813" UserId="7462" Text="|raytracing|shader|artifacts|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33408" PostHistoryTypeId="5" PostId="11071" RevisionGUID="4c3dd08c-03c9-4931-9e27-c2da629b126a" CreationDate="2021-07-21T22:38:31.637" UserId="48" Comment="link to the gltf github instead" Text="[GLTF](https://github.com/KhronosGroup/glTF) is a standardized 3D file format from the Khronos group, the same people behind OpenGL and Vulkan. It has both text and binary formats (the latter called GLB) and is a full-featured format, including support for vertex colors.&#xD;&#xA;&#xD;&#xA;[tinygltf](https://github.com/syoyo/tinygltf) is an example of a C++ library for loading and saving GLTF/GLB files, but there are many others, I'm sure." ContentLicense="CC BY-SA 4.0" />
  <row Id="33409" PostHistoryTypeId="5" PostId="11068" RevisionGUID="2dd9ea9e-b8f2-44a6-b981-fde677de73d8" CreationDate="2021-07-22T13:40:23.883" UserId="7952" Comment="add brief explanation of why two vectors sums change length" Text="RGB &quot;Colors&quot; contain chromaticity(color) and luminance(brightness), normal vectors contain direction and magnitude. &#xD;&#xA;&#xD;&#xA;Gouraud shading approximates color gradients.&#xD;&#xA;&#xD;&#xA;Phong shading approximates surface gradients.&#xD;&#xA;&#xD;&#xA;Imagine a large triangle with a small specular highlight at the center and all 3 vertex positions have normal vectors pointing away from the highlight so are only dimly lit.&#xD;&#xA;&#xD;&#xA;Interpolating the color will completely miss the highlight and only give values between those at the 3 vertex positions.&#xD;&#xA;&#xD;&#xA;Interpolating the normal vectors will force a change of direction in the vector so that the highlight is visible. &#xD;&#xA;&#xD;&#xA;Also, interpolation of normal vectors changes their length which can be recalculated in the fragment shader to help improve the approximation.  But there is very little we can do to help correct interpolated colors.&#xD;&#xA;&#xD;&#xA;Edit: Why interpolating between two vectors changes length.&#xD;&#xA;To interpolate vectors we use the formula $N_c = N_a\alpha+N_b(1-\alpha)$ where $N_a$ and $N_b$ are the two vectors being interpolated. This includes the sum of two vectors. Adding vectors can be thought of visually as placing them end to end, so the sum of two vectors results in a third vector with its own length resulting from the angle between the two vectors.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Additionally, interpolated colors tend have a nice perfect change from one color to another across the surface of the triangle, this causes an effect called &quot;mach banding&quot; where it looks like there are color bands when the transition is actually smooth.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bUp3b.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="33410" PostHistoryTypeId="2" PostId="11073" RevisionGUID="0282a3d6-2137-47e6-af64-f00084e898db" CreationDate="2021-07-22T16:40:56.610" UserId="38" Text="View angle changes all the time. In goraud shading the color sampling is done once per vertex.&#xD;&#xA;&#xD;&#xA;But in phong shading the angle between view angle and normal is calculated for every pixel.&#xD;&#xA;&#xD;&#xA;Why would that be different. Well simply because angle change is not a linearily changing quantity. (Ill draw a picture later when i get to a computer) &#xD;&#xA;&#xD;&#xA;Imagine a large plane. That is lit symmetrically, and has same normal directions in the corners. Camera is placed so it is aimed at the middle of the plane. Now the goraud shading will show you a flat colored plane. But the phong will not as at some point on the plane you will have a reflection directly from the light showing a specular hit.&#xD;&#xA;&#xD;&#xA;So they are different." ContentLicense="CC BY-SA 4.0" />
  <row Id="33411" PostHistoryTypeId="5" PostId="11073" RevisionGUID="ac6fea6f-4ec2-4684-aafb-47a00d730fb2" CreationDate="2021-07-22T16:46:09.450" UserId="38" Comment="added 16 characters in body" Text="View angle changes all the time. In goraud shading the color sampling is done once per vertex.&#xD;&#xA;&#xD;&#xA;But in phong shading the angle between view angle and normal is calculated for every pixel.&#xD;&#xA;&#xD;&#xA;Why would that be different. Well simply because angle change, and its cosine, is not a linearily changing quantity. (Ill draw a picture later when i get to a computer) &#xD;&#xA;&#xD;&#xA;Imagine a large plane. That is lit symmetrically, and has same normal directions in the corners. Camera is placed so it is aimed at the middle of the plane. Now the goraud shading will show you a flat colored plane. But the phong will not as at some point on the plane you will have a reflection directly from the light showing a specular hit.&#xD;&#xA;&#xD;&#xA;So they are different." ContentLicense="CC BY-SA 4.0" />
  <row Id="33412" PostHistoryTypeId="5" PostId="11072" RevisionGUID="40b10869-38b2-4b5c-9b37-d49ee7837d98" CreationDate="2021-07-22T19:01:45.297" UserId="7462" Comment="added 4458 characters in body" Text="I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not entirely sure where they are coming from, as I am using nothing but linear operations to render this.&#xD;&#xA;&#xD;&#xA;This is how I generate a ray:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;    {&#xD;&#xA;        vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;        r.y /= aspect_ratio;&#xD;&#xA;    &#xD;&#xA;        return normalize(r);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And after that all I do is ray march until I am inside the volume.&#xD;&#xA;&#xD;&#xA;This is the full shader:&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;#extension GL_ARB_separate_shader_objects : enable&#xD;&#xA;#extension GL_EXT_scalar_block_layout : enable&#xD;&#xA;#extension GL_NV_compute_shader_derivatives : enable&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 8, local_size_y = 8) in;&#xD;&#xA;&#xD;&#xA;layout(binding = 0) uniform MVPOnlyUbo&#xD;&#xA;{&#xD;&#xA;    mat4 model;&#xD;&#xA;    mat4 view;&#xD;&#xA;    mat4 proj;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(binding = 1, rgba16f) uniform image2D output_image;&#xD;&#xA;&#xD;&#xA;layout(binding = 2) uniform RayTracingData&#xD;&#xA;{&#xD;&#xA;    uint display_width;&#xD;&#xA;    uint display_height;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(binding = 3) uniform sampler2D albedo;&#xD;&#xA;&#xD;&#xA;#include &lt;phong_lighting.glsl&gt;&#xD;&#xA;&#xD;&#xA;float SphereFunction(vec3 position)&#xD;&#xA;{&#xD;&#xA;    return sqrt(dot(position, position)) - 64;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;{&#xD;&#xA;    vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;    r.y /= aspect_ratio;&#xD;&#xA;&#xD;&#xA;    return normalize(r);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float SdRoundBox( vec3 p  )&#xD;&#xA;{&#xD;&#xA;    vec3 b = vec3(2, 2, 2);&#xD;&#xA;    float r = 0.5;&#xD;&#xA;    vec3 q = abs(p) - b;&#xD;&#xA;    return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 Gradient(vec3 point)&#xD;&#xA;{&#xD;&#xA;    const float epsilon = 0.0001;&#xD;&#xA;    const float dx =&#xD;&#xA;          SdBoxSphere(vec3(point.x + epsilon, point.y, point.z))&#xD;&#xA;        - SdBoxSphere(vec3(point.x - epsilon, point.y, point.z));&#xD;&#xA;&#xD;&#xA;    const float dy =&#xD;&#xA;          SdBoxSphere(vec3(point.x, point.y + epsilon, point.z))&#xD;&#xA;        - SdBoxSphere(vec3(point.x, point.y - epsilon, point.z));&#xD;&#xA;&#xD;&#xA;    const float dz =&#xD;&#xA;          SdBoxSphere(vec3(point.x, point.y, point.z  + epsilon))&#xD;&#xA;        - SdBoxSphere(vec3(point.x, point.y, point.z  - epsilon));&#xD;&#xA;&#xD;&#xA;    return vec3(dx, dy, dz);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 BiplanarMapping( sampler2D sam, in vec3 p, in vec3 n, in float k )&#xD;&#xA;{&#xD;&#xA;    // grab coord derivatives for texturing&#xD;&#xA;    vec3 dpdx = vec3(0.01);//dFdx(p);&#xD;&#xA;    vec3 dpdy = vec3(0.01);//dFdy(p);&#xD;&#xA;    n = abs(n);&#xD;&#xA;&#xD;&#xA;    // determine major axis (in x; yz are following axis)&#xD;&#xA;    ivec3 ma = (n.x&gt;n.y &amp;&amp; n.x&gt;n.z) ? ivec3(0,1,2) :&#xD;&#xA;               (n.y&gt;n.z)            ? ivec3(1,2,0) :&#xD;&#xA;                                      ivec3(2,0,1) ;&#xD;&#xA;    // determine minor axis (in x; yz are following axis)&#xD;&#xA;    ivec3 mi = (n.x&lt;n.y &amp;&amp; n.x&lt;n.z) ? ivec3(0,1,2) :&#xD;&#xA;               (n.y&lt;n.z)            ? ivec3(1,2,0) :&#xD;&#xA;                                      ivec3(2,0,1) ;&#xD;&#xA;    // determine median axis (in x;  yz are following axis)&#xD;&#xA;    ivec3 me = ivec3(3) - mi - ma;&#xD;&#xA;&#xD;&#xA;    // project+fetch&#xD;&#xA;    vec4 x = textureGrad( sam, vec2(   p[ma.y],   p[ma.z]),&#xD;&#xA;                               vec2(dpdx[ma.y],dpdx[ma.z]),&#xD;&#xA;                               vec2(dpdy[ma.y],dpdy[ma.z]) );&#xD;&#xA;    vec4 y = textureGrad( sam, vec2(   p[me.y],   p[me.z]),&#xD;&#xA;                               vec2(dpdx[me.y],dpdx[me.z]),&#xD;&#xA;                               vec2(dpdy[me.y],dpdy[me.z]) );&#xD;&#xA;&#xD;&#xA;    // blend factors&#xD;&#xA;    vec2 w = vec2(n[ma.x],n[me.x]);&#xD;&#xA;    // make local support&#xD;&#xA;    w = clamp( (w-0.5773)/(1.0-0.5773), 0.0, 1.0 );&#xD;&#xA;    // shape transition&#xD;&#xA;    w = pow( w, vec2(k/8.0) );&#xD;&#xA;    // blend and return&#xD;&#xA;    return (x*w.x + y*w.y) / (w.x + w.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    const float aspect_ratio = float(display_width) / float(display_height);&#xD;&#xA;    const float disp_x = gl_GlobalInvocationID.x;&#xD;&#xA;    const float disp_y = gl_GlobalInvocationID.y;&#xD;&#xA;&#xD;&#xA;    const float x = disp_x * 2 / display_width - 1;&#xD;&#xA;    const float y = disp_y * 2 / display_height - 1;&#xD;&#xA;&#xD;&#xA;    const vec3 r = (inverse(view) * vec4(GenerateRay(vec2(x, y), aspect_ratio, 45), 0)).xyz;&#xD;&#xA;    const vec3 cam_pos = (inverse(view) * vec4(0, 0, 0, 1)).xyz;&#xD;&#xA;&#xD;&#xA;    vec3 ray_pos = vec3(x, y, 0) + cam_pos;&#xD;&#xA;    vec4 x_color = vec4(0);&#xD;&#xA;&#xD;&#xA;    float last_distance = 0;&#xD;&#xA;    for(uint i = 0; i &lt; 100; i++)&#xD;&#xA;    {&#xD;&#xA;        float sphere_radius = SdRoundBoxray_pos);&#xD;&#xA;        ray_pos += r * sphere_radius;&#xD;&#xA;        last_distance = sphere_radius;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    const vec3 normal = normalize(Gradient(ray_pos));&#xD;&#xA;    vec3 albedo = BiplanarMapping( albedo, ray_pos, normal, 10 ).rgb;&#xD;&#xA;    float test = min(min(mod(ray_pos.x, 1.f), mod(ray_pos.y, 1.f)), mod(ray_pos.z, 1.f));&#xD;&#xA;    vec4 highlight = test &lt;= 0.01 ? vec4(1, 0, 0, 1) : vec4(0);&#xD;&#xA;&#xD;&#xA;    vec4 color = BlinnPhong(&#xD;&#xA;        ray_pos,&#xD;&#xA;        normal,&#xD;&#xA;        cam_pos,&#xD;&#xA;        albedo,&#xD;&#xA;        vec3(100),&#xD;&#xA;        normalize(vec3(1, 1, 1)) * 0.3,&#xD;&#xA;        1)&#xD;&#xA;        + highlight;&#xD;&#xA;&#xD;&#xA;    x_color = color * int(last_distance &lt; 0.01);&#xD;&#xA;&#xD;&#xA;    imageStore(&#xD;&#xA;        output_image,&#xD;&#xA;        ivec2(disp_x, disp_y),&#xD;&#xA;        x_color&#xD;&#xA;    );&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;  [1]: https://i.stack.imgur.com/TDJyE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33413" PostHistoryTypeId="5" PostId="11073" RevisionGUID="bd34cec7-22e4-4431-a42b-2897c7899946" CreationDate="2021-07-22T22:15:26.370" UserId="38" Comment="added 235 characters in body" Text="View angle changes all the time. In goraud shading the color sampling is done once per vertex.&#xD;&#xA;&#xD;&#xA;But in phong shading the angle between view angle and normal is calculated for every pixel.&#xD;&#xA;&#xD;&#xA;Why would that be different. Well simply because angle changes, and its cosine, is not a linearly changing quantity. (Ill draw a picture later when i get to a computer) &#xD;&#xA;&#xD;&#xA;Imagine a large plane diffuse plane. Then the diffuse shading you see is based on the dot product of the normal and the normalized vector to light. Now imagine the light is in the middle of the plane. If you only have verices at the corners of the plane you get a uniform intensity. If you subdivide once you do not. If you subdivide by pixel you get phong shading and due to the dot prduct not being linear a different answer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;&#xD;&#xA;A noninear function does not approximate well with a linear function.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/75IWx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33414" PostHistoryTypeId="2" PostId="11074" RevisionGUID="4aee0ceb-0f87-4451-8272-fefeed9e688b" CreationDate="2021-07-23T07:08:13.177" UserId="6496" Text="I am looking at a sample code from a respected source and the *mipmap level-of-detail* parameter (float) is passed to the vertex shader as a uniform which then passes to the fragment shader *without* using the **flat** keyword, thus subject to interpolation(but all the vertex shaders are providing the same value-what would be the point of interpolation). What could I be missing here?&#xD;&#xA;&#xD;&#xA;Is it not better to pass a such a variable as a uniform to the fragment shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33415" PostHistoryTypeId="1" PostId="11074" RevisionGUID="4aee0ceb-0f87-4451-8272-fefeed9e688b" CreationDate="2021-07-23T07:08:13.177" UserId="6496" Text="Level of detail passed from vertex shader to fragment shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="33416" PostHistoryTypeId="3" PostId="11074" RevisionGUID="4aee0ceb-0f87-4451-8272-fefeed9e688b" CreationDate="2021-07-23T07:08:13.177" UserId="6496" Text="|glsl|vulkan|fragment-shader|mipmap|uniform-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33417" PostHistoryTypeId="5" PostId="10746" RevisionGUID="05c88846-48ab-47be-b320-0912e37bad15" CreationDate="2021-07-23T12:10:43.490" UserId="209" Comment="fixed a typo" Text="This is not really an answer to the latter parts of your question but more to address&#xD;&#xA;&gt; As we know, tiles can make it quicker to update large portions of the display at once, as compared with a bitmap. To put, say a letter, on the screen, the Commodore 64 typically does two writes (the screencode and the attribute)&#xD;&#xA;&#xD;&#xA;What you are effectively describing is a compressed framebuffer where you are directly writing/storing compressed data and letting the display pipeline decompress on the fly. &#xD;&#xA;&#xD;&#xA;I would say that such things &quot;still exist&quot; in today's games/hardware, but not perhaps in the form you are expecting.&#xD;&#xA;&#xD;&#xA;1) Compressed frame buffers do still exist. Mobile devices certainly do (for example Imagination/PowerVR have [PVRIC][1], and I believe ARM devices have their own scheme)&#xD;&#xA;These compression schemes are generally &quot;transparent&quot; to the programmer, but it does mean the GPU and display pipeline does less reading and writing of external memory.&#xD;&#xA;&lt;br/&gt;&lt;br/&gt;&#xD;&#xA;&#xD;&#xA;2) A display decompression system like PCG  (Programmable Character Generator) is effectively a precursor to (and effectively a subset of) some texture compression schemes, e.g. such as S3TC/DXT1. In that sense, therefore it still exists, but users don't typically write directly to them, but certainly take advantage of the bandwidth savings.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.imgtec.com/blog/reducing-bandwidth-pvric/" ContentLicense="CC BY-SA 4.0" />
  <row Id="33418" PostHistoryTypeId="5" PostId="11068" RevisionGUID="ed988c83-9322-476f-bf14-6b5202a13e50" CreationDate="2021-07-23T12:23:05.483" UserId="7952" Comment="added mach banding image and referenced comment" Text="RGB &quot;Colors&quot; contain chromaticity(color) and luminance(brightness), normal vectors contain direction and magnitude. &#xD;&#xA;&#xD;&#xA;Gouraud shading approximates color gradients.&#xD;&#xA;&#xD;&#xA;Phong shading approximates surface gradients.&#xD;&#xA;&#xD;&#xA;Imagine a large triangle with a small specular highlight at the center and all 3 vertex positions have normal vectors pointing away from the highlight so are only dimly lit.&#xD;&#xA;&#xD;&#xA;Interpolating the color will completely miss the highlight and only give values between those at the 3 vertex positions.&#xD;&#xA;&#xD;&#xA;Interpolating the normal vectors will force a change of direction in the vector so that the highlight is visible. &#xD;&#xA;&#xD;&#xA;Also, interpolation of normal vectors changes their length which can be recalculated in the fragment shader to help improve the approximation.  But there is very little we can do to help correct interpolated colors.&#xD;&#xA;&#xD;&#xA;Edit: Why interpolating between two vectors changes length.&#xD;&#xA;To interpolate vectors we use the formula $N_c = N_a\alpha+N_b(1-\alpha)$ where $N_a$ and $N_b$ are the two vectors being interpolated. This includes the sum of two vectors. Adding vectors can be thought of visually as placing them end to end, so the sum of two vectors results in a third vector with its own length resulting from the angle between the two vectors.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As simon f pointed out in comments my description of mach banding is poorly worded and misleading. See the comment below. Here is an image of the effect in action. &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bUp3b.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/n5Axi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33419" PostHistoryTypeId="2" PostId="11075" RevisionGUID="6895dc12-2ac4-4167-9ab6-7c839d228c9a" CreationDate="2021-07-23T14:50:24.913" UserId="7952" Text="FBX: while FBX is proprietary, it has both binary and text versions of the format, provides color support, and it provides an SDK which can make integration easier. [Here is a link.][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2020-0?AID=10282382&amp;PID=9069228&amp;SID=oc5A05L8E%2FcFrofF6SHThM2E3y3pj38LNvENP0hS0mILwHLVKKrvn%2B9SIG76o1vC&amp;mktvar002=afc_us_deeplink&amp;cjevent=fdb3a1a2ebc411eb816c01400a82b82d&amp;affname=9069228_10282382" ContentLicense="CC BY-SA 4.0" />
  <row Id="33420" PostHistoryTypeId="2" PostId="11076" RevisionGUID="f915126c-e5d1-4268-9f14-4d133b31c0db" CreationDate="2021-07-23T23:31:59.863" UserId="16927" Text="I'm using GLFW to create a full screen GL application. I'm running it on my Ubuntu 20.04 laptop that has a typical 1920:1080 display, at least that's the screen resolution reported under Settings-&gt;Displays. When I run the following code:&#xD;&#xA;&#xD;&#xA;    int monitor_x = 0;&#xD;&#xA;    int monitor_y = 0;&#xD;&#xA;    int monitor_width = 0;&#xD;&#xA;    int monitor_height = 0;&#xD;&#xA;&#xD;&#xA;    GLFWmonitor *monitor = glfwGetPrimaryMonitor();&#xD;&#xA;    glfwGetMonitorWorkarea(monitor, &amp;monitor_x, &amp;monitor_y, &amp;monitor_width, &amp;monitor_height);&#xD;&#xA;    printf(&quot;before monitor %d, %d, %d, %d\n&quot;, monitor_x, monitor_y, monitor_width, monitor_height);&#xD;&#xA;    window = glfwCreateWindow(1920, 1080, &quot;OpenGL&quot;, glfwGetPrimaryMonitor(), nullptr); // Fullscreen&#xD;&#xA;    glfwGetMonitorWorkarea(monitor, &amp;monitor_x, &amp;monitor_y, &amp;monitor_width, &amp;monitor_height);&#xD;&#xA;    printf(&quot;after monitor %d, %d, %d, %d\n&quot;, monitor_x, monitor_y, monitor_width, monitor_height);&#xD;&#xA;&#xD;&#xA;When I run the code, I get the following output on stdout:&#xD;&#xA;&#xD;&#xA;    before monitor 72, 27, 1848, 1053&#xD;&#xA;    after monitor 72, 27, 1848, 1053&#xD;&#xA;&#xD;&#xA;Also, it seems as if there's a horizontal band at the top and a vertical band at the right of the full screen that remains the background color, no matter what my application attempts to write to those areas.&#xD;&#xA;&#xD;&#xA;So 72 + 1848 = 1920 and 27 + 1053 = 1080, but it seems that the system is reserving these horizontal and vertical bands for something else that I assume has something to do with that 72 and 27.&#xD;&#xA;&#xD;&#xA;Is there some hint or some such thing that i need to specify in order to make the entire 1920 by 1080 of the screen available for rendering?&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33421" PostHistoryTypeId="1" PostId="11076" RevisionGUID="f915126c-e5d1-4268-9f14-4d133b31c0db" CreationDate="2021-07-23T23:31:59.863" UserId="16927" Text="why is reported screen size smaller than display size with GLFW full screen window" ContentLicense="CC BY-SA 4.0" />
  <row Id="33422" PostHistoryTypeId="3" PostId="11076" RevisionGUID="f915126c-e5d1-4268-9f14-4d133b31c0db" CreationDate="2021-07-23T23:31:59.863" UserId="16927" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33423" PostHistoryTypeId="2" PostId="11077" RevisionGUID="a84579e7-786f-4822-acf1-d193de81b841" CreationDate="2021-07-24T23:27:00.093" UserId="16300" Text="I'm not entirely sure about this case, but at least with some APIs I've worked with, there's a &quot;maximize window&quot; option. &#xD;&#xA;&#xD;&#xA;The bands that you're having is most likely because the window isn't maximized (isn't fullscreen) and so the computer makes no effort to align it with the edges of your screen.&#xD;&#xA;&#xD;&#xA;The reason why the window dimensions are funky are probably because, since the window isn't aligned to the edges of your screen, it has to get slimmed down a bit to still fit on your screen.&#xD;&#xA;&#xD;&#xA;Edit: Ah, found something: https://www.glfw.org/docs/3.3/window_guide.html&#xD;&#xA;&#xD;&#xA;GLFW_MAXIMIZED, set it to GLFW_TRUE and you'll be set :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33424" PostHistoryTypeId="2" PostId="11078" RevisionGUID="94adc50e-2471-4a1a-baac-cf8e5cb03ecd" CreationDate="2021-07-24T23:49:16.757" UserId="7952" Text="Passing interpolated values that don't produce any result(other then the original value) is a waste of bandwidth and yes, it should be passed directly to the fragment shader in those cases. Point it out to the author and they will (usually) thank you for their simple mistake, or point out how they are leading up to something, or point out some easily over looked bit of code. I personally have submitted several bug reports to authors of books and shaders which have all been well received. (and a couple of them pointed out how and why I was actually mistaken)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33425" PostHistoryTypeId="5" PostId="11076" RevisionGUID="23fd79da-6a08-4999-84ec-a2e828b83372" CreationDate="2021-07-25T01:06:39.950" UserId="16927" Comment="added 1333 characters in body" Text="I'm using GLFW to create a full screen GL application. I'm running it on my Ubuntu 20.04 laptop that has a typical 1920:1080 display, at least that's the screen resolution reported under Settings-&gt;Displays. When I run the following code:&#xD;&#xA;&#xD;&#xA;    int monitor_x = 0;&#xD;&#xA;    int monitor_y = 0;&#xD;&#xA;    int monitor_width = 0;&#xD;&#xA;    int monitor_height = 0;&#xD;&#xA;&#xD;&#xA;    GLFWmonitor *monitor = glfwGetPrimaryMonitor();&#xD;&#xA;    glfwGetMonitorWorkarea(monitor, &amp;monitor_x, &amp;monitor_y, &amp;monitor_width, &amp;monitor_height);&#xD;&#xA;    printf(&quot;before monitor %d, %d, %d, %d\n&quot;, monitor_x, monitor_y, monitor_width, monitor_height);&#xD;&#xA;    window = glfwCreateWindow(1920, 1080, &quot;OpenGL&quot;, glfwGetPrimaryMonitor(), nullptr); // Fullscreen&#xD;&#xA;    glfwGetMonitorWorkarea(monitor, &amp;monitor_x, &amp;monitor_y, &amp;monitor_width, &amp;monitor_height);&#xD;&#xA;    printf(&quot;after monitor %d, %d, %d, %d\n&quot;, monitor_x, monitor_y, monitor_width, monitor_height);&#xD;&#xA;&#xD;&#xA;When I run the code, I get the following output on stdout:&#xD;&#xA;&#xD;&#xA;    before monitor 72, 27, 1848, 1053&#xD;&#xA;    after monitor 72, 27, 1848, 1053&#xD;&#xA;&#xD;&#xA;Also, it seems as if there's a horizontal band at the top and a vertical band at the right of the full screen that remains the background color, no matter what my application attempts to write to those areas.&#xD;&#xA;&#xD;&#xA;So 72 + 1848 = 1920 and 27 + 1053 = 1080, but it seems that the system is reserving these horizontal and vertical bands for something else that I assume has something to do with that 72 and 27.&#xD;&#xA;&#xD;&#xA;Is there some hint or some such thing that i need to specify in order to make the entire 1920 by 1080 of the screen available for rendering?&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;=======================================================&#xD;&#xA;&#xD;&#xA;update:&#xD;&#xA;&#xD;&#xA;So far I've tried this (including your suggestion, EthanKim8683, and some from others).&#xD;&#xA;&#xD;&#xA;	GLFWmonitor *monitor = glfwGetPrimaryMonitor();&#xD;&#xA;	vid_mode = glfwGetVideoMode(monitor);&#xD;&#xA;	printf(&quot;mode.width %d, mode.height %d\n&quot;, vid_mode-&gt;width, vid_mode-&gt;height);&#xD;&#xA;	screen_x = vid_mode-&gt;width;&#xD;&#xA;	screen_y = vid_mode-&gt;height;&#xD;&#xA;	// screen_x = 640; screen_y = 480;&#xD;&#xA;	// screen_x = 1600; screen_y = 900;&#xD;&#xA;	glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);&#xD;&#xA;	glfwWindowHint(GLFW_GREEN_BITS, vid_mode-&gt;greenBits);&#xD;&#xA;	glfwWindowHint(GLFW_BLUE_BITS, vid_mode-&gt;blueBits);&#xD;&#xA;	glfwWindowHint(GLFW_REFRESH_RATE, vid_mode-&gt;refreshRate);&#xD;&#xA;	glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);&#xD;&#xA;	window = glfwCreateWindow(screen_x, screen_y, window_title, monitor, nullptr); // Fullscreen&#xD;&#xA;	glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);&#xD;&#xA;	glfwSetWindowSize(window, screen_x, screen_y);&#xD;&#xA;	glfwSetWindowPos(window, 0, 0);&#xD;&#xA;	glfwShowWindow(window);&#xD;&#xA;&#xD;&#xA;The behavior is the same as reported before. There's these apparently inaccessible bands of screen real estate at the top and on the right side of the screen. But if I uncomment the line where I assign 1600 and 900 to screen_x and screen_y, the unaccessible bands disappear. The whole full screen shows the output of my application.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33427" PostHistoryTypeId="12" PostId="11077" RevisionGUID="55c0fdef-5aa4-48a4-9c7c-5cb77a04aeaa" CreationDate="2021-07-25T07:55:46.640" UserId="16300" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:16300,&quot;DisplayName&quot;:&quot;EthanKim8683&quot;}]}" />
  <row Id="33428" PostHistoryTypeId="13" PostId="11077" RevisionGUID="38787830-e7fb-48e7-9eaa-acafcd4af76a" CreationDate="2021-07-25T07:56:14.637" UserId="16300" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:16300,&quot;DisplayName&quot;:&quot;EthanKim8683&quot;}]}" />
  <row Id="33432" PostHistoryTypeId="5" PostId="11072" RevisionGUID="2b5f6fb9-2833-4eae-a328-a2408de1fa73" CreationDate="2021-07-25T23:28:29.003" UserId="7462" Comment="added 133 characters in body" Text="I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not entirely sure where they are coming from, as I am using nothing but linear operations to render this.&#xD;&#xA;&#xD;&#xA;This is how I generate a ray:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;    {&#xD;&#xA;        vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;        r.y /= aspect_ratio;&#xD;&#xA;    &#xD;&#xA;        return normalize(r);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And after that all I do is ray march until I am inside the volume.&#xD;&#xA;&#xD;&#xA;This is the full shader:&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;#extension GL_ARB_separate_shader_objects : enable&#xD;&#xA;#extension GL_EXT_scalar_block_layout : enable&#xD;&#xA;#extension GL_NV_compute_shader_derivatives : enable&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 8, local_size_y = 8) in;&#xD;&#xA;&#xD;&#xA;layout(binding = 0) uniform MVPOnlyUbo&#xD;&#xA;{&#xD;&#xA;    mat4 model;&#xD;&#xA;    mat4 view;&#xD;&#xA;    mat4 proj;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(binding = 1, rgba16f) uniform image2D output_image;&#xD;&#xA;&#xD;&#xA;layout(binding = 2) uniform RayTracingData&#xD;&#xA;{&#xD;&#xA;    uint display_width;&#xD;&#xA;    uint display_height;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(binding = 3) uniform sampler2D albedo;&#xD;&#xA;&#xD;&#xA;#include &lt;phong_lighting.glsl&gt;&#xD;&#xA;&#xD;&#xA;float SphereFunction(vec3 position)&#xD;&#xA;{&#xD;&#xA;    return sqrt(dot(position, position)) - 64;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;{&#xD;&#xA;    vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;    r.y /= aspect_ratio;&#xD;&#xA;&#xD;&#xA;    return normalize(r);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float SdRoundBox( vec3 p  )&#xD;&#xA;{&#xD;&#xA;    vec3 b = vec3(2, 2, 2);&#xD;&#xA;    float r = 0.5;&#xD;&#xA;    vec3 q = abs(p) - b;&#xD;&#xA;    return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 Gradient(vec3 point)&#xD;&#xA;{&#xD;&#xA;    const float epsilon = 0.0001;&#xD;&#xA;    const float dx =&#xD;&#xA;          SdBoxSphere(vec3(point.x + epsilon, point.y, point.z))&#xD;&#xA;        - SdBoxSphere(vec3(point.x - epsilon, point.y, point.z));&#xD;&#xA;&#xD;&#xA;    const float dy =&#xD;&#xA;          SdBoxSphere(vec3(point.x, point.y + epsilon, point.z))&#xD;&#xA;        - SdBoxSphere(vec3(point.x, point.y - epsilon, point.z));&#xD;&#xA;&#xD;&#xA;    const float dz =&#xD;&#xA;          SdBoxSphere(vec3(point.x, point.y, point.z  + epsilon))&#xD;&#xA;        - SdBoxSphere(vec3(point.x, point.y, point.z  - epsilon));&#xD;&#xA;&#xD;&#xA;    return vec3(dx, dy, dz);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 BiplanarMapping( sampler2D sam, in vec3 p, in vec3 n, in float k )&#xD;&#xA;{&#xD;&#xA;    // grab coord derivatives for texturing&#xD;&#xA;    vec3 dpdx = vec3(0.01);//dFdx(p);&#xD;&#xA;    vec3 dpdy = vec3(0.01);//dFdy(p);&#xD;&#xA;    n = abs(n);&#xD;&#xA;&#xD;&#xA;    // determine major axis (in x; yz are following axis)&#xD;&#xA;    ivec3 ma = (n.x&gt;n.y &amp;&amp; n.x&gt;n.z) ? ivec3(0,1,2) :&#xD;&#xA;               (n.y&gt;n.z)            ? ivec3(1,2,0) :&#xD;&#xA;                                      ivec3(2,0,1) ;&#xD;&#xA;    // determine minor axis (in x; yz are following axis)&#xD;&#xA;    ivec3 mi = (n.x&lt;n.y &amp;&amp; n.x&lt;n.z) ? ivec3(0,1,2) :&#xD;&#xA;               (n.y&lt;n.z)            ? ivec3(1,2,0) :&#xD;&#xA;                                      ivec3(2,0,1) ;&#xD;&#xA;    // determine median axis (in x;  yz are following axis)&#xD;&#xA;    ivec3 me = ivec3(3) - mi - ma;&#xD;&#xA;&#xD;&#xA;    // project+fetch&#xD;&#xA;    vec4 x = textureGrad( sam, vec2(   p[ma.y],   p[ma.z]),&#xD;&#xA;                               vec2(dpdx[ma.y],dpdx[ma.z]),&#xD;&#xA;                               vec2(dpdy[ma.y],dpdy[ma.z]) );&#xD;&#xA;    vec4 y = textureGrad( sam, vec2(   p[me.y],   p[me.z]),&#xD;&#xA;                               vec2(dpdx[me.y],dpdx[me.z]),&#xD;&#xA;                               vec2(dpdy[me.y],dpdy[me.z]) );&#xD;&#xA;&#xD;&#xA;    // blend factors&#xD;&#xA;    vec2 w = vec2(n[ma.x],n[me.x]);&#xD;&#xA;    // make local support&#xD;&#xA;    w = clamp( (w-0.5773)/(1.0-0.5773), 0.0, 1.0 );&#xD;&#xA;    // shape transition&#xD;&#xA;    w = pow( w, vec2(k/8.0) );&#xD;&#xA;    // blend and return&#xD;&#xA;    return (x*w.x + y*w.y) / (w.x + w.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    const float aspect_ratio = float(display_width) / float(display_height);&#xD;&#xA;    const float disp_x = gl_GlobalInvocationID.x;&#xD;&#xA;    const float disp_y = gl_GlobalInvocationID.y;&#xD;&#xA;&#xD;&#xA;    const float x = disp_x * 2 / display_width - 1;&#xD;&#xA;    const float y = disp_y * 2 / display_height - 1;&#xD;&#xA;&#xD;&#xA;    const vec3 r = (inverse(view) * vec4(GenerateRay(vec2(x, y), aspect_ratio, 45), 0)).xyz;&#xD;&#xA;    const vec3 cam_pos = (inverse(view) * vec4(0, 0, 0, 1)).xyz;&#xD;&#xA;&#xD;&#xA;    vec3 ray_pos = vec3(x, y, 0) + cam_pos;&#xD;&#xA;    vec4 x_color = vec4(0);&#xD;&#xA;&#xD;&#xA;    float last_distance = 0;&#xD;&#xA;    for(uint i = 0; i &lt; 100; i++)&#xD;&#xA;    {&#xD;&#xA;        float sphere_radius = SdRoundBoxray_pos);&#xD;&#xA;        ray_pos += r * sphere_radius;&#xD;&#xA;        last_distance = sphere_radius;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    const vec3 normal = normalize(Gradient(ray_pos));&#xD;&#xA;    vec3 albedo = BiplanarMapping( albedo, ray_pos, normal, 10 ).rgb;&#xD;&#xA;    float test = min(min(mod(ray_pos.x, 1.f), mod(ray_pos.y, 1.f)), mod(ray_pos.z, 1.f));&#xD;&#xA;    vec4 highlight = test &lt;= 0.01 ? vec4(1, 0, 0, 1) : vec4(0);&#xD;&#xA;&#xD;&#xA;    vec4 color = BlinnPhong(&#xD;&#xA;        ray_pos,&#xD;&#xA;        normal,&#xD;&#xA;        cam_pos,&#xD;&#xA;        albedo,&#xD;&#xA;        vec3(100),&#xD;&#xA;        normalize(vec3(1, 1, 1)) * 0.3,&#xD;&#xA;        1)&#xD;&#xA;        + highlight;&#xD;&#xA;&#xD;&#xA;    x_color = color * int(last_distance &lt; 0.01);&#xD;&#xA;&#xD;&#xA;    imageStore(&#xD;&#xA;        output_image,&#xD;&#xA;        ivec2(disp_x, disp_y),&#xD;&#xA;        x_color&#xD;&#xA;    );&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This image might make it more obvious:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TDJyE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVnkX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33433" PostHistoryTypeId="2" PostId="11080" RevisionGUID="3bba293c-d3c0-4123-946e-33d61c206702" CreationDate="2021-07-26T00:38:27.733" UserId="48" Text="First, to preface: the reason it's hard to find details about these hierarchical cluster culling systems because they are a still emerging field, at the very cutting edge of real-time rendering development. Only a handful of games/engines have successfully shipped something like this, and mostly not open source (UE5 being a recent exception). It is an area of very active development and research, so there are no standard algorithms; everyone is experimenting and doing it differently. That said, I'll try to give a picture of what this is all about and why people are excited about it. This is going to be kind of a brain dump, but I hope it's somewhat useful.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;First of all, why are mesh clusters important? Historically, real-time rendering engines have done things like frustum and occlusion culling, as well as LOD selection and draws, on an object-by-object basis. What an &quot;object&quot; is here, is determined by the engine but would often correspond to a single authored model from a 3D content creation app, or to a scene graph node, or to higher level game logic (e.g. an entity with its own behavior such as a character or vehicle). In other words, object boundaries are not primarily determined by rendering considerations, but by other things entirely.&#xD;&#xA;&#xD;&#xA;As games have increased in geometric complexity, the amount of vertices/triangles in an &quot;object&quot; (whatever that means in a given game) have tended to increase. For example, player characters in AAA games might easily have hundreds of thousands of triangles. And we can only make LOD or culling decisions at the object level. If any part of an object is visible, we have to draw the whole thing, which might not be very efficient. When we want to switch LODs, we have to switch it for the whole object at once, which tends to cause visible popping since there are generally only a few discrete LODs stored for any given mesh.&#xD;&#xA;&#xD;&#xA;Another effect of increasing geometric complexity is that triangles are typically denser on screen, covering ≲10 pixels each, and often down to just ~1 pixel each for very dense meshes such as AAA characters. Such dense geometry exacerbates various inefficiencies in GPU rasterizers, such that over-rendering (i.e. drawing more triangles than you need to) becomes a more significant performance problem than it was in the past. This is why Nanite uses a compute-based software rasterizer for extremely dense meshes (and falls back to regular hardware rasterization for larger triangles or tricky corner cases, such as triangles that cross the near plane).&#xD;&#xA;&#xD;&#xA;Mesh clusters, also known as meshlets, are a way to break down these object-sized meshes into more manageable pieces. The meshlets are a roughly fixed geometry size, such as 64–128 vertices, no matter how big the object they come from. Then we can make rendering decisions per meshlet instead of per object. At a minimum, we can cull per meshlet, which enables us to do things like only render the visible parts of a large object. With some more work we can also make LOD decisions per meshlet, so that we only render parts of an object at high detail that are close enough to need high detail, and farther away parts can be at a lower detail. This also gives us much more fine-grained LOD control; we can transition a mesh from one LOD to another a few meshlets at a time, rather than all at once, reducing the problem of visible pops. To do this we need a way of ensuring that we can have meshlets at different LODs without cracks between them, which is tricky to do; Nanite has a clever approach to this.&#xD;&#xA;&#xD;&#xA;Meshlets are also relevant for rendering using [mesh shaders](https://developer.nvidia.com/blog/introduction-turing-mesh-shaders/), which is a separate topic, although it dovetails well with meshlet-based culling/LOD.&#xD;&#xA;&#xD;&#xA;As far as algorithms for building meshlets go: there are lots of ways to do it, but generally you start a meshlet with an arbitrary triangle, then iteratively try to add other triangles that share as many vertices as possible with the triangles already in the meshlet. You might also incorporate some scoring for candidate triangles based on how much they increase the size of the bounding box (favoring smaller boxes) or how much their normals deviate from those already in the meshlet (favoring similar normals). Once you've got enough vertices/triangles to fill the meshlet, you mark them as used, and you start again with a new unmarked triangle. The [meshoptimizer](https://github.com/zeux/meshoptimizer#mesh-shading) library includes a meshlet building algorithm, if you want to take a look at it.&#xD;&#xA;&#xD;&#xA;Once you've grouped your triangles into meshlets, you might still have a lot of meshlets, so it can make sense to do the same thing again and group neighboring meshlets together into larger clusters, and so on again hierarchically, forming a tree. Nanite does something along these lines, but also builds simplified representations of each cluster (keeping the boundaries intact) in order to be able to switch LODs without cracks. See the &quot;Brief Analysis of Nanite&quot; article linked at the bottom for more details.&#xD;&#xA;&#xD;&#xA;For the SDF-based apps like Dreams and Claybook, I think their &quot;clusters&quot; are just 4×4×4 bricks of SDF, and larger clusters are higher mip levels of the SDF, so that's much simpler to deal with.&#xD;&#xA;&#xD;&#xA;For culling on the GPU: the basic idea is you run a compute shader over the list of meshlets (one thread per meshlet). It does the culling calculations (e.g. testing bounding box against frustum, testing normal cone against camera position to eliminate backfacing meshlets) and outputs the list of surviving meshlets into an append buffer. This list becomes the input to an indirect draw or indirect dispatch which renders the visible geometry. This is well-suited for the GPU because it's a massively parallel computation, and there can be a large number of meshlets in the scene.&#xD;&#xA;&#xD;&#xA;In the case of a tree of clusters, you start at the root and walk down the tree. At each node you can make the decision to accept the whole node for rasterization (and stop traversal), or cull the whole node, or else recurse to the children. In a compute shader this can be implemented by issuing separate indirect dispatches for each level of the tree, with each level outputting a list of nodes to be processed in the next level. However, Nanite takes a different approach to this with what appears to be a single compute dispatch that uses a ring buffer (maybe?) of nodes to process, and the shaders keep running and popping off nodes to process until the whole thing is done. Nanite also does LOD selection during this phase, as higher levels in the tree represent more simplified LODs, and it stops descending a part of the tree when it reaches a node with low enough LOD error to render it (or if it reaches parts of the tree that are not streamed in at the moment - in which case it can also log a request for that node in another append buffer, to be read back and processed by the CPU streaming code later).&#xD;&#xA;&#xD;&#xA;GPU occlusion culling is a pretty interesting algorithm, too. The basic idea is to use last frame's depth buffer as an approximate &quot;initial guess&quot; as to what surfaces are visible or occluded in the new frame, then fix up the errors (things initially marked as occluded that are actually visible) in a second pass. Alex Evans talked about this a bit in the HPG keynote you linked above. This doesn't actually require hierarchical cluster culling, but can be applied even for ordinary object-based culling on the GPU. Basically, while you're traversing your list/tree of meshlets to cull, if they pass the frustum and backfacing tests then you test their bounding box against the HiZ buffer (hierarchical representation of the last frame's Z-buffer - basically a mip chain that stores the min and max Z in each pixel). This is done using the last frame's camera and object transform for that node. If the bounding box is behind the HiZ buffer then that node is culled and traversal stops, but it also gets added to a separate list of occlusion-culled nodes to re-test later. You proceed to rendering all the nodes that passed this first culling pass, then build a new HiZ buffer from the current frame's depth buffer so far. Finally, you re-test all the occlusion-culled nodes against the new HiZ buffer, which lets you find all the ones that were mistakenly culled but are actually visible. Then you resume traversal etc as usual for those nodes, and draw them in a follow-up pass. This second pass usually contains a relatively small number of nodes, in areas where camera or object movement has created a &quot;disocclusion&quot; (a place where previously hidden geometry has been revealed). Finally, the HiZ buffer is updated again and goes forward to repeat the process in the next frame (as well as being potentially used for other purposes, like screen-space ray tracing for lighting).&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Further on Nanite specifically, here are some analyses made by third parties (not Epic-associated) looking at Nanite in RenderDoc and reading the source code:&#xD;&#xA;&#xD;&#xA;* [A Macro View of Nanite](http://www.elopezr.com/a-macro-view-of-nanite/)&#xD;&#xA;* [Brief Analysis of Nanite](https://www.notion.so/Brief-Analysis-of-Nanite-94be60f292434ba3ae62fa4bcf7d9379)&#xD;&#xA;&#xD;&#xA;Since UE5 is open-source, you can go and look at the code for Nanite if you want. You have to register with Epic to join their GitHub organization, but then you should be able to access the following links (deep linked to the Nanite source directories within the UE5 GitHub):&#xD;&#xA;&#xD;&#xA;* [Nanite data preprocessing](https://github.com/EpicGames/UnrealEngine/tree/ue5-main/Engine/Source/Developer/NaniteBuilder)&#xD;&#xA;* [Nanite CPU rendering code](https://github.com/EpicGames/UnrealEngine/tree/ue5-main/Engine/Source/Runtime/Renderer/Private/Nanite)&#xD;&#xA;* [Nanite shader code](https://github.com/EpicGames/UnrealEngine/tree/ue5-main/Engine/Shaders/Private/Nanite)&#xD;&#xA;&#xD;&#xA;Also, some of the Nanite (and Lumen) developers are scheduled to do talks at this summer's SIGGRAPH, where no doubt additional details and history will be discussed.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="33434" PostHistoryTypeId="2" PostId="11081" RevisionGUID="8e2e3e62-5b15-4eee-a0ce-190ebaae5867" CreationDate="2021-07-26T20:11:37.923" UserId="10783" Text="I believe I already know the answer to this question, but I want to make sure I'm understanding this correctly. Within a physically based rendering pipeline, you calculate your indirect lighting from an hdri image (which is transformed into an irradiance map in engine (from what I can tell so far)). &#xD;&#xA;&#xD;&#xA;Therefore if one had a scene which was outside for example and you were using some form of daytime sky hdri, but then you transitioned into a cave where there's very little or no light, you would then need a separate irradiance map for this location as well, correct? &#xD;&#xA;&#xD;&#xA;Or if you wanted to emulate complete darkness, use a solid black irradiance map (or simply a shader that uses black for what would have been the calculated value of the irradiance map) and have your direct lighting (point lights, area lights, etc) be your only source of light?&#xD;&#xA;&#xD;&#xA;Do I seem to be grasping the concept or am I missing something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33435" PostHistoryTypeId="1" PostId="11081" RevisionGUID="8e2e3e62-5b15-4eee-a0ce-190ebaae5867" CreationDate="2021-07-26T20:11:37.923" UserId="10783" Text="PBR pipeline with multiple HDR images?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33436" PostHistoryTypeId="3" PostId="11081" RevisionGUID="8e2e3e62-5b15-4eee-a0ce-190ebaae5867" CreationDate="2021-07-26T20:11:37.923" UserId="10783" Text="|physically-based|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33437" PostHistoryTypeId="5" PostId="11072" RevisionGUID="e0ca9096-67a5-4475-b70e-296c8d80dc4c" CreationDate="2021-07-26T21:14:13.453" UserId="7462" Comment="added 113 characters in body" Text="I have a pretty simple raytracer that is rendering some SDFs, but when my camera is close to the object I see curves:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not entirely sure where they are coming from, as I am using nothing but linear operations to render this.&#xD;&#xA;&#xD;&#xA;This is how I generate a ray:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;    {&#xD;&#xA;        vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;        r.y /= aspect_ratio;&#xD;&#xA;    &#xD;&#xA;        return normalize(r);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And after that all I do is ray march until I am inside the volume.&#xD;&#xA;&#xD;&#xA;This is the full shader:&#xD;&#xA;```&#xD;&#xA;#version 450&#xD;&#xA;#extension GL_ARB_separate_shader_objects : enable&#xD;&#xA;#extension GL_EXT_scalar_block_layout : enable&#xD;&#xA;#extension GL_NV_compute_shader_derivatives : enable&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 8, local_size_y = 8) in;&#xD;&#xA;&#xD;&#xA;layout(binding = 0) uniform MVPOnlyUbo&#xD;&#xA;{&#xD;&#xA;    mat4 model;&#xD;&#xA;    mat4 view;&#xD;&#xA;    mat4 proj;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(binding = 1, rgba16f) uniform image2D output_image;&#xD;&#xA;&#xD;&#xA;layout(binding = 2) uniform RayTracingData&#xD;&#xA;{&#xD;&#xA;    uint display_width;&#xD;&#xA;    uint display_height;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout(binding = 3) uniform sampler2D albedo;&#xD;&#xA;&#xD;&#xA;#include &lt;phong_lighting.glsl&gt;&#xD;&#xA;&#xD;&#xA;float SphereFunction(vec3 position)&#xD;&#xA;{&#xD;&#xA;    return sqrt(dot(position, position)) - 64;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 GenerateRay(vec2 screen_position, float aspect_ratio, float fov)&#xD;&#xA;{&#xD;&#xA;    vec3 r = vec3(screen_position, -1.f / tan(radians(fov)));&#xD;&#xA;    r.y /= aspect_ratio;&#xD;&#xA;&#xD;&#xA;    return normalize(r);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float SdRoundBox( vec3 p  )&#xD;&#xA;{&#xD;&#xA;    vec3 b = vec3(2, 2, 2);&#xD;&#xA;    float r = 0.5;&#xD;&#xA;    vec3 q = abs(p) - b;&#xD;&#xA;    return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 Gradient(vec3 point)&#xD;&#xA;{&#xD;&#xA;    const float epsilon = 0.0001;&#xD;&#xA;    const float dx =&#xD;&#xA;          SdBoxSphere(vec3(point.x + epsilon, point.y, point.z))&#xD;&#xA;        - SdBoxSphere(vec3(point.x - epsilon, point.y, point.z));&#xD;&#xA;&#xD;&#xA;    const float dy =&#xD;&#xA;          SdBoxSphere(vec3(point.x, point.y + epsilon, point.z))&#xD;&#xA;        - SdBoxSphere(vec3(point.x, point.y - epsilon, point.z));&#xD;&#xA;&#xD;&#xA;    const float dz =&#xD;&#xA;          SdBoxSphere(vec3(point.x, point.y, point.z  + epsilon))&#xD;&#xA;        - SdBoxSphere(vec3(point.x, point.y, point.z  - epsilon));&#xD;&#xA;&#xD;&#xA;    return vec3(dx, dy, dz);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 BiplanarMapping( sampler2D sam, in vec3 p, in vec3 n, in float k )&#xD;&#xA;{&#xD;&#xA;    // grab coord derivatives for texturing&#xD;&#xA;    vec3 dpdx = vec3(0.01);//dFdx(p);&#xD;&#xA;    vec3 dpdy = vec3(0.01);//dFdy(p);&#xD;&#xA;    n = abs(n);&#xD;&#xA;&#xD;&#xA;    // determine major axis (in x; yz are following axis)&#xD;&#xA;    ivec3 ma = (n.x&gt;n.y &amp;&amp; n.x&gt;n.z) ? ivec3(0,1,2) :&#xD;&#xA;               (n.y&gt;n.z)            ? ivec3(1,2,0) :&#xD;&#xA;                                      ivec3(2,0,1) ;&#xD;&#xA;    // determine minor axis (in x; yz are following axis)&#xD;&#xA;    ivec3 mi = (n.x&lt;n.y &amp;&amp; n.x&lt;n.z) ? ivec3(0,1,2) :&#xD;&#xA;               (n.y&lt;n.z)            ? ivec3(1,2,0) :&#xD;&#xA;                                      ivec3(2,0,1) ;&#xD;&#xA;    // determine median axis (in x;  yz are following axis)&#xD;&#xA;    ivec3 me = ivec3(3) - mi - ma;&#xD;&#xA;&#xD;&#xA;    // project+fetch&#xD;&#xA;    vec4 x = textureGrad( sam, vec2(   p[ma.y],   p[ma.z]),&#xD;&#xA;                               vec2(dpdx[ma.y],dpdx[ma.z]),&#xD;&#xA;                               vec2(dpdy[ma.y],dpdy[ma.z]) );&#xD;&#xA;    vec4 y = textureGrad( sam, vec2(   p[me.y],   p[me.z]),&#xD;&#xA;                               vec2(dpdx[me.y],dpdx[me.z]),&#xD;&#xA;                               vec2(dpdy[me.y],dpdy[me.z]) );&#xD;&#xA;&#xD;&#xA;    // blend factors&#xD;&#xA;    vec2 w = vec2(n[ma.x],n[me.x]);&#xD;&#xA;    // make local support&#xD;&#xA;    w = clamp( (w-0.5773)/(1.0-0.5773), 0.0, 1.0 );&#xD;&#xA;    // shape transition&#xD;&#xA;    w = pow( w, vec2(k/8.0) );&#xD;&#xA;    // blend and return&#xD;&#xA;    return (x*w.x + y*w.y) / (w.x + w.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    const float aspect_ratio = float(display_width) / float(display_height);&#xD;&#xA;    const float disp_x = gl_GlobalInvocationID.x;&#xD;&#xA;    const float disp_y = gl_GlobalInvocationID.y;&#xD;&#xA;&#xD;&#xA;    const float x = disp_x * 2 / display_width - 1;&#xD;&#xA;    const float y = disp_y * 2 / display_height - 1;&#xD;&#xA;&#xD;&#xA;    const vec3 r = (inverse(view) * vec4(GenerateRay(vec2(x, y), aspect_ratio, 45), 0)).xyz;&#xD;&#xA;    const vec3 cam_pos = (inverse(view) * vec4(0, 0, 0, 1)).xyz;&#xD;&#xA;&#xD;&#xA;    vec3 ray_pos = vec3(x, y, 0) + cam_pos;&#xD;&#xA;    vec4 x_color = vec4(0);&#xD;&#xA;&#xD;&#xA;    float last_distance = 0;&#xD;&#xA;    for(uint i = 0; i &lt; 100; i++)&#xD;&#xA;    {&#xD;&#xA;        float sphere_radius = SdRoundBoxray_pos);&#xD;&#xA;        ray_pos += r * sphere_radius;&#xD;&#xA;        last_distance = sphere_radius;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    const vec3 normal = normalize(Gradient(ray_pos));&#xD;&#xA;    vec3 albedo = BiplanarMapping( albedo, ray_pos, normal, 10 ).rgb;&#xD;&#xA;    float test = min(min(mod(ray_pos.x, 1.f), mod(ray_pos.y, 1.f)), mod(ray_pos.z, 1.f));&#xD;&#xA;    vec4 highlight = test &lt;= 0.01 ? vec4(1, 0, 0, 1) : vec4(0);&#xD;&#xA;&#xD;&#xA;    vec4 color = BlinnPhong(&#xD;&#xA;        ray_pos,&#xD;&#xA;        normal,&#xD;&#xA;        cam_pos,&#xD;&#xA;        albedo,&#xD;&#xA;        vec3(100),&#xD;&#xA;        normalize(vec3(1, 1, 1)) * 0.3,&#xD;&#xA;        1)&#xD;&#xA;        + highlight;&#xD;&#xA;&#xD;&#xA;    x_color = color * int(last_distance &lt; 0.01);&#xD;&#xA;&#xD;&#xA;    imageStore(&#xD;&#xA;        output_image,&#xD;&#xA;        ivec2(disp_x, disp_y),&#xD;&#xA;        x_color&#xD;&#xA;    );&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This image might make it more obvious:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Same scene raymarched:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TDJyE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YVnkX.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/q3pqo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33438" PostHistoryTypeId="2" PostId="11082" RevisionGUID="2d394805-57a3-431a-a112-91581dcdf4b2" CreationDate="2021-07-26T21:37:50.770" UserId="13456" Text="The answer to your first question is yes. &#xD;&#xA;&#xD;&#xA;Your second question is a little vague. Yes, they would be the only source of light, but them being the only source does not solve the use case for the irradiance map. Irradiance map is needed for accounting ambient light. In a cave setting, ray would bounce around and create ambient light. Thus you might still need the irradiance light to stimulate the effect of ray bouncing around creating the ambient light.&#xD;&#xA;I would say anytime the ambient light has a significant role for the scene, irradiance map would be something good to have. " ContentLicense="CC BY-SA 4.0" />
  <row Id="33439" PostHistoryTypeId="2" PostId="11083" RevisionGUID="84cda235-0b8a-4fc9-99f7-28758bbc5b34" CreationDate="2021-07-26T22:51:14.353" UserId="16927" Text="I've written a program that uses OpenGL and GLFW to display some simple geometric shapes. I'm now trying to add some transform feedback capability to it and I find that as soon as I do so, the program stops displaying anything. So in pursuit of tracking down the problem I've started with a simple tutorial from the open.gl website that displays a red triangle (see https://open.gl/drawing for the original code) and then started adding the necessary transform feedback gl calls in order to reproduce the problem. The program is below:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &lt;chrono&gt;&#xD;&#xA;    &#xD;&#xA;    #define GL_GLEXT_PROTOTYPES&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    // #include &lt;GL/glu.h&gt;&#xD;&#xA;    #include &lt;thread&gt;&#xD;&#xA;    &#xD;&#xA;    #define gl_error_check do { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, &quot;gl error %d at %s:%d\n&quot;, err, __FILE__, __LINE__); } } while (0)&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	float vertices[] = {&#xD;&#xA;    		0.0f,  0.5f, // Vertex 1 (X, Y)&#xD;&#xA;    		0.5f, -0.5f, // Vertex 2 (X, Y)&#xD;&#xA;    		-0.5f, -0.5f  // Vertex 3 (X, Y)&#xD;&#xA;    	};&#xD;&#xA;    &#xD;&#xA;    	GLuint vbo;&#xD;&#xA;    &#xD;&#xA;    	const char* vertexSource = R&quot;glsl(&#xD;&#xA;    		#version 150 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 position;&#xD;&#xA;    		// out float outValue;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char* fragmentSource = R&quot;glsl(&#xD;&#xA;    		#version 150 core&#xD;&#xA;    &#xD;&#xA;    		uniform vec3 triangleColor;&#xD;&#xA;    &#xD;&#xA;    		out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outColor = vec4(triangleColor, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	glfwInit();&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    &#xD;&#xA;    	GLFWwindow* window = glfwCreateWindow(800, 600, &quot;OpenGL&quot;, nullptr, nullptr); // Windowed&#xD;&#xA;    &#xD;&#xA;    	glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;    	GLuint vao;&#xD;&#xA;    	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    	glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;vbo); // Generate 1 buffer&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    	glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);&#xD;&#xA;    	glCompileShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	GLint status;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;vertex shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    	glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);&#xD;&#xA;    	glCompileShader(fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;fragment shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint shaderProgram = glCreateProgram();&#xD;&#xA;    	glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;    	glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;);   // not necessary&#xD;&#xA;    &#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(shaderProgram);&#xD;&#xA;    	glUseProgram(shaderProgram);&#xD;&#xA;    &#xD;&#xA;    	GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;);&#xD;&#xA;    	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;    	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    &#xD;&#xA;    	GLint uniColor = glGetUniformLocation(shaderProgram, &quot;triangleColor&quot;);&#xD;&#xA;    	glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };&#xD;&#xA;    &#xD;&#xA;    	// shader output buffer&#xD;&#xA;    	GLuint tbo;&#xD;&#xA;    	glGenBuffers(1, &amp;tbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, tbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(data), nullptr, GL_STATIC_READ);&#xD;&#xA;    &#xD;&#xA;    	std::cout &lt;&lt; &quot;Init complete&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    	while(!glfwWindowShouldClose(window))&#xD;&#xA;    	{&#xD;&#xA;    		if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;    			glfwSetWindowShouldClose(window, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    		// Clear the screen to black&#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;    		glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    		// Draw a triangle from the 3 vertices&#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;    &#xD;&#xA;    		glfwSwapBuffers(window);&#xD;&#xA;    		glfwPollEvents();&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// std::this_thread::sleep_for(std::chrono::seconds(10));&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(shaderProgram);&#xD;&#xA;    	glDeleteShader(fragmentShader);&#xD;&#xA;    	glDeleteShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(1, &amp;tbo);&#xD;&#xA;    	glDeleteBuffers(1, &amp;vbo);&#xD;&#xA;    &#xD;&#xA;    	glDeleteVertexArrays(1, &amp;vao);&#xD;&#xA;    &#xD;&#xA;    	glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I compile and run the program as shown above, it displays a red triangle, like so:&#xD;&#xA;&#xD;&#xA;[![working triangle][1]][1]&#xD;&#xA;&#xD;&#xA;So far so good. In the code above, I've commented and ifdef'ed out a couple of what appear to be problematic lines. In the vertex shader, there's the declaration of the output variable outValue:&#xD;&#xA;&#xD;&#xA;		// out float outValue;&#xD;&#xA;&#xD;&#xA;and then in the CPU code:&#xD;&#xA;&#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;If I uncomment the declaration of outValue and change the 0 in the #if to a 1 so that the call to glTransformFeedbackVaryings() is compiled, the resulting executable displays only an empty window, no triangle.&#xD;&#xA;&#xD;&#xA;So it seems that the call to glTransformFeedbackVaryings() is somehow breaking the rasterization process, even though so far the shader doesn't yet write anything to outValue nor does the CPU code try to read the feedback buffer.&#xD;&#xA;&#xD;&#xA;Thus my question.&#xD;&#xA;&#xD;&#xA;Is it a requirement that when a GL program is using transform feedback that it cannot actually render pixels to the screen?&#xD;&#xA;&#xD;&#xA;Assuming this is not the case, is there something I'm missing?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNuZX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33440" PostHistoryTypeId="1" PostId="11083" RevisionGUID="84cda235-0b8a-4fc9-99f7-28758bbc5b34" CreationDate="2021-07-26T22:51:14.353" UserId="16927" Text="is doing transform feedback while rendering vertices not possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33441" PostHistoryTypeId="3" PostId="11083" RevisionGUID="84cda235-0b8a-4fc9-99f7-28758bbc5b34" CreationDate="2021-07-26T22:51:14.353" UserId="16927" Text="|opengl|transform-feedback|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33442" PostHistoryTypeId="5" PostId="11083" RevisionGUID="063050b7-17ca-4543-ae8c-b349332beb9c" CreationDate="2021-07-26T23:01:54.813" UserId="16927" Comment="added 188 characters in body" Text="I've written a program that uses OpenGL and GLFW to display some simple geometric shapes. I'm now trying to add some transform feedback capability to it and I find that as soon as I do so, the program stops displaying anything. So in pursuit of tracking down the problem I've started with a simple tutorial from the open.gl website that displays a red triangle (see https://open.gl/drawing for the original code) and then started adding the necessary transform feedback gl calls in order to reproduce the problem. The program is below:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &lt;chrono&gt;&#xD;&#xA;    &#xD;&#xA;    #define GL_GLEXT_PROTOTYPES&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    // #include &lt;GL/glu.h&gt;&#xD;&#xA;    #include &lt;thread&gt;&#xD;&#xA;    &#xD;&#xA;    #define gl_error_check do { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, &quot;gl error %d at %s:%d\n&quot;, err, __FILE__, __LINE__); } } while (0)&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	float vertices[] = {&#xD;&#xA;    		0.0f,  0.5f, // Vertex 1 (X, Y)&#xD;&#xA;    		0.5f, -0.5f, // Vertex 2 (X, Y)&#xD;&#xA;    		-0.5f, -0.5f  // Vertex 3 (X, Y)&#xD;&#xA;    	};&#xD;&#xA;    &#xD;&#xA;    	GLuint vbo;&#xD;&#xA;    &#xD;&#xA;    	const char* vertexSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 position;&#xD;&#xA;    		// out float outValue;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char* fragmentSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		uniform vec3 triangleColor;&#xD;&#xA;    &#xD;&#xA;    		out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outColor = vec4(triangleColor, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	glfwInit();&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    &#xD;&#xA;    	GLFWwindow* window = glfwCreateWindow(800, 600, &quot;OpenGL&quot;, nullptr, nullptr); // Windowed&#xD;&#xA;    &#xD;&#xA;    	glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;    	GLuint vao;&#xD;&#xA;    	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    	glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;vbo); // Generate 1 buffer&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    	glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);&#xD;&#xA;    	glCompileShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	GLint status;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;vertex shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    	glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);&#xD;&#xA;    	glCompileShader(fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;fragment shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint shaderProgram = glCreateProgram();&#xD;&#xA;    	glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;    	glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;);   // not necessary&#xD;&#xA;    &#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(shaderProgram);&#xD;&#xA;    	glUseProgram(shaderProgram);&#xD;&#xA;    &#xD;&#xA;    	GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;);&#xD;&#xA;    	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;    	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    &#xD;&#xA;    	GLint uniColor = glGetUniformLocation(shaderProgram, &quot;triangleColor&quot;);&#xD;&#xA;    	glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };&#xD;&#xA;    &#xD;&#xA;    	// shader output buffer&#xD;&#xA;    	GLuint tbo;&#xD;&#xA;    	glGenBuffers(1, &amp;tbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, tbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(data), nullptr, GL_STATIC_READ);&#xD;&#xA;    &#xD;&#xA;    	std::cout &lt;&lt; &quot;Init complete&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    	while(!glfwWindowShouldClose(window))&#xD;&#xA;    	{&#xD;&#xA;    		if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;    			glfwSetWindowShouldClose(window, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    		// Clear the screen to black&#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;    		glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    		// Draw a triangle from the 3 vertices&#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;    &#xD;&#xA;    		glfwSwapBuffers(window);&#xD;&#xA;    		glfwPollEvents();&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// std::this_thread::sleep_for(std::chrono::seconds(10));&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(shaderProgram);&#xD;&#xA;    	glDeleteShader(fragmentShader);&#xD;&#xA;    	glDeleteShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(1, &amp;tbo);&#xD;&#xA;    	glDeleteBuffers(1, &amp;vbo);&#xD;&#xA;    &#xD;&#xA;    	glDeleteVertexArrays(1, &amp;vao);&#xD;&#xA;    &#xD;&#xA;    	glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I compile and run the program as shown above, it displays a red triangle, like so:&#xD;&#xA;&#xD;&#xA;[![working triangle][1]][1]&#xD;&#xA;&#xD;&#xA;So far so good. In the code above, I've commented and ifdef'ed out a couple of what appear to be problematic lines. In the vertex shader, there's the declaration of the output variable outValue:&#xD;&#xA;&#xD;&#xA;		// out float outValue;&#xD;&#xA;&#xD;&#xA;and then in the CPU code:&#xD;&#xA;&#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;If I uncomment the declaration of outValue and change the 0 in the #if to a 1 so that the call to glTransformFeedbackVaryings() is compiled, the resulting executable displays only an empty window, no triangle.&#xD;&#xA;&#xD;&#xA;So it seems that the call to glTransformFeedbackVaryings() is somehow breaking the rasterization process, even though so far the shader doesn't yet write anything to outValue nor does the CPU code try to read the feedback buffer.&#xD;&#xA;&#xD;&#xA;Thus my question.&#xD;&#xA;&#xD;&#xA;Is it a requirement that when a GL program is using transform feedback that it cannot actually render pixels to the screen?&#xD;&#xA;&#xD;&#xA;Assuming this is not the case, is there something I'm missing?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;Edit: updated the version declarations in the shaders from 150 to 330. I still get a blank screen with the problematic lines enabled.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNuZX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33443" PostHistoryTypeId="5" PostId="11083" RevisionGUID="e27b6362-e135-4dd3-83b9-24ae016fcd80" CreationDate="2021-07-26T23:07:41.447" UserId="16927" Comment="added 188 characters in body" Text="I've written a program that uses OpenGL and GLFW to display some simple geometric shapes. I'm now trying to add some transform feedback capability to it and I find that as soon as I do so, the program stops displaying anything. So in pursuit of tracking down the problem I've started with a simple tutorial from the open.gl website that displays a red triangle (see https://open.gl/drawing for the original code) and then started adding the necessary transform feedback gl calls in order to reproduce the problem. The program is below:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &lt;chrono&gt;&#xD;&#xA;    &#xD;&#xA;    #define GL_GLEXT_PROTOTYPES&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    // #include &lt;GL/glu.h&gt;&#xD;&#xA;    #include &lt;thread&gt;&#xD;&#xA;    &#xD;&#xA;    #define gl_error_check do { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, &quot;gl error %d at %s:%d\n&quot;, err, __FILE__, __LINE__); } } while (0)&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	float vertices[] = {&#xD;&#xA;    		0.0f,  0.5f, // Vertex 1 (X, Y)&#xD;&#xA;    		0.5f, -0.5f, // Vertex 2 (X, Y)&#xD;&#xA;    		-0.5f, -0.5f  // Vertex 3 (X, Y)&#xD;&#xA;    	};&#xD;&#xA;    &#xD;&#xA;    	GLuint vbo;&#xD;&#xA;    &#xD;&#xA;    	const char* vertexSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 position;&#xD;&#xA;    		// out float outValue;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char* fragmentSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		uniform vec3 triangleColor;&#xD;&#xA;    &#xD;&#xA;    		out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outColor = vec4(triangleColor, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	glfwInit();&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    &#xD;&#xA;    	GLFWwindow* window = glfwCreateWindow(800, 600, &quot;OpenGL&quot;, nullptr, nullptr); // Windowed&#xD;&#xA;    &#xD;&#xA;    	glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;    	GLuint vao;&#xD;&#xA;    	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    	glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;vbo); // Generate 1 buffer&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    	glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);&#xD;&#xA;    	glCompileShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	GLint status;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;vertex shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    	glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);&#xD;&#xA;    	glCompileShader(fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;fragment shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint shaderProgram = glCreateProgram();&#xD;&#xA;    	glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;    	glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;);   // not necessary&#xD;&#xA;    &#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(shaderProgram);&#xD;&#xA;    	glUseProgram(shaderProgram);&#xD;&#xA;    &#xD;&#xA;    	GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;);&#xD;&#xA;    	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;    	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    &#xD;&#xA;    	GLint uniColor = glGetUniformLocation(shaderProgram, &quot;triangleColor&quot;);&#xD;&#xA;    	glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };&#xD;&#xA;    &#xD;&#xA;    	// shader output buffer&#xD;&#xA;    	GLuint tbo;&#xD;&#xA;    	glGenBuffers(1, &amp;tbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, tbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(data), nullptr, GL_STATIC_READ);&#xD;&#xA;    &#xD;&#xA;    	std::cout &lt;&lt; &quot;Init complete&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    	while(!glfwWindowShouldClose(window))&#xD;&#xA;    	{&#xD;&#xA;    		if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;    			glfwSetWindowShouldClose(window, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    		// Clear the screen to black&#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;    		glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    		// Draw a triangle from the 3 vertices&#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;    &#xD;&#xA;    		glfwSwapBuffers(window);&#xD;&#xA;    		glfwPollEvents();&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// std::this_thread::sleep_for(std::chrono::seconds(10));&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(shaderProgram);&#xD;&#xA;    	glDeleteShader(fragmentShader);&#xD;&#xA;    	glDeleteShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(1, &amp;tbo);&#xD;&#xA;    	glDeleteBuffers(1, &amp;vbo);&#xD;&#xA;    &#xD;&#xA;    	glDeleteVertexArrays(1, &amp;vao);&#xD;&#xA;    &#xD;&#xA;    	glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I compile and run the program as shown above, it displays a red triangle, like so:&#xD;&#xA;&#xD;&#xA;[![working triangle][1]][1]&#xD;&#xA;&#xD;&#xA;So far so good. In the code above, I've commented and ifdef'ed out a couple of what appear to be problematic lines. In the vertex shader, there's the declaration of the output variable outValue:&#xD;&#xA;&#xD;&#xA;		// out float outValue;&#xD;&#xA;&#xD;&#xA;and then in the CPU code:&#xD;&#xA;&#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;If I uncomment the declaration of outValue and change the 0 in the #if to a 1 so that the call to glTransformFeedbackVaryings() is compiled, the resulting executable displays only an empty window, no triangle.&#xD;&#xA;&#xD;&#xA;So it seems that the call to glTransformFeedbackVaryings() is somehow breaking the rasterization process, even though so far the shader doesn't yet write anything to outValue nor does the CPU code try to read the feedback buffer.&#xD;&#xA;&#xD;&#xA;Thus my question.&#xD;&#xA;&#xD;&#xA;Is it a requirement that when a GL program is using transform feedback that it cannot actually render pixels to the screen?&#xD;&#xA;&#xD;&#xA;Assuming this is not the case, is there something I'm missing?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;Edit: updated the version declarations in the shaders from 150 to 330. I still get a blank screen with the problematic lines enabled.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNuZX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33444" PostHistoryTypeId="5" PostId="11083" RevisionGUID="e385e0b8-5873-4791-badd-6d97fa64f632" CreationDate="2021-07-26T23:25:35.210" UserId="16927" Comment="edited body" Text="I've written a program that uses OpenGL and GLFW to display some simple geometric shapes. I'm now trying to add some transform feedback capability to it and I find that as soon as I do so, the program stops displaying anything. So in pursuit of tracking down the problem I've started with a simple tutorial from the open.gl website that displays a red triangle (see https://open.gl/drawing for the original code) and then started adding the necessary transform feedback gl calls in order to reproduce the problem. The program is below:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &lt;chrono&gt;&#xD;&#xA;    &#xD;&#xA;    #define GL_GLEXT_PROTOTYPES&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    // #include &lt;GL/glu.h&gt;&#xD;&#xA;    #include &lt;thread&gt;&#xD;&#xA;    &#xD;&#xA;    #define gl_error_check do { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, &quot;gl error %d at %s:%d\n&quot;, err, __FILE__, __LINE__); } } while (0)&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	float vertices[] = {&#xD;&#xA;    		0.0f,  0.5f, // Vertex 1 (X, Y)&#xD;&#xA;    		0.5f, -0.5f, // Vertex 2 (X, Y)&#xD;&#xA;    		-0.5f, -0.5f  // Vertex 3 (X, Y)&#xD;&#xA;    	};&#xD;&#xA;    &#xD;&#xA;    	GLuint vbo;&#xD;&#xA;    &#xD;&#xA;    	const char* vertexSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 position;&#xD;&#xA;    		// out float outValue;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char* fragmentSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		uniform vec3 triangleColor;&#xD;&#xA;    &#xD;&#xA;    		out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outColor = vec4(triangleColor, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	glfwInit();&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    &#xD;&#xA;    	GLFWwindow* window = glfwCreateWindow(800, 600, &quot;OpenGL&quot;, nullptr, nullptr); // Windowed&#xD;&#xA;    &#xD;&#xA;    	glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;    	GLuint vao;&#xD;&#xA;    	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    	glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;vbo); // Generate 1 buffer&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    	glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);&#xD;&#xA;    	glCompileShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	GLint status;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;vertex shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    	glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);&#xD;&#xA;    	glCompileShader(fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;fragment shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint shaderProgram = glCreateProgram();&#xD;&#xA;    	glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;    	glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;);   // not necessary&#xD;&#xA;    &#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(shaderProgram);&#xD;&#xA;    	glUseProgram(shaderProgram);&#xD;&#xA;    &#xD;&#xA;    	GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;);&#xD;&#xA;    	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;    	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    &#xD;&#xA;    	GLint uniColor = glGetUniformLocation(shaderProgram, &quot;triangleColor&quot;);&#xD;&#xA;    	glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };&#xD;&#xA;    &#xD;&#xA;    	// shader output buffer&#xD;&#xA;    	GLuint tbo;&#xD;&#xA;    	glGenBuffers(1, &amp;tbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, tbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(data), nullptr, GL_STATIC_READ);&#xD;&#xA;    &#xD;&#xA;    	std::cout &lt;&lt; &quot;Init complete&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    	while(!glfwWindowShouldClose(window))&#xD;&#xA;    	{&#xD;&#xA;    		if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;    			glfwSetWindowShouldClose(window, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    		// Clear the screen to black&#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;    		glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    		// Draw a triangle from the 3 vertices&#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;    &#xD;&#xA;    		glfwSwapBuffers(window);&#xD;&#xA;    		glfwPollEvents();&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// std::this_thread::sleep_for(std::chrono::seconds(10));&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(shaderProgram);&#xD;&#xA;    	glDeleteShader(fragmentShader);&#xD;&#xA;    	glDeleteShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(1, &amp;tbo);&#xD;&#xA;    	glDeleteBuffers(1, &amp;vbo);&#xD;&#xA;    &#xD;&#xA;    	glDeleteVertexArrays(1, &amp;vao);&#xD;&#xA;    &#xD;&#xA;    	glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I compile and run the program as shown above, it displays a red triangle, like so:&#xD;&#xA;&#xD;&#xA;[![working triangle][1]][1]&#xD;&#xA;&#xD;&#xA;So far so good. In the code above, I've commented and ifdef'ed out a couple of what appear to be problematic lines. In the vertex shader, there's the declaration of the output variable outValue:&#xD;&#xA;&#xD;&#xA;		// out float outValue;&#xD;&#xA;&#xD;&#xA;and then in the CPU code:&#xD;&#xA;&#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;If I uncomment the declaration of outValue and change the 0 in the #if to a 1 so that the call to glTransformFeedbackVaryings() is compiled, the resulting executable displays only an empty window, no triangle.&#xD;&#xA;&#xD;&#xA;So it seems that the call to glTransformFeedbackVaryings() is somehow breaking the rasterization process, even though so far the shader doesn't yet write anything to outValue nor does the CPU code try to read the feedback buffer.&#xD;&#xA;&#xD;&#xA;Thus my question.&#xD;&#xA;&#xD;&#xA;Is it a requirement that when a GL program is using transform feedback that it cannot actually render pixels to the screen?&#xD;&#xA;&#xD;&#xA;Assuming this is not the case, is there something I'm missing?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;Edit: updated the version declarations in the shaders from 150 to 330. I still get a blank window with the problematic lines enabled.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNuZX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33445" PostHistoryTypeId="5" PostId="11083" RevisionGUID="9ee6848a-1a16-487b-a709-20485dda437c" CreationDate="2021-07-27T00:58:23.060" UserId="16927" Comment="added 2006 characters in body" Text="I've written a program that uses OpenGL and GLFW to display some simple geometric shapes. I'm now trying to add some transform feedback capability to it and I find that as soon as I do so, the program stops displaying anything. So in pursuit of tracking down the problem I've started with a simple tutorial from the open.gl website that displays a red triangle (see https://open.gl/drawing for the original code) and then started adding the necessary transform feedback gl calls in order to reproduce the problem. The program is below:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &lt;chrono&gt;&#xD;&#xA;    &#xD;&#xA;    #define GL_GLEXT_PROTOTYPES&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    // #include &lt;GL/glu.h&gt;&#xD;&#xA;    #include &lt;thread&gt;&#xD;&#xA;    &#xD;&#xA;    #define gl_error_check do { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, &quot;gl error %d at %s:%d\n&quot;, err, __FILE__, __LINE__); } } while (0)&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	float vertices[] = {&#xD;&#xA;    		0.0f,  0.5f, // Vertex 1 (X, Y)&#xD;&#xA;    		0.5f, -0.5f, // Vertex 2 (X, Y)&#xD;&#xA;    		-0.5f, -0.5f  // Vertex 3 (X, Y)&#xD;&#xA;    	};&#xD;&#xA;    &#xD;&#xA;    	GLuint vbo;&#xD;&#xA;    &#xD;&#xA;    	const char* vertexSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 position;&#xD;&#xA;    		// out float outValue;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char* fragmentSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		uniform vec3 triangleColor;&#xD;&#xA;    &#xD;&#xA;    		out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outColor = vec4(triangleColor, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	glfwInit();&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    &#xD;&#xA;    	GLFWwindow* window = glfwCreateWindow(800, 600, &quot;OpenGL&quot;, nullptr, nullptr); // Windowed&#xD;&#xA;    &#xD;&#xA;    	glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;    	GLuint vao;&#xD;&#xA;    	glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    	glBindVertexArray(vao);&#xD;&#xA;    &#xD;&#xA;    	glGenBuffers(1, &amp;vbo); // Generate 1 buffer&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);&#xD;&#xA;    &#xD;&#xA;    	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);&#xD;&#xA;    	glShaderSource(vertexShader, 1, &amp;vertexSource, NULL);&#xD;&#xA;    	glCompileShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	GLint status;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;vertex shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);&#xD;&#xA;    	glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL);&#xD;&#xA;    	glCompileShader(fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;status);&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;fragment shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLuint shaderProgram = glCreateProgram();&#xD;&#xA;    	glAttachShader(shaderProgram, vertexShader);&#xD;&#xA;    	glAttachShader(shaderProgram, fragmentShader);&#xD;&#xA;    &#xD;&#xA;    	glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;);   // not necessary&#xD;&#xA;    &#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(shaderProgram);&#xD;&#xA;    	glUseProgram(shaderProgram);&#xD;&#xA;    &#xD;&#xA;    	GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;);&#xD;&#xA;    	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);&#xD;&#xA;    	glEnableVertexAttribArray(posAttrib);&#xD;&#xA;    &#xD;&#xA;    	GLint uniColor = glGetUniformLocation(shaderProgram, &quot;triangleColor&quot;);&#xD;&#xA;    	glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    	GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };&#xD;&#xA;    &#xD;&#xA;    	// shader output buffer&#xD;&#xA;    	GLuint tbo;&#xD;&#xA;    	glGenBuffers(1, &amp;tbo);&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, tbo);&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(data), nullptr, GL_STATIC_READ);&#xD;&#xA;    &#xD;&#xA;    	std::cout &lt;&lt; &quot;Init complete&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    	while(!glfwWindowShouldClose(window))&#xD;&#xA;    	{&#xD;&#xA;    		if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)&#xD;&#xA;    			glfwSetWindowShouldClose(window, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    		// Clear the screen to black&#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;    		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;    		glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    		// Draw a triangle from the 3 vertices&#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;    &#xD;&#xA;    		glfwSwapBuffers(window);&#xD;&#xA;    		glfwPollEvents();&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// std::this_thread::sleep_for(std::chrono::seconds(10));&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(shaderProgram);&#xD;&#xA;    	glDeleteShader(fragmentShader);&#xD;&#xA;    	glDeleteShader(vertexShader);&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(1, &amp;tbo);&#xD;&#xA;    	glDeleteBuffers(1, &amp;vbo);&#xD;&#xA;    &#xD;&#xA;    	glDeleteVertexArrays(1, &amp;vao);&#xD;&#xA;    &#xD;&#xA;    	glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If I compile and run the program as shown above, it displays a red triangle, like so:&#xD;&#xA;&#xD;&#xA;[![working triangle][1]][1]&#xD;&#xA;&#xD;&#xA;So far so good. In the code above, I've commented and ifdef'ed out a couple of what appear to be problematic lines. In the vertex shader, there's the declaration of the output variable outValue:&#xD;&#xA;&#xD;&#xA;		// out float outValue;&#xD;&#xA;&#xD;&#xA;and then in the CPU code:&#xD;&#xA;&#xD;&#xA;    #if 0&#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(shaderProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);&#xD;&#xA;    	gl_error_check;&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;If I uncomment the declaration of outValue and change the 0 in the #if to a 1 so that the call to glTransformFeedbackVaryings() is compiled, the resulting executable displays only an empty window, no triangle.&#xD;&#xA;&#xD;&#xA;So it seems that the call to glTransformFeedbackVaryings() is somehow breaking the rasterization process, even though so far the shader doesn't yet write anything to outValue nor does the CPU code try to read the feedback buffer.&#xD;&#xA;&#xD;&#xA;Thus my question.&#xD;&#xA;&#xD;&#xA;Is it a requirement that when a GL program is using transform feedback that it cannot actually render pixels to the screen?&#xD;&#xA;&#xD;&#xA;Assuming this is not the case, is there something I'm missing?&#xD;&#xA;&#xD;&#xA;Thanks in advance.&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;Edit: updated the version declarations in the shaders from 150 to 330. I still get a blank window with the problematic lines enabled.&#xD;&#xA;&#xD;&#xA;=============================================&#xD;&#xA;&#xD;&#xA;Following Nathan Reed's suggestion, I added gl_error_check s following every gl API call. This one seems to be triggering the first error:&#xD;&#xA;&#xD;&#xA; glUseProgram(shaderProgram); gl_error_check;&#xD;&#xA;&#xD;&#xA;as the console shows:&#xD;&#xA;&#xD;&#xA;    ~/opengl/matrix_code/draw_feed$ ./a.out &#xD;&#xA;    gl error 1282 at main.cpp:125&#xD;&#xA;&#xD;&#xA;and line 125 is the call to glUseProgram(). The reported 1282 is 0x502 in hex which equates to:&#xD;&#xA;&#xD;&#xA;GL_INVALID_OPERATION, 0x0502&#xD;&#xA;    Given when the set of state for a command is not legal for the parameters given to that command. It is also given for commands where combinations of parameters define what the legal parameters are.&#xD;&#xA;&#xD;&#xA;When I lookup the reference to glUseProgram() at:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUseProgram.xhtml&#xD;&#xA;&#xD;&#xA;and read the list of errors at the bottom, it shows:&#xD;&#xA;&#xD;&#xA;GL_INVALID_OPERATION is generated if program is not a program object.&#xD;&#xA;&#xD;&#xA;GL_INVALID_OPERATION is generated if program could not be made part of current state.&#xD;&#xA;&#xD;&#xA;GL_INVALID_OPERATION is generated if transform feedback mode is active.&#xD;&#xA;&#xD;&#xA;That last reason for GL_INVALID_OPERATION seems pertinent, but its not clear to me what I should do about. Is there some call necessary to disable transform feedback mode during the call to glUseProgram()?&#xD;&#xA;&#xD;&#xA;If so, do I turn it back on again after the call to glUseProgram()?&#xD;&#xA;&#xD;&#xA;Also, I added this code to display the shader compile log:&#xD;&#xA;&#xD;&#xA;    glCompileShader(vertexShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    GLint bufflen;&#xD;&#xA;    glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &amp;bufflen); gl_error_check;&#xD;&#xA;    if (bufflen &gt; 1)&#xD;&#xA;    {&#xD;&#xA;    	GLchar* log_string = new char[bufflen + 1];&#xD;&#xA;    	glGetShaderInfoLog(vertexShader, bufflen, 0, log_string); gl_error_check;&#xD;&#xA;    	printf(&quot;vertex shader: %s\n&quot;, log_string);&#xD;&#xA;    	delete[] log_string;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But nothing gets logged.&#xD;&#xA;&#xD;&#xA;And thanks for the suggestion about Debug Output. I was unaware of that feature. I'll bone up on that and add it to my code.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nNuZX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="33446" PostHistoryTypeId="2" PostId="11084" RevisionGUID="13053b06-4c8b-4731-ac34-f21eba2f5d67" CreationDate="2021-07-27T11:31:21.243" UserId="16949" Text="A typical definition of a Vertex structure in C++ might look something like this:&#xD;&#xA;```&#xD;&#xA;struct Vertex&#xD;&#xA;{&#xD;&#xA;    Vec3 pos;&#xD;&#xA;    Vec3 color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;However, we found ourselves designing a multi-purpose system where sometimes we need textures, sometimes colors, sometimes normals etc. and sometimes even all 3.&#xD;&#xA;&#xD;&#xA;How is this usually delt with in graphics programming, where a single system might need to make use of different types of vertex structures?&#xD;&#xA;&#xD;&#xA;I see two main options:&#xD;&#xA;1. Define a single vertex structure with all the attributes defined and only used those that are need for each scenario. The disadvantage for this seems to be the memory usage on both the CPU and GPU side for storing thse structure&#xD;&#xA;2. Define multiple different structures with different attributes. The disadvantage for this might be that it could become a management nightmare.&#xD;&#xA;&#xD;&#xA;Thoughts?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33447" PostHistoryTypeId="1" PostId="11084" RevisionGUID="13053b06-4c8b-4731-ac34-f21eba2f5d67" CreationDate="2021-07-27T11:31:21.243" UserId="16949" Text="Different Vertex structures in multi-purpose system" ContentLicense="CC BY-SA 4.0" />
  <row Id="33448" PostHistoryTypeId="3" PostId="11084" RevisionGUID="13053b06-4c8b-4731-ac34-f21eba2f5d67" CreationDate="2021-07-27T11:31:21.243" UserId="16949" Text="|performance|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33449" PostHistoryTypeId="50" PostId="7804" RevisionGUID="1f2a9227-dfad-4a49-b6f3-bcc48ece821b" CreationDate="2021-07-27T18:06:00.613" UserId="-1" />
  <row Id="33453" PostHistoryTypeId="50" PostId="9626" RevisionGUID="5d62742e-f8ec-4044-9476-a49563a6adb6" CreationDate="2021-07-28T13:06:20.573" UserId="-1" />
  <row Id="33456" PostHistoryTypeId="2" PostId="11086" RevisionGUID="96f080ec-cde2-441a-8bb6-7b06464bd38e" CreationDate="2021-07-28T16:39:53.683" UserId="16879" Text="For example, when you want to compute the world space position of a fragment in the fragment shader, you can construct the fragment's NDC coordinates, then multiply by the inverse of whatever transform was used on the triangle that was rasterized to that fragment. &#xD;&#xA;&#xD;&#xA;And when this reverse process includes some projective transformation, you have to divide by w after doing that multiplication. Just like if you did the forward process.&#xD;&#xA;&#xD;&#xA;But why? My intuition would be that you instead multiply by w (the original one for the fragment, which is stored in e.g. gl_FragCoord.w as 1/w) before applying the transformation, or something like that. &#xD;&#xA;&#xD;&#xA;It kind of makes sense that you have to do a perspective divide after applying the inverse projection transform - after all it's going to alter the x,y,z and w components of the result in projecty ways, but I don't understand why this would then correctly give you back the original world space position for the fragment instead of an arbitrary result." ContentLicense="CC BY-SA 4.0" />
  <row Id="33457" PostHistoryTypeId="1" PostId="11086" RevisionGUID="96f080ec-cde2-441a-8bb6-7b06464bd38e" CreationDate="2021-07-28T16:39:53.683" UserId="16879" Text="Why perspective division ( div by w) when applying the inverse to a perspective transformation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33458" PostHistoryTypeId="3" PostId="11086" RevisionGUID="96f080ec-cde2-441a-8bb6-7b06464bd38e" CreationDate="2021-07-28T16:39:53.683" UserId="16879" Text="|transformations|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33460" PostHistoryTypeId="2" PostId="11087" RevisionGUID="23ebeaa8-6ca6-454e-8f9f-12c1d1b89a29" CreationDate="2021-07-28T18:47:52.540" UserId="48" Text="Most rendering engines do need to handle multiple vertex structures depending on the type of shading being used on the mesh.&#xD;&#xA;&#xD;&#xA;If there are only a small number of discrete vertex structures, you could simply create an enum to list them and define a struct for each one. However, many rendering engines take a fully data-driven approach to it, where there is no predefined vertex structure, but just a buffer of raw bytes plus a metadata description that lists the offset and type of each vertex component within the structure. It creates a lot of extra housekeeping code, but it is the most flexible way to deal with vertex structures.&#xD;&#xA;&#xD;&#xA;An alternate approach is to use &quot;deinterleaved&quot; vertices, where each vertex component is in its own array. You'd have one array of positions, one array of colors, one array of normals, etc. This allows for components to be present or absent simply by populating that array or leaving it empty. The GPU can read deinterleaved vertex data as well as interleaved data; you just have to configure the vertex arrays appropriately. Deinterleaved vertices may be less efficient overall, as more memory transactions are required to read the data this way. On the other hand, that may not matter much if the GPU is not vertex-bound on your scene.&#xD;&#xA;&#xD;&#xA;An advantage of the deinterleaved approach is that sometimes different vertex components are relevant for different rendering passes on the same mesh; for example, shadow rendering usually only needs positions and not colors. Deinterleaved vertex data makes it easy to supply only those components that are relevant for the current pass, so the GPU need not spend extra bandwidth reading irrelevant data.&#xD;&#xA;&#xD;&#xA;A middle ground is to partially deinterleave the data, so that positions are in one array and all the other components are interleaved together in another array, for example (or any other combination you choose)." ContentLicense="CC BY-SA 4.0" />
  <row Id="33461" PostHistoryTypeId="2" PostId="11088" RevisionGUID="7cef12e5-46e7-4422-86ae-b5d2be37b844" CreationDate="2021-07-28T19:54:05.840" UserId="16949" Text="I have been experimenting with loading in OBJ files into memory using [tinyobj][1]. I have also been learning and analysing the OBJ file format specification. I have some code which loads the BMW car model [here][2]. The code loads in the model, but removes any duplicate vertices as it reads them from the tinyobj output array.&#xD;&#xA;&#xD;&#xA;I counted the number of duplicate vertices contained in the OBJ file, and out of the 1 155 486 vertices read from file, 83% of them were duplicates.&#xD;&#xA;&#xD;&#xA;I am not sure if I am misunderstanding something or not, but isn't this unnecessary and extremely inefficient storage-wise, given the fact that each face in the OBJ format uses an index into the array of vertices to define itself? Why duplicate so much of this data instead of having each vertex be unique with faces that use it using the same index?&#xD;&#xA;&#xD;&#xA;I used a different OBJ file from a different source and got a similar result (78% duplicates), so I don't think this is an issue with the source (or could it be?).&#xD;&#xA;&#xD;&#xA;For context, I am removing duplicates as they do in [Vulkan tutorial 27][3] as I am passing them to the GPU using the vertex and index buffer method.&#xD;&#xA;&#xD;&#xA;Maybe I am misunderstanding a fundamental aspect of 3d model storage, but if someone could explain this that would be great.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/tinyobjloader/tinyobjloader&#xD;&#xA;  [2]: https://casual-effects.com/data/&#xD;&#xA;  [3]: https://github.com/Overv/VulkanTutorial/blob/master/code/27_model_loading.cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="33462" PostHistoryTypeId="1" PostId="11088" RevisionGUID="7cef12e5-46e7-4422-86ae-b5d2be37b844" CreationDate="2021-07-28T19:54:05.840" UserId="16949" Text="Why do OBJ files contain so many duplicate vertices if they use indices to define faces?" ContentLicense="CC BY-SA 4.0" />
  <row Id="33463" PostHistoryTypeId="3" PostId="11088" RevisionGUID="7cef12e5-46e7-4422-86ae-b5d2be37b844" CreationDate="2021-07-28T19:54:05.840" UserId="16949" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="33464" PostHistoryTypeId="50" PostId="9307" RevisionGUID="6342b037-3afb-4869-974a-8352edffd713" CreationDate="2021-07-28T20:03:05.290" UserId="-1" />
  <row Id="33465" PostHistoryTypeId="2" PostId="11089" RevisionGUID="c5f7c186-dcea-4d61-a136-48ad07ffbf26" CreationDate="2021-07-28T21:05:45.797" UserId="48" Text="The way homogeneous coordinates (x, y, z, w) work is that if you multiply the vector by any nonzero value, it still represents the same point in 3D projective space. These different xyzw representations of the same point are all considered equivalent to each other: one is just as good as another. The point (1, 2, 3, 4) is the same as the point (2, 4, 6, 8), or (−1, −2, −3, −4), etc.&#xD;&#xA;&#xD;&#xA;For converting back from projective space to the ordinary 3D space embedded in it, it's convenient to normalize to w = 1. That's all that the division by w is really doing. It's not part of the transformation per se.&#xD;&#xA;&#xD;&#xA;It's a lot like normalizing a vector, by dividing it by its magnitude. It still points the same direction, but it's convenient for later calculations to ensure it has length 1 (in cases where the direction is the thing you care about and the length doesn't matter).&#xD;&#xA;&#xD;&#xA;Just as you might normalize a direction vector after passing it through some 3D transformations, you can &quot;normalize&quot; projective points represented by homogeneous coordinates, after passing them through some projective transformations, to restore them to w = 1.&#xD;&#xA;&#xD;&#xA;The 4×4 matrix is the actual projective transformation, and the inverse transformation is just given by the matrix inverse. Recovering the exact original w value before transformation is meaningless, and isn't possible anyway since the division by w loses that information—just as normalizing a direction vector loses the information about its original length, but that's ok since the length wasn't relevant anyway." ContentLicense="CC BY-SA 4.0" />
  <row Id="33466" PostHistoryTypeId="2" PostId="11090" RevisionGUID="7847bc96-9cf2-4819-8079-fdb8f7f53f7d" CreationDate="2021-07-28T23:58:41.763" UserId="7952" Text="The file has multiple objects in it. The car body, tires, bolts, rondel, and more. What is good here is that all the different parts are broken down so they can be extracted and used, edited, split and combined with other models. The downside is that there are a lot of duplicate vertices. In this case there are a whole lot of duplicates.&#xD;&#xA;&#xD;&#xA;This is a common practice. Many file formats don't have an easy way to define a large number of vertices then define index sets that refer into them while still keeping all the parts separate.&#xD;&#xA;&#xD;&#xA;When we load them into the GPU it is much better to optimize the models in some way, removing duplicates is a good first step. (there are programs that are devoted solely to optimizing a mesh)" ContentLicense="CC BY-SA 4.0" />
  <row Id="33467" PostHistoryTypeId="2" PostId="11091" RevisionGUID="4d2f1b2c-ab71-45d6-8020-22025f171355" CreationDate="2021-07-29T01:03:46.080" UserId="16927" Text="To answer my original question:&#xD;&#xA;&#xD;&#xA;&quot;is doing transform feedback while rendering vertices not possible?&quot;&#xD;&#xA;&#xD;&#xA;No. It is possible, but not directly like my original code was trying to do.&#xD;&#xA;&#xD;&#xA;It appears (somebody please tell why I'm wrong if I've still got this wrong, 8^)) that what's prohibited is performing rasterization and transform feedback in the same GLSL program. One can however create two GLSL programs with one program's vertex shader outputting pixels for rasterization and the other program's vertex shader outputting the same data for transform feedback.&#xD;&#xA;&#xD;&#xA;Below I've copied the updated code that does this. It displays the same red triangle as shown above, but also feeds back the pixel coordinates and displays them on stdout like so:&#xD;&#xA;&#xD;&#xA;    $ ./draw_feed &#xD;&#xA;    Init complete&#xD;&#xA;    loop_count = 1&#xD;&#xA;    1 primitives written!&#xD;&#xA;    0.000000 0.500000 0.000000 &#xD;&#xA;    0.500000 -0.500000 0.000000 &#xD;&#xA;    -0.500000 -0.500000 0.000000 &#xD;&#xA;    &#xD;&#xA;    loop_count = 2&#xD;&#xA;    1 primitives written!&#xD;&#xA;    0.000000 0.500000 0.000000 &#xD;&#xA;    0.500000 -0.500000 0.000000 &#xD;&#xA;    -0.500000 -0.500000 0.000000 &#xD;&#xA;    $&#xD;&#xA;&#xD;&#xA;The downside is it ends up passing all the input pixel data through the GPUs twice. For this code that's pretty lightweight, but for others I suspect that's not always the case. Anyway, this is the best I've been able to come up with.&#xD;&#xA;&#xD;&#xA;Thanks to Jakob Progsch for providing the sample program I derived this from at:&#xD;&#xA;&#xD;&#xA;https://github.com/progschj/OpenGL-Examples/blob/master/09transform_feedback.cpp&#xD;&#xA;&#xD;&#xA;Jakob's code is much cleaner than mine, but while it does transform feedback first and uses that as input to rasterization, mine does the opposite.&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;cmath&gt;&#xD;&#xA;    #include &lt;chrono&gt;&#xD;&#xA;    &#xD;&#xA;    #define GL_GLEXT_PROTOTYPES&#xD;&#xA;    #include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;    #include &lt;GL/gl.h&gt;&#xD;&#xA;    #include &lt;unistd.h&gt;&#xD;&#xA;    &#xD;&#xA;    #define gl_error_check do { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, &quot;gl error %d at %s:%d\n&quot;, err, __FILE__, __LINE__); } } while (0)&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;    	float vertices[] = {&#xD;&#xA;    		0.0f,  0.5f, // Vertex 1 (X, Y)&#xD;&#xA;    		0.5f, -0.5f, // Vertex 2 (X, Y)&#xD;&#xA;    		-0.5f, -0.5f  // Vertex 3 (X, Y)&#xD;&#xA;    	};&#xD;&#xA;    &#xD;&#xA;    	const char *vertexSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 position;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char *fragmentSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		uniform vec3 triangleColor;&#xD;&#xA;    &#xD;&#xA;    		out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outColor = vec4(triangleColor, 1.0);&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    	const char *transformSource = R&quot;glsl(&#xD;&#xA;    		#version 330 core&#xD;&#xA;    &#xD;&#xA;    		in vec2 trans_position;&#xD;&#xA;    		out vec3 outValue;&#xD;&#xA;    &#xD;&#xA;    		void main()&#xD;&#xA;    		{&#xD;&#xA;    			outValue = vec3(vec4(trans_position, 0.0, 1.0));&#xD;&#xA;    		}&#xD;&#xA;    	)glsl&quot;;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	glfwInit();&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);&#xD;&#xA;    	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);&#xD;&#xA;    &#xD;&#xA;    	GLFWwindow* window = glfwCreateWindow(800, 600, &quot;OpenGL&quot;, nullptr, nullptr); // Windowed&#xD;&#xA;    &#xD;&#xA;    	glfwMakeContextCurrent(window);&#xD;&#xA;    &#xD;&#xA;    #define NUM_BUFFERS 2&#xD;&#xA;    &#xD;&#xA;    	GLuint vao[NUM_BUFFERS];&#xD;&#xA;    	glGenVertexArrays(NUM_BUFFERS, vao); gl_error_check;&#xD;&#xA;    	// printf(&quot;vao[0] = %u, vao[1] = %u\n&quot;, vao[0], vao[1]);&#xD;&#xA;    &#xD;&#xA;    	GLuint vbo[NUM_BUFFERS];&#xD;&#xA;    	glGenBuffers(NUM_BUFFERS, vbo); gl_error_check; // Generate 1 buffer&#xD;&#xA;    	// printf(&quot;vbo[0] = %u, vbo[1] = %u\n&quot;, vbo[0], vbo[1]);&#xD;&#xA;    &#xD;&#xA;    	// compile vertex shader&#xD;&#xA;    	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); gl_error_check;&#xD;&#xA;    	glShaderSource(vertexShader, 1, &amp;vertexSource, NULL); gl_error_check;&#xD;&#xA;    	glCompileShader(vertexShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	GLint bufflen;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &amp;bufflen); gl_error_check;&#xD;&#xA;    	if (bufflen &gt; 1)&#xD;&#xA;    	{&#xD;&#xA;    		GLchar* log_string = new char[bufflen + 1];&#xD;&#xA;    		glGetShaderInfoLog(vertexShader, bufflen, 0, log_string); gl_error_check;&#xD;&#xA;    		printf(&quot;vertex shader: %s\n&quot;, log_string);&#xD;&#xA;    		delete[] log_string;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	GLint status;&#xD;&#xA;    	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &amp;status); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;vertex shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// compile fragment shader&#xD;&#xA;    	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); gl_error_check;&#xD;&#xA;    	glShaderSource(fragmentShader, 1, &amp;fragmentSource, NULL); gl_error_check;&#xD;&#xA;    	glCompileShader(fragmentShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &amp;bufflen); gl_error_check;&#xD;&#xA;    	if (bufflen &gt; 1)&#xD;&#xA;    	{&#xD;&#xA;    		GLchar* log_string = new char[bufflen + 1];&#xD;&#xA;    		glGetShaderInfoLog(fragmentShader, bufflen, 0, log_string); gl_error_check;&#xD;&#xA;    		printf(&quot;fragment shader: %s\n&quot;, log_string);&#xD;&#xA;    		delete[] log_string;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &amp;status); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;fragment shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// link vertex and fragment shaders into shader program&#xD;&#xA;    	GLuint shaderProgram = glCreateProgram(); gl_error_check;&#xD;&#xA;    	glAttachShader(shaderProgram, vertexShader); gl_error_check;&#xD;&#xA;    	glAttachShader(shaderProgram, fragmentShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glBindFragDataLocation(shaderProgram, 0, &quot;outColor&quot;); gl_error_check;   // not necessary?&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(shaderProgram); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &amp;bufflen);  gl_error_check;&#xD;&#xA;    	if (bufflen &gt; 1) {&#xD;&#xA;    		GLchar* log_string = new char[bufflen + 1];&#xD;&#xA;    		glGetProgramInfoLog(shaderProgram, bufflen, 0, log_string); gl_error_check;&#xD;&#xA;    		printf(&quot;shader program: %s\n&quot;, log_string);&#xD;&#xA;    		delete[] log_string;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &amp;status); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;shader program compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// glUseProgram() needs to happen for glVertexAttribPointer() and glUniform3f() to not generate 1282 errors&#xD;&#xA;    	// though the program seems to work ok otherwise.&#xD;&#xA;    	glUseProgram(shaderProgram); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glBindVertexArray(vao[0]); gl_error_check;&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); gl_error_check;&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	GLint posAttrib = glGetAttribLocation(shaderProgram, &quot;position&quot;); gl_error_check;&#xD;&#xA;    	// printf(&quot;posAttrib = %d\n&quot;, posAttrib);&#xD;&#xA;    	glEnableVertexAttribArray(posAttrib); gl_error_check; // XXX&#xD;&#xA;    	glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	GLint uniColor = glGetUniformLocation(shaderProgram, &quot;triangleColor&quot;); gl_error_check;&#xD;&#xA;    	glUniform3f(uniColor, 1.0f, 0.0f, 0.0f); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	// compile transform shader&#xD;&#xA;    	GLuint transformShader = glCreateShader(GL_VERTEX_SHADER); gl_error_check;&#xD;&#xA;    	glShaderSource(transformShader, 1, &amp;transformSource, NULL); gl_error_check;&#xD;&#xA;    	glCompileShader(transformShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(transformShader, GL_INFO_LOG_LENGTH, &amp;bufflen); gl_error_check;&#xD;&#xA;    	if (bufflen &gt; 1)&#xD;&#xA;    	{&#xD;&#xA;    		GLchar* log_string = new char[bufflen + 1];&#xD;&#xA;    		glGetShaderInfoLog(transformShader, bufflen, 0, log_string); gl_error_check;&#xD;&#xA;    		printf(&quot;transform shader: %s\n&quot;, log_string);&#xD;&#xA;    		delete[] log_string;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	glGetShaderiv(transformShader, GL_COMPILE_STATUS, &amp;status); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;transform shader compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// link transform shader into transform program&#xD;&#xA;    	GLuint transformProgram = glCreateProgram(); gl_error_check;&#xD;&#xA;    	glAttachShader(transformProgram, transformShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	const GLchar* feedbackVaryings[] = { &quot;outValue&quot; };&#xD;&#xA;    	glTransformFeedbackVaryings(transformProgram, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glLinkProgram(transformProgram); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glGetProgramiv(transformProgram, GL_INFO_LOG_LENGTH, &amp;bufflen);  gl_error_check;&#xD;&#xA;    	if (bufflen &gt; 1) {&#xD;&#xA;    		GLchar* log_string = new char[bufflen + 1];&#xD;&#xA;    		glGetProgramInfoLog(transformProgram, bufflen, 0, log_string); gl_error_check;&#xD;&#xA;    		printf(&quot;transform program: %s\n&quot;, log_string);&#xD;&#xA;    		delete[] log_string;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	glGetProgramiv(transformProgram, GL_LINK_STATUS, &amp;status); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	if (status != GL_TRUE) {&#xD;&#xA;    		std::cerr &lt;&lt; &quot;transform program compile failed &quot; &lt;&lt; status &lt;&lt; std::endl;&#xD;&#xA;    		return -1;&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	glUseProgram(transformProgram); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glBindVertexArray(vao[1]); gl_error_check;&#xD;&#xA;    	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); gl_error_check;&#xD;&#xA;    	// 1 triangle of 3 vertices, 3 output coords (X, Y, X) per vertex == 9 floats per primitive&#xD;&#xA;    	glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), nullptr, GL_STATIC_READ); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	GLint transPosAttrib = glGetAttribLocation(transformProgram, &quot;trans_position&quot;); gl_error_check;&#xD;&#xA;    	// printf(&quot;transPosAttrib = %d\n&quot;, transPosAttrib);&#xD;&#xA;    	glEnableVertexAttribArray(transPosAttrib); gl_error_check;&#xD;&#xA;    	glVertexAttribPointer(transPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	std::cout &lt;&lt; &quot;Init complete&quot; &lt;&lt; std::endl;&#xD;&#xA;    &#xD;&#xA;    	int loop_count = 0;&#xD;&#xA;    &#xD;&#xA;    	while(!glfwWindowShouldClose(window))&#xD;&#xA;    	{&#xD;&#xA;    		if ((glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) || (++loop_count &gt; 1))&#xD;&#xA;    			glfwSetWindowShouldClose(window, GL_TRUE);&#xD;&#xA;    &#xD;&#xA;    		printf(&quot;loop_count = %d\n&quot;, loop_count);&#xD;&#xA;    &#xD;&#xA;    		// render triangle to screen using shaderProgram and vao[0]&#xD;&#xA;    		glUseProgram(shaderProgram); gl_error_check;&#xD;&#xA;    		glBindVertexArray(vao[0]); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		// Clear the screen to black&#xD;&#xA;    		glClearColor(0.0f, 0.0f, 0.0f, 1.0f); gl_error_check;&#xD;&#xA;    		glClear(GL_COLOR_BUFFER_BIT); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		glUniform3f(uniColor, 1.0f, 0.0f, 0.0f); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		// Draw a triangle from the 3 vertices&#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		// render triangle coordinates to feedback buffer&#xD;&#xA;    		glUseProgram(transformProgram); gl_error_check;&#xD;&#xA;    		glBindVertexArray(vao[0]); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		GLuint query;&#xD;&#xA;    		glGenQueries(1, &amp;query); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		glEnable(GL_RASTERIZER_DISCARD); gl_error_check;&#xD;&#xA;    		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo[1]); gl_error_check;&#xD;&#xA;    		glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query); gl_error_check;&#xD;&#xA;    		glBeginTransformFeedback(GL_TRIANGLES); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		glDrawArrays(GL_TRIANGLES, 0, 3); gl_error_check; gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		glEndTransformFeedback(); gl_error_check;&#xD;&#xA;    		glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); gl_error_check;&#xD;&#xA;    		glDisable(GL_RASTERIZER_DISCARD); gl_error_check;&#xD;&#xA;    		glFlush(); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		GLuint primitives;&#xD;&#xA;    		glGetQueryObjectuiv(query, GL_QUERY_RESULT, &amp;primitives); gl_error_check;&#xD;&#xA;    		printf(&quot;%u primitives written!\n&quot;, primitives);&#xD;&#xA;    &#xD;&#xA;    		// 1 triangle of 3 vertices, 3 output coords (X, Y, X) per vertex == 9 floats per primitive&#xD;&#xA;    &#xD;&#xA;    		// read output of shader from out buffer to here&#xD;&#xA;    		GLfloat feedback[9];&#xD;&#xA;    		glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(feedback), feedback); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		for (int i = 0; i &lt; primitives * 9; ) {&#xD;&#xA;    			printf(&quot;%f &quot;, feedback[i]);&#xD;&#xA;    			if (!(++i % 3)) {&#xD;&#xA;    				printf(&quot;\n&quot;);&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    		printf(&quot;\n&quot;);&#xD;&#xA;    &#xD;&#xA;    		glDeleteQueries(1, &amp;query); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    		glfwSwapBuffers(window);&#xD;&#xA;    		glfwPollEvents();&#xD;&#xA;    		sleep(1);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(transformProgram); gl_error_check;&#xD;&#xA;    	glDeleteShader(transformShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glDeleteProgram(shaderProgram); gl_error_check;&#xD;&#xA;    	glDeleteShader(fragmentShader); gl_error_check;&#xD;&#xA;    	glDeleteShader(vertexShader); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glDeleteBuffers(NUM_BUFFERS, vbo); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glDeleteVertexArrays(NUM_BUFFERS, vao); gl_error_check;&#xD;&#xA;    &#xD;&#xA;    	glfwTerminate();&#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34466" PostHistoryTypeId="50" PostId="10535" RevisionGUID="cc1035db-faef-4c1b-86ee-919d9819e8c6" CreationDate="2021-07-29T03:06:10.587" UserId="-1" />
  <row Id="34467" PostHistoryTypeId="5" PostId="11090" RevisionGUID="d8ace01b-8586-4cac-b8de-1902a1c418ca" CreationDate="2021-07-29T11:01:10.087" UserId="7952" Comment="added 1767 characters in body" Text="The file has multiple objects in it. The car body, tires, bolts, rondel, and more. What is good here is that all the different parts are broken down so they can be extracted and used, edited, split and combined with other models. The downside is that there are a lot of duplicate vertices. In this case there are a whole lot of duplicates.&#xD;&#xA;&#xD;&#xA;This is a common practice. Many file formats don't have an easy way to define a large number of vertices then define index sets that refer into them while still keeping all the parts separate.&#xD;&#xA;&#xD;&#xA;When we load them into the GPU it is much better to optimize the models in some way, removing duplicates is a good first step. (there are programs that are devoted solely to optimizing a mesh)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is a list of the objects: (this file also has a lot of duplicate objects in it)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;carShell 99488 faces&#xD;&#xA;plate 132 face&#xD;&#xA;carShell_001 512 faces&#xD;&#xA;RondelBack 4640 faces&#xD;&#xA;RondelFront 4640 faces&#xD;&#xA;taillight 6270 faces&#xD;&#xA;MStreak 1536 faces&#xD;&#xA;Window 2016 faces&#xD;&#xA;exhaust 1270 faces&#xD;&#xA;rearDiffuser 2496 faces&#xD;&#xA;lightsLid 1792 faces&#xD;&#xA;Platform 232 faces&#xD;&#xA;lightsGlass 472 faces&#xD;&#xA;LowerIntake 10022 faces&#xD;&#xA;lightsOutline 832 faces&#xD;&#xA;lowerIntake 1408 faces&#xD;&#xA;kidneyBars 3264 faces&#xD;&#xA;kigneyChrome 720 faces&#xD;&#xA;Interior 14604 faces&#xD;&#xA;trimming 2080 faces&#xD;&#xA;lightsAngelEyes 3072 faces&#xD;&#xA;lightsReflector 20480 faces&#xD;&#xA;lightsInterior2 2544 faces&#xD;&#xA;lightsBulb 416 faces&#xD;&#xA;lightSeperator 864 faces&#xD;&#xA;lightsInterior 816 faces&#xD;&#xA;SideMirror 128 faces&#xD;&#xA;CenterConsole 658 faces&#xD;&#xA;Inside_Window_Trim 512 faces&#xD;&#xA;carRigOutline 0 faces&#xD;&#xA;carRigArrow 0 faces&#xD;&#xA;Brake3_Cube_Dupli_ 108 faces&#xD;&#xA;Tire1_TireRim_Dupli_3 13600 faces&#xD;&#xA;Tire3_TireBolts_Dupli_ 4480 faces&#xD;&#xA;Tire3_TireRoundel_Dupli_2 4640 faces&#xD;&#xA;Tire3_TireRubber_Dupli_1 17384 faces&#xD;&#xA;Brake4_brakeAssembly_Dupli_1 350 faces&#xD;&#xA;Brake3_Cube_Dupli_001 108 faces&#xD;&#xA;Brake4_brakeAssembly_Dupli_002 350 faces&#xD;&#xA;Tire1_TireRim_Dupli_004 13600 faces&#xD;&#xA;Tire3_TireBolts_Dupli_001 4480 faces&#xD;&#xA;Tire3_TireRoundel_Dupli_003 4640 faces&#xD;&#xA;Tire3_TireRubber_Dupli_002 17384 faces&#xD;&#xA;Tire3_TireRubber_Dupli_003 17384 faces&#xD;&#xA;Brake4_brakeAssembly_Dupli_003 350 faces&#xD;&#xA;Tire1_TireRim_Dupli_005 13600 faces&#xD;&#xA;Tire3_TireBolts_Dupli_002 4480 faces&#xD;&#xA;Tire3_TireRoundel_Dupli_004 4640 faces&#xD;&#xA;Brake3_Cube_Dupli_002 108 faces&#xD;&#xA;Tire3_TireRubber_Dupli_004 17384 faces&#xD;&#xA;Tire1_TireRim_Dupli_006 13600 faces&#xD;&#xA;Tire3_TireBolts_Dupli_003 4480 faces&#xD;&#xA;Tire3_TireRoundel_Dupli_005 4640 faces&#xD;&#xA;Brake4_brakeAssembly_Dupli_004 350 faces&#xD;&#xA;Brake3_Cube_Dupli_003 108 faces&#xD;&#xA;carShell001 34548 faces&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34468" PostHistoryTypeId="2" PostId="12090" RevisionGUID="e3b7990b-18ed-4966-b4ae-486523b13168" CreationDate="2021-07-29T15:41:18.903" UserId="38" Text="There are many reasons not to merge vertices. Heres a few that i have used:&#xD;&#xA;&#xD;&#xA;1. The file contains many logical objects. If the units dont share vertices they may be separated later for reuse.&#xD;&#xA;2. You can circumvent render engine limitations by modeling. Say your modeling engine only support per vertex normals, but it does not support per face vertex normals. Well the next logical thing is just to split the vertex into two and your engine now does what you want.&#xD;&#xA;3. The vertices happen to coencide but they arent actually the same vertex. Because its easier to model the ideal surface than it is to model an actual gap between the edges. Maybe this is so that your skinning can move other side independently from the other or something.&#xD;&#xA;4. You want to make selection easy in the other engine. Having the vertices aranged in logical chunks makes this easier.&#xD;&#xA;5. Your just dumping out the data as its presented to you. This makes the translator easy to make. Besides its not like you nesseserily know how the thing should be handled in anycase. Just offering something minimal that works." ContentLicense="CC BY-SA 4.0" />
  <row Id="34469" PostHistoryTypeId="5" PostId="12090" RevisionGUID="a1f05f6a-3a21-441e-b011-1860f43c8709" CreationDate="2021-07-29T15:47:57.580" UserId="38" Comment="added 101 characters in body" Text="There are many reasons not to merge vertices. Heres a few that i have used:&#xD;&#xA;&#xD;&#xA;1. The file contains many logical objects. If the units dont share vertices they may be separated later for reuse.&#xD;&#xA;2. You can circumvent render engine limitations by modeling. Say your modeling engine only support per vertex normals, but it does not support per face vertex normals. Well the next logical thing is just to split the vertex into two and your engine now does what you want.&#xD;&#xA;3. The vertices happen to coencide but they arent actually the same vertex. Because its easier to model the ideal surface than it is to model an actual gap between the edges. Maybe this is so that your skinning can move other side independently from the other or something.&#xD;&#xA;4. You want to make something like selection/partial loading easy in the other engine. Having the vertices aranged in logical chunks makes this easier.&#xD;&#xA;5. Your just dumping out the data as its presented to you. This makes the translator easy to make. Besides its not like you nesseserily know how the thing should be handled in anycase. Just offering something minimal that works. Rest is tge users problem in many cases good users can live with this a d use it to their advantage." ContentLicense="CC BY-SA 4.0" />
  <row Id="34470" PostHistoryTypeId="5" PostId="12090" RevisionGUID="5f6d6d1e-ab1e-4052-84f8-708898893444" CreationDate="2021-07-29T20:52:30.753" UserId="38" Comment="edited body" Text="There are many reasons not to merge vertices. Heres a few that i have used:&#xD;&#xA;&#xD;&#xA;1. The file contains many logical objects. If the units dont share vertices they may be separated later for reuse.&#xD;&#xA;2. You can circumvent render engine limitations by modeling. Say your modeling engine only support per vertex normals, but it does not support per face vertex normals. Well the next logical thing is just to split the vertex into two and your engine now does what you want.&#xD;&#xA;3. The vertices happen to coencide but they arent actually the same vertex. Because its easier to model the ideal surface than it is to model an actual gap between the edges. Maybe this is so that your skinning can move other side independently from the other or something.&#xD;&#xA;4. You want to make something like selection/partial loading easy in the other engine. Having the vertices aranged in logical chunks makes this easier.&#xD;&#xA;5. Your just dumping out the data as its presented to you. This makes the translator easy to make. Besides its not like you nesseserily know how the thing should be handled in anycase. Just offering something minimal that works. Rest is the users problem in many cases good users can live with this and use it to their advantage." ContentLicense="CC BY-SA 4.0" />
  <row Id="34471" PostHistoryTypeId="2" PostId="12091" RevisionGUID="a09fc61c-98a6-4e96-b433-998e069f60d6" CreationDate="2021-07-29T23:09:36.100" UserId="16976" Text="I'm trying to reverse engineer a model format from an older Russian game (Pathologic) with limited success. It is a proprietary model format not recognized by any converters/editing tools (believe me, I've tried! someone on the fan forums confirmed this with the person behind the engine, also). I'd like to be able to read the models into a potential open-source recreation of the original engine. The original game uses Direct3D and is from 2005, so I read up on relevant docs to get a start. Unfortunately, it's not the &quot;x&quot; model format.&#xD;&#xA;&#xD;&#xA;**What I've got so far (for a simple mesh):**&#xD;&#xA;&#xD;&#xA; - Texture file name/location&#xD;&#xA; - Number of faces and vertices&#xD;&#xA; - UV coordinates for each vertex&#xD;&#xA; - Vertex buffer&#xD;&#xA;&#xD;&#xA;**Things I'm struggling to understand (least to most important)**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; - File header: what could it mean?&#xD;&#xA;&#xD;&#xA; - &quot;Arbitrary&quot; padding in the file: what could determine its size?&#xD;&#xA;&#xD;&#xA; - 12-element float matrices. Could be transformation matrices without the last row - to use with homogenous coordinate systems, but there's 6 of them in a mesh with 4 vertices and 2 faces - isn't that too many? &#xD;&#xA;&#xD;&#xA; - Mysterious 4 bytes describing each vertex: some kind of a color format? &#xD;&#xA;&#xD;&#xA; - Mysterious sets of 3 32-bit floats repeating multiple times - what could it be?&#xD;&#xA;&#xD;&#xA; - Where could the vertex normals be stored?&#xD;&#xA;&#xD;&#xA;Attached is a very simple mesh (way under 1kB) I'm studying before moving on to the more complex ones. I believe it to be a simple textured plane. I've started with a similar mesh that was in XY plane, this one seems to be oriented a bit more arbitrarily. Since it's a plane, I assume it has 4 vertices and 2 faces.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[Simple Mesh][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://drive.google.com/file/d/13pzBcUDmfhanpXx8CPLqPDPZP6-4P_fB/view?usp=sharing&#xD;&#xA;&#xD;&#xA;**File's structure as far as I can understand it**&#xD;&#xA;&#xD;&#xA; - Header at 0x00. &#xD;&#xA; - Texture Filename Length at 0x11 (16 characters here)&#xD;&#xA; - 1 byte padding&#xD;&#xA; - Texture filename (h2_door_DXT1.tex)&#xD;&#xA; - 1 byte padding&#xD;&#xA; - Number of vertices at 0x23 (4 vertices)&#xD;&#xA; - Number of faces at 0x27 (2 faces)&#xD;&#xA; - 12 bytes of recurring 3x 4-byte floats (first occurrence)&#xD;&#xA; - Mysterious float&#xD;&#xA; - 12 bytes of recurring 3x 4-byte floats (second occurrence)&#xD;&#xA; - 12-element float matrix (transformation matrix?)&#xD;&#xA; - 73 bytes of unknown data&#xD;&#xA; - 12 bytes of recurring 3x 4-byte floats (third occurrence) at 0xC0&#xD;&#xA; - Data for four vertices at 0xCC. For each vertex, there's 3x int16 for X,Y,Z coordinates, then, 4 mysterious bytes, finally, 2 32-bit floats for UV coordinates.&#xD;&#xA; - Vertex buffer at 0x114. Two triangle descriptions, for each there's 3x int16 for the vertex IDs.&#xD;&#xA;&#xD;&#xA;After that it becomes a mix of 12-element float matrices and the recurring 3x floats with some padding/magic numbers between them.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;I'd appreciate any and all help with answering my questions/helping with the bullet points I'm struggling on. I could also provide other mesh examples as needed." ContentLicense="CC BY-SA 4.0" />
  <row Id="34472" PostHistoryTypeId="1" PostId="12091" RevisionGUID="a09fc61c-98a6-4e96-b433-998e069f60d6" CreationDate="2021-07-29T23:09:36.100" UserId="16976" Text="Proprietary 3D Format Reverse Engineering: What Could These Numbers And Matrices Represent?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34473" PostHistoryTypeId="3" PostId="12091" RevisionGUID="a09fc61c-98a6-4e96-b433-998e069f60d6" CreationDate="2021-07-29T23:09:36.100" UserId="16976" Text="|3d|transformations|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34474" PostHistoryTypeId="2" PostId="12092" RevisionGUID="8083fc34-76c2-42b9-a76a-317313355920" CreationDate="2021-07-30T10:54:57.403" UserId="16980" Text="While programming something in Rust with the BevyEngine, I came across TextureFormats. My understanding is that those are used to define how the pixel data is handled. So Rgba8Unorm means that there are is a red, green, blue and alpha channel. Each of them is represented by an 8bit unsigned integer. &#xD;&#xA;&#xD;&#xA;Since I only need a black/white image I read through [this](https://docs.rs/bevy/0.5.0/bevy/render/texture/enum.TextureFormat.html) list of available TextureFormats in the BevyEngine. But all the &quot;one channel formats&quot; have only one channel for red. Also [here](https://docs.rs/wgpu/0.9.0/wgpu/enum.TextureFormat.html) in the wgpu-rs crate. There are so many formats with only one channel for red.&#xD;&#xA;&#xD;&#xA;Why is that. What is the purpose of having only the red channel. And why am I not abled to find a format that allows me to represent only B/W values. (Is that maybe an &quot;alpha only&quot; format?)" ContentLicense="CC BY-SA 4.0" />
  <row Id="34475" PostHistoryTypeId="1" PostId="12092" RevisionGUID="8083fc34-76c2-42b9-a76a-317313355920" CreationDate="2021-07-30T10:54:57.403" UserId="16980" Text="Why do some texture data formats only have the red channel?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34476" PostHistoryTypeId="3" PostId="12092" RevisionGUID="8083fc34-76c2-42b9-a76a-317313355920" CreationDate="2021-07-30T10:54:57.403" UserId="16980" Text="|texture|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34477" PostHistoryTypeId="2" PostId="12093" RevisionGUID="d352d14a-4fe1-40ad-9a24-8ccdc14e81a6" CreationDate="2021-07-30T11:38:12.723" UserId="7952" Text="Red *is* the gray scale channel (black/white). To generate a gray scale image copy the Red channel to the Green and Blue channels, set alpha to one and a gray scale image will result.&#xD;&#xA;&#xD;&#xA;Of course that single channel can be used for many other purposes besides just gray scale image data. It can represent noise, a lookup table (LUT). The list is long and mighty." ContentLicense="CC BY-SA 4.0" />
  <row Id="34478" PostHistoryTypeId="50" PostId="10994" RevisionGUID="bca73716-7775-4757-b297-09708a225d58" CreationDate="2021-07-30T13:03:20.267" UserId="-1" />
  <row Id="34479" PostHistoryTypeId="2" PostId="12094" RevisionGUID="151412c3-1c4a-4fa4-a0e5-2b546b42b34e" CreationDate="2021-07-30T15:00:37.397" UserId="7952" Text="This is just food for thought:&#xD;&#xA;&#xD;&#xA;One potential way to analyze the data is by converting the point clouds to soil density clouds by looking at the distances between points at each excavation level. Potentially the soil density could be inferred by comparing nearest points, points that have a lot of distance to the next level have lower density, points that are close to the next level have higher density. &#xD;&#xA;&#xD;&#xA;Using a density cloud would make it possible to infer densities between layers and extrapolate data in unexcavated regions, it might even be possible to compute an error metric by having the algorithm extrapolate data, then comparing that to measured data.&#xD;&#xA;&#xD;&#xA;The reason I am going on and on about density is that is how MRI scans allow us to view different structures. Blood vessels have a different density then other tissues, so we can examine only blood vessels by isolating only that density in the density cloud generated by a scan. (think marching cubes algorithm here) So by isolating density ranges in a generated density map, different structures could potentially be visualized. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34481" PostHistoryTypeId="5" PostId="11056" RevisionGUID="d5dd33b2-c1b8-4a2b-9be3-9a4bcd931814" CreationDate="2021-07-31T05:16:54.847" UserId="8009" Comment="&quot;Q&quot; was written where &quot;P&quot; was intended, in one place.  Fixed that." Text="If by ___adding two colour values with alpha___ you mean to ___combine them for the purposes of blending___ then here's the answer you need.  I'll show the full derivation too.&#xD;&#xA;&#xD;&#xA;Feel free to scroll down to the **TL;DR** indicator if you're in a hurry.&#xD;&#xA;&#xD;&#xA;## Luminance-alpha formats&#xD;&#xA;&#xD;&#xA;Let’s simplify this by considering an image using the monochrome luminance-alpha format.  Pixels in this format have two components: a luminance value (L), ranging from 0.0 to 1.0, and an alpha component (α) also ranging from 0.0 to 1.0.&#xD;&#xA;&#xD;&#xA;## Blending&#xD;&#xA;&#xD;&#xA;Pixels with alpha components typically support a ___blend___ operation.  Let’s use the symbol **⊕** to denote the blend operation.  This operator takes as its left-hand side operand, a single-channel luminance-only value that is “opaque” (no alpha).  But the right-hand side operand takes a two-channel luminance-alpha pixel.  And this operator outputs a single-channel luminance-only value.&#xD;&#xA;&#xD;&#xA;Let’s suppose we start with a pixel value B stored in the framebuffer.  You can also think of it as the “background” value onto which we can blend new semi-transparent luminance-alpha pixels.&#xD;&#xA;&#xD;&#xA;Let’s assume as want to blend a semi-transparent luminance-alpha pixel value P over top of that and write the resultant value back into the framebuffer.  We are “painting” onto the background.  You could think of this as modifying B, but we’ll write the new value of B as B’.&#xD;&#xA;&#xD;&#xA;B’ = B ⊕ P&#xD;&#xA;&#xD;&#xA;The definition of ⊕ looks like this:&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt;' = B&lt;sub&gt;L&lt;/sub&gt; (1 - P&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;This says that the output is the luminance value in the buffer (background) times one-minus-alpha, plus the semi-transparent luminance value times alpha.  This should be an alpha blending operation you’re familiar with.&#xD;&#xA;&#xD;&#xA;## Composing two blend operations&#xD;&#xA;&#xD;&#xA;One way to consider how to combine two semi-transparent pixel values, P and Q is to construct a new value R (standing for “result”) such that:&#xD;&#xA;&#xD;&#xA;(B ⊕ P) ⊕ Q = B ⊕ R&#xD;&#xA;&#xD;&#xA;What I’ve written there, is that we perform two distinct, successive, blend operations one after the other.  First, we blend P with the background B to arrive at (B ⊕ P) then we blend Q with that result to arrive at (B ⊕ P) ⊕ Q.  Furthermore, we’d like this two-step operation to be equivalent to a one-step operation of blending a single semitransparent pixel R with the original background B.&#xD;&#xA;&#xD;&#xA;Now we can define R in terms of an “alpha compose” operator of our own design that operates on P and Q, for which we will use the symbol **⊙**, and we will define it to work like this &#xD;&#xA;&#xD;&#xA;R = P ⊙ Q&#xD;&#xA;&#xD;&#xA;We want to define it such that:&#xD;&#xA;&#xD;&#xA;(B ⊕ P) ⊕ Q = B ⊕ (P ⊙ Q)&#xD;&#xA;&#xD;&#xA;If we simply expand the definitions of these operators as before in terms of modifying a background pixel, then we’d like to define B’’ which is the result of having blended Q over B’.  And recall that B’ was the result of having blended P over the background B.&#xD;&#xA;&#xD;&#xA;B'' = (B ⊕ P) ⊕ Q&#xD;&#xA;&#xD;&#xA;B'' = B' ⊕ Q&#xD;&#xA;&#xD;&#xA;### Derive the formula&#xD;&#xA;&#xD;&#xA;Here's the _show your work_ portion.&#xD;&#xA;&#xD;&#xA;We can substitute (B ⊕ P) with what we’ve shown B’ to be equal to.&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt;'' = (B&lt;sub&gt;L&lt;/sub&gt; (1 - P&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;) ⊕ Q&#xD;&#xA;&#xD;&#xA;And now we can keep expanding to show what happens after we blend Q with that intermediate result.  This gets a little cluttered, but it equals this:&#xD;&#xA;&#xD;&#xA;(B&lt;sub&gt;L&lt;/sub&gt; (1 - P&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;)(1 - Q&lt;sub&gt;α&lt;/sub&gt;) + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;We want to rearrange this to be of the form of the original blend operator definition.&#xD;&#xA;&#xD;&#xA;Let’s start by simplifying:&#xD;&#xA;&#xD;&#xA;(B&lt;sub&gt;L&lt;/sub&gt; - B&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt;)(1 - Q&lt;sub&gt;α&lt;/sub&gt;) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; (1 - Q&lt;sub&gt;α&lt;/sub&gt;) + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt; - B&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - B&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + B&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;And now remember it has to end up looking like this:&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt; (1 - R&lt;sub&gt;α&lt;/sub&gt;) + R&lt;sub&gt;L&lt;/sub&gt; R&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;Let’s rearrange to accomplish that:&#xD;&#xA;&#xD;&#xA;B&lt;sub&gt;L&lt;/sub&gt; (1 - (P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)) + P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;We now know that:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;α&lt;/sub&gt; = P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;We just need to figure out what R&lt;sub&gt;L&lt;/sub&gt; equals.&#xD;&#xA;&#xD;&#xA;We know from what’s left over in that equation that:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; R&lt;sub&gt;α&lt;/sub&gt; = P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;And therefore, if R&lt;sub&gt;α&lt;/sub&gt; is non-zero, we can divide to isolate R&lt;sub&gt;L&lt;/sub&gt;.&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; = (P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)/R&lt;sub&gt;α&lt;/sub&gt; &#xD;&#xA;&#xD;&#xA;Substituting the value we arrived at for R&lt;sub&gt;α&lt;/sub&gt; we get:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; = (P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)/(P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)&#xD;&#xA;&#xD;&#xA;This is an expression entirely in terms of components of P and Q, which means we're done.  And the final definition you've been waiting for is written below...&#xD;&#xA;&#xD;&#xA;# TL;DR (here's the answer you want)&#xD;&#xA;&#xD;&#xA;Given **R = P ⊙ Q**, we can define the _alpha compose_ operator **⊙** such that:&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;α&lt;/sub&gt; = P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;&#xD;&#xA;&#xD;&#xA;R&lt;sub&gt;L&lt;/sub&gt; = (P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; + Q&lt;sub&gt;L&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; - P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt;)/R&lt;sub&gt;α&lt;/sub&gt; &#xD;&#xA;&#xD;&#xA;Note that our formula for R&lt;sub&gt;L&lt;/sub&gt; is only valid in the case when the alpha values of P and Q are not both zero.  That’s because if the alpha is zero, then the luminance channel can be anything.  Therefore, in the case where R&lt;sub&gt;α&lt;/sub&gt; is zero, we can simply define R&lt;sub&gt;L&lt;/sub&gt; also to be zero.&#xD;&#xA;&#xD;&#xA;Now fortunately, for an RGBA format pixel, by symmetry, we can simply substitute the name “red”, “green” or “blue” for the “luminance” channel in the formulae we derived above.  The RGB streams never cross; the values don’t contaminate each other.  You can work with each colour channel independently.  The red component of a composite operation obviously depends on the red components of both P and Q, but it doesn’t depend on the green or blue channels of the either pixel, but it does depend on the alpha value of both pixels.  Simply substitute L above with R G or B for RGBA formats.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Important: order matters!&#xD;&#xA;&#xD;&#xA;I want to take a moment to observe that the expression for R&lt;sub&gt;α&lt;/sub&gt; has some symmetry, in that it doesn’t seem to matter whether P or Q happens first. But the expression for R&lt;sub&gt;L&lt;/sub&gt; lacks this symmetry.  There’s a term -P&lt;sub&gt;L&lt;/sub&gt; P&lt;sub&gt;α&lt;/sub&gt; Q&lt;sub&gt;α&lt;/sub&gt; that is unbalanced and has a Luminance contribution from P but not Q.  So, this is a big warning that the composition operator we have defined is **not commutative**.  &#xD;&#xA;&#xD;&#xA;P ⊙ Q ≠ Q ⊙ P&#xD;&#xA;&#xD;&#xA;This means that the order in which we blend pixels matters.  More fundamentally, the same thing can be expressed as:&#xD;&#xA;&#xD;&#xA;(B ⊕ P) ⊕ Q ≠ (B ⊕ Q) ⊕ P&#xD;&#xA;&#xD;&#xA;It matters whether you blend P first and then Q second, vs blending Q first and blending P second.  In this regard, the composition operation is unlike regular addition or multiplication where a + b = b + a.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34486" PostHistoryTypeId="50" PostId="11006" RevisionGUID="1a37ed14-daf2-4e04-8b0f-cf221aa57855" CreationDate="2021-08-01T10:03:20.350" UserId="-1" />
  <row Id="34487" PostHistoryTypeId="2" PostId="12096" RevisionGUID="da85ab0f-adbf-47cd-97d5-956911892496" CreationDate="2021-08-01T14:58:00.383" UserId="16989" Text="I have 2 3D surface meshes. These meshes have vertex-correspondence and have the same topology (same edges and triangles connecting the vertices). However, the vertex positions (3d coordinates) are different - that is, the meshes are a vertex deformation of each other. They are pose 1 and pose 2 of the same surface mesh (for example a 3D human or animal).&#xD;&#xA;&#xD;&#xA;I'm looking for ways to interpolate between the 2 poses and generate intermediate poses. A naive way to do this is to linearly interpolate the vertex coordinates of each corresponding vertex between the two meshes, with some small step size, to generate intermediate vertex positions. However, this can cause implausible poses in between as it won't preserve local geometry.&#xD;&#xA;&#xD;&#xA;Another, better way is to find the global transformation matrix for each triangle of poses 1 and 2, then interpolate in the transformation space (the space of 4x4 transformation matrices), and reconstruct the intermediate vertex positions using the interpolated transformations.&#xD;&#xA;&#xD;&#xA;Are there, other better methods, papers that have been published in Siggraph/Cvpr that are known to be better than these naive methods? Can someone link same papers or classical methods that are available for this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34488" PostHistoryTypeId="1" PostId="12096" RevisionGUID="da85ab0f-adbf-47cd-97d5-956911892496" CreationDate="2021-08-01T14:58:00.383" UserId="16989" Text="Methods to interpolate between 2 topologically identical 3D meshes" ContentLicense="CC BY-SA 4.0" />
  <row Id="34489" PostHistoryTypeId="3" PostId="12096" RevisionGUID="da85ab0f-adbf-47cd-97d5-956911892496" CreationDate="2021-08-01T14:58:00.383" UserId="16989" Text="|3d|computational-geometry|mesh|geometry|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34490" PostHistoryTypeId="50" PostId="5996" RevisionGUID="c2389d10-44bb-484f-9c04-dadb4d388300" CreationDate="2021-08-01T15:06:30.617" UserId="-1" />
  <row Id="34491" PostHistoryTypeId="2" PostId="12097" RevisionGUID="607b0ced-805f-481c-885e-0dcb371ed5cd" CreationDate="2021-08-01T18:06:13.883" UserId="16990" Text="I have [Intel T265 camera][1] which has a camera coordinates system like following diagram:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;- The camera system has two cameras and the center of the two cameras is the position of the camera system. &#xD;&#xA;&#xD;&#xA;- The point of my interest is P, which is translated from the position of the camera system by `z0` along z axis, and `x0` along x axis.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What I am given is a series of 4X4 (pose) matrices coming with the camera data looking like:&#xD;&#xA;&#xD;&#xA;        0.9988    0.0175   -0.0466         0&#xD;&#xA;       -0.0195    0.9989   -0.0426         0&#xD;&#xA;        0.0458    0.0434    0.9980         0&#xD;&#xA;       -0.0064   -0.0015   -0.0026    1.0000&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;       -0.1226    0.0055   -0.9924         0&#xD;&#xA;       -0.0438    0.9990    0.0109         0&#xD;&#xA;        0.9915    0.0448   -0.1223         0&#xD;&#xA;       -0.2279   -0.0244    0.1860    1.0000&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;They look like homogenous matrix (following diagram) except that they are transposed version&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now, I have a few questions about this 4x4 matrices:&#xD;&#xA;1. What is the position of the camera at each time point? Are they in these 4x4 matrices?&#xD;&#xA;2. Where exactly is the world coordinates?&#xD;&#xA;3. How do I use these 4X4 matrices to find the projected position of point P in the world coordinates system? &#xD;&#xA;&#xD;&#xA;Or do I misunderstand anything, and how should I use these matrices? Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dev.intelrealsense.com/docs/depth-and-tracking-cameras-alignment&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGDt4.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eNbrK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="34492" PostHistoryTypeId="1" PostId="12097" RevisionGUID="607b0ced-805f-481c-885e-0dcb371ed5cd" CreationDate="2021-08-01T18:06:13.883" UserId="16990" Text="How to get world coordinates from a 4X4 camera matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="34493" PostHistoryTypeId="3" PostId="12097" RevisionGUID="607b0ced-805f-481c-885e-0dcb371ed5cd" CreationDate="2021-08-01T18:06:13.883" UserId="16990" Text="|camera|vector-graphics|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34494" PostHistoryTypeId="5" PostId="12097" RevisionGUID="554bf9a1-352e-442d-bce9-93825413db4e" CreationDate="2021-08-01T18:13:31.073" UserId="16990" Comment="added 220 characters in body" Text="I have [Intel T265 camera][1] which has a camera coordinates system like following diagram:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;- The camera system has two cameras and the center of the two cameras is the position of the camera system. &#xD;&#xA;&#xD;&#xA;- The point of my interest is P, which is translated from the position of the camera system by `z0` along z axis, and `x0` along x axis.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What I am given is a series of 4X4 (pose) matrices coming with the camera data looking like:&#xD;&#xA;&#xD;&#xA;        0.9988    0.0175   -0.0466         0&#xD;&#xA;       -0.0195    0.9989   -0.0426         0&#xD;&#xA;        0.0458    0.0434    0.9980         0&#xD;&#xA;       -0.0064   -0.0015   -0.0026    1.0000&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;       -0.1226    0.0055   -0.9924         0&#xD;&#xA;       -0.0438    0.9990    0.0109         0&#xD;&#xA;        0.9915    0.0448   -0.1223         0&#xD;&#xA;       -0.2279   -0.0244    0.1860    1.0000&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;They look like homogenous matrix (following diagram) except that they are transposed version&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now, I have a few questions about this 4x4 matrices:&#xD;&#xA;1. What is the position of the camera at each time point? Are they in these 4x4 matrices?&#xD;&#xA;2. Where exactly is the world coordinates?&#xD;&#xA;3. How do I use these 4X4 matrices to find the projected position of point P in the world coordinates system? &#xD;&#xA;&#xD;&#xA;Or do I misunderstand anything, and how should I use these matrices? Thank you.&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;I have tried `P_w = M'*P_c`, where `P_c` is the center of the camera system, and `M'` is the transpose of the matrices I am given, but the projected positions do not look right to me when I plot it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dev.intelrealsense.com/docs/depth-and-tracking-cameras-alignment&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGDt4.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eNbrK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="34495" PostHistoryTypeId="2" PostId="12098" RevisionGUID="28bad068-1568-4e0e-a7fd-471a5da648cf" CreationDate="2021-08-02T01:36:27.903" UserId="16421" Text="Suppose we want to convert an RGB image into a paletted image. As an example, we may have a 1024x1024 image, and we want to map it onto 512 unique colors. All the colors are RGB. This is a problem of how to do this efficiently.&#xD;&#xA;&#xD;&#xA;The naive solution would be to go over each color, find the distance from each RGB in the palette array, and then assigning a value to the closest one.&#xD;&#xA;&#xD;&#xA;Problem is this is probably quite slow, for $n$ pixels in some 2D raster with $k$ palette indices, it's $\mathcal{O}(nk)$.&#xD;&#xA;&#xD;&#xA;My next thought was to take a 3D volume where each axis is R, G, and B from 0 - 255, find the average of the points along one axis, partition, and recurse, sort of like how BSP trees are built. For example, I'd find the average and slice along the red axis to partition approximately half of the palette indices into two pieces. Then in the children, I'd do the same averaging for green, and slice along the green axis, and then blue, then red, etc... eventually ending up with a tree where I can walk down it from a color by doing a dot product against the dividing plane or something, and figure out whether to traverse the front or back partitions until I reach a leaf (which would be some palette index).&#xD;&#xA;&#xD;&#xA;This is a common algorithm, I don't know the name of it but I used it in my graphics classes for generating a slicing point for AABB's for models. I figure I'd get approximately $\mathcal{O}(n \lg k)$ (under some assumptions) which would hopefully be somewhat faster. I don't know for sure since I haven't profiled but I'd hope it is.&#xD;&#xA;&#xD;&#xA;This is my idea, but is there another, better way of doing this? Ideally I figure the partitioning idea above would give me the most performance without doing something crazy, but I am unsure if there's a better way of doing it, or if this is _the_ ideal way to do it. That could be a valid answer to this question, as in, &quot;yes you're right, that's the way you should do it.&quot; Likewise, I'm asking because I don't know if there's a better way of doing it, or if I'm doing a needlessly complex step when something I don't need to, or maybe there's a $\mathcal{O}(1)$ algorithm out there that wouldn't be too much more work. &quot;Known unknowns&quot; are why I'm asking.&#xD;&#xA;&#xD;&#xA;Speed does somewhat matter here, so I'm willing to do implement something a bit more ugly if it's something noticeable, especially since there are some users of my application who don't have great computers, and anything I can do on the step that stands out for them (of which this is one of them) would be of help." ContentLicense="CC BY-SA 4.0" />
  <row Id="34496" PostHistoryTypeId="1" PostId="12098" RevisionGUID="28bad068-1568-4e0e-a7fd-471a5da648cf" CreationDate="2021-08-02T01:36:27.903" UserId="16421" Text="Efficient method of mapping any RGB tuple onto a list of RGB indices, is using some kind of partition plane viable?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34497" PostHistoryTypeId="3" PostId="12098" RevisionGUID="28bad068-1568-4e0e-a7fd-471a5da648cf" CreationDate="2021-08-02T01:36:27.903" UserId="16421" Text="|algorithm|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34498" PostHistoryTypeId="2" PostId="12099" RevisionGUID="ad53f95c-1b93-46fb-b3ab-fc8ab5b4f8ff" CreationDate="2021-08-02T06:41:28.577" UserId="16730" Text="When using **Screen Space Direction Occlusion(SSGI)** related techniques, such as **Screen Space Global Illumination(SSGI)**, what is the commonly used attenuation function? I read from some materials that talk about attenuated by $d^2$ ($d$ is the distance between reflect point and receive point), how to explain this attenuation function from the perspective of **PBR** ." ContentLicense="CC BY-SA 4.0" />
  <row Id="34499" PostHistoryTypeId="1" PostId="12099" RevisionGUID="ad53f95c-1b93-46fb-b3ab-fc8ab5b4f8ff" CreationDate="2021-08-02T06:41:28.577" UserId="16730" Text="The attenuation function in SSDO" ContentLicense="CC BY-SA 4.0" />
  <row Id="34500" PostHistoryTypeId="3" PostId="12099" RevisionGUID="ad53f95c-1b93-46fb-b3ab-fc8ab5b4f8ff" CreationDate="2021-08-02T06:41:28.577" UserId="16730" Text="|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34501" PostHistoryTypeId="5" PostId="12099" RevisionGUID="55fe59ed-b7ae-4872-b07f-c9437e506f61" CreationDate="2021-08-02T07:20:27.333" UserId="16730" Comment="edited body" Text="When using **Screen Space Direction Occlusion(SSGO)** related techniques, such as **Screen Space Global Illumination(SSGI)**, what is the commonly used attenuation function? I read from some materials that talk about attenuated by $d^2$ ($d$ is the distance between reflect point and receive point), how to explain this attenuation function from the perspective of **PBR** ." ContentLicense="CC BY-SA 4.0" />
  <row Id="34502" PostHistoryTypeId="5" PostId="12097" RevisionGUID="3e793352-e70c-45ec-8172-0aba10ccd693" CreationDate="2021-08-02T11:17:55.973" UserId="16990" Comment="added 23 characters in body" Text="I have [Intel T265 camera][1] which has a camera coordinates system like following diagram:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;- The camera system has two cameras and the center of the two cameras is the position of the camera system. &#xD;&#xA;&#xD;&#xA;- The point of my interest is P, which is translated from the position of the camera system by `z0` along z axis, and `x0` along x axis.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What I am given is a series of 4X4 (pose) matrices coming with the camera data looking like:&#xD;&#xA;&#xD;&#xA;        0.9988    0.0175   -0.0466         0&#xD;&#xA;       -0.0195    0.9989   -0.0426         0&#xD;&#xA;        0.0458    0.0434    0.9980         0&#xD;&#xA;       -0.0064   -0.0015   -0.0026    1.0000&#xD;&#xA;&#xD;&#xA;or &#xD;&#xA;&#xD;&#xA;       -0.1226    0.0055   -0.9924         0&#xD;&#xA;       -0.0438    0.9990    0.0109         0&#xD;&#xA;        0.9915    0.0448   -0.1223         0&#xD;&#xA;       -0.2279   -0.0244    0.1860    1.0000&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;They look like homogenous matrix (following diagram) except that they are transposed version&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now, I have a few questions about this 4x4 matrices:&#xD;&#xA;1. What is the position of the camera at each time point? Are they in these 4x4 matrices?&#xD;&#xA;2. Where exactly is the world coordinates and how is it oriented?&#xD;&#xA;3. How do I use these 4X4 matrices to find the projected position of point P in the world coordinates system? &#xD;&#xA;&#xD;&#xA;Or do I misunderstand anything, and how should I use these matrices? Thank you.&#xD;&#xA;&#xD;&#xA;-------------&#xD;&#xA;&#xD;&#xA;I have tried `P_w = M'*P_c`, where `P_c` is the center of the camera system, and `M'` is the transpose of the matrices I am given, but the projected positions do not look right to me when I plot it. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dev.intelrealsense.com/docs/depth-and-tracking-cameras-alignment&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGDt4.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eNbrK.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="34503" PostHistoryTypeId="5" PostId="6163" RevisionGUID="739bbea9-2f0c-4c3a-ba0f-d462518b3e62" CreationDate="2021-08-03T12:44:29.750" UserId="6470" Comment="Formatting improved" Text="A perfect Lambert reflector actually reflects light in a cosine distribution - that is, the amount of light per unit area reflected in any given direction $R$ is proportional to $N \cdot R$. The reason the radiance appears constant for all angles is that as the view direction moves away from the normal, the reflected light per unit area decreases, but the surface area per projected beam area (and hence per pixel) increases by the same amount - the cosine factors cancel out.&#xD;&#xA;&#xD;&#xA;Given this distribution, to be energy conserving, the probability density for the reflected light in all possible directions cannot sum to more than 1. If you integrate the cosine function over the whole hemisphere around the normal, you get $\pi$, so this is the normalization factor you need." ContentLicense="CC BY-SA 4.0" />
  <row Id="34504" PostHistoryTypeId="24" PostId="6163" RevisionGUID="739bbea9-2f0c-4c3a-ba0f-d462518b3e62" CreationDate="2021-08-03T12:44:29.750" Comment="Proposed by 6470 approved by 13095 edit id of 568" ContentLicense="CC BY-SA 4.0" />
  <row Id="34505" PostHistoryTypeId="2" PostId="12100" RevisionGUID="4a68ed6d-dff1-45a0-9188-c6d5afa06e97" CreationDate="2021-08-03T18:02:53.463" UserId="17006" Text="I have a mesh stored in .obj format with a texture image in .png format. For any &quot;defined&quot; pixel in the texture image, I'd like to compute the corresponding 3D coordinates when the texture image is mapped to the 3D mesh. For &quot;defined&quot; pixels, I mean the texture pixels that correspond to points on the surface of the mesh, not the texture pixels between the texture patches.&#xD;&#xA;&#xD;&#xA;The .obj file format is as follows:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;v 0.123 0.234 0.345 1.0&#xD;&#xA;v ...&#xD;&#xA;...&#xD;&#xA;vt 0.500 1&#xD;&#xA;vt ...&#xD;&#xA;...&#xD;&#xA;vn 0.707 0.000 0.707&#xD;&#xA;vn ...&#xD;&#xA;...&#xD;&#xA;f 1/1 2/2 3/3&#xD;&#xA;f ...&#xD;&#xA;...&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="34506" PostHistoryTypeId="1" PostId="12100" RevisionGUID="4a68ed6d-dff1-45a0-9188-c6d5afa06e97" CreationDate="2021-08-03T18:02:53.463" UserId="17006" Text="How to map texture pixels to the corresponding 3D positions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34507" PostHistoryTypeId="3" PostId="12100" RevisionGUID="4a68ed6d-dff1-45a0-9188-c6d5afa06e97" CreationDate="2021-08-03T18:02:53.463" UserId="17006" Text="|texture|mesh|uv-mapping|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34508" PostHistoryTypeId="2" PostId="12101" RevisionGUID="0c5d2992-d033-46c0-b43d-efe04c55e97e" CreationDate="2021-08-04T16:49:39.803" UserId="16867" Text="I have been developing a c++, openg, glfw3 and GLEW project on ubuntu and everything has worked so far. Recently I moved to a mac computer (chip M1 if it's important) and things stopped working.&#xD;&#xA;&#xD;&#xA;I have an error on runtime when trying to call `glGenVertexArrays`. The error code is 1282 (0x0502) which according to khronos' wiki means:&#xD;&#xA;&#xD;&#xA;&gt; GL_INVALID_OPERATION, 0x0502&#xD;&#xA;Given when the set of state for a command is not legal for the parameters given to that command. It is also given for commands where combinations of parameters define what the legal parameters are.&#xD;&#xA;&#xD;&#xA;I printed the OpenGL version with `glGetString(GL_VERSION)` and results in: &#xD;&#xA;&#xD;&#xA;&gt; Version 2.1 Metal - 71.0.7&#xD;&#xA;&#xD;&#xA;Then I tried running `glewGetExtension(&quot;GL_ARB_vertex_array_object&quot;)` which returns FALSE. I am not sure, to be honest, what exactly this means but I add it in case it's useful.&#xD;&#xA;&#xD;&#xA;Is there any way of forcing my mac to run OpenGL in a compatible way with my source code? I thought about stop using **vao**s but I am also depending on a library that is supposedly only tested in windows and linux which maybe uses vaos as well. Also, I guess that I probably have problems with other things which don't yet get the chance to run since the program halts on this error.&#xD;&#xA;&#xD;&#xA;To add up, my intention is to have a runnable program in linux and I don't intend on developing for mac. So running a VM with linux should solve the problem. Anyway, if there is a way to also make it work in my macos environment it would be much better." ContentLicense="CC BY-SA 4.0" />
  <row Id="34509" PostHistoryTypeId="1" PostId="12101" RevisionGUID="0c5d2992-d033-46c0-b43d-efe04c55e97e" CreationDate="2021-08-04T16:49:39.803" UserId="16867" Text="OpenGL on mac gives me an error when calling glGenVertexArrays" ContentLicense="CC BY-SA 4.0" />
  <row Id="34510" PostHistoryTypeId="3" PostId="12101" RevisionGUID="0c5d2992-d033-46c0-b43d-efe04c55e97e" CreationDate="2021-08-04T16:49:39.803" UserId="16867" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34511" PostHistoryTypeId="2" PostId="12102" RevisionGUID="37253ce8-e519-44d3-a5bc-e66b2ba83c29" CreationDate="2021-08-04T17:44:07.990" UserId="38" Text="Well, there is no 1:1 correspondence the pixel might be in many locations at once.&#xD;&#xA;&#xD;&#xA;What your asking is relatively easy. Just iterate through each triangle (f). Then get the texture coordinate of each triangle corner (second index in f tells you which vt to look up ). The texture coordinates are in fractions of image so 0.5 0.5 is in middle of image. You need to convert this triangle to a list of pixels. Then for each pixel read the barycentric coordinate, and from barycentric coordinate look up 3D location from vertices (first index of f and v for position in space). done.&#xD;&#xA;&#xD;&#xA;Only like i said what do you do with overlap?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34512" PostHistoryTypeId="50" PostId="11012" RevisionGUID="a010bd39-5575-402f-97d5-78231e0d93eb" CreationDate="2021-08-05T05:07:45.773" UserId="-1" />
  <row Id="34516" PostHistoryTypeId="50" PostId="10378" RevisionGUID="caddcb5b-be69-419a-af71-b2c12ee6d01c" CreationDate="2021-08-05T16:04:55.370" UserId="-1" />
  <row Id="34518" PostHistoryTypeId="2" PostId="12104" RevisionGUID="5f02f0ff-e233-494f-90cc-251cd968b1f4" CreationDate="2021-08-06T09:03:16.150" UserId="11058" Text="I have implemented an algorithm to calculate vertex normals by taking the normalized average of all its adjacent triangles. I have subdivided a cube two times with catmull clark and checked the shading. If you look close at the first image you can have these dark lines than run along the edges of the mesh.&#xD;&#xA;&#xD;&#xA;Is this normal (no pun intented) and have to do with vertex normals being just an approximation of surface normals? If so why exactly does these artifacts occur? Or have I probably done something wrong with how I calculated the normals?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hzQ36.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zBpnH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4clpz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34519" PostHistoryTypeId="1" PostId="12104" RevisionGUID="5f02f0ff-e233-494f-90cc-251cd968b1f4" CreationDate="2021-08-06T09:03:16.150" UserId="11058" Text="Dark line artifact along edges of the shaded mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="34520" PostHistoryTypeId="3" PostId="12104" RevisionGUID="5f02f0ff-e233-494f-90cc-251cd968b1f4" CreationDate="2021-08-06T09:03:16.150" UserId="11058" Text="|opengl|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34521" PostHistoryTypeId="5" PostId="12104" RevisionGUID="747c692f-bf02-4073-b574-2426198e116d" CreationDate="2021-08-06T19:50:53.333" UserId="11058" Comment="added 44 characters in body" Text="I have implemented an algorithm to calculate vertex normals by taking the normalized average of all its adjacent triangles. I have subdivided a cube two times with catmull clark and checked the shading. If you look close at the first image you can have these dark lines than run along the topological edges of the mesh (defined in the second picture).&#xD;&#xA;&#xD;&#xA;Is this normal (no pun intented) and have to do with vertex normals being just an approximation of surface normals? If so why exactly does these artifacts occur? Or have I probably done something wrong with how I calculated the normals?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hzQ36.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/zBpnH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4clpz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34522" PostHistoryTypeId="2" PostId="12105" RevisionGUID="7d3bd771-9ffe-4506-9418-b0a30672cbe2" CreationDate="2021-08-06T22:32:21.893" UserId="13456" Text="There is a slight confusion regarding the attenuation as a phenomenon and attenuation as a function of distance. They are very much related. Basically as you move away from a source of light, the light passing through some sort of medium, looses some of its energy either through absorption or diffraction. This phenomenon is the attenuation, the function computes to what extent this phenomenon is happening, that is to what extent the light looses its energy as it is passing through a medium.&#xD;&#xA;&#xD;&#xA;According to Foley, et. al, Computer Graphics Principles and Practices, 2013, p. 376. You should be using the $1/d^2$ if you want to approximate physical behaviour.&#xD;&#xA;&#xD;&#xA;For non physical behaviour other formulas are also provided for example see, id. p. 383.&#xD;&#xA;&#xD;&#xA;Where does $1/d^2$ come from ?&#xD;&#xA;According to [wikipedia](https://en.wikipedia.org/wiki/Attenuation#Light_attenuation_in_water):&#xD;&#xA;&#xD;&#xA;&gt; Attenuation is linearly dependent on the medium length and attenuation coefficient, as well as – approximately – the frequency of the incident ultrasound beam for biological tissue (while for simpler media, such as air, the relationship is quadratic).&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="34526" PostHistoryTypeId="2" PostId="12106" RevisionGUID="eb5abcf6-bbf5-4ee8-9c5d-dc35c9651478" CreationDate="2021-08-07T15:36:10.330" UserId="17030" Text="I got stuck with a problem: I have two binary images A and B, which differ by a few seconds. There are Blobs in the images which move (imagine a binary image of a lava lamp). Now I calculate the optical flow of those two images (using Lucas Kanade) which results in an &quot;image&quot; containing the motion vectors. As the image is binary, I obviously only get the movement of the outline of the blob.&#xD;&#xA;Now the question: using the GPU (GLSL preferred), how to calculate a prediction of an image C following image B for every pixel? I can use the motion vector of the outline to see where it moved to. But how would I do this for the &quot;inside&quot; pixels where I don't have optical flow information? &#xD;&#xA;&#xD;&#xA;I thought about searching for the edge in the fragment shader but this could possibly involve an excessive amount of texture lookups? Or downsample the image and do the search in the downsampled version to reduce texture lookups? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34527" PostHistoryTypeId="1" PostId="12106" RevisionGUID="eb5abcf6-bbf5-4ee8-9c5d-dc35c9651478" CreationDate="2021-08-07T15:36:10.330" UserId="17030" Text="Binary image blob movement prediction with optical flow" ContentLicense="CC BY-SA 4.0" />
  <row Id="34528" PostHistoryTypeId="3" PostId="12106" RevisionGUID="eb5abcf6-bbf5-4ee8-9c5d-dc35c9651478" CreationDate="2021-08-07T15:36:10.330" UserId="17030" Text="|glsl|motion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34533" PostHistoryTypeId="2" PostId="12108" RevisionGUID="0fce8b7f-913b-4d3d-b275-df173c0b481c" CreationDate="2021-08-08T01:39:03.153" UserId="16927" Text="Suppose I have previously rendered some set of pixels on the screen that each contain one of the following RGB values:&#xD;&#xA;&#xD;&#xA;    0.0 0.0 0.0    in other words, black&#xD;&#xA;    1.0 0.0 0.0    in other words, red&#xD;&#xA;    0.0 0.0 1.0    in other words, blue&#xD;&#xA;    1.0 0.0 1.0    in other words, purple&#xD;&#xA;&#xD;&#xA;Now I want to be able to selectively toggle the red or blue components of what's on the screen to 1.0 or 0.0, without affecting the other color components of what's on the screen. &#xD;&#xA;&#xD;&#xA;For instance, say some pixel contains 1.0, 0.0, 1.0, purple, and I want to turn off the red in that pixel without changing the value of blue.&#xD;&#xA;&#xD;&#xA;Assumption here is at this point I don't know if the blue in that pixel is 0.0 or 1.0. I just want to turn the red part of it off.&#xD;&#xA;&#xD;&#xA;Also, I don't want to have to segregate the red changes from the blue changes into separate sets of vertex attributes, i.e. I'd like to be able to set just the red component of one set of pixels and set the blue component of another set of pixels in one call to glDrawArrays(). Also, within each set of pixels some of the reds I want to be able to set to 1.0 while others I want to set to 0.0 and likewise for the blue.&#xD;&#xA;&#xD;&#xA;I have a hunch this would involve some creative usage of glBlendFunc(), but dang if I can figure out how to do it.&#xD;&#xA;&#xD;&#xA;Note that what I am trying to accomplish here is a poor man's 3D rendering on a typical PC screen using a homemade set of goggles with a red lens for the right eye and a blue lens for the left eye. Think how they did 3D for black and white movies back in the 1950s.&#xD;&#xA;&#xD;&#xA;Anybody got some suggestions?&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34534" PostHistoryTypeId="1" PostId="12108" RevisionGUID="0fce8b7f-913b-4d3d-b275-df173c0b481c" CreationDate="2021-08-08T01:39:03.153" UserId="16927" Text="how to blend RGB components separately" ContentLicense="CC BY-SA 4.0" />
  <row Id="34535" PostHistoryTypeId="3" PostId="12108" RevisionGUID="0fce8b7f-913b-4d3d-b275-df173c0b481c" CreationDate="2021-08-08T01:39:03.153" UserId="16927" Text="|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34539" PostHistoryTypeId="5" PostId="12090" RevisionGUID="12514993-0b4b-481f-a6a9-cd70947c7f60" CreationDate="2021-08-08T08:50:01.650" UserId="5778" Comment="typos corrected" Text="There are many reasons not to merge vertices. Here's a few that I have used:&#xD;&#xA;&#xD;&#xA;1. The file contains many logical objects. If the units don't share vertices they may be separated later for reuse.&#xD;&#xA;2. You can circumvent render engine limitations by modeling. Say your modeling engine only support per vertex normals, but it does not support per face vertex normals. Well the next logical thing is just to split the vertex into two and your engine now does what you want.&#xD;&#xA;3. The vertices happen to coincide but they aren't actually the same vertex. Because it's easier to model the ideal surface than it is to model an actual gap between the edges. Maybe this is so that your skinning can move other side independently from the other or something.&#xD;&#xA;4. You want to make something like selection/partial loading easy in the other engine. Having the vertices arranged in logical chunks makes this easier.&#xD;&#xA;5. Your just dumping out the data as it's presented to you. This makes the translator easy to make. Besides it's not like you necessarily know how the thing should be handled in any case. Just offering something minimal that works. The rest is the user's problem; in many cases good users can live with this and use it to their advantage." ContentLicense="CC BY-SA 4.0" />
  <row Id="34540" PostHistoryTypeId="24" PostId="12090" RevisionGUID="12514993-0b4b-481f-a6a9-cd70947c7f60" CreationDate="2021-08-08T08:50:01.650" Comment="Proposed by 5778 approved by 13095 edit id of 569" ContentLicense="CC BY-SA 4.0" />
  <row Id="34541" PostHistoryTypeId="5" PostId="12106" RevisionGUID="15bb712e-b8e7-45b3-bcc8-cdf54712a074" CreationDate="2021-08-08T11:11:49.290" UserId="17030" Comment="added 93 characters in body" Text="I got stuck with a problem: I have two binary images A and B, which differ by a few seconds. There are Blobs in the images which move (imagine a binary image of a lava lamp). Now I calculate the optical flow of those two images (using Lucas Kanade) which results in an &quot;image&quot; containing the motion vectors. As the image is binary, I obviously only get the movement of the outline of the blob.&#xD;&#xA;Now the question: using the GPU (GLSL preferred), how to calculate a prediction of an image C following image B for every pixel? I can use the motion vector of the outline to see where it moved to. But how would I do this for the &quot;inside&quot; pixels where I don't have optical flow information? &#xD;&#xA;&#xD;&#xA;I thought about searching for the edge in the fragment shader but this could possibly involve an excessive amount of texture lookups? Or downsample the image and do the search in the downsampled version to reduce texture lookups? &#xD;&#xA;&#xD;&#xA;For clarification: There are many blobs in the image. The blobs are not (necessarily) konvex." ContentLicense="CC BY-SA 4.0" />
  <row Id="34543" PostHistoryTypeId="2" PostId="12109" RevisionGUID="59d7424c-7676-4d59-ae48-96a3f0f89490" CreationDate="2021-08-09T13:00:29.647" UserId="17035" Text="I am looking through [this code][1] and seeing two things which confuse me (well, the whole functions does) in the top functions.&#xD;&#xA;&#xD;&#xA;First, `dir * p` where `dir` and `p` are vec3s. What does component wise multiplication of two vec3s give you in geometric terms? The function is clearly meant to give you the maximum distance along a vector to an AABB, but how we got there from a load of point-vector multiplications? I do not know.&#xD;&#xA;&#xD;&#xA;Secondly, `tng = d - dot(d, N) * N`. Here, `d` is the shortest vector between a point and an AABB, and `N` is the point's normal. I can see `tng` is meant to say &quot;tangent&quot;, but I'm not seeing how we got from a normal and an effectively random vector to a tangent to something? &#xD;&#xA;&#xD;&#xA;Also, I have read the papers this code is derived from, and they do not explain it. If anything they would suggest that just `clamp(p, boundMin, boundMax) - p` should be returned.&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/DQLin/RealTimeStochasticLightcuts/blob/c18e888330323917dfb747a8ce53fd8220d45581/RealTimeStochasticLightcuts/Shaders/LightTreeUtilities.hlsli" ContentLicense="CC BY-SA 4.0" />
  <row Id="34544" PostHistoryTypeId="1" PostId="12109" RevisionGUID="59d7424c-7676-4d59-ae48-96a3f0f89490" CreationDate="2021-08-09T13:00:29.647" UserId="17035" Text="Help understanding tangent from dot product and max distance from component wise vector multiplication" ContentLicense="CC BY-SA 4.0" />
  <row Id="34545" PostHistoryTypeId="3" PostId="12109" RevisionGUID="59d7424c-7676-4d59-ae48-96a3f0f89490" CreationDate="2021-08-09T13:00:29.647" UserId="17035" Text="|mathematics|computational-geometry|geometry|shading|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34546" PostHistoryTypeId="2" PostId="12110" RevisionGUID="4c7e9d0b-0a05-4e95-a827-c85432e7fc09" CreationDate="2021-08-09T15:00:48.897" UserId="17037" Text="I've been reading a bit about the graphics pipeline for processing on a graphics card, and I'm interested to know in what kind of format data is passed from the CPU to the GPU when rendering 3D graphics, for example for a video game.&#xD;&#xA;&#xD;&#xA;I understood that the CPU would calculate what's actually going on inside the game each frame, for example it might have some internal representation of the different characters on the screen and maybe calculate some collision detection between them, and then it might move them around a bit and output the change to the GPU. Then the GPU must receive some information corresponding to many different triangles in different locations, and it has rasterize them and add textures and then combine them all together into a HD pixel array.&#xD;&#xA;&#xD;&#xA;So what would be a kind of schematic overview of the form of the data passed to the GPU each frame? I imagine something like a great big array of sets of three points which respond to the vertices of triangles, with associated textures or pointers to textures or something? I expect there would need to be additional information passed each frame as well as the actual triangles and textures, and I'm interested to know what this would be also.&#xD;&#xA;&#xD;&#xA;Also, is there some kind of standard format for this, or does it depend on the hardware?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34547" PostHistoryTypeId="1" PostId="12110" RevisionGUID="4c7e9d0b-0a05-4e95-a827-c85432e7fc09" CreationDate="2021-08-09T15:00:48.897" UserId="17037" Text="What data is passed from the CPU to the GPU each frame?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34548" PostHistoryTypeId="3" PostId="12110" RevisionGUID="4c7e9d0b-0a05-4e95-a827-c85432e7fc09" CreationDate="2021-08-09T15:00:48.897" UserId="17037" Text="|gpu|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34549" PostHistoryTypeId="2" PostId="12111" RevisionGUID="2584ec30-6c58-41d9-b956-61452064ded1" CreationDate="2021-08-09T15:49:20.227" UserId="17038" Text="I am trying a simple passthrough just to get a feel for the geometry shader. I am taking in a single point and trying to output that point from the geometry shader, it works with the vertex and fragment shaders, but when I add in the geometry shader I get no output. There are no compilation errors neither.&#xD;&#xA;&#xD;&#xA;I am using python's moderngl and have it set to render as points with `vao.render(moderngl.POINTS)`. &#xD;&#xA;&#xD;&#xA;**vertex shader**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;in vec3 point;&#xD;&#xA;in vec4 color;&#xD;&#xA;&#xD;&#xA;out vec3 v_point;&#xD;&#xA;out vec4 v_color;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;    v_point = point;&#xD;&#xA;    v_color = color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**geometry shader**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;layout (points) in;&#xD;&#xA;layout (points, max_vertices=1) out;&#xD;&#xA;&#xD;&#xA;in vec3 v_point[1];&#xD;&#xA;in vec4 v_color[1];&#xD;&#xA;&#xD;&#xA;out vec4 g_color;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    gl_Position = vec4(v_point[0], 1.0);&#xD;&#xA;    EmitVertex();&#xD;&#xA;    EndPrimitive();&#xD;&#xA;    g_color = v_color[0];&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**fragment shader**&#xD;&#xA;```&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;in vec4 g_color;&#xD;&#xA;&#xD;&#xA;out vec4 f_color;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    f_color = g_color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34550" PostHistoryTypeId="1" PostId="12111" RevisionGUID="2584ec30-6c58-41d9-b956-61452064ded1" CreationDate="2021-08-09T15:49:20.227" UserId="17038" Text="Opengl geometry shader input point to output point doesn't show any ouput" ContentLicense="CC BY-SA 4.0" />
  <row Id="34551" PostHistoryTypeId="3" PostId="12111" RevisionGUID="2584ec30-6c58-41d9-b956-61452064ded1" CreationDate="2021-08-09T15:49:20.227" UserId="17038" Text="|opengl|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34558" PostHistoryTypeId="5" PostId="12108" RevisionGUID="7e0034f3-8b0f-4a45-bdc3-26f389e55c2e" CreationDate="2021-08-09T21:28:16.610" UserId="16927" Comment="added 4278 characters in body" Text="Suppose I have previously rendered some set of pixels on the screen that each contain one of the following RGB values:&#xD;&#xA;&#xD;&#xA;    0.0 0.0 0.0    in other words, black&#xD;&#xA;    1.0 0.0 0.0    in other words, red&#xD;&#xA;    0.0 0.0 1.0    in other words, blue&#xD;&#xA;    1.0 0.0 1.0    in other words, purple&#xD;&#xA;&#xD;&#xA;Now I want to be able to selectively toggle the red or blue components of what's on the screen to 1.0 or 0.0, without affecting the other color components of what's on the screen. &#xD;&#xA;&#xD;&#xA;For instance, say some pixel contains 1.0, 0.0, 1.0, purple, and I want to turn off the red in that pixel without changing the value of blue.&#xD;&#xA;&#xD;&#xA;Assumption here is at this point I don't know if the blue in that pixel is 0.0 or 1.0. I just want to turn the red part of it off.&#xD;&#xA;&#xD;&#xA;Also, I don't want to have to segregate the red changes from the blue changes into separate sets of vertex attributes, i.e. I'd like to be able to set just the red component of one set of pixels and set the blue component of another set of pixels in one call to glDrawArrays(). Also, within each set of pixels some of the reds I want to be able to set to 1.0 while others I want to set to 0.0 and likewise for the blue.&#xD;&#xA;&#xD;&#xA;I have a hunch this would involve some creative usage of glBlendFunc(), but dang if I can figure out how to do it.&#xD;&#xA;&#xD;&#xA;Note that what I am trying to accomplish here is a poor man's 3D rendering on a typical PC screen using a homemade set of goggles with a red lens for the right eye and a blue lens for the left eye. Think how they did 3D for black and white movies back in the 1950s.&#xD;&#xA;&#xD;&#xA;Anybody got some suggestions?&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;============================================================&#xD;&#xA;&#xD;&#xA;To answer gilgamec's questions:&#xD;&#xA;&#xD;&#xA;&quot;where are the pixels coming from? A texture map? An image? Rendered triangles?&quot;&#xD;&#xA;&#xD;&#xA;The GLSL part of the application consists of a vertex shader and a fragment shader in one GLSL program and a vertex shader that does transform feedback in a second GLSL program. Pairs of vertices are encoded by the host CPU into a vertex attribute array and passed to the first GLSL program for rendering to the screen via a call to glDrawArrays(GL_LINES,...). The same set of vertices is then passed to the second GLSL program whose vertex shader does the same transformations as the first's but then feeds them back to the host CPU.&#xD;&#xA;&#xD;&#xA;&quot;Why can't you alter the input directly?&quot;&#xD;&#xA;&#xD;&#xA;Well, I can. The problem is algorithm running in the host CPU code that generates the vertex pairs is very CPU intensive and thus gets delivered to the GPUs rather slowly. Slow enough that there is a visible delay and there's really no way to speed that up much. It's modelling reflections of images off of sets of mirrors as viewed by some observer that moves around virtually among the set of mirrors. Imagine a big polyhedron made of mirrors with their reflective surfaces facing inward and the observer is standing inside of it along with a light source consisting of a collection of line segments. I've copied a non-steroscopic rendering of it as an example below. Here the mirrored polyhedron is a cube that the observer is standing in. The big red triangle is the single light source and everything else is reflections of reflections of the triangle plus reflections of the edges of the cube in blue. The observer himself is transparent so his head doesn't get in the way of the reflections. 8)&#xD;&#xA;&#xD;&#xA;[![cube][1]][1]&#xD;&#xA;&#xD;&#xA;I can run this program in the usual manner in which on each pass through the main loop the screen is first cleared via glClear(), transform matrices are computed and vertices are rendered via glDrawArrays(GL_LINES...). The problem there is the vertices representing the reflections get generated slowly with large models, so it takes a visible while for rendering to complete. So I've implemented a second mode of operation in which I only clear the screen once at program start up. On each pass through the main loop after glDrawArrays() and the screen buffer swap I copy the front frame buffer to the back buffer. On the next pass through the loop as new reflections come out of the algorithm I use the feed back data from the second GLSL program to &quot;erase&quot; the old reflections from the screen by painting them black in the fragment shader before each new reflection is painted in red or blue. The effect isn't perfect, there's still lag, but the old reflections get sort of dragged along as the observer moves around until they finally get erased and replaced by new reflections once the observer sits still long enough. It's pretty, which is the whole point of this exercise.&#xD;&#xA;&#xD;&#xA;So I've got this second &quot;incremental screen update&quot; mode implemented for non-stereoscopic (1 eyed observer) mode and it works. And I have non-incremental screen mode implemented for red-blue stereoscopic mode, see below:&#xD;&#xA;&#xD;&#xA;[![cube3d][2]][2]&#xD;&#xA;&#xD;&#xA;If you happen to have some red and blue transparent sheets lying around, get in a dark room and look at the above with the red in front of your right eye and the blue in front of your left eye. Relax your eyes a bit and you should be able to perceive the reflections in 3D (at least I can see it and my eyes are 65 years old, 8).&#xD;&#xA;&#xD;&#xA;But to get incremental screen mode to work in 3D, I need to be able to write 0.0 (to erase to black) or 1.0 to the blue component of pixels on the screen without affecting the red and vis-versa. I think I can do that with glColorMask() but that means segregating the vertex attributes corresponding to left eye (blue) perspective from those corresponding to right eye (red) perspective.&#xD;&#xA;&#xD;&#xA;&quot;You mention OpenGL functions, so have you just tried modifying the fragment shader?&quot;&#xD;&#xA;&#xD;&#xA;That's what the question is about. Is there a way to write to only the red or blue components of existing pixels in the frame buffer from a fragment shader?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Z5ity.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/tUKa9.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34560" PostHistoryTypeId="2" PostId="12114" RevisionGUID="ccfe5c3c-699b-4acf-8dc8-dbca67d02b6b" CreationDate="2021-08-10T02:36:48.293" UserId="16730" Text="In PBRT-V3, the light has following spectrum in scene file:&#xD;&#xA;&#xD;&#xA;    &quot;spectrum&quot; [400.0 0.0 500.0 8.0 600.0 15.6 700.0 18.4]&#xD;&#xA;&#xD;&#xA;then it's converted to following RGB in C++:&#xD;&#xA;&#xD;&#xA;    &quot;rgb&quot; [20.7467213 10.8233843 2.76458955]&#xD;&#xA;&#xD;&#xA;is this correct? Why the RGB value exceeds 1? Whether this is used to indicate light intensity?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34561" PostHistoryTypeId="1" PostId="12114" RevisionGUID="ccfe5c3c-699b-4acf-8dc8-dbca67d02b6b" CreationDate="2021-08-10T02:36:48.293" UserId="16730" Text="Why RGB value bigger than 1 when convert from spectrum in PBRT-V3" ContentLicense="CC BY-SA 4.0" />
  <row Id="34562" PostHistoryTypeId="3" PostId="12114" RevisionGUID="ccfe5c3c-699b-4acf-8dc8-dbca67d02b6b" CreationDate="2021-08-10T02:36:48.293" UserId="16730" Text="|pbrt-v3|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34563" PostHistoryTypeId="5" PostId="12114" RevisionGUID="f062042e-cc33-41fe-9cd3-cd651b318c25" CreationDate="2021-08-10T02:49:12.997" UserId="16730" Comment="added 55 characters in body" Text="In PBRT-V3, the light has following spectrum in scene file(Note that the scene file is not come from PBRT itself):&#xD;&#xA;&#xD;&#xA;    &quot;spectrum&quot; [400.0 0.0 500.0 8.0 600.0 15.6 700.0 18.4]&#xD;&#xA;&#xD;&#xA;then it's converted to following RGB in C++:&#xD;&#xA;&#xD;&#xA;    &quot;rgb&quot; [20.7467213 10.8233843 2.76458955]&#xD;&#xA;&#xD;&#xA;is this correct? Why the RGB value exceeds 1? Whether this is used to indicate light intensity?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34565" PostHistoryTypeId="2" PostId="12115" RevisionGUID="b0eb8c22-fdea-4a80-baf0-0fe400b72f9e" CreationDate="2021-08-10T07:47:05.927" UserId="17042" Text="Kinda late on reply, but I'm still gonna post it here for future searches.&#xD;&#xA;&#xD;&#xA;Since all (or many, I'm not sure) macs use Intel GPUs you can use [Intel Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html). It isn't much, but still got frame capture, texture browser etc. and helps debug many errors." ContentLicense="CC BY-SA 4.0" />
  <row Id="34566" PostHistoryTypeId="2" PostId="12116" RevisionGUID="217cdd23-8c4e-4b73-84d4-1a7d23126c4f" CreationDate="2021-08-10T08:56:48.690" UserId="13095" Text="How much data is passed from the CPU to the GPU per frame depends on the engine you are using and its needs. Usually, you want to keep it minimal to avoid that the GPU needs to wait for data because the CPU can't deliver it fast enough. I can not guarantee you, that the following is always the same for all engines and graphic APIs since I have only written OpenGL code myself so far, but to my knowledge, it is quite similar.&#xD;&#xA;&#xD;&#xA;What you usually do is that you send all data that doesn't change to the GPU at the beginning. Objects (meshes) and textures are typical candidates for this. Animated meshes like characters can also be loaded in advance by providing a default position.&#xD;&#xA;&#xD;&#xA;The object data consists of vertices. They are control points that store the position of each point and an arbitrary set of additional information. A typical additional piece of information might be a color, surface normal, or texture coordinate (this does not specify which texture). Note, that there is no information at this point, how those vertices are connected. This is why I put &quot;meshes&quot; into parenthesis in the previous section.&#xD;&#xA;&#xD;&#xA;Now you have a bunch of vertex groups and textures and it is time to render our scene. We assume, that all work that is not related to rendering is done by the CPU. Most of it can also be done by the GPU, but lets keep it simple. &#xD;&#xA;&#xD;&#xA;The CPU calculates where every object is positioned in the current frame, including the camera. It also calculates the skeletal state of our animated characters. Now, to render a single object, we need to provide the following information to the GPU:&#xD;&#xA;&#xD;&#xA;- the object data we want to use&#xD;&#xA;- the textures we want to use&#xD;&#xA;- connectivity of the vertices&#xD;&#xA;- the shader program we want to use&#xD;&#xA;- the data the shader program requires to do its job (usually some transformation matrices and vectors)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The first two are just IDs we got from our API/engine when we uploaded the data. You should know for all your objects, which mesh and texture IDs they use. The third point, connectivity, actually tells the GPU how the single vertices are connected to each other. In OpenGL, there are several ways to specify this. A lot of them assume a specific order in the data, for example that 3 vertices in a row represent a single triangle. But there are also explicit ways by providing an index list to the GPU (This is usually also done at startup).&#xD;&#xA;&#xD;&#xA;Now that the GPU knows which data to use and how it is connected, it needs to know what to do with it. This is done by selecting a shader program.&#xD;&#xA;&#xD;&#xA;Shaders are small programs that run on the GPU. They have several stages that turn your mesh into actual pixels on your screen ([see OpenGL rendering pipeline](https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview)). You usually compile several of them at the beginning when uploading all the other data. Those programs generally also need some additional information to run and you need to pass that to the GPU. What that data is, strongly depends on the effects you want to use, but something you need very often are the transformations needed to place a vertex in relation to the camera and the projection you want to use (perspective, parallel). Now the shader program can calculate each vertex position on the screen, create triangles from it and color each of its pixel as desired (using the textures you specified). You do this for every object in your scene (that is not culled).&#xD;&#xA;&#xD;&#xA;**To sum it up:**&#xD;&#xA;&#xD;&#xA;For a single object in a basic OpenGL engine, you pass the IDs of its vertex data, textures and shader program to the GPU, which are just numbers. Then you pass all data needed by the shader program. This is mostly a bunch of floats for the transformations. Finally, you also tell the GPU how the data is connected for your current &quot;draw call&quot;. There is also not much data transfer involved here, since you either have your data ordered in a specific way and need to tell the GPU just which method to use or you have uploaded a connectivity list upfront and tell the GPU the ID of the index list it should use.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Please note, that the described procedure is based on the approach that is described in most tutorials. Modern engines use several optimization techniques to balance CPU and GPU processing power so that they are always busy. This might require more involved data transfer. Also note, that the data transfer itself has bandwidth limitations that need to be considered. " ContentLicense="CC BY-SA 4.0" />
  <row Id="34567" PostHistoryTypeId="2" PostId="12117" RevisionGUID="5aabe68a-08e6-44d3-b77e-26f7df7b4e50" CreationDate="2021-08-10T12:31:37.087" UserId="7952" Text="The short answer to this question is: **everything**&#xD;&#xA;&#xD;&#xA;On any give frame almost any kind of data my be needed to render that new and wonderful object that just popped into view. It's shader needs to be loaded and compiled, its textures, buffer data, specializations, push constants, if you can dream it up for a render call then it needs to find its way to the GPU on a per frame basis.&#xD;&#xA;&#xD;&#xA;This is the reason GPU's have rich and diverse paths for loading data, along with dedicated hardware and code for handling all the red tape that goes along with it.&#xD;&#xA;&#xD;&#xA;*What is its format*: &#xD;&#xA;Again the answer to this question is: **everything** GPU's handle specialized data types that we don't see on the CPU while doing c/c++/whatever programming. Normalized 8 bit floating point values for example. &#xD;&#xA;&#xD;&#xA;For technology demo's and simple scene's much of that data can be preloaded, but for any program that is going to do meaningful work, expect any kind of data to be loaded on a per frame basis.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Don't imagine *great big arrays*, imagine rich and diverse data. Tutorials will focus on the great big arrays, but they are just the tip of the iceberg.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Finally, don't image the CPU as driving everything. Thanks to compute shaders the GPU is taking more control of the action. " ContentLicense="CC BY-SA 4.0" />
  <row Id="34569" PostHistoryTypeId="2" PostId="12119" RevisionGUID="b53df284-c2d8-4691-9a45-848bc135c8ef" CreationDate="2021-08-11T12:55:31.907" UserId="17046" Text="Not to advertise my own stuff here, but I created a program to do just this. No building from source is needed, simply download and install (you may need to bypass windows smart-screen or similar protection). &#xD;&#xA;See [https://github.com/mikeandike523/SDFBuilder](https://github.com/mikeandike523/SDFBuilder)&#xD;&#xA;&#xD;&#xA;Please be aware:&#xD;&#xA;&#xD;&#xA;- The program taxes your GPU and CPU, so watch for CPU/GPU temperature spikes as well as hot computer surfaces. See the warning in the repo.&#xD;&#xA;- The program normalizes the coordinates of your model, so you should record the size and position of the bounding box of your original model&#xD;&#xA;- See the repo README for additional details and constraints&#xD;&#xA;&#xD;&#xA;I would love to see what you think, and if this fits your needs. My contact info is given on the repo page, and you can also post comments below." ContentLicense="CC BY-SA 4.0" />
  <row Id="34573" PostHistoryTypeId="2" PostId="12121" RevisionGUID="6ada6d88-ad49-4315-9e77-5b36075ec5c6" CreationDate="2021-08-12T12:43:42.643" UserId="7952" Text="There is very little geometrical meaning to the multiplication of two vectors and there are no well defined identities describing the result. But that doesn't make it illegal, and is an important part of many well defined functions such as the dot product. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Multiplication of vectors also have several important identities that allow terms to be moved around in a larger function. And it looks like that is what is going on here. The function this code is in returns the sum of the products after clipping it against the min/max of the bounding box, and contains magnitude and direction. (think dot product)&#xD;&#xA;&#xD;&#xA;The code $tng = d - dot(d, N) * N$ is called vector rejection. That is, find the component of a vector $d$ that is perpendicular to $N$. Vector rejection usually includes a division by $dot(d,d)$ but that can be skipped in some cases. (like if the vector $N$ is normalized).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34577" PostHistoryTypeId="5" PostId="12121" RevisionGUID="5c8bb1f7-8f11-4b15-9726-052e3a6ccec9" CreationDate="2021-08-12T22:41:30.773" UserId="7952" Comment="edited body" Text="There is very little geometrical meaning to the multiplication of two vectors and there are no well defined identities describing the result. But that doesn't make it illegal, and is an important part of many well defined functions such as the dot product. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Multiplication of vectors also have several important identities that allow terms to be moved around in a larger function. And it looks like that is what is going on here. The function this code is in returns the sum of the products after clipping it against the min/max of the bounding box, and contains magnitude and direction. (think dot product)&#xD;&#xA;&#xD;&#xA;The code $tng = d - dot(d, N) * N$ is called vector rejection. That is, find the component of a vector $d$ that is perpendicular to $N$. Vector rejection usually includes a division by $dot(N,N)$ but that can be skipped in some cases. (like if the vector $N$ is normalized).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34579" PostHistoryTypeId="2" PostId="12123" RevisionGUID="7d2b8c83-8683-439d-a65a-e61b8139f65d" CreationDate="2021-08-13T07:29:21.083" UserId="17046" Text="Some curvature artifacts are normal when doing raymarching or ray-tracing. And if you are careful, you can even find curvature artifacts in some rastered scenes if the triangles are small enough.&#xD;&#xA;&#xD;&#xA;It may be that your camera is too close with respect to the size of your cube.&#xD;&#xA;&#xD;&#xA;In the following render, which uses raymarching, the greatest dimension of the box is about 3.2 units. The camera is 4.5 units away from the center of the scene. The fov is 45 degrees, which is the same as in your code:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;It is also important to mention, that in some cases, you won't notice this same distortion effect in raster rendering, since only the vertices of large triangles are distorted, but the edges are always straight.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rSKgt.png&#xD;&#xA;&#xD;&#xA;Also I recommend testing your normal generation. You can do this by making the color of the material equal to the absolute value of the normal." ContentLicense="CC BY-SA 4.0" />
  <row Id="34580" PostHistoryTypeId="50" PostId="9549" RevisionGUID="cc0dc89f-d311-4dcd-bf2c-4f59f1e10022" CreationDate="2021-08-13T13:02:25.200" UserId="-1" />
  <row Id="34581" PostHistoryTypeId="50" PostId="2516" RevisionGUID="a9129775-dd0f-4dfc-84ec-3f0a5c01542e" CreationDate="2021-08-13T15:06:55.577" UserId="-1" />
  <row Id="34585" PostHistoryTypeId="2" PostId="12125" RevisionGUID="1480627d-2b73-40e6-81e9-2aa964db4fe8" CreationDate="2021-08-13T22:07:15.303" UserId="17074" Text="As far as I know, the only options we have for true 3D rendering are polygonal rendering, ray-marching and raytracing/casting. &#xD;&#xA;&#xD;&#xA;Why is that? Surely there must be other ways? Is there some paper somewhere proving that these are the only ways? Is there even anyone working on coming up with a new way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34586" PostHistoryTypeId="1" PostId="12125" RevisionGUID="1480627d-2b73-40e6-81e9-2aa964db4fe8" CreationDate="2021-08-13T22:07:15.303" UserId="17074" Text="Is it possible that a superior, undiscovered 3D rendering method exists?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34587" PostHistoryTypeId="3" PostId="12125" RevisionGUID="1480627d-2b73-40e6-81e9-2aa964db4fe8" CreationDate="2021-08-13T22:07:15.303" UserId="17074" Text="|raytracing|rendering|3d|real-time|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34589" PostHistoryTypeId="2" PostId="12126" RevisionGUID="34e4f03e-5420-47b3-81ec-b96a6382bd36" CreationDate="2021-08-14T00:16:09.680" UserId="17046" Text="In raymarching, it's typical to change the direction of the ray according to the fragment coordinates, but leave the origin at vec3(0,0,0). In you code you add `r`, which is equivalent to vec3(x,y,1) to `ray_pos`, which starts at `vec3(x,y,0)`. You scale x and y properly to lie from 0 to 1. So lets consider the angle of the ray along the x coordinate. Lets say x=1 and y=0 for a given array. If x=1, y=0, and z=1,  then you get a 45 degree fov as desired. In your code, you would add an extra x=1 to your ray direction, leading to a ray direction of X=2, Y=0, and Z=1, which is an fov of 63 degrees. However, the problem is worse, since the &quot;effective fov&quot; will change as X and Y vary, leading to significant distortion. Try using `vec3 ray_pos = cam_pos;` and see if it fixes your problem.&#xD;&#xA;&#xD;&#xA;Other than that&#xD;&#xA;&#xD;&#xA;1. Make sure to separate the tracing code from the shading code&#xD;&#xA;2. Always check your normals&#xD;&#xA;3. In your sphere tracing loop, make sure to add breaking conditions for when the ray intersects the surface (SDF&lt;0.0001 or similar epsilon), or exceeds some max distance (I like 2048.0). This can save you some unnecessary &quot;back and forth&quot; oscillation near the end of your march sequence.&#xD;&#xA;&#xD;&#xA;The following is my ray-marching code:&#xD;&#xA;github.com/mikeandike523/SDFBuilder/blob/main/f1.frag.&#xD;&#xA;&#xD;&#xA;Feel free to even lift code as long as you use it according to GNU GPL 3.0&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;Mike&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34593" PostHistoryTypeId="2" PostId="12128" RevisionGUID="a1d390fa-a9a3-4177-ac21-d238e52b1fb3" CreationDate="2021-08-14T14:20:41.390" UserId="6496" Text="**This question is NOT about the hardware difficulties and shortcomings of tesselation shaders**&#xD;&#xA;&#xD;&#xA;I am trying to understand the motivation behind tesselation shaders.&#xD;&#xA;&#xD;&#xA;Why/when/where tesselation is a good idea?&#xD;&#xA;&#xD;&#xA;Wouldn't the new triangles formed after tesselation lie on the same plane as the original triangle, thus have the same normal? &#xD;&#xA;&#xD;&#xA;How is that going to help the final drawing more realistic?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34594" PostHistoryTypeId="1" PostId="12128" RevisionGUID="a1d390fa-a9a3-4177-ac21-d238e52b1fb3" CreationDate="2021-08-14T14:20:41.390" UserId="6496" Text="Motivation behind tesselation" ContentLicense="CC BY-SA 4.0" />
  <row Id="34595" PostHistoryTypeId="3" PostId="12128" RevisionGUID="a1d390fa-a9a3-4177-ac21-d238e52b1fb3" CreationDate="2021-08-14T14:20:41.390" UserId="6496" Text="|rendering|3d|lighting|physically-based|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34596" PostHistoryTypeId="2" PostId="12129" RevisionGUID="40ed860f-4738-439b-bb53-b310e8fb645f" CreationDate="2021-08-14T15:07:15.210" UserId="17077" Text="You are setting `g_color` after the vertex have been emitted so it will have no effect. `EmitVertex()` will emit the poition and whatever values are current in the out attributes. Set the attribute before emitting the vertex." ContentLicense="CC BY-SA 4.0" />
  <row Id="34597" PostHistoryTypeId="5" PostId="12129" RevisionGUID="c4d6edd0-dd5a-4a2c-9541-1512b0d8da98" CreationDate="2021-08-14T15:13:32.517" UserId="17077" Comment="added 187 characters in body" Text="You are setting `g_color` after the vertex have been emitted so it will have no effect. `EmitVertex()` will emit the poition and whatever values are current in the out attributes. Set the attribute before emitting the vertex.&#xD;&#xA;&#xD;&#xA;The gemometry shader can create geometry by emitting multiple vertices or destroy geometry by not emitting something. This is why the order of the `Emit` functions are very important." ContentLicense="CC BY-SA 4.0" />
  <row Id="34598" PostHistoryTypeId="5" PostId="12111" RevisionGUID="ef60230e-ac01-4565-ac3e-9a9c7444c8dd" CreationDate="2021-08-14T15:33:07.583" UserId="17038" Comment="Added python code" Text="I am trying a simple passthrough just to get a feel for the geometry shader. I am taking in a single point and trying to output that point from the geometry shader, it works with the vertex and fragment shaders, but when I add in the geometry shader I get no output. There are no compilation errors neither.&#xD;&#xA;&#xD;&#xA;I am using python's moderngl and have it set to render as points with `vao.render(moderngl.POINTS)`. &#xD;&#xA;&#xD;&#xA;**vertex shader**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;in vec3 point;&#xD;&#xA;in vec4 color;&#xD;&#xA;&#xD;&#xA;out vec3 v_point;&#xD;&#xA;out vec4 v_color;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;    v_point = point;&#xD;&#xA;    v_color = color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**geometry shader**&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;layout (points) in;&#xD;&#xA;layout (points, max_vertices=1) out;&#xD;&#xA;&#xD;&#xA;in vec3 v_point[1];&#xD;&#xA;in vec4 v_color[1];&#xD;&#xA;&#xD;&#xA;out vec4 g_color;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    gl_Position = vec4(v_point[0], 1.0);&#xD;&#xA;    EmitVertex();&#xD;&#xA;    EndPrimitive();&#xD;&#xA;    g_color = v_color[0];&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**fragment shader**&#xD;&#xA;```&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;in vec4 g_color;&#xD;&#xA;&#xD;&#xA;out vec4 f_color;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    f_color = g_color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**python code:**&#xD;&#xA;&#xD;&#xA;```py&#xD;&#xA;import moderngl&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;from PIL import Image&#xD;&#xA;&#xD;&#xA;ctx = moderngl.create_standalone_context()&#xD;&#xA;&#xD;&#xA;shaders_source = {}&#xD;&#xA;&#xD;&#xA;with open(&quot;vert_test.glsl&quot;, &quot;r&quot;) as f:&#xD;&#xA;    shaders_source['vertex_shader'] = f.read()&#xD;&#xA;&#xD;&#xA;with open(&quot;geom_test.glsl&quot;, &quot;r&quot;) as f:&#xD;&#xA;    shaders_source['geometry_shader'] = f.read()&#xD;&#xA;&#xD;&#xA;with open(&quot;frag_test.glsl&quot;, &quot;r&quot;) as f:&#xD;&#xA;    shaders_source['fragment_shader'] = f.read()&#xD;&#xA;&#xD;&#xA;prog = ctx.program(**shaders_source)&#xD;&#xA;&#xD;&#xA;points = np.array([&#xD;&#xA;    [0.0, 0.0, 0.0, 1, 0, 0, 1],&#xD;&#xA;])&#xD;&#xA;&#xD;&#xA;ctx.enable(moderngl.PROGRAM_POINT_SIZE)&#xD;&#xA;vbo = ctx.buffer(points.astype('f4').tobytes())&#xD;&#xA;vao = ctx.simple_vertex_array(prog, vbo, 'point', 'color')&#xD;&#xA;&#xD;&#xA;fbo = ctx.simple_framebuffer((512, 512))&#xD;&#xA;&#xD;&#xA;fbo.use()&#xD;&#xA;&#xD;&#xA;fbo.clear(0.0, 0.0, 0.0, 1.0)&#xD;&#xA;&#xD;&#xA;vao.render(moderngl.POINTS)&#xD;&#xA;&#xD;&#xA;Image.frombytes('RGB', fbo.size, fbo.read(), 'raw', 'RGB', 0, -1).show()&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34599" PostHistoryTypeId="50" PostId="10748" RevisionGUID="1c97f8d5-8a6b-4fae-a41d-057dc301678b" CreationDate="2021-08-14T16:06:05.580" UserId="-1" />
  <row Id="34600" PostHistoryTypeId="5" PostId="12129" RevisionGUID="e6560a41-b266-44dd-a4c3-2715a75b636f" CreationDate="2021-08-14T16:29:18.650" UserId="17077" Comment="added 302 characters in body" Text="You are setting `g_color` after the vertex have been emitted so it will have no effect. `EmitVertex()` will emit the poition and whatever values are current in the out attributes. Set the attribute before emitting the vertex.&#xD;&#xA;&#xD;&#xA;The gemometry shader can create geometry by emitting multiple vertices or destroy geometry by not emitting something. This is why the order of the `Emit` functions are very important.&#xD;&#xA;&#xD;&#xA;The second issue is that you are enabling `PROGRAM_POINT_SIZE`. This requires the shader to set `gl_PointSize`. If this is not set the behaviour is undefined. Depending on drivers the default point size might be 0 or 1. It seems intel drivers use 0 as the default causing the point to be discarded." ContentLicense="CC BY-SA 4.0" />
  <row Id="34601" PostHistoryTypeId="2" PostId="12130" RevisionGUID="8c88a744-c316-48b4-98b7-9405ab35e596" CreationDate="2021-08-14T18:43:31.763" UserId="13975" Text="I wrote some code which basically computes the color value $c_{t+1,x,y}$ of a pixel at time $t+1$ and position $(x,y)$ by taking adding linear transformations of the values $c_{t,x,y}-c_{t-1,x,y}$, $c_{t,x+1,y}-c_{t,x,y}$ and $c_{t,x,y+1}-c_{t,x,y}$ to $c_{t,x,y}$.  So I kind of solve numerically the PDE $\frac{\partial{f}}{\partial{t}}=A\frac{\partial{f}}{\partial{t}}+B\frac{\partial{f}}{\partial{x}}+C\frac{\partial{f}}{\partial{y}}$ for $3\times 3$ matrices $A,B,C$ if that makes any sense.&#xD;&#xA;&#xD;&#xA;[Here](https://i.stack.imgur.com/Bj4vo.jpg) are some images, which are generated by a slight variation of this concept, working with polar coordinates, but basically what is described above.  The checker pattern rotates and initializes the pixels.  Also there is some Gaussian noise to avoid singularities.&#xD;&#xA;&#xD;&#xA;I just wonder if the patterns, which can be observed in these images, are 'true', in the sense that an analytic solution to that PDE would look similar, or if they stem from numerical artefacts.  Especially, I'd like to know if the patterns would change if I write a program which uses not pixels on a grid but a random Delaunay triangulation of the plane.  Did anyone experiment with something similar?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34602" PostHistoryTypeId="1" PostId="12130" RevisionGUID="8c88a744-c316-48b4-98b7-9405ab35e596" CreationDate="2021-08-14T18:43:31.763" UserId="13975" Text="Zebra-Like Patterns Generated By Linear PDE" ContentLicense="CC BY-SA 4.0" />
  <row Id="34603" PostHistoryTypeId="3" PostId="12130" RevisionGUID="8c88a744-c316-48b4-98b7-9405ab35e596" CreationDate="2021-08-14T18:43:31.763" UserId="13975" Text="|triangulation|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34604" PostHistoryTypeId="5" PostId="12130" RevisionGUID="76121430-279d-4597-a371-01ad6dfde6ec" CreationDate="2021-08-14T18:52:13.740" UserId="13975" Comment="added 41 characters in body" Text="I wrote some code which basically computes the color value $c_{t+1,x,y}$ of a pixel at time $t+1$ and position $(x,y)$ by taking adding linear transformations of the values $c_{t,x,y}-c_{t-1,x,y}$, $c_{t,x+1,y}-c_{t,x,y}$ and $c_{t,x,y+1}-c_{t,x,y}$ to $c_{t,x,y}$.  So I kind of solve numerically the PDE $\frac{\partial{f}}{\partial{t}}=A\frac{\partial{f}}{\partial{t}}+B\frac{\partial{f}}{\partial{x}}+C\frac{\partial{f}}{\partial{y}}$ for $3\times 3$ matrices $A,B,C$ if that makes any sense.&#xD;&#xA;&#xD;&#xA;[Here](https://i.stack.imgur.com/Bj4vo.jpg) are some images, which are generated by a slight [variation](https://codepen.io/fweth/full/VwbNeyG) of this concept, working with polar coordinates, but basically what is described above.  The checker pattern rotates and initializes the pixels.  Also there is some Gaussian noise to avoid singularities.&#xD;&#xA;&#xD;&#xA;I just wonder if the patterns, which can be observed in these images, are 'true', in the sense that an analytic solution to that PDE would look similar, or if they stem from numerical artefacts.  Especially, I'd like to know if the patterns would change if I write a program which uses not pixels on a grid but a random Delaunay triangulation of the plane.  Did anyone experiment with something similar?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34606" PostHistoryTypeId="2" PostId="12131" RevisionGUID="0cec223f-58cf-4f4c-849b-35bafc82b9e7" CreationDate="2021-08-14T20:29:23.863" UserId="48" Text="&gt; Wouldn't the new triangles formed after tesselation lie on the same plane as the original triangle, thus have the same normal?&#xD;&#xA;&#xD;&#xA;No. The domain shader / tessellation evaluation shader can move the new vertices anywhere you like based on shader logic, so the generated surface need not be flat.&#xD;&#xA;&#xD;&#xA;Tessellation can be used to evaluate curved surfaces such as bicubic patches of various kinds, or apply displacement mapping. See [Phong tessellation](https://perso.telecom-paristech.fr/boubek/papers/PhongTessellation/) for an example of this.&#xD;&#xA;&#xD;&#xA;Sometimes, there are also reasons to use tessellation even if you place the generated vertices on the same plane. For example, you can evaluate lighting terms in the domain shader, enabling more detailed lighting than if you did it in the vertex shader, but at less expense than if you did it in the pixel shader. This can be useful for particles, as seen in the presentation [Practical Particle Lighting](https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2012/slides/Programming%20Track/Persson_Tobias_Practical_Particle_Lighting.pdf.pdf) from GDC 2012." ContentLicense="CC BY-SA 4.0" />
  <row Id="34607" PostHistoryTypeId="5" PostId="12128" RevisionGUID="b7d1db4e-67d1-406d-b2a6-ed46192cf162" CreationDate="2021-08-14T21:26:57.853" UserId="6496" Comment="typo" Text="**This question is NOT about the hardware difficulties and shortcomings of tesselation shaders**&#xD;&#xA;&#xD;&#xA;I am trying to understand the motivation behind tesselation shaders.&#xD;&#xA;&#xD;&#xA;Why/when/where tesselation is a good idea?&#xD;&#xA;&#xD;&#xA;Wouldn't the new triangles formed after tesselation lie on the same plane as the original triangle, thus have the same normal? &#xD;&#xA;&#xD;&#xA;How is that going to help the final drawing being more realistic?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34619" PostHistoryTypeId="2" PostId="12134" RevisionGUID="cbef6678-77e3-4c22-9007-7b9133ea519c" CreationDate="2021-08-15T13:39:57.520" UserId="17081" Text="I have a problem that requires Partial Derivative of X and Partial Derivative of Y &#xD;&#xA;&#xD;&#xA;**(Like OpenGL's dFdx() and dFdy() functions.. [OpenGL Registry dFdx](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/dFdx.xhtml))**&#xD;&#xA;&#xD;&#xA;However, the issue is, I dont have access to these functions, and I'm basically writing formulas using Math nodes in blender.&#xD;&#xA;&#xD;&#xA;**What I want to know is, how can I get the Partial Derivative of any point?**&#xD;&#xA;&#xD;&#xA;These are all the pre-existing functions I *can* use:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r1K12.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34620" PostHistoryTypeId="1" PostId="12134" RevisionGUID="cbef6678-77e3-4c22-9007-7b9133ea519c" CreationDate="2021-08-15T13:39:57.520" UserId="17081" Text="How to dynamically calculate the Partial Derivative of any vector?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34621" PostHistoryTypeId="3" PostId="12134" RevisionGUID="cbef6678-77e3-4c22-9007-7b9133ea519c" CreationDate="2021-08-15T13:39:57.520" UserId="17081" Text="|opengl|rendering|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34622" PostHistoryTypeId="6" PostId="12134" RevisionGUID="afdc16c3-10b8-4515-930a-74abe955d666" CreationDate="2021-08-15T16:59:55.707" UserId="2654" Comment="edited tags; edited tags" Text="|rendering|blender|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34623" PostHistoryTypeId="50" PostId="10045" RevisionGUID="2f11d487-0e52-499d-9bff-5b5a5595be76" CreationDate="2021-08-15T21:04:35.450" UserId="-1" />
  <row Id="34624" PostHistoryTypeId="5" PostId="12119" RevisionGUID="555cd887-355f-4dda-b8fd-7c587640d9ae" CreationDate="2021-08-16T05:54:50.760" UserId="17046" Comment="added 1400 characters in body" Text="**EDIT**&#xD;&#xA;I was able to get a simple algorithm working for this purpose, though its not highlight optomized.&#xD;&#xA;&#xD;&#xA;In my implementation, I use sheer brute force, accelerated by GPU. By this, I mean that I get the signed distance function for each triangle to a given point in 3D space, and just take the minimum of those values. I use the signed distance function by Inigo Quilez, https://www.iquilezles.org/www/articles/triangledistance/triangledistance.htm&#xD;&#xA;MAKE SURE TO ADD NON-TRIVIAL THICKNESS to your triangles. `sdf_new=abs(sdf)-thickness`. Otherwise, it will end up near-useless for ray-marching.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, I implement one simple culling trick to make the algorithm a bit faster. Lets say, I have some sample point I want the signed distance value for. Start with an extremely large initial value, for instance, 2048.0 units (call this `Dcurrent`). Then, for each triangle, before calculating the signed distance, calculate the triangle's centroid, and the maximum distance from each vertex of the triangle to the centroid. Call that distance `Dcentroid`. Next, calculate the distance from the centroid of the triangle to the point in question, call this `Dpoint`. If `Dcurrent`&lt;(`Dpoint`-`Dcentroid`), then skip the triangle entirely. This will save you on costly cross-product calculations.&#xD;&#xA;&#xD;&#xA;Why it works:&#xD;&#xA;The current estimate for the SDF (for a given point `P`) represents a &quot;sphere of relevance&quot; around a `P`. The centroid and `Dcentroid` represent the &quot;sphere of relevance&quot; of a given triangle. If the spheres do not overlap, then that triangle will have no influence on the SDF for point `P`." ContentLicense="CC BY-SA 4.0" />
  <row Id="34625" PostHistoryTypeId="5" PostId="12119" RevisionGUID="7ed4a126-c5ec-4ebd-b270-1e8923071992" CreationDate="2021-08-16T06:00:32.970" UserId="17046" Comment="added 1400 characters in body" Text="**EDIT**&#xD;&#xA;I was able to get a simple algorithm working for this purpose, though it's not highly optimized.&#xD;&#xA;&#xD;&#xA;In my implementation, I use sheer brute force, accelerated by GPU. By this, I mean that I get the signed distance function for each triangle to a given point in 3D space, and just take the minimum of those values. I use the unsigned distance function by Inigo Quilez, https://www.iquilezles.org/www/articles/triangledistance/triangledistance.htm&#xD;&#xA;MAKE SURE TO ADD NON-TRIVIAL THICKNESS to your triangle sdf function (thus creating a signed distance function instead of an unsigned one). `sdf=abs(udf)-thickness`. Otherwise, it will end up near-useless for ray-marching.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, I implement one simple culling trick to make the algorithm a bit faster. Lets say, I have some sample point I want the signed distance value for. Start with an extremely large initial value, for instance, 2048.0 units (call this `Dcurrent`). Then, for each triangle, before calculating the signed distance, calculate the triangle's centroid, and the maximum distance from each vertex of the triangle to the centroid. Call that distance `Dcentroid`. Next, calculate the distance from the centroid of the triangle to the point in question, call this `Dpoint`. If `Dcurrent`&lt;(`Dpoint`-`Dcentroid`), then skip the triangle entirely. This will save you on costly cross-product calculations.&#xD;&#xA;&#xD;&#xA;Why it works:&#xD;&#xA;The current estimate for the SDF (for a given point `P`) represents a &quot;sphere of relevance&quot; around a `P`. The centroid and `Dcentroid` represent the &quot;sphere of relevance&quot; of a given triangle. If the spheres do not overlap, then that triangle will have no influence on the SDF for point `P`." ContentLicense="CC BY-SA 4.0" />
  <row Id="34632" PostHistoryTypeId="50" PostId="2146" RevisionGUID="690e757f-d040-471b-b7fc-aa06dee760c6" CreationDate="2021-08-16T09:02:55.303" UserId="-1" />
  <row Id="34636" PostHistoryTypeId="50" PostId="11048" RevisionGUID="8352fa38-8ae2-4d35-aba3-1b8811ff9f2c" CreationDate="2021-08-16T14:03:15.307" UserId="-1" />
  <row Id="34639" PostHistoryTypeId="50" PostId="8886" RevisionGUID="404b5a20-dd24-43c1-abcd-771d4250650f" CreationDate="2021-08-16T16:08:50.873" UserId="-1" />
  <row Id="34640" PostHistoryTypeId="50" PostId="11049" RevisionGUID="6bd75a20-a32e-4e51-8837-c31505e2c242" CreationDate="2021-08-16T17:06:05.460" UserId="-1" />
  <row Id="34649" PostHistoryTypeId="2" PostId="12139" RevisionGUID="ee0fa069-b4b1-4998-bf1e-a5358b7de320" CreationDate="2021-08-17T16:56:27.773" UserId="8125" Text="Under OpenGL 4.5 on `AMD RENOIR (DRM 3.40.0, 5.10.56-1-lts, LLVM 12.0.1)`, running&#xD;&#xA;```&#xD;&#xA;glCreateBuffers(1, &amp;result_buffer);&#xD;&#xA;glNamedBufferData(result_buffer, count * 4, NULL, GL_STATIC_DRAW);&#xD;&#xA;glClearNamedBufferData(result_buffer, GL_R32UI, GL_RED, GL_UNSIGNED_INT, NULL);&#xD;&#xA;```&#xD;&#xA;results in `GL_INVALID_OPERATION in glClearNamedBufferData(integer vs non-integer)`.&#xD;&#xA;&#xD;&#xA;It works fine if I use `GL_R32F`instead, but that is not the format I want here.&#xD;&#xA;&#xD;&#xA;[The spec](https://khronos.org/registry/OpenGL-Refpages/gl4/html/glClearBufferData.xhtml) states that `GL_INVALID_OPERATION` can only occur if `result_buffer` were mapped or not the name of an existing buffer object; neither seems to be the case.&#xD;&#xA;&#xD;&#xA;What am I doing wrong? What is &quot;integer vs non-integer&quot; getting at?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34650" PostHistoryTypeId="1" PostId="12139" RevisionGUID="ee0fa069-b4b1-4998-bf1e-a5358b7de320" CreationDate="2021-08-17T16:56:27.773" UserId="8125" Text="Unexpected INVALID_OPERATION on glClearNamedBufferData" ContentLicense="CC BY-SA 4.0" />
  <row Id="34651" PostHistoryTypeId="3" PostId="12139" RevisionGUID="ee0fa069-b4b1-4998-bf1e-a5358b7de320" CreationDate="2021-08-17T16:56:27.773" UserId="8125" Text="|opengl|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34652" PostHistoryTypeId="2" PostId="12140" RevisionGUID="180cb100-9273-4e18-886f-28c8a2c78517" CreationDate="2021-08-17T18:35:04.547" UserId="2654" Text="[Buffer clears][1] are defined as a form of pixel transfer operation. Essentially, you are specifying data as if you were specifying packed pixel data to be copied. So you must specify the [pixel transfer format and type parameters][2], as well as the &quot;internal format&quot; equivalent to be used in the buffer.&#xD;&#xA;&#xD;&#xA;But this means that all of the rules of pixel transfers apply, *including* the fact that transferring data to an integer internal format must use the `*_INTEGER` pixel transfer formats. That's the mismatch: you have to use `GL_RED_INTEGER` because you're writing to an integer internal format.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Buffer_Object#Clearing&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_transfer_arguments" ContentLicense="CC BY-SA 4.0" />
  <row Id="34654" PostHistoryTypeId="2" PostId="12141" RevisionGUID="1b3fef33-ebf5-4eea-9034-873d779b33c5" CreationDate="2021-08-18T04:52:38.617" UserId="17093" Text="So, I've been learning 3D rendering for more than a year now, and I've read a lot about various rendering techniques and theories, such as PBR, deferred shading, real-time raytracing, BRDF, all that stuff. As far as I know, these topics are either trying to solve the rendering equation, or reduce the computation overhead to boost performance, it's almost always on the side of software, and it seems that shading only cares about finding the color for each pixel. Whatever smart algorithms we use, the most bright pixel on the screen can only be white, we can't have a pixel brighter than `RGB(255,255,255)`, which is not realistic.&#xD;&#xA;&#xD;&#xA;In the real world, human eyes can see much more than just RGBA colors, so I wonder if we can change the pixel brightness in a shader program. To clarify, I'm talking about the screen brightness, brightness of the monitor that we can adjust in hardware settings. For example, each pixel could not only have a color, but also a different brightness value depending on the shader code, is this possible? Just like how we have the depth Z-buffer, I wonder if there's any hardware that supports a B-buffer (brightness buffer)." ContentLicense="CC BY-SA 4.0" />
  <row Id="34655" PostHistoryTypeId="1" PostId="12141" RevisionGUID="1b3fef33-ebf5-4eea-9034-873d779b33c5" CreationDate="2021-08-18T04:52:38.617" UserId="17093" Text="Is it possible to change pixel brightness programmatically?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34656" PostHistoryTypeId="3" PostId="12141" RevisionGUID="1b3fef33-ebf5-4eea-9034-873d779b33c5" CreationDate="2021-08-18T04:52:38.617" UserId="17093" Text="|shading|brightness|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34657" PostHistoryTypeId="50" PostId="8321" RevisionGUID="2183b50b-1ad0-48e6-9e31-5719e0e6ba0b" CreationDate="2021-08-18T07:03:25.463" UserId="-1" />
  <row Id="34658" PostHistoryTypeId="2" PostId="12142" RevisionGUID="ec6eb961-d60e-493f-9770-9449a910cb8d" CreationDate="2021-08-18T07:30:39.307" UserId="17046" Text="I doubt that per-pixel PHYSICAL brightness control is possible. Many computers still use LCD, which uses a single backlight which is spread by optical planes, so there is no per-pixel brightness. Even on LED computers it would be a nightmare to implement variable brightness in hardware.&#xD;&#xA;&#xD;&#xA;One important thing to remember is that when you increase pixel brightness, the blacks will also get brighter. Therefore, gains in contrast due to per-pixel PHYSICAL brightness control may not be predictable.&#xD;&#xA;&#xD;&#xA;If you somehow find any hardware that provides a win32 or similar API for per-pixel PHYSICAL brightness, I doubt it will port to any commonly used devices. There is no standard OpenGL API for this, since I can't even name a device that can do this.&#xD;&#xA;&#xD;&#xA;What you SHOULD LOOK INTO is color transforms. Basically, color is relative. For instance, the black on your computer screen is not PHYSICAL darkness, it is just darker than the other colors. OpenGL will accept RGB values in the range of 0.0 to 1.0 (or 0 to 255), and the hardware determines how they will appear to humans. What a color transform can do is modify the RGB values you feed into OpenGL before it reaches the screen, so it has the appearance of a different color space. For instance, Blender and Unreal Engine both have filmic color transforms that can allow for extremely bright whites (RGB &gt;&gt; 1.0 or 255) without washing out (using a sort of logarithmic scaling). The simplest way to implement a color transform would be in your fragment shader. I do not think OpenGL has in-built color transform pipelines. &#xD;&#xA;&#xD;&#xA;Blender's filmic color transform as well as other color management code uses OpenColorIO: If you are interested, you can google further:&#xD;&#xA;https://docs.blender.org/manual/en/latest/render/color_management.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**NOTE**&#xD;&#xA;Most monitors support sRGB, which is a standard describing a mapping between the 0.0-1.0 range RGB values to physical colors (i.e. red/green/blue sub-pixel physical brightnesses). However, many monitors boast expanded physical color-spaces, with their own transforms. If you are extremely concerned with color fidelity, you may want to look into the color mappings for the monitors you wish to support.&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="34659" PostHistoryTypeId="2" PostId="12143" RevisionGUID="eff19429-7799-4685-a058-2600a6d73e84" CreationDate="2021-08-18T09:21:30.710" UserId="17046" Text="Dear Computer Graphics SE,&#xD;&#xA;&#xD;&#xA;I have a RAYMARCHING renderer, that looks up voxel data from a 3D texture. Each cell in the texture can be 0 or 1. &#xD;&#xA;&#xD;&#xA;I have a very simple algorithm for calculating the signed distance at a given point p in space. Here is some pseudocode&#xD;&#xA;&#xD;&#xA;    Let p be some vec3(x,y,z)&#xD;&#xA;    Let v = value of the 3D texture at point p (or or 1)&#xD;&#xA;    If v == 1:&#xD;&#xA;        sdf=0.0&#xD;&#xA;    If v == 0:&#xD;&#xA;        sdf = cell_width/2.0&#xD;&#xA;&#xD;&#xA;This works fine to find the intersection point between the ray and the voxel grid for raymarching, but this totally messes with the normals. More specifically, normals in +x, +y, +z direction work fine, but normals that should be in the -x, -y, -z directions show up as vec3(0.0) instead.&#xD;&#xA;&#xD;&#xA;Here is my normal algorithm (glsl):&#xD;&#xA;&#xD;&#xA;    vec3 get_normal(vec3 intersection){&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    vec3 axis1 = intersection+vec3(1.0,0.0,0.0)*normal_epsilon;&#xD;&#xA;	    vec3 axis2 = intersection+vec3(0.0,1.0,0.0)*normal_epsilon;&#xD;&#xA;	    vec3 axis3 = intersection+vec3(0.0,0.0,1.0)*normal_epsilon;&#xD;&#xA;&#xD;&#xA;	    float d1 = primary_sdf(axis1);&#xD;&#xA;	    float d2 = primary_sdf(axis2);&#xD;&#xA;	    float d3 = primary_sdf(axis3);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    vec3 n = normalize(vec3(d1,d2,d3));&#xD;&#xA;&#xD;&#xA;	    return n;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the best way to get a good sdf for my voxel field, that won't break the normals?&#xD;&#xA;&#xD;&#xA;I did some digging myself but did not come across any reasonable sources for this problem.&#xD;&#xA;&#xD;&#xA;Links to well-established solutions or peer-reviewed academic papers preffered.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34660" PostHistoryTypeId="1" PostId="12143" RevisionGUID="eff19429-7799-4685-a058-2600a6d73e84" CreationDate="2021-08-18T09:21:30.710" UserId="17046" Text="Ray-Marching: Rendering a Voxel Grid with Proper Normals" ContentLicense="CC BY-SA 4.0" />
  <row Id="34661" PostHistoryTypeId="3" PostId="12143" RevisionGUID="eff19429-7799-4685-a058-2600a6d73e84" CreationDate="2021-08-18T09:21:30.710" UserId="17046" Text="|glsl|voxelization|raymarching|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34662" PostHistoryTypeId="5" PostId="12143" RevisionGUID="85a3416a-5e0a-4b1d-bf7d-29272964ebcb" CreationDate="2021-08-18T09:27:49.613" UserId="17046" Comment="deleted 84 characters in body" Text="Dear Computer Graphics SE,&#xD;&#xA;&#xD;&#xA;I have a RAYMARCHING renderer, that looks up voxel data from a 3D texture. Each cell in the texture can be 0 or 1. &#xD;&#xA;&#xD;&#xA;I have a very simple algorithm for calculating the signed distance at a given point p in space. Here is some pseudocode&#xD;&#xA;&#xD;&#xA;    Let p be some vec3(x,y,z)&#xD;&#xA;    Let v = value of the 3D texture at point p (0 or 1)&#xD;&#xA;    If v == 1:&#xD;&#xA;        sdf=0.0&#xD;&#xA;    If v == 0:&#xD;&#xA;        sdf = cell_width/2.0&#xD;&#xA;&#xD;&#xA;This works fine to find the intersection point between the ray and the voxel grid for raymarching, but this totally messes with the normals. More specifically, normals in +x, +y, +z direction work fine, but normals that should be in the -x, -y, -z directions show up as vec3(0.0) instead.&#xD;&#xA;&#xD;&#xA;Here is my normal algorithm (glsl):&#xD;&#xA;&#xD;&#xA;    vec3 get_normal(vec3 intersection){&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    vec3 axis1 = intersection+vec3(1.0,0.0,0.0)*normal_epsilon;&#xD;&#xA;	    vec3 axis2 = intersection+vec3(0.0,1.0,0.0)*normal_epsilon;&#xD;&#xA;	    vec3 axis3 = intersection+vec3(0.0,0.0,1.0)*normal_epsilon;&#xD;&#xA;&#xD;&#xA;	    float d1 = primary_sdf(axis1);&#xD;&#xA;	    float d2 = primary_sdf(axis2);&#xD;&#xA;	    float d3 = primary_sdf(axis3);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    vec3 n = normalize(vec3(d1,d2,d3));&#xD;&#xA;&#xD;&#xA;	    return n;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the best way to get a good sdf for my voxel field, that won't break the normals?&#xD;&#xA;&#xD;&#xA;I did some digging myself but did not come across any reasonable sources for this problem.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34663" PostHistoryTypeId="5" PostId="12143" RevisionGUID="07269fe0-c220-4f94-8d2c-3b24e8accbe1" CreationDate="2021-08-18T09:55:16.897" UserId="17046" Comment="deleted 92 characters in body" Text="Dear Computer Graphics SE,&#xD;&#xA;&#xD;&#xA;I have a RAYMARCHING renderer, that looks up voxel data from a 3D texture. Each cell in the texture can be 0 or 1. &#xD;&#xA;&#xD;&#xA;I have a very simple algorithm for calculating the signed distance at a given point p in space. Here is some pseudocode&#xD;&#xA;&#xD;&#xA;    Let p be some vec3(x,y,z)&#xD;&#xA;    Let v = value of the 3D texture at point p (0 or 1)&#xD;&#xA;    If v == 1:&#xD;&#xA;        sdf=0.0&#xD;&#xA;    If v == 0:&#xD;&#xA;        sdf = cell_width/2.0&#xD;&#xA;&#xD;&#xA;This works fine to find the intersection point between the ray and the voxel grid for raymarching, but this totally messes with the normals. More specifically, normals in +x, +y, +z direction work fine, but normals that should be in the -x, -y, -z directions show up as vec3(0.0) instead.&#xD;&#xA;&#xD;&#xA;Here is my normal algorithm (glsl):&#xD;&#xA;&#xD;&#xA;    vec3 get_normal(vec3 intersection){&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    vec3 axis1 = intersection+vec3(1.0,0.0,0.0)*normal_epsilon;&#xD;&#xA;	    vec3 axis2 = intersection+vec3(0.0,1.0,0.0)*normal_epsilon;&#xD;&#xA;	    vec3 axis3 = intersection+vec3(0.0,0.0,1.0)*normal_epsilon;&#xD;&#xA;&#xD;&#xA;	    float d1 = primary_sdf(axis1);&#xD;&#xA;	    float d2 = primary_sdf(axis2);&#xD;&#xA;	    float d3 = primary_sdf(axis3);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	    vec3 n = normalize(vec3(d1,d2,d3));&#xD;&#xA;&#xD;&#xA;	    return n;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What is the best way to get a good sdf for my voxel field, that won't break the normals?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34664" PostHistoryTypeId="2" PostId="12144" RevisionGUID="90c409c9-0b3f-4b62-af04-a44a0883349f" CreationDate="2021-08-18T12:31:14.070" UserId="7952" Text="sRGB does have luminance (perceived brightness), and the limitations you express concern about are a display hardware limitation, *not* a limitation of the underlying algorithms we use. PBR algorithms are *not* limited in there ability to compute brightness and color, but display hardware does have limitations, and after computing a value with both luminance and color, it can then be converted to a format that the display hardware is capable of displaying. And there *is* hardware that has extended brightness, which allows graphics programs to show a wider range of color, and brightness.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Many new graphics programmers make the mistake of thinking a *color space* only describes *color*. This is naïve as a color space encodes both color and luminance (the perceived brightness of a light) the sRGB color space was designed many years ago to fit the hardware of the time and its luminance range reflects that. The international standard color space CIE XYZ encodes luminance directly in the Y value, and all standardized color spaces including sRGB have conversion functions that allow them to be converted to and from the CIE XYZ color space. If you want to compute the luminance of any given sRGB value then convert it to CIE XYZ and look at the Y value, you will find that there are many different luminance values that the various sRGB values convert to.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34668" PostHistoryTypeId="50" PostId="8695" RevisionGUID="b87c7df0-218f-4fbd-9f8e-6c8de60c157d" CreationDate="2021-08-18T21:05:15.543" UserId="-1" />
  <row Id="34673" PostHistoryTypeId="50" PostId="10754" RevisionGUID="0946bf80-9b57-46db-9325-ca7cfcecb30d" CreationDate="2021-08-19T20:07:25.633" UserId="-1" />
  <row Id="34674" PostHistoryTypeId="5" PostId="10833" RevisionGUID="a59ab7d9-611c-4d3d-8bd1-4319efbfc2e0" CreationDate="2021-08-20T04:57:28.683" UserId="113" Comment="added 579 characters in body" Text="Foolproof Accurate Way:&#xD;&#xA;&#xD;&#xA;Find the nearest element (vertex, edge, or face). Compute distance to it. Check the angle-weighted psuedonormal to tell if inside or out.&#xD;&#xA;&#xD;&#xA;Brute Force:&#xD;&#xA;&#xD;&#xA;    given a point X inside a mesh&#xD;&#xA;    for every feature of mesh&#xD;&#xA;        compute closest point on feature y&#xD;&#xA;        compute angle-weighted normal at y.&#xD;&#xA;        project (y-x) onto the normal for sign&#xD;&#xA;&#xD;&#xA;You can speed this up with a spatial accelerator (octrees, etc).&#xD;&#xA;&#xD;&#xA;Why the angle-weighted pseudonormal? What is the angle-weighted pseudonormal? There's a whole proof for it: &quot;Signed Distance Computation using the Angle&#xD;&#xA;Weighted Pseudo-normal&quot; by J. Bærentzen.&#xD;&#xA;&#xD;&#xA;Forewarning, there are many approximations to it, as mentioned in the paper, one of the other approaches listed as an answer works for one triangle but suffers edge cases for many triangles.&#xD;&#xA;&#xD;&#xA;There are many such libraries with the implementation if you don't want to write it yourself. VTK has this [ImplicitPolyDataDistance][1]. LibIGL as well [LibIGLs][2]. But there are many light-weight ones to do it as well.&#xD;&#xA;&#xD;&#xA;Faster but often less accurate:&#xD;&#xA;&#xD;&#xA;Scan conversion methods are also very popular and a number of methods fall under this category. Nvidia has a brief for it in GPU Gems [here][3]. Particularly outlining a method to do it fast on the GPU. A similar method exists for Euclidean distance transforms of a voxelized/binarized shape.&#xD;&#xA;&#xD;&#xA;EDIT: Also worth mentioning narrow bands and hierarchical SDFs. Those are very popular as well. Instead of computing SDF values for every element. Say in an image. We can compute SDF values only near the boundary of the shape. With an octree you can compute it at each vertex and interpolate to get inbetween estimates. There are special methods for computing these as well and libraries such as OpenVDB.&#xD;&#xA;&#xD;&#xA;  [1]: https://vtk.org/doc/nightly/html/classvtkImplicitPolyDataDistance.html&#xD;&#xA;  [2]: https://libigl.github.io/tutorial/#signed-distances&#xD;&#xA;  [3]: https://developer.nvidia.com/gpugems/gpugems3/part-v-physics-simulation/chapter-34-signed-distance-fields-using-single-pass-gpu" ContentLicense="CC BY-SA 4.0" />
  <row Id="34675" PostHistoryTypeId="50" PostId="5697" RevisionGUID="1733ad98-734c-4175-a178-bb4619449f70" CreationDate="2021-08-20T06:04:50.417" UserId="-1" />
  <row Id="34676" PostHistoryTypeId="2" PostId="12147" RevisionGUID="b4f536c1-b983-4d33-9a29-4ce3bb274f70" CreationDate="2021-08-20T18:22:11.900" UserId="17104" Text="Just a guess here.&#xD;&#xA;&#xD;&#xA;The minimal physical workgroup on Nvidia GPUs is so-called 'warp', which is 32 threads wide. AMD's so-called 'wavefront' is 64 threads wide. This means, if one of these 32/64 virtual threads goes to memory (boundary condition), all of the rest ones have to wait, because warp performs a single instruction for all of the threads. It is a vector instruction. It's called 'thread divergency&quot;&#xD;&#xA;&#xD;&#xA;Your workgroup is 8x8 which is 64 virtual scalar threads or 1 or 2 real vector threads. This means the warp/wavefront goes to memory twice. The second fetch is less effective, than the first one.&#xD;&#xA;&#xD;&#xA;You can try either expand the workgroup, for example 32x32 threads, or redesign your code to make if fetch the data only once. The out-of-boundary threads may be disabled after the prefetch stage." ContentLicense="CC BY-SA 4.0" />
  <row Id="34682" PostHistoryTypeId="50" PostId="10425" RevisionGUID="0eafcfda-519e-4b5f-b300-a29848546812" CreationDate="2021-08-21T06:07:50.707" UserId="-1" />
  <row Id="34683" PostHistoryTypeId="50" PostId="8721" RevisionGUID="4dac2e38-9107-4c93-a004-7412d63dc58f" CreationDate="2021-08-21T10:04:25.353" UserId="-1" />
  <row Id="34684" PostHistoryTypeId="2" PostId="12148" RevisionGUID="f7daad45-c1fb-47b7-b094-af86d4f7fbcf" CreationDate="2021-08-21T17:54:33.330" UserId="17106" Text="I've encountered this glitch a few times in various video games and other apps with 3D graphics. It causes things to get stretched all the way to the vanishing point of the scene, usually towards the sky. The affected object can seemingly be anything: a model or a part of it, a foliage, a patch of texture, the terrain, anything.&#xD;&#xA;&#xD;&#xA;In video games, these &quot;spikes&quot; don't seem to have physics. Other objects don't collide or interact with them. Which leads me to believe that it's graphics-related. The model affected can move freely, and the stretching always goes to the same point no matter how the model moves around.&#xD;&#xA;&#xD;&#xA;What are they and what causes them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34685" PostHistoryTypeId="1" PostId="12148" RevisionGUID="f7daad45-c1fb-47b7-b094-af86d4f7fbcf" CreationDate="2021-08-21T17:54:33.330" UserId="17106" Text="What is this glitch where objects get stretched to infinity?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34686" PostHistoryTypeId="3" PostId="12148" RevisionGUID="f7daad45-c1fb-47b7-b094-af86d4f7fbcf" CreationDate="2021-08-21T17:54:33.330" UserId="17106" Text="|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34687" PostHistoryTypeId="2" PostId="12149" RevisionGUID="37ad1629-4796-4078-a86d-189058a43197" CreationDate="2021-08-21T18:35:12.007" UserId="48" Text="Hard to say without seeing a visual of the glitch, but what you describe sounds like one or more vertices of the affected model having bad data, or coming out bad from the vertex shader somehow. The bad vertices might be getting some of their components set to extremely large or infinite floating-point values, or their w component set to 0 (which has a similar effect). This would lead to all the triangles attached to that vertex shooting off to infinity somewhere, creating the &quot;stretching&quot; effect.&#xD;&#xA;&#xD;&#xA;If you're seeing this across multiple games and applications, it may be an indicator of bad GPU hardware. If there is a portion of the GPU's memory that doesn't function correctly, it may corrupt data stored there. If that happens to be the vertex buffer of some model, that could create this effect." ContentLicense="CC BY-SA 4.0" />
  <row Id="34688" PostHistoryTypeId="50" PostId="8209" RevisionGUID="bff10635-1572-4e13-890b-49e6af8123ec" CreationDate="2021-08-22T02:03:00.260" UserId="-1" />
  <row Id="34694" PostHistoryTypeId="50" PostId="11074" RevisionGUID="73cdea7a-4e95-4144-b486-2d08e8fb30f7" CreationDate="2021-08-24T00:04:30.473" UserId="-1" />
  <row Id="34695" PostHistoryTypeId="2" PostId="12151" RevisionGUID="d09c3193-5904-4aaa-9c95-7d670d29bb39" CreationDate="2021-08-24T05:30:38.133" UserId="6046" Text="I asked a similar question here before but since the previous post original question was different, I think it was confusing people. So I've voted to close that and asking the new question here. I'm doing a volume rendering project and made a cubic spline editor for transfer function. I used [this](http://graphicsrunner.blogspot.com/2008/05/camera-animation-part-ii.html) as a source which basically uses Wolfram as the main source. Now Wolfram defines a parametric representation. After I made it, I tried to compare it online but the curves are different. The only difference I found is that the online version is using a non-parametric representation.&#xD;&#xA;&#xD;&#xA;Here's mine.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here's the online version&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In order to clarify a bit more on what I'm trying to do. I have 2 variables.&#xD;&#xA;&#xD;&#xA;$X = [0, 255] $&#xD;&#xA;&#xD;&#xA;$Y = [0, 1] $&#xD;&#xA;&#xD;&#xA;For every given $X$ value I need the interpolated $Y$ value. At first glance it seems that the explicit form of cubic spline is what I want. But I have another case where $Y$ values are RGB triplets $(r,g,b)$. Since the parametric representation doesn't have to deal with dimensions and since the code was already online I'm using the parametric form. The parametric form uses the parameter $t \in [0,1]$ for every segment.  &#xD;&#xA;&#xD;&#xA;Now things get a little trickier. Technichally my graph is of $(t, Y(t))$ but as you can see in the first picture the X-axis isn't $t$ but the previously defined $X$ which is in range $[0-255]$. I'm simply rescaling between $X$ and $t$. So if I get $t = 0.5$ for the first segment as an example, I'd take the two bounding control points which resolve to $(0,0)$ and $(141, 0.759)$ in the first picture. Then do simple rescaling like&#xD;&#xA;&#xD;&#xA;$0 + (141 - 0) * t$&#xD;&#xA;&#xD;&#xA;to get my iso-value and plot the graph. Here's how I'm actually drawing the graph&#xD;&#xA;```&#xD;&#xA;float t_step = 1/255.0f;&#xD;&#xA;for(int i = 0; i &lt; knots.size() - 1; i++)&#xD;&#xA;  {&#xD;&#xA;    for (int i_step = 1; i_step &lt;= num_line_segments; i_step++)&#xD;&#xA;    {&#xD;&#xA;        glm::vec2 coord;&#xD;&#xA;        coord.x = knots[i].iso_value + (t_step * i_step * (knots[i+1].iso_value - knots[i].iso_value));&#xD;&#xA;        coord.y = glm::clamp(alpha_spline.getPointOnSpline(t_step * i_step, i).w, v_min.y, v_max.y);&#xD;&#xA;        win-&gt;DrawList-&gt;_Path.push_back(getAbsMousePositionFromPoint(coord) );&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;  &#xD;&#xA;getAbsMousePositionFromPoint(glm::vec2 v)&#xD;&#xA;{&#xD;&#xA;  glm::vec2 v_min(0,0), v_max(255, 1.0)&#xD;&#xA;  glm::vec2 t = (v - v_min) / (v_max - v_min);&#xD;&#xA;  return glm::mix(graph_bot_left, graph_top_right, t);   // both &quot;graph_bot_left&quot; and &quot;graph_top_right&quot; are absolute coordinates of the drawing region&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Basically I need absolute coordinates for drawing anything on the screen. Each segment of the spline is basically drawn as a polyline. Just to be on the safe side I have currently set the number of line segments per curve of the spline to be `255`. This means per segment of the spline I need to draw 255 line segments. I step along `t` then transform it to the proper X-value by doing the transformation step as I told above then find absolute coordinates  from that X-value and draw the segment there.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; ***Now all I wanna know is, do parametric and explicit forms give different curves? If not, then is there something wrong with the rescaling step I'm doing above or something else?***&#xD;&#xA;&#xD;&#xA;P.S :- I've checked the formulation and the boundary conditions of the online one and all  are similar to the Wolfram one. Both mine and the online one are natural cubic splines. I've also double checked my code, even derived the whole parametric form on paper and checked the code with the one derived on paper and it matches perfectly so I'm pretty sure the code isn't wrong. Still [here's](https://github.com/gallickgunner/Volume-Renderer/blob/master/src/CubicSpline.cpp) my spline source as a reference if anybody here knows programming&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yo4am.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fEXlf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34696" PostHistoryTypeId="1" PostId="12151" RevisionGUID="d09c3193-5904-4aaa-9c95-7d670d29bb39" CreationDate="2021-08-24T05:30:38.133" UserId="6046" Text="Cubic Splines - Do Parametric and Explicit representation give different curves?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34697" PostHistoryTypeId="3" PostId="12151" RevisionGUID="d09c3193-5904-4aaa-9c95-7d670d29bb39" CreationDate="2021-08-24T05:30:38.133" UserId="6046" Text="|mathematics|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34699" PostHistoryTypeId="5" PostId="12151" RevisionGUID="4ac7149f-e1a5-42dd-aa3d-23335f4aa7c7" CreationDate="2021-08-24T16:28:03.903" UserId="6046" Comment="added 69 characters in body" Text="I asked a similar question here before but since the previous post original question was different, I think it was confusing people. So I've voted to close that and asking the new question here. I'm doing a volume rendering project and made a cubic spline editor for transfer function. I used [this](http://graphicsrunner.blogspot.com/2008/05/camera-animation-part-ii.html) as a source which basically uses Wolfram as the main source. Now Wolfram defines a parametric representation. After I made it, I tried to compare it online but the curves are different. The only difference I found is that the online version is using a non-parametric representation.&#xD;&#xA;&#xD;&#xA;Here's mine.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here's the online version&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In order to clarify a bit more on what I'm trying to do. I have 2 variables.&#xD;&#xA;&#xD;&#xA;$X = [0, 255] $&#xD;&#xA;&#xD;&#xA;$Y = [0, 1] $&#xD;&#xA;&#xD;&#xA;For every given $X$ value I need the interpolated $Y$ value. At first glance it seems that the explicit form of cubic spline is what I want. But I have another case where $Y$ values are RGB triplets $(r,g,b)$. Since the parametric representation doesn't have to deal with dimensions and since the code was already online I'm using the parametric form. The parametric form uses the parameter $t \in [0,1]$ for every segment.  &#xD;&#xA;&#xD;&#xA;Now things get a little trickier. Technichally my graph is of $(t, Y(t))$ but as you can see in the first picture the X-axis isn't $t$ but the previously defined $X$ which is in range $[0-255]$. I'm simply rescaling between $X$ and $t$. So if I get $t = 0.5$ for the first segment as an example, I'd take the two bounding control points which resolve to $(0,0)$ and $(141, 0.759)$ in the first picture. Then do simple rescaling like&#xD;&#xA;&#xD;&#xA;$0 + (141 - 0) * t$&#xD;&#xA;&#xD;&#xA;to get my iso-value and plot the graph. Here's how I'm actually drawing the graph&#xD;&#xA;```&#xD;&#xA;float t_step = 1/255.0f;&#xD;&#xA;for(int i = 0; i &lt; knots.size() - 1; i++)&#xD;&#xA;  {&#xD;&#xA;    for (int i_step = 1; i_step &lt;= num_line_segments; i_step++)&#xD;&#xA;    {&#xD;&#xA;        glm::vec2 coord;&#xD;&#xA;        coord.x = knots[i].iso_value + (t_step * i_step * (knots[i+1].iso_value - knots[i].iso_value));&#xD;&#xA;        coord.y = glm::clamp(alpha_spline.getPointOnSpline(t_step * i_step, i).w, v_min.y, v_max.y);&#xD;&#xA;        win-&gt;DrawList-&gt;_Path.push_back(getAbsMousePositionFromPoint(coord) );&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;  &#xD;&#xA;getAbsMousePositionFromPoint(glm::vec2 v)&#xD;&#xA;{&#xD;&#xA;  glm::vec2 v_min(0,0), v_max(255, 1.0)&#xD;&#xA;  glm::vec2 t = (v - v_min) / (v_max - v_min);&#xD;&#xA;  return glm::mix(graph_bot_left, graph_top_right, t);   // both &quot;graph_bot_left&quot; and &quot;graph_top_right&quot; are absolute coordinates of the drawing region&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Basically I need absolute coordinates for drawing anything on the screen. Each segment of the spline is basically drawn as a polyline. Just to be on the safe side I have currently set the number of line segments per curve of the spline to be `255`. This means per segment of the spline I need to draw 255 line segments. I step along `t` then transform it to the proper X-value by doing the transformation step as I told above then find absolute coordinates  from that X-value and draw the segment there.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; ***Now all I wanna know is, do parametric and explicit forms give different curves? If not, then is there something wrong with the rescaling step I'm doing above or something else?***&#xD;&#xA;&#xD;&#xA;P.S :- I've checked the formulation and the boundary conditions of the [online][3] one and all  are similar to the Wolfram one. Both mine and the online one are natural cubic splines. I've also double checked my code, even derived the whole parametric form on paper and checked the code with the one derived on paper and it matches perfectly so I'm pretty sure the code isn't wrong. Still [here's](https://github.com/gallickgunner/Volume-Renderer/blob/master/src/CubicSpline.cpp) my spline source as a reference if anybody here knows programming&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yo4am.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fEXlf.png&#xD;&#xA;  [3]: https://timodenk.com/blog/cubic-spline-interpolation/" ContentLicense="CC BY-SA 4.0" />
  <row Id="34700" PostHistoryTypeId="50" PostId="9591" RevisionGUID="d24fb960-92e8-4009-92cc-089dea7656ec" CreationDate="2021-08-25T01:03:45.373" UserId="-1" />
  <row Id="34704" PostHistoryTypeId="50" PostId="8260" RevisionGUID="f6933860-e246-40ea-afd9-04f8689c8ddd" CreationDate="2021-08-26T08:03:30.283" UserId="-1" />
  <row Id="34706" PostHistoryTypeId="50" PostId="10784" RevisionGUID="44c9c61a-26f7-48c2-87fc-ff3eab2cff49" CreationDate="2021-08-27T16:04:05.467" UserId="-1" />
  <row Id="34713" PostHistoryTypeId="50" PostId="11083" RevisionGUID="3a6da4e6-ea67-45c8-a4ac-d51f47fbb593" CreationDate="2021-08-28T02:00:35.073" UserId="-1" />
  <row Id="34714" PostHistoryTypeId="2" PostId="12155" RevisionGUID="2ce23c27-7a61-477d-8437-b4a006269ebb" CreationDate="2021-08-28T02:17:06.280" UserId="482" Text="I'm not sure of the current state of the art, but this style of drawing windows with rounded corners originated in the NeWS graphical environment for Unix workstations. And it was accompanied by an additional nonstandard operator `arcto` into Sun's customized PostScript dialect which was then adopted into PostScript Level 2.&#xD;&#xA;&#xD;&#xA;*x&lt;sub&gt;1&lt;/sub&gt; y&lt;sub&gt;1&lt;/sub&gt; x&lt;sub&gt;2&lt;/sub&gt; y&lt;sub&gt;2&lt;/sub&gt; r* **arcto** *xt&lt;sub&gt;1&lt;/sub&gt; yt&lt;sub&gt;1&lt;/sub&gt; xt&lt;sub&gt;2&lt;/sub&gt; yt&lt;sub&gt;2&lt;/sub&gt;* &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; append tangent arc  &#xD;&#xA;returns the two tangent point coordinates&#xD;&#xA;(*xt&lt;sub&gt;1&lt;/sub&gt;*, *yt&lt;sub&gt;1&lt;/sub&gt;*) and (*xt&lt;sub&gt;2&lt;/sub&gt;*, *yt&lt;sub&gt;2&lt;/sub&gt;*) in user space.&#xD;&#xA;&#xD;&#xA;The usage of this operator can be seen in the example of the similar operator `arct` which does the same drawing but does not return tangent points.&#xD;&#xA;&#xD;&#xA;[![arcto usage snipped from PLRM2][1]][1]&#xD;&#xA;&#xD;&#xA;Changing `arct` to `arcto` in this example would return the points `0 3` and `1 4` while the programmer only needs to specify the points `0 0`, `0 4`, `4 4` and the radius `1`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FdH6B.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34715" PostHistoryTypeId="5" PostId="12155" RevisionGUID="32df653a-5728-455b-9a1b-ee00267a3619" CreationDate="2021-08-28T02:28:17.840" UserId="482" Comment="link to longer example" Text="I'm not sure of the current state of the art, but this style of drawing windows with rounded corners originated in the NeWS graphical environment for Unix workstations. And it was accompanied by an additional nonstandard operator `arcto` into Sun's customized PostScript dialect which was then adopted into PostScript Level 2.&#xD;&#xA;&#xD;&#xA;*x&lt;sub&gt;1&lt;/sub&gt; y&lt;sub&gt;1&lt;/sub&gt; x&lt;sub&gt;2&lt;/sub&gt; y&lt;sub&gt;2&lt;/sub&gt; r* **arcto** *xt&lt;sub&gt;1&lt;/sub&gt; yt&lt;sub&gt;1&lt;/sub&gt; xt&lt;sub&gt;2&lt;/sub&gt; yt&lt;sub&gt;2&lt;/sub&gt;* &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; append tangent arc  &#xD;&#xA;returns the two tangent point coordinates&#xD;&#xA;(*xt&lt;sub&gt;1&lt;/sub&gt;*, *yt&lt;sub&gt;1&lt;/sub&gt;*) and (*xt&lt;sub&gt;2&lt;/sub&gt;*, *yt&lt;sub&gt;2&lt;/sub&gt;*) in user space.&#xD;&#xA;&#xD;&#xA;The usage of this operator can be seen in the example of the similar operator `arct` which does the same drawing but does not return tangent points.&#xD;&#xA;&#xD;&#xA;[![arcto usage snipped from PLRM2][1]][1]&#xD;&#xA;&#xD;&#xA;Changing `arct` to `arcto` in this example would return the points `0 3` and `1 4` while the programmer only needs to specify the points `0 0`, `0 4`, `4 4` and the radius `1`.&#xD;&#xA;&#xD;&#xA;I was given a longer usage example that draws a full rectangle (er ... *rectar*) when I asked about this operator in [comp.lang.postscript](https://groups.google.com/g/comp.lang.postscript/c/AvLVpYr2TuE/m/PjQgDUUlBwAJ)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FdH6B.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34716" PostHistoryTypeId="5" PostId="12155" RevisionGUID="cc47b064-d704-4266-919e-baf588ba5824" CreationDate="2021-08-28T04:30:53.320" UserId="482" Comment="added 324 characters in body" Text="I'm not sure of the current state of the art, but this style of drawing windows with rounded corners originated in the NeWS graphical environment for Unix workstations. And it was accompanied by an additional nonstandard operator `arcto` into Sun's customized PostScript dialect which was then adopted into PostScript Level 2.&#xD;&#xA;&#xD;&#xA;*x&lt;sub&gt;1&lt;/sub&gt; y&lt;sub&gt;1&lt;/sub&gt; x&lt;sub&gt;2&lt;/sub&gt; y&lt;sub&gt;2&lt;/sub&gt; r* **arcto** *xt&lt;sub&gt;1&lt;/sub&gt; yt&lt;sub&gt;1&lt;/sub&gt; xt&lt;sub&gt;2&lt;/sub&gt; yt&lt;sub&gt;2&lt;/sub&gt;* &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; append tangent arc  &#xD;&#xA;returns the two tangent point coordinates&#xD;&#xA;(*xt&lt;sub&gt;1&lt;/sub&gt;*, *yt&lt;sub&gt;1&lt;/sub&gt;*) and (*xt&lt;sub&gt;2&lt;/sub&gt;*, *yt&lt;sub&gt;2&lt;/sub&gt;*) in user space.&#xD;&#xA;&#xD;&#xA;The usage of this operator can be seen in the example of the similar operator `arct` which does the same drawing but does not return tangent points.&#xD;&#xA;&#xD;&#xA;[![arcto usage snipped from PLRM2][1]][1]&#xD;&#xA;&#xD;&#xA;Changing `arct` to `arcto` in this example would return the points `0 3` and `1 4` while the programmer only needs to specify the points `0 0`, `0 4`, `4 4` and the radius `1`.&#xD;&#xA;&#xD;&#xA;I was given a longer usage example that draws a full rectangle (er ... *rectar*) when I asked about this operator in [comp.lang.postscript](https://groups.google.com/g/comp.lang.postscript/c/AvLVpYr2TuE/m/PjQgDUUlBwAJ).&#xD;&#xA;&#xD;&#xA;So, a broader answer to the question is that rounded corners can be handled at the vector graphics level, pre-rendering. You can insert arc segments in the places where the corners would be into a path and then either stroke or fill the result and apply any anti-aliasing or blurring effects at the rasterization stage.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FdH6B.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34717" PostHistoryTypeId="2" PostId="12156" RevisionGUID="23f75c9a-4804-47ab-a690-d133c4c10865" CreationDate="2021-08-28T09:19:58.263" UserId="17129" Text="OpenGL version `2.1` does not support vertex arrays (vaos), you need OpenGL version `3.0+`. Try invoking a core profile and see if that helps. If not then your version might be maxed out at version `2.1` as Apple does not really support OpenGL well (And especially since your graphics card is directly vendored from Apple). Also a handy tip would to consider Apple's built in graphics API, `Metal`, because they have dedicated to supporting this graphics API." ContentLicense="CC BY-SA 4.0" />
  <row Id="34718" PostHistoryTypeId="2" PostId="12157" RevisionGUID="0619dcc0-a0cb-4154-b77f-311f3fe8412a" CreationDate="2021-08-28T13:59:51.367" UserId="17130" Text="Vertices of each LOD Version is always loaded on VRAM?         &#xD;&#xA;I know Many game engines have feature what Mesh Vertices and Textures LOD.    &#xD;&#xA;I'm just wondering if All vertices and textures of all(each) LOD version is always loaded on VRAM or loaded at that time each LOD version is selected" ContentLicense="CC BY-SA 4.0" />
  <row Id="34719" PostHistoryTypeId="1" PostId="12157" RevisionGUID="0619dcc0-a0cb-4154-b77f-311f3fe8412a" CreationDate="2021-08-28T13:59:51.367" UserId="17130" Text="Vertices of each LOD Version is always loaded on VRAM" ContentLicense="CC BY-SA 4.0" />
  <row Id="34720" PostHistoryTypeId="3" PostId="12157" RevisionGUID="0619dcc0-a0cb-4154-b77f-311f3fe8412a" CreationDate="2021-08-28T13:59:51.367" UserId="17130" Text="|rendering|mesh|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34721" PostHistoryTypeId="2" PostId="12158" RevisionGUID="31412125-e259-4c0f-98e6-e646b8f0bc13" CreationDate="2021-08-28T14:10:28.333" UserId="13273" Text="I am working on a software with lots of different shaders, which require different states in OpenGL.&#xD;&#xA;My problem is the following:&#xD;&#xA;The different models with different shaders are not rendered in the same order, so there is a switch form shader1 to shader23 to shader2 and so on. In the next frame this order can change (depending on the scenario). When I am adding a new kind of object (with new shader and so on) and I think it is working, I need to check every order of object-rendering to see, if bugs appear.&#xD;&#xA;With bugs I mean OpenGL states which are set to a specific value and later not changed back.&#xD;&#xA;How do you handle this?&#xD;&#xA;&#xD;&#xA;I have the idea, to create a OpenGL state class where you can define each parameter. When running an render method, the current state will be compared with the OpenGL state and each setting which is different should be set to the state will is required for this rendering.&#xD;&#xA;&#xD;&#xA;This seems to me more than a few lines of code... The most hardest part is to figure out which states are saved in which OpenGL table (with table I mean VAO, FBO, Texture, ...). Where can I find a table very good described where each OpenGL state will be saved? &#xD;&#xA;&#xD;&#xA;I mean: when binding Shader1 and setting uniform &quot;test&quot; to value &quot;123&quot; and then binding Shader2, the uniform there also named &quot;test&quot; will not have the value &quot;123&quot;... so the uniform values are somehow stored on shader level?? Same with attributepointer and VAO...&#xD;&#xA;&#xD;&#xA;On the other hand: PointSize is not stored on shader level... so each time I am rendering Points, I need to check which size they have and change it to the required size.&#xD;&#xA;&#xD;&#xA;Can someone give me some URL to a table of OpenGL states?&#xD;&#xA;&#xD;&#xA;Does someone has a better idea to handle this problem? BTW: I am not the only one who is working on this software... so saying &quot;every time when changing a state, change it back at the end of the method&quot; will not work.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34722" PostHistoryTypeId="1" PostId="12158" RevisionGUID="31412125-e259-4c0f-98e6-e646b8f0bc13" CreationDate="2021-08-28T14:10:28.333" UserId="13273" Text="OpenGL state management" ContentLicense="CC BY-SA 4.0" />
  <row Id="34723" PostHistoryTypeId="3" PostId="12158" RevisionGUID="31412125-e259-4c0f-98e6-e646b8f0bc13" CreationDate="2021-08-28T14:10:28.333" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34727" PostHistoryTypeId="2" PostId="12160" RevisionGUID="9bd9582d-e0b7-4037-8813-8913957741e9" CreationDate="2021-08-29T01:00:34.130" UserId="48" Text="Many game engines have _texture streaming_, which means that not all mip levels of each texture are loaded at all times. The game engine will track which textures are in view and how close up they are seen, and will dynamically load and unload mip levels in an attempt to provide enough detail for the current view, while staying within a fixed VRAM budget.&#xD;&#xA;&#xD;&#xA;This is done because typically with AAA game content on a consumer GPU, there is not enough VRAM to load all mips of all textures at once. Usually, the highest few mip levels (low resolutions) of all textures are loaded all the time, and the lower mips (high resolutions) are streamed.&#xD;&#xA;&#xD;&#xA;Some game engines also have mesh LOD streaming, though it is less common. Mesh data (vertices and indices) typically takes up much less VRAM than textures, so there is less impetus to do mesh LOD streaming. Still, with highly detailed meshes, the most detailed LODs can be a substantial size and it can make sense to stream those. This can be done analogously to how texture mip levels are streamed.&#xD;&#xA;&#xD;&#xA;There is also UE5 Nanite which uses a cluster-based LOD system and streams trees of clusters instead of whole mesh LODs." ContentLicense="CC BY-SA 4.0" />
  <row Id="34728" PostHistoryTypeId="50" PostId="9319" RevisionGUID="500e099f-0ae6-42e0-8119-a3ed39225062" CreationDate="2021-08-29T15:01:50.083" UserId="-1" />
  <row Id="34729" PostHistoryTypeId="5" PostId="2296" RevisionGUID="6c6ee21f-a812-4626-853d-80a7a74a9eea" CreationDate="2021-08-29T18:38:51.487" UserId="48" Comment="update answer for d3d11/12 differences" Text="The short answer is It's Complicated™. :)&#xD;&#xA;&#xD;&#xA;A lot of factors can affect frame timing (and the associated problem of animation juddering, due to the game's animation delta-times not matching actual frame delivery times). Some of the factors are: how CPU-limited versus GPU-limited the game is, how the game's code measures time, how much variability there is in frame time on both the CPU and GPU, how many frames of queue-ahead the CPU is allowed to build up, double versus triple buffering, and driver behavior.&#xD;&#xA;&#xD;&#xA;On the specific question of whether you get locked to a divisor of 60 fps (30, 20, 15, etc), this seems to depend mainly on whether the application is GPU-limited or CPU-limited. If you're GPU-limited, then assuming the application is running steadily (not producing any hitches or rapid performance shifts in itself), it does lock to the highest divisor of the vsync rate that it can sustain. This timing diagram shows how it works:&#xD;&#xA;&#xD;&#xA;![vsync in GPU limited case][1]&#xD;&#xA;&#xD;&#xA;Time runs from left to right and the width of each block represents the duration of one frame's work. After the first few frames, the system settles into a state where the frames are turned out at a steady rate, one every two vsync periods (i.e. if vsync was 60 Hz, the game would be running at exactly 30 fps).&#xD;&#xA;&#xD;&#xA;Note the empty spaces (idle time) in both CPU and GPU rows. That indicates that the game could run faster if vsync were turned off. However, with vsync on, the swapchain puts back-pressure on the GPU&amp;mdash;the GPU can't start rendering the next frame until vsync releases a backbuffer for it to render into. The GPU in turn puts back-pressure on the CPU via the command queue, as the driver won't return from `Present()` / `SwapBuffers()` until the GPU starts rendering the next frame, and opens a queue slot for the CPU to continue issuing commands. (**EDIT:** The preceding remark applies to D3D11 and OpenGL. In D3D12 and Vulkan, `Present()` works differently, and the CPU must wait on fences from command queues in order to get back-pressure.) The result is that everything runs at a steady 30 fps rate, and everyone's happy (except maybe the 60fps purist gamer ).&#xD;&#xA;&#xD;&#xA;Compare this to what happens when the application is CPU-limited:&#xD;&#xA;&#xD;&#xA;![vsync in CPU-limited case][2]&#xD;&#xA;&#xD;&#xA;This time we ended up with the game running at 36 fps, the maximum speed possible given the CPU load in this case. But this isn't a divisor of the refresh rate, so we get uneven frame delivery to the display, with some frames shown for two vsync periods and some for only one. This will cause judder.&#xD;&#xA;&#xD;&#xA;Here the GPU goes idle because it's waiting for the CPU to give it more work&amp;mdash;not because it's waiting for a backbuffer to be available to render into. The swapchain thus doesn't put back-pressure on the GPU (or at least doesn't do so consistently), and the GPU in turn doesn't put back-pressure on the CPU. So the CPU just runs as fast as it can, oblivious to the irregular frame times appearing on the display.&#xD;&#xA;&#xD;&#xA;It's possible to &quot;fix&quot; this so that the game still discretizes to vsync-friendly rates even in the CPU-limited case. The game code could try to recognize this situation and compensate by sleeping its CPU thread to artificially lock itself to 30 fps, or by increasing its swap interval to 2. Alternatively, the driver could do the same thing by inserting extra sleeps in `Present()` / `SwapBuffers()` (the NVIDIA drivers do have this as a control panel option; I don't know about others). But in any case, _someone_ has to detect the problem and do something about it; the game won't naturally settle on a vsync-friendly rate the way it does when it's GPU-limited.&#xD;&#xA;&#xD;&#xA;This was all a simplified case in which both CPU and GPU workloads are perfectly steady. In real life, of course, there's variability in the workloads and frame times, which can cause even more interesting things to happen. The CPU render-ahead queue and triple buffering can come into play then.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Rm3tV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mXZJo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34731" PostHistoryTypeId="5" PostId="12157" RevisionGUID="868118ae-e337-46ff-96cf-a391d506944e" CreationDate="2021-08-30T06:43:31.587" UserId="13095" Comment="Fix grammar" Text="Are vertices of each LOD version always loaded into VRAM?         &#xD;&#xA;I know many game engines have a LOD feature for mesh vertices and textures.    &#xD;&#xA;I'm just wondering if all vertices and textures of all(each) LOD versions are always loaded in VRAM or are they loaded at the time each LOD version is selected." ContentLicense="CC BY-SA 4.0" />
  <row Id="34732" PostHistoryTypeId="4" PostId="12157" RevisionGUID="868118ae-e337-46ff-96cf-a391d506944e" CreationDate="2021-08-30T06:43:31.587" UserId="13095" Comment="Fix grammar" Text="Are vertices of each LOD version always loaded into VRAM" ContentLicense="CC BY-SA 4.0" />
  <row Id="34733" PostHistoryTypeId="2" PostId="12161" RevisionGUID="8e8ce3cc-0b51-4ff6-8823-f0c664e01aa3" CreationDate="2021-08-30T07:48:40.340" UserId="16730" Text="I'm reading the article [Sampling microfacet BRDF](https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/). &#xD;&#xA;&#xD;&#xA;The GGX function is $D(h)$, the articles says the PDF respecting the spherical coordinates is $P_1(\theta)=D(h)Cos(\theta)Sin(\theta)$. But I think the PDF(in spherical coordinates) is $P_2(\theta)=D(h)Cos(\theta)$, where the term $Sin(\theta)$ is the Jacobian of integrator. &#xD;&#xA;&#xD;&#xA;Another intuitive feeling is that $P_1(0)=0$, $P_2(0)=D(h)$. I think $P_2$ seems more reasonable.&#xD;&#xA;&#xD;&#xA;Is my understanding correct? Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="34734" PostHistoryTypeId="1" PostId="12161" RevisionGUID="8e8ce3cc-0b51-4ff6-8823-f0c664e01aa3" CreationDate="2021-08-30T07:48:40.340" UserId="16730" Text="PDF of BRDF respecting the spherical coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="34735" PostHistoryTypeId="3" PostId="12161" RevisionGUID="8e8ce3cc-0b51-4ff6-8823-f0c664e01aa3" CreationDate="2021-08-30T07:48:40.340" UserId="16730" Text="|rendering|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34736" PostHistoryTypeId="5" PostId="12161" RevisionGUID="2e5d24d1-f8c9-40f4-93b1-7f8db8aaaf7b" CreationDate="2021-08-30T07:54:50.270" UserId="16730" Comment="added 70 characters in body" Text="I'm reading the article [Sampling microfacet BRDF](https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/). &#xD;&#xA;&#xD;&#xA;The GGX function is $D(h)$, the articles says the PDF respecting the spherical coordinates is $P_1(\theta)=D(h)Cos(\theta)Sin(\theta)$. But I think the PDF(in spherical coordinates) is $P_2(\theta)=D(h)Cos(\theta)$, where the term $Sin(\theta)$ is the Jacobian of integrator. Note that $\theta$ is the angle between normal vector and half vector.&#xD;&#xA;&#xD;&#xA;Another intuitive feeling is that $P_1(0)=0$, $P_2(0)=D(h)$. I think $P_2$ seems more reasonable.&#xD;&#xA;&#xD;&#xA;Is my understanding correct? Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="34737" PostHistoryTypeId="50" PostId="9178" RevisionGUID="7a257253-30b8-4b75-b8c9-848721db4f6d" CreationDate="2021-08-30T14:06:30.547" UserId="-1" />
  <row Id="34738" PostHistoryTypeId="2" PostId="12162" RevisionGUID="e7e380d5-a0c7-4724-beef-b7ea518d2608" CreationDate="2021-08-30T18:56:18.407" UserId="48" Text="The pdf with respect to solid angle (area on the sphere) is $D(h) \cos \theta \, \mathrm{d}\omega$, but then when you go to sample it in terms of spherical coordinates, you must include the $\sin \theta$ factor.&#xD;&#xA;$$&#xD;&#xA;\mathrm{d}\omega = \sin \theta \, \mathrm{d}\theta \, \mathrm{d}\phi&#xD;&#xA;$$&#xD;&#xA;If you imagine choosing sample points uniformly in $(\theta, \phi)$ space, then they would concentrate at the pole, and so you would need to weight down by $\sin \theta$ to compensate for that and get points that are uniform in area on the sphere.&#xD;&#xA;&#xD;&#xA;For importance-sampling the NDF, with an isotropic NDF like this the $\phi$ parameter is just chosen uniformly from $[0, 2\pi]$, and then the remaining $P(\theta)$ does need to include the $\sin \theta$ factor, otherwise you would have too many points close to the pole. It is true that $P(0) = 0$; that is correct because a $\mathrm{d}\phi$-wide sliver comes to have zero width at the pole, and so the density in $(\theta, \phi)$ space has to come to zero there." ContentLicense="CC BY-SA 4.0" />
  <row Id="34740" PostHistoryTypeId="2" PostId="12163" RevisionGUID="3380ecf1-9556-4a5f-81db-906e02ea437b" CreationDate="2021-08-31T13:32:23.530" UserId="17139" Text="When attempting to compute the gradient noise derivatives Iäve seen the use of a function named &quot;hash&quot; and I don't understand its purpose (nor why they have commented that it should be replaced by something better): [link][1] &#xD;&#xA;&#xD;&#xA;Code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec2 hash( in vec2 x )  // replace this by something better&#xD;&#xA;    {&#xD;&#xA;        const vec2 k = vec2( 0.3183099, 0.3678794 );&#xD;&#xA;        x = x*k + k.yx;&#xD;&#xA;        return -1.0 + 2.0*fract( 16.0 * k*fract( x.x*x.y*(x.x+x.y)) );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // return gradient noise (in x) and its derivatives (in yz)&#xD;&#xA;    vec3 noised( in vec2 p )&#xD;&#xA;    {&#xD;&#xA;        vec2 i = floor( p );&#xD;&#xA;        vec2 f = fract( p );&#xD;&#xA;    &#xD;&#xA;    #if 1&#xD;&#xA;        // quintic interpolation&#xD;&#xA;        vec2 u = f*f*f*(f*(f*6.0-15.0)+10.0);&#xD;&#xA;        vec2 du = 30.0*f*f*(f*(f-2.0)+1.0);&#xD;&#xA;    #else&#xD;&#xA;        // cubic interpolation&#xD;&#xA;        vec2 u = f*f*(3.0-2.0*f);&#xD;&#xA;        vec2 du = 6.0*f*(1.0-f);&#xD;&#xA;    #endif    &#xD;&#xA;        &#xD;&#xA;        vec2 ga = hash( i + vec2(0.0,0.0) );&#xD;&#xA;        vec2 gb = hash( i + vec2(1.0,0.0) );&#xD;&#xA;        vec2 gc = hash( i + vec2(0.0,1.0) );&#xD;&#xA;        vec2 gd = hash( i + vec2(1.0,1.0) );&#xD;&#xA;        &#xD;&#xA;    float va = dot( ga, f - vec2(0.0,0.0) );&#xD;&#xA;    float vb = dot( gb, f - vec2(1.0,0.0) );&#xD;&#xA;    float vc = dot( gc, f - vec2(0.0,1.0) );&#xD;&#xA;    float vd = dot( gd, f - vec2(1.0,1.0) );&#xD;&#xA;&#xD;&#xA;    return vec3( va + u.x*(vb-va) + u.y*(vc-va) + u.x*u.y*(va-vb-vc+vd),   // value&#xD;&#xA;                 ga + u.x*(gb-ga) + u.y*(gc-ga) + u.x*u.y*(ga-gb-gc+gd) +  // derivatives&#xD;&#xA;                 du * (u.yx*(va-vb-vc+vd) + vec2(vb,vc) - va));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // -----------------------------------------------&#xD;&#xA;    &#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;        vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;&#xD;&#xA;        &#xD;&#xA;        vec3 n = noised( 8.0*p + iTime*4.0 );&#xD;&#xA;    &#xD;&#xA;        vec3 col = 0.5 + 0.5*((p.x&gt;0.0) ? n.yzx : n.xxx);&#xD;&#xA;        &#xD;&#xA;    	fragColor = vec4( col, 1.0 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/XdXBRH&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34741" PostHistoryTypeId="1" PostId="12163" RevisionGUID="3380ecf1-9556-4a5f-81db-906e02ea437b" CreationDate="2021-08-31T13:32:23.530" UserId="17139" Text="Understanding how gradient noise generation works" ContentLicense="CC BY-SA 4.0" />
  <row Id="34742" PostHistoryTypeId="3" PostId="12163" RevisionGUID="3380ecf1-9556-4a5f-81db-906e02ea437b" CreationDate="2021-08-31T13:32:23.530" UserId="17139" Text="|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34743" PostHistoryTypeId="5" PostId="12163" RevisionGUID="2cb4008b-4c9e-41ed-83db-1afbbe0909e6" CreationDate="2021-08-31T15:55:56.383" UserId="13095" Comment="Fix a typo" Text="When attempting to compute the gradient noise derivatives I've seen the use of a function named &quot;hash&quot; and I don't understand its purpose (nor why they have commented that it should be replaced by something better): [link][1] &#xD;&#xA;&#xD;&#xA;Code:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    vec2 hash( in vec2 x )  // replace this by something better&#xD;&#xA;    {&#xD;&#xA;        const vec2 k = vec2( 0.3183099, 0.3678794 );&#xD;&#xA;        x = x*k + k.yx;&#xD;&#xA;        return -1.0 + 2.0*fract( 16.0 * k*fract( x.x*x.y*(x.x+x.y)) );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // return gradient noise (in x) and its derivatives (in yz)&#xD;&#xA;    vec3 noised( in vec2 p )&#xD;&#xA;    {&#xD;&#xA;        vec2 i = floor( p );&#xD;&#xA;        vec2 f = fract( p );&#xD;&#xA;    &#xD;&#xA;    #if 1&#xD;&#xA;        // quintic interpolation&#xD;&#xA;        vec2 u = f*f*f*(f*(f*6.0-15.0)+10.0);&#xD;&#xA;        vec2 du = 30.0*f*f*(f*(f-2.0)+1.0);&#xD;&#xA;    #else&#xD;&#xA;        // cubic interpolation&#xD;&#xA;        vec2 u = f*f*(3.0-2.0*f);&#xD;&#xA;        vec2 du = 6.0*f*(1.0-f);&#xD;&#xA;    #endif    &#xD;&#xA;        &#xD;&#xA;        vec2 ga = hash( i + vec2(0.0,0.0) );&#xD;&#xA;        vec2 gb = hash( i + vec2(1.0,0.0) );&#xD;&#xA;        vec2 gc = hash( i + vec2(0.0,1.0) );&#xD;&#xA;        vec2 gd = hash( i + vec2(1.0,1.0) );&#xD;&#xA;        &#xD;&#xA;    float va = dot( ga, f - vec2(0.0,0.0) );&#xD;&#xA;    float vb = dot( gb, f - vec2(1.0,0.0) );&#xD;&#xA;    float vc = dot( gc, f - vec2(0.0,1.0) );&#xD;&#xA;    float vd = dot( gd, f - vec2(1.0,1.0) );&#xD;&#xA;&#xD;&#xA;    return vec3( va + u.x*(vb-va) + u.y*(vc-va) + u.x*u.y*(va-vb-vc+vd),   // value&#xD;&#xA;                 ga + u.x*(gb-ga) + u.y*(gc-ga) + u.x*u.y*(ga-gb-gc+gd) +  // derivatives&#xD;&#xA;                 du * (u.yx*(va-vb-vc+vd) + vec2(vb,vc) - va));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // -----------------------------------------------&#xD;&#xA;    &#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;        vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;&#xD;&#xA;        &#xD;&#xA;        vec3 n = noised( 8.0*p + iTime*4.0 );&#xD;&#xA;    &#xD;&#xA;        vec3 col = 0.5 + 0.5*((p.x&gt;0.0) ? n.yzx : n.xxx);&#xD;&#xA;        &#xD;&#xA;    	fragColor = vec4( col, 1.0 );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/XdXBRH&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34748" PostHistoryTypeId="2" PostId="12165" RevisionGUID="af9f5a08-e0e1-4f26-b864-a9a6ad458e1e" CreationDate="2021-09-01T09:26:19.070" UserId="7724" Text="The noise is defined using a rectangular regular lattice. This lattice contains cells in which the noise is evaluated using the four corner points of this cell. At every point of the lattice a pseudo-random gradient is defined. The hash function is simply a compact way of defining a pseudo-random function that given coordinates of a point of the lattice $(i,j)$ returns a pseudo-random gradient. In this way the gradient vector is the same for all cells which are adjacent to lattice point $(i, j)$.&#xD;&#xA;&#xD;&#xA;The reason it says the hash function should be replaced by something better is because it is a very simple hash function which when evaluated might not be too random at all and periodicities might be observed in the generated noise field. " ContentLicense="CC BY-SA 4.0" />
  <row Id="34751" PostHistoryTypeId="2" PostId="12166" RevisionGUID="8d684ac6-56c0-4051-bdea-4fc6a799e509" CreationDate="2021-09-03T07:35:26.030" UserId="17088" Text="I want to create a single-channel 2d texture with bytebuffer which contain each float for each pixel (let say it is an alpha value) to use further in shader&#xD;&#xA;&#xD;&#xA;Btw, I've tried this&#xD;&#xA;```&#xD;&#xA;glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_FLOAT, null)&#xD;&#xA;// Then I call below when I want to change value in those texture&#xD;&#xA;glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ALPHA, GL_FLOAT, buffer)&#xD;&#xA;```&#xD;&#xA;with access the alpha value as `tex.a` in shader&#xD;&#xA;And it just works fine on only some devices, and as you can see as a reference from [doc](https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml) it would raise `INVALID_OPERATION` which happens in other devices but not some devices I mention before.&#xD;&#xA;&#xD;&#xA;So the question is how would I make this right?&#xD;&#xA;&#xD;&#xA;I also tried this&#xD;&#xA;```&#xD;&#xA;glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, null)&#xD;&#xA;// Then I call below when I want to change value in those texture&#xD;&#xA;glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, buffer)&#xD;&#xA;```&#xD;&#xA;I think it suppose to do the same but place value in red channel but It seems the value is rgba (0, 0, 0, 1) on every pixel.&#xD;&#xA;&#xD;&#xA;And another question is what happened in those devices that work?&#xD;&#xA;&#xD;&#xA;PS. All I want to do is some kind of use that buffer as alpha value for texture so If it possible to send it directly to texture please show me." ContentLicense="CC BY-SA 4.0" />
  <row Id="34752" PostHistoryTypeId="1" PostId="12166" RevisionGUID="8d684ac6-56c0-4051-bdea-4fc6a799e509" CreationDate="2021-09-03T07:35:26.030" UserId="17088" Text="glTexImage2d from bytebuffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="34753" PostHistoryTypeId="3" PostId="12166" RevisionGUID="8d684ac6-56c0-4051-bdea-4fc6a799e509" CreationDate="2021-09-03T07:35:26.030" UserId="17088" Text="|texture|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34754" PostHistoryTypeId="5" PostId="12166" RevisionGUID="7cee09fe-d34f-48e6-9606-4a30d4afb85b" CreationDate="2021-09-03T12:46:55.550" UserId="17088" Comment="added 246 characters in body" Text="I want to create a single-channel 2d texture with bytebuffer which contain each float for each pixel (let say it is an alpha value) to use further in shader&#xD;&#xA;&#xD;&#xA;Btw, I've tried this&#xD;&#xA;```&#xD;&#xA;glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_FLOAT, null)&#xD;&#xA;// Then I call below when I want to change value in those texture&#xD;&#xA;glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ALPHA, GL_FLOAT, buffer)&#xD;&#xA;```&#xD;&#xA;with access the alpha value as `tex.a` in shader&#xD;&#xA;And it just works fine on only some devices, and as you can see as a reference from [doc](https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml) it would raise `INVALID_OPERATION` which happens in other devices but not some devices I mention before.&#xD;&#xA;&#xD;&#xA;So the question is how would I make this right?&#xD;&#xA;&#xD;&#xA;I also tried this&#xD;&#xA;```&#xD;&#xA;glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, null)&#xD;&#xA;// Then I call below when I want to change value in those texture&#xD;&#xA;glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_FLOAT, buffer)&#xD;&#xA;```&#xD;&#xA;I think it suppose to do the same but place value in red channel but It seems the value is rgba (0, 0, 0, 1) on every pixel.&#xD;&#xA;&#xD;&#xA;And another question is what happened in those devices that work?&#xD;&#xA;&#xD;&#xA;PS. All I want to do is some kind of use that buffer as alpha value for texture so If it possible to send it directly to texture please show me.&#xD;&#xA;&#xD;&#xA;Update: Addition information I've found&#xD;&#xA; - bytebuffer is actually a floatbuffer&#xD;&#xA; - both of the solution work on the device that work but in shader of the second one It need to access `tex.r` as we tell GL that we provide data in red channel" ContentLicense="CC BY-SA 4.0" />
  <row Id="34755" PostHistoryTypeId="2" PostId="12167" RevisionGUID="7f76e160-448a-4535-84b2-56073605a9e4" CreationDate="2021-09-03T13:53:22.127" UserId="17150" Text="Can someone please explain to me what the **Viewport** is. I've read the OpenGL wiki and doc.gl but they give me a definition that I don't understand at all. The definition they gave me is &quot;glViewport specifies the affine transformation of x and y from normalized device coordinates to window coordinates. Let (xnd,ynd) be normalized device coordinates.&quot;. I don't understand what that means." ContentLicense="CC BY-SA 4.0" />
  <row Id="34756" PostHistoryTypeId="1" PostId="12167" RevisionGUID="7f76e160-448a-4535-84b2-56073605a9e4" CreationDate="2021-09-03T13:53:22.127" UserId="17150" Text="What is the Viewport?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34757" PostHistoryTypeId="3" PostId="12167" RevisionGUID="7f76e160-448a-4535-84b2-56073605a9e4" CreationDate="2021-09-03T13:53:22.127" UserId="17150" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34758" PostHistoryTypeId="2" PostId="12168" RevisionGUID="25316286-9b0f-4917-baf3-136c26f5649d" CreationDate="2021-09-04T05:36:46.030" UserId="17153" Text="Recently I have been looking at pbrt, and was looking at their remapping from roughness to $\alpha$ values:&#xD;&#xA;https://github.com/mmp/pbrt-v3/blob/master/src/core/microfacet.h#L86&#xD;&#xA;&#xD;&#xA;I understand that it is quite common to use some non-linear remapping between roughness values and $\alpha$ values to make the changes in roughness perceptually linear and in the range $[0, 1]$. To me this function looks like it could be some kind of polynomial approximation of the function:&#xD;&#xA;&#xD;&#xA;$\alpha = 1.62142\cdot\sqrt{roughness}$.&#xD;&#xA;&#xD;&#xA;[(Here is a Desmos link to show the match - if anyone knows if this is correct and also knows how they came up with this approximation I would love to find out, as it doesn't seem like a standard Taylor series expansion).][1] If this is correct, it would seem to be a pretty standard remapping, using the square of $\alpha$ to get roughness values, and ensuring that the maximum value of $\alpha$ (which in this case is $1.62142$) goes to $1$ in roughness.&#xD;&#xA;&#xD;&#xA;What I'm really curious about is how this maximum value of $1.62142$ is chosen. In pbrt, $\alpha = \sqrt{2}\cdot(RMS slope)$:&#xD;&#xA;&#xD;&#xA;https://pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#eq:beckmann-isotropic ,&#xD;&#xA;&#xD;&#xA;meaning the maximum RMS slope is $\approx 1.14652$. This seems like a very specific value for maximum roughness - where does this limit come from? RMS slope has infinite bounds as far as I'm aware - is there some physical reason for the limit or some standard that they are conforming to?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/kcldap4yti" ContentLicense="CC BY-SA 4.0" />
  <row Id="34759" PostHistoryTypeId="1" PostId="12168" RevisionGUID="25316286-9b0f-4917-baf3-136c26f5649d" CreationDate="2021-09-04T05:36:46.030" UserId="17153" Text="How is the maximum value for alpha (roughness == 1) decided for microfacet models?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34760" PostHistoryTypeId="3" PostId="12168" RevisionGUID="25316286-9b0f-4917-baf3-136c26f5649d" CreationDate="2021-09-04T05:36:46.030" UserId="17153" Text="|brdf|microfacet|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34762" PostHistoryTypeId="2" PostId="12169" RevisionGUID="24c80e52-df61-409f-ae69-9c952b3b54af" CreationDate="2021-09-04T17:01:19.490" UserId="48" Text="In truth, there is no mathematical maximum value for $\alpha$. As you noted, microfacet slope is unbounded, so in principle you could have arbitrarily large slope values and hence arbitrarily large $\alpha$. There's nothing wrong with that—the mathematics of the microfacet model keeps working fine.&#xD;&#xA;&#xD;&#xA;As a practical matter, beyond a certain point you don't really see a lot of perceptual change in the appearance of the surface with increasing $\alpha$. As the roughness increases, the specular highlights become more broad and soft until the surface looks essentially Lambertian.&#xD;&#xA;&#xD;&#xA;I don't know what is the origin of the value 1.62142 or that particular roughness remapping curve, but I'd guess that the maximum $\alpha$ is mainly chosen to give a visually useful range of roughness values, with the maximum being about at the point where it becomes indistinguishable to a diffuse surface. As this is a fuzzy aesthetic judgement, there may be no significance to the exact value.&#xD;&#xA;&#xD;&#xA;Also, from a PBR standpoint, typical BSDFs only model single scattering (no inter-reflection between microfacets), but as roughness increases, multiple scattering becomes more important to the surface appearance. So at some point with high $\alpha$, the accuracy of the model breaks down and it ceases to be really physically based, unless you incorporate multiple scattering in the BSDF. Materials with complex micro-geometry may also be better modeled by volumetric microflake distributions rather than (or in addition to) surface BSDFs.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34763" PostHistoryTypeId="2" PostId="12170" RevisionGUID="20c610bb-1b88-4158-abc0-8b7489eb1b41" CreationDate="2021-09-04T17:14:41.887" UserId="48" Text="The viewport as specified by `glViewport` is just the rectangle in pixels on the screen that you wish to render to. Usually it's from (0,0) to (width, height) in pixels, but you could set it to a smaller region (or larger, for that matter) and it will basically scale the image as it's being rendered.&#xD;&#xA;&#xD;&#xA;The &quot;affine transformation from normalized device coordinates&quot; business is saying that the GPU is going to remap from the abstract coordinates in which you define your scene, to the physical pixel coordinates on the actual image you're rendering (which in OpenGL is called window coordinates).&#xD;&#xA;&#xD;&#xA;The coordinates of triangle vertices, after going through the projection matrix and so forth, end up in a normalized range from −1 to 1 representing your field of view. For example, x = −1 on the left edge of the camera frustum and x = 1 on the right edge of the frustum (no matter how big the actual field of view of the frustum is). To find which pixels the triangles actually cover on screen, those coordinates get linearly remapped from [−1, 1] to the range of the viewport rectangle in pixels. Technically that kind of mapping is called an &quot;affine transformation&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="34764" PostHistoryTypeId="2" PostId="12171" RevisionGUID="dca470f7-6472-49d4-bfcf-446b996ceef3" CreationDate="2021-09-05T07:49:49.547" UserId="17158" Text="I only discovered there was name for it last Siggraph despite it being around, here is good introduction https://diff-render.org/ with lots of references to more specialized topics. Can somebody confirm this phd thesis the earliest work on it? https://www.graphics.cornell.edu/pubs/1998/Mar98.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="34765" PostHistoryTypeId="2" PostId="12172" RevisionGUID="115ead1b-3fd4-4939-ab8f-1b160a4b8d8b" CreationDate="2021-09-05T12:14:12.487" UserId="10129" Text="I'm currently implementing SSR in my engine and I've created Hi-Z buffer using multiple PSOs in way presented below:&#xD;&#xA;&#xD;&#xA;1. Create descriptor table with multiple UAV entries (this case - 3 entries for Mip 0, Mip 1, Mip 2). Each of this will be bound to appropriate UAV in shader&#xD;&#xA;2. Create PSO for each **compute shader** function depending on which mip is currently being generated&#xD;&#xA;3. In runtime, switch PSO and dispatch **CS** for each shader&#xD;&#xA;4. In result, each mip of Hi-Z buffer texture is filled with correct data. However, there is PSO switch before each dispatch which seems to be costly&#xD;&#xA;&#xD;&#xA;**I want to get rid of PSO switch** (although, I'm not sure if that's possible because I have two functions - one is generating mip 0 by mapping depth from compute space to view space, other one is standard Hi-Z mip generation) and **use single UAV to read data from and save data to.** &#xD;&#xA;&#xD;&#xA;If it is not possible, I would appreciate tips how to implement cleaner solution, because what I'm currently using seems a little ugly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Relevant code:&#xD;&#xA;&#xD;&#xA;A - create PSO for each UAV mip&#xD;&#xA;&#xD;&#xA;    // Create PSO for mip 0&#xD;&#xA;    pipelineStateStream.pRootSignature = m_rootSignatureHiZ.Get();&#xD;&#xA;    pipelineStateStream.CS = CD3DX12_SHADER_BYTECODE(computeShader.Get());&#xD;&#xA;    {&#xD;&#xA;        D3D12_PIPELINE_STATE_STREAM_DESC pipelineStateStreamDesc = { sizeof(PipelineStateStream), &amp;pipelineStateStream };&#xD;&#xA;        ThrowIfFailed(m_device-&gt;CreatePipelineState(&amp;pipelineStateStreamDesc, IID_PPV_ARGS(&amp;m_pipelineStateHiZMipZero))); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Create PSO for mip 1&#xD;&#xA;    Compile_Shader(L&quot;Shaders/CS_HiZ.hlsl&quot;, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, &quot;generateHiZMip1&quot;, &quot;cs_5_1&quot;, 0, 0, &amp;computeShader);&#xD;&#xA;    //...&#xD;&#xA;&#xD;&#xA;    // Create PSO for mip 2&#xD;&#xA;    Compile_Shader(L&quot;Shaders/CS_HiZ.hlsl&quot;, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, &quot;generateHiZMip2&quot;, &quot;cs_5_1&quot;, 0, 0, &amp;computeShader);&#xD;&#xA;    //...&#xD;&#xA;&#xD;&#xA;B - in runtime, switch PSOs and dispatch compute shaders&#xD;&#xA;&#xD;&#xA;    // Generate Hi-Z mip 0 (transform depth buffer from Compute-Space (CS) to View-Space (VS))&#xD;&#xA;    {&#xD;&#xA;        m_commandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(m_hiZBuffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));&#xD;&#xA;        m_commandList-&gt;Dispatch(m_windowSize.x / 16, m_windowSize.y / 16, 1);&#xD;&#xA;        m_commandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(m_hiZBuffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COMMON));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Generate additional mips for Hi-Z buffer (in this implementation we use mip 1 and mip 2)&#xD;&#xA;    m_commandList-&gt;SetPipelineState(m_pipelineStateHiZMipOne.Get());&#xD;&#xA;    m_commandList-&gt;Dispatch(m_windowSize.x / 32, m_windowSize.y / 32, 1); // Mip 1&#xD;&#xA;&#xD;&#xA;    m_commandList-&gt;SetPipelineState(m_pipelineStateHiZMipTwo.Get());&#xD;&#xA;    m_commandList-&gt;Dispatch(m_windowSize.x / 64, m_windowSize.y / 64, 1); // Mip 2&#xD;&#xA;&#xD;&#xA;C - full compute shader, Hi-Z generation HLSL code&#xD;&#xA;&#xD;&#xA;    Texture2D g_depthBuffer : register(t0);&#xD;&#xA;    &#xD;&#xA;    RWTexture2D&lt;float&gt; hiZMip0 : register(u0);&#xD;&#xA;    RWTexture2D&lt;float&gt; hiZMip1 : register(u1);&#xD;&#xA;    RWTexture2D&lt;float&gt; hiZMip2 : register(u2);&#xD;&#xA;    &#xD;&#xA;    [numthreads(16, 16, 1)]&#xD;&#xA;    void generateHiZMip0(uint3 index : SV_DispatchThreadID)&#xD;&#xA;    {&#xD;&#xA;    	float depthCS = g_depthBuffer.Load(int3(index.xy, 0));&#xD;&#xA;    	hiZMip0[index.xy] = depthCStoVS(depthCS);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [numthreads(16, 16, 1)]&#xD;&#xA;    void generateHiZMip1(uint3 index : SV_DispatchThreadID)&#xD;&#xA;    {&#xD;&#xA;    	float a = hiZMip0.Load(int3(index.xy * 2 + int2(0, 0), 0));&#xD;&#xA;    	float b = hiZMip0.Load(int3(index.xy * 2 + int2(1, 0), 0));&#xD;&#xA;    	float c = hiZMip0.Load(int3(index.xy * 2 + int2(0, 1), 0));&#xD;&#xA;    	float d = hiZMip0.Load(int3(index.xy * 2 + int2(1, 1), 0));&#xD;&#xA;    		&#xD;&#xA;    	hiZMip1[index.xy] = min4(a.x, b.x, c.x, d.x);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    [numthreads(16, 16, 1)]&#xD;&#xA;    void generateHiZMip2(uint3 index : SV_DispatchThreadID)&#xD;&#xA;    {&#xD;&#xA;    	float a = hiZMip1.Load(int3(index.xy * 2 + int2(0, 0), 0));&#xD;&#xA;    	float b = hiZMip1.Load(int3(index.xy * 2 + int2(1, 0), 0));&#xD;&#xA;    	float c = hiZMip1.Load(int3(index.xy * 2 + int2(0, 1), 0));&#xD;&#xA;    	float d = hiZMip1.Load(int3(index.xy * 2 + int2(1, 1), 0));&#xD;&#xA;    		&#xD;&#xA;    	hiZMip2[index.xy] = min4(a.x, b.x, c.x, d.x);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="34766" PostHistoryTypeId="1" PostId="12172" RevisionGUID="115ead1b-3fd4-4939-ab8f-1b160a4b8d8b" CreationDate="2021-09-05T12:14:12.487" UserId="10129" Text="Generate Hi-Z buffer using single PSO and single UAV" ContentLicense="CC BY-SA 4.0" />
  <row Id="34767" PostHistoryTypeId="3" PostId="12172" RevisionGUID="115ead1b-3fd4-4939-ab8f-1b160a4b8d8b" CreationDate="2021-09-05T12:14:12.487" UserId="10129" Text="|directx12|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34768" PostHistoryTypeId="2" PostId="12173" RevisionGUID="a3a926fb-1642-4c96-a372-d4a63b592c16" CreationDate="2021-09-05T17:28:38.513" UserId="48" Text="The code for mip1 and mip2 (and higher mips if you have them—SSR ray marching can benefit a lot from higher mips) is identical except for which mip is being read and written; you don't need separate PSOs for those. Instead of creating bindings for mip0, mip1, mip2, you could rather create bindings for &quot;source mip&quot; and &quot;dest mip&quot; and set the descriptors for each dispatch to point to the appropriate mips.&#xD;&#xA;&#xD;&#xA;Also note that you'll need a UAV barrier between these dispatches since each one will be reading from the mip written by the previous one.&#xD;&#xA;&#xD;&#xA;The overall sequence would be like:&#xD;&#xA;```&#xD;&#xA;switch to PSO for mip0&#xD;&#xA;dispatch mip0 (reads g_depthBuffer, writes mip0)&#xD;&#xA;barrier on mip0&#xD;&#xA;switch to shared PSO for all higher mips&#xD;&#xA;dispatch mip1 (src = mip0, dest = mip1)&#xD;&#xA;barrier on mip1&#xD;&#xA;dispatch mip2 (src = mip1, dest = mip2)&#xD;&#xA;barrier on mip2&#xD;&#xA;...&#xD;&#xA;```&#xD;&#xA;If the remaining PSO switch is still too expensive, you could also try putting it all in one shader and branching on a constant buffer value based on whether it's mip0 or a higher mip. So the shader code would look something like:&#xD;&#xA;```&#xD;&#xA;cbuffer { bool isFirstMip; }&#xD;&#xA;void generateHiZ(uint3 index : SV_DispatchThreadID)&#xD;&#xA;{&#xD;&#xA;    [branch] if (isFirstMip)&#xD;&#xA;        generateHiZMip0(index);&#xD;&#xA;    else&#xD;&#xA;        generateHiZHigherMips(index);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;As this branch is 100% coherent within a dispatch, it should not be very expensive (especially if the bool is in a root constant), and might well be faster than incurring the PSO switch.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;A further optimization you can make is to generate more than 1 mip per dispatch. With a threadgroup size of 16x16 it is possible to generate up to 5 mips in one pass, using one source and 5 dest UAVs. You would loop over the 5 mips in the shader and do a memory barrier at the end of each iteration, ensuring all threads in the group have finished their UAV writes. The first iteration will read 32x32 and write 16x16 (over the whole threadgroup), then will write 8x8, 4x4, 2x2, and 1x1.&#xD;&#xA;&#xD;&#xA;It also might be faster to use threadgroup shared memory after the first iteration, rather than re-reading it from the UAV, but this would need to be profiled to be sure (the UAV reads will be hitting cache, so may be fast enough on their own).&#xD;&#xA;&#xD;&#xA;Then, you would only need to invoke one dispatch for each 5 mips to generate. Two dispatches gives you up to 10 mips which is probably enough for SSR." ContentLicense="CC BY-SA 4.0" />
  <row Id="34769" PostHistoryTypeId="50" PostId="10438" RevisionGUID="f2c5a06f-a536-47b0-94f0-45576266bdef" CreationDate="2021-09-05T23:02:05.207" UserId="-1" />
  <row Id="34770" PostHistoryTypeId="2" PostId="12174" RevisionGUID="467f806d-36d3-4fcb-b2bb-81dfea187ba4" CreationDate="2021-09-06T00:00:25.803" UserId="17160" Text="I am brushing up on the fundamentals of OpenGL. Things are going great. I am looking at BSP for maps/levels. I understand that Doom uses BSP, but I worry. Can BSP be used with complete 3D world and just not a 2.5D perspective?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34771" PostHistoryTypeId="1" PostId="12174" RevisionGUID="467f806d-36d3-4fcb-b2bb-81dfea187ba4" CreationDate="2021-09-06T00:00:25.803" UserId="17160" Text="Is BSP the right tool for my game?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34772" PostHistoryTypeId="3" PostId="12174" RevisionGUID="467f806d-36d3-4fcb-b2bb-81dfea187ba4" CreationDate="2021-09-06T00:00:25.803" UserId="17160" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34773" PostHistoryTypeId="2" PostId="12175" RevisionGUID="b88f948d-71e2-43f3-8e22-37130e2bea8c" CreationDate="2021-09-06T00:09:32.917" UserId="48" Text="Yes, full 3D BSPs are possible, such as in Quake or in Quake-derived engines such as Half-Life, or other games from that era.&#xD;&#xA;&#xD;&#xA;That said, BSPs are not usually used for rendering purposes anymore. They may still be used in physics engines for collision detection in some cases." ContentLicense="CC BY-SA 4.0" />
  <row Id="34774" PostHistoryTypeId="5" PostId="12151" RevisionGUID="8a4c8dd9-f0db-4e7f-81da-0d960b0ff18a" CreationDate="2021-09-06T06:53:22.290" UserId="6046" Comment="added 4 characters in body" Text="I asked a similar question here before but since the previous post original question was different, I think it was confusing people. So I've voted to close that and asking the new question here. I'm doing a volume rendering project and made a cubic spline editor for transfer function. I used [this](http://graphicsrunner.blogspot.com/2008/05/camera-animation-part-ii.html) as a source which basically uses Wolfram as the main source. Now Wolfram defines a parametric representation. After I made it, I tried to compare it online but the curves are different. The only difference I found is that the online version is using a non-parametric representation.&#xD;&#xA;&#xD;&#xA;Here's mine.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here's the online version&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;In order to clarify a bit more on what I'm trying to do. I have 2 variables.&#xD;&#xA;&#xD;&#xA;$X = [0, 255] $&#xD;&#xA;&#xD;&#xA;$Y = [0, 1] $&#xD;&#xA;&#xD;&#xA;For every given $X$ value I need the interpolated $Y$ value. At first glance it seems that the explicit form of cubic spline is what I want. But I have another case where $Y$ values are RGB triplets $(r,g,b)$. Since the parametric representation doesn't have to deal with dimensions and since the code was already online I'm using the parametric form. The parametric form uses the parameter $t \in [0,1]$ for every segment.  &#xD;&#xA;&#xD;&#xA;Now things get a little trickier. Technichally my graph is of $(t, Y(t))$ but as you can see in the first picture the X-axis isn't $t$ but the previously defined $X$ which is in range $[0-255]$. I'm simply rescaling between $X$ and $t$. So if I get $t = 0.5$ for the first segment as an example, I'd take the two bounding control points which resolve to $(0,0)$ and $(141, 0.759)$ in the first picture. Then do simple rescaling like&#xD;&#xA;&#xD;&#xA;$0 + (141 - 0) * t$&#xD;&#xA;&#xD;&#xA;to get my iso-value and plot the graph. Here's how I'm actually drawing the graph&#xD;&#xA;```&#xD;&#xA;float t_step = 1/255.0f;&#xD;&#xA;for(int i = 0; i &lt; knots.size() - 1; i++)&#xD;&#xA;  {&#xD;&#xA;    for (int i_step = 1; i_step &lt;= num_line_segments; i_step++)&#xD;&#xA;    {&#xD;&#xA;        glm::vec2 coord;&#xD;&#xA;        coord.x = knots[i].iso_value + (t_step * i_step * (knots[i+1].iso_value - knots[i].iso_value));&#xD;&#xA;        coord.y = glm::clamp(alpha_spline.getPointOnSpline(t_step * i_step, i).w, v_min.y, v_max.y);&#xD;&#xA;        win-&gt;DrawList-&gt;_Path.push_back(getAbsMousePositionFromPoint(coord) );&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;  &#xD;&#xA;getAbsMousePositionFromPoint(glm::vec2 v)&#xD;&#xA;{&#xD;&#xA;  glm::vec2 v_min(0,0), v_max(255, 1.0)&#xD;&#xA;  glm::vec2 t = (v - v_min) / (v_max - v_min);&#xD;&#xA;  return glm::mix(graph_bot_left, graph_top_right, t);   // both &quot;graph_bot_left&quot; and &quot;graph_top_right&quot; are absolute coordinates of the drawing region&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Basically I need absolute coordinates for drawing anything on the screen. Each segment of the spline is basically drawn as a polyline. Just to be on the safe side I have currently set the number of line segments per curve of the spline to be `255`. This means per segment of the spline I need to draw 255 line segments. I step along `t` then transform it to the proper X-value by doing the transformation step as I told above then find absolute coordinates  from that X-value and draw the segment there.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; ***Now all I wanna know is, do parametric and explicit forms give different curves? If not, then is there something wrong with the rescaling step I'm doing above or something else?***&#xD;&#xA;&#xD;&#xA;P.S :- I've checked the formulation and the boundary conditions of the [online][3] one and all  are similar to the Wolfram one. Both mine and the online one are natural cubic splines. I've also double checked my code, even derived the whole parametric form on paper and checked the code with the one derived on paper and it matches perfectly so I'm pretty sure the code isn't wrong. Still [here's](https://github.com/gallickgunner/Volume-Renderer/blob/master/src/CubicSpline.cpp) my spline source as a reference if anybody here knows programming&#xD;&#xA;&#xD;&#xA;UPDATE:- So I just found another guy using the same logic as well [here][4].  I guess the math is all right then. Don't see where's the problem then.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Yo4am.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fEXlf.png&#xD;&#xA;  [3]: https://timodenk.com/blog/cubic-spline-interpolation/&#xD;&#xA;  [4]: https://github.com/jose-villegas/VolumeRendering/blob/3de0008cbd6c1771dc25d0e382b47240220ee7cc/VolumeRendering/TransferFunction.cpp#L96" ContentLicense="CC BY-SA 4.0" />
  <row Id="34775" PostHistoryTypeId="2" PostId="12176" RevisionGUID="dc49c0d3-c90e-41e2-a7af-5544bb95cfda" CreationDate="2021-09-06T11:26:24.543" UserId="6046" Text="I've very less knowledge when it comes to rasterization and typical rendering in games and other applications. So I was reading up on the rendering pipeline and found that the hardware could do early depth testing if you don't write to depth in fragment shader and this struck as odd to me. I'm having a hard time imagining cases where you'd wanna write to depth inside a fragment shader. In a normal rendering environment, the depth value gets calculated properly through all the transformations so why would you wanna mess with that? If anybody can explain briefly 2 or 3 examples it'd be great. Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="34776" PostHistoryTypeId="1" PostId="12176" RevisionGUID="dc49c0d3-c90e-41e2-a7af-5544bb95cfda" CreationDate="2021-09-06T11:26:24.543" UserId="6046" Text="Examples of cases where you write depth value in Fragment Shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34777" PostHistoryTypeId="3" PostId="12176" RevisionGUID="dc49c0d3-c90e-41e2-a7af-5544bb95cfda" CreationDate="2021-09-06T11:26:24.543" UserId="6046" Text="|rendering|fragment-shader|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34778" PostHistoryTypeId="2" PostId="12177" RevisionGUID="7fe63d23-7f81-48a1-8fb2-ad9d612ef847" CreationDate="2021-09-06T12:00:21.203" UserId="7952" Text="There are two types of BSP trees, the Axis Aligned BSP (aka k-D tree) and the polygon aligned BSP. Doom used the polygon aligned variety.&#xD;&#xA;&#xD;&#xA;Polygon aligned BSP tree's can be traversed in occlusion order (back to front, or front to back depending on the needs). This makes them useful in situations where a Z-buffer isn't available and was the original reason BSP tree's were chosen for Doom. (There were no Z buffers when Doom was first created)&#xD;&#xA;&#xD;&#xA;BSP tree's are constructed using a &quot;[hyperplane][1]&quot;. The so called 2.5D world is using a 1 dimensional hyperplane (aka a line) to split up an effectively 2 dimensional world.&#xD;&#xA;&#xD;&#xA;In 3D the hyperplane is a 2 dimensional plane that splits the 3D world into two separate 3D subspaces. Which are then recursively split until all objects in the world are divided up. This is the type of BSP tree you are suggesting: polygon aligned, using a 2D hyperplane for dividing the 3D world.&#xD;&#xA;&#xD;&#xA;BSP tree's are sensitive to the split point choices and can result in very large tree's especially in densely populated worlds with objects that have a wide variety of sizes since many objects can end up falling on split points.&#xD;&#xA;&#xD;&#xA;The octree would be another choice of BVH that has better resources available on the net for implementing and is less sensitive to the choice of split points so generally results in more performant trees. (but not always)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Hyperplane" ContentLicense="CC BY-SA 4.0" />
  <row Id="34779" PostHistoryTypeId="2" PostId="12178" RevisionGUID="73620a76-77f6-47e7-bb77-3b4ca05b2074" CreationDate="2021-09-07T11:38:27.397" UserId="15879" Text="To estimate the normal at a point, you need to find the gradient of the distance field in the immediate vicinity of the point. You need the rate of change, not the actual values.&#xD;&#xA;&#xD;&#xA;    vec3 getNormal(vec3 p) {&#xD;&#xA;       return normalize(vec3(&#xD;&#xA;           getSDF(vec3(p.x + EPSILON, p.y, p.z)) - getSDF(vec3(p.x - EPSILON, p.y, p.z)),&#xD;&#xA;           getSDF(vec3(p.x, p.y + EPSILON, p.z)) - getSDF(vec3(p.x, p.y - EPSILON, p.z)),&#xD;&#xA;           getSDF(vec3(p.x, p.y, p.z + EPSILON)) - getSDF(vec3(p.x, p.y, p.z - EPSILON))&#xD;&#xA;       ));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, a set of 1 and 0 values is not a proper signed distance field, so it's not clear if this will work.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34780" PostHistoryTypeId="50" PostId="10384" RevisionGUID="943c479e-7f4c-468d-857c-b02550ec45c9" CreationDate="2021-09-08T09:06:30.573" UserId="-1" />
  <row Id="34781" PostHistoryTypeId="50" PostId="9426" RevisionGUID="6ca983b8-2f3a-4f8a-bbaa-5a98a38ab611" CreationDate="2021-09-08T12:03:55.383" UserId="-1" />
  <row Id="34782" PostHistoryTypeId="2" PostId="12179" RevisionGUID="fd211f27-e5e1-4cc4-9f95-3b371e9cd3b3" CreationDate="2021-09-08T19:48:10.793" UserId="17173" Text="To represent a 3D geometry in our software we use this format below:&#xD;&#xA;Material-1 Material-2 P1(X1,Y1,Z1) P2(X2,Y2,Z2) P3(X3,Y3,Z3)&#xD;&#xA;&#xD;&#xA;This 11 point gives us a triangle with the description of what is behind and front of the triangle. Depicted below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/z1N10.png&#xD;&#xA;&#xD;&#xA;By applying the right-hand rule (P1 to P2 and then P3, like for electromagnetic force), we know what is Material-1 and Material-2 these are the properties on both sides of the triangular plane.&#xD;&#xA;&#xD;&#xA;Using these triangles we can construct the complete surface of our geometries. Since it is hard to create complex 3D surfaces and volumes (enclosed space by these triangles) manually, we want to use CAD software like Blender, SolidWorks, etc. What is the easiest data format (e.g. .STP, .STL, ...) that we can use to convert and represent the 3D geometries with our 5 parameters (actually 11 parameters) geometry format.&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="34783" PostHistoryTypeId="1" PostId="12179" RevisionGUID="fd211f27-e5e1-4cc4-9f95-3b371e9cd3b3" CreationDate="2021-09-08T19:48:10.793" UserId="17173" Text="Which geometry file format is the most similar to our geometry file format?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34784" PostHistoryTypeId="3" PostId="12179" RevisionGUID="fd211f27-e5e1-4cc4-9f95-3b371e9cd3b3" CreationDate="2021-09-08T19:48:10.793" UserId="17173" Text="|geometry|model|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34785" PostHistoryTypeId="2" PostId="12180" RevisionGUID="22bfaffd-607d-4e2d-acbd-dca6a8ff48cb" CreationDate="2021-09-08T21:11:47.983" UserId="38" Text="Easiest is probably OBJ or PLY. But can not really dump material info like you want. But you could encode it in a per face value. Both formats use similar windup rules to yours.&#xD;&#xA;&#xD;&#xA;Step (.STP) is out of question. Its a a few orders of magnitude more complex than what you have and does not deal with polygons, but rather a BREP model.&#xD;&#xA;&#xD;&#xA;Ascii STL might work. But be aware that the format itself is a bit screwy due to not having a very well done original standardisation. Namely it was unclear how the normal info should be handled. Because of this this normal or windup is quite universaly ignored by stl exporters and importers. So theres no guarantee the triangles directions come out as you made them (probably they do but relying on this is a bit dangerous). If it werent for this feature then ascii stl would be the closest format&#xD;&#xA;&#xD;&#xA;Blender is not really classified as a CAD application rather its a DCC application (Document Content Creation). They use different primitive constructs. But blender is much closer in nature than most cads considering your polygon modeling." ContentLicense="CC BY-SA 4.0" />
  <row Id="34786" PostHistoryTypeId="5" PostId="12180" RevisionGUID="5654275f-81d5-4d45-bc71-33d0073222c7" CreationDate="2021-09-08T21:18:30.737" UserId="38" Comment="added 113 characters in body" Text="Easiest is probably OBJ or PLY. But can not really dump material info like you want. But you could encode it in a per face value. Both formats use similar windup rules to yours.&#xD;&#xA;&#xD;&#xA;Step (.STP) is out of question. Its a a few orders of magnitude more complex than what you have and does not deal with polygons, but rather a BREP model.&#xD;&#xA;&#xD;&#xA;Ascii STL might work. But be aware that the format itself is a bit screwy due to not having a very well done original standardisation. Namely it was unclear how the normal info should be handled. Because of this this normal or windup is quite universaly ignored by stl exporters and importers. So theres no guarantee the triangles directions come out as you made them (probably they do but relying on this is a bit dangerous). If it werent for this feature then ascii stl would be the closest format&#xD;&#xA;&#xD;&#xA;Blender is not really classified as a CAD application rather its a DCC application (Document Content Creation). They use different primitive constructs. But blender is much closer in nature than most cads considering your polygon modeling.&#xD;&#xA;&#xD;&#xA;PS: Consuder implementing point sharing beween polygons theres lots of advantages for processing and modeling" ContentLicense="CC BY-SA 4.0" />
  <row Id="34787" PostHistoryTypeId="5" PostId="12180" RevisionGUID="20d6f5c9-b17c-429a-9469-b652547dcfb6" CreationDate="2021-09-08T21:28:35.970" UserId="38" Comment="added 164 characters in body" Text="Easiest is probably OBJ or PLY. But can not really dump material info like you want. But you could encode it in a per face value. Both formats use similar windup rules to yours.&#xD;&#xA;&#xD;&#xA;Step (.STP) is out of question. Its a a few orders of magnitude more complex than what you have and does not deal with polygons, but rather a BREP model.\*&#xD;&#xA;&#xD;&#xA;Ascii STL might work. But be aware that the format itself is a bit screwy due to not having a very well done original standardisation. Namely it was unclear how the normal info should be handled. Because of this this normal or windup is quite universaly ignored by stl exporters and importers. So theres no guarantee the triangles directions come out as you made them (probably they do but relying on this is a bit dangerous). If it werent for this feature then ascii stl would be the closest format&#xD;&#xA;&#xD;&#xA;Blender is not really classified as a CAD application rather its a DCC application (Document Content Creation). They use different primitive constructs. But blender is much closer in nature than most cads considering your polygon modeling.&#xD;&#xA;&#xD;&#xA;PS: Consider implementing point sharing beween polygons theres lots of advantages for processing and modeling.&#xD;&#xA;&#xD;&#xA;\* I'd say about four or five orders of magnitude. Even without the testing mandates even reading just the specification is 10000 pages of iso standard text. OBJ should be implemebtable in a few hours for step you may be better of buying a third party reader and still need a month of implementation time." ContentLicense="CC BY-SA 4.0" />
  <row Id="34791" PostHistoryTypeId="5" PostId="12180" RevisionGUID="35302e34-8866-4a7c-99b8-0cb4919d4580" CreationDate="2021-09-09T16:46:40.710" UserId="38" Comment="edited body" Text="Easiest is probably OBJ or PLY. But can not really dump material info like you want. But you could encode it in a per face value. Both formats use similar windup rules to yours.&#xD;&#xA;&#xD;&#xA;Step (.STP) is out of question. Its a a few orders of magnitude more complex than what you have and does not deal with polygons, but rather a BREP model.\*&#xD;&#xA;&#xD;&#xA;Ascii STL might work. But be aware that the format itself is a bit screwy due to not having a very well done original standardisation. Namely it was unclear how the normal info should be handled. Because of this this normal or windup is quite universaly ignored by stl exporters and importers. So theres no guarantee the triangles directions come out as you made them (probably they do but relying on this is a bit dangerous). If it werent for this feature then ascii stl would be the closest format&#xD;&#xA;&#xD;&#xA;Blender is not really classified as a CAD application rather its a DCC application (Document Content Creation). They use different primitive constructs. But blender is much closer in nature than most cads considering your polygon modeling.&#xD;&#xA;&#xD;&#xA;PS: Consider implementing point sharing beween polygons theres lots of advantages for processing and modeling.&#xD;&#xA;&#xD;&#xA;\* I'd say about four or five orders of magnitude. Even without the testing mandates even reading just the specification is 10000 pages of iso standard text. OBJ should be implementable in a few hours for step you may be better of buying a third party reader and still need a month of implementation time." ContentLicense="CC BY-SA 4.0" />
  <row Id="34795" PostHistoryTypeId="2" PostId="12182" RevisionGUID="a3bf999f-8fc6-48fe-b9d2-2d20064ca74e" CreationDate="2021-09-10T10:27:55.270" UserId="13273" Text="In the usual pipeline (vertex, tessellation, geometry and fragment shaders) the geometry can be deformed and in the geometry shader it is possible to copy the generated and deformed geometry in order to transfer it from several positions into several layers of a texture to render. Also known as &quot;layered rendering&quot;.&#xD;&#xA;Does the new mesh shading pipeline (task shader, mesh shader and fragment shader) also have the option of generating / deforming the mesh and then copying it into different layers? So that you can render the same scenario multiple times within one drawcall?&#xD;&#xA;&#xD;&#xA;I am asking for Vulkan, OpenGL and DirectX 12" ContentLicense="CC BY-SA 4.0" />
  <row Id="34796" PostHistoryTypeId="1" PostId="12182" RevisionGUID="a3bf999f-8fc6-48fe-b9d2-2d20064ca74e" CreationDate="2021-09-10T10:27:55.270" UserId="13273" Text="Mesh-Shader and layered rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="34797" PostHistoryTypeId="3" PostId="12182" RevisionGUID="a3bf999f-8fc6-48fe-b9d2-2d20064ca74e" CreationDate="2021-09-10T10:27:55.270" UserId="13273" Text="|opengl|shader|vulkan|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34798" PostHistoryTypeId="2" PostId="12183" RevisionGUID="c3ea9301-c170-4436-adac-77fba2bb1316" CreationDate="2021-09-10T16:16:14.840" UserId="2654" Text="In accord with [the GLSL extension][1], `gl_Layer` in a mesh shader is part of the predefined `gl_MeshPerPrimitiveNV` output interface block. It seems to have the expected definition. This is a per-primitive parameter, so you can set it to a different value for each primitive you output.&#xD;&#xA;&#xD;&#xA;Basically, yes: layered rendering is available in task/mesh shaders. And since this extension specifies the SPIR-V decorator equivalent (ie: `Layer`), it seems clear it can be used in the Vulkan equivalent just as well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/GLSL/blob/master/extensions/nv/GLSL_NV_mesh_shader.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="34799" PostHistoryTypeId="2" PostId="12184" RevisionGUID="45e548ce-ff34-4eeb-9270-e4b312584d7d" CreationDate="2021-09-10T16:23:10.893" UserId="213" Text="I have a mesh (Mesh-A) with a bounding box of some arbitrary size defined by X,Y,Z scale.&#xD;&#xA;In runtime I import another mesh (Mesh-B),which has an overall topology similar to the Mesh-A, but it can have a different default scale. I am looking for an efficient algorithm to rescale the Mesh-B to have the new scale equal to the Mesh-A,which basically means - their bounding boxes are of similar sizes. The naive approach would be to run for... loop, scaling the Mesh-B transform,till its BB has an approximate size equal to that of  the Mesh-B's BB. I would like to learn other approaches.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34800" PostHistoryTypeId="1" PostId="12184" RevisionGUID="45e548ce-ff34-4eeb-9270-e4b312584d7d" CreationDate="2021-09-10T16:23:10.893" UserId="213" Text="Efficient algorithm for mesh scale adjustment based on the scale of another mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="34801" PostHistoryTypeId="3" PostId="12184" RevisionGUID="45e548ce-ff34-4eeb-9270-e4b312584d7d" CreationDate="2021-09-10T16:23:10.893" UserId="213" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34802" PostHistoryTypeId="2" PostId="12185" RevisionGUID="a6acfd24-38e6-4999-8abc-e2e04c41169c" CreationDate="2021-09-10T17:32:04.127" UserId="506" Text="Scaling is linear, so you can do this in one step rather than iteratively. If you have two vector values `sizeA` and `sizeB` for the sizes of the two meshes’ bounding boxes, the vector value you should scale mesh B by is `sizeA / sizeB`. If you want to scale it uniformly, you’ll need to pick a single scalar value; one way to do that would be to average the ratios of each component, i.e. `(sizeA.x / sizeB.x + sizeA.y / sizeB.y + sizeA.z / sizeB.z) / 3`." ContentLicense="CC BY-SA 4.0" />
  <row Id="34803" PostHistoryTypeId="2" PostId="12186" RevisionGUID="0903ec9b-75d9-437b-9a19-a5e42dc9481a" CreationDate="2021-09-11T15:34:22.383" UserId="8704" Text="I've recently been working on a particle system in my renderer and I've encountered a situation where my particle class on the C++ side has data I need to maintain my particle on that end, but that I don't need in my shader (velocity, acceleration, life span, start colour, end colour, gravity toggle, etc.). &#xD;&#xA;&#xD;&#xA;So presently I've created a second class that just contains my necessary rendering data and I have a function that will copy the needed data from my &quot;full&quot; particle to my &quot;rendering&quot; particle.&#xD;&#xA;&#xD;&#xA;    class HParticle {&#xD;&#xA;    public:&#xD;&#xA;    	vec3 m_pos = vec3(0, 0, 0);&#xD;&#xA;    	float m_life = 0; // Remaining life of the particle. if &lt; 0 : dead and unused.&#xD;&#xA;    	vec4 m_color = vec4(1, 1, 1, 1); // Color&#xD;&#xA;    	float m_texture = -1;&#xD;&#xA;    	float m_scale = 1;&#xD;&#xA;    	vec3 m_orientation;&#xD;&#xA;    	float m_featureValue = 0;&#xD;&#xA;    	float m_featureSelected = 0;&#xD;&#xA;    	float m_emission = 0;&#xD;&#xA;    	float m_scaleRate = 0;&#xD;&#xA;    	vec4 m_startColor = vec4(1, 1, 1, 1);&#xD;&#xA;    	vec4 m_endColor = vec4(1, 1, 1, 1);&#xD;&#xA;    	vec3 m_velocity = vec3(0, 0, 0);&#xD;&#xA;    	vec3 m_acceleration = vec3(0, 0, 0);&#xD;&#xA;    	float m_featureValueRateOfChange = 0;&#xD;&#xA;    	float m_totalLife = 0;&#xD;&#xA;    	float m_colorLife = 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    struct HStrippedParticle {&#xD;&#xA;    	mat4 m_transform;&#xD;&#xA;    	vec4 m_color = vec4(1, 1, 1, 1); // Color&#xD;&#xA;    	float m_texture = -1;&#xD;&#xA;    	float m_featureValue = 0;&#xD;&#xA;    	float m_featureSelected = 0;&#xD;&#xA;    	float m_emission = 0;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;I know I'm speaking specifically to particles here but I've encountered this situation a couple of times before and I'm wondering if there's a better general approach than maintaining two lists. One for C++ and one for my shader. And having to update the shader one every time I go to render (I know I could be cleverer and avoid updating data that hasn't changed but still). Maybe something fancy with C++ memory to copy desired chunks from the full class to the stripped class?&#xD;&#xA;&#xD;&#xA;Thanks in advance" ContentLicense="CC BY-SA 4.0" />
  <row Id="34804" PostHistoryTypeId="1" PostId="12186" RevisionGUID="0903ec9b-75d9-437b-9a19-a5e42dc9481a" CreationDate="2021-09-11T15:34:22.383" UserId="8704" Text="Stripping unnecessary data from C++ data structures before sending to GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="34805" PostHistoryTypeId="3" PostId="12186" RevisionGUID="0903ec9b-75d9-437b-9a19-a5e42dc9481a" CreationDate="2021-09-11T15:34:22.383" UserId="8704" Text="|opengl|shader|c++|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34806" PostHistoryTypeId="2" PostId="12187" RevisionGUID="ed5afe7c-b851-4ee1-be4f-c267436ceabf" CreationDate="2021-09-11T16:58:05.427" UserId="17184" Text="I came across some Non-Euclidean Games which involve Hyperbolic Spaces, Spherical Spaces, Portals, etc. And, I noticed that they give quite deep feel of what Non-Euclidean Spaces feel like. So, I was thinking whether space rendering was possible for other unconventional perspectives, for example, **Hypercentric Perspective** (Objects that are farther away from the lens produce larger images than objects that are closer to the lens, contrary to the human eye where farther-away objects always appear smaller.) Due to physical restrictions, only a handful of images for Hypercentric Perspective exists on the internet, but these should give some idea:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA;Now, my question is how to render Hypercentric Perspective in preferably 3 Dimensional Space? &#xD;&#xA;&#xD;&#xA;I tried doing this in Unity by varying the physical parameters of the virtual physical camera, but  it was no success. What can be the other way of approaching the problem? Preferably, the optimal approach? I'm very new to Computer Graphics so please pardon me if I missed something obvious here. &#xD;&#xA;&#xD;&#xA;Please help me here.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TJkxV.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/dxiGG.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="34807" PostHistoryTypeId="1" PostId="12187" RevisionGUID="ed5afe7c-b851-4ee1-be4f-c267436ceabf" CreationDate="2021-09-11T16:58:05.427" UserId="17184" Text="Rendering Hypercentric Perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="34808" PostHistoryTypeId="3" PostId="12187" RevisionGUID="ed5afe7c-b851-4ee1-be4f-c267436ceabf" CreationDate="2021-09-11T16:58:05.427" UserId="17184" Text="|rendering|physically-based|perspective|physics|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34809" PostHistoryTypeId="2" PostId="12188" RevisionGUID="27e893ed-3456-4bc7-9d7d-ad901ae9ba16" CreationDate="2021-09-11T23:12:44.647" UserId="48" Text="I typically like to define a &quot;GPUData&quot; struct containing the fields that are going to the shader, and keep the GPUDatas for all the particles in an array. Then, when it's time to update the GPU buffer, you can just memcpy out of that array to your mapped buffer (or you can pass the array to `glBufferSubData`, etc).&#xD;&#xA;&#xD;&#xA;For the CPU state, rather than duplicating the fields that are already in the GPUData, you can just keep the non-GPU fields there. Then your particle simulation code just reads and write the GPUData fields directly.&#xD;&#xA;&#xD;&#xA;Pseudocode example:&#xD;&#xA;```&#xD;&#xA;struct ParticleGPUData&#xD;&#xA;{&#xD;&#xA;    mat4 m_transform;&#xD;&#xA;    vec4 m_color;&#xD;&#xA;    // ...&#xD;&#xA;};&#xD;&#xA;std::vector&lt;ParticleGPUData&gt; particleGPUData;&#xD;&#xA;&#xD;&#xA;struct ParticleCPUData&#xD;&#xA;{&#xD;&#xA;    float m_life;&#xD;&#xA;    vec3 m_velocity;&#xD;&#xA;    vec3 m_acceleration;&#xD;&#xA;    // ...&#xD;&#xA;};&#xD;&#xA;std::vector&lt;ParticleCPUData&gt; particleCPUData;&#xD;&#xA;&#xD;&#xA;// In your simulation loop&#xD;&#xA;for (int i = 0; i &lt; countParticles; ++i)&#xD;&#xA;{&#xD;&#xA;    ParticleCPUData* cpuData = &amp;particleCPUData[i];&#xD;&#xA;    ParticleGPUData* gpuData = &amp;particleGPUData[i];&#xD;&#xA;&#xD;&#xA;    // update the particle...&#xD;&#xA;    cpuData-&gt;m_velocity += cpuData-&gt;m_acceleration * dT;&#xD;&#xA;    gpuData-&gt;m_color = CalculateColor(cpuData);&#xD;&#xA;    // ... etc.&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// When you go to update the buffer to render&#xD;&#xA;glBufferSubData(&#xD;&#xA;    GL_SHADER_STORAGE_BUFFER, 0,&#xD;&#xA;    particleGPUData.size() * sizeof(ParticleGPUData),&#xD;&#xA;    particleGPUData.data());&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Also, it can be handy to keep the GPUData struct definition in a header file that is included by both C++ and GLSL, which ensures there's one definition of it and it will always be in sync between application code and shader code (although you have to watch out for potential alignment differences)." ContentLicense="CC BY-SA 4.0" />
  <row Id="34810" PostHistoryTypeId="2" PostId="12189" RevisionGUID="70e110ae-77d5-409c-b564-475a5c9b1ec7" CreationDate="2021-09-12T01:27:34.393" UserId="13456" Text="The answer is yes. &#xD;&#xA;&#xD;&#xA;You need 2 things:&#xD;&#xA;&#xD;&#xA;- View space coordinates of the object&#xD;&#xA;- Projection function for the hypercentric perspective camera.&#xD;&#xA;&#xD;&#xA;The second one can be found in [here](https://link.springer.com/article/10.1007/s00138-019-01032-w).&#xD;&#xA;&#xD;&#xA;The overview of the model&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Here is a small discription in case the link goes away. &#xD;&#xA;&#xD;&#xA;- You project the point using this $\begin{aligned} \left( \begin{array}{@{}c@{}} x_\mathrm {u} \\ y_\mathrm {u} \end{array} \right) = \frac{c}{z_k} \left( \begin{array}{@{}c@{}} x_k \\ y_k \end{array} \right) , \end{aligned}$ where components with $k$ represents the coordiantes of the point in camera space.&#xD;&#xA;&#xD;&#xA;- You then model the lens distortion with $\begin{aligned} \left( \begin{array}{@{}c@{}} x_\mathrm {d} \\ y_\mathrm {d} \end{array} \right) = \frac{2}{1+\sqrt{1-4\kappa r_\mathrm {u}^2}} \left( \begin{array}{@{}c@{}} x_\mathrm {u} \\ y_\mathrm {u} \end{array} \right) , \end{aligned}$ where $r_\mathrm {u}^2=x_\mathrm {u}^2 + y_\mathrm {u}^2$&#xD;&#xA;&#xD;&#xA;- Then you transform the distorted points to image space with $\begin{aligned} \left( \begin{array}{@{}c@{}} x_\mathrm {i} \\ y_\mathrm {i} \end{array} \right) = \left( \begin{array}{@{}c@{}} x_\mathrm {d}/s_x+c_x \\ y_\mathrm {d}/s_y+c_y \end{array} \right) , \end{aligned}$ where where $s_x$ and $s_y$ are the pixel pitch on the sensor and $(_,_)^⊤$ denotes the principal point.&#xD;&#xA;&#xD;&#xA;The description here is very brief, the paper in the link explains various transformations for arriving to the camera space as well; plus other topics such as camera calibration and stereo matching with hypercentric perspective cameras.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vnlE1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34811" PostHistoryTypeId="2" PostId="12190" RevisionGUID="4ec8f963-6dc1-455d-a758-5c1ac2c372a7" CreationDate="2021-09-12T02:23:34.980" UserId="48" Text="You can approximate the view of a hypercentric camera with an ordinary 3D perspective camera if you are able to manipulate the projection matrix, and/or reverse the direction of the depth test.&#xD;&#xA;&#xD;&#xA;In a hypercentric perspective the camera rays converge at a point in front of the camera. This is just the same as a regular perspective camera but with the direction of rays reversed. You can get the same collection of rays by placing an ordinary 3D camera at the hypercentric focal point, aimed backward toward the hypercentric camera lens. Then, you have to render the scene with the depth test reversed (or equivalently, swap the near and far planes in the projection matrix) so that surfaces farthest from the camera (closest to the hypercentric lens) will occlude others. You may also need to flip the direction of the backface culling test.&#xD;&#xA;&#xD;&#xA;This should produce a hypercentric perspective. The caveat to this is that it won't render anything farther away than the hypercentric focal point (contrary to a real hypercentric camera). That's because those points are behind the perspective camera, so will get clipped during rasterization. This could however be addressed by rendering the scene in two passes: first draw everything beyond the hypercentric focal point with a camera facing forward (and turned upside down), and then clear the depth buffer and draw everything in front of the hypercentric focal point with the camera facing backward as described above.&#xD;&#xA;&#xD;&#xA;It's unlikely that any of this can be accomplished in Unity with the default camera model as it's not designed for these unusual situations. You'll have to get deeper in, to a point where you can manipulate render passes, the depth buffer, and the projection matrix." ContentLicense="CC BY-SA 4.0" />
  <row Id="34812" PostHistoryTypeId="50" PostId="10824" RevisionGUID="f8cf1db9-63f1-4833-9a16-db63c80bbf36" CreationDate="2021-09-12T11:07:30.697" UserId="-1" />
  <row Id="34818" PostHistoryTypeId="2" PostId="12193" RevisionGUID="4ce87966-cea2-4b4d-a745-47f892fb35a2" CreationDate="2021-09-13T10:07:56.863" UserId="13273" Text="I am looking for an easy solution for passing information between shader stages when adding additional shader stages.&#xD;&#xA;Right now I am using the &quot;out&quot; keyword to pass data from for example vertex to fragment shader.&#xD;&#xA;On the fragment shader of cause I am using &quot;in&quot; to receive the data.&#xD;&#xA;&#xD;&#xA;**The problem I have is the following:**&#xD;&#xA;The variable name MUST be the same. So &quot;out vec3 test;&quot; can only be received by variable &quot;in vec3 test;&quot;. When optionally plug in a geometry shader to duplicate triangles, I would like to receive the outputting data from the vertex shader &quot;in vec3 test&quot; and pass it to the fragment shader &quot;out vec3 test&quot;. And here the program crashes... because both variables names are &quot;test&quot;&#xD;&#xA;&#xD;&#xA;**Here the Vertex shader code:**&#xD;&#xA;&#xD;&#xA;    #version 430&#xD;&#xA;    layout(location = 0) in vec3 vertexPosition;&#xD;&#xA;&#xD;&#xA;    out vec3 test;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vec4(vertexPosition, 1.0f);&#xD;&#xA;        test = vec3(1.0f, 2.0f, 3.0f); //this is just a test!&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**The Fragment shader code:**&#xD;&#xA;&#xD;&#xA;    #version 430&#xD;&#xA;    &#xD;&#xA;    in vec3 test;&#xD;&#xA;    out vec4 color;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        color = vec4(test, 1.0f); &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So the last shader (geometry shader) should be able to plug in if wanted, without changing the vertex or fragment shader.&#xD;&#xA;&#xD;&#xA;**The Geometry shader code:**&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (triangles) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 30) out;&#xD;&#xA;&#xD;&#xA;    in vec3 test[];  &#xD;&#xA;    out vec3 test;  // this does not work (name already exists)&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 position0 = gl_Position[0];&#xD;&#xA;        vec4 position1 = gl_Position[1];&#xD;&#xA;        vec4 position2 = gl_Position[2];      &#xD;&#xA;&#xD;&#xA;        for(uint i = 0; i &lt; 10; ++i)&#xD;&#xA;        {&#xD;&#xA;            gl_Position = position0 + vec4(i,0,0,0);   &#xD;&#xA;            test = test[0]; //this of cause does not work... (I just want to pass this information)&#xD;&#xA;            EmitVertex();&#xD;&#xA;            gl_Position = position1 + vec4(i,0,0,0);    &#xD;&#xA;            test = test[1]; //this of cause does not work... &#xD;&#xA;            EmitVertex();&#xD;&#xA;            gl_Position = position2 + vec4(i,0,0,0);    &#xD;&#xA;            test = test[2]; //this of cause does not work... &#xD;&#xA;            EmitVertex();&#xD;&#xA;    &#xD;&#xA;            EndPrimitive();&#xD;&#xA;        }    &#xD;&#xA;    }        &#xD;&#xA;        &#xD;&#xA;This geometry shader should copy the input triangle 10 times and pass the &quot;varying&quot; data from vertex to fragment shader.  &#xD;&#xA;So the goal is that the vertex and fragment shader do not need to be changed when adding or leaving out the geometry shader.    &#xD;&#xA;        &#xD;&#xA;We would like to do stuff like that for example to enable/disable layered rendering, adding a tessellation shader when wanted. Right now we need to write several shaders for the same thing. For example when having the option of enable/disable layered rendering and enable/disable tessellation there are 2^2 = 4 possibilities. This means we need to write the same shader 4 times. With this approach we only need to write it once and just plug in the shader stages when needed.&#xD;&#xA;        &#xD;&#xA;I am also interested in dynamically read out type and values of passed data. So ask within the geometry shader which variables are passed and then forward them to the next stage. With this approach we would be able to write one geometry shader which can be plugged between several other shaders.&#xD;&#xA;&#xD;&#xA;What possibilities do we have to generate such a system?&#xD;&#xA;         &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34819" PostHistoryTypeId="1" PostId="12193" RevisionGUID="4ce87966-cea2-4b4d-a745-47f892fb35a2" CreationDate="2021-09-13T10:07:56.863" UserId="13273" Text="optional geometry shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="34820" PostHistoryTypeId="3" PostId="12193" RevisionGUID="4ce87966-cea2-4b4d-a745-47f892fb35a2" CreationDate="2021-09-13T10:07:56.863" UserId="13273" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34821" PostHistoryTypeId="2" PostId="12194" RevisionGUID="bc001687-ce5f-43d1-ac20-a924bcda8157" CreationDate="2021-09-13T12:22:45.667" UserId="7952" Text="GLSL allows a location to be assigned to each in/out variables then the names can be anything you want.&#xD;&#xA;&#xD;&#xA;Here is an example:&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;    layout(location=0) out vec3 test;&#xD;&#xA;&#xD;&#xA;Geometery shader:&#xD;&#xA;&#xD;&#xA;    // as long as the location numbers match, the names don't matter&#xD;&#xA;    layout(location=0) in vec3 testIn; &#xD;&#xA;    layout(location=0) out vec3 testOut;&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;     // location 0 gets testOut from geom shader&#xD;&#xA;    layout(location=0) in vec3 randomName;&#xD;&#xA;&#xD;&#xA;If the geometry shader is removed from this example then the fragment shader will get the output of the vertex shader location 0 output." ContentLicense="CC BY-SA 4.0" />
  <row Id="34822" PostHistoryTypeId="2" PostId="12195" RevisionGUID="6474e0d7-d636-4bb3-906b-2eb019b95654" CreationDate="2021-09-14T08:08:37.000" UserId="13975" Text="I progammed a simple cloth animation.  Initially I tried to implement Hooke's law, but it wasn't numerically stable, presumably because I used explicit Euler.  Anyway, I came up with [something](https://codepen.io/fweth/full/wvedBPz) I quite like but I don't understand the math at all.&#xD;&#xA;&#xD;&#xA;Every point has a position $p$ and velocity $v$.  The position is given relative to the initial position, where the initial position of point $(i,j)$ can be thought as $(i,j,0,0)$ (I rendered the cloth in 4 dimensions to make it more interesting, but that should not make a huge difference).  There is a linear gravity term $g_v$ on the velocity which pulls the point back to its original position and also a friction term $f_v$ which slows down the velocity, so we have $v_{t+1}=f_vv_t+g_vp_t+d$ where $d$ is some external disturbance which is triggered by mouse clicks.  But the position doesn't follow just $p_{t+1}=p_t+v_{t+1}$, as I added some term to implement clothiness, so the points tend to the center of the four surrounding points.  What I came up with is $$p_{t+1}=g_pp_t+v_{t+1}+a|c|^{2/3}c$$ where the center $c$ is computed as the sum of the positions of the four neighbouring points, $g_p&lt;1$ is some kind of another gravity term and $a$ controls the clothiness. &#xD;&#xA;&#xD;&#xA;I played around with this and tried to get rid of some terms but couldn't really find a satisfying way to do so.  On the other hand, I just can't wrap my head around what I have actually done here.  It's also weird that if you click the cloth once, it more or less just changes position, but on the second click it starts to actually behave like a cloth.&#xD;&#xA;&#xD;&#xA;Can someone tell me if this math does make any sense or if there is some underlying principle for this dynamics which I accidentally approximated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34823" PostHistoryTypeId="1" PostId="12195" RevisionGUID="6474e0d7-d636-4bb3-906b-2eb019b95654" CreationDate="2021-09-14T08:08:37.000" UserId="13975" Text="What's The Math Behind This Cloth Animation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34824" PostHistoryTypeId="3" PostId="12195" RevisionGUID="6474e0d7-d636-4bb3-906b-2eb019b95654" CreationDate="2021-09-14T08:08:37.000" UserId="13975" Text="|physically-based|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34825" PostHistoryTypeId="5" PostId="12195" RevisionGUID="3833d281-7122-4c73-9daf-ccac15d0ca1b" CreationDate="2021-09-14T08:17:31.230" UserId="13975" Comment="added 51 characters in body" Text="I progammed a simple cloth animation.  Initially I tried to implement Hooke's law, but it wasn't numerically stable, presumably because I used explicit Euler.  Anyway, I came up with [something](https://codepen.io/fweth/full/wvedBPz) (WebGL2 based, won't work in Safari unfortunately) I quite like but don't understand the math at all.&#xD;&#xA;&#xD;&#xA;Every point has a position $p$ and velocity $v$.  The position is given relative to the initial position, where the initial position of point $(i,j)$ can be thought as $(i,j,0,0)$ (I rendered the cloth in 4 dimensions to make it more interesting, but that should not make a huge difference).  There is a linear gravity term $g_v$ on the velocity which pulls the point back to its original position and also a friction term $f_v$ which slows down the velocity, so we have $v_{t+1}=f_vv_t+g_vp_t+d$ where $d$ is some external disturbance which is triggered by mouse clicks.  But the position doesn't follow just $p_{t+1}=p_t+v_{t+1}$, as I added some term to implement clothiness, so the points tend to the center of the four surrounding points.  What I came up with is $$p_{t+1}=g_pp_t+v_{t+1}+a|c|^{2/3}c$$ where the center $c$ is computed as the sum of the positions of the four neighbouring points, $g_p&lt;1$ is some kind of another gravity term and $a$ controls the clothiness. &#xD;&#xA;&#xD;&#xA;I played around with this and tried to get rid of some terms but couldn't really find a satisfying way to do so.  On the other hand, I just can't wrap my head around what I have actually done here.  The velocity is not the true velocity anymore, as it doesn't reflect the change in position.  Yet the new position feeds back in the velocity via the $g_v$ term.  It's also weird that if you click the cloth once, it more or less just changes position, but on every further click it behaves much more like a cloth.&#xD;&#xA;&#xD;&#xA;Can someone tell me if this math does make any sense or if there is some underlying principle for this dynamics which I accidentally approximated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34826" PostHistoryTypeId="5" PostId="12195" RevisionGUID="46f77ddd-ae68-4616-bc79-88e21f034204" CreationDate="2021-09-14T11:09:53.790" UserId="13975" Comment="added 101 characters in body" Text="I progammed a simple cloth animation.  Initially I tried to implement Hooke's law, but it wasn't numerically stable, presumably because I used explicit Euler.  Anyway, I came up with [something](https://codepen.io/fweth/full/wvedBPz) (WebGL2 based, won't work in Safari unfortunately) I quite like but don't understand the math at all.&#xD;&#xA;&#xD;&#xA;Every point has a position $p$ and velocity $v$.  The position is given relative to the initial position, where the initial position of point $(i,j)$ can be thought as $(i,j,0,0)$ (I rendered the cloth in 4 dimensions to make it more interesting, but that should not make a huge difference).  There is a linear gravity term $g_v$ on the velocity which pulls the point back to its original position and also a friction term $f_v$ which slows down the velocity, so we have $v_{t+1}=f_vv_t+g_vp_t+d$ where $d$ is some external disturbance which is triggered by mouse clicks.  But the position doesn't follow just $p_{t+1}=p_t+v_{t+1}$, as I added some term to implement clothiness, so the points tend to the center of the four surrounding points.  What I came up with is $$p_{t+1}=g_pp_t+v_{t+1}+\frac{c}{|c|^{2/3}+1}$$ where the center $c$ is computed as the sum of the positions of the four neighbouring points, $g_p&lt;1$ is some kind of another gravity term and the $2/3$ basically just make the last term approximates $c$ for small $|c|$ but grows slower for larger values of $|c|$.&#xD;&#xA;&#xD;&#xA;I played around with this and tried to get rid of some terms but couldn't really find a satisfying way to do so.  On the other hand, I just can't wrap my head around what I have actually done here.  The velocity is not the true velocity anymore, as it doesn't reflect the change in position.  Yet the new position feeds back in the velocity via the $g_v$ term.  It's also weird that if you click the cloth once, it more or less just changes position, but on every further click it behaves much more like a cloth.&#xD;&#xA;&#xD;&#xA;Can someone tell me if this math does make any sense or if there is some underlying principle for this dynamics which I accidentally approximated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34828" PostHistoryTypeId="50" PostId="8431" RevisionGUID="b8becb07-cc76-4d27-a59b-2545d0f5d5ff" CreationDate="2021-09-15T03:05:50.473" UserId="-1" />
  <row Id="34829" PostHistoryTypeId="2" PostId="12196" RevisionGUID="f14aa4fd-328b-4d8b-8b7d-9995d059b340" CreationDate="2021-09-15T08:38:03.563" UserId="13273" Text="I am trying to pass a vec3 array from vertex shader to tessellation shader.&#xD;&#xA;&#xD;&#xA;passing just one value works fine, but how to pass an array?&#xD;&#xA;&#xD;&#xA;**Vertex shader**&#xD;&#xA;    &#xD;&#xA;    #version 430&#xD;&#xA;    out vec3 data; //working!&#xD;&#xA;    out vec3 dataArray[2];&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_position = vec4(0,0,0,0);&#xD;&#xA;        data = vec3(1,2,3);&#xD;&#xA;        dataArray[0] = vec3(1,2,3);&#xD;&#xA;        dataArray[1] = vec3(4,5,6);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;**tessellation controll shader**&#xD;&#xA;&#xD;&#xA;    #version 430&#xD;&#xA;    layout (vertices = 3) out;&#xD;&#xA;  &#xD;&#xA;    in vec3 data[]; //working!&#xD;&#xA;    in vec3 dataArray[2][]; // how to do this?&#xD;&#xA;  &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The error message is: error C7618: OpenGL/ES does not allow input array declarations with size not equal to gl_MaxPatchVertices&#xD;&#xA;&#xD;&#xA;I also tried &#xD;&#xA;&#xD;&#xA;    in vec3 dataArray[2][gl_MaxPatchVertices]&#xD;&#xA;&#xD;&#xA;But this also doesn't work.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34831" PostHistoryTypeId="1" PostId="12196" RevisionGUID="f14aa4fd-328b-4d8b-8b7d-9995d059b340" CreationDate="2021-09-15T08:38:03.563" UserId="13273" Text="glsl passing data array from vertex to tessellation control shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="34832" PostHistoryTypeId="3" PostId="12196" RevisionGUID="f14aa4fd-328b-4d8b-8b7d-9995d059b340" CreationDate="2021-09-15T08:38:03.563" UserId="13273" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34833" PostHistoryTypeId="2" PostId="12197" RevisionGUID="0e7b7b7f-cf83-4154-9811-41ae5cba53de" CreationDate="2021-09-15T09:32:19.320" UserId="17208" Text="So this is something i recently noticed. &#xD;&#xA;I have a 27inch 1440p monitor. And a game in 1080p looks pixelated on that.&#xD;&#xA;My friend has a 27 inch 1080p monitor and the same game on 1080p with all same graphics settings doesn't look pixelated on his monitor.&#xD;&#xA;&#xD;&#xA;What's up with that?&#xD;&#xA;Anything happening with upscaling on my monitor thats causing this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34835" PostHistoryTypeId="1" PostId="12197" RevisionGUID="0e7b7b7f-cf83-4154-9811-41ae5cba53de" CreationDate="2021-09-15T09:32:19.320" UserId="17208" Text="Why does a game at 1080p look better on a 1080p display than 1440p display of the same size" ContentLicense="CC BY-SA 4.0" />
  <row Id="34836" PostHistoryTypeId="3" PostId="12197" RevisionGUID="0e7b7b7f-cf83-4154-9811-41ae5cba53de" CreationDate="2021-09-15T09:32:19.320" UserId="17208" Text="|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34837" PostHistoryTypeId="2" PostId="12198" RevisionGUID="cea6c7e3-cac0-4fbc-b37b-2b7c6f2b9e5e" CreationDate="2021-09-15T10:38:44.243" UserId="7952" Text="I just went through this with a new 4k monitor under Windows 10 (but have repeated it many times with many different monitors):&#xD;&#xA;&#xD;&#xA;The On Screen Display (OSD) of the monitor should have an info page that lists it screen dimensions and frequency. For example my monitors OSD says 3840x2160 @ 60hz. So the first step is to bring up the OSD info page under Windows. If the OSD says the monitor is running at 1080p in windows then that could be affecting the game and should be changed to the native resolution, under Windows go to &quot;Display Settings&quot; and look for &quot;Display Resolution&quot;. It should be set to 1440p which would be the native resolution of the monitor. Windows will usually list the native resolution with a &quot;recommended&quot; in parenthesis next to it.  If the font size in windows is very small when switched to the native resolution, then you can use font scaling (found on the same &quot;Display Settings&quot; page in windows) to increase the font size till you like it. A reboot isn't required when this change is made, but Windows 10 always seem to be quirky until it is rebooted after a font scale change. My 2160p monitor has font scaling set to 200% and the fonts look almost printed on the screen, but the same monitor with font scaling set to 100% and the display resolution set to 1080p looks pixelated and terrible frankly.&#xD;&#xA;&#xD;&#xA;Once you are happy with the Windows settings, start up the game and use the monitors OSD to check the resolution and frequency again. Many newer games can detect and set the monitor to specific modes, but not all of them so you really have to check both windows and the game.&#xD;&#xA;&#xD;&#xA;One issue that may come up is that your Video card may not be able to sustain 30fps at 1440p. Here again some newer games will allow the game to be rendered at a lower resolution then scaled to the native resolution. The game will look a lot better scaled to the native resolution then if the monitor is running at a non-native setting.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34839" PostHistoryTypeId="2" PostId="12199" RevisionGUID="3203de3a-522e-4afe-bbb3-ccc6717a28e3" CreationDate="2021-09-15T14:33:12.297" UserId="7724" Text="Change the output of the vertex shader to&#xD;&#xA;&#xD;&#xA;    out vec3[2] dataArray;&#xD;&#xA;&#xD;&#xA;and the input to the tessellation control shader as&#xD;&#xA;&#xD;&#xA;    in vec3[2] dataArray[];&#xD;&#xA;&#xD;&#xA;That should work. Alternatively you could also define the type of dataArray as a struct.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34841" PostHistoryTypeId="2" PostId="12200" RevisionGUID="f3a3a883-6ecd-4884-a522-1e8574565ca0" CreationDate="2021-09-15T14:58:27.433" UserId="2654" Text="&gt;     in vec3 dataArray[2][]; // how to do this?&#xD;&#xA;&#xD;&#xA;[Arrays of arrays in GLSL][1] work differently than you might expect. The array indices are read left-to-right. For example, `vec2 var[2][3]` is a 2-element array of 3-element arrays of `vec2`s.&#xD;&#xA;&#xD;&#xA;What you want is an &quot;unsized array of 2 element arrays of `vec3`&quot;. To do that, you need `in vec3 dataArray[][2];`.&#xD;&#xA;&#xD;&#xA;Alternatively, you can declare the main type next to the type name and the array aggregation beside the variable name: `in vec3[2] dataArray[];`. GLSL allows this kind of split declaration style, where the array sizes on the type happen before the array sizes on the variable.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Arrays_of_arrays" ContentLicense="CC BY-SA 4.0" />
  <row Id="34843" PostHistoryTypeId="50" PostId="9364" RevisionGUID="b0f46520-f33b-423b-951d-e555ccfe8144" CreationDate="2021-09-15T23:03:05.313" UserId="-1" />
  <row Id="34844" PostHistoryTypeId="2" PostId="12201" RevisionGUID="97a815c0-1daf-4fca-84d9-5ce9b6d43382" CreationDate="2021-09-16T00:34:37.003" UserId="13456" Text="This is more of a software design problem and might suit better [software engineering se](https://softwareengineering.stackexchange.com/). &#xD;&#xA;&#xD;&#xA;If I understood right, you have a problem like this:&#xD;&#xA;```&#xD;&#xA;shader1 with parameter P=1           object1&#xD;&#xA;shader2 with parameter P=3           object2&#xD;&#xA;shader3 with parameter K=1           object3&#xD;&#xA;shader1 with parameter P=1           object4&#xD;&#xA;                  \                    /&#xD;&#xA;                   \                  /&#xD;&#xA;                    \                /&#xD;&#xA;                       drawing call&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Instead of accessing to the global OpenGL state and its shaders programs, you can do one of the following. You can either embed shaders into objects or objects into shaders.&#xD;&#xA;&#xD;&#xA;The first case is basically:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;shader1 with parameter P=1 --------&gt; object1&#xD;&#xA;                        |&#xD;&#xA;                        +----------&gt; object4&#xD;&#xA;shader2 with parameter P=3 --------&gt; object2&#xD;&#xA;shader3 with parameter K=1 --------&gt; object3&#xD;&#xA;                                       /&#xD;&#xA;                                      /&#xD;&#xA;                                     /&#xD;&#xA;                       drawing call&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The second solution (objects into shaders):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;                                     object1&#xD;&#xA;                                        |&#xD;&#xA;                     +------------------+&#xD;&#xA;                     |                  |&#xD;&#xA;                     v                  |&#xD;&#xA;shader1 with parameter P=1           object4&#xD;&#xA;shader2 with parameter P=3 &lt;-------- object2&#xD;&#xA;shader3 with parameter K=1 &lt;-------- object3&#xD;&#xA;                  \                     &#xD;&#xA;                   \                   &#xD;&#xA;                    \                 &#xD;&#xA;                       drawing call&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then during the draw call, you simply enumerate the objects in the order you wish them to be drawn with correct parameters. If the order changes dynamically along with parameters for each draw call; you either traverse the objects first to set correct parameters then draw. In the dynamic case embeding objects into your shader class might result in better performance if you have a lot of objects, since you can order objects inside your shaders according to the drawing order (the problem is simply about ordering your sublists according to the containing list `[[1,2,3],[4,5],[6,7,8,9]]`).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34846" PostHistoryTypeId="50" PostId="8291" RevisionGUID="4c1521ba-3469-43ee-9a66-53f33b0d4045" CreationDate="2021-09-16T03:08:10.730" UserId="-1" />
  <row Id="34847" PostHistoryTypeId="5" PostId="12201" RevisionGUID="3d16d063-4743-4eab-95b9-1896fb690277" CreationDate="2021-09-16T08:21:00.597" UserId="13456" Comment="changed shaders to scene management as per comments" Text="This is more of a software design problem and might suit better [software engineering se](https://softwareengineering.stackexchange.com/). &#xD;&#xA;&#xD;&#xA;If I understood right, you have a problem like this:&#xD;&#xA;```&#xD;&#xA;scene1 with parameter P=1           object1&#xD;&#xA;scene2 with parameter P=3           object2&#xD;&#xA;scene3 with parameter K=1           object3&#xD;&#xA;scene4 with parameter P=1           object4&#xD;&#xA;                  \                    /&#xD;&#xA;                   \                  /&#xD;&#xA;                    \                /&#xD;&#xA;                       drawing call&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;You can do one of the following. You can either embed states into objects or objects into scene states.&#xD;&#xA;&#xD;&#xA;The first case is basically:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;scene1 with parameter P=1 --------&gt; object1&#xD;&#xA;                       |&#xD;&#xA;                       +----------&gt; object4&#xD;&#xA;scene2 with parameter P=3 --------&gt; object2&#xD;&#xA;scene3 with parameter K=1 --------&gt; object3&#xD;&#xA;                                       /&#xD;&#xA;                                      /&#xD;&#xA;                                     /&#xD;&#xA;                       drawing call&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The second solution (objects into shaders):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;                                     object1&#xD;&#xA;                                        |&#xD;&#xA;                     +------------------+&#xD;&#xA;                     |                  |&#xD;&#xA;                     v                  |&#xD;&#xA;scene1 with parameter P=1           object4&#xD;&#xA;scene2 with parameter P=3 &lt;-------- object2&#xD;&#xA;scene3 with parameter K=1 &lt;-------- object3&#xD;&#xA;                  \                     &#xD;&#xA;                   \                   &#xD;&#xA;                    \                 &#xD;&#xA;                       drawing call&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then during the draw call, you simply enumerate the objects in the order you wish them to be drawn with correct parameters. If the order changes dynamically along with parameters for each draw call; you either traverse the objects first to set correct parameters then draw. In the dynamic case embeding objects into your scene state class might result in better performance if you have a lot of objects, since you can order objects inside your scene states according to the drawing order (the problem is simply about ordering your sublists according to the containing list `[[1,2,3],[4,5],[6,7,8,9]]`).&#xD;&#xA;&#xD;&#xA;**Update 01 - 16/09/2021**&#xD;&#xA;&#xD;&#xA;The global state of OpenGL can be accessed using [`glGet` function of state management functions](http://docs.gl/gl3/glGet). You can write a wrapper class over those functions as you had stated in the comments. If you need to access primitives and related information dynamically to determine state, you should be able to do so with query functions such as [`glBeginQuery`](http://docs.gl/gl3/glBeginQuery) &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34848" PostHistoryTypeId="2" PostId="12202" RevisionGUID="41443356-6810-4478-bf77-d5b444672998" CreationDate="2021-09-16T15:24:06.620" UserId="13348" Text="I am more less familiarized with the major computer graphics concepts up to certain dregree of &quot;low-levelness&quot;. So I know how models, vertices, poligons etc and how these works. Also how is the info in these (meaning the models) serialized and interpreted by a software, generally a game or graphics engine, to use this models info, vertices and indices, to get the model itself and handle it accordingly.&#xD;&#xA;&#xD;&#xA;Thats why I was surprised when I found some [wireframe models](https://en.wikipedia.org/wiki/Wire-frame_model), because I am not familiar neither with the concept nor the purpose of these.&#xD;&#xA;&#xD;&#xA;1.- Are these handled (seralized and de-serialized) same as regular vertices models? Back in the beginning of computer graphics guess this was about all a computer could easily do, but is there any other purpose?&#xD;&#xA;&#xD;&#xA;2.- If there is a wireframe resource provided such as [this](https://www.spriters-resource.com/pc_computer/starcraft/sheet/59990/), how it would me used/handled. In the case of a 2D isometric view game, I do not know what would I need to do with resources provided in this format. What would be roughly the approach? There are no vertices in this case, the wireframe is provided as a sprite resource, so what is it that needs to be done roughly to make use of it?&#xD;&#xA;&#xD;&#xA;I am not after an specific algorithm to handle this, this is not a code question. I mean what would be the general concept/workflow for this type of resource." ContentLicense="CC BY-SA 4.0" />
  <row Id="34850" PostHistoryTypeId="1" PostId="12202" RevisionGUID="41443356-6810-4478-bf77-d5b444672998" CreationDate="2021-09-16T15:24:06.620" UserId="13348" Text="Purpose and workflow of wireframe models" ContentLicense="CC BY-SA 4.0" />
  <row Id="34851" PostHistoryTypeId="3" PostId="12202" RevisionGUID="41443356-6810-4478-bf77-d5b444672998" CreationDate="2021-09-16T15:24:06.620" UserId="13348" Text="|2d-graphics|model|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34856" PostHistoryTypeId="5" PostId="12202" RevisionGUID="03c41335-7a7c-4a0c-9300-d6be4b3223c7" CreationDate="2021-09-16T16:47:20.077" UserId="38" Comment="added 1 character in body" Text="I am more less familiarized with the major computer graphics concepts up to certain dregree of &quot;low-levelness&quot;. So I know how models, vertices, polygons etc. and how these works. Also how is the info in these (meaning the models) serialized and interpreted by a software, generally a game or graphics engine, to use this models info, vertices and indices, to get the model itself and handle it accordingly.&#xD;&#xA;&#xD;&#xA;Thats why I was surprised when I found some [wireframe models](https://en.wikipedia.org/wiki/Wire-frame_model), because I am not familiar neither with the concept nor the purpose of these.&#xD;&#xA;&#xD;&#xA;1.- Are these handled (seralized and de-serialized) same as regular vertices models? Back in the beginning of computer graphics guess this was about all a computer could easily do, but is there any other purpose?&#xD;&#xA;&#xD;&#xA;2.- If there is a wireframe resource provided such as [this](https://www.spriters-resource.com/pc_computer/starcraft/sheet/59990/), how it would me used/handled. In the case of a 2D isometric view game, I do not know what would I need to do with resources provided in this format. What would be roughly the approach? There are no vertices in this case, the wireframe is provided as a sprite resource, so what is it that needs to be done roughly to make use of it?&#xD;&#xA;&#xD;&#xA;I am not after an specific algorithm to handle this, this is not a code question. I mean what would be the general concept/workflow for this type of resource." ContentLicense="CC BY-SA 4.0" />
  <row Id="34861" PostHistoryTypeId="2" PostId="12205" RevisionGUID="41692d86-8b9d-4f37-88c4-f3d920b09792" CreationDate="2021-09-16T18:58:34.887" UserId="7952" Text="Regarding wireframes as an edge list.&#xD;&#xA;&#xD;&#xA;Wireframe models are used in engineering and CAD they provide several benefits. The Wikipedia page you linked has some benefits, this [AutoCAD page][1] has some more. Wireframe are used less in games and movies since they are generally more concerned about the visuals and wireframes are more concerned about design (form over function).  But wireframes can be converted for rasterization and will get used in games/movies but so far as I have seen are converted (to the appropriate format) first, ( I am going to guess that there are games that use wireframe almost exclusively, but I haven't had the pleasure...knock on wood)&#xD;&#xA;&#xD;&#xA;The source you linked in the second question is not a edge list wire frame since there is no source for the edges provided. Sprites drawn as a wireframe are yet another thing again, usually the background is clear and the sprite is drawn over another sprite to give it an outline. Such as when it is selected or a mouse if hovering over it.&#xD;&#xA;&#xD;&#xA;Games and most rendering tools overload the term &quot;wireframe&quot; when referring to a triangle mesh drawn as lines without filling the triangles, sometimes drawn as quads, again just as lines. This is not the same thing as a wire frame model either since a wireframe model is comprised edge lists. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-Core/files/GUID-84E193D7-A18D-4EE2-B978-19E4AFBCAEEC-htm.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="34865" PostHistoryTypeId="2" PostId="12207" RevisionGUID="837eb855-3320-4dd0-b4bf-ad4b1bf865c0" CreationDate="2021-09-17T09:16:24.550" UserId="38" Text="1. Why are wireframes used? &#xD;&#xA;  &#xD;&#xA;   * Games don't really use wireframes much, but they might be useful for HUD items etc.&#xD;&#xA;   * Asset creators, designers and engineers use wireframes to see whats inside objects. TO clarify the edged between elements or to preview unimportant aspects. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;     **Image 1**: Different 3D views (click to zoom)&#xD;&#xA;&#xD;&#xA;      Engineers and Architects also may have very complex pure line drawings, with millions of lines and they would like to have them accelerated. (Imagine having each brick in one layer for a shopping mall, along with lines for each strut, electrical wire bundle, each air and plumbing pipe and each furniture in one drawing.) Nothing kills productivity like having a sluggish CAD response.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;   * Selection highlight etc.&#xD;&#xA;&#xD;&#xA;     &lt;img src=&quot;https://i.stack.imgur.com/QsZwg.png&quot; height=&quot;180&quot; /&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;   **Note**: Gamer card drivers don't frequently have, or have lacking wireframe acceleration routines, while the workstation versions of the cards do.&#xD;&#xA;&#xD;&#xA;1. How are wireframes drawn?&#xD;&#xA;&#xD;&#xA;   Same way as polygons, or just as lists of points to be joined&#xD;&#xA;&#xD;&#xA;2.  *&quot;If there is a wireframe resource provided such as this, how it would me used/handled. In the case of a 2D isometric view game, I do not know what would I need to do with resources provided in this format.&quot;*&#xD;&#xA;&#xD;&#xA;    its not a wireframe. Its a sprite sheet. Don't confuse the technical meaning of wireframe in computer graphics and how ui designers use teh word to mean different things.&#xD;&#xA;&#xD;&#xA;    Presumably your game engine has a method for defining sprite sheets. Otherwise you would just use a shader to make them. &#xD;&#xA;&#xD;&#xA;    Its not really related to the body of the question you asked should be separated into a different question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ukO7h.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QsZwg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34867" PostHistoryTypeId="5" PostId="12207" RevisionGUID="f172af9a-4c84-4c11-a674-704db1f82ae8" CreationDate="2021-09-17T09:29:26.757" UserId="38" Comment="edited body" Text="1. Why are wireframes used? &#xD;&#xA;  &#xD;&#xA;   * Games don't really use wireframes much, but they might be useful for HUD items etc.&#xD;&#xA;   * Asset creators, designers and engineers use wireframes to see whats inside objects. TO clarify the edged between elements or to preview unimportant aspects. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;     **Image 1**: Different 3D views (click to zoom)&#xD;&#xA;&#xD;&#xA;      Engineers and Architects also may have very complex pure line drawings, with millions of lines and they would like to have them accelerated. (Imagine having each brick in one layer for a shopping mall, along with lines for each strut, electrical wire bundle, each air and plumbing pipe and each furniture in one drawing.) Nothing kills productivity like having a sluggish CAD response.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;   * Selection highlight etc.&#xD;&#xA;&#xD;&#xA;     &lt;img src=&quot;https://i.stack.imgur.com/QsZwg.png&quot; height=&quot;180&quot; /&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;   **Note**: Gamer card drivers don't frequently have, or have lacking wireframe acceleration routines, while the workstation versions of the cards do.&#xD;&#xA;&#xD;&#xA;1. How are wireframes drawn?&#xD;&#xA;&#xD;&#xA;   Same way as polygons, or just as lists of points to be joined&#xD;&#xA;&#xD;&#xA;2.  *&quot;If there is a wireframe resource provided such as this, how it would me used/handled. In the case of a 2D isometric view game, I do not know what would I need to do with resources provided in this format.&quot;*&#xD;&#xA;&#xD;&#xA;    its not a wireframe. Its a sprite sheet. Don't confuse the technical meaning of wireframe in computer graphics and how ui designers use the word to mean different things.&#xD;&#xA;&#xD;&#xA;    Presumably your game engine has a method for defining sprite sheets. Otherwise you would just use a shader to make them. &#xD;&#xA;&#xD;&#xA;    Its not really related to the body of the question you asked should be separated into a different question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ukO7h.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QsZwg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34868" PostHistoryTypeId="2" PostId="12208" RevisionGUID="9e0ddba5-2acc-4600-a039-a75f0aa0e20d" CreationDate="2021-09-17T11:52:36.100" UserId="17223" Text="I am trying to derive the formula for perspective correct texture interpolation on my own while implementing my own software rasterizer (projecting an arbitrarily rotated triangle in camera space on the projection plane and rasterize its texture). Sure, the solution is that one can interpolate the inverse of z in the projection plane (or screen space). However, given the assumption that I do not know that yet, all I came up with so far is the following:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1] &#xD;&#xA;&#xD;&#xA;My first step was to formulate the problem (maybe my problem statement is the problem?) and visualize it. Then I tried to find some relations between the variables.&#xD;&#xA;&#xD;&#xA;What I am now looking for is some hint / observation that leads to right direction (not the solution). &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FsW63.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34870" PostHistoryTypeId="1" PostId="12208" RevisionGUID="9e0ddba5-2acc-4600-a039-a75f0aa0e20d" CreationDate="2021-09-17T11:52:36.100" UserId="17223" Text="Deriving formula for perspective correct texture interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="34871" PostHistoryTypeId="3" PostId="12208" RevisionGUID="9e0ddba5-2acc-4600-a039-a75f0aa0e20d" CreationDate="2021-09-17T11:52:36.100" UserId="17223" Text="|texture|mathematics|perspective|interpolation|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34872" PostHistoryTypeId="5" PostId="12207" RevisionGUID="bb6fc913-690a-4f7f-acf2-06a62d108a3f" CreationDate="2021-09-17T11:59:26.173" UserId="38" Comment="added 55 characters in body" Text="1. Why are wireframes used? &#xD;&#xA;  &#xD;&#xA;   * Games don't really use wireframes much, but they might be useful for HUD items etc.&#xD;&#xA;   * Asset creators, designers and engineers use wireframes to see whats inside objects. TO clarify the edged between elements or to preview unimportant aspects. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;     [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;     **Image 1**: Different 3D views (click to zoom)&#xD;&#xA;&#xD;&#xA;      Engineers and Architects also may have very complex pure line drawings, with millions of lines and they would like to have them accelerated. (Imagine having each brick in one layer for a shopping mall, along with lines for each strut, electrical wire bundle, each air and plumbing pipe and each furniture in one drawing.) Nothing kills productivity like having a sluggish CAD response.&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;   * Selection highlight etc.&#xD;&#xA;&#xD;&#xA;     &lt;img src=&quot;https://i.stack.imgur.com/QsZwg.png&quot; height=&quot;180&quot; /&gt;&#xD;&#xA;&#xD;&#xA;      **Image 2**: Edge loop Selected and highlighted&#xD;&#xA;&#xD;&#xA;   **Note**: Gamer card drivers don't frequently have, or have lacking wireframe acceleration routines, while the workstation versions of the cards do.&#xD;&#xA;&#xD;&#xA;1. How are wireframes drawn?&#xD;&#xA;&#xD;&#xA;   Same way as polygons, or just as lists of points to be joined&#xD;&#xA;&#xD;&#xA;2.  *&quot;If there is a wireframe resource provided such as this, how it would me used/handled. In the case of a 2D isometric view game, I do not know what would I need to do with resources provided in this format.&quot;*&#xD;&#xA;&#xD;&#xA;    its not a wireframe. Its a sprite sheet. Don't confuse the technical meaning of wireframe in computer graphics and how ui designers use the word to mean different things.&#xD;&#xA;&#xD;&#xA;    Presumably your game engine has a method for defining sprite sheets. Otherwise you would just use a shader to make them. &#xD;&#xA;&#xD;&#xA;    Its not really related to the body of the question you asked should be separated into a different question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ukO7h.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QsZwg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34873" PostHistoryTypeId="2" PostId="12209" RevisionGUID="81f0571d-e18f-4b2c-9ccd-fc785073ed95" CreationDate="2021-09-17T12:52:23.857" UserId="17225" Text="In my experience using VBO allows to render model consisting of 500 million triangles in realtime (more then 20 fps) on NVidia RTX 2080 videocard.&#xD;&#xA;&#xD;&#xA;Model size is 8GB, there is 11GB available video memory" ContentLicense="CC BY-SA 4.0" />
  <row Id="34875" PostHistoryTypeId="2" PostId="12210" RevisionGUID="eb0defcc-b995-41df-b554-1b6494655eb6" CreationDate="2021-09-17T15:26:24.267" UserId="7952" Text="This is to long for a comment so I put it as an answer (but it is really more of a long comment)&#xD;&#xA;&#xD;&#xA;Deriving formula for perspective correct texture interpolation : solving for texture coordinate interpolation is the same as solving for any arbitrary attribute interpolation. So you could also title this: Deriving formula for perspective correct interpolation&#xD;&#xA;&#xD;&#xA;The diagram is on the right track but all the x's and z's can be confusing to follow. I suggest just giving positions on the diagram plain old points. For example naming points on the triangle p1 and p2, then naming points on the image plain q1 and q2, ect. That makes it a easier/more intuitive to follow the math which would then refer to the individual components. Like $q_x$ and $p_z$ for arbitrary points on either plane.&#xD;&#xA;&#xD;&#xA;I think the solution is slightly easier to find if you fix s=1 and compute d (sometimes called the focal length). This corresponds better to a standard projection matrix as well. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34880" PostHistoryTypeId="52" PostId="12208" RevisionGUID="ae4809e4-bf95-499b-86d3-5767b2580d4f" CreationDate="2021-09-17T19:52:46.407" />
  <row Id="34883" PostHistoryTypeId="10" PostId="1793" RevisionGUID="32dccef6-6eec-455f-b997-8e950a4a7254" CreationDate="2021-09-18T02:51:57.397" UserId="482" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}]}" />
  <row Id="34891" PostHistoryTypeId="50" PostId="10154" RevisionGUID="af2392b2-2df9-4b78-aefb-118d24a6bc5d" CreationDate="2021-09-19T19:01:40.140" UserId="-1" />
  <row Id="34892" PostHistoryTypeId="2" PostId="12213" RevisionGUID="f6f6b0e3-a963-4131-ad4e-b770addb15aa" CreationDate="2021-09-20T18:11:31.937" UserId="10193" Text="In different sources I see ACES tonemapping, but I see one of two possible sets of formulas:&#xD;&#xA;&#xD;&#xA; 1. https://www.shadertoy.com/view/XsGfWV this one&#xD;&#xA; 2. https://www.shadertoy.com/view/tdffDl or this&#xD;&#xA;&#xD;&#xA;I compared them and the first one looks better, it can transform very bright monochromatic light to white.&#xD;&#xA;&#xD;&#xA;But the question is: why do they both are called ACES and what is the &quot;true&quot; ACES? It seems like number 2 is used alot though number 1 looks better." ContentLicense="CC BY-SA 4.0" />
  <row Id="34894" PostHistoryTypeId="1" PostId="12213" RevisionGUID="f6f6b0e3-a963-4131-ad4e-b770addb15aa" CreationDate="2021-09-20T18:11:31.937" UserId="10193" Text="ACES tonemapping confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="34895" PostHistoryTypeId="3" PostId="12213" RevisionGUID="f6f6b0e3-a963-4131-ad4e-b770addb15aa" CreationDate="2021-09-20T18:11:31.937" UserId="10193" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34896" PostHistoryTypeId="2" PostId="12214" RevisionGUID="50901b9f-055d-4437-89a4-21809088b424" CreationDate="2021-09-20T19:08:26.473" UserId="10129" Text="Second link that you've presented is using exactly the same formula as one used in Krzysztof's Narkowicz blog (and used in UE4) - https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ - his blog provide source, which is official ACES github.&#xD;&#xA;&#xD;&#xA;At the same time, source provide in first shadertoy code, points to official ACES website - http://www.oscars.org/science-technology/sci-tech-projects/aces - in which you can find link to the official ACES github (https://github.com/ampas/aces-dev) which is the same as provided by Krzysztof Narkowicz.&#xD;&#xA;&#xD;&#xA;**In conclusion:** It looks like both code is using official ACES formula, but different versions. As you can see in ACES github, there are version up to 1.3. Therefore, two shadertoy codes that you've presented are probably using different versions." ContentLicense="CC BY-SA 4.0" />
  <row Id="34898" PostHistoryTypeId="5" PostId="12214" RevisionGUID="4758f66a-ab12-472a-bc11-92865df279a2" CreationDate="2021-09-20T20:50:38.893" UserId="10129" Comment="added 117 characters in body" Text="Second link that you've presented is using exactly the same formula as one used in Krzysztof's Narkowicz blog (and used in UE4) - https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ - his blog provide source, which is official ACES github.&#xD;&#xA;&#xD;&#xA;At the same time, source provide in first shadertoy code, points to official ACES website - http://www.oscars.org/science-technology/sci-tech-projects/aces - in which you can find link to the official ACES github (https://github.com/ampas/aces-dev) which is the same as provided by Krzysztof Narkowicz.&#xD;&#xA;&#xD;&#xA;**In conclusion:** It looks like both code is using official ACES formula, but different versions. As you can see in ACES github, there are version up to 1.3. Therefore, two shadertoy codes that you've presented are probably using different versions.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Edit: Read Nathan Reed's comment below. Indeed I forgot that Krzysztof Narkowicz's version is approximation." ContentLicense="CC BY-SA 4.0" />
  <row Id="34899" PostHistoryTypeId="52" PostId="12213" RevisionGUID="0ecb328b-94bf-4c7c-8e42-44f1e4da759f" CreationDate="2021-09-21T02:13:21.713" />
  <row Id="34900" PostHistoryTypeId="2" PostId="12215" RevisionGUID="93820b09-ce12-4eb1-b2ec-f1150abdc445" CreationDate="2021-09-21T19:03:19.450" UserId="17240" Text="I'm trying to implement voxel world using OpenGL (Core 3.3). I've come across a problem with transparency. It looks like sometimes GPU decides to not render stuff that would be important. Can you help me diagnose the problem, please? &#xD;&#xA;(I thought this problem can be related to sorting (I don't perform any extra sorting at the moment), but I've changed &quot;clear color&quot; to glClearColor(1.0f, 1.0f, 1.0f, 0.01f); and the &quot;gaps&quot; are still noticeable)&#xD;&#xA;Here are some pictures:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QaKhT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ahFb2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JUwqg.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/8nOV0.png&#xD;&#xA;&#xD;&#xA;The Ftagment Shader is very simple:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    in vec2 v_TexCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_Texture;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 texColor = texture(u_Texture, v_TexCoord);&#xD;&#xA;        if(texColor.a &lt; 0.2)&#xD;&#xA;            discard;&#xD;&#xA;        FragColor = texColor;&#xD;&#xA;    }&#xD;&#xA;Depth test and blending:&#xD;&#xA;&#xD;&#xA;    void Renderer::clear() const {&#xD;&#xA;        glClearColor(0.53f, 0.8f, 0.92f, 1.0f);&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Before render loop&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;    glEnable(GL_DEPTH_TEST);&#xD;&#xA;&#xD;&#xA;Do you have any idea how can I fix this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34902" PostHistoryTypeId="1" PostId="12215" RevisionGUID="93820b09-ce12-4eb1-b2ec-f1150abdc445" CreationDate="2021-09-21T19:03:19.450" UserId="17240" Text="OpenGL transparency - object behind is not rendered" ContentLicense="CC BY-SA 4.0" />
  <row Id="34903" PostHistoryTypeId="3" PostId="12215" RevisionGUID="93820b09-ce12-4eb1-b2ec-f1150abdc445" CreationDate="2021-09-21T19:03:19.450" UserId="17240" Text="|opengl|3d|fragment-shader|transparency|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34907" PostHistoryTypeId="2" PostId="12217" RevisionGUID="45afa7a5-f3f7-4e21-9ff5-5674ffecce0e" CreationDate="2021-09-21T20:27:09.910" UserId="10193" Text="I know we can't bind the same texture as an input resource to a shader and as a render target within a single draw call, Direct3D just forces unbinding of such a texture SRV, OpenGL says it's undefined behaviour, and I am not sure about Vulkan.&#xD;&#xA;&#xD;&#xA;We can bypass that via Unordered Access Views in Direct3D or Images in OpenGL though.&#xD;&#xA;&#xD;&#xA;But the question is: what is the reason of these limitations **in case we know that every fragment shader thread reads and writes the same texel just once from hardware perspective?**&#xD;&#xA;&#xD;&#xA;I can imagine that this won't work due to reads and writes caching if we deal with another case not mentioned above, with some random read/write positions and counts, but what about this specific case I asked about? Shouldn't we safely read values from read cache and write values into write cache and just flush write cache in the end overwriting previous content and do not worry about asynchronous glitches?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34909" PostHistoryTypeId="1" PostId="12217" RevisionGUID="45afa7a5-f3f7-4e21-9ff5-5674ffecce0e" CreationDate="2021-09-21T20:27:09.910" UserId="10193" Text="Graphics APIs: read/write the same texture" ContentLicense="CC BY-SA 4.0" />
  <row Id="34910" PostHistoryTypeId="3" PostId="12217" RevisionGUID="45afa7a5-f3f7-4e21-9ff5-5674ffecce0e" CreationDate="2021-09-21T20:27:09.910" UserId="10193" Text="|rendering|texture|api|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34911" PostHistoryTypeId="5" PostId="12215" RevisionGUID="9a19bded-9b6f-4c06-a447-99521570cb8c" CreationDate="2021-09-21T22:19:37.447" UserId="17240" Comment="added 302 characters in body" Text="I'm trying to implement voxel world using OpenGL (Core 3.3). I've come across a problem with transparency. It looks like sometimes GPU decides to not render stuff that would be important. Can you help me diagnose the problem, please? &#xD;&#xA;(I thought this problem can be related to sorting (I don't perform any extra sorting at the moment), but I've changed &quot;clear color&quot; to glClearColor(1.0f, 1.0f, 1.0f, 0.01f); and the &quot;gaps&quot; are still noticeable)&#xD;&#xA;&#xD;&#xA;**EDIT:** I've found a resource that claims that it is indeed  sorting problem and drawing background triangles at first should solve this issue. However every 'chunk' (16x16 blocks' column) is rendered as a separate batch with single draw call. Is there a way to preserve this batch rendering?  &#xD;&#xA;&#xD;&#xA;Here are some pictures:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QaKhT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ahFb2.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JUwqg.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/8nOV0.png&#xD;&#xA;&#xD;&#xA;The Ftagment Shader is very simple:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    in vec2 v_TexCoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D u_Texture;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        vec4 texColor = texture(u_Texture, v_TexCoord);&#xD;&#xA;        if(texColor.a &lt; 0.2)&#xD;&#xA;            discard;&#xD;&#xA;        FragColor = texColor;&#xD;&#xA;    }&#xD;&#xA;Depth test and blending:&#xD;&#xA;&#xD;&#xA;    void Renderer::clear() const {&#xD;&#xA;        glClearColor(0.53f, 0.8f, 0.92f, 1.0f);&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //Before render loop&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;    glEnable(GL_DEPTH_TEST);&#xD;&#xA;&#xD;&#xA;Do you have any idea how can I fix this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34916" PostHistoryTypeId="33" PostId="12151" RevisionGUID="92aca13b-c6a9-42ac-965f-7f88848f6dfd" CreationDate="2021-09-22T04:33:14.463" UserId="6046" Comment="70" />
  <row Id="34917" PostHistoryTypeId="2" PostId="12219" RevisionGUID="85bca36a-6f94-49d1-b874-ca5c9e419d60" CreationDate="2021-09-22T09:21:57.950" UserId="13273" Text="It depends on the order of rendering. When first rendering the object which is far away and then rendering the closer object, the transparency will work. Otherwise when first rendering the close object, you depthbuffer will block the object which is behind.&#xD;&#xA;There are different ways to manage this issue:&#xD;&#xA;&#xD;&#xA;1:First render all opaque geometries. and then render the transparent.&#xD;&#xA;&#xD;&#xA;This gives you NOT the correct output, because other transparent objects which are behind transparent objects will cause the same problem you described. But opaque objects will always be visible.&#xD;&#xA;&#xD;&#xA;2:Use other rendertechniques like Order independent transparencies (OIT)&#xD;&#xA;&#xD;&#xA;Here you create a list of fragments (pixels) for each pixel on your screen. The list of fragments must hold the depth and color value. when all geometry is rendered, you can iterate through each list and sort the fragments by the depth value and render them again from back to front. This will give you a very good final image.&#xD;&#xA;&#xD;&#xA;This technique can be improved when first enable depth writing, depth testing and rendering the opaque objects.&#xD;&#xA;Disable depth writing, enable depth testing. And then render the transparent ones. This will shrink your list size. &#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="34930" PostHistoryTypeId="50" PostId="9614" RevisionGUID="7c9dc4aa-02fd-4af2-82e2-56a7bd5f88ab" CreationDate="2021-09-24T22:06:05.563" UserId="-1" />
  <row Id="34931" PostHistoryTypeId="2" PostId="12221" RevisionGUID="ed68593e-536e-4d9e-9f95-ea0568a35a4d" CreationDate="2021-09-25T08:23:19.853" UserId="9779" Text="My actual problem is considerably more complex, but can be solved if there is a cheap way to compute the intersection of a ray with a regular grid of circles. If I had a circle centered at every integer (x,y) pair, and a ray in xy space, what's the fastest way to determine where the ray first intersects the surface of a circtle? My ray origin will not be inside one of the circles.&#xD;&#xA;&#xD;&#xA;The grid will be at least 256x256, so a signed distance function would be far too expensive, as I'd have to allow too many iterations to get the answer I need. I'm hoping that there's a mathematical solution to my problem so I can get this over in a dozen or two floating point operations. If a solution exists, I would assume that it will test against an infinite grid. I can happily cull intersections outside of the finite space in which I am working.&#xD;&#xA;&#xD;&#xA;  Thanks..." ContentLicense="CC BY-SA 4.0" />
  <row Id="34933" PostHistoryTypeId="1" PostId="12221" RevisionGUID="ed68593e-536e-4d9e-9f95-ea0568a35a4d" CreationDate="2021-09-25T08:23:19.853" UserId="9779" Text="Is there a mathematical (as opposed to iterative/SDF) test for ray intersection with a grid of circles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34934" PostHistoryTypeId="3" PostId="12221" RevisionGUID="ed68593e-536e-4d9e-9f95-ea0568a35a4d" CreationDate="2021-09-25T08:23:19.853" UserId="9779" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34936" PostHistoryTypeId="50" PostId="9116" RevisionGUID="57837be5-948b-42d4-aff9-6fe3a821fe1d" CreationDate="2021-09-25T10:02:25.237" UserId="-1" />
  <row Id="34937" PostHistoryTypeId="2" PostId="12222" RevisionGUID="d8e8e5bd-e80a-4e3c-9a5b-227787d4a9e9" CreationDate="2021-09-26T09:59:49.653" UserId="17270" Text="I have a question about Peter Shirley's Ray tracing in one weekend. In the [True Lambertian Reflection section](https://raytracing.github.io/books/RayTracingInOneWeekend.html#diffusematerials/truelambertianreflection), when talking about rejection method, he said &#xD;&#xA;&gt; This distribution scales by the cos^3(ϕ) where ϕ is the angle from normal&#xD;&#xA;&#xD;&#xA;Can anyone please tell me where the exponent 3 comes from?&#xD;&#xA;Thanks!&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="34939" PostHistoryTypeId="1" PostId="12222" RevisionGUID="d8e8e5bd-e80a-4e3c-9a5b-227787d4a9e9" CreationDate="2021-09-26T09:59:49.653" UserId="17270" Text="question about true Lambertian reflection in Ray tracing in one weekend" ContentLicense="CC BY-SA 4.0" />
  <row Id="34940" PostHistoryTypeId="3" PostId="12222" RevisionGUID="d8e8e5bd-e80a-4e3c-9a5b-227787d4a9e9" CreationDate="2021-09-26T09:59:49.653" UserId="17270" Text="|raytracing|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34941" PostHistoryTypeId="2" PostId="12223" RevisionGUID="69271244-b8b7-4737-ab00-122650acbfdc" CreationDate="2021-09-26T14:04:08.460" UserId="7952" Text="The two graphs are graphing Cubic Splines but they are not equivalent splines. The method used in the code you linked produces a curve that is very local to the points and produces the tightest fit to a data set of any of the curves. This curve is only affect by adjacent (knots) control points.&#xD;&#xA;&#xD;&#xA;The method used in the online calculator produces a similar curve but individual segments are affected by control points that are up to 2 positions away which change the tangent and causes the big dips in the curve shown in the graph.&#xD;&#xA;&#xD;&#xA;You should be able to convince yourself of this by looking at the two matrices used in the solution for both curves. The tridiagonal matrix can only affect adjacent rows and columns where as the matrix shown in the solution for the online calculator effects several rows and columns, this translates to very different curves.&#xD;&#xA;&#xD;&#xA;I attempted to use Mathematica to check the curve produced by the linked code but the resulting curve (as described by the wolfram math web link in the references you gave) was not even a cubic spline.&#xD;&#xA;&#xD;&#xA;I was able to verify the curve output by the online calculator in the web link using Maple, they both produce almost identical equations. MatLab supposedly has a function that will produce the same spline linked in your code but I don't have access to that program so wasn't able to verify it.&#xD;&#xA;&#xD;&#xA;I started to convert the equations between implicit/explicit/parametric forms but that turned into more math then I am willing to do (and I didn't want to post a  massive list of equations showing the conversion). But these are not implicit vs parametric forms of the same curve anyway so it would have been kind of pointless.&#xD;&#xA;&#xD;&#xA;After all that I decided to implement my own version of the spline solver from the book wolfram references. ( I managed to get a used copy on the cheap ) My solution ended up being very similar to the code you linked and produced very similar results. The curves were slightly smoother at the control points but I think that I was using a different method of computing the values...along the lines of:&#xD;&#xA;&#xD;&#xA;    segment_count = knot_count -1;&#xD;&#xA;    vec4 solved_coefficients[segment_count];&#xD;&#xA;    vec2 curve[segment_count *100];&#xD;&#xA;    for each segment_count&#xD;&#xA;      vec4 coeff = solved_coefficients[segment];&#xD;&#xA;      for x=0 x&lt;100; x++;&#xD;&#xA;         t = 1.0/x;&#xD;&#xA;         curve[knot*x] = calcPointOnLine( coeff, t);&#xD;&#xA;&#xD;&#xA;This turned out to be a fun little side project into the different versions of fitted cubic splines.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34943" PostHistoryTypeId="2" PostId="12224" RevisionGUID="b882107f-0dcf-4963-8ee3-be0b85a86c21" CreationDate="2021-09-26T15:23:53.927" UserId="7427" Text="When designing/coding/&quot;architecting&quot; some geometry-ray intersection routines for a path tracer, there seems to be a spectrum of potential designs, with these two extremes:&#xD;&#xA;&#xD;&#xA;1. Return the distance to the intersection only&#xD;&#xA;&#xD;&#xA;1. Return the distance to the intersection, the surface normal, the material, the world coordinates, texture coordinates, barycentric coordinates, ...&#xD;&#xA;&#xD;&#xA;When we're just looking for the closest hit, the first design is obviously better. But for shading we need additional information, which could be computed quite cheaply in addition to the distance. So, perhaps it's smarter to compute this information for every intersection test? Or we could implement both routines, and use the first to find the first-hit, and then invoke the second one to re-compute the same intersection and all the additional information.&#xD;&#xA;&#xD;&#xA;**Is there a &quot;best&quot; design, or is the answer (as always) &quot;It depends&quot;?**" ContentLicense="CC BY-SA 4.0" />
  <row Id="34945" PostHistoryTypeId="1" PostId="12224" RevisionGUID="b882107f-0dcf-4963-8ee3-be0b85a86c21" CreationDate="2021-09-26T15:23:53.927" UserId="7427" Text="How much information should intersection routines return in a path tracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34946" PostHistoryTypeId="3" PostId="12224" RevisionGUID="b882107f-0dcf-4963-8ee3-be0b85a86c21" CreationDate="2021-09-26T15:23:53.927" UserId="7427" Text="|pathtracing|implementation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34947" PostHistoryTypeId="50" PostId="9781" RevisionGUID="edf581da-4efe-46f5-8971-d3480db404d8" CreationDate="2021-09-26T18:07:35.623" UserId="-1" />
  <row Id="34948" PostHistoryTypeId="5" PostId="12223" RevisionGUID="47102255-c655-4913-98fa-d9c5d68e661b" CreationDate="2021-09-26T23:38:01.113" UserId="7952" Comment="added 899 characters in body" Text="The two graphs are graphing Cubic Splines but they are not equivalent splines. The method used in the code you linked produces a curve that is very local to the points and produces the tightest fit to a data set of any of the curves. This curve is only affect by adjacent (knots) control points.&#xD;&#xA;&#xD;&#xA;The method used in the online calculator produces a similar curve but individual segments are affected by control points that are up to 2 positions away which change the tangent and causes the big dips in the curve shown in the graph.&#xD;&#xA;&#xD;&#xA;You should be able to convince yourself of this by looking at the two matrices used in the solution for both curves. The tridiagonal matrix can only affect adjacent rows and columns where as the matrix shown in the solution for the online calculator effects several rows and columns, this translates to very different curves.&#xD;&#xA;&#xD;&#xA;I attempted to use Mathematica to check the curve produced by the linked code but the resulting curve (as described by the wolfram math web link in the references you gave) was not even a cubic spline.&#xD;&#xA;&#xD;&#xA;I was able to verify the curve output by the online calculator in the web link using Maple, they both produce almost identical equations. MatLab supposedly has a function that will produce the same spline linked in your code but I don't have access to that program so wasn't able to verify it.&#xD;&#xA;&#xD;&#xA;I started to convert the equations between implicit/explicit/parametric forms but that turned into more math then I am willing to do (and I didn't want to post a  massive list of equations showing the conversion). But these are not implicit vs parametric forms of the same curve anyway so it would have been kind of pointless.&#xD;&#xA;&#xD;&#xA;After all that I decided to implement my own version of the spline solver from the book wolfram references. ( I managed to get a used copy on the cheap ) My solution ended up being very similar to the code you linked and produced very similar results. The curves were slightly smoother at the control points but I think that I was using a different method of computing the values...along the lines of:&#xD;&#xA;&#xD;&#xA;    segment_count = knot_count -1;&#xD;&#xA;    vec4 solved_coefficients[segment_count];&#xD;&#xA;    vec2 curve[segment_count *100];&#xD;&#xA;    for each segment_count&#xD;&#xA;      vec4 coeff = solved_coefficients[segment];&#xD;&#xA;      for x=0 x&lt;100; x++;&#xD;&#xA;         t = 1.0/x;&#xD;&#xA;         curve[knot*x] = calcPointOnLine( coeff, t);&#xD;&#xA;&#xD;&#xA;This turned out to be a fun little side project into the different versions of fitted cubic splines.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;The problem is that the terminology used to describe the splines is used so interchangeably that the different solutions which produce very different splines are given the same names. I found one paper which used the name &quot;Cubic Hermite Spline&quot; for the what we implemented,  and it gave the name &quot;Cubic Spline&quot; for what the online calculator implemented. &#xD;&#xA;&#xD;&#xA;It is also possible to make the splines equivalent to each other by playing with the knot positions. I refitted the Cubic spline to a Cubic Hermite by moving/adding knot positions separated by a distance of 1 and got exactly the same splines from both solutions. The other direction (which I didn't try) is to fit the cubic Hermite spline to the cubic spline by changing the knot sequence from 0,1,2,3 to 0,141,149,255. &#xD;&#xA;&#xD;&#xA;When it is all said and done I think it is more about what kind of fit works best for your algorithm.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34949" PostHistoryTypeId="50" PostId="10177" RevisionGUID="052f031e-4a05-4d29-ab6e-1337e989b956" CreationDate="2021-09-27T03:09:15.780" UserId="-1" />
  <row Id="34951" PostHistoryTypeId="34" PostId="12151" RevisionGUID="81b8ea0b-3a8d-4414-a401-7ff473affc36" CreationDate="2021-09-27T06:44:30.910" UserId="6046" Comment="70" />
  <row Id="34952" PostHistoryTypeId="2" PostId="12225" RevisionGUID="d59dbcb5-431d-4c4b-bffb-c6a160f338b4" CreationDate="2021-09-27T12:26:50.073" UserId="7647" Text="I can simplify the problem for you, but I'm not sure it's possible to do what you want in the general case. When it works, this solution will tell you which circle the ray intersects first; finding the exact intersection point is then simple.&#xD;&#xA;&#xD;&#xA;First, let's say that the ray starts at a point where $-1 &lt; x \le 0$ and is traveling in the positive x and y direction, with direction vector parallel to $(1,m)$, with $0 &lt; m \le 1$. (This can be arranged for any input by various translations and reflections.)&#xD;&#xA;&#xD;&#xA;Second, note that you don't strictly need to consider intersections with circles, just with line segments parallel to the y-axis. If the circles have radius $r$, then clearly any ray that intersects the segment $(a,b-r)-(a,b+r)$ (where $a$ and $b$ are integers) intersects the sphere at $(a,b)$. If the ray is traveling up and to the right, then there is only one situation where it can intersect the circle but not the segment:&#xD;&#xA;&#xD;&#xA;[![Image of a ray osculating a circle of radius r. The circle's center is at point C; the ray touches the circle at point O and intersects the vertical line through C at P. Q is the projection of O on the line PC.][1]][1]&#xD;&#xA;&#xD;&#xA;We can compute the extra distance $v$ by simple trigonometry. Note that the three triangles $OPC$, $QPO$, and $QOC$ are similar. The value $m$ is the slope of the ray: $PQ / OQ$, or, by similarity, $m = \ell/r$. By Pythagoras, we know that $\ell^2 + r^2 = (r+v)^2$. Substituting, we get a quadratic equation for $v$&#xD;&#xA;$$ v^2 + 2rv - m^2r^2 = 0, $$&#xD;&#xA;which has a single positive (if $r &gt; 0$) solution&#xD;&#xA;$$ v = r \left(\sqrt{1 + m^2} - 1\right). $$&#xD;&#xA;&#xD;&#xA;The ray will intersect the circle of radius $r$ at $(a,b)$ exactly when it intersects the line $x = a$ between $y = b - r$ and $y = b + r + v$. We can simplify this even further by shifting everything up by $r$; then the interval becomes $[b, b + 2r + v]$ and the ray intersects a circle at $a$ exactly when&#xD;&#xA;$$ (y_0 + r) + a m \le 2r + v \mod 1, $$&#xD;&#xA;where $y_0$ is the intersection point with the y-axis (the first vertical line it reaches, per our simplification).&#xD;&#xA;&#xD;&#xA;Then the circle intersected can (often) be found quite simply. If $y_0 + r \mod 1 &lt; 2r + v$, then it is the first circle reached, i.e. $a = 0$. If $m &lt; 2r + v$, then we can just divide the y-distance yet to be traveled by $m$, i.e.&#xD;&#xA;$$a = \left\lceil \frac{1 - (y_0 + r)}{m} \right\rceil.$$&#xD;&#xA;&#xD;&#xA;Unfortunately, the problem comes with $m &gt; 2r+v = r\left(\sqrt{1 + m^2} + 1\right)$. In this regime, it's possible for the y-intersection point to skip over the critical interval, and even to miss it entirely. In general, I'm not sure it's possible to find when the iteration hits the critical interval without some iteration of the value. Maybe there's some GCD-esque iteration that will get you the value?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QcGLQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="34954" PostHistoryTypeId="50" PostId="10852" RevisionGUID="4bee9dd4-b19e-4646-97a0-9a47fbe562ee" CreationDate="2021-09-27T18:07:40.703" UserId="-1" />
  <row Id="34955" PostHistoryTypeId="2" PostId="12226" RevisionGUID="8ef3f3fa-6aa7-4a13-9147-b1dbe8ea1373" CreationDate="2021-09-28T16:21:07.957" UserId="17275" Text="Being new to Python and this community, I am trying to plot the pulse return from a transducer. The pulse return is 400 uSecs in duration and occurs every 100 milliseconds. So far I can plot the received values that are constantly being received and the plot graphs these in a strip chart fashion scrolling from right to left. I would like to be able to present the plot similar to how an oscilloscope would display the return pulse. I am not all that familiar with Numpy arrays yet. I am not sure what I am forgetting in writing the proper syntax for this." ContentLicense="CC BY-SA 4.0" />
  <row Id="34957" PostHistoryTypeId="1" PostId="12226" RevisionGUID="8ef3f3fa-6aa7-4a13-9147-b1dbe8ea1373" CreationDate="2021-09-28T16:21:07.957" UserId="17275" Text="How to plot an ADC value from the Raspberry PI Pico using pythons matplotlib" ContentLicense="CC BY-SA 4.0" />
  <row Id="34958" PostHistoryTypeId="3" PostId="12226" RevisionGUID="8ef3f3fa-6aa7-4a13-9147-b1dbe8ea1373" CreationDate="2021-09-28T16:21:07.957" UserId="17275" Text="|2d|animation|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34959" PostHistoryTypeId="50" PostId="12163" RevisionGUID="2eb6207a-ea85-4b56-82b9-17091a145b15" CreationDate="2021-10-01T10:03:35.283" UserId="-1" />
  <row Id="34960" PostHistoryTypeId="5" PostId="12226" RevisionGUID="7f76df3d-0b83-4cc1-a110-824e858e6fb8" CreationDate="2021-10-01T17:10:48.963" UserId="17275" Comment="added 1157 characters in body" Text="Being new to Python and this community, I am trying to plot the pulse return from a transducer. The pulse return is 400 uSecs in duration and occurs every 100 milliseconds. So far I can plot the received values that are constantly being received and the plot graphs these in a strip chart fashion scrolling from right to left. I would like to be able to present the plot similar to how an oscilloscope would display the return pulse. I am not all that familiar with Numpy arrays yet. I am not sure what I am forgetting in writing the proper syntax for this. Here is a snippet of the code I am having issues with.&#xD;&#xA;&#xD;&#xA;### Parameters   ##################&#xD;&#xA;x = 300            # Number of points to display&#xD;&#xA;&#xD;&#xA;y_range = [0,300]   # Range of possible Y values to display&#xD;&#xA;#y_range = list(np.arange(0, 300))&#xD;&#xA;xs = list(np.arange(0, 300))&#xD;&#xA;ys = [0] * x&#xD;&#xA;plot1.set_ylim(y_range)&#xD;&#xA;&#xD;&#xA;###  Initialize communication with the pico and read value from ADC&#xD;&#xA;reading = analogio.AnalogIn(board.ADC0)&#xD;&#xA;&#xD;&#xA;###   Create plot line&#xD;&#xA;line, = plot1.plot(xs, ys, color= &quot;yellow&quot;)&#xD;&#xA;&#xD;&#xA;###   Start Thread&#xD;&#xA;def plot():&#xD;&#xA;    def animate(i, ys):&#xD;&#xA;    # Read data from Pico&#xD;&#xA;        DATA = reading.value/20&#xD;&#xA;    &#xD;&#xA;    #   Add y to list&#xD;&#xA;        ys.append(DATA)&#xD;&#xA;    &#xD;&#xA;    #   Limit y list to set number of items&#xD;&#xA;        ys = ys[- x:]&#xD;&#xA;        #ys = ys(np.arange(0, 300))&#xD;&#xA;    &#xD;&#xA;    #   Update line with new y values&#xD;&#xA;        line.set_ydata(ys)&#xD;&#xA;        print(&quot;ADC:&quot;, DATA) &#xD;&#xA;        return line,&#xD;&#xA;&#xD;&#xA;### Set up plot to call animate() function&#xD;&#xA;    ani = animation.FuncAnimation(fig, animate, fargs=(ys,),interval=.0001, blit=True)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;print(&quot;thread starting&quot;)&#xD;&#xA;t = threading.Thread(name='plot', target=plot)&#xD;&#xA;t.setDaemon(True)&#xD;&#xA;t.start()" ContentLicense="CC BY-SA 4.0" />
  <row Id="34961" PostHistoryTypeId="50" PostId="9146" RevisionGUID="652c53c1-82f0-4c99-8a08-65eaafeb529c" CreationDate="2021-10-01T19:05:10.560" UserId="-1" />
  <row Id="34962" PostHistoryTypeId="2" PostId="12227" RevisionGUID="075937c4-2935-4998-9dce-fd29c8c3c798" CreationDate="2021-10-01T20:33:08.657" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="34964" PostHistoryTypeId="1" PostId="12227" RevisionGUID="075937c4-2935-4998-9dce-fd29c8c3c798" CreationDate="2021-10-01T20:33:08.657" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="34965" PostHistoryTypeId="2" PostId="12228" RevisionGUID="1bae6033-2527-422e-b2c9-b787cc52babb" CreationDate="2021-10-01T20:33:08.657" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="34967" PostHistoryTypeId="1" PostId="12228" RevisionGUID="1bae6033-2527-422e-b2c9-b787cc52babb" CreationDate="2021-10-01T20:33:08.657" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="34969" PostHistoryTypeId="5" PostId="12226" RevisionGUID="394ec399-d8a1-4f65-8fe0-cd4a003b9a86" CreationDate="2021-10-02T03:13:26.720" UserId="482" Comment="add code formatting" Text="Being new to Python and this community, I am trying to plot the pulse return from a transducer. The pulse return is 400 uSecs in duration and occurs every 100 milliseconds. So far I can plot the received values that are constantly being received and the plot graphs these in a strip chart fashion scrolling from right to left. I would like to be able to present the plot similar to how an oscilloscope would display the return pulse. I am not all that familiar with Numpy arrays yet. I am not sure what I am forgetting in writing the proper syntax for this. Here is a snippet of the code I am having issues with.&#xD;&#xA;&#xD;&#xA;    ### Parameters   ##################&#xD;&#xA;    x = 300            # Number of points to display&#xD;&#xA;    &#xD;&#xA;    y_range = [0,300]   # Range of possible Y values to display&#xD;&#xA;    #y_range = list(np.arange(0, 300))&#xD;&#xA;    xs = list(np.arange(0, 300))&#xD;&#xA;    ys = [0] * x&#xD;&#xA;    plot1.set_ylim(y_range)&#xD;&#xA;    &#xD;&#xA;    ###  Initialize communication with the pico and read value from ADC&#xD;&#xA;    reading = analogio.AnalogIn(board.ADC0)&#xD;&#xA;    &#xD;&#xA;    ###   Create plot line&#xD;&#xA;    line, = plot1.plot(xs, ys, color= &quot;yellow&quot;)&#xD;&#xA;    &#xD;&#xA;    ###   Start Thread&#xD;&#xA;    def plot():&#xD;&#xA;        def animate(i, ys):&#xD;&#xA;        # Read data from Pico&#xD;&#xA;            DATA = reading.value/20&#xD;&#xA;        &#xD;&#xA;        #   Add y to list&#xD;&#xA;            ys.append(DATA)&#xD;&#xA;        &#xD;&#xA;        #   Limit y list to set number of items&#xD;&#xA;            ys = ys[- x:]&#xD;&#xA;            #ys = ys(np.arange(0, 300))&#xD;&#xA;        &#xD;&#xA;        #   Update line with new y values&#xD;&#xA;            line.set_ydata(ys)&#xD;&#xA;            print(&quot;ADC:&quot;, DATA) &#xD;&#xA;            return line,&#xD;&#xA;    &#xD;&#xA;    ### Set up plot to call animate() function&#xD;&#xA;        ani = animation.FuncAnimation(fig, animate, fargs=(ys,),interval=.0001, blit=True)&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;    &#xD;&#xA;    print(&quot;thread starting&quot;)&#xD;&#xA;    t = threading.Thread(name='plot', target=plot)&#xD;&#xA;    t.setDaemon(True)&#xD;&#xA;    t.start()" ContentLicense="CC BY-SA 4.0" />
  <row Id="34970" PostHistoryTypeId="50" PostId="10853" RevisionGUID="a22f6956-2325-4070-b3fd-9c4f4cde5cb7" CreationDate="2021-10-02T07:07:25.710" UserId="-1" />
  <row Id="34971" PostHistoryTypeId="2" PostId="12229" RevisionGUID="44df36eb-3bfe-4b61-9802-c63704d07c00" CreationDate="2021-10-02T20:57:27.927" UserId="17299" Text="I am building a volumetric ray marching shader in HLSL in Unreal Engine, based on Ryan Brucks’ work: [https://shaderbits.com/blog/creating-volumetric-ray-marcher][1]&#xD;&#xA;&#xD;&#xA;I am trying to add some additional noise to the shader using a tiling 3D noise texture, and I’ve noticed something which I don’t understand, and can’t find an explanation for - probably because I’m not exactly sure what I should be searching for to get to the bottom of the problem.&#xD;&#xA;&#xD;&#xA;The position inside the ray marched volume is normalized, so I can just use that value to read into the 3D texture. When using this value directly, I get decent performance. But as soon as I start multiplying the value in order to increase the UV tiling (and frequency of the noise) the performance drops seemingly linearly with the amount of tiling. The thing that confuses me about this is that I’m not changing the number of ray march steps or any other value, each step is simply taking a read of the 3D texture at different points.&#xD;&#xA;&#xD;&#xA;The only thing I can imagine is that this is something fundamental to do with how texture reads work, or something to do with GPU caching, and that reading from the texture in this way does so in a manner that is somehow less efficient.&#xD;&#xA;&#xD;&#xA;So I would like to understand the nature of the problem, but also understand if there is some way around it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://shaderbits.com/blog/creating-volumetric-ray-marcher" ContentLicense="CC BY-SA 4.0" />
  <row Id="34973" PostHistoryTypeId="1" PostId="12229" RevisionGUID="44df36eb-3bfe-4b61-9802-c63704d07c00" CreationDate="2021-10-02T20:57:27.927" UserId="17299" Text="Why does UV tiling affect performance in volumetric ray marching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34974" PostHistoryTypeId="3" PostId="12229" RevisionGUID="44df36eb-3bfe-4b61-9802-c63704d07c00" CreationDate="2021-10-02T20:57:27.927" UserId="17299" Text="|texture|gpu|volumetric|raymarching|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34975" PostHistoryTypeId="5" PostId="12228" RevisionGUID="349b082c-85c7-4d8e-bee8-07725bb2a539" CreationDate="2021-10-02T21:06:48.613" UserId="17297" Comment="added 151 characters in body" Text="OpenCV is a real-time computer vision library originally developed by Intel. The library is cross-platform and free for use under the Apache 2 License." ContentLicense="CC BY-SA 4.0" />
  <row Id="34976" PostHistoryTypeId="24" PostId="12228" RevisionGUID="349b082c-85c7-4d8e-bee8-07725bb2a539" CreationDate="2021-10-02T21:06:48.613" Comment="Proposed by 17297 approved by 13095 edit id of 570" ContentLicense="CC BY-SA 4.0" />
  <row Id="34977" PostHistoryTypeId="2" PostId="12230" RevisionGUID="d2c7d6ed-e2c3-4001-b3f7-d94db7c74e9c" CreationDate="2021-10-03T00:07:43.690" UserId="48" Text="It sounds like you are experiencing a loss of texture cache hit rate on your 3D texture.&#xD;&#xA;&#xD;&#xA;As with any modern processor, GPUs have a cache hierarchy. Texture units typically read from a local L1 cache, then a global L2 cache, then from DRAM. With a texture, each cache line will typically contain several adjacent texels. So, when you sample a texture at a certain location, you bring a small region surrounding that sample point into cache. If other texture samples (e.g. the corresponding samples in other nearby fragments, or later sequential samples within the same shader) hit the regions that are already in cache, they will process a lot faster than if they have to descend the cache hierarchy to get the data.&#xD;&#xA;&#xD;&#xA;So, sampling the texture at spread-out sample points (more than a few texels apart from each other) will likely be a lot slower than sampling them at closely spaced points. This will be exacerbated for 3D textures as opposed to 2D ones, because there's a lot more texels within a given distance of an initial sample point; and thus the surrounding region brought in with a cache line will tend to be smaller in diameter for 3D than for 2D.&#xD;&#xA;&#xD;&#xA;As a concrete example, supposing your texture is 8 bits per texel and a cache line is 64 bytes, a single cache line could fit an 8×8 region of a 2D texture, but only a 4×4×4 region of a 3D texture. So, as soon as your texture samples got to be further than about 4 texels from each other, you would experience a performance cliff.&#xD;&#xA;&#xD;&#xA;In ray marching, the samples will spread farther from each other the farther they are from the camera, so this perf cliff could occur at different distances depending on the texture scaling. That might explain the proportional performance drop you saw.&#xD;&#xA;&#xD;&#xA;This effect is one of the reasons why we have mipmaps. It's not just to prevent aliasing; it's also for performance. Mipmapping tries to match the texel size to the distance between adjacent texture samples, so it helps maintain higher cache hit rates as the texture gets farther away from the camera (and thus the distance in UV space between adjacent samples grows larger).&#xD;&#xA;&#xD;&#xA;If you don't have mipmaps on your noise texture, that would be the first thing I would try. Also, you can try narrowing the texture format (e.g. use 8 bits instead of 16, or 1 channel instead of 4) or using a compressed texture if possible, which will improve the number of texels per cache line.&#xD;&#xA;&#xD;&#xA;An alternative approach would be to implement a noise function instead of a texture. This can be quite fast, and the cost of the math instructions may be able to be hidden behind other texture fetches in the shader anyway." ContentLicense="CC BY-SA 4.0" />
  <row Id="34979" PostHistoryTypeId="50" PostId="10509" RevisionGUID="2df359f0-7afa-4f78-b2cd-ec87b43ae842" CreationDate="2021-10-03T04:06:50.653" UserId="-1" />
  <row Id="34980" PostHistoryTypeId="2" PostId="12231" RevisionGUID="8face230-f3bb-43f8-883b-6c0bf0803c9d" CreationDate="2021-10-04T05:34:24.347" UserId="11058" Text="I would like to use `glBufferStorage` to load data once into the vertex buffer. However sometimes I want to pass non-interleaved data from separate arrays like shown below.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glBufferStorage(GL_ARRAY_BUFFER, sizeVerts+sizeUVs, 0, 0);&#xD;&#xA;    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeVerts, verts.data());&#xD;&#xA;    glBufferSubData(GL_ARRAY_BUFFER, sizeVerts, sizeUVs, uvs.data());&#xD;&#xA;&#xD;&#xA;Because of this I have to specify `GL_DYNAMIC_STORAGE_BIT` flag, despite loading the data once, and thus use a less performant alternative.&#xD;&#xA;&#xD;&#xA;Are there any workarounds to this problem?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34982" PostHistoryTypeId="1" PostId="12231" RevisionGUID="8face230-f3bb-43f8-883b-6c0bf0803c9d" CreationDate="2021-10-04T05:34:24.347" UserId="11058" Text="Passing non-interleaved data to glBufferStorage without using glBufferSubData" ContentLicense="CC BY-SA 4.0" />
  <row Id="34983" PostHistoryTypeId="3" PostId="12231" RevisionGUID="8face230-f3bb-43f8-883b-6c0bf0803c9d" CreationDate="2021-10-04T05:34:24.347" UserId="11058" Text="|opengl|c++|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34984" PostHistoryTypeId="5" PostId="12231" RevisionGUID="ae088705-d4e2-43b1-973d-899736469a24" CreationDate="2021-10-04T05:40:02.797" UserId="11058" Comment="added 135 characters in body" Text="I would like to use `glBufferStorage` to load data once into the vertex buffer. However sometimes I want to pass non-interleaved data from separate arrays like shown below.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glBufferStorage(GL_ARRAY_BUFFER, sizeVerts+sizeUVs, 0, 0);&#xD;&#xA;    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeVerts, verts.data());&#xD;&#xA;    glBufferSubData(GL_ARRAY_BUFFER, sizeVerts, sizeUVs, uvs.data());&#xD;&#xA;&#xD;&#xA;Because of this I have to specify `GL_DYNAMIC_STORAGE_BIT` flag, despite loading the data once, and thus use a less performant alternative.&#xD;&#xA;&#xD;&#xA;Are there any workarounds to this problem?&#xD;&#xA;&#xD;&#xA;Or does using `GL_DYNAMIC_STORAGE_BIT` not lead to a significant performance hit, and should I just use it despite loading data once?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34985" PostHistoryTypeId="50" PostId="10537" RevisionGUID="c87d6ff9-6860-4304-9030-d05debb93c0e" CreationDate="2021-10-04T07:04:25.463" UserId="-1" />
  <row Id="34986" PostHistoryTypeId="50" PostId="5547" RevisionGUID="86867187-5ca7-4533-a839-e318a130d3b5" CreationDate="2021-10-04T09:01:05.190" UserId="-1" />
  <row Id="34987" PostHistoryTypeId="2" PostId="12232" RevisionGUID="998da7df-6f0f-484a-bc00-10f6697e31f7" CreationDate="2021-10-04T15:55:25.687" UserId="2654" Text="You can put your data in one piece of memory on the CPU and then copy it in with `glBufferStorage`. It's just a bunch of `memcpy` calls.&#xD;&#xA;&#xD;&#xA;With C++20's `std::span` (or the GSL version), you can even make a function to build byte-spans from any number of `vector&lt;T&gt;`s (even of different types) and do the building and `memcpy`'s manually.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;#include &lt;vector&gt;&#xD;&#xA;#include &lt;concepts&gt;&#xD;&#xA;#include &lt;ranges&gt;&#xD;&#xA;#include &lt;span&gt;&#xD;&#xA;#include &lt;cstdint&gt;&#xD;&#xA;#include &lt;cstring&gt;&#xD;&#xA;&#xD;&#xA;using byte_range = std::span&lt;std::byte const, std::dynamic_extent&gt;;&#xD;&#xA;&#xD;&#xA;template&lt;std::ranges::contiguous_range Rng&gt;&#xD;&#xA;byte_range get_span(Rng const &amp;rng)&#xD;&#xA;{&#xD;&#xA;    auto sp = std::span(rng);&#xD;&#xA;    return std::as_bytes(sp);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;template&lt;std::ranges::contiguous_range ...Rngs&gt;&#xD;&#xA;    requires (sizeof...(Rngs) &gt; 0)&#xD;&#xA;GLuint upload_to_buffer(Rngs const &amp;...rngs)&#xD;&#xA;{&#xD;&#xA;    std::array&lt;byte_range, sizeof...(rngs)&gt; spans =&#xD;&#xA;        {get_span(rngs)...};&#xD;&#xA;&#xD;&#xA;    std::size_t buffer_size = 0;&#xD;&#xA;    for(auto const&amp; sp : spans)&#xD;&#xA;        buffer_size += sp.size();&#xD;&#xA;&#xD;&#xA;    std::vector&lt;std::byte&gt; byte_buff(buffer_size);&#xD;&#xA;&#xD;&#xA;    std::size_t offset = 0;&#xD;&#xA;    for(auto const&amp; sp : spans)&#xD;&#xA;    {&#xD;&#xA;        std::memcpy(&amp;byte_buff[offset], sp.data(), sp.size());&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLuint buff;&#xD;&#xA;    glCreateBuffer(&amp;buff, 1);&#xD;&#xA;    glNamedBufferStorage(buff, byte_buff.size(), byte_buff.data(), 0);&#xD;&#xA;    return buff;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="34989" PostHistoryTypeId="2" PostId="12233" RevisionGUID="3069f34e-909e-447d-b233-1e7826df4d5f" CreationDate="2021-10-04T17:00:06.870" UserId="17310" Text="Data formats for images (but also for geospacial or geometric data) are usually classified in &quot;vector data&quot; and &quot;raster data&quot;.&#xD;&#xA;Does this classification have a commonly used name? &#xD;&#xA;I am looking for a term that could be used as a property name in a library catalogue to describe image or geospacial data files.&#xD;&#xA;&#xD;&#xA;Example:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&quot;file name&quot;: &quot;Map_of_Europe.jpg&quot;&#xD;&#xA;&quot;file type&quot;: &quot;JPEG&quot;&#xD;&#xA;&quot;&lt;the term i am looking for&gt;&quot;: &quot;raster data&quot;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here is a candidate I can think of:&#xD;&#xA;&#xD;&#xA;**Representation type:** The main difference between vector and raster data is the way information is represented (as points, lines, arcs etc. versus as a grid).&#xD;&#xA;This seems like the most precise description to me. Unfortunately, it does not seem to be commonly used. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="34991" PostHistoryTypeId="1" PostId="12233" RevisionGUID="3069f34e-909e-447d-b233-1e7826df4d5f" CreationDate="2021-10-04T17:00:06.870" UserId="17310" Text="What is the common term for the distinction between vector and raster data?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34992" PostHistoryTypeId="3" PostId="12233" RevisionGUID="3069f34e-909e-447d-b233-1e7826df4d5f" CreationDate="2021-10-04T17:00:06.870" UserId="17310" Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34993" PostHistoryTypeId="2" PostId="12234" RevisionGUID="5f565e8f-e87a-4d2f-ba1b-02e27327302d" CreationDate="2021-10-05T00:43:05.893" UserId="11058" Text="I wonder what happens when functions that change OpenGL states, ex `glBindVertexArray` or `glBindTexture` are called with the same buffer object parameter multiple times in a row like below?&#xD;&#xA;&#xD;&#xA;     glBindVertexArray(vao);&#xD;&#xA;     glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;We know that state changes are costly. But if the new state is the same as the old one is performance overhead the same as if the two states where different? Or does OpenGL perform conditional check and ignore the second state change command?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34995" PostHistoryTypeId="1" PostId="12234" RevisionGUID="5f565e8f-e87a-4d2f-ba1b-02e27327302d" CreationDate="2021-10-05T00:43:05.893" UserId="11058" Text="How OpenGL handles assigning the same state multiple times in a row" ContentLicense="CC BY-SA 4.0" />
  <row Id="34996" PostHistoryTypeId="3" PostId="12234" RevisionGUID="5f565e8f-e87a-4d2f-ba1b-02e27327302d" CreationDate="2021-10-05T00:43:05.893" UserId="11058" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="34997" PostHistoryTypeId="5" PostId="12234" RevisionGUID="b441e2b1-ba18-472f-8d31-d6c82517bc23" CreationDate="2021-10-05T00:48:15.897" UserId="11058" Comment="added 191 characters in body" Text="I wonder what happens when functions that change OpenGL states, ex `glBindVertexArray` or `glBindTexture` are called with the same parameter multiple times in a row like below?&#xD;&#xA;&#xD;&#xA;     //like this&#xD;&#xA;     glBindVertexArray(vao);&#xD;&#xA;     glBindVertexArray(vao);&#xD;&#xA;     glBindTexture(GL_TEXTURE_2D, tbo);&#xD;&#xA;     glBindTexture(GL_TEXTURE_2D, tbo);&#xD;&#xA;&#xD;&#xA;     //or like this&#xD;&#xA;     glBindVertexArray(vao);&#xD;&#xA;     glBindTexture(GL_TEXTURE_2D, tbo);&#xD;&#xA;     glBindVertexArray(vao);&#xD;&#xA;     glBindTexture(GL_TEXTURE_2D, tbo);&#xD;&#xA;     &#xD;&#xA; &#xD;&#xA;We know that state changes are costly. But if the new state is the same as the old one is performance overhead the same as if the two states where different? Or does OpenGL perform conditional check and ignore the second state change command?" ContentLicense="CC BY-SA 4.0" />
  <row Id="34999" PostHistoryTypeId="50" PostId="10365" RevisionGUID="43c94db7-d92a-40c9-8719-a214676b1da7" CreationDate="2021-10-05T08:05:10.420" UserId="-1" />
  <row Id="35000" PostHistoryTypeId="2" PostId="12235" RevisionGUID="912072b3-3fd5-4075-88d5-c8b78cc8667f" CreationDate="2021-10-05T13:26:57.410" UserId="16126" Text="I have an 8192x8192 texture atlas that contains 1024x1024 shadow maps aligned side by side. I'm trying to calculate the uv coordinates so that I can sample each shadow map appropriately based on the 'shadowIndex' of my light. With a single non-atlas shadowmap I can easily calculate the uv coordinates like this:&#xD;&#xA;&#xD;&#xA;    tc.x = lightViewPosition.x / lightViewPosition.w / 2.0f + 0.5f;&#xD;&#xA;    tc.y = -lightViewPosition.y / lightViewPosition.w / 2.0f + 0.5f;&#xD;&#xA;&#xD;&#xA;    shadowFactor += shadowMap.SampleCmpLevelZero(SampleComp, tc, lightDepthValue);&#xD;&#xA;&#xD;&#xA;How can I replicate the same thing while also factoring in an offset for sampling the correct shadow map from the atlas? I tried this:&#xD;&#xA;&#xD;&#xA;    tc.x = lightViewPosition.x / lightViewPosition.w / 2.0f + 0.5f;&#xD;&#xA;    tc.y = -lightViewPosition.y / lightViewPosition.w / 2.0f + 0.5f;&#xD;&#xA;&#xD;&#xA;    float tileSize = 1024.0f / 8.0f;&#xD;&#xA;    float tileOffset = tileSize * lights[i].shadowIndex;&#xD;&#xA;&#xD;&#xA;    tc += frac((tc - tileOffset) / tileSize) * tileSize + tileOffset;&#xD;&#xA;&#xD;&#xA;But this does not work correctly. Additionally I have to consider that the y (V) coordinate should not be affected while the shadow index isn't a multiple of 8 because there are 8 shadow maps per row. Any ideas? Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="35002" PostHistoryTypeId="1" PostId="12235" RevisionGUID="912072b3-3fd5-4075-88d5-c8b78cc8667f" CreationDate="2021-10-05T13:26:57.410" UserId="16126" Text="Calculating UV coordinates for sampling texture atlas" ContentLicense="CC BY-SA 4.0" />
  <row Id="35003" PostHistoryTypeId="3" PostId="12235" RevisionGUID="912072b3-3fd5-4075-88d5-c8b78cc8667f" CreationDate="2021-10-05T13:26:57.410" UserId="16126" Text="|3d|hlsl|uv-mapping|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35004" PostHistoryTypeId="2" PostId="12236" RevisionGUID="5c955fe2-d26e-4fe0-8a9b-ad3b0063b4c9" CreationDate="2021-10-05T14:05:34.347" UserId="2654" Text="There are no performance guarantees in OpenGL. Many implementations will filter out some kinds of redundant state, but nothing guarantees that.&#xD;&#xA;&#xD;&#xA;The best you can do is this: if you change state, you should do so with the expectation that you will pay the cost of that state change.&#xD;&#xA;&#xD;&#xA;It should also be noted that the cost of a state change is paid at the next *render* call, not when the change is made. So if you bind 20 different VAOs, but only render with the last one, it's probably going to be just as expensive as binding the last one." ContentLicense="CC BY-SA 4.0" />
  <row Id="35006" PostHistoryTypeId="2" PostId="12237" RevisionGUID="106f2b6e-c7ec-4a82-a0df-50a99f670fdd" CreationDate="2021-10-05T14:36:35.053" UserId="7952" Text="There are two different methods of computing a random ray bounce being compared in this section of the online book, the first one is: Pick a point $s$ anywhere *inside* the sphere, then compute a vector from a point $p$ on the surface to the point $s$ *inside* the sphere.&#xD;&#xA;&#xD;&#xA;The second method is: Pick a point $s$ anywhere *on the surface* of the sphere, then compute a vector from the point $p$ to the point $s$ *on the surface* of the sphere.&#xD;&#xA;&#xD;&#xA;After computing the random vector, compute the angle $\phi$ between the given normal vector and random vector. That angle is then used in the lighting computations.&#xD;&#xA;&#xD;&#xA;Given the two methods of computing a random vector the question arises: &quot;Are these two methods equivalent and how do we show that they are or are not?&quot;  To show that we have to somehow compute every possible angle using the two different methods which should result in a function they are equivalent to. The bit of language &quot;every possible angle&quot; suggests using integrals over a volume for the first method and integrals over a surface for the second method. And that is where these two approaches diverge, the integration over the volume gives a different answer then the integration over the surface.&#xD;&#xA;&#xD;&#xA;...skipping all the math...&#xD;&#xA;&#xD;&#xA;The first method it turns out, after doing a bunch of calculus, is equivalent to $cos^3(\phi)$ suggesting that all those points on the interior of the sphere are skewing the random vector angle towards the center of the sphere which are close to the normal vector.&#xD;&#xA;&#xD;&#xA;The second method, after a bit more calculus, gives the result $cos(\phi)$ which is the answer we were hoping for.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35008" PostHistoryTypeId="2" PostId="12238" RevisionGUID="f30eef1a-261e-4185-9ed1-0b2521214e56" CreationDate="2021-10-05T16:14:53.817" UserId="7952" Text="Assuming normalized texture coordinates and a grid of 8x8 (which is 64 tiles not 16 like I said in the comments) then tileOffset will need to be a vec2 for the x and y offsets.&#xD;&#xA;&#xD;&#xA;Also, assuming texture coordinates tc are mapped to a single texture map (0,1).&#xD;&#xA;&#xD;&#xA;Then the new texture coordinates for tile 0,0 are tc = tc/vec2(8192,8192);&#xD;&#xA;For tile 1 the texture coordinates would added 1024/8192 to the tc.x, tile two would add 2048/8192 to tc.x and so forth up to tile 8.&#xD;&#xA;&#xD;&#xA;tc.y doesn't change till tile 8 which then gets 1024/8192 added to it until tile 16 and so forth.&#xD;&#xA;&#xD;&#xA;So the tile specific texture coords would be&#xD;&#xA;&#xD;&#xA;    tc = tc/vec2(8192,8192);&#xD;&#xA;    tc.x += ((lights[i].shadowIndex % 8) * 1024)/8192.0;&#xD;&#xA;    tc.y += ((lights[i].shadowIndex / 8) * 1024)/8192.0;&#xD;&#xA;&#xD;&#xA;Where the %8 and /8 are indicating integer modulus and division.&#xD;&#xA;This is just psudo code and I was using the upper left corner as 0,0 but the idea is the same for other origins." ContentLicense="CC BY-SA 4.0" />
  <row Id="35010" PostHistoryTypeId="5" PostId="12238" RevisionGUID="b00ef836-b48d-43c7-a09d-bf058c32169c" CreationDate="2021-10-05T16:20:14.347" UserId="7952" Comment="added explanation of the math" Text="Assuming normalized texture coordinates and a grid of 8x8 (which is 64 tiles not 16 like I said in the comments) then tileOffset will need to be a vec2 for the x and y offsets.&#xD;&#xA;&#xD;&#xA;Also, assuming texture coordinates tc are mapped to a single texture map (0,1).&#xD;&#xA;&#xD;&#xA;Then the new texture coordinates for tile 0,0 are tc = (tc*vec2(1024,1024))/vec2(8192,8192);&#xD;&#xA;For tile 1 the texture coordinates would added 1024/8192 to the tc.x, tile two would add 2048/8192 to tc.x and so forth up to tile 8.&#xD;&#xA;&#xD;&#xA;tc.y doesn't change till tile 8 which then gets 1024/8192 added to it until tile 16 and so forth.&#xD;&#xA;&#xD;&#xA;So the tile specific texture coords would be&#xD;&#xA;&#xD;&#xA;    tc = (tc*vec2(1024,1024))/vec2(8192,8192);&#xD;&#xA;    tc.x += ((lights[i].shadowIndex % 8) * 1024)/8192.0;&#xD;&#xA;    tc.y += ((lights[i].shadowIndex / 8) * 1024)/8192.0;&#xD;&#xA;&#xD;&#xA;Where the %8 and /8 are indicating integer modulus and division.&#xD;&#xA;This is just psudo code and I was using the upper left corner as 0,0 but the idea is the same for other origins.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;The code is converting normalized coordinates to unnormalized coordinates for a texture map size of 1024x1024. Then converting that to normalized coordinates for a texture maps size of 8192x8192.&#xD;&#xA;&#xD;&#xA;Then it computes the normalized offsets for x and y and adds them to get the grid specific location." ContentLicense="CC BY-SA 4.0" />
  <row Id="35011" PostHistoryTypeId="50" PostId="9829" RevisionGUID="c77bc9c9-584d-4fe7-80ca-a004ba8470f8" CreationDate="2021-10-05T18:01:55.267" UserId="-1" />
  <row Id="35012" PostHistoryTypeId="2" PostId="12239" RevisionGUID="4b0678ef-4d3f-4dee-b45e-b48bf21403bd" CreationDate="2021-10-06T05:14:49.307" UserId="38" Text="Well, for images that consists of pixels they are usually called raster or bitmap images. GIS programs quite universally call these just rasters. You could describe them as pixel matrixes. Thing is though most people just call them images or photographs.&#xD;&#xA;&#xD;&#xA;Now then i would not personally call  vector formats images at all. I would call them models, because thats what they are. Also i wouldnt geet hooked on the type of primitives they use, because they might not use the kinds of primitives you assume.\* &#xD;&#xA;&#xD;&#xA;The common feature that all vector formats share is that the image is not rendered to pixels, yet. Literally rendering is to be done later. So personally on a philosophical level i would like to call them delayed render models/images. Mainly because this would impart some understanding to the audience. But vector images are what they are commonly called, though most users just call them images too.\** In a GIS context i would just call them vectors, to reflect the way they use raster.\***&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* a model which consists of some sort of distance fields for example. Not common but might become common.&#xD;&#xA;&#xD;&#xA;\** isnt spoken language wonderfully blunt and imprecise.&#xD;&#xA;&#xD;&#xA;\*** GIS applications also usually have point cloud datatypes as well as which they usually categorize separately.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35014" PostHistoryTypeId="5" PostId="12239" RevisionGUID="78c5e2aa-7e62-4f67-817b-29b8f9fb5c5d" CreationDate="2021-10-06T05:21:53.387" UserId="38" Comment="added 61 characters in body" Text="Well, for images that consists of pixels they are usually called raster or bitmap images. GIS programs quite universally call these just rasters. You could describe them as pixel matrixes. Thing is though most people just call them images or photographs.&#xD;&#xA;&#xD;&#xA;Now then i would not personally call  vector formats images at all. I would call them models, because thats what they are. Also i wouldnt geet hooked on the type of primitives they use, because they might not use the kinds of primitives you assume.\* &#xD;&#xA;&#xD;&#xA;The common feature that all vector formats share is that the image is not rendered to pixels, yet. Literally rendering is to be done later. So personally on a philosophical level i would like to call them delayed render models/images. Mainly because this would impart some understanding to the audience. But vector images are what they are commonly called, though most users just call them images too.\** In a GIS context i would just call them vectors, to reflect the way they use raster.\*** The problem is that vecto data may contain rasters, so are you prepared to say that its a mixed file?&#xD;&#xA;&#xD;&#xA;So after this preamble i would call the term *Model Type*, or maybe *Data Model*.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* a model which consists of some sort of distance fields for example. Not common but might become common.&#xD;&#xA;&#xD;&#xA;\** isnt spoken language wonderfully blunt and imprecise.&#xD;&#xA;&#xD;&#xA;\*** GIS applications also usually have point cloud datatypes as well as which they usually categorize separately.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35015" PostHistoryTypeId="50" PostId="10341" RevisionGUID="1ef40660-69ef-49e7-94d8-dce569b350cf" CreationDate="2021-10-06T10:05:55.503" UserId="-1" />
  <row Id="35016" PostHistoryTypeId="5" PostId="2339" RevisionGUID="61651e0b-6bb4-4e2a-be9a-a23a66acbbd0" CreationDate="2021-10-07T07:34:52.683" UserId="-1" Comment="replaced https://tools.ietf.org/html/rfc with https://www.rfc-editor.org/rfc/rfc" Text="Embedding human readable data is not supported. However you can put the data into a [data uri][1] to store the data inline in base64 format.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    &quot;buffers&quot;: {&#xD;&#xA;        &quot;a-buffer-id&quot;: {&#xD;&#xA;            &quot;byteLength&quot;: 1024,&#xD;&#xA;            &quot;type&quot;: &quot;arraybuffer&quot;,&#xD;&#xA;            &quot;uri&quot;=&quot;data:application/octet-stream;base64,...&quot;&#xD;&#xA;        }&#xD;&#xA;    },&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.rfc-editor.org/rfc/rfc2397&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35017" PostHistoryTypeId="5" PostId="5254" RevisionGUID="40326754-b6ff-4e09-a154-03ea257bbc8b" CreationDate="2021-10-07T07:34:52.683" UserId="-1" Comment="replaced https://tools.ietf.org/html/rfc with https://www.rfc-editor.org/rfc/rfc" Text="The following four SVG paths render the same (using the default [`fill-rule=&quot;nonzero&quot;`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule)):&#xD;&#xA;&#xD;&#xA;    &lt;path id=&quot;cwOccwI&quot; d=&quot;M0,0 10,0 10,10zM5,2 8,5 8,2z&quot; transform=&quot;translate( 0,0)&quot;/&gt;&#xD;&#xA;    &lt;path id=&quot;ccwOcwI&quot; d=&quot;M0,0 10,10 10,0zM5,2 8,2 8,5z&quot; transform=&quot;translate(15,0)&quot;/&gt;&#xD;&#xA;    &lt;path id=&quot;ccwIcwO&quot; d=&quot;M5,2 8,5 8,2zM0,0 10,0 10,10z&quot; transform=&quot;translate(30,0)&quot;/&gt;&#xD;&#xA;    &lt;path id=&quot;cwIccwO&quot; d=&quot;M5,2 8,2 8,5zM0,0 10,10 10,0z&quot; transform=&quot;translate(45,0)&quot;/&gt;&#xD;&#xA;&#xD;&#xA;[![Four triangles with triangular holes inside][1]][1]&#xD;&#xA;&#xD;&#xA;As hinted at by the IDs, these are combinations of clockwise (`cw`) and counter-clockwise (`ccw`) orientations for the outer (`O`) and inner (`I`) subpaths, varying the order the subpaths are added.&#xD;&#xA;&#xD;&#xA;I'm converting SVG paths to [GeoJSON](http://geojson.org/). It requires a single 'positive' subpath that is oriented counter-clockwise, and any/all ['hole' subpaths to be oriented clockwise](https://www.rfc-editor.org/rfc/rfc7946#section-3.1.6).&#xD;&#xA;&#xD;&#xA;Given an SVG path with subpaths (which I can assume/guarantee will not overlap), how can I determine which subpath(s) are 'positive' paths, and which are 'holes'? As shown above, I cannot rely on the orientation of the points within the path, and I cannot rely on the ordering of sub-paths.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4yENe.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35018" PostHistoryTypeId="50" PostId="12143" RevisionGUID="3ea44d47-2e69-43a6-83d3-ebff0db74d4b" CreationDate="2021-10-07T12:02:00.193" UserId="-1" />
  <row Id="35019" PostHistoryTypeId="4" PostId="12208" RevisionGUID="cec50a4a-9405-4067-b311-c6e69c944456" CreationDate="2021-10-07T12:27:10.150" UserId="17223" Comment="edited title" Text="Deriving formula for perspective correct interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="35026" PostHistoryTypeId="2" PostId="12241" RevisionGUID="5c9d44df-57f7-4dac-801f-b9ce573f474f" CreationDate="2021-10-08T09:58:06.897" UserId="17330" Text="**Short Question:**&#xD;&#xA; How can i integrate a buffer variable in a compute shader over each pixel i.e. how can i ensure memory coherence in such a case?&#xD;&#xA;&#xD;&#xA;**Long Question:**&#xD;&#xA;I've written a deferred renderer with hdr and i want to implement automatic exposure.&#xD;&#xA;For that purpose i orignally used mipmapping, but that is not very performant and i want to improve my knowledge about compute shaders. So i tried to write a compute shader that approximates the average luminance of a image (approximation in the sense that i don't process every pixel but e.g. only 64 x 36 samples).&#xD;&#xA;&#xD;&#xA;That would require me to accumulate the luminance of each pixel i.e. of each shader invocation. So i created a buffer which holds my luminance value:&#xD;&#xA;&#xD;&#xA;    volatile layout(std430, binding = 0) buffer averageBlock{&#xD;&#xA;        float luminance;&#xD;&#xA;    } average;&#xD;&#xA;BUT: there are no atomic operations for floats so i changed it to&#xD;&#xA;&#xD;&#xA;    uint luminance[10];&#xD;&#xA;Were each entry holds a part of the luminance (i.e. the first pixel writes to entry 0, the second to 1, ... the tenth to 0, ...) to increase the value range. I then mapped the float values to ints (multiplied them with 280, since that uses the available memory range nearly completly in the edge case were everything as a luminance of 1).&#xD;&#xA;&#xD;&#xA;I then accumulated the values with:&#xD;&#xA;&#xD;&#xA;    uint discl = uint(lum * 280.0);&#xD;&#xA;    int slot = int(mod(gl_GlobalInvocationID.x, 10));&#xD;&#xA;    memoryBarrierBuffer();&#xD;&#xA;    atomicAdd(average.luminance[slot], discl);&#xD;&#xA;    memoryBarrierBuffer();&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;But it seems that this also leads to visibility problems, since when i set `lum` to a certain value, only a random proportion of that value is present after `barrier()` (maybe because between those memoryBarrier calls the atomic adds don't see the changed values of the other ones).&#xD;&#xA;&#xD;&#xA;So how do i do this correctly? &#xD;&#xA;Thanks for your help!  " ContentLicense="CC BY-SA 4.0" />
  <row Id="35028" PostHistoryTypeId="1" PostId="12241" RevisionGUID="5c9d44df-57f7-4dac-801f-b9ce573f474f" CreationDate="2021-10-08T09:58:06.897" UserId="17330" Text="Compute Shader shared average value" ContentLicense="CC BY-SA 4.0" />
  <row Id="35029" PostHistoryTypeId="3" PostId="12241" RevisionGUID="5c9d44df-57f7-4dac-801f-b9ce573f474f" CreationDate="2021-10-08T09:58:06.897" UserId="17330" Text="|opengl|glsl|image-processing|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35031" PostHistoryTypeId="2" PostId="12242" RevisionGUID="a5bdb71f-b8d1-4a07-b2d8-6a83655e6f8b" CreationDate="2021-10-09T13:04:18.787" UserId="17320" Text=" When I use the CreateGraphicsPipelineState function in DX12, there's an error &quot;E_INVALIDARG One or more arguments are invalid.&quot; returned by the function, but there isn't detailed information on which argument is wrong. I'm sure I opened the debug layer, here is the code:&#xD;&#xA;&#xD;&#xA;    #if defined(DEBUG) || defined(_DEBUG) &#xD;&#xA;    	{&#xD;&#xA;    		ComPtr&lt;ID3D12Debug&gt; debugController;&#xD;&#xA;    		if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&amp;debugController))))&#xD;&#xA;    		{&#xD;&#xA;    			debugController-&gt;EnableDebugLayer();&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    #endif&#xD;&#xA; I also opened the debug layer in the DirectX Control Panel. And it also has no detailed error information in the output window. I really can not find which argument is wrong. Here is my code:&#xD;&#xA;&#xD;&#xA;    //&#xD;&#xA;	// PSO for shadow map pass.&#xD;&#xA;	//&#xD;&#xA;	D3D12_GRAPHICS_PIPELINE_STATE_DESC shadowPsoDesc = basePsoDesc;&#xD;&#xA;	shadowPsoDesc.RasterizerState.DepthBias = 100000;&#xD;&#xA;	shadowPsoDesc.RasterizerState.DepthBiasClamp = 0.0f;&#xD;&#xA;	shadowPsoDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;&#xD;&#xA;	shadowPsoDesc.pRootSignature = mRootSignature.Get();&#xD;&#xA;	shadowPsoDesc.VS =&#xD;&#xA;	{&#xD;&#xA;		reinterpret_cast&lt;BYTE*&gt;(mShaders[&quot;ShadowVS&quot;]-&gt;GetBufferPointer()),&#xD;&#xA;		mShaders[&quot;ShadowVS&quot;]-&gt;GetBufferSize()&#xD;&#xA;	};&#xD;&#xA;	shadowPsoDesc.PS =&#xD;&#xA;	{&#xD;&#xA;		reinterpret_cast&lt;BYTE*&gt;(mShaders[&quot;ShadowPS&quot;]-&gt;GetBufferPointer()),&#xD;&#xA;		mShaders[&quot;ShadowPS&quot;]-&gt;GetBufferSize()&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	// Shadow map pass does not have a render target.&#xD;&#xA;	shadowPsoDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;&#xD;&#xA;	shadowPsoDesc.NumRenderTargets = 0;&#xD;&#xA;	HRESULT hr = md3dDevice-&gt;CreateGraphicsPipelineState(&amp;shadowPsoDesc, IID_PPV_ARGS(&amp;mPSOs[&quot;Shadow&quot;]));&#xD;&#xA;	ThrowIfFailed(hr);&#xD;&#xA;&#xD;&#xA;basePsoDesc is used for creating test pso:&#xD;&#xA;&#xD;&#xA;    D3D12_GRAPHICS_PIPELINE_STATE_DESC basePsoDesc;&#xD;&#xA;    	ZeroMemory(&amp;basePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));&#xD;&#xA;    	basePsoDesc.InputLayout = { mLoadModelInputLayout.data(), (UINT)mLoadModelInputLayout.size() };&#xD;&#xA;    	basePsoDesc.pRootSignature = mRootSignature.Get();&#xD;&#xA;    	basePsoDesc.VS =&#xD;&#xA;    	{&#xD;&#xA;    		reinterpret_cast&lt;BYTE*&gt;(mShaders[&quot;testVS&quot;]-&gt;GetBufferPointer()),&#xD;&#xA;    		mShaders[&quot;testVS&quot;]-&gt;GetBufferSize()&#xD;&#xA;    	};&#xD;&#xA;    	basePsoDesc.PS =&#xD;&#xA;    	{&#xD;&#xA;    		reinterpret_cast&lt;BYTE*&gt;(mShaders[&quot;testPS&quot;]-&gt;GetBufferPointer()),&#xD;&#xA;    		mShaders[&quot;testPS&quot;]-&gt;GetBufferSize()&#xD;&#xA;    	};&#xD;&#xA;    	basePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);&#xD;&#xA;    	basePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);&#xD;&#xA;    	basePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);&#xD;&#xA;    	basePsoDesc.SampleMask = UINT_MAX;&#xD;&#xA;    	basePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;&#xD;&#xA;    	basePsoDesc.NumRenderTargets = 1;&#xD;&#xA;    	basePsoDesc.RTVFormats[0] = mBackBufferFormat;&#xD;&#xA;    	basePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;&#xD;&#xA;    	basePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;&#xD;&#xA;    	basePsoDesc.DSVFormat = mDepthStencilFormat;&#xD;&#xA;    	ThrowIfFailed(md3dDevice-&gt;CreateGraphicsPipelineState(&amp;basePsoDesc, IID_PPV_ARGS(&amp;mPSOs[&quot;test&quot;]))); &#xD;&#xA;Shader input layout code:&#xD;&#xA;&#xD;&#xA;    mLoadModelInputLayout =&#xD;&#xA;    	{&#xD;&#xA;    		{ &quot;POSITION&quot;,     0, DXGI_FORMAT_R32G32B32_FLOAT,   0,   0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },&#xD;&#xA;    		{ &quot;NORMAL&quot;,		  0, DXGI_FORMAT_R32G32B32_FLOAT,   1,	 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },&#xD;&#xA;    		{ &quot;TANGENT&quot;,      0, DXGI_FORMAT_R32G32B32_FLOAT,   2,	 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },&#xD;&#xA;    		{ &quot;TEXCOORD&quot;,	  0, DXGI_FORMAT_R32G32_FLOAT,      3,	 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },&#xD;&#xA;    	};&#xD;&#xA;And the Shadow shader code:&#xD;&#xA;&#xD;&#xA;    struct VertexIn&#xD;&#xA;    {&#xD;&#xA;    	float3 posL : POSITION;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VertexOut&#xD;&#xA;    {&#xD;&#xA;    	float4 posH : SV_POSITION;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    VertexOut VS(VertexIn vin)&#xD;&#xA;    {&#xD;&#xA;    	VertexOut vout;&#xD;&#xA;    	float4 posW = mul(float4(vin.posL, 1.0f), mxWorld);&#xD;&#xA;    	vout.posH = mul(posW, mxViewProj);&#xD;&#xA;    	return vout;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void PS(VertexOut vout)&#xD;&#xA;    {&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;who can tell me why there is no detailed error information output or where the code is wrong? thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="35033" PostHistoryTypeId="1" PostId="12242" RevisionGUID="a5bdb71f-b8d1-4a07-b2d8-6a83655e6f8b" CreationDate="2021-10-09T13:04:18.787" UserId="17320" Text="DX12 Debug Layer doesn't output detailed error information" ContentLicense="CC BY-SA 4.0" />
  <row Id="35034" PostHistoryTypeId="3" PostId="12242" RevisionGUID="a5bdb71f-b8d1-4a07-b2d8-6a83655e6f8b" CreationDate="2021-10-09T13:04:18.787" UserId="17320" Text="|directx12|debugging|render|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35035" PostHistoryTypeId="50" PostId="12179" RevisionGUID="ba2ca72a-7293-4a6e-99f7-94099d996f90" CreationDate="2021-10-09T17:04:25.453" UserId="-1" />
  <row Id="35036" PostHistoryTypeId="50" PostId="10879" RevisionGUID="4ba58a85-1c47-4814-83bd-b4d616412904" CreationDate="2021-10-09T19:07:30.610" UserId="-1" />
  <row Id="35037" PostHistoryTypeId="2" PostId="12243" RevisionGUID="60c54da3-7c6f-4a98-b4b8-3bd63d3d8f66" CreationDate="2021-10-09T19:09:28.093" UserId="48" Text="First of all, I don't think you need `volatile` or memory barriers if you're just using atomic operations. Atomic operations are always supposed to be atomic regardless.&#xD;&#xA;&#xD;&#xA;However, having everything accumulate directly into one (or a small number) of atomic variables is not advisable because there will be too much contention on those few memory locations, thus largely serializing the computation.&#xD;&#xA;&#xD;&#xA;Usually, the way to do reduction operations (like sums, averages, histograms etc) on the GPU is to do it in multiple passes, similar to building mipmaps.&#xD;&#xA;&#xD;&#xA;You don't need to go just by steps of 2x, however. As you don't need all the individual mipmaps in the chain, only the final result, you can reduce by larger factors at a time; then you will get down to the target size in fewer passes, and it should be faster. For example, you can write a pixel shader that does an 8x8 reduction in one step, by sampling 4x4 times, each with a bilinear tap that averages 2x2 pixels, and outputs the average of those 16 samples (totaling 64 pixels). In that way, you can get from a 4K input image down to 60x33 in just two passes. You could experiment with how much reduction factor per pass gives the best performance.&#xD;&#xA;&#xD;&#xA;Alternatively, if you wanted to do some other operation than just averaging (for instance computing a luminance histogram), you could use a compute shader with say an 8x8 workgroup. Have each invocation load a pixel from the texture, and do the reduction of the workgroup into a shared memory variable (either using atomic operations or by memory barriers, etc). This is all staying within the workgroup, so it remains parallel across different workgroups. Then a single invocation writes out the result from shared memory into a destination buffer. Additional compute dispatches can be used for further reduction passes (summing histogram elements etc) and again you can get down to a very small target size in just a handful of passes.&#xD;&#xA;&#xD;&#xA;For more information, search &quot;parallel reduction&quot; as that's the generic term for this type of operation." ContentLicense="CC BY-SA 4.0" />
  <row Id="35039" PostHistoryTypeId="2" PostId="12244" RevisionGUID="5409d138-8169-46b3-bd0d-0f705d169fca" CreationDate="2021-10-10T11:56:34.970" UserId="15705" Text="I'm trying to make a software renderer, but I want to avoid creating extra triangles with clipping. For this I want to transform lines which compose triangles, instead of individual points. However I'm not sure how to do a perspective transformation on a line equation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="35041" PostHistoryTypeId="1" PostId="12244" RevisionGUID="5409d138-8169-46b3-bd0d-0f705d169fca" CreationDate="2021-10-10T11:56:34.970" UserId="15705" Text="How do I perform a perspective transform on a straight line?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35042" PostHistoryTypeId="3" PostId="12244" RevisionGUID="5409d138-8169-46b3-bd0d-0f705d169fca" CreationDate="2021-10-10T11:56:34.970" UserId="15705" Text="|transformations|perspective|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35048" PostHistoryTypeId="2" PostId="12246" RevisionGUID="448f4cdb-0d34-4162-a5dc-6f327e99683c" CreationDate="2021-10-11T04:54:08.793" UserDisplayName="user17337" Text="I want to explain what I understood of definition of the two things.&#xD;&#xA;&#xD;&#xA;**Projection plane:** &#xD;&#xA;The general processing steps for modeling and converting a world coordinate description of a scene to &#xD;&#xA;device coordinates, we need projection plane. &#xD;&#xA;&#xD;&#xA;**Projective plane:** We know that $P^2$ is all $\mathbb R^2$ points and point at infinity.In projection plane any point exists in $(∞,∞)$ if we want to represents it then we need projective plane. &#xD;&#xA;&#xD;&#xA;For instance, a point in Cartesian $(1, 2)$ becomes $(1, 2, 1)$ in Homogeneous. If a point, $(1, 2)$, moves toward infinity, it becomes $(∞,∞)$ in Cartesian coordinates. And it becomes $(1, 2, 0)$ in Homogeneous coordinates, because of $(1/0, 2/0) ≈ (∞,∞).$ Notice that we can express the point at infinity without using $&quot;∞&quot;.$&#xD;&#xA;&#xD;&#xA;My question is what's difference between Projection plane and Projective plane? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35050" PostHistoryTypeId="1" PostId="12246" RevisionGUID="448f4cdb-0d34-4162-a5dc-6f327e99683c" CreationDate="2021-10-11T04:54:08.793" UserDisplayName="user17337" Text="$P^2$ vs projection plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="35051" PostHistoryTypeId="3" PostId="12246" RevisionGUID="448f4cdb-0d34-4162-a5dc-6f327e99683c" CreationDate="2021-10-11T04:54:08.793" UserDisplayName="user17337" Text="|3d|projections|2d|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35052" PostHistoryTypeId="2" PostId="12247" RevisionGUID="7b8bc2da-38d7-49b7-be25-5de4a60f4ef0" CreationDate="2021-10-11T11:06:36.910" UserId="7952" Text="There are many methods you could use to go about doing this, here is one using the parametric form of a line which is: $L(t) = p+t\vec v$ Where $p$ is a point on the line and would be stored as a 4 component vector $p = \{x,y,z,1\}$ and $\vec v$ is a vector that would be stored as a 4 components $\vec v = \{x,y,z,0\}$ &#xD;&#xA;&#xD;&#xA;This form translates with a 4x4 matrix just like any point/vector would by simply transforming both the vector and the point. A 1 is put in the 4th component of a point since it has a location in 3D space and the 0 in the 4th component of vector reflects that a vector has magnitude and direction but no position.&#xD;&#xA;&#xD;&#xA;The point can be chosen as one of the ends of the line (it doesn't matter which just be consistent), and the vector is computed just like you would expect. IE if the line has the two end points $a$ and $b$ and the $a$ is chosen as the start, then the vector is computed as $b-a$.&#xD;&#xA;&#xD;&#xA;Do not normalize the vector and just vary $t$ between 0 and 1 for every line. Though you may want to calculate the magnitude of the vector (which corresponds to the length of the line) to determine how many points on the line you want to compute WRT the resolution of the image.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;This can be done in 2D and works exactly the same way. The points would just be x,y,1 and the vectors would be x,y,0 and the transformation matrix becomes a 3x3 matrix.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35054" PostHistoryTypeId="2" PostId="12248" RevisionGUID="3edaafba-1a6c-4192-bf6b-5d4919de1e9b" CreationDate="2021-10-11T11:38:56.927" UserId="7952" Text="In computer graphics the projection plane is most commonly defined as a plane perpendicular to the camera at a specific distance from the camera (the distance is often labeled $g$). It is the plane that an image will be projected onto and is usually shown between the near and far planes of a projection matrix. In the attached image (from the fged website) it is the blue plane.&#xD;&#xA;[![Projection plane example][1]][1]&#xD;&#xA;&#xD;&#xA;The projective plane on the other hand is usually shown as being parallel with the camera (or nearly parallel) extending out to infinity and typically has two lines draw on it like railroad tracks that meet (at infinity). Projective planes are not generally computed, though sometimes the need comes up. While a &quot;projection plane&quot; is mostly just conceptual, real world examples of a &quot;projective plane&quot; can be found. I attached a couple images showing some examples.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;There are other definitions of projective plane (such as the one over at wolfram math) but from my experience these are the two most common definitions and what folks generally are referring to when using the terms.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/s1Xq7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/31nf3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/96piG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35061" PostHistoryTypeId="50" PostId="10235" RevisionGUID="bbba4868-e680-4323-92da-ae712d1fa229" CreationDate="2021-10-12T03:12:11.117" UserId="-1" />
  <row Id="35062" PostHistoryTypeId="2" PostId="12250" RevisionGUID="fb498114-0de8-4596-aa4a-3e38249beb27" CreationDate="2021-10-12T11:00:09.873" UserId="6044" Text="I ended up using the LOS-Dijkstra algorithm for &quot;near-isometric flattening of brain surfaces&quot; described [here][2]. The code is available in [this][1] repository but:&#xD;&#xA;1. It is mixed with a lot of irrelevant code.&#xD;&#xA;2. It is poorly commented.&#xD;&#xA;3. It is in Matlab.&#xD;&#xA;&#xD;&#xA;If someone stumbles onto this question in the future and would to use the code, I would be happy to help fix the issues above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/kalenkovich/waves&#xD;&#xA;  [2]: https://www.sciencedirect.com/science/article/pii/S1053811910001564" ContentLicense="CC BY-SA 4.0" />
  <row Id="35064" PostHistoryTypeId="2" PostId="12251" RevisionGUID="50461258-00c7-4828-86c7-96187dbc5da2" CreationDate="2021-10-12T23:44:18.297" UserId="17351" Text="I am doing some image processing and am a little bit confused about reporting a 35 mm equivalent focal length. I am working with a 640x360 image which has an aspect ratio of 1.7777. A 35 mm film is 36 mm x 24 mm, for an aspect ratio of 1.5. We have the formulae $F_X = f_x \frac{W}{w}$ and $F_y = f_y \frac{H}{h}$. I currently have the values $f_x = f_y =$ 370 px calibrated for the 640x360 image. If I use $W = $ 36 mm, $w = $ 640 px, $H = $ 24 mm, and $h = $ 360 px, then the scale factors $\frac{W}{w}$ and $\frac{H}{h}$ disagree due to the disparity in aspect ratio, and $F_x \neq F_y$, when I expect them to be equal.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is the idea to consider my 640x360 px image as a cropped 640x426.666 px image? Or is it to consider my current 640x360 as a vertically squeezed image with non-square pixels?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35066" PostHistoryTypeId="1" PostId="12251" RevisionGUID="50461258-00c7-4828-86c7-96187dbc5da2" CreationDate="2021-10-12T23:44:18.297" UserId="17351" Text="35 mm equivalent focal length but with a different aspect ratio" ContentLicense="CC BY-SA 4.0" />
  <row Id="35067" PostHistoryTypeId="3" PostId="12251" RevisionGUID="50461258-00c7-4828-86c7-96187dbc5da2" CreationDate="2021-10-12T23:44:18.297" UserId="17351" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35068" PostHistoryTypeId="2" PostId="12252" RevisionGUID="09a92492-53ce-456e-b061-dd1c8ac9acd2" CreationDate="2021-10-13T02:48:51.340" UserId="5664" Text="My goal is to render a volumetric point light as explained in this book's chapter 10: [FGED Rendering][1]&#xD;&#xA;The book explains the math pretty well, but I'm not sure I understand what is the required setup for a volumetric point light halo to be visible. The book describes the following code snippet to calculate the brightness of the volumetric halo:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float R = 5.f; // Radius of the volumetric point light halo.&#xD;&#xA;float R2 = R * R;&#xD;&#xA;float recipR2 = 1.f / R2;&#xD;&#xA;float recip3R2 = 1.f / (3.f * R2);&#xD;&#xA;float normalizer = 3.f / (4.f * R);&#xD;&#xA;&#xD;&#xA;// This shader renders a halo effect of radius R at the object-space position pobject.&#xD;&#xA;// The object-space camera position c and view direction z are given by cameraPosition &#xD;&#xA;// and cameraView. The pixelCoord parameter specifies the viewport coordinates of the&#xD;&#xA;// pixel being processed, and it is used to read from the depth buffer.&#xD;&#xA;float CalculateHaloBrightness(float3 pobject, float2 pixelCoord)&#xD;&#xA;{&#xD;&#xA;	float3 vdir = cameraPosition - pobject;&#xD;&#xA;	float v2 = dot(vdir, vdir);&#xD;&#xA;	float p2 = dot(pobject, pobject);&#xD;&#xA;	float pv = -dot(pobject, vdir);&#xD;&#xA;	float m = sqrt(max(pv * pv - v2 * (p2 - R2), 0.0));&#xD;&#xA;&#xD;&#xA;     // Read z0 from the structure buffer.&#xD;&#xA;	float2 depth = texture(depthBuffer, pixelCoord);&#xD;&#xA;	float t0 = 1.0 + depth / dot(cameraView, vdir);&#xD;&#xA;&#xD;&#xA;     // Calculate clamped limits of integration.&#xD;&#xA;	float t1 = clamp((pv - m) / v2, t0, 1.0);&#xD;&#xA;	float t2 = clamp((pv + m) / v2, t0, 1.0);&#xD;&#xA;	float u1 = t1 * t1;&#xD;&#xA;	float u2 = t2 * t2;&#xD;&#xA;&#xD;&#xA;     // Evaluate density integral, normalize, and square.&#xD;&#xA;	float B = ((1.0 - p2 * recipR2) * (t2 - t1) + pv * recipR2 * (u2 - u1) - v2 * recip3R2 * (t2 * u2 - t1 * u1)) * normalizer;&#xD;&#xA;	return (B * B * v2);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;There's a few things that I don't understand:&#xD;&#xA;1) What is meant exactly by `pobject`, `cameraPosition` and `cameraView` being in object-space? Does it just mean that they all have to be in world-space for this function to work correctly?&#xD;&#xA;&#xD;&#xA;2) On what surface am I supposed to execute this pixel shader on? From what I read, it sounds like it has to be run on a cube centered at `pobject` but I'm not sure.&#xD;&#xA;&#xD;&#xA;3) Is a light scattering medium required, such as fog? It would make sense that it does, but it's not really mentioned in the book's explanation.&#xD;&#xA;&#xD;&#xA;I realize this is a difficult question to answer, since I haven't included the entire explanation present in the book here. I assume the author would not like that. So I am hoping that maybe somebody here might roughly understand what's going on and point me in the right direction.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.amazon.ca/Foundations-Game-Engine-Development-Rendering/dp/0985811757/ref=sr_1_2?crid=2U5PN7NJQ31S7&amp;dchild=1&amp;keywords=foundations%20of%20game%20engine%20development&amp;qid=1634091891&amp;sprefix=foundations%20of%20game%20engine%20deve%2Caps%2C174&amp;sr=8-2" ContentLicense="CC BY-SA 4.0" />
  <row Id="35070" PostHistoryTypeId="1" PostId="12252" RevisionGUID="09a92492-53ce-456e-b061-dd1c8ac9acd2" CreationDate="2021-10-13T02:48:51.340" UserId="5664" Text="Trying to understand how to render a volumetric point light" ContentLicense="CC BY-SA 4.0" />
  <row Id="35071" PostHistoryTypeId="3" PostId="12252" RevisionGUID="09a92492-53ce-456e-b061-dd1c8ac9acd2" CreationDate="2021-10-13T02:48:51.340" UserId="5664" Text="|opengl|rendering|lighting|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35072" PostHistoryTypeId="2" PostId="12253" RevisionGUID="54e0f61a-ac77-40e6-ad92-2028319f98cb" CreationDate="2021-10-13T04:45:19.967" UserId="9749" Text="My question is fairly simple but I guess it contains two questions, one is how to arrive at an answer (imagine a similar one and you want to deduce it using existing tools like a GLSL compiler or the like, I wasn't able to as I couldn't find any loop unrolling on trivial loops from the compilers I found online) and the question per se is: at what point does doing arithmetic/logic on a uniform becomes non trivial for the driver and stuff like loop unrolling stops happening. Imagine the scenario were you have a uniform on which the kernel size of a convolution depends on, something like &#xA;&#xA;```uniform whatever;&#xA;&#xA;int maxIter = fract( log2( float( whatever ) ) ) == 0. ? 3 : 2;&#xA;&#xA;for (int i = -maxIter; i &lt;= maxIter; ++i) &#xA;{ &#xA;```&#xA;&#xA;will this get unrolled? I am fairly certain that simply having a `min( 0, whatever );` won't unroll the loop as the compiler takes the uniform as a blackbox if I am correct." ContentLicense="CC BY-SA 4.0" />
  <row Id="35074" PostHistoryTypeId="1" PostId="12253" RevisionGUID="54e0f61a-ac77-40e6-ad92-2028319f98cb" CreationDate="2021-10-13T04:45:19.967" UserId="9749" Text="Dynamic Loop Based on Uniform" ContentLicense="CC BY-SA 4.0" />
  <row Id="35075" PostHistoryTypeId="3" PostId="12253" RevisionGUID="54e0f61a-ac77-40e6-ad92-2028319f98cb" CreationDate="2021-10-13T04:45:19.967" UserId="9749" Text="|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35076" PostHistoryTypeId="5" PostId="12252" RevisionGUID="a4bfc535-bb6c-4469-b5d6-f2b0105cf9ae" CreationDate="2021-10-13T05:24:35.190" UserId="5664" Comment="deleted 4 characters in body" Text="My goal is to render a volumetric point light as explained in this book's chapter 10: [FGED Rendering][1]&#xD;&#xA;The book explains the math pretty well, but I'm not sure I understand what is the required setup for a volumetric point light halo to be visible. The book describes the following code snippet to calculate the brightness of the volumetric halo:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float R = 5.f; // Radius of the volumetric point light halo.&#xD;&#xA;float R2 = R * R;&#xD;&#xA;float recipR2 = 1.f / R2;&#xD;&#xA;float recip3R2 = 1.f / (3.f * R2);&#xD;&#xA;float normalizer = 3.f / (4.f * R);&#xD;&#xA;&#xD;&#xA;// This shader renders a halo effect of radius R at the object-space position pobject.&#xD;&#xA;// The object-space camera position c and view direction z are given by cameraPosition &#xD;&#xA;// and cameraView. The pixelCoord parameter specifies the viewport coordinates of the&#xD;&#xA;// pixel being processed, and it is used to read from the depth buffer.&#xD;&#xA;float CalculateHaloBrightness(float3 pobject, float2 pixelCoord)&#xD;&#xA;{&#xD;&#xA;	float3 vdir = cameraPosition - pobject;&#xD;&#xA;	float v2 = dot(vdir, vdir);&#xD;&#xA;	float p2 = dot(pobject, pobject);&#xD;&#xA;	float pv = -dot(pobject, vdir);&#xD;&#xA;	float m = sqrt(max(pv * pv - v2 * (p2 - R2), 0.0));&#xD;&#xA;&#xD;&#xA;     // Read z0 from the depth buffer.&#xD;&#xA;	float2 depth = texture(depthBuffer, pixelCoord);&#xD;&#xA;	float t0 = 1.0 + depth / dot(cameraView, vdir);&#xD;&#xA;&#xD;&#xA;     // Calculate clamped limits of integration.&#xD;&#xA;	float t1 = clamp((pv - m) / v2, t0, 1.0);&#xD;&#xA;	float t2 = clamp((pv + m) / v2, t0, 1.0);&#xD;&#xA;	float u1 = t1 * t1;&#xD;&#xA;	float u2 = t2 * t2;&#xD;&#xA;&#xD;&#xA;     // Evaluate density integral, normalize, and square.&#xD;&#xA;	float B = ((1.0 - p2 * recipR2) * (t2 - t1) + pv * recipR2 * (u2 - u1) - v2 * recip3R2 * (t2 * u2 - t1 * u1)) * normalizer;&#xD;&#xA;	return (B * B * v2);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;There's a few things that I don't understand:&#xD;&#xA;1) What is meant exactly by `pobject`, `cameraPosition` and `cameraView` being in object-space? Does it just mean that they all have to be in world-space for this function to work correctly?&#xD;&#xA;&#xD;&#xA;2) On what surface am I supposed to execute this pixel shader on? From what I read, it sounds like it has to be run on a cube centered at `pobject` but I'm not sure.&#xD;&#xA;&#xD;&#xA;3) Is a light scattering medium required, such as fog? It would make sense that it does, but it's not really mentioned in the book's explanation.&#xD;&#xA;&#xD;&#xA;I realize this is a difficult question to answer, since I haven't included the entire explanation present in the book here. I assume the author would not like that. So I am hoping that maybe somebody here might roughly understand what's going on and point me in the right direction.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.amazon.ca/Foundations-Game-Engine-Development-Rendering/dp/0985811757/ref=sr_1_2?crid=2U5PN7NJQ31S7&amp;dchild=1&amp;keywords=foundations%20of%20game%20engine%20development&amp;qid=1634091891&amp;sprefix=foundations%20of%20game%20engine%20deve%2Caps%2C174&amp;sr=8-2" ContentLicense="CC BY-SA 4.0" />
  <row Id="35077" PostHistoryTypeId="2" PostId="12254" RevisionGUID="be97eb91-b681-4f68-bd80-9334a0323e41" CreationDate="2021-10-13T12:11:23.107" UserId="7952" Text="The post reads cropped but then talks about squeezed, so I gave a little extra info to help clarify.&#xD;&#xA;&#xD;&#xA;One possibility is that the final image is cropped, ie some texel data is being removed completely from the image such as the top and/or bottom rows of texels.&#xD;&#xA;&#xD;&#xA;In this case the image is considered just like it is worded &quot;cropped&quot;.&#xD;&#xA;&#xD;&#xA;Another possibility is the image is being rescaled, meaning that the entire image is kept but an algorithm is being used to compute new texels to fit the final image size and keep as much of the original image as possible.&#xD;&#xA;&#xD;&#xA;Normally rescaling is done in a way that keeps the original aspect ratio, but when that isn't possible then the texels are effectively stretched or squeezed. Which is the second option listed in the question.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35079" PostHistoryTypeId="2" PostId="12255" RevisionGUID="e05e5e52-87c5-4b84-9c51-fc77a9643eb4" CreationDate="2021-10-13T13:19:17.077" UserId="7952" Text="Here are a few steps to (hopefully) help get you going:&#xD;&#xA;&#xD;&#xA;Rendering the cube:&#xD;&#xA;For the geometry a simple cube is needed, so really the first step is just to get a cube rendering just like you would expect, I suggest placing the cube at the origin in both world and object space.&#xD;&#xA;&#xD;&#xA;After you are happy with the way the cube is rendered, change the winding direction for triangles the easiest way to do that is just a quick call to the API. So if the API is set to render counter clockwise as the front face, just change it so the front face is clockwise. This makes the &quot;interior&quot; of the cube visible.&#xD;&#xA;&#xD;&#xA;At this point you aren't actually trying to render the halo, just the interior of the cube. So the fragment shader should just return a color. Once that is all set up and you are happy with it, the next step will be the actual rendering of halo's and is where you would call the halo functions in the fragment shader.&#xD;&#xA;&#xD;&#xA;Thinking about the object spaces:&#xD;&#xA;The cube itself is in &quot;object space&quot; normally there is a Model to World matrix that we multiply the cube by that puts it in world space. When the book refers to &quot;object space&quot; it is referring to the cube's object space. (I think that book actually covers object/world spaces pretty well you may want to look up the chapter that goes over this to help clarify the subject) A good way to side step the issue is just to render the halo at the origin in world space, with the cube at the origin in object space. This cause the two spaces to coincide with each other. Once halo's are rendering at the origin, then tackle the issue of object/world space conversion.&#xD;&#xA;&#xD;&#xA;No fog is needed, a halo will render correctly without any special medium. &#xD;&#xA;&#xD;&#xA;Alpha blending will need to be enabled for the final halo, but you can skip that until the basic outline of the halo is rendering correctly.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35081" PostHistoryTypeId="5" PostId="12255" RevisionGUID="8f88ec0b-bc47-47f6-8ff8-e987e4f647a2" CreationDate="2021-10-13T13:32:08.247" UserId="7952" Comment="Removed the bit about using origin as it might be confusing." Text="Here are a few steps to (hopefully) help get you going:&#xD;&#xA;&#xD;&#xA;Rendering the cube:&#xD;&#xA;For the geometry a simple cube is needed, so really the first step is just to get a cube rendering just like you would expect, I suggest placing the cube at the origin in both world and object space.&#xD;&#xA;&#xD;&#xA;After you are happy with the way the cube is rendered, change the winding direction for triangles the easiest way to do that is just a quick call to the API. So if the API is set to render counter clockwise as the front face, just change it so the front face is clockwise. This makes the &quot;interior&quot; of the cube visible.&#xD;&#xA;&#xD;&#xA;At this point you aren't actually trying to render the halo, just the interior of the cube. So the fragment shader should just return a color. Once that is all set up and you are happy with it, the next step will be the actual rendering of halo's and is where you would call the halo functions in the fragment shader.&#xD;&#xA;&#xD;&#xA;Thinking about the object spaces:&#xD;&#xA;The cube itself is in &quot;object space&quot; normally there is a Model to World matrix that we multiply the cube by that puts it in world space. When the book refers to &quot;object space&quot; it is referring to the cube's object space. (I think that book actually covers object/world spaces pretty well you may want to look up the chapter that goes over this to help clarify the subject) &#xD;&#xA;&#xD;&#xA;No fog is needed, a halo will render correctly without any special medium. &#xD;&#xA;&#xD;&#xA;Alpha blending will need to be enabled for the final halo, but you can skip that until the basic outline of the halo is rendering correctly.&#xD;&#xA;&#xD;&#xA;Edit: Here is some code to help with cameraPosition and cameraView&#xD;&#xA;&#xD;&#xA;    mat4 Camera2World = inverse(view_matrix); // The view matrix &#xD;&#xA;    mat4 World2Object = inverse(object_matrix); // The object2world matrix&#xD;&#xA;    vec3 cameraPosition = (World2Object * Camara2World[3]).xyz;&#xD;&#xA;    vec3 cameraView = (World2Object * Camera2World[2]).xyz;&#xD;&#xA;&#xD;&#xA;Note that this is using column major matrices.&#xD;&#xA;&#xD;&#xA;This isn't the most efficient code, but hopefully it will help get you going.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35082" PostHistoryTypeId="2" PostId="12256" RevisionGUID="84fb0ab9-d6a9-4586-988c-0c837a825bc9" CreationDate="2021-10-13T15:36:39.207" UserId="16264" Text="### Intro&#xD;&#xA;&#xD;&#xA;I'm trying to render multi-channel images (more than 4 channels, for the purposes of feeding it to a Neural Network). Since OpenGL doesn't support it natively, I have multiple 4-channel render buffers, into which I render a corresponding portion of channels. &#xD;&#xA;&#xD;&#xA;For example, I need multi-channel image of size `512 x 512 x 16`, in OpenGL I have 4 render buffers of size `512 x 512 x 4`. Now the problem is that the Neural Network expects the data with strides `512 x 512 x 16`, i.e. 16 values of channels of one pixel are followed by 16 values of channels from the next pixel. However currently I can efficiently read my 4 render buffers via 4 calls to `glReadPixels`, basically making the data having strides `4 x 512 x 512 x 4`. Manual reordering of data on the client side **will not suffice me** as it's too slow.&#xD;&#xA;&#xD;&#xA;### Main question&#xD;&#xA;I've got an idea to render to a single 4-channel render buffer of size `512 x 512*4 x 4`, because stride-wise it's equivalent to `512 x 512 x 16`, we just treat a combination of 4 pixels in a row as a single pixel of 16-channel output image. Let's call it an &quot;interleaved rendering&quot;&#xD;&#xA;&#xD;&#xA;But this requires me to magically adjust my fragment shader, so that every group of consequent 4 *fragments* would have exactly the same interpolation of vertex attributes. Is there any way to do that? &#xD;&#xA;&#xD;&#xA;This bad illustration with 1 render buffer of `512 x 1024` 4-channel image, is an example of how it should be rendered. With that I can in 1 call `glReadPixels` extract the data with stride `512 x 512 x 8` [![enter image description here][1]][1]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Py6fX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35084" PostHistoryTypeId="1" PostId="12256" RevisionGUID="84fb0ab9-d6a9-4586-988c-0c837a825bc9" CreationDate="2021-10-13T15:36:39.207" UserId="16264" Text="&quot;Interleaved rendering&quot; in fragment shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="35085" PostHistoryTypeId="3" PostId="12256" RevisionGUID="84fb0ab9-d6a9-4586-988c-0c837a825bc9" CreationDate="2021-10-13T15:36:39.207" UserId="16264" Text="|opengl|rendering|efficiency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35086" PostHistoryTypeId="5" PostId="12256" RevisionGUID="699bd9db-c52b-4ff6-8cbb-29ea094a81b8" CreationDate="2021-10-13T15:57:20.733" UserId="16264" Comment="added 308 characters in body" Text="### Intro&#xD;&#xA;&#xD;&#xA;I'm trying to render multi-channel images (more than 4 channels, for the purposes of feeding it to a Neural Network). Since OpenGL doesn't support it natively, I have multiple 4-channel render buffers, into which I render a corresponding portion of channels. &#xD;&#xA;&#xD;&#xA;For example, I need multi-channel image of size `512 x 512 x 16`, in OpenGL I have 4 render buffers of size `512 x 512 x 4`. Now the problem is that the Neural Network expects the data with strides `512 x 512 x 16`, i.e. 16 values of channels of one pixel are followed by 16 values of channels from the next pixel. However currently I can efficiently read my 4 render buffers via 4 calls to `glReadPixels`, basically making the data having strides `4 x 512 x 512 x 4`. Manual reordering of data on the client side **will not suffice me** as it's too slow.&#xD;&#xA;&#xD;&#xA;### Main question&#xD;&#xA;I've got an idea to render to a single 4-channel render buffer of size `512 x 512*4 x 4`, because stride-wise it's equivalent to `512 x 512 x 16`, we just treat a combination of 4 pixels in a row as a single pixel of 16-channel output image. Let's call it an &quot;interleaved rendering&quot;&#xD;&#xA;&#xD;&#xA;But this requires me to magically adjust my fragment shader, so that every group of consequent 4 *fragments* would have exactly the same interpolation of vertex attributes. Is there any way to do that? &#xD;&#xA;&#xD;&#xA;This bad illustration with 1 render buffer of `512 x 1024` 4-channel image, is an example of how it should be rendered. With that I can in 1 call `glReadPixels` extract the data with stride `512 x 512 x 8` [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;EDIT: better pictures&#xD;&#xA;What I have now (4 render buffers)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What I want to do natively in OpenGL (this image is done in Python offline)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Py6fX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WQeZY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/n0UaB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35087" PostHistoryTypeId="5" PostId="12251" RevisionGUID="eef7161c-0b73-48ed-980d-14b1bfad1d45" CreationDate="2021-10-13T16:49:17.790" UserId="17351" Comment="Added some diagrams to help with the confusion" Text="I am doing some image processing and am a little bit confused about reporting a 35 mm equivalent focal length. I am working with a 640x360 image which has an aspect ratio of 1.7777. A 35 mm film is 36 mm x 24 mm, for an aspect ratio of 1.5. We have the formulae $F_X = f_x \frac{W}{w}$ and $F_y = f_y \frac{H}{h}$. I currently have the values $f_x = f_y =$ 370 px calibrated for the 640x360 image. If I use $W = $ 36 mm, $w = $ 640 px, $H = $ 24 mm, and $h = $ 360 px, then the scale factors $\frac{W}{w}$ and $\frac{H}{h}$ disagree due to the disparity in aspect ratio, and $F_x \neq F_y$, when I expect them to be equal.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is the idea to consider my 640x360 px image as a cropped 640x426.666 px image? Or is it to consider my current 640x360 as a vertically squeezed image with non-square pixels?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I have added the following diagram to help articulate my confusion:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have added the viewing frustum for the 640x360 image. The aspect ratio of this image determines the frustum. I have two ways I can fit a 35 mm film into this frustum. I can find where it fits horizontally, where the 36 mm piece sits in the frustum, but then the film hangs below the frustum. I can also slide the film until it fits vertically, where the 24 mm piece fits, but then the 36 mm side can't reach the other side of the frustum. In both of these options, the focal length is different. Which one is more proper to report?&#xD;&#xA;&#xD;&#xA;My intuition tells me that the first option is more correct, where the 35 mm film is fit horizontally. Then the 640x360 image is considered as a cropped 35 mm film image. But then there is another ambiguity. Do we center the film so that there is equal overhang on the top and bottom? That is, should the film be centered along the principal point? See the blue piece of film here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FM7D2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/p1jkE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35088" PostHistoryTypeId="2" PostId="12257" RevisionGUID="4b536777-3e5a-44c3-9084-32ea1667ae3b" CreationDate="2021-10-14T00:15:52.857" UserId="48" Text="It really depends on the individual compiler. The GPU vendor is responsible for the compiler as part of their driver, so it's really a total crapshoot as to how things get optimized, and you would need vendor-specific tools (if available) to get the compiled shader and disassemble it.&#xD;&#xA;&#xD;&#xA;If the GLSL is compiled to SPIR-V (i.e. for Vulkan) then you can at least look at the SPIR-V and see what optimizations were done at that level. If the loop gets unrolled by the SPIR-V compiler, it's unlikely that it would be re-rolled by the driver compiler. However, ultimately when it's submitted to the driver it will still go through another compile stage which may transform the code further, so whatever you see in the SPIR-V isn't necessarily definitive.&#xD;&#xA;&#xD;&#xA;In general, you're right that the compiler has to assume that uniform values are arbitrary. So if, for instance, you loop from 0 up to some 32-bit int uniform value, then it won't be able to unroll the loop as it could have in principle billions of iterations.&#xD;&#xA;&#xD;&#xA;Sometimes, if you put a compiler-visible upper bound on the loop count then the compiler will be able to unroll it:&#xD;&#xA;```&#xD;&#xA;uniform int iterCount;&#xD;&#xA;...&#xD;&#xA;int count = min(iterCount, 4);&#xD;&#xA;for (int i = 0; i &lt; count; ++i)&#xD;&#xA;{&#xD;&#xA;    ...&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;Here, it's possible for the compiler to prove that the count can't be more than 4, so it would be safe to unroll the loop 4x, with conditionals to jump over parts of it based on the actual value of `iterCount`. But again, whether the compiler actually does that in any given instance is going to be down to the individual compiler's analysis and heuristics. Generally if the loop body is long, or the iteration count is high, it will be less profitable to unroll it.&#xD;&#xA;&#xD;&#xA;By the way, in your example the value of `maxIter` is always either 2 or 3, and so the loop count is either 5 or 7, and the compiler should be able to see that, so it would be a reasonable expectation that it could unroll that loop if it decides it's a good idea.&#xD;&#xA;&#xD;&#xA;Also, if you have access to [GL_EXT_control_flow_attributes](https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_control_flow_attributes.txt) then you can mark up loops with the `[[unroll]]` annotation to explicitly request the compiler to unroll it—although the compiler may still refuse to honor that if it doesn't have a compiler-visible upper bound." ContentLicense="CC BY-SA 4.0" />
  <row Id="35090" PostHistoryTypeId="5" PostId="12252" RevisionGUID="d42b6acf-4a50-47bc-8dec-be2bd5d61270" CreationDate="2021-10-14T05:10:16.080" UserId="5664" Comment="added 2073 characters in body" Text="My goal is to render a volumetric point light as explained in this book's chapter 10: [FGED Rendering][1]&#xD;&#xA;The book explains the math pretty well, but I'm not sure I understand what is the required setup for a volumetric point light halo to be visible. The book describes the following code snippet to calculate the brightness of the volumetric halo:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float R = 5.f; // Radius of the volumetric point light halo.&#xD;&#xA;float R2 = R * R;&#xD;&#xA;float recipR2 = 1.f / R2;&#xD;&#xA;float recip3R2 = 1.f / (3.f * R2);&#xD;&#xA;float normalizer = 3.f / (4.f * R);&#xD;&#xA;&#xD;&#xA;// This shader renders a halo effect of radius R at the object-space position pobject.&#xD;&#xA;// The object-space camera position c and view direction z are given by cameraPosition &#xD;&#xA;// and cameraView. The pixelCoord parameter specifies the viewport coordinates of the&#xD;&#xA;// pixel being processed, and it is used to read from the depth buffer.&#xD;&#xA;float CalculateHaloBrightness(float3 pobject, float2 pixelCoord)&#xD;&#xA;{&#xD;&#xA;	float3 vdir = cameraPosition - pobject;&#xD;&#xA;	float v2 = dot(vdir, vdir);&#xD;&#xA;	float p2 = dot(pobject, pobject);&#xD;&#xA;	float pv = -dot(pobject, vdir);&#xD;&#xA;	float m = sqrt(max(pv * pv - v2 * (p2 - R2), 0.0));&#xD;&#xA;&#xD;&#xA;     // Read z0 from the depth buffer.&#xD;&#xA;	float2 depth = texture(depthBuffer, pixelCoord);&#xD;&#xA;	float t0 = 1.0 + depth / dot(cameraView, vdir);&#xD;&#xA;&#xD;&#xA;     // Calculate clamped limits of integration.&#xD;&#xA;	float t1 = clamp((pv - m) / v2, t0, 1.0);&#xD;&#xA;	float t2 = clamp((pv + m) / v2, t0, 1.0);&#xD;&#xA;	float u1 = t1 * t1;&#xD;&#xA;	float u2 = t2 * t2;&#xD;&#xA;&#xD;&#xA;     // Evaluate density integral, normalize, and square.&#xD;&#xA;	float B = ((1.0 - p2 * recipR2) * (t2 - t1) + pv * recipR2 * (u2 - u1) - v2 * recip3R2 * (t2 * u2 - t1 * u1)) * normalizer;&#xD;&#xA;	return (B * B * v2);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;There's a few things that I don't understand:&#xD;&#xA;1) What is meant exactly by `pobject`, `cameraPosition` and `cameraView` being in object-space? Does it just mean that they all have to be in world-space for this function to work correctly?&#xD;&#xA;&#xD;&#xA;2) On what surface am I supposed to execute this pixel shader on? From what I read, it sounds like it has to be run on a cube centered at `pobject` but I'm not sure.&#xD;&#xA;&#xD;&#xA;3) Is a light scattering medium required, such as fog? It would make sense that it does, but it's not really mentioned in the book's explanation.&#xD;&#xA;&#xD;&#xA;I realize this is a difficult question to answer, since I haven't included the entire explanation present in the book here. I assume the author would not like that. So I am hoping that maybe somebody here might roughly understand what's going on and point me in the right direction.&#xD;&#xA;&#xD;&#xA;edit:&#xD;&#xA;I am almost there! Here's my current HLSL implementation:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;ConstantBuffer&lt;pass_data&gt; cb_pass : register(b0);&#xD;&#xA;Texture2D&lt;float&gt; Depth : register(t3);&#xD;&#xA;SamplerState linear_wrap_sampler : register(s0);&#xD;&#xA;&#xD;&#xA;float4 ps_main(vertex_out pin) : SV_Target&#xD;&#xA;{&#xD;&#xA;    float2 uv = pin.posh.xy / cb_pass.sceen_size;&#xD;&#xA;    float depth = Depth.SampleLevel(linear_wrap_sampler, uv, 0.f);&#xD;&#xA;&#xD;&#xA;    // Volumetric halo variables.&#xD;&#xA;    float halo = 0.f;&#xD;&#xA;    float halo_radius = cb_pass.radius;&#xD;&#xA;    float halo_radius2 = halo_radius * halo_radius;&#xD;&#xA;    float rcp_halo_radius2 = 1.f / halo_radius2;&#xD;&#xA;    float rcp_3halo_radius2 = 1.f / (3.f * halo_radius2);&#xD;&#xA;    float density_integral_normalizer = 3.f / (4.f * halo_radius);&#xD;&#xA;&#xD;&#xA;    // Render volumetric halo.&#xD;&#xA;    float4 world_space_pixel = float4(pin.posw, 1.f);&#xD;&#xA;    float3 pobject = float3(mul(world_space_pixel, cb_pass.world_to_object).xyz);&#xD;&#xA;    float3 cam_pos = mul(float4(cb_pass.eye_pos, 1.f), cb_pass.world_to_object).xyz;&#xD;&#xA;    float3 vdir = cam_pos - pobject;&#xD;&#xA;    float v2 = dot(vdir, vdir);&#xD;&#xA;    float p2 = dot(pobject, pobject);&#xD;&#xA;    float pv = -dot(pobject, vdir);&#xD;&#xA;    float m = sqrt(max(pv * pv - v2 * (p2 - halo_radius2), 0.f));&#xD;&#xA;&#xD;&#xA;    float3 cam_view = mul(float4(cb_pass.eye_forward, 0.f), cb_pass.world_to_object).xyz;&#xD;&#xA;    float t0 = 1.f + depth / dot(cam_view, vdir);&#xD;&#xA;    float t1 = clamp((pv - m) / v2, t0, 1.f);&#xD;&#xA;    float t2 = clamp((pv + m) / v2, t0, 1.f);&#xD;&#xA;    float u1 = t1 * t1;&#xD;&#xA;    float u2 = t2 * t2;&#xD;&#xA;&#xD;&#xA;    float B = ((1.f - p2 * rcp_halo_radius2) * (t2 - t1) + pv * rcp_halo_radius2 * (u2 - u1) - v2 * rcp_3halo_radius2 * (t2 * u2 - t1 * u1)) * density_integral_normalizer;&#xD;&#xA;    halo = (B * B * v2);&#xD;&#xA;&#xD;&#xA;    return float4(halo, halo, halo, 1.f);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;The only problem remaining is that the halo only appears when the camera gets very close to the halo. When the camera is close enough it does show up correctly though. I noticed that scaling `cb_pass.eye_forward` will make the halo show up from further away but I'm not sure what is causing this.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.amazon.ca/Foundations-Game-Engine-Development-Rendering/dp/0985811757/ref=sr_1_2?crid=2U5PN7NJQ31S7&amp;dchild=1&amp;keywords=foundations%20of%20game%20engine%20development&amp;qid=1634091891&amp;sprefix=foundations%20of%20game%20engine%20deve%2Caps%2C174&amp;sr=8-2&#xD;&#xA;  [2]: https://i.stack.imgur.com/SJxR2.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35091" PostHistoryTypeId="5" PostId="12254" RevisionGUID="eb71b7ae-0b52-4fad-a5aa-874d61c37725" CreationDate="2021-10-14T12:25:32.380" UserId="7952" Comment="added options that might help" Text="The post reads cropped but then talks about squeezed, so I gave a little extra info to help clarify.&#xD;&#xA;&#xD;&#xA;One possibility is that the final image is cropped, ie some texel data is being removed completely from the image such as the top and/or bottom rows of texels.&#xD;&#xA;&#xD;&#xA;In this case the image is considered just like it is worded &quot;cropped&quot;.&#xD;&#xA;&#xD;&#xA;Another possibility is the image is being rescaled, meaning that the entire image is kept but an algorithm is being used to compute new texels to fit the final image size and keep as much of the original image as possible.&#xD;&#xA;&#xD;&#xA;Normally rescaling is done in a way that keeps the original aspect ratio, but when that isn't possible then the texels are effectively stretched or squeezed. Which is the second option listed in the question.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;One possibility here is to modify the frustum to fit the entire image then rescale the image to fit the frustum. Is this possible here? (I'm guessing not but thought I would mention it)&#xD;&#xA;&#xD;&#xA;Yet another approach is to introduce black(or some other color) bars on the top/bottom/left/right of the image and fit the frustum to capture the entire image. The image itself would be nearly exactly what is needed but the end result would have the dead space. Just like how a widescreen movie is fit to a 4x3 television.&#xD;&#xA;&#xD;&#xA;If cropping is the only viable option then usually the bottom of the image is cropped, but this is getting into the realm of opinion and may be something you want to go back to the client to get clarification on. (and is also wandering out of my knowledge area since I am used to having that handy gpu available to manipulate the image to my every whim)&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35092" PostHistoryTypeId="5" PostId="12251" RevisionGUID="5591deb7-6b66-49fd-8a9a-6df48f5fb614" CreationDate="2021-10-15T20:30:53.623" UserId="17351" Comment="added 864 characters in body" Text="I am doing some image processing and am a little bit confused about reporting a 35 mm equivalent focal length. I am working with a 640x360 image which has an aspect ratio of 1.7777. A 35 mm film is 36 mm x 24 mm, for an aspect ratio of 1.5. We have the formulae $F_X = f_x \frac{W}{w}$ and $F_y = f_y \frac{H}{h}$. I currently have the values $f_x = f_y =$ 370 px calibrated for the 640x360 image. If I use $W = $ 36 mm, $w = $ 640 px, $H = $ 24 mm, and $h = $ 360 px, then the scale factors $\frac{W}{w}$ and $\frac{H}{h}$ disagree due to the disparity in aspect ratio, and $F_x \neq F_y$, when I expect them to be equal.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is the idea to consider my 640x360 px image as a cropped 640x426.666 px image? Or is it to consider my current 640x360 as a vertically squeezed image with non-square pixels?&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;I have added the following diagram to help articulate my confusion:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have added the viewing frustum for the 640x360 image. The aspect ratio of this image determines the frustum. I have two ways I can fit a 35 mm film into this frustum. I can find where it fits horizontally, where the 36 mm piece sits in the frustum, but then the film hangs below the frustum. I can also slide the film until it fits vertically, where the 24 mm piece fits, but then the 36 mm side can't reach the other side of the frustum. In both of these options, the focal length is different. Which one is more proper to report?&#xD;&#xA;&#xD;&#xA;My intuition tells me that the first option is more correct, where the 35 mm film is fit horizontally. Then the 640x360 image is considered as a cropped 35 mm film image. But then there is another ambiguity. Do we center the film so that there is equal overhang on the top and bottom? That is, should the film be centered along the principal point? See the blue piece of film here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;FINAL EDIT:&#xD;&#xA;&#xD;&#xA;My conclusion is that there really is no concept of a 35 mm film equivalent when the aspect ratio doesn't match 36/24 = 1.5. Take, for example, this image taken with extremely high aspect ratio film:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;We can consider a 35 mm equivalent with a common principal point either like such:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;or like such:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The comparison shows that there is no analogue:&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;Depending on which way you decide to frame the 35 mm film, you conclude either that the focal length is really really large or very small.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FM7D2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/p1jkE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ZRg26.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ipgoE.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/hc1f9.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/5Ygrb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35097" PostHistoryTypeId="50" PostId="12158" RevisionGUID="9e508ba0-f483-4f0c-a8f2-7b2066f9156c" CreationDate="2021-10-16T09:03:55.250" UserId="-1" />
  <row Id="35098" PostHistoryTypeId="2" PostId="12259" RevisionGUID="2383bb72-f857-486b-a0ca-3d77014fee0f" CreationDate="2021-10-16T13:37:03.280" UserId="16949" Text="We have an application which needs to render spline curves (cubic, bezier, b-spline etc.). We currently have working algorithms in C to stroke the control points of these curves into line strips.&#xD;&#xA;&#xD;&#xA;The issue we are running to is the need to constantly re-stroke the curves based on zoom and how much of the curve is visible. I am guessing this would be both more practical and more efficient to do on the GPU.&#xD;&#xA;&#xD;&#xA;What is the most standard way to approach this problem? I have heard about Geometry shaders but have also heard they are inefficient so I'm not sure if there is maybe a better way. If not, what is the general process of stroking curves like this?&#xD;&#xA;&#xD;&#xA;In general, the stroking algorithms take in the control points of the curves, and determine a new set of points for a line strip (based on a tolerance calculated from the zoom level, which defines the stroking interval).&#xD;&#xA;&#xD;&#xA;We are using Vulkan if it makes any difference. Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="35100" PostHistoryTypeId="1" PostId="12259" RevisionGUID="2383bb72-f857-486b-a0ca-3d77014fee0f" CreationDate="2021-10-16T13:37:03.280" UserId="16949" Text="Rendering splines on GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="35101" PostHistoryTypeId="3" PostId="12259" RevisionGUID="2383bb72-f857-486b-a0ca-3d77014fee0f" CreationDate="2021-10-16T13:37:03.280" UserId="16949" Text="|curve|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35104" PostHistoryTypeId="2" PostId="12260" RevisionGUID="26ff5960-216d-4927-b93d-43ca8ca3560d" CreationDate="2021-10-17T18:52:22.430" UserId="17192" Text="This demo:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/registry/webgl/sdk/demos/google/particles/&#xD;&#xA;&#xD;&#xA;Contains multiple effects that can be done with WebGL. I've been able to recreate some of them, but for example I don't understand (even after looking at the code) how the flames &quot;swing&quot; (&quot;curl&quot;?) effect is done. Same for the smoke effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You can see part of the code here:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/registry/webgl/sdk/demos/google/particles/demo.js&#xD;&#xA;&#xD;&#xA;Is the `spinSpeedRange` variable the one that creates this effect? In which case, how does it work? Looking at the code I reach something like this (for billboarding):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  '  vec2 uv = uvLifeTimeFrameStart.xy;\n' +&#xD;&#xA;  // (... more code)&#xD;&#xA;  '  float s = sin(spinStart + spinSpeed * localTime);\n' +&#xD;&#xA;  '  float c = cos(spinStart + spinSpeed * localTime);\n' +&#xD;&#xA;  '\n' +&#xD;&#xA;  '  vec2 rotatedPoint = vec2(uv.x * c + uv.y * s, \n' +&#xD;&#xA;  '                           -uv.x * s + uv.y * c);\n' +&#xD;&#xA;  '  vec3 localPosition = vec3(basisX * rotatedPoint.x +\n' +&#xD;&#xA;  '                            basisZ * rotatedPoint.y) * size +\n' +&#xD;&#xA;  '                       velocity * localTime +\n' +&#xD;&#xA;  '                       acceleration * localTime * localTime + \n' +&#xD;&#xA;  '                       position;\n' +&#xD;&#xA;  '\n' +&#xD;&#xA;  '  outputPercentLife = percentLife;\n' +&#xD;&#xA;  '  gl_Position = viewProjection * vec4(localPosition + world[3].xyz, 1.);\n' +&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;But I don't understand exactly how it works. I guess the question would be what should I do to a single particle (e.g. rotate it?) to get as a result a simulation of a flame like the one in the example?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35106" PostHistoryTypeId="1" PostId="12260" RevisionGUID="26ff5960-216d-4927-b93d-43ca8ca3560d" CreationDate="2021-10-17T18:52:22.430" UserId="17192" Text="How khronos flame swing effect is done?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35107" PostHistoryTypeId="3" PostId="12260" RevisionGUID="26ff5960-216d-4927-b93d-43ca8ca3560d" CreationDate="2021-10-17T18:52:22.430" UserId="17192" Text="|shader|webgl|particles|transform-feedback|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35108" PostHistoryTypeId="50" PostId="10248" RevisionGUID="c81b30cf-4811-45cf-9023-09d8954fb85b" CreationDate="2021-10-17T21:03:00.217" UserId="-1" />
  <row Id="35111" PostHistoryTypeId="2" PostId="12261" RevisionGUID="3c3218f4-aa9f-40e6-9870-d044dd2aa556" CreationDate="2021-10-19T14:52:32.967" UserId="7952" Text="It should be reasonably easy to implement a line segment based spline shader using just a vertex shader and fragment shader. The biggest issues are how the splines are represented, getting that data to the GPU, then writing a vertex shader that accesses the correct spline info.&#xD;&#xA;&#xD;&#xA;As one possibility:&#xD;&#xA;&#xD;&#xA; 1. Upload the spline info to an appropriate buffer. &#xD;&#xA; 2. Setup a graphics pipeline to draw lines. &#xD;&#xA; 3. Setup the vertex shader to take a push constant which holds info about which spline to use and other relevant info.&#xD;&#xA; 4. Then do a draw call with the number of line segments needed for the final spline, along with appropriate push data.&#xD;&#xA;&#xD;&#xA;Since the pipeline is expecting lines every two vertices represent 1 line segment. The vertex shader can use the vertex index (made available through glsl) to determine which segment to draw. IE 0, 1 are segment 0: 2,3 are segment 1. Combined with the push data it can lookup the spline values, compute the segment vertex data, do the appropriate MVP transform for each end of that segment.&#xD;&#xA;&#xD;&#xA;The upside is each spline can have a variable number of segments such as a draw call for a spline with 256 vertices would get 128 segments. The vertex shader can also determine line width which could be varied if the splines are 3D to make them thicker as they move away from the camera.&#xD;&#xA;&#xD;&#xA;But the ends of the splines could be tricky to get connected smoothly, as the line segments change direction there could be overlap and disjoint looking spots on the splines. (it really depends on the line thickness)&#xD;&#xA;&#xD;&#xA;Computing a segment that is equally spaced on splines isn't very easy but is doable.&#xD;&#xA;&#xD;&#xA;This answer is making a lot of assumptions about the splines repersentation and what not, if you give more info about where I have gotten it wrong (or areas you just need more info) then let me know and I'll update the answer." ContentLicense="CC BY-SA 4.0" />
  <row Id="35113" PostHistoryTypeId="50" PostId="9199" RevisionGUID="aa6ab393-5288-4e14-adf3-462b64851933" CreationDate="2021-10-20T02:06:30.740" UserId="-1" />
  <row Id="35114" PostHistoryTypeId="50" PostId="10584" RevisionGUID="b8dea28b-5db0-41b5-b93a-0aea4922bff4" CreationDate="2021-10-20T06:06:40.670" UserId="-1" />
  <row Id="35115" PostHistoryTypeId="2" PostId="12262" RevisionGUID="cf7fa9bb-ce39-449b-aaed-2389e8410492" CreationDate="2021-10-20T07:39:35.153" UserDisplayName="user11739" Text="I am currently writing an AR experience.&#xD;&#xA;I have a Camera View Matrix, A Camera Perspective matrix and the Model Matrix of the content I display.&#xD;&#xA;&#xD;&#xA;The AR content should can be switched to &quot;2D&quot;, so it is attached to the screen.&#xD;&#xA;&#xD;&#xA;For this, I have predefined Model, View and Projection Matrices.&#xD;&#xA;&#xD;&#xA;I would like to create an interpolation between &quot;Content in Room&quot; and &quot;Content attached to screen&quot;&#xD;&#xA;How would I achieve this?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;My first idea was to calculate both MVPs and sending them both to the shaders and giving each shader an interpolation factor (I would interpolate the vertices)  &#xD;&#xA;This would work out I think, but I don't know if this causes deformations during interpolation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RaFak.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35117" PostHistoryTypeId="1" PostId="12262" RevisionGUID="cf7fa9bb-ce39-449b-aaed-2389e8410492" CreationDate="2021-10-20T07:39:35.153" UserDisplayName="user11739" Text="How to interpolate between two MVP setups?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35118" PostHistoryTypeId="3" PostId="12262" RevisionGUID="cf7fa9bb-ce39-449b-aaed-2389e8410492" CreationDate="2021-10-20T07:39:35.153" UserDisplayName="user11739" Text="|shader|matrix|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35120" PostHistoryTypeId="2" PostId="12263" RevisionGUID="4b149b9e-7f1c-442c-8f81-30499754c1ec" CreationDate="2021-10-20T13:23:02.850" UserDisplayName="user17390" Text="We know that in **perspective projection** Object positions are transformed to the view plane along lines that converge to the projection reference (center) point Which is like this:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/p9bEa.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But many websites saying that COP(Centre of projection) and vanishing point both are same. But we know that Parallel lines that are not parallel to the viewing &#xD;&#xA;plane, converge to a vanishing point vanishing point. In the above picture if I draw the parallel line through the point $A, B, C$ then they are intersects at infinity which is vanishing point. &#xD;&#xA;&#xD;&#xA;My question is how COP and vanishing point both are same? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35122" PostHistoryTypeId="1" PostId="12263" RevisionGUID="4b149b9e-7f1c-442c-8f81-30499754c1ec" CreationDate="2021-10-20T13:23:02.850" UserDisplayName="user17390" Text="Why vanishing point and centre of projection are same" ContentLicense="CC BY-SA 4.0" />
  <row Id="35123" PostHistoryTypeId="3" PostId="12263" RevisionGUID="4b149b9e-7f1c-442c-8f81-30499754c1ec" CreationDate="2021-10-20T13:23:02.850" UserDisplayName="user17390" Text="|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35124" PostHistoryTypeId="5" PostId="12263" RevisionGUID="e054cbc9-2a47-404a-855e-e6bc78d37229" CreationDate="2021-10-20T14:01:35.407" UserId="13095" Comment="Fix some grammar and spelling" Text="We know that in **perspective projection** object positions are transformed to the view plane along lines that converge to the projection reference (center) point like this:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[1]:https://i.stack.imgur.com/p9bEa.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But many websites say that COP(Centre of projection) and vanishing point both are the same. But we know that parallel lines that are not parallel to the viewing plane converge to a vanishing point. In the above picture, if I draw the parallel line through the point $A, B, C$, then they intersect at infinity which is the vanishing point. &#xD;&#xA;&#xD;&#xA;My question is: How are COP and vanishing point both the same? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35125" PostHistoryTypeId="4" PostId="12263" RevisionGUID="e054cbc9-2a47-404a-855e-e6bc78d37229" CreationDate="2021-10-20T14:01:35.407" UserId="13095" Comment="Fix some grammar and spelling" Text="Why are vanishing point and centre of projection the same" ContentLicense="CC BY-SA 4.0" />
  <row Id="35126" PostHistoryTypeId="50" PostId="10025" RevisionGUID="56b10661-b08c-4fb7-9cd2-ab54a895fecb" CreationDate="2021-10-21T00:06:15.423" UserId="-1" />
  <row Id="35127" PostHistoryTypeId="50" PostId="9267" RevisionGUID="20a19f5e-c3b0-47f1-b10d-9573c8575bad" CreationDate="2021-10-21T09:07:30.770" UserId="-1" />
  <row Id="35128" PostHistoryTypeId="2" PostId="12264" RevisionGUID="ace46ce7-2687-479f-9e2a-bef2d5184671" CreationDate="2021-10-21T16:13:24.467" UserId="17391" Text="I have a simple question just because I can’t find any good example in the internet. How to create fog without using particles? How to make for with different density on different locations and in general how to make gaseous objects (like a nebula)? Any pointers? Thanks for reading" ContentLicense="CC BY-SA 4.0" />
  <row Id="35130" PostHistoryTypeId="1" PostId="12264" RevisionGUID="ace46ce7-2687-479f-9e2a-bef2d5184671" CreationDate="2021-10-21T16:13:24.467" UserId="17391" Text="How to render fog in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="35131" PostHistoryTypeId="3" PostId="12264" RevisionGUID="ace46ce7-2687-479f-9e2a-bef2d5184671" CreationDate="2021-10-21T16:13:24.467" UserId="17391" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35132" PostHistoryTypeId="2" PostId="12265" RevisionGUID="65731aef-3ce4-444b-aaab-0c365041a75b" CreationDate="2021-10-21T16:38:27.017" UserId="13095" Text="The answer is: they are **not the same**. Here is a [related question from another site](https://www.quora.com/What-is-the-difference-between-vanishing-point-and-center-of-projection-in-computer-graphics) where somebody asked what the difference between both of them is (found the sentence I asked about in the comments there too). This is the main reference my answer is based on.&#xD;&#xA;&#xD;&#xA;From [Wikipedia](https://en.wikipedia.org/wiki/Vanishing_point):&#xD;&#xA;&#xD;&#xA;&quot;A vanishing point is a point **on** the image plane of a perspective drawing where the two-dimensional perspective projections (or drawings) of mutually parallel lines in three-dimensional space appear to converge.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The centre of projection (COP) is **not on** the image plane as you can see on the image you posted. It is the focal point where all your projection lines converge. If you place it on the image plane you would create a singularity and the whole projection math would fail.&#xD;&#xA;&#xD;&#xA;However, the location of the vanishing point on the 2d plane depends on the position of your COP. Take the drawn cube on the projection plane of your image as an example. The top plane has 2 vanishing points because it has two sets of parallel lines. Now if you rotate the COP left or right around the 3d cube until one set of lines of the top face is parallel to the projection plane you would observe the following: One vanishing point would move directly to the 12 o'clock position while the other would accelerate away from the plane until it disappears because as you wrote:&#xD;&#xA;&#xD;&#xA;&gt; parallel lines **that are not parallel** to the viewing plane converge to a vanishing point&#xD;&#xA;&#xD;&#xA;Lines parallel to the projection plane do not have a vanishing point.&#xD;&#xA;&#xD;&#xA;So how does it come that the internet says otherwise? My educated guess here is, that like with many other things, people start mixing up terms of closely related things. Also, you provided [this link](https://drive.google.com/file/d/1PRTh8sWwhM7AWDti1m7VCBTbNj_Ha5Fh/view) here as a reference. Strictly, they are not saying both are the same. They simply just name them identically. But that doesn't make it any better." ContentLicense="CC BY-SA 4.0" />
  <row Id="35134" PostHistoryTypeId="5" PostId="12265" RevisionGUID="dd34ecfe-a9c5-4111-a927-74053c0003a5" CreationDate="2021-10-21T16:52:22.220" UserId="13095" Comment="added 285 characters in body" Text="The answer is: they are **not the same**. Here is a [related question from another site](https://www.quora.com/What-is-the-difference-between-vanishing-point-and-center-of-projection-in-computer-graphics) where somebody asked what the difference between both of them is (found the sentence I asked about in the comments there too). This is the main reference my answer is based on.&#xD;&#xA;&#xD;&#xA;From [Wikipedia](https://en.wikipedia.org/wiki/Vanishing_point):&#xD;&#xA;&#xD;&#xA;&quot;A vanishing point is a point **on** the image plane of a perspective drawing where the two-dimensional perspective projections (or drawings) of mutually parallel lines in three-dimensional space appear to converge.&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The centre of projection (COP) is **not on** the image plane as you can see on the image you posted. It is the focal point where all your projection lines converge. If you place it on the image plane you would create a singularity and the whole projection math would fail.&#xD;&#xA;&#xD;&#xA;However, the location of the vanishing point on the 2d plane depends on the position of your COP. Take the drawn cube on the projection plane of your image as an example. The top plane has 2 vanishing points because it has two sets of parallel lines. Now if you rotate the COP left or right around the 3d cube until one set of lines of the top face is parallel to the projection plane you would observe the following: One vanishing point would move directly to the 12 o'clock position while the other would accelerate away from the plane until it disappears because as you wrote:&#xD;&#xA;&#xD;&#xA;&gt; parallel lines **that are not parallel** to the viewing plane converge to a vanishing point&#xD;&#xA;&#xD;&#xA;Lines parallel to the projection plane do not have a vanishing point.&#xD;&#xA;&#xD;&#xA;So how does it come that the internet says otherwise? My educated guess here is, that like with many other things, people start mixing up terms of closely related things. Also, you provided [this link](https://drive.google.com/file/d/1PRTh8sWwhM7AWDti1m7VCBTbNj_Ha5Fh/view) here as a reference. Strictly, they are not saying both are the same. They simply just name them identically. But that doesn't make it any better.&#xD;&#xA;&#xD;&#xA;**UPDATE**&#xD;&#xA;A noteworthy difference between COP and vanishing point (as mentioned by Wyck in the questions comments) is that the vanishing point is actually a 2d point while the COP is a 3d point. One can deduce it from my answer, but I felt like it should be mentioned explicitly." ContentLicense="CC BY-SA 4.0" />
  <row Id="35135" PostHistoryTypeId="2" PostId="12266" RevisionGUID="f109ee8e-57ac-44b5-9bad-68d0ca09033e" CreationDate="2021-10-21T22:00:33.480" UserId="7952" Text="Clouds are a good fit for this but good quality cloud(s) rendering isn't usually simple. Searching for cloud rendering should give a few hits good hits. Here is neat [shader toy rendering a cloud like tunnel][1]. But take a look at your GPU stats, ray marched clouds can be very expensive. If you search shader toy for clouds you'll find several really good examples.  Search shader toy for nebula as well. Sometimes the effects on shader toy can be adapted to rasterization.&#xD;&#xA;&#xD;&#xA;Atmospheric shadowing/Volumetric lights/many other names... can be extended by sending a ray through a 3D volume to accumulate fog along that ray, combined with flow fields these techniques can create outstanding effects but it is fairly difficult to implement. (each texel of the 3D volume tends to represent large areas and aliasing becomes an important issue that has to be dealt with)&#xD;&#xA;&#xD;&#xA;Next, it is possible to combine multiple effects such as halo's, planar fog, etc., to get an effect for particular scenarios.&#xD;&#xA;&#xD;&#xA;If the &quot;nebula&quot; is always off in the distance (cannot be approached) then a simple quad with a partially transparent texture mapped to it can provide a nice effect.&#xD;&#xA;&#xD;&#xA;There are dozens of other approach's I listed some of the most current.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/3l23Rh" ContentLicense="CC BY-SA 4.0" />
  <row Id="35137" PostHistoryTypeId="50" PostId="8935" RevisionGUID="c2d7f80f-de89-4d54-90a3-dd5f3ed5f6a3" CreationDate="2021-10-21T23:06:15.367" UserId="-1" />
  <row Id="35138" PostHistoryTypeId="50" PostId="9875" RevisionGUID="522b51b6-44cf-4b55-ac98-3feb91aefba8" CreationDate="2021-10-22T04:06:40.647" UserId="-1" />
  <row Id="35144" PostHistoryTypeId="50" PostId="12215" RevisionGUID="c2feed74-78d1-461e-a8a0-ea7a3c2ab3b8" CreationDate="2021-10-22T10:01:05.083" UserId="-1" />
  <row Id="35145" PostHistoryTypeId="2" PostId="12268" RevisionGUID="068de99c-d770-4365-8fc2-530892496022" CreationDate="2021-10-22T10:31:16.897" UserId="10129" Text="**My main problem is:** When I'm raymarching (should I use View Space or Screen Space/Clip Space?), how do I determine condition to end marching and find which UV's color should be used?&#xD;&#xA;&#xD;&#xA;My current code and results:&#xD;&#xA;&#xD;&#xA;    bool GetReflection(float3 ScreenSpaceReflectionVec, float3 ScreenSpacePos, out float3 ReflectionColor)&#xD;&#xA;    {&#xD;&#xA;    	for (int RayStepIdx = 0; RayStepIdx &lt; NUM_RAY_MARCH_SAMPLES; RayStepIdx++)&#xD;&#xA;    	{&#xD;&#xA;    		float3 RaySample = (RayStepIdx * MAX_REFLECTION_RAY_MARCH_STEP) * ScreenSpaceReflectionVec + ScreenSpacePos;&#xD;&#xA;    		float ZBufferVal = (hiZBuffer.Sample(pointSampler, RaySample.xy).r); // Current Pos&#xD;&#xA;    		float ZBufferOrigin = (hiZBuffer.Sample(pointSampler, ScreenSpacePos.xy).r); // Origin Pos&#xD;&#xA;    				&#xD;&#xA;    		if (ZBufferOrigin &gt; ZBufferVal)&#xD;&#xA;    		{&#xD;&#xA;    			ReflectionColor = colorBuffer.SampleLevel(pointSampler, RaySample.xy, 0).rgb;&#xD;&#xA;    			return true;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return false;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Camera ray in CS&#xD;&#xA;    inline void GenerateCameraRay(uint2 index, uint2 dimensions, float4x4 projectionToWorld, inout float3 origin, out float3 direction)&#xD;&#xA;    {&#xD;&#xA;        // Doesn't really matter, works correctly&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float4 SSR(PixelInputType input) : SV_TARGET&#xD;&#xA;    {&#xD;&#xA;    	float3 normalVS = normalBuffer.Sample(pointSampler, input.uv).xyz;&#xD;&#xA;    	if (!any(normalVS))&#xD;&#xA;    	{&#xD;&#xA;    		return float4(colorBuffer.SampleLevel(pointSampler, input.uv, 0).rgb, 1.0f);&#xD;&#xA;    	}&#xD;&#xA;    	normalVS = mul(float4(normalVS, 0.0f), g_matricesCB.viewMatrix).xyz;&#xD;&#xA;    	&#xD;&#xA;    	float depthCS = hiZBuffer.Sample(pointSampler, input.uv).r;&#xD;&#xA;    	&#xD;&#xA;    	// Calculate primary ray origin and direction&#xD;&#xA;    	float3 primaryRayOrigin = g_constantBuffer.cameraPosition.xyz;&#xD;&#xA;    	float3 primaryRayDirection;&#xD;&#xA;    	GenerateCameraRay(input.uv * float2(1024.0f, 512.0f), float2(1024.0f, 512.0f), g_matricesCB.invViewProjMatrix, primaryRayOrigin, primaryRayDirection);    	&#xD;&#xA;    	&#xD;&#xA;    	float3 ReflectionColor = float3(0, 0, 0);&#xD;&#xA;    	if (GetReflection(primaryRayDirection, float3(input.uv, depthCS), ReflectionColor))&#xD;&#xA;    	{&#xD;&#xA;    		return float4(ReflectionColor + colorBuffer.SampleLevel(pointSampler, input.uv, 0).rgb, 1.0f);&#xD;&#xA;        // * float4(1, 0, 0, 1); // DEBUG multiply&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	return float4(colorBuffer.SampleLevel(pointSampler, input.uv, 0).rgb, 1.0f); // Just return scene color&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;White is 3D plane model and red is reflection of that model reflected on black plane:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But using presented code above with textures, it looks like this (because iteration always stops on first Suzanne's pixel due to current depth condition):&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;My question is - **how can I correctly obtain UV in reflection plane and what should be terminating condition of raymarching?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LywJr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bUXyR.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/UfFzu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35147" PostHistoryTypeId="1" PostId="12268" RevisionGUID="068de99c-d770-4365-8fc2-530892496022" CreationDate="2021-10-22T10:31:16.897" UserId="10129" Text="SSR/RTLR - hitting object/ending condition" ContentLicense="CC BY-SA 4.0" />
  <row Id="35148" PostHistoryTypeId="3" PostId="12268" RevisionGUID="068de99c-d770-4365-8fc2-530892496022" CreationDate="2021-10-22T10:31:16.897" UserId="10129" Text="|raymarching|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35149" PostHistoryTypeId="5" PostId="12266" RevisionGUID="a014cde9-2ea7-4501-9274-918704b5ec91" CreationDate="2021-10-22T12:25:01.273" UserId="7952" Comment="added 596 characters in body" Text="Clouds are a good fit for this but good quality cloud(s) rendering isn't usually simple. Searching for cloud rendering should give a few hits good hits. Here is neat [shader toy rendering a cloud like tunnel][1]. But take a look at your GPU stats, ray marched clouds can be very expensive. If you search shader toy for clouds you'll find several really good examples.  Search shader toy for nebula as well. Sometimes the effects on shader toy can be adapted to rasterization.&#xD;&#xA;&#xD;&#xA;Atmospheric shadowing/Volumetric lights/many other names... can be extended by sending a ray through a 3D volume to accumulate fog along that ray, combined with flow fields these techniques can create outstanding effects but it is fairly difficult to implement. (each texel of the 3D volume tends to represent large areas and aliasing becomes an important issue that has to be dealt with)&#xD;&#xA;&#xD;&#xA;Next, it is possible to combine multiple effects such as halo's, planar fog, etc., to get an effect for particular scenarios.&#xD;&#xA;&#xD;&#xA;If the &quot;nebula&quot; is always off in the distance (cannot be approached) then a simple quad with a partially transparent texture mapped to it can provide a nice effect.&#xD;&#xA;&#xD;&#xA;There are dozens of other approach's I listed some of the most current.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;Searching for &quot;volumetric fog&quot; gives a lot of hits. This [presentation by Wronski for siggraph 2014][2] is very good. Wronski has a [blog][3] that is generally pretty good to read.  Techniques like this work best when all the buffers that are needed to create the effect are used by as many techniques as possible because it amortizes the cost of creating them. Cascade shadow maps in particular go with this technique well.&#xD;&#xA;&#xD;&#xA;[Here is a link][4] to a fairly straight forward approach to generating volumetric fog. It has shaders included but is light on the math/explanation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/3l23Rh&#xD;&#xA;  [2]: https://bartwronski.files.wordpress.com/2014/08/bwronski_volumetric_fog_siggraph2014.pdf&#xD;&#xA;  [3]: https://bartwronski.com/articles-blog-posts-index/#graphics&#xD;&#xA;  [4]: https://www.evl.uic.edu/sjames/cs525/shader.html#:~:text=Volumetric%20fog%20enables%20the%20fog%20only%20within%20desired,here%20only%20works%20for%20static%20lighting%20and%20fogging." ContentLicense="CC BY-SA 4.0" />
  <row Id="35150" PostHistoryTypeId="2" PostId="12269" RevisionGUID="84059f70-f65e-4b61-a434-7790d5df99bf" CreationDate="2021-10-22T21:45:12.763" UserId="17397" Text="# What I am trying to achieve #&#xD;&#xA;So I'm a fractal enthusiast and decided to build a 2D/3D fractal generator in WebGL using raymarching, with Typescript as scripting language. I've been a C#/Typescript dev for several years but having zero experience with 3d programming, I used [Michael Walczyk's blog][1] as a starting point. Some of my code I use here is derived from his tutorial.&#xD;&#xA;&#xD;&#xA;I added the functionality that you can move through the object in my 3d raymarched world using WASDQEZC keys. WS = strafe forward-back, AD = strafe left-right, QE = strafe up-down, ZC = roll left-right. I combine this with a mouse look function which moves in the direction the mouse pointer is located on the rendering canvas. So what I want is total freedom of movement like in a spacesim. For this I am using a separate camera rotation matrix together with translation values and send them to the shader like this. So far I've got WS, AD and QE working okayish (please see 'my problem' to find out why).&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  setCameraMatrix(): void {&#xD;&#xA;    let cameraRotationMatrixLocation: WebGLUniformLocation = this.currentContext.getUniformLocation(this.currentProgram, &quot;u_cameraRotation&quot;);&#xD;&#xA;    let cameraTranslationLocation: WebGLUniformLocation = this.currentContext.getUniformLocation(this.currentProgram, &quot;u_cameraTranslation&quot;);&#xD;&#xA;    let foVLocation: WebGLUniformLocation = this.currentContext.getUniformLocation(this.currentProgram, &quot;u_foV&quot;);&#xD;&#xA;&#xD;&#xA;    //add point of camera rotation at beginning&#xD;&#xA;    let cameraRotationMatrix: Array&lt;number&gt; = Matrix3D.identity();&#xD;&#xA;&#xD;&#xA;    //set camera rotation and translation, Z-axis (heading) first, then X-axis (pitch), then Y-axis (roll)&#xD;&#xA;    cameraRotationMatrix = Matrix3D.multiply(cameraRotationMatrix, Matrix3D.rotateZ(this.cameraRotateZ * Math.PI / 180));&#xD;&#xA;    cameraRotationMatrix = Matrix3D.multiply(cameraRotationMatrix, Matrix3D.rotateX(this.cameraRotateX * Math.PI / 180));&#xD;&#xA;    cameraRotationMatrix = Matrix3D.multiply(cameraRotationMatrix, Matrix3D.rotateY(this.cameraRotateY * Math.PI / 180));&#xD;&#xA;    //cameraRotationMatrix = Matrix3D.multiply(cameraRotationMatrix, Matrix3D.translate(this.cameraTranslateX, this.cameraTranslateY, this.cameraTranslateZ));&#xD;&#xA;    cameraRotationMatrix = Matrix3D.inverse(cameraRotationMatrix);&#xD;&#xA;&#xD;&#xA;    let cameraPosition: Array&lt;number&gt; = [&#xD;&#xA;      this.cameraTranslateX,&#xD;&#xA;      this.cameraTranslateY,&#xD;&#xA;      -this.cameraTranslateZ,&#xD;&#xA;    ];&#xD;&#xA;&#xD;&#xA;    this.currentContext.uniformMatrix4fv(cameraRotationMatrixLocation, false, cameraRotationMatrix);&#xD;&#xA;    this.currentContext.uniform3fv(cameraTranslationLocation, cameraPosition);&#xD;&#xA;    this.currentContext.uniform1f(foVLocation, this.foV);&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;I tried adding the camera translation values to the camera matrix but that didn't work. I got weird distortion effects and couldn't get it right so I commented that line out and left it there for now for clarity. The reason I did it this way is because of the way my GLSL code is constructed:&#xD;&#xA;&#xD;&#xA;The main function from the fragment shader with the call to the ray_march function. `v_position` is a vec2 with x,y coordinates coming from the vertex shader.:&#xD;&#xA;```&#xD;&#xA;    void main() {&#xD;&#xA;      outColor = vec4(ray_march(u_cameraTranslation, u_cameraRotation * vec4(rayDirection(u_foV,v_position),1), u_world, vec3(u_light * vec4(0,0,0,1)).xyz ).xyz,1);&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The ray_march function I am using. This derives from the sample code in Michael Walczyk's blog.&#xD;&#xA;```&#xD;&#xA;    vec3 ray_march(in vec3 ro, in vec4 rd, in mat4 wm, in vec3 lightPosition) //ro = ray origin, rd = ray direction gt = geometry position after matrix multiplication&#xD;&#xA;    {&#xD;&#xA;        float total_distance_traveled = 0.0;&#xD;&#xA;        const int NUMBER_OF_STEPS = 1024;&#xD;&#xA;&#xD;&#xA;        float MINIMUM_HIT_DISTANCE = 0.001 * min_hit_distance_correction;&#xD;&#xA;&#xD;&#xA;        const float MAXIMUM_TRACE_DISTANCE = 1000.0;&#xD;&#xA;&#xD;&#xA;        for (int i = 0; i &lt; NUMBER_OF_STEPS; i++)&#xD;&#xA;        {&#xD;&#xA;            vec3 current_position = ro + total_distance_traveled * vec3(rd);&#xD;&#xA;&#xD;&#xA;            float distance_to_closest = map(current_position, wm);&#xD;&#xA;&#xD;&#xA;            if (distance_to_closest &lt; MINIMUM_HIT_DISTANCE) &#xD;&#xA;            {&#xD;&#xA;              vec3 normal = calculate_normal(current_position, wm);&#xD;&#xA;              vec3 outColor = vec3(1.0,0,0);&#xD;&#xA;              vec3 v_surfaceToLight = lightPosition - current_position;&#xD;&#xA;              vec3 v_surfaceToView = ro - current_position;&#xD;&#xA;&#xD;&#xA;              //insert lighting code below this line&#xD;&#xA;&#xD;&#xA;              return outColor;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            if (total_distance_traveled &gt; MAXIMUM_TRACE_DISTANCE)&#xD;&#xA;            {&#xD;&#xA;              break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            total_distance_traveled += distance_to_closest;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        return vec3(0.25);//gray background&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The rayDirection function I am using.&#xD;&#xA;```&#xD;&#xA;  vec3 rayDirection(float fieldOfView, vec2 p) {&#xD;&#xA;    float z = 1.0 / (tan(radians(fieldOfView) / 2.0));&#xD;&#xA;    return normalize(vec3(p.xy, -z));&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;# My problem #&#xD;&#xA;I have issues moving and rotating my camera correctly in 3d world. I'm doing this by applying some trigonometry to get the movement right. E.g., when I move forward, that is the Z-axis. But when I make a 90 degree turn to the right the X-axis now becomes the Z-axis. I am using trigonometry to correct this and actually got something working but now I am stuck in a quagmire of trigonometry trying to get 'roll', rotation around the Z-axis working when being combined with rotations around the X and Z axis, with no end in sight and I have a feeling there must be a better and less complicated way. To see what I'm talking about, here is the code of the 'move' function:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;  move(event: KeyboardEvent): void {&#xD;&#xA;    &#xD;&#xA;    //strafe forward-back&#xD;&#xA;    let tXForwardBack: number = (Math.sin(this.cameraRotateY * Math.PI / 180) * Math.cos(this.cameraRotateX * Math.PI / 180)) * this.clipSpaceFactor * this.speed;&#xD;&#xA;    let tYForwardBack: number = Math.sin(this.cameraRotateX * Math.PI / 180) * this.speed;&#xD;&#xA;    let tZForwardBack: number = (Math.cos(this.cameraRotateY * Math.PI / 180) * Math.cos(this.cameraRotateX * Math.PI / 180)) * this.clipSpaceFactor * this.speed;&#xD;&#xA;&#xD;&#xA;    //strafe up-down&#xD;&#xA;    let tXUpDown: number = ((Math.sin(this.cameraRotateX * Math.PI / 180) * Math.sin(this.cameraRotateY * Math.PI / 180)) * this.clipSpaceFactor * this.speed);&#xD;&#xA;    let tYUpDown: number = Math.cos(this.cameraRotateX * Math.PI / 180) * this.speed;&#xD;&#xA;    let tZUpDown: number = Math.sin(this.cameraRotateX * Math.PI / 180) * Math.cos(this.cameraRotateY * Math.PI / 180) * this.clipSpaceFactor * this.speed;&#xD;&#xA;&#xD;&#xA;    //strafe left-right without roll. TODO: implement roll&#xD;&#xA;    let tXLeftRight: number = Math.cos(this.cameraRotateY * Math.PI / 180) * this.clipSpaceFactor * this.speed;&#xD;&#xA;    let tYLeftRight: number = 0;&#xD;&#xA;    let tZLeftRight: number = Math.sin(this.cameraRotateY * Math.PI / 180) * this.clipSpaceFactor * this.speed;&#xD;&#xA;&#xD;&#xA;    switch (event.key) {&#xD;&#xA;      case &quot;w&quot;: { //strafe forward&#xD;&#xA;        this.cameraTranslateX = this.cameraTranslateX + tXForwardBack;&#xD;&#xA;        this.cameraTranslateY = this.cameraTranslateY - tYForwardBack;&#xD;&#xA;        this.cameraTranslateZ = this.cameraTranslateZ + tZForwardBack;&#xD;&#xA;        //this.cameraTranslateZ = this.cameraTranslateZ + (this.clipSpaceFactor * this.speed);&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;s&quot;: { //strafe back&#xD;&#xA;        this.cameraTranslateX = this.cameraTranslateX - tXForwardBack;&#xD;&#xA;        this.cameraTranslateY = this.cameraTranslateY + tYForwardBack;&#xD;&#xA;        this.cameraTranslateZ = this.cameraTranslateZ - tZForwardBack;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;a&quot;: {//strafe left&#xD;&#xA;        this.cameraTranslateX = this.cameraTranslateX - tXLeftRight;&#xD;&#xA;        this.cameraTranslateY = this.cameraTranslateY + tYLeftRight;&#xD;&#xA;        this.cameraTranslateZ = this.cameraTranslateZ + tZLeftRight;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;d&quot;: { //strafe right&#xD;&#xA;        this.cameraTranslateX = this.cameraTranslateX + tXLeftRight;&#xD;&#xA;        this.cameraTranslateY = this.cameraTranslateY - tYLeftRight;&#xD;&#xA;        this.cameraTranslateZ = this.cameraTranslateZ - tZLeftRight;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;q&quot;: { //strafe up&#xD;&#xA;        this.cameraTranslateX = this.cameraTranslateX + tXUpDown;&#xD;&#xA;        this.cameraTranslateY = this.cameraTranslateY + tYUpDown;&#xD;&#xA;        this.cameraTranslateZ = this.cameraTranslateZ + tZUpDown;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;e&quot;: { //strafe down&#xD;&#xA;        this.cameraTranslateX = this.cameraTranslateX - tXUpDown;&#xD;&#xA;        this.cameraTranslateY = this.cameraTranslateY - tYUpDown;&#xD;&#xA;        this.cameraTranslateZ = this.cameraTranslateZ - tZUpDown;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;z&quot;: { //roll left&#xD;&#xA;        this.cameraRotateZ = (this.cameraRotateZ + (this.sensitivity * this.speed)) % 360;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;      case &quot;c&quot;: { //roll right&#xD;&#xA;        this.cameraRotateZ = (this.cameraRotateZ - (this.sensitivity * this.speed)) % 360;&#xD;&#xA;        break;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;It actually works to some degree, but you can see where this is going :( Also, I get a 'dead' zone in the center when I look up and down along the Y-axis. I found [This thread][2] which seems to describe my problem and says 'The trick is to apply the translation to the z-axis but in the local coordinate system of the camera.'&#xD;&#xA;&#xD;&#xA;But how do I do that with my existing code? I tried multiplying the world matrix `u_world` by the rotationmatrix `u_rotationMatrix` but then the lighting changes as well and it's just an object rotation instead of a separate camera rotation. In the thread I posted there is no lighting so multiplying the camera matrix with the world matrix works for them. But it doesn't for me because of the lighting I implemented. Also, I can't seem to apply the normals separately this way so that I only apply the normals to the world matrix and not to the camera rotation matrix, so that the lighting stays in place when I rotate/translate the camera.&#xD;&#xA;&#xD;&#xA;The only way I can get correct normals to the world matrix and a separate cameramatrix is by multiplying the rotationMatrix with the rayDirection like so `u_cameraRotation * vec4(rayDirection(u_foV,v_position),1)`. But when I do this I have to apply all this horrible, partially working trigonometry mess to get something decent. What I want is getting it to work like 'The trick is to apply the translation to the z-axis but in the local coordinate system of the camera.'&#xD;&#xA;&#xD;&#xA;But I don't know how. I tried all kinds of things but I'm currently stuck. Any help would be greatly appreciated. I think I've outlined my problem sufficiently enough, if you miss anything please let me know. I posted my question on StackOverflow earlier but I was told this was a more appropriate place. Thanks in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://michaelwalczyk.com/blog-ray-marching.html&#xD;&#xA;  [2]: https://stackoverflow.com/questions/60561455/how-do-i-rotate-my-camera-correctly-in-my-3d-world" ContentLicense="CC BY-SA 4.0" />
  <row Id="35152" PostHistoryTypeId="1" PostId="12269" RevisionGUID="84059f70-f65e-4b61-a434-7790d5df99bf" CreationDate="2021-10-22T21:45:12.763" UserId="17397" Text="Is there a better, more elegant way of translating/rotating my camera in my 3d raymarched world or am I stuck with trigonometry?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35153" PostHistoryTypeId="3" PostId="12269" RevisionGUID="84059f70-f65e-4b61-a434-7790d5df99bf" CreationDate="2021-10-22T21:45:12.763" UserId="17397" Text="|glsl|webgl|camera-matrix|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35155" PostHistoryTypeId="2" PostId="12270" RevisionGUID="483938bc-5dfc-4762-ab8a-c36bddb18a93" CreationDate="2021-10-23T02:26:41.197" UserId="3073" Text="A reliable way of getting the forward/left directions relative to the view is to use the camera rotation matrix itself to produce forward, Up and right vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // The sign of the vector depends on your coordinate system (e.g. UP may be 0,0,-1 for you)&#xD;&#xA;    &#xD;&#xA;    vec3 forward = rotMatrix * vec3(0,0,1);&#xD;&#xA;    vec3 up = rotMatrix * vec3(0,1,0);&#xD;&#xA;    vec3 right = rotMatrix * vec3(1,0,0);&#xD;&#xA;    &#xD;&#xA;    With those vectors you can plug them into your movement code&#xD;&#xA;    &#xD;&#xA;    e.g.&#xD;&#xA;    &#xD;&#xA;    if(keyDown(W)) cameraPos += forward;&#xD;&#xA;    if(keyDown(S)) cameraPos -= forward;&#xD;&#xA;    if(keyDown(D)) cameraPos += right;&#xD;&#xA;    ...&#xD;&#xA;    etc&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Because this is using the rotation matrix it doesn't matter if your rotation matrix was built from Euler angles, quaternions, etc.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35157" PostHistoryTypeId="2" PostId="12271" RevisionGUID="958dd27b-cfcb-402d-a551-aa69fccad347" CreationDate="2021-10-23T03:38:23.547" UserId="48" Text="The termination condition is that the ray passes through the surface represented in the depth buffer. To track this, you have to calculate the z position of the ray at the current step, and compare it to the value sampled from the depth buffer at the ray's current screen-space position. In terms of your code, this would be something like `RaySample.z &gt; ZBufferVal` (assuming that your Z is increasing with distance from the camera)." ContentLicense="CC BY-SA 4.0" />
  <row Id="35159" PostHistoryTypeId="5" PostId="12271" RevisionGUID="024d4329-0151-4390-9b62-7f74e493ff58" CreationDate="2021-10-23T03:55:09.610" UserId="48" Comment="added 346 characters in body" Text="The termination condition is that the ray passes through the surface represented in the depth buffer. To track this, you have to calculate the z position of the ray at the current step, and compare it to the value sampled from the depth buffer at the ray's current screen-space position. In terms of your code, this would be something like `RaySample.z &gt; ZBufferVal` (assuming that your Z is increasing with distance from the camera).&#xD;&#xA;&#xD;&#xA;To make it a bit fancier and more accurate, you could also interpolate the position over the last two steps: the second to last step is known to be in front of the depth buffer, and the last step is known to be behind it, so you could calculate the intersection point of the ray approximating the depth as linear between those last two steps." ContentLicense="CC BY-SA 4.0" />
  <row Id="35160" PostHistoryTypeId="50" PostId="10263" RevisionGUID="dc00c44b-f263-4901-ae17-f265bdef021a" CreationDate="2021-10-23T11:07:20.663" UserId="-1" />
  <row Id="35162" PostHistoryTypeId="2" PostId="12272" RevisionGUID="3b363f12-aa00-4188-9c31-ed93181942ca" CreationDate="2021-10-23T16:32:29.257" UserDisplayName="user17337" Text="We know that in orthographic Projection Projectors (projection vectors) are perpendicular to the projection plane.&#xD;&#xA;&#xD;&#xA;And in Perspective Projection Object positions are transformed to the view plane along lines that converge to the projection reference (center) point.&#xD;&#xA;&#xD;&#xA;The Point $(x,y,z)$ is projected to position $(x_p,y_p,z_{vp})$ on the view plane.Since the view plane is placed at position $z_{vp}$ along the &#xD;&#xA;$z_v$ axis. &#xD;&#xA;&#xD;&#xA;Then in parallel projection any point $(x,y,z)$ in viewing coordinates &#xD;&#xA;is transformed to projection coordinates as:&#xD;&#xA;    $x_p=x,$$y_p=y$ and $z_{vp}=0.$&#xD;&#xA;&#xD;&#xA;My question is why $(x,y,z)$ is projected to $(x_p,y_p)$, why not $(x_p,y_p,z_{vp})?$ I mean why $z_{vp}=0.$ And another question in perspective projection a why  $(x,y,z)$ is projected to $(x_p,y_p,z_{vp})?$&#xD;&#xA;&#xD;&#xA;My final question is that in perspective projection projectors are perpendicular to the viewing plane? &#xD;&#xA;&#xD;&#xA;N. B. - [Reference](https://drive.google.com/file/d/1DO2pwP8u6GPs6pjnOg0q19JMr6k8dIhr/view?usp=drivesdk) " ContentLicense="CC BY-SA 4.0" />
  <row Id="35164" PostHistoryTypeId="1" PostId="12272" RevisionGUID="3b363f12-aa00-4188-9c31-ed93181942ca" CreationDate="2021-10-23T16:32:29.257" UserDisplayName="user17337" Text="Difference between perspective and parallel projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="35165" PostHistoryTypeId="3" PostId="12272" RevisionGUID="3b363f12-aa00-4188-9c31-ed93181942ca" CreationDate="2021-10-23T16:32:29.257" UserDisplayName="user17337" Text="|3d|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35166" PostHistoryTypeId="5" PostId="12272" RevisionGUID="31c0b6f6-026c-457e-8269-c8d39e50e66a" CreationDate="2021-10-23T19:25:04.820" UserDisplayName="user17337" Comment="added 68 characters in body" Text="We know that in orthographic Projection Projectors (projection vectors) are perpendicular to the projection plane.&#xD;&#xA;&#xD;&#xA;And in Perspective Projection Object positions are transformed to the view plane along lines that converge to the projection reference (center) point.&#xD;&#xA;&#xD;&#xA;The Point $(x,y,z)$ is projected to position $(x_p,y_p,z_{vp})$ on the view plane.Since the view plane is placed at position $z_{vp}$ along the &#xD;&#xA;$z_v$ axis. &#xD;&#xA;&#xD;&#xA;Then in parallel projection any point $(x,y,z)$ in viewing coordinates &#xD;&#xA;is transformed to projection coordinates as:&#xD;&#xA;    $x_p=x,$$y_p=y$ and $z_{vp}=0.$&#xD;&#xA;&#xD;&#xA;My question is why $(x,y,z)$ is projected to $(x_p,y_p)$, why not $(x_p,y_p,z_{vp}),$ I mean view plane is placed at position $z_{vp}$ ,so why $z_{vp}=0$ in $(x_p,y_p,z_{vp})?$ And another question in perspective projection a why  $(x,y,z)$ is projected to $(x_p,y_p,z_{vp})?$&#xD;&#xA;&#xD;&#xA;My final question is that in perspective projection projectors are perpendicular to the viewing plane? &#xD;&#xA;&#xD;&#xA;N. B. - [Reference](https://drive.google.com/file/d/1DO2pwP8u6GPs6pjnOg0q19JMr6k8dIhr/view?usp=drivesdk) " ContentLicense="CC BY-SA 4.0" />
  <row Id="35167" PostHistoryTypeId="2" PostId="12273" RevisionGUID="c2dfb125-5ee5-4c9d-943e-b0c08d810a4f" CreationDate="2021-10-24T15:31:30.870" UserId="17408" Text="I am trying to understand exactly what is happening when Gimbal lock occurs. I have read many explanations now which provide the high-level idea, in that Gimbal lock occurs when two axes are aligned during the sequence of three rotations. But I am struggling to understand what this really means in terms of the calculations that are going on.&#xD;&#xA;&#xD;&#xA;Here's my understanding of the setup. We have an initial 3D rotation of a body, and a target 3D rotation of that body, and we want to move the body from the initial to the target rotation. To do this, we calculate the Euler angles representing this rotation. (I don't know the maths behind this, but I will assume that this is just an algorithm that takes in an initial and target rotation, and returns a third rotation).&#xD;&#xA;&#xD;&#xA;So, we now have a rotation expressed as Euler angles, which we want the body to move over. And now I will explain my confusion. From what I have been reading, there are two ideas:&#xD;&#xA;&#xD;&#xA;1. Gimbal lock occurs when two of the axes become aligned, during the sequence of three rotations, which means that there is one axis about which rotation cannot occur.&#xD;&#xA;2. Due to Gimbal lock, the path which the rotation occurs over will not be &quot;straight&quot;, and there will be a curve.&#xD;&#xA;&#xD;&#xA;This to me is very confusing. 1) is saying that Gimbal lock means that we cannot rotate the body along a certain axis. 2) is saying that Gimbal lock means that we can rotate the body, but that the path will not be &quot;straight&quot;.&#xD;&#xA;&#xD;&#xA;Please can somebody explain which one is correct, and help me to overcome this confusion? Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="35169" PostHistoryTypeId="1" PostId="12273" RevisionGUID="c2dfb125-5ee5-4c9d-943e-b0c08d810a4f" CreationDate="2021-10-24T15:31:30.870" UserId="17408" Text="Gimbal lock confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="35170" PostHistoryTypeId="3" PostId="12273" RevisionGUID="c2dfb125-5ee5-4c9d-943e-b0c08d810a4f" CreationDate="2021-10-24T15:31:30.870" UserId="17408" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35171" PostHistoryTypeId="2" PostId="12274" RevisionGUID="9414b182-7d60-4230-9d1f-ba561f21977d" CreationDate="2021-10-24T21:20:52.330" UserId="48" Text="Gimbal lock is your item 1. It is the situation where we have rotated our 2nd axis (in the order of application of the three axes) by ±90 degrees, which aligns the 1st axis and the 3rd axis together, so that rotating either one of them does the same thing. From that position, there are some directions we cannot rotate in.&#xD;&#xA;&#xD;&#xA;For a concrete example, let's say we apply rotations in the order of roll, pitch, yaw. If I have pitched up by 90 degrees, so that my aircraft (or whatever) is pointing straight up, then rolling will rotate about the global vertical axis (because I'm pitched straight up), and yawing will also rotate around the global vertical axis (as it always does). From this position I am able to roll and pitch, but what I _can't_ do is tilt the aircraft to its local left or right. I would have to pitch away from that 90 degree position by some distance, and then &quot;circle around&quot; so to speak in order to get to the left- or right-tilted position.&#xD;&#xA;&#xD;&#xA;Item 2 isn't the same thing as gimbal lock, but is affected by it. It is a property of interpolating in Euler angles in general. If you move from your initial to your target rotation by, say, linearly interpolating each of the three Euler angles individually from its initial value to its target value, then in general the path taken will not be the shortest path through the space of rotations to the target—and it may look odd to the eye, perhaps appearing to rotate in the &quot;wrong&quot; direction at first and then circle around to come at the desired target orientation from a different angle.&#xD;&#xA;&#xD;&#xA;This happens to some extent for almost any choice of initial and target orientations, but it gets worse if the path taken approaches close to a gimbal lock configuration. This can happen if the initial or target orientation is a gimbal lock configuration, or if we happen to pass through a gimbal lock configuration (or close to it) in the middle of the interpolation. When that happens, we will get particularly strange-looking &quot;wrong&quot; rotation paths. If we don't happen to get near a gimbal lock configuration, then the &quot;wrongness&quot; won't be so clearly visible, or may go unnoticed entirely." ContentLicense="CC BY-SA 4.0" />
  <row Id="35173" PostHistoryTypeId="5" PostId="12274" RevisionGUID="d97b4633-8a09-4abb-94dd-52457d6efe54" CreationDate="2021-10-24T21:28:13.243" UserId="48" Comment="add analogy to spherical coordinates" Text="Gimbal lock is your item 1. It is the situation where we have rotated our 2nd axis (in the order of application of the three axes) by ±90 degrees, which aligns the 1st axis and the 3rd axis together, so that rotating either one of them does the same thing. From that position, there are some directions we cannot rotate in.&#xD;&#xA;&#xD;&#xA;For a concrete example, let's say we apply rotations in the order of roll, pitch, yaw. If I have pitched up by 90 degrees, so that my aircraft (or whatever) is pointing straight up, then rolling will rotate about the global vertical axis (because I'm pitched straight up), and yawing will also rotate around the global vertical axis (as it always does). From this position I am able to roll and pitch, but what I _can't_ do is tilt the aircraft to its local left or right. I would have to pitch away from that 90 degree position by some distance, and then &quot;circle around&quot; so to speak in order to get to the left- or right-tilted position. (This is the situation represented in the .gif that lightxbulb posted.)&#xD;&#xA;&#xD;&#xA;Item 2 isn't the same thing as gimbal lock, but is affected by it. It is a property of interpolating in Euler angles in general. If you move from your initial to your target rotation by, say, linearly interpolating each of the three Euler angles individually from its initial value to its target value, then in general the path taken will not be the shortest path through the space of rotations to the target—and it may look odd to the eye, perhaps appearing to rotate in the &quot;wrong&quot; direction at first and then circle around to come at the desired target orientation from a different angle.&#xD;&#xA;&#xD;&#xA;This happens to some extent for almost any choice of initial and target orientations, but it gets worse if the path taken approaches close to a gimbal lock configuration. This can happen if the initial or target orientation is a gimbal lock configuration, or if we happen to pass through a gimbal lock configuration (or close to it) in the middle of the interpolation. When that happens, we will get particularly strange-looking &quot;wrong&quot; rotation paths. If we don't happen to get near a gimbal lock configuration, then the &quot;wrongness&quot; won't be so clearly visible, or may go unnoticed entirely.&#xD;&#xA;&#xD;&#xA;An analogy that may help is to think about the Earth's surface with latitude and longitude coordinates, and what happens if you generate a path between two points on Earth by interpolating the latitude and longitude individually. You can see that things may get weird if the path gets close to the poles, where the coordinate system has a singularity. That is very analogous to how gimbal lock configurations are singularities in the Euler angle coordinate system. These singularities can be resolved by using quaternions, which would be analogous to representing points on the Earth's surface using Cartesian xyz vectors instead of latitude/longitude." ContentLicense="CC BY-SA 4.0" />
  <row Id="35175" PostHistoryTypeId="52" PostId="12273" RevisionGUID="90d0cccb-6f1e-449f-9edd-5af262b87b50" CreationDate="2021-10-25T06:42:07.703" />
  <row Id="35176" PostHistoryTypeId="5" PostId="4438" RevisionGUID="e390257c-bf38-4443-80ee-8459a1c3708f" CreationDate="2021-10-25T07:45:46.210" UserId="38" Comment="edited body" Text="A `gimbal` is a pivoted support that allows you to rotate around one axis. Now it so happens that Euler rotations\* work like a set of 3 gimbals attached to each other, one rotation builds upon the next (or previous/whole stack if your inclined to model it that way). &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Image 1**: Rotation is like a gimbal. [Model](http://tf3dm.com/3d-model/fa-22-raptor-86148.html) using *yxz* rotation (z=blue, x= red and y=green) in a physical 3 axis gimbal structure. &#xD;&#xA;&#xD;&#xA;A `gimbal lock` happens when you turn 2 or 3 of the successive gimbals and they align onto a plane. You succeed in erasing one direction since the angles both operate same same direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Image 2**: Rotation direction lost because 2 of the rotations overlap.&#xD;&#xA;&#xD;&#xA;The only way out is to unwind the structure. Although this is the lock, problems due to diminishing possibilities to turn start earlier than the lock itself.&#xD;&#xA;&#xD;&#xA;### A more in depth look at things&#xD;&#xA;&#xD;&#xA;Now this is where most people stop thinking about the issue and move on with their life. They just conclude that Euler angles are somehow broken. This is also where a lot of misunderstandings happen so it's worth investigating the matter slightly further than what causes gimbal lock.&#xD;&#xA;&#xD;&#xA;It is important to understand that this is *only* problematic if you `interpolate` in Euler angles\*\*! In a real physical gimbal this is given - you have no other choice. In computer graphics you have many other choices, from normalized matrix, axis angle or quaternion interpolation. Gimbal lock has a much more dramatic implication to designing control systems than it has to 3d graphics. Which is why a mechanical engineer for example will have a very different take on gimbal locking. &#xD;&#xA;&#xD;&#xA;You don't have to give up using Euler angles to get rid of gimbal locking, just stop interpolating values in Euler angles. Of course, this means that you can now no longer drive a rotation by doing direct manipulation of one of the channels. But as long as you key the 3 angles simultaneously you have no problems and you can internally convert your interpolation target to something that has less problems.&#xD;&#xA;&#xD;&#xA;Using Euler angles is just simply more intuitive to think in most cases. And indeed Euler never claimed it was good for interpolating but just that it can model all possible space orientations. So Euler angles are just fine for setting orientations like they were meant to do. Also incidentally Euler angles have the benefit of being able to model multi turn rotations which will not happen sanely for the other representations.&#xD;&#xA;&#xD;&#xA;### Problems and how to circumvent them&#xD;&#xA;&#xD;&#xA;The fact of the matter is that interpolating in Euler angle space is a bad idea, in general and affects you way before you come close to a true gimbal lock. For this reason NASA lunar orbiter would warn of gimbal lock when you come close to a 70-80 degree angle on a single gimbal's turn. So be aware that people do not necessarily talk of just the actual locking condition when they talk of a gimbal lock. Even worse some people blame all their rotation problems on gimbal locking.&#xD;&#xA;&#xD;&#xA;Euler rotation is only safe if you rotate primarily one angle and shallow amounts on the other 2 rotations, which is quite common admittedly. This works fine for describing movement of a commercial airliner, a car etc. But not so well for a jet fighter or an acrobatics plane doing complex air maneuvers. What happens is the rotations start to interfere with each other and you get a weird wobble instead of moving straight from one position to the next.&#xD;&#xA;&#xD;&#xA;To fix the wobble problem in shallow cases just swap the rotation order so that the big rotation gets applied on the other rotations. If you need to use more complex rotations then either switch over to other interpolation methods or add even more rotation links to your gimbal (which is a good stopgap measure for cases where you cannot do the switch in a timely manner).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;\* To be exact most of the time people do not actually use Euler angles but Tait–Bryan angles. Which are nearly the same thing only Euler insisted on repeating the same axis, not very important distinction but good to know if you ever speak to an academic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\*\* Oh well, if you use Euler–Lagrange equation it won't matter.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9Bkct.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/1pCtJ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35177" PostHistoryTypeId="2" PostId="12275" RevisionGUID="7e4d529f-9da7-4fe4-8ea8-20dda672afe7" CreationDate="2021-10-25T08:06:35.887" UserId="10096" Text="Maybe it's also worth considering why people find gimbal lock &quot;wrong&quot; even when they do not know what gimbal lock is. This suggests some intuitive expectation that doesn't align with what Euler angles do (i.e. they actually do not want to work with gimbals). It begs the question how this natural expectation may be fulfilled instead.&#xD;&#xA;&#xD;&#xA;Assume you are given a joystick to control an airplane's orientation (you are in the airplane), but make it special so that the stick can also be rotated around its axis to achieve a yaw rotation. Store the set of orthonormal vectors describing the orientation of the plane $e_1,e_2,e_3$ and identify the stick's current direction with $e_2$. Now let the airplane's computer record the airplane's basis $e_1, e_2, e_3$, and the stick's direction $d$, every $x$ seconds and keep its last two states: previous $p$ and current $c$. Assume you have tilted the stick from $e_2$ in $p$ to $e'_2$ in $c$. Intuitively one wants to align the plane so that $e'_2$ is the plane's &quot;up&quot; again. This can be done by rotating the previous basis $e_1, e_2, e_3$ along the shortest path as to align $e_2$ to $e'_2$. This can be achieved using the following formula: &#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$&#xD;&#xA;and the vectors have to be further normalized. This yields a new basis $e'_1, e'_2, e'_3$ that you align your airplane to. This has a singularity if you allow your joystick a range of motion of 180 degrees, since if in $c$ you recorded $e'_2 = -e_2$ it is not clear along which rotation you reached it (all rotations are equal then: 180 degrees around any axis perpendicular to $e_2$, and there are infinitely many such axes). A solution is to either disallow 180 degrees tilts (which holds for actual joysticks), poll your joystick state more often than every $x$ seconds so it would be physically impossible to flip it by 180 degrees between polling in $p$ and $c$, or set a &quot;default&quot; flip rotation, e.g. $e'_1 = e_1, e'_2 = -e_2, e'_3 = -e_3$ which rotates around $e_1$ whenever $e'_2 = -e_2$ in $c$ (your airplane becomes reversed, but any other axis perpendicular to $e_2$ would work). Now what should be done about the yaw rotation induced by the rotation of the stick around its axis? One option is to rotate around $e'_2$. Note that the above combination of operations do not lead to gimbal lock ever, since it's not a gimbal configuration of rotations in the first place. In all states you get the exact same &quot;intuitive&quot; behaviour.&#xD;&#xA;&#xD;&#xA;Note that one could have chosen a different vector $d$ instead of $e_2$ to correspond to the joystick's direction and the idea remains the same. The point is that the two rotations - one induced from the tilting of $d$, and one induced from the rotation of $d$ around its axis, are different in behaviour, but at least for flight sims/joystick that seems to be the intuitive expected behaviour. You can achieve the same thing by using a keyboard too, e.g. up/down corresponds to tilting the stick forward/backward, left/right = tilting left/right, some other two keys for the clockwise and counter-clockwise rotation around its axis.&#xD;&#xA;&#xD;&#xA;Now forget the airplane and joystick setting, and assume you were given an actual physical gimbal with 3 rotation axes as a controller. In that scenario it is likely that you would not find the joystick behaviour intuitive but the gimbal one, in which case it would make sense to use Euler angles. The point is that the gimbal lock by itself isn't the issue, it's the mismatch between expectations and how a system operates. That is, if I give you a joystick controller and it acts like a gimbal virtually (i.e. I use Euler angles), or if I give you a gimbal controller and it acts like a joystick (i.e. I use the shortest rotation described for the joystick), you will likely find both confusing. All in all, I would say this issue arises simply because people apply the wrong mathematics to model their problem: wrong in the sense that they do not match their expectations." ContentLicense="CC BY-SA 4.0" />
  <row Id="35179" PostHistoryTypeId="5" PostId="12275" RevisionGUID="9fb3ccf0-ac49-4893-b3db-c5f1def5ded5" CreationDate="2021-10-25T08:20:49.360" UserId="10096" Comment="added 117 characters in body" Text="Maybe it's also worth considering why people find gimbal lock &quot;wrong&quot; even when they do not know what gimbal lock is. This suggests some intuitive expectation that doesn't align with what Euler angles do (i.e. they actually do not want to work with gimbals). It begs the question how this natural expectation may be fulfilled instead.&#xD;&#xA;&#xD;&#xA;Assume you are given a joystick to control an airplane's orientation (you are in the airplane), but make it special so that the stick can also be rotated around its axis to achieve a yaw rotation. Store the set of orthonormal vectors describing the orientation of the plane $e_1,e_2,e_3$ and identify the stick's current direction with $e_2$. Now let the airplane's computer record the airplane's basis $e_1, e_2, e_3$, and the stick's direction $d$, every $x$ seconds and keep its last two states: previous $p$ and current $c$. Assume you have tilted the stick from $e_2$ in $p$ to $e'_2$ in $c$. Intuitively one wants to align the plane so that $e'_2$ is the plane's &quot;up&quot; again. This can be done by rotating the previous basis $e_1, e_2, e_3$ along the shortest path as to align $e_2$ to $e'_2$. This can be achieved using the following formula: &#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$&#xD;&#xA;and the vectors have to be further normalized. This yields a new basis $e'_1, e'_2, e'_3$ that you align your airplane to. This has a singularity if you allow your joystick a range of motion of 180 degrees, since if in $c$ you recorded $e'_2 = -e_2$ it is not clear along which rotation you reached it (all rotations are equal then: 180 degrees around any axis perpendicular to $e_2$, and there are infinitely many such axes). A solution is to either disallow 180 degrees tilts (which holds for actual joysticks), poll your joystick state more often than every $x$ seconds so it would be physically impossible to flip it by 180 degrees between polling in $p$ and $c$, or set a &quot;default&quot; flip rotation, e.g. $e'_1 = e_1, e'_2 = -e_2, e'_3 = -e_3$ which rotates around $e_1$ whenever $e'_2 = -e_2$ in $c$ (your airplane becomes reversed, but any other axis perpendicular to $e_2$ would work). Now what should be done about the yaw rotation induced by the rotation of the stick around its axis? One option is to rotate around $e'_2$. Note that the above combination of operations do not lead to gimbal lock ever, since it's not a gimbal configuration of rotations in the first place. In all states you get the exact same &quot;intuitive&quot; behaviour.&#xD;&#xA;&#xD;&#xA;Note that one could have chosen a different vector $d$ instead of $e_2$ to correspond to the joystick's direction and the idea remains the same. The point is that the two rotations - one induced from the tilting of $d$, and one induced from the rotation of $d$ around its axis, are different in behaviour, but at least for flight sims/joystick that seems to be the intuitive expected behaviour. You can achieve the same thing by using a keyboard too, e.g. up/down corresponds to tilting the stick forward/backward, left/right = tilting left/right, some other two keys for the clockwise and counter-clockwise rotation around its axis.&#xD;&#xA;&#xD;&#xA;Now forget the airplane and joystick setting, and assume you were given an actual physical 3-gimbal as a controller. In that scenario it is likely that you would not find the joystick behaviour intuitive but the 3-gimbal one, in which case it would make sense to use Euler angles. The point is that the gimbal lock by itself isn't the issue, it's the mismatch between expectations and how a system operates. That is, if I give you a joystick controller and it acts like a 3-gimbal virtually (i.e. I use Euler angles), or if I give you a 3-gimbal controller and it acts like a joystick (i.e. I use the shortest rotation described for the joystick), you will likely find both confusing. All in all, I would say this issue arises simply because people apply the wrong mathematical model to what they envision, i.e. it doesn't model their expectations but something else instead. Speaking of which, I haven't seen any 3-gimbal PC controllers. Using those Euler angles ought to make perfect sense." ContentLicense="CC BY-SA 4.0" />
  <row Id="35180" PostHistoryTypeId="2" PostId="12276" RevisionGUID="fdbe2ccb-eed0-403a-9dc0-649c6f8f4a8e" CreationDate="2021-10-25T09:00:40.943" UserDisplayName="user17337" Text="We know that shear is transformation that distorts the shape of the object. Shear relative to X-axis that is $y=0$ line can be written as:&#xD;&#xA;$x'=x+sh_x.y, y'=y$&#xD;&#xA;My question is why $sh_x$ is multiplying by $y,$why not any other constant ?  I want to understand intuition behind this. Every book, website don't mention any reason. " ContentLicense="CC BY-SA 4.0" />
  <row Id="35182" PostHistoryTypeId="1" PostId="12276" RevisionGUID="fdbe2ccb-eed0-403a-9dc0-649c6f8f4a8e" CreationDate="2021-10-25T09:00:40.943" UserDisplayName="user17337" Text="Why shearing concepts multiplying by y?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35183" PostHistoryTypeId="3" PostId="12276" RevisionGUID="fdbe2ccb-eed0-403a-9dc0-649c6f8f4a8e" CreationDate="2021-10-25T09:00:40.943" UserDisplayName="user17337" Text="|transformations|projections|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35184" PostHistoryTypeId="2" PostId="12277" RevisionGUID="055885dd-1042-4827-a436-6fa09b5801d0" CreationDate="2021-10-25T11:31:08.183" UserId="17416" Text="I tried implementing my own diffuse irradiance map maker after reading [Learn OpenGL &gt; PBR &gt; IBL &gt; Diffuse Irradiance][1].&#xD;&#xA;&#xD;&#xA;It takes an HDR image and makes six HDR cube map.&#xD;&#xA;But It keeps making this very bright dots that altogether forms some kind of contour lines. (Almost looks like gamma correction artifact)&#xD;&#xA;&#xD;&#xA;Any idea what possibly can cause this kind of artifacts? &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/IBL/Diffuse-irradiance&#xD;&#xA;  [2]: https://i.stack.imgur.com/HYnZs.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/H6dgE.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35186" PostHistoryTypeId="1" PostId="12277" RevisionGUID="055885dd-1042-4827-a436-6fa09b5801d0" CreationDate="2021-10-25T11:31:08.183" UserId="17416" Text="Contour-line looking artifact on diffuse irradiance map" ContentLicense="CC BY-SA 4.0" />
  <row Id="35187" PostHistoryTypeId="3" PostId="12277" RevisionGUID="055885dd-1042-4827-a436-6fa09b5801d0" CreationDate="2021-10-25T11:31:08.183" UserId="17416" Text="|pbr|diffuse|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35188" PostHistoryTypeId="5" PostId="12275" RevisionGUID="349e357a-d6df-4c08-9bbd-bf4ce474c3ff" CreationDate="2021-10-25T13:29:41.157" UserId="10096" Comment="added 1830 characters in body" Text="Maybe it's also worth considering why people find gimbal lock &quot;wrong&quot; even when they do not know what gimbal lock is. This suggests some intuitive expectation that doesn't align with what Euler angles do (i.e. they actually do not want to work with gimbals). It begs the question how this natural expectation may be fulfilled instead.&#xD;&#xA;&#xD;&#xA;Assume you are given a joystick to control an airplane's orientation (you are in the airplane), but make it special so that the stick can also be rotated around its axis to achieve a yaw rotation. Store the set of orthonormal vectors describing the orientation of the plane $e_1,e_2,e_3$ and identify the stick's current direction with $e_2$. Now let the airplane's computer record the airplane's basis $e_1, e_2, e_3$, and the stick's direction $d$, every $x$ seconds and keep its last two states: previous $p$ and current $c$. Assume you have tilted the stick from $e_2$ in $p$ to $e'_2$ in $c$. Intuitively one wants to align the plane so that $e'_2$ is the plane's &quot;up&quot; again. This can be done by rotating the previous basis $e_1, e_2, e_3$ along the shortest path as to align $e_2$ to $e'_2$. This can be achieved using the following formula: &#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$&#xD;&#xA;and the vectors have to be further normalized. This yields a new basis $e'_1, e'_2, e'_3$ that you align your airplane to. This has a singularity if you allow your joystick a range of motion of 180 degrees, since if in $c$ you recorded $e'_2 = -e_2$ it is not clear along which rotation you reached it (all rotations are equal then: 180 degrees around any axis perpendicular to $e_2$, and there are infinitely many such axes). A solution is to either disallow 180 degrees tilts (which holds for actual joysticks), poll your joystick state more often than every $x$ seconds so it would be physically impossible to flip it by 180 degrees between polling in $p$ and $c$, or set a &quot;default&quot; flip rotation, e.g. $e'_1 = e_1, e'_2 = -e_2, e'_3 = -e_3$ which rotates around $e_1$ whenever $e'_2 = -e_2$ in $c$ (your airplane becomes reversed, but any other axis perpendicular to $e_2$ would work). Now what should be done about the yaw rotation induced by the rotation of the stick around its axis? One option is to rotate around $e'_2$. Note that the above combination of operations do not lead to gimbal lock ever, since it's not a gimbal configuration of rotations in the first place. In all states you get the exact same &quot;intuitive&quot; behaviour.&#xD;&#xA;&#xD;&#xA;Note that one could have chosen a different vector $d$ instead of $e_2$ to correspond to the joystick's direction and the idea remains the same. The point is that the two rotations - one induced from the tilting of $d$, and one induced from the rotation of $d$ around its axis, are different in behaviour, but at least for flight sims/joystick that seems to be the intuitive expected behaviour. You can achieve the same thing by using a keyboard too, e.g. up/down corresponds to tilting the stick forward/backward, left/right = tilting left/right, some other two keys for the clockwise and counter-clockwise rotation around its axis.&#xD;&#xA;&#xD;&#xA;Now forget the airplane and joystick setting, and assume you were given an actual physical 3-gimbal as a controller. In that scenario it is likely that you would not find the joystick behaviour intuitive but the 3-gimbal one, in which case it would make sense to use Euler angles. The point is that the gimbal lock by itself isn't the issue, it's the mismatch between expectations and how a system operates. That is, if I give you a joystick controller and it acts like a 3-gimbal virtually (i.e. I use Euler angles), or if I give you a 3-gimbal controller and it acts like a joystick (i.e. I use the shortest rotation described for the joystick), you will likely find both confusing. All in all, I would say this issue arises simply because people apply the wrong mathematical model to what they envision, i.e. it doesn't model their expectations but something else instead. Speaking of which, I haven't seen any 3-gimbal PC controllers. Using those Euler angles ought to make perfect sense.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;I should probably clarify that the main &quot;problem&quot; with gimbal lock arises when one wants a local rotation and instead uses mathematics describing one with respect to the global axes. To elaborate consider an update of rotation of the form: `pitch+=delta*key_pitch; yaw+=delta*key_yaw; roll+=delta*key_roll;` where the orientation update is then computed as $R_z(roll)R_y(yaw)R_x(pitch)$, versus a solution where the current orientation is kept as $R$ and the update happens through $R=R_z(delta*key_{roll})R_y(delta*key_{yaw})R_x(delta*key_{pitch})R$, the latter would also not result in gimbal lock (at least beyond the possibility of this &quot;occurring&quot; only for a single frame). In the above `key_pitch/yaw/roll` is in $\{-1,0,1\}$ for example depending on whether left key/neither left nor right key/right key is pressed. The issue in $R_z(roll)R_y(yaw)R_x(pitch)$ is really that the gimbals are &quot;fixed&quot; in place (tied to the global axes or to each other) so they do not represent the changes adequately from a local coordinate system's point of view (as incremental changes to the local coordinate system, and not to some global angles).&#xD;&#xA;&#xD;&#xA;Finally a remark on all the claims you can find on the internet that alternative rotation representations such as axis-and-angle, matrices, or quaternions avoid gimbal lock. That is not the case, as if you compose your rotations from Euler angles (regardless of the representation) and do the updates in the form `pitch+=delta*key_pitch; yaw+=delta*key_yaw; roll+=delta*key_roll;` with a recomputation of the quaternions/axis-and-angle/matrix representation in a form similar to $R_z(roll)R_y(yaw)R_x(pitch)$, you will still get gimbal lock. If instead you do the incremental updates like $R=R_z(delta*key_{roll})R_y(delta*key_{yaw})R_x(delta*key_{pitch})R$ you will not get such an &quot;issue&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="35189" PostHistoryTypeId="4" PostId="12276" RevisionGUID="f831ea29-228c-4c22-9221-d62aa366f648" CreationDate="2021-10-25T13:36:58.480" UserDisplayName="user17337" Comment="edited title" Text="Why shearing coefficients multiplying by y?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35190" PostHistoryTypeId="5" PostId="12275" RevisionGUID="d2f28943-4a8a-45d9-8000-445d3b04aa3c" CreationDate="2021-10-25T15:29:37.577" UserId="10096" Comment="deleted 493 characters in body" Text="Maybe it's also worth considering why people find gimbal lock &quot;wrong&quot; even when they do not know what gimbal lock is. This suggests some intuitive expectation that doesn't align with what Euler angles do (i.e. they actually do not want to work with gimbals). It begs the question how this natural expectation may be fulfilled instead.&#xD;&#xA;&#xD;&#xA;Assume you are given a joystick to control an airplane's orientation (you are in the airplane), but make it special so that the stick can also be rotated around its axis to achieve a yaw rotation. Store the set of orthonormal vectors describing the orientation of the plane $e_1,e_2,e_3$ and identify the stick's current direction with $e_2$. Now let the airplane's computer record the airplane's basis $e_1, e_2, e_3$, and the stick's direction $d$, every $x$ seconds and keep its last two states: previous $p$ and current $c$. Assume you have tilted the stick from $e_2$ in $p$ to $e'_2$ in $c$. Intuitively one wants to align the plane so that $e'_2$ is the plane's &quot;up&quot; again. This can be done by rotating the previous basis $e_1, e_2, e_3$ along the shortest path as to align $e_2$ to $e'_2$. This can be achieved using the following formula: &#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$&#xD;&#xA;and the vectors have to be further normalized. This yields a new basis $e'_1, e'_2, e'_3$ that you align your airplane to. This has a singularity if you allow your joystick a range of motion of 180 degrees, since if in $c$ you recorded $e'_2 = -e_2$ it is not clear along which rotation you reached it (all rotations are equal then: 180 degrees around any axis perpendicular to $e_2$, and there are infinitely many such axes). A solution is to either disallow 180 degrees tilts (which holds for actual joysticks), poll your joystick state more often than every $x$ seconds so it would be physically impossible to flip it by 180 degrees between polling in $p$ and $c$, or set a &quot;default&quot; flip rotation, e.g. $e'_1 = e_1, e'_2 = -e_2, e'_3 = -e_3$ which rotates around $e_1$ whenever $e'_2 = -e_2$ in $c$ (your airplane becomes reversed, but any other axis perpendicular to $e_2$ would work). Now what should be done about the yaw rotation induced by the rotation of the stick around its axis? One option is to rotate around $e'_2$. Note that the above combination of operations do not lead to gimbal lock ever, since it's not a gimbal configuration of rotations in the first place. In all states you get the exact same &quot;intuitive&quot; behaviour.&#xD;&#xA;&#xD;&#xA;Note that one could have chosen a different vector $d$ instead of $e_2$ to correspond to the joystick's direction and the idea remains the same. The point is that the two rotations - one induced from the tilting of $d$, and one induced from the rotation of $d$ around its axis, are different in behaviour, but at least for flight sims/joystick that seems to be the intuitive expected behaviour. You can achieve the same thing by using a keyboard too, e.g. up/down corresponds to tilting the stick forward/backward, left/right = tilting left/right, some other two keys for the clockwise and counter-clockwise rotation around its axis.&#xD;&#xA;&#xD;&#xA;Now forget the airplane and joystick setting, and assume you were given an actual physical 3-gimbal as a controller. In that scenario it is likely that you would not find the joystick behaviour intuitive but the 3-gimbal one, in which case it would make sense to use Euler angles. The point is that the gimbal lock by itself isn't the issue, it's the mismatch between expectations and how a system operates. That is, if I give you a joystick controller and it acts like a 3-gimbal virtually (i.e. I use Euler angles), or if I give you a 3-gimbal controller and it acts like a joystick (i.e. I use the shortest rotation described for the joystick), you will likely find both confusing. All in all, I would say this issue arises simply because people apply the wrong mathematical model to what they envision, i.e. it doesn't model their expectations but something else instead. Speaking of which, I haven't seen any 3-gimbal PC controllers. Using those Euler angles ought to make perfect sense.&#xD;&#xA;&#xD;&#xA;TLDR:&#xD;&#xA;&#xD;&#xA;In order to achieve incremental rotations while avoiding gimbal lock don't do this:&#xD;&#xA;&#xD;&#xA;    pitch += incr_pitch; yaw += incr_yaw; roll += incr_yaw;&#xD;&#xA;    R = Rz(roll) * Ry(yaw) * Rx(pitch);&#xD;&#xA;&#xD;&#xA;Some alternatives are to store the orientation matrix $R$ and modify it by the desired incremental change:&#xD;&#xA;&#xD;&#xA;    R = Rz(incr_roll) * Ry(incr_yaw) * Rz(incr_pitch) * R;&#xD;&#xA;    &#xD;&#xA;Another very convoluted and inefficient option, which nevertheless doesn't exhibit gimbal lock and thus illustrates that the issue is the incrementing of `pitch, yaw, roll` and not the storage of Euler angles, is the following:&#xD;&#xA;&#xD;&#xA;    R = Rz(incr_roll) * Ry(incr_yaw) * Rz(incr_pitch) * Rz(roll) * Ry(yaw) * Rx(pitch);&#xD;&#xA;    (pitch,yaw,roll) = extract_Euler(R)&#xD;&#xA;&#xD;&#xA;A different alternative is to use quaternions in the exact same way as the second snippet (`q` is assumed to be stored):&#xD;&#xA;&#xD;&#xA;    q = quat(incr_roll/2,(0,0,1)) * quat(incr_yaw/2,(0,1,0)) * quat(incr_pitch/2,(0,0,1)) * q;&#xD;&#xA;&#xD;&#xA;This also provides a counterexample to a common misconception that you cannot get gimbal lock by using quaterions. The below snippet will exhibit gimbal lock:&#xD;&#xA;&#xD;&#xA;    pitch+=incr_pitch; yaw+=inct_yaw; roll+=incr_roll;&#xD;&#xA;    q = quat(incr_roll/2,(0,0,1)) * quat(incr_yaw/2,(0,1,0)) * quat(incr_pitch/2,(0,0,1));&#xD;&#xA;&#xD;&#xA;The point I am trying to make is that the issue arises when incrementing Euler angles and then producing a rotation from those. The increment results in a behaviour consistent with turning a specific gimbal from a 3-axis gimbal, and not with the controls of an airplane for example. For the latter one has to produce the increment through matrix/quaternion composition with the orientation, or the trick that I suggested:&#xD;&#xA;&#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="35191" PostHistoryTypeId="50" PostId="8888" RevisionGUID="e98e09bc-faf8-44de-98bd-3ec100e10408" CreationDate="2021-10-25T17:08:40.713" UserId="-1" />
  <row Id="35192" PostHistoryTypeId="2" PostId="12278" RevisionGUID="1518835b-3e3b-41d1-84e9-fe11a08693d9" CreationDate="2021-10-25T17:32:31.443" UserId="16126" Text="I generate a normal GBuffer in my engine, and I store it using a R16G16G16_SNORM format like this:&#xD;&#xA;&#xD;&#xA;    input.normal = normalize(input.normal);&#xD;&#xA;    input.tangent = normalize(input.tangent);&#xD;&#xA;    float3 binormal = normalize(cross(input.tangent, input.normal));&#xD;&#xA;&#xD;&#xA;    float3 normal = (normalMap.Sample(SampleType, input.tex).rgb * 2.0) - 1.0f;&#xD;&#xA;    float3x3 texSpace = float3x3(input.tangent, binormal, input.normal);&#xD;&#xA;    float3 finalNormal = normalize(mul(normal, texSpace));&#xD;&#xA;&#xD;&#xA;    output.normals = float4(finalNormal.rgb, 1.0f);&#xD;&#xA;&#xD;&#xA;But when debugging the frame in RenderDoc, I notice that the 3rd component of the frame (Z, or blue channel) is always 0.0&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yPsQI.jpg&#xD;&#xA;&#xD;&#xA;As you can see, both the blue and alpha components come back as zero, even though the alpha is explicitly set to 1.0 in the shader. The frame visually contains information in the blue channel, so why is it coming up as 0.0? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35194" PostHistoryTypeId="1" PostId="12278" RevisionGUID="1518835b-3e3b-41d1-84e9-fe11a08693d9" CreationDate="2021-10-25T17:32:31.443" UserId="16126" Text="16 bit SNORM format not correctly storing Z component?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35195" PostHistoryTypeId="3" PostId="12278" RevisionGUID="1518835b-3e3b-41d1-84e9-fe11a08693d9" CreationDate="2021-10-25T17:32:31.443" UserId="16126" Text="|c++|hlsl|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35196" PostHistoryTypeId="5" PostId="12278" RevisionGUID="b345745e-d446-4ffb-b202-00cb09adbb6c" CreationDate="2021-10-25T18:02:57.590" UserId="16126" Comment="added 3 characters in body" Text="I generate a normal GBuffer in my engine, and I store it using a R16G16G16A16_SNORM format like this:&#xD;&#xA;&#xD;&#xA;    input.normal = normalize(input.normal);&#xD;&#xA;    input.tangent = normalize(input.tangent);&#xD;&#xA;    float3 binormal = normalize(cross(input.tangent, input.normal));&#xD;&#xA;&#xD;&#xA;    float3 normal = (normalMap.Sample(SampleType, input.tex).rgb * 2.0) - 1.0f;&#xD;&#xA;    float3x3 texSpace = float3x3(input.tangent, binormal, input.normal);&#xD;&#xA;    float3 finalNormal = normalize(mul(normal, texSpace));&#xD;&#xA;&#xD;&#xA;    output.normals = float4(finalNormal.rgb, 1.0f);&#xD;&#xA;&#xD;&#xA;But when debugging the frame in RenderDoc, I notice that the 3rd component of the frame (Z, or blue channel) is always 0.0&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yPsQI.jpg&#xD;&#xA;&#xD;&#xA;As you can see, both the blue and alpha components come back as zero, even though the alpha is explicitly set to 1.0 in the shader. The frame visually contains information in the blue channel, so why is it coming up as 0.0? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35197" PostHistoryTypeId="2" PostId="12279" RevisionGUID="1b189579-a9e2-4e88-906d-7d57efcb088b" CreationDate="2021-10-25T19:55:48.317" UserId="7952" Text="While it is often the case that a parallel projection such as an orthographic projection has all zero's in one row/column of a matrix, it is also easy to set a projection plane other then zero, such as the near plane which is often done in CG for things like shadow maps of infinitely distant point lights. (think cascade shadow maps)&#xD;&#xA;&#xD;&#xA;Also, projection planes are very frequently perpendicular to the view plane but this is just the norm, it is possible and sometimes desirable to have an oblique projection plane. Oblique parallel projections are a specific subtype, see this [paper for an example][1] of an oblique perspective projection.&#xD;&#xA;&#xD;&#xA;These terms are so overloaded in the industry that it is easy to start talking apples and oranges so just be clear my terminology is that planar projections are the super set of all perspective and parallel projections, under perspective projections there are 1,2 and 3 point projections, most people are referring to 3 point projections when they say &quot;perspective projection&quot;. Under parallel projections there are orthographic, axonometric, and oblique. So when you say parallel it sounds like your are referring to a large assortment of projections, then again some folks refer to axonometric as parallel, it really depends on the industry their school, and where they work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35199" PostHistoryTypeId="5" PostId="12278" RevisionGUID="6e9d314a-769a-44c9-b414-fc555567e12d" CreationDate="2021-10-25T22:50:35.823" UserId="16126" Comment="edited body" Text="I generate a normal GBuffer in my engine, and I store it using a R16G16B16A16_SNORM format like this:&#xD;&#xA;&#xD;&#xA;    input.normal = normalize(input.normal);&#xD;&#xA;    input.tangent = normalize(input.tangent);&#xD;&#xA;    float3 binormal = normalize(cross(input.tangent, input.normal));&#xD;&#xA;&#xD;&#xA;    float3 normal = (normalMap.Sample(SampleType, input.tex).rgb * 2.0) - 1.0f;&#xD;&#xA;    float3x3 texSpace = float3x3(input.tangent, binormal, input.normal);&#xD;&#xA;    float3 finalNormal = normalize(mul(normal, texSpace));&#xD;&#xA;&#xD;&#xA;    output.normals = float4(finalNormal.rgb, 1.0f);&#xD;&#xA;&#xD;&#xA;But when debugging the frame in RenderDoc, I notice that the 3rd component of the frame (Z, or blue channel) is always 0.0&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yPsQI.jpg&#xD;&#xA;&#xD;&#xA;As you can see, both the blue and alpha components come back as zero, even though the alpha is explicitly set to 1.0 in the shader. The frame visually contains information in the blue channel, so why is it coming up as 0.0? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35200" PostHistoryTypeId="2" PostId="12280" RevisionGUID="133e90ba-38de-47de-9454-efee21af6cfa" CreationDate="2021-10-26T00:26:18.923" UserId="8009" Text="In OpenGL parlance, the projection matrix, whether orthographic or perspective, takes you from _View Space_ (a.k.a. _Camera Space_) to _Homogenous Clip Space_.  After clipping you arrive at _Normalized Device Coordinates_ (also known as NDC) and these points are still 3D $(x_p, y_p, z_{vp})$ and finally it's the _viewport transform_ that transforms NDC to _Viewport coordinates_ (a.k.a. _screen coordinates_, _window coordinates_ or (not normalized) _device coordinates_) which are 2D $(x_p, y_p)$.&#xD;&#xA;&#xD;&#xA;May I suggest reading: [OpenGL Transformation](http://www.songho.ca/opengl/gl_transform.html)&#xD;&#xA;&#xD;&#xA;And with respect to your final question:  No, perspective &quot;projectors&quot; (projected rays) are not all perpendicular to the viewing plane - that would require a curved viewing surface.  If all the rays projected from a point were perpendicular to the viewing surface, that surface would be a section of a _sphere_.  There is one line that passes through the center of projection and meets the image plane at a right angle and that is the _axis of projection_ arriving at the viewing plane at the _principal point_.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35202" PostHistoryTypeId="5" PostId="12279" RevisionGUID="754f26a6-16d6-4e60-ac79-0b777279143c" CreationDate="2021-10-26T07:09:12.247" UserId="13095" Comment="Fix some grammar/spelling and split some very long sentences into multiple ones" Text="While it is often the case that a parallel projection such as an orthographic projection has all zero's in one row/column of a matrix, it is also easy to set a projection plane other than zero, such as the near plane which is often done in CG for things like shadow maps of infinitely distant point lights. (think cascade shadow maps)&#xD;&#xA;&#xD;&#xA;Also, projection planes are very frequently perpendicular to the view plane but this is just the norm. It is possible and sometimes desirable to have an oblique projection plane. Oblique parallel projections are a specific subtype. See this [paper for an example][1] of an oblique perspective projection.&#xD;&#xA;&#xD;&#xA;These terms are so overloaded in the industry that it is easy to start talking apples and oranges. So just be clear my terminology is that planar projections are the superset of all perspective and parallel projections. Under perspective projections, there are 1,2, and 3 point projections. Most people are referring to 3 point projections when they say &quot;perspective projection&quot;. Under parallel projections, there are orthographic, axonometric, and oblique. So when you say parallel it sounds like you are referring to a large assortment of projections. Then again some folks refer to axonometric as parallel, it really depends on the industry their school, and where they work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35203" PostHistoryTypeId="2" PostId="12281" RevisionGUID="2d684ae9-3d19-4e21-8bc2-08fffb9fa8b0" CreationDate="2021-10-26T09:52:40.487" UserId="7647" Text="A shear can be thought of as an affine transformation that turns a square into a parallelogram:&#xD;&#xA;&#xD;&#xA;[![An undeformed units square, with points a, b, c, and d identified, and the square after deformation by a shear, with points a', b', c', and d' identified.][1]][1]&#xD;&#xA;&#xD;&#xA;Note that the spacing of points at the same x-position are unchanged by the transformation; the distance between $a$ and $b$ is the same as between $a'$ and $b'$, and the distance $cd$ is the same as the distance $c'd'$. What has changed is that each x-layer has been shifted to the right, relative to the layers below it; the x-axis itself is unshifted. This means that the image of a point $(x,y)$ must be at the same y-level, i.e. $y' = y$, and be shifted to the right, i.e. $x' = x + d$ for some $d$. In fact, $d$ must be a function of $y$ that increases as $y$ increases, since each layer is to the right of the layers below it.&#xD;&#xA;&#xD;&#xA;The point $c = (0,1)$ has been shifted to $c' = (sh_x,1)$. Since the shear is an affine transformation, the vertical line from the origin to $c$ has been transformed to a straight line from the origin to $c'$. The point $a = (0,0.5)$, halfway along the line to $c$, must therefore be transformed to a point halfway along the line to $c'$, i.e. $(0.5 \times sh_x, 0.5)$. In general, the distance $d$ from the y-axis to the transformed y-axis must just be $sh_x \times y$, or&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;x \mapsto x + sh_x \times y, &#xD;&#xA;y \mapsto y.&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KBzII.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35205" PostHistoryTypeId="2" PostId="12282" RevisionGUID="5a414fbb-7d7c-43dd-be58-de3792fad7f7" CreationDate="2021-10-26T19:22:46.537" UserDisplayName="user17337" Text="We know that world co-ordinate $(x_w, y_w)$ transforms to viewport co-ordinate $(x_v, y_v)$ which is physical device co-ordinate. And during projection any point $(x, y, z)$ projects to $(x, y)$ into projection plane. My question is  projection and transformation both are same? &#xD;&#xA;Please explain with small example. I want to understand intuition rather than details proof. " ContentLicense="CC BY-SA 4.0" />
  <row Id="35207" PostHistoryTypeId="1" PostId="12282" RevisionGUID="5a414fbb-7d7c-43dd-be58-de3792fad7f7" CreationDate="2021-10-26T19:22:46.537" UserDisplayName="user17337" Text="Difference between transformation and projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35208" PostHistoryTypeId="3" PostId="12282" RevisionGUID="5a414fbb-7d7c-43dd-be58-de3792fad7f7" CreationDate="2021-10-26T19:22:46.537" UserDisplayName="user17337" Text="|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35213" PostHistoryTypeId="2" PostId="12284" RevisionGUID="4b52c5b7-bfac-4fd1-b552-1a8f3fc136d6" CreationDate="2021-10-27T02:14:54.913" UserId="2654" Text="A projection is a *kind* of transformation.&#xD;&#xA;&#xD;&#xA;A transformation is any modification of a coordinate that expresses that coordinate relative to a coordinate system that is different from its original coordinate system. As such, a transformation involves two coordinate systems: the source and the destination.&#xD;&#xA;&#xD;&#xA;A projection is any transformation where the destination coordinate system has fewer dimensions than the source coordinate system. That is, it removes one or more dimensions from the coordinate." ContentLicense="CC BY-SA 4.0" />
  <row Id="35217" PostHistoryTypeId="2" PostId="12285" RevisionGUID="8e8c980f-d48e-4b63-a646-82829bbcff99" CreationDate="2021-10-27T08:17:14.817" UserId="13273" Text="I found a very nice paper regarding [Time Interval Ray Tracing for Motion Blur][1] published in 2017. That was before RTX GPUs were on the market.&#xD;&#xA;I have a few questions about an optimal implementation and its performance.&#xD;&#xA;&#xD;&#xA;**Short introduction:**&#xD;&#xA;I'm using the Vulkan api to raytrace outer space scenarios, like spacecraft docking scenarios. So the scenario has only one till max 10 spacecrafts, which are close enough to be visible. Each spacecraft is very detailed. It is optimized to only have the outer shell, so they have no geometry inside. The spacecraft geometries has up to 50.000 triangles each. And the scenario should be rendered in real-time (hopefully 60 fps). &#xD;&#xA;&#xD;&#xA;**Problem**: So when using the Motion Blur algorithm linked above, The number of triangles will increase to factor *3 when only using two keyframes. These new triangles and their position / orientation will change from frame to frame. And each frame I have to store the new triangles to the Bottom-Level-Acceleration-Structure (BLAS). Do you guys see a performance problem here?&#xD;&#xA;So the idea is to use the render pipeline (from vertex- till geometry- shader) to create the 4D (3D + time) geometry on GPU. Rotations are the most problematic transformations. To have a good rotational movement, the number of keyframes need to be increased depending on the rotational speed and the exposure time. I think these keyframes need to be split into several BLAS (one BLAS for each keyframe transformation).&#xD;&#xA;&#xD;&#xA;In case to fill the BLAS is no performance problem, I think the next problem could be to fire rays.&#xD;&#xA;When having fast camera movements or fast translating spacecrafts, a ray could hit a lot of primitives (triangles). Is this a performance problem? Usually the scenario is very simple.&#xD;&#xA; We are trying to generate the output image as realistic as possible, so the different blending functions are extremely interesting for us. &#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA; 1. How performant is filling the BLAS? (I thought about refitting acceleration structures, because the number of primitives will not change)&#xD;&#xA; 2. Is it better to use several BLAS for the same objekt in case of faster rotations and therefore several keyframes?&#xD;&#xA; 3. How performant is firing the rays?&#xD;&#xA; 4. Do I have enough performance to fire even more rays? Shadow rays, reflection / refraction rays, Photon mapping rays?&#xD;&#xA; 5. Did someone even tested the algorithm with a newer RTX graphics card? (For this project we will use a NVIDIA RTX3080)&#xD;&#xA; 6. Do you know other techniques which better fit to our scenario for real-time?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cemyuksel.com/research/papers/time_interval_ray_tracing_for_motion_blur-high.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35219" PostHistoryTypeId="1" PostId="12285" RevisionGUID="8e8c980f-d48e-4b63-a646-82829bbcff99" CreationDate="2021-10-27T08:17:14.817" UserId="13273" Text="Time Interval Ray Tracing performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="35220" PostHistoryTypeId="3" PostId="12285" RevisionGUID="8e8c980f-d48e-4b63-a646-82829bbcff99" CreationDate="2021-10-27T08:17:14.817" UserId="13273" Text="|raytracing|vulkan|real-time|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35222" PostHistoryTypeId="2" PostId="12286" RevisionGUID="a53a9c5a-02c4-4f9d-9fcb-2c3b66abc1fa" CreationDate="2021-10-27T10:11:27.650" UserDisplayName="user17337" Text="I synchronised with @David k's [first](https://math.stackexchange.com/questions/4285168/difference-between-parallel-projection-and-perspective-projection) and [second](https://math.stackexchange.com/questions/4288470/special-cases-of-perspective-projection) answer regarding perspective and parallel projection. From the first question I understand that image on the screen is typically described in horizontal and vertical coordinates, that is 2D points. But from second question I understand that image on the screen are realistic which uses perspective projection has coordinates 3D. &#xD;&#xA;&#xD;&#xA;My confusion is that how we show the image on the screen with 2D points by perspective projection? &#xD;&#xA;&#xD;&#xA;The Point $(x,y,z)$ is projected to position $(x_p,y_p,z_{vp})$ on the view plane.Since the view plane is placed at position $z_{vp}$ along the $z_v$ axis. So when $z_{vp}=0$ Projectors (projection vectors) are not converged to projection reference point in parallel projection. But in perspective projection when $z_{vp}=0$, it is reduced to parallel projection,but projectors are converged to centre of projection. Am I correct above these concepts? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35224" PostHistoryTypeId="1" PostId="12286" RevisionGUID="a53a9c5a-02c4-4f9d-9fcb-2c3b66abc1fa" CreationDate="2021-10-27T10:11:27.650" UserDisplayName="user17337" Text="Parallel projection is special case of perspective projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="35225" PostHistoryTypeId="3" PostId="12286" RevisionGUID="a53a9c5a-02c4-4f9d-9fcb-2c3b66abc1fa" CreationDate="2021-10-27T10:11:27.650" UserDisplayName="user17337" Text="|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35226" PostHistoryTypeId="5" PostId="12286" RevisionGUID="1591031b-4517-4bf0-9ed5-c149fa6bc34d" CreationDate="2021-10-27T13:36:35.453" UserDisplayName="user17337" Comment="added 147 characters in body" Text="I synchronised with @David k's [first](https://math.stackexchange.com/questions/4285168/difference-between-parallel-projection-and-perspective-projection) and [second](https://math.stackexchange.com/questions/4288470/special-cases-of-perspective-projection) answer regarding perspective and parallel projection. From the first question I understand that image on the screen is typically described in horizontal and vertical coordinates, that is 2D points. But from second question I understand that image on the screen are realistic which uses perspective projection has coordinates 3D. &#xD;&#xA;&#xD;&#xA;My confusion is that how we show the image on the screen with 2D points by perspective projection? &#xD;&#xA;&#xD;&#xA;The Point $(x,y,z)$ is projected to position $(x_p,y_p,z_{vp})$ on the view plane.Since the view plane is placed at position $z_{vp}$ along the $z_v$ axis. So when $z_{vp}=0$ Projectors (projection vectors) are not converged to projection reference point in parallel projection. But in perspective projection when $z_{vp}=0$, it is reduced to parallel projection,but projectors are converged to centre of projection. Am I correct above these concepts? &#xD;&#xA;&#xD;&#xA;The vanishing point in perspective projection which is 3D coordinates could be represents in projective plane as $(x, y, z, 0).$ Am I correct? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35227" PostHistoryTypeId="5" PostId="12280" RevisionGUID="b80cf1c7-324e-400c-8f26-081e1a73f7e3" CreationDate="2021-10-27T13:54:20.017" UserId="8009" Comment="Added more info to help clarify." Text="In OpenGL parlance, the projection matrix, whether orthographic or perspective, takes you from _View Space_ (a.k.a. _Camera Space_) to _Homogenous Clip Space_.  After clipping you arrive at _Normalized Device Coordinates_ (also known as NDC) and these points are still 3D $(x_p, y_p, z_{vp})$ and finally it's the _viewport transform_ that transforms NDC to _Viewport coordinates_ (a.k.a. _screen coordinates_, _window coordinates_ or (not normalized) _device coordinates_) which are 2D $(x_p, y_p)$.&#xD;&#xA;&#xD;&#xA;May I suggest reading: [OpenGL Transformation](http://www.songho.ca/opengl/gl_transform.html)&#xD;&#xA;&#xD;&#xA;And with respect to your final question:  No, perspective &quot;projectors&quot; (projected rays) are not all perpendicular to the viewing plane - that would require a curved viewing surface.  If all the rays projected from a point were perpendicular to the viewing surface, that surface would be a section of a _sphere_.  There is one line that passes through the center of projection and meets the image plane at a right angle and that is the _axis of projection_ arriving at the viewing plane at the _principal point_.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;More info:&#xD;&#xA;&#xD;&#xA;_Transformation_ just means change.  With respect to 3D points it usually means the output bears some resemblance to the input.  e.g.:  Translation, Rotation, Scale, Skew, or even Projection is a kind of transformation.  If the output can be transformed back to the input then the transformation is _invertible_.  _Projection_ is a specific kind of transformation that moves all the input points onto a plane.  Either to the closest point (orthographic) or along a lines passing through a common projection point (perspective).  The projection transformation is not invertible.&#xD;&#xA;&#xD;&#xA;A transformation is said to be _linear_ if it can be represented by a matrix multiply.&#xD;&#xA;&#xD;&#xA;Here's the confusing part.  To perform the perspective transformation, one must perform a non-linear step of dividing by Z.  This can't be represented by a matrix.  To get around this, we transform all the coordinates linearly into what is called _clip space_.  And then the pipeline includes a non-linear transformation from _clip space_ to _normalized device coordinates_ by performing the division operation.  The so-called _PROJECTION MATRIX_ (in OpenGL) is actually just a linear transformation from camera/eye coordinates to clip coordinates.  It's only the first of **two steps** required to perform an actual projection transformation.  The actual projection transformation is completed in a second step by doing the divide, and arriving at NDC coordinates.  This divide cannot be represented by a matrix multiply.  The linear part of the transformation produces the numerator and the denominator of the quotient in separate coordinates.  The non-linear part of the transformation divides.&#xD;&#xA;&#xD;&#xA;Interestingly, the linear transformation from camera coordinates to clip coordinates (as given by the PROJECTION MATRIX) **is** invertible.  And after dividing by Z it's still invertible (provided we retain the Z value).  But after we **discard** the Z-value and go to just Screen coordinates, we can no longer invert the 2D screen-coordinates back into the original 3D coordinates.  Similarly, if we actually transformed all the points onto the projection plane (still in 3D), we wouldn't be able to invert that transformation of points on the plane back into the original 3D points (information has been lost, because it's been scaled down to 0 in the &quot;depth&quot; direction).&#xD;&#xA;&#xD;&#xA;Even after dividing, we're still in 3-dimensional coordinates.  The third coordinate is still useful for writing to your depth buffer.&#xD;&#xA;&#xD;&#xA;Only when we are ready to compute screen coordinates do we drop the Z value and use just 2-dimensional coordinates.&#xD;&#xA;&#xD;&#xA;Other transformations such as perspective texture mapping (like to simulate a projector) follow a similar path and have a non-linear divide step to arrive at texture mapping coordinates (u,v).&#xD;&#xA;&#xD;&#xA;So, to answer your question, in the pipeline we try to keep invertible 3D coordinates around as long as possible in the pipeline, deferring the divide as late as possible and discarding the Z information as late as possible so that things are linear for as much of the pipeline as possible (thanks to homogenous coordinates) and are invertible as long as possible (by retaining the depth coordinate in NDC space)." ContentLicense="CC BY-SA 4.0" />
  <row Id="35228" PostHistoryTypeId="2" PostId="12287" RevisionGUID="51ea4878-c5fb-49bc-a950-3a3fda34cc44" CreationDate="2021-10-27T21:15:45.250" UserId="17433" Text="I'm making a POV fan and would like to display some simple graphics in real-time on it. I have a working naive solution with OpenGL, but I'm maxing out at 7 fps rending a simple cube on a raspberry pi 3 B+.&#xD;&#xA;&#xD;&#xA;normal rasterization of an image, as I understand it, happens as illustrated in the following image, where the pixels are processed left-to-right, top-to-bottom.&#xD;&#xA;[![tradition rasterization][1]][1]&#xD;&#xA;&#xD;&#xA;However, to be displayed on a rotating fan, the rasterization needs to be radial like in this image:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now, I'm not sure if this is best achieved with a custom rasterization or perhaps applying a matrix after the projection matrix has been applied. My current solution to the issue is for every &quot;frame&quot; I render a 128x1 pixel image, slightly rotate the camera about it's viewing axis, and repeat until the camera has rotated 360 degrees. This works, but it's abyssmally slow and is a pretty hacky solution. Another thing that is unique to this problem is that the final result never needs to actually be shown on screen. The colors in the color buffer are sent out over a simplified SPI protocol to the LED fan blade. I'm programming this in OpenGL 2.1, so any relevant code examples would be much appreciated!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dJiPb.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7yknw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35230" PostHistoryTypeId="1" PostId="12287" RevisionGUID="51ea4878-c5fb-49bc-a950-3a3fda34cc44" CreationDate="2021-10-27T21:15:45.250" UserId="17433" Text="How to Achieve Radial Rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="35231" PostHistoryTypeId="3" PostId="12287" RevisionGUID="51ea4878-c5fb-49bc-a950-3a3fda34cc44" CreationDate="2021-10-27T21:15:45.250" UserId="17433" Text="|opengl|rendering|transformations|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35232" PostHistoryTypeId="2" PostId="12288" RevisionGUID="8b758747-bba3-4d8d-9557-289a1977884a" CreationDate="2021-10-27T22:03:18.737" UserId="48" Text="GPU hardware rasterization can't generate the kind of image you're looking for directly. However, one option would be to render a normal image to an offscreen buffer, and then use a pixel shader to convert it to the format to send out to the LEDs.&#xD;&#xA;&#xD;&#xA;In other words, run a full-screen pass on the output render target, with a shader that interprets its input X as radius and Y as time, and samples the calculated location in the previously rendered image as a texture. Then the output render target can be read back, and will contain the successive LED values row by row." ContentLicense="CC BY-SA 4.0" />
  <row Id="35234" PostHistoryTypeId="5" PostId="12275" RevisionGUID="6965c9fc-5fc5-46da-8d51-ca40cd02efca" CreationDate="2021-10-27T22:29:05.257" UserId="10096" Comment="typos" Text="Maybe it's also worth considering why people find gimbal lock &quot;wrong&quot; even when they do not know what gimbal lock is. This suggests some intuitive expectation that doesn't align with what Euler angles do (i.e. they actually do not want to work with gimbals). It begs the question how this natural expectation may be fulfilled instead.&#xD;&#xA;&#xD;&#xA;Assume you are given a joystick to control an airplane's orientation (you are in the airplane), but make it special so that the stick can also be rotated around its axis to achieve a yaw rotation. Store the set of orthonormal vectors describing the orientation of the plane $e_1,e_2,e_3$ and identify the stick's current direction with $e_2$. Now let the airplane's computer record the airplane's basis $e_1, e_2, e_3$, and the stick's direction $d$, every $x$ seconds and keep its last two states: previous $p$ and current $c$. Assume you have tilted the stick from $e_2$ in $p$ to $e'_2$ in $c$. Intuitively one wants to align the plane so that $e'_2$ is the plane's &quot;up&quot; again. This can be done by rotating the previous basis $e_1, e_2, e_3$ along the shortest path as to align $e_2$ to $e'_2$. This can be achieved using the following formula: &#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$&#xD;&#xA;and the vectors have to be further normalized. This yields a new basis $e'_1, e'_2, e'_3$ that you align your airplane to. This has a singularity if you allow your joystick a range of motion of 180 degrees, since if in $c$ you recorded $e'_2 = -e_2$ it is not clear along which rotation you reached it (all rotations are equal then: 180 degrees around any axis perpendicular to $e_2$, and there are infinitely many such axes). A solution is to either disallow 180 degrees tilts (which holds for actual joysticks), poll your joystick state more often than every $x$ seconds so it would be physically impossible to flip it by 180 degrees between polling in $p$ and $c$, or set a &quot;default&quot; flip rotation, e.g. $e'_1 = e_1, e'_2 = -e_2, e'_3 = -e_3$ which rotates around $e_1$ whenever $e'_2 = -e_2$ in $c$ (your airplane becomes reversed, but any other axis perpendicular to $e_2$ would work). Now what should be done about the yaw rotation induced by the rotation of the stick around its axis? One option is to rotate around $e'_2$. Note that the above combination of operations do not lead to gimbal lock ever, since it's not a gimbal configuration of rotations in the first place. In all states you get the exact same &quot;intuitive&quot; behaviour.&#xD;&#xA;&#xD;&#xA;Note that one could have chosen a different vector $d$ instead of $e_2$ to correspond to the joystick's direction and the idea remains the same. The point is that the two rotations - one induced from the tilting of $d$, and one induced from the rotation of $d$ around its axis, are different in behaviour, but at least for flight sims/joystick that seems to be the intuitive expected behaviour. You can achieve the same thing by using a keyboard too, e.g. up/down corresponds to tilting the stick forward/backward, left/right = tilting left/right, some other two keys for the clockwise and counter-clockwise rotation around its axis.&#xD;&#xA;&#xD;&#xA;Now forget the airplane and joystick setting, and assume you were given an actual physical 3-gimbal as a controller. In that scenario it is likely that you would not find the joystick behaviour intuitive but the 3-gimbal one, in which case it would make sense to use Euler angles. The point is that the gimbal lock by itself isn't the issue, it's the mismatch between expectations and how a system operates. That is, if I give you a joystick controller and it acts like a 3-gimbal virtually (i.e. I use Euler angles), or if I give you a 3-gimbal controller and it acts like a joystick (i.e. I use the shortest rotation described for the joystick), you will likely find both confusing. All in all, I would say this issue arises simply because people apply the wrong mathematical model to what they envision, i.e. it doesn't model their expectations but something else instead. Speaking of which, I haven't seen any 3-gimbal PC controllers. Using those, Euler angles ought to make perfect sense.&#xD;&#xA;&#xD;&#xA;TLDR:&#xD;&#xA;&#xD;&#xA;In order to achieve incremental rotations while avoiding gimbal lock don't do this:&#xD;&#xA;&#xD;&#xA;    pitch += incr_pitch; yaw += incr_yaw; roll += incr_yaw;&#xD;&#xA;    R = Rz(roll) * Ry(yaw) * Rx(pitch);&#xD;&#xA;&#xD;&#xA;Some alternatives are to store the orientation matrix $R$ and modify it by the desired incremental change:&#xD;&#xA;&#xD;&#xA;    R = Rz(incr_roll) * Ry(incr_yaw) * Rx(incr_pitch) * R;&#xD;&#xA;    &#xD;&#xA;Another very convoluted and inefficient option, which nevertheless doesn't exhibit gimbal lock and thus illustrates that the issue is the incrementing of `pitch, yaw, roll` and not the storage of Euler angles, is the following:&#xD;&#xA;&#xD;&#xA;    R = Rz(incr_roll) * Ry(incr_yaw) * Rx(incr_pitch) * Rz(roll) * Ry(yaw) * Rx(pitch);&#xD;&#xA;    (pitch,yaw,roll) = extract_Euler(R)&#xD;&#xA;&#xD;&#xA;A different alternative is to use quaternions in the exact same way as the second snippet (`q` is assumed to be stored):&#xD;&#xA;&#xD;&#xA;    q = quat(incr_roll/2,(0,0,1)) * quat(incr_yaw/2,(0,1,0)) * quat(incr_pitch/2,(1,0,0)) * q;&#xD;&#xA;&#xD;&#xA;This also provides a counterexample to a common misconception that you cannot get gimbal lock by using quaterions. The below snippet will exhibit gimbal lock:&#xD;&#xA;&#xD;&#xA;    pitch+=incr_pitch; yaw+=inct_yaw; roll+=incr_roll;&#xD;&#xA;    q = quat(incr_roll/2,(0,0,1)) * quat(incr_yaw/2,(0,1,0)) * quat(incr_pitch/2,(1,0,0));&#xD;&#xA;&#xD;&#xA;The point I am trying to make is that the issue arises when incrementing Euler angles and then producing a rotation from those. The increment results in a behaviour consistent with turning a specific gimbal from a 3-axis gimbal, and not with the controls of an airplane for example. For the latter one has to produce the increment through matrix/quaternion composition with the orientation, or the trick that I suggested:&#xD;&#xA;&#xD;&#xA;$$e'_i = e_i - \frac{e_i \cdot e'_2}{1 + (e_2 \cdot e'_2)}(e_2 + e'_2), \, i \in \{1,3\},$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="35235" PostHistoryTypeId="2" PostId="12289" RevisionGUID="c832c684-f6be-4d5b-838d-272f73cf5607" CreationDate="2021-10-27T22:35:37.670" UserId="38" Text="Lets try to reign stuff in a bit. In practical applications we do not deal with infinites. Because that would mean we would need to use some kind of symbolic solver for all of our stuff. We couldnt afford to do this in many practical applications.&#xD;&#xA;&#xD;&#xA;Because of these practical considerations i need to have a near and far plane for my camera rasterizer. If i were to make some kind of vector graphics i most likely wouldnt have infinite objects, and if we would do some sort of tracing we would have hard time deducing intersections near infinity.&#xD;&#xA;&#xD;&#xA;Also because of practical considerations, we do not generally \* turn the data into 2D coordinates. What we conceptually do is we transform the points so that they seem like something that looks like a perspective projection from a paralell projection in our z direction. We then use this view  to build out the data that we need. During this building process we are free to discard any data that we dont need. So think of this like a preliminarry sorting so that i can really do what i intended easily. &#xD;&#xA;&#xD;&#xA;Now usually we have acess to both the transformed data and untransformed data so we not terribly concerned in deducing something from the projection that we can simply read it from the 3D space directly or from our scene graph for that matter. But both the z and even the fourth component data could be useful for building my next stage primitives.&#xD;&#xA;&#xD;&#xA;Ok so at this point we are done with projecting and now we can start building our output. But this has nothing to do with any of the math you asked so far. The next stages are about triangle barycentric coordinates, shading, intersection finding, depth sorting etc. The math that you have gone trough so far dont really help with this step.&#xD;&#xA;&#xD;&#xA;\* It is hard to generalize somebody might be doing this but i wouldnt because its a waste of my time." ContentLicense="CC BY-SA 4.0" />
  <row Id="35237" PostHistoryTypeId="5" PostId="12289" RevisionGUID="cf6d5419-2d1e-44d8-a956-8dc8aadb9a07" CreationDate="2021-10-27T22:42:14.577" UserId="38" Comment="added 45 characters in body" Text="Lets try to reign stuff in a bit. In practical applications we do not deal with infinites. Because that would mean we would need to use some kind of symbolic solver for all of our stuff. We couldnt afford to do this in many practical applications.&#xD;&#xA;&#xD;&#xA;Because of these practical considerations i need to have a near and far plane for my camera rasterizer. If i were to make some kind of vector graphics i most likely wouldnt have infinite objects (or atleast deal with this in the scenegraph) and if we would do some sort of tracing we would have hard time deducing intersections near infinity.&#xD;&#xA;&#xD;&#xA;Also because of practical considerations, we do not generally \* turn the data into 2D coordinates. What we conceptually do is we transform the points so that they seem like something that looks like a perspective projection from a paralell projection in our z direction. We then use this view  to build out the data that we need. During this building process we are free to discard any data that we dont need. So think of this like a preliminarry sorting so that i can really do what i intended easily. &#xD;&#xA;&#xD;&#xA;Now usually we have acess to both the transformed data and untransformed data so we not terribly concerned in deducing something from the projection that we can simply read it from the 3D space directly or from our scene graph for that matter. But both the z and even the fourth component data could be useful for building my next stage primitives.&#xD;&#xA;&#xD;&#xA;Ok so at this point we are done with projecting and now we can start building our output. But this has nothing to do with any of the math you asked so far. The next stages are about triangle barycentric coordinates, shading, intersection finding, depth sorting etc. The math that you have gone trough so far dont really help with this step.&#xD;&#xA;&#xD;&#xA;\* It is hard to generalize somebody might be doing this but i wouldnt because its a waste of my time." ContentLicense="CC BY-SA 4.0" />
  <row Id="35238" PostHistoryTypeId="5" PostId="12289" RevisionGUID="7594cbc6-bc69-4d22-ad05-94e97843ecea" CreationDate="2021-10-27T22:47:21.147" UserId="38" Comment="added 45 characters in body" Text="Lets try to reign stuff in a bit. In practical applications we do not deal with infinites. Because that would mean we would need to use some kind of symbolic solver for all of our stuff. We couldnt afford to do this in many practical applications.&#xD;&#xA;&#xD;&#xA;Because of these practical considerations i need to have a near and far plane for my camera rasterizer. If i were to make some kind of vector graphics i most likely wouldnt have infinite objects (or atleast deal with this in the scenegraph) and if we would do some sort of tracing we would have hard time deducing intersections near infinity.&#xD;&#xA;&#xD;&#xA;Also because of practical considerations, we do not generally \* turn the data into 2D coordinates. What we conceptually do is we transform the points so that they seem like something that looks like a perspective projection from a paralell projection in our z direction. We then use this view  to build out the data that we need. During this building process we are free to discard any data that we dont need. So think of this like a preliminarry sorting so that i can really do what i intended easily. &#xD;&#xA;&#xD;&#xA;Now usually we have acess to both the transformed data and untransformed data so that being terribly concerned about deducing something from the projection, that we can simply read it from the 3D space directly or from our scene graph for that matter, is a priority. But both the z and even the fourth component data could be useful for building my next stage primitives.&#xD;&#xA;&#xD;&#xA;Ok so at this point we are done with projecting and now we can start building our output. But this has nothing to do with any of the math you asked so far. The next stages are about triangle barycentric coordinates, shading, intersection finding, depth sorting etc. The math that you have gone trough so far dont really help with this step.&#xD;&#xA;&#xD;&#xA;\* It is hard to generalize somebody might be doing this but i wouldnt because its a waste of my time." ContentLicense="CC BY-SA 4.0" />
  <row Id="35239" PostHistoryTypeId="5" PostId="12289" RevisionGUID="869dcdb5-6699-4229-a439-ebde5b4f206e" CreationDate="2021-10-28T00:07:29.623" UserId="38" Comment="added 118 characters in body" Text="Lets try to reign stuff in a bit. In practical applications we do not deal with infinites. Because that would mean we would need to use some kind of symbolic solver for all of our stuff. We couldnt afford to do this in many practical applications.&#xD;&#xA;&#xD;&#xA;Because of these practical considerations i need to have a near and far plane for my camera rasterizer. If i were to make some kind of vector graphics i most likely wouldnt have infinite objects (or atleast deal with this in the scenegraph) and if we would do some sort of tracing we would have hard time deducing intersections near infinity.&#xD;&#xA;&#xD;&#xA;Also because of practical considerations, we do not generally \* turn the data into 2D coordinates. What we conceptually do is we transform the points so that they seem like something that looks like a perspective projection from a paralell projection in our z direction. We then use this view  to build out the data that we need. During this building process we are free to discard any data that we dont need. So think of this like a preliminarry sorting so that i can really do what i intended easily. &#xD;&#xA;&#xD;&#xA;Now usually we have acess to both the transformed data and untransformed data so that being terribly concerned about deducing something from the projection, that we can simply read it from the 3D space directly or from our scene graph for that matter, is a priority. But both the z and even the fourth component data could be useful for building my next stage primitives.&#xD;&#xA;&#xD;&#xA;Ok so at this point we are done with projecting and now we can start building our output. But this has nothing to do with any of the math you asked so far. The next stages are about triangle barycentric coordinates, shading, intersection finding, depth sorting etc. The math that you have gone trough so far dont really help with this step.&#xD;&#xA;&#xD;&#xA;\* It is hard to generalize somebody might be doing this but i wouldnt because its a waste of my time.&#xD;&#xA;&#xD;&#xA;PS: theres no need to know where wanishing points lie, since the projection stage has solved both ends of my line." ContentLicense="CC BY-SA 4.0" />
  <row Id="35240" PostHistoryTypeId="5" PostId="12289" RevisionGUID="e765f368-9928-4735-b214-f36cfcb3685a" CreationDate="2021-10-28T00:30:31.433" UserId="38" Comment="added 1 character in body" Text="Lets try to reign stuff in a bit. In practical applications we do not deal with infinites. Because that would mean we would need to use some kind of symbolic solver for all of our stuff. We couldnt afford to do this in many practical applications.&#xD;&#xA;&#xD;&#xA;Because of these practical considerations i need to have a near and far plane for my camera rasterizer. If i were to make some kind of vector graphics i most likely wouldnt have infinite objects (or atleast deal with this in the scenegraph) and if we would do some sort of tracing we would have hard time deducing intersections near infinity.&#xD;&#xA;&#xD;&#xA;Also because of practical considerations, we do not generally \* turn the data into 2D coordinates. What we conceptually do is we transform the points so that they seem like something that looks like a perspective projection from a paralell projection in our z direction. We then use this view  to build out the data that we need. During this building process we are free to discard any data that we dont need. So think of this like a preliminarry sorting so that i can really do what i intended easily. &#xD;&#xA;&#xD;&#xA;Now usually we have acess to both the transformed data and untransformed data so that being terribly concerned about deducing something from the projection, that we can simply read it from the 3D space directly or from our scene graph for that matter, is a priority. But both the z and even the fourth component data could be useful for building my next stage primitives.&#xD;&#xA;&#xD;&#xA;Ok so at this point we are done with projecting and now we can start building our output. But this has nothing to do with any of the math you asked so far. The next stages are about triangle barycentric coordinates, shading, intersection finding, depth sorting etc. The math that you have gone trough so far dont really help with this step.&#xD;&#xA;&#xD;&#xA;\* It is hard to generalize somebody might be doing this but i wouldnt because its a waste of my time.&#xD;&#xA;&#xD;&#xA;PS: theres no need to know where wanishing points lie, since the projection stage has solved both ends of the line." ContentLicense="CC BY-SA 4.0" />
  <row Id="35241" PostHistoryTypeId="5" PostId="12286" RevisionGUID="cb6988f3-571e-4aa0-a420-b4158f646469" CreationDate="2021-10-28T07:02:03.103" UserId="13095" Comment="Fix some grammar and spelling" Text="I synchronized with @David k's [first](https://math.stackexchange.com/questions/4285168/difference-between-parallel-projection-and-perspective-projection) and [second](https://math.stackexchange.com/questions/4288470/special-cases-of-perspective-projection) answer regarding perspective and parallel projection. From the first question I understand that the image on the screen is typically described in horizontal and vertical coordinates, that is 2D points. But from the second question, I understand that images on the screen are realistic if they use perspective projection which has 3D coordinates. &#xD;&#xA;&#xD;&#xA;My confusion is that how we show the image on the screen with 2D points by perspective projection? &#xD;&#xA;&#xD;&#xA;The point $(x,y,z)$ is projected to position $(x_p,y_p,z_{vp})$ on the view plane. Since the view plane is placed at position $z_{vp}$ along the $z_v$ axis. So when $z_{vp}=0$ projectors (projection vectors) do not converge towards a projection reference point in parallel projection. But in perspective projection, when $z_{vp}=0$, it is reduced to parallel projection, but the projectors converge at the centre of projection. Am I correct above these concepts? &#xD;&#xA;&#xD;&#xA;The vanishing point in perspective projection which is 3D coordinates could be represented in the projective plane as $(x, y, z, 0).$ Am I correct? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35242" PostHistoryTypeId="5" PostId="12289" RevisionGUID="e144ceae-1832-4984-a368-65aad146e922" CreationDate="2021-10-28T07:10:48.553" UserId="13095" Comment="Fix some grammar and spelling" Text="Let's try to reign stuff in a bit. In practical applications, we do not deal with infinites. Because that would mean we would need to use some kind of symbolic solver for all of our stuff. We couldn't afford to do this in many practical applications.&#xD;&#xA;&#xD;&#xA;Because of these practical considerations, I need to have a near and far plane for my camera rasterizer. If I were to make some kind of vector graphics I most likely wouldn't have infinite objects (or at least deal with this in the scenegraph) and if we would do some sort of tracing we would have a hard time deducing intersections near infinity.&#xD;&#xA;&#xD;&#xA;Also because of practical considerations, we do not generally \* turn the data into 2D coordinates. What we conceptually do is transform the points so that they seem like something that looks like a perspective projection from a parallel projection in our z-direction. We then use this view to build out the data that we need. During this building process, we are free to discard any data that we don't need. So think of this as a preliminary sorting so that I can really do what I intended easily. &#xD;&#xA;&#xD;&#xA;Now usually we have access to both the transformed data and untransformed data so that being terribly concerned about deducing something from the projection, that we can simply read it from the 3D space directly or from our scene graph for that matter, is a priority. But both the z and even the fourth component data could be useful for building my next stage primitives.&#xD;&#xA;&#xD;&#xA;Ok so at this point we are done with projecting and now we can start building our output. But this has nothing to do with any of the math you asked so far. The next stages are about triangle barycentric coordinates, shading, intersection finding, depth sorting, etc. The math that you have gone through so far doesn't really help with this step.&#xD;&#xA;&#xD;&#xA;\* It is hard to generalize somebody might be doing this but I wouldn't because it's a waste of my time.&#xD;&#xA;&#xD;&#xA;PS: there's no need to know where vanishing points lie since the projection stage has solved both ends of the line." ContentLicense="CC BY-SA 4.0" />
  <row Id="35243" PostHistoryTypeId="5" PostId="12282" RevisionGUID="6dfaa7ec-6ce4-49ad-a3b5-a6a65523e479" CreationDate="2021-10-28T07:25:40.247" UserId="13095" Comment="Fix some grammar and spelling" Text="We know that world coordinates $(x_w, y_w)$ transform to viewport coordinates $(x_v, y_v)$ which are the physical device coordinates. And during projection, any point $(x, y, z)$ projects to $(x, y)$ onto the projection plane. My question is: Are projection and transformation both the same? &#xD;&#xA;Please explain it with a small example. I want to understand intuition rather than details proof. " ContentLicense="CC BY-SA 4.0" />
  <row Id="35244" PostHistoryTypeId="2" PostId="12290" RevisionGUID="3c00075d-fc96-4f93-a9db-492e763b4cfd" CreationDate="2021-10-28T11:45:08.990" UserDisplayName="user17337" Text="**2D transformation and viewing:**&#xD;&#xA;The camera projects the 2D world co-ordinate $(x_w, y_w)$ on its projection plane which co-ordinates $(x_v, y_v)$.&#xD;&#xA;&#xD;&#xA;**3D transformation and viewing:**&#xD;&#xA;The camera projects the 3D world co-ordinate $(x_w, y_w, z_w)$ on its projection plane which co-ordinates $(x_v, y_v, z_v)$.Then $(x_v, y_v, z_v)$ can be transforms to $(x_v, y_v)$ of display device coordinates. &#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;$A.$ In **2D transformation and viewing** projection plane is 2D means it has 2 dimensions height and width. But I am confused projection plane which is a plane (2D) has equation is of the form $ax+by+cz+d=0.$ But here $z$ coordinate is missing, so how will it be plane? &#xD;&#xA;&#xD;&#xA;In contrast 3D has projection plane  means it has 3 dimensions height, width and depth. But we know that 2D plane $ax+by+cz+d=0.$ But how we're saying 3D?&#xD;&#xA;I am struggling to differentiate projection plane and dimensions. What I have misunderstood in the concepts of both cases? &#xD;&#xA;&#xD;&#xA;$B.$ In **2D transformation and viewing** how world co-ordinate $(x_w, y_w)$  is 2D? Because we know real world is 3D." ContentLicense="CC BY-SA 4.0" />
  <row Id="35246" PostHistoryTypeId="1" PostId="12290" RevisionGUID="3c00075d-fc96-4f93-a9db-492e763b4cfd" CreationDate="2021-10-28T11:45:08.990" UserDisplayName="user17337" Text="Difference between 2D and 3D pipeline" ContentLicense="CC BY-SA 4.0" />
  <row Id="35247" PostHistoryTypeId="3" PostId="12290" RevisionGUID="3c00075d-fc96-4f93-a9db-492e763b4cfd" CreationDate="2021-10-28T11:45:08.990" UserDisplayName="user17337" Text="|3d|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35248" PostHistoryTypeId="50" PostId="10919" RevisionGUID="ea022d66-8aa5-4312-93ea-2429a81d669f" CreationDate="2021-10-28T12:07:50.770" UserId="-1" />
  <row Id="35249" PostHistoryTypeId="2" PostId="12291" RevisionGUID="84f78fb9-5fc2-45c1-9066-4706696dd5de" CreationDate="2021-10-28T14:16:53.187" UserId="5574" Text="There are various options, even with OpenGL 3.3 (over a decade old), that will depend hardware factors, GPU, bus, etc., the driver-specific implementations, and finally, the sort of access patterns and frequency of updates to the VBO that the application will be making.&#xD;&#xA;&#xD;&#xA;I'm not entirely clear what you are thinking in terms of when and how a vertex array object 'knows' it's out of date. The VAO has attribute array bindings to specific buffers - and when the application modifies a VBO, it does so through the GL API. Therefore, the GL is forced to synchronize these updates - and that means potentially stalling the pipeline, which is a [problem](https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem). And because it's a complex problem, there are several solutions.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The first is just to call [`glBufferData`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml) again, and replace the data. That might be fine for infrequent changes or small buffers - again, it's too hard to give a one-size-fits-all solution.&#xD;&#xA;&#xD;&#xA;A better strategy in a lot of cases is 'orphaning'. Effectively, call `glBufferData` again, but this time with `data = NULL`. This can be very effective, because the GL knows it doesn't have to retain that data. There is still some cost in calling `glBufferData` or [`glBufferSubData`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetBufferSubData.xhtml) - this time with *actual* data; but it doesn't need to synchronize waiting for a partial update.&#xD;&#xA;&#xD;&#xA;VBOs have been around since OpenGL 1.5, so it's a well-established technique that drivers have optimized for a long time. It's relatively simple to implement, and tends to have good results. In most VBO update code I've written, it tends to perform well over a wide range of platforms.&#xD;&#xA;&#xD;&#xA;There the idea of 'ping-pong' buffers (alternating VBOs). Update a buffer not currently in use, while another is being used as a source. When a frame is finished, swap the VBOs used for a particular vertex attribute stream. I don't know how effective this is with more recent GPUs.&#xD;&#xA;&#xD;&#xA;As an alternative approach, there's [`glMapBuffer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBuffer.xhtml), and the corresponding [`glUnmapBuffer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUnmapBuffer.xhtml). The driver is responsible for presenting the VBO data in a (modifiable) region of memory for the application. When the application has updated the data, the 'unmap' call updates the VBO. There are obvious issues with DMA transfers to and from GPU memory. The GL is effectively stalled - the VBO can't be used without generating errors - until the memory is unmapped.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Then there are ['ranged'](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml) buffer updates, with finer control over synchronization. To be honest, I'm getting out of my depth at this point, and the [link](https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem) I referenced earlier provides a better background than I can.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35251" PostHistoryTypeId="5" PostId="12291" RevisionGUID="010354b5-c37f-45be-9d44-14367e85fb0a" CreationDate="2021-10-28T14:21:53.703" UserId="5574" Comment="added 5 characters in body" Text="There are various options, even with OpenGL 3.3 (over a decade old), that will depend on hardware factors, GPU, bus, etc., the driver-specific implementations, and finally, the sort of access patterns and frequency of updates to the VBO that the application will be making.&#xD;&#xA;&#xD;&#xA;I'm not entirely clear what you are thinking in terms of when and how a vertex array object 'knows' it's out of date. The VAO has attribute array bindings to specific buffers - and when the application modifies a VBO, it does so through the GL API. Therefore, the GL is forced to synchronize these updates - and that means potentially stalling the pipeline, which is a [problem](https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem). And because it's a complex problem, there are several solutions...&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The first is just to call [`glBufferData`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml) again, and replace the data. That might be fine for infrequent changes or small buffers - again, it's too hard to give a one-size-fits-all solution.&#xD;&#xA;&#xD;&#xA;A better strategy in a lot of cases is 'orphaning'. Effectively, call `glBufferData` again, but this time with `data = NULL`. This can be very effective, because the GL knows it doesn't have to retain that data. There is still some cost in calling `glBufferData` or [`glBufferSubData`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetBufferSubData.xhtml) - this time with *actual* data; but it doesn't need to synchronize waiting for a partial update.&#xD;&#xA;&#xD;&#xA;VBOs have been around since OpenGL 1.5, so it's a well-established technique that drivers have optimized for a long time. It's relatively simple to implement, and tends to have good results. In most VBO update code I've written, it tends to perform well over a wide range of platforms.&#xD;&#xA;&#xD;&#xA;There's the idea of 'ping-pong' buffers (alternating VBOs). Update a buffer not currently in use, while another is being used as a source. When a frame is finished, swap the VBOs used for a particular vertex attribute stream. I don't know how effective this is with more recent GPUs.&#xD;&#xA;&#xD;&#xA;As an alternative approach, there's [`glMapBuffer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBuffer.xhtml), and the corresponding [`glUnmapBuffer`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUnmapBuffer.xhtml). The driver is responsible for presenting the VBO data in a (modifiable) region of memory for the application. When the application has updated the data, the 'unmap' call updates the VBO. There are obvious issues with DMA transfers to and from GPU memory. The GL is effectively stalled - the VBO can't be used without generating errors - until the memory is unmapped.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Then there are ['ranged'](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMapBufferRange.xhtml) buffer updates, with finer control over synchronization. To be honest, I'm getting out of my depth at this point, and the [link](https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming#The_problem) I referenced earlier provides a better background than I can.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35252" PostHistoryTypeId="5" PostId="12290" RevisionGUID="6347ccb8-fd8b-4fa7-9478-5009ae0aa93d" CreationDate="2021-10-28T15:00:36.393" UserDisplayName="user17337" Comment="added 395 characters in body" Text="**2D transformation and viewing:**&#xD;&#xA;The camera projects the 2D world co-ordinate $(x_w, y_w)$ on its projection plane which co-ordinates $(x_v, y_v)$.&#xD;&#xA;&#xD;&#xA;**3D transformation and viewing:**&#xD;&#xA;The camera projects the 3D world co-ordinate $(x_w, y_w, z_w)$ on its projection plane which co-ordinates $(x_v, y_v, z_v)$.Then $(x_v, y_v, z_v)$ can be transforms to $(x_v, y_v)$ of display device coordinates. &#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;&#xD;&#xA;$A.$ In **2D transformation and viewing** projection plane is 2D means it has 2 dimensions height and width. But I am confused projection plane which is a plane (2D) has equation is of the form $ax+by+cz+d=0.$ But here $z$ coordinate is missing, so how will it be plane? &#xD;&#xA;&#xD;&#xA;In contrast 3D has projection plane  means it has 3 dimensions height, width and depth. But we know that 2D plane $ax+by+cz+d=0.$ But how we're saying 3D?&#xD;&#xA;I am struggling to differentiate projection plane and dimensions. What I have misunderstood in the concepts of both cases? &#xD;&#xA;&#xD;&#xA;$B.$ In **2D transformation and viewing** how world co-ordinate $(x_w, y_w)$  is 2D? Because we know real world is 3D.&#xD;&#xA;&#xD;&#xA;$C. $ In perspective projection how we will represents vanishing point coordinates in projection plane? For example I catch one image of railway tracks where two parallel lines intersects. During projection what could be it's world co-ordinate and projection plane coordinates respectively? It's normal form of projection from $(x_w, y_w, z_w)$ to $(x_p, y_p,z_{vp})$ in projection plane? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35253" PostHistoryTypeId="2" PostId="12292" RevisionGUID="a24e7fc2-ed6c-4018-b392-a4d650ff56d1" CreationDate="2021-10-28T15:17:51.357" UserId="17440" Text="I was looking to implement SSAO; demonstrated on learnopeng (https://learnopengl.com/Advanced-Lighting/SSAO). While I have implemented the way they have done it i.e using a position texture for positions and normal texture... I was looking to re-implement it using the depth buffer for positions &amp; normals.&#xD;&#xA;&#xD;&#xA;I have obtained my positions from the depth buffer and stored them in a vec3 as shown below:&#xD;&#xA;&#xD;&#xA;    vec3 computeViewPosFromDepth(vec2 texcoords) {&#xD;&#xA;    &#xD;&#xA;       float depth = texture(depthMap, vec2(1.0 - uvCoords.x, uvCoords.y)).x;&#xD;&#xA;&#xD;&#xA;       vec4 clipSpace = vec4(vec2(1.0 - uvCoords.x, uvCoords.y) * 2.0 - 1.0, depth, 1.0);&#xD;&#xA;       vec4 viewSpace = inverse(camera.proj) * clipSpace;&#xD;&#xA;       return viewSpace.xyz /= viewSpace.w;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // contains my positions&#xD;&#xA;    vec3 positions = computeViewPosFromDepth(vec2(1.0 - uvCoords.x, uvCoords.y));&#xD;&#xA;&#xD;&#xA;but when it comes to sampling the depth value of my sample position I can no longer do the following:&#xD;&#xA;&#xD;&#xA;    float sampleDepth = texture(gPosition, offset.xy).z; &#xD;&#xA;&#xD;&#xA;i.e not use texture()&#xD;&#xA;&#xD;&#xA;I am wondering how else I could go about obtainig the depth value of my sample position, given that my positions are from the depth buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="35255" PostHistoryTypeId="1" PostId="12292" RevisionGUID="a24e7fc2-ed6c-4018-b392-a4d650ff56d1" CreationDate="2021-10-28T15:17:51.357" UserId="17440" Text="Obtaining sample position z value when using positions from depth buffer for SSAO" ContentLicense="CC BY-SA 4.0" />
  <row Id="35256" PostHistoryTypeId="3" PostId="12292" RevisionGUID="a24e7fc2-ed6c-4018-b392-a4d650ff56d1" CreationDate="2021-10-28T15:17:51.357" UserId="17440" Text="|glsl|z-buffer|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35257" PostHistoryTypeId="2" PostId="12293" RevisionGUID="e3e89512-6211-47ca-b059-b519fc1c33a9" CreationDate="2021-10-28T16:56:27.723" UserId="2654" Text="There is a great deal of literalism in your understanding of concepts.&#xD;&#xA;&#xD;&#xA;A &quot;world coordinate&quot; is a term for a coordinate that is in the space you have designated to represent &quot;the world&quot;. Whatever that means to your application. Different objects may have different native coordinate systems, but they will be transformed into a common coordinate system, of which you will render some subsection of. We call that coordinate system &quot;world coordinates&quot;.&#xD;&#xA;&#xD;&#xA;That's it. That's what it means. It doesn't really have anything to do with &quot;the world&quot; in any literal sense.&#xD;&#xA;&#xD;&#xA;It can be whatever numerical coordinate system works best for your needs. It can have however many dimensions you feel comfortable giving it.&#xD;&#xA;&#xD;&#xA;Similarly, look at your 2D/3D confusion. What is &quot;2D&quot;? If all of your 3D coordinates and transformations and the like all have a Z of zero, is that not exactly equivalent to &quot;2D&quot;?&#xD;&#xA;&#xD;&#xA;Any X-dimension is a special-case of the X+1-dimension where the +1 coordinate is 0 and is unchanged by any transformations. So if it makes you feel more comfortable to think of 2D as 3D with a zero Z, where you're projecting these &quot;3D&quot; coordinates onto a plane at zero Z perpendicular to the Z axis, then you can do that and the math still works out.&#xD;&#xA;&#xD;&#xA;But really, you should just think of it as 2D. If the source and destination dimensions of your transformation are the same, then it's not a projection. It's just a generic transformation." ContentLicense="CC BY-SA 4.0" />
  <row Id="35260" PostHistoryTypeId="5" PostId="12285" RevisionGUID="7980808e-4fa8-4ba4-89f7-94c9c9f7faa5" CreationDate="2021-10-29T08:24:24.287" UserId="13273" Comment="added 426 characters in body" Text="I found a very nice paper regarding [Time Interval Ray Tracing for Motion Blur][1] published in 2017. That was before RTX GPUs were on the market.&#xD;&#xA;I have a few questions about an optimal implementation and its performance.&#xD;&#xA;&#xD;&#xA;**Short introduction:**&#xD;&#xA;I'm using the Vulkan api to raytrace outer space scenarios, like spacecraft docking scenarios. So the scenario has only one till max 10 spacecrafts, which are close enough to be visible. Each spacecraft is very detailed. It is optimized to only have the outer shell, so they have no geometry inside. The spacecraft geometries has up to 50.000 triangles each. And the scenario should be rendered in real-time (hopefully 60 fps). &#xD;&#xA;&#xD;&#xA;**Problem**: So when using the Motion Blur algorithm linked above, The number of triangles will increase to factor *3 when only using two keyframes. These new triangles and their position / orientation will change from frame to frame. And each frame I have to store the new triangles to the Bottom-Level-Acceleration-Structure (BLAS). Do you guys see a performance problem here?&#xD;&#xA;So the idea is to use the render pipeline (from vertex- till geometry- shader) to create the 4D (3D + time) geometry on GPU. Rotations are the most problematic transformations. To have a good rotational movement, the number of keyframes need to be increased depending on the rotational speed and the exposure time. I think these keyframes need to be split into several BLAS (one BLAS for each keyframe transformation).&#xD;&#xA;&#xD;&#xA;In case to fill the BLAS is no performance problem, I think the next problem could be to fire rays.&#xD;&#xA;When having fast camera movements or fast translating spacecrafts, a ray could hit a lot of primitives (triangles). Is this a performance problem? Usually the scenario is very simple.&#xD;&#xA; We are trying to generate the output image as realistic as possible, so the different blending functions are extremely interesting for us. &#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA; 1. How performant is filling the BLAS? (I thought about refitting acceleration structures, because the number of primitives will not change)&#xD;&#xA; 2. Is it better to use several BLAS for the same objekt in case of faster rotations and therefore several keyframes?&#xD;&#xA; 3. How performant is firing the rays?&#xD;&#xA; 4. Do I have enough performance to fire even more rays? Shadow rays, reflection / refraction rays, Photon mapping rays?&#xD;&#xA; 5. Did someone even tested the algorithm with a newer RTX graphics card? (For this project we will use a NVIDIA RTX3080)&#xD;&#xA; 6. Do you know other techniques which better fit to our scenario for real-time?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I added this self made image, just to show how I think this algorithm works... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;When having both intersection point of a triangle, I can calculate the UV-coordinates and do texture lookup do get a very good motion blur effect. With this technology I can implement all kind of shutter for my simulated physical camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cemyuksel.com/research/papers/time_interval_ray_tracing_for_motion_blur-high.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/V8HHn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35261" PostHistoryTypeId="5" PostId="12285" RevisionGUID="1f33628e-b4cd-4add-ac42-4cf66df12d1e" CreationDate="2021-10-29T08:35:22.233" UserId="13273" Comment="added 1 character in body" Text="I found a very nice paper regarding [Time Interval Ray Tracing for Motion Blur][1] published in 2017. That was before RTX GPUs were on the market.&#xD;&#xA;I have a few questions about an optimal implementation and its performance.&#xD;&#xA;&#xD;&#xA;**Short introduction:**&#xD;&#xA;I'm using the Vulkan api to raytrace outer space scenarios, like spacecraft docking scenarios. So the scenario has only one till max 10 spacecrafts, which are close enough to be visible. Each spacecraft is very detailed. It is optimized to only have the outer shell, so they have no geometry inside. The spacecraft geometries has up to 50.000 triangles each. And the scenario should be rendered in real-time (hopefully 60 fps). &#xD;&#xA;&#xD;&#xA;**Problem**: So when using the Motion Blur algorithm linked above, The number of triangles will increase to factor *3 when only using two keyframes. These new triangles and their position / orientation will change from frame to frame. And each frame I have to store the new triangles to the Bottom-Level-Acceleration-Structure (BLAS). Do you guys see a performance problem here?&#xD;&#xA;So the idea is to use the render pipeline (from vertex- till geometry- shader) to create the 4D (3D + time) geometry on GPU. Rotations are the most problematic transformations. To have a good rotational movement, the number of keyframes need to be increased depending on the rotational speed and the exposure time. I think these keyframes need to be split into several BLAS (one BLAS for each keyframe transformation).&#xD;&#xA;&#xD;&#xA;In case to fill the BLAS is no performance problem, I think the next problem could be to fire rays.&#xD;&#xA;When having fast camera movements or fast translating spacecrafts, a ray could hit a lot of primitives (triangles). Is this a performance problem? Usually the scenario is very simple.&#xD;&#xA; We are trying to generate the output image as realistic as possible, so the different blending functions are extremely interesting for us. &#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA; 1. How performant is filling the BLAS? (I thought about refitting acceleration structures, because the number of primitives will not change)&#xD;&#xA; 2. Is it better to use several BLAS for the same objekt in case of faster rotations and therefore several keyframes?&#xD;&#xA; 3. How performant is firing the rays?&#xD;&#xA; 4. Do I have enough performance to fire even more rays? Shadow rays, reflection / refraction rays, Photon mapping rays?&#xD;&#xA; 5. Did someone even tested the algorithm with a newer RTX graphics card? (For this project we will use a NVIDIA RTX3080)&#xD;&#xA; 6. Do you know other techniques which better fit to our scenario for real-time?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I added this self made image, just to show how I think this algorithm works... &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;When having both intersection points of a triangle, I can calculate the UV-coordinates and do texture lookup do get a very good motion blur effect. With this technology I can implement all kind of shutter for my simulated physical camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cemyuksel.com/research/papers/time_interval_ray_tracing_for_motion_blur-high.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/V8HHn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35271" PostHistoryTypeId="2" PostId="12295" RevisionGUID="6e4badbf-376a-4a67-a7ba-057e05efef07" CreationDate="2021-10-30T02:04:09.180" UserId="17445" Text="Screen space ambient occlusion&#xD;&#xA;&#xD;&#xA;https://learnopengl.com/Advanced-Lighting/SSAO&#xD;&#xA;&quot;Because the sample kernel used was a **sphere, it caused flat walls to look gray** as half of the kernel samples end up being in the surrounding geometry.&quot;&#xD;&#xA;&#xD;&#xA;So, flat walls are 0.5, wall corners are 0.25. By **multiplying 2, they become 1.0 and 0.5** that should be correct. The question is, **why didn't this simple &quot;multiplying 2&quot; become a viable solution to the problem?**&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="35273" PostHistoryTypeId="1" PostId="12295" RevisionGUID="6e4badbf-376a-4a67-a7ba-057e05efef07" CreationDate="2021-10-30T02:04:09.180" UserId="17445" Text="Can CryTek SSAO's gray feel be improved simply by multiplying 2?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35274" PostHistoryTypeId="3" PostId="12295" RevisionGUID="6e4badbf-376a-4a67-a7ba-057e05efef07" CreationDate="2021-10-30T02:04:09.180" UserId="17445" Text="|ambient-occlusion|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35275" PostHistoryTypeId="2" PostId="12296" RevisionGUID="fd6e97cd-4719-4499-bd80-684428cd1aa4" CreationDate="2021-10-30T11:39:06.303" UserDisplayName="user17337" Text="Shearing in $X$ axis is achieved by using the following shearing equations-&#xD;&#xA;&#xD;&#xA;$X_{new} = X_{old}, &#xD;&#xA;Y_{new} = Y_{old} + Sh_y × X_{old}, &#xD;&#xA;Z_{new} = Z_{old} + Sh_z × X_{old}.$&#xD;&#xA;&#xD;&#xA;My question is during $Y_{new}$ and $Z_{new}$ calculations why $Sh_y,Sh_z$ is multiplying with $X_{old}$ respectively, why not any other constant? Every books, websites mention just formula not the reason. &#xD;&#xA;&#xD;&#xA;Can anyone give pictorial representations how shearing is happening with explanation. &#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="35277" PostHistoryTypeId="1" PostId="12296" RevisionGUID="fd6e97cd-4719-4499-bd80-684428cd1aa4" CreationDate="2021-10-30T11:39:06.303" UserDisplayName="user17337" Text="3D shearing w. r. t $x$-axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="35278" PostHistoryTypeId="3" PostId="12296" RevisionGUID="fd6e97cd-4719-4499-bd80-684428cd1aa4" CreationDate="2021-10-30T11:39:06.303" UserDisplayName="user17337" Text="|3d|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35279" PostHistoryTypeId="5" PostId="12295" RevisionGUID="4cca4661-b191-4f21-ae24-12b07882014a" CreationDate="2021-10-30T13:46:44.030" UserId="17445" Comment="added 15 characters in body" Text="Screen space ambient occlusion&#xD;&#xA;&#xD;&#xA;https://learnopengl.com/Advanced-Lighting/SSAO&#xD;&#xA;&quot;Because the sample kernel used was a **sphere, it caused flat walls to look gray** as half of the kernel samples end up being in the surrounding geometry.&quot;&#xD;&#xA;&#xD;&#xA;So, flat walls are 0.5, wall corners are 0.25. By **multiplying 2, they become 1.0 and 0.5** that should be correct. The question is, **why didn't they think of this simple &quot;multiplying 2&quot; when the original algorithm was released?**&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="35280" PostHistoryTypeId="2" PostId="12297" RevisionGUID="59091c49-5c57-4c37-83d7-3a0563bd7cc4" CreationDate="2021-10-30T23:24:16.163" UserId="7462" Text="I am trying to determine if and when flipping an edge is topologically valid.&#xD;&#xA;&#xD;&#xA;The current criterion I have is that it is only valid if there is no edge connecting the opposite vertices of the edge.&#xD;&#xA;&#xD;&#xA;I.e. consider these 2 drawings where the first allows for a valid edge flip but the second does not.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nKy3p.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35282" PostHistoryTypeId="1" PostId="12297" RevisionGUID="59091c49-5c57-4c37-83d7-3a0563bd7cc4" CreationDate="2021-10-30T23:24:16.163" UserId="7462" Text="Half Edge criterion to check if an edge flip is illegal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35283" PostHistoryTypeId="3" PostId="12297" RevisionGUID="59091c49-5c57-4c37-83d7-3a0563bd7cc4" CreationDate="2021-10-30T23:24:16.163" UserId="7462" Text="|mathematics|computational-geometry|geometry|half-edge|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35284" PostHistoryTypeId="5" PostId="12295" RevisionGUID="01d34e26-2f84-49e5-8f24-7b85d9eba5c8" CreationDate="2021-10-31T00:53:53.017" UserId="17445" Comment="added 302 characters in body; edited title" Text="Screen space ambient occlusion&#xD;&#xA;&#xD;&#xA;https://learnopengl.com/Advanced-Lighting/SSAO&#xD;&#xA;&quot;Because the sample kernel used was a **sphere, it caused flat walls to look gray** as half of the kernel samples end up being in the surrounding geometry.&quot;&#xD;&#xA;&#xD;&#xA;OK, let me assume the following facts:&#xD;&#xA;&#xD;&#xA; - There is no absolute correctness in AO.&#xD;&#xA; - I am not talking about the later improvement of using hemi-sphere kernel.&#xD;&#xA;&#xD;&#xA;So, flat walls are 0.5, wall corners are 0.25. By **multiplying 2, they become 1.0 and 0.5** that obviously should be more correct. The question is, **why didn't they think of this simple &quot;multiplying 2&quot; when the original algorithm was released?**&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;&#xD;&#xA;RTR4: “edges being brighter than their surroundings”. Edges were 0.75, by x2 and clamping to 1.0 they would be the more correct 1.0." ContentLicense="CC BY-SA 4.0" />
  <row Id="35285" PostHistoryTypeId="4" PostId="12295" RevisionGUID="01d34e26-2f84-49e5-8f24-7b85d9eba5c8" CreationDate="2021-10-31T00:53:53.017" UserId="17445" Comment="added 302 characters in body; edited title" Text="Why wasn't CryTek SSAO multiplied by 2?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35286" PostHistoryTypeId="2" PostId="12298" RevisionGUID="927f56f6-ca62-40ba-bbac-33d0c16c658e" CreationDate="2021-10-31T06:35:25.410" UserId="17445" Text="1 possible answer from RTR4:&#xD;&#xA;&quot;Doing so causes a **flat surface to be darkened**, with **edges being brighter than their surroundings**. Nonetheless, the results are **often visually pleasing**.&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35288" PostHistoryTypeId="2" PostId="12299" RevisionGUID="6cf6cdb7-2291-46af-b3b4-720f623c49aa" CreationDate="2021-10-31T11:11:22.610" UserId="10096" Text="Ambient occlusion is the direct illumination at a Lambertian surface point due to a homogeneous light source at infinity. That means that you assume a light source with $L_e(\pm\infty, \omega_i) = 1$, and a fully reflective (energy conserving) Lambertian [brdf][1] $f(\omega_o, x, \omega_i) = \frac{1}{\pi}$. Intuitively this is is like putting your object inside an emissive sphere, and computing the illumination at every surface point due to direct illumination (ignoring illumination from later bounces). Formally it is a simplification of [the rendering equation][2]:&#xD;&#xA;&#xD;&#xA;$$\require{cancel} L = L_e + TL = L_e + TL_e + T^2L \approx L_e + TL_e + \cancel{T^2L}$$&#xD;&#xA;&#xD;&#xA;What ambient occlusion is computing is this $TL_e$ term with the discussed $L_e$ and brdf. The $TL_e$ term is of the form:&#xD;&#xA;&#xD;&#xA;$$(TL_e)(x, \omega_o) = \int_{\Omega_{N_x}}f(\omega_o, x, \omega_i)L_e(r(x,\omega_i), -\omega_i)(N_x \cdot\omega_i)d\omega_i$$ &#xD;&#xA;$$= \frac{1}{\pi}\int_{\Omega_{N_x}}(N_x \cdot\omega_i)V_{x, \omega_i}\,d\omega_i,$$&#xD;&#xA;&#xD;&#xA;where $N_x$ is the unit normal at $x$, $\Omega_{N_x}$ is the upper hemisphere centered around $N_{x}$, $r(x,\omega_i)$ is the ray-tracing function. I have used in the second equality that $f(\omega_o, x, \omega_i) = \frac{1}{\pi}$, and $L_e(\pm\infty, \omega_i) = 1$, where $V_{x,\omega_i}$ is one if the ray with origin $x$ and direction $\omega_i$ intersects nothing, and zero otherwise.&#xD;&#xA;&#xD;&#xA;The ambient occlusion term is cheaper to compute than a full-blown light transport simulation with multiple bounces and varying light sources, while at the same time providing a somewhat convincing shading and visual cues for the geometry of an object. For this reason it is often considered in real-time graphics, with various approximations of it (e.g. integration based on information from the depth buffer with a range-limited $V_{x, \omega_i}$ term). Note however that the integration happens over the upper hemisphere centered around the normal: $\Omega_{N_x}$, and not over the whole sphere (an integration over the full sphere would consider transmitting materials and various things would need to be adjusted). The integration over the whole sphere present in Crytek's SSAO is a mistake that can be easily rectified by considering the normal of the fragment being shaded (as many follow-up SSAO implementations do). A multiplication by 2 is linear, and thus doesn't change the relative appearance between two nearby pixels. Consider the scenario where pixel A has ambient occlusion value $c_A$ and pixel B has ambient occlusion value $c_B$, then if we multiply those by $k/ne 0$ the ratio remains the same: &#xD;&#xA;&#xD;&#xA;$$\frac{c'_A}{c'_B} = \frac{kc_A}{kc_B} = \frac{c_A}{c_B}.$$&#xD;&#xA;&#xD;&#xA;Considering that visual shading cues are relative, the above is not very useful, and amounts to rescaling the brdf in the ambient occlusion - it doesn't correct for the incorrect integration domain.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="35290" PostHistoryTypeId="5" PostId="12299" RevisionGUID="91116150-8c0d-4d3e-b52c-6cde706d444e" CreationDate="2021-10-31T11:16:26.130" UserId="10096" Comment="added 22 characters in body" Text="Ambient occlusion is the direct illumination at a Lambertian surface point due to a homogeneous light source at infinity. That means that you assume a light source with $L_e(\pm\infty, \omega_i) = 1$, and a fully reflective (energy conserving) Lambertian [brdf][1] $f(\omega_o, x, \omega_i) = \frac{1}{\pi}$. Intuitively this is is like putting your object inside an emissive sphere, and computing the illumination at every surface point due to direct illumination (ignoring illumination from later bounces). Formally it is a simplification of [the rendering equation][2]:&#xD;&#xA;&#xD;&#xA;$$\require{cancel} L = L_e + TL = L_e + TL_e + T^2L \approx L_e + TL_e + \cancel{T^2L}$$&#xD;&#xA;&#xD;&#xA;What ambient occlusion is computing is this $TL_e$ term with the discussed $L_e$ and brdf. The $TL_e$ term is of the form:&#xD;&#xA;&#xD;&#xA;$$(TL_e)(x, \omega_o) = \int_{\Omega_{N_x}}f(\omega_o, x, \omega_i)L_e(r(x,\omega_i), -\omega_i)(N_x \cdot\omega_i)d\omega_i$$ &#xD;&#xA;$$= \frac{1}{\pi}\int_{\Omega_{N_x}}(N_x \cdot\omega_i)V_{x, \omega_i}\,d\omega_i,$$&#xD;&#xA;&#xD;&#xA;where $N_x$ is the unit normal at $x$, $\Omega_{N_x}$ is the upper hemisphere centered around $N_{x}$, $r(x,\omega_i)$ is the ray-tracing function. I have used in the second equality that $f(\omega_o, x, \omega_i) = \frac{1}{\pi}$, and $L_e(\pm\infty, \omega_i) = 1$, where $V_{x,\omega_i}$ is one if the ray with origin $x$ and direction $\omega_i$ intersects nothing, and zero otherwise.&#xD;&#xA;&#xD;&#xA;The ambient occlusion term is cheaper to compute than a full-blown light transport simulation with multiple bounces and varying light sources, while at the same time providing a somewhat convincing shading and visual cues for the geometry of an object. For this reason it is often considered in real-time graphics, with various approximations of it (e.g. integration based on information from the depth buffer with a range-limited $V_{x, \omega_i}$ term). Note however that the integration happens over the upper hemisphere centered around the normal: $\Omega_{N_x}$, and not over the whole sphere (integration over the full sphere would consider transmitting materials and various things would need to be adjusted). The integration over the whole sphere present in Crytek's SSAO is a mistake that can be rectified easily by considering the normal of the fragment being shaded (as many follow-up SSAO implementations do). &#xD;&#xA;&#xD;&#xA;As for the suggested solution, consider the following. A multiplication by 2 is linear and thus doesn't change the relative appearance between two nearby pixels. Let pixel A have ambient occlusion value $c_A$ and pixel B have ambient occlusion value $c_B$, then if we multiply those by $k\ne 0$ the ratio remains the same: &#xD;&#xA;&#xD;&#xA;$$\frac{c'_A}{c'_B} = \frac{kc_A}{kc_B} = \frac{c_A}{c_B}.$$&#xD;&#xA;&#xD;&#xA;Since visual shading cues are relative, the above is not very useful, and amounts to rescaling the brdf in the ambient occlusion - it doesn't correct for the incorrect integration domain.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="35291" PostHistoryTypeId="5" PostId="12299" RevisionGUID="a22dd0af-8a44-4f1f-9e35-5fa4e437de4b" CreationDate="2021-10-31T11:25:01.620" UserId="10096" Comment="added 22 characters in body" Text="[Ambient occlusion][1] is the direct illumination at a Lambertian surface point due to a homogeneous light source at infinity. That means that you assume a light source with $L_e(\pm\infty, \omega_i) = 1$, and a fully reflective (energy conserving) Lambertian [brdf][2] $f(\omega_o, x, \omega_i) = \frac{1}{\pi}$. Intuitively this is is like putting your object inside an emissive sphere, and computing the illumination at every surface point due to direct illumination (ignoring illumination from later bounces). Formally it is a simplification of [the rendering equation][3]:&#xD;&#xA;&#xD;&#xA;$$\require{cancel} L = L_e + TL = L_e + TL_e + T^2L \approx L_e + TL_e + \cancel{T^2L}$$&#xD;&#xA;&#xD;&#xA;What ambient occlusion is computing is this $TL_e$ term with the discussed $L_e$ and brdf. The $TL_e$ term is of the form:&#xD;&#xA;&#xD;&#xA;$$(TL_e)(x, \omega_o) = \int_{\Omega_{N_x}}f(\omega_o, x, \omega_i)L_e(r(x,\omega_i), -\omega_i)(N_x \cdot\omega_i)d\omega_i$$ &#xD;&#xA;$$= \frac{1}{\pi}\int_{\Omega_{N_x}}(N_x \cdot\omega_i)V_{x, \omega_i}\,d\omega_i,$$&#xD;&#xA;&#xD;&#xA;where $N_x$ is the unit normal at $x$, $\Omega_{N_x}$ is the upper hemisphere centered around $N_{x}$, $r(x,\omega_i)$ is the ray-tracing function. I have used in the second equality that $f(\omega_o, x, \omega_i) = \frac{1}{\pi}$, and $L_e(\pm\infty, \omega_i) = 1$, where $V_{x,\omega_i}$ is one if the ray with origin $x$ and direction $\omega_i$ intersects nothing, and zero otherwise.&#xD;&#xA;&#xD;&#xA;The ambient occlusion term is cheaper to compute than a full-blown light transport simulation with multiple bounces and varying light sources, while at the same time providing a somewhat convincing shading and visual cues for the geometry of an object. For this reason it is often considered in real-time graphics, with various approximations of it (e.g. integration based on information from the depth buffer with a range-limited $V_{x, \omega_i}$ term). Note however that the integration happens over the upper hemisphere centered around the normal: $\Omega_{N_x}$, and not over the whole sphere (integration over the full sphere would consider transmitting materials and various things would need to be adjusted). The integration over the whole sphere present in Crytek's SSAO is a mistake that can be rectified easily by considering the normal of the fragment being shaded (as many follow-up SSAO implementations do). &#xD;&#xA;&#xD;&#xA;As for the suggested solution, consider the following. A multiplication by 2 is linear and thus doesn't change the relative appearance between two nearby pixels. Let pixel A have ambient occlusion value $c_A$ and pixel B have ambient occlusion value $c_B$, then if we multiply those by $k\ne 0$ the ratio remains the same: &#xD;&#xA;&#xD;&#xA;$$\frac{c'_A}{c'_B} = \frac{kc_A}{kc_B} = \frac{c_A}{c_B}.$$&#xD;&#xA;&#xD;&#xA;Since visual shading cues are relative, the above is not very useful, and amounts to rescaling the brdf in the ambient occlusion - it doesn't correct for the incorrect integration domain. By all means, you can multiply the SSAO by $2$, but even with clamping this will result in an incorrect solution. The simplest solution is to generate samples in the upper hemisphere by using the normal $N_x$ at the fragment being shaded. This is not a complex modification of the Crytek SSAO either, you just have to reflect the samples that end up in the wrong hemisphere ($N_x \cdot (y-x) &lt;0$) so that they'll end up on the correct side ($N_x \cdot (y-x) \geq 0$).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Ambient_occlusion&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="35294" PostHistoryTypeId="50" PostId="10619" RevisionGUID="274bff8f-bf18-4bfa-906e-c19077309731" CreationDate="2021-10-31T16:02:25.243" UserId="-1" />
  <row Id="35295" PostHistoryTypeId="2" PostId="12301" RevisionGUID="d6952bb5-e051-4e77-916a-08f217cb1a54" CreationDate="2021-10-31T16:33:01.470" UserDisplayName="user17337" Text="Suppose I have one railway track with two lines meets at point say,$X$ at infinity which is theoretical approach.And this X is called vanishing point.But practically  this $X$ doesn't exists. &#xD;&#xA;&#xD;&#xA;My first question is how we can say it doesn't exist, but when we see real image of railway track they intersects at $X?$&#xD;&#xA;&#xD;&#xA;My second question is if it exists then during projection how this $X$ is projects in projection plane?  Is it projecting like normal point projection $(x, y,z)$ to in view plane $(x_p, y_p, z_p)?$" ContentLicense="CC BY-SA 4.0" />
  <row Id="35297" PostHistoryTypeId="1" PostId="12301" RevisionGUID="d6952bb5-e051-4e77-916a-08f217cb1a54" CreationDate="2021-10-31T16:33:01.470" UserDisplayName="user17337" Text="Existence of vanishing point" ContentLicense="CC BY-SA 4.0" />
  <row Id="35298" PostHistoryTypeId="3" PostId="12301" RevisionGUID="d6952bb5-e051-4e77-916a-08f217cb1a54" CreationDate="2021-10-31T16:33:01.470" UserDisplayName="user17337" Text="|3d|transformations|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35299" PostHistoryTypeId="5" PostId="12301" RevisionGUID="607b1402-2d33-43af-b265-c5b86b1839df" CreationDate="2021-10-31T17:04:43.960" UserDisplayName="user17337" Comment="added 185 characters in body" Text="Suppose I have considered example of perspective projection. I have one railway track with two parallel lines meets at point say,$X$ at infinity which is theoretical approach.And this X is called vanishing point.But practically  this $X$ doesn't exists. &#xD;&#xA;&#xD;&#xA;My first question is how we can say it doesn't exist, but when we see real image of railway track they intersects at $X?$&#xD;&#xA;&#xD;&#xA;My second question is if it exists then during projection how this $X$ is projects in projection plane?  Is it projecting like normal point projection $(x, y,z)$ to in view plane $(x_p, y_p, z_p)?$&#xD;&#xA;&#xD;&#xA;N. B- I don't want that answer which is in details manner. I want just intuition which is brief and easy to understand." ContentLicense="CC BY-SA 4.0" />
  <row Id="35300" PostHistoryTypeId="2" PostId="12302" RevisionGUID="0fcc7cf7-141b-4619-a022-e69df5996f85" CreationDate="2021-10-31T20:19:39.380" UserId="7952" Text="In CG the vanishing point can be found computationally by figuring where every pixel on the view plane merges into a single pixel. Imagine a line from every corner of the screen extending out until they touch. That is the vanishing point. It is very literal in computer graphics because no mater what you render beyond that point it will all merge to a single pixel. Now you can move the camera all over the place and that single pixel size block can be anywhere on the screen, it is not unique. But it is still at the vanishing point.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;That is the ideal. In practice the vanishing point is much closer because objects become so small that attempting to render them is more or less pointless.&#xD;&#xA;&#xD;&#xA;How does it exist in the view plane? If you start with the camera looking at a block covering the entire view plane then start moving backward, that block will become smaller and smaller until it is the size of a single pixel. The camera can keep moving back but what's the point?&#xD;&#xA;&#xD;&#xA;Vanishing points in the real world are much more ephemeral as we can get great big telescopes and move them back, we are about to move vanishing points back in the real world even more with the James Web telescope. But in computer graphics the vanishing point is real and can be computed." ContentLicense="CC BY-SA 4.0" />
  <row Id="35302" PostHistoryTypeId="2" PostId="12303" RevisionGUID="3f0c12e6-e128-43a6-8d93-6703604720f0" CreationDate="2021-11-01T01:56:33.580" UserId="38" Text="Vanishing points is a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history its ony one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so its the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image. Indeed you can also use advanced methods to draw fisheye perspectives where straight lines arent straight.&#xD;&#xA;&#xD;&#xA;In 3D it does not exist. There is no single point in the 3D world that would represent a vanishing point. Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. &#xD;&#xA;&#xD;&#xA;Mathematically such a point exist at the limit of a infinite line, but theres no set where they overlap. One can not really say mathematically that the lines intersect. But in pactice theres no difference between a mathematical point and a apparent point. &#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons a imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again like i said earlier any point sufficiently far away from the camera is at the mathematically approximate location of a vanishing point. For all intents and purposes this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of querry? Probably not since this definition would mean that there is lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your question is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep methaphysical question. In some sense its not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, its a concept. There is no contradiction here just different models that have different results. The concept exists, after all it has a wikipedia page, but so does spider man. Real world is like that, lots and lots of conflicting models.&#xD;&#xA;&#xD;&#xA;\* If you havent noticed it is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera or this model?&quot;. Because there is probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35304" PostHistoryTypeId="5" PostId="12303" RevisionGUID="f7c954db-2202-47b5-80e1-c54e1563e58a" CreationDate="2021-11-01T02:01:35.587" UserId="38" Comment="added 58 characters in body" Text="Vanishing points is a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history its only one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so its the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image. Indeed you can also use advanced methods to draw fisheye perspectives where straight lines are nolonger straight.&#xD;&#xA;&#xD;&#xA;In 3D it does not exist. There is no single point in the 3D world that would represent a vanishing point. Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. &#xD;&#xA;&#xD;&#xA;Mathematically such a point exist at the limit of a infinite line, but theres no set where they overlap. One can not really say mathematically that the lines intersect. But in pactice theres no difference between a mathematical point and a apparent point. &#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons a imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again like i said earlier any point sufficiently far away from the camera is at the mathematically approximate location of a vanishing point. For all intents and purposes this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of querry? Probably not since this definition would mean that there is lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your line questioning is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer. Consider asking what you want to achieve instead.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep methaphysical question. In some sense its not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, its a concept. There is no contradiction here just different models that have different results. The concept exists, after all it has a wikipedia page, but so does spider man. Real world is like that, lots and lots of conflicting models.&#xD;&#xA;&#xD;&#xA;\* If you havent noticed it is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera or this model?&quot;. Because there is probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35305" PostHistoryTypeId="5" PostId="12303" RevisionGUID="aa3fb920-7006-40ae-88e9-e3a6478ef55d" CreationDate="2021-11-01T02:08:52.727" UserId="38" Comment="added 43 characters in body" Text="Vanishing points is a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history its only one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so its the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image. Indeed, most other methods work in reverse of vanishing point construction as do 3D graphics.  You can also use advanced methods to draw fisheye perspectives where straight lines are nolonger straight.&#xD;&#xA;&#xD;&#xA;In 3D it does not exist. There is no single point in the 3D world that would represent a vanishing point. Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. &#xD;&#xA;&#xD;&#xA;Mathematically such a point exist at the limit of a infinite line, but theres no set where they overlap. One can not really say mathematically that the lines intersect. But in pactice theres no difference between a mathematical point and a apparent point. &#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons a imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again like i said earlier any point sufficiently far away from the camera in 3D is at the mathematically approximate location of a vanishing point in 2D. For all intents and purposes this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of querry? Probably not since this definition would mean that there is lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your line questioning is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer. Consider asking what you want to achieve instead.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep methaphysical question\**. In some sense its not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, its a concept. There is no contradiction here just different models that have different results. The concept exists, after all it has a wikipedia page, but so does spider man. Real world is like that, lots and lots of conflicting models.&#xD;&#xA;&#xD;&#xA;\* If you havent noticed it is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera or this model?&quot;. Because there is probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;&#xD;&#xA;&#xD;&#xA;\** ask a philosophy.se?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35306" PostHistoryTypeId="5" PostId="12303" RevisionGUID="de1a97c0-aa5a-43e9-a45a-35ac343ad611" CreationDate="2021-11-01T02:22:07.737" UserId="38" Comment="added 253 characters in body" Text="Vanishing points is a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history its only one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so its the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image. Indeed, most other methods work in reverse of vanishing point construction as do 3D graphics.  You can also use advanced methods to draw fisheye perspectives where straight lines are nolonger straight.&#xD;&#xA;&#xD;&#xA;In 3D it does not exist. There is no single point in the 3D world that would represent a vanishing point. Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. &#xD;&#xA;&#xD;&#xA;Mathematically such a point exist at the limit of a infinite line, but theres no set where they overlap. One can not really say mathematically that the lines intersect. But in pactice theres no difference between a mathematical point and a apparent point. &#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons a imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again like i said earlier any point sufficiently far away from the camera in 3D is at the mathematically approximate location of a vanishing point in 2D. For all intents and purposes this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of querry? Probably not since this definition would mean that there is lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your line questioning is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer. Consider asking what you want to achieve instead.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep methaphysical question\**. In some sense its not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, its a concept. There is no contradiction here just different models that have different results. The concept exists, after all it has a wikipedia page, but so does spider man. Real world is like that, lots and lots of conflicting models.\***&#xD;&#xA;&#xD;&#xA;\* If you havent noticed it is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera or this model?&quot;. Because there is probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;&#xD;&#xA;&#xD;&#xA;\** ask a philosophy.se?&#xD;&#xA;&#xD;&#xA;\*** this reminds me of fractal nature of the world. If you ask how long is the coastline of a country is you get different answers depending on how accurately you measure. The length of this is may be infinite. Which admittedly is not very useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="35307" PostHistoryTypeId="5" PostId="12303" RevisionGUID="3249b62b-0920-4ecc-9e2c-43d84e9062c0" CreationDate="2021-11-01T02:29:39.063" UserId="38" Comment="deleted 3 characters in body" Text="Vanishing points is a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history its only one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so its the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image.  You can also use advanced methods to draw fisheye perspectives where straight lines are nolonger straight.&#xD;&#xA;&#xD;&#xA;In 3D it does not exist. There is no single point in the 3D world that would represent a vanishing point. Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. &#xD;&#xA;&#xD;&#xA;Mathematically such a point exist at the limit of a infinite line, but theres no set where they overlap. One can not really say mathematically that the lines intersect. But in pactice theres no difference between a mathematical point and a apparent point. &#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons a imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again like i said earlier any point sufficiently far away from the camera in 3D is at the mathematically approximate location of a vanishing point in 2D. For all intents and purposes this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of querry? Probably not since this definition would mean that there is lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your line questioning is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer. Consider asking what you want to achieve instead.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep methaphysical question\**. In some sense its not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, its a concept. There is no contradiction here just different models that have different results. The concept exists, after all it has a wikipedia page, but so does spider man. Real world is like that, lots and lots of conflicting models.\***&#xD;&#xA;&#xD;&#xA;\* If you havent noticed it is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera or this model?&quot;. Because there is probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;&#xD;&#xA;&#xD;&#xA;\** ask a philosophy.se?&#xD;&#xA;&#xD;&#xA;\*** this reminds me of fractal nature of the world. If you ask how long is the coastline of a country is you get different answers depending on how accurately you measure. The length of this may be infinite. Which admittedly is not very useful and probabky not accepted as real in any pub quiz." ContentLicense="CC BY-SA 4.0" />
  <row Id="35308" PostHistoryTypeId="2" PostId="12304" RevisionGUID="f6f3d226-abaa-4824-a7a3-441be5a9c582" CreationDate="2021-11-01T03:14:13.837" UserId="2654" Text="&gt; My first question is how we can say it doesn't exist, but when we see real image of railway track they intersects at X?&#xD;&#xA;&#xD;&#xA;Because human vision only sees a perspective on reality. It may appear to cause some intersection at a far distant point, but if you change your perspective (by moving towards said far distant point), no such intersection ever actually happens.&#xD;&#xA;&#xD;&#xA;Just because you see a thing doesn't make it real.&#xD;&#xA;&#xD;&#xA;&gt; My second question is if it exists then during projection how this X is projects in projection plane?&#xD;&#xA;&#xD;&#xA;A 2D space cannot capture the entirety of a 3D space. There's too much of it.&#xD;&#xA;&#xD;&#xA;As such, any 2D view of a 3D space is going to only present a subsection of it. A perspective projection works by essentially squeezing a triangular prism view of a 3D world into a 2D area. This creates depth distortion, as more distant areas take up less space than areas closer to you.&#xD;&#xA;&#xD;&#xA;A &quot;vanishing point&quot; exists after a perspective projection by the nature of the perspective projection." ContentLicense="CC BY-SA 4.0" />
  <row Id="35310" PostHistoryTypeId="52" PostId="12301" RevisionGUID="fa501325-69e4-44bd-9e51-1d829817450b" CreationDate="2021-11-01T07:16:27.607" />
  <row Id="35311" PostHistoryTypeId="5" PostId="12301" RevisionGUID="6bda4262-6f48-420a-bc3b-60dd1808ac38" CreationDate="2021-11-01T07:34:33.270" UserId="13095" Comment="Fix grammar and spelling" Text="Consider the following example of perspective projection: I have one railway track with two parallel lines meeting at the point $X$ at infinity which is the theoretical approach. This X is called the vanishing point. But practically, this $X$ doesn't exist. &#xD;&#xA;&#xD;&#xA;My first question is: How can we say it doesn't exist, but when we see a real image of a railway track, the tracks intersect at $X$?&#xD;&#xA;&#xD;&#xA;My second question is: If it exists, how does this $X$ project onto the projection plane during projection? Is it projecting like normal point projection of $(x, y, z)$ onto the view plane $(x_p, y_p, z_p)$?&#xD;&#xA;&#xD;&#xA;N. B - I don't want that detailed answer. I just want an intuitive one that is brief and easy to understand." ContentLicense="CC BY-SA 4.0" />
  <row Id="35312" PostHistoryTypeId="5" PostId="12303" RevisionGUID="b75eb873-c570-40a5-ac68-1a6c89efa16c" CreationDate="2021-11-01T07:45:48.560" UserId="13095" Comment="Fix some grammar and spelling" Text="Vanishing points are a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history it's only one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so it's the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image.  You can also use advanced methods to draw fisheye perspectives where straight lines are no longer straight.&#xD;&#xA;&#xD;&#xA;In 3D it does not exist. There is no single point in the 3D world that would represent a vanishing point. Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. &#xD;&#xA;&#xD;&#xA;Mathematically such a point exists at the limit of an infinite line, but there's no set where they overlap. One can not really say mathematically that the lines intersect. But in practice, there's no difference between a mathematical point and an apparent point. &#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons, an imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again, as I said earlier, any point sufficiently far away from the camera in 3D is at the mathematically approximate location of a vanishing point in 2D. For all intents and purposes, this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of query? Probably not since this definition would mean that there are lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your line questioning is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer. Consider asking what you want to achieve instead.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep metaphysical question\**. In some sense, it's not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, it's a concept. There is no contradiction here just different models that have different results. The concept exists, after all, it has a Wikipedia page, but so does spider man. Real-world is like that, with lots and lots of conflicting models.\***&#xD;&#xA;&#xD;&#xA;\* If you haven't noticed it, is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera, or this model?&quot;. Because there are probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;&#xD;&#xA;&#xD;&#xA;\** ask a philosophy.se?&#xD;&#xA;&#xD;&#xA;\*** this reminds me of the fractal nature of the world. If you ask how long is the coastline of a country is you get different answers depending on how accurately you measure. The length of this may be infinite. Which admittedly is not very useful and probably not accepted as real in any pub quiz." ContentLicense="CC BY-SA 4.0" />
  <row Id="35317" PostHistoryTypeId="2" PostId="12306" RevisionGUID="94f7ed08-d76b-4601-a18b-1cf6bddbc309" CreationDate="2021-11-01T11:48:59.187" UserDisplayName="user17337" Text="We know that in transformation source and destination has same coordinates dimensions. But in projection destination coordinate system has fewer dimensions than the source coordinate system. &#xD;&#xA;&#xD;&#xA;And in perspective projection the world co-ordinate $(x_w, y_w, z_w)$  has transformed to $(x_p, y_p, z_p)$ in projection plane. Since dimensions has remains same here, so it should be perspective transformation. &#xD;&#xA;My question is why we said perspective projection instead of perspective transformation? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35319" PostHistoryTypeId="1" PostId="12306" RevisionGUID="94f7ed08-d76b-4601-a18b-1cf6bddbc309" CreationDate="2021-11-01T11:48:59.187" UserDisplayName="user17337" Text="Perspective transformation is perspective projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35320" PostHistoryTypeId="3" PostId="12306" RevisionGUID="94f7ed08-d76b-4601-a18b-1cf6bddbc309" CreationDate="2021-11-01T11:48:59.187" UserDisplayName="user17337" Text="|3d|transformations|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35321" PostHistoryTypeId="5" PostId="12306" RevisionGUID="cb0aadb5-b5f5-444b-b874-ab4d48b65eff" CreationDate="2021-11-01T12:01:28.003" UserDisplayName="user17337" Comment="added 133 characters in body; deleted 2 characters in body" Text="I know that (&#xD;&#xA;[Reference](https://computergraphics.stackexchange.com/questions/12282/difference-between-transformation-and-projection) )in transformation source and destination has same coordinates dimensions. But in projection destination coordinate system has fewer dimensions than the source coordinate system. &#xD;&#xA;&#xD;&#xA;And in perspective projection the world co-ordinate $(x_w, y_w, z_w)$  has transformed to $(x_p, y_p, z_p)$ in projection plane. Since dimensions has remains same here, so it should be perspective transformation. &#xD;&#xA;My question is why we said perspective projection instead of perspective transformation? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35322" PostHistoryTypeId="2" PostId="12307" RevisionGUID="d78432cd-cabd-4561-8082-e3d8a509e935" CreationDate="2021-11-01T12:19:18.973" UserId="17456" Text="The vanishing point does not exist in the 3d model, only in the projected image.&#xD;&#xA;&#xD;&#xA;&gt; If it exists, how does this X project onto the projection plane during projection? &#xD;&#xA;&#xD;&#xA;It's the limit of the projection of the straight rail tracks as distance goes to inifinity,&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35325" PostHistoryTypeId="5" PostId="12303" RevisionGUID="badc61d5-b72a-4ff5-96fa-be492f200ba1" CreationDate="2021-11-01T13:34:23.383" UserId="38" Comment="added 275 characters in body" Text="Vanishing points are a simplified concept that artists use to help them draw perspective images of idealized pinhole cameras. Like so much in art history it's only one possible way to draw 3D imagery. You can use other methods but they are more convoluted and not widely taught to people. Artists have a person in the loop so that person can use judgement so it's the quick and dirty way is good enough. &#xD;&#xA;&#xD;&#xA;There is no need to know or even draw a line to a vanishing point to draw a correct perspective image.  You can also use advanced methods to draw fisheye perspectives where straight lines are no longer straight.&#xD;&#xA;&#xD;&#xA;* A vanishing point does not exist in 3D space ($R^3$).&#xD;&#xA;* A vanishing point exists in a projection $R^2$.&#xD;&#xA;* But it does exist in a homogenious projective space. But needs to be modelled separately from normal geometry as you can not rely on taking it with you form 3d space. Like normal points&#xD;&#xA;&#xD;&#xA;Therefore you can not transform a vanishing point from 3D to 2D which is what you originally asked. But you can create a model where its true.&#xD;&#xA;&#xD;&#xA;Mathematically such a point exists at the limit of an infinite line, but there's no set where they overlap. Intersects at infinity is OK. But in practice, there's no difference between a mathematical point and an apparent point. They transform the same way in spaces they exist in.&#xD;&#xA;&#xD;&#xA;Now, it is important that we do not regard a 2D image consisting of pixels. We might be rendering vector graphics and thus computing points coordinates not pixels. Yet for practical reasons, an imaging system has to have some minimal width for a line for it to be visible. &#xD;&#xA;&#xD;&#xA;Again, as I said earlier, any point sufficiently far away from the camera in 3D is at the mathematically approximate location of a vanishing point in 2D. For all intents and purposes, this is a vanishing point. This point behaves like any other point. But is this in any way useful for your line of query? Probably not since this definition would mean that there are lots of vanishing points in any image, horizon line being all the vanishing points for all lines of a plane.\* Your line questioning is sufficiently close to a [XY problem](https://xyproblem.info/) to never have a good answer. Consider asking what you want to achieve instead.&#xD;&#xA;&#xD;&#xA;Is a vanishing point real? This is a really deep metaphysical question\**. In some sense, it's not, if you give me the ability to zoom infinitely then you will never reach it. But you can still identify it and see it. It both does and does not exist at the same time, it's a concept. There is no contradiction here just different models that have different results. The concept exists, after all, it has a Wikipedia page, but so does spider man. Real-world is like that, with lots and lots of conflicting models.\***&#xD;&#xA;&#xD;&#xA;\* If you haven't noticed it, is not very fruitful to ask: &quot;Where is the vanishing point of this image, this camera, or this model?&quot;. Because there are probably too many of them. It is however much more fruitful to ask: &quot;Where is the vanishing point of this line?&quot;&#xD;&#xA;&#xD;&#xA;\** ask a philosophy.se?&#xD;&#xA;&#xD;&#xA;\*** this reminds me of the fractal nature of the world. If you ask how long is the coastline of a country is you get different answers depending on how accurately you measure. The length of this may be infinite. Which admittedly is not very useful and probably not accepted as real in any pub quiz." ContentLicense="CC BY-SA 4.0" />
  <row Id="35326" PostHistoryTypeId="2" PostId="12308" RevisionGUID="eb2992dd-959e-49fa-baf5-29cde1f08a9a" CreationDate="2021-11-01T18:10:11.327" UserId="17458" Text="&gt; My first question is: How can we say it doesn't exist, but when we see a real image of a railway track, the tracks intersect at X?&#xD;&#xA;&#xD;&#xA;You do not see the tracks intersect at X or anywhere else because the tracks do not intersect. However, when they get far enough away and the angles line up, you can no longer distinguish the tracks as two separate entities, and that is what we call the vanishing point. It might be easier to understand vanishing points in the real world before dealing with projections. when you look at a road or a track as it goes around a bend there is a point where the inside of the curve obscures the far side so what is around the bend is no longer visible, but as you approach the corner, you can see further and further around it. That is also known as the vanishing point and it moves as your view point moves.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="35328" PostHistoryTypeId="2" PostId="12309" RevisionGUID="b95e52b0-5b31-49a8-8cd0-a242191963cf" CreationDate="2021-11-02T02:07:20.933" UserId="10193" Text="I read some articles about BRDF integration with and without importance sampling and I don't understand one thing in equations. &#xD;&#xA;&#xD;&#xA; - If we integrate a BRDF over hemisphere with uniform sample direction distribution, we evaluate BRDF at all generated directions, sum all values, divide the sum by N (number of samples) **and then multiply the result by 2π, because we need to multiply the result by integration area, and 2π is solid angle of hemisphere**&#xD;&#xA; - If we integrate a BRDF over hemisphere using importance sampling, we generate sample directions from inverted CDF (Cumulative Distribution Function), evaluate BRDF at these samples dividing each value by PDF (Probability Distribution Function) of a corresponding sample, then sum values and divide by N **and that's it, no 2π multiplication**&#xD;&#xA;&#xD;&#xA;I confirmed it numerically integrating Cook-Torrance BRDF and simple Lambertian cosine BRDF, ***but I don't get why 2π multiplication disappears when we use importance sampling from math perspective?***&#xD;&#xA;&#xD;&#xA;Below is example with just cosine function integration. In importance sampling cosine function is also used as its own PDF. Also is my integration code for both cases correct?&#xD;&#xA;&#xD;&#xA;    float f(Vec3f sampleDir) { return sampleDir.z; }&#xD;&#xA;	float pdf(Vec3f sampleDir) { return sampleDir.z; } // cosine function is also its PDF&#xD;&#xA;&#xD;&#xA;	void uniformIntegrationCos()&#xD;&#xA;	{&#xD;&#xA;		double sum = 0.0;&#xD;&#xA;		const int N = 1000;&#xD;&#xA;		for (int i = 0; i &lt; N; ++i)&#xD;&#xA;		{&#xD;&#xA;			Vec3f sampleDir = randomHemisphere(i, N); // fibonacci hemisphere spiral&#xD;&#xA;&#xD;&#xA;			float value = f(sampleDir);&#xD;&#xA;			float weight = sampleDir.z; // NdotL == pdf(sample)&#xD;&#xA;			sum += value * weight / PI / N; // divide by PI to normalize cosine-weighted PDF&#xD;&#xA;&#xD;&#xA;		}&#xD;&#xA;		const float HEMISPHERE_SOLID_ANGLE = 2.f * PI; // integration area&#xD;&#xA;		sum *= HEMISPHERE_SOLID_ANGLE;&#xD;&#xA;&#xD;&#xA;		std::cout &lt;&lt; &quot;Sum = &quot; &lt;&lt; sum &lt;&lt; std::endl;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void importanceIntegrationCos()&#xD;&#xA;	{&#xD;&#xA;		double sum = 0.0;&#xD;&#xA;		const int N = 1000;&#xD;&#xA;		for (int i = 0; i &lt; N; ++i)&#xD;&#xA;		{&#xD;&#xA;			// generate sample direction using inversed CDF of cosine BRDF&#xD;&#xA;			Vec2f r = randomHammersley(i, N);&#xD;&#xA;			float phi = 2.f * PI * r.x;&#xD;&#xA;			float sinTheta = sqrt(r.y);&#xD;&#xA;			float cosTheta = sqrtf(1.f - sinTheta * sinTheta);&#xD;&#xA;&#xD;&#xA;			Vec3f sampleDir;&#xD;&#xA;			sampleDir.x = cos(phi) * sinTheta;&#xD;&#xA;			sampleDir.y = sin(phi) * sinTheta;&#xD;&#xA;			sampleDir.z = cosTheta;&#xD;&#xA;&#xD;&#xA;			float value = f(sampleDir);&#xD;&#xA;			sum += value / N; // BRDF is divided by it's PDF, so no NdotL weight and no PDF normalization by dividing by PI&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		//const float HEMISPHERE_SOLID_ANGLE = 2.f * PI; // integration area&#xD;&#xA;		//sum *= HEMISPHERE_SOLID_ANGLE; // Not needed, why ???&#xD;&#xA;&#xD;&#xA;		std::cout &lt;&lt; &quot;Sum = &quot; &lt;&lt; sum &lt;&lt; std::endl;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	void main()&#xD;&#xA;	{&#xD;&#xA;		uniformIntegrationCos();&#xD;&#xA;		importanceIntegrationCos();&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="35330" PostHistoryTypeId="1" PostId="12309" RevisionGUID="b95e52b0-5b31-49a8-8cd0-a242191963cf" CreationDate="2021-11-02T02:07:20.933" UserId="10193" Text="Integrating BRDF using Importance Sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="35331" PostHistoryTypeId="3" PostId="12309" RevisionGUID="b95e52b0-5b31-49a8-8cd0-a242191963cf" CreationDate="2021-11-02T02:07:20.933" UserId="10193" Text="|brdf|monte-carlo|importance-sampling|ibl|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35332" PostHistoryTypeId="2" PostId="12310" RevisionGUID="25ad4989-99f3-4833-b5ca-c0086521140e" CreationDate="2021-11-02T18:36:36.713" UserId="48" Text="Think of this way: when integrating uniformly over the hemisphere, it's like you are importance-sampling with a constant pdf of $1/2\pi$.&#xD;&#xA;&#xD;&#xA;The multiplication by $2\pi$ at the end, then, can be seen as the division by the pdf, factored out of the sum because it's constant.&#xD;&#xA;&#xD;&#xA;The constant pdf is $1/2\pi$ (as opposed to some other number) because it needs to be normalized to integrate to 1 over the hemisphere, which it does because the area of the hemisphere is $2\pi$." ContentLicense="CC BY-SA 4.0" />
  <row Id="35334" PostHistoryTypeId="5" PostId="12310" RevisionGUID="eebd47da-f80e-4544-b8ae-79b518b95ba1" CreationDate="2021-11-02T18:43:23.050" UserId="48" Comment="added 235 characters in body" Text="Think of this way: when integrating uniformly over the hemisphere, it's like you are importance-sampling with a constant pdf of $1/2\pi$.&#xD;&#xA;&#xD;&#xA;The multiplication by $2\pi$ at the end, then, can be seen as the division by the pdf, factored out of the sum because it's constant.&#xD;&#xA;&#xD;&#xA;The constant pdf is $1/2\pi$ (as opposed to some other number) because it needs to be normalized to integrate to 1 over the hemisphere, which it does because the area of the hemisphere is $2\pi$.&#xD;&#xA;&#xD;&#xA;Your code looks reasonable from what I can see, but I would define the function `pdf` to include the normalization factor of $1/\pi$ for the cosine pdf:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float cosinePDF(Vec3f sampleDir) { return sampleDir.z / PI; }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35335" PostHistoryTypeId="2" PostId="12311" RevisionGUID="3f0f7042-6f02-4030-9668-41a6ceda0913" CreationDate="2021-11-02T18:59:56.917" UserId="10096" Text="It seem like there's some confusion about how perspective projection works in the first place, so I will try to clarify this point.&#xD;&#xA;&#xD;&#xA;Let $p_w = (p_{w,1}, p_{w,2}, p_{w,3})$ be the world-space coordinates of some point $p$. By world space I mean that the coordinates are defined with respect to the standard coordinate system in $\mathbb{R}^3$ with origin $O=(0,0,0)$ and basis $e_1=(1,0,0), e_2=(0,1,0), e_3=(0,0,1)$. Introduce a notion of camera which for the current purpose would be defined through an origin $c_w = (c_{w,1}, c_{w,2}, c_{w,3})$ and orthonormal basis vectors: $t_w = (t_{w,1}, t_{w,2}, t_{w,3})$, $n_w = (n_{w,1}, n_{w,2}, n_{w,3})$, $b_w = (b_{w,1}, b_{w,2}, b_{w,3})$. Then the point $p_w$ can be expressed also through its coordinates $p_v$ in the camera's coordinate system: $p_w = c_w + p_{v,1}t_w + p_{v,2}n_w + p_{v,3}b_w$, or equivalently in matrix notation:&#xD;&#xA;&#xD;&#xA;$$p_w = c_w+M p_v, \, M = \begin{pmatrix} t_{w,1} &amp; n_{w,1} &amp; b_{w,1} \\ t_{w,2} &amp; n_{w,2} &amp; b_{w,2} \\ t_{w,3} &amp; n_{w,3} &amp; b_{w,3} \end{pmatrix}.$$&#xD;&#xA;&#xD;&#xA;To find $p_v$ we compute $p_v = M^{-1}(p_w-c_w) = M^T(p_w-c_w)$. Now assume that we want the camera's projection plane to be at $z_{v}=1$ in the camera's coordinate system (i.e. it's perpendicular to the $b$ vector and it's at an offset of $1$ from $c$ along it). We can find the perspective projection $p_{\pi}$ onto that plane using: $p_{\pi} = \left(\frac{p_{v,1}}{p_{v,3}}, \frac{p_{v,2}}{p_{v,3}}\right)$. As you can see the projected point is two-dimensional, its 3-dimensional analogue (as a 3D point on the film) in the camera's coordinate system is $\left(\frac{p_{v,1}}{p_{v,3}}, \frac{p_{v,2}}{p_{v,3}}, 1\right)$.&#xD;&#xA;&#xD;&#xA;In computer graphics, we typically need some depth information while drawing fragments/pixels to figure out which surfaces are occluded and which aren't (see [Z-buffer][1]). For that purpose it is useful to also keep information about the &quot;depth&quot; of $p_v$ before it gets projected, then the third coordinate is kept in the form $a + \frac{b}{p_{v,3}}$ where $a$ and $b$ are constants determined by the near and far plane values. Thus in ndc coordinates you typically have the triple $\left(\frac{p_{v,1}}{p_{v,3}}, \frac{p_{v,2}}{p_{v,3}}, a + \frac{b}{p_{v,3}}\right)$ (sometimes a division by the negative of $p_{v,3}$ is employed). Using the third coordinate one can figure out whether a specific point $p$ is &quot;behind&quot; another point $q$: $p_{v,3} &gt; q_{v,3}$.&#xD;&#xA;&#xD;&#xA;Often people want to control the size of their imaginary camera film, and the near and far plane values. To achieve this typically a projection matrix is applied to $p_v$ before the division (yielding $p$ in clip space). Note that even though it's termed a projection matrix, it doesn't really project anything, as the projection occurs through the division.&#xD;&#xA;&#xD;&#xA;An orthographic projection on the other hand is achieved by just dropping the last coordinate of $p_v$: $(p_{v,1}, p_{v,2})$.&#xD;&#xA;&#xD;&#xA;Regarding implementation details in various APIs and some more information I would suggest reading:&#xD;&#xA;http://www.songho.ca/opengl/gl_projectionmatrix.html&#xD;&#xA;&#xD;&#xA;http://www.songho.ca/opengl/gl_transform.html&#xD;&#xA;&#xD;&#xA;https://learnopengl.com/Getting-started/Coordinate-Systems&#xD;&#xA;&#xD;&#xA;https://learnopengl.com/Getting-started/Transformations&#xD;&#xA;&#xD;&#xA;I should probably also touch upon how this is related to vanishing points. First to disambiguate from the pinhole/perspective projection point of the camera $c$: all points lying on the same line passing through $c_w$ (the origin/pinhole of the camera) and $p_{w}$ get projected to the same point $p_{\pi}$. Note that $c_w$ is not a vanishing point. Now consider parallel lines in 3D space. A line can be defined parametrically as $l(\alpha) = f + \alpha d, \alpha \in \mathbb{R}$, where $f$ is some point on the line and $d$ is its direction. Two lines $l(\alpha) = f+\alpha d,\, k(\beta) = g+\beta h$ are parallel if $d \parallel h$ ($\exists \gamma\ne 0: d=\gamma h$). Now given two arbitrary parallel lines in the coordinate system of the camera: $l_{v}(\alpha) = f_v + \alpha d_v, \, k(\beta) = g_v + \beta h_v$ their projections intersect on the projective plane at $\left( \frac{d_{v,1}}{d_{v,3}}, \frac{d_{v,1}}{d_{v,3}} \right) = \left( \frac{h_{v,1}}{h_{v,3}}, \frac{h_{v,1}}{h_{v,3}} \right)$ which one terms the vanishing point for all lines parallel to those. Artists sometimes draw those points to check the correctness of their perspective/construction :&#xD;&#xA;&#xD;&#xA;[![https://i.stack.imgur.com/Nae7R.gif][2]][2]&#xD;&#xA;&#xD;&#xA;The vanishing point doesn't exist only on the projection plane, but it also exists if we extend $\mathbb{R}^3$ with the points at infinity through homogeneous coordinates: &#xD;&#xA;$$(d_{v,1}, d_{v,2}, d_{v,3}, 0) = (\gamma h_{v,1}, \gamma h_{v,2}, \gamma h_{v,3}, 0) = (h_{v,1}, h_{v,2}, h_{v,3}, 0).$$ &#xD;&#xA;&#xD;&#xA;You can think of this point as one situated on a sphere at infinity - each unique direction gets its own point at infinity ($d$ and $h$ represent the same direction thus they get the same point at infinity). If you project this point onto the projection plane you get precisely the intersection point $\left( \frac{d_{v,1}}{d_{v,3}}, \frac{d_{v,1}}{d_{v,3}} \right) $ of the projection onto the projection plane of any lines parallel to $d$. There is a caveat for lines parallel to the projection plane (e.g. of the form $(d_{v,1}, d_{v,2}, 0)$): the intersection of their projections lies in $\mathbb{R}^2$ extended with homogeneous coordinates, namely: $(d_{v,1}, d_{v,2}, 0)$ (this means that their projections remain parallel in practice, and those are the only lines for which this holds).&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Z-buffering&#xD;&#xA;  [2]: https://i.stack.imgur.com/Nae7R.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="35337" PostHistoryTypeId="2" PostId="12312" RevisionGUID="40833c4d-f521-49dd-b800-c86f3adc911f" CreationDate="2021-11-02T22:04:11.980" UserId="17466" Text="I have developed some software that generates a pdf file for visualizing air traffic. Each page shows a plan view of the traffic at a point in time, with a small time step (e.g., 20 seconds) from one page to the next. It works well, but it would be more useful if I could zoom in on a smaller section of the viewport (e.g., the lower left quadrant) and maintain the same viewport frame as I step through the pages. I can zoom in using Adobe Acrobat Reader, but then I lose the viewport frame when I step to the next page. I would like to maintain the same zoomed-in viewport from one page to the next. Is that possible with Acrobat Reader or any other pdf viewer? If so, how? This feature would provide a major advancement in the visualization of air traffic. Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="35339" PostHistoryTypeId="1" PostId="12312" RevisionGUID="40833c4d-f521-49dd-b800-c86f3adc911f" CreationDate="2021-11-02T22:04:11.980" UserId="17466" Text="How can I step through a pdf file while maintaining a fixed viewport for each page?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35340" PostHistoryTypeId="3" PostId="12312" RevisionGUID="40833c4d-f521-49dd-b800-c86f3adc911f" CreationDate="2021-11-02T22:04:11.980" UserId="17466" Text="|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35341" PostHistoryTypeId="50" PostId="9926" RevisionGUID="b1da18d1-c92b-4c51-8c01-b385c30e0147" CreationDate="2021-11-03T00:02:25.233" UserId="-1" />
  <row Id="35342" PostHistoryTypeId="2" PostId="12313" RevisionGUID="78e79b4a-0b71-4e7c-bb66-34453eaa8ff0" CreationDate="2021-11-03T00:12:25.073" UserId="48" Text="[PDF.js](https://mozilla.github.io/pdf.js/) is a PDF viewer that runs in a web browser, using HTML and Javascript. It is quite usable (it's the default PDF viewer shipped with Firefox) and it has an API that can be used to script it. For example, there is an API call to render a page using a chosen viewport and transform. I've never tried working with it as a developer, but it seems plausible that you could build your own front-end UI using PDF.js as a rendering backend, or modify the existing PDF.js UI to change the navigation logic to do what you want." ContentLicense="CC BY-SA 4.0" />
  <row Id="35344" PostHistoryTypeId="2" PostId="12314" RevisionGUID="2b06abdb-958b-48ed-a87b-c10b230af5e3" CreationDate="2021-11-03T04:15:21.247" UserId="17467" Text="Please do not confuse this question with [this one](https://computergraphics.stackexchange.com/questions/2267/why-does-the-integral-of-ndf-over-a-solid-angle-equals-the-area-where-micronorma). In [Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs](https://jcgt.org/published/0003/02/03/paper.pdf), Eric Heitz defines the distribution of normals as. &#xD;&#xA;  &#xD;&#xA;[![Definition of D][1]][1]&#xD;&#xA;&#xD;&#xA;**There, the footnote.** Even the footnote description is confusing &quot;per square meter of the geometric surface&quot; and then it is in the numerator. **Everyone else, before and after this well-cited paper still persists that the distribution is $1/\mathbf{sr}$**, which creates different issues with their math resolved through sketchy corrective expressions and language. With some people avoiding the subject with intentionally unclear language (PBR book).&#xD;&#xA;&#xD;&#xA;**I can buy the argument and the definition, but the author handwaves the notion of said area everywhere.** Even defines the surface as being 1 meter squared to justify relegating it to a cosine normalization factor. In no capacity does $dA$ come up which implicitly makes all the equations result in radiant intensity, not radiance. **(I know the author says it's projected area, but a cosine alone is not projected area, making the area implicit is a cop out at the lack of area to cancel out because it's supposedly encoded by $D$)**.&#xD;&#xA;&#xD;&#xA;On the third side of the fence, Matt Pharr can't decide which side he's on, adding in murky $dA$ in the derivation of the Torrance-Sparrow microfacet model, to cancel it out. He also suggests one needs to use the projected solid angle while proving normalization.&#xD;&#xA;&#xD;&#xA;Who is right? I am beyond confused and frustrated at this point.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zgYQM.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35346" PostHistoryTypeId="1" PostId="12314" RevisionGUID="2b06abdb-958b-48ed-a87b-c10b230af5e3" CreationDate="2021-11-03T04:15:21.247" UserId="17467" Text="Conflicting definitions for the distribution of normals $D$ in microfacet BSDFs" ContentLicense="CC BY-SA 4.0" />
  <row Id="35347" PostHistoryTypeId="3" PostId="12314" RevisionGUID="2b06abdb-958b-48ed-a87b-c10b230af5e3" CreationDate="2021-11-03T04:15:21.247" UserId="17467" Text="|mathematics|brdf|pbr|microfacet|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35348" PostHistoryTypeId="5" PostId="12314" RevisionGUID="bf06d454-8c1a-470a-b671-f4767c4c99c6" CreationDate="2021-11-03T04:20:30.740" UserId="17467" Comment="added 24 characters in body" Text="Please do not confuse this question with [this one](https://computergraphics.stackexchange.com/questions/2267/why-does-the-integral-of-ndf-over-a-solid-angle-equals-the-area-where-micronorma). In [Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs](https://jcgt.org/published/0003/02/03/paper.pdf), Eric Heitz defines the distribution of normals as. &#xD;&#xA;  &#xD;&#xA;[![Definition of D][1]][1]&#xD;&#xA;&#xD;&#xA;**There, the footnote.** Even the footnote description is confusing &quot;per square meter of the geometric surface&quot; and then it is in the numerator. **Everyone else, before and after this well-cited paper still persists that the distribution is $1/\mathbf{sr}$**, which creates different issues with their math resolved through sketchy corrective expressions and language. With some people avoiding the subject with intentionally unclear language (PBR book).&#xD;&#xA;&#xD;&#xA;**I can buy the argument and the definition, but the author handwaves the notion of said area everywhere.** Even defines the surface as being 1 meter squared to justify relegating it to a cosine normalization factor. In no capacity does $dA$ come up which implicitly makes all the equations result in radiant intensity, not radiance. **(I know the author says it's projected area, but a cosine alone is not projected area, making the area implicit is a cop out at the lack of area to cancel out because it's supposedly encoded by $D$)**.&#xD;&#xA;&#xD;&#xA;On the third side of the fence, Matt Pharr can't decide which side he's on, adding in murky $dA$ in the derivation of the Torrance-Sparrow microfacet model, to cancel it out. He also suggests one needs to use the projected solid angle while proving normalization, while nobody else does.&#xD;&#xA;&#xD;&#xA;Who is right? I am beyond confused and frustrated at this point.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zgYQM.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35353" PostHistoryTypeId="2" PostId="12316" RevisionGUID="07ee3f30-c9c5-4e2f-ba23-e953eaec0452" CreationDate="2021-11-04T03:53:53.913" UserId="17472" Text="Building upon the answer by @shashankan and [another answer in Blender][1], I wrote a Blender script to convert from FBX into a subfolder with GLTFs.  &#xD;&#xA;&#xD;&#xA;(You may want to remove my scaling code, which scales up the import and then resets the object to be scaled at 1.0 at the new size.)&#xD;&#xA;&#xD;&#xA;    import bpy&#xD;&#xA;    import os&#xD;&#xA;&#xD;&#xA;    for root, dirs, files in os.walk('/path/to/directory'):&#xD;&#xA;        for name in files:&#xD;&#xA;            if name.endswith('fbx'):&#xD;&#xA;                # clear the scene&#xD;&#xA;                bpy.ops.object.select_all(action='SELECT')&#xD;&#xA;                bpy.ops.object.delete()&#xD;&#xA;                &#xD;&#xA;                # import fbx, scale up by 3.28&#xD;&#xA;                bpy.ops.import_scene.fbx(filepath=os.path.join(root, name), global_scale=3.28)&#xD;&#xA;                bpy.ops.object.select_all(action='SELECT')&#xD;&#xA;                &#xD;&#xA;                # 'reset' transform to 1.0, putting current scale into data&#xD;&#xA;                bpy.ops.object.transform_apply(scale=True, rotation=False, location=False, properties=False)&#xD;&#xA;                &#xD;&#xA;                # export as fbx, replacing file extension&#xD;&#xA;                # change export_format as needed, see api for options&#xD;&#xA;                # https://docs.blender.org/api/current/bpy.ops.export_scene.html&#xD;&#xA;                bpy.ops.export_scene.gltf(filepath=os.path.join(root+'/gltf', name.removesuffix('fbx')+'gltf'), export_format='GLTF_SEPARATE', use_selection=True)&#xD;&#xA;                &#xD;&#xA;                bpy.ops.object.delete() # clear the scene&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://blender.stackexchange.com/a/62604/134890" ContentLicense="CC BY-SA 4.0" />
  <row Id="35355" PostHistoryTypeId="10" PostId="12296" RevisionGUID="c6287e63-1163-4c17-99a1-8994e1692587" CreationDate="2021-11-04T08:52:41.097" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7952,&quot;DisplayName&quot;:&quot;pmw1234&quot;},{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="35356" PostHistoryTypeId="10" PostId="12306" RevisionGUID="e4a13619-7dcc-47fb-ba3b-0349f62e6783" CreationDate="2021-11-04T09:05:38.710" UserId="13095" Comment="101" Text="{&quot;OriginalQuestionIds&quot;:[12282],&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="35357" PostHistoryTypeId="10" PostId="12282" RevisionGUID="a1fa3626-8101-4902-9e96-370baacc6dd7" CreationDate="2021-11-04T09:22:09.313" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="35358" PostHistoryTypeId="10" PostId="12276" RevisionGUID="553944e9-1564-426d-8df5-a0c712a9e993" CreationDate="2021-11-04T09:26:53.317" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="35360" PostHistoryTypeId="10" PostId="12272" RevisionGUID="878504ba-0fa3-4ae9-8a94-3f34a8e29c59" CreationDate="2021-11-04T09:37:19.447" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="35361" PostHistoryTypeId="2" PostId="12317" RevisionGUID="161a5974-2d84-4669-b3c1-79c65be299dc" CreationDate="2021-11-05T20:44:01.570" UserId="17045" Text="I'm rendering some UI using an immediate-mode UI library, so each frame it produces some meshes, which I then load into buffers and render, only to get some strange errors from Renderdoc:&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;You can see in the API inspector the list of calls preceding the draw. &#xD;&#xA;&#xD;&#xA;I'm deeply puzzled by this, because of the following facts:&#xD;&#xA;&#xD;&#xA;**This problem only happens when the UI library returns more than one mesh.**&#xD;&#xA;That is, the API calls for multiple meshes would go as follows:&#xD;&#xA;&#xD;&#xA;    // First mesh&#xD;&#xA;    glUseProgram&#xD;&#xA;    // set textures&#xD;&#xA;    // bind vertex array&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    // Second mesh&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    ...    &#xD;&#xA;&#xD;&#xA;**If I call glVertexArrayVertexBuffer even once per frame, the errors are not reported**, regardless of how many meshes the UI returns.&#xD;&#xA;First mesh draw:&#xD;&#xA;[![][2]][2]&#xD;&#xA;Second mesh draw:&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;**Why I find this strange:**&#xD;&#xA;&#xD;&#xA;1. The vertex array object is fully set up at the start of the program, including the call to glVertexArrayVertexBuffer, and the binding of vbo to vao is never supposed to change, together with offset and stride.&#xD;&#xA;2. I removed every other draw call from the program for testing and left only those for the UI, so nothing should interfere&#xD;&#xA;3. The UI renders just fine in the program, it's only RenderDoc that complains&#xD;&#xA;&#xD;&#xA;I see 2 possibilities - 1) I am using the API incorrectly, and 2) there's a bug in RenderDoc.&#xD;&#xA;&#xD;&#xA;Would really appreciate if someone could shed some light onto this issue.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I69FU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/THh3I.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dGkMC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35363" PostHistoryTypeId="1" PostId="12317" RevisionGUID="161a5974-2d84-4669-b3c1-79c65be299dc" CreationDate="2021-11-05T20:44:01.570" UserId="17045" Text="Renderdoc reports incorrect OpenGL API usage, can't figure out why" ContentLicense="CC BY-SA 4.0" />
  <row Id="35364" PostHistoryTypeId="3" PostId="12317" RevisionGUID="161a5974-2d84-4669-b3c1-79c65be299dc" CreationDate="2021-11-05T20:44:01.570" UserId="17045" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35365" PostHistoryTypeId="2" PostId="12318" RevisionGUID="1d257713-b182-4b8a-9cf5-83167dfacbb8" CreationDate="2021-11-06T16:13:36.883" UserId="17485" Text="Im not sure if this is the right section to ask this question but i figured its worth a shot.&#xD;&#xA;&#xD;&#xA;Is it possible to take metadata from a video and use that data to identify what phone model was used to record that video, like iPhone X, iPhone XR, iPhone 8+, etc.&#xD;&#xA;&#xD;&#xA;I did some research on my own and I found two factors that might help, the first is vendor ID which is just “apple”, and then the second is the encoder, im not sure if different phones have different encoders in the hardware, i couldnt find any information on it.&#xD;&#xA;&#xD;&#xA;If anybody could help me out that would be greatly appreciated!" ContentLicense="CC BY-SA 4.0" />
  <row Id="35367" PostHistoryTypeId="1" PostId="12318" RevisionGUID="1d257713-b182-4b8a-9cf5-83167dfacbb8" CreationDate="2021-11-06T16:13:36.883" UserId="17485" Text="Is it possible to get recording device from meta data?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35368" PostHistoryTypeId="3" PostId="12318" RevisionGUID="1d257713-b182-4b8a-9cf5-83167dfacbb8" CreationDate="2021-11-06T16:13:36.883" UserId="17485" Text="|rendering|image-processing|gpu|javascript|image-comparison|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35370" PostHistoryTypeId="2" PostId="12319" RevisionGUID="99d47912-a92a-4581-a88d-d854150f7f2f" CreationDate="2021-11-06T22:04:49.513" UserId="48" Text="There's a tool called [ExifTool](https://exiftool.org/) that can extract various forms of metadata from video and audio files. [Here is an example](https://stackoverflow.com/a/18658208/938914) (from 2013) of using the tool on a .mov file from an iPhone, which includes some lines in the output identifying the model of phone and OS version:&#xD;&#xA;&#xD;&#xA;```none&#xD;&#xA;Make                            : Apple&#xD;&#xA;Software (und-AU)               : 6.1.3&#xD;&#xA;Model (und-AU)                  : iPhone 4S&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However, it's entirely dependent on what metadata the program that created the video decided to include in the file. For example, on my Android phone using the built-in camera app, the metadata includes the version of Android but nothing about the make or model of the phone hardware." ContentLicense="CC BY-SA 4.0" />
  <row Id="35372" PostHistoryTypeId="5" PostId="12317" RevisionGUID="b73fd74d-567a-4d21-977a-6d42192c467b" CreationDate="2021-11-06T22:15:55.447" UserId="17045" Comment="added 675 characters in body" Text="I'm rendering some UI using an immediate-mode UI library, so each frame it produces some meshes, which I then load into buffers and render, only to get some strange errors from Renderdoc:&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;You can see in the API inspector the list of calls preceding the draw. &#xD;&#xA;&#xD;&#xA;I'm deeply puzzled by this, because of the following facts:&#xD;&#xA;&#xD;&#xA;**This problem only happens when the UI library returns more than one mesh.**&#xD;&#xA;That is, the API calls for multiple meshes would go as follows:&#xD;&#xA;&#xD;&#xA;    // First mesh&#xD;&#xA;    glUseProgram&#xD;&#xA;    // set textures&#xD;&#xA;    // bind vertex array&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    // Second mesh&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    ...    &#xD;&#xA;&#xD;&#xA;**If I call glVertexArrayVertexBuffer even once per frame, the errors are not reported**, regardless of how many meshes the UI returns.&#xD;&#xA;First mesh draw:&#xD;&#xA;[![][2]][2]&#xD;&#xA;Second mesh draw:&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;**Why I find this strange:**&#xD;&#xA;&#xD;&#xA;1. The vertex array object is fully set up at the start of the program, including the call to glVertexArrayVertexBuffer, and the binding of vbo to vao is never supposed to change, together with offset and stride.&#xD;&#xA;2. I removed every other draw call from the program for testing and left only those for the UI, so nothing should interfere&#xD;&#xA;3. The UI renders just fine in the program, it's only RenderDoc that complains&#xD;&#xA;&#xD;&#xA;I see 2 possibilities - 1) I am using the API incorrectly, and 2) there's a bug in RenderDoc.&#xD;&#xA;&#xD;&#xA;Would really appreciate if someone could shed some light onto this issue.&#xD;&#xA;&#xD;&#xA;UPDATE:&#xD;&#xA;&#xD;&#xA;Nicol Bolas commented below&#xD;&#xA;&gt; &quot;including the call to glVertexArrayVertexBuffer&quot; Are you sure about that?&#xD;&#xA;&#xD;&#xA;I have captured Frame #0 and Frame #1815 in Renderdoc to illustrate that the call is made (see the image below) and noticed that in the second frame no errors were reported! It strongly suggests that if Frame #0 is not captured, then Renderdoc just doesn't know that the appropriate calls have been made and reports false errors. &#xD;&#xA;&#xD;&#xA;Also quite expectedly, if I remove the call to glVertexArrayVertexBuffer, then nothing gets drawn and OpenGL complains. I almost think we've solved the mystery.&#xD;&#xA;[![][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I69FU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/THh3I.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dGkMC.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/CXVQA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35373" PostHistoryTypeId="5" PostId="12317" RevisionGUID="56692485-25d1-4a35-b567-ad5b05c657c0" CreationDate="2021-11-06T22:31:42.197" UserId="17045" Comment="added 2 characters in body" Text="I'm rendering some UI using an immediate-mode UI library, so each frame it produces some meshes, which I then load into buffers and render, only to get some strange errors from Renderdoc:&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;You can see in the API inspector the list of calls preceding the draw. &#xD;&#xA;&#xD;&#xA;I'm deeply puzzled by this, because of the following facts:&#xD;&#xA;&#xD;&#xA;**This problem only happens when the UI library returns more than one mesh.**&#xD;&#xA;That is, the API calls for multiple meshes would go as follows:&#xD;&#xA;&#xD;&#xA;    // First mesh&#xD;&#xA;    glUseProgram&#xD;&#xA;    // set textures&#xD;&#xA;    // bind vertex array&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    // Second mesh&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    ...    &#xD;&#xA;&#xD;&#xA;**If I call glVertexArrayVertexBuffer even once per frame, the errors are not reported**, regardless of how many meshes the UI returns.&#xD;&#xA;First mesh draw:&#xD;&#xA;[![][2]][2]&#xD;&#xA;Second mesh draw:&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;**Why I find this strange:**&#xD;&#xA;&#xD;&#xA;1. The vertex array object is fully set up at the start of the program, including the call to glVertexArrayVertexBuffer, and the binding of vbo to vao is never supposed to change, together with offset and stride.&#xD;&#xA;2. I removed every other draw call from the program for testing and left only those for the UI, so nothing should interfere&#xD;&#xA;3. The UI renders just fine in the program, it's only RenderDoc that complains&#xD;&#xA;&#xD;&#xA;I see 2 possibilities - 1) I am using the API incorrectly, and 2) there's a bug in RenderDoc.&#xD;&#xA;&#xD;&#xA;Would really appreciate if someone could shed some light onto this issue.&#xD;&#xA;&#xD;&#xA;UPDATE:&#xD;&#xA;&#xD;&#xA;Nicol Bolas commented below&#xD;&#xA;&gt; &quot;including the call to glVertexArrayVertexBuffer&quot; Are you sure about that?&#xD;&#xA;&#xD;&#xA;I have captured Frame #0 and Frame #1815 in Renderdoc to illustrate that the call is made (see the image below) and noticed that in the second frame no errors were reported! It strongly suggests that if Frame #0 is not captured, then Renderdoc just doesn't know that the appropriate calls have been made and reports false errors. &#xD;&#xA;&#xD;&#xA;Also quite expectedly, if I remove the call to glVertexArrayVertexBuffer, then nothing gets drawn and OpenGL complains. I almost think we've solved the mystery.&#xD;&#xA;&#xD;&#xA;[![][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I69FU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/THh3I.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dGkMC.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/fkDMY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35374" PostHistoryTypeId="5" PostId="12317" RevisionGUID="343e4066-4083-4eb2-a848-0bcb7a8c6c40" CreationDate="2021-11-07T19:12:05.073" UserId="17045" Comment="added 678 characters in body" Text="I'm rendering some UI using an immediate-mode UI library, so each frame it produces some meshes, which I then load into buffers and render, only to get some strange errors from Renderdoc:&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;You can see in the API inspector the list of calls preceding the draw. &#xD;&#xA;&#xD;&#xA;I'm deeply puzzled by this, because of the following facts:&#xD;&#xA;&#xD;&#xA;**This problem only happens when the UI library returns more than one mesh.**&#xD;&#xA;That is, the API calls for multiple meshes would go as follows:&#xD;&#xA;&#xD;&#xA;    // First mesh&#xD;&#xA;    glUseProgram&#xD;&#xA;    // set textures&#xD;&#xA;    // bind vertex array&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    // Second mesh&#xD;&#xA;    glNamedBufferData // for the vertex buffer&#xD;&#xA;    glNamedBufferData // for the index buffer&#xD;&#xA;    glDrawElements&#xD;&#xA;&#xD;&#xA;    ...    &#xD;&#xA;&#xD;&#xA;**If I call glVertexArrayVertexBuffer even once per frame, the errors are not reported**, regardless of how many meshes the UI returns.&#xD;&#xA;First mesh draw:&#xD;&#xA;[![][2]][2]&#xD;&#xA;Second mesh draw:&#xD;&#xA;[![][3]][3]&#xD;&#xA;&#xD;&#xA;**Why I find this strange:**&#xD;&#xA;&#xD;&#xA;1. The vertex array object is fully set up at the start of the program, including the call to glVertexArrayVertexBuffer, and the binding of vbo to vao is never supposed to change, together with offset and stride.&#xD;&#xA;2. I removed every other draw call from the program for testing and left only those for the UI, so nothing should interfere&#xD;&#xA;3. The UI renders just fine in the program, it's only RenderDoc that complains&#xD;&#xA;&#xD;&#xA;I see 2 possibilities - 1) I am using the API incorrectly, and 2) there's a bug in RenderDoc.&#xD;&#xA;&#xD;&#xA;Would really appreciate if someone could shed some light onto this issue.&#xD;&#xA;&#xD;&#xA;UPDATE:&#xD;&#xA;&#xD;&#xA;Nicol Bolas commented below&#xD;&#xA;&gt; &quot;including the call to glVertexArrayVertexBuffer&quot; Are you sure about that?&#xD;&#xA;&#xD;&#xA;I have captured Frame #0 and Frame #1815 in Renderdoc to illustrate that the call is made (see the image below) and noticed that in the second frame no errors were reported! It strongly suggests that if Frame #0 is not captured, then Renderdoc just doesn't know that the appropriate calls have been made and reports false errors. &#xD;&#xA;&#xD;&#xA;Also quite expectedly, if I remove the call to glVertexArrayVertexBuffer, then nothing gets drawn and OpenGL complains. I almost think we've solved the mystery.&#xD;&#xA;&#xD;&#xA;[![][4]][4]&#xD;&#xA;&#xD;&#xA;UPDATE 2.&#xD;&#xA;&#xD;&#xA;As per Nicol Bolas's suggestion I have rewritten the code so that all the meshes are packed into one vertex buffer and are loaded there once per frame. After this change Renderdoc stopped complaining. I mostly consider the issue solved, but one thing is still not clear:&#xD;&#xA;&#xD;&#xA;If the assumption that Renderdoc needed Frame #0 to &quot;know&quot; about the call to `glVertexArrayVertexBuffer` is correct, then why did it not complain when there was only 1 mesh to draw (i.e. there were no multiple draw calls with `glNamedBufferData` between them).&#xD;&#xA;&#xD;&#xA;If no one knows for sure why this is happening, I will probably raise an issue with Renderdoc and mark this question as done.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I69FU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/THh3I.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/dGkMC.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/fkDMY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35375" PostHistoryTypeId="10" PostId="12263" RevisionGUID="2d99dca7-f297-434a-a2da-774b04dba278" CreationDate="2021-11-08T07:53:25.490" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="35376" PostHistoryTypeId="2" PostId="12320" RevisionGUID="021900f4-e2ec-4fee-9f1b-798ce84c16ec" CreationDate="2021-11-09T06:18:10.130" UserId="48" Text="The units of the NDF are tricky. For whatever it's worth, Heitz's convention of defining it relative to a 1 m² reference geometric surface is unusual, and although I can see why he would want to define it that way for conceptual simplicity, it does not really match how NDFs are used in practice. I definitely had a head-tilt moment when I first read that passage in his paper.&#xD;&#xA;&#xD;&#xA;The problem with NDFs is that they involve two different area measures: a macrosurface (or &quot;geometric&quot;) area and a microsurface area. As far as I understand, the true and complete definition of the units of the NDF is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{\text{micro area}}{\text{solid angle} \cdot \text{macro area}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In other words, if we _double_-integrate the NDF over a region of solid angle $\Omega$ and a region of macrosurface $A$, we obtain the area of the microsurface that has normals within that region of solid angle:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\int_\Omega \int_A D(\omega)\,dA\,d\omega  = \text{total area of microfacets above $A$ with normals in $\Omega$}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Note that this is dimensionally consistent, even maintaining the distinction between the two area measures. The $dA$ is an element of macro area, and $d\omega$ an element of solid angle, so those cancel out the denominator of $D(\omega)$. The numerator is then micro area, which matches the right hand side.&#xD;&#xA;&#xD;&#xA;Now if we forget the distinction between these two area measures and cancel the area units against each other, we obtain just $1/\text{sr}$, which is consistent with the vast majority of literature. But there is a subtlety here. _Usually_, when we see a distribution that has the units of $1/\text{sr}$, this means it's a distribution over the sphere and that if you integrate it over the sphere you should get 1. But note that if you integrate the NDF over the sphere, you don't in general get 1. Instead, as the above definition shows, you get the overall ratio of micro area to macro area. For a rough surface, this is greater than 1 (and the rougher it is, the larger the value), as the microsurface is crinkly and rough and therefore has more area than the corresponding macrosurface.&#xD;&#xA;&#xD;&#xA;The correct normalization condition for an NDF is&#xD;&#xA;$$&#xD;&#xA;\int_{S^2} D(\omega) (n \cdot \omega) \, d\omega = 1&#xD;&#xA;$$&#xD;&#xA;(as can be readily verified if you take any of the usual NDF formulas, set a nonzero roughness, and try numerically integrating it—they don't come out to 1 unless you use the above integrand).&#xD;&#xA;&#xD;&#xA;The reason for the $(n \cdot \omega)$ factor in the integrand is to convert microsurface area into the corresponding (projected) macrosurface area. In other words, this factor has the units:&#xD;&#xA;$$&#xD;&#xA;n \cdot \omega = \frac{\text{macro area}}{\text{micro area}}&#xD;&#xA;$$&#xD;&#xA;With this, the area units of the NDF really do cancel properly and you're left with a true spherical distribution that integrates to 1.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Now why does Heitz say something different? He wants to eliminate the &quot;macro area&quot; factor by setting it to a standardized value of 1 m², then defining the NDF as simply $\text{micro area}/\text{solid angle}$. Thus its units become $\text{m}^2 / \text{sr}$, and the normalization condition becomes&#xD;&#xA;$$&#xD;&#xA;\int_{S^2} D(\omega) (n \cdot \omega) \, d\omega = 1\ \text{m}^2&#xD;&#xA;$$&#xD;&#xA;(cf. equation (9) in the paper). It's no longer a dimensionless scalar 1, but an area of 1 square meter.&#xD;&#xA;&#xD;&#xA;I don't love this definition. On the one hand, it does make it really explicit that an NDF involves area &quot;somehow&quot;, and isn't simply a spherical distribution. It avoids the somewhat bizarre situation of having two area measures whose _units_ cancel, but whose _values_ don't cancel. On the other hand, in real life we obviously don't apply NDFs only to flat surfaces of 1 m². We want to apply NDFs to surface patches of any size we like—such as the patch enclosed in a pixel when rendering. The obvious way to do that is by normalizing out the 1 m², so that the NDF is expressed as a fractional area relative to any desired patch size. And then you get back to the definition I stated at the beginning of this answer.&#xD;&#xA;&#xD;&#xA;Indeed, even Heitz isn't really consistent with this choice, as you noted. Starting from equation (14) in the paper, he drops the implicit 1 m² factors that ought to be there. When he proceeds to define the distribution of visible normals, $D_{\omega_o}(\omega_m)$, he no longer says that the units are $\text{m}^2/\text{sr}$, but just the usual $1/\text{sr}$ (cf. Table 2 in the paper).&#xD;&#xA;&#xD;&#xA;To be fair, Heitz's distribution of visible normals is defined in such a way that it is a legitimate spherical distribution by itself, with the usual normalization condition:&#xD;&#xA;$$&#xD;&#xA;\int_{S^2} D_{\omega_o}(\omega_m) \, d\omega_m = 1&#xD;&#xA;$$&#xD;&#xA;(cf. equation (18) in the paper), so it is no longer necessary to think about some hidden area units in order to understand the meaning of this function.&#xD;&#xA;&#xD;&#xA;Arguably BRDFs and NDFs _should_ have been defined this way as well all along, incorporating the $(n \cdot \omega)$ factor into the function, so that they would be legitimate spherical distributions and we could avoid all this hassle. Sadly, due to historical path-dependence we didn't end up there.&#xD;&#xA;&#xD;&#xA;So, to sum up, the oddities of the NDF have their origin in the (IMO under-appreciated and under-explained) fact that it has two different area measures hiding in it. If you just look at the units, they appear to cancel out, but nevertheless you need to keep the areas in mind in order to understand NDFs properly.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35378" PostHistoryTypeId="2" PostId="12321" RevisionGUID="1d24c0c4-4f7a-4e04-b584-9c5ccdb6b039" CreationDate="2021-11-09T11:55:48.790" UserId="17498" Text="We have a circle image with dimensions 60 by 60 px. We want to display this image in a smaller size (15 by 15) on a website using HTML / CSS. When we do so, the image looks blurry (ignore the cropped edges, I believe that is another issue.&#xD;&#xA;&#xD;&#xA;Could you please explain to me in very noob terms:&#xD;&#xA;- Why this is happening&#xD;&#xA;- How I can solve it&#xD;&#xA;&#xD;&#xA;Much appreciated. Not sure what tags to use so kindly feel free to edit.&#xD;&#xA;&#xD;&#xA;[![Screenshot of circle image scaled down to 15 by 15][1]][1]&#xD;&#xA;[![circle image 60x60][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nBqvE.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hnNfR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35380" PostHistoryTypeId="1" PostId="12321" RevisionGUID="1d24c0c4-4f7a-4e04-b584-9c5ccdb6b039" CreationDate="2021-11-09T11:55:48.790" UserId="17498" Text="60px * 60px circle image appears pixellated when scaled down to 15px * 15px" ContentLicense="CC BY-SA 4.0" />
  <row Id="35381" PostHistoryTypeId="3" PostId="12321" RevisionGUID="1d24c0c4-4f7a-4e04-b584-9c5ccdb6b039" CreationDate="2021-11-09T11:55:48.790" UserId="17498" Text="|rendering|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35382" PostHistoryTypeId="5" PostId="12321" RevisionGUID="36b49a23-5590-4743-9e0a-086bf1f86895" CreationDate="2021-11-09T12:10:19.660" UserId="17498" Comment="added 224 characters in body" Text="We have a circle image with dimensions 60 by 60 px. We want to display this image in a smaller size (15 by 15) on a website using HTML / CSS. When we do so, the image looks blurry (ignore the cropped edges, I believe that is another issue.&#xD;&#xA;&#xD;&#xA;Could you please explain to me in very noob terms:&#xD;&#xA;- Why this is happening&#xD;&#xA;- How I can solve it&#xD;&#xA;&#xD;&#xA;Much appreciated. Not sure what tags to use so kindly feel free to edit.&#xD;&#xA;&#xD;&#xA;Edit: My understanding is that what I'm asking for may simply be impossible? An image this small simply doesn't have enough pixels available to draw a smooth edge for the circle? What kind of workaround could I envision?&#xD;&#xA;&#xD;&#xA;For instance [drawing a tiny circle in Canvas JS][1] leads to the same issue.&#xD;&#xA;&#xD;&#xA;[![Screenshot of circle image scaled down to 15 by 15][2]][2]&#xD;&#xA;[![circle image 60x60][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.bitdegree.org/learn/best-code-editor/cRDIFdjO&#xD;&#xA;  [2]: https://i.stack.imgur.com/nBqvE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/hnNfR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35383" PostHistoryTypeId="2" PostId="12322" RevisionGUID="88a1580b-7cab-4fef-8f54-ae52e7fdb16c" CreationDate="2021-11-10T02:01:17.500" UserId="7462" Text="This is a trackball camera:&#xD;&#xA;&#xD;&#xA;https://www.khronos.org/opengl/wiki/Object_Mouse_Trackball&#xD;&#xA;&#xD;&#xA;Vulkan users beware, the coordinate system flips and so some of the signs in your computations should eb different." ContentLicense="CC BY-SA 4.0" />
  <row Id="35385" PostHistoryTypeId="2" PostId="12323" RevisionGUID="99d15483-4523-42f0-9528-adafa038f83b" CreationDate="2021-11-10T11:04:38.350" UserDisplayName="user17488" Text="We know that in parametric continuity, $C^1$ continuity is two successive curve section $C_1$ and $C_2$ has first parametric derivative is same. That means tangent  vector $t_1$ is same for both $C_1$ and $C_2$ and has same direction and magnitudes are same. Like $C_1'(t=1)=C_2'(t=0).$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Confusion:1**&#xD;&#xA;My question is the above image is right for $C^1$ continuity w. r. t tangent $t_1$ of $C_1$ and $C_2?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But geometric continuity $G^1$ continuity is two successive curve section $C_3$ and $C_4$ has first parametric derivative is proportional to each other. That means tangent  vector $t_2$ and $t_3$ has same direction  for both curve sections $C_3$ and $C_4$ and  their magnitudes may or may not be same. Like: $G_1'(t=1)=(a,b,c),G_2'(t=0)=(ka,kb,kc).$ &#xD;&#xA;&#xD;&#xA;That means two tangents $t_2$ and $t_3$ are parallel to each other. Like: [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Confusion:2**&#xD;&#xA;My question is  above image is right, to show the parallelity of the tangents $t_2$ and $t_3$ for curve sections $C_3$ and $C_4?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;We know that $C^1$ and $G^1$ continuity means $C^0$ and $G^0$ respectively. But read from  (shown below)internet which showing $C^1$ and $G^1$  continuity, but $C^0$ and $G^0$ continuity not holding because&#xD;&#xA; $r(t=1) =(-1,1) {\neq}n(t=0)=(1,1).$ &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LoYMi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1F0ff.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/5mdsR.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35387" PostHistoryTypeId="1" PostId="12323" RevisionGUID="99d15483-4523-42f0-9528-adafa038f83b" CreationDate="2021-11-10T11:04:38.350" UserDisplayName="user17488" Text="Continuity of parametric and geometric continuity" ContentLicense="CC BY-SA 4.0" />
  <row Id="35388" PostHistoryTypeId="3" PostId="12323" RevisionGUID="99d15483-4523-42f0-9528-adafa038f83b" CreationDate="2021-11-10T11:04:38.350" UserDisplayName="user17488" Text="|curve|bezier-curve|parametrization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35389" PostHistoryTypeId="5" PostId="12323" RevisionGUID="97f5a656-53eb-49a1-a79d-9d3a9bf723b6" CreationDate="2021-11-10T11:09:48.357" UserDisplayName="user17488" Comment="added 125 characters in body; added 4 characters in body" Text="We know that in parametric continuity, $C^1$ continuity is two successive curve section $C_1$ and $C_2$ has first parametric derivative is same. That means tangent  vector $t_1$ is same for both $C_1$ and $C_2$ and has same direction and magnitudes are same. Like $C_1'(t=1)=C_2'(t=0).$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Confusion:1**&#xD;&#xA;My question is the above image is right for $C^1$ continuity w. r. t tangent $t_1$ of $C_1$ and $C_2?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But geometric continuity $G^1$ continuity is two successive curve section $C_3$ and $C_4$ has first parametric derivative is proportional to each other. That means tangent  vector $t_2$ and $t_3$ has same direction  for both curve sections $C_3$ and $C_4$ and  their magnitudes may or may not be same. Like: $G_1'(t=1)=(a,b,c),G_2'(t=0)=(ka,kb,kc).$ &#xD;&#xA;&#xD;&#xA;That means two tangents $t_2$ and $t_3$ are parallel to each other. Like: [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Confusion:2**&#xD;&#xA;My question is  above image is right, to show the parallelity of the tangents $t_2$ and $t_3$ for curve sections $C_3$ and $C_4?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;We know that $C^1$ and $G^1$ continuity means $C^0$ and $G^0$ respectively. But read from  (shown below)internet which showing $C^1$ and $G^1$  continuity, but $C^0$ and $G^0$ continuity not holding because&#xD;&#xA; $r(t=1) =(-1,1) {\neq}n(t=0)=(1,1).$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LoYMi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1F0ff.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/5mdsR.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Confusion:3**&#xD;&#xA;My question is how can I say  $C^1$ or $G^1$ continuity hold inspite of  $C^0$ and $G^0$ not holding? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35390" PostHistoryTypeId="5" PostId="12323" RevisionGUID="ec1cb5e4-73b2-4623-867c-a2b239b647e9" CreationDate="2021-11-10T11:19:33.817" UserDisplayName="user17488" Comment="edited body" Text="We know that in parametric continuity, $C^1$ continuity is two successive curve section $C_1$ and $C_2$ has first parametric derivative is same. That means tangent  vector $t_1$ is same for both $C_1$ and $C_2$ and has same direction and magnitudes are same. Like $C_1'(t=1)=C_2'(t=0).$&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Confusion:1**&#xD;&#xA;My question is the above image is right for $C^1$ continuity w. r. t tangent $t_1$ of $C_1$ and $C_2?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But geometric continuity $G^1$ continuity is two successive curve section $C_3$ and $C_4$ has first parametric derivative is proportional to each other. That means tangent  vector $t_2$ and $t_3$ has same direction  for both curve sections $C_3$ and $C_4$ and  their magnitudes may or may not be same. Like: $C_3'(t=1)=(a,b,c),C_4'(t=0)=(ka,kb,kc).$ &#xD;&#xA;&#xD;&#xA;That means two tangents $t_2$ and $t_3$ are parallel to each other. Like: [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Confusion:2**&#xD;&#xA;My question is  above image is right, to show the parallelity of the tangents $t_2$ and $t_3$ for curve sections $C_3$ and $C_4?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;We know that $C^1$ and $G^1$ continuity means $C^0$ and $G^0$ respectively. But read from  (shown below)internet which showing $C^1$ and $G^1$  continuity, but $C^0$ and $G^0$ continuity not holding because&#xD;&#xA; $r(t=1) =(-1,1) {\neq}n(t=0)=(1,1).$ &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LoYMi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/1F0ff.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/5mdsR.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Confusion:3**&#xD;&#xA;My question is how can I say  $C^1$ or $G^1$ continuity hold inspite of  $C^0$ and $G^0$ not holding? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35391" PostHistoryTypeId="2" PostId="12324" RevisionGUID="c800c8af-5a1c-48db-8350-35fb8a752ef2" CreationDate="2021-11-10T11:59:55.893" UserId="13095" Text="&gt; My understanding is that what I'm asking for may simply be impossible? An image this small simply doesn't have enough pixels available to draw a smooth edge for the circle? &#xD;&#xA;&#xD;&#xA;This is more or less correct. Basically, no circle (or curved surface) is really smooth when rendered to the screen (or to any other raster-based representation). With larger circles, the effect just isn't as obvious. &#xD;&#xA;&#xD;&#xA;Since your image is composed of colored squares (the pixels) there is no way you can represent anything without data loss that isn't a rectangle with its edges aligned to the screens-coordinate axis. So the question is how to build anything else within those constraints. &#xD;&#xA;&#xD;&#xA;What you can do is to calculate if the center of the pixel lies inside or outside of the geometrical shape you want to render. If it is inside, give it the correct color, if not, leave it untouched. However, this is a binary process and leaves you with visible &quot;jumps&quot;. A diagonal line would look like stairs. To get rid of this effect, you can take any pixel that is only partially inside your shape and calculate the ratio between the area that is inside and outside of the shape. You then use this ratio to mix the color of the shape with the background color and assign this as the new pixel color. &#xD;&#xA;&#xD;&#xA;For large circles, this will give you the illusion of an almost perfectly smooth surface since the count of those interpolated pixels is relatively low when compared to the rest of the circles' pixels. But the smaller it gets, the more of those color-mixed pixels you will have in relation to the pixels that have the full color. The extreme case would be that the circle is inside of a single pixel and the less area of the said pixel it covers, the more it will &quot;fade out&quot;.&#xD;&#xA;&#xD;&#xA;When downscaling you are facing the same problems. You compute the average value of multiple pixels and assign it to a single one. If there is one pixel that isn't fully inside of the shape, the color will get blurred.&#xD;&#xA;&#xD;&#xA;So in conclusion, there is not much you can do about the &quot;blurriness&quot;. The alternative would be to disable the interpolation but this would give you a staircase pattern, which is also not really what you want." ContentLicense="CC BY-SA 4.0" />
  <row Id="35393" PostHistoryTypeId="10" PostId="12323" RevisionGUID="d7b3d4b0-844d-4b93-8580-b5e930ea5872" CreationDate="2021-11-10T15:45:12.250" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="35394" PostHistoryTypeId="2" PostId="12325" RevisionGUID="890add90-3d3e-4881-95e0-8512690d2c4d" CreationDate="2021-11-10T19:05:48.683" UserId="16126" Text="I'm trying to create a vertex shader that billboards a quad. Most resources online show the code to be some variation of the following&#xD;&#xA;&#xD;&#xA;    gl_Position = project * (view * model * billbrd_pos + vec4(position.xy, 0, 0));&#xD;&#xA;&#xD;&#xA;So I tried doing something similar in HLSL after doing some research&#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),	// 0&#xD;&#xA;        float3(1, 1, 0),	// 1&#xD;&#xA;        float3(-1, -1, 0),	// 2&#xD;&#xA;        float3(-1, -1, 0),	// 3&#xD;&#xA;        float3(1, 1, 0),	// 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    input.position.w = 1.0f;&#xD;&#xA;&#xD;&#xA;    float3 bpos = BILLBOARD[vertexID];&#xD;&#xA;    &#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;&#xD;&#xA;    output.position = mul(projectionMatrix,&#xD;&#xA;        mul(WV, float4(bpos, 1.0f))&#xD;&#xA;        + float4(input.position.x, input.position.y, 0.0f, 0.0f)&#xD;&#xA;        * float4(1.0f, 1.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;But this doesn't work as the quad disappears from the screen. How can I achieve billboarding in a vertex shader in HLSL?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35396" PostHistoryTypeId="1" PostId="12325" RevisionGUID="890add90-3d3e-4881-95e0-8512690d2c4d" CreationDate="2021-11-10T19:05:48.683" UserId="16126" Text="Billboarding in Vertex Shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="35397" PostHistoryTypeId="3" PostId="12325" RevisionGUID="890add90-3d3e-4881-95e0-8512690d2c4d" CreationDate="2021-11-10T19:05:48.683" UserId="16126" Text="|hlsl|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35398" PostHistoryTypeId="50" PostId="4703" RevisionGUID="40c78b9b-334c-4acd-839a-b1b47264600c" CreationDate="2021-11-11T11:05:50.577" UserId="-1" />
  <row Id="35399" PostHistoryTypeId="2" PostId="12326" RevisionGUID="544c9623-98f3-413d-94ac-14a692ce29d8" CreationDate="2021-11-11T11:08:55.543" UserId="17510" Text="[![beam transmittance][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6utiT.png&#xD;&#xA;&#xD;&#xA;In pbrt v3, the book gives this description of beam transmittance, but I don't know how to solve the differential equation like it says to get **Tr** , can someone please tell me how to solve the differential equation? Thanks a lot." ContentLicense="CC BY-SA 4.0" />
  <row Id="35401" PostHistoryTypeId="1" PostId="12326" RevisionGUID="544c9623-98f3-413d-94ac-14a692ce29d8" CreationDate="2021-11-11T11:08:55.543" UserId="17510" Text="How is the beam transmittance calculated in PBRT V3?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35402" PostHistoryTypeId="3" PostId="12326" RevisionGUID="544c9623-98f3-413d-94ac-14a692ce29d8" CreationDate="2021-11-11T11:08:55.543" UserId="17510" Text="|rendering|algorithm|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35403" PostHistoryTypeId="2" PostId="12327" RevisionGUID="7fae02e9-e9c4-4bdf-9ba3-eccd5602fcc9" CreationDate="2021-11-11T12:07:44.667" UserId="7952" Text="I did a little code cleaning and came up with this:&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),   // 0&#xD;&#xA;        float3(1, 1, 0),    // 1&#xD;&#xA;        float3(-1, -1, 0),  // 2&#xD;&#xA;        float3(-1, -1, 0),  // 3&#xD;&#xA;        float3(1, 1, 0),    // 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    float4 bpos = float4( input.position.xy, 0, 0);&#xD;&#xA;    float4 bbOffset = float4(BILLBOARD[vertexID],0);&#xD;&#xA;&#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;    float4 Vpos = mul(WV, float4(bpos, 1.0f));&#xD;&#xA;    float4 OffsetPos = Vpos + bbOffset;&#xD;&#xA;    float4 projected = mul( projectionMatrix, OffsetPos);&#xD;&#xA;&#xD;&#xA;    output.position = projected;&#xD;&#xA;&#xD;&#xA;The code you posted is using the billboard offset to compute the Vpos, but what you really want is to use the input.position (the billboard position) to compute the camera space position. This became clear after doing the code clean up. I'm not sure if it will &quot;fix&quot; the code, but it should get you a step closer.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35405" PostHistoryTypeId="5" PostId="12327" RevisionGUID="cf9da6d2-74b9-45e3-bc70-e0f157984e67" CreationDate="2021-11-11T12:13:04.317" UserId="7952" Comment="deleted 14 characters in body" Text="I did a little code cleaning and came up with this:&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),   // 0&#xD;&#xA;        float3(1, 1, 0),    // 1&#xD;&#xA;        float3(-1, -1, 0),  // 2&#xD;&#xA;        float3(-1, -1, 0),  // 3&#xD;&#xA;        float3(1, 1, 0),    // 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    float4 bpos = float4( input.position.xy, 0, 0);&#xD;&#xA;    float4 bbOffset = float4(BILLBOARD[vertexID],0);&#xD;&#xA;&#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;    float4 Vpos = mul(WV, bpos);&#xD;&#xA;    float4 OffsetPos = Vpos + bbOffset;&#xD;&#xA;    float4 projected = mul( projectionMatrix, OffsetPos);&#xD;&#xA;&#xD;&#xA;    output.position = projected;&#xD;&#xA;&#xD;&#xA;The code you posted is using the billboard offset to compute the Vpos, but what you really want is to use the input.position (the billboard position) to compute the camera space position. This became clear after doing the code clean up. I'm not sure if it will &quot;fix&quot; the code, but it should get you a step closer.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35406" PostHistoryTypeId="5" PostId="12325" RevisionGUID="ba68b718-e7d4-4355-b1ff-7056d6123d0a" CreationDate="2021-11-11T18:31:46.140" UserId="16126" Comment="edit" Text="I'm trying to create a vertex shader that billboards a quad. Most resources online show the code to be some variation of the following&#xD;&#xA;&#xD;&#xA;    gl_Position = project * (view * model * billbrd_pos + vec4(position.xy, 0, 0));&#xD;&#xA;&#xD;&#xA;So I tried doing something similar in HLSL after doing some research&#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),	// 0&#xD;&#xA;        float3(1, 1, 0),	// 1&#xD;&#xA;        float3(-1, -1, 0),	// 2&#xD;&#xA;        float3(-1, -1, 0),	// 3&#xD;&#xA;        float3(1, 1, 0),	// 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    input.position.w = 1.0f;&#xD;&#xA;&#xD;&#xA;    float3 bpos = BILLBOARD[vertexID];&#xD;&#xA;    &#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;&#xD;&#xA;    output.position = mul(projectionMatrix,&#xD;&#xA;        mul(WV, float4(bpos, 1.0f))&#xD;&#xA;        + float4(input.position.x, input.position.y, 0.0f, 0.0f)&#xD;&#xA;        * float4(1.0f, 1.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;But this doesn't work as the quad disappears from the screen. How can I achieve billboarding in a vertex shader in HLSL?&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;As per @pmw1234 's answer I modified the code to look like this:&#xD;&#xA;&#xD;&#xA;    float4 bpos = float4(input.position.xy, 0.0f, 1.0);&#xD;&#xA;    float4 bbOffset = float4(BILLBOARD[vertexID], 1.0f);&#xD;&#xA;&#xD;&#xA;    float4 Vpos = mul(bpos, worldMatrix);&#xD;&#xA;    Vpos = mul(Vpos, viewMatrix);&#xD;&#xA;&#xD;&#xA;    float4 OffsetPos = Vpos + bbOffset;&#xD;&#xA;    float4 projected = mul(OffsetPos, projectionMatrix);&#xD;&#xA;&#xD;&#xA;    output.position = projected;&#xD;&#xA;&#xD;&#xA;This alone doesn't really create the billboard effect that one would expect, as there is not much rotation on the quad, but modifying the bbOffset variable like shown below now creates something that resembles a billboard. The quad now moves with the camera rotation. Unfortunately, the quad ends up distorted as a result:&#xD;&#xA;&#xD;&#xA;    float3 rot = mul((float3x3)viewMatrix, 5.0f.xxx);&#xD;&#xA;    bbOffset.z += dot(bbOffset, rot) * rot * 1.0f;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MVLqw.jpg&#xD;&#xA;&#xD;&#xA;The sprite should be square shaped" ContentLicense="CC BY-SA 4.0" />
  <row Id="35407" PostHistoryTypeId="2" PostId="12328" RevisionGUID="937230bd-379d-4e78-8793-9af67d86d9aa" CreationDate="2021-11-11T19:44:12.457" UserId="17514" Text="At the moment I am looking for a tablet to use the bike simulator app &quot;BKOOL&quot;.&#xD;&#xA;The Samsung Galaxy Tab S6 Lite is my current favorite and it meets almost all app requirements (https://www.bkool.com/en/apps?updateLocale=1), but I'm not sure about the GPU &quot; ARM Mali-G72 MP3 &quot;.&#xD;&#xA;The ARM Mali-G72 MP3 supports OpenGL ES 3.2 (https://www.notebookcheck.net/ARM-Mali-G72-MP3-GPU.301008.0.html), but OpenGL 3.0 is required.&#xD;&#xA;&#xD;&#xA;If a GPU supports OpenGL ES 3.2, does it also support OpenGL 3.0?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35409" PostHistoryTypeId="1" PostId="12328" RevisionGUID="937230bd-379d-4e78-8793-9af67d86d9aa" CreationDate="2021-11-11T19:44:12.457" UserId="17514" Text="If a GPU supports OpenGL ES 3.2, does it also support OpenGl 3.0?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35410" PostHistoryTypeId="3" PostId="12328" RevisionGUID="937230bd-379d-4e78-8793-9af67d86d9aa" CreationDate="2021-11-11T19:44:12.457" UserId="17514" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35411" PostHistoryTypeId="5" PostId="12328" RevisionGUID="ebec4615-1a3d-4637-bd3b-f3273fe9a696" CreationDate="2021-11-11T20:43:17.330" UserId="17514" Comment="added picture" Text="At the moment I am looking for a tablet to use the bike simulator app &quot;BKOOL&quot;.&#xD;&#xA;The Samsung Galaxy Tab S6 Lite is my current favorite and it meets almost all app requirements (https://www.bkool.com/en/apps?updateLocale=1), but I'm not sure about the GPU &quot; ARM Mali-G72 MP3 &quot;.&#xD;&#xA;The ARM Mali-G72 MP3 supports OpenGL ES 3.2 (https://www.notebookcheck.net/ARM-Mali-G72-MP3-GPU.301008.0.html), but OpenGL 3.0 is required.&#xD;&#xA;&#xD;&#xA;If a GPU supports OpenGL ES 3.2, does it also support OpenGL 3.0?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WBzWN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35412" PostHistoryTypeId="2" PostId="12329" RevisionGUID="73e794cc-7d58-480c-9451-7f7798be0261" CreationDate="2021-11-11T22:08:34.573" UserId="2654" Text="That looks like a typo. Most mobile GPUs don't support desktop GL of any version, so they probably meant OpenGL ES 3.0 (which is a valid version)&#xD;&#xA;&#xD;&#xA;And yes, ES 3.0 is backwards compatible with ES 3.2." ContentLicense="CC BY-SA 4.0" />
  <row Id="35420" PostHistoryTypeId="11" PostId="12323" RevisionGUID="675ec38e-4f21-4dc5-b702-4c0f154b4caa" CreationDate="2021-11-12T08:07:09.410" UserId="13095" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="35421" PostHistoryTypeId="2" PostId="12331" RevisionGUID="b058cf03-51be-4ca3-b3d6-88e4d33df6ce" CreationDate="2021-11-12T08:07:54.147" UserId="17520" Text="I'm using three.js combined with face recognition, I want to rotate a sphere that displays my input video according to the detected eye location,&#xD;&#xA;the face recognition gives me a X,Y on the texture mapped to the sphere, what is the right way to find the matching angles on the sphere?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35423" PostHistoryTypeId="1" PostId="12331" RevisionGUID="b058cf03-51be-4ca3-b3d6-88e4d33df6ce" CreationDate="2021-11-12T08:07:54.147" UserId="17520" Text="Finding a texture pixel (X,Y) on a Sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="35424" PostHistoryTypeId="3" PostId="12331" RevisionGUID="b058cf03-51be-4ca3-b3d6-88e4d33df6ce" CreationDate="2021-11-12T08:07:54.147" UserId="17520" Text="|geometry|projections|uv-mapping|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35425" PostHistoryTypeId="5" PostId="12327" RevisionGUID="3dd4c56e-b31a-41fc-9e83-7b3759959ae3" CreationDate="2021-11-12T11:55:11.797" UserId="7952" Comment="Added a bit of info on orienting the billboard" Text="I did a little code cleaning and came up with this:&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),   // 0&#xD;&#xA;        float3(1, 1, 0),    // 1&#xD;&#xA;        float3(-1, -1, 0),  // 2&#xD;&#xA;        float3(-1, -1, 0),  // 3&#xD;&#xA;        float3(1, 1, 0),    // 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    float4 bpos = float4( input.position.xy, 0, 0);&#xD;&#xA;    float4 bbOffset = float4(BILLBOARD[vertexID],0);&#xD;&#xA;&#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;    float4 Vpos = mul(WV, bpos);&#xD;&#xA;    float4 OffsetPos = Vpos + bbOffset;&#xD;&#xA;    float4 projected = mul( projectionMatrix, OffsetPos);&#xD;&#xA;&#xD;&#xA;    output.position = projected;&#xD;&#xA;&#xD;&#xA;The code you posted is using the billboard offset to compute the Vpos, but what you really want is to use the input.position (the billboard position) to compute the camera space position. This became clear after doing the code clean up. I'm not sure if it will &quot;fix&quot; the code, but it should get you a step closer.&#xD;&#xA;&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;There are a number of ways to compute billboard orientation. One trick is to simply overwrite the upper 3x3 portion of the view matrix with the identity matrix before using it to compute the vertex.&#xD;&#xA;&#xD;&#xA;Another is to compute a forward vector ie &#xD;&#xA;&#xD;&#xA;    n = normalize(camera_pos - bb_pos);&#xD;&#xA;&#xD;&#xA;then, a down vector ie &#xD;&#xA;&#xD;&#xA;    d = normalize(cross(n, camera_down);&#xD;&#xA;&#xD;&#xA;and finally a right vector &#xD;&#xA;&#xD;&#xA;    r = cross( n, d);&#xD;&#xA;&#xD;&#xA;These can be used to rotate the bb position with matrix multiplication.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35426" PostHistoryTypeId="5" PostId="12327" RevisionGUID="68d59570-ba4b-4efb-b91b-cb320f326733" CreationDate="2021-11-12T12:52:48.860" UserId="7952" Comment="added 3 characters in body" Text="I did a little code cleaning and came up with this:&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),   // 0&#xD;&#xA;        float3(1, 1, 0),    // 1&#xD;&#xA;        float3(-1, -1, 0),  // 2&#xD;&#xA;        float3(-1, -1, 0),  // 3&#xD;&#xA;        float3(1, 1, 0),    // 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    float4 bpos = float4( input.position.xy, 0, 0);&#xD;&#xA;    float4 bbOffset = float4(BILLBOARD[vertexID],0);&#xD;&#xA;&#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;    float4 Vpos = mul(WV, bpos);&#xD;&#xA;    float4 OffsetPos = Vpos + bbOffset;&#xD;&#xA;    float4 projected = mul( projectionMatrix, OffsetPos);&#xD;&#xA;&#xD;&#xA;    output.position = projected;&#xD;&#xA;&#xD;&#xA;The code you posted is using the billboard offset to compute the Vpos, but what you really want is to use the input.position (the billboard position) to compute the camera space position. This became clear after doing the code clean up. I'm not sure if it will &quot;fix&quot; the code, but it should get you a step closer.&#xD;&#xA;&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;There are a number of ways to compute billboard orientation. One trick is to simply overwrite the upper 3x3 portion of the view matrix with the identity matrix before using it to compute the vertex.&#xD;&#xA;&#xD;&#xA;Another is to compute a forward vector ie &#xD;&#xA;&#xD;&#xA;    n = normalize(camera_pos - bb_pos);&#xD;&#xA;&#xD;&#xA;then, a right vector ie &#xD;&#xA;&#xD;&#xA;    d = normalize(cross(n, camera_down);&#xD;&#xA;&#xD;&#xA;and finally a down/up vector &#xD;&#xA;&#xD;&#xA;    r = cross( n, d);&#xD;&#xA;&#xD;&#xA;These can be used to rotate the bb position with matrix multiplication.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35432" PostHistoryTypeId="5" PostId="12325" RevisionGUID="774f524d-0f0d-47ab-84f7-fd4fc8b80d5b" CreationDate="2021-11-12T18:12:16.803" UserId="16126" Comment="deleted 423 characters in body" Text="I'm trying to create a vertex shader that billboards a quad. Most resources online show the code to be some variation of the following&#xD;&#xA;&#xD;&#xA;    gl_Position = project * (view * model * billbrd_pos + vec4(position.xy, 0, 0));&#xD;&#xA;&#xD;&#xA;So I tried doing something similar in HLSL after doing some research&#xD;&#xA;&#xD;&#xA;    static const float3 BILLBOARD[] = {&#xD;&#xA;        float3(-1, 1, 0),	// 0&#xD;&#xA;        float3(1, 1, 0),	// 1&#xD;&#xA;        float3(-1, -1, 0),	// 2&#xD;&#xA;        float3(-1, -1, 0),	// 3&#xD;&#xA;        float3(1, 1, 0),	// 4&#xD;&#xA;        float3(1, -1, 0),  // 5&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    input.position.w = 1.0f;&#xD;&#xA;&#xD;&#xA;    float3 bpos = BILLBOARD[vertexID];&#xD;&#xA;    &#xD;&#xA;    matrix WV = mul(worldMatrix, viewMatrix);&#xD;&#xA;&#xD;&#xA;    output.position = mul(projectionMatrix,&#xD;&#xA;        mul(WV, float4(bpos, 1.0f))&#xD;&#xA;        + float4(input.position.x, input.position.y, 0.0f, 0.0f)&#xD;&#xA;        * float4(1.0f, 1.0f, 1.0f, 1.0f));&#xD;&#xA;&#xD;&#xA;But this doesn't work as the quad disappears from the screen. How can I achieve billboarding in a vertex shader in HLSL?&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;As per @pmw1234 's answer I changed the upper 3x3 section of the view matrix to an identity matrix as shown below, the billboard now works correctly.&#xD;&#xA;&#xD;&#xA;    matrix viewIdentity = viewMatrix;&#xD;&#xA;    viewIdentity[0][0] = 1;&#xD;&#xA;    viewIdentity[0][1] = 0;&#xD;&#xA;    viewIdentity[0][2] = 0;&#xD;&#xA;&#xD;&#xA;    viewIdentity[1][0] = 0;&#xD;&#xA;    viewIdentity[1][1] = 1;&#xD;&#xA;    viewIdentity[1][2] = 0;&#xD;&#xA;&#xD;&#xA;    viewIdentity[2][0] = 0;&#xD;&#xA;    viewIdentity[2][1] = 0;&#xD;&#xA;    viewIdentity[2][2] = 1;&#xD;&#xA;&#xD;&#xA;    float4 Vpos = mul(bpos, worldMatrix);&#xD;&#xA;    Vpos = mul(Vpos, viewIdentity);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35433" PostHistoryTypeId="5" PostId="12331" RevisionGUID="03932729-3093-4be0-9c53-ad523c7f73ef" CreationDate="2021-11-12T19:57:35.720" UserId="17520" Comment="added 501 characters in body" Text="I'm using three.js combined with face recognition, I want to rotate a sphere that displays my input video according to the detected eye location,&#xD;&#xA;the face recognition gives me a X,Y on the texture mapped to the sphere, what is the right way to find the matching angles on the sphere?&#xD;&#xA;&#xD;&#xA;I've tried the next code that I've found -&#xD;&#xA;&#xD;&#xA;    function convert2d3d(r1, r2, x, y) {&#xD;&#xA;     // r1 - texture size ?&#xD;&#xA;     // r2 - sphere size&#xD;&#xA;     // x,y - position I want to reach on the sphere&#xD;&#xA;&#xD;&#xA;     let z = -1 + 2 * x / r1;&#xD;&#xA;     let phi = 2 * Math.PI * y / r1;&#xD;&#xA;     let theta = Math.asin(z);&#xD;&#xA;       return {&#xD;&#xA;        x: r2 * Math.cos(theta) * Math.cos(phi),&#xD;&#xA;        y: r2 * Math.cos(theta) * Math.sin(phi),&#xD;&#xA;        z: r2 * z,&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But I think I'm not getting the result I need" ContentLicense="CC BY-SA 4.0" />
  <row Id="35434" PostHistoryTypeId="5" PostId="12331" RevisionGUID="b0d59953-33d9-4ac6-93f9-0fbc82d22b71" CreationDate="2021-11-12T20:46:57.630" UserId="17520" Comment="added 169 characters in body" Text="I'm using three.js combined with face recognition, I want to rotate a sphere that displays my input video according to the detected eye location,&#xD;&#xA;the face recognition gives me a X,Y on the texture mapped to the sphere, what is the right way to find the matching angles on the sphere?&#xD;&#xA;&#xD;&#xA;I've tried the next code that I've found -&#xD;&#xA;&#xD;&#xA;    function convert2d3d(r1, r2, x, y) {&#xD;&#xA;     // r1 - texture size ?&#xD;&#xA;     // r2 - sphere size&#xD;&#xA;     // x,y - position I want to reach on the sphere&#xD;&#xA;&#xD;&#xA;     let z = -1 + 2 * x / r1;&#xD;&#xA;     let phi = 2 * Math.PI * y / r1;&#xD;&#xA;     let theta = Math.asin(z);&#xD;&#xA;       return {&#xD;&#xA;        x: r2 * Math.cos(theta) * Math.cos(phi),&#xD;&#xA;        y: r2 * Math.cos(theta) * Math.sin(phi),&#xD;&#xA;        z: r2 * z,&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![I’m attempting to find detected eye position on sphere and then rotate the sphere according to angle found][1]][1]&#xD;&#xA;&#xD;&#xA;But I think I'm not getting the result I need&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KZr7m.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35437" PostHistoryTypeId="2" PostId="12333" RevisionGUID="ab1a13b6-eb89-4fbb-a63f-1dedd37a4387" CreationDate="2021-11-13T15:09:47.520" UserId="7952" Text="For the rotation:&#xD;&#xA;&#xD;&#xA;It looks like this will be the combination of two rotations. Assuming Z is the up direction then the first rotation is in the XY plane and the second rotation is in the ZY plane.&#xD;&#xA;&#xD;&#xA;To get the angle of the first rotation you can do something along the lines of:&#xD;&#xA;  &#xD;&#xA;    vec4 eye_vec = normalize( sphere_center - eye_position);&#xD;&#xA;    vec4 camera_vec = normalize( sphere_ceneter - camera_position );&#xD;&#xA;    float cosAngle = dot( camera_vec, eye_vec );&#xD;&#xA;    float rads_xy = acos( cosAngle );&#xD;&#xA;    mat4 xy_rotation_matrix = MakeRotationXYplane( rads_xy);&#xD;&#xA;&#xD;&#xA;The second rotation:&#xD;&#xA;&#xD;&#xA;    vec4 forward_vec = normalize( camera_forward );&#xD;&#xA;    cosAngle = dot( forward_vec, eye_vec );&#xD;&#xA;    float rads_zy = acos( cosAngle );&#xD;&#xA;    mat4 zy_rotation_matrix = MakeRotationZYplane( rads_zy );&#xD;&#xA;&#xD;&#xA;and finally:&#xD;&#xA;&#xD;&#xA;    mat4 combined_rotations = xy_rotation_matrix * zy_rotation_matrix;&#xD;&#xA;&#xD;&#xA;Rotation order could be an issue here, but so long as sphere is at the origin then it should be okay.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To test this part of the code I recommend picking a known eye location on the sphere. Even mark it to help visualize the rotations. I didn't include code for the actual construction of the rotation matrices but that is easy to find. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35443" PostHistoryTypeId="2" PostId="12335" RevisionGUID="984b8375-cf11-410a-b4fc-a198377a82f8" CreationDate="2021-11-13T21:24:23.167" UserId="48" Text="It's a version of the standard derivation of the exponential function from its differential equation, by separation of variables.&#xD;&#xA;&#xD;&#xA;To review that standard derivation: suppose we want a function $y(x)$ obeying the differential equation $\mathrm{d}y/\mathrm{d}x = -ky$, for some constant $k$. Then we can solve the equation as follows:&#xD;&#xA;$$&#xD;&#xA;\begin{aligned}&#xD;&#xA;\mathrm{d}y &amp;= -ky \, \mathrm{d}x \\&#xD;&#xA;\frac{\mathrm{d}y}{y} &amp;= -k \, \mathrm{d}x \\&#xD;&#xA;\int \frac{\mathrm{d}y}{y} &amp;= -\int k \, \mathrm{d}x \\&#xD;&#xA;\ln y &amp;= -kx \\&#xD;&#xA;y &amp;= e^{-kx}&#xD;&#xA;\end{aligned}&#xD;&#xA;$$&#xD;&#xA;(there should actually be some constants of integration in there, but I left them out since they're not important for this answer.)&#xD;&#xA;&#xD;&#xA;Now, suppose we generalize and make the constant $k$ into a function $k(x)$. Then we can repeat this derivation, but we will not be able to do the integral on the right side, since $k(x)$ is unspecified. The result will then be:&#xD;&#xA;$$&#xD;&#xA;y = e^{-\int k(x) \, \mathrm{d}x}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The derivation for the transmittance along a ray is just the same, but with some variables renamed: $y$ becomes $L$, $x$ is now the parameter $t$ along the ray, and $k(x)$ is called $\sigma_\mathrm{t}(\mathrm{p})$." ContentLicense="CC BY-SA 4.0" />
  <row Id="35446" PostHistoryTypeId="5" PostId="9269" RevisionGUID="b6c06086-3af7-4ee1-b629-ea5671eb377e" CreationDate="2021-11-14T14:23:00.320" UserId="2654" Comment="deleted 174 characters in body" Text="For whatever reason, the text for that function documentation was copied from the GL_ARB_program_interface_query extension. Extensions in OpenGL are always defined relative to a specific version of the OpenGL specification. So if an extension references something in a specification, it's talking about that version of the spec.&#xD;&#xA;&#xD;&#xA;However, the OpenGL specification was *massively* restructured between 4.2 and 4.3, with whole chapters moved around. This means that table references in 4.2 become completely wrong relative to 4.3 and above.&#xD;&#xA;&#xD;&#xA;Program interface query was written against the 4.2 specification. Oddly enough, there is no table 2.16 in that spec; the correct number for that table is 2.13 (so it's likely a typo, since 3 is right below 6 on a number-pad). But even if the extension did mention the right table number, that table moved to a whole different chapter in 4.3+ versions. It's been renumbered and moved since then, so you'll have to look at a particular specification's definition of `glGetProgramResourceiv` to find it.&#xD;&#xA;&#xD;&#xA;In general, if you find something incongruous in the documentation pages, you should look at the [actual OpenGL specification][1] to see what it says about the function's behavior.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/OpenGL/index_gl.php&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35447" PostHistoryTypeId="2" PostId="12336" RevisionGUID="03130e3b-5e37-4d9f-ba19-99ef60a343f3" CreationDate="2021-11-14T18:41:01.897" UserId="15772" Text="From what I understand, grey-scale bump maps are used to perturb normals on a surface such that the surface appears to have bumps. With a regular tangent normal map, it seems relatively intuitive enough, considering each pixel contains the 'normal' itself so to speak&#xD;&#xA;&#xD;&#xA;A bump map only measures changes in height as far as I know. In a software like Blender, I can plug in a grey-scale bump map and get results similar to the bumps produced by a normal map (Considering they more or less produce the same end result - to perturb normals), so certainly, these ARE being converted to normals somehow&#xD;&#xA;&#xD;&#xA;The question is how exactly. I've being cracking my head over this for so long and after dozens of searches, can't find exactly what I need&#xD;&#xA;&#xD;&#xA;From what I know so far, since you only store height info in a bump map, the only meaningful way to 'extract' normals out of it is via finding the partial derivative along each axis of the bump map, and then.....I'm sorta blank in regards to the rest &#xD;&#xA;&#xD;&#xA;From what I know, to find the partial derivative along each axis, you could use the central difference method (or forward difference method), to find how much the function f(u,v) [that returns a pixel representing a height value at the coordinates on the map (u,v)] changes as we move from left to right (for partial derivatives along the x axis or u), and up to down for the y/v axis&#xD;&#xA;&#xD;&#xA;So we find how much the function changes as we move along either of the two axes. What do we do next to finally attain the normal? I am sorta lost. I would like some help with the intuition behind it as well rather than just plain equations since I really want to understand them thoroughly &#xD;&#xA;&#xD;&#xA;I will also add that I am just delving in the theory now, I haven't done any computer graphics programming YET, so I dont need any API specific help" ContentLicense="CC BY-SA 4.0" />
  <row Id="35449" PostHistoryTypeId="1" PostId="12336" RevisionGUID="03130e3b-5e37-4d9f-ba19-99ef60a343f3" CreationDate="2021-11-14T18:41:01.897" UserId="15772" Text="How are the normals 'derived' from grey scale bump maps?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35450" PostHistoryTypeId="3" PostId="12336" RevisionGUID="03130e3b-5e37-4d9f-ba19-99ef60a343f3" CreationDate="2021-11-14T18:41:01.897" UserId="15772" Text="|texture|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35451" PostHistoryTypeId="2" PostId="12337" RevisionGUID="2c46d0e1-2827-48f4-88d3-44088e8d3bbb" CreationDate="2021-11-14T20:53:23.420" UserId="10096" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small." ContentLicense="CC BY-SA 4.0" />
  <row Id="35453" PostHistoryTypeId="5" PostId="12337" RevisionGUID="f982cfe2-af5d-42de-82fc-1e66c1a51f4f" CreationDate="2021-11-14T20:58:36.753" UserId="10096" Comment="added 196 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35454" PostHistoryTypeId="2" PostId="12338" RevisionGUID="e310aac1-5531-46f9-a2cf-889726020772" CreationDate="2021-11-14T21:46:14.440" UserId="17533" Text="I'm attempting to use the jump flood algorithm to compute distance transforms of an arbitrary texture derived from a canvas2d context, roughly following the explanations detailed [here](https://blog.demofox.org/2016/02/29/fast-voronoi-diagrams-and-distance-dield-textures-on-the-gpu-with-the-jump-flooding-algorithm/)/[here](https://www.youtube.com/watch?v=A0pxY9QsgJE). &#xD;&#xA;&#xD;&#xA;[Here is the demo](https://nchilla.github.io/shaders/sdf-posters/experiments/parallel-flood-fill/) I have going. Click the 'next wave' button a few times and you'll notice that it takes 11 waves before anything starts happening, and eventually outputs something that is wrong in a way that I don't quite understand.&#xD;&#xA;&#xD;&#xA;[Here is the shader code](https://github.com/nchilla/shaders/blob/main/sdf-posters/experiments/parallel-flood-fill/jfa.frag) going with it, with the annotated jump flood step function. I'm using the A value to check if a pixel is filled in, and using RG to store the seed origin.&#xD;&#xA;&#xD;&#xA;My best guess at the moment is that there's an issue with how I'm calculating the offset in each shader pass. If you look at the web console, I'm outputting the pass index and what the offset is correspondingly *supposed* to be for each wave. But when I tried mapping the offset to the B value of each pixel in the shader, it turns out to be wildly off. &#xD;&#xA;&#xD;&#xA;Not sure if this community condones support posts, but supposing this one is okay, any help would be appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="35456" PostHistoryTypeId="1" PostId="12338" RevisionGUID="e310aac1-5531-46f9-a2cf-889726020772" CreationDate="2021-11-14T21:46:14.440" UserId="17533" Text="Having trouble implementing distance transform with jump flood" ContentLicense="CC BY-SA 4.0" />
  <row Id="35457" PostHistoryTypeId="3" PostId="12338" RevisionGUID="e310aac1-5531-46f9-a2cf-889726020772" CreationDate="2021-11-14T21:46:14.440" UserId="17533" Text="|shader|algorithm|mathematics|color|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35458" PostHistoryTypeId="6" PostId="12338" RevisionGUID="a11f63aa-34d3-4bc0-9fee-e85efe9a39f1" CreationDate="2021-11-14T22:02:25.920" UserId="17533" Comment="edited tags" Text="|shader|glsl|algorithm|mathematics|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35460" PostHistoryTypeId="2" PostId="12339" RevisionGUID="1ef550c1-bede-4862-bf3f-0ad20877fbef" CreationDate="2021-11-15T11:35:12.277" UserId="7952" Text="You are on the right track with your post...&#xD;&#xA;&#xD;&#xA;Compute two slopes then somehow use those slopes to find a normal. The slopes are the result of finite difference (like central difference)&#xD;&#xA;&#xD;&#xA;But why two slopes? Because we can use them to construct two independent vectors whose cross product will become our normal vector.&#xD;&#xA;&#xD;&#xA;One vector is in the texture's $u$ direction and is simply $vec3(1,0,slopeU)$&#xD;&#xA;&#xD;&#xA;The other vector is in the textures $v$ direction and is $vec3(0,1,slopeV)$&#xD;&#xA;&#xD;&#xA;Take the cross product and normalize, its really that simple.&#xD;&#xA;&#xD;&#xA;Both of the vectors are tangent to the height, and they are independent of each other. They can be constructed as $(0,1,S_y)$ and $(1,0,S_x)$ because the slopes are very specifically taken in those directions. If you change the directions used to compute the slopes then you have to change the directions used in the vectors to match.&#xD;&#xA;&#xD;&#xA;There are a few other minor caveats, like the calculations are assumed to always happen at the origin, and the height map, which usually contains values between 0 and 1 needs to be scaled to its final height.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35462" PostHistoryTypeId="5" PostId="12339" RevisionGUID="5e1bbf8b-d805-45cf-a27f-02d7f05393c7" CreationDate="2021-11-15T11:48:14.617" UserId="7952" Comment="edited body" Text="You are on the right track with your post...&#xD;&#xA;&#xD;&#xA;Compute two slopes then somehow use those slopes to find a normal. The slopes are the result of finite difference (like central difference)&#xD;&#xA;&#xD;&#xA;But why two slopes? Because we can use them to construct two independent vectors whose cross product will become our normal vector.&#xD;&#xA;&#xD;&#xA;One vector is in the texture's $u$ direction and is simply $vec3(1,0,slopeU)$&#xD;&#xA;&#xD;&#xA;The other vector is in the textures $v$ direction and is $vec3(0,1,slopeV)$&#xD;&#xA;&#xD;&#xA;Take the cross product and normalize, its really that simple.&#xD;&#xA;&#xD;&#xA;Both of the vectors are tangent to the height, and they are independent of each other. They can be constructed as $(0,1,S_v)$ and $(1,0,S_u)$ because the slopes are very specifically taken in those directions. If you change the directions used to compute the slopes then you have to change the directions used in the vectors to match.&#xD;&#xA;&#xD;&#xA;There are a few other minor caveats, like the calculations are assumed to always happen at the origin, and the height map, which usually contains values between 0 and 1 needs to be scaled to its final height.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35463" PostHistoryTypeId="2" PostId="12340" RevisionGUID="d8a7829b-f3c4-4cca-8d47-46d54e86f2e7" CreationDate="2021-11-15T12:05:24.463" UserId="15879" Text="Suppose a GLTF file provides a single `N` byte buffer which includes all vertex, normal and index data for multiple meshes. The first `m` bytes are interleaved vertex positions, normals and indices for one geometry and the remaining data is non-interleaved data for other geometries. All meshes will be rendered eventually.&#xD;&#xA;&#xD;&#xA;How is the data best uploaded to the GPU? &#xD;&#xA;&#xD;&#xA;Is it best to upload the whole `N` bytes and then use `vertexAttribPointer()` to define the layout or is it better to upload the different buffer regions separately, one for each mesh? Or is there a benefit to separating the first `m` bytes of interleaved data from the remaining non-interleaved data? The overall footprint on the GPU would be the same.&#xD;&#xA;&#xD;&#xA;Is there a performance impact to interleaving floats and unsigned bytes (positions and indices) in the same buffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35465" PostHistoryTypeId="1" PostId="12340" RevisionGUID="d8a7829b-f3c4-4cca-8d47-46d54e86f2e7" CreationDate="2021-11-15T12:05:24.463" UserId="15879" Text="Uploading interleaved data in gltf buffers" ContentLicense="CC BY-SA 4.0" />
  <row Id="35466" PostHistoryTypeId="3" PostId="12340" RevisionGUID="d8a7829b-f3c4-4cca-8d47-46d54e86f2e7" CreationDate="2021-11-15T12:05:24.463" UserId="15879" Text="|rendering|webgl|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35467" PostHistoryTypeId="2" PostId="12341" RevisionGUID="afc3e761-6ae6-416e-bfd9-e52ec9e27dbd" CreationDate="2021-11-15T12:31:20.937" UserId="7952" Text="It is slightly better to combine buffers since it reduces the amount of state that OpenGL has to track, which reduces memory usage overall, and helps reduce state changes.&#xD;&#xA;&#xD;&#xA;But you only really get those benefits if you have a large number of these buffers floating around, on the order of thousands of them.&#xD;&#xA;&#xD;&#xA;Usually it is better to go with whichever method best fits the code base that is supporting them since a simpler code base is easier to maintain, and will generally have less bugs. Then get fancy only if performance or memory constraints become an issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="35469" PostHistoryTypeId="5" PostId="12339" RevisionGUID="95b50481-b3d6-40f4-9be3-eab42fba67ea" CreationDate="2021-11-15T13:39:37.673" UserId="7952" Comment="added 1077 characters in body" Text="You are on the right track with your post...&#xD;&#xA;&#xD;&#xA;Compute two slopes then somehow use those slopes to find a normal. The slopes are the result of finite difference (like central difference)&#xD;&#xA;&#xD;&#xA;But why two slopes? Because we can use them to construct two independent vectors whose cross product will become our normal vector.&#xD;&#xA;&#xD;&#xA;One vector is in the texture's $u$ direction and is simply $vec3(1,0,slopeU)$&#xD;&#xA;&#xD;&#xA;The other vector is in the textures $v$ direction and is $vec3(0,1,slopeV)$&#xD;&#xA;&#xD;&#xA;**W**here are these vectors coming from?&#xD;&#xA;Take a look at a 2D cartesian coordinate system such as [this one][1]. Now overlay the height map texture over the cartesian coordinate system with the point we are interested in located at the origin. The u direction of the texture lines up with the x direction of the coordinate system. Compute the u direction slope for the heightmap at that point using central differences. This samples a=(-1,0) and b=(1,0) on the cartesian coordinate system. These two points form a line on the x axis. This is the same direction the vector needs to point. Remember that vectors have direction but no location, so as long as we pick a vector that points in the same direction as the slope calculation then it doesn't matter what values we plug into the vector, just that it has the right direction. A natural choice for the vector in the same direction as the slope is (1,0) combined with the slope gives (1,0,slopeU).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With the two directions computed, and the two vectors created:&#xD;&#xA;Take the cross product and normalize, its really that simple.&#xD;&#xA;&#xD;&#xA;Both of the vectors are tangent to the height, and they are independent of each other. They can be constructed as $(0,1,S_v)$ and $(1,0,S_u)$ because the slopes are very specifically taken in those directions. If you change the directions used to compute the slopes then you have to change the directions used in the vectors to match.&#xD;&#xA;&#xD;&#xA;There are a few other minor caveats, like the calculations are assumed to always happen at the origin, and the height map, which usually contains values between 0 and 1 needs to be scaled to its final height.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dqm1v390v3ac1.cloudfront.net/img01_22.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35470" PostHistoryTypeId="2" PostId="12342" RevisionGUID="6a88e61f-5d89-4cf6-b695-18b226bbffe9" CreationDate="2021-11-15T15:45:46.187" UserId="17518" Text="&#xD;&#xA;##### This is the basic implementation of the z buffer algorithm&#xD;&#xA;    Suppose the depth buffer is a matrix d[100][100];&#xD;&#xA;&#xD;&#xA;    for(each polygon P)&#xD;&#xA;    {&#xD;&#xA;         for(each pixel (X, Y) on the polygon)&#xD;&#xA;         {&#xD;&#xA;             depth_variable = depth of P at (X, Y);&#xD;&#xA;             if(depth &lt; d[X][Y])&#xD;&#xA;             {&#xD;&#xA;                 color_variable = color of P at (X, Y);&#xD;&#xA;                 set the pixel color at (X, Y) to color_variable;&#xD;&#xA;                 d[X][Y] = depth_variable;&#xD;&#xA;             }&#xD;&#xA;         }&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;##### As we can see while iterating through polygons we only store the new pixel value if the new depth is less (or less than equal to depending on the setting as mentioned by Mr. Nathan Reed) than the stored one in the depth buffer, so it doesnt matter in which order you render the polygons. &#xD;&#xA;&#xD;&#xA;#### The only thing that matters is the fact which polygon has the least depth at a particular pixel.&#xD;&#xA;     " ContentLicense="CC BY-SA 4.0" />
  <row Id="35472" PostHistoryTypeId="5" PostId="12337" RevisionGUID="3e6a2f81-fe47-4d40-9573-f060ccda8feb" CreationDate="2021-11-15T16:09:07.297" UserId="10096" Comment="added 2654 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit to clarify how this works in practice:&#xD;&#xA;&#xD;&#xA;In practice you typically have a triangle mesh with UVs associated with each vertex. You can parametrize any triangle in barycentric coordinates: $S(\beta, \gamma)$. Any point $S(\beta, \gamma)$ on the triangle $(p_0, p_1, p_2)$ can be described through its barycentric coordinates $(\alpha, \beta, \gamma), \, \alpha+\beta+\gamma=1, \, \alpha,\beta,\gamma\geq 0$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;We can thus compute $\partial_{\beta} S = (p_1-p_0), \, \partial_{\gamma} S = (p_2-p_0), n = \frac{(p_1-p_0) \times (p_2-p_0)}{\|(p_1-p_0) \times (p_2-p_0)\|}$. We need to compute: $\partial_{\beta} h, \, \partial_{\gamma} h$, but $h$ is defined wrt the UV coordinates: $h(u,v)$. Thus we need to map from barycentric coordinates to UV coordinates. Let the UV coordinates at the 3 vertices be $(uv_0, uv_1, uv_2)$, then:&#xD;&#xA;&#xD;&#xA;$$\hat{h}(\beta, \gamma) = h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)).$$&#xD;&#xA;&#xD;&#xA;Denote $uv = uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)$. Taking the partial derivatives yields:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} \hat{h}(\beta, \gamma) = \partial_{\beta}h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)) = \\ (uv_{1,u}-uv_{0,u})\partial_u h(uv) + (uv_{1,v}-uv_{0,v})\partial_v h(uv) = \\&#xD;&#xA;(uv_1-uv_0) \cdot (\partial_u h(uv), \partial_v h(uv)) \\&#xD;&#xA;\partial_{\gamma}\hat{h}(\beta,\gamma) = (uv_2-uv_0) \cdot (\partial_u h(uv), \partial_v h(u,v)).$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences (e.g. forward, backward, central, dFdx/dFdy in glsl):&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) = \frac{h(u+\epsilon, v)-h(u,v)}{\epsilon}, \, \partial_v h(u,v) = \frac{h(u, v+\epsilon)-h(u,v)}{\epsilon}.$$&#xD;&#xA;&#xD;&#xA;There are more elaborate strategies too that work directly in projected coordinates.&#xD;&#xA;&#xD;&#xA;Also usually shading normals are used in a triangle, i.e. the 3 vertices normals are interpolated linearly over the triangle to get smooth normals. Let the normals at the 3 vertices be $(n_0, n_1, n_2)$ then the normal at $(\beta, \gamma)$ is:&#xD;&#xA;&#xD;&#xA;$$n(\beta, \gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|},$$&#xD;&#xA;&#xD;&#xA;you can substitute with the above where you had $n$ in the expression for $m$. Note that this doesn't fix the $\partial_u S \times \partial_v S$ term, which should ideally also be modified to take into account the implied curvature of the surface from $n(\beta, \gamma)$. However this is getting too technical, and I am not sure anyone even does a correction for this term.&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35473" PostHistoryTypeId="5" PostId="12337" RevisionGUID="39fff3e4-5759-4c5f-a291-556f0e0622fd" CreationDate="2021-11-15T16:17:50.453" UserId="10096" Comment="added 2654 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit to clarify how this works in practice:&#xD;&#xA;&#xD;&#xA;In practice you typically have a triangle mesh. I will parametrize each triangle in barycentric coordinates $S(\beta, \gamma)$ instead of UV coordinates $S(u,v)$. Then the approximated normal is:&#xD;&#xA;&#xD;&#xA;$$m = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)n\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times n.$$&#xD;&#xA;&#xD;&#xA;Any point $S(\beta, \gamma)$ on the triangle $(p_0, p_1, p_2)$ can be described through its barycentric coordinates $(\alpha, \beta, \gamma), \, \alpha+\beta+\gamma=1, \, \alpha,\beta,\gamma\geq 0$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;Then we can compute $\partial_{\beta} S = (p_1-p_0), \, \partial_{\gamma} S = (p_2-p_0), n = \frac{(p_1-p_0) \times (p_2-p_0)}{\|(p_1-p_0) \times (p_2-p_0)\|}$. Additionally we need: $\partial_{\beta} h, \, \partial_{\gamma} h$, but $h$ is defined wrt the UV coordinates: $h(u,v)$. Thus we need to map from barycentric coordinates to UV coordinates. Let the UV coordinates at the 3 vertices be $(uv_0, uv_1, uv_2)$, then:&#xD;&#xA;&#xD;&#xA;$$h(uv) = h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)).$$&#xD;&#xA;&#xD;&#xA;Denote $uv = uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)$. Taking the partial derivatives yields:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} h(uv) = \partial_{\beta}h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)) = \\ (uv_{1,u}-uv_{0,u})\partial_u h(uv) + (uv_{1,v}-uv_{0,v})\partial_v h(uv) = \\&#xD;&#xA;(uv_1-uv_0) \cdot (\partial_u h(uv), \partial_v h(uv)) \\&#xD;&#xA;\partial_{\gamma}h(uv) = (uv_2-uv_0) \cdot (\partial_u h(uv), \partial_v h(u,v)).$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences (e.g. forward, backward, central, dFdx/dFdy in glsl):&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) = \frac{h(u+\epsilon, v)-h(u,v)}{\epsilon}, \, \partial_v h(u,v) = \frac{h(u, v+\epsilon)-h(u,v)}{\epsilon}.$$&#xD;&#xA;&#xD;&#xA;Also usually shading normals are used in a triangle, i.e. the 3 vertices normals are interpolated linearly over the triangle to get smooth normals. Let the normals at the 3 vertices be $(n_0, n_1, n_2)$ then the normal at $(\beta, \gamma)$ is:&#xD;&#xA;&#xD;&#xA;$$n(\beta, \gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|},$$&#xD;&#xA;&#xD;&#xA;you can substitute with the above where you had $n$ in the expression for $m$. Note that this doesn't fix the $\partial_u S \times \partial_v S$ term, which should ideally also be modified to take into account the implied curvature of the surface from $n(\beta, \gamma)$. However this is getting too technical, and I am not sure anyone even does a correction for this term. My best ad-hoc suggestion would be to use $\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma)$ instead of $\partial_{\beta} S \times \partial_{\gamma} S$.&#xD;&#xA;&#xD;&#xA;Note that there are other possible derivations of the above (e.g. in projected coordinates).&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35474" PostHistoryTypeId="5" PostId="12337" RevisionGUID="e609e3d8-9d7e-41fa-850d-1bbc52eef623" CreationDate="2021-11-15T16:33:55.513" UserId="10096" Comment="added 2654 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit to clarify how this works in practice:&#xD;&#xA;&#xD;&#xA;In practice you typically have a triangle mesh. I will parametrize each triangle in barycentric coordinates $S(\beta, \gamma)$ instead of UV coordinates $S(u,v)$. Then the approximated normal is:&#xD;&#xA;&#xD;&#xA;$$m = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)n\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times n.$$&#xD;&#xA;&#xD;&#xA;Any point $S(\beta, \gamma)$ on the triangle $(p_0, p_1, p_2)$ can be described through its barycentric coordinates $(\alpha, \beta, \gamma), \, \alpha+\beta+\gamma=1, \, \alpha,\beta,\gamma\geq 0$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;Then we can compute $\partial_{\beta} S = (p_1-p_0), \, \partial_{\gamma} S = (p_2-p_0), n = \frac{(p_1-p_0) \times (p_2-p_0)}{\|(p_1-p_0) \times (p_2-p_0)\|}$. Additionally we need: $\partial_{\beta} h, \, \partial_{\gamma} h$, but $h$ is defined wrt the UV coordinates: $h(u,v)$. Thus we need to map from barycentric coordinates to UV coordinates. Let the UV coordinates at the 3 vertices be $(uv_0, uv_1, uv_2)$, then:&#xD;&#xA;&#xD;&#xA;$$h(uv) = h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)).$$&#xD;&#xA;&#xD;&#xA;Denote $uv = uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)$. Taking the partial derivatives yields:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} h(uv) = \partial_{\beta}h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)) = \\ (uv_{1,u}-uv_{0,u})\partial_u h(uv) + (uv_{1,v}-uv_{0,v})\partial_v h(uv) = \\&#xD;&#xA;(uv_1-uv_0) \cdot (\partial_u h(uv), \partial_v h(uv)) \\&#xD;&#xA;\partial_{\gamma}h(uv) = (uv_2-uv_0) \cdot (\partial_u h(uv), \partial_v h(u,v)).$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences (e.g. forward, backward, central, dFdx/dFdy in glsl):&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) = \frac{h(u+\epsilon, v)-h(u,v)}{\epsilon}, \, \partial_v h(u,v) = \frac{h(u, v+\epsilon)-h(u,v)}{\epsilon}.$$&#xD;&#xA;&#xD;&#xA;Also usually shading normals are used in a triangle, i.e. the 3 vertices normals are interpolated linearly over the triangle to get smooth normals. Let the normals at the 3 vertices be $(n_0, n_1, n_2)$ then the normal at $(\beta, \gamma)$ is:&#xD;&#xA;&#xD;&#xA;$$n(\beta, \gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|},$$&#xD;&#xA;&#xD;&#xA;you can substitute with the above where you had $n$ in the expression for $m$. Note that this doesn't fix the $\partial_u S \times \partial_v S$ term, which should ideally also be modified to take into account the implied curvature of the surface from $n(\beta, \gamma)$. However this is getting too technical, and I am not sure anyone even does a correction for this term. My best ad-hoc suggestion would be to use $\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma)$ instead of $\partial_{\beta} S \times \partial_{\gamma} S$, $\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|}$ instead of $\partial_{\beta}S(\beta,\gamma)$, $\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}$ instead of $\partial_{\gamma} S(\beta, \gamma)$. Substituting these in $m$ yields:&#xD;&#xA;&#xD;&#xA;$$m=\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma) + \\ (\partial_{\beta}h(uv))\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|} + \\(\partial_{\gamma}h(uv))\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}.$$&#xD;&#xA;&#xD;&#xA;Be aware that this can break if $n(\beta, \gamma)$ becomes collinear with $(p_1-p_0)$ or $(p_2-p_0)$. It should be fine as long as your vertices shading normals are not coplanar with the triangle.&#xD;&#xA;&#xD;&#xA;Note that there are other possible derivations of the above (e.g. in projected coordinates).&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35475" PostHistoryTypeId="5" PostId="12337" RevisionGUID="534ff037-41ba-4f79-a21c-1611804d4ccf" CreationDate="2021-11-15T16:46:36.850" UserId="10096" Comment="added 576 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit to clarify how this works in practice:&#xD;&#xA;&#xD;&#xA;In practice you typically have a triangle mesh. I will parametrize each triangle in barycentric coordinates $S(\beta, \gamma)$ instead of UV coordinates $S(u,v)$. Then the approximated normal is:&#xD;&#xA;&#xD;&#xA;$$m = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)n\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times n.$$&#xD;&#xA;&#xD;&#xA;Any point $S(\beta, \gamma)$ on the triangle $(p_0, p_1, p_2)$ can be described through its barycentric coordinates $(\alpha, \beta, \gamma), \, \alpha+\beta+\gamma=1, \, \alpha,\beta,\gamma\geq 0$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;Then we can compute $\partial_{\beta} S = (p_1-p_0), \, \partial_{\gamma} S = (p_2-p_0), n = \frac{(p_1-p_0) \times (p_2-p_0)}{\|(p_1-p_0) \times (p_2-p_0)\|}$. Additionally we need: $\partial_{\beta} h, \, \partial_{\gamma} h$, but $h$ is defined wrt the UV coordinates: $h(u,v)$. Thus we need to map from barycentric coordinates to UV coordinates. Let the UV coordinates at the 3 vertices be $(uv_0, uv_1, uv_2)$, then:&#xD;&#xA;&#xD;&#xA;$$h(uv) = h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)).$$&#xD;&#xA;&#xD;&#xA;Denote $uv = uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)$. Taking the partial derivatives yields:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} h(uv) = \partial_{\beta}h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)) = \\ (uv_{1,u}-uv_{0,u})\partial_u h(uv) + (uv_{1,v}-uv_{0,v})\partial_v h(uv) = \\&#xD;&#xA;(uv_1-uv_0) \cdot (\partial_u h(uv), \partial_v h(uv)) \\&#xD;&#xA;\partial_{\gamma}h(uv) = (uv_2-uv_0) \cdot (\partial_u h(uv), \partial_v h(u,v)).$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences (e.g. forward, backward, central, dFdx/dFdy in glsl):&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) = \frac{h(u+\epsilon, v)-h(u,v)}{\epsilon}, \, \partial_v h(u,v) = \frac{h(u, v+\epsilon)-h(u,v)}{\epsilon}.$$&#xD;&#xA;&#xD;&#xA;Also usually shading normals are used in a triangle, i.e. the 3 vertices normals are interpolated linearly over the triangle to get smooth normals. Let the normals at the 3 vertices be $(n_0, n_1, n_2)$ then the normal at $(\beta, \gamma)$ is:&#xD;&#xA;&#xD;&#xA;$$n(\beta, \gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|},$$&#xD;&#xA;&#xD;&#xA;you can substitute with the above where you had $n$ in the expression for $m$. Note that this doesn't fix the $\partial_u S \times \partial_v S$ term, which should ideally also be modified to take into account the implied curvature of the surface from $n(\beta, \gamma)$. However this is getting too technical, and I am not sure anyone even does a correction for this term. My best ad-hoc suggestion would be to use $\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma)$ instead of $\partial_{\beta} S \times \partial_{\gamma} S$, $\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|}$ instead of $\partial_{\beta}S(\beta,\gamma)$, $\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}$ instead of $\partial_{\gamma} S(\beta, \gamma)$. Substituting these in $m$ yields:&#xD;&#xA;&#xD;&#xA;$$m=\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma) + \\ (\partial_{\beta}h(uv))\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|} + \\(\partial_{\gamma}h(uv))\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}.$$&#xD;&#xA;&#xD;&#xA;Be aware that this can break if $n(\beta, \gamma)$ becomes collinear with $(p_1-p_0)$ or $(p_2-p_0)$. It should be fine as long as your vertices shading normals are not coplanar with the triangle.&#xD;&#xA;&#xD;&#xA;Note that there are other possible derivations of the above (e.g. in projected coordinates).&#xD;&#xA;&#xD;&#xA;Edit 2: Actually the issue with the coplanar normals can be avoided. Let $t = \frac{p_1-p_0}{\|p_1-p_0\|}, \, n = \frac{(p_1-p_0)\times (p_2-p_0)}{\|(p_1-p_0)\times (p_2-p_0)\|}, \, b = \frac{p_2-p_0}{\|p_2-p_0\|}$, $n' = n(\beta,\gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|}.$ Compute:&#xD;&#xA;&#xD;&#xA;$$t' = t - \frac{t\cdot n'}{1+n\cdot n'}(n+n'), \, b' = b - \frac{b\cdot n'}{1+n\cdot n'}(n+n').$$&#xD;&#xA;&#xD;&#xA;The above fails only if you manage to get $n'=-n$ which would have your normal pointing in the wrong direction (i.e. it shouldn't occur in practice). Now normalize $t',\, b'$ to get: $\hat{t}' = \frac{t'}{\|t'\|}, \, \hat{b}'=\frac{b'}{\|b'\|}$, and you get the expression:&#xD;&#xA;&#xD;&#xA;$$m = \|(p_1-p_0)\times(p_2-p_0)\|n' + (\partial_{\beta}h(uv))\|p_1-p_0\|\hat{t}' + (\partial_{\beta}h(uv))\|p_2-p_0\|\hat{b}'.$$&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35476" PostHistoryTypeId="5" PostId="12337" RevisionGUID="a631a140-2196-437a-ab77-696818788ffd" CreationDate="2021-11-15T16:54:01.503" UserId="10096" Comment="added 576 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit to clarify how this works in practice:&#xD;&#xA;&#xD;&#xA;In practice you typically have a triangle mesh. I will parametrize each triangle in barycentric coordinates $S(\beta, \gamma)$ instead of UV coordinates $S(u,v)$. Then the approximated normal is:&#xD;&#xA;&#xD;&#xA;$$m = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)n\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times n.$$&#xD;&#xA;&#xD;&#xA;Any point $S(\beta, \gamma)$ on the triangle $(p_0, p_1, p_2)$ can be described through its barycentric coordinates $(\alpha, \beta, \gamma), \, \alpha+\beta+\gamma=1, \, \alpha,\beta,\gamma\geq 0$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;Then we can compute $\partial_{\beta} S = (p_1-p_0), \, \partial_{\gamma} S = (p_2-p_0), n = \frac{(p_1-p_0) \times (p_2-p_0)}{\|(p_1-p_0) \times (p_2-p_0)\|}$. Additionally we need: $\partial_{\beta} h, \, \partial_{\gamma} h$, but $h$ is defined wrt the UV coordinates: $h(u,v)$. Thus we need to map from barycentric coordinates to UV coordinates. Let the UV coordinates at the 3 vertices be $(uv_0, uv_1, uv_2)$, then:&#xD;&#xA;&#xD;&#xA;$$h(uv) = h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)).$$&#xD;&#xA;&#xD;&#xA;Denote $uv = uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)$. Taking the partial derivatives yields:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} h(uv) = \partial_{\beta}h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)) = \\ (uv_{1,u}-uv_{0,u})\partial_u h(uv) + (uv_{1,v}-uv_{0,v})\partial_v h(uv) = \\&#xD;&#xA;(uv_1-uv_0) \cdot (\partial_u h(uv), \partial_v h(uv)) \\&#xD;&#xA;\partial_{\gamma}h(uv) = (uv_2-uv_0) \cdot (\partial_u h(uv), \partial_v h(u,v)).$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences (e.g. forward, backward, central, dFdx/dFdy in glsl):&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) = \frac{h(u+\epsilon, v)-h(u,v)}{\epsilon}, \, \partial_v h(u,v) = \frac{h(u, v+\epsilon)-h(u,v)}{\epsilon}.$$&#xD;&#xA;&#xD;&#xA;Also usually shading normals are used in a triangle, i.e. the 3 vertices normals are interpolated linearly over the triangle to get smooth normals. Let the normals at the 3 vertices be $(n_0, n_1, n_2)$ then the normal at $(\beta, \gamma)$ is:&#xD;&#xA;&#xD;&#xA;$$n(\beta, \gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|},$$&#xD;&#xA;&#xD;&#xA;you can substitute with the above where you had $n$ in the expression for $m$. Note that this doesn't fix the $\partial_u S \times \partial_v S$ term, which should ideally also be modified to take into account the implied curvature of the surface from $n(\beta, \gamma)$. However this is getting too technical, and I am not sure anyone even does a correction for this term. My best ad-hoc suggestion would be to use $\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma)$ instead of $\partial_{\beta} S \times \partial_{\gamma} S$, $\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|}$ instead of $\partial_{\beta}S(\beta,\gamma)$, $\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}$ instead of $\partial_{\gamma} S(\beta, \gamma)$. Substituting these in $m$ yields:&#xD;&#xA;&#xD;&#xA;$$m=\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma) + \\ (\partial_{\beta}h(uv))\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|} + \\(\partial_{\gamma}h(uv))\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}.$$&#xD;&#xA;&#xD;&#xA;Be aware that this can break if $n(\beta, \gamma)$ becomes collinear with $(p_1-p_0)$ or $(p_2-p_0)$. It should be fine as long as your vertices shading normals are not coplanar with the triangle.&#xD;&#xA;&#xD;&#xA;Note that there are other possible derivations of the above (e.g. in projected coordinates).&#xD;&#xA;&#xD;&#xA;Edit 2: Actually the issue with the coplanar normals can be avoided. Let $t = \frac{p_1-p_0}{\|p_1-p_0\|}, \, n = \frac{(p_1-p_0)\times (p_2-p_0)}{\|(p_1-p_0)\times (p_2-p_0)\|}, \, b = \frac{p_2-p_0}{\|p_2-p_0\|}$, $n' = n(\beta,\gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|}.$ Compute:&#xD;&#xA;&#xD;&#xA;$$t' = t - \frac{t\cdot n'}{1+n\cdot n'}(n+n'), \, b' = b - \frac{b\cdot n'}{1+n\cdot n'}(n+n').$$&#xD;&#xA;&#xD;&#xA;The above fails only if you manage to get $n'=-n$ which would have your normal pointing in the wrong direction (i.e. it shouldn't occur in practice). Now normalize $t',\, b'$ to get: $\hat{t}' = \frac{t'}{\|t'\|}, \, \hat{b}'=\frac{b'}{\|b'\|}$, and you get the expression:&#xD;&#xA;&#xD;&#xA;$$m = \|(p_1-p_0)\times(p_2-p_0)\|n' + (\partial_{\beta}h(uv))\|p_1-p_0\|\hat{t}' + (\partial_{\beta}h(uv))\|p_2-p_0\|\hat{b}'.$$&#xD;&#xA;&#xD;&#xA;The above expression can be interpreted as having performed normal mapping with a normal $((\partial_{\beta}h(uv))\|p_1-p_0\|, (\partial_{\beta}h(uv))\|p_2-p_0\|, \|(p_1-p_0)\times(p_2-p_0)\|)$, e.g. compare to:&#xD;&#xA;&#xD;&#xA;$$m = Bn' + R\hat{t}' + G\hat{b}',$$&#xD;&#xA;&#xD;&#xA;where $(R,G,B)$ is the stored normal for the current pixel in normal mapping.&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35477" PostHistoryTypeId="5" PostId="12337" RevisionGUID="a5164897-31d1-461c-a45b-f5159280d168" CreationDate="2021-11-15T16:59:41.360" UserId="10096" Comment="added 576 characters in body" Text="Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n= \frac{\partial_u S \times \partial_v S}{\|\partial_u S \times \partial_v S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(u,v) = S(u,v) + h(u,v)n(u,v)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_u T \times \partial_v T$$&#xD;&#xA;$$\partial_u T = \partial_uS+(\partial_u h)n + h(\partial_un), \quad \partial_v T = \partial_vS+(\partial_v h)n + h(\partial_vn)$$&#xD;&#xA;$$ \partial_uT \approx \partial_uS+(\partial_u h)n, \quad \partial_vT \approx \partial_vS+(\partial_v h)n$$&#xD;&#xA;$$m\approx (\partial_uS+(\partial_u h)n)\times(\partial_vS+(\partial_v h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_uS\times\partial_vS + (\partial_u h)n\times\partial_vS + (\partial_vh)\partial_uS\times n + \cancel{(\partial_u h)(\partial_v h)n\times n}$$&#xD;&#xA;&#xD;&#xA;This is how you derive an approximation of the (unnormalized) normal $m$. That is, you need the tangent vectors $\partial_u S,\, \partial_v S$ and the normalized normal $n$, as well as the partial derivatives $\partial_u h,\, \partial_v h$ of the height map - the latter are computed through finite differences. Note the approximation for $\partial_u T, \, \partial_v T$ and consequently $m$. This is the Blinn approximation - the assumption being that $\partial_u n, \, \partial_v n$ is sufficiently small.&#xD;&#xA;&#xD;&#xA;I can also suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] if you want something extra.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit to clarify how this works in practice:&#xD;&#xA;&#xD;&#xA;In practice you typically have a triangle mesh. I will parametrize each triangle in barycentric coordinates $S(\beta, \gamma)$ instead of UV coordinates $S(u,v)$. Then the approximated normal is:&#xD;&#xA;&#xD;&#xA;$$m = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)n\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times n.$$&#xD;&#xA;&#xD;&#xA;Any point $S(\beta, \gamma)$ on the triangle $(p_0, p_1, p_2)$ can be described through its barycentric coordinates $(\alpha, \beta, \gamma), \, \alpha+\beta+\gamma=1, \, \alpha,\beta,\gamma\geq 0$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;Then we can compute $\partial_{\beta} S = (p_1-p_0), \, \partial_{\gamma} S = (p_2-p_0), n = \frac{(p_1-p_0) \times (p_2-p_0)}{\|(p_1-p_0) \times (p_2-p_0)\|}$. Additionally we need: $\partial_{\beta} h, \, \partial_{\gamma} h$, but $h$ is defined wrt the UV coordinates: $h(u,v)$. Thus we need to map from barycentric coordinates to UV coordinates. Let the UV coordinates at the 3 vertices be $(uv_0, uv_1, uv_2)$, then:&#xD;&#xA;&#xD;&#xA;$$h(uv) = h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)).$$&#xD;&#xA;&#xD;&#xA;Denote $uv = uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)$. Taking the partial derivatives yields:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} h(uv) = \partial_{\beta}h(uv_0 + \beta(uv_1-uv_0) + \gamma(uv_2-uv_0)) = \\ (uv_{1,u}-uv_{0,u})\partial_u h(uv) + (uv_{1,v}-uv_{0,v})\partial_v h(uv) = \\&#xD;&#xA;(uv_1-uv_0) \cdot (\partial_u h(uv), \partial_v h(uv)) \\&#xD;&#xA;\partial_{\gamma}h(uv) = (uv_2-uv_0) \cdot (\partial_u h(uv), \partial_v h(u,v)).$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences (e.g. forward, backward, central, dFdx/dFdy in glsl):&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) = \frac{h(u+\epsilon, v)-h(u,v)}{\epsilon}, \, \partial_v h(u,v) = \frac{h(u, v+\epsilon)-h(u,v)}{\epsilon}.$$&#xD;&#xA;&#xD;&#xA;Also usually shading normals are used in a triangle, i.e. the 3 vertices normals are interpolated linearly over the triangle to get smooth normals. Let the normals at the 3 vertices be $(n_0, n_1, n_2)$ then the normal at $(\beta, \gamma)$ is:&#xD;&#xA;&#xD;&#xA;$$n(\beta, \gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|},$$&#xD;&#xA;&#xD;&#xA;you can substitute with the above where you had $n$ in the expression for $m$. Note that this doesn't fix the $\partial_u S \times \partial_v S$ term, which should ideally also be modified to take into account the implied curvature of the surface from $n(\beta, \gamma)$. However this is getting too technical, and I am not sure anyone even does a correction for this term. My best ad-hoc suggestion would be to use $\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma)$ instead of $\partial_{\beta} S \times \partial_{\gamma} S$, $\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|}$ instead of $\partial_{\beta}S(\beta,\gamma)$, $\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}$ instead of $\partial_{\gamma} S(\beta, \gamma)$. Substituting these in $m$ yields:&#xD;&#xA;&#xD;&#xA;$$m=\|(p_1-p_0)\times(p_2-p_0)\|n(\beta, \gamma) + \\ (\partial_{\beta}h(uv))\|p_1-p_0\|\frac{n(\beta,\gamma)\times(p_2-p_0)}{\|n(\beta,\gamma)\times(p_2-p_0)\|} + \\(\partial_{\gamma}h(uv))\|p_2-p_0\|\frac{(p_1-p_0)\times n(\beta,\gamma)}{\|(p_1-p_0)\times n(\beta,\gamma)\|}.$$&#xD;&#xA;&#xD;&#xA;Be aware that this can break if $n(\beta, \gamma)$ becomes collinear with $(p_1-p_0)$ or $(p_2-p_0)$. It should be fine as long as your vertices shading normals are not coplanar with the triangle.&#xD;&#xA;&#xD;&#xA;Note that there are other possible derivations of the above (e.g. in projected coordinates).&#xD;&#xA;&#xD;&#xA;Edit 2: Actually the issue with the coplanar normals can be avoided. Let $t = \frac{p_1-p_0}{\|p_1-p_0\|}, \, n = \frac{(p_1-p_0)\times (p_2-p_0)}{\|(p_1-p_0)\times (p_2-p_0)\|}, \, b = \frac{p_2-p_0}{\|p_2-p_0\|}$, $n' = n(\beta,\gamma) = \frac{n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)}{\|n_0 + \beta(n_1-n_0) + \gamma(n_2-n_0)\|}.$ Compute:&#xD;&#xA;&#xD;&#xA;$$t' = t - \frac{t\cdot n'}{1+n\cdot n'}(n+n'), \, b' = b - \frac{b\cdot n'}{1+n\cdot n'}(n+n').$$&#xD;&#xA;&#xD;&#xA;The above fails only if you manage to get $n'=-n$ which would have your normal pointing in the wrong direction (i.e. it shouldn't occur in practice). Now normalize $t',\, b'$ to get: $\hat{t}' = \frac{t'}{\|t'\|}, \, \hat{b}'=\frac{b'}{\|b'\|}$, and you get the expression:&#xD;&#xA;&#xD;&#xA;$$m = \|(p_1-p_0)\times(p_2-p_0)\|n' + (\partial_{\beta}h(uv))\|p_1-p_0\|\hat{t}' + (\partial_{\gamma}h(uv))\|p_2-p_0\|\hat{b}'.$$&#xD;&#xA;&#xD;&#xA;The above expression can be interpreted as having performed normal mapping with a normal $((\partial_{\beta}h(uv))\|p_1-p_0\|, (\partial_{\gamma}h(uv))\|p_2-p_0\|, \|(p_1-p_0)\times(p_2-p_0)\|)$, e.g. compare to:&#xD;&#xA;&#xD;&#xA;$$m = Bn' + R\hat{t}' + G\hat{b}',$$&#xD;&#xA;&#xD;&#xA;where $(R,G,B)$ is the stored normal for the current pixel in normal mapping.&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35478" PostHistoryTypeId="5" PostId="12339" RevisionGUID="9ebe310f-7340-4173-8389-0762695ba908" CreationDate="2021-11-15T20:37:20.930" UserId="7952" Comment="added 711 characters in body" Text="You are on the right track with your post...&#xD;&#xA;&#xD;&#xA;Compute two slopes then somehow use those slopes to find a normal. The slopes are the result of finite difference (like central difference)&#xD;&#xA;&#xD;&#xA;But why two slopes? Because we can use them to construct two independent vectors whose cross product will become our normal vector.&#xD;&#xA;&#xD;&#xA;One vector is in the texture's $u$ direction and is simply $vec3(1,0,slopeU)$&#xD;&#xA;&#xD;&#xA;The other vector is in the textures $v$ direction and is $vec3(0,1,slopeV)$&#xD;&#xA;&#xD;&#xA;**W**here are these vectors coming from?&#xD;&#xA;Take a look at a 2D cartesian coordinate system such as [this one][1]. Now overlay the height map texture over the cartesian coordinate system with the point we are interested in located at the origin. The u direction of the texture lines up with the x direction of the coordinate system. Compute the u direction slope for the heightmap at that point using central differences. This samples a=(-1,0) and b=(1,0) on the cartesian coordinate system. These two points form a line on the x axis. This is the same direction the vector needs to point. Remember that vectors have direction but no location, so as long as we pick a vector that points in the same direction as the slope calculation then it doesn't matter what values we plug into the vector, just that it has the right direction. A natural choice for the vector in the same direction as the slope is (1,0) combined with the slope gives (1,0,slopeU).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With the two directions computed, and the two vectors created:&#xD;&#xA;Take the cross product and normalize, its really that simple.&#xD;&#xA;&#xD;&#xA;Both of the vectors are tangent to the height, and they are independent of each other. They can be constructed as $(0,1,S_v)$ and $(1,0,S_u)$ because the slopes are very specifically taken in those directions. If you change the directions used to compute the slopes then you have to change the directions used in the vectors to match.&#xD;&#xA;&#xD;&#xA;There are a few other minor caveats, like the calculations are assumed to always happen at the origin, and the height map, which usually contains values between 0 and 1 needs to be scaled to its final height.&#xD;&#xA;&#xD;&#xA;**O**rigin and direction choices:&#xD;&#xA;Yes, the choice to do the calculations at the origin is completely arbitrary. It just makes the math more convenient.&#xD;&#xA;&#xD;&#xA;The choice of the (1,0) and (0,1) is not arbitrary. These are chosen because they lie in the exact same direction as the computed slopes. If we chose (12,243,slopeU) the question becomes where does this vector point? Well this vector points very heavily toward the y axis. (the y value of 243 ) so our calculation of the slope along the x (slopeU) axis will be used to compute a slope pointing nearly at the y axis and the end result will give a very skewed value. For this reason, most applications assume a grid spacing of 1 between height map points.&#xD;&#xA;&#xD;&#xA;  [1]: https://dqm1v390v3ac1.cloudfront.net/img01_22.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35479" PostHistoryTypeId="5" PostId="12338" RevisionGUID="2c7b3a25-f262-458e-8a7d-8cde25fb5ead" CreationDate="2021-11-15T20:37:42.573" UserId="17533" Comment="added 1696 characters in body" Text="I'm attempting to use the jump flood algorithm to compute distance transforms of an arbitrary texture derived from a canvas2d context, roughly following the explanations detailed [here](https://blog.demofox.org/2016/02/29/fast-voronoi-diagrams-and-distance-dield-textures-on-the-gpu-with-the-jump-flooding-algorithm/)/[here](https://www.youtube.com/watch?v=A0pxY9QsgJE). &#xD;&#xA;&#xD;&#xA;In the [demo](https://nchilla.github.io/shaders/sdf-posters/experiments/parallel-flood-fill/) I have going, nothing happens for the first 9 waves, and then all of a sudden it begins to display something that is wrong in a way that I don't quite understand. See images:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;| Wave count | Display |&#xD;&#xA;| -------- | -------------- |&#xD;&#xA;| 1-9 - no change   | ![rg stores position of original seeds](https://github.com/nchilla/shaders/raw/main/troubleshooting/Screen%20Shot%202021-11-15%20at%203.26.22%20PM.png) |&#xD;&#xA;| 10 - begins to do jump-flood-y stuff | ![begins to do jump-flood-y stuff](https://github.com/nchilla/shaders/raw/main/troubleshooting/Screen%20Shot%202021-11-15%20at%203.26.39%20PM.png)      |&#xD;&#xA;| 18 - weird artifacting and errors | ![weird artifacting in the bottom left](https://github.com/nchilla/shaders/raw/main/troubleshooting/Screen%20Shot%202021-11-15%20at%203.26.59%20PM.png)      |&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the main jump flood step function. I'm using the A value to check if a pixel is filled in, and using RG to store the seed origin.&#xD;&#xA;&#xD;&#xA;```lang-glsl&#xD;&#xA;vec4 step_jfa(vec2 pCoord,float pass){&#xD;&#xA;&#xD;&#xA;  // looking at pixel P:&#xD;&#xA;&#xD;&#xA;  //offset neighbors according to pass number&#xD;&#xA;  float offset=exp2(log2(img_width)  - pass - 1.);&#xD;&#xA;&#xD;&#xA;  vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;  float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;    // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;  for(float x = -1.; x &lt;= 1.; x++) {&#xD;&#xA;    for(float y = -1.; y &lt;= 1.; y++) {&#xD;&#xA;      vec2 nCoord=pCoord;&#xD;&#xA;      nCoord.x+=x*offset;&#xD;&#xA;      nCoord.y+=y*offset;&#xD;&#xA;&#xD;&#xA;      // if the loop item Q exists&#xD;&#xA;      if(nCoord.x&gt;0.&amp;&amp;nCoord.x&lt;=img_width&amp;&amp;nCoord.y&gt;0.&amp;&amp;nCoord.y&lt;=img_height){&#xD;&#xA;        vec4 neighbor=load0(nCoord);&#xD;&#xA;        //if Q is a seed&#xD;&#xA;        if(neighbor.a&gt;0.){&#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist){&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;            rgba.a=1.;&#xD;&#xA;&#xD;&#xA;          } &#xD;&#xA;&#xD;&#xA;        } &#xD;&#xA;&#xD;&#xA;      } &#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  return rgba;&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I'm assuming the problem is within this function, so to save space I'm going to omit some helper functions for now, but the full code is [here](https://github.com/nchilla/shaders/blob/main/sdf-posters/experiments/parallel-flood-fill/jfa.frag) and I'll update this post if something external turns out to be the problem.&#xD;&#xA;&#xD;&#xA;My best guess at the moment is that there's an issue with how I'm calculating the offset in each shader pass. When I tried mapping the offset to the B value of each pixel in the shader, it turns out to be wildly off from where it should be based on the pass. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35482" PostHistoryTypeId="5" PostId="12342" RevisionGUID="99c75d50-8de0-401d-9241-34298a9e9751" CreationDate="2021-11-16T07:46:51.990" UserId="13095" Comment="Use normal font weight and add some minor adjustments" Text="&#xD;&#xA;This is the basic implementation of the z-buffer algorithm&#xD;&#xA;    Suppose the depth buffer is a matrix `d[100][100];`&#xD;&#xA;&#xD;&#xA;    for(each polygon P)&#xD;&#xA;    {&#xD;&#xA;         for(each pixel (X, Y) on the polygon)&#xD;&#xA;         {&#xD;&#xA;             depth_variable = depth of P at (X, Y);&#xD;&#xA;             if(depth &lt; d[X][Y])&#xD;&#xA;             {&#xD;&#xA;                 color_variable = color of P at (X, Y);&#xD;&#xA;                 set the pixel color at (X, Y) to color_variable;&#xD;&#xA;                 d[X][Y] = depth_variable;&#xD;&#xA;             }&#xD;&#xA;         }&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;As we can see while iterating through polygons we only store the new pixel value if the new depth is less (or less than equal to depending on the setting as mentioned by Mr. Nathan Reed) than the stored one in the depth buffer, so it doesn't matter in which order you render the polygons. &#xD;&#xA;&#xD;&#xA;The only thing that matters is the fact which polygon has the least depth at a particular pixel.&#xD;&#xA;     " ContentLicense="CC BY-SA 4.0" />
  <row Id="35483" PostHistoryTypeId="5" PostId="4089" RevisionGUID="d00dd9b4-c1c5-4c8a-ba53-6c31a4c8cbba" CreationDate="2021-11-16T07:59:17.240" UserId="13095" Comment="Fix some grammar and spelling" Text="If you use alpha blending, then the order of rendered polygons matters even if you use depth writes &amp; tests. E.g. imagine you render two triangles A (red) and B (blue) with 50% opacity where the smaller triangle B is in front of A. If you render A before B then the B will appear purple, but if you render B before A then B will appear dark blue (pixels for A are not rendered where the triangles overlap).&#xD;&#xA;&#xD;&#xA;However, if you use opaque rendering, then the frame buffer values will be the same regardless of the rendering order, except in the special case Nathan mentioned where the depth values are equal for the two triangles.&#xD;&#xA;&#xD;&#xA;Only thing where the rendering order matters for the z-buffer result that comes to mind is if you use a specific stencil test &amp; ops. E.g. when rendering A the stencil test passes and writes a value to the stencil buffer which causes B to fail and results in only triangle A being visible. But if you render B before A, then you see B in front of A. This will naturally influence also frame buffer values." ContentLicense="CC BY-SA 4.0" />
  <row Id="35484" PostHistoryTypeId="5" PostId="12337" RevisionGUID="59c8e26f-8b90-4672-8bbd-b0cf9a24149d" CreationDate="2021-11-16T09:07:01.893" UserId="10096" Comment="deleted 1142 characters in body" Text="I have rewritten my answer to make it easier to follow and I also fixed some mistakes.&#xD;&#xA;&#xD;&#xA;Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). That is, the set of points of your surface is $\mathcal{M} = \{S(\beta, \gamma) \,:\, (\beta, \gamma) \in [0,1]^2\}$. Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n = \frac{\partial_\beta S \times \partial_\gamma S}{\|\partial_\beta S \times \partial_\gamma S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(\beta, \gamma) = S(\beta, \gamma) + h(u(\beta, \gamma),v(\beta, \gamma))n(\beta, \gamma)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_\beta T \times \partial_\gamma T$$&#xD;&#xA;$$\partial_\beta T = \partial_\beta S+(\partial_\beta h)n + h(\partial_\beta n), \quad \partial_\gamma T = \partial_\gamma S+(\partial_\gamma h)n + h(\partial_\gamma n)$$&#xD;&#xA;$$ \partial_\beta T \approx \partial_\beta S+(\partial_\beta h)n, \quad \partial_\gamma T \approx \partial_\gamma S+(\partial_\gamma h)n$$&#xD;&#xA;$$m\approx (\partial_\beta S+(\partial_\beta h)n)\times(\partial_\gamma S+(\partial_\gamma h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_\beta S\times\partial_\gamma S + (\partial_\beta  h)(n\times\partial_\gamma S) + (\partial_\gamma h)(\partial_\beta S\times n) + \cancel{(\partial_\beta h)(\partial_\gamma h)(n\times n)}$$&#xD;&#xA;&#xD;&#xA;The above expression gives you an approximation of the (not necessarily unit length) normal of the displaced surface $T$. This is Blinn's approximation - it assumes that $h$ is small enough for $h(\partial_\beta n)$ and $h(\partial_\gamma n)$ to be ignored.&#xD;&#xA;&#xD;&#xA;Let us consider how this can be applied in practice. There you usually have a triangle mesh. Then if we know how to modify the normal for every triangle, we know how to modify it for the whole mesh. Consider a specific triangle with vertices $p_0, p_1, p_2 \in \mathbb{R}^3$. We can parametrize the triangle through barycentric coordinates $\alpha, \beta, \gamma \geq 0, \alpha + \beta + \gamma = 1$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;We can now compute the partial derivatives of $S$:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} S = p_1 - p_0, \, \partial_{\gamma} S = p_2 - p_0,$$&#xD;&#xA;&#xD;&#xA;which turn out to be the edges of the triangle. Then the geometric normal is:&#xD;&#xA;&#xD;&#xA;$$n_g = \partial_{\beta}S \times \partial_\gamma S, \, \hat{n_g} = \frac{n_g}{\|n_g\|}.$$&#xD;&#xA;&#xD;&#xA;We also need $\partial_{\beta} h, \, \partial_\gamma h$ in order to be able to evaluate the perturbed normal. Let the texture coordinates at the 3 triangle vertices be $uv_0, uv_1, uv_2 \in \mathbb{R}^2$, then the reparametrization from barycentric coordinates to UV coordinates is given by:&#xD;&#xA;&#xD;&#xA;$$uv(\beta, \gamma) = uv_0 + \beta (uv_1-uv_0) + \gamma (uv_2-uv_0).$$&#xD;&#xA;&#xD;&#xA;We can now compute the partial derivatives:&#xD;&#xA;&#xD;&#xA;$$\partial_\beta h(uv(\beta, \gamma)) = (uv_1-uv_0) \cdot (\partial_u h(uv(\beta, \gamma)),\partial_v h(uv(\beta, \gamma)))$$&#xD;&#xA;$$\partial_\gamma h(uv(\beta, \gamma)) = (uv_2-uv_0) \cdot (\partial_u h(uv(\beta, \gamma)),\partial_v h(uv(\beta, \gamma)))$$&#xD;&#xA;&#xD;&#xA;The finally the perturbed normal is:&#xD;&#xA;&#xD;&#xA;$$m_g = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)n_g\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times n_g.$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences:&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) \approx \frac{h(u+\epsilon,v) - h(u,v)}{\epsilon}, \, \partial_v h(u,v) \approx \frac{h(u, v+\epsilon) - h(u,v)}{\epsilon}$$&#xD;&#xA;&#xD;&#xA;Here is some code to clarify how this would be implemented:&#xD;&#xA;&#xD;&#xA;    // Assume the following is given for a triangle&#xD;&#xA;    vec3 p0, p1, p2;    // positions of the 3 vertices&#xD;&#xA;    vec2 uv0, uv1, uv2; // texture coordinates at the 3 vertices&#xD;&#xA;    // epsilon for the finite differences&#xD;&#xA;    float eps;&#xD;&#xA;    // we want to compute the normal at bary coords (beta, gamma)&#xD;&#xA;    float beta, gamma;  // barycentric coordinates&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // compute edges&#xD;&#xA;    vec3 e1 = p1-p0;&#xD;&#xA;    vec3 e2 = p2-p0;&#xD;&#xA;&#xD;&#xA;    // compute geometric normal&#xD;&#xA;    vec3 n_g = cross(e1,e2);&#xD;&#xA;    vec3 n_g_n = normalize(n_g);&#xD;&#xA;&#xD;&#xA;    // compute n x (d_gamma S)&#xD;&#xA;    vec3 t_g = -cross(n_g, e2);&#xD;&#xA;&#xD;&#xA;    // compute (d_beta S) x n&#xD;&#xA;    vec3 b_g = -cross(e1, n);&#xD;&#xA;&#xD;&#xA;    // compute partial derivatives of h&#xD;&#xA;    vec2 uv = uv0 + beta * (uv1-uv0) + gamma * (uv2-uv0);&#xD;&#xA;    vec2 h_uv = 1/eps * (vec2(h(uv+vec2(eps,0)), h(uv+vec2(0,eps))) - vec2(h(uv)));&#xD;&#xA;    float h_beta = dot(uv1-uv0, h_uv);&#xD;&#xA;    float h_gamma = dot(uv2-uv0, h_uv);&#xD;&#xA;&#xD;&#xA;    // compute coefficients&#xD;&#xA;    float coef_n = 1.0;&#xD;&#xA;    float coef_t = -h_beta;&#xD;&#xA;    float coef_b = -h_gamma;&#xD;&#xA;    &#xD;&#xA;    // compute new geometric normal&#xD;&#xA;    vec3 m_g = coef_n * n_g + coef_t * t_g + coef_b * b_g;&#xD;&#xA;&#xD;&#xA;Note that this matches how normal mapping is sometimes defined, with a sampled normal $(c_n, c_t, c_g) = (1, -\partial_\beta h, -\partial_\gamma h)$:&#xD;&#xA;&#xD;&#xA;$$m_g = c_n (\partial_\beta S \times \partial_\gamma S) + c_t (n_g \times \partial_\gamma S) + c_b (\partial_\beta S \times n_g).$$&#xD;&#xA;&#xD;&#xA;Note that the above doesn't take into account shading normals. When considering those various approaches have been taken. I can suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] for more details on that.&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35485" PostHistoryTypeId="5" PostId="12337" RevisionGUID="036c1dca-b02b-4cbb-a2ea-c72e7c82c608" CreationDate="2021-11-16T09:12:21.260" UserId="10096" Comment="deleted 1142 characters in body" Text="I have rewritten my answer to make it easier to follow and I also fixed some mistakes.&#xD;&#xA;&#xD;&#xA;Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). That is, the set of points of your surface is $\mathcal{M} = \{S(\beta, \gamma) \,:\, (\beta, \gamma) \in [0,1]^2\}$. Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n = \frac{\partial_\beta S \times \partial_\gamma S}{\|\partial_\beta S \times \partial_\gamma S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(\beta, \gamma) = S(\beta, \gamma) + h(u(\beta, \gamma),v(\beta, \gamma))n(\beta, \gamma)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_\beta T \times \partial_\gamma T$$&#xD;&#xA;$$\partial_\beta T = \partial_\beta S+(\partial_\beta h)n + h(\partial_\beta n), \quad \partial_\gamma T = \partial_\gamma S+(\partial_\gamma h)n + h(\partial_\gamma n)$$&#xD;&#xA;$$ \partial_\beta T \approx \partial_\beta S+(\partial_\beta h)n, \quad \partial_\gamma T \approx \partial_\gamma S+(\partial_\gamma h)n$$&#xD;&#xA;$$m\approx (\partial_\beta S+(\partial_\beta h)n)\times(\partial_\gamma S+(\partial_\gamma h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_\beta S\times\partial_\gamma S + (\partial_\beta  h)(n\times\partial_\gamma S) + (\partial_\gamma h)(\partial_\beta S\times n) + \cancel{(\partial_\beta h)(\partial_\gamma h)(n\times n)}$$&#xD;&#xA;&#xD;&#xA;The above expression gives you an approximation of the (not necessarily unit length) normal of the displaced surface $T$. This is Blinn's approximation - it assumes that $h$ is small enough for $h(\partial_\beta n)$ and $h(\partial_\gamma n)$ to be ignored.&#xD;&#xA;&#xD;&#xA;Let us consider how this can be applied in practice. There you usually have a triangle mesh. Then if we know how to modify the normal for every triangle, we know how to modify it for the whole mesh. Consider a specific triangle with vertices $p_0, p_1, p_2 \in \mathbb{R}^3$. We can parametrize the triangle through barycentric coordinates $\alpha, \beta, \gamma \geq 0, \alpha + \beta + \gamma = 1$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;We can now compute the partial derivatives of $S$:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} S = p_1 - p_0, \, \partial_{\gamma} S = p_2 - p_0,$$&#xD;&#xA;&#xD;&#xA;which turn out to be the edges of the triangle. Then the geometric normal is:&#xD;&#xA;&#xD;&#xA;$$n_g = \partial_{\beta}S \times \partial_\gamma S, \, \hat{n_g} = \frac{n_g}{\|n_g\|}.$$&#xD;&#xA;&#xD;&#xA;We also need $\partial_{\beta} h, \, \partial_\gamma h$ in order to be able to evaluate the perturbed normal. Let the texture coordinates at the 3 triangle vertices be $uv_0, uv_1, uv_2 \in \mathbb{R}^2$, then the reparametrization from barycentric coordinates to UV coordinates is given by:&#xD;&#xA;&#xD;&#xA;$$uv(\beta, \gamma) = uv_0 + \beta (uv_1-uv_0) + \gamma (uv_2-uv_0).$$&#xD;&#xA;&#xD;&#xA;We can now compute the partial derivatives:&#xD;&#xA;&#xD;&#xA;$$\partial_\beta h(uv(\beta, \gamma)) = (uv_1-uv_0) \cdot (\partial_u h(uv(\beta, \gamma)),\partial_v h(uv(\beta, \gamma)))$$&#xD;&#xA;$$\partial_\gamma h(uv(\beta, \gamma)) = (uv_2-uv_0) \cdot (\partial_u h(uv(\beta, \gamma)),\partial_v h(uv(\beta, \gamma)))$$&#xD;&#xA;&#xD;&#xA;The finally the perturbed normal is:&#xD;&#xA;&#xD;&#xA;$$m_g = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)\hat{n_g}\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times \hat{n_g}.$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences:&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) \approx \frac{h(u+\epsilon,v) - h(u,v)}{\epsilon}, \, \partial_v h(u,v) \approx \frac{h(u, v+\epsilon) - h(u,v)}{\epsilon}$$&#xD;&#xA;&#xD;&#xA;Here is some code to clarify how this would be implemented:&#xD;&#xA;&#xD;&#xA;    // Assume the following is given for a triangle&#xD;&#xA;    vec3 p0, p1, p2;    // positions of the 3 vertices&#xD;&#xA;    vec2 uv0, uv1, uv2; // texture coordinates at the 3 vertices&#xD;&#xA;    // epsilon for the finite differences&#xD;&#xA;    float eps;&#xD;&#xA;    // we want to compute the normal at bary coords (beta, gamma)&#xD;&#xA;    float beta, gamma;  // barycentric coordinates&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // compute edges&#xD;&#xA;    vec3 e1 = p1-p0;&#xD;&#xA;    vec3 e2 = p2-p0;&#xD;&#xA;&#xD;&#xA;    // compute geometric normal&#xD;&#xA;    vec3 n_g = cross(e1,e2);&#xD;&#xA;    vec3 n_g_n = normalize(n_g);&#xD;&#xA;&#xD;&#xA;    // compute n x (d_gamma S)&#xD;&#xA;    vec3 t_g = -cross(n_g_n, e2);&#xD;&#xA;&#xD;&#xA;    // compute (d_beta S) x n&#xD;&#xA;    vec3 b_g = -cross(e1, n_g_n);&#xD;&#xA;&#xD;&#xA;    // compute partial derivatives of h&#xD;&#xA;    vec2 uv = uv0 + beta * (uv1-uv0) + gamma * (uv2-uv0);&#xD;&#xA;    vec2 h_uv = 1/eps * (vec2(h(uv+vec2(eps,0)), h(uv+vec2(0,eps))) - vec2(h(uv)));&#xD;&#xA;    float h_beta = dot(uv1-uv0, h_uv);&#xD;&#xA;    float h_gamma = dot(uv2-uv0, h_uv);&#xD;&#xA;&#xD;&#xA;    // compute coefficients&#xD;&#xA;    float coef_n = 1.0;&#xD;&#xA;    float coef_t = -h_beta;&#xD;&#xA;    float coef_b = -h_gamma;&#xD;&#xA;    &#xD;&#xA;    // compute new geometric normal&#xD;&#xA;    vec3 m_g = coef_n * n_g + coef_t * t_g + coef_b * b_g;&#xD;&#xA;&#xD;&#xA;Note that this matches how normal mapping is sometimes defined, with a sampled normal $(c_n, c_t, c_b) = (1, -\partial_\beta h, -\partial_\gamma h)$:&#xD;&#xA;&#xD;&#xA;$$m_g = c_n (\partial_\beta S \times \partial_\gamma S) + c_t (\hat{n_g} \times \partial_\gamma S) + c_b (\partial_\beta S \times \hat{n_g}).$$&#xD;&#xA;&#xD;&#xA;You may notice that the cross product arguments have been switched around in the last two term. This is because of how tangent space is defined when doing normal mapping. You will see I have done the same in the code (the minuses involved in $t_g, b_g$). The above doesn't take into account shading normals. When considering those, various approaches have been proposed. I can suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] for more details on that.&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35486" PostHistoryTypeId="5" PostId="12337" RevisionGUID="681362a6-f9d1-45d1-a2df-9703ccc95017" CreationDate="2021-11-16T09:19:41.743" UserId="10096" Comment="deleted 3 characters in body" Text="I have rewritten my answer to make it easier to follow and I also fixed some mistakes.&#xD;&#xA;&#xD;&#xA;Let $S:[0,1]^2 \rightarrow \mathbb{R}^3$ be some parameterization of your surface (assume that the derivatives do not become zero anywhere, i.e. it's regular/an immersion). That is, the set of points of your surface is $\mathcal{M} = \{S(\beta, \gamma) \,:\, (\beta, \gamma) \in [0,1]^2\}$. Let $h:[0,1]^2\rightarrow \mathbb{R}$ be the heightmap. The unit normal $n:[0,1]^2\rightarrow \mathbb{R}^3$ is given by the normalized cross product of the partial derivatives: $n = \frac{\partial_\beta S \times \partial_\gamma S}{\|\partial_\beta S \times \partial_\gamma S\|}$. Then we displace the surface with the heightmap along the normal in order to construct a new surface $T(\beta, \gamma) = S(\beta, \gamma) + h(u(\beta, \gamma),v(\beta, \gamma))n(\beta, \gamma)$. We want to find the normal of $T$: &#xD;&#xA;&#xD;&#xA;$$m = \partial_\beta T \times \partial_\gamma T$$&#xD;&#xA;$$\partial_\beta T = \partial_\beta S+(\partial_\beta h)n + h(\partial_\beta n), \quad \partial_\gamma T = \partial_\gamma S+(\partial_\gamma h)n + h(\partial_\gamma n)$$&#xD;&#xA;$$ \partial_\beta T \approx \partial_\beta S+(\partial_\beta h)n, \quad \partial_\gamma T \approx \partial_\gamma S+(\partial_\gamma h)n$$&#xD;&#xA;$$m\approx (\partial_\beta S+(\partial_\beta h)n)\times(\partial_\gamma S+(\partial_\gamma h)n) = $$&#xD;&#xA;$$\require{cancel}\partial_\beta S\times\partial_\gamma S + (\partial_\beta  h)(n\times\partial_\gamma S) + (\partial_\gamma h)(\partial_\beta S\times n) + \cancel{(\partial_\beta h)(\partial_\gamma h)(n\times n)}$$&#xD;&#xA;&#xD;&#xA;The above expression gives you an approximation of the (not necessarily unit length) normal of the displaced surface $T$. This is Blinn's approximation - it assumes that $h$ is small enough for $h(\partial_\beta n)$ and $h(\partial_\gamma n)$ to be ignored.&#xD;&#xA;&#xD;&#xA;Let us consider how this can be applied in practice. There you usually have a triangle mesh. Then if we know how to modify the normal for every triangle, we know how to modify it for the whole mesh. Consider a specific triangle with vertices $p_0, p_1, p_2 \in \mathbb{R}^3$. We can parametrize the triangle through barycentric coordinates $\alpha, \beta, \gamma \geq 0, \alpha + \beta + \gamma = 1$:&#xD;&#xA;&#xD;&#xA;$$S(\beta, \gamma) = \alpha p_0 + \beta p_1 + \gamma p_2 = \\&#xD;&#xA;(1-\beta-\gamma) p_0 + \beta p_1 + \gamma p_2 = p_0 + \beta (p_1-p_0) + \gamma (p_2-p_0).$$&#xD;&#xA;&#xD;&#xA;We can now compute the partial derivatives of $S$:&#xD;&#xA;&#xD;&#xA;$$\partial_{\beta} S = p_1 - p_0, \, \partial_{\gamma} S = p_2 - p_0,$$&#xD;&#xA;&#xD;&#xA;which turn out to be the edges of the triangle. Then the geometric normal is:&#xD;&#xA;&#xD;&#xA;$$n_g = \partial_{\beta}S \times \partial_\gamma S, \, \hat{n}_g = \frac{n_g}{\|n_g\|}.$$&#xD;&#xA;&#xD;&#xA;We also need $\partial_{\beta} h, \, \partial_\gamma h$ in order to be able to evaluate the perturbed normal. Let the texture coordinates at the 3 triangle vertices be $uv_0, uv_1, uv_2 \in \mathbb{R}^2$, then the reparametrization from barycentric coordinates to UV coordinates is given by:&#xD;&#xA;&#xD;&#xA;$$uv(\beta, \gamma) = uv_0 + \beta (uv_1-uv_0) + \gamma (uv_2-uv_0).$$&#xD;&#xA;&#xD;&#xA;We can now compute the partial derivatives:&#xD;&#xA;&#xD;&#xA;$$\partial_\beta h(uv(\beta, \gamma)) = (uv_1-uv_0) \cdot (\partial_u h(uv(\beta, \gamma)),\partial_v h(uv(\beta, \gamma)))$$&#xD;&#xA;$$\partial_\gamma h(uv(\beta, \gamma)) = (uv_2-uv_0) \cdot (\partial_u h(uv(\beta, \gamma)),\partial_v h(uv(\beta, \gamma)))$$&#xD;&#xA;&#xD;&#xA;The finally the perturbed normal is:&#xD;&#xA;&#xD;&#xA;$$m_g = \partial_{\beta}S\times\partial_{\gamma}S + (\partial_{\beta} h)\hat{n}_g\times\partial_{\gamma}S + (\partial_{\gamma}h)\partial_{\beta}S\times \hat{n}_g.$$&#xD;&#xA;&#xD;&#xA;To compute $\partial_u h, \, \partial_v h$ you can use finite differences:&#xD;&#xA;&#xD;&#xA;$$\partial_u h(u,v) \approx \frac{h(u+\epsilon,v) - h(u,v)}{\epsilon}, \, \partial_v h(u,v) \approx \frac{h(u, v+\epsilon) - h(u,v)}{\epsilon}$$&#xD;&#xA;&#xD;&#xA;Here is some code to clarify how this would be implemented:&#xD;&#xA;&#xD;&#xA;    // Assume the following is given for a triangle&#xD;&#xA;    vec3 p0, p1, p2;    // positions of the 3 vertices&#xD;&#xA;    vec2 uv0, uv1, uv2; // texture coordinates at the 3 vertices&#xD;&#xA;    // epsilon for the finite differences&#xD;&#xA;    float eps;&#xD;&#xA;    // we want to compute the normal at bary coords (beta, gamma)&#xD;&#xA;    float beta, gamma;  // barycentric coordinates&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // compute edges&#xD;&#xA;    vec3 e1 = p1-p0;&#xD;&#xA;    vec3 e2 = p2-p0;&#xD;&#xA;&#xD;&#xA;    // compute geometric normal&#xD;&#xA;    vec3 n_g = cross(e1,e2);&#xD;&#xA;    vec3 n_g_n = normalize(n_g);&#xD;&#xA;&#xD;&#xA;    // compute n x (d_gamma S)&#xD;&#xA;    vec3 t_g = -cross(n_g_n, e2);&#xD;&#xA;&#xD;&#xA;    // compute (d_beta S) x n&#xD;&#xA;    vec3 b_g = -cross(e1, n_g_n);&#xD;&#xA;&#xD;&#xA;    // compute partial derivatives of h&#xD;&#xA;    vec2 uv = uv0 + beta * (uv1-uv0) + gamma * (uv2-uv0);&#xD;&#xA;    vec2 h_uv = 1/eps * (vec2(h(uv+vec2(eps,0)), h(uv+vec2(0,eps))) - vec2(h(uv)));&#xD;&#xA;    float h_beta = dot(uv1-uv0, h_uv);&#xD;&#xA;    float h_gamma = dot(uv2-uv0, h_uv);&#xD;&#xA;&#xD;&#xA;    // compute coefficients&#xD;&#xA;    float coef_n = 1.0;&#xD;&#xA;    float coef_t = -h_beta;&#xD;&#xA;    float coef_b = -h_gamma;&#xD;&#xA;    &#xD;&#xA;    // compute new geometric normal&#xD;&#xA;    vec3 m_g = coef_n * n_g + coef_t * t_g + coef_b * b_g;&#xD;&#xA;&#xD;&#xA;Note that this matches how normal mapping is sometimes defined, with a sampled normal $(c_n, c_t, c_b) = (1, -\partial_\beta h, -\partial_\gamma h)$:&#xD;&#xA;&#xD;&#xA;$$m_g = c_n (\partial_\beta S \times \partial_\gamma S) + c_t (\partial_\gamma S\times\hat{n}_g) + c_b (\hat{n}_g\times \partial_\beta S).$$&#xD;&#xA;&#xD;&#xA;You may notice that the cross product arguments have been switched around in the last two term. This is because of how tangent space is defined when doing normal mapping. You will see I have done the same in the code (the minuses involved in $t_g, b_g$). The above doesn't take into account shading normals. When considering those, various approaches have been proposed. I can suggest looking into [Simulation of Wrinkled Surfaces Revisited by Mikkelsen][1] for more details on that.&#xD;&#xA;&#xD;&#xA;  [1]: http://image.diku.dk/projects/media/morten.mikkelsen.08.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35487" PostHistoryTypeId="5" PostId="12339" RevisionGUID="17bb8e70-4ca2-4caf-8215-006ce6d10232" CreationDate="2021-11-16T12:29:49.957" UserId="7952" Comment="added 978 characters in body" Text="You are on the right track with your post...&#xD;&#xA;&#xD;&#xA;Compute two slopes then somehow use those slopes to find a normal. The slopes are the result of finite difference (like central difference)&#xD;&#xA;&#xD;&#xA;But why two slopes? Because we can use them to construct two independent vectors whose cross product will become our normal vector.&#xD;&#xA;&#xD;&#xA;One vector is in the texture's $u$ direction and is simply $vec3(1,0,slopeU)$&#xD;&#xA;&#xD;&#xA;The other vector is in the textures $v$ direction and is $vec3(0,1,slopeV)$&#xD;&#xA;&#xD;&#xA;**W**here are these vectors coming from?&#xD;&#xA;Take a look at a 2D cartesian coordinate system such as [this one][1]. Now overlay the height map texture over the cartesian coordinate system with the point we are interested in located at the origin. The u direction of the texture lines up with the x direction of the coordinate system. Compute the u direction slope for the heightmap at that point using central differences. This samples a=(-1,0) and b=(1,0) on the cartesian coordinate system. These two points form a line on the x axis. This is the same direction the vector needs to point. Remember that vectors have direction but no location, so as long as we pick a vector that points in the same direction as the slope calculation then it doesn't matter what values we plug into the vector, just that it has the right direction. A natural choice for the vector in the same direction as the slope is (1,0) combined with the slope gives (1,0,slopeU).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With the two directions computed, and the two vectors created:&#xD;&#xA;Take the cross product and normalize, its really that simple.&#xD;&#xA;&#xD;&#xA;Both of the vectors are tangent to the height, and they are independent of each other. They can be constructed as $(0,1,S_v)$ and $(1,0,S_u)$ because the slopes are very specifically taken in those directions. If you change the directions used to compute the slopes then you have to change the directions used in the vectors to match.&#xD;&#xA;&#xD;&#xA;There are a few other minor caveats, like the calculations are assumed to always happen at the origin, and the height map, which usually contains values between 0 and 1 needs to be scaled to its final height.&#xD;&#xA;&#xD;&#xA;**O**rigin and direction choices:&#xD;&#xA;Yes, the choice to do the calculations at the origin is completely arbitrary. It just makes the math more convenient.&#xD;&#xA;&#xD;&#xA;The choice of the (1,0) and (0,1) is not arbitrary. These are chosen because they lie in the exact same direction as the computed slopes. If we chose (12,243,slopeU) the question becomes where does this vector point? Well this vector points very heavily toward the y axis. (the y value of 243 ) so our calculation of the slope along the x (slopeU) axis will be used to compute a slope pointing nearly at the y axis and the end result will give a very skewed value. For this reason, most applications assume a grid spacing of 1 between height map points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**T**heory is all nice, but where the rubber meets the road we need something that can be implemented, and runs in a timely manner. These functions can be implemented naively on the CPU or easily translated to a Compute Shader. They can also be used in real time to compute normals for height mapped geometry like water and terrain. Also the functions come straight out of the book FGED2 which gives brief but good explanation of the math here. This implementation of central difference can also be easily extended to 3 dimensions where it can be used to compute normals for isosurface extraction in real time.&#xD;&#xA;&#xD;&#xA;slope in x direction: $d_x = \frac{\Delta z}{ \Delta x} = \frac{scale}{2}[h(i+1,j)-h(i-1,j)]$&#xD;&#xA;&#xD;&#xA;slope in y direction: $d_y = \frac{\Delta z}{ \Delta y} = \frac{scale}{2}[h(i,j+1)-h(i,j-1)]$&#xD;&#xA;&#xD;&#xA;x direction vector: $u_x = (1,0,d_x)$&#xD;&#xA;&#xD;&#xA;y direction vector: $u_y = (0,1,d_y)$&#xD;&#xA;&#xD;&#xA;Final Value: $m = normalize(u_x \times u_y ) = \frac{(-d_x,-d_y,1)}{\sqrt{d^2_x+d^2_y+1}}$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dqm1v390v3ac1.cloudfront.net/img01_22.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35488" PostHistoryTypeId="2" PostId="12343" RevisionGUID="1b787295-8881-463a-a7be-6c292513fed6" CreationDate="2021-11-16T15:45:01.197" UserId="17540" Text="I'm writing a shader that creates a grid with coloured tiles. The color is derived from a pixel at that location on a texture. But around the tiles I get these unwanted seams.&#xD;&#xA;&#xD;&#xA;I can't seem to figure out how to get rid of those, I tried interpolating with the neighbouring cells.&#xD;&#xA;&#xD;&#xA;Suggestions on the web point to setting texture clamping/wrapping to get rid of seams, but that's only a valid solution when I'd sample near the border of the source texture.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;```&#xD;&#xA;#ifdef GL_ES&#xD;&#xA;precision highp float;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;varying vec2 v_texcoord;&#xD;&#xA;&#xD;&#xA;uniform sampler2D u_source; // ./assets/textures/moon.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vec2 st = v_texcoord;&#xD;&#xA;&#xD;&#xA;  float scale = 20.0;&#xD;&#xA;&#xD;&#xA;  vec2 uv = st * vec2(scale);&#xD;&#xA;  vec2 ipos = floor(uv);      // col &amp; row index on the grid (0, 1, 2, 3, ..., 80)&#xD;&#xA;&#xD;&#xA;  vec2 iposSample = (ipos + vec2(0.5, 0.5)) / vec2(scale);&#xD;&#xA;  gl_FragColor = texture2D(u_source, iposSample);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oYNmH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35490" PostHistoryTypeId="1" PostId="12343" RevisionGUID="1b787295-8881-463a-a7be-6c292513fed6" CreationDate="2021-11-16T15:45:01.197" UserId="17540" Text="Tiling in GLSL creates unwanted seams" ContentLicense="CC BY-SA 4.0" />
  <row Id="35491" PostHistoryTypeId="3" PostId="12343" RevisionGUID="1b787295-8881-463a-a7be-6c292513fed6" CreationDate="2021-11-16T15:45:01.197" UserId="17540" Text="|glsl|webgl|fragment-shader|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35492" PostHistoryTypeId="2" PostId="12344" RevisionGUID="1dac8b5c-aebe-40be-af97-85318a3831de" CreationDate="2021-11-16T16:20:22.523" UserId="7952" Text="I took a few minutes and hacked this to life for you. The bugs were all pretty basic things like using floating point math where it should have been using interger math. All those little fractions add up so be careful there. I'm not sure what the alpha channel was up to, I removed that completely. The biggest issue was the large if statement was skipping some of the distance transforms which snowballed as the iters stepped. I'm not sure how pass is being computed I came up with my own version for that. The code below isn't perfectly fixed but it should be enough to get you up and running (hopefully).&#xD;&#xA;&#xD;&#xA;    vec4 step_jfa(vec2 pCoord,float pass)&#xD;&#xA;    {&#xD;&#xA;     // looking at pixel P:&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     float offset=exp2(log2(img_width)  - pass - 1.);&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;   &#xD;&#xA;     // looking at pixel P:&#xD;&#xA;     float img_width = iResolution.x;&#xD;&#xA;     float pass = iter;&#xD;&#xA;     vec2 pCoord = fragCoord;&#xD;&#xA;&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     int offset= int(exp2(log2(img_width)  - pass - 1.));&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;     // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;     ivec2 nCoord= ivec2(pCoord+0.5);&#xD;&#xA;     for(float x = -1.; x &lt;= 1.; x++) &#xD;&#xA;     {&#xD;&#xA;       for(float y = -1.; y &lt;= 1.; y++) &#xD;&#xA;       {&#xD;&#xA;         ivec2 sCoord = nCoord + ivec2(x,y)*offset;&#xD;&#xA;         //nCoord.x+=x*offset;&#xD;&#xA;         //nCoord.y+=y*offset;&#xD;&#xA;&#xD;&#xA;         // if the loop item Q exists&#xD;&#xA;         //if(nCoord.x&gt;0.&amp;&amp;nCoord.x&lt;=img_width&amp;&amp;nCoord.y&gt;0.&amp;&amp;nCoord.y&lt;=img_height){&#xD;&#xA;          vec4 neighbor=load0(sCoord);&#xD;&#xA;          //if Q is a seed&#xD;&#xA;          //if(neighbor.a&gt;0.){&#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist)&#xD;&#xA;          {&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;            //rgba.a=1.;&#xD;&#xA;&#xD;&#xA;           } &#xD;&#xA;         } &#xD;&#xA;       } &#xD;&#xA;       return rgba;        &#xD;&#xA;     }&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="35494" PostHistoryTypeId="5" PostId="12344" RevisionGUID="7e6fc24d-c7b5-4df7-b238-1896ec44d123" CreationDate="2021-11-16T16:57:00.160" UserId="7952" Comment="removed some stuffed used to make it work in my env" Text="I took a few minutes and hacked this to life for you. The bugs were all pretty basic things like using floating point math where it should have been using interger math. All those little fractions add up so be careful there. I'm not sure what the alpha channel was up to, I removed that completely. The biggest issue was the large if statement was skipping some of the distance transforms which snowballed as the iters stepped. I'm not sure how pass is being computed I came up with my own version for that. The code below isn't perfectly fixed but it should be enough to get you up and running (hopefully).&#xD;&#xA;&#xD;&#xA;    vec4 step_jfa(vec2 pCoord,float pass)&#xD;&#xA;    {&#xD;&#xA;     // looking at pixel P:&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     float offset=exp2(log2(img_width)  - pass - 1.);&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;   &#xD;&#xA;&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     int offset= int(exp2(log2(img_width)  - pass - 1.));&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;     // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;     ivec2 nCoord= ivec2(pCoord+0.5);&#xD;&#xA;     for(float x = -1.; x &lt;= 1.; x++) &#xD;&#xA;     {&#xD;&#xA;       for(float y = -1.; y &lt;= 1.; y++) &#xD;&#xA;       {&#xD;&#xA;         ivec2 sCoord = nCoord + ivec2(x,y)*offset;&#xD;&#xA;         //nCoord.x+=x*offset;&#xD;&#xA;         //nCoord.y+=y*offset;&#xD;&#xA;&#xD;&#xA;         // if the loop item Q exists&#xD;&#xA;         //if(nCoord.x&gt;0.&amp;&amp;nCoord.x&lt;=img_width&amp;&amp;nCoord.y&gt;0.&amp;&amp;nCoord.y&lt;=img_height){&#xD;&#xA;          vec4 neighbor=load0(sCoord);&#xD;&#xA;          //if Q is a seed&#xD;&#xA;          //if(neighbor.a&gt;0.){&#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist)&#xD;&#xA;          {&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;            //rgba.a=1.;&#xD;&#xA;&#xD;&#xA;           } &#xD;&#xA;         } &#xD;&#xA;       } &#xD;&#xA;       return rgba;        &#xD;&#xA;     }&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="35495" PostHistoryTypeId="5" PostId="12344" RevisionGUID="06050f63-e54e-4e75-a15d-7452c4358112" CreationDate="2021-11-16T17:17:19.997" UserId="7952" Comment="added 2 characters in body" Text="I took a few minutes and hacked this to life for you. The bugs were all pretty basic things like using floating point math where it should have been using interger math. All those little fractions add up so be careful there. I'm not sure what the alpha channel was up to, I removed that completely. The biggest issue was the large if statement was skipping some of the distance transforms which snowballed as the iters stepped. I'm not sure how pass is being computed I came up with my own version for that. The code below isn't perfectly fixed but it should be enough to get you up and running (hopefully).&#xD;&#xA;&#xD;&#xA;    vec4 step_jfa(vec2 pCoord,float pass)&#xD;&#xA;    {&#xD;&#xA;     // looking at pixel P:&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     //float offset=exp2(log2(img_width)  - pass - 1.);&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;   &#xD;&#xA;&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     int offset= int(exp2(log2(img_width)  - pass - 1.));&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;     // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;     ivec2 nCoord= ivec2(pCoord+0.5);&#xD;&#xA;     for(float x = -1.; x &lt;= 1.; x++) &#xD;&#xA;     {&#xD;&#xA;       for(float y = -1.; y &lt;= 1.; y++) &#xD;&#xA;       {&#xD;&#xA;         ivec2 sCoord = nCoord + ivec2(x,y)*offset;&#xD;&#xA;         //nCoord.x+=x*offset;&#xD;&#xA;         //nCoord.y+=y*offset;&#xD;&#xA;&#xD;&#xA;         // if the loop item Q exists&#xD;&#xA;         //if(nCoord.x&gt;0.&amp;&amp;nCoord.x&lt;=img_width&amp;&amp;nCoord.y&gt;0.&amp;&amp;nCoord.y&lt;=img_height){&#xD;&#xA;          vec4 neighbor=load0(sCoord);&#xD;&#xA;          //if Q is a seed&#xD;&#xA;          //if(neighbor.a&gt;0.){&#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist)&#xD;&#xA;          {&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;            //rgba.a=1.;&#xD;&#xA;&#xD;&#xA;           } &#xD;&#xA;         } &#xD;&#xA;       } &#xD;&#xA;       return rgba;        &#xD;&#xA;     }&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="35496" PostHistoryTypeId="5" PostId="12344" RevisionGUID="643026a2-dc25-4964-97c7-f12392763a39" CreationDate="2021-11-16T17:43:42.990" UserId="7952" Comment="added load0 function" Text="I took a few minutes and hacked this to life for you. The bugs were all pretty basic things like using floating point math where it should have been using interger math. All those little fractions add up so be careful there. I'm not sure what the alpha channel was up to, I removed that completely. The biggest issue was the large if statement was skipping some of the distance transforms which snowballed as the iters stepped. I'm not sure how pass is being computed I came up with my own version for that. The code below isn't perfectly fixed but it should be enough to get you up and running (hopefully).&#xD;&#xA;&#xD;&#xA;    vec4 step_jfa(vec2 pCoord,float pass)&#xD;&#xA;    {&#xD;&#xA;     // looking at pixel P:&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     //float offset=exp2(log2(img_width)  - pass - 1.);&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;   &#xD;&#xA;&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     int offset= int(exp2(log2(img_width)  - pass - 1.));&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;     // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;     ivec2 nCoord= ivec2(pCoord+0.5);&#xD;&#xA;     for(float x = -1.; x &lt;= 1.; x++) &#xD;&#xA;     {&#xD;&#xA;       for(float y = -1.; y &lt;= 1.; y++) &#xD;&#xA;       {&#xD;&#xA;         ivec2 sCoord = nCoord + ivec2(x,y)*offset;&#xD;&#xA;         //nCoord.x+=x*offset;&#xD;&#xA;         //nCoord.y+=y*offset;&#xD;&#xA;&#xD;&#xA;         // if the loop item Q exists&#xD;&#xA;         //if(nCoord.x&gt;0.&amp;&amp;nCoord.x&lt;=img_width&amp;&amp;nCoord.y&gt;0.&amp;&amp;nCoord.y&lt;=img_height){&#xD;&#xA;          vec4 neighbor=load0(sCoord);&#xD;&#xA;          //if Q is a seed&#xD;&#xA;          //if(neighbor.a&gt;0.){&#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist)&#xD;&#xA;          {&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;            //rgba.a=1.;&#xD;&#xA;&#xD;&#xA;           } &#xD;&#xA;         } &#xD;&#xA;       } &#xD;&#xA;       return rgba;        &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the load0 function:&#xD;&#xA;&#xD;&#xA;    vec4 load0(ivec2 p) {&#xD;&#xA;        vec2 uv = (vec2(p)-0.5) / textureSize.xy;&#xD;&#xA;        return texture(usampler, uv);&#xD;&#xA;    }&#xD;&#xA;   " ContentLicense="CC BY-SA 4.0" />
  <row Id="35497" PostHistoryTypeId="5" PostId="12342" RevisionGUID="467a2bde-c76e-4c26-b151-e758fa109c03" CreationDate="2021-11-16T17:55:11.393" UserId="17518" Comment="deleted 6 characters in body" Text="&#xD;&#xA;This is the basic implementation of the z-buffer algorithm .&#xD;&#xA;    Suppose the depth buffer is a matrix `d[][];`&#xD;&#xA;&#xD;&#xA;    for(each polygon P)&#xD;&#xA;    {&#xD;&#xA;         for(each pixel (X, Y) on the polygon)&#xD;&#xA;         {&#xD;&#xA;             depth_variable = depth of P at (X, Y);&#xD;&#xA;             if(depth &lt; d[X][Y])&#xD;&#xA;             {&#xD;&#xA;                 color_variable = color of P at (X, Y);&#xD;&#xA;                 set the pixel color at (X, Y) to color_variable;&#xD;&#xA;                 d[X][Y] = depth_variable;&#xD;&#xA;             }&#xD;&#xA;         }&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;As we can see while iterating through polygons we only store the new pixel value if the new depth is less (or less than equal to depending on the setting as mentioned by Mr. Nathan Reed) than the stored one in the depth buffer, so it doesn't matter in which order you render the polygons. &#xD;&#xA;&#xD;&#xA;The only thing that matters is the fact which polygon has the least depth at a particular pixel.&#xD;&#xA;     " ContentLicense="CC BY-SA 4.0" />
  <row Id="35498" PostHistoryTypeId="5" PostId="12343" RevisionGUID="e7f80a16-67b3-47cb-b314-50115f1a5b7c" CreationDate="2021-11-16T23:12:01.657" UserId="17540" Comment="Added Shadertoy sketch" Text="I'm writing a shader that creates a grid with coloured tiles. The color is derived from a pixel at that location on a texture. But around the tiles I get these unwanted seams.&#xD;&#xA;&#xD;&#xA;I can't seem to figure out how to get rid of those, I tried interpolating with the neighbouring cells.&#xD;&#xA;&#xD;&#xA;Suggestions on the web point to setting texture clamping/wrapping to get rid of seams, but that's only a valid solution when I'd sample near the border of the source texture.&#xD;&#xA;&#xD;&#xA;**Update**: I've created a shadertoy sketch to demonstrate the problem: https://www.shadertoy.com/view/7lV3zz&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;```&#xD;&#xA;#ifdef GL_ES&#xD;&#xA;precision highp float;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;varying vec2 v_texcoord;&#xD;&#xA;&#xD;&#xA;uniform sampler2D u_source; // ./assets/textures/moon.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;  vec2 st = v_texcoord;&#xD;&#xA;&#xD;&#xA;  float scale = 20.0;&#xD;&#xA;&#xD;&#xA;  vec2 uv = st * vec2(scale);&#xD;&#xA;  vec2 ipos = floor(uv);      // col &amp; row index on the grid (0, 1, 2, 3, ..., 80)&#xD;&#xA;&#xD;&#xA;  vec2 iposSample = (ipos + vec2(0.5, 0.5)) / vec2(scale);&#xD;&#xA;  gl_FragColor = texture2D(u_source, iposSample);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/oYNmH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35499" PostHistoryTypeId="2" PostId="12345" RevisionGUID="5794795e-2566-4590-8c95-2a470e24d024" CreationDate="2021-11-16T23:36:34.480" UserId="7952" Text="Using texelFetch appears to give the correct result.&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;&#xD;&#xA;      vec2 st = v_texcoord;&#xD;&#xA;      float scale = 20.0;&#xD;&#xA;&#xD;&#xA;      vec2 uv = st * scale;&#xD;&#xA;      vec2 ipos = floor(uv);      // col &amp; row index on the grid (0, 1, 2, 3, ..., 80)&#xD;&#xA;&#xD;&#xA;      vec2 iposSample = (ipos + vec2(0.5, 0.5)) / vec2(scale);&#xD;&#xA;  &#xD;&#xA;      //gl_FragColor = texture(usource, iposSample);&#xD;&#xA;      gl_FragColor = texelFetch( usource, ivec2(iposSample*imageResolution.xy),0);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The samplers do seem to be part of the issue as texelFetch cleans up the output. I wasn't suggesting clamping or wrapping but rather nearest vs linear. I'm not sure what shader toy uses for its samplers, but texelFetch can have a significant effect on shader toy as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="35501" PostHistoryTypeId="5" PostId="12345" RevisionGUID="802f14b3-3353-459b-b690-63fb751f9fd5" CreationDate="2021-11-17T01:44:12.640" UserId="7952" Comment="added 97 characters in body" Text="Using texelFetch gives the correct result. Here is a [shaderToy][1] that shows an animated version.&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;&#xD;&#xA;      vec2 st = v_texcoord;&#xD;&#xA;      float scale = 20.0;&#xD;&#xA;&#xD;&#xA;      vec2 uv = st * scale;&#xD;&#xA;      vec2 ipos = floor(uv);      // col &amp; row index on the grid (0, 1, 2, 3, ..., 80)&#xD;&#xA;&#xD;&#xA;      vec2 iposSample = (ipos + vec2(0.5, 0.5)) / vec2(scale);&#xD;&#xA;  &#xD;&#xA;      //gl_FragColor = texture(usource, iposSample);&#xD;&#xA;      gl_FragColor = texelFetch( usource, ivec2(iposSample*imageResolution.xy),0);&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The samplers do seem to be part of the issue as texelFetch cleans up the output. I wasn't suggesting clamping or wrapping but rather nearest vs linear. I'm not sure what shader toy uses for its samplers, but texelFetch can have a significant effect on shader toy as well.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/NtG3zh" ContentLicense="CC BY-SA 4.0" />
  <row Id="35502" PostHistoryTypeId="2" PostId="12346" RevisionGUID="c5e034dd-42f2-44eb-9f18-d1c0df14a21c" CreationDate="2021-11-17T09:15:55.050" UserId="13273" Text="I have some questions about the GPU usage of Queues / Queue families, command buffer / pool.&#xD;&#xA;I am reading the Book: `Vulkan Programming Guide: The Official Guide to Learning Vulkan`. What I don't get is how the usage of the GPU is based on the listed items:&#xD;&#xA;&#xD;&#xA;**How I understand how it works:**&#xD;&#xA;There are Queue families (my hardware has 3 families) which can handle different things. There I should use the family with the minimum support with which my program is able to work. So in case not doing graphics, I should use a family without graphics support. That is fine!&#xD;&#xA;Using the same resources between queues within the same family has no negative affect on performance, except synchronization.&#xD;&#xA;&#xD;&#xA;**Question 1:**&#xD;&#xA;Does each Queue family has the full excess of the GPU? Meaning when using just one Queue, does the GPU can work with 100% usage?&#xD;&#xA;&#xD;&#xA;**Question 2:**&#xD;&#xA;Does it make sense using 2 Queues from different families (graphics and transfer) in case the task is to render a scenario (queue graphics) and transfer the finished image to CPU to save it as a file (queue transfer). I am asking that because my graphics queue family also has transfer bit. So maybe it is better to use just this one graphics queue.&#xD;&#xA;&#xD;&#xA;**Question 3:**&#xD;&#xA;The book says that the command buffers belong to a command pool. What is the difference when using 1 pool with several buffers instead of using several pools with each having 1 buffer? Is it only because of the barriers? Or do I have performance issue or access problems when using several pools? It would be nice if someone could write a bit about the pools and buffers (I miss that in the book).&#xD;&#xA;&#xD;&#xA;**Question 4:**&#xD;&#xA;I don't think there is a general answer for this question, but maybe some rule of thumb? When using Vulkan, multi-threading should be used, to not block the CPU. As far as I understood, I would use one thread per command pool, because the barriers (smallest synchronization tools) work per pool. Does that makes sense? Or is it better to use one thread per Queue? Or maybe per Queue family? I also thought about have one thread per queue, which is controlling one thread per command pool, to keep the synchronization simple (each queue thread is like the master of each command pool thread). But here I am confused, because the command pool belongs to a queue family (not a queue itself). So two queues from the same family could use the same command pool.&#xD;&#xA;&#xD;&#xA;Please correct me if something I wrote is wrong. I am new to Vulkan but comming from OpenGL / DirectX 11. I also would like to receive some links to better explanations regarding the Queues and command buffer / pools hierarchy and maybe something about the threading for Vulkan applications. When answering the questions, please give an example scenario if possible (to see which difference it makes). Thanks a lot!" ContentLicense="CC BY-SA 4.0" />
  <row Id="35504" PostHistoryTypeId="1" PostId="12346" RevisionGUID="c5e034dd-42f2-44eb-9f18-d1c0df14a21c" CreationDate="2021-11-17T09:15:55.050" UserId="13273" Text="Vulkan Queue (Family), Command (pool) and Hardware usage" ContentLicense="CC BY-SA 4.0" />
  <row Id="35505" PostHistoryTypeId="3" PostId="12346" RevisionGUID="c5e034dd-42f2-44eb-9f18-d1c0df14a21c" CreationDate="2021-11-17T09:15:55.050" UserId="13273" Text="|vulkan|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35506" PostHistoryTypeId="2" PostId="12347" RevisionGUID="12617edd-2489-45c6-a187-22cf074325a1" CreationDate="2021-11-17T13:09:02.717" UserId="7952" Text="**Queues**&#xD;&#xA;&#xD;&#xA;The Vulkan Queues aren't as segregated as that book makes them sound. If you look at the spec very carefully you will noticed that there must be at least on queue that  supports Graphics, transfer and compute. So you will find a combined Graphics/Transfer/Compute queue on every machine. Some machines will only have this one queue. Then there are specialized Queues such as those dedicated to Compute and dedicated transfer queues.&#xD;&#xA;&#xD;&#xA;Some GPU's have a dedicated hardware unit that only supports transfers. That unit really has no access to the rest of the GPU, so to answer question **1**: no not every queue can access 100% of the GPU. &#xD;&#xA;&#xD;&#xA;But those dedicated pieces of hardware also gives us programmers the power to split up work which answers question **2**: Taking full advantage of the hardware requires splitting the work up among queues. The better a piece of software can do that, the more performance we are likely to get.&#xD;&#xA;&#xD;&#xA;**Command Buffers**&#xD;&#xA;&#xD;&#xA;Question **3**:Command buffers are not thread safe, writing to a buffer with the vkxCmd* functions causes memory allocations. Those memory allocations go back to the pool. The pool then manages memory for all its Command buffers. So writing to several command buffers from a single pool will cause contention on memory and can lead to a pool using much more memory then it needs. Using multiple pools allows that memory to be released periodically(by resetting the pool), it also allows multiple threads to manage their pools/buffers more effectively. There are a few other details here but memory contention and thread safety are the major reason to split up buffers between pools.&#xD;&#xA;&#xD;&#xA;Question **4**:&#xD;&#xA;Splitting threads up between Command pools is the way to go, splitting threads between queues can also be a big win but there is less hardware out there that can take advantage of it. For high end hardware you want threads that can manage async compute, dedicated transfers and multiple command pools along with the graphics queue." ContentLicense="CC BY-SA 4.0" />
  <row Id="35513" PostHistoryTypeId="5" PostId="12346" RevisionGUID="529c1214-38d8-4ae5-8fac-9de72a2c83f6" CreationDate="2021-11-18T08:51:47.897" UserId="13095" Comment="Fix some grammar and spelling" Text="I have some questions about the GPU usage of Queues / Queue families, command buffer / pool.&#xD;&#xA;I am reading the Book: `Vulkan Programming Guide: The Official Guide to Learning Vulkan`. What I don't get is how the usage of the GPU is based on the listed items:&#xD;&#xA;&#xD;&#xA;**How I understand how it works:**&#xD;&#xA;There are Queue families (my hardware has 3 families) which can handle different things. There I should use the family with the minimum support with which my program is able to work. So in case not doing graphics, I should use a family without graphics support. That is fine!&#xD;&#xA;Using the same resources between queues within the same family has no negative effect on performance, except synchronization.&#xD;&#xA;&#xD;&#xA;**Question 1:**&#xD;&#xA;Does each Queue family has the full excess of the GPU? Meaning when using just one Queue, does the GPU can work with 100% usage?&#xD;&#xA;&#xD;&#xA;**Question 2:**&#xD;&#xA;Does it make sense to use 2 Queues from different families (graphics and transfer) in case the task is to render a scenario (queue graphics) and transfer the finished image to the CPU to save it as a file (queue transfer)? I am asking that because my graphics queue family also has a transfer bit. So maybe it is better to use just this one graphics queue.&#xD;&#xA;&#xD;&#xA;**Question 3:**&#xD;&#xA;The book says that the command buffers belong to a command pool. What is the difference when using 1 pool with several buffers instead of using several pools with each having 1 buffer? Is it only because of the barriers? Or do I have performance issues or access problems when using several pools? It would be nice if someone could write a bit about the pools and buffers (I miss that in the book).&#xD;&#xA;&#xD;&#xA;**Question 4:**&#xD;&#xA;I don't think there is a general answer for this question, but maybe some rule of thumb? When using Vulkan, multi-threading should be used, to not block the CPU. As far as I understood, I would use one thread per command pool, because the barriers (smallest synchronization tools) work per pool. Does that make sense? Or is it better to use one thread per Queue? Or maybe per Queue family? I also thought about having one thread per queue, which is controlling one thread per command pool, to keep the synchronization simple (each queue thread is like the master of each command pool thread). But here I am confused because the command pool belongs to a queue family (not a queue itself). So two queues from the same family could use the same command pool.&#xD;&#xA;&#xD;&#xA;Please correct me if something I wrote is wrong. I am new to Vulkan but comming from OpenGL / DirectX 11. I also would like to receive some links to better explanations regarding the Queues and command buffer / pools hierarchy and maybe something about the threading for Vulkan applications. When answering the questions, please give an example scenario if possible (to see which difference it makes). Thanks a lot!" ContentLicense="CC BY-SA 4.0" />
  <row Id="35514" PostHistoryTypeId="5" PostId="12347" RevisionGUID="4076d192-847b-4cb1-aea5-39892a3a3802" CreationDate="2021-11-18T09:12:07.687" UserId="13095" Comment="Fix some grammar and spelling" Text="**Queues**&#xD;&#xA;&#xD;&#xA;The Vulkan Queues aren't as segregated as that book makes them sound. If you look at the spec very carefully you will notice that there must be at least one queue that supports Graphics, transfer and compute. So you will find a combined Graphics/Transfer/Compute queue on every machine. Some machines will only have this one queue. Then there are specialized Queues such as those dedicated to Compute and dedicated transfer queues.&#xD;&#xA;&#xD;&#xA;Some GPU's have a dedicated hardware unit that only supports transfers. That unit really has no access to the rest of the GPU, so to answer question **1**: no not every queue can access 100% of the GPU. &#xD;&#xA;&#xD;&#xA;But those dedicated pieces of hardware also give us programmers the power to split up work which answers question **2**: Taking full advantage of the hardware requires splitting the work up among queues. The better a piece of software can do that, the more performance we are likely to get.&#xD;&#xA;&#xD;&#xA;**Command Buffers**&#xD;&#xA;&#xD;&#xA;Question **3**: Command buffers are not thread-safe, writing to a buffer with the vkxCmd* functions causes memory allocations. Those memory allocations go back to the pool. The pool then manages memory for all its Command buffers. So writing to several command buffers from a single pool will cause contention on memory and can lead to a pool using much more memory than it needs. Using multiple pools allows that memory to be released periodically(by resetting the pool), it also allows multiple threads to manage their pools/buffers more effectively. There are a few other details here but memory contention and thread safety are the major reason to split up buffers between pools.&#xD;&#xA;&#xD;&#xA;Question **4**:&#xD;&#xA;Splitting threads up between Command pools is the way to go, splitting threads between queues can also be a big win but there is less hardware out there that can take advantage of it. For high-end hardware, you want threads that can manage async compute, dedicated transfers, and multiple command pools along with the graphics queue." ContentLicense="CC BY-SA 4.0" />
  <row Id="35515" PostHistoryTypeId="5" PostId="12344" RevisionGUID="bd3fe518-c6c7-472d-8f47-22fb5021d746" CreationDate="2021-11-18T13:24:08.357" UserId="7952" Comment="Added setup function example, and did a little code cleaning to make the examples a little more clear" Text="I took a few minutes and hacked this to life for you. The bugs were all pretty basic things like using floating point math where it should have been using interger math. All those little fractions add up so be careful there. I'm not sure what the alpha channel was up to, I removed that completely. The biggest issue was the large if statement was skipping some of the distance transforms which snowballed as the iters stepped. I'm not sure how pass is being computed I came up with my own version for that. The code below isn't perfectly fixed but it should be enough to get you up and running (hopefully).&#xD;&#xA;&#xD;&#xA;    vec4 step_jfa(vec2 pCoord,float pass)&#xD;&#xA;    {&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     pass = clamp( pass-1.0, 0.0, 15); &#xD;&#xA;     int offset= int(exp2(log2(img_width)  - pass));&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;     // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;     ivec2 nCoord= ivec2(pCoord+0.5);&#xD;&#xA;     for(float x = -1.; x &lt;= 1.; x++) &#xD;&#xA;     {&#xD;&#xA;       for(float y = -1.; y &lt;= 1.; y++) &#xD;&#xA;       {&#xD;&#xA;         ivec2 sCoord = nCoord + ivec2(x,y)*offset;&#xD;&#xA;&#xD;&#xA;         // if the loop item Q exists&#xD;&#xA;          vec4 neighbor=load0(sCoord);&#xD;&#xA;          &#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist)&#xD;&#xA;          {&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;&#xD;&#xA;           } &#xD;&#xA;         } &#xD;&#xA;       } &#xD;&#xA;       return rgba;        &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the load0 function:&#xD;&#xA;&#xD;&#xA;    vec4 load0(ivec2 p) {&#xD;&#xA;        vec2 uv = (vec2(p)-0.5) / textureSize.xy;&#xD;&#xA;        return texture(usampler, uv);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a jfaPrep function example, it should be pretty close to just plug and play.&#xD;&#xA;   &#xD;&#xA;    // pCoord is normalized uv coords&#xD;&#xA;    vec4 jfa_prep( vec2 pCoord ) &#xD;&#xA;    {&#xD;&#xA;        // don't use load0 here...just us the normalized uv coords&#xD;&#xA;        vec4 color = texture2D(original_image_sampler, pCoord);&#xD;&#xA;		&#xD;&#xA;        // decide if color is meaningful in some way&#xD;&#xA;        // such as...do any of the rgb channels contain a value?&#xD;&#xA;        float useful = color.r+color.g+color.b;&#xD;&#xA;        vec4 save_value = vec4(0.0);&#xD;&#xA;        if( useful &gt; 0.0) { // assumes image is on a black background (all zero's)&#xD;&#xA;           // save the unnormalized coords&#xD;&#xA;           // 8bit images work, but for debugging 16bit images are better&#xD;&#xA;           // such as r16g16b16a16&#xD;&#xA;           save_value = vec4( uv*imageSize, 0.0, 0.0);&#xD;&#xA;        } &#xD;&#xA;        return save_value;&#xD;&#xA;    } " ContentLicense="CC BY-SA 4.0" />
  <row Id="35516" PostHistoryTypeId="5" PostId="12344" RevisionGUID="ebe42640-3592-44ef-bb63-72dec81354b9" CreationDate="2021-11-18T13:36:34.217" UserId="7952" Comment="added 38 characters in body" Text="I took a few minutes and hacked this to life for you. The bugs were all pretty basic things like using floating point math where it should have been using interger math. All those little fractions add up so be careful there. I'm not sure what the alpha channel was up to, I removed that completely. The biggest issue was the large if statement was skipping some of the distance transforms which snowballed as the iters stepped. I'm not sure how pass is being computed I came up with my own version for that. The code below isn't perfectly fixed but it should be enough to get you up and running (hopefully).&#xD;&#xA;&#xD;&#xA;    vec4 step_jfa(vec2 pCoord,float pass)&#xD;&#xA;    {&#xD;&#xA;     //offset neighbors according to pass number&#xD;&#xA;     pass = clamp( pass-1.0, 0.0, 15); &#xD;&#xA;     int offset= int(exp2(log2(img_width)  - pass));&#xD;&#xA;&#xD;&#xA;     vec4 rgba=vec4(0.,0.,0.,0.);&#xD;&#xA;     float bestDist=900000.;&#xD;&#xA;&#xD;&#xA;     // loop through P and 8 surrounding neighbor pixels&#xD;&#xA;     ivec2 nCoord= ivec2(pCoord+0.5);&#xD;&#xA;     for(float x = -1.; x &lt;= 1.; x++) &#xD;&#xA;     {&#xD;&#xA;       for(float y = -1.; y &lt;= 1.; y++) &#xD;&#xA;       {&#xD;&#xA;         ivec2 sCoord = nCoord + ivec2(x,y)*offset;&#xD;&#xA;&#xD;&#xA;         // if the loop item Q exists&#xD;&#xA;          vec4 neighbor=load0(sCoord);&#xD;&#xA;          &#xD;&#xA;          // compute the distance of P to Q's saved origin&#xD;&#xA;          vec2 nOrigin=vec2(neighbor.rg);&#xD;&#xA;          float d=distance(pCoord,nOrigin);&#xD;&#xA;          if(d&lt;bestDist)&#xD;&#xA;          {&#xD;&#xA;            // if it's shorter than the currently saved distance record, overwrite the saved origin in P.&#xD;&#xA;            bestDist=d;&#xD;&#xA;            rgba.rg=nOrigin.rg;&#xD;&#xA;&#xD;&#xA;           } &#xD;&#xA;         } &#xD;&#xA;       } &#xD;&#xA;       return rgba;        &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the load0 function:&#xD;&#xA;&#xD;&#xA;    vec4 load0(ivec2 p) {&#xD;&#xA;        vec2 uv = (vec2(p)-0.5) / textureSize.xy;&#xD;&#xA;        return texture(usampler, uv);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a jfaPrep function example, it should be pretty close to just plug and play.&#xD;&#xA;   &#xD;&#xA;    // pCoord is normalized uv coords&#xD;&#xA;    vec4 jfa_prep( vec2 pCoord ) &#xD;&#xA;    {&#xD;&#xA;        // don't use load0 here...just us the normalized uv coords&#xD;&#xA;        vec4 color = texture2D(original_image_sampler, pCoord);&#xD;&#xA;		&#xD;&#xA;        // decide if color is meaningful in some way&#xD;&#xA;        // such as...do any of the rgb channels contain a value?&#xD;&#xA;        float useful = color.r+color.g+color.b;&#xD;&#xA;        vec4 save_value = vec4(0.0);&#xD;&#xA;        if( useful &gt; 0.0) { // assumes image is on a black background (all zero's)&#xD;&#xA;           // save the unnormalized coords&#xD;&#xA;           // 8bit images work, but for debugging 16bit images are better&#xD;&#xA;           // such as r16g16b16a16&#xD;&#xA;           save_value = vec4( uv*imageSize, 0.0, 0.0);&#xD;&#xA;        } &#xD;&#xA;&#xD;&#xA;        // Save value to jfa image&#xD;&#xA;        return save_value;&#xD;&#xA;    } " ContentLicense="CC BY-SA 4.0" />
  <row Id="35517" PostHistoryTypeId="50" PostId="12259" RevisionGUID="8f6d8a02-6e6d-4f27-8c25-74804095941f" CreationDate="2021-11-18T15:00:45.043" UserId="-1" />
  <row Id="35524" PostHistoryTypeId="2" PostId="12350" RevisionGUID="d50e8d2d-4c2b-4920-94b8-f68d19bed7fc" CreationDate="2021-11-19T20:19:34.920" UserId="17343" Text="We know that $(x, y, 1)$ is the homogenous coordinates of 2D points $(x, y).$ And $(x, y, 1)$ is 2 degree of freedom that's why we should said it to be 2D homogenous coordinates. But many websites saying it's 3D homogenous coordinates. &#xD;&#xA;&#xD;&#xA;My question what is right, $(x, y, 1)$ is 2D homogenous coordinates or 3D homogenous coordinates? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35526" PostHistoryTypeId="1" PostId="12350" RevisionGUID="d50e8d2d-4c2b-4920-94b8-f68d19bed7fc" CreationDate="2021-11-19T20:19:34.920" UserId="17343" Text="$(x, y, 1)$ is 2D homogenous coordinates or 3D homogenous coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35527" PostHistoryTypeId="3" PostId="12350" RevisionGUID="d50e8d2d-4c2b-4920-94b8-f68d19bed7fc" CreationDate="2021-11-19T20:19:34.920" UserId="17343" Text="|3d|geometry|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35528" PostHistoryTypeId="2" PostId="12351" RevisionGUID="bdbd2ded-9dab-4394-be8f-617b1485ab54" CreationDate="2021-11-19T22:05:27.147" UserId="16241" Text="I suppose in some respects it's a matter of perspective (no pun intended).  The ordered triple (x,y,w) is a point in a 3-dimensional [projective space][1] projective space that is mapped (projected) to a 2-dimensional point in the Euclidean plane: (x/w, y/w).  Given that, (x,y,1) would be point in that 3-dimensional space that maps to the point (x,y) in a 2-dimensional plane.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="35530" PostHistoryTypeId="5" PostId="12351" RevisionGUID="94278722-8ee0-4ba3-96e0-65e12c793f6d" CreationDate="2021-11-19T22:25:38.060" UserId="17343" Comment="Use dollar" Text="I suppose in some respects it's a matter of perspective (no pun intended).  The ordered triple $(x,y,w)$ is a point in a 3-dimensional [projective space][1]. Projective space that is mapped (projected) to a 2-dimensional point in the Euclidean plane: $(x/w, y/w).$  Given that, $(x,y,1)$ would be point in that 3-dimensional space that maps to the point $(x,y)$ in a 2-dimensional plane.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="35531" PostHistoryTypeId="24" PostId="12351" RevisionGUID="94278722-8ee0-4ba3-96e0-65e12c793f6d" CreationDate="2021-11-19T22:25:38.060" Comment="Proposed by 17556 approved by 16241 edit id of 571" ContentLicense="CC BY-SA 4.0" />
  <row Id="35532" PostHistoryTypeId="5" PostId="12351" RevisionGUID="16bc530f-e1ff-4229-b4ab-6b0ded9c9684" CreationDate="2021-11-19T23:05:18.070" UserId="17343" Comment="Use dollar" Text="I suppose in some respects it's a matter of perspective (no pun intended).  The ordered triple $(x,y,w)$ is a point in a 3-dimensional [projective space][1] that is mapped (projected) to a 2-dimensional point in the Euclidean plane: $(x/w, y/w).$  Given that, $(x,y,1)$ would be point in that 3-dimensional space that maps to the point $(x,y)$ in a 2-dimensional plane.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="35533" PostHistoryTypeId="24" PostId="12351" RevisionGUID="16bc530f-e1ff-4229-b4ab-6b0ded9c9684" CreationDate="2021-11-19T23:05:18.070" Comment="Proposed by 17556 approved by -1 edit id of 572" ContentLicense="CC BY-SA 4.0" />
  <row Id="35534" PostHistoryTypeId="5" PostId="12351" RevisionGUID="b4590607-7bdc-4a5b-8295-e0c686465c8f" CreationDate="2021-11-19T23:05:18.070" UserId="16241" Comment="Use dollar" Text="I suppose in some respects it's a matter of perspective (no pun intended).  The ordered triple $(x,y,w)$ is a point in a 3-dimensional [projective space][1] that is mapped (projected) to a 2-dimensional point in the Euclidean plane: $(x/w, y/w).$  Given that, $(x,y,1)$ would be 2-dimensional plane in that 3-dimensional space (or a specific point if $x$ and $y$ are fixed) that maps to $(x,y)$ in the standard Euclidean 2-dimensional plane.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_space" ContentLicense="CC BY-SA 4.0" />
  <row Id="35535" PostHistoryTypeId="2" PostId="12352" RevisionGUID="9a0e6623-5d6a-43bd-8c8a-ff2b7666000e" CreationDate="2021-11-20T17:36:05.483" UserId="10096" Text="If you have $(x,y,z) \in \mathbb{R}^3$ and you relate it to $(x/z, y/z) \in \mathbb{R}^2$ then you have interpreted $(x,y,z)$ as one possible representation of the 2D vector $(x/z, y/z)$ in homogeneous coordinates. The special case of $z=0$ corresponds to &quot;points at infinity&quot; or directions. If you have  $(x,y,z,w) \in \mathbb{R}^4$ and you relate it to $(x/w,y/w,z/w) \in \mathbb{R}^3$ then you have interpreted $(x,y,z,w)$ as one possible representation of the 3D vector $(x/w, y/w, z/w)$ in homogeneous coordinates. From this it becomes clear that to represent an $N$-dimensional point in homogeneous coordinates you need $N+1$ components.&#xD;&#xA;&#xD;&#xA;To clarify what I mean by one possible representation, consider the following example:&#xD;&#xA;&#xD;&#xA;$$(3,7) \equiv (3,7,1) \equiv (6,14,2),$$&#xD;&#xA;&#xD;&#xA;where the second and third vectors are different representations of the same 2D vector in homogeneous coordinates. In general, if you have a 2D vector $(X,Y)$, then for any $\lambda\ne 0$, the vector $(\lambda X, \lambda Y, \lambda)$ is a representation of $(X,Y)$ in homogeneous coordinates. So you really get an equivalence class of points in $N+1$ dimensions corresponding to a specific point in $N$ dimensions. Notably this equivalence class forms a line through $(0,0,0)$ and $(X,Y,1)$ in the $N+1$ dimensional space." ContentLicense="CC BY-SA 4.0" />
  <row Id="35540" PostHistoryTypeId="2" PostId="12353" RevisionGUID="74df2379-5e7f-463d-9510-6469e7fba93b" CreationDate="2021-11-21T18:15:30.000" UserId="17343" Text="We know that any 2D point $(x, y) $which represents as 3D homogeneous coordinates is of the form $(x, y, 1)$ which is the points of projective plane $P^2.$&#xD;&#xA;&#xD;&#xA;If I use the same concepts for 3D points  $(x, y, z)$ which represents as 4D homogeneous coordinates is of the form $(x, y, z, 1).$&#xD;&#xA;&#xD;&#xA;My question is $(x, y, z, 1)$ could be the points of 3D projective space? &#xD;&#xA;&#xD;&#xA;My second question is always homogenous coordinates are the points of projective space ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35542" PostHistoryTypeId="1" PostId="12353" RevisionGUID="74df2379-5e7f-463d-9510-6469e7fba93b" CreationDate="2021-11-21T18:15:30.000" UserId="17343" Text="3D homogenous coordinates versus 4D homogenous coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="35543" PostHistoryTypeId="3" PostId="12353" RevisionGUID="74df2379-5e7f-463d-9510-6469e7fba93b" CreationDate="2021-11-21T18:15:30.000" UserId="17343" Text="|3d|transformations|projections|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35550" PostHistoryTypeId="2" PostId="12355" RevisionGUID="fc486d3b-000a-4a05-8a11-5ca0477d18de" CreationDate="2021-11-21T20:26:18.300" UserId="2654" Text="So, a [projective plane][1] is a plane constructed such that parallel lines intersect at infinity. The plane plane defined by the equation (x, y, 1) is not projective. Just draw two parallel lines on that plane, and you will find that they never intersect, even under homogeneous transformations.&#xD;&#xA;&#xD;&#xA;Now, homogeneous transformations can *create* projective planes. But such a plane would not have a fixed homogeneous coordinate of 1, because the homogeneous transform doesn't change the other coordinates.&#xD;&#xA;&#xD;&#xA;That is, the plane (x, y) is not projective, so (x, y, 1) is likewise not projective.&#xD;&#xA;&#xD;&#xA;Since the rest of your question is based on the assumption that (x, y, 1) is projective, it's kind of irrelevant.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="35552" PostHistoryTypeId="5" PostId="12355" RevisionGUID="a9247d5b-f457-456b-8776-e5827ee70fc5" CreationDate="2021-11-21T20:32:43.377" UserId="2654" Comment="added 218 characters in body" Text="So, a [projective plane][1] is a plane constructed such that parallel lines intersect at infinity. The plane plane defined by the equation (x, y, 1) is not projective. Just draw two parallel lines on that plane, and you will find that they never intersect, even under homogeneous transformations.&#xD;&#xA;&#xD;&#xA;Now, homogeneous transformations can *create* projective planes. But such a plane would not have a fixed homogeneous coordinate of 1, because the homogeneous transform  with a coordinate of 1 doesn't change the other coordinates. A projective plane in homogeneous space needs to be able to represent points at infinity, and that only happens with a homogeneous coordinate of zero.&#xD;&#xA;&#xD;&#xA;So if a plane in homogeneous space does not pass through the 0 homogeneous coordinate, it *cannot* represent a projective plane.&#xD;&#xA;&#xD;&#xA;Since the rest of your question is based on the assumption that (x, y, 1) is projective, it's kind of irrelevant.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="35553" PostHistoryTypeId="5" PostId="12355" RevisionGUID="39ef13c2-53f0-4bc1-b7dd-8956a0f23b1c" CreationDate="2021-11-22T00:00:54.517" UserId="2654" Comment="deleted 6 characters in body" Text="So, a [projective plane][1] is a plane constructed such that parallel lines intersect at infinity. The plane defined by the equation (x, y, 1) is not projective. Just draw two parallel lines on that plane, and you will find that they never intersect, even under homogeneous transformations.&#xD;&#xA;&#xD;&#xA;Now, homogeneous transformations can *create* projective planes. But such a plane would not have a fixed homogeneous coordinate of 1, because the homogeneous transform  with a coordinate of 1 doesn't change the other coordinates. A projective plane in homogeneous space needs to be able to represent points at infinity, and that only happens with a homogeneous coordinate of zero.&#xD;&#xA;&#xD;&#xA;So if a plane in homogeneous space does not pass through the 0 homogeneous coordinate, it *cannot* represent a projective plane.&#xD;&#xA;&#xD;&#xA;Since the rest of your question is based on the assumption that (x, y, 1) is projective, it's kind of irrelevant.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Projective_plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="35554" PostHistoryTypeId="5" PostId="12353" RevisionGUID="fdd34241-7875-478f-836b-e08238a07015" CreationDate="2021-11-22T07:14:27.367" UserId="17343" Comment="added 168 characters in body" Text="We know that any 2D point $(x, y) $which represents as 3D homogeneous coordinates is of the form $(x, y, 1)$ which is the points of projective plane $P^2.$&#xD;&#xA;&#xD;&#xA;If I use the same concepts for 3D points  $(x, y, z)$ which represents as 4D homogeneous coordinates is of the form $(x, y, z, 1).$&#xD;&#xA;&#xD;&#xA;My question is $(x, y, z, 1)$ could be the points of 3D projective space? &#xD;&#xA;&#xD;&#xA;My second question is always homogenous coordinates are the points of projective space ? &#xD;&#xA;&#xD;&#xA;N. B. -- $P^2$ is projective plane which contains the points of $\mathbb{R^2}$ and ideal points, is of the form $(x, y, 0)$  which is called points at infinity. " ContentLicense="CC BY-SA 4.0" />
  <row Id="35555" PostHistoryTypeId="5" PostId="12353" RevisionGUID="6768884d-9711-46c0-ab82-80588e3b72c5" CreationDate="2021-11-22T07:19:35.510" UserId="17343" Comment="added 168 characters in body" Text="We know that any 2D point $(x, y) $which represents as 3D homogeneous coordinates is of the form $(x, y, 1)$ which is the points of projective plane $P^2.$&#xD;&#xA;&#xD;&#xA;If I use the same concepts for 3D points  $(x, y, z)$ which represents as 4D homogeneous coordinates is of the form $(x, y, z, 1).$&#xD;&#xA;&#xD;&#xA;My question is $(x, y, z, 1)$ could be the points of 3D projective space? &#xD;&#xA;&#xD;&#xA;My second question is always homogenous coordinates are the points of projective space ? &#xD;&#xA;&#xD;&#xA;N. B. -- $P^2$ is projective plane which contains the points of $\mathbb{R^2}$($\mathbb{R^2}$ points in $P^2$ can be represents as $(x, y, 1)$ ) and ideal points, is of the form $(x, y, 0)$  which is called points at infinity. " ContentLicense="CC BY-SA 4.0" />
  <row Id="35556" PostHistoryTypeId="2" PostId="12356" RevisionGUID="af73c719-f289-41ec-86b5-b87b9bc1b99b" CreationDate="2021-11-22T08:36:23.523" UserId="6968" Text="Yes, your understanding of $C1$ and $G1$, as shown in your drawings, is roughly correct: $C1$ means equal derivative vectors, and $G1$ means parallel derivative vectors.&#xD;&#xA;&#xD;&#xA;I say “roughly” because there are some subtleties when derivative vectors have zero length. But that’s a corner case that doesn’t have much impact on conceptual understanding.&#xD;&#xA;&#xD;&#xA;Regarding your last question: people who write books and papers and internet articles are, of course, free to make whatever definitions they want. But I think most people would define a curve joint to be $C1$ if **both** positions and first derivative vectors match across the join. In other words, most people would define $C1$ to include $C0$." ContentLicense="CC BY-SA 4.0" />
  <row Id="35558" PostHistoryTypeId="2" PostId="12357" RevisionGUID="2d20b9c8-9c16-44af-9090-1decf72fa4d3" CreationDate="2021-11-22T12:32:47.457" UserId="17570" Text="As a hobby project I am creating text rendering application that renders text directly from glyph outlines. Currently I am trying to find info on how to implement subpixel antialiasing. I know that vulkan supports MSAA but that samples the pixels from predefined locations and for subpixel antialiasing I assume I would have to specify sampling locations myself. &#xD;&#xA;&#xD;&#xA;Does anybody know a high level overview on how to implement subpixel antialiasing in vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35560" PostHistoryTypeId="1" PostId="12357" RevisionGUID="2d20b9c8-9c16-44af-9090-1decf72fa4d3" CreationDate="2021-11-22T12:32:47.457" UserId="17570" Text="How can I implement subpixel antialiasing in Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35561" PostHistoryTypeId="3" PostId="12357" RevisionGUID="2d20b9c8-9c16-44af-9090-1decf72fa4d3" CreationDate="2021-11-22T12:32:47.457" UserId="17570" Text="|vulkan|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35562" PostHistoryTypeId="4" PostId="12357" RevisionGUID="ae06cda9-3563-4dd1-86eb-a95f11e3d8b0" CreationDate="2021-11-22T16:34:51.087" UserId="2654" Comment="edited title" Text="How can I implement subpixel antialiasing for font rasterization in Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35563" PostHistoryTypeId="2" PostId="12358" RevisionGUID="de8a40ca-8db2-4c8b-8b5f-caf49f9b7081" CreationDate="2021-11-22T17:49:21.190" UserId="48" Text="I would rather draw the $G_1$ example something like this:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/BOL8Q.png&quot; width=&quot;500&quot;/&gt;&#xD;&#xA;&#xD;&#xA;This makes it clear that $t_2$ and $t_3$ are parallel, but have different lengths in general. (They both start at the same point, but $t_3$ is longer.) The way you have drawn it, they have the same length but slightly different directions—they don't quite look parallel.&#xD;&#xA;&#xD;&#xA;The standard definition of the [$C^k$ smoothness classes](https://en.wikipedia.org/wiki/Smoothness#Differentiability_classes) implies that any $C^k$ is contained in all the lower-numbered classes $C^{k-1}, C^{k-2}, \ldots, C^0$. So if a curve is in $C^k$ then it is also in all the lower classes down to $C^0$. The book you found is giving a bad example. Its notation also looks inconsistent/wrong from what you posted, so I would not trust that particular book overly much.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35565" PostHistoryTypeId="2" PostId="12359" RevisionGUID="d72c34c8-b355-4eec-9c54-baffc6d54bd2" CreationDate="2021-11-22T21:44:17.277" UserId="17343" Text="TEST #2: &#xD;&#xA;Surface S is completely behind the &#xD;&#xA;overlapping  surface relative to the viewing&#xD;&#xA;position.&#xD;&#xA;&#xD;&#xA;S1 is completely behind/inside the overlapping surface S2 [![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA; [1]: https://i.stack.imgur.com/5farG.jpg&#xD;&#xA;&#xD;&#xA;How to check these conditions? &#xD;&#xA;&#xD;&#xA;i) Set the plane equation of S2(Ax + By + Cz + D = 0), such that the surface S2 is towards the viewing position.&#xD;&#xA;&#xD;&#xA;ii) Substitute the coordinates of all vertices of Substitute the coordinates of all vertices of S1(x', y',z') into the plane equation of S2 and check for the sign.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; iii) If all vertices of S1 are inside S2  then S1 is behind S2. (Fig. 1). &#xD;&#xA;&#xD;&#xA; i. e. Ax' + By' + Cz' + D &lt; 0 ,x', y', z' are S1 vertices. &#xD;&#xA;&#xD;&#xA;iv) If all vertices of S1 are outside  S2  then S1 in front of S2. &#xD;&#xA;&#xD;&#xA;My question is why all vertices of one polygon(S1) substitute in the plane of another(S2) and value is less than 0 then say S1 is behind S2? I don't understand when value less than 0 by the vertices of one polygon then we say onevis behind another? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35567" PostHistoryTypeId="1" PostId="12359" RevisionGUID="d72c34c8-b355-4eec-9c54-baffc6d54bd2" CreationDate="2021-11-22T21:44:17.277" UserId="17343" Text="Painter's algorithm test 2 and test 3?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35568" PostHistoryTypeId="3" PostId="12359" RevisionGUID="d72c34c8-b355-4eec-9c54-baffc6d54bd2" CreationDate="2021-11-22T21:44:17.277" UserId="17343" Text="|shader|color|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35569" PostHistoryTypeId="5" PostId="12359" RevisionGUID="aaf8242a-af3d-4d28-befa-e91ba03ef7f3" CreationDate="2021-11-22T21:49:46.350" UserId="17343" Comment="added 3 characters in body" Text="TEST #2: &#xD;&#xA;Surface S is completely behind the &#xD;&#xA;overlapping  surface relative to the viewing&#xD;&#xA;position.&#xD;&#xA;&#xD;&#xA;S1 is completely behind/inside the overlapping surface S2 [![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA; [1]: https://i.stack.imgur.com/5farG.jpg&#xD;&#xA;&#xD;&#xA;How to check these conditions? &#xD;&#xA;&#xD;&#xA;i) Set the plane equation of S2(Ax + By + Cz + D = 0), such that the surface S2 is towards the viewing position.&#xD;&#xA;&#xD;&#xA;ii) Substitute the coordinates of all vertices of Substitute the coordinates of all vertices of S1(x', y',z') into the plane equation of S2 and check for the sign.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; iii) If all vertices of S1 are inside S2  then S1 is behind S2. (Fig. 1). &#xD;&#xA;&#xD;&#xA; i. e. Ax' + By' + Cz' + D &lt; 0 ,x', y', z' are S1 vertices. &#xD;&#xA;&#xD;&#xA;iv) If all vertices of S1 are outside  S2  then S1 in front of S2. &#xD;&#xA;&#xD;&#xA;My question is why all vertices of one polygon(S1) substitute in the plane of another(S2) and value is less than 0 then we say S1 is behind S2? I don't understand when value less than 0 by the vertices of one polygon then we say one is behind another? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35570" PostHistoryTypeId="5" PostId="12359" RevisionGUID="f7e4d0b9-bab3-4b97-a404-8ada92729f98" CreationDate="2021-11-22T22:43:03.567" UserId="17343" Comment="added 253 characters in body" Text="TEST #2: &#xD;&#xA;Surface S is completely behind the &#xD;&#xA;overlapping  surface relative to the viewing&#xD;&#xA;position.&#xD;&#xA;&#xD;&#xA;S1 is completely behind/inside the overlapping surface S2 [![enter image description here][1]][1]&#xD;&#xA; &#xD;&#xA; [1]: https://i.stack.imgur.com/5farG.jpg&#xD;&#xA;&#xD;&#xA;How to check these conditions? &#xD;&#xA;&#xD;&#xA;i) Set the plane equation of S2(Ax + By + Cz + D = 0), such that the surface S2 is towards the viewing position.&#xD;&#xA;&#xD;&#xA;ii) Substitute the coordinates of all vertices of Substitute the coordinates of all vertices of S1(x', y',z') into the plane equation of S2 and check for the sign.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; iii) If all vertices of S1 are inside S2  then S1 is behind S2. (Fig. 1). &#xD;&#xA;&#xD;&#xA; i. e. Ax' + By' + Cz' + D &lt; 0 ,x', y', z' are S1 vertices. &#xD;&#xA;&#xD;&#xA;iv) If all vertices of S1 are outside  S2  then S1 in front of S2. &#xD;&#xA;&#xD;&#xA;My first question is why all vertices of one polygon(S1) substitute in the plane of another(S2) and value is less than 0 then we say S1 is behind S2? I don't understand when value less than 0 by the vertices of one polygon then we say one is behind another? &#xD;&#xA;&#xD;&#xA;My second question  is when Test #2 is passed (i.e. S1 is completely behind/inside the overlapping surface S2) why we coloring S1 first before S2. There is no necessitates to S1 because S1 is totally obscured&#xD;&#xA; by S2. So why we colored S2?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35571" PostHistoryTypeId="33" PostId="12297" RevisionGUID="9430b651-6106-4dbc-8a21-160a4acf343c" CreationDate="2021-11-23T04:38:45.187" UserId="7462" Comment="71" />
  <row Id="35572" PostHistoryTypeId="2" PostId="12360" RevisionGUID="c9c9262c-656b-4b47-8cd2-f62a26646c8f" CreationDate="2021-11-23T13:06:41.943" UserId="7008" Text="There is this article about conversions in Direct3D: https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion&#xD;&#xA;&#xD;&#xA;I do not understand the part of conversion from higher to lower precision:&#xD;&#xA;&#xD;&#xA;&gt; Round-to-zero is used during conversion to another float format. If the target is an integer or fixed point format, round-to-nearest-even is used, unless the conversion is explicitly documented as using another rounding behavior, such as round-to-nearest for FLOAT to SNORM, FLOAT to UNORM or FLOAT to SRGB. &#xD;&#xA;&#xD;&#xA;What does round-to-zero mean, e.g. if I want to convert float -&gt; half?&#xD;&#xA;What does round-to-nearest-even mean, e.g. for half-&gt;unorm?&#xD;&#xA;&#xD;&#xA;Why is one round-to-nearest-even while another conversion is round-to-nearest?&#xD;&#xA;&#xD;&#xA;Phrased differently, how do these conversions work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35574" PostHistoryTypeId="1" PostId="12360" RevisionGUID="c9c9262c-656b-4b47-8cd2-f62a26646c8f" CreationDate="2021-11-23T13:06:41.943" UserId="7008" Text="How do (Direct3D) precision conversions for floats work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35575" PostHistoryTypeId="3" PostId="12360" RevisionGUID="c9c9262c-656b-4b47-8cd2-f62a26646c8f" CreationDate="2021-11-23T13:06:41.943" UserId="7008" Text="|direct3d|conversion|float|precision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35576" PostHistoryTypeId="2" PostId="12361" RevisionGUID="f45cc8b2-7ca9-4e14-9dbe-8b5681d6127c" CreationDate="2021-11-23T13:14:22.157" UserId="17576" Text="I'm writing a Monte Carlo path tracer, and I'm trying to allow any mesh to be an emitter, but I'm not entirely sure about the probabilities to use when I sample them.&#xD;&#xA;&#xD;&#xA;Right now, my algorithm for light sampling does the following:&#xD;&#xA;&#xD;&#xA; 1. Pick a light $L$ in the scene with some PDF $p_{\mathcal{L}}$.&#xD;&#xA; 2. Pick a random point $y$ on the mesh with uniform probability $p_{\mathcal{S}}(y) = \frac1{S_L}$, where $S_L$ is the total area of the mesh (computed summing over all the areas of all the triangles composing the mesh).&#xD;&#xA; 3. Cast a shadow ray from the current position $x$ to the sampled point $y$.&#xD;&#xA; 4. Check visibility.&#xD;&#xA; 5. Compute the PDF wrt solid angle (I need it wrt to solid angle for my integrator); the PDF wrt area mesure should now be just $p_A(y) = p_{\mathcal{L}}(L) \cdot p_{\mathcal{S}}(y)$ (the choice of light and of a point on the light are independent events), hence the actual PDF I need is $p_\omega(y) = \frac{\lvert y-x \rvert ^2}{\cos \theta_y} p_A(y)$.&#xD;&#xA; 6. Compute the light contribution to the current point as $\frac{E_L \cdot f_r \cdot \cos(\theta_x)}{p_\omega(y)}\cdot \mathrm{thr}$, where $\mathrm{thr}$ is the ray throughput, $E_L$ is the emissive value of the light $L$, $f_r = f_r(-\omega_{\mathrm{incoming}},\omega_{\mathrm{shadow}})$ is the BRDF of the surface containing $x$, $\omega_{\mathrm{incoming}}$ is the unit vector of the current ray direction, and $\omega_{\mathrm{shadow}} = \frac{y-x}{\lvert y-x \rvert ^2}$ is the direction of the shadow ray.&#xD;&#xA; 7. Use that light contribution for next event estimation; use $p_\omega$ as my PDF for the NEE when computing the weights for multiple importance sampling.&#xD;&#xA;&#xD;&#xA;I think this should account correctly for the fact that only the projected area of my mesh on the plane of the triangle $x$ lies on should contribute to the illumination of $x$, as the visibility check rules out all the triangles &quot;hidden&quot; by the geometry of the mesh, but I'd like to be sure that I'm not forgetting anything." ContentLicense="CC BY-SA 4.0" />
  <row Id="35578" PostHistoryTypeId="1" PostId="12361" RevisionGUID="f45cc8b2-7ca9-4e14-9dbe-8b5681d6127c" CreationDate="2021-11-23T13:14:22.157" UserId="17576" Text="PDF for sampling emissive meshes for NEE/MIS" ContentLicense="CC BY-SA 4.0" />
  <row Id="35579" PostHistoryTypeId="3" PostId="12361" RevisionGUID="f45cc8b2-7ca9-4e14-9dbe-8b5681d6127c" CreationDate="2021-11-23T13:14:22.157" UserId="17576" Text="|pathtracing|monte-carlo|importance-sampling|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35580" PostHistoryTypeId="2" PostId="12362" RevisionGUID="440e91a1-7944-4970-8f40-675360d57d71" CreationDate="2021-11-23T15:27:29.110" UserId="2654" Text="Rounding is all about what happens to the data in the higher precision format that don't exist in the lower precision one. For example, 0.7 cannot exactly be represented as an 8-bit unsigned, normalized integer, as 0.7 * 255 = 178.5. Which gets stored: 178 or 179?&#xD;&#xA;&#xD;&#xA;The same goes for any other precision. 16-bit floats can't store as many digits as a 32-bit float.&#xD;&#xA;&#xD;&#xA;So when doing rounding, you (conceptually) first convert the number with full precision, then you figure out which of the two valid values in the destination precision are available, and then you use an algorithm to pick one of these two.&#xD;&#xA;&#xD;&#xA;Round-to-nearest-even means that you round to the closest of the two values, but if you're halfway between them, you pick the *even number* of the two. So if we're converting 178.5 into a non-normalized integer, 178.5 is halfway between 178 and 179. But 178 is an even number, so we pick that instead of the traditional method of rounding up halves.&#xD;&#xA;&#xD;&#xA;Round-to-zero means that you always pick the number which is closest to zero, no matter how close you are to the other one.&#xD;&#xA;&#xD;&#xA;Round to zero is used for float-to-float conversions because that is what happens if you just drop the extra bits of the mantissa in the converted value. Because IEEE-754 floats are stored as a magnitude + sign-bit, the magnitude doesn't contain a sign value. So if you remove significant low precision bits, the resulting number is closer to zero.&#xD;&#xA;&#xD;&#xA;As to why there's a difference when converting to normalized and non-normalized integers, that's unclear." ContentLicense="CC BY-SA 4.0" />
  <row Id="35582" PostHistoryTypeId="2" PostId="12363" RevisionGUID="b1fafe5d-46d1-45e6-88ce-b5821ff977cf" CreationDate="2021-11-23T15:38:11.917" UserId="7952" Text="Edge flipping is considered a local operation of 1 edge between the points making up two triangles. (see the book polygon mesh processing for references as to why this is the case)&#xD;&#xA;&#xD;&#xA;The second example is vague since it involves 3 triangles.&#xD;&#xA;&#xD;&#xA;Given any *two* triangles that share a single edge, an edge flip is topologically valid only when the triangles form a convex quadrilateral. To check that two triangles from a convex quad: Compute the interior angle between all the connected edges, if any of the angles is greater then 180 degrees then the resulting polygon is concave.&#xD;&#xA;&#xD;&#xA;This will give some cases where the edge flip results in an edge collapse because the new edge coincides with an existing edge. To detect an edge collapse it is usually easiest to just calculate the area of the two resulting triangles and only accept edge flips that result in two triangles with some preset min area. (or recognize the edge collapse and remove the edge completely if the resulting triangle meets some other criteria)." ContentLicense="CC BY-SA 4.0" />
  <row Id="35584" PostHistoryTypeId="5" PostId="12297" RevisionGUID="5fa0c1d6-cb79-4ffb-904d-4633321d2cd7" CreationDate="2021-11-24T05:52:54.443" UserId="7462" Comment="added 917 characters in body" Text="I am trying to determine if and when flipping an edge is topologically valid.&#xD;&#xA;&#xD;&#xA;The current criterion I have is that it is only valid if there is no edge connecting the opposite vertices of the edge.&#xD;&#xA;&#xD;&#xA;I.e. consider these 2 drawings where the first allows for a valid edge flip but the second does not.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To clarify what we mean by topological validity. Topology does not care about geometric ifnormation such as angles, teh reason the second triangle does not allow for edge flips is, pick any edge between the face center and the other vertices a flip would create a set of 2 vertices with 2 edges in between them, this is wrong.&#xD;&#xA;&#xD;&#xA;A possibly non inclusive set of restrictions on topological requirements of a half edge mesh:&#xD;&#xA;&#xD;&#xA;All vertices are connected by either exactly 0 or exactly 1 edge (an edge flip can accidentally invalidate this). &#xD;&#xA;&#xD;&#xA;All edges are contained in a face (the boundary face counts as a face).&#xD;&#xA;&#xD;&#xA;There are no &quot;butterfly holes&quot;, (2 triangles that share a vertex but no edges and no other triangles containing that vertex).&#xD;&#xA;&#xD;&#xA;2 triangles cannot share more than one edge between them.&#xD;&#xA;&#xD;&#xA;etc...&#xD;&#xA;&#xD;&#xA;The above are all examples of topological requirements, this is what we are trying to preserve.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nKy3p.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35585" PostHistoryTypeId="2" PostId="12364" RevisionGUID="2e7edc7a-60e6-4883-b310-38f46d413a0d" CreationDate="2021-11-24T06:29:10.250" UserId="10096" Text="Let the edge to be flipped be made up of $v_l, \, v_r$. This edge needs to be part of 2 triangles (cannot be a boundary edge). Let the remaining vertices of the two triangles be $v_t, \, v_b$. Now consider the triangles adjacent to the edges $e_1 = v_tv_l$, $e_2 = v_lv_b$, $e_3= v_bv_r$, $e_4=v_rv_t$. If the triangle adjacent to $e_1$ is the same as the one to $e_2$ disallow the flip (except for the boundary face). Similarly for $e_3$ and $e_4$. This is consistent with your criterion of the vertices not gaining an extra edge. I have assumed that your triangulation is manifold in order to guarantee that an edge is shared by at most 2 triangles." ContentLicense="CC BY-SA 4.0" />
  <row Id="35587" PostHistoryTypeId="2" PostId="12365" RevisionGUID="85eabbe7-d27f-49b0-b53b-f36effc4fb1b" CreationDate="2021-11-24T08:29:39.913" UserId="17479" Text="Been trying to follow a shader from **A Comparative Study of Screen-Space Ambient Occlusion Methods** &#xD;&#xA;&#xD;&#xA;&gt; http://frederikaalund.com/wp-content/uploads/2013/05/A-Comparative-Study-of-Screen-Space-Ambient-Occlusion-Methods.pdf&#xD;&#xA;&#xD;&#xA; (shader in appendix) specifically the Alchemy AO implementation. I am getting some odd results, can't seem to figure out what might be causing it. I feel it could do with the depth buffer since I was not sure what &quot;ndc_linear_depth&quot; meant. I was told to implement a &#xD;&#xA;&#xD;&#xA;&gt; normalised device coordinate linear depth &#xD;&#xA;&#xD;&#xA;Which confused me since Vulkan depth is already 0-1 and NDC is -1:1 which would produce inaccuracy for the depth? Regardless, I implemented what I thought would be correct but that did not seem to produce the right result for Alchemy AO. I was curious to know if the depth buffer is what was causing the issue. Would appreciate any insight. I am using Vulkan and GLSL&#xD;&#xA;&#xD;&#xA;My shader: &#xD;&#xA; &#xD;&#xA;    layout(binding = 3) uniform sampler2D texNoise;&#xD;&#xA;    layout(binding = 6) uniform sampler2D depthMap;&#xD;&#xA;    layout(binding = 2) uniform sampler2D gNormal;&#xD;&#xA;    &#xD;&#xA;    layout(location = 1) in vec2 uvCoords;&#xD;&#xA;    &#xD;&#xA;    layout(binding = 5) uniform UniformBufferObject {&#xD;&#xA;        mat4 model;&#xD;&#xA;        mat4 view;&#xD;&#xA;        mat4 proj;&#xD;&#xA;        float time;&#xD;&#xA;    }camera;&#xD;&#xA;    &#xD;&#xA;    layout(binding = 4) uniform KernelSample {&#xD;&#xA;    	vec3 samples[64];&#xD;&#xA;    	mat4 projection;&#xD;&#xA;    	vec4 camera_eye;&#xD;&#xA;    	vec4 camera_center;&#xD;&#xA;    	float z_far;&#xD;&#xA;    }kernelsamples;&#xD;&#xA;    &#xD;&#xA;    layout(location = 0) out vec4 outColor;&#xD;&#xA;    &#xD;&#xA;    vec4 ambient_occlusion;&#xD;&#xA;    &#xD;&#xA;    const vec2 window = vec2(1920.0, 1080.0);&#xD;&#xA;    &#xD;&#xA;    float near = 0.1;&#xD;&#xA;    float zfar = 1000;&#xD;&#xA;    &#xD;&#xA;    float tc_depth(in vec2 tc)&#xD;&#xA;    {&#xD;&#xA;    	return texture(depthMap, vec2(1.0 - uvCoords.x, uvCoords.y)).x;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float LinearizeDepth(in vec2 tc) {&#xD;&#xA;    	float buffer_z = texture(depthMap, tc).x;&#xD;&#xA;    	return (2.0 * near) / (zfar + near - buffer_z * (near - zfar));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float ndcDepth(in vec2 tc) {&#xD;&#xA;    	float depth = texture(depthMap, tc).x;&#xD;&#xA;    &#xD;&#xA;    	return camera.proj[3][2] / (camera.proj[2][2] + depth);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float ec_depth(in vec2 tc)&#xD;&#xA;    {&#xD;&#xA;    	float buffer_z = texture(depthMap, tc).x;&#xD;&#xA;    	return camera.proj[3][2] / (-2.0 * buffer_z + 1.0 - camera.proj[2][2]);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() &#xD;&#xA;    {&#xD;&#xA;    	vec2 tc_depths = gl_FragCoord.xy / window;&#xD;&#xA;    	&#xD;&#xA;    	// Normals&#xD;&#xA;    	vec3 normals = normalize(texture(gNormal, tc_depths).rgb * 2.0 - 1.0);&#xD;&#xA;    &#xD;&#xA;    	// normals in world coordinates&#xD;&#xA;    	vec3 wc_normal = normalize(transpose(mat3(camera.view)) * normals);&#xD;&#xA;    &#xD;&#xA;    	float ndc_linear_depth = ndcDepth(tc_depths);&#xD;&#xA;    &#xD;&#xA;    	// camera_center(target) - camera_eye = world coordinate camera ray direction&#xD;&#xA;    	vec3 wc_position_current_frag = kernelsamples.camera_eye.xyz + normalize((kernelsamples.camera_center.xyz - kernelsamples.camera_eye.xyz)) * ndc_linear_depth;&#xD;&#xA;    &#xD;&#xA;    	ambient_occlusion.a = 0.0; &#xD;&#xA;    &#xD;&#xA;    	const int base_samples = 0;&#xD;&#xA;    	const int min_samples = 64;&#xD;&#xA;    	const float radius = 10.0;&#xD;&#xA;    	const float projection_factor = 0.75;&#xD;&#xA;    	const float bias = 1.000;&#xD;&#xA;    	const float sigma = 2.0;&#xD;&#xA;    	const float epsilon = 0.0001;&#xD;&#xA;    &#xD;&#xA;    	int samples = max(int(base_samples / (1.0 + base_samples * ndc_linear_depth)), min_samples);&#xD;&#xA;    &#xD;&#xA;    	mat4 inverse_view_projection_matrix = inverse(camera.view);&#xD;&#xA;    	float projected_radius = radius * projection_factor / ndcDepth(tc_depths);&#xD;&#xA;    &#xD;&#xA;    	vec2 inverted_random_texture_size = 1.0 / vec2(textureSize(texNoise, 0));&#xD;&#xA;    	vec2 tc_random_texture = gl_FragCoord.xy * inverted_random_texture_size;&#xD;&#xA;    &#xD;&#xA;    	// scale texture back to [-1: 1] range&#xD;&#xA;    	vec3 random_direction = texture(texNoise, tc_random_texture).xyz;&#xD;&#xA;    	random_direction = normalize(random_direction * 2.0 - 1.0);&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; samples; i++) &#xD;&#xA;    	{&#xD;&#xA;    		// select random point&#xD;&#xA;    		vec2 sample_random_direction = texture(texNoise,  vec2(float(i) * inverted_random_texture_size.x, float(i / textureSize(texNoise, 0).x) * inverted_random_texture_size.y)).xy;&#xD;&#xA;    		sample_random_direction = sample_random_direction * 2.0 - 1.0; //to screen coordinates&#xD;&#xA;    &#xD;&#xA;    		//read position and depth for sample&#xD;&#xA;    		vec3 tc_sample;&#xD;&#xA;    		tc_sample.xy = tc_depths + sample_random_direction * projected_radius;&#xD;&#xA;    		tc_sample.z = tc_depth(tc_sample.xy);&#xD;&#xA;    &#xD;&#xA;    		vec3 ndc_sample = tc_sample * 2.0 - 1.0;&#xD;&#xA;    		vec4 temporary = inverse_view_projection_matrix * vec4(ndc_sample, 1.0);&#xD;&#xA;    		vec3 wc_sample = temporary.xyz / temporary.w;&#xD;&#xA;    &#xD;&#xA;    		vec3 v = wc_sample - wc_position_current_frag;&#xD;&#xA;    &#xD;&#xA;    		ambient_occlusion.a += max(0.0, dot(v, wc_normal) - bias) / (dot(v, v) + epsilon);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	ambient_occlusion.a = max(0.0, 1.0 - 2.0 * sigma / float(samples) * ambient_occlusion.a);&#xD;&#xA;    &#xD;&#xA;    	outColor = vec4(ambient_occlusion.a, ambient_occlusion.a, ambient_occlusion.a, 1.0); &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;## Result from my shader ##&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;## Original shader (also in appendix) ##&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/erEza.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/G1WvY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35589" PostHistoryTypeId="1" PostId="12365" RevisionGUID="85eabbe7-d27f-49b0-b53b-f36effc4fb1b" CreationDate="2021-11-24T08:29:39.913" UserId="17479" Text="Ambient occlusion implementation depth buffer causing issue?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35590" PostHistoryTypeId="3" PostId="12365" RevisionGUID="85eabbe7-d27f-49b0-b53b-f36effc4fb1b" CreationDate="2021-11-24T08:29:39.913" UserId="17479" Text="|shader|glsl|vulkan|ambient-occlusion|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35591" PostHistoryTypeId="6" PostId="12365" RevisionGUID="6caa8f60-d4c3-4989-84f3-da82b52bc0e9" CreationDate="2021-11-24T08:57:26.210" UserId="17479" Comment="edited tags" Text="|shader|glsl|lighting|ambient-occlusion|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35592" PostHistoryTypeId="4" PostId="12365" RevisionGUID="6caa8f60-d4c3-4989-84f3-da82b52bc0e9" CreationDate="2021-11-24T08:57:26.210" UserId="17479" Comment="edited tags" Text="Ambient occlusion depth buffer normalization" ContentLicense="CC BY-SA 4.0" />
  <row Id="35593" PostHistoryTypeId="5" PostId="12297" RevisionGUID="6868b923-0775-448c-b2a3-58c7871a63e2" CreationDate="2021-11-24T10:59:40.460" UserId="7952" Comment="spelling corrections" Text="I am trying to determine if and when flipping an edge is topologically valid.&#xD;&#xA;&#xD;&#xA;The current criterion I have is that it is only valid if there is no edge connecting the opposite vertices of the edge.&#xD;&#xA;&#xD;&#xA;I.e. consider these 2 drawings where the first allows for a valid edge flip but the second does not.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;To clarify what we mean by topological validity. Topology does not care about geometric information such as angles, the reason the second triangle does not allow for edge flips is, pick any edge between the face center and the other vertices a flip would create a set of 2 vertices with 2 edges in between them, this is wrong.&#xD;&#xA;&#xD;&#xA;A possibly non inclusive set of restrictions on topological requirements of a half edge mesh:&#xD;&#xA;&#xD;&#xA;All vertices are connected by either exactly 0 or exactly 1 edge (an edge flip can accidentally invalidate this). &#xD;&#xA;&#xD;&#xA;All edges are contained in a face (the boundary face counts as a face).&#xD;&#xA;&#xD;&#xA;There are no &quot;butterfly holes&quot;, (2 triangles that share a vertex but no edges and no other triangles containing that vertex).&#xD;&#xA;&#xD;&#xA;2 triangles cannot share more than one edge between them.&#xD;&#xA;&#xD;&#xA;etc...&#xD;&#xA;&#xD;&#xA;The above are all examples of topological requirements, this is what we are trying to preserve.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nKy3p.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35594" PostHistoryTypeId="5" PostId="12363" RevisionGUID="422584db-f77d-45b3-bc69-87409262756e" CreationDate="2021-11-24T11:31:18.143" UserId="7952" Comment="added 426 characters in body" Text="Edge flipping is considered a local operation of 1 edge between the points making up two triangles. (see the book polygon mesh processing for references as to why this is the case)&#xD;&#xA;&#xD;&#xA;The second example is vague since it involves 3 triangles.&#xD;&#xA;&#xD;&#xA;Given any *two* triangles that share a single edge, an edge flip is topologically valid only when the triangles form a convex quadrilateral. To check that two triangles from a convex quad: Compute the interior angle between all the connected edges, if any of the angles is greater then 180 degrees then the resulting polygon is concave.&#xD;&#xA;&#xD;&#xA;This will give some cases where the edge flip results in an edge collapse because the new edge coincides with an existing edge. To detect an edge collapse it is usually easiest to just calculate the area of the two resulting triangles and only accept edge flips that result in two triangles with some preset min area.&#xD;&#xA;&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;In other words, if an interior edge is flipped on a concave polygon formed by two triangles sharing a single edge then the flipped edge will cross at least one of the other edges. So flip the edge and check that it doesn't cross another edge by any means you choose.&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;A better solution is to remesh the entire topology such that any valid flip is legal.(again flips are only valid on edges between two triangles, and it must always be a local operation). There are many excellent algorithms for this operation." ContentLicense="CC BY-SA 4.0" />
  <row Id="35595" PostHistoryTypeId="5" PostId="12363" RevisionGUID="1a204955-8520-48e6-8c12-43184f01af6d" CreationDate="2021-11-24T11:36:20.507" UserId="7952" Comment="added 426 characters in body" Text="Edge flipping is considered a local operation of 1 edge between the points making up two triangles. (see the book polygon mesh processing for references as to why this is the case)&#xD;&#xA;&#xD;&#xA;The second example is vague since it involves 3 triangles.&#xD;&#xA;&#xD;&#xA;Given any *two* triangles that share a single edge, an edge flip is topologically valid only when the triangles form a convex quadrilateral. To check that two triangles from a convex quad: Compute the interior angle between all the connected edges, if any of the angles is greater then 180 degrees then the resulting polygon is concave.&#xD;&#xA;&#xD;&#xA;This will give some cases where the edge flip results in an edge collapse because the new edge coincides with an existing edge. To detect an edge collapse it is usually easiest to just calculate the area of the two resulting triangles and only accept edge flips that result in two triangles with some preset min area.&#xD;&#xA;&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;In other words, if an interior edge is flipped on a concave polygon formed by two triangles sharing a single edge then the flipped edge will cross at least one of the other edges. So flip the edge and check that it doesn't cross another edge by any means you choose. (only the edges of the two triangles that share a common edge need be checked)&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;A better solution is to remesh the entire topology such that any valid flip is legal.(again flips are only valid on edges between two triangles, and it must always be a local operation). There are many excellent algorithms for this operation, and it creates a new mesh that can be processed through heavily pipelined tool sets." ContentLicense="CC BY-SA 4.0" />
  <row Id="35596" PostHistoryTypeId="5" PostId="12363" RevisionGUID="d5ddcae2-b161-4f7d-b2fa-6865d7428ca4" CreationDate="2021-11-24T11:50:03.190" UserId="7952" Comment="added 175 characters in body" Text="Edge flipping is considered a local operation of 1 edge between the points making up two triangles. (see the book polygon mesh processing for references as to why this is the case)&#xD;&#xA;&#xD;&#xA;The second example is vague since it involves 3 triangles.&#xD;&#xA;&#xD;&#xA;Given any *two* triangles that share a single edge, an edge flip is topologically valid only when the triangles form a convex quadrilateral. To check that two triangles from a convex quad: Compute the interior angle between all the connected edges, if any of the angles is greater then 180 degrees then the resulting polygon is concave.&#xD;&#xA;&#xD;&#xA;This will give some cases where the edge flip results in an edge collapse because the new edge coincides with an existing edge. To detect an edge collapse it is usually easiest to just calculate the area of the two resulting triangles and only accept edge flips that result in two triangles with some preset min area.&#xD;&#xA;&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;In other words, if an interior edge is flipped on a concave polygon formed by two triangles sharing a single edge then the flipped edge will cross at least one of the other edges. Meaning that some portion of the flipped edge will be exterior to the original quad. Meaning that the edge will lie on a different side of at least one of the original edges. So flip the edge and check that it doesn't cross another edge by any means you choose. (only the edges of the two triangles that share a common edge need be checked)&#xD;&#xA;&#xD;&#xA;---------&#xD;&#xA;&#xD;&#xA;A better solution is to remesh the entire topology such that any valid flip is legal.(again flips are only valid on edges between two triangles, and it must always be a local operation). There are many excellent algorithms for this operation, and it creates a new mesh that can be processed through heavily pipelined tool sets." ContentLicense="CC BY-SA 4.0" />
  <row Id="35597" PostHistoryTypeId="5" PostId="12361" RevisionGUID="01ab939b-4b80-481b-a5d8-326e2dec793c" CreationDate="2021-11-24T13:14:40.173" UserId="17576" Comment="added 172 characters in body" Text="I'm writing a Monte Carlo path tracer, and I'm trying to allow any mesh to be an emitter, but I'm not entirely sure about the probabilities to use when I sample them.&#xD;&#xA;&#xD;&#xA;Right now, my algorithm for light sampling does the following:&#xD;&#xA;&#xD;&#xA; 1. Pick a light $L$ in the scene with some PDF $p_{\mathcal{L}}$.&#xD;&#xA; 2. Pick a random point $y$ on the mesh with uniform probability $p_{\mathcal{S}}(y) = \frac1{S_L}$, where $S_L$ is the total area of the mesh (computed summing over all the areas of all the triangles composing the mesh).&#xD;&#xA; 3. Cast a shadow ray from the current position $x$ to the sampled point $y$.&#xD;&#xA; 4. Check visibility.&#xD;&#xA; 5. Compute the PDF wrt solid angle (I need it wrt to solid angle for my integrator); the PDF wrt area mesure should now be just $p_A(y) = p_{\mathcal{L}}(L) \cdot p_{\mathcal{S}}(y)$ (the choice of light and of a point on the light are independent events), hence the actual PDF I need is $p_\omega(y) = \frac{\cos \theta_y}{\lvert y-x \rvert ^2} p_A(y)$.&#xD;&#xA; 6. Compute the light contribution to the current point as $\frac{E_L \cdot f_r \cdot \cos(\theta_x)}{p_\omega(y)}\cdot \mathrm{thr}$, where $\mathrm{thr}$ is the ray throughput, $E_L$ is the emissive value of the light $L$, $f_r = f_r(-\omega_{\mathrm{incoming}},\omega_{\mathrm{shadow}})$ is the BRDF of the surface containing $x$, $\omega_{\mathrm{incoming}}$ is the unit vector of the current ray direction, and $\omega_{\mathrm{shadow}} = \frac{y-x}{\lvert y-x \rvert ^2}$ is the direction of the shadow ray.&#xD;&#xA; 7. Use that light contribution for next event estimation; use $p_\omega$ as my PDF for the NEE when computing the weights for multiple importance sampling.&#xD;&#xA;&#xD;&#xA;I think this should account correctly for the fact that only the projected area of my mesh on the plane of the triangle $x$ lies on should contribute to the illumination of $x$, as the visibility check rules out all the triangles &quot;hidden&quot; by the geometry of the mesh, but I'd like to be sure that I'm not forgetting anything.&#xD;&#xA;&#xD;&#xA;EDIT: In particular, the thing that makes me a bit unsure is using the entire surface area of the mesh, even though the part facing the point $x$ might be much smaller." ContentLicense="CC BY-SA 4.0" />
  <row Id="35598" PostHistoryTypeId="50" PostId="7804" RevisionGUID="33b01f6f-8635-42a7-9761-2ec74bd7fc29" CreationDate="2021-11-24T19:02:30.193" UserId="-1" />
  <row Id="35600" PostHistoryTypeId="5" PostId="12350" RevisionGUID="1f756047-aab9-4127-8453-29a9acfedbfc" CreationDate="2021-11-25T08:02:54.920" UserId="13095" Comment="Fix some grammar and spelling" Text="We know that $(x, y, 1)$ are the homogenous coordinates of a 2D point $(x, y)$. $(x, y, 1)$ has 2 degrees of freedom. That's why we should call it 2D homogenous coordinates. But many websites say it's 3D homogenous coordinates. &#xD;&#xA;&#xD;&#xA;My question is: What is right? $(x, y, 1)$ are 2D homogenous coordinates or 3D homogenous coordinates? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35602" PostHistoryTypeId="2" PostId="12366" RevisionGUID="89002b8a-cb23-4270-9640-655ace7e1297" CreationDate="2021-11-25T14:03:06.630" UserId="17593" Text="Recently, I want to use an roughness map to get better rendering result.&#xD;&#xA;While, most information in the internet are about the operation of 3D software.&#xD;&#xA;So, how can I geneate an roughness map of my owen 3D mesh.&#xD;&#xA;Thanks very much." ContentLicense="CC BY-SA 4.0" />
  <row Id="35604" PostHistoryTypeId="1" PostId="12366" RevisionGUID="89002b8a-cb23-4270-9640-655ace7e1297" CreationDate="2021-11-25T14:03:06.630" UserId="17593" Text="how can I compute a roughness map without any 3D softwares?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35605" PostHistoryTypeId="3" PostId="12366" RevisionGUID="89002b8a-cb23-4270-9640-655ace7e1297" CreationDate="2021-11-25T14:03:06.630" UserId="17593" Text="|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35606" PostHistoryTypeId="50" PostId="9626" RevisionGUID="6ef16b97-7cfb-474b-80f6-92050787d6bb" CreationDate="2021-11-25T14:04:25.263" UserId="-1" />
  <row Id="35607" PostHistoryTypeId="50" PostId="9307" RevisionGUID="55aac8ab-1868-4e79-84ba-4722b3306839" CreationDate="2021-11-25T20:06:30.680" UserId="-1" />
  <row Id="35608" PostHistoryTypeId="50" PostId="10535" RevisionGUID="8eafc637-5887-4dd1-9b73-28f54dde747e" CreationDate="2021-11-26T04:04:45.440" UserId="-1" />
  <row Id="35609" PostHistoryTypeId="2" PostId="12367" RevisionGUID="54981b69-2ae8-4b1a-ae08-ca6a89a370d7" CreationDate="2021-11-26T09:04:37.200" UserId="13095" Text="&gt; I feel it could do with the depth buffer since I was not sure what &quot;ndc_linear_depth&quot; meant. I was told to implement a&#xD;&#xA;&gt; &gt;normalised device coordinate linear depth&#xD;&#xA;&gt;&#xD;&#xA;&gt; Which confused me since Vulkan depth is already 0-1 and NDC is -1:1 which would produce inaccuracy for the depth?&#xD;&#xA;&#xD;&#xA;NDC (normalized device coordinates) is just a coordinate system with the value range -1 to 1 on all its axis. If you have your values in the range 0 to 1, the simple transformation would be:&#xD;&#xA;&#xD;&#xA;$$2 \cdot \mathbf{v} - 1$$&#xD;&#xA;&#xD;&#xA;where $\mathbf{v}$ is your coordinate vector or depth value. It basically &quot;just doubles the distances&quot; between your depth values but the relations remain the same. So if one pixel is 4 times closer to the camera plane than another one in your original coordinate system, it will still be 4 times closer after the transformation. Since we are using floating-point numbers here, the only inaccuracies you should get are the usual floating-point math errors (most likely negligible). However, if you are storing values only in the range 0 to 1 in a buffer that supports values from -1 to 1, you are using just half of its value range and effectively reducing your available precision by 50%.&#xD;&#xA;&#xD;&#xA;Now let's get to the &quot;linear&quot; part. In a linear depth buffer, the difference between two depth values always translates to the same distance. So if your NDC depth buffer covers an area of $10$ meters, the difference between the values $-0.3$ and $-0.1$ would be $1$ meter as it would be for the values $0.8$ and $1.0$.&#xD;&#xA;&#xD;&#xA;Now consider, that your depth buffer has a limited set of values determined by the number of available bits. The problem with a linear depth buffer for rendering purposes is that you &quot;waste bits&quot; on far-away objects. You can not really tell if an object $1$km away is closer by $1$cm than another object. If both objects are just a meter away, it is more obvious. &#xD;&#xA;The closer object gets the smaller is the noticeable distance difference. However, at some point, you hit the minimal representable distance difference of your depth buffer. This leads to undesired effects like an object that is farther away being rendered in front of a closer one just because they share the same depth buffer value due to the limited number of values.&#xD;&#xA;&#xD;&#xA;To fix this problem, one can apply a non-linear function to the depth values so that you can distinguish much smaller distances for closer objects than for far-away objects. In this non-linear depth buffer, assuming your camera resides at the depth value $-1$, the covered distance between the values $-0.3$ and $-0.1$ might be just a few meters while the distance between the values $0.8$ and $1.0$ is now more than a kilometer. A better explanation of this can be found [here (see section Depth value precision)](https://learnopengl.com/Advanced-OpenGL/Depth-testing)&#xD;&#xA;&#xD;&#xA;So to come back to your problem: If you use non-NDC values, non-linear values, or both in an equation that expects linear NDC values, you will most likely get the wrong results. This might be what causes your &quot;odd results&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35611" PostHistoryTypeId="2" PostId="12368" RevisionGUID="24af2b1c-ecd2-472b-8623-ee2c6e3e185a" CreationDate="2021-11-26T12:04:27.400" UserId="17599" Text="I have been going through scratchapixel.com lessons. Unfortunately some of the lessons are incomplete and one of the missing chapters is titled &quot;Jacobi Transformation and Eigenvalue Algorithm&quot;. Can someone explain its usages in CG (not physics) as well as give an example or two?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35613" PostHistoryTypeId="1" PostId="12368" RevisionGUID="24af2b1c-ecd2-472b-8623-ee2c6e3e185a" CreationDate="2021-11-26T12:04:27.400" UserId="17599" Text="Usage of Jacobi transformation in computer graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="35614" PostHistoryTypeId="3" PostId="12368" RevisionGUID="24af2b1c-ecd2-472b-8623-ee2c6e3e185a" CreationDate="2021-11-26T12:04:27.400" UserId="17599" Text="|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35615" PostHistoryTypeId="2" PostId="12369" RevisionGUID="4e7771f4-986d-4c48-890e-567b7d992fe1" CreationDate="2021-11-26T21:38:25.697" UserId="7952" Text="Most of the major photo/image editing software programs can be used to generate a roughness map. It is usually best just to search google with something like, &quot;How to create a roughness map using xyz.&quot; Where xyz is photoshop or some other popular image editor. If you can narrow you question down a little with the software you have, or the images you have and how they are generated then it makes it easier to give a specific answer to your question." ContentLicense="CC BY-SA 4.0" />
  <row Id="35618" PostHistoryTypeId="2" PostId="12370" RevisionGUID="7d6c98da-7373-448e-b1ea-632783d32003" CreationDate="2021-11-27T01:27:04.493" UserId="17602" Text="I'm trying to render a dodecahedron triangle mesh and the triangles seem flipped or mirrored somehow. The first picture is what I should be getting, the second picture is what I'm getting and the last picture is if I only render the first triangle face of the mesh from the obj file. I'm attempting to use Barycentric coordinates and Cramer's rule to find the determinant and solve for beta, gamma, and t (the depth of the ray at the point of intersection). I think the mistake is in how I read in the triangle's vertices or how I build the other functions and compute the determinant.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5QOXw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ttve3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7bryW.png&#xD;&#xA;&#xD;&#xA;This function is called during a loop of all the objects in a scene and compares the closest hit point found in the mesh to a global HitRecord (h) that was passed in and has a h.t parameter that has the depth (t) of the ray hit point of any other objects checked before the current mesh.&#xD;&#xA;&#xD;&#xA;    bool Mesh::hit(Ray r, HitRecord &amp; h){&#xD;&#xA;	double closest_sofar = 0.0;&#xD;&#xA;	vec3 normal;&#xD;&#xA;	size_t size = m_faces.size();&#xD;&#xA;	for(int i = 0; i &lt; size; ++i){&#xD;&#xA;		Triangle t = m_faces[i];&#xD;&#xA;		glm::vec3 a = m_vertices[t.v1];&#xD;&#xA;		glm::vec3 b = m_vertices[t.v2];&#xD;&#xA;		glm::vec3 c = m_vertices[t.v3];&#xD;&#xA;&#xD;&#xA;		// course notes&#xD;&#xA;		glm::vec3 answer = a - r.r_origin;&#xD;&#xA;		vec3 A = a-b;&#xD;&#xA;		vec3 B = a-c;&#xD;&#xA;		vec3 D = r.r_direction;&#xD;&#xA;&#xD;&#xA;		double det = dot(cross(A, B), D);&#xD;&#xA;		if(det == 0.0 || det == -0.0) {	continue; }&#xD;&#xA;&#xD;&#xA;		double beta = dot(cross(answer, B), D) / det;&#xD;&#xA;		double gamma = dot(cross(A, answer), D) / det;&#xD;&#xA;		double closest = dot(cross(A, B), answer) / det;&#xD;&#xA;&#xD;&#xA;		if((1.0 &gt; beta &gt; 0.0) &amp;&amp;&#xD;&#xA;			 (1.0 &gt; gamma &gt; 0.0) &amp;&amp;&#xD;&#xA;			 (1.0 &gt; 1.0 - beta - gamma &gt; 0.0) &amp;&amp;&#xD;&#xA;			 (closest_sofar == 0.0 || closest_sofar &gt; closest &gt; 0.0)){&#xD;&#xA;			closest_sofar = closest;&#xD;&#xA;			normal = normalize(cross(A, B));&#xD;&#xA;		}&#xD;&#xA;		else { continue; }&#xD;&#xA;	  } &#xD;&#xA;&#xD;&#xA;	  if(closest_sofar == 0.0) {&#xD;&#xA;		return false; }&#xD;&#xA;	  if(h.t == 0.0 || closest_sofar &lt; h.t){&#xD;&#xA;	  	h.t = closest_sofar;&#xD;&#xA;	  	h.normal = normal;&#xD;&#xA;	  	return true;&#xD;&#xA;	  }&#xD;&#xA;	  else{ return false; }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35620" PostHistoryTypeId="1" PostId="12370" RevisionGUID="7d6c98da-7373-448e-b1ea-632783d32003" CreationDate="2021-11-27T01:27:04.493" UserId="17602" Text="ray triangle mesh intersection logic" ContentLicense="CC BY-SA 4.0" />
  <row Id="35621" PostHistoryTypeId="3" PostId="12370" RevisionGUID="7d6c98da-7373-448e-b1ea-632783d32003" CreationDate="2021-11-27T01:27:04.493" UserId="17602" Text="|raytracing|c++|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35622" PostHistoryTypeId="5" PostId="12370" RevisionGUID="66151d50-1fbc-4e54-b61e-4488e3718bb5" CreationDate="2021-11-27T05:06:36.630" UserId="17602" Comment="deleted 19 characters in body" Text="I'm trying to render a dodecahedron triangle mesh and the triangles seem flipped or mirrored somehow. The first picture is what I should be getting, the second picture is what I'm getting and the last picture is if I only render the first triangle face of the mesh from the obj file. I'm attempting to use Barycentric coordinates and Cramer's rule to find the determinant and solve for beta, gamma, and t (the depth of the ray at the point of intersection). I think the mistake is in how I read in the triangle's vertices or how I build the other functions and compute the determinant.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5QOXw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ttve3.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7bryW.png&#xD;&#xA;&#xD;&#xA;This function is called during a loop of all the objects in a scene and compares the closest hit point found in the mesh to a global HitRecord (h) that was passed in and has a h.t parameter that has the depth (t) of the ray hit point of any other objects checked before the current mesh.&#xD;&#xA;&#xD;&#xA;    bool Mesh::hit(Ray r, HitRecord &amp; h){&#xD;&#xA;	double closest_sofar = 0.0;&#xD;&#xA;	vec3 normal;&#xD;&#xA;	size_t size = m_faces.size();&#xD;&#xA;	for(int i = 0; i &lt; size; ++i){&#xD;&#xA;		Triangle t = m_faces[i];&#xD;&#xA;		glm::vec3 a = m_vertices[t.v1];&#xD;&#xA;		glm::vec3 b = m_vertices[t.v2];&#xD;&#xA;		glm::vec3 c = m_vertices[t.v3];&#xD;&#xA;&#xD;&#xA;		glm::vec3 answer = a - r.r_origin;&#xD;&#xA;		vec3 A = a-b;&#xD;&#xA;		vec3 B = a-c;&#xD;&#xA;		vec3 D = r.r_direction;&#xD;&#xA;&#xD;&#xA;		double det = dot(cross(A, B), D);&#xD;&#xA;		if(det == 0.0 || det == -0.0) {	continue; }&#xD;&#xA;&#xD;&#xA;		double beta = dot(cross(answer, B), D) / det;&#xD;&#xA;		double gamma = dot(cross(A, answer), D) / det;&#xD;&#xA;		double closest = dot(cross(A, B), answer) / det;&#xD;&#xA;&#xD;&#xA;		if((1.0 &gt; beta &gt; 0.0) &amp;&amp;&#xD;&#xA;			 (1.0 &gt; gamma &gt; 0.0) &amp;&amp;&#xD;&#xA;			 (1.0 &gt; 1.0 - beta - gamma &gt; 0.0) &amp;&amp;&#xD;&#xA;			 (closest_sofar == 0.0 || closest_sofar &gt; closest &gt; 0.0)){&#xD;&#xA;			closest_sofar = closest;&#xD;&#xA;			normal = normalize(cross(A, B));&#xD;&#xA;		}&#xD;&#xA;		else { continue; }&#xD;&#xA;	  } &#xD;&#xA;&#xD;&#xA;	  if(closest_sofar == 0.0) {&#xD;&#xA;		return false; }&#xD;&#xA;	  if(h.t == 0.0 || closest_sofar &lt; h.t){&#xD;&#xA;	  	h.t = closest_sofar;&#xD;&#xA;	  	h.normal = normal;&#xD;&#xA;	  	return true;&#xD;&#xA;	  }&#xD;&#xA;	  else{ return false; }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35623" PostHistoryTypeId="2" PostId="12371" RevisionGUID="fe9f51f9-d5dd-4329-9a6c-f1cda04a7b11" CreationDate="2021-11-27T05:59:01.207" UserId="48" Text="First, it's important to realize what &quot;behind&quot; means here, which could be confusing. The way it's being used in this context, &quot;S1 is behind S2&quot; doesn't actually mean that S1 is totally obscured by S2 from the camera position. Rather, it means that S1 is behind the plane containing S2. This means it's impossible for any part of S1 to obscure any of S2, thus S1 should be drawn before S2 in the painter's algorithm.&#xD;&#xA;&#xD;&#xA;&gt; why all vertices of one polygon(S1) substitute in the plane of another(S2) and value is less than 0 then we say S1 is behind S2? I don't understand when value less than 0 by the vertices of one polygon then we say one is behind another?&#xD;&#xA;&#xD;&#xA;That's how plane equations work. The equation $Ax + By + Cz + D = 0$ defines the points on the plane, but in fact it goes further: if you evaluate the left-hand side for a given point, you get a number that tells you how far that point is from the plane, and the sign tells you which side of the plane it's on.&#xD;&#xA;&#xD;&#xA;Given the right-hand rule, plane equations are set up so that the front of the polygon (the visible side) is the side that gets positive values in the plane equation. So, all points behind the polygon will get negative values. Thus, if you check all the points of polygon S1, you will know S1 is entirely behind the plane of S2 if all of its vertices get negative values when substituted into S2's plane equation." ContentLicense="CC BY-SA 4.0" />
  <row Id="35625" PostHistoryTypeId="2" PostId="12372" RevisionGUID="7f8d57db-e708-427d-a55d-13504a62f658" CreationDate="2021-11-27T06:38:15.547" UserId="48" Text="At the high level it's not too difficult. Most laptop/desktop displays have three vertical subpixels, in RGB order from left to right. Given that, in your fragment shader you will need to evaluate the glyph outlines three times, using sample points at the center of each subpixel. Since the usual sample point for a fragment shader is at the pixel center, you would want to offset it by 1/3 of a pixel left and right to get the other two sample points.&#xD;&#xA;&#xD;&#xA;If you do any antialiasing as part of your glyph outline evaluation (e.g. estimating how much of the pixel area is covered), you would likewise want to narrow the antialiasing kernel to cover only 1/3 of the width of the pixel, instead of the whole pixel.&#xD;&#xA;&#xD;&#xA;A subtlety here is that if you want to render colored text, or text over different backgrounds, then you will need to use [dual-source blending](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#framebuffer-dsb) in order to correctly blend all three subpixels independently, using the three glyph evaluations as alpha values.&#xD;&#xA;&#xD;&#xA;However, note that displays might have the subpixels in other orientations (which can change dynamically as the user rotates the display in the case of phones and tablets), and some displays have pentile layouts which are more complex. For subpixel rendering to work, your sample points need to adapt to the layout of the actual display you're running on, but I'm not sure if there is any reasonable way to query this information. It's for this reason, plus the general increase in display DPIs making subpixel rendering less advantageous, that people have generally moved away from subpixel text rendering in recent years." ContentLicense="CC BY-SA 4.0" />
  <row Id="35627" PostHistoryTypeId="2" PostId="12373" RevisionGUID="244ed677-db1e-40d8-ae90-e2350dd1ffbe" CreationDate="2021-11-27T07:20:35.543" UserId="48" Text="I wasn't familiar with the &quot;Jacobi transformation&quot;, and after googling, it seems there are multiple things with that name; but given the mention of eigenvalues, I'm guessing they were referring to [a method of matrix diagonalization](https://mathworld.wolfram.com/JacobiTransformation.html) using &quot;Jacobi rotation matrices&quot;, which are better known as [Givens rotations](https://en.wikipedia.org/wiki/Givens_rotation).&#xD;&#xA;&#xD;&#xA;In other words, the Jacobi transformation would be a method of finding eigenvalues and eigenvectors of a matrix. (There are many methods for doing that, and you can read more elsewhere about exactly what those methods are and when one should use one method or another.)&#xD;&#xA;&#xD;&#xA;As for the use of eigenvalues/vectors in graphics, here are a few examples:&#xD;&#xA;&#xD;&#xA;* Decomposing a transformation matrix into rotation and scaling parts&#xD;&#xA;* Finding directions of principal curvature on a mesh&#xD;&#xA;* Fitting an oriented bounding box to a mesh&#xD;&#xA;* In texture compression: finding a line segment in RGB space to best match a block of pixels&#xD;&#xA;* In animation: finding a set of blend shapes to best match a captured or simulated vertex deformation" ContentLicense="CC BY-SA 4.0" />
  <row Id="35629" PostHistoryTypeId="4" PostId="12370" RevisionGUID="2ac376f3-1065-4990-bdfb-d7883cccc093" CreationDate="2021-11-27T07:31:32.510" UserId="17602" Comment="edited title" Text="ray triangle mesh intersection triangles inverted" ContentLicense="CC BY-SA 4.0" />
  <row Id="35630" PostHistoryTypeId="50" PostId="12286" RevisionGUID="56829d7d-a232-4e58-be6a-bbdf11861a72" CreationDate="2021-11-27T08:00:55.087" UserId="-1" />
  <row Id="35631" PostHistoryTypeId="2" PostId="12374" RevisionGUID="29c45738-031d-422d-9eed-b937a47b66c3" CreationDate="2021-11-27T15:45:37.080" UserId="17604" Text="Ive been thinking about the same problem. I suppose rather than finding the level sets, it might be more useful to think of it as finding the local maxima  of the sum of the squares of the positive/internal part of the SDF; which should behave somewhat like the hypothetical point of contact assuming both bodies were elastic and yielding equally. &#xD;&#xA;&#xD;&#xA;That function should have maxima; though not particularly unique ones, if you take the case of a box lying on a plane; thered be a square-shaped maximum.&#xD;&#xA;&#xD;&#xA;Of course there can be multiple local maxima too, in case of a banana-shaped or concave object. &#xD;&#xA;&#xD;&#xA;Either way we should be able to find such maxima using some type of descent. But I dont know if itd be efficient. And then there is the question of how to create the seed-points. One might take the extrema, or vertices of a convex hull, say, as seed points to start doing descent on other SDFs. But you can already see where that might go wrong in case of two cubes hitting edgewise. &#xD;&#xA;&#xD;&#xA;You can put more sampling points on the edge, but without edge-specific logic, you are going to be stuck with the resolution of the sampling of that edge; though maybe it would work fine in practice with a rather coarse sampling, and just a fixed few descent steps? Perhaps caching of points from the previous frame would make for really decent average-case performance? Hard to tell without giving it a spin, and I am not aware of any prior work doing so.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35633" PostHistoryTypeId="5" PostId="12361" RevisionGUID="9a1a21be-ad8d-4a81-b264-8764448d7061" CreationDate="2021-11-27T21:17:42.690" UserId="17576" Comment="added 93 characters in body" Text="I'm writing a Monte Carlo path tracer, and I'm trying to allow any mesh to be an emitter, but I'm not entirely sure about the probabilities to use when I sample them.&#xD;&#xA;&#xD;&#xA;Right now, my algorithm for light sampling does the following:&#xD;&#xA;&#xD;&#xA; 1. Pick a light $L$ in the scene with some PDF $p_{\mathcal{L}}$.&#xD;&#xA; 2. Pick a random point $y$ on the mesh with uniform probability $p_{\mathcal{S}}(y) = \frac1{S_L}$, where $S_L$ is the total area of the mesh (computed summing over all the areas of all the triangles composing the mesh).&#xD;&#xA; 3. Cast a shadow ray from the current position $x$ to the sampled point $y$.&#xD;&#xA; 4. Check visibility.&#xD;&#xA; 5. Compute the PDF wrt solid angle (I need it wrt to solid angle for my integrator); the PDF wrt area mesure should now be just $p_A(y) = p_{\mathcal{L}}(L) \cdot p_{\mathcal{S}}(y)$ (the choice of light and of a point on the light are independent events), hence the actual PDF I need is EDIT: not $p_\omega(\omega) = \frac{\cos \theta_y}{\lvert y-x \rvert ^2} p_A(y)$ but $p_\omega(\omega) = \frac{\lvert y-x \rvert ^2}{\cos \theta_y} p_A(y)$ :).&#xD;&#xA; 6. Compute the light contribution to the current point as $\frac{E_L \cdot f_r \cdot \cos(\theta_x)}{p_\omega(y)}\cdot \mathrm{thr}$, where $\mathrm{thr}$ is the ray throughput, $E_L$ is the emissive value of the light $L$, $f_r = f_r(-\omega_{\mathrm{incoming}},\omega_{\mathrm{shadow}})$ is the BRDF of the surface containing $x$, $\omega_{\mathrm{incoming}}$ is the unit vector of the current ray direction, and $\omega_{\mathrm{shadow}} = \frac{y-x}{\lvert y-x \rvert ^2}$ is the direction of the shadow ray.&#xD;&#xA; 7. Use that light contribution for next event estimation; use $p_\omega$ as my PDF for the NEE when computing the weights for multiple importance sampling.&#xD;&#xA;&#xD;&#xA;I think this should account correctly for the fact that only the projected area of my mesh on the plane of the triangle $x$ lies on should contribute to the illumination of $x$, as the visibility check rules out all the triangles &quot;hidden&quot; by the geometry of the mesh, but I'd like to be sure that I'm not forgetting anything.&#xD;&#xA;&#xD;&#xA;EDIT: In particular, the thing that makes me a bit unsure is using the entire surface area of the mesh, even though the part facing the point $x$ might be much smaller." ContentLicense="CC BY-SA 4.0" />
  <row Id="35634" PostHistoryTypeId="2" PostId="12375" RevisionGUID="a508695e-0a8f-4ef0-aa05-c3275e7ffbac" CreationDate="2021-11-27T22:43:23.477" UserId="10096" Text="Sampling the entire surface would produce a correct result, even if some contributions are zero, as long as you properly account for those being zero. Consider a similar example in 1D, where you are given a function $g$ which is nonzero in $[a,b]$ (i.e. $\operatorname{supp}(g)=[a,b]$ - the support of $g$ is $[a,b]$). Say you want to numerically estimate the integral $\int_a^bg(t)\,dt$. Assume that for some reason you aren't able to generate samples in $[a,b]$ but can instead generate those in $[a,b+\delta],\, \delta&gt;0$. Since $g\big((b,b+\delta]\big) = 0$ then it follows that:&#xD;&#xA;&#xD;&#xA;$$\int_a^{b+\delta}g(t)\,dt = \int_a^bg(t)\,dt + \int_b^{b+\delta}g(t)\,dt = \int_a^bg(t)\,dt + \int_b^{b+\delta}0\,dt = \int_a^bg(t)\,dt.$$&#xD;&#xA;&#xD;&#xA;Granted, when you numerically estimate $\int_a^{b+\delta}g(t)\,dt$ you will have higher variance since samples in $(b,b+\delta]$ would be used for estimating the zero function.&#xD;&#xA;&#xD;&#xA;While the above example is not very realistic, the case in the rendering equation is a realistic one. There the visibility function $V(x,y)$ is zero over some of the domain of integration, but the non-zero part is hard to explicitly integrate over, since the evaluation of $V(x,y)$ generally requires a ray-tracing operation." ContentLicense="CC BY-SA 4.0" />
  <row Id="35637" PostHistoryTypeId="2" PostId="12376" RevisionGUID="06f25ab5-d36e-4f65-8869-bae3dc448f79" CreationDate="2021-11-28T23:11:46.787" UserId="17610" Text="In recent years, the technology of Live2D has become particularly popular and I have been attempting to find any papers or articles which explain what the mathematics for the mesh-based image morphing system are and how they work. Unfortunately, there doesn't seem to be a lot of information on the subject and most of the links I found where just different versions of the same two or three papers and they didn't seem to answer my question.&#xD;&#xA;&#xD;&#xA;I am trying to find information on what the algorithm which performs the mesh-based morph/warp looks like. I am aware that there are point-based algorithm which morph between the established points on two different images. ([This is not what I am looking for.][1]). I am looking for an algorithm which can freely transform an image based on a non-rectangular mesh. I'm primarily referring to the image warping seen in Live2D Cubism ([manual][2]). See below for visuals.&#xD;&#xA;&#xD;&#xA;The initial definition of the &quot;artmesh&quot; on top of the image to be morphed:&#xD;&#xA;[![The initial definition of the &quot;artmesh&quot; on top of the image to be morphed.][3]][3]&#xD;&#xA;&#xD;&#xA;The vertices in the &quot;artmesh&quot; have now been moved around and the solitary layer has been morphed smoothly to match:&#xD;&#xA;[![The vertices in the &quot;artmesh&quot; have now been moved around and the solitary layer has been morphed smoothly to match.][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Does anybody know what the algorithm looks like? Sources such as papers, articles or open-source projects would also be appreciated, if possible. As a side note, I am posting this on ComputerGraphics, since I get the feeling that the mesh-based morphing logic may relate to texture projection in 3D graphics. Unfortunately, I'm not experienced enough in that subject to be more specific. I hope you can answer my question. Thank you in advance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/F2AitTPI5U0?t=327&#xD;&#xA;  [2]: https://docs.live2d.com/cubism-editor-tutorials/import/&#xD;&#xA;  [3]: https://i.stack.imgur.com/aKHLG.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/N5fgt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35639" PostHistoryTypeId="1" PostId="12376" RevisionGUID="06f25ab5-d36e-4f65-8869-bae3dc448f79" CreationDate="2021-11-28T23:11:46.787" UserId="17610" Text="What does an algorithm which handles mesh-based image morphing look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35640" PostHistoryTypeId="3" PostId="12376" RevisionGUID="06f25ab5-d36e-4f65-8869-bae3dc448f79" CreationDate="2021-11-28T23:11:46.787" UserId="17610" Text="|algorithm|mesh|2d|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35641" PostHistoryTypeId="2" PostId="12377" RevisionGUID="9de2f614-62c4-4b33-a3e4-39e3e3a74110" CreationDate="2021-11-29T06:01:06.903" UserId="2654" Text="Let's talk barycentric coordinates.&#xD;&#xA;&#xD;&#xA;For triangles, any point within a triangle can be defined by a set of 3 coordinates called [barycentric coordinates][1]. The three values are each on the range [0, 1], and they represent a relative distance from the point in question to each of the 3 vertex positions of the triangle.&#xD;&#xA;&#xD;&#xA;You can think of barycentric coordinates as kind of a normalized position within a triangle. The coordinate (1, 0, 0) is always the position of the first vertex of the triangle (whichever one you define to be &quot;first&quot;). This means that barycentric coordinates are *independent* of the absolute shape of the triangle.&#xD;&#xA;&#xD;&#xA;For example, the center point of a triangle is always at the coordinate (0.33, 0.33, 0.33), no matter what the shape of that triangle is. Which means that if you perform any kind of transformation on the triangle, the barycentric coordinate stays the same.&#xD;&#xA;&#xD;&#xA;So you have a triangle in the source image and a triangle in the destination image. When you rasterize the destination triangle, you get a bunch of pixels within the triangle. For each location in the destination triangle, you can compute its barycentric coordinates. You can then convert those barycentric coordinates to the *source* triangle to get the position in the source image.&#xD;&#xA;&#xD;&#xA;Then just convert that position into a texture coordinate and read from the image there. And you're done.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Barycentric_coordinate_system#Barycentric_coordinates_on_triangles" ContentLicense="CC BY-SA 4.0" />
  <row Id="35643" PostHistoryTypeId="50" PostId="5996" RevisionGUID="9831a788-29ea-45a3-995f-d63502914e7a" CreationDate="2021-11-29T16:00:35.057" UserId="-1" />
  <row Id="35650" PostHistoryTypeId="5" PostId="12366" RevisionGUID="45b0284e-57d3-4cbe-97bd-7c6cc5aa8c74" CreationDate="2021-11-30T08:57:33.373" UserId="13095" Comment="Fix some grammar and spelling" Text="Recently, I want to use a roughness map to get better rendering results.&#xD;&#xA;Most information on the internet is about the operation of 3D software.&#xD;&#xA;So, how can I generate a roughness map of my own 3D mesh?&#xD;&#xA;Thanks very much." ContentLicense="CC BY-SA 4.0" />
  <row Id="35651" PostHistoryTypeId="2" PostId="12379" RevisionGUID="c5a363d1-6f8f-493a-b0c5-f633846363b8" CreationDate="2021-11-30T12:59:21.417" UserId="17223" Text="I am somewhat confused with the following issue reading about the rendering equation and BRDFs. That is, the BRDF is usually defined as surface radiance $Lr(ω_r)$ over irradiance $L_i(ω_i)cosθ_i$ for an infinitesimal solid angle like so:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;fr(ωi,ωr) = \frac{dL_r(ω_r)}{L_i(ω_i)cosθ_idω_i}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And the integrand of the rendering equation is given by:&#xD;&#xA;&#xD;&#xA;$$f_r(ω_i, ω_o)L_i(x,ω_i)cos(ω_i\cdot\vec{n})dω_i$$&#xD;&#xA;&#xD;&#xA;I conclude that $cosθ_i$ = $cos(ω_i\cdot\vec{n})$ which raises the question why bothering about the cosine term at all since it cancels out anyway? **There are some posts on why the brdf is radiance over irradiance (instead of radiance of radiance). This makes sense on its own to get independence of the incoming radiance direction. However, in combination with the rendering equation it gets confusing again because it seems useless.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="35653" PostHistoryTypeId="1" PostId="12379" RevisionGUID="c5a363d1-6f8f-493a-b0c5-f633846363b8" CreationDate="2021-11-30T12:59:21.417" UserId="17223" Text="Cosine in Rendering Equation and BRDF cancel out: Why cosine at all?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35654" PostHistoryTypeId="3" PostId="12379" RevisionGUID="c5a363d1-6f8f-493a-b0c5-f633846363b8" CreationDate="2021-11-30T12:59:21.417" UserId="17223" Text="|rendering|brdf|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35655" PostHistoryTypeId="2" PostId="12380" RevisionGUID="15430a3d-b110-4c26-afa2-3ec6f04fa712" CreationDate="2021-11-30T16:31:07.970" UserId="9552" Text="Is it proportional to the samples count?&#xD;&#xA;How does it affect the performance when resolving it immediately or later?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35657" PostHistoryTypeId="1" PostId="12380" RevisionGUID="15430a3d-b110-4c26-afa2-3ec6f04fa712" CreationDate="2021-11-30T16:31:07.970" UserId="9552" Text="How big is a multi-sampled FBO than a regular FBO with the same resolution?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35658" PostHistoryTypeId="3" PostId="12380" RevisionGUID="15430a3d-b110-4c26-afa2-3ec6f04fa712" CreationDate="2021-11-30T16:31:07.970" UserId="9552" Text="|antialiasing|memory|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35659" PostHistoryTypeId="34" PostId="12297" RevisionGUID="93093667-0749-43b6-a449-36552194db05" CreationDate="2021-12-01T06:03:00.293" UserId="-1" Comment="71" />
  <row Id="35660" PostHistoryTypeId="5" PostId="12380" RevisionGUID="ba6e9778-3c16-4ded-b5a0-412008f87919" CreationDate="2021-12-01T15:12:53.547" UserId="9552" Comment="deleted 76 characters in body" Text="Is it proportional to the samples count?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35661" PostHistoryTypeId="2" PostId="12381" RevisionGUID="927b949a-4e0a-4a48-bb0c-0ddd13269259" CreationDate="2021-12-01T15:18:20.297" UserId="15955" Text="Good Morning!&#xD;&#xA;I'm having trouble rendering an on-screen bloom shader by post processing.&#xD;&#xA;Basically the shader works like this:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Camera image before rendering the effect:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;First a filter is passed on the camera image to leave only one highlights.&#xD;&#xA;&#xD;&#xA;[![\[ATTACH=full\]964042\[/ATTACH\]][2]][2]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float4 _BloomThreshold;&#xD;&#xA;float _BloomIntensity;&#xD;&#xA;float _BloomScattering;&#xD;&#xA;&#xD;&#xA;float3 ApplyBloomThreshold(float3 color) {&#xD;&#xA;    float brightness = Max3(color.r, color.g, color.b);&#xD;&#xA;    float soft = brightness + _BloomThreshold.y;&#xD;&#xA;    soft = clamp(soft, 0.0, _BloomThreshold.z);&#xD;&#xA;    soft = soft * soft * _BloomThreshold.w;&#xD;&#xA;    float contribution = max(soft, brightness - _BloomThreshold.x);&#xD;&#xA;    contribution /= max(brightness, 0.00001);&#xD;&#xA;    return color * contribution;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float4 PreFilter(Varyings i) : SV_TARGET{&#xD;&#xA;    float3 color = pow(ApplyBloomThreshold(GetSource(i.fxUV).rgb),2);&#xD;&#xA;    return float4(color, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;After that, the image goes through a downsample:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float4 FragBox(Varyings i) : SV_Target&#xD;&#xA;{&#xD;&#xA;    return float4(SampleBox(i.fxUV),1);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;static const float gaussian[14] = {&#xD;&#xA;    0.00598,    0.060626,    0.241843,    0.383103,    0.241843,    0.060626,    0.00598,&#xD;&#xA;    0.02400,    0.0160125,    0.741843,    0.455653,    0.296803,    0.189060,    0.18406&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;float4 FragHBlur(Varyings i) : SV_Target&#xD;&#xA;{&#xD;&#xA;    float4 color;&#xD;&#xA;    float2 o = float2(GetSourceTexelSize().x, 0);&#xD;&#xA;    for (int idx = -3; idx &lt;= 3; idx++) {&#xD;&#xA;        float4 tColor = GetSource(i.fxUV + idx * o);&#xD;&#xA;        color += tColor * gaussian[idx + 3];&#xD;&#xA;    }&#xD;&#xA;    return float4(color.rgb, 1 / _Levels);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float4 FragVBlur(Varyings i) : SV_Target&#xD;&#xA;{&#xD;&#xA;    float4 color;&#xD;&#xA;    float2 o = float2(0, GetSourceTexelSize().y);&#xD;&#xA;    for (int idx = -3; idx &lt;= 3; idx++) {&#xD;&#xA;        float4 tColor = GetSource(i.fxUV + idx * o);&#xD;&#xA;        color += tColor * gaussian[idx + 3];&#xD;&#xA;    }&#xD;&#xA;    return float4(color.rgb, 1 / _Levels);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This step occurs several times in the effect's rendering, with each of the images used from source having its dimensions shrunk.&#xD;&#xA;&#xD;&#xA;After the image is blurred, it will be merged with the image from the previous frame, which was also blurred but has larger dimensions.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;After merging all bloomed images, the final image is merged with the camera image before rendering the effect:&#xD;&#xA;&#xD;&#xA;https://youtu.be/upFOgWgLqXc&#xD;&#xA;&#xD;&#xA;So far so good.&#xD;&#xA;&#xD;&#xA;https://youtu.be/2rJ7lS8DM5I&#xD;&#xA;&#xD;&#xA;The problem is these black squares that sometimes appear when I move the camera.&#xD;&#xA;Why are they there???&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;https://youtu.be/ralRa_-nqiU&#xD;&#xA;&#xD;&#xA;The same problem happens in the lens flare shader, which uses the same downsample method:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/92lGr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/10ED8.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/i1HEm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/P6Qel.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/D649n.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35663" PostHistoryTypeId="1" PostId="12381" RevisionGUID="927b949a-4e0a-4a48-bb0c-0ddd13269259" CreationDate="2021-12-01T15:18:20.297" UserId="15955" Text="Black squares in bloom effect" ContentLicense="CC BY-SA 4.0" />
  <row Id="35664" PostHistoryTypeId="3" PostId="12381" RevisionGUID="927b949a-4e0a-4a48-bb0c-0ddd13269259" CreationDate="2021-12-01T15:18:20.297" UserId="15955" Text="|hlsl|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35665" PostHistoryTypeId="5" PostId="12380" RevisionGUID="11cd8c17-0895-46b3-bbfd-3f15ca81c844" CreationDate="2021-12-01T15:18:20.763" UserId="9552" Comment="deleted 76 characters in body" Text="Is it proportional to the samples count?&#xD;&#xA;&#xD;&#xA;Whats the performance difference between binding a multi-sampler and  a regular sampler? " ContentLicense="CC BY-SA 4.0" />
  <row Id="35666" PostHistoryTypeId="2" PostId="12382" RevisionGUID="a8096dc6-b4b7-4127-8b99-b1a391c9e8f6" CreationDate="2021-12-01T20:27:33.860" UserId="17625" Text="I am reading this paper [\[Practical Path Guiding for Efficient Light-Transport Simulation, Müller et al, 2017\]][1] and it contains the following sentence:&#xA;&#xA;&gt; In practice, however, we recommend combining path-guiding with NEE via multiple importance sampling due to the ease of im- plementation and low performance overhead.&#xA;&#xA;What does NEE stand for? I have found some other authors using this abbreviation, but no explanation.&#xA;&#xA;&#xA;&#xA;&#xA;  [1]: https://studios.disneyresearch.com/wp-content/uploads/2019/03/Practical-Path-Guiding-for-Efficient-Light-Transport-Simulation.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35668" PostHistoryTypeId="1" PostId="12382" RevisionGUID="a8096dc6-b4b7-4127-8b99-b1a391c9e8f6" CreationDate="2021-12-01T20:27:33.860" UserId="17625" Text="What is meant by ‘NEE’ in computer graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35669" PostHistoryTypeId="3" PostId="12382" RevisionGUID="a8096dc6-b4b7-4127-8b99-b1a391c9e8f6" CreationDate="2021-12-01T20:27:33.860" UserId="17625" Text="|pathtracing|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35670" PostHistoryTypeId="2" PostId="12383" RevisionGUID="d89f1748-4e91-43e7-b413-7fc669192151" CreationDate="2021-12-02T12:39:36.780" UserId="7952" Text="Here is a  linearize depth function that expects the non-linear values to be between [0,1] and works in Vulkan.&#xD;&#xA;&#xD;&#xA;    float LinearizeDepth(float d)&#xD;&#xA;    {&#xD;&#xA;       return zNear * zFar / (zFar + d * (zNear - zFar));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I recommend breaking the texture lookup and the linearization into seperate functions to help keep the code base clean/readable and have less bugs.&#xD;&#xA;&#xD;&#xA;Also note that if this doesn't work then the issues with the code run deeper then just depth linearization." ContentLicense="CC BY-SA 4.0" />
  <row Id="35672" PostHistoryTypeId="2" PostId="12384" RevisionGUID="151d97f3-c1bd-4341-a24c-127bcb16d70c" CreationDate="2021-12-02T16:28:29.087" UserId="72" Text="If I have a regular sampling pattern there typically exist many reasonably fast ways to interpolate the results of the sampling procedure in between the sample locations. For example bilinear or bicubic (etc.) interpolation for a rectangular pattern.&#xD;&#xA;&#xD;&#xA;How can I interpolate sample results when the sample locations were randomly generated (but still, all of them are known before the sampling begins)? &#xD;&#xA;&#xD;&#xA;If computation time wasn't a concern, I could e.g. find the nearest k neighbours and then use e.g. barycentric coordinates to interpolate any way I like. But that is too slow for applications like simple texture sampling in a shader. &#xD;&#xA;&#xD;&#xA;Do any alternatives exist, or is it fundamentally an impossible task? Does it help if at least the random distribution is known beforehand (e.g. poisson)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35674" PostHistoryTypeId="1" PostId="12384" RevisionGUID="151d97f3-c1bd-4341-a24c-127bcb16d70c" CreationDate="2021-12-02T16:28:29.087" UserId="72" Text="Interpolating randomly distributed samples in real time" ContentLicense="CC BY-SA 4.0" />
  <row Id="35675" PostHistoryTypeId="3" PostId="12384" RevisionGUID="151d97f3-c1bd-4341-a24c-127bcb16d70c" CreationDate="2021-12-02T16:28:29.087" UserId="72" Text="|sampling|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35676" PostHistoryTypeId="5" PostId="10675" RevisionGUID="1dd7eee6-edc1-4f8d-a216-a935748e9479" CreationDate="2021-12-02T16:34:26.367" UserId="-1" Comment="y&gt;&gt;256 probably means y/256 or y &gt;&gt; 8" Text="Absolutely there is, the Bresenham's Algorithm, modified.&#xD;&#xA;&#xD;&#xA;Instead of drawing from (x0,y0) to (x1,y1), one can use Bresenham's algorithm to draw lines from `(x0,y0*256)` to `(x1, y1*256)` still in x1-x0+1 steps, meaning that the delta_y is also multiplied by a factor of 256.&#xD;&#xA;&#xD;&#xA;At each step  `plot(x, y &gt;&gt; 8, y ^ 255); plot(x, sign(y1-y0)+(y&gt;&gt;8), y &amp; 255);`&#xD;&#xA;&#xD;&#xA;This is similarly fast, as it would use Bresenham's middle point algorithm with better error handing than Wu's algorithm (given that it suffers from error accumulation due to DDA) while also calculating the distance properly rounded. This approach of course adds one shift `y &gt;&gt; 8` one `xor` and two pixel writings. `y &amp; 255` is typically free.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35677" PostHistoryTypeId="24" PostId="10675" RevisionGUID="1dd7eee6-edc1-4f8d-a216-a935748e9479" CreationDate="2021-12-02T16:34:26.367" Comment="Proposed by anonymous approved by 15781 edit id of 575" ContentLicense="CC BY-SA 4.0" />
  <row Id="35678" PostHistoryTypeId="5" PostId="2132" RevisionGUID="9034eaec-6e5c-4a9b-bbc7-be4a6e4e4b60" CreationDate="2021-12-02T22:39:11.037" UserId="48" Comment="update links" Text="There is a great paper from 2006 on this topic, [Filter Importance Sampling](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.183.3579&amp;rep=rep1&amp;type=pdf). They propose your method 2, study the properties, and come out generally in favor of it. They claim that this method gives smoother rendering results because it weights all samples that contribute to a pixel equally, thereby reducing variance in the final pixel values. This makes some sense, as it's a general maxim in Monte Carlo rendering that importance-sampling will give lower variance than weighted samples.&#xD;&#xA;&#xD;&#xA;Method 2 also has the advantage of being slightly easier to parallelize because each pixel's computations are independent of all other pixels, while in method 1, sample results are shared across neighboring pixels (and therefore have to be synchronized/communicated somehow when pixels are parallelized across multiple processors). For the same reason, it's easier to do adaptive sampling (more samples in high-variance areas of the image) with method 2 than method 1.&#xD;&#xA;&#xD;&#xA;In the paper, they also experimented with a Mitchell filter, sampling from abs() of the filter and then weighting each sample with either +1 or &amp;minus;1, like @trichoplax suggested. But this ended up actually increasing the variance and being worse than method 1, so they conclude that method 2 is only usable for positive filters.&#xD;&#xA;&#xD;&#xA;That being said, the results from this paper may not be universally applicable, and it may be somewhat scene-dependent which sampling method is better. I wrote [a blog post investigating this question](https://www.reedbeta.com/blog/antialiasing-to-splat-or-not/) independently in 2014, using a synthetic &quot;image function&quot; rather than full rendering, and found method 1 to give more visually pleasing results due to smoothing high-contrast edges more nicely. Benedikt Bitterli also commented on that post reporting a similar issue with his renderer (excess high-frequency noise around light sources when using method 2). Beyond that, I found the main difference between the methods was the frequency of the resulting noise: method 2 gives higher-frequency, &quot;pixel-sized&quot; noise, while method 1 gives noise &quot;grains&quot; that are 2-3 pixels across, but the amplitude of noise was similar for both, so which kind of noise looks less bad is probably a matter of personal preference." ContentLicense="CC BY-SA 4.0" />
  <row Id="35679" PostHistoryTypeId="50" PostId="11012" RevisionGUID="6e869357-6950-430f-b968-9992b5cfb5af" CreationDate="2021-12-03T06:06:00.587" UserId="-1" />
  <row Id="35680" PostHistoryTypeId="5" PostId="12384" RevisionGUID="bd85cabe-0fde-4c1b-8e5a-b6338d50d6e2" CreationDate="2021-12-03T08:26:03.547" UserId="72" Comment="deleted 110 characters in body; edited title" Text="If I have a regular sampling pattern there typically exist many reasonably fast ways to interpolate the results of the sampling procedure in between the sample locations. For example bilinear or bicubic (etc.) interpolation for a rectangular pattern.&#xD;&#xA;&#xD;&#xA;How can I interpolate sample results from poisson disk sampling when the sample locations were randomly generated (but still, all of them are known before the sampling begins)? &#xD;&#xA;&#xD;&#xA;If computation time wasn't a concern, I could e.g. find the nearest k neighbours of sample location and then use e.g. barycentric coordinates to interpolate any way I like. But that is too slow for applications like simple texture sampling in a shader. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35681" PostHistoryTypeId="4" PostId="12384" RevisionGUID="bd85cabe-0fde-4c1b-8e5a-b6338d50d6e2" CreationDate="2021-12-03T08:26:03.547" UserId="72" Comment="deleted 110 characters in body; edited title" Text="Interpolating poisson disk samples in real time" ContentLicense="CC BY-SA 4.0" />
  <row Id="35686" PostHistoryTypeId="2" PostId="12386" RevisionGUID="a86957ed-4e60-4191-b1e8-925b6236f70e" CreationDate="2021-12-03T09:24:39.077" UserId="4746" Text="There is a lot of implication in binding a multi-sampler image.&#xD;&#xA;&#xD;&#xA;Basically multi-sampling will run multiple fragment for the same pixel.&#xD;&#xA;AFAIK if the same triangle is rasterized on multiple sample of the same pixel, it will be shaded only once (This is implementation specific!). This is the advantage of upsampling.&#xD;&#xA;&#xD;&#xA;More sample count you have more chance you get to get more shaded fragments, therefore, bandwith, instructions count, memory, everything is impacted.&#xD;&#xA;&#xD;&#xA;Also the multi-sampled image take more space and might(will) have different internal alignment.&#xD;&#xA;&#xD;&#xA;To conclude there is summary of difference between the techniques:&#xD;&#xA;&#xD;&#xA; - normal sampler: 1 fragment per pixel, good coherency, fast, might have aliasing&#xD;&#xA; - ms sampler: 2/4/8/16 fragment per pixel when a lot of triangle are partially covering the triangle, less good coherency, quite fast, need a resolve pass, less aliasing.&#xD;&#xA; - upsampling: 2/4/8 fragment run for each resolved pixel. very expensive, need a beefy gc good coherency, not fast, best mathematical antialiasing.&#xD;&#xA;&#xD;&#xA;Basically multi sampling is a &quot;cheap upsampling&quot;.&#xD;&#xA;&#xD;&#xA;&gt; Is it proportional to the samples count?&#xD;&#xA;&#xD;&#xA;Yes but not linear.&#xD;&#xA;&#xD;&#xA;&gt;Whats the performance difference between binding a multi-sampler and a regular sampler?&#xD;&#xA;&#xD;&#xA;Benchmarking is the only way to know for your renderer on one card model with one driver. But it will affect speed significantly." ContentLicense="CC BY-SA 4.0" />
  <row Id="35688" PostHistoryTypeId="2" PostId="12387" RevisionGUID="6d1772cf-cfd9-4a18-bd17-2740d8fc6614" CreationDate="2021-12-03T09:29:41.697" UserId="17330" Text="I wrote an ssao algorithm with compute shaders and view-position-reconstruction from the depth buffer. It works great for objects near by but results in strip or banding artifacts for large planes further away:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RJrut.png&#xD;&#xA;&#xD;&#xA;This does **not** happen if i use an explicit position buffer. I don't think this is because of floating point accuracy. My methods to reconstruct the position for the original pixel and the z coordinate for the pixels in its hemisphere:&#xD;&#xA;&#xD;&#xA;    vec3 calcViewPos(vec2 texCoords, float depth){&#xD;&#xA;        vec3 clipPos = vec3(texCoords, depth) * 2.0 - vec3(1.0);&#xD;&#xA;        vec4 viewPos = vec4(vec2(invProj[0][0], invProj[1][1]) * clipPos.xy, -1,&#xD;&#xA;                                       invProj[2][3] * clipPos.z + invProj[3][3]);&#xD;&#xA;        return(viewPos.xyz / viewPos.w);&#xD;&#xA;    }&#xD;&#xA;I use a `GL_DEPTH_COMPONENT32` depth texture. I could solve the problem by a little hack:&#xD;&#xA;Comparing the normal of the original pixel and the normal of the neighbourhood pixels and skipping those which have a too similar normal solves this problem (since this only occurs on those large plains), but causes an additional texture lookup in a for loop, which costs too much (and would make using a position buffer again more efficient).&#xD;&#xA;&#xD;&#xA;Did any of you experience a simillar problem or have ideas of how to solve this smarter? &#xD;&#xA;Thank you very much :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="35690" PostHistoryTypeId="1" PostId="12387" RevisionGUID="6d1772cf-cfd9-4a18-bd17-2740d8fc6614" CreationDate="2021-12-03T09:29:41.697" UserId="17330" Text="SSAO with reconstructed depths yields strip artifacts" ContentLicense="CC BY-SA 4.0" />
  <row Id="35691" PostHistoryTypeId="3" PostId="12387" RevisionGUID="6d1772cf-cfd9-4a18-bd17-2740d8fc6614" CreationDate="2021-12-03T09:29:41.697" UserId="17330" Text="|opengl|shader|compute-shader|ambient-occlusion|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35697" PostHistoryTypeId="2" PostId="12389" RevisionGUID="8e9053e6-d791-475d-96c1-61c7ec7b2ce9" CreationDate="2021-12-03T10:45:12.037" UserId="10096" Text="Here are several options:&#xD;&#xA;&#xD;&#xA;1) Use the jump flood algorithm to construct a voronoi diagram with seeds containing their $k$ closest seeds. Then use some weighting function between those $k$ values (e.g. linear for $3$, billinear for $4$, generalized barycentric coordinates, Shepard interpolation, Gaussians, rbfs, or other).&#xD;&#xA;&#xD;&#xA;2) Pick a convolution kernel (e.g. Gaussian with appropriately large sigma) and convolve your points in a vertical and horizontal pass or using FFT.&#xD;&#xA;&#xD;&#xA;3) Downsample your image until at every pixel you have a sample. At each level produce `ceil(N/2)` pixels in the given dimension provided the previous had $N$ pixels. If $N$ is even then consider every 2 pixels in that dimension. If both pixels contain samples then average, if only 1 contains a sample then just copy its value, otherwise set 0. That's you restriction operator. You can convolve before applying it. If $N$ is odd the consider every 3 pixels from the finer level (there is some overlap), if all 3 are samples then average all 3, if only 2 of the 3 are samples then average with weight $0.5$, if only 1 is a sample copy its value, otherwise 0. Your samples will thus grow in size at each downsampling until you get an image full of samples at some level. At that point start upsampling and at each level overwrite with the fine samples. This would produce a hierarchy of levels with the finest providing interpolation based on the convolution and interpolation operators you chose at each level." ContentLicense="CC BY-SA 4.0" />
  <row Id="35702" PostHistoryTypeId="5" PostId="12386" RevisionGUID="0ff35d4d-e457-43ad-906f-c36de3ed7795" CreationDate="2021-12-03T11:45:52.503" UserId="13095" Comment="Fix some grammar and spelling" Text="There is a lot of implication in binding a multi-sampler image.&#xD;&#xA;&#xD;&#xA;Basically, multi-sampling will run multiple fragments for the same pixel.&#xD;&#xA;AFAIK if the same triangle is rasterized on multiple samples of the same pixel, it will be shaded only once (This is implementation-specific!). This is the advantage of upsampling.&#xD;&#xA;&#xD;&#xA;More sample count you have more chance you get to get more shaded fragments, therefore, bandwidth, instructions count, memory, everything is impacted.&#xD;&#xA;&#xD;&#xA;Also, the multi-sampled image takes more space and might(will) have different internal alignment.&#xD;&#xA;&#xD;&#xA;To conclude, here is a summary of the differences between the techniques:&#xD;&#xA;&#xD;&#xA; - normal sampler: 1 fragment per pixel, good coherency, fast, might have aliasing&#xD;&#xA; - ms sampler: 2/4/8/16 fragment per pixel when a lot of triangles are partially covering the triangle, less good coherency, quite fast, need a resolve pass, less aliasing.&#xD;&#xA; - upsampling: 2/4/8 fragment run for each resolved pixel. very expensive, need a beefy gc good coherency, not fast, best mathematical antialiasing.&#xD;&#xA;&#xD;&#xA;Basically, multi sampling is a &quot;cheap upsampling&quot;.&#xD;&#xA;&#xD;&#xA;&gt; Is it proportional to the samples count?&#xD;&#xA;&#xD;&#xA;Yes but not linear.&#xD;&#xA;&#xD;&#xA;&gt;Whats the performance difference between binding a multi-sampler and a regular sampler?&#xD;&#xA;&#xD;&#xA;Benchmarking is the only way to know for your renderer on one card model with one driver. But it will affect speed significantly." ContentLicense="CC BY-SA 4.0" />
  <row Id="35703" PostHistoryTypeId="5" PostId="12389" RevisionGUID="9f8e31cc-3e49-4491-834b-c57764d8d12e" CreationDate="2021-12-03T15:28:22.123" UserId="10096" Comment="added 1 character in body" Text="Here are several options:&#xD;&#xA;&#xD;&#xA;1) Use the jump flood algorithm to construct a voronoi diagram with pixels containing their $k$ closest seeds. Then use some weighting function between those $k$ values (e.g. linear for $3$, billinear for $4$, generalized barycentric coordinates, Shepard interpolation, Gaussians, rbfs, or other).&#xD;&#xA;&#xD;&#xA;2) Pick a convolution kernel (e.g. Gaussian with appropriately large sigma) and convolve your points in a vertical and horizontal pass or using FFT.&#xD;&#xA;&#xD;&#xA;3) Downsample your image until at every pixel you have a sample. At each level produce `ceil(N/2)` pixels in the given dimension provided the previous had $N$ pixels. If $N$ is even then consider every 2 pixels in that dimension. If both pixels contain samples then average, if only 1 contains a sample then just copy its value, otherwise set 0. That's you restriction operator. You can convolve before applying it. If $N$ is odd the consider every 3 pixels from the finer level (there is some overlap), if all 3 are samples then average all 3, if only 2 of the 3 are samples then average with weight $0.5$, if only 1 is a sample copy its value, otherwise 0. Your samples will thus grow in size at each downsampling until you get an image full of samples at some level. At that point start upsampling and at each level overwrite with the fine samples. This would produce a hierarchy of levels with the finest providing interpolation based on the convolution and interpolation operators you chose at each level." ContentLicense="CC BY-SA 4.0" />
  <row Id="35704" PostHistoryTypeId="50" PostId="10378" RevisionGUID="01709e26-b12f-4d2c-971b-1e52bd616a16" CreationDate="2021-12-03T17:02:00.173" UserId="-1" />
  <row Id="35711" PostHistoryTypeId="5" PostId="12340" RevisionGUID="f93e7ef6-45fe-4a52-9431-29cb5a0c5c04" CreationDate="2021-12-05T02:53:29.237" UserId="15879" Comment="deleted 144 characters in body" Text="Suppose a GLTF file provides a single `N` byte buffer which includes all vertex data for multiple meshes. The first `m` bytes are interleaved vertex positions, normals etc. for one geometry and the remaining data is non-interleaved data for other geometries. All meshes will be rendered eventually.&#xD;&#xA;&#xD;&#xA;How is the data best uploaded to the GPU? &#xD;&#xA;&#xD;&#xA;Is it best to upload the whole `N` bytes and then use `vertexAttribPointer()` to define the layout or is it better to upload the different buffer regions separately, one for each mesh? Or is there a benefit to separating the first `m` bytes of interleaved data from the remaining non-interleaved data? The overall footprint on the GPU would be the same." ContentLicense="CC BY-SA 4.0" />
  <row Id="35713" PostHistoryTypeId="5" PostId="12386" RevisionGUID="c05ceae7-96bc-4ca2-b2a3-86b6353cf975" CreationDate="2021-12-05T23:50:54.017" UserId="48" Comment="change upsampling to supersampling (upsampling refers to stretching an image larger)" Text="There is a lot of implication in binding a multi-sampler image.&#xD;&#xA;&#xD;&#xA;Basically, multi-sampling will run multiple fragments for the same pixel.&#xD;&#xA;AFAIK if the same triangle is rasterized on multiple samples of the same pixel, it will be shaded only once (This is implementation-specific!). This is the advantage of supersampling.&#xD;&#xA;&#xD;&#xA;More sample count you have more chance you get to get more shaded fragments, therefore, bandwidth, instructions count, memory, everything is impacted.&#xD;&#xA;&#xD;&#xA;Also, the multi-sampled image takes more space and might(will) have different internal alignment.&#xD;&#xA;&#xD;&#xA;To conclude, here is a summary of the differences between the techniques:&#xD;&#xA;&#xD;&#xA; - normal sampler: 1 fragment per pixel, good coherency, fast, might have aliasing&#xD;&#xA; - ms sampler: 2/4/8/16 fragments per pixel when a lot of triangles are partially covering the triangle, less good coherency, quite fast, need a resolve pass, less aliasing.&#xD;&#xA; - supersampling: 2/4/8 fragments run for each resolved pixel. very expensive, need a beefy gc good coherency, not fast, best mathematical antialiasing.&#xD;&#xA;&#xD;&#xA;Basically, multi sampling is a &quot;cheap supersampling&quot;.&#xD;&#xA;&#xD;&#xA;&gt; Is it proportional to the samples count?&#xD;&#xA;&#xD;&#xA;Yes but not linear.&#xD;&#xA;&#xD;&#xA;&gt;Whats the performance difference between binding a multi-sampler and a regular sampler?&#xD;&#xA;&#xD;&#xA;Benchmarking is the only way to know for your renderer on one card model with one driver. But it will affect speed significantly." ContentLicense="CC BY-SA 4.0" />
  <row Id="35714" PostHistoryTypeId="2" PostId="12391" RevisionGUID="0caba7bc-8d13-40ef-8a91-85982936418a" CreationDate="2021-12-06T10:37:11.563" UserId="17638" Text="In rasterization, at least in the context of game development, it is a common to have many instances of the same 3D object in a scene (think many identical rocks in different sizes/positions/rotations) and to render them by only putting the 3D object in GPU memory once and just updating the model matrix every time. This works relatively easily in rasterization since the rendering is done &quot;object by object&quot;, but it allows to be way more efficient than if we were to upload several copies of the same mesh.&#xD;&#xA;&#xD;&#xA;I was wondering: is that possible/usually done in raytracing? I was looking at the code from Raytracing in one Weekend and the author allocates one new sphere every time he adds a sphere to the scene:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    for (int a = -11; a &lt; 11; a++) {&#xD;&#xA;        for (int b = -11; b &lt; 11; b++) {&#xD;&#xA;            auto choose_mat = random_double();&#xD;&#xA;            point3 center(a + 0.9*random_double(), 0.2, b + 0.9*random_double());&#xD;&#xA;&#xD;&#xA;            if ((center - point3(4, 0.2, 0)).length() &gt; 0.9) {&#xD;&#xA;                shared_ptr&lt;material&gt; sphere_material;&#xD;&#xA;&#xD;&#xA;                if (choose_mat &lt; 0.8) {&#xD;&#xA;                    // diffuse&#xD;&#xA;                    auto albedo = color::random() * color::random();&#xD;&#xA;                    sphere_material = make_shared&lt;lambertian&gt;(albedo);&#xD;&#xA;                    world.add(make_shared&lt;sphere&gt;(center, 0.2, sphere_material));&#xD;&#xA;                } else if (choose_mat &lt; 0.95) {&#xD;&#xA;                    // metal&#xD;&#xA;                    auto albedo = color::random(0.5, 1);&#xD;&#xA;                    auto fuzz = random_double(0, 0.5);&#xD;&#xA;                    sphere_material = make_shared&lt;metal&gt;(albedo, fuzz);&#xD;&#xA;                    world.add(make_shared&lt;sphere&gt;(center, 0.2, sphere_material));&#xD;&#xA;                } else {&#xD;&#xA;                    // glass&#xD;&#xA;                    sphere_material = make_shared&lt;dielectric&gt;(1.5);&#xD;&#xA;                    world.add(make_shared&lt;sphere&gt;(center, 0.2, sphere_material));&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I wonder: is this done just for simplicity (after all it is a beginners raytracing course) or is it not an usual practice to reuse geometry in such renderers (possibly because the algorithms do not make it possible, as they evaluate the whole scene ar once)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35716" PostHistoryTypeId="1" PostId="12391" RevisionGUID="0caba7bc-8d13-40ef-8a91-85982936418a" CreationDate="2021-12-06T10:37:11.563" UserId="17638" Text="Can meshes be reused in raytracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35717" PostHistoryTypeId="3" PostId="12391" RevisionGUID="0caba7bc-8d13-40ef-8a91-85982936418a" CreationDate="2021-12-06T10:37:11.563" UserId="17638" Text="|raytracing|performance|rasterizer|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35718" PostHistoryTypeId="2" PostId="12392" RevisionGUID="70e4636f-99ba-4fb3-af39-2b737b89e887" CreationDate="2021-12-06T15:09:20.277" UserId="2654" Text="Example code tends to be bad code from a performance (or even software engineering) standpoint because... it's an example. Its primary purpose is to make it clear how to do a thing, not to do it in an efficient or well-structured way.&#xD;&#xA;&#xD;&#xA;Ray tracing can reference &quot;meshes&quot; or any object definition just fine. You have the data for some mesh or whatever with its own model space, and you have zero or more instances of those objects in the world. Those instances each come with per-instance data, like their transformation into world space, any bounding volumes used for quick ray intersection tests, and attachments to whatever your spatial subdivision scheme is to make ray tracing fast.&#xD;&#xA;&#xD;&#xA;In ray tracing, when testing ray intersection with an object in the world, you often transform the ray from world-space into the model space of that object. You then do intersection tests in the space of the mesh. That way, you're not transforming thousands of vertices or whatever for each ray intersection test. Once you get the intersection point+normal, you can transform those back into world-space to do world-space computations.&#xD;&#xA;&#xD;&#xA;This also allows you to have a single &quot;mesh&quot; for basic objects like spheres and cubes. Scales in the model transform can be used to stretch spheres and cubes, thus allowing you to create a sphere/cube of any size. Also any rectangular parallelopiped. Or really, any parallelogram." ContentLicense="CC BY-SA 4.0" />
  <row Id="35722" PostHistoryTypeId="2" PostId="12393" RevisionGUID="bf3d9452-57c9-4031-94bb-b71a5349a815" CreationDate="2021-12-07T16:59:33.863" UserId="17638" Text="I've stumbled into Optix samples that define their own intersection programs to define how primitives intersect (or don't) with a ray, and others (mostly those only dealing with triangle meshes) [that don't](https://gitlab.com/ingowald/optix7course/-/blob/iw/offline/example04_firstTriangleMesh/devicePrograms.cu). &#xD;&#xA;&#xD;&#xA;Maybe I haven't really figured out exactly *what* is hardware accelerated when we write programs using Optix, but I would've guessed that checking the intersection is the costly (and thus hardware accelerated) part. So why are we allowed to write our own software intersection programs? Maybe I'm not really understanding how the hardware acceleration of raytracing works?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35724" PostHistoryTypeId="1" PostId="12393" RevisionGUID="bf3d9452-57c9-4031-94bb-b71a5349a815" CreationDate="2021-12-07T16:59:33.863" UserId="17638" Text="Are intersections still hardware accelerated if we define a custom intersection program in Optix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35725" PostHistoryTypeId="3" PostId="12393" RevisionGUID="bf3d9452-57c9-4031-94bb-b71a5349a815" CreationDate="2021-12-07T16:59:33.863" UserId="17638" Text="|raytracing|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35726" PostHistoryTypeId="2" PostId="12394" RevisionGUID="4570bf68-1fea-4152-81c5-267a621732bc" CreationDate="2021-12-07T17:41:15.667" UserId="13321" Text="Raytracing cores can generally do two hardware accelerated things:&#xD;&#xA;&#xD;&#xA;1) Test an intersection between a triangle and a ray.&#xD;&#xA;&#xD;&#xA;2) Traverse a BVH (Basically to test an intersection between a bounding boxes and a ray).&#xD;&#xA;&#xD;&#xA;When things are raytraced we don't typically loop through every triangle and test each one. Instead the triangles are placed into a BVH (https://en.wikipedia.org/wiki/Bounding_volume_hierarchy) which is a set of boxes which partition the triangles. We first test the ray against this BVH as it allows us to quickly ignore large sets triangles.&#xD;&#xA;&#xD;&#xA;Eg, if you have a box with a million triangles inside and the ray doesn't intersect the box you know it won't intersect any of the triangles either using only one test.&#xD;&#xA;&#xD;&#xA;If you want to intersect something which isn't a triangle, for example a curve (for hair) or a sphere, you can write your own non-hardware accelerated program which will still benifit from traversing the BVH but will call your intersection program to test individual primitives.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35728" PostHistoryTypeId="5" PostId="12394" RevisionGUID="edf26e6c-a142-48bb-b20d-c1be0bc4e1ba" CreationDate="2021-12-07T18:05:35.870" UserId="13321" Comment="deleted 2 characters in body" Text="Raytracing cores can generally do two hardware accelerated things:&#xD;&#xA;&#xD;&#xA;1) Test an intersection between a triangle and a ray.&#xD;&#xA;&#xD;&#xA;2) Traverse a BVH (Basically to test an intersection between bounding boxes and a ray).&#xD;&#xA;&#xD;&#xA;When things are raytraced we don't typically loop through every triangle and test each one. Instead the triangles are placed into a BVH (https://en.wikipedia.org/wiki/Bounding_volume_hierarchy) which is a set of boxes which partition the triangles. We first test the ray against this BVH as it allows us to quickly ignore large sets triangles.&#xD;&#xA;&#xD;&#xA;Eg, if you have a box with a million triangles inside and the ray doesn't intersect the box you know it won't intersect any of the triangles either using only one test.&#xD;&#xA;&#xD;&#xA;If you want to intersect something which isn't a triangle, for example a curve (for hair) or a sphere, you can write your own non-hardware accelerated program which will still benifit from traversing the BVH but will call your intersection program to test individual primitives.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35729" PostHistoryTypeId="2" PostId="12395" RevisionGUID="856b3ac2-c106-4e69-9c08-c1aeddac000e" CreationDate="2021-12-09T13:13:42.153" UserId="17223" Text="When working with Graphics APIs like OpenGL its common to use an index face set model. That is, multiple faces share adjacent / overlapping vertices by using a list of indices.&#xD;&#xA;&#xD;&#xA;Most game engines like Unity come with an integrated lightmapper that provides automatic UV unwrapping (UVs for lightmaps are usually different from those for the albedo texture).&#xD;&#xA;&#xD;&#xA;However, automatic UV unwrapping (or UV unwrapping in general) means almost certainly seams which means a single vertex (along the seam) must have multiple UV coordinates (one for each face) if the faces are laid out in different charts in the UV atlas.&#xD;&#xA;&#xD;&#xA;How is this dealt with in like Blender or Unity? Does the process of UV unwrapping add more vertices and modify the model? At least I'm not aware that UV unwrapping in Unity for lightmap generation changes my model.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35731" PostHistoryTypeId="1" PostId="12395" RevisionGUID="856b3ac2-c106-4e69-9c08-c1aeddac000e" CreationDate="2021-12-09T13:13:42.153" UserId="17223" Text="Does automatic UV unwrapping work with an indexed face set model?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35732" PostHistoryTypeId="3" PostId="12395" RevisionGUID="856b3ac2-c106-4e69-9c08-c1aeddac000e" CreationDate="2021-12-09T13:13:42.153" UserId="17223" Text="|texture|mesh|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35734" PostHistoryTypeId="50" PostId="9192" RevisionGUID="d546384d-05af-40ef-9155-65ced8352b0e" CreationDate="2021-12-10T03:02:20.167" UserId="-1" />
  <row Id="35735" PostHistoryTypeId="2" PostId="12396" RevisionGUID="43d8fc37-098b-4ba5-8aa2-339a65c32a30" CreationDate="2021-12-10T07:01:25.720" UserId="11224" Text="CodeBlocks offers an example program in C, that uses OpenGL. It draws a single multicoloured rotating triangle. I have been building on this example. I am a novice in C and in OpenGL. I believe that I am using an old style of OpenGL coding (possibly called &quot;Immediate Mode ?&quot;) and I am trying to keep things as simple as possible. For example, I am not, to my knowledge, using VBOs, nor VAOs, nor GLSL. I am also not, as far as I know, using any helper libraries (if that's a right way to say it), such as GLEW, GLFW, GLut, etc.&#xD;&#xA;&#xD;&#xA;I notice that the sides of the triangles are more jagged than they need to be, given the resolution of my laptop screen. Even if no multisampling were used (and I am not yet trying to use it), much smaller &quot;jaggies&quot; could be achieved, if OpenGL's raster array really corresponded to the physical pixel array. I took a &quot;print screen&quot; and opened it in MS Paint, saving it as a .bmp. When I zoomed in, it seemed that multisampling *had* been used, but to smooth the edges of the large jaggies ! If you see what I mean.&#xD;&#xA;&#xD;&#xA;My question is, how can I use the maximum resolution of the screen ?&#xD;&#xA;&#xD;&#xA;Here are some excerpts from the code:&#xD;&#xA;&#xD;&#xA;    #include &lt;windows.h&gt;&#xD;&#xA;    #include &lt;gl/gl.h&gt;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    &#xD;&#xA;    int WINAPI WinMain(HINSTANCE hInstance,&#xD;&#xA;                       HINSTANCE hPrevInstance,&#xD;&#xA;                       LPSTR lpCmdLine,&#xD;&#xA;                       int nCmdShow)&#xD;&#xA;    {&#xD;&#xA;        WNDCLASSEX wcex;&#xD;&#xA;        HWND hwnd;&#xD;&#xA;        HDC hDC;&#xD;&#xA;        HGLRC hRC;&#xD;&#xA;        MSG msg;&#xD;&#xA;        BOOL bQuit = FALSE;&#xD;&#xA;    &#xD;&#xA;        const int width = 768;&#xD;&#xA;        const int height = 768;&#xD;&#xA;    &#xD;&#xA;        /* register window class */&#xD;&#xA;        wcex.cbSize = sizeof(WNDCLASSEX);&#xD;&#xA;        wcex.style = CS_OWNDC;&#xD;&#xA;        wcex.lpfnWndProc = WindowProc;&#xD;&#xA;        wcex.cbClsExtra = 0;&#xD;&#xA;        wcex.cbWndExtra = 0;&#xD;&#xA;        wcex.hInstance = hInstance;&#xD;&#xA;        wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);&#xD;&#xA;        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);&#xD;&#xA;        wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);&#xD;&#xA;        wcex.lpszMenuName = NULL;&#xD;&#xA;        wcex.lpszClassName = &quot;GLSample&quot;;&#xD;&#xA;        wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if (!RegisterClassEx(&amp;wcex))&#xD;&#xA;            return 0;&#xD;&#xA;    &#xD;&#xA;        /* create main window */&#xD;&#xA;        hwnd = CreateWindowEx(0,&#xD;&#xA;                              &quot;GLSample&quot;,&#xD;&#xA;                              &quot;OpenGL Sample&quot;,&#xD;&#xA;                              WS_OVERLAPPEDWINDOW,&#xD;&#xA;                              CW_USEDEFAULT,&#xD;&#xA;                              CW_USEDEFAULT,&#xD;&#xA;                              width,&#xD;&#xA;                              height,&#xD;&#xA;                              NULL,&#xD;&#xA;                              NULL,&#xD;&#xA;                              hInstance,&#xD;&#xA;                              NULL);&#xD;&#xA;    &#xD;&#xA;        ShowWindow(hwnd, nCmdShow);&#xD;&#xA;    &#xD;&#xA;        /* enable OpenGL for the window */&#xD;&#xA;        EnableOpenGL(hwnd, &amp;hDC, &amp;hRC);&#xD;&#xA;        &#xD;&#xA;        etc..&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and the EnableOpenGL function:&#xD;&#xA;&#xD;&#xA;    void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)&#xD;&#xA;    {&#xD;&#xA;        PIXELFORMATDESCRIPTOR pfd;&#xD;&#xA;    &#xD;&#xA;        int iFormat;&#xD;&#xA;    &#xD;&#xA;        /* get the device context (DC) */&#xD;&#xA;        *hDC = GetDC(hwnd);&#xD;&#xA;    &#xD;&#xA;        /* set the pixel format for the DC */&#xD;&#xA;        ZeroMemory(&amp;pfd, sizeof(pfd));&#xD;&#xA;    &#xD;&#xA;        pfd.nSize = sizeof(pfd);&#xD;&#xA;        pfd.nVersion = 1;&#xD;&#xA;        pfd.dwFlags = PFD_DRAW_TO_WINDOW |&#xD;&#xA;                      PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;&#xD;&#xA;        pfd.iPixelType = PFD_TYPE_RGBA;&#xD;&#xA;        pfd.cColorBits = 24;&#xD;&#xA;        pfd.cDepthBits = 16;&#xD;&#xA;        pfd.iLayerType = PFD_MAIN_PLANE;&#xD;&#xA;    &#xD;&#xA;        iFormat = ChoosePixelFormat(*hDC, &amp;pfd);&#xD;&#xA;    &#xD;&#xA;        SetPixelFormat(*hDC, iFormat, &amp;pfd);&#xD;&#xA;    &#xD;&#xA;        /* create and enable the render context (RC) */&#xD;&#xA;        *hRC = wglCreateContext(*hDC);&#xD;&#xA;    &#xD;&#xA;        wglMakeCurrent(*hDC, *hRC);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35737" PostHistoryTypeId="1" PostId="12396" RevisionGUID="43d8fc37-098b-4ba5-8aa2-339a65c32a30" CreationDate="2021-12-10T07:01:25.720" UserId="11224" Text="How to use maximum resolution (pixel density) with OpenGL in MS Windows" ContentLicense="CC BY-SA 4.0" />
  <row Id="35738" PostHistoryTypeId="3" PostId="12396" RevisionGUID="43d8fc37-098b-4ba5-8aa2-339a65c32a30" CreationDate="2021-12-10T07:01:25.720" UserId="11224" Text="|opengl|rasterizer|pixels|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35739" PostHistoryTypeId="5" PostId="12396" RevisionGUID="30804aa0-d239-4bbe-9be4-d7783d22a6f0" CreationDate="2021-12-10T12:09:24.897" UserId="11224" Comment="added 273 characters in body" Text="CodeBlocks offers an example program in C, that uses OpenGL. It draws a single multicoloured rotating triangle. I have been building on this example. I am a novice in C and in OpenGL. I believe that I am using an old style of OpenGL coding (possibly called &quot;Immediate Mode ?&quot;) and I am trying to keep things as simple as possible. For example, I am not, to my knowledge, using VBOs, nor VAOs, nor GLSL. I am also not, as far as I know, using any helper libraries (if that's a right way to say it), such as GLEW, GLFW, GLut, etc.&#xD;&#xA;&#xD;&#xA;I notice that the sides of the triangles are more jagged than they need to be, given the resolution of my laptop screen. Even if no multisampling were used (and I am not yet trying to use it), much smaller &quot;jaggies&quot; could be achieved, if OpenGL's raster array really corresponded to the physical pixel array. I took a &quot;print screen&quot; and opened it in MS Paint, saving it as a .bmp. When I zoomed in, it seemed that multisampling *had* been used, but to smooth the edges of the large jaggies ! If you see what I mean.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Here is a picture:&#xD;&#xA;[![Example][1]][1]&#xD;&#xA;&#xD;&#xA;This shows that the text on the left (which is not from my OpenGL window) is rendered at a higher resolution than my triangley object on the right (which is in my OpenGL window).&#xD;&#xA;&#xD;&#xA;My question is, how can I use the maximum resolution of the screen ?&#xD;&#xA;&#xD;&#xA;Here are some excerpts from the code:&#xD;&#xA;&#xD;&#xA;    #include &lt;windows.h&gt;&#xD;&#xA;    #include &lt;gl/gl.h&gt;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    &#xD;&#xA;    int WINAPI WinMain(HINSTANCE hInstance,&#xD;&#xA;                       HINSTANCE hPrevInstance,&#xD;&#xA;                       LPSTR lpCmdLine,&#xD;&#xA;                       int nCmdShow)&#xD;&#xA;    {&#xD;&#xA;        WNDCLASSEX wcex;&#xD;&#xA;        HWND hwnd;&#xD;&#xA;        HDC hDC;&#xD;&#xA;        HGLRC hRC;&#xD;&#xA;        MSG msg;&#xD;&#xA;        BOOL bQuit = FALSE;&#xD;&#xA;    &#xD;&#xA;        const int width = 768;&#xD;&#xA;        const int height = 768;&#xD;&#xA;    &#xD;&#xA;        /* register window class */&#xD;&#xA;        wcex.cbSize = sizeof(WNDCLASSEX);&#xD;&#xA;        wcex.style = CS_OWNDC;&#xD;&#xA;        wcex.lpfnWndProc = WindowProc;&#xD;&#xA;        wcex.cbClsExtra = 0;&#xD;&#xA;        wcex.cbWndExtra = 0;&#xD;&#xA;        wcex.hInstance = hInstance;&#xD;&#xA;        wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);&#xD;&#xA;        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);&#xD;&#xA;        wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);&#xD;&#xA;        wcex.lpszMenuName = NULL;&#xD;&#xA;        wcex.lpszClassName = &quot;GLSample&quot;;&#xD;&#xA;        wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if (!RegisterClassEx(&amp;wcex))&#xD;&#xA;            return 0;&#xD;&#xA;    &#xD;&#xA;        /* create main window */&#xD;&#xA;        hwnd = CreateWindowEx(0,&#xD;&#xA;                              &quot;GLSample&quot;,&#xD;&#xA;                              &quot;OpenGL Sample&quot;,&#xD;&#xA;                              WS_OVERLAPPEDWINDOW,&#xD;&#xA;                              CW_USEDEFAULT,&#xD;&#xA;                              CW_USEDEFAULT,&#xD;&#xA;                              width,&#xD;&#xA;                              height,&#xD;&#xA;                              NULL,&#xD;&#xA;                              NULL,&#xD;&#xA;                              hInstance,&#xD;&#xA;                              NULL);&#xD;&#xA;    &#xD;&#xA;        ShowWindow(hwnd, nCmdShow);&#xD;&#xA;    &#xD;&#xA;        /* enable OpenGL for the window */&#xD;&#xA;        EnableOpenGL(hwnd, &amp;hDC, &amp;hRC);&#xD;&#xA;        &#xD;&#xA;        etc..&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and the EnableOpenGL function:&#xD;&#xA;&#xD;&#xA;    void EnableOpenGL(HWND hwnd, HDC* hDC, HGLRC* hRC)&#xD;&#xA;    {&#xD;&#xA;        PIXELFORMATDESCRIPTOR pfd;&#xD;&#xA;    &#xD;&#xA;        int iFormat;&#xD;&#xA;    &#xD;&#xA;        /* get the device context (DC) */&#xD;&#xA;        *hDC = GetDC(hwnd);&#xD;&#xA;    &#xD;&#xA;        /* set the pixel format for the DC */&#xD;&#xA;        ZeroMemory(&amp;pfd, sizeof(pfd));&#xD;&#xA;    &#xD;&#xA;        pfd.nSize = sizeof(pfd);&#xD;&#xA;        pfd.nVersion = 1;&#xD;&#xA;        pfd.dwFlags = PFD_DRAW_TO_WINDOW |&#xD;&#xA;                      PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;&#xD;&#xA;        pfd.iPixelType = PFD_TYPE_RGBA;&#xD;&#xA;        pfd.cColorBits = 24;&#xD;&#xA;        pfd.cDepthBits = 16;&#xD;&#xA;        pfd.iLayerType = PFD_MAIN_PLANE;&#xD;&#xA;    &#xD;&#xA;        iFormat = ChoosePixelFormat(*hDC, &amp;pfd);&#xD;&#xA;    &#xD;&#xA;        SetPixelFormat(*hDC, iFormat, &amp;pfd);&#xD;&#xA;    &#xD;&#xA;        /* create and enable the render context (RC) */&#xD;&#xA;        *hRC = wglCreateContext(*hDC);&#xD;&#xA;    &#xD;&#xA;        wglMakeCurrent(*hDC, *hRC);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sa9SN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35741" PostHistoryTypeId="2" PostId="12397" RevisionGUID="ef1e1622-f9ea-41ff-9131-a69310f1ef2a" CreationDate="2021-12-11T07:04:28.000" UserId="48" Text="You might need to use a setting to tell Windows that your program is DPI-aware, meaning that it can adjust to very high-resolution screens like many current-gen laptops have.&#xA;&#xA;Lots of older programs have trouble with such high resolutions, so without the DPI awareness flag, Windows will tell the program the resolution is lower, and then upscale the whole window. That looks like it might be what's happening to your OpenGL app.&#xA;&#xA;The simplest way to do this is to add a call to [`SetProcessDPIAware()`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiaware) during your program's startup, before creating the window. You might also want to increase the hard-coded width and height values.&#xA;&#xA;The other way to do it is by adding an XML &quot;manifest&quot; file that gets linked into your app's .exe file, but it might be hard to get that working in Code::Blocks if it doesn't have it built in.&#xA;&#xA;For more information: [Setting the default DPI awareness for a process](https://docs.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process)" ContentLicense="CC BY-SA 4.0" />
  <row Id="35743" PostHistoryTypeId="50" PostId="9549" RevisionGUID="dd9c766d-19b4-4136-ade5-8e7cd01f0692" CreationDate="2021-12-11T13:04:00.327" UserId="-1" />
  <row Id="35744" PostHistoryTypeId="50" PostId="2516" RevisionGUID="a12f60bd-ccd5-4461-882d-b14f46eee8f1" CreationDate="2021-12-11T16:05:35.567" UserId="-1" />
  <row Id="35745" PostHistoryTypeId="50" PostId="10748" RevisionGUID="a644834d-301f-46c7-b2dc-4902b93f54ba" CreationDate="2021-12-12T17:04:15.360" UserId="-1" />
  <row Id="35746" PostHistoryTypeId="2" PostId="12398" RevisionGUID="8b9bd9e8-0840-4d25-8239-c87a565779f3" CreationDate="2021-12-12T17:19:41.813" UserId="48" Text="&gt; Does the process of UV unwrapping add more vertices and modify the model?&#xD;&#xA;&#xD;&#xA;Yes, in general. The final model that is rendered, i.e. what the GPU sees, will have vertices with the same position but differing UV values. The triangles on one side of the seam will reference one set of vertices, and on the other side of the seam reference different vertices.&#xD;&#xA;&#xD;&#xA;The same thing happens when &quot;hard edges&quot; are added to the model: you have vertices with the same position but differing normals. In fact this can happen with any vertex attribute, but UVs and normals are the most common cases.&#xD;&#xA;&#xD;&#xA;The way that models are represented in an editing tool like Blender can be different, though. To facilitate editing operations, they will have data structures that are able to keep track of the fact that it's conceptually one vertex even if it has multiple UV or normal values. For example, they might store separate lists of positions, UVs, and normals, and let each face have separate indices for the position, UV, and normal of each face-vertex. That way, any modeling operations that move the vertex position will keep all the faces welded together properly, since they are all indexing the same element of the positions array. (I don't know if this is actually how Blender does it; it's just an example.)&#xD;&#xA;&#xD;&#xA;The engine's lightmapping pipeline might also use such a representation internally for constructing the UV unwrap. But ultimately, before rendering, the engine's asset pipeline will convert the model into the GPU-ready format with multiple vertices and one index per face-vertex (as well as doing various other cleanup/optimization on the model)." ContentLicense="CC BY-SA 4.0" />
  <row Id="35752" PostHistoryTypeId="50" PostId="12331" RevisionGUID="1a0f18c1-95aa-44b5-84b4-8c7736e6be75" CreationDate="2021-12-13T15:11:36.090" UserId="-1" />
  <row Id="35753" PostHistoryTypeId="50" PostId="10045" RevisionGUID="b80c7c8d-2bc3-43b1-bf30-95dea1e46978" CreationDate="2021-12-13T21:10:10.937" UserId="-1" />
  <row Id="35754" PostHistoryTypeId="50" PostId="2146" RevisionGUID="0fd4c220-1828-494f-94b6-a8bef535337b" CreationDate="2021-12-14T09:05:25.567" UserId="-1" />
  <row Id="35755" PostHistoryTypeId="2" PostId="12400" RevisionGUID="3b3314cf-236e-4f55-b7ae-3fab08ad83a9" CreationDate="2021-12-14T09:32:29.207" UserId="13273" Text="My scenario is a Solar system with satellites. Therefor objects can be very close to the camera while a planet for example is in background far away. This setup causes problems with the depthbuffer precision, because to render the whole scenario I would need to put my nearplane of the projection matrix very close to zero to capture the satellite, while the farplane is extremely far away. This causes depth fighting (flickering). To better use the depthbuffer I calculated for different areas the optimal near and far plane values (span) shown in figure below.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Depending on the number of spans the depthbuffer is split in the following way:**&#xD;&#xA;The depthbuffer values which go from 0 to 1 is equally split into #number of spans with equal size. That means for 2 spans the first goes from 0 to 0.5 and the second starts from &gt;0.5 to 1.&#xD;&#xA;With 3 spans it would be 0 to 0.33, 0.33 to 0.66 and 0.66 to 1.&#xD;&#xA;&#xD;&#xA;This is done with the `glDepthRange()` function. I also change the projection matrix's near and far plane values to the boundaries &#xD;&#xA;&#xD;&#xA;When rendering the scenario, the depthbuffer is used very good now. All the flickering has gone. &#xD;&#xA;&#xD;&#xA;**But now I try to convert the depthbuffer values back to distance values.**&#xD;&#xA;&#xD;&#xA;To do so, I stored the span information into an vec4 array &quot;u_depthSpans[]&quot; in the following way:&#xD;&#xA;x: depthbuffer near value [0,1]. y: depthbuffer far value [0,1]. z: real distance near value. w: real distance far value. Each vec4 item in the array is one span.&#xD;&#xA;&#xD;&#xA;To calculate the distance I wrote this:&#xD;&#xA;&#xD;&#xA;    float linearDepth(float depthSample, float zNear, float zFar)                &#xD;&#xA;    {&#xD;&#xA;        depthSample = 2.0 * depthSample - 1.0;                                   &#xD;&#xA;        float zLinear = 2.0 * zNear * zFar / (zFar + zNear - depthSample * (zFar - zNear));&#xD;&#xA;        return zLinear;                                                          &#xD;&#xA;    }                                                                           &#xD;&#xA;&#xD;&#xA;    for(uint i = 0; i &lt; u_countDepthSpans; ++i)&#xD;&#xA;    {&#xD;&#xA;        if(depthBufferValue &gt;= u_depthSpans[i].x &amp;&amp; depthBufferValue &lt;= u_depthSpans[i].y)//is depth value inside span?&#xD;&#xA;        {&#xD;&#xA;            float factorDepth = (depthBufferValue - u_depthSpans[i].x) / (u_depthSpans[i].y - u_depthSpans[i].x);&#xD;&#xA;            depthReal = linearDepth(factorDepth, u_depthSpans[i].z, u_depthSpans[i].w);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;But it gives me wrong results. What am I doing wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/R9FO1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35757" PostHistoryTypeId="1" PostId="12400" RevisionGUID="3b3314cf-236e-4f55-b7ae-3fab08ad83a9" CreationDate="2021-12-14T09:32:29.207" UserId="13273" Text="splitted Depthbuffer values to distance" ContentLicense="CC BY-SA 4.0" />
  <row Id="35758" PostHistoryTypeId="3" PostId="12400" RevisionGUID="3b3314cf-236e-4f55-b7ae-3fab08ad83a9" CreationDate="2021-12-14T09:32:29.207" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35759" PostHistoryTypeId="4" PostId="12400" RevisionGUID="681f7a59-4bff-4299-887b-de2ea48cb6d4" CreationDate="2021-12-14T09:52:30.013" UserId="13273" Comment="edited title" Text="split Depthbuffer values to distance" ContentLicense="CC BY-SA 4.0" />
  <row Id="35760" PostHistoryTypeId="50" PostId="11048" RevisionGUID="7eb326b0-e922-4fa8-8c81-abec672d3ebd" CreationDate="2021-12-14T15:06:10.523" UserId="-1" />
  <row Id="35761" PostHistoryTypeId="50" PostId="8886" RevisionGUID="40bb1bf9-eb89-4366-aa27-e6c9a9c176a0" CreationDate="2021-12-14T17:01:20.120" UserId="-1" />
  <row Id="35762" PostHistoryTypeId="50" PostId="11049" RevisionGUID="b5d84dca-167b-411e-a4d5-e0346fe41d68" CreationDate="2021-12-14T18:07:55.670" UserId="-1" />
  <row Id="35763" PostHistoryTypeId="2" PostId="12401" RevisionGUID="1a60d8ca-5559-411b-859e-81ee9d77d6a0" CreationDate="2021-12-15T00:43:31.243" UserId="15955" Text="I managed to solve the problem by putting a saturate on the color input.&#xD;&#xA;&#xD;&#xA;    float4 _BloomThreshold;&#xD;&#xA;    float _BloomIntensity;&#xD;&#xA;    float _BloomScattering;&#xD;&#xA;    &#xD;&#xA;    float3 ApplyBloomThreshold(float3 color) {&#xD;&#xA;        float brightness = Max3(color.r, color.g, color.b);&#xD;&#xA;        float soft = brightness + _BloomThreshold.y;&#xD;&#xA;        soft = clamp(soft, 0.0, _BloomThreshold.z);&#xD;&#xA;        soft = soft * soft * _BloomThreshold.w;&#xD;&#xA;        float contribution = max(soft, brightness - _BloomThreshold.x);&#xD;&#xA;        contribution /= max(brightness, 0.00001);&#xD;&#xA;        return color * contribution;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float4 PreFilter(Varyings i) : SV_TARGET{&#xD;&#xA;        float3 color = pow(ApplyBloomThreshold(GetSource(i.fxUV).rgb),2);&#xD;&#xA;        return float4(saturate(color), 1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="35765" PostHistoryTypeId="2" PostId="12402" RevisionGUID="81b4429f-73a6-4c29-a3a5-16557d6d3e04" CreationDate="2021-12-15T22:32:00.647" UserId="17576" Text="I am working on a path tracing renderer, and I want to produce an sRGB image out of the HDR image buffer I get at the end of my rendering algorithm. Up until now I have worked just by clamping values, which of course works fine only for a limited range of light conditions.&#xD;&#xA;&#xD;&#xA;Now, reading around (I started [here][1], then read some of the links given in that post) I got that one way to go is (starting in linear RGB space):&#xD;&#xA;&#xD;&#xA; 1. Calculate the exposure&#xD;&#xA; 2. Scale all the values in the image by the exposure, channel by channel&#xD;&#xA; 3. Apply some tonemapping function&#xD;&#xA; 4. Gamma correct.&#xD;&#xA;&#xD;&#xA;The preferred way to calculate the exposure seems to be as the inverse of &quot;the luminance value that will saturate the sensor&quot;, computed from some average luminance value of the image; the latter in turn is obtained by computing a histogram of the log2's of all pixel's [luma][2], ignoring some percentage of values (e.g. 50% of the darkest pixels and 5% of the brightest), and computing the average of the remaining values.&#xD;&#xA;&#xD;&#xA;Another way I found was in this [answer][3] here, where the scalar factor seems to be based only on the pixel value, rather than the whole scene.&#xD;&#xA;&#xD;&#xA; 1. What's the theory behind the second method, and does it relate in any way to exposure?&#xD;&#xA; 2. Is it normal that if I apply the first method, I usually (regardless of the percentage thresholds I use) get images that are way darker than if I apply the second (although maybe a bit more realistic), or is this a smell that I'm getting something wrong in my implementation of the first method? (Additionally, the images I get by rendering my test scenes with Cycles are as bright as the images I get from my renderer using the second method, thus not nearly as dark as the ones I get from the first method.)&#xD;&#xA;&#xD;&#xA;  [1]: https://bruop.github.io/exposure/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luma_(video)&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/6311/17576" ContentLicense="CC BY-SA 4.0" />
  <row Id="35767" PostHistoryTypeId="1" PostId="12402" RevisionGUID="81b4429f-73a6-4c29-a3a5-16557d6d3e04" CreationDate="2021-12-15T22:32:00.647" UserId="17576" Text="Confusion about HDR image pipeline" ContentLicense="CC BY-SA 4.0" />
  <row Id="35768" PostHistoryTypeId="3" PostId="12402" RevisionGUID="81b4429f-73a6-4c29-a3a5-16557d6d3e04" CreationDate="2021-12-15T22:32:00.647" UserId="17576" Text="|rendering|color|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35769" PostHistoryTypeId="50" PostId="8321" RevisionGUID="7ace54f8-174e-43be-aa21-cc0334d7c610" CreationDate="2021-12-16T07:05:50.580" UserId="-1" />
  <row Id="35770" PostHistoryTypeId="50" PostId="8695" RevisionGUID="9dabb918-ddb9-4595-a607-80310f016c45" CreationDate="2021-12-16T22:06:35.590" UserId="-1" />
  <row Id="35771" PostHistoryTypeId="2" PostId="12403" RevisionGUID="8dc29e3b-caa6-45b1-96b2-6130c7856d06" CreationDate="2021-12-17T04:54:08.000" UserId="17686" Text="I've often seen images that look like the following example&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FOwpF.png&#xD;&#xA;&#xD;&#xA;Q1) is there a term for such an image?&#xD;&#xA;&#xD;&#xA;Q2) What common software is used to convert a real photo (e.g. human face) to be composed of such shapes? (or even an online service)" ContentLicense="CC BY-SA 4.0" />
  <row Id="35773" PostHistoryTypeId="1" PostId="12403" RevisionGUID="8dc29e3b-caa6-45b1-96b2-6130c7856d06" CreationDate="2021-12-17T04:54:08.000" UserId="17686" Text="Image made of shapes - terminology + software?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35774" PostHistoryTypeId="3" PostId="12403" RevisionGUID="8dc29e3b-caa6-45b1-96b2-6130c7856d06" CreationDate="2021-12-17T04:54:08.000" UserId="17686" Text="|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35775" PostHistoryTypeId="2" PostId="12404" RevisionGUID="424f4cf8-f18a-40a0-b7dd-4a3c1e4dc215" CreationDate="2021-12-17T08:57:22.400" UserId="13975" Text="I just posted this to SO but the question got closed, so I hope it's OK if I try it again here.  They say &quot;we don’t allow questions seeking recommendations for books, tools, software libraries&quot; so I'll only ask for help on an algorithm.&#xD;&#xA;&#xD;&#xA;What's the most effective way to perform a simple extrusion effect to composite cubic Bezier curves (which I'll refer to as composite curves), like they are used in SVGs, similar to figure (5) in the picture below?  I want the result as a composite curve, not just the rasterization.&#xD;&#xA;&#xD;&#xA;![](https://wiki.inkscape.org/wiki/images/d/df/Extrude.png)&#xD;&#xA;&#xD;&#xA;The mathematical formulation for this would be [dilation](https://en.wikipedia.org/wiki/Dilation_(morphology)) with a structural element in the form of a line segment (which can be w.l.o.g. be the unit interval [0, 1] embedded in R^2).  So given a set A of points in the plane whose boundary can be described by a composite curve, I am looking for a composite curve describing the set A' := [p ∈ R^2 : ∃q ∈ A : p − q ∈ [0, 1]] of points which are to the right of a point from A, but not further than distance 1.&#xD;&#xA;&#xD;&#xA;I imagine one must first find all points on a Bezier segment where the derivative of the curve is horizontal (unless the curve is a horizontal straight line) and divide the curve there.  Then horizontal straight lines are inserted between certain (new or old) curve segments.  If the shape has holes, the holes are just duplicated, moved to the right and intersected with the original hole.  Possibly related to [finding the points of inflection.](https://stackoverflow.com/questions/11465703/finding-points-of-inflection-on-a-2d-bezier-curve)" ContentLicense="CC BY-SA 4.0" />
  <row Id="35777" PostHistoryTypeId="1" PostId="12404" RevisionGUID="424f4cf8-f18a-40a0-b7dd-4a3c1e4dc215" CreationDate="2021-12-17T08:57:22.400" UserId="13975" Text="Extrusion Algorithm For Bezier Curves" ContentLicense="CC BY-SA 4.0" />
  <row Id="35778" PostHistoryTypeId="3" PostId="12404" RevisionGUID="424f4cf8-f18a-40a0-b7dd-4a3c1e4dc215" CreationDate="2021-12-17T08:57:22.400" UserId="13975" Text="|algorithm|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35779" PostHistoryTypeId="5" PostId="12404" RevisionGUID="3ecba592-2da6-4136-9810-1eded858aebe" CreationDate="2021-12-17T09:03:34.380" UserId="13975" Comment="added 298 characters in body" Text="I just posted this to SO but the question got closed, so I hope it's OK if I try it again here.  They say &quot;we don’t allow questions seeking recommendations for books, tools, software libraries&quot; so I'll only ask for help on the algorithm.&#xD;&#xA;&#xD;&#xA;What's the best way to perform a simple extrusion effect to composite cubic Bezier curves (which I'll refer to as composite curves), like they are used in SVGs, similar to figure (5) in the picture below?  I want the result as a composite curve, not just the rasterization.&#xD;&#xA;&#xD;&#xA;![](https://wiki.inkscape.org/wiki/images/d/df/Extrude.png)&#xD;&#xA;&#xD;&#xA;The mathematical formulation for this would be [dilation](https://en.wikipedia.org/wiki/Dilation_(morphology)) with a structural element in the form of a line segment (which can be w.l.o.g. be the unit interval $[0, 1]$ embedded in $\mathbf{R}^2$).  So given a set $A$ of points in the plane whose boundary can be described by a composite curve, I am looking for a composite curve describing the set $A':=\{p+[0,1]:p\in A\}$ of points which are to the right of a point from $A$, but not further than distance $1$.&#xD;&#xA;&#xD;&#xA;I imagine one must first find all points on a Bezier segment where the derivative of the curve is horizontal (unless the curve is a horizontal straight line) and divide the curve there.  Then horizontal straight lines are inserted between certain (new or old) curve segments.  If the shape has holes, the holes are just duplicated, moved to the right and intersected with the original hole.  Possibly related to [finding the points of inflection.](https://stackoverflow.com/questions/11465703/finding-points-of-inflection-on-a-2d-bezier-curve)&#xD;&#xA;&#xD;&#xA;My approach would be sampling the derivative of each curve segment at N points, look if the x-component of the derivative switches sign between two samples, then perform some kind of root finding algorithm to further contain the point where the sign switch happens.  Does that sound reasonable?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35785" PostHistoryTypeId="50" PostId="10754" RevisionGUID="e6677275-7c7a-4421-a07a-99226d65bff9" CreationDate="2021-12-17T21:00:00.140" UserId="-1" />
  <row Id="35786" PostHistoryTypeId="2" PostId="12406" RevisionGUID="07443b7f-df49-4f29-956d-152037abbe94" CreationDate="2021-12-17T21:10:28.583" UserId="17690" Text="THREE.js recently dropped support for THREE.Geometry in favor of exclusively THREE.BufferGeometry. I'm trying to decide which paradigm to teach in my computer graphics course to best provide students with an intuition for the field (I don't mind teaching using an old version of THREE.js if this provides a better understanding).&#xD;&#xA;&#xD;&#xA;THREE.Geometry describes 3d geometry in terms of an array of vertices and an array of faces, where each face is a triple of indices into the array of vertices. So for instance, a tetrahedron could be represented as: &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;geometry.vertices.push(&#xD;&#xA;    new THREE.Vector3(1, 1, 1),//a&#xD;&#xA;    new THREE.Vector3(-1, -1, 1),//b&#xD;&#xA;    new THREE.Vector3(-1, 1, -1),//c&#xD;&#xA;    new THREE.Vector3(1, -1, -1)//d&#xD;&#xA;)&#xD;&#xA;geometry.faces.push(&#xD;&#xA;    new THREE.Face3(2, 1, 0), &#xD;&#xA;    new THREE.Face3(0, 3, 2),&#xD;&#xA;    new THREE.Face3(1, 3, 0), &#xD;&#xA;    new THREE.Face3(2, 3, 1)&#xD;&#xA;)&#xD;&#xA;```&#xD;&#xA;(code from &lt;https://sbcode.net/threejs/geometry-to-buffergeometry/&gt;)&#xD;&#xA;&#xD;&#xA;THREE.BufferGeometry describes 3d geometry as just an array of vertices, where vertices are grouped in threes and automatically turned into faces. If vertices are reused, they have to be listed again.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const points = [&#xD;&#xA;    new THREE.Vector3(-1, 1, -1),//c&#xD;&#xA;    new THREE.Vector3(-1, -1, 1),//b&#xD;&#xA;    new THREE.Vector3(1, 1, 1),//a   &#xD;&#xA;&#xD;&#xA;    new THREE.Vector3(1, 1, 1),//a    &#xD;&#xA;    new THREE.Vector3(1, -1, -1),//d  &#xD;&#xA;    new THREE.Vector3(-1, 1, -1),//c&#xD;&#xA;&#xD;&#xA;    new THREE.Vector3(-1, -1, 1),//b&#xD;&#xA;    new THREE.Vector3(1, -1, -1),//d  &#xD;&#xA;    new THREE.Vector3(1, 1, 1),//a&#xD;&#xA;&#xD;&#xA;    new THREE.Vector3(-1, 1, -1),//c&#xD;&#xA;    new THREE.Vector3(1, -1, -1),//d    &#xD;&#xA;    new THREE.Vector3(-1, -1, 1),//b&#xD;&#xA;]&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(code from &lt;https://sbcode.net/threejs/geometry-to-buffergeometry/&gt;)&#xD;&#xA;&#xD;&#xA;Which paradigm is better for first coming to understand computer graphics? My understanding was that the faces-as-lists-of-vertex-indices was a common way of representing 3d geometry, but perhaps the lists-of-vertex-coordinates is more fundamental?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35788" PostHistoryTypeId="1" PostId="12406" RevisionGUID="07443b7f-df49-4f29-956d-152037abbe94" CreationDate="2021-12-17T21:10:28.583" UserId="17690" Text="Which provides better intuition: THREE.Geometry or THREE.BufferGeometry?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35789" PostHistoryTypeId="3" PostId="12406" RevisionGUID="07443b7f-df49-4f29-956d-152037abbe94" CreationDate="2021-12-17T21:10:28.583" UserId="17690" Text="|3d|geometry|vertex-buffer-object|data-structure|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35791" PostHistoryTypeId="2" PostId="12407" RevisionGUID="1fdd3ad9-6fcd-40e7-8282-1667bb7e8c1d" CreationDate="2021-12-18T03:34:13.700" UserId="17686" Text="It's called low poly&#xD;&#xA;&#xD;&#xA;https://en.wikipedia.org/wiki/Low_poly&#xD;&#xA;&#xD;&#xA;(thanks to a user on GD.SE)&#xD;&#xA;https://graphicdesign.stackexchange.com/questions/155190/image-made-of-shapes-terminology-software&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35793" PostHistoryTypeId="50" PostId="5697" RevisionGUID="02f8dc02-7f4a-4da6-a176-bc37aae546c8" CreationDate="2021-12-18T07:03:45.383" UserId="-1" />
  <row Id="35794" PostHistoryTypeId="5" PostId="12402" RevisionGUID="ad0197e1-5afa-4fd7-b2b2-a126a70b5821" CreationDate="2021-12-18T21:36:59.867" UserId="17576" Comment="added 3260 characters in body" Text="I am working on a path tracing renderer, and I want to produce an sRGB image out of the HDR image buffer I get at the end of my rendering algorithm. Up until now I have worked just by clamping values, which of course works fine only for a limited range of light conditions.&#xD;&#xA;&#xD;&#xA;Now, reading around (I started [here][1], then read some of the links given in that post) I got that one way to go is (starting in linear RGB space):&#xD;&#xA;&#xD;&#xA; 1. Calculate the exposure&#xD;&#xA; 2. Scale all the values in the image by the exposure, channel by channel&#xD;&#xA; 3. Apply some tonemapping function&#xD;&#xA; 4. Gamma correct.&#xD;&#xA;&#xD;&#xA;The preferred way to calculate the exposure seems to be as the inverse of &quot;the luminance value that will saturate the sensor&quot;, computed from some average luminance value of the image; the latter in turn is obtained by computing a histogram of the log2's of all pixel's [luma][2], ignoring some percentage of values (e.g. 50% of the darkest pixels and 5% of the brightest), and computing the average of the remaining values.&#xD;&#xA;&#xD;&#xA;Another way I found was in this [answer][3] here, where the scalar factor seems to be based only on the pixel value, rather than the whole scene.&#xD;&#xA;**EDIT:** &#xD;&#xA;Here, it seems to me that the steps 2 and 3 above are replaced by a different procedure:&#xD;&#xA;&#xD;&#xA; - The color gets `mix`ed between its luminance and a $\left(\frac{m-0.18}{m}\right)^{20}$, where $m$ is the maximum value in the RGB channels&#xD;&#xA; - Tonemapping is applied only to $m'$ = ($m$ after the above `mix`)&#xD;&#xA; - The color channels are multiplied by a factor equal to $f(m')/m'$, where $f$ is the tonemapping function.&#xD;&#xA;&#xD;&#xA; 1. What's the theory behind the second approach, and does it relate in any way to exposure?&#xD;&#xA;&#xD;&#xA; 2. Is it normal that if I apply the first method, I usually (regardless of the percentage thresholds I use) get images that are way darker than if I apply the second (although maybe a bit more realistic), or is this a smell that I'm getting something wrong in my implementation of the first method? (Additionally, the images I get by rendering my test scenes with Cycles are as bright as the images I get from my renderer using the second method, thus not nearly as dark as the ones I get from the first method.)&#xD;&#xA;&#xD;&#xA;Here are some examples: for reference, this is a test scene I'm using, rendered with Cycles, containing two emissive squares each of emission respectively 2, 10, 100 and 1000&#xD;&#xA;[![emission 2][4]][4]&#xD;&#xA;[![emission 10][5]][5]&#xD;&#xA;[![emission 100][6]][6]&#xD;&#xA;[![emission 1000][7]][7]&#xD;&#xA;&#xD;&#xA;Here is the same scene, with the same factors, rendered with my renderer, applying [this][8] tonemapping function directly to each color channel, after exposure-correcting (histogram-based, clamped at 50% for dark and 5% for light)&#xD;&#xA;[![2][9]][9]&#xD;&#xA;[![10][10]][10]&#xD;&#xA;[![100][11]][11]&#xD;&#xA;[![1000][12]][12]&#xD;&#xA;&#xD;&#xA;Here are the tests without exposure correction (same tonemapping):&#xD;&#xA;[![2][17]][17]&#xD;&#xA;[![10][18]][18]&#xD;&#xA;[![100][19]][19]&#xD;&#xA;[![1000][20]][20]&#xD;&#xA;&#xD;&#xA;Here, I am using the answer's method to deal with the alternative &quot;scaling&quot; (with the same tonemapping function I used for the results above).&#xD;&#xA;&#xD;&#xA;[![2][13]][13]&#xD;&#xA;[![10][14]][14]&#xD;&#xA;[![100][15]][15]&#xD;&#xA;[![1000][16]][16]&#xD;&#xA;&#xD;&#xA;The exposure-corrected gives clearly wrong results, as the 10, 100 and 1000 values all give pretty much the same output, the non-exposure-corrected one has some weird saturation values but it's perceptively the closest to Cycles' illumination levels; the answer's method flattens the background too much, and feels a bit darker than it should, at least compared to Cycles' output.&#xD;&#xA;&#xD;&#xA;At this point I'd guess that I'm applying the exposure correction wrongly. A simplified version of my code is the following:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;constexpr float a = 2.51;&#xD;&#xA;constexpr float b = 0.03;&#xD;&#xA;constexpr float c = 2.43;&#xD;&#xA;constexpr float d = 0.59;&#xD;&#xA;constexpr float e = 0.14;&#xD;&#xA;&#xD;&#xA;float expsr = this.exposure();&#xD;&#xA;&#xD;&#xA;// the image buffer contains RGB values (no alpha) in linear space&#xD;&#xA;for (size_t j = 0; j &lt; this.image_buffer.size(); ++j)&#xD;&#xA;{&#xD;&#xA;    image_buffer[j] *= expsr;&#xD;&#xA;    image_buffer[j] = (image_buffer[j] * (a * image_buffer[j] + b)) / (image_buffer[j] * (c * image_buffer[j] + d) + e);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;And afterwards I gamma-correct. Am I supposed to use the exposure value or the tone mapping function differently?&#xD;&#xA;&#xD;&#xA;  [1]: https://bruop.github.io/exposure/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luma_(video)&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/6311/17576&#xD;&#xA;  [4]: https://i.stack.imgur.com/Z25Yv.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/c4XI1.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/rpqmZ.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/YASlO.png&#xD;&#xA;  [8]: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/&#xD;&#xA;  [9]: https://i.stack.imgur.com/0SHtb.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/eL2v5.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/rwpGh.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/95QpQ.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/V2cig.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/S6l7P.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/AEFrJ.png&#xD;&#xA;  [16]: https://i.stack.imgur.com/hHeA2.png&#xD;&#xA;  [17]: https://i.stack.imgur.com/8km04.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/z22IM.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/cl0f4.png&#xD;&#xA;  [20]: https://i.stack.imgur.com/WEVyI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35795" PostHistoryTypeId="2" PostId="12408" RevisionGUID="300c736c-702d-402a-bfff-e57a8f696ece" CreationDate="2021-12-19T17:00:55.563" UserId="48" Text="Note that BufferGeometry still supports both indexed and non-indexed meshes.  It contains arrays of vertex attributes and indices, and works in non-indexed mode if the indices array is null. You can construct a mesh by setting the attributes and indices directly, as shown in [this example](https://github.com/mrdoob/three.js/blob/master/examples/webgl_buffergeometry_indexed.html).&#xA;&#xA;The tutorial you linked is setting up a non-indexed mesh using a helper method, `setFromPoints`, but only so that it can obtain flat face normals using `computeVertexNormals`. If it used an indexed mesh with shared vertices, then it would end up with smoothed normals instead.&#xA;&#xA;Indexed meshes are generally more efficient and are the preferred way of representing meshes in most cases, and I think it would still be important for your students to learn that. However, you could start with non-indexed meshes for pedagogical purposes, and introduce indices later." ContentLicense="CC BY-SA 4.0" />
  <row Id="35797" PostHistoryTypeId="5" PostId="12402" RevisionGUID="e36a100c-cd50-40c1-96a3-5a302d452587" CreationDate="2021-12-19T19:27:00.253" UserId="17576" Comment="added 4 characters in body" Text="I am working on a path tracing renderer, and I want to produce an sRGB image out of the HDR image buffer I get at the end of my rendering algorithm. Up until now I have worked just by clamping values, which of course works fine only for a limited range of light conditions.&#xD;&#xA;&#xD;&#xA;Now, reading around (I started [here][1], then read some of the links given in that post) I got that one way to go is (starting in linear RGB space):&#xD;&#xA;&#xD;&#xA; 1. Calculate the exposure&#xD;&#xA; 2. Scale all the values in the image by the exposure, channel by channel&#xD;&#xA; 3. Apply some tonemapping function&#xD;&#xA; 4. Gamma correct.&#xD;&#xA;&#xD;&#xA;The preferred way to calculate the exposure seems to be as the inverse of &quot;the luminance value that will saturate the sensor&quot;, computed from some average luminance value of the image; the latter in turn is obtained by computing a histogram of the log2's of all pixel's [luma][2], ignoring some percentage of values (e.g. 50% of the darkest pixels and 5% of the brightest), and computing the average of the remaining values.&#xD;&#xA;&#xD;&#xA;Another way I found was in this [answer][3] here, where the scalar factor seems to be based only on the pixel value, rather than the whole scene.&#xD;&#xA;**EDIT:** &#xD;&#xA;Here, it seems to me that the steps 2 and 3 above are replaced by a different procedure:&#xD;&#xA;&#xD;&#xA; - The color gets `mix`ed to its luminance by a factor of $\left(\frac{m-0.18}{m}\right)^{20}$, where $m$ is the maximum value in the RGB channels&#xD;&#xA; - Tonemapping is applied only to $m'$ = ($m$ after the above `mix`)&#xD;&#xA; - The color channels are multiplied by a factor equal to $f(m')/m'$, where $f$ is the tonemapping function.&#xD;&#xA;&#xD;&#xA; 1. What's the theory behind the second approach, and does it relate in any way to exposure?&#xD;&#xA;&#xD;&#xA; 2. Is it normal that if I apply the first method, I usually (regardless of the percentage thresholds I use) get images that are way darker than if I apply the second (although maybe a bit more realistic), or is this a smell that I'm getting something wrong in my implementation of the first method? (Additionally, the images I get by rendering my test scenes with Cycles are as bright as the images I get from my renderer using the second method, thus not nearly as dark as the ones I get from the first method.)&#xD;&#xA;&#xD;&#xA;Here are some examples: for reference, this is a test scene I'm using, rendered with Cycles, containing two emissive squares each of emission respectively 2, 10, 100 and 1000&#xD;&#xA;[![emission 2][4]][4]&#xD;&#xA;[![emission 10][5]][5]&#xD;&#xA;[![emission 100][6]][6]&#xD;&#xA;[![emission 1000][7]][7]&#xD;&#xA;&#xD;&#xA;Here is the same scene, with the same factors, rendered with my renderer, applying [this][8] tonemapping function directly to each color channel, after exposure-correcting (histogram-based, clamped at 50% for dark and 5% for light)&#xD;&#xA;[![2][9]][9]&#xD;&#xA;[![10][10]][10]&#xD;&#xA;[![100][11]][11]&#xD;&#xA;[![1000][12]][12]&#xD;&#xA;&#xD;&#xA;Here are the tests without exposure correction (same tonemapping):&#xD;&#xA;[![2][17]][17]&#xD;&#xA;[![10][18]][18]&#xD;&#xA;[![100][19]][19]&#xD;&#xA;[![1000][20]][20]&#xD;&#xA;&#xD;&#xA;Here, I am using the answer's method to deal with the alternative &quot;scaling&quot; (with the same tonemapping function I used for the results above).&#xD;&#xA;&#xD;&#xA;[![2][13]][13]&#xD;&#xA;[![10][14]][14]&#xD;&#xA;[![100][15]][15]&#xD;&#xA;[![1000][16]][16]&#xD;&#xA;&#xD;&#xA;The exposure-corrected gives clearly wrong results, as the 10, 100 and 1000 values all give pretty much the same output, the non-exposure-corrected one has some weird saturation values but it's perceptively the closest to Cycles' illumination levels; the answer's method flattens the background too much, and feels a bit darker than it should, at least compared to Cycles' output.&#xD;&#xA;&#xD;&#xA;At this point I'd guess that I'm applying the exposure correction wrongly. A simplified version of my code is the following:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;constexpr float a = 2.51;&#xD;&#xA;constexpr float b = 0.03;&#xD;&#xA;constexpr float c = 2.43;&#xD;&#xA;constexpr float d = 0.59;&#xD;&#xA;constexpr float e = 0.14;&#xD;&#xA;&#xD;&#xA;float expsr = this.exposure();&#xD;&#xA;&#xD;&#xA;// the image buffer contains RGB values (no alpha) in linear space&#xD;&#xA;for (size_t j = 0; j &lt; this.image_buffer.size(); ++j)&#xD;&#xA;{&#xD;&#xA;    image_buffer[j] *= expsr;&#xD;&#xA;    image_buffer[j] = (image_buffer[j] * (a * image_buffer[j] + b)) / (image_buffer[j] * (c * image_buffer[j] + d) + e);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;And afterwards I gamma-correct. Am I supposed to use the exposure value or the tone mapping function differently?&#xD;&#xA;&#xD;&#xA;  [1]: https://bruop.github.io/exposure/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Luma_(video)&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/6311/17576&#xD;&#xA;  [4]: https://i.stack.imgur.com/Z25Yv.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/c4XI1.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/rpqmZ.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/YASlO.png&#xD;&#xA;  [8]: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/&#xD;&#xA;  [9]: https://i.stack.imgur.com/0SHtb.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/eL2v5.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/rwpGh.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/95QpQ.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/V2cig.png&#xD;&#xA;  [14]: https://i.stack.imgur.com/S6l7P.png&#xD;&#xA;  [15]: https://i.stack.imgur.com/AEFrJ.png&#xD;&#xA;  [16]: https://i.stack.imgur.com/hHeA2.png&#xD;&#xA;  [17]: https://i.stack.imgur.com/8km04.png&#xD;&#xA;  [18]: https://i.stack.imgur.com/z22IM.png&#xD;&#xA;  [19]: https://i.stack.imgur.com/cl0f4.png&#xD;&#xA;  [20]: https://i.stack.imgur.com/WEVyI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35798" PostHistoryTypeId="2" PostId="12409" RevisionGUID="a37b9457-350b-44ae-b5d7-d9971019d5b0" CreationDate="2021-12-19T23:57:36.030" UserId="17702" Text="I am wondering how I can use perspective rendering to render a point onto a screen. An image showing perspective rendering:&#xD;&#xA;&#xD;&#xA;[![Picture of perspective rendering][1]][1]&#xD;&#xA;&#xD;&#xA;&lt;br&gt;&#xD;&#xA;Say I have a 3d point (with x, y, and z coordinates), a point for the camera, and a lookat point for the camera (the point that the camera is facing), how can I use this to plot the point?&#xD;&#xA;&#xD;&#xA;In pseudo-code:&#xD;&#xA;```&#xD;&#xA;cameraPosition = [10, 6, 5] // Camera coordinates&#xD;&#xA;cameraLookat = [5, 6, 5] // Where the camera is looking&#xD;&#xA;pointA = [5, 5, 5] // X, Y, and Z coordinates&#xD;&#xA;&#xD;&#xA;// Perspective render it to get 2d-coordinates&#xD;&#xA;pointA2D = perspectivePlot(pointA, cameraPosition, cameraLookat)&#xD;&#xA;```&#xD;&#xA;How would the `perspectivePlot` function work? From my understanding, it needs to plot a line between the `cameraPosition` and `pointA`, then find where the line intersects a plane that is 1 unit away from `cameraPosition` at the angle determined by `cameraLookat`.&#xD;&#xA;&#xD;&#xA;How would this be done?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iwh5j.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35800" PostHistoryTypeId="1" PostId="12409" RevisionGUID="a37b9457-350b-44ae-b5d7-d9971019d5b0" CreationDate="2021-12-19T23:57:36.030" UserId="17702" Text="Using Perspective Rendering To Render A 3D Point" ContentLicense="CC BY-SA 4.0" />
  <row Id="35801" PostHistoryTypeId="3" PostId="12409" RevisionGUID="a37b9457-350b-44ae-b5d7-d9971019d5b0" CreationDate="2021-12-19T23:57:36.030" UserId="17702" Text="|rendering|3d|perspective|camera|render|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35802" PostHistoryTypeId="2" PostId="12410" RevisionGUID="3a994717-3dd4-4be5-9351-308f73be3222" CreationDate="2021-12-20T00:03:10.627" UserId="17576" Text="I think I got at least some of it. I'll write here what I've found out thus far, but I'll keep the question open for a few weeks, in case someone comes up with more insight.&#xD;&#xA;&#xD;&#xA;I'll refer to the book &quot;High dynamic range imaging&quot; by Reinhard et al. as [HDRI].&#xD;&#xA;&#xD;&#xA;I'll start with my confusion about exposure (what I'm about to say only applies to ideal cameras, the matter changes significantly if one wants to model a realistic camera). According to [HDRI], $\S$ 7.6.1 the &quot;exposure&quot; correction is only needed when the units of the scene are not specified/agreed upon. In this case, the scalar correction before tonemapping  is aimed at &quot;guessing&quot; a plausible reference for the value of the mid grey, and correcting accordingly. Therefore, for a ray tracer, it's sort of a design choice whether to assume that the units of the lights in the scene are to be interpreted as standard radiometric units or not. If not, the exposure correction is needed, but then the behavior shown in my question's tests is correct/what one should expect. This accounts for the exposure-corrected example (2nd set of tests).&#xD;&#xA;&#xD;&#xA;As for Cycles and my non-exposure-corrected one, in both cases (at least, I'm guessing this is the case for Cycles, I didn't carefully check the code) the tonemapping curve is applied right away to the color channels (or better yet to multiply all the channels by the ratio between the tonemapped luminance and the original one, see [HDRI], $7.6.2$; which is at least part of what happens in the last method). The differences should mostly be due to the different curves used in the two renderers (I guess Cycles' one is not filmic, at least by default(?)).&#xD;&#xA;&#xD;&#xA;Finally, regarding the last method/set of tests, it's still not entirely clear to me. I get the $f(m)/m$ factor is just a more numerically stable way to apply the tonemapping function to the color channels, but the rest of the method is still kinda mysterious. I guess the idea is to scale color values, similarly to what one does with the &quot;exposure method&quot;, while at the same time applying a saturation trick to bake in the &quot;high values means bright scene&quot; assumption. I guess is sort of a compromise solution between assuming the units and just guessing the scene brightness globally from some average. I'd still be interested in knowing where the formulas for this trick come from though, I didn't manage to find anything yet (I still don't have the reputation to comment under that answer and ask for references)." ContentLicense="CC BY-SA 4.0" />
  <row Id="35804" PostHistoryTypeId="50" PostId="8209" RevisionGUID="37184da4-b7a5-48b7-b1cc-7c5abf3ac129" CreationDate="2021-12-20T03:07:25.700" UserId="-1" />
  <row Id="35805" PostHistoryTypeId="2" PostId="12411" RevisionGUID="0efadb82-801b-44c5-90fa-3d529f36f1b5" CreationDate="2021-12-20T17:39:10.637" UserId="17705" Text="I am writing a raytracer which is meant to support shadows. Previously, I have naively implemented hard shadows by casting a shadow ray towards the light (+ offset) and seeing if it hits anything along the way. This worked great, but now I am challenging myself by adding support for dielectrics and transparency in general.&#xD;&#xA;&#xD;&#xA;Intuitively, I wanted to make my shadow rays refract if they hit an object on the way to the light. However, it turns out this is pretty difficult to do. I then found [this post](https://computergraphics.stackexchange.com/questions/4573/refraction-in-a-ray-tracer-what-do-with-an-intersection-within-the-medium/4579#4579) which explains that I can just ignore refraction for a good enough approximation. Therefore:&#xD;&#xA; * How does the final result change depending on if you refract the shadow ray or not? I am having a hard time trying to visualize it, are there maybe any side by side comparisons?&#xD;&#xA; * The answer also mentions photon mapping. Alternatively, is it not possible to solve for the angle you need to shoot in order to end up at the light after refracting many times? Should this not end up being a linear system of equations? Or do we not do this because it is computationally too intense?&#xD;&#xA; * Are there any heuristics or rules of thumbs for when you should start actually modelling it in a physically realistic way (i.e. refract shadow rays)? Does the number of dielectrics in the scene affect this?&#xD;&#xA;&#xD;&#xA;Now, assuming that I do cast a straight shadow ray and beteen a point and the light there is a semi-transparent (50% opaque) purple surface. &#xD;&#xA;* So, half the light should go through. Does that mean I multiply the surface's colour by half the intensity of the light and then shade the area under the surface like I would shade any surface normally? Or do I just set the surface colour to be half the intensity of the light multiplied by purple?&#xD;&#xA;* What happens if I have many surfaces stacked on top of eachother? Say I have 3 purple surfaces all stacked perfectly on top of each other, with a vertical distance between them. The light shines straight down. I'm guessing that the intensity of the light with initial intensity $i$ would be as follows: after the first surface, it is $\frac{i}{2}$, then $\frac{i}{4}$ and lastly the point sees $\frac{i}{8}$ of the original intensity?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35807" PostHistoryTypeId="1" PostId="12411" RevisionGUID="0efadb82-801b-44c5-90fa-3d529f36f1b5" CreationDate="2021-12-20T17:39:10.637" UserId="17705" Text="Hard Shadows with Dielectrics/Transparency" ContentLicense="CC BY-SA 4.0" />
  <row Id="35808" PostHistoryTypeId="3" PostId="12411" RevisionGUID="0efadb82-801b-44c5-90fa-3d529f36f1b5" CreationDate="2021-12-20T17:39:10.637" UserId="17705" Text="|raytracing|lighting|shadow|transparency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35809" PostHistoryTypeId="2" PostId="12412" RevisionGUID="82123676-a11e-46f3-822a-1343952f9b54" CreationDate="2021-12-20T20:06:42.327" UserId="48" Text="Note that the [other answer](https://computergraphics.stackexchange.com/questions/6307/tone-mapping-bright-images/6311#6311) that you linked to is describing only a tonemapping operator, and does not include any exposure scaling at all. It's not replacing your steps 2 and 3 in the process, but only step 3. So it's potentially confusing and not all that useful, I think, to compare images that are using an exposure estimation + tonemapping pipeline with images that are using only the tonemapping part.&#xD;&#xA;&#xD;&#xA;I think of exposure estimation and scaling as being a separate part of the image pipeline prior to tonemapping (and not part of tonemapping). The purpose of exposure is to bring the image values into the range where most of the detail we want to see is roughly in the [0, 1] range. The exposure-scaled image is still HDR and may have values above 1, but we aren't going to be able to see as much detail in the values above 1 after tonemapping.&#xD;&#xA;&#xD;&#xA;One reason we need to do exposure mapping could be about the units of measurement, but another reason is just that natural scenes have wildly varying general light levels. A scene in daylight might have its overall intensity values 100x greater than a scene at night. If you try to put both through the same tonemapping curve without any exposure scaling, either the daylight scene will come out completely washed out and you won't be able to see anything, or the night scene will be practically black and you won't be able to see anything. By using exposure scaling we can adjust these scenes to a reasonable range before tonemapping. To put it another way, with exposure we are selecting what range of values contains the detail we want to be visible in the final image.&#xD;&#xA;&#xD;&#xA;Methods of estimating exposure, like log-luminance histograms and such, are more associated with real-time rendering scenarios like video games, where the user might move their camera around the scene and sometimes be looking into dark areas, sometimes into bright areas, and the game needs to adapt the exposure to make sure they can see something. There's a lot of tuning and tweaking needed to get such algorithms to behave reasonably and not be distracting.&#xD;&#xA;&#xD;&#xA;However, it is also perfectly acceptable to just tune the exposure value by hand when you have a shot you're composing. You can just set it up so that it looks &quot;right&quot; to your eye. You can also make artistic choices, like for example slightly overexposing a scene to communicate brightness/heat/harshness, or underexposing to make something feel more mysterious/foreboding, etc.&#xD;&#xA;&#xD;&#xA;&gt; The exposure-corrected gives clearly wrong results, as the 10, 100 and 1000 values all give pretty much the same output&#xD;&#xA;&#xD;&#xA;I think you figured this out already, but this is exactly the expected result from exposure scaling if you're setting exposure based off the luminance of the scene. Scaling all the light sources in the scene 100x brighter results in the exact same image only with all the pixel values 100x brighter, which results in an exposure scale 100x smaller, which results in the same final image.&#xD;&#xA;&#xD;&#xA;OK, now let's talk about tonemapping. Usually tonemapping curves are described as a scalar curve: one input, one output. Broadly speaking, two general approaches are to either apply this curve to each of the R, G, B channels individually (evaluating the function 3 times per pixel), or to apply the curve to the overall luminance of each pixel only (evaluating it just once per pixel).&#xD;&#xA;&#xD;&#xA;The per-channel approach has the nice property that it automatically desaturates colors as they get brighter, which is aesthetically appealing: a bright, colored light source may appear as a white core with colored bloom/glare around it, which does a good job of making it &quot;feel&quot; really bright to our visual system. In the per-channel approach, this happens because of the shoulder of the tonemapping curve, where it approaches its horizontal asymptote: the difference between R, G, B values gets compressed, producing an output that's closer to monochrome.&#xD;&#xA;&#xD;&#xA;However, the per-channel approach also tends to mess with hues, as after going through this nonlinear curve there is no guarantee that the final RGB color represents the same hue as the initial one. In order to fix this, you can calculate the luminance of the input color, apply the tonemapping curve to that, and then scale the input color to match the new tonemapped luminance. However, this approach doesn't alter the saturation of the input at all, so you lose that desirable property of the per-channel approach.&#xD;&#xA;&#xD;&#xA;The other answer you linked is working around that by putting the desaturation effect back in by hand. The author came up with this $\left(\frac{m-0.18}{m}\right)^{20}$ function that you mentioned as an empirical estimate of how much desaturation there should be. The `mix` from the original color to its luminance just implements the desaturation.&#xD;&#xA;&#xD;&#xA;A somewhat more principled approach to this could be to base the desaturation off the slope of the tonemapping curve, as that's where the effect originates in the per-channel approach. But tonemapping curves are completely empirical and based on aesthetics anyway; there is no real theory behind them that I'm aware of. So ultimately you can do anything that works and produces images you like.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35811" PostHistoryTypeId="2" PostId="12413" RevisionGUID="4ac92a56-2966-411a-bdb7-44c09340a096" CreationDate="2021-12-20T20:44:24.583" UserId="48" Text="&quot;Refracting the shadow ray&quot; is really the wrong mental model to use to think about this. After all, shadow rays are not real things; light rays are. Shadow rays are only used to test for some geometry blocking a light ray that could otherwise be there.&#xD;&#xA;&#xD;&#xA;What you're really asking about is: how do I go from simulating only direct lighting paths (light goes straight from source to the illuminated surface) to incorporating indirect specular paths as well (light gets to the illuminated surface through some set of specular refractions/reflections).&#xD;&#xA;&#xD;&#xA;&gt; How does the final result change depending on if you refract the shadow ray or not? I am having a hard time trying to visualize it, are there maybe any side by side comparisons?&#xD;&#xA;&#xD;&#xA;In general, light from a light source refracting through a transparent object and illuminating a surface will produce [caustics](https://en.wikipedia.org/wiki/Caustic_(optics)), as in this image from Wikipedia:&#xD;&#xA;&#xD;&#xA;![light shining on a glass of water producing caustics on the table](https://i.stack.imgur.com/4Czn3.png)&#xD;&#xA;&#xD;&#xA;You can see here the ordinary shadow due to interruption of the direct light path from source to the tabletop (this is the same shape as if the glass were opaque), plus a very complex pattern of extra light that's produced where the refraction through water and glass happens to focus more of the incident light rays. All the light that would have filled in the shadowed area if the water glass wasn't there has instead gotten pushed around, removed from some areas and concentrated in others, resulting in this pattern.&#xD;&#xA;&#xD;&#xA;&gt; is it not possible to solve for the angle you need to shoot in order to end up at the light after refracting many times? Should this not end up being a linear system of equations? &#xD;&#xA;&#xD;&#xA;Perhaps in the case of some exceedingly simple geometry, like a point light and a single perfect sphere, this could be done. In general, it is far too complex to handle this way. It certainly is not as simple as some linear equations. After all, look at the complexity of the caustics above, which is the result of essentially two nested cylinders. Really, the way to handle this is with photon mapping, or other advanced path tracing approaches like path guiding or VCM.&#xD;&#xA;&#xD;&#xA;&gt; Are there any heuristics or rules of thumbs for when you should start actually modelling it in a physically realistic way?&#xD;&#xA;&#xD;&#xA;It depends on the scene, and it depends how much realism you want vs how much computational budget you have, as caustics are expensive to simulate. A rule of thumb could be if you have any highly specular (low roughness) surfaces in or near the camera's field of view, and exposed to a small bright light source. Those are the cases where caustics will probably be most visible.&#xD;&#xA;&#xD;&#xA;&gt; So, half the light should go through. Does that mean I multiply the surface's colour by half the intensity of the light and then shade the area under the surface like I would shade any surface normally? Or do I just set the surface colour to be half the intensity of the light multiplied by purple?&#xD;&#xA;&#xD;&#xA;This gets into the interpretation of what your transparent surface is. When you say it is purple, does that mean it applies a purple tint to the light that passes through it? If so, then you should multiply the light color by purple. Or does the surface reflect/scatter purple light? In that case the light that passes through it would actually get a green tint (the complementary color to purple) since it will have its purple component filtered out of it. This is what happens with air on a clear day: it scatters blue light (producing the blue sky) and applies a yellow/orange tint to sunlight passing through it.&#xD;&#xA;&#xD;&#xA;BTW, to be more physically accurate, a color tint is not imparted by a surface but by a medium, and it depends on how far the ray travels through the medium. If you want to model tinted but clear (not cloudy) transparent materials, you can look up some material about [Beer's Law](https://my.eng.utah.edu/~cs6620/beers.pdf), which governs that.&#xD;&#xA;&#xD;&#xA;&gt; I'm guessing that the intensity of the light with initial intensity $i$ would be as follows: after the first surface, it is $\frac{i}{2}$, then $\frac{i}{4}$ and lastly the point sees $\frac{i}{8}$ of the original intensity?&#xD;&#xA;&#xD;&#xA;That's right, the attenuation of each layer stacks as you add more layers.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35813" PostHistoryTypeId="2" PostId="12414" RevisionGUID="6fcf6799-e45d-4627-955f-bd5188c96485" CreationDate="2021-12-21T07:27:29.130" UserId="17708" Text="After defining an attribute pointer, why can't I just reuse it? I have a VAO bound so shouldn't it just accept the AttributePointer I defined with the last VAO?&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;&#xD;&#xA;    unsigned int VBO;&#xD;&#xA;	glGenBuffers(1, &amp;VBO);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertecies), vertecies, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	unsigned int EBO;&#xD;&#xA;	glGenBuffers(1, &amp;EBO);&#xD;&#xA;	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);&#xD;&#xA;	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	//Second Cordinates&#xD;&#xA;	glBindVertexArray(VAO2);&#xD;&#xA;&#xD;&#xA;	unsigned int VBO2;&#xD;&#xA;	glGenBuffers(1, &amp;VBO2);&#xD;&#xA;	glBindBuffer(GL_ARRAY_BUFFER, VBO2);&#xD;&#xA;	glBufferData(GL_ARRAY_BUFFER, sizeof(vertecies2), vertecies2, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	unsigned int EBO2;&#xD;&#xA;	glGenBuffers(1, &amp;EBO2);&#xD;&#xA;	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2);&#xD;&#xA;	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies2), indicies2, GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;	//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;	glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;	glBindVertexArray(0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35815" PostHistoryTypeId="1" PostId="12414" RevisionGUID="6fcf6799-e45d-4627-955f-bd5188c96485" CreationDate="2021-12-21T07:27:29.130" UserId="17708" Text="Question about using glVertexAttribArray" ContentLicense="CC BY-SA 4.0" />
  <row Id="35816" PostHistoryTypeId="3" PostId="12414" RevisionGUID="6fcf6799-e45d-4627-955f-bd5188c96485" CreationDate="2021-12-21T07:27:29.130" UserId="17708" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35817" PostHistoryTypeId="2" PostId="12415" RevisionGUID="601bc831-5f9e-4cfc-9412-bc3701879e1f" CreationDate="2021-12-21T08:05:18.603" UserId="17708" Text="So... after a little more reading I found out that VertexAttributePointer is stored per VAO..." ContentLicense="CC BY-SA 4.0" />
  <row Id="35819" PostHistoryTypeId="2" PostId="12416" RevisionGUID="7695878d-466c-4c29-90f8-057b60b3cf48" CreationDate="2021-12-21T14:32:55.867" UserId="13273" Text="I am trying to generate mipmaps, which are based on depthbuffer values. To generate the next mipmap level, I am trying to read in the 4 pixels of the upper mipmap level per pixel. Unlike the usual mipmap generation. I am checking the depth values, and only averaging those of the 4 pixels which are in depth range.&#xD;&#xA;To do so, I need to read in the next larger mipmap level than the current one I am suppose to render to.&#xD;&#xA;I know, that reading from the same texture than rendering to is not allowed. but I found this post on stackoverflow: https://stackoverflow.com/questions/44349792/is-it-possible-to-render-to-textures-mipmap-level-1-while-sampling-from-level-0&#xD;&#xA;Here in the comments one person is talking about &quot;texture mipmap range specifiers&quot;. Does that mean, that I don't need to use two framebuffers (one for reading and one for writing and for each mipmap level switching between these both framebuffers?) with two textures to do what I am trying? If so. How can I specify which mipmap should be read from the shader?&#xD;&#xA;I am using &#xD;&#xA;&#xD;&#xA;      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmaplevelToRenderTo);&#xD;&#xA;&#xD;&#xA;command to render into a specific mipmap level. And I only want to read pixels from level &quot;mipmaplevelToRenderTo - 1&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35821" PostHistoryTypeId="1" PostId="12416" RevisionGUID="7695878d-466c-4c29-90f8-057b60b3cf48" CreationDate="2021-12-21T14:32:55.867" UserId="13273" Text="OpenGL: read texture mipmap level 0 and render to same texture mipmap level 1" ContentLicense="CC BY-SA 4.0" />
  <row Id="35822" PostHistoryTypeId="3" PostId="12416" RevisionGUID="7695878d-466c-4c29-90f8-057b60b3cf48" CreationDate="2021-12-21T14:32:55.867" UserId="13273" Text="|opengl|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35823" PostHistoryTypeId="2" PostId="12417" RevisionGUID="e2fddc89-ae67-4937-814f-4ef9c7e1780d" CreationDate="2021-12-21T23:30:25.803" UserId="17715" Text="I implemented reflection on my ray tracer. I had very few objects in the scene, so the reflected rays would less likely intersect.  If most of the rays don't intersect, metallic objects would appear less metallic. What I tried to do was use the dot product of the direction from the reflected ray's origin to the light source and the reflected ray's direction. It doesn't look very metallic. It just makes the parts of the object closer to the specular highlight brighter. I was wondering what'd be a better way to deal with reflected rays that don't intersect.&#xD;&#xA;&#xD;&#xA;This is what I got with rendering a silver sphere.[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YVic1.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BkjLc.png&#xD;&#xA;&#xD;&#xA;Here is an example of how a metallic surface should be handled. It does look like some reflected rays don't intersect but contribute to the shading.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35825" PostHistoryTypeId="1" PostId="12417" RevisionGUID="e2fddc89-ae67-4937-814f-4ef9c7e1780d" CreationDate="2021-12-21T23:30:25.803" UserId="17715" Text="What do I do with reflected rays that don't intersect?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35826" PostHistoryTypeId="3" PostId="12417" RevisionGUID="e2fddc89-ae67-4937-814f-4ef9c7e1780d" CreationDate="2021-12-21T23:30:25.803" UserId="17715" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35827" PostHistoryTypeId="4" PostId="12417" RevisionGUID="0fe0bd0d-8876-4200-8786-064f9db6ecaa" CreationDate="2021-12-22T00:15:47.907" UserId="17715" Comment="edited title" Text="What to do with reflected rays that don't intersect?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35828" PostHistoryTypeId="2" PostId="12418" RevisionGUID="ff601319-0eb2-4c91-9709-4e656bb6d91e" CreationDate="2021-12-22T00:59:17.920" UserId="48" Text="For metallic materials to look metallic, they should have some environment surrounding them for them to reflect. In the sphereflake image you posted, the metal spheres are reflecting the yellow ground and a blue sky, together with getting specular highlights from three light sources, and this is enough to give the impression of metal. The reflected rays are either hitting the other spheres, the ground plane, or if they miss (don't hit anything) they are assumed to hit the sky, and assigned the sky color.&#xD;&#xA;&#xD;&#xA;So, providing some sort of colored sky is useful. For instance, you can map a texture onto the sky based on the direction the ray is heading. There are many free [environment maps](https://www.hdri-hub.com/free-hdri-environments-for-download) available on the web that can be used for this purpose. Set it up so that &quot;miss&quot; rays sample the environment map, and the detail in the texture will provide the cues your brain needs to perceive the material as metallic. This is also known as &quot;image-based lighting&quot; since the lighting environment is determined by an image rather than (or in addition to) specified light sources.&#xD;&#xA;&#xD;&#xA;For a simpler version of this, you could create a 1D gradient or color ramp mapped from the top of the sky to the bottom (i.e. based on the ray's vertical angle). It won't be quite as effective as a full HDR environment map but will still work better than a single flat color." ContentLicense="CC BY-SA 4.0" />
  <row Id="35830" PostHistoryTypeId="5" PostId="12417" RevisionGUID="f880d6a0-5181-4fcd-a3f8-09fc2269ebd9" CreationDate="2021-12-22T06:42:32.190" UserId="17715" Comment="deleted 85 characters in body" Text="I implemented reflection on my ray tracer. I had very few objects in the scene, so the reflected rays would less likely intersect.  If most of the rays don't intersect, metallic objects would appear less metallic. What I tried to do was use the dot product of the direction from the reflected ray's origin to the light source and the reflected ray's direction. It doesn't look very metallic. It just makes the parts of the object closer to the specular highlight brighter. I was wondering what'd be a better way to deal with reflected rays that don't intersect.&#xD;&#xA;&#xD;&#xA;This is what I got with rendering a silver sphere.[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YVic1.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/BkjLc.png&#xD;&#xA;&#xD;&#xA;Here is an example of how a metallic surface should be handled.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35831" PostHistoryTypeId="50" PostId="12353" RevisionGUID="4a8f3255-a1c3-450c-bc84-adde28339a9b" CreationDate="2021-12-22T08:02:45.300" UserId="-1" />
  <row Id="35836" PostHistoryTypeId="10" PostId="12403" RevisionGUID="28ba69cb-5a9e-4c24-8c00-1a931cfffdff" CreationDate="2021-12-22T11:53:39.597" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:38,&quot;DisplayName&quot;:&quot;joojaa&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[5]}" />
  <row Id="35838" PostHistoryTypeId="50" PostId="9591" RevisionGUID="c7c66b13-53a5-46bc-af2d-b728ec4b5892" CreationDate="2021-12-23T01:06:15.650" UserId="-1" />
  <row Id="35842" PostHistoryTypeId="2" PostId="12420" RevisionGUID="db06d086-2e99-40ca-b675-764f9a2ef9af" CreationDate="2021-12-23T07:08:22.480" UserId="17718" Text="Recently, I am doing some research about subsurface scattering.  i am a little confused about the **backscattered radiance** mentioned in this paper [Reflection from Layered Surfaces due to Subsurface Scattering][1]. I understand the light transfer equation, but i just cannot figure out why it has to be that form.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I don't know Why does it has to be [![enter image description here][3]][3],there is a picture which can describe the radiance clearly:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Does anyone who have read that paper? I need some help&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://cseweb.ucsd.edu/~ravir/6998/papers/p165-hanrahan.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/vg9Wo.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/nO1zv.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/68Gk7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35844" PostHistoryTypeId="1" PostId="12420" RevisionGUID="db06d086-2e99-40ca-b675-764f9a2ef9af" CreationDate="2021-12-23T07:08:22.480" UserId="17718" Text="[Subsurface Scattering]Reflection from Layered Surfaces due to Subsurface Scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="35845" PostHistoryTypeId="3" PostId="12420" RevisionGUID="db06d086-2e99-40ca-b675-764f9a2ef9af" CreationDate="2021-12-23T07:08:22.480" UserId="17718" Text="|lighting|brdf|subsurface-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35846" PostHistoryTypeId="2" PostId="12421" RevisionGUID="0e3af76e-eeac-484f-a92b-fd901b2e4785" CreationDate="2021-12-23T09:48:30.347" UserId="8048" Text="I implemented a MicrofacetTransmission in nori. Buy it can not pass all Chi2test when alpha is large(&gt;= 0.4 or ?),part of chi2test is passed.And I can not found the problem.[Nori framework][1].&#xD;&#xA;Code is below:&#xD;&#xA;[![sample function][2]][2]&#xD;&#xA;&#xD;&#xA;[![pdf function][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://wjakob.github.io/nori/&#xD;&#xA;  [2]: https://i.stack.imgur.com/FD0cd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/S6PFV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35848" PostHistoryTypeId="1" PostId="12421" RevisionGUID="0e3af76e-eeac-484f-a92b-fd901b2e4785" CreationDate="2021-12-23T09:48:30.347" UserId="8048" Text="Why my bsdf can not pass Chi2test?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35849" PostHistoryTypeId="3" PostId="12421" RevisionGUID="0e3af76e-eeac-484f-a92b-fd901b2e4785" CreationDate="2021-12-23T09:48:30.347" UserId="8048" Text="|pathtracing|pbr|material|microfacet|bsdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35850" PostHistoryTypeId="2" PostId="12422" RevisionGUID="e47b6808-e975-4400-a6d1-046ab0e8fed8" CreationDate="2021-12-24T04:51:59.087" UserId="48" Text="The factor $e^{-\tau_d (1/\cos \theta_i + 1/\cos \theta_r)}$ represents the attenuation of backscattered light due to the path it takes through the layer.&#xD;&#xA;&#xD;&#xA;Imagine for a moment a layer of thickness 1. A ray passing through this layer from top to bottom at angle $\theta$ will then have a length of $1/\cos \theta$, which you can see by drawing a right triangle. This applies to both the incident and reflected rays, so the total path length of the ray within this layer is $1/\cos \theta_i + 1/\cos\theta_r$.&#xD;&#xA;&#xD;&#xA;Multiply this by the optical thickness of the layer, $\tau_d$, and you have the optical thickness of the whole ray path; thus $e^{-\tau_d (1/\cos \theta_i + 1/\cos \theta_r)}$ is the attenuation factor along that path.&#xD;&#xA;&#xD;&#xA;The other cosine factors out front and the $1 -$ in front of the exponential term, I'm guessing, probably arise from doing an integral over the depth of the layer, to account for scattering events at any depth in the layer. This often shows up when integrating exponentials:&#xD;&#xA;$$&#xD;&#xA;\int_0^{\tau_d} e^{-\tau \cdot \text{stuff}}\,d\tau&#xD;&#xA;= \frac{1}{\text{stuff}} \bigl(1 - e^{-\tau_d \cdot \text{stuff}} \bigr)&#xD;&#xA;$$&#xD;&#xA;as long as the $\text{stuff}$ is independent of depth." ContentLicense="CC BY-SA 4.0" />
  <row Id="35852" PostHistoryTypeId="50" PostId="8260" RevisionGUID="33015bda-1d64-4084-a575-15dc1506ce3d" CreationDate="2021-12-24T09:04:55.437" UserId="-1" />
  <row Id="35858" PostHistoryTypeId="2" PostId="12424" RevisionGUID="2d288b4a-4ca2-4392-8853-49713acf6207" CreationDate="2021-12-24T23:53:08.377" UserId="11224" Text="I am writing basic code to; draw triangles, lines etc; to translate and orient them, and to project them in perspective, solving the occlusion problem using the depth buffer.&#xD;&#xA;&#xD;&#xA;Having had success with a hand-made projection matrix emulating what ``glFrustum`` used to do before it was deprecated, I upgraded to a hand-made infinite projection matrix having no far clipping plane, based on what I've read in books. This mapped $z = -\infty$ in camera space to $z = 1$ in normalised device coordinates. This all worked, and allowed me for the first time, to use infinitely distant objects, i.e. objects having $w = 0$. These render correctly behind everything else, and exhibit no parallax, and no change in size. They move only when the camera *orientation* changes, as desired.&#xD;&#xA;&#xD;&#xA;I was able to induce $z$-fighting by having the ratio of the distances of the far and near clipping planes nice and large, and making two very large distant triangles, one parallel to and not far behind the other. I did this in order to justify upgrading my projection matrix again, this time to a reversed-$z$ style, again based on what I've read in books. Having done so, I changed ``glDepthFunc(GL_LEQUAL)`` to ``glDepthFunc(GL_GEQUAL)`` and set ``glClearDepth(0.0f)``. The last step remaining seemed to be to  set ``glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE)``. However, the IDE did not recognise the definitions of the two constant parameters. The specific errors from the IDE are &quot;GL_LOWER_LEFT undeclared (first use in this function). Did you mean...&quot; followed by a suggestion of something else with a similar spelling, and a similar error, for the other constant. I don't know if the problem is with the function itself - the IDE seemed not to object to it, in any case. I know that this function became available only in OpenGL version 4, however, my code reports, via ``const GLubyte* VERSIONSTRING = glGetString(GL_VERSION)``, that it is using version 4.6.0.&#xD;&#xA;&#xD;&#xA;The only other time I've encountered a problem like this so far, was with ``const GLubyte* SHADINGLANGUAGESTRING = glGetString(GL_SHADING_LANGUAGE_VERSION)``. Here too, the constant parameter was not recognised.&#xD;&#xA;&#xD;&#xA;There are more details here: https://computergraphics.stackexchange.com/q/12396/11224 about the template that I have borrowed and modified, in case that helps diagnose the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="35860" PostHistoryTypeId="1" PostId="12424" RevisionGUID="2d288b4a-4ca2-4392-8853-49713acf6207" CreationDate="2021-12-24T23:53:08.377" UserId="11224" Text="OpenGL in CodeBlocks with GNU GCC compiler not recognising some constants" ContentLicense="CC BY-SA 4.0" />
  <row Id="35861" PostHistoryTypeId="3" PostId="12424" RevisionGUID="2d288b4a-4ca2-4392-8853-49713acf6207" CreationDate="2021-12-24T23:53:08.377" UserId="11224" Text="|opengl|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35863" PostHistoryTypeId="50" PostId="10784" RevisionGUID="7119f7ea-9904-452b-b5df-8462c6e55141" CreationDate="2021-12-25T16:06:55.573" UserId="-1" />
  <row Id="35870" PostHistoryTypeId="5" PostId="12424" RevisionGUID="8a9d0ea7-967a-4aad-8a0b-e187545e4a75" CreationDate="2021-12-26T02:00:41.997" UserId="11224" Comment="added 258 characters in body" Text="I am writing basic code to; draw triangles, lines etc; to translate and orient them, and to project them in perspective, solving the occlusion problem using the depth buffer.&#xD;&#xA;&#xD;&#xA;Having had success with a hand-made projection matrix emulating what ``glFrustum`` used to do before it was deprecated, I upgraded to a hand-made infinite projection matrix having no far clipping plane, based on what I've read in books. This mapped $z = -\infty$ in camera space to $z = 1$ in normalised device coordinates. This all worked, and allowed me for the first time, to use infinitely distant objects, i.e. objects having $w = 0$. These render correctly behind everything else, and exhibit no parallax, and no change in size. They move only when the camera *orientation* changes, as desired.&#xD;&#xA;&#xD;&#xA;I was able to induce $z$-fighting by having the ratio of the distances of the far and near clipping planes nice and large, and making two very large distant triangles, one parallel to and not far behind the other. I did this in order to justify upgrading my projection matrix again, this time to a reversed-$z$ style, again based on what I've read in books. Having done so, I changed ``glDepthFunc(GL_LEQUAL)`` to ``glDepthFunc(GL_GEQUAL)`` and set ``glClearDepth(0.0f)``. The last step remaining seemed to be to  set ``glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE)``. However, the IDE did not recognise the definitions of the two constant parameters. The specific errors from the IDE are &quot;GL_LOWER_LEFT undeclared (first use in this function). Did you mean...&quot; followed by a suggestion of something else with a similar spelling, and a similar error, for the other constant. I don't know if the problem is with the function itself - the IDE seemed not to object to it, in any case. I know that this function became available only in OpenGL version 4, however, my code reports, via ``const GLubyte* VERSIONSTRING = glGetString(GL_VERSION)``, that it is using version 4.6.0.&#xD;&#xA;&#xD;&#xA;The only other time I've encountered a problem like this so far, was with ``const GLubyte* SHADINGLANGUAGESTRING = glGetString(GL_SHADING_LANGUAGE_VERSION)``. Here too, the constant parameter was not recognised.&#xD;&#xA;&#xD;&#xA;There are more details here: https://computergraphics.stackexchange.com/q/12396/11224 about the template that I have borrowed and modified, in case that helps diagnose the problem.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;In case it is relevant, CodeBlocks' autocomplete did *not* recognise the command `glClipControl`, whereas it did recognise the `glGetString`, in spite of it not knowing the constant GL_SHADING_LANGUAGE_VERSION that I passed to `glGetString`." ContentLicense="CC BY-SA 4.0" />
  <row Id="35871" PostHistoryTypeId="2" PostId="12426" RevisionGUID="2296ae09-9a60-4148-af4b-fea62328c2b0" CreationDate="2021-12-26T05:55:42.977" UserId="17718" Text="Recently, i am reading the papaer [A Practical Model for Subsurface Light Transport][1] . I have understand the radiative transport equation and the approximation of the diffusion equation. However i saw the diffuse BSSRDF `Rd` definition:[![definition][2]][2]&#xD;&#xA;&#xD;&#xA;, i can't understand the meaning of `Rd`. Why we need that definition which describes &#xD;&#xA;&quot;the radiant exitance divided by the incident flux&quot; .&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/qW0fk.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35873" PostHistoryTypeId="1" PostId="12426" RevisionGUID="2296ae09-9a60-4148-af4b-fea62328c2b0" CreationDate="2021-12-26T05:55:42.977" UserId="17718" Text="[Subsurface Scattering]What's the meaning of diffuse bssrdf `Rd` in [A Practical Model for Subsurface Light Transport] paper" ContentLicense="CC BY-SA 4.0" />
  <row Id="35874" PostHistoryTypeId="3" PostId="12426" RevisionGUID="2296ae09-9a60-4148-af4b-fea62328c2b0" CreationDate="2021-12-26T05:55:42.977" UserId="17718" Text="|lighting|subsurface-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35875" PostHistoryTypeId="5" PostId="12426" RevisionGUID="b3c2766e-51ed-4561-9b43-ef5602620d82" CreationDate="2021-12-26T06:06:23.233" UserId="17718" Comment="added 553 characters in body; edited title" Text="Recently, i am reading the papaer [A Practical Model for Subsurface Light Transport][1] . I have understand the radiative transport equation :&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;and the approximation of the diffusion equation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;.&#xD;&#xA; &#xD;&#xA;In BRDF lighting model, we define BRDF coefficient as below :&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;and in the bssrdf lighting model we have :&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA; However i saw the diffuse BSSRDF `Rd` definition:[![definition][7]][7]&#xD;&#xA;&#xD;&#xA;, i can't understand the meaning of `Rd`. Why we need that definition which describes &#xD;&#xA;&quot;the radiant exitance divided by the incident flux&quot; .&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphics.stanford.edu/papers/bssrdf/bssrdf.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/3FSkN.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/i6C1Z.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/xGkyo.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/cOyhN.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/dEbjI.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/qW0fk.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35876" PostHistoryTypeId="4" PostId="12426" RevisionGUID="b3c2766e-51ed-4561-9b43-ef5602620d82" CreationDate="2021-12-26T06:06:23.233" UserId="17718" Comment="added 553 characters in body; edited title" Text="[Subsurface Scattering]What's the meaning of diffuse coefficient `Rd` in bssrdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35877" PostHistoryTypeId="2" PostId="12427" RevisionGUID="13a4eddf-9f4f-4a75-be9c-5e0cd354eda9" CreationDate="2021-12-26T18:43:06.310" UserId="48" Text="It sounds like your version of the `opengl.h` header is too old, and doesn't include the declarations for functions and constants from newer versions. Despite that the OpenGL implementation in the driver is 4.6, you won't be able to access the newer functionality without the appropriate declarations. You'll also need code to load the function addresses from the driver for newer functions (this is called a &quot;loader&quot;).&#xD;&#xA;&#xD;&#xA;There are a few different libraries/tools out there for this, but one I like is [Glad](https://glad.dav1d.de/), which is an online loader generator. It will generate a header and source file that you can download and add directly to your project in place of the usual `opengl.h`.&#xD;&#xA;&#xD;&#xA;You can put in the version of OpenGL you want - probably 4.6 with &quot;Compatibility&quot; profile - that will include the &quot;old-fashioned&quot; stuff like immediate mode, which I think you said you were using. (You could use &quot;Core&quot; profile if you want to get rid of all deprecated stuff and only use modern OpenGL, but that may be a steeper learning curve.) You can also put in any extensions you want to use, and it will include their associated functions and constants in the generated loader." ContentLicense="CC BY-SA 4.0" />
  <row Id="35879" PostHistoryTypeId="2" PostId="12428" RevisionGUID="714d47a0-7c8f-4795-a9b4-2b5c678654a4" CreationDate="2021-12-26T19:00:12.587" UserId="48" Text="$R_d$ is the diffusion profile. It's a falloff function that describes how light spreads through the material, as a function of the distance between the entering and exiting point.&#xD;&#xA;&#xD;&#xA;If you imagine a tiny, bright beam of light (like a laser) illuminating the surface at an incident point $x_i$, it would produce a glow on the surface surrounding it, as light scatters around in the material and then exits at nearby points. The diffusion profile gives the brightness of this glow (the radiant exitance), as a function of distance ($r$) from the incident point, and proportional to the brightness of the incoming light (the incident flux)." ContentLicense="CC BY-SA 4.0" />
  <row Id="35882" PostHistoryTypeId="2" PostId="12429" RevisionGUID="9ade99f2-9b8d-4f2c-a867-a94eba7165bd" CreationDate="2021-12-27T03:26:30.863" UserId="15354" Text="As for question 4, i am also confused when i read the same article, after googling, i find this article well explained [Importance Sampling techniques for GGX][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://schuttejoe.github.io/post/ggximportancesamplingpart1/" ContentLicense="CC BY-SA 4.0" />
  <row Id="35884" PostHistoryTypeId="50" PostId="12359" RevisionGUID="898b698b-ba3a-446d-a6cf-e9014a09d567" CreationDate="2021-12-27T06:04:50.543" UserId="-1" />
  <row Id="35885" PostHistoryTypeId="50" PostId="9319" RevisionGUID="3d66f93c-63da-4c1c-8eb9-7baac6d761d4" CreationDate="2021-12-27T15:05:40.520" UserId="-1" />
  <row Id="35886" PostHistoryTypeId="50" PostId="9163" RevisionGUID="32a5bc69-e2c8-4b51-8e15-0321c55bd587" CreationDate="2021-12-27T16:04:05.420" UserId="-1" />
  <row Id="35889" PostHistoryTypeId="2" PostId="12430" RevisionGUID="b5f33be3-f750-43f7-b373-2eaab4b85655" CreationDate="2021-12-27T22:47:55.557" UserId="17751" Text="I'm reading section 8.2 of Eric Veach's thesis, in regards to the relationship between probability densities per solid angle vs projected solid angle:&#xD;&#xA;&#xD;&#xA;$$\frac{dP}{d\sigma^\perp}(w_o) = \frac{dP}{d\sigma}(w_o)\frac{d\sigma(w_o)}{d\sigma^\perp (w_o)}$$&#xD;&#xA;$$\implies p^\perp (w_o) = p(w_o)\frac{1}{cos(\theta_o)}$$&#xD;&#xA;&#xD;&#xA;where we have used the relationship&#xD;&#xA;$$d \sigma^\perp(w_o) = |w_o \cdot N(x)|d \sigma(w_o)$$&#xD;&#xA;&#xD;&#xA;I think this is just a straightforward application of calculus somewhere, but I can't see how to get to the &quot;implies&quot; part. The result makes sense to me intuitively, but I'd like to follow the math. Starting with the first line, then after doing the substitution using the relationship he provides, would you integrate both sides or something? But then aren't they over different domains?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35891" PostHistoryTypeId="1" PostId="12430" RevisionGUID="b5f33be3-f750-43f7-b373-2eaab4b85655" CreationDate="2021-12-27T22:47:55.557" UserId="17751" Text="Relationship between probability densities" ContentLicense="CC BY-SA 4.0" />
  <row Id="35892" PostHistoryTypeId="3" PostId="12430" RevisionGUID="b5f33be3-f750-43f7-b373-2eaab4b85655" CreationDate="2021-12-27T22:47:55.557" UserId="17751" Text="|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35893" PostHistoryTypeId="50" PostId="9178" RevisionGUID="6fa0733a-cfc9-486f-a545-4a32389328be" CreationDate="2021-12-28T15:01:00.187" UserId="-1" />
  <row Id="35894" PostHistoryTypeId="2" PostId="12431" RevisionGUID="2a7896aa-c8ce-40c0-9936-0b1a4dd50de7" CreationDate="2021-12-28T23:46:53.450" UserId="48" Text="I think this is mainly just giving new names to terms and a bit of algebra.&#xD;&#xA;&#xD;&#xA;$p^\perp(\omega_o)$ is the name given to the probability density $\frac{dP}{d\sigma^\perp}(\omega_o)$. Similarly $p(\omega_o)$ is the name given to $\frac{dP}{d\sigma}(\omega_o)$. A probability density is the amount of probability ($dP$) per unit area ($d\sigma$), so this is kind of just expanding out the pdfs into their definitions.&#xD;&#xA;&#xD;&#xA;Then we just need the factor $\frac{d\sigma(\omega_o)}{d\sigma^\perp(\omega_o)}$ which, from the relationship in the 3rd equation, is $\frac{1}{|\omega_o \cdot N(x)|}$.&#xD;&#xA;&#xD;&#xA;Since the dot product gives the cosine between vectors, $\omega_o \cdot N(x)$ = $\cos(\theta_o)$. I am not sure why the absolute value gets dropped, but it may just be a typo as it reappears in the following equation in the thesis.&#xD;&#xA;&#xD;&#xA;The application of calculus here is in putting in the factor $\frac{d\sigma(\omega_o)}{d\sigma^\perp(\omega_o)}$, which is the inverse Jacobian, used for transforming probability densities (or other densities) from one domain to another—here, from the &quot;ordinary solid angle&quot; ($\sigma$) domain to that of projected solid angle ($\sigma^\perp$). Basically an enhanced version of the chain rule." ContentLicense="CC BY-SA 4.0" />
  <row Id="35896" PostHistoryTypeId="5" PostId="12421" RevisionGUID="1c520c0b-1b69-48bb-bd18-86afe6cae42e" CreationDate="2021-12-29T08:01:52.647" UserId="8048" Comment="added 23 characters in body" Text="I implemented a MicrofacetTransmission in nori. But it can not pass all Chi2test when alpha is large(&gt;= 0.4 or ?),part of chi2test is passed.And I can not found the problem.Can someone help me? &#xD;&#xA;[Nori framework][1].&#xD;&#xA;Code is below:&#xD;&#xA;[![sample function][2]][2]&#xD;&#xA;&#xD;&#xA;[![pdf function][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://wjakob.github.io/nori/&#xD;&#xA;  [2]: https://i.stack.imgur.com/FD0cd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/S6PFV.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35899" PostHistoryTypeId="6" PostId="12421" RevisionGUID="095b269c-3a86-457b-902c-862d1a4f1853" CreationDate="2021-12-29T08:05:08.897" UserId="8048" Comment="edited tags" Text="|raytracing|pathtracing|pbr|microfacet|bsdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35900" PostHistoryTypeId="2" PostId="12433" RevisionGUID="6bf10e2c-1ee0-4537-b267-39120d8f6bbe" CreationDate="2021-12-29T08:26:52.970" UserId="17760" Text="Hey Im currently learning about geometry and vectors and was trying to build a room builder with three js.&#xD;&#xA;&#xD;&#xA;I basicly create walls from two points (p1, p2). I draw a line and extrude the line to a rectangle. I create the rectangle by making a path of 4 points, where I offset the two points p1, p2 in the perpendicular direction (normal) of the line in both directions (right and left of the line). In code I used this pattern (Extrude = e)&#xD;&#xA;&#xD;&#xA;    e2 _______________e4&#xD;&#xA;    p1|______________|p2&#xD;&#xA;    e1|______________|e3&#xD;&#xA;              |&#xD;&#xA;&#xD;&#xA;Now I noticed a weird but obvious behavior. When I draw the wall from p2 to p1 instead of p1 to p2 everything starts to rotate&#xD;&#xA;&#xD;&#xA;    e3 _______|_______e1&#xD;&#xA;    p2|______________|p1&#xD;&#xA;    e4|______________|e2&#xD;&#xA;&#xD;&#xA;Now I wonder how to work around this behavior. I want to connect the walls to all other walls having the same points. So Im calculating the angle of all walls to get the two neighbours of the current wall, when I have multiple connections.&#xD;&#xA;&#xD;&#xA;    \ /&#xD;&#xA;     |&#xD;&#xA;&#xD;&#xA;Here is the issue im facing. When I want to calculate the intersection point of a wall and its neighbours, therefore I use 2 extruded points of wall1 and two of wall2, but I dont know which sides of the wall are facing each other. &#xD;&#xA;&#xD;&#xA;If the pattern of above wouldnt rotate, this would work fine for me. I would take the points as lines like so (e1, e3) (e2, e4) for example and calculate the intersection. I need to find out in what direction I need to extrude the points of each wall&#xD;&#xA;&#xD;&#xA;Im confused that the points are rotating when I draw the line from the opposite direction and also how to know the facing sides of the rectangular.&#xD;&#xA;&#xD;&#xA;Any help is highly appreciated &#xD;&#xA;Ask for more infos please" ContentLicense="CC BY-SA 4.0" />
  <row Id="35902" PostHistoryTypeId="1" PostId="12433" RevisionGUID="6bf10e2c-1ee0-4537-b267-39120d8f6bbe" CreationDate="2021-12-29T08:26:52.970" UserId="17760" Text="Extrude from line and find intersection points" ContentLicense="CC BY-SA 4.0" />
  <row Id="35903" PostHistoryTypeId="3" PostId="12433" RevisionGUID="6bf10e2c-1ee0-4537-b267-39120d8f6bbe" CreationDate="2021-12-29T08:26:52.970" UserId="17760" Text="|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35904" PostHistoryTypeId="5" PostId="12433" RevisionGUID="962aa346-7518-4164-8ce9-c6be20b04d2a" CreationDate="2021-12-29T12:07:23.170" UserId="17760" Comment="deleted 405 characters in body" Text="Hey Im currently learning about geometry and vectors and was trying to build a room builder with three js.&#xD;&#xA;&#xD;&#xA;I basicly create walls from two points (p1, p2). I draw a line and extrude the line to a rectangle. I create the rectangle by making a path of 4 points, where I offset the two points p1, p2 in the perpendicular direction (normal) of the line in both directions (right and left of the line). In code I used this pattern (Extrude = e)&#xD;&#xA;&#xD;&#xA;    e2 _______________e4&#xD;&#xA;    p1|______________|p2&#xD;&#xA;    e1|______________|e3&#xD;&#xA;              |&#xD;&#xA;&#xD;&#xA;Now I noticed a weird but obvious behavior. When I draw the wall from p2 to p1 instead of p1 to p2 everything starts to rotate&#xD;&#xA;&#xD;&#xA;    e3 _______|_______e1&#xD;&#xA;    p2|______________|p1&#xD;&#xA;    e4|______________|e2&#xD;&#xA;&#xD;&#xA;Now I wonder how to work around this behavior. I want to connect the walls to all other walls having the same points. So Im calculating the angle of all walls to get the two neighbours of the current wall, when I have multiple connections.&#xD;&#xA;&#xD;&#xA;    \ /&#xD;&#xA;     |&#xD;&#xA;&#xD;&#xA;Here is the issue im facing. When I want to calculate the intersection point of a wall and its neighbours, therefore I use 2 extruded points of wall1 and two of wall2, but I dont know which sides of the wall are facing each other. &#xD;&#xA;&#xD;&#xA;Any help is highly appreciated &#xD;&#xA;Ask for more infos please" ContentLicense="CC BY-SA 4.0" />
  <row Id="35905" PostHistoryTypeId="5" PostId="12433" RevisionGUID="a6ee5550-bc71-4a88-915e-dcc5e3613ebd" CreationDate="2021-12-29T14:29:44.880" UserId="17760" Comment="added 144 characters in body" Text="Hey Im currently learning about geometry and vectors and was trying to build a room builder with three js.&#xD;&#xA;&#xD;&#xA;I basicly create walls from two points (p1, p2). I draw a line and extrude the line to a rectangle. I create the rectangle by making a path of 4 points, where I offset the two points p1, p2 in the perpendicular direction (normal) of the line in both directions (right and left of the line). In code I used this pattern (Extrude = e)&#xD;&#xA;&#xD;&#xA;    e2 _______________e4&#xD;&#xA;    p1|______________|p2&#xD;&#xA;    e1|______________|e3&#xD;&#xA;              |&#xD;&#xA;&#xD;&#xA;Now I noticed a weird but obvious behavior. When I draw the wall from p2 to p1 instead of p1 to p2 everything starts to rotate&#xD;&#xA;&#xD;&#xA;    e3 _______|_______e1&#xD;&#xA;    p2|______________|p1&#xD;&#xA;    e4|______________|e2&#xD;&#xA;&#xD;&#xA;Now I wonder how to work around this behavior. I want to connect the walls to all other walls having the same points. So Im calculating the angle of all walls to get the two neighbours of the current wall, when I have multiple connections.&#xD;&#xA;&#xD;&#xA;    \ /&#xD;&#xA;     |&#xD;&#xA;&#xD;&#xA;Here is the issue im facing. When I want to calculate the intersection point of a wall and its neighbours, therefore I use 2 extruded points of wall1 and two of wall2, but I dont know which sides of the wall are facing each other. &#xD;&#xA;&#xD;&#xA;I guess the actual question is how to handle a positive and negative draw direction of a line and how to get the sides facing to each other.&#xD;&#xA;&#xD;&#xA;Any help is highly appreciated &#xD;&#xA;Ask for more infos please" ContentLicense="CC BY-SA 4.0" />
  <row Id="35907" PostHistoryTypeId="5" PostId="12421" RevisionGUID="88c1c079-a3a2-43e2-bd61-5d24cbf390eb" CreationDate="2021-12-30T03:19:53.460" UserId="8048" Comment="added 80 characters in body" Text="I implemented a MicrofacetTransmission in nori. But it can not pass all Chi2test when alpha is large(&gt;= 0.4 or ?),part of chi2test is passed.And I can not found the problem.Can someone help me? &#xD;&#xA;[Nori framework][1].&#xD;&#xA;Code is below:&#xD;&#xA;[![sample function][2]][2]&#xD;&#xA;&#xD;&#xA;[![pdf function][3]][3]&#xD;&#xA;[![rendered image][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://wjakob.github.io/nori/&#xD;&#xA;  [2]: https://i.stack.imgur.com/FD0cd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/S6PFV.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/1CTLZ.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35908" PostHistoryTypeId="50" PostId="12366" RevisionGUID="b579b0b6-d2ac-4ae3-9a2c-fd65a01de585" CreationDate="2021-12-30T09:04:30.443" UserId="-1" />
  <row Id="35909" PostHistoryTypeId="2" PostId="12434" RevisionGUID="8c8b9fe0-5543-4f82-866e-221700cf93ba" CreationDate="2021-12-30T09:27:44.900" UserId="17333" Text="I have a 2D texture, without any depth maps, which I'd like to blur to achieve a bokeh effect. The catch, however, is that I want the effect to be custom bitmaps/shapes (e.g. a heart). Here's a part of the shader I'm using to achieve the blur:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const float vertices = 5.0; // For a pentagonal bokeh&#xD;&#xA;&#xD;&#xA;vec4 gamma_fun(vec4 vector, float gamma)&#xD;&#xA;{&#xD;&#xA;    return vec4(pow(vector.rgb, vec3(gamma)), vector.w);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    float maxradius = 10.;&#xD;&#xA;    vec2 texelSize = 1.0 / resolution.xy;&#xD;&#xA;    vec2 texcoord = textureCoordinate.xy;&#xD;&#xA;    &#xD;&#xA;    vec4 color = vec4(0.0);&#xD;&#xA;    for (float x = -maxradius; x &lt;= maxradius; x += 1.0)&#xD;&#xA;    {&#xD;&#xA;        for (float y = -maxradius; y &lt;= maxradius; y += 1.0)&#xD;&#xA;        {&#xD;&#xA;            vec2 offset = vec2(x, y);&#xD;&#xA;            float angle = atan(y, x);&#xD;&#xA;            float radius = sqrt(dot(offset, offset));&#xD;&#xA;&#xD;&#xA;            float paraPoly = cos(angle - (2.0 * PI * floor((PI + vertices * angle) / (2.0 * PI))) / vertices) / cos(PI / vertices);&#xD;&#xA;            float sdfPoly = paraPoly * radius - maxradius;&#xD;&#xA;            float egdeFalloff = smoothstep(0.0, -1.0, sdfPoly);&#xD;&#xA;&#xD;&#xA;            vec4 tap = texture2D(inputImageTexture, textureCoordinate.xy  + texelSize.xy * offset.xy);&#xD;&#xA;&#xD;&#xA;            tap = gamma_fun(tap, 4.0);&#xD;&#xA;            color += tap * egdeFalloff;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    color.rgb /= color.www;&#xD;&#xA;    color = gamma_fun(color, 1.0 / 4.0);&#xD;&#xA;    gl_FragColor = vec4(color.rgb, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Instead of the polygonal bokeh (achieved by setting the value of `vertices`), I'd like a custom bitmap, such as heart, to be displayed instead." ContentLicense="CC BY-SA 4.0" />
  <row Id="35911" PostHistoryTypeId="1" PostId="12434" RevisionGUID="8c8b9fe0-5543-4f82-866e-221700cf93ba" CreationDate="2021-12-30T09:27:44.900" UserId="17333" Text="Achieving bokeh blur with custom shapes" ContentLicense="CC BY-SA 4.0" />
  <row Id="35912" PostHistoryTypeId="3" PostId="12434" RevisionGUID="8c8b9fe0-5543-4f82-866e-221700cf93ba" CreationDate="2021-12-30T09:27:44.900" UserId="17333" Text="|glsl|opengl-es|blur|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35913" PostHistoryTypeId="5" PostId="12434" RevisionGUID="9f1e1812-cf9b-42bd-939a-7faa79a859af" CreationDate="2021-12-30T12:47:59.077" UserId="17333" Comment="deleted 6 characters in body" Text="I have a 2D texture, without any depth maps, which I'd like to blur to achieve a bokeh effect. The catch, however, is that I want the effect to be custom bitmaps/shapes (e.g. a heart). Here's a part of the shader I'm using to achieve the blur:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const float vertices = 5.0; // For a pentagonal bokeh&#xD;&#xA;&#xD;&#xA;vec4 gamma_fun(vec4 vector, float gamma)&#xD;&#xA;{&#xD;&#xA;    return vec4(pow(vector.rgb, vec3(gamma)), vector.w);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    float maxradius = 10.;&#xD;&#xA;    vec2 texelSize = 1.0 / resolution.xy;&#xD;&#xA;    vec2 texcoord = textureCoordinate.xy;&#xD;&#xA;    &#xD;&#xA;    vec4 color = vec4(0.0);&#xD;&#xA;    for (float x = -maxradius; x &lt;= maxradius; x += 1.0)&#xD;&#xA;    {&#xD;&#xA;        for (float y = -maxradius; y &lt;= maxradius; y += 1.0)&#xD;&#xA;        {&#xD;&#xA;            vec2 offset = vec2(x, y);&#xD;&#xA;            float angle = atan(y, x);&#xD;&#xA;            float radius = sqrt(dot(offset, offset));&#xD;&#xA;&#xD;&#xA;            float paraPoly = cos(angle - (2.0 * PI * floor((PI + vertices * angle) / (2.0 * PI))) / vertices) / cos(PI / vertices);&#xD;&#xA;            float sdfPoly = paraPoly * radius - maxradius;&#xD;&#xA;            float egdeFalloff = smoothstep(0.0, -1.0, sdfPoly);&#xD;&#xA;&#xD;&#xA;            vec4 tap = texture2D(inputImageTexture, textureCoordinate.xy  + texelSize.xy * offset.xy);&#xD;&#xA;&#xD;&#xA;            tap = gamma_fun(tap, 4.0);&#xD;&#xA;            color += tap * egdeFalloff;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    color.rgb /= color.www;&#xD;&#xA;    color = gamma_fun(color, 1.0 / 4.0);&#xD;&#xA;    gl_FragColor = vec4(color.rgb, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Instead of the polygonal bokeh (achieved by setting the value of `vertices`), I'd like a custom bitmap, such as a heart, to be displayed." ContentLicense="CC BY-SA 4.0" />
  <row Id="35915" PostHistoryTypeId="2" PostId="12435" RevisionGUID="45ec7245-3227-4fb6-927b-66244c27f5ea" CreationDate="2022-01-01T02:14:07.850" UserId="482" Text="I can see 2 ways of attacking this.&#xD;&#xA;&#xD;&#xA;1. You could organize all the walls of the world into a *tree* data structure (or maybe a *forest*, if you have like a list of separate rooms). This way, you can arrange the wall data so p1 always comes before p2 when traversing the points to draw the walls.&#xD;&#xA;&#xD;&#xA;2. Use the natural ordering from the underlying coordinate system. Assuming you already have a 3D space, then you've got a straightforward way to sort the points of a line.  &#xD;&#xA;&#xD;&#xA;    (ax,ay,az,bx,by,bz)=&gt;ax&lt;bx?-1:ax&gt;bx?1:ay&lt;by?-1:ay&gt;by?1:az&lt;bz?-1:az&gt;bz?1:0&#xD;&#xA;&#xD;&#xA;You could use this ordering to sort the points of a line and always draw it in a consistent orientation. &#xD;&#xA;&#xD;&#xA;Re-reading the question, I may not have fully understood what the problem is that you're facing. Hopefully this will at least spark some ideas.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35917" PostHistoryTypeId="50" PostId="12365" RevisionGUID="caa01f1c-f709-41e1-bc68-0800ec6001a2" CreationDate="2022-01-01T13:06:10.543" UserId="-1" />
  <row Id="35918" PostHistoryTypeId="2" PostId="12436" RevisionGUID="97151247-1296-4338-a2e7-ba3977b945a9" CreationDate="2022-01-01T17:11:49.757" UserId="17772" Text="As an information, Vulkan is a low-level abstraction layer thru modern GPU. It allows programmers to program the GPU and assemble [rendering pipeline](https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Introduction). On that pipeline, there are modules of program which are called &quot;shaders&quot;. As a programmer, we only have control on programmable shaders, not fixed shaders. For simplicity, let's only use two types of programmable shaders:&#xD;&#xA;&#xD;&#xA;1. Vertex Shader&#xD;&#xA;&#xD;&#xA;   A program for calculating geometric transformation for each point. Every 3 points always represent a triangle, but can be configured to be 3 lines or 3 dots.&#xD;&#xA;&#xD;&#xA;2. Fragment Shader&#xD;&#xA;&#xD;&#xA;   This is per-pixel program to calculate color for each pixel on that triangles (or lines).&#xD;&#xA;&#xD;&#xA;From those shaders, I would like to implement [bezier curve](https://www.tutorialspoint.com/computer_graphics/computer_graphics_curves.htm) (for shape) and [scanline algorithm](https://www.tutorialspoint.com/computer_graphics/polygon_filling_algorithm.htm) for fill color, rendered with GPU. The planned result would be like this.&#xD;&#xA;&#xD;&#xA;[![Heart shape drawn with bezier and scanline][1]][1]&#xD;&#xA;&#xD;&#xA;## The Problem&#xD;&#xA;&#xD;&#xA;1. To draw Bezier lines, pixel position must be set. Whereas in fragment shader, the pixel position [cannot be set by programmer](https://stackoverflow.com/a/17945094/3730834) because  GPU already set the position.&#xD;&#xA;2. As far as I know, generating curved lines is not possible by only set control points as vertices. Any workaround for this problem?&#xD;&#xA;3. Even if the bezier can be drawn by GPU, how do I implement scanline algorithm for adding fill color with fragment shader?&#xD;&#xA;&#xD;&#xA;**NOTE:** I already explored learning resources via internet. However, none of them actually talks about bezier curve + scanline algorithm implementation with Vulkan. Perhaps I missed something? Please let me know&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CwOhU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35920" PostHistoryTypeId="1" PostId="12436" RevisionGUID="97151247-1296-4338-a2e7-ba3977b945a9" CreationDate="2022-01-01T17:11:49.757" UserId="17772" Text="Is drawing Bezier curve with scanline algorithm possible with Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35921" PostHistoryTypeId="3" PostId="12436" RevisionGUID="97151247-1296-4338-a2e7-ba3977b945a9" CreationDate="2022-01-01T17:11:49.757" UserId="17772" Text="|gpu|vulkan|2d-graphics|bezier-curve|scanline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35922" PostHistoryTypeId="2" PostId="12437" RevisionGUID="117e8070-8c82-4610-89a3-cf1791e40e00" CreationDate="2022-01-01T20:30:56.857" UserId="7952" Text="The typical solution is to compute a bounding structure using triangles that would be transformed by the vertex shader. The bounding structure is computed to be large enough to fit the entire curve that will be drawn inside of it. It can be anything from a simple quad to a tightly fitted polygon.&#xD;&#xA;&#xD;&#xA;The fragment shader then does the work of deciding which fragments get colored by figuring out if a fragment lies in the area shaded by the curve. If a fragment isn't shaded then either the fragment is discarded, it is set to some background color, or it's alpha value is set to be fully transparent depending on programs needs. And of course if it is shaded the color is set to the curve color.&#xD;&#xA;&#xD;&#xA;Normally the computations are done in object space to help simplify some of the logic/computations in the fragment shader.&#xD;&#xA;&#xD;&#xA;There are a variety of approach's used to determine if a fragment should be discarded or not for Bezier curves. Such as computing the winding of each curve segment and determining which side of the winding the fragment falls on. Usually the winding is reduced to having a positive and a negative side. If a fragment falls on the positive side of every curve it is kept, otherwise it is discarded.&#xD;&#xA;&#xD;&#xA;BTW this is a *very* general description of how fonts can be drawn directly from font outlines.&#xD;&#xA;&#xD;&#xA;The reason you don't find a lot of information about this on the web is because it generally falls under more advanced techniques, there have also been attempts to create generalized algorithms that have several aliasing problems resulting from numerical instability.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35924" PostHistoryTypeId="50" PostId="12384" RevisionGUID="09acc9bb-4084-4d9b-b535-a2aca2843da1" CreationDate="2022-01-02T16:00:35.040" UserId="-1" />
  <row Id="35925" PostHistoryTypeId="2" PostId="12438" RevisionGUID="2e3d4637-7f5b-4225-ac2b-c2f1499ae290" CreationDate="2022-01-03T14:51:22.460" UserId="17343" Text="Suppose $P_1$ and $P_2$ two different points on surface. And let &#xD;&#xA;- $l$: be the light source direction,&#xD;&#xA;- $n$: normal vector&#xD;&#xA;- $r$: specular reflection direction&#xD;&#xA;- $v$: viewing direction . &#xD;&#xA;&#xD;&#xA;In case 1 (at $P_1$) the angel between $l$ and $n$ is $\theta_1.$ And specular reflection $r$ coincide with $v.$ So we get maximum specular intensity $I_1$,say. &#xD;&#xA;Like the image below:&#xD;&#xA;&#xD;&#xA;[![**enter image description here**][1]][1]&#xD;&#xA;&#xD;&#xA;In case 2 (at $P_2$) $l$ is positioned as case 1. But $n$ is different on $P_2$. The angle between $l$ and $n$ is $\theta_2.$ And in this case also specular reflection $r$ coincide with $v.$  So --let's say that-- the maximum specular intensity is $I_2$. In this case we have different angle between $n$ and $l,$ different $r,$ different $v$ from case1.&#xD;&#xA;&#xD;&#xA;Like the image below :&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My question is specular intensity $I_1$ has greater intensity than $I_2$ or $I_1$ and $I_2$ are equal ? &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qRK9x.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/DHy5n.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35927" PostHistoryTypeId="1" PostId="12438" RevisionGUID="2e3d4637-7f5b-4225-ac2b-c2f1499ae290" CreationDate="2022-01-03T14:51:22.460" UserId="17343" Text="Specular reflection with different viewing direction where reflection direction and viewing direction coincide" ContentLicense="CC BY-SA 4.0" />
  <row Id="35928" PostHistoryTypeId="3" PostId="12438" RevisionGUID="2e3d4637-7f5b-4225-ac2b-c2f1499ae290" CreationDate="2022-01-03T14:51:22.460" UserId="17343" Text="|lighting|shading|global-illumination|specular|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35929" PostHistoryTypeId="2" PostId="12439" RevisionGUID="7edf9e00-756a-4c99-bfed-f13eaf08b678" CreationDate="2022-01-03T18:56:18.207" UserId="17768" Text="It is possible to implement the CIE Lab/XYZ color space in GLSL, to shift the hue/change chroma of colors/images?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35931" PostHistoryTypeId="1" PostId="12439" RevisionGUID="7edf9e00-756a-4c99-bfed-f13eaf08b678" CreationDate="2022-01-03T18:56:18.207" UserId="17768" Text="Shift hue/adjust chroma in CIE Lab space using GLSL" ContentLicense="CC BY-SA 4.0" />
  <row Id="35932" PostHistoryTypeId="3" PostId="12439" RevisionGUID="7edf9e00-756a-4c99-bfed-f13eaf08b678" CreationDate="2022-01-03T18:56:18.207" UserId="17768" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35933" PostHistoryTypeId="5" PostId="12438" RevisionGUID="d58313ad-fd71-45a5-8a03-dbe766eb1540" CreationDate="2022-01-03T19:05:39.877" UserId="17343" Comment="deleted 32 characters in body" Text="Suppose $P_1$ and $P_2$ two different points on surface. And let &#xD;&#xA;- $l$: be the light source direction,&#xD;&#xA;- $n$: normal vector&#xD;&#xA;- $r$: specular reflection direction&#xD;&#xA;- $v$: viewing direction . &#xD;&#xA;&#xD;&#xA;In case 1 (at $P_1$) the angel between $l$ and $n$ is $\theta_1.$ And specular reflection $r$ coincide with $v.$ So we get maximum specular intensity $I_1$,say. &#xD;&#xA;Like the image below:&#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/8NOIG.jpg)&#xD;&#xA;&#xD;&#xA;In case 2 (at $P_2$) $l$ is positioned as case 1. But $n$ is different on $P_2$. The angle between $l$ and $n$ is $\theta_2.$ And in this case also specular reflection $r$ coincide with $v.$  So --let's say that-- the maximum specular intensity is $I_2$. In this case we have different angle between $n$ and $l,$ different $r,$ different $v$ from case1.&#xD;&#xA;&#xD;&#xA;Like the image below :&#xD;&#xA;&#xD;&#xA;![enter image description here](https://i.stack.imgur.com/sQbMy.jpg)&#xD;&#xA;&#xD;&#xA;My question is specular intensity $I_1$ has greater intensity than $I_2$ or $I_1$ and $I_2$ are equal ? &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35934" PostHistoryTypeId="5" PostId="12439" RevisionGUID="0f7a15d1-4ff0-44b8-a689-07305dc46281" CreationDate="2022-01-03T19:08:03.310" UserId="17768" Comment="added 33 characters in body" Text="It is possible to implement the CIE Lab/XYZ color space in GLSL, to shift the hue/change chroma of colors/images? Does it require compute shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35935" PostHistoryTypeId="2" PostId="12440" RevisionGUID="06394423-ae4a-459c-af0e-29d2d9975c59" CreationDate="2022-01-04T05:44:17.980" UserId="11224" Text="**Question:**&#xD;&#xA;&#xD;&#xA;What is going wrong with the shape of the contours of constant illumination in the below picture ?&#xD;&#xA;&#xD;&#xA;**Detail:**&#xD;&#xA;&#xD;&#xA;Although Lambertian shading might be ill-regarded because it exposes the hard edges of our low-poly models, and because it models only &quot;matte&quot; surfaces, which it supposes reflect light equally in all directions (in particular, independent of the direction to the camera), yet I understand that it is considered a reasonably accurate approximation to how a single (hence no shadows, no illumination from light bouncing off surfaces and hitting other surfaces, no ambient occlusion etc) planar matte surface might look in space, say, illuminated by several lights which are either effectively infinitely far away (like the sun), or else nearby.&#xD;&#xA;&#xD;&#xA;I would like to make the physically correct choice to have the surface normal vector constant across the surface of my triangle, that is, I do not want to use any of the various tricks that make the mesh look smoother, by averaging vertex normals over the triangles sharing the vertex, etc.&#xD;&#xA;&#xD;&#xA;I believe that the intensity of incident light should decrease as the inverse square of the distance to the light (and therefore be effectively constant, for lights effectively infinitely far away, like the sun) ? But I am not sure. In any case, I would like to ignore this possible effect for now.&#xD;&#xA;&#xD;&#xA;I would also like to ignore specular effects, whether produced by raising to some power, the cosine of the angle between the surface normal and the direction to the light, as in Blinn and Phong, or by more physically accurate models.&#xD;&#xA;&#xD;&#xA;In spite of all these simplifications, I believe that I still must interpolate across the triangle, since the direction from the point on the triangle to the light source varies with that point (given that my light is *not* infinitely far away, but rather is quite close to the model). My understanding is that in world coordinates, it is mathematically correct to interpolate that cosine linearly between the 3 vertices, using for instance Barycentric coordinates.&#xD;&#xA;&#xD;&#xA;My understanding of perspective projections is that linear interpolation in the world space becomes hyperbolic interpolation, after the perspective projection and w-divide transform coordinates into normalised device coordinates (NDCs). The GPU automatically uses such hyperbolic interpolation, for occlusion testing with the z-buffer, I believe. That is, it measures the reciprocal z at each vertex, and then for each pixel interior to the triangle, it linearly interpolates between those reciprocals, and takes the reciprocal of the result, to get a correct z value. Similarly, any quantity that varies linearly across the triangle in world-space must be treated the same way, once in NDCs.&#xD;&#xA;&#xD;&#xA;In the picture below, I have a square made from two triangles joined along the top-left to bottom-right diagonal, lying in a horizontal plane. The camera is above the square, looking down on it, via a reversed-z, infinite far-plane, perspective projection matrix. I have a light source close to the plane of the square but just above it, and (as we look at it) off the bottom-right corner of the image. As expected, the bottom-right corner of the square is brighter than the top-left corner. Also as expected (if we look very carefully) we see faint Mach bands, due to the quantisation of colour and the characteristics of our eyes / brain.&#xD;&#xA;&#xD;&#xA;[![Strange shading][1]][1]&#xD;&#xA;&#xD;&#xA;I would expect the Mach bands to form concentric circles, being the level sets of the cosine mentioned above. Even without any explicit attenuation of intensity due to the distance to the light (see above). However, they do not, or if they do, then the centre of the circle is much farther away than the light source, and is different for the two triangles. It seems as if maybe something has gone wrong with the interpolation. Perhaps it is being done linearly instead of hyperbolically ? Even though Blinn explained this potential error in 1992:&#xD;&#xA;&#xD;&#xA;[Hyperbolic Interpolation - Jim Blinn][2]&#xD;&#xA;&#xD;&#xA;I am using the very old-fashioned, deprecated, (Immediate-mode ? Fixed Function ?) style of OpenGL. I am given to understand that by using the modern type of OpenGL, with shaders etc, I could specify the lighting more or less exactly as I would like. But I am trying to find out whether the model described above is achievable in the old-fashioned OpenGL. It seems as if it ought to be, since even that kind of OpenGL was capable of techniques fancier than Lambertian shading, for instance, specular lights.&#xD;&#xA;&#xD;&#xA;Here are some of my settings:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    GLfloat light0_position[] = {800.0f, 0.0f, -(float)screendistmm + 800.0f, 1.0f};&#xD;&#xA;    GLfloat light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};&#xD;&#xA;    GLfloat light0_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};&#xD;&#xA;&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);&#xD;&#xA;   &#xD;&#xA;    glShadeModel(GL_SMOOTH);&#xD;&#xA;&#xD;&#xA;    glEnable(GL_LIGHT0);&#xD;&#xA;&#xD;&#xA;    glEnable(GL_RESCALE_NORMAL);&#xD;&#xA;    glEnable(GL_NORMALIZE);&#xD;&#xA;&#xD;&#xA;    // Enable gamma-correction:&#xD;&#xA;    glEnable(GL_FRAMEBUFFER_SRGB);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glEnable(GL_LIGHTING);&#xD;&#xA;&#xD;&#xA;    glBegin(GL_TRIANGLE_FAN);&#xD;&#xA;&#xD;&#xA;         GLfloat colour[] = {1.0f, 0.5f, 0.5f, 1.0f};&#xD;&#xA;         glMaterialfv(GL_FRONT, GL_DIFFUSE, colour);&#xD;&#xA;         glNormal3f(0.0f, 1.0f, 0.0f);&#xD;&#xA;&#xD;&#xA;         glVertex4f(-500.0f, -200.0f, -500.0f - (float)screendistmm, 1.0f);&#xD;&#xA;         glVertex4f(-500.0f, -200.0f, 500.0f - (float)screendistmm, 1.0f);&#xD;&#xA;         glVertex4f(500.0f, -200.0f, 500.0f - (float)screendistmm, 1.0f);&#xD;&#xA;         glVertex4f(500.0f, -200.0f, -500.0f - (float)screendistmm, 1.0f);&#xD;&#xA;&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iHVhG.png&#xD;&#xA;  [2]: https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&amp;arnumber=8891846" ContentLicense="CC BY-SA 4.0" />
  <row Id="35937" PostHistoryTypeId="1" PostId="12440" RevisionGUID="06394423-ae4a-459c-af0e-29d2d9975c59" CreationDate="2022-01-04T05:44:17.980" UserId="11224" Text="OpenGL old-style diffuse shading producing unexpected effects" ContentLicense="CC BY-SA 4.0" />
  <row Id="35938" PostHistoryTypeId="3" PostId="12440" RevisionGUID="06394423-ae4a-459c-af0e-29d2d9975c59" CreationDate="2022-01-04T05:44:17.980" UserId="11224" Text="|lighting|projections|shading|diffuse|legacy-opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35939" PostHistoryTypeId="2" PostId="12441" RevisionGUID="111a8924-9b7d-4073-8d99-fbcceb0844c4" CreationDate="2022-01-04T13:50:45.697" UserId="10096" Text="The rendering equation is the standard equation that people use to approximate geometric optics in computer graphics. The equation reads:&#xD;&#xA;&#xD;&#xA;$$L(x, \omega_o) = L_e(x, \omega_o) + \int_{\Omega_x}f(\omega_o, x, \omega_i) L_i(x, \omega_i)\cos\theta_i\,d\omega_i,$$&#xD;&#xA;&#xD;&#xA;where $L$ is the radiance function (we want to find this function to compute the radiance arriving at the virtual camera sensors in the scene corresponding to specific pixels). $L_e$ is the emitted radiance from surface point $x$ in direction $\omega_o$ and it is non-zero only for light-sources - it basically encodes the strength/colour of light sources in the scene. $\Omega_x$ is the upper hemisphere around the normal $N_x$ at point $x$. The [Lambertian factor][1] is $\cos\theta_i = \omega_i \cdot N_x$ where $\omega_i$ is a direction from $\Omega_x$. It accounts for light getting spread out over a larger area for larger angles with the normal. $L_i(x, \omega_i)$ is the radiance arriving at $x$ from direction $\omega_i$. In vaccum we have $L(\gamma(x,\omega_i), -\omega_i) = L_i(x,\omega_i)$, where $\gamma$ is the ray-tracing function. Finally $f$ is the [brdf][2]: it describes the light scattering properties of the surfaces in the scene - e.g. wood scatters light differently than metal or an ideal mirror.&#xD;&#xA;&#xD;&#xA;As I understand it, you are only interested in one bounce reflected light, this is accounted by changing $L_i$ to $L_e$ and ignoring the direct emission:&#xD;&#xA;&#xD;&#xA;$$L(x, \omega_o) = \int_{\Omega_x}f(\omega_o, x, \omega_i) L_e(r(x,\omega_i), -\omega_i)\cos\theta_i\,d\omega_i$$,&#xD;&#xA;&#xD;&#xA;and from now on I'll set $y=r(x,\omega_i)$ for simplicity. You also seem to be considering a single directional light, which amounts to setting a Dirac delta light source: $L_e(y,-\omega_i) = \delta(l - \omega_i)$. Setting $v=\omega_o, \, n=N_x$ and plugging into the equation yields:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = f(v, x, l)(n \cdot l)$$&#xD;&#xA;&#xD;&#xA;The behaviour wrt the angle between $n$ and $l$ in the above depends on $f$. Let us consider some examples. The specular part of the Phong brdf is: $f(v,x,l) = C\frac{(r\cdot v)^{\alpha}}{n\cdot l}$ which results in:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = C(r\cdot v)^{\alpha}$$&#xD;&#xA;&#xD;&#xA;and thus if $r=v$ then the angle between $n$ and $l$ doesn't affect the radiance. Now consider the energy-conserving modification of the Phong brdf: $f(v,x,l) = C(r\cdot v)^{\alpha}$, which results in:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = C(r\cdot v)^{\alpha}(n\cdot l)$$&#xD;&#xA;&#xD;&#xA;If $\theta = \angle (n, l)$ then if $\theta_1&lt;\theta_2$ it follows that $L_1&gt;L_2$. Now consider some imaginary brdf $f(v,x,l) = C\frac{(r\cdot v)^{\alpha}}{(n\cdot l)^2}$, then you have:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = C\frac{(r\cdot v)^{\alpha}}{n\cdot l}$$&#xD;&#xA;&#xD;&#xA;and it follows that $\theta_1&lt;\theta_2 \implies L_1&lt;L_2$. From this you can conclude that you can get all possible cases based on your choice of brdf. My guess is that for most physically plausible brdfs however the following would hold: $\theta_1&lt;\theta_2 \implies L_1&gt;L_2$ due to [Lambert's cosine law][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Lambert%27s_cosine_law&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="35941" PostHistoryTypeId="5" PostId="12441" RevisionGUID="88437d41-96ef-4906-b48a-fff5a13f7945" CreationDate="2022-01-04T13:57:29.237" UserId="10096" Comment="added 19 characters in body" Text="The rendering equation is the standard equation that people use to approximate geometric optics in computer graphics. The equation reads:&#xD;&#xA;&#xD;&#xA;$$L(x, \omega_o) = L_e(x, \omega_o) + \int_{\Omega_x}f(\omega_o, x, \omega_i) L_i(x, \omega_i)\cos\theta_i\,d\omega_i,$$&#xD;&#xA;&#xD;&#xA;where $L$ is the radiance function (we want to find this function to compute the radiance arriving at the virtual camera sensors in the scene corresponding to specific pixels). $L_e$ is the emitted radiance from surface point $x$ in direction $\omega_o$ and it is non-zero only for light-sources - it basically encodes the strength/colour of light sources in the scene. $\Omega_x$ is the upper hemisphere around the normal $N_x$ at point $x$. The [Lambertian factor][1] is $\cos\theta_i = \omega_i \cdot N_x$ where $\omega_i$ is a direction from $\Omega_x$. It accounts for light getting spread out over a larger area for larger angles with the normal. $L_i(x, \omega_i)$ is the radiance arriving at $x$ from direction $\omega_i$. In vaccum we have $L(\gamma(x,\omega_i), -\omega_i) = L_i(x,\omega_i)$, where $\gamma$ is the ray-tracing function. Finally $f$ is the [brdf][2]: it describes the light scattering properties of the surfaces in the scene - e.g. wood scatters light differently than metal or an ideal mirror.&#xD;&#xA;&#xD;&#xA;As I understand it, you are only interested in one bounce reflected light, this is accounted by changing $L_i$ to $L_e$ and ignoring the direct emission:&#xD;&#xA;&#xD;&#xA;$$L(x, \omega_o) = \int_{\Omega_x}f(\omega_o, x, \omega_i) L_e(r(x,\omega_i), -\omega_i)\cos\theta_i\,d\omega_i$$,&#xD;&#xA;&#xD;&#xA;and from now on I'll set $y=r(x,\omega_i)$ for simplicity. You also seem to be considering a single directional light, which amounts to setting a Dirac delta light source: $L_e(y,-\omega_i) = \delta(l - \omega_i)$. Setting $v=\omega_o, \, n=N_x$ and plugging into the equation yields:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = f(v, x, l)(n \cdot l)$$&#xD;&#xA;&#xD;&#xA;The behaviour wrt the angle between $n$ and $l$ in the above depends on $f$. Let us consider some examples. The specular part of the Phong brdf is: $f(v,x,l) = C\frac{(r\cdot v)^{\alpha}}{n\cdot l}$ which results in:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = C(r\cdot v)^{\alpha}$$&#xD;&#xA;&#xD;&#xA;and thus if $r=v$ then the angle between $n$ and $l$ doesn't affect the radiance. Now consider the energy-conserving modification of the Phong brdf: $f(v,x,l) = C(r\cdot v)^{\alpha}$, which results in:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = C(r\cdot v)^{\alpha}(n\cdot l)$$&#xD;&#xA;&#xD;&#xA;If $r=v$ and $\theta = \angle (n, l)$ then if $\theta_1&lt;\theta_2$ it follows that $L_1&gt;L_2$. Now consider some imaginary brdf $f(v,x,l) = C\frac{(r\cdot v)^{\alpha}}{(n\cdot l)^2}$, then you have:&#xD;&#xA;&#xD;&#xA;$$L(x, v) = C\frac{(r\cdot v)^{\alpha}}{n\cdot l}$$&#xD;&#xA;&#xD;&#xA;and if $r=v$ it follows that $\theta_1&lt;\theta_2 \implies L_1&lt;L_2$. From this you can conclude that you can get all possible cases based on your choice of brdf. My guess is that for most physically plausible brdfs however the following would hold: $\theta_1&lt;\theta_2 \implies L_1&gt;L_2$ due to [Lambert's cosine law][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Lambert%27s_cosine_law&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="35946" PostHistoryTypeId="2" PostId="12443" RevisionGUID="1545ee4f-065b-4207-a875-521759ce51d5" CreationDate="2022-01-04T22:12:26.157" UserId="17794" Text="I have a question regarding the NEE for light sources that are composed from triangles. I implemented the next event estimation (explicit light source sampling) for spherical light sources but after all of the trials, the output is always noisy and not even close to spherical luminaries.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            else if(const Triangle* tr=dynamic_cast&lt;const Triangle*&gt;(prim))&#xD;&#xA;			{&#xD;&#xA;				double ran1=rand01();&#xD;&#xA;				double ran2=rand01();&#xD;&#xA;&#xD;&#xA;				double alpha=1-sqrt(ran1);&#xD;&#xA;				double beta=(1-ran2)*sqrt(ran1);&#xD;&#xA;				double gamma=ran2*sqrt(ran1);&#xD;&#xA;&#xD;&#xA;				while(alpha+beta&gt;1)&#xD;&#xA;				{&#xD;&#xA;					ran1=rand01();&#xD;&#xA;					ran2=rand01();&#xD;&#xA;					alpha=1-sqrt(ran1);&#xD;&#xA;					beta=(1-ran2)*sqrt(ran1);&#xD;&#xA;				}&#xD;&#xA;&#xD;&#xA;				Vec firstEdge=tr-&gt;vertex1-tr-&gt;vertex0;&#xD;&#xA;				Vec secondEdge=tr-&gt;vertex2-tr-&gt;vertex0;&#xD;&#xA;				Vec nPrime=secondEdge.cross(firstEdge);&#xD;&#xA;				double A=nPrime.length()*1/2;&#xD;&#xA;&#xD;&#xA;				Vec xPrime = tr-&gt;vertex0*alpha+tr-&gt;vertex1*beta+tr-&gt;vertex2*gamma;&#xD;&#xA;&#xD;&#xA;				Vec omega=(xPrime-x).normalize();&#xD;&#xA;				Vec inverseOmega=(x-xPrime).normalize();&#xD;&#xA;&#xD;&#xA;				double cosTheta=clamp(((n-x).normalize()).dot(inverseOmega))/(n-x).length()*inverseOmega.length();&#xD;&#xA;				double cosThetaPrime=abs(((nPrime-xPrime).normalize()).dot(omega))/(nPrime-xPrime).length()*omega.length();&#xD;&#xA;				double magOfxPrimeToX=(xPrime-x).dot(xPrime-x);&#xD;&#xA;				&#xD;&#xA;				int idShadowRay=0;&#xD;&#xA;				double tShadowRay;&#xD;&#xA;				Vec xShadowRay;&#xD;&#xA;				Vec nShadowRay;&#xD;&#xA;&#xD;&#xA;				if(intersect(Ray(x,xPrime),idShadowRay,tShadowRay,xShadowRay,nShadowRay) &amp;&amp; idShadowRay==i)&#xD;&#xA;				{&#xD;&#xA;					L_direct = L_direct + (f.mult(tr-&gt;e))*(cosTheta)*(cosThetaPrime/magOfxPrimeToX) /(1/A);&#xD;&#xA;				}&#xD;&#xA;			&#xD;&#xA;			}&#xD;&#xA;After the loop ends for the light sources, I add direct contribution and indirect contribution in the return statement:&#xD;&#xA;`return obj.e * emissive + L_direct + f.mult(radiance(Ray(x, d), depth, 0));`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result with 150 sample with 750x500 resolution: &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However spherical light sources are quite succesful in same specifications (150 sample with 750x500 resolution):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cabsi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/xa9I6.jpg&#xD;&#xA;&#xD;&#xA;What could be wrong in this case ? Thanks a lot." ContentLicense="CC BY-SA 4.0" />
  <row Id="35948" PostHistoryTypeId="1" PostId="12443" RevisionGUID="1545ee4f-065b-4207-a875-521759ce51d5" CreationDate="2022-01-04T22:12:26.157" UserId="17794" Text="Next Event Estimation for Triangle-based Light Sources" ContentLicense="CC BY-SA 4.0" />
  <row Id="35949" PostHistoryTypeId="3" PostId="12443" RevisionGUID="1545ee4f-065b-4207-a875-521759ce51d5" CreationDate="2022-01-04T22:12:26.157" UserId="17794" Text="|raytracing|pathtracing|lighting|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35950" PostHistoryTypeId="50" PostId="10384" RevisionGUID="b62dc58c-7639-4823-a946-daa31c4fcb2f" CreationDate="2022-01-06T10:00:15.023" UserId="-1" />
  <row Id="35951" PostHistoryTypeId="50" PostId="9426" RevisionGUID="e104831b-fd2c-43b3-8724-f83681048fc1" CreationDate="2022-01-06T13:05:50.660" UserId="-1" />
  <row Id="35952" PostHistoryTypeId="2" PostId="12444" RevisionGUID="68c1b5bc-0278-4384-bc86-d345f3e4c6bf" CreationDate="2022-01-06T19:50:19.023" UserId="11458" Text="First of all I am not sure if this is the correct place to ask my question. If it is not please be so kind to point me in a direction where my question is relevant. &#xD;&#xA;&#xD;&#xA;A while ago I came across this cross platform graphics library called [Veldrid][1].  &#xD;&#xA;Resulting in me getting the idea to write my own [processing][2] clone but then for C#. Only problem with this plan is that I have absolutely no knowledge about graphics programming. So I started researching the matter with little luck... since what i found was either too generic or way to academic. &#xD;&#xA;&#xD;&#xA;What I really want to know is; is it even possible to write a 2d renderer with a gpu powered graphics library (eg opengl, metal, vulkan etc). And if so how do you write the renderer? &#xD;&#xA;&#xD;&#xA;My initial way of going about it was the following: create a bunch of shaders to render things like rectangles, ellipses, triangles, lines etc. and linking them with a uniformbuffers to send shader properties on how to draw the ellipse colour for example. &#xD;&#xA;&#xD;&#xA;But this seems to become very dumb when having to render lines, since in this case i would make a quad have a shader draw a line in the quad and have the leftover pixels transparent. Which seems very inefficient. &#xD;&#xA;&#xD;&#xA;Any advice would be super helpful! But please keep it noob friendly since i am no where near an amateur on the subject :) &#xD;&#xA;&#xD;&#xA;If any clarification or additional information is needed please let me know!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/mellinoe/veldrid&#xD;&#xA;  [2]: https://processing.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="35954" PostHistoryTypeId="1" PostId="12444" RevisionGUID="68c1b5bc-0278-4384-bc86-d345f3e4c6bf" CreationDate="2022-01-06T19:50:19.023" UserId="11458" Text="2d gpu powered rendering engine" ContentLicense="CC BY-SA 4.0" />
  <row Id="35955" PostHistoryTypeId="3" PostId="12444" RevisionGUID="68c1b5bc-0278-4384-bc86-d345f3e4c6bf" CreationDate="2022-01-06T19:50:19.023" UserId="11458" Text="|rendering|gpu|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35957" PostHistoryTypeId="2" PostId="12445" RevisionGUID="0c4b2b12-ab14-4daf-b1d1-8f183e324d88" CreationDate="2022-01-07T13:12:10.480" UserId="7952" Text="Writing a 2D render system is a perfectly reasonable thing to do using any of the Graphics API's that you listed.&#xD;&#xA;&#xD;&#xA;Triangles are the basic medium of all the popular graphics API's so learning to work with, and manipulate triangles whether it is in 2D or 3D is one of the big hurdles to getting a render system up and running.&#xD;&#xA;&#xD;&#xA;OpenGL tends to be the most popular and is (usually) considered to be the easiest API to learn. There are many tutorials on OpenGL as well,  most of those tutorials like learnopengl.com are focused on 3D, but working through those examples will familiarize you with the interface also a 2D rendering system will use the same interfaces just in a slightly different way. &#xD;&#xA;&#xD;&#xA;You will have to learn some linear math for things like rotations and translation, but the good news is almost all decent resources on the subject start out by describing 2D linear math. The bad news is that there is really no way around the academic side of the math. The really bad news is that a 2D homogenous coordinate system is the best way manage objects. A homogenous coordinate system allows you to put objects in there own private coordinate systems, do &quot;work&quot; on objects inside that coordinate system, and then easily move objects into a different, usually shared, coordinate system. It sounds complicated but once you get the main ideas it is actually very easy. Also there are some outstanding entry level books on the subject that cover 2D rendering really well.&#xD;&#xA;&#xD;&#xA;The next major component of the rendering system is the actual code that it gets written in. C++ tends to be the most popular mostly because it is a fairly expressive language that can be optimized very well. However learning the entire C++ language can be very daunting. Luckily you can pick and chose some areas of the language to get started then expand your knowledge base as you become familiar with the language. These days scripting languages offer decent efficiency and tend to be easier to learn. A scripting language could be a good choice since it would allow more development focus to be put on learning the graphics side. Unfortunately scripting languages have limits. They don't expose the entire graphics API, they don't allow some high level concepts, and they have performance limitations. But much of that can be worked around. (except the performance which is what eventually drives many programmers to languages like C++)" ContentLicense="CC BY-SA 4.0" />
  <row Id="35959" PostHistoryTypeId="5" PostId="12445" RevisionGUID="198ed400-7a1d-419f-9dd6-0dfd1f944ffc" CreationDate="2022-01-07T13:17:34.633" UserId="7952" Comment="added 13 characters in body" Text="Writing a 2D render system is a perfectly reasonable thing to do using any of the Graphics API's that you listed.&#xD;&#xA;&#xD;&#xA;Triangles are the basic medium of all the popular graphics API's so learning to work with, and manipulate triangles whether it is in 2D or 3D is one of the big hurdles to getting a render system up and running.&#xD;&#xA;&#xD;&#xA;OpenGL tends to be the most popular and is (usually) considered to be the easiest API to learn. There are many tutorials on OpenGL as well,  most of those tutorials like learnopengl.com are focused on 3D, but working through those examples will familiarize you with the interface also a 2D rendering system will use the same interfaces just in a slightly different way. &#xD;&#xA;&#xD;&#xA;You will have to learn some linear math for things like rotations and translation, but the good news is almost all decent resources on the subject start out by describing 2D linear math. The bad news is that there is really no way around the academic side of the math. The really bad news is that a 2D homogenous coordinate system is the best way manage objects. A homogenous coordinate system allows you to put objects in there own private coordinate systems, do &quot;work&quot; on objects inside that coordinate system, and then easily move objects into a different, usually shared, coordinate system. It sounds complicated but once you get the main ideas it is actually very easy. Also there are some outstanding entry level books on the subject that cover 2D rendering really well.&#xD;&#xA;&#xD;&#xA;The next major component of the rendering system is the actual code that it gets written in. C++ tends to be the most popular mostly because it is a fairly expressive language that can be optimized very well. However learning the entire C++ language can be very daunting. Luckily you can pick and chose some areas of the language to get started then expand your knowledge base as you become familiar with the language. These days scripting languages offer decent efficiency and tend to be easier to learn. A scripting language could be a good choice since it would allow more development focus to be put on learning the graphics side. Unfortunately scripting languages have limits. They don't expose the entire graphics API, they don't allow very low level access to the hardware, and they have performance limitations. But much of that can be worked around. (except the performance which is what eventually drives many programmers to languages like C++)" ContentLicense="CC BY-SA 4.0" />
  <row Id="35960" PostHistoryTypeId="2" PostId="12446" RevisionGUID="6187f5a2-ef98-43a0-987d-c9bdccaa6471" CreationDate="2022-01-07T21:13:01.743" UserId="17813" Text="[![milk jug from thesis][1]][1]&#xD;&#xA;&#xD;&#xA;The little milk pitcher / jug in [Ed Catmull][2]'s 1975 PhD thesis [“The Utilization of Procedure Models in Digital Image Synthesis”][3], does anybody have the bicubic patch data for it?  The teapot's data ([in several early versions][4]) is well-distributed of course, [the spoon and cup/saucer are downloadable][5] from a few repositories.  But (so far) [I can't find the milk jug's][6].&#xD;&#xA;&#xD;&#xA;Is it lost forever, or is somebody out there willing / able to make it available?&#xD;&#xA;&#xD;&#xA;[![Figure 29  Table Setting][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rySjW.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Edwin_Catmull&#xD;&#xA;  [3]: https://collections.lib.utah.edu/ark:/87278/s6hh73p6&#xD;&#xA;  [4]: http://www.holmes3d.net/graphics/teapot/&#xD;&#xA;  [5]: https://github.com/rm-hull/newell-teapot&#xD;&#xA;  [6]: https://blenderartists.org/t/how-do-i-propose-an-addition-to-the-extra-objects-add-on/1351462/16&#xD;&#xA;  [7]: https://i.stack.imgur.com/bJvNG.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35962" PostHistoryTypeId="1" PostId="12446" RevisionGUID="6187f5a2-ef98-43a0-987d-c9bdccaa6471" CreationDate="2022-01-07T21:13:01.743" UserId="17813" Text="Historically Significant 3D Bicubic Patch Data?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35963" PostHistoryTypeId="3" PostId="12446" RevisionGUID="6187f5a2-ef98-43a0-987d-c9bdccaa6471" CreationDate="2022-01-07T21:13:01.743" UserId="17813" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35965" PostHistoryTypeId="2" PostId="12447" RevisionGUID="7b7fd597-d606-4e6f-91f8-85bb05fe1625" CreationDate="2022-01-08T12:50:17.283" UserId="17794" Text="I found my error which was quite hard to understand but I think it is misleading on it's explanations in books. The visibility term is denoted most of the time as *V(x,x')*. However, if visibility is taken account as form one point to another, it gives a wrong answer. The correct fix for that is to get the intersection point &quot;x&quot; to direction of &quot; x' &quot;. In that case visibility is changed as *V(x,(x'-x).normalized())*. So, a direction should be used, not a point." ContentLicense="CC BY-SA 4.0" />
  <row Id="35967" PostHistoryTypeId="2" PostId="12448" RevisionGUID="60387f7f-e0eb-44e5-8765-d9736c0ccd44" CreationDate="2022-01-10T11:39:02.150" UserId="6064" Text="Hi I have a slight confusion in using the opengl perspective matrix in vulkan.&#xD;&#xA;glm's perspective matrix works directly in vulkan just by multiplying the [1][1] term by -1 but when I compared the formula for cration of perspective matrix for both the apis.&#xD;&#xA;&#xD;&#xA;opengl one here:&lt;http://www.songho.ca/opengl/gl_projectionmatrix.html&gt;&#xD;&#xA;&#xD;&#xA;vulkan here:&lt;https://www.youtube.com/watch?v=U0_ONQQ5ZNM&gt;&#xD;&#xA;&#xD;&#xA;and I see 2 diffrences:&#xD;&#xA;1st at [1][1]&#xD;&#xA;2nd at [2][3]: here is my doubt(opengl's is 2 times the one in vulkan.&#xD;&#xA;&#xD;&#xA;So how does glm's matrix work for my vulkan program just by correcting [1][1] location?&#xD;&#xA;Please do correct me if I am making some mistake in understanding the differences in matrix.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35969" PostHistoryTypeId="1" PostId="12448" RevisionGUID="60387f7f-e0eb-44e5-8765-d9736c0ccd44" CreationDate="2022-01-10T11:39:02.150" UserId="6064" Text="vulkan perspective matrix vs opengl perspective matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="35970" PostHistoryTypeId="3" PostId="12448" RevisionGUID="60387f7f-e0eb-44e5-8765-d9736c0ccd44" CreationDate="2022-01-10T11:39:02.150" UserId="6064" Text="|opengl|mathematics|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35971" PostHistoryTypeId="2" PostId="12449" RevisionGUID="f5a762c8-c5f8-4e89-987c-86670d6bc0ab" CreationDate="2022-01-10T20:45:03.447" UserId="17826" Text="I'm currently trying to implement animation blending. Or more specifically, parametric animation. Unreal Engine has this in the form of [blendspaces][1]. After some experimentation, I've noticed that they perform timewarping on the input animations *and then* blend. Meaning they change the way animations are sampled through time before performing any blending.&#xD;&#xA;&#xD;&#xA;[![An example of time warping between a running/jogging animation][2]][2]&#xD;&#xA;&#xD;&#xA;I'm having difficulty implementing timewarping and blending with more than just two animations, specifically the case for a 2D blendspace. Are there any recent papers/publications related to this? The most useful one I could find was [this one][3] from 2003. It seems more designed for static cases where the transitioning is preplanned, dynamic not as much.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.unrealengine.com/4.27/en-US/AnimatingObjects/SkeletalMeshAnimation/Blendspaces/Overview/&#xD;&#xA;  [2]: https://i.stack.imgur.com/LJnRm.png&#xD;&#xA;  [3]: https://research.cs.wisc.edu/graphics/Gallery/kovar.vol/RegistrationCurves/regCurves.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35973" PostHistoryTypeId="1" PostId="12449" RevisionGUID="f5a762c8-c5f8-4e89-987c-86670d6bc0ab" CreationDate="2022-01-10T20:45:03.447" UserId="17826" Text="How is Unreal's 2D Blendspace implemented?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35974" PostHistoryTypeId="3" PostId="12449" RevisionGUID="f5a762c8-c5f8-4e89-987c-86670d6bc0ab" CreationDate="2022-01-10T20:45:03.447" UserId="17826" Text="|animation|parametrization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35975" PostHistoryTypeId="2" PostId="12450" RevisionGUID="0fb4a5a2-3ea7-4462-9ab0-0c8838f6ca42" CreationDate="2022-01-10T21:52:39.790" UserId="7684" Text="I have some confusion regarding gamma correction and the output of my shaders. I'll start with the setup, then explain my current understanding of the matter, and finally the question.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**Setup**&#xD;&#xA;&#xD;&#xA;I'm using OpenGL ES 3.2 on Android.&#xD;&#xA;&#xD;&#xA;I have a texture (skybox) and an object in the scene. Both are rendered to an off-screen framebuffer that has a texture as color attachment. This texture is then sampled for on-screen rendering. &#xD;&#xA;&#xD;&#xA;Skybox shader:&#xD;&#xA;```cpp&#xD;&#xA;#version 320 es&#xD;&#xA;&#xD;&#xA;precision mediump float;&#xD;&#xA;&#xD;&#xA;in vec3 o_textureCoords;&#xD;&#xA;&#xD;&#xA;out vec4 o_fragColor;&#xD;&#xA;&#xD;&#xA;uniform samplerCube u_skyboxTexture;&#xD;&#xA;&#xD;&#xA;vec4 srgbToLinear(vec4 srgbColor) {&#xD;&#xA;    return vec4(pow(srgbColor.rgb, vec3(2.2)), srgbColor.a);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    o_fragColor = texture(u_skyboxTexture, o_textureCoords);               // Left&#xD;&#xA;    o_fragColor = srgbToLinear(texture(u_skyboxTexture, o_textureCoords)); // Right&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Object shader (relevant parts):&#xD;&#xA;```cpp&#xD;&#xA;#version 320 es&#xD;&#xA;&#xD;&#xA;precision mediump float;&#xD;&#xA;&#xD;&#xA;const vec3 lightColor = vec3(1.0, 1.0, 1.0);&#xD;&#xA;const vec3 objectColor = vec3(0.4, 0.2, 0.1);&#xD;&#xA;&#xD;&#xA;out vec4 o_fragColor;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    // ...&#xD;&#xA;    vec3 light = (ambient + diffuse + specular) * objectColor;&#xD;&#xA;    o_fragColor = vec4(light, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Final shader:&#xD;&#xA;```cpp&#xD;&#xA;#version 320 es&#xD;&#xA;&#xD;&#xA;precision mediump float;&#xD;&#xA;&#xD;&#xA;in vec2 o_texCoords;&#xD;&#xA;&#xD;&#xA;out vec4 o_fragColor;&#xD;&#xA;&#xD;&#xA;uniform sampler2D u_texture;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 color = texture(u_texture, o_texCoords);&#xD;&#xA;    o_fragColor = color;                                           // Left&#xD;&#xA;    o_fragColor = vec4(pow(color.rgb, vec3(1.0 / 2.2)), color.a);  // Right&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Let's consider two cases:&#xD;&#xA;&#xD;&#xA;[![No Gamma][1]][1] [![Yes Gamma][3]][3]&#xD;&#xA;&#xD;&#xA; - Left: not concerning myself with colorspace and gamma correction at all&#xD;&#xA; - Right: transforming the texture into linear colorspace and gamma correction at the end&#xD;&#xA;&#xD;&#xA;The object color is `(0.4, 0.2, 0.1)`. When I type these values into a color picker I get [![Color from color picker][4]][4], which looks similar to the rabbit-color on the left.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**My Understanding**&#xD;&#xA;&#xD;&#xA;1. Assume images (like the skybox) to be in sRGB space most of the time&#xD;&#xA;2. Try to work in linear colorspace as long as possible, and gamma correct at the end&#xD;&#xA;&#xD;&#xA;If `c` is my color, then because of (1) I should assume that when I retrieve a texel it actually is gamma-corrected (`c ^ (1/gamma)`). So to get `c` I do `(c ^ (1/gamma)) ^ gamma` as in `srgbToLinear()`.&#xD;&#xA;&#xD;&#xA;Because of (2) I leave my object color as is when shading the object and only apply gamma correction at the very end.&#xD;&#xA;&#xD;&#xA;Also, because of gamma correction we can expect the resulting images to look a bit brighter.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;With my current understanding I would expect the image on the right to be the correct one. I get that the rabbit should look brighter, but especially when comparing it to what the color picker outputs, I can't help but feel confused about it. Is it simply my expectations that fail me or am I doing something wrong here?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hCdo6m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/q3nUZm.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Uf8wjs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35977" PostHistoryTypeId="1" PostId="12450" RevisionGUID="0fb4a5a2-3ea7-4462-9ab0-0c8838f6ca42" CreationDate="2022-01-10T21:52:39.790" UserId="7684" Text="Gamma Correction vs Color Picker" ContentLicense="CC BY-SA 4.0" />
  <row Id="35978" PostHistoryTypeId="3" PostId="12450" RevisionGUID="0fb4a5a2-3ea7-4462-9ab0-0c8838f6ca42" CreationDate="2022-01-10T21:52:39.790" UserId="7684" Text="|gamma|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35979" PostHistoryTypeId="2" PostId="12451" RevisionGUID="cea0a52f-70b9-4a73-b243-ad430dd8e213" CreationDate="2022-01-11T04:42:06.143" UserId="48" Text="Your understanding is correct, and I think the image on the right looks like the more correct one. I think the root of your confusion is that the constant `objectColor` you've defined in your shader is being interpreted as a gamma-corrected color in the left image, and the same values are being interpreted as a linear color in the right image. To be more consistent, in the latter case you should apply `srgbToLinear` to the `objectColor` as well. Then, I expect, the two images will look more like the same dark reddish color.&#xD;&#xA;&#xD;&#xA;Note that if I interpret `objectColor` as linear, then apply the 1/2.2 gamma to it, it comes out as this color:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/OG8MR.png&quot; width=&quot;100&quot; height=&quot;100&quot; alt=&quot;light brown color&quot;&gt;&#xD;&#xA;&#xD;&#xA;which looks more plausibly like the underlying color of the rabbit on the right.&#xD;&#xA;&#xD;&#xA;BTW, a point of terminology quibble. Gamma 2.2 is not the same thing as the sRGB nonlinear curve. The sRGB curve is the more complicated one given in by $C_\text{linear}$ and $C_\text{srgb}$ in [the formulas here](https://en.wikipedia.org/wiki/SRGB#Transformation), with the 2.4 power and the 0.055s. Now it's fine to use gamma 2.2 instead if you prefer, but I think you shouldn't call it sRGB, as it's not the curve defined by the sRGB standard and it will cause confusion." ContentLicense="CC BY-SA 4.0" />
  <row Id="35981" PostHistoryTypeId="5" PostId="12448" RevisionGUID="e5625f74-7128-40f6-9af3-9e10721a8b49" CreationDate="2022-01-11T06:04:18.240" UserId="6064" Comment="added 124 characters in body" Text="Hi I have a slight confusion in using the opengl perspective matrix in vulkan.&#xD;&#xA;glm's perspective matrix works directly in vulkan just by multiplying the [1][1] term by -1 but when I compared the formula for cration of perspective matrix for both the apis.&#xD;&#xA;&#xD;&#xA;opengl one here:&lt;http://www.songho.ca/opengl/gl_projectionmatrix.html&gt;&#xD;&#xA;&#xD;&#xA;vulkan here:&lt;https://www.youtube.com/watch?v=U0_ONQQ5ZNM&gt;( at 12:10)&#xD;&#xA;&#xD;&#xA;and I see 2 diffrences:&#xD;&#xA;1st at [1][1]&#xD;&#xA;2nd at [2][3]: here is my doubt(opengl's is 2 times the one in vulkan.&#xD;&#xA;&#xD;&#xA;So how does glm's matrix work for my vulkan program just by correcting [1][1] location?&#xD;&#xA;Please do correct me if I am making some mistake in understanding the differences in matrix.&#xD;&#xA;&#xD;&#xA;openglMarix talking about:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hcIFm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35982" PostHistoryTypeId="2" PostId="12452" RevisionGUID="386aaedc-dafb-4ac2-a37c-d86fbf644933" CreationDate="2022-01-11T10:14:35.777" UserId="13273" Text="I'm trying to implement a camera, which is able to go very close to a planet/moon surface, without flickering surface.&#xD;&#xA;&#xD;&#xA;**The problem:**&#xD;&#xA;Right now the position of a planet / moon is saved at the center of the planet / moon. When looking at the earth, its radius is ~6371km. So when creating a sphere with such a radius the problem starts when the camera is very close to the surface. The surface (ground) bumps up and down like randomly (~1 meter) which I am trying to prevent.&#xD;&#xA;This behavior is simple to understand: The vertex position in VBO is like 6371km away from the origin. And the camera (when it is close to the surface) is also like 6371km away from the planets center. So the viewmatrix is working with such high numbers, so that the result (position) flickers because of the floating precision. Right now I am using km as base unit. To use meter or other units as baseunit will not solve the problem, because it only shifts the comma. So the problem is that I need more, than the I think it was 8 digits of precision a float has, to avoid the flickering. So using doubles would solve the problem, but as far as I found, double vectors are available in GLSL, but double matrices not.&#xD;&#xA;Are there other algorithms which I can use? &#xD;&#xA;&#xD;&#xA;later I want to tessellate the mesh in camera region and put a heightmap on top of it to visualize mountains. I also would like to add Simplex-noise on top of it to have a realistic surface.&#xD;&#xA;&#xD;&#xA;**The idea I have right now:** To describe my idea in a simpler way I'll use a 2D representation of the problem.&#xD;&#xA;In the image below you can see several parts of a circle. These meshes will be used depending on the camera distance to the surface like LOD. So when being far away from the planet, the circle (sphere) should be rendered. when coming closer, smaller parts of the planet will be visible. The black dot represents the real center of the planet. The red dot represents the origin of the mesh (VBO) which will be calculated on CPU (double) before rendering the scenario. This sub mesh need to be rotated so that the camera will always be in a line with the black and red dot.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the red dot is moving towards the camera, so the precision problem will be solved. But I think that other heads (better ones) already thought about a perfect solution for that problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GZTAh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35984" PostHistoryTypeId="1" PostId="12452" RevisionGUID="386aaedc-dafb-4ac2-a37c-d86fbf644933" CreationDate="2022-01-11T10:14:35.777" UserId="13273" Text="Precision problems when rendering whole planets" ContentLicense="CC BY-SA 4.0" />
  <row Id="35985" PostHistoryTypeId="3" PostId="12452" RevisionGUID="386aaedc-dafb-4ac2-a37c-d86fbf644933" CreationDate="2022-01-11T10:14:35.777" UserId="13273" Text="|opengl|glsl|precision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="35986" PostHistoryTypeId="5" PostId="12448" RevisionGUID="300858a1-4a76-47db-8bf7-3daffc002444" CreationDate="2022-01-11T11:13:34.387" UserId="6064" Comment="deleted 6 characters in body" Text="Hi I have a slight confusion in using the opengl perspective matrix in vulkan.&#xD;&#xA;glm's perspective matrix works directly in vulkan just by multiplying the &quot;[1,1 term by -1 but when I compared the formula for creation of perspective matrix for both the apis.&#xD;&#xA;&#xD;&#xA;opengl one here:&lt;http://www.songho.ca/opengl/gl_projectionmatrix.html&gt;&#xD;&#xA;&#xD;&#xA;vulkan here:&lt;https://www.youtube.com/watch?v=U0_ONQQ5ZNM&gt;( at 12:10)&#xD;&#xA;&#xD;&#xA;and I see 2 differences:&#xD;&#xA;1st at 1,1&#xD;&#xA;2nd at 2,3: here is my doubt(opengl's is 2 times the one in vulkan.&#xD;&#xA;&#xD;&#xA;So how does glm's matrix works for my vulkan program just by correcting [1,1 location?&#xD;&#xA;Please do correct me if I am making some mistake in understanding the differences in matrix.&#xD;&#xA;&#xD;&#xA;openglMarix talking about:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hcIFm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="35987" PostHistoryTypeId="2" PostId="12453" RevisionGUID="62ccee2a-dd5e-4eb7-a35e-a7eddd3c8fc9" CreationDate="2022-01-11T11:27:56.780" UserId="7952" Text="Vulkan has [0, -1] for the y axis where OpenGL has [0, 1] so just multiplying the y axis by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;&#xD;&#xA;However:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;Which does exactly what you described.&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1].&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(flt32 fovy_rads, flt32 s, flt32 near, flt32 far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * inv_y_size);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35989" PostHistoryTypeId="5" PostId="12453" RevisionGUID="f35e5e59-5408-494a-b754-08c796b3ca24" CreationDate="2022-01-11T11:38:19.017" UserId="7952" Comment="added 576 characters in body" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that give all the solution in one place....&#xD;&#xA;&#xD;&#xA;Vulkan has [0, -1] for the y axis where OpenGL has [0, 1] so just multiplying the y axis by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1].&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35990" PostHistoryTypeId="5" PostId="12453" RevisionGUID="5e7bbfba-026b-4dbe-b852-32851f3d5137" CreationDate="2022-01-11T11:43:32.987" UserId="7952" Comment="added 576 characters in body" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that give all the solution in one place....&#xD;&#xA;&#xD;&#xA;Vulkan has [0, -1] for the y axis where OpenGL has [0, 1] so just multiplying the perspective matrix [1][1] value by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;(or you can also use gl_Postion.y *= -1)&#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1].&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;(This solution does not flip the y-axis.)&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35991" PostHistoryTypeId="5" PostId="12453" RevisionGUID="074ca8d7-7e1b-4196-a9bb-bf7a335df38a" CreationDate="2022-01-11T11:48:52.080" UserId="7952" Comment="added 576 characters in body" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that give all the solution in one place....&#xD;&#xA;&#xD;&#xA;Vulkan has [1, -1] for the y axis where OpenGL has [-1, 1] so just multiplying the perspective matrix [1][1] value by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;(or you can also use gl_Postion.y *= -1) This give Vulkan a right hand NDC space, while OpenGL has a left handed NDC space.&#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1].&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;(This solution does not flip the y-axis.)&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35992" PostHistoryTypeId="5" PostId="12453" RevisionGUID="1fdc9e68-d3b0-403a-8d36-7e6b8088015a" CreationDate="2022-01-11T11:55:44.900" UserId="7952" Comment="deleted 71 characters in body" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that give all the solution in one place....&#xD;&#xA;&#xD;&#xA;Vulkan clip space has [1, -1] for the y axis where OpenGL has [-1, 1] so just multiplying the perspective matrix [1][1] value by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;(or you can also use gl_Postion.y *= -1) &#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1].&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;(This solution does not flip the y-axis.)&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35993" PostHistoryTypeId="5" PostId="12453" RevisionGUID="a4541fc5-deef-489d-bc00-28919c183e99" CreationDate="2022-01-11T12:05:46.010" UserId="7952" Comment="deleted 71 characters in body" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that give all the solution in one place....&#xD;&#xA;&#xD;&#xA;Vulkan clip space has [1, -1] for the y axis where OpenGL has [-1, 1] so just multiplying the perspective matrix [1][1] value by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;(or you can also use gl_Postion.y *= -1) &#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1]. Finally, using a range [0,1] allows for &quot;reverse Z&quot; (improving floating point number distribution)&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;(This solution does not flip the y-axis.)&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35994" PostHistoryTypeId="5" PostId="12453" RevisionGUID="95bd8e48-6458-46c4-8fad-95db5da60bfe" CreationDate="2022-01-11T12:11:18.830" UserId="7952" Comment="deleted 71 characters in body" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that give all the solution in one place....&#xD;&#xA;&#xD;&#xA;Vulkan clip space has [1, -1] for the y axis where OpenGL has [-1, 1] so just multiplying the perspective matrix [1][1] value by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;(or you can also use gl_Postion.y *= -1) &#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1]. Finally, using a range [0,1] allows for &quot;reverse Z&quot; (improving floating point number distribution)&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This is code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;(This solution does not flip the y-axis.)&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. Since Vulkan has a depth range of [0,1] it is easy to get the &quot;illusion&quot; that it is fully functional since the camera will appear to map correctly to the full depth range.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="35995" PostHistoryTypeId="5" PostId="12452" RevisionGUID="279dc919-b4d9-4b15-b562-585d5a0eacd9" CreationDate="2022-01-11T13:44:35.283" UserId="13273" Comment="added 147 characters in body" Text="I'm trying to implement a camera, which is able to go very close to a planet/moon surface, without flickering surface.&#xD;&#xA;&#xD;&#xA;**The problem:**&#xD;&#xA;Right now the position of a planet / moon is saved at the center of the planet / moon. When looking at the earth, its radius is ~6371km. So when creating a sphere with such a radius the problem starts when the camera is very close to the surface. The surface (ground) bumps up and down like randomly (~1 meter) which I am trying to prevent.&#xD;&#xA;This behavior is simple to understand: The vertex position in VBO is like 6371km away from the origin. And the camera (when it is close to the surface) is also like 6371km away from the planets center. So the viewmatrix is working with such high numbers, so that the result (position) flickers because of the floating precision. Right now I am using km as base unit. To use meter or other units as baseunit will not solve the problem, because it only shifts the comma. So the problem is that I need more, than the I think it was 8 digits of precision a float has, to avoid the flickering. So using doubles would solve the problem, but as far as I found, double vectors are available in GLSL, but double matrices not.&#xD;&#xA;Are there other algorithms which I can use? &#xD;&#xA;&#xD;&#xA;later I want to tessellate the mesh in camera region and put a heightmap on top of it to visualize mountains. I also would like to add Simplex-noise on top of it to have a realistic surface.&#xD;&#xA;&#xD;&#xA;**The idea I have right now:** To describe my idea in a simpler way I'll use a 2D representation of the problem.&#xD;&#xA;In the image below you can see several parts of a circle. These meshes will be used depending on the camera distance to the surface like LOD. So when being far away from the planet, the circle (sphere) should be rendered. when coming closer, smaller parts of the planet will be visible. The black dot represents the real center of the planet. The red dot represents the origin of the mesh (VBO) which will be calculated on CPU (double) before rendering the scenario. This sub mesh need to be rotated so that the camera will always be in a line with the black and red dot.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see, the red dot is moving towards the camera, so the precision problem will be solved. What is problematic here is, that the earth for example is not a sphere but a ellipsoid. So the sub-parts somehow need to be scaled non uniformly. But I think that other heads (better ones) already thought about a perfect solution for that problem.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GZTAh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="35996" PostHistoryTypeId="2" PostId="12454" RevisionGUID="d290112b-e420-4fdb-912a-b5bd814f20d3" CreationDate="2022-01-11T17:03:58.733" UserId="17223" Text="There are several papers like this one [here][1] that refer to a concept called many-light global illumination using Virtual Point Lights (VPL). That is, the problem of global illumination is reduced to a matter of direct illumination by simply placing &quot;invisible&quot; light sources all over the place in the scene. To me this sounds suspiciously like Light Probes (Unity Engine) or GIProbes (Godot Engine). Are Light Probes simply a way to implement the concept of many-light global illumination?&#xD;&#xA;&#xD;&#xA;  [1]: http://web.cs.wpi.edu/~emmanuel/publications/PDFs/C13.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="35998" PostHistoryTypeId="1" PostId="12454" RevisionGUID="d290112b-e420-4fdb-912a-b5bd814f20d3" CreationDate="2022-01-11T17:03:58.733" UserId="17223" Text="Is are virtual point lights in many-light global illumination the same same light probes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="35999" PostHistoryTypeId="3" PostId="12454" RevisionGUID="d290112b-e420-4fdb-912a-b5bd814f20d3" CreationDate="2022-01-11T17:03:58.733" UserId="17223" Text="|lighting|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36000" PostHistoryTypeId="2" PostId="12455" RevisionGUID="43926746-cee2-48e3-bf5f-751039d85493" CreationDate="2022-01-12T01:01:01.127" UserId="17836" Text="To perform importance sampling on a light source, a probability density function must be provided for the sampling distribution. For most light sources, a valid probability distribution can be found, but point lights and pure directional lights (directional lights which emit light exclusively in one direction, with 0 spread angle) do not have this property, as there is only one valid light path connecting them with any given point. This would require an infinite probability density, which would result in an infinitely small light contribution due to importance sampling. My question is: how can these light types be sampled without introducing bias? &#xD;&#xA;&#xD;&#xA;I've asked more specifically about the mathematics behind this [on the Mathematics Stack Exchange][1], but seeing as I received no replies there, I think this would be a more appropriate place to ask.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.stackexchange.com/questions/4217966/what-would-be-the-probability-density-function-for-a-monte-carlo-sampling-strate" ContentLicense="CC BY-SA 4.0" />
  <row Id="36002" PostHistoryTypeId="1" PostId="12455" RevisionGUID="43926746-cee2-48e3-bf5f-751039d85493" CreationDate="2022-01-12T01:01:01.127" UserId="17836" Text="How are point and pure directional lights sampled in an unbiased path tracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36003" PostHistoryTypeId="3" PostId="12455" RevisionGUID="43926746-cee2-48e3-bf5f-751039d85493" CreationDate="2022-01-12T01:01:01.127" UserId="17836" Text="|pathtracing|lighting|sampling|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36008" PostHistoryTypeId="50" PostId="8431" RevisionGUID="15a96a3e-8115-41a1-890d-1c59623db7c4" CreationDate="2022-01-13T04:04:50.393" UserId="-1" />
  <row Id="36009" PostHistoryTypeId="2" PostId="12457" RevisionGUID="8329a2b4-6470-4066-bffe-4200519a8cf8" CreationDate="2022-01-13T09:29:31.140" UserId="13273" Text="The background of this question is that I am trying to write an automatic binding system, where for each uniform variable I want to declare in my GLSL code, I call a method `declareUniform` which is counting up the location value, saving the type and name of the uniform to a list which will be saved within my shaderobject... &#xD;&#xA;&#xD;&#xA;I already did something similar with varyings, where I save the varying information (location, type, name, shader stage from, shader stage to, isarray, arraycount) and of cause also generating glsl string which is working fine.&#xD;&#xA;&#xD;&#xA;I am trying to bind several things to a shader, which does not work right now.&#xD;&#xA;I've read, that uniform block binding indices have nothing to do with sampler binding locations [here][1], which is totally confusing me... I also read the `Explicit_uniform_location` site from khronos [here][2].&#xD;&#xA;I am trying to bind some sampler2D, image2D and other uniforms in one shader.&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in  vec2 texCoordIn; //value from VBO&#xD;&#xA;    layout(binding = 0, rgba32f) uniform  image2D writeColorTexture;&#xD;&#xA;    layout(binding = 1) uniform  sampler2D readColorTexture;&#xD;&#xA;    layout(location = 0) uniform  float u_apature;&#xD;&#xA;    layout(location = 1) uniform  float u_focalDistance;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;On CPU it looks like this:&#xD;&#xA;&#xD;&#xA;    GLint readColorTextureLoc = glGetUniformLocation(glShaderHandle, &quot;readColorTexture&quot;);&#xD;&#xA;    GLint writeColorTextureLoc = glGetUniformLocation(glShaderHandle, &quot;writeColorTexture&quot;);&#xD;&#xA;&#xD;&#xA;trying to bind the samper2D:&#xD;&#xA;&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0);&#xD;&#xA;    glUniform1i(readColorTextureLoc, 0);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, colorTexture-&gt;id());&#xD;&#xA;&#xD;&#xA;trying to bind the image2D:&#xD;&#xA;&#xD;&#xA;    glBindImageTexture(writeColorTextureLoc, colorImage-&gt;id(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;when using `glGetUniformLocation(glShaderHandle, &quot;readColorTexture&quot;);` I get the value 31 which also confuses me.&#xD;&#xA;This brought me to understand it to the following way: `layout(location = ...) uniform` is the value which will be returned by `glGetUniformLocation`. &#xD;&#xA;&#xD;&#xA;The binding qualifier maps the uniform variable to a (I'll call it) &quot;background list&quot;, which can be addressed by `glActiveTexture` for example if it is a sampler. As far as I understood (please correct me if I am wrong!) there are several of these &quot;background lists&quot;. One for samplers, one for block bindings, one for images... and each of them starts with 0.&#xD;&#xA;&#xD;&#xA;Now my question: Am I right? Did I understand it correctly? If so: which &quot;background lists&quot; are available and how can I bind a sampler together with an Image?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/questions/49097947/glsl-uniform-layout-binding-and-textures&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Explicit_uniform_location" ContentLicense="CC BY-SA 4.0" />
  <row Id="36011" PostHistoryTypeId="1" PostId="12457" RevisionGUID="8329a2b4-6470-4066-bffe-4200519a8cf8" CreationDate="2022-01-13T09:29:31.140" UserId="13273" Text="Opengl GLSL binding locations confusion" ContentLicense="CC BY-SA 4.0" />
  <row Id="36012" PostHistoryTypeId="3" PostId="12457" RevisionGUID="8329a2b4-6470-4066-bffe-4200519a8cf8" CreationDate="2022-01-13T09:29:31.140" UserId="13273" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36013" PostHistoryTypeId="2" PostId="12458" RevisionGUID="faa315e0-b1f4-418f-925d-47db8c2a4571" CreationDate="2022-01-13T15:10:23.330" UserId="2654" Text="While OpenGL's organic growth as an API has led to some inconsistencies regarding the naming of things, the API here means what it says. `location` means *location*, and `binding` means binding. As such, a function named `glGetUniformLocation` should be expected to return the `location` of the uniform, not the `binding`.&#xD;&#xA;&#xD;&#xA;When introspecting GLSL, there are several quantities to consider. For a particular kind of thing (program inputs, uniforms, etc. In the [modern introspection API, these are called &quot;interfaces&quot;][1]), all of the introspectable variables ([called &quot;resources&quot;][2]) are given an index as if they're all in an array. This index is from 0 to the number of active resources in this interface.&#xD;&#xA;&#xD;&#xA;You can then [query properties about a resource (name, etc)][3] by its index. But the index of a resource is neither its `location` nor its `binding`; it is merely an identifier for the resource.&#xD;&#xA;&#xD;&#xA;Some resources have a location; a number used by the API to directly affect the value it gets or gives. Program inputs use locations to determine which variable gets when data from the VAO (or prior program stage if the program doesn't contain a VS). Uniform locations are how you set values into the uniform via `glProgramUniform*` calls. And so forth.&#xD;&#xA;&#xD;&#xA;Some resources have a binding; a number which represents the index in a table (in the OpenGL context) for how the resource is used to access memory of some kind. The binding for opaque types determine which binding slot the given object represents. To make a memory object (texture or buffer) available to this resource, you bind that object to the binding index for that kind of access (image load/store, texture, etc).&#xD;&#xA;&#xD;&#xA;So if you have an image uniform, the `location` determines how you would set its binding from the API via `glProgramUniform1i`. But the `binding` determines which index in the OpenGL context the OpenGL object you're trying to access will be bound to. If you do not assign a location to a uniform in the shader, the API will assign one itself, which you would have to query (if you need to change the binding for some reason. Which you shouldn't).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Program_Introspection#Interfaces&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Program_Introspection#Interface_query&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Program_Introspection#Resource_properties" ContentLicense="CC BY-SA 4.0" />
  <row Id="36015" PostHistoryTypeId="50" PostId="8291" RevisionGUID="39a2131e-ee7a-4857-ac7e-c180a181d5c3" CreationDate="2022-01-14T04:04:55.470" UserId="-1" />
  <row Id="36016" PostHistoryTypeId="2" PostId="12459" RevisionGUID="db310b95-9c44-4e2f-ae58-24acdaaa6a68" CreationDate="2022-01-14T05:06:27.667" UserId="7462" Text="I have a working oct-ree raytracer and I am applying it to the sponza.&#xD;&#xA;&#xD;&#xA;The algorithm I have designed works like this at a high level:&#xD;&#xA;&#xD;&#xA; * Collide with the bounding box of the model, move your ray to that collision point&#xD;&#xA; * Add to a stack the largest BB and the point at which the ray collided with the box&#xD;&#xA; * while the stack is not empty&#xD;&#xA; * Check if this voxel is occupied, if it isn't continue&#xD;&#xA; * move along the ray, colliding with up to the 4 children of the voxel, add each one, along with its collision point to the stack&#xD;&#xA; * If we are at the lowest level and the voxel is occupied, return the found value&#xD;&#xA;&#xD;&#xA;To try to show a picture:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;* Ray collides with box, we move to collision point. &#xD;&#xA;&#xD;&#xA;* We then calculate in which of the 4 children we currently are, push it to the stack. &#xD;&#xA;&#xD;&#xA;* We move along the ray  to the very next voxel, we add it to the stack.&#xD;&#xA;&#xD;&#xA;* We would move outside the box if we kept going, so we stop here and pop from the stack.&#xD;&#xA;This box is empty, so we skip it.&#xD;&#xA;&#xD;&#xA;* This box has something in it, so we check the children by doing the same traversal as before (we only add 2 of them).&#xD;&#xA;&#xD;&#xA;* We pop, box is empty, we skip.&#xD;&#xA;&#xD;&#xA;* We pop, box is full, this is a leaf node, we return the value.&#xD;&#xA;&#xD;&#xA;Some features of this algorithm that should make it efficient are, we never check all 8 children of a voxel we check at most 4 at any one time. We never need to sort them, because we are using a grid traversal to collide with them, so we know which one is closer and which one is furthest from the starting point of the ray.&#xD;&#xA;&#xD;&#xA;Despite all of this and my best efforts, the algorithm is not running in real time. A 256 resolution SVO of the sponza is rendering at 200 ms per frame on a GTX 1070, I strongly believe there are mechanisms to get this working faster but I am somewhat out of ideas.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tsHhD.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/nLGor.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36018" PostHistoryTypeId="1" PostId="12459" RevisionGUID="db310b95-9c44-4e2f-ae58-24acdaaa6a68" CreationDate="2022-01-14T05:06:27.667" UserId="7462" Text="Sparse voxel oct tree tracing, optimization tricks?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36019" PostHistoryTypeId="3" PostId="12459" RevisionGUID="db310b95-9c44-4e2f-ae58-24acdaaa6a68" CreationDate="2022-01-14T05:06:27.667" UserId="7462" Text="|raytracing|performance|voxelization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36027" PostHistoryTypeId="2" PostId="12461" RevisionGUID="6b653211-8ad3-4497-90d8-a5456e4e7592" CreationDate="2022-01-14T13:10:24.283" UserId="13442" Text="In my tests a GTX 1050 can do ~1B triangles with `glDrawElementsInstanced(GL_TRIANGLES, ...`. That's roughly 2/3 of chip clock. Arguably `GL_TRIANGLE_STRIP` can give you an x3 speed boost, but e.g. idtech4 only supports `GL_TRIANGLES`." ContentLicense="CC BY-SA 4.0" />
  <row Id="36029" PostHistoryTypeId="2" PostId="12462" RevisionGUID="eba5b47f-3c4d-4cc5-9dbe-b7ffe866cf09" CreationDate="2022-01-14T16:04:42.917" UserId="10193" Text="I want to clarify how are workgroups executed on various GPUs, thus I have several questions. I know that different GPU architectures work differently, but I expect an answer YES if **there is single (popular) GPU** for which some statement is true. I really would like to get simple Yes/No answers in addition to complicated discussion about specific architectures.&#xD;&#xA;&#xD;&#xA; 1. Is Work Group a synonyme to wavefront and warp? So it means a bundle of threads?&#xD;&#xA; 2. A Compute Unit, typically, has 4 SIMD units inside. Each SIMD executes 1 instruction per cycle for (typically?) 16 threads. Question: can one CU execute **one WG per SIMD**, so 4 SIMDs execute 1/4 of each 4 WG in one cycle? **Or/and** can it execute **one whole WG on different SIMDs**, so 4 SIMDs finish together 1 WG in one cycle?&#xD;&#xA; 3. If WG size is bigger than SIMD size (or CU size), it may be executed on different SIMDs (or even different CU units) in parallel (right?). But if WG size is less than SIMD size: **can one SIMD execute threads of different Work Groups** (of course such WGs need to execute same shader code) in the same cycle?&#xD;&#xA; 4. Is it ok to define Work Group size as (1, 1, 1)? I saw an example of such compute shader in D3D documentation. This relates to previous Question 3: it seems to be ok if one SIMD can execute 16 threads each belonging to a different WG of size 1. But if it can't, it is a waste of SIMD power.&#xD;&#xA; 5. Can execution/memory barriers be omitted, if Work Group size is equal or less than SIMD size?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36031" PostHistoryTypeId="1" PostId="12462" RevisionGUID="eba5b47f-3c4d-4cc5-9dbe-b7ffe866cf09" CreationDate="2022-01-14T16:04:42.917" UserId="10193" Text="Compute shader workgroups execution and size" ContentLicense="CC BY-SA 4.0" />
  <row Id="36032" PostHistoryTypeId="3" PostId="12462" RevisionGUID="eba5b47f-3c4d-4cc5-9dbe-b7ffe866cf09" CreationDate="2022-01-14T16:04:42.917" UserId="10193" Text="|gpu|compute-shader|hardware|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36033" PostHistoryTypeId="5" PostId="12462" RevisionGUID="27f3676f-225d-442c-90f8-3500168a8a60" CreationDate="2022-01-14T16:10:20.277" UserId="10193" Comment="added 24 characters in body" Text="I want to clarify how are workgroups executed on various GPUs, thus I have several questions. I know that different GPU architectures work differently, but I expect an answer YES if **there is single (popular) GPU** for which some statement is true. I really would like to get simple Yes/No answers in addition to complicated discussion about specific architectures.&#xD;&#xA;&#xD;&#xA; 1. Is Work Group a synonyme to wavefront and warp? So it means a bundle of threads?&#xD;&#xA; 2. A Compute Unit, typically, has 4 SIMD units inside. Each SIMD executes 1 instruction per cycle for (typically?) 16 threads. Question: if WG size is 64 (equal to total width of all SIMDs): can one CU execute **one WG per SIMD**, so 4 SIMDs execute 1/4 of each 4 WG in one cycle? **Or/and** can it execute **one whole WG on different SIMDs**, so 4 SIMDs finish together 1 WG in one cycle?&#xD;&#xA; 3. If WG size is bigger than SIMD size (or CU size), it may be executed on different SIMDs (or even different CU units) in parallel (right?). But if WG size is less than SIMD size: **can one SIMD execute threads of different Work Groups** (of course such WGs need to execute same shader code) in the same cycle?&#xD;&#xA; 4. Is it ok to define Work Group size as (1, 1, 1)? I saw an example of such compute shader in D3D documentation. This relates to previous Question 3: it seems to be ok if one SIMD can execute 16 threads each belonging to a different WG of size 1. But if it can't, it is a waste of SIMD power.&#xD;&#xA; 5. Can execution/memory barriers be omitted, if Work Group size is equal or less than SIMD size? (Relates to Question 4)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36034" PostHistoryTypeId="5" PostId="12462" RevisionGUID="ca0c147c-68ba-4a23-99c9-92c1b4fcf37f" CreationDate="2022-01-14T16:15:56.430" UserId="10193" Comment="added 103 characters in body" Text="I want to clarify how are workgroups executed on various GPUs, thus I have several questions. I know that different GPU architectures work differently, but I expect an answer YES if **there is single (popular) GPU** for which some statement is true. I really would like to get simple Yes/No answers in addition to complicated discussion about specific architectures.&#xD;&#xA;&#xD;&#xA; 1. Is Work Group a synonyme to wavefront and warp? So it means a bundle of threads?&#xD;&#xA; 2. A Compute Unit, typically, has 4 SIMD units inside. Each SIMD executes 1 instruction per cycle for (typically?) 16 threads. Question: if WG size is 64 (equal to total width of all SIMDs): can one CU execute **one WG per SIMD**, so 4 SIMDs execute 1/4 of each 4 WG in one cycle? **Or/and** can it execute **one whole WG on different SIMDs**, so 4 SIMDs finish together 1 WG in one cycle?&#xD;&#xA; 3. If WG size is bigger than SIMD size (or CU size), it may be executed on different SIMDs (or even different CU units) in parallel (right?). But if WG size is less than SIMD size: **can one SIMD execute threads of different Work Groups** (of course such WGs need to execute same shader code) in the same cycle?&#xD;&#xA; 4. Is it ok to define Work Group size as (1, 1, 1)? I saw an example of such compute shader in D3D documentation. This relates to previous Question 3: it seems to be ok if one SIMD can execute 16 threads each belonging to a different WG of size 1. But if it can't, it is a waste of SIMD power.&#xD;&#xA; 5. Can execution/memory barriers be omitted, if Work Group size is equal or less than SIMD size? Relates to Question 4. They can't be omiited if threads of one WG share some data but are executed on different SIMDs or CUs." ContentLicense="CC BY-SA 4.0" />
  <row Id="36035" PostHistoryTypeId="5" PostId="12462" RevisionGUID="a2ee64a8-d31f-4b05-943f-91f05058c12f" CreationDate="2022-01-14T23:53:16.467" UserId="2654" Comment="deleted 21 characters in body" Text="I want to clarify how are workgroups executed on various GPUs, thus I have several questions. I know that different GPU architectures work differently, but I expect an answer YES if there is single (popular) GPU for which some statement is true. I really would like to get simple Yes/No answers in addition to complicated discussion about specific architectures.&#xD;&#xA;&#xD;&#xA; 1. Is Work Group a synonym to wavefront and warp? So it means a bundle of threads?&#xD;&#xA; 2. A Compute Unit, typically, has 4 SIMD units inside. Each SIMD executes 1 instruction per cycle for (typically?) 16 threads. Question: if WG size is 64 (equal to total width of all SIMDs): can one CU execute one WG per SIMD, so 4 SIMDs execute 1/4 of each 4 WG in one cycle? Or/and can it execute one whole WG on different SIMDs, so 4 SIMDs finish together 1 WG in one cycle?&#xD;&#xA; 3. If WG size is bigger than SIMD size (or CU size), it may be executed on different SIMDs (or even different CU units) in parallel (right?). But if WG size is less than SIMD size: can one SIMD execute threads of different Work Groups (of course such WGs need to execute same shader code) in the same cycle?&#xD;&#xA; 4. Is it ok to define Work Group size as (1, 1, 1)? I saw an example of such compute shader in D3D documentation. This relates to previous Question 3: it seems to be ok if one SIMD can execute 16 threads each belonging to a different WG of size 1. But if it can't, it is a waste of SIMD power.&#xD;&#xA; 5. Can execution/memory barriers be omitted, if Work Group size is equal or less than SIMD size? Relates to Question 4. They can't be omiited if threads of one WG share some data but are executed on different SIMDs or CUs." ContentLicense="CC BY-SA 4.0" />
  <row Id="36037" PostHistoryTypeId="2" PostId="12463" RevisionGUID="0f0e5075-1dbd-41d8-8e02-92bf13dbf96d" CreationDate="2022-01-15T06:34:00.183" UserId="48" Text="Since you mentioned CUs and SIMDs, I wrote this mainly from the perspective of AMD's GCN architecture, but broadly speaking the answers apply to other GPU architectures as well (except for #2 which is really a detail specific to GCN). Other GPUs have parts that are at least somewhat analogous to CUs and SIMDs, though the details vary a lot.&#xD;&#xA;&#xD;&#xA;1. Not exactly. They are both bundles of threads, but a workgroup is a software concept, while wavefronts/warps (generically referred to as &quot;waves&quot;) are a hardware concept. The size of workgroup is defined by your code when you write the compute shader, but the size of a wave is defined by the hardware. A workgroup can be anywhere from 1 to 1024 threads, but a wave on NVIDIA (a warp) is always 32 threads, a wave on AMD (a wavefront) is 64 threads—or, on their newer RDNA architecture, can be set to either 32 or 64 by the driver (but is always one or the other for any given shader).&#xD;&#xA;&#xD;&#xA;   As far as I know, a workgroup may be made up of multiple waves but not the other way around. That is, multiple workgroups will not be coalesced together into a single wave.&#xD;&#xA;&#xD;&#xA;2. The way AMD's GCN architecture works is that a SIMD is physically 16-wide, but it is &quot;quad-pumped&quot;. This means that each instruction is issued 4 times in a row, operating on 1/4th of the wave each time. So, a 64-wide wave will be executed on a single SIMD, with the 16 physical lanes cycling through the 64 threads of the wave. A wave will not be split across multiple SIMDs; rather, other SIMDs are used to run other waves in the same dispatch.&#xD;&#xA;&#xD;&#xA;3. If the workgroup size is bigger than a wave, it will be split up into waves, and all those waves will execute on the various SIMDs inside a single CU (there is no splitting of a workgroup across different CUs, because of shared memory—all threads in the workgroup need to be able to access the shared memory, and it's part of the CU).&#xD;&#xA;&#xD;&#xA;    As mentioned earlier, as far as I am aware, multiple workgroups do not ever get packed into the same wave, so they would not execute together on a single SIMD.&#xD;&#xA;&#xD;&#xA;4. It is not advisable to define a workgroup of size (1, 1, 1) unless you truly need just one single thread in the whole dispatch. This is uncommon, but it comes up sometimes when some small calculation needs to be done on the GPU, such as setting up indirect draw parameters based on output of an earlier pass.&#xD;&#xA;&#xD;&#xA;    Generally, you should use workgroups smaller than 64 threads when you actually want to do a lot of calculations in parallel. Otherwise, as you said, a bunch of the lanes in the SIMDs are left unoccupied, which is a waste.&#xD;&#xA;&#xD;&#xA;5. Maybe, sometimes. If you know the exact hardware and can be 100% assured that the workgroup is within a single wave, then it may be possible to omit some barriers.&#xD;&#xA;&#xD;&#xA;    However, barriers serve other purposes besides inter-wave synchronization: they also inform the compiler not to re-order memory operations across the barrier when it does optimization, and they may also be needed at runtime to tell the SIMD to wait for memory writes before proceeding, even if it's only a single wave, due to pipelined execution (without the barrier, later instructions might start before the earlier writes had completed). Both of these could be required for the correctness of the algorithm you're implementing.&#xD;&#xA;&#xD;&#xA;    Generally, I would not advise removing barriers unless you're a stone-cold expert and working with a specific hardware and driver stack that you understand well, as opposed to a broad spectrum of GPUs.&#xD;&#xA;&#xD;&#xA;    Also, you might be aware that there are &quot;wave operations&quot; exposed by most APIs now, that allow some safe intra-wave communication without barriers. These are often useful for reducing the need for barriers in optimized versions of algorithms." ContentLicense="CC BY-SA 4.0" />
  <row Id="36039" PostHistoryTypeId="2" PostId="12464" RevisionGUID="aeac57a6-605e-4d56-a36c-85375985b193" CreationDate="2022-01-15T16:22:45.590" UserId="1810" Text="As far as I remember, without a fragment shader the shading is only evaluated at vertices then interpolated. Try subdividing the mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="36041" PostHistoryTypeId="5" PostId="12463" RevisionGUID="f465174f-3b1f-44f9-9624-f3a52c9ee64d" CreationDate="2022-01-15T16:39:53.387" UserId="48" Comment="fix typo" Text="Since you mentioned CUs and SIMDs, I wrote this mainly from the perspective of AMD's GCN architecture, but broadly speaking the answers apply to other GPU architectures as well (except for #2 which is really a detail specific to GCN). Other GPUs have parts that are at least somewhat analogous to CUs and SIMDs, though the details vary a lot.&#xD;&#xA;&#xD;&#xA;1. Not exactly. They are both bundles of threads, but a workgroup is a software concept, while wavefronts/warps (generically referred to as &quot;waves&quot;) are a hardware concept. The size of workgroup is defined by your code when you write the compute shader, but the size of a wave is defined by the hardware. A workgroup can be anywhere from 1 to 1024 threads, but a wave on NVIDIA (a warp) is always 32 threads, a wave on AMD (a wavefront) is 64 threads—or, on their newer RDNA architecture, can be set to either 32 or 64 by the driver (but is always one or the other for any given shader).&#xD;&#xA;&#xD;&#xA;   As far as I know, a workgroup may be made up of multiple waves but not the other way around. That is, multiple workgroups will not be coalesced together into a single wave.&#xD;&#xA;&#xD;&#xA;2. The way AMD's GCN architecture works is that a SIMD is physically 16-wide, but it is &quot;quad-pumped&quot;. This means that each instruction is issued 4 times in a row, operating on 1/4th of the wave each time. So, a 64-wide wave will be executed on a single SIMD, with the 16 physical lanes cycling through the 64 threads of the wave. A wave will not be split across multiple SIMDs; rather, other SIMDs are used to run other waves in the same dispatch.&#xD;&#xA;&#xD;&#xA;3. If the workgroup size is bigger than a wave, it will be split up into waves, and all those waves will execute on the various SIMDs inside a single CU (there is no splitting of a workgroup across different CUs, because of shared memory—all threads in the workgroup need to be able to access the shared memory, and it's part of the CU).&#xD;&#xA;&#xD;&#xA;    As mentioned earlier, as far as I am aware, multiple workgroups do not ever get packed into the same wave, so they would not execute together on a single SIMD.&#xD;&#xA;&#xD;&#xA;4. It is not advisable to define a workgroup of size (1, 1, 1) unless you truly need just one single thread in the whole dispatch. This is uncommon, but it comes up sometimes when some small calculation needs to be done on the GPU, such as setting up indirect draw parameters based on output of an earlier pass.&#xD;&#xA;&#xD;&#xA;    Generally, you should use workgroups that are a multiple of 64 threads when you actually want to do a lot of calculations in parallel. Otherwise, as you said, a bunch of the lanes in the SIMDs are left unoccupied, which is a waste.&#xD;&#xA;&#xD;&#xA;5. Maybe, sometimes. If you know the exact hardware and can be 100% assured that the workgroup is within a single wave, then it may be possible to omit some barriers.&#xD;&#xA;&#xD;&#xA;    However, barriers serve other purposes besides inter-wave synchronization: they also inform the compiler not to re-order memory operations across the barrier when it does optimization, and they may also be needed at runtime to tell the SIMD to wait for memory writes before proceeding, even if it's only a single wave, due to pipelined execution (without the barrier, later instructions might start before the earlier writes had completed). Both of these could be required for the correctness of the algorithm you're implementing.&#xD;&#xA;&#xD;&#xA;    Generally, I would not advise removing barriers unless you're a stone-cold expert and working with a specific hardware and driver stack that you understand well, as opposed to a broad spectrum of GPUs.&#xD;&#xA;&#xD;&#xA;    Also, you might be aware that there are &quot;wave operations&quot; exposed by most APIs now, that allow some safe intra-wave communication without barriers. These are often useful for reducing the need for barriers in optimized versions of algorithms." ContentLicense="CC BY-SA 4.0" />
  <row Id="36042" PostHistoryTypeId="2" PostId="12465" RevisionGUID="2e09a4f4-bd31-4019-b1bd-f734848ad182" CreationDate="2022-01-16T06:40:03.123" UserId="11865" Text="Just to show a 1:1 comparison to help people easily understand the new functions:  &#xD;&#xA;`1). create 2). bind 3). allocate 4). upload`&#xD;&#xA;&#xD;&#xA;    1: glGenTextures(1,&amp;tex);&#xD;&#xA;    2: glBindTexture(GL_TEXTURE_2D,tex);&#xD;&#xA;    3: glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w,h, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);&#xD;&#xA;    4: glTexSubImage2D(GL_TEXTURE_2D, level, x,y,w,h, GL_BGRA, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    1: glCreateTextures(GL_TEXTURE_2D,1,&amp;tex);&#xD;&#xA;    2: // glBindTextureUnit(unit, tex);&#xD;&#xA;    3: glTextureStorage2D(tex, levels, GL_RGBA8, w,h);&#xD;&#xA;    4: glTextureSubImage2D(tex, level, x,y,w,h, GL_BGRA, GL_UNSIGNED_BYTE, data);&#xD;&#xA;&#xD;&#xA;Much cleaner. We don't need to bind. We just allocate our texture levels, then upload to them.&#xD;&#xA;&#xD;&#xA;Also with `glBindTextureUnit` we don't need `glActiveTexture`.  &#xD;&#xA;And the equivalent of `glTextureStorage2D` in the old code would actually be:&#xD;&#xA;&#xD;&#xA;    for(int i=0; i&lt;levels; i++) glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, max(1,w&gt;&gt;i),max(1,h&gt;&gt;i), 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr);&#xD;&#xA;&#xD;&#xA;Of course you'd still need such a loop if you are uploading different levels manually.  &#xD;&#xA;&#xD;&#xA;Also here's some other dsa texture functions to use instead:  &#xD;&#xA;`glTextureParameteri` and `glGenerateTextureMipmap`" ContentLicense="CC BY-SA 4.0" />
  <row Id="36049" PostHistoryTypeId="4" PostId="12454" RevisionGUID="f5f36301-6cbe-43ee-8a59-7b93c8f9b50b" CreationDate="2022-01-16T19:11:31.770" UserId="7952" Comment="cleaned up title (or tried to without changing meaning)" Text="Are virtual point lights in many-light global illumination the same light probes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36050" PostHistoryTypeId="2" PostId="12467" RevisionGUID="d3fecda2-bade-4b72-acad-159855acc6d5" CreationDate="2022-01-16T22:01:58.780" UserId="17860" Text="I thought that if I used an image with a transparent background, I would still be able to see the colors I had specified in my vertex attribute buffer.&#xD;&#xA;&#xD;&#xA;        // Vertices coordinates&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    { //     COORDINATES     /        COLORS      /   TexCoord  //&#xD;&#xA;    	-0.5f, 0.0f,  0.5f,     0.83f, 0.70f, 0.44f,	0.0f, 0.0f,&#xD;&#xA;    	-0.5f, 0.0f, -0.5f,     0.83f, 0.70f, 0.44f,	5.0f, 0.0f,&#xD;&#xA;    	 0.5f, 0.0f, -0.5f,     0.83f, 0.70f, 0.44f,	0.0f, 0.0f,&#xD;&#xA;    	 0.5f, 0.0f,  0.5f,     0.83f, 0.70f, 0.44f,	5.0f, 0.0f,&#xD;&#xA;    	 0.0f, 0.8f,  0.0f,     0.92f, 0.86f, 0.76f,	2.5f, 5.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is not the case however, and what I am getting instead is this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What would be the easiest way to see my specified colors instead of all that black on my object?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RH4yC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36052" PostHistoryTypeId="1" PostId="12467" RevisionGUID="d3fecda2-bade-4b72-acad-159855acc6d5" CreationDate="2022-01-16T22:01:58.780" UserId="17860" Text="How do I view my vertex colors that I specified through the texture I've applied on my objec [OpenGL]?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36053" PostHistoryTypeId="3" PostId="12467" RevisionGUID="d3fecda2-bade-4b72-acad-159855acc6d5" CreationDate="2022-01-16T22:01:58.780" UserId="17860" Text="|opengl|texture|compute-shader|transparency|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36054" PostHistoryTypeId="2" PostId="12468" RevisionGUID="64efb49c-71c8-4857-b560-978a13292bd1" CreationDate="2022-01-17T00:03:41.880" UserId="12040" Text="I am creating a path tracer and I got some strange results when calculating the strength of light.&#xD;&#xA;&#xD;&#xA;I am using a rendering equation inspired by this diagram:&#xD;&#xA;[![Rendering equation][1]][1]&#xD;&#xA;&#xD;&#xA;1) When I use the cosine everything gets really dark and the edges of my spheres are almost black. That makes sense because I am almost multiplying by cos(PI/2) = 0. I have read that it suppose to cancel out with something so I have removed it which help. But what does it cancel out with?&#xD;&#xA;&#xD;&#xA;2) I am using Lambertian diffuse BRDF which means that the &quot;Fr&quot; part of the equation should be &quot;albedo / PI&quot;. I am also doing uniform hemisphere sampling which gave me a PDF of 1 / PI.&#xD;&#xA;Now when I calculate BRDF / PDF I get &quot;2 * albedo&quot;. That does not seem right. This means that the more and more bounces I make the bigger influence the light has which is nonsense. The light should be dimmer from the 3rd bounce than from the 1st bounce. Where did I make a mistake?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uKxvp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36056" PostHistoryTypeId="1" PostId="12468" RevisionGUID="64efb49c-71c8-4857-b560-978a13292bd1" CreationDate="2022-01-17T00:03:41.880" UserId="12040" Text="Rendering equation - brdf / pdf &gt; 1?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36057" PostHistoryTypeId="3" PostId="12468" RevisionGUID="64efb49c-71c8-4857-b560-978a13292bd1" CreationDate="2022-01-17T00:03:41.880" UserId="12040" Text="|raytracing|rendering|pathtracing|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36058" PostHistoryTypeId="50" PostId="10154" RevisionGUID="771ab002-6aef-415c-91e5-192db607d924" CreationDate="2022-01-17T19:05:45.577" UserId="-1" />
  <row Id="36059" PostHistoryTypeId="2" PostId="12469" RevisionGUID="f93d2f78-f1fc-426b-928e-fb012db4b487" CreationDate="2022-01-17T22:05:01.713" UserId="17867" Text="I have encountered two solid grey textures, #303030 and #1b1b1b, being put through texture compression and coming out as #313031 (changed) and #1b1b1b (unchanged), presumably due to the 32-bit (8:8:8) to 16-bit (5:6:5) stage. For a texture with many colors I understand that texture compressor could pick arbitrary endpoints for the palette and I am effectively at the mercy of chance regarding which colors change how much. However, with single solid color textures, I am hopeful that there is some modern equivalent of [web-safe colors][1] that I could at least somewhat rely on. Does this exist?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors" ContentLicense="CC BY-SA 4.0" />
  <row Id="36061" PostHistoryTypeId="1" PostId="12469" RevisionGUID="f93d2f78-f1fc-426b-928e-fb012db4b487" CreationDate="2022-01-17T22:05:01.713" UserId="17867" Text="Are certain solid colors more likely to survive texture compression unchanged?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36062" PostHistoryTypeId="3" PostId="12469" RevisionGUID="f93d2f78-f1fc-426b-928e-fb012db4b487" CreationDate="2022-01-17T22:05:01.713" UserId="17867" Text="|texture|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36063" PostHistoryTypeId="10" PostId="12462" RevisionGUID="5f6560ba-fba7-4cf0-9d1f-69d3460416a6" CreationDate="2022-01-17T23:21:20.550" UserId="482" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:7952,&quot;DisplayName&quot;:&quot;pmw1234&quot;},{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}]}" />
  <row Id="36064" PostHistoryTypeId="2" PostId="12470" RevisionGUID="a39e8ba7-2461-4928-a881-0623b4725a41" CreationDate="2022-01-18T02:21:04.763" UserId="17868" Text="I'm learning OpenGL for a personal project. I need to draw a triangle mesh as a wireframe. From what I've read, I can do this using glPolygonMode. However, the program always draws my polygons filled. Is is a bad driver? I'm using the linux subsystem on a chromebook. It's basically debian in a container. How do I get an wireframe triangle? &#xD;&#xA;&#xD;&#xA;Here is my program, with all the windowing functions and the shader compilation pulled into their own .cpp file. &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#include &lt;glad/glad.h&gt;&#xD;&#xA;#include &lt;GLFW/glfw3.h&gt;&#xD;&#xA;#include &lt;glm/glm.hpp&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &quot;ah_graphics.h&quot;&#xD;&#xA;#include &quot;ah_window.h&quot;&#xD;&#xA;&#xD;&#xA;const char *vertexShaderSource();&#xD;&#xA;&#xD;&#xA;const char *fragmentShaderSource();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;// set up vertex data (and buffer(s)) and configure vertex attributes&#xD;&#xA;// ------------------------------------------------------------------&#xD;&#xA;float positions[] = {&#xD;&#xA;        -1.0f, 1.0f, 0.0f, // left&#xD;&#xA;        -1.0f, 0.0f, 0.0f, // right&#xD;&#xA;        0.0f, 1.0f, 0.0f // top&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;int main() {&#xD;&#xA;    GLFWwindow *window = ahCreateWindow(800, 600);&#xD;&#xA;    ahLoadGlFunctionPointers();&#xD;&#xA;    GLuint program = ahCreateGlProgram(vertexShaderSource(), fragmentShaderSource());&#xD;&#xA;    unsigned int VBO_pos, VAO;&#xD;&#xA;    glGenVertexArrays(1, &amp;VAO);&#xD;&#xA;    glBindVertexArray(VAO);&#xD;&#xA;    glGenBuffers(1, &amp;VBO_pos);&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, VBO_pos);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);&#xD;&#xA;    int numComponents = 3; // (x,y,z) and (r,g,b)&#xD;&#xA;    std::size_t stride = numComponents * sizeof(float);&#xD;&#xA;    glVertexAttribPointer(0, numComponents, GL_FLOAT, GL_FALSE, stride, (void *) 0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    while (!glfwWindowShouldClose(window)) {&#xD;&#xA;        // input&#xD;&#xA;        ahProcessInput(window);&#xD;&#xA;        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;        glUseProgram(program);&#xD;&#xA;        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);&#xD;&#xA;        glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;        glfwSwapBuffers(window);&#xD;&#xA;        glfwPollEvents();&#xD;&#xA;    }&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;const char *vertexShaderSource() {&#xD;&#xA;    return &quot;#version 330 core\n&quot;&#xD;&#xA;           &quot;layout (location = 0) in vec3 aPos;\n&quot;&#xD;&#xA;           &quot;void main()\n&quot;&#xD;&#xA;           &quot;{\n&quot;&#xD;&#xA;           &quot;  gl_Position = vec4(aPos, 1.0);\n&quot;&#xD;&#xA;           &quot;}\0&quot;;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;const char *fragmentShaderSource() {&#xD;&#xA;    return &quot;#version 330 core\n&quot;&#xD;&#xA;           &quot;void main()\n&quot;&#xD;&#xA;           &quot;{\n&quot;&#xD;&#xA;           &quot; gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n&quot;&#xD;&#xA;           &quot;}\n\0&quot;;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And this is the scene it renders:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/u4YIk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36066" PostHistoryTypeId="1" PostId="12470" RevisionGUID="a39e8ba7-2461-4928-a881-0623b4725a41" CreationDate="2022-01-18T02:21:04.763" UserId="17868" Text="OpenGL ignores glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);" ContentLicense="CC BY-SA 4.0" />
  <row Id="36067" PostHistoryTypeId="3" PostId="12470" RevisionGUID="a39e8ba7-2461-4928-a881-0623b4725a41" CreationDate="2022-01-18T02:21:04.763" UserId="17868" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36068" PostHistoryTypeId="5" PostId="12467" RevisionGUID="59aa2f10-17c9-4b9a-8eb2-44095dde2487" CreationDate="2022-01-18T04:35:53.523" UserId="17860" Comment="added 650 characters in body" Text="I thought that if I used an image with a transparent background, I would still be able to see the colors I had specified in my vertex attribute buffer.&#xD;&#xA;&#xD;&#xA;        // Vertices coordinates&#xD;&#xA;    GLfloat vertices[] =&#xD;&#xA;    { //     COORDINATES     /        COLORS      /   TexCoord  //&#xD;&#xA;    	-0.5f, 0.0f,  0.5f,     0.83f, 0.70f, 0.44f,	0.0f, 0.0f,&#xD;&#xA;    	-0.5f, 0.0f, -0.5f,     0.83f, 0.70f, 0.44f,	5.0f, 0.0f,&#xD;&#xA;    	 0.5f, 0.0f, -0.5f,     0.83f, 0.70f, 0.44f,	0.0f, 0.0f,&#xD;&#xA;    	 0.5f, 0.0f,  0.5f,     0.83f, 0.70f, 0.44f,	5.0f, 0.0f,&#xD;&#xA;    	 0.0f, 0.8f,  0.0f,     0.92f, 0.86f, 0.76f,	2.5f, 5.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;This is not the case however, and what I am getting instead is this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What would be the easiest way to see my specified colors instead of all that black on my object?&#xD;&#xA;&#xD;&#xA;default.vert&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout (location = 0) in vec3 aPos;&#xD;&#xA;    layout (location  =1) in vec3 aColor;&#xD;&#xA;    layout (location =2) in vec2  aTex;&#xD;&#xA;    &#xD;&#xA;    out vec3 color;&#xD;&#xA;    &#xD;&#xA;    out vec2 texcoord;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    uniform mat4 camMatrix;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = camMatrix* vec4(aPos, 1.0);&#xD;&#xA;        color =aColor;&#xD;&#xA;        texcoord = aTex;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;default.frag&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    out vec4 FragColor;&#xD;&#xA;    &#xD;&#xA;    in vec3 aColor;&#xD;&#xA;    &#xD;&#xA;    in vec2 texcoord;&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D tex0;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        FragColor = texture(tex0, texcoord );&#xD;&#xA;        &#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RH4yC.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36069" PostHistoryTypeId="5" PostId="12468" RevisionGUID="f325ac8b-6283-41eb-9e73-e1f465d701cf" CreationDate="2022-01-18T10:10:46.287" UserId="12040" Comment="Adding pseudo code" Text="I am creating a path tracer and I got some strange results when calculating the strength of light.&#xD;&#xA;&#xD;&#xA;I am using a rendering equation inspired by this diagram:&#xD;&#xA;[![Rendering equation][1]][1]&#xD;&#xA;&#xD;&#xA;1) When I use the cosine everything gets really dark and the edges of my spheres are almost black. That makes sense because I am almost multiplying by cos(PI/2) = 0. I have read that it suppose to cancel out with something so I have removed it which help. But what does it cancel out with?&#xD;&#xA;&#xD;&#xA;2) I am using Lambertian diffuse BRDF which means that the &quot;Fr&quot; part of the equation should be &quot;albedo / PI&quot;. I am also doing uniform hemisphere sampling which gave me a PDF of 1 / PI.&#xD;&#xA;Now when I calculate BRDF / PDF I get &quot;2 * albedo&quot;. That does not seem right. This means that the more and more bounces I make the bigger influence the light has which is nonsense. The light should be dimmer from the 3rd bounce than from the 1st bounce. Where did I make a mistake?&#xD;&#xA;&#xD;&#xA;**EDIT 1:**&#xD;&#xA;I am including pseudo-code. The cosine is the dot product. And after boun&#xD;&#xA;There are some things I have not included because they do not contribute to the equation. &#xD;&#xA;&#xD;&#xA;    &lt;!-- language: lang-cpp --&gt;&#xD;&#xA;    //Initialization&#xD;&#xA;    Ray ray;&#xD;&#xA;    float3 passthrought = (1,1,1);&#xD;&#xA;    float3 color = (0,0,0);&#xD;&#xA;    &#xD;&#xA;    //Bouncing&#xD;&#xA;    for(int I = 0; i &lt; 4; i++){&#xD;&#xA;        Object obj = ray.intersect(...);&#xD;&#xA;&#xD;&#xA;        color += obj.emission * passthrought;&#xD;&#xA;&#xD;&#xA;        float3 newDirection = sample_hemisphere();&#xD;&#xA;        float pdf = 1 / (2 * PI);&#xD;&#xA;        float3 brdf = obj.color / PI; &#xD;&#xA;&#xD;&#xA;        if(pdf &gt; EPSILON)&#xD;&#xA;            passthrought *= dot(normal, newDirection) * brdf / pdf;&#xD;&#xA;        else&#xD;&#xA;            passthrought *= 0;&#xD;&#xA;&#xD;&#xA;        //Prepare new bounce&#xD;&#xA;        ray.origin = ray.direction * ray.distance + ray.origin;&#xD;&#xA;        ray.direction = newDirection;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float3 sample_hemisphere(){&#xD;&#xA;        //Tranformation to world space&#xD;&#xA;        float3 w = ray-&gt;worldNormal;&#xD;&#xA;	    float3 axis = fabs(w.x) &gt; 0.1f ? (float3)(0.0f, 1.0f, 0.0f) : (float3)(1.0f, 0.0f, 0.0f);&#xD;&#xA;	    float3 u = normalize(cross(axis, w));&#xD;&#xA;	    float3 v = cross(w, u);&#xD;&#xA;&#xD;&#xA;        //Sampling from 2 random variables &lt;0, 1&gt;&#xD;&#xA;	    float e1 = rand();&#xD;&#xA;	    float e2 = rand();&#xD;&#xA;&#xD;&#xA;	    float s = sqrt(1.0 - e1 * e1);&#xD;&#xA;	    float phi = 2 * M_PI_F * e2;&#xD;&#xA;&#xD;&#xA;	    return normalize(u * cos(2 * M_PI_F * e2) * s + v * sin(2 * M_PI_F * e2) * s + w * e1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uKxvp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36070" PostHistoryTypeId="5" PostId="12468" RevisionGUID="49357ba9-55b0-455d-b456-4b944570ad0b" CreationDate="2022-01-18T10:19:51.080" UserId="12040" Comment="Adding pseudo code" Text="I am creating a path tracer and I got some strange results when calculating the strength of light.&#xD;&#xA;&#xD;&#xA;I am using a rendering equation inspired by this diagram:&#xD;&#xA;[![Rendering equation][1]][1]&#xD;&#xA;&#xD;&#xA;1) When I use the cosine everything gets really dark and the edges of my spheres are almost black. That makes sense because I am almost multiplying by cos(PI/2) = 0. I have read that it suppose to cancel out with something so I have removed it which help. But what does it cancel out with?&#xD;&#xA;&#xD;&#xA;2) I am using Lambertian diffuse BRDF which means that the &quot;Fr&quot; part of the equation should be &quot;albedo / PI&quot;. I am also doing uniform hemisphere sampling which gave me a PDF of 1 / PI.&#xD;&#xA;Now when I calculate BRDF / PDF I get &quot;2 * albedo&quot;. That does not seem right. This means that the more and more bounces I make the bigger influence the light has which is nonsense. The light should be dimmer from the 3rd bounce than from the 1st bounce. Where did I make a mistake?&#xD;&#xA;&#xD;&#xA;**EDIT 1:**&#xD;&#xA;I am including pseudo-code. The cosine is the dot product. And after boun&#xD;&#xA;There are some things I have not included because they do not contribute to the equation. &#xD;&#xA;&#xD;&#xA;    &lt;!-- language: lang-cpp --&gt;&#xD;&#xA;    //Initialization&#xD;&#xA;    Ray ray;&#xD;&#xA;    float3 passthrought = (1,1,1);&#xD;&#xA;    float3 color = (0,0,0);&#xD;&#xA;    &#xD;&#xA;    //Bouncing&#xD;&#xA;    for(int I = 0; i &lt; 4; i++){&#xD;&#xA;        Object obj = ray.intersect(...);&#xD;&#xA;&#xD;&#xA;        color += obj.emission * passthrought;&#xD;&#xA;&#xD;&#xA;        float3 newDirection = sample_hemisphere();&#xD;&#xA;        float pdf = 1 / (2 * PI);&#xD;&#xA;        float3 brdf = obj.color / PI; &#xD;&#xA;&#xD;&#xA;        if(pdf &gt; EPSILON)&#xD;&#xA;            passthrought *= dot(normal, newDirection) * brdf / pdf;&#xD;&#xA;        else&#xD;&#xA;            passthrought *= 0;&#xD;&#xA;&#xD;&#xA;        //Prepare new bounce&#xD;&#xA;        ray.origin = ray.direction * ray.distance + ray.origin;&#xD;&#xA;        ray.direction = newDirection;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float3 sample_hemisphere(){&#xD;&#xA;        //Tranformation to world space&#xD;&#xA;        float3 w = ray-&gt;worldNormal;&#xD;&#xA;	    float3 axis = fabs(w.x) &gt; 0.1f ? (float3)(0.0f, 1.0f, 0.0f) : (float3)(1.0f, 0.0f, 0.0f);&#xD;&#xA;	    float3 u = normalize(cross(axis, w));&#xD;&#xA;	    float3 v = cross(w, u);&#xD;&#xA;&#xD;&#xA;        //Sampling from 2 random variables &lt;0, 1&gt;&#xD;&#xA;	    float e1 = rand();&#xD;&#xA;	    float e2 = rand();&#xD;&#xA;&#xD;&#xA;	    float s = sqrt(1.0 - e1 * e1);&#xD;&#xA;	    float phi = 2 * M_PI_F * e2;&#xD;&#xA;&#xD;&#xA;	    return normalize(u * cos(2 * M_PI_F * e2) * s + v * sin(2 * M_PI_F * e2) * s + w * e1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Edit 2:**&#xD;&#xA;I just wanted to include an example render with both variants and somehow it works now. The black border around objects is gone. I think I had to calculate the cosine with normal and the ray towards the camera which was wrong. Anyway, I am including 2 renders one with a cosine of normal and **outgoing** ray and one without it. Keep in mind that Reinhard tone mapping with white point set to max luminance and gamma correction of 1/2.2 was applied. Which one of them is more right?&#xD;&#xA;&#xD;&#xA;With cosine:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;without cosine (is smoother because it has like 10 times more samples):&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uKxvp.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/rx6nd.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/FEgtC.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36071" PostHistoryTypeId="2" PostId="12471" RevisionGUID="e25a3e27-1f28-4379-bef7-523a9c6e71c2" CreationDate="2022-01-18T16:45:56.157" UserId="2654" Text="There are two possibilities: you either are in control of the image format or you're not.&#xD;&#xA;&#xD;&#xA;If you are in control of the image format, and you need a color to be exact, then use an image format that gives you that exact color. If the color you want cannot be represented in a 5:6:5 format, *don't use them*.&#xD;&#xA;&#xD;&#xA;If you have no control over the image format, then you're going to have to look at what image format you're *told* to use and find something that's good enough. For basic 5:6:5, that's not too hard. But if you're being forced to use actual texture compression... you're out of luck.&#xD;&#xA;&#xD;&#xA;Note that JPEG *does not care* about &quot;web-safe colors&quot;; it will do whatever it wants to the image. The same goes for texture compression schemes. By using texture compression, you have decided to sacrifice image accuracy for smaller space. That's just the nature of the beast." ContentLicense="CC BY-SA 4.0" />
  <row Id="36085" PostHistoryTypeId="50" PostId="12414" RevisionGUID="65b72174-f528-43e0-bba3-a2a192ef12c1" CreationDate="2022-01-20T08:07:30.857" UserId="-1" />
  <row Id="36088" PostHistoryTypeId="5" PostId="12469" RevisionGUID="0785e1f6-0b18-4e47-93ca-77c31a711d8a" CreationDate="2022-01-20T15:08:26.967" UserId="17867" Comment="specify hardware compression" Text="I have encountered two solid grey textures, #303030 and #1b1b1b, being put through [BCn texture compression][1] and coming out as #313031 (changed) and #1b1b1b (unchanged), presumably due to the 32-bit (8:8:8) to 16-bit (5:6:5) stage. For a texture with many colors I understand that texture compressor could pick arbitrary endpoints for the palette and I am effectively at the mercy of chance regarding which colors change how much. However, with single solid color textures, I am hopeful that there is some modern equivalent of [web-safe colors][2] that I could at least somewhat rely on. Does this exist?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors" ContentLicense="CC BY-SA 4.0" />
  <row Id="36089" PostHistoryTypeId="4" PostId="12469" RevisionGUID="0785e1f6-0b18-4e47-93ca-77c31a711d8a" CreationDate="2022-01-20T15:08:26.967" UserId="17867" Comment="specify hardware compression" Text="Are certain solid colors more likely to survive hardware texture compression unchanged?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36090" PostHistoryTypeId="2" PostId="12475" RevisionGUID="bc207bc2-50c5-445e-9009-54236a4c8f34" CreationDate="2022-01-20T16:51:28.173" UserId="17876" Text="In late 1990s and early 2000, I tried out &quot;Active Worlds&quot; and more. They let me register an account and then walk around in a vast 3D world and chat with people/avatars. It was surreal and frankly felt more scary and unsettling than exciting, in spite of the bright and colorful visuals.&#xD;&#xA;&#xD;&#xA;Fast-forward to ~2007, there was a brief mainstream &quot;Second Life&quot; craze. I tried it out for about 15 minutes then and was forced to conclude that it looked even worse than what I remember from those many years earlier.&#xD;&#xA;&#xD;&#xA;Now there's yet again this &quot;Metaverse&quot; being constantly mentioned/pushed. This time, I didn't even bother downloading anything (I bet I couldn't even join it now anyway, as it seems to require a Facebook account or something), but rather just watched gameplay footage on YouTube.&#xD;&#xA;&#xD;&#xA;It looks exactly like it did 22+ years ago. No joke.&#xD;&#xA;&#xD;&#xA;It's still the same worse-than-cartoony, deadly dull, sterile look. I expected it to be literally photo-realistic at this point, but they seem to not even be trying.&#xD;&#xA;&#xD;&#xA;Can somebody please explain to me how it's possible that so much happened up until the late 1990s, but since then, apparently, *nothing* has improved whatsoever? I know for a fact that they are able to make extremely realistic simulations, so why can't I launch an EXE on my desktop right now which lets me walk around in first person in an extremely realistic virtual city and own my own virtual apartment and go down to the store and buy items and have all kinds of exciting adventures which I would never dare or be able to do in real life?&#xD;&#xA;&#xD;&#xA;Not only are we &quot;not quite there yet&quot; -- they don't even seem to be *trying*, or even using existing technology. I don't get it." ContentLicense="CC BY-SA 4.0" />
  <row Id="36092" PostHistoryTypeId="1" PostId="12475" RevisionGUID="bc207bc2-50c5-445e-9009-54236a4c8f34" CreationDate="2022-01-20T16:51:28.173" UserId="17876" Text="Why does today's &quot;Metaverse&quot; look equally or even worse than the 1990s 3D chat worlds?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36093" PostHistoryTypeId="3" PostId="12475" RevisionGUID="bc207bc2-50c5-445e-9009-54236a4c8f34" CreationDate="2022-01-20T16:51:28.173" UserId="17876" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36099" PostHistoryTypeId="2" PostId="12477" RevisionGUID="6cea9f83-7da4-47c5-bcc5-b5b17fe448ea" CreationDate="2022-01-20T22:31:04.943" UserId="17879" Text="I want to make a program that, for starters, list all image files in a folder and writes a warning if one dimension is (i.e.) double (2x) the other dimension, regardless of &quot;image orientation&quot;.&#xD;&#xA;&#xD;&#xA;I know how to do this, I divide the bigger dimension with the smaller dimension, and if the quotient is 2 or greater, there would be a warning.&#xD;&#xA;&#xD;&#xA;Q1: Is there a best practise for this; should divide the bigger with the smaller dimension (and look for numbers higher than 1, i.e. 2) OR should I divide the smaller with the bigger dimension (and look for numbers lower than 1, i.e. 0.5)?&#xD;&#xA;&#xD;&#xA;Q2: In this context, photo/graphics, what is the quotient called after &quot;solving the ratio&quot; (if it has got a name), and how to &quot;solve&quot; it?&#xD;&#xA;&#xD;&#xA;As a measure the program would then add padding to make image more square like.&#xD;&#xA;&#xD;&#xA;I hope this question could be useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="36101" PostHistoryTypeId="1" PostId="12477" RevisionGUID="6cea9f83-7da4-47c5-bcc5-b5b17fe448ea" CreationDate="2022-01-20T22:31:04.943" UserId="17879" Text="Can an aspect ratio be shortened to one value, best practise" ContentLicense="CC BY-SA 4.0" />
  <row Id="36102" PostHistoryTypeId="3" PostId="12477" RevisionGUID="6cea9f83-7da4-47c5-bcc5-b5b17fe448ea" CreationDate="2022-01-20T22:31:04.943" UserId="17879" Text="|transformations|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36103" PostHistoryTypeId="2" PostId="12478" RevisionGUID="32aa4367-4a3f-4c78-ac75-15ba73c9ae02" CreationDate="2022-01-21T01:06:59.087" UserId="506" Text="One of the main reasons is that a number of these “metaverse” (ugh) products are meant to run on consumer VR hardware, which is _at best_ a high-end desktop machine with a good GPU, but is much more likely to be a mobile device like a Quest. VR demands high frame rates—75 to 90 frames per second as a rule—and in the absence of fancy techniques like [foveated rendering](https://en.wikipedia.org/wiki/Foveated_rendering) (which requires eye-tracking hardware absent from most consumer headsets), you have to render two full-size viewpoints rather than one.&#xD;&#xA;&#xD;&#xA;In other words, a virtual world that can run at 60fps at 1080p resolution—already a bar many games don’t clear on midrange consumer PCs—would need to be optimized to run more than twice as fast for an acceptable VR experience. Add slower mobile processors into the equation and the visual quality has to drop dramatically to be at all viable." ContentLicense="CC BY-SA 4.0" />
  <row Id="36110" PostHistoryTypeId="5" PostId="12477" RevisionGUID="048067dc-22be-4d8d-8ad8-b06ef011f770" CreationDate="2022-01-21T23:38:41.877" UserId="17879" Comment="Removing a branch question" Text="I want to make a program that, for starters, list all image files in a folder and writes a warning if one dimension is (i.e.) double (2x) the other dimension, regardless of &quot;image orientation&quot;.&#xD;&#xA;&#xD;&#xA;I know how to do this, I divide the bigger dimension with the smaller dimension, and if the quotient is 2 or greater, there would be a warning...&#xD;&#xA;&#xD;&#xA;Is there a best practise for this; should divide the bigger with the smaller dimension (and look for numbers higher than 1, i.e. 2) OR should I divide the smaller with the bigger dimension (and look for numbers lower than 1, i.e. 0.5)?&#xD;&#xA;&#xD;&#xA;As a measure the program would then add padding to make image more square like. Actually I have done this already in Java code, now I try 'go'.&#xD;&#xA;&#xD;&#xA;I hope this question could be useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="36112" PostHistoryTypeId="2" PostId="12480" RevisionGUID="7cd49240-775a-4a8f-a473-dd0c83cf11c5" CreationDate="2022-01-22T05:57:05.673" UserId="17772" Text="There is no true standard for storing an aspect ratio as bytes. However, If you remember how ratio mostly written in math, it looks like this:&#xD;&#xA;&#xD;&#xA;&gt; 1:20&#xD;&#xA;&#xD;&#xA;&gt; 1:0.33333&#xD;&#xA;&#xD;&#xA;&gt; 1:2.4&#xD;&#xA;&#xD;&#xA;Thus, I would recommend you to transform your aspect ratio that way and **only stores the right side as a float**. If precision is more important than memory size, then make it double instead of float." ContentLicense="CC BY-SA 4.0" />
  <row Id="36114" PostHistoryTypeId="2" PostId="12481" RevisionGUID="9ee89f9c-336e-40de-98ec-2f9f1c6111c7" CreationDate="2022-01-22T06:04:49.773" UserId="17772" Text="I would like to represent creation for each 2D shape or bitmap effect as a pipeline. The only purpose of this to modularize algorithms because extendibility is a big deal for current project. However, is there any drawback for using that kind of strategy? If it’s too risky (in term of performance and stability), then any other alternatives?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36116" PostHistoryTypeId="1" PostId="12481" RevisionGUID="9ee89f9c-336e-40de-98ec-2f9f1c6111c7" CreationDate="2022-01-22T06:04:49.773" UserId="17772" Text="A lot of pipelines on Vulkan for each render pass, what could go wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36117" PostHistoryTypeId="3" PostId="12481" RevisionGUID="9ee89f9c-336e-40de-98ec-2f9f1c6111c7" CreationDate="2022-01-22T06:04:49.773" UserId="17772" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36118" PostHistoryTypeId="2" PostId="12482" RevisionGUID="4eb198ca-0b1e-49da-877b-eb2b4695b368" CreationDate="2022-01-22T13:20:10.860" UserId="7952" Text="Binding a Graphics Pipeline in Vulkan is considered to be an expensive operation. So performance can be an issue if a program wants to bind many pipelines for each frame. Binding hundreds or even a few thousand pipelines per a frame is reasonable, a high end system could support up into the tens of thousands (good luck getting anything else done though).&#xD;&#xA;&#xD;&#xA;Alternatives:&#xD;&#xA;&#xD;&#xA;Vulkan allows some parts of the pipeline to be dynamic, the list of what can be dynamic was recently extended as well. Using dynamic pipelines is less efficient then using a &quot;non&quot; dynamic pipes, but much more efficient then constantly binding many different pipelines.&#xD;&#xA;&#xD;&#xA;Even if there are only a few pipelines per a frame, a program can still get into trouble by constantly switching between pipelines. So, combine draw calls on a per pipe basis, meaning bind a pipe, do all the draws for that pipe, bind the next pipe, etc.&#xD;&#xA;&#xD;&#xA;Finding ways to merge shaders is probably the best way to reduce the number of pipelines. The extreme on this is the so called *uber* shader where virtually all the shaders are merged into a single shader. Just merging groups of similar shaders can greatly reduce the number of pipelines though and is usually fairly easy to do.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There is a little hand waving for this next one, but I have seen some programs with hardcoded descriptor values inside shaders which causes pipeline count to explode, just switching to multiple descriptor sets helps resolve this. This creates a system where a pipeline is bound, then each draw for that pipeline binds a descriptor set. (often there is a single descriptor set that has all the generic info in it, and a per draw set that has per draw specific info) This has its own drawbacks but is better then many graphics pipelines. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36120" PostHistoryTypeId="2" PostId="12483" RevisionGUID="aec86019-855e-4888-b8b4-79a23b559cbc" CreationDate="2022-01-22T17:43:30.733" UserId="7952" Text="Aspect ratio's are usually described in terms of width and height not bigger vs smaller. for example 16:9 is a width : height ratio.  It doesn't matter if you pick &#xD;&#xA; width/height or height/width but being consistent *is* important. So pick one and stick with it. To check for a ratio where one dimension is over 2x the other dimension:&#xD;&#xA;&#xD;&#xA;    float ratio = width/height;&#xD;&#xA;    if( ratio &gt;= 2.0  || ratio &lt;= 0.5 ) { warn_ratio(); }&#xD;&#xA;&#xD;&#xA;The same code works whether it is width/height or height/width.&#xD;&#xA;&#xD;&#xA;Should they be saved as a single floating point value or two separate (usually integer) values? That doesn't matter. I suggest just programming it into obscurity with something like:&#xD;&#xA;&#xD;&#xA;    class Aspect {&#xD;&#xA;         Aspect( int width, int height ) : ratio(width/height) {}&#xD;&#xA;         float ratio;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Add a float conversion operator to the above class and it will automatically cast to a float (and a const float) as needed. If for some reason the code needs to store the ratio as two values later, it is easy to convert it and the cast operation to use two values instead." ContentLicense="CC BY-SA 4.0" />
  <row Id="36124" PostHistoryTypeId="10" PostId="12475" RevisionGUID="08fe506a-80d9-4081-8f1b-d021f87cd34d" CreationDate="2022-01-22T21:49:20.177" UserId="13095" Comment="105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="36125" PostHistoryTypeId="50" PostId="9116" RevisionGUID="c30abd6c-b407-423b-97ed-bd59f4d477e8" CreationDate="2022-01-23T10:05:10.587" UserId="-1" />
  <row Id="36126" PostHistoryTypeId="2" PostId="12484" RevisionGUID="6bc8729e-7c2c-49c0-9f9e-85719a21cf1f" CreationDate="2022-01-23T12:10:27.770" UserId="17893" Text="Your screen has 1440 pixels vertically and you are trying to fit them into 1080 pixel picture. How? His monitor has 1080 pixels fitting into 1080 pixel picture. Therefore the saying &quot;pixel perfect&quot;. What your monitor is trying to do is somehow use extra pixels but their algorithms cannot easily do this without some blur. You can tell your monitor not to scale picture to whole screen and just use black bars for the excess pixels. This works however remember that your pixel is smaller and your 1080p picture will look small and hardly readable. Also you can make custom resolution. " ContentLicense="CC BY-SA 4.0" />
  <row Id="36129" PostHistoryTypeId="2" PostId="12485" RevisionGUID="e4029945-2830-4042-ac16-e7b7c83762dd" CreationDate="2022-01-23T17:18:45.177" UserId="17895" Text="I am a beginner at graphics. I am given a triangular mesh (assume a manifold mesh). I want to sample a square on a mesh that is independent of the triangulation.&#xD;&#xA;&#xD;&#xA;I am following these steps&#xD;&#xA;&#xD;&#xA; - Sample a triangle (based on the areas of the triangles)&#xD;&#xA; - Sample a point uniformly on the triangle&#xD;&#xA; - Sample a random direction&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now all corners of the square can be computed using that point as the origin (and the direction as the x-axis) on a 2D plane trivially. I want to get (Face, barycentric coordinates) of corners of the square on the mesh efficiently (preferably in C++/python) since I'll need to sample a random square again and again. I am looking at libraries such as [Polyscope][1] or [pygeodesic][2] that use the heat method to compute the geodesic distance between vertices of the mesh, but I am not sure how to get points at an arbitrary geodesic distance from another point. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://polyscope.run/structures/surface_mesh/distance_quantities/&#xD;&#xA;  [2]: https://pypi.org/project/pygeodesic/" ContentLicense="CC BY-SA 4.0" />
  <row Id="36131" PostHistoryTypeId="1" PostId="12485" RevisionGUID="e4029945-2830-4042-ac16-e7b7c83762dd" CreationDate="2022-01-23T17:18:45.177" UserId="17895" Text="Given a mesh, a point on the mesh, a direction and a distance, compute the face+barycentric coordinates of point at that geodesic distance" ContentLicense="CC BY-SA 4.0" />
  <row Id="36132" PostHistoryTypeId="3" PostId="12485" RevisionGUID="e4029945-2830-4042-ac16-e7b7c83762dd" CreationDate="2022-01-23T17:18:45.177" UserId="17895" Text="|computational-geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36134" PostHistoryTypeId="50" PostId="9781" RevisionGUID="9e4545e6-4456-42db-a1da-56c58d6ed8d9" CreationDate="2022-01-24T19:07:20.707" UserId="-1" />
  <row Id="36135" PostHistoryTypeId="33" PostId="12470" RevisionGUID="b1861cbc-0e9d-4eea-aef3-483680b8b4b2" CreationDate="2022-01-24T23:21:38.590" UserId="17868" Comment="74" />
  <row Id="36136" PostHistoryTypeId="50" PostId="10177" RevisionGUID="6d853351-f746-4ea8-824f-d106d9f29475" CreationDate="2022-01-25T04:09:55.977" UserId="-1" />
  <row Id="36137" PostHistoryTypeId="2" PostId="12486" RevisionGUID="74ddd908-cfe2-41b2-9cc3-cba2dc7aed9d" CreationDate="2022-01-25T12:32:12.620" UserId="7952" Text="&#xD;&#xA;There is a little setup to get this to work correctly, and a few different approach's that can be taken. &#xD;&#xA;&#xD;&#xA;First the image needs to somehow mark the texel's in the image that need to be shown as the background color. If this isn't done and the generic background color is chosen such as black, vec3(0,0,0), then the background color will bleed through anyplace the image uses the same color. Here is some code to try that will demonstrate the issue: ( in the fragment shader)&#xD;&#xA;&#xD;&#xA;    FragColor = texture(tex0, texcoord );&#xD;&#xA;    if( FragColor.xyz == vec3(0,0,0)) { FragColor = aColor; }&#xD;&#xA;&#xD;&#xA;One way to fix this is to use the same code above and edit the image so that the texels that need to be the background color are set to a unique color that isn't used anywhere else in the image. This method essentially forces the entire project to &quot;never&quot; use the chosen background in the visible parts of an image. As you can &#xD;&#xA;guess, this approach becomes its own headache.&#xD;&#xA;&#xD;&#xA;A better way is to add an alpha channel to the image. This is done by OpenGL anyway when the image is loaded. (OpenGL implementations almost never store images as three channel RGB colors, a fourth Alpha channel is added). Unfortunetaly this also means that the image has to be edited. First it needs an alpha channel added (any good image editor can do this) and then the alpha channel needs to be adjusted so that the areas that need to show the shader color are zero, and other areas are one. Then in the fragment shader the code can be changed to handle the color, which could look something like...&#xD;&#xA;&#xD;&#xA;     if( FragColor.a == 0.0) { FragColor = aColor; } // don't do this&#xD;&#xA;&#xD;&#xA;But if statements can be terribly slow, and there is a much better way by using simple &quot;alpha blending&quot;, such as:&#xD;&#xA;&#xD;&#xA;     vec4 texColor = texture(tex0, texcoord );&#xD;&#xA;     float a = texColor.a;&#xD;&#xA;     FragColor = aColor * (1-a) + texColor * a; // this is called the &quot;over&quot; operator&#xD;&#xA;     FragColor.a = 1.0; // force the alpha channel back to 1&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;This allows the alpha channel to vary so that blending can be done at the edges, you could even use a second image as a background just by changing aColor to a second texture read, this is also basic alpha blending which turns out to be an &quot;interesting&quot; subject.&#xD;&#xA;&#xD;&#xA;Also this is doing all the alpha blending inside the shader so it doesn't require alpha blending to be enabled in OpenGL. Just make sure the image load is updated to handle a 4 channel image." ContentLicense="CC BY-SA 4.0" />
  <row Id="36139" PostHistoryTypeId="5" PostId="12486" RevisionGUID="75a5ee39-b6ac-4155-b21e-78aa5af3cdeb" CreationDate="2022-01-25T13:03:55.813" UserId="7952" Comment="deleted 62 characters in body" Text="&#xD;&#xA;There is a little setup to get this to work correctly, and a few different approach's that can be taken. &#xD;&#xA;&#xD;&#xA;First the image needs to somehow mark the texel's in the image that need to be shown as the background color. If this isn't done and the generic background color is chosen such as black, vec3(0,0,0), then the background color will bleed through anyplace the image uses the same color. Here is some code to try that will demonstrate the issue: ( in the fragment shader)&#xD;&#xA;&#xD;&#xA;    FragColor = texture(tex0, texcoord );&#xD;&#xA;    if( FragColor.xyz == vec3(0,0,0)) { FragColor = aColor; }&#xD;&#xA;&#xD;&#xA;One way to fix this is to use the same code above and edit the image so that the texels that need to be the background color are set to a unique color that isn't used anywhere else in the image. This method essentially forces the entire project to &quot;never&quot; use the chosen background in the visible parts of an image. As you can &#xD;&#xA;guess, this approach becomes its own headache.&#xD;&#xA;&#xD;&#xA;A better way is to add an alpha channel to the image. This is done by OpenGL anyway when the image is loaded. (OpenGL implementations almost never store images as three channel RGB colors, a fourth Alpha channel is added). Unfortunetaly this also means that the image has to be edited. First it needs an alpha channel added (any good image editor can do this) and then the alpha channel needs to be adjusted so that the areas that need to show the shader color are zero, and other areas are one. Then in the fragment shader the code can be changed to handle the color, which could look something like...&#xD;&#xA;&#xD;&#xA;     if( FragColor.a == 0.0) { FragColor = aColor; } // don't do this&#xD;&#xA;&#xD;&#xA;But if statements can be terribly slow, and there is a much better way by using simple &quot;alpha blending&quot;, such as:&#xD;&#xA;&#xD;&#xA;     vec4 texColor = texture(tex0, texcoord );&#xD;&#xA;     float a = texColor.a;&#xD;&#xA;     FragColor = aColor * (1-a) + texColor * a; // this is called the &quot;over&quot; operator&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;This allows the alpha channel to vary so that blending can be done at the edges, you could even use a second image as a background just by changing aColor to a second texture read, this is also basic alpha blending which turns out to be an &quot;interesting&quot; subject.&#xD;&#xA;&#xD;&#xA;Also this is doing all the alpha blending inside the shader so it doesn't require alpha blending to be enabled in OpenGL. Just make sure the image load is updated to handle a 4 channel image." ContentLicense="CC BY-SA 4.0" />
  <row Id="36140" PostHistoryTypeId="5" PostId="12439" RevisionGUID="f16e475d-9838-4d99-837c-9afb0e1d1bf7" CreationDate="2022-01-25T21:21:15.683" UserId="17768" Comment="added 13 characters in body; edited title" Text="It is possible to convert an image or other output to CIE Lab color model using GLSL? Does it require compute shaders or can be done using only vertex shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36141" PostHistoryTypeId="4" PostId="12439" RevisionGUID="f16e475d-9838-4d99-837c-9afb0e1d1bf7" CreationDate="2022-01-25T21:21:15.683" UserId="17768" Comment="added 13 characters in body; edited title" Text="Convert image to CIE Lab using GLSL to change hue/chroma" ContentLicense="CC BY-SA 4.0" />
  <row Id="36143" PostHistoryTypeId="2" PostId="12487" RevisionGUID="b15a6196-de6d-4c3d-868a-493d5b172a0e" CreationDate="2022-01-26T17:52:12.490" UserId="17343" Text="Suppose in perspective projection $(x, y, z)$ coordinate projects to point $(x_p, y_p, z_{vp})$ in projection plane $AX+BY+CZ+D=0$ where projection plane kept at $z_{vp}$ position. And the plane $AX+BY+CZ+D=0$ is satisfied by every point $(x_p, y_p, z_{vp})$ and in whole projection plane $z_{vp}$ is constant. &#xD;&#xA;&#xD;&#xA;Also we know that Z value(Z buffer value) for an object doesn't come from the z-value $z_{vp}$ of the projection plane.&#xD;&#xA;&#xD;&#xA;But in many [websites](https://www-geeksforgeeks-org.cdn.ampproject.org/v/s/www.geeksforgeeks.org/z-buffer-depth-buffer-method/amp/?usqp=mq331AQKKAFQArABIIACAw%3D%3D&amp;amp_js_v=a8&amp;amp_gsa=1#referrer=https%3A%2F%2Fwww.google.com&amp;csi=0&amp;ampshare=https%3A%2F%2Fwww.geeksforgeeks.org%2Fz-buffer-depth-buffer-method%2F) I seen Z value(Z buffer value) is calculating by the plane equation $AX+BY+CZ+D=0$ of the point (x, y, z) which is the point of space point not the projection plane point. My question is why can we calculate Z value(Z buffer value) from the plane equation $AX+BY+CZ+D=0$ of the space point $(x, y, z)$ because $AX+BY+CZ+D=0$ is only satisfied by the point  $(x_p, y_p, z_{vp})?$" ContentLicense="CC BY-SA 4.0" />
  <row Id="36145" PostHistoryTypeId="1" PostId="12487" RevisionGUID="b15a6196-de6d-4c3d-868a-493d5b172a0e" CreationDate="2022-01-26T17:52:12.490" UserId="17343" Text="Why we calculate z buffer value from plane equation $AX+BY+CZ+D=0$?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36146" PostHistoryTypeId="3" PostId="12487" RevisionGUID="b15a6196-de6d-4c3d-868a-493d5b172a0e" CreationDate="2022-01-26T17:52:12.490" UserId="17343" Text="|3d|projections|perspective|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36147" PostHistoryTypeId="2" PostId="12488" RevisionGUID="e4d1e425-3875-4d3b-8a90-8eecc9f05506" CreationDate="2022-01-26T18:37:18.890" UserId="2654" Text="You are talking about two different planes.&#xD;&#xA;&#xD;&#xA;The website is talking about the plane of the quadrilateral being rendered. It uses that plane to compute the Z for a particular X,Y point. Basically, the question being asked is, &quot;what is the Z value for the quad at this X,Y value on the screen?&quot; To compute that, you can use the plane equation for that plane, solve for Z, and plug in appropriate X, Y values.&#xD;&#xA;&#xD;&#xA;This is different from the plane of perspective projection.&#xD;&#xA;&#xD;&#xA;Now it should be said, this isn't how people compute the Z coordinate in perspective projection for rasterizers. The website in question is meant to explain how depth buffers work. As they require some sort of &quot;depth&quot; data, they present the simplest way to compute a Z value for a polygon as projected on a point on the screen. The depth buffer doesn't care about the exact values involved; so long as the closer values consistently have bigger or smaller values than those farther away, the depth test does what it is meant to do.&#xD;&#xA;&#xD;&#xA;So do not take this as &quot;how depth is calculated&quot;. It's merely an example meant to illustrate how the depth buffer works: it's a comparative test between the incoming fragment's depth and a stored depth.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36159" PostHistoryTypeId="2" PostId="12491" RevisionGUID="8f067776-1d0a-470e-a0e7-9cf666ba5f71" CreationDate="2022-01-27T10:21:15.397" UserId="16879" Text="Constant buffers stay constant throughout entire dispatches / draw calls, and thus their data can presumably be shared as efficiently as possible between different threads using those buffers.&#xD;&#xA;&#xD;&#xA;But I guess this probably doesn't mean they are &quot;free&quot; in terms of memory bandwidth? Are they loaded from memory once per thread group / wave (whatever hardware terminology is fitting), or are they somehow cached more efficiently?&#xD;&#xA;&#xD;&#xA;What other performance metrics / considerations do they affect? Is there something like register pressure where CB size can impact how well  your shader can be parallelized if the CB is too large (even below the 65k limit)?&#xD;&#xA;&#xD;&#xA;Is the size of your constant buffer something you should keep an eye out for when optimizing shaders, or is it shared efficiently enough that it's generally not a point of worry? For example, in many cases one can probably output constant buffer constants as shader code constants (leading to more variants) instead. Or maybe some computation in the shader is the result of two values in the CB - you could add a third value to the CB, or compute it on the fly in the shader for every single pixel / thread but in return you maybe don't have to fetch as much memory... how to reason about this?&#xD;&#xA;&#xD;&#xA;How is this impacted by different hardware vendors? For example, in certain cases I saw it recommended to use struct buffers instead of constant buffers, even if all data fetched is the same in an entire thread group, but only on certain hardware (was it AMD GCN?). I think light cluster culling is such a case, where one might want to fetch light list data with a struct buffer.&#xD;&#xA;&#xD;&#xA;My overall question is how to reason about the performance implications of constant buffers on various hardware . " ContentLicense="CC BY-SA 4.0" />
  <row Id="36161" PostHistoryTypeId="1" PostId="12491" RevisionGUID="8f067776-1d0a-470e-a0e7-9cf666ba5f71" CreationDate="2022-01-27T10:21:15.397" UserId="16879" Text="Performance impact/implications of constant buffers / uniform buffers" ContentLicense="CC BY-SA 4.0" />
  <row Id="36162" PostHistoryTypeId="3" PostId="12491" RevisionGUID="8f067776-1d0a-470e-a0e7-9cf666ba5f71" CreationDate="2022-01-27T10:21:15.397" UserId="16879" Text="|gpu|performance|constant-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36163" PostHistoryTypeId="2" PostId="12492" RevisionGUID="0bb67cee-ca36-46f6-923b-ba84e010e043" CreationDate="2022-01-27T14:41:56.643" UserId="2654" Text="There's no real way to know as there is significant hardware variance. AMD hardware for example doesn't have UBOs as a distinct concept; a UBO is implemented as a read-only SSBO, relying on caching to aid performance. Other hardware makers have specialized hardware for this stuff, where it reads from the buffer to populate the execution units, and never again.&#xD;&#xA;&#xD;&#xA;What matters is this: if you have data that the shader needs to access which is backed by GPU storage, and it fits within the hardware limitations of a UBO... then use them. They will be as fast as the hardware allows for that purpose. Something else might be equally as fast, but nothing will be *faster* (because the hardware would have just used that)." ContentLicense="CC BY-SA 4.0" />
  <row Id="36166" PostHistoryTypeId="2" PostId="12493" RevisionGUID="6123eb1a-d8ac-4d66-b5e5-615ee8fb907f" CreationDate="2022-01-27T20:05:07.910" UserId="17343" Text="Suppose I have one convex polyhedron, I need to detect back face. And $N=(A, B, C)$ is normal vector of polygon surface and vector V in viewing direction. According to books formula and internet content if $V. N&gt;0$ then polygon is back face otherwise front face. &#xD;&#xA;&#xD;&#xA;We know that $V. N=|V|.|N|cos\theta$ from this when we consider &#xD;&#xA;$\pi/2&lt;\theta&lt;=\pi$ then $V. N&lt;0$ $\implies$ front-face. And when we consider  $0°&lt;=\theta&lt;=\pi/2$ then $V. N&gt;0$ $\implies$ back-face.&#xD;&#xA;&#xD;&#xA;**Case:1**&#xD;&#xA;Now suppose in this case for front face where V and N are parallel to each then they makes angle 0°.Then we get $V. N&gt;0$ but according to books formula when $V. N&lt;0$ then we will get front face. &#xD;&#xA;&#xD;&#xA;:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Case:2** Again I consider the case for back face where V along with N then they makes angle 180°.Then &#xD;&#xA;we get $V. N&lt;0$ but according to books formula when $V. N&gt;0$ then we will get back face. [![enter image description here][2]][2]&#xD;&#xA;  &#xD;&#xA;My question is where I mistaken to understand the detect the back face and front face for the above cases with formula $V. N &gt;0  or &lt;0?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r0DBF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/kMOMV.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36168" PostHistoryTypeId="1" PostId="12493" RevisionGUID="6123eb1a-d8ac-4d66-b5e5-615ee8fb907f" CreationDate="2022-01-27T20:05:07.910" UserId="17343" Text="Back-face detention" ContentLicense="CC BY-SA 4.0" />
  <row Id="36169" PostHistoryTypeId="3" PostId="12493" RevisionGUID="6123eb1a-d8ac-4d66-b5e5-615ee8fb907f" CreationDate="2022-01-27T20:05:07.910" UserId="17343" Text="|rendering|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36170" PostHistoryTypeId="2" PostId="12494" RevisionGUID="fed27687-9d91-4466-bc57-1b84b2d5faba" CreationDate="2022-01-27T20:32:29.500" UserId="2654" Text="&gt; Now suppose in this case for front face where V and N are parallel to each then they makes angle 0°.&#xD;&#xA;&#xD;&#xA;In your example, V and N are pointing in opposite directions. The angle between them is 180 degrees, so the cosine is -1. Similarly:&#xD;&#xA;&#xD;&#xA;&gt; Again I consider the case for back face where V along with N then they makes angle 180°.&#xD;&#xA;&#xD;&#xA;If V and N are pointing in the same direction, then the angle between them is 0 degrees, so the cosine is 1.&#xD;&#xA;&#xD;&#xA;You have these backwards; that's why you're getting the wrong value." ContentLicense="CC BY-SA 4.0" />
  <row Id="36172" PostHistoryTypeId="52" PostId="12493" RevisionGUID="df5f305e-ec3d-4d5d-8bc8-780ee1f6e1ee" CreationDate="2022-01-28T04:05:59.943" />
  <row Id="36173" PostHistoryTypeId="5" PostId="12493" RevisionGUID="09ce99f5-e756-4ed8-994a-591ee540b6e0" CreationDate="2022-01-28T08:24:24.590" UserId="17343" Comment="added 2 characters in body; added 2 characters in body; added 4 characters in body; added 2 characters in body; added 5 characters in body" Text="Suppose I have one convex polyhedron, I need to detect back face. And $N=(A, B, C)$ is normal vector of polygon surface and vector $V$ in viewing direction. According to books formula and internet content if $V. N&gt;0$ then polygon is back face otherwise front face. &#xD;&#xA;&#xD;&#xA;We know that $V. N=|V|.|N|cos\theta$ from this when we consider &#xD;&#xA;$\pi/2&lt;\theta&lt;=\pi$ then $V. N&lt;0$ $\implies$ front-face. And when we consider  $0°&lt;=\theta&lt;=\pi/2$ then $V. N&gt;0$ $\implies$ back-face.&#xD;&#xA;&#xD;&#xA;**Case:1**&#xD;&#xA;Now suppose in this case for front face where $V$ and $N$ are parallel to each then they makes angle 0°.Then we get $V. N&gt;0$ but according to books formula when $V. N&lt;0$ then we will get front face. &#xD;&#xA;&#xD;&#xA;:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Case:2** Again I consider the case for back face where $V$ along with $N$ then they makes angle 180°.Then &#xD;&#xA;we get $V. N&lt;0$ but according to books formula when $V. N&gt;0$ then we will get back face. [![enter image description here][2]][2]&#xD;&#xA;  &#xD;&#xA;My question is where I mistaken to understand the detect the back face and front face for the above cases with formula &#xD;&#xA;$V. N &gt;0   or   &lt;0?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r0DBF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/kMOMV.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36174" PostHistoryTypeId="2" PostId="12495" RevisionGUID="9166fdeb-add8-452a-980e-fffb2f1a27bf" CreationDate="2022-01-28T10:32:03.540" UserId="17916" Text="The direct answer to your question is yes: you can use glsl to convert a pixel value between different color models such as RGB and CIELAB, although you have to consider how your RGB space matches to XYZ tristimulus values, but that's a bit outside the scope of this question.&#xA;&#xA;Basically, as long as you have a closed function to convert between color models, you can leverage a GPU to do this for you, and you can use GLSL to do so.&#xA;&#xA;Ultimately, whether or not it makes sense to do this with a GPU, and which type of shader stage to use, is up to what you want to do with the conversion.&#xA;&#xA;If you simply want to convert one file from one model to another, you should consider using existing software such as Photoshop or Gimp. If you need to convert many files, these tools have methods for automating the conversion process.&#xA;&#xA;Alternatively you can make a regular program, for example in C# to do transformations as needed. I particularly like using the System.Drawing library for manipulating images in an easy way.&#xA;&#xA;If you want to do the conversion for drawing the image on the screen, then you can definitely leverage the graphics pipeline to help you do this. The most natural place to do this is in the fragment shader, but depending on what you're doing, you may also want to consider doing this in a compute shader. The code will basically be the same, but the code to prepare the pipeline will be different.&#xA;&#xA;Without knowing what is it exactly that you want to do, it's quite difficult to give more concrete advice though." ContentLicense="CC BY-SA 4.0" />
  <row Id="36178" PostHistoryTypeId="50" PostId="12163" RevisionGUID="43aab2de-51e8-44c1-bc7a-02169f8590fb" CreationDate="2022-01-29T10:04:40.443" UserId="-1" />
  <row Id="36179" PostHistoryTypeId="50" PostId="9146" RevisionGUID="54a478d8-72c2-437a-b6cc-502799bc0d52" CreationDate="2022-01-29T20:05:55.590" UserId="-1" />
  <row Id="36188" PostHistoryTypeId="50" PostId="10853" RevisionGUID="792ec0c3-6248-4abd-a828-bb8ec32aee7a" CreationDate="2022-01-30T08:01:20.113" UserId="-1" />
  <row Id="36202" PostHistoryTypeId="50" PostId="10509" RevisionGUID="b775392e-1ac9-4cdd-81d5-2bd798da024a" CreationDate="2022-01-31T05:05:45.550" UserId="-1" />
  <row Id="36203" PostHistoryTypeId="2" PostId="12498" RevisionGUID="7ddbcde2-4613-48d0-971d-4beba6fcba52" CreationDate="2022-01-31T09:55:28.610" UserId="16879" Text="[This source][1] on slide 38 on receiver plane depth bias I can find compute a matrix (Jacobian of screen space uv derivatives) which is used to transform the screen space depth derivatives from screen space to texture space.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;But why does this work? I'm not familiar with the usage of Jacobian matrices and how they relate to coordinate system transformations. Does the basic Jacobian shown in the slide transform from texture space to screen space, or why does it have to be inverse-transposed (I suppose of the former was true it could just be inverted?).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.amd.com/wordpress/media/2012/10/Isidoro-ShadowMapping.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/JNOHd.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36205" PostHistoryTypeId="1" PostId="12498" RevisionGUID="7ddbcde2-4613-48d0-971d-4beba6fcba52" CreationDate="2022-01-31T09:55:28.610" UserId="16879" Text="Receiver plane depth bias - matrix explanation / derivation" ContentLicense="CC BY-SA 4.0" />
  <row Id="36206" PostHistoryTypeId="3" PostId="12498" RevisionGUID="7ddbcde2-4613-48d0-971d-4beba6fcba52" CreationDate="2022-01-31T09:55:28.610" UserId="16879" Text="|transformations|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36207" PostHistoryTypeId="2" PostId="12499" RevisionGUID="76310f61-2d9b-4806-9845-6b06b06e235f" CreationDate="2022-01-31T17:05:46.057" UserId="16224" Text="&gt; When I use the cosine everything gets really dark and the edges of my spheres are almost black. That makes sense because I am almost multiplying by cos(PI/2) = 0. I have read that it suppose to cancel out with something so I have removed it which help. But what does it cancel out with?&#xD;&#xA;&#xD;&#xA;That cosine has a geometrical meaning, keep it, or if you take it off, be sure you have a mathematical reason to do so.&#xD;&#xA;Grazing angles distribute much less of their radiance to the surface, and at an angle of 90°, the received radiance is zero.&#xD;&#xA;&#xD;&#xA;&gt; I am using Lambertian diffuse BRDF which means that the &quot;Fr&quot; part of the equation should be &quot;albedo / PI&quot;. I am also doing uniform hemisphere sampling which gave me a PDF of 1 / PI. Now when I calculate BRDF / PDF I get &quot;2 * albedo&quot;. That does not seem right. This means that the more and more bounces I make the bigger influence the light has which is nonsense. The light should be dimmer from the 3rd bounce than from the 1st bounce. Where did I make a mistake?&#xD;&#xA;&#xD;&#xA;The probability density function $p$, by its definition, must have an integral of 1 on the whole definition set, thus on the half hemisphere. If you do the math, you'll get:&#xD;&#xA;&#xD;&#xA;$\int_\Omega p \, \text{d}\Omega = \int_0^{2\pi} \int_0^{\pi/2} p \, \sin \theta \, \text{d}\theta \, \text{d}\phi = 2\pi \Rightarrow p = \frac{1}{2\pi}$&#xD;&#xA;&#xD;&#xA;Sampling your PDF will give you $\theta = \arccos \xi_1 $, $\phi = 2\pi \xi_2$, where $\xi_1, \xi_2$ are independant random real numbers between 0 and 1. Sampling a PDF is not always easy and is another topic in itself, but for more details you can read this [excerpt from the excellent PBR][1].&#xD;&#xA;&#xD;&#xA;But as you saw it, you can do better : the cosine term in the rendering equation that bothers you from the beginning tells you that you **should** favor the directions that maximize this term. So let's choose a pdf such that&#xD;&#xA;&#xD;&#xA;$p = \alpha \cos \theta_i$&#xD;&#xA;&#xD;&#xA;If you want to know the value of $\alpha$, you have to remember that the integral of the pdf must be equal to one. If you do the math, this will give you $p = \frac{\cos \theta_i}{\pi}$.&#xD;&#xA;&#xD;&#xA;Sampling this new PDF with the method shown in PBR will give you $\theta = \arccos \sqrt{\xi_1}$, $\phi = 2\pi \xi_2$.&#xD;&#xA;&#xD;&#xA;Now, and only now, you can notice that the cosine of the rendering equation simplifies with the one in the PDF. You can then remove them.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations" ContentLicense="CC BY-SA 4.0" />
  <row Id="36209" PostHistoryTypeId="5" PostId="12493" RevisionGUID="05d4fb89-ffcd-473c-b0fe-bab533c5c515" CreationDate="2022-01-31T18:58:19.637" UserId="482" Comment="spelling and hyphenation" Text="Suppose I have one convex polyhedron, I need to detect back face. And $N=(A, B, C)$ is normal vector of polygon surface and vector $V$ in viewing direction. According to books formula and internet content if $V. N&gt;0$ then polygon is back face otherwise front face. &#xD;&#xA;&#xD;&#xA;We know that $V. N=|V|.|N|cos\theta$ from this when we consider &#xD;&#xA;$\pi/2&lt;\theta&lt;=\pi$ then $V. N&lt;0$ $\implies$ front face. And when we consider  $0°&lt;=\theta&lt;=\pi/2$ then $V. N&gt;0$ $\implies$ back face.&#xD;&#xA;&#xD;&#xA;**Case:1**&#xD;&#xA;Now suppose in this case for front face where $V$ and $N$ are parallel to each then they makes angle 0°.Then we get $V. N&gt;0$ but according to books formula when $V. N&lt;0$ then we will get front face. &#xD;&#xA;&#xD;&#xA;:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Case:2** Again I consider the case for back face where $V$ along with $N$ then they makes angle 180°.Then &#xD;&#xA;we get $V. N&lt;0$ but according to books formula when $V. N&gt;0$ then we will get back face. [![enter image description here][2]][2]&#xD;&#xA;  &#xD;&#xA;My question is where I mistaken to understand the detect the back face and front face for the above cases with formula &#xD;&#xA;$V. N &gt;0   or   &lt;0?$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r0DBF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/kMOMV.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36210" PostHistoryTypeId="4" PostId="12493" RevisionGUID="05d4fb89-ffcd-473c-b0fe-bab533c5c515" CreationDate="2022-01-31T18:58:19.637" UserId="482" Comment="spelling and hyphenation" Text="Back face detection" ContentLicense="CC BY-SA 4.0" />
  <row Id="36211" PostHistoryTypeId="2" PostId="12500" RevisionGUID="65896f9b-7109-4be3-b997-d3c03ce0e951" CreationDate="2022-01-31T19:11:29.280" UserId="482" Text="I think the terminology makes it seem more complicated than it is. The &quot;Texture Space Jacobean&quot; Matrix in your slide here is just a Linear Transformation Matrix. &#xD;&#xA;&#xD;&#xA;The transformation you need to apply here is the inverse of the *Texture Space Jacobean*. But because of the properties of a Jacobean, its inverse is exactly the same as its transpose. If I were editing the slide, I would replace the text &quot;(inverse-transpose)&quot; with &quot;inverse (= transposed)&quot;.&#xD;&#xA;&#xD;&#xA;I think the notation &lt;sup&gt;-T&lt;/sup&gt; is wrong. It should be &lt;sup&gt;-1&lt;/sup&gt; or &lt;sup&gt;T&lt;/sup&gt;." ContentLicense="CC BY-SA 4.0" />
  <row Id="36213" PostHistoryTypeId="50" PostId="10537" RevisionGUID="b5c0bcc4-faa9-49b7-91ad-9285bebc2f20" CreationDate="2022-02-01T08:02:55.217" UserId="-1" />
  <row Id="36214" PostHistoryTypeId="2" PostId="12501" RevisionGUID="e232689a-8741-4725-9e77-0eb7ebe68c25" CreationDate="2022-02-01T14:34:58.417" UserId="13273" Text="I am trying to implement the paper: [Real-Time Depth-of-Field Rendering Using Anisotropically Filtered Mipmap Interpolation][1] from Sungkil Lee, Gerard Jounghyun Kim and Seungmoon Choi.&#xD;&#xA;&#xD;&#xA;Everything works fine till I reached chepter 5 (Smoothing forground Boundaries). After I created the DoN texture, on site 6 between (10) and (11) I don't know how to get value of `M` to continue.&#xD;&#xA;&#xD;&#xA;  [1]: http://cg.skku.edu/pub/papers/2009-lee-tvcg-mintdof-cam.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="36216" PostHistoryTypeId="1" PostId="12501" RevisionGUID="e232689a-8741-4725-9e77-0eb7ebe68c25" CreationDate="2022-02-01T14:34:58.417" UserId="13273" Text="Depth of Field algorithm implementation issue" ContentLicense="CC BY-SA 4.0" />
  <row Id="36217" PostHistoryTypeId="3" PostId="12501" RevisionGUID="e232689a-8741-4725-9e77-0eb7ebe68c25" CreationDate="2022-02-01T14:34:58.417" UserId="13273" Text="|depth-of-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36218" PostHistoryTypeId="2" PostId="12502" RevisionGUID="2ac99f47-b375-4265-8bbb-68204d89c0b5" CreationDate="2022-02-01T14:49:35.840" UserId="17930" Text="When trying to obtain high resolution images of geometry files, the only option seems to be to take a screenshot of the software in use (FreeCAD, Salome, Catia, etc...). Although enough in most circumstances, it seems that it is not possible to take a higher-resolution image (e.g. 3840x2160) in a standard FullHD monitor.&#xD;&#xA;&#xD;&#xA;Is there any software or process to obtain very high resolution image (.PNG or .TIFF) of a geometry file in STEP or IGES format?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36220" PostHistoryTypeId="1" PostId="12502" RevisionGUID="2ac99f47-b375-4265-8bbb-68204d89c0b5" CreationDate="2022-02-01T14:49:35.840" UserId="17930" Text="High resolution image of a STEP geometry file" ContentLicense="CC BY-SA 4.0" />
  <row Id="36221" PostHistoryTypeId="3" PostId="12502" RevisionGUID="2ac99f47-b375-4265-8bbb-68204d89c0b5" CreationDate="2022-02-01T14:49:35.840" UserId="17930" Text="|image|cad|capture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36222" PostHistoryTypeId="2" PostId="12503" RevisionGUID="bd422ddf-cbc2-4769-b2b8-271a753a8990" CreationDate="2022-02-01T18:26:38.717" UserId="17931" Text="I've noticed some very obvious color banding on the screen of my Dell Precision 7750 laptop while watching video (same in every video program; VLC, built-in Windows video player, etc.)  Not only does this not happen for the same video on other computers, but also when I plug in a second monitor to the laptop and play the video on there, it looks find on the second monitor.  So it seems like it's something to do with the color profile on the main laptop monitor.  Here's what the banding looks like:&#xD;&#xA;&#xD;&#xA;aaa&#xD;&#xA;&#xD;&#xA;I took a screenshot and pasted it in GIMP to check the actual pixel values.  Zooming in on a particular banding edge as an example, there was a very noticeable difference between pixels of colour `#040404` and `#050505`:&#xD;&#xA;&#xD;&#xA;bbb&#xD;&#xA;&#xD;&#xA;ccc&#xD;&#xA;&#xD;&#xA;I then made a `#060606` pixel and as you can see, it looks almost identical to the `#050505`, so something is causing `#040404` and `#050505` to look quite different when they should be almost indistinguishable, but this doesn't apply to most small changes in pixel colour:&#xD;&#xA;&#xD;&#xA;ddd&#xD;&#xA;&#xD;&#xA;What could be causing this effect on the laptop screen?  A screwed up colour profile?  The system has onboard Intel graphics, but is using the installed nVidia Quadro RTX 3000 graphics card." ContentLicense="CC BY-SA 4.0" />
  <row Id="36224" PostHistoryTypeId="1" PostId="12503" RevisionGUID="bd422ddf-cbc2-4769-b2b8-271a753a8990" CreationDate="2022-02-01T18:26:38.717" UserId="17931" Text="Why does my Dell laptop monitor give this weird color banding?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36225" PostHistoryTypeId="3" PostId="12503" RevisionGUID="bd422ddf-cbc2-4769-b2b8-271a753a8990" CreationDate="2022-02-01T18:26:38.717" UserId="17931" Text="|rendering|color|video|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36226" PostHistoryTypeId="5" PostId="12503" RevisionGUID="d03a334d-efa4-427b-b310-4e823a7b0f19" CreationDate="2022-02-01T18:34:17.530" UserId="17931" Comment="added 285 characters in body" Text="I've noticed some very obvious color banding on the screen of my Dell Precision 7750 laptop while watching video (same in every video program; VLC, built-in Windows video player, etc.)  Not only does this not happen for the same video on other computers, but also when I plug in a second monitor to the laptop and play the video on there, it looks find on the second monitor.  So it seems like it's something to do with the color profile on the main laptop monitor.  Here's what the banding looks like:&#xD;&#xA;&#xD;&#xA;![video banding](https://i.stack.imgur.com/8FXva.jpg)&#xD;&#xA;&#xD;&#xA;I took a screenshot and pasted it in GIMP to check the actual pixel values.  Zooming in on a particular banding edge as an example, there was a very noticeable difference between pixels of colour `#040404` and `#050505`:&#xD;&#xA;&#xD;&#xA;![444](https://i.stack.imgur.com/fW8uP.jpg)&#xD;&#xA;&#xD;&#xA;![555](https://i.stack.imgur.com/kmxVR.jpg)&#xD;&#xA;&#xD;&#xA;I then made a `#060606` pixel and as you can see, it looks almost identical to the `#050505`, so something is causing `#040404` and `#050505` to look quite different when they should be almost indistinguishable, but this doesn't apply to most small changes in pixel colour:&#xD;&#xA;&#xD;&#xA;![666](https://i.stack.imgur.com/63eHi.jpg)&#xD;&#xA;&#xD;&#xA;What could be causing this effect on the laptop screen?  A screwed up colour profile?  The system has onboard Intel graphics, but is using the installed nVidia Quadro RTX 3000 graphics card." ContentLicense="CC BY-SA 4.0" />
  <row Id="36227" PostHistoryTypeId="34" PostId="12470" RevisionGUID="7603d035-2375-4e78-bc5c-dc82a7b7969c" CreationDate="2022-02-02T01:02:25.210" UserId="-1" Comment="74" />
  <row Id="36228" PostHistoryTypeId="50" PostId="10365" RevisionGUID="118ed4f0-e206-4c9d-b34a-5f2a77e1781a" CreationDate="2022-02-02T09:00:10.083" UserId="-1" />
  <row Id="36229" PostHistoryTypeId="5" PostId="12501" RevisionGUID="87ab7816-56c7-4fee-a704-cd7060e086dd" CreationDate="2022-02-02T14:13:11.767" UserId="13273" Comment="added 158 characters in body" Text="I am trying to implement the paper: [Real-Time Depth-of-Field Rendering Using Anisotropically Filtered Mipmap Interpolation][1] from Sungkil Lee, Gerard Jounghyun Kim and Seungmoon Choi.&#xD;&#xA;&#xD;&#xA;Everything works fine till I reached chepter 5 (Smoothing forground Boundaries). After I created the DoN texture, on site 6 between (10) and (11) I don't know how to get value of `M` to continue. My texture has 1024x1024 pixels. The highest mipmap level I have is 10 (1x1 pixel). I don't think in the paper they talk about the maximum mipmap level (10).&#xD;&#xA;&#xD;&#xA;  [1]: http://cg.skku.edu/pub/papers/2009-lee-tvcg-mintdof-cam.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="36230" PostHistoryTypeId="2" PostId="12504" RevisionGUID="ad84352d-a0b2-45e0-b8b4-0b9940fe4470" CreationDate="2022-02-02T16:12:07.003" UserId="482" Text="&gt; If a DoN value is taken and magnified (using&#xD;&#xA;the circular filtering) at the highest mipmap level, M ,&#xD;&#xA;this value (i.e., ρ(M ); see Fig. 8c) can be used for finding&#xD;&#xA;the foreground objects and their boundaries that may&#xD;&#xA;occlude non-foreground areas.&#xD;&#xA;&#xD;&#xA;I think this means that M is indeed the highest mipmap level." ContentLicense="CC BY-SA 4.0" />
  <row Id="36232" PostHistoryTypeId="50" PostId="9829" RevisionGUID="7753d443-54fe-4ef8-a330-cf77c3e98adc" CreationDate="2022-02-02T18:05:15.523" UserId="-1" />
  <row Id="36233" PostHistoryTypeId="2" PostId="12505" RevisionGUID="2bc97e7e-b9f6-4c73-848b-fa8e68fce906" CreationDate="2022-02-02T19:14:36.690" UserId="7952" Text="This was just going to be a comment but it go to long...&#xD;&#xA;&#xD;&#xA;Is this being streamed? If the connection speed is to low then the a lower quality video will be streamed with most services.  Also, check the &quot;video&quot; settings on the NVidia card settings page. There should be an entire tab on video settings, make sure the best quality and true color settings are selected. Also make sure the &quot;use hardware decoding&quot; options are turned on. It is also possible to &quot;override&quot; the software settings. Lastly check your windows settings just to make sure full color is enabled and that the best video quality settings are turned on. Most of these settings can be accessed just by right clicking on the desktop and choosing &quot;Nvidia control panel&quot;, and &quot;display settings&quot;...usually.&#xD;&#xA;&#xD;&#xA;Under the windows &quot;video playback&quot; page there is a video which can be played, set that to full screen to see if the banding exists on it, if not then it is mostly likely the source video quality/download speed issue. If it has bands then it is likely a setting in windows or the video driver.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36235" PostHistoryTypeId="2" PostId="12506" RevisionGUID="c49ca2d4-7978-4de9-9c9c-56c3133fc079" CreationDate="2022-02-02T21:30:58.777" UserId="17935" Text="While calibrating a **system that includes the automatic detection of planes from the SLAM output**, the **information about planes** provided is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1 -** (x,y) pairs representing the plane's convex hull&#xD;&#xA;&#xD;&#xA;**2-** the &quot;pose&quot;, defined as a 3D translation and a quaternion.&#xD;&#xA;&#xD;&#xA;**3-** the &quot;extents&quot;, two real valued numbers.&#xD;&#xA;&#xD;&#xA;The question is how to recover the 3D position of this plane from this data. &#xD;&#xA;&#xD;&#xA;Based on observed data, the convex hull appears to be scaled from -1 to 1 in both dimensions, so my best guess would be that the &quot;extents&quot; are each dimension's scale. I haven't found the word &quot;extent&quot; particularly tied to the concept of spatial scale in Computer Graphics, so any help would be appreciated.&#xD;&#xA;&#xD;&#xA;The proposed algorithm for reconstruction is:&#xD;&#xA;&#xD;&#xA;- Build the interior of the convex hull in a 2-dim plane (e.g. $(x,y,0)$) bounded by $[-1,1]^3$&#xD;&#xA;&#xD;&#xA;- Scale it by $(extent_0, extent_1,1)$&#xD;&#xA;&#xD;&#xA;- Rotate it according to the quaternion, and translate it according to the 3D vec." ContentLicense="CC BY-SA 4.0" />
  <row Id="36237" PostHistoryTypeId="1" PostId="12506" RevisionGUID="c49ca2d4-7978-4de9-9c9c-56c3133fc079" CreationDate="2022-02-02T21:30:58.777" UserId="17935" Text="Plane detector: information provided is convex hull and pose (transl + rot). Are the &quot;extents&quot; the scaling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36238" PostHistoryTypeId="3" PostId="12506" RevisionGUID="c49ca2d4-7978-4de9-9c9c-56c3133fc079" CreationDate="2022-02-02T21:30:58.777" UserId="17935" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36239" PostHistoryTypeId="50" PostId="10341" RevisionGUID="ff5d906c-0f63-4958-bf75-a6dbb5eb84b4" CreationDate="2022-02-03T10:07:05.683" UserId="-1" />
  <row Id="36240" PostHistoryTypeId="2" PostId="12507" RevisionGUID="29e178d7-8871-4d67-b12b-8af4899c1f63" CreationDate="2022-02-03T22:48:34.117" UserId="17942" Text="I have spent the longest amount of time just taking the terminology for granted &amp; have only just recently started studying or at least trying to understand the difference between radiometric and photometric units.&#xD;&#xA;&#xD;&#xA;It has recently dawned on me that most PBR implementations (in realtime rendering and video game engines such as Frostbite, UE4, Unity or even Filament) use the term **diffuse irradiance** *(radiometric unit)* yet they use photometric units for the rest of their lighting pipeline, analytic lights &amp; output **luminance** *(photometric unit)* to their render target / output surface.&#xD;&#xA;&#xD;&#xA;Is the use of the term **diffuse irradiance** actually correct or am I right in thinking the correct term should really be **diffuse illuminance**, since the term is usually generated from a cubemap rendered through the same lighting pipeline and expressed in luminance, or a HDR image?&#xD;&#xA;&#xD;&#xA;Thanks in advance,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36242" PostHistoryTypeId="1" PostId="12507" RevisionGUID="29e178d7-8871-4d67-b12b-8af4899c1f63" CreationDate="2022-02-03T22:48:34.117" UserId="17942" Text="Diffuse irradiance map : confusion about photometric vs radiometric units" ContentLicense="CC BY-SA 4.0" />
  <row Id="36243" PostHistoryTypeId="3" PostId="12507" RevisionGUID="29e178d7-8871-4d67-b12b-8af4899c1f63" CreationDate="2022-02-03T22:48:34.117" UserId="17942" Text="|physically-based|photometric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36244" PostHistoryTypeId="50" PostId="12143" RevisionGUID="52360362-7661-4646-b728-6211197158c6" CreationDate="2022-02-04T12:04:20.383" UserId="-1" />
  <row Id="36254" PostHistoryTypeId="5" PostId="12500" RevisionGUID="2be47267-451b-4763-b1c7-65445f6d8d3d" CreationDate="2022-02-05T23:38:08.530" UserId="482" Comment="remove wrong info" Text="I think the terminology makes it seem more complicated than it is. The &quot;Texture Space Jacobean&quot; Matrix in your slide here is just a Linear Transformation Matrix. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36255" PostHistoryTypeId="2" PostId="12509" RevisionGUID="b483a19e-d2c2-4c4c-a78d-b2290a53c5ce" CreationDate="2022-02-06T04:29:54.057" UserId="482" Text="*Extents* is a somewhat archaic term for geometric length, or more properly a set of boundaries that define the space between them. I also haven't seen it used in Computer Graphics literature, but it shows up in Geometry.&#xD;&#xA;&#xD;&#xA;Your plan seems sound, but take care of doing the rotation and translation in the correct order because they are not commutative. It's not clear to me here what the correct order ought to be, but there will be a right and wrong way." ContentLicense="CC BY-SA 4.0" />
  <row Id="36262" PostHistoryTypeId="50" PostId="12179" RevisionGUID="6227264f-62c8-4136-84e0-d2c7ce150450" CreationDate="2022-02-06T18:03:45.320" UserId="-1" />
  <row Id="36263" PostHistoryTypeId="50" PostId="10879" RevisionGUID="3c3b1aea-884e-4d47-b0c4-6ed78871cd25" CreationDate="2022-02-06T19:07:45.823" UserId="-1" />
  <row Id="36264" PostHistoryTypeId="2" PostId="12511" RevisionGUID="9511c1a6-d2ec-41e8-8431-6e357f9a4940" CreationDate="2022-02-07T09:05:50.853" UserId="15688" Text="If you want to draw pixels you can create a 2d texture resource and draw this texture to a fullscreen quad/triangle. After you set this up you can update the texture's pixels on the host site, update the texture and draw.&#xD;&#xA;If you specifically after this drawing method you can use Direct2D for this (D2D is a wrapper on D3D, so you don't need hundreds of lines of code to set this up)." ContentLicense="CC BY-SA 4.0" />
  <row Id="36278" PostHistoryTypeId="2" PostId="12515" RevisionGUID="4c514cb9-8a84-4ae9-bb57-f75c5f6ef8b3" CreationDate="2022-02-08T09:39:21.583" UserId="17962" Text="Your second shader reads 10x10 pixels of data and writes 8x8 (which is correct), however, it handles corner and edge cases with lots of &quot;if&quot;s. This leads to divergence and kills performance.&#xD;&#xA;&#xD;&#xA;One way to avoid divergence is that, a workgroup reads NxN (1 thread to 1 pixel), and only writes (N-2)x(N-2) pixels in the middle, discard corner and edge cases. Dispatch with N-2 stride.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36283" PostHistoryTypeId="2" PostId="12516" RevisionGUID="f3ca24f1-fa44-42a3-9cf4-77a7b0947e06" CreationDate="2022-02-08T10:39:12.190" UserId="17963" Text="I want to generate a vector field animation similar to what is shown [at 55s in this video][1], it looks a bit like wind in a grass/wheat field, I would like to know what kind of equation / noise generator is used to create this kind of pattern ?&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=rB83DpBJQsE&amp;t=55s" ContentLicense="CC BY-SA 4.0" />
  <row Id="36285" PostHistoryTypeId="1" PostId="12516" RevisionGUID="f3ca24f1-fa44-42a3-9cf4-77a7b0947e06" CreationDate="2022-02-08T10:39:12.190" UserId="17963" Text="How can I generate such vector field animation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36286" PostHistoryTypeId="3" PostId="12516" RevisionGUID="f3ca24f1-fa44-42a3-9cf4-77a7b0947e06" CreationDate="2022-02-08T10:39:12.190" UserId="17963" Text="|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36288" PostHistoryTypeId="4" PostId="12502" RevisionGUID="baa7dd48-d7a6-476e-b507-8c02eb274a9a" CreationDate="2022-02-08T16:50:43.773" UserId="17930" Comment="edited title" Text="Software to obtain high resolution images of a STEP geometry file" ContentLicense="CC BY-SA 4.0" />
  <row Id="36289" PostHistoryTypeId="5" PostId="12502" RevisionGUID="baa7dd48-d7a6-476e-b507-8c02eb274a9a" CreationDate="2022-02-08T16:50:43.773" UserId="17930" Comment="edited title" Text="When trying to obtain high resolution images of geometry files, the only option seems to take a screenshot of the software in use (Salome, Catia, etc...). Although enough in most circumstances, it seems that it is not possible to take a higher-resolution image (e.g. 3840x2160) in a standard FullHD monitor.&#xD;&#xA;&#xD;&#xA;Is there any software or process to obtain very high resolution image (.PNG or .TIFF) of a geometry file in STEP or IGES format?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36290" PostHistoryTypeId="2" PostId="12517" RevisionGUID="b895e933-b9f0-468b-88f4-4ea39241a12a" CreationDate="2022-02-09T11:28:28.903" UserId="17969" Text="I have implemented [Preetham, Shirley, and Smits’s daylight model](https://courses.cs.duke.edu/cps124/spring08/assign/07_papers/p91-preetham.pdf) using [Aubrey Jaffer’s Scheme implementation](https://github.com/taktoa/slib/blob/master/daylight.scm) as a reference and confirmed that my implementation produces the same results in the xyY coordinate space for the same input on all my test cases as Jaffer’s.&#xD;&#xA;&#xD;&#xA;However, when I try to convert this output to sRGB using the [standard formulae](https://www.w3.org/Graphics/Color/sRGB.html), almost all inputs except for those around sunrise and sunset map to colours ‘darker than black’ (all coordinates less than 0) at night, or ‘lighter than white’ (all coordinates greater than 1.0/255) during the day.&#xD;&#xA;&#xD;&#xA;An example: for solar day 38 (declination -15.7117) at solar hour 14 at latitude 52.52 (θ&lt;sub&gt;s&lt;/sub&gt; = 72.9996°, φ&lt;sub&gt;s&lt;/sub&gt; = 44.0935°) with turbidity 6, Jaffer’s implementation and mine both give xyY values for θ = 30, φ = 0: (0.3576953919457298, 0.3065955987210767, 5.907977352059564). This is the procedure `clear-sky-color-xyY` in Jaffer’s Scheme implementation. However, using Jaffer’s [`xyY-&gt;XYZ` and `CIEXYZ-&gt;sRGB` procedures](https://github.com/taktoa/slib/blob/master/colorspc.scm) (which likewise apply the same formulae as my code) on this result yields sRGB octets 255, 255, and 255.&#xD;&#xA;&#xD;&#xA;For solar hours around 7 and 17 (sunset and sunrise), the results appear somewhat reasonable, but broad daylight and dark night are both too light and too dark.&#xD;&#xA;&#xD;&#xA;What corrections are necessary to make the model practical for rendering in sRGB and similar colour spaces?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36292" PostHistoryTypeId="1" PostId="12517" RevisionGUID="b895e933-b9f0-468b-88f4-4ea39241a12a" CreationDate="2022-02-09T11:28:28.903" UserId="17969" Text="Using the Preetham/Shirley/Smits daylight model to get practical (s)RGB values" ContentLicense="CC BY-SA 4.0" />
  <row Id="36293" PostHistoryTypeId="3" PostId="12517" RevisionGUID="b895e933-b9f0-468b-88f4-4ea39241a12a" CreationDate="2022-02-09T11:28:28.903" UserId="17969" Text="|lighting|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36299" PostHistoryTypeId="2" PostId="12519" RevisionGUID="405eb129-ebad-44b9-81c1-f573ec44d9a0" CreationDate="2022-02-10T08:10:53.783" UserId="13273" Text="I try to render extreme large landscapes, which are deformed by height-maps. Each area has several level of detail height-maps. Other textures are structured like the height-maps as well, so that all textures together are way more than 4GB. I wrote a texture class, which loads textures which are needed to GPU and remove them again, when they are not used several frames. With this technique the GPU Memory is not full. &#xD;&#xA;&#xD;&#xA;Now each landscape patch is rendered by its own draw-call, where the correct texture is loaded first.&#xD;&#xA;But each patch has the same geometry, so I thought, that an instanced rendering would push my FPS due to not having so many draw calls each frame (GPU activity is at around 20% by 10 FPS).&#xD;&#xA;To do so, I need to load a lot of textures to my shader but `GL_TEXTUREi` is limited to 32.&#xD;&#xA;&#xD;&#xA;My idea is to use texture 2D arrays, so I can hold several textures in one `GL_TEXTUREi` slot. This also simplifies my shader code...&#xD;&#xA;&#xD;&#xA;Now I can see two solutions,&#xD;&#xA;&#xD;&#xA;first: store neighboring patches (patch clusters) to one texture 2D array. I would not like to do so, because a patch holds several textures, and only the needed textures should be loaded (most of the time I don't need the neighboring textures). This solution slows down my program due to loading high amounts of textures from CPU to GPU. It also fills my GPU memory without any need.&#xD;&#xA;&#xD;&#xA;second: On the fly combining several textures to one texture 2D array every few frames. So loading the textures is working fine, the only thing I need to do would be to combine them to an array.&#xD;&#xA;&#xD;&#xA;So the big question:&#xD;&#xA;Is it possible to combine textures (same format, same amount of channels, same resolution ...) to an array, without copying the pixels? Like having a buffer holding the texture-IDs to define an array. Is this possible? Or is there something similar I can use?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36301" PostHistoryTypeId="1" PostId="12519" RevisionGUID="405eb129-ebad-44b9-81c1-f573ec44d9a0" CreationDate="2022-02-10T08:10:53.783" UserId="13273" Text="OpenGL: storing several textures to texture2dArray and exchange them continuesly" ContentLicense="CC BY-SA 4.0" />
  <row Id="36302" PostHistoryTypeId="3" PostId="12519" RevisionGUID="405eb129-ebad-44b9-81c1-f573ec44d9a0" CreationDate="2022-02-10T08:10:53.783" UserId="13273" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36315" PostHistoryTypeId="2" PostId="12523" RevisionGUID="6df8afd6-4865-4ead-99d0-eda7c29e30d6" CreationDate="2022-02-10T16:47:29.033" UserId="17978" Text="I am working on a 3D packing algorithm (MIT-licensed). The box and the cuboids it contains are displayed as a 2D projection. The order of drawing the cuboids (now represented as polygons) is important: a cuboid placed at the back of the box must not be drawn after the cuboids in the front row. I am currently using order by(cuboid.X + cuboid.Y + cuboid.Z) and it works around 99% of the time, but not always. Some aberrations do ocurr, as depicted below. I have tried multiplying the coordinates, and order by X then by Y then by z, and other combinations. Adding the coordinates is the one that gave the best result. POV-ordering has been suggested, but it won't work, as illustrated by the second diagram.  Can someone enlighten me?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aGyXA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DoNuu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36317" PostHistoryTypeId="1" PostId="12523" RevisionGUID="6df8afd6-4865-4ead-99d0-eda7c29e30d6" CreationDate="2022-02-10T16:47:29.033" UserId="17978" Text="When fitting 3d cuboids into a box, how to find the order of drawing (in a 2D projection) so that the cuboids don't appear to overlap?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36318" PostHistoryTypeId="3" PostId="12523" RevisionGUID="6df8afd6-4865-4ead-99d0-eda7c29e30d6" CreationDate="2022-02-10T16:47:29.033" UserId="17978" Text="|geometry|projections|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36319" PostHistoryTypeId="2" PostId="12524" RevisionGUID="558b17dc-d4cd-4673-83ba-cd466766e298" CreationDate="2022-02-10T17:39:10.660" UserId="2654" Text="Let's get our orientation straight first. When I speak of a direction, I mean the direction relative to our viewpoint. So the &quot;front&quot; face of a cuboid is the face nearest the camera; &quot;back&quot; means the face pointing away from the camera. The &quot;left&quot; face of a cuboid is the face pointing to the left from the camera's view.&#xD;&#xA;&#xD;&#xA;A cuboid X is in front of cuboid Y if one of the following is true:&#xD;&#xA;&#xD;&#xA;* The back face of X is in front of the front face of Y&#xD;&#xA;* The left face of X is to the right of the right face of Y.&#xD;&#xA;&#xD;&#xA;If either of these is true, then Y should be drawn before X. This is how you build your sort order. If one of the above is true, then Y should be &quot;less than&quot; X and thus come earlier in the sort." ContentLicense="CC BY-SA 4.0" />
  <row Id="36321" PostHistoryTypeId="5" PostId="12524" RevisionGUID="2bde1d04-d52a-49f4-9e40-9f7864d4430d" CreationDate="2022-02-10T17:51:53.173" UserId="2654" Comment="added 209 characters in body" Text="Let's get our orientation straight first. When I speak of a direction, I mean the direction relative to our viewpoint. So the &quot;front&quot; face of a cuboid is the face nearest the camera; &quot;back&quot; means the face pointing away from the camera. The &quot;left&quot; face of a cuboid is the face pointing to the left from the camera's view.&#xD;&#xA;&#xD;&#xA;A cuboid X is in front of cuboid Y if one of the following is true:&#xD;&#xA;&#xD;&#xA;* The back face of X is in front of the front face of Y&#xD;&#xA;* The left face of X is to the right of the right face of Y.&#xD;&#xA;&#xD;&#xA;If either of these is true, then Y should be drawn before X. This is how you build your sort order. If one of the above is true, then Y should be &quot;less than&quot; X and thus come earlier in the sort.&#xD;&#xA;&#xD;&#xA;Note that this algorithm assumes exact math is used to compute the faces of the cuboids for comparison purposes. If you're using floating-point math, you may encounter precision issues that cause problems." ContentLicense="CC BY-SA 4.0" />
  <row Id="36326" PostHistoryTypeId="2" PostId="12526" RevisionGUID="c11fb515-48a7-4b04-b98b-2f4729ca950b" CreationDate="2022-02-11T00:40:09.520" UserId="17980" Text="# Introduction #&#xD;&#xA;&#xD;&#xA;I am building an application in which given a surface and a pair of points on it, an analytic expression of some geodesic arc (preferably the one with the shortest length), between them is needed. Furthermore, this parametrized curve, needs to have minimal geodesic curvature.&#xD;&#xA;&#xD;&#xA;I have been struggling to find a tool/ algorithm that does this. In this forum, I found [this](https://computergraphics.stackexchange.com/questions/9964/finding-geodesics-on-a-mesh) question, however I was not able to extract the information I need from it.&#xD;&#xA;&#xD;&#xA;**Is there a suggested tool that specializes in minimizing the geodesic curvature of the generated approximation?**&#xD;&#xA;&#xD;&#xA;I am looking for geodesic curvature less than 10^-8, ideally on any given NURBS representation of a smooth surface.&#xD;&#xA;&#xD;&#xA;# What I have tried so far: #&#xD;&#xA;&#xD;&#xA;- The “geodesic” element in Grasshopper. This produces a geodesic curve with around roughly 10^-1 geodesic curvature. (reference surface is a cone)&#xD;&#xA;- The “shortpath” algorithm implemented in Grasshopper. This produces a geodesic curve with geodesic curvature roughly of the order 10^-3 to 10^-5. (reference surface is a cone)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36328" PostHistoryTypeId="1" PostId="12526" RevisionGUID="c11fb515-48a7-4b04-b98b-2f4729ca950b" CreationDate="2022-02-11T00:40:09.520" UserId="17980" Text="Geodesic approximation algorithms for minimal geodesic curvature" ContentLicense="CC BY-SA 4.0" />
  <row Id="36329" PostHistoryTypeId="3" PostId="12526" RevisionGUID="c11fb515-48a7-4b04-b98b-2f4729ca950b" CreationDate="2022-02-11T00:40:09.520" UserId="17980" Text="|computational-geometry|mesh|geometry|nurbs|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36330" PostHistoryTypeId="52" PostId="12523" RevisionGUID="bce176f5-2f8a-4ddb-ba19-1182bae54bf4" CreationDate="2022-02-11T00:50:31.127" />
  <row Id="36331" PostHistoryTypeId="2" PostId="12527" RevisionGUID="7f08a557-f0cf-4481-9066-1c3b6da7e59a" CreationDate="2022-02-11T12:51:02.693" UserId="13273" Text="I am using the tessellation shader stage to increase the density of triangles close to camera.&#xD;&#xA;Thereby when the camera is too close to a triangle, so that the maximum tessellation is not high enough, it should store the tessellated parts to the transform feedback buffer. Then, in the next render pass, these tessellated parts should be tessellated again to ensure a good triangle to pixel ratio.&#xD;&#xA;&#xD;&#xA;To achieve that, the idea is to only render the well tessellated triangles, and only store the &quot;not enough tessellated&quot; triangles to the transform feedback buffer AND NOT render them.&#xD;&#xA;&#xD;&#xA;As far as I understood, this behavior is not possible, because all vertices which pass the final Vertex Processing shader stage will be stored to the feedback buffer.&#xD;&#xA;&#xD;&#xA;So first: Is there a way to enable / disable the transform feedback writing inside GLSL? &#xD;&#xA;&#xD;&#xA;second: And also the other way around: stop rendering but writing to the buffer?&#xD;&#xA;&#xD;&#xA;for the last case (stop rendering but writing) the fragment shader could discard these triangles... A better way would be to stop rasterize them... (performance)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36333" PostHistoryTypeId="1" PostId="12527" RevisionGUID="7f08a557-f0cf-4481-9066-1c3b6da7e59a" CreationDate="2022-02-11T12:51:02.693" UserId="13273" Text="enable / disable transform feedback within glsl for specific primitives" ContentLicense="CC BY-SA 4.0" />
  <row Id="36334" PostHistoryTypeId="3" PostId="12527" RevisionGUID="7f08a557-f0cf-4481-9066-1c3b6da7e59a" CreationDate="2022-02-11T12:51:02.693" UserId="13273" Text="|opengl|glsl|transform-feedback|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36335" PostHistoryTypeId="2" PostId="12528" RevisionGUID="74ff1047-a2f6-4eb8-984d-24c44138be07" CreationDate="2022-02-11T13:21:43.277" UserId="8758" Text="I have come across Signed Distance Field usage in Computer Graphics in construction of vector shapes, glyphs and 3D surfaces. However I can not find much of the background mathematical theory as to why it works, under what assumptions it can reconstruct the vectors at any resolution. Can someone point me to the right resources to understand the topic better?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36337" PostHistoryTypeId="1" PostId="12528" RevisionGUID="74ff1047-a2f6-4eb8-984d-24c44138be07" CreationDate="2022-02-11T13:21:43.277" UserId="8758" Text="Mathematical foundations of Signed Distance Fields in computer graphics" ContentLicense="CC BY-SA 4.0" />
  <row Id="36338" PostHistoryTypeId="3" PostId="12528" RevisionGUID="74ff1047-a2f6-4eb8-984d-24c44138be07" CreationDate="2022-02-11T13:21:43.277" UserId="8758" Text="|opengl|vectors|signed-distance-field|font-rendering|bsdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36339" PostHistoryTypeId="2" PostId="12529" RevisionGUID="a348d978-1532-4e5d-92de-5bb381354d86" CreationDate="2022-02-11T17:07:05.860" UserId="2654" Text="What you want isn't really doable. While OpenGL 4.x allows GS's to [output to multiple streams of primitives][1] (and to collect them in separate feedback buffers), multi-stream output is restricted to point primitive generation. So you couldn't really render *triangles* with them later (well, you could, but it would require a full GPU/CPU sync to read the number of primitives written so that you can divide it by 3 and render triangles).&#xD;&#xA;&#xD;&#xA;That having been said, this does not seem like a good idea from a performance perspective anyway. Implementations of tessellation are required to offer a minimum of 64 tessellation levels. In the triangle abstract primitive, using 64 for each tessellation level would generate thousands of triangles for that triangle. If that is insufficient tessellation... it's probably best to live with it.&#xD;&#xA;&#xD;&#xA;The cost of doing a feedback operation of so many triangles back into the tessellation system would be exceedingly expensive. Especially considering that you need to communicate which triangles that need more tessellation border triangles that don't, so that you can provide the correct tessellation levels to [ensure connectivity][2].&#xD;&#xA;&#xD;&#xA;If you truly need REYES-levels of tessellation (where you ensure each triangle takes up a specific pixel size), you may need a compute shader or more likely just use the CPU.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Output_streams&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Tessellation#Patch_interface_and_continuity" ContentLicense="CC BY-SA 4.0" />
  <row Id="36349" PostHistoryTypeId="2" PostId="12531" RevisionGUID="285b9dd3-f055-4b67-90fa-5efd7c9a21dd" CreationDate="2022-02-12T05:21:00.983" UserId="445" Text="Consider these facts:&#xD;&#xA;&#xD;&#xA;* Monitors and TVs cannot reproduce the full brightness of the sun, or even many other light sources.&#xD;&#xA;* Both eyes and cameras react to the overall brightness they perceive (“adaptation” in the first case, and “automatic exposure” in the second) to capture an image which is in a _usable range_.&#xD;&#xA;&#xD;&#xA;Thus, _at least one_, and often several, of the steps in the path from physical reality (or simulation thereof) to what we perceive in our brains, largely discard the absolute intensity of light in favor of preserving _differences between parts of the scene._ Most color and image data on computers represents [relative luminance](https://en.wikipedia.org/wiki/Relative_luminance), not absolute.&#xD;&#xA;&#xD;&#xA;You're attempting to skip that step, and it's not working, because the practice of storing 8 bits per color component (as most image file formats typically do) rests on the premise that the image represents a “reasonable” range of luminance. (High-dynamic-range image formats store more bits per component.)&#xD;&#xA;&#xD;&#xA;What you can do instead:&#xD;&#xA;&#xD;&#xA;1. Scale your pixel values (“set the exposure”) differently for day and night. You can do this arbitrarily as an artistic choice, or you can render your scene, make a histogram of the pixels' luminance, and then choose a scale value which ensures that no more than some chosen fraction of the pixels are “overexposed” (greater than 255 after scaling).&#xD;&#xA;2. Use a HDR output format.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I also notice that you mention pixels that are “blacker than black”. That shouldn't happen in a realistic model, since there's no such thing as negative light. This might mean that small floating-point rounding errors produced numbers slightly less than zero (harmless), or that the color-space conversion math produced a slightly [impossible color](https://en.wikipedia.org/wiki/Impossible_color#Imaginary_colors_in_color_spaces), or that you have some other more significant arithmetic error." ContentLicense="CC BY-SA 4.0" />
  <row Id="36351" PostHistoryTypeId="2" PostId="12532" RevisionGUID="0fb0088e-211b-4a85-bfe6-599f957089ed" CreationDate="2022-02-12T12:59:27.883" UserId="17989" Text="The title says it all.  Blended image or video contains multiple image or video blended on top of each other. I am looking for any software or tools that can separate the original images or videos. &#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="36353" PostHistoryTypeId="1" PostId="12532" RevisionGUID="0fb0088e-211b-4a85-bfe6-599f957089ed" CreationDate="2022-02-12T12:59:27.883" UserId="17989" Text="Is it possible to separate or split original images (or videos) from a blend image (or video)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36354" PostHistoryTypeId="3" PostId="12532" RevisionGUID="0fb0088e-211b-4a85-bfe6-599f957089ed" CreationDate="2022-02-12T12:59:27.883" UserId="17989" Text="|transformations|blending|fourier-transform|blender|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36355" PostHistoryTypeId="50" PostId="12457" RevisionGUID="59ac8e99-e344-4d1c-a052-3a815e99cd74" CreationDate="2022-02-12T16:03:25.327" UserId="-1" />
  <row Id="36358" PostHistoryTypeId="50" PostId="12158" RevisionGUID="37b8325f-89bc-4631-9556-2e2483d83c05" CreationDate="2022-02-13T10:03:55.413" UserId="-1" />
  <row Id="36359" PostHistoryTypeId="2" PostId="12534" RevisionGUID="d435a44e-d3c0-4739-971f-c8b38ec6e6c1" CreationDate="2022-02-14T06:39:52.257" UserId="17998" Text="This isn't a dumb question.  This is a much more important question than most people realize.&#xD;&#xA;&#xD;&#xA;Here's the worst case scenario for tessellating a quad:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;No sane artist will ever make this for static geometry, but no sane animator will check every frame of every animation to make sure that we never get this. We have a degenerate quad, with three collinear vertices, and it's being triangulated such that we have a zero area face.  Note that this is shortest diagonal triangulation; shortest diagonal is no proof against this.&#xD;&#xA;&#xD;&#xA;If we put some normals on there, and treat this as smooth shaded, we'll see that the central vert's normal contributes reasonably to the quads on the left, but not at all to the quad on the right.  This will cause a discontinuity in normals:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The best way to prevent this bad situation is to triangulate to minimize the difference in area between triangles.  Triangulation in this way will also give us symmetrical triangulation on symmetrical portions of our mesh, which is also a desirable trait.&#xD;&#xA;&#xD;&#xA;For animated meshes, one might be tempted to do this dynamically, but that would be a mistake.  Flipping triangulation will change the interpolation of vertex data across the quad:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;All I'm doing here is flipping triangulation.  This is shown with mildly distorted UV, which is an optimistic expectation, but we'll see the same swimming with normals and vertex color, and with data derived from interpolated vertex data, like UV tangents.  Instantaneous change like this-- pop-- is one of the most noticeable kinds of artifacts in animation.&#xD;&#xA;&#xD;&#xA;So we don't want to determine triangulation from a deformed state.  To have stably interpolated vertex data, we need to have a consistent triangulation of the mesh.  If our framework allows, we can mark vertices appropriate for triangulation in the pre-deformed state.  If it doesn't, it's better to use something like vertex order, which is stable through deformations, than it is to risk swimming from dynamic triangulation.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4J1TL.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/0R5p9.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/mzKly.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="36365" PostHistoryTypeId="5" PostId="12534" RevisionGUID="981e78a6-bee1-4716-b72e-6b9855f4cb1c" CreationDate="2022-02-14T07:08:15.877" UserId="17998" Comment="added 394 characters in body" Text="This isn't a dumb question.  This is a much more important question than most people realize.&#xD;&#xA;&#xD;&#xA;Here's the worst case scenario for triangulating a quad:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;No sane artist will ever make this for static geometry, but no sane animator will check every frame of every animation to make sure that we never get this. We have a degenerate quad, with three collinear vertices, and it's being triangulated such that we have a zero area face.  Note that this is shortest diagonal triangulation; shortest diagonal is no proof against this, and neither is longest diagonal.&#xD;&#xA;&#xD;&#xA;If we put some normals on there, and treat this as smooth shaded, we'll see that the central vert's normal contributes reasonably to the quads on the left, but not at all to the quad on the right.  This will cause a discontinuity in normals:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is not some magical thing that only happens at perfect degeneracy.  As our quad is divided into triangles of increasingly different areas, our vertex data will be divided increasingly unevenly across the quad.  That may mean pinched normals, it may mean unsmooth vertex color-- in either case, the triangulation will be increasingly apparent visually.&#xD;&#xA;&#xD;&#xA;The best way to prevent this bad situation is to triangulate to minimize the difference in area between triangles.  Triangulation in this way will also give us symmetrical triangulation on symmetrical portions of our mesh, which is also a desirable trait.&#xD;&#xA;&#xD;&#xA;For animated meshes, one might be tempted to do this dynamically, but that would be a mistake.  Flipping triangulation will change the interpolation of vertex data across the quad:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;All I'm doing here is flipping triangulation.  This is shown with mildly distorted UV, which is an optimistic expectation, but we'll see the same swimming with normals and vertex color, and with data derived from interpolated vertex data, like UV tangents.  Instantaneous change like this-- pop-- is one of the most noticeable kinds of artifacts in animation.&#xD;&#xA;&#xD;&#xA;So we don't want to determine triangulation from a deformed state.  To have stably interpolated vertex data, we need to have a consistent triangulation of the mesh.  If our framework allows, we can mark vertices appropriate for triangulation in the pre-deformed state.  If it doesn't, it's better to use something like vertex order, which is stable through deformations, than it is to risk swimming from dynamic triangulation.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4J1TL.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/0R5p9.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/mzKly.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="36366" PostHistoryTypeId="2" PostId="12536" RevisionGUID="c0799f1c-b162-4a6e-8a41-92bf90ec476c" CreationDate="2022-02-14T14:18:29.200" UserId="18001" Text="recently i started studying computer science and computer graphics, and one question really haunts me. Mby someone can explain this.&#xD;&#xA;How bit patterns become translated into (for example ) text. &#xD;&#xA;I know we have encoding like ascii and unicode but this is also just bit patterns. Main mystery is at what point do the bits turn into what we see on the screen?&#xD;&#xA;So maybe you have some sources which can explain it? How bits translated into text?&#xD;&#xA;&#xD;&#xA;Thanks![![Basic text which displayed on pc screen][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/DqaCg.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36368" PostHistoryTypeId="1" PostId="12536" RevisionGUID="c0799f1c-b162-4a6e-8a41-92bf90ec476c" CreationDate="2022-02-14T14:18:29.200" UserId="18001" Text="How bits transformed into graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36369" PostHistoryTypeId="3" PostId="12536" RevisionGUID="c0799f1c-b162-4a6e-8a41-92bf90ec476c" CreationDate="2022-02-14T14:18:29.200" UserId="18001" Text="|transformations|bitmap-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36370" PostHistoryTypeId="50" PostId="10248" RevisionGUID="a78f5402-18bd-44db-89d0-08e574d3b0e4" CreationDate="2022-02-14T21:07:05.493" UserId="-1" />
  <row Id="36371" PostHistoryTypeId="2" PostId="12537" RevisionGUID="f1ba1216-256a-4060-a7f8-8bb2281cc449" CreationDate="2022-02-14T23:24:18.307" UserId="482" Text="For a machine like in your image, the IBM PC, the characters shown are created using [character ROMs](https://second.wiki/wiki/ibm_pc_rom_bios). When software writes the character code into video memory, the memory hardware will use this code to lookup the bitmap from the character ROM. &#xD;&#xA;&#xD;&#xA;This is very different from more modern home computers with a graphical windowing environment. Here the glyphs for characters are stored in *font* files. Some fonts do contain bitmaps, even the exact same ones from old character ROMs. But many fonts will contain a [vector description](https://docs.microsoft.com/en-us/windows/win32/gdi/raster--vector--truetype--and-opentype-fonts) of the glyph which has to be rastered into a bitmap before use." ContentLicense="CC BY-SA 4.0" />
  <row Id="36373" PostHistoryTypeId="5" PostId="12537" RevisionGUID="6b1cad7f-ea04-48f5-bf6a-7c3cdb0022ae" CreationDate="2022-02-14T23:30:05.797" UserId="482" Comment="added 244 characters in body" Text="For a machine like in your image, the IBM PC, the characters shown are created using [character ROMs](https://second.wiki/wiki/ibm_pc_rom_bios). When software writes the character code into video memory, the memory hardware will use this code to lookup the bitmap from the character ROM. &#xD;&#xA;&#xD;&#xA;This is very different from more modern home computers with a graphical windowing environment. Here the glyphs for characters are stored in *font* files. Some fonts do contain bitmaps, even the exact same ones from old character ROMs. But many fonts will contain a [vector description](https://docs.microsoft.com/en-us/windows/win32/gdi/raster--vector--truetype--and-opentype-fonts) of the glyph which has to be rastered into a bitmap before use.&#xD;&#xA;&#xD;&#xA;Also, the importance of [ascii](https://en.wikipedia.org/wiki/ASCII) is not to be underestimated. This was a monumental effort to standardize character encoding in a time when every computer in the world (pretty much) used a different code." ContentLicense="CC BY-SA 4.0" />
  <row Id="36374" PostHistoryTypeId="5" PostId="10181" RevisionGUID="5ea5a33b-c815-4ba9-b8bb-ce8b6d68956f" CreationDate="2022-02-14T23:50:36.237" UserId="48" Comment="fix broken link" Text="A simple heuristic that many 3D content creation apps use is to split along the shorter of the two diagonals of the quad. This generally seems to work pretty well. It minimizes the appearance of long, skinny triangles, which are generally undesirable both for visual and performance reasons.&#xD;&#xA;&#xD;&#xA;See this article: [Deformation and Triangulation in Maya](https://noahalzayer.wordpress.com/2017/04/11/deformation-and-triangulation-in-maya/) for some further discussion. In particular if you have a dynamically deforming mesh, you ideally want to retriangulate the quads based on the deformed geometry each frame, or you can get some pretty wonky artifacts if you stick with a fixed triangulation:&#xD;&#xA;&#xD;&#xA;![dynamic retriangulation based on shortest diagonal vs fixed triangulation][1]\&#xD;&#xA;(image from the above linked blog post)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/egHDt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36376" PostHistoryTypeId="5" PostId="5253" RevisionGUID="76571f4e-24af-4e25-a30e-8d9d4b20894e" CreationDate="2022-02-15T10:41:58.367" UserId="13273" Comment="indent program code" Text="I am trying to run the following program on ubuntu 15.04. However on typing &quot;g++ pgm1.cpp -lglut&quot;&#xD;&#xA;I am getting following errors&#xD;&#xA;&#xD;&#xA;**/usr/bin/ld: /tmp/cc9aXqhZ.o: undefined reference to symbol 'glClear'**&#xD;&#xA;&#xD;&#xA;**/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1: error adding symbols: DSO missing from command line**&#xD;&#xA;    &#xD;&#xA;Though I am familiar with C programming in Codeblocks and DevC++, this is the first time I am working on Ubuntu and OpenGL. I installed ubuntu and files related to OpenGL based on information available on the net. The sample program too is from the internet. I would request help in getting the program run. Thanks.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    # include &quot;GL/freeglut.h&quot;&#xD;&#xA;    # include &quot;GL/gl.h&quot;&#xD;&#xA;    # include &lt;GL/glut.h&gt;&#xD;&#xA;&#xD;&#xA;    void init(void)&#xD;&#xA;    {&#xD;&#xA;        glClearColor(0.0f,0.0f,1.0f,1.0f);&#xD;&#xA;    }&#xD;&#xA;    void display (void) &#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        glFlush();&#xD;&#xA;    }&#xD;&#xA;    int main (int argc, char** argv)&#xD;&#xA;    {&#xD;&#xA;        glutInit(&amp;argc,argv);&#xD;&#xA;        glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);&#xD;&#xA;        glutCreateWindow(&quot;A Blank Window&quot;);&#xD;&#xA;        init();&#xD;&#xA;        glutDisplayFunc(display);&#xD;&#xA;        glutMainLoop();&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36377" PostHistoryTypeId="24" PostId="5253" RevisionGUID="76571f4e-24af-4e25-a30e-8d9d4b20894e" CreationDate="2022-02-15T10:41:58.367" Comment="Proposed by 13273 approved by 13095 edit id of 576" ContentLicense="CC BY-SA 4.0" />
  <row Id="36383" PostHistoryTypeId="5" PostId="10195" RevisionGUID="0f54970b-e3d3-40fc-91ed-12636fe78d03" CreationDate="2022-02-16T14:51:39.317" UserId="209" Comment="used wrong adjective" Text="One other, albeit more expensive approach, is to subdivide your quad into 4 triangles by putting a point at the centre of each quad. There are some advantages to this in that:&#xD;&#xA; 1. It will be more temporally stable. If your quad vertices are moving and you were otherwise using the &quot;shortest diagonal&quot; approach Nathan has suggested, the tessellation will change pattern every now and then.  Maybe this won't matter *too* much geometrically, but remember that the UV texture coordinates are also linearly interpolated in world space (obviously hyperbolically in screen space) and so the texturing can jump.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA; 3. If the quad is quite distorted (e.g non-planar or non-convex),  I think the 4xtri approach will look much better than either of the two 2xtri options&#xD;&#xA;&#xD;&#xA; 4. If you instead are just chopping into triangles based on the order of the vertices of your quad, i.e. ABCD always becomes ABC and CDA, then if by chance the modelling package spits out another &quot;identical&quot; quad but ordered as BCDA, then the rendered versions won't match.&#xD;&#xA;&#xD;&#xA;Of course, the downside is that you have 2x the number of vertices and triangles, but it may be worth considering.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36388" PostHistoryTypeId="2" PostId="12540" RevisionGUID="b00f4870-cfb2-4a1d-b147-bdc40c2a4d75" CreationDate="2022-02-16T21:27:25.957" UserId="18019" Text="I am not an expert in the area, but you can literally search for &quot;bits into graphics&quot; on google and get the following article. http://www.impacttectonics.org/GEO310/Labs/1B-Bits_and_Bytes.pdf which gives you a good description on how this work.&#xD;&#xA;&#xD;&#xA;So essentially once you have access to the monitor, you get access to the array of pixel that monitor has. &#xD;&#xA;&#xD;&#xA;Internally each pixel is a byte usually represented by 3 bytes Red, Green and Blue. &#xD;&#xA;&#xD;&#xA;Then you just create your own font (text) with that information, and if you want. ASCII is was created to everyone knows what the value 65 (01000001) will represent when interacting with the computer.&#xD;&#xA;&#xD;&#xA;I might be missing a lot of more information here, but I believe that's a good reference." ContentLicense="CC BY-SA 4.0" />
  <row Id="36390" PostHistoryTypeId="50" PostId="9199" RevisionGUID="ce2ba8b7-237c-47a1-ac27-d42f133e3af6" CreationDate="2022-02-17T03:07:05.640" UserId="-1" />
  <row Id="36391" PostHistoryTypeId="50" PostId="10584" RevisionGUID="16d330c1-f1fb-4a0e-869d-b6b148a56829" CreationDate="2022-02-17T07:02:35.280" UserId="-1" />
  <row Id="36392" PostHistoryTypeId="50" PostId="10025" RevisionGUID="0be0b715-3e6f-4fa6-a743-fcda9ddcddcb" CreationDate="2022-02-18T01:07:45.763" UserId="-1" />
  <row Id="36394" PostHistoryTypeId="50" PostId="9267" RevisionGUID="d4b518cd-5a28-4739-915b-03a2db2a6bd1" CreationDate="2022-02-18T10:00:35.057" UserId="-1" />
  <row Id="36395" PostHistoryTypeId="50" PostId="8935" RevisionGUID="b96e54d0-1c65-4acb-8bb6-bab72ba87243" CreationDate="2022-02-18T23:09:25.880" UserId="-1" />
  <row Id="36396" PostHistoryTypeId="50" PostId="12215" RevisionGUID="862277bd-77bf-4586-8f1b-ab67377bca1a" CreationDate="2022-02-19T10:04:45.687" UserId="-1" />
  <row Id="36397" PostHistoryTypeId="5" PostId="12499" RevisionGUID="6186bc84-4d1a-4f26-8d41-7c66506bbd3c" CreationDate="2022-02-20T08:56:37.970" UserId="16224" Comment="deleted 5 characters in body" Text="&gt; When I use the cosine everything gets really dark and the edges of my spheres are almost black. That makes sense because I am almost multiplying by cos(PI/2) = 0. I have read that it suppose to cancel out with something so I have removed it which help. But what does it cancel out with?&#xD;&#xA;&#xD;&#xA;That cosine has a geometrical meaning, keep it, or if you take it off, be sure you have a mathematical reason to do so.&#xD;&#xA;Grazing angles distribute much less of their radiance to the surface, and at an angle of 90°, the received radiance is zero.&#xD;&#xA;&#xD;&#xA;&gt; I am using Lambertian diffuse BRDF which means that the &quot;Fr&quot; part of the equation should be &quot;albedo / PI&quot;. I am also doing uniform hemisphere sampling which gave me a PDF of 1 / PI. Now when I calculate BRDF / PDF I get &quot;2 * albedo&quot;. That does not seem right. This means that the more and more bounces I make the bigger influence the light has which is nonsense. The light should be dimmer from the 3rd bounce than from the 1st bounce. Where did I make a mistake?&#xD;&#xA;&#xD;&#xA;The probability density function $p$, by its definition, must have an integral of 1 on the whole definition set, thus on the hemisphere. If you do the math, you'll get:&#xD;&#xA;&#xD;&#xA;$\int_\Omega p \, \text{d}\Omega = \int_0^{2\pi} \int_0^{\pi/2} p \, \sin \theta \, \text{d}\theta \, \text{d}\phi = 2\pi \Rightarrow p = \frac{1}{2\pi}$&#xD;&#xA;&#xD;&#xA;Sampling your PDF will give you $\theta = \arccos \xi_1 $, $\phi = 2\pi \xi_2$, where $\xi_1, \xi_2$ are independant random real numbers between 0 and 1. Sampling a PDF is not always easy and is another topic in itself, but for more details you can read this [excerpt from the excellent PBR][1].&#xD;&#xA;&#xD;&#xA;But as you saw it, you can do better : the cosine term in the rendering equation that bothers you from the beginning tells you that you **should** favor the directions that maximize this term. So let's choose a pdf such that&#xD;&#xA;&#xD;&#xA;$p = \alpha \cos \theta_i$&#xD;&#xA;&#xD;&#xA;If you want to know the value of $\alpha$, you have to remember that the integral of the pdf must be equal to one. If you do the math, this will give you $p = \frac{\cos \theta_i}{\pi}$.&#xD;&#xA;&#xD;&#xA;Sampling this new PDF with the method shown in PBR will give you $\theta = \arccos \sqrt{\xi_1}$, $\phi = 2\pi \xi_2$.&#xD;&#xA;&#xD;&#xA;Now, and only now, you can notice that the cosine of the rendering equation simplifies with the one in the PDF. You can then remove them.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations" ContentLicense="CC BY-SA 4.0" />
  <row Id="36398" PostHistoryTypeId="50" PostId="10263" RevisionGUID="93b25a10-0815-4817-9cc3-9fccb5ecd0de" CreationDate="2022-02-20T12:02:05.203" UserId="-1" />
  <row Id="36399" PostHistoryTypeId="2" PostId="12541" RevisionGUID="02344e2c-1fef-4825-8b63-4f345eec8ec1" CreationDate="2022-02-20T12:09:47.420" UserId="18034" Text="So I'm looking at incorporating instancing to my ray tracer. However what I would like some insight on is what to apply the transformation to?. Most suggest to apply the inverse transformation to the ray then proceed to check for detection. However this would require me to then transform the hit point and the direction of scattered ray back into world space. Whereas if I applied the transformation to the object space all is required is to apply the matrix transformation to a pair of pints in the form of a box primitive or just the centre of my sphere in the case of a sphere primitive. Could anyone tell me if I'm looking at this the wrong way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36401" PostHistoryTypeId="1" PostId="12541" RevisionGUID="02344e2c-1fef-4825-8b63-4f345eec8ec1" CreationDate="2022-02-20T12:09:47.420" UserId="18034" Text="Raytracing and transformation" ContentLicense="CC BY-SA 4.0" />
  <row Id="36402" PostHistoryTypeId="3" PostId="12541" RevisionGUID="02344e2c-1fef-4825-8b63-4f345eec8ec1" CreationDate="2022-02-20T12:09:47.420" UserId="18034" Text="|raytracing|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36404" PostHistoryTypeId="2" PostId="12542" RevisionGUID="5185e66f-cca7-4320-bec3-425fa3015337" CreationDate="2022-02-20T18:50:47.817" UserId="13711" Text="temporal reprojection works surprisingly well and simplistic with (in between) volume-marching (where rays scatter through a cloud of different density, with hard or smooth density-gradients)&#xD;&#xA;&#xD;&#xA;validity is is then as simple as an upper bound difference between 2 euclidean-distances (currentFrame + previousFrame)&#xD;&#xA;&#xD;&#xA;it may help, to use objectIDs to maintain sharper borders between any 2 solids, but too sharp borders will cause artefacts on movement. The definition of &quot;solid&quot; starts to get fluent, as soon as you do pure volume-marching, and then objectIDs may not be needed for reprojection (and only vor texturing), as in many more basic shaders of&#xD;&#xA;https://www.shadertoy.com/results?query=reproject&amp;sort=newest&amp;filter=&#xD;&#xA;explore my volume-marching with quaternion-camera unifications:&#xD;&#xA;https://www.shadertoy.com/view/7lBXWW (voumetric laser refraction on spheres+prism)&#xD;&#xA;https://www.shadertoy.com/view/wl3yDs (2 dynamic lights near a mandelbulb)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36406" PostHistoryTypeId="2" PostId="12543" RevisionGUID="a3452edd-3fb2-40cf-a91e-cfc3387ecd86" CreationDate="2022-02-21T10:41:59.070" UserId="18040" Text="Consider a monochrome ball. The colours of the pixels is a function of the point height, the light intensity, the light angle, and the surface material (reflection).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What is the simplest formula defining the resulting gradient?&#xD;&#xA;&#xD;&#xA;Note that my question is not about raytracing, as we assume a simple object with no inner shadow/reflection. I am just curious what is the simplest relation between the pixel colour and the four parameters (of if there are more).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mn7tk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36408" PostHistoryTypeId="1" PostId="12543" RevisionGUID="a3452edd-3fb2-40cf-a91e-cfc3387ecd86" CreationDate="2022-02-21T10:41:59.070" UserId="18040" Text="physics/math of lighting gradient of a 3D object" ContentLicense="CC BY-SA 4.0" />
  <row Id="36409" PostHistoryTypeId="3" PostId="12543" RevisionGUID="a3452edd-3fb2-40cf-a91e-cfc3387ecd86" CreationDate="2022-02-21T10:41:59.070" UserId="18040" Text="|3d|mathematics|lighting|perspective|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36410" PostHistoryTypeId="5" PostId="12543" RevisionGUID="6121732e-8c26-4f33-89aa-f18e9d891acb" CreationDate="2022-02-21T10:51:38.587" UserId="18040" Comment="added 173 characters in body" Text="Consider a monochrome ball. The colours of the pixels is a function of the point height, the light intensity, the light angle, and the surface material (reflection).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What is the simplest formula defining the resulting gradient?&#xD;&#xA;&#xD;&#xA;Note that my question is not about raytracing, as we assume a simple object with no inner shadow/reflection. I am just curious what is the simplest relation between the pixel colour and the four parameters (of if there are more).&#xD;&#xA;&#xD;&#xA;For every point, we have the coordinate `(x,y,z)` and the RGB colour of the material. How can we calculate the appearance colour (the right image) in a very basic form? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mn7tk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36411" PostHistoryTypeId="5" PostId="12543" RevisionGUID="558b4de1-17d4-450e-aeea-662a3f929fdc" CreationDate="2022-02-21T10:59:12.890" UserId="18040" Comment="added 13 characters in body" Text="Consider a monochrome ball. The colours of the pixels is a function of the point height, the light intensity, the light angle, and the surface material (reflection).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What is the simplest formula defining the resulting gradient?&#xD;&#xA;&#xD;&#xA;Note that my question is not about raytracing, as we assume a simple object with no inner shadow/reflection. I am just curious what is the simplest relation between the pixel colour and the four parameters (of if there are more).&#xD;&#xA;&#xD;&#xA;For every point, we have the coordinate `(x,y,z)` and the RGB colour of the material (left image). How can we calculate the appearance colour (the right image) in a very basic form? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mn7tk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36413" PostHistoryTypeId="2" PostId="12544" RevisionGUID="00d7a61d-81f2-4c68-a9e7-0a67dbf7be68" CreationDate="2022-02-22T01:57:58.033" UserId="7462" Text="I am trying to find an algorithm for the following problem.&#xD;&#xA;&#xD;&#xA;Assume we have a black and white image. The image contains a white region that encloses a space. This space may be concave but it has no holes, i.e. there is only one boundary.&#xD;&#xA;&#xD;&#xA;We must create a polyline such that, each point in the polyline, that point is inside a boundary pixel in the original image, the winding direction of the polyline points is the same for all images fed to the algorithm.&#xD;&#xA;&#xD;&#xA;I know opencv has a couple of functions that do this but I am interested in the algorithm rather than the implementation." ContentLicense="CC BY-SA 4.0" />
  <row Id="36415" PostHistoryTypeId="1" PostId="12544" RevisionGUID="00d7a61d-81f2-4c68-a9e7-0a67dbf7be68" CreationDate="2022-02-22T01:57:58.033" UserId="7462" Text="How to get a polyline from an image with consistent winding number" ContentLicense="CC BY-SA 4.0" />
  <row Id="36416" PostHistoryTypeId="3" PostId="12544" RevisionGUID="00d7a61d-81f2-4c68-a9e7-0a67dbf7be68" CreationDate="2022-02-22T01:57:58.033" UserId="7462" Text="|computational-geometry|image-processing|polygon|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36417" PostHistoryTypeId="50" PostId="8888" RevisionGUID="8a1f19ee-2e9b-4a2b-98f1-2f59fb522bd4" CreationDate="2022-02-22T18:00:55.113" UserId="-1" />
  <row Id="36418" PostHistoryTypeId="2" PostId="12545" RevisionGUID="312dbc18-f99b-48d1-8fc7-5320782973f8" CreationDate="2022-02-23T01:34:05.217" UserId="18040" Text="I read the pixels of PNG files via `libpng` and creates an array of alpha channels (showing visible pixels for a monochromatic image).&#xD;&#xA;&#xD;&#xA;int pixels[height][width];&#xD;&#xA;&#xD;&#xA;    for( int i=0; i&lt;height; i++){&#xD;&#xA;        for( int j=0; j&lt;width; j++){&#xD;&#xA;            if(pixels[i][j]&gt;0){&#xD;&#xA;                double x = (double)j;&#xD;&#xA;                double y = (double)i;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This creates steps at curvatures. Anti-aliasing uses lighter pixels to visually create smoothness at the edges. Assuming the image has only black pixels, and the alpha channel is used for anti-aliasing only, I decided to move the points (x,y) according to the alpha value&#xD;&#xA;&#xD;&#xA;    for( int i=0; i&lt;height; i++){&#xD;&#xA;        for( int j=0; j&lt;width; j++){&#xD;&#xA;            if(pixels[i][j]&gt;0){ // visible pixels&#xD;&#xA;                double x = (double)j;&#xD;&#xA;                double y = (double)i;&#xD;&#xA;&#xD;&#xA;                if(pixels[i][j]&lt;255){ // anti-aliasing partly transparent pixels&#xD;&#xA;                    if(pixels[i][j-1]==0){  // left edge&#xD;&#xA;                    x+=(double)(255-pixels[i][j])/255 // move the point to the right&#xD;&#xA;                }&#xD;&#xA;                else if(pixels[i][j]&lt;255){ &#xD;&#xA;                    if(pixels[i][j+1]==0){  // right edge&#xD;&#xA;                    x-=(double)(255-pixels[i][j])/255 // move the point to the left&#xD;&#xA;                }&#xD;&#xA;                // and the same for the vertical edges&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This massively improved the edge smoothness, but I believe the logic I followed is totally wrong, as it cannot account for the curves. For example,&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Programs like `potrace` do this job by transforming edges to paths, but here I just want to re-arrange the pixels points to form smooth edges (imagine we are creating the edges by dots instead of cubic pixels) rather than creating bezier curves.&#xD;&#xA;&#xD;&#xA;What is the practical way to capture points at the edge of PNG pixels with smoothness?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Kb7N2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36420" PostHistoryTypeId="1" PostId="12545" RevisionGUID="312dbc18-f99b-48d1-8fc7-5320782973f8" CreationDate="2022-02-23T01:34:05.217" UserId="18040" Text="Algorithm for transforming PNG anti-aliasing to smooth paths" ContentLicense="CC BY-SA 4.0" />
  <row Id="36421" PostHistoryTypeId="3" PostId="12545" RevisionGUID="312dbc18-f99b-48d1-8fc7-5320782973f8" CreationDate="2022-02-23T01:34:05.217" UserId="18040" Text="|algorithm|computational-geometry|image-processing|antialiasing|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36423" PostHistoryTypeId="50" PostId="12467" RevisionGUID="fd117426-0cad-4b5a-bf2a-f88c28a1e384" CreationDate="2022-02-24T13:05:40.473" UserId="-1" />
  <row Id="36434" PostHistoryTypeId="50" PostId="12491" RevisionGUID="7112e634-595e-4da4-b9ad-dc094524428e" CreationDate="2022-02-26T15:02:05.187" UserId="-1" />
  <row Id="36435" PostHistoryTypeId="50" PostId="10619" RevisionGUID="485a076e-41b2-47a1-8150-642f869aa09e" CreationDate="2022-02-28T16:02:40.253" UserId="-1" />
  <row Id="36436" PostHistoryTypeId="2" PostId="12547" RevisionGUID="f728108f-29bb-4f4a-af3e-cbfa14aec71c" CreationDate="2022-02-28T20:54:55.813" UserId="6530" Text="## Background:&#xD;&#xA;&#xD;&#xA;I'm trying to render lightning within a volumetrically rendered cloud.  I'm currently using a series of line-segments to represent lightning. &#xD;&#xA;&#xD;&#xA;At first I used a distance field rendered into a 128^3 texture to calculate lighting from the strike on each cloud segment. However I wanted to render the actual core lighting bolt, and using a distance check from this distance field resulted in a blocky blobby lightning bolt with lots of artifacts. &#xD;&#xA;&#xD;&#xA;I then transitioned to use IDs for the closest segment in a 128^3 buffer, then analytically determine the distance from the current sample point to the segment. While this isn't 100% accurate, I can generally get accurate distances and actually can render the core lightning bolt with out nearly as many artifacts. &#xD;&#xA;&#xD;&#xA;The problem is that I need to be able to do this for an arbitrarily large scene, and I'd like to do this for mostly arbitrary number of segments. &#xD;&#xA;&#xD;&#xA;At 128^3, that's 2MB for 1 byte per cell (256 segments). 1024^3? That's 1 gigabyte at 1 byte per cell. &#xD;&#xA;&#xD;&#xA;This scaling is unsustainable. But the actual data required to merely represent a bunch of line-segments is quite small. &#xD;&#xA;&#xD;&#xA;It's quickly calculating the distance for billions of points that's the issue.  Because the clouds are volumetric, I have to make 3D samples with ray marching, for each pixel.  I can't afford to add another N to my complexity per ray and still get real time framerates. &#xD;&#xA;&#xD;&#xA;But given the simplicity of the object I'm trying to find the distance to (the distance to the closest linesegment, or even more generally &quot;something that looks like lightning&quot;), and how specific I'm trying to be and the sheer amount of blank space, I get the feeling there should be *something* I can do to simplify the whole structure, reduce the amount of memory it takes up, with out majorly impacting performance.&#xD;&#xA;&#xD;&#xA;## Question:&#xD;&#xA;&#xD;&#xA;Is there any method to reduce memory usage of a *signed distance field* or closest object map given it represents distance to a series of connected linesegments? &#xD;&#xA;&#xD;&#xA;There's only a few things I can think of and all have major issues, what's more None of these solutions are really specific to lightning in the way I have described:&#xD;&#xA;&#xD;&#xA;* maybe I could put a bunch of boxes around the core of the lightning, and try to some how use that to reduce the blank space, then use the closest distance to the boxes instead, and grab the associated edge cell's closest linesegment.  This has issues that would require me to test distances several times, I'm not sure If I can limit how many time I test. I would still need to some how traverse these boxes as well.  &#xD;&#xA;&#xD;&#xA;* maybe I could create some sort of list of lists, where each pixel corresponds to an index into another array which contains the list of segment ID's that could physically have overlapped in the viewport given a certain distance. I'd have to re-create the list every frame lightning struck, and this could potentially be time consuming, but basically I'd do the following:&#xD;&#xA;&#xD;&#xA;1. for each line segment:&#xD;&#xA;&#xD;&#xA;  * 1.a project AABB, accounting for radius, onto viewport&#xD;&#xA;  * 1.b fill in pixels with in capsules. &#xD;&#xA;  * 1.c for each pixel within capsule distance&#xD;&#xA;  * 1.d increment value for pixel&#xD;&#xA;&#xD;&#xA;2. sum up pixel increments&#xD;&#xA;&#xD;&#xA;3. allocate total space for pixel increments (probably a pre-allocated size), offsets are now calculated for each pixel. Possibly use stream compaction. &#xD;&#xA;&#xD;&#xA;4. for each line segment:&#xD;&#xA;&#xD;&#xA;  * 4.a project AABB, accounting for radius, onto viewport&#xD;&#xA;  * 4.b fill in pixels with in capsules. &#xD;&#xA;  * 4.c for each pixel within capsule&#xD;&#xA;  * 4.d set linesegment ID to current pixel location (will need atomic ops per pixel). &#xD;&#xA;&#xD;&#xA;5. within each linesegment list, sort by depth to screen. &#xD;&#xA;&#xD;&#xA;6. when rendering use sorted list to figure out which segment distance to use, may have to compare multiple. hypothetically very few closest values most of the time. &#xD;&#xA;&#xD;&#xA;This solution seems like a lot of effort, and I'm afraid of uncapped memory usage and just bugs in general. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36438" PostHistoryTypeId="1" PostId="12547" RevisionGUID="f728108f-29bb-4f4a-af3e-cbfa14aec71c" CreationDate="2022-02-28T20:54:55.813" UserId="6530" Text="Distance to arbitrary set of line segments acceleration structure?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36439" PostHistoryTypeId="3" PostId="12547" RevisionGUID="f728108f-29bb-4f4a-af3e-cbfa14aec71c" CreationDate="2022-02-28T20:54:55.813" UserId="6530" Text="|lighting|line-drawing|volumetric|raymarching|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36440" PostHistoryTypeId="2" PostId="12548" RevisionGUID="aece1c5a-1055-4096-b5b9-52bd4cac7468" CreationDate="2022-03-01T15:06:38.063" UserId="18034" Text="I'm slightly confused on how to create a simple noise function in a fragment shader if all fragment coordinates are integer therefore unable to interpolate between randomly generated values. What am I missing here? Any hint would be appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="36442" PostHistoryTypeId="1" PostId="12548" RevisionGUID="aece1c5a-1055-4096-b5b9-52bd4cac7468" CreationDate="2022-03-01T15:06:38.063" UserId="18034" Text="Noise and fragment shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="36443" PostHistoryTypeId="3" PostId="12548" RevisionGUID="aece1c5a-1055-4096-b5b9-52bd4cac7468" CreationDate="2022-03-01T15:06:38.063" UserId="18034" Text="|rasterizer|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36444" PostHistoryTypeId="2" PostId="12549" RevisionGUID="56ad1235-7843-449a-9331-30947cf940d1" CreationDate="2022-03-02T10:32:21.353" UserId="13273" Text="I have a scenario with several cameras. Each hold its own color and depth texture.&#xD;&#xA;Because the geometry of the environment is expansively procedural generated, I would like to combine cameras with same resolution and texture format, to use layered rendering. This would be a very good performance boost.&#xD;&#xA;&#xD;&#xA;The question: Is it possible to combine multiple textures within a Framebuffer, so that when using layered rendering, each camera texture is a separate layer?&#xD;&#xA;I know, that when combining all camera textures to one single GL_TEXTURE_2D_ARRAY texture, I could use layered rendering. But I would like to manage them separately, because from time to time the camera positions move away from each other, so the layered rendering will not be helpful anymore. Or better several groups of cameras, which are nearby should be flexible grouped to one layered rendering call." ContentLicense="CC BY-SA 4.0" />
  <row Id="36446" PostHistoryTypeId="1" PostId="12549" RevisionGUID="56ad1235-7843-449a-9331-30947cf940d1" CreationDate="2022-03-02T10:32:21.353" UserId="13273" Text="Combining multiple textures within Framebuffer to use them in layered rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="36447" PostHistoryTypeId="3" PostId="12549" RevisionGUID="56ad1235-7843-449a-9331-30947cf940d1" CreationDate="2022-03-02T10:32:21.353" UserId="13273" Text="|opengl|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36448" PostHistoryTypeId="2" PostId="12550" RevisionGUID="fe9ba93d-07c4-4cb6-8976-f9f8d07ae5c0" CreationDate="2022-03-02T15:08:14.503" UserId="2654" Text="Layered rendering requires array textures, period (well, cubemaps can also work, but they're basically array textures anyway). There's no avoiding that.&#xD;&#xA;&#xD;&#xA;But unless you need the sizes and formats of the individual &quot;layers&quot; to be different, there's no reason you should be unable to use array textures for this purpose." ContentLicense="CC BY-SA 4.0" />
  <row Id="36450" PostHistoryTypeId="50" PostId="9926" RevisionGUID="069abbce-b877-4a63-a03d-78fc1e572787" CreationDate="2022-03-03T00:06:35.597" UserId="-1" />
  <row Id="36452" PostHistoryTypeId="2" PostId="12551" RevisionGUID="8b32f25c-d4b3-4aff-b061-c140117947ed" CreationDate="2022-03-03T05:28:22.240" UserId="7462" Text="As stated I have a triangle mesh I want to separate into connected components. One way I would assume would be to do a depth first search on a vertex and remove vertices, then repeat until the set is empty, but I wonder if there is a simpler (friendlier for the human) way to go about it." ContentLicense="CC BY-SA 4.0" />
  <row Id="36454" PostHistoryTypeId="1" PostId="12551" RevisionGUID="8b32f25c-d4b3-4aff-b061-c140117947ed" CreationDate="2022-03-03T05:28:22.240" UserId="7462" Text="What's a simple way to find connected components in a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36455" PostHistoryTypeId="3" PostId="12551" RevisionGUID="8b32f25c-d4b3-4aff-b061-c140117947ed" CreationDate="2022-03-03T05:28:22.240" UserId="7462" Text="|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36456" PostHistoryTypeId="2" PostId="12552" RevisionGUID="0acfd3a3-f3da-4b8a-b808-ca0073643243" CreationDate="2022-03-03T14:32:46.807" UserId="7952" Text="Perhaps this will be helpful:&#xD;&#xA;&#xD;&#xA;Typically when I think of noise in computer graphics I also think in terms of a grid, usually the grid is 2D or 3D. (the rest of this post refers to 2D noise)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So given a 2D grid, each coordinate in the grid will have an (x,y) position. Usually the origin is (0,0) and the grid extends out in both the positive and negative directions to some limit. The limit is important because of numerical accuracy.&#xD;&#xA;&#xD;&#xA;We can chose to use the screen coordinates as that grid, so it would have a range of something like (0,0)...(1024,768). Given an (x,y) position on that grid a noise function will always return the same value. And there are many algorithms out there to generate different kinds of noise. So long as a given noise function always returns the same value for a given input, then all will work out nicely. The code can even compute values for (x,y) locations that are not whole integer offsets in the grid using offsets, like (x,y)+(0.25,-0.25). Then take the average of those values for the fragment.&#xD;&#xA;&#xD;&#xA;Returning the same value for a given (x,y) screen position is useful when generating new noise algorithms or tweaking an existing algorithm to get a particular pattern, beyond that it isn't that interesting.&#xD;&#xA;&#xD;&#xA;The next alternative is to  make the screen coordinates a sliding window over a larger grid. This is done by adding the current (x,y) offset for the grid to every fragment like (x,y)+(183,251). This essentially changes the origin to (183,251). And by incrementing the x and/or y coordinates of (183,251) we can slide the grid around to see different areas of the noise. Still not terribly interesting.&#xD;&#xA;&#xD;&#xA;But how to visualize that grid as something like a height map of mountains or hills?&#xD;&#xA;&#xD;&#xA;The trick here is to keep the idea of the grid but change how it is visualized. There are multiple ways to accomplish this, many of the shader toy examples use some form of ray tracing.&#xD;&#xA;&#xD;&#xA;The first step to set up ray tracing is to define a camera. Usually the camera has a position and a direction. The camera position gives the current location within the noise grid, and the camera direction defines where the camera is looking.&#xD;&#xA;&#xD;&#xA;Using the camera position, its direction, and the fragment (x,y) coordinate of the screen it is fairly easy to find a direction for a unique vector that passes through that screen coordinate, in the direction of the camera. That vector is called a ray, and it is usually normalized to make it easier to work with.&#xD;&#xA;&#xD;&#xA;Now it is just a matter of figuring out where that ray intersects the noise grid. This is done just by stepping the ray forward from the camera position. Usually the steps are done using a fixed increment like 1.0. At each step figure out that rays (x,y) position on the noise grid, then compute the noise value for that position. The noise value is then directly used to compute a &quot;height&quot; at that point, and the rays position is compared with the computed height to determine if the ray is hitting, above, or below the terrain. If the ray is &quot;above&quot; the terrain then it is considered a miss, the ray is marched forward another step and tested again. This is done out to some limit, if nothing is hit, then a standard value like sky blue is returned. A ray that is below the terrain is usually considered a hit, but can be refined until a more accurate hit is determined. If the ray steps are to big, small terrain details can be missed, if the ray steps are to small, then algorithm will run to slowly to produce anything in real time.&#xD;&#xA;&#xD;&#xA;This is referred to as &quot;ray marching&quot; since the ray is &quot;marched&quot; forward. But the noise, and how it is visualized is the heart of the algorithm. Coders can even use the computed noise value, along with a position for a light source to compute shading for a ray hit.&#xD;&#xA;&#xD;&#xA;Additional rays can be sent out at small offsets from the original fragment coordinate then all the values averaged together. Atmospherics can be computed using 3D noise, and clouds can be added. The terrain height combined with another noise can be used to compute vegetation, snow, and rock colors.&#xD;&#xA;&#xD;&#xA;When all these techniques are combined, the results can be stunning, and noise, combined with the fragment coords are what make it all tick.&#xD;&#xA;&#xD;&#xA;Anyway, hopefully that gives a little insight into how fragment coordinates are used &#xD;&#xA; with noise algorithms to compute interesting scenes.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36458" PostHistoryTypeId="2" PostId="12553" RevisionGUID="e434ab16-39b8-46a9-8fc4-e4a9b620f40c" CreationDate="2022-03-03T19:25:50.673" UserId="17690" Text="I'm teaching a computer graphics course, and would like to give my students a function for calculating ray-triangle intersections (not just the point of intersection, but also the uv coordinates within the triangle). This seems like a good opportunity to review some key ideas in 3d vector geometry, so I'd like to pick an algorithm that is intuitive and helps review key vector topics.&#xD;&#xA;&#xD;&#xA;My original approach to this problem was to write out the equations and solve the system using a matrix inverse: Three equations (the x, y, and z coordinates of the intersection point) and three unknowns (how far along the ray, and the uv coordinates in the triangle). It looks like this is similar to Möller–Trumbore. This would be good for reviewing how to solve systems of linear equations, but doesn't seem to have much vector intuition behind it.&#xD;&#xA;&#xD;&#xA;The textbook I'm using as a reference suggests using a ray-plane intersection (a nice dot product, which is good for reviewing dot products!) then solving for u and v as a system of two equations in two unknowns.&#xD;&#xA;&#xD;&#xA;I'm not interested in the most efficient algorithm, but something that gives me an opportunity to teach something. Any suggestions? Any resources I can link my students to?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36460" PostHistoryTypeId="1" PostId="12553" RevisionGUID="e434ab16-39b8-46a9-8fc4-e4a9b620f40c" CreationDate="2022-03-03T19:25:50.673" UserId="17690" Text="Student-friendly ray-triangle intersection" ContentLicense="CC BY-SA 4.0" />
  <row Id="36461" PostHistoryTypeId="3" PostId="12553" RevisionGUID="e434ab16-39b8-46a9-8fc4-e4a9b620f40c" CreationDate="2022-03-03T19:25:50.673" UserId="17690" Text="|rendering|geometry|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36462" PostHistoryTypeId="2" PostId="12554" RevisionGUID="d22a22b4-c99b-413d-bb56-5626e66a5b36" CreationDate="2022-03-04T13:36:46.300" UserId="10096" Text="Note: work in progress.&#xD;&#xA;&#xD;&#xA;Let $v_0, v_1, v_2$ be the triangle vertices and $o$ be the origin of the ray and $d$ its direction. Denote the triangle edges $f_1 = v_1 - v_0$ and $f_2 = v_2 - v_0$. Then using $v_0$ as origin and $f_1, f_2$ as basis vectors defines a 2D coordinates system in 3D space. That is $v = v_0 + \beta f_1 + \gamma f_2$ is a parametric definition of a plane: any point $v$ on the plane has a unique coordinate $(\beta, \gamma)$ provided that $f_1$ is not parallel to $f_2$ (i.e. they are linearly independent). A triangle is a cutout of a plane. Namely, it is the set of points for which $0\leq \beta$, $0\leq \gamma$, $\beta + \gamma \leq 1$. Note that $\beta, \gamma$ are also the barycentric coordinates, which directly relates this also to rasterisation.&#xD;&#xA;&#xD;&#xA;Since we have a parametric definition of a ray: $p=o+td$ and a parametric definition of a plane: $v = v_0 + \beta f_1 + \gamma f_2$, then a point in the intersection satisfies both equations, and thus:&#xD;&#xA;&#xD;&#xA;$$o+td = v_0 + \beta f_1 + \gamma f_2$$&#xD;&#xA;$$\beta f_1 + \gamma f_2 - t d = o-v_o$$&#xD;&#xA;$$M = \begin{bmatrix} f_1 &amp; f_2 &amp; d\end{bmatrix} \implies M \begin{bmatrix} \beta \\ \gamma \\ -t\end{bmatrix} = o-v_0$$&#xD;&#xA;&#xD;&#xA;Solve for $t, \beta, \gamma$ and check $0\leq t$, $0\leq \beta$, $0\leq \gamma$, $\beta + \gamma\leq 1$. If all are fulfilled the intersection is at $p = o+td$.&#xD;&#xA;&#xD;&#xA;There's a more elegant solution that I'll add when I get back home, and I need to expand and elaborate on this one." ContentLicense="CC BY-SA 4.0" />
  <row Id="36464" PostHistoryTypeId="2" PostId="12555" RevisionGUID="9a7a788f-b03e-453b-9f3f-7d2546eae15e" CreationDate="2022-03-04T18:11:28.797" UserId="48" Text="No matter how you do it, there's going to be some kind of graph traversal (e.g. BFS or DFS) involved as that's pretty inherent to the problem.&#xD;&#xA;&#xD;&#xA;I'd first build a face neighbor array: for each face (assuming triangles), store the indices of the three neighboring faces. This can be done with a half-edge structure if you have it. If not, a simple way to do this is to create a hash table that maps edges, represented as ordered pairs of vertex indices, to face indices. Then, for each face you can look up the opposing edge and its face by swapping the two vertex indices. (This assumes the mesh is manifold.)&#xD;&#xA;&#xD;&#xA;Then, I'd allocate an array of ints to store the component index for each face, initially all set to -1 meaning unassigned.&#xD;&#xA;&#xD;&#xA;Start at the first face, assign it to component 0, then perform a BFS using the face neighbors array and assign everything it finds to component 0 (the component index here doubles as the &quot;marked&quot; flag for the BFS). Then find the first unassigned face, assign to component 1, and repeat.&#xD;&#xA;&#xD;&#xA;Then, if need be, you can build up arrays of face indices for each component by scanning through the component index array, or build new vertex/index buffers for each component, or whatever you need.&#xD;&#xA;&#xD;&#xA;This produces edge-connected components (two faces need to share an edge to be in the same component). An alternative is to do vertex-connected components (two faces are in the same component if they share a vertex, even if they have no shared edges), which is a little more general. For this, you would need to do similar logic but work on vertices instead of faces, which is a little trickier since each vertex can have an arbitrary number of neighbors. There's probably a clever way to build a vertex neighbor table efficiently, but it's not something I've thought about too much.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36466" PostHistoryTypeId="2" PostId="12556" RevisionGUID="077fb277-b44d-405c-879a-50561e4b171d" CreationDate="2022-03-04T18:19:08.967" UserId="48" Text="If you want something that looks more vectorial, start with doing a ray-plane intersection; then you can get the barycentric coordinates as follows:&#xD;&#xA;&#xD;&#xA;For each edge of the triangle, construct the plane through that edge that's perpendicular to the plane of the triangle (use cross products, etc).&#xD;&#xA;&#xD;&#xA;Then you can use the plane equation to measure (a) the distance from the edge to the opposite vertex of the triangle, and (b) the distance from the edge to the intersection point. Then divide b by a to obtain the barycentric coordinate associated with that opposite vertex.&#xD;&#xA;&#xD;&#xA;(UVs in the triangle are just picking two of the three barycentric coordinates; since they add up to 1, you can reconstruct the third once you have two.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36468" PostHistoryTypeId="5" PostId="12554" RevisionGUID="fee77b79-458b-4642-b890-1eb43cf8156d" CreationDate="2022-03-04T19:40:36.387" UserId="10096" Comment="added 9914 characters in body" Text="I am aware of two main ways for deriving the intersection between a ray and a triangle. I believe most ray-tri intersection routines are variants of those. In fact Möller–Trumbore is not something special from a purely mathematical perspective, it's just a specific grouping of terms when solving a 3x3 system.&#xD;&#xA;&#xD;&#xA;The first derivation involves finding barycentric and ray coordinates simultaneously which results in a 3x3 system. The second intersects the ray with the plane in which the triangle lies first, and then finds the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;**0.1) Parametric Ray Definition**&#xD;&#xA;&#xD;&#xA;A parametric definition of a line given an origin $\vec{o}$ and a direction $\vec{d}$ is: &#xD;&#xA;&#xD;&#xA;$$\vec{r}(t) = \vec{o} + t\vec{d}.$$ &#xD;&#xA;&#xD;&#xA;A ray is the set of points on one side of the origin of the line:&#xD;&#xA;&#xD;&#xA;$$\mathcal{R} = \{\vec{r}(t) = \vec{o} + t\vec{d}\,:\,t\in[0,\infty)\}.$$&#xD;&#xA;&#xD;&#xA;You should convince your students that this is indeed a ray. A good approach would be to draw several point on the ray for different $t$ vaues (e.g. 0, 1, 0.5, but also note that -1 is on the line but not part of the ray).&#xD;&#xA;&#xD;&#xA;**0.2) Parametric Triangle Definition**&#xD;&#xA;&#xD;&#xA;A parametric definition of a plane given a point on it $\vec{v}_0$ and two vectors $\vec{f}_1 = \vec{v}_1 - \vec{v}_0$, $\vec{f}_2 = \vec{v}_2-\vec{v}_0$ is: &#xD;&#xA;&#xD;&#xA;$$\vec{v}(\beta, \gamma) = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2$$&#xD;&#xA;&#xD;&#xA;The pair $(\beta, \gamma)$ are the coordinates of $\vec{v}$ in the 2D coordinate system with origin $\vec{v}_0$ and basis vectors $\vec{f}_1, \vec{f}_2$. For those to be basis vectors we additionally require that $\vec{f}_1, \vec{f}_2$ are not parallel/linearly dependent (i.e. the triangle is non-degenerate). &#xD;&#xA;&#xD;&#xA;You should convince the students that $\vec{v}(\beta, \gamma)$ indeed spans the whole plane for different $(\beta, \gamma)$. For instance you could draw the points $(0,0), (1,0), (0,1), (1,1)$ which are the vertices of a parallelogram. Additionally, the points forming the 3 edges of the triangle are: $(0,\gamma); \gamma \in[0,1]$, $(\beta, 0); \beta \in [0,1]$, and $(\beta, \gamma); \beta \geq 0, \gamma \geq 0, \beta + \gamma = 1$. Then the set of points forming the triangle are:&#xD;&#xA;&#xD;&#xA;$$\mathcal{T} = \{\vec{v}(\beta, \gamma)\,:\,0\leq \beta, 0\leq \gamma, \beta+\gamma \leq 1\}.$$&#xD;&#xA;&#xD;&#xA;This should definitely be accompanied with a drawing of the geometry so that the students may grasp its meaning.&#xD;&#xA;&#xD;&#xA;**0.2.1) Barycentric Coorindates**&#xD;&#xA;&#xD;&#xA;This is something that I would personally leave to the very end, since it is not integral to any of the derivation, is less general, and more complex.&#xD;&#xA;&#xD;&#xA;The coordinates $\beta, \gamma$ are in fact the barycentric coordinates of $\vec{v}$ associated with $\vec{v}_1, \vec{v}_2$. In fact we can rewrite our formulation as:&#xD;&#xA;&#xD;&#xA;$$\begin{align}\vec{v}(\beta, \gamma) &amp;= \vec{v}_0 + \beta \vec{f}_1 + \gamma \vec{f}_2 \\ \vec{v}(\beta, \gamma) &amp;= \alpha\vec{v}_0 + \beta\vec{v}_1 + \gamma\vec{v}_2, \alpha = 1-\beta -\gamma,\end{align}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;where $\alpha, \beta, \gamma$ are the barycentric coordinates of point $\vec{v}$ with respect to the triangle $\vec{v}_0, \vec{v}_1, \vec{v}_2$. The choice of $(\beta, \gamma)$ over $(\alpha, \beta)$ or $(\alpha, \gamma)$ was arbitrary. Indeed using $\alpha+\beta+\gamma=1$ I could have equivalently written:&#xD;&#xA;&#xD;&#xA;$$\vec{v}(\alpha, \beta) = \vec{v}_2 + \alpha (\vec{v}_0-\vec{v}_2) + \beta (\vec{v}_1-\vec{v}_2) \\ \text{or} \\&#xD;&#xA;\vec{v}(\alpha, \gamma) = \vec{v}_1 + \alpha (\vec{v}_0-\vec{v}_1) + \gamma (\vec{v}_2-\vec{v}_1).&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However, the fact that $\alpha, \beta, \gamma$ are the barycentric coordinates is not really important, and can be kept as an additional fact in order to not overload the students. The 2D basis interpretation is simpler and much more general.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**0.3) Problem Formulation**&#xD;&#xA;&#xD;&#xA;We want to find the closest intersection (the one with smallest $t$) between $\mathcal{R}$ and $\mathcal{T}$. Let $\vec{p}$ be an intersection point, i.e. $\vec{p} \in \mathcal{R}$ and $\vec{p} \in \mathcal{T}$, then there exist $t\geq 0, \beta\geq 0, \gamma\geq 0, \beta+\gamma\leq 1$ such that:&#xD;&#xA;&#xD;&#xA;$$\vec{o}+t\vec{d} = \vec{p} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;Conversely, if those do not exist then we'll say that there is no intersection. Beyond this point the only difference is how one groups the terms when solving the above $3\times 3$ system. For example Möller–Trumbore is just a special case of a specific solution order for the unknowns $t, \beta, \gamma$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1) Simultaneous Solution**&#xD;&#xA;&#xD;&#xA;Let us rewrite the equations in matrix form:&#xD;&#xA;&#xD;&#xA;$$\vec{o}+t\vec{d} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2$$&#xD;&#xA;$$\begin{bmatrix}\vec{d} &amp; \vec{f}_1 &amp; \vec{f}_2 \end{bmatrix} \begin{bmatrix} -t \\ \beta \\ \gamma \end{bmatrix} = \vec{o} - \vec{v}_0.$$&#xD;&#xA;&#xD;&#xA;It should be made clear for the students that $M = \begin{bmatrix}\vec{d} &amp; \vec{f}_1 &amp; \vec{f}_2 \end{bmatrix}$ is a 3x3 matrix, didactically, being explicit there may help:&#xD;&#xA;&#xD;&#xA;$$M = \begin{bmatrix}d_x &amp; f_{1,x} &amp; f_{2,x} \\  d_y &amp; f_{1,y} &amp; f_{2,y} \\ d_z &amp; f_{1,z} &amp; f_{2,z}\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Solving the system is as simple as:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} -t \\ \beta \\ \gamma \end{bmatrix} = M^{-1}(\vec{o}-\vec{v}_0)$$&#xD;&#xA;&#xD;&#xA;Either $3\times 3$ matrix inversion followed by matrix-vector multiplication can be used, or the equivalent Cramer's rule formulation. There's also a trick involving the cross product that works for $3\times 3$ matrix inversion that some people like to use (which is elegant, but didactically not very useful):&#xD;&#xA;&#xD;&#xA;$$M^{-1} = \frac{1}{det[M]}adj(M) = \frac{1}{\vec{d}\cdot(\vec{f}_1\times\vec{f}_2)}\begin{bmatrix} (\vec{f}_1\times\vec{f}_2)^T \\ (\vec{f}_2 \times \vec{d})^T \\ (\vec{d}\times \vec{f}_1)^T\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can identify the terms in Möller–Trumbore's algorithm with the terms from above, albeit I would altogether just recommend skipping Möller–Trumbore, and giving your students a 3x3 matrix inverse procedure and a matrix-vector multiplication procedure which should be enough to find the vector $\begin{bmatrix} -t &amp; \beta &amp; \gamma \end{bmatrix}^T$.&#xD;&#xA;&#xD;&#xA;Once $t, \beta, \gamma$ are computed one needs to check that this is indeed a valid intersection (i.e. it belongs to both $\mathcal{R}$ and $\mathcal{T}$):&#xD;&#xA;&#xD;&#xA;$$(0\leq t &lt; \infty) \land (0\leq \beta) \land (0\leq \gamma) \land (\beta+\gamma\leq 1).$$&#xD;&#xA;&#xD;&#xA;In C++ the above check would fail also when the matrix is not invertible, since NaNs and infinities will fail this check, so no additional code is necessary for the special cases. It is instructive however to consider what the special cases represent. One option is that $\vec{f}_1$ and $\vec{f}_2$ are parallel/linearly dependent - that means that we have a degenerate triangle (it's rather a line segment in this case). Another option is that $\vec{d}, \vec{f}_1, \vec{f}_2$ are coplanar/linearly dependent. This may occur if $\vec{d}$ is parallel to the plane spanned by $\vec{f}_1,\vec{f}_2$. Then if $\vec{o}$ doesn't lie in the plane there is no intersection. If $\vec{o}$ lies in the plane, then there are infinitely many intersections, and the closest one is at $t=0$. For convenience one can treat this as a non-intersection however, since the ray is inside the plane, which is infinitely thin.&#xD;&#xA;&#xD;&#xA;**2) Split Solution**&#xD;&#xA;&#xD;&#xA;The other solution method that I like and which has a nice geometric interpretation is the one where we first intersect the plane in which the triangle lies, and only after do we find the $\beta, \gamma$ coordinates. This is equivalent to solving for $1$ variable in the system, and the substituting back in order to get a $2\times 2$ system. We know that the plane has a normal $\vec{n} = \vec{f}_1\times\vec{f}_2$ and that the set of points on the plane ares:&#xD;&#xA;&#xD;&#xA;$$\mathcal{P} = \{\vec{p}\,:\, (\vec{p}-\vec{v}_0)\cdot \vec{n} = 0\}.$$&#xD;&#xA;&#xD;&#xA;Then plugging in $\vec{r}(t)$ for $\vec{p}$ yields:&#xD;&#xA;&#xD;&#xA;$$(\vec{o}+t\vec{d}-\vec{v}_0)\cdot \vec{n} = 0 \implies t = \frac{(\vec{v}_0-\vec{o})\cdot\vec{n}}{\vec{d}\cdot \vec{n}}.$$&#xD;&#xA;&#xD;&#xA;Note also that this is exactly what you'll get using Cramer's rule for $t$ using the $3\times 3$ system. Provided that $t \in [0,\infty)$ we can use the fact that we know the intersection point on the plane: $\vec{p} = \vec{o}+t\vec{d}$. We are now left with 3 equations but two unknowns:&#xD;&#xA;&#xD;&#xA;$$\vec{p} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;Ideally we would like to reduce this to a system of $2$ equations, this can be done by dotting the equations with $\vec{f}_1$ and $\vec{f}_2$:&#xD;&#xA;&#xD;&#xA;$$\vec{f}_1\cdot(\vec{p}-\vec{v}_0) = \beta\vec{f}_1\cdot\vec{f}_1 + \gamma\vec{f}_1\cdot\vec{f}_2 \\&#xD;&#xA;\vec{f}_2\cdot(\vec{p}-\vec{v}_0) = \beta\vec{f}_2\cdot\vec{f}_1 + \gamma\vec{f}_2\cdot\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;It's also instructive to look at what this looks like in terms of matrix notation:&#xD;&#xA;&#xD;&#xA;$$F = \begin{bmatrix} \vec{f}_1 &amp; \vec{f}_2\end{bmatrix} \\&#xD;&#xA;\vec{p}-\vec{v}_0 = F \begin{bmatrix} \beta \\ \gamma \end{bmatrix} \\&#xD;&#xA;F^T(\vec{p}-\vec{v}_0) = F^TF\begin{bmatrix} \beta \\ \gamma \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Then the solution reads:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} \beta \\ \gamma \end{bmatrix} = (F^TF)^{-1}F^T(\vec{p}-\vec{v}_0),$$&#xD;&#xA;&#xD;&#xA;and one must check that $(0\leq \beta) \land (0\leq \gamma) \land (\beta+\gamma\leq 1)$ as before.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2.1) Algebraic and Geometric Meaning**&#xD;&#xA;&#xD;&#xA;These are additional mathematically interesting details, that are probably best left for the very end.&#xD;&#xA;&#xD;&#xA;The matrix $F^TF$ is a $2\times 2$ matrix that is trivial to invert and has the following form:&#xD;&#xA;&#xD;&#xA;$$F^TF = \begin{bmatrix} \vec{f}_1\cdot\vec{f}_1 &amp; \vec{f}_1\cdot\vec{f}_2 \\ \vec{f}_1\cdot\vec{f}_2 &amp; \vec{f}_2\cdot\vec{f}_2\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;The matrix $G=F^TF$ is in fact the metric tensor on the plane. To motivate the metric tensor you can describe it as a tool to measure angles and lengths in a non-orthonormal coordinate system. Given two vectors $\vec{u}$ and $\vec{w}$ in the plane described through $\vec{u}_P = \begin{bmatrix} \beta_u &amp; \gamma_u\end{bmatrix}^T$ and $\vec{w}_P = \begin{bmatrix} \beta_w &amp; \gamma_w\end{bmatrix}^T$ the metric tensor can be used to compute the equivalent of the dot product between those:&#xD;&#xA;&#xD;&#xA;$$\vec{u}_P^TG\vec{w}_P = \vec{w}_P^TG\vec{u}_P = \vec{u}\cdot\vec{w} = \|\vec{u}\|\|\vec{w}\|\cos\angle(\vec{u},\vec{w}).$$&#xD;&#xA;&#xD;&#xA;In the above $\vec{u}, \vec{v}$ are the representations of the vectors with respect to the canonical basis $(1,0,0),\, (0,1,0),\, (0,0,1)$. It is also clear that for an orthonormal basis $\vec{f}_1, \vec{f}_2$, the metric tensor is the identity matrix.&#xD;&#xA;&#xD;&#xA;Another interpretation of the system is that:&#xD;&#xA;&#xD;&#xA;$$F^T(\vec{p}-\vec{v}_0) = F^TF\begin{bmatrix} \beta \\ \gamma \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;are the normal equations, which are used when we have an overdetermined system (more linearly independent equations than unknowns). In fact even if $\vec{p}$ was not in the plane of the triangle, the above would find the $\beta, \gamma$ for its projection on this plane, since the solution of the normal equations is a minimizer for:&#xD;&#xA;&#xD;&#xA;$$\|F\begin{bmatrix} \beta \\ \gamma \end{bmatrix} - (\vec{p}-\vec{v}_0)\|^2.$$&#xD;&#xA;&#xD;&#xA;Moreover in:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} \beta \\ \gamma \end{bmatrix} = (F^TF)^{-1}F^T(\vec{p}-\vec{v}_0),$$&#xD;&#xA;&#xD;&#xA;the matrix (F^TF)^{-1}F^T is known as the Moore–Penrose inverse. So there are in fact many algebraic and geometric interpretations that can be made in order to connect this problem to topics that the students have studied or are about to study." ContentLicense="CC BY-SA 4.0" />
  <row Id="36469" PostHistoryTypeId="5" PostId="12554" RevisionGUID="51921216-7a39-427c-a197-d5018379d47f" CreationDate="2022-03-04T19:52:37.667" UserId="10096" Comment="added 508 characters in body" Text="I am aware of two main ways for deriving the intersection between a ray and a triangle. I believe most ray-tri intersection routines are variants of those. In fact Möller–Trumbore is not something special from a purely mathematical perspective, it's just a specific grouping of terms when solving a 3x3 system.&#xD;&#xA;&#xD;&#xA;The first derivation involves finding barycentric and ray coordinates simultaneously which results in a 3x3 system. The second chooses to first intersect the ray with the plane, in which the triangle lies, and then finds the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;**0.1) Parametric Ray Definition**&#xD;&#xA;&#xD;&#xA;A parametric definition of a line given an origin $\vec{o}$ and a direction $\vec{d}$ is: &#xD;&#xA;&#xD;&#xA;$$\vec{r}(t) = \vec{o} + t\vec{d}.$$ &#xD;&#xA;&#xD;&#xA;A ray is the set of points on one side of the origin of the line:&#xD;&#xA;&#xD;&#xA;$$\mathcal{R} = \{\vec{r}(t) = \vec{o} + t\vec{d}\,:\,t\in[0,\infty)\}.$$&#xD;&#xA;&#xD;&#xA;You should convince your students that this is indeed a ray. A good approach would be to draw several point on the ray for different $t$ vaues (e.g. 0, 1, 0.5, but also note that -1 is on the line but not part of the ray).&#xD;&#xA;&#xD;&#xA;**0.2) Parametric Triangle Definition**&#xD;&#xA;&#xD;&#xA;A parametric definition of a plane given a point on it $\vec{v}_0$ and two vectors $\vec{f}_1 = \vec{v}_1 - \vec{v}_0$, $\vec{f}_2 = \vec{v}_2-\vec{v}_0$ is: &#xD;&#xA;&#xD;&#xA;$$\vec{v}(\beta, \gamma) = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2$$&#xD;&#xA;&#xD;&#xA;The pair $(\beta, \gamma)$ are the coordinates of $\vec{v}$ in the 2D coordinate system with origin $\vec{v}_0$ and basis vectors $\vec{f}_1, \vec{f}_2$. For those to be basis vectors we additionally require that $\vec{f}_1, \vec{f}_2$ are not parallel/linearly dependent (i.e. the triangle is non-degenerate). &#xD;&#xA;&#xD;&#xA;You should convince the students that $\vec{v}(\beta, \gamma)$ indeed spans the whole plane for different $(\beta, \gamma)$. For instance you could draw the points $(0,0), (1,0), (0,1), (1,1)$ which are the vertices of a parallelogram. Additionally, the points forming the 3 edges of the triangle are: $(0,\gamma); \gamma \in[0,1]$, $(\beta, 0); \beta \in [0,1]$, and $(\beta, \gamma); \beta \geq 0, \gamma \geq 0, \beta + \gamma = 1$. Then the set of points forming the triangle are:&#xD;&#xA;&#xD;&#xA;$$\mathcal{T} = \{\vec{v}(\beta, \gamma)\,:\,0\leq \beta, 0\leq \gamma, \beta+\gamma \leq 1\}.$$&#xD;&#xA;&#xD;&#xA;This should definitely be accompanied with a drawing of the geometry so that the students may grasp its meaning.&#xD;&#xA;&#xD;&#xA;**0.2.1) Barycentric Coorindates**&#xD;&#xA;&#xD;&#xA;This is something that I would personally leave for the very end, since it is not integral to any of the derivation, is less general, and more complex.&#xD;&#xA;&#xD;&#xA;The coordinates $\beta, \gamma$ are in fact the barycentric coordinates of $\vec{v}$ associated with $\vec{v}_1, \vec{v}_2$. In fact we can rewrite our formulation as:&#xD;&#xA;&#xD;&#xA;$$\begin{align}\vec{v}(\beta, \gamma) &amp;= \vec{v}_0 + \beta \vec{f}_1 + \gamma \vec{f}_2 \\ \vec{v}(\beta, \gamma) &amp;= \alpha\vec{v}_0 + \beta\vec{v}_1 + \gamma\vec{v}_2, \alpha = 1-\beta -\gamma,\end{align}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;where $\alpha, \beta, \gamma$ are the barycentric coordinates of point $\vec{v}$ with respect to the triangle $\vec{v}_0, \vec{v}_1, \vec{v}_2$. The choice of $(\beta, \gamma)$ over $(\alpha, \beta)$ or $(\alpha, \gamma)$ was arbitrary. Indeed using $\alpha+\beta+\gamma=1$ I could have equivalently written:&#xD;&#xA;&#xD;&#xA;$$\vec{v}(\alpha, \beta) = \vec{v}_2 + \alpha (\vec{v}_0-\vec{v}_2) + \beta (\vec{v}_1-\vec{v}_2) \\ \text{or} \\&#xD;&#xA;\vec{v}(\alpha, \gamma) = \vec{v}_1 + \alpha (\vec{v}_0-\vec{v}_1) + \gamma (\vec{v}_2-\vec{v}_1).&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However, the fact that $\alpha, \beta, \gamma$ are the barycentric coordinates is not really important, and can be kept as an additional fact in order to not overload the students. The 2D basis interpretation is simpler and much more general.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**0.3) Problem Formulation**&#xD;&#xA;&#xD;&#xA;We want to find the closest intersection (the one with smallest $t$) between $\mathcal{R}$ and $\mathcal{T}$. Let $\vec{p}$ be an intersection point, i.e. $\vec{p} \in \mathcal{R}$ and $\vec{p} \in \mathcal{T}$, then there exist $t\geq 0, \beta\geq 0, \gamma\geq 0, \beta+\gamma\leq 1$ such that:&#xD;&#xA;&#xD;&#xA;$$\vec{o}+t\vec{d} = \vec{p} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;Conversely, if those do not exist then we'll say that there is no intersection. Beyond this point the only difference is how one groups the terms when solving the above $3\times 3$ system. For example Möller–Trumbore is just a special case of a specific solution order for the unknowns $t, \beta, \gamma$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1) Simultaneous Solution**&#xD;&#xA;&#xD;&#xA;Let us rewrite the equations in matrix form:&#xD;&#xA;&#xD;&#xA;$$\vec{o}+t\vec{d} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2$$&#xD;&#xA;$$\begin{bmatrix}\vec{d} &amp; \vec{f}_1 &amp; \vec{f}_2 \end{bmatrix} \begin{bmatrix} -t \\ \beta \\ \gamma \end{bmatrix} = \vec{o} - \vec{v}_0.$$&#xD;&#xA;&#xD;&#xA;It should be made clear for the students that $M = \begin{bmatrix}\vec{d} &amp; \vec{f}_1 &amp; \vec{f}_2 \end{bmatrix}$ is a 3x3 matrix, didactically, being explicit there may help:&#xD;&#xA;&#xD;&#xA;$$M = \begin{bmatrix}d_x &amp; f_{1,x} &amp; f_{2,x} \\  d_y &amp; f_{1,y} &amp; f_{2,y} \\ d_z &amp; f_{1,z} &amp; f_{2,z}\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Solving the system is as simple as:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} -t \\ \beta \\ \gamma \end{bmatrix} = M^{-1}(\vec{o}-\vec{v}_0)$$&#xD;&#xA;&#xD;&#xA;Either $3\times 3$ matrix inversion followed by matrix-vector multiplication can be used, or the equivalent Cramer's rule formulation. There's also a trick involving the cross product that works for $3\times 3$ matrix inversion that some people like to use (which is elegant, but didactically not very useful):&#xD;&#xA;&#xD;&#xA;$$M^{-1} = \frac{1}{det[M]}adj(M) = \frac{1}{\vec{d}\cdot(\vec{f}_1\times\vec{f}_2)}\begin{bmatrix} (\vec{f}_1\times\vec{f}_2)^T \\ (\vec{f}_2 \times \vec{d})^T \\ (\vec{d}\times \vec{f}_1)^T\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can identify the terms in Möller–Trumbore's algorithm with the terms from above, albeit I would altogether just recommend skipping Möller–Trumbore, and giving your students a 3x3 matrix inverse procedure and a matrix-vector multiplication procedure which should be enough to find the vector $\begin{bmatrix} -t &amp; \beta &amp; \gamma \end{bmatrix}^T$.&#xD;&#xA;&#xD;&#xA;Once $t, \beta, \gamma$ are computed one needs to check that this is indeed a valid intersection (i.e. it belongs to both $\mathcal{R}$ and $\mathcal{T}$):&#xD;&#xA;&#xD;&#xA;$$(0\leq t &lt; \infty) \land (0\leq \beta) \land (0\leq \gamma) \land (\beta+\gamma\leq 1).$$&#xD;&#xA;&#xD;&#xA;In C++ the above check would fail also when the matrix is not invertible, since NaNs and infinities will fail this check, so no additional code is necessary for the special cases. It is instructive however to consider what the special cases represent. One option is that $\vec{f}_1$ and $\vec{f}_2$ are parallel/linearly dependent - that means that we have a degenerate triangle (it's rather a line segment in this case). Another option is that $\vec{d}, \vec{f}_1, \vec{f}_2$ are coplanar/linearly dependent. This may occur if $\vec{d}$ is parallel to the plane spanned by $\vec{f}_1,\vec{f}_2$. Then if $\vec{o}$ doesn't lie in the plane there is no intersection. If $\vec{o}$ lies in the plane, then there are infinitely many intersections, and the closest one is at $t=0$. For convenience one can treat this as a non-intersection however, since the ray is inside the plane, which is infinitely thin.&#xD;&#xA;&#xD;&#xA;**2) Split Solution**&#xD;&#xA;&#xD;&#xA;The other solution method that I like and which has a nice geometric interpretation is the one where we first intersect the plane in which the triangle lies, and only after do we find the $\beta, \gamma$ coordinates. This is loosely equivalent to solving for the $t$ variable in the system, and then substituting back in order to get a $2\times 2$ system. We know that the plane has a normal $\vec{n} = \vec{f}_1\times\vec{f}_2$ and that the set of points on the plane are:&#xD;&#xA;&#xD;&#xA;$$\mathcal{P} = \{\vec{p}\,:\, (\vec{p}-\vec{v}_0)\cdot \vec{n} = 0\}.$$&#xD;&#xA;&#xD;&#xA;Then plugging in $\vec{r}(t)$ for $\vec{p}$ yields:&#xD;&#xA;&#xD;&#xA;$$(\vec{o}+t\vec{d}-\vec{v}_0)\cdot \vec{n} = 0 \implies t = \frac{(\vec{v}_0-\vec{o})\cdot\vec{n}}{\vec{d}\cdot \vec{n}}.$$&#xD;&#xA;&#xD;&#xA;Note also that this is exactly what you'll get using Cramer's rule for $t$ using the $3\times 3$ system. Provided that $t \in [0,\infty)$ we can use the fact that we know the intersection point on the plane: $\vec{p} = \vec{o}+t\vec{d}$. We are now left with 3 equations but two unknowns:&#xD;&#xA;&#xD;&#xA;$$\vec{p} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;Ideally we would like to reduce this to a system of $2$ equations, this can be done by dotting the equations with $\vec{f}_1$ and $\vec{f}_2$:&#xD;&#xA;&#xD;&#xA;$$\vec{f}_1\cdot(\vec{p}-\vec{v}_0) = \beta\vec{f}_1\cdot\vec{f}_1 + \gamma\vec{f}_1\cdot\vec{f}_2 \\&#xD;&#xA;\vec{f}_2\cdot(\vec{p}-\vec{v}_0) = \beta\vec{f}_2\cdot\vec{f}_1 + \gamma\vec{f}_2\cdot\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;It's also instructive to look at what this looks like in terms of matrix notation:&#xD;&#xA;&#xD;&#xA;$$F = \begin{bmatrix} \vec{f}_1 &amp; \vec{f}_2\end{bmatrix} \\&#xD;&#xA;\vec{p}-\vec{v}_0 = F \begin{bmatrix} \beta \\ \gamma \end{bmatrix} \\&#xD;&#xA;F^T(\vec{p}-\vec{v}_0) = F^TF\begin{bmatrix} \beta \\ \gamma \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Then the solution reads:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} \beta \\ \gamma \end{bmatrix} = (F^TF)^{-1}F^T(\vec{p}-\vec{v}_0),$$&#xD;&#xA;&#xD;&#xA;and one must check that $(0\leq \beta) \land (0\leq \gamma) \land (\beta+\gamma\leq 1)$ as before.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2.1) Algebraic and Geometric Meaning**&#xD;&#xA;&#xD;&#xA;These are additional mathematically interesting details, that are probably best left for the very end.&#xD;&#xA;&#xD;&#xA;The matrix $F^TF$ is a $2\times 2$ matrix that is trivial to invert and has the following form:&#xD;&#xA;&#xD;&#xA;$$F^TF = \begin{bmatrix} \vec{f}_1\cdot\vec{f}_1 &amp; \vec{f}_1\cdot\vec{f}_2 \\ \vec{f}_1\cdot\vec{f}_2 &amp; \vec{f}_2\cdot\vec{f}_2\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;The matrix $G=F^TF$ is in fact the metric tensor on the plane. To motivate the metric tensor you can describe it as a tool to measure angles and lengths in a non-orthonormal coordinate system. Given two vectors $\vec{u}$ and $\vec{w}$ in the plane described through $\vec{u}_P = \begin{bmatrix} \beta_u &amp; \gamma_u\end{bmatrix}^T$ and $\vec{w}_P = \begin{bmatrix} \beta_w &amp; \gamma_w\end{bmatrix}^T$ the metric tensor can be used to compute the equivalent of the dot product between those:&#xD;&#xA;&#xD;&#xA;$$\vec{u}_P^TG\vec{w}_P = \vec{w}_P^TG\vec{u}_P = \vec{u}\cdot\vec{w} = \|\vec{u}\|\|\vec{w}\|\cos\angle(\vec{u},\vec{w}).$$&#xD;&#xA;&#xD;&#xA;In the above $\vec{u}, \vec{w}$ are the representations of the vectors with respect to the canonical basis $(1,0,0),\, (0,1,0),\, (0,0,1)$. It is also clear that for an orthonormal basis $\vec{f}_1, \vec{f}_2$, the metric tensor is the identity matrix, recovering the usual dot product. In fact any inner product in a finite-dimensional real space has the form: $\vec{u}^TG\vec{w}$ for $G$ symmetric and positive definite. So this can be used to introduce both the concept of metric tensor and inner product with a suitable motivation. Using the definition for length: $\|\vec{u}_P\|^2 = \vec{u}_P^TG\vec{u}_P = \vec{u}^T\vec{u}$ it is also clear that the metric tensor helps with measuring length in non-orthonormal coordinate systems.&#xD;&#xA;&#xD;&#xA;Another interpretation of the system is that:&#xD;&#xA;&#xD;&#xA;$$F^T(\vec{p}-\vec{v}_0) = F^TF\begin{bmatrix} \beta \\ \gamma \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;are the normal equations, which are used when we have an overdetermined system (more linearly independent equations than unknowns, note that $F$ is rectangular with more rows than columns). In fact even if $\vec{p}$ was not in the plane of the triangle, the above would find the $\beta, \gamma$ for its projection on this plane, since the solution of the normal equations is a minimizer of:&#xD;&#xA;&#xD;&#xA;$$\left\|F\begin{bmatrix} \beta \\ \gamma \end{bmatrix} - (\vec{p}-\vec{v}_0)\right\|^2.$$&#xD;&#xA;&#xD;&#xA;Moreover in:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} \beta \\ \gamma \end{bmatrix} = (F^TF)^{-1}F^T(\vec{p}-\vec{v}_0),$$&#xD;&#xA;&#xD;&#xA;the matrix $(F^TF)^{-1}F^T$ is known as the Moore–Penrose (left pseudo-)inverse. So there are in fact many algebraic and geometric interpretations that can be made in order to connect this problem to topics that the students have studied or are about to study. It's a good motivational tool." ContentLicense="CC BY-SA 4.0" />
  <row Id="36470" PostHistoryTypeId="5" PostId="12554" RevisionGUID="06fb3dd8-77ee-4f29-aea4-872b19310a84" CreationDate="2022-03-04T20:06:20.200" UserId="10096" Comment="edited body" Text="I am aware of two main ways for deriving the intersection between a ray and a triangle. I believe most ray-tri intersection routines are variants of those. In fact Möller–Trumbore is not something special from a purely mathematical perspective, it's just a specific grouping of terms when solving a 3x3 system.&#xD;&#xA;&#xD;&#xA;The first derivation involves finding barycentric and ray coordinates simultaneously which results in a 3x3 system. The second chooses to first intersect the ray with the plane, in which the triangle lies, and then finds the barycentric coordinates.&#xD;&#xA;&#xD;&#xA;**0.1) Parametric Ray Definition**&#xD;&#xA;&#xD;&#xA;A parametric definition of a line given an origin $\vec{o}$ and a direction $\vec{d}$ is: &#xD;&#xA;&#xD;&#xA;$$\vec{r}(t) = \vec{o} + t\vec{d}.$$ &#xD;&#xA;&#xD;&#xA;A ray is the set of points on one side of the origin of the line:&#xD;&#xA;&#xD;&#xA;$$\mathcal{R} = \{\vec{r}(t) = \vec{o} + t\vec{d}\,:\,t\in[0,\infty)\}.$$&#xD;&#xA;&#xD;&#xA;You should convince your students that this is indeed a ray. A good approach would be to draw several point on the ray for different $t$ vaues (e.g. 0, 1, 0.5, but also note that -1 is on the line but not part of the ray).&#xD;&#xA;&#xD;&#xA;**0.2) Parametric Triangle Definition**&#xD;&#xA;&#xD;&#xA;A parametric definition of a plane given a point on it $\vec{v}_0$ and two vectors $\vec{f}_1 = \vec{v}_1 - \vec{v}_0$, $\vec{f}_2 = \vec{v}_2-\vec{v}_0$ is: &#xD;&#xA;&#xD;&#xA;$$\vec{v}(\beta, \gamma) = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2$$&#xD;&#xA;&#xD;&#xA;The pair $(\beta, \gamma)$ are the coordinates of $\vec{v}$ in the 2D coordinate system with origin $\vec{v}_0$ and basis vectors $\vec{f}_1, \vec{f}_2$. For those to be basis vectors we additionally require that $\vec{f}_1, \vec{f}_2$ are not parallel/linearly dependent (i.e. the triangle is non-degenerate). &#xD;&#xA;&#xD;&#xA;You should convince the students that $\vec{v}(\beta, \gamma)$ indeed spans the whole plane for different $(\beta, \gamma)$. For instance you could draw the points $(0,0), (1,0), (0,1), (1,1)$ which are the vertices of a parallelogram. Additionally, the points forming the 3 edges of the triangle are: $(0,\gamma); \gamma \in[0,1]$, $(\beta, 0); \beta \in [0,1]$, and $(\beta, \gamma); \beta \geq 0, \gamma \geq 0, \beta + \gamma = 1$. Then the set of points forming the triangle are:&#xD;&#xA;&#xD;&#xA;$$\mathcal{T} = \{\vec{v}(\beta, \gamma)\,:\,0\leq \beta, 0\leq \gamma, \beta+\gamma \leq 1\}.$$&#xD;&#xA;&#xD;&#xA;This should definitely be accompanied with a drawing of the geometry so that the students may grasp its meaning.&#xD;&#xA;&#xD;&#xA;**0.2.1) Barycentric Coorindates**&#xD;&#xA;&#xD;&#xA;This is something that I would personally leave for the very end, since it is not integral to any of the derivation, is less general, and more complex.&#xD;&#xA;&#xD;&#xA;The coordinates $\beta, \gamma$ are in fact the barycentric coordinates of $\vec{v}$ associated with $\vec{v}_1, \vec{v}_2$. In fact we can rewrite our formulation as:&#xD;&#xA;&#xD;&#xA;$$\begin{align}\vec{v}(\beta, \gamma) &amp;= \vec{v}_0 + \beta \vec{f}_1 + \gamma \vec{f}_2 \\ \vec{v}(\beta, \gamma) &amp;= \alpha\vec{v}_0 + \beta\vec{v}_1 + \gamma\vec{v}_2, \alpha = 1-\beta -\gamma,\end{align}$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;where $\alpha, \beta, \gamma$ are the barycentric coordinates of point $\vec{v}$ with respect to the triangle $\vec{v}_0, \vec{v}_1, \vec{v}_2$. The choice of $(\beta, \gamma)$ over $(\alpha, \beta)$ or $(\alpha, \gamma)$ was arbitrary. Indeed using $\alpha+\beta+\gamma=1$ I could have equivalently written:&#xD;&#xA;&#xD;&#xA;$$\vec{v}(\alpha, \beta) = \vec{v}_2 + \alpha (\vec{v}_0-\vec{v}_2) + \beta (\vec{v}_1-\vec{v}_2) \\ \text{or} \\&#xD;&#xA;\vec{v}(\alpha, \gamma) = \vec{v}_1 + \alpha (\vec{v}_0-\vec{v}_1) + \gamma (\vec{v}_2-\vec{v}_1).&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;However, the fact that $\alpha, \beta, \gamma$ are the barycentric coordinates is not really important, and can be kept as an additional fact in order to not overload the students. The 2D basis interpretation is simpler and much more general.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**0.3) Problem Formulation**&#xD;&#xA;&#xD;&#xA;We want to find the closest intersection (the one with smallest $t$) between $\mathcal{R}$ and $\mathcal{T}$. Let $\vec{p}$ be an intersection point, i.e. $\vec{p} \in \mathcal{R}$ and $\vec{p} \in \mathcal{T}$, then there exist $t\geq 0, \beta\geq 0, \gamma\geq 0, \beta+\gamma\leq 1$ such that:&#xD;&#xA;&#xD;&#xA;$$\vec{o}+t\vec{d} = \vec{p} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;Conversely, if those do not exist then we'll say that there is no intersection. Beyond this point the only difference is how one groups the terms when solving the above $3\times 3$ system. For example Möller–Trumbore is just a special case of a specific solution order for the unknowns $t, \beta, \gamma$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**1) Simultaneous Solution**&#xD;&#xA;&#xD;&#xA;Let us rewrite the equations in matrix form:&#xD;&#xA;&#xD;&#xA;$$\vec{o}+t\vec{d} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2$$&#xD;&#xA;$$\begin{bmatrix}\vec{d} &amp; \vec{f}_1 &amp; \vec{f}_2 \end{bmatrix} \begin{bmatrix} -t \\ \beta \\ \gamma \end{bmatrix} = \vec{o} - \vec{v}_0.$$&#xD;&#xA;&#xD;&#xA;It should be made clear for the students that $M = \begin{bmatrix}\vec{d} &amp; \vec{f}_1 &amp; \vec{f}_2 \end{bmatrix}$ is a 3x3 matrix, didactically, being explicit there may help:&#xD;&#xA;&#xD;&#xA;$$M = \begin{bmatrix}d_x &amp; f_{1,x} &amp; f_{2,x} \\  d_y &amp; f_{1,y} &amp; f_{2,y} \\ d_z &amp; f_{1,z} &amp; f_{2,z}\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Solving the system is as simple as:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} -t \\ \beta \\ \gamma \end{bmatrix} = M^{-1}(\vec{o}-\vec{v}_0)$$&#xD;&#xA;&#xD;&#xA;Either $3\times 3$ matrix inversion followed by matrix-vector multiplication can be used, or the equivalent Cramer's rule formulation. There's also a trick involving the cross product that works for $3\times 3$ matrix inversion that some people like to use (which is elegant, but didactically not very useful):&#xD;&#xA;&#xD;&#xA;$$M^{-1} = \frac{1}{det[M]}adj(M) = \frac{1}{\vec{d}\cdot(\vec{f}_1\times\vec{f}_2)}\begin{bmatrix} (\vec{f}_1\times\vec{f}_2)^T \\ (\vec{f}_2 \times \vec{d})^T \\ (\vec{d}\times \vec{f}_1)^T\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;You can identify the terms in Möller–Trumbore's algorithm with the terms from above, albeit I would altogether just recommend skipping Möller–Trumbore, and giving your students a 3x3 matrix inverse procedure and a matrix-vector multiplication procedure which should be enough to find the vector $\begin{bmatrix} -t &amp; \beta &amp; \gamma \end{bmatrix}^T$.&#xD;&#xA;&#xD;&#xA;Once $t, \beta, \gamma$ are computed one needs to check that this is indeed a valid intersection (i.e. it belongs to both $\mathcal{R}$ and $\mathcal{T}$):&#xD;&#xA;&#xD;&#xA;$$(0\leq t &lt; \infty) \land (0\leq \beta) \land (0\leq \gamma) \land (\beta+\gamma\leq 1).$$&#xD;&#xA;&#xD;&#xA;In C++ the above check would fail also when the matrix is not invertible, since NaNs and infinities will fail this check, so no additional code is necessary for the special cases. It is instructive however to consider what the special cases represent. One option is that $\vec{f}_1$ and $\vec{f}_2$ are parallel/linearly dependent - that means that we have a degenerate triangle (it's rather a line segment in this case). Another option is that $\vec{d}, \vec{f}_1, \vec{f}_2$ are coplanar/linearly dependent. This may occur if $\vec{d}$ is parallel to the plane spanned by $\vec{f}_1,\vec{f}_2$. Then if $\vec{o}$ doesn't lie in the plane there is no intersection. If $\vec{o}$ lies in the plane, then there are infinitely many intersections, and the closest one is at $t=0$. For convenience one can treat this as a non-intersection however, since the ray is inside the plane, which is infinitely thin.&#xD;&#xA;&#xD;&#xA;**2) Split Solution**&#xD;&#xA;&#xD;&#xA;The other solution method that I like and which has a nice geometric interpretation is the one where we first intersect the plane in which the triangle lies, and only after do we find the $\beta, \gamma$ coordinates. This is loosely equivalent to solving for the $t$ variable in the system, and then substituting back in order to get a $2\times 2$ system. We know that the plane has a normal $\vec{n} = \vec{f}_1\times\vec{f}_2$ and that the set of points on the plane are:&#xD;&#xA;&#xD;&#xA;$$\mathcal{P} = \{\vec{p}\,:\, (\vec{p}-\vec{v}_0)\cdot \vec{n} = 0\}.$$&#xD;&#xA;&#xD;&#xA;Then plugging in $\vec{r}(t)$ for $\vec{p}$ yields:&#xD;&#xA;&#xD;&#xA;$$(\vec{o}+t\vec{d}-\vec{v}_0)\cdot \vec{n} = 0 \implies t = \frac{(\vec{v}_0-\vec{o})\cdot\vec{n}}{\vec{d}\cdot \vec{n}}.$$&#xD;&#xA;&#xD;&#xA;Note also that this is exactly what you'll get using Cramer's rule for $t$ using the $3\times 3$ system. Provided that $t \in [0,\infty)$ we can use the fact that we know the intersection point on the plane: $\vec{p} = \vec{o}+t\vec{d}$. We are now left with 3 equations but two unknowns:&#xD;&#xA;&#xD;&#xA;$$\vec{p} = \vec{v}_0 + \beta\vec{f}_1 + \gamma\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;Ideally we would like to reduce this to a system of $2$ equations, this can be done by dotting the equations with $\vec{f}_1$ and $\vec{f}_2$:&#xD;&#xA;&#xD;&#xA;$$\vec{f}_1\cdot(\vec{p}-\vec{v}_0) = \beta\vec{f}_1\cdot\vec{f}_1 + \gamma\vec{f}_1\cdot\vec{f}_2 \\&#xD;&#xA;\vec{f}_2\cdot(\vec{p}-\vec{v}_0) = \beta\vec{f}_2\cdot\vec{f}_1 + \gamma\vec{f}_2\cdot\vec{f}_2.$$&#xD;&#xA;&#xD;&#xA;It's also instructive to look at what this looks like in terms of matrix notation:&#xD;&#xA;&#xD;&#xA;$$F = \begin{bmatrix} \vec{f}_1 &amp; \vec{f}_2\end{bmatrix} \\&#xD;&#xA;\vec{p}-\vec{v}_0 = F \begin{bmatrix} \beta \\ \gamma \end{bmatrix} \\&#xD;&#xA;F^T(\vec{p}-\vec{v}_0) = F^TF\begin{bmatrix} \beta \\ \gamma \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Then the solution reads:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} \beta \\ \gamma \end{bmatrix} = (F^TF)^{-1}F^T(\vec{p}-\vec{v}_0),$$&#xD;&#xA;&#xD;&#xA;and one must check that $(0\leq \beta) \land (0\leq \gamma) \land (\beta+\gamma\leq 1)$ as before.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**2.1) Algebraic and Geometric Meaning**&#xD;&#xA;&#xD;&#xA;These are additional mathematically interesting details, that are probably best left for the very end.&#xD;&#xA;&#xD;&#xA;The matrix $F^TF$ is a $2\times 2$ matrix that is trivial to invert and has the following form:&#xD;&#xA;&#xD;&#xA;$$F^TF = \begin{bmatrix} \vec{f}_1\cdot\vec{f}_1 &amp; \vec{f}_1\cdot\vec{f}_2 \\ \vec{f}_1\cdot\vec{f}_2 &amp; \vec{f}_2\cdot\vec{f}_2\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;The matrix $G=F^TF$ is in fact the metric tensor on the plane. To motivate the metric tensor you can describe it as a tool to measure angles and lengths in a non-orthonormal coordinate system. Given two vectors $\vec{u}$ and $\vec{w}$ in the plane described through $\vec{u}_P = \begin{bmatrix} \beta_u &amp; \gamma_u\end{bmatrix}^T$ and $\vec{w}_P = \begin{bmatrix} \beta_w &amp; \gamma_w\end{bmatrix}^T$ the metric tensor can be used to compute the equivalent of the dot product between those:&#xD;&#xA;&#xD;&#xA;$$\vec{u}_P^TG\vec{w}_P = \vec{w}_P^TG\vec{u}_P = \vec{u}\cdot\vec{w} = \|\vec{u}\|\|\vec{w}\|\cos\angle(\vec{u},\vec{w}).$$&#xD;&#xA;&#xD;&#xA;In the above $\vec{u}, \vec{w}$ are the representations of the vectors with respect to the canonical basis $(1,0,0),\, (0,1,0),\, (0,0,1)$. It is also clear that for an orthonormal basis $\vec{f}_1, \vec{f}_2$, the metric tensor is the identity matrix, recovering the usual dot product. In fact any inner product in a finite-dimensional real space has the form: $\vec{u}^TG\vec{w}$ for $G$ symmetric and positive definite. So this can be used to introduce both the concept of metric tensor and inner product with a suitable motivation. Using the definition for length: $\|\vec{u}_P\|^2 = \vec{u}_P^TG\vec{u}_P = \vec{u}^T\vec{u}$ it is also clear that the metric tensor helps with measuring length in non-orthonormal coordinate systems.&#xD;&#xA;&#xD;&#xA;Another interpretation of the system is that:&#xD;&#xA;&#xD;&#xA;$$F^T(\vec{p}-\vec{v}_0) = F^TF\begin{bmatrix} \beta \\ \gamma \end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;are the normal equations, which are used when we have an overdetermined system (more linearly independent equations than unknowns, note that $F$ is rectangular with more rows than columns). In fact even if $\vec{p}$ was not in the plane of the triangle, the above would find the $\beta, \gamma$ for its projection on this plane, since the solution of the normal equations is a minimizer of:&#xD;&#xA;&#xD;&#xA;$$\left\|\vec{v}_0 + F\begin{bmatrix} \beta \\ \gamma \end{bmatrix} - \vec{p}\right\|^2.$$&#xD;&#xA;&#xD;&#xA;Moreover in:&#xD;&#xA;&#xD;&#xA;$$\begin{bmatrix} \beta \\ \gamma \end{bmatrix} = (F^TF)^{-1}F^T(\vec{p}-\vec{v}_0),$$&#xD;&#xA;&#xD;&#xA;the matrix $(F^TF)^{-1}F^T$ is known as the Moore–Penrose (left pseudo-)inverse. So there are in fact many algebraic and geometric interpretations that can be made in order to connect this problem to topics that the students have studied or are about to study. It's a good motivational tool." ContentLicense="CC BY-SA 4.0" />
  <row Id="36471" PostHistoryTypeId="50" PostId="12503" RevisionGUID="2af269d1-ec0e-49eb-910c-ac0819950c05" CreationDate="2022-03-04T21:06:55.750" UserId="-1" />
  <row Id="36473" PostHistoryTypeId="2" PostId="12557" RevisionGUID="723f3373-0260-4058-b8ea-47390dae33a2" CreationDate="2022-03-05T13:42:01.183" UserId="7952" Text="The University of Washington, Computer Science department teaches a ray, triangle intersection algorithm that is fairly intuitive, has good documentation [(they did their own write up here)][1], and covers a nice range of concepts. It also reviews several important concepts with nice explanations. I thought about doing a write up here but the original paper is better so I will just leave the link.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://courses.cs.washington.edu/courses/csep557/10au/lectures/triangle_intersection.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="36475" PostHistoryTypeId="2" PostId="12558" RevisionGUID="a0bc07f2-db4b-4197-8da9-4dad1e93e6ff" CreationDate="2022-03-06T10:57:49.070" UserId="7462" Text="Pretty much the title I am trying to delete a few faces of a mesh using open mesh, like this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;	MyMesh mesh;&#xD;&#xA;&#xD;&#xA;	char fname[1024];&#xD;&#xA;	sprintf(fname, &quot;box_%i.obj&quot;, 0);&#xD;&#xA;	if (!OpenMesh::IO::read_mesh(mesh, std::string(fname)))&#xD;&#xA;	{&#xD;&#xA;	    std::cerr &lt;&lt; &quot;read error\n&quot;;&#xD;&#xA;    	exit(1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	MyMesh::FaceIter v_it, v_end(mesh.faces_end());&#xD;&#xA;	uint count = 0;&#xD;&#xA;    for (v_it=mesh.faces_begin(); v_it!=v_end; ++v_it)&#xD;&#xA;	{&#xD;&#xA;		mesh.delete_face(*v_it, true);&#xD;&#xA;	}&#xD;&#xA; ```&#xD;&#xA;&#xD;&#xA;This is segfaulting on the first call to delete_face.&#xD;&#xA;&#xD;&#xA;However, writing this mesh (without trying to delete faces):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    if (!OpenMesh::IO::write_mesh(mesh, std::string(&quot;open_mesh.obj&quot;)))&#xD;&#xA;	{&#xD;&#xA;    	std::cerr &lt;&lt; &quot;write error\n&quot;;&#xD;&#xA;    	exit(1);&#xD;&#xA;	}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Works perfectly fine and blender can open the obj. So the issue very much seems to be with how I am trying to delete the faces. " ContentLicense="CC BY-SA 4.0" />
  <row Id="36477" PostHistoryTypeId="1" PostId="12558" RevisionGUID="a0bc07f2-db4b-4197-8da9-4dad1e93e6ff" CreationDate="2022-03-06T10:57:49.070" UserId="7462" Text="How to delete a face using open mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36478" PostHistoryTypeId="3" PostId="12558" RevisionGUID="a0bc07f2-db4b-4197-8da9-4dad1e93e6ff" CreationDate="2022-03-06T10:57:49.070" UserId="7462" Text="|c++|computational-geometry|geometry|half-edge|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36479" PostHistoryTypeId="2" PostId="12559" RevisionGUID="3a890180-8a53-4fc3-8a4a-070eab9f541b" CreationDate="2022-03-07T17:47:25.823" UserId="17330" Text="For anyone having the same problem:&#xD;&#xA;I calculated the normalized texture coordinates by&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec2 imgSize = imageSize(img_output);&#xD;&#xA;vec2 normtc = vec2(gl_GlobalInvocationID.xy) / imgSize;&#xD;&#xA;```&#xD;&#xA;this is of course wrong, the last line should be:&#xD;&#xA;```&#xD;&#xA;vec2 normtc = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5)) / imgSize;&#xD;&#xA;```&#xD;&#xA;since we want to sample the center of the pixel. This solved the problem for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="36481" PostHistoryTypeId="50" PostId="12498" RevisionGUID="c7ef0a25-17d1-4724-9e80-b09628145337" CreationDate="2022-03-08T00:04:00.680" UserId="-1" />
  <row Id="36482" PostHistoryTypeId="2" PostId="12560" RevisionGUID="499a6c2b-7d3e-41e6-8eec-14e15346e416" CreationDate="2022-03-08T21:08:51.290" UserId="18102" Text="I don't know if this is the right stack exchange for this question, but I couldn't find a better one, so I am posting it here. My question is, is text considered a form of graphics? As I am writing this question, certain pixels on my computer are changing color from white to black. So, I assume text is considered a form of graphics. But is it really? And if it isn't, what is the general name for something that covers both text and graphics, that is to say, all forms of things that appear on a computer monitor?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36484" PostHistoryTypeId="1" PostId="12560" RevisionGUID="499a6c2b-7d3e-41e6-8eec-14e15346e416" CreationDate="2022-03-08T21:08:51.290" UserId="18102" Text="Is text one form of graphics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36485" PostHistoryTypeId="3" PostId="12560" RevisionGUID="499a6c2b-7d3e-41e6-8eec-14e15346e416" CreationDate="2022-03-08T21:08:51.290" UserId="18102" Text="|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36486" PostHistoryTypeId="2" PostId="12561" RevisionGUID="f87ca95e-2da5-4405-bd23-4fcd0947797f" CreationDate="2022-03-08T21:52:15.440" UserId="18103" Text="The photographic version shows much more detailed fur than the popular test image." ContentLicense="CC BY-SA 4.0" />
  <row Id="36488" PostHistoryTypeId="1" PostId="12561" RevisionGUID="f87ca95e-2da5-4405-bd23-4fcd0947797f" CreationDate="2022-03-08T21:52:15.440" UserId="18103" Text="Has the Stanford Bunny ever been re-imaged?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36489" PostHistoryTypeId="3" PostId="12561" RevisionGUID="f87ca95e-2da5-4405-bd23-4fcd0947797f" CreationDate="2022-03-08T21:52:15.440" UserId="18103" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36490" PostHistoryTypeId="2" PostId="12562" RevisionGUID="6bdd8b9d-8fb2-4ebf-8a44-d665dc1348ec" CreationDate="2022-03-09T02:24:37.350" UserId="17813" Text="The latest scan of the Stanford Bunny that I'm aware of was in January 2000, a CT scan:  “The scale of the voxel data is 0.337891 mm x 0.337891 mm x 0.5mm in the x-, y-, and z-dimensions respectively.  The greyscale units are Hounsfield units, denoting electron-density of the subject.  The data is raw 512x512 slices, unsigned, 12 bit data stored as 16bit (2-byte) pixels.”&#xD;&#xA;&#xD;&#xA;http://graphics.stanford.edu/data/voldata/voldata.html#bunny&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36492" PostHistoryTypeId="5" PostId="12562" RevisionGUID="2eea16c0-92aa-4322-a641-cf5e9aa6c0bd" CreationDate="2022-03-09T02:35:17.270" UserId="17813" Comment="clairification" Text="The latest scan of the Stanford Bunny that I'm aware of was in January 2000, a CT scan:  “The scale of the voxel data is 0.337891 mm x 0.337891 mm x 0.5mm in the x-, y-, and z-dimensions respectively.  The greyscale units are Hounsfield units, denoting electron-density of the subject.  The data is raw 512x512 slices, unsigned, 12 bit data stored as 16bit (2-byte) pixels.”&#xD;&#xA;&#xD;&#xA;http://graphics.stanford.edu/data/voldata/voldata.html#bunny&#xD;&#xA;&#xD;&#xA;That link includes a download of the data, although I don't know how to open the files.  Even though the scan is later than the original 1994 range data, I'm not sure it can be considered higher resolution for 3D purposes.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36493" PostHistoryTypeId="2" PostId="12563" RevisionGUID="7d17b02e-e1e1-41a6-a3aa-0254c66286b5" CreationDate="2022-03-09T03:33:09.397" UserId="2654" Text="All of these terms are reliant on context. In the context of modern computers, text is a form of graphics. But this has not always been the case.&#xD;&#xA;&#xD;&#xA;Since before monitors existed, computer users had to have ways to get useful data out of computers. This would often involve specialized lights or something, but they eventually developed text output through a printer.&#xD;&#xA;&#xD;&#xA;CRT television displays existed at the time of course. But the interface between the computer and such displays had to be mediated by highly specialized electronics. Computers of the day couldn't just devise a picture and shove it at the CRT. Some kinds of such electronics were able to take a simple stream of bytes from the computer, similar to the form a computer would use to print something, and convert it into readable text on a CRT.&#xD;&#xA;&#xD;&#xA;And thus, a computer could display text.&#xD;&#xA;&#xD;&#xA;As memory capacities and processing power increased, some early CRT-interface hardware was capable of reading certain memories and interpreting them as pixels for display. One could call this &quot;graphics&quot;.&#xD;&#xA;&#xD;&#xA;Some computers, particularly early home computers, had specialized modes for displaying text compared to arbitrary graphics. These sometimes represented different hardware display circuitry. And of course, there were sprite-and-tilemap systems used by early game console hardware like the NES, but that's a different (though related) animal.&#xD;&#xA;&#xD;&#xA;Of course, as computers became more general-purpose and more capable, the need for specialized circuitry and modes to handle video display faded away. Everyone more or less landed on the same solution: write data into a specialized piece of memory, which display output hardware will read and display as pixels in some colorspace." ContentLicense="CC BY-SA 4.0" />
  <row Id="36495" PostHistoryTypeId="2" PostId="12564" RevisionGUID="908e4b52-46a5-4f8b-b17b-ec259020759b" CreationDate="2022-03-09T05:17:57.103" UserId="18104" Text="I am tasked with creating an outline shader in WebGL (i'm using WASM/Emscripten, so an OpenGL solution will work too) for meshes that the user can upload into our software (be it .obj, .fbx, .3ds), basically a clone of how [sketchup](https://www.sketchup.com/) does their outlines on meshes. Where the user can also control the thickness of the outlines with a slider. So, I basically have a vertex buffer, index buffer, the associated textures, and uv coordinates. &#xD;&#xA;&#xD;&#xA;My first try at this problem was creating a sobel edge detector on both the depth buffer and a buffer containing the normals of each fragment in the GLSL shaders using a post processing pass, in order to detect edges. And then the slider just controls the threshold value. However the thresholding doesn't seem to work generically for all meshes that a user can upload (especially if the mesh doesn't have smooth normals, like the threshold value will work for one mesh, but not another) and the number of bits in the depth buffer doesn't seem to be great when working with WebGL/JS. I learned my first approach from [GPU Gems](https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-15-blueprint-rendering-and-sketchy).&#xD;&#xA;&#xD;&#xA;So I am looking for a better solution. Something that is more robust. &#xD;&#xA;&#xD;&#xA;In my research I have found some repos in unreal engine 4 that use vertex colors to achieve the task. But that seems like something an artist would have to do themselves, not really computer generated. These are the repos [1](https://github.com/chrisloop/UE4_Vertex_Color_Edges) and [2](https://github.com/chrisloop/HDRPVertexColorEdges).&#xD;&#xA;&#xD;&#xA;I also read this page here [3](https://alexanderameye.github.io/notes/rendering-outlines/). But all the other methods don't seem to give nice internal outlines like edge detection has done. Here are some other resources I have read [4](https://bgolus.medium.com/the-quest-for-very-wide-outlines-ba82ed442cd9) and [5](https://www.videopoetics.com/tutorials/pixel-perfect-outline-shaders-unity/).&#xD;&#xA;&#xD;&#xA;Any suggestions would be a massive help, thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="36497" PostHistoryTypeId="1" PostId="12564" RevisionGUID="908e4b52-46a5-4f8b-b17b-ec259020759b" CreationDate="2022-03-09T05:17:57.103" UserId="18104" Text="Generating cheap perfect outlines for meshes in WebGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="36498" PostHistoryTypeId="3" PostId="12564" RevisionGUID="908e4b52-46a5-4f8b-b17b-ec259020759b" CreationDate="2022-03-09T05:17:57.103" UserId="18104" Text="|opengl|rendering|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36499" PostHistoryTypeId="5" PostId="12564" RevisionGUID="2220910a-096f-4068-ba0d-b51b55767e4d" CreationDate="2022-03-09T06:11:08.787" UserId="18104" Comment="added 78 characters in body" Text="I am tasked with creating an outline shader in WebGL (i'm using WASM/Emscripten, so an OpenGL solution will work too) for meshes that the user can upload into our software (be it .obj, .fbx, .3ds), basically a clone of how [sketchup](https://www.sketchup.com/) does their outlines on meshes. Where the user can also control the thickness of the outlines with a slider. So, I basically have a vertex buffer, index buffer, the associated textures, and uv coordinates. &#xD;&#xA;&#xD;&#xA;My first try at this problem was creating a sobel edge detector on both the depth buffer and a buffer containing the normals of each fragment in the GLSL shaders using a post processing pass, in order to detect edges. And then the slider just controls the threshold value. However the thresholding doesn't seem to work generically for all meshes that a user can upload (especially if the mesh doesn't have smooth normals, like the threshold value will work for one mesh, but not another) and the number of bits in the depth buffer doesn't seem to be great when working with WebGL/JS. I learned my first approach from [GPU Gems](https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-15-blueprint-rendering-and-sketchy).&#xD;&#xA;&#xD;&#xA;So I am looking for a better solution. Something that is more robust. &#xD;&#xA;&#xD;&#xA;In my research I have found some repos in unreal engine 4 that use vertex colors to achieve the task. But that seems like something an artist would have to do themselves, not really computer generated. These are the repos [1](https://github.com/chrisloop/UE4_Vertex_Color_Edges) and [2](https://github.com/chrisloop/HDRPVertexColorEdges).&#xD;&#xA;&#xD;&#xA;I also read this page here [3](https://alexanderameye.github.io/notes/rendering-outlines/). But all the other methods don't seem to give nice internal outlines like edge detection has done. Here are some other resources I have read [4](https://bgolus.medium.com/the-quest-for-very-wide-outlines-ba82ed442cd9) and [5](https://www.videopoetics.com/tutorials/pixel-perfect-outline-shaders-unity/) and [6](http://xroft666.blogspot.com/2015/07/glow-highlighting-in-unity.html).&#xD;&#xA;&#xD;&#xA;Any suggestions would be a massive help, thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="36500" PostHistoryTypeId="5" PostId="12564" RevisionGUID="7eff035f-0ba6-4c43-a11e-c0ebbd70fb16" CreationDate="2022-03-09T06:50:27.503" UserId="18104" Comment="added 360 characters in body" Text="I am tasked with creating an outline shader in WebGL (i'm using WASM/Emscripten, so an OpenGL solution will work too) for meshes that the user can upload into our software (be it .obj, .fbx, .3ds), basically a clone of how [sketchup](https://www.sketchup.com/) does their outlines on meshes. Where the user can also control the thickness of the outlines with a slider. So, I basically have a vertex buffer, index buffer, the associated textures, and uv coordinates. &#xD;&#xA;&#xD;&#xA;My first try at this problem was creating a sobel edge detector on both the depth buffer and a buffer containing the normals of each fragment in the GLSL shaders using a post processing pass, in order to detect edges. And then the slider just controls the threshold value. However the thresholding doesn't seem to work generically for all meshes that a user can upload (especially if the mesh doesn't have smooth normals, like the threshold value will work for one mesh, but not another) and the number of bits in the depth buffer doesn't seem to be great when working with WebGL/JS. I learned my first approach from [GPU Gems](https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-15-blueprint-rendering-and-sketchy).&#xD;&#xA;&#xD;&#xA;So I am looking for a better solution. Something that is more robust. &#xD;&#xA;&#xD;&#xA;In my research I have found some repos in unreal engine 4 that use vertex colors to achieve the task. Where they assign a vertex color for every vertex that is part of the same face (so multiple tris can have the same vertex color). But that seems like something an artist would have to do themselves, not really computer generated. These are the repos [1](https://github.com/chrisloop/UE4_Vertex_Color_Edges) and [2](https://github.com/chrisloop/HDRPVertexColorEdges). Another approach I though about is generating a wireframe mesh for the faces of the mesh in question (not the tris of the mesh, but the faces). But it then comes back to the problem of discovering what the faces of the mesh are.&#xD;&#xA;&#xD;&#xA;I also read this page here [3](https://alexanderameye.github.io/notes/rendering-outlines/). But all the other methods don't seem to give nice internal outlines like edge detection has done. Here are some other resources I have read [4](https://bgolus.medium.com/the-quest-for-very-wide-outlines-ba82ed442cd9) and [5](https://www.videopoetics.com/tutorials/pixel-perfect-outline-shaders-unity/) and [6](http://xroft666.blogspot.com/2015/07/glow-highlighting-in-unity.html).&#xD;&#xA;&#xD;&#xA;Any suggestions would be a massive help, thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="36501" PostHistoryTypeId="50" PostId="10879" RevisionGUID="8afd8007-71db-45ba-b373-8c729aa21ae9" CreationDate="2022-03-09T10:01:30.367" UserId="-1" />
  <row Id="36503" PostHistoryTypeId="50" PostId="10154" RevisionGUID="921144e2-7c1e-4851-91ec-0a3e20eecb0e" CreationDate="2022-03-10T10:07:20.657" UserId="-1" />
  <row Id="36504" PostHistoryTypeId="2" PostId="12565" RevisionGUID="cfbc336a-46bf-474a-ab2e-2810b8b7b9f8" CreationDate="2022-03-10T14:55:42.643" UserId="17690" Text="I'm trying to understand what causes the blobby edges when using alpha testing to create transparency with 1-bit alpha channels. The edges appear pixelated, but with rounded corners and diagonal lines. [![blobby edge effect on plant leaf][1]][1] [Image from http://wiki.polycount.com/wiki/File:Alphatest_8bit_vs_1bit.jpg]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/q097z.jpg&#xD;&#xA;&#xD;&#xA;My theory is that the fragment shader is sampling from the alpha channel using bicubic interpolation then comparing with the alpha threshold. (I would expect straighter edges with bilinear interpolation). Is this correct? Is something special done to prevent overshoot artifacts?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36506" PostHistoryTypeId="1" PostId="12565" RevisionGUID="cfbc336a-46bf-474a-ab2e-2810b8b7b9f8" CreationDate="2022-03-10T14:55:42.643" UserId="17690" Text="What causes blobby edges with alpha testing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36507" PostHistoryTypeId="3" PostId="12565" RevisionGUID="cfbc336a-46bf-474a-ab2e-2810b8b7b9f8" CreationDate="2022-03-10T14:55:42.643" UserId="17690" Text="|interpolation|transparency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36508" PostHistoryTypeId="2" PostId="12566" RevisionGUID="d02747f4-d55f-40b6-ac1e-dbae932d5c64" CreationDate="2022-03-10T19:27:26.897" UserId="18115" Text="Okay, so let's say I have a point in 3d. And I have a camera state. That is, I know the camera position, the camera target and the camera up vector.&#xD;&#xA;&#xD;&#xA;I am using the perspective projection to get the screen coordinates of that point, given viewport size.&#xD;&#xA;&#xD;&#xA;Now, for two different viewport sizes: V1: (w1, h1) and V2: (w2, h2).&#xD;&#xA;If I know the screen coordinates of a point in V1, how would I compute the screen coordinates of the same point in V2?&#xD;&#xA;&#xD;&#xA;So we are keeping the camera state constant, the field of view constant and only changing the size of the viewport.&#xD;&#xA;&#xD;&#xA;That is, I want to determine the function F, such that F(x1, y1) = (x2, y2) which would depend on w1, h1, w2 and h2. I'm having a hard time working this out since it's been a long while since I touched any 3d graphics math.&#xD;&#xA;&#xD;&#xA;I'm guessing it would be linear in x1, y1. Since, if we keep the same aspect ratio in both the viewports, (x2, y2) would simply be w2*(x1, y1)/w1.&#xD;&#xA;&#xD;&#xA;But happens when the aspect ratio changes?&#xD;&#xA;&#xD;&#xA;Also, as a separate question, by what factor would an object be scaled as we go from viewport V1 to V2? Here, again the answer seems simple when the aspect ratio is maintained but I can't figure out what happens if it isn't." ContentLicense="CC BY-SA 4.0" />
  <row Id="36510" PostHistoryTypeId="1" PostId="12566" RevisionGUID="d02747f4-d55f-40b6-ac1e-dbae932d5c64" CreationDate="2022-03-10T19:27:26.897" UserId="18115" Text="How to translate screen coordinates of a 3d point as the viewport size changes assuming camera state remains constant?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36511" PostHistoryTypeId="3" PostId="12566" RevisionGUID="d02747f4-d55f-40b6-ac1e-dbae932d5c64" CreationDate="2022-03-10T19:27:26.897" UserId="18115" Text="|3d|transformations|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36516" PostHistoryTypeId="2" PostId="12568" RevisionGUID="7d688845-959a-4279-91f8-3a37f169ca0b" CreationDate="2022-03-11T06:31:20.410" UserId="18115" Text="Okay so turns out when the viewport sizes change, the zoom is simply either `h2 / h1` or `w2 / w1`, depending on what field of view we are keeping constant.&#xD;&#xA;&#xD;&#xA;In my case, I had the vertical field of view constant, thus I used `h2 / h1`.&#xD;&#xA;So we can have `f(x1, y1) = (h2*x1/h1, h2*y2/h1)`.&#xD;&#xA;&#xD;&#xA;This will give us the correct y coordinate but we might get an offset on the x coordinate since the aspect ratio changes. To fix this, we just compute the offset by using the fact that the smaller/larger size of the viewport in the x-axis would have the same centre as the original viewport.&#xD;&#xA;&#xD;&#xA;So the offset is just (change in width) / 2 = `(w2 - h2*w1/h1) / 2`&#xD;&#xA;Finally, `f(x1, y1) = ((w2 - h2*w1/h1) / 2 + h2*x1/h1, h2*y2/h1)` is the function I needed!&#xD;&#xA;&#xD;&#xA;I plugged this into my program and got the desired results!" ContentLicense="CC BY-SA 4.0" />
  <row Id="36518" PostHistoryTypeId="5" PostId="12568" RevisionGUID="f4a8ba68-1f1d-4d4b-bf48-68f82e734831" CreationDate="2022-03-11T06:42:58.473" UserId="18115" Comment="deleted 8 characters in body" Text="Turns out when the viewport sizes change, the zoom is simply either `h2 / h1` or `w2 / w1`, depending on what field of view we are keeping constant.&#xD;&#xA;&#xD;&#xA;In my case, I had the vertical field of view constant, thus I used `h2 / h1`.&#xD;&#xA;So we can have `f(x1, y1) = (h2*x1/h1, h2*y2/h1)`.&#xD;&#xA;&#xD;&#xA;This will give us the correct y coordinate but we might get an offset on the x coordinate since the aspect ratio changes. To fix this, we just compute the offset by using the fact that the smaller/larger size of the viewport in the x-axis would have the same centre as the original viewport.&#xD;&#xA;&#xD;&#xA;So the offset is just (change in width) / 2 = `(w2 - h2*w1/h1) / 2`&#xD;&#xA;Finally, `f(x1, y1) = ((w2 - h2*w1/h1) / 2 + h2*x1/h1, h2*y2/h1)` is the function I needed!&#xD;&#xA;&#xD;&#xA;I plugged this into my program and got the desired results!" ContentLicense="CC BY-SA 4.0" />
  <row Id="36519" PostHistoryTypeId="50" PostId="4703" RevisionGUID="5cef345f-c7bb-4c8a-8c13-f8fe3e61836b" CreationDate="2022-03-11T11:06:20.660" UserId="-1" />
  <row Id="36520" PostHistoryTypeId="5" PostId="12561" RevisionGUID="6f9621d6-9c6c-41b0-9ef4-4e33564a3c60" CreationDate="2022-03-11T23:45:12.537" UserId="18103" Comment="image not page" Text="The [photographic version][1] shows much more detailed fur than the popular [test image][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://faculty.cc.gatech.edu/~turk/bunny/stanford-bunny-photo.jpg&#xD;&#xA;  [2]: https://commons.wikimedia.org/wiki/File:Stanford_Bunny.stl" ContentLicense="CC BY-SA 4.0" />
  <row Id="36523" PostHistoryTypeId="2" PostId="12569" RevisionGUID="3183bf3d-894a-4d8c-a979-2bd758304cef" CreationDate="2022-03-12T19:04:30.057" UserId="17690" Text="Let's consider the simplest case, where our texture is 2x2, with alpha values $a_{0,0}, a_{1,0}, a_{0,1}, a_{1,1}$. With bilinear filtering, the alpha at $uv$ coordinate $(x,y)$ is &#xD;&#xA;&#xD;&#xA;lerp(lerp($a_{0,0}$,$a_{1,0}$,$x$),lerp($a_{0,1}$,$a_{1,1}$,$x$),$y$), &#xD;&#xA;&#xD;&#xA;which works out to:&#xD;&#xA;&#xD;&#xA;lerp($x a_{1,0} + (1-x) a_{0,0}$, $x a_{1,1} + (1-x) a_{0,1}$,$y$)&#xD;&#xA;&#xD;&#xA;= $y(x a_{1,1} + (1-x) a_{0,1}) + (1-y) (x a_{1,0} + (1-x) a_{0,0})$,&#xD;&#xA;&#xD;&#xA;Expanding this out, it's a polynomial of the form:&#xD;&#xA;&#xD;&#xA;$b+cx+dy+exy$.&#xD;&#xA;&#xD;&#xA;Solving when this is equal to some threshold generally produces hyperbolas, but in degenerate cases can produce lines. &#xD;&#xA;&#xD;&#xA;In the image below, the texture specifies the colors at each grid line intersection. Within each grid square we have an example of interpolating a 2x2 texture, and the edge produced by comparing with a threshold is a segment of line or hyperbola.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I had originally assumed the lerp of the lerps would produce a polynomial of the form $b+cx+dy$, which solving against a threshold can only produce lines, so it was surprising to see nonlinear curves in the result.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1xTDJ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36525" PostHistoryTypeId="2" PostId="12570" RevisionGUID="8608c4d7-f56a-4eeb-8ae1-ea3bdf084da3" CreationDate="2022-03-16T06:37:37.107" UserId="18138" Text="How do I write a code to facilitate common shared memory for communication between multiple shaders as well as processes within them in python?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36527" PostHistoryTypeId="1" PostId="12570" RevisionGUID="8608c4d7-f56a-4eeb-8ae1-ea3bdf084da3" CreationDate="2022-03-16T06:37:37.107" UserId="18138" Text="Inter-Process communication in compute shaders" ContentLicense="CC BY-SA 4.0" />
  <row Id="36528" PostHistoryTypeId="3" PostId="12570" RevisionGUID="8608c4d7-f56a-4eeb-8ae1-ea3bdf084da3" CreationDate="2022-03-16T06:37:37.107" UserId="18138" Text="|opengl|gpu|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36531" PostHistoryTypeId="2" PostId="12571" RevisionGUID="e830ec5a-bb4b-4984-b2d3-bb57395dc2f9" CreationDate="2022-03-17T12:06:08.037" UserId="228" Text="I am reading through an old paper ([Interpolation for Polygon Texture Mapping and Shading][1]), cause it is mentioned in other papers I am reading.&#xD;&#xA;&#xD;&#xA;In section two we have the following steps to perform linear interpolation of parameters in screen space&#xD;&#xA;&#xD;&#xA;&gt; 1) Associate a record containing the paraemters of interest with each vertex of the polygon&#xD;&#xA;&gt; 2) For each transform object space coordinates to homogeneous space using screen space using 4x4 object to screen matrix, yielding the values $(xw,yw,zw,w)$.&#xD;&#xA;&gt; 3) Clip the polygon against plane equations for each of the six sides of the viewing frustum, linearly interpolating all the parameters when the new vertices are created.&#xD;&#xA;&gt; 4) Perform a homogenous division to compute $x = xw/w, y = yw/w, z = zw/w.&#xD;&#xA;&gt; 5) Scan convert in screen space, by linear interpolation of all the parameters using the parameter value at each pixel for shading.&#xD;&#xA;&#xD;&#xA;Following this procedure for texture mapping for example, according to the paper, it would produce artifacts like the following:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I understand what the artifact is, what I don't understand where (from the math) the artifact is coming from. Can anyone clarify somewhat where this is coming from?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.academia.edu/28684978/Interpolation_for_Polygon_Texture_Mapping_and_Shading&#xD;&#xA;  [2]: https://i.stack.imgur.com/hfMFf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36533" PostHistoryTypeId="1" PostId="12571" RevisionGUID="e830ec5a-bb4b-4984-b2d3-bb57395dc2f9" CreationDate="2022-03-17T12:06:08.037" UserId="228" Text="Polygon Rendering with Linear interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="36534" PostHistoryTypeId="3" PostId="12571" RevisionGUID="e830ec5a-bb4b-4984-b2d3-bb57395dc2f9" CreationDate="2022-03-17T12:06:08.037" UserId="228" Text="|texture|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36535" PostHistoryTypeId="5" PostId="12571" RevisionGUID="e68476ad-fefc-4d20-b223-9c60611bc0a1" CreationDate="2022-03-17T12:12:01.083" UserId="228" Comment="added 172 characters in body" Text="I am reading through an old paper ([Interpolation for Polygon Texture Mapping and Shading][1]), cause it is mentioned in other papers I am reading.&#xD;&#xA;&#xD;&#xA;In section two we have the following steps to perform linear interpolation of parameters in screen space&#xD;&#xA;&#xD;&#xA;&gt; 1) Associate a record containing the paraemters of interest with each vertex of the polygon&#xD;&#xA;&gt; 2) For each transform object space coordinates to homogeneous space using screen space using 4x4 object to screen matrix, yielding the values $(xw,yw,zw,w)$.&#xD;&#xA;&gt; 3) Clip the polygon against plane equations for each of the six sides of the viewing frustum, linearly interpolating all the parameters when the new vertices are created.&#xD;&#xA;&gt; 4) Perform a homogenous division to compute $x = xw/w, y = yw/w, z = zw/w.&#xD;&#xA;&gt; 5) Scan convert in screen space, by linear interpolation of all the parameters using the parameter value at each pixel for shading.&#xD;&#xA;&#xD;&#xA;Following this procedure for texture mapping for example, according to the paper, it would produce artifacts like the following:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I understand what the artifact is, what I don't understand where (from the math) the artifact is coming from. Can anyone clarify somewhat where this is coming from?&#xD;&#xA;&#xD;&#xA;Also I think the code associated with the procedure above is in&#xD;&#xA;[here][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.academia.edu/28684978/Interpolation_for_Polygon_Texture_Mapping_and_Shading&#xD;&#xA;  [2]: https://i.stack.imgur.com/hfMFf.png&#xD;&#xA;  [3]: https://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gems/PolyScan/poly_scan.c" ContentLicense="CC BY-SA 4.0" />
  <row Id="36536" PostHistoryTypeId="50" PostId="12259" RevisionGUID="0ce7eb79-ef85-4d58-bf00-5bb4d3d13b65" CreationDate="2022-03-18T15:07:05.683" UserId="-1" />
  <row Id="36538" PostHistoryTypeId="2" PostId="12572" RevisionGUID="5b7c5dd3-d350-4036-8d31-6265b8aa25e7" CreationDate="2022-03-19T03:50:52.660" UserId="18153" Text="I've implemented the marching squares algorithm following wikipedia &lt;https://en.wikipedia.org/wiki/Marching_squares&gt;. The output I got is a set of edges, to which each contouring cell contributes 0, 1, or 4 edges.&#xD;&#xA;&#xD;&#xA;So my question is how I modify or post-process this algorithm to obtain a set of distinct polygons from these edges? Oh and I want to do so in parallel.&#xD;&#xA;&#xD;&#xA;I guess the sequential approach would be to pick an edge and follow it until it comes back to the beginning, then move on to another unprocessed edge.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="36540" PostHistoryTypeId="1" PostId="12572" RevisionGUID="5b7c5dd3-d350-4036-8d31-6265b8aa25e7" CreationDate="2022-03-19T03:50:52.660" UserId="18153" Text="generate polygons after marching squares in parallel" ContentLicense="CC BY-SA 4.0" />
  <row Id="36541" PostHistoryTypeId="3" PostId="12572" RevisionGUID="5b7c5dd3-d350-4036-8d31-6265b8aa25e7" CreationDate="2022-03-19T03:50:52.660" UserId="18153" Text="|computational-geometry|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36547" PostHistoryTypeId="2" PostId="12574" RevisionGUID="40f3d1c8-bdaf-4205-a0db-9dd12105bf99" CreationDate="2022-03-20T05:27:47.953" UserId="18155" Text="I am a beginner in glsl and processing. I have a cube, can I know how to deform it using mathematical or progammatical functions?&#xD;&#xA;&#xD;&#xA;     void setup(){&#xD;&#xA;     size(500,500,P3D); &#xD;&#xA;     lightShader = loadShader(&quot;phFragmentShader.glsl&quot;, &quot;phVertexShader.glsl&quot;);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void draw(){&#xD;&#xA;     &#xD;&#xA;       shader(lightShader);&#xD;&#xA;       fill(125);&#xD;&#xA;       noStroke();&#xD;&#xA;      &#xD;&#xA;      rotateX(0.8);&#xD;&#xA;      rotateY(0.6);&#xD;&#xA;      rotateZ(0.1);&#xD;&#xA;      &#xD;&#xA;      &#xD;&#xA;       pointLight(255, 0, 0, 159, 272, 200);&#xD;&#xA;      // pointLight(255, 0, 0, mouseX, mouseY, 200);&#xD;&#xA;    &#xD;&#xA;      translate(250,250);&#xD;&#xA;    &#xD;&#xA;        box(100);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36549" PostHistoryTypeId="1" PostId="12574" RevisionGUID="40f3d1c8-bdaf-4205-a0db-9dd12105bf99" CreationDate="2022-03-20T05:27:47.953" UserId="18155" Text="How to deform an object in glsl? (processing)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36550" PostHistoryTypeId="3" PostId="12574" RevisionGUID="40f3d1c8-bdaf-4205-a0db-9dd12105bf99" CreationDate="2022-03-20T05:27:47.953" UserId="18155" Text="|opengl|glsl|processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36551" PostHistoryTypeId="2" PostId="12575" RevisionGUID="2ed995ce-9849-4bc4-adbd-5376f94e138b" CreationDate="2022-03-21T22:41:23.830" UserId="18168" Text="I'll admit it blew my mind when I first realized that you could actually enter a &quot;first-person mode&quot; in *Google Earth Pro*, and not just view the 3D maps from a floating camera in the air. But once the initial &quot;wow factor&quot; wears off, you quickly start to get annoyed and frustrated with how flawed it is.&#xD;&#xA;&#xD;&#xA;Allow me to give you a couple of random examples where I compare the ground-level 3D representation to the Street View photo of the same locations and angles:&#xD;&#xA;&#xD;&#xA;[![XXXXXX][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;There are *much* worse examples, but I wanted to pick locations that actually have a Street View to show the comparison. For example, any kind of forest path location (for example) which I've been to in real life and which is not an actual street where Google cars can go are just bizarre, surreal nightmares of forest textures looking like mountains shooting into each other, like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Yes, you can argue that it's amazing that this can exist at all, and it's &quot;not really meant to be inspected so closely and from a first-person perspective&quot;, but that's at least what *I* personally am interested in. My dream is to be able to walk around in something that looks like &quot;Street View&quot; but is actually a fully walkable 3D environment. Clearly, the current technology is lightyears from that dream.&#xD;&#xA;&#xD;&#xA;But what exactly is limiting the realism? They seem to somewhat be able to make up &quot;rough&quot; representations of buildings and geometry. They certainly seem to have no lack of *data* to work with. So why does it look so &quot;rough&quot;? What is limiting their current program that analyses all their collected and bought data from producing much more clean and accurate representations of the surroundings?&#xD;&#xA;&#xD;&#xA;I haven't been able to find any video where engineers at Google talk for hours about how exactly they make these 3D environments, but it seems odd to me that they are able to get them this &quot;good&quot;, yet still fail at the end of the day.&#xD;&#xA;&#xD;&#xA;Again, it looks very cool at first, but you soon realize that it's useless for anything but a novelty and &quot;maaaaybe this one place looks pretty cool&quot;, but then you just get disappointed when it's just a big mess, like every other place. Unless you exit the mode and let the camera float around in the air, but again, that's not what I'm after. I want the &quot;FPS freedom&quot; controls with breath-taking detail. It would be insanely cool, but I have a terrible feeling that I'll be dead and gone when this ever becomes possible.&#xD;&#xA;&#xD;&#xA;What are the main limiting factors?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QtGUX.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7ouV4.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/gaZDX.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/eZITZ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/9kWca.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36553" PostHistoryTypeId="1" PostId="12575" RevisionGUID="2ed995ce-9849-4bc4-adbd-5376f94e138b" CreationDate="2022-03-21T22:41:23.830" UserId="18168" Text="What stops the auto-generated 3D worlds of Google Earth Pro from being MUCH more detailed and accurate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36554" PostHistoryTypeId="3" PostId="12575" RevisionGUID="2ed995ce-9849-4bc4-adbd-5376f94e138b" CreationDate="2022-03-21T22:41:23.830" UserId="18168" Text="|3d|geometry|virtual-reality|photo-realistic|realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36555" PostHistoryTypeId="2" PostId="12576" RevisionGUID="846c54cb-307d-4fdb-aac5-5dbfae7fde67" CreationDate="2022-03-22T09:42:45.500" UserId="13273" Text="I am using layered rendering for all my light sources to avoid rendering multiple times.&#xD;&#xA;I have `lightSourceCount` many point lights and one sun, which is implemented as an orthographic light source (due to the large distance).&#xD;&#xA;The sun light should be implemented as cascaded shadow mapping (4 cascades), because I would like to render landscapes. &#xD;&#xA;The shadowmap resolution and format of the point lights and the cascaded shadow maps are equal.&#xD;&#xA;&#xD;&#xA;Is it possible to define a GL_TEXTURE_2D_ARRAY with (`lightSourceCount` * 6 + 4) layers as shadow maps. Render the scenario using layered rendering to fill these shadow maps. And afterwards use the first `lightSourceCount` * 6 layeres as a GL_TEXTURE_CUBEMAP_ARRAY with `lightSourceCount` layers within GLSL to be able to use &#xD;&#xA;`gvec4 texture(gsamplerCubeArray sampler, vec4 P, [float bias]);` while the last 4 layers are able to be used with `gvec4 texture(gsampler2DArray sampler, vec3 P, [float bias]);`?&#xD;&#xA;&#xD;&#xA;If yes, how can I do that? Can I just bind the GL_TEXTURE_2D_ARRAY as a GL_TEXTURE_CUBEMAP_ARRAY?&#xD;&#xA;And use the last 4 layers by binding the same Texture as GL_TEXTURE_2D_ARRAY and access the last 4 layers by using `texture(gsampler2DArray sampler, vec3(uvCoordinate, lightSourceCount * 6 + currentTexture))`?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36557" PostHistoryTypeId="1" PostId="12576" RevisionGUID="846c54cb-307d-4fdb-aac5-5dbfae7fde67" CreationDate="2022-03-22T09:42:45.500" UserId="13273" Text="using parts of GL_TEXTURE_2D_ARRAY as GL_TEXTURE_CUBEMAP_ARRAY" ContentLicense="CC BY-SA 4.0" />
  <row Id="36558" PostHistoryTypeId="3" PostId="12576" RevisionGUID="846c54cb-307d-4fdb-aac5-5dbfae7fde67" CreationDate="2022-03-22T09:42:45.500" UserId="13273" Text="|opengl|texture|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36559" PostHistoryTypeId="2" PostId="12577" RevisionGUID="1d5eb9d1-c79f-4237-859b-5899ad44a062" CreationDate="2022-03-22T13:32:38.700" UserId="2654" Text="You can use [view textures][1] to accomplish what you're talking about. You create a 2D array texture and give it the number of layers you want. This is the base texture.&#xD;&#xA;&#xD;&#xA;You can then construct two restricted views of the base texture. The first is a cubemap array texture using layers 0 to `lightSourceCount * 6`. The second is a 2D array texture using layers `lightSourceCount * 6` to `lightSourceCount * 6 + 4`.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Texture_Storage#Texture_views&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36561" PostHistoryTypeId="2" PostId="12578" RevisionGUID="904bceb0-7c9d-452d-a23d-2c440773e833" CreationDate="2022-03-22T14:57:22.383" UserId="7952" Text="The first piece of deforming a mesh is the mesh itself. A very simple mesh with very few vertices can be deformed but the results will be limited, there is only so much that can be done with 8 vertices. (The code posted in the question refers to a box, usually those have only 8 unique vertices which is a good simple object to use when setting up/learning graphics). But to do any interesting deformations a mesh that is nicely tessellated is needed. This can be done by adding tessellation shaders, which aren't to hard to setup but can be confusing for someone just learning GLSL/OpenGL. The other choice is to replace the box with something that has more triangles, a few hundred usually is enough to start getting interesting results.&#xD;&#xA;&#xD;&#xA;The code to do deformations come in so many forms that I think there is literally an infinite number of possibilities. I will list a few simple techniques to hopefully get you started.&#xD;&#xA;&#xD;&#xA;The first &quot;class&quot; of deformations are simple matrix deformations that can be created by adding an extra matrix into the usual MVP, and the simplest form I can think of is a non-symmetric scale such as:&#xD;&#xA;&#xD;&#xA;\begin{equation*}&#xD;&#xA;D_scale = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; y &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; z &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{equation*}&#xD;&#xA;&#xD;&#xA;Where x,y and z are not equal to each other. Something like $\{0.6, 1.3, 2.6\}$.&#xD;&#xA;&#xD;&#xA;A shear/skew matrix along a specific axes is of the form:&#xD;&#xA;\begin{equation*}&#xD;&#xA;D_skew = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; tan(\theta) &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\end{equation*}&#xD;&#xA;&#xD;&#xA;Combine skews and non-uniform scales by multiplying them together.&#xD;&#xA;&#xD;&#xA;    D_combined = D_skew * D_scale; // order matters here, swap them around for different effects.&#xD;&#xA;&#xD;&#xA;The vertex shader can move/wiggle vertices around with a simple noise generator. Keep the movement very small or the mesh will just look a mess of unconnected triangles. Here is a nice intro to [noise generators][1].&#xD;&#xA;&#xD;&#xA;    // to use the generated noise do something similar to the below:&#xD;&#xA;    vec4 generated_noise = MakeNoise( vertex_input_position);&#xD;&#xA;    float scale = 0.02;  // scale the noise up or down&#xD;&#xA;    vec4 new_vertex_position = vertex_input_position + generated_noise * scale;&#xD;&#xA;&#xD;&#xA;    // now process the new vertex position as usual...&#xD;&#xA;    vec4 output_vertex_position = MVP * new_vertex_position;&#xD;&#xA;&#xD;&#xA;Another form of mesh deformation are simple functions that move the vertices around using math formulas. A personal favorite is to move all the vertices along a straight line out to some limit. The line is made by creating a vector from a point (usually at the center of the mesh) to the vertex that is being processed, normalize it, multiply by a scale factor, then clamp. This effectively creates a sphere and is very easy to animate by passing the current time to the shader through a uniform variable. Use $cos(time)*scale$ to make the object &quot;throb&quot;.&#xD;&#xA;&#xD;&#xA;This post has gotten a lot longer then I expected so I won't post any code for this last one. Anyway, hopefully this post illustrates that the possibilities for deformations are limited only by the coders imagination.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://thebookofshaders.com/11/" ContentLicense="CC BY-SA 4.0" />
  <row Id="36563" PostHistoryTypeId="2" PostId="12579" RevisionGUID="cf6880f1-6aea-4ccc-87d9-f30617ca3aa6" CreationDate="2022-03-22T16:17:45.053" UserId="7952" Text="These views are generated using photogrammetry. Usually by vehicles that are colleting GPS data about the streets at the same time. As the data collection vehicle drives by it take multiple photo's which are geolocated with the GPS data. The photo's are then used to generate rough 3D views.&#xD;&#xA;&#xD;&#xA;Photogrammetry can be generated with just a handful of views but the results are limited to the quantity, quality (not the same quality as our eyes see though) and angles of the images, and to the ability of the software generating the views to correlate the images. It is much more difficult to correlate multiple images of a forest scene, then it is for a row of nice geometric objects like cars, hedges and homes.&#xD;&#xA;&#xD;&#xA;This process is fundamentally limited because of the way the data is being collected. Typically a high quality photogram needs many angles and many photos to create a detailed image. A car driving down the road can only get so many images of its surroundings, with very limited angles. The results will probably improve as the software improves but until they find a way to gather much more data the 3D views will probably only improve incrementally. That said, generating 3D views of streets from a few pictures taken while driving by is pretty amazing stuff." ContentLicense="CC BY-SA 4.0" />
  <row Id="36565" PostHistoryTypeId="2" PostId="12580" RevisionGUID="5eebc28e-8d3d-4914-a258-9576d279ccad" CreationDate="2022-03-22T19:40:12.127" UserId="17045" Text="I'm writing a simple text editor using Vulkan for rendering, and I'm seeing some strange outline around the rendered letters if I take a screenshot of the text and zoom in, which bothers me because I can't explain why it's there.&#xD;&#xA;&#xD;&#xA;Here's what RenderDoc shows in the texture view (note that in the pixel context view at the bottom right there's no outline around the text)&#xD;&#xA;[![RenderDoc textyre view][1]][1]&#xD;&#xA;&#xD;&#xA;However, if I take a screenshot and zoom in, I'll see this border around the letters:&#xD;&#xA;[![text border][2]][2]&#xD;&#xA;&#xD;&#xA;I use a pre-rendered font atlas in a texture stored as R8_UNORM. Then I use a very basic shader which takes the texture and produces a pixel with premultiplied alpha, ready to be blended by just adding the colors of src and dest:&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    layout(set = 1, binding = 0) uniform sampler2D texSampler;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec2 v_tex_coord;&#xD;&#xA;    layout(location = 1) in vec3 v_color;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) out vec4 f_color;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        f_color = vec4(v_color * texture(texSampler, v_tex_coord).a, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm puzzled and out of ideas on why this outline is there - I don't see why the pixels next to text border would suddenly become darker when I'm only adding positive color components and none of them are negative (just to make sure there are no negative components I tried modifying the shader and took absolute value of every component with exactly the same result).&#xD;&#xA;&#xD;&#xA;In case it matters, my swapchain surface format is B8G8R8A8_UNORM and the colorspace is SRGB_NONLINEAR_KHR. The colors are exactly what I expect them to be so I assumed that gamma-wise it's OK but maybe I'm wrong.&#xD;&#xA;&#xD;&#xA;Would appreciate any help with this.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDHpa.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2cgt1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36567" PostHistoryTypeId="1" PostId="12580" RevisionGUID="5eebc28e-8d3d-4914-a258-9576d279ccad" CreationDate="2022-03-22T19:40:12.127" UserId="17045" Text="Text rendering - weird outline when zoomed" ContentLicense="CC BY-SA 4.0" />
  <row Id="36568" PostHistoryTypeId="3" PostId="12580" RevisionGUID="5eebc28e-8d3d-4914-a258-9576d279ccad" CreationDate="2022-03-22T19:40:12.127" UserId="17045" Text="|rendering|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36569" PostHistoryTypeId="5" PostId="12580" RevisionGUID="76fdd16b-6769-47e7-9a0f-16d241aa8993" CreationDate="2022-03-22T19:58:43.283" UserId="17045" Comment="added 328 characters in body" Text="I'm writing a simple text editor using Vulkan for rendering, and I'm seeing some strange outline around the rendered letters if I take a screenshot of the text and zoom in, which bothers me because I can't explain why it's there.&#xD;&#xA;&#xD;&#xA;Here's what RenderDoc shows in the texture view (note that in the pixel context view at the bottom right there's no outline around the text)&#xD;&#xA;[![RenderDoc textyre view][1]][1]&#xD;&#xA;&#xD;&#xA;However, if I take a screenshot and zoom in, I'll see this border around the letters:&#xD;&#xA;[![text border][2]][2]&#xD;&#xA;&#xD;&#xA;I use a pre-rendered font atlas in a texture stored as R8_UNORM. Then I use a very basic shader which takes the texture and produces a pixel with premultiplied alpha, ready to be blended by just adding the colors of src and dest:&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    layout(set = 1, binding = 0) uniform sampler2D texSampler;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec2 v_tex_coord;&#xD;&#xA;    layout(location = 1) in vec3 v_color;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) out vec4 f_color;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        f_color = vec4(v_color * texture(texSampler, v_tex_coord).a, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm puzzled and out of ideas on why this outline is there - I don't see why the pixels next to text border would suddenly become darker when I'm only adding positive color components and none of them are negative (just to make sure there are no negative components I tried modifying the shader and took absolute value of every component with exactly the same result).&#xD;&#xA;&#xD;&#xA;In case it matters, my swapchain surface format is B8G8R8A8_UNORM and the colorspace is SRGB_NONLINEAR_KHR. The colors are exactly what I expect them to be so I assumed that gamma-wise it's OK but maybe I'm wrong.&#xD;&#xA;&#xD;&#xA;Would appreciate any help with this.&#xD;&#xA;&#xD;&#xA;UPD. I just made it work on my office Macbook and there's no outline there! So it must be something to do with either my window surface on windows or even with screenshot-taking apps (I've tried snipping tool, printscr and snip &amp; sketch)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDHpa.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2cgt1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jFIgN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36570" PostHistoryTypeId="2" PostId="12581" RevisionGUID="0dd3007d-3927-4c52-93b4-b668a16a448b" CreationDate="2022-03-22T21:35:57.370" UserId="18176" Text="lately I have been learning about photometry, and everywhere I look I see a BRDF written according to the &quot;dichromatic model&quot;. Roughly speaking: $$\rho= \rho_D+\rho_S \cdot (...)$$&#xD;&#xA;&#xD;&#xA;for some $(...)$ function depending on the halfway vector and so on. My question would be: is this model physically based, or is it just a modeling choice, or as I suspect, a mixture of the two? Under which assumptions would it then be invalid?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36572" PostHistoryTypeId="1" PostId="12581" RevisionGUID="0dd3007d-3927-4c52-93b4-b668a16a448b" CreationDate="2022-03-22T21:35:57.370" UserId="18176" Text="Is the dichromatic model physically based?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36573" PostHistoryTypeId="3" PostId="12581" RevisionGUID="0dd3007d-3927-4c52-93b4-b668a16a448b" CreationDate="2022-03-22T21:35:57.370" UserId="18176" Text="|rendering|brdf|physically-based|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36574" PostHistoryTypeId="5" PostId="12580" RevisionGUID="b774a9c1-9b36-4a52-b483-5da180bcca76" CreationDate="2022-03-24T05:20:42.280" UserId="17045" Comment="edited body" Text="I'm writing a simple text editor using Vulkan for rendering, and I'm seeing some strange outline around the rendered letters if I take a screenshot of the text and zoom in, which bothers me because I can't explain why it's there.&#xD;&#xA;&#xD;&#xA;Here's what RenderDoc shows in the texture view (note that in the pixel context view at the bottom right there's no outline around the text)&#xD;&#xA;[![RenderDoc textyre view][1]][1]&#xD;&#xA;&#xD;&#xA;However, if I take a screenshot and zoom in, I'll see this border around the letters:&#xD;&#xA;[![text border][2]][2]&#xD;&#xA;&#xD;&#xA;I use a pre-rendered font atlas in a texture stored as R8_UNORM. Then I use a very basic shader which takes the texture and produces a pixel with premultiplied alpha, ready to be blended by just adding the colors of src and dest:&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    layout(set = 1, binding = 0) uniform sampler2D texSampler;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) in vec2 v_tex_coord;&#xD;&#xA;    layout(location = 1) in vec3 v_color;&#xD;&#xA;&#xD;&#xA;    layout(location = 0) out vec4 f_color;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        f_color = vec4(v_color, 1.0) * texture(texSampler, v_tex_coord).a;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I'm puzzled and out of ideas on why this outline is there - I don't see why the pixels next to text border would suddenly become darker when I'm only adding positive color components and none of them are negative (just to make sure there are no negative components I tried modifying the shader and took absolute value of every component with exactly the same result).&#xD;&#xA;&#xD;&#xA;In case it matters, my swapchain surface format is B8G8R8A8_UNORM and the colorspace is SRGB_NONLINEAR_KHR. The colors are exactly what I expect them to be so I assumed that gamma-wise it's OK but maybe I'm wrong.&#xD;&#xA;&#xD;&#xA;Would appreciate any help with this.&#xD;&#xA;&#xD;&#xA;UPD. I just made it work on my office Macbook and there's no outline there! So it must be something to do with either my window surface on windows or even with screenshot-taking apps (I've tried snipping tool, printscr and snip &amp; sketch)&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDHpa.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2cgt1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/jFIgN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36579" PostHistoryTypeId="5" PostId="12572" RevisionGUID="f116890d-42c2-4feb-9ad5-a046f4b7146f" CreationDate="2022-03-24T10:43:55.313" UserId="18004" Comment="Text and tag" Text="I've implemented the marching squares algorithm following Wikipedia's &lt;https://en.wikipedia.org/wiki/Marching_squares&gt;. The output I got is a set of edges, to which each contouring cell contributes 0, 1, or 4 edges.&#xD;&#xA;&#xD;&#xA;How do I modify or post-process this algorithm to obtain a set of distinct polygons from these edges?  &#xD;&#xA;Oh and I want to do so in parallel.&#xD;&#xA;&#xD;&#xA;I guess the sequential approach would be to pick an edge and follow it until it comes back to the beginning, then move on to another unprocessed edge." ContentLicense="CC BY-SA 4.0" />
  <row Id="36580" PostHistoryTypeId="4" PostId="12572" RevisionGUID="f116890d-42c2-4feb-9ad5-a046f4b7146f" CreationDate="2022-03-24T10:43:55.313" UserId="18004" Comment="Text and tag" Text="Generate polygons after marching squares in parallel" ContentLicense="CC BY-SA 4.0" />
  <row Id="36581" PostHistoryTypeId="6" PostId="12572" RevisionGUID="f116890d-42c2-4feb-9ad5-a046f4b7146f" CreationDate="2022-03-24T10:43:55.313" UserId="18004" Comment="Text and tag" Text="|computational-geometry|polygon|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36582" PostHistoryTypeId="24" PostId="12572" RevisionGUID="f116890d-42c2-4feb-9ad5-a046f4b7146f" CreationDate="2022-03-24T10:43:55.313" Comment="Proposed by 18004 approved by 13095 edit id of 577" ContentLicense="CC BY-SA 4.0" />
  <row Id="36583" PostHistoryTypeId="2" PostId="12583" RevisionGUID="d63bdd15-e617-4a17-ba5f-a1df6d7e772d" CreationDate="2022-03-24T11:06:12.313" UserId="3123" Text="due to some features in materials I need to create my own directional shadow map.&#xD;&#xA;&#xD;&#xA;Everything seems to work ok, until the moment where I compare depths.&#xD;&#xA;&#xD;&#xA;First I add camera component to directional light with RenderTexture:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;then in code, I set this texture and camera projection matrix as global variables for shaders:&#xD;&#xA;```&#xD;&#xA;Camera shadowCaptureCamera = GetComponent&lt;Camera&gt;();&#xD;&#xA;Shader.SetGlobalTexture(&quot;_CustomShadowsTex&quot;, shadowCaptureCamera.targetTexture, UnityEngine.Rendering.RenderTextureSubElement.Depth);&#xD;&#xA;           &#xD;&#xA;Matrix4x4 worldToClipMatrix = shadowCaptureCamera.projectionMatrix * shadowCaptureCamera.worldToCameraMatrix;&#xD;&#xA;Shader.SetGlobalMatrix(&quot;_CustomShadowsMatrix&quot;, worldToClipMatrix);&#xD;&#xA;```&#xD;&#xA;Then in shaders I do this:&#xD;&#xA;```&#xD;&#xA;v2f vert(appdata v)&#xD;&#xA;{&#xD;&#xA;    v2f o;&#xD;&#xA;    o.pos = UnityObjectToClipPos(v.vertex);&#xD;&#xA;    o.uv = TRANSFORM_TEX(v.uv, _MainTex);&#xD;&#xA;&#xD;&#xA;    float4 worldPos = mul( unity_ObjectToWorld, float4( v.vertex.xyz, 1.0f) );&#xD;&#xA;    float4 shadowPosition = mul( _CustomShadowsMatrix, worldPos );&#xD;&#xA;    shadowPosition.xyz /= shadowPosition.w;&#xD;&#xA;    shadowPosition.xy = shadowPosition.xy * 0.5f + 0.5f;&#xD;&#xA;    o.shadowMapUV = shadowPosition;&#xD;&#xA;    return o;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;fixed4 frag(v2f i) : SV_Target&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;    ......&#xD;&#xA;&#xD;&#xA;    float shadowDepth = tex2D( _CustomShadowsTex, i.shadowMapUV.xy ).r;             &#xD;&#xA;    float atten = shadowDepth &gt; abs(i.shadowMapUV.z) ? 1.0f : 0.0f;&#xD;&#xA;    return atten;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;Everything has value 1.0f.&#xD;&#xA;&#xD;&#xA;Any idea what's wrong? It samples shadow at correct place, but something is wrong with values. I'm also not sure why i.shadowMapUV.z is &lt;0.f. Looking at matrix's values it shouldn't be.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qTZMn.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/WPyh7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36585" PostHistoryTypeId="1" PostId="12583" RevisionGUID="d63bdd15-e617-4a17-ba5f-a1df6d7e772d" CreationDate="2022-03-24T11:06:12.313" UserId="3123" Text="Unity - custom shadow from sun" ContentLicense="CC BY-SA 4.0" />
  <row Id="36586" PostHistoryTypeId="3" PostId="12583" RevisionGUID="d63bdd15-e617-4a17-ba5f-a1df6d7e772d" CreationDate="2022-03-24T11:06:12.313" UserId="3123" Text="|shader|projections|unity|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36587" PostHistoryTypeId="2" PostId="12584" RevisionGUID="98037f7b-2556-42f4-b71a-76bccf327dee" CreationDate="2022-03-24T11:15:19.600" UserId="18184" Text="Because OpenGL is deprecating, I was wondering where to position myself to keep on learning graphics programming in the years to come on the same level of abstraction as OpenGL ? I don't want to go low-level with endless Vulkan / GPU settings, and would like to be in more or less the abstraction that OpenGL offers. What graphics library to choose ? Any good middleware that is suiting on top of Vulkan ? Or maybe I just have to learn Vulkan, lol. " ContentLicense="CC BY-SA 4.0" />
  <row Id="36589" PostHistoryTypeId="1" PostId="12584" RevisionGUID="98037f7b-2556-42f4-b71a-76bccf327dee" CreationDate="2022-03-24T11:15:19.600" UserId="18184" Text="Vulkan abstraction similar to OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36590" PostHistoryTypeId="3" PostId="12584" RevisionGUID="98037f7b-2556-42f4-b71a-76bccf327dee" CreationDate="2022-03-24T11:15:19.600" UserId="18184" Text="|opengl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36591" PostHistoryTypeId="2" PostId="12585" RevisionGUID="da66c97f-f960-47e2-9468-d377fc2fb021" CreationDate="2022-03-24T16:32:34.490" UserId="48" Text="It's a modeling choice, but one that allows for a reasonably good fit to a variety of real-world materials through different choices of the parameters.&#xD;&#xA;&#xD;&#xA;Many common non-metallic materials can be roughly thought of as being something like a translucent medium with some pigmented particles embedded in it that provide its color. This includes plastics, wood, paints, ceramics, even concrete and asphalt. In such materials, the surface (which can be smooth or rough) produces some specular reflection according to the Fresnel principle. The light which is transmitted (refracted) into the material then strikes the pigmented particles, scatters around randomly many times, and becomes near isotropic by the time it scatters back out (loses any directional distribution from the incoming light).&#xD;&#xA;&#xD;&#xA;![illustration of specular and diffuse scattering](https://i.stack.imgur.com/edqwv.png)&#xD;&#xA;&#xD;&#xA;This slide from [Naty Hoffman - Physics and Math of Shading](https://blog.selfshadow.com/publications/s2015-shading-course/hoffman/s2015_pbs_physics_math_slides.pdf) (p. 39) illustrates specular reflection/refraction with the orange arrows, and diffuse scattering with the blue/green ones.&#xD;&#xA;&#xD;&#xA;Such materials can be modeled by a BRDF like the one you mentioned, by setting $\rho_S$ to the color induced by the specular reflection, and $\rho_D$ to the overall color produced by the diffuse scattering. For non-metals, the specular color is usually just a monochrome value with a narrow range between 0.02 and 0.05, depending on the density of the material.&#xD;&#xA;&#xD;&#xA;Technically, because light that reflects specularly is not available to illuminate the diffuse part of the material, $\rho_D$ also ought to have a factor on it that depends on the light angle and reduces it by the total amount of specular reflection for that light angle. But because non-metals have a relatively low amount of specular overall (especially for rougher surfaces), it's often possible to get away without this and have the result look plausible. If we're trying to get more physically accurate, this is an effect that should be accounted for, though.&#xD;&#xA;&#xD;&#xA;For metals, they have essentially all of their reflection through the specular component, and no diffuse component, as metals aren't transparent (unless you get to very, _very_ thin metal foils that aren't really found in everyday materials). So metals can be modeled by setting $\rho_D = 0$ and $\rho_S$ to the reflection color of the metal.&#xD;&#xA;&#xD;&#xA;If you're interested in the physical basis of material models, I'd recommend looking at the rest of those slides from Naty Hoffman's talk that I linked above, as well as this other talk by him: [Recent Advances in Physically Based Shading (2016)](https://blog.selfshadow.com/publications/s2016-shading-course/hoffman/s2016_pbs_recent_advances_v2.pdf). The SIGGRAPH [Physically Based Shading courses](https://blog.selfshadow.com/publications/) also have many more interesting talks on different aspects of this issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="36593" PostHistoryTypeId="2" PostId="12586" RevisionGUID="0fa32454-2da0-4799-af29-2835539fc7fb" CreationDate="2022-03-24T16:33:40.303" UserId="3123" Text="Ok, I got it.&#xD;&#xA;`i.shadowMapUV.z` is &lt; 0.f because it's mapped to -1;1 between near;far.&#xD;&#xA;Forward is also at -Z, so correct way to calculate `shadowPosition` is:&#xD;&#xA;```&#xD;&#xA;float4 shadowPosition= mul( _CustomShadowsMatrix, float4(worldPos, 1.f) );&#xD;&#xA;shadowPosition.xyz /= shadowPosition.w;&#xD;&#xA;shadowPosition.xy = shadowPosition.xy * 0.5f + 0.5f;&#xD;&#xA;shadowPosition.z = -shadowPosition.z * 0.5f + 0.5f;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="36595" PostHistoryTypeId="50" PostId="7804" RevisionGUID="d96855a7-f5a5-4b81-b7f7-6075e0eecc20" CreationDate="2022-03-24T19:09:10.950" UserId="-1" />
  <row Id="36597" PostHistoryTypeId="50" PostId="9413" RevisionGUID="370b0bdb-dfc7-44a6-a2ed-3e814267747d" CreationDate="2022-03-25T03:01:00.097" UserId="-1" />
  <row Id="36602" PostHistoryTypeId="50" PostId="9626" RevisionGUID="a211d21c-dbbd-4357-835e-b340b960703d" CreationDate="2022-03-25T14:09:30.960" UserId="-1" />
  <row Id="36603" PostHistoryTypeId="50" PostId="9307" RevisionGUID="fef8bb82-0764-456c-94b6-dc9864e1e2f4" CreationDate="2022-03-25T21:02:20.227" UserId="-1" />
  <row Id="36605" PostHistoryTypeId="2" PostId="12588" RevisionGUID="8b3ed56e-8b76-4a9f-b872-4ece3508e7a2" CreationDate="2022-03-25T23:49:21.707" UserId="1608" Text="If this is still of interest to some readers in the future), I would recommend that you look at the lesson on ray-marching / volume rendering for developers on scratchapixel.&#xD;&#xA;&#xD;&#xA;https://www.scratchapixel.com/lessons/advanced-rendering/volume-rendering-for-developers/intro-volume-rendering&#xD;&#xA;&#xD;&#xA;It explains how ray-marching works and also gives info on how to render volumetric objects with varying volume density (including voxel grids). Hope it helps." ContentLicense="CC BY-SA 4.0" />
  <row Id="36609" PostHistoryTypeId="50" PostId="10535" RevisionGUID="5e8d3ae2-6fd7-4747-b59a-d8f0cee02adf" CreationDate="2022-03-26T05:00:35.070" UserId="-1" />
  <row Id="36618" PostHistoryTypeId="2" PostId="12591" RevisionGUID="9ae43e83-d28a-4c38-86fe-7a180fc2bf23" CreationDate="2022-03-26T21:39:49.813" UserId="9522" Text="Bowyer–Watson algorithm might be the most famous method for computing the Delaunay triangulation of a finite set of points in any number of dimensions. Its [Wikipedia][1] page and most textbooks on unstructured meshing [1] introduced it as the same way in the original article of Watson's [2]. However, when I looked into Bowyer's original article [3], it seems to me his version is different from Watson's version. Are they really equivalent? If so, how can they be converted into each other?&#xD;&#xA;&#xD;&#xA;Bowyer's version:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Watson's version:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;[1] Farrashkhalvat, M., and J. P. Miles. Basic Structured Grid Generation: With an introduction to unstructured grid generation. Elsevier, 2003.&#xD;&#xA;&#xD;&#xA;[2] Watson, David F. (1981). &quot;Computing the n-dimensional Delaunay tessellation with application to Voronoi polytopes&quot;. Comput. J. 24 (2): 167–172. doi:10.1093/comjnl/24.2.167&#xD;&#xA;&#xD;&#xA;[3] Bowyer, Adrian (1981). &quot;Computing Dirichlet tessellations&quot;. Comput. J. 24 (2): 162–166. doi:10.1093/comjnl/24.2.162&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bowyer%E2%80%93Watson_algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/p2mxN.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Oymws.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/SThvv.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/xpZkd.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/ZVh97.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36620" PostHistoryTypeId="1" PostId="12591" RevisionGUID="9ae43e83-d28a-4c38-86fe-7a180fc2bf23" CreationDate="2022-03-26T21:39:49.813" UserId="9522" Text="Why the Bowyer's version and Watson's version of computing the Delaunay tessellation are equivalent?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36621" PostHistoryTypeId="3" PostId="12591" RevisionGUID="9ae43e83-d28a-4c38-86fe-7a180fc2bf23" CreationDate="2022-03-26T21:39:49.813" UserId="9522" Text="|computational-geometry|mesh|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36622" PostHistoryTypeId="50" PostId="12286" RevisionGUID="f9f67379-7ec3-4a1c-b136-75834ab13e4b" CreationDate="2022-03-27T08:07:45.633" UserId="-1" />
  <row Id="36623" PostHistoryTypeId="2" PostId="12592" RevisionGUID="0c1dc3fb-8846-429c-912c-d0b046b390f9" CreationDate="2022-03-28T00:32:55.643" UserId="48" Text="Bowyer's version looks like it's expressed in terms of the vertices of a Voronoi diagram. Voronoi diagrams and Delaunay triangulations are &quot;dual&quot; to each other, meaning that each vertex of the Voronoi diagram corresponds to one triangle of the Delaunay triangulation. In fact, the Voronoi vertex is at the circumcenter of the corresponding Delaunay triangle.&#xD;&#xA;&#xD;&#xA;So, when Bowyer speaks of removing any &quot;vertex that is nearer to the new point than to its forming points&quot;, that's the same thing as removing triangles (simplices) that have the new point within their circumcircle (circumsphere).&#xD;&#xA;&#xD;&#xA;In both articles, the process of finding new vertices/simplices is, uhh, not exceptionally cleary explained. But if you squint a bit, they're both talking about filling in the &quot;hole&quot; created by deleting the old vertices/simplices, by combining the new point with each of the edges around the &quot;hole&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="36629" PostHistoryTypeId="2" PostId="12594" RevisionGUID="5d00b0cf-62d3-4119-98a3-de4fccceafe4" CreationDate="2022-03-28T19:16:42.727" UserId="18201" Text="I'm studying coordinate transformations from the book Fundamentals Of Computer Graphics - Peter Shirley, Steve Marschner&#xD;&#xA;&#xD;&#xA;The book first shows&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;It then says: &quot;We call this matrix the frame-to-canonical matrix for the (u, v) frame. It takes points expressed in the (u,v) frame and converts them to the same points ex- pressed in the canonical frame.&quot;&#xD;&#xA;&#xD;&#xA;Really confused by this since &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;and it seems like we get a contradiction if we let the shift be 0 for the images above.&#xD;&#xA;&#xD;&#xA;Is something really wrong or am I missing something?&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c7Rdh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/F0yMx.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/kStgf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36631" PostHistoryTypeId="1" PostId="12594" RevisionGUID="5d00b0cf-62d3-4119-98a3-de4fccceafe4" CreationDate="2022-03-28T19:16:42.727" UserId="18201" Text="Confused with Coordinate Transformations" ContentLicense="CC BY-SA 4.0" />
  <row Id="36632" PostHistoryTypeId="3" PostId="12594" RevisionGUID="5d00b0cf-62d3-4119-98a3-de4fccceafe4" CreationDate="2022-03-28T19:16:42.727" UserId="18201" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36633" PostHistoryTypeId="2" PostId="12595" RevisionGUID="194dffff-b6fa-4f4f-850b-49b68d372539" CreationDate="2022-03-28T21:55:24.547" UserId="18203" Text="I think that I see what you mean. For me, the correct &quot;change of basis&quot;, going from $(x,y)$ to $(u,v)$ does not take into account a &quot;translation&quot; of the basis into another: the origin of the basis is ignored (it is not even in the definition of what a basis is). So the second paragraph is the most accurate mathematically speaking: the only thing that matters is the rotation between the basis vectors (assuming all basis vectors have the same length).&#xD;&#xA;&#xD;&#xA;However, in practice in Graphics, it is more convenient to attach different basis to different origins points. To account for that, you now need the first formula, which is a change of basis plus a translation: &#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v \\&#xD;&#xA; y_u&amp; y_v \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix} &#xD;&#xA;= R \begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This writting is quite heavy, so an additional component is usually used to add translation transformations, and that leads to the formula that is in the book:&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p\\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v&amp;x_e \\&#xD;&#xA; y_u&amp; y_v&amp;y_e \\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p\\1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;(For 3D basis, it would lead to matrices with four components.)&#xD;&#xA;&#xD;&#xA;I hope that it helps?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36635" PostHistoryTypeId="5" PostId="12595" RevisionGUID="517b3fab-5b24-4daa-89ea-6c5442e36d4c" CreationDate="2022-03-28T22:05:01.443" UserId="18203" Comment="deleted 1 character in body" Text="I think that I see what you mean. For me, the correct &quot;change of basis&quot;, going from $(x,y)$ to $(u,v)$ does not take into account a &quot;translation&quot; of the basis into another: the origin of the basis is ignored (it is not even in the definition of what a basis is). So the second paragraph is the most accurate mathematically speaking: the only thing that matters is the rotation between the basis vectors (assuming all basis vectors have the same length).&#xD;&#xA;&#xD;&#xA;However, in practice in Graphics, it is more convenient to attach different basis to different origins points. To account for that, you now need the first formula, which is a change of basis plus a translation: &#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v \\&#xD;&#xA; y_u&amp; y_v \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix} &#xD;&#xA;= R \begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This writting is quite heavy, so an additional component is usually used to add translation transformations, and that leads to the formula that is in the book:&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p\\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v&amp;x_e \\&#xD;&#xA; y_u&amp; y_v&amp;y_e \\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p\\1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;(For 3D basis, it would lead to matrices with 4x4 components.)&#xD;&#xA;&#xD;&#xA;I hope that it helps?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36636" PostHistoryTypeId="50" PostId="5996" RevisionGUID="437af8c7-7fc0-4879-8f87-7373641aeed6" CreationDate="2022-03-29T16:05:05.407" UserId="-1" />
  <row Id="36637" PostHistoryTypeId="5" PostId="12595" RevisionGUID="458f22f2-8c3c-465c-8959-8d4da09f2785" CreationDate="2022-03-29T18:29:29.423" UserId="18203" Comment="added 932 characters in body" Text="I think that I see what you mean. For me, the correct &quot;change of basis&quot;, going from $(x,y)$ to $(u,v)$ does not take into account a &quot;translation&quot; of the basis into another: the origin of the basis is ignored (it is not even in the definition of what a basis is). So the second paragraph is the most accurate mathematically speaking: the only thing that matters is the rotation between the basis vectors (assuming all basis vectors have the same length).&#xD;&#xA;&#xD;&#xA;However, in practice in Graphics, it is more convenient to attach different basis to different origins points. To account for that, you now need the first formula, which is a change of basis plus a translation: &#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v \\&#xD;&#xA; y_u&amp; y_v \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix} &#xD;&#xA;= R \begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This writting is quite heavy, so an additional component is usually used to add translation transformations, and that leads to the formula that is in the book:&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p\\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v&amp;x_e \\&#xD;&#xA; y_u&amp; y_v&amp;y_e \\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p\\1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;(For 3D basis, it would lead to matrices with 4x4 components.)&#xD;&#xA;&#xD;&#xA;I hope that it helps?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[edit]&#xD;&#xA;Also, the confustion can come from the fact that the matrix R can be seen in two ways: a tool to express the coordinates in another basis, or a transformation matrix (a rotation). Therefore, if you use this time the transpose of the $R$ matrix that I have written:&#xD;&#xA;$$R_{uv}=\begin{bmatrix}&#xD;&#xA; x_u&amp;y_u \\&#xD;&#xA; x_v&amp; y_v \\&#xD;&#xA;\end{bmatrix}  $$ this matrix can express the coordinates from (xy) frame to the (uv) frame:&#xD;&#xA;$$\begin{bmatrix} u_u\\ v_u\end{bmatrix}=  \begin{bmatrix} x_u&amp;y_u \\&#xD;&#xA; x_v&amp; y_v \\  \end{bmatrix}\begin{bmatrix} x_u\\y_u\end{bmatrix} =\begin{bmatrix}&#xD;&#xA; 1\\0&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;but it can also be used as a tranformation in (xy) frame that would rotate the vector u to the vector x, and the vector v to the vector y&#xD;&#xA;$$\begin{bmatrix} x_{x}\\ y_{x}\end{bmatrix}=  \begin{bmatrix} x_u&amp;y_u \\&#xD;&#xA; x_v&amp; y_v \\  \end{bmatrix}\begin{bmatrix} x_u\\y_u\end{bmatrix}$$&#xD;&#xA;$$&#xD;&#xA;\mathbf{x}=R\,\mathbf{u}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36642" PostHistoryTypeId="5" PostId="12595" RevisionGUID="8714a62c-c572-40d4-b7ca-0329a729cc0e" CreationDate="2022-03-29T21:22:58.673" UserId="18203" Comment="added 8 characters in body" Text="I think that I see what you mean. For me, the correct &quot;change of basis&quot;, going from $(x,y)$ to $(u,v)$ does not take into account a &quot;translation&quot; of the basis into another: the origin of the basis is ignored (it is not even in the definition of what a basis is). So the second paragraph is the most accurate mathematically speaking: the only thing that matters is the rotation between the basis vectors (assuming all basis vectors have the same length).&#xD;&#xA;&#xD;&#xA;However, in practice in Graphics, it is more convenient to attach different basis to different origins points. To account for that, you now need the first formula, which is a change of basis plus a translation: &#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v \\&#xD;&#xA; y_u&amp; y_v \\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix} &#xD;&#xA;= R \begin{bmatrix}&#xD;&#xA; u_p\\v_p&#xD;&#xA;\end{bmatrix} +&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; x_e\\y_e&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;This writting is quite heavy, so an additional component is usually used to add translation transformations, and that leads to the formula that is in the book:&#xD;&#xA;$$\begin{bmatrix}&#xD;&#xA; x_p\\&#xD;&#xA; y_p\\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=  \begin{bmatrix}&#xD;&#xA; x_u&amp; x_v&amp;x_e \\&#xD;&#xA; y_u&amp; y_v&amp;y_e \\&#xD;&#xA;0&amp;0&amp;1\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA; u_p\\v_p\\1&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;(For 3D basis, it would lead to matrices with 4x4 components.)&#xD;&#xA;&#xD;&#xA;I hope that it helps?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[edit]&#xD;&#xA;Also, the confustion can come from the fact that the matrix R can be seen in two ways: a tool to express the coordinates in another basis, or a transformation matrix (a rotation). Therefore, if you use this time the transpose of the $R$ matrix that I have written earlier:&#xD;&#xA;$$R_{uv}=\begin{bmatrix}&#xD;&#xA; x_u&amp;y_u \\&#xD;&#xA; x_v&amp; y_v \\&#xD;&#xA;\end{bmatrix}  $$ this matrix can express the coordinates from (xy) frame to the (uv) frame:&#xD;&#xA;$$\begin{bmatrix} u_u\\ v_u\end{bmatrix}=  \begin{bmatrix} x_u&amp;y_u \\&#xD;&#xA; x_v&amp; y_v \\  \end{bmatrix}\begin{bmatrix} x_u\\y_u\end{bmatrix} =\begin{bmatrix}&#xD;&#xA; 1\\0&#xD;&#xA;\end{bmatrix}$$&#xD;&#xA;but it can also be used as a tranformation in the (xy) frame that would rotate the vector u to the vector x, and the vector v to the vector y&#xD;&#xA;$$\begin{bmatrix} x_{x}\\ y_{x}\end{bmatrix}=  \begin{bmatrix} x_u&amp;y_u \\&#xD;&#xA; x_v&amp; y_v \\  \end{bmatrix}\begin{bmatrix} x_u\\y_u\end{bmatrix}$$&#xD;&#xA;$$&#xD;&#xA;\mathbf{x}=R\,\mathbf{u}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36644" PostHistoryTypeId="2" PostId="12597" RevisionGUID="57ea3549-8311-406a-895c-7034101235ca" CreationDate="2022-03-31T00:14:04.790" UserId="18214" Text="I made this ray tracer in javascript to run on html with imageData. I have been using the book &quot;Ray Tracing in One Weekend&quot; as a reference (https://raytracing.github.io/books/RayTracingInOneWeekend.html) and I am on the step where I create a diffuse material (essentially the surfaces with diffuse materials picks up the color of another object through randomly generated rays in a recursive process) Apparently, the diffuse material works on the plane I create but it doesn't work on the sphere. I have been trying to troubleshoot the problem but I don't seem to be able to find the root of the problem. The places that could potentially be problematic are the ray-sphere intersection function and the normal calculation but I just couldn't debug it. It would be very helpful if someone could hel me debug this code.&#xD;&#xA;This is the script (main.js):&#xD;&#xA;&#xD;&#xA;```var cvs = document.getElementById(&quot;viewport&quot;);&#xD;&#xA;var ctx = cvs.getContext(&quot;2d&quot;);&#xD;&#xA;var h = cvs.height;&#xD;&#xA;var w = cvs.width;&#xD;&#xA;var data = ctx.getImageData(0,0, w, h);&#xD;&#xA;var scene ={};&#xD;&#xA;scene.skybox = {&#xD;&#xA;  color: {&#xD;&#xA;    x:150,&#xD;&#xA;    y:200,&#xD;&#xA;    z:250,&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;scene.camera = {&#xD;&#xA;    point: {&#xD;&#xA;      x: 0,&#xD;&#xA;      y: 0,&#xD;&#xA;      z: 10,&#xD;&#xA;    },&#xD;&#xA;    fieldOfView: 45,&#xD;&#xA;    vector: {&#xD;&#xA;      x: 0,&#xD;&#xA;      y: 0,&#xD;&#xA;      z: 0,&#xD;&#xA;    },&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;scene.objects = [&#xD;&#xA;    {&#xD;&#xA;      type: &quot;sphere&quot;,&#xD;&#xA;      point: {&#xD;&#xA;        x: 0,&#xD;&#xA;        y: 0,&#xD;&#xA;        z: 0,&#xD;&#xA;      },&#xD;&#xA;    },&#xD;&#xA;    {&#xD;&#xA;      type: &quot;plane&quot;,&#xD;&#xA;      point: {&#xD;&#xA;        x: 0,&#xD;&#xA;        y: 1,&#xD;&#xA;        z: 0,&#xD;&#xA;      },&#xD;&#xA;      vector:{&#xD;&#xA;        x:0,&#xD;&#xA;        y:-1,&#xD;&#xA;        z:0,&#xD;&#xA;      },&#xD;&#xA;    },&#xD;&#xA;  ];&#xD;&#xA;window.onload=init();&#xD;&#xA;function init(){&#xD;&#xA;  var w_key = 87;&#xD;&#xA;  var a_key = 65;&#xD;&#xA;  var s_key = 83;&#xD;&#xA;  var d_key = 68;&#xD;&#xA;  render();&#xD;&#xA;  window.onkeydown= function(gfg){&#xD;&#xA;    if(gfg.keyCode === a_key){&#xD;&#xA;      scene.camera.point.x+=1;&#xD;&#xA;      render();&#xD;&#xA;    };&#xD;&#xA;    if(gfg.keyCode === d_key)&#xD;&#xA;    {&#xD;&#xA;      scene.camera.point.x-=1;&#xD;&#xA;      render();&#xD;&#xA;    };&#xD;&#xA;    if(gfg.keyCode === w_key){&#xD;&#xA;      scene.camera.point.y-=1;&#xD;&#xA;      render();&#xD;&#xA;    };&#xD;&#xA;    if(gfg.keyCode === s_key)&#xD;&#xA;    {&#xD;&#xA;      scene.camera.point.y+=1;&#xD;&#xA;      render();&#xD;&#xA;    };&#xD;&#xA;  };&#xD;&#xA;}&#xD;&#xA;function render(){&#xD;&#xA;  var start = performance.now();&#xD;&#xA;  var camera = scene.camera;&#xD;&#xA;  var eVec = unitVector(subtract(camera.vector, camera.point));&#xD;&#xA;  var eVecRight = unitVector(crossProduct(eVec, {x:0, y:1, z:0}));&#xD;&#xA;  var eVecUp = unitVector(crossProduct(eVecRight, eVec));&#xD;&#xA;  var halfFOV = (Math.PI * (camera.fieldOfView / 2)) / 180;&#xD;&#xA;  var halfW = Math.tan(halfFOV);&#xD;&#xA;  var halfH = (h/w)*halfW;&#xD;&#xA;  var W = halfW*2;&#xD;&#xA;  var H = halfH*2;&#xD;&#xA;  var Wpx = W/(w-1);&#xD;&#xA;  var Hpx = H/(h-1);&#xD;&#xA;  var index;&#xD;&#xA;  var spx = 50;&#xD;&#xA;  var ray = {&#xD;&#xA;      point: camera.point,&#xD;&#xA;  };&#xD;&#xA;  for (var i=0; i&lt;scene.objects.length; i++){&#xD;&#xA;    var object = scene.objects[i];&#xD;&#xA;    if (object.type == &quot;plane&quot;){&#xD;&#xA;      object.vector = unitVector(object.vector);&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;  for (var x =0; x&lt;w; x++){&#xD;&#xA;      for(var y =0; y&lt;h; y++){&#xD;&#xA;        var color = {x:0,y:0,z:0};&#xD;&#xA;        for (var i=0; i&lt;spx; i++){&#xD;&#xA;          var xcomp = scaleVector(eVecRight, (x+Math.random()) * Wpx - halfW);&#xD;&#xA;          var ycomp = scaleVector(eVecUp, (y+Math.random()) * Hpx - halfH);&#xD;&#xA;          ray.vector = unitVector(add3Vectors(eVec, xcomp, ycomp));&#xD;&#xA;          color = addVectors(gamma(scaleVector(trace(ray, scene, 20), 1/spx)),color);&#xD;&#xA;        }&#xD;&#xA;        index = (y*w+x)*4;&#xD;&#xA;        data.data[index]=clamp(color.x, 0, 255);&#xD;&#xA;        data.data[index+1]=clamp(color.y, 0, 255);&#xD;&#xA;        data.data[index+2]=clamp(color.z, 0, 255);&#xD;&#xA;        data.data[index+3]=255;&#xD;&#xA;      }&#xD;&#xA;  }&#xD;&#xA;  ctx.putImageData(data, 0,0);&#xD;&#xA;  var end = performance.now();&#xD;&#xA;  console.log(end-start);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function trace(ray, scene, iter){&#xD;&#xA;  var distObj = SceneIntersect(ray, scene);&#xD;&#xA;  if (distObj[0] === Infinity){&#xD;&#xA;    var pointOfIntersect = null;&#xD;&#xA;  }else{&#xD;&#xA;    var pointOfIntersect = addVectors(scene.camera.point, scaleVector(ray.vector, distObj[0]));&#xD;&#xA;  }&#xD;&#xA;  return surface(ray, scene, distObj[1], pointOfIntersect, iter);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function SceneIntersect(ray, scene){&#xD;&#xA;  var closest = [Infinity, null];&#xD;&#xA;  for (var i=0; i&lt;scene.objects.length; i++){&#xD;&#xA;    var object = scene.objects[i];&#xD;&#xA;    if (object.type == &quot;sphere&quot;){&#xD;&#xA;      var dist = raySphereIntersect(object, ray);&#xD;&#xA;    }else if(object.type == &quot;plane&quot;){&#xD;&#xA;      var dist = rayPlaneIntersect(object, ray);&#xD;&#xA;    }&#xD;&#xA;    if (dist !== undefined &amp;&amp; dist &lt; closest[0]){&#xD;&#xA;      closest = [dist, object];&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;  return closest;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function gamma(a){&#xD;&#xA;  return {&#xD;&#xA;    x:Math.sqrt(a.x),&#xD;&#xA;    y:Math.sqrt(a.y),&#xD;&#xA;    z:Math.sqrt(a.z),&#xD;&#xA;  };&#xD;&#xA;}&#xD;&#xA;function dotProduct(a,b){&#xD;&#xA;    return a.x*b.x+a.y*b.y+a.z*b.z;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function unitVector(a){&#xD;&#xA;    m = Math.sqrt(dotProduct(a,a));&#xD;&#xA;    return {&#xD;&#xA;        x: a.x/m,&#xD;&#xA;        y: a.y/m,&#xD;&#xA;        z: a.z/m&#xD;&#xA;    };&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function scaleVector(a, m){&#xD;&#xA;  return {&#xD;&#xA;    x:a.x*m,&#xD;&#xA;    y:a.y*m,&#xD;&#xA;    z:a.z*m&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function subtract(a,b){&#xD;&#xA;    return {&#xD;&#xA;        x: a.x- b.x,&#xD;&#xA;        y: a.y- b.y,&#xD;&#xA;        z: a.z - b.z&#xD;&#xA;    };&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function crossProduct(a,b){&#xD;&#xA;    return {&#xD;&#xA;       x: a.y*b.z-a.z*b.y,&#xD;&#xA;       y: a.z*b.x-a.x*b.z,&#xD;&#xA;       z: a.x*b.y-a.y*b.x&#xD;&#xA;    };&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function add3Vectors(a,b,c){&#xD;&#xA;  return {&#xD;&#xA;    x:a.x+b.x+c.x,&#xD;&#xA;    y:a.y+b.y+c.y,&#xD;&#xA;    z:a.z+b.z+c.z&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function addVectors(a,b){&#xD;&#xA;  return{&#xD;&#xA;    x:a.x+b.x,&#xD;&#xA;    y:a.y+b.y,&#xD;&#xA;    z:a.z+b.z&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function reflect(a,n){&#xD;&#xA;  return subtract(scaleVector(n, 2*dotProduct(n,a)),a);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function clamp(x, min, max){&#xD;&#xA;  if(x&lt;min) return min;&#xD;&#xA;  if (x&gt;max) return max;&#xD;&#xA;  return x;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function raySphereIntersect(sphere, ray){&#xD;&#xA;  var ec = subtract(sphere.point, ray.point);&#xD;&#xA;  var v = dotProduct(ray.vector, ec);&#xD;&#xA;  var ecDot = dotProduct(ec, ec);&#xD;&#xA;  var s2 = sphere.radius * sphere.radius - ecDot + v*v;&#xD;&#xA;  if (s2 &lt;0){&#xD;&#xA;      return;&#xD;&#xA;  }else{&#xD;&#xA;      return v - Math.sqrt(s2);&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function rayPlaneIntersect(plane, ray){&#xD;&#xA;  var n = unitVector(plane.vector);&#xD;&#xA;  var d = dotProduct(n,subtract(plane.point,ray.point))/dotProduct(ray.vector,n);&#xD;&#xA;  if (d&lt;0){&#xD;&#xA;    return;&#xD;&#xA;  }else{&#xD;&#xA;    return d;&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function surface(ray, scene, object, p, iter){&#xD;&#xA;  if (iter &lt;= 0) {&#xD;&#xA;    return {x:0,y:0,z:0};&#xD;&#xA;  }&#xD;&#xA;  if (p == null){&#xD;&#xA;    return scene.skybox.color;&#xD;&#xA;  }else{&#xD;&#xA;    if (object.type == &quot;sphere&quot;){&#xD;&#xA;      var normal = sphereNormal(object, p, ray);&#xD;&#xA;      var target = add3Vectors(p, normal, randSphere());&#xD;&#xA;      console.log(Math.sqrt(dotProduct(subtract(p,object.point),subtract(p,object.point))));&#xD;&#xA;      return scaleVector(trace({point:p, vector: unitVector(subtract(target, p))}, scene, --iter), 0.5);&#xD;&#xA;    }else{&#xD;&#xA;      var normal = object.vector;&#xD;&#xA;      var target = add3Vectors(p, normal, randSphere());&#xD;&#xA;      return scaleVector(trace({point:subtract(p,{x:0.005, y:0.005, z:0.005}), vector: unitVector(subtract(target, p))}, scene, --iter), 0.5);&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function sphereNormal(sphere, p, ray){&#xD;&#xA;  var normal = scaleVector(subtract(p, sphere.point), 1/sphere.radius);&#xD;&#xA;  var front = dotProduct(ray.vector, normal) &lt; 0;&#xD;&#xA;  normal = front ? normal : scaleVector(normal, -1);&#xD;&#xA;  return normal;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function randSphere(){&#xD;&#xA;  var a = Math.random()*2*Math.PI;&#xD;&#xA;  var b = Math.random()*2*Math.PI;&#xD;&#xA;  var x = Math.sin(a)*Math.cos(b);&#xD;&#xA;  var y = Math.sin(a)*Math.sin(b);&#xD;&#xA;  var z = Math.cos(a);&#xD;&#xA;  return {x:x,y:y,z:z};&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;html here:&#xD;&#xA;```&#xD;&#xA;&lt;!DOCTYPE html&gt;&#xD;&#xA;&lt;html&gt;&#xD;&#xA;&lt;head&gt;&#xD;&#xA;	&lt;title&gt;raytracing&lt;/title&gt;&#xD;&#xA;    &lt;canvas id='viewport' width = '256' height = '256'&gt;&lt;/canvas&gt;&#xD;&#xA;    &lt;script type=&quot;text/javascript&quot; src=&quot;main.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;&lt;/head&gt;&#xD;&#xA;&lt;body&gt;&#xD;&#xA;&#xD;&#xA;&lt;/body&gt;&#xD;&#xA;&lt;/html&gt;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36646" PostHistoryTypeId="1" PostId="12597" RevisionGUID="57ea3549-8311-406a-895c-7034101235ca" CreationDate="2022-03-31T00:14:04.790" UserId="18214" Text="Ray tracing of a diffuse material sphere doesn't work, the sphere just shades black" ContentLicense="CC BY-SA 4.0" />
  <row Id="36647" PostHistoryTypeId="3" PostId="12597" RevisionGUID="57ea3549-8311-406a-895c-7034101235ca" CreationDate="2022-03-31T00:14:04.790" UserId="18214" Text="|raytracing|shading|javascript|diffuse|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36648" PostHistoryTypeId="2" PostId="12598" RevisionGUID="5ddcba34-f0df-4a90-a570-8fee0d7558f4" CreationDate="2022-04-01T13:08:56.770" UserId="15772" Text="To preface, I am a bit of a beginner to graphics programming. From what I've read, normal maps merely perturb the existing surface normal as opposed to overwriting them as I'd previously thought&#xD;&#xA;&#xD;&#xA;But why is this so? Would this not put our normal map at the 'mercy' of the normals of our mesh? If I am to overwrite normals (that is, replacing the normal on the surface with the corresponding one from the normal map), would I not have more 'control'?&#xD;&#xA;&#xD;&#xA;Is this because perturbing as opposed to overwriting allows us control how 'strong' the normal map is, for which we need the existing surface normals as 'reference' (assuming we use tangent maps that is) ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36650" PostHistoryTypeId="1" PostId="12598" RevisionGUID="5ddcba34-f0df-4a90-a570-8fee0d7558f4" CreationDate="2022-04-01T13:08:56.770" UserId="15772" Text="Why do normal maps perturb existing normals as opposed to 'overwriting' them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36651" PostHistoryTypeId="3" PostId="12598" RevisionGUID="5ddcba34-f0df-4a90-a570-8fee0d7558f4" CreationDate="2022-04-01T13:08:56.770" UserId="15772" Text="|texture|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36657" PostHistoryTypeId="2" PostId="12600" RevisionGUID="bfe4a8e7-47f8-4200-b02c-31c4ae84ebd7" CreationDate="2022-04-01T22:29:40.890" UserId="48" Text="By &quot;perturb the existing surface normal&quot;, I think what you mean is that we use normal maps defined in tangent space, so that when the normal map is applied to a surface it acts as a displacement (loosely speaking) applied to the underlying geometric normal of that surface.&#xD;&#xA;&#xD;&#xA;One reason to do this is simply that a tiling texture can be designed, where the texture can be applied to any surface on a 3D model. For example, a single brick texture could be used on walls, a floor, or a ceiling. All those surfaces to which we want to apply the texture all have different geometric normals. We can re-use the same normal map for all of them by using the geometric normal,  and associated tangent space, as a basis for applying the normal map.&#xD;&#xA;&#xD;&#xA;A similar issue affects animated characters, where for instance you want to move the character's arms and legs around using an animation at runtime. Tangent-space normal maps enable the fine texture detail to follow along with any motion, without needing to alter the contents of the texture.&#xD;&#xA;&#xD;&#xA;&gt; If I am to overwrite normals (that is, replacing the normal on the surface with the corresponding one from the normal map), would I not have more 'control'?&#xD;&#xA;&#xD;&#xA;You as the author of the normal map would have more control in some sense, but do you _want_ that control? It's usually more useful to create normal maps that can adjust to the shape of the mesh they're applied to. Otherwise, every time you change the shape of a mesh, you would need to update the normal map to match. And if you got it wrong, the lighting on the model would just look completely messed up. The information provided by the underlying surface geometric normals is _useful_ - you don't want to just throw that away.&#xD;&#xA;&#xD;&#xA;It's true that normal map strength can also be readily adjusted in tangent space, by lerping the normal map toward or away from (0, 0, 1), which is the default or &quot;identity&quot; normal in tangent space. This is more of a side benefit to the tangent space technique than its primary purpose. Other texture transformations, such as rotating or blending between different texture layers, can also be done readily in tangent space.&#xD;&#xA;&#xD;&#xA;Another side benefit is that tangent space normal maps are easier to compress without losing too much quality, since they have effectively fewer degrees of freedom and a narrower typical range of values." ContentLicense="CC BY-SA 4.0" />
  <row Id="36659" PostHistoryTypeId="50" PostId="11012" RevisionGUID="e9653fa6-dad6-4835-8cdc-263ce67b9a2f" CreationDate="2022-04-02T07:05:40.493" UserId="-1" />
  <row Id="36664" PostHistoryTypeId="50" PostId="10378" RevisionGUID="558633fb-b62b-4f56-b099-392985a99d5b" CreationDate="2022-04-02T18:04:10.397" UserId="-1" />
  <row Id="36665" PostHistoryTypeId="2" PostId="12602" RevisionGUID="473ee21e-4cce-4fe8-848f-17d2ca13b50d" CreationDate="2022-04-02T20:11:03.793" UserId="18220" Text="I'm following this book, Computer Graphics from scratch: A programmer's introduction to 3D rendering, to build a simple raytracer and rendering the scene to a bitmap image. I've run into a problem when doing the recursive reflections. When the program performs the recursion, the image ends up having corrupted pixel/color data (not sure how else to explain it). I've run into a similar problem earlier when I added specular reflections because I forgot to saturate the color values. However, now I'm not sure where the problem is.&#xD;&#xA;&#xD;&#xA;The first image is what it currently renders. The second is what it should look like (aside from the image size).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is my code (c++):&#xD;&#xA;&#xD;&#xA;[Defines.h](https://pastebin.com/iskhCZzZ)&#xD;&#xA;&#xD;&#xA;I'm not familiar with bitmap formatting. I used this as a [reference](https://dev.to/muiz6/c-how-to-write-a-bitmap-image-from-scratch-1k6m).&#xD;&#xA;&#xD;&#xA;[main.cpp](https://pastebin.com/th40YG3e)&#xD;&#xA;&#xD;&#xA;You can assume the math functions work. If needed I can provide the math library in an edit.&#xD;&#xA;&#xD;&#xA;I noticed if I removed lighting or just scaled the color by a constant value but still do the recursion I get this result:&#xD;&#xA;&#xD;&#xA;[![recursion depth 2 no lighting][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![recursion depth 3 no lighting][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iivcA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/MnMqk.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KsYKl.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pwwai.png&#xD;&#xA;&#xD;&#xA;I don't know if the problem lies with my implementation of the algorithm or how I'm handling writing the data to a bitmap file. I've looked over the algorithm in the book and compared it to my implementation and I don't see anything different, but maybe another set of eyes can help.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="36667" PostHistoryTypeId="1" PostId="12602" RevisionGUID="473ee21e-4cce-4fe8-848f-17d2ca13b50d" CreationDate="2022-04-02T20:11:03.793" UserId="18220" Text="Problem with Corrupted Pixel/color data on bitmap image in Raytracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="36668" PostHistoryTypeId="3" PostId="12602" RevisionGUID="473ee21e-4cce-4fe8-848f-17d2ca13b50d" CreationDate="2022-04-02T20:11:03.793" UserId="18220" Text="|raytracing|bitmap-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36669" PostHistoryTypeId="5" PostId="12115" RevisionGUID="79c88e41-7bd7-44b1-abac-98c6f6c3ffc8" CreationDate="2022-04-02T20:56:51.687" UserId="-1" Comment="This questions is about Mac's suggestion is for software that doesn't have a Mac option." Text="Kinda late on reply, but I'm still gonna post it here for future searches.&#xD;&#xA;&#xD;&#xA;Since all (or many, I'm not sure) macs use Intel GPUs you can use [Intel Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html). It isn't much, but still got frame capture, texture browser etc. and helps debug many errors.&#xD;&#xA;&#xD;&#xA;(Not Available On Mac)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36670" PostHistoryTypeId="24" PostId="12115" RevisionGUID="79c88e41-7bd7-44b1-abac-98c6f6c3ffc8" CreationDate="2022-04-02T20:56:51.687" Comment="Proposed by anonymous approved by -1 edit id of 578" ContentLicense="CC BY-SA 4.0" />
  <row Id="36671" PostHistoryTypeId="5" PostId="12115" RevisionGUID="0189b688-8051-49b7-bd5b-2f3bf5e9a949" CreationDate="2022-04-02T20:56:51.687" UserId="17042" Comment="Since I posted the reply Intel dropped support for macOS" Text="UPD: Intel GPA dropped macOS support for some reason. [Help page on GPA Metal Support](https://www.intel.com/content/www/us/en/developer/articles/training/how-to-use-intel-gpa.html) says Metal is not supported too, maybe that was before they dropped macOS version completely.&#xD;&#xA;&#xD;&#xA;If you're lucky you can find an old version of GPA. When I'm writing this there's still a link to macOS version on [Russian version of Intel website](https://www.intel.ru/content/www/ru/ru/developer/tools/graphics-performance-analyzers/download.html)&#xD;&#xA;&#xD;&#xA;Original post:&#xD;&#xA;&#xD;&#xA;Kinda late on reply, but I'm still gonna post it here for future searches.&#xD;&#xA;&#xD;&#xA;Since all (or many, I'm not sure) macs use Intel GPUs you can use [Intel Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html). It isn't much, but still got frame capture, texture browser etc. and helps to debug many errors." ContentLicense="CC BY-SA 4.0" />
  <row Id="36672" PostHistoryTypeId="5" PostId="12115" RevisionGUID="83f04b83-1913-4d02-a54a-7f6854736f13" CreationDate="2022-04-02T21:12:03.690" UserId="17042" Comment="added 245 characters in body" Text="UPD: Intel GPA dropped macOS support for some reason. [Intel GPA Metal support page](https://www.intel.com/content/www/us/en/developer/articles/training/how-to-use-intel-gpa.html) says Metal is not supported too, maybe that was before they dropped macOS version completely.&#xD;&#xA;&#xD;&#xA;If you're lucky you can find an old version of GPA. When I'm writing this there's still a link to macOS version on [Russian version of Intel website](https://www.intel.ru/content/www/ru/ru/developer/tools/graphics-performance-analyzers/download.html)&#xD;&#xA;&#xD;&#xA;UPD2: This link from Intel GPA Metal support page: https://registrationcenter.intel.com/forms/?productid=3055 after you register allows you to download 2019 R1 version (should support OGL) or 2021 R1 version (supports macOS not sure about OGL)&#xD;&#xA;&#xD;&#xA;Original post:&#xD;&#xA;&#xD;&#xA;Kinda late on reply, but I'm still gonna post it here for future searches.&#xD;&#xA;&#xD;&#xA;Since all (or many, I'm not sure) macs use Intel GPUs you can use [Intel Analyzers](https://software.intel.com/content/www/us/en/develop/tools/graphics-performance-analyzers.html). It isn't much, but still got frame capture, texture browser etc. and helps to debug many errors." ContentLicense="CC BY-SA 4.0" />
  <row Id="36678" PostHistoryTypeId="5" PostId="12602" RevisionGUID="0713633e-8e73-498d-bd0f-ec91a4d8088a" CreationDate="2022-04-04T15:52:24.253" UserId="18220" Comment="added 147 characters in body" Text="I'm following this book, Computer Graphics from scratch: A programmer's introduction to 3D rendering, to build a simple raytracer and rendering the scene to a bitmap image. I've run into a problem when doing the recursive reflections. When the program performs the recursion, the image ends up having corrupted pixel/color data (not sure how else to explain it). I've run into a similar problem earlier when I added specular reflections because I forgot to saturate the color values. However, now I'm not sure where the problem is.&#xD;&#xA;&#xD;&#xA;The first image is what it currently renders. The second is what it should look like (aside from the image size).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is my code (c++):&#xD;&#xA;&#xD;&#xA;[Defines.h](https://pastebin.com/iskhCZzZ) &#xD;&#xA;(where I define the bitmap header data as well as other things)&#xD;&#xA;&#xD;&#xA;I'm not familiar with bitmap formatting. I used this as a [reference](https://dev.to/muiz6/c-how-to-write-a-bitmap-image-from-scratch-1k6m).&#xD;&#xA;&#xD;&#xA;[main.cpp](https://pastebin.com/th40YG3e) &#xD;&#xA;(where all the functions related to the raytracing algorithm are defined and used and where I write the data to the .bmp file)&#xD;&#xA;&#xD;&#xA;You can assume the math functions work. If needed I can provide the math library in an edit.&#xD;&#xA;&#xD;&#xA;I noticed if I removed lighting or just scaled the color by a constant value but still do the recursion I get this result:&#xD;&#xA;&#xD;&#xA;[![recursion depth 2 no lighting][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![recursion depth 3 no lighting][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iivcA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/MnMqk.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/KsYKl.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pwwai.png&#xD;&#xA;&#xD;&#xA;I don't know if the problem lies with my implementation of the algorithm or how I'm handling writing the data to a bitmap file. I've looked over the algorithm in the book and compared it to my implementation and I don't see anything different, but maybe another set of eyes can help.&#xD;&#xA;&#xD;&#xA;Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="36679" PostHistoryTypeId="5" PostId="12602" RevisionGUID="756e1b4d-a1fb-44c0-8dd4-e0de59e09d6b" CreationDate="2022-04-04T16:01:36.030" UserId="18220" Comment="Added image of output without recursive reflections" Text="I'm following this book, Computer Graphics from scratch: A programmer's introduction to 3D rendering, to build a simple raytracer and rendering the scene to a bitmap image. I've run into a problem when doing the recursive reflections. When the program performs the recursion, the image ends up having corrupted pixel/color data (not sure how else to explain it). I've run into a similar problem earlier when I added specular reflections because I forgot to saturate the color values. However, now I'm not sure where the problem is.&#xD;&#xA;&#xD;&#xA;The first image is what it currently renders. The second is what it should look like (aside from the image size).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is the output without any recursive reflections for reference:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is my code (c++):&#xD;&#xA;&#xD;&#xA;[Defines.h](https://pastebin.com/iskhCZzZ) &#xD;&#xA;(where I define the bitmap header data as well as other things)&#xD;&#xA;&#xD;&#xA;I'm not familiar with bitmap formatting. I used this as a [reference](https://dev.to/muiz6/c-how-to-write-a-bitmap-image-from-scratch-1k6m).&#xD;&#xA;&#xD;&#xA;[main.cpp](https://pastebin.com/th40YG3e) &#xD;&#xA;(where all the functions related to the raytracing algorithm are defined and used and where I write the data to the .bmp file)&#xD;&#xA;&#xD;&#xA;You can assume the math functions work. If needed I can provide the math library in an edit.&#xD;&#xA;&#xD;&#xA;I noticed if I removed lighting or just scaled the color by a constant value but still do the recursion I get this result:&#xD;&#xA;&#xD;&#xA;[![recursion depth 2 no lighting][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![recursion depth 3 no lighting][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I don't know if the problem lies with my implementation of the algorithm or how I'm handling writing the data to a bitmap file. I've looked over the algorithm in the book and compared it to my implementation and I don't see anything different, but maybe another set of eyes can help.&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iivcA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/MnMqk.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/zB0HP.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/KsYKl.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/pwwai.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36684" PostHistoryTypeId="2" PostId="12605" RevisionGUID="479d6d8d-358e-41cd-b785-b7b9281076a6" CreationDate="2022-04-05T04:20:23.740" UserId="18228" Text="This [wikipedia](https://en.wikipedia.org/wiki/Supersampling#Supersampling_patterns) page explains the principle of patterning in Supersampling.&#xD;&#xA;&#xD;&#xA;However, I have a question: should the pattern be constant for every pixel?&#xD;&#xA;&#xD;&#xA;Of course, the pattern will be constant for a &quot;grid algorithm&quot; but for the &quot;random algorithm&quot;, should the randomness pattern be the same across all pixels?&#xD;&#xA;&#xD;&#xA;I think about it because it could be an optimization, pre-computing the sub-pixel positions instead of calculating it in each pixel. However I don't know if it's an acceptable technique." ContentLicense="CC BY-SA 4.0" />
  <row Id="36686" PostHistoryTypeId="1" PostId="12605" RevisionGUID="479d6d8d-358e-41cd-b785-b7b9281076a6" CreationDate="2022-04-05T04:20:23.740" UserId="18228" Text="Ray tracing Supersampling patterns : pre-computing them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36687" PostHistoryTypeId="3" PostId="12605" RevisionGUID="479d6d8d-358e-41cd-b785-b7b9281076a6" CreationDate="2022-04-05T04:20:23.740" UserId="18228" Text="|raytracing|antialiasing|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36688" PostHistoryTypeId="5" PostId="12605" RevisionGUID="2299ffba-1448-4ae1-ab26-71d49d45870f" CreationDate="2022-04-05T04:27:26.300" UserId="18228" Comment="added 399 characters in body" Text="This [wikipedia](https://en.wikipedia.org/wiki/Supersampling#Supersampling_patterns) page explains the principle of patterning in Supersampling.&#xD;&#xA;&#xD;&#xA;However, I have a question: should the pattern be constant for every pixel?&#xD;&#xA;&#xD;&#xA;Of course, the pattern will be constant for a &quot;grid algorithm&quot; but for the &quot;random algorithm&quot;, should the randomness pattern be the same across all pixels?&#xD;&#xA;&#xD;&#xA;I think about it because it could be an optimization, pre-computing the sub-pixel positions instead of calculating it in each pixel. However I don't know if it's an acceptable technique.&#xD;&#xA;&#xD;&#xA;To illustrate this: Here for example a 2x2 image, with random pattern, on the left the same pattern is repeated (it is random, but the same across all pixels so can be cached). On the right the pattern is re-computed for each pixel. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;My question is: **it is visually acceptable to cache the pattern?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TOMq7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36689" PostHistoryTypeId="2" PostId="12606" RevisionGUID="6726c1f2-5605-48a9-bd47-5ba3aa884821" CreationDate="2022-04-05T10:47:29.587" UserId="13321" Text="It's common to precompute some of the sampling. The most modern approach is probably to use a blue noise pattern. Have a read through here (I belive it also has some precomputed patterns and source code you can use):&#xD;&#xA;&#xD;&#xA;https://belcour.github.io/blog/research/publication/2019/06/17/sampling-bluenoise.html&#xD;&#xA;&#xD;&#xA;This gives you which &quot;subpixel&quot; to sample from but I think you still want to apply some randomness within that subpixel." ContentLicense="CC BY-SA 4.0" />
  <row Id="36691" PostHistoryTypeId="5" PostId="12606" RevisionGUID="2eb854e1-df72-4d9c-b15d-088daac26250" CreationDate="2022-04-05T15:19:57.717" UserId="13321" Comment="added 188 characters in body" Text="It's common to precompute some of the sampling. The most modern approach is probably to use a blue noise pattern. Have a read through here (I belive it also has some precomputed patterns and source code you can use):&#xD;&#xA;&#xD;&#xA;https://belcour.github.io/blog/research/publication/2019/06/17/sampling-bluenoise.html&#xD;&#xA;&#xD;&#xA;This gives you which &quot;subpixel&quot; to sample from but I think you still want to apply some randomness within that subpixel.&#xD;&#xA;&#xD;&#xA;EDIT: As lightxbulb points out, what I shared precomputes for a tile of 128x128 pixels. You don't want neightbouring pixels to be exactly the same or you will notice it when rendering." ContentLicense="CC BY-SA 4.0" />
  <row Id="36692" PostHistoryTypeId="2" PostId="12607" RevisionGUID="dcfaa5bd-276e-48c0-8958-1ef60c85812b" CreationDate="2022-04-06T14:03:25.483" UserId="17510" Text="Recently I'm reading Eric Heitz's paper 'Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs', in section 5, 5.2, the paper defines the distribution of slopes and then says the distribution of normals is constructed from it (equation 64), I tried to understand it but still don't know how to manipulate the equations to do that, can somebody help me with this? Thanks a lot!&#xD;&#xA;[![the part of this paper][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GK8fu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36694" PostHistoryTypeId="1" PostId="12607" RevisionGUID="dcfaa5bd-276e-48c0-8958-1ef60c85812b" CreationDate="2022-04-06T14:03:25.483" UserId="17510" Text="How is the distribution of normals constructed from the distribution of slopes in 'Understanding the masking-shadowing function' paper?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36695" PostHistoryTypeId="3" PostId="12607" RevisionGUID="dcfaa5bd-276e-48c0-8958-1ef60c85812b" CreationDate="2022-04-06T14:03:25.483" UserId="17510" Text="|rendering|physically-based|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36696" PostHistoryTypeId="2" PostId="12608" RevisionGUID="6aeb3d93-b592-4ccf-8c3b-552a5fdd67db" CreationDate="2022-04-06T16:45:42.863" UserId="48" Text="The &quot;slope space&quot; is a coordinate system that describes unit vectors in the upper hemisphere using their $x$ and $y$ slopes, i.e. $-x/z$ and $-y/z$. It's related to the usual polar coordinates $\theta, \phi$ by a certain change-of-variables formula.&#xD;&#xA;&#xD;&#xA;When a probability density function like the $P^{22}$ function is taken through a change of variables, it picks up an additional factor called the Jacobian, which accounts for the scaling of volume during the change of variables. It preserves the total amount of probability within any given region of the space, and keeps the function normalized.&#xD;&#xA;&#xD;&#xA;In the passage from slope space to polar coordinates, the relevant Jacobian is $1/\cos^4 \theta$, so you will see this factor show up whenever a density defined in slope space is reparameterized to polar coordinates.&#xD;&#xA;&#xD;&#xA;More in-depth explanation here: [Slope Space in BRDF Theory](https://www.reedbeta.com/blog/slope-space-in-brdf-theory/)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36698" PostHistoryTypeId="2" PostId="12609" RevisionGUID="04630803-eb5c-40ee-81d2-7ee6252b186d" CreationDate="2022-04-07T01:27:33.820" UserId="18237" Text="I'm looking for some guidance.  &#xD;&#xA;I'm not sure if this is possible, and I'm not sure where to start.&#xD;&#xA;&#xD;&#xA;**I need to compute or estimate the FOV angles of a first-person, 3D game using only gameplay screenshots.**  &#xD;&#xA;&#xD;&#xA;Naively, I imagine the simplest solution would be rendering three virtual protractors at 0, 45, and 90 degrees which share an origin with the camera and that extend out to infinity. But alas. I do not have this level of control over the game engine.  &#xD;&#xA;&#xD;&#xA;The best I can do is use existing in-game geometry as a reference point.  &#xD;&#xA;Right angles, parallel lines, squares, cubes, and other primitives are somewhat plentiful.&#xD;&#xA;&#xD;&#xA;**Can FOV be derived from the 2D appearance of known angles, distances, or objects?**&#xD;&#xA;&#xD;&#xA;Consider the diagram at the bottom.  &#xD;&#xA;The gameplay screenshots being referenced are represented by the **z Near** plane.  &#xD;&#xA;The **Viewing Frustum** represents the observable 3D space.  &#xD;&#xA;&#xD;&#xA;**I need to compute the following angles:**  &#xD;&#xA; - Horizontal Field of View (**x FOV**)  &#xD;&#xA; - Vertical Field of View (**y FOV**)  &#xD;&#xA; - Diagonal Field of View (**diag FOV**)  &#xD;&#xA;&#xD;&#xA;**Things available to me:**  &#xD;&#xA; - I can increase and decrease a singular &quot;FOV&quot; setting  &#xD;&#xA; - I can point the camera almost anywhere  &#xD;&#xA; - I can view some common shapes, primitives, and angles  &#xD;&#xA;&#xD;&#xA;**Things I do not/cannot know:** (unless someone else knows a way)  &#xD;&#xA; - The distance from the camera origin to the **z Near** plane  &#xD;&#xA;    (maybe sometimes this is called focal distance? not sure)  &#xD;&#xA; - Maybe more...  &#xD;&#xA;  &#xD;&#xA;I found two online tools that claim to do this, but I'm skeptical.  &#xD;&#xA; - They don't specify any requirements for the camera's orientation relative to the reference object.&#xD;&#xA; - The ONLY thing that affects the calculation is the distance between two vanishing points.&#xD;&#xA;&#xD;&#xA;Tools are here:  &#xD;&#xA;[https://www.desmos.com/calculator/3e9hs7usyr][1]  &#xD;&#xA;[https://www.desmos.com/calculator/zb2jqy5bik][2]&#xD;&#xA;&#xD;&#xA;**Finally,** these tools don't really work for me since I need to detect too wide a range of FOVs. I need a method that can detect FOVs as small as 5 degrees and as large as 150 degrees.  &#xD;&#xA;&#xD;&#xA;[![Frustum FOV Diagram][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/3e9hs7usyr&#xD;&#xA;  [2]: https://www.desmos.com/calculator/zb2jqy5bik&#xD;&#xA;  [3]: https://i.stack.imgur.com/MdZN1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36700" PostHistoryTypeId="1" PostId="12609" RevisionGUID="04630803-eb5c-40ee-81d2-7ee6252b186d" CreationDate="2022-04-07T01:27:33.820" UserId="18237" Text="How to derive Field of View (FOV) angles from a 2D projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="36701" PostHistoryTypeId="3" PostId="12609" RevisionGUID="04630803-eb5c-40ee-81d2-7ee6252b186d" CreationDate="2022-04-07T01:27:33.820" UserId="18237" Text="|3d|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36702" PostHistoryTypeId="5" PostId="12609" RevisionGUID="fd2b074e-52c1-4f4d-82f0-2b0dc11b0151" CreationDate="2022-04-07T01:37:05.650" UserId="18237" Comment="added 166 characters in body" Text="I'm looking for some guidance.  &#xD;&#xA;I'm not sure if this is possible, and I'm not sure where to start.&#xD;&#xA;&#xD;&#xA;**I need to compute or estimate the FOV angles of a first-person, 3D game using only gameplay screenshots.**  &#xD;&#xA;&#xD;&#xA;Naively, I imagine the simplest solution would be rendering three virtual protractors at 0, 45, and 90 degrees which share an origin with the camera and that extend out to infinity. But alas. I do not have this level of control over the game engine.  &#xD;&#xA;&#xD;&#xA;The best I can do is use existing in-game geometry as a reference point.  &#xD;&#xA;Right angles, parallel lines, squares, cubes, and other primitives are somewhat plentiful.&#xD;&#xA;&#xD;&#xA;**Can FOV be derived from the 2D appearance of known angles, distances, or objects?**&#xD;&#xA;&#xD;&#xA;Consider the diagram at the bottom.  &#xD;&#xA;The gameplay screenshots being referenced are represented by the **z Near** plane.  &#xD;&#xA;The **Viewing Frustum** represents the observable 3D space.  &#xD;&#xA;&#xD;&#xA;**I need to compute the following angles:**  &#xD;&#xA; - Horizontal Field of View (**x FOV**)  &#xD;&#xA; - Vertical Field of View (**y FOV**)  &#xD;&#xA; - Diagonal Field of View (**diag FOV**)  &#xD;&#xA;&#xD;&#xA;**Things available to me:**  &#xD;&#xA; - I can increase and decrease a singular &quot;FOV&quot; setting  &#xD;&#xA; - I can point the camera almost anywhere  &#xD;&#xA; - I can view some common shapes, primitives, and angles  &#xD;&#xA;&#xD;&#xA;**Things I do not/cannot know:** (unless someone else knows a way)  &#xD;&#xA; - The distance from the camera origin to the **z Near** plane  &#xD;&#xA;    (maybe sometimes this is called focal distance? not sure)  &#xD;&#xA; - Maybe more...  &#xD;&#xA;  &#xD;&#xA;I found two online tools that claim to do this, but I'm skeptical.  &#xD;&#xA; - They don't specify any requirements for the camera's orientation relative to the reference object.&#xD;&#xA; - The ONLY thing that affects the calculation is the distance between two vanishing points.&#xD;&#xA;&#xD;&#xA;Tools are here:  &#xD;&#xA;[https://www.desmos.com/calculator/3e9hs7usyr][1]  &#xD;&#xA;[https://www.desmos.com/calculator/zb2jqy5bik][2]&#xD;&#xA;&#xD;&#xA;**Finally,** these tools don't really work for me since I need to detect too wide a range of FOVs. I need a method that can detect FOVs as small as 5 degrees and as large as 150 degrees. At an FOV of 5 degrees, the distance between the two vanishing points becomes absurdly large and way beyond the margin of error of these tools AND my image resolution.&#xD;&#xA;&#xD;&#xA;[![Frustum FOV Diagram][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/3e9hs7usyr&#xD;&#xA;  [2]: https://www.desmos.com/calculator/zb2jqy5bik&#xD;&#xA;  [3]: https://i.stack.imgur.com/MdZN1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36703" PostHistoryTypeId="5" PostId="12609" RevisionGUID="2341595e-822b-4fe3-8c48-c719d400cc2e" CreationDate="2022-04-07T13:56:23.893" UserId="18237" Comment="edits for grammar and clarity " Text="I'm looking for some guidance.  &#xD;&#xA;I'm not sure if this is possible, and I'm not sure where to start.&#xD;&#xA;&#xD;&#xA;**I need to measure the FOV angles of a first-person, 3D game using only gameplay screenshots.**  &#xD;&#xA;&#xD;&#xA;Naively, I imagine the simplest solution would be to render three virtual protractors in-game at 0, 45, and 90 degrees which share an origin with the camera and that extend out to infinity. But alas. I do not have this level of control over the game engine.  &#xD;&#xA;&#xD;&#xA;I'm bound by the game's sandbox.  &#xD;&#xA;&#xD;&#xA;The best I can do is use existing in-game geometry as a reference point.  &#xD;&#xA;Right angles, parallel lines, squares, cubes, and other primitives are somewhat plentiful.&#xD;&#xA;&#xD;&#xA;**Can FOV be derived from the 2D appearance of known angles, distances, or objects?**&#xD;&#xA;&#xD;&#xA;Consider the diagram at the bottom of this post.  &#xD;&#xA;My understanding is that a gameplay screenshot is represented by the **z Near** plane.  &#xD;&#xA;The **Viewing Frustum** represents the observable 3D space in-game.  &#xD;&#xA;&#xD;&#xA;**I need to measure the following angles:**  &#xD;&#xA; - Horizontal Field of View (**x FOV**)  &#xD;&#xA; - Vertical Field of View (**y FOV**)  &#xD;&#xA; - Diagonal Field of View (**diag FOV**)  &#xD;&#xA;&#xD;&#xA;**Things available to me:**  &#xD;&#xA; - I can increase and decrease a singular in-game &quot;FOV&quot; setting  &#xD;&#xA; - I can point and position the camera  &#xD;&#xA; - I can view some common shapes, primitives, and angles  &#xD;&#xA; - I know the width, height, and resolution of **z Near**&#xD;&#xA;&#xD;&#xA;**Things I do not/cannot know:** (unless someone else knows a way)  &#xD;&#xA; - The distance from the camera origin to the center of the **z Near** plane  &#xD;&#xA;    (maybe sometimes this is called focal length? not sure)  &#xD;&#xA; - Camera focal length (if different from above)  &#xD;&#xA; - Camera aperture (if relevant)  &#xD;&#xA; - Maybe more...  &#xD;&#xA;  &#xD;&#xA;I found two online tools that claim to do this, but I'm skeptical.  &#xD;&#xA; - They don't specify any requirements for the camera's orientation relative to the reference object.&#xD;&#xA; - The ONLY thing that affects the calculation is the distance between two vanishing points.&#xD;&#xA;&#xD;&#xA;Tools are here:  &#xD;&#xA;[https://www.desmos.com/calculator/3e9hs7usyr][1]  &#xD;&#xA;[https://www.desmos.com/calculator/zb2jqy5bik][2]&#xD;&#xA;&#xD;&#xA;**Finally,** these tools don't work for me since I need to detect too wide a range of FOVs. I need a method that can detect FOVs as small as 5 degrees and as large as 150 degrees. At an FOV of 5 degrees, the distance between the two vanishing points becomes absurdly large and way beyond the margin of error of these tools AND my image resolution.&#xD;&#xA;&#xD;&#xA;[![Frustum FOV Diagram][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/3e9hs7usyr&#xD;&#xA;  [2]: https://www.desmos.com/calculator/zb2jqy5bik&#xD;&#xA;  [3]: https://i.stack.imgur.com/MdZN1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36704" PostHistoryTypeId="5" PostId="12609" RevisionGUID="bc9e7c06-4875-462e-a019-e8a99731e652" CreationDate="2022-04-07T18:24:46.913" UserId="18237" Comment="added 9 characters in body" Text="I'm looking for some guidance.  &#xD;&#xA;I'm not sure if this is possible, and I'm not sure where to start.&#xD;&#xA;&#xD;&#xA;**I need to measure the FOV angles of a first-person, 3D game using only gameplay screenshots.**  &#xD;&#xA;&#xD;&#xA;Naively, I imagine the simplest solution would be to render three virtual protractors in-game at 0, 45, and 90 degrees which share an origin with the camera and that extend out to infinity. But alas. I do not have this level of control over the game engine.  &#xD;&#xA;&#xD;&#xA;I'm bound by the game's sandbox.  &#xD;&#xA;&#xD;&#xA;The best I can do is use existing in-game geometry as a reference point.  &#xD;&#xA;Right angles, parallel lines, squares, cubes, and other primitives are somewhat plentiful.&#xD;&#xA;&#xD;&#xA;**Can FOV be derived from the 2D appearance of known angles, distances, or objects?**&#xD;&#xA;&#xD;&#xA;Consider the diagram at the bottom of this post.  &#xD;&#xA;My understanding is that a gameplay screenshot is represented by the **z Near** plane.  &#xD;&#xA;The **Viewing Frustum** represents the observable 3D space in-game.  &#xD;&#xA;&#xD;&#xA;**I need to measure the following angles:**  &#xD;&#xA; - Horizontal Field of View (**x FOV**)  &#xD;&#xA; - Vertical Field of View (**y FOV**)  &#xD;&#xA; - Diagonal Field of View (**diag FOV**)  &#xD;&#xA;&#xD;&#xA;**Things available to me:**  &#xD;&#xA; - I can increase and decrease a singular in-game &quot;FOV&quot; setting  &#xD;&#xA; - I can point and position the camera  &#xD;&#xA; - I can view some common shapes, primitives, and angles  &#xD;&#xA; - I know the width, height, and resolution of **z Near**&#xD;&#xA;&#xD;&#xA;**Things I do not/cannot know:** (unless someone else knows a way)  &#xD;&#xA; - The distance from the camera origin to the center of the **z Near** plane  &#xD;&#xA;    (maybe sometimes this is called focal length? not sure)  &#xD;&#xA; - Camera focal length (if different from above)  &#xD;&#xA; - Camera aperture (if relevant)  &#xD;&#xA; - Maybe more...  &#xD;&#xA;  &#xD;&#xA;I found two online tools that claim to do this, but I'm skeptical.  &#xD;&#xA; - They don't specify any requirements for the camera's position/orientation relative to the reference object.&#xD;&#xA; - The ONLY thing that affects the calculation is the distance between two vanishing points.&#xD;&#xA;&#xD;&#xA;Tools are here:  &#xD;&#xA;[https://www.desmos.com/calculator/3e9hs7usyr][1]  &#xD;&#xA;[https://www.desmos.com/calculator/zb2jqy5bik][2]&#xD;&#xA;&#xD;&#xA;**Finally,** these tools don't work for me since I need to detect too wide a range of FOVs. I need a method that can detect FOVs as small as 5 degrees and as large as 150 degrees. At an FOV of 5 degrees, the distance between the two vanishing points becomes absurdly large and way beyond the margin of error of these tools AND my image resolution.&#xD;&#xA;&#xD;&#xA;[![Frustum FOV Diagram][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/3e9hs7usyr&#xD;&#xA;  [2]: https://www.desmos.com/calculator/zb2jqy5bik&#xD;&#xA;  [3]: https://i.stack.imgur.com/MdZN1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36705" PostHistoryTypeId="5" PostId="12609" RevisionGUID="a4525a6c-456f-475d-9787-6b055a1b7a66" CreationDate="2022-04-08T01:08:24.623" UserId="18237" Comment="fixed some misconceptions and updated diagram" Text="I'm looking for some guidance.  &#xD;&#xA;I'm not sure if this is possible, and I'm not sure where to start.&#xD;&#xA;&#xD;&#xA;**I need to measure the FOV angles of a first-person, 3D game using only gameplay screenshots.**  &#xD;&#xA;&#xD;&#xA;Naively, I imagine the simplest solution would be to render three virtual protractors in-game at 0, 45, and 90 degrees which share an origin with the camera and that extend out to infinity. But alas. I do not have this level of control over the game engine.  &#xD;&#xA;&#xD;&#xA;I'm bound by the game's sandbox.  &#xD;&#xA;&#xD;&#xA;The best I can do is use existing in-game geometry as a reference point.  &#xD;&#xA;Right angles, parallel lines, squares, cubes, and other primitives are somewhat plentiful.&#xD;&#xA;&#xD;&#xA;**Can FOV be derived from the 2D appearance of known angles, distances, or objects?**&#xD;&#xA;&#xD;&#xA;Consider the diagram at the bottom of this post.  &#xD;&#xA;My understanding is that a gameplay screenshot is represented by the **z Projection** plane.  &#xD;&#xA;The **Viewing Frustum** represents the observable 3D space in-game.  &#xD;&#xA;&#xD;&#xA;**I need to measure the following angles:**  &#xD;&#xA; - Horizontal Field of View (**x FOV**)  &#xD;&#xA; - Vertical Field of View (**y FOV**)  &#xD;&#xA; - Diagonal Field of View (**diag FOV**)  &#xD;&#xA;&#xD;&#xA;**Things available to me:**  &#xD;&#xA; - I can increase and decrease a singular in-game &quot;FOV&quot; setting  &#xD;&#xA; - I can point and position the camera  &#xD;&#xA; - I can view some common shapes, primitives, and angles  &#xD;&#xA; - I know the width, height, and resolution of **z Projection**&#xD;&#xA;&#xD;&#xA;**Things I do not/cannot know:** (unless someone else knows a way)  &#xD;&#xA; - The distance from the camera origin to the center of the **z Projection** plane  &#xD;&#xA;    (maybe sometimes this is called focal length? not sure)  &#xD;&#xA; - Camera focal length (if different from above)  &#xD;&#xA; - Camera aperture (if relevant)  &#xD;&#xA; - Maybe more...  &#xD;&#xA;  &#xD;&#xA;I found two online tools that claim to do this, but I'm skeptical.  &#xD;&#xA; - They don't specify any requirements for the camera's position/orientation relative to the reference object.&#xD;&#xA; - The ONLY thing that affects the calculation is the distance between two vanishing points.&#xD;&#xA;&#xD;&#xA;Tools are here:  &#xD;&#xA;[https://www.desmos.com/calculator/3e9hs7usyr][1]  &#xD;&#xA;[https://www.desmos.com/calculator/zb2jqy5bik][2]&#xD;&#xA;&#xD;&#xA;**Finally,** these tools don't work for me since I need to detect too wide a range of FOVs. I need a method that can detect FOVs as small as 5 degrees and as large as 150 degrees. At an FOV of 5 degrees, the distance between the two vanishing points becomes absurdly large and way beyond the margin of error of these tools AND my image resolution.&#xD;&#xA;&#xD;&#xA;[![Diagram][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/3e9hs7usyr&#xD;&#xA;  [2]: https://www.desmos.com/calculator/zb2jqy5bik&#xD;&#xA;  [3]: https://i.stack.imgur.com/57N9U.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36706" PostHistoryTypeId="5" PostId="12609" RevisionGUID="2a76389d-d911-4fba-921b-7a362fbd373f" CreationDate="2022-04-08T01:15:30.623" UserId="18237" Comment="fixed some misconceptions and updated diagram" Text="I'm looking for some guidance.  &#xD;&#xA;I'm not sure if this is possible, and I'm not sure where to start.&#xD;&#xA;&#xD;&#xA;**I need to measure the FOV angles of a first-person, 3D game using only gameplay screenshots.**  &#xD;&#xA;&#xD;&#xA;I'm bound by the game's sandbox.  &#xD;&#xA;&#xD;&#xA;The best I can do is use existing in-game geometry as a reference points.  &#xD;&#xA;Right angles, parallel lines, squares, cubes, and other primitives are somewhat plentiful, and I have a fair amount of control over the camera's position and orientation.&#xD;&#xA;&#xD;&#xA;**Can FOV be derived from the 2D appearance of known angles, distances, or objects?**  &#xD;&#xA;&#xD;&#xA;**If not from a single image, can it be done using multiple images; each showing a different perspective of the same scene, or a different arrangement of known objects?**  &#xD;&#xA;&#xD;&#xA;Consider the diagram at the bottom of this post.  &#xD;&#xA;My understanding is that a gameplay screenshot is represented by the **z Projection** plane.  &#xD;&#xA;The **Viewing Frustum** represents the observable 3D space in-game.  &#xD;&#xA;&#xD;&#xA;**I need to measure the following angles:**  &#xD;&#xA; - Horizontal Field of View (**x FOV**)  &#xD;&#xA; - Vertical Field of View (**y FOV**)  &#xD;&#xA; - Diagonal Field of View (**diag FOV**)  &#xD;&#xA;&#xD;&#xA;**Things available to me:**  &#xD;&#xA; - I can increase and decrease a singular in-game &quot;FOV&quot; setting  &#xD;&#xA; - I can point and position the camera  &#xD;&#xA; - I can view some common shapes, primitives, and angles  &#xD;&#xA; - I know the width, height, and resolution of **z Projection**&#xD;&#xA;&#xD;&#xA;**Things I do not/cannot know:** (unless someone else knows a way)  &#xD;&#xA; - The distance from the camera origin to the center of the **z Projection** plane  &#xD;&#xA;    (maybe sometimes this is called focal length? not sure)  &#xD;&#xA; - Camera focal length (if different from above)  &#xD;&#xA; - Camera aperture (if relevant)  &#xD;&#xA; - Maybe more...  &#xD;&#xA;  &#xD;&#xA;I found two online tools that claim to do this, but I'm skeptical.  &#xD;&#xA; - They don't specify any requirements for the camera's position/orientation relative to the reference object.&#xD;&#xA; - The ONLY thing that affects the calculation is the distance between two vanishing points.&#xD;&#xA;&#xD;&#xA;Tools are here:  &#xD;&#xA;[https://www.desmos.com/calculator/3e9hs7usyr][1]  &#xD;&#xA;[https://www.desmos.com/calculator/zb2jqy5bik][2]&#xD;&#xA;&#xD;&#xA;**Finally,** these tools don't work for me since I need to detect too wide a range of FOVs. I need a method that can detect FOVs as small as 5 degrees and as large as 150 degrees. At an FOV of 5 degrees, the distance between the two vanishing points becomes absurdly large and way beyond the margin of error of these tools AND my image resolution.&#xD;&#xA;&#xD;&#xA;[![Diagram][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.desmos.com/calculator/3e9hs7usyr&#xD;&#xA;  [2]: https://www.desmos.com/calculator/zb2jqy5bik&#xD;&#xA;  [3]: https://i.stack.imgur.com/57N9U.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36707" PostHistoryTypeId="5" PostId="8168" RevisionGUID="0cbc273c-fc85-419d-a806-1ab93c44faec" CreationDate="2022-04-08T01:52:13.870" UserId="6172" Comment="fixed broken link (now to the official AMD webpage)" Text="Work groups share resources. The most notable resources they share are barriers and LDS (Local Data Storage aka shared memory in GL lingo, aka Thread Group Shared Memory).&#xD;&#xA;&#xD;&#xA;See [Efficient Compute Shader Programming][1] for an example where LDS/TGSM is used to accelerate a simple gaussian blur.&#xD;&#xA;&#xD;&#xA;It is an interesting thought exercise of how a simple algorithm (weight average N values and output the result) can be rewritten to better leverage the hardware. Basically with a kernel radius of 5, Pixel A will load pixels [A; E] to average them, pixel B loads pixels [A; F] to average, pixel C loads pixels [A; G], and so on until we hit pixel F which will load pixels [B; J] to average them. So the paper asks the question: why do we load pixels A through F from main RAM so many times? (note: GPUs DO have caches, but if multiple threads are requesting all the same regions is likely many of these loads will miss the cache or have bank conflicts) and instead tries to load A through F ONCE (each thread loads only one pixel) and store it into TGSM memory which is much faster (and can also be accessed directly by the HW). It's basically very similar to manual cache management.&#xD;&#xA;&#xD;&#xA;Also if the workgroup happens to be &lt;= than the GPU's native workgroup size, barriers are much cheaper.&#xD;&#xA;&#xD;&#xA;Note not all GPUs are created equal. For example current Mali's GPU do not have LDS, and shared memory is &quot;emulated&quot; via RAM fetches, thus trying to use LDS like a cache is only going to hurt performance.&#xD;&#xA;&#xD;&#xA;[1]:https://developer.amd.com/wordpress/media/2012/10/Efficient%20Compute%20Shader%20Programming.pps" ContentLicense="CC BY-SA 4.0" />
  <row Id="36708" PostHistoryTypeId="24" PostId="8168" RevisionGUID="0cbc273c-fc85-419d-a806-1ab93c44faec" CreationDate="2022-04-08T01:52:13.870" Comment="Proposed by 6172 approved by 482 edit id of 579" ContentLicense="CC BY-SA 4.0" />
  <row Id="36709" PostHistoryTypeId="5" PostId="12600" RevisionGUID="67c19b33-2ca7-42ca-b47f-8713b250eca0" CreationDate="2022-04-08T18:23:01.433" UserId="48" Comment="re-wording" Text="By &quot;perturb the existing surface normal&quot;, I think what you mean is that we use normal maps defined in tangent space, so that when the normal map is applied it acts as a displacement (loosely speaking) to the underlying geometric normal of that surface.&#xD;&#xA;&#xD;&#xA;One reason to do this is simply that a tiling texture can be designed, where the texture can be applied to surfaces of any orientation. For example, a single brick texture could be used on walls, a floor, or a ceiling. All those surfaces have different geometric normals, but we can re-use the same normal map for all of them by using their tangent space as a basis for applying the normal map.&#xD;&#xA;&#xD;&#xA;A similar issue affects animated characters, where for instance you want to move the character's arms and legs around using an animation at runtime. Tangent-space normal maps enable the fine texture detail to follow along with any motion, without needing to alter the contents of the texture.&#xD;&#xA;&#xD;&#xA;&gt; If I am to overwrite normals (that is, replacing the normal on the surface with the corresponding one from the normal map), would I not have more 'control'?&#xD;&#xA;&#xD;&#xA;You as the author of the normal map would have more control in some sense, but do you _want_ that control? It's usually more useful to create normal maps that can adjust to the shape of the mesh they're applied to. Otherwise, every time you change the shape of a mesh, you would need to update the normal map to match. And if you got it wrong, the lighting on the model would just look completely messed up. The information provided by the underlying surface geometric normals is _useful_ - you don't want to just throw that away.&#xD;&#xA;&#xD;&#xA;It's true that normal map strength can also be readily adjusted in tangent space, by lerping the normal map toward or away from (0, 0, 1), which is the default or &quot;identity&quot; normal in tangent space. This is more of a side benefit to the tangent space technique than its primary purpose. Other texture transformations, such as rotating or blending between different texture layers, can also be done readily in tangent space.&#xD;&#xA;&#xD;&#xA;Another side benefit is that tangent space normal maps are easier to compress without losing too much quality, since they have effectively fewer degrees of freedom and a narrower typical range of values." ContentLicense="CC BY-SA 4.0" />
  <row Id="36712" PostHistoryTypeId="50" PostId="9192" RevisionGUID="ef168c10-5908-4ac2-b07d-91b11f572e61" CreationDate="2022-04-09T03:02:35.243" UserId="-1" />
  <row Id="36713" PostHistoryTypeId="50" PostId="9549" RevisionGUID="0ab2cdaa-8989-4c48-8eb3-64e77b515b5b" CreationDate="2022-04-10T14:05:35.600" UserId="-1" />
  <row Id="36714" PostHistoryTypeId="2" PostId="12610" RevisionGUID="1e849459-2b73-4e36-8b77-d29e34310d4a" CreationDate="2022-04-10T16:18:35.667" UserId="18256" Text="Suppose that someone implemented rendering for a video game using entirely GPGPU apis, like compute shaders or CUDA.&#xD;&#xA;&#xD;&#xA;Would it be possible to achieve the same performance as standard graphics pipelines on common modern GPUs? If not, then what hardware do standard graphics pipelines have access to which general purpose GPU programming APIs dont give access to?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36716" PostHistoryTypeId="1" PostId="12610" RevisionGUID="1e849459-2b73-4e36-8b77-d29e34310d4a" CreationDate="2022-04-10T16:18:35.667" UserId="18256" Text="On modern GPUs, what hardware do vertex/pixel shaders have access to that compute shaders don't?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36717" PostHistoryTypeId="3" PostId="12610" RevisionGUID="1e849459-2b73-4e36-8b77-d29e34310d4a" CreationDate="2022-04-10T16:18:35.667" UserId="18256" Text="|rendering|shader|compute-shader|hardware|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36718" PostHistoryTypeId="2" PostId="12611" RevisionGUID="f7104904-9293-4399-9fc9-99fdfa5f5ad4" CreationDate="2022-04-10T16:27:09.290" UserId="2654" Text="&gt; what hardware do standard graphics pipelines have access to which general purpose GPU programming APIs dont give access to?&#xD;&#xA;&#xD;&#xA;Every part of the [graphics pipeline and architecture][1] that isn't a shader. This includes but is not limited to:&#xD;&#xA;&#xD;&#xA;* The rasterizer&#xD;&#xA;* The post T&amp;L cache&#xD;&#xA;* Any vertex buffer fetching/decompressing logic&#xD;&#xA;* ROPs, which do read/modify&amp;test/write operation with the framebuffer, such as:&#xD;&#xA;    * blending&#xD;&#xA;    * depth/stencil testing&#xD;&#xA;    * write masking&#xD;&#xA;* All of the hardware buffers and pipelines between various stages&#xD;&#xA;&#xD;&#xA;None of these are accessible by shader logic. They're hard-wired parts of the graphics pipeline.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview" ContentLicense="CC BY-SA 4.0" />
  <row Id="36720" PostHistoryTypeId="50" PostId="2516" RevisionGUID="1baa47ed-cd7b-4067-8229-aedab3938915" CreationDate="2022-04-10T17:01:10.093" UserId="-1" />
  <row Id="36721" PostHistoryTypeId="52" PostId="12610" RevisionGUID="2d333212-8f36-4e2b-9b95-7106939e5ec7" CreationDate="2022-04-11T00:19:29.000" />
  <row Id="36723" PostHistoryTypeId="2" PostId="12612" RevisionGUID="8d72e3c9-f664-44f5-bcc3-02aff615bae4" CreationDate="2022-04-11T10:15:04.527" UserId="2316" Text="I can't actually spot the problem from your pictures, but the problem you describe is a very common one for new developers trying to implement transparency, so I'll assume it's there.&#xD;&#xA;&#xD;&#xA;**The problem:**&#xD;&#xA;&#xD;&#xA;Let's consider what happens to a single pixel. In boring old opaque rendering, we expect the pixel to have the frontmost triangle at that pixel (closest to the camera, lowest Z value). This can be done with a depth buffer: the GPU stores the Z coordinate of the frontmost triangle that touches the pixel so far, and overwrites the pixel when drawing a triangle in front of that, and doesn't overwrite it when drawing a triangle behind that. Therefore the final result has the colour from the frontmost triangle.&#xD;&#xA;&#xD;&#xA;However this simple algorithm *only works* for fully opaque triangles. With a translucent triangle, instead of just overwriting the colour of the pixel, the GPU combines it with the colour already in the colour buffer. If some of the triangles are skipped because of the depth buffer algorithm, the final colour is wrong. The only case when it's right is when the triangles are drawn in back-to-front order. And *if you use the typical alpha blending algorithm for translucency*, then you can't just solve it by turning off the depth buffer, because the colour is calculated differently depending on which order the triangles are rendered in, and it's only correct when they are drawn in back-to-front order (when you get the correct result whether the depth buffer is on or off).&#xD;&#xA;&#xD;&#xA;**The solution:**&#xD;&#xA;&#xD;&#xA;If you only have fully opaque and fully transparent pixels, a *really easy solution* is to enable alpha test. Pixels with 0 alpha will be fully discarded and won't update the depth buffer. Pixels with 1.0 alpha will act as opaque. &#xD;&#xA;&#xD;&#xA;    glEnable(GL_ALPHA_TEST); // &lt;- literally that simple&#xD;&#xA;&#xD;&#xA;If you have partially translucent pixels, then you have two options: either *actually render front-to-back* or implement one of the schemes of *order-independent transparency*. All of these options have significant tradeoffs. Fortunately, you appear to have only fully transparent pixels, so it is not necessary to delve into either." ContentLicense="CC BY-SA 4.0" />
  <row Id="36725" PostHistoryTypeId="2" PostId="12613" RevisionGUID="61198f6a-8754-46f0-81ad-ea6e20e3455f" CreationDate="2022-04-11T10:25:27.047" UserId="2316" Text="Since you only want full brightness and no brightness, sure you can.&#xD;&#xA;&#xD;&#xA;Red channel on: additive blend with red  &#xD;&#xA;Red channel off: multiplicative blend with cyan  &#xD;&#xA;Blue channel on: additive blend with blue  &#xD;&#xA;Blue channel off: multiplicative blend with yellow&#xD;&#xA;&#xD;&#xA;I also don't understand why you can't just run your rendering code twice: once with a red color mask and once with a blue color mask. It doesn't seem like you need to control it from GLSL. You're allowed to render the same vertices twice with different states - commercial video games do that sort of thing routinely.&#xD;&#xA;&#xD;&#xA;Switching the blend mode from additive to multiplicative is a state change, just like setting the colour mask." ContentLicense="CC BY-SA 4.0" />
  <row Id="36728" PostHistoryTypeId="50" PostId="10748" RevisionGUID="32809dbb-a33a-454a-88ef-30e6436941fd" CreationDate="2022-04-11T17:07:45.650" UserId="-1" />
  <row Id="36729" PostHistoryTypeId="2" PostId="12614" RevisionGUID="e62722a5-5a72-4e8b-9e71-95880d47ef24" CreationDate="2022-04-11T17:43:30.820" UserId="18264" Text="I am looking for an algorithm which would smoothly interpolate triangles of a mesh (computed by Delaunay triangulation) where each vertex has some value (elevation in my case). I need it for [PDAL][1] where I want to try to implement it. Its current implementation uses linear interpolation which makes the result not so pleasant:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;(image is already post-processed to display the result as hill-shading)&#xD;&#xA;&#xD;&#xA;Is there some public algorithm which would interpolate it smoothly, without sharp edges? Result should be a raster (rectangular grid of points).&#xD;&#xA;&#xD;&#xA;  [1]: https://pdal.io&#xD;&#xA;  [2]: https://i.stack.imgur.com/m9T2P.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36731" PostHistoryTypeId="1" PostId="12614" RevisionGUID="e62722a5-5a72-4e8b-9e71-95880d47ef24" CreationDate="2022-04-11T17:43:30.820" UserId="18264" Text="Smooth triangular mesh interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="36732" PostHistoryTypeId="3" PostId="12614" RevisionGUID="e62722a5-5a72-4e8b-9e71-95880d47ef24" CreationDate="2022-04-11T17:43:30.820" UserId="18264" Text="|mesh|interpolation|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36733" PostHistoryTypeId="2" PostId="12615" RevisionGUID="829834d3-e853-4bcc-952c-6c0c8e30d9ab" CreationDate="2022-04-11T18:09:20.797" UserId="18220" Text="I was able to solve my problem, I realized I wasn't using the `std::ios::binary` flag when writing to the file, but adding it seemed to solve my problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="36735" PostHistoryTypeId="2" PostId="12616" RevisionGUID="9bd84076-315f-42e0-8328-1f335b882d5e" CreationDate="2022-04-12T01:55:30.047" UserId="18237" Text="After lots of delving, eventually I learned that what I was trying to do is an established practice called “still image camera matching” or just “camera matching”.&#xD;&#xA;&#xD;&#xA;It’s used in special effects, augmented reality, traffic analysis etc.&#xD;&#xA;&#xD;&#xA;It’s the process of recovering information about a camera using a photo taken by the camera as reference.&#xD;&#xA;&#xD;&#xA;There’s an open source project which does exactly this: https://fspy.io/&#xD;&#xA;&#xD;&#xA;Not the easiest to use, but gets the job done." ContentLicense="CC BY-SA 4.0" />
  <row Id="36737" PostHistoryTypeId="2" PostId="12617" RevisionGUID="c83f9db0-ec8c-4bdf-a662-adad35a0fa11" CreationDate="2022-04-12T06:31:20.500" UserId="6064" Text="I wished to understand which mip map in the chain of mips is selected upon sampling a texture.Which factors it depends on.I know that it depends on the area of the texture visible.&#xD;&#xA;&#xD;&#xA;I tried a simple application recently to try out reserved resource textures but I am having trouble understanding one situation in it.&#xD;&#xA;&#xD;&#xA;test application details:rendering a full screen quad on a window via dx12.The quad is textured by a texture(reserved resource).&#xD;&#xA;&#xD;&#xA;test cases:&#xD;&#xA;1.&#xD;&#xA;the texture used is large(5184X3456) and the mip auto selected is 2nd.&#xD;&#xA;&#xD;&#xA;2.&#xD;&#xA;the texture used is small(256X256) and the mip auto selected is 0th.&#xD;&#xA;&#xD;&#xA;both the textures contains full mip chain and nothing other than the size of texture is changing here so why is larger one using 2nd mip rather 0th like smaller tex(I am rendering both of them on a full screen quad).Is the size of texture also a factor in auto mip selection?&#xD;&#xA;Sampler used is same in both the cases:D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36739" PostHistoryTypeId="1" PostId="12617" RevisionGUID="c83f9db0-ec8c-4bdf-a662-adad35a0fa11" CreationDate="2022-04-12T06:31:20.500" UserId="6064" Text="mipmap selection process" ContentLicense="CC BY-SA 4.0" />
  <row Id="36740" PostHistoryTypeId="3" PostId="12617" RevisionGUID="c83f9db0-ec8c-4bdf-a662-adad35a0fa11" CreationDate="2022-04-12T06:31:20.500" UserId="6064" Text="|opengl|directx12|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36741" PostHistoryTypeId="2" PostId="12618" RevisionGUID="d990300a-e827-44a4-a8e3-1763920b886c" CreationDate="2022-04-12T18:22:22.380" UserId="48" Text="Mipmap selection is done by looking at adjacent pixels on the screen, and finding how far apart their texture samples fall. The mip level is chosen so as to make the space between adjacent texture samples approximately 1 texel.&#xD;&#xA;&#xD;&#xA;For example if you have a 4K texture and display it 1K wide on the screen, then adjacent pixels will be sampling points 4 texels apart (at the base mip), and so the hardware will choose mip level 2 (which is 1/4th the resolution). At mip level 2, the sample points are 1 texel apart.&#xD;&#xA;&#xD;&#xA;Conversely, if you have a 256×256 texture and display it 1K wide, then adjacent pixels will be sampling points only 0.25 texels apart. In this case, since the spacing is less than 1 texel it will use mip level 0.&#xD;&#xA;&#xD;&#xA;So, it's not really about either the size of the texture or the area of texture that's visible, at least not directly. It's about the ratio of texels to pixels." ContentLicense="CC BY-SA 4.0" />
  <row Id="36743" PostHistoryTypeId="50" PostId="10045" RevisionGUID="e0f86ea9-d611-43a9-90a8-3f2a51489e2c" CreationDate="2022-04-12T22:01:40.150" UserId="-1" />
  <row Id="36744" PostHistoryTypeId="2" PostId="12619" RevisionGUID="d80de78c-b983-4fcd-9344-2cb06ccaa8b7" CreationDate="2022-04-13T02:20:57.773" UserId="17045" Text="Almost a month after I posted this question I finally found the answer.&#xD;&#xA;&#xD;&#xA;The steps I took:&#xD;&#xA;&#xD;&#xA;1. I decided to disable blending altogether and play with it:&#xD;&#xA;[![no-blending][1]][1]&#xD;&#xA;&#xD;&#xA;2. But when inspecting the produced image more closely I noticed that the outline was still there, and it was sticking outside of the rendered quad, which suggested that it's a post-processing effect:&#xD;&#xA;[![more closely][2]][2]&#xD;&#xA;&#xD;&#xA;3. I decided to browse through the settings of the graphics driver and found this:&#xD;&#xA;[![oh dear, radeon][3]][3]&#xD;&#xA;&#xD;&#xA;Disabling it removed the outline.&#xD;&#xA;&#xD;&#xA;[hard-facepalm-sound.ogg]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zgOAA.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/7BKlL.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vULgf.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36746" PostHistoryTypeId="50" PostId="2146" RevisionGUID="fa3cdcd5-93d5-41af-b39f-be2f9d908c4a" CreationDate="2022-04-13T10:04:50.407" UserId="-1" />
  <row Id="36747" PostHistoryTypeId="2" PostId="12620" RevisionGUID="81473244-be84-4eb5-8395-3377f876c7f3" CreationDate="2022-04-13T11:51:27.253" UserId="18272" Text="I'm a total newbie to coding and recently got interested into generative art.&#xD;&#xA;This is my problem:&#xD;&#xA;I have to copy all of the functions I need (and there are a lot) in every single fragment file I'm working on.&#xD;&#xA;I'm wondering if there is a way to keep all the functions in a separate file(s) and import what I need, into the fragment file I'm working on.&#xD;&#xA;Thanks.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36749" PostHistoryTypeId="1" PostId="12620" RevisionGUID="81473244-be84-4eb5-8395-3377f876c7f3" CreationDate="2022-04-13T11:51:27.253" UserId="18272" Text="GLSL, Fragment Shader: How to separate functions (like noise, transform...) to reuse in different projects" ContentLicense="CC BY-SA 4.0" />
  <row Id="36750" PostHistoryTypeId="3" PostId="12620" RevisionGUID="81473244-be84-4eb5-8395-3377f876c7f3" CreationDate="2022-04-13T11:51:27.253" UserId="18272" Text="|shader|glsl|pixel-shader|function|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36751" PostHistoryTypeId="50" PostId="11048" RevisionGUID="2d1f4237-34a8-45d1-81d4-97f30ab4338b" CreationDate="2022-04-13T16:03:00.243" UserId="-1" />
  <row Id="36752" PostHistoryTypeId="50" PostId="8886" RevisionGUID="29d03d23-87cb-4345-833d-84667b5332dd" CreationDate="2022-04-13T17:04:15.367" UserId="-1" />
  <row Id="36753" PostHistoryTypeId="50" PostId="11049" RevisionGUID="430e2886-65f9-4768-8dbb-f7fdfe02aa02" CreationDate="2022-04-13T19:00:55.117" UserId="-1" />
  <row Id="36758" PostHistoryTypeId="2" PostId="12622" RevisionGUID="f561fb69-cecb-4626-b561-8cf55963760a" CreationDate="2022-04-14T15:17:08.463" UserId="16879" Text="Perspective projection matrices we use map 3D coords onto some imaginary image plane in front of the cameras pinhole position by casting a ray directly from the eye position to that 3d coordinate and seeing where it intersects the image plane.&#xD;&#xA;&#xD;&#xA;But if you take your average 4x4 perspective projection matrix (assume no reversed z or infinite far plane at the moment), where exactly is this thing? As in, if you drew a diagram, where would you draw this &quot;world space image plane&quot; and all the contents in it?&#xD;&#xA;&#xD;&#xA;It must be one of the planes orthogonal to the view direction. All points projected onto any of these planes will produce the same image only differing in scale. Yet presumably in one of them the ray along the top left of the view frustum of the camera will strike the image plane at the coordinate [-1,1] (depending on your choice of clip space coordinates), and the depth value of this intersection is disregarded (instead the distance of the point from the camera receives a custom remapping function for various reasons) and so on for the other frustum edges. &#xD;&#xA;&#xD;&#xA;But I'm having a hard time figuring out how this can be with cameras that don't have a 1:1 aspect ratio. If I'm drawing a classical view frustum on paper and check some intersections on the frustum corners, it's never at [x,y] with |x| = |y|. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36760" PostHistoryTypeId="1" PostId="12622" RevisionGUID="f561fb69-cecb-4626-b561-8cf55963760a" CreationDate="2022-04-14T15:17:08.463" UserId="16879" Text="Where exactly is the image plane / plane of projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="36761" PostHistoryTypeId="3" PostId="12622" RevisionGUID="f561fb69-cecb-4626-b561-8cf55963760a" CreationDate="2022-04-14T15:17:08.463" UserId="16879" Text="|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36762" PostHistoryTypeId="2" PostId="12623" RevisionGUID="5783ad72-6083-4999-b031-4247d4a5cb34" CreationDate="2022-04-14T17:42:34.857" UserId="18271" Text="This post is hidden. You deleted this post 1 min ago.&#xD;&#xA;&#xD;&#xA;Is this possible with GLFW? AFAIK you can't use GLFW to create a child window per se, so the question probably boils down on how to turn a GLFW created, opengl enabled window into a child window and assign the parent window." ContentLicense="CC BY-SA 4.0" />
  <row Id="36764" PostHistoryTypeId="1" PostId="12623" RevisionGUID="5783ad72-6083-4999-b031-4247d4a5cb34" CreationDate="2022-04-14T17:42:34.857" UserId="18271" Text="GLFW: create embeddable opengl child window and set parent on Mac?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36765" PostHistoryTypeId="3" PostId="12623" RevisionGUID="5783ad72-6083-4999-b031-4247d4a5cb34" CreationDate="2022-04-14T17:42:34.857" UserId="18271" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36766" PostHistoryTypeId="2" PostId="12624" RevisionGUID="8cdd71df-b796-4883-8f08-2315cefd2ebc" CreationDate="2022-04-14T21:38:15.993" UserId="18034" Text="I have been struggling very much to wrap my head around this part of Peter Shirley's book. There is no explanation what the angle Alpha represents and to make things worse in the code the cos(Alpha) is calculated is the y component of the direction vector from hit point to a random point on the light source. The whole thing makes no sense and I am struggling to find any resources to help me along. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/d4Xac.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36768" PostHistoryTypeId="1" PostId="12624" RevisionGUID="8cdd71df-b796-4883-8f08-2315cefd2ebc" CreationDate="2022-04-14T21:38:15.993" UserId="18034" Text="importance sampling rectangular light" ContentLicense="CC BY-SA 4.0" />
  <row Id="36769" PostHistoryTypeId="3" PostId="12624" RevisionGUID="8cdd71df-b796-4883-8f08-2315cefd2ebc" CreationDate="2022-04-14T21:38:15.993" UserId="18034" Text="|raytracing|pathtracing|monte-carlo|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36771" PostHistoryTypeId="2" PostId="12625" RevisionGUID="b4b01460-9106-416d-9f01-2a420c56ef99" CreationDate="2022-04-15T04:34:19.063" UserId="2654" Text="&gt; where exactly is this thing?&#xD;&#xA;&#xD;&#xA;Nowhere. It's imaginary; it doesn't exist and doesn't have a position in space.&#xD;&#xA;&#xD;&#xA;For a given point in camera space, the projection matrix defines a line between that point and the camera. You could consider the plane of projection to be any plane along that line (perpendicular to the camera view), with the point being projected defined by the intersection of that line with the plane.&#xD;&#xA;&#xD;&#xA;The math doesn't need a projection plane. The idea is solely for the benefit of imagining how it would look.&#xD;&#xA;&#xD;&#xA;&gt; But I'm having a hard time figuring out how this can be with cameras that don't have a 1:1 aspect ratio.&#xD;&#xA;&#xD;&#xA;This is simulated by applying a non-uniform scale to the X and Y of the projection matrices." ContentLicense="CC BY-SA 4.0" />
  <row Id="36773" PostHistoryTypeId="2" PostId="12626" RevisionGUID="8d86800a-9d91-447a-9db9-5f1f37bc5fde" CreationDate="2022-04-15T05:27:57.557" UserId="48" Text="From looking at the equations, it looks to me like alpha must be the angle between the surface normal of the light source, and the ray direction. This is the &quot;projected area&quot; factor: the amount of solid angle subtended at the receiving point has to be scaled based on how much the light source is tilted away from the receiver.&#xD;&#xA;&#xD;&#xA;The calculation of cos(alpha) as the y component of the direction vector, I suppose, must be in the coordinate system of the rectangle light, where xz is the plane of the rectangle. In such coordinates, the normal will be (0, 1, 0), and cos(alpha) would reduce to dot(direction, normal) which would be direction.y." ContentLicense="CC BY-SA 4.0" />
  <row Id="36780" PostHistoryTypeId="50" PostId="8695" RevisionGUID="9b7e547d-ad4c-40de-b185-aa4a526aa36b" CreationDate="2022-04-15T23:01:05.167" UserId="-1" />
  <row Id="36786" PostHistoryTypeId="2" PostId="12629" RevisionGUID="59efd36c-99b1-4327-9029-9ed3ecbdd3d7" CreationDate="2022-04-16T02:49:29.310" UserId="17510" Text="I've seen some phrases like 'free-path', 'free-path distributions', 'mean free path' in some computer graphics resources, but none of them explains what does these phrases mean, does anyone have an explanation of these phrases? Thanks a lot!" ContentLicense="CC BY-SA 4.0" />
  <row Id="36788" PostHistoryTypeId="1" PostId="12629" RevisionGUID="59efd36c-99b1-4327-9029-9ed3ecbdd3d7" CreationDate="2022-04-16T02:49:29.310" UserId="17510" Text="What does 'free-path' mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36789" PostHistoryTypeId="3" PostId="12629" RevisionGUID="59efd36c-99b1-4327-9029-9ed3ecbdd3d7" CreationDate="2022-04-16T02:49:29.310" UserId="17510" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36794" PostHistoryTypeId="2" PostId="12631" RevisionGUID="b09ac750-d432-48d2-ad5e-ab7baa4c887e" CreationDate="2022-04-16T22:05:59.037" UserId="48" Text="The term &quot;free path&quot; usually shows up in the context of Monte Carlo simulation of volumetric scattering—i.e., rendering such things as smoke, fog, or clouds in a path tracer. In this context, interactions between a light ray and the volume are treated as random events: the picture is that the photon flies through the volume &quot;freely&quot; (without interacting) for some random distance, then is absorbed or scattered at a discrete point. If scattered, it then flies off in another direction for another random distance, and may interact a second time, and so forth.&#xD;&#xA;&#xD;&#xA;The &quot;free path&quot; is the distance that a photon travels in the volume between interactions. This is a random quantity, so sometimes we see &quot;mean free path&quot;, which is the mean distance to the next interaction. In a homogeneous volume, scattering events are modeled as a Poisson process, so the distribution of free path distances is an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution). In such a case, the mean free path is the inverse of the scattering coefficient. A greater scattering coefficient means the volume interacts with photons more often, so the mean free path gets shorter, and vice versa. &#xD;&#xA;&#xD;&#xA;In a path tracer, when a ray enters a volume (or starts inside a volume), we would then sample that distribution to determine how far the ray should go. If it does not exit the volume or strike some other object before the sampled free-path distance, then it interacts with the volume, and we do further sampling to see what direction it scatters, etc., to set up the next path segment.&#xD;&#xA;&#xD;&#xA;In heterogeneous volumes, the algorithms get more complicated, but the same principles apply. Also, there is some research dealing with so-called [&quot;non-exponential media&quot;](https://rgl.epfl.ch/publications/Vicini2021NonExponential), in which the free path distribution is something other than the standard exponential one (i.e. breaking the Poisson assumption that interactions at different points in the volume are independent of each other)." ContentLicense="CC BY-SA 4.0" />
  <row Id="36796" PostHistoryTypeId="2" PostId="12632" RevisionGUID="3ecc61b8-d0af-4a79-b636-d7247ca16c8a" CreationDate="2022-04-16T22:18:14.507" UserId="18286" Text="What is the difference between particles system and smoothed particles hydrodynamic(SPH) ?&#xD;&#xA;&#xD;&#xA;is SPH a more specific version of particles system ?&#xD;&#xA;&#xD;&#xA;More searches on google I do more confusing I get since articles don't accurate when talking about concepts" ContentLicense="CC BY-SA 4.0" />
  <row Id="36798" PostHistoryTypeId="1" PostId="12632" RevisionGUID="3ecc61b8-d0af-4a79-b636-d7247ca16c8a" CreationDate="2022-04-16T22:18:14.507" UserId="18286" Text="What is the difference between particles system and smoothed particles hydrodynamic?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36799" PostHistoryTypeId="3" PostId="12632" RevisionGUID="3ecc61b8-d0af-4a79-b636-d7247ca16c8a" CreationDate="2022-04-16T22:18:14.507" UserId="18286" Text="|simulation|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36800" PostHistoryTypeId="50" PostId="5697" RevisionGUID="7aeefe9d-727b-495b-8cb9-444f194bca75" CreationDate="2022-04-17T08:00:20.053" UserId="-1" />
  <row Id="36802" PostHistoryTypeId="2" PostId="12633" RevisionGUID="5d944918-d27b-4136-88e0-424884a9a7ae" CreationDate="2022-04-18T16:09:02.350" UserId="48" Text="Particle systems are used in graphics to represent phenomena like fire, smoke, fog, sparks, splashes, small bits of debris like rocks, splinters, or leaves, as well as magic or sci-fi effects like spells, energy charges, etc. They involve large numbers of lightweight particle entities often rendered as sprites or simple meshes, generated randomly and obeying simple simulation rules, usually without much physics interactions with each other or with the rest of the scene. The primary purpose of particle systems is to create a visual effect as opposed to an accurate simulation, so their appearance and behavior is very much artist-driven.&#xD;&#xA;&#xD;&#xA;SPH is a kind of fluid simulation using discrete particle entities to represent parcels of fluid. They are used to estimate the fluid density/pressure/velocity/etc at a given point by averaging over the particles nearby. The advection of fluids is represented by directly moving the particles through space. This is in contrast to the grid-based approach to fluid simulation, where fluid properties are stored at discrete grid points and advection is performed by resampling the grid. There are advantages and disadvantages to both approaches. SPH particles are not usually used directly for rendering; instead, one might use marching cubes or similar to extract an isosurface from a density field defined by the particles, and render that.&#xD;&#xA;&#xD;&#xA;There is not much in common between these besides that they use the metaphor of &quot;particles&quot;, meaning large numbers of lightweight discrete entities that move around in space according to some rules. One is for a visual effect and is whatever the artist desires, the other is a class of methods for computational fluid dynamics." ContentLicense="CC BY-SA 4.0" />
  <row Id="36804" PostHistoryTypeId="50" PostId="8209" RevisionGUID="f7eded91-9f0e-4881-9fc0-73af96378f2f" CreationDate="2022-04-19T04:04:05.353" UserId="-1" />
  <row Id="36806" PostHistoryTypeId="2" PostId="12634" RevisionGUID="fd0b2995-c0f4-426e-8f49-2f607ce16119" CreationDate="2022-04-20T15:41:33.957" UserId="6064" Text=" what exactly does the rasterizer outputs as per my knowlage it outputs primitives rasterized as fragments which seems correct as the next step in vulkan/opengl is fragment shader but dx confuses me here because there the step after rasterization is pixel shader.Is it just a convention for dx to call it pixel shader even though it runs per fragment or is my understanding incorrect that rasterizer outputs fragments.Also what is the size of a fragment?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36808" PostHistoryTypeId="1" PostId="12634" RevisionGUID="fd0b2995-c0f4-426e-8f49-2f607ce16119" CreationDate="2022-04-20T15:41:33.957" UserId="6064" Text="what is the output from rasterizer" ContentLicense="CC BY-SA 4.0" />
  <row Id="36809" PostHistoryTypeId="3" PostId="12634" RevisionGUID="fd0b2995-c0f4-426e-8f49-2f607ce16119" CreationDate="2022-04-20T15:41:33.957" UserId="6064" Text="|opengl|vulkan|directx12|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36810" PostHistoryTypeId="2" PostId="12635" RevisionGUID="9b99c5f3-aa4a-499e-8f92-5fbdf8260481" CreationDate="2022-04-20T18:07:55.527" UserId="482" Text="In general, a rasterizer converts a vector description of an image to a raster description, like converting (*center&lt;sub&gt;x&lt;/sub&gt; center&lt;sub&gt;y&lt;/sub&gt; radius color*) to a bitmap of a shaded circle. Literally, the rasters are the *rakes* ([unrelated implement named from the same Latin root](http://en.wikipedia.org/wiki/Rastrum)) or scanlines of the image, so they might be interally represented as rows of a bitmap or a run-length encoding or a set of cooefficients for a fourier transform or something. &#xD;&#xA;&#xD;&#xA;The process can be considered as projecting the scanlines backwards into the model space and detecting where these lines intersect with the boundaries of objects. A distributed shader might produce a small bitmap or a few scanlines which must be reintegrated to produce the full image.&#xD;&#xA;&#xD;&#xA;In a finer-grained setting, the rasterizer could be isolated to just detecting the edges of objects and then call the pixel shader for the smaller range of the scanline where it's actually inside of the object." ContentLicense="CC BY-SA 4.0" />
  <row Id="36812" PostHistoryTypeId="2" PostId="12636" RevisionGUID="5c244121-c04f-42ec-bd76-a9a6458cb7cd" CreationDate="2022-04-21T07:19:46.187" UserId="18304" Text="I am loading an image to shaders in Vulkan, but do not wish to use it as a texture. I wish to access the texels exactly as they are to decode the information I compressed in it. How should I do it? More specifically, I do not wish to use the filtering, mipmaping, address modes, and so on that usually accompanies a texture. I just want to load an image.&#xD;&#xA;&#xD;&#xA;New to Vulkan and computer graphics, thanks for anyone's help." ContentLicense="CC BY-SA 4.0" />
  <row Id="36814" PostHistoryTypeId="1" PostId="12636" RevisionGUID="5c244121-c04f-42ec-bd76-a9a6458cb7cd" CreationDate="2022-04-21T07:19:46.187" UserId="18304" Text="loading images not through sampler" ContentLicense="CC BY-SA 4.0" />
  <row Id="36815" PostHistoryTypeId="3" PostId="12636" RevisionGUID="5c244121-c04f-42ec-bd76-a9a6458cb7cd" CreationDate="2022-04-21T07:19:46.187" UserId="18304" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36816" PostHistoryTypeId="50" PostId="12353" RevisionGUID="231bad90-fc46-42e7-9ac6-7e035b0671ce" CreationDate="2022-04-21T08:07:30.850" UserId="-1" />
  <row Id="36817" PostHistoryTypeId="2" PostId="12637" RevisionGUID="61338465-f7de-4c29-8357-7531e985335d" CreationDate="2022-04-21T11:05:08.197" UserId="7952" Text="In Vulkan &quot;everything is a buffer&quot;. So the image can be loaded into a buffer and accessed directly. Copies to/from VkBuffer are detailed in section 18.4 of the Vulkan spec. Its fairly straight forward to do. Another way is to use VK_IMAGE_TILING_LINEAR when creating images. But linear tiling has many downsides, both have performance ramifications...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="36819" PostHistoryTypeId="5" PostId="1843" RevisionGUID="1bed0c45-bd6e-4a3e-9f51-67388e86424b" CreationDate="2022-04-21T13:38:53.840" UserId="2355" Comment="Make the explanation and the actual code shown match." Text="Changed the core profile to `3.2` by setting the window hints.&#xD;&#xA;&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);&#xD;&#xA;    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);&#xD;&#xA;    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);" ContentLicense="CC BY-SA 4.0" />
  <row Id="36820" PostHistoryTypeId="2" PostId="12638" RevisionGUID="0f7410af-7bd3-4075-adf5-fd55ee39fd14" CreationDate="2022-04-21T21:40:51.527" UserId="2654" Text="&gt; I wish to access the texels exactly as they are to decode the information I compressed in it.&#xD;&#xA;&#xD;&#xA;If it's not in an image format that Vulkan understands, then it's not an image as far as Vulkan is concerned. It's just a bunch of bytes.&#xD;&#xA;&#xD;&#xA;You can access a bunch of bytes stored in device-accessible memory through a shader storage buffer." ContentLicense="CC BY-SA 4.0" />
  <row Id="36822" PostHistoryTypeId="50" PostId="9591" RevisionGUID="ae993426-adbc-4bf7-ae34-d73a6258a614" CreationDate="2022-04-22T01:06:30.580" UserId="-1" />
  <row Id="36827" PostHistoryTypeId="2" PostId="12640" RevisionGUID="805e39a3-a910-4b72-bb56-87dac0830a6b" CreationDate="2022-04-22T02:46:12.777" UserId="18310" Text="You are correct in your understanding that the rasterizer produces fragments. Each fragment can be thought of as a quasi-pixel, in that geometry may generate more than one fragment for the same pixel (such as in multisampling). The pixel shader's job is to take those fragments and compute lighting, color, etc., to produce the final pixel that gets written to the target buffer.&#xD;&#xA;&#xD;&#xA;In essence: Vertex Shader -&gt; Rasterizer -&gt; Fragment -&gt; Pixel Shader -&gt; Pixel&#xD;&#xA;&#xD;&#xA;You might also find the DX11 documentation [here](https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-graphics-pipeline), and [this](https://stackoverflow.com/questions/31173002/what-is-the-difference-between-a-sample-a-pixel-and-a-fragment) question about the difference between fragments, samples, and pixels to be useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="36829" PostHistoryTypeId="2" PostId="12641" RevisionGUID="58d50e3a-58c5-40f8-8c53-02d0a5574815" CreationDate="2022-04-22T13:37:57.900" UserId="18312" Text="I'm working on a fluid simulation project where two spheres are simulated using smoothed particle hydrodynamics (SPH). I have generated two sets of particles inside and on the surface of a sphere. You can see the result in this picture:&#xD;&#xA;&#xD;&#xA;[scatter plot of spheres' particles][1]&#xD;&#xA;&#xD;&#xA;I am going to extract the surface of the particles by the marching cubes algorithm. Currently, I am using &quot;scikit-image&quot; implementation of marching cubes in python, and I got this result:&#xD;&#xA;&#xD;&#xA;[Reconstructed surfaces and particles][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In the above picture, two small spheres are scattered plots of my particles, and two large surfaces are the reconstructed surface that I got from the marching cube algorithm.&#xD;&#xA;&#xD;&#xA;I have two problems:&#xD;&#xA;&#xD;&#xA;1- As you can see, the surfaces are not smooth enough. So, I'm looking for an efficient method to make these surfaces smoother with a more sphere shape. The function that I used for surface reconstruction of my SHPs is:&#xD;&#xA;&#xD;&#xA;    Phi(x) = - c + sum_{j in N(x)} of (V_j * W(x - x_j, h))&#xD;&#xA;where `c` is the surface threshold, `x` is the position where we want to evaluate, `sum_{j in N(x)}` is the sum over all particles `j` in the neighborhood of point `x`, `V_j` is the volume of particle `j`, `W` is the SPH kernel function, `x_j` is the position of particle `j`, and `h` is the kernel smoothing length&#xD;&#xA;&#xD;&#xA;2- The surfaces are supposed to exactly lie on particles as they are constructed to cover the outer surfaces of the particles. But as you can see in the picture, two surfaces are located somewhere far from the particles. I think my voxelization is not correct.&#xD;&#xA;&#xD;&#xA;The code that I have written for surface reconstruction is:&#xD;&#xA;&#xD;&#xA;    def surface_reconstruction(rezolution=20, surfacelevel=0, bounds=(-4, 4)):&#xD;&#xA;        # First I creat my voxel grid&#xD;&#xA;        x = np.linspace(bounds[0], bounds[1], rezolution)&#xD;&#xA;        y = np.linspace(bounds[0], bounds[1], rezolution)&#xD;&#xA;        z = np.linspace(bounds[0], bounds[1], rezolution)&#xD;&#xA;&#xD;&#xA;        xx, yy, zz = np.meshgrid(x, y, z)&#xD;&#xA;        surface = np.zeros((len(xx), len(yy), len(zz)))&#xD;&#xA;        # Then I loop over each voxel's corner and find a value for that point to check whether &#xD;&#xA;        # it is inside the mesh or no?&#xD;&#xA;        for i in range(len(xx)):&#xD;&#xA;            for j in range(len(yy)):&#xD;&#xA;                for k in range(len(zz)):&#xD;&#xA;                    for p1 in env.particles:&#xD;&#xA;                        # p1.X is the position of particle p1. Here, I compute the distance &#xD;&#xA;                        # between each particle and voxel coordinate&#xD;&#xA;                        dX = p1.X - [xx[i, j, k], yy[i, j, k], zz[i, j, k]]&#xD;&#xA;                        r = np.linalg.norm(dX)&#xD;&#xA;                        # p1.H is a kernel radius of particle p1&#xD;&#xA;                        if r &lt;= p1.H:&#xD;&#xA;                            # p1.vol is particle p1 volume&#xD;&#xA;                            # Wij is a kernel function of SPH&#xD;&#xA;                            surface[i, j, k] += -surfacelevel + p1.vol * Wij(r, p1.H)&#xD;&#xA;       return surface&#xD;&#xA;Then I apply marching cubes on &quot;surface&quot;&#xD;&#xA;&#xD;&#xA;    verts, faces, normals, values = skimage.measure.marching_cubes(surface_reconstruction(), 0)&#xD;&#xA;&#xD;&#xA;So, I am wondering&#xD;&#xA;&#xD;&#xA;1- How can I make the surfaces smoother?&#xD;&#xA;&#xD;&#xA;2- Why surfaces are larger than particles scale and far from particles?&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lOlW8.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/izV5Q.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36831" PostHistoryTypeId="1" PostId="12641" RevisionGUID="58d50e3a-58c5-40f8-8c53-02d0a5574815" CreationDate="2022-04-22T13:37:57.900" UserId="18312" Text="How to extract surface of smoothed particle hydrodynamics smoothly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36832" PostHistoryTypeId="3" PostId="12641" RevisionGUID="58d50e3a-58c5-40f8-8c53-02d0a5574815" CreationDate="2022-04-22T13:37:57.900" UserId="18312" Text="|particles|fluid-sim|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36839" PostHistoryTypeId="50" PostId="8260" RevisionGUID="93cb0488-441f-4319-ac57-fc8b930a19fd" CreationDate="2022-04-23T10:01:00.107" UserId="-1" />
  <row Id="36840" PostHistoryTypeId="2" PostId="12643" RevisionGUID="3d608952-c17a-41a5-a335-2646065a4063" CreationDate="2022-04-23T19:43:05.380" UserId="18306" Text="For a good and scalable project structure, what fields would you add to a camera class, apart from its position and orientation? Should I add the near and far planes? Or should that be global, what about the FOV? And worse, what about the yaw, pitch and roll variables? (which I think might be global but I'm not 100% sure)." ContentLicense="CC BY-SA 4.0" />
  <row Id="36842" PostHistoryTypeId="1" PostId="12643" RevisionGUID="3d608952-c17a-41a5-a335-2646065a4063" CreationDate="2022-04-23T19:43:05.380" UserId="18306" Text="What fields should a camera class have?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36843" PostHistoryTypeId="3" PostId="12643" RevisionGUID="3d608952-c17a-41a5-a335-2646065a4063" CreationDate="2022-04-23T19:43:05.380" UserId="18306" Text="|3d|transformations|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36844" PostHistoryTypeId="5" PostId="12623" RevisionGUID="dce63bd6-6af6-4db1-89cf-a308b2a8de19" CreationDate="2022-04-23T21:03:54.020" UserId="48" Comment="deleted 57 characters in body" Text="Is this possible with GLFW? AFAIK you can't use GLFW to create a child window per se, so the question probably boils down on how to turn a GLFW created, opengl enabled window into a child window and assign the parent window." ContentLicense="CC BY-SA 4.0" />
  <row Id="36845" PostHistoryTypeId="2" PostId="12644" RevisionGUID="9bd0de6b-8e43-45ba-88ee-472bfd0b2cc1" CreationDate="2022-04-23T21:30:59.140" UserId="48" Text="You can set up the VkImage as usual, then in your shaders you can use [`texelFetch`](https://docs.gl/sl4/texelFetch) to load a specific texel at the coordinates you specify. It still takes a sampler parameter, but addressing modes are not applied and no filtering or automatic mipmapping is done.&#xD;&#xA;&#xD;&#xA;Depending on what kind of data you stored in your image, you might also want to use an int or uint image format rather than the typical unorm, so that you'll get the exact bits you stored without any conversion." ContentLicense="CC BY-SA 4.0" />
  <row Id="36849" PostHistoryTypeId="50" PostId="5220" RevisionGUID="d76924c3-f785-4fca-935e-72bd04709cd7" CreationDate="2022-04-25T00:06:45.630" UserId="-1" />
  <row Id="36850" PostHistoryTypeId="5" PostId="12637" RevisionGUID="317aee28-6113-4e68-a20b-f6729a6907e6" CreationDate="2022-04-25T11:09:11.733" UserId="7952" Comment="added 545 characters in body" Text="In Vulkan &quot;everything is a buffer&quot;. So the image can be loaded into a buffer and accessed directly. Copies to/from VkBuffer are detailed in section 18.4 of the Vulkan spec. Its fairly straight forward to do. Another way is to use VK_IMAGE_TILING_LINEAR when creating images. But linear tiling has many downsides, both have performance ramifications...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As a way to flip a texture vertically in the shader:&#xD;&#xA;&#xD;&#xA;    float flipped_y = 1 - texcoord.y;&#xD;&#xA;&#xD;&#xA;This changes texture coordinates in the range [0,1] to coords in the range [1,0]. (this is handy for debugging but should not be used generically)&#xD;&#xA;&#xD;&#xA;Vulkan has the texture origin at the top left corner of the image, OpenGL has the texture origin at the bottom left corner. So images created for OpenGL can end up flipped vertically in Vulkan.&#xD;&#xA;&#xD;&#xA;Vulkan doesn't do anything to change the actual values. It just handles them differently from OpenGL.&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="36857" PostHistoryTypeId="50" PostId="12359" RevisionGUID="94afc20f-f195-4ffd-89b8-6a13d2c78949" CreationDate="2022-04-26T07:04:05.467" UserId="-1" />
  <row Id="36865" PostHistoryTypeId="2" PostId="12647" RevisionGUID="5e5d8b41-0aee-4cf8-9191-59dc54030df0" CreationDate="2022-04-26T11:51:02.463" UserId="7952" Text="This is one of those &quot;ask 10 different programmers and get 10 different answers&quot; types of questions. Also the &quot;right&quot; answer is going to depend heavily on the requirements of the program. &#xD;&#xA;&#xD;&#xA;Having said that, good programming practices server this type of problem well. Based on that I would recommend keeping the Camera info which ultimately produces the View matrix, and the projection info which is used to generate a projection matrix decoupled.&#xD;&#xA;&#xD;&#xA;For projection info something as simple as a POD holding near, far, aspect, and fov. This info can be passed to the camera as needed, and if it is truly necessary the camera can &quot;have a&quot; projection info inside it, or at least refer to one. It also provides a simple way to pass all the info needed to a &quot;GenerateProjection&quot; function (or similar). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For a camera class, functions that provide movement/rotation and View matrix generation typically dictate the private data and this depends on how the camera is coded. For example a camera that uses polar coordinates will be very different from one that uses quaternions. It is also handy to have functions that allow access to both the CameraToWorld matrix and the WorldToCamera aka View matrix since both are often needed for other calculations. Fields that hold constant data can be useful, for switching the camera between Z up or Y up worlds for example. These can be simple compile time code (such as using &quot;if constexpr (IsZup) {...}&quot;) Keeping the view matrix in the class can be handy but when both the CameraToWorld matrix and WorldToCamera matrix are needed every frame, just having a function that computes, and returns them can be more useful. Both then end up sitting a per frame data structure. This allows multiple frames to be floating around in the system without any one frame being tied directly to the camera class. Again, this is a requirements thing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; A &quot;lookAt&quot; function can be handy as a way to generate alternate camera views for things like lighting and can be used to generate a matrix for a spot light. Functions like this tend to creep into camera code because they are so similar, but also can lead to extraneous fields that the class doesn't really need. (finding ways to share code and data between competing algorithms can be challenging)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36867" PostHistoryTypeId="50" PostId="9163" RevisionGUID="5d5c034e-5220-4dfb-acf0-498c00553491" CreationDate="2022-04-26T17:05:00.533" UserId="-1" />
  <row Id="36869" PostHistoryTypeId="2" PostId="12648" RevisionGUID="94d92419-0bc8-4fa0-a544-c9c2bd2cbf2f" CreationDate="2022-04-27T12:05:40.493" UserId="18335" Text="You may be able to eliminate the triangular artifacts by using Natural Neighbor Interpolation.  You can find a description of the technique and an associated description of the algorithm at [An Introduction to Natural Neighbor Interpolation][1].   I've got an open-source implementation in Java.  And while it won't solve your problem (since you're working in C/C++), you could run your data through the Tinfour Viewer demonstration application to see how it looks under Natural Neighbor Interpolation. That would, at least, tell you if it was worth further consideration.  If you're interested, you can find more information at the [Tinfour Project][2].&#xD;&#xA;&#xD;&#xA;It looks like your input data is from a Lidar source.  So here's a picture of some Lidar data taken over Bear Mountain in Salisbury, CT, USA. Interpolation was performed using NNI. NNI works fine when your data represents a coherent surface.  For Lidar, that means sticking to all ground points or all first returns.  If you start mixing in things like tree branches and other vegetation, you'd be better served by something like an Inverse Distance Weighting solution.&#xD;&#xA;&#xD;&#xA;[![Lidar sample over Bear Mountain][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gwlucastrig.github.io/TinfourDocs/NaturalNeighborIntro/index.html&#xD;&#xA;  [2]: https://github.com/gwlucastrig/Tinfour&#xD;&#xA;  [3]: https://i.stack.imgur.com/sghlz.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="36871" PostHistoryTypeId="50" PostId="9178" RevisionGUID="b2fd9894-d982-4487-87b2-8b6b77fc2607" CreationDate="2022-04-27T15:04:55.553" UserId="-1" />
  <row Id="36874" PostHistoryTypeId="50" PostId="12366" RevisionGUID="c7ce2514-b410-44f9-92eb-f783486bf444" CreationDate="2022-04-29T10:02:50.313" UserId="-1" />
  <row Id="36880" PostHistoryTypeId="2" PostId="12650" RevisionGUID="10ef3cc7-a45d-419d-a324-eb5a3c72a6fe" CreationDate="2022-05-01T14:30:09.843" UserId="6064" Text="I would like to understand how anisotripic filtering works in gpu.&#xD;&#xA;Specifically what is the minimum state in which the texture needs to be in for anisotropic filtering to work.&#xD;&#xA;by state of the texture I mean the content(mip level data) of the texture.&#xD;&#xA;For example if I try load just to 0th mip for the texture and use anisotropic filtering will it work or the full mip chain needs to be loaded for anisotropic filter to work correctly(no artifacts in output).&#xD;&#xA;The information is needed as I am working with sampler feedback streaming so I want to make sure I do not miss any cases which might lead to artifacts(namely I will start the sparse texture will just the least detailed tail mips loaded,so will aniso filter work correctly with it or not)? " ContentLicense="CC BY-SA 4.0" />
  <row Id="36882" PostHistoryTypeId="1" PostId="12650" RevisionGUID="10ef3cc7-a45d-419d-a324-eb5a3c72a6fe" CreationDate="2022-05-01T14:30:09.843" UserId="6064" Text="How Anisotropic filtering works" ContentLicense="CC BY-SA 4.0" />
  <row Id="36883" PostHistoryTypeId="3" PostId="12650" RevisionGUID="10ef3cc7-a45d-419d-a324-eb5a3c72a6fe" CreationDate="2022-05-01T14:30:09.843" UserId="6064" Text="|opengl|vulkan|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36884" PostHistoryTypeId="2" PostId="12651" RevisionGUID="5b60841f-cfd5-4639-95e8-1429e205a9ce" CreationDate="2022-05-01T15:03:16.210" UserId="2654" Text="Anisotropic filtering (and any other filtering process) will respect the base/max level settings for the texture they're fetching from. So as long as those settings are properly provided, it will never fetch garbage data if the mipmap pyramid is incomplete.&#xD;&#xA;&#xD;&#xA;Anisotrpoic filtering will be more effective (ie: look better given a particular sample count) if more of the pyramid is available. But that's about it." ContentLicense="CC BY-SA 4.0" />
  <row Id="36886" PostHistoryTypeId="52" PostId="12650" RevisionGUID="22db7049-d452-45e6-86be-d96944e27c18" CreationDate="2022-05-01T22:30:27.563" />
  <row Id="36887" PostHistoryTypeId="50" PostId="12384" RevisionGUID="498d7876-c6ec-485f-9e37-8b5845c8e77a" CreationDate="2022-05-02T16:04:00.370" UserId="-1" />
  <row Id="36888" PostHistoryTypeId="2" PostId="12652" RevisionGUID="9daa4ea5-d42a-40bc-b4a8-7da559d579e3" CreationDate="2022-05-02T17:54:20.183" UserId="17985" Text="Is it possible to convert Polar to Cartesian coordinates and map result to an image?&#xD;&#xA;&#xD;&#xA;I want to get the output same as the `distort depolar 0` from image magick.&#xD;&#xA;&#xD;&#xA;[https://legacy.imagemagick.org/Usage/distorts/#depolar][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://legacy.imagemagick.org/Usage/distorts/#depolar&#xD;&#xA;&#xD;&#xA;Is it possible to get the same output using opengl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36890" PostHistoryTypeId="1" PostId="12652" RevisionGUID="9daa4ea5-d42a-40bc-b4a8-7da559d579e3" CreationDate="2022-05-02T17:54:20.183" UserId="17985" Text="Is it possible to convert Polar to Cartesian coordinates and map result to an image using opengl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36891" PostHistoryTypeId="3" PostId="12652" RevisionGUID="9daa4ea5-d42a-40bc-b4a8-7da559d579e3" CreationDate="2022-05-02T17:54:20.183" UserId="17985" Text="|opengl|image-processing|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36892" PostHistoryTypeId="2" PostId="12653" RevisionGUID="0ef04e01-8da5-4a1a-a911-7ee2b467d7c8" CreationDate="2022-05-03T10:01:50.657" UserId="7647" Text="You'd be doing a change of coordinates from polar to Cartesian; at output point $(x,y)$ draw polar coordinate $(\theta = 2 \pi x, r = y)$. The coordinates in a unit circle drawn in the input image are $(r \cos \theta, r \sin \theta)$. In OpenGL this'd be drawn from a sampler, so the input image $u$ and $v$ coordinates would be in $[0,1]$ and you'd have to sample instead from a circle of radius 0.5 centered at $(0.5,0.5)$, resulting in $\mathrm{out}(x,y) = \mathrm{in}(0.5 + 0.5 * r * \cos \theta, 0.5 + 0.5 * r * \sin \theta)$.&#xD;&#xA;&#xD;&#xA;Here's a fragment shader function I tested at [Shadertoy](https://www.shadertoy.com) that performs this transformation:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;{&#xD;&#xA;    // Normalized pixel coordinates (from 0 to 1)&#xD;&#xA;    vec2 xy = fragCoord/iResolution.xy;&#xD;&#xA;&#xD;&#xA;    // map x to theta and y to r on unit circle&#xD;&#xA;    float theta = 2.0 * 3.14159265368979 * xy.x;&#xD;&#xA;    float r = xy.y;&#xD;&#xA;    &#xD;&#xA;    // map unit circle to circle of radius 0.5 centered at (0.5,0.5)&#xD;&#xA;    vec2 uv = vec2(0.5 + 0.5*r*cos(theta), 0.5 + 0.5*r*sin(theta));&#xD;&#xA;&#xD;&#xA;    // texture lookup&#xD;&#xA;    float v = texture(iChannel0,uv).x;&#xD;&#xA;&#xD;&#xA;    // Output to screen&#xD;&#xA;    fragColor = vec4(v,v,v,1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36910" PostHistoryTypeId="2" PostId="12656" RevisionGUID="e0f74ee2-d668-41b4-817e-826e3d191190" CreationDate="2022-05-04T09:03:21.923" UserId="13273" Text="I am implementing Variance Shadow Mapping from Nvidia GPU Gems 3 Chapter 8:&#xD;&#xA;[Summed-Area Variance Shadow Maps][1]&#xD;&#xA;&#xD;&#xA;There they are talking about clamping the minimum variance to a very small value. I did that and depending on that value I can decide between two different errors.&#xD;&#xA;&#xD;&#xA;But first, here is the fragment shader for creating the shadow map:&#xD;&#xA;&#xD;&#xA;    varying vec4 positionLightSpace;&#xD;&#xA;    vec2 computeMoments(float distToLight) &#xD;&#xA;    {&#xD;&#xA;      vec2 moments;&#xD;&#xA;      moments.x = distToLight;&#xD;&#xA;      float dx = dFdx(distToLight);&#xD;&#xA;      float dy = dFdy(distToLight);&#xD;&#xA;      moments.y = distToLight * distToLight + 0.25 * (dx * dx + dy * dy);&#xD;&#xA;      return moments;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main() &#xD;&#xA;    {&#xD;&#xA;      //convert length to [m]. otherwise the derivatives (dFdx, dFdy) are 0&#xD;&#xA;      float distToLight = length(1.0e3 * positionLightSpace.xyz);&#xD;&#xA;      gl_FragColor = vec4(computeMoments(distToLight), 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;After creating this shadow map, the shadow map will be blurred by a gaussian 3x3 filter to smooth the edges.&#xD;&#xA;&#xD;&#xA;And this is the fragment shader to check whether there is shadow or not:&#xD;&#xA;&#xD;&#xA;    float chebyshevUpperBound(sampler2D shadowTex, vec4 shadowCoord, float depth)&#xD;&#xA;    {&#xD;&#xA;      vec2 moments = texture2D(shadowTex, shadowCoord.xy).xy;&#xD;&#xA;      //One-tailed inequality valid if distance &gt; moments.x&#xD;&#xA;      float p = (depth &lt;= moments.x) ? 1.0 : 0.0;&#xD;&#xA;      //Compute variance&#xD;&#xA;      float minVariance = 1.0e-7; // &lt;=== this is the value I am talking about ===&#xD;&#xA;      float variance = moments.y - (moments.x * moments.x);&#xD;&#xA;      variance = max(variance, minVariance);&#xD;&#xA;      //Compute probabilistic upper bound&#xD;&#xA;      float deltaDepth = depth - moments.x;&#xD;&#xA;      float pMax = variance / (variance + deltaDepth * deltaDepth);&#xD;&#xA;      //clamp pMax in order to reduce light bleeding&#xD;&#xA;      float minVal = 0.1;&#xD;&#xA;      float maxVal = 1.0;&#xD;&#xA;      pMax = smoothstep(minVal, maxVal, pMax);&#xD;&#xA;      return max(p, pMax);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When setting `minVariance` to value 1.0e-7, the shadow looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Here the black dots (1) occur when surface normal vector points close towards the light direction (not good).&#xD;&#xA;Light bleeding (3) occurs at some regions (not good). but the shadows starts even for small distance differences (2)(very good). So the shadow touches the geometry, which I prefer.  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When setting `minVariance` to value 1.0e-2, the shadow looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Here the black dots (1) have disappeared (very good). Light bleeding (3) has gone as well (very good). But the shadows starts at far distance (2) (not good).&#xD;&#xA;&#xD;&#xA;I tested to set the `minVariance` to values between 1.0e-7 and 1.0e-2. But no setting fulfills the aspect to cancel &quot;light bleeding&quot; and the black dots and start shadow at small distances.&#xD;&#xA;How can I achieve that? &#xD;&#xA;&#xD;&#xA;BTW: The shadow texture has format: RGB32F. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-8-summed-area-variance-shadow-maps&#xD;&#xA;  [2]: https://i.stack.imgur.com/f13QO.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4Zi9l.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36912" PostHistoryTypeId="1" PostId="12656" RevisionGUID="e0f74ee2-d668-41b4-817e-826e3d191190" CreationDate="2022-05-04T09:03:21.923" UserId="13273" Text="Variance Shadow Mapping (Shadow occurs when normal vector is close to light direction)" ContentLicense="CC BY-SA 4.0" />
  <row Id="36913" PostHistoryTypeId="3" PostId="12656" RevisionGUID="e0f74ee2-d668-41b4-817e-826e3d191190" CreationDate="2022-05-04T09:03:21.923" UserId="13273" Text="|opengl|shadow|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36930" PostHistoryTypeId="50" PostId="10384" RevisionGUID="162a08d5-7cfe-4647-befb-dab2e608876c" CreationDate="2022-05-06T10:05:15.533" UserId="-1" />
  <row Id="36931" PostHistoryTypeId="50" PostId="9426" RevisionGUID="edb19759-ac05-4002-a034-455b43e22f16" CreationDate="2022-05-06T14:00:45.067" UserId="-1" />
  <row Id="36936" PostHistoryTypeId="2" PostId="12660" RevisionGUID="62372809-8dba-4d4d-afeb-c925aa97c4d6" CreationDate="2022-05-07T09:27:52.883" UserId="5256" Text="I want to get the coordinates of my mouse after the left mouse button is released after being held down in OpenGL? I am new to this and wanted to know how I can implement it." ContentLicense="CC BY-SA 4.0" />
  <row Id="36938" PostHistoryTypeId="1" PostId="12660" RevisionGUID="62372809-8dba-4d4d-afeb-c925aa97c4d6" CreationDate="2022-05-07T09:27:52.883" UserId="5256" Text="How to get coordinates of mouse after left mouse button is released in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36939" PostHistoryTypeId="3" PostId="12660" RevisionGUID="62372809-8dba-4d4d-afeb-c925aa97c4d6" CreationDate="2022-05-07T09:27:52.883" UserId="5256" Text="|opengl|curve|mouse|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36940" PostHistoryTypeId="5" PostId="12660" RevisionGUID="a2673579-b1ef-4d50-86c9-606a2bd58312" CreationDate="2022-05-07T09:49:08.560" UserId="5256" Comment="deleted 2 characters in body; edited title" Text="I want to get the coordinates of my mouse after the left mouse button is released after being dragged in OpenGL? I am new to this and wanted to know how I can implement it." ContentLicense="CC BY-SA 4.0" />
  <row Id="36941" PostHistoryTypeId="4" PostId="12660" RevisionGUID="a2673579-b1ef-4d50-86c9-606a2bd58312" CreationDate="2022-05-07T09:49:08.560" UserId="5256" Comment="deleted 2 characters in body; edited title" Text="How to get coordinates of mouse after left mouse button is released after drag in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36947" PostHistoryTypeId="2" PostId="12662" RevisionGUID="92cde5ad-a906-48fe-bc15-249f6596ec48" CreationDate="2022-05-07T23:22:23.327" UserId="5256" Text="   I found this method and I believe I am using GLUT.&#xD;&#xA;&#xD;&#xA;    // If left button was clicked&#xD;&#xA;        if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN) &#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        // Event after mouse is clicked and released&#xD;&#xA;        else if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_UP) &#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }" ContentLicense="CC BY-SA 4.0" />
  <row Id="36949" PostHistoryTypeId="2" PostId="12663" RevisionGUID="e7936f89-2201-4b43-a879-35182e03249f" CreationDate="2022-05-07T23:37:16.467" UserId="5256" Text="I am trying to implement the pen tool from Adobe Illustrator in OpenGL. I am trying to get the coordinates of the reverse tangent upon mouse release. I tried negating the coordinates I got upon mouse release but that doesn't seem to work.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myMouse(int button, int state, int x, int y) {&#xD;&#xA;&#xD;&#xA;    int DirectionHandleX;&#xD;&#xA;    int DirectionHandleY;&#xD;&#xA;&#xD;&#xA;    // If left button was clicked&#xD;&#xA;    if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN) &#xD;&#xA;    {&#xD;&#xA;        drawDot(x, SCREEN_HEIGHT - y);&#xD;&#xA;    }&#xD;&#xA;    else if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_UP) &#xD;&#xA;    {&#xD;&#xA;        DirectionHandleX = x;&#xD;&#xA;        DirectionHandleY = y;&#xD;&#xA;        drawDot(DirectionHandleX, SCREEN_HEIGHT - DirectionHandleY);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hO0lg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36951" PostHistoryTypeId="1" PostId="12663" RevisionGUID="e7936f89-2201-4b43-a879-35182e03249f" CreationDate="2022-05-07T23:37:16.467" UserId="5256" Text="How to get coordinates of opposite direction from mouse release point relative to a point?" ContentLicense="CC BY-SA 4.0" />
  <row Id="36952" PostHistoryTypeId="3" PostId="12663" RevisionGUID="e7936f89-2201-4b43-a879-35182e03249f" CreationDate="2022-05-07T23:37:16.467" UserId="5256" Text="|opengl|bezier-curve|point|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36953" PostHistoryTypeId="2" PostId="12664" RevisionGUID="18780fce-8062-4e0f-8268-b8e91c422a79" CreationDate="2022-05-08T00:10:37.703" UserId="18369" Text="Assuming you're doing spline curves: Let p be the point at the end of your curve (the one marked with a solid square above). Let h be your handle point (the one denoted as such). The vector from p to h is (h-p). To get the other handle point, take p + -(h-p). This can be more concisely written 2p-h." ContentLicense="CC BY-SA 4.0" />
  <row Id="36955" PostHistoryTypeId="2" PostId="12665" RevisionGUID="4e88a413-6f98-4b9e-ad04-324bdf92be0d" CreationDate="2022-05-08T01:46:51.133" UserId="18370" Text="A watertight mesh is one which does not have holes, and for which each face has a designated inside and outside. Such a mesh can be &quot;tetrahedralized&quot;, has a defined volume, and can be an operand in a polyhedral boolean operation.&#xD;&#xA;&#xD;&#xA;I'm looking for a method to represent such watertight meshes that reduces the amount of invalid states or singularities. As an example of what I mean, consider a simple mesh of vertex positions and triplets of indices that represent triangles. This is a poor way to represent a watertight mesh because the set of representable meshes largely does not intersect the set of watertight meshes. As a somewhat opposite example, consider a convex hull described by a set of points. This representation has the opposite problem: while every representable mesh is watertight (for now overlooking singularities like a hull defined exclusively by points lying within the same plane), watertight meshes with concavity are not representable.&#xD;&#xA;&#xD;&#xA;One possible solution would be to store a set of points, then a set of indices into these points that describe a convex hull that completely encloses the watertight mesh. In addition to these, store zero or more sets of indices that describe convex hulls to be subtracted from the first convex hull to add concavity. This would, with a few singularities, restrict representable meshes to the set of watertight meshes. Requiring each set of indices to contain at least 4 vertices would further reduce the number of singularities in this system.&#xD;&#xA;&#xD;&#xA;Are there other ways to represent watertight meshes and operate on them? Possibly a more commonly used, better-researched, or more intuitive way? Common useful operations would include boolean operations or tetrahedralization/triangulation of the resulting mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="36957" PostHistoryTypeId="1" PostId="12665" RevisionGUID="4e88a413-6f98-4b9e-ad04-324bdf92be0d" CreationDate="2022-05-08T01:46:51.133" UserId="18370" Text="Watertight Mesh Representation" ContentLicense="CC BY-SA 4.0" />
  <row Id="36958" PostHistoryTypeId="3" PostId="12665" RevisionGUID="4e88a413-6f98-4b9e-ad04-324bdf92be0d" CreationDate="2022-05-08T01:46:51.133" UserId="18370" Text="|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36959" PostHistoryTypeId="5" PostId="12663" RevisionGUID="91a7bc3b-4e11-4316-9db2-28c040b137b2" CreationDate="2022-05-08T01:59:09.487" UserId="5256" Comment="deleted 3 characters in body" Text="I am trying to implement the pen tool from Adobe Illustrator in OpenGL. I am trying to get the coordinates of the reverse tangent upon mouse release. I tried negating the coordinates I got upon mouse release but that doesn't seem to work.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myMouse(int button, int state, int x, int y) {&#xD;&#xA;&#xD;&#xA;    int DirectionHandleX;&#xD;&#xA;    int DirectionHandleY;&#xD;&#xA;&#xD;&#xA;    // If left button was clicked&#xD;&#xA;    if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN) &#xD;&#xA;    {&#xD;&#xA;        drawDot(x, SCREEN_HEIGHT - y);&#xD;&#xA;    }&#xD;&#xA;    else if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_UP) &#xD;&#xA;    {&#xD;&#xA;        DirectionHandleX = x;&#xD;&#xA;        DirectionHandleY = y;&#xD;&#xA;        drawDot(DirectionHandleX, SCREEN_HEIGHT - DirectionHandleY);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hO0lg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="36966" PostHistoryTypeId="2" PostId="12667" RevisionGUID="c1575aa1-f40b-4279-9fa5-ae2dd2cc0155" CreationDate="2022-05-09T00:46:10.410" UserId="482" Text="One way to approach this topic that can help is to distinguish between points and vectors as distinct *types* and make sure your operations fit into one of the &quot;known good&quot; scenarios:&#xD;&#xA;&#xD;&#xA;1. Point + Vector = Point&#xD;&#xA;1. Point - Vector = Point&#xD;&#xA;1. Point - Point = Vector&#xD;&#xA;1. Point + Point = total nonsense&#xD;&#xA;1. Scalar * Vector = Vector&#xD;&#xA;1. Scalar * Point = total nonsense&#xD;&#xA;&#xD;&#xA;You can think of this as the points are the real dots on the screen and vectors are just invisible arrows. You can only get a point from a vector if you attach it (ie. *add* it) to another point.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36968" PostHistoryTypeId="2" PostId="12668" RevisionGUID="3493c689-04b8-4eb0-b2c3-334ab9ef9005" CreationDate="2022-05-09T08:45:37.653" UserId="13273" Text="I am trying to implement shadow mapping. Therefore I am trying to render the back faces of the geometry to reduce the shadow acne.&#xD;&#xA;&#xD;&#xA;When culling back faces everything works (the geometry will be rendered).&#xD;&#xA;When culling front faces, the geometry is invisible.&#xD;&#xA;&#xD;&#xA;what could be reasons for that behavior?&#xD;&#xA;&#xD;&#xA;BTW: The geometry is closed (so when rendering only the back faces you should see it).&#xD;&#xA;the fragment shader is not checking for face direction... so there is not the problem.&#xD;&#xA;&#xD;&#xA;I replaced the fragment shader to:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(1,1,1,1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the result is still black (wrong).&#xD;&#xA;But when rendering front faces, the result is white (correct)&#xD;&#xA;&#xD;&#xA;I am using &#xD;&#xA;&#xD;&#xA;    glFrontFace(GL_CCW); &#xD;&#xA;    glEnable(GL_CULL_FACE); &#xD;&#xA;    glCullFace(GL_FRONT);" ContentLicense="CC BY-SA 4.0" />
  <row Id="36970" PostHistoryTypeId="1" PostId="12668" RevisionGUID="3493c689-04b8-4eb0-b2c3-334ab9ef9005" CreationDate="2022-05-09T08:45:37.653" UserId="13273" Text="geometry is invisible when culling front faces" ContentLicense="CC BY-SA 4.0" />
  <row Id="36971" PostHistoryTypeId="3" PostId="12668" RevisionGUID="3493c689-04b8-4eb0-b2c3-334ab9ef9005" CreationDate="2022-05-09T08:45:37.653" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="36981" PostHistoryTypeId="5" PostId="12667" RevisionGUID="a7f5721f-a565-47d1-a99e-4cf752d4d8bc" CreationDate="2022-05-09T19:23:25.227" UserId="482" Comment="added 665 characters in body" Text="One way to approach this topic that can help is to distinguish between points and vectors as distinct *types* and make sure your operations fit into one of the &quot;known good&quot; scenarios:&#xD;&#xA;&#xD;&#xA;1. Point + Vector = Point&#xD;&#xA;1. Point - Vector = Point&#xD;&#xA;1. Point - Point = Vector&#xD;&#xA;1. Point + Point = total nonsense&#xD;&#xA;1. Scalar * Vector = Vector  &#xD;&#xA;   eg. *-1* * Vector = -Vector, the reverse direction&#xD;&#xA;1. Scalar * Point = total nonsense  &#xD;&#xA;   eg. *-1* * Point = a conceptual mistake, you can reverse a vector but not a point&#xD;&#xA;&#xD;&#xA;You can think of this as the points are the real dots on the screen and vectors are just invisible arrows. You can only get a point from a vector if you attach it (ie. *add* it) to another point.&#xD;&#xA;&#xD;&#xA;You can also kind of think of this as the points are *unsigned* quantities and the vectors are *signed* quantities. The points have only position, whereas the vectors have only direction -- even though they can have the exact same representation in the computer. You could enforce the distinction to some degree by using integers for points and floating point for vector components. This also emphasizes the scalability of vectors, a feature that points lack.&#xD;&#xA;&#xD;&#xA;Aside: a more apt analogy in programming might be to consider points as *`*`pointers* and vectors as *`ptrdiff_t`s*. But those would be a bad choice of types for implementing these objects for graphics." ContentLicense="CC BY-SA 4.0" />
  <row Id="36982" PostHistoryTypeId="5" PostId="12668" RevisionGUID="3abec671-1775-47c3-855a-133be8d8a1ba" CreationDate="2022-05-10T07:17:05.130" UserId="13273" Comment="added 415 characters in body" Text="I am trying to implement shadow mapping. Therefore I am trying to render the back faces of the geometry to reduce the shadow acne.&#xD;&#xA;&#xD;&#xA;When culling back faces everything works (the geometry will be rendered).&#xD;&#xA;When culling front faces, the geometry is invisible.&#xD;&#xA;&#xD;&#xA;what could be reasons for that behavior?&#xD;&#xA;&#xD;&#xA;BTW: The geometry is closed (so when rendering only the back faces you should see it).&#xD;&#xA;the fragment shader is not checking for face direction... so there is not the problem.&#xD;&#xA;&#xD;&#xA;I replaced the fragment shader to:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(1,1,1,1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the result is still black (wrong).&#xD;&#xA;But when rendering front faces, the result is white (correct)&#xD;&#xA;&#xD;&#xA;I am using &#xD;&#xA;&#xD;&#xA;    glFrontFace(GL_CCW); &#xD;&#xA;    glEnable(GL_CULL_FACE); &#xD;&#xA;    glCullFace(GL_FRONT);&#xD;&#xA;&#xD;&#xA;I've also tried to do this:&#xD;&#xA;disabling culling and add the following to the fragment shader:&#xD;&#xA;&#xD;&#xA;    if(gl_FrontFacing == true)&#xD;&#xA;    {&#xD;&#xA;        discard;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In principle it is like culling, with difference, that I have a lot of fragment calls... but when doing this way, it works perfectly. But this is not an option due to the bad performance. But it shows me, that the front face culling should work :/&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="36983" PostHistoryTypeId="5" PostId="12668" RevisionGUID="c1528b2b-bbca-4f16-b994-b4bc441d5b95" CreationDate="2022-05-10T07:32:47.530" UserId="13273" Comment="added 126 characters in body" Text="I am trying to implement shadow mapping. Therefore I am trying to render the back faces of the geometry to reduce the shadow acne.&#xD;&#xA;&#xD;&#xA;When culling back faces everything works (the geometry will be rendered).&#xD;&#xA;When culling front faces, the geometry is invisible.&#xD;&#xA;&#xD;&#xA;what could be reasons for that behavior?&#xD;&#xA;&#xD;&#xA;BTW: The geometry is closed (so when rendering only the back faces you should see it).&#xD;&#xA;the fragment shader is not checking for face direction... so there is not the problem.&#xD;&#xA;&#xD;&#xA;I replaced the fragment shader to:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(1,1,1,1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the result is still black (wrong).&#xD;&#xA;But when rendering front faces, the result is white (correct)&#xD;&#xA;&#xD;&#xA;I am using &#xD;&#xA;&#xD;&#xA;    glFrontFace(GL_CCW); &#xD;&#xA;    glEnable(GL_CULL_FACE); &#xD;&#xA;    glCullFace(GL_FRONT);&#xD;&#xA;&#xD;&#xA;I've also tried to do this:&#xD;&#xA;disabling culling and add the following to the fragment shader:&#xD;&#xA;&#xD;&#xA;    if(gl_FrontFacing == true)&#xD;&#xA;    {&#xD;&#xA;        discard;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In principle it is like culling, with difference, that I have a lot of fragment calls... but when doing this way, it works perfectly. But this is not an option due to the bad performance. But it shows me, that the front face culling should work :/&#xD;&#xA;&#xD;&#xA;I tried to define front face as CW (which is wrong... my front face is CCW) and culling back faces. This is working as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="36984" PostHistoryTypeId="5" PostId="12668" RevisionGUID="970106d3-f270-431b-9357-2e3719bfdfb1" CreationDate="2022-05-10T07:57:10.270" UserId="13273" Comment="added 126 characters in body" Text="I am trying to implement shadow mapping. Therefore I am trying to render the back faces of the geometry to reduce the shadow acne.&#xD;&#xA;&#xD;&#xA;When culling back faces everything works (the geometry will be rendered).&#xD;&#xA;When culling front faces, the geometry is invisible.&#xD;&#xA;&#xD;&#xA;what could be reasons for that behavior?&#xD;&#xA;&#xD;&#xA;BTW: The geometry is closed (so when rendering only the back faces you should see it).&#xD;&#xA;the fragment shader is not checking for face direction... so there is not the problem.&#xD;&#xA;&#xD;&#xA;I replaced the fragment shader to:&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(1,1,1,1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the result is still black (wrong).&#xD;&#xA;But when rendering front faces, the result is white (correct)&#xD;&#xA;&#xD;&#xA;I am using &#xD;&#xA;&#xD;&#xA;    glFrontFace(GL_CCW); &#xD;&#xA;    glEnable(GL_CULL_FACE); &#xD;&#xA;    glCullFace(GL_FRONT);&#xD;&#xA;&#xD;&#xA;I've also tried to do this:&#xD;&#xA;disabling culling and add the following to the fragment shader:&#xD;&#xA;&#xD;&#xA;    if(gl_FrontFacing == true)&#xD;&#xA;    {&#xD;&#xA;        discard;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;In principle it is like culling, with difference, that I have a lot of fragment calls... but when doing this way, it works perfectly. But this is not an option due to the bad performance. But it shows me, that the front face culling should work :/&#xD;&#xA;&#xD;&#xA;I tried to define front face as CW (which is wrong... my front face is CCW) and culling back faces. This is working as well. But my favorite and easiest to understand solution would be to define front face as CCW and culling front faces when needed. " ContentLicense="CC BY-SA 4.0" />
  <row Id="36997" PostHistoryTypeId="5" PostId="12662" RevisionGUID="381d4d60-c1f5-4bf1-b1d6-78ed942df5da" CreationDate="2022-05-10T22:27:12.087" UserId="5256" Comment="added 60 characters in body" Text="   I found this method and I am using GLUT.&#xD;&#xA;&#xD;&#xA;    void myMouse(int button, int state, int x, int y) &#xD;&#xA;    {&#xD;&#xA;    // If left button was clicked&#xD;&#xA;        if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN) &#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        // Event after mouse is clicked and released&#xD;&#xA;        else if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_UP) &#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37005" PostHistoryTypeId="2" PostId="12674" RevisionGUID="4decf91f-dbc6-4337-94b1-16e25633a795" CreationDate="2022-05-11T10:36:05.813" UserId="228" Text="I am reading through [Kajiya - Ray Tracing Volume Densities][1] paper. And I've already got stuck into section 2. I wonder if there's a mistake in that equation.&#xD;&#xA;&#xD;&#xA;I'll quote the relevant bit&#xD;&#xA;&#xD;&#xA;&gt; The quantity to be calculated in a scattering problem is the energy per unit solid angle per unit area&#xD;&#xA;$$&#xD;&#xA;dE = I(x,\omega)\sin\vartheta d\omega d\sigma&#xD;&#xA;$$&#xD;&#xA;This quantity is called the *intesity* of radiation at a point $x$ in the direction of the solid angle $d\omega$. The scattering equation can be derived by considering a differential cylindrical volume $dV = d\sigma ds$, where $d\sigma$ is the cross section of the cylinder and $ds$ is the length. If we follow a pencil of radiation along the length of the cylinder, we find the difference in intensity between the two ends is given by&#xD;&#xA;$$&#xD;&#xA;dI = -absorbed + emitted = -k\rho ds d\sigma d\omega + j \rho ds d\sigma d\omega&#xD;&#xA;$$&#xD;&#xA;where $\rho$ is the density of the matter in the volume element $k$ is the absorbption coefficient...&#xD;&#xA;&#xD;&#xA;I believe there's a mistake in the absorbed intensity expression, there's a reference quoted at the very beginning of the section where this formulation is taken from (the reference is [Chandrasekhar - Radiative Transfer][2]). I cannot to manage what later the paper defines as scattering equation&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{k\rho} s\cdot\nabla_xI(x,s) - I(x,s) + \frac{1}{4\pi} \int_{\left\lVert s \right\rVert = 1} p(s,\overline{s})I(x,\overline{s}) d\overline{s}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I believe in the reference (Chandrasekhar) I've found what was used for Kajiya's derivation, I'll put an image just in case not everyone can see it from the preview:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In Chandrasekhar's formula 44 there's a $I_\nu$ factor, which should correspond to $I(x,s)$ in Kajiya's. And formula (48) in Chandrasekhar is exactly the same as Kajiya's scattering equation, except that the former takes into account in his formulation time and wavelength. But apart from this they're the same.&#xD;&#xA;&#xD;&#xA;So I suspect there's a typo in Kajiya's. I think in general absorption is formulate as some form of exponatial decay of the form $f'(x) = -\alpha f(x)$, which is used in Chandrasekhar.&#xD;&#xA;&#xD;&#xA;Can you confirm if my suspicion is correct? Thank you&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/publication/234800181_Ray_Tracing_Volume_Densities&#xD;&#xA;  [2]: https://www.google.co.uk/books/edition/Radiative_Transfer/K7YLRcTP_XUC?hl=en&amp;gbpv=1&amp;dq=chandrasekhar%20radiative%20transfer%20pdf&amp;printsec=frontcover&#xD;&#xA;  [3]: https://i.stack.imgur.com/elb9Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37007" PostHistoryTypeId="1" PostId="12674" RevisionGUID="4decf91f-dbc6-4337-94b1-16e25633a795" CreationDate="2022-05-11T10:36:05.813" UserId="228" Text="Error in equation 2.1. in Ray Tracing Volume Densities" ContentLicense="CC BY-SA 4.0" />
  <row Id="37008" PostHistoryTypeId="3" PostId="12674" RevisionGUID="4decf91f-dbc6-4337-94b1-16e25633a795" CreationDate="2022-05-11T10:36:05.813" UserId="228" Text="|mathematics|volumetric-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37009" PostHistoryTypeId="5" PostId="12674" RevisionGUID="2e4a297c-cdc1-4bed-997f-dcd39846f3a4" CreationDate="2022-05-11T11:07:39.740" UserId="228" Comment="added 165 characters in body" Text="I am reading through [Kajiya - Ray Tracing Volume Densities][1] paper. And I've already got stuck into section 2. I wonder if there's a mistake in that equation.&#xD;&#xA;&#xD;&#xA;I'll quote the relevant bit&#xD;&#xA;&#xD;&#xA;&gt; The quantity to be calculated in a scattering problem is the energy per unit solid angle per unit area&#xD;&#xA;$$&#xD;&#xA;dE = I(x,\omega)\sin\vartheta d\omega d\sigma&#xD;&#xA;$$&#xD;&#xA;This quantity is called the *intesity* of radiation at a point $x$ in the direction of the solid angle $d\omega$. The scattering equation can be derived by considering a differential cylindrical volume $dV = d\sigma ds$, where $d\sigma$ is the cross section of the cylinder and $ds$ is the length. If we follow a pencil of radiation along the length of the cylinder, we find the difference in intensity between the two ends is given by&#xD;&#xA;$$&#xD;&#xA;dI = -absorbed + emitted = -k\rho ds d\sigma d\omega + j \rho ds d\sigma d\omega \;\;\; (2.1)&#xD;&#xA;$$&#xD;&#xA;where $\rho$ is the density of the matter in the volume element $k$ is the absorbption coefficient...&#xD;&#xA;&#xD;&#xA;I believe there's a mistake in the absorbed intensity expression, there's a reference quoted at the very beginning of the section where this formulation is taken from (the reference is [Chandrasekhar - Radiative Transfer][2]). I cannot to manage what later the paper defines as scattering equation&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1}{k\rho} s\cdot\nabla_xI(x,s) - I(x,s) + \frac{1}{4\pi} \int_{\left\lVert s \right\rVert = 1} p(s,\overline{s})I(x,\overline{s}) d\overline{s}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I believe in the reference (Chandrasekhar) I've found what was used for Kajiya's derivation, I'll put an image just in case not everyone can see it from the preview:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;In Chandrasekhar's formula 44 there's a $I_\nu$ factor, which should correspond to $I(x,s)$ in Kajiya's. And formula (48) in Chandrasekhar is exactly the same as Kajiya's scattering equation, except that the former takes into account in his formulation time and wavelength. But apart from this they're the same.&#xD;&#xA;&#xD;&#xA;So I suspect there's a typo in Kajiya's. I think in general absorption is formulate as some form of exponatial decay of the form $f'(x) = -\alpha f(x)$, which is used in Chandrasekhar. In summary I think equation (2.1) from Kajiya should be written as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;dI d\sigma d\omega = -k\rho I ds d\sigma d\omega + j \rho ds d\sigma d\omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Can you confirm if my suspicion is correct? Thank you&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/publication/234800181_Ray_Tracing_Volume_Densities&#xD;&#xA;  [2]: https://www.google.co.uk/books/edition/Radiative_Transfer/K7YLRcTP_XUC?hl=en&amp;gbpv=1&amp;dq=chandrasekhar%20radiative%20transfer%20pdf&amp;printsec=frontcover&#xD;&#xA;  [3]: https://i.stack.imgur.com/elb9Z.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37010" PostHistoryTypeId="50" PostId="12108" RevisionGUID="73a3b981-a54f-48e9-81eb-f412efc693f8" CreationDate="2022-05-11T11:07:40.737" UserId="-1" />
  <row Id="37011" PostHistoryTypeId="2" PostId="12675" RevisionGUID="81cbe8be-acfc-43c1-9b06-f3647f544601" CreationDate="2022-05-11T15:24:46.037" UserId="18387" Text="ALL,&#xD;&#xA;&#xD;&#xA;Task: Modify existing OSX cursor&#xD;&#xA;&#xD;&#xA;Solution:&#xD;&#xA;&#xD;&#xA;Cursors in OSX are stored in PDF format. So, I used an online&#xD;&#xA;converter PDF -&gt; PNG.&#xD;&#xA;&#xD;&#xA;Next I modified resulting PNG in Windows Paint and saved it as PNG.&#xD;&#xA;&#xD;&#xA;Problem: When looking at the resulting PNG in OSX (Preview app f.e), I&#xD;&#xA;see a white background. I don't see any transparency around my&#xD;&#xA;modified image.&#xD;&#xA;&#xD;&#xA;I presume it is a result of the MS Paint saving the image as it&#xD;&#xA;appears on the screen.&#xD;&#xA;&#xD;&#xA;Now, how do I convert all those white pixels on background to become&#xD;&#xA;transparent?&#xD;&#xA;&#xD;&#xA;I tried to look online, but what I found is the converted will ask me&#xD;&#xA;for a specific transparency color, and I am not sure whether I should&#xD;&#xA;say &quot;white&quot; or something else.&#xD;&#xA;&#xD;&#xA;Could someone please help?&#xD;&#xA;&#xD;&#xA;TIA!!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37013" PostHistoryTypeId="1" PostId="12675" RevisionGUID="81cbe8be-acfc-43c1-9b06-f3647f544601" CreationDate="2022-05-11T15:24:46.037" UserId="18387" Text="Create a transparent PNG" ContentLicense="CC BY-SA 4.0" />
  <row Id="37014" PostHistoryTypeId="3" PostId="12675" RevisionGUID="81cbe8be-acfc-43c1-9b06-f3647f544601" CreationDate="2022-05-11T15:24:46.037" UserId="18387" Text="|transparency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37015" PostHistoryTypeId="50" PostId="12602" RevisionGUID="117ac0f1-2013-428c-95a8-6c4990c09a4a" CreationDate="2022-05-11T19:05:55.603" UserId="-1" />
  <row Id="37016" PostHistoryTypeId="2" PostId="12676" RevisionGUID="c7eac524-8205-47df-aa66-bad355658f22" CreationDate="2022-05-11T23:49:15.153" UserId="17855" Text="I'm trying to learn about compute shaders, and as such decided to give it a go at implementing the particle system described in these slides: https://www.khronos.org/assets/uploads/developers/library/2014-siggraph-bof/KITE-BOF_Aug14.pdf&#xD;&#xA;&#xD;&#xA;TLDR; I have an SSBO filled with particle position data:&#xD;&#xA;```&#xD;&#xA;struct particlePos&#xD;&#xA;{&#xD;&#xA;	GLfloat x, y, z, w;&#xD;&#xA;};&#xD;&#xA;[...]&#xD;&#xA;GLuint posSSBO;&#xD;&#xA;glGenBuffers(1, &amp;posSSBO);&#xD;&#xA;glBindBuffer(GL_SHADER_STORAGE_BUFFER, posSSBO);&#xD;&#xA;glBufferData(GL_SHADER_STORAGE_BUFFER, num_particles*sizeof(particlePos),&#xD;&#xA;             nullptr, GL_STATIC_DRAW);&#xD;&#xA;glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, posSSBO);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I dispatch a compute shader to propagate the particles, and then I wish to render each individual particle with `glDrawArrays(GL_POINT, 0, num_particles);`. Problem is, it's not working. In my humble opinion I think the slides are riddled with errors (all respect to those who wrote them as they have been very informative!). This is the code that I'm trying to get to work:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glEnable(GL_PROGRAM_POINT_SIZE);&#xD;&#xA;&#xD;&#xA;glBindBuffer(GL_ARRAY_BUFFER, posSSBO);&#xD;&#xA;glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);&#xD;&#xA;glEnableVertexAttribArray(0);&#xD;&#xA;glVertexPointer(4, GL_FLOAT, 0, (GLvoid*)0);&#xD;&#xA;glEnableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;glDrawArrays(GL_POINTS, 0, num_particles);&#xD;&#xA;glDisableClientState(GL_VERTEX_ARRAY);&#xD;&#xA;glBindBuffer(GL_ARRAY_BUFFER, 0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Granted, I'm probably doing too many things here, but I'm desperate. And it seems close to impossible to find tutorials that explain how to use compute shaders in plan English.&#xD;&#xA;&#xD;&#xA;The function `glVertexPointer` seems strange and undocumented, and I read [here](https://stackoverflow.com/questions/27017824/whats-the-purpose-of-glvertexpointer) that using attribute pointers is better. I have tried both though. This is the vertex shader:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#version 430 compatibility&#xD;&#xA;&#xD;&#xA;layout (location = 0) in vec4 aPosition;&#xD;&#xA;&#xD;&#xA;layout (std140, binding = 0) buffer Pos&#xD;&#xA;{&#xD;&#xA;	vec4 Positions[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;uniform mat4 view;&#xD;&#xA;uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    //gl_Position = projection * view * Positions[gl_VertexID];&#xD;&#xA;    //gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f); // this verified that zero shader invocations took place!&#xD;&#xA;    gl_Position = aPosition;&#xD;&#xA;    gl_PointSize = 50.0f; // desperate attempt!&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The compute shader is a bit too long to post here in its entirety, but this is the interface:&#xD;&#xA;```&#xD;&#xA;#version 430 compatibility&#xD;&#xA;#extension GL_ARB_compute_shader :                   enable&#xD;&#xA;#extension GL_ARB_shader_storage_buffer_object :     enable&#xD;&#xA;&#xD;&#xA;layout (std140, binding = 0) buffer Pos&#xD;&#xA;{&#xD;&#xA;	vec4 Positions[];&#xD;&#xA;};&#xD;&#xA;layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    uint gid = gl_GlobalInvocationID.x;   // y and z are both 1&#xD;&#xA;    [...]&#xD;&#xA;    Positions[gid].xyz = ... // give new position&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Dispatching the compute shader is like this:&#xD;&#xA;```&#xD;&#xA;glDispatchCompute(num_particles / work_group_size, 1, 1);&#xD;&#xA;glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I have checks in place that verify that particles are actually propagating. So it seems like linking the SSBO together with the vertex shader invocation is the missing piece (as well as ensuring that the compute shader is correctly written).&#xD;&#xA;&#xD;&#xA;Sorry for the long question, I tried to be as specific as possible. Hopefully someone has experience with this?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37018" PostHistoryTypeId="1" PostId="12676" RevisionGUID="c7eac524-8205-47df-aa66-bad355658f22" CreationDate="2022-05-11T23:49:15.153" UserId="17855" Text="Bind shader storage buffer object for vertex input" ContentLicense="CC BY-SA 4.0" />
  <row Id="37019" PostHistoryTypeId="3" PostId="12676" RevisionGUID="c7eac524-8205-47df-aa66-bad355658f22" CreationDate="2022-05-11T23:49:15.153" UserId="17855" Text="|opengl|compute-shader|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37020" PostHistoryTypeId="50" PostId="12609" RevisionGUID="ba791d64-411c-4d43-b031-62215f183350" CreationDate="2022-05-12T02:02:15.260" UserId="-1" />
  <row Id="37021" PostHistoryTypeId="2" PostId="12677" RevisionGUID="0679e0b6-3281-4d34-bed0-17915c1e4411" CreationDate="2022-05-12T06:11:49.387" UserId="5256" Text="I am creating a Bezier curve tool in OpenGL and every time my program draws something in motion with cursor coordinates I see the previously drawn lines on the screen for a second or two before they disappear as shown below:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is how it should look:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;    &#xD;&#xA;Below are my mouse motion functions and render function. I am using a double buffer and swap buffers each frame.&#xD;&#xA;&#xD;&#xA;    void passiveMotion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        Point Cursor;&#xD;&#xA;        Cursor.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        Point Cursor;&#xD;&#xA;        Cursor.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;        drawLine(pointsVector[points], Cursor);&#xD;&#xA;        Point reverseCursor;&#xD;&#xA;        reverseCursor.x = (2 * pointsVector[points].x) - Cursor.x;&#xD;&#xA;        reverseCursor.y = (2 * pointsVector[points].y) - Cursor.y;&#xD;&#xA;        drawLine(pointsVector[points], reverseCursor);&#xD;&#xA;    &#xD;&#xA;        vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;    &#xD;&#xA;        Point p1;&#xD;&#xA;        p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;    &#xD;&#xA;        if ((finalPoints[1].x != NULL) &amp;&amp; (finalPoints[1].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            // draw bezier curve&#xD;&#xA;            for (float i = 0; i &lt; 1; i += 0.01)&#xD;&#xA;            {&#xD;&#xA;                // The Green Lines&#xD;&#xA;                int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                int xb = getPt(finalPoints[1].x, reverseCursor.x, i);&#xD;&#xA;                int yb = getPt(finalPoints[1].y, reverseCursor.y, i);&#xD;&#xA;                int xc = getPt(reverseCursor.x, finalPoints[3].x, i);&#xD;&#xA;                int yc = getPt(reverseCursor.y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                // The Blue Line&#xD;&#xA;                int xm = getPt(xa, xb, i);&#xD;&#xA;                int ym = getPt(ya, yb, i);&#xD;&#xA;                int xn = getPt(xb, xc, i);&#xD;&#xA;                int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                // The Black Dot&#xD;&#xA;                int x2 = getPt(xm, xn, i);&#xD;&#xA;                int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                Point p2;&#xD;&#xA;                p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                drawLine(p1, p2);&#xD;&#xA;                p1 = p2;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void myDisplay() &#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i]);&#xD;&#xA;            glColor3f(0, 0, 0);&#xD;&#xA;            drawLine(pointsVector[i], pointsVector[i + 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;    &#xD;&#xA;            if((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                // draw bezier curve&#xD;&#xA;                for (float i = 0; i &lt; 1; i += 0.01)&#xD;&#xA;                {&#xD;&#xA;                    // The Green Lines&#xD;&#xA;                    int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                    int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                    int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                    int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                    int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                    int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                    // The Blue Line&#xD;&#xA;                    int xm = getPt(xa, xb, i);&#xD;&#xA;                    int ym = getPt(ya, yb, i);&#xD;&#xA;                    int xn = getPt(xb, xc, i);&#xD;&#xA;                    int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                    // The Black Dot&#xD;&#xA;                    int x2 = getPt(xm, xn, i);&#xD;&#xA;                    int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                    Point p2;&#xD;&#xA;                    p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                    drawLine(p1, p2);&#xD;&#xA;                    p1 = p2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GNgw4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/9CUxS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37023" PostHistoryTypeId="1" PostId="12677" RevisionGUID="0679e0b6-3281-4d34-bed0-17915c1e4411" CreationDate="2022-05-12T06:11:49.387" UserId="5256" Text="Lines not disappearing after being drawn in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="37024" PostHistoryTypeId="3" PostId="12677" RevisionGUID="0679e0b6-3281-4d34-bed0-17915c1e4411" CreationDate="2022-05-12T06:11:49.387" UserId="5256" Text="|opengl|bezier-curve|glut|line|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37026" PostHistoryTypeId="2" PostId="12678" RevisionGUID="d43d7894-5a1a-465e-ac8d-153e2c2b91a7" CreationDate="2022-05-12T07:46:24.310" UserId="5256" Text="I am trying to detect when my left mouse button is released in OpenGL GLUT. Currently, I am using the `motion()` function in `glutMotionFunc(motion);` and setting the boolean variable `bool mouseIsHeldDown` as true so I can say the left mouse button is being held down. However, I cannot find an efficient way to find when the left mouse button is released.&#xD;&#xA;&#xD;&#xA;Any ideas? Is there a way in Win32?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37028" PostHistoryTypeId="1" PostId="12678" RevisionGUID="d43d7894-5a1a-465e-ac8d-153e2c2b91a7" CreationDate="2022-05-12T07:46:24.310" UserId="5256" Text="How to detect when left mouse button is released in GLUT?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37029" PostHistoryTypeId="3" PostId="12678" RevisionGUID="d43d7894-5a1a-465e-ac8d-153e2c2b91a7" CreationDate="2022-05-12T07:46:24.310" UserId="5256" Text="|opengl|mouse|glut|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37030" PostHistoryTypeId="2" PostId="12679" RevisionGUID="8ca6e958-aea7-425c-b940-2ce7278cd3de" CreationDate="2022-05-12T08:01:37.483" UserId="3073" Text="One common method is to store the LAST mouse button pressed and then test if the last state was not pressed compared to the current state. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;E.g.&#xD;&#xA;&#xD;&#xA;    bool lastButtonState = false;&#xD;&#xA;    &#xD;&#xA;    void readInput() {&#xD;&#xA;         bool curButtonState = readButton();     &#xD;&#xA;    &#xD;&#xA;         // Detect &quot;rising&quot; edge of button (AKA, pressed)&#xD;&#xA;         if(curButtonState == true &amp;&amp; curButtonState != lastButtonState) {&#xD;&#xA;             doStuff();&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;         // Update last state for next call..&#xD;&#xA;         lastButtonState = curButtonState;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can also detect if the button was released using this method.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    if(curButtonState == false &amp;&amp; curButtonState != lastButtonState)&#xD;&#xA;        doStuffRelatedToButtonRelease();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: readInput() should be called once per frame because it keeps a copy of the current frames input state." ContentLicense="CC BY-SA 4.0" />
  <row Id="37032" PostHistoryTypeId="5" PostId="12678" RevisionGUID="0dc1022a-30f1-497f-b7c9-b96a53b6f429" CreationDate="2022-05-12T08:09:20.163" UserId="5256" Comment="added 197 characters in body" Text="I am trying to detect when my left mouse button is released in OpenGL GLUT. Currently, I am using the `motion()` function in `glutMotionFunc(motion);` and setting the boolean variable `bool mouseIsHeldDown` as true so I can say the left mouse button is being held down. However, I cannot find an efficient way to find when the left mouse button is released.&#xD;&#xA;&#xD;&#xA;Any ideas? Is there a way in Win32?&#xD;&#xA;&#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        mouseIsHeldDown = true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void myDisplay() &#xD;&#xA;    {&#xD;&#xA;        if (mouseIsHeldDown == true)&#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37033" PostHistoryTypeId="5" PostId="12662" RevisionGUID="706a2531-ca34-481e-8c3d-b8fde8636142" CreationDate="2022-05-12T08:15:15.157" UserId="5256" Comment="added 38 characters in body" Text="   I found this method and I am using GLUT.&#xD;&#xA;&#xD;&#xA;    void myMouse(int button, int state, int x, int y) &#xD;&#xA;    {&#xD;&#xA;    // If left button was clicked&#xD;&#xA;        if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN) &#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        // Event after mouse is clicked and released&#xD;&#xA;        else if (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_UP) &#xD;&#xA;        {&#xD;&#xA;            //initialize a point and set it coordinates given to us by the function&#xD;&#xA;            Point p1;&#xD;&#xA;            p1.setxy(x, y);&#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37034" PostHistoryTypeId="5" PostId="12678" RevisionGUID="2e5cbd4b-3767-4393-9494-6f4d5964017d" CreationDate="2022-05-12T08:24:39.723" UserId="5256" Comment="added 110 characters in body" Text="I am trying to detect when my left mouse button is released in OpenGL GLUT. Currently, I am using the `motion()` function in `glutMotionFunc(motion);` and setting the boolean variable `bool mouseIsHeldDown` as true so I can say the left mouse button is being held down. However, I cannot find an efficient way to find when the left mouse button is released.&#xD;&#xA;&#xD;&#xA;Any ideas? Is there a way in Win32?&#xD;&#xA;&#xD;&#xA;    int main(int argc, char* argv[]) &#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        glutMotionFunc(motion);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        mouseIsHeldDown = true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void myDisplay() &#xD;&#xA;    {&#xD;&#xA;        if (mouseIsHeldDown == true)&#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37035" PostHistoryTypeId="4" PostId="12678" RevisionGUID="98aa7352-cbff-451b-b43c-9134409a1bd3" CreationDate="2022-05-12T08:36:45.270" UserId="5256" Comment="edited title" Text="How to detect when left mouse button is released in GLUT after motion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37036" PostHistoryTypeId="4" PostId="12678" RevisionGUID="5e6c3986-a06b-42ec-8259-561294c427fc" CreationDate="2022-05-12T08:41:59.410" UserId="5256" Comment="edited title" Text="How to detect when left mouse button is released in GLUT after being held in motion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37037" PostHistoryTypeId="5" PostId="12678" RevisionGUID="88ed7560-066c-4a71-8905-b08ea536a9af" CreationDate="2022-05-12T08:50:25.673" UserId="5256" Comment="edited title" Text="I am trying to detect when my left mouse button is released to store the result in a boolean variable in OpenGL GLUT. Currently, I am using the `motion()` function in `glutMotionFunc(motion);` and setting the boolean variable `bool mouseIsHeldDown` to true when the left mouse button is held in motion to trigger an if statement in my render function `myDisplay()`. However, I cannot find an efficient way to find when the left mouse button is released to declare the same variable as false.&#xD;&#xA;&#xD;&#xA;Any ideas? Is there a way in Win32?&#xD;&#xA;&#xD;&#xA;    int main(int argc, char* argv[]) &#xD;&#xA;    {&#xD;&#xA;        ...&#xD;&#xA;        glutMotionFunc(motion);&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        mouseIsHeldDown = true;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void myDisplay() &#xD;&#xA;    {&#xD;&#xA;        if (mouseIsHeldDown == true)&#xD;&#xA;        {&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37038" PostHistoryTypeId="5" PostId="12679" RevisionGUID="632a8b6a-7102-402c-b821-ea55fecb8854" CreationDate="2022-05-12T09:01:14.973" UserId="3073" Comment="added 672 characters in body" Text="One common method is to store the LAST mouse button pressed and then test if the last state was not pressed compared to the current state. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;E.g.&#xD;&#xA;&#xD;&#xA;    bool lastButtonState = false;&#xD;&#xA;    &#xD;&#xA;    void readInput() {&#xD;&#xA;         bool curButtonState = readButton();     &#xD;&#xA;    &#xD;&#xA;         // Detect &quot;rising&quot; edge of button (AKA, pressed)&#xD;&#xA;         if(curButtonState == true &amp;&amp; curButtonState != lastButtonState) {&#xD;&#xA;             doStuff();&#xD;&#xA;         }&#xD;&#xA;&#xD;&#xA;         // Update last state for next call..&#xD;&#xA;         lastButtonState = curButtonState;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;You can also detect if the button was released using this method.&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    if(curButtonState == false &amp;&amp; curButtonState != lastButtonState)&#xD;&#xA;        doStuffRelatedToButtonRelease();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Note: readInput() should be called once per frame because it keeps a copy of the current frames input state.&#xD;&#xA;&#xD;&#xA;EDIT: The above example is a general solution, below is a solution specific to GLUT as per your update. You need to use the mouse() function to read the button state, motion() doesn't have the needed button state information. GLUT already tells you if that was pressed (transition from false-&gt;true) or released (transition from true-&gt;false) via the &quot;state&quot; variable.&#xD;&#xA;&#xD;&#xA;    void mouse(int button, int state, int x, int y)&#xD;&#xA;    {&#xD;&#xA;        if (button == GLUT_LEFT_BUTTON) {&#xD;&#xA;            if(state == GLUT_DOWN) &#xD;&#xA;                onLeftButtonPressed();    // do your thing here..&#xD;&#xA;    &#xD;&#xA;            // You can also test for (state == GLUT_UP) for mouse button release..&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37039" PostHistoryTypeId="2" PostId="12680" RevisionGUID="9e68ac7c-c989-4555-be6e-e3285bc627b1" CreationDate="2022-05-12T09:10:12.940" UserId="18391" Text="I have 2 3D head images and want to morph one into the other (animation) without using blender etc. I want to do it using coding preferably using C++, C# or python(libraries are ok). I have done 2D image morphing etc but was unable to replicate it in 3D. Kindly give guidance about the steps that needs to be followed to achieve this task. ( Any Sample project would help)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37041" PostHistoryTypeId="1" PostId="12680" RevisionGUID="9e68ac7c-c989-4555-be6e-e3285bc627b1" CreationDate="2022-05-12T09:10:12.940" UserId="18391" Text="3D head mesh morphing from one mesh into another using coding" ContentLicense="CC BY-SA 4.0" />
  <row Id="37042" PostHistoryTypeId="3" PostId="12680" RevisionGUID="9e68ac7c-c989-4555-be6e-e3285bc627b1" CreationDate="2022-05-12T09:10:12.940" UserId="18391" Text="|opengl|3d|c++|mesh|opencv|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37043" PostHistoryTypeId="2" PostId="12681" RevisionGUID="e149d1da-383e-4b22-a27c-4bb6de754376" CreationDate="2022-05-13T00:21:47.027" UserId="5256" Text="Although not ideal after reading PaulHK's answer and solution in the coments I decided to call `glClear(COLOR_BUFFER_BIT)` at the start of the passive motion function, motion function, and display function. I then iterate through my `points` variable starting at `i = 1;` (this is very specific to my code) and draw all geometry I was having trouble with in the loop. This works perfectly and is fast. Based on mouse movement each time there is a callback I draw the entire geometry for each mouse function. `glClear(COLOR_BUFFER_BIT)` clears the screen each frame.&#xD;&#xA;&#xD;&#xA;    void passiveMotion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;        Point Cursor;&#xD;&#xA;        Cursor.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i]);&#xD;&#xA;            glColor3f(0, 0, 0);&#xD;&#xA;            drawLine(pointsVector[i], pointsVector[i + 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                // draw bezier curve&#xD;&#xA;                for (float i = 0; i &lt; 1; i += 0.01)&#xD;&#xA;                {&#xD;&#xA;                    // The Green Lines&#xD;&#xA;                    int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                    int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                    int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                    int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                    int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                    int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                    // The Blue Line&#xD;&#xA;                    int xm = getPt(xa, xb, i);&#xD;&#xA;                    int ym = getPt(ya, yb, i);&#xD;&#xA;                    int xn = getPt(xb, xc, i);&#xD;&#xA;                    int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                    // The Black Dot&#xD;&#xA;                    int x2 = getPt(xm, xn, i);&#xD;&#xA;                    int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                    Point p2;&#xD;&#xA;                    p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                    drawLine(p1, p2);&#xD;&#xA;                    p1 = p2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        Point Cursor;&#xD;&#xA;        Cursor.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;        drawLine(pointsVector[points], Cursor);&#xD;&#xA;        Point reverseCursor;&#xD;&#xA;        reverseCursor.x = (2 * pointsVector[points].x) - Cursor.x;&#xD;&#xA;        reverseCursor.y = (2 * pointsVector[points].y) - Cursor.y;&#xD;&#xA;        drawLine(pointsVector[points], reverseCursor);&#xD;&#xA;    &#xD;&#xA;        vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;    &#xD;&#xA;        Point p1;&#xD;&#xA;        p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;    &#xD;&#xA;        if ((finalPoints[1].x != NULL) &amp;&amp; (finalPoints[1].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            // draw bezier curve&#xD;&#xA;            for (float i = 0; i &lt; 1; i += 0.01)&#xD;&#xA;            {&#xD;&#xA;                // The Green Lines&#xD;&#xA;                int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                int xb = getPt(finalPoints[1].x, reverseCursor.x, i);&#xD;&#xA;                int yb = getPt(finalPoints[1].y, reverseCursor.y, i);&#xD;&#xA;                int xc = getPt(reverseCursor.x, finalPoints[3].x, i);&#xD;&#xA;                int yc = getPt(reverseCursor.y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                // The Blue Line&#xD;&#xA;                int xm = getPt(xa, xb, i);&#xD;&#xA;                int ym = getPt(ya, yb, i);&#xD;&#xA;                int xn = getPt(xb, xc, i);&#xD;&#xA;                int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                // The Black Dot&#xD;&#xA;                int x2 = getPt(xm, xn, i);&#xD;&#xA;                int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                Point p2;&#xD;&#xA;                p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                drawLine(p1, p2);&#xD;&#xA;                p1 = p2;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i]);&#xD;&#xA;            glColor3f(0, 0, 0);&#xD;&#xA;            drawLine(pointsVector[i], pointsVector[i + 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                // draw bezier curve&#xD;&#xA;                for (float i = 0; i &lt; 1; i += 0.01)&#xD;&#xA;                {&#xD;&#xA;                    // The Green Lines&#xD;&#xA;                    int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                    int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                    int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                    int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                    int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                    int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                    // The Blue Line&#xD;&#xA;                    int xm = getPt(xa, xb, i);&#xD;&#xA;                    int ym = getPt(ya, yb, i);&#xD;&#xA;                    int xn = getPt(xb, xc, i);&#xD;&#xA;                    int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                    // The Black Dot&#xD;&#xA;                    int x2 = getPt(xm, xn, i);&#xD;&#xA;                    int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                    Point p2;&#xD;&#xA;                    p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                    drawLine(p1, p2);&#xD;&#xA;                    p1 = p2;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37051" PostHistoryTypeId="50" PostId="8431" RevisionGUID="e9402d4f-9651-4701-adc7-f58d39a17fbe" CreationDate="2022-05-13T05:01:05.183" UserId="-1" />
  <row Id="37052" PostHistoryTypeId="2" PostId="12683" RevisionGUID="89d17a73-c36a-44a8-a850-7aa6ed40add6" CreationDate="2022-05-13T07:47:37.730" UserId="7462" Text="I am making a procedural sdf (just a bunch of cubes) based of an image. The idea is very simple. We have a stencil image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Each texel in the image corresponds to a 3D cube. So to ray trace what I am doing is, calculate the intersection with the plane where the image should live. Grab that point and cmpute the discrete coordinate of the texel corresponding to the collision point. e.g. if each texel corresponds to a cube of size $s$ and the plane corresponds to the union of the front faces of all squares we have:&#xD;&#xA;&#xD;&#xA;Let $p$ be te point of intersection between the ray and the plane, the discrete cooridnate is $\lfloor p / s \rfloor$.&#xD;&#xA;&#xD;&#xA;This allows me to find the position of the cube sdf corresponding to the face being collided with. If I raytrace this sdf I get:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Which is an infinite tiling of cubes. Now I can use the above texel coordinate and the image to figure out if the point of collission $p$ corresponds to a full texel or not. If the texel is empty then i can modify the cube sdf to return infinity, making it be equivalent to an &quot;empty&quot; sdf.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;This did get rid of unwanted cubes, but now things look 2D. Since I am deciding which cubes to keep and which to throw based on the planar information, when we are looking from the side (or any angle induced by perspective) a ray that would have collided against a filled cube will collide first agianst an empty one and be discarded when it should actually collide.&#xD;&#xA;&#xD;&#xA;I can correct this by not testing just the current cube sdf, but the 8 neighbours as well:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;This is much better and it looks solved, except...&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;A steeper angle will cause the issue from before. Now the ray is colliding against an empty texel much farther away from the filled ones and beign discarded when it should collide.&#xD;&#xA;&#xD;&#xA;I was hoping someone could suggest a way to specify my sdf such that I get soemthing like the second to last picture from any angle:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float CubeSdf( vec3 p )&#xD;&#xA;{&#xD;&#xA;    p -= vec3(voxel_size / 2.f);&#xD;&#xA;  	vec3 b = vec3(voxel_size / 2.f) - vec3(rounding) * 0.95;&#xD;&#xA;  	vec3 q = abs(p) - b;&#xD;&#xA;  	return (length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0)) - rounding;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float CrossSdf( vec3 p, ivec2 map_index)&#xD;&#xA;{&#xD;&#xA;    vec3 position = vec3(-voxel_size * float(map_index.x), 0, -voxel_size * float(map_index.y));&#xD;&#xA;    // vec3 position = vec3(0);&#xD;&#xA;&#xD;&#xA;    float final = 1e30;&#xD;&#xA;    int radius = 1;&#xD;&#xA;    const ivec2 texture_size = textureSize(terrain_map, 0);&#xD;&#xA;    for(int i=-radius; i&lt;=radius; i++)&#xD;&#xA;    {&#xD;&#xA;        for(int j=-radius; j&lt;=radius; j++)&#xD;&#xA;        {&#xD;&#xA;            ivec2 sample_coord = ivec2(map_index.x + i, texture_size.y - map_index.y - j);&#xD;&#xA;            bool inside_bounds =&#xD;&#xA;                sample_coord.x &gt;= 0 &amp;&amp; sample_coord.x &lt; texture_size.x &amp;&amp;&#xD;&#xA;                sample_coord.y &gt;= 0 &amp;&amp; sample_coord.y &lt; texture_size.y ;&#xD;&#xA;            float val = texelFetch(terrain_map, sample_coord, 0).r * int(inside_bounds);&#xD;&#xA;            vec3 offset = vec3(float(i) * voxel_size, 0, float(j) * voxel_size);&#xD;&#xA;            final = min(final, CubeSdf(p + position - offset) + float(1e30) * float(val &lt;= 0));&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    return final;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KJL4u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/oiuJ6.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/pPxIM.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/hodDv.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/Gj7Cr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37054" PostHistoryTypeId="1" PostId="12683" RevisionGUID="89d17a73-c36a-44a8-a850-7aa6ed40add6" CreationDate="2022-05-13T07:47:37.730" UserId="7462" Text="Defining the proper sdf for this structure" ContentLicense="CC BY-SA 4.0" />
  <row Id="37055" PostHistoryTypeId="3" PostId="12683" RevisionGUID="89d17a73-c36a-44a8-a850-7aa6ed40add6" CreationDate="2022-05-13T07:47:37.730" UserId="7462" Text="|raytracing|glsl|c++|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37058" PostHistoryTypeId="50" PostId="8291" RevisionGUID="042ec64f-ec33-413e-b1ca-64a0a9a3c6d5" CreationDate="2022-05-14T04:08:50.847" UserId="-1" />
  <row Id="37059" PostHistoryTypeId="2" PostId="12684" RevisionGUID="5a86fd36-7cd5-4175-8087-d8c5120bcf0e" CreationDate="2022-05-14T19:14:54.577" UserId="7462" Text="If anyone runs into this in the future:&#xD;&#xA;&#xD;&#xA;What I did was, I used @lightxbulbs suggestion and made a sandwich although I used two planes instead of a prism because plane intersections are easier and simpler to calculate. I capped the intersection distance at 0 if it is negative and then calculated the intersection point (or the starting position if the intersection is behind the camera).&#xD;&#xA;&#xD;&#xA;Then I do a few iterations of DDA (efficient grid traversal) looking for a texel with the correct depth that is also full.&#xD;&#xA;&#xD;&#xA;If I find such a texel for the given pixel then I know my current ray MUST intersect one of the cubes. Then I raytrace normally from a small offset away from the intersection point.&#xD;&#xA;&#xD;&#xA;I get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PDVDs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37067" PostHistoryTypeId="50" PostId="12622" RevisionGUID="34ec4239-7d0d-4b6a-8aad-4d99a1b2a56d" CreationDate="2022-05-15T05:03:20.277" UserId="-1" />
  <row Id="37069" PostHistoryTypeId="2" PostId="12686" RevisionGUID="2ac58cbd-036d-4f9e-87cb-af258172db3f" CreationDate="2022-05-15T21:32:04.707" UserId="7952" Text="One method, probably the easiest. Is to have a one to one association of vertices in 1 model (model A) with vertices in the other model(model B). To do the morph look up the two vertices and lerp between them. Where the linear interpolation ranges from 0 to 1 and the two points form a line segment. 0 would represent model A and 1 would be the fully morphed version of model B.&#xD;&#xA;&#xD;&#xA;The biggest problem with this approach is generating the association between the vertices. &#xD;&#xA;&#xD;&#xA;To overcome this issue, a relatively simple solution is to scale and rotate both models so they effectively share the same model space, and are approximately overlapping each other. Distortions don't matter here, the goal is to get the two models roughly equivalent in size and shape with the bits of model A that map to model B close to each other. (if the two models are rigged, then this actually becomes easy to do automatically just by mapping the joints to each other)&#xD;&#xA;&#xD;&#xA;Once you are happy that the basic parts are lined up, simply iterate across the vertices doing a brute force search for the nearest vertex from model A in model B. There will be some repeated vertices, either repeat them or create a structure to hold multiple mappings. &#xD;&#xA;&#xD;&#xA;The result is your mapping. At this point the models can be massaged to be GPU friendly or whatever else is needed.&#xD;&#xA;&#xD;&#xA;Other methods exist, but they get very bogged down in theory and math. I like this simple approach because it is relatively easy to implement and understand. (it is also easy to adjust it to fit different needs)" ContentLicense="CC BY-SA 4.0" />
  <row Id="37081" PostHistoryTypeId="2" PostId="12689" RevisionGUID="5652797f-6f2e-46f9-903e-aaff9440e6a7" CreationDate="2022-05-16T17:45:17.470" UserId="17998" Text="I'm investigating software that uses the unnormalized, interpolated vertex normal for creating its tangent space, creating a scaled tangent space that depends on concavity/convexity of the mesh.  It both bakes and reads based around this assumption, so it creates unnormalized normal maps.&#xD;&#xA;&#xD;&#xA;These normal maps would be incompatible with a rendering engine that used a normalized tangent space-- the angle from the normal changes with the length of the tangent space's Z basis.  Likewise, normal maps built around an orthonormal tangent space would be incompatible with engines using scaled tangent spaces.  This means that even if orthonormal space would be preferable, that engines might not use them just to meet a common standard.&#xD;&#xA;&#xD;&#xA;How do commonly used engines handle this?  Do they use orthonormal space or not?  I have investigated Blender and xNormal, and neither use orthonormal tangent spaces, but I'm interested in how more popular commercial software handles their normal maps." ContentLicense="CC BY-SA 4.0" />
  <row Id="37083" PostHistoryTypeId="1" PostId="12689" RevisionGUID="5652797f-6f2e-46f9-903e-aaff9440e6a7" CreationDate="2022-05-16T17:45:17.470" UserId="17998" Text="Is orthonormal tangent space an industry standard for use of tangent space normal maps?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37084" PostHistoryTypeId="3" PostId="12689" RevisionGUID="5652797f-6f2e-46f9-903e-aaff9440e6a7" CreationDate="2022-05-16T17:45:17.470" UserId="17998" Text="|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37087" PostHistoryTypeId="2" PostId="12690" RevisionGUID="d701e7a3-0aff-4709-a4fb-d57e691093d2" CreationDate="2022-05-17T03:50:02.440" UserId="5256" Text="I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        //vector&lt;Point&gt; bezierPoints;&#xD;&#xA;    &#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i - 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;            vector&lt;Point&gt; finalPointsReverseP1 = final4PointsReverseP1();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            if (firstSegmentDrawn == false)&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                if (firstSegmentDrawn == true)&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; bezierPointsMyDisplay.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w3CdT.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37089" PostHistoryTypeId="1" PostId="12690" RevisionGUID="d701e7a3-0aff-4709-a4fb-d57e691093d2" CreationDate="2022-05-17T03:50:02.440" UserId="5256" Text="Why is there a straight line between my bezier paths?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37090" PostHistoryTypeId="3" PostId="12690" RevisionGUID="d701e7a3-0aff-4709-a4fb-d57e691093d2" CreationDate="2022-05-17T03:50:02.440" UserId="5256" Text="|opengl|c++|bezier-curve|glut|line|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37091" PostHistoryTypeId="5" PostId="12690" RevisionGUID="e93ed194-ca21-49f7-926a-2077c1548506" CreationDate="2022-05-17T05:57:57.557" UserId="5256" Comment="Provided a debugging update" Text="I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        //vector&lt;Point&gt; bezierPoints;&#xD;&#xA;    &#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i - 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;            vector&lt;Point&gt; finalPointsReverseP1 = final4PointsReverseP1();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            if (firstSegmentDrawn == false)&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                if (firstSegmentDrawn == true)&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; bezierPointsMyDisplay.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Update:**&#xD;&#xA;&#xD;&#xA;I think this error may be because of the code in the else:&#xD;&#xA;&#xD;&#xA;    Point p1;&#xD;&#xA;    if (firstSegmentDrawn == false)&#xD;&#xA;    {&#xD;&#xA;       p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;       p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am unsure what to initialize p1 to after the first segment is drawn.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w3CdT.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37092" PostHistoryTypeId="5" PostId="12690" RevisionGUID="699ec19e-65f0-4f83-942c-de9ff979a459" CreationDate="2022-05-17T06:21:55.193" UserId="5256" Comment="deleted 61 characters in body" Text="I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        //vector&lt;Point&gt; bezierPoints;&#xD;&#xA;    &#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i - 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;            vector&lt;Point&gt; finalPointsReverseP1 = final4PointsReverseP1();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            if (firstSegmentDrawn == false)&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                if (firstSegmentDrawn == true)&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; bezierPointsMyDisplay.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Update:**&#xD;&#xA;&#xD;&#xA;I think this error may be because of the code in the else:&#xD;&#xA;&#xD;&#xA;    Point p1;&#xD;&#xA;    if (firstSegmentDrawn == false)&#xD;&#xA;    {&#xD;&#xA;       p1 = pointsVector[0];&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;       p1 = pointsVector[points - 1];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I am unsure what to initialize p1 to after the first segment is drawn.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w3CdT.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37093" PostHistoryTypeId="2" PostId="12691" RevisionGUID="d403c351-70a6-4d96-8e3a-e11b05807a71" CreationDate="2022-05-17T09:00:47.797" UserId="13273" Text="I have a GL_TEXTURE_CUBE_MAP_ARRAY texture of 8 cube maps (`countLayers`). Now I am trying to transfer the pixels to CPU.&#xD;&#xA;&#xD;&#xA;Currently I am using this code:&#xD;&#xA;&#xD;&#xA;    unsigned int countFloats = size * size * countChannels * 6 * countLayers;&#xD;&#xA;    pixels = new float[countFloats];&#xD;&#xA;&#xD;&#xA;    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, colorTexture()-&gt;id());&#xD;&#xA;    glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, GL_FLOAT, pixels);&#xD;&#xA;    &#xD;&#xA;    glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);&#xD;&#xA;&#xD;&#xA;It seems like, that this code works only for the first cubemap within the array. Because when deleting the multiplication with `countLayers` in the first line, everything is still working. But when `pixels` does not have enough storage (for example deleting the factor `6` as well), the program is crashing. &#xD;&#xA;&#xD;&#xA;How can I store all cube maps to CPU? It would also be okay to store each cube map separately." ContentLicense="CC BY-SA 4.0" />
  <row Id="37095" PostHistoryTypeId="1" PostId="12691" RevisionGUID="d403c351-70a6-4d96-8e3a-e11b05807a71" CreationDate="2022-05-17T09:00:47.797" UserId="13273" Text="store GL_TEXTURE_CUBE_MAP_ARRAY data to CPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="37096" PostHistoryTypeId="3" PostId="12691" RevisionGUID="d403c351-70a6-4d96-8e3a-e11b05807a71" CreationDate="2022-05-17T09:00:47.797" UserId="13273" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37097" PostHistoryTypeId="2" PostId="12692" RevisionGUID="84cfdf0f-5db8-4714-990d-458b6b77683e" CreationDate="2022-05-17T09:52:57.810" UserId="18408" Text="Where should the model matrix be uploaded to the GPU in a batch renderer?&#xD;&#xA;&#xD;&#xA;All the tutorials I've ever seen use a uniform for this, but that's not with batch rendering. Since the uniform is only constant for a single draw call, it seems to me that this should be a vertex attribute. But then there will be a lot of duplication of data (once for each vertex).&#xD;&#xA;&#xD;&#xA;How can one batch draw calls with different model matrices without excess duplication?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37099" PostHistoryTypeId="1" PostId="12692" RevisionGUID="84cfdf0f-5db8-4714-990d-458b6b77683e" CreationDate="2022-05-17T09:52:57.810" UserId="18408" Text="Model matrix for batch renderer as uniform or vertex attribute?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37100" PostHistoryTypeId="3" PostId="12692" RevisionGUID="84cfdf0f-5db8-4714-990d-458b6b77683e" CreationDate="2022-05-17T09:52:57.810" UserId="18408" Text="|shader|uniform-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37101" PostHistoryTypeId="2" PostId="12693" RevisionGUID="152ac87b-3179-4b2e-a0e7-a5f6f38052f6" CreationDate="2022-05-17T11:15:05.453" UserId="18408" Text="Just realised I can apply the necessary transformations before uploading the vertex positions to the GPU.&#xD;&#xA;&#xD;&#xA;Thanks for being a rubber duck!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37103" PostHistoryTypeId="2" PostId="12694" RevisionGUID="dca97751-9c05-4e2a-86c0-2ca4f9339a53" CreationDate="2022-05-17T11:30:10.907" UserId="7952" Text="The Orthonormal TBN tends to be the most popular. I can't speak to every piece of software out there, that question is better asked on sites specific to the software. &#xD;&#xA;&#xD;&#xA;One reason for its popularity is a normal map can be compressed down to two channels since we know that $x^2+y^2+z^2=1$ this allows z to be computed in the shader, it also allows conversion to other formats for compression, such as using quaternions to represent the TBN. (see this [link][1] near the bottom of the page)&#xD;&#xA;&#xD;&#xA;The values can also be compressed more easily since a normalized vector tends to produce decent results even when the number of bits is reduced all the way down to just 8 bits per component.&#xD;&#xA;&#xD;&#xA;Also, be sure to look into derivative maps, a popular alternative to the usual TBN with normal map. Which have several nice advantages and some similarities to what you are describing.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.yosoygames.com.ar/wp/2018/03/vertex-formats-part-1-compression/" ContentLicense="CC BY-SA 4.0" />
  <row Id="37105" PostHistoryTypeId="2" PostId="12695" RevisionGUID="17585b2d-574f-4760-a9ba-cb6e5d9277ab" CreationDate="2022-05-17T12:50:39.723" UserId="482" Text="IIRC in another question, your said your Point class actually uses `float x,y;` for the coordinates. So one thing that can help is to shift the centers (the &quot;zeros&quot;) over to the edge of the pixel, like:&#xD;&#xA;&#xD;&#xA;    int xi = pt.x + 0.5;&#xD;&#xA;    int yi = pt.y + 0.5;&#xD;&#xA;&#xD;&#xA;And use those integers in calls the GLUT line drawing api.&#xD;&#xA;&#xD;&#xA;I think this change would go inside your `drawLine()` function." ContentLicense="CC BY-SA 4.0" />
  <row Id="37107" PostHistoryTypeId="5" PostId="12695" RevisionGUID="bb31cdb7-f060-4a3f-a71a-d8dd5441598d" CreationDate="2022-05-17T12:56:55.283" UserId="482" Comment="added 126 characters in body" Text="IIRC in another question, your said your Point class actually uses `float x,y;` for the coordinates. So one thing that can help is to shift the centers (the &quot;zeros&quot;) over to the edge of the pixel, like:&#xD;&#xA;&#xD;&#xA;    int xi = pt.x + 0.5;&#xD;&#xA;    int yi = pt.y + 0.5;&#xD;&#xA;&#xD;&#xA;And use those integers in calls the GLUT line drawing api.&#xD;&#xA;&#xD;&#xA;I think this change would go inside your `drawLine()` function.&#xD;&#xA;&#xD;&#xA;A more robust, but much more complicated solution would be to do the above *and* also implement anti-aliased line drawing." ContentLicense="CC BY-SA 4.0" />
  <row Id="37111" PostHistoryTypeId="5" PostId="12689" RevisionGUID="f5f85ef5-96cd-4fdf-9239-97f4684ffb4e" CreationDate="2022-05-17T15:30:01.263" UserId="17998" Comment="added 137 characters in body" Text="I'm investigating software that uses the unnormalized, interpolated vertex normal for creating its tangent space, creating a scaled tangent space that depends on concavity/convexity of the mesh.  It both bakes and reads based around this assumption, so it creates unnormalized normal maps.&#xD;&#xA;&#xD;&#xA;These normal maps would be incompatible with a rendering engine that used a normalized tangent space-- the angle from the normal changes with the length of the tangent space's Z basis.  Likewise, normal maps built around an orthonormal tangent space would be incompatible with engines using scaled tangent spaces.  This means that even if orthonormal space would be preferable, that engines might not use them just to meet a common standard.&#xD;&#xA;&#xD;&#xA;How do commonly used engines handle this?  Do they use orthonormal space or not?  I have investigated Blender and xNormal, and neither use orthonormal tangent spaces, but I'm interested in how more popular commercial software handles their normal maps.&#xD;&#xA;&#xD;&#xA;Any information about specific, big name software is appreciated-- names like Maya are basically industry standards all on their own." ContentLicense="CC BY-SA 4.0" />
  <row Id="37113" PostHistoryTypeId="5" PostId="12690" RevisionGUID="ebb4e05d-0ef3-471e-ba75-4aae7e1675c2" CreationDate="2022-05-17T21:11:14.823" UserId="5256" Comment="deleted 312 characters in body" Text="I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        //vector&lt;Point&gt; bezierPoints;&#xD;&#xA;    &#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i - 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;            vector&lt;Point&gt; finalPointsReverseP1 = final4PointsReverseP1();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            if (firstSegmentDrawn == false)&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);&#xD;&#xA;                bezierPointsMyDisplay.push_back(p1);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                if (firstSegmentDrawn == true)&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; bezierPointsMyDisplay.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My `drawLine()` function:&#xD;&#xA;&#xD;&#xA;    void drawLine(Point p1, Point p2) &#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_LINE_STRIP);&#xD;&#xA;        glVertex2f(p1.x, p1.y);&#xD;&#xA;        glVertex2f(p2.x, p2.y);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w3CdT.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37114" PostHistoryTypeId="5" PostId="12690" RevisionGUID="f0a0af82-e34a-4163-8cd9-df245c207abe" CreationDate="2022-05-17T23:26:59.093" UserId="5256" Comment="deleted 45 characters in body" Text="I have created a bezier curve tool and each time I draw a bezier curve segment I get a straight line between each mouse click. I don't understand why this is happening and was wondering if someone could take a look at my render function and see the error. I have been working on this program with some other users on this stack exchange.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        if ((pointsVector[0].x != NULL) &amp;&amp; (pointsVector[0].y != NULL))&#xD;&#xA;        {&#xD;&#xA;            drawLine(pointsVector[points], Cursor);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; points; i++)&#xD;&#xA;        {&#xD;&#xA;            // draw main line &amp; dot&#xD;&#xA;            glColor3f(255, 0, 0);&#xD;&#xA;            drawDot(pointsVector[i - 1]);&#xD;&#xA;    &#xD;&#xA;            // draw tangent lines and tangent dots&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawDot(controlPoints[i + 1]);&#xD;&#xA;            drawDot(reverseControlPoints[i + 1]);&#xD;&#xA;    &#xD;&#xA;            vector&lt;Point&gt; finalPoints = final4Points();&#xD;&#xA;            vector&lt;Point&gt; finalPointsReverseP1 = final4PointsReverseP1();&#xD;&#xA;    &#xD;&#xA;            Point p1;&#xD;&#xA;            if (firstSegmentDrawn == false)&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[0].x, pointsVector[0].y);&#xD;&#xA;            }&#xD;&#xA;            else&#xD;&#xA;            {&#xD;&#xA;                p1.setxy(pointsVector[points - 1].x, pointsVector[points - 1].y);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            if ((finalPoints[2].x != NULL) &amp;&amp; (finalPoints[2].y != NULL))&#xD;&#xA;            {&#xD;&#xA;                if (firstSegmentDrawn == true)&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPointsReverseP1[0].x, finalPointsReverseP1[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPointsReverseP1[0].y, finalPointsReverseP1[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPointsReverseP1[1].x, finalPointsReverseP1[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPointsReverseP1[1].y, finalPointsReverseP1[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPointsReverseP1[2].x, finalPointsReverseP1[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPointsReverseP1[2].y, finalPointsReverseP1[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;                else&#xD;&#xA;                {&#xD;&#xA;                    float i;&#xD;&#xA;                    // draw bezier curve&#xD;&#xA;                    for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;                    {&#xD;&#xA;                        i = j / 100;&#xD;&#xA;                        // The Green Lines&#xD;&#xA;                        int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);&#xD;&#xA;                        int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);&#xD;&#xA;                        int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);&#xD;&#xA;                        int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);&#xD;&#xA;                        int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);&#xD;&#xA;                        int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);&#xD;&#xA;    &#xD;&#xA;                        // The Blue Line&#xD;&#xA;                        int xm = getPt(xa, xb, i);&#xD;&#xA;                        int ym = getPt(ya, yb, i);&#xD;&#xA;                        int xn = getPt(xb, xc, i);&#xD;&#xA;                        int yn = getPt(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                        // The Black Dot&#xD;&#xA;                        int x2 = getPt(xm, xn, i);&#xD;&#xA;                        int y2 = getPt(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                        Point p2;&#xD;&#xA;                        p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                        drawLine(p1, p2);&#xD;&#xA;                        //drawDot(p1);&#xD;&#xA;    &#xD;&#xA;                        p1 = p2;&#xD;&#xA;                        bezierPointsMyDisplay.push_back(p2);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        for (int i = 1; i &lt; bezierPointsMyDisplay.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(bezierPointsMyDisplay[i - 1], bezierPointsMyDisplay[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;My `drawLine()` function:&#xD;&#xA;&#xD;&#xA;    void drawLine(Point p1, Point p2) &#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_LINE_STRIP);&#xD;&#xA;        glVertex2f(p1.x, p1.y);&#xD;&#xA;        glVertex2f(p2.x, p2.y);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/w3CdT.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37120" PostHistoryTypeId="2" PostId="12697" RevisionGUID="9da3dd9c-cb13-423d-b65b-be7946f0eae2" CreationDate="2022-05-18T10:16:25.560" UserId="13273" Text="I found my mistake...&#xD;&#xA;I was creating 6 cube maps, not 8... but when creating them I have to multiply the number of wanted cube maps by 6 which I didn't done. So the cube map array texture was only holding one cube map.&#xD;&#xA;&#xD;&#xA;    glTexStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, ToGlInternalFormat(format), size, size, layer); // this layer variable needs to be multiplied by 6&#xD;&#xA;&#xD;&#xA;So the source code I posted within the question is working fine." ContentLicense="CC BY-SA 4.0" />
  <row Id="37127" PostHistoryTypeId="2" PostId="12699" RevisionGUID="529a97bb-c099-41d6-8738-5a447d0e889f" CreationDate="2022-05-18T21:27:28.680" UserId="7952" Text="Consider using &#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(blablabla, base_instance). &#xD;&#xA;&#xD;&#xA;Put all the model matrix in an array (in an SSBO or a Uniform buffer) GLSL will provide a gl_InstanceIndex variable that will start at the base_instance value you provide to the draw elements function. After each instance the value will be incremented automatically. The biggest challenge becomes grouping the object models so they are lined up all nice and neat for indexing the model matrix.&#xD;&#xA;&#xD;&#xA;A natural extension of this is to run a compute shader that can update the matrices for physics, rotation, and rearrange them for drawing those visible with one or two draw calls.&#xD;&#xA;&#xD;&#xA;There is even an indirect version that allows the buffer the data is sitting in to be specified so that virtually the entire draw call can be setup on the GPU using compute shaders. &#xD;&#xA;&#xD;&#xA;Combined with &quot;bindless&quot; rendering techniques this can be a very powerful method." ContentLicense="CC BY-SA 4.0" />
  <row Id="37129" PostHistoryTypeId="5" PostId="12699" RevisionGUID="4cc07de8-2cd2-4aa7-b1ed-f526c6ddac39" CreationDate="2022-05-18T21:35:42.817" UserId="7952" Comment="added 165 characters in body" Text="Consider using &#xD;&#xA;&#xD;&#xA;    glDrawElementsInstanced(blablabla, base_instance). &#xD;&#xA;&#xD;&#xA;Put all the model matrix in an array (in an SSBO or a Uniform buffer) GLSL will provide a gl_InstanceIndex variable to the shader that will start at the base_instance value you provide to the draw elements function.&#xD;&#xA;&#xD;&#xA;    mat4 model = ssbo_model_mats[gl_instanceIndex];&#xD;&#xA;&#xD;&#xA;After each instance the value will be incremented automatically. The biggest challenge becomes grouping the object model matrices so they are lined up all nice and neat for indexing the model matrix.&#xD;&#xA;&#xD;&#xA;A natural extension of this is to run a compute shader that can update the matrices for physics, rotation, collision, whatever, then rearrange them for drawing those visible with one or two draw calls.&#xD;&#xA;&#xD;&#xA;There is even an indirect version:&#xD;&#xA;&#xD;&#xA;    glDrawElementsIndirect(...); // and several others&#xD;&#xA;&#xD;&#xA; that allows the buffer the data is sitting in to be specified so that virtually the entire draw call can be setup on the GPU using compute shaders. &#xD;&#xA;&#xD;&#xA;Combined with &quot;bindless&quot; rendering techniques this can be a very powerful method." ContentLicense="CC BY-SA 4.0" />
  <row Id="37130" PostHistoryTypeId="2" PostId="12700" RevisionGUID="b4ae6c53-73a0-43a4-885b-e7a35863abf7" CreationDate="2022-05-19T00:13:32.313" UserId="3242" Text="I'm following [Ray Tracing The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html) to implement a ray tracer, but the explains on math (mainly pdf part) got me confused so I followed Rendering Equation to understand the math behind. As a result, I sample the scene with plain Monte Carlo method (derived from the Equation) and got some seemly correct result after removing the `cos(θ)` in Rendering Equation, but got an incorrectly dark image with `cos(θ)`. And worse, the rendering doesn't converge: as number of samples increase, it goes darker and darker.&#xD;&#xA;&#xD;&#xA;500 samples, without `cos(θ)`:&#xD;&#xA;[![500 samples, without `cos(θ)`][1]][1]&#xD;&#xA;&#xD;&#xA;500 samples, with `cos(θ)`:&#xD;&#xA;[![500 samples, with `cos(θ)`][2]][2]&#xD;&#xA;&#xD;&#xA;100 samples, with `cos(θ)`&#xD;&#xA;[![100 samples, with `cos(θ)`][3]][3]&#xD;&#xA;&#xD;&#xA;The code is not complicated. For every sampling, the camera send a ray into function `ray_trace(Ray ray, int depth)`, the function terminates when the ray hit a light or couldn't find one after bouncing enough time (`depth &lt;= 0`). When it hits something in the scene (the only material in the scene other than light is Lambertian material), a scattered ray is generated from material's `scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)` function. In Lambertian's `scatter()` function, the scattered ray is generated by uniformly sampling around hemisphere. Then this scattered ray becomes the new ray in function `ray_trace`, thus `depth = depth-1`, and  start another round of ray tracing.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Vec3 ray_trace(Ray ray, int depth)&#xD;&#xA;{&#xD;&#xA;    // initially, this ray is generated from a camera&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;    {&#xD;&#xA;        // return black when no light found&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    auto intersection = scene.intersect(ray);&#xD;&#xA;&#xD;&#xA;    if (!intersection.intersected)&#xD;&#xA;    {&#xD;&#xA;        // return black when hits nothing&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (intersection.hit_a_light)&#xD;&#xA;    {&#xD;&#xA;        // found a light&#xD;&#xA;        return intersection.material.emit(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray scattered_ray;&#xD;&#xA;    Vec3 attenuation = intersection.material.scatter(ray, intersection, &amp;scattered_ray);&#xD;&#xA;&#xD;&#xA;    if (with_cosine_theta)&#xD;&#xA;    {&#xD;&#xA;        Vec3 cosine_theta = dot(intersection.normal, scattered_ray).normalize();&#xD;&#xA;        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        // without cosine(theta)&#xD;&#xA;        return attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);&#xD;&#xA;&#xD;&#xA;    // generate random direction in a hemisphere&#xD;&#xA;    if (dot(scattered_direction, intersection.normal) &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        scattered_direction = -scattered_direction;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = scattered_direction;&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can someone point out what makes my rendering wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jR1dH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bBTmY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bR04W.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37132" PostHistoryTypeId="1" PostId="12700" RevisionGUID="b4ae6c53-73a0-43a4-885b-e7a35863abf7" CreationDate="2022-05-19T00:13:32.313" UserId="3242" Text="Adding cos(θ) from rendering equation ruins the renderings" ContentLicense="CC BY-SA 4.0" />
  <row Id="37133" PostHistoryTypeId="3" PostId="12700" RevisionGUID="b4ae6c53-73a0-43a4-885b-e7a35863abf7" CreationDate="2022-05-19T00:13:32.313" UserId="3242" Text="|raytracing|rendering|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37138" PostHistoryTypeId="5" PostId="12700" RevisionGUID="9bf8b3fa-d76b-4050-9379-edf3c245460c" CreationDate="2022-05-19T05:14:10.567" UserId="3242" Comment="added 20 characters in body" Text="I'm following [Ray Tracing The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html) to implement a ray tracer, but the explains on math (mainly pdf part) got me confused so I followed Rendering Equation to understand the math behind. As a result, I sample the scene with plain Monte Carlo method (derived from the Equation) and got some seemly correct result after removing the `cos(θ)` in Rendering Equation, but got an incorrectly dark image with `cos(θ)`. And worse, the rendering doesn't converge: as number of samples increase, it goes darker and darker.&#xD;&#xA;&#xD;&#xA;500 samples, without `cos(θ)`:&#xD;&#xA;[![500 samples, without `cos(θ)`][1]][1]&#xD;&#xA;&#xD;&#xA;500 samples, with `cos(θ)`:&#xD;&#xA;[![500 samples, with `cos(θ)`][2]][2]&#xD;&#xA;&#xD;&#xA;100 samples, with `cos(θ)`&#xD;&#xA;[![100 samples, with `cos(θ)`][3]][3]&#xD;&#xA;&#xD;&#xA;The code is not complicated. For every sampling, the camera send a ray into function `ray_trace(Ray ray, int depth)`, the function terminates when the ray hit a light or couldn't find one after bouncing enough time (`depth &lt;= 0`). When it hits something in the scene (the only material in the scene other than light is Lambertian material), a scattered ray is generated from material's `scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)` function. In Lambertian's `scatter()` function, the scattered ray is generated by uniformly sampling around hemisphere. Then this scattered ray becomes the new ray in function `ray_trace`, thus `depth = depth-1`, and  start another round of ray tracing.&#xD;&#xA;&#xD;&#xA;```Vec3 ray_trace(Ray ray, int depth)&#xD;&#xA;{&#xD;&#xA;    // initially, this ray is generated from a camera&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;    {&#xD;&#xA;        // return black when no light found&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    auto intersection = scene.intersect(ray);&#xD;&#xA;&#xD;&#xA;    if (!intersection.intersected)&#xD;&#xA;    {&#xD;&#xA;        // return black when hits nothing&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (intersection.hit_a_light)&#xD;&#xA;    {&#xD;&#xA;        // found a light&#xD;&#xA;        return intersection.material.emit(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray scattered_ray;&#xD;&#xA;    Vec3 attenuation = intersection.material.scatter(ray, intersection, &amp;scattered_ray);&#xD;&#xA;&#xD;&#xA;    if (with_cosine_theta)&#xD;&#xA;    {&#xD;&#xA;        Vec3 cosine_theta = dot(intersection.normal.normalize(), scattered_ray.direction.normalize());&#xD;&#xA;        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        // without cosine(theta)&#xD;&#xA;        return attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);&#xD;&#xA;&#xD;&#xA;    // generate random direction in a hemisphere&#xD;&#xA;    if (dot(scattered_direction, intersection.normal) &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        scattered_direction = -scattered_direction;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = scattered_direction;&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can someone point out what makes my rendering wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jR1dH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bBTmY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bR04W.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37139" PostHistoryTypeId="2" PostId="12702" RevisionGUID="0cdb0d9a-882f-4b87-9047-c02cc223359a" CreationDate="2022-05-19T08:09:43.263" UserId="10096" Text="Your rendering without the cosine is probably wrong since you're using uniform sphere sampling and the cosine must be the there (unless you assume your brdfs contain a term 1/cos(theta)). Also do this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;pdf = 1.0/(2.0*PI);&#xD;&#xA;return cosine_theta * attenuation / pdf * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and also for the non-cosine part:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;pdf = 1.0/(2.0*PI);&#xD;&#xA;return attenuation/pdf * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If you want to use the non-cosine estimator, then you will have to use cosine distributed sampling for it. It will look like this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Vec3 Lambertian::scatter_cosine_dist(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta).normalize();&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = (intersection.normal+scattered_direction).normalize();&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then modify the non-cosine estimator's pdf too:&#xD;&#xA;```&#xD;&#xA;pdf_wo_cos = 1.0/PI;&#xD;&#xA;return attenuation/pdf_wo_cos * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The pdf in this is actually cos(theta)/PI, but the cosine cancels with the cosine from the rendering equation. If you use the cosine distributed sampling for the estimator without the cosine, and use the uniform sampling for the estimator with the cosine, then you should get equivalent results up to noise (the cosine estimator ought to result in less noise).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37141" PostHistoryTypeId="5" PostId="12700" RevisionGUID="8bdc50a5-d616-4477-bfd0-d901260c3ca1" CreationDate="2022-05-19T10:12:52.623" UserId="3242" Comment="added 474 characters in body" Text="I'm following [Ray Tracing The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html) to implement a ray tracer, but the explains on math (mainly pdf part) got me confused so I followed Rendering Equation to understand the math behind. As a result, I sample the scene with plain Monte Carlo method (derived from the Equation) and got some seemly correct result after removing the `cos(θ)` in Rendering Equation, but got an incorrectly dark image with `cos(θ)`. And worse, the rendering doesn't converge: as number of samples increase, it goes darker and darker.&#xD;&#xA;&#xD;&#xA;500 samples, without `cos(θ)`:&#xD;&#xA;[![500 samples, without `cos(θ)`][1]][1]&#xD;&#xA;&#xD;&#xA;500 samples, with `cos(θ)`:&#xD;&#xA;[![500 samples, with `cos(θ)`][2]][2]&#xD;&#xA;&#xD;&#xA;100 samples, with `cos(θ)`&#xD;&#xA;[![100 samples, with `cos(θ)`][3]][3]&#xD;&#xA;&#xD;&#xA;The code is not complicated. For every sampling, the camera send a ray into function `ray_trace(Ray ray, int depth)`, the function terminates when the ray hit a light or couldn't find one after bouncing enough time (`depth &lt;= 0`). When it hits something in the scene (the only material in the scene other than light is Lambertian material), a scattered ray is generated from material's `scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)` function. In Lambertian's `scatter()` function, the scattered ray is generated by uniformly sampling around hemisphere. Then this scattered ray becomes the new ray in function `ray_trace`, thus `depth = depth-1`, and  start another round of ray tracing.&#xD;&#xA;&#xD;&#xA;```Vec3 ray_trace(Ray ray, int depth)&#xD;&#xA;{&#xD;&#xA;    // initially, this ray is generated from a camera&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;    {&#xD;&#xA;        // return black when no light found&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    auto intersection = scene.intersect(ray);&#xD;&#xA;&#xD;&#xA;    if (!intersection.intersected)&#xD;&#xA;    {&#xD;&#xA;        // return black when hits nothing&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (intersection.hit_a_light)&#xD;&#xA;    {&#xD;&#xA;        // found a light&#xD;&#xA;        return intersection.material.emit(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray scattered_ray;&#xD;&#xA;    Vec3 attenuation = intersection.material.scatter(ray, intersection, &amp;scattered_ray);&#xD;&#xA;&#xD;&#xA;    if (with_cosine_theta)&#xD;&#xA;    {&#xD;&#xA;        Vec3 cosine_theta = dot(intersection.normal.normalize(), scattered_ray.direction.normalize());&#xD;&#xA;        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        // without cosine(theta)&#xD;&#xA;        return attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);&#xD;&#xA;&#xD;&#xA;    // generate random direction in a hemisphere&#xD;&#xA;    if (dot(scattered_direction, intersection.normal) &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        scattered_direction = -scattered_direction;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = scattered_direction;&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can someone point out what makes my rendering wrong?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;update:&#xD;&#xA;&#xD;&#xA;Following lightxbulb's idea, I add `pdf` to function `ray_trace()` and uniformly sample the hemisphere but find the new function doesn't converge:&#xD;&#xA;```&#xD;&#xA;pdf = 1.0/(2.0*PI);&#xD;&#xA;return cosine_theta * attenuation / pdf * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;// the hemisphere sampling part stays as it was&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;From left to right: 100 samples, 200 samples, 500 samples&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jR1dH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bBTmY.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bR04W.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/a8Zza.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37142" PostHistoryTypeId="5" PostId="12700" RevisionGUID="139eeeab-8a7c-4ace-b9a9-247230f5a9bf" CreationDate="2022-05-19T10:18:44.967" UserId="3242" Comment="added 474 characters in body" Text="I'm following [Ray Tracing The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html) to implement a ray tracer, but the explains on math (mainly pdf part) got me confused so I followed Rendering Equation to understand the math behind. As a result, I sample the scene with plain Monte Carlo method (derived from the Equation) and got some seemly correct result after removing the `cos(θ)` in Rendering Equation, but got an incorrectly dark image with `cos(θ)`. And worse, the rendering doesn't converge: as number of samples increase, it goes darker and darker.&#xD;&#xA;&#xD;&#xA;from left to right: 500 samples without `cos(θ)`, 500 samples with `cos(θ)`, 100 samples with `cos(θ)`:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code is not complicated. For every sampling, the camera send a ray into function `ray_trace(Ray ray, int depth)`, the function terminates when the ray hit a light or couldn't find one after bouncing enough time (`depth &lt;= 0`). When it hits something in the scene (the only material in the scene other than light is Lambertian material), a scattered ray is generated from material's `scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)` function. In Lambertian's `scatter()` function, the scattered ray is generated by uniformly sampling around hemisphere. Then this scattered ray becomes the new ray in function `ray_trace`, thus `depth = depth-1`, and  start another round of ray tracing.&#xD;&#xA;&#xD;&#xA;```Vec3 ray_trace(Ray ray, int depth)&#xD;&#xA;{&#xD;&#xA;    // initially, this ray is generated from a camera&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;    {&#xD;&#xA;        // return black when no light found&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    auto intersection = scene.intersect(ray);&#xD;&#xA;&#xD;&#xA;    if (!intersection.intersected)&#xD;&#xA;    {&#xD;&#xA;        // return black when hits nothing&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (intersection.hit_a_light)&#xD;&#xA;    {&#xD;&#xA;        // found a light&#xD;&#xA;        return intersection.material.emit(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray scattered_ray;&#xD;&#xA;    Vec3 attenuation = intersection.material.scatter(ray, intersection, &amp;scattered_ray);&#xD;&#xA;&#xD;&#xA;    if (with_cosine_theta)&#xD;&#xA;    {&#xD;&#xA;        Vec3 cosine_theta = dot(intersection.normal.normalize(), scattered_ray.direction.normalize());&#xD;&#xA;        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        // without cosine(theta)&#xD;&#xA;        return attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);&#xD;&#xA;&#xD;&#xA;    // generate random direction in a hemisphere&#xD;&#xA;    if (dot(scattered_direction, intersection.normal) &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        scattered_direction = -scattered_direction;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = scattered_direction;&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can someone point out what makes my rendering wrong?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;update:&#xD;&#xA;&#xD;&#xA;Following lightxbulb's idea, I add `pdf` to function `ray_trace()` and uniformly sample the hemisphere but find the new function doesn't converge:&#xD;&#xA;```&#xD;&#xA;pdf = 1.0/(2.0*PI);&#xD;&#xA;return cosine_theta * attenuation / pdf * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;// the hemisphere sampling part stays as it was&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;left to right: 100 samples, 200 samples, 500 samples&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v0OVp.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/1SALK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37146" PostHistoryTypeId="5" PostId="12700" RevisionGUID="d18b1b2e-3856-494a-8bb0-42bd00e20de5" CreationDate="2022-05-19T12:50:34.663" UserId="3242" Comment="added 119 characters in body" Text="I'm following [Ray Tracing The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html) to implement a ray tracer, but the explains on math (mainly pdf part) got me confused so I followed Rendering Equation to understand the math behind. As a result, I sample the scene with plain Monte Carlo method (derived from the Equation) and got some seemly correct result after removing the `cos(θ)` in Rendering Equation, but got an incorrectly dark image with `cos(θ)`. And worse, the rendering doesn't converge: as number of samples increase, it goes darker and darker.&#xD;&#xA;&#xD;&#xA;from left to right: 500 samples without `cos(θ)`, 500 samples with `cos(θ)`, 100 samples with `cos(θ)`:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code is not complicated. For every sampling, the camera send a ray into function `ray_trace(Ray ray, int depth)`, the function terminates when the ray hit a light or couldn't find one after bouncing enough time (`depth &lt;= 0`). When it hits something in the scene (the only material in the scene other than light is Lambertian material), a scattered ray is generated from material's `scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)` function. In Lambertian's `scatter()` function, the scattered ray is generated by uniformly sampling around hemisphere. Then this scattered ray becomes the new ray in function `ray_trace`, thus `depth = depth-1`, and  start another round of ray tracing.&#xD;&#xA;&#xD;&#xA;```Vec3 ray_trace(Ray ray, int depth)&#xD;&#xA;{&#xD;&#xA;    // initially, this ray is generated from a camera&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;    {&#xD;&#xA;        // return black when no light found&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    auto intersection = scene.intersect(ray);&#xD;&#xA;&#xD;&#xA;    if (!intersection.intersected)&#xD;&#xA;    {&#xD;&#xA;        // return black when hits nothing&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (intersection.hit_a_light)&#xD;&#xA;    {&#xD;&#xA;        // found a light&#xD;&#xA;        return intersection.material.emit(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray scattered_ray;&#xD;&#xA;    Vec3 attenuation = intersection.material.scatter(ray, intersection, &amp;scattered_ray);&#xD;&#xA;&#xD;&#xA;    if (with_cosine_theta)&#xD;&#xA;    {&#xD;&#xA;        Vec3 cosine_theta = dot(intersection.normal.normalize(), scattered_ray.direction.normalize());&#xD;&#xA;        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        // without cosine(theta)&#xD;&#xA;        return attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);&#xD;&#xA;&#xD;&#xA;    // generate random direction in a hemisphere&#xD;&#xA;    if (dot(scattered_direction, intersection.normal) &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        scattered_direction = -scattered_direction;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = scattered_direction;&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can someone point out what makes my rendering wrong?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;update:&#xD;&#xA;&#xD;&#xA;Following lightxbulb's idea, I tried both approaches:&#xD;&#xA;* keep `cos(θ)` in `ray_trace()` and uniformly sample hemisphere in `scatter()`&#xD;&#xA;* remove `cos(θ)` in `ray_trace()` and sample hemisphere with `cos(θ)` importance in `scatter()`&#xD;&#xA;&#xD;&#xA;for the 1st approach I have (100/200/500 samples):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;for the 2nd approach I have (100/200/500 samples):&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;left to right: 100 samples, 200 samples, 500 samples&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v0OVp.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/iPG68.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bOh3O.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37147" PostHistoryTypeId="5" PostId="12700" RevisionGUID="13608565-3ef2-4fdd-8310-0210f2c2aef5" CreationDate="2022-05-19T12:57:01.657" UserId="3242" Comment="added 119 characters in body" Text="I'm following [Ray Tracing The Rest of Your Life](https://raytracing.github.io/books/RayTracingTheRestOfYourLife.html) to implement a ray tracer, but the explains on math (mainly pdf part) got me confused so I followed Rendering Equation to understand the math behind. As a result, I sample the scene with plain Monte Carlo method (derived from the Equation) and got some seemly correct result after removing the `cos(θ)` in Rendering Equation, but got an incorrectly dark image with `cos(θ)`. And worse, the rendering doesn't converge: as number of samples increase, it goes darker and darker.&#xD;&#xA;&#xD;&#xA;from left to right: 500 samples without `cos(θ)`, 500 samples with `cos(θ)`, 100 samples with `cos(θ)`:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The code is not complicated. For every sampling, the camera send a ray into function `ray_trace(Ray ray, int depth)`, the function terminates when the ray hit a light or couldn't find one after bouncing enough time (`depth &lt;= 0`). When it hits something in the scene (the only material in the scene other than light is Lambertian material), a scattered ray is generated from material's `scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)` function. In Lambertian's `scatter()` function, the scattered ray is generated by uniformly sampling around hemisphere. Then this scattered ray becomes the new ray in function `ray_trace`, thus `depth = depth-1`, and  start another round of ray tracing.&#xD;&#xA;&#xD;&#xA;```Vec3 ray_trace(Ray ray, int depth)&#xD;&#xA;{&#xD;&#xA;    // initially, this ray is generated from a camera&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;    {&#xD;&#xA;        // return black when no light found&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    auto intersection = scene.intersect(ray);&#xD;&#xA;&#xD;&#xA;    if (!intersection.intersected)&#xD;&#xA;    {&#xD;&#xA;        // return black when hits nothing&#xD;&#xA;        return Vec3(0.0, 0.0, 0.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (intersection.hit_a_light)&#xD;&#xA;    {&#xD;&#xA;        // found a light&#xD;&#xA;        return intersection.material.emit(...);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray scattered_ray;&#xD;&#xA;    Vec3 attenuation = intersection.material.scatter(ray, intersection, &amp;scattered_ray);&#xD;&#xA;&#xD;&#xA;    if (with_cosine_theta)&#xD;&#xA;    {&#xD;&#xA;        Vec3 cosine_theta = dot(intersection.normal.normalize(), scattered_ray.direction.normalize());&#xD;&#xA;        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;    else&#xD;&#xA;    {&#xD;&#xA;        // without cosine(theta)&#xD;&#xA;        return attenuation * ray_trace(scattered_ray, depth - 1);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &amp;scattered_ray)&#xD;&#xA;{&#xD;&#xA;    double phi = random(0.0, 2.0 * PI);&#xD;&#xA;    double sin_phi = sine(phi);&#xD;&#xA;    double cos_phi = cosine(phi);&#xD;&#xA;&#xD;&#xA;    double cos_theta = random(-1.0, 1.0);&#xD;&#xA;    double sin_theta = sqrt(1 - cos_theta * cos_theta);&#xD;&#xA;&#xD;&#xA;    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);&#xD;&#xA;&#xD;&#xA;    // generate random direction in a hemisphere&#xD;&#xA;    if (dot(scattered_direction, intersection.normal) &lt; 0)&#xD;&#xA;    {&#xD;&#xA;        scattered_direction = -scattered_direction;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    scattered_ray.origin = intersection.hit_point;&#xD;&#xA;    scattered_ray.direction = scattered_direction;&#xD;&#xA;&#xD;&#xA;    return this.albedo;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Can someone point out what makes my rendering wrong?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;update:&#xD;&#xA;&#xD;&#xA;Following lightxbulb's idea, I tried both approaches (code at https://codeshare.io/bvR8ev):&#xD;&#xA;* keep `cos(θ)` in `ray_trace()` and uniformly sample hemisphere in `scatter()` (`WITH_COSINE=true`, `UNIFORM_SAMPLE=true`)&#xD;&#xA;* remove `cos(θ)` in `ray_trace()` and sample hemisphere with `cos(θ)` importance in `scatter()` (`WITH_COSINE=false`, `UNIFORM_SAMPLE=false`)&#xD;&#xA;&#xD;&#xA;for the 1st approach I have (100/200/500 samples):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;for the 2nd approach I have (100/200/500 samples):&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;left to right: 100 samples, 200 samples, 500 samples&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v0OVp.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/iPG68.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/bOh3O.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37148" PostHistoryTypeId="2" PostId="12704" RevisionGUID="a71ba6fa-dc2c-4f54-8798-17f9eb8ace41" CreationDate="2022-05-19T19:34:05.117" UserId="18421" Text="I have the following projection matrix:&#xD;&#xA;[![Projection matrix overview][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Projection matrix formula][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and I need to make a hole in the center of my matrix, something like that: (I don't want to project a custom W and H)&#xD;&#xA;[![Example of projection matrix wihout center][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XMDwq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mxmvj.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/f0KiC.png&#xD;&#xA;&#xD;&#xA;Is that possible ? Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="37150" PostHistoryTypeId="1" PostId="12704" RevisionGUID="a71ba6fa-dc2c-4f54-8798-17f9eb8ace41" CreationDate="2022-05-19T19:34:05.117" UserId="18421" Text="It's possible to make a projection matrix to not project in the center?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37151" PostHistoryTypeId="3" PostId="12704" RevisionGUID="a71ba6fa-dc2c-4f54-8798-17f9eb8ace41" CreationDate="2022-05-19T19:34:05.117" UserId="18421" Text="|mathematics|projections|matrix|camera-matrix|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37152" PostHistoryTypeId="2" PostId="12705" RevisionGUID="bc701c95-6ed5-471f-9e97-b12a0c991198" CreationDate="2022-05-19T20:46:03.047" UserId="48" Text="It's not possible to cut a hole in the image by altering the projection matrix, no. However, you can mask out rendering in that region by using the depth test or stencil test.&#xD;&#xA;&#xD;&#xA;For example, before rendering your scene, you could render a depth-only quad at the near plane to define the excluded region. Then any subsequent rendering will be clipped to outside of that region, because it will fail the depth test. The region doesn't have to be a rectangle with this approach, either; it can be any shape." ContentLicense="CC BY-SA 4.0" />
  <row Id="37159" PostHistoryTypeId="2" PostId="12707" RevisionGUID="f2d7287c-055c-4fee-84e7-54a482becfb7" CreationDate="2022-05-20T05:22:06.027" UserId="18304" Text="I rendered similar images using a Vulkan and an OpenGL ES program. Supposedly the two programs should generate the same result, so I want to test it by comparing the two images. However, the camera settings, the size of the images and so on make it hard to compare images directly. Does anyone have some ideas about this?&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37161" PostHistoryTypeId="1" PostId="12707" RevisionGUID="f2d7287c-055c-4fee-84e7-54a482becfb7" CreationDate="2022-05-20T05:22:06.027" UserId="18304" Text="how to compare two slightly different images rendered by two programs" ContentLicense="CC BY-SA 4.0" />
  <row Id="37162" PostHistoryTypeId="3" PostId="12707" RevisionGUID="f2d7287c-055c-4fee-84e7-54a482becfb7" CreationDate="2022-05-20T05:22:06.027" UserId="18304" Text="|image-comparison|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37163" PostHistoryTypeId="50" PostId="12414" RevisionGUID="68ebb53b-e179-47ae-9084-aeb3bff20666" CreationDate="2022-05-20T08:08:10.790" UserId="-1" />
  <row Id="37164" PostHistoryTypeId="2" PostId="12708" RevisionGUID="3332c0a3-4b3a-4240-b125-dd3352193bb6" CreationDate="2022-05-20T10:09:09.380" UserId="13095" Text="Like the color values, transparency is a piece of information that needs to be stored in an image. A quite common data representation is `RGB` with the channels red, green, and blue (often 8bit). This only contains color information. Transparency can not be represented by this format. You need to add another channel for that where you can store the transparency information. This extended format would be `RGBA` where `A` is the &quot;alpha&quot; channel that represents transparency. This is not a simple &quot;yes&quot; or &quot;no&quot; boolean value, since a pixel can also be partially transparent which creates a color mixture with the background. This is important to understand because the problem in your case is that the converter you used obviously dropped the alpha channel, and recreating it &quot;correctly&quot; is not possible in most cases.&#xD;&#xA;&#xD;&#xA;When the program asks you to specify a transparency color, here is what is likely going to happen: The program will add the missing alpha channel and then scan every pixel of the image. If the pixel is of the specified color, it will be set the alpha value to 100% transparent and to fully opaque otherwise. So just &quot;yes&quot; or &quot;no&quot;. Why is this approach problematic?&#xD;&#xA;&#xD;&#xA;First, you might have some parts of the same color in your image that shouldn't be transparent. But the bigger problem is usually that the borders will look weird. To avoid visible staircase patterns at shape borders one usually applies some color blending on non-transparent images. For example, a black line on white background gets some grey pixels added so that the steps aren't as obvious anymore. If your image has transparent parts, you will do this blending via the alpha channel instead. The original image you used most likely did this. But when the converter dropped the alpha channel, he just stored the colors resulting from a white background. &#xD;&#xA;&#xD;&#xA;So considering that the transparent color just sets exact color matches to transparent and everything else to opaque will give you a lot of lighter, fully opaque pixels at the border that should just be partially transparent. That would be the grey pixels from the mentioned black line. This gets more obvious and disturbing, the darker the background.&#xD;&#xA;&#xD;&#xA;What can you do about it? You can either use an editing tool that supports direct editing of the alpha channel to correct all of this manually but the better approach would probably be to convert the original pdf again with a converter that preserves the alpha channel.&#xD;&#xA;&#xD;&#xA;Note, that there might be some alpha reconstruction algorithms that handle things a bit smarter than I described them, but this is not as easy as one might think. If it was, there wouldn't be the need for an alpha channel at all.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37168" PostHistoryTypeId="4" PostId="12704" RevisionGUID="422d9cd7-54fb-4a9b-8506-dd732a54d3c2" CreationDate="2022-05-21T12:09:44.903" UserId="7952" Comment="edited title" Text="Is it possible to make a projection matrix to not project in the center?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37169" PostHistoryTypeId="2" PostId="12709" RevisionGUID="d4aa797e-d4f1-4328-bd0f-9b6e6c71dfd1" CreationDate="2022-05-21T17:09:37.507" UserId="18431" Text="I recently came across a set of models that include Derivative Maps. I'd like to use them in Blender, but from what I've seen so far Blender only supports exporting baked Derivative Maps, not importing them. Therefore I'm trying to convert these Derivative Maps into tangent space Normal Maps for use in Blender.&#xD;&#xA;&#xD;&#xA;So far all the programs that I've seen (like xNormal etc) also only support exporting Derivative Maps (not importing them) so they haven't worked for me, but if anyone knows a program that can be used for this conversion that would be great.&#xD;&#xA;&#xD;&#xA;As for developing a converter myself, I've done some research on Derivative Maps to try to understand the logic behind them, including reading [these links](https://computergraphics.stackexchange.com/questions/4937/derivative-maps-vs-tangent-space-normal-maps) and the [original paper](https://www.dropbox.com/s/l1yl164jb3rhomq/mm_sfgrad_bump.pdf?dl=0), but it's been a while since I've seen math in this level and I'm just not understanding it well enough to develop an algorithm that works.&#xD;&#xA;&#xD;&#xA;Can anyone help be understand how I can turn a Derivative Map's pixels into a Normal Map's pixels? A simple explanation of the necessary equations, or even some pseudocode algorithm, would be a lot of help.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37171" PostHistoryTypeId="1" PostId="12709" RevisionGUID="d4aa797e-d4f1-4328-bd0f-9b6e6c71dfd1" CreationDate="2022-05-21T17:09:37.507" UserId="18431" Text="How do I convert Derivative Maps to Normal Maps?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37172" PostHistoryTypeId="3" PostId="12709" RevisionGUID="d4aa797e-d4f1-4328-bd0f-9b6e6c71dfd1" CreationDate="2022-05-21T17:09:37.507" UserId="18431" Text="|texture|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37173" PostHistoryTypeId="2" PostId="12710" RevisionGUID="ce3cb899-4417-4a15-9d27-142137289513" CreationDate="2022-05-21T22:18:12.060" UserId="18201" Text="I'm a little bit confused with the transition from just setting solid colors to object to involving light and its different components. For instance, the following formula&#xD;&#xA;$R = I K_d max(0, n.l)$ that computes the involvement of the diffuse component of light in the object's color. The part where we compute the dot product makes sense because indeed visually points in the object where the normal is orthogonal on the light vector should be dark. However, I can't get to understand what's the purpose of $K_d$. Is there any example of an object in real life that would for instance have low $K_d$ (hardly react to the existence of a light source)? Why would changing $K_d$'s value ever make sense?&#xD;&#xA;&#xD;&#xA;Thank you." ContentLicense="CC BY-SA 4.0" />
  <row Id="37175" PostHistoryTypeId="1" PostId="12710" RevisionGUID="ce3cb899-4417-4a15-9d27-142137289513" CreationDate="2022-05-21T22:18:12.060" UserId="18201" Text="Understanding the diffuse component of light" ContentLicense="CC BY-SA 4.0" />
  <row Id="37176" PostHistoryTypeId="3" PostId="12710" RevisionGUID="ce3cb899-4417-4a15-9d27-142137289513" CreationDate="2022-05-21T22:18:12.060" UserId="18201" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37177" PostHistoryTypeId="2" PostId="12711" RevisionGUID="418b3b93-80ed-4d71-9406-c6f39fcfd8cd" CreationDate="2022-05-22T02:03:28.700" UserId="18433" Text="With the library `glm`, we can do matrix computation on CPU. However, GPU is more suitable to do this. So, what if I put matrix computation in Compute Shader? Will it be faster? If it is possible, it will be really nice to C, as doing matrix computation is a really hard job in C.&#xD;&#xA;&#xD;&#xA;I may have to implement `glm::perspective()`, `glm::lookat()`, `glm::rotate()`, `etc.` in Compute Shader, though.&#xD;&#xA;&#xD;&#xA;(Sorry if my English sucks.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="37179" PostHistoryTypeId="1" PostId="12711" RevisionGUID="418b3b93-80ed-4d71-9406-c6f39fcfd8cd" CreationDate="2022-05-22T02:03:28.700" UserId="18433" Text="Is it possible to put matrix computation in Compute Shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37180" PostHistoryTypeId="3" PostId="12711" RevisionGUID="418b3b93-80ed-4d71-9406-c6f39fcfd8cd" CreationDate="2022-05-22T02:03:28.700" UserId="18433" Text="|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37181" PostHistoryTypeId="5" PostId="12711" RevisionGUID="2b00941f-527c-4f4e-9ce9-283a2af72421" CreationDate="2022-05-22T11:58:16.000" UserId="13095" Comment="deleted 11 characters in body" Text="With the library `glm`, we can do matrix computations on the CPU. However, the GPU is more suitable to do this. So what if I put the matrix computations in a Compute Shader? Will it be faster? If it is possible, it will be really nice for C, as doing matrix computations is a really hard job in C.&#xD;&#xA;&#xD;&#xA;I may have to implement `glm::perspective()`, `glm::lookat()`, `glm::rotate()`, etc. in the Compute Shader, though." ContentLicense="CC BY-SA 4.0" />
  <row Id="37182" PostHistoryTypeId="2" PostId="12712" RevisionGUID="e4d53afa-4614-460c-811f-880fbcd46c24" CreationDate="2022-05-22T19:19:56.270" UserId="9044" Text="Let's ignore $K_d$'s dependence on wavelength for a moment (which @lightxbulb mentioned in the comments). Consider a bright white surface, and a grey one. The difference between them is precisely that the latter reflects less light; this, has lower value of $K_d$.&#xD;&#xA;&#xD;&#xA;In general, one might loosely think of $K_d(\lambda)$ as the colour of the material (usually represented as a triple of values for $\lambda$ equal to reed, green, and blue lights wavelength)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37184" PostHistoryTypeId="2" PostId="12713" RevisionGUID="04891825-b982-4e93-bb57-4cee2f28073f" CreationDate="2022-05-22T19:31:21.103" UserId="9044" Text="Suppose you have a function $f$ (think a height field) of $(x,y)$. A derivative map contains point samples of $\left( {\partial f\over \partial x}, {\partial f\over \partial y}\right)$, typically as a two-component texture.&#xD;&#xA;&#xD;&#xA;What this means is that at a point $(x,y)$ the 3D vector $\left( 1, 0, {\partial f\over \partial x}\right)$ is parallel to the surface $z = f(x,y)$. Likewise, the vector $\left(0,1, {\partial f\over \partial y}\right)$ is parallel to said surface.&#xD;&#xA;&#xD;&#xA;Now, a vector orthogonal to the surface $z = f(x,y)$ can be computed as the cross product of these two vectors, which expands into&#xD;&#xA;&#xD;&#xA;$$\left(-{\partial f\over \partial x}, -{\partial f\over \partial y}, 1\right)$$&#xD;&#xA;Normalizing this vector (dividing by its length) will give you precisely the normal." ContentLicense="CC BY-SA 4.0" />
  <row Id="37186" PostHistoryTypeId="2" PostId="12714" RevisionGUID="6ef7eaac-aa52-4b44-970d-eb71e351607f" CreationDate="2022-05-22T20:24:35.657" UserId="18437" Text="I have a very weird problem in my raytracer. I have been following along with Ray Tracing in one Weekend by Peter Shirley. I have a very weird problem with artifacts in my renders. This is an image of the artifacts (I moved one sphere so that it is easy to see):[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZffkK.png&#xD;&#xA;&#xD;&#xA;This has been a big problem, and I can't quite figure out why it is like so. I ran some tests and found out that this is not because of normal calculations, or random floating point calculations. I am just starting to learn computer graphics, and would like some help with this. If anybody had a similar problem, please tell me how I could fix it." ContentLicense="CC BY-SA 4.0" />
  <row Id="37188" PostHistoryTypeId="1" PostId="12714" RevisionGUID="6ef7eaac-aa52-4b44-970d-eb71e351607f" CreationDate="2022-05-22T20:24:35.657" UserId="18437" Text="How do I get rid of the Artifacts in my Ray tracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37189" PostHistoryTypeId="3" PostId="12714" RevisionGUID="6ef7eaac-aa52-4b44-970d-eb71e351607f" CreationDate="2022-05-22T20:24:35.657" UserId="18437" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37190" PostHistoryTypeId="2" PostId="12715" RevisionGUID="d778aca2-3190-4718-aa3a-ef944bacd9a8" CreationDate="2022-05-23T01:36:57.553" UserId="18373" Text="I'm confused about what orthographic projection matrix outputs. Based on what I know so far, orthographic projection matrix converts vertexes in eye coordinates into clip coordinates. But what exactly are clip coordinates? What are its bounds of x, y, z values? I read somewhere that its x, y, z are all in range [-1.0...1.0]. Is it true? Also, how and why axes are orientated in clip clip coordinates? right handed (z goes out of page) or left handed (z goes into page)? What are main differences between clip coordinates and normalized device coordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37192" PostHistoryTypeId="1" PostId="12715" RevisionGUID="d778aca2-3190-4718-aa3a-ef944bacd9a8" CreationDate="2022-05-23T01:36:57.553" UserId="18373" Text="Understanding orthographic projection matrix clip coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="37193" PostHistoryTypeId="3" PostId="12715" RevisionGUID="d778aca2-3190-4718-aa3a-ef944bacd9a8" CreationDate="2022-05-23T01:36:57.553" UserId="18373" Text="|opengl|projections|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37194" PostHistoryTypeId="5" PostId="12715" RevisionGUID="3d91db01-bb93-45bb-ab5b-d5558bb8bf79" CreationDate="2022-05-23T05:40:09.213" UserId="18373" Comment="added 391 characters in body" Text="I'm confused about what orthographic projection matrix outputs. Based on what I know so far, orthographic projection matrix converts vertexes in eye coordinates into clip coordinates. But what exactly are clip coordinates? What are its bounds of x, y, z values? I read somewhere that its x, y, z are all in range [-1...1]. Is it true? Also, how and why axes are orientated in clip coordinates? right handed (z goes out of page) or left handed (z goes into page)? What are main differences between clip coordinates and normalized device coordinates?&#xD;&#xA;&#xD;&#xA;Edit: I think the primary difference between clip coordinates and NDC is that NDC can be obtained by dividing clip coordinates by w (ie. $x_{ndc}=x_{clip}/w$, $y_{ndc}=y_{clip}/w$, and $z_{ndc}=z_{clip}/w$. But what I don’t understand here is that even though clip coordinates x,y,z values obtained by projection matrix are in range [-1...1], is it still necessary to divide them by w to get NDC?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37195" PostHistoryTypeId="2" PostId="12716" RevisionGUID="830eb277-7e92-4b36-a910-93465cd789d7" CreationDate="2022-05-23T06:42:29.413" UserId="18438" Text="Most bump mapping (meaning black and white height map) uses Tangents/Bitangents computed from Position using dFdx/y. And they also compute the offsets/derivatives of the height map using dFdx/y.  The standard seems to be to not use precomputed Tangents/Bitangents. If you search for bump mapping, everything to do with it seems to be like this. I am trying to get a setup working that does use precomputed tangents, as these are higher quality. But I do not know how to adapt the math to work with them.&#xD;&#xA;&#xD;&#xA;Here is an example of typical bump mapping based on [Mikkelsen2010][1]. (This is actually the setup that Blender uses for the [bump mapping node][2] in its Eevee render engine. I have recreated it in the [Malt render engine][3].)&#xD;&#xA;&#xD;&#xA;    void bump_without_precomputed_tangents(&#xD;&#xA;        float strength, float dist, float height, float invert, out vec3 result)&#xD;&#xA;    {&#xD;&#xA;    #ifdef PIXEL_SHADER&#xD;&#xA;      vec3 N = normalize(NORMAL);&#xD;&#xA;      dist *= gl_FrontFacing ? invert : -invert;&#xD;&#xA;    &#xD;&#xA;      vec3 dPdx = dFdx(POSITION);&#xD;&#xA;      vec3 dPdy = dFdy(POSITION);&#xD;&#xA;    &#xD;&#xA;      //Get surface tangents from normal.&#xD;&#xA;      vec3 Rx = cross(dPdy, N);&#xD;&#xA;      vec3 Ry = cross(N, dPdx);&#xD;&#xA;    &#xD;&#xA;      //Calculate height derivatives (usually done in another function)&#xD;&#xA;      vec2 dHd = vec2(dFdx(height), dFdy(height));&#xD;&#xA;    &#xD;&#xA;      //Compute surface gradient and determinant.&#xD;&#xA;      float det = dot(dPdx, Rx);&#xD;&#xA;    &#xD;&#xA;      vec3 surfgrad = dHd.x * Rx + dHd.y * Ry;&#xD;&#xA;    &#xD;&#xA;      strength = max(strength, 0.0);&#xD;&#xA;    &#xD;&#xA;      result = normalize(abs(det) * N - dist * sign(det) * surfgrad);&#xD;&#xA;      result = normalize(mix(N, result, strength));&#xD;&#xA;    &#xD;&#xA;    #else&#xD;&#xA;      result = (NORMAL);&#xD;&#xA;    #endif&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here's a test setup showing a gradient sphere height map texture:&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;And the Normal from using it with the above code (using Malt 1.0 in Blender 3.1):&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;You can see there are problems of ridge-like noise and the geometry showing in the Normal. These are normal for this style of bump mapping. The ridges are caused by using dFdx/y for the height map derivatives. The mesh showing is partially from that, and partially from using dFdx/y on Position to get the Tangent/Bitangent. If proper precomputed Tangents are used, these problems will be reduced. (The derivatives can also be improved in various ways.)&#xD;&#xA;&#xD;&#xA;The problem is that the precomputed tangent/bitangent are Normalized, but in the above code, dPdx/y, Rx/y, and dHd are all very low values. If I simply replace Rx/y with the precomputed Tangent/Bitangent, it doesn't work due to this. I am trying to figure out how to get dHd Normalized without causing problems. Or, the precomputed Tangents need to be scaled into the proper range without reintroducing these problems. (The precomputed tangents are provided by the Malt render engine.)&#xD;&#xA;&#xD;&#xA;Here is code where I am bringing in the precomputed tangents and Normalizing dHd. But this does not give the proper Normals in the end.&#xD;&#xA;&#xD;&#xA;    void bump_normalized(&#xD;&#xA;        float strength, float dist, float height, float invert, out vec3 result)&#xD;&#xA;    {&#xD;&#xA;    #ifdef PIXEL_SHADER&#xD;&#xA;      vec3 T = get_tangent(0);&#xD;&#xA;      vec3 B = get_bitangent(0);&#xD;&#xA;      vec3 N = normalize(NORMAL);&#xD;&#xA;    &#xD;&#xA;      dist *= gl_FrontFacing ? invert : -invert;&#xD;&#xA;    &#xD;&#xA;      vec3 dPdx = dFdx(POSITION);&#xD;&#xA;      vec3 dPdy = dFdy(POSITION);&#xD;&#xA;    &#xD;&#xA;      //Calculate height derivatives.&#xD;&#xA;      vec2 dHd = vec2(dFdx(height), dFdy(height));&#xD;&#xA;    &#xD;&#xA;      //Normalize derivs so they work with Normalized Tangent. Avoid div by 0.&#xD;&#xA;      dHd = length(dHd) == vec2(0.0) ? vec2(0.0) : normalize(dHd);&#xD;&#xA;    &#xD;&#xA;      //Compute surface gradient and determinant.&#xD;&#xA;      float det = dot(normalize(dPdx), T);&#xD;&#xA;    &#xD;&#xA;      vec3 surfgrad = (dHd.x * T + dHd.y * B);&#xD;&#xA;    &#xD;&#xA;      strength = max(strength, 0.0);&#xD;&#xA;    &#xD;&#xA;      //result = normalize(abs(det) * N - dist * sign(det) * surfgrad);&#xD;&#xA;      result = normalize(N - dist * surfgrad);&#xD;&#xA;      result = normalize(mix(N, result, strength));&#xD;&#xA;    &#xD;&#xA;    #else&#xD;&#xA;      result = (NORMAL);&#xD;&#xA;    #endif&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The Normal looks like this. It is incorrect.&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;In this code, I also do not know what to do with the det, as it is based on dPdx, which isn't needed now (its usual result line is commented out for now.)&#xD;&#xA;&#xD;&#xA;I have other setups that successfully use the precomputed tangents and UV offset based derivatives instead, and these work fine (and are clean as no dFdx/y is involved.)&#xD;&#xA;&#xD;&#xA;Can anyone tell me what I'm doing wrong here, or if there's some other way entirely to approach this? I want to be able to properly use Normalized T and B.&#xD;&#xA;&#xD;&#xA;  [1]: https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf&#xD;&#xA;  [2]: https://github.com/blender/blender/blob/master/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl&#xD;&#xA;  [3]: https://github.com/bnpr/Malt&#xD;&#xA;  [4]: https://i.stack.imgur.com/LpY4k.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7kXjP.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/PrhTa.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37197" PostHistoryTypeId="1" PostId="12716" RevisionGUID="830eb277-7e92-4b36-a910-93465cd789d7" CreationDate="2022-05-23T06:42:29.413" UserId="18438" Text="Bump mapping WITH precomputed tangents?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37198" PostHistoryTypeId="3" PostId="12716" RevisionGUID="830eb277-7e92-4b36-a910-93465cd789d7" CreationDate="2022-05-23T06:42:29.413" UserId="18438" Text="|opengl|rendering|glsl|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37199" PostHistoryTypeId="50" PostId="9116" RevisionGUID="9396453f-3ab2-43ad-acc6-676a1872e1f4" CreationDate="2022-05-23T10:07:40.930" UserId="-1" />
  <row Id="37204" PostHistoryTypeId="2" PostId="12718" RevisionGUID="544119c3-1c79-4fea-8225-8d1438919530" CreationDate="2022-05-24T13:16:02.213" UserId="18440" Text="I am new to graphics programming and I'm trying to create an efficient 2D tilemap renderer (using rust and wgpu (webgpu)).&#xD;&#xA;&#xD;&#xA;**My current implementation**&#xD;&#xA;&#xD;&#xA;My current implementation consists of:&#xD;&#xA;&#xD;&#xA; 1. A Rust-Vec (contains all tiles needed for rendering in a normal buffer)&#xD;&#xA; 2. A Vertex Buffer (contains 4 Vertices, describing a quad)&#xD;&#xA; 3. An Index Buffer (contains Indices to define the said quad)&#xD;&#xA; 4. An Instance Buffer (basically contains ALL the tile data (currently only world positions (2 u32 Integers))&#xD;&#xA; 5. A Uniform Buffer (contains current camera position (x, y, zoom))&#xD;&#xA;&#xD;&#xA;The 1. buffer (Rust-Vec) is updated and copied to the Instance Buffer every new frame (both buffers are fully replaced every frame). In order to improve performance a bit, the world is split up into chunks. Although that does not affect the rendering process after the needed tiles are loaded into the 1. buffer.&#xD;&#xA;&#xD;&#xA;The instance data (tile coordinates) is translated to the relative normal positions in the vertex shader.&#xD;&#xA;&#xD;&#xA;My project currently does not support textures etc.&#xD;&#xA;&#xD;&#xA;**Problem**&#xD;&#xA;&#xD;&#xA;When zooming out far enough, but not unreasonably far, the frame time starts to increase immensely. Looking at a flamegraph I have found the part of code that takes the longest is updating the 1. Vector and copying it to the instance buffer. Sadly I have not come up with a more efficient solution to rendering large amounts of 2D tiles.&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;What concepts and ideas can I make use of to increase the performance of my project? Is my current solution inherently flawed, or is it somewhat acceptable?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37206" PostHistoryTypeId="1" PostId="12718" RevisionGUID="544119c3-1c79-4fea-8225-8d1438919530" CreationDate="2022-05-24T13:16:02.213" UserId="18440" Text="Good way of implementing an efficient tilemap renderer" ContentLicense="CC BY-SA 4.0" />
  <row Id="37207" PostHistoryTypeId="3" PostId="12718" RevisionGUID="544119c3-1c79-4fea-8225-8d1438919530" CreationDate="2022-05-24T13:16:02.213" UserId="18440" Text="|performance|2d|2d-graphics|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37208" PostHistoryTypeId="50" PostId="9781" RevisionGUID="5e4ded4a-c376-4f21-9f58-3321fad2fbf8" CreationDate="2022-05-24T20:02:25.263" UserId="-1" />
  <row Id="37209" PostHistoryTypeId="2" PostId="12719" RevisionGUID="8041e3ec-e235-48bb-8e12-d55cd1d5a0ff" CreationDate="2022-05-24T20:47:50.347" UserId="7684" Text="**Problem**&#xD;&#xA;&#xD;&#xA;I'm currently working on multi UV support for glTF-models, and after getting a first version up and running (checking against glTF's [multi-uv-test][1]) I checked if the other models are still running fine.&#xD;&#xA;&#xD;&#xA;I noticed some very visible artifacts (left image) for the Sponza model which has only one set of texture coordinates.&#xD;&#xA;&#xD;&#xA;[![Sponza Bad][2]][2]&#xD;&#xA;[![Sponza Good][3]][3]&#xD;&#xA;&#xD;&#xA;I could at least find the code that seems to cause this issue in a fragment shader (the condition should always be true for Sponza):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;vec2 getBaseColorTexCoords() {&#xD;&#xA;    return u_material.baseColorTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When I return the second line instead, I get the desired output (right image).&#xD;&#xA;&#xD;&#xA;Some additional stuff:&#xD;&#xA;&#xD;&#xA; - If I change the condition to `true` it works fine. I guess the branching is just optimized away in that case&#xD;&#xA; - If I change the condition to `false` I get a black screen (`texCoords1` attribute disabled for Sponza)&#xD;&#xA; - If I pass `o_texCoords0` on both sides of the colon `:` I still get these artifacts, but not if I just return `o_texCoords0` in analogous functions for other texture maps (eg. normal or metallic-roughness)&#xD;&#xA;&#xD;&#xA;The only place where I use this function:&#xD;&#xA;```cpp&#xD;&#xA;vec4 getBaseColor() {&#xD;&#xA;    vec4 baseColor = u_material.baseColor;&#xD;&#xA;    if(u_hasBaseColorTexture) {&#xD;&#xA;        vec2 texCoords = getBaseColorTexCoords();&#xD;&#xA;        baseColor *= srgbToLinear4fv(texture(u_baseColorTexture, texCoords));&#xD;&#xA;    }&#xD;&#xA;    if(u_hasVertexColors) {&#xD;&#xA;        baseColor *= o_color;&#xD;&#xA;    }&#xD;&#xA;    return baseColor;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Analogous functions:&#xD;&#xA;```cpp&#xD;&#xA;vec2 getMetallicRoughnessTexCoords() {&#xD;&#xA;    return u_material.metallicRoughnessTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 getNormalTexCoords() {&#xD;&#xA;    return u_material.normalTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Additional Code Snippets**&#xD;&#xA;&#xD;&#xA;First I suspected that perhaps `u_material.baseColorTexCoordSet` somehow somewhere gets assigned a value that is not equal to 0 on the CPU side. But that is not the case and to make doubly sure  I'm passing in the constant 0:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;val baseColorTexCoordSetLoc = glGetUniformLocation(shaderProgram, &quot;u_material.baseColorTexCoordSet&quot;)&#xD;&#xA;// glUniform1i(baseColorTexCoordSetLoc, material.baseColorTexCoordSet)&#xD;&#xA;glUniform1i(baseColorTexCoordSetLoc, 0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't think it is the cause, but here are some code snippets related to `o_texCoords1`, which gets its value from a disabled vertex attribute:&#xD;&#xA;&#xD;&#xA;GPU:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// Vertex shader&#xD;&#xA;layout (location = 1) in vec2 texCoords0;&#xD;&#xA;layout (location = 2) in vec2 texCoords1;&#xD;&#xA;&#xD;&#xA;out vec2 o_texCoords0;&#xD;&#xA;out vec2 o_texCoords1;&#xD;&#xA;&#xD;&#xA;// Inside main()...&#xD;&#xA;o_texCoords0 = texCoords0;&#xD;&#xA;o_texCoords1 = texCoords1;&#xD;&#xA;&#xD;&#xA;// Fragment shader&#xD;&#xA;in vec2 o_texCoords0;&#xD;&#xA;in vec2 o_texCoords1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;CPU:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;if(primitives.texCoords0.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(1)&#xD;&#xA;	glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords0.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// This is empty for the Sponza model&#xD;&#xA;if(primitives.texCoords1.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(2)&#xD;&#xA;	glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords1.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**&quot;Question&quot;**&#xD;&#xA;&#xD;&#xA;Currently I'm suspecting that this is some GPU branching issue. &#xD;&#xA;&#xD;&#xA;I guess this might be difficult to answer, but any clues or hints on how to best tackle this problem are welcomed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/MultiUVTest&#xD;&#xA;  [2]: https://i.stack.imgur.com/jEVDyl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eMxEMl.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37211" PostHistoryTypeId="1" PostId="12719" RevisionGUID="8041e3ec-e235-48bb-8e12-d55cd1d5a0ff" CreationDate="2022-05-24T20:47:50.347" UserId="7684" Text="Artifacts Multi UV Branching on GPU" ContentLicense="CC BY-SA 4.0" />
  <row Id="37212" PostHistoryTypeId="3" PostId="12719" RevisionGUID="8041e3ec-e235-48bb-8e12-d55cd1d5a0ff" CreationDate="2022-05-24T20:47:50.347" UserId="7684" Text="|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37213" PostHistoryTypeId="5" PostId="12719" RevisionGUID="8aa5c48c-2b50-4dbe-8694-1b3c46a9a8a4" CreationDate="2022-05-24T22:49:06.477" UserId="7684" Comment="Added screenshots of another device" Text="**Problem**&#xD;&#xA;&#xD;&#xA;I'm currently working on multi UV support for glTF-models, and after getting a first version up and running (checking against glTF's [multi-uv-test][1]) I checked if the other models are still running fine.&#xD;&#xA;&#xD;&#xA;I noticed some very visible artifacts (left image) for the Sponza model which has only one set of texture coordinates.&#xD;&#xA;&#xD;&#xA;[![Sponza Bad][2]][2]&#xD;&#xA;[![Sponza Good][3]][3]&#xD;&#xA;&#xD;&#xA;[![Sponza Bad 2][4]][4]&#xD;&#xA;[![Sponza Good 2][5]][5]&#xD;&#xA;&#xD;&#xA;I could at least find the code that seems to cause this issue in a fragment shader (the condition should always be true for Sponza):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;vec2 getBaseColorTexCoords() {&#xD;&#xA;    return u_material.baseColorTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When I return the second line instead, I get the desired output (right image).&#xD;&#xA;&#xD;&#xA;Some additional stuff:&#xD;&#xA;&#xD;&#xA; - If I change the condition to `true` it works fine. I guess the branching is just optimized away in that case&#xD;&#xA; - If I change the condition to `false` I get a black screen (`texCoords1` attribute disabled for Sponza)&#xD;&#xA; - If I pass `o_texCoords0` on both sides of the colon `:` I still get these artifacts, but not if I just return `o_texCoords0` in analogous functions for other texture maps (eg. normal or metallic-roughness)&#xD;&#xA;&#xD;&#xA;The only place where I use this function:&#xD;&#xA;```cpp&#xD;&#xA;vec4 getBaseColor() {&#xD;&#xA;    vec4 baseColor = u_material.baseColor;&#xD;&#xA;    if(u_hasBaseColorTexture) {&#xD;&#xA;        vec2 texCoords = getBaseColorTexCoords();&#xD;&#xA;        baseColor *= srgbToLinear4fv(texture(u_baseColorTexture, texCoords));&#xD;&#xA;    }&#xD;&#xA;    if(u_hasVertexColors) {&#xD;&#xA;        baseColor *= o_color;&#xD;&#xA;    }&#xD;&#xA;    return baseColor;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Analogous functions:&#xD;&#xA;```cpp&#xD;&#xA;vec2 getMetallicRoughnessTexCoords() {&#xD;&#xA;    return u_material.metallicRoughnessTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 getNormalTexCoords() {&#xD;&#xA;    return u_material.normalTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Additional Code Snippets**&#xD;&#xA;&#xD;&#xA;First I suspected that perhaps `u_material.baseColorTexCoordSet` somehow somewhere gets assigned a value that is not equal to 0 on the CPU side. But that is not the case and to make doubly sure  I'm passing in the constant 0:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;val baseColorTexCoordSetLoc = glGetUniformLocation(shaderProgram, &quot;u_material.baseColorTexCoordSet&quot;)&#xD;&#xA;// glUniform1i(baseColorTexCoordSetLoc, material.baseColorTexCoordSet)&#xD;&#xA;glUniform1i(baseColorTexCoordSetLoc, 0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't think it is the cause, but here are some code snippets related to `o_texCoords1`, which gets its value from a disabled vertex attribute:&#xD;&#xA;&#xD;&#xA;GPU:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// Vertex shader&#xD;&#xA;layout (location = 1) in vec2 texCoords0;&#xD;&#xA;layout (location = 2) in vec2 texCoords1;&#xD;&#xA;&#xD;&#xA;out vec2 o_texCoords0;&#xD;&#xA;out vec2 o_texCoords1;&#xD;&#xA;&#xD;&#xA;// Inside main()...&#xD;&#xA;o_texCoords0 = texCoords0;&#xD;&#xA;o_texCoords1 = texCoords1;&#xD;&#xA;&#xD;&#xA;// Fragment shader&#xD;&#xA;in vec2 o_texCoords0;&#xD;&#xA;in vec2 o_texCoords1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;CPU:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;if(primitives.texCoords0.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(1)&#xD;&#xA;	glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords0.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// This is empty for the Sponza model&#xD;&#xA;if(primitives.texCoords1.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(2)&#xD;&#xA;	glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords1.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**&quot;Question&quot;**&#xD;&#xA;&#xD;&#xA;Currently I'm suspecting that this is some GPU branching issue. &#xD;&#xA;&#xD;&#xA;I guess this might be difficult to answer, but any clues or hints on how to best tackle this problem are welcomed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/MultiUVTest&#xD;&#xA;  [2]: https://i.stack.imgur.com/jEVDyl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eMxEMl.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/MKCBGm.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/lmazGm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37214" PostHistoryTypeId="5" PostId="12719" RevisionGUID="1593983f-b08e-4acd-aaa2-ed79227fe9b0" CreationDate="2022-05-25T00:41:36.523" UserId="7684" Comment="Add note on precision" Text="**Problem**&#xD;&#xA;&#xD;&#xA;I'm currently working on multi UV support for glTF-models, and after getting a first version up and running (checking against glTF's [multi-uv-test][1]) I checked if the other models are still running fine.&#xD;&#xA;&#xD;&#xA;I noticed some very visible artifacts (left image) for the Sponza model which has only one set of texture coordinates.&#xD;&#xA;&#xD;&#xA;[![Sponza Bad][2]][2]&#xD;&#xA;[![Sponza Good][3]][3]&#xD;&#xA;&#xD;&#xA;[![Sponza Bad 2][4]][4]&#xD;&#xA;[![Sponza Good 2][5]][5]&#xD;&#xA;&#xD;&#xA;I could at least find the code that seems to cause this issue in a fragment shader (the condition should always be true for Sponza):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;vec2 getBaseColorTexCoords() {&#xD;&#xA;    return u_material.baseColorTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When I return the second line instead, I get the desired output (right image).&#xD;&#xA;&#xD;&#xA;Some additional stuff:&#xD;&#xA;&#xD;&#xA; - If I change the condition to `true` it works fine. I guess the branching is just optimized away in that case&#xD;&#xA; - If I change the condition to `false` I get a black screen (`texCoords1` attribute disabled for Sponza)&#xD;&#xA; - If I pass `o_texCoords0` on both sides of the colon `:` I still get these artifacts, but not if I just return `o_texCoords0` in analogous functions for other texture maps (eg. normal or metallic-roughness)&#xD;&#xA;&#xD;&#xA;The only place where I use this function:&#xD;&#xA;```cpp&#xD;&#xA;vec4 getBaseColor() {&#xD;&#xA;    vec4 baseColor = u_material.baseColor;&#xD;&#xA;    if(u_hasBaseColorTexture) {&#xD;&#xA;        vec2 texCoords = getBaseColorTexCoords();&#xD;&#xA;        baseColor *= srgbToLinear4fv(texture(u_baseColorTexture, texCoords));&#xD;&#xA;    }&#xD;&#xA;    if(u_hasVertexColors) {&#xD;&#xA;        baseColor *= o_color;&#xD;&#xA;    }&#xD;&#xA;    return baseColor;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Analogous functions:&#xD;&#xA;```cpp&#xD;&#xA;vec2 getMetallicRoughnessTexCoords() {&#xD;&#xA;    return u_material.metallicRoughnessTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 getNormalTexCoords() {&#xD;&#xA;    return u_material.normalTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Additional Code Snippets**&#xD;&#xA;&#xD;&#xA;First I suspected that perhaps `u_material.baseColorTexCoordSet` somehow somewhere gets assigned a value that is not equal to 0 on the CPU side. But that is not the case and to make doubly sure  I'm passing in the constant 0:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;val baseColorTexCoordSetLoc = glGetUniformLocation(shaderProgram, &quot;u_material.baseColorTexCoordSet&quot;)&#xD;&#xA;// glUniform1i(baseColorTexCoordSetLoc, material.baseColorTexCoordSet)&#xD;&#xA;glUniform1i(baseColorTexCoordSetLoc, 0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't think it is the cause, but here are some code snippets related to `o_texCoords1`, which gets its value from a disabled vertex attribute:&#xD;&#xA;&#xD;&#xA;GPU:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// Vertex shader&#xD;&#xA;layout (location = 1) in vec2 texCoords0;&#xD;&#xA;layout (location = 2) in vec2 texCoords1;&#xD;&#xA;&#xD;&#xA;out vec2 o_texCoords0;&#xD;&#xA;out vec2 o_texCoords1;&#xD;&#xA;&#xD;&#xA;// Inside main()...&#xD;&#xA;o_texCoords0 = texCoords0;&#xD;&#xA;o_texCoords1 = texCoords1;&#xD;&#xA;&#xD;&#xA;// Fragment shader&#xD;&#xA;in vec2 o_texCoords0;&#xD;&#xA;in vec2 o_texCoords1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;CPU:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;if(primitives.texCoords0.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(1)&#xD;&#xA;	glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords0.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// This is empty for the Sponza model&#xD;&#xA;if(primitives.texCoords1.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(2)&#xD;&#xA;	glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords1.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**&quot;Question&quot;**&#xD;&#xA;&#xD;&#xA;Currently I'm suspecting that this is some GPU branching issue. &#xD;&#xA;&#xD;&#xA;I guess this might be difficult to answer, but any clues or hints on how to best tackle this problem are welcomed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;Changing the precision to `highp float` helps resolve the issue (not sure why), though that's not desirable on mobile.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/MultiUVTest&#xD;&#xA;  [2]: https://i.stack.imgur.com/jEVDyl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eMxEMl.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/MKCBGm.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/lmazGm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37215" PostHistoryTypeId="50" PostId="10177" RevisionGUID="a23515ea-37fc-4ce3-b924-23d5c28534ac" CreationDate="2022-05-25T05:04:05.380" UserId="-1" />
  <row Id="37216" PostHistoryTypeId="33" PostId="12716" RevisionGUID="5594f046-689d-4b7f-b173-67216c541db1" CreationDate="2022-05-25T22:10:04.063" UserId="18438" Comment="77" />
  <row Id="37217" PostHistoryTypeId="5" PostId="12719" RevisionGUID="9ced19b1-f521-4fef-94fe-16e4f94a72ab" CreationDate="2022-05-26T01:01:39.470" UserId="7684" Comment="added 854 characters in body" Text="**Problem**&#xD;&#xA;&#xD;&#xA;I'm currently working on multi UV support for glTF-models, and after getting a first version up and running (checking against glTF's [multi-uv-test][1]) I checked if the other models are still running fine.&#xD;&#xA;&#xD;&#xA;I noticed some very visible artifacts (left image) for the Sponza model which has only one set of texture coordinates.&#xD;&#xA;&#xD;&#xA;[![Sponza Bad][2]][2]&#xD;&#xA;[![Sponza Good][3]][3]&#xD;&#xA;&#xD;&#xA;[![Sponza Bad 2][4]][4]&#xD;&#xA;[![Sponza Good 2][5]][5]&#xD;&#xA;&#xD;&#xA;I could at least find the code that seems to cause this issue in a fragment shader (the condition should always be true for Sponza):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;vec2 getBaseColorTexCoords() {&#xD;&#xA;    return u_material.baseColorTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;When I return the second line instead, I get the desired output (right image).&#xD;&#xA;&#xD;&#xA;Some additional stuff:&#xD;&#xA;&#xD;&#xA; - If I change the condition to `true` it works fine. I guess the branching is just optimized away in that case&#xD;&#xA; - If I change the condition to `false` I get a black screen (`texCoords1` attribute disabled for Sponza)&#xD;&#xA; - If I pass `o_texCoords0` on both sides of the colon `:` I still get these artifacts, but not if I just return `o_texCoords0` in analogous functions for other texture maps (eg. normal or metallic-roughness)&#xD;&#xA;&#xD;&#xA;The only place where I use this function:&#xD;&#xA;```cpp&#xD;&#xA;vec4 getBaseColor() {&#xD;&#xA;    vec4 baseColor = u_material.baseColor;&#xD;&#xA;    if(u_hasBaseColorTexture) {&#xD;&#xA;        vec2 texCoords = getBaseColorTexCoords();&#xD;&#xA;        baseColor *= srgbToLinear4fv(texture(u_baseColorTexture, texCoords));&#xD;&#xA;    }&#xD;&#xA;    if(u_hasVertexColors) {&#xD;&#xA;        baseColor *= o_color;&#xD;&#xA;    }&#xD;&#xA;    return baseColor;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Analogous functions:&#xD;&#xA;```cpp&#xD;&#xA;vec2 getMetallicRoughnessTexCoords() {&#xD;&#xA;    return u_material.metallicRoughnessTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 getNormalTexCoords() {&#xD;&#xA;    return u_material.normalTexCoordSet == 0 ? o_texCoords0 : o_texCoords1;&#xD;&#xA;//    return o_texCoords0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Additional Code Snippets**&#xD;&#xA;&#xD;&#xA;First I suspected that perhaps `u_material.baseColorTexCoordSet` somehow somewhere gets assigned a value that is not equal to 0 on the CPU side. But that is not the case and to make doubly sure  I'm passing in the constant 0:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;val baseColorTexCoordSetLoc = glGetUniformLocation(shaderProgram, &quot;u_material.baseColorTexCoordSet&quot;)&#xD;&#xA;// glUniform1i(baseColorTexCoordSetLoc, material.baseColorTexCoordSet)&#xD;&#xA;glUniform1i(baseColorTexCoordSetLoc, 0)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't think it is the cause, but here are some code snippets related to `o_texCoords1`, which gets its value from a disabled vertex attribute:&#xD;&#xA;&#xD;&#xA;GPU:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;// Vertex shader&#xD;&#xA;layout (location = 1) in vec2 texCoords0;&#xD;&#xA;layout (location = 2) in vec2 texCoords1;&#xD;&#xA;&#xD;&#xA;out vec2 o_texCoords0;&#xD;&#xA;out vec2 o_texCoords1;&#xD;&#xA;&#xD;&#xA;// Inside main()...&#xD;&#xA;o_texCoords0 = texCoords0;&#xD;&#xA;o_texCoords1 = texCoords1;&#xD;&#xA;&#xD;&#xA;// Fragment shader&#xD;&#xA;in vec2 o_texCoords0;&#xD;&#xA;in vec2 o_texCoords1;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;CPU:&#xD;&#xA;&#xD;&#xA;```kotlin&#xD;&#xA;if(primitives.texCoords0.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(1)&#xD;&#xA;	glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords0.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// This is empty for the Sponza model&#xD;&#xA;if(primitives.texCoords1.isNotEmpty()) {&#xD;&#xA;	glEnableVertexAttribArray(2)&#xD;&#xA;	glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, offset)&#xD;&#xA;	offset += primitives.texCoords1.size * Float.SIZE_BYTES&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**&quot;Question&quot;**&#xD;&#xA;&#xD;&#xA;Currently I'm suspecting that this is some GPU branching issue. &#xD;&#xA;&#xD;&#xA;I guess this might be difficult to answer, but any clues or hints on how to best tackle this problem are welcomed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Edit**&#xD;&#xA;&#xD;&#xA;Changing the precision to `highp float` helps resolve the issue (not sure why), though that's not desirable on mobile.&#xD;&#xA;&#xD;&#xA;**Edit 2**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've decided to replace my uniform branches with preprocessor directives: &#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;vec2 getBaseColorTexCoords() {&#xD;&#xA;    vec2 texCoords;&#xD;&#xA;&#xD;&#xA;#ifdef BASE_COLOR_TEX_COORD_SET_0&#xD;&#xA;    texCoords = o_texCoords0;&#xD;&#xA;#else&#xD;&#xA;    texCoords = o_texCoords1;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;    return texCoords;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Cons: more cumbersome to maintain (perhaps also program switches, but I haven't benchmarked yet and it seems to run just fine)&#xD;&#xA;&#xD;&#xA;Pros: no artifacts, don't have to use `highp` precision, recommended by [Mali][6]:&#xD;&#xA;&#xD;&#xA;&gt; Use #defines at compile time in OpenGL ES, and specialization constants in Vulkan for all control flow. Doing so allows the compilation to completely remove unused code blocks and statically unroll loops.&#xD;&#xA;&#xD;&#xA;So I'll roll with this for now.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/MultiUVTest&#xD;&#xA;  [2]: https://i.stack.imgur.com/jEVDyl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/eMxEMl.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/MKCBGm.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/lmazGm.jpg&#xD;&#xA;  [6]: https://developer.arm.com/documentation/101897/v2-2/Shader-code/Uniform-control-flow" ContentLicense="CC BY-SA 4.0" />
  <row Id="37223" PostHistoryTypeId="2" PostId="12721" RevisionGUID="38146de5-a17d-464e-9b9f-3a01aae5d1c4" CreationDate="2022-05-26T11:40:36.003" UserId="7952" Text="Usually the tangent and normal for a given vertex TBN is passed in as a vertex attribute, something along the lines of this...&#xD;&#xA;&#xD;&#xA;    x,y,z //vertex position&#xD;&#xA;    x,y,z //normal&#xD;&#xA;    x,y,z,w //tangent where &quot;w&quot; represents the direction of the bitangent&#xD;&#xA;    u,v //texture coordinates&#xD;&#xA;&#xD;&#xA;Given that set of attributes:&#xD;&#xA;The bitangent is computed by taking the cross product of vertex attributes tangent and normal, then multiplied by the w coordinated of the tangent to get the correct direction. The w component is either 1 or -1. This gives us our TBN.&#xD;&#xA;&#xD;&#xA;The fragment shader uses the UV coordinates to lookup the associated normal from a normal map. Then uses the TBN computed above to compute a normal that will be used for lighting.&#xD;&#xA;&#xD;&#xA;That's pretty much it.&#xD;&#xA;&#xD;&#xA;All the hard work is precomputed. A normal map is computed from the height map. The TBN for the mesh vertex attributes is also precomputed.&#xD;&#xA;&#xD;&#xA;One way to compute the TBN is using the UV coordinates and vertex positions to create a system of equations which can be solved to find the tangent and bitangent.&#xD;&#xA;&#xD;&#xA;The TBN values are also typically &quot;averaged&quot; together with neighboring TBN vectors, and finally orthonormalized to get a better tangent frame." ContentLicense="CC BY-SA 4.0" />
  <row Id="37225" PostHistoryTypeId="2" PostId="12722" RevisionGUID="262188cf-ff66-4cbd-905e-ccbf1a8cce06" CreationDate="2022-05-26T13:26:14.530" UserId="18447" Text="I have two 3D polygons, and in both of them all vertices are coplanar.  I set a viewing direction and transform the polygons into the coordinate system of the viewing direction, such that the x, y components of the vertices are the projection into the orthographic viewing plane and the z component is the distance from the plane.  What I want to do now is to create the set of 2d polygons that outline all of the visible surfaces.  To do this I take the difference of the front polygon from the one in back, resulting in just that portion of the back polygon that is visible.&#xD;&#xA;&#xD;&#xA;The part that I am stuck on is how do I determine which polygon is in front?  There are simple cases where all of the z-values in one will be greater than the z-values in the other, but there will be more complicated cases where the z-extents of both overlap.  I imagine this must be known, but I am having trouble finding the answer.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZzXaZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37227" PostHistoryTypeId="1" PostId="12722" RevisionGUID="262188cf-ff66-4cbd-905e-ccbf1a8cce06" CreationDate="2022-05-26T13:26:14.530" UserId="18447" Text="Given two non-intersecting polygons, how to determine which one is in front" ContentLicense="CC BY-SA 4.0" />
  <row Id="37228" PostHistoryTypeId="3" PostId="12722" RevisionGUID="262188cf-ff66-4cbd-905e-ccbf1a8cce06" CreationDate="2022-05-26T13:26:14.530" UserId="18447" Text="|computational-geometry|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37229" PostHistoryTypeId="2" PostId="12723" RevisionGUID="ca7b8ebc-d1d0-4233-be12-167b3133276c" CreationDate="2022-05-26T14:02:39.273" UserId="18448" Text="This question is motivated by looking at two numbers for different GPU's: (1) the memory size and (2) the memory bandwidth. &#xD;&#xA;&#xD;&#xA;My understanding is that memory bandwidth means, the amount of data that can be copied from the system RAM to the GPU RAM (or vice versa) per second.&#xD;&#xA;&#xD;&#xA;But looking at typical GPU's, the memory bandwitdh per second is much larger than the memory size: e.g. the Nvidia A100 has memory size 40 or 80 GB, and the memory bandwitdh is 1555 GB/s. This suggests that the GPU can copy its entire memory contents over to system RAM or back within about 1/20th or 1/40th of a second. Maybe this is true, but it just sounds insanel" ContentLicense="CC BY-SA 4.0" />
  <row Id="37231" PostHistoryTypeId="1" PostId="12723" RevisionGUID="ca7b8ebc-d1d0-4233-be12-167b3133276c" CreationDate="2022-05-26T14:02:39.273" UserId="18448" Text="What does memory bandwidth of a GPU mean exactly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37232" PostHistoryTypeId="3" PostId="12723" RevisionGUID="ca7b8ebc-d1d0-4233-be12-167b3133276c" CreationDate="2022-05-26T14:02:39.273" UserId="18448" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37233" PostHistoryTypeId="5" PostId="12723" RevisionGUID="c443d845-93d2-4515-bca1-f94e931f11dc" CreationDate="2022-05-26T15:08:45.650" UserId="18448" Comment="added 8 characters in body" Text="This question is motivated by looking at two numbers for different GPU's: (1) the memory size and (2) the memory bandwidth. &#xD;&#xA;&#xD;&#xA;My understanding is that memory bandwidth means, the amount of data that can be copied from the system RAM to the GPU RAM (or vice versa) per second.&#xD;&#xA;&#xD;&#xA;But looking at typical GPU's, the memory bandwitdh per second is much larger than the memory size: e.g. the Nvidia A100 has memory size 40 or 80 GB, and the memory bandwitdh is 1555 GB/s. This suggests that the GPU can copy its entire memory contents over to system RAM or back within about 1/20th or 1/40th of a second. Maybe this is true, but it just sounds extremely fast." ContentLicense="CC BY-SA 4.0" />
  <row Id="37234" PostHistoryTypeId="2" PostId="12724" RevisionGUID="e2d6baad-a7a5-4e29-be32-b28de8fb00d4" CreationDate="2022-05-26T15:49:51.927" UserId="18450" Text="Memory Bandwidth is the theoretical maximum amount of data that the bus can handle at any given time, playing a determining role in how quickly a GPU can access and utilize its frame buffer." ContentLicense="CC BY-SA 4.0" />
  <row Id="37236" PostHistoryTypeId="2" PostId="12725" RevisionGUID="42cf246a-5fb9-409b-8b3d-7e8a17e015f1" CreationDate="2022-05-26T15:51:09.133" UserId="2654" Text="Before we begin, it's important to understand that raw spec numbers are typically not meant for use by actual graphics programmers. They are marketing tools to sell products. Sure, they have to be &quot;accurate&quot; (somewhat), but that does not mean that they are meaningful.&#xD;&#xA;&#xD;&#xA;As for what bandwidth actually means, consider two parking lots. They can hold a number of cars. Connecting them is a road. This road has a number of lanes. In terms of meaningful &quot;bandwidth,&quot; that is the answer to the question, &quot;how many cars can I get from one lot to the other?&quot; In our analogy, parking lots are pools of memory; the road is the connection between them.&#xD;&#xA;&#xD;&#xA;So if someone tells you they have a 16 lane highway, does that mean something? Not really, not unless you know what parking lots that highway *connects*. The same goes for bandwidth; a raw number means nothing without knowing the source and destination memory for that bandwidth.&#xD;&#xA;&#xD;&#xA;Marketers sometimes just add bandwidths from completely different memory pools together, as though the sum of lanes from 4 unconnected highways has some actual meaning.&#xD;&#xA;&#xD;&#xA;So bandwidth is a measure of the rate of flow between pools of memory. It is the amount of data that can flow from one pool to another in a unit of time. These pools can be general GPU RAM, storage within a compute unit, various caches, etc. Many modern GPUs have memory architectures that connect many of these pools onto a single bus (effectively linking all parking lots by a single set of roads).&#xD;&#xA;&#xD;&#xA;The other thing to remember is that pools of memory are not always *permanent*. Caches, compute storage, and the like are volatile; they get overwritten constantly by design. They exist because accessing bulk storage is slow, so operations that need to access memory quickly need small pools of faster memory closer to their use of this data.&#xD;&#xA;&#xD;&#xA;If the bandwidth from GPU memory to a texture cache is 1'555GB/sec, this means that, within a 60fps frame, the total amount of storage that all shaders can access via texture fetches is 25.9GB. You may note that this is much smaller than the 40GB of storage such a GPU may have.&#xD;&#xA;&#xD;&#xA;GPU bandwidths are so large *per second* because GPUs have to use that bandwidth many times per second. Once you look at them per frame, they're not so large.&#xD;&#xA;&#xD;&#xA;Also, all bandwidth from one pool to another is purely *theoretical*. If nobody is reading from memory at any particular cycle, that cycle's worth of bandwidth goes *unused*. It can't be stored and use later when there's more memory pressure. You either use it or you lose it. And since GPU workloads tend to read memory in spurts, the *usable* bandwidth is often lower than the numerically available bandwidth." ContentLicense="CC BY-SA 4.0" />
  <row Id="37243" PostHistoryTypeId="36" PostId="12727" RevisionGUID="220d31be-5239-4cf0-a51b-0e3fbee8c3a4" CreationDate="2022-05-27T19:50:17.763" UserId="-1" Comment="from https://stackoverflow.com/questions/72410122/what-cmfs-aka-spectral-functions-did-microsoft-and-hp-use-to-develop-srgb-stan" />
  <row Id="37244" PostHistoryTypeId="2" PostId="12727" RevisionGUID="ba8cd3c7-421d-4868-b6e0-abc597636df9" CreationDate="2022-05-27T19:18:06.107" UserDisplayName="Ben McKenneby" Text="CIE 1931 2° probably served as a basis, but which version?&#xD;&#xA;&#xD;&#xA;Published in 1999, the final specification can not have referred to CIE 2006, but [cvrl.org lists several others][1]: CIE 1931 2°, CIE 1931 2° Judd 1951, or CIE 1931 2° Judd 1951 and Vos 1978?  It also provides variants of CIE 1931 at 5 nano meter or 1 nano meter wavelength step sizes.  If the spec ignored updated CMFs, which resolution underpins sRGB?&#xD;&#xA;&#xD;&#xA;How about for other spaces like Adobe RGB 1998, Apple RGB, and P3-Display?&#xD;&#xA;&#xD;&#xA;How does one go about determining which CMFs underlie color spaces in general?&#xD;&#xA;&#xD;&#xA;  [1]: http://www.cvrl.org/cmfs.htm" ContentLicense="CC BY-SA 4.0" />
  <row Id="37246" PostHistoryTypeId="1" PostId="12727" RevisionGUID="ba8cd3c7-421d-4868-b6e0-abc597636df9" CreationDate="2022-05-27T19:18:06.107" UserDisplayName="Ben McKenneby" Text="What CMFs (aka Spectral Functions) did Microsoft and HP use to develop sRGB standardized in: IEC 61966-2-1:1999?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37247" PostHistoryTypeId="3" PostId="12727" RevisionGUID="ba8cd3c7-421d-4868-b6e0-abc597636df9" CreationDate="2022-05-27T19:18:06.107" UserDisplayName="Ben McKenneby" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37248" PostHistoryTypeId="6" PostId="12727" RevisionGUID="2a132191-54f9-49d2-94ac-bf2a1fb78791" CreationDate="2022-05-27T20:56:21.957" UserId="18457" Comment="Added tags to the question." Text="|color-science|color-management|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37251" PostHistoryTypeId="2" PostId="12728" RevisionGUID="1ae49e87-cf07-41e2-a47e-ea0b0eccb967" CreationDate="2022-05-28T06:45:13.263" UserId="18460" Text="Have a fragment shader:  &#xD;&#xA;```&#xD;&#xA;// simply set all pixel white if inside unit circle else transparent.&#xD;&#xA;&#xD;&#xA;#pragma fragment frag&#xD;&#xA;float4 frag(float4 Pos : SV_POSITION) : SV_TARGET&#xD;&#xA;{&#xD;&#xA;    return Pos.x * Pos.x + Pos.y * Pos.y &lt;= rad * rad;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;How to apply Anti-Aliasing?&#xD;&#xA;from [this](https://i.stack.imgur.com/bLqSF.png) to [this](https://i.stack.imgur.com/fMt9y.png).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37253" PostHistoryTypeId="1" PostId="12728" RevisionGUID="1ae49e87-cf07-41e2-a47e-ea0b0eccb967" CreationDate="2022-05-28T06:45:13.263" UserId="18460" Text="Anti-Aliasing simple circle fragment shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="37254" PostHistoryTypeId="3" PostId="12728" RevisionGUID="1ae49e87-cf07-41e2-a47e-ea0b0eccb967" CreationDate="2022-05-28T06:45:13.263" UserId="18460" Text="|antialiasing|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37255" PostHistoryTypeId="5" PostId="12728" RevisionGUID="0403ee26-c7b9-4f0e-a34a-7317687576e2" CreationDate="2022-05-28T06:46:05.673" UserId="18460" Comment="deleted 8 characters in body" Text="Have a fragment shader:  &#xD;&#xA;```&#xD;&#xA;// simply set all pixel white if inside unit circle else transparent.&#xD;&#xA;&#xD;&#xA;#pragma fragment frag&#xD;&#xA;float4 frag(float4 Pos : SV_POSITION) : SV_TARGET&#xD;&#xA;{&#xD;&#xA;    return Pos.x * Pos.x + Pos.y * Pos.y &lt;= 1;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;How to apply Anti-Aliasing?&#xD;&#xA;from [this](https://i.stack.imgur.com/bLqSF.png) to [this](https://i.stack.imgur.com/fMt9y.png).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37256" PostHistoryTypeId="2" PostId="12729" RevisionGUID="1a80999b-1ba2-4449-bde4-21fb4058a29c" CreationDate="2022-05-28T10:29:01.777" UserId="18448" Text="I was looking at the specs of [this GPU][1] in particular, and tried to compute its theoretical GFLOPs based on more basic specs, such as clock frequency and number of CUDA cores. &#xD;&#xA;&#xD;&#xA;My first thought was: each cuda core probably computes one FLOP per cycle, and the clock frequency is 900 MHz = 0.9 GHz, and it has 384 CUDA cores, so this gives:&#xD;&#xA;0.9 * 384 * 1 = 345 GFLOPs. However, the card's actual GFLOPs (in FP32) is stated to be 692.7 GFLOPS.&#xD;&#xA;&#xD;&#xA;So my calculation is off, and I'm not sure why. **What is the correct way of calculating the theoretical GFLOPs of a GPU?** I'm ok with the calculation being more complicated or merely approximate.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.techpowerup.com/gpu-specs/geforce-gt-640.c813" ContentLicense="CC BY-SA 4.0" />
  <row Id="37258" PostHistoryTypeId="1" PostId="12729" RevisionGUID="1a80999b-1ba2-4449-bde4-21fb4058a29c" CreationDate="2022-05-28T10:29:01.777" UserId="18448" Text="How to compute a GPU's theoretical GFLOPs based on its specs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37259" PostHistoryTypeId="3" PostId="12729" RevisionGUID="1a80999b-1ba2-4449-bde4-21fb4058a29c" CreationDate="2022-05-28T10:29:01.777" UserId="18448" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37260" PostHistoryTypeId="2" PostId="12730" RevisionGUID="789145e6-16c2-480b-b73e-4a7c20b0f127" CreationDate="2022-05-28T22:36:34.373" UserId="9044" Text="Probably the simplest way is to use [smoothstep][1] to make a transition from white to black:&#xD;&#xA;&#xD;&#xA;    float R = 0.5 / ScreenSize; // you'll have to pass or hardcode it&#xD;&#xA;    return smoothstep(Pos.x * Pos.x + Pos.y * Pos.y, 1.0 - R, 1.0 + R);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-smoothstep" ContentLicense="CC BY-SA 4.0" />
  <row Id="37262" PostHistoryTypeId="2" PostId="12731" RevisionGUID="72d4a7c2-e535-4449-9b03-4f4ac17134ea" CreationDate="2022-05-28T22:50:49.727" UserId="18463" Text="I want to know what is view transformation, and what is model transformation respectively, and what methods/functions in opengl could be applied to implement each transformation.&#xD;&#xA;Just simple ways to implement each transformation." ContentLicense="CC BY-SA 4.0" />
  <row Id="37264" PostHistoryTypeId="1" PostId="12731" RevisionGUID="72d4a7c2-e535-4449-9b03-4f4ac17134ea" CreationDate="2022-05-28T22:50:49.727" UserId="18463" Text="What is view transformation and model transformation respectively? How do I implement each transformation in simple opengl program?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37265" PostHistoryTypeId="3" PostId="12731" RevisionGUID="72d4a7c2-e535-4449-9b03-4f4ac17134ea" CreationDate="2022-05-28T22:50:49.727" UserId="18463" Text="|opengl|transformations|implementation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37266" PostHistoryTypeId="2" PostId="12732" RevisionGUID="98cc2358-7257-463a-9d29-17ff5c50bbfb" CreationDate="2022-05-29T02:08:21.630" UserId="11224" Text="Using&#xD;&#xA;&#xD;&#xA;    glTexStorage2D(GL_TEXTURE_2D, num_mipmaps, GL_RGBA8, width, height);&#xD;&#xA;&#xD;&#xA;followed by&#xD;&#xA;&#xD;&#xA;    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, data);&#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;we can ask OpenGL to generate storage for the first `num_mipmaps` many mipmaps levels, and to compute and store those mipmaps. The width and height need not be a power of 2.&#xD;&#xA;&#xD;&#xA;According to this:&#xD;&#xA;&#xD;&#xA;[Khronos webpage on Texture Storage][1]&#xD;&#xA;&#xD;&#xA;the dimensions of each new mipmap level are computed by halving corresponding dimension of the previous level, and rounding down, and that this process stops when all dimensions are 1.&#xD;&#xA;&#xD;&#xA;It seems to me that if this were 100% literally what happens, then in some cases we might actually reach an image one of whose dimensions was 1, and the other of which was greater than 1. If we were to halve and round down once more, then the smaller dimension would become 0. Is it more accurate to say that the function mapping a given dimension of the current level to the corresponding dimension of the next level, is actually&#xD;&#xA;\begin{equation}&#xD;&#xA;f(x) = \max(\lfloor x/2 \rfloor), 1)&#xD;&#xA;\end{equation}&#xD;&#xA;where $\lfloor \cdot \rfloor$ denotes the floor function ?&#xD;&#xA;&#xD;&#xA;Since I am using automatic mipmap storage generation, I suppose that I do not need these two calls:&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);&#xD;&#xA;&#xD;&#xA;at least, so it seems according to this:&#xD;&#xA;&#xD;&#xA;[Khronos webpage on common mistakes][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Texture_Storage#Image_sizes&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Common_Mistakes#Automatic_mipmap_generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="37268" PostHistoryTypeId="1" PostId="12732" RevisionGUID="98cc2358-7257-463a-9d29-17ff5c50bbfb" CreationDate="2022-05-29T02:08:21.630" UserId="11224" Text="Calculating maximum number of mipmap levels for OpenGL automatic mipmap storage generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="37269" PostHistoryTypeId="3" PostId="12732" RevisionGUID="98cc2358-7257-463a-9d29-17ff5c50bbfb" CreationDate="2022-05-29T02:08:21.630" UserId="11224" Text="|opengl|texture|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37270" PostHistoryTypeId="2" PostId="12733" RevisionGUID="1ff2cc1a-8a9f-4c3c-a4b0-0bfd5838c620" CreationDate="2022-05-29T09:32:14.327" UserId="17510" Text="I'm trying to find a way to visualize the outgoing directions sampled from BSDF. &#xD;&#xA;&#xD;&#xA;More specifically, for a given incident direction, I can sample the outgoing directions, using 'BSDF sample', and I want to visualize them. I tried to output some images but they have low quality. Does anyone know how to visualize those outgoing directions? Is there any software researchers often use for a case like this? Or some API? Or something else? Thanks a lot!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37272" PostHistoryTypeId="1" PostId="12733" RevisionGUID="1ff2cc1a-8a9f-4c3c-a4b0-0bfd5838c620" CreationDate="2022-05-29T09:32:14.327" UserId="17510" Text="How to visualize the outgoing directions sampled from BSDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37273" PostHistoryTypeId="3" PostId="12733" RevisionGUID="1ff2cc1a-8a9f-4c3c-a4b0-0bfd5838c620" CreationDate="2022-05-29T09:32:14.327" UserId="17510" Text="|rendering|brdf|bsdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37274" PostHistoryTypeId="50" PostId="12163" RevisionGUID="2d9b563a-ef64-44c7-87aa-28127ff0e1fc" CreationDate="2022-05-29T11:03:00.323" UserId="-1" />
  <row Id="37275" PostHistoryTypeId="5" PostId="12721" RevisionGUID="db0167a1-6c0f-4e72-ab89-fc65f10f35c1" CreationDate="2022-05-29T15:11:14.133" UserId="7952" Comment="added 1008 characters in body" Text="Usually the tangent and normal for a given vertex TBN is passed in as a vertex attribute, something along the lines of this...&#xD;&#xA;&#xD;&#xA;    x,y,z //vertex position&#xD;&#xA;    x,y,z //normal&#xD;&#xA;    x,y,z,w //tangent where &quot;w&quot; represents the direction of the bitangent&#xD;&#xA;    u,v //texture coordinates&#xD;&#xA;&#xD;&#xA;Given that set of attributes:&#xD;&#xA;The bitangent is computed by taking the cross product of vertex attributes tangent and normal, then multiplied by the w coordinated of the tangent to get the correct direction. The w component is either 1 or -1. This gives us our TBN.&#xD;&#xA;&#xD;&#xA;The fragment shader uses the UV coordinates to lookup the associated normal from a normal map. Then uses the TBN computed above to compute a normal that will be used for lighting.&#xD;&#xA;&#xD;&#xA;That's pretty much it.&#xD;&#xA;&#xD;&#xA;All the hard work is precomputed. A normal map is computed from the height map. The TBN for the mesh vertex attributes is also precomputed.&#xD;&#xA;&#xD;&#xA;One way to compute the TBN is using the UV coordinates and vertex positions to create a system of equations which can be solved to find the tangent and bitangent.&#xD;&#xA;&#xD;&#xA;The TBN values are also typically &quot;averaged&quot; together with neighboring TBN vectors, and finally orthonormalized to get a better tangent frame.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;When computing the Tangent frame, *u* and *v* coordinates for the vertex attributes give distances along the *t* and *b* axes and are aligned to the *x* and *y* directions of the texture map.&#xD;&#xA;&#xD;&#xA;This means that the *T* and *B* vectors of the TBN rotate vectors from the normal map in the *x*, *y* plane to align with triangles in the mesh.&#xD;&#xA;&#xD;&#xA;If we then take that tangent frame and attempt to use it with vectors derived from derivatives of values in a height map, we may end up with *T* and *B* vectors that are in the correct plane, but those vectors will be rotated so they point in directions aligned with texture space of the normal map they are created for. This will result in transformed normals that are correct when they align with the original texture map, but will otherwise point in directions that give unusable results.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Another approach to this problem that is somewhat similar to what you are describing is called &quot;derivative maps&quot;. I recommend looking up that technique." ContentLicense="CC BY-SA 4.0" />
  <row Id="37276" PostHistoryTypeId="2" PostId="12734" RevisionGUID="6a741470-5bff-4f8a-95a8-7e336c92e662" CreationDate="2022-05-29T15:25:00.890" UserId="7952" Text="Both the Model and View are created through basic linear algebra techniques. Both are 4x4 matrices which is a fundamental part of the GLSL language. OpenGL usually has very little to do with their actual creation, but is used to transfer the matrices to the GPU.&#xD;&#xA;&#xD;&#xA;OpenGL is the API that allows programs to interact with the GPU, GLSL is a language that can be used to write programs that are executed on the GPU itself. The programs written in GLSL is where the View and Model matrix would be used.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37278" PostHistoryTypeId="5" PostId="12732" RevisionGUID="b683ecd0-85f6-45dd-a5a1-2af00e5efdf4" CreationDate="2022-05-29T21:04:25.363" UserId="11224" Comment="added 404 characters in body" Text="Using&#xD;&#xA;&#xD;&#xA;    glTexStorage2D(GL_TEXTURE_2D, num_mipmaps, GL_RGBA8, width, height);&#xD;&#xA;&#xD;&#xA;followed by&#xD;&#xA;&#xD;&#xA;    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, data);&#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;we can ask OpenGL to generate storage for the first `num_mipmaps` many mipmaps levels, and to compute and store those mipmaps. The width and height need not be a power of 2.&#xD;&#xA;&#xD;&#xA;According to this:&#xD;&#xA;&#xD;&#xA;[Khronos webpage on Texture Storage][1]&#xD;&#xA;&#xD;&#xA;the dimensions of each new mipmap level are computed by halving corresponding dimension of the previous level, and rounding down, and that this process stops when all dimensions are 1.&#xD;&#xA;&#xD;&#xA;It seems to me that if this were 100% literally what happens, then in some cases we might actually reach an image one of whose dimensions was 1, and the other of which was greater than 1. If we were to halve and round down once more, then the smaller dimension would become 0. Is it more accurate to say that the function mapping a given dimension of the current level to the corresponding dimension of the next level, is actually&#xD;&#xA;\begin{equation}&#xD;&#xA;f(x) = \max(\lfloor x/2 \rfloor), 1)&#xD;&#xA;\end{equation}&#xD;&#xA;where $\lfloor \cdot \rfloor$ denotes the floor function ?&#xD;&#xA;&#xD;&#xA;Since I am using automatic mipmap storage generation, I suppose that I do not need these two calls:&#xD;&#xA;&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);&#xD;&#xA;&#xD;&#xA;at least, so it seems according to this:&#xD;&#xA;&#xD;&#xA;[Khronos webpage on common mistakes][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 1**&#xD;&#xA;&#xD;&#xA;If indeed the dimensions were clamped below to 1, then I suppose that the function for computing the number of distinct mipmap levels would be&#xD;&#xA;\begin{equation}&#xD;&#xA;f(w, h) = \lfloor \log_2(\max(w, h)) \rfloor&#xD;&#xA;\end{equation}&#xD;&#xA;or else&#xD;&#xA;\begin{equation}&#xD;&#xA;f(w, h) = \lfloor \log_2(\min(w, h)) \rfloor&#xD;&#xA;\end{equation}&#xD;&#xA;but the language on the Khronos website seems to suggest it's the former, which would also make more sense, since one might have a triangle whose projection into texture space was very long and thin, and whose projection onto the screen occupied only a single pixel.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT 2**&#xD;&#xA;&#xD;&#xA;Whatever the answer to my question, a separate question is whether I need to set `glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, f(w, h));` or whether the use of `glGenerateMipmap(GL_TEXTURE_2D);` takes care of this automatically.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Texture_Storage#Image_sizes&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Common_Mistakes#Automatic_mipmap_generation" ContentLicense="CC BY-SA 4.0" />
  <row Id="37279" PostHistoryTypeId="2" PostId="12735" RevisionGUID="cd5c98ad-2808-4e78-896b-c62c43f72de6" CreationDate="2022-05-29T21:14:55.883" UserId="48" Text="As you surmised, the minimum dimension is 1, and for non-square images the smaller dimension will remain 1 until we get all the way down to 1x1.&#xD;&#xA;&#xD;&#xA;I make the _count_ of mip levels to be $\lfloor \log_2(\max(w,h)) \rfloor + 1$, while the _index_ of the last level is the formula without the +1 (due to the first level being index 0).&#xD;&#xA;&#xD;&#xA;Regarding `GL_TEXTURE_MAX_LEVEL`, I don't think that you need to set it at all; the [documentation](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml) says that the default value is 1000, which is far more than the number of mip levels of any conceivable texture. So it seems like it only acts as an upper bound." ContentLicense="CC BY-SA 4.0" />
  <row Id="37281" PostHistoryTypeId="2" PostId="12736" RevisionGUID="c15362c6-03c7-443a-af05-fd356f90931b" CreationDate="2022-05-30T06:36:57.737" UserId="18373" Text="I have a set of vertexes (x, y, z) in normalized device coordinates. Its x, y, and z values are in range (-1, 1). Normalized device coordinates uses the left handed coordinate system, as shown below&#xD;&#xA;&#xD;&#xA;[![ndc][1]][1]&#xD;&#xA;&#xD;&#xA;I want to convert NDC vertexes into a viewport whose coordinate system which looks like this&#xD;&#xA;&#xD;&#xA;[![vp][2]][2]&#xD;&#xA;&#xD;&#xA;It is a standard coordinate system used by most 2D graphics libraries. x starts from top left corner and goes to right while y starts from the same corner and goes down. I decided to make z to go into the page. All NDC vertexes must fit inside the dotted rectangular box, shown above.&#xD;&#xA;&#xD;&#xA;What are the set of transformation matrixes that converts NDC coordinates $(x, y, z, 1)$ (note that I am using homogenous coordinates here) to viewport coordinates $(x', y', z', 1)$?&#xD;&#xA;&#xD;&#xA;This is what I came up with&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x' \\&#xD;&#xA;y' \\&#xD;&#xA;z' \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; width/2 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; height/2 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;width/2 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; -height/2 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $width$ and $height$ are width and height of viewport. I first scale vertexes to viewport width and height and also flip the y coordinate (notice the minus sign). Then I translate the resulting vertex to fit in the viewport. But I'm not sure if my viewport transformation matrix is correct because I think the resulting z value might be wrong. What should I change here?&#xD;&#xA;&#xD;&#xA;—————-&#xD;&#xA;&#xD;&#xA;Crossposted in [math.stackexchange](https://math.stackexchange.com/questions/4461572/what-are-viewport-transformation-matrixes-for-this-coordinate-system).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fTZhO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DNW3E.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37283" PostHistoryTypeId="1" PostId="12736" RevisionGUID="c15362c6-03c7-443a-af05-fd356f90931b" CreationDate="2022-05-30T06:36:57.737" UserId="18373" Text="What are viewport transformation matrixes for this coordinate system?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37284" PostHistoryTypeId="3" PostId="12736" RevisionGUID="c15362c6-03c7-443a-af05-fd356f90931b" CreationDate="2022-05-30T06:36:57.737" UserId="18373" Text="|transformations|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37285" PostHistoryTypeId="2" PostId="12737" RevisionGUID="96ccd7d4-4e53-4edf-8aac-ac86fff37d0e" CreationDate="2022-05-30T08:41:11.123" UserId="18373" Text="I am currently creating my own 3D renderer. Here is a coloured cube created by the renderer.&#xD;&#xA;&#xD;&#xA;[![cube][1]][1]&#xD;&#xA;&#xD;&#xA;I modelled cube using a set of coloured triangles. Notice extraneous lines from edges and cube edges does not look straight to me. Also there is a visible diagonal line from the bottom face as a result of using two triangles to represent square. How can I eliminate these deficiencies?&#xD;&#xA;&#xD;&#xA;I used a variant of Bresenham's Algorithm to draw lines and [the standard algorithm](http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html) to render filled triangles.&#xD;&#xA;&#xD;&#xA;I want to improve my triangle and line rendering functions. I wonder how OpenGL are able to render smooth lines and triangles. What kind algorithms they use?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HdodN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37287" PostHistoryTypeId="1" PostId="12737" RevisionGUID="96ccd7d4-4e53-4edf-8aac-ac86fff37d0e" CreationDate="2022-05-30T08:41:11.123" UserId="18373" Text="How to draw smoother lines and triangles?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37288" PostHistoryTypeId="3" PostId="12737" RevisionGUID="96ccd7d4-4e53-4edf-8aac-ac86fff37d0e" CreationDate="2022-05-30T08:41:11.123" UserId="18373" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37289" PostHistoryTypeId="5" PostId="12737" RevisionGUID="e932ee26-73b0-4e40-80ed-f010a06bc630" CreationDate="2022-05-30T08:47:18.827" UserId="18373" Comment="deleted 6 characters in body" Text="I am currently creating my own 3D renderer. Here is a coloured cube created by the renderer.&#xD;&#xA;&#xD;&#xA;[![cube][1]][1]&#xD;&#xA;&#xD;&#xA;I modelled cube using a set of coloured triangles. Notice extraneous lines from edges and they does not look straight to me. Also there is a visible diagonal line from the bottom face as a result of using two triangles to represent square. How can I eliminate these deficiencies?&#xD;&#xA;&#xD;&#xA;I used a variant of Bresenham's Algorithm to draw lines and [the standard algorithm](http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html) to render filled triangles.&#xD;&#xA;&#xD;&#xA;I want to improve my triangle and line rendering functions. I wonder how OpenGL are able to render smooth lines and triangles. What kind algorithms they use?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HdodN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37290" PostHistoryTypeId="50" PostId="10853" RevisionGUID="9efe3282-ef32-488c-9686-3d4b40934c13" CreationDate="2022-05-30T09:07:10.750" UserId="-1" />
  <row Id="37291" PostHistoryTypeId="2" PostId="12738" RevisionGUID="5bc36ccc-84a5-40d8-8a09-da3321cd7c2a" CreationDate="2022-05-30T10:35:49.333" UserId="7952" Text="The &quot;big idea&quot; around most anti aliasing algorithms is taking multiple samples in the region around the fragment in question. These can range from very simple above/below to random samples to complex heuristics. &#xD;&#xA;&#xD;&#xA;Another issue is the distance that those samples are taken from the original fragment. Here again it can range from simple fixed distance to &quot;smart&quot; heuristics.&#xD;&#xA;&#xD;&#xA;Last but not least is weighting the samples taken. And as you can guess this ranges from a simple average, to weights that compute the distance to other fragments and many other schemes. (weights are like CPU TLB algorithms, everyone has a better one, but we always use the generic version because its good enough)&#xD;&#xA;&#xD;&#xA;There is also the issue of diminishing returns where taking more samples doesn't really help the final output.&#xD;&#xA;&#xD;&#xA;I wrote a shader toy that demonstrates basic antialiasing using an ellipse (partly because I was to lazy to adjust for aspect ratio) and is very similar to the sample you submitted with your question. Also, I tried to make it easy to change the sampling and turn sampling on/off.&#xD;&#xA;&#xD;&#xA;The shader toy can be found [here][1]. &#xD;&#xA;&#xD;&#xA;Here is the code of the shader toy:&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;&#xD;&#xA;     // Comment this out to turn of sampling &#xD;&#xA;    #define do_samples&#xD;&#xA;    &#xD;&#xA;    // Average the samples together&#xD;&#xA;    float num_samples =0.0;&#xD;&#xA;    &#xD;&#xA;    vec4 GetFragValAt( vec2 uv )&#xD;&#xA;    {&#xD;&#xA;        num_samples += 1.0;&#xD;&#xA;        &#xD;&#xA;        // dot is same as uv.x*uv.x+uv.y*uv.y&#xD;&#xA;        return vec4( dot( uv, uv) &lt;= 0.4);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void mainImage( out vec4 fragColor, in vec2 fragCoord )&#xD;&#xA;    {&#xD;&#xA;     &#xD;&#xA;        // Normalized pixel coordinates (from -1 to 1)&#xD;&#xA;        vec2 uv = fragCoord/iResolution.xy*2.0-1.0;&#xD;&#xA;        &#xD;&#xA;        // Change offset to adjust sampling distance&#xD;&#xA;        float offset = 0.002;&#xD;&#xA;        &#xD;&#xA;        fragColor = GetFragValAt( uv );&#xD;&#xA;        &#xD;&#xA;        #ifdef do_samples&#xD;&#xA;        // samples in +/- x direction&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2( offset, 0.0));&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2( -offset, 0.0));&#xD;&#xA;        &#xD;&#xA;        // samples in +/- y direction&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2( 0.0, offset ));&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2( 0.0, -offset));&#xD;&#xA;        &#xD;&#xA;        // samples at diagonals&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2(offset, offset));&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2(-offset, offset));&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2(offset, -offset));&#xD;&#xA;        fragColor += GetFragValAt(uv + vec2(-offset, -offset));&#xD;&#xA;        #endif&#xD;&#xA;        &#xD;&#xA;        // compute average&#xD;&#xA;        fragColor /= num_samples;&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/Ns3yzs" ContentLicense="CC BY-SA 4.0" />
  <row Id="37293" PostHistoryTypeId="2" PostId="12739" RevisionGUID="54f75809-49a7-4a82-9d97-87bed699e859" CreationDate="2022-05-30T19:49:26.290" UserId="11094" Text="I keep running into this phrase when reading specs and tutorials, but I have no idea what &quot;tightly packed&quot; is supposed to mean. Is it simply the opposite of an interleaved buffer? I.e. all the vertex data of a position attribute first, and then the normal attribute data sticked right after it? Or is it something else?&#xD;&#xA;&#xD;&#xA;For instance, from [the glTF spec][1]:&#xD;&#xA;&#xD;&#xA;&gt; If the accessor is used for any other kind of data (vertex indices, animation keyframes, etc.), its data elements are tightly packed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="37295" PostHistoryTypeId="1" PostId="12739" RevisionGUID="54f75809-49a7-4a82-9d97-87bed699e859" CreationDate="2022-05-30T19:49:26.290" UserId="11094" Text="What does it mean for a buffer to be &quot;tightly packed&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37296" PostHistoryTypeId="3" PostId="12739" RevisionGUID="54f75809-49a7-4a82-9d97-87bed699e859" CreationDate="2022-05-30T19:49:26.290" UserId="11094" Text="|vertex-buffer-object|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37297" PostHistoryTypeId="2" PostId="12740" RevisionGUID="2b5f8112-cb63-4b02-b7d8-ba8e21d7b472" CreationDate="2022-05-30T20:15:35.777" UserId="2654" Text="To take an example from the glTF spec you cited:&#xD;&#xA;&#xD;&#xA;&gt; The stride, in bytes, between vertex attributes. When this is not defined, data is tightly packed.&#xD;&#xA;&#xD;&#xA;The stride of an array is the number of bytes from the start of one element to the start of the next element. If that stride is the same as the byte size of an element, then the array is &quot;tightly packed&quot;. This means that there is no space between elements in the array; the byte after one element is the first byte of the next.&#xD;&#xA;&#xD;&#xA;What this is saying is that, if you don't specify a stride, then the stride will be computed to be the size of the element type in question.&#xD;&#xA;&#xD;&#xA;Interleaved vertex attributes are not &quot;tightly packed&quot; with respect to each other. If you have positions and normals interleaved, the position array is not tightly packed because the byte after one position is not the first byte of the next position.&#xD;&#xA;&#xD;&#xA;*However*, you could consider it to be &quot;tightly packed&quot; with respect to an aggregation of the vertex data as a whole. If the byte after one position/normal combination is the first byte of another position/normal combination, then this could be said to be a &quot;tightly packed&quot; array of position/normal aggregates." ContentLicense="CC BY-SA 4.0" />
  <row Id="37299" PostHistoryTypeId="52" PostId="12739" RevisionGUID="671c59b1-5b75-4823-bba3-32b1bf5c308c" CreationDate="2022-05-31T03:58:15.463" />
  <row Id="37300" PostHistoryTypeId="50" PostId="10509" RevisionGUID="5983c70c-c65a-434b-8b8f-30dcf8d66ef5" CreationDate="2022-05-31T06:04:25.490" UserId="-1" />
  <row Id="37301" PostHistoryTypeId="2" PostId="12741" RevisionGUID="ebffdd3b-4ad1-4413-a032-a3791835e8a0" CreationDate="2022-05-31T15:37:10.307" UserId="6041" Text="I am trying to do the derivation of transforming uniformly distributed 2D points on the unit square into the 2D &quot;tent&quot; distribution below. i.e the standard method of getting the cdf and inversting it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Peter Shirley has the sampling code for tent funciton in [his book][2] Realistic Ray tracing as this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;And I am trying to do the derivation of the formula here but somewhere I am making a mistake:&#xD;&#xA;&#xD;&#xA;So for the first part t=[-1,0), the cdf is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4] &#xD;&#xA;&#xD;&#xA;But I don't know where I got it wrong. Any idea anyone? Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/dAeDI.png&#xD;&#xA;  [2]: https://books.google.co.uk/books?id=knpN6mnhJ8QC&amp;pg=PA56&amp;lpg=PA56&amp;dq=importance%20sampling%20of%20triangle%20tent%20function&amp;source=bl&amp;ots=OLbIq51B9B&amp;sig=ACfU3U17KRJrkwjvmEmZA3elroPGDmkTwQ&amp;hl=en&amp;sa=X&amp;ved=2ahUKEwiou6yJ5In4AhVFoVwKHRExAI4Q6AF6BAgsEAM#v=onepage&amp;q=importance%20sampling%20of%20triangle%20tent%20function&amp;f=false&#xD;&#xA;  [3]: https://i.stack.imgur.com/iNwyS.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/TmSm5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37303" PostHistoryTypeId="1" PostId="12741" RevisionGUID="ebffdd3b-4ad1-4413-a032-a3791835e8a0" CreationDate="2022-05-31T15:37:10.307" UserId="6041" Text="Sampling 2d Tent Distribution" ContentLicense="CC BY-SA 4.0" />
  <row Id="37304" PostHistoryTypeId="3" PostId="12741" RevisionGUID="ebffdd3b-4ad1-4413-a032-a3791835e8a0" CreationDate="2022-05-31T15:37:10.307" UserId="6041" Text="|sampling|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37305" PostHistoryTypeId="4" PostId="12741" RevisionGUID="a4379491-0894-4fd1-a567-0a15b5f3e327" CreationDate="2022-05-31T15:54:00.633" UserId="6041" Comment="edited title" Text="Derivation of Sampling 2d Tent Distribution" ContentLicense="CC BY-SA 4.0" />
  <row Id="37306" PostHistoryTypeId="50" PostId="10537" RevisionGUID="9aa36025-51f6-41ba-bc8d-b410c4eebcda" CreationDate="2022-06-01T09:05:50.527" UserId="-1" />
  <row Id="37307" PostHistoryTypeId="2" PostId="12742" RevisionGUID="329c1569-37a7-461d-abdf-56369eef8ae4" CreationDate="2022-06-01T13:11:59.813" UserId="18481" Text="Quite an old post, put based on the comments here and the posted plot, &#xD;&#xA;I fitted a curve leading to the following equation:&#xD;&#xA;&#xD;&#xA;smoothness = 0.25 * shininess ^ 0.2" ContentLicense="CC BY-SA 4.0" />
  <row Id="37309" PostHistoryTypeId="2" PostId="12743" RevisionGUID="c7a88bf6-a56e-43d9-a0cc-d6cebd8326ac" CreationDate="2022-06-01T20:34:05.883" UserId="18484" Text="There's a set of pictures that if you take them literally, they're different. That is, there can be two images of the same thing among them, only in different hue. In addition, among these two, there is a difference in the white pixel filling. That is, there are several pixels that do not match the criterion: white or non-white.&#xD;&#xA;&#xD;&#xA;What is the algorithm for finding such two pictures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37311" PostHistoryTypeId="1" PostId="12743" RevisionGUID="c7a88bf6-a56e-43d9-a0cc-d6cebd8326ac" CreationDate="2022-06-01T20:34:05.883" UserId="18484" Text="How to identify images with similar content?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37312" PostHistoryTypeId="3" PostId="12743" RevisionGUID="c7a88bf6-a56e-43d9-a0cc-d6cebd8326ac" CreationDate="2022-06-01T20:34:05.883" UserId="18484" Text="|image|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37313" PostHistoryTypeId="6" PostId="12743" RevisionGUID="7f7aedc2-bcc1-43da-9dd0-0834fedcdcb7" CreationDate="2022-06-02T05:19:59.980" UserId="18484" Comment="edited tags" Text="|image-processing|image|raster-image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37314" PostHistoryTypeId="2" PostId="12744" RevisionGUID="ff9ee703-a939-4a34-aa6b-4613eba592c1" CreationDate="2022-06-02T10:27:25.383" UserId="18487" Text="I have EPS/PDF figures which contain scatterplots consisting of a lot of dots resulting in files sizes from dozens to hundreds of MBytes. Now, many of the points are completely hidden, so I could remove them from the EPS/PDF.&#xD;&#xA;&#xD;&#xA;I addition, I have a histogram on the plot where I have the same effect.&#xD;&#xA;&#xD;&#xA;The vector-graphics where generated in R (ggplot2 and generic R plot). Or do you know of some functionality in R?&#xD;&#xA;&#xD;&#xA;I am using GNU/Linux, is there a way to do this post generating the figures?&#xD;&#xA;&#xD;&#xA;And yes, I can export it to PNG/JPG/other, sure, but then my collaborator can not modify it without loss of quality (modification of text, etc.)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37316" PostHistoryTypeId="1" PostId="12744" RevisionGUID="ff9ee703-a939-4a34-aa6b-4613eba592c1" CreationDate="2022-06-02T10:27:25.383" UserId="18487" Text="How to remove elements in PDF/EPS vector graphics which are completely hidden?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37317" PostHistoryTypeId="3" PostId="12744" RevisionGUID="ff9ee703-a939-4a34-aa6b-4613eba592c1" CreationDate="2022-06-02T10:27:25.383" UserId="18487" Text="|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37319" PostHistoryTypeId="5" PostId="12744" RevisionGUID="e9ad11a8-d50a-4b80-a7b4-e8a4783e4eaf" CreationDate="2022-06-02T13:42:50.857" UserId="18487" Comment="deleted 76 characters in body" Text="I have EPS/PDF figures which contain scatterplots consisting of a lot of dots resulting in files sizes from dozens to hundreds of MBytes. Now, many of the points are completely hidden, so I could remove them from the EPS/PDF.&#xD;&#xA;&#xD;&#xA;The vector-graphics where generated in R (ggplot2 and generic R plot).&#xD;&#xA;&#xD;&#xA;I am using GNU/Linux, is there a way to do this post generating the figures? Or do you know of some functionality in R?&#xD;&#xA;&#xD;&#xA;And yes, I can export it to PNG/JPG/other, sure, but then my collaborator can not modify it without loss of quality (modification of text, etc.)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37320" PostHistoryTypeId="50" PostId="9829" RevisionGUID="018eb39f-afa8-4ea4-9655-882fcbbfb68b" CreationDate="2022-06-02T18:05:15.777" UserId="-1" />
  <row Id="37321" PostHistoryTypeId="34" PostId="12716" RevisionGUID="f1b068b7-6a90-4d78-9381-04d663dca13d" CreationDate="2022-06-03T00:04:10.393" UserId="-1" Comment="77" />
  <row Id="37325" PostHistoryTypeId="50" PostId="10341" RevisionGUID="7f8e0da6-59f0-4fb4-a137-665f6ee88e4b" CreationDate="2022-06-03T11:02:20.347" UserId="-1" />
  <row Id="37326" PostHistoryTypeId="2" PostId="12745" RevisionGUID="398c03b0-8eb7-4e83-9bd4-0578315b5ed4" CreationDate="2022-06-03T11:19:20.697" UserId="13095" Text="The z-axis is indeed not correct if you want to transform to the space depicted in the second picture, because you perform no transformations on the z-axis. So your coordinate origin lies in the middle between the top-left-front and the top-left-back vertex. The coordinate range is still -1 to 1. You can easily fix it by applying the same transformation as for the other axis. Introduce a depth to define the coordinate range in the z-direction. Then your correct transformation should be:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x' \\&#xD;&#xA;y' \\&#xD;&#xA;z' \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; width/2 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; height/2 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; depth/2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;width/2 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; -height/2 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; depth/2 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Multiplication yields the following transformation matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;width/2 &amp; 0 &amp; 0 &amp; width/2  \\&#xD;&#xA;0 &amp; -height/2 &amp; 0 &amp; height/2 \\&#xD;&#xA;0 &amp; 0 &amp; depth/2 &amp; depth/2 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;To understand it a bit better it is probably easier to postpone the scaling until the end and look at the different substeps.&#xD;&#xA;Starting in NDC coordinates, we first flip the y-axis using the reflection matrix:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; -1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As a result, the point `(-1,-1,-1)` in the new intermediate coordinate system is the top-left-front point which is `(-1, 1,-1)` in NDC coordinates. Since we want our coordinates to be in the range `(0, x)` we translate all vertices in every axis by 1. This moves the origin of the next coordinate system to `(-1,-1,-1)` in our current intermediate system:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 1 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now the values are in the range `(0, 2)` and the current coordinate systems' origin is at the NDC coordinates `(-1, 1,-1)`.&#xD;&#xA;&#xD;&#xA;If you multiply both matrices you would get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; -1 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 1 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;All that is left now is to apply the correct scaling. So we need to divide by 2 in every direction and multiply by the corresponding maximum value:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;width/2 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; height/2 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; depth/2 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So the final result would be:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x' \\&#xD;&#xA;y' \\&#xD;&#xA;z' \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;width/2 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; height/2 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; depth/2 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; -1 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 1 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If you multiply it, you will get the same transformation matrix as above" ContentLicense="CC BY-SA 4.0" />
  <row Id="37328" PostHistoryTypeId="5" PostId="12736" RevisionGUID="0f0d064c-d7af-4746-ab59-d27ffde0d1b2" CreationDate="2022-06-03T11:26:24.787" UserId="13095" Comment="Fix some grammar and spelling" Text="I have a set of vertexes (x, y, z) in normalized device coordinates. Its x, y, and z values are in the range (-1, 1). Normalized device coordinates use the left-handed coordinate system, as shown below&#xD;&#xA;&#xD;&#xA;[![ndc][1]][1]&#xD;&#xA;&#xD;&#xA;I want to convert NDC vertexes into a viewport whose coordinate system looks like this&#xD;&#xA;&#xD;&#xA;[![vp][2]][2]&#xD;&#xA;&#xD;&#xA;It is a standard coordinate system used by most 2D graphics libraries. x starts from the top left corner and goes to the right while y starts from the same corner and goes down. I decided to make z to go into the page. All NDC vertexes must fit inside the dotted rectangular box, shown above.&#xD;&#xA;&#xD;&#xA;What is the set of transformation matrixes that converts NDC coordinates $(x, y, z, 1)$ (note that I am using homogenous coordinates here) to viewport coordinates $(x', y', z', 1)$?&#xD;&#xA;&#xD;&#xA;This is what I came up with&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x' \\&#xD;&#xA;y' \\&#xD;&#xA;z' \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix} =&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 &amp; width/2 \\&#xD;&#xA;0 &amp; 1 &amp; 0 &amp; height/2 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;width/2 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; -height/2 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z \\&#xD;&#xA;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $width$ and $height$ are width and height of viewport. I first scale vertexes to viewport width and height and also flip the y coordinate (notice the minus sign). Then I translate the resulting vertex to fit into the viewport. But I'm not sure if my viewport transformation matrix is correct because I think the resulting z value might be wrong. What should I change here?&#xD;&#xA;&#xD;&#xA;—————-&#xD;&#xA;&#xD;&#xA;Crossposted in [math.stackexchange](https://math.stackexchange.com/questions/4461572/what-are-viewport-transformation-matrixes-for-this-coordinate-system).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fTZhO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DNW3E.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37329" PostHistoryTypeId="2" PostId="12746" RevisionGUID="bfca8c1e-e316-41ee-96f9-0aca27d1a8e4" CreationDate="2022-06-03T17:45:37.987" UserId="18064" Text="I am reading the book **An introduction to raytracing by Eric Haines** and it mentions an algorithm to map a point from a sphere into a UV plane, it calls it **Inverse Spherical Mapping** (page 49). I googled a lot about this term and could not find a single piece of information regarding it.&#xD;&#xA; &#xD;&#xA;Given the normal to a point on a sphere (**Sn**) and the sphere's north pole unit vector (**Sp**) and a unit vector from the sphere's origin to the sphere's equator (**Se**) as shown below&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Using the right-hand coordinates system. It drives the following formula for v and u&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I understand the **Dot product** yields **cosine** of an angle between two vectors, but why **-Sn**? from the picture **v** starts from the south pole and varies towards the north, but why the **minus sign**? (the book mentions **v** varies from **-Sp** to **+Sp** )&#xD;&#xA;&#xD;&#xA;As for **u** I am not sure why we do divide by **sine phi**. and why do we take the cross product to determine **u**? (I know the **cross-product** gives us a perpendicular vector to both, which is probably used to know on which side the normal is, but I am not sure exactly how that worked as the **equator** is changing, so it can be both right and left) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MJJ7u.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ysmyP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37331" PostHistoryTypeId="1" PostId="12746" RevisionGUID="bfca8c1e-e316-41ee-96f9-0aca27d1a8e4" CreationDate="2022-06-03T17:45:37.987" UserId="18064" Text="mapping of a point from a sphere into UV plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="37332" PostHistoryTypeId="3" PostId="12746" RevisionGUID="bfca8c1e-e316-41ee-96f9-0aca27d1a8e4" CreationDate="2022-06-03T17:45:37.987" UserId="18064" Text="|raytracing|projections|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37333" PostHistoryTypeId="2" PostId="12747" RevisionGUID="33068f3c-08e6-4f66-ada5-c29f4d3d7432" CreationDate="2022-06-03T19:30:30.400" UserId="445" Text="It looks like most of the errors in your image are due to the lack of one critical property. That is that, for any _edge_ (two out of three vertices of a triangle), **the rasterization algorithm must have a consistent opinion on which side of the line each pixel falls on, even for different triangles, if those triangles share an edge** (have the same vertex coordinates for 2 vertices).&#xD;&#xA;&#xD;&#xA;For example, on the blue face, you have two triangles forming the surface. There are visible gaps, which indicate that the two blue triangles are not meeting perfectly at the edge, which happens because the two rasterizations are not agreeing on which triangle is responsible for filling a given pixel — there's probably some overlap (which is invisible) in addition to the gaps.&#xD;&#xA;&#xD;&#xA;Fixing this should also help with the yellow edge on the right and the wiggliness of the red-green edge.&#xD;&#xA;&#xD;&#xA;(I do not have any advice on how to implement this property in rasterization, as I haven't dealt with triangle-based software rendering myself; I just know it's necessary.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Additionally, you should implement “back-face culling”: do not draw a triangle if it is facing away from the viewer. Facing is usually defined by triangle “winding order”, clockwise or counterclockwise; one way to understand this is that you take the first two vertices of the triangle as a line with a direction (in screen space), and ask whether the third vertex is to the left (CCW order) or the right (CW order) of that line. That turns out to be equivalent to asking which face of the triangle is being viewed; you pick one such face to not draw, and make sure your mesh's vertex ordering matches that choice consistently.&#xD;&#xA;&#xD;&#xA;I'd recommend fixing your rasterization first, because implementing back-face culling will hide some of the problems. But culling will give you a big speedup since you can stop rendering half of the triangles in the scene (typically)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37338" PostHistoryTypeId="50" PostId="12143" RevisionGUID="8c84f745-df6b-4e9d-b704-e78635d4f24b" CreationDate="2022-06-04T12:05:15.503" UserId="-1" />
  <row Id="37339" PostHistoryTypeId="5" PostId="12747" RevisionGUID="0c7bae7e-956a-459a-b552-b413fbd14f83" CreationDate="2022-06-04T13:58:50.507" UserId="445" Comment="added 84 characters in body" Text="It looks like most of the errors in your image are due to the lack of one critical property. That is that, for any _edge_ (two out of three vertices of a triangle), **the rasterization algorithm must have a consistent opinion on which side of the line each pixel falls on, even for different triangles, if those triangles share an edge** (have the same vertex coordinates for 2 vertices).&#xD;&#xA;&#xD;&#xA;For example, on the blue face, you have two triangles forming the surface. There are visible gaps, which indicate that the two blue triangles are not meeting perfectly at the edge, which happens because the two rasterizations are not agreeing on which triangle is responsible for filling a given pixel — there's probably some overlap (which is invisible) in addition to the gaps.&#xD;&#xA;&#xD;&#xA;Fixing this should also help with the yellow edge on the right and the wiggliness of the red-green edge.&#xD;&#xA;&#xD;&#xA;(I do not have any advice on how to implement this property in rasterization, as I haven't dealt with triangle-based software rendering myself; I just know it's necessary.)&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Additionally, you should implement “back-face culling”: do not draw a triangle if it is facing away from the viewer. Facing is usually defined by triangle “winding order”, clockwise or counterclockwise; one way to understand this is that you take the first two vertices of the triangle as a line with a direction (in screen space), and ask whether the third vertex is to the left (CCW order) or the right (CW order) of that line. That turns out to be equivalent to asking which face of the triangle is being viewed; you pick one such face to not draw, and make sure your mesh's vertex ordering matches that choice consistently.&#xD;&#xA;&#xD;&#xA;When you have done this properly, the yellow back-face will not be drawn at all.&#xD;&#xA;&#xD;&#xA;I'd recommend fixing your rasterization first, because implementing back-face culling will hide some of the problems. But culling will give you a big speedup since you can stop rendering half of the triangles in the scene (typically)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37343" PostHistoryTypeId="33" PostId="12744" RevisionGUID="86d1b25c-fd3c-4899-96a1-f50be19d21c2" CreationDate="2022-06-05T14:34:09.690" UserId="18487" Comment="78" />
  <row Id="37344" PostHistoryTypeId="2" PostId="12749" RevisionGUID="1a3c4be6-a574-4449-b32f-bd46d3ea382b" CreationDate="2022-06-05T16:05:42.837" UserId="18064" Text="I found the answer, someone pointed me to the spherical coordinates system and it is the exact match. [as shown here][1]&#xD;&#xA;The only difference is that, this assumes **phi** is actually calculated from the z-axis towards xy-plane, however in the picture I shared in the question **V** varies from south pole to north pole, for that we take the negative of the north pole in V calculation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://tutorial.math.lamar.edu/Classes/CalcIII/TISphericalCoords.aspx" ContentLicense="CC BY-SA 4.0" />
  <row Id="37346" PostHistoryTypeId="2" PostId="12750" RevisionGUID="d4735ed5-9802-4bdc-b5ed-0e3d96422ecf" CreationDate="2022-06-06T01:34:51.487" UserId="482" Text="*This answer intends to flesh out joojaa's comment to a more complete answer.*&#xD;&#xA;&#xD;&#xA;It's possible. But probably not easy.&#xD;&#xA;&#xD;&#xA;If you work with the EPS file, it's very likely to be ASCII or mostly ASCII so you can open it and edit with a text editor. Then you've got some obvious subtasks:&#xD;&#xA;&#xD;&#xA;1. locate the points in the file&#xD;&#xA;2. filter them somehow&#xD;&#xA;&#xD;&#xA;To locate the points, it's all going to depend on exactly how the ggplot2 chooses to encode the points. They may be just decimal numbers or they may be something else. Level 2 PostScript added support for several kinds of binary encoding and binary tokens.&#xD;&#xA;&#xD;&#xA;To filter the points. There are a few routes I can imagine, but I'm not sure which will come out easiest--or least challenging. You could modify the EPS program to not call any of the drawing operators, but just dump &quot;surviving&quot; points to a file or stdout with the `=` or `print` or `writestring` operators. *Then*, add a step which calls `clip` to determine if a point is &quot;surviving&quot; or maybe the `infill` would be useful for this. One issue is that in order &quot;draw a point&quot; in PostScript you really have to draw some other shape like a circle or rectangle. So when the program gets to the drawing phase, the point may no longer exist as just coordinates but a whole sequence of lines or curves which describe the actual shape being drawn. So far, all of these options involve modifying the PostScript code to steer or wrangle the points through a sieve instead of onto a display. If you get the code just right, then it should produce a small list of points which you can then edit back into the original EPS file.&#xD;&#xA;&#xD;&#xA;Another option would be to write a much smaller PostScript program that just sets up the appropriate clip path (or just a regular path to use `infill`) and output the points. Then you could copy/paste the points out of the original, run them through this smaller, simpler sieve, and then paste them back in to the original.&#xD;&#xA;&#xD;&#xA;Most of these steps could be done in some other, more convenient programming language assuming you can accomplish subtask 1 and find the points in the file to begin with.&#xD;&#xA;&#xD;&#xA;In contrast, working with the PDF could provide some advantages, as well as some disadvantages. To start with, we're no longer in nice clean ASCII land. PDFs may contain a lot of just plain ASCII but there's a lot of binary as well (possibly a whole lot). PDF is not a programming language, just a flat data representation. *But* it's a flat data representation of *printed output*. So we may hit some of the same issues as working with PostScript, viz. the points may or may not exist in the file as just coordinates. &#xD;&#xA;&#xD;&#xA;You might try passing the PDF through a tool like `qpdf` to get a readable ASCII file that can be edited and converted back to PDF. &#xD;&#xA;&#xD;&#xA;After (some of) the above is done and working for a single file, you then will have the further task of automating the solution to run on multiple files. And depending on the details, that may make your process dependent on the details of gglot2's current behavior which may or may not be fully documented. At least if it depends upon the EPS being produced the same way forever into the future, that feels like a risky move.&#xD;&#xA;&#xD;&#xA;I don't know much about R, but at the spot in the R code where you call ggplot2 to produce the output, like, you've *got* the points right there, right? I don't know what tools R has available for insideness testing, but for an axis-aligned box it ought to be pretty simple to code a function( x&gt;min_x &amp;&amp; x&lt;max_x &amp;&amp; y&gt;min_y &amp;&amp; y&lt;max_y ). If they're gone before they get to ggplot2, then it will have no opportunity to include them in the output." ContentLicense="CC BY-SA 4.0" />
  <row Id="37348" PostHistoryTypeId="5" PostId="12750" RevisionGUID="e3a82b80-a2ec-40be-a5dc-f5646b8ff412" CreationDate="2022-06-06T02:11:51.830" UserId="482" Comment="deleted 3 characters in body" Text="*This answer intends to flesh out joojaa's comment to a more complete answer.*&#xD;&#xA;&#xD;&#xA;It's possible. But probably not easy.&#xD;&#xA;&#xD;&#xA;If you work with the EPS file, it's very likely to be ASCII or mostly ASCII so you can open it and edit with a text editor. Then you've got some obvious subtasks:&#xD;&#xA;&#xD;&#xA;1. locate the points in the file&#xD;&#xA;2. filter them somehow&#xD;&#xA;&#xD;&#xA;To locate the points, it's all going to depend on exactly how the ggplot2 chooses to encode the points. They may be just decimal numbers or they may be something else. Level 2 PostScript added support for several kinds of binary encoding and binary tokens.&#xD;&#xA;&#xD;&#xA;To filter the points. There are a few routes I can imagine, but I'm not sure which will come out easiest--or least challenging. You could modify the EPS program to not call any of the drawing operators, but just dump &quot;surviving&quot; points to a file or stdout with the `=` or `print` or `writestring` operators. *Then*, add a step which calls `clip` to determine if a point is &quot;surviving&quot; or maybe the `infill` would be useful for this. One issue is that in order &quot;draw a point&quot; in PostScript you really have to draw some other shape like a circle or rectangle. So when the program gets to the drawing phase, the point may no longer exist as just coordinates but a whole sequence of lines or curves which describe the actual shape being drawn. So far, all of these options involve modifying the PostScript code to steer or wrangle the points through a sieve instead of onto a display. If you get the code just right, then it should produce a small list of points which you can then edit back into the original EPS file.&#xD;&#xA;&#xD;&#xA;Another option would be to write a much smaller PostScript program that just sets up the appropriate clip path (or just a regular path to use `infill`) and output the points. Then you could copy/paste the points out of the original, run them through this smaller, simpler sieve, and then paste them back in to the original.&#xD;&#xA;&#xD;&#xA;Most of these steps could be done in some other, more convenient programming language assuming you can accomplish subtask 1 and find the points in the file to begin with.&#xD;&#xA;&#xD;&#xA;In contrast, working with the PDF could provide some advantages, as well as some disadvantages. To start with, we're no longer in nice clean ASCII land. PDFs may contain a lot of just plain ASCII but there's a lot of binary as well (possibly a whole lot). PDF is not a programming language, just a flat data representation. *But* it's a flat data representation of *printed output*. So we may hit some of the same issues as working with PostScript, viz. the points may or may not exist in the file as just coordinates. &#xD;&#xA;&#xD;&#xA;You might try passing the PDF through a tool like `qpdf` to get a readable ASCII file that can be edited and converted back to PDF. &#xD;&#xA;&#xD;&#xA;After (some of) the above is done and working for a single file, you then will have the further task of automating the solution to run on multiple files. And depending on the details, that may make your process dependent on the details of gglot2's current behavior which may or may not be fully documented. At least if it depends upon the EPS being produced the same way forever into the future, that feels like a risky move.&#xD;&#xA;&#xD;&#xA;I don't know much about R, but at the spot in the R code where you call ggplot2 to produce the output, like, you've *got* the points right there, right? I don't know what tools R has available for insideness testing, but for an axis-aligned box it ought to be pretty simple to code a function ( x&gt;LL_x &amp;&amp; x&lt;UR_x &amp;&amp; y&gt;LL_y &amp;&amp; y&lt;UR_y ). If they're gone before they get to ggplot2, then it will have no opportunity to include them in the output." ContentLicense="CC BY-SA 4.0" />
  <row Id="37353" PostHistoryTypeId="2" PostId="12752" RevisionGUID="462237c7-68b7-438c-8db0-6c8ca5dd911d" CreationDate="2022-06-07T08:17:23.217" UserId="18304" Text="I want to render on two windows. What are some stuffs that I should share, and what stuffs should I separate? I have a rendering program in Vulkan and want to add a window to it. It seems that I need two sets of MVP matrices and camera positions, both of which I already put in one uniform struct. I would imagine that I need to create a new instance of window and camera, but do I need another pipeline for this? how about command buffers? The data input is exactly the same for the two windows. I think all the uniforms and vertex data are the same except MVP matrices and camera positions. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37355" PostHistoryTypeId="1" PostId="12752" RevisionGUID="462237c7-68b7-438c-8db0-6c8ca5dd911d" CreationDate="2022-06-07T08:17:23.217" UserId="18304" Text="rendering in two windows" ContentLicense="CC BY-SA 4.0" />
  <row Id="37356" PostHistoryTypeId="3" PostId="12752" RevisionGUID="462237c7-68b7-438c-8db0-6c8ca5dd911d" CreationDate="2022-06-07T08:17:23.217" UserId="18304" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37362" PostHistoryTypeId="5" PostId="12750" RevisionGUID="ba182cd1-bf33-4273-9851-4c8f308d2c88" CreationDate="2022-06-07T12:43:31.220" UserId="482" Comment="add some code for a similar task" Text="*This answer intends to flesh out joojaa's comment to a more complete answer.*&#xD;&#xA;&#xD;&#xA;It's possible. But probably not easy.&#xD;&#xA;&#xD;&#xA;If you work with the EPS file, it's very likely to be ASCII or mostly ASCII so you can open it and edit with a text editor. Then you've got some obvious subtasks:&#xD;&#xA;&#xD;&#xA;1. locate the points in the file&#xD;&#xA;2. filter them somehow&#xD;&#xA;&#xD;&#xA;To locate the points, it's all going to depend on exactly how the ggplot2 chooses to encode the points. They may be just decimal numbers or they may be something else. Level 2 PostScript added support for several kinds of binary encoding and binary tokens.&#xD;&#xA;&#xD;&#xA;To filter the points. There are a few routes I can imagine, but I'm not sure which will come out easiest--or least challenging. You could modify the EPS program to not call any of the drawing operators, but just dump &quot;surviving&quot; points to a file or stdout with the `=` or `print` or `writestring` operators. *Then*, add a step which calls `clip` to determine if a point is &quot;surviving&quot; or maybe the `infill` would be useful for this. One issue is that in order &quot;draw a point&quot; in PostScript you really have to draw some other shape like a circle or rectangle. So when the program gets to the drawing phase, the point may no longer exist as just coordinates but a whole sequence of lines or curves which describe the actual shape being drawn. So far, all of these options involve modifying the PostScript code to steer or wrangle the points through a sieve instead of onto a display. If you get the code just right, then it should produce a small list of points which you can then edit back into the original EPS file.&#xD;&#xA;&#xD;&#xA;Another option would be to write a much smaller PostScript program that just sets up the appropriate clip path (or just a regular path to use `infill`) and output the points. Then you could copy/paste the points out of the original, run them through this smaller, simpler sieve, and then paste them back in to the original.&#xD;&#xA;&#xD;&#xA;Most of these steps could be done in some other, more convenient programming language assuming you can accomplish subtask 1 and find the points in the file to begin with.&#xD;&#xA;&#xD;&#xA;In contrast, working with the PDF could provide some advantages, as well as some disadvantages. To start with, we're no longer in nice clean ASCII land. PDFs may contain a lot of just plain ASCII but there's a lot of binary as well (possibly a whole lot). PDF is not a programming language, just a flat data representation. *But* it's a flat data representation of *printed output*. So we may hit some of the same issues as working with PostScript, viz. the points may or may not exist in the file as just coordinates. &#xD;&#xA;&#xD;&#xA;You might try passing the PDF through a tool like `qpdf` to get a readable ASCII file that can be edited and converted back to PDF. &#xD;&#xA;&#xD;&#xA;After (some of) the above is done and working for a single file, you then will have the further task of automating the solution to run on multiple files. And depending on the details, that may make your process dependent on the details of gglot2's current behavior which may or may not be fully documented. At least if it depends upon the EPS being produced the same way forever into the future, that feels like a risky move.&#xD;&#xA;&#xD;&#xA;I don't know much about R, but at the spot in the R code where you call ggplot2 to produce the output, like, you've *got* the points right there, right? I don't know what tools R has available for insideness testing, but for an axis-aligned box it ought to be pretty simple to code a function ( x&gt;LL_x &amp;&amp; x&lt;UR_x &amp;&amp; y&gt;LL_y &amp;&amp; y&lt;UR_y ). If they're gone before they get to ggplot2, then it will have no opportunity to include them in the output.&#xD;&#xA;&#xD;&#xA;*Edit*&#xD;&#xA;&#xD;&#xA;The closest existing PS code that I know of was from a prototype program to visualize a Steinmetz solid. This was [posted to usenet in 2012](https://groups.google.com/g/comp.lang.postscript/c/DXfU2xrRCxY/m/ocELBfAvhxUJ). It generates points with an O(n^3) algorithm but then saves the results in a file so it can alter the view without doing the generating step each time. So, it shows one way of passing points through a sieve (the function `x y z f -&gt; bool`) and saving them in a separate file.&#xD;&#xA;&#xD;&#xA;    %!&#xD;&#xA;    % Point-field sampling&#xD;&#xA;    % with data caching (in a file),&#xD;&#xA;    % point-wise axial rotations,&#xD;&#xA;    % and perspective projection.&#xD;&#xA;    &#xD;&#xA;    /fuzz 10000 def %the &quot;grain&quot; of eq&#xD;&#xA;    /oldeq /eq load def&#xD;&#xA;    /eq {&#xD;&#xA;        fuzz mul round exch fuzz mul round oldeq&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    /max {&#xD;&#xA;        2 copy lt { exch } if pop&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    %x y z  f  bool&#xD;&#xA;    /f {&#xD;&#xA;        dup mul 3 1 roll    %z^2 x y&#xD;&#xA;        dup mul 3 1 roll    %y^2 z^2 x&#xD;&#xA;        dup mul 3 1 roll    %x^2 y^2 z^2&#xD;&#xA;        2 index 2 index add %x^2 y^2 z^2  x^2+y^2&#xD;&#xA;        3 index 2 index add %x^2 y^2 z^2  x^2+y^2  x^2+z^2&#xD;&#xA;        3 index 3 index add %x^2 y^2 z^2  x^2+y^2  x^2+z^2  y^2+z^2&#xD;&#xA;        max                 %x^2 y^2 z^2  x^2+y^2  max(x^2+z^2,y^2+z^2)&#xD;&#xA;        max                 %x^2 y^2 z^2  max(x^2+y^2, max(x^2+z^2,y^2+z^2))&#xD;&#xA;        4 1 roll pop pop pop %max(...)&#xD;&#xA;        4 eq&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    /filename (stein.pts) def&#xD;&#xA;    &#xD;&#xA;    /low -2.2 def&#xD;&#xA;    /hi 2.2 def&#xD;&#xA;    &#xD;&#xA;    %generate data by brute force, cache in file, plot&#xD;&#xA;    /pointfieldtocache {&#xD;&#xA;        /res exch def&#xD;&#xA;        /dt 1 res div def&#xD;&#xA;        /fuzz res .5 mul def&#xD;&#xA;            %fuzz affects the &quot;closeness&quot; of&#xD;&#xA;            %the equality test. a lower fuzz will allow more&#xD;&#xA;            %values to be equal.&#xD;&#xA;            % 'res' gives thin lines&#xD;&#xA;            % 'res .5 mul' gives wider &quot;ribbons&quot;&#xD;&#xA;    &#xD;&#xA;    /outfile filename (w) file def&#xD;&#xA;    /outbuf 128 string def&#xD;&#xA;        low dt hi {&#xD;&#xA;            low dt hi {&#xD;&#xA;                low dt hi { % xW yW zW &quot;world&quot; coords&#xD;&#xA;                    3 copy f {&#xD;&#xA;                        3 copy 3 -1 1 { -1 roll&#xD;&#xA;                            outbuf cvs outfile exch writestring&#xD;&#xA;                            outfile (\n) writestring&#xD;&#xA;                        } for %dump points to file&#xD;&#xA;                        3 copy project&#xD;&#xA;                        %2 copy exch = =&#xD;&#xA;                        %2 copy transform exch = =  ()=&#xD;&#xA;                        2 copy 2 copy moveto dt .5 mul 0 360 arc moveto&#xD;&#xA;                        fill&#xD;&#xA;                        /flushpage where {pop flushpage} if&#xD;&#xA;                    } if&#xD;&#xA;                    pop&#xD;&#xA;                } for&#xD;&#xA;                pop&#xD;&#xA;            } for&#xD;&#xA;            pop&#xD;&#xA;        } for&#xD;&#xA;    outfile closefile&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    %plot cached data from file&#xD;&#xA;    /pointfieldfromcache {&#xD;&#xA;        /res exch def&#xD;&#xA;        /dt 1 res div def&#xD;&#xA;        /infile filename (r) file def&#xD;&#xA;        /it 1 def&#xD;&#xA;            %cvx exec&#xD;&#xA;        %count 3 idiv {&#xD;&#xA;    &#xD;&#xA;        {&#xD;&#xA;            {&#xD;&#xA;                /it it 1 add def&#xD;&#xA;                infile token not {stop} if % bail-out&#xD;&#xA;                infile token not {stop} if % on any datafile issues&#xD;&#xA;                infile token not {stop} if&#xD;&#xA;                        %3 copy&#xD;&#xA;                        project&#xD;&#xA;                        2 copy 2 copy moveto dt .5 mul 0 360 arc moveto&#xD;&#xA;                it res mod 0 oldeq {&#xD;&#xA;                    fill /flushpage where {pop flushpage} if&#xD;&#xA;                } if&#xD;&#xA;            } loop&#xD;&#xA;        } stopped pop&#xD;&#xA;        %} repeat&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    /pointfield { %check if there's a readable data file&#xD;&#xA;        { filename (r) file closefile } stopped not&#xD;&#xA;        //pointfieldfromcache %yes! read it.&#xD;&#xA;        { pop pop pointfieldtocache } ifelse %no! make one.&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % x y z ang -&gt; x y' z'&#xD;&#xA;    /rotx {&#xD;&#xA;        /theta exch def&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        y theta cos mul&#xD;&#xA;        z theta sin mul sub&#xD;&#xA;        y theta sin mul&#xD;&#xA;        z theta cos mul add&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % x y z ang -&gt; x' y z'&#xD;&#xA;    /roty {&#xD;&#xA;        /theta exch def&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        /x exch def&#xD;&#xA;        x theta cos mul&#xD;&#xA;        z theta sin mul add&#xD;&#xA;        y&#xD;&#xA;        x theta sin mul neg&#xD;&#xA;        z theta cos mul add&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % x y z ang -&gt; x' y' z&#xD;&#xA;    /rotz {&#xD;&#xA;        /theta exch def&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        /x exch def&#xD;&#xA;        x theta cos mul&#xD;&#xA;        y theta sin mul sub&#xD;&#xA;        x theta sin mul&#xD;&#xA;        y theta cos mul add&#xD;&#xA;        z&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % Eye coords&#xD;&#xA;    /ex .2 def %a little x-y skew adds &quot;drama&quot;&#xD;&#xA;    /ey .2 def&#xD;&#xA;    /ez 5 def&#xD;&#xA;    &#xD;&#xA;    % x y z -&gt; X Y&#xD;&#xA;    /project {&#xD;&#xA;    ang roty&#xD;&#xA;    ang .25 mul rotx&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        /x exch def&#xD;&#xA;        1 ez z sub div&#xD;&#xA;        &#xD;&#xA;    x ez mul z ex mul sub&#xD;&#xA;        1 index mul&#xD;&#xA;        y ez mul z ey mul sub&#xD;&#xA;        3 2 roll mul&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    10 10 360 {&#xD;&#xA;        /ang exch def&#xD;&#xA;        %matrix currentmatrix&#xD;&#xA;        300 400 translate&#xD;&#xA;        100 100 scale&#xD;&#xA;        60 pointfield&#xD;&#xA;        %setmatrix fill&#xD;&#xA;        /flushpage where {pop flushpage} if&#xD;&#xA;        showpage&#xD;&#xA;    } for&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37363" PostHistoryTypeId="5" PostId="12750" RevisionGUID="f40f96dc-b6fb-473e-901c-782e87329137" CreationDate="2022-06-07T12:54:47.067" UserId="482" Comment="added 141 characters in body" Text="*This answer intends to flesh out joojaa's comment to a more complete answer.*&#xD;&#xA;&#xD;&#xA;It's possible. But probably not easy.&#xD;&#xA;&#xD;&#xA;If you work with the EPS file, it's very likely to be ASCII or mostly ASCII so you can open it and edit with a text editor. Then you've got some obvious subtasks:&#xD;&#xA;&#xD;&#xA;1. locate the points in the file&#xD;&#xA;2. filter them somehow&#xD;&#xA;&#xD;&#xA;To locate the points, it's all going to depend on exactly how the ggplot2 chooses to encode the points. They may be just decimal numbers or they may be something else. Level 2 PostScript added support for several kinds of binary encoding and binary tokens.&#xD;&#xA;&#xD;&#xA;To filter the points. There are a few routes I can imagine, but I'm not sure which will come out easiest--or least challenging. You could modify the EPS program to not call any of the drawing operators, but just dump &quot;surviving&quot; points to a file or stdout with the `=` or `print` or `writestring` operators. *Then*, add a step which calls `clip` to determine if a point is &quot;surviving&quot; or maybe the `infill` would be useful for this. One issue is that in order &quot;draw a point&quot; in PostScript you really have to draw some other shape like a circle or rectangle. So when the program gets to the drawing phase, the point may no longer exist as just coordinates but a whole sequence of lines or curves which describe the actual shape being drawn. So far, all of these options involve modifying the PostScript code to steer or wrangle the points through a sieve instead of onto a display. If you get the code just right, then it should produce a small list of points which you can then edit back into the original EPS file.&#xD;&#xA;&#xD;&#xA;Another option would be to write a much smaller PostScript program that just sets up the appropriate clip path (or just a regular path to use `infill`) and output the points. Then you could copy/paste the points out of the original, run them through this smaller, simpler sieve, and then paste them back in to the original.&#xD;&#xA;&#xD;&#xA;Most of these steps could be done in some other, more convenient programming language assuming you can accomplish subtask 1 and find the points in the file to begin with.&#xD;&#xA;&#xD;&#xA;In contrast, working with the PDF could provide some advantages, as well as some disadvantages. To start with, we're no longer in nice clean ASCII land. PDFs may contain a lot of just plain ASCII but there's a lot of binary as well (possibly a whole lot). PDF is not a programming language, just a flat data representation. *But* it's a flat data representation of *printed output*. So we may hit some of the same issues as working with PostScript, viz. the points may or may not exist in the file as just coordinates. &#xD;&#xA;&#xD;&#xA;You might try passing the PDF through a tool like `qpdf` to get a readable ASCII file that can be edited and converted back to PDF. &#xD;&#xA;&#xD;&#xA;After (some of) the above is done and working for a single file, you then will have the further task of automating the solution to run on multiple files. And depending on the details, that may make your process dependent on the details of gglot2's current behavior which may or may not be fully documented. At least if it depends upon the EPS being produced the same way forever into the future, that feels like a risky move.&#xD;&#xA;&#xD;&#xA;I don't know much about R, but at the spot in the R code where you call ggplot2 to produce the output, like, you've *got* the points right there, right? I don't know what tools R has available for insideness testing, but for an axis-aligned box it ought to be pretty simple to code a function ( x&gt;LL_x &amp;&amp; x&lt;UR_x &amp;&amp; y&gt;LL_y &amp;&amp; y&lt;UR_y ). If they're gone before they get to ggplot2, then it will have no opportunity to include them in the output.&#xD;&#xA;&#xD;&#xA;*Edit*&#xD;&#xA;&#xD;&#xA;The closest existing PS code that I know of was from a prototype program to visualize a Steinmetz solid. This was [posted to usenet in 2012](https://groups.google.com/g/comp.lang.postscript/c/DXfU2xrRCxY/m/ocELBfAvhxUJ) (note: if you add custom CSS `html-blob{white-space:pre}html-blob br{display:none}`, you can view the original indentation in Google groups). It generates points with an O(n^3) algorithm but then saves the results in a file so it can alter the view without doing the generating step each time. So, it shows one way of passing points through a sieve (the function `x y z f -&gt; bool`) and saving them in a separate file.&#xD;&#xA;&#xD;&#xA;    %!&#xD;&#xA;    % Point-field sampling&#xD;&#xA;    % with data caching (in a file),&#xD;&#xA;    % point-wise axial rotations,&#xD;&#xA;    % and perspective projection.&#xD;&#xA;    &#xD;&#xA;    /fuzz 10000 def %the &quot;grain&quot; of eq&#xD;&#xA;    /oldeq /eq load def&#xD;&#xA;    /eq {&#xD;&#xA;        fuzz mul round exch fuzz mul round oldeq&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    /max {&#xD;&#xA;        2 copy lt { exch } if pop&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    %x y z  f  bool&#xD;&#xA;    /f {&#xD;&#xA;        dup mul 3 1 roll    %z^2 x y&#xD;&#xA;        dup mul 3 1 roll    %y^2 z^2 x&#xD;&#xA;        dup mul 3 1 roll    %x^2 y^2 z^2&#xD;&#xA;        2 index 2 index add %x^2 y^2 z^2  x^2+y^2&#xD;&#xA;        3 index 2 index add %x^2 y^2 z^2  x^2+y^2  x^2+z^2&#xD;&#xA;        3 index 3 index add %x^2 y^2 z^2  x^2+y^2  x^2+z^2  y^2+z^2&#xD;&#xA;        max                 %x^2 y^2 z^2  x^2+y^2  max(x^2+z^2,y^2+z^2)&#xD;&#xA;        max                 %x^2 y^2 z^2  max(x^2+y^2, max(x^2+z^2,y^2+z^2))&#xD;&#xA;        4 1 roll pop pop pop %max(...)&#xD;&#xA;        4 eq&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    /filename (stein.pts) def&#xD;&#xA;    &#xD;&#xA;    /low -2.2 def&#xD;&#xA;    /hi 2.2 def&#xD;&#xA;    &#xD;&#xA;    %generate data by brute force, cache in file, plot&#xD;&#xA;    /pointfieldtocache {&#xD;&#xA;        /res exch def&#xD;&#xA;        /dt 1 res div def&#xD;&#xA;        /fuzz res .5 mul def&#xD;&#xA;            %fuzz affects the &quot;closeness&quot; of&#xD;&#xA;            %the equality test. a lower fuzz will allow more&#xD;&#xA;            %values to be equal.&#xD;&#xA;            % 'res' gives thin lines&#xD;&#xA;            % 'res .5 mul' gives wider &quot;ribbons&quot;&#xD;&#xA;    &#xD;&#xA;    /outfile filename (w) file def&#xD;&#xA;    /outbuf 128 string def&#xD;&#xA;        low dt hi {&#xD;&#xA;            low dt hi {&#xD;&#xA;                low dt hi { % xW yW zW &quot;world&quot; coords&#xD;&#xA;                    3 copy f {&#xD;&#xA;                        3 copy 3 -1 1 { -1 roll&#xD;&#xA;                            outbuf cvs outfile exch writestring&#xD;&#xA;                            outfile (\n) writestring&#xD;&#xA;                        } for %dump points to file&#xD;&#xA;                        3 copy project&#xD;&#xA;                        %2 copy exch = =&#xD;&#xA;                        %2 copy transform exch = =  ()=&#xD;&#xA;                        2 copy 2 copy moveto dt .5 mul 0 360 arc moveto&#xD;&#xA;                        fill&#xD;&#xA;                        /flushpage where {pop flushpage} if&#xD;&#xA;                    } if&#xD;&#xA;                    pop&#xD;&#xA;                } for&#xD;&#xA;                pop&#xD;&#xA;            } for&#xD;&#xA;            pop&#xD;&#xA;        } for&#xD;&#xA;    outfile closefile&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    %plot cached data from file&#xD;&#xA;    /pointfieldfromcache {&#xD;&#xA;        /res exch def&#xD;&#xA;        /dt 1 res div def&#xD;&#xA;        /infile filename (r) file def&#xD;&#xA;        /it 1 def&#xD;&#xA;            %cvx exec&#xD;&#xA;        %count 3 idiv {&#xD;&#xA;    &#xD;&#xA;        {&#xD;&#xA;            {&#xD;&#xA;                /it it 1 add def&#xD;&#xA;                infile token not {stop} if % bail-out&#xD;&#xA;                infile token not {stop} if % on any datafile issues&#xD;&#xA;                infile token not {stop} if&#xD;&#xA;                        %3 copy&#xD;&#xA;                        project&#xD;&#xA;                        2 copy 2 copy moveto dt .5 mul 0 360 arc moveto&#xD;&#xA;                it res mod 0 oldeq {&#xD;&#xA;                    fill /flushpage where {pop flushpage} if&#xD;&#xA;                } if&#xD;&#xA;            } loop&#xD;&#xA;        } stopped pop&#xD;&#xA;        %} repeat&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    /pointfield { %check if there's a readable data file&#xD;&#xA;        { filename (r) file closefile } stopped not&#xD;&#xA;        //pointfieldfromcache %yes! read it.&#xD;&#xA;        { pop pop pointfieldtocache } ifelse %no! make one.&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % x y z ang -&gt; x y' z'&#xD;&#xA;    /rotx {&#xD;&#xA;        /theta exch def&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        y theta cos mul&#xD;&#xA;        z theta sin mul sub&#xD;&#xA;        y theta sin mul&#xD;&#xA;        z theta cos mul add&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % x y z ang -&gt; x' y z'&#xD;&#xA;    /roty {&#xD;&#xA;        /theta exch def&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        /x exch def&#xD;&#xA;        x theta cos mul&#xD;&#xA;        z theta sin mul add&#xD;&#xA;        y&#xD;&#xA;        x theta sin mul neg&#xD;&#xA;        z theta cos mul add&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % x y z ang -&gt; x' y' z&#xD;&#xA;    /rotz {&#xD;&#xA;        /theta exch def&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        /x exch def&#xD;&#xA;        x theta cos mul&#xD;&#xA;        y theta sin mul sub&#xD;&#xA;        x theta sin mul&#xD;&#xA;        y theta cos mul add&#xD;&#xA;        z&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    % Eye coords&#xD;&#xA;    /ex .2 def %a little x-y skew adds &quot;drama&quot;&#xD;&#xA;    /ey .2 def&#xD;&#xA;    /ez 5 def&#xD;&#xA;    &#xD;&#xA;    % x y z -&gt; X Y&#xD;&#xA;    /project {&#xD;&#xA;    ang roty&#xD;&#xA;    ang .25 mul rotx&#xD;&#xA;        /z exch def&#xD;&#xA;        /y exch def&#xD;&#xA;        /x exch def&#xD;&#xA;        1 ez z sub div&#xD;&#xA;        &#xD;&#xA;    x ez mul z ex mul sub&#xD;&#xA;        1 index mul&#xD;&#xA;        y ez mul z ey mul sub&#xD;&#xA;        3 2 roll mul&#xD;&#xA;    } def&#xD;&#xA;    &#xD;&#xA;    10 10 360 {&#xD;&#xA;        /ang exch def&#xD;&#xA;        %matrix currentmatrix&#xD;&#xA;        300 400 translate&#xD;&#xA;        100 100 scale&#xD;&#xA;        60 pointfield&#xD;&#xA;        %setmatrix fill&#xD;&#xA;        /flushpage where {pop flushpage} if&#xD;&#xA;        showpage&#xD;&#xA;    } for&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37369" PostHistoryTypeId="2" PostId="12755" RevisionGUID="41a8eb38-71cc-4e8f-ac6e-a00df63135d7" CreationDate="2022-06-07T15:27:38.400" UserId="2654" Text="From a cursory examination of the documentation, the following seems apparent.&#xD;&#xA;&#xD;&#xA;Vulkan mediates interactions between OS display regions (aka: windows) and a Vulkan application via an object called a `VkSurface`. If you want to draw to a window, you must create a surface associated with that window. A surface is created from a single window, so there is no way for a surface to be associated with multiple windows.&#xD;&#xA;&#xD;&#xA;A surface is associated with a window, but it is also associated with Vulkan. But it is not associated with a specific `VkDevice`; it is instead associated with a `VkInstance`. Therefore, a `VkSurface` can be used (in theory) by any `VkDevice` created from that instance.&#xD;&#xA;&#xD;&#xA;Rendering to a surface is (usually) mediated by a swapchain, which represents a series of images owned by the surface that you can render to and present their contents to that surface. A swapchain is therefore created with a surface, but it is also created with a specific `VkDevice` which is permitted to use the swapchain and its associated images. A surface can only be associated with a single (non-retired) swapchain.&#xD;&#xA;&#xD;&#xA;*However*, there does not appear to be any rule in Vulkan which requires that a `VkDevice` can only be associated with a *single* swapchain at a time. That is, it seems entire reasonable to have a single `VkDevice` that renders to multiple windows, each through their own swapchain.&#xD;&#xA;&#xD;&#xA;Now, you might wish to create multiple graphics queues (where possible), so that one window does not have to wait on presentation from another window." ContentLicense="CC BY-SA 4.0" />
  <row Id="37371" PostHistoryTypeId="2" PostId="12756" RevisionGUID="2b3ddd2f-8e18-42a7-abd7-31bf595de82c" CreationDate="2022-06-07T17:29:02.237" UserId="5256" Text="I want to render my OpenGL GLUT project to a window/control in C# WPF. I have read articles online from Microsoft on how to do it but I am very confused.&#xD;&#xA;&#xD;&#xA;Does anyone have any experience with this? Could someone walk me through it with code? What are some other good ways to create a UI?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37373" PostHistoryTypeId="1" PostId="12756" RevisionGUID="2b3ddd2f-8e18-42a7-abd7-31bf595de82c" CreationDate="2022-06-07T17:29:02.237" UserId="5256" Text="How to give C++ GLUT a UI in C# WPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37374" PostHistoryTypeId="3" PostId="12756" RevisionGUID="2b3ddd2f-8e18-42a7-abd7-31bf595de82c" CreationDate="2022-06-07T17:29:02.237" UserId="5256" Text="|opengl|c++|glut|c#|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37375" PostHistoryTypeId="4" PostId="12756" RevisionGUID="cfe98c16-3feb-4485-923b-0871c439ad34" CreationDate="2022-06-07T18:02:55.290" UserId="5256" Comment="edited title" Text="How to give C++ GLUT project an Editor/UI?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37376" PostHistoryTypeId="2" PostId="12757" RevisionGUID="38c50c9c-d6b5-4c9b-8c47-f8c74de10014" CreationDate="2022-06-07T20:48:35.130" UserId="2654" Text="GLUT owns the window it creates. It can't share it with WPF, nor can it use a window created by WPF.&#xD;&#xA;&#xD;&#xA;If you want to have an OpenGL application render to a window owned by WPF, that may be possible, but you can't use GLUT for that. You'd have to manually attach OpenGL to the window and manage all of the stuff GLUT otherwise does.&#xD;&#xA;&#xD;&#xA;Also, most WPF &quot;windows&quot; are not Win32 HWNDs. So OpenGL cannot render to them. You'd need to make sure that the window is an actual HWND." ContentLicense="CC BY-SA 4.0" />
  <row Id="37378" PostHistoryTypeId="2" PostId="12758" RevisionGUID="2d6a88b3-475f-4809-9b56-af6b9f8edc71" CreationDate="2022-06-07T20:50:24.203" UserId="18373" Text="I am trying optimize routines for drawing primitive shapes for my custom 3D renderer.&#xD;&#xA;&#xD;&#xA;What is the best data type for representing a z buffer array? I thought that integer would be the best choice since calculations involving integer are fast, compared to float or double. But the drawback for using integer is the loss of precision, leading to z fighting. Here is the attempt to draw overlapping 3D triangles using integer z buffer array&#xD;&#xA;&#xD;&#xA;[![f1][1]][1]&#xD;&#xA;&#xD;&#xA;You can see the rough line on the area where triangles overlap. It is supposed to be straight. On the other hand, if I use float for z buffer array,&#xD;&#xA;&#xD;&#xA;[![f2][2]][1]&#xD;&#xA;&#xD;&#xA;It works as expected.&#xD;&#xA;&#xD;&#xA;I wonder if it is possible to fix z fighting issue if I use integer z array. If so, how?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UaULM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZOqiA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37380" PostHistoryTypeId="1" PostId="12758" RevisionGUID="2d6a88b3-475f-4809-9b56-af6b9f8edc71" CreationDate="2022-06-07T20:50:24.203" UserId="18373" Text="Data type for z buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="37381" PostHistoryTypeId="3" PostId="12758" RevisionGUID="2d6a88b3-475f-4809-9b56-af6b9f8edc71" CreationDate="2022-06-07T20:50:24.203" UserId="18373" Text="|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37382" PostHistoryTypeId="5" PostId="12758" RevisionGUID="6daaaf4b-7e4a-4bc8-9b57-c208836839d0" CreationDate="2022-06-07T22:32:46.717" UserId="18373" Comment="added 607 characters in body; edited title" Text="I am trying optimize routines for drawing primitive shapes for my custom 3D renderer.&#xD;&#xA;&#xD;&#xA;What is the best data type for representing a coordinate in 3D space? I thought that integer would be the best choice since calculations involving integer are fast, compared to float or double. Also, Bresenham's algorithm loves integers. But the drawback for using integer is the loss of precision which leads to z fighting. Here is the attempt to draw overlapping 3D triangles if I use integer coordinates.&#xD;&#xA;&#xD;&#xA;[![f1][1]][1]&#xD;&#xA;&#xD;&#xA;You can see the rough line on the area where triangles overlap. It is supposed to be straight. On the other hand, if I use float for coordinates,&#xD;&#xA;&#xD;&#xA;[![f2][2]][1]&#xD;&#xA;&#xD;&#xA;It works as expected.&#xD;&#xA;&#xD;&#xA;I wonder if it is possible to fix the z fighting issue when I use integer coordinates. Maybe there's no other way than using float for coordinates?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Here is my code for rendering a single pixel. I thought it might be relevant.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void Renderer::PutPixel(int x, int y, int z, const Colour&amp; col)&#xD;&#xA;{&#xD;&#xA;    int offset = y * width + x;&#xD;&#xA;    float depth = 1.0 / z;&#xD;&#xA;&#xD;&#xA;    if (zdepth[offset] &lt; depth)&#xD;&#xA;    {&#xD;&#xA;         zdepth[offset] = depth;&#xD;&#xA;         pixels[offset] = col.argb;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The z buffer array `zdepth` is a 1D array of floating point values and `pixels` is an another 1D array of 32-bit unsigned RGB values.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UaULM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZOqiA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37383" PostHistoryTypeId="4" PostId="12758" RevisionGUID="6daaaf4b-7e4a-4bc8-9b57-c208836839d0" CreationDate="2022-06-07T22:32:46.717" UserId="18373" Comment="added 607 characters in body; edited title" Text="Data type for coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="37384" PostHistoryTypeId="2" PostId="12759" RevisionGUID="28069340-e1c0-4630-93a0-0c151a78f8b7" CreationDate="2022-06-08T08:48:51.640" UserId="13975" Text="I want to write a simple ray tracing(?) algorithm with continuous refraction.  So my idea was, what if you have a material whose optical density varies continuously in space, if this is physically possible?&#xD;&#xA;&#xD;&#xA;So say you have some closed zero-set $A\subseteq\mathbf{R}^3$ and the optical density of some point $x$ in your world is $n(x):=\exp(-d(x,A)^2)$ where $d(x,A)$ is the distance between $x$ and (one of) the closest point to $x$ in $A$.  I couldn't find a formula for this, but I assume it would be some limit of [Snell's law](https://en.wikipedia.org/wiki/Snell%27s_law) where you you round $n(x)$ to some multiple of $\epsilon$ and let $\epsilon$ approach $0$.&#xD;&#xA;&#xD;&#xA;What would be a good algorithm to approximate this?  Basically my idea is to have a position and a direction, which describe the current stat of your ray, then you loop over some fixed number of iterations and in each step do&#xD;&#xA; - compute the vector $v$ from the current position to the closest point in $A$ (I hope the set of $x$ with more than one closest point in $A$ is a zero-set and I will never encounter it),&#xD;&#xA; - compute length of $v$ and its angle relative to the current travelling direction,&#xD;&#xA; - then compute a new direction and some distance to travel, update the position and continue the loop, or break if you encounter some texture inbetween.&#xD;&#xA; &#xD;&#xA;The idea is that the travel distances are shorter when you are closer to $A$, as the refraction index changes more rapidly here.  How could the function for the last step look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37386" PostHistoryTypeId="1" PostId="12759" RevisionGUID="28069340-e1c0-4630-93a0-0c151a78f8b7" CreationDate="2022-06-08T08:48:51.640" UserId="13975" Text="Ray Tracing With Continuous Refraction" ContentLicense="CC BY-SA 4.0" />
  <row Id="37387" PostHistoryTypeId="3" PostId="12759" RevisionGUID="28069340-e1c0-4630-93a0-0c151a78f8b7" CreationDate="2022-06-08T08:48:51.640" UserId="13975" Text="|raytracing|webgl|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37388" PostHistoryTypeId="5" PostId="12759" RevisionGUID="f13a104c-e7b8-4b30-87fc-3b350b5c180e" CreationDate="2022-06-08T08:55:47.563" UserId="13975" Comment="added 9 characters in body" Text="I want to write a simple ray tracing(?) algorithm in WebGL with continuous refraction.  So my idea was, what if you have a material whose optical density varies continuously and differentiable almost everywhere in space, if this is physically possible?&#xD;&#xA;&#xD;&#xA;So say you have some closed zero-set $A\subseteq\mathbf{R}^3$ and the optical density of some point $x$ in your world is $n(x):=\exp(-d(x,A)^2)$ where $d(x,A)$ is the distance between $x$ and (one of) the closest point to $x$ in $A$.  I couldn't find a formula for this, but I assume it would be some limit of [Snell's law](https://en.wikipedia.org/wiki/Snell%27s_law) where you you round $n(x)$ to some multiple of $\epsilon$ and let $\epsilon$ approach $0$.&#xD;&#xA;&#xD;&#xA;What would be a good algorithm to approximate this?  Basically my idea is to have a position and a direction, which describe the current stat of your ray, then you loop over some fixed number of iterations and in each step do&#xD;&#xA; - compute the vector $v$ from the current position to the closest point in $A$ (I hope the set of $x$ with more than one closest point in $A$ is a zero-set and I will never encounter it),&#xD;&#xA; - compute length of $v$ and its angle relative to the current travelling direction,&#xD;&#xA; - then compute a new direction and some distance to travel, update the position and continue the loop, or break if you encounter some texture inbetween.&#xD;&#xA; &#xD;&#xA;The idea is that the travel distances are shorter when you are closer to $A$, as the refraction index changes more rapidly here.  How could the function for the last step look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37389" PostHistoryTypeId="5" PostId="12759" RevisionGUID="07dc03f5-97c5-43c5-8cfe-445e8d8cc749" CreationDate="2022-06-08T12:07:31.983" UserId="13975" Comment="deleted 46 characters in body" Text="I want to write a simple ray tracing(?) algorithm in WebGL with continuous refraction.  So my idea was, what if you have a material whose optical density varies continuously, if this is physically possible?&#xD;&#xA;&#xD;&#xA;So say you have some closed zero-set $A\subseteq\mathbf{R}^3$ and the optical density of some point $x$ in your world is $n(x):=\exp(-d(x,A)^2)$ where $d(x,A)$ is the distance between $x$ and (one of) the closest point to $x$ in $A$.  I couldn't find a formula for this, but I assume it would be some limit of [Snell's law](https://en.wikipedia.org/wiki/Snell%27s_law) where you you round $n(x)$ to some multiple of $\epsilon$ and let $\epsilon$ approach $0$.&#xD;&#xA;&#xD;&#xA;What would be a good algorithm to approximate this?  Basically my idea is to have a position and a direction, which describe the current stat of your ray, then you loop over some fixed number of iterations and in each step do&#xD;&#xA; - compute the vector $v$ from the current position to the closest point in $A$ (I hope the set of $x$ with more than one closest point in $A$ is a zero-set and I will never encounter it),&#xD;&#xA; - compute length of $v$ and its angle relative to the current travelling direction,&#xD;&#xA; - then compute a new direction and some distance to travel, update the position and continue the loop, or break if you encounter some texture inbetween.&#xD;&#xA; &#xD;&#xA;The idea is that the travel distances are shorter when you are closer to $A$, as the refraction index changes more rapidly here.  How could the function for the last step look like?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37396" PostHistoryTypeId="2" PostId="12761" RevisionGUID="7338d92b-a486-4d64-bad6-c66bb8ea8ac7" CreationDate="2022-06-08T16:47:36.677" UserId="17751" Text="I'm reading section 6.1 (Determinants) of the book Fundamentals of Computer Graphics (5th Ed), in regards to the definition of the determinant:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;|\textbf{ab}| &amp;= |(x_a \textbf{x} + y_a \textbf{y})(x_b \textbf{x} + y_b \textbf{y})|\\&#xD;&#xA;&amp;= x_a x_b|\textbf{xx}| + x_a y_b |\textbf{xy}| + y_a x_b|\textbf{yx}| + y_a y_b|\textbf{yy}|&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;where the following have been declared beforehand:&#xD;&#xA;&#xD;&#xA;$$|(k \textbf{a})\textbf{b}| = |\textbf{a}(k \textbf{b})| = k|\textbf{ab}|$$&#xD;&#xA;$$|(\textbf{a}+k \textbf{b})\textbf{b}| = |\textbf{a}(\textbf{b} + k\textbf{a})| = |\textbf{ab}|$$&#xD;&#xA;$$| \textbf{a}(\textbf{b} + \textbf{c})| = |\textbf{ab}| + |\textbf{ac}|$$&#xD;&#xA;&#xD;&#xA;First, I don't know how it's legal to just multiply out the two vectors $ \textbf{a}$ and $ \textbf{b}$ like that inside a determinant, but more importantly, even if I assume that, I get&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;|\textbf{ab}| &amp;= |(x_a \textbf{x} + y_a \textbf{y})(x_b \textbf{x} + y_b \textbf{y})|\\&#xD;&#xA;&amp;= |x_a x_b\textbf{xx} + x_a y_b \textbf{xy} + y_a x_b\textbf{yx} + y_a y_b\textbf{yy}|&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;but it seems like I'd need something like:&#xD;&#xA;$$|\textbf{ab} + \textbf{ac}| = |\textbf{ab}| + |\textbf{ac}|$$&#xD;&#xA;&#xD;&#xA;to be able to get to that second line with the individual $|\textbf{xx}|$ type terms. Am I just missing something here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37398" PostHistoryTypeId="1" PostId="12761" RevisionGUID="7338d92b-a486-4d64-bad6-c66bb8ea8ac7" CreationDate="2022-06-08T16:47:36.677" UserId="17751" Text="Determinants as another way to multiply two vectors" ContentLicense="CC BY-SA 4.0" />
  <row Id="37399" PostHistoryTypeId="3" PostId="12761" RevisionGUID="7338d92b-a486-4d64-bad6-c66bb8ea8ac7" CreationDate="2022-06-08T16:47:36.677" UserId="17751" Text="|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37406" PostHistoryTypeId="2" PostId="12763" RevisionGUID="aff26796-845e-4486-ac70-8a93238fabad" CreationDate="2022-06-08T17:21:01.077" UserId="10096" Text="You can refer to the available literature on the topic. The papers I am aware of are:&#xD;&#xA;&#xD;&#xA;[Ray Tracing in Non-Constant Media][1]&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;[Interactive Rendering of Non-Constant, Refractive Media Using the Ray Equations of Gradient-Index Optics][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The general algorithm for handling a varying index of refraction is ray-marching, where the size of the steps is related to the accuracy of your solution.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/publication/220853139_Ray_Tracing_in_Non-Constant_Media&#xD;&#xA;  [2]: https://onlinelibrary.wiley.com/doi/abs/10.1111/j.1467-8659.2010.01733.x" ContentLicense="CC BY-SA 4.0" />
  <row Id="37408" PostHistoryTypeId="2" PostId="12764" RevisionGUID="2b106fbf-7e57-4726-b68c-fd8dfc5f4764" CreationDate="2022-06-08T18:02:16.067" UserId="10096" Text="I think they just mean $\boldsymbol{a}\boldsymbol{b} = \begin{bmatrix} (x_a \boldsymbol{x} + y_a \boldsymbol{y}) &amp; (x_b \boldsymbol{x} + y_b \boldsymbol{y}) \end{bmatrix}$, where the vectors are set as column vectors (you can also set them as row vectors if you wish and the determinant will not change). Then $|\boldsymbol{a}\boldsymbol{b}| = det[\boldsymbol{a}\boldsymbol{b}]$ has the properties that they describe. If you wish you can pick a specific basis, e.g. $\boldsymbol{x} = \begin{bmatrix} 1 &amp; 0 \end{bmatrix}$ and $\boldsymbol{y} = \begin{bmatrix} 0 &amp; 1 \end{bmatrix}$.  &#xD;&#xA;&#xD;&#xA;As for the expression that you were having an issue with: $|\boldsymbol{a}\boldsymbol{b}+\boldsymbol{a}\boldsymbol{c}| = |\boldsymbol{a}(\boldsymbol{b}+\boldsymbol{c})| = |\boldsymbol{a}\boldsymbol{b}| + |\boldsymbol{a}\boldsymbol{c}|$ from their 3rd rule.&#xD;&#xA;&#xD;&#xA;I am not sure whether this generalizes to more than 2D. You should probably look into exterior products and Levi-Civita if you want something more general." ContentLicense="CC BY-SA 4.0" />
  <row Id="37415" PostHistoryTypeId="2" PostId="12766" RevisionGUID="e6302b4f-3147-4416-8023-1da3c273a661" CreationDate="2022-06-09T17:14:05.633" UserId="11136" Text="I am unsure exactly about your white pixel filling criterion. However, I will offer a solution.&#xD;&#xA;&#xD;&#xA;Create a histogram for each image and compare histograms. If for instance there are 800 red pixels in image A and 800 blue pixels in image B we can make an assumption that there exists a mapping from red to blue across images. There could be some mapping subtleties, for instance there could be 800 red and 800 yellow pixels in image A, then we would need to do a little work to determine which color maps to which color in image B, but that is a workable edge case.&#xD;&#xA;&#xD;&#xA;Now (and this is assuming I understand your white filling problem) start with the image with the most white in its histogram and compare pixel for pixel both images. We do not need to compare the white pixels, because we already know there is not a 1:1 mapping between images. If all of the other pixels map correctly, then we know the image fits our idea of equality.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37417" PostHistoryTypeId="2" PostId="12767" RevisionGUID="b3f35f64-68ae-4419-bb59-286d6a217635" CreationDate="2022-06-09T17:30:01.080" UserId="11136" Text="You could implement a Z buffer. That is, just start drawing the polygons in any order and in a separate buffer record the pixels depth in the scene (0.0 - 1.0 ranging from the front viewing plane to the rear viewing plane of the frustum)&#xD;&#xA;Then when you render the next polygon, compare its depth with that existing in the buffer. If the depth is less (closer to the viewer) draw the pixel, and if it is equal to or greater keep the pixel that already exists in the image." ContentLicense="CC BY-SA 4.0" />
  <row Id="37419" PostHistoryTypeId="2" PostId="12768" RevisionGUID="1cf315ac-4e9f-4139-bf04-cee3564b046c" CreationDate="2022-06-10T02:58:04.740" UserId="18373" Text="I was studying how the OpenGL's [gluUnProject](https://dondi.lmu.build/share/cg/unproject-explained.pdf) works. There is one thing I don't understand: is there any benefit of returning a ray instead of 3D point?&#xD;&#xA;&#xD;&#xA;One can use this function to get a ray not a 3D point by inputting screen x and y. The linked document said that `we can’t really go from a mouse point to a single &#xD;&#xA;3D point`.&#xD;&#xA;&#xD;&#xA;But I think it is still possible to get a 3D point from mouse coordinates. 3D graphics libraries usually implement z buffer and we can easily get the value of z (in screen coordinates) from z buffer. For example, given a mouse coordinates x and y, the value of z can be calculated by `1.0/zbuffer[y][x]`. It is easy to get 3D world space x, y and z with all these information. So why `gluUnProject` is not implemented this way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37421" PostHistoryTypeId="1" PostId="12768" RevisionGUID="1cf315ac-4e9f-4139-bf04-cee3564b046c" CreationDate="2022-06-10T02:58:04.740" UserId="18373" Text="Understanding gluUnProject" ContentLicense="CC BY-SA 4.0" />
  <row Id="37422" PostHistoryTypeId="3" PostId="12768" RevisionGUID="1cf315ac-4e9f-4139-bf04-cee3564b046c" CreationDate="2022-06-10T02:58:04.740" UserId="18373" Text="|opengl|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37423" PostHistoryTypeId="34" PostId="12744" RevisionGUID="472d2b17-650d-472a-8859-82a9dd5865fa" CreationDate="2022-06-10T06:46:59.783" UserId="18487" Comment="78" />
  <row Id="37424" PostHistoryTypeId="5" PostId="12764" RevisionGUID="0094742e-c860-4950-9af7-f94f9591b889" CreationDate="2022-06-10T07:01:37.917" UserId="10096" Comment="added 3383 characters in body" Text="I think they just mean $\boldsymbol{a}\boldsymbol{b} = \begin{bmatrix} (x_a \boldsymbol{x} + y_a \boldsymbol{y}) &amp; (x_b \boldsymbol{x} + y_b \boldsymbol{y}) \end{bmatrix}$, where the vectors are set as column vectors (you can also set them as row vectors if you wish and the determinant will not change). Then $|\boldsymbol{a}\boldsymbol{b}| = det[\boldsymbol{a}\boldsymbol{b}]$ has the properties that they describe. If you wish you can pick a specific basis, e.g. $\boldsymbol{x} = \begin{bmatrix} 1 &amp; 0 \end{bmatrix}$ and $\boldsymbol{y} = \begin{bmatrix} 0 &amp; 1 \end{bmatrix}$.  &#xD;&#xA;&#xD;&#xA;As for the expression that you were having an issue with: $|\boldsymbol{a}\boldsymbol{b}+\boldsymbol{a}\boldsymbol{c}| = |\boldsymbol{a}(\boldsymbol{b}+\boldsymbol{c})| = |\boldsymbol{a}\boldsymbol{b}| + |\boldsymbol{a}\boldsymbol{c}|$ from their 3rd rule.&#xD;&#xA;&#xD;&#xA;I am not sure whether this generalizes to more than 2D. You should probably look into exterior products and Levi-Civita if you want something more general.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;They just assumed that distributivity holds like with normal addition and multiplication, so $\boldsymbol{a}(\boldsymbol{b}+\boldsymbol{c}) = \boldsymbol{a}\boldsymbol{b}+\boldsymbol{a}\boldsymbol{c}$. In fact the only difference to the properties that you're used to for real numbers is that commutativity becomes anti-commutativity: $\boldsymbol{a}\boldsymbol{b}=-\boldsymbol{b}\boldsymbol{a}$. &#xD;&#xA;&#xD;&#xA;The product that they wrote is the [outer product][1]: $\boldsymbol{a}\boldsymbol{b} := \boldsymbol{a}\wedge\boldsymbol{b}$. Or more generally for $n$ $n$-D vectors: $\prod_{i=1}^n\boldsymbol{a}_i := \bigwedge_{i=1}^{n}\boldsymbol{a}_i$. If you take the coefficient in front of the resulting object ([$n$-blade)][2], it is equal to the determinant of the matrix where the vectors have been set as columns, provided that the dimension of the vectors is equal to $n$. &#xD;&#xA;&#xD;&#xA;This means that if you have two 2-D vectors $\boldsymbol{a}, \boldsymbol{b}$, putting them together in a matrix $\begin{bmatrix} \boldsymbol{a} &amp; \boldsymbol{b} \end{bmatrix}$ and computing the determinant $|\boldsymbol{a}\boldsymbol{b}| = \operatorname{det}\left(\begin{bmatrix} \boldsymbol{a} &amp; \boldsymbol{b} \end{bmatrix}\right)$ yields the signed area of the parallelogram formed by those ($\boldsymbol{a},\boldsymbol{b}$ are two of its non-parallel edges). If you have three 3-D vectors $\boldsymbol{a},\boldsymbol{b},\boldsymbol{c}$, putting them together in a matrix $\begin{bmatrix}\boldsymbol{a} &amp; \boldsymbol{b} &amp; \boldsymbol{c}\end{bmatrix}$ and computing the determinant $|\boldsymbol{a}\boldsymbol{b}\boldsymbol{c}| = \operatorname{det}\left(\begin{bmatrix}\boldsymbol{a} &amp; \boldsymbol{b} &amp; \boldsymbol{c}\end{bmatrix}\right)$ yields the signed volume of the parallelepiped spanned by those. Similarly, if you have $n$ $n$-D vectors $\boldsymbol{a}_1,\ldots,\boldsymbol{a}_n$, then putting them in a matrix $\begin{bmatrix}\boldsymbol{a}_1 &amp; \ldots &amp; \boldsymbol{a}_n\end{bmatrix}$ and computing the determinant $|\boldsymbol{a}_1\ldots\boldsymbol{a}_n|= \operatorname{det}\left(\begin{bmatrix}\boldsymbol{a}_1 &amp; \ldots &amp; \boldsymbol{a}_n\end{bmatrix}\right)$ yields the signed hypervolume of the [$n$-parallelotope][3] formed by those.&#xD;&#xA;&#xD;&#xA;Naturally the question arises what happens when you wedge $n$ $d$-D vectors where $d$ is not equal to $n$. A simple example is wedging two 3-D vectors. The coefficients in front of the three resulting $2$-blades that you get are [equal to the coefficients of the cross product][4], and you have $\star(\boldsymbol{a}\wedge\boldsymbol{b}) = \boldsymbol{a}\times\boldsymbol{b}$, where $\star$ is [the Hodge star operator][5]. Then the definition from the book that you are reading is not applicable. It can be generalized though as the coefficients are made up of sub-determinants. More generally if you want to compute a specific coefficient of the wedge of multiple arbitrary dimensional vectors, then you can contract them with the [Levi-Civita symbol][6] and extract the relevant coefficient.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Exterior_algebra#Areas_in_the_plane&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Blade_(geometry)&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Parallelepiped#Parallelotope&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Cross_product#As_an_external_product&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Hodge_star_operator&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Levi-Civita_symbol" ContentLicense="CC BY-SA 4.0" />
  <row Id="37429" PostHistoryTypeId="2" PostId="12770" RevisionGUID="2e483b69-d652-4bff-b7c8-d8b24ab223df" CreationDate="2022-06-10T08:03:10.060" UserId="209" Text="It sounds to me that maybe you need to have a look at Newell, Newell,&amp; Sancha's algorithm ( [Paper from 1972][1] or [Wikipedia Summary][2] ).  It was a method to order polygons into back to front order so that you could use a &quot;Painters' Algorithm&quot; to do hidden surface removal (back when a Z-buffer would have probably cost more than a house).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://ohiostate.pressbooks.pub/app/uploads/sites/45/2017/09/newell-newell-sancha.pdf&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Newell%27s_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="37431" PostHistoryTypeId="2" PostId="12771" RevisionGUID="a4cb7ad9-7c0b-42c8-962a-ee495b3112d1" CreationDate="2022-06-10T11:37:47.670" UserId="6" Text="With your question you have basically identified a core problem in your assumption of *&quot;how the OpenGL's gluUnProject works&quot;*, namely that this function *isn't* actually part of the OpenGL. The GLU library is a (very old) auxiliary library containing some useful methods (of questionable relevance nowadays) for computer graphics computing on top of OpenGL.&#xD;&#xA;&#xD;&#xA;Now why does this matter? Well, those **GLU functions have absolutely nothing to do with hardware accelerated rendering**, which is the core, if not *the only*, competence of OpenGL. So they neither have any business messing with the hardware resources you'd need for your implementation of the method, namely reading back the hardware depth buffer. In fact `gluUnProject` is a rather simple method containing a few simple 4x4 matrix multiplies, that's really all.&#xD;&#xA;&#xD;&#xA;You certainly *can* use your method for determining the actual 3D point of a pixel, but you'd have to do it yourself on top of that computation. This way you'd also be **responsible yourself for reading back the depth buffer** onto the CPU, which **isn't actually a zero-cost operation**, even for a single pixel, since it causes pipeline stalls and many other synchronization issues. That's why it might not be the best idea to have such a basic operation do it on its own, when often a general ray without actual depth information is enough.&#xD;&#xA;&#xD;&#xA;So while `gluUnProject`, at least back in the day when rendering was all simple like that, could theoretically do a `glReadPixels` call internally, that's just not in its area of competence as a simple geometric linear algebra function. And nowadays you'd not use GLU anymore anyway, rather than the third-party mathematics library you'd have to use on top of OpenGL (since modern OpenGL doesn't do matrix math for you anymore). And such third-party libaries, while possibly offering a similar function as `gluUnProject`, would be even more out of their depths (pun intended) to call OpenGL functions willy-nilly and query hardware information that's absolutely not of their responsibility to mess with. Not to speak of the fact that rendering nowadays is a lot more flexible and your depth buffer data could be computed in any or no way possible." ContentLicense="CC BY-SA 4.0" />
  <row Id="37434" PostHistoryTypeId="2" PostId="12772" RevisionGUID="7f204065-2227-4434-9153-7db3668f5c95" CreationDate="2022-06-10T11:56:03.617" UserId="6" Text="You are running on a few false assumptions here. Whoeever told you that *&quot;x, y, z are all in range [-1...1]&quot;* for clip coordinates was wrong, or explained it badly, or was misunderstood.&#xD;&#xA;&#xD;&#xA;First of all, the **clip coordinates can have *all kinds* of values**. Afterall, they resulted from putting your whatever-natured objects through the transformation pipeline. The *NDC coordinates* of *all visible* points will be in the [-1,1] range. And that is where clipping comes into play, the operation that the &quot;clip space&quot; takes its name from. Clipping is when you **cut your primitives** (i.e. triangles and lines, technically also points, but practically you either cull these or not) so that they are **inside the viewing volume**, which in clip space means coordinates not in [-1,1], but **[-w,w]**.&#xD;&#xA;&#xD;&#xA;Sounds weird to have a different interval for each point and what is this 4D space anyway? Well, that's what makes clipping a bit complicated. You can't just cut lines and triangles to the viewing volume in 3D, as for perspective trtansformations that might result in things behind the camera being shown or lines crossing from front to back and all kinds of weird stuff. Really, though, I leave explaining the mathematics of 4D projective space and homogenous coordinates to a proper learning resource with cool pictures. The bottom line is, **you need to clip primitives in 4D homogenous space for them to behave properly under perspective projection**. And that is what clip space is for.&#xD;&#xA;&#xD;&#xA;After clipping, all cordinates are within the [-w,w] range and in NDC space, after dividing by w and thus realizing any actual perspective distortion, all coordinates are within [-1,1] and ready for the viewport transformation.&#xD;&#xA;&#xD;&#xA;Why clip space (and thus also NDC space) is left-handed is a bit of a question of taste and tradition, based on the fact that OpenGL's depth buffer uses 1 for the back and 0 for the front. But nowadays you can pretty much change this up to your liking anyway." ContentLicense="CC BY-SA 4.0" />
  <row Id="37436" PostHistoryTypeId="5" PostId="12761" RevisionGUID="dcdf5c07-151a-4188-beb2-7f75442fca98" CreationDate="2022-06-10T20:39:45.100" UserId="17751" Comment="added 1471 characters in body" Text="I'm reading section 6.1 (Determinants) of the book Fundamentals of Computer Graphics (5th Ed), in regards to the definition of the determinant:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;|\textbf{ab}| &amp;= |(x_a \textbf{x} + y_a \textbf{y})(x_b \textbf{x} + y_b \textbf{y})|\\&#xD;&#xA;&amp;= x_a x_b|\textbf{xx}| + x_a y_b |\textbf{xy}| + y_a x_b|\textbf{yx}| + y_a y_b|\textbf{yy}|&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;where the following have been declared beforehand:&#xD;&#xA;&#xD;&#xA;$$|(k \textbf{a})\textbf{b}| = |\textbf{a}(k \textbf{b})| = k|\textbf{ab}|$$&#xD;&#xA;$$|(\textbf{a}+k \textbf{b})\textbf{b}| = |\textbf{a}(\textbf{b} + k\textbf{a})| = |\textbf{ab}|$$&#xD;&#xA;$$| \textbf{a}(\textbf{b} + \textbf{c})| = |\textbf{ab}| + |\textbf{ac}|$$&#xD;&#xA;&#xD;&#xA;First, I don't know how it's legal to just multiply out the two vectors $ \textbf{a}$ and $ \textbf{b}$ like that inside a determinant, but more importantly, even if I assume that, I get&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;|\textbf{ab}| &amp;= |(x_a \textbf{x} + y_a \textbf{y})(x_b \textbf{x} + y_b \textbf{y})|\\&#xD;&#xA;&amp;= |x_a x_b\textbf{xx} + x_a y_b \textbf{xy} + y_a x_b\textbf{yx} + y_a y_b\textbf{yy}|&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;but it seems like I'd need something like:&#xD;&#xA;$$|\textbf{ab} + \textbf{ac}| = |\textbf{ab}| + |\textbf{ac}|$$&#xD;&#xA;&#xD;&#xA;to be able to get to that second line with the individual $|\textbf{xx}|$ type terms. Am I just missing something here?&#xD;&#xA;&#xD;&#xA;UPDATE:&#xD;&#xA;&#xD;&#xA;I finally figured out why this is ok, but wanted to leave accepted answer below as it has useful info. Anyway, for posterity, here it is. We'll need both&#xD;&#xA;\begin{align}&#xD;&#xA;|\textbf{a}(\textbf{b} + \textbf{c})| &amp;= |\textbf{ab}| + |\textbf{ac}|&#xD;&#xA;\end{align}&#xD;&#xA;and&#xD;&#xA;\begin{align}&#xD;&#xA;|(\textbf{b} + \textbf{c})\textbf{a}| = |\textbf{ba}| + |\textbf{ca}|&#xD;&#xA;\end{align}&#xD;&#xA;in addition to the first identity above in the original post. Figure 6.5 of the text shows the geometry behind both of these for intuition. Then, let&#xD;&#xA;\begin{align*}&#xD;&#xA;\textbf{a} &amp;= (x_a \textbf{x} + y_a \textbf{y}) \\&#xD;&#xA;\textbf{b} &amp;= x_b \textbf{x} \\&#xD;&#xA;\textbf{c} &amp;= y_b \textbf{y}&#xD;&#xA;\end{align*}&#xD;&#xA;so that, applying (1) followed by (2), we have&#xD;&#xA;\begin{align*}&#xD;&#xA;|(x_a \textbf{x} + y_a \textbf{y})(x_b \textbf{x} + y_b \textbf{y})| &amp;= |\textbf{a}(\textbf{b} + \textbf{c})| \\&#xD;&#xA;&amp;= |(x_a \textbf{x} + y_a \textbf{y})x_b \textbf{x}| + |(x_a \textbf{x} + y_a \textbf{y})y_b \textbf{y}| \\&#xD;&#xA;&amp;= |x_a x_b \textbf{xx}| + |y_a x_b \textbf{yx}| + |x_a y_b \textbf{xy}| + |y_a y_b \textbf{yy}| \\&#xD;&#xA;&amp;= x_a x_b |\textbf{xx}| + x_a y_b |\textbf{xy}| + y_a x_b |\textbf{yx}| + y_a y_b |\textbf{yy}|&#xD;&#xA;\end{align*}&#xD;&#xA;where we used the first identity $|(k \textbf{a})\textbf{b}| = k|\textbf{ab}|$ to pull out the coefficients. This is nice because we're not using e.g. FOIL for &quot;multiplying out the two vectors&quot; as I had originally supposed (even though it looks like that). All we're doing is just applying identities." ContentLicense="CC BY-SA 4.0" />
  <row Id="37437" PostHistoryTypeId="2" PostId="12773" RevisionGUID="6ef018b4-357c-423f-8385-2ea19c927c24" CreationDate="2022-06-11T00:56:16.507" UserId="18517" Text="The book defines operator $\tau$ for the propagation of an exitant function as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e68RC.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;if I'm assuming that the position of the point $x$ is on the top-left surface, and that $\Psi$ is considered as the direction originating from point $y = r(x, \Theta)$ ($r$ being the raycast function) then what's the interpretation of $cos(N_{x}, \Psi)$ ? Why would we use the normal at point $x$ (on another surface!) instead of $cos(N_{r(x, \Theta)}, \Psi)$ ?&#xD;&#xA;&#xD;&#xA;on the other hand, if I'm assuming that $x$ is the point on the surface at bottom-right, then where's the point $y = r(x, \Theta)$ ? And what's the physical meaning of $L(y, \rightarrow -\Psi)$ ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37439" PostHistoryTypeId="1" PostId="12773" RevisionGUID="6ef018b4-357c-423f-8385-2ea19c927c24" CreationDate="2022-06-11T00:56:16.507" UserId="18517" Text="Difficulty in understanding the interpretation of propagation of an exitant function from the book Adanvaced Global Illumination (2nd ed)" ContentLicense="CC BY-SA 4.0" />
  <row Id="37440" PostHistoryTypeId="3" PostId="12773" RevisionGUID="6ef018b4-357c-423f-8385-2ea19c927c24" CreationDate="2022-06-11T00:56:16.507" UserId="18517" Text="|raytracing|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37441" PostHistoryTypeId="5" PostId="12773" RevisionGUID="b23f7361-ea19-42b2-9549-d1edb6f6cefb" CreationDate="2022-06-11T00:57:36.610" UserId="18517" Comment="misplaced comma" Text="The book defines operator $\tau$ for the propagation of an exitant function as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e68RC.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;if I'm assuming that the position of the point $x$ is on the top-left surface, and that $\Psi$ is considered as the direction originating from point $y = r(x, \Theta)$ ($r$ being the raycast function) then what's the interpretation of $cos(N_{x}, \Psi)$ ? Why would we use the normal at point $x$ (on another surface!) instead of $cos(N_{r(x, \Theta)}, \Psi)$ ?&#xD;&#xA;&#xD;&#xA;on the other hand, if I'm assuming that $x$ is the point on the surface at bottom-right, then where's the point $y = r(x, \Theta)$ ? And what's the physical meaning of $L(y \rightarrow -\Psi)$ ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37442" PostHistoryTypeId="4" PostId="12773" RevisionGUID="53bb1044-4d2e-4afb-99d1-3e770b8e434c" CreationDate="2022-06-11T00:58:39.593" UserId="18517" Comment="edited title" Text="Difficulty in understanding the interpretation of propagation of an exitant function from the book Advanced Global Illumination (2nd ed)" ContentLicense="CC BY-SA 4.0" />
  <row Id="37444" PostHistoryTypeId="5" PostId="12773" RevisionGUID="45847ada-e725-4a46-91dd-d0bbf75ef14e" CreationDate="2022-06-11T06:23:29.770" UserId="10096" Comment="added 7 characters in body" Text="The book defines operator $\mathcal{T}$ for the propagation of an exitant function as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/e68RC.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;if I'm assuming that the position of the point $x$ is on the top-left surface, and that $\Psi$ is considered as the direction originating from point $y = r(x, \Theta)$ ($r$ being the raycast function) then what's the interpretation of $cos(N_{x}, \Psi)$ ? Why would we use the normal at point $x$ (on another surface!) instead of $cos(N_{r(x, \Theta)}, \Psi)$ ?&#xD;&#xA;&#xD;&#xA;on the other hand, if I'm assuming that $x$ is the point on the surface at bottom-right, then where's the point $y = r(x, \Theta)$ ? And what's the physical meaning of $L(y \rightarrow -\Psi)$ ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37454" PostHistoryTypeId="2" PostId="12776" RevisionGUID="1eaa824a-f534-4740-a4f0-22fdbaa8747a" CreationDate="2022-06-12T11:43:28.577" UserId="9157" Text="So I am trying to implement a fluid simulation, as described in [Chapter 38 of GPU Gems](https://developer.nvidia.com/gpugems/gpugems/part-vi-beyond-triangles/chapter-38-fast-fluid-dynamics-simulation-gpu).&#xD;&#xA;&#xD;&#xA;I am also drawing heavily from the excellent implementation by [Pavel](https://github.com/PavelDoGreat/WebGL-Fluid-Simulation).&#xD;&#xA;&#xD;&#xA;Where I'm getting a bit stuck is with advection.&#xD;&#xA;&#xD;&#xA;So as I understand it, advection is the process that moves quantities along with the movement of the fluid.  So for example, if at one timestamp, you have a velocity `v` at position `p`, then in the next timestamp, you have velocity `V` at position `p + v * dt`, at least according to advection.&#xD;&#xA;&#xD;&#xA;So as it says in GPU gems, there is a difficulty implementing this logic on the GPU:&#xD;&#xA;&#xD;&#xA;&gt; We implement our simulation in fragment programs, which cannot change the locations of the fragments they are writing. This forward-integration method requires the ability to &quot;move&quot; the particles, so it cannot be implemented on current GPUs.&#xD;&#xA;&#xD;&#xA;&gt; The solution is to invert the problem and use an implicit method (Stam 1999). Rather than advecting quantities by computing where a particle moves over the current time step, we trace the trajectory of the particle from each grid cell back in time to its former position, and we copy the quantities at that position to the starting grid cell.&#xD;&#xA;&#xD;&#xA;So in other words, instead of projecting values forward in the grid, based on the velocity value in the current timestamp, we use the current velocity to trace *backwards* in the grid, to see what the next value should be which is coming in the direction of our current grid cell.&#xD;&#xA;&#xD;&#xA;The problem with this approach appears to occur when velocity is zero.  So for instance, consider that we have a 1 dimensional grid of velocities:&#xD;&#xA;&#xD;&#xA;`[3|1|2|1]`&#xD;&#xA;&#xD;&#xA;If we advect this grid according to the backwards lookup, at the next timestamp, we will have the following:&#xD;&#xA;&#xD;&#xA;`[0|3|3|2]`&#xD;&#xA;&#xD;&#xA;So this is working as expected.&#xD;&#xA;&#xD;&#xA;However this breaks down, and if we have a *zero* in any position, there's no way to get another value to replace the zero:&#xD;&#xA;&#xD;&#xA;`t+0:` `[3|1|2|0]`&#xD;&#xA;&#xD;&#xA;`t+1:` `[0|3|3|0]`&#xD;&#xA;&#xD;&#xA;`t+2:` `[0|0|0|0]`&#xD;&#xA;&#xD;&#xA;So basically, if the value of the cell is zero, it will never look up any value other than itself, so there is no way for another quantity to advect into it.&#xD;&#xA;&#xD;&#xA;And indeed this is exactly the behavior I am seeing in my simulation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;And here's the shader I am using:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#define WORKGROUP_SIZE 16&#xD;&#xA;layout (local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1 ) in;&#xD;&#xA;&#xD;&#xA;precision highp float;&#xD;&#xA;precision highp sampler2D;&#xD;&#xA;&#xD;&#xA;layout(push_constant) uniform PushConstant {&#xD;&#xA;    vec2 viewport;&#xD;&#xA;    vec2 texelSize;&#xD;&#xA;    vec2 dyeTexelSize;&#xD;&#xA;    float dt;&#xD;&#xA;    float dissipation;&#xD;&#xA;} pushConstants;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout(binding = 0, rgba8) uniform writeonly image2D outputImage;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout(binding = 1) uniform sampler2D uVelocity;&#xD;&#xA;layout(binding = 2) uniform sampler2D uSource;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;vec4 bilerp(sampler2D sam, vec2 uv, vec2 tsize) {&#xD;&#xA;    vec2 st = uv / tsize - 0.5;&#xD;&#xA;    vec2 iuv = floor(st);&#xD;&#xA;    vec2 fuv = fract(st);&#xD;&#xA;    vec4 a = texture(sam, (iuv + vec2(0.5, 0.5)) * tsize);&#xD;&#xA;    vec4 b = texture(sam, (iuv + vec2(1.5, 0.5)) * tsize);&#xD;&#xA;    vec4 c = texture(sam, (iuv + vec2(0.5, 1.5)) * tsize);&#xD;&#xA;    vec4 d = texture(sam, (iuv + vec2(1.5, 1.5)) * tsize);&#xD;&#xA;    return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    &#xD;&#xA;    vec2 viewport = pushConstants.viewport;&#xD;&#xA;    vec2 texelSize = pushConstants.texelSize;&#xD;&#xA;    vec2 dyeTexelSize = pushConstants.dyeTexelSize;&#xD;&#xA;    float dt = pushConstants.dt;&#xD;&#xA;    float dissipation = pushConstants.dissipation;&#xD;&#xA;    vec2 position = vec2(gl_GlobalInvocationID.x / viewport.x, gl_GlobalInvocationID.y / viewport.y);&#xD;&#xA;    if (position.x &gt; 1.0 || position.y &gt; 1.0) {&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec2 uv = position + texelSize/2;&#xD;&#xA;    vec2 vUv = params.uv;&#xD;&#xA;    vec2 coord = vUv - dt * bilerp(uVelocity, uv, texelSize).xy * texelSize;&#xD;&#xA;    vec4 result = bilerp(uSource, coord, dyeTexelSize);&#xD;&#xA;    float decay = 1.0 + dissipation * dt;&#xD;&#xA;    imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy), result / decay);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;So my question is, how are quantities supposed to advect forward into a void?  Am I missing part of the process here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9EdjA.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37456" PostHistoryTypeId="1" PostId="12776" RevisionGUID="1eaa824a-f534-4740-a4f0-22fdbaa8747a" CreationDate="2022-06-12T11:43:28.577" UserId="9157" Text="Having trouble understanding advection from GPU gems fluid dynamics example" ContentLicense="CC BY-SA 4.0" />
  <row Id="37457" PostHistoryTypeId="3" PostId="12776" RevisionGUID="1eaa824a-f534-4740-a4f0-22fdbaa8747a" CreationDate="2022-06-12T11:43:28.577" UserId="9157" Text="|glsl|vulkan|compute-shader|fluid-sim|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37458" PostHistoryTypeId="2" PostId="12777" RevisionGUID="44313e29-9a65-474d-b40b-f02efb8307f4" CreationDate="2022-06-12T17:57:49.543" UserId="120" Text="The cells with zero velocity are boundaries (walls) of the simulation domain. You will need to handle the boundary conditions explicitly. The advection itself cannot do much for you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;From the context it seems you are simulating incompressible flow. Intuitively, if the fluid flows toward a wall then the fluid is expected to be &quot;pushed&quot; to the sides of the wall.&#xD;&#xA;That is handled by pressure projection.&#xD;&#xA;Specifically it is around Equation 16 on the page you linked.&#xD;&#xA;&#xD;&#xA;That Equation 16 is a discretization of the pressure term. That will lead you to a linear system. You can solve it iteratively (Stam99). The solution of that system will give you the divergence-free velocity, and it will advect your fluid to the sides of walls as expected.&#xD;&#xA;&#xD;&#xA;Regarding to your question: if the boundary is a wall then nothing will advect into it. The incompressibility (the pressure here) will enforce the fluid to flow somewhere else." ContentLicense="CC BY-SA 4.0" />
  <row Id="37460" PostHistoryTypeId="52" PostId="12776" RevisionGUID="b1f9505b-6287-4223-92ad-29174b3a7b12" CreationDate="2022-06-12T19:47:13.630" />
  <row Id="37461" PostHistoryTypeId="2" PostId="12778" RevisionGUID="7ae0e14b-7192-418e-a942-816662e6c2b1" CreationDate="2022-06-12T22:15:00.017" UserId="7462" Text="Inigo Quilez has an [explanation][1] of smooth operations to join sdfs.&#xD;&#xA;&#xD;&#xA;I am trying to get something close to the convex hull of multiple sdfs. For starters let;s consider a simple case of 3 cubes int eh following configuration:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The convex hull would be a very, very similar shape, with the exception that the region inside the l shape would be a diagonal slope.&#xD;&#xA;&#xD;&#xA;I tried using smooth joining operations with a high weight, but I get this&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The area I expected to be filled is indeed filled, but everything else bloated up. I am trying to come up with a mathematical formula to test if a point would be inside the convex hull.&#xD;&#xA;&#xD;&#xA;  [1]: https://iquilezles.org/articles/distfunctions/&#xD;&#xA;  [2]: https://i.stack.imgur.com/nwTGH.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/O4sQa.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37463" PostHistoryTypeId="1" PostId="12778" RevisionGUID="7ae0e14b-7192-418e-a942-816662e6c2b1" CreationDate="2022-06-12T22:15:00.017" UserId="7462" Text="Getting something close to the convex full of SDFs using CSG operations" ContentLicense="CC BY-SA 4.0" />
  <row Id="37464" PostHistoryTypeId="3" PostId="12778" RevisionGUID="7ae0e14b-7192-418e-a942-816662e6c2b1" CreationDate="2022-06-12T22:15:00.017" UserId="7462" Text="|raytracing|glsl|mathematics|computational-geometry|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37468" PostHistoryTypeId="50" PostId="12158" RevisionGUID="18c63307-80fe-4deb-a998-3d40606ad07c" CreationDate="2022-06-13T11:02:10.203" UserId="-1" />
  <row Id="37474" PostHistoryTypeId="2" PostId="12780" RevisionGUID="5d22f44d-d21e-4df8-a6a4-2f4122340bae" CreationDate="2022-06-14T10:36:48.853" UserId="18526" Text="What i have now? &#xD;&#xA;i have a cube consistend of 6 planes. All this planes i generate in XY coordinates and then place them by matrix transformations.&#xD;&#xA;&#xD;&#xA;[![введите сюда описание изображения][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I need to rotate my cube along global axis and move my planes along cube rotation;&#xD;&#xA;&#xD;&#xA;I rotate by cube &#xD;&#xA;[![введите сюда описание изображения][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then i need move one of the planes correctly. But planes anyway moves along global axis. Red Line shows how plane moves now, green line shows how it should moves.&#xD;&#xA;[![введите сюда описание изображения][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PLe8w.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/elfwB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uZXso.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How i create a cube. All vertices in range (0,0) - (2, 2);&#xD;&#xA;```&#xD;&#xA;    planeXY.setupMesh();&#xD;&#xA;    planeXY.setOrigin({1, 1, 1});&#xD;&#xA;    &#xD;&#xA;    planeXY1.setupMesh();&#xD;&#xA;    planeXY1.setOrigin({1, 1, 1});&#xD;&#xA;    planeXY1.moveAlongGlobalAxis(QVector3D(0.0, 0.0, 2.0));&#xD;&#xA;    &#xD;&#xA;    planeZY.setupMesh();&#xD;&#xA;    planeZY.setOrigin({1, 1, 1});&#xD;&#xA;    planeZY.rotate(QVector3D(0.0f, -90.0f, 0.0f));&#xD;&#xA;    planeZY.moveAlongGlobalAxis(QVector3D(-2.0, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    planeZY1.setupMesh();&#xD;&#xA;    planeZY1.setOrigin({1, 1, 1});&#xD;&#xA;    planeZY1.rotate(QVector3D(0.0f, -90.0f, 0.0f));&#xD;&#xA;    &#xD;&#xA;    planeXZ.setupMesh();&#xD;&#xA;    planeXZ.setOrigin({1, 1, 1});&#xD;&#xA;    planeXZ.rotate(QVector3D(90.0f, 0.0f, 0.0f));&#xD;&#xA;    planeXZ.moveAlongGlobalAxis(QVector3D(0.0, -2.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    planeXZ1.setupMesh();&#xD;&#xA;    planeXZ1.setOrigin({1, 1, 1});&#xD;&#xA;    planeXZ1.rotate(QVector3D(90.0f, 0.0f, 0.0f));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Mesh.cpp&#xD;&#xA;```&#xD;&#xA;void Mesh::moveAlongGlobalAxis(QVector3D coordinates)&#xD;&#xA;{&#xD;&#xA;    QMatrix4x4 identityMatrix;   &#xD;&#xA;    identityMatrix.translate(coordinates);&#xD;&#xA;    position += coordinates;&#xD;&#xA;    this-&gt;translationMatrix = identityMatrix * translationMatrix;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Mesh::moveAlongLocalAxis(QVector3D coordinates)&#xD;&#xA;{   &#xD;&#xA;    this-&gt;moveAlongGlobalAxis(coordinates); &#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Mesh::rotate(QVector3D rotation)&#xD;&#xA;{&#xD;&#xA;    QMatrix4x4 identityMatrix;&#xD;&#xA;    &#xD;&#xA;    identityMatrix.translate((-1) * this-&gt;position + this-&gt;origin);&#xD;&#xA;    identityMatrix.rotate(rotation.x(), QVector3D(1.0, 0.0, 0.0));&#xD;&#xA;    identityMatrix.rotate(rotation.y(), QVector3D(0.0, 1.0, 0.0));&#xD;&#xA;    identityMatrix.rotate(rotation.z(), QVector3D(0.0, 0.0, 1.0));&#xD;&#xA;    identityMatrix.translate(this-&gt;position - this-&gt;origin);&#xD;&#xA;    this-&gt;rotationMatrix =  identityMatrix * this-&gt;rotationMatrix;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void Mesh::setOrigin(QVector3D origin)&#xD;&#xA;{&#xD;&#xA;    this-&gt;origin = origin;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;const QMatrix4x4 Mesh::getModelMatrix() const&#xD;&#xA;{&#xD;&#xA;    &#xD;&#xA;    return translationMatrix * rotationMatrix;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This function i want to implement:&#xD;&#xA;```&#xD;&#xA;void Mesh::moveAlongLocalAxis(QVector3D coordinates)&#xD;&#xA;{   &#xD;&#xA;    this-&gt;moveAlongGlobalAxis(coordinates); &#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;How i rotate my cube&#xD;&#xA;```&#xD;&#xA;else if(ev-&gt;key() == Qt::Key_R)&#xD;&#xA;    {&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        planeXY.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeXY1.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeZY.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeZY1.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeXZ.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeXZ1.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37476" PostHistoryTypeId="1" PostId="12780" RevisionGUID="5d22f44d-d21e-4df8-a6a4-2f4122340bae" CreationDate="2022-06-14T10:36:48.853" UserId="18526" Text="How to rotate and move group of objects in OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37477" PostHistoryTypeId="3" PostId="12780" RevisionGUID="5d22f44d-d21e-4df8-a6a4-2f4122340bae" CreationDate="2022-06-14T10:36:48.853" UserId="18526" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37479" PostHistoryTypeId="2" PostId="12781" RevisionGUID="78d88684-404a-4c3d-a8ee-0e53b3b2fd58" CreationDate="2022-06-14T15:04:34.937" UserId="18529" Text="Microsoft D3D11 [documentation][1] for **D3D11_RASTERIZER_DESC** structure writes:&#xD;&#xA;&#xD;&#xA;&gt;The settings of the MultisampleEnable and AntialiasedLineEnable members apply only to multisample antialiasing (MSAA) render targets (that is, render targets with sample counts greater than 1).&#xD;&#xA;&#xD;&#xA;Should I expect line rendering to be affected by those members only when I am rendering to a multisampled target and not when I am rendering on a &quot;single sampled&quot; one? &#xD;&#xA;&#xD;&#xA;When drawing a Line Strip I found line rasterization to be affected by those settings:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;What am I missing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_rasterizer_desc#remarks&#xD;&#xA;  [2]: https://i.stack.imgur.com/NQVha.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37481" PostHistoryTypeId="1" PostId="12781" RevisionGUID="78d88684-404a-4c3d-a8ee-0e53b3b2fd58" CreationDate="2022-06-14T15:04:34.937" UserId="18529" Text="D3D11 MultisampleEnable and AntialiasedLineEnable affecting line rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="37482" PostHistoryTypeId="3" PostId="12781" RevisionGUID="78d88684-404a-4c3d-a8ee-0e53b3b2fd58" CreationDate="2022-06-14T15:04:34.937" UserId="18529" Text="|antialiasing|directx11|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37483" PostHistoryTypeId="50" PostId="10248" RevisionGUID="d5bc15ae-5732-4385-83c1-d237aff3820c" CreationDate="2022-06-14T22:08:30.800" UserId="-1" />
  <row Id="37485" PostHistoryTypeId="5" PostId="12780" RevisionGUID="b9940079-f23f-4687-9788-233e67de3688" CreationDate="2022-06-15T07:02:36.843" UserId="13095" Comment="Fix some grammar" Text="What do I have now? &#xD;&#xA;I have a cube consisting of 6 planes. All these planes I generate in XY coordinates and then place them by matrix transformations.&#xD;&#xA;&#xD;&#xA;[![введите сюда описание изображения][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I need to rotate my cube along the global axis and move my planes along cube rotation;&#xD;&#xA;&#xD;&#xA;I rotate the cube &#xD;&#xA;[![введите сюда описание изображения][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then I need to move one of the planes correctly. But the planes move along the global axis. The red line shows how the plane moves now. The green line shows how it should move.&#xD;&#xA;[![введите сюда описание изображения][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PLe8w.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/elfwB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uZXso.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How I create a cube. All vertices are in the range (0,0) - (2, 2);&#xD;&#xA;```&#xD;&#xA;    planeXY.setupMesh();&#xD;&#xA;    planeXY.setOrigin({1, 1, 1});&#xD;&#xA;    &#xD;&#xA;    planeXY1.setupMesh();&#xD;&#xA;    planeXY1.setOrigin({1, 1, 1});&#xD;&#xA;    planeXY1.moveAlongGlobalAxis(QVector3D(0.0, 0.0, 2.0));&#xD;&#xA;    &#xD;&#xA;    planeZY.setupMesh();&#xD;&#xA;    planeZY.setOrigin({1, 1, 1});&#xD;&#xA;    planeZY.rotate(QVector3D(0.0f, -90.0f, 0.0f));&#xD;&#xA;    planeZY.moveAlongGlobalAxis(QVector3D(-2.0, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    planeZY1.setupMesh();&#xD;&#xA;    planeZY1.setOrigin({1, 1, 1});&#xD;&#xA;    planeZY1.rotate(QVector3D(0.0f, -90.0f, 0.0f));&#xD;&#xA;    &#xD;&#xA;    planeXZ.setupMesh();&#xD;&#xA;    planeXZ.setOrigin({1, 1, 1});&#xD;&#xA;    planeXZ.rotate(QVector3D(90.0f, 0.0f, 0.0f));&#xD;&#xA;    planeXZ.moveAlongGlobalAxis(QVector3D(0.0, -2.0, 0.0));&#xD;&#xA;    &#xD;&#xA;    planeXZ1.setupMesh();&#xD;&#xA;    planeXZ1.setOrigin({1, 1, 1});&#xD;&#xA;    planeXZ1.rotate(QVector3D(90.0f, 0.0f, 0.0f));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Mesh.cpp&#xD;&#xA;```&#xD;&#xA;void Mesh::moveAlongGlobalAxis(QVector3D coordinates)&#xD;&#xA;{&#xD;&#xA;    QMatrix4x4 identityMatrix;   &#xD;&#xA;    identityMatrix.translate(coordinates);&#xD;&#xA;    position += coordinates;&#xD;&#xA;    this-&gt;translationMatrix = identityMatrix * translationMatrix;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Mesh::moveAlongLocalAxis(QVector3D coordinates)&#xD;&#xA;{   &#xD;&#xA;    this-&gt;moveAlongGlobalAxis(coordinates); &#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void Mesh::rotate(QVector3D rotation)&#xD;&#xA;{&#xD;&#xA;    QMatrix4x4 identityMatrix;&#xD;&#xA;    &#xD;&#xA;    identityMatrix.translate((-1) * this-&gt;position + this-&gt;origin);&#xD;&#xA;    identityMatrix.rotate(rotation.x(), QVector3D(1.0, 0.0, 0.0));&#xD;&#xA;    identityMatrix.rotate(rotation.y(), QVector3D(0.0, 1.0, 0.0));&#xD;&#xA;    identityMatrix.rotate(rotation.z(), QVector3D(0.0, 0.0, 1.0));&#xD;&#xA;    identityMatrix.translate(this-&gt;position - this-&gt;origin);&#xD;&#xA;    this-&gt;rotationMatrix =  identityMatrix * this-&gt;rotationMatrix;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void Mesh::setOrigin(QVector3D origin)&#xD;&#xA;{&#xD;&#xA;    this-&gt;origin = origin;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;const QMatrix4x4 Mesh::getModelMatrix() const&#xD;&#xA;{&#xD;&#xA;    &#xD;&#xA;    return translationMatrix * rotationMatrix;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This function I want to implement:&#xD;&#xA;```&#xD;&#xA;void Mesh::moveAlongLocalAxis(QVector3D coordinates)&#xD;&#xA;{   &#xD;&#xA;    this-&gt;moveAlongGlobalAxis(coordinates); &#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;How I rotate my cube&#xD;&#xA;```&#xD;&#xA;else if(ev-&gt;key() == Qt::Key_R)&#xD;&#xA;    {&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        planeXY.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeXY1.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeZY.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeZY1.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeXZ.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;        planeXZ1.rotate(QVector3D(20.0f, 0.0f, 0.0f));&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37486" PostHistoryTypeId="2" PostId="12782" RevisionGUID="11c57bcf-e8ea-46cc-8fef-05bba0773d30" CreationDate="2022-06-15T08:13:19.737" UserId="13095" Text="Think about matrix multiplications as transforming data from one coordinate system to another. So initially, your cubes' local coordinate system is identical to the &quot;global&quot; coordinate system. Every translation in the &quot;global&quot; system along one of its coordinate axes is a single component in the translation vector. &#xD;&#xA;&#xD;&#xA;Now you rotate your cube and its local coordinate system so that they are no longer aligned with the &quot;global&quot; one. By the transformation order you chose, the translations are applied in the &quot;global&quot; system. If you want to apply a translation that was defined in your cubes' local coordinate system, you have to transform the translation vector into the &quot;global&quot; one first. In your case, the green line is one of the axes in the local coordinate system. So locally, the translation vector along this axis has one coordinate different from 0. But in the &quot;global&quot; one, all components might differ from 0. &#xD;&#xA;&#xD;&#xA;So how do we find this vector? Fortunately, it is pretty simple since you already know how to transform between both coordinate systems. You already did it with the cube. So just apply the **rotations** you used for your vertices.&#xD;&#xA;Unless I missed something in your code or made any other mistake, the function should look like this:&#xD;&#xA;&#xD;&#xA;~~~ cpp&#xD;&#xA;void Mesh::moveAlongLocalAxis(QVector3D coordinates)&#xD;&#xA;{   &#xD;&#xA;    // transform local translation to global coordinate system&#xD;&#xA;    coordinates = this-&gt;rotationMatrix * coordinates&#xD;&#xA;    this-&gt;moveAlongGlobalAxis(coordinates); &#xD;&#xA;}&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;Note that I oversimplified some things in the text above that was tailored to help you out with your specific problem.&#xD;&#xA;Coordinate systems and transformations are not particularly hard to understand, but it needs some time to adapt the correct mental model. You always have to keep in mind in which coordinate system you ended up after a set of transformations and how rotations and translations have to be applied to get you to the next one. I recommend [this site](https://learnopengl.com/Getting-started/Coordinate-Systems) to get a better understanding of the topic." ContentLicense="CC BY-SA 4.0" />
  <row Id="37493" PostHistoryTypeId="2" PostId="12784" RevisionGUID="735bdfc7-2381-4eb5-88ae-7d68e21542d4" CreationDate="2022-06-16T16:26:37.527" UserId="5256" Text="After rewriting the application to only render in the display function I have found what the bug was. The line was continuously rewriting on top of the vector in each frame as opposed to each mouse click release. Here is the fully working code. I have also implemented the suggestion above.&#xD;&#xA;&#xD;&#xA;header.h&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    int SCREEN_HEIGHT = 500;&#xD;&#xA;    &#xD;&#xA;    //Point class for taking the points&#xD;&#xA;    class Point {&#xD;&#xA;    public:&#xD;&#xA;        float x, y;&#xD;&#xA;    &#xD;&#xA;        void setxy(float x2, float y2)&#xD;&#xA;        {&#xD;&#xA;            x = x2; y = y2;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        //operator overloading for '=' sign&#xD;&#xA;        const Point&amp; operator=(const Point&amp; rPoint)&#xD;&#xA;        {&#xD;&#xA;            x = rPoint.x;&#xD;&#xA;            y = rPoint.y;&#xD;&#xA;            return *this;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    void drawDot(Point p1)&#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_POINTS);&#xD;&#xA;        glVertex2i(p1.x, p1.y);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void drawLine(Point p1, Point p2)&#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_LINE_STRIP);&#xD;&#xA;        glVertex2f(p1.x, p1.y);&#xD;&#xA;        glVertex2f(p2.x, p2.y);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float interpolate(float n1, float n2, float perc)&#xD;&#xA;    {&#xD;&#xA;        float diff = n2 - n1;&#xD;&#xA;    &#xD;&#xA;        return n1 + (diff * perc);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA;    #include &lt;GL/glut.h&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    #include &quot;header.h&quot;&#xD;&#xA;    &#xD;&#xA;    using namespace std;&#xD;&#xA;    &#xD;&#xA;    vector&lt;Point&gt; Points;&#xD;&#xA;    Point Tangent;&#xD;&#xA;    Point inverseTangent;&#xD;&#xA;    Point cursorLocationLive;&#xD;&#xA;    int TangentsSize = 0;&#xD;&#xA;    vector&lt;Point&gt; Tangents(TangentsSize);&#xD;&#xA;    vector&lt;Point&gt; inverseTangents(TangentsSize);&#xD;&#xA;    vector&lt;Point&gt; BezierCurve;&#xD;&#xA;    bool MouseReleased = false;&#xD;&#xA;    bool PrevMouse = false;&#xD;&#xA;    &#xD;&#xA;    void myMouse(int button, int state, int x, int y)&#xD;&#xA;    {&#xD;&#xA;        if (button == GLUT_LEFT_BUTTON)&#xD;&#xA;        {&#xD;&#xA;            if (state == GLUT_DOWN)&#xD;&#xA;            {&#xD;&#xA;                MouseReleased = false;&#xD;&#xA;                // Store points into Points vector on click&#xD;&#xA;                Point point;&#xD;&#xA;                point.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;                Points.push_back(point);&#xD;&#xA;    &#xD;&#xA;                // Tangents are set to the cursor position&#xD;&#xA;                Tangent.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;                inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;&#xD;&#xA;                inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;&#xD;&#xA;    &#xD;&#xA;                /*Add new element to Tangent &amp; inverseTangent so when we draw the curve&#xD;&#xA;                the tangents are accessed at the right index*/&#xD;&#xA;                TangentsSize++;&#xD;&#xA;            }&#xD;&#xA;            else if (state == GLUT_UP)&#xD;&#xA;            {&#xD;&#xA;                MouseReleased = true;&#xD;&#xA;                // Upon mouse release store tangent and inverse tangent into separate vectors&#xD;&#xA;                Tangents.push_back(Tangent);&#xD;&#xA;                inverseTangents.push_back(inverseTangent);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void passiveMotion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        // Sets the location of cursor while moving with no buttons pressed&#xD;&#xA;        cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        // Sets the coordinates of the tangents when mouse moves with a button held down&#xD;&#xA;        Tangent.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;        inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;&#xD;&#xA;        inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        // Draw main points in red&#xD;&#xA;        glColor3f(255, 0, 0);&#xD;&#xA;        for (int i = 0; i &lt; Points.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawDot(Points[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // If there is a starting point draw a line to cursor from last drawn point in passive motion&#xD;&#xA;        if (Points.size() &gt; 0)&#xD;&#xA;        {&#xD;&#xA;            glColor3f(0, 0, 0);&#xD;&#xA;            drawLine(Points[Points.size() - 1], cursorLocationLive);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Draw live tangent dots in green&#xD;&#xA;        glColor3f(0, 255, 0);&#xD;&#xA;        drawDot(Tangent);&#xD;&#xA;        drawDot(inverseTangent);&#xD;&#xA;        // Draw live tangent lines in blue&#xD;&#xA;        glColor3f(0, 0, 255);&#xD;&#xA;        drawLine(Tangent, inverseTangent);&#xD;&#xA;    &#xD;&#xA;        for (int i = 0; i &lt; Tangents.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            // Draw stored tangent dots in green&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawDot(Tangents[i]);&#xD;&#xA;            drawDot(inverseTangents[i]);&#xD;&#xA;            // Draw stored tangent lines in blue&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawLine(Tangents[i], inverseTangents[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Loop through all points&#xD;&#xA;        if (Points.size() &gt;= 2)&#xD;&#xA;        {&#xD;&#xA;            // p1 is the start of the curve set to second last point&#xD;&#xA;            Point p1;&#xD;&#xA;            p1 = Points[Points.size() - 2];&#xD;&#xA;    &#xD;&#xA;            float i;&#xD;&#xA;            // Calculate curve coordinates&#xD;&#xA;            for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;            {&#xD;&#xA;                i = j / 100;&#xD;&#xA;                // The Green Lines&#xD;&#xA;                float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);&#xD;&#xA;                float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);&#xD;&#xA;                float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);&#xD;&#xA;                float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);&#xD;&#xA;                float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);&#xD;&#xA;                float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);&#xD;&#xA;    &#xD;&#xA;                // The Blue Line&#xD;&#xA;                float xm = interpolate(xa, xb, i);&#xD;&#xA;                float ym = interpolate(ya, yb, i);&#xD;&#xA;                float xn = interpolate(xb, xc, i);&#xD;&#xA;                float yn = interpolate(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                // The Black Dot&#xD;&#xA;                float x2 = interpolate(xm, xn, i);&#xD;&#xA;                float y2 = interpolate(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                Point p2;&#xD;&#xA;                p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                glColor3f(0, 0, 0);&#xD;&#xA;                drawLine(p1, p2);&#xD;&#xA;    &#xD;&#xA;                p1 = p2;&#xD;&#xA;    &#xD;&#xA;                // Prevents curves generated during mouse motion from being stored&#xD;&#xA;                if (PrevMouse == false &amp;&amp; MouseReleased == true)&#xD;&#xA;                {&#xD;&#xA;                    // Store curvature into Bezier Points&#xD;&#xA;                    BezierCurve.push_back(p2);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // When the mouse is down PrevMouse = false so when the mouse is released&#xD;&#xA;        // the if statement evaluates to true and stores the new curvature once&#xD;&#xA;        // and then sets PrevMouse to true to prevent writing on top of the vector&#xD;&#xA;        PrevMouse = MouseReleased;&#xD;&#xA;    &#xD;&#xA;        // Draw all bezier curvature&#xD;&#xA;        for (int i = 1; i &lt; BezierCurve.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(BezierCurve[i - 1], BezierCurve[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void timer(int)&#xD;&#xA;    {&#xD;&#xA;        glutTimerFunc(1000 / 60, timer, 0);&#xD;&#xA;        glutPostRedisplay();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char* argv[]) {&#xD;&#xA;        glutInit(&amp;argc, argv);&#xD;&#xA;        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);&#xD;&#xA;        glutInitWindowSize(640, 500);&#xD;&#xA;        glutInitWindowPosition(100, 150);&#xD;&#xA;        glutCreateWindow(&quot;Bezier Curve&quot;);&#xD;&#xA;        glutDisplayFunc(myDisplay);&#xD;&#xA;        glutIdleFunc(myDisplay);&#xD;&#xA;        glutTimerFunc(0, timer, 0);&#xD;&#xA;        glutMouseFunc(myMouse);&#xD;&#xA;        glutPassiveMotionFunc(passiveMotion);&#xD;&#xA;        glutMotionFunc(motion);&#xD;&#xA;        glClearColor(255, 255, 255, 0.0);&#xD;&#xA;        glPointSize(3);&#xD;&#xA;        glMatrixMode(GL_PROJECTION);&#xD;&#xA;        glLoadIdentity();&#xD;&#xA;        gluOrtho2D(0.0, 640.0, 0.0, 500.0);&#xD;&#xA;        glutMainLoop();&#xD;&#xA;    &#xD;&#xA;        return 0;&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="37495" PostHistoryTypeId="5" PostId="12784" RevisionGUID="5b27dee5-fce4-41b1-b579-e692fc8a6d94" CreationDate="2022-06-16T16:45:02.370" UserId="5256" Comment="added 32 characters in body" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;After rewriting the application to only render in the display function I have found what the bug was. The line was continuously rewriting on top of the vector in each frame as opposed to each mouse click release. Here is the fully working code. I have also implemented the suggestion above using floating-point variables. A more thorough explanation can be found [here][2]: &#xD;&#xA;&#xD;&#xA;header.h&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    int SCREEN_HEIGHT = 500;&#xD;&#xA;    &#xD;&#xA;    //Point class for taking the points&#xD;&#xA;    class Point {&#xD;&#xA;    public:&#xD;&#xA;        float x, y;&#xD;&#xA;    &#xD;&#xA;        void setxy(float x2, float y2)&#xD;&#xA;        {&#xD;&#xA;            x = x2; y = y2;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        //operator overloading for '=' sign&#xD;&#xA;        const Point&amp; operator=(const Point&amp; rPoint)&#xD;&#xA;        {&#xD;&#xA;            x = rPoint.x;&#xD;&#xA;            y = rPoint.y;&#xD;&#xA;            return *this;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    void drawDot(Point p1)&#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_POINTS);&#xD;&#xA;        glVertex2i(p1.x, p1.y);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void drawLine(Point p1, Point p2)&#xD;&#xA;    {&#xD;&#xA;        glBegin(GL_LINE_STRIP);&#xD;&#xA;        glVertex2f(p1.x, p1.y);&#xD;&#xA;        glVertex2f(p2.x, p2.y);&#xD;&#xA;        glEnd();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float interpolate(float n1, float n2, float perc)&#xD;&#xA;    {&#xD;&#xA;        float diff = n2 - n1;&#xD;&#xA;    &#xD;&#xA;        return n1 + (diff * perc);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;main.cpp&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA;    #include &lt;GL/glut.h&gt;&#xD;&#xA;    #include &lt;vector&gt;&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;    #include &quot;header.h&quot;&#xD;&#xA;    &#xD;&#xA;    using namespace std;&#xD;&#xA;    &#xD;&#xA;    vector&lt;Point&gt; Points;&#xD;&#xA;    Point Tangent;&#xD;&#xA;    Point inverseTangent;&#xD;&#xA;    Point cursorLocationLive;&#xD;&#xA;    int TangentsSize = 0;&#xD;&#xA;    vector&lt;Point&gt; Tangents(TangentsSize);&#xD;&#xA;    vector&lt;Point&gt; inverseTangents(TangentsSize);&#xD;&#xA;    vector&lt;Point&gt; BezierCurve;&#xD;&#xA;    bool MouseReleased = false;&#xD;&#xA;    bool PrevMouse = false;&#xD;&#xA;    &#xD;&#xA;    void myMouse(int button, int state, int x, int y)&#xD;&#xA;    {&#xD;&#xA;        if (button == GLUT_LEFT_BUTTON)&#xD;&#xA;        {&#xD;&#xA;            if (state == GLUT_DOWN)&#xD;&#xA;            {&#xD;&#xA;                MouseReleased = false;&#xD;&#xA;                // Store points into Points vector on click&#xD;&#xA;                Point point;&#xD;&#xA;                point.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;                Points.push_back(point);&#xD;&#xA;    &#xD;&#xA;                // Tangents are set to the cursor position&#xD;&#xA;                Tangent.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;                inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;&#xD;&#xA;                inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;&#xD;&#xA;    &#xD;&#xA;                /*Add new element to Tangent &amp; inverseTangent so when we draw the curve&#xD;&#xA;                the tangents are accessed at the right index*/&#xD;&#xA;                TangentsSize++;&#xD;&#xA;            }&#xD;&#xA;            else if (state == GLUT_UP)&#xD;&#xA;            {&#xD;&#xA;                MouseReleased = true;&#xD;&#xA;                // Upon mouse release store tangent and inverse tangent into separate vectors&#xD;&#xA;                Tangents.push_back(Tangent);&#xD;&#xA;                inverseTangents.push_back(inverseTangent);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void passiveMotion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        // Sets the location of cursor while moving with no buttons pressed&#xD;&#xA;        cursorLocationLive.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void motion(int x, int y)&#xD;&#xA;    {&#xD;&#xA;        // Sets the coordinates of the tangents when mouse moves with a button held down&#xD;&#xA;        Tangent.setxy(x, SCREEN_HEIGHT - y);&#xD;&#xA;        inverseTangent.x = (2 * Points[Points.size() - 1].x) - Tangent.x;&#xD;&#xA;        inverseTangent.y = (2 * Points[Points.size() - 1].y) - Tangent.y;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void myDisplay()&#xD;&#xA;    {&#xD;&#xA;        glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    &#xD;&#xA;        // Draw main points in red&#xD;&#xA;        glColor3f(255, 0, 0);&#xD;&#xA;        for (int i = 0; i &lt; Points.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawDot(Points[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // If there is a starting point draw a line to cursor from last drawn point in passive motion&#xD;&#xA;        if (Points.size() &gt; 0)&#xD;&#xA;        {&#xD;&#xA;            glColor3f(0, 0, 0);&#xD;&#xA;            drawLine(Points[Points.size() - 1], cursorLocationLive);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Draw live tangent dots in green&#xD;&#xA;        glColor3f(0, 255, 0);&#xD;&#xA;        drawDot(Tangent);&#xD;&#xA;        drawDot(inverseTangent);&#xD;&#xA;        // Draw live tangent lines in blue&#xD;&#xA;        glColor3f(0, 0, 255);&#xD;&#xA;        drawLine(Tangent, inverseTangent);&#xD;&#xA;    &#xD;&#xA;        for (int i = 0; i &lt; Tangents.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            // Draw stored tangent dots in green&#xD;&#xA;            glColor3f(0, 255, 0);&#xD;&#xA;            drawDot(Tangents[i]);&#xD;&#xA;            drawDot(inverseTangents[i]);&#xD;&#xA;            // Draw stored tangent lines in blue&#xD;&#xA;            glColor3f(0, 0, 255);&#xD;&#xA;            drawLine(Tangents[i], inverseTangents[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // Loop through all points&#xD;&#xA;        if (Points.size() &gt;= 2)&#xD;&#xA;        {&#xD;&#xA;            // p1 is the start of the curve set to second last point&#xD;&#xA;            Point p1;&#xD;&#xA;            p1 = Points[Points.size() - 2];&#xD;&#xA;    &#xD;&#xA;            float i;&#xD;&#xA;            // Calculate curve coordinates&#xD;&#xA;            for (float j = 0; j &lt;= 100; j++)&#xD;&#xA;            {&#xD;&#xA;                i = j / 100;&#xD;&#xA;                // The Green Lines&#xD;&#xA;                float xa = interpolate(Points[Points.size() - 2].x, Tangents[TangentsSize - 2].x, i);&#xD;&#xA;                float ya = interpolate(Points[Points.size() - 2].y, Tangents[TangentsSize - 2].y, i);&#xD;&#xA;                float xb = interpolate(Tangents[TangentsSize - 2].x, inverseTangent.x, i);&#xD;&#xA;                float yb = interpolate(Tangents[TangentsSize - 2].y, inverseTangent.y, i);&#xD;&#xA;                float xc = interpolate(inverseTangent.x, Points[Points.size() - 1].x, i);&#xD;&#xA;                float yc = interpolate(inverseTangent.y, Points[Points.size() - 1].y, i);&#xD;&#xA;    &#xD;&#xA;                // The Blue Line&#xD;&#xA;                float xm = interpolate(xa, xb, i);&#xD;&#xA;                float ym = interpolate(ya, yb, i);&#xD;&#xA;                float xn = interpolate(xb, xc, i);&#xD;&#xA;                float yn = interpolate(yb, yc, i);&#xD;&#xA;    &#xD;&#xA;                // The Black Dot&#xD;&#xA;                float x2 = interpolate(xm, xn, i);&#xD;&#xA;                float y2 = interpolate(ym, yn, i);&#xD;&#xA;    &#xD;&#xA;                Point p2;&#xD;&#xA;                p2.setxy(x2, y2);&#xD;&#xA;    &#xD;&#xA;                glColor3f(0, 0, 0);&#xD;&#xA;                drawLine(p1, p2);&#xD;&#xA;    &#xD;&#xA;                p1 = p2;&#xD;&#xA;    &#xD;&#xA;                // Prevents curves generated during mouse motion from being stored&#xD;&#xA;                if (PrevMouse == false &amp;&amp; MouseReleased == true)&#xD;&#xA;                {&#xD;&#xA;                    // Store curvature into Bezier Points&#xD;&#xA;                    BezierCurve.push_back(p2);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // When the mouse is down PrevMouse = false so when the mouse is released&#xD;&#xA;        // the if statement evaluates to true and stores the new curvature once&#xD;&#xA;        // and then sets PrevMouse to true to prevent writing on top of the vector&#xD;&#xA;        PrevMouse = MouseReleased;&#xD;&#xA;    &#xD;&#xA;        // Draw all bezier curvature&#xD;&#xA;        for (int i = 1; i &lt; BezierCurve.size(); i++)&#xD;&#xA;        {&#xD;&#xA;            drawLine(BezierCurve[i - 1], BezierCurve[i]);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        glutSwapBuffers();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void timer(int)&#xD;&#xA;    {&#xD;&#xA;        glutTimerFunc(1000 / 60, timer, 0);&#xD;&#xA;        glutPostRedisplay();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    int main(int argc, char* argv[]) {&#xD;&#xA;        glutInit(&amp;argc, argv);&#xD;&#xA;        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);&#xD;&#xA;        glutInitWindowSize(640, 500);&#xD;&#xA;        glutInitWindowPosition(100, 150);&#xD;&#xA;        glutCreateWindow(&quot;Bezier Curve&quot;);&#xD;&#xA;        glutDisplayFunc(myDisplay);&#xD;&#xA;        glutIdleFunc(myDisplay);&#xD;&#xA;        glutTimerFunc(0, timer, 0);&#xD;&#xA;        glutMouseFunc(myMouse);&#xD;&#xA;        glutPassiveMotionFunc(passiveMotion);&#xD;&#xA;        glutMotionFunc(motion);&#xD;&#xA;        glClearColor(255, 255, 255, 0.0);&#xD;&#xA;        glPointSize(3);&#xD;&#xA;        glMatrixMode(GL_PROJECTION);&#xD;&#xA;        glLoadIdentity();&#xD;&#xA;        gluOrtho2D(0.0, 640.0, 0.0, 500.0);&#xD;&#xA;        glutMainLoop();&#xD;&#xA;    &#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gzxt0.gif&#xD;&#xA;  [2]: https://stackoverflow.com/questions/72312477/how-to-clear-my-beziercurve-vector-to-stop-writing-coordinates-on-top-of-each-ot" ContentLicense="CC BY-SA 4.0" />
  <row Id="37501" PostHistoryTypeId="2" PostId="12786" RevisionGUID="1e5d22c8-1d62-4ab1-86e5-6fd19b698c31" CreationDate="2022-06-17T02:21:44.213" UserId="11058" Text="On CPU dynamic arrays are often used to store data of dynamic size, and often implemented by doubling the size when the array is full and copying the data over. The data structure has amortized O(1) performance.&#xD;&#xA;&#xD;&#xA;But is similar approach ever used and is practical GPU? Specifically for a similar scenario to when it is useful on CPU, for dynamically adding data into it?&#xD;&#xA;&#xD;&#xA;On GPU we allocate a buffer and upload data to the buffer. We could make the buffer &quot;dynamic&quot; by reallocating double the size when it gets full, and copying the old data over to the new buffer. But how performance effective would this be?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37503" PostHistoryTypeId="1" PostId="12786" RevisionGUID="1e5d22c8-1d62-4ab1-86e5-6fd19b698c31" CreationDate="2022-06-17T02:21:44.213" UserId="11058" Text="Dynamic array approach for GPU buffers" ContentLicense="CC BY-SA 4.0" />
  <row Id="37504" PostHistoryTypeId="3" PostId="12786" RevisionGUID="1e5d22c8-1d62-4ab1-86e5-6fd19b698c31" CreationDate="2022-06-17T02:21:44.213" UserId="11058" Text="|gpu|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37505" PostHistoryTypeId="50" PostId="9199" RevisionGUID="0ac165a1-d6bb-40af-9104-0d31fc756984" CreationDate="2022-06-17T04:03:45.217" UserId="-1" />
  <row Id="37506" PostHistoryTypeId="50" PostId="12691" RevisionGUID="a2c445e3-525d-4f3e-b125-4f62094ea552" CreationDate="2022-06-17T11:05:30.507" UserId="-1" />
  <row Id="37507" PostHistoryTypeId="2" PostId="12787" RevisionGUID="33bd86a7-f521-4981-91a3-6f7c11470a91" CreationDate="2022-06-17T13:23:04.863" UserId="9912" Text="I started working on a &quot;stylus annotation program&quot;, and as part of it I need an algorithm that convert a path with width indicators to an outline. This is similar to the Advanced Outline Layer in the synfig program, and the Power Stroke path effect in Inkscape. I'm looking for a paper describing such an algorithm. Of course I can always read the source code, but I'd prefer a paper to understand the mathematics behind it." ContentLicense="CC BY-SA 4.0" />
  <row Id="37509" PostHistoryTypeId="1" PostId="12787" RevisionGUID="33bd86a7-f521-4981-91a3-6f7c11470a91" CreationDate="2022-06-17T13:23:04.863" UserId="9912" Text="Converting a Bezier Path with variable width stroke to an outline?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37510" PostHistoryTypeId="3" PostId="12787" RevisionGUID="33bd86a7-f521-4981-91a3-6f7c11470a91" CreationDate="2022-06-17T13:23:04.863" UserId="9912" Text="|mathematics|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37512" PostHistoryTypeId="50" PostId="10025" RevisionGUID="b4ea5f26-cb7d-474f-a980-2a10e54b86ce" CreationDate="2022-06-18T02:05:55.543" UserId="-1" />
  <row Id="37513" PostHistoryTypeId="2" PostId="12788" RevisionGUID="5f96d947-23a2-4356-bd2f-8330980ce81b" CreationDate="2022-06-18T09:35:31.973" UserId="9157" Text="So I need to have a texture size for my compute shader.  I found this function in GLSL to query this inside the shader:&#xD;&#xA;&#xD;&#xA;    ivec2 textureSize = imageSize(outputImage)&#xD;&#xA;&#xD;&#xA;My question is, is this less efficient than passing the texture size as a push constant for instance?&#xD;&#xA;&#xD;&#xA;Also is there an increased cost if for instance I put this inside a loop and call it multiple times in the same shader invocation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37515" PostHistoryTypeId="1" PostId="12788" RevisionGUID="5f96d947-23a2-4356-bd2f-8330980ce81b" CreationDate="2022-06-18T09:35:31.973" UserId="9157" Text="Is there a cost to querying a texture side inside a GLSL shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37516" PostHistoryTypeId="3" PostId="12788" RevisionGUID="5f96d947-23a2-4356-bd2f-8330980ce81b" CreationDate="2022-06-18T09:35:31.973" UserId="9157" Text="|glsl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37517" PostHistoryTypeId="50" PostId="9267" RevisionGUID="d1e042ca-5ddd-482a-a46a-6cadce04c9d3" CreationDate="2022-06-18T10:06:20.687" UserId="-1" />
  <row Id="37518" PostHistoryTypeId="4" PostId="12788" RevisionGUID="8a5dc048-46e5-4411-ab61-7c1c9b856f82" CreationDate="2022-06-18T10:29:55.277" UserId="7952" Comment="changed side to size in title" Text="Is there a cost to querying a texture size inside a GLSL shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37519" PostHistoryTypeId="2" PostId="12789" RevisionGUID="6ab783e1-1b77-4d9e-bcf0-a9d88f79f49b" CreationDate="2022-06-18T10:47:48.110" UserId="7952" Text="In order for the GPU to work with textures through samplers, the driver needs to know the textures dimensions, and a good implementation will be able to access those dimension much more easily/quickly then passing them around in buffers or as push constants. If the shader is already accessing the texture then those values should be sitting in the cache or a register.&#xD;&#xA;&#xD;&#xA;Based on that I would always use the shader function and would only change to another method if profiling data showed otherwise. (It is always best to profile, blanket statements about performance are almost always wrong for some implementation)" ContentLicense="CC BY-SA 4.0" />
  <row Id="37521" PostHistoryTypeId="50" PostId="12700" RevisionGUID="b202cc42-06c1-46d7-a55b-de4932e48a10" CreationDate="2022-06-18T14:04:40.423" UserId="-1" />
  <row Id="37522" PostHistoryTypeId="50" PostId="8935" RevisionGUID="d9dd20d8-d442-45ea-886f-4e157f64cfbc" CreationDate="2022-06-19T00:07:20.703" UserId="-1" />
  <row Id="37524" PostHistoryTypeId="2" PostId="12790" RevisionGUID="2a3f0492-fffb-49fc-a642-c434cb151e76" CreationDate="2022-06-19T10:05:57.850" UserId="9157" Text="I would like to declare a function which reads from an image2D and modifies the output.&#xD;&#xA;&#xD;&#xA;My shader is written like so:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;...&#xD;&#xA;layout(binding = 1, rg32f) uniform readonly image2D uVelocity;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;vec2 loadVelocity(image2D velocity, ivec2 index) {&#xD;&#xA;    ...&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    ...&#xD;&#xA;    vec2 v = loadVelocity(uVelocity, coord);&#xD;&#xA;    ...&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;When I try to compile this shader to SPIRV, I get the following errors:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&gt;'readonly' : argument cannot drop memory qualifier when passed to formal parameter &#xD;&#xA;&#xD;&#xA;&gt;'format' : image formats must match &#xD;&#xA;&#xD;&#xA;So it seems that the function declaration is not specific enough to allow this image to be used.&#xD;&#xA;&#xD;&#xA;I have tried adding `readonly` to the function arg declaration, and this silences the first error, but how can I declare the format?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37526" PostHistoryTypeId="1" PostId="12790" RevisionGUID="2a3f0492-fffb-49fc-a642-c434cb151e76" CreationDate="2022-06-19T10:05:57.850" UserId="9157" Text="Problem when passing a readonly image2D to a function" ContentLicense="CC BY-SA 4.0" />
  <row Id="37527" PostHistoryTypeId="3" PostId="12790" RevisionGUID="2a3f0492-fffb-49fc-a642-c434cb151e76" CreationDate="2022-06-19T10:05:57.850" UserId="9157" Text="|glsl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37528" PostHistoryTypeId="50" PostId="12675" RevisionGUID="4eeb46f6-b4fa-4180-a024-c649649a30d0" CreationDate="2022-06-19T11:00:50.087" UserId="-1" />
  <row Id="37529" PostHistoryTypeId="2" PostId="12791" RevisionGUID="119dc4da-63fb-4610-80d7-9549e85fa3fe" CreationDate="2022-06-19T17:57:29.593" UserId="5256" Text="I am following this [tutorial][1] on how to host Win32 OpenGL windows in WPF. There is also a Microsoft walkthrough on how to [Host a Win32 Control in WPF][2] that is useful aswell. The original project is from 2009 and uses managed C++. I have rebuilt the program using the same source code (a few modifications due to debugging) using a C++ CLR Class Library. I use the compiled DLL in C# WPF however, when I run the program I get a blank window as opposed to the triangle in the tutorial.&#xD;&#xA;&#xD;&#xA;I was wondering if someone could take a look at my program and see why nothing is rendering.&#xD;&#xA;&#xD;&#xA;What the original program renders:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What I am getting:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;OpenGLCpp.h&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    // Exclude rarely used parts of the windows headers&#xD;&#xA;    #define WIN32_LEAN_AND_MEAN&#xD;&#xA;    &#xD;&#xA;    #include &lt;Windows.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;Helper.h&quot;&#xD;&#xA;    #include &quot;OpenGL.h&quot;&#xD;&#xA;    &#xD;&#xA;    // To use these, we must add some references...&#xD;&#xA;    //	o PresentationFramework (for HwndHost)&#xD;&#xA;    //		* PresentationCore&#xD;&#xA;    //		* WindowsBase&#xD;&#xA;    using namespace System;&#xD;&#xA;    using namespace System::Windows;&#xD;&#xA;    using namespace System::Windows::Interop;&#xD;&#xA;    using namespace System::Windows::Input;&#xD;&#xA;    using namespace System::Windows::Media;&#xD;&#xA;    using namespace System::Runtime::InteropServices;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLCpp &#xD;&#xA;    {&#xD;&#xA;    	LRESULT WINAPI MyMsgProc(HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam)&#xD;&#xA;    	{&#xD;&#xA;    		switch (_msg)&#xD;&#xA;    		{&#xD;&#xA;    			// Make sure the window gets focus when it has to!&#xD;&#xA;    		case WM_IME_SETCONTEXT:&#xD;&#xA;    			// LOWORD(wParam) = 0 stands for deactivation, so don't set&#xD;&#xA;    			// focus then (results in a rather, err... 'greedy' window...)&#xD;&#xA;    			if (LOWORD(_wParam) &gt; 0)&#xD;&#xA;    				SetFocus(_hWnd);&#xD;&#xA;    &#xD;&#xA;    			return 0;&#xD;&#xA;    &#xD;&#xA;    		default:&#xD;&#xA;    			return DefWindowProc(_hWnd, _msg, _wParam, _lParam);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	//&#xD;&#xA;    	// This class implements HwndHost&#xD;&#xA;    	//&#xD;&#xA;    	// We have to overwrite BuildWindowCore and DestroyWindowCore&#xD;&#xA;    	//&#xD;&#xA;    	// A very simple example which creates a Win32 ListBox can be found in the MSDN:&#xD;&#xA;    	// http://msdn2.microsoft.com/en-us/library/aa970061.aspx&#xD;&#xA;    	//&#xD;&#xA;    	public ref class OpenGLHwnd : public HwndHost&#xD;&#xA;    	{&#xD;&#xA;    	public:&#xD;&#xA;    		OpenGLHwnd() : m_hRC(NULL),&#xD;&#xA;    			m_hDC(NULL),&#xD;&#xA;    			m_hWnd(NULL),&#xD;&#xA;    			m_hInstance(NULL),&#xD;&#xA;    			m_sWindowName(NULL),&#xD;&#xA;    			m_sClassName(NULL),&#xD;&#xA;    			m_fRotationAngle(0.0f)&#xD;&#xA;    		{&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    	private:&#xD;&#xA;    		HGLRC					m_hRC;&#xD;&#xA;    		HDC						m_hDC;&#xD;&#xA;    		HWND					m_hWnd;&#xD;&#xA;    		HINSTANCE				m_hInstance;&#xD;&#xA;    		LPCWSTR					m_sWindowName;&#xD;&#xA;    		LPCWSTR					m_sClassName;&#xD;&#xA;    &#xD;&#xA;    		float					m_fRotationAngle;&#xD;&#xA;    &#xD;&#xA;    		// DPI Scaling&#xD;&#xA;    		double					m_dScaleX;&#xD;&#xA;    		double					m_dScaleY;&#xD;&#xA;    &#xD;&#xA;    	protected:&#xD;&#xA;    		/*virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool% handled) override&#xD;&#xA;    		{&#xD;&#xA;    			switch( msg )&#xD;&#xA;    			{&#xD;&#xA;    				case WM_IME_SETCONTEXT:&#xD;&#xA;    					if(LOWORD(wParam.ToInt32()) &gt; 0)&#xD;&#xA;    						SetFocus(m_hWnd);&#xD;&#xA;    &#xD;&#xA;    					handled = true;&#xD;&#xA;    					return System::IntPtr::Zero;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			handled = false;&#xD;&#xA;    			return System::IntPtr::Zero;&#xD;&#xA;    		}*/&#xD;&#xA;    	public:&#xD;&#xA;    		virtual void OnRenderSizeChanged(SizeChangedInfo^ sizeInfo) override&#xD;&#xA;    		{&#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			// Apply DPI correction&#xD;&#xA;    			// NOTE: sizeInfo-&gt;NewSize contains doubles, so we do the multiplication before&#xD;&#xA;    			// converting to int.&#xD;&#xA;    			int iHeight = (int)(sizeInfo-&gt;NewSize.Height * m_dScaleY);&#xD;&#xA;    			int iWidth = (int)(sizeInfo-&gt;NewSize.Width * m_dScaleX);&#xD;&#xA;    &#xD;&#xA;    			if (iWidth == 0 || iHeight == 0)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    			glViewport(0, 0, iWidth, iHeight);&#xD;&#xA;    &#xD;&#xA;    			glMatrixMode(GL_PROJECTION);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    			glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 100.0);&#xD;&#xA;    			// gluPerspective( 67.5, ((double)(iWidth) / (double)(iHeight)), 1.0, 500.0);&#xD;&#xA;    			glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// Communicating with this method will be considerably more complicated in a real-&#xD;&#xA;    		// world application...&#xD;&#xA;    		//&#xD;&#xA;    		virtual void OnRender(System::Windows::Media::DrawingContext^ drawingContext) override&#xD;&#xA;    		{&#xD;&#xA;    			UNREF(drawingContext);&#xD;&#xA;    &#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    &#xD;&#xA;    			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    &#xD;&#xA;    			glTranslatef(0.0f, 0.0f, -2.6f);&#xD;&#xA;    			glRotatef(m_fRotationAngle, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glBegin(GL_TRIANGLES);&#xD;&#xA;    			glColor3f(1.0f, 0.0f, 0.0f);	glVertex3f(-1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 1.0f, 0.0f);	glVertex3f(0.0f, 1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 0.0f, 1.0f);	glVertex3f(1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glEnd();&#xD;&#xA;    &#xD;&#xA;    			glFlush();&#xD;&#xA;    			SwapBuffers(m_hDC); // NOTE: This is no longer wglSwapBuffers&#xD;&#xA;    &#xD;&#xA;    			// For constant rotation speed, and correct rotation speeds on different machines,&#xD;&#xA;    			// we'd need a timer here. However, I don't want to bloat the example code.&#xD;&#xA;    			m_fRotationAngle += 1.0;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		virtual void DestroyWindowCore(HandleRef hwnd) override&#xD;&#xA;    		{&#xD;&#xA;    			if (NULL != m_hRC)&#xD;&#xA;    			{&#xD;&#xA;    				wglDeleteContext(m_hRC);&#xD;&#xA;    				m_hRC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; NULL != m_hDC)&#xD;&#xA;    			{&#xD;&#xA;    				ReleaseDC(m_hWnd, m_hDC);&#xD;&#xA;    				m_hDC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; m_hWnd == (HWND)hwnd.Handle.ToPointer())&#xD;&#xA;    			{&#xD;&#xA;    				::DestroyWindow(m_hWnd);&#xD;&#xA;    				m_hWnd = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			UnregisterClass(m_sClassName, m_hInstance);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		bool RegisterWindowClass()&#xD;&#xA;    		{&#xD;&#xA;    			//&#xD;&#xA;    			// Create custom WNDCLASS&#xD;&#xA;    			//&#xD;&#xA;    			WNDCLASS wndClass;&#xD;&#xA;    &#xD;&#xA;    			if (GetClassInfo(m_hInstance, m_sClassName, &amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				// Class is already registered!&#xD;&#xA;    				return true;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;&#xD;&#xA;    &#xD;&#xA;    			// Not providing a WNDPROC here results in a crash on my system:&#xD;&#xA;    			wndClass.lpfnWndProc = (WNDPROC)MyMsgProc;&#xD;&#xA;    			wndClass.cbClsExtra = 0;&#xD;&#xA;    			wndClass.cbWndExtra = 0;&#xD;&#xA;    			wndClass.hInstance = m_hInstance;&#xD;&#xA;    			wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);&#xD;&#xA;    			wndClass.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;    			wndClass.hbrBackground = 0;&#xD;&#xA;    			wndClass.lpszMenuName = 0; // No menu&#xD;&#xA;    			wndClass.lpszClassName = m_sClassName;&#xD;&#xA;    &#xD;&#xA;    			// ... and register it&#xD;&#xA;    			if (!RegisterClass(&amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				Helper::ErrorExit(L&quot;RegisterWindowClass&quot;);&#xD;&#xA;    				return false;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return true;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// This is the key method to override&#xD;&#xA;    		//&#xD;&#xA;    		virtual HandleRef BuildWindowCore(HandleRef hwndParent) override&#xD;&#xA;    		{&#xD;&#xA;    			// Get HINSTANCE&#xD;&#xA;    			m_hInstance = (HINSTANCE)GetModuleHandle(NULL);&#xD;&#xA;    			m_sWindowName = L&quot;OpenGL in HwndHost&quot;;&#xD;&#xA;    			m_sClassName = L&quot;OGLClassHwnd&quot;;&#xD;&#xA;    &#xD;&#xA;    			if (RegisterWindowClass())&#xD;&#xA;    			{&#xD;&#xA;    				// some default size&#xD;&#xA;    				int iWidth = 2;&#xD;&#xA;    				int iHeight = 2;&#xD;&#xA;    &#xD;&#xA;    				DWORD dwStyle = WS_CHILD | WS_VISIBLE;&#xD;&#xA;    &#xD;&#xA;    				// Get the parent (WPF) Hwnd. This is important: Windows won't let you create&#xD;&#xA;    				// the Hwnd otherwise.&#xD;&#xA;    				HWND parentHwnd = (HWND)hwndParent.Handle.ToPointer();&#xD;&#xA;    &#xD;&#xA;    				m_hWnd = CreateWindowEx(0,&#xD;&#xA;    					m_sClassName,&#xD;&#xA;    					m_sWindowName,&#xD;&#xA;    					dwStyle,&#xD;&#xA;    					0,	// X Pos&#xD;&#xA;    					0,	// Y Pos&#xD;&#xA;    					iWidth,&#xD;&#xA;    					iHeight,&#xD;&#xA;    					parentHwnd, // Parent&#xD;&#xA;    					0,	// Menu&#xD;&#xA;    					m_hInstance,&#xD;&#xA;    					0); // Param&#xD;&#xA;    &#xD;&#xA;    				if (!m_hWnd)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hDC = GetDC(m_hWnd);&#xD;&#xA;    				if (!m_hDC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Create PixelFormatDescriptor and choose pixel format&#xD;&#xA;    				//&#xD;&#xA;    				uint PixelFormat;&#xD;&#xA;    &#xD;&#xA;    				BYTE iAlphaBits = 0;&#xD;&#xA;    				BYTE iColorBits = 32;&#xD;&#xA;    				BYTE iDepthBits = 16;&#xD;&#xA;    				BYTE iAccumBits = 0;&#xD;&#xA;    				BYTE iStencilBits = 0;&#xD;&#xA;    &#xD;&#xA;    				static PIXELFORMATDESCRIPTOR pfd =&#xD;&#xA;    				{&#xD;&#xA;    					sizeof(PIXELFORMATDESCRIPTOR),	//size&#xD;&#xA;    					1,								//version&#xD;&#xA;    					PFD_DRAW_TO_WINDOW |				//flags&#xD;&#xA;    					PFD_SUPPORT_OPENGL |&#xD;&#xA;    					PFD_DOUBLEBUFFER,&#xD;&#xA;    					PFD_TYPE_RGBA,					//pixeltype&#xD;&#xA;    					iColorBits,&#xD;&#xA;    					0, 0, 0, 0, 0, 0,				//color bits ignored&#xD;&#xA;    					iAlphaBits,&#xD;&#xA;    					0,								//alpha shift ignored&#xD;&#xA;    					iAccumBits,						//accum. buffer&#xD;&#xA;    					0, 0, 0, 0,						//accum bits ignored&#xD;&#xA;    					iDepthBits,						//depth buffer&#xD;&#xA;    					iStencilBits,					//stencil buffer&#xD;&#xA;    					0,								//aux buffer&#xD;&#xA;    					PFD_MAIN_PLANE,					//layer type&#xD;&#xA;    					0,								//reserved&#xD;&#xA;    					0, 0, 0							//masks ignored&#xD;&#xA;    				};&#xD;&#xA;    &#xD;&#xA;    				PixelFormat = ChoosePixelFormat(m_hDC, &amp;pfd);&#xD;&#xA;    				if (!PixelFormat)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!SetPixelFormat(m_hDC, PixelFormat, &amp;pfd))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hRC = wglCreateContext(m_hDC);&#xD;&#xA;    				if (!m_hRC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!wglMakeCurrent(m_hDC, m_hRC))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Get DPI information and store scaling relative to 96 DPI.&#xD;&#xA;    				// See http://msdn2.microsoft.com/en-us/library/ms969894.aspx&#xD;&#xA;    				//&#xD;&#xA;    				m_dScaleX = GetDeviceCaps(m_hDC, LOGPIXELSX) / 96.0;&#xD;&#xA;    				m_dScaleY = GetDeviceCaps(m_hDC, LOGPIXELSY) / 96.0;&#xD;&#xA;    &#xD;&#xA;    				glEnable(GL_DEPTH_TEST);&#xD;&#xA;    				glDisable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;    				return HandleRef(this, IntPtr(m_hWnd));&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return HandleRef(nullptr, System::IntPtr::Zero);&#xD;&#xA;    		}&#xD;&#xA;    	};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;OpenGLHWND.xaml.cs&#xD;&#xA;&#xD;&#xA;    using System;&#xD;&#xA;    using System.Collections.Generic;&#xD;&#xA;    using System.Linq;&#xD;&#xA;    using System.Text;&#xD;&#xA;    using System.Threading.Tasks;&#xD;&#xA;    using System.Windows;&#xD;&#xA;    using System.Windows.Controls;&#xD;&#xA;    using System.Windows.Data;&#xD;&#xA;    using System.Windows.Documents;&#xD;&#xA;    using System.Windows.Input;&#xD;&#xA;    using System.Windows.Media;&#xD;&#xA;    using System.Windows.Media.Imaging;&#xD;&#xA;    using System.Windows.Shapes;&#xD;&#xA;    &#xD;&#xA;    using System.Windows.Interop; //HwndHost&#xD;&#xA;    using OpenGLCpp;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLinWPF&#xD;&#xA;    {&#xD;&#xA;        /// &lt;summary&gt;&#xD;&#xA;        /// Interaction logic for OpenGLHWND.xaml&#xD;&#xA;        /// &lt;/summary&gt;&#xD;&#xA;        public partial class OpenGLHWND : Window&#xD;&#xA;        {&#xD;&#xA;            public OpenGLHWND()&#xD;&#xA;            {&#xD;&#xA;                InitializeComponent();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private System.Windows.Threading.DispatcherTimer updateTimer = new System.Windows.Threading.DispatcherTimer();&#xD;&#xA;    &#xD;&#xA;            public override void BeginInit()&#xD;&#xA;            {&#xD;&#xA;                updateTimer.Interval = new TimeSpan(160000);&#xD;&#xA;                updateTimer.Tick += new EventHandler(updateTimer_Tick);&#xD;&#xA;                updateTimer.Start();&#xD;&#xA;                base.BeginInit();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            protected override void OnClosing(System.ComponentModel.CancelEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                base.OnClosing(e);&#xD;&#xA;    &#xD;&#xA;                if (!e.Cancel)&#xD;&#xA;                {&#xD;&#xA;                    if (null != updateTimer)&#xD;&#xA;                    {&#xD;&#xA;                        updateTimer.Stop();&#xD;&#xA;                        updateTimer = null;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void updateTimer_Tick(object sender, EventArgs e)&#xD;&#xA;            {&#xD;&#xA;                if (null != hwndPlaceholder &amp;&amp;&#xD;&#xA;                    null != hwndPlaceholder.Child)&#xD;&#xA;                {&#xD;&#xA;                    hwndPlaceholder.Child.InvalidateVisual();&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void Window_Loaded(object sender, RoutedEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                // Create our OpenGL Hwnd 'control'...&#xD;&#xA;                HwndHost host = new OpenGLCpp.OpenGLHwnd(); &#xD;&#xA;    &#xD;&#xA;                // ... and attach it to the placeholder control:&#xD;&#xA;                hwndPlaceholder.Child = host;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is a [link][5] to the source on GitHub.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/Articles/23736/Creating-OpenGL-Windows-in-WPF&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-hosting-a-win32-control-in-wpf?view=netframeworkdesktop-4.8&#xD;&#xA;  [3]: https://i.stack.imgur.com/FAd3o.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/tp3tP.png&#xD;&#xA;  [5]: https://github.com/arjansingh00/OpenGLinWPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37531" PostHistoryTypeId="1" PostId="12791" RevisionGUID="119dc4da-63fb-4610-80d7-9549e85fa3fe" CreationDate="2022-06-19T17:57:29.593" UserId="5256" Text="Creating OpenGL Windows in WPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37532" PostHistoryTypeId="3" PostId="12791" RevisionGUID="119dc4da-63fb-4610-80d7-9549e85fa3fe" CreationDate="2022-06-19T17:57:29.593" UserId="5256" Text="|opengl|c++|c#|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37533" PostHistoryTypeId="4" PostId="12791" RevisionGUID="b23793c1-b0c2-46fb-a390-02f88c9eedec" CreationDate="2022-06-19T19:24:23.030" UserId="5256" Comment="edited title" Text="Creating OpenGL Windows in C# WPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37534" PostHistoryTypeId="4" PostId="12791" RevisionGUID="14f03112-832d-478d-8edf-9ec2d3cce59b" CreationDate="2022-06-19T21:24:42.237" UserId="5256" Comment="edited title" Text="Creating OpenGL C++ Windows in C# WPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37535" PostHistoryTypeId="4" PostId="12791" RevisionGUID="7fc1dc8e-8a6d-4c58-9c20-971ee33c66e4" CreationDate="2022-06-19T22:25:40.947" UserId="5256" Comment="edited title" Text="Hosting OpenGL C++ Window in C# WPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37536" PostHistoryTypeId="5" PostId="12791" RevisionGUID="d4418b23-cfad-4960-b003-9121b9d84402" CreationDate="2022-06-19T22:39:49.243" UserId="5256" Comment="edited body" Text="I am following this [tutorial][1] on how to host Win32 OpenGL windows in WPF. There is also a Microsoft walkthrough on how to [Host a Win32 Control in WPF][2] that is useful aswell. The original project is from 2009 and uses managed C++. I have rebuilt the program using the same source code (a few modifications due to debugging) using a C++ CLR Class Library. I use the compiled DLL in C# WPF however, when I run the program I get a blank window as opposed to the triangle in the tutorial.&#xD;&#xA;&#xD;&#xA;I was wondering if someone could take a look at my program and see why nothing is rendering.&#xD;&#xA;&#xD;&#xA;What the original program renders:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What I am getting:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Here is a [link][5] to the source on GitHub.&#xD;&#xA;&#xD;&#xA;OpenGLCpp.h&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    // Exclude rarely used parts of the windows headers&#xD;&#xA;    #define WIN32_LEAN_AND_MEAN&#xD;&#xA;    &#xD;&#xA;    #include &lt;Windows.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;Helper.h&quot;&#xD;&#xA;    #include &quot;OpenGL.h&quot;&#xD;&#xA;    &#xD;&#xA;    // To use these, we must add some references...&#xD;&#xA;    //	o PresentationFramework (for HwndHost)&#xD;&#xA;    //		* PresentationCore&#xD;&#xA;    //		* WindowsBase&#xD;&#xA;    using namespace System;&#xD;&#xA;    using namespace System::Windows;&#xD;&#xA;    using namespace System::Windows::Interop;&#xD;&#xA;    using namespace System::Windows::Input;&#xD;&#xA;    using namespace System::Windows::Media;&#xD;&#xA;    using namespace System::Runtime::InteropServices;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLCpp &#xD;&#xA;    {&#xD;&#xA;    	LRESULT WINAPI MyMsgProc(HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam)&#xD;&#xA;    	{&#xD;&#xA;    		switch (_msg)&#xD;&#xA;    		{&#xD;&#xA;    			// Make sure the window gets focus when it has to!&#xD;&#xA;    		case WM_IME_SETCONTEXT:&#xD;&#xA;    			// LOWORD(wParam) = 0 stands for deactivation, so don't set&#xD;&#xA;    			// focus then (results in a rather, err... 'greedy' window...)&#xD;&#xA;    			if (LOWORD(_wParam) &gt; 0)&#xD;&#xA;    				SetFocus(_hWnd);&#xD;&#xA;    &#xD;&#xA;    			return 0;&#xD;&#xA;    &#xD;&#xA;    		default:&#xD;&#xA;    			return DefWindowProc(_hWnd, _msg, _wParam, _lParam);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	//&#xD;&#xA;    	// This class implements HwndHost&#xD;&#xA;    	//&#xD;&#xA;    	// We have to overwrite BuildWindowCore and DestroyWindowCore&#xD;&#xA;    	//&#xD;&#xA;    	// A very simple example which creates a Win32 ListBox can be found in the MSDN:&#xD;&#xA;    	// http://msdn2.microsoft.com/en-us/library/aa970061.aspx&#xD;&#xA;    	//&#xD;&#xA;    	public ref class OpenGLHwnd : public HwndHost&#xD;&#xA;    	{&#xD;&#xA;    	public:&#xD;&#xA;    		OpenGLHwnd() : m_hRC(NULL),&#xD;&#xA;    			m_hDC(NULL),&#xD;&#xA;    			m_hWnd(NULL),&#xD;&#xA;    			m_hInstance(NULL),&#xD;&#xA;    			m_sWindowName(NULL),&#xD;&#xA;    			m_sClassName(NULL),&#xD;&#xA;    			m_fRotationAngle(0.0f)&#xD;&#xA;    		{&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    	private:&#xD;&#xA;    		HGLRC					m_hRC;&#xD;&#xA;    		HDC						m_hDC;&#xD;&#xA;    		HWND					m_hWnd;&#xD;&#xA;    		HINSTANCE				m_hInstance;&#xD;&#xA;    		LPCWSTR					m_sWindowName;&#xD;&#xA;    		LPCWSTR					m_sClassName;&#xD;&#xA;    &#xD;&#xA;    		float					m_fRotationAngle;&#xD;&#xA;    &#xD;&#xA;    		// DPI Scaling&#xD;&#xA;    		double					m_dScaleX;&#xD;&#xA;    		double					m_dScaleY;&#xD;&#xA;    &#xD;&#xA;    	protected:&#xD;&#xA;    		/*virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool% handled) override&#xD;&#xA;    		{&#xD;&#xA;    			switch( msg )&#xD;&#xA;    			{&#xD;&#xA;    				case WM_IME_SETCONTEXT:&#xD;&#xA;    					if(LOWORD(wParam.ToInt32()) &gt; 0)&#xD;&#xA;    						SetFocus(m_hWnd);&#xD;&#xA;    &#xD;&#xA;    					handled = true;&#xD;&#xA;    					return System::IntPtr::Zero;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			handled = false;&#xD;&#xA;    			return System::IntPtr::Zero;&#xD;&#xA;    		}*/&#xD;&#xA;    	public:&#xD;&#xA;    		virtual void OnRenderSizeChanged(SizeChangedInfo^ sizeInfo) override&#xD;&#xA;    		{&#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			// Apply DPI correction&#xD;&#xA;    			// NOTE: sizeInfo-&gt;NewSize contains doubles, so we do the multiplication before&#xD;&#xA;    			// converting to int.&#xD;&#xA;    			int iHeight = (int)(sizeInfo-&gt;NewSize.Height * m_dScaleY);&#xD;&#xA;    			int iWidth = (int)(sizeInfo-&gt;NewSize.Width * m_dScaleX);&#xD;&#xA;    &#xD;&#xA;    			if (iWidth == 0 || iHeight == 0)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    			glViewport(0, 0, iWidth, iHeight);&#xD;&#xA;    &#xD;&#xA;    			glMatrixMode(GL_PROJECTION);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    			glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 100.0);&#xD;&#xA;    			// gluPerspective( 67.5, ((double)(iWidth) / (double)(iHeight)), 1.0, 500.0);&#xD;&#xA;    			glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// Communicating with this method will be considerably more complicated in a real-&#xD;&#xA;    		// world application...&#xD;&#xA;    		//&#xD;&#xA;    		virtual void OnRender(System::Windows::Media::DrawingContext^ drawingContext) override&#xD;&#xA;    		{&#xD;&#xA;    			UNREF(drawingContext);&#xD;&#xA;    &#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    &#xD;&#xA;    			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    &#xD;&#xA;    			glTranslatef(0.0f, 0.0f, -2.6f);&#xD;&#xA;    			glRotatef(m_fRotationAngle, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glBegin(GL_TRIANGLES);&#xD;&#xA;    			glColor3f(1.0f, 0.0f, 0.0f);	glVertex3f(-1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 1.0f, 0.0f);	glVertex3f(0.0f, 1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 0.0f, 1.0f);	glVertex3f(1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glEnd();&#xD;&#xA;    &#xD;&#xA;    			glFlush();&#xD;&#xA;    			SwapBuffers(m_hDC); // NOTE: This is no longer wglSwapBuffers&#xD;&#xA;    &#xD;&#xA;    			// For constant rotation speed, and correct rotation speeds on different machines,&#xD;&#xA;    			// we'd need a timer here. However, I don't want to bloat the example code.&#xD;&#xA;    			m_fRotationAngle += 1.0;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		virtual void DestroyWindowCore(HandleRef hwnd) override&#xD;&#xA;    		{&#xD;&#xA;    			if (NULL != m_hRC)&#xD;&#xA;    			{&#xD;&#xA;    				wglDeleteContext(m_hRC);&#xD;&#xA;    				m_hRC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; NULL != m_hDC)&#xD;&#xA;    			{&#xD;&#xA;    				ReleaseDC(m_hWnd, m_hDC);&#xD;&#xA;    				m_hDC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; m_hWnd == (HWND)hwnd.Handle.ToPointer())&#xD;&#xA;    			{&#xD;&#xA;    				::DestroyWindow(m_hWnd);&#xD;&#xA;    				m_hWnd = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			UnregisterClass(m_sClassName, m_hInstance);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		bool RegisterWindowClass()&#xD;&#xA;    		{&#xD;&#xA;    			//&#xD;&#xA;    			// Create custom WNDCLASS&#xD;&#xA;    			//&#xD;&#xA;    			WNDCLASS wndClass;&#xD;&#xA;    &#xD;&#xA;    			if (GetClassInfo(m_hInstance, m_sClassName, &amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				// Class is already registered!&#xD;&#xA;    				return true;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;&#xD;&#xA;    &#xD;&#xA;    			// Not providing a WNDPROC here results in a crash on my system:&#xD;&#xA;    			wndClass.lpfnWndProc = (WNDPROC)MyMsgProc;&#xD;&#xA;    			wndClass.cbClsExtra = 0;&#xD;&#xA;    			wndClass.cbWndExtra = 0;&#xD;&#xA;    			wndClass.hInstance = m_hInstance;&#xD;&#xA;    			wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);&#xD;&#xA;    			wndClass.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;    			wndClass.hbrBackground = 0;&#xD;&#xA;    			wndClass.lpszMenuName = 0; // No menu&#xD;&#xA;    			wndClass.lpszClassName = m_sClassName;&#xD;&#xA;    &#xD;&#xA;    			// ... and register it&#xD;&#xA;    			if (!RegisterClass(&amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				Helper::ErrorExit(L&quot;RegisterWindowClass&quot;);&#xD;&#xA;    				return false;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return true;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// This is the key method to override&#xD;&#xA;    		//&#xD;&#xA;    		virtual HandleRef BuildWindowCore(HandleRef hwndParent) override&#xD;&#xA;    		{&#xD;&#xA;    			// Get HINSTANCE&#xD;&#xA;    			m_hInstance = (HINSTANCE)GetModuleHandle(NULL);&#xD;&#xA;    			m_sWindowName = L&quot;OpenGL in HwndHost&quot;;&#xD;&#xA;    			m_sClassName = L&quot;OGLClassHwnd&quot;;&#xD;&#xA;    &#xD;&#xA;    			if (RegisterWindowClass())&#xD;&#xA;    			{&#xD;&#xA;    				// some default size&#xD;&#xA;    				int iWidth = 2;&#xD;&#xA;    				int iHeight = 2;&#xD;&#xA;    &#xD;&#xA;    				DWORD dwStyle = WS_CHILD | WS_VISIBLE;&#xD;&#xA;    &#xD;&#xA;    				// Get the parent (WPF) Hwnd. This is important: Windows won't let you create&#xD;&#xA;    				// the Hwnd otherwise.&#xD;&#xA;    				HWND parentHwnd = (HWND)hwndParent.Handle.ToPointer();&#xD;&#xA;    &#xD;&#xA;    				m_hWnd = CreateWindowEx(0,&#xD;&#xA;    					m_sClassName,&#xD;&#xA;    					m_sWindowName,&#xD;&#xA;    					dwStyle,&#xD;&#xA;    					0,	// X Pos&#xD;&#xA;    					0,	// Y Pos&#xD;&#xA;    					iWidth,&#xD;&#xA;    					iHeight,&#xD;&#xA;    					parentHwnd, // Parent&#xD;&#xA;    					0,	// Menu&#xD;&#xA;    					m_hInstance,&#xD;&#xA;    					0); // Param&#xD;&#xA;    &#xD;&#xA;    				if (!m_hWnd)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hDC = GetDC(m_hWnd);&#xD;&#xA;    				if (!m_hDC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Create PixelFormatDescriptor and choose pixel format&#xD;&#xA;    				//&#xD;&#xA;    				uint PixelFormat;&#xD;&#xA;    &#xD;&#xA;    				BYTE iAlphaBits = 0;&#xD;&#xA;    				BYTE iColorBits = 32;&#xD;&#xA;    				BYTE iDepthBits = 16;&#xD;&#xA;    				BYTE iAccumBits = 0;&#xD;&#xA;    				BYTE iStencilBits = 0;&#xD;&#xA;    &#xD;&#xA;    				static PIXELFORMATDESCRIPTOR pfd =&#xD;&#xA;    				{&#xD;&#xA;    					sizeof(PIXELFORMATDESCRIPTOR),	//size&#xD;&#xA;    					1,								//version&#xD;&#xA;    					PFD_DRAW_TO_WINDOW |				//flags&#xD;&#xA;    					PFD_SUPPORT_OPENGL |&#xD;&#xA;    					PFD_DOUBLEBUFFER,&#xD;&#xA;    					PFD_TYPE_RGBA,					//pixeltype&#xD;&#xA;    					iColorBits,&#xD;&#xA;    					0, 0, 0, 0, 0, 0,				//color bits ignored&#xD;&#xA;    					iAlphaBits,&#xD;&#xA;    					0,								//alpha shift ignored&#xD;&#xA;    					iAccumBits,						//accum. buffer&#xD;&#xA;    					0, 0, 0, 0,						//accum bits ignored&#xD;&#xA;    					iDepthBits,						//depth buffer&#xD;&#xA;    					iStencilBits,					//stencil buffer&#xD;&#xA;    					0,								//aux buffer&#xD;&#xA;    					PFD_MAIN_PLANE,					//layer type&#xD;&#xA;    					0,								//reserved&#xD;&#xA;    					0, 0, 0							//masks ignored&#xD;&#xA;    				};&#xD;&#xA;    &#xD;&#xA;    				PixelFormat = ChoosePixelFormat(m_hDC, &amp;pfd);&#xD;&#xA;    				if (!PixelFormat)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!SetPixelFormat(m_hDC, PixelFormat, &amp;pfd))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hRC = wglCreateContext(m_hDC);&#xD;&#xA;    				if (!m_hRC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!wglMakeCurrent(m_hDC, m_hRC))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Get DPI information and store scaling relative to 96 DPI.&#xD;&#xA;    				// See http://msdn2.microsoft.com/en-us/library/ms969894.aspx&#xD;&#xA;    				//&#xD;&#xA;    				m_dScaleX = GetDeviceCaps(m_hDC, LOGPIXELSX) / 96.0;&#xD;&#xA;    				m_dScaleY = GetDeviceCaps(m_hDC, LOGPIXELSY) / 96.0;&#xD;&#xA;    &#xD;&#xA;    				glEnable(GL_DEPTH_TEST);&#xD;&#xA;    				glDisable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;    				return HandleRef(this, IntPtr(m_hWnd));&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return HandleRef(nullptr, System::IntPtr::Zero);&#xD;&#xA;    		}&#xD;&#xA;    	};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;OpenGLHWND.xaml.cs&#xD;&#xA;&#xD;&#xA;    using System;&#xD;&#xA;    using System.Collections.Generic;&#xD;&#xA;    using System.Linq;&#xD;&#xA;    using System.Text;&#xD;&#xA;    using System.Threading.Tasks;&#xD;&#xA;    using System.Windows;&#xD;&#xA;    using System.Windows.Controls;&#xD;&#xA;    using System.Windows.Data;&#xD;&#xA;    using System.Windows.Documents;&#xD;&#xA;    using System.Windows.Input;&#xD;&#xA;    using System.Windows.Media;&#xD;&#xA;    using System.Windows.Media.Imaging;&#xD;&#xA;    using System.Windows.Shapes;&#xD;&#xA;    &#xD;&#xA;    using System.Windows.Interop; //HwndHost&#xD;&#xA;    using OpenGLCpp;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLinWPF&#xD;&#xA;    {&#xD;&#xA;        /// &lt;summary&gt;&#xD;&#xA;        /// Interaction logic for OpenGLHWND.xaml&#xD;&#xA;        /// &lt;/summary&gt;&#xD;&#xA;        public partial class OpenGLHWND : Window&#xD;&#xA;        {&#xD;&#xA;            public OpenGLHWND()&#xD;&#xA;            {&#xD;&#xA;                InitializeComponent();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private System.Windows.Threading.DispatcherTimer updateTimer = new System.Windows.Threading.DispatcherTimer();&#xD;&#xA;    &#xD;&#xA;            public override void BeginInit()&#xD;&#xA;            {&#xD;&#xA;                updateTimer.Interval = new TimeSpan(160000);&#xD;&#xA;                updateTimer.Tick += new EventHandler(updateTimer_Tick);&#xD;&#xA;                updateTimer.Start();&#xD;&#xA;                base.BeginInit();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            protected override void OnClosing(System.ComponentModel.CancelEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                base.OnClosing(e);&#xD;&#xA;    &#xD;&#xA;                if (!e.Cancel)&#xD;&#xA;                {&#xD;&#xA;                    if (null != updateTimer)&#xD;&#xA;                    {&#xD;&#xA;                        updateTimer.Stop();&#xD;&#xA;                        updateTimer = null;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void updateTimer_Tick(object sender, EventArgs e)&#xD;&#xA;            {&#xD;&#xA;                if (null != hwndPlaceholder &amp;&amp;&#xD;&#xA;                    null != hwndPlaceholder.Child)&#xD;&#xA;                {&#xD;&#xA;                    hwndPlaceholder.Child.InvalidateVisual();&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void Window_Loaded(object sender, RoutedEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                // Create our OpenGL Hwnd 'control'...&#xD;&#xA;                HwndHost host = new OpenGLCpp.OpenGLHwnd(); &#xD;&#xA;    &#xD;&#xA;                // ... and attach it to the placeholder control:&#xD;&#xA;                hwndPlaceholder.Child = host;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/Articles/23736/Creating-OpenGL-Windows-in-WPF&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-hosting-a-win32-control-in-wpf?view=netframeworkdesktop-4.8&#xD;&#xA;  [3]: https://i.stack.imgur.com/FAd3o.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/tp3tP.png&#xD;&#xA;  [5]: https://github.com/arjansingh00/OpenGLinWPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37537" PostHistoryTypeId="5" PostId="12791" RevisionGUID="89ea65ce-316a-4bd0-852f-a798f6248a81" CreationDate="2022-06-20T00:11:19.807" UserId="5256" Comment="added 28 characters in body" Text="I am following this [tutorial][1] on how to host Win32 OpenGL windows in WPF. There is also a Microsoft walkthrough on how to [Host a Win32 Control in WPF][2] that is useful aswell. The original project is from 2009 and uses managed C++ but doesn't actually render. I have rebuilt the program using the same source code (a few modifications due to debugging) using a C++ CLR Class Library. I use the compiled DLL in C# WPF however, when I run the program I get a blank window as opposed to the triangle in the tutorial.&#xD;&#xA;&#xD;&#xA;I was wondering if someone could take a look at my program and see why nothing is rendering.&#xD;&#xA;&#xD;&#xA;What the original program renders:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What I am getting:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Here is a [link][5] to the source on GitHub.&#xD;&#xA;&#xD;&#xA;OpenGLCpp.h&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    // Exclude rarely used parts of the windows headers&#xD;&#xA;    #define WIN32_LEAN_AND_MEAN&#xD;&#xA;    &#xD;&#xA;    #include &lt;Windows.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;Helper.h&quot;&#xD;&#xA;    #include &quot;OpenGL.h&quot;&#xD;&#xA;    &#xD;&#xA;    // To use these, we must add some references...&#xD;&#xA;    //	o PresentationFramework (for HwndHost)&#xD;&#xA;    //		* PresentationCore&#xD;&#xA;    //		* WindowsBase&#xD;&#xA;    using namespace System;&#xD;&#xA;    using namespace System::Windows;&#xD;&#xA;    using namespace System::Windows::Interop;&#xD;&#xA;    using namespace System::Windows::Input;&#xD;&#xA;    using namespace System::Windows::Media;&#xD;&#xA;    using namespace System::Runtime::InteropServices;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLCpp &#xD;&#xA;    {&#xD;&#xA;    	LRESULT WINAPI MyMsgProc(HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam)&#xD;&#xA;    	{&#xD;&#xA;    		switch (_msg)&#xD;&#xA;    		{&#xD;&#xA;    			// Make sure the window gets focus when it has to!&#xD;&#xA;    		case WM_IME_SETCONTEXT:&#xD;&#xA;    			// LOWORD(wParam) = 0 stands for deactivation, so don't set&#xD;&#xA;    			// focus then (results in a rather, err... 'greedy' window...)&#xD;&#xA;    			if (LOWORD(_wParam) &gt; 0)&#xD;&#xA;    				SetFocus(_hWnd);&#xD;&#xA;    &#xD;&#xA;    			return 0;&#xD;&#xA;    &#xD;&#xA;    		default:&#xD;&#xA;    			return DefWindowProc(_hWnd, _msg, _wParam, _lParam);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	//&#xD;&#xA;    	// This class implements HwndHost&#xD;&#xA;    	//&#xD;&#xA;    	// We have to overwrite BuildWindowCore and DestroyWindowCore&#xD;&#xA;    	//&#xD;&#xA;    	// A very simple example which creates a Win32 ListBox can be found in the MSDN:&#xD;&#xA;    	// http://msdn2.microsoft.com/en-us/library/aa970061.aspx&#xD;&#xA;    	//&#xD;&#xA;    	public ref class OpenGLHwnd : public HwndHost&#xD;&#xA;    	{&#xD;&#xA;    	public:&#xD;&#xA;    		OpenGLHwnd() : m_hRC(NULL),&#xD;&#xA;    			m_hDC(NULL),&#xD;&#xA;    			m_hWnd(NULL),&#xD;&#xA;    			m_hInstance(NULL),&#xD;&#xA;    			m_sWindowName(NULL),&#xD;&#xA;    			m_sClassName(NULL),&#xD;&#xA;    			m_fRotationAngle(0.0f)&#xD;&#xA;    		{&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    	private:&#xD;&#xA;    		HGLRC					m_hRC;&#xD;&#xA;    		HDC						m_hDC;&#xD;&#xA;    		HWND					m_hWnd;&#xD;&#xA;    		HINSTANCE				m_hInstance;&#xD;&#xA;    		LPCWSTR					m_sWindowName;&#xD;&#xA;    		LPCWSTR					m_sClassName;&#xD;&#xA;    &#xD;&#xA;    		float					m_fRotationAngle;&#xD;&#xA;    &#xD;&#xA;    		// DPI Scaling&#xD;&#xA;    		double					m_dScaleX;&#xD;&#xA;    		double					m_dScaleY;&#xD;&#xA;    &#xD;&#xA;    	protected:&#xD;&#xA;    		/*virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool% handled) override&#xD;&#xA;    		{&#xD;&#xA;    			switch( msg )&#xD;&#xA;    			{&#xD;&#xA;    				case WM_IME_SETCONTEXT:&#xD;&#xA;    					if(LOWORD(wParam.ToInt32()) &gt; 0)&#xD;&#xA;    						SetFocus(m_hWnd);&#xD;&#xA;    &#xD;&#xA;    					handled = true;&#xD;&#xA;    					return System::IntPtr::Zero;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			handled = false;&#xD;&#xA;    			return System::IntPtr::Zero;&#xD;&#xA;    		}*/&#xD;&#xA;    	public:&#xD;&#xA;    		virtual void OnRenderSizeChanged(SizeChangedInfo^ sizeInfo) override&#xD;&#xA;    		{&#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			// Apply DPI correction&#xD;&#xA;    			// NOTE: sizeInfo-&gt;NewSize contains doubles, so we do the multiplication before&#xD;&#xA;    			// converting to int.&#xD;&#xA;    			int iHeight = (int)(sizeInfo-&gt;NewSize.Height * m_dScaleY);&#xD;&#xA;    			int iWidth = (int)(sizeInfo-&gt;NewSize.Width * m_dScaleX);&#xD;&#xA;    &#xD;&#xA;    			if (iWidth == 0 || iHeight == 0)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    			glViewport(0, 0, iWidth, iHeight);&#xD;&#xA;    &#xD;&#xA;    			glMatrixMode(GL_PROJECTION);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    			glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 100.0);&#xD;&#xA;    			// gluPerspective( 67.5, ((double)(iWidth) / (double)(iHeight)), 1.0, 500.0);&#xD;&#xA;    			glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// Communicating with this method will be considerably more complicated in a real-&#xD;&#xA;    		// world application...&#xD;&#xA;    		//&#xD;&#xA;    		virtual void OnRender(System::Windows::Media::DrawingContext^ drawingContext) override&#xD;&#xA;    		{&#xD;&#xA;    			UNREF(drawingContext);&#xD;&#xA;    &#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    &#xD;&#xA;    			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    &#xD;&#xA;    			glTranslatef(0.0f, 0.0f, -2.6f);&#xD;&#xA;    			glRotatef(m_fRotationAngle, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glBegin(GL_TRIANGLES);&#xD;&#xA;    			glColor3f(1.0f, 0.0f, 0.0f);	glVertex3f(-1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 1.0f, 0.0f);	glVertex3f(0.0f, 1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 0.0f, 1.0f);	glVertex3f(1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glEnd();&#xD;&#xA;    &#xD;&#xA;    			glFlush();&#xD;&#xA;    			SwapBuffers(m_hDC); // NOTE: This is no longer wglSwapBuffers&#xD;&#xA;    &#xD;&#xA;    			// For constant rotation speed, and correct rotation speeds on different machines,&#xD;&#xA;    			// we'd need a timer here. However, I don't want to bloat the example code.&#xD;&#xA;    			m_fRotationAngle += 1.0;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		virtual void DestroyWindowCore(HandleRef hwnd) override&#xD;&#xA;    		{&#xD;&#xA;    			if (NULL != m_hRC)&#xD;&#xA;    			{&#xD;&#xA;    				wglDeleteContext(m_hRC);&#xD;&#xA;    				m_hRC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; NULL != m_hDC)&#xD;&#xA;    			{&#xD;&#xA;    				ReleaseDC(m_hWnd, m_hDC);&#xD;&#xA;    				m_hDC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; m_hWnd == (HWND)hwnd.Handle.ToPointer())&#xD;&#xA;    			{&#xD;&#xA;    				::DestroyWindow(m_hWnd);&#xD;&#xA;    				m_hWnd = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			UnregisterClass(m_sClassName, m_hInstance);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		bool RegisterWindowClass()&#xD;&#xA;    		{&#xD;&#xA;    			//&#xD;&#xA;    			// Create custom WNDCLASS&#xD;&#xA;    			//&#xD;&#xA;    			WNDCLASS wndClass;&#xD;&#xA;    &#xD;&#xA;    			if (GetClassInfo(m_hInstance, m_sClassName, &amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				// Class is already registered!&#xD;&#xA;    				return true;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;&#xD;&#xA;    &#xD;&#xA;    			// Not providing a WNDPROC here results in a crash on my system:&#xD;&#xA;    			wndClass.lpfnWndProc = (WNDPROC)MyMsgProc;&#xD;&#xA;    			wndClass.cbClsExtra = 0;&#xD;&#xA;    			wndClass.cbWndExtra = 0;&#xD;&#xA;    			wndClass.hInstance = m_hInstance;&#xD;&#xA;    			wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);&#xD;&#xA;    			wndClass.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;    			wndClass.hbrBackground = 0;&#xD;&#xA;    			wndClass.lpszMenuName = 0; // No menu&#xD;&#xA;    			wndClass.lpszClassName = m_sClassName;&#xD;&#xA;    &#xD;&#xA;    			// ... and register it&#xD;&#xA;    			if (!RegisterClass(&amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				Helper::ErrorExit(L&quot;RegisterWindowClass&quot;);&#xD;&#xA;    				return false;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return true;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// This is the key method to override&#xD;&#xA;    		//&#xD;&#xA;    		virtual HandleRef BuildWindowCore(HandleRef hwndParent) override&#xD;&#xA;    		{&#xD;&#xA;    			// Get HINSTANCE&#xD;&#xA;    			m_hInstance = (HINSTANCE)GetModuleHandle(NULL);&#xD;&#xA;    			m_sWindowName = L&quot;OpenGL in HwndHost&quot;;&#xD;&#xA;    			m_sClassName = L&quot;OGLClassHwnd&quot;;&#xD;&#xA;    &#xD;&#xA;    			if (RegisterWindowClass())&#xD;&#xA;    			{&#xD;&#xA;    				// some default size&#xD;&#xA;    				int iWidth = 2;&#xD;&#xA;    				int iHeight = 2;&#xD;&#xA;    &#xD;&#xA;    				DWORD dwStyle = WS_CHILD | WS_VISIBLE;&#xD;&#xA;    &#xD;&#xA;    				// Get the parent (WPF) Hwnd. This is important: Windows won't let you create&#xD;&#xA;    				// the Hwnd otherwise.&#xD;&#xA;    				HWND parentHwnd = (HWND)hwndParent.Handle.ToPointer();&#xD;&#xA;    &#xD;&#xA;    				m_hWnd = CreateWindowEx(0,&#xD;&#xA;    					m_sClassName,&#xD;&#xA;    					m_sWindowName,&#xD;&#xA;    					dwStyle,&#xD;&#xA;    					0,	// X Pos&#xD;&#xA;    					0,	// Y Pos&#xD;&#xA;    					iWidth,&#xD;&#xA;    					iHeight,&#xD;&#xA;    					parentHwnd, // Parent&#xD;&#xA;    					0,	// Menu&#xD;&#xA;    					m_hInstance,&#xD;&#xA;    					0); // Param&#xD;&#xA;    &#xD;&#xA;    				if (!m_hWnd)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hDC = GetDC(m_hWnd);&#xD;&#xA;    				if (!m_hDC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Create PixelFormatDescriptor and choose pixel format&#xD;&#xA;    				//&#xD;&#xA;    				uint PixelFormat;&#xD;&#xA;    &#xD;&#xA;    				BYTE iAlphaBits = 0;&#xD;&#xA;    				BYTE iColorBits = 32;&#xD;&#xA;    				BYTE iDepthBits = 16;&#xD;&#xA;    				BYTE iAccumBits = 0;&#xD;&#xA;    				BYTE iStencilBits = 0;&#xD;&#xA;    &#xD;&#xA;    				static PIXELFORMATDESCRIPTOR pfd =&#xD;&#xA;    				{&#xD;&#xA;    					sizeof(PIXELFORMATDESCRIPTOR),	//size&#xD;&#xA;    					1,								//version&#xD;&#xA;    					PFD_DRAW_TO_WINDOW |				//flags&#xD;&#xA;    					PFD_SUPPORT_OPENGL |&#xD;&#xA;    					PFD_DOUBLEBUFFER,&#xD;&#xA;    					PFD_TYPE_RGBA,					//pixeltype&#xD;&#xA;    					iColorBits,&#xD;&#xA;    					0, 0, 0, 0, 0, 0,				//color bits ignored&#xD;&#xA;    					iAlphaBits,&#xD;&#xA;    					0,								//alpha shift ignored&#xD;&#xA;    					iAccumBits,						//accum. buffer&#xD;&#xA;    					0, 0, 0, 0,						//accum bits ignored&#xD;&#xA;    					iDepthBits,						//depth buffer&#xD;&#xA;    					iStencilBits,					//stencil buffer&#xD;&#xA;    					0,								//aux buffer&#xD;&#xA;    					PFD_MAIN_PLANE,					//layer type&#xD;&#xA;    					0,								//reserved&#xD;&#xA;    					0, 0, 0							//masks ignored&#xD;&#xA;    				};&#xD;&#xA;    &#xD;&#xA;    				PixelFormat = ChoosePixelFormat(m_hDC, &amp;pfd);&#xD;&#xA;    				if (!PixelFormat)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!SetPixelFormat(m_hDC, PixelFormat, &amp;pfd))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hRC = wglCreateContext(m_hDC);&#xD;&#xA;    				if (!m_hRC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!wglMakeCurrent(m_hDC, m_hRC))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Get DPI information and store scaling relative to 96 DPI.&#xD;&#xA;    				// See http://msdn2.microsoft.com/en-us/library/ms969894.aspx&#xD;&#xA;    				//&#xD;&#xA;    				m_dScaleX = GetDeviceCaps(m_hDC, LOGPIXELSX) / 96.0;&#xD;&#xA;    				m_dScaleY = GetDeviceCaps(m_hDC, LOGPIXELSY) / 96.0;&#xD;&#xA;    &#xD;&#xA;    				glEnable(GL_DEPTH_TEST);&#xD;&#xA;    				glDisable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;    				return HandleRef(this, IntPtr(m_hWnd));&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return HandleRef(nullptr, System::IntPtr::Zero);&#xD;&#xA;    		}&#xD;&#xA;    	};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;OpenGLHWND.xaml.cs&#xD;&#xA;&#xD;&#xA;    using System;&#xD;&#xA;    using System.Collections.Generic;&#xD;&#xA;    using System.Linq;&#xD;&#xA;    using System.Text;&#xD;&#xA;    using System.Threading.Tasks;&#xD;&#xA;    using System.Windows;&#xD;&#xA;    using System.Windows.Controls;&#xD;&#xA;    using System.Windows.Data;&#xD;&#xA;    using System.Windows.Documents;&#xD;&#xA;    using System.Windows.Input;&#xD;&#xA;    using System.Windows.Media;&#xD;&#xA;    using System.Windows.Media.Imaging;&#xD;&#xA;    using System.Windows.Shapes;&#xD;&#xA;    &#xD;&#xA;    using System.Windows.Interop; //HwndHost&#xD;&#xA;    using OpenGLCpp;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLinWPF&#xD;&#xA;    {&#xD;&#xA;        /// &lt;summary&gt;&#xD;&#xA;        /// Interaction logic for OpenGLHWND.xaml&#xD;&#xA;        /// &lt;/summary&gt;&#xD;&#xA;        public partial class OpenGLHWND : Window&#xD;&#xA;        {&#xD;&#xA;            public OpenGLHWND()&#xD;&#xA;            {&#xD;&#xA;                InitializeComponent();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private System.Windows.Threading.DispatcherTimer updateTimer = new System.Windows.Threading.DispatcherTimer();&#xD;&#xA;    &#xD;&#xA;            public override void BeginInit()&#xD;&#xA;            {&#xD;&#xA;                updateTimer.Interval = new TimeSpan(160000);&#xD;&#xA;                updateTimer.Tick += new EventHandler(updateTimer_Tick);&#xD;&#xA;                updateTimer.Start();&#xD;&#xA;                base.BeginInit();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            protected override void OnClosing(System.ComponentModel.CancelEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                base.OnClosing(e);&#xD;&#xA;    &#xD;&#xA;                if (!e.Cancel)&#xD;&#xA;                {&#xD;&#xA;                    if (null != updateTimer)&#xD;&#xA;                    {&#xD;&#xA;                        updateTimer.Stop();&#xD;&#xA;                        updateTimer = null;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void updateTimer_Tick(object sender, EventArgs e)&#xD;&#xA;            {&#xD;&#xA;                if (null != hwndPlaceholder &amp;&amp;&#xD;&#xA;                    null != hwndPlaceholder.Child)&#xD;&#xA;                {&#xD;&#xA;                    hwndPlaceholder.Child.InvalidateVisual();&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void Window_Loaded(object sender, RoutedEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                // Create our OpenGL Hwnd 'control'...&#xD;&#xA;                HwndHost host = new OpenGLCpp.OpenGLHwnd(); &#xD;&#xA;    &#xD;&#xA;                // ... and attach it to the placeholder control:&#xD;&#xA;                hwndPlaceholder.Child = host;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/Articles/23736/Creating-OpenGL-Windows-in-WPF&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-hosting-a-win32-control-in-wpf?view=netframeworkdesktop-4.8&#xD;&#xA;  [3]: https://i.stack.imgur.com/FAd3o.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/tp3tP.png&#xD;&#xA;  [5]: https://github.com/arjansingh00/OpenGLinWPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="37538" PostHistoryTypeId="2" PostId="12792" RevisionGUID="2066c536-3031-4c6c-b560-c705fa423704" CreationDate="2022-06-20T10:32:06.340" UserId="7952" Text="This is a perfectly reasonable thing to do. GPU to GPU copies are fast. This is best suited to API's like Vulkan or DX12 but I don't see any reason why doing it under OpenGL/DX11 wouldn't work. &#xD;&#xA;&#xD;&#xA;How big are these buffers? Allocating a large chunk of memory from OpenGL could set off a memory management event that causes it to move memory all over the place which could take a &quot;long&quot; time. Also if the buffers grow repeatedly it could cause fragmentation. But if the buffers are relatively small like a few MIBS in size then it really shouldn't be an issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="37540" PostHistoryTypeId="5" PostId="12792" RevisionGUID="d5c010d3-d3e8-46f6-8893-91a21a265516" CreationDate="2022-06-20T10:38:51.683" UserId="7952" Comment="added 198 characters in body" Text="This is a perfectly reasonable thing to do. GPU to GPU copies are fast. This is best suited to API's like Vulkan or DX12 but I don't see any reason why doing it under OpenGL/DX11 wouldn't work. &#xD;&#xA;&#xD;&#xA;How big are these buffers? Allocating a large chunk of memory from OpenGL could set off a memory management event that causes it to move memory all over the place which could take a &quot;long&quot; time. Also if the buffers grow repeatedly it could cause fragmentation. But if the buffers are relatively small like a few MIBS in size then it really shouldn't be an issue.&#xD;&#xA;&#xD;&#xA;I guess the other question is...&quot;where&quot; is this memory being allocated?  If this is for buffers that are CPU visible then it becomes a lot more &quot;sketchy&quot; just because this is a limited resource." ContentLicense="CC BY-SA 4.0" />
  <row Id="37541" PostHistoryTypeId="2" PostId="12793" RevisionGUID="974e9346-00da-4924-a334-baad67b42199" CreationDate="2022-06-20T17:02:42.087" UserId="5256" Text="Someone on Reddit said that I did not set Loaded=&quot;Window_Loaded&quot; in&#xD;&#xA;&#xD;&#xA;    &lt;Window x:Class=&quot;OpenGLinWPF.OpenGLHWND&quot;&#xD;&#xA;            xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;&#xD;&#xA;            xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&#xD;&#xA;            xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;&#xD;&#xA;            xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;&#xD;&#xA;            xmlns:local=&quot;clr-namespace:OpenGLinWPF&quot;&#xD;&#xA;            mc:Ignorable=&quot;d&quot;&#xD;&#xA;            Title=&quot;OpenGLHWND&quot; Height=&quot;450&quot; Width=&quot;800&quot;&#xD;&#xA;            Loaded=&quot;Window_Loaded&quot;&gt;&#xD;&#xA;        &lt;Grid&gt;&#xD;&#xA;            &lt;Border Name=&quot;hwndPlaceholder&quot; /&gt;&#xD;&#xA;        &lt;/Grid&gt;&#xD;&#xA;    &lt;/Window&gt;&#xD;&#xA;&#xD;&#xA;After setting it I get:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/49Ooj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37543" PostHistoryTypeId="5" PostId="12793" RevisionGUID="84245c89-374a-4a57-8cd9-c2736f0a620a" CreationDate="2022-06-20T17:14:27.417" UserId="5256" Comment="added 113 characters in body" Text="I did not set Loaded=&quot;Window_Loaded&quot; in&#xD;&#xA;&#xD;&#xA;    &lt;Window x:Class=&quot;OpenGLinWPF.OpenGLHWND&quot;&#xD;&#xA;            xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;&#xD;&#xA;            xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;&#xD;&#xA;            xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;&#xD;&#xA;            xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;&#xD;&#xA;            xmlns:local=&quot;clr-namespace:OpenGLinWPF&quot;&#xD;&#xA;            mc:Ignorable=&quot;d&quot;&#xD;&#xA;            Title=&quot;OpenGLHWND&quot; Height=&quot;450&quot; Width=&quot;800&quot;&#xD;&#xA;            Loaded=&quot;Window_Loaded&quot;&gt;&#xD;&#xA;        &lt;Grid&gt;&#xD;&#xA;            &lt;Border Name=&quot;hwndPlaceholder&quot; /&gt;&#xD;&#xA;        &lt;/Grid&gt;&#xD;&#xA;    &lt;/Window&gt;&#xD;&#xA;&#xD;&#xA;The description of the Window.Loaded event here says&#xD;&#xA;&#xD;&#xA;&gt; Occurs when the element is laid out, rendered, and ready for&#xD;&#xA;&gt; interaction.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;After setting it I get:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/49Ooj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37544" PostHistoryTypeId="2" PostId="12794" RevisionGUID="3c134d63-5172-45c9-b305-693af9b93bf2" CreationDate="2022-06-21T11:03:11.720" UserId="15408" Text="What coordinate system did you use for intersection.normal and scattered_ray.direction? A typical way would be sampling the scattering direction in the local space and then transforming it into the world space. Thus the cosine theta will be computed inside the sampling function. I am not sure if it is the coordinate system that caused your issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="37551" PostHistoryTypeId="50" PostId="8888" RevisionGUID="329f26a6-5973-41a5-8e29-374906a0413c" CreationDate="2022-06-22T19:00:55.093" UserId="-1" />
  <row Id="37556" PostHistoryTypeId="2" PostId="12797" RevisionGUID="430359b5-19d8-4c1d-821c-b67163503a41" CreationDate="2022-06-22T20:15:22.967" UserId="18587" Text="Currently I have a basic (OpenGL 3.3) rendering scheme using a simple depth vertex shader to generate shadow maps for a scene. I don't care about having a large number of lights in the scene so it is fine to do individual render passes to generate each shadow map.&#xD;&#xA;&#xD;&#xA;**What I want to do:**&#xD;&#xA;&#xD;&#xA;My concern is that I want (or indeed NEED) to render the same scene geometry from many different camera transforms (over 500x) and it is very resource intensive to do one render pass per transform. Besides, reading pixels from the device is slow, so I would rather prefer to draw and fetch as many of these camera renders per call as the hardware allows.&#xD;&#xA;&#xD;&#xA;**What have I found:**&#xD;&#xA;&#xD;&#xA;Despite all the parallel computing capabilities of GPU devices, I find the OpenGL API regarding shader pipelines somewhat abstruse. I found something called [instanced rendering][1], which *seems* like should be the correct way to implement what I want, except I haven't found a decent example of how instanced rendering should work when rendering different fragments to different layers of a framebuffer.&#xD;&#xA; &#xD;&#xA;Btw I also *think* that [a layered framebuffer][2] is the way for doing multiple renders at once, but not sure if this is accurate or current&#xD;&#xA;&#xD;&#xA;**What would help me:**&#xD;&#xA;&#xD;&#xA;If perhaps this use case requires more recent OpenGL versions, or perhaps another framework (Vulkan?) this would also be an acceptable answer, as long as some details or examples are provided that I can use to build on&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Advanced-OpenGL/Instancing&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Framebuffer_Object#Layered_Images" ContentLicense="CC BY-SA 4.0" />
  <row Id="37558" PostHistoryTypeId="1" PostId="12797" RevisionGUID="430359b5-19d8-4c1d-821c-b67163503a41" CreationDate="2022-06-22T20:15:22.967" UserId="18587" Text="Rendering multiple camera transforms of the same geometry at once" ContentLicense="CC BY-SA 4.0" />
  <row Id="37559" PostHistoryTypeId="3" PostId="12797" RevisionGUID="430359b5-19d8-4c1d-821c-b67163503a41" CreationDate="2022-06-22T20:15:22.967" UserId="18587" Text="|opengl|shader|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37560" PostHistoryTypeId="5" PostId="12797" RevisionGUID="1099b4f8-fc2c-4f16-826e-e16441c6ba4a" CreationDate="2022-06-22T20:39:18.080" UserId="18587" Comment="added 116 characters in body" Text="Currently I have a basic (OpenGL 3.3) rendering scheme using a simple depth vertex shader to generate shadow maps for a scene. I don't care about having a large number of lights in the scene so it is fine to do individual render passes to generate each shadow map.&#xD;&#xA;&#xD;&#xA;**What I want to do:**&#xD;&#xA;&#xD;&#xA;My concern is that I want (or indeed NEED) to render the same scene geometry from many different camera transforms (over 500x) and it is very resource intensive to do one render pass per transform. Besides, reading pixels from the device is slow, so I would rather prefer to draw and fetch as many of these camera renders per call as the hardware allows. The current rendering pass uses a standard Phong vertex-&gt;fragment pipeline that relies on the computed shadow maps.&#xD;&#xA;&#xD;&#xA;**What have I found:**&#xD;&#xA;&#xD;&#xA;Despite all the parallel computing capabilities of GPU devices, I find the OpenGL API regarding shader pipelines somewhat abstruse. I found something called [instanced rendering][1], which *seems* like should be the correct way to implement what I want, except I haven't found a decent example of how instanced rendering should work when rendering different fragments to different layers of a framebuffer.&#xD;&#xA; &#xD;&#xA;Btw I also *think* that [a layered framebuffer][2] is the way for doing multiple renders at once, but not sure if this is accurate or current&#xD;&#xA;&#xD;&#xA;**What would help me:**&#xD;&#xA;&#xD;&#xA;If perhaps this use case requires more recent OpenGL versions, or perhaps another framework (Vulkan?) this would also be an acceptable answer, as long as some details or examples are provided that I can use to build on&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Advanced-OpenGL/Instancing&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Framebuffer_Object#Layered_Images" ContentLicense="CC BY-SA 4.0" />
  <row Id="37561" PostHistoryTypeId="2" PostId="12798" RevisionGUID="d64e00b7-08f3-4e17-a3d3-9d33c28b6c4e" CreationDate="2022-06-22T21:52:26.170" UserId="18588" Text="I am trying to draw points of a 3D sphere onto my monitor as if I was looking out into space.  Me, the viewer, is at (0, 0, 0).  The plane of my monitor is at (x, y, 1) and I have a sphere out in space beyond the screen, off to the side not centered on the Z axis.  For each point of the sphere I compute where the point of intersection is between the plane of the monitor and the line between me and the point.  What I get is an ellipse.  Not surprising since a plane intersecting a cone at an angle would form an ellipse.  But if I look at a real sphere off to the side it looks like a sphere and not an ellipsoid.  If you draw an ellipse on a roadway and you view it from the correct spot it looks like a circle.  I presume you've seen stretched lettering on roads which are readable.&#xD;&#xA;&#xD;&#xA;So why when I draw the points of a 3D object exactly at the point of intersection with the line between the point and my eyes doesn't it look right?  Or more simply:&#xD;&#xA;Given P1 = (0, 0, 0),&#xD;&#xA;a plane 0X + 0Y + Z = 1,&#xD;&#xA;and P2 at (X2, Y2, Z2) assume Z2 &gt; 1 so that P2 is on the far side of the plane;&#xD;&#xA;where do I draw the point on my monitor such that a collection of points forming a sphere actually look like a sphere instead of an ellipsoid?  I've been using (X2/Z2, Y2/Z2) assuming the distance between me and the monitor is '1'.  But this gives me an ellipse." ContentLicense="CC BY-SA 4.0" />
  <row Id="37563" PostHistoryTypeId="1" PostId="12798" RevisionGUID="d64e00b7-08f3-4e17-a3d3-9d33c28b6c4e" CreationDate="2022-06-22T21:52:26.170" UserId="18588" Text="3D to view plane projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="37564" PostHistoryTypeId="3" PostId="12798" RevisionGUID="d64e00b7-08f3-4e17-a3d3-9d33c28b6c4e" CreationDate="2022-06-22T21:52:26.170" UserId="18588" Text="|rendering|mathematics|computational-geometry|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37572" PostHistoryTypeId="2" PostId="12800" RevisionGUID="586c5073-e69a-4462-b9bf-30a1b5fa6674" CreationDate="2022-06-24T09:43:01.027" UserId="13273" Text="I've implemented the Phong shading model and I would like to improve the brightness depending to the distance of the light, its spectrum, luminosity and the cameras exposure time.&#xD;&#xA;&#xD;&#xA;Each of your light sources has a position, spectrum and a luminosity.&#xD;&#xA;&#xD;&#xA;for example our sun has the following information:&#xD;&#xA;&#xD;&#xA;Spectrum: 6.25, 7.239, 7.1916&#xD;&#xA;Luminosity: 3.86e26 (I've found these values online)&#xD;&#xA;&#xD;&#xA;When rendering the scenario, for each fragment I am calculating the distance (meters) from the surface to the light (sun).&#xD;&#xA;&#xD;&#xA;How can I calculate some kind of brightness? I tried the following:&#xD;&#xA;&#xD;&#xA;    float brightness = luminosity / (4 * PI * pow(distance, 2))&#xD;&#xA;&#xD;&#xA;but when doing so, the brightness value is around &quot;42261897.7&quot; so it is way to high.&#xD;&#xA;&#xD;&#xA;afterwards the brightness multiplied with the phong shading model will be multiplied with the exposure time (0.001). So the final brightness is &quot;42261.8977&quot;.&#xD;&#xA;As you can imagine, this value is as well way to high... What am I doing wrong? How can I get a brightness factor which I can multiply to my color value?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37574" PostHistoryTypeId="1" PostId="12800" RevisionGUID="586c5073-e69a-4462-b9bf-30a1b5fa6674" CreationDate="2022-06-24T09:43:01.027" UserId="13273" Text="Light brightness calculation" ContentLicense="CC BY-SA 4.0" />
  <row Id="37575" PostHistoryTypeId="3" PostId="12800" RevisionGUID="586c5073-e69a-4462-b9bf-30a1b5fa6674" CreationDate="2022-06-24T09:43:01.027" UserId="13273" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37576" PostHistoryTypeId="50" PostId="12467" RevisionGUID="d43f7ff1-bebf-4228-a543-73239f25fc8a" CreationDate="2022-06-24T14:08:25.767" UserId="-1" />
  <row Id="37581" PostHistoryTypeId="2" PostId="12802" RevisionGUID="30461f98-5850-4d50-a252-24fc404f50c3" CreationDate="2022-06-24T15:19:19.067" UserId="18597" Text="To use a texture in an OpenGL shader, I have to write the Texture Unit to be used into a uniform variable:&#xD;&#xA;&#xD;&#xA;**source.c:**&#xD;&#xA;&#xD;&#xA;    // Write 0 to uniform variable&#xD;&#xA;    GLuint texSampler = glGetUniformLocation(program, &quot;texSampler&quot;);&#xD;&#xA;    glUniform1i(texSampler, 0);&#xD;&#xA;&#xD;&#xA;**shader.glsl**&#xD;&#xA;&#xD;&#xA;    uniform sampler2D texSampler;&#xD;&#xA;&#xD;&#xA;    void SomeFunction(vec2 coord)&#xD;&#xA;    {&#xD;&#xA;        vec4 data = texture(texSampler, coord);&#xD;&#xA;        // do something&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Why can't I just select the texture unit directly into the shader source, like this?&#xD;&#xA;&#xD;&#xA;**shader.glsl**&#xD;&#xA;&#xD;&#xA;    void SomeFunction(vec2 coord)&#xD;&#xA;    {&#xD;&#xA;        vec4 data = texture(0, coord);&#xD;&#xA;        // do something&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;What is the architecturial reason, that I have to use a uniform variable to pass the texture unit into the shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37583" PostHistoryTypeId="1" PostId="12802" RevisionGUID="30461f98-5850-4d50-a252-24fc404f50c3" CreationDate="2022-06-24T15:19:19.067" UserId="18597" Text="Why must texture samplers be uniform variables in GLSL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37584" PostHistoryTypeId="3" PostId="12802" RevisionGUID="30461f98-5850-4d50-a252-24fc404f50c3" CreationDate="2022-06-24T15:19:19.067" UserId="18597" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37585" PostHistoryTypeId="2" PostId="12803" RevisionGUID="5e92e43a-24cc-47b9-b607-5ea58e782a44" CreationDate="2022-06-24T15:56:23.333" UserId="2654" Text="&gt; Why can't I just select the texture unit directly into the shader source&#xD;&#xA;&#xD;&#xA;[You can:][1]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;layout(binding = 0) uniform sampler2D texSampler;&#xD;&#xA;&#xD;&#xA;void SomeFunction(vec2 coord)&#xD;&#xA;{&#xD;&#xA;    vec4 data = texture(texSampler, coord);&#xD;&#xA;    // do something&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Binding indices of course must be constant expressions.&#xD;&#xA;&#xD;&#xA;As for why you can't just use a number directly... how would GLSL know what *kind* of texture you're talking about? [GLSL samplers are typed][2], in accord with the kind of texture being accessed. This is important, as it also changes what parameters `texture` takes. If you're accessing a 1D texture, `texture` takes a single float as a texture coordinate. If you're accessing a cubemap, it takes a `vec3`. Etc.&#xD;&#xA;&#xD;&#xA;This is important for many reasons. One of them being that the logic for doing the fetch is often part of the *shader* itself. A shadow sampler might do the conditional logic within the shader. That wouldn't be possible if the GLSL didn't specify that it was doing a comparison test.&#xD;&#xA;&#xD;&#xA;Note that even [bindless textures][3], where you pass an integer that represents a texture object to the shader, still requires that you [convert the integer handle for the texture into a specific sampler type][4].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)#Binding_points&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Sampler_types&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Bindless_Texture#Purpose&#xD;&#xA;  [4]: https://www.khronos.org/opengl/wiki/Bindless_Texture#Handles_as_integers" ContentLicense="CC BY-SA 4.0" />
  <row Id="37589" PostHistoryTypeId="2" PostId="12804" RevisionGUID="06247554-0006-476e-9343-f2f19c56ba94" CreationDate="2022-06-25T03:43:50.933" UserId="18588" Text="Egads.  I was trying to place points for my sphere on my 3440x1440 monitors 860 pixels from right of center.  At 75% from left to right on the monitor.  I just arbitrarily choose the &quot;number&quot; 100 for my eye distance from my monitor and then worked backward to find the right size sphere and distance for it to appear where I wanted on the screen.  I got an exaggerated ellipse and had the hardest time figuring out why.  Yes, if you look at an ellipse at an angle it will look like a circle but it was way way to elliptical.&#xD;&#xA;&#xD;&#xA;I finally realize that my eyes are not at 100 pixels or about 3/4th of an inch from the screen.  At that angle to the ellipse it'd probably look right.  When I set the monitor as being 2200 pixels from my eyes and redid everything it looks fine.  Now I have a beautiful globular cluster in a galaxy of stars.  Looks quite realistic.  Coming soon to a github near you(I hope)." ContentLicense="CC BY-SA 4.0" />
  <row Id="37591" PostHistoryTypeId="5" PostId="12800" RevisionGUID="7a0d9747-602b-42b5-818d-1a34ad90e254" CreationDate="2022-06-27T11:26:40.757" UserId="13273" Comment="added 140 characters in body" Text="I've implemented the Phong shading model and I would like to improve the brightness depending to the distance of the light, its spectrum, luminosity and the cameras exposure time.&#xD;&#xA;&#xD;&#xA;Each of your light sources has a position, spectrum and a luminosity.&#xD;&#xA;&#xD;&#xA;for example our sun has the following information:&#xD;&#xA;&#xD;&#xA;Spectrum: 6.25, 7.239, 7.1916 (650 nm, 510nm, 475 nm of wavelength)&#xD;&#xA;Luminosity: 3.86e26 (I've found these values online)&#xD;&#xA;&#xD;&#xA;When rendering the scenario, for each fragment I am calculating the distance (meters) from the surface to the light (sun).&#xD;&#xA;&#xD;&#xA;How can I calculate some kind of brightness? I tried the following:&#xD;&#xA;&#xD;&#xA;    float brightness = luminosity / (4 * PI * pow(distance, 2))&#xD;&#xA;&#xD;&#xA;but when doing so, the brightness value is around &quot;42261897.7&quot; so it is way to high.&#xD;&#xA;&#xD;&#xA;afterwards the brightness multiplied with the phong shading model will be multiplied with the exposure time (0.001). So the final brightness is &quot;42261.8977&quot;.&#xD;&#xA;As you can imagine, this value is as well way to high... What am I doing wrong? How can I get a brightness factor which I can multiply to my color value?&#xD;&#xA;&#xD;&#xA;So how to bring the luminosity, exposure time and spectrum together into the phong lighting model?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37602" PostHistoryTypeId="2" PostId="12807" RevisionGUID="f002158f-1ef1-47b1-a33f-9bc0af9984d2" CreationDate="2022-06-28T13:16:36.340" UserId="18586" Text="I'm doing my own engine in college to display a wireframe on screen with an isometric projection but I literally can't find any literature about maths behind doing it by hand just for game engines which I'm not allowed to use.&#xD;&#xA;&#xD;&#xA;So how can I get implement an isometric projection by hand?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37604" PostHistoryTypeId="1" PostId="12807" RevisionGUID="f002158f-1ef1-47b1-a33f-9bc0af9984d2" CreationDate="2022-06-28T13:16:36.340" UserId="18586" Text="What projection matrix and world transformation do I need to have an isometric projection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37605" PostHistoryTypeId="3" PostId="12807" RevisionGUID="f002158f-1ef1-47b1-a33f-9bc0af9984d2" CreationDate="2022-06-28T13:16:36.340" UserId="18586" Text="|mathematics|projections|matrix|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37606" PostHistoryTypeId="5" PostId="12807" RevisionGUID="9ea45979-4c59-4787-8523-27d4b5703134" CreationDate="2022-06-28T14:17:49.560" UserId="18586" Comment="added matrix" Text="I'm doing my own engine in college to display a wireframe on screen with an isometric projection but I literally can't find any literature about maths behind doing it by hand just for game engines which I'm not allowed to use.&#xD;&#xA;&#xD;&#xA;So how can I get implement an isometric projection by hand?&#xD;&#xA;&#xD;&#xA;my projection matrix (row-major):&#xD;&#xA;[![Row-major][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/L3n8M.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37607" PostHistoryTypeId="50" PostId="10619" RevisionGUID="c94eb053-d68c-4e9f-bdb4-bc37a0bdec39" CreationDate="2022-06-28T17:07:00.700" UserId="-1" />
  <row Id="37613" PostHistoryTypeId="2" PostId="12809" RevisionGUID="456e81f7-2f34-4a87-8442-aa396c4f1a79" CreationDate="2022-06-29T10:47:30.450" UserId="7952" Text="Another way to formulate an Isometric projection is with the matrix:&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;  \left[ {\begin{array}{cc}&#xD;&#xA;    cos(\phi) &amp; sin(\phi)sin(\theta) &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; cos(\theta) &amp; 0 &amp;0 \\&#xD;&#xA;    sin(\phi) &amp; -cos(\phi)sin(\theta) &amp; 0 &amp; 0 \\&#xD;&#xA;    0 &amp; 0 &amp; 0 &amp; 1 \\&#xD;&#xA;  \end{array} } \right]&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Where $\phi$ and $\theta$ are the two rotational angles.&#xD;&#xA;&#xD;&#xA;Note that the 3rd column is all zero's indicating the plane of projection." ContentLicense="CC BY-SA 4.0" />
  <row Id="37615" PostHistoryTypeId="2" PostId="12810" RevisionGUID="af053907-fcba-478b-8246-e4e3b78668d0" CreationDate="2022-06-29T10:57:59.593" UserId="18586" Text="I found that the easiest way is to just use a Transformation Matrix like:&#xD;&#xA;[![This bad boi][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RUKXE.png&#xD;&#xA;&#xD;&#xA;And just adjust the Rz(a) to 45º and Rx(g) to 35.264º&#xD;&#xA;&#xD;&#xA;Or if -z to Rz(a) to -45º and Rx(g) to 215.264º" ContentLicense="CC BY-SA 4.0" />
  <row Id="37626" PostHistoryTypeId="2" PostId="12813" RevisionGUID="6d5a0f64-464d-4323-8da2-90dda1a80206" CreationDate="2022-06-30T23:18:58.027" UserId="18335" Text="I asked a version of this question on [GIS Stack Exchang][1]e three months ago, but did not receive an answer. So I am posting it here.&#xD;&#xA;&#xD;&#xA;I’ve written a simple Java application for rendering high-resolution terrestrial elevation data from the U.S. Geological Survey.  The algorithms, lighting model, and data sources I use are described in [Elevation from Cloud-Optimized GeoTIFFs (Parts 1 and 2)][3].&#xD;&#xA;&#xD;&#xA;While I have gotten satisfactory results for terrain, I’d like to improve the rendering of surface water (which is comes from a polygon-based dataset).  Can anyone recommend techniques that can be implemented with a reasonable effort?&#xD;&#xA;&#xD;&#xA;I’m not looking for a high-level of realism. Unfortunately, the flat surfaces I render don’t harmonize well with the terrain (I’ve attached a picture to show what I’m talking about).  So I am looking for something that will reduce the dissonance between the two kinds of data.&#xD;&#xA;&#xD;&#xA;Thank you in advance for your consideration.&#xD;&#xA;&#xD;&#xA;[![Shaded-relief image in a 2D map][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://gis.stackexchange.com/questions/425189/seeking-ways-to-improve-rendering-of-surface-water-in-shaded-relief-images&#xD;&#xA;  [2]: https://i.stack.imgur.com/fjTkf.jpg&#xD;&#xA;  [3]: https://gwlucastrig.github.io/GridfourDocs/notes/ElevationGeoTiff1.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="37628" PostHistoryTypeId="1" PostId="12813" RevisionGUID="6d5a0f64-464d-4323-8da2-90dda1a80206" CreationDate="2022-06-30T23:18:58.027" UserId="18335" Text="How to improve rendering of surface water in shaded-relief images" ContentLicense="CC BY-SA 4.0" />
  <row Id="37629" PostHistoryTypeId="3" PostId="12813" RevisionGUID="6d5a0f64-464d-4323-8da2-90dda1a80206" CreationDate="2022-06-30T23:18:58.027" UserId="18335" Text="|texture|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37630" PostHistoryTypeId="50" PostId="9926" RevisionGUID="e7ea2114-6909-4f9b-ad56-8075d30c4fb8" CreationDate="2022-07-01T00:06:35.617" UserId="-1" />
  <row Id="37636" PostHistoryTypeId="2" PostId="12815" RevisionGUID="b0c4db86-914d-4c75-b606-5e5576ed43d2" CreationDate="2022-07-01T19:50:39.707" UserId="7952" Text="You might look into &quot;mulitview&quot; it is fairly straight forward to setup and use. It does have limits on the number of views that can be rendered at the same time. Most examples are geared toward VR but it has obvious uses for a wide range of other situations like rendering cube maps. This would still mean multiple render passes but could get the number well under a hundred.  It is supported on both Vulkan and OpenGL." ContentLicense="CC BY-SA 4.0" />
  <row Id="37645" PostHistoryTypeId="2" PostId="12817" RevisionGUID="36ac5013-6486-48b9-a2ca-b4063c296ac9" CreationDate="2022-07-02T08:08:52.163" UserId="1763" Text="The context openGL instances learning.&#xD;&#xA;&#xD;&#xA;I want to transform a reference triangle to another one. So final goal is to have one triangle and the instance being a transformation of that initial triangle.&#xD;&#xA;&#xD;&#xA;The idea is to apply a Matrix4x4 transformation on that reference triangle to inject into a 3d rendering pipeline.&#xD;&#xA;&#xD;&#xA;Z is UP (wrong, but it doesn't matter for the calculus logic now, i should still have the shapes right, even on the wrong axis).&#xD;&#xA;Points are packed in a buffer.&#xD;&#xA;&#xD;&#xA;So far I have this:&#xD;&#xA;&#xD;&#xA;### Reference triangle, column major:&#xD;&#xA;&#xD;&#xA;      array &lt;double, 16&gt; reference_triangle {0, 2, 1, 1,&#xD;&#xA;                                             0, 0, 1, 1,&#xD;&#xA;                                             0, 0, 0, 1,&#xD;&#xA;                                             1, 1, 1, 1};&#xD;&#xA;&#xD;&#xA;x: {0,0,0], y:{2,0,0} and z:{1,1,0}&#xD;&#xA;&#xD;&#xA;### Second triangle given by:&#xD;&#xA;&#xD;&#xA;      array &lt;double, 16&gt; to_transf_triangle {5 , 42, 31 ,1,&#xD;&#xA;                                             10, 20, 11 ,1,&#xD;&#xA;                                             0,   0,  0 ,1,&#xD;&#xA;                                             1,   1,  1, 1};&#xD;&#xA;&#xD;&#xA;x: {5,10,0], y:{42,20,0} and z:{31,11,0}&#xD;&#xA;&#xD;&#xA;**Note:**&#xD;&#xA;Z axis is always 0 so my triangles could be considered 2D in that example (but won't always be the case, so please stick with 3D logic).&#xD;&#xA;&#xD;&#xA;The other values are set to one for the transformation.&#xD;&#xA;&#xD;&#xA;### Transformation pseudo code:&#xD;&#xA;&#xD;&#xA;    temp_transf = inverse(reference_triangle) * to_transf_triangle;&#xD;&#xA;&#xD;&#xA;Later, in the pipeline, when I do:&#xD;&#xA;&#xD;&#xA;    final_transf = reference_triangle * temp_transf;&#xD;&#xA;&#xD;&#xA;The final result in 3D is not what I expected: no translation (I expected it somehow because the resulting translation vector is null, I should add it from a point of the transform triangle) and triangles going visually awry.&#xD;&#xA;&#xD;&#xA;Now what is the way to transform one triangle given 3 points into another in a matrix 4x4 in a 3D opengl instance context?&#xD;&#xA;&#xD;&#xA;I don't need code that much, just the logic.&#xD;&#xA;&#xD;&#xA;Not even sure my method is a good starting point.&#xD;&#xA;&#xD;&#xA;Thanks," ContentLicense="CC BY-SA 4.0" />
  <row Id="37647" PostHistoryTypeId="1" PostId="12817" RevisionGUID="36ac5013-6486-48b9-a2ca-b4063c296ac9" CreationDate="2022-07-02T08:08:52.163" UserId="1763" Text="Convert one triangle to another in matrix4x4?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37648" PostHistoryTypeId="3" PostId="12817" RevisionGUID="36ac5013-6486-48b9-a2ca-b4063c296ac9" CreationDate="2022-07-02T08:08:52.163" UserId="1763" Text="|opengl|3d|transformations|matrix|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37649" PostHistoryTypeId="5" PostId="12817" RevisionGUID="a2c62af2-265f-4e10-8b7d-81f5b507aca4" CreationDate="2022-07-02T08:15:09.837" UserId="1763" Comment="added 52 characters in body" Text="The context openGL instances learning.&#xD;&#xA;&#xD;&#xA;I want to transform a reference triangle to another one. So final goal is to have one triangle and the instance being a transformation of that initial triangle.&#xD;&#xA;&#xD;&#xA;The idea is to apply a Matrix4x4 transformation on that reference triangle to inject into a 3d rendering pipeline.&#xD;&#xA;&#xD;&#xA;**The library I use needs a reference triangle and a packed array of matrix 4x4 to tell it the transforms applied to the reference points.**&#xD;&#xA;&#xD;&#xA;Z is UP (wrong, but it doesn't matter for the calculus logic now, i should still have the shapes right, even on the wrong axis).&#xD;&#xA;Points are packed in a buffer.&#xD;&#xA;&#xD;&#xA;So far I have this:&#xD;&#xA;&#xD;&#xA;### Reference triangle, column major:&#xD;&#xA;&#xD;&#xA;      array &lt;double, 16&gt; reference_triangle {0, 2, 1, 1,&#xD;&#xA;                                             0, 0, 1, 1,&#xD;&#xA;                                             0, 0, 0, 1,&#xD;&#xA;                                             1, 1, 1, 1};&#xD;&#xA;&#xD;&#xA;x: {0,0,0], y:{2,0,0} and z:{1,1,0}&#xD;&#xA;&#xD;&#xA;### Second triangle given by:&#xD;&#xA;&#xD;&#xA;      array &lt;double, 16&gt; to_transf_triangle {5 , 42, 31 ,1,&#xD;&#xA;                                             10, 20, 11 ,1,&#xD;&#xA;                                             0,   0,  0 ,1,&#xD;&#xA;                                             1,   1,  1, 1};&#xD;&#xA;&#xD;&#xA;x: {5,10,0], y:{42,20,0} and z:{31,11,0}&#xD;&#xA;&#xD;&#xA;**Note:**&#xD;&#xA;Z axis is always 0 so my triangles could be considered 2D in that example (but won't always be the case, so please stick with 3D logic).&#xD;&#xA;&#xD;&#xA;The other values are set to one for the transformation.&#xD;&#xA;&#xD;&#xA;### Transformation pseudo code:&#xD;&#xA;&#xD;&#xA;    temp_transf = inverse(reference_triangle) * to_transf_triangle;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The final result in 3D is not what I expected: no translation (I expected it somehow because the resulting translation vector is null, I should add it from a point of the transform triangle) and triangles going visually awry.&#xD;&#xA;&#xD;&#xA;**There must be a missing step.**&#xD;&#xA;&#xD;&#xA;Now what is the way to transform one triangle given 3 points into another in a matrix 4x4 in a 3D opengl instance context?&#xD;&#xA;&#xD;&#xA;I don't need code that much, just the logic.&#xD;&#xA;&#xD;&#xA;Not even sure my method is a good starting point.&#xD;&#xA;&#xD;&#xA;Thanks," ContentLicense="CC BY-SA 4.0" />
  <row Id="37653" PostHistoryTypeId="50" PostId="12503" RevisionGUID="83fc76e7-d1af-40a4-b793-0907b787d341" CreationDate="2022-07-02T21:07:20.707" UserId="-1" />
  <row Id="37655" PostHistoryTypeId="2" PostId="12819" RevisionGUID="b90fa9fb-cd37-4203-bde2-5a5b883709f9" CreationDate="2022-07-03T17:07:46.900" UserId="16349" Text="I am given this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and asked to determine the transformation matrix that took me from ΑΒΓΔΕ(lets call it ABCDE for convenience) to Α'Β'Γ'Δ'Ε' (A'B'C'D'E'). &#xD;&#xA;&#xD;&#xA;I am also given the solution, so as to be able to verify my process.&#xD;&#xA;From the image I can easily tell that ABCDE has been scaled by 2, rotated by π, and transposed by some vector, in that order. &#xD;&#xA;&#xD;&#xA;Question 1. The solution says that the values for the transposition are dx =10, dy=11. It is unclear to me how these values where extracted.&#xD;&#xA;&#xD;&#xA;Question 2. I am unsure as to the order of the transformations. Is there any way to tell for sure? My guess happened to agree with the solution but it was just that, a guess. &#xD;&#xA;&#xD;&#xA;Question 3. Possessing the matrices that express each object:&#xD;&#xA;&#xD;&#xA; [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;is it possible to extract the transformation matrix if the image was not provided? and if so, how?&#xD;&#xA;&#xD;&#xA;I am aware that I am posing multiple questions but they all concern one subject and are very related to eachother. Any pointers would be helpful. Thanks. &#xD;&#xA;&#xD;&#xA;(My classes are not in english, apologies if the terms do not match up very well)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/elqIe.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LMsDq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37657" PostHistoryTypeId="1" PostId="12819" RevisionGUID="b90fa9fb-cd37-4203-bde2-5a5b883709f9" CreationDate="2022-07-03T17:07:46.900" UserId="16349" Text="How to determine transformation matrix for an object given a graph?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37658" PostHistoryTypeId="3" PostId="12819" RevisionGUID="b90fa9fb-cd37-4203-bde2-5a5b883709f9" CreationDate="2022-07-03T17:07:46.900" UserId="16349" Text="|transformations|mathematics|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37659" PostHistoryTypeId="2" PostId="12820" RevisionGUID="0a0572cd-881b-4aaf-8062-fc73bfbcdc73" CreationDate="2022-07-04T00:07:11.993" UserId="120" Text="This kind of problem is usually called shape matching. It is possible to deduce the transformation between two given sets of positions.&#xD;&#xA;&#xD;&#xA;You can learn more about the shape matching here&#xD;&#xA;&#xD;&#xA;Müller, Matthias, et al. &quot;Meshless deformations based on shape matching.&quot; ACM transactions on graphics (TOG) 24.3 (2005): 471-478.&#xD;&#xA;&#xD;&#xA;https://dl.acm.org/doi/abs/10.1145/1073204.1073216?casa_token=ByW2rb3f-VgAAAAA:6wMJ5MT3moK_0lRPZtDDxFI0B16Nw8b5hcI-dclZaUV3RDJgeMUYTR7Sk7vE-4qMQ_6wHmlxReh5&#xD;&#xA;&#xD;&#xA;(hint: no need to finish the whole paper. Section 3.3 is all you need)&#xD;&#xA;&#xD;&#xA;-----------&#xD;&#xA;Just apply the paper idea here to your question as a concrete example.&#xD;&#xA;&#xD;&#xA;Denote the source point set as $x^0_i$ ($i=1..5$), and target point set as $x_i$.&#xD;&#xA;Let $t^0$ be the center of source points, and $t$ be the center of target points.&#xD;&#xA;&#xD;&#xA;Let $q_i$ be the source point set minus the center: $q_i = x^0_i-t^0$.&#xD;&#xA;Similarly let $p_i$ be the target point set minus the center: $p_i=x_i -t$.&#xD;&#xA;&#xD;&#xA;Then suppose we have found a transformation $A = R S$ (rotation and scaling), and the transformation maps our source point set to $A q_i + t^0$.&#xD;&#xA;We want its distance to the target as small as possible. That is, minimize this:&#xD;&#xA;$$&#xD;&#xA;F = \sum_i (A q_i - p_i)^2&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In order to minimize $F$ we want to take derivative of $F$ and set it to 0 and then solve for A.&#xD;&#xA;That should give you&#xD;&#xA;$$&#xD;&#xA;A =&#xD;&#xA;(\sum_i p_i q_i^T)(\sum_i q_i q_i^T)^{-1}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;That $A$ is the transform associates the source and the target point sets.&#xD;&#xA;Further take QR decomposition of $A$ should give you the rotation and scaling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;In your case, (I am dropping z coordinates)&#xD;&#xA;&#xD;&#xA;Centers:&#xD;&#xA;```&#xD;&#xA;t0={2, 13/5}&#xD;&#xA;t={7, 24/5}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Coordinates with center translations removed:&#xD;&#xA;```&#xD;&#xA;p={{0, 2, 2, -2, -2}, {-24/5, -4/5, 16/5, 16/5, -4/5}}&#xD;&#xA;q={{0, -1, -1, 1, 1}, {12/5, 2/5, -8/5, -8/5, 2/5}}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;pq={{-8, 0}, {0, -112/5}}&#xD;&#xA;qq={{4, 0}, {0, 56/5}}&#xD;&#xA;A={{-2, 0}, {0, -2}}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then the expression `A q + t` should give you the target point set.&#xD;&#xA;&#xD;&#xA;------------------&#xD;&#xA;&#xD;&#xA;This should give you a general solution to this problem without visualizing it.&#xD;&#xA;&#xD;&#xA;For your question on transformation order: you can freely specify the order as you want. (that $A q + t$ thing).&#xD;&#xA;&#xD;&#xA;For your question on deriving the translation: it should be the center of target point set, i.e. `{7, 24/5}` assuming the rotation happens at the center.&#xD;&#xA;&#xD;&#xA;If you expand the transformation a bit:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;A q + t &amp;=&#xD;&#xA;A (x^0 - t^0) + t \\&#xD;&#xA;&amp;= A x^0 - A t^0 + t \\&#xD;&#xA;&amp;= A x^0 + (- A t^0 + t)&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;The given solution might assume the rotation happens at the origin. In that case the translation is $(-A t^0 + t)$, and it is `{11, 10}`.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37662" PostHistoryTypeId="2" PostId="12821" RevisionGUID="06c1edc5-a433-44bd-8be7-cbaca366b001" CreationDate="2022-07-04T07:11:24.317" UserId="18304" Text="I am developing Vulkan games. It is still a basic rendering program with some cornel boxed data. Apart from testing hairs, calculating fps, what are some tools to apply to test the performance of such a program? Would also appreciate for some resources to read up on." ContentLicense="CC BY-SA 4.0" />
  <row Id="37664" PostHistoryTypeId="1" PostId="12821" RevisionGUID="06c1edc5-a433-44bd-8be7-cbaca366b001" CreationDate="2022-07-04T07:11:24.317" UserId="18304" Text="What are some tools to test performance of a Vulkan based game?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37665" PostHistoryTypeId="3" PostId="12821" RevisionGUID="06c1edc5-a433-44bd-8be7-cbaca366b001" CreationDate="2022-07-04T07:11:24.317" UserId="18304" Text="|vulkan|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37666" PostHistoryTypeId="2" PostId="12822" RevisionGUID="45152fe9-8e8a-4c67-a471-aae5f073c05b" CreationDate="2022-07-04T09:54:37.507" UserId="13095" Text="**Regarding question 3:**&#xD;&#xA;&#xD;&#xA;There are many ways to solve this problem. Some answers are [here](https://math.stackexchange.com/q/186286/776637)  and [here](https://math.stackexchange.com/q/557507/776637). You can also create a system of equations by writing down the matrix multiplication symbolically.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;X \cdot A = B&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$X$ is the transformation matrix you are looking for, $A$ your matrix before the transformation, and $B$ the matrix after the transformation. So you can write:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}&amp;x_{12}&amp;x_{13}\\&#xD;&#xA;x_{21}&amp;x_{22}&amp;x_{23}\\&#xD;&#xA;x_{31}&amp;x_{32}&amp;x_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{12}&amp;a_{13}\\&#xD;&#xA;a_{21}&amp;a_{22}&amp;a_{23}\\&#xD;&#xA;a_{31}&amp;a_{32}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{11}&amp;b_{12}&amp;b_{13}\\&#xD;&#xA;b_{21}&amp;b_{22}&amp;b_{23}\\&#xD;&#xA;b_{31}&amp;b_{32}&amp;b_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with the individual matrix products being: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;b_{11} =&amp;x_{11}\cdot a_{11} + x_{12}\cdot a_{21} + x_{13}\cdot a_{31}\\&#xD;&#xA;b_{12} =&amp;x_{11}\cdot a_{12} + x_{12}\cdot a_{22} + x_{13}\cdot a_{32}\\&#xD;&#xA;b_{13} =&amp;x_{11}\cdot a_{13} + x_{12}\cdot a_{23} + x_{13}\cdot a_{33}\\\\&#xD;&#xA;b_{21} =&amp;x_{21}\cdot a_{11} + x_{22}\cdot a_{21} + x_{23}\cdot a_{31}\\&#xD;&#xA;b_{22} =&amp;x_{21}\cdot a_{12} + x_{22}\cdot a_{22} + x_{23}\cdot a_{32}\\&#xD;&#xA;b_{23} =&amp;x_{21}\cdot a_{13} + x_{22}\cdot a_{23} + x_{23}\cdot a_{33}\\\\&#xD;&#xA;b_{31} =&amp;x_{31}\cdot a_{11} + x_{32}\cdot a_{21} + x_{33}\cdot a_{31}\\&#xD;&#xA;b_{32} =&amp;x_{31}\cdot a_{12} + x_{32}\cdot a_{22} + x_{33}\cdot a_{32}\\&#xD;&#xA;b_{33} =&amp;x_{31}\cdot a_{13} + x_{32}\cdot a_{23} + x_{33}\cdot a_{33}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or in matrix form:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}\\&#xD;&#xA;x_{12}\\&#xD;&#xA;x_{13}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{11}\\&#xD;&#xA;b_{12}\\&#xD;&#xA;b_{13}&#xD;&#xA;\end{bmatrix}\\\\&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{21}\\&#xD;&#xA;x_{22}\\&#xD;&#xA;x_{23}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{21}\\&#xD;&#xA;b_{22}\\&#xD;&#xA;b_{23}&#xD;&#xA;\end{bmatrix}\\\\&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{31}\\&#xD;&#xA;x_{32}\\&#xD;&#xA;x_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{31}\\&#xD;&#xA;b_{32}\\&#xD;&#xA;b_{33}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now you have 9 equations for 9 unknowns that you can solve with Gaussian elimination, LU decomposition, or any other linear solver you are familiar with.&#xD;&#xA;&#xD;&#xA;You might say that those are just 3x3 matrices and yours are 3x5. Adding those two columns yourself should be easy, but you actually don't need them to determine the matrix. It would give you an overdetermined system of equations. Just pick 3 columns instead (but the same from both matrices).&#xD;&#xA;&#xD;&#xA;Note that if you combine the 3 matrix-vector equations into a single matrix-matrix equation, you basically end up with [something similar to this solution](https://math.stackexchange.com/a/2040965/776637). All you need to do is to multiply by the inverse of $A^T$ and then transpose everything. Then you have the same equation.&#xD;&#xA;&#xD;&#xA;I wrote a short python script to check if everything is correct that I wrote:&#xD;&#xA;&#xD;&#xA;~~~ python&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;a = np.array([[2, 5, 1], [1, 3, 1], [1, 1, 1], [3, 1, 1], [3, 3, 1]]).transpose()&#xD;&#xA;b = np.array([[7, 0, 1], [9, 4, 1], [9, 8, 1], [5, 8, 1], [5, 4, 1]]).transpose()&#xD;&#xA;&#xD;&#xA;# pick first 3 vectors&#xD;&#xA;a_red = a[:, :3]&#xD;&#xA;b_red = b[:, :3]&#xD;&#xA;&#xD;&#xA;# solve for each row vector of x&#xD;&#xA;x_1 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 0])&#xD;&#xA;x_2 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 1])&#xD;&#xA;x_3 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 2])&#xD;&#xA;&#xD;&#xA;# combine vectors to the transformation matrix we are looking for&#xD;&#xA;x = np.array([x_1, x_2, x_3])&#xD;&#xA;print(x)&#xD;&#xA;&#xD;&#xA;# check if x*a yields b&#xD;&#xA;b_check = np.matmul(x, a)&#xD;&#xA;print(b_check)&#xD;&#xA;assert np.allclose(b, b_check)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The assertion holds and the matrix looks like expected:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;11\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;10\\&#xD;&#xA;0&amp;0&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Seems like you swapped the numbers in `dx` and `dy` cause I got `dx=11` and `dy=10`. The first two rows of the last column represent the translation vector as [described here](https://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf).&#xD;&#xA;The last row is `(0, 0, 1)` as it should be since we are not doing any transformation into the 3. dimension.&#xD;&#xA;&#xD;&#xA;I left out the upper left 2x2 matrices for you to find out. As another hint, $x_{11}=x_{22}$ and $x_{12}=x_{21}$. I think you will manage to figure them out. If you can't, just ask for help or run the python script but I recommend trying it yourself.&#xD;&#xA;&#xD;&#xA;**Regarding question 2**&#xD;&#xA;&#xD;&#xA;The usual forward order is scale, rotate, and translate for reasons I won't further explain. But this is not a &quot;rule&quot; and you can not rely on that. It is just the approach that makes the most sense for us humans. However, looking at the graphics and the calculated matrix, they followed this order.&#xD;&#xA;&#xD;&#xA;**Regarding question 1**&#xD;&#xA;&#xD;&#xA;Now with the information, I gave you for question 2, it should be obvious. Just pick the point Γ and follow it if you first apply the scaling, then the rotation, and finally the translation. If you manage this, you should also be able to just guess the remaining numbers of the matrix with all the information you got, at least if you understood all the involved substeps and the basic transformation matrices ([check this link again](https://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf)). You will also see that `dx` and `dy` are indeed swapped in your question." ContentLicense="CC BY-SA 4.0" />
  <row Id="37668" PostHistoryTypeId="5" PostId="12819" RevisionGUID="e25bcde3-7d7b-4e6f-9353-1f6ca66fbf77" CreationDate="2022-07-04T09:56:29.770" UserId="13095" Comment="Fix some grammar and spelling" Text="I am given this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;and asked to determine the transformation matrix that took me from ΑΒΓΔΕ(let's call it ABCDE for convenience) to Α'Β'Γ'Δ'Ε' (A'B'C'D'E'). &#xD;&#xA;&#xD;&#xA;I am also given the solution, so as to be able to verify my process.&#xD;&#xA;From the image, I can easily tell that ABCDE has been scaled by 2, rotated by π, and transposed by some vector, in that order. &#xD;&#xA;&#xD;&#xA;Question 1. The solution says that the values for the transposition are dx =10, dy=11. It is unclear to me how these values were extracted.&#xD;&#xA;&#xD;&#xA;Question 2. I am unsure as to the order of the transformations. Is there any way to tell for sure? My guess happened to agree with the solution but it was just that, a guess. &#xD;&#xA;&#xD;&#xA;Question 3. Possessing the matrices that express each object:&#xD;&#xA;&#xD;&#xA; [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;is it possible to extract the transformation matrix if the image was not provided? and if so, how?&#xD;&#xA;&#xD;&#xA;I am aware that I am posing multiple questions but they all concern one subject and are very related to each other. Any pointers would be helpful. Thanks. &#xD;&#xA;&#xD;&#xA;(My classes are not in English, apologies if the terms do not match up very well)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/elqIe.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LMsDq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37669" PostHistoryTypeId="5" PostId="12822" RevisionGUID="b0845358-00fe-4faa-85d2-802855110f55" CreationDate="2022-07-04T10:06:45.647" UserId="13095" Comment="added 55 characters in body" Text="**Regarding question 3:**&#xD;&#xA;&#xD;&#xA;There are many ways to solve this problem. Some answers are [here](https://math.stackexchange.com/q/186286/776637)  and [here](https://math.stackexchange.com/q/557507/776637). You can also create a system of equations by writing down the matrix multiplication symbolically.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;X \cdot A = B&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$X$ is the transformation matrix you are looking for, $A$ your matrix before the transformation, and $B$ the matrix after the transformation. So you can write:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}&amp;x_{12}&amp;x_{13}\\&#xD;&#xA;x_{21}&amp;x_{22}&amp;x_{23}\\&#xD;&#xA;x_{31}&amp;x_{32}&amp;x_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{12}&amp;a_{13}\\&#xD;&#xA;a_{21}&amp;a_{22}&amp;a_{23}\\&#xD;&#xA;a_{31}&amp;a_{32}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{11}&amp;b_{12}&amp;b_{13}\\&#xD;&#xA;b_{21}&amp;b_{22}&amp;b_{23}\\&#xD;&#xA;b_{31}&amp;b_{32}&amp;b_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with the individual matrix products being: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;b_{11} =&amp;x_{11}\cdot a_{11} + x_{12}\cdot a_{21} + x_{13}\cdot a_{31}\\&#xD;&#xA;b_{12} =&amp;x_{11}\cdot a_{12} + x_{12}\cdot a_{22} + x_{13}\cdot a_{32}\\&#xD;&#xA;b_{13} =&amp;x_{11}\cdot a_{13} + x_{12}\cdot a_{23} + x_{13}\cdot a_{33}\\\\&#xD;&#xA;b_{21} =&amp;x_{21}\cdot a_{11} + x_{22}\cdot a_{21} + x_{23}\cdot a_{31}\\&#xD;&#xA;b_{22} =&amp;x_{21}\cdot a_{12} + x_{22}\cdot a_{22} + x_{23}\cdot a_{32}\\&#xD;&#xA;b_{23} =&amp;x_{21}\cdot a_{13} + x_{22}\cdot a_{23} + x_{23}\cdot a_{33}\\\\&#xD;&#xA;b_{31} =&amp;x_{31}\cdot a_{11} + x_{32}\cdot a_{21} + x_{33}\cdot a_{31}\\&#xD;&#xA;b_{32} =&amp;x_{31}\cdot a_{12} + x_{32}\cdot a_{22} + x_{33}\cdot a_{32}\\&#xD;&#xA;b_{33} =&amp;x_{31}\cdot a_{13} + x_{32}\cdot a_{23} + x_{33}\cdot a_{33}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or in matrix form:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}\\&#xD;&#xA;x_{12}\\&#xD;&#xA;x_{13}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{11}\\&#xD;&#xA;b_{12}\\&#xD;&#xA;b_{13}&#xD;&#xA;\end{bmatrix}\\\\&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{21}\\&#xD;&#xA;x_{22}\\&#xD;&#xA;x_{23}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{21}\\&#xD;&#xA;b_{22}\\&#xD;&#xA;b_{23}&#xD;&#xA;\end{bmatrix}\\\\&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{31}\\&#xD;&#xA;x_{32}\\&#xD;&#xA;x_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{31}\\&#xD;&#xA;b_{32}\\&#xD;&#xA;b_{33}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&gt; **Watch out:** the matrix here is transposed -&gt; $A^T$&#xD;&#xA;&#xD;&#xA;Now you have 9 equations for 9 unknowns that you can solve with Gaussian elimination, LU decomposition, or any other linear solver you are familiar with.&#xD;&#xA;&#xD;&#xA;You might say that those are just 3x3 matrices and yours are 3x5. Adding those two columns yourself should be easy, but you actually don't need them to determine the matrix. It would give you an overdetermined system of equations. Just pick 3 columns instead (but the same from both matrices).&#xD;&#xA;&#xD;&#xA;Note that if you combine the 3 matrix-vector equations into a single matrix-matrix equation, you basically end up with [something similar to this solution](https://math.stackexchange.com/a/2040965/776637). All you need to do is to multiply by the inverse of $A^T$ and then transpose everything. Then you have the same equation.&#xD;&#xA;&#xD;&#xA;I wrote a short python script to check if everything is correct that I wrote:&#xD;&#xA;&#xD;&#xA;~~~ python&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;a = np.array([[2, 5, 1], [1, 3, 1], [1, 1, 1], [3, 1, 1], [3, 3, 1]]).transpose()&#xD;&#xA;b = np.array([[7, 0, 1], [9, 4, 1], [9, 8, 1], [5, 8, 1], [5, 4, 1]]).transpose()&#xD;&#xA;&#xD;&#xA;# pick first 3 vectors&#xD;&#xA;a_red = a[:, :3]&#xD;&#xA;b_red = b[:, :3]&#xD;&#xA;&#xD;&#xA;# solve for each row vector of x&#xD;&#xA;x_1 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 0])&#xD;&#xA;x_2 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 1])&#xD;&#xA;x_3 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 2])&#xD;&#xA;&#xD;&#xA;# combine vectors to the transformation matrix we are looking for&#xD;&#xA;x = np.array([x_1, x_2, x_3])&#xD;&#xA;print(x)&#xD;&#xA;&#xD;&#xA;# check if x*a yields b&#xD;&#xA;b_check = np.matmul(x, a)&#xD;&#xA;print(b_check)&#xD;&#xA;assert np.allclose(b, b_check)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The assertion holds and the matrix looks like expected:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;11\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;10\\&#xD;&#xA;0&amp;0&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Seems like you swapped the numbers in `dx` and `dy` cause I got `dx=11` and `dy=10`. The first two rows of the last column represent the translation vector as [described here](https://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf).&#xD;&#xA;The last row is `(0, 0, 1)` as it should be since we are not doing any transformation into the 3. dimension.&#xD;&#xA;&#xD;&#xA;I left out the upper left 2x2 matrices for you to find out. As another hint, $x_{11}=x_{22}$ and $x_{12}=x_{21}$. I think you will manage to figure them out. If you can't, just ask for help or run the python script but I recommend trying it yourself.&#xD;&#xA;&#xD;&#xA;**Regarding question 2**&#xD;&#xA;&#xD;&#xA;The usual forward order is scale, rotate, and translate for reasons I won't further explain. But this is not a &quot;rule&quot; and you can not rely on that. It is just the approach that makes the most sense for us humans. However, looking at the graphics and the calculated matrix, they followed this order.&#xD;&#xA;&#xD;&#xA;**Regarding question 1**&#xD;&#xA;&#xD;&#xA;Now with the information, I gave you for question 2, it should be obvious. Just pick the point Γ and follow it if you first apply the scaling, then the rotation, and finally the translation. If you manage this, you should also be able to just guess the remaining numbers of the matrix with all the information you got, at least if you understood all the involved substeps and the basic transformation matrices ([check this link again](https://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf)). You will also see that `dx` and `dy` are indeed swapped in your question." ContentLicense="CC BY-SA 4.0" />
  <row Id="37670" PostHistoryTypeId="5" PostId="12822" RevisionGUID="29771f50-ea3b-4612-a8d6-115313d539a2" CreationDate="2022-07-04T10:11:48.147" UserId="13095" Comment="added 55 characters in body" Text="**Regarding question 3:**&#xD;&#xA;&#xD;&#xA;There are many ways to solve this problem. Some answers are [here](https://math.stackexchange.com/q/186286/776637)  and [here](https://math.stackexchange.com/q/557507/776637). You can also create a system of equations by writing down the matrix multiplication symbolically.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;X \cdot A = B&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$X$ is the transformation matrix you are looking for, $A$ your matrix before the transformation, and $B$ the matrix after the transformation. So you can write:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}&amp;x_{12}&amp;x_{13}\\&#xD;&#xA;x_{21}&amp;x_{22}&amp;x_{23}\\&#xD;&#xA;x_{31}&amp;x_{32}&amp;x_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{12}&amp;a_{13}\\&#xD;&#xA;a_{21}&amp;a_{22}&amp;a_{23}\\&#xD;&#xA;a_{31}&amp;a_{32}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{11}&amp;b_{12}&amp;b_{13}\\&#xD;&#xA;b_{21}&amp;b_{22}&amp;b_{23}\\&#xD;&#xA;b_{31}&amp;b_{32}&amp;b_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with the individual matrix products being: &#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;b_{11} =&amp;x_{11}\cdot a_{11} + x_{12}\cdot a_{21} + x_{13}\cdot a_{31}\\&#xD;&#xA;b_{12} =&amp;x_{11}\cdot a_{12} + x_{12}\cdot a_{22} + x_{13}\cdot a_{32}\\&#xD;&#xA;b_{13} =&amp;x_{11}\cdot a_{13} + x_{12}\cdot a_{23} + x_{13}\cdot a_{33}\\\\&#xD;&#xA;b_{21} =&amp;x_{21}\cdot a_{11} + x_{22}\cdot a_{21} + x_{23}\cdot a_{31}\\&#xD;&#xA;b_{22} =&amp;x_{21}\cdot a_{12} + x_{22}\cdot a_{22} + x_{23}\cdot a_{32}\\&#xD;&#xA;b_{23} =&amp;x_{21}\cdot a_{13} + x_{22}\cdot a_{23} + x_{23}\cdot a_{33}\\\\&#xD;&#xA;b_{31} =&amp;x_{31}\cdot a_{11} + x_{32}\cdot a_{21} + x_{33}\cdot a_{31}\\&#xD;&#xA;b_{32} =&amp;x_{31}\cdot a_{12} + x_{32}\cdot a_{22} + x_{33}\cdot a_{32}\\&#xD;&#xA;b_{33} =&amp;x_{31}\cdot a_{13} + x_{32}\cdot a_{23} + x_{33}\cdot a_{33}&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;or in matrix form:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{matrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}\\&#xD;&#xA;x_{12}\\&#xD;&#xA;x_{13}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{11}\\&#xD;&#xA;b_{12}\\&#xD;&#xA;b_{13}&#xD;&#xA;\end{bmatrix}\\\\&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{21}\\&#xD;&#xA;x_{22}\\&#xD;&#xA;x_{23}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{21}\\&#xD;&#xA;b_{22}\\&#xD;&#xA;b_{23}&#xD;&#xA;\end{bmatrix}\\\\&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;a_{11}&amp;a_{21}&amp;a_{31}\\&#xD;&#xA;a_{12}&amp;a_{22}&amp;a_{32}\\&#xD;&#xA;a_{13}&amp;a_{23}&amp;a_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\cdot&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{31}\\&#xD;&#xA;x_{32}\\&#xD;&#xA;x_{33}&#xD;&#xA;\end{bmatrix}&#xD;&#xA;=\begin{bmatrix}&#xD;&#xA;b_{31}\\&#xD;&#xA;b_{32}\\&#xD;&#xA;b_{33}&#xD;&#xA;\end{bmatrix}\\&#xD;&#xA;\end{matrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&gt; **Watch out:** the matrix here is transposed -&gt; $A^T$&#xD;&#xA;&#xD;&#xA;Now you have 9 equations for 9 unknowns that you can solve with Gaussian elimination, LU decomposition, or any other linear solver you are familiar with.&#xD;&#xA;&#xD;&#xA;You might say that those are just 3x3 matrices and yours are 3x5. Adding those two columns yourself should be easy, but you actually don't need them to determine the matrix. It would give you an overdetermined system of equations. Just pick 3 columns instead (but the same from both matrices).&#xD;&#xA;&#xD;&#xA;Note that if you combine the 3 matrix-vector equations into a single matrix-matrix equation, you basically end up with [something similar to this solution](https://math.stackexchange.com/a/2040965/776637). All you need to do is to multiply by the inverse of $A^T$ and then transpose everything. Then you have the same equation.&#xD;&#xA;&#xD;&#xA;I wrote a short python script to check if everything is correct that I wrote:&#xD;&#xA;&#xD;&#xA;~~~ python&#xD;&#xA;import numpy as np&#xD;&#xA;&#xD;&#xA;a = np.array([[2, 5, 1], [1, 3, 1], [1, 1, 1], [3, 1, 1], [3, 3, 1]]).transpose()&#xD;&#xA;b = np.array([[7, 0, 1], [9, 4, 1], [9, 8, 1], [5, 8, 1], [5, 4, 1]]).transpose()&#xD;&#xA;&#xD;&#xA;# pick first 3 vectors&#xD;&#xA;a_red = a[:, :3]&#xD;&#xA;b_red = b[:, :3]&#xD;&#xA;&#xD;&#xA;# solve for each row vector of x&#xD;&#xA;x_1 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 0])&#xD;&#xA;x_2 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 1])&#xD;&#xA;x_3 = np.linalg.solve(a_red.transpose(), b_red.transpose()[:, 2])&#xD;&#xA;&#xD;&#xA;# combine vectors to the transformation matrix we are looking for&#xD;&#xA;x = np.array([x_1, x_2, x_3])&#xD;&#xA;print(x)&#xD;&#xA;&#xD;&#xA;# check if x*a yields b&#xD;&#xA;b_check = np.matmul(x, a)&#xD;&#xA;print(b_check)&#xD;&#xA;assert np.allclose(b, b_check)&#xD;&#xA;~~~&#xD;&#xA;&#xD;&#xA;The assertion holds and the matrix looks like expected:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x_{11}&amp;x_{12}&amp;11\\&#xD;&#xA;x_{21}&amp;x_{22}&amp;10\\&#xD;&#xA;0&amp;0&amp;1&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Seems like you swapped the numbers in `dx` and `dy` cause I got `dx=11` and `dy=10`. The first two rows of the last column represent the translation vector as [described here](https://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf).&#xD;&#xA;The last row is `(0, 0, 1)` as it should be since we are not doing any transformation into the 3. dimension.&#xD;&#xA;&#xD;&#xA;I left out the upper left 2x2 matrices for you to find out. As another hint, $x_{11}=x_{22}$ and $x_{12}=x_{21}$. I think you will manage to figure them out. If you can't, just ask for help or run the python script but I recommend trying it yourself.&#xD;&#xA;&#xD;&#xA;**Regarding question 2**&#xD;&#xA;&#xD;&#xA;The usual forward order is scale, rotate, and translate for reasons I won't further explain. But this is not a &quot;rule&quot; and you can not rely on that. It is just the approach that makes the most sense for us humans. However, looking at the graphics and the calculated matrix, they followed this order.&#xD;&#xA;&#xD;&#xA;**Regarding question 1**&#xD;&#xA;&#xD;&#xA;Now with the information, I gave you for question 2, it should be obvious. Just pick the point Γ and follow it if you first apply the scaling, then the rotation, and finally the translation. If you manage this, you should also be able to just guess the remaining numbers of the matrix with all the information you got, at least if you understood all the involved substeps and the basic transformation matrices ([check this link again](https://web.cse.ohio-state.edu/~shen.94/681/Site/Slides_files/transformation_review.pdf)). You will also see that `dx` and `dy` are indeed swapped in your question." ContentLicense="CC BY-SA 4.0" />
  <row Id="37671" PostHistoryTypeId="2" PostId="12823" RevisionGUID="86d0f907-f6a2-46dc-aec8-cdfe20afa142" CreationDate="2022-07-04T10:25:14.487" UserId="7952" Text="The Vulkan layers provide some basic performance help. They are very easy to use (can be turned on via the Vulkan Configurator) and provide basic performance diagnostics. This is a good tool to just turn on and run regularly, its output gives enough info to look up whatever issue it finds in the spec. It even provides a basic fps calculator. The tool can be found in the vulkan install location bin/vkconfig.exe. Once the tool is running look under message severity and make sure performance is checked.&#xD;&#xA;&#xD;&#xA;Render Doc: There is a dedicated Vulkan layer just to help out with using RenderDoc. It is advertised as a debugger but provides excellent information about GPU state which is very helpful with many performance tasks such as helping tweak shader programs.&#xD;&#xA;&#xD;&#xA;Vulkan itself provides performance aids like VK_KHR_performance_query. Use vkcmdwritetimestamp (google it for pages that help with its usage) to time commands in a vulkan queue.&#xD;&#xA;&#xD;&#xA;As you can image the list goes on and on, but these are some good places to start." ContentLicense="CC BY-SA 4.0" />
  <row Id="37679" PostHistoryTypeId="50" PostId="12746" RevisionGUID="f49dfa06-044d-4398-acd7-dc83d578f88f" CreationDate="2022-07-05T17:04:15.490" UserId="-1" />
  <row Id="37684" PostHistoryTypeId="50" PostId="12498" RevisionGUID="464f4736-b2c1-45be-96a4-0567b9db7287" CreationDate="2022-07-06T01:02:25.300" UserId="-1" />
  <row Id="37686" PostHistoryTypeId="2" PostId="12826" RevisionGUID="d53f0375-7769-4481-b318-a9ecdacc6f99" CreationDate="2022-07-06T09:53:57.137" UserId="18304" Text="I wish to render an image with my vulkan program and save it to local path. What's a good way to do this or has anyone done it before?&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37688" PostHistoryTypeId="1" PostId="12826" RevisionGUID="d53f0375-7769-4481-b318-a9ecdacc6f99" CreationDate="2022-07-06T09:53:57.137" UserId="18304" Text="exporting the final image from Vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="37689" PostHistoryTypeId="3" PostId="12826" RevisionGUID="d53f0375-7769-4481-b318-a9ecdacc6f99" CreationDate="2022-07-06T09:53:57.137" UserId="18304" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37690" PostHistoryTypeId="2" PostId="12827" RevisionGUID="afbd553c-bb8a-459e-a6ff-b90c1cefde5b" CreationDate="2022-07-06T11:20:45.980" UserId="7952" Text="This is done in a very similar way of copying images to the gpu: (here some pseudo code:&#xD;&#xA;&#xD;&#xA;    Create dest image in mappable memory so it can be read back later.&#xD;&#xA;    Transition source image to transfer read access.&#xD;&#xA;    Transition the dest image to transfer write access.&#xD;&#xA;    vkCmdBlit src to dest&#xD;&#xA;    Transition dest image to a access memory read/general layout&#xD;&#xA;    Transition src image back to original access/layout (assuming it will be used again)&#xD;&#xA;    memory map the dest image for reading back to the cpu&#xD;&#xA;    copy dest image to cpu memory&#xD;&#xA;    clean up&#xD;&#xA;&#xD;&#xA;Use VkImageMemoryBarrier(2) for the transitions.&#xD;&#xA;&#xD;&#xA;I am sure there are some good samples on how to do this out there." ContentLicense="CC BY-SA 4.0" />
  <row Id="37692" PostHistoryTypeId="2" PostId="12828" RevisionGUID="6bb1cac7-65ea-4642-b372-2b290495c301" CreationDate="2022-07-06T12:06:27.567" UserId="10096" Text="Here is a more detailed description of what I wrote in the comments. Ideally such a description should come with a ton of graphics illustrating all of the discussed ideas. I did not have the time to produce said images, so my answer is lacking in that respect.&#xD;&#xA;&#xD;&#xA;**Summary For Implementation Purposes**&#xD;&#xA;&#xD;&#xA;Let the vertices of the first triangle be $v_0, v_1, v_2\in\mathbb{R}^3$ and the vertices of the second triangle be $w_0, w_1, w_2\in\mathbb{R}^3$. For a unique solution we require that the first triangle is non-degenerate: it must have non-zero area (we cannot have the 3 vertices lying on a single line or in a single point). &#xD;&#xA;&#xD;&#xA;Compute $e_1 = v_1-v_0, \, e_2 = v_2-v_0$ and $f_1 = w_1-w_0, \, f_2 = w_2 - w_0$.&#xD;&#xA;&#xD;&#xA;*Option 1*&#xD;&#xA;&#xD;&#xA;Compute $e_3 = e_1 \times e_2$ and $f_3 = f_1 \times f_2$ where $\times$ is the [cross product][1]. Then form the $3\times 3$ matrices $E$ and $F$ using the $e_i$ and $f_i$ as column vectors:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;E = \begin{bmatrix} e_1 &amp; e_2 &amp; e_3 \end{bmatrix}, \quad F = \begin{bmatrix} f_1 &amp; f_2 &amp; f_3\end{bmatrix}.&#xD;&#xA;\end{gather}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Finally, compute $M = FE^{-1}$ where $E^{-1}$ is the inverse of $E$, and compute $m_3 = w_0 - Mv_0$. Set $M$ as the $3\times 3$ part of your $4\times 4$ matrix $M'$ and $m_3$ as its last column:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;M' = \begin{bmatrix} m_0 &amp; m_1 &amp; m_2 &amp; m_3 \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}.&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;*Option 2*&#xD;&#xA;&#xD;&#xA;Form the $3\times 2$ matrices $E$ and $F$:&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;E = \begin{bmatrix} e_1 &amp; e_2 \end{bmatrix}, \quad F = \begin{bmatrix} f_1 &amp; f_2 \end{bmatrix}.&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;The form of the solution is similar to the one from *Option 1*:&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;M = FE^{+}, \quad m_3 = w_0 - FE^{+}v_0,\quad E^{+} = (E^TE)^{-1}E^T \\&#xD;&#xA;M' = \begin{bmatrix} m_0 &amp; m_1 &amp; m_2 &amp; m_3 \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}.&#xD;&#xA;\end{gather}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;*Differences Between Option 1 and Option 2*&#xD;&#xA;&#xD;&#xA;The two approaches (*Option 1* and *Option 2*) agree when applied to points $p$ that lie in the plane of the triangle $v_0, v_1, v_2$, however they differ if $p$ is not in this plane. &#xD;&#xA;&#xD;&#xA;*Option 1* rescales space perpendicular to the triangles $v_0, v_1, v_2$ and $w_0, w_1, w_2$ according to the ratio $r = \frac{area(w_0, w_1, w_2)}{area(v_0,v_1,v_2)}$. For example, if $r = 2$ (the second triangle has twice larger area than the first) and $p$ was $3$ units perpendicularly away from the first triangle's plane, then its transformed version would be $3\times r = 3\times 2 = 6$ units perpendicularly away from the second triangle.&#xD;&#xA;&#xD;&#xA;If $p$ is not inside the plane in which $v_0, v_1, v_2$ lies, then *Option 2* projects $p$ on this plane, and only then does it transform it. That is, you would always get a transformed point in the plane of the second triangle $w_0,w_1,w_2$ regardless of what point you feed in, since it would first get projected on the plane of the first triangle. For example if you had a point $p$ that is $3$ units perpendicularly away from the plane of the first triangle, then it will end up $0$ units perpendicularly away from the plane of the second triangle (i.e. it will be in it).&#xD;&#xA;&#xD;&#xA;**Introduction**&#xD;&#xA;&#xD;&#xA;The following sections contain a more detailed treatment of the problem along with guidelines on ideas that may be used to derive the final solution.&#xD;&#xA;&#xD;&#xA;I'll start with a simplified case for clarity. It turns out that studying [affine transformations][2] between [tetrahedra][3] in 3-D is simpler than studying affine transformations between triangles in 3-D. Studying transformations between triangles is simplest in 2-D for instance, and for $n$-D it is simplest to study transformations between [$n$-simplices][4] (a $2$-simplex is a triangle, and a $3$-simplex is a tetrahedron). This is due to the fact that [an $n$-dimensional vector space is uniquely represented through exactly $n$ basis vectors][5]. Consequently, studying transformations between triangles (a 2-D object) in 3-D results in some difficulties compared to studying tetrahedra, since in 3-D the triangle case leaves out one of the basis vectors.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Tetrahedron Case: Formulation**&#xD;&#xA;&#xD;&#xA;Let $v_0,v_1,v_2, v_3 \in\mathbb{R}^3$ be the vertices of a non-degenerate tetrahedron $\mathcal{T}_{\mathcal{V}}$ in 3-D, and let $w_0, w_1, w_2, w_3\in\mathbb{R}^3$ be the vertices of another (not necessarily non-degenerate) tetrahedron $\mathcal{T}_{\mathcal{W}}$. We want an [affine][2] (linear + offset) function $g:\mathcal{T}_{\mathcal{V}}\to\mathcal{T}_{\mathcal{W}}$ that maps the first tetrahedron to the second one. As a special case the corresponding vertices must map to each other:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;g(v_0) = w_0, \quad&#xD;&#xA;g(v_1) = w_1, \quad&#xD;&#xA;g(v_2) = w_2, \quad&#xD;&#xA;g(v_3) = w_3.&#xD;&#xA;\end{gather}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Since $g(p)$ is affine and acts on 3-D points, then it follows from the definition that [it can be represented by a multiplication with a 3x3 matrix and a translation][2]:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;g(p) = Mp + m_3, \quad M = \begin{bmatrix} m_0 &amp; m_1 &amp; m_2 \end{bmatrix}, \quad  m_0, m_1, m_2, m_3 \in\mathbb{R}^3.&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;That is, we have a 3x3 matrix $M$ with 3-D column vectors $m_0, m_1, m_2$ and one translation/offset 3-D vector $m_3$. Rewriting the constraints using the above form of $g$ yields:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;g(v_0) = w_0 &amp;\iff m_0 v_{0,x} + m_1 v_{0,y} + m_2 v_{0,z} + m_3 = w_0 \\&#xD;&#xA;g(v_1) = w_1 &amp;\iff m_0 v_{1,x} + m_1 v_{1,y} + m_2 v_{1,z} + m_3 = w_1 \\&#xD;&#xA;g(v_2) = w_2 &amp;\iff m_0 v_{2,x} + m_1 v_{2,y} + m_2 v_{2,z} + m_3 = w_2 \\&#xD;&#xA;g(v_3) = w_3 &amp;\iff m_0 v_{3,x} + m_1 v_{3,y} + m_2 v_{3,z} + m_3 = w_3.&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;**Tetrahedron Case: Solution**&#xD;&#xA;&#xD;&#xA;The above is a system with $4\times 3=12$ unknowns (4 $m_i$ vectors each with 3 components) and $4\times 3=12$ equations. From linear algebra we know that [as long as the equations are not linearly dependent this system has a unique solution][6]. We can express $m_0$ from the first equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;m_3 = w_0 - (m_0 v_{0,x} + m_1 v_{0,y} + m_2 v_{0,z}).&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Plugging this expression in the remaining equations reduces the system to 9 unknowns:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;m_0 e_{1,x} + m_1 e_{1,y} + m_2 e_{1,z} &amp;= f_1 \\&#xD;&#xA;m_0 e_{2,x} + m_1 e_{2,y} + m_2 e_{2,z} &amp;= f_2 \\&#xD;&#xA;m_0 e_{3,x} + m_1 e_{3,y} + m_2 e_{3,z} &amp;= f_3,&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $e_1 = v_1-v_0, \, e_2 = v_2-v_0, \, e_3 = v_3-v_0$ and $f_1 = w_1-w_0, \, f_2 = w_2-w_0, \, f_3 = w_3-w_0$. This can be written compactly in matrix form:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;M E = F, \, E = \begin{bmatrix} e_1 &amp; e_2 &amp; e_3 \end{bmatrix}, \, F =  \begin{bmatrix} f_1 &amp; f_2 &amp; f_3 \end{bmatrix}\\ &#xD;&#xA;\implies \\&#xD;&#xA;M = E^{-1}F, \, m_3 = w_0 - Mv_0.&#xD;&#xA;\end{gather} &#xD;&#xA;$$&#xD;&#xA;The matrix [$E^{-1}$ exists provided that its columns are linearly independent][7]. This is the case when the tetrahedron with vertices $v_0, v_1, v_2, v_3$ is non-degenerate: the points do not coincide, they do not lie on a single line, they do not lie in a single plane, i.e. [it's a proper pyramid with non-zero volume][8] (not a squished one).&#xD;&#xA;&#xD;&#xA;[We can form a $4\times 4$ matrix][9] by using $M$ as the $3\times 3$ part, $m_3$ as the last column, and setting $\begin{bmatrix} 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}$ in the last row. Then the transformation takes the form:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;f(p) = q \iff \begin{bmatrix} m_0 &amp; m_1 &amp; m_2 &amp; m_3 \\ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}\begin{bmatrix} p \\ 1 \end{bmatrix} = \begin{bmatrix} q \\ 1 \end{bmatrix}&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Note also that we could have taken any of the vertices as origin instead of $v_0, w_0$:&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;m_3 = w_i - (m_0 v_{i,x} + m_1 v_{i,y} + m_2 v_{i,z}) \\&#xD;&#xA;e_j = v_j - v_i, \, f_j = w_j - w_i, \, j\ne i,&#xD;&#xA;\end{gather}&#xD;&#xA;$$&#xD;&#xA;so the choice of $v_0,w_0$ as origins in the two coordinate systems was arbitrary.&#xD;&#xA;&#xD;&#xA;**Triangle Case: Formulation**&#xD;&#xA;&#xD;&#xA;The setting of transforming between two triangles in 3-D is similar to the tetrahedra case, however $v_3$ and $w_3$ are not provided. We have:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;g(v_0) = w_0 &amp;\iff m_0 v_{0,x} + m_1 v_{0,y} + m_2 v_{0,z} + m_3 = w_0 \\&#xD;&#xA;g(v_1) = w_1 &amp;\iff m_0 v_{1,x} + m_1 v_{1,y} + m_2 v_{1,z} + m_3 = w_1 \\&#xD;&#xA;g(v_2) = w_2 &amp;\iff m_0 v_{2,x} + m_1 v_{2,y} + m_2 v_{2,z} + m_3 = w_2,&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;which is a system of $3\times 3=9$ equations, but there are $3\times 4 = 12$ unknowns. This means that the system is underdetermined $\implies$ it has infinitely many solutions even if $v_0, v_1, v_2$ is a non-degenerate triangle (has non-zero area). There are various approaches to reduce the set of solutions to a single one.&#xD;&#xA;&#xD;&#xA;**Triangle Case: Solution**&#xD;&#xA;&#xD;&#xA;The first option is to supply a 3rd vector $e_3$ that is [linearly independent][10] of $e_1, e_2$ (doesn't lie in the same plane as $e_1$ and $e_2$), and similarly $f_3$ that isn't necessarily linearly independent of $f_1, f_2$. Then this becomes a special case of the tetrahedra transformations with $v_3 = v_0 + e_3$ and $w_3 = w_0 + f_3$. Depending on the direction and length of $e_3$ and $f_3$ the space outside of the planes in which the triangles lie gets sheared and scaled differently. &#xD;&#xA;&#xD;&#xA;It also becomes geometrically clear at this point why we have $12$ unknowns and $9$ equations: the remaining $12-9=3$ unknowns correspond to this choice of 3-dimensional vectors. One would of course note that we had to specify two vectors: $e_3$ and $f_3$, which constitutes $6$ free variables instead of the $3$ pointed out above. The catch is that those $6$ variables get mixed together through $FE^{-1}$ in such a way that they could be represented through just $3$ free variables.&#xD;&#xA;&#xD;&#xA;One simple option that guarantees linear independence is $e_3 = e_1 \times e_2$ and $f_3 = f_1 \times f_2$ where $\times$ is the [cross product][11]. The geometric implications of this choice are discussed in the **TLDR:** *Differences Between Option 1 and Option 2* subsection. Another option would be to normalize the vectors: $e_3 = \frac{e_1 \times e_2}{\|e_1\times e_2\|}$ and $f_3 = \frac{f_1 \times f_2}{\|f_1\times f_2\|}$, where $\|\cdot\|$ is the [Euclidean norm/length][12] of the vectors. Finally, a choice of the form $e_3 = c (e_1\times e_2)$, where $c\ne0$, and $f_3=0$ results in a solution consistent with *Option 2*.&#xD;&#xA;&#xD;&#xA;The difference to *Option 1* is that points that are perpendicularly $X$ units away from the plane of the first triangle remain $X$ units away from the plane of the second triangle after transformation. That is, there is no dependence on the change of triangle area. Thus the case without normalization (i.e. *Option 1*) assumes the transformation is uniform rescaling with ratio $r = \frac{area(w_0,w_1,w_2)}{area(v_0,v_1,v_2)}$ -&gt; rotation -&gt; translation, while the normalized case assumes that scale may be applied only perpendicular to the normal of the triangle, followed by a rotation and translation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Triangle Case: Pseudoinverse Solution**&#xD;&#xA;&#xD;&#xA;We take a slightly different approach by starting directly from the underdetermined system:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;g(v_0) = w_0 &amp;\iff m_0 v_{0,x} + m_1 v_{0,y} + m_2 v_{0,z} + m_3 = w_0 \\&#xD;&#xA;g(v_1) = w_1 &amp;\iff m_0 v_{1,x} + m_1 v_{1,y} + m_2 v_{1,z} + m_3 = w_1 \\&#xD;&#xA;g(v_2) = w_2 &amp;\iff m_0 v_{2,x} + m_1 v_{2,y} + m_2 v_{2,z} + m_3 = w_2.&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;Rewriting $m_3 = w_0 - (m_0 v_{0,x} + m_1 v_{0,y} + m_2 v_{0,z})$ and plugging in the remaining two equations yields:&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;m_0 e_{1,x} + m_1 e_{1,y} + m_2 e_{1,z} = f_1 \\&#xD;&#xA;m_0 e_{2,x} + m_1 e_{2,y} + m_2 e_{2,z} = f_2 \\&#xD;&#xA;\end{gather}&#xD;&#xA;$$&#xD;&#xA;We can write this more compactly in matrix form:&#xD;&#xA;$$&#xD;&#xA;\begin{gather}&#xD;&#xA;M = \begin{bmatrix} m_0 &amp; m_1 &amp; m_2 \end{bmatrix}, \, E=\begin{bmatrix} e_1 &amp; e_2 \end{bmatrix}, \, F=\begin{bmatrix} f_1 &amp; f_2\end{bmatrix} \\&#xD;&#xA;M E = F\\&#xD;&#xA;ME = FI \\&#xD;&#xA;ME = F(E^TE)^{-1}(E^TE) \\&#xD;&#xA;ME = \left(F(E^TE)^{-1}E^T\right)E&#xD;&#xA;\end{gather}&#xD;&#xA;$$&#xD;&#xA;In the above $(E^TE)^{-1}$ exists provided $e_1, e_2$ are linearly independent (the triangle $v_0,v_1,v_2$ is non-degenerate). By identifying the terms on the left- and right-hand sides we come to the conclusion that one possible form of $M$ is $M = F(E^TE)^{-1}E^T$.&#xD;&#xA;&#xD;&#xA;The matrix $E^{+} = (E^TE)^{-1}E^T$ is in fact the [Moore-Penrose pseudoinverse][13]. It essentially projects points on the plane of the first triangle. For example, if we have a point $p$ then [its projection][14] is $p' = EE^+p$. Thus the final solution is:&#xD;&#xA;$$&#xD;&#xA;\begin{equation}&#xD;&#xA;M = FE^{+}, \quad m_3 = w_0 - Mv_0.&#xD;&#xA;\end{equation}&#xD;&#xA;$$&#xD;&#xA;Note the similarity to the solution $M = FE^{-1}$ where $E = \begin{bmatrix} e_1 &amp; e_2 &amp; e_3\end{bmatrix}$ and $F = \begin{bmatrix} f_1 &amp; f_2 &amp; f_3 \end{bmatrix}$. And actually the exact same solution for $M$ can be recovered by choosing $e_3 = c(e_1 \times e_2), c\ne 0$, and $f_3 = 0$.&#xD;&#xA;&#xD;&#xA;For an efficient application of the Moore-Penrose pseudoinverse $E^{+}$  to some vector $p$ the following can be used:&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;E^{+}p &amp;= (E^TE)^{-1}E^Tp \\&#xD;&#xA;&amp;= \left(\begin{bmatrix} e_1\cdot e_1 &amp; e_1 \cdot e_2 \\ e_2 \cdot e_1 &amp; e_2 \cdot e_2 \end{bmatrix}\right)^{-1}\begin{bmatrix} e_1^T \\ e_2^T \end{bmatrix}p \\&#xD;&#xA;&amp;= \frac{1}{(e_1\cdot e_1)(e_2 \cdot e_2) - (e_1\cdot e_2)^2}\begin{bmatrix} e_2\cdot e_2 &amp; -e_1\cdot e_2 \\ -e_2 \cdot e_1 &amp; e_1\cdot e_1 \end{bmatrix}\begin{bmatrix} e_1^T \\ e_2^T \end{bmatrix}p \\&#xD;&#xA;&amp;= \frac{1}{(e_1\cdot e_1)(e_2 \cdot e_2) - (e_1\cdot e_2)^2}\begin{bmatrix}(e_2\cdot e_2)(e_1\cdot p) - (e_1\cdot e_2)(e_2\cdot p) \\ (e_1\cdot e_1)(e_2\cdot p) -(e_1\cdot e_2)(e_1\cdot p)\end{bmatrix}.&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;This results in 5 dot products, 6 scalar multiplications, and 3 subtractions for computing the application of $E^{+}$ to some vector $p$. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cross_product#Coordinate_notation&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Affine_transformation#Representation&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Tetrahedron&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/Simplex&#xD;&#xA;  [5]: https://en.wikipedia.org/wiki/Dimension_(vector_space)&#xD;&#xA;  [6]: https://en.wikipedia.org/wiki/Rank%E2%80%93nullity_theorem&#xD;&#xA;  [7]: https://en.wikipedia.org/wiki/Invertible_matrix#The_invertible_matrix_theorem&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Determinant#Volume_and_Jacobian_determinant&#xD;&#xA;  [9]: https://en.wikipedia.org/wiki/Affine_transformation#Augmented_matrix&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Linear_independence&#xD;&#xA;  [11]: https://en.wikipedia.org/wiki/Cross_product&#xD;&#xA;  [12]: https://en.wikipedia.org/wiki/Norm_(mathematics)#Euclidean_norm&#xD;&#xA;  [13]: https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse&#xD;&#xA;  [14]: https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse#Projectors" ContentLicense="CC BY-SA 4.0" />
  <row Id="37694" PostHistoryTypeId="50" PostId="10879" RevisionGUID="7ea26cce-41c9-4938-afea-8c7c27194ee6" CreationDate="2022-07-07T11:01:25.117" UserId="-1" />
  <row Id="37701" PostHistoryTypeId="50" PostId="10154" RevisionGUID="ec6f546c-9ac8-46dd-880c-986376d05f20" CreationDate="2022-07-08T11:08:00.690" UserId="-1" />
  <row Id="37704" PostHistoryTypeId="2" PostId="12832" RevisionGUID="2a62f595-0bc0-480e-8da7-3d919506cd52" CreationDate="2022-07-09T09:54:25.660" UserId="6041" Text="[&quot;An Area-Preserving Parametrization for Spherical Rectangles&quot;][1] paper describes an efficient approach for sampling solid angles for ***rectangle*** light sources. &#xD;&#xA;&#xD;&#xA;I am wondering if &#xD;&#xA;&#xD;&#xA;- The light source in world space is a quad shape(not necessarily a perfect rect), can I transform it to it's local space which will be a rectangle, apply the above to sample the solid angle and then transform the sampled dir back to world coordinate? Would this approach be valid for sampling quad shapes (using the method in this paper)? &#xD;&#xA;&#xD;&#xA;- Also (I guess this is a more general thing) if the world to object (and obj to world) transformation has shear transformation in it, would sampling in local space and then transforming the sample back to world still be a valid one?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.arnoldrenderer.com/research/egsr2013_spherical_rectangle.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="37706" PostHistoryTypeId="1" PostId="12832" RevisionGUID="2a62f595-0bc0-480e-8da7-3d919506cd52" CreationDate="2022-07-09T09:54:25.660" UserId="6041" Text="Sampling Quad Shape Light Using Spherical Rectangles in Local Space" ContentLicense="CC BY-SA 4.0" />
  <row Id="37707" PostHistoryTypeId="3" PostId="12832" RevisionGUID="2a62f595-0bc0-480e-8da7-3d919506cd52" CreationDate="2022-07-09T09:54:25.660" UserId="6041" Text="|sampling|pbrt|light|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37708" PostHistoryTypeId="50" PostId="4703" RevisionGUID="252e8d8d-0b14-410f-b58f-b10ae52e1882" CreationDate="2022-07-09T12:04:50.470" UserId="-1" />
  <row Id="37709" PostHistoryTypeId="50" PostId="12743" RevisionGUID="f0ef5e35-1690-4ab2-973f-f8bacd6861c3" CreationDate="2022-07-09T18:03:10.287" UserId="-1" />
  <row Id="37710" PostHistoryTypeId="2" PostId="12833" RevisionGUID="6180a3c5-d5d0-4241-957f-fdcfe806c4f1" CreationDate="2022-07-10T13:38:28.333" UserId="18529" Text="Reading through the source code of the [XeGTAO][1] project I found this function while looking for the denoise filter:&#xD;&#xA;````&#xD;&#xA;lpfloat4 XeGTAO_CalculateEdges( const lpfloat centerZ, const lpfloat leftZ, const lpfloat rightZ, const lpfloat topZ, const lpfloat bottomZ )&#xD;&#xA;{&#xD;&#xA;    lpfloat4 edgesLRTB = lpfloat4( leftZ, rightZ, topZ, bottomZ ) - (lpfloat)centerZ;&#xD;&#xA;&#xD;&#xA;    lpfloat slopeLR = (edgesLRTB.y - edgesLRTB.x) * 0.5;&#xD;&#xA;    lpfloat slopeTB = (edgesLRTB.w - edgesLRTB.z) * 0.5;&#xD;&#xA;    lpfloat4 edgesLRTBSlopeAdjusted = edgesLRTB + lpfloat4( slopeLR, -slopeLR, slopeTB, -slopeTB );&#xD;&#xA;    edgesLRTB = min( abs( edgesLRTB ), abs( edgesLRTBSlopeAdjusted ) );&#xD;&#xA;    return lpfloat4(saturate( ( 1.25 - edgesLRTB / (centerZ * 0.011) ) ));&#xD;&#xA;}&#xD;&#xA;````&#xD;&#xA;*(From XeGTAO.hlsli)*&#xD;&#xA;&#xD;&#xA;Where `centerZ`, `left/right/...Z` are view space z values.&#xD;&#xA;&#xD;&#xA;As the name suggests the function is used to find edges for the denoising filter. &#xD;&#xA;&#xD;&#xA;While I understand the general idea I find it difficult to make sense of the last line, this *thing* in particular: `1.25 - edgesLRTB / (centerZ * 0.011)`.&#xD;&#xA;&#xD;&#xA;Could you guess where do those constants come from? &#xD;&#xA;Could you suggest any resource about edge/silhouette extraction from depth &#xD;&#xA;(to be used as input for a filter/displayed for non-photorealistic rendering)? &#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/GameTechDev/XeGTAO" ContentLicense="CC BY-SA 4.0" />
  <row Id="37712" PostHistoryTypeId="1" PostId="12833" RevisionGUID="6180a3c5-d5d0-4241-957f-fdcfe806c4f1" CreationDate="2022-07-10T13:38:28.333" UserId="18529" Text="Edge-aware spatial denoising (Ambient Occlusion)" ContentLicense="CC BY-SA 4.0" />
  <row Id="37713" PostHistoryTypeId="3" PostId="12833" RevisionGUID="6180a3c5-d5d0-4241-957f-fdcfe806c4f1" CreationDate="2022-07-10T13:38:28.333" UserId="18529" Text="|image-processing|direct3d|ambient-occlusion|denoise|silhouette|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37715" PostHistoryTypeId="2" PostId="12834" RevisionGUID="188ab175-3c2b-4fb6-8733-102627ae5fb7" CreationDate="2022-07-10T16:19:11.923" UserId="15909" Text="I'm trying to render the Sponza scene using the Cook-Torrance BRDF Model Plugged with the GGX Normal Distribution, Gemoetry Schlick and fresnel Schlick approximation and a punctual point light. When rendered I get these artifacts &#xD;&#xA;&#xD;&#xA;[![final scene][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I don't know why these fragments in the yellow boxes are shadowed although everything in the **Gbuffer** looks normal. Here is the **positions map**&#xD;&#xA;&#xD;&#xA;[![positions][2]][2]&#xD;&#xA;&#xD;&#xA;diffuse map&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;normal map&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;roughness map&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;metallness map&#xD;&#xA;&#xD;&#xA;[![enter image description here][6]][6]&#xD;&#xA;&#xD;&#xA;and finally the Ambient Occlusion&#xD;&#xA;&#xD;&#xA;[![enter image description here][7]][7]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/djbxo.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/WP5Jh.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/t5KTS.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/kzogt.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/2KyA9.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/F2VTf.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/FXkwr.jpg&#xD;&#xA;&#xD;&#xA;and here the fragment shader used to render the scene &#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    const float PI = 3.14159265359f;&#xD;&#xA;    &#xD;&#xA;    struct PointLight &#xD;&#xA;    {&#xD;&#xA;    	vec3 light_position;&#xD;&#xA;    	vec3 light_intensity;&#xD;&#xA;    	float radius; &#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D position_map;&#xD;&#xA;    uniform sampler2D normal_map;&#xD;&#xA;    uniform sampler2D diffuse_map;&#xD;&#xA;    uniform sampler2D roughness_map;&#xD;&#xA;    uniform sampler2D metalness_map;&#xD;&#xA;    uniform sampler2D ao_map;&#xD;&#xA;    uniform PointLight pointlight; &#xD;&#xA;    &#xD;&#xA;    in vec2 o_uv; &#xD;&#xA;    &#xD;&#xA;    out vec4 final_color; &#xD;&#xA;    &#xD;&#xA;    // NDF&#xD;&#xA;    float GGX_Distribution(float roughness, vec3 normal, vec3 halfway)&#xD;&#xA;    {&#xD;&#xA;    	float numerator = pow(roughness, 4.0f); &#xD;&#xA;    	float NdotH = max(dot(normal, halfway), 0.0f); &#xD;&#xA;    	float denominator = PI * pow((NdotH * NdotH * (numerator - 1) + 1), 2.0f);&#xD;&#xA;    	return numerator / denominator;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // Schlick-GGX&#xD;&#xA;    float SchlickGGX(vec3 normal, vec3 dir, float roughness)&#xD;&#xA;    {&#xD;&#xA;    	float k_numerator = roughness + 1; &#xD;&#xA;    	float k = (k_numerator * k_numerator) / 8.0f; &#xD;&#xA;    	float numerator = max(dot(normal, dir), 0.0f); &#xD;&#xA;    	float denominator = numerator * (1.0f - k) + k;&#xD;&#xA;    &#xD;&#xA;    	return numerator / denominator; &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float GeometrySchlickGGX(vec3 normal, vec3 lightdir, vec3 viewdir, float roughness)&#xD;&#xA;    {&#xD;&#xA;    	return SchlickGGX(normal, lightdir, roughness) * SchlickGGX(normal, viewdir, roughness); &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 F_Schlick(vec3 F0, vec3 lightdir, vec3 halfway)&#xD;&#xA;    {&#xD;&#xA;    	float LdotH = max(dot(lightdir, halfway), 0.0f); &#xD;&#xA;    	return F0 + (1.0f - F0) * pow((1.0f - LdotH), 5.0f); &#xD;&#xA;    }&#xD;&#xA;        &#xD;&#xA;    vec3 PointLightIllum(PointLight pointlight, vec3 fragPos, float roughness,&#xD;&#xA;    							vec3 diffuse, float metalness, vec3 normal)&#xD;&#xA;    {&#xD;&#xA;    	vec3 lightDir = normalize(pointlight.light_position - fragPos);&#xD;&#xA;    &#xD;&#xA;    	vec3 viewDir = normalize(-fragPos);&#xD;&#xA;    	vec3 halfway = normalize(lightDir + viewDir);&#xD;&#xA;    	&#xD;&#xA;    	float d = length(pointlight.light_position - fragPos); &#xD;&#xA;    	float attenuation = 1.0f / ((d * d) + 0.001f);&#xD;&#xA;    &#xD;&#xA;    	float NdotL = max(dot(lightDir, normal), 0.0f); &#xD;&#xA;    	float NdotV = max(dot(viewDir, normal), 0.0f); &#xD;&#xA;    &#xD;&#xA;    	vec3 F0 = vec3(0.04);&#xD;&#xA;    	F0 = mix(F0, diffuse, metalness);&#xD;&#xA;    &#xD;&#xA;    	// Specular Reflections&#xD;&#xA;    	vec3 F = F_Schlick(F0, lightDir, halfway);&#xD;&#xA;    &#xD;&#xA;    	// Shadowing and masking&#xD;&#xA;    	float G = GeometrySchlickGGX(normal, lightDir, viewDir, roughness);&#xD;&#xA;    	float D = GGX_Distribution(roughness, normal, halfway);&#xD;&#xA;    &#xD;&#xA;    	vec3 numerator = F * G * D; &#xD;&#xA;    	float denominator = 4.0f * NdotV * NdotL + 0.0001f;&#xD;&#xA;    	vec3 BRDF = numerator / denominator; &#xD;&#xA;    &#xD;&#xA;    	vec3 spec = BRDF * pointlight.light_intensity * attenuation * NdotL;&#xD;&#xA;    	vec3 diff = (diffuse / PI) * pointlight.light_intensity * attenuation * NdotL * (1.0f - metalness); &#xD;&#xA;    	diff *= vec3(1.0f) - F;&#xD;&#xA;    &#xD;&#xA;    	vec3 Lo = spec + diff; &#xD;&#xA;    &#xD;&#xA;    	return Lo;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	vec3 fragPos = texture(position_map, o_uv).rgb;&#xD;&#xA;    	vec3 normal = normalize(texture(normal_map, o_uv).rgb);&#xD;&#xA;    	vec3 diffuse = texture(diffuse_map, o_uv).rgb;&#xD;&#xA;    	float roughness = texture(roughness_map, o_uv).r; &#xD;&#xA;    	float metalness = texture(metalness_map, o_uv).r; &#xD;&#xA;    	float ao = texture(ao_map, o_uv).r;&#xD;&#xA;    &#xD;&#xA;    	// Ambient occlusion&#xD;&#xA;    	float ambient_intensity = 0.2f; &#xD;&#xA;    	vec3 ambient = diffuse * ambient_intensity * ao;&#xD;&#xA;    &#xD;&#xA;    	vec3 direct = PointLightIllum(pointlight, fragPos, roughness, diffuse, metalness, normal);&#xD;&#xA;    	vec3 indirect = ambient; &#xD;&#xA;    &#xD;&#xA;    	final_color = vec4(indirect + direct, 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;the vertex shader is a simple shader where i just render a quad with the size of screen and use its UVs to sample the textures. Could Someone tell why i'm having this artifact and how to resolve it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37717" PostHistoryTypeId="1" PostId="12834" RevisionGUID="188ab175-3c2b-4fb6-8733-102627ae5fb7" CreationDate="2022-07-10T16:19:11.923" UserId="15909" Text="Artifacts while rendering sponza scene" ContentLicense="CC BY-SA 4.0" />
  <row Id="37718" PostHistoryTypeId="3" PostId="12834" RevisionGUID="188ab175-3c2b-4fb6-8733-102627ae5fb7" CreationDate="2022-07-10T16:19:11.923" UserId="15909" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37719" PostHistoryTypeId="2" PostId="12835" RevisionGUID="519702bd-3be6-4cd1-b002-8b6dcec61003" CreationDate="2022-07-10T22:29:41.800" UserId="18640" Text="I have a problem which I believe is caused by the fragment shader code I use, however I'm not entirely sure.&#xD;&#xA;&#xD;&#xA;The issue is this: I’ve been playing with few examples using Cesium (3D globe) and specifically, with it's shadowMap implementation. In the process, I observed that If I generate a shadowMap, and then zoom or move around on the globe, the shadow detaches or appears and then reappears. If you also observe the green and red areas, they seem to change depending on the zoom and the panning position.&#xD;&#xA;&#xD;&#xA;For example, observe the green area in front of the start of the camera: it slowly disappears as I continue to zoom out (also, please find a link to the code demo below the images)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You could also test it by yourself in the sandcastle here:&#xD;&#xA;&#xD;&#xA;[Sandcastle][4]&#xD;&#xA;&#xD;&#xA;Is this a problem with the fragment shader, or it’s something related to the shadowMap itself? Any hints as to where I could fine tune this behavior?&#xD;&#xA;&#xD;&#xA;I'm using the latest stable version of Chrome and have a decent GPU.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/weAww.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/KQMk4.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/5A6fS.png&#xD;&#xA;  [4]: https://sandcastle.cesium.com/#[encoded data, 9290 characters]" ContentLicense="CC BY-SA 4.0" />
  <row Id="37721" PostHistoryTypeId="1" PostId="12835" RevisionGUID="519702bd-3be6-4cd1-b002-8b6dcec61003" CreationDate="2022-07-10T22:29:41.800" UserId="18640" Text="ShadowMap artifacts when moving on the map" ContentLicense="CC BY-SA 4.0" />
  <row Id="37722" PostHistoryTypeId="3" PostId="12835" RevisionGUID="519702bd-3be6-4cd1-b002-8b6dcec61003" CreationDate="2022-07-10T22:29:41.800" UserId="18640" Text="|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37723" PostHistoryTypeId="2" PostId="12836" RevisionGUID="a0ad30d4-380b-4743-a8fc-ac565668bc23" CreationDate="2022-07-10T23:46:55.150" UserId="18641" Text="I'm trying to simulate a moving catheter inside a human heart. I want to accurately model the behaviour of the catheter and I assume the heart to be solid. What I want is, when the catheter hits the wall, it should bend and move, instead of going through the wall.&#xD;&#xA;catheter is modelled as a discrete rod with 4 particles. &#xD;&#xA;&#xD;&#xA;I am planning to use Position Based Dynamics (PBD) for the simulations. Is this the best/simplest simulation framework to use? If not, which framework would suit the setup best?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37725" PostHistoryTypeId="1" PostId="12836" RevisionGUID="a0ad30d4-380b-4743-a8fc-ac565668bc23" CreationDate="2022-07-10T23:46:55.150" UserId="18641" Text="Simulating a moving catheter inside a human heart" ContentLicense="CC BY-SA 4.0" />
  <row Id="37726" PostHistoryTypeId="3" PostId="12836" RevisionGUID="a0ad30d4-380b-4743-a8fc-ac565668bc23" CreationDate="2022-07-10T23:46:55.150" UserId="18641" Text="|computational-geometry|geometry|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37727" PostHistoryTypeId="2" PostId="12837" RevisionGUID="e61bd47b-efe4-4cf4-a7ff-9639594e9795" CreationDate="2022-07-11T08:56:19.817" UserId="18643" Text="I can only find online infomation such as some scene need days to render a single frame, but I'm not sure what is the hardware based on, it may be based on CPU rendering farms in the 2000s. There is also information about it takes several minutes to ray trace a scene in Maya, but the level of photorealism for the render is unkown. A lot of search doesn't give more accurate information.&#xD;&#xA;&#xD;&#xA;To render a photo realistic video that is absolutely of the same photorealism level as video or film shot with real scenes, how many RAM is needed (i.e. can 16GB comsumer GPU be used)? Is it still needed to be rendered on CPU? What is the time scale needed to render a video? Can inter-frame correlation be exploited? " ContentLicense="CC BY-SA 4.0" />
  <row Id="37729" PostHistoryTypeId="1" PostId="12837" RevisionGUID="e61bd47b-efe4-4cf4-a7ff-9639594e9795" CreationDate="2022-07-11T08:56:19.817" UserId="18643" Text="What is the rendering cost of photo realistic video today?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37730" PostHistoryTypeId="3" PostId="12837" RevisionGUID="e61bd47b-efe4-4cf4-a7ff-9639594e9795" CreationDate="2022-07-11T08:56:19.817" UserId="18643" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37731" PostHistoryTypeId="2" PostId="12838" RevisionGUID="530874f8-61c0-4426-b1a3-4c540cedc3a6" CreationDate="2022-07-11T15:05:47.183" UserId="15909" Text="Well I'm embarrassed to say that but turns out the problem was with the format of the normals render target instead of making it **GL_RGB32F** I accidentally made it **GL_RGB** causing the normals to be clipped to range 0 -&gt; 1 instead of -1 -&gt; 1 causing some fragments to be shadowed due to incorrect lighting calculations." ContentLicense="CC BY-SA 4.0" />
  <row Id="37735" PostHistoryTypeId="2" PostId="12839" RevisionGUID="736690ee-c0bb-4a26-9c1f-683126c088e2" CreationDate="2022-07-13T16:27:55.667" UserId="18649" Text="&quot;NEE&quot; stands for Next Event Estimation algorithm.&#xD;&#xA;For learning more about this algorithm, you can watch [this presentation from TU Wien][1] or have a look on [their presentation slides][2].&#xD;&#xA;&#xD;&#xA;Also, you can find a useful piece of code for NEE in [this presentation][3].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=FU1dbi827LY&#xD;&#xA;  [2]: https://www.cg.tuwien.ac.at/sites/default/files/course/4411/attachments/08_next%20event%20estimation.pdf&#xD;&#xA;  [3]: https://www.youtube.com/watch?v=i6KDgYk5Nzg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37745" PostHistoryTypeId="2" PostId="12842" RevisionGUID="b3009887-9faa-4059-905e-4d2d34b41b39" CreationDate="2022-07-14T13:38:19.293" UserId="18529" Text="I'm using a joint bilateral filter to denoise ambient occlusion data using view-space z values as input.&#xD;&#xA;&#xD;&#xA;However, I'm having some trouble with that, in particular, I don't know if there's a way to fix the following issues:&#xD;&#xA;&#xD;&#xA;**1. Artifacts at grazing angles:**&#xD;&#xA;&#xD;&#xA;When looking at a surface almost edge-on, Z values changes rapidly in one dimensions (image space) while remain almost constant in the other. This causes the filter to smooth the image only in one dimension. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**2. &quot;Jumps&quot; across edges:**&#xD;&#xA;&#xD;&#xA;Samples separated by (what I'd like the filter to consider) an edge are considered similar and influence each other's final value greatly. (They have the same Z).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**3. How to choose the correct parameters for the filter so that it consistently detects edges in the most scene-independent way possible?**&#xD;&#xA;&#xD;&#xA;Do you have any suggestions? Are there other techniques out there that could help me?&#xD;&#xA;&#xD;&#xA;Thank you all in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fZ1co.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/c3wwn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37747" PostHistoryTypeId="1" PostId="12842" RevisionGUID="b3009887-9faa-4059-905e-4d2d34b41b39" CreationDate="2022-07-14T13:38:19.293" UserId="18529" Text="Bilateral Filter artifacts" ContentLicense="CC BY-SA 4.0" />
  <row Id="37748" PostHistoryTypeId="3" PostId="12842" RevisionGUID="b3009887-9faa-4059-905e-4d2d34b41b39" CreationDate="2022-07-14T13:38:19.293" UserId="18529" Text="|opengl|image-processing|direct3d|ambient-occlusion|denoise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37749" PostHistoryTypeId="5" PostId="12842" RevisionGUID="50d8e06b-443c-4294-b79c-8708c3581ec5" CreationDate="2022-07-14T14:04:08.243" UserId="18529" Comment="added 442 characters in body; edited title" Text="I'm trying to implement a filter to denoise ambient occlusion data.&#xD;&#xA;&#xD;&#xA;What kind of filter do you suggest for the purpose?&#xD;&#xA;&#xD;&#xA;The techniques I've come across are the following:&#xD;&#xA;&#xD;&#xA;- Gaussian filter (doesn't preserve edges)&#xD;&#xA;- Bilateral/Joint Bilateral filter (the one I've tried)&#xD;&#xA;- Guided filter (never tried, looks intrinsically blurrier than bilateral)&#xD;&#xA;- Gaussian + Edge detection (did't find good resources about the edge detection part, do you know any?)&#xD;&#xA;&#xD;&#xA;I choose to implement a joint bilateral filter using view-space z values as input.&#xD;&#xA;&#xD;&#xA;However, I'm having some trouble with that, in particular, I don't know if there's a way to fix the following issues:&#xD;&#xA;&#xD;&#xA;**1. Artifacts at grazing angles:**&#xD;&#xA;&#xD;&#xA;When looking at a surface almost edge-on, Z values changes rapidly in one dimensions (image space) while remain almost constant in the other. This causes the filter to smooth the image only in one dimension. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**2. &quot;Jumps&quot; across edges:**&#xD;&#xA;&#xD;&#xA;Samples separated by (what I'd like the filter to consider) an edge are considered similar and influence each other's final value greatly. (They have the same Z).&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**3. How to choose the correct parameters for the filter so that it consistently detects edges in the most scene-independent way possible?**&#xD;&#xA;&#xD;&#xA;Do you have any suggestions? Are there other techniques out there that could help me?&#xD;&#xA;&#xD;&#xA;Thank you all in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fZ1co.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/c3wwn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37750" PostHistoryTypeId="4" PostId="12842" RevisionGUID="50d8e06b-443c-4294-b79c-8708c3581ec5" CreationDate="2022-07-14T14:04:08.243" UserId="18529" Comment="added 442 characters in body; edited title" Text="AO Denoise Filter" ContentLicense="CC BY-SA 4.0" />
  <row Id="37751" PostHistoryTypeId="2" PostId="12843" RevisionGUID="c5884d5e-f4f4-4328-909c-fe8c7eea430a" CreationDate="2022-07-14T15:20:53.417" UserId="18583" Text="I am trying to find gradient of the following image. Now shouldn't the gradient for $x$ be the vertical lines with respect to axes we have on the top left corner please?  &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GaRhn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37753" PostHistoryTypeId="1" PostId="12843" RevisionGUID="c5884d5e-f4f4-4328-909c-fe8c7eea430a" CreationDate="2022-07-14T15:20:53.417" UserId="18583" Text="Image gradient of $x$-axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="37754" PostHistoryTypeId="3" PostId="12843" RevisionGUID="c5884d5e-f4f4-4328-909c-fe8c7eea430a" CreationDate="2022-07-14T15:20:53.417" UserId="18583" Text="|image-processing|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37755" PostHistoryTypeId="2" PostId="12844" RevisionGUID="0acecd13-75ef-43ca-a26f-93bd56fb0b7e" CreationDate="2022-07-15T03:37:10.573" UserId="18634" Text="I am simulating multiple users rendering with my program on my computer with multiple threads. I wonder why my fps counter tells me that the performance on all threads is the same, regardless of the different data I am using on those threads. I mean, for some data, the rendering is slower, due to the complexity of the scene. However, when I mix a larger and more difficult-to-render dataset with a faster-to-render one, each scene is rendered with the same fps on different threads. That does not seem intuitive for me. &#xD;&#xA;&#xD;&#xA;Best,&#xD;&#xA;Lily" ContentLicense="CC BY-SA 4.0" />
  <row Id="37757" PostHistoryTypeId="1" PostId="12844" RevisionGUID="0acecd13-75ef-43ca-a26f-93bd56fb0b7e" CreationDate="2022-07-15T03:37:10.573" UserId="18634" Text="multithread rendering performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="37758" PostHistoryTypeId="3" PostId="12844" RevisionGUID="0acecd13-75ef-43ca-a26f-93bd56fb0b7e" CreationDate="2022-07-15T03:37:10.573" UserId="18634" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37759" PostHistoryTypeId="50" PostId="12780" RevisionGUID="1b840f2b-1088-4f39-836c-72ec415e2b42" CreationDate="2022-07-15T09:05:40.633" UserId="-1" />
  <row Id="37762" PostHistoryTypeId="2" PostId="12845" RevisionGUID="2484a1b4-87de-4743-b4ab-176539b66149" CreationDate="2022-07-16T07:35:25.183" UserId="18661" Text="I'm trying to render sprites/textures in my raycasting engine, but I don't quite understand the math behind drawing the columns of the texture I intend to project. I've tried looking at several tutorials, e.g., [lodev][1], [Wynnliam][2], and [several posts][3] on Allegro.cc, but none of them seem to explain the sprite-casting component in an easy-to-digest way. Can anyone help? Note that I'm currently drawing a yellow square in the location of the sprite and it appears as if the sprite is not positioned in the correct spot... My main problem is that I don’t understand how to compute the column of the texture to render. Once I figure this out, I can easily add z-depth sorting, but I really have no idea how to do this step.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;        final int TEXTURE_SIZE = 64;&#xD;&#xA;        final int PROJ_HEIGHT = 640;&#xD;&#xA;        final int PROJ_WIDTH = 640;&#xD;&#xA;        ArrayList&lt;TextureSprite&gt; sprites = this.RAYCASTER_PANEL.getTileMap().getSprites();&#xD;&#xA;        for (int s = 0; s &lt; sprites.size(); s++) {&#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            // computes the distance and angle of the sprite...&#xD;&#xA;            double fov = this.RAYCASTER_PANEL.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double dx = sp.getX() - this.RAYCASTER_PANEL.getCamera().getX();&#xD;&#xA;            double dy = sp.getY() - this.RAYCASTER_PANEL.getCamera().getY();&#xD;&#xA;            double d = Point2D.distanceSq(sp.getX(), sp.getY(), this.RAYCASTER_PANEL.getCamera().getX(), this.RAYCASTER_PANEL.getCamera().getY());&#xD;&#xA;            double theta_temp = Math.toDegrees(Math.atan2(dy, dx));&#xD;&#xA;            if(theta_temp &lt; 0) theta_temp += 360;&#xD;&#xA;            if (theta_temp &gt; 360) theta_temp -= 360;&#xD;&#xA;&#xD;&#xA;            double y = ca + fov/2 - theta_temp;&#xD;&#xA;&#xD;&#xA;            if(theta_temp &gt; 270 &amp;&amp; ca &lt; 90) y = ca + fov/2 - theta_temp + 360;&#xD;&#xA;            if(ca &gt; 270 &amp;&amp; theta_temp &lt; 90) y = ca + fov/2 - theta_temp - 360;&#xD;&#xA;     &#xD;&#xA;            // attempt to compute the sprite's x, y, width, and height&#xD;&#xA;            double sw = (TEXTURE_SIZE / Math.sqrt(d)) * this.getCamera().getDistanceToProjectionPlane();&#xD;&#xA;            double sh = sw;&#xD;&#xA;            double sx = (y * PROJ_HEIGHT / fov) - sw/2.f;&#xD;&#xA;            double sy = (PROJ_HEIGHT / 2.f) - (TEXTURE_SIZE / 2.f);&#xD;&#xA;&#xD;&#xA;            // Just a temporary until I understand how to draw the textures themselves...&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            g2.fillRect((int)sx,(int)sy,(int)sw,(int)sh);&#xD;&#xA;```&#xD;&#xA;[Example of the problem][4] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lodev.org/cgtutor/raycasting3.html&#xD;&#xA;  [2]: https://wynnliam.github.io/raycaster/news/tutorial/2019/04/03/raycaster-part-02.html&#xD;&#xA;  [3]: https://www.allegro.cc/forums/thread/355015&#xD;&#xA;  [4]: https://i.stack.imgur.com/aJ489.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37764" PostHistoryTypeId="1" PostId="12845" RevisionGUID="2484a1b4-87de-4743-b4ab-176539b66149" CreationDate="2022-07-16T07:35:25.183" UserId="18661" Text="How to sprite cast in a raycasting engine?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37765" PostHistoryTypeId="3" PostId="12845" RevisionGUID="2484a1b4-87de-4743-b4ab-176539b66149" CreationDate="2022-07-16T07:35:25.183" UserId="18661" Text="|depth-map|ray|occlusion|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37766" PostHistoryTypeId="5" PostId="12845" RevisionGUID="5c5c9823-a005-45f5-aee3-d201e6459b7e" CreationDate="2022-07-16T13:19:39.817" UserId="18661" Comment="added 1565 characters in body" Text="I'm trying to render sprites/textures in my raycasting engine, but I don't quite understand the math behind drawing the columns of the texture I intend to project. I've tried looking at several tutorials, e.g., [lodev][1], [Wynnliam][2], and [several posts][3] on Allegro.cc, but none of them seem to explain the sprite-casting component in an easy-to-digest way. Can anyone help? Note that I'm currently drawing a yellow square in the location of the sprite and it appears as if the sprite is not positioned in the correct spot... My main problem is that I don’t understand how to compute the column of the texture to render. Once I figure this out, I can easily add z-depth sorting, but I really have no idea how to do this step.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;        final int TEXTURE_SIZE = 64;&#xD;&#xA;        final int PROJ_HEIGHT = 640;&#xD;&#xA;        final int PROJ_WIDTH = 640;&#xD;&#xA;        ArrayList&lt;TextureSprite&gt; sprites = this.RAYCASTER_PANEL.getTileMap().getSprites();&#xD;&#xA;        for (int s = 0; s &lt; sprites.size(); s++) {&#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            // computes the distance and angle of the sprite...&#xD;&#xA;            double fov = this.RAYCASTER_PANEL.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double dx = sp.getX() - this.RAYCASTER_PANEL.getCamera().getX();&#xD;&#xA;            double dy = sp.getY() - this.RAYCASTER_PANEL.getCamera().getY();&#xD;&#xA;            double d = Point2D.distanceSq(sp.getX(), sp.getY(), this.RAYCASTER_PANEL.getCamera().getX(), this.RAYCASTER_PANEL.getCamera().getY());&#xD;&#xA;            double theta_temp = Math.toDegrees(Math.atan2(dy, dx));&#xD;&#xA;            if(theta_temp &lt; 0) theta_temp += 360;&#xD;&#xA;            if (theta_temp &gt; 360) theta_temp -= 360;&#xD;&#xA;&#xD;&#xA;            double y = ca + fov/2 - theta_temp;&#xD;&#xA;&#xD;&#xA;            if(theta_temp &gt; 270 &amp;&amp; ca &lt; 90) y = ca + fov/2 - theta_temp + 360;&#xD;&#xA;            if(ca &gt; 270 &amp;&amp; theta_temp &lt; 90) y = ca + fov/2 - theta_temp - 360;&#xD;&#xA;     &#xD;&#xA;            // attempt to compute the sprite's x, y, width, and height&#xD;&#xA;            double sw = (TEXTURE_SIZE / Math.sqrt(d)) * this.getCamera().getDistanceToProjectionPlane();&#xD;&#xA;            double sh = sw;&#xD;&#xA;            double sx = (y * PROJ_HEIGHT / fov) - sw/2.f;&#xD;&#xA;            double sy = (PROJ_HEIGHT / 2.f) - (TEXTURE_SIZE / 2.f);&#xD;&#xA;&#xD;&#xA;            // Just a temporary until I understand how to draw the textures themselves...&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            g2.fillRect((int)sx,(int)sy,(int)sw,(int)sh);&#xD;&#xA;```&#xD;&#xA;[Example of the problem][4] &#xD;&#xA;&#xD;&#xA;Code after @lightxbulb's post suggestion:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            double fov = this.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double px = this.getCamera().getX() + this.getCamera().getWidth() / 2.f;&#xD;&#xA;            double py = this.getCamera().getY() + this.getCamera().getHeight() / 2.f;&#xD;&#xA;            double sx = sp.getX() + sp.getWidth() / 2;&#xD;&#xA;            double sy = sp.getY() + sp.getHeight() / 2;&#xD;&#xA;&#xD;&#xA;            double dx = sx - px;&#xD;&#xA;            double dy = sy - py;&#xD;&#xA;            double sprite_dir = Math.atan2(dy, dx);&#xD;&#xA;            while (sprite_dir - ca &gt; 180) sprite_dir -= 360;&#xD;&#xA;            while (sprite_dir - ca &lt; -180) sprite_dir += 360;&#xD;&#xA;&#xD;&#xA;            double sprite_dist = Math.sqrt(Math.pow(px - sp.getX(), 2) + Math.pow(py - sp.getY(), 2));&#xD;&#xA;            double sprite_screen_size = Math.min(2000, PROJ_HEIGHT / sprite_dist);&#xD;&#xA;            int h_offset = (int) ((sprite_dir - ca) * (PROJ_WIDTH/2) / (fov) + (PROJ_WIDTH/2)/2 - sprite_screen_size / 2);&#xD;&#xA;            int v_offset = (int) (PROJ_HEIGHT/2 - sprite_screen_size / 2);&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            for (int i = 0; i &lt; sprite_screen_size; i++) {&#xD;&#xA;                // Adding these range guards prevents any rendering whatsoever&#xD;&#xA;                if (h_offset+i&lt;0||h_offset+i&gt;PROJ_WIDTH/2) continue;&#xD;&#xA;                for (int j = 0; j &lt; sprite_screen_size; j++) {&#xD;&#xA;                    g2.fillRect(PROJ_WIDTH/2+h_offset+i,v_offset+j,1,1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lodev.org/cgtutor/raycasting3.html&#xD;&#xA;  [2]: https://wynnliam.github.io/raycaster/news/tutorial/2019/04/03/raycaster-part-02.html&#xD;&#xA;  [3]: https://www.allegro.cc/forums/thread/355015&#xD;&#xA;  [4]: https://i.stack.imgur.com/aJ489.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37767" PostHistoryTypeId="5" PostId="12845" RevisionGUID="27ca764b-86f8-43ff-a273-3dd6a30f4db7" CreationDate="2022-07-16T13:21:25.270" UserId="18661" Comment="deleted 114 characters in body" Text="I'm trying to render sprites/textures in my raycasting engine, but I don't quite understand the math behind drawing the columns of the texture I intend to project. I've tried looking at several tutorials, e.g., [lodev][1], [Wynnliam][2], and [several posts][3] on Allegro.cc, but none of them seem to explain the sprite-casting component in an easy-to-digest way. Can anyone help? Note that I'm currently drawing a yellow square in the location of the sprite and it appears as if the sprite is not positioned in the correct spot... My main problem is that I don’t understand how to compute the column of the texture to render. Once I figure this out, I can easily add z-depth sorting, but I really have no idea how to do this step.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;        final int TEXTURE_SIZE = 64;&#xD;&#xA;        final int PROJ_HEIGHT = 640;&#xD;&#xA;        final int PROJ_WIDTH = 640;&#xD;&#xA;        ArrayList&lt;TextureSprite&gt; sprites = this.RAYCASTER_PANEL.getTileMap().getSprites();&#xD;&#xA;        for (int s = 0; s &lt; sprites.size(); s++) {&#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            // computes the distance and angle of the sprite...&#xD;&#xA;            double fov = this.RAYCASTER_PANEL.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double dx = sp.getX() - this.RAYCASTER_PANEL.getCamera().getX();&#xD;&#xA;            double dy = sp.getY() - this.RAYCASTER_PANEL.getCamera().getY();&#xD;&#xA;            double d = Point2D.distanceSq(sp.getX(), sp.getY(), this.RAYCASTER_PANEL.getCamera().getX(), this.RAYCASTER_PANEL.getCamera().getY());&#xD;&#xA;            double theta_temp = Math.toDegrees(Math.atan2(dy, dx));&#xD;&#xA;            if(theta_temp &lt; 0) theta_temp += 360;&#xD;&#xA;            if (theta_temp &gt; 360) theta_temp -= 360;&#xD;&#xA;&#xD;&#xA;            double y = ca + fov/2 - theta_temp;&#xD;&#xA;&#xD;&#xA;            if(theta_temp &gt; 270 &amp;&amp; ca &lt; 90) y = ca + fov/2 - theta_temp + 360;&#xD;&#xA;            if(ca &gt; 270 &amp;&amp; theta_temp &lt; 90) y = ca + fov/2 - theta_temp - 360;&#xD;&#xA;     &#xD;&#xA;            // attempt to compute the sprite's x, y, width, and height&#xD;&#xA;            double sw = (TEXTURE_SIZE / Math.sqrt(d)) * this.getCamera().getDistanceToProjectionPlane();&#xD;&#xA;            double sh = sw;&#xD;&#xA;            double sx = (y * PROJ_HEIGHT / fov) - sw/2.f;&#xD;&#xA;            double sy = (PROJ_HEIGHT / 2.f) - (TEXTURE_SIZE / 2.f);&#xD;&#xA;&#xD;&#xA;            // Just a temporary until I understand how to draw the textures themselves...&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            g2.fillRect((int)sx,(int)sy,(int)sw,(int)sh);&#xD;&#xA;```&#xD;&#xA;[Example of the problem][4] &#xD;&#xA;&#xD;&#xA;Code after @lightxbulb's post suggestion:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            double fov = this.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double px = this.getCamera().getX();&#xD;&#xA;            double py = this.getCamera().getY();&#xD;&#xA;            double sx = sp.getX();&#xD;&#xA;            double sy = sp.getY();&#xD;&#xA;&#xD;&#xA;            double dx = sx - px;&#xD;&#xA;            double dy = sy - py;&#xD;&#xA;            double sprite_dir = Math.atan2(dy, dx);&#xD;&#xA;            while (sprite_dir - ca &gt; 180) sprite_dir -= 360;&#xD;&#xA;            while (sprite_dir - ca &lt; -180) sprite_dir += 360;&#xD;&#xA;&#xD;&#xA;            double sprite_dist = Math.sqrt(Math.pow(px - sp.getX(), 2) + Math.pow(py - sp.getY(), 2));&#xD;&#xA;            double sprite_screen_size = Math.min(2000, PROJ_HEIGHT / sprite_dist);&#xD;&#xA;            int h_offset = (int) ((sprite_dir - ca) * (PROJ_WIDTH/2) / (fov) + (PROJ_WIDTH/2)/2 - sprite_screen_size / 2);&#xD;&#xA;            int v_offset = (int) (PROJ_HEIGHT/2 - sprite_screen_size / 2);&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            for (int i = 0; i &lt; sprite_screen_size; i++) {&#xD;&#xA;                // Adding these range guards prevents any rendering whatsoever&#xD;&#xA;                if (h_offset+i&lt;0||h_offset+i&gt;PROJ_WIDTH/2) continue;&#xD;&#xA;                for (int j = 0; j &lt; sprite_screen_size; j++) {&#xD;&#xA;                    g2.fillRect(PROJ_WIDTH/2+h_offset+i,v_offset+j,1,1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lodev.org/cgtutor/raycasting3.html&#xD;&#xA;  [2]: https://wynnliam.github.io/raycaster/news/tutorial/2019/04/03/raycaster-part-02.html&#xD;&#xA;  [3]: https://www.allegro.cc/forums/thread/355015&#xD;&#xA;  [4]: https://i.stack.imgur.com/aJ489.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37768" PostHistoryTypeId="5" PostId="12845" RevisionGUID="4d03014f-7e27-4275-a500-19bca80e5329" CreationDate="2022-07-16T13:39:48.557" UserId="18661" Comment="Changed atan2 result to degrees and changed PROJ_WIDTH in second code block (wasn't the bug)." Text="I'm trying to render sprites/textures in my raycasting engine, but I don't quite understand the math behind drawing the columns of the texture I intend to project. I've tried looking at several tutorials, e.g., [lodev][1], [Wynnliam][2], and [several posts][3] on Allegro.cc, but none of them seem to explain the sprite-casting component in an easy-to-digest way. Can anyone help? Note that I'm currently drawing a yellow square in the location of the sprite and it appears as if the sprite is not positioned in the correct spot... My main problem is that I don’t understand how to compute the column of the texture to render. Once I figure this out, I can easily add z-depth sorting, but I really have no idea how to do this step.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;        final int TEXTURE_SIZE = 64;&#xD;&#xA;        final int PROJ_HEIGHT = 640;&#xD;&#xA;        final int PROJ_WIDTH = 640;&#xD;&#xA;        ArrayList&lt;TextureSprite&gt; sprites = this.RAYCASTER_PANEL.getTileMap().getSprites();&#xD;&#xA;        for (int s = 0; s &lt; sprites.size(); s++) {&#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            // computes the distance and angle of the sprite...&#xD;&#xA;            double fov = this.RAYCASTER_PANEL.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double dx = sp.getX() - this.RAYCASTER_PANEL.getCamera().getX();&#xD;&#xA;            double dy = sp.getY() - this.RAYCASTER_PANEL.getCamera().getY();&#xD;&#xA;            double d = Point2D.distanceSq(sp.getX(), sp.getY(), this.RAYCASTER_PANEL.getCamera().getX(), this.RAYCASTER_PANEL.getCamera().getY());&#xD;&#xA;            double theta_temp = Math.toDegrees(Math.atan2(dy, dx));&#xD;&#xA;            if(theta_temp &lt; 0) theta_temp += 360;&#xD;&#xA;            if (theta_temp &gt; 360) theta_temp -= 360;&#xD;&#xA;&#xD;&#xA;            double y = ca + fov/2 - theta_temp;&#xD;&#xA;&#xD;&#xA;            if(theta_temp &gt; 270 &amp;&amp; ca &lt; 90) y = ca + fov/2 - theta_temp + 360;&#xD;&#xA;            if(ca &gt; 270 &amp;&amp; theta_temp &lt; 90) y = ca + fov/2 - theta_temp - 360;&#xD;&#xA;     &#xD;&#xA;            // attempt to compute the sprite's x, y, width, and height&#xD;&#xA;            double sw = (TEXTURE_SIZE / Math.sqrt(d)) * this.getCamera().getDistanceToProjectionPlane();&#xD;&#xA;            double sh = sw;&#xD;&#xA;            double sx = (y * PROJ_HEIGHT / fov) - sw/2.f;&#xD;&#xA;            double sy = (PROJ_HEIGHT / 2.f) - (TEXTURE_SIZE / 2.f);&#xD;&#xA;&#xD;&#xA;            // Just a temporary until I understand how to draw the textures themselves...&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            g2.fillRect((int)sx,(int)sy,(int)sw,(int)sh);&#xD;&#xA;```&#xD;&#xA;[Example of the problem][4] &#xD;&#xA;&#xD;&#xA;Code after @lightxbulb's post suggestion:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;            final int PROJ_WIDTH=1280; // changed &#xD;&#xA;            TextureSprite sp = sprites.get(s);&#xD;&#xA;            double fov = this.getCamera().getFov();&#xD;&#xA;            double ca = this.getCamera().getCurrentAngle();&#xD;&#xA;            double px = this.getCamera().getX();&#xD;&#xA;            double py = this.getCamera().getY();&#xD;&#xA;            double sx = sp.getX();&#xD;&#xA;            double sy = sp.getY();&#xD;&#xA;&#xD;&#xA;            double dx = sx - px;&#xD;&#xA;            double dy = sy - py;&#xD;&#xA;            double sprite_dir = Math.toDegrees(Math.atan2(dy, dx));&#xD;&#xA;            while (sprite_dir - ca &gt; 180) sprite_dir -= 360;&#xD;&#xA;            while (sprite_dir - ca &lt; -180) sprite_dir += 360;&#xD;&#xA;&#xD;&#xA;            double sprite_dist = Math.sqrt(Math.pow(px - sp.getX(), 2) + Math.pow(py - sp.getY(), 2));&#xD;&#xA;            double sprite_screen_size = Math.min(2000, PROJ_HEIGHT / sprite_dist);&#xD;&#xA;            int h_offset = (int) ((sprite_dir - ca) * (PROJ_WIDTH/2) / (fov) + (PROJ_WIDTH/2)/2 - sprite_screen_size / 2);&#xD;&#xA;            int v_offset = (int) (PROJ_HEIGHT/2 - sprite_screen_size / 2);&#xD;&#xA;            g2.setColor(Color.YELLOW);&#xD;&#xA;            for (int i = 0; i &lt; sprite_screen_size; i++) {&#xD;&#xA;                // Adding these range guards prevents any rendering whatsoever&#xD;&#xA;                if (h_offset+i&lt;0||h_offset+i&gt;PROJ_WIDTH/2) continue;&#xD;&#xA;                for (int j = 0; j &lt; sprite_screen_size; j++) {&#xD;&#xA;                    g2.fillRect(PROJ_WIDTH/2+h_offset+i,v_offset+j,1,1);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lodev.org/cgtutor/raycasting3.html&#xD;&#xA;  [2]: https://wynnliam.github.io/raycaster/news/tutorial/2019/04/03/raycaster-part-02.html&#xD;&#xA;  [3]: https://www.allegro.cc/forums/thread/355015&#xD;&#xA;  [4]: https://i.stack.imgur.com/aJ489.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="37769" PostHistoryTypeId="50" PostId="12259" RevisionGUID="406ea519-65c9-493d-94eb-1a4d808b2cfa" CreationDate="2022-07-16T16:04:35.383" UserId="-1" />
  <row Id="37770" PostHistoryTypeId="2" PostId="12846" RevisionGUID="5beffdfe-0ed7-43e2-9e93-7c42a3f2fc3b" CreationDate="2022-07-16T22:13:38.460" UserId="11058" Text="If I want to draw a cubic bezier curve, I need to sample points on it and draw the resulting poly lines. One could sample the curve using De Casteljau algorithm and incrementing $t$ from 0 to 1 with a given interval. However depending on the length of the curve or how far away the control points are from each other, one might want to choose bigger or smaller sampling interval. Is there a good metric to calculate a satisfactory sampling interval? Would the the length of the poly lines formed by the control points of the bezier curve be considered a good metric? Or the length of the curve itself?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37772" PostHistoryTypeId="1" PostId="12846" RevisionGUID="5beffdfe-0ed7-43e2-9e93-7c42a3f2fc3b" CreationDate="2022-07-16T22:13:38.460" UserId="11058" Text="How to decide granularity for sampling a bezier curve for rendetion" ContentLicense="CC BY-SA 4.0" />
  <row Id="37773" PostHistoryTypeId="3" PostId="12846" RevisionGUID="5beffdfe-0ed7-43e2-9e93-7c42a3f2fc3b" CreationDate="2022-07-16T22:13:38.460" UserId="11058" Text="|bezier-curve|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37774" PostHistoryTypeId="2" PostId="12847" RevisionGUID="6767f30a-92d7-4f94-a665-6ac5db115ef2" CreationDate="2022-07-18T08:41:28.587" UserId="209" Text="IIRC, Watt and Watt's &quot;Advanced Animation and Rendering Techniques&quot; (Chapter 3) has an interesting discussion on this (which I think is summarising the work of Clark https://dl.acm.org/doi/10.1145/965103.807440 ... but only the first page seems to be there :-(  )&#xD;&#xA;&#xD;&#xA;Failing that, you could try the following: Take the Cubic Bezier cage shown in green with curve in purple:&#xD;&#xA;&#xD;&#xA;[![Bezier (Possibly not 100% accurate)][1]][1]&#xD;&#xA;&#xD;&#xA;If you do a do a mid-point subdivision of the curve, you can measure the (squared) distance (red) from the centre of the straight line (blue) joining the original end points to the mid point of your curve. If this exceeds a threshold (some number of pixels), recurse, else stop.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;I seem to recall that the difference between the straight-line approx and the curve drops by a factor of 4 (or was it 8??) with each subdivision, so it converges quite rapidly.&#xD;&#xA;&#xD;&#xA;The maths to subdivide the 4 control points of any Cubic Bezier into 2 smaller Beziers is quite simple .. but I'd need to go and look it up ;-)&#xD;&#xA;&#xD;&#xA;Though, thinking about it, I'd say you might need to go one more step to account for these cases:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nxyy4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/T5QI5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37776" PostHistoryTypeId="5" PostId="12847" RevisionGUID="12732d52-8011-4ebe-8ecc-26b644863738" CreationDate="2022-07-18T12:25:24.253" UserId="209" Comment="added 15 characters in body" Text="IIRC, Watt and Watt's &quot;Advanced Animation and Rendering Techniques&quot; (Chapter 3) has an interesting discussion on this (which I think is summarising the work of Clark https://dl.acm.org/doi/10.1145/965103.807440 ... but only the first page seems to be there :-(  )&#xD;&#xA;&#xD;&#xA;Failing that, you could try the following: Take the Cubic Bezier cage shown in green with curve in purple:&#xD;&#xA;&#xD;&#xA;[![Bezier (Possibly not 100% accurate)][1]][1]&#xD;&#xA;&#xD;&#xA;If you do a do a mid-point subdivision of the curve, you can measure the (squared) distance (red) from the centre of the straight line (blue) joining the original end points to the mid point of your curve. If this exceeds a threshold (some number of pixels), recurse, else stop.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;I seem to recall that the difference between the straight-line approx and the curve drops by a factor of 4 (or was it 8??) with each subdivision, so it converges quite rapidly.&#xD;&#xA;&#xD;&#xA;The maths to subdivide the 4 control points of any Cubic Bezier into 2 smaller Beziers is quite simple .. but I'd need to go and look it up ;-)&#xD;&#xA;&#xD;&#xA;Though, thinking about it, I'd say you might need to go one more step to account for this type of starting case:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nxyy4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/T5QI5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37781" PostHistoryTypeId="2" PostId="12849" RevisionGUID="08ca4f9a-1644-47d6-9e6c-39d3998b5682" CreationDate="2022-07-18T13:56:17.557" UserId="18669" Text="I've noticed that I consistently get worse results in path-tracing when I try to do monte-carlo correctly compared to when I don't, and I think this might be because of a fundamental misunderstanding.&#xD;&#xA;&#xD;&#xA;My assumption has been that you apply MC in path-tracing by calculating PDFs for each vertex and dividing the bounce contributions by their probability, then dividing the complete path by the number of bounces. This feels wrong, since it isn't what happens in e.g. [the Scratchapixel tutorial][1].&#xD;&#xA;&#xD;&#xA;The correct method seems like multisampling the scattering function at each vertex, and integrating _those_ samples using MC. So path contributions from each vertex are multiplied together normally, but each vertex computes `sum(samples / pdfs) / num_samples`.&#xD;&#xA;&#xD;&#xA;In pseudocode, my current understanding is this:&#xD;&#xA;&#xD;&#xA;    for each bounce&#xD;&#xA;        color *= BRDF(origin, direction, etc) / pdf;&#xD;&#xA;    color / num_bounces;&#xD;&#xA;&#xD;&#xA;But I think it's really more like:&#xD;&#xA;&#xD;&#xA;    for each bounce&#xD;&#xA;        for each sample&#xD;&#xA;            contribution += BRDF(origin, direction, etc) / pdf;&#xD;&#xA;        color *= contribution / num_samples;&#xD;&#xA;&#xD;&#xA;Am I on the right track? I've been driving myself crazy with this and the algorithm being per-bounce instead of per-path feels like the only way everything would make sense.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/global-illumination-path-tracing-practical-implementation" ContentLicense="CC BY-SA 4.0" />
  <row Id="37783" PostHistoryTypeId="1" PostId="12849" RevisionGUID="08ca4f9a-1644-47d6-9e6c-39d3998b5682" CreationDate="2022-07-18T13:56:17.557" UserId="18669" Text="Applying Monte-Carlo methods in path tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="37784" PostHistoryTypeId="3" PostId="12849" RevisionGUID="08ca4f9a-1644-47d6-9e6c-39d3998b5682" CreationDate="2022-07-18T13:56:17.557" UserId="18669" Text="|pathtracing|monte-carlo|theory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37785" PostHistoryTypeId="2" PostId="12850" RevisionGUID="66910796-b496-4e3c-82b2-5cefe8b45cc8" CreationDate="2022-07-18T16:08:20.993" UserId="18665" Text="I want to render as if someone is looking at a landscape through a window, adjusting for the viewer's head position. The landscape is easy enough (just a distant plane), but I'm not sure how to approach the window frame.&#xD;&#xA;&#xD;&#xA;It seems like I want perspective *within* the window frame but for the frame itself to be fixed to the four corners of the viewport.  I'm not sure what I want matches a frustum model, because the view I want isn't rectangular? Or maybe at really far distances and low FOV it'll get close?&#xD;&#xA;&#xD;&#xA;Here's an example of rendering from a distan camera with a small FOV, one head-on and one from a side view. The head-on is fine, but in the side-view the frame has depth but is no longer aligned with the viewport.&#xD;&#xA;&#xD;&#xA;[![window square to the viewport, head-on][1]][1]&#xD;&#xA;[![window viewed from the side][2]][2]&#xD;&#xA;&#xD;&#xA;I'm using three.js but not tied to that and can rewrite the shaders if need be. I have a [demonstration of a stylized frame](https://jsfiddle.net/achatham/3okmbaun/32/) with a distant camera, high zoom, and exaggerated lateral movement, which sort of gets what I'm after, but I'm not confident in the approach.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OZuRi.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/FlikD.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37787" PostHistoryTypeId="1" PostId="12850" RevisionGUID="66910796-b496-4e3c-82b2-5cefe8b45cc8" CreationDate="2022-07-18T16:08:20.993" UserId="18665" Text="Camera model for rendering the viewport as a window frame?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37788" PostHistoryTypeId="3" PostId="12850" RevisionGUID="66910796-b496-4e3c-82b2-5cefe8b45cc8" CreationDate="2022-07-18T16:08:20.993" UserId="18665" Text="|perspective|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37793" PostHistoryTypeId="5" PostId="12847" RevisionGUID="44ac3e1e-3d30-46d9-b6af-fe1eb0a81fb5" CreationDate="2022-07-19T13:46:46.263" UserId="209" Comment="formatting" Text="IIRC, Watt and Watt's &quot;Advanced Animation and Rendering Techniques&quot; (Chapter 3) has an interesting discussion on this (which I think is summarising the work of Clark https://dl.acm.org/doi/10.1145/965103.807440 ... but only the first page seems to be there :-(  )&#xD;&#xA;&#xD;&#xA;Failing that, you could try the following: Take the Cubic Bezier cage shown in green with curve in purple:&#xD;&#xA;&#xD;&#xA;[![Bezier (Possibly not 100% accurate)][1]][1]&#xD;&#xA;&#xD;&#xA;If you do a do a mid-point subdivision of the curve, you can measure the (squared) distance (red) from the centre of the straight line (blue) joining the original end points to the mid point of your curve. If this exceeds a threshold (some number of pixels), recurse, else stop.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;I seem to recall that the difference between the straight-line approx and the curve drops by a factor of 4 (or was it 8??) with each subdivision, so it converges quite rapidly.&#xD;&#xA;&#xD;&#xA;The maths to subdivide the 4 control points of any Cubic Bezier into 2 smaller Beziers is quite simple .. but I'd need to go and look it up ;-)&#xD;&#xA;&#xD;&#xA;Though, thinking about it, I'd say you might need to go one more step to account for this type of starting case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nxyy4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/T5QI5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37794" PostHistoryTypeId="5" PostId="12847" RevisionGUID="a60e372b-6ae1-4173-ac88-c2ebeb3fa497" CreationDate="2022-07-19T14:03:07.360" UserId="209" Comment="added 398 characters in body" Text="IIRC, Watt and Watt's &quot;Advanced Animation and Rendering Techniques&quot; (Chapter 3) has an interesting discussion on this (which I think is summarising the work of Clark https://dl.acm.org/doi/10.1145/965103.807440 ... but only the first page seems to be there :-(  )&#xD;&#xA;&#xD;&#xA;**UPDATE**: There is some text from Watt and Watt describing Clark's method [available here][1]: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If that's not to your taste, you could try the following: Take the Cubic Bezier cage - shown in green  - with the curve in purple:&#xD;&#xA;&#xD;&#xA;[![Bezier (Possibly not 100% accurate)][2]][2]&#xD;&#xA;&#xD;&#xA;If you do a do a mid-point subdivision of the curve, you can measure the (squared) distance (red) from the centre of the straight line (blue) joining the original end points to the mid point of your curve. If this exceeds a threshold (some number of pixels), recurse, else stop.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;I seem to recall that the difference between the straight-line approx and the curve drops by a factor of 4 (or was it 8??) with each subdivision, so it converges quite rapidly.&#xD;&#xA;&#xD;&#xA;The maths to subdivide the 4 control points of any Cubic Bezier into 2 smaller Beziers is quite simple .. but I'd need to go and look it up ...&#xD;&#xA;&#xD;&#xA;**Update 2**: [See here for splitting a Bezier in 'twain'][3]&#xD;&#xA;&#xD;&#xA;Though, thinking about it, I'd say you might need to go one more step to account for this type of starting case:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://archive.org/details/advanced-animation-and-rendering-techniques-1992/page/85/mode/2up&#xD;&#xA;  [2]: https://i.stack.imgur.com/Nxyy4.png&#xD;&#xA;  [3]: https://archive.org/details/advanced-animation-and-rendering-techniques-1992/page/79/mode/2up&#xD;&#xA;  [4]: https://i.stack.imgur.com/T5QI5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37800" PostHistoryTypeId="2" PostId="12853" RevisionGUID="d9ab8492-6810-4926-a993-415f1415c35f" CreationDate="2022-07-21T16:07:52.967" UserId="18681" Text="Im unsure about how I could describe what im trying to achieve in few words or a title so ill go on to describe it. &#xD;&#xA;&#xD;&#xA;So I have voxel, in 3D space, represented solely by its center. &#xD;&#xA;The voxel though, is going to be rendered by using a set of pre-rendered images and rotation parameters. &#xD;&#xA;E. G.: &#xD;&#xA;A function would take an x- &amp; y-rotation and match it with a particular image, which it will display on the screen&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem now is that rotation of the voxel would need to be modified based on the position and fov of the camera:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![3D Space with a Cube and a Camera][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This cube has a rotation of 0,0. But when using the above described function with the parameters 0,0 it would display a rectangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The correct parameters would be x: 45° and y: 295°&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Obviously the position on the screen can be calculated using the projected coordinates of the center and the size can be derived from the Z-coordinate of the center. And In general I have a basic idea of how I would calculate the rotation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;But im unsure if it will work correctly and if there's a more elegant way of calculating the rotation like e. g. with a matrix.&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U43rr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Kd39K.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ovj5t.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/0RB4M.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/BOUlo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37802" PostHistoryTypeId="1" PostId="12853" RevisionGUID="d9ab8492-6810-4926-a993-415f1415c35f" CreationDate="2022-07-21T16:07:52.967" UserId="18681" Text="View rotation matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="37803" PostHistoryTypeId="3" PostId="12853" RevisionGUID="d9ab8492-6810-4926-a993-415f1415c35f" CreationDate="2022-07-21T16:07:52.967" UserId="18681" Text="|3d|transformations|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37804" PostHistoryTypeId="5" PostId="12853" RevisionGUID="1528d05a-f554-4517-a0a0-97818694adf8" CreationDate="2022-07-21T16:10:19.447" UserId="18681" Comment="added 147 characters in body" Text="Im unsure about how I could describe what im trying to achieve in few words or a title so ill go on to describe it. &#xD;&#xA;&#xD;&#xA;So I have voxel, in 3D space, represented solely by its center. &#xD;&#xA;The voxel though, is going to be rendered by using a set of pre-rendered images and rotation parameters. &#xD;&#xA;E. G.: &#xD;&#xA;A function would take an x- &amp; y-rotation and match it with a particular image, which it will display on the screen (Edit: For clarity, the image the function would match with a particular rotation would be an frontal image of the voxel rotated by that rotation)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem now is that rotation of the voxel would need to be modified based on the position and fov of the camera:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![3D Space with a Cube and a Camera][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This cube has a rotation of 0,0. But when using the above described function with the parameters 0,0 it would display a rectangle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The correct parameters would be x: 45° and y: 295°&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Obviously the position on the screen can be calculated using the projected coordinates of the center and the size can be derived from the Z-coordinate of the center. And In general I have a basic idea of how I would calculate the rotation:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;But im unsure if it will work correctly and if there's a more elegant way of calculating the rotation like e. g. with a matrix.&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U43rr.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Kd39K.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ovj5t.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/0RB4M.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/BOUlo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37805" PostHistoryTypeId="2" PostId="12854" RevisionGUID="cc4d5a0d-ea0e-452c-9dad-11c0e21e7aef" CreationDate="2022-07-21T18:51:53.917" UserId="13273" Text="to generate the disired orientation matrix you can do the following:&#xD;&#xA;&#xD;&#xA;lets say `v` is the vector from the cubes origin towards the camera. `u` is the up vector of your camera in worldspace.&#xD;&#xA;&#xD;&#xA;    //This method returns the orientation towards the camera&#xD;&#xA;    Matrix3x3 calculateOrientationTowardsCamera(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result;&#xD;&#xA;        Vector3D vNormalized = v.normalized();&#xD;&#xA;        Vector3D uNormalized = u.normalized();&#xD;&#xA;        Vector3D rightDirection = cross(vNormalized, uNormalized); // this vector does not need to be normalized, because vNormalized and uNormalized is normalized already, so the result is normalized as well&#xD;&#xA;        Vector3D uCorrectedNormalized = cross(vNormalized, rightDirection); &#xD;&#xA;        result.row(0) = rightDirection;&#xD;&#xA;        result.row(1) = uCorrectedNormalized;&#xD;&#xA;        result.row(2) = vNormalized;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 get45And195Rotation()&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = Matrix3x3::Identity(); //matrix filled with &quot;0&quot;. Only the diagonal cells from left up to right down is filled with &quot;1&quot;&#xD;&#xA;        result *= rotation(45, 0, 0); //rotation should give you a rotation matrix&#xD;&#xA;        result *= rotation(0, 195, 0);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 combineRotations(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = calculateOrientationTowardsCamera(v, u);&#xD;&#xA;        result *= get45And195Rotation();&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The order of matrix multiplications is important because it is not commutative. So the result matrix from the last method applies the `calculateOrientationTowardsCamera' rotation on top of the 45/195 rotation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37807" PostHistoryTypeId="5" PostId="12854" RevisionGUID="2156e711-8ee9-44a2-98af-893f6f38263c" CreationDate="2022-07-21T20:34:04.587" UserId="13273" Comment="edited body" Text="to generate the disired orientation matrix you can do the following:&#xD;&#xA;&#xD;&#xA;lets say `v` is the vector from the cubes origin towards the camera. `u` is the up vector of your camera in worldspace.&#xD;&#xA;&#xD;&#xA;    //This method returns the orientation towards the camera&#xD;&#xA;    Matrix3x3 calculateOrientationTowardsCamera(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result;&#xD;&#xA;        Vector3D vNormalized = v.normalized();&#xD;&#xA;        Vector3D uNormalized = u.normalized();&#xD;&#xA;        Vector3D rightDirection = cross(vNormalized, uNormalized); // this vector does not need to be normalized, because vNormalized and uNormalized is normalized already, so the result is normalized as well&#xD;&#xA;        Vector3D uCorrectedNormalized = cross(vNormalized, rightDirection); &#xD;&#xA;        result.row(0) = rightDirection;&#xD;&#xA;        result.row(1) = uCorrectedNormalized;&#xD;&#xA;        result.row(2) = vNormalized;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 get45And295Rotation()&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = Matrix3x3::Identity(); //matrix filled with &quot;0&quot;. Only the diagonal cells from left up to right down is filled with &quot;1&quot;&#xD;&#xA;        result *= rotation(45, 0, 0); //rotation should give you a rotation matrix&#xD;&#xA;        result *= rotation(0, 295, 0);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 combineRotations(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = calculateOrientationTowardsCamera(v, u);&#xD;&#xA;        result *= get45And195Rotation();&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The order of matrix multiplications is important because it is not commutative. So the result matrix from the last method applies the `calculateOrientationTowardsCamera' rotation on top of the 45/295 rotation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37812" PostHistoryTypeId="5" PostId="12854" RevisionGUID="12a39794-ebb9-415a-8bde-62c3de568d44" CreationDate="2022-07-22T06:06:17.657" UserId="13273" Comment="edited body" Text="to generate the disired orientation matrix you can do the following:&#xD;&#xA;&#xD;&#xA;lets say `v` is the vector from the cubes origin towards the camera. `u` is the up vector of your camera in worldspace.&#xD;&#xA;&#xD;&#xA;    //This method returns the orientation towards the camera&#xD;&#xA;    Matrix3x3 calculateOrientationTowardsCamera(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result;&#xD;&#xA;        Vector3D vNormalized = v.normalized();&#xD;&#xA;        Vector3D uNormalized = u.normalized();&#xD;&#xA;        Vector3D rightDirection = cross(vNormalized, uNormalized); // this vector does not need to be normalized, because vNormalized and uNormalized is normalized already, so the result is normalized as well&#xD;&#xA;        Vector3D uCorrectedNormalized = cross(vNormalized, rightDirection); &#xD;&#xA;        result.row(0) = rightDirection;&#xD;&#xA;        result.row(1) = uCorrectedNormalized;&#xD;&#xA;        result.row(2) = vNormalized;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 get45And295Rotation()&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = Matrix3x3::Identity(); //matrix filled with &quot;0&quot;. Only the diagonal cells from left up to right down is filled with &quot;1&quot;&#xD;&#xA;        result *= rotation(45, 0, 0); //rotation should give you a rotation matrix&#xD;&#xA;        result *= rotation(0, 295, 0);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 combineRotations(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = calculateOrientationTowardsCamera(v, u);&#xD;&#xA;        result *= get45And195Rotation();&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The order of matrix multiplications is important because it is not commutative. So the result matrix from the last method applies the `calculateOrientationTowardsCamera` rotation on top of the 45/295 rotation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37815" PostHistoryTypeId="5" PostId="12854" RevisionGUID="66d68bdf-e895-45df-8a89-73df79cfe508" CreationDate="2022-07-22T09:45:15.780" UserId="13273" Comment="edited body" Text="to generate the disired orientation matrix you can do the following:&#xD;&#xA;&#xD;&#xA;lets say `v` is the vector from the cubes origin towards the camera. `u` is the up vector of your camera in worldspace.&#xD;&#xA;&#xD;&#xA;    //This method returns the orientation towards the camera&#xD;&#xA;    Matrix3x3 calculateOrientationTowardsCamera(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result;&#xD;&#xA;        Vector3D vNormalized = v.normalized();&#xD;&#xA;        Vector3D uNormalized = u.normalized();&#xD;&#xA;        Vector3D rightDirection = cross(vNormalized, uNormalized); // this vector does not need to be normalized, because vNormalized and uNormalized is normalized already, so the result is normalized as well&#xD;&#xA;        Vector3D uCorrectedNormalized = cross(rightDirection, vNormalized); &#xD;&#xA;        result.row(0) = rightDirection;&#xD;&#xA;        result.row(1) = uCorrectedNormalized;&#xD;&#xA;        result.row(2) = vNormalized;&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 get45And295Rotation()&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = Matrix3x3::Identity(); //matrix filled with &quot;0&quot;. Only the diagonal cells from left up to right down is filled with &quot;1&quot;&#xD;&#xA;        result *= rotation(45, 0, 0); //rotation should give you a rotation matrix&#xD;&#xA;        result *= rotation(0, 295, 0);&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Matrix3x3 combineRotations(Vector3D v, Vector3D u)&#xD;&#xA;    {&#xD;&#xA;        Matrix3x3 result = calculateOrientationTowardsCamera(v, u);&#xD;&#xA;        result *= get45And295Rotation();&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The order of matrix multiplications is important because it is not commutative. So the result matrix from the last method applies the `calculateOrientationTowardsCamera` rotation on top of the 45/295 rotation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37816" PostHistoryTypeId="2" PostId="12856" RevisionGUID="b4eeac1b-d584-4d9d-b65d-dc908b33b737" CreationDate="2022-07-22T10:18:36.647" UserId="38" Text="This question can not be quantified. There are too many variables involved. For one it really depends on what you want to happen in the scene and how much flexibility your rendering pipeline needs.&#xD;&#xA;&#xD;&#xA;But consider this: In the past there was a whole lot more of optimization work happening in the rendering pipeline. With more computational power and knowledge. This optimisation work is turned into more details. The work stays mostly constant, sure less capital overhead also. The reason for this is that if before youd spent 300 hours optimizing, now you can just add more things in that 300 hours or simply not work those hours and be less convincing.&#xD;&#xA;&#xD;&#xA;Now also what you consider photoreal changes over time. Generally, we dont strive to simulate a camera perfectly. Unless we design imaging equipment. Instead we aim for convincing enough images that are interesting. If we could photograph it efficiently and interestingly we would do that. But you know that you can photograph an image and its still not necceserily interesting nor particularily realistic looking. Most of the things you see are heavily editted, curated and filtered.&#xD;&#xA;&#xD;&#xA;So can you do this stuff with a consumer card? Sure, this kind of stuff was also done in late 90's with computers which by all metrics are less powerful than most smartphones. In essence its just a question of patience and extra work. But considering that the operator costs several thousands per month, then it does not make sense to save few thousands on the computer if your worker is more productive with more resources. So its not done because it makes sense economically not because it really needs all of this stuff." ContentLicense="CC BY-SA 4.0" />
  <row Id="37818" PostHistoryTypeId="5" PostId="12856" RevisionGUID="a4a3b5c5-df38-4370-9e1a-5d9e7a1ee762" CreationDate="2022-07-22T15:17:41.153" UserId="38" Comment="added 12 characters in body" Text="This question can not be quantified. There are too many variables involved. For one it really depends on what you want to happen in the scene and how much flexibility your rendering pipeline needs.&#xD;&#xA;&#xD;&#xA;But consider this: In the past there was a whole lot more of optimization work happening in the rendering pipeline. With more computational power and knowledge. This optimisation work is turned into more details. The work stays mostly constant, sure less capital overhead also. The reason for this is that if before youd spent 300 hours optimizing and waiting, now you can just add more things in that 300 hours or simply not work those hours and be less convincing.&#xD;&#xA;&#xD;&#xA;Now also what you consider photoreal changes over time. Generally, we dont strive to simulate a camera perfectly. Unless we design imaging equipment. Instead we aim for convincing enough images that are interesting. If we could photograph it efficiently and interestingly we would do that. But you know that you can photograph an image and its still not necceserily interesting nor particularily realistic looking. Most of the things you see are heavily editted, curated and filtered.&#xD;&#xA;&#xD;&#xA;So can you do this stuff with a consumer card? Sure, this kind of stuff was also done in late 90's with computers which by all metrics are less powerful than most smartphones. In essence its just a question of patience and extra work. But considering that the operator costs several thousands per month, then it does not make sense to save few thousands on the computer if your worker is more productive with more resources. So its not done because it makes sense economically not because it really needs all of this stuff." ContentLicense="CC BY-SA 4.0" />
  <row Id="37819" PostHistoryTypeId="50" PostId="7804" RevisionGUID="eb47c99c-6984-44de-b2f2-314f79ad6b6c" CreationDate="2022-07-22T20:01:25.093" UserId="-1" />
  <row Id="37820" PostHistoryTypeId="50" PostId="9626" RevisionGUID="324771bb-f1ab-49cb-93b3-902a0983d07a" CreationDate="2022-07-23T15:05:10.477" UserId="-1" />
  <row Id="37821" PostHistoryTypeId="50" PostId="9307" RevisionGUID="70b86b5e-5854-4023-b6bb-3f9b1e3eb9df" CreationDate="2022-07-23T22:01:45.090" UserId="-1" />
  <row Id="37822" PostHistoryTypeId="50" PostId="10535" RevisionGUID="2c83061d-af80-4cc4-b4fa-34c765107134" CreationDate="2022-07-24T05:03:45.287" UserId="-1" />
  <row Id="37823" PostHistoryTypeId="2" PostId="12857" RevisionGUID="955ee7c6-6930-4a3a-85fc-e3478c3e3e18" CreationDate="2022-07-24T22:58:30.847" UserId="18665" Text="The magic phrases for what I'm trying to achieve are &quot;oblique frustum&quot;, &quot;asymmetric projection&quot;, or &quot;off-axis camera&quot;. I haven't implemented it in three.js but achieved the right effect with this unity plugin. But the general concept is to use the more esoteric fields in the projection matrix to create a skewed view volume.&#xD;&#xA;&#xD;&#xA;* https://docs.unity3d.com/Manual/ObliqueFrustum.html&#xD;&#xA;* https://jsantell.com/portals-with-asymmetric-projection/&#xD;&#xA;* https://assetstore.unity.com/packages/tools/camera/offaxiscamera-98991&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37825" PostHistoryTypeId="50" PostId="12286" RevisionGUID="54a3a1fc-4193-467f-ab42-72f1efddcb27" CreationDate="2022-07-25T09:06:05.533" UserId="-1" />
  <row Id="37834" PostHistoryTypeId="2" PostId="12860" RevisionGUID="6d04eb40-ead5-4883-9352-f0e57da2b321" CreationDate="2022-07-25T21:19:15.330" UserId="17063" Text="I'm adding some motionblur feature to my raytracer and I'm using an uniform grid acceleration scheme (it will be updated to bvh later on) to speed up the rendering time. &#xD;&#xA;&#xD;&#xA;My problem is that if I have a strong motion blur the grid will need to intersect with too many objects in every cell and kill the rendering time by a lot.&#xD;&#xA;&#xD;&#xA;Essentially what happens is the following: for each triangle mesh I intersect it's bbox with the cells of the uniform grid and if there is an intersection I add that triangle to the intersected cell. Until now everything it's well accelerated, but now if the triangle mesh bbox contains the frame before and the frame after vertex positions (which is necessary to get the proper motion blur) that bbox grows a lot (especially if the mBlur is considerable) making it intersecting with many more cells (from let's say 15 to 200) and the raytrace engine struggles too much to be usable.&#xD;&#xA;&#xD;&#xA;So I haven't found a solution to that problem and I'm sure there is one somewhere. What am I doing  wrong here? is there any other way to make the motion blur faster? " ContentLicense="CC BY-SA 4.0" />
  <row Id="37836" PostHistoryTypeId="1" PostId="12860" RevisionGUID="6d04eb40-ead5-4883-9352-f0e57da2b321" CreationDate="2022-07-25T21:19:15.330" UserId="17063" Text="RayTracing grid acceleration slowness using motion blur" ContentLicense="CC BY-SA 4.0" />
  <row Id="37837" PostHistoryTypeId="3" PostId="12860" RevisionGUID="6d04eb40-ead5-4883-9352-f0e57da2b321" CreationDate="2022-07-25T21:19:15.330" UserId="17063" Text="|raytracing|blur|motion|grid|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37842" PostHistoryTypeId="2" PostId="12862" RevisionGUID="5aeecfb3-cd5e-44a4-b14a-e90f08b5199e" CreationDate="2022-07-26T05:19:41.490" UserId="18693" Text="I've been watching this Ancient Earth glob for sometime and got mesmerized by it. It ticked my imagination enough that I wonder what technology was used in the creation of this beautiful Ancient Earth Globe in the Ancient Dinosaurs website.&#xD;&#xA;&#xD;&#xA;The link to the Ancient Earth looks like this:&#xD;&#xA;&#xD;&#xA;https://dinosaurpictures.org/ancient-earth#&#xD;&#xA;&#xD;&#xA;[![Ancient Earth globe][1]][1]&#xD;&#xA;&#xD;&#xA;What is the technology used in the creation of Ancient Earth globe? It greatly interests me and perhaps, I might make my own graphics with the technology used in the making of Ancient Earth globe...&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xJOZv.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37844" PostHistoryTypeId="1" PostId="12862" RevisionGUID="5aeecfb3-cd5e-44a4-b14a-e90f08b5199e" CreationDate="2022-07-26T05:19:41.490" UserId="18693" Text="What technology was used in the creation of Ancient Earth in dinosaurpictures.org website?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37845" PostHistoryTypeId="3" PostId="12862" RevisionGUID="5aeecfb3-cd5e-44a4-b14a-e90f08b5199e" CreationDate="2022-07-26T05:19:41.490" UserId="18693" Text="|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37846" PostHistoryTypeId="5" PostId="12862" RevisionGUID="4678e392-7dde-4985-a649-6c3a7c96eaa2" CreationDate="2022-07-26T05:19:57.840" UserId="18693" Comment="added 1 character in body" Text="I've been watching this Ancient Earth globe for sometime and got mesmerized by it. It ticked my imagination enough that I wonder what technology was used in the creation of this beautiful Ancient Earth Globe in the Ancient Dinosaurs website.&#xD;&#xA;&#xD;&#xA;The link to the Ancient Earth looks like this:&#xD;&#xA;&#xD;&#xA;https://dinosaurpictures.org/ancient-earth#&#xD;&#xA;&#xD;&#xA;[![Ancient Earth globe][1]][1]&#xD;&#xA;&#xD;&#xA;What is the technology used in the creation of Ancient Earth globe? It greatly interests me and perhaps, I might make my own graphics with the technology used in the making of Ancient Earth globe...&#xD;&#xA;&#xD;&#xA;Thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xJOZv.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="37848" PostHistoryTypeId="2" PostId="12863" RevisionGUID="a36ba912-02d3-48f7-b5d0-8f21adba6b16" CreationDate="2022-07-26T09:54:05.860" UserId="18696" Text="Short answer is yes.&#xD;&#xA;MRG32k3a has withstood the test of time, much more than PCG or XorShift256*. In fact, a recent paper by Matsumoto (creator of Mersenne-Twister) shows some poor properties of XorShift128 variants. So going 64-bit is not the answer.&#xD;&#xA;&#xD;&#xA;64-bit is also ambiguous. The question indirectly assumes 64-bit+ of state. It could also mean the size of the one random integer output in bits. MRG32k3a will give you (almost) 32-bit numbers as output (I think actually 31).&#xD;&#xA;&#xD;&#xA;The [latest implementation](https://github.com/vigna/MRG32k3a) by Vigna of MRG32k3a is fast on CPUs.&#xD;&#xA;&#xD;&#xA;MRG32k3a has also a relatively efficient skip to arbitrary positions in the stream, which may be useful for multithreading, although there are faster alternatives, the fastests generators to skip are counter based generators derived from crypto, such as Chacha or Philox. But they are also slower in general at generating a single number. Finally Xoshiro256++, used in the Julia programming language by default, offers a decent compromise between fast generation and efficient skip." ContentLicense="CC BY-SA 4.0" />
  <row Id="37876" PostHistoryTypeId="2" PostId="12869" RevisionGUID="3e7db02b-e509-416a-b6e1-a8db52695b9f" CreationDate="2022-07-27T16:04:13.333" UserId="6562" Text="I want to create an animated GIF, but instead of 8-bit 256 colours, my data is comprised of binary bitmaps of black/white pixels.&#xD;&#xA;&#xD;&#xA;Can GIF accommodate this, or are pixels in GIF always 8-bit indices?&#xD;&#xA;&#xD;&#xA;I need the resulting GIF to be small in size, so I cannot afford to waste 7 of the 8 bits.&#xD;&#xA;&#xD;&#xA;If GIF does not support this, is there any other file format that would allow me to do this?&#xD;&#xA;&#xD;&#xA;I believe that TIFF supports 1-bit images, but I've never seen an animated TIFF file.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37878" PostHistoryTypeId="1" PostId="12869" RevisionGUID="3e7db02b-e509-416a-b6e1-a8db52695b9f" CreationDate="2022-07-27T16:04:13.333" UserId="6562" Text="Animated bitmaps with 2 colours only" ContentLicense="CC BY-SA 4.0" />
  <row Id="37879" PostHistoryTypeId="3" PostId="12869" RevisionGUID="3e7db02b-e509-416a-b6e1-a8db52695b9f" CreationDate="2022-07-27T16:04:13.333" UserId="6562" Text="|animation|raster-image|bitmap-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37880" PostHistoryTypeId="50" PostId="5996" RevisionGUID="ca760de8-988e-4490-98ad-a675f79a9d47" CreationDate="2022-07-27T17:06:45.687" UserId="-1" />
  <row Id="37885" PostHistoryTypeId="2" PostId="12871" RevisionGUID="f9301dcb-1e0b-44e6-aa31-bcd177dce95d" CreationDate="2022-07-28T07:15:12.150" UserId="18701" Text="Actually by referencing to this presentation https://advances.realtimerendering.com/s2016/s2016_ltc_rnd.pdf, I use the &quot;Form Vector&quot; to intersect with the texture and it works well. This also helps to get rid of the annoying margin in prefiltering.&#xD;&#xA;&#xD;&#xA;However, I'm still stuck on the texture prefiltering section for not knowing how to properly choose prefilter kernel size and select lod at runtime." ContentLicense="CC BY-SA 4.0" />
  <row Id="37887" PostHistoryTypeId="2" PostId="12872" RevisionGUID="eef99685-b093-4664-a328-49913a71d523" CreationDate="2022-07-28T14:46:24.500" UserId="18704" Text="The formula for Phong illumination [as given on Wikipedia](https://en.wikipedia.org/wiki/Phong_reflection_model#Description) (see there for the variable definitions) is:&#xD;&#xA;&#xD;&#xA;$$I_\text{p} = k_\text{a} i_\text{a} + \sum_{m\;\in\;\text{lights}} (k_\text{d} (\hat{L}_m \cdot \hat{N}) i_{m,\text{d}} + k_\text{s} (\hat{R}_m \cdot \hat{V})^{\alpha}i_{m,\text{s}})$$&#xD;&#xA;&#xD;&#xA;This gives the &quot;illumination&quot; of a point on a surface.  However, once I've calculated that, how do I take the color of the surface into account to find the final value of, say, a raytraced pixel?  Do I just multiply the illumination by the surface color's RGB components?  Are the RGB components expected to have already been taken into account in the $k_a, k_d, k_s$ terms?  None of the raytracing tutorials I've found online come out and give a straight answer to this question, aside from [this](https://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_2_Phong_Mirrors_and_Shadows.shtml), which multiplies the diffuse term but not the specular term by the surface color (and omits the ambient term entirely), something which [this page](https://www.scratchapixel.com/lessons/3d-basic-rendering/phong-shader-BRDF) implies should only be done for dielectrics." ContentLicense="CC BY-SA 4.0" />
  <row Id="37889" PostHistoryTypeId="1" PostId="12872" RevisionGUID="eef99685-b093-4664-a328-49913a71d523" CreationDate="2022-07-28T14:46:24.500" UserId="18704" Text="Applying Phong illumination to a colored surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="37890" PostHistoryTypeId="3" PostId="12872" RevisionGUID="eef99685-b093-4664-a328-49913a71d523" CreationDate="2022-07-28T14:46:24.500" UserId="18704" Text="|raytracing|color|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37891" PostHistoryTypeId="6" PostId="12872" RevisionGUID="3734125c-2361-4e9e-82f3-fa53bf46475d" CreationDate="2022-07-28T14:53:34.653" UserId="18704" Comment="edited tags" Text="|raytracing|lighting|color|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37892" PostHistoryTypeId="5" PostId="10" RevisionGUID="560c2529-0d4d-4f66-8674-c2010e739185" CreationDate="2022-07-29T06:04:31.110" UserId="18705" Comment="fixed a dead link" Text="As TheBuzzSaw said, it does depend on lots of things, including implementations of the rasterized graphics vs the vector graphics.&#xD;&#xA;&#xD;&#xA;Here are some high performance vector graphics methods that are rendered using traditionally rasterization methods.&#xD;&#xA;&#xD;&#xA;Loop and Blinn show how to render a vector graphics quadratic bezier curve by rendering a single triangle, and using the texture coordinates in a pixel shader to say whether a pixel is above or below the curve:&#xD;&#xA;http://www.msr-waypoint.net/en-us/um/people/cloop/LoopBlinn05.pdf&#xD;&#xA;&#xD;&#xA;The basic idea is that you set your triangle corner positions to be the 3 control point positions, and you set the texture coordinates at each corner to be (0,0), (0.5,0) and (1,1) respectively.  In your shader, if the interpolated texture coordinate (x*x-y) is &lt; 0, the pixel is underneath the curve, else it's above the curve.&#xD;&#xA;&#xD;&#xA;You can see a faux implementation of it on shadertoy here:&#xD;&#xA;https://www.shadertoy.com/view/4tj3Dy&#xD;&#xA;&#xD;&#xA;As for the second method, here's a method from Valve, where distances to a shape are stored in a texture, instead of pixel data, allowing vector graphics to be drawn by using texture sampling.  The decoding is so simple, it could be implemented even on fixed function hardware using only an alpha test!&#xD;&#xA;https://cdn.akamai.steamstatic.com/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf&#xD;&#xA;&#xD;&#xA;To give you an idea of how well the second technique works, this 1024x768 mustache image was generated from a 64x32 source image that had a single color channel! (aka 2KB uncompressed)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I also wrote some stuff about it on my blog:&#xD;&#xA;http://blog.demofox.org/2014/06/30/distance-field-textures/&#xD;&#xA;&#xD;&#xA;Here is some sample OpenCL code to show just how simple it is:&#xD;&#xA;&#xD;&#xA;    float alpha = read_imagef(tex3dIn, g_textureSampler, textureCoords).w;&#xD;&#xA;    float3 color = (alpha &lt; 0.5f) ? (float3)(1.0f) : (float3)(0.0f);&#xD;&#xA;&#xD;&#xA;Both of these techniques are super fast, and blur the line between vector and rasterized graphics a bit.  They are rendered using rasterization techniques, but have zooming / scaling properties like vector graphics techniques.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wlC0y.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37893" PostHistoryTypeId="24" PostId="10" RevisionGUID="560c2529-0d4d-4f66-8674-c2010e739185" CreationDate="2022-07-29T06:04:31.110" Comment="Proposed by 18705 approved by 13095 edit id of 580" ContentLicense="CC BY-SA 4.0" />
  <row Id="37894" PostHistoryTypeId="50" PostId="12807" RevisionGUID="ee557125-c7e9-468d-ba07-397dfa9401b0" CreationDate="2022-07-29T11:03:50.307" UserId="-1" />
  <row Id="37900" PostHistoryTypeId="2" PostId="12874" RevisionGUID="6fb530a7-7a13-498d-bbd3-20af8ee94515" CreationDate="2022-07-29T22:26:07.660" UserId="18357" Text="If you only need to update a subset of the vertex data, you could use glBufferSubData() with the offset and size to upload only that section to the GPU. That has worked well for me in the past. It's hard to say how well suited it is to your case without knowing more about how big the data chunk associated with each of your vertices is, how many you nominally update per frame, and how contiguous that subsection is within the full set. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37903" PostHistoryTypeId="2" PostId="12875" RevisionGUID="69373ec7-9702-4068-8175-e97ed50ea02b" CreationDate="2022-07-30T18:50:39.450" UserId="18704" Text="According to chapter 6 of [*The Ray Tracer Challenge* by Jamis Buck](http://raytracerchallenge.com), in order to get the final color, the color of the material is multiplied by the ambient term and the diffuse term but not by the specular term.  $k_a$, $k_d$, and $k_s$, meanwhile, are simply material properties in the range $[0,1]$." ContentLicense="CC BY-SA 4.0" />
  <row Id="37906" PostHistoryTypeId="50" PostId="10378" RevisionGUID="47836fe0-9d90-4833-b0f8-78b5bee68bc9" CreationDate="2022-07-31T18:07:35.733" UserId="-1" />
  <row Id="37911" PostHistoryTypeId="50" PostId="12797" RevisionGUID="381750c6-2a71-4e9a-9c35-842edd9ce3e5" CreationDate="2022-07-31T20:03:00.277" UserId="-1" />
  <row Id="37919" PostHistoryTypeId="2" PostId="12878" RevisionGUID="ec0d1dd1-1ebb-468d-849b-ae94a96edee3" CreationDate="2022-08-02T07:59:48.927" UserId="13273" Text="I want to improve my shadow mapping depth precision by getting the minimum and maximum depth value within my shadow map. When having both values I would convert the depth map to convolution shadow map basis functions and encode the values to 8bit each, which looses precision a lot, in case the depth span is high. &#xD;&#xA;&#xD;&#xA;Right now I render the scenario depth values into a R32F texture. A second shader checks for each pixel, if it is the min / max depth within the shadowmap by using SSBO and AtomicMax / AtomicMin.&#xD;&#xA;Then the next shader converts the depth values with respect to the min/max depth into the basis functions of convolution shadow mapping.&#xD;&#xA;&#xD;&#xA;Is there a way to get the minimum / maximum depth during the render pass of the scenario? If this is the case, I could skip the second shader.&#xD;&#xA;&#xD;&#xA;During the geometry rendering within the fragment shader I can get the depth value and use the AtomicMin / AtomixMax function. But when doing so, there can be the case (it happens very often) that fragments will be executed, which are behind other faces. so the max distance will be wrong at the end, which decreases the shadow map precision.&#xD;&#xA;&#xD;&#xA;I found the `layout(early_fragment_tests) in;` specification. But I am not sure if this will solve the problem. Does the specification solve my problem? Or do you have other ideas?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37921" PostHistoryTypeId="1" PostId="12878" RevisionGUID="ec0d1dd1-1ebb-468d-849b-ae94a96edee3" CreationDate="2022-08-02T07:59:48.927" UserId="13273" Text="efficient way to get min/max distance during rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="37922" PostHistoryTypeId="3" PostId="12878" RevisionGUID="ec0d1dd1-1ebb-468d-849b-ae94a96edee3" CreationDate="2022-08-02T07:59:48.927" UserId="13273" Text="|opengl|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37929" PostHistoryTypeId="5" PostId="6268" RevisionGUID="8d6591f5-91db-4847-97b9-6284e6d3202f" CreationDate="2022-08-03T08:32:35.767" UserId="171" Comment="readibility ++" Text="Why don't we just use a hash function to reduce the size of a bitmap, rgb or raw image? Isn't it more efficient of storage data and it produces lossless image after being decoded? The decoder is also very simple, and it would use an universal standard hash code for all images. Some private image would have its own hash code. Isn't it an opportunity for us to compress a file to very low capacity, without any complicated algorithm and entropy code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37930" PostHistoryTypeId="4" PostId="6268" RevisionGUID="8d6591f5-91db-4847-97b9-6284e6d3202f" CreationDate="2022-08-03T08:32:35.767" UserId="171" Comment="readibility ++" Text="Why not use hash function image instead of jpeg?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37931" PostHistoryTypeId="24" PostId="6268" RevisionGUID="8d6591f5-91db-4847-97b9-6284e6d3202f" CreationDate="2022-08-03T08:32:35.767" Comment="Proposed by 171 approved by 13095 edit id of 581" ContentLicense="CC BY-SA 4.0" />
  <row Id="37932" PostHistoryTypeId="2" PostId="12880" RevisionGUID="6b9e8912-9fe2-44d5-a1bb-98de1850c829" CreationDate="2022-08-03T11:07:41.513" UserId="7952" Text="This question is conflating different lighting models, Phong lighting has no concept of dielectrics and the referenced website is clearly just comparing the Phong models to more physically based models. All the websites listed are consistent in their presentation of the Phong model which is fundamentally and intentionally simple as it reflects the capabilities of the hardware it was designed to run on. ( I agree that the flip code site is confusing and the formula's don't even display correctly in my browser)&#xD;&#xA;&#xD;&#xA;$I_p$ reads as *intensity sub point* this is what the entire goal of computing the lighting is. Once intensity is computed for the lighting it is multiplied by the point color and its done. Again, this is for the Phong lighting model. $k_a$, $k_d$ and $k_s$ are constants used to compute $I_p$ that is why they are on the *right hand side of the equation*. Once $I_p$ is computed $k_a$, $k_d$ and $k_s$ are no longer needed and do not participate in lighting calculations further.&#xD;&#xA;&#xD;&#xA;To talk it through...&#xD;&#xA;The term $k_ai_a$ represents the ambient contribution of the light. Think of a room painted bright red with a white light in it. The &quot;ambient&quot; light in the room is going to pick up a red color as it bounces off all those red walls. $k_a$ is most often used to represent that red color while $i_a$ represents the  intensity of that light. When multiplied they represent the ambient term for the lighting calculation. $i_a$ is usually just a floating point value and is very small relative to diffuse and specular. Some models will drop the ambient term all together. (but then they are no longer a true Phong lighting model). In real code this term is almost always a pre-multiplied constant and is not actually computed.&#xD;&#xA;&#xD;&#xA;$k_d(\hat{L}_m⋅N)i_{m,d}$ here $k_d$ is a constant and again is almost always used as the color of the light, in this example it would be white. $(\hat{L}_m⋅N)$ is the cosine of the angle between the light the surface normal, and $I_{m,d}$ is the intensity of the diffuse light. When multiplied out this term represents the &quot;diffuse&quot; component of the light. In real code the terms $k_d$ and $I_{m,d}$ are almost always a pre-multiplied constant and are not actually computed.&#xD;&#xA;&#xD;&#xA;Finally, $k_s(\hat{R}_m⋅\hat{V})^αi_{m,s}$ here again $k_s$ is a constant, and again almost always a color representing the light and $k_s$ almost always is equal to $k_d$. Next $i_{m,s}$ is the specular intensity and it is almost always equal to diffuse intensity, and again is pre-multiplied with $k_s$, is very frequently the same value used for diffuse and is usually constant for a given light. The value $(\hat{R}_m⋅\hat{V})^α$ is the specular intensity. Once computed this term represents specular intensity. So in this case the specular $k_s$ is white and the intensity is equal to $i_d$. (so we end up with the same constant used to compute the diffuse term)&#xD;&#xA;&#xD;&#xA;Now add them up... A little bit of red light from the ambient plus the diffuse light which is a bright white plus very bright white highlights from the specular. This is $I_p$, call it &quot;light_intensity&quot; now figure out the color of the point, and compute the final color...&#xD;&#xA;&#xD;&#xA;    // lets make the color a constant blue-green...&#xD;&#xA;    vec4 point_color = vec4(0.0,0.2,0.8, 1.0);&#xD;&#xA;    final_color = light_intensity * point_color;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37934" PostHistoryTypeId="5" PostId="12880" RevisionGUID="1fb240cd-8dee-449c-96a2-d20897bc07df" CreationDate="2022-08-03T11:13:09.243" UserId="7952" Comment="added 85 characters in body" Text="This question is conflating different lighting models, Phong lighting has no concept of dielectrics and the referenced website is clearly just comparing the Phong models to more physically based models. All the websites listed are consistent in their presentation of the Phong model which is fundamentally and intentionally simple as it reflects the capabilities of the hardware it was designed to run on. ( I agree that the flip code site is confusing and the formula's don't even display correctly in my browser)&#xD;&#xA;&#xD;&#xA;$I_p$ reads as *intensity sub point* this is what the entire goal of computing the lighting is. Once intensity is computed for the lighting it is multiplied by the point color and its done. Again, this is for the Phong lighting model. $k_a$, $k_d$ and $k_s$ are constants used to compute $I_p$ that is why they are on the *right hand side of the equation*. Once $I_p$ is computed $k_a$, $k_d$ and $k_s$ are no longer needed and do not participate in lighting calculations further.&#xD;&#xA;&#xD;&#xA;To talk it through...&#xD;&#xA;The term $k_ai_a$ represents the ambient contribution of the light. Think of a room painted bright red with a white light in it. The &quot;ambient&quot; light in the room is going to pick up a red color as it bounces off all those red walls. $k_a$ is most often used to represent that red color while $i_a$ represents the  intensity of that light. When multiplied they represent the ambient term for the lighting calculation. $i_a$ is usually just a floating point value and is very small relative to diffuse and specular. Some models will drop the ambient term all together. (but then they are no longer a true Phong lighting model). In real code this term is almost always a pre-multiplied constant and is not actually computed.&#xD;&#xA;&#xD;&#xA;$k_d(\hat{L}_m⋅N)i_{m,d}$ here $k_d$ is a constant and again is almost always used as the color of the light, in this example it would be white. $(\hat{L}_m⋅N)$ is the cosine of the angle between the light the surface normal, and $I_{m,d}$ is the intensity of the diffuse light. When multiplied out this term represents the &quot;diffuse&quot; component of the light. In real code the terms $k_d$ and $I_{m,d}$ are almost always a pre-multiplied constant and are not actually computed.&#xD;&#xA;&#xD;&#xA;Finally, $k_s(\hat{R}_m⋅\hat{V})^αi_{m,s}$ here again $k_s$ is a constant, and again almost always a color representing the light and $k_s$ almost always is equal to $k_d$. Next $i_{m,s}$ is the specular intensity and it is almost always equal to diffuse intensity, and again is pre-multiplied with $k_s$, is very frequently the same value used for diffuse and is usually constant for a given light. The value $(\hat{R}_m⋅\hat{V})^α$ is the cosine of the angle between view vector and the reflection vector raised to the specular power $\alpha$. Once computed this term represents specular intensity. So in this case the specular $k_s$ is white and the intensity is equal to $i_d$. (so we end up with the same constant used to compute the diffuse term)&#xD;&#xA;&#xD;&#xA;Now add them up... A little bit of red light from the ambient plus the diffuse light which is a bright white plus very bright white highlights from the specular. This is $I_p$, call it &quot;light_intensity&quot; now figure out the color of the point, and compute the final color...&#xD;&#xA;&#xD;&#xA;    // lets make the color a constant blue-green...&#xD;&#xA;    vec4 point_color = vec4(0.0,0.2,0.8, 1.0);&#xD;&#xA;    final_color = light_intensity * point_color;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37937" PostHistoryTypeId="2" PostId="12881" RevisionGUID="84036dce-53cc-4734-9f7a-65a457243d36" CreationDate="2022-08-04T06:32:55.550" UserId="18726" Text="Thanks @IneQuation, I'm also wondering what is bilateral upsampling recently, and the post by Angelo Pesce you provided explained his practices quite well, but one thing should be made clear ahead —— 'Bilateral Filtering' usually means adding neigboring pixel similarity factor to Guassian Filtering, which can be used to denoise and preserve sharp edges, but 'Bilateral Upsampling' Angelo talked about has nothing to do with Gaussian, it's Bilinear Upsampling added with depth and normal continuity factor, and so also named with 'Bilateral'. [This presentation by AMD's Shopf][1] explained it better for beginners I think.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.amd.com/wordpress/media/2012/10/ShopfMixedResolutionRendering.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="37939" PostHistoryTypeId="2" PostId="12882" RevisionGUID="527f0b30-7616-4b79-91ec-5fdd8ba9f8bd" CreationDate="2022-08-04T10:30:50.050" UserId="18727" Text="I am following a book &quot;Ray tracer challenge&quot; by Buck, but it doesn't explain anything. The code works, but I don't properly understand, why.&#xD;&#xA;&#xD;&#xA;The code is as follows:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;struct camera {&#xD;&#xA;    unsigned hsize; // in px;&#xD;&#xA;    unsigned vsize; // in px;&#xD;&#xA;    float fov;&#xD;&#xA;    float pixel_size;&#xD;&#xA;    float half_width;&#xD;&#xA;    float half_height;&#xD;&#xA;    tform4 tform;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;camera::camera(unsigned hsize, unsigned vsize, float fov) noexcept&#xD;&#xA;    : hsize{hsize}, vsize{vsize}, fov{fov}, tform{} {&#xD;&#xA;    float half_view = std::tan(fov / 2.f);&#xD;&#xA;    float aspect = float(hsize) / float(vsize);&#xD;&#xA;    if (aspect &gt;= 1.f) {&#xD;&#xA;        half_width = half_view;&#xD;&#xA;        half_height = half_view / aspect;&#xD;&#xA;    } else {&#xD;&#xA;        half_width = half_view * aspect;&#xD;&#xA;        half_height = half_view;&#xD;&#xA;    }&#xD;&#xA;    pixel_size = (half_width * 2.f) / hsize;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;tform4 view(pnt3 const&amp; from, pnt3 const&amp; to, vec3 const&amp; up) noexcept {&#xD;&#xA;    vec3 const forward = normalize(to - from);&#xD;&#xA;    vec3 const left = normalize(cross(forward, normalize(up)));&#xD;&#xA;    vec3 const true_up = normalize(cross(left, forward));&#xD;&#xA;    tform4 orientation{left.x,     left.y,     left.z,     0, //&#xD;&#xA;                       true_up.x,  true_up.y,  true_up.z,  0, //&#xD;&#xA;                       -forward.x, -forward.y, -forward.z, 0};&#xD;&#xA;    return orientation * tform4::translate({-from.x, -from.y, -from.z});&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ray ray_for_pixel(camera const&amp; cam, float px, float py) noexcept {&#xD;&#xA;    // offset from edge of canvas to pixel center&#xD;&#xA;    float const xoffset = (px + 0.5f) * cam.pixel_size;&#xD;&#xA;    float const yoffset = (py + 0.5f) * cam.pixel_size;&#xD;&#xA;&#xD;&#xA;    // cam looks towards -z, x is to the left&#xD;&#xA;    float const world_x = cam.half_width - xoffset;&#xD;&#xA;    float const world_y = cam.half_height - yoffset;&#xD;&#xA;    assert(-1.f &lt;= world_x &amp;&amp; world_x &lt;= 1.f);&#xD;&#xA;    assert(-1.f &lt;= world_y &amp;&amp; world_y &lt;= 1.f);&#xD;&#xA;&#xD;&#xA;    // canvas is at z=-1&#xD;&#xA;    tform4 inv_cam_tform = inverse(cam.tform);&#xD;&#xA;    pnt3 const pixel = inv_cam_tform * pnt3{world_x, world_y, -1};&#xD;&#xA;    pnt3 const origin = inv_cam_tform * pnt3{0, 0, 0};&#xD;&#xA;    vec3 const direction = normalize(pixel - origin);&#xD;&#xA;&#xD;&#xA;    return ray{origin, direction};&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I left the comments as in pseudocode which I took this from.&#xD;&#xA;&#xD;&#xA;So, I was reading about cameras etc. from Lengyel &quot;Rendering&quot;, and I cannot match how it's usually done on the GPU with what I'm doing above. Or generally, I cannot match it against anything I've read elsewhere (learnopengl, scratchapixel, songho). He provides this picture:&#xD;&#xA;&#xD;&#xA;[![img][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is understanding how camera transformation matrix and ray generation functions work.&#xD;&#xA;&#xD;&#xA;I use left hand coordinate system. So, X grows to the right, Y grows up, Z grows into the screen. Do I understand correctly, based on the code, that in my camera space X grows to the left, Y grows up, Z grows outside of the screen? In other words, seems like the camera is looking at the opposite side of where the scene is, towards -Z.&#xD;&#xA;&#xD;&#xA;Now, I generate a new basis in `view()`, okay, I understand that. However, [this](http://www.songho.ca/opengl/gl_lookattoaxes.html) demonstrates filling the transformation matrix by columns, while I'm doing it by rows. Why am I doing it this way? I am using column major matrices. When I need to fill in a transformation matrix, I do it column-wise, not row-wise. Okay, I thought, maybe it is already inverted, because inverse of orthogonal matrix is its transpose. But how does inverting it make any sense? I multiply it by another transformation matrix of translation, which is not inverted. And I also later invert the result of `view()` (`inv_cam_tform`), so... what is going on here?&#xD;&#xA;&#xD;&#xA;Another thing. The `forward` vector is negated. In the source above, it is not. Okay, I _guess_ it is because camera is looking towards -Z. But I do not _understand_ it, clear as day.&#xD;&#xA;&#xD;&#xA;Ray generation. Okay, I need to adjust the coordinate for the center of the pixel, hence the +0.5. But what is `x/yoffset`, ultimately? Coordinates of a concrete point on the canvas (or I guess projection plane) in world space? Why is there no Z coordinate? Did we make a prespective divide at z=-1 or something, so this is already device space? Then where was the clip space? Why is there no projection matrix?&#xD;&#xA;&#xD;&#xA;Another picture of camera for reference (also from Lengyel):&#xD;&#xA;&#xD;&#xA;[![img2][2]][2]&#xD;&#xA;&#xD;&#xA;And then what is the meaning of `world_x/y`? What is `half_width/height`? On the picture, half width would be `s`, and half height would be `1`, correct? Except that the picture is only for 16:9, while this code can handle any aspect ratio based on width and height. Seems like these are the coordinates of pixel in world space, so a ray can be generated from origin towards these coordinates, to find any intersections with the scene. But why is the origin of the ray at 0? Shouldn't it be at the origin of the camera? Or does the translation transformation in `view()` account for that?&#xD;&#xA;&#xD;&#xA;I do not have any solid understanding of what is happening. Every resource, be it a blog like learnopengl or scratchapixel, a book like Lengyel's, explain everything differently and never generally (although Lengyel is probably the best so far), just in coherence with their line of thought and conventions. Can you make any sense of all this mess in my head? Sorry for incoherent explanation.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I49pK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YB5yF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37941" PostHistoryTypeId="1" PostId="12882" RevisionGUID="527f0b30-7616-4b79-91ec-5fdd8ba9f8bd" CreationDate="2022-08-04T10:30:50.050" UserId="18727" Text="Understanding camera of a CPU raytracer from &quot;Ray tracer challenge&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37942" PostHistoryTypeId="3" PostId="12882" RevisionGUID="527f0b30-7616-4b79-91ec-5fdd8ba9f8bd" CreationDate="2022-08-04T10:30:50.050" UserId="18727" Text="|raytracing|transformations|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37943" PostHistoryTypeId="2" PostId="12883" RevisionGUID="096c6ed8-589d-4d35-9f3c-d14ac9c4255e" CreationDate="2022-08-04T12:37:26.763" UserId="18728" Text="Is it practical to implement the Lorenz-Mie(LM) phase function in a renderer ?&#xD;&#xA;&#xD;&#xA;$p(\cos\theta)=\frac{|S_1(\theta)|^2+|S_2(\theta)|^2}{4\pi\sum_{n=1}^\infty (2n+1)(|a_n|^2+|b_n|^2)}$&#xD;&#xA;&#xD;&#xA;I'll spare you the details but: $S_1(\theta), S_2(\theta), a_n, b_n$ are complex numbers involving Legendre polynomials, and their derivatives. All of that to say the computation are quite involved.&#xD;&#xA;&#xD;&#xA;So do the benefit of LM phase function(Physical accuracies mainly) outweighs the cost to computed them, or I better of with the standard Henyey-Greenstein or some modified version of it ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37945" PostHistoryTypeId="1" PostId="12883" RevisionGUID="096c6ed8-589d-4d35-9f3c-d14ac9c4255e" CreationDate="2022-08-04T12:37:26.763" UserId="18728" Text="(Lorenz-)Mie phase function instead of Henyey-Greenstein?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37946" PostHistoryTypeId="3" PostId="12883" RevisionGUID="096c6ed8-589d-4d35-9f3c-d14ac9c4255e" CreationDate="2022-08-04T12:37:26.763" UserId="18728" Text="|pathtracing|volumetric|volumetric-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37947" PostHistoryTypeId="5" PostId="12883" RevisionGUID="29424a92-990a-48f0-baac-5f0c22c9553f" CreationDate="2022-08-04T12:38:26.587" UserId="18728" Comment="added 1 character in body" Text="Is it practical to implement the Lorenz-Mie(LM) phase function in a renderer ?&#xD;&#xA;&#xD;&#xA;$p(\cos\theta)=\frac{|S_1(\theta)|^2+|S_2(\theta)|^2}{4\pi\sum_{n=1}^\infty (2n+1)(|a_n|^2+|b_n|^2)}$&#xD;&#xA;&#xD;&#xA;I'll spare you the details but: $S_1(\theta), S_2(\theta), a_n, b_n$ are complex numbers involving Legendre polynomials, and their derivatives. All of that to say the computations are quite involved.&#xD;&#xA;&#xD;&#xA;So do the benefit of LM phase function(Physical accuracies mainly) outweighs the cost to computed them, or I better of with the standard Henyey-Greenstein or some modified version of it ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37948" PostHistoryTypeId="5" PostId="12883" RevisionGUID="0e4f786e-83b9-45c8-b0d3-6b60d1ae98a9" CreationDate="2022-08-04T12:38:50.420" UserId="18728" Comment="added 1 character in body" Text="Is it practical to implement the Lorenz-Mie(LM) phase function in a renderer ?&#xD;&#xA;&#xD;&#xA;$p(\cos\theta)=\frac{|S_1(\theta)|^2+|S_2(\theta)|^2}{4\pi\sum_{n=1}^\infty (2n+1)(|a_n|^2+|b_n|^2)}$&#xD;&#xA;&#xD;&#xA;I'll spare you the details but: $S_1(\theta), S_2(\theta), a_n, b_n$ are complex numbers involving Legendre polynomials, and their derivatives. All of that to say the computations are quite involved.&#xD;&#xA;&#xD;&#xA;So do the benefit of LM phase function(Physical accuracies mainly) outweighs the cost to computed them, or I better off with the standard Henyey-Greenstein or some modified version of it ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37949" PostHistoryTypeId="2" PostId="12884" RevisionGUID="1635715b-e196-40b9-b0c0-a240502e5b16" CreationDate="2022-08-04T17:35:33.127" UserId="18729" Text="Lets say I have a rectangle with known coordinates in 3D scene, and I'm projecting it using pin point camera to the plane (screen).&#xD;&#xA;&#xD;&#xA;You can imagine it deforms on the screen per camera transformation and projection.&#xD;&#xA;&#xD;&#xA;And I know the resulting project 2D coordinates on the screen.&#xD;&#xA;&#xD;&#xA;I wonder if I can recover camera parameters (projection matrix, transformation, field of view, distance from the screen and from the object) from known coordinates of the rectangle in 3d and know coordinates/results for 2d projection.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;PS: if this task has infinite many solutions or unsolvable - what a minimum extra information I could get to actually solve it ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37951" PostHistoryTypeId="1" PostId="12884" RevisionGUID="1635715b-e196-40b9-b0c0-a240502e5b16" CreationDate="2022-08-04T17:35:33.127" UserId="18729" Text="Finding Camera projection matrix from known input and output" ContentLicense="CC BY-SA 4.0" />
  <row Id="37952" PostHistoryTypeId="3" PostId="12884" RevisionGUID="1635715b-e196-40b9-b0c0-a240502e5b16" CreationDate="2022-08-04T17:35:33.127" UserId="18729" Text="|3d|transformations|projections|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37953" PostHistoryTypeId="5" PostId="12884" RevisionGUID="1caa7c77-e470-49c2-af68-ec042d44a6ff" CreationDate="2022-08-04T17:36:30.623" UserId="18729" Comment="added 10 characters in body" Text="Lets say I have a rectangle with known coordinates in 3D scene, and I'm projecting it using pin point camera to the plane (screen).&#xD;&#xA;&#xD;&#xA;You can imagine it deforms on the screen per camera transformation and projection.&#xD;&#xA;&#xD;&#xA;And I know the resulting project 2D coordinates on the screen.&#xD;&#xA;&#xD;&#xA;I wonder if I can recover camera parameters (projection matrix, transformation, field of view, distance from the screen and from the object) from known coordinates of the rectangle in 3d and know coordinates/results for 2d projection.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;PS: if this task has infinite many solutions or unsolvable - what a minimum extra information I could gather or add to actually solve it ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37954" PostHistoryTypeId="2" PostId="12885" RevisionGUID="ded12cec-c27d-45c0-b94e-beb90ee009a0" CreationDate="2022-08-04T23:00:12.907" UserId="6114" Text="It's almost never a problem of computational costs, it's a matter of how well a function works in a Monte Carlo scenario. Ie. how well it can be importance sampled. That generally leads to how well it can be inversely transformed to get an importance sampled scattering direction.&#xD;&#xA;&#xD;&#xA;With HG or some modified HG phase fnc we can nicely match Mie for anything bigger than the wavelength and looking how well it can be importance sampled it make no sense to use Mie for common cases like those we find generally in rendering. So yep you better off with HG.&#xD;&#xA;&#xD;&#xA;Eventually some good read : &#xD;&#xA;https://opg.optica.org/ao/abstract.cfm?uri=ao-35-18-3270&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="37956" PostHistoryTypeId="2" PostId="12886" RevisionGUID="1fd125b6-f288-4f87-aa70-d5870707c67d" CreationDate="2022-08-05T00:24:28.213" UserId="8572" Text="for the folks that came here expecting the technical difference, exclusive to shader execution difference between an if statement and an equivalent ternary operator, see this precise and polite explanation: https://itecnote.com/tecnote/r-shader-optimization-is-a-ternary-operator-equivalent-to-branching/" ContentLicense="CC BY-SA 4.0" />
  <row Id="37958" PostHistoryTypeId="5" PostId="12886" RevisionGUID="3c6921ec-1c85-4ce8-bfed-c22b1de5f124" CreationDate="2022-08-05T00:25:25.003" UserId="8572" Comment="xcgh explanation &lt;-&gt; difference" Text="for the folks that came here expecting the technical explanation, exclusive to shader execution difference between an if statement and an equivalent ternary operator, see this precise and polite explanation: https://itecnote.com/tecnote/r-shader-optimization-is-a-ternary-operator-equivalent-to-branching/" ContentLicense="CC BY-SA 4.0" />
  <row Id="37959" PostHistoryTypeId="2" PostId="12887" RevisionGUID="c9a22f0c-7483-4cad-ba82-036581672379" CreationDate="2022-08-05T03:21:51.467" UserId="18732" Text="As John said, yes it was there because my first job was working on content for it.  That was before 1981.  The 'snake room' was about 20 feet from my office and I did many demos on that system.  My job was as probably one of the first paid modelers in the world.  It was a very impressive machine.  E&amp;S had all kinds of other equipment they had built over the years.  Some of the smartest people I ever met worked there." ContentLicense="CC BY-SA 4.0" />
  <row Id="37961" PostHistoryTypeId="50" PostId="12817" RevisionGUID="bff9124e-d3de-42f3-a307-97c8079b51de" CreationDate="2022-08-05T13:04:35.417" UserId="-1" />
  <row Id="37962" PostHistoryTypeId="50" PostId="12826" RevisionGUID="51ca0a05-651d-401d-9917-206185476f8e" CreationDate="2022-08-05T14:07:05.727" UserId="-1" />
  <row Id="37971" PostHistoryTypeId="5" PostId="8763" RevisionGUID="3131b4e0-226a-497c-81cc-b0151f842a75" CreationDate="2022-08-06T09:51:52.243" UserId="171" Comment="added 99 characters in body" Text="Questions about the conversion of a 2D or 3D model to a photorealistic or non-photorealistic image." ContentLicense="CC BY-SA 4.0" />
  <row Id="37972" PostHistoryTypeId="24" PostId="8763" RevisionGUID="3131b4e0-226a-497c-81cc-b0151f842a75" CreationDate="2022-08-06T09:51:52.243" Comment="Proposed by 171 approved by 13095 edit id of 582" ContentLicense="CC BY-SA 4.0" />
  <row Id="37973" PostHistoryTypeId="50" PostId="9192" RevisionGUID="9662d41e-c15c-40c9-a59f-276b4d06b448" CreationDate="2022-08-07T03:07:45.700" UserId="-1" />
  <row Id="37974" PostHistoryTypeId="2" PostId="12889" RevisionGUID="09e4079b-f75f-438d-ba33-fe60068a2944" CreationDate="2022-08-07T10:01:22.183" UserId="18740" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is likely simplified by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled (and quite lo-res) input image, we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some most-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37976" PostHistoryTypeId="1" PostId="12889" RevisionGUID="09e4079b-f75f-438d-ba33-fe60068a2944" CreationDate="2022-08-07T10:01:22.183" UserId="18740" Text="Turning colorized comic-art into uncolorized monochrome (inks-only B&amp;W), not just very-light-grayscale" ContentLicense="CC BY-SA 4.0" />
  <row Id="37977" PostHistoryTypeId="3" PostId="12889" RevisionGUID="09e4079b-f75f-438d-ba33-fe60068a2944" CreationDate="2022-08-07T10:01:22.183" UserId="18740" Text="|algorithm|image-processing|2d|2d-graphics|bitmap-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37978" PostHistoryTypeId="5" PostId="12889" RevisionGUID="da9dbb55-6c6a-4520-bfef-bf8ebc7fef7b" CreationDate="2022-08-07T10:11:40.007" UserId="18740" Comment="edited body" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is likely simplified by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled (and quite lo-res) input image, we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37979" PostHistoryTypeId="5" PostId="12889" RevisionGUID="92a6a291-d42b-47e8-a0dd-7d25d7b9f465" CreationDate="2022-08-07T10:18:17.080" UserId="18740" Comment="deleted 19 characters in body" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The problem is likely simplified by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image, we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37980" PostHistoryTypeId="5" PostId="12889" RevisionGUID="96a97a26-92ca-4ca9-9e33-3ac0781eb94f" CreationDate="2022-08-07T10:20:59.703" UserId="18740" Comment="added 70 characters in body" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image, we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37981" PostHistoryTypeId="5" PostId="12889" RevisionGUID="2cc8ee7d-e5c3-440c-a294-e6d22dbc41cf" CreationDate="2022-08-07T10:41:34.687" UserId="18740" Comment="added 32 characters in body" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity per se), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37982" PostHistoryTypeId="5" PostId="12889" RevisionGUID="c0cc3c74-fffc-440e-8a7c-e4b723a4e5ab" CreationDate="2022-08-07T10:42:05.533" UserId="18740" Comment="added 6 characters in body" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37983" PostHistoryTypeId="2" PostId="12890" RevisionGUID="2b84b117-35b6-4037-a3dc-fd3c40e27048" CreationDate="2022-08-07T10:59:04.293" UserId="18737" Text="I've also been working on GTAO denoising, and came across the same equation.The function is weighing the neighbouring samples by their depth-difference from the center sample, and also by their slopes. (The higher their slope, the less influence they have) &#xD;&#xA;&#xD;&#xA;The final line inverts the weighting, which is required, because as slope and depth differences increase, you want the weight of the sample to decrease. If the slope or depth differences were between 0 and 1, you'd invert it by subtracting it from 1, however as these numbers are essentially unbounded, they are mapped into an 0 to 1 range by inverting, and then adding a small bias of 1.25, then clamping within 0 to 1 with the saturate function.&#xD;&#xA;&#xD;&#xA;The other part of the equation is dividing the weights by &quot;centerZ * 0.011.&quot; Using a uniform weighting does not work nicely for all distances. Samples close to the camera have much smaller depth deltas and their weights will all be very uniform, whereas samples far away from the camera will be weights that change very quickly, causing aliasing. Dividing the weight by the distance ensures that near and far samples will be affected similarly in screen space. This helps the edge-detection/sharpening appear uniform across different view distances.&#xD;&#xA;&#xD;&#xA;For problems like this, it can be handy to convert the constants (1.25, 0.011 etc) to variables, and then playing around with them to see how it affects the image.&#xD;&#xA;&#xD;&#xA;It can also be helpful to visualize the equation in desmos or similar, here's a quick example I made for this equation: https://www.desmos.com/calculator/rwsszxin7l&#xD;&#xA;&#xD;&#xA;I hope this info helps!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37985" PostHistoryTypeId="5" PostId="12889" RevisionGUID="cceccbba-9ad7-4a55-8a9b-778f9c6eca27" CreationDate="2022-08-07T11:24:49.000" UserId="18740" Comment="added 51 characters in body" Text="This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37986" PostHistoryTypeId="2" PostId="12891" RevisionGUID="c9a01282-c8b3-43e2-a5bc-04746e99f086" CreationDate="2022-08-07T14:23:09.327" UserId="18741" Text="I was hoping someone could check my understanding.&#xD;&#xA;&#xD;&#xA;I've got a pipeline that does some path tracing, and then draws some debugging rays using standard rasterization. I'm trying to get depth to work between the two.&#xD;&#xA;&#xD;&#xA;In my path tracer I have `t`, the distance from the camera position to the closest surface intersection or the ray in world space. I want this `t` to be converted to something that can be directly used by the standard OpenGL/glsl depth buffer. Am I correct in thinking that using the z buffer formulae from [Wikipedia][1] directly on my `t` should work?&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float far = 10000.0;&#xD;&#xA;float near = 0.1;&#xD;&#xA;&#xD;&#xA;// From Wikipedia&#xD;&#xA;float depth_value = (far + near) / (far - near) + ((1.0 / t)*((-2.0 * far * near)/(far - near)));&#xD;&#xA;&#xD;&#xA;depth_value = (depth_value + 1.0) / 2.0; // I did this to convert from (-1,1) to (0,1)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This gives me something close to working, but not quite correct. However, if my logic is correct, my issue could lie elsewhere in my code. For the record, I'm using OpenGL with `gl_FragDepth` at the end of the pathtracing step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Z-buffering#Mathematics" ContentLicense="CC BY-SA 4.0" />
  <row Id="37988" PostHistoryTypeId="1" PostId="12891" RevisionGUID="c9a01282-c8b3-43e2-a5bc-04746e99f086" CreationDate="2022-08-07T14:23:09.327" UserId="18741" Text="How do I convert pathtraced distance to value that is usable by OpenGL's depthbuffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="37989" PostHistoryTypeId="3" PostId="12891" RevisionGUID="c9a01282-c8b3-43e2-a5bc-04746e99f086" CreationDate="2022-08-07T14:23:09.327" UserId="18741" Text="|opengl|pathtracing|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="37990" PostHistoryTypeId="2" PostId="12892" RevisionGUID="2c0d39e8-5ed5-49b5-8871-89db5c168a56" CreationDate="2022-08-07T15:44:22.117" UserId="18742" Text="There's a subtle difference between depth and what your t variable is (normally referred to as distance). Depth is distance along the camera z direction (=view direction), while t is euclidean distance. You need to first calculate the distance along the z direction, this is&#xD;&#xA;&#xD;&#xA;    rayOrigin.z + rayDirection.z * t&#xD;&#xA;&#xD;&#xA;and then apply the formula you found" ContentLicense="CC BY-SA 4.0" />
  <row Id="37992" PostHistoryTypeId="5" PostId="12892" RevisionGUID="4852646d-775d-481f-b038-4be75ec3753e" CreationDate="2022-08-07T15:47:19.177" UserId="18742" Comment="added 95 characters in body" Text="There's a subtle difference between depth and what your t variable is (normally referred to as distance). Depth is distance along the camera z direction (=view direction), while t is euclidean distance. You need to first calculate the distance along the z direction, this is&#xD;&#xA;&#xD;&#xA;    rayOrigin.z + rayDirection.z * t&#xD;&#xA;&#xD;&#xA;(rayOrigin and rayDirection being the origin and direction of the ray in **view coordinates**) and then apply the formula you found" ContentLicense="CC BY-SA 4.0" />
  <row Id="37993" PostHistoryTypeId="5" PostId="12892" RevisionGUID="65690952-9d66-4f48-b51c-6c102389990b" CreationDate="2022-08-07T15:48:10.723" UserId="18742" Comment="added 141 characters in body" Text="There's a subtle difference between depth and what your t variable is (normally referred to as distance). Depth is distance along the camera z direction (=view direction), while t is euclidean distance. You need to first calculate the distance along the z direction, this is&#xD;&#xA;&#xD;&#xA;    rayOrigin.z + rayDirection.z * t&#xD;&#xA;&#xD;&#xA;(rayOrigin and rayDirection being the origin and direction of the ray in **view coordinates**) and then apply the formula you found.&#xD;&#xA;&#xD;&#xA;If you only have your ray parameters in world space, you will need to calculate the full hit position and multiply it by a view matrix. " ContentLicense="CC BY-SA 4.0" />
  <row Id="37994" PostHistoryTypeId="5" PostId="12889" RevisionGUID="3ce204fe-8102-47c1-93c9-3c2ef8d8d035" CreationDate="2022-08-07T16:45:24.230" UserId="18740" Comment="added 134 characters in body" Text="(Note: I'm trying to go here *without edge-detection or vector-ization algos*, for merely a smoother-than-jaggy B/W thresholding.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37995" PostHistoryTypeId="5" PostId="12889" RevisionGUID="6659acfb-4fc0-40e0-909d-7f913aaf5f2e" CreationDate="2022-08-07T17:28:17.620" UserId="18740" Comment="added 7 characters in body" Text="(Note: I'm trying to go here *without edge-detection or vector-ization algos*, for merely a smoother-than-jaggy B/W thresholding.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be *either* some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), *or* perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37996" PostHistoryTypeId="5" PostId="12889" RevisionGUID="c5c40903-353c-4141-b551-5c94743686f6" CreationDate="2022-08-07T17:28:46.480" UserId="18740" Comment="added 4 characters in body" Text="(Note: I'm trying to go here *without edge-detection or vector-ization algos*, for merely a smoother-than-jaggy B/W thresholding.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception and lo-res inputs), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37997" PostHistoryTypeId="5" PostId="12889" RevisionGUID="38ef957e-ce65-4be7-b0f4-deda6c5ea1db" CreationDate="2022-08-07T17:29:22.297" UserId="18740" Comment="deleted 18 characters in body" Text="(Note: I'm trying to go here *without edge-detection or vector-ization algos*, for merely a smoother-than-jaggy B/W thresholding.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/DC5ks.png&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!" ContentLicense="CC BY-SA 4.0" />
  <row Id="37998" PostHistoryTypeId="5" PostId="12889" RevisionGUID="abfddca0-7841-4716-af77-befd03e46082" CreationDate="2022-08-08T04:34:04.113" UserId="18740" Comment="added 130 characters in body; edited title" Text="(Note: I'm trying to go here *[without][1] edge-detection or vector-ization algos*, for merely a smoother-than-jaggy B/W thresholding.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise.&#xD;&#xA;&#xD;&#xA;Rephrasing the problem, assuming a grayscaled input image (again, not a necessity even perhaps), we want to &quot;turn blacks-smoothly-fading-into-grays into the-same-blacks-smoothly-fading-into-#FFFFFF&quot;.&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="37999" PostHistoryTypeId="4" PostId="12889" RevisionGUID="abfddca0-7841-4716-af77-befd03e46082" CreationDate="2022-08-08T04:34:04.113" UserId="18740" Comment="added 130 characters in body; edited title" Text="Turning colorized comic-art into uncolorized monochrome (line-art-inks-only B&amp;W), not just very-light-grayscale" ContentLicense="CC BY-SA 4.0" />
  <row Id="38000" PostHistoryTypeId="50" PostId="9549" RevisionGUID="73842792-ae54-494a-be5c-032a8fc12395" CreationDate="2022-08-08T15:04:30.413" UserId="-1" />
  <row Id="38001" PostHistoryTypeId="50" PostId="2516" RevisionGUID="84c8e981-3748-466c-b170-dbf261f62ef9" CreationDate="2022-08-08T17:02:15.280" UserId="-1" />
  <row Id="38002" PostHistoryTypeId="5" PostId="12889" RevisionGUID="56d17d7e-b5da-4307-a4bf-128c56056cb2" CreationDate="2022-08-08T19:27:21.800" UserId="18740" Comment="added 59 characters in body" Text="(Note: I'm trying to go here *[without][1] edge-detection or vector-ization or binarization algos*, for &quot;merely&quot; a smoother-than-jaggy B/W thresholding.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise. This goes for hard-coded thresholds or auto-thresholding-computed ones. What's really needed at these low resolutions is to fade as smoothly into white from the line-blacks as they originally fade into colorization (or grayscaled, into grays).&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38003" PostHistoryTypeId="5" PostId="12889" RevisionGUID="ab7f29fe-258d-471e-a705-e9d5c44f7be5" CreationDate="2022-08-08T19:29:04.887" UserId="18740" Comment="added 70 characters in body" Text="(Note: I'm trying to go here *[without][1] edge-detection or vector-ization or binarization algos*, for &quot;merely&quot; a smoother alternative to any &amp; all always-jaggy B/W thresholding (binarization) approaches you'll ever find.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise. This goes for hard-coded thresholds or auto-thresholding-computed ones. What's really needed at these low resolutions is to fade as smoothly into white from the line-blacks as they originally fade into colorization (or grayscaled, into grays).&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38004" PostHistoryTypeId="5" PostId="12889" RevisionGUID="de16f99a-4938-4680-af06-91591a3610f7" CreationDate="2022-08-08T19:31:50.413" UserId="18740" Comment="added 143 characters in body" Text="(Note: I'm trying to go here *[without][1] edge-detection or vector-ization or binarization algos*, for &quot;merely&quot; a smoother alternative to any &amp; all always-jaggy B/W thresholding (binarization) approaches you'll ever find.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise. This goes for hard-coded thresholds or auto-thresholding-computed ones (unless there's one I haven't encountered yet that's especially geared to this scenario — most of them are for text-scans/photos/paintings).&#xD;&#xA;&#xD;&#xA;What's really needed at these low resolutions is to fade as smoothly into white from the line-blacks as they originally fade into colorization (or grayscaled, into grays).&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38005" PostHistoryTypeId="5" PostId="12889" RevisionGUID="fa2d9695-0566-4fa6-81b5-c89483c3c6a0" CreationDate="2022-08-08T19:32:45.357" UserId="18740" Comment="added 4 characters in body" Text="(Note: I'm trying to go here *[without][1] edge-detection or vector-ization or binarization algos*, for &quot;merely&quot; a smoother alternative to any &amp; all always-jaggy B/W thresholding (binarization) approaches you'll ever find.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise. This goes for hard-coded thresholds or auto-thresholding-computed ones (unless there's one I haven't encountered yet that's especially geared to this scenario — most of them are for lo-fi text-scans or photographs).&#xD;&#xA;&#xD;&#xA;What's really needed at these low resolutions is to fade as smoothly into white from the line-blacks as they originally fade into colorization (or grayscaled, into grays).&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38006" PostHistoryTypeId="5" PostId="12884" RevisionGUID="54cc4aa9-77aa-437e-8878-4f1bd85c91b8" CreationDate="2022-08-08T20:38:32.033" UserId="18729" Comment="added 225 characters in body" Text="Lets say I have a rectangle with known coordinates in 3D scene, and I'm projecting it using pin point camera to the plane (screen).&#xD;&#xA;&#xD;&#xA;You can imagine it deforms on the screen per camera transformation and projection.&#xD;&#xA;&#xD;&#xA;And I know the resulting project 2D coordinates on the screen.&#xD;&#xA;&#xD;&#xA;I wonder if I can recover camera parameters (projection matrix, transformation, field of view, distance from the screen and from the object) from known coordinates of the rectangle in 3d and know coordinates/results for 2d projection.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;PS: if this task has infinite many solutions or unsolvable - what a minimum extra information I could gather or add to actually solve it ?&#xD;&#xA;&#xD;&#xA;UPDATE (08/08/22):&#xD;&#xA;Found this lecture notes that seems to describe similar problem and call it Camera Calibration - https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/EPSRC_SSAZ/node5.html#SECTION00050000000000000000" ContentLicense="CC BY-SA 4.0" />
  <row Id="38007" PostHistoryTypeId="2" PostId="12893" RevisionGUID="5f9a4802-e8d3-4af8-9b40-ff9d2c2a9773" CreationDate="2022-08-08T22:30:02.337" UserId="11058" Text="Say I have a couple of meshes that I want to reupload to GPU for each frame. I can do this by generating a single array from all the meshes on CPU and then uploading to GPU (ex with `glBufferData` with OpenGL). I can regenerate the array and reupload for each frame.&#xD;&#xA;&#xD;&#xA;This is something I've done before I became aware of buffer streaming. The way I understand buffer streaming is we first allocate a large enough vertex buffer, then we upload each mesh to it (ex with `glBufferSubData` with OpenGL) while keeping track of offset for each added mesh inside the buffer.&#xD;&#xA;&#xD;&#xA;With streaming there are issues like implicit synchronization. We can avoid this problem by different means. But why not just collect all data on CPU instead? Is this because doing this would mean a performance hit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38009" PostHistoryTypeId="1" PostId="12893" RevisionGUID="5f9a4802-e8d3-4af8-9b40-ff9d2c2a9773" CreationDate="2022-08-08T22:30:02.337" UserId="11058" Text="Why use buffer streaming instead of collecting data on CPU and uploading to GPU all at once" ContentLicense="CC BY-SA 4.0" />
  <row Id="38010" PostHistoryTypeId="3" PostId="12893" RevisionGUID="5f9a4802-e8d3-4af8-9b40-ff9d2c2a9773" CreationDate="2022-08-08T22:30:02.337" UserId="11058" Text="|gpu|vertex-buffer-object|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38011" PostHistoryTypeId="5" PostId="12884" RevisionGUID="5e25acd5-a30d-4351-8ff9-60d3376f9a53" CreationDate="2022-08-08T22:30:19.210" UserId="18729" Comment="added 349 characters in body" Text="Lets say I have a rectangle with known coordinates in 3D scene, and I'm projecting it using pin point camera to the plane (screen).&#xD;&#xA;&#xD;&#xA;You can imagine it deforms on the screen per camera transformation and projection.&#xD;&#xA;&#xD;&#xA;And I know the resulting project 2D coordinates on the screen.&#xD;&#xA;&#xD;&#xA;I wonder if I can recover camera parameters (projection matrix, transformation, field of view, distance from the screen and from the object) from known coordinates of the rectangle in 3d and know coordinates/results for 2d projection.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;PS: if this task has infinite many solutions or unsolvable - what a minimum extra information I could gather or add to actually solve it ?&#xD;&#xA;&#xD;&#xA;UPDATE (08/08/22):&#xD;&#xA;Found this lecture notes that seems to describe similar problem and call it Camera Calibration - https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/EPSRC_SSAZ/node5.html#SECTION00050000000000000000&#xD;&#xA;&#xD;&#xA;Similar questions was discussed at StackOverflow:&#xD;&#xA;https://stackoverflow.com/questions/64613719/recover-a-projection-matrix-with-known-3d-and-2d-points&#xD;&#xA;&#xD;&#xA;And here is module that seems to solve this problem - https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html&#xD;&#xA;&#xD;&#xA;I'll try it out, for now would consider this to be this question to be solved." ContentLicense="CC BY-SA 4.0" />
  <row Id="38012" PostHistoryTypeId="5" PostId="12884" RevisionGUID="48e3e1bc-3bc9-45ce-87b9-9bc512bf3976" CreationDate="2022-08-08T22:31:40.337" UserId="18729" Comment="added 1 character in body" Text="Lets say I have a rectangle with known coordinates in 3D scene, and I'm projecting it using pin point camera to the plane (screen).&#xD;&#xA;&#xD;&#xA;You can imagine it deforms on the screen per camera transformation and projection.&#xD;&#xA;&#xD;&#xA;And I know the resulting project 2D coordinates on the screen.&#xD;&#xA;&#xD;&#xA;I wonder if I can recover camera parameters (projection matrix, transformation, field of view, distance from the screen and from the object) from known coordinates of the rectangle in 3d and know coordinates/results for 2d projection.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;PS: if this task has infinite many solutions or unsolvable - what a minimum extra information I could gather or add to actually solve it ?&#xD;&#xA;&#xD;&#xA;UPDATE (08/08/22):&#xD;&#xA;Found this lecture notes that seems to describe similar problem and call it Camera Calibration - https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/EPSRC_SSAZ/node5.html#SECTION00050000000000000000&#xD;&#xA;&#xD;&#xA;Similar questions were discussed at StackOverflow:&#xD;&#xA;https://stackoverflow.com/questions/64613719/recover-a-projection-matrix-with-known-3d-and-2d-points&#xD;&#xA;&#xD;&#xA;And here is module that seems to solve this problem - https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html&#xD;&#xA;&#xD;&#xA;I'll try it out, for now would consider this to be this question to be solved." ContentLicense="CC BY-SA 4.0" />
  <row Id="38013" PostHistoryTypeId="5" PostId="12884" RevisionGUID="1d25e21b-fe3b-423b-a5b5-f07499b56558" CreationDate="2022-08-08T22:33:18.713" UserId="18729" Comment="deleted 9 characters in body" Text="Lets say I have a rectangle with known coordinates in 3D scene, and I'm projecting it using pin point camera to the plane (screen).&#xD;&#xA;&#xD;&#xA;You can imagine it deforms on the screen per camera transformation and projection.&#xD;&#xA;&#xD;&#xA;And I know the resulting project 2D coordinates on the screen.&#xD;&#xA;&#xD;&#xA;I wonder if I can recover camera parameters (projection matrix, transformation, field of view, distance from the screen and from the object) from known coordinates of the rectangle in 3d and know coordinates/results for 2d projection.&#xD;&#xA;&#xD;&#xA;Thank you.&#xD;&#xA;&#xD;&#xA;PS: if this task has infinite many solutions or unsolvable - what a minimum extra information I could gather or add to actually solve it ?&#xD;&#xA;&#xD;&#xA;UPDATE (08/08/22):&#xD;&#xA;Found this lecture notes that seems to describe similar problem and call it Camera Calibration - https://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/EPSRC_SSAZ/node5.html#SECTION00050000000000000000&#xD;&#xA;&#xD;&#xA;Similar questions were discussed at StackOverflow:&#xD;&#xA;https://stackoverflow.com/questions/64613719/recover-a-projection-matrix-with-known-3d-and-2d-points&#xD;&#xA;&#xD;&#xA;And here is module that seems to solve this problem - https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html&#xD;&#xA;&#xD;&#xA;I'll try it out, for now would consider this to be a solved question." ContentLicense="CC BY-SA 4.0" />
  <row Id="38014" PostHistoryTypeId="5" PostId="12893" RevisionGUID="233588ef-47c2-4a86-b851-407a6151200e" CreationDate="2022-08-08T22:35:30.337" UserId="11058" Comment="added 63 characters in body" Text="Say I have a couple of meshes that I want to reupload to GPU for each frame. I can do this by generating a single array from all the meshes on CPU and then uploading to GPU (ex with `glBufferData` with OpenGL). I can regenerate the array and reupload for each frame.&#xD;&#xA;&#xD;&#xA;This is something I've done before I became aware of buffer streaming. The way I understand buffer streaming is we first allocate a large enough vertex buffer, then we upload each mesh to it (ex with `glBufferSubData` with OpenGL) while keeping track of offset for each added mesh inside the buffer.&#xD;&#xA;&#xD;&#xA;With streaming there are issues like implicit synchronization. We can avoid this problem by different means. But why not just do the work on CPU instead, by collecting all the data into one array and uploading at the end of the frame? Would it be a considerable performance hit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38015" PostHistoryTypeId="5" PostId="12893" RevisionGUID="de837229-8022-4772-8f37-ddaa2ab7e6cc" CreationDate="2022-08-08T22:42:47.553" UserId="11058" Comment="added 27 characters in body" Text="Say I have a couple of meshes that I want to reupload to GPU for each frame. I can do this by generating a single array from all the meshes on CPU and then uploading to GPU (ex with `glBufferData` with OpenGL). I can regenerate the array and reupload for each frame.&#xD;&#xA;&#xD;&#xA;This is something I've done before I became aware of buffer streaming. The way I understand buffer streaming is we first allocate a large enough vertex buffer, then we upload each mesh to it (ex with `glBufferSubData` with OpenGL) while keeping track of offset for each added mesh inside the buffer. We do this for each frame.&#xD;&#xA;&#xD;&#xA;With streaming there are issues like implicit synchronization. We can avoid this problem by different means. But why not just do the work on CPU instead, by collecting all the data into one array and uploading at the end of the frame? Would it be a considerable performance hit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38016" PostHistoryTypeId="5" PostId="12889" RevisionGUID="90f6df0a-d4fb-4882-bda8-800054d47084" CreationDate="2022-08-09T08:45:44.933" UserId="18740" Comment="added 361 characters in body" Text="(Note: I'm trying to go here *[without][1] edge-detection or vector-ization or binarization algos*, for &quot;merely&quot; a smoother alternative to any &amp; all always-jaggy B/W thresholding (binarization) approaches you'll ever find.)&#xD;&#xA;&#xD;&#xA;I'm trying to figure out how to go about removing the &quot;colorization&quot; of drawn comic/cartoon/manga/etc. art inputs where the black-ink strokes (&quot;the line-art&quot;) are to be retained against (near-perfectly-)white &quot;background&quot; — but also in a smooth non-jagged manner so there'll be some retaining/graying of the &quot;fade tones&quot; from the ink-blacks to the background (formerly colored, now white).&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `x` (for turning all-grays-above-`x` into `#FF`, keeping all-below-`x` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `x=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `x`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise. This goes for hard-coded thresholds or auto-thresholding-computed ones (unless there's one I haven't encountered yet that's especially geared to this scenario — most of them are for lo-fi text-scans or photographs).&#xD;&#xA;&#xD;&#xA;What's really needed at these low resolutions is to fade as smoothly into white from the line-blacks as they originally fade into colorization (or grayscaled, into grays).&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38017" PostHistoryTypeId="5" PostId="12889" RevisionGUID="a6e543c7-9393-4c66-96ca-6456ac623637" CreationDate="2022-08-09T08:55:12.563" UserId="18740" Comment="edited body" Text="I'm trying to figure out how to go about removing the &quot;colorization&quot; of comic/cartoon/manga/etc drawn-art inputs where the black-ink strokes (&quot;the line-art&quot;) are to be retained against (near-perfectly-)white &quot;background&quot; — but also in a smooth non-jagged manner so there'll be some retaining/graying of the &quot;fade tones&quot; from the ink-blacks to the background (formerly colored, now white).&#xD;&#xA;&#xD;&#xA;(Note: I'm trying to go here *[without][1] edge-detection or vector-ization or binarization algos*, for &quot;merely&quot; a smoother alternative to any &amp; all always-jaggy B/W thresholding (binarization) approaches you'll ever find.)&#xD;&#xA;&#xD;&#xA;This colorized input, for example, sports quite dark colorization tones that would still have to turn (near-)`#FF` for the removing-colorization-but-preserving-the-black-inks use case — despite (in grayscale) being quite close to the original-black-inks-to-be-fully-preserved in the (seemingly ca.) `#00..#36` range.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The problem is likely simplified (though that's just assumption on my part, not a necessary requirement) by first generating a light-greyscale (max-decomposition ie. `gray=max(r,g,b)`) version to work with:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Now any given hard-coded threshold cutoff value `t` (for turning all-grays-above-`t` into `#FF`, keeping all-below-`t` as they are) will not &quot;work&quot; to produce a smooth outcome, to wit for `t=#36`:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;**No matter** one's choice of cutoff threshold `t`, the result will naturally **always** be jaggy and impoverished (just in different places), with some lines too-severely-thickened, others too harshly thinned or lost, plus dither noise. This goes for hard-coded thresholds or auto-thresholding-computed ones (unless there's one I haven't encountered yet that's especially geared to this scenario — most of them are for lo-fi text-scans or photographs).&#xD;&#xA;&#xD;&#xA;What's really needed at these low resolutions is to fade as smoothly into white from the line-blacks as they originally fade into colorization (or grayscaled, into grays).&#xD;&#xA;&#xD;&#xA;I guess that there should be **either** some near-perfectly-suited *Curve* (`some 0..1 -&gt; another 0..1` I haven't yet found) that would solve this &quot;good enough&quot; (for the human visual perception), **or** perhaps some other papers/algos/research/gfx-techniques tackling this very use-case (albeit in jargon I wouldn't know to include in searches)... thanks for any ideas and pointers!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://aaronhertzmann.com/2020/04/19/lines-as-edges.html#problem-5-edge-detection-is-not-a-line-drawing-algorithm&#xD;&#xA;  [2]: https://i.stack.imgur.com/ALkuc.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/sd5lE.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/DC5ks.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38018" PostHistoryTypeId="5" PostId="12878" RevisionGUID="7aad8081-46b6-454f-b602-6c504646c9e0" CreationDate="2022-08-09T12:18:25.730" UserId="13273" Comment="deleted 44 characters in body" Text="I want to improve my shadow mapping depth precision by getting the minimum and maximum depth value within my shadow map. When having both values I would convert the depth map to convolution shadow map basis functions and encode the values to 8bit each, which looses precision a lot, in case the depth span is high. &#xD;&#xA;&#xD;&#xA;Right now I render the scenario depth values into a R32F texture. A second shader checks for each pixel, if it is the min / max depth within the shadowmap by using SSBO and AtomicMax / AtomicMin.&#xD;&#xA;Then the next shader converts the depth values with respect to the min/max depth into the basis functions of convolution shadow mapping.&#xD;&#xA;&#xD;&#xA;Is there a way to get the minimum / maximum depth during the render pass of the scenario? If this is the case, I could skip the second shader.&#xD;&#xA;&#xD;&#xA;During the geometry rendering within the fragment shader I can get the depth value and use the AtomicMin / AtomixMax function. But when doing so, there can be the case (it happens very often) that fragments will be executed, which are behind other faces. so the max distance will be wrong at the end, which decreases the shadow map precision.&#xD;&#xA;&#xD;&#xA;I found the `layout(early_fragment_tests) in;` specification. But I am not sure if this will solve the problem. Do you have other ideas?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38019" PostHistoryTypeId="2" PostId="12894" RevisionGUID="c79af8ce-4ea9-4710-be8d-3030e02a9869" CreationDate="2022-08-09T14:01:06.167" UserId="18529" Text="I'm using queries to profile my Direct3D renderer.&#xD;&#xA;&#xD;&#xA;What precision and consistency should I expect from them?&#xD;&#xA;&#xD;&#xA;Those are some values for a full-screen draw I do each frame as an example:&#xD;&#xA; ````&#xD;&#xA;|Full-Screen shader: 714.16 us&#xD;&#xA;|Full-Screen shader: 709.72 us&#xD;&#xA;|Full-Screen shader: 706.44 us&#xD;&#xA;|Full-Screen shader: 707.44 us&#xD;&#xA;|Full-Screen shader: 710.76 us&#xD;&#xA;|Full-Screen shader: 707.76 us&#xD;&#xA;|Full-Screen shader: 706.48 us&#xD;&#xA;|Full-Screen shader: 712.88 us&#xD;&#xA;|Full-Screen shader: 715.36 us&#xD;&#xA;|Full-Screen shader: 704.72 us&#xD;&#xA;|Full-Screen shader: 708.32 us&#xD;&#xA;|Full-Screen shader: 702.32 us&#xD;&#xA;|Full-Screen shader: 707.8 us&#xD;&#xA;|Full-Screen shader: 720.6 us&#xD;&#xA;|Full-Screen shader: 711.12 us&#xD;&#xA;|Full-Screen shader: 715.36 us&#xD;&#xA;|Full-Screen shader: 713.84 us&#xD;&#xA;|Full-Screen shader: 716.52 us&#xD;&#xA;|Full-Screen shader: 711.52 us&#xD;&#xA;|Full-Screen shader: 1228.57 us&#xD;&#xA;|Full-Screen shader: 1202.5 us&#xD;&#xA;|Full-Screen shader: 706.44 us&#xD;&#xA;|Full-Screen shader: 712.68 us&#xD;&#xA;|Full-Screen shader: 715.32 us&#xD;&#xA; &#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;The shader used while profiling has nothing parametrized with time and while it contains branching to early-exit when certain conditions are met, the scene was &quot;static&quot; while profiling.&#xD;&#xA;&#xD;&#xA;Is it the expected behavior to have so much variance?&#xD;&#xA;&#xD;&#xA;Or is it an indicator that something is wrong with my code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38021" PostHistoryTypeId="1" PostId="12894" RevisionGUID="c79af8ce-4ea9-4710-be8d-3030e02a9869" CreationDate="2022-08-09T14:01:06.167" UserId="18529" Text="D3D11 Gpu profiling with queries accuracy" ContentLicense="CC BY-SA 4.0" />
  <row Id="38022" PostHistoryTypeId="3" PostId="12894" RevisionGUID="c79af8ce-4ea9-4710-be8d-3030e02a9869" CreationDate="2022-08-09T14:01:06.167" UserId="18529" Text="|directx11|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38023" PostHistoryTypeId="50" PostId="10748" RevisionGUID="7392d8f1-e16c-4dc4-8b04-2ab473c33469" CreationDate="2022-08-09T17:07:45.660" UserId="-1" />
  <row Id="38024" PostHistoryTypeId="2" PostId="12895" RevisionGUID="d3e2e5ca-6545-4d01-95e4-a6ff05931454" CreationDate="2022-08-10T02:56:11.587" UserId="48" Text="It looks like a normal amount of variance to me. Profiling results naturally fluctuate because there can be nondeterministic cache effects, changes in how the work is scheduled, there can be other applications and the OS submitting work at the same time as yours, etc. This applies to both CPU and GPU.&#xD;&#xA;&#xD;&#xA;There can also be changes in clock rate that can screw up profiling data, though that causes larger and longer-lasting changes, not this kind of micro-variance. (The two samples where it jumped up to over 1200 us could be due to a clock speed change, for instance; or they could be due to some other work being on the GPU at the same time.)&#xD;&#xA;&#xD;&#xA;It's common to average the measurements over some number of frames, or even do more complicated statistics on them, to account for this." ContentLicense="CC BY-SA 4.0" />
  <row Id="38026" PostHistoryTypeId="2" PostId="12896" RevisionGUID="a5580d5b-14dc-4d59-8480-2dc28450f698" CreationDate="2022-08-10T06:56:50.757" UserId="18634" Text="I am supposed to use bilateral filter to denoise my image rendered with Vulkan. I wonder how I should implement the method. Should I add the rendered image to another frag shader as a texture and denoise the image there before drawing it on the screen? or are there simpler methods? Should I do it through CPU after rendering instead of GPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38028" PostHistoryTypeId="1" PostId="12896" RevisionGUID="a5580d5b-14dc-4d59-8480-2dc28450f698" CreationDate="2022-08-10T06:56:50.757" UserId="18634" Text="bilateral filter in vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="38029" PostHistoryTypeId="3" PostId="12896" RevisionGUID="a5580d5b-14dc-4d59-8480-2dc28450f698" CreationDate="2022-08-10T06:56:50.757" UserId="18634" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38030" PostHistoryTypeId="50" PostId="2146" RevisionGUID="1991e7d0-d91f-4b79-8a50-7ff2ecb25032" CreationDate="2022-08-11T11:01:05.107" UserId="-1" />
  <row Id="38031" PostHistoryTypeId="50" PostId="11048" RevisionGUID="d412d9bf-d8fa-4adc-bcf4-bd096f8cd26d" CreationDate="2022-08-11T17:04:40.493" UserId="-1" />
  <row Id="38032" PostHistoryTypeId="50" PostId="8886" RevisionGUID="3513d693-f6ac-43f5-bcb5-fb601b28868f" CreationDate="2022-08-11T18:05:20.540" UserId="-1" />
  <row Id="38033" PostHistoryTypeId="50" PostId="11049" RevisionGUID="f25730e4-3435-4af7-bb0a-0b41345cc088" CreationDate="2022-08-11T19:03:50.360" UserId="-1" />
  <row Id="38034" PostHistoryTypeId="2" PostId="12897" RevisionGUID="dcbb9871-b45f-47e0-b33c-1a84d56895fd" CreationDate="2022-08-11T21:10:24.943" UserId="15909" Text="I have been reading the book &quot;real-time rendering 4th edition&quot; and came across this Directional-hemispherical reflectance equation.&#xD;&#xA;&#xD;&#xA;[![Directional-hemispherical reflectance equation][1]][1]&#xD;&#xA;&#xD;&#xA;It can be used to measure to what degree a BRDF is energy conserving. According to my understanding what it does is that for a given light direction l we evaluate the BRDF for this l and every possible view direction in the upper hemisphere oriented along my surface normal n. In other words we capture the reflected light from every possible view sum that and see if the result we have is less than or equal to 1 (assuming a fixed radiance of 1). If it is then our BRDF is energy conserving as the outgoing energy must be less than or equal to the incoming energy (not counting glowing surfaces). What I don't get is the role of the NdotV in this equation I know that it represents the angle between the normal surface and the view direction but what I don't get is how that affects the amount of reflected light why having an angle of 90 degrees evaluates to 0 reflected light in this view direction.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PEdQb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38036" PostHistoryTypeId="1" PostId="12897" RevisionGUID="dcbb9871-b45f-47e0-b33c-1a84d56895fd" CreationDate="2022-08-11T21:10:24.943" UserId="15909" Text="The purpose of NdotV in the directional-hemispherical reflectance equation in the book &quot;Real-time rendering book&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38037" PostHistoryTypeId="3" PostId="12897" RevisionGUID="dcbb9871-b45f-47e0-b33c-1a84d56895fd" CreationDate="2022-08-11T21:10:24.943" UserId="15909" Text="|brdf|pbr|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38038" PostHistoryTypeId="5" PostId="8761" RevisionGUID="505b3224-ab94-4991-aad3-a64bb397e5d2" CreationDate="2022-08-12T11:23:49.360" UserId="171" Comment="added 93 characters in body" Text="General-purpose programming language used widely in game development and CPU-intensive tasks." ContentLicense="CC BY-SA 4.0" />
  <row Id="38039" PostHistoryTypeId="24" PostId="8761" RevisionGUID="505b3224-ab94-4991-aad3-a64bb397e5d2" CreationDate="2022-08-12T11:23:49.360" Comment="Proposed by 171 approved by 13095 edit id of 583" ContentLicense="CC BY-SA 4.0" />
  <row Id="38040" PostHistoryTypeId="2" PostId="12898" RevisionGUID="5414b162-8e2b-4b8e-87c0-b7569cb83761" CreationDate="2022-08-12T12:15:35.577" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38042" PostHistoryTypeId="1" PostId="12898" RevisionGUID="5414b162-8e2b-4b8e-87c0-b7569cb83761" CreationDate="2022-08-12T12:15:35.577" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38043" PostHistoryTypeId="2" PostId="12899" RevisionGUID="b09df811-db4c-4894-b30b-95460b65ac10" CreationDate="2022-08-12T12:15:35.577" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38045" PostHistoryTypeId="1" PostId="12899" RevisionGUID="b09df811-db4c-4894-b30b-95460b65ac10" CreationDate="2022-08-12T12:15:35.577" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38046" PostHistoryTypeId="2" PostId="12900" RevisionGUID="2d9d2b95-d09b-4034-834b-9b912e86c4d3" CreationDate="2022-08-12T13:44:57.970" UserId="6064" Text="Hi I want to generate a ray generation shader which traces rays inside a box frustum given by an Orthographic projection matrix(XMMatrixOrthographicLH) I use the following ray generation shader code:&#xD;&#xA;```&#xD;&#xA;struct RTConstants&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	matrix invproj;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct Simpleraypayload&#xD;&#xA;{&#xD;&#xA;	float3 outcol;&#xD;&#xA;};&#xD;&#xA;RWTexture2D&lt;float4&gt; outtex: register(u0);&#xD;&#xA;RaytracingAccelerationStructure basicas:register(t0);&#xD;&#xA;ConstantBuffer&lt;RTConstants&gt; rtconsts:register(b0);&#xD;&#xA;[shader(&quot;raygeneration&quot;)]&#xD;&#xA;void rgsmain()&#xD;&#xA;{&#xD;&#xA;Simpleraypayload payload;&#xD;&#xA;payload.outcol=float3(0.0f,0.0f,0.0f);&#xD;&#xA;RayDesc ray;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;ray.TMin=0.001f;&#xD;&#xA;ray.TMax=10.0f;&#xD;&#xA;ray.Direction=float3(0.0f,0.0f,-1.0f);&#xD;&#xA;	uint3 rayidx=DispatchRaysIndex();&#xD;&#xA;	uint3 raydims=DispatchRaysDimensions();&#xD;&#xA;	float2 clippointxy=rayidx.xy/float2(raydims.xy);&#xD;&#xA;	clippointxy=(clippointxy*2.0f)-float2(1.0f,1.0f);&#xD;&#xA;	float4 clippointnear=float4(clippointxy,0.0f,1.0f);&#xD;&#xA;	clippointnear=mul(rtconsts.invproj,clippointnear);clippointnear=clippointnear/clippointnear.w;&#xD;&#xA;	float4 clippointfar=float4(clippointxy,1.0f,1.0f);&#xD;&#xA;	clippointfar=mul(rtconsts.invproj,clippointfar);clippointfar=clippointfar/clippointfar.w;&#xD;&#xA;	ray.Origin=clippointnear.xyz;&#xD;&#xA;	ray.Direction=normalize(clippointfar.xyz-clippointnear.xyz);&#xD;&#xA;	TraceRay(basicas,RAY_FLAG_NONE,0xFF,0,0,0,ray,payload);&#xD;&#xA;	//flipping the output.&#xD;&#xA;	uint2 outindex=uint2(rayidx.x,raydims.y-rayidx.y);&#xD;&#xA;	&#xD;&#xA;	outtex[outindex]=float4(payload.outcol,1.0f);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;here &quot;invproj&quot; is the inverse of the ortho projection matrix for which we are trying to shootrays for.Am I right in using this rgs shader code for tracing all possible rays inside the frustum represented by the ortho matrix whose inverse I am using here?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="38048" PostHistoryTypeId="1" PostId="12900" RevisionGUID="2d9d2b95-d09b-4034-834b-9b912e86c4d3" CreationDate="2022-08-12T13:44:57.970" UserId="6064" Text="Am I creating my raygeneration shader correctly" ContentLicense="CC BY-SA 4.0" />
  <row Id="38049" PostHistoryTypeId="3" PostId="12900" RevisionGUID="2d9d2b95-d09b-4034-834b-9b912e86c4d3" CreationDate="2022-08-12T13:44:57.970" UserId="6064" Text="|raytracing|directx12|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38050" PostHistoryTypeId="5" PostId="12900" RevisionGUID="c1071165-146b-4412-a954-adc039fcf807" CreationDate="2022-08-12T15:12:14.653" UserId="6064" Comment="deleted 2 characters in body" Text="Hi I want to create a ray generation shader which traces rays inside a box frustum given by an Orthographic projection matrix(XMMatrixOrthographicLH) I use the following ray generation shader code:&#xD;&#xA;```&#xD;&#xA;struct RTConstants&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	matrix invproj;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct Simpleraypayload&#xD;&#xA;{&#xD;&#xA;	float3 outcol;&#xD;&#xA;};&#xD;&#xA;RWTexture2D&lt;float4&gt; outtex: register(u0);&#xD;&#xA;RaytracingAccelerationStructure basicas:register(t0);&#xD;&#xA;ConstantBuffer&lt;RTConstants&gt; rtconsts:register(b0);&#xD;&#xA;[shader(&quot;raygeneration&quot;)]&#xD;&#xA;void rgsmain()&#xD;&#xA;{&#xD;&#xA;Simpleraypayload payload;&#xD;&#xA;payload.outcol=float3(0.0f,0.0f,0.0f);&#xD;&#xA;RayDesc ray;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;ray.TMin=0.001f;&#xD;&#xA;ray.TMax=10.0f;&#xD;&#xA;ray.Direction=float3(0.0f,0.0f,-1.0f);&#xD;&#xA;	uint3 rayidx=DispatchRaysIndex();&#xD;&#xA;	uint3 raydims=DispatchRaysDimensions();&#xD;&#xA;	float2 clippointxy=rayidx.xy/float2(raydims.xy);&#xD;&#xA;	clippointxy=(clippointxy*2.0f)-float2(1.0f,1.0f);&#xD;&#xA;	float4 clippointnear=float4(clippointxy,0.0f,1.0f);&#xD;&#xA;	clippointnear=mul(rtconsts.invproj,clippointnear);clippointnear=clippointnear/clippointnear.w;&#xD;&#xA;	float4 clippointfar=float4(clippointxy,1.0f,1.0f);&#xD;&#xA;	clippointfar=mul(rtconsts.invproj,clippointfar);clippointfar=clippointfar/clippointfar.w;&#xD;&#xA;	ray.Origin=clippointnear.xyz;&#xD;&#xA;	ray.Direction=normalize(clippointfar.xyz-clippointnear.xyz);&#xD;&#xA;	TraceRay(basicas,RAY_FLAG_NONE,0xFF,0,0,0,ray,payload);&#xD;&#xA;	//flipping the output.&#xD;&#xA;	uint2 outindex=uint2(rayidx.x,raydims.y-rayidx.y);&#xD;&#xA;	&#xD;&#xA;	outtex[outindex]=float4(payload.outcol,1.0f);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;here &quot;invproj&quot; is the inverse of the ortho projection matrix for which we are trying to shootrays for.Am I right in using this rgs shader code for tracing all possible rays inside the frustum represented by the ortho matrix whose inverse I am using here?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="38054" PostHistoryTypeId="2" PostId="12901" RevisionGUID="8cb62fa9-c585-4f9b-aac2-66cda93532ba" CreationDate="2022-08-13T11:29:24.917" UserId="18765" Text="First, you are not exactly capturing &quot;reflected light from view direction&quot;. What you mean is called importance, and it is transported exactly the same way in the scene as radiance (Helmholtz reciprocity), but in the opposite direction (i.e. from camera to light source). &#xD;&#xA;&#xD;&#xA;Also note that for BRDF to be energy conserving, the equation must hold for every l.&#xD;&#xA;&#xD;&#xA;Due to the reciprocity, the equation can be also rewritten with l and v interchanged, which can be more practical (see white furnace test).&#xD;&#xA;&#xD;&#xA;The cosine of angle between a viewing direction and normal represents foreshortening, that is the reduction of area of the surface patch when projected into the viewing direction. " ContentLicense="CC BY-SA 4.0" />
  <row Id="38056" PostHistoryTypeId="5" PostId="12899" RevisionGUID="4c3eff12-20ef-4883-832f-577d1df934f5" CreationDate="2022-08-13T14:34:36.563" UserId="171" Comment="added 137 characters in body" Text="The knowledge of the numbers, formulas, shapes and quantities. In the computer graphics, almost exclusively linear algebra is being used." ContentLicense="CC BY-SA 4.0" />
  <row Id="38057" PostHistoryTypeId="24" PostId="12899" RevisionGUID="4c3eff12-20ef-4883-832f-577d1df934f5" CreationDate="2022-08-13T14:34:36.563" Comment="Proposed by 171 approved by 482 edit id of 584" ContentLicense="CC BY-SA 4.0" />
  <row Id="38058" PostHistoryTypeId="50" PostId="8695" RevisionGUID="24679449-8215-424d-b1f7-7ce185811541" CreationDate="2022-08-13T23:05:05.590" UserId="-1" />
  <row Id="38059" PostHistoryTypeId="5" PostId="12897" RevisionGUID="cef5abb3-0071-47d9-8459-f467b437c14a" CreationDate="2022-08-14T16:54:55.787" UserId="16241" Comment="Converted image to mathjax" Text="I have been reading the book &quot;real-time rendering 4th edition&quot; and came across this Directional-hemispherical reflectance equation.&#xD;&#xA;&#xD;&#xA;$$R(\mathbf{l}) = \int_{\mathbf{v}\in\Omega} f(\mathbf{l}, \mathbf{v})(\mathbf{n}\cdot\mathbf{v}) \,d\mathbf{v} $$&#xD;&#xA;&#xD;&#xA;It can be used to measure to what degree a BRDF is energy conserving. According to my understanding what it does is that for a given light direction l we evaluate the BRDF for this l and every possible view direction in the upper hemisphere oriented along my surface normal n. In other words we capture the reflected light from every possible view sum that and see if the result we have is less than or equal to 1 (assuming a fixed radiance of 1). If it is then our BRDF is energy conserving as the outgoing energy must be less than or equal to the incoming energy (not counting glowing surfaces). What I don't get is the role of the NdotV in this equation I know that it represents the angle between the normal surface and the view direction but what I don't get is how that affects the amount of reflected light why having an angle of 90 degrees evaluates to 0 reflected light in this view direction.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PEdQb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38060" PostHistoryTypeId="24" PostId="12897" RevisionGUID="cef5abb3-0071-47d9-8459-f467b437c14a" CreationDate="2022-08-14T16:54:55.787" Comment="Proposed by 16241 approved by 15909 edit id of 585" ContentLicense="CC BY-SA 4.0" />
  <row Id="38063" PostHistoryTypeId="50" PostId="5697" RevisionGUID="7a32fc56-a41a-4b71-a943-cf55ad96e0c4" CreationDate="2022-08-15T08:07:45.993" UserId="-1" />
  <row Id="38066" PostHistoryTypeId="2" PostId="12903" RevisionGUID="d2ec54ed-2e38-4f41-9a39-14b0e0a344e3" CreationDate="2022-08-15T22:19:04.603" UserId="18774" Text="I was debugging with RenderDoc an issue on an app based on Directx11 and 12 that draw screen space quads to perform various baking steps. These baking steps just render a quad in clip space without any transformation with two triangles and the interpolated texture coordinates (TEXCOORD0) of the 4 vertices (which are then used in the pixel shader) are set to (0, 0), (0, 1), (1, 1), (1, 0).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the pixel shader, checking these coordinates in the (0, 0) pixel, I expect to see the coordinates of the center of that pixel, but the values are slightly off:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;With a 17x17 viewport, I was expecting to see both (x, y) at 1 / (2 * 17) = (0.0294117647, 0.0294117647) but as you see I get (0.0294118524, 0.029411763). I see this on any coordinate and both in dx11 and 12. The error is small, but well above the float precision, is this normal or am I missing something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uv2v0.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/uWyxd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/2Wbz0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38068" PostHistoryTypeId="1" PostId="12903" RevisionGUID="d2ec54ed-2e38-4f41-9a39-14b0e0a344e3" CreationDate="2022-08-15T22:19:04.603" UserId="18774" Text="Imprecise TEXCOORD interpolation of a screen quad in DirectX" ContentLicense="CC BY-SA 4.0" />
  <row Id="38069" PostHistoryTypeId="3" PostId="12903" RevisionGUID="d2ec54ed-2e38-4f41-9a39-14b0e0a344e3" CreationDate="2022-08-15T22:19:04.603" UserId="18774" Text="|rendering|interpolation|directx12|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38070" PostHistoryTypeId="5" PostId="12903" RevisionGUID="d4418e19-4d37-4f41-b32a-f770d96ce0db" CreationDate="2022-08-15T22:21:24.580" UserId="18774" Comment="edited body" Text="I was debugging with RenderDoc an issue on an app based on Directx11 and 12 that draw screen space quads to perform various baking steps. These baking steps just render a quad in clip space without any transformation with two triangles and the interpolated texture coordinates (TEXCOORD0) of the 4 vertices (which are then used in the pixel shader) are set to (0, 0), (0, 1), (1, 1), (1, 0).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the pixel shader, checking these coordinates in the (0, 0) pixel, I expect to see the coordinates of the center of that pixel, but the values are slightly off:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;With a 17x17 viewport, I was expecting to see both (x, y) at 1 / (2 * 17) = (0.0294117647, 0.0294117647) but as you see I get (0.0294118524, 0.029411763). I see this on any coordinate and both in dx11 and 12. The error is small, but well above the float precision, is this normal or am I missing something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7xPJX.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/uWyxd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/2Wbz0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38071" PostHistoryTypeId="2" PostId="12904" RevisionGUID="603a1027-28ae-4ec3-be27-353cd00ecb3d" CreationDate="2022-08-16T15:57:45.453" UserId="9908" Text="Bilateral filter can be implemented as a fragment shader, once you have the full rendered image. &#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/4dfGDH&#xD;&#xA;&#xD;&#xA;The first option should be much faster than downloading the rendered frame to main memory and performing the calculations in CPU.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38073" PostHistoryTypeId="2" PostId="12905" RevisionGUID="b15860b6-03cc-4c37-93a8-441da7ccf189" CreationDate="2022-08-16T23:45:42.823" UserId="18373" Text="Here is my simple scanline-based quadrilateral rasterizer using pure integer arithmetic. I adapted the code from [this Stack Overflow answer](https://stackoverflow.com/questions/65460132/how-to-hide-invisible-elements-of-the-3d-drawing/65664918#65664918)&#xD;&#xA;```&#xD;&#xA;/* g++ trig.cpp -o trig -lSDL2 */&#xD;&#xA;&#xD;&#xA;#include &lt;cstdlib&gt;&#xD;&#xA;#include &lt;ctime&gt;&#xD;&#xA;&#xD;&#xA;#define SDL_MAIN_HANDLED&#xD;&#xA;#include &lt;SDL2/SDL.h&gt;&#xD;&#xA;&#xD;&#xA;#define SCREEN_HEIGHT 400&#xD;&#xA;#define SCREEN_WIDTH  600&#xD;&#xA;&#xD;&#xA;// TODO make an array of values to be interpolated&#xD;&#xA;// TODO 1/z buffer using something like this: 0xfffff / z where z is integer&#xD;&#xA;// TODO uv texture mapping&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;    int x, y, z;&#xD;&#xA;    uint8_t r, g, b;&#xD;&#xA;    int u, v;&#xD;&#xA;} Point2D;&#xD;&#xA;&#xD;&#xA;uint8_t pixels[SCREEN_HEIGHT * SCREEN_WIDTH * 4];&#xD;&#xA;&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] = r;&#xD;&#xA;    pixels[offset + 1] = g;&#xD;&#xA;    pixels[offset + 2] = b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int ContourX[SCREEN_HEIGHT][2]; // min X and max X for every horizontal line within the triangle&#xD;&#xA;int ContourR[SCREEN_HEIGHT][2]; // red value for every horizontal line&#xD;&#xA;int ContourG[SCREEN_HEIGHT][2]; // green value for every horizontal line&#xD;&#xA;int ContourB[SCREEN_HEIGHT][2]; // blue value for every horizontal line&#xD;&#xA;&#xD;&#xA;#define ABS(x) ((x &gt;= 0) ? x : -x)&#xD;&#xA;&#xD;&#xA;// Scans a side of a triangle setting min X and max X in ContourX[][] (same for ContourR, ContourG, and ContourB) using the Bresenham's&#xD;&#xA;void TriangleLine(const Point2D&amp; p0, const Point2D&amp; p1)&#xD;&#xA;{&#xD;&#xA;    // DDA variables&#xD;&#xA;    int kx, ky, kr, kg, kb; // step directions&#xD;&#xA;    int dx, dy, dr, dg, db; // abs delta&#xD;&#xA;    kx = 0; dx = p1.x - p0.x; if (dx &gt; 0) kx = 1; if (dx &lt; 0) { kx = -1; dx = -dx; }&#xD;&#xA;    ky = 0; dy = p1.y - p0.y; if (dy &gt; 0) ky = 1; if (dy &lt; 0) { ky = -1; dy = -dy; }&#xD;&#xA;    kr = 0; dr = p1.r - p0.r; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;    kg = 0; dg = p1.g - p0.g; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;    kb = 0; db = p1.b - p0.b; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;    int n;&#xD;&#xA;    n = dx;&#xD;&#xA;    if (n &lt; dy) n = dy;&#xD;&#xA;    if (n &lt; dr) n = dr;&#xD;&#xA;    if (n &lt; dg) n = dg;&#xD;&#xA;    if (n &lt; db) n = db;&#xD;&#xA;    if (!n) n = 1;&#xD;&#xA;&#xD;&#xA;    // target buffer according to ky direction&#xD;&#xA;    int target; if (ky &gt; 0) target = 0; else target = 1;&#xD;&#xA;&#xD;&#xA;    // integer DDA line start point&#xD;&#xA;    int x = p0.x;&#xD;&#xA;    int y = p0.y;&#xD;&#xA;    int r = p0.r;&#xD;&#xA;    int g = p0.g;&#xD;&#xA;    int b = p0.b;&#xD;&#xA;&#xD;&#xA;    // fix endpoints just to be sure (wrong division constants by +/-1 can cause that last point is missing)&#xD;&#xA;    ContourX[p0.y][target] = p0.x;&#xD;&#xA;    ContourR[p0.y][target] = p0.r;&#xD;&#xA;    ContourG[p0.y][target] = p0.g;&#xD;&#xA;    ContourB[p0.y][target] = p0.b;&#xD;&#xA;&#xD;&#xA;    ContourX[p1.y][target] = p1.x;&#xD;&#xA;    ContourR[p1.y][target] = p1.r;&#xD;&#xA;    ContourG[p1.y][target] = p1.g;&#xD;&#xA;    ContourB[p1.y][target] = p1.b;&#xD;&#xA;&#xD;&#xA;    int cx, cy, cr, cg, cb, i;&#xD;&#xA;    for (cx = cy = cr = cg = cb = n, i = 0; i &lt; n; ++i)&#xD;&#xA;    {&#xD;&#xA;        ContourX[y][target] = x;&#xD;&#xA;        ContourR[y][target] = r;&#xD;&#xA;        ContourG[y][target] = g;&#xD;&#xA;        ContourB[y][target] = b;&#xD;&#xA;&#xD;&#xA;        cx -= dx; if (cx &lt;= 0){ cx += n; x += kx; }&#xD;&#xA;        cy -= dy; if (cy &lt;= 0){ cy += n; y += ky; }&#xD;&#xA;        cr -= dr; if (cr &lt;= 0){ cr += n; r += kr; }&#xD;&#xA;        cg -= dg; if (cg &lt;= 0){ cg += n; g += kg; }&#xD;&#xA;        cb -= db; if (cb &lt;= 0){ cb += n; b += kb; }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void DrawTriangle(const Point2D&amp; p0, const Point2D&amp; p1, const Point2D&amp; p2)&#xD;&#xA;{&#xD;&#xA;    TriangleLine(p0, p1);&#xD;&#xA;    TriangleLine(p1, p2);&#xD;&#xA;    TriangleLine(p2, p0);&#xD;&#xA;&#xD;&#xA;    int y0, y1; // min and max y&#xD;&#xA;    y0 = p0.y; if (y0 &gt; p1.y) y0 = p1.y; if (y0 &gt; p2.y) y0 = p2.y;&#xD;&#xA;    y1 = p0.y; if (y1 &lt; p1.y) y1 = p1.y; if (y1 &lt; p2.y) y1 = p2.y;&#xD;&#xA;&#xD;&#xA;    int x0, r0, g0, b0;&#xD;&#xA;    int x1, r1, g1, b1;&#xD;&#xA;    int dx;&#xD;&#xA;    int kr, kg, kb;&#xD;&#xA;    int dr, dg, db;&#xD;&#xA;    int r, cr;&#xD;&#xA;    int g, cg;&#xD;&#xA;    int b, cb;&#xD;&#xA;&#xD;&#xA;    for (int y = y0; y &lt;= y1; ++y)&#xD;&#xA;    {&#xD;&#xA;        if (ContourX[y][0] &lt; ContourX[y][1])&#xD;&#xA;        {&#xD;&#xA;            x0 = ContourX[y][0];&#xD;&#xA;            r0 = ContourR[y][0];&#xD;&#xA;            g0 = ContourG[y][0];&#xD;&#xA;            b0 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x1 = ContourX[y][1];&#xD;&#xA;            r1 = ContourR[y][1];&#xD;&#xA;            g1 = ContourG[y][1];&#xD;&#xA;            b1 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            x1 = ContourX[y][0];&#xD;&#xA;            r1 = ContourR[y][0];&#xD;&#xA;            g1 = ContourG[y][0];&#xD;&#xA;            b1 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x0 = ContourX[y][1];&#xD;&#xA;            r0 = ContourR[y][1];&#xD;&#xA;            g0 = ContourG[y][1];&#xD;&#xA;            b0 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        dx = x1 - x0;&#xD;&#xA;&#xD;&#xA;        kr = 0; dr = r1 - r0; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;        kg = 0; dg = g1 - g0; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;        kb = 0; db = b1 - b0; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;        r = r0; cr = dx;&#xD;&#xA;        g = g0; cg = dx;&#xD;&#xA;        b = b0; cb = dx;&#xD;&#xA;&#xD;&#xA;        for (int x = x0; x &lt;= x1; ++x)&#xD;&#xA;        {&#xD;&#xA;            SetPixel(x, y, r, g, b);&#xD;&#xA;&#xD;&#xA;            cr -= dr; if (cr &lt;= 0) { cr += dx; r += kr; }&#xD;&#xA;            cg -= dg; if (cg &lt;= 0) { cg += dx; g += kg; }&#xD;&#xA;            cb -= db; if (cb &lt;= 0) { cb += dx; b += kb; }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(void)&#xD;&#xA;{&#xD;&#xA;    Point2D p0, p1, p2, p3;&#xD;&#xA;&#xD;&#xA;    // clear the screen&#xD;&#xA;    memset(pixels, 0, sizeof(pixels));&#xD;&#xA;&#xD;&#xA;    // generate random triangle coordinates&#xD;&#xA;    srand((unsigned) time(NULL));&#xD;&#xA;&#xD;&#xA;    p0.x = 30;&#xD;&#xA;    p0.y = 41;&#xD;&#xA;    p0.r = 255;&#xD;&#xA;    p0.g = 0;&#xD;&#xA;    p0.b = 0;&#xD;&#xA;&#xD;&#xA;    p1.x = 350;&#xD;&#xA;    p1.y = 58;&#xD;&#xA;    p1.r = 0;&#xD;&#xA;    p1.g = 255;&#xD;&#xA;    p1.b = 0;&#xD;&#xA;&#xD;&#xA;    p2.x = 40;&#xD;&#xA;    p2.y = 311;&#xD;&#xA;    p2.r = 0;&#xD;&#xA;    p2.g = 0;&#xD;&#xA;    p2.b = 255;&#xD;&#xA;&#xD;&#xA;    p3.x = 572;&#xD;&#xA;    p3.y = 280;&#xD;&#xA;    p3.r = 255;&#xD;&#xA;    p3.g = 140;&#xD;&#xA;    p3.b = 0;&#xD;&#xA;&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p3, p2);&#xD;&#xA;&#xD;&#xA;    SDL_Init(SDL_INIT_EVERYTHING);&#xD;&#xA;&#xD;&#xA;    SDL_Window* window = SDL_CreateWindow&#xD;&#xA;    (&#xD;&#xA;        &quot;Trig&quot;,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SCREEN_WIDTH,&#xD;&#xA;        SCREEN_HEIGHT,&#xD;&#xA;        SDL_WINDOW_SHOWN&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);&#xD;&#xA;    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);&#xD;&#xA;    SDL_Event event;&#xD;&#xA;&#xD;&#xA;    bool quit = false;&#xD;&#xA;&#xD;&#xA;    while (!quit)&#xD;&#xA;    {&#xD;&#xA;        if (SDL_PollEvent(&amp;event))&#xD;&#xA;        {&#xD;&#xA;            switch (event.type)&#xD;&#xA;            {&#xD;&#xA;            case SDL_QUIT:&#xD;&#xA;            {&#xD;&#xA;                quit = true;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        SDL_UpdateTexture(texture, NULL, &amp;pixels[0], SCREEN_WIDTH * 4);&#xD;&#xA;        SDL_RenderCopy(renderer, texture, NULL, NULL);&#xD;&#xA;        SDL_RenderPresent(renderer);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    SDL_DestroyRenderer(renderer);&#xD;&#xA;    SDL_DestroyWindow(window);&#xD;&#xA;    SDL_Quit();&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;The problem is that there is an unfilled diagonal line in a quadrilateral&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;I am not sure what changes I should make to fix this issue. Any ideas? Also, how to make sure that edges don't overlap each other?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nx38t.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38075" PostHistoryTypeId="1" PostId="12905" RevisionGUID="b15860b6-03cc-4c37-93a8-441da7ccf189" CreationDate="2022-08-16T23:45:42.823" UserId="18373" Text="How to make sure that triangles share edges (also not overlap each other) when rendering a quadrilateral?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38076" PostHistoryTypeId="3" PostId="12905" RevisionGUID="b15860b6-03cc-4c37-93a8-441da7ccf189" CreationDate="2022-08-16T23:45:42.823" UserId="18373" Text="|c++|interpolation|scanline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38077" PostHistoryTypeId="5" PostId="12905" RevisionGUID="ecb1177d-7c3b-41d2-ac4a-158ca916bc12" CreationDate="2022-08-16T23:52:19.570" UserId="18373" Comment="added 302 characters in body" Text="Here is my simple scanline-based quadrilateral rasterizer using pure integer arithmetic. I adapted the code from [this Stack Overflow answer](https://stackoverflow.com/questions/65460132/how-to-hide-invisible-elements-of-the-3d-drawing/65664918#65664918)&#xD;&#xA;```&#xD;&#xA;/* g++ trig.cpp -o trig -lSDL2 */&#xD;&#xA;&#xD;&#xA;#include &lt;cstdlib&gt;&#xD;&#xA;#include &lt;ctime&gt;&#xD;&#xA;&#xD;&#xA;#define SDL_MAIN_HANDLED&#xD;&#xA;#include &lt;SDL2/SDL.h&gt;&#xD;&#xA;&#xD;&#xA;#define SCREEN_HEIGHT 400&#xD;&#xA;#define SCREEN_WIDTH  600&#xD;&#xA;&#xD;&#xA;// TODO make an array of values to be interpolated&#xD;&#xA;// TODO 1/z buffer using something like this: 0xfffff / z where z is integer&#xD;&#xA;// TODO uv texture mapping&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;    int x, y, z;&#xD;&#xA;    uint8_t r, g, b;&#xD;&#xA;    int u, v;&#xD;&#xA;} Point2D;&#xD;&#xA;&#xD;&#xA;uint8_t pixels[SCREEN_HEIGHT * SCREEN_WIDTH * 4];&#xD;&#xA;&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] = r;&#xD;&#xA;    pixels[offset + 1] = g;&#xD;&#xA;    pixels[offset + 2] = b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int ContourX[SCREEN_HEIGHT][2]; // min X and max X for every horizontal line within the triangle&#xD;&#xA;int ContourR[SCREEN_HEIGHT][2]; // red value for every horizontal line&#xD;&#xA;int ContourG[SCREEN_HEIGHT][2]; // green value for every horizontal line&#xD;&#xA;int ContourB[SCREEN_HEIGHT][2]; // blue value for every horizontal line&#xD;&#xA;&#xD;&#xA;#define ABS(x) ((x &gt;= 0) ? x : -x)&#xD;&#xA;&#xD;&#xA;// Scans a side of a triangle setting min X and max X in ContourX[][] (same for ContourR, ContourG, and ContourB) using the Bresenham's&#xD;&#xA;void TriangleLine(const Point2D&amp; p0, const Point2D&amp; p1)&#xD;&#xA;{&#xD;&#xA;    // DDA variables&#xD;&#xA;    int kx, ky, kr, kg, kb; // step directions&#xD;&#xA;    int dx, dy, dr, dg, db; // abs delta&#xD;&#xA;    kx = 0; dx = p1.x - p0.x; if (dx &gt; 0) kx = 1; if (dx &lt; 0) { kx = -1; dx = -dx; }&#xD;&#xA;    ky = 0; dy = p1.y - p0.y; if (dy &gt; 0) ky = 1; if (dy &lt; 0) { ky = -1; dy = -dy; }&#xD;&#xA;    kr = 0; dr = p1.r - p0.r; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;    kg = 0; dg = p1.g - p0.g; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;    kb = 0; db = p1.b - p0.b; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;    int n;&#xD;&#xA;    n = dx;&#xD;&#xA;    if (n &lt; dy) n = dy;&#xD;&#xA;    if (n &lt; dr) n = dr;&#xD;&#xA;    if (n &lt; dg) n = dg;&#xD;&#xA;    if (n &lt; db) n = db;&#xD;&#xA;    if (!n) n = 1;&#xD;&#xA;&#xD;&#xA;    // target buffer according to ky direction&#xD;&#xA;    int target; if (ky &gt; 0) target = 0; else target = 1;&#xD;&#xA;&#xD;&#xA;    // integer DDA line start point&#xD;&#xA;    int x = p0.x;&#xD;&#xA;    int y = p0.y;&#xD;&#xA;    int r = p0.r;&#xD;&#xA;    int g = p0.g;&#xD;&#xA;    int b = p0.b;&#xD;&#xA;&#xD;&#xA;    // fix endpoints just to be sure (wrong division constants by +/-1 can cause that last point is missing)&#xD;&#xA;    ContourX[p0.y][target] = p0.x;&#xD;&#xA;    ContourR[p0.y][target] = p0.r;&#xD;&#xA;    ContourG[p0.y][target] = p0.g;&#xD;&#xA;    ContourB[p0.y][target] = p0.b;&#xD;&#xA;&#xD;&#xA;    ContourX[p1.y][target] = p1.x;&#xD;&#xA;    ContourR[p1.y][target] = p1.r;&#xD;&#xA;    ContourG[p1.y][target] = p1.g;&#xD;&#xA;    ContourB[p1.y][target] = p1.b;&#xD;&#xA;&#xD;&#xA;    int cx, cy, cr, cg, cb, i;&#xD;&#xA;    for (cx = cy = cr = cg = cb = n, i = 0; i &lt; n; ++i)&#xD;&#xA;    {&#xD;&#xA;        ContourX[y][target] = x;&#xD;&#xA;        ContourR[y][target] = r;&#xD;&#xA;        ContourG[y][target] = g;&#xD;&#xA;        ContourB[y][target] = b;&#xD;&#xA;&#xD;&#xA;        cx -= dx; if (cx &lt;= 0){ cx += n; x += kx; }&#xD;&#xA;        cy -= dy; if (cy &lt;= 0){ cy += n; y += ky; }&#xD;&#xA;        cr -= dr; if (cr &lt;= 0){ cr += n; r += kr; }&#xD;&#xA;        cg -= dg; if (cg &lt;= 0){ cg += n; g += kg; }&#xD;&#xA;        cb -= db; if (cb &lt;= 0){ cb += n; b += kb; }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void DrawTriangle(const Point2D&amp; p0, const Point2D&amp; p1, const Point2D&amp; p2)&#xD;&#xA;{&#xD;&#xA;    TriangleLine(p0, p1);&#xD;&#xA;    TriangleLine(p1, p2);&#xD;&#xA;    TriangleLine(p2, p0);&#xD;&#xA;&#xD;&#xA;    int y0, y1; // min and max y&#xD;&#xA;    y0 = p0.y; if (y0 &gt; p1.y) y0 = p1.y; if (y0 &gt; p2.y) y0 = p2.y;&#xD;&#xA;    y1 = p0.y; if (y1 &lt; p1.y) y1 = p1.y; if (y1 &lt; p2.y) y1 = p2.y;&#xD;&#xA;&#xD;&#xA;    int x0, r0, g0, b0;&#xD;&#xA;    int x1, r1, g1, b1;&#xD;&#xA;    int dx;&#xD;&#xA;    int kr, kg, kb;&#xD;&#xA;    int dr, dg, db;&#xD;&#xA;    int r, cr;&#xD;&#xA;    int g, cg;&#xD;&#xA;    int b, cb;&#xD;&#xA;&#xD;&#xA;    for (int y = y0; y &lt;= y1; ++y)&#xD;&#xA;    {&#xD;&#xA;        if (ContourX[y][0] &lt; ContourX[y][1])&#xD;&#xA;        {&#xD;&#xA;            x0 = ContourX[y][0];&#xD;&#xA;            r0 = ContourR[y][0];&#xD;&#xA;            g0 = ContourG[y][0];&#xD;&#xA;            b0 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x1 = ContourX[y][1];&#xD;&#xA;            r1 = ContourR[y][1];&#xD;&#xA;            g1 = ContourG[y][1];&#xD;&#xA;            b1 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            x1 = ContourX[y][0];&#xD;&#xA;            r1 = ContourR[y][0];&#xD;&#xA;            g1 = ContourG[y][0];&#xD;&#xA;            b1 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x0 = ContourX[y][1];&#xD;&#xA;            r0 = ContourR[y][1];&#xD;&#xA;            g0 = ContourG[y][1];&#xD;&#xA;            b0 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        dx = x1 - x0;&#xD;&#xA;&#xD;&#xA;        kr = 0; dr = r1 - r0; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;        kg = 0; dg = g1 - g0; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;        kb = 0; db = b1 - b0; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;        r = r0; cr = dx;&#xD;&#xA;        g = g0; cg = dx;&#xD;&#xA;        b = b0; cb = dx;&#xD;&#xA;&#xD;&#xA;        for (int x = x0; x &lt;= x1; ++x)&#xD;&#xA;        {&#xD;&#xA;            SetPixel(x, y, r, g, b);&#xD;&#xA;&#xD;&#xA;            cr -= dr; if (cr &lt;= 0) { cr += dx; r += kr; }&#xD;&#xA;            cg -= dg; if (cg &lt;= 0) { cg += dx; g += kg; }&#xD;&#xA;            cb -= db; if (cb &lt;= 0) { cb += dx; b += kb; }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(void)&#xD;&#xA;{&#xD;&#xA;    Point2D p0, p1, p2, p3;&#xD;&#xA;&#xD;&#xA;    // clear the screen&#xD;&#xA;    memset(pixels, 0, sizeof(pixels));&#xD;&#xA;&#xD;&#xA;    // generate random triangle coordinates&#xD;&#xA;    srand((unsigned) time(NULL));&#xD;&#xA;&#xD;&#xA;    p0.x = 30;&#xD;&#xA;    p0.y = 41;&#xD;&#xA;    p0.r = 255;&#xD;&#xA;    p0.g = 0;&#xD;&#xA;    p0.b = 0;&#xD;&#xA;&#xD;&#xA;    p1.x = 350;&#xD;&#xA;    p1.y = 58;&#xD;&#xA;    p1.r = 0;&#xD;&#xA;    p1.g = 255;&#xD;&#xA;    p1.b = 0;&#xD;&#xA;&#xD;&#xA;    p2.x = 40;&#xD;&#xA;    p2.y = 311;&#xD;&#xA;    p2.r = 0;&#xD;&#xA;    p2.g = 0;&#xD;&#xA;    p2.b = 255;&#xD;&#xA;&#xD;&#xA;    p3.x = 572;&#xD;&#xA;    p3.y = 280;&#xD;&#xA;    p3.r = 255;&#xD;&#xA;    p3.g = 140;&#xD;&#xA;    p3.b = 0;&#xD;&#xA;&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p3, p2);&#xD;&#xA;&#xD;&#xA;    SDL_Init(SDL_INIT_EVERYTHING);&#xD;&#xA;&#xD;&#xA;    SDL_Window* window = SDL_CreateWindow&#xD;&#xA;    (&#xD;&#xA;        &quot;Trig&quot;,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SCREEN_WIDTH,&#xD;&#xA;        SCREEN_HEIGHT,&#xD;&#xA;        SDL_WINDOW_SHOWN&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);&#xD;&#xA;    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);&#xD;&#xA;    SDL_Event event;&#xD;&#xA;&#xD;&#xA;    bool quit = false;&#xD;&#xA;&#xD;&#xA;    while (!quit)&#xD;&#xA;    {&#xD;&#xA;        if (SDL_PollEvent(&amp;event))&#xD;&#xA;        {&#xD;&#xA;            switch (event.type)&#xD;&#xA;            {&#xD;&#xA;            case SDL_QUIT:&#xD;&#xA;            {&#xD;&#xA;                quit = true;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        SDL_UpdateTexture(texture, NULL, &amp;pixels[0], SCREEN_WIDTH * 4);&#xD;&#xA;        SDL_RenderCopy(renderer, texture, NULL, NULL);&#xD;&#xA;        SDL_RenderPresent(renderer);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    SDL_DestroyRenderer(renderer);&#xD;&#xA;    SDL_DestroyWindow(window);&#xD;&#xA;    SDL_Quit();&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;The problem is that there is an unfilled diagonal line in a quadrilateral&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;I am not sure what changes I should make to fix this issue. Any ideas? Also, how to make sure that edges don't overlap each other?&#xD;&#xA;&#xD;&#xA;I asked [this related question](https://computergraphics.stackexchange.com/questions/12737/how-to-draw-smoother-lines-and-triangles) about a month ago and I didn't get a complete answer because I want to know implementation details. I appreciate it if anyone can modify my sample code to show how it is done.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nx38t.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38078" PostHistoryTypeId="5" PostId="12905" RevisionGUID="648adfa6-e72c-44e7-9363-dddd3ac71c78" CreationDate="2022-08-17T00:15:33.250" UserId="18373" Comment="added 467 characters in body" Text="Here is my simple scanline-based quadrilateral rasterizer using pure integer arithmetic. I adapted the code from [this Stack Overflow answer](https://stackoverflow.com/questions/65460132/how-to-hide-invisible-elements-of-the-3d-drawing/65664918#65664918)&#xD;&#xA;```&#xD;&#xA;/* g++ trig.cpp -o trig -lSDL2 */&#xD;&#xA;&#xD;&#xA;#include &lt;cstdlib&gt;&#xD;&#xA;#include &lt;ctime&gt;&#xD;&#xA;&#xD;&#xA;#define SDL_MAIN_HANDLED&#xD;&#xA;#include &lt;SDL2/SDL.h&gt;&#xD;&#xA;&#xD;&#xA;#define SCREEN_HEIGHT 400&#xD;&#xA;#define SCREEN_WIDTH  600&#xD;&#xA;&#xD;&#xA;// TODO make an array of values to be interpolated&#xD;&#xA;// TODO 1/z buffer using something like this: 0xfffff / z where z is integer&#xD;&#xA;// TODO uv texture mapping&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;    int x, y, z;&#xD;&#xA;    uint8_t r, g, b;&#xD;&#xA;    int u, v;&#xD;&#xA;} Point2D;&#xD;&#xA;&#xD;&#xA;uint8_t pixels[SCREEN_HEIGHT * SCREEN_WIDTH * 4];&#xD;&#xA;&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] = r;&#xD;&#xA;    pixels[offset + 1] = g;&#xD;&#xA;    pixels[offset + 2] = b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int ContourX[SCREEN_HEIGHT][2]; // min X and max X for every horizontal line within the triangle&#xD;&#xA;int ContourR[SCREEN_HEIGHT][2]; // red value for every horizontal line&#xD;&#xA;int ContourG[SCREEN_HEIGHT][2]; // green value for every horizontal line&#xD;&#xA;int ContourB[SCREEN_HEIGHT][2]; // blue value for every horizontal line&#xD;&#xA;&#xD;&#xA;#define ABS(x) ((x &gt;= 0) ? x : -x)&#xD;&#xA;&#xD;&#xA;// Scans a side of a triangle setting min X and max X in ContourX[][] (same for ContourR, ContourG, and ContourB) using the Bresenham's&#xD;&#xA;void TriangleLine(const Point2D&amp; p0, const Point2D&amp; p1)&#xD;&#xA;{&#xD;&#xA;    // DDA variables&#xD;&#xA;    int kx, ky, kr, kg, kb; // step directions&#xD;&#xA;    int dx, dy, dr, dg, db; // abs delta&#xD;&#xA;    kx = 0; dx = p1.x - p0.x; if (dx &gt; 0) kx = 1; if (dx &lt; 0) { kx = -1; dx = -dx; }&#xD;&#xA;    ky = 0; dy = p1.y - p0.y; if (dy &gt; 0) ky = 1; if (dy &lt; 0) { ky = -1; dy = -dy; }&#xD;&#xA;    kr = 0; dr = p1.r - p0.r; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;    kg = 0; dg = p1.g - p0.g; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;    kb = 0; db = p1.b - p0.b; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;    int n;&#xD;&#xA;    n = dx;&#xD;&#xA;    if (n &lt; dy) n = dy;&#xD;&#xA;    if (n &lt; dr) n = dr;&#xD;&#xA;    if (n &lt; dg) n = dg;&#xD;&#xA;    if (n &lt; db) n = db;&#xD;&#xA;    if (!n) n = 1;&#xD;&#xA;&#xD;&#xA;    // target buffer according to ky direction&#xD;&#xA;    int target; if (ky &gt; 0) target = 0; else target = 1;&#xD;&#xA;&#xD;&#xA;    // integer DDA line start point&#xD;&#xA;    int x = p0.x;&#xD;&#xA;    int y = p0.y;&#xD;&#xA;    int r = p0.r;&#xD;&#xA;    int g = p0.g;&#xD;&#xA;    int b = p0.b;&#xD;&#xA;&#xD;&#xA;    // fix endpoints just to be sure (wrong division constants by +/-1 can cause that last point is missing)&#xD;&#xA;    ContourX[p0.y][target] = p0.x;&#xD;&#xA;    ContourR[p0.y][target] = p0.r;&#xD;&#xA;    ContourG[p0.y][target] = p0.g;&#xD;&#xA;    ContourB[p0.y][target] = p0.b;&#xD;&#xA;&#xD;&#xA;    ContourX[p1.y][target] = p1.x;&#xD;&#xA;    ContourR[p1.y][target] = p1.r;&#xD;&#xA;    ContourG[p1.y][target] = p1.g;&#xD;&#xA;    ContourB[p1.y][target] = p1.b;&#xD;&#xA;&#xD;&#xA;    int cx, cy, cr, cg, cb, i;&#xD;&#xA;    for (cx = cy = cr = cg = cb = n, i = 0; i &lt; n; ++i)&#xD;&#xA;    {&#xD;&#xA;        ContourX[y][target] = x;&#xD;&#xA;        ContourR[y][target] = r;&#xD;&#xA;        ContourG[y][target] = g;&#xD;&#xA;        ContourB[y][target] = b;&#xD;&#xA;&#xD;&#xA;        cx -= dx; if (cx &lt;= 0){ cx += n; x += kx; }&#xD;&#xA;        cy -= dy; if (cy &lt;= 0){ cy += n; y += ky; }&#xD;&#xA;        cr -= dr; if (cr &lt;= 0){ cr += n; r += kr; }&#xD;&#xA;        cg -= dg; if (cg &lt;= 0){ cg += n; g += kg; }&#xD;&#xA;        cb -= db; if (cb &lt;= 0){ cb += n; b += kb; }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void DrawTriangle(const Point2D&amp; p0, const Point2D&amp; p1, const Point2D&amp; p2)&#xD;&#xA;{&#xD;&#xA;    TriangleLine(p0, p1);&#xD;&#xA;    TriangleLine(p1, p2);&#xD;&#xA;    TriangleLine(p2, p0);&#xD;&#xA;&#xD;&#xA;    int y0, y1; // min and max y&#xD;&#xA;    y0 = p0.y; if (y0 &gt; p1.y) y0 = p1.y; if (y0 &gt; p2.y) y0 = p2.y;&#xD;&#xA;    y1 = p0.y; if (y1 &lt; p1.y) y1 = p1.y; if (y1 &lt; p2.y) y1 = p2.y;&#xD;&#xA;&#xD;&#xA;    int x0, r0, g0, b0;&#xD;&#xA;    int x1, r1, g1, b1;&#xD;&#xA;    int dx;&#xD;&#xA;    int kr, kg, kb;&#xD;&#xA;    int dr, dg, db;&#xD;&#xA;    int r, cr;&#xD;&#xA;    int g, cg;&#xD;&#xA;    int b, cb;&#xD;&#xA;&#xD;&#xA;    for (int y = y0; y &lt;= y1; ++y)&#xD;&#xA;    {&#xD;&#xA;        if (ContourX[y][0] &lt; ContourX[y][1])&#xD;&#xA;        {&#xD;&#xA;            x0 = ContourX[y][0];&#xD;&#xA;            r0 = ContourR[y][0];&#xD;&#xA;            g0 = ContourG[y][0];&#xD;&#xA;            b0 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x1 = ContourX[y][1];&#xD;&#xA;            r1 = ContourR[y][1];&#xD;&#xA;            g1 = ContourG[y][1];&#xD;&#xA;            b1 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            x1 = ContourX[y][0];&#xD;&#xA;            r1 = ContourR[y][0];&#xD;&#xA;            g1 = ContourG[y][0];&#xD;&#xA;            b1 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x0 = ContourX[y][1];&#xD;&#xA;            r0 = ContourR[y][1];&#xD;&#xA;            g0 = ContourG[y][1];&#xD;&#xA;            b0 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        dx = x1 - x0;&#xD;&#xA;&#xD;&#xA;        kr = 0; dr = r1 - r0; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;        kg = 0; dg = g1 - g0; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;        kb = 0; db = b1 - b0; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;        r = r0; cr = dx;&#xD;&#xA;        g = g0; cg = dx;&#xD;&#xA;        b = b0; cb = dx;&#xD;&#xA;&#xD;&#xA;        for (int x = x0; x &lt;= x1; ++x)&#xD;&#xA;        {&#xD;&#xA;            SetPixel(x, y, r, g, b);&#xD;&#xA;&#xD;&#xA;            cr -= dr; if (cr &lt;= 0) { cr += dx; r += kr; }&#xD;&#xA;            cg -= dg; if (cg &lt;= 0) { cg += dx; g += kg; }&#xD;&#xA;            cb -= db; if (cb &lt;= 0) { cb += dx; b += kb; }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(void)&#xD;&#xA;{&#xD;&#xA;    Point2D p0, p1, p2, p3;&#xD;&#xA;&#xD;&#xA;    // clear the screen&#xD;&#xA;    memset(pixels, 0, sizeof(pixels));&#xD;&#xA;&#xD;&#xA;    // generate random triangle coordinates&#xD;&#xA;    srand((unsigned) time(NULL));&#xD;&#xA;&#xD;&#xA;    p0.x = 30;&#xD;&#xA;    p0.y = 41;&#xD;&#xA;    p0.r = 255;&#xD;&#xA;    p0.g = 0;&#xD;&#xA;    p0.b = 0;&#xD;&#xA;&#xD;&#xA;    p1.x = 350;&#xD;&#xA;    p1.y = 58;&#xD;&#xA;    p1.r = 0;&#xD;&#xA;    p1.g = 255;&#xD;&#xA;    p1.b = 0;&#xD;&#xA;&#xD;&#xA;    p2.x = 40;&#xD;&#xA;    p2.y = 311;&#xD;&#xA;    p2.r = 0;&#xD;&#xA;    p2.g = 0;&#xD;&#xA;    p2.b = 255;&#xD;&#xA;&#xD;&#xA;    p3.x = 572;&#xD;&#xA;    p3.y = 280;&#xD;&#xA;    p3.r = 255;&#xD;&#xA;    p3.g = 140;&#xD;&#xA;    p3.b = 0;&#xD;&#xA;&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p3, p2);&#xD;&#xA;&#xD;&#xA;    SDL_Init(SDL_INIT_EVERYTHING);&#xD;&#xA;&#xD;&#xA;    SDL_Window* window = SDL_CreateWindow&#xD;&#xA;    (&#xD;&#xA;        &quot;Trig&quot;,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SCREEN_WIDTH,&#xD;&#xA;        SCREEN_HEIGHT,&#xD;&#xA;        SDL_WINDOW_SHOWN&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);&#xD;&#xA;    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);&#xD;&#xA;    SDL_Event event;&#xD;&#xA;&#xD;&#xA;    bool quit = false;&#xD;&#xA;&#xD;&#xA;    while (!quit)&#xD;&#xA;    {&#xD;&#xA;        if (SDL_PollEvent(&amp;event))&#xD;&#xA;        {&#xD;&#xA;            switch (event.type)&#xD;&#xA;            {&#xD;&#xA;            case SDL_QUIT:&#xD;&#xA;            {&#xD;&#xA;                quit = true;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        SDL_UpdateTexture(texture, NULL, &amp;pixels[0], SCREEN_WIDTH * 4);&#xD;&#xA;        SDL_RenderCopy(renderer, texture, NULL, NULL);&#xD;&#xA;        SDL_RenderPresent(renderer);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    SDL_DestroyRenderer(renderer);&#xD;&#xA;    SDL_DestroyWindow(window);&#xD;&#xA;    SDL_Quit();&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;The problem is that there is an unfilled diagonal line in a quadrilateral&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;I am not sure what changes I should make to fix this issue. Any ideas? Also, how to make sure that edges don't overlap each other?&#xD;&#xA;&#xD;&#xA;When I change the order of vertexes to&#xD;&#xA;```&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p2, p3);&#xD;&#xA;```&#xD;&#xA;The problem seems to be solved but there are overlapping pixels if I change my pixel rendering function to&#xD;&#xA;```&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] += r;&#xD;&#xA;    pixels[offset + 1] += g;&#xD;&#xA;    pixels[offset + 2] += b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I asked [this related question](https://computergraphics.stackexchange.com/questions/12737/how-to-draw-smoother-lines-and-triangles) about a month ago and I didn't get a complete answer because I want to know implementation details. I appreciate it if anyone can modify my sample code to show how it is done.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nx38t.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38079" PostHistoryTypeId="5" PostId="12905" RevisionGUID="4e919f17-e16e-4219-97b7-47958577376c" CreationDate="2022-08-17T00:30:32.437" UserId="18373" Comment="added 82 characters in body" Text="Here is my simple scanline-based triangle rasterizer using pure integer arithmetic. I adapted the code from [this Stack Overflow answer](https://stackoverflow.com/questions/65460132/how-to-hide-invisible-elements-of-the-3d-drawing/65664918#65664918) The below code attempts to render a coloured quadrilateral by rendering two triangles.&#xD;&#xA;```&#xD;&#xA;/* g++ trig.cpp -o trig -lSDL2 */&#xD;&#xA;&#xD;&#xA;#include &lt;cstdlib&gt;&#xD;&#xA;#include &lt;ctime&gt;&#xD;&#xA;&#xD;&#xA;#define SDL_MAIN_HANDLED&#xD;&#xA;#include &lt;SDL2/SDL.h&gt;&#xD;&#xA;&#xD;&#xA;#define SCREEN_HEIGHT 400&#xD;&#xA;#define SCREEN_WIDTH  600&#xD;&#xA;&#xD;&#xA;// TODO make an array of values to be interpolated&#xD;&#xA;// TODO 1/z buffer using something like this: 0xfffff / z where z is integer&#xD;&#xA;// TODO uv texture mapping&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;    int x, y, z;&#xD;&#xA;    uint8_t r, g, b;&#xD;&#xA;    int u, v;&#xD;&#xA;} Point2D;&#xD;&#xA;&#xD;&#xA;uint8_t pixels[SCREEN_HEIGHT * SCREEN_WIDTH * 4];&#xD;&#xA;&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] = r;&#xD;&#xA;    pixels[offset + 1] = g;&#xD;&#xA;    pixels[offset + 2] = b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int ContourX[SCREEN_HEIGHT][2]; // min X and max X for every horizontal line within the triangle&#xD;&#xA;int ContourR[SCREEN_HEIGHT][2]; // red value for every horizontal line&#xD;&#xA;int ContourG[SCREEN_HEIGHT][2]; // green value for every horizontal line&#xD;&#xA;int ContourB[SCREEN_HEIGHT][2]; // blue value for every horizontal line&#xD;&#xA;&#xD;&#xA;#define ABS(x) ((x &gt;= 0) ? x : -x)&#xD;&#xA;&#xD;&#xA;// Scans a side of a triangle setting min X and max X in ContourX[][] (same for ContourR, ContourG, and ContourB) using the Bresenham's&#xD;&#xA;void TriangleLine(const Point2D&amp; p0, const Point2D&amp; p1)&#xD;&#xA;{&#xD;&#xA;    // DDA variables&#xD;&#xA;    int kx, ky, kr, kg, kb; // step directions&#xD;&#xA;    int dx, dy, dr, dg, db; // abs delta&#xD;&#xA;    kx = 0; dx = p1.x - p0.x; if (dx &gt; 0) kx = 1; if (dx &lt; 0) { kx = -1; dx = -dx; }&#xD;&#xA;    ky = 0; dy = p1.y - p0.y; if (dy &gt; 0) ky = 1; if (dy &lt; 0) { ky = -1; dy = -dy; }&#xD;&#xA;    kr = 0; dr = p1.r - p0.r; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;    kg = 0; dg = p1.g - p0.g; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;    kb = 0; db = p1.b - p0.b; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;    int n;&#xD;&#xA;    n = dx;&#xD;&#xA;    if (n &lt; dy) n = dy;&#xD;&#xA;    if (n &lt; dr) n = dr;&#xD;&#xA;    if (n &lt; dg) n = dg;&#xD;&#xA;    if (n &lt; db) n = db;&#xD;&#xA;    if (!n) n = 1;&#xD;&#xA;&#xD;&#xA;    // target buffer according to ky direction&#xD;&#xA;    int target; if (ky &gt; 0) target = 0; else target = 1;&#xD;&#xA;&#xD;&#xA;    // integer DDA line start point&#xD;&#xA;    int x = p0.x;&#xD;&#xA;    int y = p0.y;&#xD;&#xA;    int r = p0.r;&#xD;&#xA;    int g = p0.g;&#xD;&#xA;    int b = p0.b;&#xD;&#xA;&#xD;&#xA;    // fix endpoints just to be sure (wrong division constants by +/-1 can cause that last point is missing)&#xD;&#xA;    ContourX[p0.y][target] = p0.x;&#xD;&#xA;    ContourR[p0.y][target] = p0.r;&#xD;&#xA;    ContourG[p0.y][target] = p0.g;&#xD;&#xA;    ContourB[p0.y][target] = p0.b;&#xD;&#xA;&#xD;&#xA;    ContourX[p1.y][target] = p1.x;&#xD;&#xA;    ContourR[p1.y][target] = p1.r;&#xD;&#xA;    ContourG[p1.y][target] = p1.g;&#xD;&#xA;    ContourB[p1.y][target] = p1.b;&#xD;&#xA;&#xD;&#xA;    int cx, cy, cr, cg, cb, i;&#xD;&#xA;    for (cx = cy = cr = cg = cb = n, i = 0; i &lt; n; ++i)&#xD;&#xA;    {&#xD;&#xA;        ContourX[y][target] = x;&#xD;&#xA;        ContourR[y][target] = r;&#xD;&#xA;        ContourG[y][target] = g;&#xD;&#xA;        ContourB[y][target] = b;&#xD;&#xA;&#xD;&#xA;        cx -= dx; if (cx &lt;= 0){ cx += n; x += kx; }&#xD;&#xA;        cy -= dy; if (cy &lt;= 0){ cy += n; y += ky; }&#xD;&#xA;        cr -= dr; if (cr &lt;= 0){ cr += n; r += kr; }&#xD;&#xA;        cg -= dg; if (cg &lt;= 0){ cg += n; g += kg; }&#xD;&#xA;        cb -= db; if (cb &lt;= 0){ cb += n; b += kb; }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void DrawTriangle(const Point2D&amp; p0, const Point2D&amp; p1, const Point2D&amp; p2)&#xD;&#xA;{&#xD;&#xA;    TriangleLine(p0, p1);&#xD;&#xA;    TriangleLine(p1, p2);&#xD;&#xA;    TriangleLine(p2, p0);&#xD;&#xA;&#xD;&#xA;    int y0, y1; // min and max y&#xD;&#xA;    y0 = p0.y; if (y0 &gt; p1.y) y0 = p1.y; if (y0 &gt; p2.y) y0 = p2.y;&#xD;&#xA;    y1 = p0.y; if (y1 &lt; p1.y) y1 = p1.y; if (y1 &lt; p2.y) y1 = p2.y;&#xD;&#xA;&#xD;&#xA;    int x0, r0, g0, b0;&#xD;&#xA;    int x1, r1, g1, b1;&#xD;&#xA;    int dx;&#xD;&#xA;    int kr, kg, kb;&#xD;&#xA;    int dr, dg, db;&#xD;&#xA;    int r, cr;&#xD;&#xA;    int g, cg;&#xD;&#xA;    int b, cb;&#xD;&#xA;&#xD;&#xA;    for (int y = y0; y &lt;= y1; ++y)&#xD;&#xA;    {&#xD;&#xA;        if (ContourX[y][0] &lt; ContourX[y][1])&#xD;&#xA;        {&#xD;&#xA;            x0 = ContourX[y][0];&#xD;&#xA;            r0 = ContourR[y][0];&#xD;&#xA;            g0 = ContourG[y][0];&#xD;&#xA;            b0 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x1 = ContourX[y][1];&#xD;&#xA;            r1 = ContourR[y][1];&#xD;&#xA;            g1 = ContourG[y][1];&#xD;&#xA;            b1 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            x1 = ContourX[y][0];&#xD;&#xA;            r1 = ContourR[y][0];&#xD;&#xA;            g1 = ContourG[y][0];&#xD;&#xA;            b1 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x0 = ContourX[y][1];&#xD;&#xA;            r0 = ContourR[y][1];&#xD;&#xA;            g0 = ContourG[y][1];&#xD;&#xA;            b0 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        dx = x1 - x0;&#xD;&#xA;&#xD;&#xA;        kr = 0; dr = r1 - r0; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;        kg = 0; dg = g1 - g0; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;        kb = 0; db = b1 - b0; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;        r = r0; cr = dx;&#xD;&#xA;        g = g0; cg = dx;&#xD;&#xA;        b = b0; cb = dx;&#xD;&#xA;&#xD;&#xA;        for (int x = x0; x &lt;= x1; ++x)&#xD;&#xA;        {&#xD;&#xA;            SetPixel(x, y, r, g, b);&#xD;&#xA;&#xD;&#xA;            cr -= dr; if (cr &lt;= 0) { cr += dx; r += kr; }&#xD;&#xA;            cg -= dg; if (cg &lt;= 0) { cg += dx; g += kg; }&#xD;&#xA;            cb -= db; if (cb &lt;= 0) { cb += dx; b += kb; }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(void)&#xD;&#xA;{&#xD;&#xA;    Point2D p0, p1, p2, p3;&#xD;&#xA;&#xD;&#xA;    // clear the screen&#xD;&#xA;    memset(pixels, 0, sizeof(pixels));&#xD;&#xA;&#xD;&#xA;    // generate random triangle coordinates&#xD;&#xA;    srand((unsigned) time(NULL));&#xD;&#xA;&#xD;&#xA;    p0.x = 30;&#xD;&#xA;    p0.y = 41;&#xD;&#xA;    p0.r = 255;&#xD;&#xA;    p0.g = 0;&#xD;&#xA;    p0.b = 0;&#xD;&#xA;&#xD;&#xA;    p1.x = 350;&#xD;&#xA;    p1.y = 58;&#xD;&#xA;    p1.r = 0;&#xD;&#xA;    p1.g = 255;&#xD;&#xA;    p1.b = 0;&#xD;&#xA;&#xD;&#xA;    p2.x = 40;&#xD;&#xA;    p2.y = 311;&#xD;&#xA;    p2.r = 0;&#xD;&#xA;    p2.g = 0;&#xD;&#xA;    p2.b = 255;&#xD;&#xA;&#xD;&#xA;    p3.x = 572;&#xD;&#xA;    p3.y = 280;&#xD;&#xA;    p3.r = 255;&#xD;&#xA;    p3.g = 140;&#xD;&#xA;    p3.b = 0;&#xD;&#xA;&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p3, p2);&#xD;&#xA;&#xD;&#xA;    SDL_Init(SDL_INIT_EVERYTHING);&#xD;&#xA;&#xD;&#xA;    SDL_Window* window = SDL_CreateWindow&#xD;&#xA;    (&#xD;&#xA;        &quot;Trig&quot;,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SCREEN_WIDTH,&#xD;&#xA;        SCREEN_HEIGHT,&#xD;&#xA;        SDL_WINDOW_SHOWN&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);&#xD;&#xA;    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);&#xD;&#xA;    SDL_Event event;&#xD;&#xA;&#xD;&#xA;    bool quit = false;&#xD;&#xA;&#xD;&#xA;    while (!quit)&#xD;&#xA;    {&#xD;&#xA;        if (SDL_PollEvent(&amp;event))&#xD;&#xA;        {&#xD;&#xA;            switch (event.type)&#xD;&#xA;            {&#xD;&#xA;            case SDL_QUIT:&#xD;&#xA;            {&#xD;&#xA;                quit = true;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        SDL_UpdateTexture(texture, NULL, &amp;pixels[0], SCREEN_WIDTH * 4);&#xD;&#xA;        SDL_RenderCopy(renderer, texture, NULL, NULL);&#xD;&#xA;        SDL_RenderPresent(renderer);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    SDL_DestroyRenderer(renderer);&#xD;&#xA;    SDL_DestroyWindow(window);&#xD;&#xA;    SDL_Quit();&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;The problem is that there is an unfilled diagonal line in a quadrilateral&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;I am not sure what changes I should make to fix this issue. Any ideas? Also, how to make sure that edges don't overlap each other?&#xD;&#xA;&#xD;&#xA;When I change the order of vertexes to&#xD;&#xA;```&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p2, p3);&#xD;&#xA;```&#xD;&#xA;The problem seems to be solved but there are overlapping pixels if I change my pixel rendering function to&#xD;&#xA;```&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] += r;&#xD;&#xA;    pixels[offset + 1] += g;&#xD;&#xA;    pixels[offset + 2] += b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I asked [this related question](https://computergraphics.stackexchange.com/questions/12737/how-to-draw-smoother-lines-and-triangles) about a month ago and I didn't get a complete answer because I want to know implementation details. I appreciate it if anyone can modify my sample code to show how it is done.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nx38t.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38080" PostHistoryTypeId="5" PostId="12905" RevisionGUID="90eba988-73ef-413d-9187-4a01cb87b4d3" CreationDate="2022-08-17T01:48:22.293" UserId="18373" Comment="added 292 characters in body" Text="Here is my simple scanline-based triangle rasterizer using pure integer arithmetic. I adapted the code from [this Stack Overflow answer](https://stackoverflow.com/questions/65460132/how-to-hide-invisible-elements-of-the-3d-drawing/65664918#65664918) The below code attempts to render a coloured quadrilateral by rendering two triangles.&#xD;&#xA;```&#xD;&#xA;/* g++ trig.cpp -o trig -lSDL2 */&#xD;&#xA;&#xD;&#xA;#include &lt;cstdlib&gt;&#xD;&#xA;#include &lt;ctime&gt;&#xD;&#xA;&#xD;&#xA;#define SDL_MAIN_HANDLED&#xD;&#xA;#include &lt;SDL2/SDL.h&gt;&#xD;&#xA;&#xD;&#xA;#define SCREEN_HEIGHT 400&#xD;&#xA;#define SCREEN_WIDTH  600&#xD;&#xA;&#xD;&#xA;// TODO make an array of values to be interpolated&#xD;&#xA;// TODO 1/z buffer using something like this: 0xfffff / z where z is integer&#xD;&#xA;// TODO uv texture mapping&#xD;&#xA;typedef struct&#xD;&#xA;{&#xD;&#xA;    int x, y, z;&#xD;&#xA;    uint8_t r, g, b;&#xD;&#xA;    int u, v;&#xD;&#xA;} Point2D;&#xD;&#xA;&#xD;&#xA;uint8_t pixels[SCREEN_HEIGHT * SCREEN_WIDTH * 4];&#xD;&#xA;&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] = r;&#xD;&#xA;    pixels[offset + 1] = g;&#xD;&#xA;    pixels[offset + 2] = b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int ContourX[SCREEN_HEIGHT][2]; // min X and max X for every horizontal line within the triangle&#xD;&#xA;int ContourR[SCREEN_HEIGHT][2]; // red value for every horizontal line&#xD;&#xA;int ContourG[SCREEN_HEIGHT][2]; // green value for every horizontal line&#xD;&#xA;int ContourB[SCREEN_HEIGHT][2]; // blue value for every horizontal line&#xD;&#xA;&#xD;&#xA;#define ABS(x) ((x &gt;= 0) ? x : -x)&#xD;&#xA;&#xD;&#xA;// Scans a side of a triangle setting min X and max X in ContourX[][] (same for ContourR, ContourG, and ContourB) using the Bresenham's&#xD;&#xA;void TriangleLine(const Point2D&amp; p0, const Point2D&amp; p1)&#xD;&#xA;{&#xD;&#xA;    // DDA variables&#xD;&#xA;    int kx, ky, kr, kg, kb; // step directions&#xD;&#xA;    int dx, dy, dr, dg, db; // abs delta&#xD;&#xA;    kx = 0; dx = p1.x - p0.x; if (dx &gt; 0) kx = 1; if (dx &lt; 0) { kx = -1; dx = -dx; }&#xD;&#xA;    ky = 0; dy = p1.y - p0.y; if (dy &gt; 0) ky = 1; if (dy &lt; 0) { ky = -1; dy = -dy; }&#xD;&#xA;    kr = 0; dr = p1.r - p0.r; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;    kg = 0; dg = p1.g - p0.g; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;    kb = 0; db = p1.b - p0.b; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;    int n;&#xD;&#xA;    n = dx;&#xD;&#xA;    if (n &lt; dy) n = dy;&#xD;&#xA;    if (n &lt; dr) n = dr;&#xD;&#xA;    if (n &lt; dg) n = dg;&#xD;&#xA;    if (n &lt; db) n = db;&#xD;&#xA;    if (!n) n = 1;&#xD;&#xA;&#xD;&#xA;    // target buffer according to ky direction&#xD;&#xA;    int target; if (ky &gt; 0) target = 0; else target = 1;&#xD;&#xA;&#xD;&#xA;    // integer DDA line start point&#xD;&#xA;    int x = p0.x;&#xD;&#xA;    int y = p0.y;&#xD;&#xA;    int r = p0.r;&#xD;&#xA;    int g = p0.g;&#xD;&#xA;    int b = p0.b;&#xD;&#xA;&#xD;&#xA;    // fix endpoints just to be sure (wrong division constants by +/-1 can cause that last point is missing)&#xD;&#xA;    ContourX[p0.y][target] = p0.x;&#xD;&#xA;    ContourR[p0.y][target] = p0.r;&#xD;&#xA;    ContourG[p0.y][target] = p0.g;&#xD;&#xA;    ContourB[p0.y][target] = p0.b;&#xD;&#xA;&#xD;&#xA;    ContourX[p1.y][target] = p1.x;&#xD;&#xA;    ContourR[p1.y][target] = p1.r;&#xD;&#xA;    ContourG[p1.y][target] = p1.g;&#xD;&#xA;    ContourB[p1.y][target] = p1.b;&#xD;&#xA;&#xD;&#xA;    int cx, cy, cr, cg, cb, i;&#xD;&#xA;    for (cx = cy = cr = cg = cb = n, i = 0; i &lt; n; ++i)&#xD;&#xA;    {&#xD;&#xA;        ContourX[y][target] = x;&#xD;&#xA;        ContourR[y][target] = r;&#xD;&#xA;        ContourG[y][target] = g;&#xD;&#xA;        ContourB[y][target] = b;&#xD;&#xA;&#xD;&#xA;        cx -= dx; if (cx &lt;= 0){ cx += n; x += kx; }&#xD;&#xA;        cy -= dy; if (cy &lt;= 0){ cy += n; y += ky; }&#xD;&#xA;        cr -= dr; if (cr &lt;= 0){ cr += n; r += kr; }&#xD;&#xA;        cg -= dg; if (cg &lt;= 0){ cg += n; g += kg; }&#xD;&#xA;        cb -= db; if (cb &lt;= 0){ cb += n; b += kb; }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void DrawTriangle(const Point2D&amp; p0, const Point2D&amp; p1, const Point2D&amp; p2)&#xD;&#xA;{&#xD;&#xA;    TriangleLine(p0, p1);&#xD;&#xA;    TriangleLine(p1, p2);&#xD;&#xA;    TriangleLine(p2, p0);&#xD;&#xA;&#xD;&#xA;    int y0, y1; // min and max y&#xD;&#xA;    y0 = p0.y; if (y0 &gt; p1.y) y0 = p1.y; if (y0 &gt; p2.y) y0 = p2.y;&#xD;&#xA;    y1 = p0.y; if (y1 &lt; p1.y) y1 = p1.y; if (y1 &lt; p2.y) y1 = p2.y;&#xD;&#xA;&#xD;&#xA;    int x0, r0, g0, b0;&#xD;&#xA;    int x1, r1, g1, b1;&#xD;&#xA;    int dx;&#xD;&#xA;    int kr, kg, kb;&#xD;&#xA;    int dr, dg, db;&#xD;&#xA;    int r, cr;&#xD;&#xA;    int g, cg;&#xD;&#xA;    int b, cb;&#xD;&#xA;&#xD;&#xA;    for (int y = y0; y &lt;= y1; ++y)&#xD;&#xA;    {&#xD;&#xA;        if (ContourX[y][0] &lt; ContourX[y][1])&#xD;&#xA;        {&#xD;&#xA;            x0 = ContourX[y][0];&#xD;&#xA;            r0 = ContourR[y][0];&#xD;&#xA;            g0 = ContourG[y][0];&#xD;&#xA;            b0 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x1 = ContourX[y][1];&#xD;&#xA;            r1 = ContourR[y][1];&#xD;&#xA;            g1 = ContourG[y][1];&#xD;&#xA;            b1 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            x1 = ContourX[y][0];&#xD;&#xA;            r1 = ContourR[y][0];&#xD;&#xA;            g1 = ContourG[y][0];&#xD;&#xA;            b1 = ContourB[y][0];&#xD;&#xA;&#xD;&#xA;            x0 = ContourX[y][1];&#xD;&#xA;            r0 = ContourR[y][1];&#xD;&#xA;            g0 = ContourG[y][1];&#xD;&#xA;            b0 = ContourB[y][1];&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        dx = x1 - x0;&#xD;&#xA;&#xD;&#xA;        kr = 0; dr = r1 - r0; if (dr &gt; 0) kr = 1; if (dr &lt; 0) { kr = -1; dr = -dr; }&#xD;&#xA;        kg = 0; dg = g1 - g0; if (dg &gt; 0) kg = 1; if (dg &lt; 0) { kg = -1; dg = -dg; }&#xD;&#xA;        kb = 0; db = b1 - b0; if (db &gt; 0) kb = 1; if (db &lt; 0) { kb = -1; db = -db; }&#xD;&#xA;&#xD;&#xA;        r = r0; cr = dx;&#xD;&#xA;        g = g0; cg = dx;&#xD;&#xA;        b = b0; cb = dx;&#xD;&#xA;&#xD;&#xA;        for (int x = x0; x &lt;= x1; ++x)&#xD;&#xA;        {&#xD;&#xA;            SetPixel(x, y, r, g, b);&#xD;&#xA;&#xD;&#xA;            cr -= dr; if (cr &lt;= 0) { cr += dx; r += kr; }&#xD;&#xA;            cg -= dg; if (cg &lt;= 0) { cg += dx; g += kg; }&#xD;&#xA;            cb -= db; if (cb &lt;= 0) { cb += dx; b += kb; }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(void)&#xD;&#xA;{&#xD;&#xA;    Point2D p0, p1, p2, p3;&#xD;&#xA;&#xD;&#xA;    // clear the screen&#xD;&#xA;    memset(pixels, 0, sizeof(pixels));&#xD;&#xA;&#xD;&#xA;    // generate random triangle coordinates&#xD;&#xA;    srand((unsigned) time(NULL));&#xD;&#xA;&#xD;&#xA;    p0.x = 30;&#xD;&#xA;    p0.y = 41;&#xD;&#xA;    p0.r = 255;&#xD;&#xA;    p0.g = 0;&#xD;&#xA;    p0.b = 0;&#xD;&#xA;&#xD;&#xA;    p1.x = 350;&#xD;&#xA;    p1.y = 58;&#xD;&#xA;    p1.r = 0;&#xD;&#xA;    p1.g = 255;&#xD;&#xA;    p1.b = 0;&#xD;&#xA;&#xD;&#xA;    p2.x = 40;&#xD;&#xA;    p2.y = 311;&#xD;&#xA;    p2.r = 0;&#xD;&#xA;    p2.g = 0;&#xD;&#xA;    p2.b = 255;&#xD;&#xA;&#xD;&#xA;    p3.x = 572;&#xD;&#xA;    p3.y = 280;&#xD;&#xA;    p3.r = 255;&#xD;&#xA;    p3.g = 140;&#xD;&#xA;    p3.b = 0;&#xD;&#xA;&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p3, p2);&#xD;&#xA;&#xD;&#xA;    SDL_Init(SDL_INIT_EVERYTHING);&#xD;&#xA;&#xD;&#xA;    SDL_Window* window = SDL_CreateWindow&#xD;&#xA;    (&#xD;&#xA;        &quot;Trig&quot;,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SDL_WINDOWPOS_UNDEFINED,&#xD;&#xA;        SCREEN_WIDTH,&#xD;&#xA;        SCREEN_HEIGHT,&#xD;&#xA;        SDL_WINDOW_SHOWN&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);&#xD;&#xA;    SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);&#xD;&#xA;    SDL_Event event;&#xD;&#xA;&#xD;&#xA;    bool quit = false;&#xD;&#xA;&#xD;&#xA;    while (!quit)&#xD;&#xA;    {&#xD;&#xA;        if (SDL_PollEvent(&amp;event))&#xD;&#xA;        {&#xD;&#xA;            switch (event.type)&#xD;&#xA;            {&#xD;&#xA;            case SDL_QUIT:&#xD;&#xA;            {&#xD;&#xA;                quit = true;&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        SDL_UpdateTexture(texture, NULL, &amp;pixels[0], SCREEN_WIDTH * 4);&#xD;&#xA;        SDL_RenderCopy(renderer, texture, NULL, NULL);&#xD;&#xA;        SDL_RenderPresent(renderer);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    SDL_DestroyRenderer(renderer);&#xD;&#xA;    SDL_DestroyWindow(window);&#xD;&#xA;    SDL_Quit();&#xD;&#xA;&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;The problem is that there is an unfilled diagonal line in a quadrilateral&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;I am not sure what changes I should make to fix this issue. Any ideas? Also, how to make sure that edges don't overlap each other?&#xD;&#xA;&#xD;&#xA;When I change the order of vertexes to&#xD;&#xA;```&#xD;&#xA;    DrawTriangle(p0, p1, p2);&#xD;&#xA;    DrawTriangle(p1, p2, p3);&#xD;&#xA;```&#xD;&#xA;The problem seems to be solved but there are overlapping pixels if I change my pixel rendering function to&#xD;&#xA;```&#xD;&#xA;void SetPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)&#xD;&#xA;{&#xD;&#xA;    int offset = y * SCREEN_WIDTH * 4 + x * 4;&#xD;&#xA;&#xD;&#xA;    pixels[offset] += r;&#xD;&#xA;    pixels[offset + 1] += g;&#xD;&#xA;    pixels[offset + 2] += b;&#xD;&#xA;    pixels[offset + 3] = 255;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I asked [this related question](https://computergraphics.stackexchange.com/questions/12737/how-to-draw-smoother-lines-and-triangles) about a month ago and I didn't get a complete answer because I want to know implementation details. I appreciate it if anyone can modify my sample code to show how it is done.&#xD;&#xA;&#xD;&#xA;Edit: I learned about the &quot;top left rule&quot; and I changed this line in `DrawTriangle`&#xD;&#xA;```&#xD;&#xA;for (int x = x0; x &lt;= x1; ++x)&#xD;&#xA;```&#xD;&#xA;to&#xD;&#xA;```&#xD;&#xA;for (int x = x0; x &lt; x1; ++x)&#xD;&#xA;```&#xD;&#xA;It seems to work well but I am not sure if this is the correct way to implement this rule. Are there any edge cases?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Nx38t.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38082" PostHistoryTypeId="19" PostId="7916" RevisionGUID="a69ba57d-6f3d-4da7-aa77-8803161645d5" CreationDate="2022-08-17T03:35:48.653" UserId="-1" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:-1,&quot;DisplayName&quot;:&quot;Community&quot;}]}" />
  <row Id="38083" PostHistoryTypeId="5" PostId="12446" RevisionGUID="d86fe815-8689-4d67-b5b9-cfb0320d5d18" CreationDate="2022-08-17T03:49:52.533" UserId="17813" Comment="added bounty info" Text="[![milk jug from thesis][1]][1]&#xD;&#xA;&#xD;&#xA;The little milk pitcher / jug in [Ed Catmull][2]'s 1975 PhD thesis [“The Utilization of Procedure Models in Digital Image Synthesis”][3], does anybody have the bicubic patch data for it?  The teapot's data ([in several early versions][4]) is well-distributed of course, [the spoon and cup/saucer are downloadable][5] from a few repositories.  But (so far) [I can't find the milk jug's][6].&#xD;&#xA;&#xD;&#xA;Is it lost forever, or is somebody out there willing / able to make it available?&#xD;&#xA;&#xD;&#xA;[![Figure 29  Table Setting][7]][7]&#xD;&#xA;&#xD;&#xA;**Edited to add:**  for the purposes of the bounty I need patch data that when added properly to add_mesh_teapot.py produces a mesh substantially similar to “Figure 26  Meshes Defining a Jug” above, with [provenance][8] (at minimum, a description of how the data came into the answerer's possession that won't be significantly contradicted).&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;Above image is a screenshot of [Blender][10] using [a version of add_mesh_teapot.py that's had the teacup &amp; saucer patch data added to it][11].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rySjW.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Edwin_Catmull&#xD;&#xA;  [3]: https://collections.lib.utah.edu/ark:/87278/s6hh73p6&#xD;&#xA;  [4]: http://www.holmes3d.net/graphics/teapot/&#xD;&#xA;  [5]: https://github.com/rm-hull/newell-teapot&#xD;&#xA;  [6]: https://blenderartists.org/t/how-do-i-propose-an-addition-to-the-extra-objects-add-on/1351462/16&#xD;&#xA;  [7]: https://i.stack.imgur.com/bJvNG.jpg&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Provenance&#xD;&#xA;  [9]: https://i.stack.imgur.com/wPT18.jpg&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Blender_(software)&#xD;&#xA;  [11]: https://blenderartists.org/t/how-do-i-propose-an-addition-to-the-extra-objects-add-on/1351462/22" ContentLicense="CC BY-SA 4.0" />
  <row Id="38084" PostHistoryTypeId="33" PostId="12446" RevisionGUID="0398fbe0-9fe4-46e0-a82e-335cc8296f1c" CreationDate="2022-08-17T03:58:43.297" UserId="17813" Comment="79" />
  <row Id="38085" PostHistoryTypeId="2" PostId="12906" RevisionGUID="8cadeb6e-4e72-44de-b936-5baafcad4a8b" CreationDate="2022-08-17T03:59:38.813" UserId="18373" Text="I have doubts on 1/z depth buffer interpolation. According to [this website](https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/visibility-problem-depth-buffer-depth-interpolation), the correct 1/z interpolation formula is&#xD;&#xA;&#xD;&#xA;$\dfrac{1}{P.z} = \dfrac{1}{V0.z} * \lambda_0 + \dfrac{1}{V1.z} * \lambda_1 + \dfrac{1}{V2.z} * \lambda_2.&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Here is my 1/z interpolation implementation in my barycentric triangle rendering algorithm for my software renderer&#xD;&#xA;```&#xD;&#xA;    void DrawFilledTriangleBarycentric(const vec3f&amp; v1, const vec3f&amp; v2, const vec3f&amp; v3, const Colour&amp; colour) {&#xD;&#xA;        ...&#xD;&#xA;                // Barycentric weights&#xD;&#xA;                float w1 = ((px - v2[0]) * (v3[1] - v2[1]) - (py - v2[1]) * (v3[0] - v2[0])) / area;&#xD;&#xA;                float w2 = ((px - v3[0]) * (v1[1] - v3[1]) - (py - v3[1]) * (v1[0] - v3[0])) / area;&#xD;&#xA;                float w3 = ((px - v1[0]) * (v2[1] - v1[1]) - (py - v1[1]) * (v2[0] - v1[0])) / area;&#xD;&#xA;&#xD;&#xA;                if ((w1 &gt;= 0.0f) &amp; (w2 &gt;= 0.0f) &amp; (w3 &gt;= 0.0f))&#xD;&#xA;                {&#xD;&#xA;                    float z = w1 * v1[2] + w2 * v2[2] + w3 * v3[2];&#xD;&#xA;                    float depth = 1.0f / z;&#xD;&#xA;&#xD;&#xA;                    PutPixel(x, y, depth, colour.argb);&#xD;&#xA;                }&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;especially this part&#xD;&#xA;```&#xD;&#xA;float z = w1 * v1[2] + w2 * v2[2] + w3 * v3[2];&#xD;&#xA;float depth = 1.0f / z;&#xD;&#xA;```&#xD;&#xA;`v1[2]`, `v2[2]`, and `v3[2]` are z values. I am wondering whether I should change it to&#xD;&#xA;```&#xD;&#xA;float z = w1 * (1.0 / v1[2]) + w2 * (1.0 / v2[2]) + w3 * (1.0 / v3[2]);&#xD;&#xA;float depth = z;&#xD;&#xA;```&#xD;&#xA;But if I do I got the following output&#xD;&#xA;&#xD;&#xA;[![1][1]][1]&#xD;&#xA;&#xD;&#xA;which is different from what I expect (using `depth=1.0f/(w1 * v1[2] + w2 * v2[2] + w3 * v3[2])`)&#xD;&#xA;&#xD;&#xA;[![2][2]][2]&#xD;&#xA;&#xD;&#xA;These are the triangles I am trying to render&#xD;&#xA;```&#xD;&#xA;DrawFilledTriangleBarycentric(vec3f(10, 50, 10), vec3f(400, 100, 10), vec3f(290, 380, 10), RED);&#xD;&#xA;DrawFilledTriangleBarycentric(vec3f(50, 350, 2), vec3f(130, 40, 20), vec3f(380, 200, 5), GREEN);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2rVBG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ForGR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38087" PostHistoryTypeId="1" PostId="12906" RevisionGUID="8cadeb6e-4e72-44de-b936-5baafcad4a8b" CreationDate="2022-08-17T03:59:38.813" UserId="18373" Text="Correct way to interpolate 1/z?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38088" PostHistoryTypeId="3" PostId="12906" RevisionGUID="8cadeb6e-4e72-44de-b936-5baafcad4a8b" CreationDate="2022-08-17T03:59:38.813" UserId="18373" Text="|interpolation|z-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38095" PostHistoryTypeId="5" PostId="12906" RevisionGUID="6072548e-d4c0-4c18-8f16-895b6be0eb6b" CreationDate="2022-08-17T11:05:44.987" UserId="18373" Comment="added 348 characters in body" Text="I have doubts on 1/z depth buffer interpolation. According to [this website](https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/visibility-problem-depth-buffer-depth-interpolation), the correct 1/z interpolation formula is&#xD;&#xA;&#xD;&#xA;$\dfrac{1}{P.z} = \dfrac{1}{V0.z} * \lambda_0 + \dfrac{1}{V1.z} * \lambda_1 + \dfrac{1}{V2.z} * \lambda_2.&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;Here is my 1/z interpolation implementation in my barycentric triangle rendering algorithm for my software renderer&#xD;&#xA;```&#xD;&#xA;    void DrawFilledTriangleBarycentric(const vec3f&amp; v1, const vec3f&amp; v2, const vec3f&amp; v3, const Colour&amp; colour) {&#xD;&#xA;        ...&#xD;&#xA;                // Barycentric weights&#xD;&#xA;                float w1 = ((px - v2[0]) * (v3[1] - v2[1]) - (py - v2[1]) * (v3[0] - v2[0])) / area;&#xD;&#xA;                float w2 = ((px - v3[0]) * (v1[1] - v3[1]) - (py - v3[1]) * (v1[0] - v3[0])) / area;&#xD;&#xA;                float w3 = ((px - v1[0]) * (v2[1] - v1[1]) - (py - v1[1]) * (v2[0] - v1[0])) / area;&#xD;&#xA;&#xD;&#xA;                if ((w1 &gt;= 0.0f) &amp; (w2 &gt;= 0.0f) &amp; (w3 &gt;= 0.0f))&#xD;&#xA;                {&#xD;&#xA;                    float z = w1 * v1[2] + w2 * v2[2] + w3 * v3[2];&#xD;&#xA;                    float depth = 1.0f / z;&#xD;&#xA;&#xD;&#xA;                    PutPixel(x, y, depth, colour.argb);&#xD;&#xA;                }&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;especially this part&#xD;&#xA;```&#xD;&#xA;float z = w1 * v1[2] + w2 * v2[2] + w3 * v3[2];&#xD;&#xA;float depth = 1.0f / z;&#xD;&#xA;```&#xD;&#xA;`v1[2]`, `v2[2]`, and `v3[2]` are z values. I am wondering whether I should change it to&#xD;&#xA;```&#xD;&#xA;float z = w1 * (1.0 / v1[2]) + w2 * (1.0 / v2[2]) + w3 * (1.0 / v3[2]);&#xD;&#xA;float depth = z;&#xD;&#xA;```&#xD;&#xA;But if I do I got the following output&#xD;&#xA;&#xD;&#xA;[![1][1]][1]&#xD;&#xA;&#xD;&#xA;which is different from what I expect (using `depth=1.0f/(w1 * v1[2] + w2 * v2[2] + w3 * v3[2])`)&#xD;&#xA;&#xD;&#xA;[![2][2]][2]&#xD;&#xA;&#xD;&#xA;These are the triangles I am trying to render&#xD;&#xA;```&#xD;&#xA;DrawFilledTriangleBarycentric(vec3f(10, 50, 10), vec3f(400, 100, 10), vec3f(290, 380, 10), RED);&#xD;&#xA;DrawFilledTriangleBarycentric(vec3f(50, 350, 2), vec3f(130, 40, 20), vec3f(380, 200, 5), GREEN);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Edit: I think I got it now. Depth testing method actually depends on what projection I use. If I use orthographic projection, z is linear but 1/z is not so I can use naive z buffer without problems. If I use perspective projection, z is no longer linear but 1/z becomes linear. In this case, inverse z testing is necessary. Am I right here? no?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2rVBG.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ForGR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38096" PostHistoryTypeId="2" PostId="12908" RevisionGUID="ba546471-e248-44cb-8b81-b24d253090cb" CreationDate="2022-08-18T22:35:24.377" UserId="18774" Text="You are right.&#xD;&#xA;In the examples you provided you only seem to render &quot;pre-transformed&quot; triangles which is why I think you were missing the point made in the article. Which depth testing is the correct one depends on what those triangles representeded *before* being transformed.&#xD;&#xA;&#xD;&#xA;Interpolating 1 / z instead of z is needed to get the correct depth for perspective-transformed geometry.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Homogeneous_coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="38098" PostHistoryTypeId="2" PostId="12909" RevisionGUID="8c1c1620-1b1c-4ca8-9926-9c0973b06397" CreationDate="2022-08-19T02:19:06.133" UserId="18787" Text="I'm having difficult understanding the issue with gimbal lock, namely why so many diagrams show an aircraft in apparent gimbal lock unable to turn about an axis conventionally, using yaw/pitch/roll. For example, below are some diagrams depicting a common scene of gimbal lock.&#xD;&#xA;&#xD;&#xA;In the first one, let us call it **Frame A** we start in a position where the Euler angles are all 0 and the aircraft is flying level:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Depicted are the gimbles aligned with their respective axis on the **body frame** denoted in yellow. Now, in the second image, we have pitched up 90 degrees, and we are in what, all resources I've found, is called gimbal lock:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;If you notice the second graphic, called **Frame B**, the body frame has followed along and we can see the intermediate frame after the pitch. The y-gimble and the z-gimble are now aligned however, and adjusting yaw results in the same response as adjusting roll:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;But this is where to me that doesn't make any sense. If we refer back to **Frame B** and look at our body frame, the yellow, it indicates that a roll does what we see in the two images above as the x-axis, or roll axis, is extending through the nose, but the z-axis, or the yaw axis, is perpendicular. Thus, the aircraft should be able to yaw appropriately (given rudder control surfaces and thrust).&#xD;&#xA;&#xD;&#xA;So why is it depicted here as if the body frame after **Frame A** is like so:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;With this axis that makes sense, but its not how I understand aircraft mechanics to work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/V5hY7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/f8rlF.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/abAkk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/kmT5g.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/CKajO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38100" PostHistoryTypeId="1" PostId="12909" RevisionGUID="8c1c1620-1b1c-4ca8-9926-9c0973b06397" CreationDate="2022-08-19T02:19:06.133" UserId="18787" Text="Confusion surrounding Gimbal Lock" ContentLicense="CC BY-SA 4.0" />
  <row Id="38101" PostHistoryTypeId="3" PostId="12909" RevisionGUID="8c1c1620-1b1c-4ca8-9926-9c0973b06397" CreationDate="2022-08-19T02:19:06.133" UserId="18787" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38102" PostHistoryTypeId="2" PostId="12910" RevisionGUID="4138a605-efd2-4690-b939-913623cabaf7" CreationDate="2022-08-19T04:06:10.030" UserId="2654" Text="&gt; its not how I understand aircraft mechanics to work&#xD;&#xA;&#xD;&#xA;Good, because they aren't supposed to.&#xD;&#xA;&#xD;&#xA;The aircraft in these examples are just models that have a well-defined front and up. They could be any model or even no model at all, just a set of coordinate axes. The point is to show the behavior of the *gimbals*, to show that no change of the yaw/pitch/roll gimbals array are able to orient the model along the locked-out axis.&#xD;&#xA;&#xD;&#xA;Aircraft fly based on aerodynamics, not mechanical structures wrapped around the plane that orient it. You're taking an analogy literally when you aren't supposed to." ContentLicense="CC BY-SA 4.0" />
  <row Id="38104" PostHistoryTypeId="52" PostId="12909" RevisionGUID="c2a7a0f0-9995-46cc-87e4-9999446806f9" CreationDate="2022-08-19T13:17:09.600" />
  <row Id="38105" PostHistoryTypeId="5" PostId="5560" RevisionGUID="ad83bd08-e4b0-480d-b8d5-61c0528abd49" CreationDate="2022-08-19T18:19:11.687" UserId="48" Comment="update link" Text="Mip selection is pretty well standardized across devices today—with the exception of some of the nitty-gritty details of anisotropic filtering, which is still up to the individual GPU manufacturers to define (and its precise details are generally not publicly documented).&#xD;&#xA;&#xD;&#xA;A good place to read about mip selection  in detail is in [the OpenGL spec, section 8.14, &quot;Texture Minification&quot;](https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf#section.8.14). I'd assume it works the same way in Metal. (Apple _could_ have changed something, considering they make both the hardware and the API...but I doubt they have.) I'll summarize it here.&#xD;&#xA;&#xD;&#xA;The default mip selection (not using any of the `lod_options` modifiers) uses the screen-space gradients of the texture coordinates to pick the mip levels. Essentially, it tries to pick the mip levels that produce as close as possible to a 1:1 mapping of texels to pixels. For example, if the gradients have a length of 4 texels per pixel, it would pick mip level 2 (which is 1/4th the size of level 0 and therefore gives you 1 mipped texel per pixel).&#xD;&#xA;&#xD;&#xA;With trilinear filtering, since you usually don't land on an _exact_ 1:1 mapping, it picks the two nearest levels and linearly interpolates between them, so that you have a smooth transition between mip levels as the camera or objects in your scene move around.&#xD;&#xA;&#xD;&#xA;To be mathematically precise: you take the screen-space gradients of the texture coordinates, scale them by the texture size (to get them in units of &quot;texels per pixel&quot;), take their lengths, take the longer of the two (X and Y) gradients, and calculate its logarithm base 2. This quantity is called $\lambda$ in the OpenGL spec; it's also commonly known as the texture LOD (level of detail). It's simply a continuous version of the integer mip level index. So, the mip levels used are the two integers nearest to $\lambda$, and the fractional part of $\lambda$ is used to blend between them. For example if $\lambda = 2.8$, the GPU will sample mip levels 2 and 3 of the texture, then blend to 80% level 3 and 20% level 2.&#xD;&#xA;&#xD;&#xA;If anisotropic filtering is turned on, then instead of simply using the longer of the two gradients, you use the ratio of them to set the number of aniso samples. For example, if the X gradient is 4 times longer than the Y gradient, you'd use 4 aniso samples, with their positions spaced out along the X gradient. Each one would be a trilinear sample, using a $\lambda$ corresponding to 1/4th the length of the X gradient (i.e. two mip levels lower, since $\log_2(1/4) = -2$).&#xD;&#xA;&#xD;&#xA;Now, as for the modifier options:&#xD;&#xA;&#xD;&#xA;* `bias` applies an offset to $\lambda$ before using it to select mip levels. So, for example, a bias of +1 will make it do trilinear filtering using mips one level higher than it would normally. A bias of −1 will use mips one level lower, and so on.&#xD;&#xA;* `level` completely overrides the automatic calculation of $\lambda$ from screen-space gradients, and lets you put in your own value of $\lambda$ (aka `lod`) directly.&#xD;&#xA;* `gradient2d` lets you put in your own gradient vectors, which substitute for the implicit screen-space gradients of the texture coordinates. The rest of the mip selection and sampling process proceeds as normal, but with the altered gradients. This lets you customize anisotropic filtering.&#xD;&#xA;&#xD;&#xA;In other types of shaders besides fragment shaders, there's no notion of &quot;screen-space gradients&quot;, so the latter two operations are typically the only ones allowed—any operation that tries to use implicit gradients would give a compile error. I'm not positive that's how Metal does it, but that's what I'd expect from working with other APIs." ContentLicense="CC BY-SA 4.0" />
  <row Id="38109" PostHistoryTypeId="50" PostId="9591" RevisionGUID="9b4970a3-86ff-49e8-ad36-4022e00b6aca" CreationDate="2022-08-20T01:10:05.997" UserId="-1" />
  <row Id="38110" PostHistoryTypeId="2" PostId="12911" RevisionGUID="6bbfcd4f-34fd-4c46-8691-91860ed8064f" CreationDate="2022-08-20T08:42:00.923" UserId="10505" Text="I am currently experimenting with unbounded descriptor arrays and ultimately want to use bindless descriptors. I wrote a simple test application, that draws 100.000 simple object instances, where the transform for each object is pulled from a buffer array.&#xD;&#xA;&#xD;&#xA;```hlsl&#xD;&#xA;#pragma pack_matrix(row_major)&#xD;&#xA;&#xD;&#xA;struct VertexData &#xD;&#xA;{&#xD;&#xA;    float4 Position : SV_POSITION;&#xD;&#xA;}; &#xD;&#xA;&#xD;&#xA;struct VertexInput&#xD;&#xA;{&#xD;&#xA;    float3 Position : POSITION;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct CameraData&#xD;&#xA;{&#xD;&#xA;    float4x4 ViewProjection;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct InstanceData&#xD;&#xA;{&#xD;&#xA;    float4x4 Transform;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;ConstantBuffer&lt;CameraData&gt; camera : register(b0, space0);&#xD;&#xA;StructuredBuffer&lt;InstanceData&gt; instanceBuffer[] : register(t0, space1);&#xD;&#xA;&#xD;&#xA;VertexData main(in VertexInput input, uint id : SV_InstanceID)&#xD;&#xA;{&#xD;&#xA;    VertexData vertex;&#xD;&#xA;&#xD;&#xA;    InstanceData instance = instanceBuffer[id].Load(0);&#xD;&#xA;    float4 position = mul(float4(input.Position, 1.0), instance.Transform);&#xD;&#xA;    vertex.Position = mul(position, camera.ViewProjection);&#xD;&#xA; &#xD;&#xA;    return vertex;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I am using DXC to compile this shader to both, SPIR-V and DXIL. Under Vulkan, the draw call takes roughly 2ms, however under D3D, it takes around 10ms. I tried eliminating the buffer access by hashing the instance id and generating the transform for each object this way and (as expected) the draw calls were equally fast. I then tried using a `ByteAddressBuffer` instead of a `StructuredBuffer` and it did not show any difference in Vulkan (which is expected, since [they are essentially the same in SPIR-V](https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#constant-texture-structured-byte-buffers)), but in D3D performance dropped even further to around 40ms per draw call. Now I am wondering what could cause such behavior. I tried [looking at the IL](https://godbolt.org/z/1j5WofcWs), but I can't really tell how this compares to each other.&#xD;&#xA;&#xD;&#xA;What could cause this discrepancy? Is there any way to profile this? All debuggers I tried just showed me the GPU times, which I mentioned above, but not more. Also some NSight Graphics features are not supported on my GPU (1080 Ti), so I could not test this compeltely." ContentLicense="CC BY-SA 4.0" />
  <row Id="38112" PostHistoryTypeId="1" PostId="12911" RevisionGUID="6bbfcd4f-34fd-4c46-8691-91860ed8064f" CreationDate="2022-08-20T08:42:00.923" UserId="10505" Text="What causes buffer access to be significantly slower in DXIL than SPIR-V?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38113" PostHistoryTypeId="3" PostId="12911" RevisionGUID="6bbfcd4f-34fd-4c46-8691-91860ed8064f" CreationDate="2022-08-20T08:42:00.923" UserId="10505" Text="|vulkan|directx12|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38114" PostHistoryTypeId="2" PostId="12912" RevisionGUID="58db4a8f-f1b7-4ea7-bfcc-21d9b20bdecd" CreationDate="2022-08-21T09:58:52.890" UserId="6046" Text="Summary taken from my original question and answer [here][1]..&#xD;&#xA;&#xD;&#xA;First of all as Nicol suggested you are mixing up the reality with how computers or the mechanics of the gimbals work. You are taking an analogy literally. &#xD;&#xA;&#xD;&#xA;If we scratch the whole concept of gimbals and see how rotations work in terms of maths, the idea is quite simple. The rotations around the 3 axes are described by the matrices..&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note however, that these matrices don't know the difference between global and local axes. By global, I mean axes that remain fixed in space no matter the rotations applied and the local are axes/frame fixed with the body so it moves accordingly. So when it comes down to math the rotation matrix is going to change the values in the same way it was doing the first time. So for e.g if we apply a $A_{x}({90^{\circ}})$ to a standard frame like in your first picture, it'd move the $Y$ axis to $Z$ and $Z$ to $-Y$ assuming counter-clockwise rotation for right handed system. Now if you apply a $A_{y}({u^{\circ}})$ with a random angle, the matrix is still gonna rotate around the previous $Y$ which is currently the local $-Z$ not the new local $Y$ axis.&#xD;&#xA;&#xD;&#xA;This is because matrix multiplication only modifies the respective columns/rows. If Y-axis was in the middle column at the beginning and then after a rotation the middle column values changed to Z-axis $(0,0,1)$ that doesn't mean it's going to rotate around the Z-axis next. Graphically speaking the rotation is still around the global Y-axis no matter what the values of the middle column are. If you have trouble understanding this try doing what I explained on a piece of paper and you'll see what I mean.&#xD;&#xA;&#xD;&#xA;Moving on, once you understand that, the second concept to understand is that euler angles work with chained rotations. So stuff like $x-y-z$ or $z-y-z$. The key thing to note is that the concept of gimbal lock appears after you apply 1 or 2 of those rotations in order *within* a specific chained rotation, say $x-y-z$. This is important because if you forget this you are gonna ask the question &quot;Well, why can't we just move the other axes?&quot; You can't because you are following a specific order of three chained rotations and you have already done the first one or two rotations.&#xD;&#xA;&#xD;&#xA;That being said, now you can imagine an aeroplane with the orientation&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Note here, that if you rotate around the $X$ you'll either roll left/right. Assume we are following the order $x-y-z$. Next assume we rotated around the $X$ axis a little so we can see the plane's bottom and then rotated $90$ degrees around the $Y$. This is how it'd look like&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Now here's the gimbal lock. If you try to rotate around the $Z$ axis it's the same rotation back when you were rotating around the $X$. That is, the plane is only rolling. We lost 1 degree of freedom.&#xD;&#xA;&#xD;&#xA;You might be thinking well but now, rotation around the $X$ rotates differently so we haven't lost any freedom at all. True but that's thinking again outside the concept of the chained rotation order. We have already done rotation around $X$ and $Y$ so the order only leaves us $Z$ but due to a certain angle of rotation around the $Y$ we can't uniquely rotate it in the third dimension. That's the gimbal lock. If you break free from the order, then it's really hard to perceive the idea of the loss of the degree of freedom.&#xD;&#xA;&#xD;&#xA;In applied mathematics terms, this is what's happening...&#xD;&#xA;&#xD;&#xA;We have our rotation order $x-y-z$ with the corresponding angles $\alpha-\beta-\gamma$,&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos \gamma &amp; -\sin \gamma &amp; 0 \\&#xD;&#xA;\sin \gamma &amp; \cos \gamma &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos \beta &amp; 0 &amp; \sin \beta \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;-\sin \beta &amp; 0 &amp; \cos \beta&#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos \alpha &amp; -\sin \alpha \\&#xD;&#xA;0 &amp; \sin \alpha &amp; \cos \alpha &#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now just to explain what's really going on we skip applying the first rotation and directly rotate 90 degrees around $Y$ which would be $\beta = 90$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos \gamma &amp; -\sin \gamma &amp; 0 \\&#xD;&#xA;\sin \gamma &amp; \cos \gamma &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 &amp; 0 &amp; 1 \\&#xD;&#xA;0 &amp; 1 &amp; 0 \\&#xD;&#xA;-1 &amp; 0 &amp; 0 &#xD;&#xA;\end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; \cos \alpha &amp; -\sin \alpha \\&#xD;&#xA;0 &amp; \sin \alpha &amp; \cos \alpha&#xD;&#xA;\end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;\cos \gamma &amp; -\sin \gamma &amp; 0 \\&#xD;&#xA;\sin \gamma &amp; \cos \gamma &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 \end{bmatrix}&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 &amp; \sin \alpha &amp; \cos \alpha \\&#xD;&#xA;0 &amp; \cos \alpha &amp; -\sin \alpha \\&#xD;&#xA;-1 &amp; 0 &amp; 0 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now multiplying these, we get,&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 &amp; \cos\gamma * \sin\alpha -\sin \gamma * \cos\alpha &amp; \cos\gamma * \cos\alpha + \sin \gamma * \sin \alpha \\&#xD;&#xA;0 &amp; \cos\gamma * \cos\alpha + \sin \gamma * \sin \alpha &amp; -\cos\gamma * \sin\alpha +\sin \gamma * \cos\alpha \\&#xD;&#xA;-1 &amp; 0 &amp; 0 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R = &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;0 &amp; \sin(\alpha - \gamma) &amp; \cos(\alpha - \gamma) \\&#xD;&#xA;0 &amp; \cos(\alpha - \gamma) &amp; -\sin(\alpha - \gamma) \\&#xD;&#xA;-1 &amp; 0 &amp; 0 \end{bmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;As you can see, changing either $\alpha$ or $\gamma$ here gives us the same matrix. Which means rotation around the $X$ or the $Z$ axis gives us the same result resulting in a loss of 1 degree of freedom.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Personally speaking all those images of gimbals always confused the hell out of me. For a graphics guy it'd have been much more clearer if people explained it more in terms of applied mathematics i.e. Matrices and such and used the diagrams of perpendicular axes instead of gimbals.&#xD;&#xA;&#xD;&#xA;What the artiles explaining this concept in terms of gimbals don't do is map the gimbal analogy to the axes analogy. In gimbals there is the concept of parenting. So moving the innermost or I guess the red gimbal in your case won't move the outer two. Moving the outermost will move the other two. This feels really confusing if you have the global/local axes analogy in mind and you are thinking of the gimbals as axes since here both local/global seem all mixed. The idea of the gimbals and parenting here is to preserve the way the previous rotation rotates the object so that when the gimbals align you can actually see that the previous and the new rotation rotate in the same way. So if we have the order $x-y-z$ The innermost gimbal would correspond to $x$. Think of the gimbals appearing one by one after each rotation is applied and not being there from the start.&#xD;&#xA;&#xD;&#xA;So considering my example of the plane, rotation around the $x$ does the rolling. The gimbal tied to it is the innermost. So that when you apply rotations around $y$ and $z$ the $x$ gimbal would move with them in order to preserve the rolling aspect.&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/6233/euler-angles-gimbal-lock-why-non-orthogonal-axes&#xD;&#xA;  [2]: https://i.stack.imgur.com/agrEP.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/5jGNQ.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/7cgdo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38116" PostHistoryTypeId="50" PostId="12853" RevisionGUID="ddc1741f-c298-4e8b-8011-45dfd98ec384" CreationDate="2022-08-21T10:06:40.623" UserId="-1" />
  <row Id="38117" PostHistoryTypeId="50" PostId="8260" RevisionGUID="34b2cedd-3d6a-4c3d-ada1-37811683efc7" CreationDate="2022-08-21T12:02:30.247" UserId="-1" />
  <row Id="38118" PostHistoryTypeId="50" PostId="12837" RevisionGUID="2f3d8cde-a9f8-4871-950b-c1bc6afeaf9d" CreationDate="2022-08-21T16:00:00.047" UserId="-1" />
  <row Id="38122" PostHistoryTypeId="2" PostId="12914" RevisionGUID="56b3cc11-b48b-40cb-9d09-ee66e5f0bd7b" CreationDate="2022-08-22T16:00:12.717" UserId="18793" Text="I am trying to simulate the behavior of &quot;texelFetch()&quot; and so far I've understood the following:&#xD;&#xA;&#xD;&#xA;If &quot;gvec4 texelFetch(gsampler3D sampler, ivec3 P, int lod)&quot; is given then :&#xD;&#xA;&#xD;&#xA;result = sampler * P&#xD;&#xA;&#xD;&#xA;But what should I do with &quot;lod&quot;? Is it supposed to be used to scale the sampler?&#xD;&#xA;&#xD;&#xA;I've gathered information about the purpose of *lod/level-of-details/mipmapping level* theoretically but I would like to understand the computation usage of it in the sampling process." ContentLicense="CC BY-SA 4.0" />
  <row Id="38124" PostHistoryTypeId="1" PostId="12914" RevisionGUID="56b3cc11-b48b-40cb-9d09-ee66e5f0bd7b" CreationDate="2022-08-22T16:00:12.717" UserId="18793" Text="How is mipmap level used mathemetically in image sampling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38125" PostHistoryTypeId="3" PostId="12914" RevisionGUID="56b3cc11-b48b-40cb-9d09-ee66e5f0bd7b" CreationDate="2022-08-22T16:00:12.717" UserId="18793" Text="|opengl|glsl|sampling|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38126" PostHistoryTypeId="5" PostId="12914" RevisionGUID="0890d16d-7fc4-4c18-a05d-54e8442f88b9" CreationDate="2022-08-22T16:01:08.967" UserId="18793" Comment="added 7 characters in body" Text="I am trying to simulate the behavior of &quot;texelFetch()&quot; and so far I've understood the following:&#xD;&#xA;&#xD;&#xA;If &quot;gvec4 texelFetch(gsampler3D sampler, ivec3 P, int lod)&quot; is given then :&#xD;&#xA;&#xD;&#xA;result = sampler * P&#xD;&#xA;&#xD;&#xA;But what should I do with &quot;lod&quot;? Is it supposed to be used to scale the sampler?&#xD;&#xA;&#xD;&#xA;I've read sufficient information about the purpose of *lod/level-of-details/mipmapping level* theoretically but I would like to understand the computation usage of it in the sampling process." ContentLicense="CC BY-SA 4.0" />
  <row Id="38127" PostHistoryTypeId="2" PostId="12915" RevisionGUID="9b8827b7-c716-46c2-bf5e-c01fa2232c4e" CreationDate="2022-08-22T17:44:54.843" UserId="2654" Text="`texelFetch` doesn't do any computations. The texture coordinates are in integer texels in texel space. That represents the exact texel you're asking for. The same goes for the `lod`: it specifies the exact mipmap level to fetch from, with 0 being the base level (largest) for the texture.&#xD;&#xA;&#xD;&#xA;`sampler * P` is not valid GLSL. Samplers are [opaque types][1]; the only way to access the resources the sampler represents is to use the standard library functions like `texelFetch`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Opaque_Type" ContentLicense="CC BY-SA 4.0" />
  <row Id="38129" PostHistoryTypeId="2" PostId="12916" RevisionGUID="44ea818f-a0d3-40f0-9d83-d3c269bec596" CreationDate="2022-08-22T17:47:41.440" UserId="18794" Text="**Is it possible, in OpenGL (specifically in WebGL), to use a single value from buffer for multiple shader iterations? Like to put the same element from buffer into shader attribute multiple times?**&#xD;&#xA;Like:&#xD;&#xA;&#xD;&#xA;glVertexAttribPointer(*, 0.5, *, *, *, *)&#xD;&#xA;&#xD;&#xA;Here what I have now:&#xD;&#xA;```js&#xD;&#xA;//buffer 1&#xD;&#xA;[&#xD;&#xA;    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,&#xD;&#xA;    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,&#xD;&#xA;    62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, &#xD;&#xA;    41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,&#xD;&#xA;    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,&#xD;&#xA;    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,&#xD;&#xA;    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,&#xD;&#xA;]&#xD;&#xA;// buffer 2&#xD;&#xA;[&#xD;&#xA;    -1, 1,&#xD;&#xA;    1, -1,&#xD;&#xA;    // ...&#xD;&#xA;    1, 1,&#xD;&#xA;]&#xD;&#xA;```&#xD;&#xA;Here what I want to have:&#xD;&#xA;```js&#xD;&#xA;//buffer 1&#xD;&#xA;[&#xD;&#xA;    0,&#xD;&#xA;    4,&#xD;&#xA;    62, &#xD;&#xA;    41,&#xD;&#xA;    0,&#xD;&#xA;    0,&#xD;&#xA;    1,&#xD;&#xA;]&#xD;&#xA;// buffer 2&#xD;&#xA;[&#xD;&#xA;    -1, 1,&#xD;&#xA;    1, -1,&#xD;&#xA;    // ...&#xD;&#xA;    1, 1,&#xD;&#xA;]&#xD;&#xA;```&#xD;&#xA;I don't know how fit the second one with OpenGL API&#xD;&#xA;&#xD;&#xA;I'm writing to my buffer1 a lot using CPU (glBufferSubData), that's why I need what I need.&#xD;&#xA;&#xD;&#xA;I'll appreciate any `C OpenGL` / `JS WebGL` code " ContentLicense="CC BY-SA 4.0" />
  <row Id="38131" PostHistoryTypeId="1" PostId="12916" RevisionGUID="44ea818f-a0d3-40f0-9d83-d3c269bec596" CreationDate="2022-08-22T17:47:41.440" UserId="18794" Text="How do I make &quot;vec0.5&quot; in GLSL. Sorry if it confuses" ContentLicense="CC BY-SA 4.0" />
  <row Id="38132" PostHistoryTypeId="3" PostId="12916" RevisionGUID="44ea818f-a0d3-40f0-9d83-d3c269bec596" CreationDate="2022-08-22T17:47:41.440" UserId="18794" Text="|opengl|glsl|c++|webgl|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38133" PostHistoryTypeId="4" PostId="12916" RevisionGUID="9ac2079e-7d26-4d50-aec4-8f11537ec6a2" CreationDate="2022-08-22T17:48:52.400" UserId="18794" Comment="edited title" Text="How do I make &quot;attribute vec0.5&quot; in GLSL. Sorry if it confuses" ContentLicense="CC BY-SA 4.0" />
  <row Id="38134" PostHistoryTypeId="5" PostId="12915" RevisionGUID="fdf3a23e-9eb4-46db-8857-15c42ac782aa" CreationDate="2022-08-22T17:51:09.177" UserId="2654" Comment="added 67 characters in body" Text="`texelFetch` doesn't do any computations. The texture coordinates are in integer texels in texel space. That represents the exact texel you're asking for. The same goes for the `lod`: it specifies the exact mipmap level to fetch from, with 0 being the base level (largest) for the texture.&#xD;&#xA;&#xD;&#xA;`sampler * P` is not valid GLSL. Samplers are [opaque types][1]; the only way to access the resources the sampler represents is to use the standard library functions like `texelFetch`. You cannot &quot;simulate the behavior of `texelFetch`&quot; with a sampler.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Opaque_Type" ContentLicense="CC BY-SA 4.0" />
  <row Id="38140" PostHistoryTypeId="50" PostId="5220" RevisionGUID="74d8d989-0166-4257-acfa-a4e3c8c90a71" CreationDate="2022-08-23T00:07:40.710" UserId="-1" />
  <row Id="38141" PostHistoryTypeId="2" PostId="12918" RevisionGUID="2a721d0b-f3d8-448e-90e9-52abc01d7bb4" CreationDate="2022-08-23T14:14:43.740" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38143" PostHistoryTypeId="1" PostId="12918" RevisionGUID="2a721d0b-f3d8-448e-90e9-52abc01d7bb4" CreationDate="2022-08-23T14:14:43.740" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38144" PostHistoryTypeId="2" PostId="12919" RevisionGUID="596db635-eaf0-4ab7-bd91-0f5315afcc6e" CreationDate="2022-08-23T14:14:43.740" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38146" PostHistoryTypeId="1" PostId="12919" RevisionGUID="596db635-eaf0-4ab7-bd91-0f5315afcc6e" CreationDate="2022-08-23T14:14:43.740" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38147" PostHistoryTypeId="2" PostId="12920" RevisionGUID="2c04bb32-3fac-4957-b555-b6d3262ac9c8" CreationDate="2022-08-23T14:16:31.240" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38149" PostHistoryTypeId="1" PostId="12920" RevisionGUID="2c04bb32-3fac-4957-b555-b6d3262ac9c8" CreationDate="2022-08-23T14:16:31.240" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38150" PostHistoryTypeId="2" PostId="12921" RevisionGUID="fd8163e2-82e6-4420-a855-b33c70a52fc4" CreationDate="2022-08-23T14:16:31.240" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38152" PostHistoryTypeId="1" PostId="12921" RevisionGUID="fd8163e2-82e6-4420-a855-b33c70a52fc4" CreationDate="2022-08-23T14:16:31.240" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38153" PostHistoryTypeId="2" PostId="12922" RevisionGUID="79a06e61-aaa9-41a4-b0de-757fe0ca3787" CreationDate="2022-08-23T14:27:41.120" UserId="18798" Text="Suppose we have a suface without self-intersection, then we can store it numerically using grid samples from its signed distance funtion. But what for the self-intersecting case, can we still use the SDF tech?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38155" PostHistoryTypeId="1" PostId="12922" RevisionGUID="79a06e61-aaa9-41a4-b0de-757fe0ca3787" CreationDate="2022-08-23T14:27:41.120" UserId="18798" Text="How can we represent a self-intersecting surface without analytic expression in computer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38156" PostHistoryTypeId="3" PostId="12922" RevisionGUID="79a06e61-aaa9-41a4-b0de-757fe0ca3787" CreationDate="2022-08-23T14:27:41.120" UserId="18798" Text="|raytracing|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38157" PostHistoryTypeId="2" PostId="12923" RevisionGUID="999d3944-fb9c-4251-b6dc-32fad7cb1fce" CreationDate="2022-08-23T16:37:26.830" UserId="17695" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/ef73e6c0b7b0c5b48aa091ffd75ae5d3b3ba4f67/mainwindow.cpp#L137 It fails to add all the points with some data sets like the one I made for the demo (a C++/Qt program) I am forced to use the last point of the points to extend as the last point in the output list. It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code.&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;In my french blog (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/" ContentLicense="CC BY-SA 4.0" />
  <row Id="38159" PostHistoryTypeId="1" PostId="12923" RevisionGUID="999d3944-fb9c-4251-b6dc-32fad7cb1fce" CreationDate="2022-08-23T16:37:26.830" UserId="17695" Text="Split a string of line segments into several other line segments" ContentLicense="CC BY-SA 4.0" />
  <row Id="38160" PostHistoryTypeId="3" PostId="12923" RevisionGUID="999d3944-fb9c-4251-b6dc-32fad7cb1fce" CreationDate="2022-08-23T16:37:26.830" UserId="17695" Text="|c++|2d|vectors|line|point|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38161" PostHistoryTypeId="5" PostId="12923" RevisionGUID="194ca63c-ce36-4f8c-92ae-d0570d68b87d" CreationDate="2022-08-23T16:46:05.760" UserId="17695" Comment="added 91 characters in body" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/ef73e6c0b7b0c5b48aa091ffd75ae5d3b3ba4f67/mainwindow.cpp#L137 It fails to add all the points with some data sets like the one I made for the demo (a C++/Qt program) I am forced to use the last point of the points to extend as the last point in the output list. It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code.&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;In my french blog (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/n7FQL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38162" PostHistoryTypeId="2" PostId="12924" RevisionGUID="d54c4e71-e50b-49eb-8541-ec57e9202c6f" CreationDate="2022-08-23T19:28:14.493" UserId="10096" Text="Here is some pseudo-code for an arc-length parametrization (would work for any dimension if you replace `vec2` with `vecD`):&#xD;&#xA;&#xD;&#xA;```lang-cpp&#xD;&#xA;vec2 p[n]; /* initial points */&#xD;&#xA;vec2 q[m]; /* array for output points */&#xD;&#xA;&#xD;&#xA;/* cumulative distances */&#xD;&#xA;float dists[n]; &#xD;&#xA;dists[0] = 0;&#xD;&#xA;for (int i=1; i&lt;n; ++i)&#xD;&#xA;    dists[i] = dists[i-1] + length(p[i]-p[i-1]);&#xD;&#xA;&#xD;&#xA;/* step size */&#xD;&#xA;float step = dists[n-1] / (m-1);&#xD;&#xA;q[0] = p[0];&#xD;&#xA;float total_dist = 0;&#xD;&#xA;int segment_idx = 1;&#xD;&#xA;for (int i=1; i&lt;m; ++i)&#xD;&#xA;{&#xD;&#xA;    total_dist = total_dist + step;&#xD;&#xA;    while (total_dist&gt;dists[segment_idx])&#xD;&#xA;    {&#xD;&#xA;         ++segment_idx;&#xD;&#xA;         if (segment_idx==n)&#xD;&#xA;             goto end;&#xD;&#xA;    }&#xD;&#xA;    float t = (total_dist - dists[segment_idx-1]) / (dists[segment_idx]-dists[segment_idx-1]);&#xD;&#xA;    q[i] = (1-t) * p[segment_idx-1] + t * p[segment_idx];&#xD;&#xA;}&#xD;&#xA;end:&#xD;&#xA;q[m-1] = p[n-1];&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;For the above to work you should not have degenerate cases such as `length(p[i]-p[i-1])==0` or you have to write extra code to handle those." ContentLicense="CC BY-SA 4.0" />
  <row Id="38164" PostHistoryTypeId="50" PostId="12850" RevisionGUID="13cdce0e-4830-4fb0-9fdf-849a93a1236e" CreationDate="2022-08-23T23:03:25.270" UserId="-1" />
  <row Id="38165" PostHistoryTypeId="5" PostId="12911" RevisionGUID="f80170fc-b4f9-494b-b0e2-00ff3ed28e0b" CreationDate="2022-08-24T08:05:27.863" UserId="10505" Comment="deleted 7 characters in body" Text="I am currently experimenting with unbounded descriptor arrays and ultimately want to use bindless descriptors. I wrote a test application, that draws 100.000 simple object instances, where the transform for each object is pulled from a buffer array.&#xD;&#xA;&#xD;&#xA;```hlsl&#xD;&#xA;#pragma pack_matrix(row_major)&#xD;&#xA;&#xD;&#xA;struct VertexData &#xD;&#xA;{&#xD;&#xA;    float4 Position : SV_POSITION;&#xD;&#xA;}; &#xD;&#xA;&#xD;&#xA;struct VertexInput&#xD;&#xA;{&#xD;&#xA;    float3 Position : POSITION;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct CameraData&#xD;&#xA;{&#xD;&#xA;    float4x4 ViewProjection;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct InstanceData&#xD;&#xA;{&#xD;&#xA;    float4x4 Transform;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;ConstantBuffer&lt;CameraData&gt; camera : register(b0, space0);&#xD;&#xA;StructuredBuffer&lt;InstanceData&gt; instanceBuffer[] : register(t0, space1);&#xD;&#xA;&#xD;&#xA;VertexData main(in VertexInput input, uint id : SV_InstanceID)&#xD;&#xA;{&#xD;&#xA;    VertexData vertex;&#xD;&#xA;&#xD;&#xA;    InstanceData instance = instanceBuffer[id].Load(0);&#xD;&#xA;    float4 position = mul(float4(input.Position, 1.0), instance.Transform);&#xD;&#xA;    vertex.Position = mul(position, camera.ViewProjection);&#xD;&#xA; &#xD;&#xA;    return vertex;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I am using DXC to compile this shader to both, SPIR-V and DXIL. Under Vulkan, the draw call takes roughly 2ms, however under D3D, it takes around 10ms. I tried eliminating the buffer access by hashing the instance id and generating the transform for each object this way and (as expected) the draw calls were equally fast. I then tried using a `ByteAddressBuffer` instead of a `StructuredBuffer` and it did not show any difference in Vulkan (which is expected, since [they are essentially the same in SPIR-V](https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#constant-texture-structured-byte-buffers)), but in D3D performance dropped even further to around 40ms per draw call. Now I am wondering what could cause such behavior. I tried [looking at the IL](https://godbolt.org/z/1j5WofcWs), but I can't really tell how this compares to each other.&#xD;&#xA;&#xD;&#xA;What could cause this discrepancy? Is there any way to profile this? All debuggers I tried just showed me the GPU times, which I mentioned above, but not more. Also some NSight Graphics features are not supported on my GPU (1080 Ti), so I could not test this compeltely." ContentLicense="CC BY-SA 4.0" />
  <row Id="38166" PostHistoryTypeId="50" PostId="12359" RevisionGUID="99ad9b31-ef15-4727-8bab-a256f640553f" CreationDate="2022-08-24T08:05:45.480" UserId="-1" />
  <row Id="38175" PostHistoryTypeId="5" PostId="12921" RevisionGUID="1633ff80-15a3-4158-a0cf-e5141d88da56" CreationDate="2022-08-24T14:02:27.660" UserId="171" Comment="added 111 characters in body" Text="Questions about a network of connected vertices, edges and faces to describe the shape of a specific 3D object." ContentLicense="CC BY-SA 4.0" />
  <row Id="38176" PostHistoryTypeId="24" PostId="12921" RevisionGUID="1633ff80-15a3-4158-a0cf-e5141d88da56" CreationDate="2022-08-24T14:02:27.660" Comment="Proposed by 171 approved by 13095 edit id of 587" ContentLicense="CC BY-SA 4.0" />
  <row Id="38177" PostHistoryTypeId="5" PostId="12919" RevisionGUID="23e04c91-cc37-460d-a848-6f7538657fd6" CreationDate="2022-08-24T14:02:49.407" UserId="171" Comment="added 102 characters in body" Text="Questions about the rigorous usage of instructions used to solve a specific computer graphics problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="38178" PostHistoryTypeId="24" PostId="12919" RevisionGUID="23e04c91-cc37-460d-a848-6f7538657fd6" CreationDate="2022-08-24T14:02:49.407" Comment="Proposed by 171 approved by 13095 edit id of 586" ContentLicense="CC BY-SA 4.0" />
  <row Id="38179" PostHistoryTypeId="5" PostId="12923" RevisionGUID="0be55a29-20be-43c0-a15f-b8b27fd19a50" CreationDate="2022-08-24T16:49:06.673" UserId="17695" Comment="added 111 characters in body" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/ef73e6c0b7b0c5b48aa091ffd75ae5d3b3ba4f67/mainwindow.cpp#L137 It fails to add all the points with some data sets like the one I made for the demo (a C++/Qt program) I am forced to use the last point of the points to extend as the last point in the output list. It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code.&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;Update: when I change the greater or equal sign of line to 223 to a great sign, I can reach the last point.&#xD;&#xA;&#xD;&#xA;In my french blog (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kSdRo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38180" PostHistoryTypeId="5" PostId="12923" RevisionGUID="dc7c4d86-adb9-4f05-a208-50069bc56cad" CreationDate="2022-08-24T16:58:38.033" UserId="17695" Comment="edited body" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/ef73e6c0b7b0c5b48aa091ffd75ae5d3b3ba4f67/mainwindow.cpp#L1377 It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code (the dot added towards the end is not precise).&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;In my french blog (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kSdRo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38181" PostHistoryTypeId="5" PostId="12923" RevisionGUID="e76652a7-0ef9-4aa1-95fc-2b2938f5d72e" CreationDate="2022-08-24T17:03:56.377" UserId="17695" Comment="added 5 characters in body" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/ef73e6c0b7b0c5b48aa091ffd75ae5d3b3ba4f67/mainwindow.cpp#L1377 It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code (the dot added towards the end is not precise).&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;In my french blog post (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kSdRo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38182" PostHistoryTypeId="34" PostId="12446" RevisionGUID="4b785623-2286-4f63-b6f5-e37e43cbec6e" CreationDate="2022-08-25T05:04:50.440" UserId="-1" Comment="79" />
  <row Id="38183" PostHistoryTypeId="50" PostId="8194" RevisionGUID="fd036ee9-cca7-469e-8c00-98a6f51b53fc" CreationDate="2022-08-25T10:07:40.793" UserId="-1" />
  <row Id="38184" PostHistoryTypeId="5" PostId="12923" RevisionGUID="48045142-b621-4cf7-8a8e-4a929e557909" CreationDate="2022-08-25T10:55:26.800" UserId="17695" Comment="deleted 1 character in body" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/d4137c087d0c2df1917f3b57170db96d81aca3b9/mainwindow.cpp#L137 It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code (the dot added towards the end is not precise).&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;In my french blog post (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kSdRo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38185" PostHistoryTypeId="5" PostId="12924" RevisionGUID="7add3010-f19e-4058-b96b-28eb24534f38" CreationDate="2022-08-25T11:04:59.410" UserId="10096" Comment="added 702 characters in body" Text="Here is some pseudo-code for an arc-length parametrization (would work for any dimension if you replace `vec2` with `vecD`):&#xD;&#xA;&#xD;&#xA;```lang-cpp&#xD;&#xA;vec2 p[n]; /* initial points */&#xD;&#xA;vec2 q[m]; /* array for output points */&#xD;&#xA;&#xD;&#xA;/* cumulative distances */&#xD;&#xA;float dists[n]; &#xD;&#xA;dists[0] = 0;&#xD;&#xA;for (int i=1; i&lt;n; ++i)&#xD;&#xA;    dists[i] = dists[i-1] + length(p[i]-p[i-1]);&#xD;&#xA;&#xD;&#xA;/* step size */&#xD;&#xA;float step = dists[n-1] / (m-1);&#xD;&#xA;q[0] = p[0];&#xD;&#xA;float total_dist = 0;&#xD;&#xA;int segment_idx = 1;&#xD;&#xA;for (int i=1; i&lt;m; ++i)&#xD;&#xA;{&#xD;&#xA;    total_dist = total_dist + step;&#xD;&#xA;    while (total_dist&gt;dists[segment_idx])&#xD;&#xA;    {&#xD;&#xA;         ++segment_idx;&#xD;&#xA;         if (segment_idx==n)&#xD;&#xA;             goto end;&#xD;&#xA;    }&#xD;&#xA;    float t = (total_dist - dists[segment_idx-1]) / (dists[segment_idx]-dists[segment_idx-1]);&#xD;&#xA;    q[i] = (1-t) * p[segment_idx-1] + t * p[segment_idx];&#xD;&#xA;}&#xD;&#xA;end:&#xD;&#xA;q[m-1] = p[n-1];&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;For the above to work you should not have degenerate cases such as `length(p[i]-p[i-1])==0` or you have to write extra code to handle those.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;Here is how the `vec2` struct may look like:&#xD;&#xA;&#xD;&#xA;```cpp-lang&#xD;&#xA;struct vec2&#xD;&#xA;{&#xD;&#xA;    float e[2];&#xD;&#xA;    vec2() : e{0,0} {}&#xD;&#xA;    vec2(float e0, float e1) : e{e0,e1} {}&#xD;&#xA;    const float&amp; operator[](int i) const {return e[i];}&#xD;&#xA;    float&amp; operator[](int i) {return e[i];}&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;vec2 operator+(const vec2&amp; l, const vec2&amp; r)&#xD;&#xA;{&#xD;&#xA;    return vec2(l[0]+r[0], l[1]+r[1]);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 operator-(const vec2&amp; l, const vec2&amp; r)&#xD;&#xA;{&#xD;&#xA;    return vec2(l[0]-r[0], l[1]-r[1]);  &#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec2 operator*(float l, const vec2&amp; r)&#xD;&#xA;{&#xD;&#xA;    return vec2(l*r[0], l*r[1]);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float dot(const vec2&amp; l, const vec2&amp; r)&#xD;&#xA;{&#xD;&#xA;    return l[0]*r[0]+l[1]*r[1];&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float length(const vec2&amp; v)&#xD;&#xA;{&#xD;&#xA;    return sqrtf(dot(v,v));&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="38188" PostHistoryTypeId="2" PostId="12927" RevisionGUID="99e11d61-d096-4346-94fa-be7ec3c55636" CreationDate="2022-08-26T13:00:06.303" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38190" PostHistoryTypeId="1" PostId="12927" RevisionGUID="99e11d61-d096-4346-94fa-be7ec3c55636" CreationDate="2022-08-26T13:00:06.303" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38191" PostHistoryTypeId="2" PostId="12928" RevisionGUID="292079cb-b3b9-4479-afe9-73cc5b58cfc8" CreationDate="2022-08-26T13:00:06.303" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38193" PostHistoryTypeId="1" PostId="12928" RevisionGUID="292079cb-b3b9-4479-afe9-73cc5b58cfc8" CreationDate="2022-08-26T13:00:06.303" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38194" PostHistoryTypeId="5" PostId="12923" RevisionGUID="1c8f0065-c834-4fca-95b1-d2012db9a79c" CreationDate="2022-08-26T16:25:45.597" UserId="17695" Comment="added 271 characters in body" Text="I have written a code to extend &quot;n&quot; points, constituting &quot;n-1&quot; lines ,to constitute more lines so you can map &quot;m&quot; data to &quot;m&quot; lines with m &gt; n-1.&#xD;&#xA;&#xD;&#xA;This is the function I wrote : https://github.com/embeddedmz/split_a_string_of_2d_line_segments/blob/d4137c087d0c2df1917f3b57170db96d81aca3b9/mainwindow.cpp#L137 It was really hard to write, I did it in 2019 with the VTK framework (coloring lines on a map background with data, there was not enough GeoJSON points) and I want to improve the code (the dot added towards the end is not precise).&#xD;&#xA;&#xD;&#xA;Has anyone ever coded something like this ?&#xD;&#xA;&#xD;&#xA;In my french blog post (you can translate it), I briefly describe what the algorithm is supposed to do: https://mmzoughi.wordpress.com/2022/08/22/decouper-une-chaine-de-segments-de-ligne-en-plusieurs-autres-segments-de-ligne/&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Update : the extended points with my function are the green points and the black points are the ones created with lightxbulb function (notice a black point at 0,0 that's a bug) :&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kSdRo.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/vO54R.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38204" PostHistoryTypeId="50" PostId="12366" RevisionGUID="046e60cc-90cc-4b38-950d-5039b72f8af6" CreationDate="2022-08-27T11:02:55.297" UserId="-1" />
  <row Id="38205" PostHistoryTypeId="2" PostId="12930" RevisionGUID="c7235c48-ba68-41dc-a93c-dc72c4a6cf84" CreationDate="2022-08-27T14:31:08.463" UserId="6041" Text="I am trying to proof the equality of **MSE=Var+Bias^2** but obvoisly I got something worng as they don't equal in my calculation:&#xD;&#xA;&#xD;&#xA;So here is the example. I use monte carlo to estimate this integral:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The value of this integral is 1. Assuming samples are computed from a uniform probability distribution my estimator is:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And the variance of the estimator can be analytically computed as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So Var here is the variance of the estimator, is that right? where, up to each iteration I calculate it as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;and in the code:&#xD;&#xA;&#xD;&#xA;    float Ie = sum / (i + 1); //estimator&#xD;&#xA;    float avg2 = sum2 / (i + 1);&#xD;&#xA;    float var = avg2 - (Ie * Ie);&#xD;&#xA;    var /= i + 1;&#xD;&#xA;&#xD;&#xA;and the bias is simply:&#xD;&#xA;&#xD;&#xA;    float bias2 = (trueValue - Ie);&#xD;&#xA;    bias2 *= bias2;&#xD;&#xA;&#xD;&#xA;Here is the full code:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    const int nsamp = 100;&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        float trueValue = 1;&#xD;&#xA;        float data[nsamp];&#xD;&#xA;        float sum = 0;&#xD;&#xA;    	float sum2=0;&#xD;&#xA;    	float mse = 0;&#xD;&#xA;    	float sqErr=0;&#xD;&#xA;    	&#xD;&#xA;        for (int i = 0; i &lt; nsamp; i++)&#xD;&#xA;        {&#xD;&#xA;            float x = rand1();&#xD;&#xA;            data[i] = 5 * x*x*x*x;&#xD;&#xA;            sum += data[i];&#xD;&#xA;            sum2 += data[i] * data[i]; &#xD;&#xA;    &#xD;&#xA;            float Ie = sum / (i + 1); //estimator&#xD;&#xA;            float avg2 = sum2 / (i + 1);&#xD;&#xA;            float var = avg2 - (Ie * Ie);&#xD;&#xA;            var /= i + 1;&#xD;&#xA;    		&#xD;&#xA;            float bias2 = (trueValue - Ie);&#xD;&#xA;            bias2 *= bias2;&#xD;&#xA;            &#xD;&#xA;            sqErr += (trueValue - Ie) * (trueValue - Ie);&#xD;&#xA;            mse = sqErr / (i+1);&#xD;&#xA;            &#xD;&#xA;            printf(&quot;\nI=%f Var=%f Bias2=%f MSE=%f&quot;, Ie, var, bias2, mse);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the output where the mse doesn't equal var+bias2:&#xD;&#xA;&#xD;&#xA;    I=0.000000 Var=0.000000 Bias2=1.000000 MSE=1.000000&#xD;&#xA;    I=0.252220 Var=0.031807 Bias2=0.559176 MSE=0.779588&#xD;&#xA;    I=0.170473 Var=0.018592 Bias2=0.688114 MSE=0.749097&#xD;&#xA;    I=0.662600 Var=0.192099 Bias2=0.113839 MSE=0.590282&#xD;&#xA;    I=0.647206 Var=0.123133 Bias2=0.124464 MSE=0.497118&#xD;&#xA;    I=0.583528 Var=0.088888 Bias2=0.173449 MSE=0.443174&#xD;&#xA;    I=0.510921 Var=0.069824 Bias2=0.239198 MSE=0.414034&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    I=0.984586 Var=0.001662 Bias2=0.000238 MSE=0.005417&#xD;&#xA;    I=0.983600 Var=0.001659 Bias2=0.000269 MSE=0.005411&#xD;&#xA;    I=0.982616 Var=0.001657 Bias2=0.000302 MSE=0.005406&#xD;&#xA;    I=0.985189 Var=0.001660 Bias2=0.000219 MSE=0.005401&#xD;&#xA;    I=0.984248 Var=0.001658 Bias2=0.000248 MSE=0.005396&#xD;&#xA;    I=0.983362 Var=0.001655 Bias2=0.000277 MSE=0.005391&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v82jg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M8bRC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ixwhk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/F6apv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38207" PostHistoryTypeId="1" PostId="12930" RevisionGUID="c7235c48-ba68-41dc-a93c-dc72c4a6cf84" CreationDate="2022-08-27T14:31:08.463" UserId="6041" Text="MSE &amp; Variance of Monte Carlo Estimator" ContentLicense="CC BY-SA 4.0" />
  <row Id="38208" PostHistoryTypeId="3" PostId="12930" RevisionGUID="c7235c48-ba68-41dc-a93c-dc72c4a6cf84" CreationDate="2022-08-27T14:31:08.463" UserId="6041" Text="|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38209" PostHistoryTypeId="5" PostId="12930" RevisionGUID="6c51546d-54a7-462c-8dce-858632f2db88" CreationDate="2022-08-27T14:52:02.253" UserId="6041" Comment="added 86 characters in body" Text="I am trying to proof the equality of **MSE=Var+Bias^2** but obvoisly I got something worng as they don't equal in my calculation:&#xD;&#xA;&#xD;&#xA;So here is the example. I use monte carlo to estimate this integral:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The value of this integral is 1. Assuming samples are computed from a uniform probability distribution my estimator is:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;And the variance of the estimator can be analytically computed as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So Var here is the variance of the estimator, is that right? where, up to each iteration I calculate it as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;and in the code:&#xD;&#xA;&#xD;&#xA;    float Ie = sum / (i + 1); //estimator&#xD;&#xA;    float avg2 = sum2 / (i + 1);&#xD;&#xA;    float var = avg2 - (Ie * Ie);&#xD;&#xA;    var /= i + 1;&#xD;&#xA;&#xD;&#xA;and the bias is simply:&#xD;&#xA;&#xD;&#xA;    float bias2 = (trueValue - Ie);&#xD;&#xA;    bias2 *= bias2;&#xD;&#xA;&#xD;&#xA;Here is the full code:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    const int nsamp = 100;&#xD;&#xA;    &#xD;&#xA;    float rand1()&#xD;&#xA;    {&#xD;&#xA;        return ((float)rand() / (float)RAND_MAX);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        float trueValue = 1;&#xD;&#xA;        float data[nsamp];&#xD;&#xA;        float sum = 0;&#xD;&#xA;    	float sum2=0;&#xD;&#xA;    	float mse = 0;&#xD;&#xA;    	float sqErr=0;&#xD;&#xA;    	&#xD;&#xA;        for (int i = 0; i &lt; nsamp; i++)&#xD;&#xA;        {&#xD;&#xA;            float x = rand1();&#xD;&#xA;            data[i] = 5 * x*x*x*x;&#xD;&#xA;            sum += data[i];&#xD;&#xA;            sum2 += data[i] * data[i]; &#xD;&#xA;    &#xD;&#xA;            float Ie = sum / (i + 1); //estimator&#xD;&#xA;            float avg2 = sum2 / (i + 1);&#xD;&#xA;            float var = avg2 - (Ie * Ie);&#xD;&#xA;            var /= i + 1;&#xD;&#xA;    		&#xD;&#xA;            float bias2 = (trueValue - Ie);&#xD;&#xA;            bias2 *= bias2;&#xD;&#xA;            &#xD;&#xA;            sqErr += (trueValue - Ie) * (trueValue - Ie);&#xD;&#xA;            mse = sqErr / (i+1);&#xD;&#xA;            &#xD;&#xA;            printf(&quot;\nI=%f Var=%f Bias2=%f MSE=%f&quot;, Ie, var, bias2, mse);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the output where the mse doesn't equal var+bias2:&#xD;&#xA;&#xD;&#xA;    I=0.000000 Var=0.000000 Bias2=1.000000 MSE=1.000000&#xD;&#xA;    I=0.252220 Var=0.031807 Bias2=0.559176 MSE=0.779588&#xD;&#xA;    I=0.170473 Var=0.018592 Bias2=0.688114 MSE=0.749097&#xD;&#xA;    I=0.662600 Var=0.192099 Bias2=0.113839 MSE=0.590282&#xD;&#xA;    I=0.647206 Var=0.123133 Bias2=0.124464 MSE=0.497118&#xD;&#xA;    I=0.583528 Var=0.088888 Bias2=0.173449 MSE=0.443174&#xD;&#xA;    I=0.510921 Var=0.069824 Bias2=0.239198 MSE=0.414034&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    I=0.984586 Var=0.001662 Bias2=0.000238 MSE=0.005417&#xD;&#xA;    I=0.983600 Var=0.001659 Bias2=0.000269 MSE=0.005411&#xD;&#xA;    I=0.982616 Var=0.001657 Bias2=0.000302 MSE=0.005406&#xD;&#xA;    I=0.985189 Var=0.001660 Bias2=0.000219 MSE=0.005401&#xD;&#xA;    I=0.984248 Var=0.001658 Bias2=0.000248 MSE=0.005396&#xD;&#xA;    I=0.983362 Var=0.001655 Bias2=0.000277 MSE=0.005391&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v82jg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M8bRC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ixwhk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/F6apv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38210" PostHistoryTypeId="2" PostId="12931" RevisionGUID="94cbccbd-629b-428e-9b46-0266a1afa029" CreationDate="2022-08-27T15:34:08.960" UserId="10096" Text="Here's a proof of the equality, it doesn't require choosing a specific function or numerical computations:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;E[(I_N - I)^2] &amp;= E[(I_N-E[I_N]+E[I_N]-I)^2] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2 + (E[I_N]-I)^2 + 2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2] + E[(E[I_N]-I)^2] + E[2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= Var[I_N] + (E[I_N]-I)^2 + 2(E[I_N]-E[I_N])(E[I_N]-I) \\&#xD;&#xA;&amp;= Var[I_N] + (Bias(I_N))^2 + 0&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;The 3rd line holds by linearity of $E$, the 4th holds because $E[I_N]-I$ is not a random variable. The last holds since by definition $Bias(I_N) = E[I_N] - I$." ContentLicense="CC BY-SA 4.0" />
  <row Id="38212" PostHistoryTypeId="5" PostId="12930" RevisionGUID="883bc510-1f23-449c-a391-b6324ee9afac" CreationDate="2022-08-27T16:07:34.753" UserId="6041" Comment="added 42 characters in body" Text="I am trying to prove the equality of $$\rm MSE=Var+Bias^2$$ but obviously I got something wrong as they don't equal in my calculation:&#xD;&#xA;&#xD;&#xA;So here is the example. I use monte carlo to estimate this integral:&#xD;&#xA;&#xD;&#xA;$$I = \int_0^1 5x^4~\mathrm dx$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The value of this integral is 1. Assuming samples are computed from a uniform probability distribution my estimator is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\langle I\rangle = \frac1N\sum _1^N 5x_i^4$$&#xD;&#xA;&#xD;&#xA;And the variance of the estimator can be analytically computed as:$$ \textrm{Var}(\langle I\rangle )= \frac1N\int _0^1(5x^4-1) ^2~\mathrm dx=\frac{16}{9N}$$&#xD;&#xA;&#xD;&#xA;So Var here is the variance of the estimator, is that right? where, up to each iteration I calculate it as:&#xD;&#xA;&#xD;&#xA;$$ \textrm{Var}(\langle I\rangle )= \frac{(\mathrm E[\langle I\rangle ^2] - \mathrm E[\langle I\rangle]^2) }{N}$$&#xD;&#xA;&#xD;&#xA;and in the code:&#xD;&#xA;&#xD;&#xA;    float Ie = sum / (i + 1); //estimator&#xD;&#xA;    float avg2 = sum2 / (i + 1);&#xD;&#xA;    float var = avg2 - (Ie * Ie);&#xD;&#xA;    var /= i + 1;&#xD;&#xA;&#xD;&#xA;and the bias is simply:&#xD;&#xA;&#xD;&#xA;    float bias2 = (trueValue - Ie);&#xD;&#xA;    bias2 *= bias2;&#xD;&#xA;&#xD;&#xA;Here is the full code:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    const int nsamp = 100;&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        float trueValue = 1;&#xD;&#xA;        float data[nsamp];&#xD;&#xA;        float sum = 0;&#xD;&#xA;    	float sum2=0;&#xD;&#xA;    	float mse = 0;&#xD;&#xA;    	float sqErr=0;&#xD;&#xA;    	&#xD;&#xA;        for (int i = 0; i &lt; nsamp; i++)&#xD;&#xA;        {&#xD;&#xA;            float x = rand1();&#xD;&#xA;            data[i] = 5 * x*x*x*x;&#xD;&#xA;            sum += data[i];&#xD;&#xA;            sum2 += data[i] * data[i]; &#xD;&#xA;    &#xD;&#xA;            float Ie = sum / (i + 1); //estimator&#xD;&#xA;            float avg2 = sum2 / (i + 1);&#xD;&#xA;            float var = avg2 - (Ie * Ie);&#xD;&#xA;            var /= i + 1;&#xD;&#xA;    		&#xD;&#xA;            float bias2 = (trueValue - Ie);&#xD;&#xA;            bias2 *= bias2;&#xD;&#xA;            &#xD;&#xA;            sqErr += (trueValue - Ie) * (trueValue - Ie);&#xD;&#xA;            mse = sqErr / (i+1);&#xD;&#xA;            &#xD;&#xA;            printf(&quot;\nI=%f Var=%f Bias2=%f MSE=%f&quot;, Ie, var, bias2, mse);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the output where the mse doesn't equal var+bias2:&#xD;&#xA;&#xD;&#xA;    I=0.000000 Var=0.000000 Bias2=1.000000 MSE=1.000000&#xD;&#xA;    I=0.252220 Var=0.031807 Bias2=0.559176 MSE=0.779588&#xD;&#xA;    I=0.170473 Var=0.018592 Bias2=0.688114 MSE=0.749097&#xD;&#xA;    I=0.662600 Var=0.192099 Bias2=0.113839 MSE=0.590282&#xD;&#xA;    I=0.647206 Var=0.123133 Bias2=0.124464 MSE=0.497118&#xD;&#xA;    I=0.583528 Var=0.088888 Bias2=0.173449 MSE=0.443174&#xD;&#xA;    I=0.510921 Var=0.069824 Bias2=0.239198 MSE=0.414034&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    I=0.984586 Var=0.001662 Bias2=0.000238 MSE=0.005417&#xD;&#xA;    I=0.983600 Var=0.001659 Bias2=0.000269 MSE=0.005411&#xD;&#xA;    I=0.982616 Var=0.001657 Bias2=0.000302 MSE=0.005406&#xD;&#xA;    I=0.985189 Var=0.001660 Bias2=0.000219 MSE=0.005401&#xD;&#xA;    I=0.984248 Var=0.001658 Bias2=0.000248 MSE=0.005396&#xD;&#xA;    I=0.983362 Var=0.001655 Bias2=0.000277 MSE=0.005391&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v82jg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M8bRC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ixwhk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/F6apv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38213" PostHistoryTypeId="5" PostId="12930" RevisionGUID="bf51c5f4-3ffc-4dde-a140-c4ccaf78166a" CreationDate="2022-08-27T17:28:17.090" UserId="6041" Comment="deleted 10 characters in body" Text="I am trying to prove the equality of $$\rm MSE=Var+Bias^2$$ but obviously I got something wrong as they don't equal in my calculation:&#xD;&#xA;&#xD;&#xA;So here is the example. I use monte carlo to estimate this integral:&#xD;&#xA;&#xD;&#xA;$$I = \int_0^1 5x^4~\mathrm dx$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The value of this integral is 1. Assuming samples are computed from a uniform probability distribution my estimator is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\langle I\rangle = \frac1N\sum _1^N 5x_i^4$$&#xD;&#xA;&#xD;&#xA;And the variance of the estimator can be analytically computed as:$$ \textrm{Var}(\langle I\rangle )= \frac1N\int _0^1(5x^4-1) ^2~\mathrm dx=\frac{16}{9N}$$&#xD;&#xA;&#xD;&#xA;So Var here is the variance of the estimator, is that right? where, up to each iteration I calculate it as:&#xD;&#xA;&#xD;&#xA;$$ \textrm{Var}(\langle I\rangle )= (\mathrm E[\langle I\rangle ^2] - \mathrm E[\langle I\rangle]^2) $$&#xD;&#xA;&#xD;&#xA;and in the code:&#xD;&#xA;&#xD;&#xA;    float Ie = sum / (i + 1); //estimator&#xD;&#xA;    float avg2 = sum2 / (i + 1);&#xD;&#xA;    float var = avg2 - (Ie * Ie);&#xD;&#xA;    var /= i + 1;&#xD;&#xA;&#xD;&#xA;and the bias is simply:&#xD;&#xA;&#xD;&#xA;    float bias2 = (trueValue - Ie);&#xD;&#xA;    bias2 *= bias2;&#xD;&#xA;&#xD;&#xA;Here is the full code:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    const int nsamp = 100;&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        float trueValue = 1;&#xD;&#xA;        float data[nsamp];&#xD;&#xA;        float sum = 0;&#xD;&#xA;    	float sum2=0;&#xD;&#xA;    	float mse = 0;&#xD;&#xA;    	float sqErr=0;&#xD;&#xA;    	&#xD;&#xA;        for (int i = 0; i &lt; nsamp; i++)&#xD;&#xA;        {&#xD;&#xA;            float x = rand1();&#xD;&#xA;            data[i] = 5 * x*x*x*x;&#xD;&#xA;            sum += data[i];&#xD;&#xA;            sum2 += data[i] * data[i]; &#xD;&#xA;    &#xD;&#xA;            float Ie = sum / (i + 1); //estimator&#xD;&#xA;            float avg2 = sum2 / (i + 1);&#xD;&#xA;            float var = avg2 - (Ie * Ie);&#xD;&#xA;            var /= i + 1;&#xD;&#xA;    		&#xD;&#xA;            float bias2 = (trueValue - Ie);&#xD;&#xA;            bias2 *= bias2;&#xD;&#xA;            &#xD;&#xA;            sqErr += (trueValue - Ie) * (trueValue - Ie);&#xD;&#xA;            mse = sqErr / (i+1);&#xD;&#xA;            &#xD;&#xA;            printf(&quot;\nI=%f Var=%f Bias2=%f MSE=%f&quot;, Ie, var, bias2, mse);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the output where the mse doesn't equal var+bias2:&#xD;&#xA;&#xD;&#xA;    I=0.000000 Var=0.000000 Bias2=1.000000 MSE=1.000000&#xD;&#xA;    I=0.252220 Var=0.031807 Bias2=0.559176 MSE=0.779588&#xD;&#xA;    I=0.170473 Var=0.018592 Bias2=0.688114 MSE=0.749097&#xD;&#xA;    I=0.662600 Var=0.192099 Bias2=0.113839 MSE=0.590282&#xD;&#xA;    I=0.647206 Var=0.123133 Bias2=0.124464 MSE=0.497118&#xD;&#xA;    I=0.583528 Var=0.088888 Bias2=0.173449 MSE=0.443174&#xD;&#xA;    I=0.510921 Var=0.069824 Bias2=0.239198 MSE=0.414034&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    I=0.984586 Var=0.001662 Bias2=0.000238 MSE=0.005417&#xD;&#xA;    I=0.983600 Var=0.001659 Bias2=0.000269 MSE=0.005411&#xD;&#xA;    I=0.982616 Var=0.001657 Bias2=0.000302 MSE=0.005406&#xD;&#xA;    I=0.985189 Var=0.001660 Bias2=0.000219 MSE=0.005401&#xD;&#xA;    I=0.984248 Var=0.001658 Bias2=0.000248 MSE=0.005396&#xD;&#xA;    I=0.983362 Var=0.001655 Bias2=0.000277 MSE=0.005391&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v82jg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M8bRC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ixwhk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/F6apv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38214" PostHistoryTypeId="5" PostId="12931" RevisionGUID="1105178c-ca79-4fbe-8688-868d00e6d449" CreationDate="2022-08-27T18:43:31.883" UserId="10096" Comment="added 1491 characters in body" Text="Here's a proof of the equality, it doesn't require choosing a specific function or numerical computations:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;E[(I_N - I)^2] &amp;= E[(I_N-E[I_N]+E[I_N]-I)^2] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2 + (E[I_N]-I)^2 + 2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2] + E[(E[I_N]-I)^2] + E[2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= Var[I_N] + (E[I_N]-I)^2 + 2(E[I_N]-E[I_N])(E[I_N]-I) \\&#xD;&#xA;&amp;= Var[I_N] + (Bias(I_N))^2 + 0&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;The 3rd line holds by linearity of $E$, the 4th holds because $E[I_N]-I$ is not a random variable. The last holds since by definition $Bias(I_N) = E[I_N] - I$.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;In your code you are not computing the variance or the bias, you are computing estimates of those. By definition the bias, variance, and MSE are:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;Bias(\langle I\rangle, I) = E[\langle I \rangle] - I \\&#xD;&#xA;Var(\langle I\rangle) = E[(\langle I \rangle - E[\langle I\rangle])^2] = E[(\langle I \rangle)^2] - (E[\langle I \rangle])^2 \\&#xD;&#xA;MSE(\langle I \rangle, I) = E[(\langle I \rangle - I)^2] = Var[\langle I \rangle] + (Bias(\langle I \rangle, I))^2&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Now let's look at what you are computing in your code. You obviously know the true solution $I=1$. However in code you only compute $\langle I \rangle = \frac{1}{N}\sum_{k=1}^N g(x_k)$ and not $E[\langle I \rangle]$. This means that you don't compute the squared bias $(E[\langle I \rangle] - I)^2$ but instead you computed $(\langle I \rangle - I)^2$. That alone already introduced approximation error. Then for an estimate of the variance you have used $\frac{1}{N}\left(\frac{1}{N}\sum_{k=1}^N (g(x))^2 - (\frac{1}{N}\sum_{k=1}^N g(x))^2\right)$, but note that this is not equal to the variance, it's an estimate of it. And it's even a biased estimate (you need Bessel's correction for example for an unbiased one).&#xD;&#xA;&#xD;&#xA;Either way it should be clear now that you never computed the expectations in the first place, so you never computed the variance, bias, and mse. At best you computed estimates of those, so it shouldn't be surprising that for the estimates the identity does not hold.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38215" PostHistoryTypeId="5" PostId="12931" RevisionGUID="ef603b12-9e79-4102-aa7e-3ee8d799775d" CreationDate="2022-08-27T19:03:32.827" UserId="10096" Comment="added 262 characters in body" Text="Here's a proof of the equality, it doesn't require choosing a specific function or numerical computations:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;E[(I_N - I)^2] &amp;= E[(I_N-E[I_N]+E[I_N]-I)^2] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2 + (E[I_N]-I)^2 + 2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2] + E[(E[I_N]-I)^2] + E[2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= Var[I_N] + (E[I_N]-I)^2 + 2(E[I_N]-E[I_N])(E[I_N]-I) \\&#xD;&#xA;&amp;= Var[I_N] + (Bias(I_N))^2 + 0&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;The 3rd line holds by linearity of $E$, the 4th holds because $E[I_N]-I$ is not a random variable. The last holds since by definition $Bias(I_N) = E[I_N] - I$.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;In your code you are not computing the variance or the bias, you are computing estimates of those. By definition the bias, variance, and MSE are:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;Bias(\langle I\rangle, I) = E[\langle I \rangle] - I \\&#xD;&#xA;Var(\langle I\rangle) = E[(\langle I \rangle - E[\langle I\rangle])^2] = E[(\langle I \rangle)^2] - (E[\langle I \rangle])^2 \\&#xD;&#xA;MSE(\langle I \rangle, I) = E[(\langle I \rangle - I)^2] = Var[\langle I \rangle] + (Bias(\langle I \rangle, I))^2&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Now let's look at what you are computing in your code. You obviously know the true solution $I=1$. However in code you only compute $\langle I \rangle = \frac{1}{N}\sum_{k=1}^N g(x_k)$ and not $E[\langle I \rangle]$. This means that you don't compute the squared bias $(E[\langle I \rangle] - I)^2$ but instead you computed $(\langle I \rangle - I)^2$. That alone already introduced approximation error. Then for an estimate of the variance you have used $\frac{1}{N}\left(\frac{1}{N}\sum_{k=1}^N (g(x))^2 - (\frac{1}{N}\sum_{k=1}^N g(x))^2\right)$, but note that this is not equal to the variance, it's an estimate of it. And it's even a biased estimate (you need Bessel's correction for example for an unbiased one).&#xD;&#xA;&#xD;&#xA;Finally let's address the elephant in the room: I don't think what you are doing for the MSE estimate makes any sense: &#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;mse = \frac{1}{N}\sum_{k=1}^N(I_k-I)^2&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Either way it should be clear now that you never computed the expectations in the first place, so you never computed the variance, bias, and mse. At best you computed estimates of those, so it shouldn't be surprising that for the estimates the identity does not hold.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38216" PostHistoryTypeId="5" PostId="12931" RevisionGUID="79290d58-65da-4737-83ed-aaae645a42b0" CreationDate="2022-08-27T19:12:07.417" UserId="10096" Comment="added 262 characters in body" Text="Here's a proof of the equality, it doesn't require choosing a specific function or numerical computations:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;E[(I_N - I)^2] &amp;= E[(I_N-E[I_N]+E[I_N]-I)^2] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2 + (E[I_N]-I)^2 + 2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= E[(I_N-E[I_N])^2] + E[(E[I_N]-I)^2] + E[2(I_N-E[I_N])(E[I_N]-I)] \\&#xD;&#xA;&amp;= Var[I_N] + (E[I_N]-I)^2 + 2(E[I_N]-E[I_N])(E[I_N]-I) \\&#xD;&#xA;&amp;= Var[I_N] + (Bias(I_N))^2 + 0&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;The 3rd line holds by linearity of $E$, the 4th holds because $E[I_N]-I$ is not a random variable. The last holds since by definition $Bias(I_N) = E[I_N] - I$.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;In your code you are not computing the variance or the bias, you are computing estimates of those. By definition the bias, variance, and MSE are:&#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;Bias(\langle I\rangle, I) = E[\langle I \rangle] - I \\&#xD;&#xA;Var(\langle I\rangle) = E[(\langle I \rangle - E[\langle I\rangle])^2] = E[(\langle I \rangle)^2] - (E[\langle I \rangle])^2 \\&#xD;&#xA;MSE(\langle I \rangle, I) = E[(\langle I \rangle - I)^2] = Var[\langle I \rangle] + (Bias(\langle I \rangle, I))^2&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;Now let's look at what you are computing in your code. You obviously know the true solution $I=1$. However in code you only compute $\langle I \rangle = \frac{1}{N}\sum_{k=1}^N g(x_k)$ and not $E[\langle I \rangle]$. This means that you don't compute the squared bias $(E[\langle I \rangle] - I)^2$ but instead you computed $(\langle I \rangle - I)^2$. That alone already introduced approximation error. Then for an estimate of the variance you have used $\frac{1}{N}\left(\frac{1}{N}\sum_{k=1}^N (g(x))^2 - (\frac{1}{N}\sum_{k=1}^N g(x))^2\right)$, but note that this is not equal to the variance, it's an estimate of it. And it's even a biased estimate (you need Bessel's correction for example for an unbiased one).&#xD;&#xA;&#xD;&#xA;Finally let's address the elephant in the room: I don't think what you are doing for the MSE estimate makes any sense: &#xD;&#xA;&#xD;&#xA;\begin{equation}&#xD;&#xA;mse = \frac{1}{N}\sum_{k=1}^N(I_k-I)^2&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;In fact I am fairly certain that the above &quot;estimator&quot; isn't even consistent (i.e. it doesn't even estimate the MSE), since if I make a large error at the beginning then it will stick around forever.&#xD;&#xA;&#xD;&#xA;Either way it should be clear now that you never computed the expectations in the first place, and just approximations of those, and the estimator for the mse that you wrote is wrong." ContentLicense="CC BY-SA 4.0" />
  <row Id="38217" PostHistoryTypeId="2" PostId="12932" RevisionGUID="9c718721-490d-46a1-8188-a2f9a7148e49" CreationDate="2022-08-27T20:16:29.427" UserId="18727" Text="I am creating different coloring patterns for my CPU raytracer, such as checker, gradient, ring, stripe pattern etc. The problems started when I tried to create a perturbation pattern (of a subpattern) based on Perlin noise function. The noise seems to work, **but not when the subpattern is rotated 45 degrees around Y (up in left-hand coordinate system)**. For example, 90 or -45 degree rotation works, too. Which is why I am very confused.&#xD;&#xA;&#xD;&#xA;The client code is:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;plane floor{&#xD;&#xA;        {},&#xD;&#xA;        material{.pattern = stripe_pattern{solid_pattern{1, 1, 1}, solid_pattern{0, 0, 0},&#xD;&#xA;                                           rotation&lt;Axis::Y&gt;(deg_to_rad(45)) * scale(.2, .2, .2)}}};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This defines a plane with a stripe pattern attached. The stripe pattern has two subpatterns (this is designed so that pattern nesting is possible), both return solid colors, white and black in this case. The stripe pattern is scaled down and rotated. The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Great. Now, let's try to apply Perlin noise to it:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;    plane floor{{},&#xD;&#xA;                material{.pattern = perturb_pattern{stripe_pattern{&#xD;&#xA;                             solid_pattern{1, 1, 1}, solid_pattern{0, 0, 0},&#xD;&#xA;                             rotation&lt;Axis::Y&gt;(deg_to_rad(45)) * scale(.2, .2, .2)}}}};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't see any difference:&#xD;&#xA;&#xD;&#xA;[![][2]][2]&#xD;&#xA;&#xD;&#xA;Now, let's rotate the stripe pattern 90 degrees instead of 45 and apply the noise:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;plane floor{{},&#xD;&#xA;                material{.pattern = perturb_pattern{stripe_pattern{&#xD;&#xA;                             solid_pattern{1, 1, 1}, solid_pattern{0, 0, 0},&#xD;&#xA;                             rotation&lt;Axis::Y&gt;(deg_to_rad(90)) * scale(.2, .2, .2)}}}};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Well, it did something:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Finally, let's try to crank up the Perlin noise coefficient (the default is `.2`):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;plane floor{{},&#xD;&#xA;                material{.pattern = perturb_pattern{&#xD;&#xA;                             stripe_pattern{solid_pattern{1, 1, 1}, solid_pattern{0, 0, 0},&#xD;&#xA;                                            rotation&lt;Axis::Y&gt;(deg_to_rad(90)) * scale(.2, .2, .2)},&#xD;&#xA;                             1}}};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And the result:&#xD;&#xA;&#xD;&#xA;[![][4]][4]&#xD;&#xA;&#xD;&#xA;So, as you can see, my implementation generally works okay with patterns and transformations. I also tested it with other patterns, and it works too. **The only case when it doesn't work is the 45-degree rotation transformation**. It just doesn't seem to do anything.&#xD;&#xA;&#xD;&#xA;Here is an attempt with 50 degrees and coefficient of 1, which makes the changes slightly visible:&#xD;&#xA;&#xD;&#xA;[![][5]][5]&#xD;&#xA;&#xD;&#xA;If I try this with `.2` instead of `1`, the changes are again invisible.&#xD;&#xA;&#xD;&#xA;Here is the definition of `perturb_pattern`:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;struct perturb_pattern {&#xD;&#xA;    class pattern pattern; // subpattern to apply Perlin noise to&#xD;&#xA;    float scale; // how much weight Perlin noise has on the resulting jitter&#xD;&#xA;    tform4 tform; // patterns can be transformed&#xD;&#xA;    tform4 inv_tform;&#xD;&#xA;&#xD;&#xA;    perturb_pattern(class pattern pattern, float scale = .2f) { /*...*/ }&#xD;&#xA;    perturb_pattern(class pattern pattern, tform4 tform, float scale = .2f) { /*...*/ }&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The code works as follows. In this particular case, for each world space point that can be traced from the screen pixel grid, its color is determined by calling the main dispatch function:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;color pattern_at(pattern const&amp; pattern, shape const&amp; shape, pnt3 const&amp; world_point) noexcept {&#xD;&#xA;    return pattern_at(pattern, inv_tform(pattern) * inv_tform(shape) * world_point);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;as `pattern_at(perturb_pattern, floor, point)`. This applies both shape and pattern transformations and then delegates to a particular pattern, in our case:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;color pattern_at(perturb_pattern const&amp; pattern, pnt3 const&amp; world_point) noexcept {&#xD;&#xA;    shape stub{stub_shape{}};&#xD;&#xA;    float jitter = perlin_noise(world_point.x, world_point.y, world_point.z);&#xD;&#xA;    return pattern_at(pattern.pattern, stub,&#xD;&#xA;                      {world_point.x + pattern.scale * jitter,&#xD;&#xA;                       world_point.y + pattern.scale * jitter,&#xD;&#xA;                       world_point.z + pattern.scale * jitter});&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here we calculate get the jitter in range `[0;1]` from Perlin noise function, scale it by some constant (`.2` by default, but we also tried `1` previously) and delegate the resulting point to subpattern's main dispatch function (see above), which this time applies subpattern's transformations. The `stub_shape` contains just an identity matrix. In our case, the subpattern is the `stripe_pattern`, and so `pattern_at(stripe_pattern, stub_shape, point)` calls `stripe_pattern`'s function:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;color pattern_at(stripe_pattern const&amp; pattern, pnt3 const&amp; world_point) noexcept {&#xD;&#xA;    shape stub{stub_shape{}};&#xD;&#xA;    if (int(std::floor(world_point.x)) % 2 == 0) {&#xD;&#xA;        return pattern_at(pattern.first, stub, world_point);&#xD;&#xA;    }&#xD;&#xA;    return pattern_at(pattern.second, stub, world_point);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Based on whether `point.x` is odd or even, the first or the second subpattern of `stripe_pattern` is used in a call to the main dispatch function. In our case, the innermost subpattern is the `solid_pattern`, so again, `pattern_at(solid_subpattern, stub_shape, point)` is called to apply transformations, which finally calls&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;color pattern_at(solid_pattern const&amp; pattern, pnt3 const&amp; /*unused*/) noexcept {&#xD;&#xA;    return pattern.color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and the single color is returned. I would like to stress that excluding Perlin noise this implementation works just fine with other patterns and subpatterns, and was provided for better understanding, there shouldn't be an error here.&#xD;&#xA;&#xD;&#xA;Now, here is my Perlin noise implementation. It is based on [the original implementation of improved Perlin noise](https://cs.nyu.edu/~perlin/noise/) with the `grad()` replaced by the one from [this](https://riven8192.blogspot.com/2010/08/calculate-perlinnoise-twice-as-fast.html) blog post.&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float perlin_noise(float x, float y, float z) noexcept;&#xD;&#xA;&#xD;&#xA;namespace {&#xD;&#xA;&#xD;&#xA;constexpr int p[] = {&#xD;&#xA;    151, 160, 137, 91,  90,  15,  131, 13,  201, 95,  96,  53,  194, 233, 7,   225, 140, 36,  103,&#xD;&#xA;    30,  69,  142, 8,   99,  37,  240, 21,  10,  23,  190, 6,   148, 247, 120, 234, 75,  0,   26,&#xD;&#xA;    197, 62,  94,  252, 219, 203, 117, 35,  11,  32,  57,  177, 33,  88,  237, 149, 56,  87,  174,&#xD;&#xA;    20,  125, 136, 171, 168, 68,  175, 74,  165, 71,  134, 139, 48,  27,  166, 77,  146, 158, 231,&#xD;&#xA;    83,  111, 229, 122, 60,  211, 133, 230, 220, 105, 92,  41,  55,  46,  245, 40,  244, 102, 143,&#xD;&#xA;    54,  65,  25,  63,  161, 1,   216, 80,  73,  209, 76,  132, 187, 208, 89,  18,  169, 200, 196,&#xD;&#xA;    135, 130, 116, 188, 159, 86,  164, 100, 109, 198, 173, 186, 3,   64,  52,  217, 226, 250, 124,&#xD;&#xA;    123, 5,   202, 38,  147, 118, 126, 255, 82,  85,  212, 207, 206, 59,  227, 47,  16,  58,  17,&#xD;&#xA;    182, 189, 28,  42,  223, 183, 170, 213, 119, 248, 152, 2,   44,  154, 163, 70,  221, 153, 101,&#xD;&#xA;    155, 167, 43,  172, 9,   129, 22,  39,  253, 19,  98,  108, 110, 79,  113, 224, 232, 178, 185,&#xD;&#xA;    112, 104, 218, 246, 97,  228, 251, 34,  242, 193, 238, 210, 144, 12,  191, 179, 162, 241, 81,&#xD;&#xA;    51,  145, 235, 249, 14,  239, 107, 49,  192, 214, 31,  181, 199, 106, 157, 184, 84,  204, 176,&#xD;&#xA;    115, 121, 50,  45,  127, 4,   150, 254, 138, 236, 205, 93,  222, 114, 67,  29,  24,  72,  243,&#xD;&#xA;    141, 128, 195, 78,  66,  215, 61,  156, 180, // and again&#xD;&#xA;    151, 160, 137, 91,  90,  15,  131, 13,  201, 95,  96,  53,  194, 233, 7,   225, 140, 36,  103,&#xD;&#xA;    30,  69,  142, 8,   99,  37,  240, 21,  10,  23,  190, 6,   148, 247, 120, 234, 75,  0,   26,&#xD;&#xA;    197, 62,  94,  252, 219, 203, 117, 35,  11,  32,  57,  177, 33,  88,  237, 149, 56,  87,  174,&#xD;&#xA;    20,  125, 136, 171, 168, 68,  175, 74,  165, 71,  134, 139, 48,  27,  166, 77,  146, 158, 231,&#xD;&#xA;    83,  111, 229, 122, 60,  211, 133, 230, 220, 105, 92,  41,  55,  46,  245, 40,  244, 102, 143,&#xD;&#xA;    54,  65,  25,  63,  161, 1,   216, 80,  73,  209, 76,  132, 187, 208, 89,  18,  169, 200, 196,&#xD;&#xA;    135, 130, 116, 188, 159, 86,  164, 100, 109, 198, 173, 186, 3,   64,  52,  217, 226, 250, 124,&#xD;&#xA;    123, 5,   202, 38,  147, 118, 126, 255, 82,  85,  212, 207, 206, 59,  227, 47,  16,  58,  17,&#xD;&#xA;    182, 189, 28,  42,  223, 183, 170, 213, 119, 248, 152, 2,   44,  154, 163, 70,  221, 153, 101,&#xD;&#xA;    155, 167, 43,  172, 9,   129, 22,  39,  253, 19,  98,  108, 110, 79,  113, 224, 232, 178, 185,&#xD;&#xA;    112, 104, 218, 246, 97,  228, 251, 34,  242, 193, 238, 210, 144, 12,  191, 179, 162, 241, 81,&#xD;&#xA;    51,  145, 235, 249, 14,  239, 107, 49,  192, 214, 31,  181, 199, 106, 157, 184, 84,  204, 176,&#xD;&#xA;    115, 121, 50,  45,  127, 4,   150, 254, 138, 236, 205, 93,  222, 114, 67,  29,  24,  72,  243,&#xD;&#xA;    141, 128, 195, 78,  66,  215, 61,  156, 180};&#xD;&#xA;&#xD;&#xA;float fade(float t) { return t * t * t * (t * (t * 6 - 15) + 10); }&#xD;&#xA;&#xD;&#xA;// https://riven8192.blogspot.com/2010/08/calculate-perlinnoise-twice-as-fast.html&#xD;&#xA;float grad(int hash, float x, float y, float z) {&#xD;&#xA;    switch (hash &amp; 0xF) {&#xD;&#xA;    case 0x0:&#xD;&#xA;        return x + y;&#xD;&#xA;    case 0x1:&#xD;&#xA;        return -x + y;&#xD;&#xA;    case 0x2:&#xD;&#xA;        return x - y;&#xD;&#xA;    case 0x3:&#xD;&#xA;        return -x - y;&#xD;&#xA;    case 0x4:&#xD;&#xA;        return x + z;&#xD;&#xA;    case 0x5:&#xD;&#xA;        return -x + z;&#xD;&#xA;    case 0x6:&#xD;&#xA;        return x - z;&#xD;&#xA;    case 0x7:&#xD;&#xA;        return -x - z;&#xD;&#xA;    case 0x8:&#xD;&#xA;        return y + z;&#xD;&#xA;    case 0x9:&#xD;&#xA;        return -y + z;&#xD;&#xA;    case 0xA:&#xD;&#xA;        return y - z;&#xD;&#xA;    case 0xB:&#xD;&#xA;        return -y - z;&#xD;&#xA;    case 0xC:&#xD;&#xA;        return y + x;&#xD;&#xA;    case 0xD:&#xD;&#xA;        return -y + z;&#xD;&#xA;    case 0xE:&#xD;&#xA;        return y - x;&#xD;&#xA;    case 0xF:&#xD;&#xA;        return -y - z;&#xD;&#xA;    default:&#xD;&#xA;        return 0; // never happens&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;} // namespace&#xD;&#xA;&#xD;&#xA;float perlin_noise(float x, float y, float z) noexcept {&#xD;&#xA;    float const floor_x = std::floor(x);&#xD;&#xA;    float const floor_y = std::floor(y);&#xD;&#xA;    float const floor_z = std::floor(z);&#xD;&#xA;&#xD;&#xA;    int const X = static_cast&lt;int&gt;(floor_x) &amp; 255;&#xD;&#xA;    int const Y = static_cast&lt;int&gt;(floor_y) &amp; 255;&#xD;&#xA;    int const Z = static_cast&lt;int&gt;(floor_z) &amp; 255;&#xD;&#xA;&#xD;&#xA;    x -= floor_x;&#xD;&#xA;    y -= floor_y;&#xD;&#xA;    z -= floor_z;&#xD;&#xA;&#xD;&#xA;    float const u = fade(x);&#xD;&#xA;    float const v = fade(y);&#xD;&#xA;    float const w = fade(z);&#xD;&#xA;&#xD;&#xA;    int const A = p[X] + Y;&#xD;&#xA;    int const AA = p[A] + Z;&#xD;&#xA;    int const AB = p[A + 1] + Z;&#xD;&#xA;    int const B = p[X + 1] + Y;&#xD;&#xA;    int const BA = p[B] + Z;&#xD;&#xA;    int const BB = p[B + 1] + Z;&#xD;&#xA;&#xD;&#xA;    return std::lerp(&#xD;&#xA;        std::lerp(std::lerp(grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z), u),&#xD;&#xA;                  std::lerp(grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z), u), v),&#xD;&#xA;        std::lerp(&#xD;&#xA;            std::lerp(grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1), u),&#xD;&#xA;            std::lerp(grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1), u),&#xD;&#xA;            v),&#xD;&#xA;        w);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The `std::lerp(a,b,t)` is the usual `a+t(b-a)`.&#xD;&#xA;&#xD;&#xA;[The whole project can be found on GitHub](https://github.com/hgkjshegfskef/wors_tracer), but these should be the only relevant parts.&#xD;&#xA;&#xD;&#xA;In general, **I am very confused why particularly 45 degree rotation is causing trouble**. Shouldn't all rotations cause trouble then? Shouldn't -45 degree rotation cause trouble then? Perhaps there is some corner case in the improved Perlin noise algorithm?&#xD;&#xA;&#xD;&#xA;For completeness, here is the result with **-45** degree rotation and again the &quot;mild&quot; `.2` coefficient:&#xD;&#xA;&#xD;&#xA;[![][6]][6]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zDEtw.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2ReuW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/mJ5E3.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/3X845.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/4odXo.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/nD9nP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38219" PostHistoryTypeId="1" PostId="12932" RevisionGUID="9c718721-490d-46a1-8188-a2f9a7148e49" CreationDate="2022-08-27T20:16:29.427" UserId="18727" Text="Perlin noise is mysteriously ignored when the pattern is rotated 45 degrees" ContentLicense="CC BY-SA 4.0" />
  <row Id="38220" PostHistoryTypeId="3" PostId="12932" RevisionGUID="9c718721-490d-46a1-8188-a2f9a7148e49" CreationDate="2022-08-27T20:16:29.427" UserId="18727" Text="|raytracing|transformations|c++|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38221" PostHistoryTypeId="5" PostId="12930" RevisionGUID="f1b79d83-073c-4c1b-980d-237b772002ea" CreationDate="2022-08-27T20:59:53.750" UserId="6041" Comment="added 56 characters in body" Text="I am trying to prove the equality of $$\rm MSE(\langle I\rangle)=Var(\langle I \rangle)+Bias(\langle I \rangle)^2$$ but obviously I got something wrong as they don't equal in my calculation:&#xD;&#xA;&#xD;&#xA;So here is the example. I use monte carlo to estimate this integral:&#xD;&#xA;&#xD;&#xA;$$I = \int_0^1 5x^4~\mathrm dx$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The value of this integral is 1. Assuming samples are computed from a uniform probability distribution my estimator is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$\langle I\rangle = \frac1N\sum _1^N 5x_i^4$$&#xD;&#xA;&#xD;&#xA;And the variance of the estimator can be analytically computed as:$$ \textrm{Var}(\langle I\rangle )= \frac1N\int _0^1(5x^4-1) ^2~\mathrm dx=\frac{16}{9N}$$&#xD;&#xA;&#xD;&#xA;So Var here is the variance of the estimator, is that right? where, up to each iteration I calculate it as:&#xD;&#xA;&#xD;&#xA;$$ \textrm{Var}(\langle I\rangle )= (\mathrm E[\langle I\rangle ^2] - \mathrm E[\langle I\rangle]^2) $$&#xD;&#xA;&#xD;&#xA;and in the code:&#xD;&#xA;&#xD;&#xA;    float Ie = sum / (i + 1); //estimator&#xD;&#xA;    float avg2 = sum2 / (i + 1);&#xD;&#xA;    float var = avg2 - (Ie * Ie);&#xD;&#xA;    var /= i + 1;&#xD;&#xA;&#xD;&#xA;and the bias is simply:&#xD;&#xA;&#xD;&#xA;    float bias2 = (trueValue - Ie);&#xD;&#xA;    bias2 *= bias2;&#xD;&#xA;&#xD;&#xA;Here is the full code:&#xD;&#xA;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    const int nsamp = 100;&#xD;&#xA;    &#xD;&#xA;    int main()&#xD;&#xA;    {&#xD;&#xA;        float trueValue = 1;&#xD;&#xA;        float data[nsamp];&#xD;&#xA;        float sum = 0;&#xD;&#xA;    	float sum2=0;&#xD;&#xA;    	float mse = 0;&#xD;&#xA;    	float sqErr=0;&#xD;&#xA;    	&#xD;&#xA;        for (int i = 0; i &lt; nsamp; i++)&#xD;&#xA;        {&#xD;&#xA;            float x = rand1();&#xD;&#xA;            data[i] = 5 * x*x*x*x;&#xD;&#xA;            sum += data[i];&#xD;&#xA;            sum2 += data[i] * data[i]; &#xD;&#xA;    &#xD;&#xA;            float Ie = sum / (i + 1); //estimator&#xD;&#xA;            float avg2 = sum2 / (i + 1);&#xD;&#xA;            float var = avg2 - (Ie * Ie);&#xD;&#xA;            var /= i + 1;&#xD;&#xA;    		&#xD;&#xA;            float bias2 = (trueValue - Ie);&#xD;&#xA;            bias2 *= bias2;&#xD;&#xA;            &#xD;&#xA;            sqErr += (trueValue - Ie) * (trueValue - Ie);&#xD;&#xA;            mse = sqErr / (i+1);&#xD;&#xA;            &#xD;&#xA;            printf(&quot;\nI=%f Var=%f Bias2=%f MSE=%f&quot;, Ie, var, bias2, mse);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And the output where the mse doesn't equal var+bias2:&#xD;&#xA;&#xD;&#xA;    I=0.000000 Var=0.000000 Bias2=1.000000 MSE=1.000000&#xD;&#xA;    I=0.252220 Var=0.031807 Bias2=0.559176 MSE=0.779588&#xD;&#xA;    I=0.170473 Var=0.018592 Bias2=0.688114 MSE=0.749097&#xD;&#xA;    I=0.662600 Var=0.192099 Bias2=0.113839 MSE=0.590282&#xD;&#xA;    I=0.647206 Var=0.123133 Bias2=0.124464 MSE=0.497118&#xD;&#xA;    I=0.583528 Var=0.088888 Bias2=0.173449 MSE=0.443174&#xD;&#xA;    I=0.510921 Var=0.069824 Bias2=0.239198 MSE=0.414034&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    .&#xD;&#xA;    I=0.984586 Var=0.001662 Bias2=0.000238 MSE=0.005417&#xD;&#xA;    I=0.983600 Var=0.001659 Bias2=0.000269 MSE=0.005411&#xD;&#xA;    I=0.982616 Var=0.001657 Bias2=0.000302 MSE=0.005406&#xD;&#xA;    I=0.985189 Var=0.001660 Bias2=0.000219 MSE=0.005401&#xD;&#xA;    I=0.984248 Var=0.001658 Bias2=0.000248 MSE=0.005396&#xD;&#xA;    I=0.983362 Var=0.001655 Bias2=0.000277 MSE=0.005391&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v82jg.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/M8bRC.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ixwhk.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/F6apv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38222" PostHistoryTypeId="2" PostId="12933" RevisionGUID="2a1fc6d2-b4b4-4f48-8e51-dca03bf1b25a" CreationDate="2022-08-28T05:52:26.163" UserId="6064" Text="Yes the raygen shader used here is correct for shooting rays inside the frustum given by the projection matrix(whose inverse is used here)." ContentLicense="CC BY-SA 4.0" />
  <row Id="38224" PostHistoryTypeId="6" PostId="12900" RevisionGUID="8270a948-0c6e-439b-8e5a-307175f91544" CreationDate="2022-08-28T05:53:33.383" UserId="2654" Comment="edited tags" Text="|raytracing|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38225" PostHistoryTypeId="5" PostId="12900" RevisionGUID="525d6efc-2527-4bdd-86a3-b2c893fd6dde" CreationDate="2022-08-28T05:54:24.717" UserId="6064" Comment="ading a small detail missed" Text="Hi I want to create a ray generation shader which traces rays inside a box frustum given by an Orthographic projection matrix(XMMatrixOrthographicLH) I use the following ray generation shader code:&#xD;&#xA;```&#xD;&#xA;struct RTConstants&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	matrix invproj;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;struct Simpleraypayload&#xD;&#xA;{&#xD;&#xA;	float3 outcol;&#xD;&#xA;};&#xD;&#xA;RWTexture2D&lt;float4&gt; outtex: register(u0);&#xD;&#xA;RaytracingAccelerationStructure basicas:register(t0);&#xD;&#xA;ConstantBuffer&lt;RTConstants&gt; rtconsts:register(b0);&#xD;&#xA;[shader(&quot;raygeneration&quot;)]&#xD;&#xA;void rgsmain()&#xD;&#xA;{&#xD;&#xA;Simpleraypayload payload;&#xD;&#xA;payload.outcol=float3(0.0f,0.0f,0.0f);&#xD;&#xA;RayDesc ray;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;ray.TMin=0.001f;&#xD;&#xA;ray.TMax=10.0f;&#xD;&#xA;ray.Direction=float3(0.0f,0.0f,-1.0f);&#xD;&#xA;	uint3 rayidx=DispatchRaysIndex();&#xD;&#xA;	uint3 raydims=DispatchRaysDimensions();&#xD;&#xA;	float2 clippointxy=rayidx.xy/float2(raydims.xy);&#xD;&#xA;	clippointxy=(clippointxy*2.0f)-float2(1.0f,1.0f);&#xD;&#xA;	float4 clippointnear=float4(clippointxy,0.0f,1.0f);&#xD;&#xA;	clippointnear=mul(rtconsts.invproj,clippointnear);clippointnear=clippointnear/clippointnear.w;&#xD;&#xA;	float4 clippointfar=float4(clippointxy,1.0f,1.0f);&#xD;&#xA;	clippointfar=mul(rtconsts.invproj,clippointfar);clippointfar=clippointfar/clippointfar.w;&#xD;&#xA;	ray.Origin=clippointnear.xyz;&#xD;&#xA;	ray.Direction=normalize(clippointfar.xyz-clippointnear.xyz);&#xD;&#xA;	TraceRay(basicas,RAY_FLAG_NONE,0xFF,0,0,0,ray,payload);&#xD;&#xA;	//flipping the output.&#xD;&#xA;	uint2 outindex=uint2(rayidx.x,raydims.y-rayidx.y);&#xD;&#xA;	&#xD;&#xA;	outtex[outindex]=float4(payload.outcol,1.0f);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;here &quot;invproj&quot; is the inverse of the ortho projection matrix for which we are trying to shootrays for.Am I right in using this rgs shader code for tracing all possible rays inside the frustum represented by the ortho matrix whose inverse I am using here?I have tested it for ortho projection only though.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="38226" PostHistoryTypeId="6" PostId="12900" RevisionGUID="525d6efc-2527-4bdd-86a3-b2c893fd6dde" CreationDate="2022-08-28T05:54:24.717" UserId="6064" Comment="ading a small detail missed" Text="|raytracing|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38227" PostHistoryTypeId="2" PostId="12934" RevisionGUID="c4c14798-a58d-4964-bf67-cf31bd648485" CreationDate="2022-08-28T11:40:39.850" UserId="6064" Text="Hi I have a confusion in dx pipeline what is the range for a vertex to be visible?&#xD;&#xA;&#xD;&#xA;Generally for a vertex to be visible vertex shader position output must be within -1 to 1 for both x &amp; y component and between 0 to 1 for z component but in the microsoft documents it shows a algo being used [![enter image description here][1]][1] here it says x &amp; y needs to be between -w &amp; w for x&amp;y component.&#xD;&#xA;Now I am confused vs output must be in what range to be visible?I understand that w component is usually kept 1.0f in vertex shader but that is not the case all the time(eg. when it holds the value for perspective devide).So can someoone clarify me which range is correct for vertex to be visible.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VvsqO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38229" PostHistoryTypeId="1" PostId="12934" RevisionGUID="c4c14798-a58d-4964-bf67-cf31bd648485" CreationDate="2022-08-28T11:40:39.850" UserId="6064" Text="what is the range for NDC coordinates to be visible in directx" ContentLicense="CC BY-SA 4.0" />
  <row Id="38230" PostHistoryTypeId="3" PostId="12934" RevisionGUID="c4c14798-a58d-4964-bf67-cf31bd648485" CreationDate="2022-08-28T11:40:39.850" UserId="6064" Text="|directx12|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38232" PostHistoryTypeId="2" PostId="12935" RevisionGUID="6a0e9754-f25f-4011-b785-2eacecba2736" CreationDate="2022-08-28T13:38:15.117" UserId="13273" Text="Like you said... When using a perspective projection, your 'w' can be !=1. Then before in front of the rasterizer, the vector will be devided by 'w'. After the devision the visible part is within 0 and 1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38238" PostHistoryTypeId="50" PostId="10535" RevisionGUID="32c008ed-8c8d-43d1-84bc-af5b1e386cd0" CreationDate="2022-08-28T23:06:55.553" UserId="-1" />
  <row Id="38240" PostHistoryTypeId="2" PostId="12937" RevisionGUID="ff0c7396-9eff-493f-a1dd-425ce980e26a" CreationDate="2022-08-29T02:07:12.870" UserId="18634" Text="I am writing a program to add a compute shader after rendering my image, and add a graphics pipeline after the compute shader to present the final image.&#xD;&#xA;I have a question though. How should I set the camera to be that of my original 3D scene instead of that of the second graphics pipeline. " ContentLicense="CC BY-SA 4.0" />
  <row Id="38242" PostHistoryTypeId="1" PostId="12937" RevisionGUID="ff0c7396-9eff-493f-a1dd-425ce980e26a" CreationDate="2022-08-29T02:07:12.870" UserId="18634" Text="adding a compute shader after a pipeline" ContentLicense="CC BY-SA 4.0" />
  <row Id="38243" PostHistoryTypeId="3" PostId="12937" RevisionGUID="ff0c7396-9eff-493f-a1dd-425ce980e26a" CreationDate="2022-08-29T02:07:12.870" UserId="18634" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38244" PostHistoryTypeId="2" PostId="12938" RevisionGUID="63fcc94a-bf0a-47e7-9b5f-ccc092137da7" CreationDate="2022-08-29T06:25:47.167" UserId="18824" Text="I have a SVG which contains rectangles with other shapes. How can I extract all rectangle details(co-ordinates, height and width)? Find below svg details where I kept only one rectangle for reference.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#xD;&#xA;&lt;svg width=&quot;301.36mm&quot; height=&quot;174.36mm&quot; viewBox=&quot;0 0 1139 659&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&#xD;&#xA;	&lt;g fill=&quot;none&quot; stroke=&quot;black&quot; stroke-width=&quot;1&quot; fill-rule=&quot;evenodd&quot; stroke-linecap=&quot;square&quot; stroke-linejoin=&quot;bevel&quot;&gt;&#xD;&#xA;		&lt;defs&gt;&#xD;&#xA;			&lt;clipPath id=&quot;clip27&quot;&gt;&#xD;&#xA;				&lt;path d=&quot;M-272.5,-2.5 L866.5,-2.5 L866.5,656.5 L-272.5,656.5 L-272.5,-2.5 z&quot;/&gt;&#xD;&#xA;			&lt;/clipPath&gt;&#xD;&#xA;		&lt;/defs&gt;&lt;g clip-path=&quot;url(#clip27)&quot; fill=&quot;none&quot; opacity=&quot;1&quot; stroke=&quot;#000000&quot; stroke-linecap=&quot;butt&quot; stroke-linejoin=&quot;miter&quot; stroke-miterlimit=&quot;2&quot; stroke-opacity=&quot;1&quot; stroke-width=&quot;1&quot; transform=&quot;matrix(1,0,0,1,272.5,2.5)&quot;&gt;&#xD;&#xA;			&lt;path d=&quot;M0,0 L110,0 L110,176 L0,176 L0,0 z&quot; fill-rule=&quot;evenodd&quot; vector-effect=&quot;none&quot;/&gt;&#xD;&#xA;		&lt;/g&gt;&#xD;&#xA;		&lt;defs&gt;&#xD;&#xA;			&lt;clipPath id=&quot;clip34&quot;&gt;&#xD;&#xA;				&lt;path d=&quot;M0,0 L112,0 L112,15 L0,15 L0,0 z&quot;/&gt;&#xD;&#xA;			&lt;/clipPath&gt;&#xD;&#xA;		&lt;/defs&gt;&lt;g clip-path=&quot;url(#clip34)&quot; fill=&quot;none&quot; opacity=&quot;1&quot; stroke=&quot;#000000&quot; stroke-linecap=&quot;square&quot; stroke-linejoin=&quot;bevel&quot; stroke-opacity=&quot;1&quot; stroke-width=&quot;1&quot; transform=&quot;matrix(1,0,0,1,271.07,180)&quot;&gt;&#xD;&#xA;			&lt;text fill=&quot;#000000&quot; fill-opacity=&quot;1&quot; font-family=&quot;Arial&quot; font-size=&quot;10&quot; font-style=&quot;normal&quot; font-weight=&quot;400&quot; stroke=&quot;none&quot; textLength=&quot;109.859&quot; x=&quot;1&quot; xml:space=&quot;preserve&quot; y=&quot;11&quot;&gt;BoostDiagSlow_Release&lt;/text&gt;&#xD;&#xA;		&lt;/g&gt;&#xD;&#xA;	&lt;/g&gt;&#xD;&#xA;&lt;/svg&gt;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="38246" PostHistoryTypeId="1" PostId="12938" RevisionGUID="63fcc94a-bf0a-47e7-9b5f-ccc092137da7" CreationDate="2022-08-29T06:25:47.167" UserId="18824" Text="How to programmatically extract all rectangle shapes from SVG file?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38247" PostHistoryTypeId="3" PostId="12938" RevisionGUID="63fcc94a-bf0a-47e7-9b5f-ccc092137da7" CreationDate="2022-08-29T06:25:47.167" UserId="18824" Text="|vector-graphics|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38251" PostHistoryTypeId="2" PostId="12940" RevisionGUID="784bc841-77a7-466d-aa80-d2ba5259a2ac" CreationDate="2022-08-29T11:45:39.657" UserId="18825" Text="Right now, if you want to use a GPU, you have to do it through graphics APIs like DirectX or Vulkan. These APIs are meant to be hardware-independent, but more often than not, they are tied to a specific platform (like DirectX for Windows, or Metal for iOS and macOS). The only modern graphics API which was designed to be cross-platform is Vulkan and even it is not supported by every platform. Both iOS and macOS don't support it (you have to use MoltenVK, but that's an API wrapper, not a driver implementation) and I'm assuming that neither PlayStation nor Xbox have support for it.&#xD;&#xA;&#xD;&#xA;It seems like we have solved the problem of hardware independence, but we've imposed the (artificial) problem of platform dependence. The hardware is doing the same thing no matter if it's in a Windows system or an Apple system. Wouldn't it be better if each GPU vendor provided their own graphics API?&#xD;&#xA;&#xD;&#xA;So, **my question is**: Why don't we have hardware-specific graphics APIs instead of platform-specific ones?&#xD;&#xA;&#xD;&#xA;Here's my reasoning for it...&#xD;&#xA;&#xD;&#xA;**More work for engine programmers**&#xD;&#xA;&#xD;&#xA;Let's say you are a game company and you want to make a game using your own game engine. And let's say you want to ship your game on PC and consoles. This means you want to support Windows, Xbox, and PlayStation. macOS and Linux aren't really a concern because not that many people game on them. The graphics APIs for Windows are DirectX and Vulkan (not counting OpenGL), for Xbox its DirectX (DX12 Ultimate *technically* is the same for Windows and Xbox), and for PlayStation, it's GNM (Sony's own proprietary graphics API). This means that if you wanted to write a rendering engine with as little effort as possible, you would, at the very least, have to support DirectX 12 and GNM.&#xD;&#xA;&#xD;&#xA;This doesn't seem that bad until you consider the fact that this is only the bare minimum. Many game engines also support Vulkan on Windows, not to mention that if you want to port your game to Mac or the Nintendo Switch you'll have to support even more APIs. &#xD;&#xA;&#xD;&#xA;Additionally, if you are writing a high-end rendering engine and you want to get the most out of your GPU, you'll need to do architecture-specific optimizations to shaders, which means having multiple variations of each shader, FOR EACH graphics API. You could write a shader translator so that you only need to write your shaders once, but then you get into other problems.&#xD;&#xA;&#xD;&#xA;**More work for driver implementers**&#xD;&#xA;&#xD;&#xA;On the other side, we have drivers. You have to support OpenGL, DirectX 11, DirectX 12, and Vulkan (all of these are just for Windows). If you provide hardware to Apple you also have to support Metal (although, Apple seem to be making their own hardware now so maybe they're not a concern anymore) and if you provide hardware for consoles, you also have to support their proprietary API. This becomes even worse when you consider the fact that drivers for mobile GPUs (e.g. for laptops and phones) and discrete GPUs are different.&#xD;&#xA;&#xD;&#xA;I don't think hardware vendors write a completely different driver for each API+platform+GPU combination, that would be insane! I'm guessing that drivers have their own internal API, or something similar, and each graphics API implementation is just wrapping around that internal API. However, this still leads to a massive amount of software, which ultimately means more bugs and more money spent on more developers.&#xD;&#xA;&#xD;&#xA;**The (possibly) ideal solution**&#xD;&#xA;&#xD;&#xA;I think it makes much more sense for hardware vendors to provide their own APIs. These APIs are tailor-made for their own GPUs. If your new GPUs behave differently than the older ones, you can just change the API to better fit the new GPUs instead of giving programmers hacky workarounds for existing APIs. I also think that these APIs should let programmers write in GPU assembly. Of course, I don't think programmers will write in GPU assembly most of the time, however, it gives them more freedom to do architecture-specific optimizations. &#xD;&#xA;&#xD;&#xA;One big problem with current graphics APIs is that they are hardware-independent. Why is that a problem? Because it means that everybody has to conform to the same interface. This isn't always bad. A well-designed API can be general enough that it suits everyone's needs, while also not being too restrictive. However, doing this means collaborating with multiple hardware manufacturers, which can take a lot of time. For example, look at how long it took for raytracing to land in Vulkan. The first raytracing cards came out near the end of 2018 and while raytracing was supported in Vulkan soon after, it was only through an NVIDIA-exclusive extension. The official, cross-vendor extension didn't come until 2020.&#xD;&#xA;&#xD;&#xA;Granted, I don't think current graphics APIs should be removed entirely. I think that the responsibility of implementing them should fall in the hands of the people who design/provide them, like Microsoft, Apple, or the Khronos Group, and not in the hands of hardware vendors. Instead of having custom implementations for each API in the driver, APIs like DirectX will be implemented at the application level using the publicly-available hardware-specific APIs provided by GPU vendors. This way, programmers who don't care a lot about performance or cutting-edge features, will still be able to use the current APIs.&#xD;&#xA;&#xD;&#xA;**The end (Finally!)**&#xD;&#xA;&#xD;&#xA;This seems like something someone working on graphics APIs would have thought of and since it seems like this approach is much better than the current one, I can't think of a reason why it hasn't happened yet. I expect that there must be a pretty good reason why this isn't the way we do things other than just &quot;we've always done things this way so why change it now&quot;, I just can't think of it!" ContentLicense="CC BY-SA 4.0" />
  <row Id="38253" PostHistoryTypeId="1" PostId="12940" RevisionGUID="784bc841-77a7-466d-aa80-d2ba5259a2ac" CreationDate="2022-08-29T11:45:39.657" UserId="18825" Text="Why can't we have hardware-specific graphics APIs?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38254" PostHistoryTypeId="3" PostId="12940" RevisionGUID="784bc841-77a7-466d-aa80-d2ba5259a2ac" CreationDate="2022-08-29T11:45:39.657" UserId="18825" Text="|gpu|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38255" PostHistoryTypeId="2" PostId="12941" RevisionGUID="a80e0e8d-a88d-4c04-bdfe-ddab33b728bf" CreationDate="2022-08-29T14:21:34.503" UserId="2654" Text="&gt; Wouldn't it be better if each GPU vendor provided their own graphics API?&#xD;&#xA;&#xD;&#xA;... no.&#xD;&#xA;&#xD;&#xA;First, the GPU doesn't belong to you. It belongs to the platform, the OS. In order for different programs to effectively share hardware resources, those programs have to talk to some intermediary that exists to ensure that no programs are completely starved of resources. Furthermore, there needs to be code to ensure that pathological use of the hardware resources resources can be dealt with.&#xD;&#xA;&#xD;&#xA;We know what platforms that don't have these kinds of things look like. One program that does something wrong can force a reboot of the system. The only way to prevent this is for someone to stand between programs and the hardware to make sure everybody plays by the rules.&#xD;&#xA;&#xD;&#xA;So regardless, there is going to be some platform-specific aspect of any of this. The platform is going to have to approve at least that there is a direct connection between a program and the driver.&#xD;&#xA;&#xD;&#xA;Second, developers benefit from having cross-hardware APIs, even platform-specific ones.&#xD;&#xA;&#xD;&#xA;Here's the thing. While Metal, D3D12, and Vulkan are different APIs, they're not all *that* different, structurally speaking. They all have command buffers, some object that represents the shader pipeline, similar ways of attaching resources, similar mechanisms for allocating memory and using it with objects, etc.&#xD;&#xA;&#xD;&#xA;By contrast, hardware-specific APIs will expose their particular hardware in substantially different ways. They will also expose specific details of their hardware that other APIs don't, which will make building hardware-neutral graphics programs incredibly difficult.&#xD;&#xA;&#xD;&#xA;To take an example, consider image layouts. This is a concept that Vulkan introduced almost entirely as an affordance to AMD's graphics hardware. Their hardware has a lot of layouts that restrict the use of images.&#xD;&#xA;&#xD;&#xA;Their OpenGL/D3D11 drivers would do the behind-the-scenes work to transition layouts as you changed how you used images. But the nature of a command-buffer API makes doing that highly impractical. Therefore, any command-buffer API built to handle AMD hardware must expose the basic concept of layouts to the user.&#xD;&#xA;&#xD;&#xA;But NVIDIA hardware has no such concept. Well, it does have similar concepts, but the GPU *itself* handles transitions automatically in most cases.&#xD;&#xA;&#xD;&#xA;So an AMD API would require you to use image layouts, and the NVIDIA version wouldn't. Any platform-neutral engine would have to figure out how to square this circle.&#xD;&#xA;&#xD;&#xA;Consider Mantle. It had no concept of UBOs (just read-only SSBOs) or a vertex fetching stage. This is because AMD's hardware of the day had no concept of those things either. But other hardware of the day *did* have those things. So that's another thing you would have to deal with.&#xD;&#xA;&#xD;&#xA;And that doesn't even *begin* to get into some of the more fundamental differences between a standard rendering GPU and a tile-based GPU.&#xD;&#xA;&#xD;&#xA;Eventually, developers would just build some kind of cross-hardware abstraction API. You know, like Vulkan.&#xD;&#xA;&#xD;&#xA;&gt; Additionally, if you are writing a high-end rendering engine and you want to get the most out of your GPU, you'll need to do architecture-specific optimizations to shaders, which means having multiple variations of each shader, FOR EACH graphics API.&#xD;&#xA;&#xD;&#xA;But you're going to have to do that work *regardless* of the API you're using. Optimizations based on architecture are based on the GPU architecture, not the graphics API.&#xD;&#xA;&#xD;&#xA;Windows boxes don't use the same GPUs as consoles. They may be similar to certain specific PC GPUs, but they're not the same. You're going to have to use specific optimizations for those specific GPUs anyway.&#xD;&#xA;&#xD;&#xA;Not to mention, there are so many PC GPUs anyway that if you're doing significant hardware-specific optimizations to your shader logic, you won't notice 2 more versions. And since you're doing development on consoles too, you're already going to have to build some mechanism to compile your shaders for different targets.&#xD;&#xA;&#xD;&#xA;This would be true if you were coding to the GPU; you'd just have *way more targets*, since each GPU core has changes to its internal machine code relative to previous generations of GPUs.&#xD;&#xA;&#xD;&#xA;&gt; For example, look at how long it took for raytracing to land in Vulkan. The first raytracing cards came out near the end of 2018 and while raytracing was supported in Vulkan soon after, it was only through an NVIDIA-exclusive extension. The official, cross-vendor extension didn't come until 2020.&#xD;&#xA;&#xD;&#xA;What's your point?&#xD;&#xA;&#xD;&#xA;If you were in 2019 and wanted to implement raytracing in a program, you were going to be limited to NVIDIA hardware anyway because... no *other GPUs* supported it. It took quite a long time for other GPUs to provide the feature. So relying on an NVIDIA extension is just normal.&#xD;&#xA;&#xD;&#xA;Furthermore, when that feature did land in Vulkan, it did so in a way that non-NVIDIA GPUs could also implement. And it did so at a time when non-NVIDIA GPUs actually existed that could use it." ContentLicense="CC BY-SA 4.0" />
  <row Id="38261" PostHistoryTypeId="5" PostId="12940" RevisionGUID="dfdf3afa-6c21-4cac-9199-3bd582187a18" CreationDate="2022-08-30T00:32:07.543" UserId="18825" Comment="added 498 characters in body" Text="Right now, if you want to use a GPU, you have to do it through graphics APIs like DirectX or Vulkan. These APIs are meant to be hardware-independent, but more often than not, they are tied to a specific platform (like DirectX for Windows, or Metal for iOS and macOS). The only modern graphics API which was designed to be cross-platform is Vulkan and even it is not supported by every platform. Both iOS and macOS don't support it (you have to use MoltenVK, but that's an API wrapper, not a driver implementation) and I'm assuming that neither PlayStation nor Xbox have support for it.&#xD;&#xA;&#xD;&#xA;It seems like we have solved the problem of hardware independence, but we've imposed the (artificial) problem of platform dependence. The hardware is doing the same thing no matter if it's in a Windows system or an Apple system. Wouldn't it be better if each GPU vendor provided their own graphics API?&#xD;&#xA;&#xD;&#xA;So, **my question is**: Why don't we have hardware-specific graphics APIs instead of platform-specific ones?&#xD;&#xA;&#xD;&#xA;Here's my reasoning for it...&#xD;&#xA;&#xD;&#xA;**More work for engine programmers**&#xD;&#xA;&#xD;&#xA;Let's say you are a game company and you want to make a game using your own game engine. And let's say you want to ship your game on PC and consoles. This means you want to support Windows, Xbox, and PlayStation. macOS and Linux aren't really a concern because not that many people game on them. The graphics APIs for Windows are DirectX and Vulkan (not counting OpenGL), for Xbox its DirectX (DX12 Ultimate *technically* is the same for Windows and Xbox), and for PlayStation, it's GNM (Sony's own proprietary graphics API). This means that if you wanted to write a rendering engine with as little effort as possible, you would, at the very least, have to support DirectX 12 and GNM.&#xD;&#xA;&#xD;&#xA;This doesn't seem that bad until you consider the fact that this is only the bare minimum. Many game engines also support Vulkan on Windows, not to mention that if you want to port your game to Mac or the Nintendo Switch you'll have to support even more APIs. &#xD;&#xA;&#xD;&#xA;Additionally, if you are writing a high-end rendering engine and you want to get the most out of your GPU, you'll need to do architecture-specific optimizations to shaders, which means having multiple variations of each shader, FOR EACH graphics API. You could write a shader translator so that you only need to write your shaders once, but then you get into other problems.&#xD;&#xA;&#xD;&#xA;**More work for driver implementers**&#xD;&#xA;&#xD;&#xA;On the other side, we have drivers. You have to support OpenGL, DirectX 11, DirectX 12, and Vulkan (all of these are just for Windows). If you provide hardware to Apple you also have to support Metal (although, Apple seem to be making their own hardware now so maybe they're not a concern anymore) and if you provide hardware for consoles, you also have to support their proprietary API. This becomes even worse when you consider the fact that drivers for mobile GPUs (e.g. for laptops and phones) and discrete GPUs are different.&#xD;&#xA;&#xD;&#xA;I don't think hardware vendors write a completely different driver for each API+platform+GPU combination, that would be insane! I'm guessing that drivers have their own internal API, or something similar, and each graphics API implementation is just wrapping around that internal API. However, this still leads to a massive amount of software, which ultimately means more bugs and more money spent on more developers.&#xD;&#xA;&#xD;&#xA;**The (possibly) ideal solution**&#xD;&#xA;&#xD;&#xA;I think it makes much more sense for hardware vendors to provide their own APIs. These APIs are tailor-made for their own GPUs. If your new GPUs behave differently than the older ones, you can just change the API to better fit the new GPUs instead of giving programmers hacky workarounds for existing APIs. I also think that these APIs should let programmers write in GPU assembly. Of course, I don't think programmers will write in GPU assembly most of the time, however, it gives them more freedom to do architecture-specific optimizations. &#xD;&#xA;&#xD;&#xA;One big problem with current graphics APIs is that they are hardware-independent. Why is that a problem? Because it means that everybody has to conform to the same interface. This isn't always bad. A well-designed API can be general enough that it suits everyone's needs, while also not being too restrictive. However, doing this means collaborating with multiple hardware manufacturers, which can take a lot of time. For example, look at how long it took for raytracing to land in Vulkan. The first raytracing cards came out near the end of 2018 and while raytracing was supported in Vulkan soon after, it was only through an NVIDIA-exclusive extension. The official, cross-vendor extension didn't come until 2020.&#xD;&#xA;&#xD;&#xA;Granted, I don't think current graphics APIs should be removed entirely. I think that the responsibility of implementing them should fall in the hands of the people who design/provide them, like Microsoft, Apple, or the Khronos Group, and not in the hands of hardware vendors. Instead of having custom implementations for each API in the driver, APIs like DirectX will be implemented at the application level using the publicly-available hardware-specific APIs provided by GPU vendors. This way, programmers who don't care a lot about performance or cutting-edge features, will still be able to use the current APIs.&#xD;&#xA;&#xD;&#xA;**The end (Finally!)**&#xD;&#xA;&#xD;&#xA;This seems like something someone working on graphics APIs would have thought of and since it seems like this approach is much better than the current one, I can't think of a reason why it hasn't happened yet. I expect that there must be a pretty good reason why this isn't the way we do things other than just &quot;we've always done things this way so why change it now&quot;, I just can't think of it!&#xD;&#xA;&#xD;&#xA;Edit: After reading the responses, I think I may have explained some things a bit poorly. In particular, I'm not suggesting that we remove all abstractions and have APIs that are extremely low level. They should still live in user-land and take advantage of things like sharing resources, scheduling, and TDR. What I'm suggesting is APIs similar to Vulkan or DirectX in terms of abstraction, but that are tied to specific hardware, not a specific platform.&#xD;&#xA;Anyway, thank you for the responses!" ContentLicense="CC BY-SA 4.0" />
  <row Id="38262" PostHistoryTypeId="52" PostId="12940" RevisionGUID="014a4a24-39dc-4b6a-9ba1-e67d04a2e252" CreationDate="2022-08-30T01:17:58.620" />
  <row Id="38263" PostHistoryTypeId="2" PostId="12943" RevisionGUID="af32ba4a-32a8-4efa-ac12-e30616fb668b" CreationDate="2022-08-30T12:31:36.223" UserId="18832" Text="In the early days of PC gaming, it was common for every game to ship with its own set of sound and graphics drivers. This had a number of drawbacks:&#xD;&#xA;&#xD;&#xA;* Every game developer had to write and maintain a large set of drivers, even though most games needed exactly the same facilities.&#xD;&#xA;* New hardware would have to list in its user manual which drivers from old software it was most likely to work with.&#xD;&#xA;* Smaller hardware vendors were forced to reverse-engineer their rivals interfaces from documentation, to make these existing drivers work.&#xD;&#xA;* The operating system could not take any control of these drivers to guarantee the security and stability of the system. MS-DOS essentially gave full control of the hardware to the game, and hoped for the best.&#xD;&#xA;&#xD;&#xA;This led to the development of what Windows 95 called &quot;virtual device drivers&quot; - rather than a driver interfacing each game to each piece of hardware, a single driver interfaces the OS to the hardware, and the game ships with a single adapter for the OS. In theory, this solves all the above problems:&#xD;&#xA;&#xD;&#xA;* The game developer only needs to write and maintain a single driver&#xD;&#xA;* New hardware can ship with a driver that installs into the OS, and immediately be available for all games&#xD;&#xA;* The OS interface is designed and documented for new drivers to be written implementing it&#xD;&#xA;* The OS can limit the access of games to keep the system secure and stable, and allow multiple pieces of software to share the hardware effectively&#xD;&#xA;&#xD;&#xA;Abstraction layers like DirectX, OpenGL, etc, work on the same principle: they act as an intermediary between the hardware-specific driver and the game-specific code.&#xD;&#xA;&#xD;&#xA;Note that is doesn't really matter whether Nvidia writes a GeForce driver for DirectX, or Microsoft writes a DirectX driver for GeForce; games written for DirectX can use it either way.&#xD;&#xA;&#xD;&#xA;As you've pointed out, it's not _quite_ as simple as that:&#xD;&#xA;&#xD;&#xA;* Games may wish to target more than one OS (or abstraction layer), so still need multiple drivers.&#xD;&#xA;* Games may wish to use cutting edge or unusual features of a particular piece of hardware, which the abstraction layer doesn't support.&#xD;&#xA;&#xD;&#xA;These two problems point in exactly opposite directions: the first suggests that there should be &quot;one abstraction to rule them all&quot;; the second suggests that abstractions should be fragmented into a huge range of device-specific functionality. &#xD;&#xA;&#xD;&#xA;Highly vendor-specific APIs might appeal to console developers with exclusive agreements to develop for a particular hardware and software platform; highly portable APIs will be more useful to indie developers who want to make their game available on multiple platforms as cheaply as possible. &#xD;&#xA;&#xD;&#xA;The result is that people will keep coming up with new abstractions, and extensions to those abstractions, to suit different situations. But ultimately, *somebody* has to write the code that makes the different combinations of game+OS+hardware possible." ContentLicense="CC BY-SA 4.0" />
  <row Id="38265" PostHistoryTypeId="2" PostId="12944" RevisionGUID="78403b36-21bb-4d6c-ab31-e0bc2397bb69" CreationDate="2022-08-30T12:37:49.840" UserId="18837" Text="**Featureful Versus Widely Available**&lt;br&gt;&#xD;&#xA;You're talking about the economics proposition of high functionality for limited subsets versus having a program (game, image processing, video processing) be widely available, independent of hardware.&#xD;&#xA;&#xD;&#xA;This can work but only if the features are compelling. This was the case very early on when there were a large number of graphics card providers and even a modest number of computer platform providers. Amiga with Video Toaster was one. So was Silicon Graphics with their advanced workstations.&#xD;&#xA;&#xD;&#xA;The problem is that, as technology advances, the common feature set accumulates enough weight to typically outweigh any comparatively small advantages offered by a specific competitor. Their only option is to provide a common driver with extra features that expose their specific advances to be taken advantage of. That allows program developers who want to the option to take advantage of those. The previous answer talks about ray tracing in NVIDIA hardware as a specific example.&#xD;&#xA;&#xD;&#xA;As a developer, I'm rarely going to choose a novel software package that requires significant work beyond a standard approach for several reasons. They all boil down to economics. I will have a hard time justifying paying the premium for the license and the extra work to my management. On top of that, the single vendor is likely to have serious bugs in their implementation that we have to cope with over the long haul. The benefits have to be very, very compelling to take on the risk and extra cost.&#xD;&#xA;&#xD;&#xA;The economy of scale pretty much demands that maturing technologies evolve towards a common API so that developers can easily switch between products. It's so well pronounced a phenomenon that it typically starts happening in less than ten years. Expect quantum computing to be the same way." ContentLicense="CC BY-SA 4.0" />
  <row Id="38267" PostHistoryTypeId="50" PostId="12384" RevisionGUID="b20b3b26-898c-49a3-844b-55e2eb4f89db" CreationDate="2022-08-30T17:02:25.180" UserId="-1" />
  <row Id="38268" PostHistoryTypeId="2" PostId="12945" RevisionGUID="3dffee9f-19fd-4ae3-a421-3effd45d9ddd" CreationDate="2022-08-30T18:19:52.930" UserId="8618" Text="I think a summary of other answers is: you would end up with current situation. On top of vendor-specific API you would implement some abstraction layer, which in the long run, with typical forces, would end up similar to current &quot;general&quot; APIs.&#xD;&#xA;&#xD;&#xA;Anyway, the world is complicated. &#xD;&#xA;&#xD;&#xA;I think current (rendering/compute) GPU architecture is close to Vulkan/Direct3D12 APIs, so perhaps internal APIs are not that different (I'm guessing). Also, much of what is hardware-specific is in extensions. And there are lots of them.&#xD;&#xA;&#xD;&#xA;But there are vendor-specific APIs: video encoding APIs. Current GPUs have video encoding and decoding chips. Each vendor has their own encoding API. For example, NVIDIA's [NVENC](https://developer.nvidia.com/nvidia-video-codec-sdk), AMD's [AMF](https://gpuopen.com/advanced-media-framework/), Intel's Quick Sync Video, and probably mobile GPUs too. And there are platform-specific video encoding APIs too! Such as VAAPI and VDPAU on linux, and recently Direct3D 12 Video.&#xD;&#xA;&#xD;&#xA;There is some information on low level access to GPU hardware. See for example [this question](https://computergraphics.stackexchange.com/questions/7809/what-does-gpu-assembly-look-like). AMD has [published details on their GPUs](https://developer.amd.com/resources/developer-guides-manuals/); [more info](https://rocmdocs.amd.com/en/latest/Programming_Guides/gcn-assembler.html). NVIDIA has their (compute) [CUDA API](https://developer.nvidia.com/cuda-zone).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38270" PostHistoryTypeId="5" PostId="12943" RevisionGUID="c78c3dd7-6cce-4ac7-9d7c-fe0c7d912a18" CreationDate="2022-08-30T21:48:44.843" UserId="18832" Comment="mention other software more explicitly" Text="In the early years of the PC, it was common for every game (and other piece of software that needed them) to ship with its own set of sound and graphics drivers. This had a number of drawbacks:&#xD;&#xA;&#xD;&#xA;* Every game developer had to write and maintain a large set of drivers, even though most games needed exactly the same facilities.&#xD;&#xA;* New hardware would have to list in its user manual which drivers from old software it was most likely to work with.&#xD;&#xA;* Smaller hardware vendors were forced to reverse-engineer their rivals interfaces from documentation, to make these existing drivers work.&#xD;&#xA;* The operating system could not take any control of these drivers to guarantee the security and stability of the system. MS-DOS essentially gave full control of the hardware to the game, and hoped for the best.&#xD;&#xA;&#xD;&#xA;This led to the development of what Windows 95 called &quot;virtual device drivers&quot; - rather than a driver interfacing each game to each piece of hardware, a single driver interfaces the OS to the hardware, and the game ships with a single adapter for the OS. In theory, this solves all the above problems:&#xD;&#xA;&#xD;&#xA;* The game developer only needs to write and maintain a single driver&#xD;&#xA;* New hardware can ship with a driver that installs into the OS, and immediately be available for all games&#xD;&#xA;* The OS interface is designed and documented for new drivers to be written implementing it&#xD;&#xA;* The OS can limit the access of games to keep the system secure and stable, and allow multiple pieces of software to share the hardware effectively&#xD;&#xA;&#xD;&#xA;Abstraction layers like DirectX, OpenGL, etc, work on the same principle: they act as an intermediary between the hardware-specific driver and the game-specific code.&#xD;&#xA;&#xD;&#xA;Note that is doesn't really matter whether Nvidia writes a GeForce driver for DirectX, or Microsoft writes a DirectX driver for GeForce; games written for DirectX can use it either way.&#xD;&#xA;&#xD;&#xA;As you've pointed out, it's not _quite_ as simple as that:&#xD;&#xA;&#xD;&#xA;* Games may wish to target more than one OS (or abstraction layer), so still need multiple drivers.&#xD;&#xA;* Games may wish to use cutting edge or unusual features of a particular piece of hardware, which the abstraction layer doesn't support.&#xD;&#xA;&#xD;&#xA;These two problems point in exactly opposite directions: the first suggests that there should be &quot;one abstraction to rule them all&quot;; the second suggests that abstractions should be fragmented into a huge range of device-specific functionality. &#xD;&#xA;&#xD;&#xA;Highly vendor-specific APIs might appeal to console developers with exclusive agreements to develop for a particular hardware and software platform; highly portable APIs will be more useful to indie developers who want to make their game available on multiple platforms as cheaply as possible. &#xD;&#xA;&#xD;&#xA;The result is that people will keep coming up with new abstractions, and extensions to those abstractions, to suit different situations. But ultimately, *somebody* has to write the code that makes the different combinations of game+OS+hardware possible." ContentLicense="CC BY-SA 4.0" />
  <row Id="38271" PostHistoryTypeId="2" PostId="12946" RevisionGUID="33e6aa76-14a9-418c-ad6f-524ef4600196" CreationDate="2022-08-30T21:58:54.583" UserId="18847" Text="I think the best example of a hardware-specific graphics API was [Glide][1], by 3dfx.  It was fairly common in the late 1990's.  If you owned one of their Voodoo Graphics cards, it was consistently the most performant way to play a game.&#xD;&#xA;&#xD;&#xA;There were a couple of issues with this:&#xD;&#xA;&#xD;&#xA; - It caused vendor lock-in (the best performance required specific hardware), which was good for 3dfx but not so much for the consumer.&#xD;&#xA; - It required more development effort from the game developers, as the rendering pipeline would have to target yet another API (and DirectX, OpenGL, and Software renderers were common options at the time, so this would add yet another code path and set of testing)&#xD;&#xA;&#xD;&#xA;Glide faded away when 3dfx did, as a result of questionable business choices by 3dfx coupled with Nvidia releasing superior hardware in their TNT2 and GeForce GPUs.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Glide_(API)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38273" PostHistoryTypeId="2" PostId="12947" RevisionGUID="e9a76b47-af8e-4110-be48-bc2d8f4c023a" CreationDate="2022-08-31T08:49:30.367" UserId="18851" Text="I read this article (https://developer.nvidia.com/content/depth-precision-visualized) about reverseZ and I'm confused about why is glClipControl necessary.Can't we juse modify ProjectionMatrix to make the depth in [0,1] and use glDepthRange(-1,1) to not do an extra (0.5* depth + 0.5) remapping before put it in the depth buffer?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tl4n4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38275" PostHistoryTypeId="1" PostId="12947" RevisionGUID="e9a76b47-af8e-4110-be48-bc2d8f4c023a" CreationDate="2022-08-31T08:49:30.367" UserId="18851" Text="Why need glClipControl-like extensions when implementing ReverseZ in opgl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38276" PostHistoryTypeId="3" PostId="12947" RevisionGUID="e9a76b47-af8e-4110-be48-bc2d8f4c023a" CreationDate="2022-08-31T08:49:30.367" UserId="18851" Text="|projections|depth-map|precision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38277" PostHistoryTypeId="2" PostId="12948" RevisionGUID="9b4babd5-c5e1-4173-8ca7-f099c85551cb" CreationDate="2022-08-31T14:12:04.543" UserId="2654" Text="The screenshot you posted states the answer:&#xD;&#xA;&#xD;&#xA;&gt; The value gets mapped into [0, 1] for storage in the depth buffer later, but that doesn't help, since the initial mapping to [-1, 1] has already destroyed all the precision in the far half of the range.&#xD;&#xA;&#xD;&#xA;That [-1, 1] mapping cannot be changed by your projection matrix or anything else. It is a fundamental part of the OpenGL-defined fixed-function transformation sequence. It's the transformation from clip-coordinates to NDC coordinates. NDC coordinates range from [-1, 1] (without `glClipControl`).&#xD;&#xA;&#xD;&#xA;Yes, you can use a projection matrix that maps the camera-space Z range to [1, 0] in NDC space. However, this creates two problems:&#xD;&#xA;&#xD;&#xA;1. This is done by using a clip space whose Z range is effectively [W, 0]. But OpenGL doesn't care what you *think* the range is; for GL, clip space is still [-W, W]. This means you will get *no clipping* in the [0, -W] parts of your scene. You can compensate for this by using a user-defined clip plane, but those aren't performance free.&#xD;&#xA;&#xD;&#xA;2. It doesn't actually fix the problem. The site you cited was written well after `glClipControl`, so it doesn't go into details for why this doesn't work. But [this blog post][1] was written beforehand, so it goes into those details.&#xD;&#xA;&#xD;&#xA;    Because OpenGL still thinks the NDC space Z range is [-1, 1], it is going to map that space to [Rn, Rf] in the window-space transform, where `Rn` and `Rf` are the `glDepthRange` near and far values. So the transformation to window-space depth is this: you halve the NDC Z value, scale up by the difference between Rn and Rf... and then add half of that difference to get the window-space Z.&#xD;&#xA;&#xD;&#xA;    And that addition is the problem. As stated on that site:&#xD;&#xA;&#xD;&#xA;    &gt; That 0.5 bias locks the floating point exponent and pretty much destroys any and all additional precision that the encoding of floating point values brings close to zero, since now there are just 24 bits of mantissa to handle the unfortunate 1/z shape.&#xD;&#xA;&#xD;&#xA;    That site suggests using a [-1, 1] depth range, but that's not allowed in unextended OpenGL. That's why it suggests `glDepthRangeNV`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="38279" PostHistoryTypeId="2" PostId="12949" RevisionGUID="47b8d012-3b51-4883-8bf9-dad6f48fe606" CreationDate="2022-08-31T22:23:58.667" UserId="18844" Text="A good deal of software is only available for a single platform (e.g., Android, iOS, Windows or Mac). The current situation means that authors of single-platform software only need to program for a single graphics API. &#xD;&#xA;&#xD;&#xA;If you're producing software for multiple platforms, you're already having to deal with differences between them. Adding multiple graphics APIs makes that situation worse, but not radically so. " ContentLicense="CC BY-SA 4.0" />
  <row Id="38281" PostHistoryTypeId="2" PostId="12950" RevisionGUID="09d6d098-f73a-44e5-a36c-c123cb3065fa" CreationDate="2022-09-01T07:27:00.953" UserId="18862" Text="[LMS Color Space][1] is based on responsivity of 3 cones in Human eyes with each having different curves. I'm looking for a way to plot those curves. Moreover, Is threre a way to covert wavelength under visible spectrum to RGB or XYZ colorspace?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/LMS_color_space#:~:text=LMS%20%28long%2C%20medium%2C%20short%29%2C%20is%20a%20color%20space,the%20lower%20end%20is%20generally%20bounded%20by%20zero." ContentLicense="CC BY-SA 4.0" />
  <row Id="38283" PostHistoryTypeId="1" PostId="12950" RevisionGUID="09d6d098-f73a-44e5-a36c-c123cb3065fa" CreationDate="2022-09-01T07:27:00.953" UserId="18862" Text="How do I plot tristimulus curves?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38284" PostHistoryTypeId="3" PostId="12950" RevisionGUID="09d6d098-f73a-44e5-a36c-c123cb3065fa" CreationDate="2022-09-01T07:27:00.953" UserId="18862" Text="|2d-graphics|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38285" PostHistoryTypeId="5" PostId="8769" RevisionGUID="f1a15a94-382b-4def-8f36-917629d38573" CreationDate="2022-09-01T21:27:52.157" UserId="171" Comment="added 94 characters in body" Text="The reduction of unwanted effects caused by the limited pixel grid or by the staircase effect." ContentLicense="CC BY-SA 4.0" />
  <row Id="38286" PostHistoryTypeId="24" PostId="8769" RevisionGUID="f1a15a94-382b-4def-8f36-917629d38573" CreationDate="2022-09-01T21:27:52.157" Comment="Proposed by 171 approved by 13095 edit id of 589" ContentLicense="CC BY-SA 4.0" />
  <row Id="38287" PostHistoryTypeId="5" PostId="12928" RevisionGUID="4d777111-0104-4d9e-9daf-b31c420caf3d" CreationDate="2022-09-02T00:35:15.020" UserId="171" Comment="added 117 characters in body" Text="Questions related to the massively parallel computing units targeting effective computer graphics in modern machines." ContentLicense="CC BY-SA 4.0" />
  <row Id="38288" PostHistoryTypeId="24" PostId="12928" RevisionGUID="4d777111-0104-4d9e-9daf-b31c420caf3d" CreationDate="2022-09-02T00:35:15.020" Comment="Proposed by 171 approved by 482 edit id of 588" ContentLicense="CC BY-SA 4.0" />
  <row Id="38289" PostHistoryTypeId="2" PostId="12951" RevisionGUID="41b15d5e-bafa-4b8a-bbb5-b7532785a09f" CreationDate="2022-09-02T10:57:23.903" UserId="18872" Text="I'm reading the book &quot;Multiple View Geometry in Computer Vision&quot; of Hartley and Zisserman. There was something I was unable to understand correctly. Here's the example where K denotes calibration matrix and w conic in image plane.:&#xD;&#xA;&#xD;&#xA;&gt; **Example 8.18.** A simple calibration device&#xD;&#xA;The image of three squares (on planes which are not parallel, but which need not be&#xD;&#xA;orthogonal) provides sufficiently many constraints to compute K. Consider one of the&#xD;&#xA;squares. The correspondences between its four corner points and their images define&#xD;&#xA;the homography H between the plane π of the square and the image. Applying this&#xD;&#xA;homography to circular points on π determines their images as H(1, ±i, 0) T . Thus we have two points on the (as yet unknown) ω. A similar procedure applied to the other squares generates a total of six points on ω, from which it may be computed (since five points are required to determine a conic). In outline the algorithm has the following steps:&#xD;&#xA;&#xD;&#xA;where the following steps are:&#xD;&#xA;1. For each square compute the homography H that maps its corner points,&#xD;&#xA;(0, 0) T , (1, 0) T , (0, 1) T , (1, 1) T , to their imaged points. (**The alignment of the plane coordinate system with the square is a similarity transformation and does not affect the position of the circular points on the plane**)&#xD;&#xA;2. Compute the imaged circular points for the plane of that square as H(1, ±i, 0) T .Writing H = [h 1 , h 2 , h 3 ], the imaged circular points are h 1 ± ih 2 . &#xD;&#xA;3. Fit a conic ω to the six imaged circular points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Why is the transformation in bold part &quot;**The alignment of the plane coordinate system with the square is a similarity transformation and does not affect the position of the circular points on the plane**&quot; (or H) supposed to be a similarity transformation (or matrix)? I thought imaging the real square here is **projective transformation** which is a more general case, not a similarity transformation. What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38291" PostHistoryTypeId="1" PostId="12951" RevisionGUID="41b15d5e-bafa-4b8a-bbb5-b7532785a09f" CreationDate="2022-09-02T10:57:23.903" UserId="18872" Text="Alignment of the plane coordinate system with the square is similarity transformation" ContentLicense="CC BY-SA 4.0" />
  <row Id="38292" PostHistoryTypeId="3" PostId="12951" RevisionGUID="41b15d5e-bafa-4b8a-bbb5-b7532785a09f" CreationDate="2022-09-02T10:57:23.903" UserId="18872" Text="|transformations|affine-transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38293" PostHistoryTypeId="5" PostId="12951" RevisionGUID="c7a5e691-c236-497b-984c-8447b6ff2c0b" CreationDate="2022-09-02T11:25:40.273" UserId="18872" Comment="deleted 29 characters in body" Text="I'm reading the book &quot;Multiple View Geometry in Computer Vision&quot; of Hartley and Zisserman. There was something I was unable to understand correctly. Here's the example where K denotes calibration matrix and w conic in image plane.:&#xD;&#xA;&#xD;&#xA;&gt; **Example 8.18.** A simple calibration device&#xD;&#xA;The image of three squares (on planes which are not parallel, but which need not be&#xD;&#xA;orthogonal) provides sufficiently many constraints to compute K. Consider one of the&#xD;&#xA;squares. The correspondences between its four corner points and their images define&#xD;&#xA;the homography H between the plane π of the square and the image. Applying this&#xD;&#xA;homography to circular points on π determines their images as H(1, ±i, 0) T . Thus we have two points on the (as yet unknown) ω. A similar procedure applied to the other squares generates a total of six points on ω, from which it may be computed (since five points are required to determine a conic). In outline the algorithm has the following steps:&#xD;&#xA;&gt; 1. For each square compute the homography H that maps its corner points,&#xD;&#xA;(0, 0) T , (1, 0) T , (0, 1) T , (1, 1) T , to their imaged points. (**The alignment of the plane coordinate system with the square is a similarity transformation and does not affect the position of the circular points on the plane**) &#xD;&#xA;&gt;2. Compute the imaged circular points for the plane of that square as H(1, ±i, 0) T .Writing H = [h 1 , h 2 , h 3 ], the imaged circular points are h 1 ± ih 2 . &#xD;&#xA;&gt;3. Fit a conic ω to the six imaged circular points.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Why is the transformation in bold part &quot;**The alignment of the plane coordinate system with the square is a similarity transformation and does not affect the position of the circular points on the plane**&quot; (or H) supposed to be a similarity transformation (or matrix)? I thought imaging the real square here is **projective transformation** which is a more general case, not a similarity transformation. What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38294" PostHistoryTypeId="50" PostId="12872" RevisionGUID="d754722b-77c4-4a51-83d0-4bcb9f612a77" CreationDate="2022-09-02T12:03:15.290" UserId="-1" />
  <row Id="38295" PostHistoryTypeId="5" PostId="12878" RevisionGUID="31aa0f7d-2b5b-4113-96b9-f29556ab4792" CreationDate="2022-09-02T12:04:54.200" UserId="13273" Comment="added 34 characters in body" Text="I want to improve my shadow mapping depth precision by getting the minimum and maximum depth value within my shadow map. When having both values I would convert the depth map to convolution shadow map basis functions and encode the values to 8bit each, which looses precision a lot, in case the depth span is high. &#xD;&#xA;&#xD;&#xA;Right now I render the scenario depth values into a R32F texture. A second shader checks for each pixel, if it is the min / max depth within the shadowmap by using SSBO and AtomicMax / AtomicMin.&#xD;&#xA;Then the next shader converts the depth values with respect to the min/max depth into the basis functions of convolution shadow mapping.&#xD;&#xA;&#xD;&#xA;Is there a way to get the minimum / maximum depth during the render pass of the scenario? If this is the case, I could skip the second shader.&#xD;&#xA;&#xD;&#xA;During the geometry rendering within the fragment shader I can get the depth value and use the AtomicMin / AtomixMax function. But when doing so, there can be the case (it happens very often) that fragments will be executed, which are behind other faces. so the max distance will be wrong at the end, which decreases the shadow map precision.&#xD;&#xA;&#xD;&#xA;I found the `layout(early_fragment_tests) in;` specification. But I am not sure if this will solve the problem. How does this specification work? Do you have other ideas?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38300" PostHistoryTypeId="5" PostId="12945" RevisionGUID="dd19d354-9b94-4bac-9234-298ec2fa4ea5" CreationDate="2022-09-02T13:38:03.560" UserId="8618" Comment="correction, based on comments" Text="I think a summary of other answers is: you would end up with current situation. On top of vendor-specific API you would implement some abstraction layer, which in the long run, with typical forces, would end up similar to current &quot;general&quot; APIs.&#xD;&#xA;&#xD;&#xA;Anyway, the world is complicated. &#xD;&#xA;&#xD;&#xA;I think current (rendering/compute) GPU architecture is close to Vulkan/Direct3D12 APIs, so perhaps internal APIs are not that different (I'm guessing). Also, much of what is hardware-specific is in extensions. And there are lots of them.&#xD;&#xA;&#xD;&#xA;But there are vendor-specific APIs: video encoding APIs. Current GPUs have video encoding and decoding chips. Each vendor has their own encoding API. For example, NVIDIA's [NVENC](https://developer.nvidia.com/nvidia-video-codec-sdk), AMD's [AMF](https://gpuopen.com/advanced-media-framework/), Intel's Quick Sync Video, and probably mobile GPUs too. And there are platform-specific video encoding APIs too! Such as VAAPI &lt;del&gt;and VDPAU&lt;/del&gt; on linux, and recently Direct3D 12 Video.&#xD;&#xA;&#xD;&#xA;There is some information on low level access to GPU hardware. See for example [this question](https://computergraphics.stackexchange.com/questions/7809/what-does-gpu-assembly-look-like). AMD has [published details on their GPUs](https://developer.amd.com/resources/developer-guides-manuals/); [more info](https://rocmdocs.amd.com/en/latest/Programming_Guides/gcn-assembler.html). NVIDIA has their (compute) [CUDA API](https://developer.nvidia.com/cuda-zone).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38307" PostHistoryTypeId="50" PostId="9426" RevisionGUID="ab6827d4-f1da-4324-ad48-efe28497ecb9" CreationDate="2022-09-03T15:01:55.120" UserId="-1" />
  <row Id="38308" PostHistoryTypeId="2" PostId="12954" RevisionGUID="7734daa7-1932-4793-a6ea-e355061d3bf5" CreationDate="2022-09-03T18:12:34.893" UserId="18876" Text="I am using c++. I have to find vertex normal in mesh. The mesh is triangle soup. I know that it is the sum of all faces normals arround the vertex. But I don't know how to set correct direction of faces (triangles) normals.&#xD;&#xA;I want to know for algorythm for this." ContentLicense="CC BY-SA 4.0" />
  <row Id="38310" PostHistoryTypeId="1" PostId="12954" RevisionGUID="7734daa7-1932-4793-a6ea-e355061d3bf5" CreationDate="2022-09-03T18:12:34.893" UserId="18876" Text="compiting vertex normals in in mesh triangle soup" ContentLicense="CC BY-SA 4.0" />
  <row Id="38311" PostHistoryTypeId="3" PostId="12954" RevisionGUID="7734daa7-1932-4793-a6ea-e355061d3bf5" CreationDate="2022-09-03T18:12:34.893" UserId="18876" Text="|c++|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38312" PostHistoryTypeId="4" PostId="12954" RevisionGUID="bc94e527-f0c4-44e2-9364-ca87421f3e08" CreationDate="2022-09-03T18:17:52.387" UserId="18876" Comment="edited title" Text="Compiting vertex normals in mesh triangle soup" ContentLicense="CC BY-SA 4.0" />
  <row Id="38313" PostHistoryTypeId="2" PostId="12955" RevisionGUID="d8815842-9e24-4124-8209-017e30c5f6cc" CreationDate="2022-09-03T21:42:18.270" UserId="48" Text="It seems to be referring to the fact that for any given square on a plane, you can set up coordinates on that plane that make the square's corners fall at (0,0), (1,0), (0,1), and (1,1). So when computing the homography H, you can safely specify that those four points are the corners. There is no need to set up any additional variables to represent, for instance, the translation or rotation of the square within the plane's coordinates.&#xD;&#xA;&#xD;&#xA;The transformation between two different Cartesian coordinate systems on the same plane would be a similarity transformation. Since similarity transformations don't affect the &quot;circular points&quot;, and the circular points are the only information about H that we need, the final result does not depend on what coordinate system we chose for the plane. So, we are free to choose one that is convenient.&#xD;&#xA;&#xD;&#xA;So, the text is illustrating that it doesn't matter where the square is on the plane, we can always move our coordinates to align with the square." ContentLicense="CC BY-SA 4.0" />
  <row Id="38315" PostHistoryTypeId="2" PostId="12956" RevisionGUID="05b6b16b-f1e7-4f8e-8812-0fd6ffc00c92" CreationDate="2022-09-03T22:15:58.360" UserId="48" Text="There is no way in general to know whether a fragment you're currently shading will make it into the final image or not. You could be rendering 10,000 different meshes, and the last one could cover up the first one. Early fragment tests won't solve that issue.&#xD;&#xA;&#xD;&#xA;Doing a post-pass over the image to find the min and max values is the right way to do it. There are, however, faster ways to accomplish this than atomic operations that try to reduce the whole image down to a single value in one step, as that will create a ton of contention.&#xD;&#xA;&#xD;&#xA;It will be better to calculate the min/max of smaller areas of the image in parallel, then recursively take the min/max of those results. For example, do a pass where each threadgroup reads an 8×8 tile of the original image, calculates the min/max over those (can be done quickly using subgroup operations) and then stores that out to an 8× smaller RG32F texture. Then repeat that until you get down to 1×1, kind of like building mipmaps, but you can reduce by a factor of 8 or more in each pass.&#xD;&#xA;&#xD;&#xA;See also: the AMD [Single Pass Downsample](https://github.com/GPUOpen-Effects/FidelityFX-SPD) library, which is a complex library but might be useful for ideas about this." ContentLicense="CC BY-SA 4.0" />
  <row Id="38322" PostHistoryTypeId="2" PostId="12958" RevisionGUID="8acd7395-a620-42c8-be76-1e10ddfd89fe" CreationDate="2022-09-04T09:17:43.960" UserId="8457" Text="I am generating a normal map for a texture for use in a PBR shader.  I have a map for the diffuse texture, and I am estimating the normal at each point using the derivative of the texture's brightness.  I store the result in a new texture and read the values out of it as a standard normal map.&#xD;&#xA;&#xD;&#xA;This is the method used by tools such as [SmartNormap](https://www.smart-page.net/smartnormal/).  It works quite well and I am happy with the quality of the result.&#xD;&#xA;&#xD;&#xA;However, there is a caveat.  In the same shader, I am also using a [hex tiling algorithm](https://www.shadertoy.com/view/MdyfDV) to generate an infinitely repeating, seamless output.  I currently run this algorithm on both the diffuse map as well as the normal map.  Since it is an expensive algorithm, this is causing a significant perf impact.&#xD;&#xA;&#xD;&#xA;To try to mitigate the perf impact and avoid the double lookups, I had the idea of generating the normal map on the fly within the fragment shader based on derivatives of the fragment colors.  I have created an implementation that looks something like this:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;float diffuseMagnitude = length(diffuseColor);&#xD;&#xA;float dDiffuseX = dFdx(diffuseMagnitude);&#xD;&#xA;float dDiffuseY = dFdy(diffuseMagnitude);&#xD;&#xA;&#xD;&#xA;float computeNormalBias = 0.1;&#xD;&#xA;vec3 mapN = normalize(vec3(&#xD;&#xA;  dDiffuseX,&#xD;&#xA;  dDiffuseY,&#xD;&#xA;  1.0 - ((computeNormalBias - 0.1) / 100.0)&#xD;&#xA;));&#xD;&#xA;mapN.xy *= normalScale;&#xD;&#xA;&#xD;&#xA;normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here is what the results looks like for that.&#xD;&#xA;&#xD;&#xA;Before:&#xD;&#xA;&#xD;&#xA;![](https://ameo.link/u/acj.png)&#xD;&#xA;&#xD;&#xA;After:&#xD;&#xA;&#xD;&#xA;![](https://ameo.link/u/ack.png)&#xD;&#xA;&#xD;&#xA;You may have to expand the images to see the impact in more detail.&#xD;&#xA;&#xD;&#xA;This does work and I find it to be a great improvement, but there is a rather severe issue.  Since these derivatives are computed in screen space, the world space distance between pixels can become quite large at higher distances and sharp angles of incidence with the camera.  This results in severe aliasing when moving in certain directions.&#xD;&#xA;&#xD;&#xA;Demo video: https://ameo.link/u/bcafbfde12486f95388b5c448db2c1dbb037f9b4.mp4&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;I think I understand the reason this issue issue is happening, but I don't know how to solve it - or if it's even possible to solve it.&#xD;&#xA;&#xD;&#xA;Normally, I'd solve aliasing by oversampling, but there's no way to really oversample when using the `dFdx`/`dFdy` functions that I know of.&#xD;&#xA;&#xD;&#xA;I know that my use of that expensive anti-tiling algorithm really limit things but it's very important to my use case and I can't do without it.  If I am unable to find a solution with this dynamic normal generation idea, I will probably go back to pre-generating normal maps and doing the double lookups and then turning it off in low detail mode or something similar.&#xD;&#xA;&#xD;&#xA;If anyone has any ideas or pointers, though, I'd love to hear them!" ContentLicense="CC BY-SA 4.0" />
  <row Id="38324" PostHistoryTypeId="1" PostId="12958" RevisionGUID="8acd7395-a620-42c8-be76-1e10ddfd89fe" CreationDate="2022-09-04T09:17:43.960" UserId="8457" Text="Is it possible to reduce aliasing in derivatives used to estimate normals from a texture?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38325" PostHistoryTypeId="3" PostId="12958" RevisionGUID="8acd7395-a620-42c8-be76-1e10ddfd89fe" CreationDate="2022-09-04T09:17:43.960" UserId="8457" Text="|glsl|antialiasing|normal-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38326" PostHistoryTypeId="5" PostId="12954" RevisionGUID="0232474a-04fe-471b-b1ad-19838d2d3412" CreationDate="2022-09-04T09:25:38.480" UserId="18876" Comment="added 34 characters in body" Text="I am using c++. I have to find vertex normal in mesh. The mesh is triangle soup. the winding order is inconsistent I know that it is the sum of all faces normals arround the vertex. But I don't know how to set correct direction of faces (triangles) normals.&#xD;&#xA;I want to know for algorythm for this." ContentLicense="CC BY-SA 4.0" />
  <row Id="38327" PostHistoryTypeId="5" PostId="12954" RevisionGUID="1a3c5c91-a9a8-436c-bd51-c5f2b7647ead" CreationDate="2022-09-04T09:56:00.337" UserId="18876" Comment="added 1 character in body" Text="I am using c++. I have to find vertex normal in mesh. The mesh is triangle soup. The winding order is inconsistent. I know that it is the sum of all faces normals arround the vertex. But I don't know how to set correct direction of faces (triangles) normals.&#xD;&#xA;I want to know for algorythm for this." ContentLicense="CC BY-SA 4.0" />
  <row Id="38333" PostHistoryTypeId="2" PostId="12960" RevisionGUID="81cdf156-1b85-4404-b979-7a04d9dde99e" CreationDate="2022-09-04T14:37:24.237" UserId="7952" Text="A very simple, but computationally expensive, way to do this is to pick a triangle, preferably one that you know has the winding you want.&#xD;&#xA;&#xD;&#xA;Then search every triangle in the soup for triangles that share an edge with the chosen triangle.&#xD;&#xA;&#xD;&#xA;For every triangle that shares an edge, check that its winding is the same as the chosen triangle. The winding is the same iff the ordering of the vertices on the shared edge are the same. If the ordering is different swap the order of any two vertices on the found triangle.&#xD;&#xA;&#xD;&#xA;Remove found triangles from the original set as they are discovered.&#xD;&#xA;&#xD;&#xA;Wash rinse repeat. &#xD;&#xA;&#xD;&#xA;It is usually easiest to implement this algorithm using indexed triangles, it is straight forward to index a set of vertices. (1:iterate over every vertex and assign a new index to only those that are unique, then 2:iterate over every triangle and assign an index from the index pool created in step 1. )&#xD;&#xA;&#xD;&#xA;One nice thing about this algorithm is there are extra &quot;whistle while you work&quot; things that can be done to check the integrity of the polyhedron.&#xD;&#xA;&#xD;&#xA;1) Keep a count of edges that don't share an edge with any other triangle. At the end if this number is non-zero then the polyhedron is not &quot;water tight&quot;. This can be a good starting point for making the polyhedron water tight.&#xD;&#xA;&#xD;&#xA;2) It is possible to have triangles that are not connected to the original chosen triangle, meaning the soup is either inconsistent, or defines multiple polyhedrons. &#xD;&#xA;&#xD;&#xA;Lastly, this algorithm is so easy to code up it can be used to compare other more advance techniques against. " ContentLicense="CC BY-SA 4.0" />
  <row Id="38337" PostHistoryTypeId="2" PostId="12961" RevisionGUID="1f3854af-5b76-4752-a7d8-8cf079a909ce" CreationDate="2022-09-05T06:50:54.320" UserId="18108" Text="Given 3D mesh with a closed surface. (solid object without hole).&#xD;&#xA;&#xD;&#xA;I'm looking for an algorithm to accurately calculate its volume.&#xD;&#xA;&#xD;&#xA;My current idea I is to voxelize the mesh and count it by voxel, But this would give me a pretty rough estimation.&#xD;&#xA;&#xD;&#xA;Any suggestion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38339" PostHistoryTypeId="1" PostId="12961" RevisionGUID="1f3854af-5b76-4752-a7d8-8cf079a909ce" CreationDate="2022-09-05T06:50:54.320" UserId="18108" Text="How to calculate volume of any given 3D mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="38340" PostHistoryTypeId="3" PostId="12961" RevisionGUID="1f3854af-5b76-4752-a7d8-8cf079a909ce" CreationDate="2022-09-05T06:50:54.320" UserId="18108" Text="|algorithm|mesh|volumetric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38341" PostHistoryTypeId="5" PostId="12961" RevisionGUID="89bb7513-8dea-4dd7-afd6-04c4971bbb14" CreationDate="2022-09-05T07:16:15.303" UserId="18108" Comment="added 160 characters in body" Text="Given 3D mesh with a closed surface. (solid object without hole).&#xD;&#xA;&#xD;&#xA;I'm looking for an algorithm to calculate its volume.&#xD;&#xA;&#xD;&#xA;There are several ideas, Such as&#xD;&#xA;- Voxelized and count voxels&#xD;&#xA;- Point cloud and Monte-carlo integration to find the point inside the mesh.&#xD;&#xA;&#xD;&#xA;I didn't know yet if these are possible but it would give me a pretty rough estimation.\&#xD;&#xA;So I'd like to have an accurate analysis approach.&#xD;&#xA;&#xD;&#xA;Any suggestion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38342" PostHistoryTypeId="4" PostId="12954" RevisionGUID="d04d6546-7592-468b-8fa2-84be185ac484" CreationDate="2022-09-05T07:51:31.930" UserId="209" Comment="fixed typo in title - might make it easier for others to find" Text="Computing vertex normals in mesh triangle soup" ContentLicense="CC BY-SA 4.0" />
  <row Id="38343" PostHistoryTypeId="2" PostId="12962" RevisionGUID="2e65ec68-e7da-434b-bb5e-d09d00c9bc83" CreationDate="2022-09-05T08:14:22.020" UserId="9438" Text="The [Shoelace Formula][1] can be extended to 3D by using tetrahedrons instead of triangles.&#xD;&#xA;&#xD;&#xA;1. Pick a point, Any point can be used, even one of the original vertices of the mesh (although a point outside the mesh is what I tend to go for).&#xD;&#xA;2. For each triangle, construct a tetrahedron using the triangle vertices and this chosen point, and calculate the volume of this tetrahedron.&#xD;&#xA;3. Assuming mesh triangles are CCW wound, sum all the volumes of tets with CCW winding, and subtract the volumes of the tetrahedrons with CW winding (if your mesh uses CW winding, then add all these volumes together and subtract volumes of tets which are CCW).&#xD;&#xA;&#xD;&#xA;Calculating the determinent of the tetrahedron is useful since it can be used to deduce both the volume, and winding of a tetrahedron.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shoelace_formula" ContentLicense="CC BY-SA 4.0" />
  <row Id="38345" PostHistoryTypeId="5" PostId="12962" RevisionGUID="d029df0d-f03a-4607-952f-1c215a4f5c65" CreationDate="2022-09-05T08:49:23.767" UserId="9438" Comment="deleted 3 characters in body" Text="The [Shoelace Formula][1] can be extended to 3D by using tetrahedrons instead of triangles.&#xD;&#xA;&#xD;&#xA;1. Pick a point, Any point can be used, even one of the original vertices of the mesh (personally I tend to use the x,y,z min of the mesh AABB).&#xD;&#xA;2. For each triangle, construct a tetrahedron using the triangle vertices and this chosen point, and calculate the volume of this tetrahedron.&#xD;&#xA;3. Assuming mesh triangles are CCW wound, sum all the volumes of tets with CCW winding, and subtract the volumes of the tetrahedrons with CW winding (if your mesh uses CW winding, then add all these volumes together and subtract volumes of tets which are CCW).&#xD;&#xA;&#xD;&#xA;Calculating the determinent of the tetrahedron is useful since it can be used to deduce both the volume, and winding of a tetrahedron.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shoelace_formula" ContentLicense="CC BY-SA 4.0" />
  <row Id="38346" PostHistoryTypeId="5" PostId="12962" RevisionGUID="f5ec9ce4-58a8-4b2e-bea8-1357a4ee10f5" CreationDate="2022-09-05T09:03:01.413" UserId="9438" Comment="added 21 characters in body" Text="The triangle form of the [Shoelace Formula][1] can be extended to 3D by using tetrahedrons instead of triangles.&#xD;&#xA;&#xD;&#xA;1. Pick a point, Any point can be used, even one of the original vertices of the mesh (personally I tend to use the x,y,z min of the mesh AABB).&#xD;&#xA;2. For each triangle, construct a tetrahedron using the triangle vertices and this chosen point, and calculate the volume of this tetrahedron.&#xD;&#xA;3. Assuming mesh triangles are CCW wound, sum all the volumes of tets with CCW winding, and subtract the volumes of the tetrahedrons with CW winding (if your mesh uses CW winding, then add all these volumes together and subtract volumes of tets which are CCW).&#xD;&#xA;&#xD;&#xA;Calculating the determinent of the tetrahedron is useful since it can be used to deduce both the volume, and winding of a tetrahedron.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shoelace_formula" ContentLicense="CC BY-SA 4.0" />
  <row Id="38347" PostHistoryTypeId="52" PostId="12961" RevisionGUID="676bf604-1362-47fa-8521-d89b823e5c5f" CreationDate="2022-09-05T14:51:03.347" />
  <row Id="38348" PostHistoryTypeId="5" PostId="12446" RevisionGUID="4b7f888a-d3e9-45e7-8358-088f0a1924e4" CreationDate="2022-09-05T16:28:37.427" UserId="17813" Comment="corrected reference" Text="[![milk jug from thesis][1]][1]&#xD;&#xA;&#xD;&#xA;The little milk pitcher / jug in [Martin Newell][2]'s 1975 PhD thesis [“The Utilization of Procedure Models in Digital Image Synthesis”][3], does anybody have the bicubic patch data for it?  The teapot's data ([in several early versions][4]) is well-distributed of course, [the spoon and cup/saucer are downloadable][5] from a few repositories.  But (so far) [I can't find the milk jug's][6].&#xD;&#xA;&#xD;&#xA;Is it lost forever, or is somebody out there willing / able to make it available?&#xD;&#xA;&#xD;&#xA;[![Figure 29  Table Setting][7]][7]&#xD;&#xA;&#xD;&#xA;**Edited to add:**  for the purposes of the bounty I need patch data that when added properly to add_mesh_teapot.py produces a mesh substantially similar to “Figure 26  Meshes Defining a Jug” above, with [provenance][8] (at minimum, a description of how the data came into the answerer's possession that won't be significantly contradicted).&#xD;&#xA;&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;Above image is a screenshot of [Blender][10] using [a version of add_mesh_teapot.py that's had the teacup &amp; saucer patch data added to it][11].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rySjW.jpg&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Martin_Newell_(computer_scientist)&#xD;&#xA;  [3]: https://collections.lib.utah.edu/ark:/87278/s6hh73p6&#xD;&#xA;  [4]: http://www.holmes3d.net/graphics/teapot/&#xD;&#xA;  [5]: https://github.com/rm-hull/newell-teapot&#xD;&#xA;  [6]: https://blenderartists.org/t/how-do-i-propose-an-addition-to-the-extra-objects-add-on/1351462/16&#xD;&#xA;  [7]: https://i.stack.imgur.com/bJvNG.jpg&#xD;&#xA;  [8]: https://en.wikipedia.org/wiki/Provenance&#xD;&#xA;  [9]: https://i.stack.imgur.com/wPT18.jpg&#xD;&#xA;  [10]: https://en.wikipedia.org/wiki/Blender_(software)&#xD;&#xA;  [11]: https://blenderartists.org/t/how-do-i-propose-an-addition-to-the-extra-objects-add-on/1351462/22" ContentLicense="CC BY-SA 4.0" />
  <row Id="38351" PostHistoryTypeId="5" PostId="12962" RevisionGUID="ce3c5b32-f61d-49a4-ae63-ecc9f115f0a7" CreationDate="2022-09-06T09:39:48.547" UserId="9438" Comment="added 5 characters in body" Text="The triangle form of the [Shoelace Formula][1] can be extended to 3D by using tetrahedrons instead of triangles.&#xD;&#xA;&#xD;&#xA;1. Pick a point, Any point can be used, even one of the original vertices of the mesh (personally I tend to use the x,y,z min of the mesh AABB).&#xD;&#xA;2. For each triangle, construct a tetrahedron using the triangle vertices and this chosen point, and calculate the volume of this tetrahedron.&#xD;&#xA;3. Assuming mesh triangles are CCW wound, sum all the volumes of tets with CCW winding, and subtract the volumes of the tetrahedrons with CW winding (if your mesh uses CW winding, then add all the CW tet volumes together and subtract volumes of tets which are CCW).&#xD;&#xA;&#xD;&#xA;Calculating the determinent of the tetrahedron is useful since it can be used to deduce both the volume, and winding of a tetrahedron.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Shoelace_formula" ContentLicense="CC BY-SA 4.0" />
  <row Id="38352" PostHistoryTypeId="5" PostId="12935" RevisionGUID="207ae552-d227-4eca-ae01-c2d51f922cd3" CreationDate="2022-09-06T14:56:14.233" UserId="13273" Comment="added 157 characters in body" Text="Like you said... When using a perspective projection, your 'w' can be !=1. &#xD;&#xA;Between the vertex pocess stages (Vertex, Tessellation control, Tessellation evaluation, geometry) and the Fragment shader, the position vector gets divided by its `w` component (this is part of the render pipeline). As result everything between -1 and 1 for `x` and `y` and everything between 0 and 1 for `z` is visible." ContentLicense="CC BY-SA 4.0" />
  <row Id="38353" PostHistoryTypeId="2" PostId="12964" RevisionGUID="aa955d2e-5cbf-412c-b49b-94c82beeffb8" CreationDate="2022-09-06T17:25:17.790" UserId="7918" Text="I've written a small software rasterizer using OpenCL and would like to optimize and parallelize it more, currently I'm scanning the whole screen and see if the triangle overlaps with the pixels..&#xD;&#xA;&#xD;&#xA;I would like to parallelize the loop and do it more efficiently. For example in my idea, is to process only the bounding box pixels.. ? [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    __kernel void sendImageToPBO(__global uchar4* dst_buffer, __global float* vbo, int vbosize,&#xD;&#xA;        __global int* ibo, int ibosize)&#xD;&#xA;    &#xD;&#xA;    {&#xD;&#xA;        size_t blockIdx = get_group_id(0);&#xD;&#xA;        size_t blockIdy = get_group_id(1);&#xD;&#xA;        size_t blockDimX = get_local_size(0);&#xD;&#xA;        size_t blockDimY = get_local_size(1);&#xD;&#xA;        size_t threadIdX = get_local_id(0);&#xD;&#xA;        size_t threadIdY = get_local_id(1);&#xD;&#xA;    &#xD;&#xA;        float3 c0 = { 1, 0, 0 };&#xD;&#xA;        float3 c1 = { 0, 1, 0 };&#xD;&#xA;        float3 c2 = { 0, 0, 1 };&#xD;&#xA;    &#xD;&#xA;        int x = get_global_id(0);&#xD;&#xA;        int y= get_global_id(1);&#xD;&#xA;     &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        int imageWidth = 800;&#xD;&#xA;        int imageHeight = 800;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        if (x &lt; vbosize &amp;&amp; y &lt; vbosize)&#xD;&#xA;        {&#xD;&#xA;    &#xD;&#xA;            for (int i = 0; i &lt; vbosize; i += 9)&#xD;&#xA;            {&#xD;&#xA;                float3 v1 = (float3)(vbo[i], vbo[i + 1], vbo[i + 2]);&#xD;&#xA;                float3 v0 = (float3)(vbo[i + 3], vbo[i + 4], vbo[i + 5]);&#xD;&#xA;                float3 v2 = (float3)(vbo[i + 6], vbo[i + 7], vbo[i + 8]);&#xD;&#xA;    &#xD;&#xA;                float xmin = fmin(v0.x, fmin(v1.x, v2.x));&#xD;&#xA;                float ymin = fmin(v0.y, fmin(v1.y, v2.y));&#xD;&#xA;                float xmax = fmax(v0.x, fmin(v1.x, v2.x));&#xD;&#xA;                float ymax = fmax(v0.y, fmin(v1.y, v2.y));&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;                // be careful xmin/xmax/ymin/ymax can be negative. Don't cast to unsigned int&#xD;&#xA;                unsigned int x0 = max(0, (int)(floor(xmin)));&#xD;&#xA;                unsigned int x1 = min((int)(imageWidth)-1, (int)(floor(xmax)));&#xD;&#xA;                unsigned int y0 = max(0, (int)(floor(ymin)));&#xD;&#xA;                unsigned int y1 = min((int)(imageHeight)-1, (int)(floor(ymax)));&#xD;&#xA;                &#xD;&#xA;                float3 p = { x + 0.5f, y + 0.5f, 0 };&#xD;&#xA;    &#xD;&#xA;                float w0 = edgeFunction(v1, v2, p);&#xD;&#xA;                float w1 = edgeFunction(v2, v0, p);&#xD;&#xA;                float w2 = edgeFunction(v0, v1, p);&#xD;&#xA;                if (w0 &gt;= 0 &amp;&amp; w1 &gt;= 0 &amp;&amp; w2 &gt;= 0) {&#xD;&#xA;    &#xD;&#xA;                    float area = edgeFunction(v0, v1, v2);&#xD;&#xA;    &#xD;&#xA;                    float r = w0 * c0.x + w1 * c1.x + w2 * c2.x;&#xD;&#xA;                    float g = w0 * c0.y + w1 * c1.y + w2 * c2.y;&#xD;&#xA;                    float b = w0 * c0.z + w1 * c1.z + w2 * c2.z;&#xD;&#xA;    &#xD;&#xA;                    w0 /= area;&#xD;&#xA;                    w1 /= area;&#xD;&#xA;                    w2 /= area;&#xD;&#xA;                    float z = 1 / (w0 * v0.z + w1 * v1.z + w2 * v2.z);&#xD;&#xA;                    r *= z, g *= z, b *= z;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;                    dst_buffer[y * get_global_size(0) + x] = (uchar4)(r * 255, g * 255, b * 255, 255);&#xD;&#xA;                }&#xD;&#xA;                &#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HBHG5.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38355" PostHistoryTypeId="1" PostId="12964" RevisionGUID="aa955d2e-5cbf-412c-b49b-94c82beeffb8" CreationDate="2022-09-06T17:25:17.790" UserId="7918" Text="parallelizing a software rasterizer algorithm using opencl" ContentLicense="CC BY-SA 4.0" />
  <row Id="38356" PostHistoryTypeId="3" PostId="12964" RevisionGUID="aa955d2e-5cbf-412c-b49b-94c82beeffb8" CreationDate="2022-09-06T17:25:17.790" UserId="7918" Text="|opengl|c++|opencl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38360" PostHistoryTypeId="5" PostId="12960" RevisionGUID="143dc572-3738-4958-9992-427fd97145bf" CreationDate="2022-09-07T15:47:26.270" UserId="6" Comment="deleted 1 character in body" Text="A very simple, but computationally expensive, way to do this is to pick a triangle, preferably one that you know has the winding you want.&#xD;&#xA;&#xD;&#xA;Then search every triangle in the soup for triangles that share an edge with the chosen triangle.&#xD;&#xA;&#xD;&#xA;For every triangle that shares an edge, check that its winding is the same as the chosen triangle. The winding is the same iff the ordering of the vertices on the shared edge are the same. If the ordering is different swap the order of any two vertices on the found triangle.&#xD;&#xA;&#xD;&#xA;Remove found triangles from the original set as they are discovered.&#xD;&#xA;&#xD;&#xA;Wash rinse repeat. &#xD;&#xA;&#xD;&#xA;It is usually easiest to implement this algorithm using indexed triangles, it is straight forward to index a set of vertices. (1:iterate over every vertex and assign a new index to only those that are unique, then 2:iterate over every triangle and assign an index from the index pool created in step 1.)&#xD;&#xA;&#xD;&#xA;One nice thing about this algorithm is there are extra &quot;whistle while you work&quot; things that can be done to check the integrity of the polyhedron.&#xD;&#xA;&#xD;&#xA;1) Keep a count of edges that don't share an edge with any other triangle. At the end if this number is non-zero then the polyhedron is not &quot;water tight&quot;. This can be a good starting point for making the polyhedron water tight.&#xD;&#xA;&#xD;&#xA;2) It is possible to have triangles that are not connected to the original chosen triangle, meaning the soup is either inconsistent, or defines multiple polyhedrons. &#xD;&#xA;&#xD;&#xA;Lastly, this algorithm is so easy to code up it can be used to compare other more advance techniques against. " ContentLicense="CC BY-SA 4.0" />
  <row Id="38361" PostHistoryTypeId="5" PostId="8598" RevisionGUID="8de53827-2c9f-4d91-9bfa-71bbf260203c" CreationDate="2022-09-07T15:59:06.317" UserId="6" Comment="deleted 157 characters in body" Text="What `GL_LUMINANCE` as a texture format actually does is store one component of data per pixel that is used for the red, green and blue color components. So, a classic greyscale image (It doesn't use it for the alpha component, though, that's why there was also `GL_LUMINANCE_ALPHA` for two compnent storage and `GL_INTENSITY` that broadcasts it to all components).&#xD;&#xA;&#xD;&#xA;When using shaders you don't actually need this distinction anymore, though, since you can do the swizzling yourself in the shader. So you just use a proper typed 1-component internal format, most probably `GL_R8` (i.e. 8-bit normalized fixed point red) in your case, but depending on your exact data type requirements really. And for setting it you would (in that case) use `GL_RED` as the format of the data in your RAM storage. So something like:&#xD;&#xA;&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, &lt;width&gt;, &lt;height&gt;, 0, GL_RED, &lt;type&gt;, &lt;data&gt;);&#xD;&#xA;&#xD;&#xA;And in the shader you can do with that red color component whatever you want. If you just need a single value per pixel, you use that. If you need a grey color (i.e. `GL_LUMINANCE` behaviour), you swizzle it to the RGB components, and if you need it as color and opacity, you swizzle it into all four components. Or whatever else you want to do.&#xD;&#xA;&#xD;&#xA;    float data = texture(...).r;&#xD;&#xA;    vec4 luminance = texture(...).rrra;&#xD;&#xA;    vec4 intensity = texture(...).rrrr;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;Though, this requires your shader to be somewhat aware of what texture you're working with. But if you want to use a more generic shader working with a 4-component color from an arbitrary texture, this might be too much of a hassle. In this case what you can also do is have the [texture itself control its own swizzling behaviour](https://www.khronos.org/opengl/wiki/Texture#Swizzle_mask). This is an OpenGL 3.3+ feature and can be set with `glTexParameter` and for good old `GL_LUMIMANCE` behaviour this would be:&#xD;&#xA;&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_R, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_G, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_B, GL_RED);&#xD;&#xA;    glTexParameter(..., GL_TEXTURE_SWIZZLE_A, GL_ONE);&#xD;&#xA;&#xD;&#xA;So then you can retrieve a normal 4-component color from your texture in the shader and get the 1-component it's storing conveniently broadcast into the RGBA components of the result." ContentLicense="CC BY-SA 4.0" />
  <row Id="38362" PostHistoryTypeId="2" PostId="12965" RevisionGUID="030c7680-9181-4595-9afb-325299da2eee" CreationDate="2022-09-07T16:28:32.300" UserId="13831" Text="I think it is a mistake in the book.&#xD;&#xA;&#xD;&#xA;Pick random points uniformly on a sphere offset by the normal, you will get a &#xD;&#xA; distribution of rays proportional to $\cos{\theta} \sin{\theta}$, rather than $\cos{\theta}$ as the book written.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;ds = \frac{(2r \cdot \cos{\theta} \cdot d\theta) }{\cos{\theta}}&#xD;&#xA;\cdot (2 \pi \cdot 2r \cdot \cos{\theta} \sin{\theta)} &#xD;&#xA;$$&#xD;&#xA;where $ds$ is the differential area on the shifted sphere's surface with respect to $\theta$. Integrate $\theta$ from 0 to $\pi/2$, you'll get $4 \pi r^2$.&#xD;&#xA;&#xD;&#xA;And pick random points uniformly inside a sphere offset by the normal, you obtain a distribution of rays proportional to $\cos{\theta}^3 \sin{\theta}$.&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;dv = (2r \cos{\theta} d\theta) \cdot(2\pi \cdot 2r \cos{\theta} \sin{\theta})&#xD;&#xA;\cdot(2r \cos{\theta} \cdot \frac{1}{3})&#xD;&#xA;$$&#xD;&#xA;where $dv$ is the differential volume (whitch is a &#xD;&#xA;quadrangular pyramid) with respect to $\theta$ inside the sphere. You can readily integrate it to $\frac{4}{3} \pi r^3$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38364" PostHistoryTypeId="2" PostId="12966" RevisionGUID="d01577fe-3935-4b5d-b8fd-e9bc686a6807" CreationDate="2022-09-07T16:52:32.677" UserId="18888" Text="I have a process where a web user selects a photo for a profile image. User is then presented with a canvas to zoom, rotate and move their image within a square viewport. Once satisfied, the user submits and the original image along with the adjustment settings are posted to the server.&#xD;&#xA;&#xD;&#xA;I need to find the most efficient way to produce the same end result using the original image but with the highest quality/size allowed.&#xD;&#xA;&#xD;&#xA;I could apply the submitted scale to all the properties and get the exact outcome but it would be in the size of the &quot;viewport&quot; which is 290px-400px square depending on the user's device size. I need that final image to be the maximum size allowed for the job. i.e. if the max size is 1000x700, the final image would be 700x700 if the original image was large enough compared to the submitted scale.&#xD;&#xA;&#xD;&#xA;Here are a couple of examples:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/b1f0u.png&#xD;&#xA;&#xD;&#xA;I dont need the programming/syntax help I need the math help! Shouldnt matter but if it helps I am using C# for this.&#xD;&#xA;&#xD;&#xA;Using the available variables in the example above, what would be the best approach to determine the maximum image size / scale allowed?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38366" PostHistoryTypeId="1" PostId="12966" RevisionGUID="d01577fe-3935-4b5d-b8fd-e9bc686a6807" CreationDate="2022-09-07T16:52:32.677" UserId="18888" Text="Automate Image resize, scale, position for best quality (size)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38367" PostHistoryTypeId="3" PostId="12966" RevisionGUID="d01577fe-3935-4b5d-b8fd-e9bc686a6807" CreationDate="2022-09-07T16:52:32.677" UserId="18888" Text="|mathematics|computational-geometry|image-processing|image|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38368" PostHistoryTypeId="5" PostId="9870" RevisionGUID="0e83fbd7-62bd-4a8b-832a-e4b1bf812143" CreationDate="2022-09-07T17:55:30.933" UserId="6041" Comment="added 79 characters in body" Text="I am struggling understanding gamma encoding/decoding.&#xD;&#xA;&#xD;&#xA;So the colors I see and the values I get from a color picker application(like MS Paint) are already in sRGB space(correct?). &#xD;&#xA;&#xD;&#xA;Assume the color picker gives color C1=(186,70,2). If I create an image programmatically with all pixels in color C1 and Do Not apply gamma encoding C1^(1/gamma), and save it as ppm file, I see exactly same color C1 on opening the file on a viewer.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But this is not the case in my experiment. I save values of color C1 into the file and see color C1. And this is what I don't understand: if the display raise the input color C1 by gamma why do I still see C1 on the screen? Should I not expect to get C1^gamma?&#xD;&#xA;&#xD;&#xA;**UPDATE:**&#xD;&#xA;&#xD;&#xA;Basically here is the ppm file with all pixel RGB values (128,128,128). &#xD;&#xA;No gamma-encoding has been applied. That is simply writing linear values of 128.&#xD;&#xA;&#xD;&#xA;    P3&#xD;&#xA;    400 400&#xD;&#xA;    255&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    128 128 128&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;According to Wikipedia [Gamma correction][1] page:&#xD;&#xA;&#xD;&#xA;&gt; *For example, when using 24-bit RGB color (8 bits per channel), writing*&#xD;&#xA;&gt; *a value of 128 (rounded midpoint of the 0–255 byte range) in video*&#xD;&#xA;&gt; *memory it outputs the proportional ≈ 0.5 voltage to the display, which*&#xD;&#xA;&gt; *it is shown darker due to the monitor behavior.*&#xD;&#xA;&#xD;&#xA;Wikipedia clearly says write a value 128 and you will see a darker than you expect. Those values in my ppm file are not gamma-encoded and so I expect seeing &#xD;&#xA;a darker color(0.5^gamma) on the screen. Yet this is not the case and if you open this file on a viewer you will see pixels with brightness half as white.&#xD;&#xA;&#xD;&#xA;127 in file -&gt; screen outputs -&gt; ~20% light -&gt; eye sees -&gt; ~50% as bright&#xD;&#xA;&#xD;&#xA;That is what I don't get.&#xD;&#xA;&#xD;&#xA;***Update 2* (After Nathan good answer..)**&#xD;&#xA;&#xD;&#xA;So with input of 186 the screen outputs 50% of white intensity? &#xD;&#xA;And the eye perceives it as 50% as bright as white? is this right?&#xD;&#xA;But if the screen output is 50% in intensity, and eye has its own curve(roughly power of 1/gamma) then the screen output of 50% should be *seen* brighter? &#xD;&#xA;&#xD;&#xA;Another question I have is that, &#xD;&#xA;So is it the programmer responsibility to write gamma-corrected values into the file or the whatever API we use to save image file formats does it internally?&#xD;&#xA;For example i use .Net Bitmap class. Do I need to save bitmap with gamma-encoded values or Bitmap.Save method does it?&#xD;&#xA;I ask this since according Wikipedia, and you mentioned this too, almost all image formats are encoded&#xD;&#xA;&#xD;&#xA;&gt;  binary data in still image files (such as JPEG) are explicitly&#xD;&#xA;&gt; encoded (that is, they carry gamma-encoded values, not linear&#xD;&#xA;&gt; intensities)&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gamma_correction#Methods_to_perform_display_gamma_correction_in_computing" ContentLicense="CC BY-SA 4.0" />
  <row Id="38370" PostHistoryTypeId="2" PostId="12967" RevisionGUID="6d6c39dd-28e5-45c0-84c1-308fc2523a3f" CreationDate="2022-09-08T07:34:28.900" UserId="1614" Text="`tbuffer` is certainly not known as well as `cbuffer` is, I just found out that it was a valid keyword actually.&#xD;&#xA;Source for verification:  &#xD;&#xA;https://github.com/microsoft/DirectXShaderCompiler/blob/50c0199c17b0b7530cbc0bdddadc3697eaece695/tools/clang/include/clang/Basic/TokenKinds.def  &#xD;&#xA;It's line 485 in that revision.&#xD;&#xA;&#xD;&#xA;What I'm guessing, as said by @DirectX_Programmer this is surely an effort to make symmetric the language handling of constant buffers by respect to more recently introduced structured buffer. Which uses different packing and alignment rules; and also different physical hardware memory depending on vendors.&#xD;&#xA;&#xD;&#xA;    tbuffer SkinConstants : register(t0)&#xD;&#xA;    {&#xD;&#xA;       float4x3 bone_matrices[15];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // is probably synonymous to:&#xD;&#xA;    struct SkC&#xD;&#xA;    {&#xD;&#xA;        float4x3 bone_matrices[15];&#xD;&#xA;    };&#xD;&#xA;    StructuredBuffer&lt;SkC&gt; g_skc : register(t1);&#xD;&#xA;    &#xD;&#xA;    // note that similarly, since HLSL6 the template type ConstantBuffer&lt;T&gt; can be used symmetrically instead of cbuffer." ContentLicense="CC BY-SA 4.0" />
  <row Id="38372" PostHistoryTypeId="5" PostId="12967" RevisionGUID="1fa8da37-42c9-46c9-990b-0268c34ba71f" CreationDate="2022-09-08T07:52:20.423" UserId="1614" Comment="confusing terminology resolved" Text="`tbuffer` is certainly not known as well as `cbuffer` is, I just found out that it was a valid keyword actually.&#xD;&#xA;Source for verification:  &#xD;&#xA;https://github.com/microsoft/DirectXShaderCompiler/blob/50c0199c17b0b7530cbc0bdddadc3697eaece695/tools/clang/include/clang/Basic/TokenKinds.def  &#xD;&#xA;It's line 485 in that revision.&#xD;&#xA;&#xD;&#xA;What I'm guessing, as said by @DirectX_Programmer this is surely an effort to make symmetric the language handling of constant buffers by respect to more recently introduced structured buffer. Which uses different packing and alignment rules; and also different physical hardware memory depending on vendors.&#xD;&#xA;&#xD;&#xA;    tbuffer SkinConstants : register(t0)&#xD;&#xA;    {&#xD;&#xA;       float4x3 bone_matrices[15];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // close in concept to (but oddly differs in packing rules):&#xD;&#xA;    struct SkC&#xD;&#xA;    {&#xD;&#xA;        float4x3 bone_matrices[15];&#xD;&#xA;    };&#xD;&#xA;    StructuredBuffer&lt;SkC&gt; g_skc : register(t1);&#xD;&#xA;    &#xD;&#xA;    // note that similarly, since HLSL6 the template type ConstantBuffer&lt;T&gt; can be used symmetrically instead of cbuffer.&#xD;&#xA;&#xD;&#xA;Here a little experiment to demonstrate packing differences:  &#xD;&#xA;https://shader-playground.timjones.io/0421fd2f000cd65b771f12b387680fc7&#xD;&#xA;&#xD;&#xA;Using the same source code as above, enriched with a supplementary variable `float4 center`, this is the layout:&#xD;&#xA;&#xD;&#xA;    Resource bind info for g_skc&#xD;&#xA;    ; {&#xD;&#xA;    ;&#xD;&#xA;    ;   struct hostlayout.struct.SkC&#xD;&#xA;    ;   {&#xD;&#xA;    ;&#xD;&#xA;    ;       column_major float3x4 bone_matrices[15];      ; Offset:    0&#xD;&#xA;    ;       float4 center;                                ; Offset:  720&#xD;&#xA;    ;   &#xD;&#xA;    ;   } $Element;                                       ; Offset:    0 Size:   736&#xD;&#xA;    ;&#xD;&#xA;    ; }&#xD;&#xA;    ;&#xD;&#xA;    ; tbuffer SkinConstants&#xD;&#xA;    ; {&#xD;&#xA;    ;&#xD;&#xA;    ;   struct hostlayout.SkinConstants&#xD;&#xA;    ;   {&#xD;&#xA;    ;&#xD;&#xA;    ;       column_major float3x4 bone_matrices[15];      ; Offset:    0&#xD;&#xA;    ;       float4 center;                                ; Offset:  960&#xD;&#xA;    ;   &#xD;&#xA;    ;   } SkinConstants;                                  ; Offset:    0 Size:   976&#xD;&#xA;    ;&#xD;&#xA;    ; }&#xD;&#xA;    ;&#xD;&#xA;    ;&#xD;&#xA;    ; Resource Bindings:&#xD;&#xA;    ;&#xD;&#xA;    ; Name                                 Type  Format         Dim      ID      HLSL Bind  Count&#xD;&#xA;    ; ------------------------------ ---------- ------- ----------- ------- -------------- ------&#xD;&#xA;    ; g_skc                             texture  struct         r/o      T0             t1     1&#xD;&#xA;    ; SkinConstants                     texture     u32     tbuffer      T1             t0     1&#xD;&#xA;    ;&#xD;&#xA;&#xD;&#xA;It appears that the `tbuffer` language construct, packs exactly like `cbuffer` does. I suppose it's a helper facility." ContentLicense="CC BY-SA 4.0" />
  <row Id="38377" PostHistoryTypeId="5" PostId="12967" RevisionGUID="dae01849-8d37-4bee-8c1c-ddfd1c5e02b2" CreationDate="2022-09-08T08:23:01.937" UserId="1614" Comment="add dx11 limit remark" Text="`tbuffer` is certainly not known as well as `cbuffer` is, I just found out that it was a valid keyword actually.&#xD;&#xA;Source for verification:  &#xD;&#xA;https://github.com/microsoft/DirectXShaderCompiler/blob/50c0199c17b0b7530cbc0bdddadc3697eaece695/tools/clang/include/clang/Basic/TokenKinds.def  &#xD;&#xA;It's line 485 in that revision.&#xD;&#xA;&#xD;&#xA;What I'm guessing, as said by @DirectX_Programmer this is surely an effort to make symmetric the language handling of constant buffers by respect to more recently introduced structured buffer. Which uses different packing and alignment rules; and also different physical hardware memory depending on vendors.&#xD;&#xA;&#xD;&#xA;    tbuffer SkinConstants : register(t0)&#xD;&#xA;    {&#xD;&#xA;       float4x3 bone_matrices[15];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // close in concept to (but oddly differs in packing rules):&#xD;&#xA;    struct SkC&#xD;&#xA;    {&#xD;&#xA;        float4x3 bone_matrices[15];&#xD;&#xA;    };&#xD;&#xA;    StructuredBuffer&lt;SkC&gt; g_skc : register(t1);&#xD;&#xA;    &#xD;&#xA;    // note that similarly, since HLSL6 the template type ConstantBuffer&lt;T&gt; can be used symmetrically instead of cbuffer.&#xD;&#xA;&#xD;&#xA;Here a little experiment to demonstrate packing differences:  &#xD;&#xA;https://shader-playground.timjones.io/0421fd2f000cd65b771f12b387680fc7&#xD;&#xA;&#xD;&#xA;Using the same source code as above, enriched with a supplementary variable `float4 center`, this is the layout:&#xD;&#xA;&#xD;&#xA;    Resource bind info for g_skc&#xD;&#xA;    ; {&#xD;&#xA;    ;&#xD;&#xA;    ;   struct hostlayout.struct.SkC&#xD;&#xA;    ;   {&#xD;&#xA;    ;&#xD;&#xA;    ;       column_major float3x4 bone_matrices[15];      ; Offset:    0&#xD;&#xA;    ;       float4 center;                                ; Offset:  720&#xD;&#xA;    ;   &#xD;&#xA;    ;   } $Element;                                       ; Offset:    0 Size:   736&#xD;&#xA;    ;&#xD;&#xA;    ; }&#xD;&#xA;    ;&#xD;&#xA;    ; tbuffer SkinConstants&#xD;&#xA;    ; {&#xD;&#xA;    ;&#xD;&#xA;    ;   struct hostlayout.SkinConstants&#xD;&#xA;    ;   {&#xD;&#xA;    ;&#xD;&#xA;    ;       column_major float3x4 bone_matrices[15];      ; Offset:    0&#xD;&#xA;    ;       float4 center;                                ; Offset:  960&#xD;&#xA;    ;   &#xD;&#xA;    ;   } SkinConstants;                                  ; Offset:    0 Size:   976&#xD;&#xA;    ;&#xD;&#xA;    ; }&#xD;&#xA;    ;&#xD;&#xA;    ;&#xD;&#xA;    ; Resource Bindings:&#xD;&#xA;    ;&#xD;&#xA;    ; Name                                 Type  Format         Dim      ID      HLSL Bind  Count&#xD;&#xA;    ; ------------------------------ ---------- ------- ----------- ------- -------------- ------&#xD;&#xA;    ; g_skc                             texture  struct         r/o      T0             t1     1&#xD;&#xA;    ; SkinConstants                     texture     u32     tbuffer      T1             t0     1&#xD;&#xA;    ;&#xD;&#xA;&#xD;&#xA;It appears that the `tbuffer` language construct, packs exactly like `cbuffer` does. I suppose it's a helper facility.&#xD;&#xA;&#xD;&#xA;We shall note that in this documentation (DX11?) https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-constants it is mentioned that constant buffers are limited to &quot;4096 128-bits vector variables&quot;. Whereas texture buffers are not. I suspect this is not true in DX12 anymore." ContentLicense="CC BY-SA 4.0" />
  <row Id="38380" PostHistoryTypeId="5" PostId="12960" RevisionGUID="1c851838-75c9-4c41-aa57-55540bf4e1e9" CreationDate="2022-09-08T11:00:54.237" UserId="7952" Comment="added 36 characters in body" Text="A very simple, but computationally expensive, way to do this is to pick a triangle, preferably one that you know has the winding you want.&#xD;&#xA;&#xD;&#xA;Then search every triangle in the soup for triangles that share an edge with the chosen triangle.&#xD;&#xA;&#xD;&#xA;For every triangle that shares an edge, check that its winding is the same as the chosen triangle. The winding is the same iff the ordering of the vertices on the shared edge &lt;strike&gt;are the same&lt;/strike&gt; *are the opposite*. If the ordering is different swap the order of any two vertices on the found triangle.&#xD;&#xA;&#xD;&#xA;Remove found triangles from the original set as they are discovered.&#xD;&#xA;&#xD;&#xA;Wash rinse repeat. &#xD;&#xA;&#xD;&#xA;It is usually easiest to implement this algorithm using indexed triangles, it is straight forward to index a set of vertices. (1:iterate over every vertex and assign a new index to only those that are unique, then 2:iterate over every triangle and assign an index from the index pool created in step 1.)&#xD;&#xA;&#xD;&#xA;One nice thing about this algorithm is there are extra &quot;whistle while you work&quot; things that can be done to check the integrity of the polyhedron.&#xD;&#xA;&#xD;&#xA;1) Keep a count of edges that don't share an edge with any other triangle. At the end if this number is non-zero then the polyhedron is not &quot;water tight&quot;. This can be a good starting point for making the polyhedron water tight.&#xD;&#xA;&#xD;&#xA;2) It is possible to have triangles that are not connected to the original chosen triangle, meaning the soup is either inconsistent, or defines multiple polyhedrons. &#xD;&#xA;&#xD;&#xA;Lastly, this algorithm is so easy to code up it can be used to compare other more advance techniques against. " ContentLicense="CC BY-SA 4.0" />
  <row Id="38381" PostHistoryTypeId="50" PostId="12602" RevisionGUID="b76b2baa-adcb-435d-9b8e-533a25786201" CreationDate="2022-09-08T20:00:35.077" UserId="-1" />
  <row Id="38382" PostHistoryTypeId="50" PostId="12609" RevisionGUID="e44b1982-6eb9-4ba7-9e07-098b28f68402" CreationDate="2022-09-09T03:07:15.713" UserId="-1" />
  <row Id="38383" PostHistoryTypeId="2" PostId="12969" RevisionGUID="c2049397-51a4-427f-a117-ddf168c5540f" CreationDate="2022-09-09T06:02:09.340" UserId="18899" Text="before considering the HSL color space, let's consider the CIE chromaticity diagram to understand what I'm looking for:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Unless I am mistaken, I read it that way:&#xD;&#xA;&#xD;&#xA;1) Given two points A, B, any color in the AB segment could be obtained by mixing A and B in different proportions.&#xD;&#xA;&#xD;&#xA;2) Given three points C, D, E, any color in the CDE triangle could be obtained by mixing C, D, E in different proportions, and that's the principle of the RGB color model.&#xD;&#xA;&#xD;&#xA;3) This 2D graph is a slice of a 3D graph, for a fixed value of color lightness.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now, each color of A,B,C,D,E points could be qualified through Hue, Saturation, Lightness:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Is there a way to visualize in this last graph something similar to the CIE diagram? Given two points A,B inside the HSL graph, which colours could be obtained by them? Should I draw a plane, a curved surface etc?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gVLS7m.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ZrXCim.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38385" PostHistoryTypeId="1" PostId="12969" RevisionGUID="c2049397-51a4-427f-a117-ddf168c5540f" CreationDate="2022-09-09T06:02:09.340" UserId="18899" Text="How to visualize color synthesis in HSL diagram" ContentLicense="CC BY-SA 4.0" />
  <row Id="38386" PostHistoryTypeId="3" PostId="12969" RevisionGUID="c2049397-51a4-427f-a117-ddf168c5540f" CreationDate="2022-09-09T06:02:09.340" UserId="18899" Text="|color|color-science|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38387" PostHistoryTypeId="2" PostId="12970" RevisionGUID="32271df8-44bd-4a60-ba73-e27c2473c8fb" CreationDate="2022-09-09T13:57:45.143" UserId="18894" Text="The first thing to say is that the line and triangle in the chromaticity diagram show the result of mixing coloured lights,&#xD;&#xA;so the triangle works for the additive RGB model which is mixing emitted light on a video screen,&#xD;&#xA;but mixing pigments will not result in a colour range in a straight line or triangle from the location on the pigment in the chromaticity diagram.&#xD;&#xA;&#xD;&#xA;In the HSL chart neither additive light mixing nor subtractive pigment mixing will generally result in a colour directly between the two colours.&#xD;&#xA;Typically the HSL chart will be defined in an attempt to make the full gamut of colours a circle, and then smaller gamuts are illustrated within this circle.&#xD;&#xA;All the attempts to do this I have seen appear to be hand-drawn estimates of the resulting gamuts, such as these:&#xD;&#xA;&#xD;&#xA;[![HSL_gamut_diagram][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Please not that in this diagram the &quot;visible colour gamut&quot; is illustrated with the RGB gamut of the computer display, despite being labelled as a wider gamut.&#xD;&#xA;It is also not trivial to define what is meant by &quot;visible colour gamut&quot;, which may contribute to these charts typically showing different ranges for CMYK etc.&#xD;&#xA;&#xD;&#xA;You could define an HSL chart with the sRGB gamut as a circle, and then calculate all the possible mixtures of a set of colours using additive or subtractive mixing.&#xD;&#xA;I think you would get gamuts with curved lines in HSL space joining the original colours, but notable corners at the original colours and their secondaries.&#xD;&#xA;&#xD;&#xA;HSL space is not well suited to do exact displays of such colour ranges. You might be better looking at other spaces. CIELAB space will have some similar issues, but it is at least exactly defined, and the ab plane within CIELAB might give you what you are looking for.&#xD;&#xA;&#xD;&#xA;If you want a gamut with straight lines for mixing colours, you could look at DKL space, which is not as commonly used, but for colour mixtures produces gamuts which are polygons with straight edges in my experience.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/64ygN.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7eLux.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38389" PostHistoryTypeId="2" PostId="12971" RevisionGUID="3b2caa8d-22e0-4dfc-9008-3f0a37543a68" CreationDate="2022-09-09T14:58:22.457" UserId="8572" Text="     __________&#xD;&#xA;(deleted by mistake)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38391" PostHistoryTypeId="12" PostId="12971" RevisionGUID="7d3f3303-e958-4f3b-9931-61fa8f06e35a" CreationDate="2022-09-09T15:01:49.853" UserId="8572" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:8572,&quot;DisplayName&quot;:&quot;Drout&quot;}]}" />
  <row Id="38392" PostHistoryTypeId="5" PostId="12971" RevisionGUID="fd64e823-1d66-40e2-bdc6-74f4f8cdb8f3" CreationDate="2022-09-09T15:17:16.547" UserId="8572" Comment="added 543 characters in body" Text="This pattern is the most efficient&#xD;&#xA;for splitting a quad. Must be in this specific order:&#xD;&#xA;&#xD;&#xA;    0 3&#xD;&#xA;    1 2&#xD;&#xA;&#xD;&#xA;using this exact sequence of triangulation:&#xD;&#xA;&#xD;&#xA;    (0,1,2) (0,2,3) for splitting the two tris in one diagonal&#xD;&#xA;     OR&#xD;&#xA;    (0,1,3) (1,2,3) for the other diagonal&#xD;&#xA;&#xD;&#xA;Why? because you just have to add one unit to the two adjacent indices to switch from one diagonal to the other:&#xD;&#xA;&#xD;&#xA;    const offset = 0 or 1 (*)&#xD;&#xA;    (0,1,2+offset) (0+offset,2,3)&#xD;&#xA;&#xD;&#xA;(*) 0 or 1 depending on the shortest distance between the two diagonals: abs( length( vertex2 - vertex0 )) and abs( length( vertex1 - vertex3 ))&#xD;&#xA;&#xD;&#xA;(Obs. all sequences of three numbers (a triangle) above are CCW (counter clockwise) for Front Facing triangles)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38393" PostHistoryTypeId="13" PostId="12971" RevisionGUID="b86ca893-5665-4a04-8558-6fa674b62b46" CreationDate="2022-09-09T15:17:23.603" UserId="8572" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:8572,&quot;DisplayName&quot;:&quot;Drout&quot;}]}" />
  <row Id="38394" PostHistoryTypeId="5" PostId="12971" RevisionGUID="a07a80a2-74dd-425c-9cc8-c65a29280bae" CreationDate="2022-09-09T15:27:59.770" UserId="8572" Comment="added 104 characters in body" Text="Assuming we are using a separate array for indices into the vertex array, the following pattern for the indices array is the most efficient for splitting a quad. Must be in this specific order:&#xD;&#xA;&#xD;&#xA;    0 3&#xD;&#xA;    1 2&#xD;&#xA;&#xD;&#xA;using this exact sequence of triangulation:&#xD;&#xA;&#xD;&#xA;    (0,1,2) (0,2,3) for splitting the two tris in one diagonal&#xD;&#xA;     OR&#xD;&#xA;    (0,1,3) (1,2,3) for the other diagonal&#xD;&#xA;&#xD;&#xA;Why? because you just have to add one unit to the two adjacent indices to switch from one diagonal to the other:&#xD;&#xA;&#xD;&#xA;    const offset = 0 or 1 (*)&#xD;&#xA;    (0,1,2+offset) (0+offset,2,3)&#xD;&#xA;&#xD;&#xA;(*) 0 or 1 depending on the shortest distance between the two diagonals: abs( length( vertex2 - vertex0 )) and abs( length( vertex1 - vertex3 ))&#xD;&#xA;&#xD;&#xA;(Obs. all sequences of three numbers (a triangle) above are CCW (counter clockwise) for Front Facing triangles)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38395" PostHistoryTypeId="5" PostId="12971" RevisionGUID="fa35d517-a518-4344-974e-d6c964639a0c" CreationDate="2022-09-09T15:36:50.123" UserId="8572" Comment="added 2nd obs" Text="Assuming we are using a separate array for indices into the vertex array, the following pattern for the indices array is the most efficient for splitting a quad. Must be in this specific order:&#xD;&#xA;&#xD;&#xA;    0 3&#xD;&#xA;    1 2&#xD;&#xA;&#xD;&#xA;using this exact sequence of triangulation:&#xD;&#xA;&#xD;&#xA;    (0,1,2) (0,2,3) for splitting the two tris in one diagonal&#xD;&#xA;     OR&#xD;&#xA;    (0,1,3) (1,2,3) for the other diagonal&#xD;&#xA;&#xD;&#xA;Why? because you just have to add one unit to the two adjacent indices to switch from one diagonal to the other:&#xD;&#xA;&#xD;&#xA;    const offset = 0 or 1 (*)&#xD;&#xA;    (0,1,2+offset) (0+offset,2,3)&#xD;&#xA;&#xD;&#xA;(*) 0 or 1 depending on the shortest distance between the two diagonals: abs( length( vertex2 - vertex0 )) and abs( length( vertex1 - vertex3 ))&#xD;&#xA;&#xD;&#xA;Obs. all sequences of three numbers (a triangle) above are CCW (counter clockwise) for Front Facing triangles&#xD;&#xA;&#xD;&#xA;Obs.2 this array of groups of 4 indices into the vertices array could be treated as a vec4 in glsl ;)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38396" PostHistoryTypeId="5" PostId="12970" RevisionGUID="6ac72214-9bdb-46e3-a711-1ce75cc7161f" CreationDate="2022-09-09T17:08:22.093" UserId="18894" Comment="clarifying one part of the answer." Text="The first thing to say is that the line and triangle in the chromaticity diagram show the result of mixing coloured lights,&#xD;&#xA;so the triangle works for the additive RGB model which is mixing emitted light on a video screen,&#xD;&#xA;but mixing pigments will not result in a colour range in a straight line or triangle from the location on the pigment in the chromaticity diagram.&#xD;&#xA;&#xD;&#xA;In the HSL chart neither additive light mixing nor subtractive pigment mixing will generally result in a colour directly between the two colours.&#xD;&#xA;Typically the HSL chart will be defined in an attempt to make the full gamut of colours a circle, and then smaller gamuts are illustrated within this circle.&#xD;&#xA;All the attempts to do this I have seen appear to be hand-drawn estimates of the resulting gamuts, such as these:&#xD;&#xA;&#xD;&#xA;[![HSL_gamut_diagram][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Please not that in this diagram the &quot;visible colour gamut&quot; is illustrated with the RGB gamut of the computer display, despite being labelled as a wider gamut.&#xD;&#xA;It is also not trivial to define what is meant by &quot;visible colour gamut&quot; in HSL terms, which may contribute to these charts typically showing different ranges for CMYK etc. It is only the chromaticity chart which has a simple, clear limit for the &quot;visible colour gamut&quot;.&#xD;&#xA;&#xD;&#xA;You could define an HSL chart with the sRGB gamut as a circle, and then calculate all the possible mixtures of a set of colours using additive or subtractive mixing.&#xD;&#xA;I think you would get gamuts with curved lines in HSL space joining the original colours, but notable corners at the original colours and their secondaries.&#xD;&#xA;&#xD;&#xA;HSL space is not well suited to do exact displays of such colour ranges. You might be better looking at other spaces. CIELAB space will have some similar issues, but it is at least exactly defined, and the ab plane within CIELAB might give you what you are looking for.&#xD;&#xA;&#xD;&#xA;If you want a gamut with straight lines for mixing colours, you could look at DKL space, which is not as commonly used, but for colour mixtures produces gamuts which are polygons with straight edges in my experience.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/64ygN.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7eLux.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38402" PostHistoryTypeId="50" PostId="8431" RevisionGUID="e6a89afe-4428-4cab-aa34-9c151ec24b1b" CreationDate="2022-09-10T05:07:00.577" UserId="-1" />
  <row Id="38403" PostHistoryTypeId="2" PostId="12973" RevisionGUID="7d5b6532-c8b3-4117-8615-a4ca7ff90f91" CreationDate="2022-09-10T13:46:26.120" UserId="7952" Text="Since UV coordinates are per a vertex this can be done by simply displaying the 2D UV coords in screen space and texture the resulting triangles using the same texture coords. Since UV coords are usually [0,1] they will need to be rescaled  for the image, but that is also very easy to do.&#xD;&#xA;&#xD;&#xA;Here is a image showing the results. This also is showing the triangles that map to the uv coords.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the example image the author is showing the mappings of the triangles onto the texture. But it is easy to break up the image, rescale, ect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AZxtx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38405" PostHistoryTypeId="5" PostId="12970" RevisionGUID="22aa3d7b-b2f8-4dfc-8e73-22b60ddf4eaf" CreationDate="2022-09-10T19:20:26.033" UserId="18894" Comment="typo fix" Text="The first thing to say is that the line and triangle in the chromaticity diagram show the result of mixing coloured lights,&#xD;&#xA;so the triangle works for the additive RGB model which is mixing emitted light on a video screen,&#xD;&#xA;but mixing pigments will not result in a colour range in a straight line or triangle from the location of the pigment in the chromaticity diagram.&#xD;&#xA;&#xD;&#xA;In the HSL chart neither additive light mixing nor subtractive pigment mixing will generally result in a colour directly between the two colours.&#xD;&#xA;Typically the HSL chart will be defined in an attempt to make the full gamut of colours a circle, and then smaller gamuts are illustrated within this circle.&#xD;&#xA;All the attempts to do this I have seen appear to be hand-drawn estimates of the resulting gamuts, such as these:&#xD;&#xA;&#xD;&#xA;[![HSL_gamut_diagram][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Please note that in this diagram the &quot;visible colour gamut&quot; is illustrated with the RGB gamut of the computer display, despite being labelled as a wider gamut.&#xD;&#xA;It is also not trivial to define what is meant by &quot;visible colour gamut&quot; in HSL terms, which may contribute to these charts typically showing different ranges for CMYK etc. It is only the chromaticity chart which has a simple, clear limit for the &quot;visible colour gamut&quot;.&#xD;&#xA;&#xD;&#xA;You could define an HSL chart with the sRGB gamut as a circle, and then calculate all the possible mixtures of a set of colours using additive or subtractive mixing.&#xD;&#xA;I think you would get gamuts with curved lines in HSL space joining the original colours, but notable corners at the original colours and their secondaries.&#xD;&#xA;&#xD;&#xA;HSL space is not well suited to do exact displays of such colour ranges. You might be better looking at other spaces. CIELAB space will have some similar issues, but it is at least exactly defined, and the ab plane within CIELAB might give you what you are looking for.&#xD;&#xA;&#xD;&#xA;If you want a gamut with straight lines for mixing colours, you could look at DKL space, which is not as commonly used, but for colour mixtures produces gamuts which are polygons with straight edges in my experience.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/64ygN.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7eLux.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38406" PostHistoryTypeId="2" PostId="12974" RevisionGUID="c8b20be9-ce36-4312-a1e2-5ca714ccb365" CreationDate="2022-09-11T20:29:36.897" UserId="17751" Text="When choosing a probability density function for Monte Carlo evaluation of rendering integrals, I get how importance sampling suggests choosing e.g. $cos(\theta)$ for $p(x)$, and then, over say the hemisphere, the normalization constant is $1/\pi$, so that the normalized pdf becomes&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;p(x) = \frac{cos(\theta)}{\pi}&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;My question is why does everyone say to draw direction samples from $cos(\theta)$ distribution rather than $cos(\theta)/\pi$ distribution? The weight is $cos(\theta)/\pi$, so I'd expect the samples to be drawn from $cos(\theta)/\pi$ as well. (The typical method I see for implementing cos distribution is uniform sampling on a disk and projecting onto hemisphere.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38408" PostHistoryTypeId="1" PostId="12974" RevisionGUID="c8b20be9-ce36-4312-a1e2-5ca714ccb365" CreationDate="2022-09-11T20:29:36.897" UserId="17751" Text="Why does cos sampling directions over hemisphere use cos theta distribution instead of cos theta / pi distribution?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38409" PostHistoryTypeId="3" PostId="12974" RevisionGUID="c8b20be9-ce36-4312-a1e2-5ca714ccb365" CreationDate="2022-09-11T20:29:36.897" UserId="17751" Text="|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38410" PostHistoryTypeId="2" PostId="12975" RevisionGUID="1c80fb95-8b15-4275-b917-25341ff52e8d" CreationDate="2022-09-12T16:45:39.223" UserId="18894" Text="You can certainly convert the wavelengths of the visible spectrum into the XYZ colour space with some extra considerations. Converting wavelengths of the visible spectrum into RGB will present some problems due to the gamut limits of RGB.&#xD;&#xA;The wavelengths of the visible spectrum are usually displayed in the CIE 1931 xy chromaticity space, where each wavelength has a fixed xy position independent of intensity. In LMS, XYZ, RGB and most colour spaces, the position will depend on the intensity of the wavelength. (Please note that the lowercase xy chromaticity values are not the same as the uppercase XY of the XYZ values.) This means you need to choose the intensity for each wavelength, and will get different results based on what you choose.&#xD;&#xA;The graph below shows the shape to expect for equal intensity of each wavelength, intensity of the wavelength in typical sunlight, and the maximum intensity which stimulates one of the cones in the human eye at 100%. For comparison there is a hexagon which shows the limit of the sRGB gamut. There is one dot for each 5-nanometre difference in wavelength.&#xD;&#xA;[![DKL space spectrum at various intensities compared to sRGB][1]][1] &#xD;&#xA;This chart is showing the values in the colour plane of DKL space, where the values are calculated from the three cone L, M and S values. The horizontal axis is the (L-M)*4.5, and the vertical axis is (L+M)/2 – S.&#xD;&#xA;The graph showing wavelengths as maximum intensity is the outside limit of what values are possible, with the conceptual “line of purples” joining the two extreme ends of the graph.&#xD;&#xA;Converting these values into RGB requires mapping values outside of the RGB gamut into the RGB gamut. Here is some analysis of an RGB image of a spectrum (presumably of daylight) showing how the image mapped the values showing the same 2d range as in the chart above. You can see how the shape below relates to the Sunlight graph above. The hexagon in white is again the RGB limit, and the curved shape outside of it is the MacAdam limit, which is a theoretical limit of surface colours. (The colours below are just illustrating this two-dimensional position in RGB space, they are not the colours of the actual pixels.)&#xD;&#xA;[![Range of sRGB pixels in a photograph of a spectrum][2]][2]&#xD;&#xA;I was initially expecting that a photograph of a spectrum would necessarily be the outside limit of colours in RGB space. When I investigated further, I learned that wavelengths of light are only at the outside edge of possible colours when viewed at maximum intensity, such as viewing one wavelength on its own in a dark environment.&#xD;&#xA;If you look at the LMS response curves below, you can see that between blue and green, around 490 nanometres, none of the cones respond strongly, so the colour sensation at that wavelength is notably weak when viewed in a whole spectrum. At the far-red end beyond 640 nanometres the L cones responds many times more strongly than the M cone, so the colour response of those pure wavelengths is much stronger than any mix of wavelengths that is likely to be seen reflecting from an object.&#xD;&#xA;&#xD;&#xA;[![LMS response curves][3]][3] &#xD;&#xA;The graphs of the spectrum in DKL space above do show an explanation for why the spectrum appears to have bands of colour. Where the dots are closely spaced there is little difference in perceived colour across a range of wavelengths. Where the dots are widely spaced there is a greater difference in perceived colour. This creates the appearance of bands of colour separated from each other. The reason for this can be seen in the LMS response curve chart above. From 430 to 460 nanometres none of the response curves change greatly. This is in contrast to the range from 470 to 500 nanometres, where the S response drops off sharply as the L and M responses increase more sharply. This creates the impression of a blue colour band which then changes to another band as the wavelength increases.&#xD;&#xA;&#xD;&#xA;As Nathan Reed said in the comment, the necessary tables are on cvrl.org, and there is more useful information about conversion between different colour spaces on www.brucelindbloom.com&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tpjsW.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/5P8sv.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/iAWU0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38412" PostHistoryTypeId="2" PostId="12976" RevisionGUID="b2f23607-bee3-400c-b6ca-c019f7815fc0" CreationDate="2022-09-13T10:42:41.243" UserId="18894" Text="If you are interpolating in HSV you will need to handle a few special cases.&#xD;&#xA;&#xD;&#xA;If the value of a colour is 0, you should calculate as though the hue and saturation of that colour is the same as the other colour. This means you should use (120, 1, 0) for black in your example. &#xD;&#xA;&#xD;&#xA;If a colour has a saturation of 0, you should calculate as though the hue was the same as the hue of the other colour. (If both colours have a saturation of 0 you can use the hue from either.)&#xD;&#xA;&#xD;&#xA;If the difference between the two hue values is greater than 180 degrees, you should add 360 to the lower hue value before interpolating. If the resulting interpolated hue is greater than 360, then you should subtract 360 from the interpolated hue.&#xD;&#xA;&#xD;&#xA;Alternatively, you could interpolate directly in RGB, which will not require any special cases. This will not give the same interpolated value as HSV, so it depends on how you want the interpolation to work." ContentLicense="CC BY-SA 4.0" />
  <row Id="38414" PostHistoryTypeId="2" PostId="12977" RevisionGUID="073fe334-bfd9-4f20-992e-3a0a501e3481" CreationDate="2022-09-13T12:03:32.733" UserId="18894" Text="This is an interesting question. I have wondered this myself in respect to the three cones of the human eye, which are primaries of an input space in the same way. How do you represent the “colours” of those cones? They are typically referred to as red, green, and blue, though the peak sensitivities lie closer to yellow, yellow-green and blue-violet. As you point out in the question, taking an integral of the response curve would be an interesting illustration, but it would not be accurate.&#xD;&#xA;&#xD;&#xA;For cone responses it is possible to convert LMS values of (1, 0, 0), (0, 1, 0) and (0, 0, 1) to the corresponding XYZ tristimulus values, and then calculate the xy chromaticities of those values, which as you say would be imaginary chromaticity values. I think the triangle connecting these imaginary chromaticity values would necessarily contain all the real chromaticity values.&#xD;&#xA;&#xD;&#xA;Strictly speaking the CIE 1931 xy chromaticity chart is determined by the shape of the LMS response curves. The distinctive shape of the chart depends on how the response curves overlap. If there was no overlap between the response curves then the chart would be a perfect triangle, with the chromaticity of each response curve each at one of the points of the triangle. I think this means that for different input primaries you would strictly need a different chromaticity chart. One set of tristimulus XYZ values would correspond with a range of different spectral power distributions, or technically metamers. With different input primaries you could not be sure that the same range of spectral power distributions would still resolve to a single set of input primary responses. I think this means that you cannot get exact CIE 1931 xy chromaticity values from the response curve of the input values, as there would not be an exact one-to-one conversion between the different versions of chromaticity.&#xD;&#xA;&#xD;&#xA;I think there would still be a way of getting a good approximation.&#xD;&#xA;For digital cameras and digital scanners it seems likely that the input primaries working in combination are equivalent to the LMS response curves, as otherwise the device would not produce a good likeness of the original colours. I would suggest picking three widely spaced colours with known spectral power distribution which are within gamut (e.g. typical R, G and B video screen phosphors), and calculating the response values for the input primaries of your device and the tristimulus XYZ values of those colours. From these values it should be possible to calculate the matrix required to convert from the responses of the input primaries to XYZ and vice versa. Then if you calculate the imaginary RGB values of the input primaries you can convert them to XYZ values and on to xy chromaticity values.&#xD;&#xA;&#xD;&#xA;There might also be a way of calculating an approximate conversion matrix between the device input primaries and LMS by comparing the input primary response curves and the LMS response curves, but I do not know what would be the best way of doing this.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38416" PostHistoryTypeId="2" PostId="12978" RevisionGUID="89a91880-1666-4f22-90be-e4d9e46c9ef2" CreationDate="2022-09-13T15:17:37.510" UserId="18529" Text="Is it possible that a call to `ID3D11DeviceContext::Map` on a dynamic vertex buffer with `D3D11_MAP_WRITE_DISCARD` causes my application to wait *for something* ?&#xD;&#xA;&#xD;&#xA;I'm using a dynamic buffer to draw my UI and I noticed a strange behavior when drawing a complex UI after a time consuming effect such as ssao:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;START FRAME&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;Draw (full-screen quad with ssao shader);&#xD;&#xA;&#xD;&#xA;for(int i=0; i&lt;N; i++)&#xD;&#xA;{&#xD;&#xA;    Update dynamic buffer;&#xD;&#xA;    Draw;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;END FRAME&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;While updating the dynamic buffer usually takes a negligible amount of time, if `N` is high enough(~100) for some `i` it looks like the `Map` command takes some time , **proportional to the GPU time of the ssao shader**, as if there was some form of synchronization.&#xD;&#xA;&#xD;&#xA;Is this possible? Why?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38418" PostHistoryTypeId="1" PostId="12978" RevisionGUID="89a91880-1666-4f22-90be-e4d9e46c9ef2" CreationDate="2022-09-13T15:17:37.510" UserId="18529" Text="D3D11 Map forces synchronization" ContentLicense="CC BY-SA 4.0" />
  <row Id="38419" PostHistoryTypeId="3" PostId="12978" RevisionGUID="89a91880-1666-4f22-90be-e4d9e46c9ef2" CreationDate="2022-09-13T15:17:37.510" UserId="18529" Text="|directx11|memory|direct3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38420" PostHistoryTypeId="2" PostId="12979" RevisionGUID="f1619d5f-7ef3-4963-8b88-28794f65830a" CreationDate="2022-09-13T19:43:58.233" UserId="6596" Text="Sup[pose I have a model of a unit cube (12 faces) aligned to the three axes, and another model of a cube divided into thousands of faces and hard-coded in a random orientation. They are both cubes, even if the point cloud and face index are completely different. What is this called? Resemblance? I know there is a term for this, yet I cannot recall it. I'm currently reading about the Hausdorff distance and the Fréchet distance, yet these do not quite pin down the concept in 3D. Thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="38422" PostHistoryTypeId="1" PostId="12979" RevisionGUID="f1619d5f-7ef3-4963-8b88-28794f65830a" CreationDate="2022-09-13T19:43:58.233" UserId="6596" Text="What is the proper term for 3D models which are similar but not necessarily the same size, orientation, face-count/tesselation, etc?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38423" PostHistoryTypeId="3" PostId="12979" RevisionGUID="f1619d5f-7ef3-4963-8b88-28794f65830a" CreationDate="2022-09-13T19:43:58.233" UserId="6596" Text="|3d|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38424" PostHistoryTypeId="2" PostId="12980" RevisionGUID="0cc29562-4a95-41e6-b156-c73b12cbecfc" CreationDate="2022-09-13T20:39:31.100" UserId="2654" Text="&gt; What is this called?&#xD;&#xA;&#xD;&#xA;Nothing.&#xD;&#xA;&#xD;&#xA;People give names to a concept when that concept is relevant to their lives. This is why programmers have a lot of technical terms for things that happen in programming, but those technical terms aren't used by people outside of programming.&#xD;&#xA;&#xD;&#xA;The concept you describe is not something that really matters to people. Sure, it's a thing that happens, but it doesn't happen often enough, meaningfully enough, to enough people to warrant giving it a name.&#xD;&#xA;&#xD;&#xA;You could say that the two meshes are similar to one another, but that's just using regular English definitions." ContentLicense="CC BY-SA 4.0" />
  <row Id="38427" PostHistoryTypeId="5" PostId="1719" RevisionGUID="88296f13-8f3e-4e30-80cb-4d4d5209d211" CreationDate="2022-09-14T05:59:45.937" UserId="48" Comment="Fix link to paper" Text="When I needed an estimate of mesh curvature for a skin shader, the algorithm I ended up settling on was this:&#xD;&#xA;&#xD;&#xA;First, I computed a scalar curvature for each edge in the mesh. If the edge has positions $p_1, p_2$ and normals $n_1, n_2$, then I estimated its curvature as:&#xD;&#xA;&#xD;&#xA;$$\text{curvature} = \frac{(n_2 - n_1) \cdot (p_2 - p_1)}{|p_2 - p_1|^2}$$&#xD;&#xA;&#xD;&#xA;This calculates the difference in normals, projected along the edge, as a fraction of the length of the edge. (See below for how I came up with this formula.)&#xD;&#xA;&#xD;&#xA;Then, for each vertex I looked at the curvatures of all the edges touching it. In my case, I just wanted a scalar estimate of &quot;average curvature&quot;, so I ended up taking the geometric mean of the absolute values of all the edge curvatures at each vertex. For your case, you might find the minimum and maximum curvatures, and take those edges to be the principal curvature directions (maybe orthonormalizing them with the vertex normal). That's a bit rough, but it might give you a good enough result for what you want to do.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;The motivation for this formula is looking at what happens in 2D when applied to a circle:&#xD;&#xA;&#xD;&#xA;![curvature formula applied to two points on a circle][1]&#xD;&#xA;&#xD;&#xA;Suppose you have a circle of radius $r$ (so its curvature is $1/r$), and you have two points on the circle, with their normals $n_1, n_2$. The positions of the points, relative to the circle's center, are going to be $p_1 = rn_1$ and $p_2 = rn_2$, due to the property that a circle or sphere's normals always point directly out from its center.&#xD;&#xA;&#xD;&#xA;Therefore you can recover the radius as $r = |p_1| / |n_1|$ or $|p_2| / |n_2|$. But in general, the vertex positions won't be relative to the circle's center. We can work around this by subtracting the two:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;p_2 - p_1 &amp;= rn_2 - rn_1 \\&#xD;&#xA;&amp;= r(n_2 - n_1) \\&#xD;&#xA;r &amp;= \frac{|p_2 - p_1|}{|n_2 - n_1|} \\&#xD;&#xA;\text{curvature} = \frac{1}{r} &amp;= \frac{|n_2 - n_1|}{|p_2 - p_1|}&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;The result is exact only for circles and spheres. However, we can extend it to make it a bit more &quot;tolerant&quot;, and use it on arbitrary 3D meshes, and it seems to work reasonably well. We can make the formula more &quot;tolerant&quot; by first projecting the vector $n_2 - n_1$ onto the direction of the edge, $p_2 - p_1$. This allows for these two vectors not being exactly parallel (as they are in the circle case); we'll just project away any component that's not parallel. We can do this by dotting with the normalized edge vector:&#xD;&#xA;$$\begin{aligned}&#xD;&#xA;\text{curvature} &amp;= \frac{(n_2 - n_1) \cdot \text{normalize}(p_2 - p_1)}{|p_2 - p_1|} \\&#xD;&#xA;&amp;= \frac{(n_2 - n_1) \cdot (p_2 - p_1)/|p_2 - p_1|}{|p_2 - p_1|} \\&#xD;&#xA;&amp;= \frac{(n_2 - n_1) \cdot (p_2 - p_1)}{|p_2 - p_1|^2}&#xD;&#xA;\end{aligned}$$&#xD;&#xA;&#xD;&#xA;Et voilà, there's the formula that appeared at the top of this answer. By the way, a nice side benefit of using the _signed_ projection (the dot product) is that the formula then gives a signed curvature: positive for convex, and negative for concave surfaces.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Another approach I can imagine using, but haven't tried, would be to estimate the [second fundamental form](https://en.wikipedia.org/wiki/Second_fundamental_form) of the surface at each vertex. This could be done by setting up a tangent basis at the vertex, then converting all neighboring vertices into that tangent space, and using least-squares to find the best-fit 2FF matrix. Then the principal curvature directions would be the eigenvectors of that matrix. This seems interesting as it could let you find curvature directions &quot;implied&quot; by the neighboring vertices without any edges explicitly pointing in those directions, but on the other hand is a lot more code, more computation, and perhaps less numerically robust.&#xD;&#xA;&#xD;&#xA;A paper that takes this approach is [Rusinkiewicz, &quot;Estimating Curvatures and Their Derivatives on Triangle Meshes&quot;](https://pixl.cs.princeton.edu/pubs/Rusinkiewicz_2004_ECA/index.php). It works by estimating the best-fit 2FF matrix per triangle, then averaging the matrices per-vertex (similar to how smooth normals are calculated).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PL8jY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38428" PostHistoryTypeId="2" PostId="12981" RevisionGUID="3f6a3aa5-49b3-407d-80ad-8c5dd47ac934" CreationDate="2022-09-14T14:36:32.183" UserId="15860" Text="What is the following wireframe, mesh topography style called and how can this effect be applied to a figure in a photograph as done in the image?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZYLmO.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38430" PostHistoryTypeId="1" PostId="12981" RevisionGUID="3f6a3aa5-49b3-407d-80ad-8c5dd47ac934" CreationDate="2022-09-14T14:36:32.183" UserId="15860" Text="Wireframe mesh effect on a photograph subject" ContentLicense="CC BY-SA 4.0" />
  <row Id="38431" PostHistoryTypeId="3" PostId="12981" RevisionGUID="3f6a3aa5-49b3-407d-80ad-8c5dd47ac934" CreationDate="2022-09-14T14:36:32.183" UserId="15860" Text="|line-drawing|photo-realistic|line|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38432" PostHistoryTypeId="2" PostId="12982" RevisionGUID="dccae9ee-2cba-4156-8cae-d3321d6a3a7a" CreationDate="2022-09-14T19:43:37.603" UserId="48" Text="Yes, `Map` can force synchronization in some situations.&#xD;&#xA;&#xD;&#xA;In D3D11, the driver handles GPU command recording, submission and synchronization. When you make D3D11 calls, generally they don't get submitted to the GPU immediately; rather, the driver tries to batch up a large amount of work into a command buffer and then submit it all at once (because submission is expensive).&#xD;&#xA;&#xD;&#xA;What this means for your vertex buffer is that every time you use `MAP_WRITE_DISCARD`, the driver is internally &quot;renaming&quot; your vertex buffer and giving you a new, fresh buffer into which to write. It can't actually overwrite the previous buffer because the work that uses that buffer hasn't executed on the GPU yet. So each time you do a discard, you're effectively allocating more memory, and the driver is buffering up all those vertex buffers and draw commands for the GPU to access at a later time.&#xD;&#xA;&#xD;&#xA;The driver uses various hints/heuristics to determine that it's time to submit work to the GPU. Usually it submits when you call `Flush` or `Present`, but probably another heuristic it uses is the amount of memory allocated that's waiting for the GPU to consume it before it can be reclaimed. So at a certain point, when you've done a large enough number of discards, the driver decides it had better submit the pending work and wait for it so that it can reclaim the memory for all those buffers.&#xD;&#xA;&#xD;&#xA;To work around this, you can help out the driver by managing the memory yourself. Allocate a vertex buffer large enough to hold all N draw calls' worth of data, fill it all in with a single `Map`, then do the draw calls using the `StartVertexLocation` parameter to point each one at its corresponding data within the buffer. Or even better, combine all the draw calls into one large one (assuming you don't need to change states between them)." ContentLicense="CC BY-SA 4.0" />
  <row Id="38434" PostHistoryTypeId="2" PostId="12983" RevisionGUID="ae0d693b-4270-4773-b47b-561cd81439fd" CreationDate="2022-09-15T01:22:55.280" UserId="18936" Text="**Introduction:** &lt;p&gt;&#xD;&#xA;I have a program that receives an image as input and does stuff. &#xD;&#xA;&lt;p&gt;&#xD;&#xA;The more colors the image has the longer it takes for the program to finish and the less visible the difference between two colors, the less important it is to have both of them. &#xD;&#xA;&lt;p&gt;&#xD;&#xA;Since I know very little about working with computer colors I have been using Photoshop to reduce the amount of colors an image has. &lt;p&gt;&#xD;&#xA;&#xD;&#xA;**The goal:** &lt;p&gt;&#xD;&#xA;To convert the program to be usable by normal people. &lt;p&gt;&#xD;&#xA;It will need to have some code capable of reducing the amount of colors on the images given by the users. &lt;p&gt;&#xD;&#xA;I've learned some color reducing theories for image compression but I don't really know how to apply them in practice with the data I have. &lt;p&gt;&#xD;&#xA;&#xD;&#xA;**The need:** &lt;p&gt;&#xD;&#xA;An algorithm that receives a list (or matrix) of sRGB colors and reduces the amount of colors on that list keeping the most information of the original image possible with the colors available. &lt;p&gt;&#xD;&#xA;Preferably one where a number n can be specified which is the number of colors the output will have. &lt;p&gt;&#xD;&#xA;&#xD;&#xA;**Extra details** &lt;p&gt;&#xD;&#xA;Speed is a bit more valuable than color perfection as if possible it would be nice to show the user the converted image in real time (or near real time) so they could see how the settings they chose are going to affect the result.&#xD;&#xA;&lt;p&gt;&#xD;&#xA;The user should be able to use lots of colors if desired but the main use case expected is a number between 10 and 200, maybe up to 500 colors.&#xD;&#xA;&lt;p&gt;&#xD;&#xA;I'm looking for descriptions and/or suggestions of algorithms I can learn and implement not random implemented code to copy/steal." ContentLicense="CC BY-SA 4.0" />
  <row Id="38436" PostHistoryTypeId="1" PostId="12983" RevisionGUID="ae0d693b-4270-4773-b47b-561cd81439fd" CreationDate="2022-09-15T01:22:55.280" UserId="18936" Text="Algorithm to reduce number of colors used on an image. (sRGB)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38437" PostHistoryTypeId="3" PostId="12983" RevisionGUID="ae0d693b-4270-4773-b47b-561cd81439fd" CreationDate="2022-09-15T01:22:55.280" UserId="18936" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38438" PostHistoryTypeId="5" PostId="12983" RevisionGUID="156397ea-e6bf-43fa-b9c2-03fe7f2e482a" CreationDate="2022-09-15T01:29:57.703" UserId="18936" Comment="deleted 17 characters in body" Text="**Introduction:** &lt;p&gt;&#xD;&#xA;I have a program that receives an image as input and does stuff. &#xD;&#xA;&lt;p&gt;&#xD;&#xA;The more colors the image has the longer it takes for the program to finish and the less visible the difference between two colors, the less important it is to have both of them. &#xD;&#xA;&lt;p&gt;&#xD;&#xA;Since I know very little about working with computer colors I have been using Photoshop to reduce the amount of colors an image has. &lt;p&gt;&#xD;&#xA;&#xD;&#xA;**The goal:** &lt;p&gt;&#xD;&#xA;To convert the program to be usable by normal people. &lt;p&gt;&#xD;&#xA;It will need to have some code capable of reducing the amount of colors on the images given by the users. &lt;p&gt;&#xD;&#xA;I've learned some color reducing theories for image compression but I don't really know how to apply them in practice with the data I have. &lt;p&gt;&#xD;&#xA;&#xD;&#xA;**The need:** &lt;p&gt;&#xD;&#xA;An algorithm that receives a list (or matrix) of sRGB colors and reduces the amount of colors on that list keeping the most information of the original image possible with the colors available. &lt;p&gt;&#xD;&#xA;Preferably one where a number n can be specified which is the number of colors the output will have. &lt;p&gt;&#xD;&#xA;&#xD;&#xA;**Extra details** &lt;p&gt;&#xD;&#xA;Speed is a bit more valuable than color perfection as if possible it would be nice to show the user the converted image in real time (or near real time) so they could see how the settings they chose are going to affect the result.&#xD;&#xA;&lt;p&gt;&#xD;&#xA;The user should be able to use lots of colors if desired but the main use case expected is a number between 10 and 200 colors.&#xD;&#xA;&lt;p&gt;&#xD;&#xA;I'm looking for descriptions and/or suggestions of algorithms I can learn and implement not random implemented code to copy/steal." ContentLicense="CC BY-SA 4.0" />
  <row Id="38439" PostHistoryTypeId="2" PostId="12984" RevisionGUID="5588cecc-0df6-4d1a-8e14-825c9832137c" CreationDate="2022-09-15T07:51:03.287" UserId="13273" Text="One possibility is to use k-means clustering. Here, the number of clusters represents the number of colors in the output image. &#xD;&#xA;&#xD;&#xA;**This is how you use the k-Means clustering algorithm for color reduction.&#xD;&#xA;Color is in 3D space (r, g, b) where each value can be between &quot;0&quot; and &quot;1&quot;.&#xD;&#xA;By iterating over each pixel of your image, you can add the color of the pixel to your search space. Once this is done for all pixels, you need to specify the number of colors for your output image. Each of them will be given a random 3D value between 0 and 1 in the color space.&#xD;&#xA;&#xD;&#xA;Each of your input colors must calculate the distance (Euclidean) to all output colors. The pixel belongs to the output color with the smallest distance. When you have done this for all colors, the positions of the output colors are recalculated. The new position is the arithmetic mean position of all input colors grouped to the output color.&#xD;&#xA;This algorithm must be run several times to get good results. &#xD;&#xA;You can stop the algorithm if no input color has changed the output color group during a whole iteration. &#xD;&#xA;&#xD;&#xA;Be aware that you can have flipping input colors. This means that one or more input color positions are between two output groups and change to the other group on each iteration. Because of this phenomenon, you should add a counter that stops the algorithm after a few iterations.&#xD;&#xA;&#xD;&#xA;To get an idea of what the result can look like, let me share one of my projects that uses this technique to reduce colors. In [this video][1] you can see the original input object on the left side. On the right side you see the voxelized output. All colors have been reduced to 6 colors. In second 26, the algorithm is applied to the model. If you look closely, you can see that the colors of the voxelized output (on the right) change for a few frames in the video and then become stable.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=zthgu9NeWUg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38441" PostHistoryTypeId="5" PostId="12984" RevisionGUID="29c3da35-f939-4eac-9a69-872549e4d17d" CreationDate="2022-09-15T08:25:13.100" UserId="13273" Comment="added 2 characters in body" Text="One possibility is to use k-means clustering. Here, the number of clusters represents the number of colors in the output image. &#xD;&#xA;&#xD;&#xA;**This is how you use the k-Means clustering algorithm for color reduction.**&#xD;&#xA;Color is in 3D space (r, g, b) where each value can be between &quot;0&quot; and &quot;1&quot;.&#xD;&#xA;By iterating over each pixel of your image, you can add the color of the pixel to your search space. Once this is done for all pixels, you need to specify the number of colors for your output image. Each of them will be given a random 3D value between 0 and 1 in the color space.&#xD;&#xA;&#xD;&#xA;Each of your input colors must calculate the distance (Euclidean) to all output colors. The pixel belongs to the output color with the smallest distance. When you have done this for all colors, the positions of the output colors are recalculated. The new position is the arithmetic mean position of all input colors grouped to the output color.&#xD;&#xA;This algorithm must be run several times to get good results. &#xD;&#xA;You can stop the algorithm if no input color has changed the output color group during a whole iteration. &#xD;&#xA;&#xD;&#xA;Be aware that you can have flipping input colors. This means that one or more input color positions are between two output groups and change to the other group on each iteration. Because of this phenomenon, you should add a counter that stops the algorithm after a few iterations.&#xD;&#xA;&#xD;&#xA;To get an idea of what the result can look like, let me share one of my projects that uses this technique to reduce colors. In [this video][1] you can see the original input object on the left side. On the right side you see the voxelized output. All colors have been reduced to 6 colors. In second 26, the algorithm is applied to the model. If you look closely, you can see that the colors of the voxelized output (on the right) change for a few frames in the video and then become stable.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.youtube.com/watch?v=zthgu9NeWUg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38442" PostHistoryTypeId="50" PostId="12896" RevisionGUID="d13d958c-e82a-4056-ac17-5a5f818a3343" CreationDate="2022-09-15T17:08:45.820" UserId="-1" />
  <row Id="38443" PostHistoryTypeId="2" PostId="12985" RevisionGUID="c6653614-8fb8-4b6d-8bd7-5573df432e42" CreationDate="2022-09-16T10:08:43.917" UserId="6496" Text="Optix has OPTIX_BUILD_INPUT_TYPE_CURVES to model splines. The SDK comes with an example named optixHair.&#xD;&#xA;&#xD;&#xA;I could not find something like this under Vulkan RayTracing Extension, how could one implement something like this in Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38445" PostHistoryTypeId="1" PostId="12985" RevisionGUID="c6653614-8fb8-4b6d-8bd7-5573df432e42" CreationDate="2022-09-16T10:08:43.917" UserId="6496" Text="Vulkan Ray Tracing analogue of Optix's of OPTIX_BUILD_INPUT_TYPE_CURVES" ContentLicense="CC BY-SA 4.0" />
  <row Id="38446" PostHistoryTypeId="3" PostId="12985" RevisionGUID="c6653614-8fb8-4b6d-8bd7-5573df432e42" CreationDate="2022-09-16T10:08:43.917" UserId="6496" Text="|raytracing|vulkan|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38447" PostHistoryTypeId="2" PostId="12986" RevisionGUID="88cd4b6f-1b72-4fe6-a27a-e358de0053b3" CreationDate="2022-09-16T12:30:45.007" UserId="13321" Text="I don't think vulkan has any way of natively doing curves.&#xD;&#xA;&#xD;&#xA;I think you will need to program it yourself using VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR, by providing your own bounding boxes for the curves and writing your own intersection shader for them.&#xD;&#xA;&#xD;&#xA;I think this is an example of what you want.&#xD;&#xA;https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/tree/master/ray_tracing_intersection" ContentLicense="CC BY-SA 4.0" />
  <row Id="38449" PostHistoryTypeId="4" PostId="12985" RevisionGUID="dc5cc568-7da7-4c52-ba6f-84a0517419ef" CreationDate="2022-09-16T12:41:52.450" UserId="6496" Comment="edited title" Text="Vulkan Ray Tracing analogue of Optix's OPTIX_BUILD_INPUT_TYPE_CURVES" ContentLicense="CC BY-SA 4.0" />
  <row Id="38450" PostHistoryTypeId="5" PostId="12985" RevisionGUID="59e5be26-96de-4df5-a5bb-8a94d7425a39" CreationDate="2022-09-16T17:30:25.147" UserId="6496" Comment="deleted 15 characters in body" Text="Optix has OPTIX_BUILD_INPUT_TYPE_CURVES to model splines. The SDK comes with an example named optixHair.&#xD;&#xA;&#xD;&#xA;I could not find something like this under Vulkan RayTracing Extension, how could one implement this in Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38451" PostHistoryTypeId="52" PostId="12985" RevisionGUID="bdaa53a3-538c-402c-9901-2650a12b64ed" CreationDate="2022-09-16T18:22:38.667" />
  <row Id="38452" PostHistoryTypeId="2" PostId="12987" RevisionGUID="a82cb524-05cf-4841-8896-4d9dad73f4af" CreationDate="2022-09-16T19:35:26.243" UserId="13367" Text="I'm not sure I have the right terminology, but in rendering it can be useful to draw cosine weighted samples from a hemisphere. In this case the integral (over the weights) is Pi.&#xD;&#xA;Now I don´t want to sample the complete hemisphere, but rather a cone, centered around the polar axis. But not in a uniformly like e.g. the function [UniformSampleCone()][1] in pbrt, but rather also in a cosine weighted manner. In other words a subset of the cosine weighted hemisphere. Is there a formula compute the integral of weights for this? I was thinking something like `(1 - cos(cone_angle)) * Pi`, but it is not quite right.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations#UniformSampleCone" ContentLicense="CC BY-SA 4.0" />
  <row Id="38454" PostHistoryTypeId="1" PostId="12987" RevisionGUID="a82cb524-05cf-4841-8896-4d9dad73f4af" CreationDate="2022-09-16T19:35:26.243" UserId="13367" Text="Integral over cosine weighted sphere cap/cone" ContentLicense="CC BY-SA 4.0" />
  <row Id="38455" PostHistoryTypeId="3" PostId="12987" RevisionGUID="a82cb524-05cf-4841-8896-4d9dad73f4af" CreationDate="2022-09-16T19:35:26.243" UserId="13367" Text="|distribution|integral|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38458" PostHistoryTypeId="2" PostId="12988" RevisionGUID="c11edd6e-b6dc-48f0-9efd-fbc7c69a57ea" CreationDate="2022-09-17T08:47:23.087" UserId="13367" Text="As I was referencing PBRT, here are the functions I ended up with:&#xD;&#xA;&#xD;&#xA;    fn coneCosine(uv: Vec2f, cos_theta_max: f32) Vec4f {&#xD;&#xA;        const xy = @splat(2, @sqrt(1.0 - cos_theta_max * cos_theta_max)) * diskConcentric(uv);&#xD;&#xA;        const z = @sqrt(std.math.max(0.0, 1.0 - xy[0] * xy[0] - xy[1] * xy[1]));&#xD;&#xA;&#xD;&#xA;        return .{ xy[0], xy[1], z, 0.0 };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    fn conePdfCosine(cos_theta_max: f32) f32 {&#xD;&#xA;        return 1.0 / ((1.0 - (cos_theta_max * cos_theta_max)) * std.math.pi);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="38460" PostHistoryTypeId="50" PostId="12414" RevisionGUID="f01e011f-8259-48ae-8dce-c65407141696" CreationDate="2022-09-17T09:06:25.517" UserId="-1" />
  <row Id="38461" PostHistoryTypeId="5" PostId="12817" RevisionGUID="82986a52-fcaf-4f35-bcfa-e9467ac80123" CreationDate="2022-09-17T12:20:28.700" UserId="1763" Comment="added 180 characters in body" Text="The context openGL instances learning.&#xD;&#xA;&#xD;&#xA;I want to transform a reference triangle to another one. So final goal is to have one triangle and the instance being a transformation of that initial triangle.&#xD;&#xA;&#xD;&#xA;The idea is to apply a Matrix4x4 transformation on that reference triangle to inject into a 3d rendering pipeline.&#xD;&#xA;&#xD;&#xA;**The library I use needs a reference triangle and a packed array of matrix 4x4 to tell it the transforms applied to the reference points.**&#xD;&#xA;&#xD;&#xA;Z is UP (wrong, but it doesn't matter for the calculus logic now, i should still have the shapes right, even on the wrong axis).&#xD;&#xA;Points are packed in a buffer.&#xD;&#xA;&#xD;&#xA;So far I have this:&#xD;&#xA;&#xD;&#xA;### Reference triangle, column major:&#xD;&#xA;&#xD;&#xA;      array &lt;double, 16&gt; reference_triangle {0, 2, 1, 1,&#xD;&#xA;                                             0, 0, 1, 1,&#xD;&#xA;                                             0, 0, 0, 1,&#xD;&#xA;                                             1, 1, 1, 1};&#xD;&#xA;&#xD;&#xA;x: {0,0,0], y:{2,0,0} and z:{1,1,0}&#xD;&#xA;&#xD;&#xA;### Second triangle given by:&#xD;&#xA;&#xD;&#xA;      array &lt;double, 16&gt; to_transf_triangle {5 , 42, 31 ,1,&#xD;&#xA;                                             10, 20, 11 ,1,&#xD;&#xA;                                             0,   0,  0 ,1,&#xD;&#xA;                                             1,   1,  1, 1};&#xD;&#xA;&#xD;&#xA;x: {5,10,0], y:{42,20,0} and z:{31,11,0}&#xD;&#xA;&#xD;&#xA;**Note:**&#xD;&#xA;Z axis is always 0 so my triangles could be considered 2D in that example (but won't always be the case, so please stick with 3D logic).&#xD;&#xA;&#xD;&#xA;The other values are set to one for the transformation.&#xD;&#xA;&#xD;&#xA;### Transformation pseudo code:&#xD;&#xA;&#xD;&#xA;    temp_transf = inverse(reference_triangle) * to_transf_triangle;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The final result in 3D is not what I expected: no translation (I expected it somehow because the resulting translation vector is null, I should add it from a point of the transform triangle) and triangles going visually awry.&#xD;&#xA;&#xD;&#xA;**There must be a missing step.**&#xD;&#xA;&#xD;&#xA;Now what is the way to transform one triangle given 3 points into another in a matrix 4x4 in a 3D opengl instance context?&#xD;&#xA;&#xD;&#xA;I don't need code that much, just the logic.&#xD;&#xA;&#xD;&#xA;Not even sure my method is a good starting point.&#xD;&#xA;&#xD;&#xA;Thanks,&#xD;&#xA;&#xD;&#xA;Update:&#xD;&#xA;&#xD;&#xA;Wrong uvs depending on the point input order, but triangle shapes of that plane are perfect:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Fqkk6.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38462" PostHistoryTypeId="2" PostId="12989" RevisionGUID="870d089a-74e5-4344-99d4-814b8fe0e2b5" CreationDate="2022-09-17T12:36:11.357" UserId="7952" Text="This is not something that would be called a &quot;*wireframe mesh*&quot; in computer graphics. Models are sometimes displayed as a wireframe to help visualize the topology which look like a lot of connected lines but are nothing like the given example. &#xD;&#xA;&#xD;&#xA; At best it could be called a &quot;surface&quot; if it was described using curves like the Utah Teapot but then I would expect it to look something like this:&#xD;&#xA;&#xD;&#xA;[![Utah Teapot][1]][1]&#xD;&#xA;&#xD;&#xA;If only the curves in a particular direction were kept, considerable more curves added in the chosen direction, thickened and stylized with noise then it would start to look something like what you are talking about. (visibility occlusion would have to be dealt with somewhere along the line)&#xD;&#xA;&#xD;&#xA;To go from a photo to a stylized surface like this would involve converting the objects in the photo to models using something like photogrammetry. (which typically involve dozens to hundreds of photo's) Then figuring out a direction for the curves then creating control points for all the curves from the model, remove all curves that don't follow the chosen direction, and stylize the lines with noise and signed distance fields, then add in some more noise to the curves control points, and extra control points to help stylize them. With hand tweaking to get the final desired effect.&#xD;&#xA;&#xD;&#xA;The entire process would be pretty involved. This could be a fun masters project (or maybe a dissertation if you could get it approved). &#xD;&#xA;&#xD;&#xA;The really fun part if you got far enough along to have the code that does all this, would be animating the entire works. But I get a 5 aspirin headache just thinking about the work involved here.&#xD;&#xA;&#xD;&#xA;Or just open some modeling software like Blender and create a texture that wraps a 3d model, or better yet, get the out the electronic art pen and touch screen which brings me full circle back to art/design suggested by Nathan Reed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yipBo.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="38466" PostHistoryTypeId="2" PostId="12990" RevisionGUID="107a4922-ccb8-4d68-beb4-36379480d00d" CreationDate="2022-09-18T10:36:38.097" UserId="7525" Text="I have a projection calculation which maps points from 3D space to pixel (image) space, and I want to use it as instead of the standard MVP projections in a vertex shader.&#xD;&#xA;&#xD;&#xA;In the image below the lower blue flow is how I understand the pipeline works in GLSL, and the upper green arc is what I want to use instead.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Since GLSL's projection matrix doesn't produce pixel coordinates, but a homogenous vec4 that allows to calculate pixel coords and depth estimation, I need to make some adjustments:&#xD;&#xA;&#xD;&#xA;My idea is to take the vec2 pixel coordinates from my calculation, map them to clip space and let openGL finish the conversion to pixel space by itself&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Only problem is I'm not entirely sure how to pull this off, as you can see Im missing some essential data about what happens after Clip space&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yP8GW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fSPEK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38468" PostHistoryTypeId="1" PostId="12990" RevisionGUID="107a4922-ccb8-4d68-beb4-36379480d00d" CreationDate="2022-09-18T10:36:38.097" UserId="7525" Text="Alternate projections in shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="38469" PostHistoryTypeId="3" PostId="12990" RevisionGUID="107a4922-ccb8-4d68-beb4-36379480d00d" CreationDate="2022-09-18T10:36:38.097" UserId="7525" Text="|shader|projections|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38470" PostHistoryTypeId="2" PostId="12991" RevisionGUID="54ddb3b0-c6cb-4ac0-bc83-c38d67dee932" CreationDate="2022-09-18T19:49:16.247" UserId="17751" Text="In the Monte Carlo chapter of PBRT, in the section Transforming Between Distributions:&#xD;&#xA;&#xD;&#xA;https://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Transforming_between_Distributions&#xD;&#xA;&#xD;&#xA;They say &quot;The density with respect to $\theta$ and $\phi$ can therefore be derived&quot;, but they *start* with&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;p(\theta, \phi) \ d\theta \ d\phi = p(\omega) \ d\omega&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;and my question is, how to see that this is true? I get how, if you are ok with that, then substituting $d\omega = \sin \theta \ d\theta \ d\phi$ gives the result that follows, but I don't understand how to even read that starting line, like is it saying &quot;the function defined with respect to $\theta$ and $\phi$ times $d\theta$ times $d\phi$ is equal to the function defined with respect to $\omega$ times $d\omega$&quot;?&#xD;&#xA;&#xD;&#xA;Anyway, it seems like it should instead be&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;p(\omega) \ d\omega = p(\theta, \phi) \sin \theta \ d\theta \ d\phi&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;according to section 5.5? (Express function in terms of $\theta$ and $\phi$ and use $d\omega = \sin \theta \ d\theta \ d\phi$.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38472" PostHistoryTypeId="1" PostId="12991" RevisionGUID="54ddb3b0-c6cb-4ac0-bc83-c38d67dee932" CreationDate="2022-09-18T19:49:16.247" UserId="17751" Text="Transforming between solid angle and spherical angle distribution in PBRT" ContentLicense="CC BY-SA 4.0" />
  <row Id="38473" PostHistoryTypeId="3" PostId="12991" RevisionGUID="54ddb3b0-c6cb-4ac0-bc83-c38d67dee932" CreationDate="2022-09-18T19:49:16.247" UserId="17751" Text="|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38479" PostHistoryTypeId="50" PostId="9116" RevisionGUID="b66d69e4-81fd-4329-84da-dcdfd32d8a56" CreationDate="2022-09-20T11:00:35.063" UserId="-1" />
  <row Id="38480" PostHistoryTypeId="5" PostId="12990" RevisionGUID="67c42900-c591-447f-8c78-24143eb1ddf9" CreationDate="2022-09-20T12:39:18.267" UserId="7525" Comment="added 131 characters in body" Text="I have a projection calculation which maps points from 3D space to pixel (image) space, and I want to use it as instead of the standard MVP projections in a vertex shader.&#xD;&#xA;&#xD;&#xA;In the image below the lower blue flow is how I understand the pipeline works in GLSL, and the upper green arc is what I want to use instead.&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Since GLSL's projection matrix doesn't produce pixel coordinates, but a homogenous vec4 that allows to calculate pixel coords and depth estimation, I need to make some adjustments:&#xD;&#xA;&#xD;&#xA;My idea is to take the vec2 pixel coordinates from my calculation, map them to clip space and let openGL finish the conversion to pixel space by itself&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Only problem is I'm not entirely sure how to pull this off, as you can see Im missing some essential data about what happens after Clip space&#xD;&#xA;&#xD;&#xA;Any ideas?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;The GLSL implementation of the 3D to 2D projection function can be found here&#xD;&#xA;https://www.shadertoy.com/view/fltfW2&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yP8GW.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fSPEK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38481" PostHistoryTypeId="2" PostId="12993" RevisionGUID="0f59ab85-f0c0-4da6-9bf0-bbd53fc02469" CreationDate="2022-09-20T16:06:54.183" UserId="10129" Text="I'm trying to perform forward pixel projection based on previous frame depth. Using UV, I'm reading prevDepth for given pixel and based on that I'm recreating worldPos in camera space (where (0, 0, 0) is camera position). Then I offset this position using previous frame camera position to find prevWorldPos in camera space.&#xD;&#xA;&#xD;&#xA;Then I'm doing standard matrix multiplication to get ndc and then prev frame uv. So, it works quite nice without any additional history buffer or using pixel neighbours, at least for camera rotation.&#xD;&#xA;&#xD;&#xA;**When it comes to camera translation, value of prevUV is the same as uv and it results in no changes in affected pixels and it destroys the reprojection. And I don't understand why.**&#xD;&#xA;&#xD;&#xA;	float3 worldPosition = GetWorldPosFromUV(uv, prevDepth); // Current frame worldPos in camera space&#xD;&#xA;	float3 prevWorldPosition = worldPosition + (currFrameCameraOffset - prevFrameCameraOffset); // Transform to camera space position in previous frame&#xD;&#xA;&#xD;&#xA;	float4 ndcPrev = mul(float4(prevWorldPosition, 1.0f), viewProjMatrixPrevFrame); &#xD;&#xA;	ndcPrev.xyz /= ndcPrev.w;&#xD;&#xA;	float2 prevUV = ndcPrev.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f);&#xD;&#xA;&#xD;&#xA;	return prevUV;&#xD;&#xA;    &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/I0NZc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38483" PostHistoryTypeId="1" PostId="12993" RevisionGUID="0f59ab85-f0c0-4da6-9bf0-bbd53fc02469" CreationDate="2022-09-20T16:06:54.183" UserId="10129" Text="Previous frame reprojection fails for camera translation" ContentLicense="CC BY-SA 4.0" />
  <row Id="38484" PostHistoryTypeId="3" PostId="12993" RevisionGUID="0f59ab85-f0c0-4da6-9bf0-bbd53fc02469" CreationDate="2022-09-20T16:06:54.183" UserId="10129" Text="|matrix|depth-map|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38485" PostHistoryTypeId="5" PostId="4183" RevisionGUID="d05d5d23-9b61-4360-8d60-1138595e66e5" CreationDate="2022-09-20T17:38:27.043" UserId="5778" Comment="broken link fixed" Text="I've tried to figure this out as well, but I don't think there is a solution that is just as performant as tracing one sphere.  Basically you would want to cast one ray to hit a infinite set of repeating spheres with no marching iteration.  That would be awesome but is not possible:  Let me explain.&#xD;&#xA;# &#xD;&#xA;&#xD;&#xA;**Ray-tracing** is basically finding the analytical solution to this equation:&#xD;&#xA;$$&#xD;&#xA;f(\vec{r(t)}) = 0 \ for \ t&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Where $f(\vec{p})$ is the implicit surface function (which gives the distance the given point $\vec{p}$ is from the surface) and $\vec{r(t)}$ is the parametric ray equation ($\vec{r(t)} = \vec{origin} + \vec{direction}*t$).  $t$ would represent the distance along the ray the intersection happens.&#xD;&#xA;&#xD;&#xA;In order to ray-trace domain manipulations (like repeating space), these domain manipulations need to be present in the implicit surface function $f(\vec{p})$ while finding an analytical solution.  Let's take a 3D repeating sphere for instance.&#xD;&#xA;$$&#xD;&#xA;f'(\vec{p}) = \|\vec{p}\bmod \vec{d}\| - r&#xD;&#xA;$$&#xD;&#xA;(where $\vec{d}$ is a constant representing the grid size and $r$ is the radius)&#xD;&#xA;&#xD;&#xA;In order to solve $f'(\vec{r(t)}) = 0$ for $t$ we would need the inverse of the modulo operator which doesn't really exist : [Link](https://web.archive.org/web/20171228030043/http://mathforum.org/library/drmath/view/51619.html).  That means there is no analytical solution to this equation, but there is a numerical one. Hence **Ray-marching**.&#xD;&#xA;# &#xD;&#xA;&#xD;&#xA;This is true for a lot of cool distance functions you see on shadertoy.com, the analytical solution does not exist for these surfaces so you cannot ray-trace.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38486" PostHistoryTypeId="24" PostId="4183" RevisionGUID="d05d5d23-9b61-4360-8d60-1138595e66e5" CreationDate="2022-09-20T17:38:27.043" Comment="Proposed by 5778 approved by 13095 edit id of 591" ContentLicense="CC BY-SA 4.0" />
  <row Id="38487" PostHistoryTypeId="10" PostId="12981" RevisionGUID="1b6b8e49-ed48-4ffb-8501-6e0c65e757a0" CreationDate="2022-09-20T17:47:02.703" UserId="13095" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:48,&quot;DisplayName&quot;:&quot;Nathan Reed&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[5]}" />
  <row Id="38489" PostHistoryTypeId="50" PostId="9781" RevisionGUID="887a1ea9-1c2c-4407-841d-ed7754d33481" CreationDate="2022-09-21T20:05:30.430" UserId="-1" />
  <row Id="38490" PostHistoryTypeId="50" PostId="10177" RevisionGUID="2ddda1db-b2a1-4e1c-8730-ee4bd48d72cf" CreationDate="2022-09-22T06:01:10.170" UserId="-1" />
  <row Id="38495" PostHistoryTypeId="2" PostId="12995" RevisionGUID="9ea09391-426b-4c56-b429-575bed805647" CreationDate="2022-09-23T11:03:18.843" UserId="18959" Text="Trying to replicate ThreeJS outline postprocessing example, but I'm facing an error on some uncompiled Vertex shader.&#xD;&#xA;&#xD;&#xA;I actually just copy/pasted source code with some small adjustment (removed the on-mouse-over detection in favor of an easier checkbox).&#xD;&#xA;&#xD;&#xA;For the sake of completeness, I'm using Webpack and LaravelMix as boundlers for the test and threejs 0.144.0.&#xD;&#xA;&#xD;&#xA;## My code&#xD;&#xA;```javascript&#xD;&#xA;import * as THREE from 'three';&#xD;&#xA;import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';&#xD;&#xA;import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';&#xD;&#xA;import { GUI } from 'three/addons/libs/lil-gui.module.min.js';&#xD;&#xA;import { OrbitControls } from 'three/addons/controls/OrbitControls.js';&#xD;&#xA;import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';&#xD;&#xA;import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';&#xD;&#xA;import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;let renderer, scene, camera, controls;&#xD;&#xA;&#xD;&#xA;let composer, outlinePass, effectFXAA;&#xD;&#xA;&#xD;&#xA;let cube;&#xD;&#xA;&#xD;&#xA;const gui = new GUI({ width: 280 });&#xD;&#xA;const guiParams = {&#xD;&#xA;    edgeStrength: 3.0,&#xD;&#xA;    edgeGlow: 0.0,&#xD;&#xA;    edgeThickness: 1.0,&#xD;&#xA;    pulsePeriod: 0,&#xD;&#xA;    rotate: false,&#xD;&#xA;    usePatternTexture: false,&#xD;&#xA;    outline: false,&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;gui.add(guiParams, 'outline').onChange(function (value) {&#xD;&#xA;    outlinePass.selectedObjects = value ? [cube] : [];&#xD;&#xA;});&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;init();&#xD;&#xA;animate();&#xD;&#xA;&#xD;&#xA;function init() {&#xD;&#xA;    const width = window.innerWidth;&#xD;&#xA;    const height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;    window.addEventListener('resize', onWindowResize);&#xD;&#xA;&#xD;&#xA;    // RENDERER&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize(width, height);&#xD;&#xA;    document.body.appendChild(renderer.domElement);&#xD;&#xA;&#xD;&#xA;    // SCENE&#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    scene.background = new THREE.Color(0x000000);&#xD;&#xA;&#xD;&#xA;    // CAMERA&#xD;&#xA;    camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);&#xD;&#xA;    camera.position.set(2, 2, 8);&#xD;&#xA;    camera.lookAt(new THREE.Vector3(0, 0, 0));&#xD;&#xA;&#xD;&#xA;    // CONTROLS&#xD;&#xA;    controls = new OrbitControls(camera, renderer.domElement);&#xD;&#xA;&#xD;&#xA;    // DIRECTIONAL LIGHT&#xD;&#xA;    const light = new THREE.PointLight(0xddffdd, 0.6);&#xD;&#xA;    light.position.set(1, 2, 3);&#xD;&#xA;    scene.add(light);&#xD;&#xA;&#xD;&#xA;    // AMBIENT LIGHT&#xD;&#xA;    scene.add(new THREE.AmbientLight(0xaaaaaa, 0.1));&#xD;&#xA;&#xD;&#xA;    // BOX&#xD;&#xA;    const geometry = new THREE.BoxGeometry(1, 1, 1);&#xD;&#xA;    const material = new THREE.MeshPhysicalMaterial({ color: 0x00ff00 });&#xD;&#xA;    cube = new THREE.Mesh(geometry, material);&#xD;&#xA;    scene.add(cube);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // ===============&#xD;&#xA;    // POST PROCESSING&#xD;&#xA;    // ===============&#xD;&#xA;&#xD;&#xA;    // COMPOSER&#xD;&#xA;    composer = new EffectComposer(renderer);&#xD;&#xA;&#xD;&#xA;    const renderPass = new RenderPass(scene, camera);&#xD;&#xA;    composer.addPass(renderPass);&#xD;&#xA;&#xD;&#xA;    outlinePass = new OutlinePass(new THREE.Vector2(width, height), scene, camera);&#xD;&#xA;    composer.addPass(outlinePass);&#xD;&#xA;&#xD;&#xA;    effectFXAA = new ShaderPass(FXAAShader);&#xD;&#xA;    effectFXAA.uniforms['resolution'].value.set(1 / width, 1 / height);&#xD;&#xA;    effectFXAA.renderToScreen = true;&#xD;&#xA;    composer.addPass(effectFXAA);&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;function animate() {&#xD;&#xA;    requestAnimationFrame(animate);&#xD;&#xA;    controls.update();&#xD;&#xA;    composer.render();&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;function onWindowResize() {&#xD;&#xA;&#xD;&#xA;    const width = window.innerWidth;&#xD;&#xA;    const height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;    camera.aspect = width / height;&#xD;&#xA;    camera.updateProjectionMatrix();&#xD;&#xA;&#xD;&#xA;    renderer.setSize(width, height);&#xD;&#xA;    composer.setSize(width, height);&#xD;&#xA;&#xD;&#xA;    effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## The error&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ar1Tu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38497" PostHistoryTypeId="1" PostId="12995" RevisionGUID="9ea09391-426b-4c56-b429-575bed805647" CreationDate="2022-09-23T11:03:18.843" UserId="18959" Text="ThreeJS OutlinePass error on Vertex shader not compiled" ContentLicense="CC BY-SA 4.0" />
  <row Id="38498" PostHistoryTypeId="3" PostId="12995" RevisionGUID="9ea09391-426b-4c56-b429-575bed805647" CreationDate="2022-09-23T11:03:18.843" UserId="18959" Text="|post-processing|three.js|compositing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38499" PostHistoryTypeId="5" PostId="12995" RevisionGUID="a6f7d86e-5c3e-4826-8875-fe0312478344" CreationDate="2022-09-23T13:54:53.840" UserId="18959" Comment="added link to followed example" Text="Trying to replicate ThreeJS outline postprocessing [example][1], but I'm facing an error on some uncompiled Vertex shader.&#xD;&#xA;&#xD;&#xA;I actually just copy/pasted source code with some small adjustment (removed the on-mouse-over detection in favor of an easier checkbox).&#xD;&#xA;&#xD;&#xA;For the sake of completeness, I'm using Webpack and LaravelMix as boundlers for the test and threejs 0.144.0.&#xD;&#xA;&#xD;&#xA;## My code&#xD;&#xA;```javascript&#xD;&#xA;import * as THREE from 'three';&#xD;&#xA;import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';&#xD;&#xA;import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';&#xD;&#xA;import { GUI } from 'three/addons/libs/lil-gui.module.min.js';&#xD;&#xA;import { OrbitControls } from 'three/addons/controls/OrbitControls.js';&#xD;&#xA;import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';&#xD;&#xA;import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';&#xD;&#xA;import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;let renderer, scene, camera, controls;&#xD;&#xA;&#xD;&#xA;let composer, outlinePass, effectFXAA;&#xD;&#xA;&#xD;&#xA;let cube;&#xD;&#xA;&#xD;&#xA;const gui = new GUI({ width: 280 });&#xD;&#xA;const guiParams = {&#xD;&#xA;    edgeStrength: 3.0,&#xD;&#xA;    edgeGlow: 0.0,&#xD;&#xA;    edgeThickness: 1.0,&#xD;&#xA;    pulsePeriod: 0,&#xD;&#xA;    rotate: false,&#xD;&#xA;    usePatternTexture: false,&#xD;&#xA;    outline: false,&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;gui.add(guiParams, 'outline').onChange(function (value) {&#xD;&#xA;    outlinePass.selectedObjects = value ? [cube] : [];&#xD;&#xA;});&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;init();&#xD;&#xA;animate();&#xD;&#xA;&#xD;&#xA;function init() {&#xD;&#xA;    const width = window.innerWidth;&#xD;&#xA;    const height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;    window.addEventListener('resize', onWindowResize);&#xD;&#xA;&#xD;&#xA;    // RENDERER&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize(width, height);&#xD;&#xA;    document.body.appendChild(renderer.domElement);&#xD;&#xA;&#xD;&#xA;    // SCENE&#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    scene.background = new THREE.Color(0x000000);&#xD;&#xA;&#xD;&#xA;    // CAMERA&#xD;&#xA;    camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);&#xD;&#xA;    camera.position.set(2, 2, 8);&#xD;&#xA;    camera.lookAt(new THREE.Vector3(0, 0, 0));&#xD;&#xA;&#xD;&#xA;    // CONTROLS&#xD;&#xA;    controls = new OrbitControls(camera, renderer.domElement);&#xD;&#xA;&#xD;&#xA;    // DIRECTIONAL LIGHT&#xD;&#xA;    const light = new THREE.PointLight(0xddffdd, 0.6);&#xD;&#xA;    light.position.set(1, 2, 3);&#xD;&#xA;    scene.add(light);&#xD;&#xA;&#xD;&#xA;    // AMBIENT LIGHT&#xD;&#xA;    scene.add(new THREE.AmbientLight(0xaaaaaa, 0.1));&#xD;&#xA;&#xD;&#xA;    // BOX&#xD;&#xA;    const geometry = new THREE.BoxGeometry(1, 1, 1);&#xD;&#xA;    const material = new THREE.MeshPhysicalMaterial({ color: 0x00ff00 });&#xD;&#xA;    cube = new THREE.Mesh(geometry, material);&#xD;&#xA;    scene.add(cube);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // ===============&#xD;&#xA;    // POST PROCESSING&#xD;&#xA;    // ===============&#xD;&#xA;&#xD;&#xA;    // COMPOSER&#xD;&#xA;    composer = new EffectComposer(renderer);&#xD;&#xA;&#xD;&#xA;    const renderPass = new RenderPass(scene, camera);&#xD;&#xA;    composer.addPass(renderPass);&#xD;&#xA;&#xD;&#xA;    outlinePass = new OutlinePass(new THREE.Vector2(width, height), scene, camera);&#xD;&#xA;    composer.addPass(outlinePass);&#xD;&#xA;&#xD;&#xA;    effectFXAA = new ShaderPass(FXAAShader);&#xD;&#xA;    effectFXAA.uniforms['resolution'].value.set(1 / width, 1 / height);&#xD;&#xA;    effectFXAA.renderToScreen = true;&#xD;&#xA;    composer.addPass(effectFXAA);&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;function animate() {&#xD;&#xA;    requestAnimationFrame(animate);&#xD;&#xA;    controls.update();&#xD;&#xA;    composer.render();&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;function onWindowResize() {&#xD;&#xA;&#xD;&#xA;    const width = window.innerWidth;&#xD;&#xA;    const height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;    camera.aspect = width / height;&#xD;&#xA;    camera.updateProjectionMatrix();&#xD;&#xA;&#xD;&#xA;    renderer.setSize(width, height);&#xD;&#xA;    composer.setSize(width, height);&#xD;&#xA;&#xD;&#xA;    effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## The error&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://threejs.org/examples/#webgl_postprocessing_outline&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ar1Tu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38500" PostHistoryTypeId="2" PostId="12996" RevisionGUID="5547ddab-c146-4c9a-ab1d-d8ea1f351c28" CreationDate="2022-09-24T22:30:26.637" UserId="48" Text="As lightxbulb mentioned in the comments, one confusing thing here is that two different functions are being called $p$. Kind of like function overloading in C++, the $p(\omega)$ and $p(\theta, \phi)$ are two different functions, in the sense of having different domains and different dependence on their inputs, though in some sense they abstractly represent the same distribution.&#xD;&#xA;&#xD;&#xA;The other thing that's confusing here is that the values returned by these functions are not just numbers. Since these are probability density functions, their values carry units of inverse area. Moreover, the two functions are expressing density with respect to different areas: $p(\omega)$ is probability per area on the unit sphere, while $p(\theta, \phi)$ is probability per unit area on the $\theta$-$\phi$ plane—an abstract 2D plane formed by $\theta$ and $\phi$ as Cartesian coordinates (just like the $x$-$y$ plane). These area measures are related to each other, but not the same: as you observed, $d\omega = \sin \theta \, d\theta \, d\phi$.&#xD;&#xA;&#xD;&#xA;Notation like $d\omega$ and $d\theta \, d\phi$ refers to these area measures. As mentioned in the comments, this can be mathematically formalized as differential forms ([here's an introduction](https://www.math.purdue.edu/~arapura/preprints/diffforms.pdf) I found useful).&#xD;&#xA;&#xD;&#xA;Because $p(\omega)$ is a probability density per area on the unit sphere, if $d\omega$ is a &quot;small&quot; area on the unit sphere around the point $\omega$, then $p(\omega) \, d\omega$ works out to be a probability—not a density, but just a plain old probability number. In the limit of $d\omega$ being infinitesimal, $p(\omega) \, d\omega$ is the amount of probability enclosed within the area $d\omega$.&#xD;&#xA;&#xD;&#xA;Similarly $p(\theta, \phi) \, d\theta \, d\phi$ is the amount of probability enclosed within a &quot;small&quot; area of the $\theta$-$\phi$ plane. The statement that&#xD;&#xA;$$&#xD;&#xA;p(\omega) \, d\omega = p(\theta, \phi) \, d\theta \, d\phi&#xD;&#xA;$$&#xD;&#xA;is intended to mean the following: the amount of probability in a small area of the unit sphere is equal to the amount of probability in the corresponding small area of the $\theta$-$\phi$ plane. In other words, probability is conserved by mapping between these two domains. This is the condition that makes these two functions represent &quot;the same&quot; distribution, abstractly, despite being parameterized with different variables.&#xD;&#xA;&#xD;&#xA;The condition needs to be written that way because the probability densities aren't unitless numbers. If we had some function whose values were just plain numbers without units attached, and we wanted to reparameterize it with different variables, the condition would just be that $f(\omega) = f(\theta, \phi)$: the function should keep the same value at &quot;the same&quot; point when we change variables. But with the probability densities, we don't want the same value of the function, we want the same amount of probability in each part of the domain.&#xD;&#xA;&#xD;&#xA;Using this &quot;conservation of probability&quot; condition $p(\omega) \, d\omega = p(\theta, \phi) \, d\theta \, d\phi$ together with the relationship between the two area measures, $d\omega = \sin \theta \, d\theta \, d\phi$, we can derive:&#xD;&#xA;$$&#xD;&#xA;p(\theta, \phi) = p(\omega) \, \sin \theta&#xD;&#xA;$$&#xD;&#xA;which shows that to express the a spherical distribution in terms of $\theta, \phi$, you have to not only change variables but also multiply the function by $\sin \theta$ to conserve the probability. That $\sin \theta$ factor is known as the &quot;inverse Jacobian&quot;, and it accounts for how the transformation stretches the area in different parts of the domain." ContentLicense="CC BY-SA 4.0" />
  <row Id="38502" PostHistoryTypeId="2" PostId="12997" RevisionGUID="9be0ae8c-7045-47f3-a28f-eb8242f61bd2" CreationDate="2022-09-25T18:22:55.747" UserId="18962" Text="I'm looking for an effect similar to this image. Assuming the UV coordinates of the triangle are known, such as:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;p0 = [0, 0]&#xD;&#xA;p1 = [1, 0]&#xD;&#xA;p2 = [0, 1]&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I know the centroid of the triangle formed by these UV coordinates is [0.33333, 0.33333]&#xD;&#xA;&#xD;&#xA;How do I output a color from black in the center to white at the edges, such as it follows the gradient pattern in this image?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xCknT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38504" PostHistoryTypeId="1" PostId="12997" RevisionGUID="9be0ae8c-7045-47f3-a28f-eb8242f61bd2" CreationDate="2022-09-25T18:22:55.747" UserId="18962" Text="How to generate a gradient to the edges of a triangle in GLSL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38505" PostHistoryTypeId="3" PostId="12997" RevisionGUID="9be0ae8c-7045-47f3-a28f-eb8242f61bd2" CreationDate="2022-09-25T18:22:55.747" UserId="18962" Text="|opengl|triangulation|gradient|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38506" PostHistoryTypeId="2" PostId="12998" RevisionGUID="be76d9b2-ecda-45ce-8257-05e1ec759a94" CreationDate="2022-09-25T21:31:38.343" UserId="48" Text="You can calculate the perpendicular distance from each edge, and then take the minimum of the three edges. This is related to barycentric coordinates (which are normalized edge distances). If you already have the barycentrics $a, b, c$, you can calculate $3 \cdot \min(a, b, c)$. The 3 is to normalize the gradient to the [0, 1] range, since the centroid of the triangle lies at barycentrics $(\tfrac{1}{3}, \tfrac{1}{3}, \tfrac{1}{3})$.&#xD;&#xA;&#xD;&#xA;The UV mapping you mentioned makes $u, v$ equal to two of the barycentrics, so you can then calculate the gradient coordinate as $3 \cdot \min(u, v, 1 - u - v)$.&#xD;&#xA;&#xD;&#xA;This coordinate runs from 0 at the edges to 1 at the center, so to go from black at the enter to white at the edges, you could take 1 minus that. And of course, you can do any other gradient using this coordinate to interpolate the desired colors." ContentLicense="CC BY-SA 4.0" />
  <row Id="38508" PostHistoryTypeId="52" PostId="12997" RevisionGUID="346f74c5-4b0f-4569-a33f-280163f348aa" CreationDate="2022-09-26T02:24:02.763" />
  <row Id="38509" PostHistoryTypeId="2" PostId="12999" RevisionGUID="df04dbba-bb75-4846-9f74-cf8f39cea863" CreationDate="2022-09-26T07:14:44.453" UserId="18964" Text="I'm trying to understand mipmapping.&#xD;&#xA;&#xD;&#xA;It makes sense that you would have many pictures of your textures at different resolutions, and use the closest ones in size to what you need in order to avoid moiré patterns--that's logical. But a lot of the diagrams I've seen split out the R, G, and B channels: for example splitting a square into quarters, in which the top left is the red component of an image, the top right is green, the bottom left is blue, and the bottom right recursively splits the image up again, at a lower resolution.&#xD;&#xA;&#xD;&#xA;So what's the point of splitting up the RGB? Why not just have a bunch of different-sized images of your texture? It seems that splitting them up is wasted work, since you'll ultimately just have to put them together again." ContentLicense="CC BY-SA 4.0" />
  <row Id="38511" PostHistoryTypeId="1" PostId="12999" RevisionGUID="df04dbba-bb75-4846-9f74-cf8f39cea863" CreationDate="2022-09-26T07:14:44.453" UserId="18964" Text="Why does mipmapping separate out the RGB channels?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38512" PostHistoryTypeId="3" PostId="12999" RevisionGUID="df04dbba-bb75-4846-9f74-cf8f39cea863" CreationDate="2022-09-26T07:14:44.453" UserId="18964" Text="|texture|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38513" PostHistoryTypeId="2" PostId="13000" RevisionGUID="654426ae-4610-439c-9774-76d3c436342e" CreationDate="2022-09-26T08:08:32.947" UserId="18959" Text="## How can I have a multicolor material in ThreeJS?&#xD;&#xA;&#xD;&#xA;I'm looking for a way to have **a single material and use one or more b/w masks to color the surface of the model with the same amount of colors**; the masks will not blend/overlap each others, so no color blending, just some areas of one color and other of another.&#xD;&#xA;&#xD;&#xA;I'm sure it is actually possible with ThreeJS to achieve this, but I couldn't find any example on how to do this.&#xD;&#xA;&#xD;&#xA;Having played with Blender I'm used to assign multiple materials to specific mesh faces for easiest models and using multiple shaders (or even entire materials) with textures masks, but in a web context I assume the best practice is to have a single model/mesh to which assign a single material.&#xD;&#xA;&#xD;&#xA;Just to be clear, the final use case will be a 3d model created with external tool (blender, maya, etc) with all necessary textures to recreate a single material, this way I can asynchronously download each assets for page speed.&#xD;&#xA;&#xD;&#xA;The problem is how then to recreate the final material with all the assets." ContentLicense="CC BY-SA 4.0" />
  <row Id="38515" PostHistoryTypeId="1" PostId="13000" RevisionGUID="654426ae-4610-439c-9774-76d3c436342e" CreationDate="2022-09-26T08:08:32.947" UserId="18959" Text="ThreeJS multicolor material" ContentLicense="CC BY-SA 4.0" />
  <row Id="38516" PostHistoryTypeId="3" PostId="13000" RevisionGUID="654426ae-4610-439c-9774-76d3c436342e" CreationDate="2022-09-26T08:08:32.947" UserId="18959" Text="|material|color-management|three.js|masking|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38517" PostHistoryTypeId="2" PostId="13001" RevisionGUID="bd93192e-4d66-4fbc-b5c2-d2f79a7954e5" CreationDate="2022-09-26T08:19:56.413" UserId="209" Text="Re separating RGB, I guess you are referring to Lance Williams' &quot;[Pyramidal Parametrics&quot; paper][1].&#xD;&#xA;&#xD;&#xA;I suspect he did it that way to fit in with the graphics system he had, but on modern GPUs (at least since I started developing them in 1992) the channels are not separate. The MIP map chain is likely to be just $N \times M$, $\frac{N}{2} \times \frac{M}{2}$ ... 1x1 etc images *possibly* arranged semi-contiguously in memory.&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/800059.801126" ContentLicense="CC BY-SA 4.0" />
  <row Id="38519" PostHistoryTypeId="50" PostId="12163" RevisionGUID="fb5d1813-eba2-4699-ba2f-846cfd5eb78c" CreationDate="2022-09-26T12:01:55.160" UserId="-1" />
  <row Id="38520" PostHistoryTypeId="5" PostId="12991" RevisionGUID="c2da8c87-cace-4bdc-8393-550eadd9d8aa" CreationDate="2022-09-26T12:44:31.533" UserId="16241" Comment="Move bare hyperlink to be a link associated with the title" Text="In the Monte Carlo chapter of PBRT, in the section [Transforming Between Distributions][1], they say &quot;The density with respect to $\theta$ and $\phi$ can therefore be derived&quot;, but they *start* with&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;p(\theta, \phi) \ d\theta \ d\phi = p(\omega) \ d\omega&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;and my question is, how to see that this is true? I get how, if you are ok with that, then substituting $d\omega = \sin \theta \ d\theta \ d\phi$ gives the result that follows, but I don't understand how to even read that starting line, like is it saying &quot;the function defined with respect to $\theta$ and $\phi$ times $d\theta$ times $d\phi$ is equal to the function defined with respect to $\omega$ times $d\omega$&quot;?&#xD;&#xA;&#xD;&#xA;Anyway, it seems like it should instead be&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;p(\omega) \ d\omega = p(\theta, \phi) \sin \theta \ d\theta \ d\phi&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;according to section 5.5? (Express function in terms of $\theta$ and $\phi$ and use $d\omega = \sin \theta \ d\theta \ d\phi$.)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Transforming_between_Distributions" ContentLicense="CC BY-SA 4.0" />
  <row Id="38521" PostHistoryTypeId="24" PostId="12991" RevisionGUID="c2da8c87-cace-4bdc-8393-550eadd9d8aa" CreationDate="2022-09-26T12:44:31.533" Comment="Proposed by 16241 approved by 13095 edit id of 592" ContentLicense="CC BY-SA 4.0" />
  <row Id="38522" PostHistoryTypeId="2" PostId="13002" RevisionGUID="c38764ad-8ea9-4bdb-9a3a-b94ac2aa151f" CreationDate="2022-09-26T20:02:37.953" UserId="18969" Text="I need to accurately plot a line chart using WebGL. The numbers have a precision of around 33 bits - that's too many to fit into a single-precision float's mantissa. WebGL does not support the double-precision floats that arrive in my program so I split each number into &quot;coarse&quot; and &quot;fine&quot; parts:&#xD;&#xA;&#xD;&#xA;	// buf is a Float32Array to be used as a vertex buffer, input is a Float64Array.&#xD;&#xA;	for (let i = 0; i &lt; input.length; ++i) {&#xD;&#xA;		buf[i * 2] = input[i];&#xD;&#xA;		buf[i * 2 + 1] = input[i] - buf[i * 2];&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The y axis range that shall be visible is passed in the same manner:&#xD;&#xA;&#xD;&#xA;	// rangeMin and rangeMax are 64-bit floats that define the plotting boundaries.&#xD;&#xA;	// rangeMin is split up just like the input numbers.&#xD;&#xA;    // The value range is only needed in single precision.&#xD;&#xA;	gl.uniform3f(range,&#xD;&#xA;		Math.fround(rangeMin),&#xD;&#xA;		rangeMin - Math.fround(rangeMin),&#xD;&#xA;		rangeMax - rangeMin);&#xD;&#xA;&#xD;&#xA;Then, in the vertex shader I evaluate the y axis position by joining coarse- and fine-grained parts in the correct order:&#xD;&#xA;&#xD;&#xA;	float y = ((n.x - range.x) + (n.y - range.y)) / range.z;&#xD;&#xA;&#xD;&#xA;For points that are inside the given range, y is the correct position on a normalized y axis between 0 and 1.&#xD;&#xA;&#xD;&#xA;This works really well. However, I also need to find the correct position on an _inversed_ y axis, i.e. an axis that linearly spans from 1 / rangeMax to 1 / rangeMin. I could easily create a second vertex buffer and reuse the existing math, only substituting `input` → `1 / input`, `rangeMin` → `1 / rangeMax` and `rangeMax` → `1 / rangeMin`. This would waste a lot of memory on the duplicated buffer. I feel like there should be a relatively simple way to approximate such kind of inverse in the vertex shader, maybe involving one or two steps of Newton's method, but I can't seem to figure it out." ContentLicense="CC BY-SA 4.0" />
  <row Id="38524" PostHistoryTypeId="1" PostId="13002" RevisionGUID="c38764ad-8ea9-4bdb-9a3a-b94ac2aa151f" CreationDate="2022-09-26T20:02:37.953" UserId="18969" Text="Plot inverse of emulated double-precision floats" ContentLicense="CC BY-SA 4.0" />
  <row Id="38525" PostHistoryTypeId="3" PostId="13002" RevisionGUID="c38764ad-8ea9-4bdb-9a3a-b94ac2aa151f" CreationDate="2022-09-26T20:02:37.953" UserId="18969" Text="|mathematics|algorithm|webgl|float|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38526" PostHistoryTypeId="5" PostId="12999" RevisionGUID="567d370b-7f5d-462b-8147-3c99c4717f14" CreationDate="2022-09-27T00:37:18.910" UserId="18964" Comment="added 113 characters in body" Text="I'm trying to understand mipmapping.&#xD;&#xA;&#xD;&#xA;It makes sense that you would have many pictures of your textures at different resolutions, and use the closest ones in size to what you need in order to avoid moiré patterns--that's logical. But a lot of the diagrams I've seen split out the R, G, and B channels: for example splitting a square into quarters, in which the top left is the red component of an image, the top right is green, the bottom left is blue, and the bottom right recursively splits the image up again, at a lower resolution.&#xD;&#xA;&#xD;&#xA;So what's the point of splitting up the RGB? Why not just have a bunch of different-sized images of your texture? It seems that splitting them up is wasted work, since you'll ultimately just have to put them together again.&#xD;&#xA;&#xD;&#xA;(There is an example of this phenomenon on the Wikipedia page for mipmapping, under the &quot;Mechanism&quot; heading.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38527" PostHistoryTypeId="50" PostId="12900" RevisionGUID="63cc3182-158d-4722-bcc7-d815e4d8d63e" CreationDate="2022-09-27T06:07:10.603" UserId="-1" />
  <row Id="38528" PostHistoryTypeId="50" PostId="10853" RevisionGUID="89d84d0f-a5f8-4b61-90d1-2ddbc08de2a7" CreationDate="2022-09-27T10:00:10.093" UserId="-1" />
  <row Id="38530" PostHistoryTypeId="2" PostId="13003" RevisionGUID="a3ad3bd0-2294-4121-a09c-bb0f339587c7" CreationDate="2022-09-27T23:55:39.590" UserId="48" Text="You could try the Taylor series expansion for $1/x$:&#xD;&#xA;$$&#xD;&#xA;\frac{1}{x + a} = \frac{1}{x} - \frac{a}{x^2} + \frac{a^2}{x^3} - \frac{a^3}{x^4} + \cdots&#xD;&#xA;$$&#xD;&#xA;when $a$ is small compared to $x$. You can probably get away with just a handful of terms (maybe even just the first two)." ContentLicense="CC BY-SA 4.0" />
  <row Id="38532" PostHistoryTypeId="50" PostId="10509" RevisionGUID="2a607a4e-0f97-4686-a98e-bf95c4f35509" CreationDate="2022-09-28T06:04:30.547" UserId="-1" />
  <row Id="38533" PostHistoryTypeId="5" PostId="12995" RevisionGUID="0a4bbb02-8a95-45ad-8481-2ff5fb9c5fea" CreationDate="2022-09-28T13:59:40.177" UserId="18959" Comment="added update on error observed on code not mine" Text="Trying to replicate ThreeJS outline postprocessing [example][1], but I'm facing an error on some uncompiled Vertex shader.&#xD;&#xA;&#xD;&#xA;I actually just copy/pasted source code with some small adjustment (removed the on-mouse-over detection in favor of an easier checkbox).&#xD;&#xA;&#xD;&#xA;For the sake of completeness, I'm using Webpack and LaravelMix as boundlers for the test and threejs 0.144.0.&#xD;&#xA;&#xD;&#xA;## My code&#xD;&#xA;```javascript&#xD;&#xA;import * as THREE from 'three';&#xD;&#xA;import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';&#xD;&#xA;import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';&#xD;&#xA;import { GUI } from 'three/addons/libs/lil-gui.module.min.js';&#xD;&#xA;import { OrbitControls } from 'three/addons/controls/OrbitControls.js';&#xD;&#xA;import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';&#xD;&#xA;import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';&#xD;&#xA;import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;let renderer, scene, camera, controls;&#xD;&#xA;&#xD;&#xA;let composer, outlinePass, effectFXAA;&#xD;&#xA;&#xD;&#xA;let cube;&#xD;&#xA;&#xD;&#xA;const gui = new GUI({ width: 280 });&#xD;&#xA;const guiParams = {&#xD;&#xA;    edgeStrength: 3.0,&#xD;&#xA;    edgeGlow: 0.0,&#xD;&#xA;    edgeThickness: 1.0,&#xD;&#xA;    pulsePeriod: 0,&#xD;&#xA;    rotate: false,&#xD;&#xA;    usePatternTexture: false,&#xD;&#xA;    outline: false,&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;gui.add(guiParams, 'outline').onChange(function (value) {&#xD;&#xA;    outlinePass.selectedObjects = value ? [cube] : [];&#xD;&#xA;});&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;init();&#xD;&#xA;animate();&#xD;&#xA;&#xD;&#xA;function init() {&#xD;&#xA;    const width = window.innerWidth;&#xD;&#xA;    const height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;    window.addEventListener('resize', onWindowResize);&#xD;&#xA;&#xD;&#xA;    // RENDERER&#xD;&#xA;    renderer = new THREE.WebGLRenderer();&#xD;&#xA;    renderer.setSize(width, height);&#xD;&#xA;    document.body.appendChild(renderer.domElement);&#xD;&#xA;&#xD;&#xA;    // SCENE&#xD;&#xA;    scene = new THREE.Scene();&#xD;&#xA;    scene.background = new THREE.Color(0x000000);&#xD;&#xA;&#xD;&#xA;    // CAMERA&#xD;&#xA;    camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);&#xD;&#xA;    camera.position.set(2, 2, 8);&#xD;&#xA;    camera.lookAt(new THREE.Vector3(0, 0, 0));&#xD;&#xA;&#xD;&#xA;    // CONTROLS&#xD;&#xA;    controls = new OrbitControls(camera, renderer.domElement);&#xD;&#xA;&#xD;&#xA;    // DIRECTIONAL LIGHT&#xD;&#xA;    const light = new THREE.PointLight(0xddffdd, 0.6);&#xD;&#xA;    light.position.set(1, 2, 3);&#xD;&#xA;    scene.add(light);&#xD;&#xA;&#xD;&#xA;    // AMBIENT LIGHT&#xD;&#xA;    scene.add(new THREE.AmbientLight(0xaaaaaa, 0.1));&#xD;&#xA;&#xD;&#xA;    // BOX&#xD;&#xA;    const geometry = new THREE.BoxGeometry(1, 1, 1);&#xD;&#xA;    const material = new THREE.MeshPhysicalMaterial({ color: 0x00ff00 });&#xD;&#xA;    cube = new THREE.Mesh(geometry, material);&#xD;&#xA;    scene.add(cube);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // ===============&#xD;&#xA;    // POST PROCESSING&#xD;&#xA;    // ===============&#xD;&#xA;&#xD;&#xA;    // COMPOSER&#xD;&#xA;    composer = new EffectComposer(renderer);&#xD;&#xA;&#xD;&#xA;    const renderPass = new RenderPass(scene, camera);&#xD;&#xA;    composer.addPass(renderPass);&#xD;&#xA;&#xD;&#xA;    outlinePass = new OutlinePass(new THREE.Vector2(width, height), scene, camera);&#xD;&#xA;    composer.addPass(outlinePass);&#xD;&#xA;&#xD;&#xA;    effectFXAA = new ShaderPass(FXAAShader);&#xD;&#xA;    effectFXAA.uniforms['resolution'].value.set(1 / width, 1 / height);&#xD;&#xA;    effectFXAA.renderToScreen = true;&#xD;&#xA;    composer.addPass(effectFXAA);&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;function animate() {&#xD;&#xA;    requestAnimationFrame(animate);&#xD;&#xA;    controls.update();&#xD;&#xA;    composer.render();&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;function onWindowResize() {&#xD;&#xA;&#xD;&#xA;    const width = window.innerWidth;&#xD;&#xA;    const height = window.innerHeight;&#xD;&#xA;&#xD;&#xA;    camera.aspect = width / height;&#xD;&#xA;    camera.updateProjectionMatrix();&#xD;&#xA;&#xD;&#xA;    renderer.setSize(width, height);&#xD;&#xA;    composer.setSize(width, height);&#xD;&#xA;&#xD;&#xA;    effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## The error&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# UPDATE #1&#xD;&#xA;I got the same error running the snippet of [this SO answer][3] so I'm wondering if the problem is relate to my specific pc, is it possible?&#xD;&#xA;&#xD;&#xA;Do I have to worry about users hardware when writing my threejs code?&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://threejs.org/examples/#webgl_postprocessing_outline&#xD;&#xA;  [2]: https://i.stack.imgur.com/Ar1Tu.png&#xD;&#xA;  [3]: https://stackoverflow.com/q/71990398&#xD;&#xA;  [4]: https://i.stack.imgur.com/EsVfu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38538" PostHistoryTypeId="2" PostId="13005" RevisionGUID="cb9264d2-e879-4abf-8956-6615d3eafd44" CreationDate="2022-09-28T20:55:42.913" UserId="8925" Text="I am trying to understand some shader code written in ARB. I am mostly using [this](https://registry.khronos.org/OpenGL/extensions/NV/NV_gpu_program5.txt) to understand it. However the doc doesn't explain (or I missed it) how vector operands are transformed into scalars, for example in this expression&#xD;&#xA;&#xD;&#xA;    MAD.F32 R1.y, R2, R1, R1.w;&#xD;&#xA;&#xD;&#xA;R2 and R1 are both 4 components vectors, but the swizzle is unspectified for R2 and the second R1. What is this instruction really doing? My hypothesis was that unspecified components were deduced using the result's component, thus the instruction would by equal to&#xD;&#xA;&#xD;&#xA;    MAD.F32 R1.y, R2.y, R1.y, R1.w;&#xD;&#xA;&#xD;&#xA;but it doesn't seems to be correct." ContentLicense="CC BY-SA 4.0" />
  <row Id="38540" PostHistoryTypeId="1" PostId="13005" RevisionGUID="cb9264d2-e879-4abf-8956-6615d3eafd44" CreationDate="2022-09-28T20:55:42.913" UserId="8925" Text="How does swizzling works in ARB shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38541" PostHistoryTypeId="3" PostId="13005" RevisionGUID="cb9264d2-e879-4abf-8956-6615d3eafd44" CreationDate="2022-09-28T20:55:42.913" UserId="8925" Text="|opengl|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38542" PostHistoryTypeId="50" PostId="10537" RevisionGUID="5655dc69-bd9b-422b-81f1-0d2a9e2426cc" CreationDate="2022-09-29T10:08:10.937" UserId="-1" />
  <row Id="38543" PostHistoryTypeId="2" PostId="13006" RevisionGUID="e5781e03-e007-49ae-952a-5b754065411a" CreationDate="2022-09-29T18:07:18.127" UserId="48" Text="Wow, NV assembly, a blast from the past! The semantics of this are that the calculation is done as if on a full 4-component vector, and then the destination register is masked so that the write only occurs to the selected component.&#xD;&#xA;&#xD;&#xA;So this should be effectively like&#xD;&#xA;```&#xD;&#xA;vec4 temp = R2.xyzw * R1.xyzw + R1.wwww;&#xD;&#xA;R1.y = temp.y;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(See [NV_gpu_program4](https://registry.khronos.org/OpenGL/extensions/NV/NV_gpu_program4.txt) spec, Section 2.X.4.3, &quot;Program Destination Variable Update&quot;.)&#xD;&#xA;&#xD;&#xA;But that agrees with the result being `R2.y * R1.y + R1.w` which you said doesn't seem to be correct, so I'm not sure what's going on." ContentLicense="CC BY-SA 4.0" />
  <row Id="38546" PostHistoryTypeId="5" PostId="13001" RevisionGUID="5f8e9915-509d-40bd-9a6e-641ad9ee2e3b" CreationDate="2022-09-30T11:12:39.583" UserId="209" Comment="added floor func to expression" Text="Re separating RGB, I guess you are referring to Lance Williams' &quot;[Pyramidal Parametrics&quot; paper][1].&#xD;&#xA;&#xD;&#xA;I suspect he did it that way to fit in with the graphics system he had, but on modern GPUs (at least since I started developing them in 1992) the channels are not separate. The MIP map chain is likely to be just a set of $N \times M$, $\lfloor \frac{N}{2} \rfloor \times \lfloor \frac{M}{2}\rfloor, ..., 1\times1 $ images *possibly* arranged semi-contiguously in memory.&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/800059.801126" ContentLicense="CC BY-SA 4.0" />
  <row Id="38550" PostHistoryTypeId="2" PostId="13007" RevisionGUID="b20a14e9-a78d-4525-a889-f8d5415d2be0" CreationDate="2022-10-01T11:38:37.207" UserId="18990" Text="I have a nurb/b-spline curve in 2d, and I want to sweep a cross section along it.&#xD;&#xA;&#xD;&#xA;Here is the curve and resulting &quot;tube&quot; (green points are control points):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;However, as you can see, the resulting &quot;tube&quot; becomes  thinner where the curve curves. So my question is, what is the correct way of sweeping a cross section along a bspline curve and obtaining constant height of the cross section?&#xD;&#xA;&#xD;&#xA;My current method is to pick some points along the curve (Greville points) (in the parametric coordinate system), and rotating the cross section such that it aligns with the normal of the curve at the current point...but it does not seems to work.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XgdPM.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/u0eZ7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38552" PostHistoryTypeId="1" PostId="13007" RevisionGUID="b20a14e9-a78d-4525-a889-f8d5415d2be0" CreationDate="2022-10-01T11:38:37.207" UserId="18990" Text="Sweeping cross section along nurbs curve" ContentLicense="CC BY-SA 4.0" />
  <row Id="38553" PostHistoryTypeId="3" PostId="13007" RevisionGUID="b20a14e9-a78d-4525-a889-f8d5415d2be0" CreationDate="2022-10-01T11:38:37.207" UserId="18990" Text="|nurbs|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38554" PostHistoryTypeId="2" PostId="13008" RevisionGUID="771a9af5-4ebf-408b-a2f4-987cc729107e" CreationDate="2022-10-01T18:07:04.797" UserId="18960" Text="Unfortunately, there are no real answers for this.  The problem is called 'offsetting'.  It is often investigated in the context of typefaces / fonts.   There is no analytical or exact solution for Bezier or NURBS curves.  &#xD;&#xA;&#xD;&#xA;One of the challenges is that curve segments easily get pinched off or other sigularities -- start with a loop and increase the offset distance.&#xD;&#xA;&#xD;&#xA;There are lots of heuristic methods out there that work more or less. Lots of academic papers.  Search around and you'll find them." ContentLicense="CC BY-SA 4.0" />
  <row Id="38556" PostHistoryTypeId="2" PostId="13009" RevisionGUID="6c2a5603-8282-43ec-a1ab-b6bc64870ca3" CreationDate="2022-10-02T09:17:32.883" UserId="18816" Text="I'm trying to implement the multiple importance sampling path tracing, the MIS path tracing uses the MIS to **combine the direct light sampling** and **brdf sampling** to evaluate the direct lighting.&#xD;&#xA;&#xD;&#xA;**The direct lighting estimator part** (the intersection point on the object is **pos**):&#xD;&#xA;1. sample a point P on the light plane and get the light intensity Li&#xD;&#xA;2. get dir = P - pos, wi = normalize(dir), dist2 = dot(dir, dir), light_pdf = 1 / area / light_cnt&#xD;&#xA;3. get the light_pdf wrt solid angle ==&gt; light_pdf_sa = light_pdf * dist2 / dot(light_normal, -wi)&#xD;&#xA;4. get the brdf_pdf wrt to wi, wo(the incident direction) and surface intersection info **rec**&#xD;&#xA;5. **calculate the `direct lighting part = eval(wi, wo, rec) * Li * dot(wi, n) / light_pdf_sa * powerhueristic(1., light_pdf_sa, 1., brdf_pdf)`**&#xD;&#xA;&#xD;&#xA;**The brdf estimator part:**&#xD;&#xA;1. sample an out direction wi wrt the wo and the material info &#xD;&#xA;2. shoot the shadow ray from pos with the direction wi and intersect with the scene&#xD;&#xA;3. if the shadow ray hit a light, then get the light color Li, light_pdf = 1/area/light_cnt, and the light_normal, dist2 (the square of the hit point and the surface point) go to 4&#xD;&#xA;4. get the light_pdf wrt solid angle ==&gt; light_pdf_sa = light_pdf * dist2 / dot(light_normal, -wi)&#xD;&#xA;5. get the brdf_pdf wrt to wi, wo(the incident direction) and surface intersection info **rec**&#xD;&#xA;6. **calculate the `brdf part = eval(wi, wo, rec) * Li * dot(wi, n) / brdf_pdf * powerhueristic(1., brdf_pdf, 1., light_pdf_sa)`**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Finally, add the direct lighting part and the brdf part together**&#xD;&#xA;&#xD;&#xA;## Here is the MIS direct lighting code:&#xD;&#xA;```c++&#xD;&#xA;bool direct_lighting_MIS(out vec3 wi, out vec3 weight, out vec3 L, const in vec3 wo, const in record rec){&#xD;&#xA;    vec3 n = rec.out_normal;&#xD;&#xA;    vec3 pt_on_obj = rec.pos;&#xD;&#xA;    vec3 pt_on_lit;&#xD;&#xA;    vec3 lit_normal;&#xD;&#xA;    float lit_pdf;&#xD;&#xA;    vec3 Li;&#xD;&#xA;    sample_from_light(pt_on_lit, lit_normal, lit_pdf, Li);&#xD;&#xA;    vec3 dir = pt_on_lit - pt_on_obj;&#xD;&#xA;    float dist = length(dir);&#xD;&#xA;    wi = normalize(dir);&#xD;&#xA;    L = vec3(0);&#xD;&#xA;    if(is_visible(pt_on_obj, dir, n) &amp;&amp; lit_pdf &gt; 0.){&#xD;&#xA;        float brdf_pdf = get_pdf(wi, wo, rec);&#xD;&#xA;        float lit_pdf_sa = lit_pdf * dist * dist / dot(lit_normal, -wi);&#xD;&#xA;        L += eval(wi, wo, rec) * Li * dot(n, wi) / lit_pdf_sa * &#xD;&#xA;             PowerHeuristic(1., lit_pdf_sa, 1., brdf_pdf);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if(sample_brdf(wi, weight, wo, rec)){&#xD;&#xA;        float brdf_pdf = get_pdf(wi, wo, rec);&#xD;&#xA;        ray r_t = ray(rec.pos, wi);&#xD;&#xA;        record rec_t;&#xD;&#xA;        bool valid;&#xD;&#xA;        hit(r_t, rec_t, valid);&#xD;&#xA;        float dist = length(at(r_t, rec_t.t) - r_t.A);&#xD;&#xA;        if(valid){&#xD;&#xA;            for(int i = 0; i &lt; light_cnts; i ++){&#xD;&#xA;                if(rec_t.obj_id == lights[i] &amp;&amp; !rec_t.is_back_face){&#xD;&#xA;                    lit_pdf = light_pdf(lights[i]);&#xD;&#xA;                    Li = light_intensity(rec_t.mat_id);&#xD;&#xA;                    float lit_pdf_sa = lit_pdf * dist * dist / dot(rec_t.normal, -wi);&#xD;&#xA;                    //float brdf_pdf_area = brdf_pdf * dot(rec_t.normal, -wi) / (dist * dist);&#xD;&#xA;                    L += eval(wi, wo, rec) * Li * dot(n, wi) / brdf_pdf *&#xD;&#xA;                         PowerHeuristic(1., brdf_pdf, 1., lit_pdf_sa);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    return false;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## Comparision between the image produced by MIS and the brute force image&#xD;&#xA;&#xD;&#xA;Here are the results:&#xD;&#xA;&#xD;&#xA;### MIS:&#xD;&#xA;&#xD;&#xA;[![MIS][1]][1]&#xD;&#xA;&#xD;&#xA;### Brute force&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;### the difference&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHMyf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/mXDVd.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/7kMC8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38558" PostHistoryTypeId="1" PostId="13009" RevisionGUID="6c2a5603-8282-43ec-a1ab-b6bc64870ca3" CreationDate="2022-10-02T09:17:32.883" UserId="18816" Text="MIS path tracing got darker image than brute force path tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="38559" PostHistoryTypeId="3" PostId="13009" RevisionGUID="6c2a5603-8282-43ec-a1ab-b6bc64870ca3" CreationDate="2022-10-02T09:17:32.883" UserId="18816" Text="|raytracing|lighting|brdf|sampling|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38560" PostHistoryTypeId="2" PostId="13010" RevisionGUID="7d068e8b-f660-46c5-88c4-3c23dc46a052" CreationDate="2022-10-02T10:05:48.193" UserId="18964" Text="I'm trying to apply a texture to 4 different triangle strips using JOGL (OpenGL/Java). I'm trying to make a 1000×1000 path in a square, where the path is 100 wide. The texture should be stamped 10 times on each side (though the corner pieces will have a diagonal discontinuity). I'm making 4 trapezoids here:&#xD;&#xA;&#xD;&#xA;	float[] positions = { /* S,W,N,E */&#xD;&#xA;			500,-50,500, 400,-50,400, -500,-50,500, -400,-50,400,&#xD;&#xA;			-500,-50,500, -400,-50,400, -500,-50,-500, -400,-50,-400,&#xD;&#xA;			-500,-50,-500, -400,-50,-400, 500,-50,-500, 400,-50,-400,&#xD;&#xA;			500,-50,-500, 400,-50,-400, 500,-50,500, 400,-50,400&#xD;&#xA;	};&#xD;&#xA;	float[] textureCoords = {&#xD;&#xA;		0f,0f, 1f,1f, 0f,10f, 1f,9f,&#xD;&#xA;		0f,0f, 1f,1f, 0f,10f, 1f,9f,&#xD;&#xA;		0f,0f, 1f,1f, 0f,10f, 1f,9f,&#xD;&#xA;		0f,0f, 1f,1f, 0f,10f, 1f,9f&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;I then get this data into VBOs, and every frame I draw with the following code:&#xD;&#xA;&#xD;&#xA;	gl.glActiveTexture(GL_TEXTURE0);&#xD;&#xA;	gl.glBindTexture(GL_TEXTURE_2D, textureIDs[0]);&#xD;&#xA;	gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);&#xD;&#xA;	for (int i=0; i&lt;4; i++) gl.glDrawArrays(GL_TRIANGLE_STRIP, i*4, 4);&#xD;&#xA;&#xD;&#xA;[![Texture smeared out][1]][1]&#xD;&#xA;&#xD;&#xA;The texture appears to be loading fine. You can see that it looks okay in one triangle of the trapezoid, within the range (0,0 -&gt; 1,1). But as soon as my interpolated (s,t) values leave that range, it just smears things. I'm very confused by this--isn't it supposed to tile, when I have texture coordinates beyond 1.0? Does this have something to do with using GL_TRIANGLE_STRIP to draw?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zQVZn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38562" PostHistoryTypeId="1" PostId="13010" RevisionGUID="7d068e8b-f660-46c5-88c4-3c23dc46a052" CreationDate="2022-10-02T10:05:48.193" UserId="18964" Text="Why is my texture being stretched out on a triangle strip?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38563" PostHistoryTypeId="3" PostId="13010" RevisionGUID="7d068e8b-f660-46c5-88c4-3c23dc46a052" CreationDate="2022-10-02T10:05:48.193" UserId="18964" Text="|opengl|texture|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38564" PostHistoryTypeId="50" PostId="12143" RevisionGUID="6e833c10-b10e-4768-b47f-8202d2337ed2" CreationDate="2022-10-02T13:06:15.700" UserId="-1" />
  <row Id="38565" PostHistoryTypeId="2" PostId="13011" RevisionGUID="15003b54-e285-4fe5-abc9-abdddde21a9b" CreationDate="2022-10-02T14:34:16.083" UserId="18994" Text="You are on the right track with setting `GL_TEXTURE_WRAP_S` to `GL_REPEAT`. However, `GL_TEXTURE_WRAP_S` affects only the first texture coordinate, called $ s $. In your code, you are trying to use the second coordinate, $ t $, to repeat the texture. For that, you need to set `GL_TEXTURE_WRAP_T`:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Also, note that you do not necessarily need to set these texture parameters every frame. You can just set them once when creating the texture.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;\* Texture coordinates are also often labelled $ u $ and $ v $, but OpenGL labels them $ s $ and $ t $." ContentLicense="CC BY-SA 4.0" />
  <row Id="38577" PostHistoryTypeId="2" PostId="13014" RevisionGUID="730fae2d-a3dc-4fec-bc50-65813a990f28" CreationDate="2022-10-03T13:05:02.763" UserId="18894" Text="First off let me say that the first line in 5.2.2 is wrong or misleading when it says &quot;spectral response curves, one for each of red, green, and blue, as emitted by the display&quot;. A &quot;spectral response curve&quot; is the property of a sensor, such as the human eye or a camera sensor, which responds to light. For an emitter of light such as a display, the equivalent is an &quot;emission curve&quot; or more commonly &quot;spectral power distribution (SPD)&quot;.&#xD;&#xA;&#xD;&#xA;The XYZ values are the device independent specification of a colour, and can be calculated using the specific spectral response curves called colour matching functions (CMFs). The XYZ systen is defined that any real colour will have X, Y and Z values in the range of 0 to 1, though not all combinations of values in that range are physically possible colours.&#xD;&#xA;&#xD;&#xA;The CMFs are available from the Colour and Vision Research laboratory here http://www.cvrl.org/, under the &quot;CMFs&quot; link. They look like this, with the X CMF displayed in red, Y displayed in green and Z displayed in blue.&#xD;&#xA;&#xD;&#xA;[![tristimuls CMFs plotted][1]][1]&#xD;&#xA;&#xD;&#xA;You can combine any SPD with these CMFs to get the XYZ values of that SPD, that is what the function is doing. By multiplyng the amount of each wavelength emitted by one of the RGB emitters in the display with the response strength of the CMF and summing them together, you calculate the total response to that emitter. By doing this for each of the X, Y and Z CMFs you get the XYZ value of the colour of that emitter.&#xD;&#xA;&#xD;&#xA;For sRGB monitors these should be approximately (in XYZ order):  &#xD;&#xA;R: (0.4124564 0.2126729 0.0193339)  &#xD;&#xA;G: (0.3575761 0.7151522 0.1191920)  &#xD;&#xA;B: (0.1804375 0.0721750 0.9503041)  &#xD;&#xA;&#xD;&#xA;If you look at the values in the RGBToXYZ function you will see these approximate values in the matrix, but arranged vertically rather than horizontally.&#xD;&#xA;&#xD;&#xA;Many different SPDs could give these same XYZ values, but any SPD with the same XYZ values should look the same to the human eye, so it does not matter that different monitors have different SPDs, as long as they have the same XYZ values.&#xD;&#xA;&#xD;&#xA;Once you have these values for the monitor, you can convert any colour's XYZ values to the required RGB values using the XYZToRGB function. If all three values are in the range 0 to 1, you can display the colour on the monitor. If any value is outside of the range of 0 to 1, then the colour is outside of the gamut of the monitor, and cannot be displayed accurately on that monitor.&#xD;&#xA;&#xD;&#xA;The reason for doing this is to convert an SPD to three values in RGB or XYZ, which is much easier to manage than the full detail of the SPD, and in most cases is an adequate description of the SPD. You can just sum the XYZ values for each SPD multiplied by the linear RGB value for each to get the resulting total XYZ, which is much simpler than calculating the combined SPD and then calculating the XYZ of the combined SPD, but will give the same answer.&#xD;&#xA;&#xD;&#xA;One last note, throughout the article you refer to and this answer, RGB values are given as LINEAR RGB values. In practice RGB values are usually given as GAMMA-ENCODED RGB values for efficiency, so there is an additional step you would need to do in practice to convert the values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pSAic.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38583" PostHistoryTypeId="5" PostId="13014" RevisionGUID="bc4482b9-9318-4969-8f5a-4842e9d55ae9" CreationDate="2022-10-03T18:22:36.800" UserId="18894" Comment="edited body" Text="First off let me say that the first line in 5.2.2 is wrong or misleading when it says &quot;spectral response curves, one for each of red, green, and blue, as emitted by the display&quot;. A &quot;spectral response curve&quot; is the property of a sensor, such as the human eye or a camera sensor, which responds to light. For an emitter of light such as a display, the equivalent is an &quot;emission curve&quot; or more commonly &quot;spectral power distribution (SPD)&quot;.&#xD;&#xA;&#xD;&#xA;The XYZ values are the device independent specification of a colour, and can be calculated using the specific spectral response curves called colour matching functions (CMFs). The XYZ system is defined that any real colour will have X, Y and Z values in the range of 0 to 1, though not all combinations of values in that range are physically possible colours.&#xD;&#xA;&#xD;&#xA;The CMFs are available from the Colour and Vision Research laboratory here http://www.cvrl.org/, under the &quot;CMFs&quot; link. They look like this, with the X CMF displayed in red, Y displayed in green and Z displayed in blue.&#xD;&#xA;&#xD;&#xA;[![tristimuls CMFs plotted][1]][1]&#xD;&#xA;&#xD;&#xA;You can combine any SPD with these CMFs to get the XYZ values of that SPD, that is what the function is doing. By multiplyng the amount of each wavelength emitted by one of the RGB emitters in the display with the response strength of the CMF and summing them together, you calculate the total response to that emitter. By doing this for each of the X, Y and Z CMFs you get the XYZ value of the colour of that emitter.&#xD;&#xA;&#xD;&#xA;For sRGB monitors these should be approximately (in XYZ order):  &#xD;&#xA;R: (0.4124564 0.2126729 0.0193339)  &#xD;&#xA;G: (0.3575761 0.7151522 0.1191920)  &#xD;&#xA;B: (0.1804375 0.0721750 0.9503041)  &#xD;&#xA;&#xD;&#xA;If you look at the values in the RGBToXYZ function you will see these approximate values in the matrix, but arranged vertically rather than horizontally.&#xD;&#xA;&#xD;&#xA;Many different SPDs could give these same XYZ values, but any SPD with the same XYZ values should look the same to the human eye, so it does not matter that different monitors have different SPDs, as long as they have the same XYZ values.&#xD;&#xA;&#xD;&#xA;Once you have these values for the monitor, you can convert any colour's XYZ values to the required RGB values using the XYZToRGB function. If all three values are in the range 0 to 1, you can display the colour on the monitor. If any value is outside of the range of 0 to 1, then the colour is outside of the gamut of the monitor, and cannot be displayed accurately on that monitor.&#xD;&#xA;&#xD;&#xA;The reason for doing this is to convert an SPD to three values in RGB or XYZ, which is much easier to manage than the full detail of the SPD, and in most cases is an adequate description of the SPD. You can just sum the XYZ values for each SPD multiplied by the linear RGB value for each to get the resulting total XYZ, which is much simpler than calculating the combined SPD and then calculating the XYZ of the combined SPD, but will give the same answer.&#xD;&#xA;&#xD;&#xA;One last note, throughout the article you refer to and this answer, RGB values are given as LINEAR RGB values. In practice RGB values are usually given as GAMMA-ENCODED RGB values for efficiency, so there is an additional step you would need to do in practice to convert the values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pSAic.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38584" PostHistoryTypeId="5" PostId="13009" RevisionGUID="7c94b0f0-8506-4b43-8fe6-ab5d0be7b1d3" CreationDate="2022-10-04T01:58:09.790" UserId="18816" Comment="added 118 characters in body" Text="I'm trying to implement the multiple importance sampling path tracing, the MIS path tracing uses the MIS to **combine the direct light sampling** and **brdf sampling** to evaluate the direct lighting.&#xD;&#xA;&#xD;&#xA;**The direct lighting estimator part** (the intersection point on the object is **pos**):&#xD;&#xA;1. sample a point P on the light plane and get the light intensity Li&#xD;&#xA;2. get dir = P - pos, wi = normalize(dir), dist2 = dot(dir, dir), light_pdf = 1 / area / light_cnt&#xD;&#xA;3. get the light_pdf wrt solid angle ==&gt; light_pdf_sa = light_pdf * dist2 / dot(light_normal, -wi)&#xD;&#xA;4. get the brdf_pdf wrt to wi, wo(the incident direction) and surface intersection info **rec**&#xD;&#xA;5. **calculate the `direct lighting part = eval(wi, wo, rec) * Li * dot(wi, n) / light_pdf_sa * powerhueristic(1., light_pdf_sa, 1., brdf_pdf)`**&#xD;&#xA;&#xD;&#xA;**The brdf estimator part:**&#xD;&#xA;1. sample an out direction wi wrt the wo and the material info &#xD;&#xA;2. shoot the shadow ray from pos with the direction wi and intersect with the scene&#xD;&#xA;3. if the shadow ray hit a light, then get the light color Li, light_pdf = 1/area/light_cnt, and the light_normal, dist2 (the square of the hit point and the surface point) go to 4&#xD;&#xA;4. get the light_pdf wrt solid angle ==&gt; light_pdf_sa = light_pdf * dist2 / dot(light_normal, -wi)&#xD;&#xA;5. get the brdf_pdf wrt to wi, wo(the incident direction) and surface intersection info **rec**&#xD;&#xA;6. **calculate the `brdf part = eval(wi, wo, rec) * Li * dot(wi, n) / brdf_pdf * powerhueristic(1., brdf_pdf, 1., light_pdf_sa)`**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Finally, add the direct lighting part and the brdf part together**&#xD;&#xA;&#xD;&#xA;## Here is the MIS direct lighting code:&#xD;&#xA;```c++&#xD;&#xA;bool direct_lighting_MIS(out vec3 wi, out vec3 weight, out vec3 L, const in vec3 wo, const in record rec){&#xD;&#xA;    vec3 n = rec.out_normal;&#xD;&#xA;    vec3 pt_on_obj = rec.pos;&#xD;&#xA;    vec3 pt_on_lit;&#xD;&#xA;    vec3 lit_normal;&#xD;&#xA;    float lit_pdf;&#xD;&#xA;    vec3 Li;&#xD;&#xA;    sample_from_light(pt_on_lit, lit_normal, lit_pdf, Li);&#xD;&#xA;    vec3 dir = pt_on_lit - pt_on_obj;&#xD;&#xA;    float dist = length(dir);&#xD;&#xA;    wi = normalize(dir);&#xD;&#xA;    L = vec3(0);&#xD;&#xA;    if(is_visible(pt_on_obj, dir, n) &amp;&amp; lit_pdf &gt; 0.){&#xD;&#xA;        float brdf_pdf = get_pdf(wi, wo, rec);&#xD;&#xA;        float lit_pdf_sa = lit_pdf * dist * dist / dot(lit_normal, -wi);&#xD;&#xA;        L += eval(wi, wo, rec) * Li * dot(n, wi) / lit_pdf_sa * &#xD;&#xA;             PowerHeuristic(1., lit_pdf_sa, 1., brdf_pdf);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if(sample_brdf(wi, weight, wo, rec)){&#xD;&#xA;        float brdf_pdf = get_pdf(wi, wo, rec);&#xD;&#xA;        ray r_t = ray(rec.pos, wi);&#xD;&#xA;        record rec_t;&#xD;&#xA;        bool valid;&#xD;&#xA;        hit(r_t, rec_t, valid);&#xD;&#xA;        float dist = length(at(r_t, rec_t.t) - r_t.A);&#xD;&#xA;        if(valid){&#xD;&#xA;            for(int i = 0; i &lt; light_cnts; i ++){&#xD;&#xA;                if(rec_t.obj_id == lights[i] &amp;&amp; !rec_t.is_back_face){&#xD;&#xA;                    lit_pdf = light_pdf(lights[i]);&#xD;&#xA;                    Li = light_intensity(rec_t.mat_id);&#xD;&#xA;                    float lit_pdf_sa = lit_pdf * dist * dist / dot(rec_t.normal, -wi);&#xD;&#xA;                    //float brdf_pdf_area = brdf_pdf * dot(rec_t.normal, -wi) / (dist * dist);&#xD;&#xA;                    L += eval(wi, wo, rec) * Li * dot(n, wi) / brdf_pdf *&#xD;&#xA;                         PowerHeuristic(1., brdf_pdf, 1., lit_pdf_sa);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    return false;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## Comparision between the image produced by MIS and the brute force image&#xD;&#xA;&#xD;&#xA;Here are the results:&#xD;&#xA;&#xD;&#xA;### MIS:&#xD;&#xA;&#xD;&#xA;[![MIS][1]][1]&#xD;&#xA;&#xD;&#xA;[link][2]&#xD;&#xA;&#xD;&#xA;### Brute force&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[link][4]&#xD;&#xA;&#xD;&#xA;### the difference&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHMyf.png&#xD;&#xA;  [2]: https://www.shadertoy.com/view/7lGfDm&#xD;&#xA;  [3]: https://i.stack.imgur.com/mXDVd.png&#xD;&#xA;  [4]: https://www.shadertoy.com/view/7tGBDw&#xD;&#xA;  [5]: https://i.stack.imgur.com/7kMC8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38591" PostHistoryTypeId="2" PostId="13017" RevisionGUID="83f1925a-63d1-4d7f-976d-c76118be4240" CreationDate="2022-10-04T19:42:32.733" UserId="4958" Text="In specular reflection result depends on view vector from camera to point. Because of that, when doing temporal reprojection and reprojecting position of current fragment while camera is translating, result color is changing and it induces ghosting. To mitigate this, motion is detected to dampen temporal reuse when moving. In diffuse there is no such dependance and this problem doesn't exists.&#xD;&#xA;&#xD;&#xA;Is there a method to calculate aproximate position of current frame specular color (if it exists) in previous frame to produce a coherent results?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38593" PostHistoryTypeId="1" PostId="13017" RevisionGUID="83f1925a-63d1-4d7f-976d-c76118be4240" CreationDate="2022-10-04T19:42:32.733" UserId="4958" Text="Temporal reprojection of specular reflection - finding previous frame color" ContentLicense="CC BY-SA 4.0" />
  <row Id="38594" PostHistoryTypeId="3" PostId="13017" RevisionGUID="83f1925a-63d1-4d7f-976d-c76118be4240" CreationDate="2022-10-04T19:42:32.733" UserId="4958" Text="|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38595" PostHistoryTypeId="6" PostId="13017" RevisionGUID="8e4b549c-8110-4df9-b370-39b161116449" CreationDate="2022-10-04T19:49:27.490" UserId="4958" Comment="edited tags" Text="|algorithm|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38596" PostHistoryTypeId="5" PostId="13009" RevisionGUID="56416c85-62bc-4354-971d-2da8a491121b" CreationDate="2022-10-05T00:57:00.423" UserId="18816" Comment="added 193 characters in body" Text="I'm trying to implement the multiple importance sampling path tracing, the MIS path tracing uses the MIS to **combine the direct light sampling** and **brdf sampling** to evaluate the direct lighting.&#xD;&#xA;&#xD;&#xA;**The direct lighting estimator part** (the intersection point on the object is **pos**):&#xD;&#xA;1. sample a point P on the light plane and get the light intensity Li&#xD;&#xA;2. get dir = P - pos, wi = normalize(dir), dist2 = dot(dir, dir), light_pdf = 1 / area / light_cnt&#xD;&#xA;3. get the light_pdf wrt solid angle ==&gt; light_pdf_sa = light_pdf * dist2 / dot(light_normal, -wi)&#xD;&#xA;4. get the brdf_pdf wrt to wi, wo(the incident direction) and surface intersection info **rec**&#xD;&#xA;5. **calculate the `direct lighting part = eval(wi, wo, rec) * Li * dot(wi, n) / light_pdf_sa * powerhueristic(1., light_pdf_sa, 1., brdf_pdf)`**&#xD;&#xA;&#xD;&#xA;**The brdf estimator part:**&#xD;&#xA;1. sample an out direction wi wrt the wo and the material info &#xD;&#xA;2. shoot the shadow ray from pos with the direction wi and intersect with the scene&#xD;&#xA;3. if the shadow ray hit a light, then get the light color Li, light_pdf = 1/area/light_cnt, and the light_normal, dist2 (the square of the hit point and the surface point) go to 4&#xD;&#xA;4. get the light_pdf wrt solid angle ==&gt; light_pdf_sa = light_pdf * dist2 / dot(light_normal, -wi)&#xD;&#xA;5. get the brdf_pdf wrt to wi, wo(the incident direction) and surface intersection info **rec**&#xD;&#xA;6. **calculate the `brdf part = eval(wi, wo, rec) * Li * dot(wi, n) / brdf_pdf * powerhueristic(1., brdf_pdf, 1., light_pdf_sa)`**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Finally, add the direct lighting part and the brdf part together**&#xD;&#xA;&#xD;&#xA;## Here is the MIS direct lighting code:&#xD;&#xA;```c++&#xD;&#xA;bool direct_lighting_MIS(out vec3 wi, out vec3 weight, out vec3 L, const in vec3 wo, const in record rec){&#xD;&#xA;    vec3 n = rec.out_normal;&#xD;&#xA;    vec3 pt_on_obj = rec.pos;&#xD;&#xA;    vec3 pt_on_lit;&#xD;&#xA;    vec3 lit_normal;&#xD;&#xA;    float lit_pdf;&#xD;&#xA;    vec3 Li;&#xD;&#xA;    sample_from_light(pt_on_lit, lit_normal, lit_pdf, Li);&#xD;&#xA;    vec3 dir = pt_on_lit - pt_on_obj;&#xD;&#xA;    float dist = length(dir);&#xD;&#xA;    wi = normalize(dir);&#xD;&#xA;    L = vec3(0);&#xD;&#xA;    if(is_visible(pt_on_obj, dir, n) &amp;&amp; lit_pdf &gt; 0.){&#xD;&#xA;        float brdf_pdf = get_pdf(wi, wo, rec);&#xD;&#xA;        float lit_pdf_sa = lit_pdf * dist * dist / dot(lit_normal, -wi);&#xD;&#xA;        L += eval(wi, wo, rec) * Li * dot(n, wi) / lit_pdf_sa * &#xD;&#xA;             PowerHeuristic(1., lit_pdf_sa, 1., brdf_pdf);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    if(sample_brdf(wi, weight, wo, rec)){&#xD;&#xA;        float brdf_pdf = get_pdf(wi, wo, rec);&#xD;&#xA;        ray r_t = ray(rec.pos, wi);&#xD;&#xA;        record rec_t;&#xD;&#xA;        bool valid;&#xD;&#xA;        hit(r_t, rec_t, valid);&#xD;&#xA;        float dist = length(at(r_t, rec_t.t) - r_t.A);&#xD;&#xA;        if(valid){&#xD;&#xA;            for(int i = 0; i &lt; light_cnts; i ++){&#xD;&#xA;                if(rec_t.obj_id == lights[i] &amp;&amp; !rec_t.is_back_face){&#xD;&#xA;                    lit_pdf = light_pdf(lights[i]);&#xD;&#xA;                    Li = light_intensity(rec_t.mat_id);&#xD;&#xA;                    float lit_pdf_sa = lit_pdf * dist * dist / dot(rec_t.normal, -wi);&#xD;&#xA;                    //float brdf_pdf_area = brdf_pdf * dot(rec_t.normal, -wi) / (dist * dist);&#xD;&#xA;                    L += eval(wi, wo, rec) * Li * dot(n, wi) / brdf_pdf *&#xD;&#xA;                         PowerHeuristic(1., brdf_pdf, 1., lit_pdf_sa);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return true;&#xD;&#xA;    }&#xD;&#xA;    return false;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## Comparision between the image produced by MIS and the brute force image&#xD;&#xA;&#xD;&#xA;Here are the results:&#xD;&#xA;&#xD;&#xA;### MIS:&#xD;&#xA;&#xD;&#xA;[![MIS][1]][1]&#xD;&#xA;&#xD;&#xA;[link][2]&#xD;&#xA;&#xD;&#xA;### Brute force&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[link][4]&#xD;&#xA;&#xD;&#xA;### the difference&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;## Edit 2022/10/5:&#xD;&#xA;After disabling ANGLE in chrome and launching chrome in OpenGL mode, the brightness of MIS and brute force appears to be the same (I don't know why and it's ridiculous...)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHMyf.png&#xD;&#xA;  [2]: https://www.shadertoy.com/view/7lGfDm&#xD;&#xA;  [3]: https://i.stack.imgur.com/mXDVd.png&#xD;&#xA;  [4]: https://www.shadertoy.com/view/7tGBDw&#xD;&#xA;  [5]: https://i.stack.imgur.com/7kMC8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38602" PostHistoryTypeId="2" PostId="13019" RevisionGUID="35ab5d75-1ddb-4c96-8620-94203a75fa85" CreationDate="2022-10-06T08:50:53.910" UserId="19015" Text="I have a voxel grid and a conic surface (hollow cone) placed in the grid. &#xD;&#xA;&#xD;&#xA;I want to know **which voxels intersect with the cone surface and how much**. &#xD;&#xA;&#xD;&#xA;So far I have tried sampling points on the conic surface and then match them to the voxels but this solution is quiet cumbersome. &#xD;&#xA;&#xD;&#xA;Is there some cone tracing algorithm that would only consider the surface of it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38604" PostHistoryTypeId="1" PostId="13019" RevisionGUID="35ab5d75-1ddb-4c96-8620-94203a75fa85" CreationDate="2022-10-06T08:50:53.910" UserId="19015" Text="Tracing conic surface through voxel grid" ContentLicense="CC BY-SA 4.0" />
  <row Id="38605" PostHistoryTypeId="3" PostId="13019" RevisionGUID="35ab5d75-1ddb-4c96-8620-94203a75fa85" CreationDate="2022-10-06T08:50:53.910" UserId="19015" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38607" PostHistoryTypeId="2" PostId="13020" RevisionGUID="9bb3d83a-9e8b-466d-8411-b8b36bac2752" CreationDate="2022-10-07T10:38:13.120" UserId="18798" Text="Suppose we have an 512x512 image, then the value of pixel j should be  $I_j = \int_{0}^{512} \int_{0}^{512} h_j(u,v)L(u,v) \,dudv$, where $h_j(u,v)$ is the filter function for pixel j, $L(u,v)$ is the corresponding radiance function.&#xD;&#xA;&#xD;&#xA;In practice, we compute the value of pixel j by the formual $\frac{\sum_{i=1}^{N} h_j(u_i,v_i)L(u_i,v_i)}{\sum_{i=1}^{N} h_j(u_i,v_i)}$. Veach said that this estimate is slightly biased in page 308 in his thesis.&#xD;&#xA;&#xD;&#xA;So my question is what's the expectation of this estimate?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38609" PostHistoryTypeId="1" PostId="13020" RevisionGUID="9bb3d83a-9e8b-466d-8411-b8b36bac2752" CreationDate="2022-10-07T10:38:13.120" UserId="18798" Text="Question about reconstruction filter in ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38610" PostHistoryTypeId="3" PostId="13020" RevisionGUID="9bb3d83a-9e8b-466d-8411-b8b36bac2752" CreationDate="2022-10-07T10:38:13.120" UserId="18798" Text="|raytracing|rendering|pathtracing|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38611" PostHistoryTypeId="2" PostId="13021" RevisionGUID="9c7c07bf-bed9-46a7-ab5b-ef70f6b6807d" CreationDate="2022-10-07T16:01:22.880" UserId="16662" Text="If I'm understanding things correctly (please correct me if I'm wrong):&#xD;&#xA; - All modern graphics APIs (vulkan, dx12, metal, webgpu) provide ways to **bundle** and replay draw calls. The bundle includes which vertices + indices for all bundled draw calls, so frame to frame you're *not changing which triangles are drawn* in the bundle. This saves a ton of CPU work.&#xD;&#xA; - With **frustum/occlusion culling**, each frame, you would typically test each object against the view pyramid and skip the draw calls for objects that are outside the view.&#xD;&#xA;&#xD;&#xA;**How should these work together?** &#xD;&#xA;With bundling, you lose the fine-grain ability to decide which sets of triangles to draw, so how do you achieve frustum culling?&#xD;&#xA;&#xD;&#xA;The only option I can think of is to have many bundles, ideally of co-located objects, and maintain some bounding volume for the whole bundle and frustum cull at the bundle level.&#xD;&#xA;&#xD;&#xA;But it seems difficult to maintain co-located sets of objects. Are the bundles anchored to a region of space and objects move in and out of that bundle? That seems like it'd cause a lot of rebundling.&#xD;&#xA;&#xD;&#xA;How do people solve this, or what part of the problem am I misunderstanding?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38613" PostHistoryTypeId="1" PostId="13021" RevisionGUID="9c7c07bf-bed9-46a7-ab5b-ef70f6b6807d" CreationDate="2022-10-07T16:01:22.880" UserId="16662" Text="How to do frustum culling with draw call bundling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38614" PostHistoryTypeId="3" PostId="13021" RevisionGUID="9c7c07bf-bed9-46a7-ab5b-ef70f6b6807d" CreationDate="2022-10-07T16:01:22.880" UserId="16662" Text="|vulkan|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38615" PostHistoryTypeId="2" PostId="13022" RevisionGUID="b7665278-4c9d-4bc3-9e09-2ae3698d8ef5" CreationDate="2022-10-07T18:08:37.623" UserId="19022" Text="Given a normal vector in 3D-Space, how can I rotate the vector, such it points to a point in 3D-Space.&#xD;&#xA;&#xD;&#xA;I tried couple of ways doing this, which ended up looking completely wrong.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p2lsU.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38617" PostHistoryTypeId="1" PostId="13022" RevisionGUID="b7665278-4c9d-4bc3-9e09-2ae3698d8ef5" CreationDate="2022-10-07T18:08:37.623" UserId="19022" Text="Point a normal vector towards a point in 3D-Space" ContentLicense="CC BY-SA 4.0" />
  <row Id="38618" PostHistoryTypeId="3" PostId="13022" RevisionGUID="b7665278-4c9d-4bc3-9e09-2ae3698d8ef5" CreationDate="2022-10-07T18:08:37.623" UserId="19022" Text="|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38619" PostHistoryTypeId="6" PostId="13022" RevisionGUID="b1769ff7-9d9c-4cd0-b68d-1194ed4f0bae" CreationDate="2022-10-07T18:18:10.940" UserId="19022" Comment="edited tags" Text="|opengl|3d|mathematics|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38620" PostHistoryTypeId="2" PostId="13023" RevisionGUID="a3276891-d2ec-47a4-a4b8-1c8065c08b07" CreationDate="2022-10-07T18:37:54.563" UserId="48" Text="If by bundles you mean secondary command buffers, I think the answer is that people generally don't use them, or at least not in the sense you mean. They might be used to parallelize command recording across threads, but not to reduce draw-call-related overhead because, as you mention, the set of things to be drawn in a frame changes constantly, due to both frustum/occlusion and also LOD switching, as well as any moving objects or other changes that may be happening in the rendered world.&#xD;&#xA;&#xD;&#xA;There are other ways to address draw-call overhead, including:&#xD;&#xA; * Pull together vertex and index buffers for different objects into larger buffers, so you're not constantly having to switch between buffers. You can issue draw calls with the starting vertex offset and index offset parameters to draw a subset of vertices/triangles from a larger buffer.&#xD;&#xA; * Similar things can be done for constant buffers, bindless textures,&#xD;&#xA;   etc. Usually it's not the individual draw calls that create CPU&#xD;&#xA;   overhead so much as the state changes between them.&#xD;&#xA; * Use instancing and/or indirect draws (ExecuteIndirect, vkCmdDrawIndirect, etc) to execute a large number of draw calls with one API-level command.&#xD;&#xA; * Move culling and LOD selection to the GPU (&quot;GPU-driven rendering&quot;), taking advantage of GPU compute to offload those tasks from the CPU." ContentLicense="CC BY-SA 4.0" />
  <row Id="38622" PostHistoryTypeId="5" PostId="13021" RevisionGUID="36442fdf-7e93-4f25-8dda-88629972671e" CreationDate="2022-10-07T19:20:55.603" UserId="16662" Comment="added 507 characters in body" Text="If I'm understanding things correctly (please correct me if I'm wrong):&#xD;&#xA; - All modern graphics APIs (vulkan, dx12, metal, webgpu) provide ways to **bundle** and replay draw calls. The bundle includes which vertices + indices for all bundled draw calls, so frame to frame you're *not changing which triangles are drawn* in the bundle. This saves a ton of CPU work.&#xD;&#xA; - With **frustum/occlusion culling**, each frame, you would typically test each object against the view pyramid and skip the draw calls for objects that are outside the view.&#xD;&#xA;&#xD;&#xA;**How should these work together?** &#xD;&#xA;With bundling, you lose the fine-grain ability to decide which sets of triangles to draw, so how do you achieve frustum culling?&#xD;&#xA;&#xD;&#xA;The only option I can think of is to have many bundles, ideally of co-located objects, and maintain some bounding volume for the whole bundle and frustum cull at the bundle level.&#xD;&#xA;&#xD;&#xA;But it seems difficult to maintain co-located sets of objects. Are the bundles anchored to a region of space and objects move in and out of that bundle? That seems like it'd cause a lot of rebundling.&#xD;&#xA;&#xD;&#xA;How do people solve this, or what part of the problem am I misunderstanding?&#xD;&#xA;&#xD;&#xA;**Edit, more context**: I'm building my first (from scratch) renderer using WebGPU which calls this &quot;bundling&quot;[0][1] and since this sits on top of {DX12,Metal,Vulkan}, I assume all these APIs can implement this. My understanding is that bundling is one of the big performance wins in webgpu over webgl. (Note: there doesn't seem to be a webgpu tag on this site yet.)&#xD;&#xA;&#xD;&#xA;[0] https://gpuweb.github.io/gpuweb/#bundles&#xD;&#xA;&#xD;&#xA;[1] https://austin-eng.com/webgpu-samples/samples/animometer (Chrome only; see &quot;bundle&quot; option)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38623" PostHistoryTypeId="2" PostId="13024" RevisionGUID="ac7918cc-dd5d-486c-8e77-66c8f8dff3ac" CreationDate="2022-10-07T22:12:38.513" UserId="10096" Text="Let $e,f$ be the two edges of the triangle.  Let's construct an orthonormal system: $e = normalize(e)$, $n = normalize(e\times f)$, $f = n \times e$, whete $\times$ is the cross product. Now compute:&#xD;&#xA;&#xD;&#xA;$$e' = e - \frac{e \cdot n'}{1+(n\cdot n')}(n+n')$$&#xD;&#xA;&#xD;&#xA;$$f' = f - \frac{f \cdot n'}{1+(n\cdot n')}(n+n')$$&#xD;&#xA;&#xD;&#xA;Then the rotation matrix is:&#xD;&#xA;&#xD;&#xA;$$R = \begin{bmatrix} e' &amp; f' &amp; n'\end{bmatrix} \begin{bmatrix} e^T \\ f^T \\ n^T \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Note that the computation of $e'$ and $f'$  breaks for $n' = -n$." ContentLicense="CC BY-SA 4.0" />
  <row Id="38625" PostHistoryTypeId="5" PostId="13024" RevisionGUID="7e5f7e8e-92c8-4593-933f-02803a9d4f3a" CreationDate="2022-10-08T00:37:26.403" UserId="10096" Comment="edited body" Text="Let $e,f$ be the two edges of the triangle.  Let's construct an orthonormal system: $e = normalize(e)$, $n = normalize(e\times f)$, $f = n \times e$, where $\times$ is the cross product. Now compute:&#xD;&#xA;&#xD;&#xA;$$e' = e - \frac{e \cdot n'}{1+(n\cdot n')}(n+n')$$&#xD;&#xA;&#xD;&#xA;$$f' = f - \frac{f \cdot n'}{1+(n\cdot n')}(n+n')$$&#xD;&#xA;&#xD;&#xA;Then the rotation matrix is:&#xD;&#xA;&#xD;&#xA;$$R = \begin{bmatrix} e' &amp; f' &amp; n'\end{bmatrix} \begin{bmatrix} e^T \\ f^T \\ n^T \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;Note that the computation of $e'$ and $f'$  breaks for $n' = -n$." ContentLicense="CC BY-SA 4.0" />
  <row Id="38627" PostHistoryTypeId="5" PostId="13021" RevisionGUID="93a2fc82-e6eb-4f0f-ab30-5cd2d40a3b45" CreationDate="2022-10-08T16:33:56.940" UserId="16662" Comment="deleted 15 characters in body" Text="If I'm understanding things correctly (please correct me if I'm wrong):&#xD;&#xA; - All modern graphics APIs (vulkan, dx12, metal, webgpu) provide ways to **bundle** and replay draw calls. The bundle includes which vertices + indices for all bundled draw calls, so frame to frame you're *not changing which triangles are drawn* in the bundle. This saves a ton of CPU work.&#xD;&#xA; - With **frustum/occlusion culling**, each frame, you would typically test each object against the view pyramid and skip the draw calls for objects that are outside the view.&#xD;&#xA;&#xD;&#xA;**How should these work together?** &#xD;&#xA;With bundling, you lose the fine-grain ability to decide which sets of triangles to draw, so how do you achieve frustum culling?&#xD;&#xA;&#xD;&#xA;The only option I can think of is to have many bundles, ideally of co-located objects, and maintain some bounding volume for the whole bundle and frustum cull at the bundle level.&#xD;&#xA;&#xD;&#xA;But it seems difficult to maintain co-located sets of objects. Are the bundles anchored to a region of space and objects move in and out of that bundle? That seems like it'd cause a lot of rebundling.&#xD;&#xA;&#xD;&#xA;How do people solve this, or what part of the problem am I misunderstanding?&#xD;&#xA;&#xD;&#xA;**Edit, more context**: I'm building my first renderer using WebGPU which calls this &quot;bundling&quot;[0][1] and since this sits on top of {DX12,Metal,Vulkan}, I assume all these APIs can implement this. My understanding is that bundling is one of the big performance wins in webgpu over webgl. (Note: there doesn't seem to be a webgpu tag on this site yet.)&#xD;&#xA;&#xD;&#xA;[0] https://gpuweb.github.io/gpuweb/#bundles&#xD;&#xA;&#xD;&#xA;[1] https://austin-eng.com/webgpu-samples/samples/animometer (Chrome only; see &quot;bundle&quot; option)" ContentLicense="CC BY-SA 4.0" />
  <row Id="38628" PostHistoryTypeId="2" PostId="13025" RevisionGUID="a887e994-c31e-4e20-816b-fe857c3b8d5d" CreationDate="2022-10-09T09:55:36.480" UserId="19030" Text="A generalised circle is either a circle in the plane or a line. The general equation of one is:&#xD;&#xA;&#xD;&#xA;$$A(x^2 + y^2) + Bx + Cy + D=0,$$&#xD;&#xA;&#xD;&#xA;where $4AD - B^2 - C^2 \leq 0$. This can be checked by completing the square on $x$ and $y$, and checking that the minimum value of the LHS is $4AD - B^2 - C^2$.&#xD;&#xA;&#xD;&#xA;My question is: What algorithm would you use to draw it?&#xD;&#xA;&#xD;&#xA;Seems there are different approaches:&#xD;&#xA;&#xD;&#xA;1. Break it into the circle case and line case. Draw each using a dedicated routine. This way, you can use pre-existing drawing routines. There is a problem here, which is that you need to use thresholds to choose between the two cases. You'll need to draw a line even when a circle is only approximately a line. When is a circle close enough to being a line? I know that this is the obvious approach, but I don't like it.&#xD;&#xA;2. Traverse each value of $x$, and compute the (at most) $2$ different values of $y$, and draw those points. Then do the same again, but traversing each value of $y$ and finding $x$.&#xD;&#xA;3. A generalised circle determines a constant-speed motion along it. Use this somehow.&#xD;&#xA;&#xD;&#xA;Approach 2 explicitly uses the viewport. Approach 3 is vague, but depends on knowing it as well.&#xD;&#xA;&#xD;&#xA;What approaches are there?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38630" PostHistoryTypeId="1" PostId="13025" RevisionGUID="a887e994-c31e-4e20-816b-fe857c3b8d5d" CreationDate="2022-10-09T09:55:36.480" UserId="19030" Text="Algorithm for drawing generalised circles" ContentLicense="CC BY-SA 4.0" />
  <row Id="38631" PostHistoryTypeId="3" PostId="13025" RevisionGUID="a887e994-c31e-4e20-816b-fe857c3b8d5d" CreationDate="2022-10-09T09:55:36.480" UserId="19030" Text="|computational-geometry|drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38632" PostHistoryTypeId="5" PostId="13025" RevisionGUID="da30bdee-d699-489f-8bd9-9d00cf6b1dd0" CreationDate="2022-10-09T10:05:40.950" UserId="19030" Comment="added 75 characters in body" Text="A generalised circle is either a circle in the plane or a line. The general equation of one is:&#xD;&#xA;&#xD;&#xA;$$A(x^2 + y^2) + Bx + Cy + D=0,$$&#xD;&#xA;&#xD;&#xA;where $4AD - B^2 - C^2 \leq 0$. This can be checked by completing the square on $x$ and $y$, and checking that the minimum value of the LHS is $4AD - B^2 - C^2$.&#xD;&#xA;&#xD;&#xA;My question is: What algorithm would you use to draw it?&#xD;&#xA;&#xD;&#xA;Seems there are different approaches:&#xD;&#xA;&#xD;&#xA;1. Break it into the circle case and line case. Draw each using a dedicated routine. This way, you can use pre-existing drawing routines. There is a problem here, which is that out of many possible floating point values, only one of them is exactly $0$. So the line case happens in one case out of $2^{64}$ (if you use $64$-bit floats). And on top of that, thanks to rounding errors, what *should* be a line can become a circle. I can't fully articulate what I suspect is wrong with this approach.&#xD;&#xA;2. Traverse each value of $x$, and compute the (at most) $2$ different values of $y$, and draw those points. Then do the same again, but traversing each value of $y$ and finding $x$.&#xD;&#xA;3. A generalised circle determines a constant-speed motion along it. Use this somehow.&#xD;&#xA;&#xD;&#xA;Approach 2 explicitly uses the viewport. Approach 3 is vague, but depends on knowing it as well.&#xD;&#xA;&#xD;&#xA;What approaches are there?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38633" PostHistoryTypeId="5" PostId="13025" RevisionGUID="fe6f9fc6-d97f-4aad-8541-81a48b5a73ed" CreationDate="2022-10-09T10:13:42.083" UserId="19030" Comment="added 164 characters in body" Text="A generalised circle is either a circle in the plane or a line. The general equation of one is:&#xD;&#xA;&#xD;&#xA;$$A(x^2 + y^2) + Bx + Cy + D=0,$$&#xD;&#xA;&#xD;&#xA;where $4AD - B^2 - C^2 \leq 0$. This can be checked by completing the square on $x$ and $y$, and checking that the minimum value of the LHS is $4AD - B^2 - C^2$.&#xD;&#xA;&#xD;&#xA;My question is: What algorithm would you use to draw it?&#xD;&#xA;&#xD;&#xA;Seems there are different approaches:&#xD;&#xA;&#xD;&#xA;1. Break it into the circle case and line case. Draw each using a dedicated routine. This way, you can use pre-existing drawing routines. There is a problem here, which is that out of many possible floating point values, only one of them is exactly $0$. So the line case happens in one case out of $2^{64}$ (if you use $64$-bit floats). And on top of that, thanks to rounding errors, what *should* be a line can become a circle. The circle case requires finding the centre and radius, but these can both be large values, subject to floating-point rounding errors. You can use a threshold instead of checking whether $A = 0$, but which threshold should get used?&#xD;&#xA;2. Traverse each value of $x$, and compute the (at most) $2$ different values of $y$, and draw those points. Then do the same again, but traversing each value of $y$ and finding $x$.&#xD;&#xA;3. A generalised circle determines a constant-speed motion along it. Use this somehow.&#xD;&#xA;&#xD;&#xA;Approach 2 explicitly uses the viewport. Approach 3 is vague, but depends on knowing it as well.&#xD;&#xA;&#xD;&#xA;What approaches are there?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38634" PostHistoryTypeId="5" PostId="13025" RevisionGUID="aa20693f-e784-43c0-ad21-a2cc78d3edc8" CreationDate="2022-10-09T10:39:34.127" UserId="19030" Comment="added 160 characters in body" Text="A generalised circle is either a circle in the plane or a line. The general equation of one is:&#xD;&#xA;&#xD;&#xA;$$A(x^2 + y^2) + Bx + Cy + D=0,$$&#xD;&#xA;&#xD;&#xA;where $4AD - B^2 - C^2 \leq 0$. This can be checked by completing the square on $x$ and $y$, and checking that the minimum value of the LHS is $4AD - B^2 - C^2$.&#xD;&#xA;&#xD;&#xA;My question is: What algorithm would you use to draw it?&#xD;&#xA;&#xD;&#xA;Seems there are different approaches:&#xD;&#xA;&#xD;&#xA;1. Break it into the circle case and line case. Draw each using a dedicated routine. This way, you can use pre-existing drawing routines. There is a problem here, which is that out of many possible floating point values, only one of them is exactly $0$. So the line case happens in one case out of $2^{64}$ (if you use $64$-bit floats). And on top of that, thanks to rounding errors, what *should* be a line can become a circle. The circle case requires finding the centre and radius, but these can both be large values, subject to floating-point rounding errors. You can use a threshold instead of checking whether $A = 0$, but which threshold should get used?&#xD;&#xA;2. Traverse each value of $x$ in the viewport, and compute the (at most) $2$ different values of $y$, and draw those points. Then do the same again, but traversing each value of $y$ and finding $x$.&#xD;&#xA;3. A generalised circle determines a constant-speed motion along it. Use this somehow.&#xD;&#xA;4. A generalised circle determines an [inversion](https://en.wikipedia.org/wiki/Inversive_geometry) through it. Use this fact somehow.&#xD;&#xA;&#xD;&#xA;Approach 2 explicitly uses the viewport. Approaches 3 and 4 are vague, but depend on knowing it as well.&#xD;&#xA;&#xD;&#xA;What approaches are there?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38635" PostHistoryTypeId="2" PostId="13026" RevisionGUID="53697424-78dc-4265-85c4-ae7f2e7cd85c" CreationDate="2022-10-10T08:28:43.540" UserId="13273" Text="I am trying to implement CSM technique with &quot;Fit to Cascade&quot; projections. My problem is to find good distances to partitioning the cameras view frustum. The FoV of my camera is changing, so the partitioning for the CSM algorithm need to be changed as well with respect to the FoV angle.&#xD;&#xA;&#xD;&#xA;My shadowMap texture is a Texture2dArray which will be filled by layered rendering technique. So unlike some CSM tutorials, the shadowMap of each cascade has the same resolution.&#xD;&#xA;&#xD;&#xA;What formular can I use to have a mostly 1 to 1 mapping of camera viewSpace pixel to shadowMap pixel?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38637" PostHistoryTypeId="1" PostId="13026" RevisionGUID="53697424-78dc-4265-85c4-ae7f2e7cd85c" CreationDate="2022-10-10T08:28:43.540" UserId="13273" Text="Cascaded Shadow Mapping (CSM), Partitioning the Frustum to a nearly 1 by 1 mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="38638" PostHistoryTypeId="3" PostId="13026" RevisionGUID="53697424-78dc-4265-85c4-ae7f2e7cd85c" CreationDate="2022-10-10T08:28:43.540" UserId="13273" Text="|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38639" PostHistoryTypeId="5" PostId="13026" RevisionGUID="420b6d93-9fed-46d4-b978-f0d267201244" CreationDate="2022-10-10T08:53:39.783" UserId="13273" Comment="added 223 characters in body" Text="I am trying to implement CSM technique with &quot;Fit to Cascade&quot; projections. My problem is to find good distances to partitioning the cameras view frustum. The FoV of my camera is changing, so the partitioning for the CSM algorithm need to be changed as well with respect to the FoV angle.&#xD;&#xA;&#xD;&#xA;My shadowMap texture is a Texture2dArray which will be filled by layered rendering technique. So unlike some CSM tutorials, the shadowMap of each cascade has the same resolution.&#xD;&#xA;&#xD;&#xA;What formular can I use to have a mostly 1 to 1 mapping of camera viewSpace pixel to shadowMap pixel?&#xD;&#xA;&#xD;&#xA;**An example to show what is meant:**&#xD;&#xA;&#xD;&#xA;For a 90° FoV, the far cascades should always be larger.&#xD;&#xA;&#xD;&#xA;For a 10° FoV, the far cascades should be much smaller than the cascades for the 90° Fov to have a better 1 to 1 match" ContentLicense="CC BY-SA 4.0" />
  <row Id="38640" PostHistoryTypeId="2" PostId="13027" RevisionGUID="16229f50-1df5-469f-82fc-f4e8e401b3cc" CreationDate="2022-10-10T13:27:40.410" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38642" PostHistoryTypeId="1" PostId="13027" RevisionGUID="16229f50-1df5-469f-82fc-f4e8e401b3cc" CreationDate="2022-10-10T13:27:40.410" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38643" PostHistoryTypeId="2" PostId="13028" RevisionGUID="fcb088e7-eaa7-49eb-b23e-d7dbd6ab067c" CreationDate="2022-10-10T13:27:40.410" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38645" PostHistoryTypeId="1" PostId="13028" RevisionGUID="fcb088e7-eaa7-49eb-b23e-d7dbd6ab067c" CreationDate="2022-10-10T13:27:40.410" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38646" PostHistoryTypeId="2" PostId="13029" RevisionGUID="3a05021c-8467-41c2-bdb3-f0bd41c790e0" CreationDate="2022-10-10T13:29:05.233" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38648" PostHistoryTypeId="1" PostId="13029" RevisionGUID="3a05021c-8467-41c2-bdb3-f0bd41c790e0" CreationDate="2022-10-10T13:29:05.233" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38649" PostHistoryTypeId="2" PostId="13030" RevisionGUID="118245eb-ff52-412d-ac08-58a7392a65ed" CreationDate="2022-10-10T13:29:05.233" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38651" PostHistoryTypeId="1" PostId="13030" RevisionGUID="118245eb-ff52-412d-ac08-58a7392a65ed" CreationDate="2022-10-10T13:29:05.233" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38652" PostHistoryTypeId="2" PostId="13031" RevisionGUID="8329d74c-8889-4448-8f28-cbc4c50ebf7a" CreationDate="2022-10-10T13:36:36.013" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38654" PostHistoryTypeId="1" PostId="13031" RevisionGUID="8329d74c-8889-4448-8f28-cbc4c50ebf7a" CreationDate="2022-10-10T13:36:36.013" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38655" PostHistoryTypeId="2" PostId="13032" RevisionGUID="af984ba1-f212-4010-b398-8df6fa622a87" CreationDate="2022-10-10T13:36:36.013" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="38657" PostHistoryTypeId="1" PostId="13032" RevisionGUID="af984ba1-f212-4010-b398-8df6fa622a87" CreationDate="2022-10-10T13:36:36.013" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="38658" PostHistoryTypeId="50" PostId="8431" RevisionGUID="42dba156-278c-4d1c-8151-e60c9c049386" CreationDate="2022-10-10T14:07:46.027" UserId="-1" />
  <row Id="38659" PostHistoryTypeId="2" PostId="13033" RevisionGUID="048c3d42-456c-4e4d-9eb8-977cafaad925" CreationDate="2022-10-11T00:53:40.067" UserId="19035" Text="(5 years, 3 months later)  &#xD;&#xA;&#xD;&#xA;You might like https://github.com/openscad/openscad/pull/4348 which adds a `fill()` builtin to do just this ... it just got merged :-)&#xD;&#xA;&#xD;&#xA;[![OpenSCAD, filled][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/kvFfZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38661" PostHistoryTypeId="50" PostId="12158" RevisionGUID="3503300e-37dc-4c00-ae56-413f7349cbdd" CreationDate="2022-10-11T12:00:40.097" UserId="-1" />
  <row Id="38662" PostHistoryTypeId="2" PostId="13034" RevisionGUID="17a90ab3-c74b-407c-8530-afcb94c84774" CreationDate="2022-10-11T14:58:11.823" UserId="7952" Text="The logarithmic shadow mapping split scheme produces split points that minimize aliasing. There is a short derivation that can be used to show that it produces the split points that reduce aliasing to values near 1. Here is the calculation:&#xD;&#xA;&#xD;&#xA;$C^{log}_i = z_n(\frac{z_f}{z_n})^\frac{i}{m}$ &#xD;&#xA;&#xD;&#xA;where $i$ is the ith cascade and m is the total number of cascades.&#xD;&#xA;&#xD;&#xA;Chose $z_n$ carefully. Often it is better to use a &quot;virtual&quot; near plane chosen to maximize coverage and reduce wasted shadow map space. (A poorly chosen near plane can cause an entire cascade to produce no meaningful data) Also, keep in mind that shadows closer to the camera then the chosen near plane will still produce shadows but may have higher aliasing. There are algorithms for choosing a virtual near plane I recommend looking them up.&#xD;&#xA;&#xD;&#xA;While $C^{log}_i$ will produce split points that minimize aliasing, it will generally not give the best coverage for distant shadows(where the majority of the geometry is rendered). And a better scheme (published in several places) is to use something called the &quot;practical&quot; or &quot;weighted&quot; algorithm. It combines a uniform distribution with the logarithmic distribution. Here is its calculation: (just a simple lerp)&#xD;&#xA;&#xD;&#xA;$C^{pract}_i = \alpha C^{log}_i + (1-\alpha)C^{uni}_i$&#xD;&#xA;&#xD;&#xA;where $C^{uni}_i$ is:&#xD;&#xA;&#xD;&#xA;$C^{uni}_i= n + (f-n)\frac{i}{m}$&#xD;&#xA;&#xD;&#xA;This makes it easy to adjust between full logarithmic and uniform split.&#xD;&#xA;&#xD;&#xA;Most of this info is readily available but the bit about choosing Z near is glossed over in most publications.&#xD;&#xA;&#xD;&#xA;Here are my sources:&#xD;&#xA;My used copy of &quot;Real-Time Shadows&quot; and [GPU Gems 3 chapter 10][1] (because there was an error in the book!)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-10-parallel-split-shadow-maps-programmable-gpus" ContentLicense="CC BY-SA 4.0" />
  <row Id="38664" PostHistoryTypeId="5" PostId="13028" RevisionGUID="478709ac-c4a9-4670-96f6-47baac958641" CreationDate="2022-10-11T16:25:19.503" UserId="171" Comment="added 141 characters in body" Text="Questions about the visual perceptual property deriving from the spectrum of light, usually expressed numerically according to a color model." ContentLicense="CC BY-SA 4.0" />
  <row Id="38665" PostHistoryTypeId="24" PostId="13028" RevisionGUID="478709ac-c4a9-4670-96f6-47baac958641" CreationDate="2022-10-11T16:25:19.503" Comment="Proposed by 171 approved by 7952, 482 edit id of 594" ContentLicense="CC BY-SA 4.0" />
  <row Id="38666" PostHistoryTypeId="5" PostId="1517" RevisionGUID="1154f8f1-1588-4f41-9278-fa1376fa3b76" CreationDate="2022-10-11T16:27:13.907" UserId="-1" Comment="Fixed typo" Text="As you already note, there is no clear cut interpretation/conversion for these values. I think it is even much worse: Depending on your BRDF and internal limitations (like having defined exponents ranging from 2-2048) the interpretation is _completely_ different. Like suggested in the comments, it might be the best to render a series with different values and fit a conversion curve until the value looks intuitive.&#xD;&#xA;&#xD;&#xA;A few examples I was able to find some blog posts that mention something about that topic:&#xD;&#xA;&#xD;&#xA; - At Dontnod entertainment they use a &quot;perceptual linear distribution&quot;. &#xD;&#xA;Sébastien Lagarde acknowledges the problem in [this blog post][1] and writes a few notes on that.&#xD;&#xA; - Brian Karis uses a squared roughness values in this [Microfacet BRDF overview][2]. This illustrates also nicely how differently  roughness is used in different Normal Distribution Functions. Blinn-Phong power is here defined as `2/roughness^4 - 2`.&#xD;&#xA; - Frostbite uses a squared remapping. ie. Roughness =  (1 − Smoothness)^2&#xD;&#xA;Details about it and their entire material system is explained in section 3.2 of Sebastien Lagarde's [writeup][3].&#xD;&#xA; - [This blog post][4] suggests to define the roughness for a Beckmann distribution from the shininess alpha as:&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://seblagarde.wordpress.com/2011/08/17/feeding-a-physical-based-lighting-mode/&#xD;&#xA;  [2]: http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html&#xD;&#xA;  [3]: http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf&#xD;&#xA;  [4]: http://simonstechblog.blogspot.de/2011/12/microfacet-brdf.html&#xD;&#xA;  [5]: https://i.stack.imgur.com/1NWdA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38667" PostHistoryTypeId="24" PostId="1517" RevisionGUID="1154f8f1-1588-4f41-9278-fa1376fa3b76" CreationDate="2022-10-11T16:27:13.907" Comment="Proposed by anonymous approved by 7952, 482 edit id of 593" ContentLicense="CC BY-SA 4.0" />
  <row Id="38668" PostHistoryTypeId="5" PostId="13032" RevisionGUID="b023b396-a520-4741-a35b-6f9861986e21" CreationDate="2022-10-11T16:27:31.737" UserId="171" Comment="added 99 characters in body" Text="Algorithms generating large sets of random numbers to simulate real-world, usually optical systems." ContentLicense="CC BY-SA 4.0" />
  <row Id="38669" PostHistoryTypeId="24" PostId="13032" RevisionGUID="b023b396-a520-4741-a35b-6f9861986e21" CreationDate="2022-10-11T16:27:31.737" Comment="Proposed by 171 approved by 482 edit id of 596" ContentLicense="CC BY-SA 4.0" />
  <row Id="38670" PostHistoryTypeId="5" PostId="13030" RevisionGUID="24e420d5-a77b-4f31-89e2-edf6bcd80989" CreationDate="2022-10-11T16:27:46.090" UserId="171" Comment="added 60 characters in body" Text="Questions about the conversions of a 3D model to a 2D model." ContentLicense="CC BY-SA 4.0" />
  <row Id="38671" PostHistoryTypeId="24" PostId="13030" RevisionGUID="24e420d5-a77b-4f31-89e2-edf6bcd80989" CreationDate="2022-10-11T16:27:46.090" Comment="Proposed by 171 approved by 7952, 482 edit id of 595" ContentLicense="CC BY-SA 4.0" />
  <row Id="38672" PostHistoryTypeId="2" PostId="13035" RevisionGUID="7121d030-742d-499d-a28d-bee621c09668" CreationDate="2022-10-12T01:51:35.907" UserId="18964" Text="I'm using OpenGL 4.30 with JOGL (in Java). I'm playing with basic texturing, trying to learn how it's done.&#xD;&#xA;&#xD;&#xA;The textbook I'm using has the following code:&#xD;&#xA;&#xD;&#xA;    gl.glActiveTexture(GL_TEXTURE0); // is this line necessary?&#xD;&#xA;    gl.glBindTexture(GL_TEXTURE_2D, textureID);&#xD;&#xA;    gl.glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;&#xD;&#xA;This works well enough. But I find that if I comment out the first line, that it appears to have absolutely no effect on my program. So what is its point? Can the GPU only hold a limited number of textures at once, and I'm using #0 to hold the texture referred to by `textureID`? If I keep reusing the same constant `GL_TEXTURE0` for all of my textures, does that mean that I'm slowing everything down? Or is this just to support legacy code, and I don't need to call this function at all? I'm very confused as to why this line is needed, and what it's doing." ContentLicense="CC BY-SA 4.0" />
  <row Id="38674" PostHistoryTypeId="1" PostId="13035" RevisionGUID="7121d030-742d-499d-a28d-bee621c09668" CreationDate="2022-10-12T01:51:35.907" UserId="18964" Text="Is glActiveTexture() still needed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38675" PostHistoryTypeId="3" PostId="13035" RevisionGUID="7121d030-742d-499d-a28d-bee621c09668" CreationDate="2022-10-12T01:51:35.907" UserId="18964" Text="|opengl|texture|java|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38676" PostHistoryTypeId="2" PostId="13036" RevisionGUID="f743e205-7641-4441-a8f4-ab6fcbe80fd1" CreationDate="2022-10-12T05:40:55.977" UserId="445" Text="&gt; But I find that if I comment out the first line, that it appears to have absolutely no effect on my program.&#xD;&#xA;&#xD;&#xA;That's because `TEXTURE0` happens to be the initial value. It might have an effect if you had previously set a different value.&#xD;&#xA;&#xD;&#xA;But more generally, the point of multiple texture units is to be able to use multiple textures simultaneously when drawing (the specific way they are used being determined by your shaders). In that case, you would need to bind each texture with a different active texture unit to be able to use them simultaneously.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38678" PostHistoryTypeId="50" PostId="10248" RevisionGUID="8d6c7fe6-c2cc-4337-b7fb-b94e22715eb2" CreationDate="2022-10-12T23:03:15.360" UserId="-1" />
  <row Id="38679" PostHistoryTypeId="2" PostId="13037" RevisionGUID="30d3692d-8f85-4922-bb76-0697811ce6a6" CreationDate="2022-10-13T08:25:27.687" UserId="13273" Text="I've a texture (2048 x 2048) Pixels.&#xD;&#xA;I am looking for an algorithm to transform the normalized texture coordinate [0 1] to pixel coordinate [0 2047]. This should be a perfect fit... &#xD;&#xA;&#xD;&#xA;So when the texture sampler has a GL_NEAREST interpolation the following code should output the same:&#xD;&#xA;&#xD;&#xA;    vec2 normalizedCoordinate = someValue;&#xD;&#xA;    ivec2 pixelCoordinate = AlgorithmIamLookingFor;&#xD;&#xA;    vec4 color = texture(tex, normalizedCoordinate);&#xD;&#xA;    vec4 color2 = texelFetch(tex, pixelCoordinate, 0);&#xD;&#xA;&#xD;&#xA;So `color` and `color2` should have the same value.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38681" PostHistoryTypeId="1" PostId="13037" RevisionGUID="30d3692d-8f85-4922-bb76-0697811ce6a6" CreationDate="2022-10-13T08:25:27.687" UserId="13273" Text="GLSL normalized texture coordinate to pixel coordinate" ContentLicense="CC BY-SA 4.0" />
  <row Id="38682" PostHistoryTypeId="3" PostId="13037" RevisionGUID="30d3692d-8f85-4922-bb76-0697811ce6a6" CreationDate="2022-10-13T08:25:27.687" UserId="13273" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38683" PostHistoryTypeId="5" PostId="13037" RevisionGUID="b2dba2c6-b1d7-4c81-ad52-bc5e445e5350" CreationDate="2022-10-13T08:31:56.320" UserId="13273" Comment="added 156 characters in body" Text="I've a texture (2048 x 2048) Pixels.&#xD;&#xA;I am looking for an algorithm to transform the normalized texture coordinate [0 1] to pixel coordinate [0 2047]. This should be a perfect fit... &#xD;&#xA;&#xD;&#xA;So when the texture sampler has a GL_NEAREST interpolation the following code should output the same:&#xD;&#xA;&#xD;&#xA;    vec2 normalizedCoordinate = someValue;&#xD;&#xA;    ivec2 pixelCoordinate = AlgorithmIamLookingFor;&#xD;&#xA;    vec4 color = texture(tex, normalizedCoordinate);&#xD;&#xA;    vec4 color2 = texelFetch(tex, pixelCoordinate, 0);&#xD;&#xA;&#xD;&#xA;So `color` and `color2` should have the same value.&#xD;&#xA;&#xD;&#xA;I've tried the following:&#xD;&#xA;&#xD;&#xA;    pixelCoordinate.x = int(normalizedCoordinate * 2047)&#xD;&#xA;&#xD;&#xA;But the last pixel (2047) will not show up or be extremely small." ContentLicense="CC BY-SA 4.0" />
  <row Id="38684" PostHistoryTypeId="5" PostId="13037" RevisionGUID="e19e761d-e5a0-4f8a-a3bb-38bb040bfe4f" CreationDate="2022-10-13T09:29:15.550" UserId="13273" Comment="added 39 characters in body" Text="I've a texture (2048 x 2048) Pixels.&#xD;&#xA;I am looking for an algorithm to transform the normalized texture coordinate [0 1] to pixel coordinate [0 2047]. This should be a perfect fit... &#xD;&#xA;&#xD;&#xA;So when the texture sampler has a GL_NEAREST interpolation the following code should output the same:&#xD;&#xA;&#xD;&#xA;    ivec2 texSize = textureSize(tex);&#xD;&#xA;    vec2 normalizedCoordinate = someValue;&#xD;&#xA;    ivec2 pixelCoordinate = AlgorithmIamLookingFor;&#xD;&#xA;    vec4 color = texture(tex, normalizedCoordinate);&#xD;&#xA;    vec4 color2 = texelFetch(tex, pixelCoordinate, 0);&#xD;&#xA;&#xD;&#xA;So `color` and `color2` should have the same value.&#xD;&#xA;&#xD;&#xA;I've tried the following:&#xD;&#xA;&#xD;&#xA;    pixelCoordinate.x = int(normalizedCoordinate * 2047)&#xD;&#xA;&#xD;&#xA;But the last pixel (2047) will not show up or be extremely small." ContentLicense="CC BY-SA 4.0" />
  <row Id="38685" PostHistoryTypeId="5" PostId="10252" RevisionGUID="2c9bb000-349c-4583-b193-67761e3cd811" CreationDate="2022-10-13T11:53:02.927" UserId="7952" Comment="fixed spelling error" Text="Answer over in Photography:&#xD;&#xA;https://photo.stackexchange.com/questions/119761/sensor-size-of-sony-hdr-hc7e/119764#119764&#xD;&#xA;It turns out to be Vertical: 3.74 horizontal 4.98 and diagonal 6.23" ContentLicense="CC BY-SA 4.0" />
  <row Id="38686" PostHistoryTypeId="50" PostId="10341" RevisionGUID="6cb0ea81-e9f5-426e-bdee-7998ea3538bc" CreationDate="2022-10-13T12:05:10.700" UserId="-1" />
  <row Id="38689" PostHistoryTypeId="50" PostId="9199" RevisionGUID="b8ee3fd4-0bf4-42dc-9e71-8db14eaf7c61" CreationDate="2022-10-15T04:04:10.460" UserId="-1" />
  <row Id="38690" PostHistoryTypeId="50" PostId="10025" RevisionGUID="fcbf678e-1b88-46d9-8519-5d09c4068f24" CreationDate="2022-10-16T03:07:25.923" UserId="-1" />
  <row Id="38691" PostHistoryTypeId="50" PostId="9267" RevisionGUID="f62e8448-af01-4e98-a535-40b89ca27ec9" CreationDate="2022-10-16T11:02:05.273" UserId="-1" />
  <row Id="38692" PostHistoryTypeId="50" PostId="8935" RevisionGUID="07efbf06-7eb7-4037-b0a5-b710fb2df7dd" CreationDate="2022-10-17T01:05:25.653" UserId="-1" />
  <row Id="38694" PostHistoryTypeId="2" PostId="13038" RevisionGUID="264af374-0ebf-4a1a-81a7-f0ac7df1a6e5" CreationDate="2022-10-17T09:20:25.860" UserId="13273" Text="I am looking for an opengl function to get the binding location of a SSBO in a shader.&#xD;&#xA;&#xD;&#xA;I found `glUniformBlockBinding` which works for uniform buffers. But there must be some function to get the SSBO binding location.&#xD;&#xA;&#xD;&#xA;on The [Khronos page][1] they have hard coded the buffer binding (3).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 4.0" />
  <row Id="38696" PostHistoryTypeId="1" PostId="13038" RevisionGUID="264af374-0ebf-4a1a-81a7-f0ac7df1a6e5" CreationDate="2022-10-17T09:20:25.860" UserId="13273" Text="get binding location of Shader Storage Buffer Object [OpenGL]" ContentLicense="CC BY-SA 4.0" />
  <row Id="38697" PostHistoryTypeId="3" PostId="13038" RevisionGUID="264af374-0ebf-4a1a-81a7-f0ac7df1a6e5" CreationDate="2022-10-17T09:20:25.860" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38701" PostHistoryTypeId="5" PostId="13038" RevisionGUID="5068f5df-2bc1-4344-810b-c7714caf22ed" CreationDate="2022-10-17T13:54:36.500" UserId="13273" Comment="added 1 character in body" Text="I am looking for an opengl function to get the binding location of a SSBO in a shader.&#xD;&#xA;&#xD;&#xA;I found `glGetUniformBlockIndex` which works for uniform buffers. But there must be some function to get the SSBO binding location.&#xD;&#xA;&#xD;&#xA;on The [Khronos page][1] they have hard coded the buffer binding (3).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object" ContentLicense="CC BY-SA 4.0" />
  <row Id="38703" PostHistoryTypeId="2" PostId="13040" RevisionGUID="b1a246f4-9426-48c9-98af-e3bc92055f7d" CreationDate="2022-10-19T21:59:33.730" UserId="7462" Text="I think somewhere in the literature there is an algorithm that, given 2 points on a triangle mesh, finds the triangle strip through which the geodesic passes, but I cannot find it anywhere.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38705" PostHistoryTypeId="1" PostId="13040" RevisionGUID="b1a246f4-9426-48c9-98af-e3bc92055f7d" CreationDate="2022-10-19T21:59:33.730" UserId="7462" Text="Geodesic triangle strip algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="38706" PostHistoryTypeId="3" PostId="13040" RevisionGUID="b1a246f4-9426-48c9-98af-e3bc92055f7d" CreationDate="2022-10-19T21:59:33.730" UserId="7462" Text="|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38712" PostHistoryTypeId="2" PostId="13042" RevisionGUID="86a64ce2-a3e1-4dcb-9405-bb9b37925c51" CreationDate="2022-10-20T14:21:10.773" UserId="19058" Text="Today we have tools such as Nvidia's CUDA and OpenCL to perform general purpose computing on the GPU (GPGPU). Seeing that traditional shaders are specifically used for generating graphics by filling a frame buffer with pixel values, are there any examples of graphics shaders being used for non-graphics computing prior to the modern GPGPU capability?&#xD;&#xA;&#xD;&#xA;Shaders can take input parameter values sent from the CPU, and the GPU can be told to render to a texture buffer instead of the screen. With this in mind, I feel like someone could send in values for computation, compute them using the vertex and/or pixel shaders, and encode the results in the output pixel values which can be read by the CPU from the target buffer." ContentLicense="CC BY-SA 4.0" />
  <row Id="38714" PostHistoryTypeId="1" PostId="13042" RevisionGUID="86a64ce2-a3e1-4dcb-9405-bb9b37925c51" CreationDate="2022-10-20T14:21:10.773" UserId="19058" Text="Has general purpose GPU computing been used before compute shaders were available?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38715" PostHistoryTypeId="3" PostId="13042" RevisionGUID="86a64ce2-a3e1-4dcb-9405-bb9b37925c51" CreationDate="2022-10-20T14:21:10.773" UserId="19058" Text="|shader|gpgpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38716" PostHistoryTypeId="2" PostId="13043" RevisionGUID="6b76f28b-f561-4333-986e-57344fe3211b" CreationDate="2022-10-20T15:21:21.497" UserId="19061" Text="Im not a professional computer graphics programmer, I'm just learning. All the tutorials I've seen so far about ray tracing have one thing in common, that in order to get good visual results they need to cast thousands of rays in random directions from each pixel of the final input and bounce them around. &#xD;&#xA;&#xD;&#xA;My question is: Why not cast only 4 and say &quot;These 4 lines form a parallelepiped(a rectangle extruded into the 3rd dimension) and every line inside this parallelepiped is considered a ray that contributes to the final color of this pixel. &#xD;&#xA;&#xD;&#xA;At the first iteration, a  parallelepiped will hit a triangle called &quot;T1&quot; (assuming all your meshes are made out of triangles) and change the geometry(on geometry shaders) of triangle T1. The triangle T1 will be split into 2 polygons: 1 that was hit by light, and one that hasnt been. These polygons can then be diveded into an array of triangles Lets call this array &quot;T2&quot;. This way, only 1 little triangle inside the T2 array will contain all the light and there woudnt be any point inside the little triangle that is not hit by light. Lets call this little triangle T3. All you have to do now, is reflect the triangle T3 to start the second iteration. The difference is that now, at the second iteration, you will have to reflect all the little triangles T3 from every triangle T1 that has been hit by light at iteration 1.&#xD;&#xA;&#xD;&#xA;With this technique, you would arrive at the nth iteration with a list of triangles that have all the light in the scene. All you need now is to convert those triangles to actual pixels on the screen and add them to the final color. It just seems faster to me to work with the geometric equation of a line 4 times, than to work with thousands of rays.&#xD;&#xA;&#xD;&#xA;What do you think?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38718" PostHistoryTypeId="1" PostId="13043" RevisionGUID="6b76f28b-f561-4333-986e-57344fe3211b" CreationDate="2022-10-20T15:21:21.497" UserId="19061" Text="Is this algorithm a variation of ray tracing worth something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38719" PostHistoryTypeId="3" PostId="13043" RevisionGUID="6b76f28b-f561-4333-986e-57344fe3211b" CreationDate="2022-10-20T15:21:21.497" UserId="19061" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38720" PostHistoryTypeId="50" PostId="8888" RevisionGUID="7db1ef7c-2cd4-4467-9764-a8eabb517bc5" CreationDate="2022-10-20T19:01:00.120" UserId="-1" />
  <row Id="38730" PostHistoryTypeId="2" PostId="13046" RevisionGUID="25e2a303-144e-4b46-b3dc-7f73cc4c3b62" CreationDate="2022-10-21T04:25:31.410" UserId="19052" Text="I’m stuyding computer animation with this book, Computer animation by The Morgan Kaufmann series. The explanation for translation from object space to world space is difficult to understand. In more detail, what I thought is not same to the textbook. &#xD;&#xA;&#xD;&#xA;I have read this article, but I’m not sure is it helpful to solve this problem. https://computergraphics.stackexchange.com/questions/8562/how-to-convert-from-object-space-into-world-space-exercise-from-3d-math-primer&#xD;&#xA;&#xD;&#xA;[![object space to world space][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is the way that I understood vs the textbook explains.&#xD;&#xA;[![Explanation ][2]][2]&#xD;&#xA;&#xD;&#xA;The difference between two of them is what is the orientation vector in z? The book explained that the endpoint of the orientation vector is at 0,0,sqrt(50). But why suddenly sqrt(34) came up?.. I don’t know why the the endpoint should be in 0,0,sqrt(50). Is it would be in 5? It is so confused to me.&#xD;&#xA;&#xD;&#xA;[Textbook explains]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/z2TFw.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/0sgiP.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/iLAKL.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38732" PostHistoryTypeId="1" PostId="13046" RevisionGUID="25e2a303-144e-4b46-b3dc-7f73cc4c3b62" CreationDate="2022-10-21T04:25:31.410" UserId="19052" Text="Translation from object space to the world space" ContentLicense="CC BY-SA 4.0" />
  <row Id="38733" PostHistoryTypeId="3" PostId="13046" RevisionGUID="25e2a303-144e-4b46-b3dc-7f73cc4c3b62" CreationDate="2022-10-21T04:25:31.410" UserId="19052" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38736" PostHistoryTypeId="2" PostId="13047" RevisionGUID="e29599d6-dbe2-496d-9f8f-997e15ebfdaf" CreationDate="2022-10-21T20:13:08.547" UserId="19070" Text="I may be getting some details wrong (e.g. colour space vs. colour model), so please bare with me:&#xD;&#xA;&#xD;&#xA;I want to represent &quot;images&quot; consisting of complex numbers i.e. for each &quot;pixel&quot; there is a complex number with a magnitude ranging from 0-1 and a phase ranging from 0 to 2*pi.&#xD;&#xA;&#xD;&#xA;I have a colour map which is supposedly good for displaying phase information (the one named &quot;phase&quot; here: https://matplotlib.org/cmocean/).&#xD;&#xA;&#xD;&#xA;I can easily colour each pixel by the phase colour map, but I want to modulate the brightness (or some similar parameter) by the complex number's magnitude at each point. For a magnitude of zero, the pixel should be black and for a magnitude of 1, the pixel should &quot;fully&quot; be of the colour determined by the phase colour map (or any other suitable colour map).&#xD;&#xA;&#xD;&#xA;The idea I've had is to convert the RGB triplet to a HSV triplet, and then set the V (brightness/value) value equal to the complex number's magnitude, and then I've converted it back for display. The H and S values remain unchanged.&#xD;&#xA;&#xD;&#xA;This seems to work alright, but I've read that HSV is actually not a perceptually uniform colour space, so I'm wondering if anyone knows of a perceptually uniform colour space to use or perhaps just a better way to visualise complex number &quot;images&quot; effectively (without resorting to using separate images for the magnitude and the phase)." ContentLicense="CC BY-SA 4.0" />
  <row Id="38738" PostHistoryTypeId="1" PostId="13047" RevisionGUID="e29599d6-dbe2-496d-9f8f-997e15ebfdaf" CreationDate="2022-10-21T20:13:08.547" UserId="19070" Text="What is the best way to display complex number &quot;images&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38739" PostHistoryTypeId="3" PostId="13047" RevisionGUID="e29599d6-dbe2-496d-9f8f-997e15ebfdaf" CreationDate="2022-10-21T20:13:08.547" UserId="19070" Text="|shader|image-processing|color-science|colorspace|human-vision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38740" PostHistoryTypeId="5" PostId="13047" RevisionGUID="7e8a4cf3-b145-4b86-b6fe-066d98175afa" CreationDate="2022-10-21T21:31:24.447" UserId="19070" Comment="edited body" Text="I may be getting some details wrong (e.g. colour space vs. colour model), so please bear with me:&#xD;&#xA;&#xD;&#xA;I want to represent &quot;images&quot; consisting of complex numbers i.e. for each &quot;pixel&quot; there is a complex number with a magnitude ranging from 0-1 and a phase ranging from 0 to 2*pi.&#xD;&#xA;&#xD;&#xA;I have a colour map which is supposedly good for displaying phase information (the one named &quot;phase&quot; here: https://matplotlib.org/cmocean/).&#xD;&#xA;&#xD;&#xA;I can easily colour each pixel by the phase colour map, but I want to modulate the brightness (or some similar parameter) by the complex number's magnitude at each point. For a magnitude of zero, the pixel should be black and for a magnitude of 1, the pixel should &quot;fully&quot; be of the colour determined by the phase colour map (or any other suitable colour map).&#xD;&#xA;&#xD;&#xA;The idea I've had is to convert the RGB triplet to a HSV triplet, and then set the V (brightness/value) value equal to the complex number's magnitude, and then I've converted it back for display. The H and S values remain unchanged.&#xD;&#xA;&#xD;&#xA;This seems to work alright, but I've read that HSV is actually not a perceptually uniform colour space, so I'm wondering if anyone knows of a perceptually uniform colour space to use or perhaps just a better way to visualise complex number &quot;images&quot; effectively (without resorting to using separate images for the magnitude and the phase)." ContentLicense="CC BY-SA 4.0" />
  <row Id="38741" PostHistoryTypeId="2" PostId="13048" RevisionGUID="eee3a663-cf32-4794-9284-27205eb5fed7" CreationDate="2022-10-22T00:21:24.237" UserId="19052" Text="Thanks for comment, and I got an answer.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;It looks like the first z vector is not illustrated.&#xD;&#xA;Vector1 represents the orientation z-vector, and 1 is rotated by y-axis for -4 to be vector2.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zBOsI.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38743" PostHistoryTypeId="5" PostId="13048" RevisionGUID="a11a50f4-5bc3-42a2-b85b-418ea3a89909" CreationDate="2022-10-22T00:30:05.890" UserId="19052" Comment="added 15 characters in body" Text="Thanks for comment, and I got an answer.&#xD;&#xA;&#xD;&#xA;It looks like the first z vector is not illustrated.&#xD;&#xA;Vector1 represents the orientation z-vector, and 1 is rotated by x-axis for the y-coordinate to be -4&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/32D2X.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="38744" PostHistoryTypeId="2" PostId="13049" RevisionGUID="94db8aba-2abe-4fef-8d35-ad18ab5680ca" CreationDate="2022-10-22T01:12:45.223" UserId="19071" Text="The call you seek is `glGetProgramResourceIndex`, and probably `glShaderStorageBlockBinding` as well.&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;uint32_t idex=glGetProgramResourceIndex(&#xD;&#xA;  program_loc,&#xD;&#xA;  GL_SHADER_STORAGE_BLOCK,&#xD;&#xA;  name_of_block&#xD;&#xA;&#xD;&#xA;);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;One thing to note, and this is annoying of blocks in general, is that it will only be found by it's &quot;first name&quot;, that would be:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;layout(std430) buffer first_name {&#xD;&#xA;  ...&#xD;&#xA;} some_alias;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The alias (as far as I've tested) will not be found. Pretty, pretty dang inconvenient for me specially; [it's complicated](https://github.com/Liebranca/sin/blob/main/bin/singl) so I won't get into why here ;&gt;&#xD;&#xA;&#xD;&#xA;Cheers." ContentLicense="CC BY-SA 4.0" />
  <row Id="38746" PostHistoryTypeId="5" PostId="13049" RevisionGUID="ee6cf0b6-da2e-42bf-bc6a-17999c139749" CreationDate="2022-10-22T13:21:31.387" UserId="19071" Comment="added 74 characters in body" Text="The call you seek is `glGetProgramResourceIndex`, and probably `glShaderStorageBlockBinding` as well.&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;uint32_t idex=glGetProgramResourceIndex(&#xD;&#xA;  program_loc,&#xD;&#xA;  GL_SHADER_STORAGE_BLOCK,&#xD;&#xA;  name_of_block&#xD;&#xA;&#xD;&#xA;);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;One thing to note, and this is annoying of blocks in general, is that you must search by block name rather than it's instance name, that would be:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;layout(std430) buffer block_name {&#xD;&#xA;  ...&#xD;&#xA;} instance_name;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Because OpenGL refrences the buffer by it's block name, it won't be found if you search by instance name. Pretty, pretty dang inconvenient for me specially; [it's complicated](https://github.com/Liebranca/sin/blob/main/bin/singl) so I won't get into why here ;&gt;&#xD;&#xA;&#xD;&#xA;Cheers." ContentLicense="CC BY-SA 4.0" />
  <row Id="38748" PostHistoryTypeId="50" PostId="12467" RevisionGUID="5b89eae9-4183-42dd-8d9e-78e74f3e09ce" CreationDate="2022-10-22T15:02:15.237" UserId="-1" />
  <row Id="38749" PostHistoryTypeId="2" PostId="13050" RevisionGUID="c6058d04-a53a-4bfb-83eb-42946d90e9d3" CreationDate="2022-10-22T16:23:55.213" UserId="6046" Text="I'm trying to render some objects but apparently X and Y coordinates need to be really small in-order to get something on screen. See this example of 2 lines&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The world space coordinates for these lines are&#xD;&#xA;```&#xD;&#xA;vertices.push_back(glm::vec3(-1.0, 1.0, -2.0)); //line 1 &#xD;&#xA;vertices.push_back(glm::vec3(1.0, 1.0, -2.0));&#xD;&#xA;vertices.push_back(glm::vec3(1.0, -1.0, -2.0)); // line 2&#xD;&#xA;vertices.push_back(glm::vec3(-1.0, -1.0, -2.0));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;My view and projection matrices are being set as&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;proj = glm::perspectiveFov(glm::radians(60), 1280, 720, 0.1, 1000);&#xD;&#xA;view = glm::lookAt(glm::vec3(0,0,300), glm::vec3(0,0,-1), glm::vec3(0,1,0));&#xD;&#xA;```&#xD;&#xA;As you can see, the lines are actually showing up when I place the camera **300 units** back and that's a lot to see lines that have X and Y coordinates in range -1 to +1, atleast that's what I think or perhaps I'm wrong and it's fine?&#xD;&#xA;&#xD;&#xA;I remember scaling the range of X and Y in legacy opengl using `glOrtho` etc. Don't quite get what's the problem here since the matrices seem pretty normal to me. I've also checked the values of the matrices and they are coming up fine using the original math so the glm function is working as intended. Anything I'm forgetting here? Would appreciate some ideas.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8pDSp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38751" PostHistoryTypeId="1" PostId="13050" RevisionGUID="c6058d04-a53a-4bfb-83eb-42946d90e9d3" CreationDate="2022-10-22T16:23:55.213" UserId="6046" Text="OpenGL - How to increase view space coordinate range in X and Y axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="38752" PostHistoryTypeId="3" PostId="13050" RevisionGUID="c6058d04-a53a-4bfb-83eb-42946d90e9d3" CreationDate="2022-10-22T16:23:55.213" UserId="6046" Text="|opengl|3d|transformations|perspective|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38753" PostHistoryTypeId="6" PostId="13050" RevisionGUID="759e1881-b77f-4353-9f55-32e5767132bc" CreationDate="2022-10-22T16:37:20.373" UserId="6046" Comment="edited tags" Text="|opengl|rendering|transformations|perspective|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38758" PostHistoryTypeId="5" PostId="13050" RevisionGUID="2feb1e00-11f9-4923-992d-2f5f55bf2a6d" CreationDate="2022-10-22T17:29:53.247" UserId="6046" Comment="added 318 characters in body" Text="I'm trying to render some objects but apparently X and Y coordinates need to be really small in-order to get something on screen. See this example of 2 lines&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The world space coordinates for these lines are&#xD;&#xA;```&#xD;&#xA;vertices.push_back(glm::vec3(-1.0, 1.0, -2.0)); //line 1 &#xD;&#xA;vertices.push_back(glm::vec3(1.0, 1.0, -2.0));&#xD;&#xA;vertices.push_back(glm::vec3(1.0, -1.0, -2.0)); // line 2&#xD;&#xA;vertices.push_back(glm::vec3(-1.0, -1.0, -2.0));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;My view and projection matrices are being set as&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;proj = glm::perspectiveFov(glm::radians(60), 1280, 720, 0.1, 1000);&#xD;&#xA;view = glm::lookAt(glm::vec3(0,0,300), glm::vec3(0,0,-1), glm::vec3(0,1,0));&#xD;&#xA;```&#xD;&#xA;As you can see, the lines are actually showing up when I place the camera **300 units** back and that's a lot to see lines that have X and Y coordinates in range -1 to +1, atleast that's what I think or perhaps I'm wrong and it's fine?&#xD;&#xA;&#xD;&#xA;I remember scaling the range of X and Y in legacy opengl using `glOrtho` etc. Don't quite get what's the problem here since the matrices seem pretty normal to me. I've also checked the values of the matrices and they are coming up fine using the original math so the glm function is working as intended. Anything I'm forgetting here? Would appreciate some ideas.&#xD;&#xA;&#xD;&#xA;EDIT:- Wait a sec guys.. my perspective matrix is off. The values are&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;It should be a `-1` in the last row afaik.&#xD;&#xA;&#xD;&#xA;EDIT:- I'm an effin idiot, was using `glm::radians` twice, once when passing it to my class then once inside. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8pDSp.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/iuTlv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38759" PostHistoryTypeId="2" PostId="13052" RevisionGUID="cc221dad-5fad-4c8c-9cc3-15d48fde37fd" CreationDate="2022-10-22T17:31:09.463" UserId="6046" Text="I was converting the angle to radians twice guys. Moral of the story is to take breaks when coding." ContentLicense="CC BY-SA 4.0" />
  <row Id="38761" PostHistoryTypeId="5" PostId="13050" RevisionGUID="64e792bd-5c1d-471b-b3b4-f54c93f270bf" CreationDate="2022-10-22T17:31:34.920" UserId="6046" Comment="deleted 160 characters in body" Text="I'm trying to render some objects but apparently X and Y coordinates need to be really small in-order to get something on screen. See this example of 2 lines&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The world space coordinates for these lines are&#xD;&#xA;```&#xD;&#xA;vertices.push_back(glm::vec3(-1.0, 1.0, -2.0)); //line 1 &#xD;&#xA;vertices.push_back(glm::vec3(1.0, 1.0, -2.0));&#xD;&#xA;vertices.push_back(glm::vec3(1.0, -1.0, -2.0)); // line 2&#xD;&#xA;vertices.push_back(glm::vec3(-1.0, -1.0, -2.0));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;My view and projection matrices are being set as&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;proj = glm::perspectiveFov(glm::radians(60), 1280, 720, 0.1, 1000);&#xD;&#xA;view = glm::lookAt(glm::vec3(0,0,300), glm::vec3(0,0,-1), glm::vec3(0,1,0));&#xD;&#xA;```&#xD;&#xA;As you can see, the lines are actually showing up when I place the camera **300 units** back and that's a lot to see lines that have X and Y coordinates in range -1 to +1, atleast that's what I think or perhaps I'm wrong and it's fine?&#xD;&#xA;&#xD;&#xA;I remember scaling the range of X and Y in legacy opengl using `glOrtho` etc. Don't quite get what's the problem here since the matrices seem pretty normal to me. I've also checked the values of the matrices and they are coming up fine using the original math so the glm function is working as intended. Anything I'm forgetting here? Would appreciate some ideas.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:- I'm an effin idiot, was using `glm::radians` twice, once when passing it to my class then once inside. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8pDSp.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/iuTlv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38766" PostHistoryTypeId="2" PostId="13054" RevisionGUID="0fc63302-b0e8-4025-a787-4e3608bd128c" CreationDate="2022-10-23T07:49:12.587" UserId="9749" Text="This still happens in constraint platforms like OpenGL ES or the like were there are no compute shaders available and you end up hacking pixel shaders to do general purpose calculations, see any WebGL GPU physics demo and you most probably see ping ponging between fragment shader FBOs to be able to do computations. Or simply go to shadertoy.com and look at any physics/simulation demo. At the end of the day a compute shader ends up being very similar with the difference of it being more general purpose and therefore more tweakable and sometimes more performant for certain tasks.&#xA;Would be very nice if some OG could point at a very primitive example or the first time that someone thought that programable GPU programs/shaders were suitable for doing math on non graphics related stuff and did it though." ContentLicense="CC BY-SA 4.0" />
  <row Id="38774" PostHistoryTypeId="2" PostId="13056" RevisionGUID="c8aeb1ca-468b-4ef2-97d7-3e4ab76683a5" CreationDate="2022-10-24T17:44:43.183" UserId="48" Text="One early example of this (no doubt there are many others) was a 2004 Gamasutra article [&quot;Building a Million-Particle System&quot;](https://www.gamedeveloper.com/programming/building-a-million-particle-system). It represented particle data, such as positions and velocities, encoded as color values in textures, and used fragment shaders to update them.&#xD;&#xA;&#xD;&#xA;&gt; In graphics hardware terms the input data stream can be represented by a texture, the output data stream by a render target. Output data is often re-used as input in a further processing step. In that case the data streams are textures as well as render targets. The processing kernel is represented by a pixel shader (also called fragment program). By drawing a full-screen rectangle, the graphics hardware is instructed to call the pixel shader once for each output data record, reading from the input stream in the pixel shader. &#xD;&#xA;&#xD;&#xA;This article even performed depth sorting of particles using multi-pass merge sort, and has some historically interesting discussion of the difficulties of turning the pixel data back into vertex data at the time (as there was no support for sampling textures in vertex shaders).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38779" PostHistoryTypeId="2" PostId="13058" RevisionGUID="a0fb7d4c-56ec-4e29-a484-ea27abbbe6f6" CreationDate="2022-10-25T05:11:22.107" UserId="11058" Text="When modeling something like a hair or foliage using textures with alpha value for offline or real-time rendering, it seems to be common practice among computer modelers to try to minimize the amount of alpha in the textures, referring to it being very GPU intensive. I wonder if this is true for both alpha testing and alpha blending techniques? With alpha blending it's pretty clear that the additional alpha would result in more fragments having to be alpha blended. Also if order-independent transparency techniques are used, I imagine more alpha would make it slower (?). With alpha testing however we just discard fragments based on an alpha threshold. But I wonder if this process is GPU intensive?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38781" PostHistoryTypeId="1" PostId="13058" RevisionGUID="a0fb7d4c-56ec-4e29-a484-ea27abbbe6f6" CreationDate="2022-10-25T05:11:22.107" UserId="11058" Text="Why is it so important to minimize alpha in textures for rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="38782" PostHistoryTypeId="3" PostId="13058" RevisionGUID="a0fb7d4c-56ec-4e29-a484-ea27abbbe6f6" CreationDate="2022-10-25T05:11:22.107" UserId="11058" Text="|texture|alpha|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38787" PostHistoryTypeId="2" PostId="13060" RevisionGUID="05920cd0-34e8-4149-acae-cdbc0d57c1b5" CreationDate="2022-10-26T02:35:26.877" UserId="19088" Text="I've been trying to make a simple rasterizer in JS, and it's working well except for this one bug. ([Example][1]) Here is part of the fragment shader, as I believe that's where something is going wrong (If it is the vertex shader I'll edit my question with that code as well)&#xD;&#xA;```&#xD;&#xA;let bounds = rasterTri.getBoundingBox(canvas.width, canvas.height)&#xD;&#xA;&#xD;&#xA;if (!bounds) {continue}&#xD;&#xA;&#xD;&#xA;let area = edgeFunction(rasterTri.a, rasterTri.b, rasterTri.c)&#xD;&#xA;&#xD;&#xA;let diffuse = worldTri.normal().dot(lightDir)&#xD;&#xA;        &#xD;&#xA;for (let y = bounds.y0; y &lt;= bounds.y1; ++y) { &#xD;&#xA;   for (let x = bounds.x0; x &lt;= bounds.x1; ++x) {&#xD;&#xA;      let pixel = new vec3(x+0.5, y+0.5, 0)&#xD;&#xA;&#xD;&#xA;      let w0 = edgeFunction(rasterTri.b, rasterTri.c, pixel)&#xD;&#xA;      let w1 = edgeFunction(rasterTri.c, rasterTri.a, pixel)&#xD;&#xA;      let w2 = edgeFunction(rasterTri.a, rasterTri.b, pixel)&#xD;&#xA;                &#xD;&#xA;      if (w0 &gt;= 0 &amp;&amp; w1 &gt;= 0 &amp;&amp; w2 &gt;= 0) {&#xD;&#xA;         w0 /= area&#xD;&#xA;         w1 /= area&#xD;&#xA;         w2 /= area&#xD;&#xA;         let z = 1 / (rasterTri.a.z * w0 + rasterTri.b.z * w1 + rasterTri.c.z * w2)&#xD;&#xA;&#xD;&#xA;         if (z &lt; depthBuffer[y * canvas.width + x] &amp;&amp; z &gt; near) {&#xD;&#xA;            depthBuffer[y * canvas.width + x] = z&#xD;&#xA;            let index = y * (canvas.width*4) + (x*4)&#xD;&#xA;&#xD;&#xA;            pixels[index+0] = 255*diffuse&#xD;&#xA;            pixels[index+1] = 0&#xD;&#xA;            pixels[index+2] = 0&#xD;&#xA;            pixels[index+3] = 255&#xD;&#xA;         }&#xD;&#xA;      }&#xD;&#xA;   }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I'm trying to follow [this][2] tutorial but clearly something got lost in translation, any help would be greatly appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8BPc8.jpg&#xD;&#xA;  [2]: https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation" ContentLicense="CC BY-SA 4.0" />
  <row Id="38789" PostHistoryTypeId="1" PostId="13060" RevisionGUID="05920cd0-34e8-4149-acae-cdbc0d57c1b5" CreationDate="2022-10-26T02:35:26.877" UserId="19088" Text="Unexpected behavior when polygon goes off the side of the camera" ContentLicense="CC BY-SA 4.0" />
  <row Id="38790" PostHistoryTypeId="3" PostId="13060" RevisionGUID="05920cd0-34e8-4149-acae-cdbc0d57c1b5" CreationDate="2022-10-26T02:35:26.877" UserId="19088" Text="|rasterizer|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38792" PostHistoryTypeId="5" PostId="1822" RevisionGUID="feb72cd1-e86c-4610-9400-d2bdba9700cd" CreationDate="2022-10-26T14:48:42.807" UserId="9199" Comment="Typo fixes" Text="### You're comparing apples to oranges&#xD;&#xA;&#xD;&#xA;The game is like the view port in your modelling app. You can use the viewport for render and you will get same 60fps speeds.&#xD;&#xA;&#xD;&#xA;There is no reason why you can not get realtime graphics that are very good out of modelling software like Maya or 3DS Max. Results that are on par with many games. They have viewport shaders just like games do. There is also a viewport rendering option that chunks frames to disk as fast as it allows (I've done full HD renders at 30 fps from Maya). All you have to do is stop using the provided software raytracers.&#xD;&#xA;&#xD;&#xA;There are some differences, though. The primary difference is that you as a user do not optimize stuff as much as game developers do (optimization is using all the tricks in the book). Second your animation primitives work on the CPU because you need the flexibility. In games one can afford to do optimizations. All in all you pay for not having a programming team next to you.&#xD;&#xA;&#xD;&#xA;Many of the things may in fact have been precomputed, so they aren't so much faster, just better organized. Baking your indirect illumination will beat non-baked results every day.&#xD;&#xA;&#xD;&#xA;### Why are the raytracers slower?&#xD;&#xA;&#xD;&#xA;They aren't\*, one just tends to do more work on a ray tracer because it's easy. Feature by feature, they aren't much slower in computation cycles. For example, there's no need for a ray tracer to cast secondary rays (life reflections in that case the ray tracer will cull geometry away, or not even load it, in fact mental ray does just that). It's just usually done because it trivial to do so and that's the clear advantage of ray tracers. You can even configure them to run on the CPU in some cases. They are just optimized for different things:&#xD;&#xA;&#xD;&#xA;1. Emitting data to disk, not just frames but all data. Something which would break most games speediness instantly.&#xD;&#xA;&#xD;&#xA;2. Working on general hardware. The GPU is much faster for certain things once you optimize for the GPU. But it does not work for all loads, in fact an Intel CPU is faster at computing in general than the GPU. The GPU is just massively parallel which the CPU is not. The architecture wins if you can stay in the GPU and minimize transfer and optimize for the GPU architecture.&#xD;&#xA;&#xD;&#xA;So you pay for flexibility and ease of use. But yes, I'll admit both Maya and Max suffer from extreme old age. So they could be faster.&#xD;&#xA;&#xD;&#xA;**TL;DR** The difference is mostly in optimization (read lots of tricks) and available external resources.&#xD;&#xA;&#xD;&#xA;PS: There is a misconception that this is because it is more physically correct. It certainly can be, but the ray tracer is not inherently more physically correct than your average game or any other computation. In fact, many games use really good models while quite many modelers do not.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;\* See http://www.graphics.cornell.edu/~bjw/mca.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="38793" PostHistoryTypeId="24" PostId="1822" RevisionGUID="feb72cd1-e86c-4610-9400-d2bdba9700cd" CreationDate="2022-10-26T14:48:42.807" Comment="Proposed by 9199 approved by 38 edit id of 601" ContentLicense="CC BY-SA 4.0" />
  <row Id="38794" PostHistoryTypeId="2" PostId="13061" RevisionGUID="dfab437e-5d06-4c2a-aaba-9887679bb69c" CreationDate="2022-10-26T14:52:34.670" UserId="18529" Text="I'm trying to implement a silhouette detection algorithm in post-processing. I've come across solutions based on Sobel/Roberts cross/... filters and I was wondering if there are more accurate techniques to perform the task.&#xD;&#xA;&#xD;&#xA;With silhouette edge I mean those edges that are at the boundary between a front-facing and a back-facing triangle of a polygonal mesh with respect to the view direction.&#xD;&#xA;&#xD;&#xA;One thing that is really important for my application is consistent silhouette thickness (so that I could inflate the output in later passes to reach a target width).&#xD;&#xA;&#xD;&#xA;I am assuming a Sobel filter on depth values (or similar) alone is not enough to consistently detect silhouettes (since it detects large enough discontinuities...that are oftentimes coincident with what we consider silhouettes).&#xD;&#xA;**Is it true or a simple filter tweaked for this purpose could perform just fine?**&#xD;&#xA;&#xD;&#xA;**Is there any other documented post-processing technique for silhouette detection?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've been experimenting with the following approach:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This approach seems to work quite well, however, **does it makes any sense to you?&#xD;&#xA;Am I re-inventing something that already exists?** &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3AuD4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38796" PostHistoryTypeId="1" PostId="13061" RevisionGUID="dfab437e-5d06-4c2a-aaba-9887679bb69c" CreationDate="2022-10-26T14:52:34.670" UserId="18529" Text="Silhouette edge detection alternatives to Sobel" ContentLicense="CC BY-SA 4.0" />
  <row Id="38797" PostHistoryTypeId="3" PostId="13061" RevisionGUID="dfab437e-5d06-4c2a-aaba-9887679bb69c" CreationDate="2022-10-26T14:52:34.670" UserId="18529" Text="|opengl|z-buffer|post-processing|direct3d|silhouette|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38798" PostHistoryTypeId="5" PostId="13061" RevisionGUID="c371e16e-a652-49c4-b70f-73f88f4a53d2" CreationDate="2022-10-26T14:58:38.587" UserId="18529" Comment="added 15 characters in body" Text="I'm trying to implement a silhouette detection algorithm in post-processing. I've come across solutions based on Sobel/Roberts cross/... filters and I was wondering if there are more accurate techniques to perform the task.&#xD;&#xA;&#xD;&#xA;With silhouette edge I mean those edges that are at the boundary between a front-facing and a back-facing triangle of a polygonal mesh with respect to the view direction.&#xD;&#xA;&#xD;&#xA;One thing that is really important for my application is consistent silhouette thickness (so that I could inflate the output in later passes to reach a target width).&#xD;&#xA;&#xD;&#xA;I am assuming a Sobel filter based approach on depth values (or similar) alone is not enough to consistently detect silhouettes (since it detects large enough discontinuities...that are oftentimes coincident with what we consider silhouettes).&#xD;&#xA;**Is it true or a simple filter tweaked for this purpose could perform just fine?**&#xD;&#xA;&#xD;&#xA;**Is there any other documented post-processing technique for silhouette detection?**&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've been experimenting with the following approach:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This approach seems to work quite well, however, **does it makes any sense to you?&#xD;&#xA;Am I re-inventing something that already exists?** &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3AuD4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38799" PostHistoryTypeId="50" PostId="10619" RevisionGUID="f75ec38f-c776-471c-86f7-906729331734" CreationDate="2022-10-26T17:08:26.023" UserId="-1" />
  <row Id="38800" PostHistoryTypeId="2" PostId="13062" RevisionGUID="92c6295c-3356-4fca-8e4e-5c9877fae02d" CreationDate="2022-10-26T20:36:48.373" UserId="19092" Text="&#xD;&#xA;&#xD;&#xA;I botched together the following code to do a simple rotating radar display.&#xD;&#xA;&#xD;&#xA;Q1) How can I eliminate the flicker of the line being drawn and then drawn over. Can I use double buffering somehow ?&#xD;&#xA;&#xD;&#xA;Q2) How can I get Mouse and Keyborad inputs and process/parse them.&#xD;&#xA;&#xD;&#xA;My goal is to read angle and distance data from an ultrasonic sensor and display that as a sweep. This data comes from an Arduino with an ultrasonic rangefinder mounted on a servo sweeping backwards and forwards 180 Deg. I also cant quite get the math right. I'd like it to go from 0 to 180, left to right and back depending on the angle data from the Arduino. 0 Deg is 90 Deg off to the right. So I know I have to offset it by 180 Deg but am hopeless at math. The sweep would have to start at 270 Deg and sweep through to 0 Deg. I will have to learn how to read the serial port and parse the data for the display.&#xD;&#xA;&#xD;&#xA;Any help would be appreciated.&#xD;&#xA;&#xD;&#xA;Pls don't jump on me. Just trying to learn.&#xD;&#xA;&#xD;&#xA;Here is my code. I used a tutorial as a base and kind of guessed my way through.&#xD;&#xA;&#xD;&#xA;CODE:&#xD;&#xA;&#xD;&#xA;    /*&#xD;&#xA;     * simple-drawing.c - demonstrate drawing of pixels, lines, arcs, etc.&#xD;&#xA;     *                    on a window. All drawings are done in black color&#xD;&#xA;     *                    over a white background.&#xD;&#xA;     */&#xD;&#xA;    &#xD;&#xA;    #include &lt;X11/Xlib.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;     /* getenv(), etc. */&#xD;&#xA;    #include &lt;unistd.h&gt;     /* sleep(), etc.  */&#xD;&#xA;&#xD;&#xA;    // Include math library functions.&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;&#xD;&#xA;    /*&#xD;&#xA;     * function: create_simple_window. Creates a window with a white background&#xD;&#xA;     *           in the given size.&#xD;&#xA;     * input:    display, size of the window (in pixels), and location of the window&#xD;&#xA;     *           (in pixels).&#xD;&#xA;     * output:   the window's ID.&#xD;&#xA;     * notes:    window is created with a black border, 2 pixels wide.&#xD;&#xA;     *           the window is automatically mapped after its creation.&#xD;&#xA;     */&#xD;&#xA;    Window&#xD;&#xA;    create_simple_window(Display* display, int width, int height, int x, int y)&#xD;&#xA;    {&#xD;&#xA;      int screen_num = DefaultScreen(display);&#xD;&#xA;      int win_border_width = 2;&#xD;&#xA;      Window win;&#xD;&#xA;    &#xD;&#xA;      /* create a simple window, as a direct child of the screen's */&#xD;&#xA;      /* root window. Use the screen's black and white colors as   */&#xD;&#xA;      /* the foreground and background colors of the window,       */&#xD;&#xA;      /* respectively. Place the new window's top-left corner at   */&#xD;&#xA;      /* the given 'x,y' coordinates.                              */&#xD;&#xA;      win = XCreateSimpleWindow(display, RootWindow(display, screen_num),&#xD;&#xA;                                x, y, width, height, win_border_width,&#xD;&#xA;                                BlackPixel(display, screen_num),&#xD;&#xA;                                WhitePixel(display, screen_num));   &#xD;&#xA;    &#xD;&#xA;      /* make the window actually appear on the screen. */&#xD;&#xA;      XMapWindow(display, win);&#xD;&#xA;    &#xD;&#xA;      /* flush all pending requests to the X server. */&#xD;&#xA;      XFlush(display);&#xD;&#xA;    &#xD;&#xA;      return win;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    GC&#xD;&#xA;    create_gc(Display* display, Window win, int reverse_video)&#xD;&#xA;    {&#xD;&#xA;      GC gc;                /* handle of newly created GC.  */&#xD;&#xA;      unsigned long valuemask = 0;      /* which values in 'values' to  */&#xD;&#xA;                        /* check when creating the GC.  */&#xD;&#xA;      XGCValues values;         /* initial values for the GC.   */&#xD;&#xA;      unsigned int line_width = 2;      /* line width for the GC.       */&#xD;&#xA;      int line_style = LineSolid;       /* style for lines drawing and  */&#xD;&#xA;      int cap_style = CapButt;      /* style of the line's edje and */&#xD;&#xA;      int join_style = JoinBevel;       /*  joined lines.       */&#xD;&#xA;      int screen_num = DefaultScreen(display);&#xD;&#xA;    &#xD;&#xA;      gc = XCreateGC(display, win, valuemask, &amp;values);&#xD;&#xA;      if (gc &lt; 0) {&#xD;&#xA;        fprintf(stderr, &quot;XCreateGC: \n&quot;);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* allocate foreground and background colors for this GC. */&#xD;&#xA;      if (reverse_video) {&#xD;&#xA;        XSetForeground(display, gc, WhitePixel(display, screen_num));&#xD;&#xA;        XSetBackground(display, gc, BlackPixel(display, screen_num));&#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        XSetForeground(display, gc, BlackPixel(display, screen_num));&#xD;&#xA;        XSetBackground(display, gc, WhitePixel(display, screen_num));&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* define the style of lines that will be drawn using this GC. */&#xD;&#xA;      XSetLineAttributes(display, gc,&#xD;&#xA;                         line_width, line_style, cap_style, join_style);&#xD;&#xA;    &#xD;&#xA;      /* define the fill style for the GC. to be 'solid filling'. */&#xD;&#xA;      XSetFillStyle(display, gc, FillSolid);&#xD;&#xA;    &#xD;&#xA;      return gc;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void&#xD;&#xA;    main(int argc, char* argv[])&#xD;&#xA;    {&#xD;&#xA;      Display* display;     /* pointer to X Display structure.           */&#xD;&#xA;      int screen_num;       /* number of screen to place the window on.  */&#xD;&#xA;      Window win;           /* pointer to the newly created window.      */&#xD;&#xA;      unsigned int display_width,&#xD;&#xA;                   display_height;  /* height and width of the X display.        */&#xD;&#xA;      unsigned int width, height;   /* height and width for the new window.      */&#xD;&#xA;      char *display_name = getenv(&quot;DISPLAY&quot;);  /* address of the X display.      */&#xD;&#xA;      GC gc;            /* GC (graphics context) used for drawing    */&#xD;&#xA;                        /*  in our window.               */&#xD;&#xA;&#xD;&#xA;      // Added code to select simple black or white color to draw.&#xD;&#xA;      Colormap screen_colormap;     /* color map to use for allocating colors.   */&#xD;&#xA;      XColor black, white;&#xD;&#xA;                                    /* used for allocation of the given color    */&#xD;&#xA;                                    /* map entries.                              */&#xD;&#xA;      Status rc;                    /* return status of various Xlib functions.  */&#xD;&#xA;    &#xD;&#xA;    // Johns stuff. This code draws a line from starting co-ordinates at an angle&#xD;&#xA;    // &#xD;&#xA;    &#xD;&#xA;    int angle=0;&#xD;&#xA;    int x1,x2,y1,y2;&#xD;&#xA;    int px,py;&#xD;&#xA;    &#xD;&#xA;    // End&#xD;&#xA;    &#xD;&#xA;      /* open connection with the X server. */&#xD;&#xA;      display = XOpenDisplay(display_name);&#xD;&#xA;      if (display == NULL) {&#xD;&#xA;        fprintf(stderr, &quot;%s: cannot connect to X server '%s'\n&quot;,&#xD;&#xA;                argv[0], display_name);&#xD;&#xA;        exit(1);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* get the geometry of the default screen for our display. */&#xD;&#xA;      screen_num = DefaultScreen(display);&#xD;&#xA;      display_width = DisplayWidth(display, screen_num);&#xD;&#xA;      display_height = DisplayHeight(display, screen_num);&#xD;&#xA;    &#xD;&#xA;      /* make the new window occupy 1/9 of the screen's size. */&#xD;&#xA;      width = (display_width / 2); &#xD;&#xA;      height = (display_height / 2);&#xD;&#xA;      printf(&quot;window width - '%d'; height - '%d'\n&quot;, width, height);&#xD;&#xA;    &#xD;&#xA;      /* create a simple window, as a direct child of the screen's   */&#xD;&#xA;      /* root window. Use the screen's white color as the background */&#xD;&#xA;      /* color of the window. Place the new window's top-left corner */&#xD;&#xA;      /* at the given 'x,y' coordinates.                             */&#xD;&#xA;      win = create_simple_window(display, width, height, 50, 50);&#xD;&#xA;    &#xD;&#xA;      /* allocate a new GC (graphics context) for drawing in the window. */&#xD;&#xA;      gc = create_gc(display, win, 0);&#xD;&#xA;      XSync(display, False);&#xD;&#xA;    &#xD;&#xA;      // Following 3 lines needed or else we just see white background.&#xD;&#xA;&#xD;&#xA;      /* catch expose events */&#xD;&#xA;      XSelectInput(display, win, ExposureMask);&#xD;&#xA;    &#xD;&#xA;      /* wait for the expose event */&#xD;&#xA;      XEvent ev;&#xD;&#xA;      XNextEvent(display, &amp;ev);&#xD;&#xA; &#xD;&#xA;      // Follwing code borrowed to get colors to draw.    &#xD;&#xA;      /* get access to the screen's color map. */&#xD;&#xA;      screen_colormap = DefaultColormap(display, DefaultScreen(display));&#xD;&#xA;    &#xD;&#xA;      /* allocate the set of colors we will want to use for the drawing. */&#xD;&#xA;      rc = XAllocNamedColor(display, screen_colormap, &quot;black&quot;, &amp;black, &amp;black);&#xD;&#xA;      if (rc == 0) {&#xD;&#xA;        fprintf(stderr, &quot;XAllocNamedColor - failed to allocated 'black' color.\n&quot;);&#xD;&#xA;        exit(1);&#xD;&#xA;      }&#xD;&#xA;      rc = XAllocNamedColor(display, screen_colormap, &quot;white&quot;, &amp;white, &amp;white);&#xD;&#xA;      if (rc == 0) {&#xD;&#xA;        fprintf(stderr, &quot;XAllocNamedColor - failed to allocated 'white' color.\n&quot;);&#xD;&#xA;        exit(1);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* draw one pixel near each corner of the window */&#xD;&#xA;      XDrawPoint(display, win, gc, 5, 5);&#xD;&#xA;      XDrawPoint(display, win, gc, 5, height-5);&#xD;&#xA;      XDrawPoint(display, win, gc, width-5, 5);&#xD;&#xA;      XDrawPoint(display, win, gc, width-5, height-5);&#xD;&#xA;    &#xD;&#xA;    // Do our display. Loop forever because I don't know how to process keystrokes.&#xD;&#xA;    // If we start from the center of the display, 0 is to the right (E), 90 is to the&#xD;&#xA;    // bottom (S), 180 (W),270 (N). Don't quite know how to &quot;rotate&quot; the &quot;beam&quot; 180 Deg.&#xD;&#xA;    // Needs double buffering to remove the flicker.&#xD;&#xA;    // I would like to make a seperate subroutine eg: DrawRadar( int angle, int distance);&#xD;&#xA;    &#xD;&#xA;      x1=width / 2;     //Find center of display.&#xD;&#xA;      y1=height / 2;&#xD;&#xA;      px=x1;            // Previous X and Y&#xD;&#xA;      py=y1;&#xD;&#xA;    &#xD;&#xA;    while(1){&#xD;&#xA;    &#xD;&#xA;      for(angle=0; angle &lt; 360; angle++)&#xD;&#xA;      {&#xD;&#xA;&#xD;&#xA;      // Distance set to 150 pixels. Radar returns value up to 3300 mm.&#xD;&#xA;      // Will have to scale down. &#xD;&#xA;        x2=x1 + cos((angle * M_PI) / 180) * 150;   // Must convert to radians.&#xD;&#xA;        y2=y1 + sin((angle * M_PI) / 180) * 150;   //  &quot;     &quot;      &quot;    &quot;&#xD;&#xA;    &#xD;&#xA;        XSetForeground(display, gc, black.pixel);  // &#xD;&#xA;        XDrawLine(display, win, gc, x1, y1, x2, y2);&#xD;&#xA;        px=x2;&#xD;&#xA;        py=y2;&#xD;&#xA;        XFlush(display);      // Display what we've drawn.&#xD;&#xA;        usleep(3500);         // Wait so eye can see it.&#xD;&#xA;        XSetForeground(display, gc, white.pixel);  // Rub out the line we just drew.&#xD;&#xA;        XDrawLine(display, win, gc, x1, y1, px ,py);&#xD;&#xA;        XFlush(display);      // Causes flickering but only way at the moment.&#xD;&#xA;        XSetForeground(display, gc, black.pixel);&#xD;&#xA;        usleep(3500);&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    // End. Never get past here.&#xD;&#xA;    &#xD;&#xA;      /* flush all pending requests to the X server. */&#xD;&#xA;      XFlush(display);&#xD;&#xA;      XSync(display, False);&#xD;&#xA;    &#xD;&#xA;      /* make a delay for a short period. */&#xD;&#xA;      sleep(4);&#xD;&#xA;    &#xD;&#xA;      /* close the connection to the X server. */&#xD;&#xA;      XCloseDisplay(display);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;Simply trying to draw a moving line without flicker. I understand the concept but am a crap coder. Any help would be appreciated.&#xD;&#xA;&#xD;&#xA;Thanks, John.``&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38802" PostHistoryTypeId="1" PostId="13062" RevisionGUID="92c6295c-3356-4fca-8e4e-5c9877fae02d" CreationDate="2022-10-26T20:36:48.373" UserId="19092" Text="Newbie Issue with X11 Double buffering. Request help with code" ContentLicense="CC BY-SA 4.0" />
  <row Id="38803" PostHistoryTypeId="3" PostId="13062" RevisionGUID="92c6295c-3356-4fca-8e4e-5c9877fae02d" CreationDate="2022-10-26T20:36:48.373" UserId="19092" Text="|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38804" PostHistoryTypeId="2" PostId="13063" RevisionGUID="102b0048-3c25-41c2-9cb3-c3b6d29867f2" CreationDate="2022-10-27T03:44:45.400" UserId="18468" Text="I am a newbie in Computer graphics and trying to implement Dynamic Fusion following [the paper][1]. I can understand most of the paper, but there is this line bothering me &quot;rendering the warped surface into the live frame shaded with canonical frame vertex positions using a rasterizing rendering pipeline.&quot; in section 3.3.1. It is unclear to me what &quot;shaded with vertex positions&quot; means because I thought you need light and camera position to do it, i.e. there is no input as &quot;vertex position&quot; for shading. I tried to re-read wikipedia and opengl, but I can't find the term &quot;shaded with vertex position&quot;.&#xD;&#xA;&#xD;&#xA;Currently I am using z-buffering to render the depth image from the surface and computing vertex and normal mapsfrom resulted depth maps for other computations. However, that line is still bugging me because clearly I don't have enough knowledge to understand it. I hope someone could help me. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://grail.cs.washington.edu/projects/dynamicfusion/papers/DynamicFusion.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="38806" PostHistoryTypeId="1" PostId="13063" RevisionGUID="102b0048-3c25-41c2-9cb3-c3b6d29867f2" CreationDate="2022-10-27T03:44:45.400" UserId="18468" Text="What does &quot;rendering a surface shaded with vertex positions&quot; mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38807" PostHistoryTypeId="3" PostId="13063" RevisionGUID="102b0048-3c25-41c2-9cb3-c3b6d29867f2" CreationDate="2022-10-27T03:44:45.400" UserId="18468" Text="|shading|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38810" PostHistoryTypeId="2" PostId="13065" RevisionGUID="8c39f985-7bda-4783-8c34-10096ed3255f" CreationDate="2022-10-27T06:52:39.920" UserId="18634" Text="I am compressing a string of data in the formats of float. The current approach is throwing away eight bits in the integer part as my float is strictly within [0,1].&#xD;&#xA;&#xD;&#xA;I wonder how I could do this.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38812" PostHistoryTypeId="1" PostId="13065" RevisionGUID="8c39f985-7bda-4783-8c34-10096ed3255f" CreationDate="2022-10-27T06:52:39.920" UserId="18634" Text="compressing my [0,1] floats by throwing away the integer part" ContentLicense="CC BY-SA 4.0" />
  <row Id="38813" PostHistoryTypeId="3" PostId="13065" RevisionGUID="8c39f985-7bda-4783-8c34-10096ed3255f" CreationDate="2022-10-27T06:52:39.920" UserId="18634" Text="|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38814" PostHistoryTypeId="2" PostId="13066" RevisionGUID="d5747ef7-2fc3-49e7-bdb0-101fb89b60b2" CreationDate="2022-10-27T07:47:16.963" UserId="13273" Text="I am calculating the Summed Area Table(SAT) of a texture with help of a compute shader in OpenGL.&#xD;&#xA;The texture which needs to be summed, has a dimension size of more than my GPU supports (GL_MAX_COMPUTE_WORK_GROUP_SIZE).&#xD;&#xA;&#xD;&#xA;Right now I am trying to do this with two steps. First build the sum for each row, in a 2nd step build the sum for each column using the first result.&#xD;&#xA;&#xD;&#xA;To simply explane how it is working, I only write down the horizontal calculation, because the vertical works in the same way.&#xD;&#xA;&#xD;&#xA;My workGroupSize is 1024 * 1 * 1 (the maximum my GPU supports) and each workgroup has its own row. &#xD;&#xA;&#xD;&#xA;This is how it works:&#xD;&#xA;First, each invocation loads its pixel from the texture and stores the result into a shared array.&#xD;&#xA;Then a invocation synchronization of a workgroup (barrier();) is performed within the shader.&#xD;&#xA;After the texture row has been stored to the shared memory, the invocations group themself into blocks with size of potentials of 2 beginning with 2, 4, 8, 16...&#xD;&#xA;the sum will be stored to the shared memory and a synchronization manages, that the next iteration can read without conflicts the last value of the previous block.&#xD;&#xA;This value needs to be summed to each arrayindex of the shared array within the block.&#xD;&#xA;With this technique I only have one pixel read per invocation and log2(textureSize.x) iterations of calculation.&#xD;&#xA;&#xD;&#xA;The big problem is, that when the texture size if larger than 1024 pixels, then the algorithm needs that all workgroups are synchronized to read out the left neighboring blocks last result. Which can be stored to SSBO...&#xD;&#xA;&#xD;&#xA;Here my code to calculate one row per workgroup:&#xD;&#xA;&#xD;&#xA;    layout (local_size_x = 1024, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    shared float sat[1024];&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        uvec4 value;&#xD;&#xA;        if(pass == 0) //sat horizontal&#xD;&#xA;            value = imageLoad(textureBase, ivec3(gl_GlobalInvocationID.xy,0));&#xD;&#xA;        else //sat vertical&#xD;&#xA;            value = imageLoad(textureBase, ivec3(gl_GlobalInvocationID.yx,0));&#xD;&#xA;        sat[gl_LocalInvocationIndex] = uintBitsToFloat(value.x);&#xD;&#xA;       &#xD;&#xA;        barrier(); //until here, the SAT is initialized.&#xD;&#xA;        for(int i = 0; i &lt; log2(1024); ++i)&#xD;&#xA;        {&#xD;&#xA;            int size = int(pow(2, i+1));&#xD;&#xA;            int locationGroup = int(mod(int(gl_LocalInvocationIndex), size));&#xD;&#xA;            int doAdd = locationGroup &gt;= size / 2 ? 1 : 0;&#xD;&#xA;            int addIndex = int(gl_LocalInvocationIndex) - (locationGroup - size / 2) - 1;&#xD;&#xA;            barrier();&#xD;&#xA;            float valueToAdd = sat[addIndex];&#xD;&#xA;            barrier();&#xD;&#xA;            if(doAdd == 1)&#xD;&#xA;            {&#xD;&#xA;                sat[gl_LocalInvocationIndex] += valueToAdd;&#xD;&#xA;            }&#xD;&#xA;            barrier();&#xD;&#xA;        }&#xD;&#xA;        uint result = floatBitsToUint(sat[gl_LocalInvocationIndex]);&#xD;&#xA;        imageStore(textureBase, ivec3(gl_GlobalInvocationID.xy,0), uvec4(gl_LocalInvocationIndex,0,result,0));&#xD;&#xA;        if(pass == 0) //sat horizontal&#xD;&#xA;            imageStore(textureBase, ivec3(gl_GlobalInvocationID.xy,0), uvec4(result,0,0,0));&#xD;&#xA;        else //sat vertical&#xD;&#xA;            imageStore(textureBase, ivec3(gl_GlobalInvocationID.yx,0), uvec4(result,0,0,0));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When having a 2048x2048 texture, two workgroups would calculate the result of one row (1st [0, 1024) 2nd [1024, 2048) ).&#xD;&#xA;At the end of this shader program, the SAT of each 1024 block has finished. The next step would be reading the 1023th value of the previous (left) neighboring workgroup and add this value to each other value within its shared array.&#xD;&#xA;&#xD;&#xA;How can I synchronize the workgroups, so that at the end of this code they will be synchronized to then load the last value of the previous block?&#xD;&#xA;&#xD;&#xA;All invocations of all workgroups have the same number of barrier().&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38816" PostHistoryTypeId="1" PostId="13066" RevisionGUID="d5747ef7-2fc3-49e7-bdb0-101fb89b60b2" CreationDate="2022-10-27T07:47:16.963" UserId="13273" Text="OpenGL compute shader workgroup synconization" ContentLicense="CC BY-SA 4.0" />
  <row Id="38817" PostHistoryTypeId="3" PostId="13066" RevisionGUID="d5747ef7-2fc3-49e7-bdb0-101fb89b60b2" CreationDate="2022-10-27T07:47:16.963" UserId="13273" Text="|opengl|glsl|compute-shader|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38818" PostHistoryTypeId="5" PostId="2303" RevisionGUID="03d04203-c36c-448f-a288-b0b58b3da268" CreationDate="2022-10-27T08:15:08.390" UserId="9199" Comment="Typo fixes" Text="I have a vertex buffer like this:&#xD;&#xA;&#xD;&#xA;    0.0, 0.0,&#xD;&#xA;    1.0, 0.0,&#xD;&#xA;    0.0, 0.6,&#xD;&#xA;    1.0, 0.6,&#xD;&#xA;    0.5, 1.0&#xD;&#xA;&#xD;&#xA;I have the following index buffer:&#xD;&#xA;&#xD;&#xA;    0, 2,&#xD;&#xA;    2, 4,&#xD;&#xA;    4, 3,&#xD;&#xA;    3, 2,&#xD;&#xA;    2, 1,&#xD;&#xA;    1, 0,&#xD;&#xA;    0, 3,&#xD;&#xA;    3, 1&#xD;&#xA;&#xD;&#xA;I know I want to draw `gl.LINES` using WebGL, which means multiple separated line segments.&#xD;&#xA;&#xD;&#xA;    gl.drawElements(gl.LINES, 16, gl.UNSIGNED_SHORT, indexBuffer);&#xD;&#xA;&#xD;&#xA;It seems to enable drawing of multiple line segments in a single draw call in WebGL.&#xD;&#xA;&#xD;&#xA;Could someone ELI5 to me, what is an index buffer and how is it related to vertex buffers? How to generate index buffers from my primitives?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38819" PostHistoryTypeId="24" PostId="2303" RevisionGUID="03d04203-c36c-448f-a288-b0b58b3da268" CreationDate="2022-10-27T08:15:08.390" Comment="Proposed by 9199 approved by 3073, 209 edit id of 599" ContentLicense="CC BY-SA 4.0" />
  <row Id="38820" PostHistoryTypeId="2" PostId="13067" RevisionGUID="c5b1ae90-4c6a-47ea-ba17-cf0fcf11c36b" CreationDate="2022-10-27T09:02:59.690" UserId="209" Text="I would say the reason for reducing cases of alpha blending (or testing) has less to do with the cost of the actual read-modify-write but more to do with increasing the use of early Z testing that's available in either, say, a TBDR system (eg PowerVR) or in systems with hierarchical Z.&#xD;&#xA;&#xD;&#xA;For early Z, which can reject a significant amount of otherwise redundant work, the driver/API needs to know the geometry is 100% opaque. As soon as there is a chance of a blend, the early-Z probably needs to be disabled. Note that its not just the read-modify-write we should be concerned about - early-Z often avoids running potentially V. expensive shaders.&#xD;&#xA;&#xD;&#xA;For cases where there is alpha tested geometry, e.g. a leaves of a tree, it may be beneficial to replace, say, every leaf that's modelled with a pair of alpha blended triangles with multiple triangles so that some of those tris are guaranteed to be 100% opaque. All the opaque tris should be batched together and rendered first as opaque." ContentLicense="CC BY-SA 4.0" />
  <row Id="38822" PostHistoryTypeId="2" PostId="13068" RevisionGUID="365dcb01-d08e-480e-9bd5-fc665ba70fda" CreationDate="2022-10-27T15:11:04.730" UserId="2654" Text="You cannot synchronize work groups. You can only synchronize work items *within* a work group. All work groups execute entirely independently of each other.&#xD;&#xA;&#xD;&#xA;Your algorithm must be adjusted accordingly. If you want to read stuff other work groups wrote, you have to execute a second compute shader operation that reads that data (with appropriate synchronization). Which means the data needs to be written to memory." ContentLicense="CC BY-SA 4.0" />
  <row Id="38824" PostHistoryTypeId="2" PostId="13069" RevisionGUID="58ddfb6d-a127-4ef5-b0ec-9dc6039729e9" CreationDate="2022-10-27T17:51:54.253" UserId="48" Text="A couple sentences later, they say:&#xD;&#xA;&#xD;&#xA;&gt; We store this prediction as a pair of images $\{ \mathbf{v}, \mathbf{n} \} : \Omega \mapsto \mathcal{P}(\mathcal{\hat V}_c)$, where&#xD;&#xA;$\Omega$ is the pixel domain of the predicted images, storing the&#xD;&#xA;rendered canonical frame vertices and normals.&#xD;&#xA;&#xD;&#xA;So it sounds like what they're doing is rendering the warped geometry using a fragment shader that outputs to multiple render targets (perhaps using floating-point texture formats), and stores the original vertex positions and normals to those render targets." ContentLicense="CC BY-SA 4.0" />
  <row Id="38826" PostHistoryTypeId="2" PostId="13070" RevisionGUID="58c87857-6105-4bf9-bcde-0ec1fec207c4" CreationDate="2022-10-27T18:32:30.593" UserId="19114" Text="I made a plane in THREEjs using Mesh, PlaneGeometry and ShaderMaterial. It's a very simple/basic form.&#xD;&#xA;I applied a simple phormula to make the plain more steep. Now I'm trying to make the lower surface darker than the higher surface. Here is what I tried.&#xD;&#xA;&#xD;&#xA;Vertex shader:&#xD;&#xA;&#xD;&#xA;		varying vec3 vColor;&#xD;&#xA;		varying vec3 test;&#xD;&#xA;&#xD;&#xA;		void main(void) {&#xD;&#xA;            float amp = 2.5;&#xD;&#xA;			float z = amp * sin(position.x*0.2)  * cos(position.y*0.5); //this makes the surface steeper&#xD;&#xA;			test = vec3(1, 1, -z); //this goes to fragment shader&#xD;&#xA;&#xD;&#xA;			gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;Fragment shader:&#xD;&#xA;&#xD;&#xA;        precision mediump float;&#xD;&#xA;		varying vec3 test;&#xD;&#xA;		void main(void) {	&#xD;&#xA;			vec3 st = gl_FragCoord.xyz/test;&#xD;&#xA;			gl_FragColor = vec4(st.xyz, 1.0);&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;Result:&#xD;&#xA;&#xD;&#xA;[![Result from this][1]][1]&#xD;&#xA;&#xD;&#xA;This result is not desirable, since the contrast between top and down is too aggressive and I'd like the lower surface less white. What do I have to change to accomplish this? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OpeCQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38828" PostHistoryTypeId="1" PostId="13070" RevisionGUID="58c87857-6105-4bf9-bcde-0ec1fec207c4" CreationDate="2022-10-27T18:32:30.593" UserId="19114" Text="How to make elevated parts of a steep plane seem darker than the lower surface? [GLSL]" ContentLicense="CC BY-SA 4.0" />
  <row Id="38829" PostHistoryTypeId="3" PostId="13070" RevisionGUID="58c87857-6105-4bf9-bcde-0ec1fec207c4" CreationDate="2022-10-27T18:32:30.593" UserId="19114" Text="|shader|glsl|javascript|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38830" PostHistoryTypeId="50" PostId="13002" RevisionGUID="e727ffaa-ed6e-47ae-aa38-eadda88d79e8" CreationDate="2022-10-28T00:07:11.013" UserId="-1" />
  <row Id="38831" PostHistoryTypeId="5" PostId="4993" RevisionGUID="8c0b1062-63d4-4bd8-b644-801c84504dac" CreationDate="2022-10-28T10:20:25.967" UserId="13111" Comment="Corrected spelling, fixed grammar" Text="If you have a 1D function $f(x)$ and you want to integrate this function from say 0 to 1, one way to perform this integration is by taking N random samples in range [0, 1], evaluate $f(x)$ for each sample and calculate the average of the samples. However, this &quot;naive&quot; Monte Carlo integration is said to &quot;converge slowly&quot;, i.e. you need a large number of samples to get close to the ground truth, particularly if the function has high frequencies.&#xD;&#xA;&#xD;&#xA;With importance sampling, instead of taking N random samples in [0, 1] range, you take more samples in the &quot;important&quot; regions of $f(x)$ that contribute most to the final result. However, because you bias sampling towards the important regions of the function, these samples must be weighted less to counter the bias, which is where the PDF (probability density function) comes along. PDF tells the probability of a sample at a given position and is used to calculate the weighted average of the samples by dividing each sample with the PDF value at each sample position.&#xD;&#xA;&#xD;&#xA;With Cook-Torrance importance sampling the common practice is to distribute samples based on the normal distribution function NDF. If NDF is already normalized, it can serve directly as PDF, which is convenient since it cancels the term out from the BRDF evaluation. Only thing you need to do then is to distribute sample positions based on PDF and evaluate BRDF without the NDF term, i.e.&#xD;&#xA;$$f=\frac{FG}{\pi(n\cdot\omega_i)(n\cdot\omega_o)}$$&#xD;&#xA;And calculate the average of the sample results multiplied by the solid angle of the domain you integrate over (e.g. $2\pi$ for hemisphere).&#xD;&#xA;&#xD;&#xA;For NDF you need to calculate [Cumulative Distribution Function][1] of the PDF to convert uniformly distributed sample position to PDF weighted sample position. For isotropic NDF this simplifies to 1D function because of the symmetry of the function. For more details about the CDF derivation you can check [this old GPU Gems article][2].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cumulative_distribution_function&#xD;&#xA;  [2]: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="38832" PostHistoryTypeId="24" PostId="4993" RevisionGUID="8c0b1062-63d4-4bd8-b644-801c84504dac" CreationDate="2022-10-28T10:20:25.967" Comment="Proposed by 13111 approved by 209, 7952 edit id of 598" ContentLicense="CC BY-SA 4.0" />
  <row Id="38833" PostHistoryTypeId="5" PostId="1819" RevisionGUID="75ddf05e-cab8-4a6e-90c8-77222b3b15f0" CreationDate="2022-10-28T10:20:51.867" UserId="9199" Comment="Typo fixes" Text="The main difference would be that with OpenGL in let's say a video game, you will have a process called *rasterization* which basically takes care of determining what part of the scene you see.&#xD;&#xA;&#xD;&#xA;It needs to be fast so we can experience it as realtime.&#xD;&#xA;&#xD;&#xA;Therefore the algorithm does a few simple steps.&#xD;&#xA;&#xD;&#xA;* Check if a certain part of the scene is in my view frustum&#xD;&#xA;&#xD;&#xA;  [![Frustum Culling][1]][1]&#xD;&#xA;&#xD;&#xA;* Check if something is in front of it which may needs to be rendered later using a depth buffer&#xD;&#xA;&#xD;&#xA;  [![Depth Buffer][2]][2]&#xD;&#xA;&#xD;&#xA;* Order the objects we found to draw&#xD;&#xA;* *Draw them* by projecting them on the screen&#xD;&#xA;* *Shade them* based on textures / shaders / lights / ...&#xD;&#xA;&#xD;&#xA;On the other hand a rendering software (Blender/Max/Maya/...) most likely uses some kind of *raytracing*&#xD;&#xA;&#xD;&#xA;This involves a lot more math to achieve a higher degree of realism.&#xD;&#xA;&#xD;&#xA;It basically works in the same way:&#xD;&#xA;&#xD;&#xA;* Create a camera and an image plane in front of it&#xD;&#xA;* Shoot one ray (or multiple sample rays) through each pixel&#xD;&#xA;* Check if the ray hits anything in the scene&#xD;&#xA;* Closest hit is the one to be drawn in the pixel finally (like depth buffer)&#xD;&#xA;* Calculate the light for the given point&#xD;&#xA; [![Light Calculation][3]][3]&#xD;&#xA;&#xD;&#xA;....&#xD;&#xA;&#xD;&#xA;I'll stopped listing here since this is the point where raytracing takes off.&#xD;&#xA;&#xD;&#xA;Instead of only checking if a point is hit, most raytracer now begins to calculate: &#xD;&#xA;&#xD;&#xA;* the amount of light a surface penetrates&#xD;&#xA;* how much light gets reflected&#xD;&#xA;* cast new rays from the hitpoint into the scene until it may hit a light source&#xD;&#xA;&#xD;&#xA;There are a ton of techniques with different degrees of realism which can be used to calculate the light of a certain point in the scene.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**TL;DR**&#xD;&#xA;The gist would be that a raytracer mostly tries to be physically accurate when it comes the lighting and therefore has a lot of more calculations to do per pixel (sometimes shoot thousands of rays) and on the other hand games get their speed by drawing bigger chunks of the screen with simpler light calculations and a lot of shader tricks which let it look realistic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TqkCF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/7N5cL.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/jmB0K.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38834" PostHistoryTypeId="24" PostId="1819" RevisionGUID="75ddf05e-cab8-4a6e-90c8-77222b3b15f0" CreationDate="2022-10-28T10:20:51.867" Comment="Proposed by 9199 approved by 209, 7952 edit id of 600" ContentLicense="CC BY-SA 4.0" />
  <row Id="38835" PostHistoryTypeId="5" PostId="9084" RevisionGUID="badc7d7c-ba22-4213-8147-1c05da13f4ec" CreationDate="2022-10-28T10:21:00.853" UserId="19077" Comment="Remove ambiguity" Text="Actually what it meant by Affine Covariant regions is that covariant regions in two images which are related by some affine transformation. So the regions found in one image are exactly same regions in other image which have been transformed through affine transformation.&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="38836" PostHistoryTypeId="24" PostId="9084" RevisionGUID="badc7d7c-ba22-4213-8147-1c05da13f4ec" CreationDate="2022-10-28T10:21:00.853" Comment="Proposed by 19077 approved by 209, 7952 edit id of 597" ContentLicense="CC BY-SA 4.0" />
  <row Id="38837" PostHistoryTypeId="2" PostId="13071" RevisionGUID="9ff9a677-f300-4879-a397-ee5e0598a384" CreationDate="2022-10-28T17:42:25.203" UserId="19116" Text="Trying to understand how OpenGL generates what is seen as images &amp; graphics and these questions come up. &#xD;&#xA;&#xD;&#xA;1. Are 3D lines (which should be drawn using vectors) drawn using triangles or polygons? Or are they drawn using vector values? &#xD;&#xA;&#xD;&#xA;2. Are the triangles drawn using vectors or smaller triangles? &#xD;&#xA;&#xD;&#xA;3. Can raster pixel data be isolated horizontally and or vertically? &#xD;&#xA;&#xD;&#xA;4. Can raster pixel data be exported into text files? &#xD;&#xA;&#xD;&#xA;5. Can lines be drawn using custom raster brush/draw tool? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I haven't tried anything yet as there really isn't anything to try. These are questions out of curiosity of knowing how 3D lines, shapes &amp; objects are drawn in OpenGL. &#xD;&#xA;&#xD;&#xA;Hopefully the answers provided will help me decide on the framework, libraries and tools to adopt within project. I would appreciate helpful answers or guides to articles that shed some light into these questions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Questions asked are applicable to 2D canvas and 3D space.**&#xD;&#xA;&#xD;&#xA;P.S - I am absolutely new to Graphics Development &amp; programming... Be nice, Thanks&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38839" PostHistoryTypeId="1" PostId="13071" RevisionGUID="9ff9a677-f300-4879-a397-ee5e0598a384" CreationDate="2022-10-28T17:42:25.203" UserId="19116" Text="Is a line drawn using vectors, triangles or polygons within OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38840" PostHistoryTypeId="3" PostId="13071" RevisionGUID="9ff9a677-f300-4879-a397-ee5e0598a384" CreationDate="2022-10-28T17:42:25.203" UserId="19116" Text="|opengl|3d|c++|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38841" PostHistoryTypeId="2" PostId="13072" RevisionGUID="030858a7-f374-4eff-95ce-d0992cb0a718" CreationDate="2022-10-28T20:40:52.730" UserId="13273" Text="The general principle of OpenGL is using the GPU and a so called rendering pipeline where you can program parts of it on your own, called &quot;shader&quot;.&#xD;&#xA;&#xD;&#xA;The input model you want to draw (render) is stored in a so called VertexBufferObject (VBO). This buffer is simple memory, where you can add information what ever you need.&#xD;&#xA;&#xD;&#xA;Before rendering, you define how your data is defined... Here one set of data represents one &quot;Vertex&quot;. Usually it is a 3d vector. But you can add several information per vertex, for example a additional normal direction, texture coordinates, color, etc.&#xD;&#xA;The vertices are stored continuously. &#xD;&#xA;&#xD;&#xA;Then you can use a 2nd buffer if you like. This buffer is called index buffer object or element Buffer object. This buffer is optional. &#xD;&#xA;When using this buffer, you can store the vertex indices which should be combined to for example a triangle, line, triangle strip etc... &#xD;&#xA;&#xD;&#xA;When doing a draw call, you tell Opengl what type of primitives you want to draw. You can use point, line, triangle and different combinations how they should be connected to the following points. For example, when drawing simple triangles, Opengl uses the first 3 vertices to span a triangle and the next 3 vertices for the next triangle. You can also use triangle strips, there the next vertex will be connected this the last two vertices... &#xD;&#xA;&#xD;&#xA;Now let's go back to the shaders. &#xD;&#xA;The simplest setup is to use a vertex shader in combination with a fragment shader. The vertex shader code will be executed for each vertex. And is usually used to rotate/scale/translate the vertex position and add a projection. Additionally you can calculate everything else which is vertex based. You can pass data from vertex shader to fragment shader as well... But between vertex stage and fragment stage there is the &quot;Rasterizer&quot;. Each primitive will be clipped and culled with respect to the normalized device coordinates. The resulting primitives can hit pixels on your viewport. Then each hit Pixel calls the fragment shader. The data which will be passed from vertex to fragment shader will be interpolated... &#xD;&#xA;&#xD;&#xA;This is a very basic and absolutely not complete description, of how OpenGL works with your data. A lot of things are missing here, like depthbuffer, frameBufferObjects, rasterizer settings, blendings, textures, vertexArray and a lot more! But this would be way too much. &#xD;&#xA;&#xD;&#xA;After learning the very basics (draw a triangle) you can take a deeper look at other shader stages (Tessellation control, Tessellation evaluation, geometry) and for general purpos calculations you can use compute shader.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38843" PostHistoryTypeId="5" PostId="13072" RevisionGUID="84ccf053-73a5-436c-a690-cf80b3bb4d8f" CreationDate="2022-10-28T20:59:42.940" UserId="13273" Comment="added 168 characters in body" Text="The general principle of OpenGL is using the GPU and a so called rendering pipeline where you can program parts of it on your own, called &quot;shader&quot;.&#xD;&#xA;&#xD;&#xA;The input model you want to draw (render) is stored in a so called VertexBufferObject (VBO). This buffer is simple memory, where you can add information what ever you need.&#xD;&#xA;&#xD;&#xA;Before rendering, you define how your data is defined... Here one set of data represents one &quot;Vertex&quot;. Usually it is a 3d vector. But you can add several information per vertex, for example a additional normal direction, texture coordinates, color, etc.&#xD;&#xA;The vertices are stored continuously. &#xD;&#xA;&#xD;&#xA;Then you can use a 2nd buffer if you like. This buffer is called index buffer object or element Buffer object. This buffer is optional. &#xD;&#xA;When using this buffer, you can store the vertex indices which should be combined to for example a triangle, line, triangle strip etc... &#xD;&#xA;&#xD;&#xA;When doing a draw call, you tell Opengl what type of primitives you want to draw. You can use point, line, triangle and different combinations how they should be connected to the following points. For example, when drawing simple triangles, Opengl uses the first 3 vertices to span a triangle and the next 3 vertices for the next triangle. You can also use triangle strips, there the next vertex will be connected this the last two vertices... &#xD;&#xA;&#xD;&#xA;Now let's go back to the shaders. &#xD;&#xA;The simplest setup is to use a vertex shader in combination with a fragment shader. The vertex shader code will be executed for each vertex. And is usually used to rotate/scale/translate the vertex position and add a projection. Additionally you can calculate everything else which is vertex based. You can pass data from vertex shader to fragment shader as well... But between vertex stage and fragment stage there is the &quot;Rasterizer&quot;. Each primitive will be clipped and culled with respect to the normalized device coordinates. The resulting primitives can hit pixels on your viewport. Then each hit Pixel calls the fragment shader. The data which will be passed from vertex to fragment shader will be interpolated... &#xD;&#xA;&#xD;&#xA;This is a very basic and absolutely not complete description, of how OpenGL works with your data. A lot of things are missing here, like depthbuffer, frameBufferObjects, rasterizer settings, blendings, textures, vertexArray and a lot more! But this would be way too much. &#xD;&#xA;&#xD;&#xA;After learning the very basics (draw a triangle) you can take a deeper look at other shader stages (Tessellation control, Tessellation evaluation, geometry) and for general purpos calculations you can use compute shader.&#xD;&#xA;&#xD;&#xA;You asked for brushes... In general I would say no, but when drawing lines, you can define the line width. &#xD;&#xA;But brushes must be implemented using shaders on your own&#xD;&#xA;&#xD;&#xA;BTW: in case of choosing Opengl, I would recommend buying the book &quot;opengl super Bible&quot;. It is for beginners and has a math chapter which is very helpful. At the end they also show how different techniques like normal mapping can be implemented. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38844" PostHistoryTypeId="5" PostId="13072" RevisionGUID="0185d94c-d3df-4abe-9474-9979cc0387de" CreationDate="2022-10-28T21:07:14.503" UserId="13273" Comment="added 165 characters in body" Text="The general principle of OpenGL is using the GPU and a so called rendering pipeline where you can program parts of it on your own, called &quot;shader&quot;.&#xD;&#xA;&#xD;&#xA;The input model you want to draw (render) is stored in a so called VertexBufferObject (VBO). This buffer is simple memory, where you can add information what ever you need.&#xD;&#xA;&#xD;&#xA;Before rendering, you define how your data is defined... Here one set of data represents one &quot;Vertex&quot;. Usually it is a 3d vector. But you can add several information per vertex, for example a additional normal direction, texture coordinates, color, etc.&#xD;&#xA;The vertices are stored continuously. &#xD;&#xA;&#xD;&#xA;Then you can use a 2nd buffer if you like. This buffer is called index buffer object or element Buffer object. This buffer is optional. &#xD;&#xA;When using this buffer, you can store the vertex indices which should be combined to for example a triangle, line, triangle strip etc... &#xD;&#xA;&#xD;&#xA;When doing a draw call, you tell Opengl what type of primitives you want to draw. You can use point, line, triangle and different combinations how they should be connected to the following points. For example, when drawing simple triangles, Opengl uses the first 3 vertices to span a triangle and the next 3 vertices for the next triangle. You can also use triangle strips, there the next vertex will be connected this the last two vertices... &#xD;&#xA;&#xD;&#xA;Now let's go back to the shaders. &#xD;&#xA;The simplest setup is to use a vertex shader in combination with a fragment shader. The vertex shader code will be executed for each vertex. And is usually used to rotate/scale/translate the vertex position and add a projection. Additionally you can calculate everything else which is vertex based. You can pass data from vertex shader to fragment shader as well... But between vertex stage and fragment stage there is the &quot;Rasterizer&quot;. Each primitive will be clipped and culled with respect to the normalized device coordinates. The resulting primitives can hit pixels on your viewport. Then each hit Pixel calls the fragment shader. The data which will be passed from vertex to fragment shader will be interpolated... &#xD;&#xA;&#xD;&#xA;This is a very basic and absolutely not complete description, of how OpenGL works with your data. A lot of things are missing here, like depthbuffer, frameBufferObjects, rasterizer settings, blendings, textures, vertexArray and a lot more! But this would be way too much. &#xD;&#xA;&#xD;&#xA;After learning the very basics (draw a triangle) you can take a deeper look at other shader stages (Tessellation control, Tessellation evaluation, geometry) and for general purpos calculations you can use compute shader.&#xD;&#xA;&#xD;&#xA;You asked for brushes... In general I would say no, but when drawing lines, you can define the line width. &#xD;&#xA;But brushes must be implemented using shaders on your own&#xD;&#xA;&#xD;&#xA;Raster images can be stored to text files. You can move images from GPU to CPU and back. Afterwards you can write code to store it to files. For example as BMP. &#xD;&#xA;&#xD;&#xA;BTW: in case of choosing Opengl, I would recommend buying the book &quot;opengl super Bible&quot;. It is for beginners and has a math chapter which is very helpful. At the end they also show how different techniques like normal mapping can be implemented. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38847" PostHistoryTypeId="5" PostId="13071" RevisionGUID="dc81787b-a2ff-4ed1-8e16-7d73808e3f87" CreationDate="2022-10-28T22:32:04.023" UserId="19116" Comment="added 193 characters in body" Text="Trying to understand how OpenGL generates what is seen as images &amp; graphics and these questions come up. &#xD;&#xA;&#xD;&#xA;1. Are 3D lines (which should be drawn using vectors) drawn using triangles or polygons? Or are they drawn using vector values? &#xD;&#xA;&#xD;&#xA;2. Are the triangles drawn using vectors or smaller triangles? &#xD;&#xA;&#xD;&#xA;3. Can raster pixel data be isolated horizontally and or vertically? &#xD;&#xA;&#xD;&#xA;4. Can raster pixel data be exported into text files? &#xD;&#xA;&#xD;&#xA;5. Can lines be drawn using custom raster brush/draw tool? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I haven't tried anything yet as there really isn't anything to try. These are questions out of curiosity of knowing how 3D lines, shapes &amp; objects are drawn in OpenGL. &#xD;&#xA;&#xD;&#xA;Hopefully the answers provided will help me decide on the framework, libraries and tools to adopt within project. I would appreciate helpful answers or guides to articles that shed some light into these questions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Questions asked are applicable to 2D canvas and 3D space.**&#xD;&#xA;&#xD;&#xA;P.S - I am absolutely new to Graphics Development &amp; Programming... Be nice, Thanks&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;**PLEASE NOTE:** Each question can easily be answered using basic straightforward approach of **Yes/No** followed by a brief explanation stating reason for answer being **Yes** or **No**&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38848" PostHistoryTypeId="5" PostId="13071" RevisionGUID="4c5eebca-907d-46ab-bb36-2ac3995331c4" CreationDate="2022-10-28T22:35:00.227" UserId="2654" Comment="deleted 16 characters in body" Text="Trying to understand how OpenGL generates what is seen as images &amp; graphics and these questions come up. &#xD;&#xA;&#xD;&#xA;1. Are 3D lines (which should be drawn using vectors) drawn using triangles or polygons? Or are they drawn using vector values? &#xD;&#xA;&#xD;&#xA;2. Are the triangles drawn using vectors or smaller triangles? &#xD;&#xA;&#xD;&#xA;3. Can raster pixel data be isolated horizontally and or vertically? &#xD;&#xA;&#xD;&#xA;4. Can raster pixel data be exported into text files? &#xD;&#xA;&#xD;&#xA;5. Can lines be drawn using custom raster brush/draw tool? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I haven't tried anything yet as there really isn't anything to try. These are questions out of curiosity of knowing how 3D lines, shapes &amp; objects are drawn in OpenGL. &#xD;&#xA;&#xD;&#xA;Hopefully the answers provided will help me decide on the framework, libraries and tools to adopt within project. I would appreciate helpful answers or guides to articles that shed some light into these questions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Questions asked are applicable to 2D canvas and 3D space.**&#xD;&#xA;&#xD;&#xA;P.S - I am absolutely new to Graphics Development &amp; Programming... Be nice, Thanks&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;PLEASE NOTE: Each question can easily be answered using basic straightforward approach of Yes/No followed by a brief explanation stating reason for answer being Yes or No&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38850" PostHistoryTypeId="50" PostId="9926" RevisionGUID="ce511a39-95dd-4f1a-9308-21392c18f72c" CreationDate="2022-10-29T01:08:11.063" UserId="-1" />
  <row Id="38851" PostHistoryTypeId="2" PostId="13073" RevisionGUID="3aeb7b60-6d6a-4544-ae60-7a2f1acab4a9" CreationDate="2022-10-29T18:48:11.580" UserId="7952" Text="In GLSL use frac to get the fractional part:&#xD;&#xA;&#xD;&#xA;       float x=1.02;&#xD;&#xA;       x = frac(x);  // x==0.02 (in C++ use the modf function)&#xD;&#xA;&#xD;&#xA;Multiply the fractional part by the max of the accuracy you want:&#xD;&#xA;&#xD;&#xA;      float accuracy=255;  // 8 bits of accuracy (65535 for 16 bits)&#xD;&#xA;      x*=255;  // x==5.12&#xD;&#xA;&#xD;&#xA;Throw away the fractional part:&#xD;&#xA;&#xD;&#xA;      int y = (int)x;  // y == 5;&#xD;&#xA;&#xD;&#xA;The value is ready to be stored in whatever 8 bit format is need. Such as a texture, or vertex attributes, etc.&#xD;&#xA;&#xD;&#xA;To recover the fraction:&#xD;&#xA;&#xD;&#xA;    float x= (float)value / 255.0;  // 5.0/255.0 == 0.01953125&#xD;&#xA;&#xD;&#xA;This gives unsigned values between 0 and 1. A similar approach can be used for values between -1 and 1.&#xD;&#xA;&#xD;&#xA;Precision is lost to the 8 bit encoding. But like mentioned in the comments that same can be done with 16 bit numbers.&#xD;&#xA;&#xD;&#xA;If the values need to be stored in a texture then there are image formats just for this such as UNORM and SNORM. The GPU does the math for these formats when they are read from the texture.&#xD;&#xA;&#xD;&#xA;The specs for the different API's provide guidelines on the expected values. The [vulkan spec][1] has something close to a function and a good explanation of the conversions it expects.&#xD;&#xA;      &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/vulkan/specs/1.0/html/vkspec.html#fundamentals-fixedconv" ContentLicense="CC BY-SA 4.0" />
  <row Id="38853" PostHistoryTypeId="2" PostId="13074" RevisionGUID="9b95a593-c30c-4ad4-8e73-c266fa8ac241" CreationDate="2022-10-29T19:05:27.367" UserId="19136" Text="By the plasma effect I mean an animation that looks like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have seen some codes, like these&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/Xst3zN&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/4tdGWX&#xD;&#xA;&#xD;&#xA;and messed with the code to try to grasp it, but I'm not understanding what is going on, for example, if there's a main math concept behind it that makes the effect possible, or a shader technique that I don't know about.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r8Hfg.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="38855" PostHistoryTypeId="1" PostId="13074" RevisionGUID="9b95a593-c30c-4ad4-8e73-c266fa8ac241" CreationDate="2022-10-29T19:05:27.367" UserId="19136" Text="What are the main concepts behind building the plasma effect with GSLS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38856" PostHistoryTypeId="3" PostId="13074" RevisionGUID="9b95a593-c30c-4ad4-8e73-c266fa8ac241" CreationDate="2022-10-29T19:05:27.367" UserId="19136" Text="|shader|glsl|color|fragment-shader|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38857" PostHistoryTypeId="5" PostId="13073" RevisionGUID="98a9e36f-c7c7-4377-92cf-d25a55623c10" CreationDate="2022-10-29T21:00:34.863" UserId="7952" Comment="added 1 character in body" Text="In GLSL use frac to get the fractional part:&#xD;&#xA;&#xD;&#xA;       float x=1.02;&#xD;&#xA;       x = frac(x);  // x==0.02 (in C++ use the modf function)&#xD;&#xA;&#xD;&#xA;Multiply the fractional part by the max of the accuracy you want:&#xD;&#xA;&#xD;&#xA;      float accuracy=255;  // 8 bits of accuracy (65535 for 16 bits)&#xD;&#xA;      x*=255;  // x==5.12&#xD;&#xA;&#xD;&#xA;Throw away the fractional part:&#xD;&#xA;&#xD;&#xA;      int y = round(x);  // y == 5;&#xD;&#xA;&#xD;&#xA;The value is ready to be stored in whatever 8 bit format is need. Such as a texture, or vertex attributes, etc.&#xD;&#xA;&#xD;&#xA;To recover the fraction:&#xD;&#xA;&#xD;&#xA;    float x = (float)value / 255.0;  // 5.0/255.0 == 0.01953125&#xD;&#xA;&#xD;&#xA;This gives unsigned values between 0 and 1. A similar approach can be used for values between -1 and 1.&#xD;&#xA;&#xD;&#xA;Precision is lost to the 8 bit encoding. But like mentioned in the comments that same can be done with 16 bit numbers.&#xD;&#xA;&#xD;&#xA;If the values need to be stored in a texture then there are image formats just for this such as UNORM and SNORM. The GPU does the math for these formats when they are read from the texture.&#xD;&#xA;&#xD;&#xA;The specs for the different API's provide guidelines on the expected values. The [vulkan spec][1] has something close to a function and a good explanation of the conversions it expects.&#xD;&#xA;      &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/vulkan/specs/1.0/html/vkspec.html#fundamentals-fixedconv" ContentLicense="CC BY-SA 4.0" />
  <row Id="38858" PostHistoryTypeId="10" PostId="13071" RevisionGUID="fc0d6d1f-edf3-46a3-ac57-68142bfd0118" CreationDate="2022-10-30T04:46:05.263" UserId="482" Comment="104" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:7952,&quot;DisplayName&quot;:&quot;pmw1234&quot;},{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}]}" />
  <row Id="38859" PostHistoryTypeId="2" PostId="13075" RevisionGUID="85d626ae-7d4c-4a37-bb3d-b01cd87f02cc" CreationDate="2022-10-30T07:31:23.653" UserId="9157" Text="So let's say I want to draw *a lot* of textured quads to the framebuffer.&#xD;&#xA;&#xD;&#xA;In each shader invocation, I will bind an array of indicies, an array of positions, and an array of textures to index into.  Then I will draw instanced.&#xD;&#xA;&#xD;&#xA;Is there any rule of thumb for how many instances I can or should draw in a single call?  For instance, should I draw tens or hundreds or thousands of instances at once, keeping in mind the number of instances will also determine the size of the arrays bound to my shader." ContentLicense="CC BY-SA 4.0" />
  <row Id="38861" PostHistoryTypeId="1" PostId="13075" RevisionGUID="85d626ae-7d4c-4a37-bb3d-b01cd87f02cc" CreationDate="2022-10-30T07:31:23.653" UserId="9157" Text="Is there a good rule of thumb for the optimal / maximum number of instances to draw in a single call?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38862" PostHistoryTypeId="3" PostId="13075" RevisionGUID="85d626ae-7d4c-4a37-bb3d-b01cd87f02cc" CreationDate="2022-10-30T07:31:23.653" UserId="9157" Text="|shader|glsl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38863" PostHistoryTypeId="2" PostId="13076" RevisionGUID="df92258b-6199-4641-a3fb-6cef132f62f6" CreationDate="2022-10-30T15:35:02.913" UserId="2654" Text="The rule of thumb is not about the number of instances; it's about the size of each instance.&#xD;&#xA;&#xD;&#xA;You don't want instances that are too small. You want instances that have a good number of vertices to them. In the hundreds to low thousands range. Quads only have 4 vertices, so they are a particularly bad choice for instancing.&#xD;&#xA;&#xD;&#xA;The benefit of instancing quads is having less vertex data to read and upload. However, there are ways of achieving these benefits without actually having to use instancing.&#xD;&#xA;&#xD;&#xA;Using indexed rendering means that you can use 4 positions instead of six. However, you also need an index buffer. Fortunately, you can [use the same index buffer for each draw call][1], as the *topology* of a list of quads is the same regardless of their vertices. This buffer can use 16-bits indices for improved performance, and you can use multidraw rendering alongside the base vertex to render more than 16K quads from a single draw call.&#xD;&#xA;&#xD;&#xA;For the other per-quad attributes, you can access an SSBO (or UBO if you don't have that much per-quad data) given each quad's index. To compute a quad's index, you need to use `gl_VertexIndex`, which gives you the index of the vertex + its base vertex offset. `gl_VertexIndex / 4` is the index of that quad, which you can then use to fetch data from your SSBO.&#xD;&#xA;&#xD;&#xA;Technically, you could do this for the positions too. You would use no vertex buffers at all; using an index buffer as above to compute the quad index. And you would compute the positions of each vertex in the quad using `gl_VertexIndex % 4` to figure out which vertex that VS invocation needs to compute.&#xD;&#xA;&#xD;&#xA;However, it is very difficult to ensure continuity if two quads share a common edge. [But if you're rendering a particle system, continuity is not all that important, so this is also an option][2]. If continuity is important, you should just use 4 positions per-quad and use per-quad indices from SSBOs for the rest.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/a/59707766/734069&#xD;&#xA;  [2]: https://community.khronos.org/t/a-review-of-a-sprite-drawing-strategy/108534/11" ContentLicense="CC BY-SA 4.0" />
  <row Id="38865" PostHistoryTypeId="5" PostId="13076" RevisionGUID="24ed75b8-6ca0-4f72-8923-b28aba360f14" CreationDate="2022-10-30T15:44:58.180" UserId="2654" Comment="added 123 characters in body" Text="The rule of thumb is not about the number of instances; it's about the size of each instance.&#xD;&#xA;&#xD;&#xA;[You don't want instances that are too small][1]. You want instances that have a good number of vertices to them. In the hundreds to low thousands range. Quads only have 4 vertices, so they are a particularly bad choice for instancing.&#xD;&#xA;&#xD;&#xA;The benefit of instancing quads is having less vertex data to read and upload. However, there are ways of achieving these benefits without actually having to use instancing.&#xD;&#xA;&#xD;&#xA;Using indexed rendering means that you can use 4 positions instead of six. However, you also need an index buffer. Fortunately, you can [use the same index buffer for each draw call][2], as the *topology* of a list of quads is the same regardless of their vertices. This buffer can use 16-bits indices for improved performance, and you can use multidraw rendering alongside the base vertex to render more than 16K quads from a single draw call.&#xD;&#xA;&#xD;&#xA;For the other per-quad attributes, you can access an SSBO (or UBO if you don't have that much per-quad data) given each quad's index. To compute a quad's index, you need to use `gl_VertexIndex`, which gives you the index of the vertex + its base vertex offset. `gl_VertexIndex / 4` is the index of that quad, which you can then use to fetch data from your SSBO.&#xD;&#xA;&#xD;&#xA;Technically, you could do this for the positions too. You would use no vertex buffers at all; using an index buffer as above to compute the quad index. And you would compute the positions of each vertex in the quad using `gl_VertexIndex % 4` to figure out which vertex that VS invocation needs to compute.&#xD;&#xA;&#xD;&#xA;However, it is very difficult to ensure continuity if two quads share a common edge. [But if you're rendering a particle system, continuity is not all that important, so this is also an option][3]. If continuity is important, you should just use 4 positions per-quad and use per-quad indices from SSBOs for the rest.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.khronos.org/t/gpu-vertex-dispatch-for-multidrawindirect-and-or-instanced-draw-calls/77308/2&#xD;&#xA;  [2]: https://stackoverflow.com/a/59707766/734069&#xD;&#xA;  [3]: https://community.khronos.org/t/a-review-of-a-sprite-drawing-strategy/108534/11" ContentLicense="CC BY-SA 4.0" />
  <row Id="38866" PostHistoryTypeId="5" PostId="13076" RevisionGUID="b5114ae3-24f7-43e2-b0c8-16f01c4191a1" CreationDate="2022-10-30T15:53:41.410" UserId="2654" Comment="added 79 characters in body" Text="The rule of thumb is not about the number of instances; it's about the size of each instance.&#xD;&#xA;&#xD;&#xA;[You don't want instances that are too small][1]. You want instances that have a good number of vertices to them. In the hundreds to low thousands range. Quads only have 4 vertices, so they are a particularly bad choice for instancing.&#xD;&#xA;&#xD;&#xA;The benefit of instancing quads is having less vertex data to read and upload. However, there are ways of achieving these benefits without actually having to use instancing.&#xD;&#xA;&#xD;&#xA;Using indexed rendering means that you can use 4 positions instead of six. However, you also need an index buffer. Fortunately, you can [use the same index buffer for each draw call][2], as the *topology* of a list of quads is the same regardless of their vertices. This buffer can use 16-bits indices for improved performance, and you can use multidraw rendering alongside the base vertex to render more than 16K quads from a single draw call.&#xD;&#xA;&#xD;&#xA;For the other per-quad attributes, you can access an SSBO (or UBO if you don't have that much per-quad data) given each quad's index. To compute a quad's index, you need to use `gl_VertexIndex`, which gives you the index of the vertex + its base vertex offset. `gl_VertexIndex / 4` is the index of that quad, which you can then use to fetch data from your SSBO.&#xD;&#xA;&#xD;&#xA;Technically, you could do this for the positions too. You would use no vertex buffers at all; using an index buffer as above to compute the quad index. And you would compute the positions of each vertex in the quad using `gl_VertexIndex % 4` to figure out which vertex that VS invocation needs to compute.&#xD;&#xA;&#xD;&#xA;However, it is difficult to ensure continuity if two quads share a common edge (this can be done via using fixed-point integer math in the scaling and offsetting). [But if you're rendering a particle system, continuity is not all that important, so this is also an option][3]. If continuity is important, you should just use 4 positions per-quad and use per-quad indices from SSBOs for the rest.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.khronos.org/t/gpu-vertex-dispatch-for-multidrawindirect-and-or-instanced-draw-calls/77308/2&#xD;&#xA;  [2]: https://stackoverflow.com/a/59707766/734069&#xD;&#xA;  [3]: https://community.khronos.org/t/a-review-of-a-sprite-drawing-strategy/108534/11" ContentLicense="CC BY-SA 4.0" />
  <row Id="38867" PostHistoryTypeId="50" PostId="12503" RevisionGUID="7d73594b-267b-4bba-9eb6-fca38d2c1a56" CreationDate="2022-10-30T22:03:35.520" UserId="-1" />
  <row Id="38873" PostHistoryTypeId="2" PostId="13078" RevisionGUID="d86de89a-8160-466f-accc-8032846d1498" CreationDate="2022-11-01T15:02:00.927" UserId="19147" Text="You need to add clipping. &#xD;&#xA;&#xD;&#xA;When a vertex goes behind the near plane in camera space, it still gets projected to the screen which leads to these issues. You need to find where the edges of your triangle intersect with the near plane and edit the triangle in order to make all the vertices in front of the near plane. &#xD;&#xA;&#xD;&#xA;[This][1] is a good resource for more information.&#xD;&#xA;&#xD;&#xA;Get the line-plane intersect algorithm from [here][2]. Here's some untested psudocode to get you started&#xD;&#xA;```&#xD;&#xA;for (worldTri of Scene)&#xD;&#xA;   camTri = worldTri.toCamSpace()&#xD;&#xA;&#xD;&#xA;   clipped = []&#xD;&#xA;&#xD;&#xA;   for (vertex of camTri)&#xD;&#xA;      clipped.push(vertex.z &gt; near)&#xD;&#xA;&#xD;&#xA;   numClipped = clipped.filter(a =&gt; a).length // get number of clipped vertices&#xD;&#xA;   clippedTris   &#xD;&#xA;&#xD;&#xA;   if (numClipped === 3) clippedTris = [camTri]&#xD;&#xA;   if (numClipped === 2)&#xD;&#xA;      clippedTris = [&#xD;&#xA;         new tri(&#xD;&#xA;            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[0], camTri[1]),&#xD;&#xA;            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[1], camTri[2]),&#xD;&#xA;            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[2], camTri[0])&#xD;&#xA;         ),&#xD;&#xA;         new tri(&#xD;&#xA;            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[0], camTri[2]),&#xD;&#xA;            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[1], camTri[0]),&#xD;&#xA;            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[2], camTri[1])&#xD;&#xA;         )&#xD;&#xA;      ]&#xD;&#xA;   if (numClipped === 1)&#xD;&#xA;      clippedTris = [&#xD;&#xA;         new tri(&#xD;&#xA;            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[1], camTri[2]),&#xD;&#xA;            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[0], camTri[2]),&#xD;&#xA;            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[0], camTri[1]),&#xD;&#xA;         )&#xD;&#xA;      ]&#xD;&#xA;   if (numClipped === 0) clippedTris = []&#xD;&#xA;&#xD;&#xA;   for (clipTri of clippedTris)&#xD;&#xA;      clipTri.doTheRestOfYourRasterizationAsIfThisWasAlreadyTransformedIntoCamSpace()&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gabrielgambetta.com/computer-graphics-from-scratch/11-clipping.html&#xD;&#xA;  [2]: https://stackoverflow.com/questions/5666222/3d-line-plane-intersection" ContentLicense="CC BY-SA 4.0" />
  <row Id="38879" PostHistoryTypeId="2" PostId="13080" RevisionGUID="68c7371e-f8f3-45f6-a9a6-df44dea498f3" CreationDate="2022-11-02T10:45:23.340" UserId="13273" Text="I've read, that OpenCL kernels are grouped like OpenGL compute shaders. That means, that you can define how many invocations should be executed within a workgroup. These invocations which are in the same workgroup, can communicate with so called `shared` variables.&#xD;&#xA;&#xD;&#xA;In OpenCL there is the CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE also called warp size. Which is 32 for my GPU. That means, when allocating less than 32 invocations per workgroup (OpenCL), your GPU is not fully used. As far as I understood, it has to do with hardware specifications. Where 32 cores on my GPU are grouped together as a warp and also executed together. When allocating less than 32 invocations, the rest of the cores within that hardware group are not used or idle.&#xD;&#xA;&#xD;&#xA;Do I have the same restrictions on OpenGL compute shaders? My GPU has 3072 shader units, when executing a post processing algorithm on OpenGL compute shader, does it make sense to allocate the workgroup size to be a multiple of 32? Even, when no interaction between neighboring pixels exists?&#xD;&#xA;&#xD;&#xA;For example we have a 1024 x 1024 rgb32f image, and we only want to apply some calculation to it ... we could define workgroup size to be x,y,z = 1. and execute 1024 x 1024 x 1 workgroups. Or, we can define workgroup size to be x = 32 and y,z = 1 and execute 32 x 1024 x 1 workgroups.&#xD;&#xA;&#xD;&#xA;maybe your answer is: Yes of cause, it is hardware specified... but I also think about the shader compiler... maybe it is trying to perfectly spread the work to the cores." ContentLicense="CC BY-SA 4.0" />
  <row Id="38881" PostHistoryTypeId="1" PostId="13080" RevisionGUID="68c7371e-f8f3-45f6-a9a6-df44dea498f3" CreationDate="2022-11-02T10:45:23.340" UserId="13273" Text="OpenCL WorkGroupSize compared to OpenGL compute shader WorkGroupSize" ContentLicense="CC BY-SA 4.0" />
  <row Id="38882" PostHistoryTypeId="3" PostId="13080" RevisionGUID="68c7371e-f8f3-45f6-a9a6-df44dea498f3" CreationDate="2022-11-02T10:45:23.340" UserId="13273" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38883" PostHistoryTypeId="2" PostId="13081" RevisionGUID="04dac72f-9660-4a98-a930-78e3cc6da1f4" CreationDate="2022-11-02T14:26:22.100" UserId="2654" Text="The hardware is the same either way, and the execution models are the same. It's the underlying execution model and hardware that creates this effect. So they will be the same for OpenGL compute shaders and OpenCL." ContentLicense="CC BY-SA 4.0" />
  <row Id="38885" PostHistoryTypeId="2" PostId="13082" RevisionGUID="c1a8420e-d44f-4484-8edd-5c147286869d" CreationDate="2022-11-02T17:50:28.920" UserId="16728" Text="It appears that reads to indices outside the range of a ComputeBuffer always return 0, and writes to out-of-range indices do not cause any exceptions or runtime errors. Is there built-in range-checking when reading and writing to a ComputeBuffer in hlsl that prevents buffer overflows?&#xD;&#xA;&#xD;&#xA;With a simple Compute Shader:&#xD;&#xA;```&#xD;&#xA;#pragma kernel CSMain&#xD;&#xA;&#xD;&#xA;RWStructuredBuffer&lt;int&gt; buf1;&#xD;&#xA;RWStructuredBuffer&lt;int&gt; buf2;&#xD;&#xA;RWStructuredBuffer&lt;int&gt; buf3;&#xD;&#xA;&#xD;&#xA;[numthreads(64,1,1)]&#xD;&#xA;void CSMain (uint3 id : SV_DispatchThreadID)&#xD;&#xA;{&#xD;&#xA;    buf1[id.x] = buf3[id.x];&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;CSharp side code:&#xD;&#xA;```&#xD;&#xA;    void TestForBufferOverruns()&#xD;&#xA;    {&#xD;&#xA;        int bufferSize = 1024;&#xD;&#xA;        buf1 = new ComputeBuffer(bufferSize, sizeof(int));&#xD;&#xA;        buf2 = new ComputeBuffer(bufferSize, sizeof(int));&#xD;&#xA;        buf3 = new ComputeBuffer(bufferSize, sizeof(int));&#xD;&#xA;&#xD;&#xA;        // Init buffers to some arbitrary values&#xD;&#xA;        int[] initData = new int[bufferSize];&#xD;&#xA;        for(int i = 0; i &lt; initData.Length; i++)&#xD;&#xA;        {&#xD;&#xA;            initData[i] = 3;&#xD;&#xA;        }&#xD;&#xA;        buf1.SetData(initData);&#xD;&#xA;&#xD;&#xA;        for(int i = 0; i &lt; initData.Length; i++)&#xD;&#xA;        {&#xD;&#xA;            initData[i] = 7;&#xD;&#xA;        }&#xD;&#xA;        buf2.SetData(initData);&#xD;&#xA;&#xD;&#xA;        for(int i = 0; i &lt; initData.Length; i++)&#xD;&#xA;        {&#xD;&#xA;            initData[i] = 8;&#xD;&#xA;        }&#xD;&#xA;        buf3.SetData(initData);&#xD;&#xA;&#xD;&#xA;        bufferOverrunShader.SetBuffer(0, &quot;buf1&quot;, buf1);&#xD;&#xA;        bufferOverrunShader.SetBuffer(0, &quot;buf2&quot;, buf2);&#xD;&#xA;        bufferOverrunShader.SetBuffer(0, &quot;buf3&quot;, buf3);&#xD;&#xA;&#xD;&#xA;        // Max numThreadGroups should be 16.&#xD;&#xA;        // bufferSize/threadGroupSize = 1024/64 = 64.&#xD;&#xA;        // Dispatching more than 16 threadGroups should&#xD;&#xA;        // case a buffer overrun, correct?&#xD;&#xA;        int numThreadGroups = 17; &#xD;&#xA;        bufferOverrunShader.Dispatch(0, numThreadGroups, 1, 1);&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;Doing a readback of the buffers from the GPU shows all buffers contain the initial expected data, with buf1 containing the values from buf3.&#xD;&#xA;&#xD;&#xA;My question is, why does this work without some sort of buffer overrun error?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38887" PostHistoryTypeId="1" PostId="13082" RevisionGUID="c1a8420e-d44f-4484-8edd-5c147286869d" CreationDate="2022-11-02T17:50:28.920" UserId="16728" Text="Does RWStructuredBuffer have built-in overflow protection in hlsl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38888" PostHistoryTypeId="3" PostId="13082" RevisionGUID="c1a8420e-d44f-4484-8edd-5c147286869d" CreationDate="2022-11-02T17:50:28.920" UserId="16728" Text="|compute-shader|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38889" PostHistoryTypeId="50" PostId="12746" RevisionGUID="0c4cc7dc-dcb0-4e14-9ae8-629d3b145aab" CreationDate="2022-11-02T18:03:55.513" UserId="-1" />
  <row Id="38890" PostHistoryTypeId="50" PostId="10537" RevisionGUID="071868a8-0cc2-432d-bddc-a1219fa2943b" CreationDate="2022-11-02T19:05:50.680" UserId="-1" />
  <row Id="38891" PostHistoryTypeId="2" PostId="13083" RevisionGUID="a0554d10-9063-4edf-b603-338b4d1f2fe2" CreationDate="2022-11-02T22:19:14.703" UserId="13565" Text="I'm trying to figure out a solution to a problem that looked simple at first: how to render overlapping windows in a 2D windowing system. Originally I was thinking about implementing a text-based UI system, something like [twin][1]; not to reinvent the wheel but to study the details.&#xD;&#xA;&#xD;&#xA;As the screen may contain several windows that can be freely moved around, they will fully or partially cover each other. I wanted to find an efficient way to do the rendering. It turned out not that trivial as it seemed at first. Surprisingly I've failed to find any useful information on the subject. &#xD;&#xA;&#xD;&#xA;Based on what I've found there are two common implementations: stacking and composing window managers (or compositors). Up to my best knowledge the latter provides an off-screen buffer for each window and renders the screen using the contents of these buffers. I've found even less about the stacking implementation: I guess it is using dirty regions and asks the owners of the windows to redraw their content.&#xD;&#xA;&#xD;&#xA;Using painter's algorithm for the compositions seems to be a rather brute force approach. I was considering if windows could use some kind of backbuffer to store the content they obscure and redraw the revealed parts when they move away - this sounds somewhat too complicated. I stared looking into segmentation and interval trees if they could be useful for identifying the obscured regions.&#xD;&#xA;&#xD;&#xA;Originally I wanted to find something for a text-based system, but now I'm interested in how it's implemented in a 'real' graphical system.&#xD;&#xA;&#xD;&#xA;I was surprised how little information can be found online on the topic; I was expecting this to be field well studied with a lot of (maybe somewhat old) articles. I was trying to search for axis-aligned bounding boxes, etc. with not much luck.&#xD;&#xA;&#xD;&#xA;Any articles, books, blog entries on the topic would be quite useful as well as any directions which algorithms or key words should I search for. I'd like to start with something more theoretical first rather than looking into the code of an existing system that might be already very complex with all the features implemented.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/cosmos72/twin" ContentLicense="CC BY-SA 4.0" />
  <row Id="38893" PostHistoryTypeId="1" PostId="13083" RevisionGUID="a0554d10-9063-4edf-b603-338b4d1f2fe2" CreationDate="2022-11-02T22:19:14.703" UserId="13565" Text="Algorithms for tendering overlapping (floating) windows in 2D" ContentLicense="CC BY-SA 4.0" />
  <row Id="38894" PostHistoryTypeId="3" PostId="13083" RevisionGUID="a0554d10-9063-4edf-b603-338b4d1f2fe2" CreationDate="2022-11-02T22:19:14.703" UserId="13565" Text="|algorithm|2d|2d-graphics|ui|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38899" PostHistoryTypeId="50" PostId="12498" RevisionGUID="d3aaab87-8d42-499f-9c7a-686f0444e831" CreationDate="2022-11-03T02:01:25.180" UserId="-1" />
  <row Id="38901" PostHistoryTypeId="2" PostId="13085" RevisionGUID="b2ea3281-23c3-4ca0-89a1-3e35fc1df129" CreationDate="2022-11-03T03:17:48.473" UserId="445" Text="I have some knowledge of what you call “stacking” (I don't know if there's a standard term), from having programmed with [classic Mac OS graphics (QuickDraw)](https://en.wikipedia.org/wiki/QuickDraw). To keep the explanation straightforward, I'm going to write as if that system is the one single way to do things.&#xD;&#xA;&#xD;&#xA;&gt;  I guess it is using dirty regions and asks the owners of the windows to redraw their content.&#xD;&#xA;&#xD;&#xA;Yes, dirty regions are critical, and there is a further refinement: the dirty region is also used as a _clipping_ region, built into the graphics system, such that drawing operations do not modify any pixels outside the region. This region is automatically set so that it contains _only_ the pixels that need to be redrawn _and are visible._&#xD;&#xA;&#xD;&#xA;Thus, when some window A is moved to uncover part of a window B, the program responsible for window B can draw as carefully or sloppily as it likes, but will not accidentally either overwrite window A, or paint over its own previous drawing, and all graphics primitives automatically skip invisible pixels. This was a very important performance optimization, back when processors were slower and there were no GPUs; it meant that the _only_ pixels that needed to be touched were the ones actually needed to show on the screen.&#xD;&#xA;&#xD;&#xA;Also, the foreground window A would be moved by copying its pixels within the video RAM (a.k.a. “blitting”), so that A does not need to be redrawn whenever it is moved. (While faster than redrawing, this copy was still slow enough to be visible on-screen — I remember noticing that depending on which direction I moved a window, the copy would either proceed top-to-bottom or bottom-to-top!)&#xD;&#xA;&#xD;&#xA;So, the window system made sure that _every pixel only needs to be drawn once._ An application might or might not be clever enough to figure out how to draw _its_ part of the screen without multiple operations touching the same pixel, but it _has the opportunity._ (The application was given, if I remember correctly, a list of dirty rectangles to draw.)&#xD;&#xA;&#xD;&#xA;Furthermore, since nothing is double-buffered and all drawing is immediately visible on-screen, minimizing overdraw also minimized the amount of flickering visible to the user.&#xD;&#xA;&#xD;&#xA;(However, classic Mac OS actually _did_ do one extra draw: it would always immediately fill the newly-visible areas with white, before invoking any applications' redraw routines. This is a noticeable difference from Windows, which would instead leave the old screen contents in place — thus resulting in visible copies of a dragged window, or other stale pixels, if the window underneath did not redraw promptly.)&#xD;&#xA;&#xD;&#xA;&gt; Using painter's algorithm for the compositions seems to be a rather brute force approach.&#xD;&#xA;&#xD;&#xA;Yes, it is. It is feasible today because GPUs are dedicated hardware optimized for copying pixels around. Even then, your window compositor probably has special cases like not drawing a window whose bounding rectangle lies completely behind another opaque window.&#xD;&#xA;&#xD;&#xA;(But for text-mode windows it is completely reasonable to do this with a CPU, since the amount of data, is so much smaller!)&#xD;&#xA;&#xD;&#xA;&gt; I was considering if windows could use some kind of backbuffer to store the content they obscure and redraw the revealed parts when they move away - this sounds somewhat too complicated.&#xD;&#xA;&#xD;&#xA;Yes, that will create complexity for not a lot of benefit. If you're going to store copies of window contents, you might as well do a full buffer for every window (with today's hardware), rather than partial storage that you have to reshape all the time. And what happens if an obscured window wants to update its contents? Does it have to draw half on the screen and half on the obscured-buffer?&#xD;&#xA;&#xD;&#xA;In the old days, we avoided keeping copies of window contents entirely, because&#xD;&#xA;&#xD;&#xA;* memory is precious, so you don't store extra copies of what's on screen, and&#xD;&#xA;* you would have had to run _three_ memory operations whenever the content changed (draw to back buffer, read back buffer, write graphics memory).&#xD;&#xA;&#xD;&#xA;The one place where having a copy of window contents stored makes sense is a paint program, where those pixels _are the document_ so you need a copy that is never affected by being obscured.&#xD;&#xA;&#xD;&#xA;&gt;  I stared looking into segmentation and interval trees if they could be useful for identifying the obscured regions.&#xD;&#xA;&#xD;&#xA;You might want to look at the QuickDraw “region” data structure, which was used for clipping. It is optimized for compactly representing irregular rectangular-ish shapes by storing a list of _only_ their corner points. I don't know if it was actually used for computing/remembering visibility, but there were definitely region union/intersection/subtraction operations that _could have_ been used for that.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38903" PostHistoryTypeId="5" PostId="10537" RevisionGUID="1cd20741-c320-4a8e-95a5-cd0b9878acb1" CreationDate="2022-11-03T10:28:43.640" UserId="16241" Comment="Convert image to mathjax" Text="I am reading Physically Based Rendering [section 2.2.2 on RGB color][1].&#xD;&#xA;&#xD;&#xA;I am trying to understand how, given a display spectral response curves for rgb intensities, we can choose the intensities so that the display will emit an equivalent spectrum (a CIE xyz metamer) &#xD;&#xA;&#xD;&#xA;It is my understanding that the following section tries to explain exactly that.&#xD;&#xA;&#xD;&#xA;&gt; Given an *(x,y,z)* representation of an SPD, we can convert it to corresponding&#xD;&#xA;&gt; RGB coefficients, given the choice of a particular set of SPDs that&#xD;&#xA;&gt; define red, green, and blue for a display of interest. Given the&#xD;&#xA;&gt; spectral response curves *R(lambda)*, *G(lambda)*, and *B(lambda)*, for a particular display, RGB&#xD;&#xA;&gt; coefficients can be computed by integrating the response curves with&#xD;&#xA;&gt; the SPD *S(lambda)* and using the tristimulus theory of color perception:&#xD;&#xA;&#xD;&#xA;$$r = \int R(\lambda) S(\lambda) d\lambda$$&#xD;&#xA;&#xD;&#xA;I can't understand this formula. Why it is considered correct? Why choosing *r* this way makes the display emit the correct / equivalent SPD?&#xD;&#xA;&#xD;&#xA;Can someone break it down for me? &#xD;&#xA;&#xD;&#xA;  [1]: http://www.pbr-book.org/3ed-2018/Color_and_Radiometry/The_SampledSpectrum_Class.html#RGBColor&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="38904" PostHistoryTypeId="24" PostId="10537" RevisionGUID="1cd20741-c320-4a8e-95a5-cd0b9878acb1" CreationDate="2022-11-03T10:28:43.640" Comment="Proposed by 16241 approved by 9154 edit id of 602" ContentLicense="CC BY-SA 4.0" />
  <row Id="38905" PostHistoryTypeId="2" PostId="13086" RevisionGUID="429bd3c1-a92a-4d9f-a136-a6f6893fe80e" CreationDate="2022-11-03T15:57:43.133" UserId="19161" Text="&#xD;&#xA;I currently have an application that uses openGL in order to render a 3d model of a car. &#xD;&#xA;I would like to change the car models but I have no clue what format my application uses. &#xD;&#xA;The current format of the working 3d model is directory that holds one xml file, 3 .tga files, and arround 40 .dat files.&#xD;&#xA;I am a backend software developper and I have never done any 3d modeling. &#xD;&#xA;I would be very gratefull if anyone could enlight me on what format this is and how I could export a blender format into this format.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="38907" PostHistoryTypeId="1" PostId="13086" RevisionGUID="429bd3c1-a92a-4d9f-a136-a6f6893fe80e" CreationDate="2022-11-03T15:57:43.133" UserId="19161" Text="Identifying an openGL 3d model" ContentLicense="CC BY-SA 4.0" />
  <row Id="38908" PostHistoryTypeId="3" PostId="13086" RevisionGUID="429bd3c1-a92a-4d9f-a136-a6f6893fe80e" CreationDate="2022-11-03T15:57:43.133" UserId="19161" Text="|opengl|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38909" PostHistoryTypeId="2" PostId="13087" RevisionGUID="90109680-53bb-48b5-a21e-9f0aedafd656" CreationDate="2022-11-04T09:39:02.890" UserId="19163" Text="I'm trying to create a galaxy simulation using opengl with the compute shader and when I start my simulation, the galaxy with the spiral arms doesn't form, instead it goes into chaos. I noticed that the particles in the center are not spinning fast enough&#xD;&#xA;Does anyone had this problem before ?&#xD;&#xA;&#xD;&#xA;I tried to:&#xD;&#xA;- change mass and smooth value&#xD;&#xA;- using verlet integration&#xD;&#xA;- change velocity initial value&#xD;&#xA;- change the number of particles&#xD;&#xA;&#xD;&#xA;here is the code:&#xD;&#xA;```&#xD;&#xA;#version 430 core&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;struct Particle&#xD;&#xA;{&#xD;&#xA;    vec4 position;&#xD;&#xA;    vec4 velocity;&#xD;&#xA;	vec4 acceleration;&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;layout (std430, binding = 0) buffer ParticleBuffer {&#xD;&#xA;	Particle p[];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;uniform float dt;&#xD;&#xA;uniform float accuracy;&#xD;&#xA;&#xD;&#xA;  const float mass = 1e-5;&#xD;&#xA;  const float csmooth = 1e-6;&#xD;&#xA;&#xD;&#xA;vec3 compute_force(vec3 posi){&#xD;&#xA;	vec3 f = vec3(0);&#xD;&#xA;	for(int i = 0; i&lt;accuracy*p.length(); i++){&#xD;&#xA;		if(posi != p[i].position.xyz){&#xD;&#xA;			vec3 v = p[i].position.xyz - posi;&#xD;&#xA;			float d = length(v);&#xD;&#xA;			f+= mass*v/(pow(d,3)+csmooth);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;	return f;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;	uint index = gl_GlobalInvocationID.x;&#xD;&#xA;&#xD;&#xA;	vec3 pos = p[index].position.xyz;&#xD;&#xA;	vec3 vel = p[index].velocity.xyz;&#xD;&#xA;	vec3 accel = p[index].acceleration.xyz;&#xD;&#xA;&#xD;&#xA;	vec3 newPos = pos+vel*dt + accel*(dt*dt*0.5);&#xD;&#xA;	vec3 newAccel = compute_force(pos);&#xD;&#xA;	vec3 newVel = vel + (accel+newAccel) *(dt*0.5);&#xD;&#xA;&#xD;&#xA;	p[index].position.xyz = newPos;&#xD;&#xA;	p[index].velocity.xyz = newVel;&#xD;&#xA;	p[index].acceleration.xyz = newAccel;&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="38911" PostHistoryTypeId="1" PostId="13087" RevisionGUID="90109680-53bb-48b5-a21e-9f0aedafd656" CreationDate="2022-11-04T09:39:02.890" UserId="19163" Text="My n-body simulation doesn't form a galaxy" ContentLicense="CC BY-SA 4.0" />
  <row Id="38912" PostHistoryTypeId="3" PostId="13087" RevisionGUID="90109680-53bb-48b5-a21e-9f0aedafd656" CreationDate="2022-11-04T09:39:02.890" UserId="19163" Text="|glsl|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38913" PostHistoryTypeId="50" PostId="10879" RevisionGUID="9162a3e6-f4e7-4cd1-8584-4fd238a5a32b" CreationDate="2022-11-04T11:07:00.857" UserId="-1" />
  <row Id="38914" PostHistoryTypeId="4" PostId="13083" RevisionGUID="ad2e530c-b962-4ed4-8e1f-f1420c7ffa89" CreationDate="2022-11-04T15:38:17.867" UserId="13565" Comment="edited title" Text="Algorithms for rendering overlapping (floating) windows in 2D" ContentLicense="CC BY-SA 4.0" />
  <row Id="38915" PostHistoryTypeId="50" PostId="10154" RevisionGUID="23fd6cbd-1148-44f7-91eb-f46f14acbbfd" CreationDate="2022-11-05T12:00:40.110" UserId="-1" />
  <row Id="38916" PostHistoryTypeId="2" PostId="13088" RevisionGUID="557496a3-3d84-481e-843e-111c7747099a" CreationDate="2022-11-05T16:50:55.053" UserId="19148" Text="The Guy's answer is correct but incomplete, that how you create *SURFACE* normals not *VERTEX* normals. to Create vertex normals see this post see the cyfex's answer. should be the second one." ContentLicense="CC BY-SA 4.0" />
  <row Id="38918" PostHistoryTypeId="5" PostId="13088" RevisionGUID="821cd348-5952-48e5-ace2-3c0a27748b56" CreationDate="2022-11-05T16:51:54.890" UserId="19148" Comment="added 131 characters in body" Text="The Guy's answer is correct but incomplete, that how you create *SURFACE* normals not *VERTEX* normals. to Create vertex normals see this post see the cyfex's answer. should be the second one.&#xD;&#xA;https://gamedev.stackexchange.com/questions/133864/calculating-vertex-normals-in-opengl-c?newreg=310c1117667f4ec99cd28866d3a49149" ContentLicense="CC BY-SA 4.0" />
  <row Id="38919" PostHistoryTypeId="5" PostId="13088" RevisionGUID="368c4f3c-203e-408d-bb65-489d5be2bf2d" CreationDate="2022-11-05T16:52:16.383" UserId="19148" Comment="added 2 characters in body" Text="The Guy's answer is correct but incomplete, that's how you create *SURFACE* normals not *VERTEX* normals. to Create vertex normals see this post see the cyfex's answer. should be the second one.&#xD;&#xA;https://gamedev.stackexchange.com/questions/133864/calculating-vertex-normals-in-opengl-c?newreg=310c1117667f4ec99cd28866d3a49149" ContentLicense="CC BY-SA 4.0" />
  <row Id="38920" PostHistoryTypeId="2" PostId="13089" RevisionGUID="85a53540-7099-4f53-aaa9-3f66c30911d5" CreationDate="2022-11-05T23:39:29.130" UserId="10547" Text="I use uber-shader approach and am having issues fitting within 16 texture units.&#xD;&#xA;&#xD;&#xA;My material uses 3 textures: albedo, special, and normal map.&#xD;&#xA;However, any of these textures can be regular 2D, or 2D array (eg. for animations), or Cube maps (eg. for skyboxes). Therefore, I have 9 samplers in my shader, even if I only use 3 of them.&#xD;&#xA;&#xD;&#xA;Similar issue applies to shadow maps.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_ALBEDO) uniform sampler2D texMaterialAlbedo2d;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_ALBEDO_ARRAY) uniform sampler2DArray texMaterialAlbedoArray;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_ALBEDO_CUBE) uniform samplerCube texMaterialAlbedoCube;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_SPECIAL) uniform sampler2D texMaterialSpecial2d;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_SPECIAL_ARRAY) uniform sampler2DArray texMaterialSpecialArray;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_SPECIAL_CUBE) uniform samplerCube texMaterialSpecialCube;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_NORMAL) uniform sampler2D texMaterialNormal2d;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_NORMAL_ARRAY) uniform sampler2DArray texMaterialNormalArray;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_NORMAL_CUBE) uniform samplerCube texMaterialNormalCube;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_SSAO) uniform sampler2D texSsao;&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_SHADOWMAP2D0) uniform sampler2D texShadows2d[CAGE_SHADER_MAX_SHADOWMAPS2D];&#xD;&#xA;layout(binding = CAGE_SHADER_TEXTURE_SHADOWMAPCUBE0) uniform samplerCube texShadowsCube[CAGE_SHADER_MAX_SHADOWMAPSCUBE];&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I have read that it is valid to have different textures bound to same texture unit if they are different targets, but it is not valid to use them for sampling.&#xD;&#xA;&#xD;&#xA;I want to avoid making shader variations just for texture types.&#xD;&#xA;&#xD;&#xA;What other possibilities are there that may help with this?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="38922" PostHistoryTypeId="1" PostId="13089" RevisionGUID="85a53540-7099-4f53-aaa9-3f66c30911d5" CreationDate="2022-11-05T23:39:29.130" UserId="10547" Text="combinatoric explosion of sampler2D, sampler2DArray, samplerCube" ContentLicense="CC BY-SA 4.0" />
  <row Id="38923" PostHistoryTypeId="3" PostId="13089" RevisionGUID="85a53540-7099-4f53-aaa9-3f66c30911d5" CreationDate="2022-11-05T23:39:29.130" UserId="10547" Text="|glsl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38925" PostHistoryTypeId="2" PostId="13090" RevisionGUID="51a5696c-ef4d-4223-abdb-499c95b381e6" CreationDate="2022-11-06T04:17:41.110" UserId="2654" Text="&gt; I want to avoid making shader variations just for texture types.&#xD;&#xA;&#xD;&#xA;Then you should rethink that decision.&#xD;&#xA;&#xD;&#xA;Skybox rendering is so rare compared to rendering everything else that having a separate shader specifically for that has negligible costs.&#xD;&#xA;&#xD;&#xA;And there's really no reason not to just make everything else an array texture, even if there is only one array layer in most of them." ContentLicense="CC BY-SA 4.0" />
  <row Id="38927" PostHistoryTypeId="50" PostId="4703" RevisionGUID="19477e6a-e8b9-48a3-8076-1b44478ce487" CreationDate="2022-11-06T12:06:30.757" UserId="-1" />
  <row Id="38928" PostHistoryTypeId="50" PostId="12743" RevisionGUID="5aa65c9f-197b-4598-8ffd-adb6160a33b5" CreationDate="2022-11-06T19:03:55.387" UserId="-1" />
  <row Id="38933" PostHistoryTypeId="2" PostId="13092" RevisionGUID="71e6b304-970b-4121-a02a-ab547e4eded9" CreationDate="2022-11-06T20:17:18.287" UserId="19173" Text="It could be the X3D format, but without more information I couldn't be sure.&#xD;&#xA;You could try reading [A comparison of 3D file formats][1].&#xD;&#xA;If you're in a unix/linux environment you could try file.&#xD;&#xA;[file(1) - Linux man page][2].&#xD;&#xA;Finally you could trade a game/engine data extraction tool&#xD;&#xA;[Game Extractor][3]&#xD;&#xA;[Game Extractor(might be the same software)][4]&#xD;&#xA;[Extraction tools][5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://liu.diva-portal.org/smash/get/diva2:462098/FULLTEXT01.pdf&#xD;&#xA;  [2]: https://linux.die.net/man/1/file&#xD;&#xA;  [3]: https://sourceforge.net/projects/gameextractor/&#xD;&#xA;  [4]: https://github.com/wattostudios/GameExtractor&#xD;&#xA;  [5]: https://wiki.xentax.com/index.php/Extraction_tools" ContentLicense="CC BY-SA 4.0" />
  <row Id="38935" PostHistoryTypeId="50" PostId="13022" RevisionGUID="5ae3eb78-8a44-407a-96e1-61f0d4305a80" CreationDate="2022-11-07T01:03:40.463" UserId="-1" />
  <row Id="38947" PostHistoryTypeId="2" PostId="13095" RevisionGUID="5f4660f9-26fc-47d5-bc34-1cac13adb26f" CreationDate="2022-11-09T14:46:26.187" UserId="13273" Text="I would like to know how material works with respect to light.&#xD;&#xA;&#xD;&#xA;first of all, I've a lightsource e.g. the sun. The sun has a spectrum like figure1&#xD;&#xA;&#xD;&#xA;**Figure1**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;When an object is illuminated by the sun, how does the reflected spectrum change? Does each surface has an own reflection spectrum? where each photon &quot;checks&quot; its wavelength and &quot;decides&quot; to reflect or absorb?&#xD;&#xA;&#xD;&#xA;for example a green object would absorb all wavelength except a small bandwidth of green?&#xD;&#xA;&#xD;&#xA;Lets do a small example:&#xD;&#xA;Lets imagine having a ray tracer setup with the sun as illumination, a few objects with different colors and a physical simulated camera with 3 color channels, where each color channel has a very small bandwidth of 10nm (see Figure2). &#xD;&#xA;&#xD;&#xA;**Figure2**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Then we can say, that we change the sun spectrum so that only the 10nm bandwidth of the camera channels are stored into 3 watt values. The same with each material reflection spectrum.&#xD;&#xA;&#xD;&#xA;Each simulated ray holds the three values of the sun spectrum.&#xD;&#xA;In case the ray is intersecting an object, can I scale the three values by the objects material reflection spectrum with respect to the 3 camera wavelength and bandwidth?&#xD;&#xA;&#xD;&#xA;Or did I understand it completely wrong?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/joLQY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OpnuC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38949" PostHistoryTypeId="1" PostId="13095" RevisionGUID="5f4660f9-26fc-47d5-bc34-1cac13adb26f" CreationDate="2022-11-09T14:46:26.187" UserId="13273" Text="light spectrum reflection / absorbation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38950" PostHistoryTypeId="3" PostId="13095" RevisionGUID="5f4660f9-26fc-47d5-bc34-1cac13adb26f" CreationDate="2022-11-09T14:46:26.187" UserId="13273" Text="|reflection|light|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38951" PostHistoryTypeId="2" PostId="13096" RevisionGUID="39a1b8be-0288-47db-aea1-5c5317d29d9c" CreationDate="2022-11-09T17:09:54.663" UserId="19136" Text="I'm trying to add light and see its changes in a simple scene in threejs but no matter the intensity or the color I set for the light, I see no change in a scene. Actually, if I don't include the light code, nothing changes as well, so why is HemisphereLight not working in my case?&#xD;&#xA;&#xD;&#xA;    import * as THREE from 'three';&#xD;&#xA;    import { OrbitControls } 	from './Assets/scripts/three.js/examples/jsm/controls/OrbitControls.js';&#xD;&#xA;    &#xD;&#xA;    var clock = new THREE.Clock()&#xD;&#xA;    &#xD;&#xA;    function main() {&#xD;&#xA;    &#xD;&#xA;    	var renderer = new THREE.WebGLRenderer();&#xD;&#xA;    &#xD;&#xA;    	renderer.setSize(window.innerWidth, window.innerHeight);&#xD;&#xA;    	console.log(window.innerHeight, window.innerWidth)&#xD;&#xA;    &#xD;&#xA;    	var scene = new THREE.Scene();&#xD;&#xA;    	var camera = new THREE.PerspectiveCamera( 200, window.innerWidth/window.innerHeight, 0.1, 1000 );&#xD;&#xA;    &#xD;&#xA;    	var renderer = new THREE.WebGLRenderer();&#xD;&#xA;    	renderer.setSize( window.innerWidth, window.innerHeight );&#xD;&#xA;    	document.body.appendChild( renderer.domElement );&#xD;&#xA;    &#xD;&#xA;    	var vShader = `&#xD;&#xA;    	precision mediump float;&#xD;&#xA;    	uniform float uTime;&#xD;&#xA;    	void main() {&#xD;&#xA;    	  float z = 0.1*cos(uTime)   * cos(position.y*40. - uTime) * position.y*sin(log(position.y))*0.5 + 0.5;&#xD;&#xA;    	  gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0);&#xD;&#xA;    	}&#xD;&#xA;      `&#xD;&#xA;      var fShader = `&#xD;&#xA;      precision mediump float;&#xD;&#xA;      	uniform vec2 uRes;&#xD;&#xA;    	void main() {&#xD;&#xA;    	vec2 uv = 1.5*gl_FragCoord.xy/uRes;&#xD;&#xA;    	  gl_FragColor = vec4(uv.x, uv.y, 0.0, 1.0);&#xD;&#xA;    	}&#xD;&#xA;    //   `&#xD;&#xA;    		var planeG = new THREE.PlaneGeometry(25, 60, 20, 20);&#xD;&#xA;    		console.log(planeG.parameters)&#xD;&#xA;    		var planeM = new THREE.ShaderMaterial({&#xD;&#xA;    			uniforms: {&#xD;&#xA;    			  uTime: {&#xD;&#xA;    				type:&quot;f&quot;,&#xD;&#xA;    				value:0.0,&#xD;&#xA;    			  },&#xD;&#xA;    			  uRes: {&#xD;&#xA;    				type:&quot;f&quot;,&#xD;&#xA;    				value:new THREE.Vector2(window.innerWidth, window.innerHeight),&#xD;&#xA;    			  }&#xD;&#xA;    			},&#xD;&#xA;    			// wireframe:true,&#xD;&#xA;    			vertexShader:vShader,&#xD;&#xA;    			fragmentShader:fShader,&#xD;&#xA;    			side:THREE.DoubleSide,&#xD;&#xA;    		});&#xD;&#xA;      &#xD;&#xA;    		var plane = new THREE.Mesh( planeG, planeM );&#xD;&#xA;    		var light = new THREE.HemisphereLight(0xffffff, 0x000000, 20000);&#xD;&#xA;    		var controls = new OrbitControls(camera, renderer.domElement)&#xD;&#xA;    	&#xD;&#xA;    		scene.add(light);&#xD;&#xA;    		console.log(light)&#xD;&#xA;    		scene.add(plane);&#xD;&#xA;      &#xD;&#xA;    		plane.rotateZ(Math.PI/2)&#xD;&#xA;    		camera.position.z = 4;&#xD;&#xA;      &#xD;&#xA;    		scene.background = new THREE.Color(0xfffffff);&#xD;&#xA;    	var render = function (time) {&#xD;&#xA;    		  requestAnimationFrame( render );   &#xD;&#xA;    		  controls.update(clock.getDelta())&#xD;&#xA;    		  plane.material.uniforms.uTime.value = time/100;&#xD;&#xA;    			renderer.render(scene, camera);&#xD;&#xA;    	};&#xD;&#xA;    	console.log(THREE.REVISION)&#xD;&#xA;    &#xD;&#xA;    	render();&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    main()" ContentLicense="CC BY-SA 4.0" />
  <row Id="38953" PostHistoryTypeId="1" PostId="13096" RevisionGUID="39a1b8be-0288-47db-aea1-5c5317d29d9c" CreationDate="2022-11-09T17:09:54.663" UserId="19136" Text="How to add HemisphereLight to a simple threejs scene?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38954" PostHistoryTypeId="3" PostId="13096" RevisionGUID="39a1b8be-0288-47db-aea1-5c5317d29d9c" CreationDate="2022-11-09T17:09:54.663" UserId="19136" Text="|lighting|color|vector-graphics|javascript|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38961" PostHistoryTypeId="2" PostId="13098" RevisionGUID="e7053072-3dd1-4fe7-af34-980ee16d9110" CreationDate="2022-11-10T09:51:27.950" UserId="13273" Text="I've implemented the convolution shadow mapping technique (CSM) and want to apply a gaussian filter to receive soft shadows.&#xD;&#xA;&#xD;&#xA;The filter size of the filtered pixels is not static. With help of a summed area table I found regions (pixels) which need to be blurred more than others.&#xD;&#xA;&#xD;&#xA;I know, that the gaussian kernel needs to be applied to the $b_i$ values (16 values in my case, because I choose $m=8$).&#xD;&#xA;But I don't understand how to apply them.&#xD;&#xA;&#xD;&#xA;I tested it by simply using a convolution (read 5x5 surrounding pixels $b_i$ values) and blur them with respect to my e.g. 5x5 gaussian kernel. But this does not lead to soft shadows. It turns out, that this leads to wider shadows. In case the gaussian kernel size is 16x16, a small shadow caster would cast a too large shadow, which is soft only at the very outside pixel.&#xD;&#xA;&#xD;&#xA;At school I learned, that in fourierspace a convolution is a simple multiplication of a fourierspaced kernel. So it came into my mind to apply the gaussian kernel into fourierspace as well. But I don't know how I can do that, and would this be the correct solution to achieve wide soft shadows?&#xD;&#xA;&#xD;&#xA;Some pictures of my results (Left: no blurring, right: gaussian blur 9x9):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zLT4y.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38963" PostHistoryTypeId="1" PostId="13098" RevisionGUID="e7053072-3dd1-4fe7-af34-980ee16d9110" CreationDate="2022-11-10T09:51:27.950" UserId="13273" Text="Convolution shadow mapping apply filter" ContentLicense="CC BY-SA 4.0" />
  <row Id="38964" PostHistoryTypeId="3" PostId="13098" RevisionGUID="e7053072-3dd1-4fe7-af34-980ee16d9110" CreationDate="2022-11-10T09:51:27.950" UserId="13273" Text="|shadow-mapping|blur|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38965" PostHistoryTypeId="5" PostId="13098" RevisionGUID="b12ca10e-683d-4bfb-86d6-0650fbc602d0" CreationDate="2022-11-10T10:27:05.190" UserId="13273" Comment="added 350 characters in body" Text="I've implemented the convolution shadow mapping technique (CSM) and want to apply a gaussian filter to receive soft shadows.&#xD;&#xA;&#xD;&#xA;The filter size of the filtered pixels is not static. With help of a summed area table I found regions (pixels) which need to be blurred more than others.&#xD;&#xA;&#xD;&#xA;I know, that the gaussian kernel needs to be applied to the $b_i$ values (16 values in my case, because I choose $m=8$).&#xD;&#xA;But I don't understand how to apply them.&#xD;&#xA;&#xD;&#xA;I tested it by simply using a convolution (read 5x5 surrounding pixels $b_i$ values) and blur them with respect to my e.g. 5x5 gaussian kernel. But this does not lead to soft shadows. It turns out, that this leads to wider shadows. In case the gaussian kernel size is 16x16, a small shadow caster would cast a too large shadow, which is soft only at the very outside pixel.&#xD;&#xA;&#xD;&#xA;At school I learned, that in fourierspace a convolution is a simple multiplication of a fourierspaced kernel. So it came into my mind to apply the gaussian kernel into fourierspace as well. But I don't know how I can do that, and would this be the correct solution to achieve wide soft shadows?&#xD;&#xA;&#xD;&#xA;Some pictures of my results (Left: no blurring, right: gaussian blur 9x9):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As you can see on the right image, there is only the most outer pixel line soft (maybe two pixel lines). the rest is turned into black completely. The width of the shadow is too large. I hoped to get the blurring also within the shadowed region like in this example:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zLT4y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/yDJ70.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38966" PostHistoryTypeId="5" PostId="13098" RevisionGUID="655ec3e4-069c-4863-bccd-a99b49a56fe6" CreationDate="2022-11-10T10:58:42.637" UserId="13273" Comment="added 61 characters in body" Text="I've implemented the convolution shadow mapping technique [(CSM)][1] and want to apply a gaussian filter to receive soft shadows.&#xD;&#xA;&#xD;&#xA;The filter size of the filtered pixels is not static. With help of a summed area table I found regions (pixels) which need to be blurred more than others.&#xD;&#xA;&#xD;&#xA;I know, that the gaussian kernel needs to be applied to the $b_i$ values (16 values in my case, because I choose $m=8$).&#xD;&#xA;But I don't understand how to apply them.&#xD;&#xA;&#xD;&#xA;I tested it by simply using a convolution (read 5x5 surrounding pixels $b_i$ values) and blur them with respect to my e.g. 5x5 gaussian kernel. But this does not lead to soft shadows. It turns out, that this leads to wider shadows. In case the gaussian kernel size is 16x16, a small shadow caster would cast a too large shadow, which is soft only at the very outside pixel.&#xD;&#xA;&#xD;&#xA;At school I learned, that in fourierspace a convolution is a simple multiplication of a fourierspaced kernel. So it came into my mind to apply the gaussian kernel into fourierspace as well. But I don't know how I can do that, and would this be the correct solution to achieve wide soft shadows?&#xD;&#xA;&#xD;&#xA;Some pictures of my results (Left: no blurring, right: gaussian blur 9x9):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see on the right image, there is only the most outer pixel line soft (maybe two pixel lines). the rest is turned into black completely. The width of the shadow is too large. I hoped to get the blurring also within the shadowed region like in this example:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jankautz.com/publications/csmEGSR07.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/zLT4y.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yDJ70.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38967" PostHistoryTypeId="5" PostId="13098" RevisionGUID="4e4bef35-f687-4197-8938-0059d4a1fc3e" CreationDate="2022-11-10T19:49:52.923" UserId="13273" Comment="added 17 characters in body" Text="I've implemented the convolution shadow mapping technique [(CSM)][1] and want to apply a gaussian filter to receive soft shadows.&#xD;&#xA;&#xD;&#xA;The filter size of the filtered pixels is not static. With help of a summed area table I found regions (pixels) which need to be blurred more than others.&#xD;&#xA;&#xD;&#xA;I know, that the gaussian kernel needs to be applied to the $b_i$ values (16 values in my case, because I choose $m=8$).&#xD;&#xA;But I don't understand how to apply them.&#xD;&#xA;&#xD;&#xA;I tested it by simply using a convolution (read 5x5 surrounding pixels $b_i$ values) and blur them by multiplying with respect to my e.g. 5x5 gaussian kernel. But this does not lead to soft shadows. It turns out, that this leads to wider shadows. In case the gaussian kernel size is 16x16, a small shadow caster would cast a too large shadow, which is soft only at the very outside pixel.&#xD;&#xA;&#xD;&#xA;At school I learned, that in fourierspace a convolution is a simple multiplication of a fourierspaced kernel. So it came into my mind to apply the gaussian kernel into fourierspace as well. But I don't know how I can do that, and would this be the correct solution to achieve wide soft shadows?&#xD;&#xA;&#xD;&#xA;Some pictures of my results (Left: no blurring, right: every pixel same gaussian blur 9x9):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;As you can see on the right image, there is only the most outer pixel line soft (maybe two pixel lines). the rest is turned into black completely. The width of the shadow is too large. I hoped to get the blurring also within the shadowed region like in this example:&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jankautz.com/publications/csmEGSR07.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/zLT4y.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/yDJ70.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38968" PostHistoryTypeId="2" PostId="13099" RevisionGUID="d0eea38d-4139-4dd0-8a84-e7f41dc1a0e9" CreationDate="2022-11-10T20:41:42.383" UserId="445" Text="&gt; When an object is illuminated by the sun, how does the reflected spectrum change? Does each surface has an own reflection spectrum? where each photon &quot;checks&quot; its wavelength and &quot;decides&quot; to reflect or absorb?&#xD;&#xA;&#xD;&#xA;Yes, this is more or less correct. But when dealing with very many photons, striking very many different atoms/molecules mixed together into one material, we observe that some _fraction_, or percentage if you like, of the photons are reflected. So, the spectrum is made up not of yes-or-no, but that fraction, for each wavelength. This is called the surface's [reflectance spectrum](https://en.wikipedia.org/wiki/Reflectance). You may also hear “diffuse reflectance” or “albedo”.&#xD;&#xA;&#xD;&#xA;(“Diffuse” means the reflection happens at a random angle, usually due to roughness or translucency of the material; its opposite is “specular”, mirror-like reflection. When an object gleams and sparkles, that is specular reflection. Most objects exhibit some of both, and the specular reflectance can have a different color/spectrum than the diffuse — usually whiter.)&#xD;&#xA;&#xD;&#xA;Then, as you have thought, we usually consider this only in 3 different wavelengths/bands since that is sufficient to reproduce _most_ (but not all) effects that human vision can observe. (For example, [color rendering index](https://en.wikipedia.org/wiki/Color_rendering_index) is about how the spectrum of a light source interacts with the reflectance spectrum of illuminated objects. You cannot simulate this without simulating more components of the spectrum than just RGB.)&#xD;&#xA;&#xD;&#xA;&gt;  Lets imagine having a ray tracer setup with the sun as illumination, a few objects with different colors and a physical simulated camera with 3 color channels, where each color channel has a very small bandwidth of 10nm (see Figure2).&#xD;&#xA;&#xD;&#xA;Computing using the RGB approximation does not generally think about wavelength bands at all — we just pick 3 precise wavelengths for our R, G, and B [primaries](https://en.wikipedia.org/wiki/Primary_color) and express all other colors in terms of mixes of those primaries which are identical to the (typical) human eye.&#xD;&#xA;&#xD;&#xA;Any such choice of primaries will constrain the [gamut](https://en.wikipedia.org/wiki/Gamut) of colors that can be represented — some highly saturated colors will be excluded, unless the color components are allowed to go negative to express the most extreme monochromatic (or purple) colors. This is usually an acceptable limitation, because RGB monitors are _physically_ limited to emit only specific wavelengths based on the color of their LED emitters, LCD color filters, or CRT phosphors.&#xD;&#xA;&#xD;&#xA;(Note that in _printed_ graphics, the situation is more complex because instead of a display device emitting only R+G+B light, we produce an object with its own reflectance spectrum based on the pigments/dyes used. That's why 4-component “CMYK” color is used — it's a better match for the actual behavior of the pigments. In some cases, “spot colors” may be used, identifying a specific pigment to be laid down in a certain area, to produce precise colors or special effects such as shininess.)&#xD;&#xA;&#xD;&#xA;&gt; In case the ray is intersecting an object, can I scale the three values by the objects material reflection spectrum with respect to the 3 camera wavelength and bandwidth?&#xD;&#xA;&#xD;&#xA;Yes, you should multiply each wavelength/color-component of the incoming light by the object's reflectance for that color. The bandwidth need not be explicitly modeled — if changing the bandwidth makes any difference, then it is equivalent to changing the choice of primaries, i.e. working in a different [color space](https://en.wikipedia.org/wiki/Color_space). You can always convert a color from one RGB color space to another (when it is in the gamut of both) with a little bit of arithmetic.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Again, all of what I've said above is true _when you are working in RGB_. This does have limitations; if you want to precisely simulate the effects of monochromatic lights or color filters, you will need to use more color channels than just RGB. The more channels you use, the better your discrete approximation of the continuous spectra in real physics. However, this is rarely done in rendering — most computer graphics you have ever seen in your life were probably only calculated using RGB." ContentLicense="CC BY-SA 4.0" />
  <row Id="38970" PostHistoryTypeId="2" PostId="13100" RevisionGUID="551e2fbe-7dfb-41cf-9f87-db666a012da7" CreationDate="2022-11-11T00:39:38.017" UserId="7462" Text="I am trying to load gltf data onto an engine I am making and I am noticing that something is wrong with the rotations. I want to be able to see the raw numeric values of the animation data in the gltf source file to compare against what my code is constructing but I cannot find anything.&#xD;&#xA;&#xD;&#xA;Gestaltor doesn't seem to show the actual data, and online viewers and validators just tell you if the data is malformed or not, they don't show it." ContentLicense="CC BY-SA 4.0" />
  <row Id="38972" PostHistoryTypeId="1" PostId="13100" RevisionGUID="551e2fbe-7dfb-41cf-9f87-db666a012da7" CreationDate="2022-11-11T00:39:38.017" UserId="7462" Text="Inspecting gltf animation data" ContentLicense="CC BY-SA 4.0" />
  <row Id="38973" PostHistoryTypeId="3" PostId="13100" RevisionGUID="551e2fbe-7dfb-41cf-9f87-db666a012da7" CreationDate="2022-11-11T00:39:38.017" UserId="7462" Text="|mesh|animation|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38974" PostHistoryTypeId="5" PostId="13099" RevisionGUID="24442dd1-1936-4fc2-969f-f5a23b77eccc" CreationDate="2022-11-11T14:42:41.527" UserId="445" Comment="added 33 characters in body" Text="&gt; When an object is illuminated by the sun, how does the reflected spectrum change? Does each surface has an own reflection spectrum? where each photon &quot;checks&quot; its wavelength and &quot;decides&quot; to reflect or absorb?&#xD;&#xA;&#xD;&#xA;Yes, this is more or less correct. But when dealing with very many photons, striking very many different atoms/molecules mixed together into one material, we observe that some _fraction_, or percentage if you like, of the photons are reflected. So, the spectrum is made up not of yes-or-no, but that fraction, for each wavelength. This is called the surface's [reflectance spectrum](https://en.wikipedia.org/wiki/Reflectance). You may also hear “diffuse reflectance” or “albedo”.&#xD;&#xA;&#xD;&#xA;(“Diffuse” means the reflection happens at a random angle, usually due to roughness or translucency of the material; its opposite is “specular”, mirror-like reflection. When an object gleams and sparkles, that is specular reflection. Most objects exhibit some of both, and the specular reflectance can have a different color/spectrum than the diffuse — usually whiter.)&#xD;&#xA;&#xD;&#xA;Then, as you have thought, we usually consider this only in 3 different wavelengths/bands since that is sufficient to reproduce _most_ (but not all) effects that human vision can observe. (For example, [color rendering index](https://en.wikipedia.org/wiki/Color_rendering_index) is about how the spectrum of a light source interacts with the reflectance spectrum of illuminated objects. You cannot simulate this without simulating more components of the spectrum than just RGB.)&#xD;&#xA;&#xD;&#xA;&gt;  Lets imagine having a ray tracer setup with the sun as illumination, a few objects with different colors and a physical simulated camera with 3 color channels, where each color channel has a very small bandwidth of 10nm (see Figure2).&#xD;&#xA;&#xD;&#xA;Computing using the RGB approximation does not generally think about wavelength bands at all — we just pick 3 precise wavelengths for our R, G, and B [primaries](https://en.wikipedia.org/wiki/Primary_color) and express all other colors in terms of mixes of those primaries, which are identical as seen by the (typical) human eye to more complex spectra.&#xD;&#xA;&#xD;&#xA;Any such choice of primaries will constrain the [gamut](https://en.wikipedia.org/wiki/Gamut) of colors that can be represented — some highly saturated colors will be excluded, unless the color components are allowed to go negative to express the most extreme monochromatic (or purple) colors. This is usually an acceptable limitation, because RGB monitors are _physically_ limited to emit only specific wavelengths based on the color of their LED emitters, LCD color filters, or CRT phosphors.&#xD;&#xA;&#xD;&#xA;(Note that in _printed_ graphics, the situation is more complex because instead of a display device emitting only R+G+B light, we produce an object with its own reflectance spectrum based on the pigments/dyes used. That's why 4-component “CMYK” color is used — it's a better match for the actual behavior of the pigments. In some cases, “spot colors” may be used, identifying a specific pigment to be laid down in a certain area, to produce precise colors or special effects such as shininess.)&#xD;&#xA;&#xD;&#xA;&gt; In case the ray is intersecting an object, can I scale the three values by the objects material reflection spectrum with respect to the 3 camera wavelength and bandwidth?&#xD;&#xA;&#xD;&#xA;Yes, you should multiply each wavelength/color-component of the incoming light by the object's reflectance for that color. The bandwidth need not be explicitly modeled — if changing the bandwidth makes any difference, then it is equivalent to changing the choice of primaries, i.e. working in a different [color space](https://en.wikipedia.org/wiki/Color_space). You can always convert a color from one RGB color space to another (when it is in the gamut of both) with a little bit of arithmetic.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Again, all of what I've said above is true _when you are working in RGB_. This does have limitations; if you want to precisely simulate the effects of monochromatic lights or color filters, you will need to use more color channels than just RGB. The more channels you use, the better your discrete approximation of the continuous spectra in real physics. However, this is rarely done in rendering — most computer graphics you have ever seen in your life were probably only calculated using RGB." ContentLicense="CC BY-SA 4.0" />
  <row Id="38980" PostHistoryTypeId="2" PostId="13102" RevisionGUID="cefa1507-a706-47a4-b0bd-60355e17edb6" CreationDate="2022-11-12T01:17:19.660" UserId="7462" Text="One thing that is mathematically sound is to grab a gltf model and apply some arbitrary linear transformation to it, like a rotation or a translation. &#xD;&#xA;&#xD;&#xA;Let's say the transformation is encoded as a 4x4 homogeneous matrix.&#xD;&#xA;&#xD;&#xA;I think it needs to be applied to the meshes, nodes, ibms in the skins, and animations.&#xD;&#xA;&#xD;&#xA;Starting simple, I want to apply it to only the meshes.&#xD;&#xA;&#xD;&#xA;i.e. something like this:&#xD;&#xA;```rust&#xD;&#xA;        for mesh in &amp;self.meshes&#xD;&#xA;        {&#xD;&#xA;            for primitive in &amp;mesh.primitives&#xD;&#xA;            {&#xD;&#xA;                for position in self&#xD;&#xA;                    .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.position)&#xD;&#xA;                    .unwrap()&#xD;&#xA;                {&#xD;&#xA;                    *position = transform_vec3(&amp;position, &amp;transform, true);&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                for normal in self&#xD;&#xA;                    .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.normal)&#xD;&#xA;                    .unwrap()&#xD;&#xA;                {&#xD;&#xA;                    *normal = transform_vec3(&amp;normal, &amp;transform, false);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;   ```&#xD;&#xA;&#xD;&#xA;This is ok and yields:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Ok now I want to apply to the nodes, so I attempt this:&#xD;&#xA;```&#xD;&#xA;        for node in &amp;mut self.nodes&#xD;&#xA;        {&#xD;&#xA;            let mut mat : Mat4 = compose_homogeneous(&amp;node.scale, &amp;node.rotation, &amp;node.translation);&#xD;&#xA;            mat = transform * mat;&#xD;&#xA;&#xD;&#xA;            let (new_scale, new_rot, new_trans) = decompose_homogeneous(&amp;mat);&#xD;&#xA;&#xD;&#xA;            node.rotation = new_rot;&#xD;&#xA;            node.translation = new_trans;&#xD;&#xA;            node.scale = new_scale;&#xD;&#xA;        }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now gltf viewers show this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Why?&#xD;&#xA;&#xD;&#xA;I have tested things and both `compose_homogeneous` and `decompose_homogeneous` are correct. Why am I getting this degenerate output?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HfnWU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/U3Pn1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38982" PostHistoryTypeId="1" PostId="13102" RevisionGUID="cefa1507-a706-47a4-b0bd-60355e17edb6" CreationDate="2022-11-12T01:17:19.660" UserId="7462" Text="How to apply a linear transformation to gltf data" ContentLicense="CC BY-SA 4.0" />
  <row Id="38983" PostHistoryTypeId="3" PostId="13102" RevisionGUID="cefa1507-a706-47a4-b0bd-60355e17edb6" CreationDate="2022-11-12T01:17:19.660" UserId="7462" Text="|transformations|animation|model|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38984" PostHistoryTypeId="2" PostId="13103" RevisionGUID="a80b06ed-5970-4be3-ab61-45684cf9ed4e" CreationDate="2022-11-12T06:11:19.560" UserId="19202" Text="There are four kinds of memory barriers in DirectX. Their names and definitions are: &#xD;&#xA;&#xD;&#xA;- `DeviceMemoryBarrier`: Blocks execution of all threads in a group until all device memory accesses have been completed.&#xD;&#xA;- `DeviceMemoryBarrierWithGroupSync`: Blocks execution of all threads in a group until all device memory accesses have been completed and all threads in the group have reached this call.&#xD;&#xA;- `GroupMemoryBarrier`: Blocks execution of all threads in a group until all group shared accesses have been completed.&#xD;&#xA;- `GroupMemoryBarrierWithGroupSync`: Blocks execution of all threads in a group until all group shared accesses have been completed and all threads in the group have reached this call.&#xD;&#xA;&#xD;&#xA;From those definitions, it looks like the only differences are the types of memories accesses they are blocking and whether the command call is synchronized. Taking the following shader code, which use groupshared memory to process texture data, as an example:&#xD;&#xA;&#xD;&#xA;``` HLSL&#xD;&#xA;Texture2D gInput;&#xD;&#xA;RWTexture2D&lt;float4&gt; gOutput;&#xD;&#xA;groupshared float4 gCache[256];&#xD;&#xA;[numthreads(256,1,1)]&#xD;&#xA;void HorzBlurCS(int3 groupThreadID : SV_GroupThreadID,&#xD;&#xA;                int3 dispatchThreadID : SV_DispatchThreadID)&#xD;&#xA;{&#xD;&#xA;  gCache[groupThreadID.x] = gInput[dispatchThreadID.xy];&#xD;&#xA;&#xD;&#xA;  // ! synchronize threads here&#xD;&#xA;  &#xD;&#xA;  // blur&#xD;&#xA;  float4 blurColor = 0.25*gCache[groupThreadID.x-1] + 0.5*gCache[groupThreadID.x] + 0.25*gCache[groupThreadID.x+1];&#xD;&#xA;  &#xD;&#xA;  gInput[dispatchThreadID.xy] = blurColor;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here are my questions:&#xD;&#xA;1. In the first line `gCache[groupThreadID.x] = gInput[dispatchThreadID.xy]`, I am accessing both device and group memory - reading from the first and writing to the second. In that case, should I choose GroupMemoryBarrier or DeviceMemoryBarrier?&#xD;&#xA;2. Should I use `WithGroupSync` version here? If not, what's the use case of that version?" ContentLicense="CC BY-SA 4.0" />
  <row Id="38986" PostHistoryTypeId="1" PostId="13103" RevisionGUID="a80b06ed-5970-4be3-ab61-45684cf9ed4e" CreationDate="2022-11-12T06:11:19.560" UserId="19202" Text="Compute shader in DirextX: difference between four kinds of memory barriers" ContentLicense="CC BY-SA 4.0" />
  <row Id="38987" PostHistoryTypeId="3" PostId="13103" RevisionGUID="a80b06ed-5970-4be3-ab61-45684cf9ed4e" CreationDate="2022-11-12T06:11:19.560" UserId="19202" Text="|compute-shader|directx|synchronization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="38992" PostHistoryTypeId="50" PostId="10248" RevisionGUID="65daec2b-4ef7-4636-9b18-976797a12cde" CreationDate="2022-11-12T13:00:25.073" UserId="-1" />
  <row Id="38993" PostHistoryTypeId="2" PostId="13105" RevisionGUID="d68a1328-5943-4867-8b04-c674e1fee766" CreationDate="2022-11-12T14:56:18.133" UserId="7952" Text="When transforming normal vectors we have to be careful to check that the transform itself is equal to its own inverse transpose. Or just do an inverse transpose on the matrix. This is usually the case, but checking it makes the requirement explicit rather then implied. (a scale in the transform for example would result in incorrect normal vectors)&#xD;&#xA;&#xD;&#xA;When transforming a matrix from one coordinate system to another where we have a matrix M that transforms vectors from coordinate system A to coordinate system B then the transform from A to B is $B=MAM^{-1}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="38995" PostHistoryTypeId="2" PostId="13106" RevisionGUID="37d4b85a-88a1-45f3-87e2-9cd78ec72ee2" CreationDate="2022-11-12T17:02:59.677" UserId="1908" Text="I help maintain an open-source extension for [VSCode](https://code.visualstudio.com/) called [glTF Tools](https://marketplace.visualstudio.com/items?itemName=cesium.gltf-vscode).&#xD;&#xA;&#xD;&#xA;Find the sampler for your animation. The `input` values will point to a list of times, and `output` will point to a list of values, likely quaternion values if this is rotation.&#xD;&#xA;&#xD;&#xA;[![screenshot of sampler][1]][1]&#xD;&#xA;&#xD;&#xA;In the above case, you might place the cursor on the `7` (the output accessor index), and press the hotkey &lt;key&gt;F12&lt;/key&gt; to find the definition of accessor index 7.&#xD;&#xA;&#xD;&#xA;[![screenshot of accessor 7][2]][2]&#xD;&#xA;&#xD;&#xA;Above, VSCode's JSON &quot;Breadcrumbs&quot; (the thin top row) are showing that the cursor has navigated to the accessor in question.  Now we can ask VSCode to decode the raw data here with the `glTF: Inspect Data` command, by default bound to the hotkey &lt;key&gt;ALT&lt;/key&gt; + &lt;key&gt;D&lt;/key&gt;.  Pressing this key should open the inspector.&#xD;&#xA;&#xD;&#xA;[![screenshot of decoded data][3]][3]&#xD;&#xA;&#xD;&#xA;Ah well, here you can see I've picked a very simple rotation with two fairly boring quaternion keyframe values.  But if you have a more complicated list of rotation keyframes, the output here will be longer and more varied.  You may right-click on a row to copy just the row's value, or copy the entire decoded data as plain text (for pasting into a spreadsheet or text file, for example).&#xD;&#xA;&#xD;&#xA;The above method works for all kinds of glTF data beyond just animations.  But there's another method specific to animations, two commands `glTF: Import animation` and `glTF: Export animation`.  These attempt to pull the raw data directly into the JSON editor for editing, but the resulting file is not valid glTF during such edits.  If you take this alternate route, remember to export the animation again when done editing.&#xD;&#xA;&#xD;&#xA;Give the inspector a try first.  Good luck!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/S9qTZ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/31T44.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/AjhYA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="38999" PostHistoryTypeId="50" PostId="12259" RevisionGUID="dfd41e6f-1142-4a9d-bd5a-85eab76f5582" CreationDate="2022-11-13T17:04:50.633" UserId="-1" />
  <row Id="39000" PostHistoryTypeId="2" PostId="13107" RevisionGUID="e5aa3bd8-0496-451b-a7cc-75529302e487" CreationDate="2022-11-13T21:12:25.127" UserId="19210" Text="unfortunately I always had problems with math and was never good at it.  I'm currently trying to combine math with my knowledge and my passion for programming.&#xD;&#xA;&#xD;&#xA;Brief introduction: In maths, we have currently arrived at the topic of matrix multiplication and 3D projection, which sounds more interesting to me as an enthusiastic programmer than the whole thing with abstract number theories.&#xD;&#xA;So I set myself the goal of programming a small 3D game in Processing (Java). My first success was to rotate a Cube in 3 dimensions.&#xD;&#xA;&#xD;&#xA;Goal: After that I wanted to have a perspective for a three-dimensional space.  I took the 3D projection matrix from here: https://en.m.wikipedia.org/wiki/3D_projection : Mathematical Formula.&#xD;&#xA;&#xD;&#xA;Problem: I noticed that when I rotate the camera, the projection (the box in this case) flips horizontally and vertically.&#xD;&#xA;&#xD;&#xA;video here: https://www.youtube.com/watch?v=_xrSYmCa_FQ&#xD;&#xA;&#xD;&#xA;What is happening (timestamp 0:14) and how can I fix it?&#xD;&#xA;&#xD;&#xA;Code: https://github.com/Dario404/3D-projection/blob/main/projection.pde" ContentLicense="CC BY-SA 4.0" />
  <row Id="39002" PostHistoryTypeId="1" PostId="13107" RevisionGUID="e5aa3bd8-0496-451b-a7cc-75529302e487" CreationDate="2022-11-13T21:12:25.127" UserId="19210" Text="3D projection Axis inversion problem (Java/Processing)" ContentLicense="CC BY-SA 4.0" />
  <row Id="39003" PostHistoryTypeId="3" PostId="13107" RevisionGUID="e5aa3bd8-0496-451b-a7cc-75529302e487" CreationDate="2022-11-13T21:12:25.127" UserId="19210" Text="|projections|matrix|camera-matrix|java|processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39004" PostHistoryTypeId="2" PostId="13108" RevisionGUID="885d7784-4e0a-414d-8bcc-49cfad37ea0f" CreationDate="2022-11-14T03:10:11.783" UserId="15155" Text="&#xD;&#xA;&#xD;&#xA;as the question suggests im looking to output to more than one canvas element in processing to speed up the calculations and limit shader draw calls. It has to be as simple as possible to be transferable to android as well.&#xD;&#xA;&#xD;&#xA;This is the shader call. Is there a way to do this using layout, if I was to provide another sampler texture?&#xD;&#xA;&#xD;&#xA;    #ifdef GL_ES&#xD;&#xA;    precision mediump float;&#xD;&#xA;    precision mediump int;&#xD;&#xA;    #endif&#xD;&#xA;    #define PROCESSING_TEXTURE_SHADER&#xD;&#xA;    uniform float v[10];&#xD;&#xA;    uniform sampler2D texture;&#xD;&#xA;    uniform sampler2D va0;&#xD;&#xA;    uniform sampler2D vb0;&#xD;&#xA;    uniform sampler2D va1;&#xD;&#xA;    uniform sampler2D vb1;&#xD;&#xA;    uniform sampler2D va2;&#xD;&#xA;    uniform sampler2D vb2;&#xD;&#xA;    uniform sampler2D va3;&#xD;&#xA;    uniform sampler2D vb3;&#xD;&#xA;    uniform float mult = 1.0;&#xD;&#xA;    uniform float type;&#xD;&#xA;    uniform float thresh;&#xD;&#xA;    uniform vec2 texOffset;&#xD;&#xA;    varying vec4 vertColor;&#xD;&#xA;    varying vec4 vertTexCoord;&#xD;&#xA;    uniform vec2 resolution;&#xD;&#xA;    uniform float w;&#xD;&#xA;    uniform int [1000]s;&#xD;&#xA;    uniform float [10]ops;&#xD;&#xA;    uniform float [1000]vars;&#xD;&#xA;    void main(void) {&#xD;&#xA;    float x = 1.0 / resolution.x;&#xD;&#xA;    float y = 1.0 / resolution.y;&#xD;&#xA;    vec2 tx = vertTexCoord.st;&#xD;&#xA;    vec4 via0 = texture2D(va0 , vertTexCoord.st);&#xD;&#xA;    vec4 vib0 = texture2D(vb0 , vertTexCoord.st);&#xD;&#xA;    vec4 via1 = texture2D(va1 , vertTexCoord.st);&#xD;&#xA;    vec4 vib1 = texture2D(vb1 , vertTexCoord.st);&#xD;&#xA;    vec4 via2 = texture2D(va2 , vertTexCoord.st);&#xD;&#xA;    vec4 vib2 = texture2D(vb2 , vertTexCoord.st);&#xD;&#xA;    vec4 via3 = texture2D(va3 , vertTexCoord.st);&#xD;&#xA;    vec4 vib3 = texture2D(vb3 , vertTexCoord.st);&#xD;&#xA;    float base = 256;&#xD;&#xA;    float b1 = base*base*255;&#xD;&#xA;    float b2 = base*255;&#xD;&#xA;    float b3 = 255;&#xD;&#xA;    float tva0 = (via0.r*b1 + via0.g*b2 + via0.b*b3);&#xD;&#xA;    float tva1 = (via1.r*b1 + via1.g*b2 + via1.b*b3);&#xD;&#xA;    float tva2 = (via2.r*b1 + via2.g*b2 + via2.b*b3);&#xD;&#xA;    float tva3 = (via3.r*b1 + via3.g*b2 + via3.b*b3);&#xD;&#xA;    float tvb0 = (vib0.r*b1 + vib0.g*b2 + vib0.b*b3 )/100000;&#xD;&#xA;    float tvb1 = (vib1.r*b1 + vib1.g*b2 + vib1.b*b3 )/100000;&#xD;&#xA;    float tvb2 = (vib2.r*b1 + vib2.g*b2 + vib2.b*b3 )/100000;&#xD;&#xA;    float tvb3 = (vib3.r*b1 + vib3.g*b2 + vib3.b*b3 )/100000;&#xD;&#xA;    float tvf0 = (tvb0+tva0);&#xD;&#xA;    float tvf1 = (tvb1+tva1);&#xD;&#xA;    float tvf2 = (tvb2+tva2);&#xD;&#xA;    float tvf3 = (tvb3+tva3);&#xD;&#xA;    if(via0.a&lt;1.0)tvf0= (tvb0+(-(tva0)*0.0));&#xD;&#xA;    if(via1.a&lt;1.0)tvf1= (tvb1+(-(tva1)*0.0));&#xD;&#xA;    if(via2.a&lt;1.0)tvf2= (tvb2+(-(tva2)*0.0));&#xD;&#xA;    if(via3.a&lt;1.0)tvf3= (tvb3+(-(tva3)*0.0));&#xD;&#xA;    float num = ((tvf0)/(tvf1)*(tvf2)/(tvf3))*1.0;&#xD;&#xA;    float numf = 0.0;&#xD;&#xA;    if(num&lt;0.0) numf = int(-num);&#xD;&#xA;    else numf = int(num);&#xD;&#xA;    float rni = round(mod (numf/(base*base), base))/255;&#xD;&#xA;    float gni = round(mod ((numf/base), base))/255;&#xD;&#xA;    float bni = round(mod (numf, base))/255;&#xD;&#xA;    if(numf&gt;0.0)gl_FragColor = vec4(rni, gni, bni, 1.0);&#xD;&#xA;    else  gl_FragColor = vec4(rni, gni, bni, 0.5);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="39006" PostHistoryTypeId="1" PostId="13108" RevisionGUID="885d7784-4e0a-414d-8bcc-49cfad37ea0f" CreationDate="2022-11-14T03:10:11.783" UserId="15155" Text="output to more than one canvas texture in processing with shader opngl" ContentLicense="CC BY-SA 4.0" />
  <row Id="39007" PostHistoryTypeId="3" PostId="13108" RevisionGUID="885d7784-4e0a-414d-8bcc-49cfad37ea0f" CreationDate="2022-11-14T03:10:11.783" UserId="15155" Text="|shader|java|processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39008" PostHistoryTypeId="5" PostId="13107" RevisionGUID="f39704fb-4415-4d29-9348-c76b27d6c7e7" CreationDate="2022-11-14T14:02:18.057" UserId="19210" Comment="added 5409 characters in body" Text="unfortunately I always had problems with math and was never good at it.  I'm currently trying to combine math with my knowledge and my passion for programming.&#xD;&#xA;&#xD;&#xA;Brief introduction: In maths, we have currently arrived at the topic of matrix multiplication and 3D projection, which sounds more interesting to me as an enthusiastic programmer than the whole thing with abstract number theories.&#xD;&#xA;So I set myself the goal of programming a small 3D game in Processing (Java). My first success was to rotate a Cube in 3 dimensions.&#xD;&#xA;&#xD;&#xA;Goal: After that I wanted to have a perspective for a three-dimensional space.  I took the 3D projection matrix from here: https://en.m.wikipedia.org/wiki/3D_projection : Mathematical Formula.&#xD;&#xA;&#xD;&#xA;Problem: I noticed that when I rotate the camera, the projection (the box in this case) flips horizontally and vertically.&#xD;&#xA;&#xD;&#xA;video here: https://www.youtube.com/watch?v=_xrSYmCa_FQ&#xD;&#xA;&#xD;&#xA;What is happening (timestamp 0:14) and how can I fix it?&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    import java.util.Arrays;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector[] points;&#xD;&#xA;    &#xD;&#xA;    PVector cam, cam_angle, point;&#xD;&#xA;    &#xD;&#xA;    float angle = 0.0;&#xD;&#xA;    &#xD;&#xA;    void setup() {&#xD;&#xA;      //fullScreen();  &#xD;&#xA;      &#xD;&#xA;      size(1000,400);&#xD;&#xA;      noCursor();&#xD;&#xA;    &#xD;&#xA;      cam = point = new PVector(0, 0, -1000);&#xD;&#xA;      cam_angle = new PVector(0,0,0);&#xD;&#xA;    &#xD;&#xA;      points = new PVector[] {&#xD;&#xA;        new PVector(-100, -100, -100),&#xD;&#xA;        new PVector(-100, -100, 100),&#xD;&#xA;        new PVector(-100, 100, -100),&#xD;&#xA;        new PVector(-100, 100, 100),&#xD;&#xA;        new PVector( 100, -100, -100),&#xD;&#xA;        new PVector( 100, -100, 100),&#xD;&#xA;        new PVector( 100, 100, -100),&#xD;&#xA;        new PVector( 100, 100, 100),&#xD;&#xA;      };&#xD;&#xA;      &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector Rotate2d(PVector p, float a) {&#xD;&#xA;      // a = angle&#xD;&#xA;    &#xD;&#xA;      float[][] m2 = {&#xD;&#xA;        {cos(a), -sin(a)},&#xD;&#xA;        {sin(a), cos(a)}&#xD;&#xA;      };&#xD;&#xA;    &#xD;&#xA;      float[][] rotated = matmul(m2, new float[][] {&#xD;&#xA;        { p.x },&#xD;&#xA;        { p.y }&#xD;&#xA;        });&#xD;&#xA;    &#xD;&#xA;      return new PVector(rotated[0][0], rotated[1][0]);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d(PVector p, float[][] m2) {&#xD;&#xA;    &#xD;&#xA;      float[][] rotated = matmul(m2, new float[][] {&#xD;&#xA;        { p.x },&#xD;&#xA;        { p.y },&#xD;&#xA;        { p.z }&#xD;&#xA;        });&#xD;&#xA;    &#xD;&#xA;      return new PVector(rotated[0][0], rotated[1][0], rotated[2][0]);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d_x(PVector p, float a) {&#xD;&#xA;      return Rotate3d(p,&#xD;&#xA;        new float[][] {&#xD;&#xA;        {1, 0, 0},&#xD;&#xA;        {0, cos(a), -sin(a)},&#xD;&#xA;        {0, sin(a), cos(a)}&#xD;&#xA;        });&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d_y(PVector p, float a) {&#xD;&#xA;      return Rotate3d(p,&#xD;&#xA;        new float[][] {&#xD;&#xA;        {cos(a), 0, sin(a)},&#xD;&#xA;        {0, 1, 0},&#xD;&#xA;        {-sin(a), 0, cos(a)}&#xD;&#xA;        });&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d_z(PVector p, float a) {&#xD;&#xA;      return Rotate3d(p,&#xD;&#xA;        new float[][] {&#xD;&#xA;        {cos(a), -sin(a), 0},&#xD;&#xA;        {sin(a), cos(a), 0},&#xD;&#xA;        {0, 0, 1}&#xD;&#xA;        });&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d(PVector p, PVector a) {&#xD;&#xA;      return Rotate3d_z( Rotate3d_y(Rotate3d_x(p, a.x), a.y), a.z );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector applyPerspective(PVector p) {&#xD;&#xA;       PVector c = cam;&#xD;&#xA;       PVector co = cam_angle;&#xD;&#xA;       PVector e =  new PVector(0, 0, 100);&#xD;&#xA;      // c = camera position&#xD;&#xA;      // co = camera orientation / camera rotation&#xD;&#xA;      // e = displays surface pos relative to camera pinhole c&#xD;&#xA;    &#xD;&#xA;      // dx, dy, dz     https://en.wikipedia.org/wiki/3D_projection   :   Mathematical Formula&#xD;&#xA;      float[][] dxyz = matmul(&#xD;&#xA;        matmul(new float[][]{&#xD;&#xA;        {1, 0, 0},&#xD;&#xA;        {0, cos(co.x), sin(co.x)},&#xD;&#xA;        {0, -sin(co.x), cos(co.x)}&#xD;&#xA;        }, new float[][]{&#xD;&#xA;          {cos(co.y), 0, -sin(co.y)},&#xD;&#xA;          {0, 1, 0},&#xD;&#xA;          {sin(co.y), 0, cos(co.y)}&#xD;&#xA;        }),&#xD;&#xA;    &#xD;&#xA;        matmul(new float[][]{&#xD;&#xA;          {cos(co.z), sin(co.z), 0},&#xD;&#xA;          {-sin(co.z), cos(co.z), 0},&#xD;&#xA;          {0, 0, 1}&#xD;&#xA;        }, new float[][]{&#xD;&#xA;          {p.x - c.x},&#xD;&#xA;          {p.y - c.y},&#xD;&#xA;          {p.z - c.z},&#xD;&#xA;        }));&#xD;&#xA;    &#xD;&#xA;      PVector d = new PVector(dxyz[0][0], dxyz[1][0], dxyz[2][0]);&#xD;&#xA;    &#xD;&#xA;      return new PVector((e.z/d.z)*d.x+e.x, (e.z/d.z)*d.y+e.y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Matrixmultiplikation&#xD;&#xA;    float[][] matmul(float[][] m1, float[][] m2) {&#xD;&#xA;    &#xD;&#xA;      int cols_m1 = m1.length,&#xD;&#xA;        rows_m1 = m1[0].length;&#xD;&#xA;    &#xD;&#xA;      int cols_m2 = m2.length,&#xD;&#xA;        rows_m2 = m2[0].length;&#xD;&#xA;    &#xD;&#xA;      try {&#xD;&#xA;        if (rows_m1 != cols_m2) throw new Exception(&quot;Rows of m1 must match Columns of m2!&quot;);&#xD;&#xA;      }&#xD;&#xA;      catch(Exception e) {&#xD;&#xA;        println(e);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      float[][] res = new float[cols_m2][rows_m2];&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      for (int c=0; c &lt; cols_m1; c++) {&#xD;&#xA;    &#xD;&#xA;        for (int r2=0; r2 &lt; rows_m2; r2++) {&#xD;&#xA;    &#xD;&#xA;          float sum = 0;&#xD;&#xA;          float[] buf = new float[rows_m1];&#xD;&#xA;    &#xD;&#xA;          // Multiply rows of m1 with columns of m2 and store in buf&#xD;&#xA;          for (int r=0; r &lt; rows_m1; r++) {&#xD;&#xA;            buf[r] = m1[c][r]* m2[r][r2];&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;          // Add up all entries into sum&#xD;&#xA;          for (float entry : buf) {&#xD;&#xA;            sum += entry;&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;          res[c][r2] = sum;&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void draw() {&#xD;&#xA;      cam_angle = new PVector(0.01*(mouseY-width/2), 0.01*(mouseX-height/2), 0);&#xD;&#xA;      &#xD;&#xA;      background(255);&#xD;&#xA;      translate(width/2, height/2);&#xD;&#xA;      strokeWeight(1);&#xD;&#xA;      fill(0);&#xD;&#xA;    &#xD;&#xA;      PVector[] points_projected = new PVector[points.length];&#xD;&#xA;    &#xD;&#xA;      for (int i=0; i &lt; points.length; i++) {&#xD;&#xA;        points_projected[i] =   applyPerspective(points[i]);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      &#xD;&#xA;      for (int i=0; i &lt; points_projected.length; i++) {    &#xD;&#xA;        for (int a=0; a &lt; points_projected.length; a++) {&#xD;&#xA;          // Alle Punkte verbinden&#xD;&#xA;          line(points_projected[i].x, points_projected[i].y, points_projected[a].x, points_projected[a].y);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void keyPressed() {&#xD;&#xA;      if (key == 'w') {&#xD;&#xA;        cam.add(Rotate3d(new PVector(0, 0, -20), cam_angle));&#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      if (key == 'a') {&#xD;&#xA;        cam.add(Rotate3d(new PVector(20, 0, 0), cam_angle));&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      if (key == 's') {&#xD;&#xA;        cam.add(Rotate3d(new PVector(0, 0, 20), cam_angle));&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      if (key == 'd') {&#xD;&#xA;       cam.add(Rotate3d(new PVector(-20, 0, 0), cam_angle));&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      &#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="39009" PostHistoryTypeId="2" PostId="13109" RevisionGUID="1ac4d930-b1e8-4968-8aae-4efc0ddc8df7" CreationDate="2022-11-14T14:14:42.247" UserId="7952" Text="After a quick look at your code, it looks like the &quot;projection&quot; is being recomputed continuously. A projection matrix is generally computed and saved, then only rarely updated. The same can be said about the model matrix but may be updated more frequently. The camera view matrix is updated whenever the camera moves.&#xD;&#xA;&#xD;&#xA;The Model, View, Projection matrix forms the MVP that is applied to every point.&#xD;&#xA;&#xD;&#xA;The loop then looks something along the lines of:&#xD;&#xA;&#xD;&#xA;    // setup the model and projection matrices and set aside&#xD;&#xA;    mat4 projection = MakeProjection( projection_values);&#xD;&#xA;    mat4 model =  GetModelMatrix(which_model);&#xD;&#xA;&#xD;&#xA;and then in the render loop&#xD;&#xA;&#xD;&#xA;    mat4 view = updateViewMatrix();&#xD;&#xA;    mat4 mvp = model * view * projection;&#xD;&#xA;&#xD;&#xA;    for( every point ) { &#xD;&#xA;        draw_points[point_num] = mvp * model_points[point_num];&#xD;&#xA;    }&#xD;&#xA;    // draw all the points&#xD;&#xA;&#xD;&#xA;I suggest this approach partly because it makes what is happening with the math very clear and easy to read. While the code is still fairly clear. It doesn't update the projection or model matrices ever but that's okay for a first basic loop. In fact you may want to just use the identity matrix for the model matrix. It also gives plenty of opportunities to break in the debugger and inspect values to see if they are what is expected.&#xD;&#xA;    &#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="39011" PostHistoryTypeId="2" PostId="13110" RevisionGUID="cd4c7030-d44c-49a2-ba82-fbe92375844c" CreationDate="2022-11-15T11:49:30.733" UserId="7952" Text="The generic term for multiple outputs from a fragment shader is MRT (multiple render targets).&#xD;&#xA;&#xD;&#xA;The fragment shader setup code is something along the lines of:&#xD;&#xA;&#xD;&#xA;    layout( location=0 ) out vec4 colorOutput;&#xD;&#xA;    layout( location=1 ) out vec4 outVelocity; // names are abritrary&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Output 0 would replace the default gl_FragColor assignment. Then later to assign values it is simply:&#xD;&#xA;&#xD;&#xA;    colorOutput = vec4(color,1);&#xD;&#xA;    outVelocity = vec4(velocityResults, 0, 0);&#xD;&#xA;&#xD;&#xA;In the opengl setup code the layout locations correspond to the buffers that are created.&#xD;&#xA;&#xD;&#xA;Creating the framebuffers is just the usual glGenFrameBuffer, glBindFrameBuffer. Using the java code extensions. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="39013" PostHistoryTypeId="4" PostId="13108" RevisionGUID="bd663949-cc4f-4950-863e-4db5b34472c5" CreationDate="2022-11-15T13:03:20.943" UserId="7952" Comment="minor type fixes" Text="Output to more than one canvas texture in processing with shader OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="39027" PostHistoryTypeId="2" PostId="13113" RevisionGUID="28352fb4-aff9-408a-9e1f-64301882e159" CreationDate="2022-11-17T12:29:39.363" UserId="19223" Text="I'm working on a glTF, precisely I'm trying to animate a &quot;static&quot; mesh exported from Blender directly acting on its JSON.&#xD;&#xA;In doing so, I'm following the logic used in this [tutorial](https://github.com/javagl/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_006_SimpleAnimation.md) , where a triangle is animated adding a new buffer, containing only data regarding time and rotation coordinates. Along with the new buffer, also the animations array, the bufferviews related to the new buffer, and the new accessors are added to animate the initial static [triangle](https://github.com/javagl/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_003_MinimalGltfFile.md) .&#xD;&#xA;&#xD;&#xA;Right now, I'm trying to animate a plane, working on the [input JSON](https://github.com/Ludovicolin/LL/blob/main/STATIC_PLANE.JSON) obtained by simply creating the plane in Blender and exporting it in the glTF format. Using the same data URI seen in the previously mentioned tutorial regarding the rotating triangle: &#xD;&#xA;&#xD;&#xA;{&#xD;&#xA;            &quot;byteLength&quot;: 100,&#xD;&#xA;            &quot;uri&quot;: &quot;data:application/octet-stream;base64,AAAAAAAAgD4AAAA/AABAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAPT9ND/0/TS/AAAAAAAAAAAAAAAAAACAPw==&quot;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;I've been able to apply successfully that rotation to the [plane](https://github.com/Ludovicolin/LL/blob/main/DYNAMIC_PLANE.JSON) .&#xD;&#xA;  &#xD;&#xA;The problem is that, always following the same logic, I'm having hard times in creating animations different from the one that is used in the tutorial so, basically I'm having problems in creating data URI containing information about time and animation.&#xD;&#xA;The procedure I'm using in creating those data URIs, consists of writing times and coordinates in a file saved with no extension (to have a generic binary data application/octet-stream) , and then converting this file in a data URI with an [online converter](https://www.adminbooster.com/tool/data_uri) .&#xD;&#xA;&#xD;&#xA;[Here](https://github.com/Ludovicolin/LL/blob/main/TIME+COORDINATES) you can see how I write the file to be converted in data URI that contains coordinates and time, and [here](https://github.com/Ludovicolin/LL/blob/main/1B_TRANSLATION_PLANE.JSON) you can see how the translation written in previous link doesn't work in the initial glTF of the plane. I suppose the error is the way i write the time and coordinates. How should I write those coordinates and time to be converted in data URI to be properly read and executed by the glTF?&#xD;&#xA;&#xD;&#xA;I've even tried to separate time and coordinates by creating two different buffers, one referring to time and one referring to animation, to avoid the problem of making mistakes in setting the byteOffset property in the accessors referring to animation and time.&#xD;&#xA;[Here](https://github.com/Ludovicolin/LL/blob/main/2B_DYNAMIC_TRANSLATION_PLANE.JSON) you can see the code of a translation applied to the same plane using the two new buffers referring to time and translation.  &#xD;&#xA;The structure of the starting file, later converted in data URI, containing information regarding time follows:  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;(0.0),  &#xD;&#xA;(0.25),  &#xD;&#xA;(0.5),  &#xD;&#xA;(0.75),  &#xD;&#xA;(1.0)  &#xD;&#xA;&#xD;&#xA;The structure of the starting file, later converted in data URI, containing the translation coordinates follows:   &#xD;&#xA;&#xD;&#xA;{ 0.0, 0.0, 0.0 },  &#xD;&#xA;{ 2.0, 0.0, 0.0 },  &#xD;&#xA;{ 6.0, 0.0, 0.0 },  &#xD;&#xA;{ 6.0, 2.0, 0.0 },  &#xD;&#xA;{ 8.0, 4.0, 0.0 }  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks in advance for your help :) " ContentLicense="CC BY-SA 4.0" />
  <row Id="39029" PostHistoryTypeId="1" PostId="13113" RevisionGUID="28352fb4-aff9-408a-9e1f-64301882e159" CreationDate="2022-11-17T12:29:39.363" UserId="19223" Text="Starting from a basic glTF (such as a static sphere or plane) exported from Blender how can I add an animation manipulating its JSON?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39030" PostHistoryTypeId="3" PostId="13113" RevisionGUID="28352fb4-aff9-408a-9e1f-64301882e159" CreationDate="2022-11-17T12:29:39.363" UserId="19223" Text="|rendering|3d|animation|buffers|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39031" PostHistoryTypeId="6" PostId="13113" RevisionGUID="12f19c1c-344b-4ebd-ae2b-94db5e16cf91" CreationDate="2022-11-17T15:21:18.170" UserId="2654" Comment="edited tags" Text="|3d|animation|buffers|gltf|blender|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39042" PostHistoryTypeId="5" PostId="13107" RevisionGUID="c4e32c3d-6bc8-468a-b92f-3033906b4a74" CreationDate="2022-11-19T06:38:22.120" UserId="6546" Comment="Grammar and Spelling" Text="Unfortunately, I always had problems with math and was never good at it. I'm currently trying to combine math with my knowledge and my passion for programming.&#xD;&#xA;&#xD;&#xA;Brief introduction: In math, we have currently arrived at the topic of matrix multiplication and 3D projection, which sounds more interesting to me as an enthusiastic programmer than the whole thing with abstract number theories.&#xD;&#xA;So I set myself the goal of programming a small 3D game in Processing (Java). My first success was rotating a Cube in 3 dimensions.&#xD;&#xA;&#xD;&#xA;Goal: After that I wanted to have a perspective for three-dimensional space.  I took the 3D projection matrix from here: https://en.m.wikipedia.org/wiki/3D_projection : Mathematical Formula.&#xD;&#xA;&#xD;&#xA;Problem: I noticed that when I rotate the camera, the projection (the box in this case) flips horizontally and vertically.&#xD;&#xA;&#xD;&#xA;video here: https://www.youtube.com/watch?v=_xrSYmCa_FQ&#xD;&#xA;&#xD;&#xA;What is happening (timestamp 0:14) and how can I fix it?&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;    import java.util.Arrays;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector[] points;&#xD;&#xA;    &#xD;&#xA;    PVector cam, cam_angle, point;&#xD;&#xA;    &#xD;&#xA;    float angle = 0.0;&#xD;&#xA;    &#xD;&#xA;    void setup() {&#xD;&#xA;      //fullScreen();  &#xD;&#xA;      &#xD;&#xA;      size(1000,400);&#xD;&#xA;      noCursor();&#xD;&#xA;    &#xD;&#xA;      cam = point = new PVector(0, 0, -1000);&#xD;&#xA;      cam_angle = new PVector(0,0,0);&#xD;&#xA;    &#xD;&#xA;      points = new PVector[] {&#xD;&#xA;        new PVector(-100, -100, -100),&#xD;&#xA;        new PVector(-100, -100, 100),&#xD;&#xA;        new PVector(-100, 100, -100),&#xD;&#xA;        new PVector(-100, 100, 100),&#xD;&#xA;        new PVector( 100, -100, -100),&#xD;&#xA;        new PVector( 100, -100, 100),&#xD;&#xA;        new PVector( 100, 100, -100),&#xD;&#xA;        new PVector( 100, 100, 100),&#xD;&#xA;      };&#xD;&#xA;      &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector Rotate2d(PVector p, float a) {&#xD;&#xA;      // a = angle&#xD;&#xA;    &#xD;&#xA;      float[][] m2 = {&#xD;&#xA;        {cos(a), -sin(a)},&#xD;&#xA;        {sin(a), cos(a)}&#xD;&#xA;      };&#xD;&#xA;    &#xD;&#xA;      float[][] rotated = matmul(m2, new float[][] {&#xD;&#xA;        { p.x },&#xD;&#xA;        { p.y }&#xD;&#xA;        });&#xD;&#xA;    &#xD;&#xA;      return new PVector(rotated[0][0], rotated[1][0]);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d(PVector p, float[][] m2) {&#xD;&#xA;    &#xD;&#xA;      float[][] rotated = matmul(m2, new float[][] {&#xD;&#xA;        { p.x },&#xD;&#xA;        { p.y },&#xD;&#xA;        { p.z }&#xD;&#xA;        });&#xD;&#xA;    &#xD;&#xA;      return new PVector(rotated[0][0], rotated[1][0], rotated[2][0]);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d_x(PVector p, float a) {&#xD;&#xA;      return Rotate3d(p,&#xD;&#xA;        new float[][] {&#xD;&#xA;        {1, 0, 0},&#xD;&#xA;        {0, cos(a), -sin(a)},&#xD;&#xA;        {0, sin(a), cos(a)}&#xD;&#xA;        });&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d_y(PVector p, float a) {&#xD;&#xA;      return Rotate3d(p,&#xD;&#xA;        new float[][] {&#xD;&#xA;        {cos(a), 0, sin(a)},&#xD;&#xA;        {0, 1, 0},&#xD;&#xA;        {-sin(a), 0, cos(a)}&#xD;&#xA;        });&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d_z(PVector p, float a) {&#xD;&#xA;      return Rotate3d(p,&#xD;&#xA;        new float[][] {&#xD;&#xA;        {cos(a), -sin(a), 0},&#xD;&#xA;        {sin(a), cos(a), 0},&#xD;&#xA;        {0, 0, 1}&#xD;&#xA;        });&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    PVector Rotate3d(PVector p, PVector a) {&#xD;&#xA;      return Rotate3d_z( Rotate3d_y(Rotate3d_x(p, a.x), a.y), a.z );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    PVector applyPerspective(PVector p) {&#xD;&#xA;       PVector c = cam;&#xD;&#xA;       PVector co = cam_angle;&#xD;&#xA;       PVector e =  new PVector(0, 0, 100);&#xD;&#xA;      // c = camera position&#xD;&#xA;      // co = camera orientation / camera rotation&#xD;&#xA;      // e = displays surface pos relative to camera pinhole c&#xD;&#xA;    &#xD;&#xA;      // dx, dy, dz     https://en.wikipedia.org/wiki/3D_projection   :   Mathematical Formula&#xD;&#xA;      float[][] dxyz = matmul(&#xD;&#xA;        matmul(new float[][]{&#xD;&#xA;        {1, 0, 0},&#xD;&#xA;        {0, cos(co.x), sin(co.x)},&#xD;&#xA;        {0, -sin(co.x), cos(co.x)}&#xD;&#xA;        }, new float[][]{&#xD;&#xA;          {cos(co.y), 0, -sin(co.y)},&#xD;&#xA;          {0, 1, 0},&#xD;&#xA;          {sin(co.y), 0, cos(co.y)}&#xD;&#xA;        }),&#xD;&#xA;    &#xD;&#xA;        matmul(new float[][]{&#xD;&#xA;          {cos(co.z), sin(co.z), 0},&#xD;&#xA;          {-sin(co.z), cos(co.z), 0},&#xD;&#xA;          {0, 0, 1}&#xD;&#xA;        }, new float[][]{&#xD;&#xA;          {p.x - c.x},&#xD;&#xA;          {p.y - c.y},&#xD;&#xA;          {p.z - c.z},&#xD;&#xA;        }));&#xD;&#xA;    &#xD;&#xA;      PVector d = new PVector(dxyz[0][0], dxyz[1][0], dxyz[2][0]);&#xD;&#xA;    &#xD;&#xA;      return new PVector((e.z/d.z)*d.x+e.x, (e.z/d.z)*d.y+e.y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    // Matrixmultiplikation&#xD;&#xA;    float[][] matmul(float[][] m1, float[][] m2) {&#xD;&#xA;    &#xD;&#xA;      int cols_m1 = m1.length,&#xD;&#xA;        rows_m1 = m1[0].length;&#xD;&#xA;    &#xD;&#xA;      int cols_m2 = m2.length,&#xD;&#xA;        rows_m2 = m2[0].length;&#xD;&#xA;    &#xD;&#xA;      try {&#xD;&#xA;        if (rows_m1 != cols_m2) throw new Exception(&quot;Rows of m1 must match Columns of m2!&quot;);&#xD;&#xA;      }&#xD;&#xA;      catch(Exception e) {&#xD;&#xA;        println(e);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      float[][] res = new float[cols_m2][rows_m2];&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;      for (int c=0; c &lt; cols_m1; c++) {&#xD;&#xA;    &#xD;&#xA;        for (int r2=0; r2 &lt; rows_m2; r2++) {&#xD;&#xA;    &#xD;&#xA;          float sum = 0;&#xD;&#xA;          float[] buf = new float[rows_m1];&#xD;&#xA;    &#xD;&#xA;          // Multiply rows of m1 with columns of m2 and store in buf&#xD;&#xA;          for (int r=0; r &lt; rows_m1; r++) {&#xD;&#xA;            buf[r] = m1[c][r]* m2[r][r2];&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;          // Add up all entries into sum&#xD;&#xA;          for (float entry : buf) {&#xD;&#xA;            sum += entry;&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;          res[c][r2] = sum;&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      return res;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void draw() {&#xD;&#xA;      cam_angle = new PVector(0.01*(mouseY-width/2), 0.01*(mouseX-height/2), 0);&#xD;&#xA;      &#xD;&#xA;      background(255);&#xD;&#xA;      translate(width/2, height/2);&#xD;&#xA;      strokeWeight(1);&#xD;&#xA;      fill(0);&#xD;&#xA;    &#xD;&#xA;      PVector[] points_projected = new PVector[points.length];&#xD;&#xA;    &#xD;&#xA;      for (int i=0; i &lt; points.length; i++) {&#xD;&#xA;        points_projected[i] =   applyPerspective(points[i]);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      &#xD;&#xA;      for (int i=0; i &lt; points_projected.length; i++) {    &#xD;&#xA;        for (int a=0; a &lt; points_projected.length; a++) {&#xD;&#xA;          // Alle Punkte verbinden&#xD;&#xA;          line(points_projected[i].x, points_projected[i].y, points_projected[a].x, points_projected[a].y);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void keyPressed() {&#xD;&#xA;      if (key == 'w') {&#xD;&#xA;        cam.add(Rotate3d(new PVector(0, 0, -20), cam_angle));&#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      if (key == 'a') {&#xD;&#xA;        cam.add(Rotate3d(new PVector(20, 0, 0), cam_angle));&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      if (key == 's') {&#xD;&#xA;        cam.add(Rotate3d(new PVector(0, 0, 20), cam_angle));&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      if (key == 'd') {&#xD;&#xA;       cam.add(Rotate3d(new PVector(-20, 0, 0), cam_angle));&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;      &#xD;&#xA;      &#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="39043" PostHistoryTypeId="24" PostId="13107" RevisionGUID="c4e32c3d-6bc8-468a-b92f-3033906b4a74" CreationDate="2022-11-19T06:38:22.120" Comment="Proposed by 6546 approved by 13095 edit id of 603" ContentLicense="CC BY-SA 4.0" />
  <row Id="39045" PostHistoryTypeId="5" PostId="13102" RevisionGUID="9d6a5434-95a2-4fba-b1d3-630dd71da5e6" CreationDate="2022-11-19T16:14:14.673" UserId="19180" Comment="syntax highlighting" Text="One thing that is mathematically sound is to grab a gltf model and apply some arbitrary linear transformation to it, like a rotation or a translation. &#xD;&#xA;&#xD;&#xA;Let's say the transformation is encoded as a 4x4 homogeneous matrix.&#xD;&#xA;&#xD;&#xA;I think it needs to be applied to the meshes, nodes, ibms in the skins, and animations.&#xD;&#xA;&#xD;&#xA;Starting simple, I want to apply it to only the meshes.&#xD;&#xA;&#xD;&#xA;i.e. something like this:&#xD;&#xA;```rust&#xD;&#xA;for mesh in &amp; self.meshes&#xD;&#xA;{&#xD;&#xA;    for primitive in &amp; mesh.primitives&#xD;&#xA;    {&#xD;&#xA;        for position in self&#xD;&#xA;            .data_from_accessor:: &lt;Vec3&gt;(primitive.attributes.position)&#xD;&#xA;                .unwrap()&#xD;&#xA;                {&#xD;&#xA;            * position = transform_vec3(&amp;position, &amp;transform, true);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;                for normal in self&#xD;&#xA;                .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.normal)&#xD;&#xA;                    .unwrap()&#xD;&#xA;                    {&#xD;&#xA;            * normal = transform_vec3(&amp;normal, &amp;transform, false);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is ok and yields:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Ok now I want to apply to the nodes, so I attempt this:&#xD;&#xA;```rust&#xD;&#xA;for node in &amp;mut self.nodes&#xD;&#xA;{&#xD;&#xA;    let mut mat : Mat4 = compose_homogeneous(&amp;node.scale, &amp;node.rotation, &amp;node.translation);&#xD;&#xA;    mat = transform * mat;&#xD;&#xA;&#xD;&#xA;    let (new_scale, new_rot, new_trans) = decompose_homogeneous(&amp;mat);&#xD;&#xA;&#xD;&#xA;    node.rotation = new_rot;&#xD;&#xA;    node.translation = new_trans;&#xD;&#xA;    node.scale = new_scale;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now gltf viewers show this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Why?&#xD;&#xA;&#xD;&#xA;I have tested things and both `compose_homogeneous` and `decompose_homogeneous` are correct. Why am I getting this degenerate output?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HfnWU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/U3Pn1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39046" PostHistoryTypeId="24" PostId="13102" RevisionGUID="9d6a5434-95a2-4fba-b1d3-630dd71da5e6" CreationDate="2022-11-19T16:14:14.673" Comment="Proposed by 19180 approved by 13095 edit id of 604" ContentLicense="CC BY-SA 4.0" />
  <row Id="39047" PostHistoryTypeId="50" PostId="7804" RevisionGUID="73b46df1-0df9-4c4f-94a9-27f5f011fe07" CreationDate="2022-11-19T20:03:05.333" UserId="-1" />
  <row Id="39048" PostHistoryTypeId="50" PostId="9626" RevisionGUID="c1bf2597-d4d2-422d-975f-eee86a60d9b7" CreationDate="2022-11-20T16:07:00.767" UserId="-1" />
  <row Id="39049" PostHistoryTypeId="50" PostId="9307" RevisionGUID="51df221f-4507-439a-bf54-683e2e02ea97" CreationDate="2022-11-20T22:02:05.293" UserId="-1" />
  <row Id="39050" PostHistoryTypeId="8" PostId="13102" RevisionGUID="a9ef9b6c-d37e-481d-9439-f185899f3c36" CreationDate="2022-11-21T07:45:01.363" UserId="7462" Comment="Rollback to [cefa1507-a706-47a4-b0bd-60355e17edb6] - Edit approval overridden by post owner or moderator" Text="One thing that is mathematically sound is to grab a gltf model and apply some arbitrary linear transformation to it, like a rotation or a translation. &#xD;&#xA;&#xD;&#xA;Let's say the transformation is encoded as a 4x4 homogeneous matrix.&#xD;&#xA;&#xD;&#xA;I think it needs to be applied to the meshes, nodes, ibms in the skins, and animations.&#xD;&#xA;&#xD;&#xA;Starting simple, I want to apply it to only the meshes.&#xD;&#xA;&#xD;&#xA;i.e. something like this:&#xD;&#xA;```rust&#xD;&#xA;        for mesh in &amp;self.meshes&#xD;&#xA;        {&#xD;&#xA;            for primitive in &amp;mesh.primitives&#xD;&#xA;            {&#xD;&#xA;                for position in self&#xD;&#xA;                    .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.position)&#xD;&#xA;                    .unwrap()&#xD;&#xA;                {&#xD;&#xA;                    *position = transform_vec3(&amp;position, &amp;transform, true);&#xD;&#xA;                }&#xD;&#xA;&#xD;&#xA;                for normal in self&#xD;&#xA;                    .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.normal)&#xD;&#xA;                    .unwrap()&#xD;&#xA;                {&#xD;&#xA;                    *normal = transform_vec3(&amp;normal, &amp;transform, false);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;   ```&#xD;&#xA;&#xD;&#xA;This is ok and yields:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Ok now I want to apply to the nodes, so I attempt this:&#xD;&#xA;```&#xD;&#xA;        for node in &amp;mut self.nodes&#xD;&#xA;        {&#xD;&#xA;            let mut mat : Mat4 = compose_homogeneous(&amp;node.scale, &amp;node.rotation, &amp;node.translation);&#xD;&#xA;            mat = transform * mat;&#xD;&#xA;&#xD;&#xA;            let (new_scale, new_rot, new_trans) = decompose_homogeneous(&amp;mat);&#xD;&#xA;&#xD;&#xA;            node.rotation = new_rot;&#xD;&#xA;            node.translation = new_trans;&#xD;&#xA;            node.scale = new_scale;&#xD;&#xA;        }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now gltf viewers show this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Why?&#xD;&#xA;&#xD;&#xA;I have tested things and both `compose_homogeneous` and `decompose_homogeneous` are correct. Why am I getting this degenerate output?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HfnWU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/U3Pn1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39051" PostHistoryTypeId="2" PostId="13116" RevisionGUID="1c4cb817-0719-4073-aee6-9ee320cda95f" CreationDate="2022-11-21T12:11:59.957" UserId="19236" Text="## Problem description&#xD;&#xA;When comparing Cornell Box image generated by my path tracer I noticed that colors are much more sharp/saturated (don't know specific term) than they should be. Comparison (on the left mine and on the right how it should look - shadows are darker and color bleeding looks unnatural, mainly because of clear green line on the floor next to small box):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5XW69.jpg&#xD;&#xA;&#xD;&#xA;## Implementation (OpenCL/C)&#xD;&#xA;### Main logic&#xD;&#xA;```&#xD;&#xA;const float3 intersectionPoint = ray-&gt;origin + hit.tNearest * ray-&gt;direction;&#xD;&#xA;        const float3 normal = interpolate3(triangle-&gt;v0.normal, triangle-&gt;v1.normal, triangle-&gt;v2.normal, hit.u, hit.v);&#xD;&#xA;        &#xD;&#xA;        // direct lighting&#xD;&#xA;        {&#xD;&#xA;            const float y = 1.985f;&#xD;&#xA;            const float factor = 0.15f;&#xD;&#xA;            const float3 v1 = (float3)( factor, y,  factor);&#xD;&#xA;            const float3 v2 = (float3)(-factor, y, -factor);&#xD;&#xA;            &#xD;&#xA;            Light light;&#xD;&#xA;            light.position = (float3)(factor, y, -factor);&#xD;&#xA;            light.emission = (float3)(17.0f, 12.0f, 4.0f);&#xD;&#xA;            light.u        = v1 - light.position;&#xD;&#xA;            light.v        = v2 - light.position;&#xD;&#xA;            light.area     = length(cross(light.u, light.v));&#xD;&#xA;            &#xD;&#xA;            float3 scatterPosition = intersectionPoint + normal * FLT_EPSILON;&#xD;&#xA;            LightSample lightSample = sample_rectangle_light(&amp;light, scatterPosition, &amp;seed);&#xD;&#xA;&#xD;&#xA;            float3 Ld = 0.0f;&#xD;&#xA;            float3 Li = lightSample.emission;&#xD;&#xA;            if (dot(lightSample.direction, lightSample.normal) &lt; 0.0f) {&#xD;&#xA;                Ray shadowRay;&#xD;&#xA;                shadowRay.origin = scatterPosition;&#xD;&#xA;                shadowRay.direction = lightSample.direction;&#xD;&#xA;                Hit shadowHit = intersect_ray_bvh(&amp;shadowRay, bvhNodes, triangles);&#xD;&#xA;&#xD;&#xA;                if (shadowHit.tNearest &gt; lightSample.distance - FLT_EPSILON) {&#xD;&#xA;                    ScatterSample scatterSample = evaluate_lambert(material, normal, lightSample.direction);&#xD;&#xA;                    if (scatterSample.pdf &gt; 0.0f) {&#xD;&#xA;                        Ld = Ld + ((Li * scatterSample.f) / lightSample.pdf);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        &#xD;&#xA;            radiance[index] += Ld * throughput;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        ScatterSample scatterSample;&#xD;&#xA;        scatterSample = sample_lambert(material, normal, &amp;seed);&#xD;&#xA;        if (scatterSample.pdf &gt; 0.0f) {&#xD;&#xA;            throughput = (throughput * scatterSample.f) / scatterSample.pdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        ray-&gt;direction = scatterSample.L;&#xD;&#xA;        ray-&gt;origin = intersectionPoint + ray-&gt;direction * FLT_EPSILON;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Rectangle light sampling&#xD;&#xA;```&#xD;&#xA;LightSample sample_rectangle_light(const Light *light, const float3 scatterPosition, uint2 *seed) {&#xD;&#xA;    const uint lightsCount = 1u;&#xD;&#xA;    const float2 random = get_random_numbers(seed);&#xD;&#xA;    const float3 lightSurfacePosition = light-&gt;position + light-&gt;u * random.x + light-&gt;v * random.y;&#xD;&#xA;&#xD;&#xA;    LightSample result;&#xD;&#xA;    result.normal = normalize(cross(light-&gt;u, light-&gt;v));&#xD;&#xA;    result.emission = light-&gt;emission * (float)lightsCount;&#xD;&#xA;    result.direction = lightSurfacePosition - scatterPosition;&#xD;&#xA;    result.distance = length(result.direction);&#xD;&#xA;    result.direction /= result.distance;&#xD;&#xA;&#xD;&#xA;    float distanceSquared = result.distance * result.distance;&#xD;&#xA;    result.pdf = distanceSquared / (light-&gt;area * fabs(dot(result.normal, result.direction)));&#xD;&#xA;&#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Lambert BSDF&#xD;&#xA;```&#xD;&#xA;ScatterSample evaluate_lambert(const Material *material, const float3 normal, const float3 L) {&#xD;&#xA;    ScatterSample result;&#xD;&#xA;    result.pdf = dot(normal, L) * M_1_PI_F;&#xD;&#xA;    result.f = M_1_PI_F * material-&gt;diffuse * dot(normal, L);&#xD;&#xA;&#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ScatterSample sample_lambert(const Material *material, const float3 normal, uint2 *seed) {&#xD;&#xA;    const float2 random = get_random_numbers(seed);&#xD;&#xA;&#xD;&#xA;    ScatterSample result;&#xD;&#xA;    result.L = sample_hemisphere(normal, random);&#xD;&#xA;    result.f = M_1_PI_F * material-&gt;diffuse * dot(normal, result.L);&#xD;&#xA;    result.pdf = dot(normal, result.L) * M_1_PI_F;&#xD;&#xA;    &#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## Culprit&#xD;&#xA;It might be the hardcoded rectangle light that causes this effect but I'm not sure because manipulating its position/area didn't change much." ContentLicense="CC BY-SA 4.0" />
  <row Id="39053" PostHistoryTypeId="1" PostId="13116" RevisionGUID="1c4cb817-0719-4073-aee6-9ee320cda95f" CreationDate="2022-11-21T12:11:59.957" UserId="19236" Text="Path tracing - colors/shadows sharper than they should be" ContentLicense="CC BY-SA 4.0" />
  <row Id="39054" PostHistoryTypeId="3" PostId="13116" RevisionGUID="1c4cb817-0719-4073-aee6-9ee320cda95f" CreationDate="2022-11-21T12:11:59.957" UserId="19236" Text="|pathtracing|lighting|opencl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39055" PostHistoryTypeId="5" PostId="13116" RevisionGUID="44fb2240-09dc-43be-8c21-e4be60cb4ff4" CreationDate="2022-11-21T12:25:22.867" UserId="19236" Comment="added 178 characters in body" Text="## Problem description&#xD;&#xA;When comparing Cornell Box image generated by my path tracer I noticed that colors are much more sharp/saturated (don't know specific term) than they should be. Comparison (on the left mine and on the right how it should look - shadows are darker and color bleeding looks unnatural, mainly because of clear green line on the floor next to small box):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5XW69.jpg&#xD;&#xA;&#xD;&#xA;## Implementation (OpenCL/C)&#xD;&#xA;### Main logic&#xD;&#xA;```&#xD;&#xA;const float3 intersectionPoint = ray-&gt;origin + hit.tNearest * ray-&gt;direction;&#xD;&#xA;        const float3 normal = interpolate3(triangle-&gt;v0.normal, triangle-&gt;v1.normal, triangle-&gt;v2.normal, hit.u, hit.v);&#xD;&#xA;        &#xD;&#xA;        // direct lighting&#xD;&#xA;        {&#xD;&#xA;            const float y = 1.985f;&#xD;&#xA;            const float factor = 0.15f;&#xD;&#xA;            const float3 v1 = (float3)( factor, y,  factor);&#xD;&#xA;            const float3 v2 = (float3)(-factor, y, -factor);&#xD;&#xA;            &#xD;&#xA;            Light light;&#xD;&#xA;            light.position = (float3)(factor, y, -factor);&#xD;&#xA;            light.emission = (float3)(17.0f, 12.0f, 4.0f);&#xD;&#xA;            light.u        = v1 - light.position;&#xD;&#xA;            light.v        = v2 - light.position;&#xD;&#xA;            light.area     = length(cross(light.u, light.v));&#xD;&#xA;            &#xD;&#xA;            float3 scatterPosition = intersectionPoint + normal * FLT_EPSILON;&#xD;&#xA;            LightSample lightSample = sample_rectangle_light(&amp;light, scatterPosition, &amp;seed);&#xD;&#xA;&#xD;&#xA;            float3 Ld = 0.0f;&#xD;&#xA;            float3 Li = lightSample.emission;&#xD;&#xA;            if (dot(lightSample.direction, lightSample.normal) &lt; 0.0f) {&#xD;&#xA;                Ray shadowRay;&#xD;&#xA;                shadowRay.origin = scatterPosition;&#xD;&#xA;                shadowRay.direction = lightSample.direction;&#xD;&#xA;                Hit shadowHit = intersect_ray_bvh(&amp;shadowRay, bvhNodes, triangles);&#xD;&#xA;&#xD;&#xA;                if (shadowHit.tNearest &gt; lightSample.distance - FLT_EPSILON) {&#xD;&#xA;                    ScatterSample scatterSample = evaluate_lambert(material, normal, lightSample.direction);&#xD;&#xA;                    if (scatterSample.pdf &gt; 0.0f) {&#xD;&#xA;                        Ld = Ld + ((Li * scatterSample.f) / lightSample.pdf);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        &#xD;&#xA;            radiance[index] += Ld * throughput;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        ScatterSample scatterSample;&#xD;&#xA;        scatterSample = sample_lambert(material, normal, &amp;seed);&#xD;&#xA;        if (scatterSample.pdf &gt; 0.0f) {&#xD;&#xA;            throughput = (throughput * scatterSample.f) / scatterSample.pdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        ray-&gt;direction = scatterSample.L;&#xD;&#xA;        ray-&gt;origin = intersectionPoint + ray-&gt;direction * FLT_EPSILON;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Rectangle light sampling&#xD;&#xA;```&#xD;&#xA;LightSample sample_rectangle_light(const Light *light, const float3 scatterPosition, uint2 *seed) {&#xD;&#xA;    const uint lightsCount = 1u;&#xD;&#xA;    const float2 random = get_random_numbers(seed);&#xD;&#xA;    const float3 lightSurfacePosition = light-&gt;position + light-&gt;u * random.x + light-&gt;v * random.y;&#xD;&#xA;&#xD;&#xA;    LightSample result;&#xD;&#xA;    result.normal = normalize(cross(light-&gt;u, light-&gt;v));&#xD;&#xA;    result.emission = light-&gt;emission * (float)lightsCount;&#xD;&#xA;    result.direction = lightSurfacePosition - scatterPosition;&#xD;&#xA;    result.distance = length(result.direction);&#xD;&#xA;    result.direction /= result.distance;&#xD;&#xA;&#xD;&#xA;    float distanceSquared = result.distance * result.distance;&#xD;&#xA;    result.pdf = distanceSquared / (light-&gt;area * fabs(dot(result.normal, result.direction)));&#xD;&#xA;&#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Lambert BSDF&#xD;&#xA;```&#xD;&#xA;ScatterSample evaluate_lambert(const Material *material, const float3 normal, const float3 L) {&#xD;&#xA;    ScatterSample result;&#xD;&#xA;    result.pdf = dot(normal, L) * M_1_PI_F;&#xD;&#xA;    result.f = M_1_PI_F * material-&gt;diffuse * dot(normal, L);&#xD;&#xA;&#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ScatterSample sample_lambert(const Material *material, const float3 normal, uint2 *seed) {&#xD;&#xA;    const float2 random = get_random_numbers(seed);&#xD;&#xA;&#xD;&#xA;    ScatterSample result;&#xD;&#xA;    result.L = sample_hemisphere(normal, random);&#xD;&#xA;    result.f = M_1_PI_F * material-&gt;diffuse * dot(normal, result.L);&#xD;&#xA;    result.pdf = dot(normal, result.L) * M_1_PI_F;&#xD;&#xA;    &#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Gamma correction&#xD;&#xA;```&#xD;&#xA;float3 color = (radiance[index] + read_imagef(imagePlane, (int2)(x, y)).xyz) / (float)sampleCount;&#xD;&#xA;color = pow(color, (float3)(1.0f / 2.2f));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## Culprit&#xD;&#xA;It might be the hardcoded rectangle light that causes this effect but I'm not sure because manipulating its position/area didn't change much." ContentLicense="CC BY-SA 4.0" />
  <row Id="39056" PostHistoryTypeId="5" PostId="13116" RevisionGUID="e067ef5f-a611-4fd8-856b-3ee039e01fad" CreationDate="2022-11-21T18:58:34.223" UserId="19236" Comment="added 299 characters in body" Text="## Problem description&#xD;&#xA;When comparing Cornell Box image generated by my path tracer I noticed that colors are much more sharp/saturated (don't know specific term) than they should be. Comparison (on the left mine and on the right how it should look - shadows are darker and color bleeding looks unnatural, mainly because of clear green line on the floor next to small box):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## Implementation (OpenCL/C)&#xD;&#xA;### Main logic&#xD;&#xA;```&#xD;&#xA;const float3 intersectionPoint = ray-&gt;origin + hit.tNearest * ray-&gt;direction;&#xD;&#xA;        const float3 normal = interpolate3(triangle-&gt;v0.normal, triangle-&gt;v1.normal, triangle-&gt;v2.normal, hit.u, hit.v);&#xD;&#xA;        &#xD;&#xA;        // direct lighting&#xD;&#xA;        {&#xD;&#xA;            const float y = 1.985f;&#xD;&#xA;            const float factor = 0.15f;&#xD;&#xA;            const float3 v1 = (float3)( factor, y,  factor);&#xD;&#xA;            const float3 v2 = (float3)(-factor, y, -factor);&#xD;&#xA;            &#xD;&#xA;            Light light;&#xD;&#xA;            light.position = (float3)(factor, y, -factor);&#xD;&#xA;            light.emission = (float3)(17.0f, 12.0f, 4.0f);&#xD;&#xA;            light.u        = v1 - light.position;&#xD;&#xA;            light.v        = v2 - light.position;&#xD;&#xA;            light.area     = length(cross(light.u, light.v));&#xD;&#xA;            &#xD;&#xA;            float3 scatterPosition = intersectionPoint + normal * FLT_EPSILON;&#xD;&#xA;            LightSample lightSample = sample_rectangle_light(&amp;light, scatterPosition, &amp;seed);&#xD;&#xA;&#xD;&#xA;            float3 Ld = 0.0f;&#xD;&#xA;            float3 Li = lightSample.emission;&#xD;&#xA;            if (dot(lightSample.direction, lightSample.normal) &lt; 0.0f) {&#xD;&#xA;                Ray shadowRay;&#xD;&#xA;                shadowRay.origin = scatterPosition;&#xD;&#xA;                shadowRay.direction = lightSample.direction;&#xD;&#xA;                Hit shadowHit = intersect_ray_bvh(&amp;shadowRay, bvhNodes, triangles);&#xD;&#xA;&#xD;&#xA;                if (shadowHit.tNearest &gt; lightSample.distance - FLT_EPSILON) {&#xD;&#xA;                    ScatterSample scatterSample = evaluate_lambert(material, normal, lightSample.direction);&#xD;&#xA;                    if (scatterSample.pdf &gt; 0.0f) {&#xD;&#xA;                        Ld = Ld + ((Li * scatterSample.f) / lightSample.pdf);&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;        &#xD;&#xA;            radiance[index] += Ld * throughput;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        ScatterSample scatterSample;&#xD;&#xA;        scatterSample = sample_lambert(material, normal, &amp;seed);&#xD;&#xA;        if (scatterSample.pdf &gt; 0.0f) {&#xD;&#xA;            throughput = (throughput * scatterSample.f) / scatterSample.pdf;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        ray-&gt;direction = scatterSample.L;&#xD;&#xA;        ray-&gt;origin = intersectionPoint + ray-&gt;direction * FLT_EPSILON;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Rectangle light sampling&#xD;&#xA;```&#xD;&#xA;LightSample sample_rectangle_light(const Light *light, const float3 scatterPosition, uint2 *seed) {&#xD;&#xA;    const uint lightsCount = 1u;&#xD;&#xA;    const float2 random = get_random_numbers(seed);&#xD;&#xA;    const float3 lightSurfacePosition = light-&gt;position + light-&gt;u * random.x + light-&gt;v * random.y;&#xD;&#xA;&#xD;&#xA;    LightSample result;&#xD;&#xA;    result.normal = normalize(cross(light-&gt;u, light-&gt;v));&#xD;&#xA;    result.emission = light-&gt;emission * (float)lightsCount;&#xD;&#xA;    result.direction = lightSurfacePosition - scatterPosition;&#xD;&#xA;    result.distance = length(result.direction);&#xD;&#xA;    result.direction /= result.distance;&#xD;&#xA;&#xD;&#xA;    float distanceSquared = result.distance * result.distance;&#xD;&#xA;    result.pdf = distanceSquared / (light-&gt;area * fabs(dot(result.normal, result.direction)));&#xD;&#xA;&#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Lambert BSDF&#xD;&#xA;```&#xD;&#xA;ScatterSample evaluate_lambert(const Material *material, const float3 normal, const float3 L) {&#xD;&#xA;    ScatterSample result;&#xD;&#xA;    result.pdf = dot(normal, L) * M_1_PI_F;&#xD;&#xA;    result.f = M_1_PI_F * material-&gt;diffuse * dot(normal, L);&#xD;&#xA;&#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;ScatterSample sample_lambert(const Material *material, const float3 normal, uint2 *seed) {&#xD;&#xA;    const float2 random = get_random_numbers(seed);&#xD;&#xA;&#xD;&#xA;    ScatterSample result;&#xD;&#xA;    result.L = sample_hemisphere(normal, random);&#xD;&#xA;    result.f = M_1_PI_F * material-&gt;diffuse * dot(normal, result.L);&#xD;&#xA;    result.pdf = dot(normal, result.L) * M_1_PI_F;&#xD;&#xA;    &#xD;&#xA;    return result;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;### Gamma correction&#xD;&#xA;```&#xD;&#xA;float3 color = (radiance[index] + read_imagef(imagePlane, (int2)(x, y)).xyz) / (float)sampleCount;&#xD;&#xA;color = pow(color, (float3)(1.0f / 2.2f));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;## Culprit&#xD;&#xA;It might be the hardcoded rectangle light that causes this effect but I'm not sure because manipulating its position/area didn't change much.&#xD;&#xA;&#xD;&#xA;## Edit&#xD;&#xA;Turns out my model had wrong normal vectors on certain meshes. That's why certain areas appeared darker.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I still have no idea why for example box's corners are much darker than in reference image.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5XW69.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/DYhrr.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39057" PostHistoryTypeId="2" PostId="13117" RevisionGUID="b6086f9e-432d-47aa-8873-8f7110368374" CreationDate="2022-11-21T20:08:32.700" UserId="19236" Text="I was comparing images on different max bounce counts. My image was generated on 2 bounces, whereas reference image was generated on 3 bounces." ContentLicense="CC BY-SA 4.0" />
  <row Id="39059" PostHistoryTypeId="50" PostId="12286" RevisionGUID="32cb8782-a560-4723-a36c-47ffae2e0f5c" CreationDate="2022-11-22T10:03:35.433" UserId="-1" />
  <row Id="39060" PostHistoryTypeId="2" PostId="13118" RevisionGUID="328f05e6-d26d-4896-b677-37cfc4a3d04d" CreationDate="2022-11-23T00:02:03.603" UserDisplayName="user19242" Text="The HSL/HSV color spaces are not considered &quot;perceptually uniform&quot; despsite being widely used. Is there a detailed reason for this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39062" PostHistoryTypeId="1" PostId="13118" RevisionGUID="328f05e6-d26d-4896-b677-37cfc4a3d04d" CreationDate="2022-11-23T00:02:03.603" UserDisplayName="user19242" Text="Why are the HSL and HSV color models not considered &quot;perceptually uniform&quot;?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39063" PostHistoryTypeId="3" PostId="13118" RevisionGUID="328f05e6-d26d-4896-b677-37cfc4a3d04d" CreationDate="2022-11-23T00:02:03.603" UserDisplayName="user19242" Text="|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39064" PostHistoryTypeId="2" PostId="13119" RevisionGUID="f46c3f24-f867-4458-a770-dd89f0765173" CreationDate="2022-11-23T06:59:09.163" UserId="19243" Text="I actually have stumbled at this same exact problem. I think I have found the solution in the pbr book: https://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#TheTorrancendashSparrowModel&#xD;&#xA;&#xD;&#xA;Basically from what I understand, the derivation for a perfect mirror without fresnel and geometry terms goes like this:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int \text{brdf}(\omega_i, \omega_o) \cos(\theta_i) d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_i) \cos(\theta_o)}\cos(\theta_i)d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_o)}d\omega_i$&#xD;&#xA;&#xD;&#xA;However, crucial detail here is that $D(\omega_h)=\delta(\omega_h)$ here is a function of $\omega_h$, but the integration happens over $\omega_i$. And according to formula 8.17 of the pbr book,&#xD;&#xA;$d\omega_h=\frac{d\omega_o}{4 \cos(\theta_h)}=\frac{d\omega_i}{4 \cos(\theta_h)}$, and for the case of integrating over a perfect mirror, $\theta_h=\theta_i=\theta_o$, which essentially means $d\omega_i=4 \cos(\theta_o)d\omega_h$.&#xD;&#xA;&#xD;&#xA;And now, finally substituting this $d\omega_i$ and essentially integrating over $\omega_h$ instead, we get:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int\frac{D(\omega_h) L_i(\omega_i(\omega_h))}{4\cos(\theta_o)}4 \cos(\omega_o)d\omega_h=\int\delta(\omega_h)L_i(\omega_i(\omega_h))d\omega_h=L(\omega_i)$&#xD;&#xA;&#xD;&#xA;TL;DR it's because $D(\omega_h)$ is a function of $\omega_h$ and not a function $d\omega_h=\frac{d\omega_o}{4\cos(\omega_h)}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39066" PostHistoryTypeId="5" PostId="13119" RevisionGUID="8c290d7e-43bb-4ffb-af40-92b1beb68e73" CreationDate="2022-11-23T07:02:09.640" UserId="19243" Comment="added 25 characters in body" Text="I actually have stumbled at this same exact problem. I think I have found the solution in the pbr book: https://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#TheTorrancendashSparrowModel&#xD;&#xA;&#xD;&#xA;Basically from what I understand, the derivation for a perfect mirror without fresnel and geometry terms goes like this:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int \text{brdf}(\omega_i, \omega_o) \cos(\theta_i) d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_i) \cos(\theta_o)}\cos(\theta_i)d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_o)}d\omega_i$&#xD;&#xA;&#xD;&#xA;However, the crucial detail is that the distribution function $D(\omega_h)=\delta(\omega_h)$ here is a function of $\omega_h$, but the integration happens over $\omega_i$. And according to formula 8.17 of the pbr book,&#xD;&#xA;$d\omega_h=\frac{d\omega_o}{4 \cos(\theta_h)}=\frac{d\omega_i}{4 \cos(\theta_h)}$, and for the case of integrating over a perfect mirror, $\theta_h=\theta_i=\theta_o$, which essentially means $d\omega_i=4 \cos(\theta_o)d\omega_h$.&#xD;&#xA;&#xD;&#xA;And now, finally substituting this $d\omega_i$ and essentially integrating over $\omega_h$ instead, we get:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int\frac{D(\omega_h) L_i(\omega_i(\omega_h))}{4\cos(\theta_o)}4 \cos(\omega_o)d\omega_h=\int\delta(\omega_h)L_i(\omega_i(\omega_h))d\omega_h=L(\omega_i)$&#xD;&#xA;&#xD;&#xA;TL;DR it's because $D(\omega_h)$ is a function of $\omega_h$ and not a function $d\omega_h=\frac{d\omega_o}{4\cos(\omega_h)}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39067" PostHistoryTypeId="5" PostId="13119" RevisionGUID="8d8a5bea-ee9d-41f4-a7dc-cb4175475634" CreationDate="2022-11-23T07:04:21.780" UserId="19243" Comment="added 2 characters in body" Text="I actually have stumbled at this same exact problem. I think I have found the solution in the pbr book: https://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#TheTorrancendashSparrowModel&#xD;&#xA;&#xD;&#xA;Basically from what I understand, the derivation for a perfect mirror (without fresnel and geometry terms) goes like this:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int \text{brdf}(\omega_i, \omega_o) \cos(\theta_i) d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_i) \cos(\theta_o)}\cos(\theta_i)d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_o)}d\omega_i$&#xD;&#xA;&#xD;&#xA;However, the crucial detail is that the distribution function $D(\omega_h)=\delta(\omega_h)$ here is a function of $\omega_h$, but the integration happens over $\omega_i$. And according to formula 8.17 of the pbr book,&#xD;&#xA;$d\omega_h=\frac{d\omega_o}{4 \cos(\theta_h)}=\frac{d\omega_i}{4 \cos(\theta_h)}$, and for the case of integrating over a perfect mirror, $\theta_h=\theta_i=\theta_o$, which essentially means $d\omega_i=4 \cos(\theta_o)d\omega_h$.&#xD;&#xA;&#xD;&#xA;And now, finally substituting this $d\omega_i$ and essentially integrating over $\omega_h$ instead, we get:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int\frac{D(\omega_h) L_i(\omega_i(\omega_h))}{4\cos(\theta_o)}4 \cos(\omega_o)d\omega_h=\int\delta(\omega_h)L_i(\omega_i(\omega_h))d\omega_h=L(\omega_i)$&#xD;&#xA;&#xD;&#xA;TL;DR it's because $D(\omega_h)$ is a function of $\omega_h$ and not a function $d\omega_h=\frac{d\omega_o}{4\cos(\omega_h)}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39068" PostHistoryTypeId="5" PostId="13119" RevisionGUID="13726f97-2ec4-404e-b816-6a188dc39c4e" CreationDate="2022-11-23T07:06:29.917" UserId="19243" Comment="added 79 characters in body" Text="I actually have stumbled at this same exact problem. I think I have found the solution in the pbr book: https://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models#TheTorrancendashSparrowModel&#xD;&#xA;&#xD;&#xA;Basically from what I understand, the derivation for a perfect mirror (without fresnel and geometry terms) goes like this:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int \text{brdf}(\omega_i, \omega_o) \cos(\theta_i) d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_i) \cos(\theta_o)}\cos(\theta_i)d\omega_i=\int\frac{D(\omega_h) L_i(\omega_i)}{4\cos(\theta_o)}d\omega_i$&#xD;&#xA;&#xD;&#xA;However, the crucial detail is that the distribution function $D(\omega_h)=\delta(\omega_h)$ here is a function of $\omega_h$, but the integration happens over $\omega_i$. And according to formula 8.17 of the pbr book,&#xD;&#xA;$d\omega_h=\frac{d\omega_o}{4 \cos(\theta_h)}=\frac{d\omega_i}{4 \cos(\theta_h)}$, and for the case of integrating over a perfect mirror, $\theta_h=\theta_i=\theta_o$, which essentially means $d\omega_i=4 \cos(\theta_o)d\omega_h$.&#xD;&#xA;&#xD;&#xA;And now, finally substituting this $d\omega_i$ and essentially integrating over $\omega_h$ instead, we get:&#xD;&#xA;&#xD;&#xA;$L(\omega_o)=\int\frac{D(\omega_h) L_i(\omega_i(\omega_h))}{4\cos(\theta_o)}4 \cos(\omega_o)d\omega_h=\int\delta(\omega_h)L_i(\omega_i(\omega_h))d\omega_h=L(\omega_i)$&#xD;&#xA;&#xD;&#xA;TL;DR it's because $D(\omega_h)$ is a function of $\omega_h$ and not a function of $\omega_i$. However, one can be converted to another via this &quot;extra&quot; term: $d\omega_h=\frac{d\omega_o}{4\cos(\omega_h)}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39070" PostHistoryTypeId="2" PostId="13120" RevisionGUID="28c2f31b-fd76-4970-889e-81e26b14793a" CreationDate="2022-11-24T08:18:36.700" UserDisplayName="user1703" Text="This is just a physiological truth. Perceptually uniform colorimetric models are complex and there must be a strong justification to use them (why would you need perceptual uniformity, after all ?).&#xD;&#xA;&#xD;&#xA;On the other hand, HLS/HVS provide a sufficient empirical decomposition in dominant color, lightness and colorfulness." ContentLicense="CC BY-SA 4.0" />
  <row Id="39072" PostHistoryTypeId="2" PostId="13121" RevisionGUID="b166b37d-8078-4eab-94bf-80594b988711" CreationDate="2022-11-24T08:26:38.097" UserDisplayName="user1703" Text="All viewing projections are from 3D to 2D. The parallel projection is just a limit case of perspective.&#xD;&#xA;&#xD;&#xA;Writing the equation of a ray from the focal point $(0, 0, -f)$ and intersecting with the viewing plane $z=0$, you have&#xD;&#xA;&#xD;&#xA;$$\begin{cases}x'=\dfrac{fx}{f+z}\\y'=\dfrac{fy}{f+z}\end{cases}$$ where the magnification factor $f$ in the numerator compensates the minification with distance.&#xD;&#xA;&#xD;&#xA;If you let $f$ tend to infinity, the equations simplify to  &#xD;&#xA;&#xD;&#xA;$$\begin{cases}x'=x\\y'=y\end{cases}$$&#xD;&#xA;&#xD;&#xA;which means that the effect of depth is cancelled and projection is achieved by dropping the $z$ cordinate." ContentLicense="CC BY-SA 4.0" />
  <row Id="39074" PostHistoryTypeId="5" PostId="13121" RevisionGUID="4103da91-3029-42b2-bbf2-f92ffe6e2e7f" CreationDate="2022-11-24T08:38:08.447" UserDisplayName="user1703" Comment="added 472 characters in body" Text="All viewing projections are from 3D to 2D. The parallel projection is just a limit case of perspective.&#xD;&#xA;&#xD;&#xA;Writing the equation of a ray from the focal point $(0, 0, -f)$ and intersecting with the viewing plane $z=0$, you have&#xD;&#xA;&#xD;&#xA;$$\begin{cases}x'=\dfrac{fx}{f+z}\\y'=\dfrac{fy}{f+z}\end{cases}$$ where the magnification factor $f$ in the numerator compensates the minification with distance.&#xD;&#xA;&#xD;&#xA;If you let $f$ tend to infinity, the equations simplify to  &#xD;&#xA;&#xD;&#xA;$$\begin{cases}x'=x\\y'=y\end{cases}$$&#xD;&#xA;&#xD;&#xA;which means that the effect of depth is cancelled and projection is achieved by dropping the $z$ cordinate.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Addendum:**&#xD;&#xA;&#xD;&#xA;There is a way to replace a perspective projection by a parallel one, using 4D homogeneous coordinates and represent the points as $\left(x,y,z,1+\dfrac zf\right)$, which is equivalent to $\left(\dfrac{fx}{f+z},\dfrac{fy}{f+z},\dfrac{fz}{f+z},1\right)$. By considering the 3D components, you obtain a deformed 3D scene which you can render using a parallel projection, while the depth information is preserved to allow hidden parts removal. Again, when $f$ tends to infinity, the transformation becomes trivial." ContentLicense="CC BY-SA 4.0" />
  <row Id="39075" PostHistoryTypeId="2" PostId="13122" RevisionGUID="88ab1d53-5bbd-4264-8423-b30d6363340f" CreationDate="2022-11-24T14:23:10.940" UserId="11224" Text="I have written a relatively simple interactive C program using OpenGL 4.4 with a vertex shader and a fragment shader, running in the CodeBlocks IDE on Windows. I included an FPS counter basically as in Anton Gerdelan's tutorial here:&#xD;&#xA;&#xD;&#xA;[Gerdelan][1]&#xD;&#xA;&#xD;&#xA;However, instead of GLFW I just use the Windows API myself. When the graphics window is in focus, the reported fps stays around 60. I noticed recently when the program was still running, but was not the active window, that the fan started running very loudly and the laptop became very warm. Using ALT-TAB a preview of the various windows I had open appeared above the taskbar (I think), as is normal in that version of windows. In the little scaled-down preview of the graphics window, visible *before* choosing that as the active window, I could see that the fps was reported as 8000 fps or something like that. As soon as I selected that as the active window, the fps dropped down to 60 and the fan began to calm down.&#xD;&#xA;&#xD;&#xA;Now I am worried - by tabbing away, have I accidentally defeated the mechanism that allows the operating system to tell my C program to wait until it is ready to swap the buffers, and if so, do I thereby risk allowing my program to run the GPU so hot that I will damage it ?&#xD;&#xA;&#xD;&#xA;Do laptop GPUs these days have built-in throttling that will slow them down when they get hot enough to risk damage ? If so, then by programming in C using OpenGL, have I accidentally defeated this mechanism ?&#xD;&#xA;&#xD;&#xA;Ought I to add a Sleep command to my animation loop, to avoid this ? Would that work ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://antongerdelan.net/opengl/glcontext2.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="39077" PostHistoryTypeId="1" PostId="13122" RevisionGUID="88ab1d53-5bbd-4264-8423-b30d6363340f" CreationDate="2022-11-24T14:23:10.940" UserId="11224" Text="Am I risking damaging my GPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39078" PostHistoryTypeId="3" PostId="13122" RevisionGUID="88ab1d53-5bbd-4264-8423-b30d6363340f" CreationDate="2022-11-24T14:23:10.940" UserId="11224" Text="|opengl|gpu|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39079" PostHistoryTypeId="5" PostId="13099" RevisionGUID="13a8a8c1-5700-438d-868d-19f504e5d54e" CreationDate="2022-11-24T15:38:15.537" UserId="445" Comment="cross link to other question I found" Text="&gt; When an object is illuminated by the sun, how does the reflected spectrum change? Does each surface has an own reflection spectrum? where each photon &quot;checks&quot; its wavelength and &quot;decides&quot; to reflect or absorb?&#xD;&#xA;&#xD;&#xA;Yes, this is more or less correct. But when dealing with very many photons, striking very many different atoms/molecules mixed together into one material, we observe that some _fraction_, or percentage if you like, of the photons are reflected. So, the spectrum is made up not of yes-or-no, but that fraction, for each wavelength. This is called the surface's [reflectance spectrum](https://en.wikipedia.org/wiki/Reflectance). You may also hear “diffuse reflectance” or “albedo”.&#xD;&#xA;&#xD;&#xA;(“Diffuse” means the reflection happens at a random angle, usually due to roughness or translucency of the material; its opposite is “specular”, mirror-like reflection. When an object gleams and sparkles, that is specular reflection. Most objects exhibit some of both, and the specular reflectance can have a different color/spectrum than the diffuse — usually whiter.)&#xD;&#xA;&#xD;&#xA;Then, as you have thought, we usually consider this only in 3 different wavelengths/bands since that is sufficient to reproduce _most_, but not all effects that human vision can observe. For an example of phenomena that require more than 3 bands, see [color rendering index](https://en.wikipedia.org/wiki/Color_rendering_index), a measurement of how well the spectrum of a light source, after interacting with the reflectance spectrum of illuminated objects, simulates broad-spectrum illumination such as sunlight. You cannot simulate this without simulating more components of the spectrum than just RGB. For more examples, see this other question: https://computergraphics.stackexchange.com/questions/203/are-there-common-materials-that-arent-represented-well-by-rgb&#xD;&#xA;&#xD;&#xA;&gt;  Lets imagine having a ray tracer setup with the sun as illumination, a few objects with different colors and a physical simulated camera with 3 color channels, where each color channel has a very small bandwidth of 10nm (see Figure2).&#xD;&#xA;&#xD;&#xA;Computing using the RGB approximation does not generally think about wavelength bands at all — we just pick 3 precise wavelengths for our R, G, and B [primaries](https://en.wikipedia.org/wiki/Primary_color) and express all other colors in terms of mixes of those primaries, which are identical as seen by the (typical) human eye to more complex spectra.&#xD;&#xA;&#xD;&#xA;Any such choice of primaries will constrain the [gamut](https://en.wikipedia.org/wiki/Gamut) of colors that can be represented — some highly saturated colors will be excluded, unless the color components are allowed to go negative to express the most extreme monochromatic (or purple) colors. This is usually an acceptable limitation, because RGB monitors are _physically_ limited to emit only specific wavelengths based on the color of their LED emitters, LCD color filters, or CRT phosphors.&#xD;&#xA;&#xD;&#xA;(Note that in _printed_ graphics, the situation is more complex because instead of a display device emitting only R+G+B light, we produce an object with its own reflectance spectrum based on the pigments/dyes used. That's why 4-component “CMYK” color is used — it's a better match for the actual behavior of the pigments. In some cases, “spot colors” may be used, identifying a specific pigment to be laid down in a certain area, to produce precise colors or special effects such as shininess.)&#xD;&#xA;&#xD;&#xA;&gt; In case the ray is intersecting an object, can I scale the three values by the objects material reflection spectrum with respect to the 3 camera wavelength and bandwidth?&#xD;&#xA;&#xD;&#xA;Yes, you should multiply each wavelength/color-component of the incoming light by the object's reflectance for that color. The bandwidth need not be explicitly modeled — if changing the bandwidth makes any difference, then it is equivalent to changing the choice of primaries, i.e. working in a different [color space](https://en.wikipedia.org/wiki/Color_space). You can always convert a color from one RGB color space to another (when it is in the gamut of both) with a little bit of arithmetic.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Again, all of what I've said above is true _when you are working in RGB_. This does have limitations; if you want to precisely simulate the effects of monochromatic lights or color filters, you will need to use more color channels than just RGB. The more channels you use, the better your discrete approximation of the continuous spectra in real physics. However, this is rarely done in rendering — most computer graphics you have ever seen in your life were probably only calculated using RGB." ContentLicense="CC BY-SA 4.0" />
  <row Id="39080" PostHistoryTypeId="2" PostId="13123" RevisionGUID="bd696025-db5d-423d-98a8-9f5effdf51d3" CreationDate="2022-11-24T15:57:22.610" UserId="445" Text="&gt; Do laptop GPUs these days have built-in throttling that will slow them down when they get hot enough to risk damage ?&#xD;&#xA;&#xD;&#xA;Yes. Every portable computing device these days has “thermal throttling” — reducing the clock rate in order to keep temperature within safe limits. If one runaway program could destroy the hardware, that would be noticed — many games are not programmed especially carefully.&#xD;&#xA;&#xD;&#xA;These mechanisms are not perfect — there have been incidents where a very particular workload produced localized heat that was not detected adequately and damaged the hardware. But those are rare exceptions.&#xD;&#xA;&#xD;&#xA;&gt; If so, then by programming in C using OpenGL, have I accidentally defeated this mechanism ?&#xD;&#xA;&#xD;&#xA;No, not at all. The mechanism is usually built into the hardware and firmware — because it's important that it keep operating regardless of what the parts of the system that run user-supplied code are doing. You're far above the layer of the system that would need to be disturbed to stop that.&#xD;&#xA;&#xD;&#xA;The fact that your laptop is warm on the outside and running fans vigorously may be unpleasant to your hands and ears, but _does not_ mean it is damaging itself. If the fans are running then that's a sign that the thermal protection _is working._&#xD;&#xA;&#xD;&#xA;&gt; Ought I to add a Sleep command to my animation loop, to avoid this ?&#xD;&#xA;&#xD;&#xA;No, you should notice when the window system tells you your window is minimized or otherwise fully obscured (I don't know how this works on Microsoft Windows but this is a feature offered by most platforms), and _stop rendering entirely._ Or maybe only render every second or so, for the sake of an updated preview image." ContentLicense="CC BY-SA 4.0" />
  <row Id="39082" PostHistoryTypeId="2" PostId="13124" RevisionGUID="9267f3c9-b7ac-4a53-ae68-1332666c32c6" CreationDate="2022-11-24T16:10:53.047" UserId="18894" Text="In a perceptually uniform colour space the perceived difference in colour of two colours is proportional to the difference of the values used to describe the two colours in the colour space. For colour spaces such as CIELAB and CIELUV this was the main reason for the creation of the colour space.&#xD;&#xA;&#xD;&#xA; If two colours are represented in CIELAB with the values L1, a1, b1 and L2, a2, b2, then the perceived difference of the colours is intended to be the square root of ((L2-L1)^2 + (a2-a1)^2 + (b2-b1)^2). This means that if two colours are represented by values in CIELAB which are significantly different then the colours will be perceived as significantly different.&#xD;&#xA;&#xD;&#xA;This is not true of HSL and HSV. Two colours such as H1=0, S1=100%, L1=100% and H2=359, S2=100%, L2=100% have greatly different values for H, but will appear nearly identical. Similarly H1=60, S1=100%, L1=1% and H2=240, S2=25%, L2=1% differ greatly in H and S values, but will appear nearly identical, being both nearly black.&#xD;&#xA;&#xD;&#xA;HSL and HSV are useful and widely used because it is easier to tell from the H, S and L/V values what the colour is, but they are not perceptually uniform and should not be used as the basis to calculate the perceived difference of two colours. Colours should be converted from HSL/HSV to e.g. CIELAB to calculate the perceived difference." ContentLicense="CC BY-SA 4.0" />
  <row Id="39084" PostHistoryTypeId="50" PostId="5996" RevisionGUID="6ce1b550-aba9-4ca0-9775-fa9cfd8ba22f" CreationDate="2022-11-24T18:03:00.490" UserId="-1" />
  <row Id="39086" PostHistoryTypeId="2" PostId="13125" RevisionGUID="75d85ee6-d2e3-4ae8-8a63-b67fd803b607" CreationDate="2022-11-25T06:50:34.770" UserId="19252" Text="I'll start with the coordinate system I'm trying to use:  If I were standing on the ground, facing north, the x axis is a line moving from the west to the east (positive X is east).  Positive y is north.  Positive Z is the line from my feet up toward my head.&#xD;&#xA;&#xD;&#xA;I have an image that represents a flat plane, upon which I might be standing - the Z coordinate is 0 for the whole image; it extends along the XY plane.  My image is x by y pixels (we'll say 10000 by 5000) and that represents some real world unit - I don't care that much about the scale.  The center of the image is located at the origin, so the top-left corner of the image (0, 0 pixel) is at (-5000, 2500).&#xD;&#xA;&#xD;&#xA;I have a camera in this hypothetical, and I know its intrinsic matrix - we can just stick to the pinhole model for now, I can worry about distortion later.  I also know the extrinsic matrix of this camera, because I know exactly where I want to position it in world space.&#xD;&#xA;&#xD;&#xA;Given this information, I want to warp the image of the plane into how my hypothetical camera would see it.&#xD;&#xA;&#xD;&#xA;With this goal in mind, I have a few questions:&#xD;&#xA;&#xD;&#xA;1) I am assuming that an initial rotation matrix of I_(3x3) would be equivalent to the camera looking straight down.  Is this correct?  If not, what does the identity rotation matrix correspond to?&#xD;&#xA;&#xD;&#xA;2) I am currently calculating a homography to use with cv2.warpPerspective.  To calculate this homography, I am doing:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;translationVector = np.matrix([[xTranslation], [yTranslation], [zTranslation]])&#xD;&#xA;extrinsic = np.block([R_3x3,-R_3x3]@translationVector])&#xD;&#xA;intrinsic = np.matrix([[f, 0, outputWidth/2],&#xD;&#xA;                       [0, f, outputHeight/2],&#xD;&#xA;                       [0, 0,   1]])&#xD;&#xA;composite = extrinsic[:, [0, 1, 3]]&#xD;&#xA;homography = intrinsic[:, :3] @ composite&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;When I use this homography matrix (using x and y translation to bring the camera to the center of the image), however, I get a weird... duplication of the source image, where it appears on the top and the bottom of the image.  I've provided an example of what I mean - in this example, there is a positive Z offset, so only the portion of the image on the bottom should exist.  (Note: in this case my 3x3 rotation matrix has rotation of +90.0001 degrees in X - more on this in question 3).&#xD;&#xA;&#xD;&#xA;[![duplication][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Hsl3l.png&#xD;&#xA;&#xD;&#xA;2A) Why does that &quot;duplicate&quot; appear, and how do I get rid of it?&#xD;&#xA;&#xD;&#xA;2B) It seems like my image is rotated oddly.  If I add 180 degrees rotation in Z it looks how I expect: is this expected or have I done something wrong?  Is this, perhaps, because in the pinhole model the image gets inverted in x and y?&#xD;&#xA;&#xD;&#xA;3) If I input a rotation angle of exactly 90 degrees in X, a flickering white line appears horizontally along the center of the image with some z translation values and not with others.  I assume this is some mathematic instability - is there any way to get rid of this, or is using &quot;90.00001&quot; degrees the best I can manage?&#xD;&#xA;&#xD;&#xA;4) Is there a better/faster/more direct way to warp the image - which always represents a flat XY plane - into the perspective of a camera with known intrinsics/extrinsics?&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="39088" PostHistoryTypeId="1" PostId="13125" RevisionGUID="75d85ee6-d2e3-4ae8-8a63-b67fd803b607" CreationDate="2022-11-25T06:50:34.770" UserId="19252" Text="Camera Perspective of 2D X/Y Plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="39089" PostHistoryTypeId="3" PostId="13125" RevisionGUID="75d85ee6-d2e3-4ae8-8a63-b67fd803b607" CreationDate="2022-11-25T06:50:34.770" UserId="19252" Text="|3d|transformations|perspective|camera-matrix|opencv|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39094" PostHistoryTypeId="50" PostId="12807" RevisionGUID="291b1ba1-3474-4e90-8749-41e546ae6f88" CreationDate="2022-11-26T12:00:50.100" UserId="-1" />
  <row Id="39095" PostHistoryTypeId="2" PostId="13127" RevisionGUID="acc3ec83-135e-48d1-b2ba-41169e83b3c6" CreationDate="2022-11-26T15:14:30.253" UserId="19258" Text="I am trying to make my camera representation work for images whose aspect ratio isn't 1 (640x480, 1920x1080...), but I am having some trouble getting it to work.&#xD;&#xA;&#xD;&#xA;The camera model is pretty simple, as it's a pinhole camera with `(F)orward`, `(L)eft` and `(U)p` vectors, and a point in space which serves as its `(O)rigin`. `F` points towards the center of the image plane, and `U` and `L` are perpendicular with each other and with `F`, forming the camera's coordinate space.&#xD;&#xA;&#xD;&#xA;The way it works is that I define everything except the `L` vector, which is the normalized cross product of `F` and `U` multiplied by the aspect ratio, so that its length is &quot;as wide&quot; as the image is going to be compared to its height.&#xD;&#xA;&#xD;&#xA;Then, to get a ray pointing at `(i, j)`, I just create a ray starting at `O` and pointing at the top-left corner (`U + F + L`)&#xD;&#xA;&#xD;&#xA;The code is this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;class Camera {&#xD;&#xA;public:&#xD;&#xA;    Direction L, U, F;&#xD;&#xA;    Point O;&#xD;&#xA;    size_t width, height;&#xD;&#xA;    size_t rays_per_pixel;&#xD;&#xA;&#xD;&#xA;private:&#xD;&#xA;    // For randomizing ray's directions inside the pixel's square&#xD;&#xA;    static std::mt19937 gen;&#xD;&#xA;    static std::uniform_real_distribution&lt;double&gt; pixel_distr;&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;&#xD;&#xA;    Camera(Point _O, Direction _U, Direction _F, size_t _width, size_t _height, size_t _rays_per_pixel) :&#xD;&#xA;            U(_U),&#xD;&#xA;            F(_F),&#xD;&#xA;            O(_O),&#xD;&#xA;            width(_width),&#xD;&#xA;            height(_height),&#xD;&#xA;            rays_per_pixel(_rays_per_pixel) {&#xD;&#xA;        // L perpendicular to F and U, then multiplied with the aspect ratio&#xD;&#xA;&#xD;&#xA;        double aspect_ratio = ((double) _width / (double) _height);&#xD;&#xA;        // * between vectors is cross product, &#xD;&#xA;        // .v just addresses their internal vector class&#xD;&#xA;        L = (F.v * U.v).normalize() * aspect_ratio;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Return a ray pointing from O to a pixel in the image, with a small &#xD;&#xA;    // random variation across the pixel's area&#xD;&#xA;    [[nodiscard]] Ray get_ray(size_t _i, size_t _j) const {&#xD;&#xA;        // Puts the ray in the pixel's center, then adds to it a random value between [0, 0.5)&#xD;&#xA;        double i = (double) _i + 0.5 + pixel_distr(gen);&#xD;&#xA;        double j = (double) _j + 0.5 + pixel_distr(gen);&#xD;&#xA;&#xD;&#xA;        return {&#xD;&#xA;            O, // Origin&#xD;&#xA;&#xD;&#xA;            Direction((U.v + F.v + L.v                      // Top left corner&#xD;&#xA;                    - ((2*L.v.modulus()*L.v)/((double) width) * j)        // Right advance (as a substraction)&#xD;&#xA;                    - ((2*U.v.modulus()*U.v)/((double) height) * i)))     // Downwards advance (as a substraction)&#xD;&#xA;        }; //&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `1`, I get this, with 512x512 as an example (ignore the texture, I know)&#xD;&#xA;[![non borked][1]][1]:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `2` or whatever else, like 640x480 I get this, which at least is somewhat hilarious:&#xD;&#xA;&#xD;&#xA;[![borked][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2b0yC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4Axab.jpg&#xD;&#xA;&#xD;&#xA;The vectors used are:&#xD;&#xA;&#xD;&#xA;`Point O(0, 0, -3.5);`&#xD;&#xA;&#xD;&#xA;`Direction U(0, 1, 0);`&#xD;&#xA;&#xD;&#xA;`Direction F(0, 0, 3);`&#xD;&#xA;&#xD;&#xA;And `L` in the first case is Direction `L(-1, 0, 0)` whereas in the second case is `L(-2, 0, 0)`.&#xD;&#xA;&#xD;&#xA;It seems to repeat the image vertically with a pattern, and I made sure the logic error shouldn't be outside of this (I ask for every single pixel across the plane correctly, etc.)&#xD;&#xA;&#xD;&#xA;Is something else needed to get a &quot;widescreen&quot; image? Should I change the camera model?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39097" PostHistoryTypeId="1" PostId="13127" RevisionGUID="acc3ec83-135e-48d1-b2ba-41169e83b3c6" CreationDate="2022-11-26T15:14:30.253" UserId="19258" Text="Trouble getting a raytracer camera representation for different aspect ratios" ContentLicense="CC BY-SA 4.0" />
  <row Id="39098" PostHistoryTypeId="3" PostId="13127" RevisionGUID="acc3ec83-135e-48d1-b2ba-41169e83b3c6" CreationDate="2022-11-26T15:14:30.253" UserId="19258" Text="|raytracing|3d|pathtracing|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39099" PostHistoryTypeId="2" PostId="13128" RevisionGUID="cdb3544a-11da-41d5-9d0d-d9a96f6645e3" CreationDate="2022-11-26T18:49:26.833" UserId="38" Text="The projection matrix tells us how to draw an image. But how does it tell us this? Well it tells us what the original vectors are like when drawn on screen. The axonometric projections have fixed direction vectors, isometric is just one of them.&#xD;&#xA;&#xD;&#xA;Now there is a entirely visually verifiable correlation between the matrix and the axes of your axonometric projection. You can offcourse also do this with rotations as others have suggested but its a very nonstraightforward way to achieve something you should be able to do by drawing the axes on a 2d surface.&#xD;&#xA;&#xD;&#xA;Now lets take the standard 120 forward facing isometric axes with z up *(offcourse any coordinate could be flitted and you could have Y up as well just change sign or swap rows in matrix. Covnention random happens to be this since I was doing architectural stuff last and architects like z up since they draw in the plane.)*:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;From this follows that in your camera matrix is of form:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;  \left[ {\begin{array}{cc}&#xD;&#xA;    cos(30°) &amp; -sin(30°) &amp; z_x &amp; 0 \\&#xD;&#xA;    -cos(30°) &amp; -sin(30°) &amp; z_y &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; z_z &amp; 0 \\&#xD;&#xA;    c_x &amp; c_y &amp; c_z &amp; 1 \\&#xD;&#xA;  \end{array} } \right] = &#xD;&#xA;  \left[ {\begin{array}{cc}&#xD;&#xA;    \sqrt{3}/2  &amp; -1/2 &amp; z_x &amp; 0 \\&#xD;&#xA;    -\sqrt{3}/2 &amp; -1/2 &amp; z_y &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; z_z &amp; 0 \\&#xD;&#xA;    c_x &amp; c_y &amp; c_z &amp; 1 \\&#xD;&#xA;  \end{array} } \right]&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;So the last column is 0 because it does not participate in a perspective. The variables $c$ represent the offset for your center. Then you may also want to multiply all the x y z components with a multiplier to fit your screen drawing coordinates, but that depends on your imaging system.&#xD;&#xA;&#xD;&#xA;What about $z$? Well you want z values to be affected by your ground plane distance somehow. Now you could decompose all this to rotations to get a natural z value. Or you can just put in a value  in $z_x$ and $z_y$ and see what happens its probably not all that important as long as your geometry does not clip by near and far planes.&#xD;&#xA;&#xD;&#xA;Similarly since the vectors are just what you see you can make any axonometric projection by drawing your axes and feeding their 2d coordinates into your matrix.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;NOTE: The matrix may be transposed depending on how your system calculation order works.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ypJnS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39101" PostHistoryTypeId="5" PostId="13128" RevisionGUID="006f6b08-cf59-49d2-ab03-abbb04bfbbeb" CreationDate="2022-11-26T18:55:15.143" UserId="38" Comment="added 60 characters in body" Text="The projection matrix tells us how to draw an image. But how does it tell us this? Well it tells us what the original vectors are like when drawn on screen. The axonometric projections have fixed direction vectors, isometric is just one of them.&#xD;&#xA;&#xD;&#xA;Now there is a entirely visually verifiable correlation between the matrix and the axes of your axonometric projection. You can offcourse also do this with rotations as others have suggested but its a very nonstraightforward way to achieve something you should be able to do by drawing the axes on a 2d surface.&#xD;&#xA;&#xD;&#xA;Now lets take the standard 120 forward facing isometric axes with z up *(offcourse any coordinate could be flitted and you could have Y up as well just change sign or swap rows in matrix. Covnention random happens to be this since I was doing architectural stuff last and architects like z up since they draw in the X-Y plane. Had i worked with machanical engineers it would be Y up)*:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Each basis vector is just a row in the matrix. From this follows that in your camera matrix is of form:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$&#xD;&#xA;  \left[ {\begin{array}{cc}&#xD;&#xA;    cos(30°) &amp; -sin(30°) &amp; z_x &amp; 0 \\&#xD;&#xA;    -cos(30°) &amp; -sin(30°) &amp; z_y &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; z_z &amp; 0 \\&#xD;&#xA;    c_x &amp; c_y &amp; c_z &amp; 1 \\&#xD;&#xA;  \end{array} } \right] = &#xD;&#xA;  \left[ {\begin{array}{cc}&#xD;&#xA;    \sqrt{3}/2  &amp; -1/2 &amp; z_x &amp; 0 \\&#xD;&#xA;    -\sqrt{3}/2 &amp; -1/2 &amp; z_y &amp; 0 \\&#xD;&#xA;    0 &amp; 1 &amp; z_z &amp; 0 \\&#xD;&#xA;    c_x &amp; c_y &amp; c_z &amp; 1 \\&#xD;&#xA;  \end{array} } \right]&#xD;&#xA;$&#xD;&#xA;&#xD;&#xA;So the last column is 0 because it does not participate in a perspective. The variables $c$ represent the offset for your center. Then you may also want to multiply all the x y z components with a multiplier to fit your screen drawing coordinates, but that depends on your imaging system.&#xD;&#xA;&#xD;&#xA;What about $z$? Well you want z values to be affected by your ground plane distance somehow. Now you could decompose all this to rotations to get a natural z value. Or you can just put in a value  in $z_x$ and $z_y$ and see what happens its probably not all that important as long as your geometry does not clip by near and far planes.&#xD;&#xA;&#xD;&#xA;Similarly since the vectors are just what you see you can make any axonometric projection by drawing your axes and feeding their 2d coordinates into your matrix.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;NOTE: The matrix may be transposed depending on how your system calculation order works.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ypJnS.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39102" PostHistoryTypeId="5" PostId="13127" RevisionGUID="178c810a-f4c2-4141-ba0b-3bb6357cc62c" CreationDate="2022-11-26T19:40:40.060" UserId="19258" Comment="added 1628 characters in body" Text="I am trying to make my camera representation work for images whose aspect ratio isn't 1 (640x480, 1920x1080...), but I am having some trouble getting it to work.&#xD;&#xA;&#xD;&#xA;The camera model is pretty simple, as it's a pinhole camera with `(F)orward`, `(L)eft` and `(U)p` vectors, and a point in space which serves as its `(O)rigin`. `F` points towards the center of the image plane, and `U` and `L` are perpendicular with each other and with `F`, forming the camera's coordinate space.&#xD;&#xA;&#xD;&#xA;The way it works is that I define everything except the `L` vector, which is the normalized cross product of `F` and `U` multiplied by the aspect ratio, so that its length is &quot;as wide&quot; as the image is going to be compared to its height.&#xD;&#xA;&#xD;&#xA;Then, to get a ray pointing at `(i, j)`, I just create a ray starting at `O` and pointing at the top-left corner (`U + F + L`)&#xD;&#xA;&#xD;&#xA;The code is this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;class Camera {&#xD;&#xA;public:&#xD;&#xA;    Direction L, U, F;&#xD;&#xA;    Point O;&#xD;&#xA;    size_t width, height;&#xD;&#xA;    size_t rays_per_pixel;&#xD;&#xA;&#xD;&#xA;private:&#xD;&#xA;    // For randomizing ray's directions inside the pixel's square&#xD;&#xA;    static std::mt19937 gen;&#xD;&#xA;    static std::uniform_real_distribution&lt;double&gt; pixel_distr;&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;&#xD;&#xA;    Camera(Point _O, Direction _U, Direction _F, size_t _width, size_t _height, size_t _rays_per_pixel) :&#xD;&#xA;            U(_U),&#xD;&#xA;            F(_F),&#xD;&#xA;            O(_O),&#xD;&#xA;            width(_width),&#xD;&#xA;            height(_height),&#xD;&#xA;            rays_per_pixel(_rays_per_pixel) {&#xD;&#xA;        // L perpendicular to F and U, then multiplied with the aspect ratio&#xD;&#xA;&#xD;&#xA;        double aspect_ratio = ((double) _width / (double) _height);&#xD;&#xA;        // * between vectors is cross product, &#xD;&#xA;        // .v just addresses their internal vector class&#xD;&#xA;        L = (F.v * U.v).normalize() * aspect_ratio;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Return a ray pointing from O to a pixel in the image, with a small &#xD;&#xA;    // random variation across the pixel's area&#xD;&#xA;    [[nodiscard]] Ray get_ray(size_t _i, size_t _j) const {&#xD;&#xA;        // Puts the ray in the pixel's center, then adds to it a random value between [0, 0.5)&#xD;&#xA;        double i = (double) _i + 0.5 + pixel_distr(gen);&#xD;&#xA;        double j = (double) _j + 0.5 + pixel_distr(gen);&#xD;&#xA;&#xD;&#xA;        return {&#xD;&#xA;            O, // Origin&#xD;&#xA;&#xD;&#xA;            Direction((U.v + F.v + L.v                      // Top left corner&#xD;&#xA;                    - ((2*L.v.modulus()*L.v)/((double) width) * j)        // Right advance (as a substraction)&#xD;&#xA;                    - ((2*U.v.modulus()*U.v)/((double) height) * i)))     // Downwards advance (as a substraction)&#xD;&#xA;        }; //&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `1`, I get this, with 512x512 as an example (ignore the texture, I know)&#xD;&#xA;[![non borked][1]][1]:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `2` or whatever else, like 640x480 I get this, which at least is somewhat hilarious:&#xD;&#xA;&#xD;&#xA;[![borked][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2b0yC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4Axab.jpg&#xD;&#xA;&#xD;&#xA;The vectors used are:&#xD;&#xA;&#xD;&#xA;`Point O(0, 0, -3.5);`&#xD;&#xA;&#xD;&#xA;`Direction U(0, 1, 0);`&#xD;&#xA;&#xD;&#xA;`Direction F(0, 0, 3);`&#xD;&#xA;&#xD;&#xA;And `L` in the first case is Direction `L(-1, 0, 0)` whereas in the second case is `L(-2, 0, 0)`.&#xD;&#xA;&#xD;&#xA;It seems to repeat the image vertically with a pattern, and I made sure the logic error shouldn't be outside of this (I ask for every single pixel across the plane correctly, etc.)&#xD;&#xA;&#xD;&#xA;Is something else needed to get a &quot;widescreen&quot; image? Should I change the camera model?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Outside of the camera stuff, a rendering job writes to the image like this, which itself is a vector representing the flattened matrix of dimensions `[height][width]`:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void rendering_job(const Scene &amp;scene, std::vector&lt;Vector3d&gt; &amp;img, size_t i, size_t j) {&#xD;&#xA;    Vector3d temp_emission;&#xD;&#xA;&#xD;&#xA;    size_t number_of_bounces = 0;&#xD;&#xA;    for (size_t r = 0; r &lt; scene.camera.rays_per_pixel; r++) {&#xD;&#xA;        Ray ray = scene.camera.get_ray(i, j);&#xD;&#xA;&#xD;&#xA;        temp_emission = temp_emission + integrator_sample(scene, ray, number_of_bounces);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Printing every single index access shows that&#xD;&#xA;    // every single pixel gets addressed (from 0 to &#xD;&#xA;    // scene.camera.height*scene.camera.height-1)&#xD;&#xA;    img[i*scene.camera.height + j] = temp_emission / scene.camera.rays_per_pixel; &#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It then gets passed to a module which writes the PPM image like this (the factor and MAX stuff is for doing tonemapping):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;void write(std::string nombFich) const {&#xD;&#xA;    double factor = color_resolution / max;&#xD;&#xA;&#xD;&#xA;    std::ofstream outfile(nombFich);&#xD;&#xA;    outfile &lt;&lt; std::fixed &lt;&lt; std::setprecision(0);&#xD;&#xA;    outfile &lt;&lt; &quot;P3&quot; &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; &quot;# &quot; &lt;&lt; nombFich &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; &quot;#MAX=&quot; &lt;&lt; max &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; width &lt;&lt; &quot; &quot; &lt;&lt; height &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; color_resolution &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;    int i = 0;&#xD;&#xA;    for (auto v : img) {&#xD;&#xA;        outfile &lt;&lt; v[0]*factor &lt;&lt; &quot; &quot; &lt;&lt; v[1]*factor &lt;&lt; &quot; &quot; &lt;&lt; v[2]*factor &lt;&lt; &quot; &quot;;&#xD;&#xA;&#xD;&#xA;        i++;&#xD;&#xA;        if (i == width - 1) {i = 0; outfile &lt;&lt; std::endl;}&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The writing process writes correctly `height` rows of `width` values in the PPM." ContentLicense="CC BY-SA 4.0" />
  <row Id="39103" PostHistoryTypeId="5" PostId="13127" RevisionGUID="b9c7b572-877e-4972-ba08-5ebde76e0a3d" CreationDate="2022-11-26T19:52:16.057" UserId="19258" Comment="added 9 characters in body" Text="I am trying to make my camera representation work for images whose aspect ratio isn't 1 (640x480, 1920x1080...), but I am having some trouble getting it to work.&#xD;&#xA;&#xD;&#xA;The camera model is pretty simple, as it's a pinhole camera with `(F)orward`, `(L)eft` and `(U)p` vectors, and a point in space which serves as its `(O)rigin`. `F` points towards the center of the image plane, and `U` and `L` are perpendicular with each other and with `F`, forming the camera's coordinate space.&#xD;&#xA;&#xD;&#xA;The way it works is that I define everything except the `L` vector, which is the normalized cross product of `F` and `U` multiplied by the aspect ratio, so that its length is &quot;as wide&quot; as the image is going to be compared to its height.&#xD;&#xA;&#xD;&#xA;Then, to get a ray pointing at `(i, j)`, I just create a ray starting at `O` and pointing at the top-left corner (`U + F + L`)&#xD;&#xA;&#xD;&#xA;The code is this:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;class Camera {&#xD;&#xA;public:&#xD;&#xA;    Direction L, U, F;&#xD;&#xA;    Point O;&#xD;&#xA;    size_t width, height;&#xD;&#xA;    size_t rays_per_pixel;&#xD;&#xA;&#xD;&#xA;private:&#xD;&#xA;    // For randomizing ray's directions inside the pixel's square&#xD;&#xA;    static std::mt19937 gen;&#xD;&#xA;    static std::uniform_real_distribution&lt;double&gt; pixel_distr;&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;&#xD;&#xA;    Camera(Point _O, Direction _U, Direction _F, size_t _width, size_t _height, size_t _rays_per_pixel) :&#xD;&#xA;            U(_U),&#xD;&#xA;            F(_F),&#xD;&#xA;            O(_O),&#xD;&#xA;            width(_width),&#xD;&#xA;            height(_height),&#xD;&#xA;            rays_per_pixel(_rays_per_pixel) {&#xD;&#xA;        // L perpendicular to F and U, then multiplied with the aspect ratio&#xD;&#xA;&#xD;&#xA;        double aspect_ratio = ((double) _width / (double) _height);&#xD;&#xA;        // * between vectors is cross product, &#xD;&#xA;        // .v just addresses their internal vector class&#xD;&#xA;        L = (F.v * U.v).normalize() * aspect_ratio;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Return a ray pointing from O to a pixel in the image, with a small &#xD;&#xA;    // random variation across the pixel's area&#xD;&#xA;    [[nodiscard]] Ray get_ray(size_t _i, size_t _j) const {&#xD;&#xA;        // Puts the ray in the pixel's center, then adds to it a random value between [0, 0.5)&#xD;&#xA;        double i = (double) _i + 0.5 + pixel_distr(gen);&#xD;&#xA;        double j = (double) _j + 0.5 + pixel_distr(gen);&#xD;&#xA;&#xD;&#xA;        return {&#xD;&#xA;            O, // Origin&#xD;&#xA;&#xD;&#xA;            Direction((U.v + F.v + L.v                      // Top left corner&#xD;&#xA;                    - ((2*L.v.modulus()*L.v)/((double) width) * j)        // Right advance (as a substraction)&#xD;&#xA;                    - ((2*U.v.modulus()*U.v)/((double) height) * i)))     // Downwards advance (as a substraction)&#xD;&#xA;        }; //&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `1`, I get this, with 512x512 as an example (ignore the texture, I know)&#xD;&#xA;[![non borked][1]][1]:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `2` or whatever else, like 640x480 I get this, which at least is somewhat hilarious:&#xD;&#xA;&#xD;&#xA;[![borked][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2b0yC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4Axab.jpg&#xD;&#xA;&#xD;&#xA;The vectors used are:&#xD;&#xA;&#xD;&#xA;`Point O(0, 0, -3.5);`&#xD;&#xA;&#xD;&#xA;`Direction U(0, 1, 0);`&#xD;&#xA;&#xD;&#xA;`Direction F(0, 0, 3);`&#xD;&#xA;&#xD;&#xA;And `L` in the first case is Direction `L(-1, 0, 0)` whereas in the second case is `L(-2, 0, 0)`.&#xD;&#xA;&#xD;&#xA;It seems to repeat the image vertically with a pattern, and I made sure the logic error shouldn't be outside of this (I ask for every single pixel across the plane correctly, etc.)&#xD;&#xA;&#xD;&#xA;Is something else needed to get a &quot;widescreen&quot; image? Should I change the camera model?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Outside of the camera stuff, a rendering job writes to the image like this, which itself is a vector representing the flattened matrix of dimensions `[height][width]`:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;void rendering_job(const Scene &amp;scene, std::vector&lt;Vector3d&gt; &amp;img, size_t i, size_t j) {&#xD;&#xA;    Vector3d temp_emission;&#xD;&#xA;&#xD;&#xA;    size_t number_of_bounces = 0;&#xD;&#xA;    for (size_t r = 0; r &lt; scene.camera.rays_per_pixel; r++) {&#xD;&#xA;        Ray ray = scene.camera.get_ray(i, j);&#xD;&#xA;&#xD;&#xA;        temp_emission = temp_emission + integrator_sample(scene, ray, number_of_bounces);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Printing every single index access shows that&#xD;&#xA;    // every single pixel gets addressed (from 0 to &#xD;&#xA;    // scene.camera.height*scene.camera.width-1)&#xD;&#xA;    img[i*scene.camera.height + j] = temp_emission / scene.camera.rays_per_pixel; &#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It then gets passed to a module which writes the PPM image like this (the factor and MAX stuff is for doing tonemapping):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;void write(std::string nombFich) const {&#xD;&#xA;    double factor = color_resolution / max;&#xD;&#xA;&#xD;&#xA;    std::ofstream outfile(nombFich);&#xD;&#xA;    outfile &lt;&lt; std::fixed &lt;&lt; std::setprecision(0);&#xD;&#xA;    outfile &lt;&lt; &quot;P3&quot; &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; &quot;# &quot; &lt;&lt; nombFich &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; &quot;#MAX=&quot; &lt;&lt; max &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; width &lt;&lt; &quot; &quot; &lt;&lt; height &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; color_resolution &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;    int i = 0;&#xD;&#xA;    for (auto v : img) {&#xD;&#xA;        outfile &lt;&lt; v[0]*factor &lt;&lt; &quot; &quot; &lt;&lt; v[1]*factor &lt;&lt; &quot; &quot; &lt;&lt; v[2]*factor &lt;&lt; &quot; &quot;;&#xD;&#xA;&#xD;&#xA;        i++;&#xD;&#xA;        if (i == width - 1) {i = 0; outfile &lt;&lt; std::endl;}&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The writing process writes correctly `height` rows of `width` values in the PPM." ContentLicense="CC BY-SA 4.0" />
  <row Id="39104" PostHistoryTypeId="5" PostId="13127" RevisionGUID="ff1f398d-f923-4db1-8758-efd48d994138" CreationDate="2022-11-26T20:32:26.790" UserId="19258" Comment="added 360 characters in body" Text="I am trying to make my camera representation work for images whose aspect ratio isn't 1 (640x480, 1920x1080...), but I am having some trouble getting it to work.&#xD;&#xA;&#xD;&#xA;The camera model is pretty simple, as it's a pinhole camera with `(F)orward`, `(L)eft` and `(U)p` vectors, and a point in space which serves as its `(O)rigin`. `F` points towards the center of the image plane, and `U` and `L` are perpendicular with each other and with `F`, forming the camera's coordinate space.&#xD;&#xA;&#xD;&#xA;The way it works is that I define everything except the `L` vector, which is the normalized cross product of `F` and `U` multiplied by the aspect ratio, so that its length is &quot;as wide&quot; as the image is going to be compared to its height.&#xD;&#xA;&#xD;&#xA;Then, to get a ray pointing at `(i, j)`, I just create a ray starting at `O` and pointing at the top-left corner (`U + F + L`)&#xD;&#xA;&#xD;&#xA;The code is this:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;class Camera {&#xD;&#xA;public:&#xD;&#xA;    Direction L, U, F;&#xD;&#xA;    Point O;&#xD;&#xA;    size_t width, height;&#xD;&#xA;    size_t rays_per_pixel;&#xD;&#xA;&#xD;&#xA;private:&#xD;&#xA;    // For randomizing ray's directions inside the pixel's square&#xD;&#xA;    static std::mt19937 gen;&#xD;&#xA;    static std::uniform_real_distribution&lt;double&gt; pixel_distr;&#xD;&#xA;&#xD;&#xA;public:&#xD;&#xA;&#xD;&#xA;    Camera(Point _O, Direction _U, Direction _F, size_t _width, size_t _height, size_t _rays_per_pixel) :&#xD;&#xA;            U(_U),&#xD;&#xA;            F(_F),&#xD;&#xA;            O(_O),&#xD;&#xA;            width(_width),&#xD;&#xA;            height(_height),&#xD;&#xA;            rays_per_pixel(_rays_per_pixel) {&#xD;&#xA;        // L perpendicular to F and U, then multiplied with the aspect ratio&#xD;&#xA;&#xD;&#xA;        double aspect_ratio = ((double) _width / (double) _height);&#xD;&#xA;        // * between vectors is cross product, &#xD;&#xA;        // .v just addresses their internal vector class&#xD;&#xA;        L = (F.v * U.v).normalize() * aspect_ratio;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // Return a ray pointing from O to a pixel in the image, with a small &#xD;&#xA;    // random variation across the pixel's area&#xD;&#xA;    [[nodiscard]] Ray get_ray(size_t _i, size_t _j) const {&#xD;&#xA;        // Puts the ray in the pixel's center, then adds to it a random value between [0, 0.5)&#xD;&#xA;        double i = (double) _i + 0.5 + pixel_distr(gen);&#xD;&#xA;        double j = (double) _j + 0.5 + pixel_distr(gen);&#xD;&#xA;&#xD;&#xA;        return {&#xD;&#xA;            O, // Origin&#xD;&#xA;&#xD;&#xA;            Direction((U.v + F.v + L.v                      // Top left corner&#xD;&#xA;                    - ((2*L.v.modulus()*L.v)/((double) width) * j)        // Right advance (as a substraction)&#xD;&#xA;                    - ((2*U.v.modulus()*U.v)/((double) height) * i)))     // Downwards advance (as a substraction)&#xD;&#xA;        }; //&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `1`, I get this, with 512x512 as an example (ignore the texture, I know)&#xD;&#xA;[![non borked][1]][1]:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If I indicate `width` and `height` with an aspect ratio of `2` or whatever else, like 640x480 I get this, which at least is somewhat hilarious:&#xD;&#xA;&#xD;&#xA;[![borked][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The vectors used are:&#xD;&#xA;&#xD;&#xA;`Point O(0, 0, -3.5);`&#xD;&#xA;&#xD;&#xA;`Direction U(0, 1, 0);`&#xD;&#xA;&#xD;&#xA;`Direction F(0, 0, 3);`&#xD;&#xA;&#xD;&#xA;And `L` in the first case is Direction `L(-1, 0, 0)` whereas in the second case is `L(-2, 0, 0)`.&#xD;&#xA;&#xD;&#xA;It seems to repeat the image vertically with a pattern, and I made sure the logic error shouldn't be outside of this (I ask for every single pixel across the plane correctly, etc.)&#xD;&#xA;&#xD;&#xA;Is something else needed to get a &quot;widescreen&quot; image? Should I change the camera model?&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;Outside of the camera stuff, a rendering job writes to the image like this, which itself is a vector representing the flattened matrix of dimensions `[height][width]`:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;void rendering_job(const Scene &amp;scene, std::vector&lt;Vector3d&gt; &amp;img, size_t i, size_t j) {&#xD;&#xA;    Vector3d temp_emission;&#xD;&#xA;&#xD;&#xA;    size_t number_of_bounces = 0;&#xD;&#xA;    for (size_t r = 0; r &lt; scene.camera.rays_per_pixel; r++) {&#xD;&#xA;        Ray ray = scene.camera.get_ray(i, j);&#xD;&#xA;&#xD;&#xA;        temp_emission = temp_emission + integrator_sample(scene, ray, number_of_bounces);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Printing every single index access shows that&#xD;&#xA;    // every single pixel gets addressed (from 0 to &#xD;&#xA;    // scene.camera.height*scene.camera.width-1)&#xD;&#xA;    img[i*scene.camera.height + j] = temp_emission / scene.camera.rays_per_pixel; &#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;It then gets passed to a module which writes the PPM image like this (the factor and MAX stuff is for doing tonemapping):&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;void write(std::string nombFich) const {&#xD;&#xA;    double factor = color_resolution / max;&#xD;&#xA;&#xD;&#xA;    std::ofstream outfile(nombFich);&#xD;&#xA;    outfile &lt;&lt; std::fixed &lt;&lt; std::setprecision(0);&#xD;&#xA;    outfile &lt;&lt; &quot;P3&quot; &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; &quot;# &quot; &lt;&lt; nombFich &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; &quot;#MAX=&quot; &lt;&lt; max &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; width &lt;&lt; &quot; &quot; &lt;&lt; height &lt;&lt; std::endl;&#xD;&#xA;    outfile &lt;&lt; color_resolution &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;    int i = 0;&#xD;&#xA;    for (auto v : img) {&#xD;&#xA;        outfile &lt;&lt; v[0]*factor &lt;&lt; &quot; &quot; &lt;&lt; v[1]*factor &lt;&lt; &quot; &quot; &lt;&lt; v[2]*factor &lt;&lt; &quot; &quot;;&#xD;&#xA;&#xD;&#xA;        i++;&#xD;&#xA;        if (i == width - 1) {i = 0; outfile &lt;&lt; std::endl;}&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The writing process writes correctly `height` rows of `width` values in the PPM.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Edit2:&#xD;&#xA;&#xD;&#xA;DAMN...It was so obvious I couldn't see the forest for the trees. I was indexing the image as `img[i*scene.camera.height + j]` instead of `img[i*scene.camera.width + j]`...&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I assume that now I should tweak my camera in order to get rid of the stretching?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2b0yC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/4Axab.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/V8qUm.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39105" PostHistoryTypeId="2" PostId="13129" RevisionGUID="b87aca81-e2d5-40a6-afe1-61667bb27629" CreationDate="2022-11-27T22:53:47.907" UserId="19264" Text="## turbulence function&#xD;&#xA;&#xD;&#xA;From my understanding, the turbulence in Perlin noise is to accumulate Perlin noise of different frequencies with different weights. Based on this understanding, the return value of turbulences should have the same range of color (or pixel).&#xD;&#xA;&#xD;&#xA;However, in some implementations ([Ray Tracing: The Next Week](https://raytracing.github.io/books/RayTracingTheNextWeek.html)) the range of [turbulence](https://raytracing.github.io/books/RayTracingTheNextWeek.html#perlinnoise/introducingturbulence) doesn't match the range of [0, 1]&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;double turb(const point3&amp; p, int depth=7) const {&#xD;&#xA;    auto accum = 0.0;&#xD;&#xA;    auto temp_p = p;&#xD;&#xA;    auto weight = 1.0;&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; depth; i++) {&#xD;&#xA;        accum += weight*noise(temp_p);&#xD;&#xA;        weight *= 0.5;&#xD;&#xA;        temp_p *= 2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    return fabs(accum);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The initial value of `weight` is 1, and the range of `noise` is [-1, 1]. So it is possible that after the first iteration, `accum` became 1, and the following iterations could make it larger than 1. &#xD;&#xA;&#xD;&#xA;I also read through the related part in the [original paper](https://dl.acm.org/doi/pdf/10.1145/325165.325247), however, the pseudocode seems very similar:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;function turbulence(p)&#xD;&#xA;  t = 0&#xD;&#xA;  scale = 1&#xD;&#xA;  while (scale &gt; pixelsize)&#xD;&#xA;      t += abs(Noise(p / scale) * scale)&#xD;&#xA;      scale /= 2&#xD;&#xA;  return t&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And it seems like the color representation in Perlin's original paper is also in the range of [0, 1] according to the the following line:&#xD;&#xA;&gt; For example, &#xD;&#xA;one possible pixel for the variable list [red green blue] is [0.5 0.3 &#xD;&#xA;0.7]. &#xD;&#xA;&#xD;&#xA;So I'm wondering if the `turbulence` function is designed this way because of the extremely low probability of returning a value that is out of range. Or am I missing something?&#xD;&#xA;&#xD;&#xA;## Noise function&#xD;&#xA;&#xD;&#xA;Also, the description of `Noise()` function in the original paper is pretty confusing. Perlin didn't explicitly write about the range of the returning value. But he used it this way:&#xD;&#xA;&gt; By evaluating Noise() at visible surface points of simulated objects we may create a simple &quot;random&quot; surface texture (figure Spotted.Donut) : &#xD;&#xA;&gt; color = white * Noise(point) &#xD;&#xA;&#xD;&#xA;So I'm assuming it should be [0, 1] which make the expression `white * Noise(point)` in the range of [0, 1]&#xD;&#xA;&#xD;&#xA;However, an `abs()` function is added in the `turbulence` function." ContentLicense="CC BY-SA 4.0" />
  <row Id="39107" PostHistoryTypeId="1" PostId="13129" RevisionGUID="b87aca81-e2d5-40a6-afe1-61667bb27629" CreationDate="2022-11-27T22:53:47.907" UserId="19264" Text="Confusion on the return value of turbulence of Perlin noise" ContentLicense="CC BY-SA 4.0" />
  <row Id="39108" PostHistoryTypeId="3" PostId="13129" RevisionGUID="b87aca81-e2d5-40a6-afe1-61667bb27629" CreationDate="2022-11-27T22:53:47.907" UserId="19264" Text="|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39117" PostHistoryTypeId="2" PostId="13132" RevisionGUID="075a28ff-e5e8-40bd-b305-f4fff3012797" CreationDate="2022-11-28T14:42:37.643" UserId="4958" Text="When I have an array of samplers, for example:&#xD;&#xA;&#xD;&#xA;    uniform sampler3D RHToBounceGridR[MULTI_BOUNCES_NUM];&#xD;&#xA;&#xD;&#xA;where ```MULTI_BOUNCES_NUM``` is bigger than ```GL_MAX_TEXTURE_IMAGE_UNITS``` value, I get ```INVALID_OPERATION``` when dispatching the shader.&#xD;&#xA;&#xD;&#xA;If I use Uniform block with bindless textures (handles)&#xD;&#xA;&#xD;&#xA;    layout (std140, binding = 0) uniform SamplersBuffer&#xD;&#xA;    {&#xD;&#xA;        sampler3D samplers[MULTI_BOUNCES_NUM];&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Or just uniforms&#xD;&#xA;&#xD;&#xA;    layout(bindless_sampler) uniform sampler3D RHToBounceGridR[MULTI_BOUNCES_NUM];&#xD;&#xA;&#xD;&#xA;Does it overcome this limitation?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39119" PostHistoryTypeId="1" PostId="13132" RevisionGUID="075a28ff-e5e8-40bd-b305-f4fff3012797" CreationDate="2022-11-28T14:42:37.643" UserId="4958" Text="Do bindless textures overcome the limit of GL_MAX_TEXTURE_IMAGE_UNITS?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39120" PostHistoryTypeId="3" PostId="13132" RevisionGUID="075a28ff-e5e8-40bd-b305-f4fff3012797" CreationDate="2022-11-28T14:42:37.643" UserId="4958" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39121" PostHistoryTypeId="2" PostId="13133" RevisionGUID="ed7e074a-74ba-417b-a347-505cc9397c58" CreationDate="2022-11-28T15:15:40.947" UserId="2654" Text="The specification defines `GL_MAX_TEXTURE_IMAGE_UNITS` as:&#xD;&#xA;&#xD;&#xA;&gt; The maximum number of texture image units available to [the fragment shader]&#xD;&#xA;&#xD;&#xA;Texture image units are locations in the OpenGL context to which you bind textures for use by shaders.&#xD;&#xA;&#xD;&#xA;Bindless texture, as the name suggests, does not involve binding textures to texture image units. As such, [they do not count against this limit][1]:&#xD;&#xA;&#xD;&#xA;&gt; Sampler uniforms specified using handles do not count as using any texture image unit, even if a texture referred to by a handle is currently bound to one or more texture image units.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL/extensions/ARB/ARB_bindless_texture.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="39123" PostHistoryTypeId="2" PostId="13134" RevisionGUID="37592b97-786c-4acd-823b-b913d9f510ef" CreationDate="2022-11-28T20:13:29.747" UserId="19180" Text="I'm working on some code to convert a 3d geometry from IFC to gltf/glb. One of the challenges I'm facing with this is that - IFC provides transformations for each primitive separately i.e., if I have a mesh (MeshA) which has 4 primitives, i'm getting a transformation matrix for each of the primitive. And once I construct MeshA using all these primitives, I would like to re-use this mesh in all other nodes where this mesh is referenced and apply a new transformation which I can retrieve from the respective mesh in IFC file.&#xD;&#xA;&#xD;&#xA;Below is the **available** structure of Geometry from IFC File:&#xD;&#xA;&#xD;&#xA;|        | IFC (Available)                                                        |&#xD;&#xA;|--------|------------------------------------------------------------------------|&#xD;&#xA;| Mesh 1 | primitive A -   TransformationA-1 &lt;br&gt; primitive B - TransformationB-1 |&#xD;&#xA;| Mesh 2 | primitive A -   TransformationA-2 &lt;br&gt; primitive B - TransformationB-2 |&#xD;&#xA;&#xD;&#xA;Below is the **expected** structure of geometry:&#xD;&#xA;&#xD;&#xA;|        |        | Gltf/Glb (Expected)                   |&#xD;&#xA;|--------|--------|---------------------------------------|&#xD;&#xA;|        | Mesh 1 | Primitive A + Primitive B             |&#xD;&#xA;| Node 1 | Mesh 1 | TransformationA-1 + TransformationB-1 |&#xD;&#xA;| Node 2 | Mesh 1 | TransformationA-2 + TransformationB-2 |&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;What I have currently tried is to &#xD;&#xA;- apply the transformations of each primitive on each of its respective Vertex &amp; Normal arrays to get a new set of arrays with the actual location after applying the transformation. &#xD;&#xA;- Then I add each primitive to a mesh and then add the mesh into a node&#xD;&#xA;&#xD;&#xA;But I'm having to do this to each mesh and create new mesh - instead of referencing the existing mesh (because I don't know the transformation of the entire mesh) - which is increasing the output size significantly.&#xD;&#xA;&#xD;&#xA;Can someone help me in understanding how to combine transformations of multiple primitives and apply it to a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39125" PostHistoryTypeId="1" PostId="13134" RevisionGUID="37592b97-786c-4acd-823b-b913d9f510ef" CreationDate="2022-11-28T20:13:29.747" UserId="19180" Text="How to apply transformation matrices from multiple primitives on a mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="39126" PostHistoryTypeId="3" PostId="13134" RevisionGUID="37592b97-786c-4acd-823b-b913d9f510ef" CreationDate="2022-11-28T20:13:29.747" UserId="19180" Text="|transformations|computational-geometry|javascript|linear-algebra|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39129" PostHistoryTypeId="2" PostId="13135" RevisionGUID="0a77292e-a612-4335-9223-d5fa5db6bf35" CreationDate="2022-11-29T01:05:20.533" UserId="19271" Text="(I don't have enough rep yet to add a comment)&#xD;&#xA;&#xD;&#xA;@pmw1234's explanation and solution work well. However, instead of writing out the perspective matrix by hand to handle the [0,1] Z-range of vulkan clip space, I found it easier to simply define `GLM_FORCE_DEPTH_ZERO_TO_ONE` for my project, e.g. in CMake, adding the line:&#xD;&#xA;```&#xD;&#xA;target_compile_definitions(&lt;target_name&gt; PUBLIC GLM_FORCE_DEPTH_ZERO_TO_ONE)&#xD;&#xA;```&#xD;&#xA;In summary, I could define my camera's projection matrix as the following, given the viewport's width and height, the &quot;zoom&quot; value for the camera, and the near/far plane:&#xD;&#xA;```cpp&#xD;&#xA;glm::mat4 proj = glm::perspective(glm::radians(Zoom), &#xD;&#xA;    static_cast&lt;float&gt;(ScreenWidth) / ScreenHeight, Near, Far);&#xD;&#xA;proj[1][1] *= -1;&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="39140" PostHistoryTypeId="2" PostId="13138" RevisionGUID="98f33815-6fd4-4524-8816-06ae78a944e9" CreationDate="2022-11-29T20:41:03.990" UserId="18711" Text="I always get `Only array uniforms may have count &gt; 1`&#xD;&#xA;&#xD;&#xA;Func returns [depthFramebuffer, checkerboardTexture, depthTexture]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;export const depthTextures = (gl) =&gt; {&#xD;&#xA;  // test&#xD;&#xA;  gl.activeTexture(gl.TEXTURE0 + 0);&#xD;&#xA;  const checkerboardTexture = gl.createTexture();&#xD;&#xA;  gl.bindTexture(gl.TEXTURE_2D, checkerboardTexture);&#xD;&#xA;  gl.texImage2D(&#xD;&#xA;    gl.TEXTURE_2D,&#xD;&#xA;    0,                // mip level&#xD;&#xA;    gl.LUMINANCE,     // internal format&#xD;&#xA;    8,                // width&#xD;&#xA;    8,                // height&#xD;&#xA;    0,                // border&#xD;&#xA;    gl.LUMINANCE,     // format&#xD;&#xA;    gl.UNSIGNED_BYTE, // type&#xD;&#xA;    new Uint8Array([  // data&#xD;&#xA;      0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,&#xD;&#xA;      0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,&#xD;&#xA;      0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,&#xD;&#xA;      0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,&#xD;&#xA;      0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,&#xD;&#xA;      0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,&#xD;&#xA;      0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC,&#xD;&#xA;      0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF, 0xCC, 0xFF,&#xD;&#xA;    ]));&#xD;&#xA;  gl.generateMipmap(gl.TEXTURE_2D);&#xD;&#xA;  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;&#xD;&#xA;  // test depth&#xD;&#xA; &#xD;&#xA;  const depthTexture = gl.createTexture();&#xD;&#xA;  const depthTextureSize = 512;&#xD;&#xA;  gl.bindTexture(gl.TEXTURE_2D, depthTexture);&#xD;&#xA;  gl.texImage2D(&#xD;&#xA;      gl.TEXTURE_2D,      // target&#xD;&#xA;      0,                  // mip level&#xD;&#xA;      gl.DEPTH_COMPONENT32F, // internal format&#xD;&#xA;      depthTextureSize,   // width&#xD;&#xA;      depthTextureSize,   // height&#xD;&#xA;      0,                  // border&#xD;&#xA;      gl.DEPTH_COMPONENT, // format&#xD;&#xA;      gl.FLOAT,           // type&#xD;&#xA;      null);              // data&#xD;&#xA;  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);&#xD;&#xA;  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);&#xD;&#xA;  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;  const depthFramebuffer = gl.createFramebuffer();&#xD;&#xA;  gl.bindFramebuffer(gl.FRAMEBUFFER, depthFramebuffer);&#xD;&#xA;  gl.framebufferTexture2D(&#xD;&#xA;      gl.FRAMEBUFFER,       // target&#xD;&#xA;      gl.DEPTH_ATTACHMENT,  // attachment point&#xD;&#xA;      gl.TEXTURE_2D,        // texture target&#xD;&#xA;      depthTexture,         // texture&#xD;&#xA;      0);                   // mip level&#xD;&#xA;  &#xD;&#xA;  // only for webgl1&#xD;&#xA;  // create a color texture of the same size as the depth texture&#xD;&#xA;  // see article why this is needed_&#xD;&#xA;  // const unusedTexture = gl.createTexture();&#xD;&#xA;  // gl.bindTexture(gl.TEXTURE_2D, unusedTexture);&#xD;&#xA;  // gl.texImage2D(&#xD;&#xA;  //   gl.TEXTURE_2D,&#xD;&#xA;  //   0,&#xD;&#xA;  //   gl.RGBA,&#xD;&#xA;  //   depthTextureSize,&#xD;&#xA;  //   depthTextureSize,&#xD;&#xA;  //   0,&#xD;&#xA;  //   gl.RGBA,&#xD;&#xA;  //   gl.UNSIGNED_BYTE,&#xD;&#xA;  //   null,&#xD;&#xA;  // );&#xD;&#xA;  // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);&#xD;&#xA;  // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);&#xD;&#xA;  // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);&#xD;&#xA;  // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;  // // attach it to the framebuffer&#xD;&#xA;  // gl.framebufferTexture2D(&#xD;&#xA;  //   gl.FRAMEBUFFER,        // target&#xD;&#xA;  //   gl.COLOR_ATTACHMENT0,  // attachment point&#xD;&#xA;  //   gl.TEXTURE_2D,         // texture target&#xD;&#xA;  //   unusedTexture,         // texture&#xD;&#xA;  //   0);                    // mip level&#xD;&#xA;&#xD;&#xA;  return [depthFramebuffer, checkerboardTexture, depthTexture]&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;App.operation.draws.drawSquareTex = function(object) {&#xD;&#xA;  var lighting = true;&#xD;&#xA;  // eslint-disable-next-line no-unused-vars&#xD;&#xA;  var localLooper = 0;&#xD;&#xA;&#xD;&#xA;  mat4.identity(object.mvMatrix);&#xD;&#xA;  this.mvPushMatrix(object.mvMatrix, this.mvMatrixStack);&#xD;&#xA;&#xD;&#xA;  if(object.isHUD === true) {&#xD;&#xA;&#xD;&#xA;    mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);&#xD;&#xA;    if(raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);&#xD;&#xA;&#xD;&#xA;  } else {&#xD;&#xA;&#xD;&#xA;    if(App.camera.FirstPersonController == true) {&#xD;&#xA;      camera.setCamera(object);&#xD;&#xA;    } else if(App.camera.SceneController == true) {&#xD;&#xA;      camera.setSceneCamera(object);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    mat4.translate(object.mvMatrix, object.mvMatrix, object.position.worldLocation);&#xD;&#xA;    if(raycaster.checkingProcedureCalc) raycaster.checkingProcedureCalc(object);&#xD;&#xA;    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rz), object.rotation.getRotDirZ());&#xD;&#xA;    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.rx), object.rotation.getRotDirX());&#xD;&#xA;    mat4.rotate(object.mvMatrix, object.mvMatrix, degToRad(object.rotation.ry), object.rotation.getRotDirY());&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // V&#xD;&#xA;  if(object.vertexPositionBuffer) {&#xD;&#xA;    world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexPositionBuffer);&#xD;&#xA;&#xD;&#xA;    if(object.geometry.dynamicBuffer == true) {&#xD;&#xA;      world.GL.gl.bufferData(world.GL.gl.ARRAY_BUFFER, object.geometry.vertices, world.GL.gl.STATIC_DRAW);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexPositionAttribute, object.vertexPositionBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);&#xD;&#xA;    world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexPositionAttribute);&#xD;&#xA;    localLooper = localLooper + 1;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // C&#xD;&#xA;  if(object.vertexColorBuffer) {&#xD;&#xA;    world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexColorBuffer);&#xD;&#xA;    world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexColorAttribute, object.vertexColorBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);&#xD;&#xA;    world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexColorAttribute);&#xD;&#xA;    localLooper = localLooper + 1;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // L&#xD;&#xA;  if(lighting &amp;&amp; object.shaderProgram.useLightingUniform) {&#xD;&#xA;    world.GL.gl.uniform1i(object.shaderProgram.useLightingUniform, lighting);&#xD;&#xA;    /* Set the normals */&#xD;&#xA;    if(object.vertexNormalBuffer) {&#xD;&#xA;      world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexNormalBuffer);&#xD;&#xA;      world.GL.gl.vertexAttribPointer(object.shaderProgram.vertexNormalAttribute, object.vertexNormalBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);&#xD;&#xA;      world.GL.gl.enableVertexAttribArray(object.shaderProgram.vertexNormalAttribute);&#xD;&#xA;      localLooper = localLooper + 1;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    /* Ambient light - posible deplaced */&#xD;&#xA;    if(object.shaderProgram.ambientColorUniform) {&#xD;&#xA;      if(E('ambLight') &amp;&amp; E('ambLight').color) {&#xD;&#xA;        world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, parseFloat(E('ambLight').color.rgb[0]), parseFloat(E('ambLight').color.rgb[1]), parseFloat(E('ambLight').color.rgb[2]));&#xD;&#xA;      } else {&#xD;&#xA;        world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, object.LightsData.ambientLight.r, object.LightsData.ambientLight.g, object.LightsData.ambientLight.b);&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    /* Directional light */&#xD;&#xA;    if(object.shaderProgram.directionalColorUniform) {&#xD;&#xA;      if(E('dirLight') &amp;&amp; E('dirLight').color) {&#xD;&#xA;        world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, parseFloat(E('dirLight').color.rgb[0]), parseFloat(E('dirLight').color.rgb[1]), parseFloat(E('dirLight').color.rgb[2]));&#xD;&#xA;      } else {&#xD;&#xA;        world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, object.LightsData.directionLight.R(), object.LightsData.directionLight.G(), object.LightsData.directionLight.B());&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    /* Normalize the direction */&#xD;&#xA;    var lightingDirection = null;&#xD;&#xA;    if(object.shaderProgram.lightingDirectionUniform) {&#xD;&#xA;      if(E('dirX') &amp;&amp; E('dirY') &amp;&amp; E('dirZ')) {&#xD;&#xA;        lightingDirection = [parseFloat(E('dirX').value), parseFloat(E('dirY').value), parseFloat(E('dirZ').value)];&#xD;&#xA;      } else {&#xD;&#xA;        lightingDirection = [object.LightsData.lightingDirection.r, object.LightsData.lightingDirection.g, object.LightsData.lightingDirection.b];&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;      var adjustedLD = vec3.create();&#xD;&#xA;      vec3.normalize(adjustedLD, lightingDirection);&#xD;&#xA;      vec3.scale(adjustedLD, adjustedLD, -1);&#xD;&#xA;      world.GL.gl.uniform3fv(object.shaderProgram.lightingDirectionUniform, adjustedLD);&#xD;&#xA;    }&#xD;&#xA;  } else {&#xD;&#xA;    if(object.shaderProgram.useLightingUniform) {&#xD;&#xA;      if(object.shaderProgram.ambientColorUniform) {&#xD;&#xA;        world.GL.gl.uniform3f(object.shaderProgram.ambientColorUniform, parseFloat(1), parseFloat(2), parseFloat(0));&#xD;&#xA;      }&#xD;&#xA;      if(object.shaderProgram.directionalColorUniform) {&#xD;&#xA;        world.GL.gl.uniform3f(object.shaderProgram.directionalColorUniform, parseFloat(1), parseFloat(0), parseFloat(0));&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // T&#xD;&#xA;  if(object.vertexTexCoordBuffer  ) {&#xD;&#xA;    world.GL.gl.bindBuffer(world.GL.gl.ARRAY_BUFFER, object.vertexTexCoordBuffer);&#xD;&#xA;&#xD;&#xA;    if(object.geometry.dynamicBuffer == true) {&#xD;&#xA;      world.GL.gl.bufferData(world.GL.gl.ARRAY_BUFFER, object.geometry.texCoords, world.GL.gl.STATIC_DRAW);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    world.GL.gl.vertexAttribPointer(object.shaderProgram.textureCoordAttribute, object.vertexTexCoordBuffer.itemSize, world.GL.gl.FLOAT, false, 0, 0);&#xD;&#xA;    world.GL.gl.enableVertexAttribArray(object.shaderProgram.textureCoordAttribute);&#xD;&#xA;&#xD;&#xA;    if(object.streamTextures != null) {&#xD;&#xA;      // video/webcam tex&#xD;&#xA;      // App.tools.loadVideoTexture('glVideoTexture', object.streamTextures.videoImage);&#xD;&#xA;      App.tools.loadVideoTexture('glVideoTexture', object.streamTextures.video);&#xD;&#xA;      world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, 0);&#xD;&#xA;    } else {&#xD;&#xA;      for(var t = 0;t &lt; object.textures.length;t++) {&#xD;&#xA;        if(object.custom.gl_texture == null) {&#xD;&#xA;&#xD;&#xA;          world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + t]);&#xD;&#xA;          world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.textures[t]);&#xD;&#xA;&#xD;&#xA;          world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);&#xD;&#xA;          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);&#xD;&#xA;&#xD;&#xA;          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);&#xD;&#xA;          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);&#xD;&#xA;          world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);&#xD;&#xA;          // -- Allocate storage for the texture&#xD;&#xA;          //world.GL.gl.texStorage2D(world.GL.gl.TEXTURE_2D, 1, world.GL.gl.RGB8, 512, 512);&#xD;&#xA;          //world.GL.gl.texSubImage2D(world.GL.gl.TEXTURE_2D, 0, 0, 0, world.GL.gl.RGB, world.GL.gl.UNSIGNED_BYTE, image);&#xD;&#xA;          //world.GL.gl.generateMipmap(world.GL.gl.TEXTURE_2D);&#xD;&#xA; &#xD;&#xA;          world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, t);&#xD;&#xA;&#xD;&#xA;        } else {&#xD;&#xA;          object.custom.gl_texture(object, t);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    localLooper = localLooper + 1;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  world.GL.gl.bindBuffer(world.GL.gl.ELEMENT_ARRAY_BUFFER, object.vertexIndexBuffer);&#xD;&#xA;  world.setMatrixUniforms(object, this.pMatrix, object.mvMatrix);&#xD;&#xA;&#xD;&#xA;  if(object.vertexNormalBuffer &amp;&amp; object.shaderProgram.nMatrixUniform) {&#xD;&#xA;    var normalMatrix = mat3.create();&#xD;&#xA;    mat3.normalFromMat4(normalMatrix, object.mvMatrix);&#xD;&#xA;    mat3.transpose(normalMatrix, normalMatrix);&#xD;&#xA;    world.GL.gl.uniformMatrix3fv(object.shaderProgram.nMatrixUniform, false, normalMatrix);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // world.disableUnusedAttr( world.GL.gl, localLooper);&#xD;&#xA;  world.disableUnusedAttr(world.GL.gl, 4); // ori&#xD;&#xA;&#xD;&#xA;  if(object.glBlend.blendEnabled == true) {&#xD;&#xA;    if(!world.GL.gl.isEnabled(world.GL.gl.BLEND)) {&#xD;&#xA;      // world.GL.gl.disable(world.GL.gl.DEPTH_TEST);&#xD;&#xA;      world.GL.gl.enable(world.GL.gl.BLEND);&#xD;&#xA;    }&#xD;&#xA;    try {&#xD;&#xA;      world.GL.gl.blendFunc(world.GL.gl[object.glBlend.blendParamSrc], world.GL.gl[object.glBlend.blendParamDest]);&#xD;&#xA;    } catch(e) {&#xD;&#xA;      console.log(e);&#xD;&#xA;    }&#xD;&#xA;  } else {&#xD;&#xA;    world.GL.gl.disable(world.GL.gl.BLEND);&#xD;&#xA;    world.GL.gl.enable(world.GL.gl.DEPTH_TEST);&#xD;&#xA;    world.GL.gl.enable(world.GL.gl.CULL_FACE);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // shadows&#xD;&#xA;  if(object.shadows &amp;&amp; object.shadows.type == 'spot' ||&#xD;&#xA;    object.shadows &amp;&amp; object.shadows.type == 'spot-shadow') {&#xD;&#xA;&#xD;&#xA;    const settings = {&#xD;&#xA;      cameraX: 6,&#xD;&#xA;      cameraY: 5,&#xD;&#xA;      posX: 2.5,&#xD;&#xA;      posY: 4.8,&#xD;&#xA;      posZ: 4.3,&#xD;&#xA;      targetX: 2.5,&#xD;&#xA;      targetY: 0,&#xD;&#xA;      targetZ: 3.5,&#xD;&#xA;      projWidth: 1,&#xD;&#xA;      projHeight: 1,&#xD;&#xA;      perspective: true,&#xD;&#xA;      fieldOfView: 120,&#xD;&#xA;      bias: -0.006,&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    if(!object.shadows.depthFramebuffer) {&#xD;&#xA;      console.log('ONLY ONCE !!!')&#xD;&#xA;      // world.GL.gl.activeTexture(world.GL.gl['TEXTURE' + 0]);&#xD;&#xA;      var depthFramebuffer = depthTextures(world.GL.gl);&#xD;&#xA;      object.shadows.depthFramebuffer = depthFramebuffer[0];&#xD;&#xA;      object.shadows.checkerboardTexture = depthFramebuffer[1];&#xD;&#xA;      object.shadows.depthTexture = depthFramebuffer[2];&#xD;&#xA;&#xD;&#xA;     // world.GL.gl.uniform3fv(object.shaderProgram.u_projectedTexture, object.shadows.depthTexture );&#xD;&#xA;       world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // console.log(&quot; SHADOWS -&gt; &quot; , object.shadows)&#xD;&#xA;    world.GL.gl.uniform3fv(object.shaderProgram.lightWorldPositionLocation, object.shadows.lightPosition);&#xD;&#xA;    world.GL.gl.uniform3fv(object.shaderProgram.viewWorldPositionLocation, object.shadows.lightPosition);&#xD;&#xA;    world.GL.gl.uniform1f(object.shaderProgram.shininessLocation, object.shadows.shininess);&#xD;&#xA;&#xD;&#xA;    // Set the spotlight uniforms&#xD;&#xA;    {&#xD;&#xA;      var target = [0, 0, 0];&#xD;&#xA;      var up = [0, 1, 0];&#xD;&#xA;      var lmat = m4.lookAt(object.shadows.lightPosition, target, up);&#xD;&#xA;      lmat = m4.multiply(m4.xRotation(object.shadows.lightRotationX), lmat);&#xD;&#xA;      lmat = m4.multiply(m4.yRotation(object.shadows.lightRotationY), lmat);&#xD;&#xA;      object.shadows.lightDirection = [-lmat[8], -lmat[9], -lmat[10]];&#xD;&#xA;      // object.shadows.lightDirection = [-0, -0, -1];&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // test&#xD;&#xA;    const viewMatrix = m4.inverse(lmat);&#xD;&#xA;    // first draw from the POV of the light&#xD;&#xA;    const lightWorldMatrix = m4.lookAt(&#xD;&#xA;      [settings.posX, settings.posY, settings.posZ],          // position&#xD;&#xA;      [settings.targetX, settings.targetY, settings.targetZ], // target&#xD;&#xA;      [0, 1, 0],                                              // up&#xD;&#xA;    );&#xD;&#xA;    const lightProjectionMatrix = settings.perspective&#xD;&#xA;      ? m4.perspective(&#xD;&#xA;        degToRad(settings.fieldOfView),&#xD;&#xA;        settings.projWidth / settings.projHeight,&#xD;&#xA;        0.5,  // near&#xD;&#xA;        10)   // far&#xD;&#xA;      : m4.orthographic(&#xD;&#xA;        -settings.projWidth / 2,   // left&#xD;&#xA;        settings.projWidth / 2,   // right&#xD;&#xA;        -settings.projHeight / 2,  // bottom&#xD;&#xA;        settings.projHeight / 2,  // top&#xD;&#xA;        0.5,                      // near&#xD;&#xA;        10);                      // far&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // draw to the depth texture&#xD;&#xA;    world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, object.shadows.depthFramebuffer);&#xD;&#xA;    world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.shadows.checkerboardTexture);&#xD;&#xA;    world.GL.gl.viewport(0, 0, 512, 512);&#xD;&#xA;    world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    // draw &#xD;&#xA;    let textureMatrix = m4.identity();&#xD;&#xA;    textureMatrix = m4.translate(textureMatrix, 0.5, 0.5, 0.5);&#xD;&#xA;    textureMatrix = m4.scale(textureMatrix, 0.5, 0.5, 0.5);&#xD;&#xA;    textureMatrix = m4.multiply(textureMatrix, lightProjectionMatrix);&#xD;&#xA;    textureMatrix = m4.multiply(&#xD;&#xA;      textureMatrix,&#xD;&#xA;      m4.inverse(lightWorldMatrix));&#xD;&#xA;&#xD;&#xA;    world.GL.gl.uniform4fv(object.shaderProgram.u_textureMatrix, textureMatrix);&#xD;&#xA;    world.GL.gl.uniform1f(object.shaderProgram.u_bias, -0.006);&#xD;&#xA;&#xD;&#xA;    world.GL.gl.uniform3fv(object.shaderProgram.lightDirectionLocation, object.shadows.lightDirection);&#xD;&#xA;    world.GL.gl.uniform1f(object.shaderProgram.innerLimitLocation, Math.cos(object.shadows.innerLimit));&#xD;&#xA;    world.GL.gl.uniform1f(object.shaderProgram.outerLimitLocation, Math.cos(object.shadows.outerLimit));&#xD;&#xA;    //world.GL.gl.uniform1i(object.shaderProgram.u_projectedTexture, 0);&#xD;&#xA;&#xD;&#xA;        // TEST &#xD;&#xA;        world.GL.gl.drawElements(world.GL.gl[object.glDrawElements.mode], object.glDrawElements.numberOfIndicesRender, world.GL.gl.UNSIGNED_SHORT, 0);&#xD;&#xA;&#xD;&#xA;    world.GL.gl.bindFramebuffer(world.GL.gl.FRAMEBUFFER, null);&#xD;&#xA;    world.GL.gl.viewport(0, 0, world.GL.gl.canvas.width, world.GL.gl.canvas.height);&#xD;&#xA;    world.GL.gl.clearColor(0.5, 0.5, 0.5, 1);&#xD;&#xA;    world.GL.gl.clear(world.GL.gl.COLOR_BUFFER_BIT | world.GL.gl.DEPTH_BUFFER_BIT);&#xD;&#xA; &#xD;&#xA;    world.GL.gl.bindTexture(world.GL.gl.TEXTURE_2D, object.shadows.depthTexture);&#xD;&#xA;&#xD;&#xA;    // world.GL.gl.pixelStorei(world.GL.gl.UNPACK_FLIP_Y_WEBGL, false);&#xD;&#xA;    // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MAG_FILTER, world.GL.gl.NEAREST);&#xD;&#xA;    // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_MIN_FILTER, world.GL.gl.NEAREST);&#xD;&#xA;    // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_S, world.GL.gl.CLAMP_TO_EDGE);&#xD;&#xA;    // world.GL.gl.texParameteri(world.GL.gl.TEXTURE_2D, world.GL.gl.TEXTURE_WRAP_T, world.GL.gl.CLAMP_TO_EDGE);&#xD;&#xA;     // world.GL.gl.uniform1i(object.shaderProgram.samplerUniform, 1);&#xD;&#xA;  &#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  world.GL.gl.drawElements(world.GL.gl[object.glDrawElements.mode], object.glDrawElements.numberOfIndicesRender, world.GL.gl.UNSIGNED_SHORT, 0);&#xD;&#xA;  object.instancedDraws.overrideDrawArraysInstance(object);&#xD;&#xA;&#xD;&#xA;  this.mvPopMatrix(object.mvMatrix, this.mvMatrixStack);&#xD;&#xA;};&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="39142" PostHistoryTypeId="1" PostId="13138" RevisionGUID="98f33815-6fd4-4524-8816-06ae78a944e9" CreationDate="2022-11-29T20:41:03.990" UserId="18711" Text="Warn GL_INVALID_OPERATION: Only array uniforms may have count &gt; 1" ContentLicense="CC BY-SA 4.0" />
  <row Id="39143" PostHistoryTypeId="3" PostId="13138" RevisionGUID="98f33815-6fd4-4524-8816-06ae78a944e9" CreationDate="2022-11-29T20:41:03.990" UserId="18711" Text="|webgl|frame-buffer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39144" PostHistoryTypeId="2" PostId="13139" RevisionGUID="cdb9f14d-bcd5-4159-828a-c758eef03766" CreationDate="2022-11-29T21:40:10.390" UserId="1908" Text="In the glTF format, &quot;primitives&quot; are just a way to specify separate draw calls (and hence, separate materials or shader programs) for a single mesh.  There is no transform, as you've discovered, applied to a glTF primitive separately from its parent mesh.&#xD;&#xA;&#xD;&#xA;I think your best bet here may be to take each IFC &quot;mesh&quot; and make it an empty parent node in glTF, and then take each IFC &quot;primitive&quot; and make it into a glTF child node + mesh + primitive with its transforms applied to the node.&#xD;&#xA;&#xD;&#xA;This would mean that each time an IFC mesh is reused, you would possibly need to place multiple child nodes and meshes in glTF.  But the raw vertex data wouldn't change per instance, so could be easily reused without duplication.&#xD;&#xA;&#xD;&#xA;If you have a substantial number of mesh instances, consider using [EXT_mesh_gpu_instancing](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing)." ContentLicense="CC BY-SA 4.0" />
  <row Id="39146" PostHistoryTypeId="5" PostId="13102" RevisionGUID="38d95b24-7899-417f-a67b-5c1c9d722e19" CreationDate="2022-11-30T08:01:15.987" UserId="7462" Comment="added 589 characters in body" Text="I am trying to transform the mesh data in a gltf file and then modify the skin and animation data accordingly.&#xD;&#xA;&#xD;&#xA;Let's say we want to transform the data using a 4x4 homogeneous matrix. For simplification let us say the transformation is just swapping the y and z axes.&#xD;&#xA;&#xD;&#xA;Doing it to the mesh data is simple enough:&#xD;&#xA;&#xD;&#xA;Something like this:&#xD;&#xA;```rust&#xD;&#xA;for mesh in &amp;gltf.meshes&#xD;&#xA;    {&#xD;&#xA;        for primitive in &amp;mesh.primitives&#xD;&#xA;        {&#xD;&#xA;            for position in gltf&#xD;&#xA;                .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.position)&#xD;&#xA;                .unwrap()&#xD;&#xA;            {&#xD;&#xA;                *position = transform_vec3(&amp;position, &amp;transform, true);&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            for normal in gltf&#xD;&#xA;                .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.normal)&#xD;&#xA;                .unwrap()&#xD;&#xA;            {&#xD;&#xA;                *normal = transform_vec3(&amp;normal, &amp;transform, false);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA; ```&#xD;&#xA;&#xD;&#xA;Now the issue is, after doing this, what must we do to the skin data and animation data to correctly change it so that now the y and z axes are swapped.&#xD;&#xA;&#xD;&#xA;We know that before our transformation, the animations are effectively computed as:&#xD;&#xA;&#xD;&#xA;$$(\sum \lambda_i A_i \cdot M_i) \cdot v$$ &#xD;&#xA;&#xD;&#xA;where $\lambda_i, A_i, M_i$ are the weights, animation matrices and inverse bind matrices.&#xD;&#xA;&#xD;&#xA;Now, after modifying the vertices of the mesh data we have:&#xD;&#xA;&#xD;&#xA;$$(\sum \lambda_i A_i \cdot M_i) \cdot T v$$ &#xD;&#xA;&#xD;&#xA;So we need to modify our matrices such that the transformation $T$ is applied only once after all other transformations are applied, so:&#xD;&#xA;&#xD;&#xA;$$T(\sum \lambda_i A_i \cdot M_i)T^{-1} T v$$ &#xD;&#xA;$$(\sum \lambda_i TA_i \cdot M_iT^{-1}) T v$$ &#xD;&#xA;&#xD;&#xA;The above formula suggests that the correct approach is to apply the transformation to all animation data and its inverse to the ibms.&#xD;&#xA;&#xD;&#xA;Something like:&#xD;&#xA;&#xD;&#xA; * for each ibm matrix ibm -&gt; ibm * $T^{-1}$&#xD;&#xA; * for each node in the skin node -&gt; $T$ * node &#xD;&#xA; * for each animation output in the skin, output -&gt; $T$ * output&#xD;&#xA;&#xD;&#xA;This fails miserably in all real life data I try and I don't understand why. For example this is the result on a model:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If I remove the skins from the model I get this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Which is the expected output, the mesh data has flipped the z and the y.&#xD;&#xA;&#xD;&#xA;So what must be done to convert the animation data to match the transform to the mesh?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/mZZTa.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/80Vaa.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39147" PostHistoryTypeId="2" PostId="13140" RevisionGUID="ddf85e6a-5f21-46cd-9932-ee967b55d1cb" CreationDate="2022-11-30T09:56:53.210" UserId="19275" Text="I am not sure if i am on the right forum. Let me know where to go if i'm wrong.&#xD;&#xA;&#xD;&#xA;I have an **ASUS** mATX motherboard **H110M2** and **PNY Quardro P620**. Initially I put it into a mini tower which only had a **450W** power unit. When I connect my fourth screen to my P620, I could either had 800x600 resolution or the fourth screen is not detected at all. For a such low resolution. I thought it's my TV having a low resolution or the HDMI cable was faulty.&#xD;&#xA;&#xD;&#xA;One day I moved my H110M2 to a full tower which had 500W power. My fourth screen connects without any hassle and obtained a full 1960 x 1280 resolution. I realised it's something to do with power.&#xD;&#xA;&#xD;&#xA;Because I didn't have the GPU bracket for the full tower, I kept changing cases, plugging and unplugging my graphic card, etc. But finally when I moved my motherboard back to my mini tower, the board is certified dead. It doesn't turn on any more. As I remember before it died, the P620 stopped working first. When I displayed out from my motherboard directly, my screen had a moment of smears of dots appearing and stripes appeared in the middle of the screen. I guess something burnt from that moment. When I turned off my computer, it never returned.&#xD;&#xA;&#xD;&#xA;Does somebody figure what happened? Is that the m-ATX motherboard just unable to output 4 displays or the power is too high for the motherboard?&#xD;&#xA;&#xD;&#xA;I am planning to buy a new motherboard but I tend to get an m-ATX rather than a full ATX. What specs should I look at if I want it fully support outputting 4 displays?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39149" PostHistoryTypeId="1" PostId="13140" RevisionGUID="ddf85e6a-5f21-46cd-9932-ee967b55d1cb" CreationDate="2022-11-30T09:56:53.210" UserId="19275" Text="What motherboard spec should i look for using 4 displays" ContentLicense="CC BY-SA 4.0" />
  <row Id="39150" PostHistoryTypeId="3" PostId="13140" RevisionGUID="ddf85e6a-5f21-46cd-9932-ee967b55d1cb" CreationDate="2022-11-30T09:56:53.210" UserId="19275" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39151" PostHistoryTypeId="5" PostId="13138" RevisionGUID="f4505af6-e296-4642-9ab3-c9f9de0d40c2" CreationDate="2022-11-30T12:09:56.730" UserId="18711" Comment="deleted 15522 characters in body" Text="I wanna implement shadows in my already exist glmatrix based project.&#xD;&#xA; You can see [project github][1] source. It is classic scebe object based structure. I have draw funcs i render recalls.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; By the this [youtube tutorial][2] + [code][3] ,  I figured that draw calls must be in order &#xD;&#xA;&#xD;&#xA;  Hronology of draw calls:&#xD;&#xA;```&#xD;&#xA;   this.gl.enable(this.gl.DEPTH_TEST);&#xD;&#xA;   this.gl.disable(this.gl.BLEND);&#xD;&#xA;   this.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;   - draw all `non fbo` and `no blend`&#xD;&#xA;&#xD;&#xA;    state.gl.enable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(false);&#xD;&#xA;&#xD;&#xA;   - draw all `non fbo` and `blend`&#xD;&#xA;    &#xD;&#xA;   (this line is after draw func in main render) &#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // moment after all (non fbo objects) draws.&#xD;&#xA;&#xD;&#xA;    state.gl.bindFramebuffer(state.gl.FRAMEBUFFER, null);&#xD;&#xA;    state.gl.viewport(0, 0, state.canvas.width, state.canvas.height);  &#xD;&#xA;&#xD;&#xA;    state.gl.clearColor(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    state.gl.clear(state.gl.COLOR_BUFFER_BIT | state.gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    // Draw again...&#xD;&#xA;    state.gl.enable(state.gl.DEPTH_TEST);&#xD;&#xA;    state.gl.disable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;     - draw **all** but `no blend`&#xD;&#xA;&#xD;&#xA;    // Leave on the depth test!&#xD;&#xA;    state.gl.enable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(false);&#xD;&#xA;&#xD;&#xA;     - draw **all** but `blend`&#xD;&#xA;&#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA; ```&#xD;&#xA;   &#xD;&#xA;Is this correct ?&#xD;&#xA;&#xD;&#xA;Is it nesessery to use `createRenderbuffer` ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/zlatnaspirala/matrix-engine&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=txcgqWdZwR8&amp;ab_channel=DavidParker&#xD;&#xA;  [3]: https://github.com/davidwparker/programmingtil-webgl/blob/master/0091-framebuffer-part-2/index.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="39152" PostHistoryTypeId="5" PostId="13138" RevisionGUID="d595778d-a064-4b30-8c8c-d3e163d518c5" CreationDate="2022-11-30T13:18:41.297" UserId="18711" Comment="added 255 characters in body" Text="I wanna implement shadows in my already exist glmatrix based project.&#xD;&#xA; You can see [project github][1] source. It is classic scebe object based structure. I have draw funcs i render recalls.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; By the this [youtube tutorial][2] + [code][3] ,  I figured that draw calls must be in order &#xD;&#xA;&#xD;&#xA;  Hronology of draw calls:&#xD;&#xA;```&#xD;&#xA;   this.gl.enable(this.gl.DEPTH_TEST);&#xD;&#xA;   this.gl.disable(this.gl.BLEND);&#xD;&#xA;   this.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;   - draw all `non fbo` and `no blend`&#xD;&#xA;&#xD;&#xA;    state.gl.enable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(false);&#xD;&#xA;&#xD;&#xA;   - draw all `non fbo` and `blend`&#xD;&#xA;    &#xD;&#xA;   (this line is after draw func in main render) &#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // moment after all (non fbo objects) draws.&#xD;&#xA;&#xD;&#xA;    state.gl.bindFramebuffer(state.gl.FRAMEBUFFER, null);&#xD;&#xA;    state.gl.viewport(0, 0, state.canvas.width, state.canvas.height);  &#xD;&#xA;&#xD;&#xA;    state.gl.clearColor(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    state.gl.clear(state.gl.COLOR_BUFFER_BIT | state.gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    // Draw again...&#xD;&#xA;    state.gl.enable(state.gl.DEPTH_TEST);&#xD;&#xA;    state.gl.disable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;     - draw **all** but `no blend`&#xD;&#xA;&#xD;&#xA;    // Leave on the depth test!&#xD;&#xA;    state.gl.enable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(false);&#xD;&#xA;&#xD;&#xA;     - draw **all** but `blend`&#xD;&#xA;&#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA; ```&#xD;&#xA;   &#xD;&#xA;Is this correct ?&#xD;&#xA;&#xD;&#xA;Is it nesessery to use `createRenderbuffer` ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I dont understand why this operation is put intro draw loop:&#xD;&#xA;```js&#xD;&#xA;    // Set FBOs&#xD;&#xA;    state.app.objects.forEach(function(obj) {&#xD;&#xA;      if (obj.state.hasTexture &amp;&amp; obj.state.hasFbo) {&#xD;&#xA;        obj.state.fbo = state.fbo;&#xD;&#xA;      }&#xD;&#xA;    });&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/zlatnaspirala/matrix-engine&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=txcgqWdZwR8&amp;ab_channel=DavidParker&#xD;&#xA;  [3]: https://github.com/davidwparker/programmingtil-webgl/blob/master/0091-framebuffer-part-2/index.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="39153" PostHistoryTypeId="33" PostId="13102" RevisionGUID="b059247d-3a10-477e-bc86-beeb71a254fb" CreationDate="2022-11-30T19:27:33.773" UserId="7462" Comment="80" />
  <row Id="39154" PostHistoryTypeId="2" PostId="13141" RevisionGUID="e328208a-ef10-47cb-b3cb-6d686e475083" CreationDate="2022-11-30T20:41:54.997" UserId="7462" Text="Say we have the transformation:&#xD;&#xA;&#xD;&#xA;\begin{bmatrix}&#xD;&#xA;1 &amp; 0 &amp; 0\\&#xD;&#xA;0 &amp; 0 &amp; 1\\&#xD;&#xA;0 &amp; 1 &amp; 0\\&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;i.e. the matrix that encodes swapping the z and y axes. This is equivalent to a reflection around the z=y line.&#xD;&#xA;&#xD;&#xA;Is it possible to encode this same transformation in a quaternion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39156" PostHistoryTypeId="1" PostId="13141" RevisionGUID="e328208a-ef10-47cb-b3cb-6d686e475083" CreationDate="2022-11-30T20:41:54.997" UserId="7462" Text="Can you encode a reflection in a quaternion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39157" PostHistoryTypeId="3" PostId="13141" RevisionGUID="e328208a-ef10-47cb-b3cb-6d686e475083" CreationDate="2022-11-30T20:41:54.997" UserId="7462" Text="|mathematics|animation|linear-algebra|quaternions|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39158" PostHistoryTypeId="2" PostId="13142" RevisionGUID="c63335ef-43ed-49f2-8506-63339264ce5a" CreationDate="2022-11-30T21:57:07.967" UserId="445" Text="As I understand it, the usual concept of a “material” in computer graphics, particularly 3D modeling, is a set of parameters (color, normal map, etc.), some specified by textures and some by constants, that are sufficient to simulate the appearance of some substance when applied to some shape.&#xD;&#xA;&#xD;&#xA;However, when computing the appearance of a single _point on a surface_ (or within a volume), these parameters take on single values (which may have been sampled from a texture) which are sufficient for the shader or raytracer to compute the effect of hitting that surface with that ray(/viewing angle).&#xD;&#xA;&#xD;&#xA;**Is there an established/recognizable name for the full set (whatever the shading technique in use requires) of these single-point values,** as distinct from the overall material? (Or, perhaps, are these too just “the material”?)&#xD;&#xA;&#xD;&#xA;The best description that has been suggested to me so far is “material sample” (sample of the material) but ideally, I would like a term that does not as strongly suggest that it is a piece of a larger entity that already existed, but rather an “atom” itself that could perhaps, but does not have to, be _assembled with others to create_ a material (including procedural generation that does not necessarily contain the original value at any point). I don't expect to necessarily find that, though. &#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;While the reason I'm asking this is to come up with vocabulary I can use in my program, to keep this question reasonably objective, please do not propose newly invented names — I'm only looking for any established terminology that I could use or at least take inspiration from." ContentLicense="CC BY-SA 4.0" />
  <row Id="39160" PostHistoryTypeId="1" PostId="13142" RevisionGUID="c63335ef-43ed-49f2-8506-63339264ce5a" CreationDate="2022-11-30T21:57:07.967" UserId="445" Text="Is there a name for the values of a material at a point?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39161" PostHistoryTypeId="3" PostId="13142" RevisionGUID="c63335ef-43ed-49f2-8506-63339264ce5a" CreationDate="2022-11-30T21:57:07.967" UserId="445" Text="|texture|sampling|material|terminology|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39162" PostHistoryTypeId="5" PostId="13142" RevisionGUID="e7416c1a-15ed-4d08-a1d2-15b107b86582" CreationDate="2022-11-30T23:33:36.180" UserId="445" Comment="added 64 characters in body" Text="As I understand it, the usual concept of a “material” in computer graphics, particularly 3D modeling, is a set of parameters (color, specular reflectivity, IOR, light emission, etc.), some specified by textures and some by constants, that are sufficient to simulate the appearance of some substance when applied to some shape.&#xD;&#xA;&#xD;&#xA;However, when computing the appearance of a single _point on a surface_ (or within a volume), these parameters take on single values (which may have been sampled from a texture) which are sufficient for the shader or raytracer to compute the effect of hitting that surface with that ray(/viewing angle).&#xD;&#xA;&#xD;&#xA;**Is there an established/recognizable name for the full set (whatever the shading technique in use requires) of these single-point values,** as distinct from the overall material? (Or, perhaps, are these too just “the material”?)&#xD;&#xA;&#xD;&#xA;The best description that has been suggested to me so far is “material sample” (sample of the material) but ideally, I would like a term that does not as strongly suggest that it is a piece of a larger entity that already existed, but rather an “atom” itself that could perhaps, but does not have to, be _assembled with others to create_ a material (including procedural generation that does not necessarily contain the original value at any point). I don't expect to necessarily find that, though. &#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;While the reason I'm asking this is to come up with vocabulary I can use in my program, to keep this question reasonably objective, please do not propose newly invented names — I'm only looking for any established terminology that I could use or at least take inspiration from." ContentLicense="CC BY-SA 4.0" />
  <row Id="39163" PostHistoryTypeId="5" PostId="13142" RevisionGUID="295160b7-b005-4817-af82-9b1967d4414b" CreationDate="2022-12-01T00:09:43.773" UserId="445" Comment="added 15 characters in body" Text="As I understand it, the usual concept of a “material” in computer graphics, particularly 3D modeling, is a set of parameters (_for example,_ color, specular reflectivity, IOR, light emission, etc.), some specified by textures and some by constants, that are sufficient to simulate the appearance of some substance when applied to some shape.&#xD;&#xA;&#xD;&#xA;However, when computing the appearance of a single _point on a surface_ (or within a volume), these parameters take on single values (which may have been sampled from a texture) which are sufficient for the shader or raytracer to compute the effect of hitting that surface with that ray(/viewing angle).&#xD;&#xA;&#xD;&#xA;**Is there an established/recognizable name for the full set (whatever the shading technique in use requires) of these single-point values,** as distinct from the overall material? (Or, perhaps, are these too just “the material”?)&#xD;&#xA;&#xD;&#xA;The best description that has been suggested to me so far is “material sample” (sample of the material) but ideally, I would like a term that does not as strongly suggest that it is a piece of a larger entity that already existed, but rather an “atom” itself that could perhaps, but does not have to, be _assembled with others to create_ a material (including procedural generation that does not necessarily contain the original value at any point). I don't expect to necessarily find that, though. &#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;While the reason I'm asking this is to come up with vocabulary I can use in my program, to keep this question reasonably objective, please do not propose newly invented names — I'm only looking for any established terminology that I could use or at least take inspiration from." ContentLicense="CC BY-SA 4.0" />
  <row Id="39164" PostHistoryTypeId="2" PostId="13143" RevisionGUID="4a669ec2-4d46-4f64-8290-a70672fed9c6" CreationDate="2022-12-01T09:42:04.537" UserId="18529" Text="I'm trying to implement a post-processing pass to detect silhouette-edges from depth data.&#xD;&#xA;(by silhouette-edge of a triangles mesh I mean the triangle edges shared by a front and a back-facing triangle relative to the view direction, see image below).&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;From the little research I've done, most of the methods used in games and 3d applications are based on finding the gradient of the eye Z coordinate in image space and then processing the values trying to isolate the silhouette-edges.&#xD;&#xA;&#xD;&#xA;Since I'm working for a CAD project, silhouettes need to be as precise as possible, while it looks to me that, with the methods mentioned above, the more accurate/sensitive your filter, the more artifacts are introduced (i.e. entire surfaces detected as edges when you look edge-on on something that extends far along the Z).&#xD;&#xA;&#xD;&#xA;Besides, one should carefully choose weights and tolerances for those algorithms.&#xD;&#xA;&#xD;&#xA;**What are some good examples of silhouette detection in post-processing in commercial products/game?**&#xD;&#xA;&#xD;&#xA;Specifically, I'd like to find something to compare my experiments against, and also to see the limitations of post-processing edge detection in a state-of-the-art application.&#xD;&#xA;&#xD;&#xA;Are there other algorithms for post-processing edge detection as alternatives to Sobel/Roberts cross/...?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pE57n.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39166" PostHistoryTypeId="1" PostId="13143" RevisionGUID="4a669ec2-4d46-4f64-8290-a70672fed9c6" CreationDate="2022-12-01T09:42:04.537" UserId="18529" Text="What are some good examples of post-processing edge detection?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39167" PostHistoryTypeId="3" PostId="13143" RevisionGUID="4a669ec2-4d46-4f64-8290-a70672fed9c6" CreationDate="2022-12-01T09:42:04.537" UserId="18529" Text="|opengl|directx11|post-processing|edge-detection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39168" PostHistoryTypeId="2" PostId="13144" RevisionGUID="bd8d86b0-5edd-40c0-a83e-7e8ede195253" CreationDate="2022-12-01T16:44:10.947" UserId="48" Text="No; quaternions can only represent proper rotations (i.e. without reflection).&#xD;&#xA;&#xD;&#xA;If you use non-unit quaternions, you can represent a combination of rotation and uniform scaling, but still not reflection." ContentLicense="CC BY-SA 4.0" />
  <row Id="39174" PostHistoryTypeId="2" PostId="13146" RevisionGUID="b4e35fd4-2321-4d3c-aecc-0704796cdfdd" CreationDate="2022-12-02T18:56:16.723" UserId="19284" Text="I've been researching for some time now the Relief Texture Mapping (https://www.inf.ufrgs.br/~oliveira/RTM.html), and I'm trying to identify implementations of this technique and its improvements in the industry (mainly game engines and rendering softwares) but I can't find anything about it.&#xD;&#xA;&#xD;&#xA;Do the usual methodologies have a better cost benefit? What is this based on? Are there difficulties in implementing this technique such as lack of a tool or optimizations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39176" PostHistoryTypeId="1" PostId="13146" RevisionGUID="b4e35fd4-2321-4d3c-aecc-0704796cdfdd" CreationDate="2022-12-02T18:56:16.723" UserId="19284" Text="Is Relief Mapping techniques being used these days?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39177" PostHistoryTypeId="3" PostId="13146" RevisionGUID="b4e35fd4-2321-4d3c-aecc-0704796cdfdd" CreationDate="2022-12-02T18:56:16.723" UserId="19284" Text="|texture|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39178" PostHistoryTypeId="2" PostId="13147" RevisionGUID="c6bdcfbf-7fc2-42c2-8df0-bf3ab9ef809e" CreationDate="2022-12-02T22:06:43.500" UserId="7952" Text="&quot;Relief Texture Mapping&quot; is comparable to &quot;Parallax Occlusion Mapping&quot; (POM). POM is common in rendering systems/games and more popular then the &quot;Relief Texture Mapping&quot; technique mostly because it is easier to implement, has better documentation, and tends to perform better. I have an old relief mapping shader for GLSL that I could post if you are interested. But I suggest looking into Parallax Mapping instead.&#xD;&#xA;&#xD;&#xA;Relief Texture Mapping usually produces better results and has a lot of extensions. But POM has the edge on efficiency and produces &quot;good enough&quot; results. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39180" PostHistoryTypeId="2" PostId="13148" RevisionGUID="7d6c09ac-d7e6-4d30-acf7-3bf22dff6850" CreationDate="2022-12-03T02:19:10.547" UserId="7462" Text="I have a non AA, non cubic, box living happily in 3D.&#xD;&#xA;&#xD;&#xA;I have a frustuum defined by 2 squares. one square is the square defined by [-1, 1]^2 and the other square can have any size, there is also a distance between the two faces that is specified by $l$.&#xD;&#xA;&#xD;&#xA;We identify 2 opposite faces on the box. We want to map the box onto our frustum such that one of the 2 selected faces maps to the [-1, 1] face and the other to the other face.&#xD;&#xA;&#xD;&#xA;To try to elaborate on what I am doing, I am trying to define a reverse perspective matrix. Something that produces something akin to this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But I am using it for texture mapping not for rendering directly. What I am looking for is the property that objects closer to the furthest face will be larger and objects closest to the front face will be smaller after the projection.&#xD;&#xA;&#xD;&#xA;I am having a hard time finding theory resources that explain how to build the camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5xknx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39182" PostHistoryTypeId="1" PostId="13148" RevisionGUID="7d6c09ac-d7e6-4d30-acf7-3bf22dff6850" CreationDate="2022-12-03T02:19:10.547" UserId="7462" Text="Mapping a box to a n inverse frustum" ContentLicense="CC BY-SA 4.0" />
  <row Id="39183" PostHistoryTypeId="3" PostId="13148" RevisionGUID="7d6c09ac-d7e6-4d30-acf7-3bf22dff6850" CreationDate="2022-12-03T02:19:10.547" UserId="7462" Text="|perspective|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39188" PostHistoryTypeId="50" PostId="10537" RevisionGUID="fa20fc04-ca18-4eab-a1a3-612fcd13f2b8" CreationDate="2022-12-03T12:03:25.387" UserId="-1" />
  <row Id="39189" PostHistoryTypeId="50" PostId="12826" RevisionGUID="c2c814f3-eca3-4fa1-9a42-2d73e02ffa28" CreationDate="2022-12-03T14:08:21.010" UserId="-1" />
  <row Id="39190" PostHistoryTypeId="2" PostId="13150" RevisionGUID="da67d64e-8d42-418c-a59a-e477e60911e2" CreationDate="2022-12-03T17:53:47.133" UserId="19285" Text="I'm new to openGL and I was following [this][1] tutorial in which they showed how to make shadow maps but I could't understand how to get it to work for non-directional lights. They have [some instructions][2] on how to extend it to work for point lights as well but I could't understand them and couldn't get it to work when trying to figure it out. Full source code of the tutorial [here][3] (simple version .cpp file and shadowmapping shaders) and here follows the snippets I'm working on. First the code for the directional light that works well:&#xD;&#xA;&#xD;&#xA;main .cpp file&#xD;&#xA;```&#xD;&#xA;// Compute the MVP matrix from the light's point of view&#xD;&#xA;glm::vec3 lightInvDir = glm::vec3(0.5f,2,2);&#xD;&#xA;glm::mat4 depthProjectionMatrix = glm::ortho&lt;float&gt;(-10,10,-10,10,-10,20);&#xD;&#xA;glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0,0,0), glm::vec3(0,1,0));&#xD;&#xA;&#xD;&#xA;glm::mat4 depthModelMatrix = glm::mat4(1.0);&#xD;&#xA;glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;&#xD;&#xA;&#xD;&#xA;// Send our transformation to the currently bound shader, &#xD;&#xA;// in the &quot;MVP&quot; uniform&#xD;&#xA;glUniformMatrix4fv(depthMatrixID, 1, GL_FALSE, &amp;depthMVP[0][0]);&#xD;&#xA;&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;// Compute the MVP matrix from keyboard and mouse input&#xD;&#xA;computeMatricesFromInputs();&#xD;&#xA;glm::mat4 ProjectionMatrix = getProjectionMatrix();&#xD;&#xA;glm::mat4 ViewMatrix = getViewMatrix();&#xD;&#xA;//ViewMatrix = glm::lookAt(glm::vec3(14,6,4), glm::vec3(0,1,0), glm::vec3(0,1,0));&#xD;&#xA;glm::mat4 ModelMatrix = glm::mat4(1.0);&#xD;&#xA;glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;&#xD;&#xA;&#xD;&#xA;glm::mat4 normaliseMatrix(&#xD;&#xA;    0.5, 0.0, 0.0, 0.0, &#xD;&#xA;    0.0, 0.5, 0.0, 0.0,&#xD;&#xA;    0.0, 0.0, 0.5, 0.0,&#xD;&#xA;    0.5, 0.5, 0.5, 1.0&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;// Send our transformation to the currently bound shader, &#xD;&#xA;// in the &quot;MVP&quot; uniform&#xD;&#xA;glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &amp;MVP[0][0]);&#xD;&#xA;glUniformMatrix4fv(NormaliseID, 1, GL_FALSE, &amp;normaliseMatrix[0][0]);&#xD;&#xA;glUniformMatrix4fv(DepthMatrixID, 1, GL_FALSE, &amp;depthMVP[0][0]);&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;vertex shader&#xD;&#xA;```&#xD;&#xA;// Output position of the vertex, in clip space : MVP * position&#xD;&#xA;gl_Position =  MVP * vec4(vertexPosition_modelspace,1);&#xD;&#xA;&#xD;&#xA;ShadowCoord = normaliseMVP * depthMVP * vec4(vertexPosition_modelspace,1);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;fragment shader&#xD;&#xA;```&#xD;&#xA;// Light emission properties&#xD;&#xA;vec3 LightColor = vec3(1,1,1);&#xD;&#xA;&#xD;&#xA;float visibility = texture( shadowMap, vec3(ShadowCoord.xy, (ShadowCoord.z)/ShadowCoord.w) );&#xD;&#xA;&#xD;&#xA;color = visibility * LightColor;&#xD;&#xA;```&#xD;&#xA;And I've tried to edit it per their instructions but I had a hard time understanding what to do. I've tried different things but my code looks something something like the following (only showing the edited rows from the snippets above):&#xD;&#xA;&#xD;&#xA;main .cpp file&#xD;&#xA;```&#xD;&#xA;glm::vec3 lightPos(5, 20, 20);&#xD;&#xA;glm::mat4 depthProjectionMatrix = glm::perspective&lt;float&gt;(glm::radians(45.0f), 1.0f, 0.1f, 100.0f);&#xD;&#xA;glm::mat4 depthViewMatrix = glm::lookAt(lightPos, lightPos-lightInvDir, glm::vec3(0,1,0));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;fragment shader&#xD;&#xA;```&#xD;&#xA;float visibility= 1.0f;&#xD;&#xA;if ( texture( shadowMap, ShadowCoord.xy ).z  &lt; ShadowCoord.z ){&#xD;&#xA;    visibility = 0.0f;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This hasn't worked and I have no idea why or what needs to be done differently. The changes to the fragment shader also throw error messages that I don't know how to resolve.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Directional light][4]][4]&#xD;&#xA;Image 1: The directional light that works well, roughly what I expect to see from a point light too.&#xD;&#xA;&#xD;&#xA;[![No shadows][5]][5]&#xD;&#xA;Image 2: Most of my failed attempts show no sign of a shadow.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/&#xD;&#xA;  [2]: https://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#spot-lights&#xD;&#xA;  [3]: https://github.com/opengl-tutorials/ogl/tree/master/tutorial16_shadowmaps&#xD;&#xA;  [4]: https://i.stack.imgur.com/OkZDx.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/7fU2i.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39192" PostHistoryTypeId="1" PostId="13150" RevisionGUID="da67d64e-8d42-418c-a59a-e477e60911e2" CreationDate="2022-12-03T17:53:47.133" UserId="19285" Text="Shadow mapping with non-directional light" ContentLicense="CC BY-SA 4.0" />
  <row Id="39193" PostHistoryTypeId="3" PostId="13150" RevisionGUID="da67d64e-8d42-418c-a59a-e477e60911e2" CreationDate="2022-12-03T17:53:47.133" UserId="19285" Text="|opengl|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39194" PostHistoryTypeId="5" PostId="13148" RevisionGUID="6b79174a-e58d-4178-a605-fb8574bf974a" CreationDate="2022-12-04T22:22:00.237" UserId="7952" Comment="fixed minor typos" Text="I have a non AA, non cubic, box living happily in 3D.&#xD;&#xA;&#xD;&#xA;I have a frustum defined by 2 squares. one square is the square defined by [-1, 1]^2 and the other square can have any size, there is also a distance between the two faces that is specified by $l$.&#xD;&#xA;&#xD;&#xA;We identify 2 opposite faces on the box. We want to map the box onto our frustum such that one of the 2 selected faces maps to the [-1, 1] face and the other to the other face.&#xD;&#xA;&#xD;&#xA;To try to elaborate on what I am doing, I am trying to define a reverse perspective matrix. Something that produces something akin to this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But I am using it for texture mapping not for rendering directly. What I am looking for is the property that objects closer to the furthest face will be larger and objects closest to the front face will be smaller after the projection.&#xD;&#xA;&#xD;&#xA;I am having a hard time finding theory resources that explain how to build the camera.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5xknx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39195" PostHistoryTypeId="4" PostId="13148" RevisionGUID="6b79174a-e58d-4178-a605-fb8574bf974a" CreationDate="2022-12-04T22:22:00.237" UserId="7952" Comment="fixed minor typos" Text="Mapping a box to an inverse frustum" ContentLicense="CC BY-SA 4.0" />
  <row Id="39196" PostHistoryTypeId="2" PostId="13151" RevisionGUID="fcb57ff6-0982-4be3-b909-4c9f2045415d" CreationDate="2022-12-04T23:21:45.500" UserId="13972" Text="I have an image of size `H`,`W`, and I would like to draw a point on this image at `x`,`y`, where those values are floats.&#xD;&#xA;I tried bi-linear interpretation but that didn't give good results, but when I generated hi res image (e.g. of size `4H`,`4W`, and placed the point at `4x`,`4y`), and then downsampled it with AA filter (or just xv&#xD;&#xA;area), I got a much better quality.&#xD;&#xA;Is there's a way to get the same results without generating the hi res image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39198" PostHistoryTypeId="1" PostId="13151" RevisionGUID="fcb57ff6-0982-4be3-b909-4c9f2045415d" CreationDate="2022-12-04T23:21:45.500" UserId="13972" Text="Float point placement with anti aliasing" ContentLicense="CC BY-SA 4.0" />
  <row Id="39199" PostHistoryTypeId="3" PostId="13151" RevisionGUID="fcb57ff6-0982-4be3-b909-4c9f2045415d" CreationDate="2022-12-04T23:21:45.500" UserId="13972" Text="|image-processing|interpolation|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39200" PostHistoryTypeId="50" PostId="9192" RevisionGUID="be6f9fee-0516-4d76-b736-44e4278c78b7" CreationDate="2022-12-05T04:04:45.550" UserId="-1" />
  <row Id="39201" PostHistoryTypeId="50" PostId="13089" RevisionGUID="7eb0393e-fe6f-4f9d-9135-ea09114d66fb" CreationDate="2022-12-06T06:02:30.270" UserId="-1" />
  <row Id="39202" PostHistoryTypeId="50" PostId="9549" RevisionGUID="ad722be5-076a-4427-badc-d004c2738a68" CreationDate="2022-12-06T16:03:40.450" UserId="-1" />
  <row Id="39203" PostHistoryTypeId="5" PostId="4994" RevisionGUID="83e7bd9a-f122-470f-97dd-7f418a7ea29d" CreationDate="2022-12-06T16:14:20.853" UserId="310" Comment="typo" Text="Short answer:&#xD;&#xA;=============&#xD;&#xA;&#xD;&#xA;**Importance sampling** is a method to reduce variance in Monte Carlo Integration by choosing an estimator close to the shape of the actual function.&#xD;&#xA;&#xD;&#xA;**PDF** is an abbreviation for [Probability Density Function][1]. A $pdf(x)$ gives the probability of a random sample generated being $x$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Long Answer:&#xD;&#xA;=====&#xD;&#xA;&#xD;&#xA;To start, let's review what Monte Carlo Integration is, and what it looks like mathematically. &#xD;&#xA;&#xD;&#xA;Monte Carlo Integration is an technique to estimate the value of an integral. It's typically used when there isn't a closed form solution to the integral. It looks like this:&#xD;&#xA;&#xD;&#xA;$$\int f(x) \, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;In english, this says that you can approximate an integral by averaging successive random samples from the function. As $N$ gets large, the approximation gets closer and closer to the solution. $pdf(x_{i})$ represents the probability density function of each random sample.&#xD;&#xA;&#xD;&#xA;Let's do an example: Calculate the value of the integral $I$.&#xD;&#xA;&#xD;&#xA;$$I = \int_{0}^{2\pi} e^{-x} \sin(x) dx$$&#xD;&#xA;&#xD;&#xA;Let's use Monte Carlo Integration:&#xD;&#xA;&#xD;&#xA;$$I \approx \frac{1}{N} \sum_{i=1}^N \frac{e^{-x} \sin(x_i)}{pdf(x_{i})}$$&#xD;&#xA;&#xD;&#xA;A simple python program to calculate this is:&#xD;&#xA;&#xD;&#xA;    import random&#xD;&#xA;    import math&#xD;&#xA;&#xD;&#xA;    N = 200000&#xD;&#xA;    TwoPi = 2.0 * math.pi&#xD;&#xA;&#xD;&#xA;    sum = 0.0&#xD;&#xA;&#xD;&#xA;    for i in range(N):&#xD;&#xA;        x = random.uniform(0, TwoPi)&#xD;&#xA;        &#xD;&#xA;        fx = math.exp(-x) * math.sin(x)&#xD;&#xA;        pdf = 1 / (TwoPi - 0.0)&#xD;&#xA;        &#xD;&#xA;        sum += fx / pdf&#xD;&#xA;&#xD;&#xA;    I = (1 / N) * sum&#xD;&#xA;    print(I)&#xD;&#xA;&#xD;&#xA;If we run the program we get $I = 0.4986941$&#xD;&#xA;&#xD;&#xA;Using separation by parts, we can get the exact solution:&#xD;&#xA;&#xD;&#xA;$$I = \frac{1}{2} (1 − e−2π) = 0.4990663$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;You'll notice that the Monte Carlo Solution is not quite correct. This is because it is an estimate. That said, as $N$ goes to infinity, the estimate should get closer and closer to the correct answer. Already at $N = 2000$ some runs are almost identical to the correct answer.&#xD;&#xA;&#xD;&#xA;A note about the PDF: In this simple example, we always take a uniform random sample. A uniform random sample means every sample has the exact same probability of being chosen. We sample in the range $[0, 2\pi]$ so, $pdf(x) = 1 / (2\pi - 0)$&#xD;&#xA;&#xD;&#xA;Importance sampling works by *not* uniformly sampling. Instead we try to choose more samples that contribute a lot to the result (important), and less samples that only contribute a little to the result (less important). Hence the name, importance sampling.&#xD;&#xA;&#xD;&#xA;If you choose a sampling function whose pdf very closely matches the shape of $f$, you can greatly reduce the variance, which means you can take less samples. However, if you choose a sampling function whose value is very different from $f$, you can ***increase*** the variance. See the picture below:&#xD;&#xA;[![Comparison of good sampling vs bad sampling][2]][2]&#xD;&#xA;Image from Wojciech Jarosz's [Dissertation Appendix A][3]&#xD;&#xA;&#xD;&#xA;One example of importance sampling in Path Tracing is how to choose the direction of a ray after it hits a surface. If the surface is not perfectly specular (ie. a mirror or glass), the outgoing ray can be anywhere in the hemisphere.&#xD;&#xA;&#xD;&#xA;[![Outgoing rays can go anywhere in the hemisphere][4]][4]&#xD;&#xA;&#xD;&#xA;We ***could*** uniformly sample the hemisphere to generate the new ray. However, we can exploit the fact that the rendering equation has a cosine factor in it:&#xD;&#xA;&#xD;&#xA;$$L_{\text{o}}(p, \omega_{\text{o}}) =  L_{e}(p, \omega_{\text{o}}) + \int_{\Omega} f(p, \omega_{\text{i}}, \omega_{\text{o}}) L_{\text{i}}(p, \omega_{\text{i}}) \left | \cos \theta_{\text{i}} \right | d\omega_{\text{i}}$$&#xD;&#xA;&#xD;&#xA;Specifically, we know that any rays at the horizon will be heavily attenuated (specifically, $\cos(x)$ ). So, rays generated near the horizon will not contribute very much to the final value.&#xD;&#xA;&#xD;&#xA;To combat this, we use importance sampling. If we generate rays according to a cosine weighted hemisphere, we ensure that more rays are generated well above the horizon, and less near the horizon. This will lower variance and reduce noise.&#xD;&#xA;&#xD;&#xA;In your case, you specified that you will be using a Cook-Torrance, microfacet-based BRDF. The common form being:&#xD;&#xA;&#xD;&#xA;$$f(p, \omega_{\text{i}}, \omega_{\text{o}}) = \frac{F(\omega_{\text{i}}, h) G(\omega_{\text{i}}, \omega_{\text{o}}, h) D(h)}{4 \cos(\theta_{i}) \cos(\theta_{o})}$$&#xD;&#xA;&#xD;&#xA;where &#xD;&#xA;&#xD;&#xA;$$F(\omega_{\text{i}}, h) = \text{Fresnel function} \\&#xD;&#xA;G(\omega_{\text{i}}, \omega_{\text{o}}, h) = \text{Geometry Masking and Shadowing function} \\&#xD;&#xA;D(h) = \text{Normal Distribution Function}$$&#xD;&#xA;&#xD;&#xA;The blog &quot;A Graphic's Guy's Note&quot; has an excellent write up on how to sample Cook-Torrance BRDFs. I will refer you to [his blog post][5]. That said, I will try to create a brief overview below:&#xD;&#xA;&#xD;&#xA;The NDF is generally the dominant portion of the Cook-Torrance BRDF, so if we are going to importance sample, then we should sample based on the NDF.&#xD;&#xA;&#xD;&#xA;Cook-Torrance doesn't specify a specific NDF to use; we are free to choose whichever one suits our fancy. That said, there are a few popular NDFs:&#xD;&#xA;&#xD;&#xA; - GGX&#xD;&#xA; - Beckmann&#xD;&#xA; - Blinn&#xD;&#xA;&#xD;&#xA;Each NDF has it's own formula, thus each must be sampled differently. I am only going to show the final sampling function for each. If you would like to see how the formula is derived, see the blog post.&#xD;&#xA;&#xD;&#xA;**GGX** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{GGX}(m) = \frac{\alpha^2}{\pi((\alpha^2-1) \cos^2(\theta) + 1)^2}$$&#xD;&#xA;&#xD;&#xA;To sample the spherical coordinates angle $\theta$, we can use the formula:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left( \sqrt{\frac{\alpha^2}{\xi_1 (\alpha^2 - 1) + 1}} \right)$$&#xD;&#xA;&#xD;&#xA;where $\xi$ is a uniform random variable.&#xD;&#xA;&#xD;&#xA;We assume that the NDF is isotropic, so we can sample $\phi$ uniformly:&#xD;&#xA;&#xD;&#xA;$$\phi = \xi_{2}$$&#xD;&#xA;&#xD;&#xA;**Beckmann** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Beckmann}(m) = \frac{1}{\pi \alpha^2\cos^4(\theta)} e^{-\frac{\tan^2(\theta)}{\alpha^2}}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\sqrt{\frac{1}{1 = \alpha^2 \ln(1 - \xi_1)}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;Lastly, **Blinn** is defined as:&#xD;&#xA;&#xD;&#xA;$$D_{Blinn}(m) = \frac{\alpha + 2}{2 \pi} (\cos(\theta))^{\alpha}$$&#xD;&#xA;&#xD;&#xA;Which can be sampled with:&#xD;&#xA;&#xD;&#xA;$$\theta = \arccos \left(\frac{1}{\xi_{1}^{\alpha + 1}} \right) \\&#xD;&#xA;\phi = \xi_2$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Putting it in Practice&#xD;&#xA;-----------&#xD;&#xA;&#xD;&#xA;Let's look at a basic backwards path tracer:&#xD;&#xA;&#xD;&#xA;    void RenderPixel(uint x, uint y, UniformSampler *sampler) {&#xD;&#xA;        Ray ray = m_scene-&gt;Camera.CalculateRayFromPixel(x, y, sampler);&#xD;&#xA;&#xD;&#xA;        float3 color(0.0f);&#xD;&#xA;        float3 throughput(1.0f);&#xD;&#xA;&#xD;&#xA;        // Bounce the ray around the scene&#xD;&#xA;        for (uint bounces = 0; bounces &lt; 10; ++bounces) {&#xD;&#xA;            m_scene-&gt;Intersect(ray);&#xD;&#xA;&#xD;&#xA;            // The ray missed. Return the background color&#xD;&#xA;            if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {&#xD;&#xA;                color += throughput * float3(0.846f, 0.933f, 0.949f);&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            // We hit an object&#xD;&#xA;            &#xD;&#xA;            // Fetch the material&#xD;&#xA;            Material *material = m_scene-&gt;GetMaterial(ray.geomID);&#xD;&#xA;            // The object might be emissive. If so, it will have a corresponding light&#xD;&#xA;            // Otherwise, GetLight will return nullptr&#xD;&#xA;            Light *light = m_scene-&gt;GetLight(ray.geomID);&#xD;&#xA;&#xD;&#xA;            // If we hit a light, add the emmisive light&#xD;&#xA;            if (light != nullptr) {&#xD;&#xA;                color += throughput * light-&gt;Le();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            float3 normal = normalize(ray.Ng);&#xD;&#xA;            float3 wo = normalize(-ray.dir);&#xD;&#xA;            float3 surfacePos = ray.org + ray.dir * ray.tfar;&#xD;&#xA;&#xD;&#xA;            // Get the new ray direction&#xD;&#xA;            // Choose the direction based on the material&#xD;&#xA;            float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;            float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;            // Accumulate the brdf attenuation&#xD;&#xA;            throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;            // Shoot a new ray&#xD;&#xA;&#xD;&#xA;            // Set the origin at the intersection point&#xD;&#xA;            ray.org = surfacePos;&#xD;&#xA;&#xD;&#xA;            // Reset the other ray properties&#xD;&#xA;            ray.dir = wi;&#xD;&#xA;            ray.tnear = 0.001f;&#xD;&#xA;            ray.tfar = embree::inf;&#xD;&#xA;            ray.geomID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.primID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.instID = RTC_INVALID_GEOMETRY_ID;&#xD;&#xA;            ray.mask = 0xFFFFFFFF;&#xD;&#xA;            ray.time = 0.0f;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        m_scene-&gt;Camera.FrameBuffer.SplatPixel(x, y, color);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;IE. we bounce around the scene, accumulating color and light attenuation as we go. At each bounce, we have to choose a new direction for the ray. As mentioned above, we ***could*** uniformly sample the hemisphere to generate the new ray. However, the code is smarter; it importance samples the new direction based on the BRDF. (Note: This is the input direction, because we are a backwards path tracer)&#xD;&#xA;&#xD;&#xA;    // Get the new ray direction&#xD;&#xA;    // Choose the direction based on the material&#xD;&#xA;    float3 wi = material-&gt;Sample(wo, normal, sampler);&#xD;&#xA;    float pdf = material-&gt;Pdf(wi, normal);&#xD;&#xA;&#xD;&#xA;Which could be implemented as:&#xD;&#xA;&#xD;&#xA;    void LambertBRDF::Sample(float3 outputDirection, float3 normal, UniformSampler *sampler) {&#xD;&#xA;        float rand = sampler-&gt;NextFloat();&#xD;&#xA;        float r = std::sqrtf(rand);&#xD;&#xA;        float theta = sampler-&gt;NextFloat() * 2.0f * M_PI;&#xD;&#xA;&#xD;&#xA;        float x = r * std::cosf(theta);&#xD;&#xA;        float y = r * std::sinf(theta);&#xD;&#xA;&#xD;&#xA;        // Project z up to the unit hemisphere&#xD;&#xA;        float z = std::sqrtf(1.0f - x * x - y * y);&#xD;&#xA;&#xD;&#xA;        return normalize(TransformToWorld(x, y, z, normal));&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float3a TransformToWorld(float x, float y, float z, float3a &amp;normal) {&#xD;&#xA;        // Find an axis that is not parallel to normal&#xD;&#xA;        float3a majorAxis;&#xD;&#xA;        if (abs(normal.x) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(1, 0, 0);&#xD;&#xA;        } else if (abs(normal.y) &lt; 0.57735026919f /* 1 / sqrt(3) */) {&#xD;&#xA;            majorAxis = float3a(0, 1, 0);&#xD;&#xA;        } else {&#xD;&#xA;            majorAxis = float3a(0, 0, 1);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // Use majorAxis to create a coordinate system relative to world space&#xD;&#xA;        float3a u = normalize(cross(normal, majorAxis));&#xD;&#xA;        float3a v = cross(normal, u);&#xD;&#xA;        float3a w = normal;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        // Transform from local coordinates to world coordinates&#xD;&#xA;        return u * x +&#xD;&#xA;               v * y +&#xD;&#xA;               w * z;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float LambertBRDF::Pdf(float3 inputDirection, float3 normal) {&#xD;&#xA;        return dot(inputDirection, normal) * M_1_PI;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After we sample the inputDirection ('wi' in the code), we use that to calculate the value of the BRDF. And then we divide by the pdf as per the Monte Carlo formula:&#xD;&#xA;&#xD;&#xA;    // Accumulate the brdf attenuation&#xD;&#xA;    throughput = throughput * material-&gt;Eval(wi, wo, normal) / pdf;&#xD;&#xA;&#xD;&#xA;Where *Eval()* is just the BRDF function itself (Lambert, Blinn-Phong, Cook-Torrance, etc.):&#xD;&#xA;&#xD;&#xA;    float3 LambertBRDF::Eval(float3 inputDirection, float3 outputDirection, float3 normal) const override {&#xD;&#xA;        return m_albedo * M_1_PI * dot(inputDirection, normal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Probability_density_function&#xD;&#xA;  [2]: https://i.stack.imgur.com/XGyXh.png&#xD;&#xA;  [3]: https://www.cs.dartmouth.edu/~wjarosz/publications/dissertation/appendixA.pdf&#xD;&#xA;  [4]: https://i.stack.imgur.com/6crnH.png&#xD;&#xA;  [5]: https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/" ContentLicense="CC BY-SA 4.0" />
  <row Id="39204" PostHistoryTypeId="50" PostId="2516" RevisionGUID="988ae0a7-6038-457d-81c6-be1476d7b9a5" CreationDate="2022-12-06T17:03:20.567" UserId="-1" />
  <row Id="39205" PostHistoryTypeId="2" PostId="13152" RevisionGUID="243b35ad-9d03-475d-8427-a4d5756070e3" CreationDate="2022-12-06T18:35:44.833" UserId="19299" Text="I have the following function to define the distance to the interesection between a ray and the surface of a sphere:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;float intersect_sphere_distance(Ray ray, Sphere sphere)&#xD;&#xA;{&#xD;&#xA;    // Calculate distance along the ray where the sphere is intersected&#xD;&#xA;    float3 sphere_to_ray_start_vector = ray.origin - sphere.position;&#xD;&#xA;    &#xD;&#xA;    float hit_distance_1 = -dot(ray.direction, sphere_to_ray_start_vector);&#xD;&#xA;    float hit_distance_2_sqr = hit_distance_1 * hit_distance_1 - dot(sphere_to_ray_start_vector, sphere_to_ray_start_vector) + sphere.radius * sphere.radius;&#xD;&#xA;    &#xD;&#xA;    if (hit_distance_2_sqr &lt; 0)&#xD;&#xA;        return 1.#INF; // Infinity&#xD;&#xA;    &#xD;&#xA;    float hit_distance_2 = sqrt(hit_distance_2_sqr);&#xD;&#xA;&#xD;&#xA;    // Use entry point is not valid, use exit point&#xD;&#xA;    return hit_distance_1 - hit_distance_2 &gt; 0 ? hit_distance_1 - hit_distance_2 : hit_distance_1 + hit_distance_2;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And this function to determine the position in 3D space that a hit occured (this could be one of many sphere intersection tests to determine which sphere actually hit, hence the &quot;best_hit&quot; detail):&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;void intersect_sphere(Ray ray, inout RayHit best_hit, Sphere sphere)&#xD;&#xA;{&#xD;&#xA;    float hit_distance = intersect_sphere_distance(ray, sphere);&#xD;&#xA;    &#xD;&#xA;    if (hit_distance &gt; 0 &amp;&amp; hit_distance &lt; best_hit.distance)&#xD;&#xA;    {&#xD;&#xA;        best_hit.distance = hit_distance;&#xD;&#xA;        best_hit.position = ray.origin + hit_distance * ray.direction;&#xD;&#xA;        &#xD;&#xA;        best_hit.normal = normalize(best_hit.position - sphere.position);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;What I'm trying to do is write a function that smoothly blends between multiple spheres to make one consistant shape. The shape I wish to achieve is two spheres joined smoothly by a tube that tapers a little towards the centre.&#xD;&#xA;&#xD;&#xA;I've seen this achieved when doing ray marching instead of using one infinite ray, but ultimately they tutorial found the distance to an object (or smoothly combined combinations of objects) and the rest should be roughly the same.&#xD;&#xA;&#xD;&#xA;The video I first saw this on:&#xD;&#xA;https://www.youtube.com/watch?v=Cp5WWtMoeKg&amp;list=PLFt_AvWsXl0ehjAfLFsp1PGaatzAwo0uK&amp;index=14&#xD;&#xA;&#xD;&#xA;A snippet of his code where he does smooth blending, but I can't get it to work (I always get a shape that looks like only the intersecting volume between the spheres):&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;// polynomial smooth min (k = 0.1);&#xD;&#xA;// from https://www.iquilezles.org/www/articles/smin/smin.htm&#xD;&#xA;float4 Blend( float a, float b, float3 colA, float3 colB, float k )&#xD;&#xA;{&#xD;&#xA;    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );&#xD;&#xA;    float blendDst = lerp( b, a, h ) - k*h*(1.0-h);&#xD;&#xA;    float3 blendCol = lerp(colB,colA,h);&#xD;&#xA;    return float4(blendCol, blendDst);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is what I've tried to do so far, with the commented out parts of the &quot;smooth_...&quot; functions being taken from the tutorial video, and the uncommented parts being from the linked github repo. The results are not good whichever I use. I either get both spheres intersecting normally with weird surface normals on one of them, or I get just the intersecting section with surface normals that look correct for the resulting shape at least, haha.&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;float smooth_lerp_amount(float a, float b, float k)&#xD;&#xA;{&#xD;&#xA;    // return max(k - abs(a-b), 0) / k;&#xD;&#xA;    return saturate(0.5 + 0.5 * (b-a) / k);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float smooth_min(float a, float b, float k)&#xD;&#xA;{&#xD;&#xA;    // float h = max(k - abs(a-b), 0) / k;&#xD;&#xA;    // return min(a, b) - pow(h, 3) * 1 / 6.0;&#xD;&#xA;&#xD;&#xA;    float h = smooth_lerp_amount(a, b, k);&#xD;&#xA;    return lerp(b, a, h) - k*h*(1.0-h);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void intersect_double_sphere(Ray ray, inout RayHit best_hit, Sphere sphere_a, Sphere sphere_b)&#xD;&#xA;{    &#xD;&#xA;    float hit_distance_a = intersect_sphere_distance(ray, sphere_a);&#xD;&#xA;    float hit_distance_b = intersect_sphere_distance(ray, sphere_b);&#xD;&#xA;&#xD;&#xA;    float hit_distance = smooth_min(hit_distance_a, hit_distance_b, 1.0f);&#xD;&#xA;    &#xD;&#xA;    if (hit_distance &gt; 0 &amp;&amp; hit_distance &lt; best_hit.distance)&#xD;&#xA;    {&#xD;&#xA;        best_hit.distance = hit_distance;&#xD;&#xA;        best_hit.position = ray.origin + hit_distance * ray.direction;&#xD;&#xA;        &#xD;&#xA;        float lerp_amount = smooth_lerp_amount(hit_distance_a, hit_distance_b, 1.0f);&#xD;&#xA;&#xD;&#xA;        float3 normal_a = normalize(best_hit.position - sphere_a.position);&#xD;&#xA;        float3 normal_b = normalize(best_hit.position - sphere_b.position);&#xD;&#xA;        best_hit.normal = lerp(normal_a, normal_b, 1.0 - lerp_amount);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="39207" PostHistoryTypeId="1" PostId="13152" RevisionGUID="243b35ad-9d03-475d-8427-a4d5756070e3" CreationDate="2022-12-06T18:35:44.833" UserId="19299" Text="Calculating ray intersection with two spheres (with smooth_blending between the two spheres to make them appear as one continuous geometry)" ContentLicense="CC BY-SA 4.0" />
  <row Id="39208" PostHistoryTypeId="3" PostId="13152" RevisionGUID="243b35ad-9d03-475d-8427-a4d5756070e3" CreationDate="2022-12-06T18:35:44.833" UserId="19299" Text="|raytracing|computational-geometry|geometry|interpolation|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39210" PostHistoryTypeId="2" PostId="13153" RevisionGUID="92334680-5752-4cd1-ac9e-ef06f2099c7b" CreationDate="2022-12-07T10:56:23.470" UserId="19301" Text="So, at this point, I'm not sure if this is a programming or a physics problem! I'm attempting to concatinate 2 video inputs together to cover a wider field of view. As far as I can tell, this is usually done by &quot;stitching&quot; using matching keypoints in the two images. This can be computationally expensive, and as I'm trying to show the output in real time, my approach has been a simple mechanical allignment and a pixel overlap, blending/merging the overlap together. &#xD;&#xA;&#xD;&#xA;Here's the problem. Usually stitching is done with 2 cameras placed next to each other. My cameras are places 3 meters apart. Two different point of views resulting in two different perspectives. &#xD;&#xA;&#xD;&#xA;Now, the stitching doesn't have to be absolutely perfect. My goal is to concatinate the inputs while NOT losing objects. Obviously, depending on the field of view of the cameras, there will be a &quot;dead space&quot; close to the cameras. &#xD;&#xA;&#xD;&#xA;Here's my starting point:&#xD;&#xA;&#xD;&#xA;[![Starting point][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;One idea was to do a cut with an angle and then stitch the images together. That way, I keep information close by while avoiding double objects further out. But this introduces an unwanted distortion and I still get double objects further out: &#xD;&#xA;&#xD;&#xA;[![angle cut &amp; stitched][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SDE10.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/GqBvg.jpg&#xD;&#xA;&#xD;&#xA;Any ideas how to move forward? Any help appriciated! " ContentLicense="CC BY-SA 4.0" />
  <row Id="39212" PostHistoryTypeId="1" PostId="13153" RevisionGUID="92334680-5752-4cd1-ac9e-ef06f2099c7b" CreationDate="2022-12-07T10:56:23.470" UserId="19301" Text="Video Stitching 3m between cameras" ContentLicense="CC BY-SA 4.0" />
  <row Id="39213" PostHistoryTypeId="3" PostId="13153" RevisionGUID="92334680-5752-4cd1-ac9e-ef06f2099c7b" CreationDate="2022-12-07T10:56:23.470" UserId="19301" Text="|opencv|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39214" PostHistoryTypeId="50" PostId="10748" RevisionGUID="e7d51056-b007-427f-94af-cbb89f2819a5" CreationDate="2022-12-07T17:10:46.270" UserId="-1" />
  <row Id="39217" PostHistoryTypeId="34" PostId="13102" RevisionGUID="6316f6bd-b6ab-4d5d-acb2-dad9279861ef" CreationDate="2022-12-08T21:03:35.337" UserId="-1" Comment="80" />
  <row Id="39219" PostHistoryTypeId="2" PostId="13154" RevisionGUID="93ece6e0-0aae-47e5-9e34-fb21a6963e0f" CreationDate="2022-12-09T01:06:32.107" UserId="19310" Text="The short answer is to use a UI extension like DearIMGUI, wxWidgets, or QT.&#xD;&#xA;  I have pondered the question too, so much so that Im partaking in the following.  So instead, using conversion types from GLUT(INSTEAD OF USING A WRAPPER).  I am plugging my extra time outside of development in to making a GLFW dependent extension, in the form of a .dll, and .h file, which allows you to create UI's, text input/output(though glfw already supports this part(if you appropriately read documents)), image texture loader, and a seperated loader for 3d models/anims.  Trying to assist in making development easier for glfw users. 1 plugin to substitute all the additional plugins." ContentLicense="CC BY-SA 4.0" />
  <row Id="39225" PostHistoryTypeId="50" PostId="2146" RevisionGUID="ec00d48d-16b2-4028-9335-798c3de2c509" CreationDate="2022-12-09T11:05:00.600" UserId="-1" />
  <row Id="39230" PostHistoryTypeId="50" PostId="11048" RevisionGUID="ecc7015e-8349-4233-ae8b-a7c07c9dd62b" CreationDate="2022-12-09T17:05:25.617" UserId="-1" />
  <row Id="39231" PostHistoryTypeId="50" PostId="8886" RevisionGUID="b82a21e2-b172-462c-8be0-b8c253fc1050" CreationDate="2022-12-09T19:08:31.063" UserId="-1" />
  <row Id="39232" PostHistoryTypeId="2" PostId="13157" RevisionGUID="df0df533-e938-4436-923b-a9ed99dad366" CreationDate="2022-12-09T19:58:32.133" UserId="19313" Text="Let's say I have a 3D model that represents a small real-world space; it could be bounded by a 10&quot; by 10&quot; by 10&quot; box. I know the real-world compass bearing for an observer in the center of the box looking down the X axis. How can I estimate the bearings of other vectors in this space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39234" PostHistoryTypeId="1" PostId="13157" RevisionGUID="df0df533-e938-4436-923b-a9ed99dad366" CreationDate="2022-12-09T19:58:32.133" UserId="19313" Text="Approximate compass bearing of a normal" ContentLicense="CC BY-SA 4.0" />
  <row Id="39235" PostHistoryTypeId="3" PostId="13157" RevisionGUID="df0df533-e938-4436-923b-a9ed99dad366" CreationDate="2022-12-09T19:58:32.133" UserId="19313" Text="|3d|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39236" PostHistoryTypeId="50" PostId="11049" RevisionGUID="755a0393-0124-4aa4-8451-d66cf6656f99" CreationDate="2022-12-09T20:07:20.940" UserId="-1" />
  <row Id="39237" PostHistoryTypeId="2" PostId="13158" RevisionGUID="0452d978-d742-4ca5-a1e6-311fdb710583" CreationDate="2022-12-09T22:06:34.597" UserId="17399" Text="I'm using [paper.js][1] and need to add a point to a curved path without affecting the path's shape. Inkscape's &quot;Edit paths by nodes&quot; tool has this feature by default -- double-clicking on a path adds a node, adjusting the handles of the new node and adjacent nodes to preserve the path shape. What appears to be [the code][2] says &quot;Handle lengths are equal to 1/3 of the distance from the adjacent node.&quot; I haven't managed to find the code which updates the handles of the adjacent nodes, but observing the behavior in Inkscape they appear to shrink to an amount proportional to the (along-path) distance to the new node.&#xD;&#xA;&#xD;&#xA;Coding this up, it works well on [a circle][3] but isn't quite right for [a less regular shape][4]. &#xD;&#xA;&#xD;&#xA;Any suggestions for making it work as reliably as Inkscape?&#xD;&#xA;&#xD;&#xA;  [1]: http://paperjs.org/reference/path/&#xD;&#xA;  [2]: https://gitlab.com/inkscape/inkscape/-/blob/master/src/ui/tool/node.cpp#L940&#xD;&#xA;  [3]: http://sketch.paperjs.org/#V/0.12.17/S/pVNNb9swDP0rhC92CkdJW+ySIAOGYocBwxaguzU9qDIdC1GoQKKTFkH++yR/pUk3YMB8I/ne46NFHhOSW0xmyeMGWVVJnihbxHiv8SDYSfJGMmZNqJAY3Wi+ohWVNSnWlkAWxePWWq6WVhNnxioZ8yM4rgjCpyx5Bpa0DmxYgBJr5F9t+IWz2+k0Cp6Rmgp8DbheSKja7VF4XG8D40409QtGV2q0NXl0nDWgfNDoO7xnFQHfMQXhK4uhoS1LjwzjobxzuNe29teQCxfFMqDeaf6v3I/g6d8tfpRqxfp6Jakw+I2CYv8UNzBuPU/gfv4n9M+aL+CtpTP6kjNMdSbfLKDvUFx1aMYZTEVgJ94DHXLtqMeH5CmO1P4bFWwRHmApuRIP2imDWbdtTha69jO4m07zriM7u8EHa6ybQfpipNqkoXSKOzGZDBtzm8PT+D6wYBxW8nkkfLPU2RH4bYeBuUa7RXZapTmUUnGUE5/g1J6DEspYwmwkSm1M0y2YTN/QGHtI5xHQjeJFad1XqarMw+Iz+JA3qBjjPrKrsdNrBu1ftT+b7118vpvrC/jbNV53CdRw6y8O5WYXkT6ZPT2ffgM=&#xD;&#xA;  [4]: http://sketch.paperjs.org/#V/0.12.17/S/pVNLa+MwEP4rgy92iqNNW/aSksJSeiiUbqB7a3pQ5XEsooyCNE5aQv77yvIjTXYXFuqbNN9rrJl9QnKNyTR5XiGrKskTZYvmvNW4E+wkeSMZs3hUSIxudLOgBZU1KdaWQBbF89paruZWE2fGKtncj2C/IAifsuQZWNIysGEGSiyRf7XHH5xdTiaN4BGpqcD3gOuFhKrdFoXH5TowrkSsnzC6UtTW5NFxFkH5oNE7fGYVAd8xBeE7i8HQlqVHhvFQ3jjcalv7c8hJimIeUJ80vyr3FDL9f8Q/pVqxvl5JKgw+UFDsn+ICxm3mb3B98zf0z5pP4G2kI/qUM3R1JF/MoHcozhxiO0OoBtiJ90CHXDvq8eHy0LTU/hsVYhHuYC65EnfaKYNZN21OFrr2U7iaTPLOkZ1d4Z011k0hfTNSrdJQOjQzMczLZQ4v4+vAgXEYyNeR8HGksz3wxwYDb4l2jey0SnMopeJGTHyHQ7sMSihjCbORKLUx0StETD/QGLtLo1HXiBeldfdSVZmH2S34cG9QMTbTyK7GTi+22b9pvzSP3fm4Nefz/69dPHcJ1LDpbw7latMgfTJ9eT38Bg==" ContentLicense="CC BY-SA 4.0" />
  <row Id="39239" PostHistoryTypeId="1" PostId="13158" RevisionGUID="0452d978-d742-4ca5-a1e6-311fdb710583" CreationDate="2022-12-09T22:06:34.597" UserId="17399" Text="Algorithm to add a path point, preserving path shape?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39240" PostHistoryTypeId="3" PostId="13158" RevisionGUID="0452d978-d742-4ca5-a1e6-311fdb710583" CreationDate="2022-12-09T22:06:34.597" UserId="17399" Text="|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39247" PostHistoryTypeId="2" PostId="13160" RevisionGUID="49035ea9-6c4b-4160-9f38-90be8fbe774f" CreationDate="2022-12-10T11:17:00.483" UserId="19318" Text="Recently I'm reading the book computer grahpics : principle and practice and I encountered first weird things. Ordinary bulb consumes 100W per second, and 2% is used to emit the light. Then how do I know the photon of the light bulb? The textbook said that 2W is divided by 10^-19.. What I tried to understand is followed : 2W is the energy consumed, and typical photon is 10^-19. Why 2 is divided by 10^-19?&#xD;&#xA;&#xD;&#xA;The example is followed; area is 100m^2 -&gt; 10^6, and it consumes 100W.=10^2. Suddenly, 10^12 comes out but I have no idea how did the author calculated...&#xD;&#xA;&#xD;&#xA;It looks like very simple, but I'm currently struggling.. It would be appreciated if you give any single hints. Thank you[![enter image description here][1]][1][![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PPENT.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/WDwSs.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39249" PostHistoryTypeId="1" PostId="13160" RevisionGUID="49035ea9-6c4b-4160-9f38-90be8fbe774f" CreationDate="2022-12-10T11:17:00.483" UserId="19318" Text="Calculation of the photon of the object" ContentLicense="CC BY-SA 4.0" />
  <row Id="39250" PostHistoryTypeId="3" PostId="13160" RevisionGUID="49035ea9-6c4b-4160-9f38-90be8fbe774f" CreationDate="2022-12-10T11:17:00.483" UserId="19318" Text="|photon-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39251" PostHistoryTypeId="2" PostId="13161" RevisionGUID="4cbdc9df-3bed-4364-8f85-42ed9ae9b2a6" CreationDate="2022-12-10T15:37:46.520" UserId="445" Text="&gt; Why 2 is divided by 10^-19?&#xD;&#xA;&#xD;&#xA;A [photon](https://en.wikipedia.org/wiki/Photon) of a specific wavelength has a specific energy; no more, no less — light is [quantized](https://en.wikipedia.org/wiki/Quantum), and photons are the quanta of light, the minimum-size piece it comes in. Whenever there is enough light to see by, that light is made up of *very many* photons, such that the energy of all the photons summed together makes up the amount of energy emitted. Therefore, we can use the energy of one photon as the conversion factor to convert between energy and photon count, or between power and photon rate.&#xD;&#xA;&#xD;&#xA;When we divide $2\,\mathrm{W}$, the total power, by $3 \cdot 10^{-19}\,\mathrm{J}$, the energy of one photon of this wavelength, we get the rate at which those photons being emitted, $0.66 \cdot 10^{19}\,\mathrm{/s} = 6.6 \cdot 10^{18}\,\mathrm{/s}$, such that all their energies together make up $2\,\mathrm{W}$ of power. " ContentLicense="CC BY-SA 4.0" />
  <row Id="39253" PostHistoryTypeId="5" PostId="13161" RevisionGUID="e286966f-42c2-4d20-adb8-8d92422947e8" CreationDate="2022-12-10T15:46:16.833" UserId="445" Comment="added 934 characters in body" Text="&gt; Why 2 is divided by 10^-19?&#xD;&#xA;&#xD;&#xA;A [photon](https://en.wikipedia.org/wiki/Photon) of a specific wavelength has a specific energy; no more, no less — light is [quantized](https://en.wikipedia.org/wiki/Quantum), and photons are the quanta of light, the minimum-size piece it comes in. Whenever there is enough light to see by, that light is made up of *very many* photons, such that the energy of all the photons summed together makes up the amount of energy emitted. Therefore, we can use the energy of one photon as the conversion factor to convert between energy and photon count, or between power and photon rate.&#xD;&#xA;&#xD;&#xA;When we divide $2\,\mathrm{W}$, the total power, by $3 \cdot 10^{-19}\,\mathrm{J}$, the energy of one photon of this wavelength, we get the rate at which those photons being emitted, $0.66 \cdot 10^{19}\,\mathrm{/s} = 6.6 \cdot 10^{18}\,\mathrm{/s}$, such that all their energies together make up $2\,\mathrm{W}$ of power. &#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;As to the $10^{12}$ figure — you're not missing something obvious; they didn't explain that well. The key thing to think about is that given a light source in a room, all the light hits objects in the room. They're _comparing areas_ as a way to compute approximately how much light hits one particular piece of surface in the room. They're saying that there are $10^{6}\,\mathrm{cm}^2$ of wall/object surface area in the room, so we can divide the number of photons being emitted by the light source in all directions, around $10^{18}$, by the $10^6\,\mathrm{cm}^2$ to obtain $10^{12}$, the approximate number of photons (per second) falling on an individual $\mathrm{cm}^2$ of the room.&#xD;&#xA;&#xD;&#xA;This calculation is very approximate and not especially relevant to actually making computer graphics; it's meant to give you an idea of the rates/quantities involved in the real physics, to contrast with how the simulations that we build for graphics work." ContentLicense="CC BY-SA 4.0" />
  <row Id="39254" PostHistoryTypeId="2" PostId="13162" RevisionGUID="b1d6d67d-69a1-4d96-92a8-5aaf0898ef3b" CreationDate="2022-12-10T15:47:41.057" UserId="17399" Text="I realized this would be better phrased as &quot;how to split a bezier curve&quot;, answered well [here][1] (De Casteljau's Algorithm).&#xD;&#xA;&#xD;&#xA;And I had somehow missed that it's implemented in paper.js as [Path.divideAt][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://stackoverflow.com/a/36434774/362702&#xD;&#xA;  [2]: http://paperjs.org/reference/path/#divideat-location" ContentLicense="CC BY-SA 4.0" />
  <row Id="39257" PostHistoryTypeId="2" PostId="13163" RevisionGUID="aa547053-d545-4f64-bf83-ea8906589e56" CreationDate="2022-12-11T02:10:52.827" UserId="19321" Text="I'm a beginner in WebGL and graphics programming in general. I'm trying to render procedurally generated terrain. My first stab at this seemed to work and I get the following result.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I want to add perspective projection to this, but I end up with something that looks like this (basically just a close up of my terrain it looks like):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The code below was used to implement the perspective matrix in javascript with glmatrix:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;const fieldOfView = (45 * Math.PI) / 180; // in radians&#xD;&#xA;const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;&#xD;&#xA;const zNear = 0.001;&#xD;&#xA;const zFar = 1.0;&#xD;&#xA;const projectionMatrix = mat4.create();&#xD;&#xA;mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);&#xD;&#xA;&#xD;&#xA;const projectionMatrixLoc = gl.getUniformLocation(program, &quot;uProjectionMatrix&quot;);&#xD;&#xA;gl.uniformMatrix4fv(projectionMatrixLoc, false, projectionMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;and this is the corresponding code in my vertex shader:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;attribute vec4 vPosition;&#xD;&#xA;uniform mat4 uModelViewMatrix;&#xD;&#xA;uniform mat4 uProjectionMatrix;&#xD;&#xA;varying float v_color;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;  gl_Position = uProjectionMatrix * uModelViewMatrix * vPosition;&#xD;&#xA;  v_color = (vPosition.z + 1.0) / 2.0;&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I have zFar at 1.0 because my maximum Z value is 1.0. I know that I can place the points at arbitrary coordinates as long as those coordinates are within the frustum, but I wanted to render this with points that would render even if I had trouble with the perspective matrix.&#xD;&#xA;&#xD;&#xA;The entire project can be found in a [Codesandbox repository][3] if you're interested in seeing the full project (shaders are in the html file).&#xD;&#xA;&#xD;&#xA;Any help is greatly appreciated!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c3x4z.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YuXGj.png&#xD;&#xA;  [3]: https://codesandbox.io/s/diamond-square-kvpbh6" ContentLicense="CC BY-SA 4.0" />
  <row Id="39259" PostHistoryTypeId="1" PostId="13163" RevisionGUID="aa547053-d545-4f64-bf83-ea8906589e56" CreationDate="2022-12-11T02:10:52.827" UserId="19321" Text="Can anyone tell me why my projection perspective matrix isn't working?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39260" PostHistoryTypeId="3" PostId="13163" RevisionGUID="aa547053-d545-4f64-bf83-ea8906589e56" CreationDate="2022-12-11T02:10:52.827" UserId="19321" Text="|webgl|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39261" PostHistoryTypeId="5" PostId="13161" RevisionGUID="b474ab3b-3721-4a26-aa58-518fe56d8d09" CreationDate="2022-12-11T02:53:11.010" UserId="445" Comment="added 47 characters in body" Text="&gt; Why 2 is divided by 10^-19?&#xD;&#xA;&#xD;&#xA;A [photon](https://en.wikipedia.org/wiki/Photon) of a specific wavelength has a specific energy; no more, no less — light is [quantized](https://en.wikipedia.org/wiki/Quantum), and photons are the quanta of light, the minimum-size piece it comes in. Whenever there is enough light to see by, that light is made up of *very many* photons, such that the energy of all the photons summed together makes up the amount of energy emitted. Therefore, we can use the energy of one photon as the conversion factor to convert between energy and photon count, or between power and photon rate.&#xD;&#xA;&#xD;&#xA;When we divide $2\,\mathrm{W}$, the total power, by $3 \cdot 10^{-19}\,\mathrm{J}$, the energy of one photon of this wavelength, we get the rate at which those photons being emitted, $0.66 \cdot 10^{19}\,\mathrm{/s} = 6.6 \cdot 10^{18}\,\mathrm{/s}$, such that all their energies together make up $2\,\mathrm{W}$ of power. &#xD;&#xA;&#xD;&#xA;&gt; Suddenly, 10^12 comes out but I have no idea how did the author calculated...&#xD;&#xA;&#xD;&#xA;You're not missing something obvious; they didn't explain that well. The key thing to think about is that given a light source in a room, all the light hits objects in the room. They're _comparing areas_ as a way to compute approximately how much light hits one particular piece of surface in the room. They're saying that there are $10^{6}\,\mathrm{cm}^2$ of wall/object surface area in the room, so we can divide the number of photons being emitted by the light source in all directions, around $10^{18}$, by the $10^6\,\mathrm{cm}^2$ to obtain $10^{12}$, the approximate number of photons (per second) falling on an individual $\mathrm{cm}^2$ of the room.&#xD;&#xA;&#xD;&#xA;This calculation is very approximate and not especially relevant to actually making computer graphics; it's meant to give you an idea of the rates/quantities involved in the real physics, to contrast with how the simulations that we build for graphics work." ContentLicense="CC BY-SA 4.0" />
  <row Id="39262" PostHistoryTypeId="2" PostId="13164" RevisionGUID="b3fe575b-b43a-4583-b37c-7c767817029e" CreationDate="2022-12-12T22:32:51.710" UserId="7952" Text="So there are an infinite number of vectors that satisfy this. Here are 3 ways to find some solutions:&#xD;&#xA;&#xD;&#xA;1) Use the swap and negate method similar to that from 2D.&#xD;&#xA;   Given a vector $(x, y, z)$ orthogonal vectors are $(-y, x, 0)$, or $(-z, 0, x)$ or $(0, -z, y)$ ie set 1 component to zero then swap the other two and negate one of them(usually the first).&#xD;&#xA;&#xD;&#xA;2) Solve for the dot product. The dot product of two orthogonal vectors would be equal to zero. So just pick two values and solve for third. ie given a vector $(1,2,3)$ the dot product of an orthogonal vector would be $1x+2y+3z=0$. Use some method to pick $x,y$, or just pick them randomly, and solve for $z$. This is nice if you have just a little extra info but not all of it.&#xD;&#xA;&#xD;&#xA;3) Similar to number 2. Solve the cross product for a vector that is orthogonal.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39264" PostHistoryTypeId="5" PostId="13164" RevisionGUID="cd0cc580-2655-4996-9474-38092996222b" CreationDate="2022-12-12T23:23:50.530" UserId="7952" Comment="added 155 characters in body" Text="So there are an infinite number of vectors that satisfy this. Here are 3 ways to find some solutions:&#xD;&#xA;&#xD;&#xA;1) Use the swap and negate method similar to that from 2D.&#xD;&#xA;   Given a vector $(x, y, z)$ orthogonal vectors are $(-y, x, 0)$, or $(-z, 0, x)$ or $(0, -z, y)$ ie set 1 component to zero then swap the other two and negate one of them(usually the first).&#xD;&#xA;&#xD;&#xA;2) Solve for the dot product. The dot product of two orthogonal vectors would be equal to zero. So just pick two values and solve for third. ie given a vector $(1,2,3)$ the dot product of an orthogonal vector would be $1x+2y+3z=0$. Use some method to pick $x,y$, or just pick them randomly, and solve for $z$. This is nice if you have just a little extra info but not all of it.&#xD;&#xA;&#xD;&#xA;3) Similar to number 2. Solve the cross product for a vector that is orthogonal.&#xD;&#xA;&#xD;&#xA;Oh...I guess it goes without saying since I forgot to say it...&#xD;&#xA;The last vector is the cross product of the compass heading, and the &quot;made up&quot; vector.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39265" PostHistoryTypeId="50" PostId="5697" RevisionGUID="54810ab3-f16f-44ba-a3b2-e5fda8be1735" CreationDate="2022-12-13T09:03:50.430" UserId="-1" />
  <row Id="39266" PostHistoryTypeId="5" PostId="7520" RevisionGUID="ee72cc2d-9a7b-4f30-8fb9-abb3b39d7598" CreationDate="2022-12-14T08:59:44.623" UserId="19180" Comment="updated image url" Text="The `min` and `max` values provide an outer bounding box for all `POSITION` data within a given accessor.  Accessors typically contain multiple vertices, for example all of the vertices of a particular primitive, and then `min: [x, y, z]` and `max: [x, y, z]` will offer the bounding box for that primitive.&#xD;&#xA;&#xD;&#xA;For your second question, let's look at the mesh structure from [BoxTextured.gltf](https://github.com/KhronosGroup/glTF-Sample-Models/blob/0bc74b12b2de22a1267ccab819efcf8c6a4f3dc8/2.0/BoxTextured/glTF/BoxTextured.gltf#L44-L56):&#xD;&#xA;&#xD;&#xA;    &quot;meshes&quot;: [&#xD;&#xA;        {&#xD;&#xA;            &quot;primitives&quot;: [&#xD;&#xA;                {&#xD;&#xA;                    &quot;attributes&quot;: {&#xD;&#xA;                        &quot;NORMAL&quot;: 1,&#xD;&#xA;                        &quot;POSITION&quot;: 2,&#xD;&#xA;                        &quot;TEXCOORD_0&quot;: 3&#xD;&#xA;                    },&#xD;&#xA;                    &quot;indices&quot;: 0,&#xD;&#xA;                    &quot;mode&quot;: 4,&#xD;&#xA;                    &quot;material&quot;: 0&#xD;&#xA;                }&#xD;&#xA;            ],&#xD;&#xA;            &quot;name&quot;: &quot;Mesh&quot;&#xD;&#xA;        }&#xD;&#xA;    ],&#xD;&#xA;&#xD;&#xA;In the above example, `mode: 4` is an enum, where `4` means `TRIANGLES`.  The `indices` are stored in accessor `0`, and the `POSITION` data is stored in accessor `2`.  So, accessor `2` will contain a list of vertex positions, but each vertex is allowed to be referenced by multiple triangles.  The indices in accessor `0` declare the triangles by indexing into the list of vertices.&#xD;&#xA;&#xD;&#xA;Here's a sample of the start of accessor `0` from this model:&#xD;&#xA;&#xD;&#xA;    0 &#xD;&#xA;    1 &#xD;&#xA;    2 &#xD;&#xA;&#xD;&#xA;    3 &#xD;&#xA;    2 &#xD;&#xA;    1 &#xD;&#xA;&#xD;&#xA;    4 &#xD;&#xA;    5 &#xD;&#xA;    6 &#xD;&#xA;&#xD;&#xA;    7 &#xD;&#xA;    6 &#xD;&#xA;    5 &#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;And this is a sample of the contents from the start of accessor `2` in this model:&#xD;&#xA;&#xD;&#xA;    -0.50000    -0.50000     0.50000 &#xD;&#xA;     0.50000    -0.50000     0.50000 &#xD;&#xA;    -0.50000     0.50000     0.50000 &#xD;&#xA;     0.50000     0.50000     0.50000 &#xD;&#xA;     0.50000     0.50000     0.50000 &#xD;&#xA;     0.50000    -0.50000     0.50000 &#xD;&#xA;     0.50000     0.50000    -0.50000 &#xD;&#xA;     0.50000    -0.50000    -0.50000 &#xD;&#xA;     ...&#xD;&#xA;&#xD;&#xA;In this manner, the sample model builds a cube by winding triangles around vertices at the corners.&#xD;&#xA;&#xD;&#xA;For a more graphical explanation of this, check out the [glTF Overview Card](https://raw.githubusercontent.com/KhronosGroup/glTF/main/specification/2.0/figures/gltfOverview-2.0.0b.png) - same image is found [here][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/glTF#overview" ContentLicense="CC BY-SA 4.0" />
  <row Id="39267" PostHistoryTypeId="24" PostId="7520" RevisionGUID="ee72cc2d-9a7b-4f30-8fb9-abb3b39d7598" CreationDate="2022-12-14T08:59:44.623" Comment="Proposed by 19180 approved by 13095 edit id of 605" ContentLicense="CC BY-SA 4.0" />
  <row Id="39268" PostHistoryTypeId="2" PostId="13165" RevisionGUID="c8f68011-a0e7-4e46-bb3a-8742ae6cbbf4" CreationDate="2022-12-14T09:36:59.290" UserId="7462" Text="I have a cube with 8 vertices representing the $[-1,1]^3$ cube vulkan uses for device coordinates.&#xD;&#xA;&#xD;&#xA;The perspective projection matrix takes a frustum and maps it onto this cube. It thus makes sense that the inverse of this transformation applied to the cube should yield the frustum.&#xD;&#xA;&#xD;&#xA;To that effect I have this little snippet:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;&#xD;&#xA;    Eigen::Matrix4d perspective_mat = Perspective(80.f, 1.f, 0.1f, node.normal.norm()).cast&lt;double&gt;(); // delete&#xD;&#xA;    HMesh&lt;VertexData&gt; cube(&quot;cube.obj&quot;);                                                                // delete&#xD;&#xA;    for (auto &amp;vert : cube.VertexDataD())&#xD;&#xA;    {&#xD;&#xA;        const auto &amp;pos = vert.position;&#xD;&#xA;        auto tmp = ((perspective_mat).inverse().eval() * Edvec4(pos.x(), pos.y(), pos.z(), 1));&#xD;&#xA;&#xD;&#xA;        vert.position = {tmp.x() / tmp[3], tmp.y() / tmp[3], tmp.z() / tmp[3]};&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Well this little guy creates this thing:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Which does not look like a frustum.&#xD;&#xA;&#xD;&#xA;What am I doing wrong? I know it's not a coding error in the sense I trust all my functions, but I might have a math error.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EYvRD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39270" PostHistoryTypeId="1" PostId="13165" RevisionGUID="c8f68011-a0e7-4e46-bb3a-8742ae6cbbf4" CreationDate="2022-12-14T09:36:59.290" UserId="7462" Text="Inverting perspective projection doesn't yield frustum?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39271" PostHistoryTypeId="3" PostId="13165" RevisionGUID="c8f68011-a0e7-4e46-bb3a-8742ae6cbbf4" CreationDate="2022-12-14T09:36:59.290" UserId="7462" Text="|rendering|geometry|perspective|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39272" PostHistoryTypeId="5" PostId="9223" RevisionGUID="a0b7a8a7-1e64-476b-a5f4-8402603ea2a4" CreationDate="2022-12-15T19:37:32.697" UserId="1908" Comment="Fix broken link" Text="There isn't a bounding box for the whole glTF file, but individual primitives have `POSITION` accessors that indicate `min` and `max` values.  This is specified in the [Meshes section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#meshes), with the following text:&#xD;&#xA;&#xD;&#xA;&gt; `POSITION` accessor must have `min` and `max` properties defined.&#xD;&#xA;&#xD;&#xA;For a concrete example of this, take a look at the Box sample model, which assigns [accessor 2 as `POSITION`](https://github.com/KhronosGroup/glTF-Sample-Models/blob/18912e96c60245f71a3775d365c990009307a11a/2.0/Box/glTF/Box.gltf#L48)&#xD;&#xA;&#xD;&#xA;    &quot;meshes&quot;: [&#xD;&#xA;        {&#xD;&#xA;            &quot;primitives&quot;: [&#xD;&#xA;                {&#xD;&#xA;                    &quot;attributes&quot;: {&#xD;&#xA;                        &quot;NORMAL&quot;: 1,&#xD;&#xA;                        &quot;POSITION&quot;: 2&#xD;&#xA;                    },&#xD;&#xA;                    &quot;indices&quot;: 0,&#xD;&#xA;                    &quot;mode&quot;: 4,&#xD;&#xA;                    &quot;material&quot;: 0&#xD;&#xA;                }&#xD;&#xA;            ],&#xD;&#xA;            &quot;name&quot;: &quot;Mesh&quot;&#xD;&#xA;        }&#xD;&#xA;    ],&#xD;&#xA;&#xD;&#xA;The accessor at index `2` (the third one in the list) looks [like this](https://github.com/KhronosGroup/glTF-Sample-Models/blob/18912e96c60245f71a3775d365c990009307a11a/2.0/Box/glTF/Box.gltf#L89-L105):&#xD;&#xA;&#xD;&#xA;    &quot;accessors&quot;: [&#xD;&#xA;        { ... },&#xD;&#xA;        { ... },&#xD;&#xA;        {&#xD;&#xA;            &quot;bufferView&quot;: 1,&#xD;&#xA;            &quot;byteOffset&quot;: 288,&#xD;&#xA;            &quot;componentType&quot;: 5126,&#xD;&#xA;            &quot;count&quot;: 24,&#xD;&#xA;            &quot;max&quot;: [&#xD;&#xA;                0.5,&#xD;&#xA;                0.5,&#xD;&#xA;                0.5&#xD;&#xA;            ],&#xD;&#xA;            &quot;min&quot;: [&#xD;&#xA;                -0.5,&#xD;&#xA;                -0.5,&#xD;&#xA;                -0.5&#xD;&#xA;            ],&#xD;&#xA;            &quot;type&quot;: &quot;VEC3&quot;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;In this accessor, `min` and `max` are arrays of `x, y, z` raw position data of the primitive.  This particular sample model is a unit cube, with values ranging from `-0.5` to `0.5` along each axis.&#xD;&#xA;&#xD;&#xA;To understand how this affects the whole model though, one must walk the tree of scene nodes, and look at how these mesh primitives are being transformed by the nodes.  Also, if there are any animations or morph targets taking effect, they can influence the final positions of these meshes as well." ContentLicense="CC BY-SA 4.0" />
  <row Id="39273" PostHistoryTypeId="2" PostId="13166" RevisionGUID="6c36427a-92ac-48a3-8f70-d3406da0c45f" CreationDate="2022-12-16T08:05:24.733" UserId="18177" Text="I wrote the following phong reflection model for ray tracing in Rust, but I am not sure about the calculation of a reflection vector for the specular reflection.&#xD;&#xA;&#xD;&#xA;````&#xD;&#xA;// Vector: from eye to sphere&#xD;&#xA;let v = hit_point.normalize();&#xD;&#xA;// Vector: from light to sphere&#xD;&#xA;let l = (hit_point - light.pos).normalize();&#xD;&#xA;// Normal vector of sphere&#xD;&#xA;let n = (hit_point - self.center).normalize();&#xD;&#xA;// Reflected light&#xD;&#xA;let r = (l + 2.0 * dot(-l, n) * n).normalize();&#xD;&#xA;let white = Vec3::new(255.0, 255.0, 255.0);&#xD;&#xA;let shininess = 20.0;&#xD;&#xA;let cosa = f64::max(0.0, dot(-l, n));&#xD;&#xA;let cosb = f64::max(0.0, dot(-r, v));&#xD;&#xA;&#xD;&#xA;let diffuse = kd * cosa * color;&#xD;&#xA;let specular = ks * cosb.powf(shininess) * white;&#xD;&#xA;let ambient = ke * color;&#xD;&#xA;&#xD;&#xA;let color = diffuse + specular + ambient;&#xD;&#xA;````&#xD;&#xA;&#xD;&#xA;I wrote the following program to calculate the reflection vector of the light as shown in the next image, but it did not reflect the specular reflection as shown in the next image.&#xD;&#xA;&#xD;&#xA;`let r = (l + 2.0 * dot(-l, n) * n).normalize();`&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Instead, when I wrote reflected ray as following program, the specular reflection is reflected nicely as follows.&#xD;&#xA;&#xD;&#xA;`let r = (-l + 2.0 * dot(l, n) * n).normalize();`&#xD;&#xA;&#xD;&#xA;Why is my first program wrong ? Why reflected ray `r = l + 2(-l・n)n` is wrong ?&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZyKqn.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/gbsHc.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Ohpsm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39275" PostHistoryTypeId="1" PostId="13166" RevisionGUID="6c36427a-92ac-48a3-8f70-d3406da0c45f" CreationDate="2022-12-16T08:05:24.733" UserId="18177" Text="Calculation of reflection vector in Phong specular lighting" ContentLicense="CC BY-SA 4.0" />
  <row Id="39276" PostHistoryTypeId="3" PostId="13166" RevisionGUID="6c36427a-92ac-48a3-8f70-d3406da0c45f" CreationDate="2022-12-16T08:05:24.733" UserId="18177" Text="|raytracing|rendering|lighting|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39278" PostHistoryTypeId="2" PostId="13167" RevisionGUID="c59c49e6-9ff1-4b39-becd-94513c2b7b57" CreationDate="2022-12-18T01:32:57.990" UserId="18818" Text="For the foreseeable future, there will be three primary platforms.&#xD;&#xA;- OpenGL&#xD;&#xA;- Vulcan&#xD;&#xA;- Metal&#xD;&#xA;&#xD;&#xA;OpenGL has a number of advantages in terms of more examples available, more broadly support (even Apple still supplies some OpenGL support). The one downside is that it is said to use a lot of CPU time to use.&#xD;&#xA;&#xD;&#xA;Vulcan is newer, but not neccessarily easier to use. Vulkan leaves a lot of setup to the programmer. Far more than OpenGl or Apple Metal. This does allow you to optimize specific aspects in exchange for more complexity demanded of you.&#xD;&#xA;&#xD;&#xA;Apple's Metal had an objective to provide similar (but not identical features) as OpenGL, but with less computational power required by the CPU. Metal does a great deal of behind-the-scenes management for you, so deviating from the common is more difficult at times.&#xD;&#xA;&#xD;&#xA;## Which one to learn? ##&#xD;&#xA;&#xD;&#xA;Learn Metal if you intend to support Apple iOS or macOS projects, Vulcan for Linux or projects requiring heavy optimization, or OpenGL if you wish to have the most widespread appeal." ContentLicense="CC BY-SA 4.0" />
  <row Id="39280" PostHistoryTypeId="50" PostId="9591" RevisionGUID="d163eb91-940b-4b65-9ed8-e7e3387e2810" CreationDate="2022-12-18T02:06:10.697" UserId="-1" />
  <row Id="39282" PostHistoryTypeId="2" PostId="13168" RevisionGUID="122a9b68-603c-40e3-b038-64a5c64b803f" CreationDate="2022-12-19T08:18:36.953" UserId="110" Text="[Direct3D 12 Programming Guide section &quot;Descriptor Heap Configurability Summary&quot;][1] lists different &quot;CPU Page Properties Supported&quot; for Shader Visible and Non Shader Visible Descriptor Heaps, `WRITE_COMBINE` and `WRITE_BACK`:&#xD;&#xA;&#xD;&#xA;[![table summarizing information about Shader and non-Shader visible heap support][2]][2]&#xD;&#xA;&#xD;&#xA;What is the difference between `WRITE_COMBINE` and `WRITE_BACK` in the context of D3D12 `D3D12_CPU_PAGE_PROPERTY` APIs?  &#xD;&#xA;&#xD;&#xA;It would be great to know the source at the origin of this terminology, in order to remember more easily what they mean.  &#xD;&#xA;Why are `WRITE_COMBINE` and `WRITE_BACK` named like this?  &#xD;&#xA;What is &quot;combined&quot; during `WRITE_COMBINE`, and what is the &quot;back&quot; movement during `WRITE_BACK`?  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learn.microsoft.com/en-us/windows/win32/direct3d12/descriptor-heap-configurability-summary&#xD;&#xA;  [2]: https://i.stack.imgur.com/o0U7C.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39284" PostHistoryTypeId="1" PostId="13168" RevisionGUID="122a9b68-603c-40e3-b038-64a5c64b803f" CreationDate="2022-12-19T08:18:36.953" UserId="110" Text="What's different between D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE and D3D12_CPU_PAGE_PROPERTY_WRITE_BACK, and why they're named like that?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39285" PostHistoryTypeId="3" PostId="13168" RevisionGUID="122a9b68-603c-40e3-b038-64a5c64b803f" CreationDate="2022-12-19T08:18:36.953" UserId="110" Text="|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39286" PostHistoryTypeId="10" PostId="3575" RevisionGUID="e6f7aa82-7d84-4540-9ac8-1e31791b79d0" CreationDate="2022-12-19T10:27:55.807" UserId="13095" Comment="105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:7952,&quot;DisplayName&quot;:&quot;pmw1234&quot;},{&quot;Id&quot;:13095,&quot;DisplayName&quot;:&quot;wychmaster&quot;}]}" />
  <row Id="39287" PostHistoryTypeId="50" PostId="12853" RevisionGUID="0c8f5077-b29a-4b2e-b584-4369ad52b308" CreationDate="2022-12-19T11:03:05.387" UserId="-1" />
  <row Id="39288" PostHistoryTypeId="50" PostId="8260" RevisionGUID="b7f92cc8-25e5-4d46-a480-ec86921fe60c" CreationDate="2022-12-19T13:07:30.893" UserId="-1" />
  <row Id="39290" PostHistoryTypeId="2" PostId="13169" RevisionGUID="1ed1d3e7-41dd-4635-ab25-be4129d47dd7" CreationDate="2022-12-19T15:23:32.207" UserId="2654" Text="These are names for certain kinds of strategies for how the CPU gets to write to certain more CPU-distant memories.&#xD;&#xA;&#xD;&#xA;Most CPU memory writes are cached; they're bundled together with other writes to contiguous blocks of memory. At some point in the future, the bytes in the cache are written to the actual memory.&#xD;&#xA;&#xD;&#xA;But most GPUs cannot see the CPU caches (some GPUs built into the CPU itself do have access to CPU caches, but for discrete GPUs, that's basically impossible). So the problem is this: how do you make CPU writes actually go out into the real memory, so that the GPU can read them?&#xD;&#xA;&#xD;&#xA;While there are specific tools to force data out of the CPU's caches, there are alternative memory structures that (mostly) bypass the need to do this.&#xD;&#xA;&#xD;&#xA;[Write combining][1] is a fairly automatic memory structure which is more coherent than a cache. There is a small buffer of storage, whose size is the smallest size that the target memory can perform a single write to. When you start writing to write-combined memory, the architecture takes note of the address of that write and figures out where in the target memory that entire buffer will go to. Any subsequent writes that map to the same target address will go into the buffer. But any writes that map to a different address will force the buffer to be written and then cleared, so that the newly written data can be stored in the block aimed at a different target address.&#xD;&#xA;&#xD;&#xA;As an example, let's say that the write combining block size is 256 bytes. So if we start writing to address 0x00001204, this means that any writes to 0x00001200-0x000012FF will all be stored in the write combining block. But if we then write to 0x00001300, then the block aimed at 0x000012XX will be written to the actual RAM.&#xD;&#xA;&#xD;&#xA;Write combining sometimes has further requirements, such as an expectation of contiguous writes in ever-increasing byte counts. That is, if you try to write bytes out of order, or skip bytes, it can cause the buffer to be flushed out to the memory ahead of time.&#xD;&#xA;&#xD;&#xA;[Write-through][2] is an alternative to write-back. Write-back is just... caching. Values are written into the cache, and are only written to main memory when the cache needs that space or if the cache line is explicitly forced to be written.&#xD;&#xA;&#xD;&#xA;Write-through is basically uncached writing. The value gets written to the cache, but it is also written to memory. It writes *through* the cache.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Write_combining&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cache_(computing)#WRITE-BACK" ContentLicense="CC BY-SA 4.0" />
  <row Id="39292" PostHistoryTypeId="5" PostId="10260" RevisionGUID="b4084af8-5639-408e-9ca4-411af4a5036f" CreationDate="2022-12-19T18:55:14.593" UserId="14015" Comment="added 1257 characters in body" Text="Keeping alpha linear makes it unbiased towards source and destination color. It should not be gamma corrected, because it should not have been subjected to sRGB-encoding.&#xD;&#xA;&#xD;&#xA;A specialized application could of course ignore this, for example to get more control over the change in perceived brightness during a blending operation of a bright source color over a dark destination color (assuming alpha is stored in a byte with range 0-255 - which is how sRGB is commonly stored these days for the purpose of data compression - where you can only change the alpha in big steps).&#xD;&#xA;&#xD;&#xA;I might add that 8 bit for linear alpha is actually very low resolution. Blending white over black with alpha 1/255 (the smallest non-zero alpha) yields sRGB values `13, 13, 13` when you do the math properly in linear RGB, possibly leading to all sorts of banding and aliasing artifacts. A lot of widespread image editing software is surprisingly inept at offering means for dealing with this.&#xD;&#xA;&#xD;&#xA;What I mostly do now is to take whatever alpha my image editing software spits out and apply smooth-stepping like so:&#xD;&#xA;&#xD;&#xA;```golang&#xD;&#xA;f := float32(alpha) / 255&#xD;&#xA;return (1-f)*f*f + f*(1-(1-f)*(1-f))&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This essentially is a hack which balances:&#xD;&#xA;* Banding artifacts in low-alpha dark-over-bright and bright-over-dark blending scenarios.&#xD;&#xA;* Lossiness in white-over-black alpha-gradients.&#xD;&#xA;* Staying close to the original curve.&#xD;&#xA;&#xD;&#xA;If the result looks bad, I will usually do some over-correcting in the image instead of in the math. The math is a lost battle due to graphics software doing whatever.&#xD;&#xA;&#xD;&#xA;Interpolation artifacts (which are often brought up as a reason for doing alpha pre-multiplication) can be remedied by giving color to pixels with zero alpha which neighbor pixels with non-zero alpha, which is a task best automated with software.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39294" PostHistoryTypeId="2" PostId="13170" RevisionGUID="1c6e34f1-a391-48eb-8a56-804b8dd44981" CreationDate="2022-12-20T17:31:12.790" UserId="19358" Text="I maintain an image dithering [library](https://github.com/makeworld-the-better-one/dither) and [command line tool](https://github.com/makeworld-the-better-one/didder). When I was initially developing the library, I was trying to figure out how to match dithered RGB values (containing quantization error or randomness, whatever the dithering algo does), to the given palette of allowed output colors. Eventually I learned that the best method is not something psycho-visual, but in fact a simple calculation of Euclidean distance, as long as linearized (gamma-expanded) values are used. As a reason, I was told this by Thomas Mansencal (unfortunately the original quote source is lost):&#xD;&#xA;&#xD;&#xA;&gt; You can factor out the observer [the human] because what you are interested in here is basically energy conservation. The idea being that for a given pool of radiant power emitters, if you remove a certain number of them, by how much must the radiant power of the remaining ones be increased to be the same as that of the full pool. It is really a ratio and doing those operations in a linear space is totally appropriate!&#xD;&#xA;&#xD;&#xA;And I wrote on my [blog](https://www.makeworld.space/2021/02/dithering.html):&#xD;&#xA;&#xD;&#xA;&gt; This helped it click for me. Dithering can be thought of as trying to reconstruct the “radiant power” of the original pixel colours, while restricted to a certain set of “emitters”, aka the palette colours. It is only with linearized RGB values that we can properly measure the radiant power.&#xD;&#xA;&#xD;&#xA;This however, does not seem to be the full story. So far I have encountered two cases where results don't seem to make sense from a human perspective, where colors are being lost. You can see them [here](https://github.com/makeworld-the-better-one/didder/issues/14) and [here](https://github.com/makeworld-the-better-one/dither/issues/9).&#xD;&#xA;&#xD;&#xA;Eventually, I came across a potential solution: at time of comparison, weight each channel (still linearized) according to human vision. So green is the highest weighted, blue is the lowest, etc. This tweaks the idea of &quot;radiant power&quot; from before to better match how humans experience it, as what we call luminance.&#xD;&#xA;&#xD;&#xA;And so finally, my question: is this the right thing to do? I have found researching this topic quite difficult, and I have no academic background in it. I am hoping someone with more knowledge can tell me whether I'm on the right track or totally off base, and most importantly, if there is any research or academically-grounded software that does what I am proposing. I will be writing some test software to see if it looks good, but I would like more assurance of correctness then just &quot;looks good on a few test cases&quot;.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39296" PostHistoryTypeId="1" PostId="13170" RevisionGUID="1c6e34f1-a391-48eb-8a56-804b8dd44981" CreationDate="2022-12-20T17:31:12.790" UserId="19358" Text="How to find the nearest palette color when dithering in RGB" ContentLicense="CC BY-SA 4.0" />
  <row Id="39297" PostHistoryTypeId="3" PostId="13170" RevisionGUID="1c6e34f1-a391-48eb-8a56-804b8dd44981" CreationDate="2022-12-20T17:31:12.790" UserId="19358" Text="|algorithm|image-processing|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39298" PostHistoryTypeId="2" PostId="13171" RevisionGUID="d0bfdc32-f44d-4d7b-ae53-a7201c7df7b7" CreationDate="2022-12-20T20:16:12.353" UserId="5556" Text="Dithering is a pretty complex subject that I've had probably a half dozen folks ask me about over the years.&#xD;&#xA;&#xD;&#xA;My visceral answer is that a dithering approach is effectively *constructing* a value between some other values.&#xD;&#xA;&#xD;&#xA;What most folks will tend to arrive at is the notion of photometric luminance to guide the dithering formula, which is certainly about half of the equation if we leave out the complexities of vision assemblage of information on the fly, and all of the nightmare fuel that comes from that.&#xD;&#xA;&#xD;&#xA;The interesting nuance is the projection of the luminance. Should it be uniform tristimulus luminance to sample from, or a more perceptually-aligned &quot;brightness-like&quot; distribution.&#xD;&#xA;&#xD;&#xA;My guts always lean toward the idea that when we are guessing / fabricating a value that does not exist, from some samples of other values, that the proper &quot;construction&quot; of the value should be based on how an observer might perceive it. That is, a *perceptual* like distribution.[1]&#xD;&#xA;&#xD;&#xA;For a simple test, I'd suggest using something very simple like L* from Lab for guessing and constructing intermediate values.&#xD;&#xA;&#xD;&#xA;For values that carry chrominance, and with the *tremendous* assumption that the values are relative to BT.709 / sRGB, the &quot;correct&quot; weighting would be `0.2126 R + 0.7152 G + 0.0722 B`. Note that this weighting can only be properly derived from uniform tristimulus, which means you do not want to weight encoded values, but rather the uniform tristimulus version (sometimes called &quot;linear&quot; but yikes...)&#xD;&#xA;&#xD;&#xA;For sRGB encoded values, a simple 2.2 power function will decode the encoded values to uniform tristimulus, avoiding another rabbit hole.&#xD;&#xA;&#xD;&#xA;Good luck. &#xD;&#xA;&#xD;&#xA;[1] For more information about why a uniform-with-respect-to-loose-perception is more sensible for guessing / constructing values between values, see page 51 of [&quot;A Fresh Look at Generalized Sampling&quot;][1] by Nehab and Hoppe.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://hhoppe.com/filtering.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="39300" PostHistoryTypeId="50" PostId="5220" RevisionGUID="69955887-19a8-42ac-92c8-04f5d2d9e79a" CreationDate="2022-12-21T00:11:56.350" UserId="-1" />
  <row Id="39301" PostHistoryTypeId="52" PostId="13170" RevisionGUID="4c670504-b237-44a8-9399-5c0538879a4a" CreationDate="2022-12-21T01:31:49.650" />
  <row Id="39302" PostHistoryTypeId="2" PostId="13172" RevisionGUID="e41ea063-53e8-4bb5-b5ca-20a8444f9dd9" CreationDate="2022-12-21T09:43:39.653" UserId="19363" Text="I've searched everywhere for an equation that suits my needs but i couldn't find anything useful. I'm making a voxel ray-tracer so I need an equation that gets me the intersection of a ray with a box, and the box's normal.&#xD;&#xA;&#xD;&#xA;I looked at inigo quilez's [intersection code][1] but I can't derive the equation from the code shown so i need the equation itself rather than code.&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Say we have the ray's origin $O(-5, 1, 0)$ and the box position $B(0, 0, 0)$ with the ray's direction as a unit vector being $(1, 0, 0)$ and the box's side lengths being $(2, 2, 2)$&#xD;&#xA;&#xD;&#xA; 1. I need the equation to return the distance between the point where the ray hits the box, and the ray's origin&#xD;&#xA;&#xD;&#xA; 2. I need the box's normal where the intersection is&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://iquilezles.org/articles/intersectors/" ContentLicense="CC BY-SA 4.0" />
  <row Id="39304" PostHistoryTypeId="1" PostId="13172" RevisionGUID="e41ea063-53e8-4bb5-b5ca-20a8444f9dd9" CreationDate="2022-12-21T09:43:39.653" UserId="19363" Text="ray-box intersection" ContentLicense="CC BY-SA 4.0" />
  <row Id="39305" PostHistoryTypeId="3" PostId="13172" RevisionGUID="e41ea063-53e8-4bb5-b5ca-20a8444f9dd9" CreationDate="2022-12-21T09:43:39.653" UserId="19363" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39306" PostHistoryTypeId="2" PostId="13173" RevisionGUID="717c36fa-c58f-4e5a-86f2-ff2e1af003a1" CreationDate="2022-12-21T14:24:44.563" UserId="19365" Text="This code displays a white texture always except when the dimensions are 383 x 512&#xD;&#xA;&#xD;&#xA;```    &#xD;&#xA;    img.size.height = 512;&#xD;&#xA;    img.size.width = 383;&#xD;&#xA;    img.data = new uint8_t[img.size.width * img.size.height*3];&#xD;&#xA;    memset(img.&#xD;&#xA;    if (!glfwInit())&#xD;&#xA;    {&#xD;&#xA;        error(&quot;Failed to initialize glfw\n&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(983, 720, &quot;Hello&quot;, NULL, NULL);&#xD;&#xA;    screenRatio = 983.0 / 720.0;&#xD;&#xA;    textureRatio = (float)img.size.width / (float)img.size.height;&#xD;&#xA;    calculate_quad_dimensions();&#xD;&#xA;    if (!window)&#xD;&#xA;        error(&quot;Failed to create GLFWwindow&quot;);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    int err = glewInit();&#xD;&#xA;    if (err != GLEW_OK)&#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;        error(&quot;Failed to initialize GLEW.&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLCall(glClearColor(0.20, 0.20, 0.20, 1));&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;    glfwSetWindowSizeCallback(window, size_callback);&#xD;&#xA;    glfwSetKeyCallback(window, key_callback);&#xD;&#xA;    glfwSwapInterval(1);&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    GLCall(glGenTextures(1, &amp;texture));&#xD;&#xA;    GLCall(glBindTexture(GL_TEXTURE_2D, texture));&#xD;&#xA;&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));&#xD;&#xA;&#xD;&#xA;    GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, img.size.width, img.size.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data));&#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;    delete[] img.data;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glBegin(GL_QUADS);&#xD;&#xA;    glTexCoord2f(offsetx + 0.0, offsety + 0.0); glVertex2f(-quadWidth, -quadHeight); // Lower left&#xD;&#xA;    glTexCoord2f(offsetx + 1, offsety + 0.0);  glVertex2f(quadWidth, -quadHeight);  // Lower right&#xD;&#xA;    glTexCoord2f(offsetx + 1, offsety + 1);     glVertex2f(quadWidth, quadHeight);   // Upper right&#xD;&#xA;    glTexCoord2f(offsetx + 0.0, offsety + 1);  glVertex2f(-quadWidth, quadHeight);  // upper left&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    glfwPollEvents();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glfwDestroyWindow(window);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;```&#xD;&#xA;when the dimensions are 383 x 512, the image has glitched random pixels at the top row:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TJd8U.png&#xD;&#xA;&#xD;&#xA;any other dimension i tried, the image is pure white. This is a problem because im making a photo viewer app and the thumbnail is the dimension 383 x 512, and the garbage pixels at the top row are pushing the image down skewing it." ContentLicense="CC BY-SA 4.0" />
  <row Id="39308" PostHistoryTypeId="1" PostId="13173" RevisionGUID="717c36fa-c58f-4e5a-86f2-ff2e1af003a1" CreationDate="2022-12-21T14:24:44.563" UserId="19365" Text="Opengl Texture top row pixels are garbage" ContentLicense="CC BY-SA 4.0" />
  <row Id="39309" PostHistoryTypeId="3" PostId="13173" RevisionGUID="717c36fa-c58f-4e5a-86f2-ff2e1af003a1" CreationDate="2022-12-21T14:24:44.563" UserId="19365" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39310" PostHistoryTypeId="5" PostId="13173" RevisionGUID="df97bfbd-d2d7-4f11-9147-c81f31914054" CreationDate="2022-12-21T14:46:39.950" UserId="19365" Comment="added 45 characters in body" Text="This code displays a white texture always except when the dimensions are 383 x 512&#xD;&#xA;&#xD;&#xA;```    &#xD;&#xA;    img.size.height = 512;&#xD;&#xA;    img.size.width = 383;&#xD;&#xA;    img.data = new uint8_t[img.size.width * img.size.height*3];&#xD;&#xA;    memset(img.data, 0, img.size.width * img.size.height*3);&#xD;&#xA;    if (!glfwInit())&#xD;&#xA;    {&#xD;&#xA;        error(&quot;Failed to initialize glfw\n&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(983, 720, &quot;Hello&quot;, NULL, NULL);&#xD;&#xA;    screenRatio = 983.0 / 720.0;&#xD;&#xA;    textureRatio = (float)img.size.width / (float)img.size.height;&#xD;&#xA;    calculate_quad_dimensions();&#xD;&#xA;    if (!window)&#xD;&#xA;        error(&quot;Failed to create GLFWwindow&quot;);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    int err = glewInit();&#xD;&#xA;    if (err != GLEW_OK)&#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;        error(&quot;Failed to initialize GLEW.&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLCall(glClearColor(0.20, 0.20, 0.20, 1));&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;    glfwSetWindowSizeCallback(window, size_callback);&#xD;&#xA;    glfwSetKeyCallback(window, key_callback);&#xD;&#xA;    glfwSwapInterval(1);&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    GLCall(glGenTextures(1, &amp;texture));&#xD;&#xA;    GLCall(glBindTexture(GL_TEXTURE_2D, texture));&#xD;&#xA;&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));&#xD;&#xA;&#xD;&#xA;    GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, img.size.width, img.size.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data));&#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;    delete[] img.data;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glBegin(GL_QUADS);&#xD;&#xA;    glTexCoord2f(offsetx + 0.0, offsety + 0.0); glVertex2f(-quadWidth, -quadHeight); // Lower left&#xD;&#xA;    glTexCoord2f(offsetx + 1, offsety + 0.0);  glVertex2f(quadWidth, -quadHeight);  // Lower right&#xD;&#xA;    glTexCoord2f(offsetx + 1, offsety + 1);     glVertex2f(quadWidth, quadHeight);   // Upper right&#xD;&#xA;    glTexCoord2f(offsetx + 0.0, offsety + 1);  glVertex2f(-quadWidth, quadHeight);  // upper left&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    glfwPollEvents();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glfwDestroyWindow(window);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;```&#xD;&#xA;when the dimensions are 383 x 512, the image has glitched random pixels at the top row:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TJd8U.png&#xD;&#xA;&#xD;&#xA;any other dimension i tried, the image is pure white. This is a problem because im making a photo viewer app and the thumbnail is the dimension 383 x 512, and the garbage pixels at the top row are pushing the image down skewing it." ContentLicense="CC BY-SA 4.0" />
  <row Id="39311" PostHistoryTypeId="5" PostId="13173" RevisionGUID="cdff6e1b-0285-4eb7-a450-18442fa89b24" CreationDate="2022-12-21T14:49:52.343" UserId="19365" Comment="added 2 characters in body" Text="This code displays a white texture always except when the dimensions are 383 x 512&#xD;&#xA;&#xD;&#xA;```    &#xD;&#xA;    img.size.height = 512;&#xD;&#xA;    img.size.width = 383;&#xD;&#xA;    img.data = new uint8_t[img.size.width * img.size.height*3];&#xD;&#xA;    memset(img.data, 'a', img.size.width * img.size.height*3);&#xD;&#xA;    if (!glfwInit())&#xD;&#xA;    {&#xD;&#xA;        error(&quot;Failed to initialize glfw\n&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLFWwindow* window = glfwCreateWindow(983, 720, &quot;Hello&quot;, NULL, NULL);&#xD;&#xA;    screenRatio = 983.0 / 720.0;&#xD;&#xA;    textureRatio = (float)img.size.width / (float)img.size.height;&#xD;&#xA;    calculate_quad_dimensions();&#xD;&#xA;    if (!window)&#xD;&#xA;        error(&quot;Failed to create GLFWwindow&quot;);&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    glfwMakeContextCurrent(window);&#xD;&#xA;    int err = glewInit();&#xD;&#xA;    if (err != GLEW_OK)&#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;        error(&quot;Failed to initialize GLEW.&quot;);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    GLCall(glClearColor(0.20, 0.20, 0.20, 1));&#xD;&#xA;    glEnable(GL_TEXTURE_2D);&#xD;&#xA;&#xD;&#xA;    glfwSetWindowSizeCallback(window, size_callback);&#xD;&#xA;    glfwSetKeyCallback(window, key_callback);&#xD;&#xA;    glfwSwapInterval(1);&#xD;&#xA;&#xD;&#xA;    GLuint texture;&#xD;&#xA;    GLCall(glGenTextures(1, &amp;texture));&#xD;&#xA;    GLCall(glBindTexture(GL_TEXTURE_2D, texture));&#xD;&#xA;&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));&#xD;&#xA;    GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));&#xD;&#xA;&#xD;&#xA;    GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, img.size.width, img.size.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data));&#xD;&#xA;    glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;    delete[] img.data;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    while (!glfwWindowShouldClose(window))&#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;    glBegin(GL_QUADS);&#xD;&#xA;    glTexCoord2f(offsetx + 0.0, offsety + 0.0); glVertex2f(-quadWidth, -quadHeight); // Lower left&#xD;&#xA;    glTexCoord2f(offsetx + 1, offsety + 0.0);  glVertex2f(quadWidth, -quadHeight);  // Lower right&#xD;&#xA;    glTexCoord2f(offsetx + 1, offsety + 1);     glVertex2f(quadWidth, quadHeight);   // Upper right&#xD;&#xA;    glTexCoord2f(offsetx + 0.0, offsety + 1);  glVertex2f(-quadWidth, quadHeight);  // upper left&#xD;&#xA;    glEnd();&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    glfwSwapBuffers(window);&#xD;&#xA;    glfwPollEvents();&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    glfwDestroyWindow(window);&#xD;&#xA;    glfwTerminate();&#xD;&#xA;```&#xD;&#xA;when the dimensions are 383 x 512, the image has glitched random pixels at the top row:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TJd8U.png&#xD;&#xA;&#xD;&#xA;any other dimension i tried, the image is pure white. This is a problem because im making a photo viewer app and the thumbnail is the dimension 383 x 512, and the garbage pixels at the top row are pushing the image down skewing it." ContentLicense="CC BY-SA 4.0" />
  <row Id="39312" PostHistoryTypeId="2" PostId="13174" RevisionGUID="257e2242-ebb4-44a7-a401-4b8e5fa58619" CreationDate="2022-12-21T18:25:13.770" UserId="19366" Text="PBRT has code for axis-aligned bounding boxes.&#xD;&#xA;&#xD;&#xA;https://www.pbr-book.org/3ed-2018/Shapes/Basic_Shape_Interface#Bounds3::IntersectP&#xD;&#xA;&#xD;&#xA;They only have an intersection predicate for occlusion rays, but extending this to give you the normals and support non-axis-aligned bounding boxes is simple.&#xD;&#xA;&#xD;&#xA;To acquire the normals, you create a normal in the proper direction for the hit slab. It loops through the x, y, and z directions, and since this is axis aligned, you return (1, 0, 0), (0, 1, 0), or (0, 0, 1). There is also a check to see if the hit values are reversed, in which case the normals are reversed, e.g. (-1, 0, 0).&#xD;&#xA;&#xD;&#xA;If you want to support non-axis-aligned bounding boxes, it's probably easiest to apply the inverse of the box's transform to the intersection ray and then do the axis-aligned test as above. In the end, you apply the transform to the output normals (remember that transforming normals has different rules than transforming vectors).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39314" PostHistoryTypeId="50" PostId="12850" RevisionGUID="dc86c48d-1a15-4a64-8b06-cfd062038766" CreationDate="2022-12-21T23:05:15.553" UserId="-1" />
  <row Id="39315" PostHistoryTypeId="2" PostId="13175" RevisionGUID="2e637ae9-0628-4ec2-92c7-19a0c6a94cef" CreationDate="2022-12-22T08:46:30.517" UserId="3242" Text="[PBRT 7.2.2](https://www.pbr-book.org/3ed-2018/Sampling_and_Reconstruction/Sampling_Interface#BasicSamplerInterface) illustrates an example on `requests sample dimensions in the same order`:&#xD;&#xA;```C++&#xD;&#xA;sampler-&gt;StartPixel(p);&#xD;&#xA;do {&#xD;&#xA;  Float v = a(sampler-&gt;Get1D());&#xD;&#xA;  if (v &gt; 0)&#xD;&#xA;      v += b(sampler-&gt;Get1D());&#xD;&#xA;  v += c(sampler-&gt;Get1D());&#xD;&#xA;} while (sampler-&gt;StartNextSample());&#xD;&#xA;```&#xD;&#xA;&gt; In this case, the first dimension of the sample vector will always be passed to the function a(); when the code path that calls b() is executed, b() will receive the second dimension. However, if the if test isn’t always true or false, then c() will sometimes receive a sample from the second dimension of the sample vector and otherwise receive a sample from the third dimension. Thus, efforts by the sampler to provide well-distributed sample points in each dimension being evaluated have been thwarted.&#xD;&#xA;&#xD;&#xA;So I'm trying to understand this concept by fixing the code: to keep samples always in the same order, we can always prepare a sample for `b()`, use it when the if test returns true and discard it otherwise:&#xD;&#xA;```&#xD;&#xA;sampler-&gt;StartPixel(p);&#xD;&#xA;do {&#xD;&#xA;  Float v = a(sampler-&gt;Get1D());&#xD;&#xA;  auto second_sample = sampler-&gt;Get1D();&#xD;&#xA;  if (v &gt; 0)&#xD;&#xA;      v += b(second_sample);&#xD;&#xA;  v += c(sampler-&gt;Get1D());&#xD;&#xA;} while (sampler-&gt;StartNextSample());&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;After fixing, the 1st sample always go to `a()`, 2nd goes to `b()` and 3rd goes to `c()` thus the order is maintained.&#xD;&#xA;&#xD;&#xA;Do I understand it correctly? Is my fix correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39317" PostHistoryTypeId="1" PostId="13175" RevisionGUID="2e637ae9-0628-4ec2-92c7-19a0c6a94cef" CreationDate="2022-12-22T08:46:30.517" UserId="3242" Text="PBRT: requests sample dimensions in the same order" ContentLicense="CC BY-SA 4.0" />
  <row Id="39318" PostHistoryTypeId="3" PostId="13175" RevisionGUID="2e637ae9-0628-4ec2-92c7-19a0c6a94cef" CreationDate="2022-12-22T08:46:30.517" UserId="3242" Text="|sampling|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39319" PostHistoryTypeId="50" PostId="12359" RevisionGUID="62ce6f66-3a30-4c98-9edd-a18e7c9c25aa" CreationDate="2022-12-22T09:01:35.180" UserId="-1" />
  <row Id="39320" PostHistoryTypeId="5" PostId="257" RevisionGUID="e4a853eb-07b5-4484-a2f4-d3f6ccd44e82" CreationDate="2022-12-23T03:49:49.303" UserId="5778" Comment="broken image fixed (click 'Inline' or 'Side-by-side' to see the difference; image retrieved via Wayback Machine); for more info, see https://git.io/JqCQN" Text="In image editing software, you often have the ability to do a directional blur where you can choose and angle and a magnitude of a blur.&#xD;&#xA;&#xD;&#xA;How does this actually work in practice with Gaussian blurring?&#xD;&#xA;&#xD;&#xA;I could see possibly doing something like making the blur go across the axis specified by the angle and use some sort of texture sampling to find the appropriate sample (bilinear or bicubic sampling), but that seems like it probably isn't correct.&#xD;&#xA;&#xD;&#xA;How does directional blurring usually work?&#xD;&#xA;&#xD;&#xA;I would say this is in fact motion blur, but I'm asking specifically about the blurring portion, not the whole set up for motion blur within a renderer.&#xD;&#xA;&#xD;&#xA;For instance before and after:&#xD;&#xA;&#xD;&#xA;![enter image description here][1]&#xD;&#xA;[![enter image description here][2]][2]  &#xA;&lt;sub&gt;(source: [gimp.org](https://docs.gimp.org/en_GB/images/filters/examples/blur-taj-mblur-linear.jpg))&lt;/sub&gt;  &#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://docs.gimp.org/en_GB/images/filters/examples/taj_orig.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/KWH12.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39321" PostHistoryTypeId="24" PostId="257" RevisionGUID="e4a853eb-07b5-4484-a2f4-d3f6ccd44e82" CreationDate="2022-12-23T03:49:49.303" Comment="Proposed by 5778 approved by 482 edit id of 606" ContentLicense="CC BY-SA 4.0" />
  <row Id="39322" PostHistoryTypeId="2" PostId="13176" RevisionGUID="001d38be-9c33-49e5-b1aa-c2302257a637" CreationDate="2022-12-23T08:12:08.480" UserId="19374" Text="I can't for the life of me figure out how to use a perspective projection matrix.  My understanding is that, once objects are in view space, the the perspective transform uses the z-coordinate to scale the x and y coordinates.&#xD;&#xA;&#xD;&#xA;Here's the code I'm using (C#, dotnet 7).&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;var viewToScreen = Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.Tau / 4), 1.0f, 0.1f, 100f);&#xD;&#xA;&#xD;&#xA;var square1 = new Vector3[]&#xD;&#xA;{&#xD;&#xA;    new(+1, +1, 1),&#xD;&#xA;    new(-1, +1, 1),&#xD;&#xA;    new(+1, +1, 1),&#xD;&#xA;    new(+1, -1, 1),&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;var square2 = Array.ConvertAll(square1, v =&gt;&#xD;&#xA;{&#xD;&#xA;    v.Z += 3;&#xD;&#xA;    return v;&#xD;&#xA;}).Dump(&quot;Square 2 (World Space)&quot;);&#xD;&#xA;&#xD;&#xA;var screen1m1 = Array.ConvertAll(square1, v =&gt; Vector3.Transform(v, viewToScreen));&#xD;&#xA;&#xD;&#xA;var screen2m1 = Array.ConvertAll(square2, v =&gt; Vector3.Transform(v, viewToScreen))&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However, after the transform, the X and Y coordinates remain unchanged.  Only the Z coordinate is changed, and then only slightly.  This is consistent with an orthogonal projection, not a perspective projection.&#xD;&#xA;&#xD;&#xA;What am I doing wrong here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39324" PostHistoryTypeId="1" PostId="13176" RevisionGUID="001d38be-9c33-49e5-b1aa-c2302257a637" CreationDate="2022-12-23T08:12:08.480" UserId="19374" Text="Trouble transforming vectors from view space to screen space using a perspective projection matrix" ContentLicense="CC BY-SA 4.0" />
  <row Id="39325" PostHistoryTypeId="3" PostId="13176" RevisionGUID="001d38be-9c33-49e5-b1aa-c2302257a637" CreationDate="2022-12-23T08:12:08.480" UserId="19374" Text="|matrix|rasterizer|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39326" PostHistoryTypeId="50" PostId="8194" RevisionGUID="76c03606-d7d5-4cea-8852-096aacf796b9" CreationDate="2022-12-23T11:02:30.390" UserId="-1" />
  <row Id="39327" PostHistoryTypeId="2" PostId="13177" RevisionGUID="4e65b0c2-faa0-4ab5-91b3-7e7390105695" CreationDate="2022-12-23T12:22:57.670" UserId="13273" Text="The way to do the projection is the following:&#xD;&#xA;&#xD;&#xA;    Matrix4x4 projection;&#xD;&#xA;    Matrix4x4 modelView;&#xD;&#xA;    Vector4D position4D;&#xD;&#xA;    &#xD;&#xA;    //fist the position's 4th value (w) need to be set to value &quot;1&quot;&#xD;&#xA;    position4D = Vector4D(position3D, 1); //the 1 in the 4th component is very important!&#xD;&#xA;    Vector4D result = projection * modelView * position4D;&#xD;&#xA;    //at the end, the result need to be divided by its 4th component (w) &#xD;&#xA;    result = result / result.w;&#xD;&#xA;&#xD;&#xA;The last line is of major importance, because the projection (perspective) is not linear. the division by the 4th component can not be applied within the matrix." ContentLicense="CC BY-SA 4.0" />
  <row Id="39329" PostHistoryTypeId="2" PostId="13178" RevisionGUID="d1820da7-f30b-459e-a238-03437d2e14c3" CreationDate="2022-12-23T18:12:45.867" UserId="19371" Text="I'm watching the [TU Wien rendering lectures][1] in the course we were presented with a rendering equation (first one on the screenshot) and then another, which results from a change of variables (if I understand correctly).&#xD;&#xA;&#xD;&#xA;No when we moved to the basic path tracer lecture, we have been using the first equation. Why is that? I thought we use the second equation when dealing with arbitrary objects (with bigger distances than 1 and different angles of the surface) and Eq.1 was just a tool to derive it.  &#xD;&#xA;&#xD;&#xA;In general I am a bit confused, when to use what equation, what is the correct image formation model, if I have an image of a scene I click and I have a renderer, how do I accurately model what we will capture? &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cg.tuwien.ac.at/courses/Rendering/VU/2021S&#xD;&#xA;  [2]: https://i.stack.imgur.com/uAWsl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39331" PostHistoryTypeId="1" PostId="13178" RevisionGUID="d1820da7-f30b-459e-a238-03437d2e14c3" CreationDate="2022-12-23T18:12:45.867" UserId="19371" Text="Rendering equation integration variable change" ContentLicense="CC BY-SA 4.0" />
  <row Id="39332" PostHistoryTypeId="3" PostId="13178" RevisionGUID="d1820da7-f30b-459e-a238-03437d2e14c3" CreationDate="2022-12-23T18:12:45.867" UserId="19371" Text="|rendering|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39333" PostHistoryTypeId="6" PostId="13178" RevisionGUID="c7e6439d-79ec-43a7-a0b0-56822fb0d6ae" CreationDate="2022-12-23T20:15:53.713" UserId="19371" Comment="edited tags" Text="|raytracing|rendering|pathtracing|physically-based|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39337" PostHistoryTypeId="50" PostId="12286" RevisionGUID="a686b41d-66b3-404e-984d-38c24aeda984" CreationDate="2022-12-24T09:00:35.083" UserId="-1" />
  <row Id="39338" PostHistoryTypeId="2" PostId="13179" RevisionGUID="3c4739ee-2c08-4e23-bbaa-29f9840af5be" CreationDate="2022-12-24T16:04:16.363" UserId="6588" Text="Both equations are correct, they are just writing the incoming radiance at point $x$ as an integral over two different domains. The first line is the solid angle formulation (integrating over all $\omega \in \Omega$), while the second one is the surface area formulation (integrating over all differential area point $A_y \in S_l$). The additional cosine term divided by the square distance is simply the Jacobian of this change of variable.&#xD;&#xA;&#xD;&#xA;The surface area formulation of the rendering equation is quite useful as it allows to integrate over all area light sources in a scene. Sometimes, it can be better to use the solid angle form for certain types of emitters (e.g. when your emitter is a perfect sphere, in which case you can sample its spherical cap more efficiently). In most cases, however, the surface area is preferred as it allows for more general emissive profiles. &#xD;&#xA;&#xD;&#xA;As an example, suppose your light is an emissive bunny. How would you sample the subtended solid angle? It can be quite tricky without determining the silhouette edges! But in the surface area form, all you have to do is sample a triangle proportional to its area, sample a point on that triangle using barycentric coordinates, and you're done.&#xD;&#xA;&#xD;&#xA;Both formulations have their pros and cons and a renderer will allow you to switch between one and the other (only when possible), with the default being surface area as most emitters are usually attached to an arbitrary mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="39340" PostHistoryTypeId="50" PostId="12807" RevisionGUID="c7afb4b5-8406-4cce-bedc-e7488a846d12" CreationDate="2022-12-26T19:08:30.990" UserId="-1" />
  <row Id="39341" PostHistoryTypeId="50" PostId="10535" RevisionGUID="04e51ce9-bc27-4e4f-a4bf-57aacf10c02f" CreationDate="2022-12-27T00:04:35.493" UserId="-1" />
  <row Id="39342" PostHistoryTypeId="2" PostId="13180" RevisionGUID="4245c3f3-6b61-4c25-a4ec-774f949383e6" CreationDate="2022-12-27T21:44:52.153" UserId="15373" Text="This is possible with only a single framebuffer and a single texture (with mips).&#xD;&#xA;&#xD;&#xA;To select the mip level to _render to_, you can use `glFramebufferTexture2D`, as in the example you gave. Be sure to also set glViewport to the width/height of the mip you are rendering to.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);&#xD;&#xA;glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmaplevelToRenderTo);&#xD;&#xA;glViewport(0, 0, mipWidth, mipHeight);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Then, to limit the mip level that you're sampling from, the safest&lt;sup&gt;1&lt;/sup&gt; way is to use the `GL_TEXTURE_BASE_LEVEL` and `GL_TEXTURE_MAX_LEVEL` texture parameters.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glBindTexture(GL_TEXTURE_2D, textureID);&#xD;&#xA;int mipToSampleFrom = mipmaplevelToRenderTo - 1;&#xD;&#xA;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, mipToSampleFrom);&#xD;&#xA;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipToSampleFrom);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This will allow you to use `texture(sampler, uv)` (or similar) in your shader as normal, and it will only sample from the one mip level you specified. Note that `GL_TEXTURE_BASE_LEVEL` also changes the meaning of GLSL functions like `textureSize()`, which takes a _lod_ parameter: if you've modified `GL_TEXTURE_BASE_LEVEL`, then _lod_ will be relative to the base level, meaning that `textureSize(sampler, 0)` will conveniently return the size of the currently configured base mip level.&#xD;&#xA;&#xD;&#xA;To reset, just set those params to their default OpenGL values:&#xD;&#xA;```&#xD;&#xA;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);&#xD;&#xA;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&lt;sup&gt;1&lt;/sup&gt; Whenever a texture is sampled from while also being rendered to, you can run the risk of hitting undefined behavior. The OpenGL spec is fairly conservative about what can constitute undefined behavior, even if the shader wouldn't _actually_ ever sample from the same texel that it's writing to, so one way to avoid the issue is to make it _impossible_ by using the `GL_TEXTURE_BASE_LEVEL` and `GL_TEXTURE_MAX_LEVEL` params. See the spec for details: https://registry.khronos.org/OpenGL/specs/es/3.0/es_spec_3.0.pdf#page=224" ContentLicense="CC BY-SA 4.0" />
  <row Id="39344" PostHistoryTypeId="2" PostId="13181" RevisionGUID="b74107a5-8d6b-4ed6-afea-17a09a2ecde4" CreationDate="2022-12-28T13:23:06.427" UserId="19365" Text="After a lot of research, i finally found the problem. glTexImage2D expects the data to be padded. I had to use ``glPixelStorei(GL_UNPACK_ALIGNMENT, 1)``&#xD;&#xA;to ask opengl to not interpret any padding" ContentLicense="CC BY-SA 4.0" />
  <row Id="39346" PostHistoryTypeId="2" PostId="13182" RevisionGUID="8c66b8c6-efad-4383-a094-71a13261345e" CreationDate="2022-12-28T15:02:48.993" UserId="19385" Text="I'm just starting to self-learn OpenGL. I have OpenGL A Primer (2nd edition) by Edward Angel and I found this useful site for setting up OpenGL with Visual Studio 2019 on Windows: &#xD;&#xA;&#xD;&#xA;https://www.geeksforgeeks.org/how-to-setup-opengl-with-visual-studio-2019-on-windows-10/&#xD;&#xA;&#xD;&#xA;I was able to get an example up and running HOWEVER, only by using a 32 bit configuration. The header file &quot;glut.h&quot; seems to specifically call out 32 bit libraries.  Is it possible to use GLUT with 64 bit builds?  I did some research and couldn't find an answer. It makes me wonder if GLUT is no longer supported or there is a newer version somewhere. The tutorial above points me to https://www.opengl.org/resources/libraries/glut/glut_downloads.php and it seems quite dated. The most relevant download appears to be glut37data.zip&#xD;&#xA;&#xD;&#xA;Summary of questions:&#xD;&#xA;1)  Are there GLUT headers/libs/dlls in 64 bit version for Windows? Where?&#xD;&#xA;2)  Should I be using GLUT or has it been replaced with something better/newer?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="39348" PostHistoryTypeId="1" PostId="13182" RevisionGUID="8c66b8c6-efad-4383-a094-71a13261345e" CreationDate="2022-12-28T15:02:48.993" UserId="19385" Text="OpenGL and GLUT in x64 on Windows (Visual C++ 2019)" ContentLicense="CC BY-SA 4.0" />
  <row Id="39349" PostHistoryTypeId="3" PostId="13182" RevisionGUID="8c66b8c6-efad-4383-a094-71a13261345e" CreationDate="2022-12-28T15:02:48.993" UserId="19385" Text="|opengl|c++|glut|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39350" PostHistoryTypeId="50" PostId="12384" RevisionGUID="f29417bf-9358-49cb-b841-67312162b70b" CreationDate="2022-12-28T17:05:05.590" UserId="-1" />
  <row Id="39351" PostHistoryTypeId="2" PostId="13183" RevisionGUID="f20a2538-45bd-4446-a615-24290802f76c" CreationDate="2022-12-29T00:21:33.130" UserId="19386" Text="could you please give me some guidance on following this libgil tutorial? https://libigl.github.io/libigl-python-bindings/tut-chapter0/&#xD;&#xA;&#xD;&#xA;The problem: When I do the first example (two yellow triangles), I run in to an error with plot() saying that: display is undefined.&#xD;&#xA;&#xD;&#xA;What I did: I followed the link to the source file (not sure what it's called in computer science...) where plot() is defined. I 'fixed' the problem by importing IPython to get display. Then new problem is, when I run the code now, I just get a printout in the console, rather than the display.[![the plot() function][1]][1]&#xD;&#xA;&#xD;&#xA;My guess: it looks like in the decision tree of plot(), I never get to the part where the viewer is activated&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/83Snc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39353" PostHistoryTypeId="1" PostId="13183" RevisionGUID="f20a2538-45bd-4446-a615-24290802f76c" CreationDate="2022-12-29T00:21:33.130" UserId="19386" Text="help with libgil tutorial (python binding)" ContentLicense="CC BY-SA 4.0" />
  <row Id="39354" PostHistoryTypeId="3" PostId="13183" RevisionGUID="f20a2538-45bd-4446-a615-24290802f76c" CreationDate="2022-12-29T00:21:33.130" UserId="19386" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39355" PostHistoryTypeId="2" PostId="13184" RevisionGUID="0efee427-c88b-460a-885e-d9fb85cca27a" CreationDate="2022-12-29T13:35:01.303" UserId="19391" Text="I just took a online computer graphics course and studied surface subdivision. &#xD;&#xA;&#xD;&#xA;I knew that surface subdivision could update a coarse surface into a fine one, but can we predict the updated surface shape depending on the original surface? &#xD;&#xA;&#xD;&#xA;In my point of view I dont think it can be predicted, and based on this assumption, how can surface subdivision technique be used in animations? (For example, in Geri's game, surface subdivision is used to upsample the coarse model)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39357" PostHistoryTypeId="1" PostId="13184" RevisionGUID="0efee427-c88b-460a-885e-d9fb85cca27a" CreationDate="2022-12-29T13:35:01.303" UserId="19391" Text="Can surface subdivision results be predicted?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39358" PostHistoryTypeId="3" PostId="13184" RevisionGUID="0efee427-c88b-460a-885e-d9fb85cca27a" CreationDate="2022-12-29T13:35:01.303" UserId="19391" Text="|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39359" PostHistoryTypeId="2" PostId="13185" RevisionGUID="6cc07a62-b53c-4a8f-9540-43985715dd31" CreationDate="2022-12-29T14:26:07.960" UserId="19392" Text="GLUT is outdated and abandoned. However there is a remake of GLUT library and it is called FreeGLUT. You can download sources from official page or complete library with compiled DLLs for windows 32bit and 64bit from here: https://www.transmissionzero.co.uk/software/freeglut-devel/" ContentLicense="CC BY-SA 4.0" />
  <row Id="39361" PostHistoryTypeId="50" PostId="13134" RevisionGUID="44e65d75-df36-4686-8522-9cb5a1444f59" CreationDate="2022-12-29T22:03:00.410" UserId="-1" />
  <row Id="39363" PostHistoryTypeId="2" PostId="13186" RevisionGUID="0f7e72ed-16fe-4cbc-99b2-58fdaa5c1dd0" CreationDate="2022-12-31T09:10:20.763" UserId="13273" Text="&gt; I knew that surface subdivision could update a coarse surface into a fine one, but can we predict the updated surface shape depending on the original surface?&#xD;&#xA;&#xD;&#xA;For me it does not sound like a question &#xD;&#xA;like: are the new generated surface vertices predictable.&#xD;&#xA;It more sounds like: how can I predict the new generated surface with respect to the neighborhood surface?&#xD;&#xA;&#xD;&#xA;**Trying to answer it**&#xD;&#xA;&#xD;&#xA;The new generated surface usually depends on the tangents of the original surface. These tangents are often defined by normal vectors which are interpolated with respect to different algorithms. For example the algorithms &quot;Curved PN triangles&quot; and &quot;Gregory patches&quot; smooth the surface with respect to bezier curves. Other techniques like &quot;displacement mapping&quot;, or different noise algorithms like &quot;perlin noise&quot;, &quot;simplex noise&quot;, &quot;white noise&quot; and a lot more add details to the new generated surface. What you do at the end, depend on your needs.&#xD;&#xA;&#xD;&#xA;&gt; how can surface subdivision technique be used in animations?&#xD;&#xA;&#xD;&#xA;Animation of character is usually based on skeletons like our physical human body works. The bones hold our body, the muscles change the orientation of these bones with respect to the neighboring bones.&#xD;&#xA;The surface above the bones (like our skin) are connected to one or more bones by having weights summed up to 1. The new generated vertices can use interpolation methods to define their weights. Alternatively textures can be used holding weight information about surrounding bones. Therefore the interpolated texture coordinates are used to find the correct pixel in the texture. " ContentLicense="CC BY-SA 4.0" />
  <row Id="39365" PostHistoryTypeId="50" PostId="12872" RevisionGUID="f57652a9-828c-49f8-887d-162c6bfaab99" CreationDate="2022-12-31T12:04:35.510" UserId="-1" />
  <row Id="39366" PostHistoryTypeId="2" PostId="13187" RevisionGUID="f980736b-0f35-482e-aa83-5c3ce4ec905e" CreationDate="2022-12-31T20:12:29.927" UserId="19399" Text="I've been trying to wrap my head around this algorithm, and I need it for my drawing function. But I can't seem to understand it.&#xD;&#xA;&#xD;&#xA;The wikipedia page https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm gives this piece of code right at the end:&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;plotLine(x0, y0, x1, y1)&#xD;&#xA;    dx = abs(x1 - x0)&#xD;&#xA;    sx = x0 &lt; x1 ? 1 : -1&#xD;&#xA;    dy = -abs(y1 - y0)&#xD;&#xA;    sy = y0 &lt; y1 ? 1 : -1&#xD;&#xA;    error = dx + dy&#xD;&#xA;    &#xD;&#xA;    while true&#xD;&#xA;        plot(x0, y0)&#xD;&#xA;        if x0 == x1 &amp;&amp; y0 == y1 break&#xD;&#xA;        e2 = 2 * error&#xD;&#xA;        if e2 &gt;= dy&#xD;&#xA;            if x0 == x1 break&#xD;&#xA;            error = error + dy&#xD;&#xA;            x0 = x0 + sx&#xD;&#xA;        end if&#xD;&#xA;        if e2 &lt;= dx&#xD;&#xA;            if y0 == y1 break&#xD;&#xA;            error = error + dx&#xD;&#xA;            y0 = y0 + sy&#xD;&#xA;        end if&#xD;&#xA;    end while&#xD;&#xA;```&#xD;&#xA;So it starts by getting the x and y distance between the end points.  &#xD;&#xA;It uses sx/sy to change the computation depending on the direction.  All fine.  &#xD;&#xA;But then it introduces the error value, and I can't wrap my head around how it can mix apples and oranges.&#xD;&#xA;&#xD;&#xA;I mean, I do kind of superficially understand that this value flip flops as you go along the line and determines whether the next pixel is above or below... but I just can't understand how you can mix x and y.&#xD;&#xA;&#xD;&#xA;Secondly, I take issue with e2 and its nonclalant doubling of the error value for some reason.  &#xD;&#xA;And then the value is used and compared to dx and dy.&#xD;&#xA;&#xD;&#xA;I just can't I'm too simple to understand this. I wasted a week on trying to figure this out. I have like 10 websites showing the code, but none have an explanation that would make me go: &quot;oh, now I understand.&quot;&#xD;&#xA;&#xD;&#xA;So please, can you explain this to me in simple terms without too much math lingo and weird function and delta notation. It's just coordinates and a line.&#xD;&#xA;&#xD;&#xA;Thank you" ContentLicense="CC BY-SA 4.0" />
  <row Id="39368" PostHistoryTypeId="1" PostId="13187" RevisionGUID="f980736b-0f35-482e-aa83-5c3ce4ec905e" CreationDate="2022-12-31T20:12:29.927" UserId="19399" Text="Can you explain to me the Bresenham's line algorithm in simple terms?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39369" PostHistoryTypeId="3" PostId="13187" RevisionGUID="f980736b-0f35-482e-aa83-5c3ce4ec905e" CreationDate="2022-12-31T20:12:29.927" UserId="19399" Text="|mathematics|algorithm|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39370" PostHistoryTypeId="2" PostId="13188" RevisionGUID="8f6bde8d-6c98-45b5-82df-517f1e134241" CreationDate="2022-12-31T23:31:18.520" UserId="7952" Text="The first thing to make note of is that the algorithm listed in the question is the integer algorithm. So no floating point math and the plotting increments by +1 or -1 in the x and y directions.&#xD;&#xA;&#xD;&#xA;The function takes for input the line starting position (x0,y0) and ending position (x1,y1). The starting position variables(x0,y0) are reused when drawing the line.&#xD;&#xA;&#xD;&#xA;Using inputs the algorithm computes the x and y increment directions. These values get held in variables sx and sy and are always either +1 or -1. They can be negative or positive depending on the line. For example we should get consistent results whether or not (x0,y0) and (x1,y1) are switched.&#xD;&#xA;&#xD;&#xA;To actually draw the line we need to determine whether to step in the x direction, the y direction or both x and y (ie diagonally). (that is why the algorithm uses two separate if statements instead of an if then else.) To step in the x direction it is simply &quot;x0 = x0+sx&quot; the same with the y direction. &quot;y0 = y0 + sy&quot;&#xD;&#xA;&#xD;&#xA;Our end condition happens when x0==x1 or y0==y1 or (x0,y0) == (x1,y1). This is handled in the algorithm by the &quot;if(..) then break;&quot; statements.&#xD;&#xA;&#xD;&#xA;Finally we need to be able to decide when to step in the x direction or the y direction or both. That is where the variables e2, dx, dy, and error come in.&#xD;&#xA;&#xD;&#xA;Notice that dx is always positive ie *dx = abs(x1-x0)* and dy is always negative ie *dy = -abs(y1-y0)* ... and error starts out as the sum of a positive and negative number ie *error = dx+dy*. The algorithm adds dx(which is postive) to error when the line is plotted in the x direction, and it adds dy(which is negative) to error when it is plotted in the y direction.&#xD;&#xA;&#xD;&#xA;So how do we figure out the next step? Simple look ahead one step which is *e2=2\*error* When either x0 or y0 is greater then e2 then they have gone too far, ie they are in an &quot;error state&quot;. &#xD;&#xA;&#xD;&#xA;One way to look at this is: As the algorithm plots in the x direction error will increase in the positive direction eventually making e2 greater then dx...which will stop it from plotting in the x direction ie *if(e2&lt;=dx)* will become false. Also as the algorithm plots in the y direction error will increment in the negative direction eventually making e2 less then dy, ie *if(e2&gt;=dy)* will become false.&#xD;&#xA;&#xD;&#xA;e2 isn't being pulled out of the air, it is the calculation of the next step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So that's a pretty long description...the way I originally came to understand it was to code it up in C and then step through various lines in the debugger looking at the values until that light bulb moment happened for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="39372" PostHistoryTypeId="2" PostId="13189" RevisionGUID="1fbe5a24-1e8e-432d-8505-226bd3576cda" CreationDate="2023-01-01T00:35:05.313" UserId="7462" Text="I am trying to re-implement the paper [&quot;A fresh perspective&quot;][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.dgp.toronto.edu/~karan/pdf/perspective.pdf&#xD;&#xA;&#xD;&#xA;In this paper there is one paragraph on secion 2 that reads:&#xD;&#xA;&#xD;&#xA;&gt;  Usually, $z_s = z$&#xD;&#xA;is the depth value of the point $P$, unchanged by $V_i$&#xD;&#xA;. We&#xD;&#xA;extend the viewport transformations $V_i$ so that the cannonical depth of a point $z ∈ [0, 1] $ is linearly mapped to&#xD;&#xA;$z_s$ in an arbitrary, user specified range. While the relative depth values are preserved with respect to a single&#xD;&#xA;perspective view, this allows the powerful visual capability of intuitively altering the relative depths of points in&#xD;&#xA;a scene as one transitions between the mutiple linear perspectives.&#xD;&#xA;&#xD;&#xA;I think I am not fully understanding the explanation. &#xD;&#xA;&#xD;&#xA;If $z_s = z$ what does it mean that &quot;the cannonical depth of a point $z ∈ [0, 1] $ is linearly mapped to&#xD;&#xA;$z_s$&quot;?&#xD;&#xA;&#xD;&#xA;We have $(x, y, z) = PM_i$, which I am assuming is the orthogonal normalization of space into the classic rendering box $[-1,1]^2\times [0, 1]$.&#xD;&#xA;&#xD;&#xA;So $z$ is the depth before perspective and $z_s$ after perspective I think.&#xD;&#xA;&#xD;&#xA;What exactly is the linear mapping described in the paper? I am very lost. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39374" PostHistoryTypeId="1" PostId="13189" RevisionGUID="1fbe5a24-1e8e-432d-8505-226bd3576cda" CreationDate="2023-01-01T00:35:05.313" UserId="7462" Text="A fresh perspective confusion about a paragraph" ContentLicense="CC BY-SA 4.0" />
  <row Id="39375" PostHistoryTypeId="3" PostId="13189" RevisionGUID="1fbe5a24-1e8e-432d-8505-226bd3576cda" CreationDate="2023-01-01T00:35:05.313" UserId="7462" Text="|rendering|perspective|camera-matrix|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39376" PostHistoryTypeId="5" PostId="13187" RevisionGUID="09f21a3d-7c73-4ac9-8f3b-7655615b4d4f" CreationDate="2023-01-01T13:17:04.283" UserId="18818" Comment="Make links hearing impaired accessible, fixed typos, and rewording to remove thank you and similar." Text="I've been trying to wrap my head around this algorithm, and I need it for my drawing function. But I can't seem to understand it.&#xD;&#xA;&#xD;&#xA;The [Wikipedia page][1] gives this piece of code right at the end:&#xD;&#xA;&#xD;&#xA;```C&#xD;&#xA;plotLine(x0, y0, x1, y1)&#xD;&#xA;    dx = abs(x1 - x0)&#xD;&#xA;    sx = x0 &lt; x1 ? 1 : -1&#xD;&#xA;    dy = -abs(y1 - y0)&#xD;&#xA;    sy = y0 &lt; y1 ? 1 : -1&#xD;&#xA;    error = dx + dy&#xD;&#xA;    &#xD;&#xA;    while true&#xD;&#xA;        plot(x0, y0)&#xD;&#xA;        if x0 == x1 &amp;&amp; y0 == y1 break&#xD;&#xA;        e2 = 2 * error&#xD;&#xA;        if e2 &gt;= dy&#xD;&#xA;            if x0 == x1 break&#xD;&#xA;            error = error + dy&#xD;&#xA;            x0 = x0 + sx&#xD;&#xA;        end if&#xD;&#xA;        if e2 &lt;= dx&#xD;&#xA;            if y0 == y1 break&#xD;&#xA;            error = error + dx&#xD;&#xA;            y0 = y0 + sy&#xD;&#xA;        end if&#xD;&#xA;    end while&#xD;&#xA;```&#xD;&#xA;So it starts by getting the `x` and `y` distance between the end points.  &#xD;&#xA;It then uses `sx`/`sy` to change the computation depending on the direction.  &#xD;&#xA;But then it introduces the error value, and I can't wrap my head around how it can mix apples and oranges.&#xD;&#xA;&#xD;&#xA;I do kind of superficially understand that this value flip flops as you go along the line and determines whether the next pixel is above or below ... but I just can't understand how you can mix `x` and `y`.&#xD;&#xA;&#xD;&#xA;Secondly, I take issue with e2 and its nonchalant doubling of the error value for some reason.  &#xD;&#xA;And then the value is used and compared to `dx` and `dy`.&#xD;&#xA;&#xD;&#xA;I have researched this for a week. I found many sites showing the code, but none have had an explanation that would make me go: &quot;oh, now I understand.&quot;&#xD;&#xA;&#xD;&#xA;I'm in need of an explanation that is in simple terms without too much math notation. It's just coordinates and a line.&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="39377" PostHistoryTypeId="24" PostId="13187" RevisionGUID="09f21a3d-7c73-4ac9-8f3b-7655615b4d4f" CreationDate="2023-01-01T13:17:04.283" Comment="Proposed by 18818 approved by 13095 edit id of 607" ContentLicense="CC BY-SA 4.0" />
  <row Id="39378" PostHistoryTypeId="50" PostId="9426" RevisionGUID="3d114b9a-d6b5-4121-b766-b626056ceae1" CreationDate="2023-01-01T16:05:10.620" UserId="-1" />
  <row Id="39379" PostHistoryTypeId="5" PostId="13188" RevisionGUID="94e0f542-0024-4f3e-a1c0-430bc3e630a6" CreationDate="2023-01-02T15:46:05.553" UserId="7952" Comment="few edits to make it more readable" Text="The first thing to make note of is that the algorithm listed in the question is the integer algorithm. So no floating point math and the plotting increments by +1 or -1 in the x and y directions.&#xD;&#xA;&#xD;&#xA;The function takes for input the line starting position (x0,y0) and ending position (x1,y1). The starting position variables(x0,y0) are reused when drawing the line.&#xD;&#xA;&#xD;&#xA;Using inputs the algorithm computes the x and y increment directions. These values get held in variables sx and sy and are always either +1 or -1. They can be negative or positive depending on the line. For example we should get consistent results whether or not (x0,y0) and (x1,y1) are switched.&#xD;&#xA;&#xD;&#xA;    sx = x0 &lt; x1 ? 1 : -1; // step x left or right&#xD;&#xA;    sy = y0 &lt; y1 ? 1 : -1; // step y left or right&#xD;&#xA;&#xD;&#xA;To actually draw the line we need to determine whether to step in the x direction, the y direction or both x and y (ie diagonally). (that is why the algorithm uses two separate if statements instead of an if then else.) To step in the x direction it is simply:&#xD;&#xA;&#xD;&#xA;     x0 = x0 + sx; // move x0 in the x direction setup in sx&#xD;&#xA;     y0 = y0 + sy; // move y0 in the y direction setup in sy&#xD;&#xA;&#xD;&#xA;Our end condition happens when x0==x1 or y0==y1 or (x0,y0) == (x1,y1). This is handled in the algorithm by the &quot;if(..) then break;&quot; statements.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if x0 == x1 &amp;&amp; y0 == y1 break; // break the while true loop&#xD;&#xA;        if x0 == x1 break; // only x meets the break condition&#xD;&#xA;        if y0 == y1 break  // only y meets the break condition&#xD;&#xA;&#xD;&#xA;Finally we need to be able to decide when to step in the x direction or the y direction or both. That is where the variables e2, dx, dy, and error come in.&#xD;&#xA;&#xD;&#xA;Notice that dx is always positive ie *dx = abs(x1-x0)* and dy is always negative ie *dy = -abs(y1-y0)* ... and error starts out as the sum of a positive and negative number ie *error = dx+dy*. The algorithm adds dx(which is postive) to error when the line is plotted in the x direction, and it adds dy(which is negative) to error when it is plotted in the y direction.&#xD;&#xA;&#xD;&#xA;So how do we figure out the next step? Simple look ahead one step which is *e2=2\*error* When either x0 or y0 is greater then e2 then they have gone too far, ie they are in an &quot;error state&quot;. &#xD;&#xA;&#xD;&#xA;One way to look at this is: As the algorithm plots in the x direction error will increase in the positive direction eventually making e2 greater then dx...which will stop it from plotting in the x direction ie *if(e2&lt;=dx)* will become false. Also as the algorithm plots in the y direction error will increment in the negative direction eventually making e2 less then dy, ie *if(e2&gt;=dy)* will become false.&#xD;&#xA;&#xD;&#xA;e2 isn't being pulled out of the air, it is the calculation of the next step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So that's a pretty long description...the way I originally came to understand it was to code it up in C and then step through various lines in the debugger looking at the values until that light bulb moment happened for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="39380" PostHistoryTypeId="5" PostId="13188" RevisionGUID="13f212ea-6910-45c7-bd53-04a32b2c7261" CreationDate="2023-01-02T20:56:50.227" UserId="7952" Comment="added 687 characters in body" Text="The first thing to make note of is that the algorithm listed in the question is the integer algorithm. So no floating point math and the plotting increments by +1 or -1 in the x and y directions.&#xD;&#xA;&#xD;&#xA;The function takes for input the line starting position (x0,y0) and ending position (x1,y1). The starting position variables(x0,y0) are reused when drawing the line.&#xD;&#xA;&#xD;&#xA;Using inputs the algorithm computes the x and y increment directions. These values get held in variables sx and sy and are always either +1 or -1. They can be negative or positive depending on the line. For example we should get consistent results whether or not (x0,y0) and (x1,y1) are switched.&#xD;&#xA;&#xD;&#xA;    sx = x0 &lt; x1 ? 1 : -1; // step x left or right&#xD;&#xA;    sy = y0 &lt; y1 ? 1 : -1; // step y left or right&#xD;&#xA;&#xD;&#xA;To actually draw the line we need to determine whether to step in the x direction, the y direction or both x and y (ie diagonally). (that is why the algorithm uses two separate if statements instead of an if then else.) To step in the x direction it is simply:&#xD;&#xA;&#xD;&#xA;     x0 = x0 + sx; // move x0 in the x direction setup in sx&#xD;&#xA;     y0 = y0 + sy; // move y0 in the y direction setup in sy&#xD;&#xA;&#xD;&#xA;Our end condition happens when x0==x1 or y0==y1 or (x0,y0) == (x1,y1). This is handled in the algorithm by the &quot;if(..) then break;&quot; statements.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        if x0 == x1 &amp;&amp; y0 == y1 break; // break the while true loop&#xD;&#xA;        if x0 == x1 break; // only x meets the break condition&#xD;&#xA;        if y0 == y1 break  // only y meets the break condition&#xD;&#xA;&#xD;&#xA;Finally we need to be able to decide when to step in the x direction or the y direction or both. That is where the variables e2, dx, dy, and error come in.&#xD;&#xA;&#xD;&#xA;Notice that dx is always positive ie *dx = abs(x1-x0)* and dy is always negative ie *dy = -abs(y1-y0)* ... and error starts out as the sum of a positive and negative number ie *error = dx+dy*. The algorithm adds dx(which is postive) to error when the line is plotted in the x direction, and it adds dy(which is negative) to error when it is plotted in the y direction.&#xD;&#xA;&#xD;&#xA;    dx = abs(x1-x0);  // distance x needs to move in increments of 1&#xD;&#xA;    dy = -abs(y1-y0); // negative distance y needs to move in increments of 1&#xD;&#xA;    error = dx + dy;  // Start state for difference between dx and dy&#xD;&#xA;    e2 = error * 2;   // look ahead&#xD;&#xA;&#xD;&#xA;If for example the line is diagonal such as the line (0,0):(5,5). The value of error will be zero, and so will e2. Making both if statements true for each step. And since dx is added and dy is subtracted both if statements will remain true until x0,y0==x1,y1!&#xD;&#xA;&#xD;&#xA;dx and dy can be thought of as the numerator and denominator of the slope of a line. When dx is 3 units bigger then dy, it will increment 3 times for every 1 dy.&#xD;&#xA;&#xD;&#xA;So how do we figure out the next step? Simple look ahead one step which is *e2=2\*error* When either x0 or y0 is greater then e2 then they have gone too far, ie they are in an &quot;error state&quot;. &#xD;&#xA;&#xD;&#xA;One way to look at this is: As the algorithm plots in the x direction error will increase in the positive direction eventually making e2 greater then dx...which will stop it from plotting in the x direction ie *if(e2&lt;=dx)* will become false. Also as the algorithm plots in the y direction error will increment in the negative direction eventually making e2 less then dy, ie *if(e2&gt;=dy)* will become false.&#xD;&#xA;&#xD;&#xA;e2 isn't being pulled out of the air, it is the calculation of the next step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So that's a pretty long description...the way I originally came to understand it was to code it up in C and then step through various lines in the debugger looking at the values until that light bulb moment happened for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="39381" PostHistoryTypeId="2" PostId="13190" RevisionGUID="390978d2-b8b0-4797-bc09-8a1c1dd86dc9" CreationDate="2023-01-03T00:32:28.107" UserId="7462" Text="This is technically about PGA motors, but dual quaternions are a subalgebra of PGA so for all given purposes it's the same idea.&#xD;&#xA;&#xD;&#xA;I have an animation in gltf, specified as inverse bind pose matrices, quaternions and translations. I am turning that data into dual quaternions (motors), which gives me a mostly correct animation with some artifacts.&#xD;&#xA;&#xD;&#xA;The artifacts are caused by a sign issue on the rotations. Basically, a 3D rotation has 2 representations, the $\alpha$ rotation around axis $A$, and the $-2\pi + \alpha$ rotation around axis $-A$. i.e. you can get to the same place whether you rotate CCW by $\alpha$ or CW by $2\pi - \alpha$.&#xD;&#xA;&#xD;&#xA;The point where this causes an issue is when blending. depending of which of the 2 rotation representations you have when blending, the operation $w_1 R1 + w_2 R_2$ can yield a very similar or a very different result, for example if $R_1 = R2$ and $w_1 = w_2 = 0.5$ then we just have the same rotation, but if $R_1 = - R_2$ then we get the 0 quaternion, which is not even a rotation.&#xD;&#xA;&#xD;&#xA;This manifests as candywrapping, like in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you know that a joint is candywrapped after blending, you can fix the issue by negating one of the motors you are blending together, for example in this particular model I know joint 8 is the elbow and I can fix the candy wrapping by negating the joint:&#xD;&#xA;&#xD;&#xA;```rust&#xD;&#xA; let index = 8;&#xD;&#xA;        skin.inverse_poses[index] = -1.0 * skin.inverse_poses[index];&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I can fix the entire animation by manually inspecting the model for regions where this happens and negating one of the motors/quaternions. However this is stupidly time consuming, this is something that should be automated, there has to be a mathematical formulation that tells me when to flip the sign.&#xD;&#xA;&#xD;&#xA;At first I thought that it was just a matter of always selecting the positive scalar version of the quaternion, i.e. doing this:&#xD;&#xA;&#xD;&#xA;```rust&#xD;&#xA;            let joint = res.joints[index];&#xD;&#xA;            let m1 = anim.joint_animations[joint[0] as usize].rotations[0] * res.skin.inverse_poses[joint[0] as usize];&#xD;&#xA;            let m2 = anim.joint_animations[joint[1] as usize].rotations[0] * res.skin.inverse_poses[joint[1] as usize];&#xD;&#xA;            let m3 = anim.joint_animations[joint[2] as usize].rotations[0] * res.skin.inverse_poses[joint[2] as usize];&#xD;&#xA;            let m4 = anim.joint_animations[joint[3] as usize].rotations[0] * res.skin.inverse_poses[joint[3] as usize];&#xD;&#xA;&#xD;&#xA;            let weights = res.skin_weights[index];&#xD;&#xA;            let combined = weights[0] * m1 + weights[1] * m2 + weights[2] * m3 + weights[3] * m4;&#xD;&#xA;            if combined.s() &lt; 0.0&#xD;&#xA;            {&#xD;&#xA;                for j_anim in &amp;mut anim.joint_animations[joint[1] as usize].rotations&#xD;&#xA;                {&#xD;&#xA;                    *j_anim = -1.0 * *j_anim;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA; ```&#xD;&#xA;&#xD;&#xA;Or in english, for every set of 4 joints that should be blended together, see if the resulting motor has a negative scalar and if it does, negate the motor.&#xD;&#xA;&#xD;&#xA;This is not the correct criterion, it does fix some of the issues but not all, and it causes some issues itself.&#xD;&#xA;&#xD;&#xA;What is the correct way to identify if a set of rotations affecting a joint should be flipped? Alternatively, how do I properly extract the quaternions from the original data?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Lj7Ff.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A6ruH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39383" PostHistoryTypeId="1" PostId="13190" RevisionGUID="390978d2-b8b0-4797-bc09-8a1c1dd86dc9" CreationDate="2023-01-03T00:32:28.107" UserId="7462" Text="Double quaternion skinning artifacts" ContentLicense="CC BY-SA 4.0" />
  <row Id="39384" PostHistoryTypeId="3" PostId="13190" RevisionGUID="390978d2-b8b0-4797-bc09-8a1c1dd86dc9" CreationDate="2023-01-03T00:32:28.107" UserId="7462" Text="|computational-geometry|animation|gltf|motion|quaternions|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39385" PostHistoryTypeId="2" PostId="13191" RevisionGUID="9378ee23-7854-49fc-a866-8bf0d8907673" CreationDate="2023-01-03T11:15:36.933" UserId="7724" Text="It is possible to compute the limit surface of a subdivision surface. The limit surface puts vertices at the places where they would be when the subdivision is applied an infinite number of times. The limit position of a vertex in a Catmull-Clark subdivision surface can be computed using the following mask. Given a vertex $v$ on the control mesh with valency $n$ surrounded by edges with midpoints $m_i$ (i being the i-th edge) and faces with centers $c_i$, we can find (or project to) the limit position $p$ as:&#xD;&#xA;&#xD;&#xA;$$p = \frac{n-5}{n-3} v + \frac{4}{n(n+5)}\sum^{n-1}_{i=0}(m_i + c_i)$$&#xD;&#xA;&#xD;&#xA;This works even for irregular points and control meshes containing arbitrary valency polygons. Then given a $k$ times subdivided subdivision surfaces you can project all point to the limit to see where they would end up on the limit surface. This formula is taken from https://charlesloop.com/SGA09.pdf end of section 3.2.&#xD;&#xA;&#xD;&#xA;In the regular regions the surface is even more predictable as there the limit surface is a uniform bicubic B-spline. These splines can be directly computed and evaluated from the control net.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39387" PostHistoryTypeId="2" PostId="13192" RevisionGUID="d6c59ed3-672b-4f1c-8efe-8b7b4156aee1" CreationDate="2023-01-03T17:44:16.113" UserId="6114" Text="Nathan's answer and his in-depth blog post are just great. &#xD;&#xA;However following pictures helped me a lot to visually understand slope space.&#xD;&#xA;From Dupuy thesis (Photorealistic Surface Rendering with Microfacet Theory, 2015).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FuP8x.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39389" PostHistoryTypeId="5" PostId="12885" RevisionGUID="64370116-428d-4f18-b61c-196a64e2be11" CreationDate="2023-01-03T17:48:03.183" UserId="6114" Comment="typo" Text="It's almost never a problem of computational costs, it's a matter of how well a function works in a Monte Carlo scenario. Ie. how well it can be importance sampled. That generally leads to how well it can be inversely transformed to get an importance sampled scattering direction.&#xD;&#xA;&#xD;&#xA;With HG or some modified HG phase fnc we can nicely match Mie for anything bigger than the wavelength and looking how well it can be importance sampled it makes no sense to use Mie for common cases like those we find generally in rendering. So yep you better off with HG.&#xD;&#xA;&#xD;&#xA;Eventually some good read : &#xD;&#xA;https://opg.optica.org/ao/abstract.cfm?uri=ao-35-18-3270&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39390" PostHistoryTypeId="5" PostId="1872" RevisionGUID="94f0af1d-f48b-4738-9aed-dc70005a04d7" CreationDate="2023-01-03T19:28:43.497" UserId="5778" Comment="broken image fixed (click 'Inline' or 'Side-by-side' to see the difference); for more info, see https://git.io/JqCQN" Text="And just to add: it is called &quot;conflation&quot; artifact and this is what AntiGrain Geometry used the [compound shapes][2] rasterizer for, see:&#xD;&#xA;&#xD;&#xA; [![flash_rasterizer.png][1]][1]  &#xA;&lt;sub&gt;(source: [sourceforge.net](http://agg.sourceforge.net/antigrain.com/demo/flash_rasterizer.png))&lt;/sub&gt;  &#xA;&#xD;&#xA;&#xD;&#xA;Also, this is what NV Path Rendering claims to improve on:&#xD;&#xA;&#xD;&#xA;[An Introduction to&#xD;&#xA;NV_path_rendering][3] (p. 67) or [NV_path_rendering FAQ][4] (#29).&#xA;&#xA; [1]: https://i.stack.imgur.com/ndTTc.png&#xA; [2]: https://agg.sourceforge.net/antigrain.com/news/release_notes/v24.agdoc.html#toc0007&#xA; [3]: https://developer.download.nvidia.com/assets/gamedev/files/An_Introduction_to_NV_path_rendering.pdf&#xA; [4]: https://developer.download.nvidia.com/assets/gamedev/files/NV_path_rendering_FAQ.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="39391" PostHistoryTypeId="24" PostId="1872" RevisionGUID="94f0af1d-f48b-4738-9aed-dc70005a04d7" CreationDate="2023-01-03T19:28:43.497" Comment="Proposed by 5778 approved by 13095 edit id of 608" ContentLicense="CC BY-SA 4.0" />
  <row Id="39392" PostHistoryTypeId="5" PostId="13190" RevisionGUID="0c557391-d2cb-4190-9133-3da3f539eba9" CreationDate="2023-01-03T22:07:13.497" UserId="7462" Comment="[Edit removed during grace period]" Text="This is technically about PGA motors, but dual quaternions are a subalgebra of PGA so for all given purposes it's the same idea.&#xD;&#xA;&#xD;&#xA;I have an animation in gltf, specified as inverse bind pose matrices, quaternions and translations. I am turning that data into dual quaternions (motors), which gives me a mostly correct animation with some artifacts.&#xD;&#xA;&#xD;&#xA;The artifacts are caused by a sign issue on the rotations. Basically, a 3D rotation has 2 representations, the $\alpha$ rotation around axis $A$, and the $-2\pi + \alpha$ rotation around axis $-A$. i.e. you can get to the same place whether you rotate CCW by $\alpha$ or CW by $2\pi - \alpha$.&#xD;&#xA;&#xD;&#xA;The point where this causes an issue is when blending. depending of which of the 2 rotation representations you have when blending, the operation $w_1 R1 + w_2 R_2$ can yield a very similar or a very different result, for example if $R_1 = R2$ and $w_1 = w_2 = 0.5$ then we just have the same rotation, but if $R_1 = - R_2$ then we get the 0 quaternion, which is not even a rotation.&#xD;&#xA;&#xD;&#xA;This manifests as candywrapping, like in this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If you know that a joint is candywrapped after blending, you can fix the issue by negating one of the motors you are blending together, for example in this particular model I know joint 8 is the elbow and I can fix the candy wrapping by negating the joint:&#xD;&#xA;&#xD;&#xA;```rust&#xD;&#xA; let index = 8;&#xD;&#xA;        skin.inverse_poses[index] = -1.0 * skin.inverse_poses[index];&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I can fix the entire animation by manually inspecting the model for regions where this happens and negating one of the motors/quaternions. However this is stupidly time consuming, this is something that should be automated, there has to be a mathematical formulation that tells me when to flip the sign.&#xD;&#xA;&#xD;&#xA;At first I thought that it was just a matter of always selecting the positive scalar version of the quaternion, i.e. doing this:&#xD;&#xA;&#xD;&#xA;```rust&#xD;&#xA;            let joint = res.joints[index];&#xD;&#xA;            let m1 = anim.joint_animations[joint[0] as usize].rotations[0] * res.skin.inverse_poses[joint[0] as usize];&#xD;&#xA;            let m2 = anim.joint_animations[joint[1] as usize].rotations[0] * res.skin.inverse_poses[joint[1] as usize];&#xD;&#xA;            let m3 = anim.joint_animations[joint[2] as usize].rotations[0] * res.skin.inverse_poses[joint[2] as usize];&#xD;&#xA;            let m4 = anim.joint_animations[joint[3] as usize].rotations[0] * res.skin.inverse_poses[joint[3] as usize];&#xD;&#xA;&#xD;&#xA;            let weights = res.skin_weights[index];&#xD;&#xA;            let combined = weights[0] * m1 + weights[1] * m2 + weights[2] * m3 + weights[3] * m4;&#xD;&#xA;            if combined.s() &lt; 0.0&#xD;&#xA;            {&#xD;&#xA;                for j_anim in &amp;mut anim.joint_animations[joint[1] as usize].rotations&#xD;&#xA;                {&#xD;&#xA;                    *j_anim = -1.0 * *j_anim;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA; ```&#xD;&#xA;&#xD;&#xA;Or in english, for every set of 4 joints that should be blended together, see if the resulting motor has a negative scalar and if it does, negate the motor.&#xD;&#xA;&#xD;&#xA;This is not the correct criterion, it does fix some of the issues but not all, and it causes some issues itself.&#xD;&#xA;&#xD;&#xA;What is the correct way to identify if a set of rotations affecting a joint should be flipped? Alternatively, how do I properly extract the quaternions from the original data?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Lj7Ff.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/A6ruH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39394" PostHistoryTypeId="5" PostId="13191" RevisionGUID="3babf73b-ed76-4b10-b25d-3e35294ac10d" CreationDate="2023-01-04T08:26:29.727" UserId="7724" Comment="added 3 characters in body" Text="It is possible to compute the limit surface of a subdivision surface. The limit surface puts vertices at the places where they would be when the subdivision is applied an infinite number of times. The limit position of a vertex in a Catmull-Clark subdivision surface can be computed using the following stencil. Given a vertex $v$ on the control mesh with valency $n$ surrounded by edges with midpoints $m_i$ (i being the i-th edge) and faces with centers $c_i$, we can find (or project to) the limit position $p$ as:&#xD;&#xA;&#xD;&#xA;$$p = \frac{n-5}{n-3} v + \frac{4}{n(n+5)}\sum^{n-1}_{i=0}(m_i + c_i)$$&#xD;&#xA;&#xD;&#xA;This works even for irregular points and control meshes containing arbitrary valency polygons. Then given a $k$ times subdivided subdivision surfaces you can project all point to the limit to see where they would end up on the limit surface. This formula is taken from https://charlesloop.com/SGA09.pdf end of section 3.2.&#xD;&#xA;&#xD;&#xA;In the regular regions the surface is even more predictable as there the limit surface is a uniform bicubic B-spline. These splines can be directly computed and evaluated from the control net.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39395" PostHistoryTypeId="2" PostId="13193" RevisionGUID="2d47f733-253a-4ea3-9ddc-cd10e70e5eee" CreationDate="2023-01-06T04:03:01.973" UserId="19415" Text="In the world coordinate system, there are objects with rotation values `rx1,ry1,rz1` and position values `px1,py1,pz1`.&#xD;&#xA;&#xD;&#xA;Similarly, there is an object in the world coordinate system with rotation values `rx2,ry2,rz2` and position values `px2,py2,pz2`.&#xD;&#xA;&#xD;&#xA;What formula can be used to convert `rx1,ry1,rz1,px1,py1,pz1` to the camera coordinate system?&#xD;&#xA;&#xD;&#xA;I would like to calculate this with Python, but any answers, including mathematical statements, are welcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="39397" PostHistoryTypeId="1" PostId="13193" RevisionGUID="2d47f733-253a-4ea3-9ddc-cd10e70e5eee" CreationDate="2023-01-06T04:03:01.973" UserId="19415" Text="How to convert from world coordinates to camera coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="39398" PostHistoryTypeId="3" PostId="13193" RevisionGUID="2d47f733-253a-4ea3-9ddc-cd10e70e5eee" CreationDate="2023-01-06T04:03:01.973" UserId="19415" Text="|3d|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39399" PostHistoryTypeId="5" PostId="13193" RevisionGUID="b7388dd7-55cf-4360-a9af-945ec2eb2537" CreationDate="2023-01-06T07:20:56.133" UserId="19415" Comment="added 118 characters in body" Text="In the world coordinate system, there are objects with rotation values `rx1,ry1,rz1` and position values `px1,py1,pz1`.&#xD;&#xA;&#xD;&#xA;Similarly, there is an object in the world coordinate system with rotation values `rx2,ry2,rz2` and position values `px2,py2,pz2`.&#xD;&#xA;&#xD;&#xA;What formula can be used to convert `rx1,ry1,rz1,px1,py1,pz1` to the camera coordinate system?&#xD;&#xA;&#xD;&#xA;The up vector of the camera is the Y-axis, always oriented toward the object near the world origin.&#xD;&#xA;&#xD;&#xA;I would like to calculate this with Python, but any answers, including mathematical statements, are welcome." ContentLicense="CC BY-SA 4.0" />
  <row Id="39400" PostHistoryTypeId="5" PostId="13193" RevisionGUID="700aea89-ef62-4201-a2d8-c14a725312b6" CreationDate="2023-01-06T07:52:55.757" UserId="19415" Comment="added 192 characters in body" Text="In the world coordinate system, there are objects with rotation values `rx1,ry1,rz1` and position values `px1,py1,pz1`.&#xD;&#xA;&#xD;&#xA;Similarly, there is an object in the world coordinate system with rotation values `rx2,ry2,rz2` and position values `px2,py2,pz2`.&#xD;&#xA;&#xD;&#xA;What formula can be used to convert `rx1,ry1,rz1,px1,py1,pz1` to the camera coordinate system?&#xD;&#xA;&#xD;&#xA;The up vector of the camera is the Y-axis, always oriented toward the object near the world origin.&#xD;&#xA;&#xD;&#xA;The camera and the model are supposed to move within the range as shown in the following gif image.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I would like to calculate this with Python, but any answers, including mathematical statements, are welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EEgj9.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="39401" PostHistoryTypeId="5" PostId="13193" RevisionGUID="f84f4774-1069-47b0-832c-4175f06cee18" CreationDate="2023-01-06T08:00:11.830" UserId="19415" Comment="added 192 characters in body" Text="In the world coordinate system, there are objects with rotation values `rx1,ry1,rz1` and position values `px1,py1,pz1`.&#xD;&#xA;&#xD;&#xA;Similarly, there is a camera in the world coordinate system with rotation values `rx2,ry2,rz2` and position values `px2,py2,pz2`.&#xD;&#xA;&#xD;&#xA;What formula can be used to convert `rx1,ry1,rz1,px1,py1,pz1` to the camera coordinate system?&#xD;&#xA;&#xD;&#xA;The up vector of the camera is the Y-axis, always oriented toward the object near the world origin.&#xD;&#xA;&#xD;&#xA;The camera and the model are supposed to move within the range as shown in the following gif image.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I would like to calculate this with Python, but any answers, including mathematical statements, are welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EEgj9.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="39402" PostHistoryTypeId="2" PostId="13194" RevisionGUID="7006f4d9-4356-4227-9103-1d9dbb1f9365" CreationDate="2023-01-06T08:01:50.303" UserId="6111" Text="I don't understand how my monitor works.&#xD;&#xA;&#xD;&#xA;I am at 1920x1080 resolution which I thought was the native resolution of my monitor.&#xD;&#xA;I proceed to take a screenshot, then I open it up in a image program at 100% zoom (aseprite), which should mean that 1 pixel of the screen is 1 pixel of the image.&#xD;&#xA;The screenshot looks TWICE as big as my monitor.&#xD;&#xA;&#xD;&#xA;How is this possible?&#xD;&#xA;Is my monitor downscaling the resolution to half so that it's not actually 1920x1080?&#xD;&#xA;I am questioning this because I could see some artifacts on the rendering of images that are supposed to be pixel perfect but look asymmetrical on my screen, though when I take a screenshot and zoom in they look perfect.&#xD;&#xA;&#xD;&#xA;Here's an example:&#xD;&#xA;[![Photo of my monitor taken with phone][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The 2 vertical side black lines of the arrow are clearly taking 3 physical pixels on the left and 4 physical pixels on the right.&#xD;&#xA;&#xD;&#xA;When I take a screenshot of that exact image I get this:&#xD;&#xA;&#xD;&#xA;[![Screenshot][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FExJq.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/YdHEf.png&#xD;&#xA;&#xD;&#xA;Opening the screenshot up in an image software shows clearly how the 2 black lines are the exact same width in pixels.&#xD;&#xA;&#xD;&#xA;How can a screenshot be different than what I see on my monitor, given that I should be using the native resolution of my monitor?&#xD;&#xA;&#xD;&#xA;Is there some hidden upscaling/downscaling for some monitors that cause them to not be at their claimed native resolution?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39404" PostHistoryTypeId="1" PostId="13194" RevisionGUID="7006f4d9-4356-4227-9103-1d9dbb1f9365" CreationDate="2023-01-06T08:01:50.303" UserId="6111" Text="Why is a screenshot visually different (and in size) to my screen?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39405" PostHistoryTypeId="3" PostId="13194" RevisionGUID="7006f4d9-4356-4227-9103-1d9dbb1f9365" CreationDate="2023-01-06T08:01:50.303" UserId="6111" Text="|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39406" PostHistoryTypeId="2" PostId="13195" RevisionGUID="dbc7f7a2-e414-4830-985a-350349c783b0" CreationDate="2023-01-06T14:31:28.487" UserId="6111" Text="This is related to how pixel LEDs are laid out on an LCD monitor.&#xD;&#xA;&#xD;&#xA;[![Pixel LEDs][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;As shown in the image, for an LCD display, the RGB LEDs are arranged in that order, each one of them taking approximately 1/3 the width of a pixel.&#xD;&#xA;&#xD;&#xA;This means that for the left black line of my red arrow, we will have this sequence of LEDs (x=off):&#xD;&#xA;&#xD;&#xA;xxB xxx xxx xxx xxx Rxx .....&#xD;&#xA;&#xD;&#xA;While for the thick line on the right, they will be like:&#xD;&#xA;&#xD;&#xA;Rxx xxx xxx xxx xxx xxB&#xD;&#xA;&#xD;&#xA;This changes the visual width of the line to be 4/3 of a pixel wider for the right line (4 more x in between coloured LEDs!).&#xD;&#xA;&#xD;&#xA;So incredibly, the colour layout of an image can change its visual geometry due to how pixel colours are created.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4XbNx.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39408" PostHistoryTypeId="2" PostId="13196" RevisionGUID="45e79f14-c8b8-41be-8858-b92c80a7148d" CreationDate="2023-01-06T15:44:07.803" UserId="19420" Text="My raytracer has a point light source, it works as it should, illuminates the scene, but there is a problem, it is not visible, I would like to add glowing objects to the raytracer, for example a sphere that would look like the sun&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I need any object to be able to glow whether it's a triangle (or a line?).&#xD;&#xA;&#xD;&#xA;How to implement it?&#xD;&#xA;&#xD;&#xA;Sorry for my poor English)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XEjxp.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39410" PostHistoryTypeId="1" PostId="13196" RevisionGUID="45e79f14-c8b8-41be-8858-b92c80a7148d" CreationDate="2023-01-06T15:44:07.803" UserId="19420" Text="Glowing objects in a raytracer? How it works?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39411" PostHistoryTypeId="3" PostId="13196" RevisionGUID="45e79f14-c8b8-41be-8858-b92c80a7148d" CreationDate="2023-01-06T15:44:07.803" UserId="19420" Text="|raytracing|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39412" PostHistoryTypeId="50" PostId="12602" RevisionGUID="3f463b6a-974e-48d2-9d8c-d339af31eb1b" CreationDate="2023-01-06T20:06:10.713" UserId="-1" />
  <row Id="39414" PostHistoryTypeId="50" PostId="12609" RevisionGUID="f4c1e5cc-763b-42ae-8247-c571bba8f91b" CreationDate="2023-01-07T04:03:45.540" UserId="-1" />
  <row Id="39415" PostHistoryTypeId="2" PostId="13197" RevisionGUID="b2221478-0bcc-4b08-b98c-35799713654b" CreationDate="2023-01-07T13:48:55.557" UserId="7952" Text="Generally the *values* $\vec{rx1},\vec{ry1},\vec{rz1}$ are themselves vectors. Each with an $(x,y,z,w)$ take special note of the $w$ value. The position values would also have $(x,y,z,w)$ values. The $w$ value for the vectors would be $0$ and it would be $1$ for the position. Together they make up an affine transformation which is a 4x4 matrix. &#xD;&#xA;&#xD;&#xA;It sounds like you have the camera matrix already, sometimes called the view matrix. After being set up it generally transforms objects from world space into camera space. Affine transformations are invertible, once inverted they transform in the *opposite* direction. For example a 4x4 affine transformation matrix that transforms from world space to camera space can be inverted to transform from camera space to world space.&#xD;&#xA;&#xD;&#xA;So the transformation formula is simply:&#xD;&#xA;&#xD;&#xA;    worldtocamera = inverse(cameratoworld)&#xD;&#xA;&#xD;&#xA;Also, this transformation generalizes very nicely. For example the transformation from model to world combined with world to camera is:&#xD;&#xA;&#xD;&#xA;    modeltocamera = modeltoworld * worldtocamera&#xD;&#xA;&#xD;&#xA;And the reverse is again simply:&#xD;&#xA;&#xD;&#xA;    cameratomodel = inverse(modeltocamera)&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    " ContentLicense="CC BY-SA 4.0" />
  <row Id="39417" PostHistoryTypeId="2" PostId="13198" RevisionGUID="1d33d30d-060f-4cd1-8ecc-fecb3a070a94" CreationDate="2023-01-08T02:57:01.940" UserId="19424" Text="Context: I am attempting to implement Trowbridge–Reitz (GGX) based on [Microfacet Models for Refraction through Rough Surfaces][1] in a pathtracer. I use numerical integration to check if the pdfs integrate to 1 (I convert solid angle to spherical coordinates using the jacobian and integrate that):&#xD;&#xA;&#xD;&#xA;It is stated that the probability of generating a given microfacet normal for GGX is [![p_m function][2]][2]&#xD;&#xA;&#xD;&#xA;Where m is the microfacet normal and n is the macrofacet normal (which I set to (0, 0, 1) for the sake of testing). Note that || on the dot product isn't needed since D(m) &lt; 0 if the dot product is below zero due to the positive characteristic function (X+) on all the given microfacet distributions including GGX (see below).&#xD;&#xA;[![GGX microfacet distribution][3]][3]&#xD;&#xA;&#xD;&#xA;As expected when I integrate p_m(m) it indeed does integrate to 1 as you would expect.&#xD;&#xA;[![integration of p_m = 1][4]][4]&#xD;&#xA;&#xD;&#xA;The problems arise when I try to integrate the pdf of the sampled direction (o). Which I should be able to do by using the jacobian.&#xD;&#xA;&#xD;&#xA;[![p_o = p_m(m) * || omega_w_h / omega_w_o ||][5]][5]&#xD;&#xA;&#xD;&#xA;The paper states that for ideal reflection the jacobian is 1/(4|o dot h|)&#xD;&#xA;&#xD;&#xA;[![ideal reflection section of paper][6]][6]&#xD;&#xA;&#xD;&#xA;So I reasoned that this would be true:&#xD;&#xA;[![integral of p_o can be done by modifying integral above with jacobian][7]][7]&#xD;&#xA;&#xD;&#xA;The reason why I'm assuming the first equality is true is due to:&#xD;&#xA;&#xD;&#xA;&quot;Let us assume that for any given incident&#xD;&#xA;and outgoing directions, there is at most one microsurface&#xD;&#xA;normal that scatters energy from i to o, and that we can compute that normal as h(i, o), which we call the half-direction&quot;. As well as the equation above (38).&#xD;&#xA;&#xD;&#xA;I would like to point out that I am only doing ideal reflection, so no refraction.&#xD;&#xA;&#xD;&#xA;The problem is when I attempt to integrate the expression in the image above. It does not integrate to 1 or a consistent value. &#xD;&#xA;&#xD;&#xA;To make the distribution integrate to 1 I have to get rid of the positive characteristic function in D(m). Which results in p_m(m) integrating to 0 but p_o(o) integrating to 1.&#xD;&#xA;&#xD;&#xA;Why does removing the positive characteristic function have this result and why doesn't p_o(o) integrate to 1 when it remains?&#xD;&#xA;&#xD;&#xA;Also as a side note, I find that using &#xD;&#xA;&#xD;&#xA;[![reflection formula in paper][8]][8]&#xD;&#xA;&#xD;&#xA;to calculate o given h and i leads to sampled distribution not matching up with the pdf (I use a chi-squared test of the binned values to verify this) compared to not using the absolute value (which matches up to most formulas online). Note that for my testing  I generate i in the top hemisphere and pointing away from the surface.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/qAQD6.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4YPda.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Sl3fg.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/Jnsjm.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/4Rxda.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/XoPha.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/YzMm6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39419" PostHistoryTypeId="1" PostId="13198" RevisionGUID="1d33d30d-060f-4cd1-8ecc-fecb3a070a94" CreationDate="2023-01-08T02:57:01.940" UserId="19424" Text="Why do I need to remove the positive charactaristic function for the pdf of the outgoing direction to integrate to 1 with GGX?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39420" PostHistoryTypeId="3" PostId="13198" RevisionGUID="1d33d30d-060f-4cd1-8ecc-fecb3a070a94" CreationDate="2023-01-08T02:57:01.940" UserId="19424" Text="|pathtracing|brdf|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39421" PostHistoryTypeId="2" PostId="13199" RevisionGUID="7267cd96-963f-43cd-9f54-25168e2d17e0" CreationDate="2023-01-09T09:54:48.950" UserId="13273" Text="I've a lots of objects, which have the same geometry. Right now I am using instanced rendering to render these objects. This is working very well. But I am trying to increase the performance of the program.&#xD;&#xA;&#xD;&#xA;I only want to render objects, which are in front of my camera. So I simply added a compute shader, which makes an intersection test of camera frustum and the object (position and bounding radius). Afterwards I only want to render (instanced) the objects, which are visible by indirect rendering.&#xD;&#xA;&#xD;&#xA;**The setup**&#xD;&#xA;&#xD;&#xA;I have three SSBOs:&#xD;&#xA;&#xD;&#xA; 1. List of objects (Position, radius). This list is created once and will not change.&#xD;&#xA; 2. List of visible indices (each object, which is inside the view frustum will add its index (from list 1) to this list. The position to add the index is given by SSBO three&#xD;&#xA; 3. One integer (atomic counter). While the visibility test is executing, each visible object executes an &quot;atomicAdd(+1)&quot; on this integer to receive the position to store its index (list 1 index) to position in list 2.&#xD;&#xA;&#xD;&#xA;So far so good. But how can I execute a draw call which is instanced and indirect? I don't want to load the third SSBO to CPU to execute an instanced draw call with its number. (I am trying to avoid GPU-&gt;CPU-&gt;GPU).&#xD;&#xA;&#xD;&#xA;Alternatively, I can make an instanced draw call of all objects and read the atomic counter in SSBO three. When the gl_InstanceID is less than this value I can render the object. Else I discard the object within the tessellation control stage. This way is very slow, because each object has a lot of vertices which will be executed during the vertex and the tessellation control stage which is completely useless.&#xD;&#xA;&#xD;&#xA;**My question**&#xD;&#xA;&#xD;&#xA;How to execute an instanced indirect draw call? (Element draw call) Is there a command for that?&#xD;&#xA;&#xD;&#xA;If so, How do I need to store my third SSBO, so that the number of the atomic counter many objects will be drawn?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39423" PostHistoryTypeId="1" PostId="13199" RevisionGUID="7267cd96-963f-43cd-9f54-25168e2d17e0" CreationDate="2023-01-09T09:54:48.950" UserId="13273" Text="How to instanced and indirect render geometry [OpenGL]" ContentLicense="CC BY-SA 4.0" />
  <row Id="39424" PostHistoryTypeId="3" PostId="13199" RevisionGUID="7267cd96-963f-43cd-9f54-25168e2d17e0" CreationDate="2023-01-09T09:54:48.950" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39425" PostHistoryTypeId="2" PostId="13200" RevisionGUID="54b65c0e-1172-4390-9bfa-ab1e0341798e" CreationDate="2023-01-09T20:56:43.443" UserId="2654" Text="The final mechanism you are wanting to employ is [indirect rendering][1]: the ability of the GPU to read the contents of one (or more) rendering commands directly from GPU memory. Your compute shader therefore needs to conform to the requirements of whatever indirect rendering mechanism you're trying to employ.&#xD;&#xA;&#xD;&#xA;That is, &quot;List of visible indices&quot; is *not* the primary information your CS needs to generate. The GPU doesn't know what a &quot;visible index&quot; into your &quot;List of objects&quot; is. What the GPU needs are two things:&#xD;&#xA;&#xD;&#xA;1. One (or more) rendering commands, as formatted for the indirect rendering function you intend to call.&#xD;&#xA;2. A way to access the per-model data needed for each of those rendering commands.&#xD;&#xA;&#xD;&#xA;So you're rendering a bunch of instances: copies of the same model with different per-model parameters. So that means you need to use one of two mechanisms for your shader to access these per-model parameters. You can bind your &quot;List of objects&quot; as [instanced vertex arrays][2]. Or your [vertex shader can access `gl_InstanceID`][3] and use that to access an SSBO containing the &quot;List of objects&quot;.&#xD;&#xA;&#xD;&#xA;You established that you don't want &quot;List of objects&quot; to change. That you're not going to add or remove things from this list. OK, but that doesn't mean your CS can't write that data elsewhere.&#xD;&#xA;&#xD;&#xA;Instead of writing which indices in that list are visible, you should instead write the per-model data to another SSBO if it is visible. So you have your original &quot;List of objects&quot; SSBO, and a second SSBO containing the visible object data. This way, the visible list can be used directly by your instanced rendering operation without having to fetch an index to use to fetch the actual data.&#xD;&#xA;&#xD;&#xA;And this brings us to the atomic counter. This counter needs to have its backing memory store be the number of instances for the instanced rendering command. The rest of the command can stay the same (number of vertices per model, etc). You just need to reset these bytes to 0 before starting to compute a new set of objects.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Indirect_Rendering&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Instanced_Array&#xD;&#xA;  [3]: https://www.khronos.org/opengl/wiki/Vertex_Rendering#Instancing" ContentLicense="CC BY-SA 4.0" />
  <row Id="39427" PostHistoryTypeId="2" PostId="13201" RevisionGUID="4be3ca23-2400-4ab6-ba42-69241966aa3c" CreationDate="2023-01-09T21:06:45.197" UserId="19431" Text="I was working through https://thebookofshaders.com/05/ when I came across some unintuitive behaviour of `smoothstep`.  I wanted to understand it better so I replaced the following line of code:&#xD;&#xA;&#xD;&#xA;    return smoothstep(0.02, 0.0, abs(st.y - st.x));&#xD;&#xA;&#xD;&#xA;With all arguments as float literals:&#xD;&#xA;&#xD;&#xA;    return smoothstep(0.02, 0.0, 0.0);&#xD;&#xA;&#xD;&#xA;I was expecting `smoothstep` to return 1.0 but instead it seems to always return 0.0 regardless of the value of the third argument.  If instead of that you use a float variable:&#xD;&#xA;&#xD;&#xA;    float temp = 0.0;&#xD;&#xA;    return smoothstep(0.02, 0.0, temp);&#xD;&#xA;&#xD;&#xA;It works as expected and returns 1.0.  Why is this?  I assume this is documented somewhere though it's not obvious what to search for.&#xD;&#xA;&#xD;&#xA;Minimal, Reproducible Example:&#xD;&#xA;&#xD;&#xA;```GLSL&#xD;&#xA;#ifdef GL_ES&#xD;&#xA;precision mediump float;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    float diff = 0.0;&#xD;&#xA;    float green = smoothstep(0.2, 0.0, diff);&#xD;&#xA;    // Won't result in green if uncommented&#xD;&#xA;    // green = smoothstep(0.2, 0.0, 0.0);&#xD;&#xA;&#xD;&#xA;	gl_FragColor = vec4(0.0, green, 0.0, 1.0);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="39429" PostHistoryTypeId="1" PostId="13201" RevisionGUID="4be3ca23-2400-4ab6-ba42-69241966aa3c" CreationDate="2023-01-09T21:06:45.197" UserId="19431" Text="Why does GLSL smoothstep returns 0 when all parameters are literal floats?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39430" PostHistoryTypeId="3" PostId="13201" RevisionGUID="4be3ca23-2400-4ab6-ba42-69241966aa3c" CreationDate="2023-01-09T21:06:45.197" UserId="19431" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39431" PostHistoryTypeId="33" PostId="10909" RevisionGUID="b3381816-0758-43ff-89c1-6232840ce956" CreationDate="2023-01-09T21:07:47.530" UserId="19431" Comment="81" />
  <row Id="39432" PostHistoryTypeId="2" PostId="13202" RevisionGUID="1bf2c03d-80d8-494e-bd0e-9334de348406" CreationDate="2023-01-10T01:18:46.630" UserId="2654" Text="Undefined behavior is undefined. [`smoothstep` requires that the first argument is less than the second.][1] If that is not the case, undefined behavior results.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="39434" PostHistoryTypeId="2" PostId="13203" RevisionGUID="d7c33635-2e37-48f4-9a32-30ace34baff5" CreationDate="2023-01-10T04:44:41.593" UserId="2654" Text="&gt; However, Hermite interpolation it links to is different from Cubic Hermite spline interpolation; they're two different articles.&#xD;&#xA;&#xD;&#xA;These are nested subjects. That is, &quot;Cubic Hermit interpolation&quot; is a specific kind of &quot;Hermite interpolation&quot;, just as a polygon is a specific kind of polytope.&#xD;&#xA;&#xD;&#xA;Hermite interpolation is itself a particular scheme for doing polynomial interpolation. And polynomial interpolation is the construction of a polynomial (of the lowest possible degree) that passes through all of a given set of points in a field.&#xD;&#xA;&#xD;&#xA;How this maps to `smoothstep` is as follows. For a given pair of start/end values, `smoothstep` defines a function `f(X)`, where X is the given value. If we plot `Y = f(X)` on a graph, we get a function whose Y range is [0, 1] and its X range is [-inf, inf].&#xD;&#xA;&#xD;&#xA;Now, when X is less than the start value, Y is always 0. When X is greater than the end value, Y is always one. When X is between those two values, it varies from 0 towards the start and 1 towards the end.&#xD;&#xA;&#xD;&#xA;What that means is that we have 2 points in 2D space: (start, 0) and (end, 1). If we presume that start is 0 and end is 1 (we can linearly rescale the X value to map [start, end] to the [0, 1] range), then our points are (0, 0) and (1, 1).&#xD;&#xA;&#xD;&#xA;Given this, we can perform Hermite interpolation between those two points. However, cubic Hermite interpolation requires 4 points: two points in space that act as the end points the curve must match and two first-derivatives which the curve must match at those points.&#xD;&#xA;&#xD;&#xA;The first-derivatives are *implied* here by the nature of the smoothstep function. That is, the derivatives are chosen to be &quot;smooth&quot;, relative to the flat parts of the function (ie: outside the X range of [0, 1]).&#xD;&#xA;&#xD;&#xA;The derivatives can be defined in terms of 2D vectors that are tangent to the curve at those points, flowing in the direction of the curve from start to end. Since the values less than 0 are going to be a flat value of 0, and the values greater than 1 will have a flat value of 1, it makes sense that the tangents are also flat. So the two tangents are both (1, 0).&#xD;&#xA;&#xD;&#xA;So our 4 Hermite interpolation positions are:&#xD;&#xA;&#xD;&#xA;| 0th Derivative | 1st Derivative |&#xD;&#xA;| -------------- | -------------- |&#xD;&#xA;|    (0, 0)      |     (1, 0)     |&#xD;&#xA;|    (1, 1)      |     (1, 0)    |&#xD;&#xA;&#xD;&#xA;The rest is just plugging those numbers into the [cubic Hermite interpolation formula][1] and reducing the result. $\boldsymbol{p}_0$ and $\boldsymbol{p}_1$ are the start/end points, and $\boldsymbol{k}_0$ &amp; $\boldsymbol{k}_1$ are the two tangents:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\boldsymbol{f}(t) = \left(2t^3 - 3t^2 + 1\right) \boldsymbol{p}_0 + \left(t^3 - 2t^2 + t\right) \boldsymbol{m}_0 + \left(-2t^3 + 3t^2\right) \boldsymbol{p}_1 + \left(t^3 - t^2\right) \boldsymbol{m}_1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The X and Y components are:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f(t)_x = \left(2t^3 - 3t^2 + 1\right) p_{0x} + \left(t^3 - 2t^2 + t\right) m_{0x} + \left(-2t^3 + 3t^2\right) p_{1x} + \left(t^3 - t^2\right) m_{1x}\\&#xD;&#xA;f(t)_y = \left(2t^3 - 3t^2 + 1\right) p_{0y} + \left(t^3 - 2t^2 + t\right) m_{0y} + \left(-2t^3 + 3t^2\right) p_{1y} + \left(t^3 - t^2\right) m_{1y}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If you insert the zeros and ones, then you get things reduced to:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;f(t)_x &amp;=&amp; (t^3 - 2t^2 + t) + (-2t^3 + 3t^2) + (t^3 - t^2)\\&#xD;&#xA;&amp;=&amp; (t^3 - 2t^3 + t^3) + (-2t^2 + 3t^2 - t^2) + t\\&#xD;&#xA;&amp;=&amp; t\\&#xD;&#xA;f(t)_y &amp;=&amp; -2t^3 + 3t^2&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;We're not actually looking for $f(t)$ however; we're looking for our function f(x) that yields Y. Because $t$ and $f(t)_x$ are the same however, that means $f(t)_y$ is just the $f(x)$ that we're looking for.&#xD;&#xA;&#xD;&#xA;Does $-2x^3 + 3x^2$ look familiar? It's just a different form of `t * t * (3.0 - 2.0 * t)`. Which is [what `smoothstep` returns][2] when `t` is between 0 and 1.&#xD;&#xA;&#xD;&#xA;QED&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Interpolation_on_a_single_interval&#xD;&#xA;  [2]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="39436" PostHistoryTypeId="5" PostId="13199" RevisionGUID="70e1521e-b0cb-4e53-a632-87473d4e19f5" CreationDate="2023-01-10T10:43:48.390" UserId="13273" Comment="added 4439 characters in body" Text="I've a lots of objects, which have the same geometry. Right now I am using instanced rendering to render these objects. This is working very well. But I am trying to increase the performance of the program.&#xD;&#xA;&#xD;&#xA;I only want to render objects, which are in front of my camera. So I simply added a compute shader, which makes an intersection test of camera frustum and the object (position and bounding radius). Afterwards I only want to render (instanced) the objects, which are visible by indirect rendering.&#xD;&#xA;&#xD;&#xA;**The setup**&#xD;&#xA;&#xD;&#xA;I have three SSBOs:&#xD;&#xA;&#xD;&#xA; 1. List of objects (Position, radius). This list is created once and will not change.&#xD;&#xA; 2. List of visible indices (each object, which is inside the view frustum will add its index (from list 1) to this list. The position to add the index is given by SSBO three&#xD;&#xA; 3. One integer (atomic counter). While the visibility test is executing, each visible object executes an &quot;atomicAdd(+1)&quot; on this integer to receive the position to store its index (list 1 index) to position in list 2.&#xD;&#xA;&#xD;&#xA;So far so good. But how can I execute a draw call which is instanced and indirect? I don't want to load the third SSBO to CPU to execute an instanced draw call with its number. (I am trying to avoid GPU-&gt;CPU-&gt;GPU).&#xD;&#xA;&#xD;&#xA;Alternatively, I can make an instanced draw call of all objects and read the atomic counter in SSBO three. When the gl_InstanceID is less than this value I can render the object. Else I discard the object within the tessellation control stage. This way is very slow, because each object has a lot of vertices which will be executed during the vertex and the tessellation control stage which is completely useless.&#xD;&#xA;&#xD;&#xA;**My question**&#xD;&#xA;&#xD;&#xA;How to execute an instanced indirect draw call? (Element draw call) Is there a command for that?&#xD;&#xA;&#xD;&#xA;If so, How do I need to store my third SSBO, so that the number of the atomic counter many objects will be drawn?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;It seems like that the idea of the three SSBOs are not well understood. So I'll try to explain it in more detail:&#xD;&#xA;&#xD;&#xA;The first SSBO stores the information of all objects (position, radius). These objects will not move or be changed at all.&#xD;&#xA;&#xD;&#xA;The second SSBO will be filled by the compute shader. (before starting the compute shader this list will be cleared.) The length of this list is the number of all objects (which have the same geometry). The compute shader will test, which of the objects in the first SSBO is in front of the camera. And stores the index of the first SSBO with help of an atomic counter (SSBO three) separately in the second list, in case it is visible.&#xD;&#xA;&#xD;&#xA;The third SSBO (the atomic counter) will be cleared before the compute shader starts. When the compute shader has finished its work, this counter gives me the number of objects which are visible.&#xD;&#xA;&#xD;&#xA;Right now I can choose two ways to only render the visible objects:&#xD;&#xA;&#xD;&#xA;**1: (the first way I can render)**&#xD;&#xA;&#xD;&#xA;Instance rendering all objects (visible and invisible). In the vertex shader stage check of the `gl_InstanceID` is less than the value in SSBO three (the atomic counter). In case it is less than the value, the object can be rendered by reading the second SSBO at index [`gl_InstanceID`] to get the information of which object is this vertex belonging to. Then read the objects parameters from the first SSBO at index [value of SSBO 2].&#xD;&#xA;In case the `gl_InstanceID` is equal or larger than the atomic counter from SSBO three, this object do NOT need to be rendered =&gt; discard this object. &#xD;&#xA;&#xD;&#xA;The rendering program of the objects have the following stages: Vertex-, tessellation (control- and evaluation-) and fragment- shader.&#xD;&#xA;The tessellation stage adds geometry detail depending on the distance to the camera. In case this object should be discarded (not visible) the `gl_TessLevelOuter` and `gl_TessLevelInner` values will be set to 0. So the this face will be discarded.&#xD;&#xA;&#xD;&#xA;**2: (the second way I can render)**&#xD;&#xA;&#xD;&#xA;Alternatively to the first way, I can load the information from the atomic counter (SSBO three) to only instance render the correct number of objects. BUT: here I have to load the information to CPU. So: GPU-&gt;CPU-&gt;GPU communication.&#xD;&#xA;&#xD;&#xA;When rending this way, the tessellation control shader does NOT need to discard anything, because only the visible objects will be rendered. The rest of the shader program code is the same as in **the first way to render**.&#xD;&#xA;&#xD;&#xA;**Performance**&#xD;&#xA;&#xD;&#xA;The first way to render does not need to load the third SSBO from GPU to CPU. So the communication (GPU-&gt;CPU-&gt;GPU) is NOT used. This is a performance boost. BUT: The vertex and tessellation control stages are executed way more often than in the second way to render. The vertex shader stage needs to load the atomic counter SSBO value to check if this vertex is relevant which might be causing branching. These are performance losses.&#xD;&#xA;&#xD;&#xA;The second way to render need to load the third SSBO from GPU to CPU. So the communication (GPU-&gt;CPU-&gt;GPU) is used, which is a performance loss. BUT: the vertex and the tessellation control stages are executed ONLY for those vertices / faces, which belong to objects, which are visible. Therefor this is a performance boost.&#xD;&#xA;&#xD;&#xA;**Conclusion**&#xD;&#xA;&#xD;&#xA;Both ways have performance positive and negative characteristics. In case the geometry of the objects which will be rendered is complex (high amount of vertices / faces) the performance of **the first way to render** will drop more and more. &#xD;&#xA;&#xD;&#xA;**The optimal way to render**&#xD;&#xA;&#xD;&#xA;When analyzing the two ways to render, this **third way to render** only has the positive performance effects, without having negative performance effects. So I am trying to do this:&#xD;&#xA;&#xD;&#xA;Indirect instance render the objects (SSBO three times). The shader program does not need to be changed. No Vertex / tessellation control of objects outside the frustum (invisible objects) will be executed. No check is required, if an objects is visible during the render stages.&#xD;&#xA;&#xD;&#xA;BUT: I don't know if this is possible... I would like to indirect execute the `glDrawElementsInstanced` command (SSBO three times). This is the only thing which stops me right now.&#xD;&#xA;Which command can I use, to achieve this indirect instanced rendering? And how (format) do I need to fill the third SSBO which will be bound later as `GL_DRAW_INDIRECT_BUFFER`? And yes, all objects do have the same geometry." ContentLicense="CC BY-SA 4.0" />
  <row Id="39439" PostHistoryTypeId="5" PostId="1551" RevisionGUID="2c84588e-6878-4386-8c4b-8eb15445bc3a" CreationDate="2023-01-10T13:29:13.017" UserId="209" Comment="three -&gt; four decades" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over four decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  A problem with palette textures is that the compression rates for the achieved quality is generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2bpp ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 322 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 8 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4bpp, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This paper also included a compression algorithm but, for our purposes, we are mainly interested in the resulting compressed data and of the decompression process.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4bpp RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses blocks of either RGB or RGB+1bit Alpha to 4bpp. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts may go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4bpp RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 bpp RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4bpp produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2bpp variant has, naturally, higher error than the 4bpp (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4bpp ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of bpp. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="39440" PostHistoryTypeId="4" PostId="13201" RevisionGUID="49d72efc-cacb-4e14-a3f3-9d3427c336f8" CreationDate="2023-01-10T19:30:35.223" UserId="19431" Comment="Minor edit to title" Text="Why does GLSL smoothstep return 0 when all parameters are literal floats?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39445" PostHistoryTypeId="2" PostId="13205" RevisionGUID="498eec4e-0169-41e1-b4e3-94b2252c4bb2" CreationDate="2023-01-10T21:31:56.057" UserId="6114" Text="Looks like the boundary of the integration change to positive m.n and so you drop the heaviside fnc to reflect that. Actually a sample for m.n&lt;0 is not a valid sample, you ain't taking its value at all but just discard it.. meaning in code it's an if() before the actual sampling routine.&#xD;&#xA;&#xD;&#xA;The 2|i.m|m-i is actually 2(i.m)m-i (Walter is writing it like that in ie. Notes on the Ward BRDF)." ContentLicense="CC BY-SA 4.0" />
  <row Id="39447" PostHistoryTypeId="2" PostId="13206" RevisionGUID="979ea51b-b758-4c94-8a3d-2250ef910d64" CreationDate="2023-01-11T08:21:26.957" UserId="19438" Text="Is there any specific difference from normal aliasing and specifically **texture aliasing?**&#xD;&#xA;&#xD;&#xA;Also, is there any specific data structure which can be used to avoid aliasing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39449" PostHistoryTypeId="1" PostId="13206" RevisionGUID="979ea51b-b758-4c94-8a3d-2250ef910d64" CreationDate="2023-01-11T08:21:26.957" UserId="19438" Text="What is texture aliasing and is there any specific &quot;data-structure&quot; to avoid it" ContentLicense="CC BY-SA 4.0" />
  <row Id="39450" PostHistoryTypeId="3" PostId="13206" RevisionGUID="979ea51b-b758-4c94-8a3d-2250ef910d64" CreationDate="2023-01-11T08:21:26.957" UserId="19438" Text="|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39451" PostHistoryTypeId="2" PostId="13207" RevisionGUID="f69bce37-6394-47d0-8045-1d06b9ce6bb3" CreationDate="2023-01-11T08:51:53.740" UserId="209" Text="What do you mean by &quot;normal&quot; aliasing?  Aliasing is the result of under-sampling: i.e being given a signal with a high frequency (temporal and/or spatial) that is being sampled too infrequently (it needs to be sampled at a rate exceeding 2x its maximum frequency OR band-limited/pre-filtered until its max frequency is &lt; 1/2 the sampling rate).&#xD;&#xA;&#xD;&#xA;With texture data, *the* common pre-filtering approach is to use MIP maps (see [Lance Williams' &quot;Pyramidal Parametrics&quot;][1]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/800059.801126" ContentLicense="CC BY-SA 4.0" />
  <row Id="39453" PostHistoryTypeId="2" PostId="13208" RevisionGUID="40df4065-0ba0-4822-acaf-c1baa1ca7632" CreationDate="2023-01-11T14:23:56.983" UserId="10096" Text="A Hermite cubic spline interpolates values at 2 points and the derivatives at those points. To be exact, let us have the point $p_0, p_1$ and the derivatives (tangents) at those $d_0, d_1$. Then we want a cubic polynomial $p(t) = a_0 + a_1 t + a_2 t^2 + a_3 t^3$ which interpolates the points and derivatives:&#xD;&#xA;$$p(0) = p_0,\,\, p(1) = p_1,\,\, p'(0) = d_0,\,\, p'(1) = d_1.$$&#xD;&#xA;We can take the derivative with respect to $t$ in order to get $p'(t) = a_1 + 2a_2 t + 3a_3 t^2$. We can compute two of the coefficients easily: $p(0) = a_0 = p_0$ and $p'(0) = a_1 = d_0$. For the remaining two equations we have&#xD;&#xA;$$p(1) = p_0 + d_0 + a_2 + a_3 = p_1,\quad p'(1) = d_0 + 2a_2 + 3a_3 = d_1.$$&#xD;&#xA;Solving the system we get&#xD;&#xA;$$a_3 = 2(p_0-p_1) + d_0 + d_1, \quad a_2 = 3(p_1 - p_0)-2d_0 - d_1.$$&#xD;&#xA;You can then rewrite the solution using the following system&#xD;&#xA;$$p(t) = \begin{bmatrix} 1 &amp; t &amp; t^2 &amp; t^3 \end{bmatrix} \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;-3 &amp; 3 &amp; -2 &amp; -1 \\&#xD;&#xA;2&amp; -2 &amp; 1 &amp; 1\end{bmatrix} \begin{bmatrix} p_0 \\ p_1 \\ d_0 \\ d_1 \end{bmatrix}.$$&#xD;&#xA;If you perform the multiplication with the matrix first, then you would get the Hermite basis functions:&#xD;&#xA;$$p(t) = (1-3t^2+2t^3)p_0 + (3t^2-2t^3)p_1 + (t-2t^2+t^3)d_0 + (t^3-t^2)d_1.$$&#xD;&#xA;You can now identify the basis function in front of $p_1$ with the smoothstep function, and the basis function in front of $p_0$ is one minus smoothstep. If you were to additionally set $d_0=d_1=0$, then it turns out that this is the only function you need. **Thus when you do $p(t) = (1-S(t)) p_0 + S(t) p_1$ you are performing cubic spline Hermite interpolation with derivatives set to zero.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="39455" PostHistoryTypeId="5" PostId="13208" RevisionGUID="b6611738-b884-4a59-839f-7697d907034d" CreationDate="2023-01-11T14:47:46.977" UserId="10096" Comment="deleted 2 characters in body" Text="A Hermite cubic spline interpolates values at 2 points and the derivatives at those points. To be exact, let us have the point $p_0, p_1$ and the derivatives (tangents) at those $d_0, d_1$. Then we want a cubic polynomial $p(t) = a_0 + a_1 t + a_2 t^2 + a_3 t^3$ which interpolates the points and derivatives:&#xD;&#xA;$$p(0) = p_0,\,\, p(1) = p_1,\,\, p'(0) = d_0,\,\, p'(1) = d_1.$$&#xD;&#xA;We can take the derivative with respect to $t$ in order to get $p'(t) = a_1 + 2a_2 t + 3a_3 t^2$. We can compute two of the coefficients easily: $p(0) = a_0 = p_0$ and $p'(0) = a_1 = d_0$. For the remaining two equations we have&#xD;&#xA;$$p(1) = p_0 + d_0 + a_2 + a_3 = p_1,\quad p'(1) = d_0 + 2a_2 + 3a_3 = d_1.$$&#xD;&#xA;Solving the system we get&#xD;&#xA;$$a_3 = 2(p_0-p_1) + d_0 + d_1, \quad a_2 = 3(p_1 - p_0)-2d_0 - d_1.$$&#xD;&#xA;You can then rewrite the solution using the following system&#xD;&#xA;$$p(t) = \begin{bmatrix} 1 &amp; t &amp; t^2 &amp; t^3 \end{bmatrix} \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;-3 &amp; 3 &amp; -2 &amp; -1 \\&#xD;&#xA;2&amp; -2 &amp; 1 &amp; 1\end{bmatrix} \begin{bmatrix} p_0 \\ p_1 \\ d_0 \\ d_1 \end{bmatrix}.$$&#xD;&#xA;If you perform the vector-matrix multiplication first, then you would get the Hermite basis functions:&#xD;&#xA;$$p(t) = (1-3t^2+2t^3)p_0 + (3t^2-2t^3)p_1 + (t-2t^2+t^3)d_0 + (t^3-t^2)d_1.$$&#xD;&#xA;You can now identify the basis function in front of $p_1$ with the smoothstep function, and the basis function in front of $p_0$ is one minus smoothstep. If you were to additionally set $d_0=d_1=0$, then it turns out that this is the only function you need. **Thus when you do $p(t) = (1-S(t)) p_0 + S(t) p_1$ you are performing cubic spline Hermite interpolation with derivatives set to zero.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="39456" PostHistoryTypeId="2" PostId="13209" RevisionGUID="49812d73-d4cb-422a-ad25-571289383e1f" CreationDate="2023-01-12T07:58:32.530" UserId="15619" Text="Is there a common approach using SSAO for blended objects?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39458" PostHistoryTypeId="1" PostId="13209" RevisionGUID="49812d73-d4cb-422a-ad25-571289383e1f" CreationDate="2023-01-12T07:58:32.530" UserId="15619" Text="Using SSAO For Blended Objects" ContentLicense="CC BY-SA 4.0" />
  <row Id="39459" PostHistoryTypeId="3" PostId="13209" RevisionGUID="49812d73-d4cb-422a-ad25-571289383e1f" CreationDate="2023-01-12T07:58:32.530" UserId="15619" Text="|real-time|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39460" PostHistoryTypeId="6" PostId="13209" RevisionGUID="afe1c2f4-4e3e-44bb-be61-a39509741628" CreationDate="2023-01-12T07:59:05.157" UserId="15619" Comment="edited tags" Text="|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39461" PostHistoryTypeId="5" PostId="13209" RevisionGUID="921b599f-abdb-4aa3-b3a5-c25652272d2e" CreationDate="2023-01-12T08:00:02.093" UserId="15619" Comment="added 31 characters in body" Text="Is there a common approach using SSAO for blended objects rendered with forward renderer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39462" PostHistoryTypeId="5" PostId="13209" RevisionGUID="d8e0e4c3-c39a-4754-9b1d-53420bf21acb" CreationDate="2023-01-12T08:00:49.303" UserId="15619" Comment="deleted 9 characters in body" Text="Is there a common approach using SSAO with forward renderer for blended objects?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39463" PostHistoryTypeId="5" PostId="13209" RevisionGUID="c321b840-47c1-4063-9b07-1eb1084ba439" CreationDate="2023-01-12T08:01:17.170" UserId="15619" Comment="added 13 characters in body" Text="What is the best (most common) approach using SSAO with forward renderer for blended objects?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39467" PostHistoryTypeId="2" PostId="13210" RevisionGUID="3bb303e0-6d80-4ee1-a436-11708edca600" CreationDate="2023-01-12T15:52:59.217" UserId="19446" Text="How do I undo the interpolation of vertex attributes? I'm using unity shader graph which doesn't support nointerpolation. I assume I need to store 3 float3 with one component of each float3 being 1 and the rest 0, this will give the barycentric coordinate. But I don't know how to actually use them to undo the interpolation. " ContentLicense="CC BY-SA 4.0" />
  <row Id="39469" PostHistoryTypeId="1" PostId="13210" RevisionGUID="3bb303e0-6d80-4ee1-a436-11708edca600" CreationDate="2023-01-12T15:52:59.217" UserId="19446" Text="Undo barycentric interpolation" ContentLicense="CC BY-SA 4.0" />
  <row Id="39470" PostHistoryTypeId="3" PostId="13210" RevisionGUID="3bb303e0-6d80-4ee1-a436-11708edca600" CreationDate="2023-01-12T15:52:59.217" UserId="19446" Text="|interpolation|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39471" PostHistoryTypeId="2" PostId="13211" RevisionGUID="32dc7123-a529-4874-986c-455684188dd8" CreationDate="2023-01-12T16:33:13.143" UserId="2654" Text="Even with the barycentric coordinates, you cannot &quot;undo&quot; interpolation. Interpolation uses 3 input values and produces one output value: $f(A, B, C) = O$. So to reverse that would mean that you have one equation with *three* unknowns, ignoring the coordinate itself. You cannot solve for 3 unknowns with one equation.&#xD;&#xA;&#xD;&#xA;If Unity's Shader Graph tool doesn't support flat interpolation, then it's probably best to solve the specific problem rather than searching for a general solution. The way to do this will be particular to exactly the effect you're trying to achieve." ContentLicense="CC BY-SA 4.0" />
  <row Id="39475" PostHistoryTypeId="5" PostId="13208" RevisionGUID="eb3b82e4-44da-4f31-bda1-72864ce2ae80" CreationDate="2023-01-13T22:33:31.847" UserId="10096" Comment="added 5 characters in body" Text="A Hermite cubic polynomial interpolates 2 points and the derivatives at those points. To be exact, let us have the points $p_0, p_1$ and the derivatives (tangents) at those $d_0, d_1$. Then we want a cubic polynomial $p(t) = a_0 + a_1 t + a_2 t^2 + a_3 t^3$ which interpolates the points and derivatives:&#xD;&#xA;$$p(0) = p_0,\,\, p(1) = p_1,\,\, p'(0) = d_0,\,\, p'(1) = d_1.$$&#xD;&#xA;We can take the derivative of $p(t)$ with respect to $t$ in order to get $p'(t) = a_1 + 2a_2 t + 3a_3 t^2$. We can compute two of the coefficients easily: $p(0) = a_0 = p_0$ and $p'(0) = a_1 = d_0$. For the remaining two equations we have&#xD;&#xA;$$p(1) = p_0 + d_0 + a_2 + a_3 = p_1,\quad p'(1) = d_0 + 2a_2 + 3a_3 = d_1.$$&#xD;&#xA;Solving the system we get&#xD;&#xA;$$a_3 = 2(p_0-p_1) + d_0 + d_1, \quad a_2 = 3(p_1 - p_0)-2d_0 - d_1.$$&#xD;&#xA;You can then rewrite the solution using the following system&#xD;&#xA;$$p(t) = \begin{bmatrix} 1 &amp; t &amp; t^2 &amp; t^3 \end{bmatrix} \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;-3 &amp; 3 &amp; -2 &amp; -1 \\&#xD;&#xA;2&amp; -2 &amp; 1 &amp; 1\end{bmatrix} \begin{bmatrix} p_0 \\ p_1 \\ d_0 \\ d_1 \end{bmatrix}.$$&#xD;&#xA;If you perform the vector-matrix multiplication first, then you would get the Hermite basis functions:&#xD;&#xA;$$p(t) = (1-3t^2+2t^3)p_0 + (3t^2-2t^3)p_1 + (t-2t^2+t^3)d_0 + (t^3-t^2)d_1.$$&#xD;&#xA;You can now identify the basis function in front of $p_1$ with the smoothstep function, and the basis function in front of $p_0$ is one minus smoothstep. If you were to additionally set $d_0=d_1=0$, then it turns out that this is the only function you need. **Thus when you do $p(t) = (1-S(t)) p_0 + S(t) p_1$ you are performing cubic spline Hermite interpolation with derivatives set to zero.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="39476" PostHistoryTypeId="2" PostId="13212" RevisionGUID="0d28fca3-e7e8-4fa8-8bcc-440f66f10662" CreationDate="2023-01-14T07:48:27.990" UserId="7462" Text="Say you have a topological skeleton, you want to fabricate a mesh out of it, what algorithms exist to accomplish this?&#xD;&#xA;&#xD;&#xA;I know of at least one way, which is to represent each edge as an implicit capsule and then run dual contouring on the resulting CSG shape given by the union of all capsules.&#xD;&#xA;&#xD;&#xA;I am wondering if there is a way to achieve it through other means, especially through explicit piece wise parametrizations or mesh stitching." ContentLicense="CC BY-SA 4.0" />
  <row Id="39478" PostHistoryTypeId="1" PostId="13212" RevisionGUID="0d28fca3-e7e8-4fa8-8bcc-440f66f10662" CreationDate="2023-01-14T07:48:27.990" UserId="7462" Text="How to create a mesh from a skeleton?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39479" PostHistoryTypeId="3" PostId="13212" RevisionGUID="0d28fca3-e7e8-4fa8-8bcc-440f66f10662" CreationDate="2023-01-14T07:48:27.990" UserId="7462" Text="|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39487" PostHistoryTypeId="2" PostId="13214" RevisionGUID="e2a65150-44db-448f-88cb-8f979d22a10b" CreationDate="2023-01-14T18:24:51.587" UserId="19453" Text="I see web browsers doing this all the time when the internet connection is slow, loading the JPEG images almost line by line from top to bottom. How is this done in practice? I experimented with several image decoding libraries in Rust for example and if I delete half the bytes in an JPEG file, they are not able to decode the image. " ContentLicense="CC BY-SA 4.0" />
  <row Id="39489" PostHistoryTypeId="1" PostId="13214" RevisionGUID="e2a65150-44db-448f-88cb-8f979d22a10b" CreationDate="2023-01-14T18:24:51.587" UserId="19453" Text="How to decode a JPEG file which is not fully loaded yet?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39490" PostHistoryTypeId="3" PostId="13214" RevisionGUID="e2a65150-44db-448f-88cb-8f979d22a10b" CreationDate="2023-01-14T18:24:51.587" UserId="19453" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39491" PostHistoryTypeId="5" PostId="13208" RevisionGUID="c3999beb-f2be-4428-aed4-082f041cf0a2" CreationDate="2023-01-15T01:54:21.753" UserId="10096" Comment="added 4 characters in body" Text="A Hermite cubic polynomial interpolates 2 points and the derivatives at those points. To be exact, let us have the points $p_0, p_1$ and the derivatives (tangents) at those $d_0, d_1$. Then we want a cubic polynomial $p(t) = a_0 + a_1 t + a_2 t^2 + a_3 t^3$ which interpolates the points and derivatives:&#xD;&#xA;$$p(0) = p_0,\,\, p(1) = p_1,\,\, p'(0) = d_0,\,\, p'(1) = d_1.$$&#xD;&#xA;We can take the derivative of $p(t)$ with respect to $t$ in order to get $p'(t) = a_1 + 2a_2 t + 3a_3 t^2$. We can compute two of the coefficients easily: $p(0) = a_0 = p_0$ and $p'(0) = a_1 = d_0$. For the remaining two equations we have&#xD;&#xA;$$p(1) = p_0 + d_0 + a_2 + a_3 = p_1,\quad p'(1) = d_0 + 2a_2 + 3a_3 = d_1.$$&#xD;&#xA;Solving the system we get&#xD;&#xA;$$a_3 = 2(p_0-p_1) + d_0 + d_1, \quad a_2 = 3(p_1 - p_0)-2d_0 - d_1.$$&#xD;&#xA;You can then rewrite the solution using the following system&#xD;&#xA;$$p(t) = \begin{bmatrix} 1 &amp; t &amp; t^2 &amp; t^3 \end{bmatrix} \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \\&#xD;&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xD;&#xA;-3 &amp; 3 &amp; -2 &amp; -1 \\&#xD;&#xA;2&amp; -2 &amp; 1 &amp; 1\end{bmatrix} \begin{bmatrix} p_0 \\ p_1 \\ d_0 \\ d_1 \end{bmatrix}.$$&#xD;&#xA;If you perform the vector-matrix multiplication first, then you would get the Hermite basis functions:&#xD;&#xA;$$p(t) = (1-3t^2+2t^3)p_0 + (3t^2-2t^3)p_1 + (t-2t^2+t^3)d_0 + (t^3-t^2)d_1.$$&#xD;&#xA;You can now identify the basis function in front of $p_1$ with the smoothstep function, and the basis function in front of $p_0$ is one minus smoothstep. If you were to additionally set $d_0=d_1=0$, then it turns out that this is the only function you need. **Thus when you do $p(t) = (1-S(t)) p_0 + S(t) p_1$ you are performing cubic polynomial Hermite interpolation with derivatives set to zero.**" ContentLicense="CC BY-SA 4.0" />
  <row Id="39492" PostHistoryTypeId="2" PostId="13215" RevisionGUID="5ca28b05-0d48-46c7-9817-a1dfdcf6203c" CreationDate="2023-01-15T02:02:05.100" UserId="2654" Text="What you are referring to is called a &quot;progressive JPEG&quot; file. This is a property of a file which allows its decompression to be done in stages, such that a less-detailed version of the image can be shown despite not having the entire file. This technology was originally invented for the early Internet, allowing slow dial-up connections to be able to display something during the several seconds it took to download the entire image. As such, if you cut off the back-end of a progressive JPEG, you can still get some version of the image.&#xD;&#xA;&#xD;&#xA;So this is a property of the file, but it is *also* a property of the decompressor. Any JPEG decompressor can read a progressive JPEG file, but only those with special support can pull off the progressive display trick. And most decompressors don't bother these days." ContentLicense="CC BY-SA 4.0" />
  <row Id="39494" PostHistoryTypeId="5" PostId="13215" RevisionGUID="a0116e65-996a-47a0-bdf1-21e38fb58956" CreationDate="2023-01-15T02:19:40.773" UserId="2654" Comment="added 118 characters in body" Text="What you are referring to is called a &quot;progressive JPEG&quot; file. This is a property of a file which allows its decompression to be done in stages, such that a less-detailed version of the image can be shown despite not having the entire file. This technology was originally invented for the early Internet, allowing slow dial-up connections to be able to display something during the several seconds it took to download the entire image. As such, if you cut off the back-end of a progressive JPEG, you can still get some version of the image.&#xD;&#xA;&#xD;&#xA;So this is a property of the file, but it is *also* a property of the decompressor. Any JPEG decompressor can read a progressive JPEG file, but only those with special support can pull off the progressive display trick. And most decompressors don't bother these days. A JPEG decompressor with progressive support will likely have a special API for doing progressive JPEG decompression." ContentLicense="CC BY-SA 4.0" />
  <row Id="39495" PostHistoryTypeId="5" PostId="3589" RevisionGUID="fcf95bc0-1ac7-4abb-8f8b-346542ccbad6" CreationDate="2023-01-15T03:15:33.453" UserId="2654" Comment="added 1309 characters in body" Text="Learning graphics programming is about more than just learning APIs. It's about learning how graphics works. Vertex transformations, lighting models, shadow techniques, texture mapping, deferred rendering, and so forth. These have absolutely nothing to do with the API you use to implement them.&#xD;&#xA;&#xD;&#xA;So the question is this: do you want to learn how to use an API? Or do you want to learn *graphics*?&#xD;&#xA;&#xD;&#xA;In order to do stuff with hardware-accelerated graphics, you have to learn how to use an API to access that hardware. But once you have the ability to interface with the system, your graphics learning stops focusing on what the API does for you and instead focuses on graphics concepts. Lighting, shadows, bump-mapping, etc.&#xD;&#xA;&#xD;&#xA;If your goal is to learn graphics concepts, the time you're spending with the API is time you're not spending *learning graphics concepts*. How to compile shaders has nothing to do with graphics. Nor does how to send them uniforms, how to upload vertex data into buffers, etc. These are tools, and important tools for doing graphics work.&#xD;&#xA;&#xD;&#xA;But they aren't actually graphics concepts. They are a means to an end.&#xD;&#xA;&#xD;&#xA;It takes a *lot* of work and learning with Vulkan before you can reach the point where you're ready to start learning graphics concepts. Passing data to shaders requires explicit memory management and explicit synchronization of access. And so forth.&#xD;&#xA;&#xD;&#xA;By contrast, getting to that point with OpenGL requires less work. And yes, I'm talking about modern, shader-based core-profile OpenGL.&#xD;&#xA;&#xD;&#xA;Just compare what it takes to do something as simple as clearing the screen. In Vulkan, this requires at least some understanding of a large number of concepts: command buffers, device queues, memory objects, images, and the various WSI constructs.&#xD;&#xA;&#xD;&#xA;In OpenGL... it's three functions: `glClearColor`, `glClear`, and the platform-specific swap buffers call. If you're using more modern OpenGL, you can get it down to two: `glClearBufferuiv` and swap buffers. You don't need to know what a framebuffer is or where its image comes from. You clear it and swap buffers.&#xD;&#xA;&#xD;&#xA;Because OpenGL hides a lot from you, it takes a lot less effort to get to the point where you're actually learning graphics as opposed to learning the interface to graphics hardware.&#xD;&#xA;&#xD;&#xA;Furthermore, OpenGL is a (relatively) safe API. It will issue errors when you do something wrong, usually. Vulkan is not. While there are debugging layers that you can use to help, the core Vulkan API will tell you almost nothing unless there is a hardware fault. If you do something wrong, you can get garbage rendering or crash the GPU.&#xD;&#xA;&#xD;&#xA;Coupled with Vulkan's complexity, it becomes very easy to accidentally do the wrong thing. Forgetting to set a texture to the right layout may work under one implementation, but not another. Forgetting a sychronization point may work sometimes, but then suddenly fail for seemingly no reason. And so forth.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;All that being said, there are two caveats to be pointed out here.&#xD;&#xA;&#xD;&#xA;First, the above is true but only for the time being. Now that a few years have passed since command-buffer APIs have come into being, hardware vendors are starting to develop important graphical features that fundamentally *cannot work* under OpenGL.&#xD;&#xA;&#xD;&#xA;Ray tracing is the prime example here. It requires such a fundamentally different rendering structure that OpenGL just has no way to handle it. This isn't like mesh shaders, where you replace the vertex processing pipeline with a different one. Here, you absolutely *need* to be able to access any texture/buffer at any time for any reason. And while you kind of can do that in OpenGL with bindless textures and a few other extensions, it ultimately becomes too complicated to make work with the structure of OpenGL.&#xD;&#xA;&#xD;&#xA;But Vulkan's command-buffer based API handles it just fine.&#xD;&#xA;&#xD;&#xA;As time goes on, more and more graphical features like this will exist. Features which are inherently incompatible with OpenGL-like APIs. So for the time being, OpenGL and Vulkan have transferable graphical concepts, this will become increasingly less true as time goes on. New features will be added to Vulkan and not OpenGL, not because OpenGL is old, but because it just can't work well with those features.&#xD;&#xA;&#xD;&#xA;Second, there is more to learning graphics than learning graphical techniques. There's one area in particular where Vulkan wins.&#xD;&#xA;&#xD;&#xA;Graphical *performance*.&#xD;&#xA;&#xD;&#xA;Being a 3D graphics programmer usually requires some idea of how to optimize your code. And it is here where OpenGL's hiding of information and doing things behind your back becomes a problem.&#xD;&#xA;&#xD;&#xA;The OpenGL memory model is synchronous. The implementation is allowed to issue commands asynchronously so long as the user cannot tell the difference. So if you render to some image, then try to read from it, the implementation must issue an explicit synchronization event between these two tasks.&#xD;&#xA;&#xD;&#xA;But in order to achieve performance in OpenGL, you have to know that implementations do this, so that you can *avoid it*. You have to realize where the implementation is secretly issuing synchronization events, and then rewrite your code to avoid them as much as possible. But the API itself doesn't make this obvious; you have to have gained this knowledge from somewhere.&#xD;&#xA;&#xD;&#xA;With Vulkan... *you* are the one who has to issue those synchronization events. Therefore, you *must* be aware of the fact that the hardware does not execute commands synchronously. You must know when you need to issue those events, and therefore you must be aware that they will probably slow your program down. So you do everything you can to avoid them.&#xD;&#xA;&#xD;&#xA;An explicit API like Vulkan forces you to make these kinds of performance decisions. And therefore, if you learn the Vulkan API, you already have a good idea about what things are going to be slow and what things are going to be fast.&#xD;&#xA;&#xD;&#xA;If you have to do some framebuffer work that forces you to create a new renderpass... odds are good that this will be slower than if you could fit it into a separate subpass of a renderpass. That doesn't mean you can't do that, but the API tells you up front that it could cause a performance problem.&#xD;&#xA;&#xD;&#xA;In OpenGL, the API basically invites you to change your framebuffer attachments willy-nilly. There's no guidance on which changes will be fast or slow.&#xD;&#xA;&#xD;&#xA;So in that case, learning Vulkan can help you better learn about how to make graphics faster. And it will certainly help you reduce CPU overhead.&#xD;&#xA;&#xD;&#xA;It'll still take much longer before you can get to the point where you can learn graphical rendering techniques." ContentLicense="CC BY-SA 4.0" />
  <row Id="39496" PostHistoryTypeId="5" PostId="13203" RevisionGUID="e1f19809-1ca9-4d2d-b649-beea2f1af020" CreationDate="2023-01-15T04:38:11.923" UserId="2654" Comment="added 40 characters in body" Text="&gt; However, Hermite interpolation it links to is different from Cubic Hermite spline interpolation; they're two different articles.&#xD;&#xA;&#xD;&#xA;These are nested subjects. That is, &quot;Cubic Hermit interpolation&quot; is a specific kind of &quot;Hermite interpolation&quot;, just as a polygon is a specific kind of polytope.&#xD;&#xA;&#xD;&#xA;Hermite interpolation is itself a particular scheme for doing polynomial interpolation. And polynomial interpolation is the construction of a polynomial (of the lowest possible degree) that passes through all of a given set of points in a field.&#xD;&#xA;&#xD;&#xA;How this maps to `smoothstep` is as follows. For a given pair of start/end values, `smoothstep` defines a function `f(X)`, where X is the given value. If we plot `Y = f(X)` on a graph, we get a function whose Y range is [0, 1] and its X range is [-inf, inf].&#xD;&#xA;&#xD;&#xA;Now, when X is less than the start value, Y is always 0. When X is greater than the end value, Y is always one. When X is between those two values, it varies from 0 towards the start and 1 towards the end.&#xD;&#xA;&#xD;&#xA;What that means is that we have 2 points in 2D space: (start, 0) and (end, 1). If we presume that start is 0 and end is 1 (we can linearly rescale the X value to map [start, end] to the [0, 1] range), then our points are (0, 0) and (1, 1).&#xD;&#xA;&#xD;&#xA;Given this, we can perform Hermite interpolation between those two points. However, cubic Hermite interpolation requires 4 points: two points in space that act as the end points the curve must match and two first-derivatives which the curve must match at those points.&#xD;&#xA;&#xD;&#xA;The first-derivatives are *implied* here by the nature of the smoothstep function. That is, the derivatives are chosen to be &quot;smooth&quot;, relative to the flat parts of the function (ie: outside the X range of [0, 1]).&#xD;&#xA;&#xD;&#xA;The derivatives can be defined in terms of 2D vectors that are tangent to the curve at those points, flowing in the direction of the curve from start to end. Since the values less than 0 are going to be a flat value of 0, and the values greater than 1 will have a flat value of 1, it makes sense that the tangents are also flat. So the two tangents are both (1, 0).&#xD;&#xA;&#xD;&#xA;So our 4 Hermite interpolation positions are:&#xD;&#xA;&#xD;&#xA;| 0th Derivative | 1st Derivative |&#xD;&#xA;| -------------- | -------------- |&#xD;&#xA;|    (0, 0)      |     (1, 0)     |&#xD;&#xA;|    (1, 1)      |     (1, 0)    |&#xD;&#xA;&#xD;&#xA;The rest is just plugging those numbers into the [cubic Hermite interpolation formula][1] and reducing the result. $\boldsymbol{p}_0$ and $\boldsymbol{p}_1$ are the start/end points, and $\boldsymbol{k}_0$ &amp; $\boldsymbol{k}_1$ are the two tangents:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\boldsymbol{f}(t) = \left(2t^3 - 3t^2 + 1\right) \boldsymbol{p}_0 + \left(t^3 - 2t^2 + t\right) \boldsymbol{m}_0 + \left(-2t^3 + 3t^2\right) \boldsymbol{p}_1 + \left(t^3 - t^2\right) \boldsymbol{m}_1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The X and Y components are:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;f(t)_x &amp;=&amp; \left(2t^3 - 3t^2 + 1\right) p_{0x} + \left(t^3 - 2t^2 + t\right) m_{0x} + \left(-2t^3 + 3t^2\right) p_{1x} + \left(t^3 - t^2\right) m_{1x}\\&#xD;&#xA;f(t)_y &amp;=&amp; \left(2t^3 - 3t^2 + 1\right) p_{0y} + \left(t^3 - 2t^2 + t\right) m_{0y} + \left(-2t^3 + 3t^2\right) p_{1y} + \left(t^3 - t^2\right) m_{1y}&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If you insert the zeros and ones, then you get things reduced to:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{eqnarray*}&#xD;&#xA;f(t)_x &amp;=&amp; (t^3 - 2t^2 + t) + (-2t^3 + 3t^2) + (t^3 - t^2)\\&#xD;&#xA;&amp;=&amp; (t^3 - 2t^3 + t^3) + (-2t^2 + 3t^2 - t^2) + t\\&#xD;&#xA;&amp;=&amp; t\\&#xD;&#xA;f(t)_y &amp;=&amp; -2t^3 + 3t^2&#xD;&#xA;\end{eqnarray*}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;We're not actually looking for $f(t)$ however; we're looking for our function f(x) that yields Y. Because $t$ and $f(t)_x$ are the same however, that means $f(t)_y$ is just the $f(x)$ that we're looking for.&#xD;&#xA;&#xD;&#xA;Does $-2x^3 + 3x^2$ look familiar? It's just a different form of `t * t * (3.0 - 2.0 * t)`. Which is [what `smoothstep` returns][2] when `t` is between 0 and 1.&#xD;&#xA;&#xD;&#xA;QED&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Interpolation_on_a_single_interval&#xD;&#xA;  [2]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/smoothstep.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="39497" PostHistoryTypeId="50" PostId="12414" RevisionGUID="3a16b45e-a4f3-4dce-b3aa-977f25a0f97f" CreationDate="2023-01-15T10:07:35.973" UserId="-1" />
  <row Id="39501" PostHistoryTypeId="34" PostId="10909" RevisionGUID="7ed8925f-649c-4f3b-a325-e3c38b838015" CreationDate="2023-01-16T01:19:02.363" UserId="19431" Comment="81" />
  <row Id="39507" PostHistoryTypeId="2" PostId="13217" RevisionGUID="322399d4-7046-466f-a3c0-e74d62221834" CreationDate="2023-01-16T10:15:24.583" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="39509" PostHistoryTypeId="1" PostId="13217" RevisionGUID="322399d4-7046-466f-a3c0-e74d62221834" CreationDate="2023-01-16T10:15:24.583" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="39510" PostHistoryTypeId="2" PostId="13218" RevisionGUID="5509cb09-4e23-4038-8c3c-9d79ee47823d" CreationDate="2023-01-16T10:15:24.583" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="39512" PostHistoryTypeId="1" PostId="13218" RevisionGUID="5509cb09-4e23-4038-8c3c-9d79ee47823d" CreationDate="2023-01-16T10:15:24.583" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="39513" PostHistoryTypeId="2" PostId="13219" RevisionGUID="b9899f14-546d-48b2-ab97-106574f357ac" CreationDate="2023-01-16T13:18:42.177" UserId="11224" Text="[![Screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA;1) Why does the wavy white line on the tennis ball texture seem to be at the wrong mip level, with blocky artifacts ? For example, at 'A' in the picture.&#xD;&#xA;The basketball and football textures are nice and smooth, even when they are smaller than the tennis ball.&#xD;&#xA;&#xD;&#xA;2) Why does the equatorial gradient between light and shade due to the overhead directional light source seem aliased in some cases, e.g. on the basketball at B1 and on the tennis ball at B2, but not in others, e.g. on the basketball at C1 and on the tennis ball at C2 ? Is MSAA able to detect such cases ? I thought it might be that MSAA only works on boundaries of triangles, and that this might explain the difference - however - these effects are invariant with respect to arbitrary rotations of the spheres about their centres.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Errors (which I will fix but which I suppose don't account for the above issues):**&#xD;&#xA;&#xD;&#xA;1) I know about the swirly pattern visible e.g. at 'D' on the pole of the basketball - that was my mistake with assigning texture coordinates.&#xD;&#xA;&#xD;&#xA;2) I know about the sawtooth glitch e.g. at 'E1' on the basketball, and at 'E2' on the football (a spurious edge running North West to South East). This is my failure to assign correct normal vectors along the meridian of longitude that forms a seam at the left and right of the equirectangular texture for the approximate sphere.&#xD;&#xA;&#xD;&#xA;I am using OpenGL 4.4, plus the anistropic filtering extension GL_EXT_texture_filter_anisotropic.&#xD;&#xA;My GPU is an integrated one by Intel. In the Intel Graphics HD Control Panel in Windows, for my program I have turned off CMAA, and I have set both MSAA and Anisotropic Filtering to &quot;Use Application Default Settings&quot;.&#xD;&#xA;My screen is 1920 x 1080 pixels.&#xD;&#xA;&#xD;&#xA;My scene has a white directional light overhead, and a red point light, both of which are calculated in the shader program, using Blinn-Phong shading.&#xD;&#xA;&#xD;&#xA;The 3 ball textures (which are 2048 x 1024) are by Paul Bourke. http://paulbourke.net/geometry/spherical/&#xD;&#xA;The wallpaper texture in the background is from wallpaper flare. https://www.wallpaperflare.com/&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My process for generating textures:&#xD;&#xA;&#xD;&#xA;1) Open the image in MS Paint.&#xD;&#xA;2) In the case of the wallpaper texture, crop out a 4096 x 4096 square.&#xD;&#xA;3) Save the file as a .bmp.&#xD;&#xA;4) My C code opens and reads the bitmap file, and makes it into a texture with internal format `GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM`.&#xD;&#xA;5) This is then written to the hard drive so that in future, the compressed version can be loadly directly instead of having to load the .bmp version and compress it.&#xD;&#xA;6) Set the MAG filter to `LINEAR`, and the MIN filter to `LINEAR_MIPMAP_LINEAR`.&#xD;&#xA;7) Ask for anistropic filtering using&#xD;&#xA;&#xD;&#xA;`glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_sample_limit);`,&#xD;&#xA;&#xD;&#xA;where the anisotropic_sample_limit was determined by passing `GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT` to `glGetFloatv`. In my case, it is 16.0.&#xD;&#xA;&#xD;&#xA;8) Ask OpenGL to generate the mipmaps using `glGenerateMipMap`.&#xD;&#xA;&#xD;&#xA;For antialising, I followed Joey de Vries learnopengl tutorial https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing on how to use MSAA. I am not using GLFW nor GLEW. Instead I am using glad https://glad.dav1d.de/ and I am using the Windows API directly in my C code (as far as I can tell).&#xD;&#xA;I tried but failed to persuade OpenGL / Windows to give me a multisampled default framebuffer. Instead I went with &quot;Off-screen MSAA&quot;. My antialising process is:&#xD;&#xA;&#xD;&#xA;1) Make a framebuffer and attach to it a multisampled colour buffer made like this (where I have set number_of_samples to 4):&#xD;&#xA;&#xD;&#xA;`glRenderbufferStorageMultisample(GL_RENDERBUFFER, number_of_samples, GL_RGBA8, window_width_pixels, window_height_pixels);`&#xD;&#xA;&#xD;&#xA;and a multisampled DEPTH / STENCIL buffer made like this:&#xD;&#xA;&#xD;&#xA;`glRenderbufferStorageMultisample(GL_RENDERBUFFER, number_of_samples, GL_DEPTH24_STENCIL8, window_width_pixels, window_height_pixels);`&#xD;&#xA;&#xD;&#xA;2) Call `glEnable(GL_MULTISAMPLE);`&#xD;&#xA;3) Before the animation loop, bind this framebuffer for reading.&#xD;&#xA;4) For each frame of the animation, bind that framebuffer for drawing, then draw on it (my shader program has no explicit antialising).&#xD;&#xA;5) Then bind the default framebuffer for drawing using&#xD;&#xA;`glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);`&#xD;&#xA;6) Blit my framebuffer to the default framebuffer using&#xD;&#xA;&#xD;&#xA;`glBlitFramebuffer(0, 0, window_width_pixels, window_height_pixels, 0, 0, window_width_pixels, window_height_pixels, GL_COLOR_BUFFER_BIT, GL_NEAREST);`&#xD;&#xA;&#xD;&#xA;7) Swap the buffers, and begin the animation loop again.&#xD;&#xA;&#xD;&#xA;I have tried the code on a different laptop, with a 4K screen and an Nvidia GPU as well as an integrated Intel one. With the integrated GPU on that laptop, both issues (the blockiness of the wavy line on the tennis ball, and the inconsistent antialiasing of the equatorial gradient on the balls) persist. With the Nvidia GPU, the wavy line on the tennis ball is perfectly correct, but the other problem persists.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Idea:**&#xD;&#xA;&#xD;&#xA;Is the problem with the inconsistent antialiasing of the equatorial gradient on the balls, due to the overhead directional light, dependent on the shininess of the balls ? Perhaps those that have a higher Blinn-Phong specular exponent and strength (which simply multiplies the specular contribution, and which I have set to be proportional to the specular exponent) have smoother gradients, because the function $\max(\cos^n \theta, 0)$ is smooth at 90 degrees, whereas the function $\max(\cos \theta, 0)$ has a corner (fails to be differentiable) at 90 degrees ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GDY9a.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39515" PostHistoryTypeId="1" PostId="13219" RevisionGUID="b9899f14-546d-48b2-ab97-106574f357ac" CreationDate="2023-01-16T13:18:42.177" UserId="11224" Text="Why are my OpenGL mipmaps and MSAA bad?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39516" PostHistoryTypeId="3" PostId="13219" RevisionGUID="b9899f14-546d-48b2-ab97-106574f357ac" CreationDate="2023-01-16T13:18:42.177" UserId="11224" Text="|opengl|texture|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39517" PostHistoryTypeId="5" PostId="13207" RevisionGUID="c38d02bf-f59f-4d38-af7f-49b5a32c1b45" CreationDate="2023-01-16T14:52:55.457" UserId="209" Comment="added simple example" Text="What do you mean by &quot;normal&quot; aliasing?  Aliasing is the result of under-sampling: i.e being given a signal with a high frequency (temporal and/or spatial) that is being sampled too infrequently (it needs to be sampled at a rate exceeding 2x its maximum frequency OR band-limited/pre-filtered until its max frequency is &lt; 1/2 the sampling rate).&#xD;&#xA;&#xD;&#xA;With texture data, *the* common pre-filtering approach is to use MIP maps (see [Lance Williams' &quot;Pyramidal Parametrics&quot;][1]. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;FWIW I like to explain aliasing by the following:&lt;br&gt;&#xD;&#xA;Imagine you work for a an office-based company (i.e pre covid WFH etc), and are at your desk solidly, 9~5, apart from a lunch break and a 15 min coffee break at 10:30. &#xD;&#xA;The CEO take a regular stroll around the office at 10:35 and thus always sees you in the kitchen, rather than at your desk. &#xD;&#xA;Because she is under-sampling your 'signal', she thus assumes you are never working. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://dl.acm.org/doi/10.1145/800059.801126" ContentLicense="CC BY-SA 4.0" />
  <row Id="39518" PostHistoryTypeId="5" PostId="13219" RevisionGUID="e882b851-f4cc-44c0-8628-742aa37877f2" CreationDate="2023-01-16T16:14:15.597" UserId="11224" Comment="Added tennis ball equirectangular texture and added code for vertex and fragment shaders" Text="[![Screenshot][1]][1]&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;&#xD;&#xA;1) Why does the wavy white line on the tennis ball texture seem to be at the wrong mip level, with blocky artifacts ? For example, at 'A' in the picture.&#xD;&#xA;The basketball and football textures are nice and smooth, even when they are smaller than the tennis ball.&#xD;&#xA;&#xD;&#xA;2) Why does the equatorial gradient between light and shade due to the overhead directional light source seem aliased in some cases, e.g. on the basketball at B1 and on the tennis ball at B2, but not in others, e.g. on the basketball at C1 and on the tennis ball at C2 ? Is MSAA able to detect such cases ? I thought it might be that MSAA only works on boundaries of triangles, and that this might explain the difference - however - these effects are invariant with respect to arbitrary rotations of the spheres about their centres.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Errors (which I will fix but which I suppose don't account for the above issues):**&#xD;&#xA;&#xD;&#xA;1) I know about the swirly pattern visible e.g. at 'D' on the pole of the basketball - that was my mistake with assigning texture coordinates.&#xD;&#xA;&#xD;&#xA;2) I know about the sawtooth glitch e.g. at 'E1' on the basketball, and at 'E2' on the football (a spurious edge running North West to South East). This is my failure to assign correct normal vectors along the meridian of longitude that forms a seam at the left and right of the equirectangular texture for the approximate sphere.&#xD;&#xA;&#xD;&#xA;I am using OpenGL 4.4, plus the anistropic filtering extension GL_EXT_texture_filter_anisotropic.&#xD;&#xA;My GPU is an integrated one by Intel. In the Intel Graphics HD Control Panel in Windows, for my program I have turned off CMAA, and I have set both MSAA and Anisotropic Filtering to &quot;Use Application Default Settings&quot;.&#xD;&#xA;My screen is 1920 x 1080 pixels.&#xD;&#xA;&#xD;&#xA;My scene has a white directional light overhead, and a red point light, both of which are calculated in the shader program, using Blinn-Phong shading.&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;Here is my vertex shader:&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    uniform mat4 M_matrix;&#xD;&#xA;    uniform mat3 N_matrix;&#xD;&#xA;    uniform mat4 PVM_matrix;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 camera_position_wc;&#xD;&#xA;    &#xD;&#xA;    // directional_light_direction_wc must be normalised before being sent to the shader program:&#xD;&#xA;    uniform vec3 directional_light_direction_wc;&#xD;&#xA;    uniform vec3 point_light_position_wc;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    layout (location = 0) in vec3 v_position_mc;&#xD;&#xA;    layout (location = 1) in vec2 v_tex_coord;&#xD;&#xA;    //layout (location = 1) in vec3 v_normal_mc;&#xD;&#xA;    layout (location = 2) in vec3 v_normal_mc;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    out vec2 v_tex_coord_pass_through;&#xD;&#xA;    out vec3 normalised_normal_wc;&#xD;&#xA;    out float directional_light_diffuse_cosine;&#xD;&#xA;    out vec3 camera_vector_wc;&#xD;&#xA;    out vec3 point_light_vector_wc;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;    	//// Pass through the texture coordinates:&#xD;&#xA;    	v_tex_coord_pass_through = v_tex_coord;&#xD;&#xA;    	// Scale the texture coordinates by the norm of the first column of the model matrix, which I believe should be equal&#xD;&#xA;    	// to model_parameters.scale[0], then translate the origin to the centre of the texture, then pass the result through:&#xD;&#xA;    	//v_tex_coord_pass_through = length(M_matrix[0])*v_tex_coord + 0.5f;&#xD;&#xA;    	//v_tex_coord_pass_through = length(M_matrix[0])*v_tex_coord;&#xD;&#xA;    	&#xD;&#xA;    	// Here we assume that v_normal_mc is nonzero, and N_matrix nondegenerate, so that their product is nonzero.&#xD;&#xA;    	// In this case, we avoid the risk that normalize tries to divide by zero:&#xD;&#xA;    	normalised_normal_wc = normalize(N_matrix*v_normal_mc);&#xD;&#xA;    &#xD;&#xA;    	// Note that &quot;directional_light_diffuse_cosine&quot; may be negative. In fact it is positive iff the directional light&#xD;&#xA;    	// direction is on the outward-facing side of the triangle.&#xD;&#xA;    	// We don't clamp it at zero here, because we want the fragment shader to be able to use the directional light,&#xD;&#xA;    	// even when the triangle is facing away from the camera.&#xD;&#xA;    	// This is a precaution, in case the programmer chooses *not* to cull back faces.&#xD;&#xA;    	// Because we are doing flat shading, and because the directional light direction is constant over the whole scene,&#xD;&#xA;    	// this cosine can be computed once per triangle vertex, instead of once per fragment.&#xD;&#xA;    	// Unfortunately, the fragment shader will still do unnecessary work, to interpolate this constant over the triangle,&#xD;&#xA;    	// but this seems to be an unavoidable result of the design of the OpenGL rendering pipeline.&#xD;&#xA;    	directional_light_diffuse_cosine = dot(directional_light_direction_wc, normalised_normal_wc);&#xD;&#xA;    &#xD;&#xA;    	vec3 vertex_position_wc = vec3(M_matrix*vec4(v_position_mc, 1.0f));&#xD;&#xA;    	camera_vector_wc = camera_position_wc - vertex_position_wc;&#xD;&#xA;    	point_light_vector_wc = point_light_position_wc - vertex_position_wc;&#xD;&#xA;    	gl_Position = PVM_matrix*vec4(v_position_mc, 1.0f);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;and my fragment shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    #version 440 core&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D tex;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 model_colour;&#xD;&#xA;    uniform vec3 model_glow_colour;&#xD;&#xA;    uniform float model_specular_exponent;&#xD;&#xA;    uniform float model_specular_strength;&#xD;&#xA;    &#xD;&#xA;    uniform vec3 ambient_light_colour;&#xD;&#xA;    // directional_light_direction_wc must be normalised before being sent to the shader program:&#xD;&#xA;    uniform vec3 directional_light_direction_wc;&#xD;&#xA;    uniform vec3 directional_light_colour;&#xD;&#xA;    uniform vec3 point_light_colour;&#xD;&#xA;    uniform float point_light_fake_radius_squared;&#xD;&#xA;    &#xD;&#xA;    uniform float exposure;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    in vec2 v_tex_coord_pass_through;&#xD;&#xA;    in vec3 normalised_normal_wc;&#xD;&#xA;    in float directional_light_diffuse_cosine;&#xD;&#xA;    in vec3 camera_vector_wc;&#xD;&#xA;    in vec3 point_light_vector_wc;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    out vec4 frag_colour;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	&#xD;&#xA;    	float directional_light_diffuse_coefficient;&#xD;&#xA;    	float directional_light_specular_coefficient;&#xD;&#xA;    	float point_light_diffuse_coefficient;&#xD;&#xA;    	float point_light_specular_coefficient;&#xD;&#xA;    	const float reciprocal_gamma = 0.4545f;&#xD;&#xA;    	&#xD;&#xA;    	// Interpolate the camera vector (automatically), and then normalise it:&#xD;&#xA;    	// I believe that the various coordinate transforms must necessarily be set up in such a way that the camera is strictly outside the viewing frustum.&#xD;&#xA;    	// If so, then no fragments inside the frustum can coincide with the camera position, and therefore the camera_vector_wc must be non-zero.&#xD;&#xA;    	// If so, then it is safe to normalise this vector using the built-in &quot;normalize&quot; function:&#xD;&#xA;    	// Since the camera vector might be zero, we will use out own home-made version of &quot;normalize&quot;.&#xD;&#xA;    	// If all the light sources that can produce specular reflections are on the opposite side of the triangle, then the following computation of the camera direction&#xD;&#xA;    	// is a wasted effort. However, let's keep the flow simple by just computing it in any case:&#xD;&#xA;    	vec3 camera_direction_wc = normalize(camera_vector_wc);&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    	// The point of this &quot;rectification&quot; is to illuminate the back faces (just in case the programmer&#xD;&#xA;    	// has chosen not to enable back-face culling) in the same way as the front faces.&#xD;&#xA;    	// A similar result can probably be achieved by using the built-in GLSL function &quot;faceforward&quot;&#xD;&#xA;    	// somewhere in the fragment or vertex shader, but for now let's just use this home-made solution.&#xD;&#xA;    	// By converting the Boolean gl_FrontFacing to a float equal to 1.0f or -1.0f, we avoid an &quot;if&quot; statement.&#xD;&#xA;    	// Branching statements are said to be expensive, although I have read that in modern GPUs, they are less of a problem than they used to be:&#xD;&#xA;    	float front_facing;&#xD;&#xA;    	vec3 normalised_normal_wc_rectified;&#xD;&#xA;    	float directional_light_diffuse_cosine_rectified;&#xD;&#xA;    	&#xD;&#xA;    	front_facing = 2.0f*float(gl_FrontFacing) - 1.0f;&#xD;&#xA;    	normalised_normal_wc_rectified = front_facing*normalised_normal_wc;&#xD;&#xA;    	directional_light_diffuse_cosine_rectified = front_facing*directional_light_diffuse_cosine;&#xD;&#xA;    &#xD;&#xA;    	// &quot;directional_light_diffuse_cosine_rectified&quot; is positive iff the directional light direction is on the same side of&#xD;&#xA;    	// the triangle as the camera is, regardless of whether that is the front or back face of the triangle.&#xD;&#xA;    	// If it is negative, then as seen by the camera, the directional light does not illuminate the triangle&#xD;&#xA;    	// at all, and we should clamp it at zero:&#xD;&#xA;    	directional_light_diffuse_coefficient = max(directional_light_diffuse_cosine_rectified, 0.0f);&#xD;&#xA;    	&#xD;&#xA;    	// Note that &quot;normalised_normal_wc_rectified&quot; is now on the same side of the triangle as is the camera.&#xD;&#xA;    	// The &quot;half_vector_wc&quot; could be also on the same side of the triangle as is the camera, *even* when the&#xD;&#xA;    	// directional light direction is *not*. In that situation, the directional light does not illuminate the&#xD;&#xA;    	// triangle, as seen by the camera, so its specular contribution should be set to zero:&#xD;&#xA;    	if (directional_light_diffuse_coefficient == 0.0f)&#xD;&#xA;    	{&#xD;&#xA;    		directional_light_specular_coefficient = 0.0f;&#xD;&#xA;    	}&#xD;&#xA;    	else&#xD;&#xA;    	{&#xD;&#xA;    		// Having reached this point, we know that the directional light direction and the camera are both on the same&#xD;&#xA;    		// side of the triangle (which may be the front or the back side). Therefore the camera will see some specular&#xD;&#xA;    		// contribution from the directional light to the triangle surface.&#xD;&#xA;    		vec3 directional_light_half_vector_wc = normalize(directional_light_direction_wc + camera_direction_wc);&#xD;&#xA;    		// Mathematically, the half vector is now guaranteed to be on the same side of the triangle as is the rectified&#xD;&#xA;    		// normalised normal vector to the triangle, so the dot product of these two vectors must be non-negative.&#xD;&#xA;    		// However, I suppose that numerical errors might cause it to be a very small but negative number.&#xD;&#xA;    		// Were this to happen, we would find ourselves raising that negative number to a power with the &quot;pow&quot; function, whose&#xD;&#xA;    		// behaviour in that case is undefined (because to do that properly requires complex numbers, as in the square roots&#xD;&#xA;    		// of negative 1, etc.) This may produce an error.&#xD;&#xA;    		// Therefore, for safety's sake, let's clamp that dot product at zero, using the &quot;max&quot; function:&#xD;&#xA;    		directional_light_specular_coefficient = pow(max(dot(directional_light_half_vector_wc, normalised_normal_wc_rectified), 0.0f), model_specular_exponent);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// Interpolate the vector from the fragment to the point light position, and normalise it.&#xD;&#xA;    	// However, in case the interpolated vector is zero, use &quot;length&quot; for this, rather than &quot;normalize&quot;:&#xD;&#xA;    	float point_light_distance = length(point_light_vector_wc);&#xD;&#xA;    	if (point_light_distance == 0.0f)&#xD;&#xA;    	{&#xD;&#xA;    		// The position of the point light source coincides with the position of the current fragment.&#xD;&#xA;    		// Set the contributions of the point light source to the colour of the fragment to zero:&#xD;&#xA;    		point_light_diffuse_coefficient = 0.0f;&#xD;&#xA;    		point_light_specular_coefficient = 0.0f;&#xD;&#xA;    	}&#xD;&#xA;    	else&#xD;&#xA;    	{&#xD;&#xA;    		vec3 point_light_direction_wc = point_light_vector_wc/point_light_distance;&#xD;&#xA;    		float point_light_diffuse_cosine_rectified = dot(point_light_direction_wc, normalised_normal_wc_rectified);&#xD;&#xA;    		point_light_diffuse_coefficient = max(point_light_diffuse_cosine_rectified, 0.0f);&#xD;&#xA;    				&#xD;&#xA;    		if (point_light_diffuse_coefficient == 0.0f)&#xD;&#xA;    		{&#xD;&#xA;    			point_light_specular_coefficient = 0.0f;&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			// The intensity (I'm probably not using the right word from physics) of the radiation from the point light decreases inversely as the square&#xD;&#xA;    			// of the distance to the point light, because the energy is spread over the surface of a sphere centred on the point light, and the surface area&#xD;&#xA;    			// of the sphere increases as the square of its radius. However, such a model has the intensity asymptotic to infinity, as the distance tends to zero !&#xD;&#xA;    			// This unphysical behaviour arises, if I understand correctly, from the unphysical notion of an infinitessimally small source of energy.&#xD;&#xA;    			// In this video, Prof. Cem Yuksel explains the derivation of a good alternative attenuation function that solves this problem:&#xD;&#xA;    			//&#xD;&#xA;    			// https://youtu.be/wzIcjzKQ2BE&#xD;&#xA;    			//&#xD;&#xA;    			// That is the formula that we use here. The parameter &quot;point_light_fake_radius_squared&quot; represents the square of the radius of a spherical light,&#xD;&#xA;    			// or at other points in the approximation, a disc light orthogonal to the direction from the fragment to the point light, that approximates the&#xD;&#xA;    			// point light. Note that this is *not* intended to approximate actual spherical lights, nor disk lights.&#xD;&#xA;    			// The squared radius is a uniform variable, so that the user can control the radius in real time, using the keyboard.&#xD;&#xA;    			// We can, if we like, add a sphere or approximate sphere to our scene, of that radius, to represent the point light source:&#xD;&#xA;    			float point_light_attenuation = 2.0f*(1.0f - point_light_distance/sqrt(point_light_distance*point_light_distance + point_light_fake_radius_squared))/(point_light_fake_radius_squared);&#xD;&#xA;    			point_light_diffuse_coefficient = point_light_diffuse_coefficient*point_light_attenuation;&#xD;&#xA;    			&#xD;&#xA;    			// Having reached this point, we know that the point light direction and the camera are both on the same&#xD;&#xA;    			// side of the triangle (which may be the front or the back side). Therefore the camera will see some specular&#xD;&#xA;    			// contribution from the point light to the triangle surface.&#xD;&#xA;    			vec3 point_light_half_vector_wc = normalize(point_light_direction_wc + camera_direction_wc);&#xD;&#xA;    			// Mathematically, the half vector is now guaranteed to be on the same side of the triangle as is the rectified&#xD;&#xA;    			// normalised normal vector to the triangle, so the dot product of these two vectors must be non-negative.&#xD;&#xA;    			// However, I suppose that numerical errors might cause it to be a very small but negative number.&#xD;&#xA;    			// Were this to happen, we would find ourselves raising that negative number to a power with the &quot;pow&quot; function, whose&#xD;&#xA;    			// behaviour in that case is undefined (because to do that properly requires complex numbers, as in the square roots&#xD;&#xA;    			// of negative 1, etc.) This may produce an error.&#xD;&#xA;    			// Therefore, for safety's sake, let's clamp that dot product at zero, using the &quot;max&quot; function:&#xD;&#xA;    			point_light_specular_coefficient = pow(max(dot(point_light_half_vector_wc, normalised_normal_wc_rectified), 0.0f), model_specular_exponent);&#xD;&#xA;    			point_light_specular_coefficient = point_light_specular_coefficient*point_light_attenuation;&#xD;&#xA;    		}&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    	//vec3 ambient_and_diffuse_colour = (ambient_light_colour + directional_light_diffuse_coefficient*directional_light_colour + point_light_diffuse_coefficient*point_light_colour)*model_colour;&#xD;&#xA;    	vec3 ambient_and_diffuse_colour = (ambient_light_colour + directional_light_diffuse_coefficient*directional_light_colour + point_light_diffuse_coefficient*point_light_colour)*(texture(tex, v_tex_coord_pass_through)).rgb;&#xD;&#xA;    &#xD;&#xA;    	// Unlike the ambient and diffuse light, the specular light is *not* modulated by the colour of the triangle:&#xD;&#xA;    	vec3 specular_colour = model_specular_strength*(directional_light_specular_coefficient*directional_light_colour + point_light_specular_coefficient*point_light_colour);&#xD;&#xA;    &#xD;&#xA;    	// Instead of clamping the fragment colour above at 1, as we used to, we will use a High Dynamic Range (HDR), in which we map the interval [0, +infinity)&#xD;&#xA;    	// into the interval [0, 1] by an *injective* function, thereby preserving all the information about contrasting colours. This also allows us to set the&#xD;&#xA;    	// colour channels for the colours of the lights to values greater than 1.0f, if we like. In this way, we can more accurately represent the relative&#xD;&#xA;    	// brightness of, say, the sun and an LED light.&#xD;&#xA;    	// However, colours of materials should still have their channels between 0.0f and 1.0f, because they represent *proportions* of light to be reflected.&#xD;&#xA;    	// The injective map that we'll use has a parameter called &quot;exposure&quot;, a bit like the exposure values used by photographers.&#xD;&#xA;    	// For now we will hard code it here to have some value that seems to work well, but in future, let's make it a uniform variable, so that it can be&#xD;&#xA;    	// controlled from within the c program. It could even be adjusted interactively by the user, during the animation loop.&#xD;&#xA;    	// Although it seems to work as intended, when we take the min of a vec3 and a float, i.e. the float seems to be implicitly converted into a vec3 whose&#xD;&#xA;    	// components are all equal to that float, yet trying the same thing in the pow function instead seems to cause an error. Therefore, to be on the safe&#xD;&#xA;    	// side, and avoid as many bugs as possible, let's always be explicit about such things:&#xD;&#xA;    	//frag_colour.rgb = min(ambient_and_diffuse_colour + specular_colour, vec3(1.0f));&#xD;&#xA;    	frag_colour.rgb = vec3(1.0f) - exp(-exposure*(ambient_and_diffuse_colour + specular_colour + model_glow_colour));&#xD;&#xA;    	//frag_colour.rgb = texture(tex, v_tex_coord_pass_through).rgb;&#xD;&#xA;    	frag_colour = vec4(pow(frag_colour.rgb, vec3(reciprocal_gamma)), 1.0f);&#xD;&#xA;    &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The 3 ball textures (which are 2048 x 1024) are by Paul Bourke. http://paulbourke.net/geometry/spherical/&#xD;&#xA;The wallpaper texture in the background is from wallpaper flare. https://www.wallpaperflare.com/&#xD;&#xA;&#xD;&#xA;**EDIT**&#xD;&#xA;Here is the tennis ball texture:&#xD;&#xA;[![tennis ball texture][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My process for generating textures:&#xD;&#xA;&#xD;&#xA;1) Open the image in MS Paint.&#xD;&#xA;2) In the case of the wallpaper texture, crop out a 4096 x 4096 square.&#xD;&#xA;3) Save the file as a .bmp.&#xD;&#xA;4) My C code opens and reads the bitmap file, and makes it into a texture with internal format `GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM`.&#xD;&#xA;5) This is then written to the hard drive so that in future, the compressed version can be loadly directly instead of having to load the .bmp version and compress it.&#xD;&#xA;6) Set the MAG filter to `LINEAR`, and the MIN filter to `LINEAR_MIPMAP_LINEAR`.&#xD;&#xA;7) Ask for anistropic filtering using&#xD;&#xA;&#xD;&#xA;`glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_sample_limit);`,&#xD;&#xA;&#xD;&#xA;where the anisotropic_sample_limit was determined by passing `GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT` to `glGetFloatv`. In my case, it is 16.0.&#xD;&#xA;&#xD;&#xA;8) Ask OpenGL to generate the mipmaps using `glGenerateMipMap`.&#xD;&#xA;&#xD;&#xA;For antialising, I followed Joey de Vries learnopengl tutorial https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing on how to use MSAA. I am not using GLFW nor GLEW. Instead I am using glad https://glad.dav1d.de/ and I am using the Windows API directly in my C code (as far as I can tell).&#xD;&#xA;I tried but failed to persuade OpenGL / Windows to give me a multisampled default framebuffer. Instead I went with &quot;Off-screen MSAA&quot;. My antialising process is:&#xD;&#xA;&#xD;&#xA;1) Make a framebuffer and attach to it a multisampled colour buffer made like this (where I have set number_of_samples to 4):&#xD;&#xA;&#xD;&#xA;`glRenderbufferStorageMultisample(GL_RENDERBUFFER, number_of_samples, GL_RGBA8, window_width_pixels, window_height_pixels);`&#xD;&#xA;&#xD;&#xA;and a multisampled DEPTH / STENCIL buffer made like this:&#xD;&#xA;&#xD;&#xA;`glRenderbufferStorageMultisample(GL_RENDERBUFFER, number_of_samples, GL_DEPTH24_STENCIL8, window_width_pixels, window_height_pixels);`&#xD;&#xA;&#xD;&#xA;2) Call `glEnable(GL_MULTISAMPLE);`&#xD;&#xA;3) Before the animation loop, bind this framebuffer for reading.&#xD;&#xA;4) For each frame of the animation, bind that framebuffer for drawing, then draw on it (my shader program has no explicit antialising).&#xD;&#xA;5) Then bind the default framebuffer for drawing using&#xD;&#xA;`glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);`&#xD;&#xA;6) Blit my framebuffer to the default framebuffer using&#xD;&#xA;&#xD;&#xA;`glBlitFramebuffer(0, 0, window_width_pixels, window_height_pixels, 0, 0, window_width_pixels, window_height_pixels, GL_COLOR_BUFFER_BIT, GL_NEAREST);`&#xD;&#xA;&#xD;&#xA;7) Swap the buffers, and begin the animation loop again.&#xD;&#xA;&#xD;&#xA;I have tried the code on a different laptop, with a 4K screen and an Nvidia GPU as well as an integrated Intel one. With the integrated GPU on that laptop, both issues (the blockiness of the wavy line on the tennis ball, and the inconsistent antialiasing of the equatorial gradient on the balls) persist. With the Nvidia GPU, the wavy line on the tennis ball is perfectly correct, but the other problem persists.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Idea:**&#xD;&#xA;&#xD;&#xA;Is the problem with the inconsistent antialiasing of the equatorial gradient on the balls, due to the overhead directional light, dependent on the shininess of the balls ? Perhaps those that have a higher Blinn-Phong specular exponent and strength (which simply multiplies the specular contribution, and which I have set to be proportional to the specular exponent) have smoother gradients, because the function $\max(\cos^n \theta, 0)$ is smooth at 90 degrees, whereas the function $\max(\cos \theta, 0)$ has a corner (fails to be differentiable) at 90 degrees ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GDY9a.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/tMbbE.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39519" PostHistoryTypeId="2" PostId="13220" RevisionGUID="bc593399-a58e-4b29-9c7d-fc3f17f0a9ad" CreationDate="2023-01-16T19:14:16.697" UserId="445" Text="&gt; Why does the wavy white line on the tennis ball texture seem to be at the wrong mip level, with blocky artifacts ? &#xD;&#xA;&#xD;&#xA;I could be wrong, but those blocky artifacts look like compression artifacts, not aliasing artifacts. In particular, notice that the white center of the line appears smoother and of a more consistent width than the gray border. Try drawing the texture undistorted (i.e. on a quad) at different scales and with explicitly selected mip levels, to see if your mipmaps are correct and your texture compression is executing correctly.&#xD;&#xA;&#xD;&#xA;&gt; Why does the equatorial gradient between light and shade due to the overhead directional light source seem aliased in some cases, … Is MSAA able to detect such cases ? I thought it might be that MSAA only works on boundaries of triangles, …&#xD;&#xA;&#xD;&#xA;You are correct that MSAA _only_ affects boundaries. Your fragment shader is run only for each pixel of the output (within the bounds of the triangle drawn), not for each MSAA sample. (That's the entire difference between MSAA and SSAA.)&#xD;&#xA;&#xD;&#xA;So, any time you have a “corner” in the output of your fragment shader, you will see it as an aliased edge. You can see the same effect on the tennis ball in the bottom right, and just a little bit in the tennis ball on the center right (whose equator is _almost_ a horizontal line but not quite).&#xD;&#xA;&#xD;&#xA;The other balls do not display the same effect because your lighting is not producing a hard corner in those cases — formally, the _spatial frequency_ of the image content is low enough to not produce noticeable aliasing.&#xD;&#xA;&#xD;&#xA;You can solve this problem by modifying your shader to “round over” that hard corner and produce a gradient instead — conventional antialiasing is essentially making a 1-pixel-wide gradient, so as long as the lighting forms a gradient at least that wide, it will look “antialiased”.&#xD;&#xA;&#xD;&#xA;(I'm not well-versed in lighting model math to recommend a specific modification.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="39525" PostHistoryTypeId="2" PostId="13222" RevisionGUID="2da05965-3ee7-4053-b4c9-6c588686daf6" CreationDate="2023-01-17T01:41:03.103" UserId="19461" Text="I have a work thread function which updates the value of a float called scale:&#xD;&#xA;&#xD;&#xA;    	DWORD WINAPI WorkThreadFn(LPVOID lpParam)&#xD;&#xA;	{&#xD;&#xA;		MyWin* pWin = (MyWin*)lpParam;&#xD;&#xA;		while (pWin-&gt;running)&#xD;&#xA;		{&#xD;&#xA;			//pWin-&gt;scale = pWin-&gt;scale - 0.001;&#xD;&#xA;			pWin-&gt;scale = 0.5;&#xD;&#xA;			SendMessage(pWin-&gt;hwnd, WM_PAINT, NULL, NULL);&#xD;&#xA;			Sleep(1);&#xD;&#xA;		}&#xD;&#xA;		return 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;If I change the value of scale in this function, the WM_PAINT draws my triangle to the correct scale. But if I uncomment the section which increments the scale, then remove the line setting the scale, the scale of the triangle remains the same, despite the fact I can see from the window procedure that the value of scale is decreasing.&#xD;&#xA;&#xD;&#xA;Code for Window procedure:&#xD;&#xA;&#xD;&#xA;        LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)&#xD;&#xA;    {&#xD;&#xA;        PAINTSTRUCT ps;&#xD;&#xA;        HDC hdc;&#xD;&#xA;        MyWin* pThis = NULL;&#xD;&#xA;        if (uMsg == WM_CREATE)&#xD;&#xA;        {&#xD;&#xA;            CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;&#xD;&#xA;            pThis = (MyWin*)pCreate-&gt;lpCreateParams;&#xD;&#xA;            SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            pThis = (MyWin*)GetWindowLongPtr(hwnd, GWLP_USERDATA);&#xD;&#xA;        }&#xD;&#xA;    ..&#xD;&#xA;    switch(uMsg) {&#xD;&#xA;    case WM_PAINT:&#xD;&#xA;            hdc = BeginPaint(hwnd, &amp;ps);&#xD;&#xA;            RECT region = ps.rcPaint;&#xD;&#xA;            glClearColor(0.62, 0.3, 0.5, 1.0);&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;            pThis-&gt;glUniform1f(pThis-&gt;scaleLoc, pThis-&gt;scale);&#xD;&#xA;            &#xD;&#xA;            glBindVertexArray(vaNames[0]);&#xD;&#xA;            glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;&#xD;&#xA;            glBindVertexArray(0);&#xD;&#xA;            SwapBuffers(hdc);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And also here is the vertex shader code&#xD;&#xA;&#xD;&#xA;    in vec3 in_Position;&#xD;&#xA;    in vec3 in_Color;&#xD;&#xA;    out vec3 ex_Color;&#xD;&#xA;    &#xD;&#xA;    uniform float scale;&#xD;&#xA;    &#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vec4(in_Position * scale, 1.0);&#xD;&#xA;        ex_Color = in_Color;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;I'm sure I'm doing something stupid here, can anybody help?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39527" PostHistoryTypeId="1" PostId="13222" RevisionGUID="2da05965-3ee7-4053-b4c9-6c588686daf6" CreationDate="2023-01-17T01:41:03.103" UserId="19461" Text="Why does my uniform only update once?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39528" PostHistoryTypeId="3" PostId="13222" RevisionGUID="2da05965-3ee7-4053-b4c9-6c588686daf6" CreationDate="2023-01-17T01:41:03.103" UserId="19461" Text="|opengl|c++|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39529" PostHistoryTypeId="5" PostId="13222" RevisionGUID="045ae058-8313-409c-9743-1fdd5471597c" CreationDate="2023-01-17T02:03:27.647" UserId="19461" Comment="added 390 characters in body" Text="I have a work thread function which updates the value of a float called scale:&#xD;&#xA;&#xD;&#xA;    	DWORD WINAPI WorkThreadFn(LPVOID lpParam)&#xD;&#xA;	{&#xD;&#xA;		MyWin* pWin = (MyWin*)lpParam;&#xD;&#xA;		while (pWin-&gt;running)&#xD;&#xA;		{&#xD;&#xA;			//pWin-&gt;scale = pWin-&gt;scale - 0.001;&#xD;&#xA;			pWin-&gt;scale = 0.5;&#xD;&#xA;			SendMessage(pWin-&gt;hwnd, WM_PAINT, NULL, NULL);&#xD;&#xA;			Sleep(1);&#xD;&#xA;		}&#xD;&#xA;		return 0;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;If I change the value of scale in this function, the WM_PAINT draws my triangle to the correct scale. But if I uncomment the section which increments the scale, then remove the line setting the scale, the scale of the triangle remains the same, despite the fact I can see from the window procedure that the value of scale is decreasing.&#xD;&#xA;&#xD;&#xA;Code for Window procedure:&#xD;&#xA;&#xD;&#xA;        LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)&#xD;&#xA;    {&#xD;&#xA;        PAINTSTRUCT ps;&#xD;&#xA;        HDC hdc;&#xD;&#xA;        MyWin* pThis = NULL;&#xD;&#xA;        if (uMsg == WM_CREATE)&#xD;&#xA;        {&#xD;&#xA;            CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;&#xD;&#xA;            pThis = (MyWin*)pCreate-&gt;lpCreateParams;&#xD;&#xA;            SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            pThis = (MyWin*)GetWindowLongPtr(hwnd, GWLP_USERDATA);&#xD;&#xA;        }&#xD;&#xA;    ..&#xD;&#xA;    switch(uMsg) {&#xD;&#xA;    case WM_PAINT:&#xD;&#xA;            hdc = BeginPaint(hwnd, &amp;ps);&#xD;&#xA;            RECT region = ps.rcPaint;&#xD;&#xA;            glClearColor(0.62, 0.3, 0.5, 1.0);&#xD;&#xA;            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;            pThis-&gt;glUniform1f(pThis-&gt;scaleLoc, pThis-&gt;scale);&#xD;&#xA;            &#xD;&#xA;            glBindVertexArray(vaNames[0]);&#xD;&#xA;            glDrawArrays(GL_TRIANGLES, 0, 3);&#xD;&#xA;&#xD;&#xA;            glBindVertexArray(0);&#xD;&#xA;            SwapBuffers(hdc);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And also here is the vertex shader code&#xD;&#xA;&#xD;&#xA;    in vec3 in_Position;&#xD;&#xA;    in vec3 in_Color;&#xD;&#xA;    out vec3 ex_Color;&#xD;&#xA;    &#xD;&#xA;    uniform float scale;&#xD;&#xA;    &#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vec4(in_Position * scale, 1.0);&#xD;&#xA;        ex_Color = in_Color;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;I'm sure I'm doing something stupid here, can anybody help?&#xD;&#xA;&#xD;&#xA;Edit (forgot to add the main function):&#xD;&#xA;&#xD;&#xA;    int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)&#xD;&#xA;	{&#xD;&#xA;		MyWin win(hInstance, nCmdShow);&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;		DWORD ThreadID;&#xD;&#xA;		HANDLE hThread;&#xD;&#xA;		hThread = CreateThread(NULL, 0, WorkThreadFn, &amp;win, 0, &amp;ThreadID);&#xD;&#xA;&#xD;&#xA;		win.MsgLoop();&#xD;&#xA;&#xD;&#xA;		if (hThread != NULL)&#xD;&#xA;			CloseHandle(hThread);&#xD;&#xA;&#xD;&#xA;		return 0;&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="39530" PostHistoryTypeId="5" PostId="13215" RevisionGUID="bc9d2425-b627-4ff8-b3c1-7f6e150aebc4" CreationDate="2023-01-17T02:42:27.950" UserId="2654" Comment="added 30 characters in body" Text="What you are referring to is called a &quot;progressive JPEG&quot; file. This is a property of the way the file was compressed file which allows its decompression to be done in stages, such that a less-detailed version of the image can be shown despite not having the entire file. This technology was originally invented for the early Internet, allowing slow dial-up connections to be able to display something during the several seconds it took to download the entire image. As such, if you cut off the back-end of a progressive JPEG, you can still get some version of the image.&#xD;&#xA;&#xD;&#xA;So this is a property of the file, but it is *also* a property of the decompressor. Any JPEG decompressor can read a progressive JPEG file, but only those with special support can pull off the progressive display trick. And most decompressors don't bother these days. A JPEG decompressor with progressive support will likely have a special API for doing progressive JPEG decompression." ContentLicense="CC BY-SA 4.0" />
  <row Id="39531" PostHistoryTypeId="2" PostId="13223" RevisionGUID="aec92457-b18a-42cb-8c4f-02f06904efb4" CreationDate="2023-01-17T03:05:52.177" UserId="19461" Text="I can send WM_PAINT messages with SendMessage or PostMessage, but the window wont be redrawn. To redraw the window I have to call InvalidateRect or InvalidateRgn.&#xD;&#xA;&#xD;&#xA;My code still doesn't work great, because the window is being redrawn too quickly, so I need to find some way to time the redraw properly." ContentLicense="CC BY-SA 4.0" />
  <row Id="39533" PostHistoryTypeId="5" PostId="13223" RevisionGUID="b1964fb1-163c-48dc-9581-0928f9a76101" CreationDate="2023-01-17T05:16:25.283" UserId="19461" Comment="learned what was causing issues" Text="I can send WM_PAINT messages with SendMessage or PostMessage, but the window wont be redrawn. To redraw the window I have to call InvalidateRect or InvalidateRgn. You can also use RedrawWindow.&#xD;&#xA;&#xD;&#xA;In the end that wasn't the problem though. I was calling glViewport on WM_SIZE, which for some season unknown to me means that WM_PAINT wasn't being processed properly, but the window was drawing correctly during resizing.&#xD;&#xA;&#xD;&#xA;I also changed my message loop, to clear the message queue before redrawing the window, which also seems to speed things up a lot.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39537" PostHistoryTypeId="5" PostId="13223" RevisionGUID="f43c085d-ff3e-4214-a0b4-16c74dc9f475" CreationDate="2023-01-18T03:27:06.873" UserId="19461" Comment="learned what was causing issues in WM_SIZE" Text="I can send WM_PAINT messages with SendMessage or PostMessage, but the window wont be redrawn. To redraw the window I have to call InvalidateRect or InvalidateRgn. You can also use RedrawWindow.&#xD;&#xA;&#xD;&#xA;In the end that wasn't the problem though. I was calling glViewport on WM_SIZE, which for some season unknown to me means that WM_PAINT wasn't being processed properly, but the window was drawing correctly during resizing.&#xD;&#xA;&#xD;&#xA;I also changed my message loop, to clear the message queue before redrawing the window, which also seems to speed things up a lot.&#xD;&#xA;&#xD;&#xA;Edit: Ok, I know why glViewport in WM_SIZE was causing issues now. I wasn't returning 0 after processing that message, and MSDN docs mentions this. After making this change, it all works as expected.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39538" PostHistoryTypeId="2" PostId="13224" RevisionGUID="086c0dc5-f2e4-4eba-abf9-ad86dee3beaf" CreationDate="2023-01-18T05:12:31.317" UserId="15318" Text="I'm writing a software ray-tracer. I implemented a BVH structure and traverse algorithm, but when I use it I get missing triangles. These are the facts that I have:&#xD;&#xA;&#xD;&#xA;- Rendering without the BVH (naively iterating over all triangles) renders correctly&#xD;&#xA;- Replacing AABB test with `return true` renders correctly&#xD;&#xA;- Making bounding volumes ~5 times larger than they need to be renders correctly&#xD;&#xA;- Otherwise, rendering with BVH of any depth renders with missing triangles, more missing triangles the deeper the BVH&#xD;&#xA;&#xD;&#xA;This is the AABB test that I'm using: (derived from here: https://tavianator.com/2011/ray_box.html)&#xD;&#xA;&#xD;&#xA;```cs&#xD;&#xA;private static bool RayBoxIntersects(in Ray ray, in BoundingVolume bvh)&#xD;&#xA;{&#xD;&#xA;    float tx1 = (bvh.MinimumCoordinates.X - ray.Origin.X) * ray.Inverse.X;&#xD;&#xA;    float tx2 = (bvh.MaximumCoordinates.X - ray.Origin.X) * ray.Inverse.X;&#xD;&#xA;&#xD;&#xA;    float tmin = MathF.Min(tx1, tx2);&#xD;&#xA;    float tmax = MathF.Max(tx1, tx2);&#xD;&#xA;&#xD;&#xA;    float ty1 = (bvh.MinimumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y;&#xD;&#xA;    float ty2 = (bvh.MaximumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y;&#xD;&#xA;&#xD;&#xA;    tmin = MathF.Max(tmin, MathF.Min(ty1, ty2));&#xD;&#xA;    tmax = MathF.Min(tmax, MathF.Max(ty1, ty2));&#xD;&#xA;&#xD;&#xA;    float tz1 = (bvh.MinimumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z;&#xD;&#xA;    float tz2 = (bvh.MaximumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z;&#xD;&#xA;&#xD;&#xA;    tmin = MathF.Max(tmin, MathF.Min(tz1, tz2));&#xD;&#xA;    tmax = MathF.Min(tmax, MathF.Max(tz1, tz2));&#xD;&#xA;&#xD;&#xA;    return (tmax &gt;= MathF.Max(0f, tmin) &amp;&amp; tmin &lt; float.PositiveInfinity) || tmin == float.NaN || tmax == float.NaN;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;`Ray.Inverse` is defined as `new Vector3(1f / direction.X, 1f / direction.Y, 1f / direction.Z)`&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39540" PostHistoryTypeId="1" PostId="13224" RevisionGUID="086c0dc5-f2e4-4eba-abf9-ad86dee3beaf" CreationDate="2023-01-18T05:12:31.317" UserId="15318" Text="Missing triangles when rendering with BVH" ContentLicense="CC BY-SA 4.0" />
  <row Id="39541" PostHistoryTypeId="3" PostId="13224" RevisionGUID="086c0dc5-f2e4-4eba-abf9-ad86dee3beaf" CreationDate="2023-01-18T05:12:31.317" UserId="15318" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39547" PostHistoryTypeId="50" PostId="9116" RevisionGUID="4db038da-e237-4223-b11c-c861cd9600a1" CreationDate="2023-01-18T11:09:06.113" UserId="-1" />
  <row Id="39553" PostHistoryTypeId="5" PostId="13218" RevisionGUID="3f81041e-6e19-4db0-9cbc-3f53ecff3f85" CreationDate="2023-01-18T17:06:50.143" UserId="19286" Comment="added 227 characters in body" Text="Three.js is a lightweight cross-browser JavaScript library/API used to create and display animated 3D computer graphics on a Web browser. Three.js scripts may be used in conjunction with the HTML5 canvas element, SVG or WebGL. " ContentLicense="CC BY-SA 4.0" />
  <row Id="39554" PostHistoryTypeId="24" PostId="13218" RevisionGUID="3f81041e-6e19-4db0-9cbc-3f53ecff3f85" CreationDate="2023-01-18T17:06:50.143" Comment="Proposed by 19286 approved by 13095 edit id of 611" ContentLicense="CC BY-SA 4.0" />
  <row Id="39555" PostHistoryTypeId="5" PostId="13224" RevisionGUID="0aa1742e-18b4-480d-9249-51ba76f905e3" CreationDate="2023-01-18T17:55:49.450" UserId="15318" Comment="added 201 characters in body" Text="I'm writing a software ray-tracer. I implemented a BVH structure and traverse algorithm, but when I use it I get missing triangles. These are the facts that I have:&#xD;&#xA;&#xD;&#xA;- Rendering without the BVH (naively iterating over all triangles) renders correctly&#xD;&#xA;- Replacing AABB test with `return true` renders correctly&#xD;&#xA;- Making bounding volumes ~5 times larger than they need to be renders correctly&#xD;&#xA;- Otherwise, rendering with BVH of any depth renders with missing triangles, more missing triangles the deeper the BVH&#xD;&#xA;- Replacing below AABB test with an actual geometry test (testing against actual triangle bounding boxes) also render missing triangles&#xD;&#xA;&#xD;&#xA;This is the AABB test that I'm using: (derived from here: https://tavianator.com/2011/ray_box.html)&#xD;&#xA;&#xD;&#xA;```cs&#xD;&#xA;private static bool RayBoxIntersects(in Ray ray, in BoundingVolume bvh)&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;    // return true // if I uncomment this, renders correctly&#xD;&#xA;    float tx1 = (bvh.MinimumCoordinates.X - ray.Origin.X) * ray.Inverse.X;&#xD;&#xA;    float tx2 = (bvh.MaximumCoordinates.X - ray.Origin.X) * ray.Inverse.X;&#xD;&#xA;&#xD;&#xA;    float tmin = MathF.Min(tx1, tx2);&#xD;&#xA;    float tmax = MathF.Max(tx1, tx2);&#xD;&#xA;&#xD;&#xA;    float ty1 = (bvh.MinimumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y;&#xD;&#xA;    float ty2 = (bvh.MaximumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y;&#xD;&#xA;&#xD;&#xA;    tmin = MathF.Max(tmin, MathF.Min(ty1, ty2));&#xD;&#xA;    tmax = MathF.Min(tmax, MathF.Max(ty1, ty2));&#xD;&#xA;&#xD;&#xA;    float tz1 = (bvh.MinimumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z;&#xD;&#xA;    float tz2 = (bvh.MaximumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z;&#xD;&#xA;&#xD;&#xA;    tmin = MathF.Max(tmin, MathF.Min(tz1, tz2));&#xD;&#xA;    tmax = MathF.Min(tmax, MathF.Max(tz1, tz2));&#xD;&#xA;&#xD;&#xA;    return (tmax &gt;= MathF.Max(0f, tmin) &amp;&amp; tmin &lt; float.PositiveInfinity) || tmin == float.NaN || tmax == float.NaN;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;`Ray.Inverse` is defined as `new Vector3(1f / direction.X, 1f / direction.Y, 1f / direction.Z)`&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39556" PostHistoryTypeId="5" PostId="13205" RevisionGUID="71090736-f440-45a6-ae09-d1b9b36ba381" CreationDate="2023-01-18T19:15:14.327" UserId="6114" Comment="added 118 characters in body" Text="Looks like the boundary of the integration changes to positive m.n and so you drop the Heaviside fnc to reflect that. (Actually a sample for m.n&lt;0 is not a valid sample, you ain't taking its value at all but just discard it.. meaning in code it's an if() before the actual sampling routine).&#xD;&#xA;&#xD;&#xA;Ie. something like this :&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The 2|i.m|m-i is actually 2(i.m)m-i (Walter is writing it like that in ie. Notes on the Ward BRDF).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zMHZ5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39558" PostHistoryTypeId="2" PostId="13227" RevisionGUID="3485eb1f-f820-4e0e-a030-d5c6947d6e8a" CreationDate="2023-01-19T10:53:33.477" UserId="13273" Text="In the discussion [Here][1] there was said, that discarding faces during Tessellation stage should be avoided. What are the reasons for that?&#xD;&#xA;&#xD;&#xA;Right now, I am rendering a 3D geometry using Vertex, Tessellation and Fragment shader. Some of the faces should be and some should not be rendered, changing from frame to frame.&#xD;&#xA;My Tessellation Evaluation shader is quite complex and a big performance drop when all faces are calculated. So my idea was to discard faces before executing the Tessellation Evaluation stage by setting `gl_TessLevelOuter` and `gl_TessLevelInner` values to zero. This works very well and my performance seems to be good.&#xD;&#xA;&#xD;&#xA;Sure, it is easy to discard fragments during Fragment shader stage but then, the performance dropping calculations are done.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/13199/how-to-instanced-and-indirect-render-geometry-opengl" ContentLicense="CC BY-SA 4.0" />
  <row Id="39560" PostHistoryTypeId="1" PostId="13227" RevisionGUID="3485eb1f-f820-4e0e-a030-d5c6947d6e8a" CreationDate="2023-01-19T10:53:33.477" UserId="13273" Text="Why shouldn't I discard faces during Tessellation control stage" ContentLicense="CC BY-SA 4.0" />
  <row Id="39561" PostHistoryTypeId="3" PostId="13227" RevisionGUID="3485eb1f-f820-4e0e-a030-d5c6947d6e8a" CreationDate="2023-01-19T10:53:33.477" UserId="13273" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39562" PostHistoryTypeId="2" PostId="13228" RevisionGUID="ad91245a-d9cd-4142-87b4-add0a42e9062" CreationDate="2023-01-19T13:20:27.347" UserId="19286" Text="I know that Three.js prepends the shader text you provide with some code that includes definitions etc. I am not a big fan of &quot;magic&quot; and I would like to be able to see the final text content of the shader(s) that Three.js actually uses.&#xD;&#xA;&#xD;&#xA;I have seen that in earlier releases of Three.js, if there was en error in a shader file (either the vertex shader of the fragment shader), the whole text content of the shader was logged in console, including all the **prepended code** by Three.js. &#xD;&#xA;&#xD;&#xA;I am currently using **r148** and in case of an error, only the line(s) containing the error(s) gets logged in console. &#xD;&#xA;&#xD;&#xA;Has the functionality of logging the whole shader file in console been removed or is there any way to enable it? Or, more generally, is there any other way to access the actual text content of each of the shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39564" PostHistoryTypeId="1" PostId="13228" RevisionGUID="ad91245a-d9cd-4142-87b4-add0a42e9062" CreationDate="2023-01-19T13:20:27.347" UserId="19286" Text="How can I see the whole shader's text content, with all the prepended code by Three.js, when using ShaderMaterial or RawShaderMaterial (r148)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39565" PostHistoryTypeId="3" PostId="13228" RevisionGUID="ad91245a-d9cd-4142-87b4-add0a42e9062" CreationDate="2023-01-19T13:20:27.347" UserId="19286" Text="|shader|fragment-shader|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39566" PostHistoryTypeId="2" PostId="13229" RevisionGUID="fce76244-72f8-489b-823c-511e83e91c25" CreationDate="2023-01-19T15:04:00.370" UserId="2654" Text="The full and complete statement you are responding to is:&#xD;&#xA;&#xD;&#xA;&gt; Never use tessellation for anything other than *tessellation*. Don't use it as a fancy way to discard vertices.&#xD;&#xA;&#xD;&#xA;The algorithm you have described is actually *doing* tessellation. As a consequence of that tessellation process, you are able to discard some patches before tessellating them. But that's a consequence of doing tessellation.&#xD;&#xA;&#xD;&#xA;The point of the statement is to keep you from just shoving a tessellation shader into the middle of your pipeline for the sole purpose of discarding faces." ContentLicense="CC BY-SA 4.0" />
  <row Id="39568" PostHistoryTypeId="50" PostId="9781" RevisionGUID="998f79e5-a524-442f-8bee-34095ac7fc25" CreationDate="2023-01-19T21:07:50.873" UserId="-1" />
  <row Id="39569" PostHistoryTypeId="50" PostId="10177" RevisionGUID="9821bc2d-d50e-43ca-bbdc-b7fab6fe3e57" CreationDate="2023-01-20T06:02:10.243" UserId="-1" />
  <row Id="39571" PostHistoryTypeId="5" PostId="13217" RevisionGUID="cbce673b-e525-4dc0-b968-d8c19d654434" CreationDate="2023-01-20T14:51:03.470" UserId="19286" Comment="added 4226 characters in body" Text="Three.js allows the creation of GPU-accelerated 3D animations using the JavaScript language as part of a website without relying on proprietary browser plugins. This is possible thanks to the advent of WebGL.&#xD;&#xA;&#xD;&#xA;**Features**&#xD;&#xA;&#xD;&#xA;&gt; Three.js includes the following features:&#xD;&#xA;&gt;&#xD;&#xA;&gt; * **Renderers:** [WebGL][1], WebGPU (experimental), [SVG][2], CSS2D and CSS3D renderers.&#xD;&#xA;&gt; * **Effects:** Anaglyph, ASCII, outline, parallax barrier, stereo and peppers ghost.&#xD;&#xA;&gt; * **Scenes:** add and remove objects at run-time, fog, background, environment&#xD;&#xA;&gt; * **Cameras:** perspective, orthographic and stereo&#xD;&#xA;&gt; * **Controllers:** orbit, trackball, FPS, fly and more&#xD;&#xA;&gt; * **Animation:** armatures, forward kinematics, inverse kinematics, morph and keyframe&#xD;&#xA;&gt; * **Lights:** ambient, hemisphere, area, directional, point, spot lights and light probes&#xD;&#xA;&gt; * **Shadows:** cast and receive&#xD;&#xA;&gt; * **Materials:** [PBR][3], Phong, Lambert, Toon, Matcap, Unlit and more&#xD;&#xA;&gt; * **Shaders:** access to full [OpenGL Shading Language][4] (GLSL)&#xD;&#xA;&gt; * **Capabilities:** lens flare, depth pass and extensive post-processing library&#xD;&#xA;&gt; * **Objects:** meshes, instanced mesh, point clouds, lines, sprites, ribbons, bones and more&#xD;&#xA;&gt; * **Geometry:** plane, cube, sphere, torus, 3D text and more&#xD;&#xA;&gt; * **Modifiers:** curve, edge split, simplify and tessellate&#xD;&#xA;&gt; * **Data loaders:** binary, image, JSON and scene&#xD;&#xA;&gt; * **Utilities:** full set of time and 3D math functions&#xD;&#xA;&gt; * including frustum, matrix, quaternion and more&#xD;&#xA;&gt; * **Support:** API documentation, public forum, chat and wiki in full operation&#xD;&#xA;&gt; * **Examples:** Over 350 files of coding examples plus fonts, models, textures, sounds and other support files&#xD;&#xA;&gt; * **Debugging:** Stats.js, Three.js Developer Tools&#xD;&#xA;&#xD;&#xA;Three.js runs in all browsers supported by WebGL.&#xD;&#xA;&#xD;&#xA;It was first released by [Ricardo Cabello (mrdoob)][5] to GitHub in April 2010 and is made available under the MIT license.&#xD;&#xA;&#xD;&#xA; **Example Code:**&#xD;&#xA;&#xD;&#xA;Renders an animated cube.&#xD;&#xA;&#xD;&#xA;&lt;!-- language: lang-html --&gt;&#xD;&#xA;&#xD;&#xA;    &lt;html&gt;&#xD;&#xA;      &lt;head&gt;&#xD;&#xA;        &lt;title&gt;My first Three.js app&lt;/title&gt;&#xD;&#xA;        &lt;style&gt;&#xD;&#xA;          body {&#xD;&#xA;            margin: 0;&#xD;&#xA;          }&#xD;&#xA;        &lt;/style&gt;&#xD;&#xA;      &lt;/head&gt;&#xD;&#xA;      &lt;body&gt;&#xD;&#xA;        &lt;script src=&quot;three.min.js&quot;&gt;&lt;/script&gt;&#xD;&#xA;        &lt;script&gt;&#xD;&#xA;          let camera, scene, renderer;&#xD;&#xA;          let geometry, material, mesh;&#xD;&#xA;&#xD;&#xA;          init();&#xD;&#xA;          animate();&#xD;&#xA;&#xD;&#xA;          function init() {&#xD;&#xA;&#xD;&#xA;            camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );&#xD;&#xA;            camera.position.z = 1;&#xD;&#xA;&#xD;&#xA;            scene = new THREE.Scene();&#xD;&#xA;&#xD;&#xA;            geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );&#xD;&#xA;            material = new THREE.MeshNormalMaterial();&#xD;&#xA;&#xD;&#xA;            mesh = new THREE.Mesh( geometry, material );&#xD;&#xA;            scene.add( mesh );&#xD;&#xA;&#xD;&#xA;            renderer = new THREE.WebGLRenderer( { antialias: true } );&#xD;&#xA;            renderer.setSize( window.innerWidth, window.innerHeight );&#xD;&#xA;            document.body.appendChild( renderer.domElement );&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;          function animate() {&#xD;&#xA;&#xD;&#xA;            requestAnimationFrame( animate );&#xD;&#xA;&#xD;&#xA;            mesh.rotation.x += 0.01;&#xD;&#xA;            mesh.rotation.y += 0.02;&#xD;&#xA;&#xD;&#xA;            renderer.render( scene, camera );&#xD;&#xA;          }&#xD;&#xA;&#xD;&#xA;        &lt;/script&gt;&#xD;&#xA;      &lt;/body&gt;&#xD;&#xA;    &lt;/html&gt;&#xD;&#xA;&#xD;&#xA;**Useful links:**&#xD;&#xA;&#xD;&#xA; - [Threejs.org][6]&#xD;&#xA; - [Documentation][7]&#xD;&#xA; - [Forum][8]&#xD;&#xA; - [GitHub repository][9]&#xD;&#xA; - [Examples][10]&#xD;&#xA; - [Wikipedia entry][11]&#xD;&#xA; - [Download][12]&#xD;&#xA; - [Books][13]&#xD;&#xA; - [WebGL][14]&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/WebGL&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Physically_based_rendering&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/OpenGL_Shading_Language&#xD;&#xA;  [5]: http://mrdoob.com/&#xD;&#xA;  [6]: http://threejs.org&#xD;&#xA;  [7]: http://threejs.org/docs&#xD;&#xA;  [8]: https://discourse.threejs.org/&#xD;&#xA;  [9]: https://github.com/mrdoob/three.js/&#xD;&#xA;  [10]: http://threejs.org/examples/&#xD;&#xA;  [11]: http://en.wikipedia.org/wiki/Threejs&#xD;&#xA;  [12]: http://github.com/mrdoob/three.js/zipball/master&#xD;&#xA;  [13]: https://www.packtpub.com/web-development/learning-threejs-javascript-3d-library-webgl-second-edition&#xD;&#xA;  [14]: http://shop.oreilly.com/product/0636920024729.do&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39572" PostHistoryTypeId="24" PostId="13217" RevisionGUID="cbce673b-e525-4dc0-b968-d8c19d654434" CreationDate="2023-01-20T14:51:03.470" Comment="Proposed by 19286 approved by 482 edit id of 610" ContentLicense="CC BY-SA 4.0" />
  <row Id="39573" PostHistoryTypeId="2" PostId="13230" RevisionGUID="ebecb9db-9bd0-4a88-8d92-652d730024ff" CreationDate="2023-01-20T18:07:19.187" UserId="445" Text="Others have interpreted your question as being about “progressive JPEG”, but “line by line from top to bottom” is _not_ how progressive JPEG appears. Progressive JPEG organizes the data in the file so that low-detail data (the average color of 8×8 blocks) is stored before the data required for higher detail. A slowly loading progressive JPEG will appear as a blocky image which then fills in with more detail. If the image is appearing gradually from top to bottom, then that is a _non_-progressive (“baseline”) JPEG image.&#xD;&#xA;&#xD;&#xA;**Both types of JPEG _can_ be decoded incrementally,** and that is what web browsers do. The reason you are seeing failures is because libraries for loading files of any format, not just JPEG, are _often_ **not designed to be able to perform loading of partial data.**&#xD;&#xA;&#xD;&#xA;The majority of applications for image decoding are loading from local disk, and are often non-interactive, so partial data loading is not a helpful feature for them. Furthermore, it is not uncommon for files to be unintentionally truncated (e.g. because a download or copy failed partway through), and in that case it is preferable to report an error (so that the application using the library can know the file is damaged) than to continue with an image missing data. (Of course, recovering what you can from damaged files is _also_ a useful feature — but also not a common requirement.)&#xD;&#xA;&#xD;&#xA;And, if a library does support loading partial data, it will almost certainly expect you to provide the data by some kind of streaming interface, rather than a truncated input (which would imply re-decoding the beginning of the file every time more data is available).&#xD;&#xA;&#xD;&#xA;To solve your problem, you will need to find a library that does support incremental decoding, and use it in the appropriate fashion — or add support for it to an existing library, or write your own." ContentLicense="CC BY-SA 4.0" />
  <row Id="39575" PostHistoryTypeId="50" PostId="13172" RevisionGUID="6a3a4174-3039-4d6d-95ce-b62072599cc2" CreationDate="2023-01-20T19:04:45.550" UserId="-1" />
  <row Id="39576" PostHistoryTypeId="5" PostId="13224" RevisionGUID="131707fd-343f-4251-b010-3ce1d2461c2f" CreationDate="2023-01-20T20:37:52.657" UserId="15318" Comment="added 19 characters in body" Text="I'm writing a software ray-tracer. I implemented a BVH structure (octree, actually) and traverse algorithm, but when I use it I get missing triangles. These are the facts that I have:&#xD;&#xA;&#xD;&#xA;- Rendering without the BVH (naively iterating over all triangles) renders correctly&#xD;&#xA;- Replacing AABB test with `return true` renders correctly&#xD;&#xA;- Making bounding volumes ~5 times larger than they need to be renders correctly&#xD;&#xA;- Otherwise, rendering with BVH of any depth renders with missing triangles, more missing triangles the deeper the BVH&#xD;&#xA;- Replacing below AABB test with an actual geometry test (testing against actual triangle bounding boxes) also render missing triangles&#xD;&#xA;&#xD;&#xA;This is the AABB test that I'm using: (derived from here: https://tavianator.com/2011/ray_box.html)&#xD;&#xA;&#xD;&#xA;```cs&#xD;&#xA;private static bool RayBoxIntersects(in Ray ray, in BoundingVolume bvh)&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;    // return true // if I uncomment this, renders correctly&#xD;&#xA;    float tx1 = (bvh.MinimumCoordinates.X - ray.Origin.X) * ray.Inverse.X;&#xD;&#xA;    float tx2 = (bvh.MaximumCoordinates.X - ray.Origin.X) * ray.Inverse.X;&#xD;&#xA;&#xD;&#xA;    float tmin = MathF.Min(tx1, tx2);&#xD;&#xA;    float tmax = MathF.Max(tx1, tx2);&#xD;&#xA;&#xD;&#xA;    float ty1 = (bvh.MinimumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y;&#xD;&#xA;    float ty2 = (bvh.MaximumCoordinates.Y - ray.Origin.Y) * ray.Inverse.Y;&#xD;&#xA;&#xD;&#xA;    tmin = MathF.Max(tmin, MathF.Min(ty1, ty2));&#xD;&#xA;    tmax = MathF.Min(tmax, MathF.Max(ty1, ty2));&#xD;&#xA;&#xD;&#xA;    float tz1 = (bvh.MinimumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z;&#xD;&#xA;    float tz2 = (bvh.MaximumCoordinates.Z - ray.Origin.Z) * ray.Inverse.Z;&#xD;&#xA;&#xD;&#xA;    tmin = MathF.Max(tmin, MathF.Min(tz1, tz2));&#xD;&#xA;    tmax = MathF.Min(tmax, MathF.Max(tz1, tz2));&#xD;&#xA;&#xD;&#xA;    return (tmax &gt;= MathF.Max(0f, tmin) &amp;&amp; tmin &lt; float.PositiveInfinity) || tmin == float.NaN || tmax == float.NaN;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;`Ray.Inverse` is defined as `new Vector3(1f / direction.X, 1f / direction.Y, 1f / direction.Z)`&#xD;&#xA;&#xD;&#xA;What could I be doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39590" PostHistoryTypeId="2" PostId="13233" RevisionGUID="c4e2fcaa-b7fd-4938-96a0-0cf185f05da4" CreationDate="2023-01-21T17:48:02.443" UserId="19476" Text="I have a set of points, which I triangulate to a Delaunay graph to make a mesh.&#xD;&#xA;&#xD;&#xA;Every mesh vertex has a unique colour, and I can render it without any problem. But I want Voronoi rendering to be possible too. Ideally, I want to make a shader which computes the distance from every vertex, and colours the vertex fragments with the colour of the nearest vertex, but somehow I get the wrong result.&#xD;&#xA;&#xD;&#xA;This is the GLSL shader I'm using:&#xD;&#xA;&#xD;&#xA;Vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;&#xD;&#xA;    layout (location=0) in vec2 position;&#xD;&#xA;    layout (location=1) in vec3 inColour;&#xD;&#xA;    &#xD;&#xA;    flat out vec3 col_in;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    &#xD;&#xA;        col_in = inColour;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Geometry:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout (triangles) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 3) out;&#xD;&#xA;    &#xD;&#xA;    uniform vec2 window_size;&#xD;&#xA;    &#xD;&#xA;    flat in vec3 col_in[];&#xD;&#xA;    &#xD;&#xA;    out vec4 vertex_a;&#xD;&#xA;    out vec4 vertex_b;&#xD;&#xA;    out vec4 vertex_c;&#xD;&#xA;    &#xD;&#xA;    flat out vec3 colour_a;&#xD;&#xA;    flat out vec3 colour_b;&#xD;&#xA;    flat out vec3 colour_c;&#xD;&#xA;    &#xD;&#xA;    void main() {    &#xD;&#xA;        vertex_a = (gl_in[0].gl_Position);&#xD;&#xA;        vertex_b = (gl_in[1].gl_Position);&#xD;&#xA;        vertex_c = (gl_in[2].gl_Position);&#xD;&#xA;    &#xD;&#xA;        gl_Position = vertex_a; &#xD;&#xA;        colour_a = col_in[0];&#xD;&#xA;        EmitVertex();&#xD;&#xA;    &#xD;&#xA;        gl_Position = vertex_b;&#xD;&#xA;        colour_b = col_in[1];&#xD;&#xA;        EmitVertex();&#xD;&#xA;    &#xD;&#xA;        gl_Position = vertex_c;&#xD;&#xA;        colour_c = col_in[2];&#xD;&#xA;        EmitVertex();&#xD;&#xA;        &#xD;&#xA;        EndPrimitive();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;Fragment:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    &#xD;&#xA;    uniform vec2 window_size;&#xD;&#xA;    &#xD;&#xA;    in vec4 vertex_a;&#xD;&#xA;    in vec4 vertex_b;&#xD;&#xA;    in vec4 vertex_c;&#xD;&#xA;    &#xD;&#xA;    flat in vec3 colour_a;&#xD;&#xA;    flat in vec3 colour_b;&#xD;&#xA;    flat in vec3 colour_c;&#xD;&#xA;    &#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {   &#xD;&#xA;        vec2 uv = (gl_FragCoord.xy / window_size) - vec2(0.5);&#xD;&#xA;    &#xD;&#xA;        float da = distance(vertex_a * 0.5, vec4(uv, 0.0, 0.0));&#xD;&#xA;        float db = distance(vertex_b * 0.5, vec4(uv, 0.0, 0.0));&#xD;&#xA;        float dc = distance(vertex_c * 0.5, vec4(uv, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;        if(da &lt; db &amp;&amp; da &lt; dc){&#xD;&#xA;            fragColor = vec4(colour_a, 1.0);&#xD;&#xA;        } else if (db &lt; da &amp;&amp; db &lt; dc){&#xD;&#xA;            fragColor = vec4(colour_b, 1.0);&#xD;&#xA;        } else if(dc &lt; da &amp;&amp; dc &lt; db) {&#xD;&#xA;            fragColor = vec4(colour_c, 1.0);&#xD;&#xA;        } else {&#xD;&#xA;            fragColor = vec4(1.0);&#xD;&#xA;        }&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;This is the result:&#xD;&#xA;&#xD;&#xA;[![Result][1]][1]&#xD;&#xA;&#xD;&#xA;Wireframe:&#xD;&#xA;&#xD;&#xA;[![Result - Wireframe rendered][2]][2]&#xD;&#xA;&#xD;&#xA;**My question is: why is my result not a Voronoi diagram? Does it depend on the shader, or maybe the triangulation is wrong?&#xD;&#xA;Is this the best way to do this? If not, what should I do?**&#xD;&#xA;&#xD;&#xA;Thanks.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GEMgV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hE6fZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39592" PostHistoryTypeId="1" PostId="13233" RevisionGUID="c4e2fcaa-b7fd-4938-96a0-0cf185f05da4" CreationDate="2023-01-21T17:48:02.443" UserId="19476" Text="Best way for rendering Voronoi diagram from Delaunay graph mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="39593" PostHistoryTypeId="3" PostId="13233" RevisionGUID="c4e2fcaa-b7fd-4938-96a0-0cf185f05da4" CreationDate="2023-01-21T17:48:02.443" UserId="19476" Text="|opengl|shader|glsl|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39594" PostHistoryTypeId="5" PostId="13233" RevisionGUID="7c492d7f-e6c6-47be-a635-988d862025b1" CreationDate="2023-01-21T19:27:07.943" UserId="2654" Comment="deleted 15 characters in body" Text="I have a set of points, which I triangulate to a Delaunay graph to make a mesh.&#xD;&#xA;&#xD;&#xA;Every mesh vertex has a unique colour, and I can render it without any problem. But I want Voronoi rendering to be possible too. Ideally, I want to make a shader which computes the distance from every vertex, and colours the vertex fragments with the colour of the nearest vertex, but somehow I get the wrong result.&#xD;&#xA;&#xD;&#xA;This is the GLSL shader I'm using:&#xD;&#xA;&#xD;&#xA;Vertex:&#xD;&#xA;&#xD;&#xA;    #version 330&#xD;&#xA;&#xD;&#xA;    layout (location=0) in vec2 position;&#xD;&#xA;    layout (location=1) in vec3 inColour;&#xD;&#xA;    &#xD;&#xA;    flat out vec3 col_in;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_Position = vec4(position, 0.0, 1.0);&#xD;&#xA;    &#xD;&#xA;        col_in = inColour;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Geometry:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout (triangles) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 3) out;&#xD;&#xA;    &#xD;&#xA;    uniform vec2 window_size;&#xD;&#xA;    &#xD;&#xA;    flat in vec3 col_in[];&#xD;&#xA;    &#xD;&#xA;    out vec4 vertex_a;&#xD;&#xA;    out vec4 vertex_b;&#xD;&#xA;    out vec4 vertex_c;&#xD;&#xA;    &#xD;&#xA;    flat out vec3 colour_a;&#xD;&#xA;    flat out vec3 colour_b;&#xD;&#xA;    flat out vec3 colour_c;&#xD;&#xA;    &#xD;&#xA;    void main() {    &#xD;&#xA;        vertex_a = (gl_in[0].gl_Position);&#xD;&#xA;        vertex_b = (gl_in[1].gl_Position);&#xD;&#xA;        vertex_c = (gl_in[2].gl_Position);&#xD;&#xA;    &#xD;&#xA;        gl_Position = vertex_a; &#xD;&#xA;        colour_a = col_in[0];&#xD;&#xA;        EmitVertex();&#xD;&#xA;    &#xD;&#xA;        gl_Position = vertex_b;&#xD;&#xA;        colour_b = col_in[1];&#xD;&#xA;        EmitVertex();&#xD;&#xA;    &#xD;&#xA;        gl_Position = vertex_c;&#xD;&#xA;        colour_c = col_in[2];&#xD;&#xA;        EmitVertex();&#xD;&#xA;        &#xD;&#xA;        EndPrimitive();&#xD;&#xA;    } &#xD;&#xA;&#xD;&#xA;Fragment:&#xD;&#xA;&#xD;&#xA;    #version 330 core&#xD;&#xA;    &#xD;&#xA;    uniform vec2 window_size;&#xD;&#xA;    &#xD;&#xA;    in vec4 vertex_a;&#xD;&#xA;    in vec4 vertex_b;&#xD;&#xA;    in vec4 vertex_c;&#xD;&#xA;    &#xD;&#xA;    flat in vec3 colour_a;&#xD;&#xA;    flat in vec3 colour_b;&#xD;&#xA;    flat in vec3 colour_c;&#xD;&#xA;    &#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {   &#xD;&#xA;        vec2 uv = (gl_FragCoord.xy / window_size) - vec2(0.5);&#xD;&#xA;    &#xD;&#xA;        float da = distance(vertex_a * 0.5, vec4(uv, 0.0, 0.0));&#xD;&#xA;        float db = distance(vertex_b * 0.5, vec4(uv, 0.0, 0.0));&#xD;&#xA;        float dc = distance(vertex_c * 0.5, vec4(uv, 0.0, 0.0));&#xD;&#xA;    &#xD;&#xA;        if(da &lt; db &amp;&amp; da &lt; dc){&#xD;&#xA;            fragColor = vec4(colour_a, 1.0);&#xD;&#xA;        } else if (db &lt; da &amp;&amp; db &lt; dc){&#xD;&#xA;            fragColor = vec4(colour_b, 1.0);&#xD;&#xA;        } else if(dc &lt; da &amp;&amp; dc &lt; db) {&#xD;&#xA;            fragColor = vec4(colour_c, 1.0);&#xD;&#xA;        } else {&#xD;&#xA;            fragColor = vec4(1.0);&#xD;&#xA;        }&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;This is the result:&#xD;&#xA;&#xD;&#xA;[![Result][1]][1]&#xD;&#xA;&#xD;&#xA;Wireframe:&#xD;&#xA;&#xD;&#xA;[![Result - Wireframe rendered][2]][2]&#xD;&#xA;&#xD;&#xA;My question is: why is my result not a Voronoi diagram? Does it depend on the shader, or maybe the triangulation is wrong?&#xD;&#xA;Is this the best way to do this? If not, what should I do?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GEMgV.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/hE6fZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39595" PostHistoryTypeId="2" PostId="13234" RevisionGUID="f31c67ee-f3df-4aaa-9753-0997a447fc2b" CreationDate="2023-01-21T19:33:15.390" UserId="2654" Text="Your geometry shader is broken. Every time you do `EmitVertex`, all of the `out` variables acquire unspecified values (ie: implementations aren't required to preserve those values). So you must reset them for every vertex.&#xD;&#xA;&#xD;&#xA;That being said, your algorithm is unnecessarily complex. It'd be way easier to just let your GPU's depth test do it. For each vertex in your triangulation, draw a cone with the vertex (in 2D) where the tip of the cone is, and with the tip pointing into the camera using an orthographic projection. The cones need to be pretty wide. Each cone should have its own color.&#xD;&#xA;&#xD;&#xA;Where two cones intersect will define the place where two vertices are equal-distances to each other." ContentLicense="CC BY-SA 4.0" />
  <row Id="39597" PostHistoryTypeId="2" PostId="13235" RevisionGUID="135a6ba9-6059-471d-8097-17f23462b193" CreationDate="2023-01-21T21:05:06.080" UserId="19477" Text="The hand written one must be quite wrong. The `-2` and `Z` got messed up. It should be `-2 Zfar Znear`, not `-Zfar...` with a Z without dash. In the field above, `Zfar` is alone, it should be `Zfar + Znear`.&#xD;&#xA;&#xD;&#xA;Apart from these typos I prefer it - it has an aspect ratio and no extra minus signs to flip axes. Well it is column-major, but that is OK.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39599" PostHistoryTypeId="52" PostId="13233" RevisionGUID="504ce4c1-f6d0-42cd-a174-dd7bb397df96" CreationDate="2023-01-22T01:48:11.270" />
  <row Id="39600" PostHistoryTypeId="2" PostId="13236" RevisionGUID="b498848a-bd50-4ae4-8af1-1e1e6c05c971" CreationDate="2023-01-22T06:06:26.040" UserId="6496" Text="I am working on the port of a demo from DXR to Vulkan Ray Tracing extension using GLSL.&#xD;&#xA;In DXR/HLSL space, there are *RayTMin()* and R*ayTCurrent()* functions to retrieve the starting and the current end point of the ray  (*Origin + (Direction * RayTMin)* and  *Origin + (Direction * RayTCurrent)*, respectively).&#xD;&#xA;In Vulkan RT/GLSL space, one specifies the **tMin** and **tMax** values in the  *traceRayEXT(...)* call, but how does one retrieve the &quot;**current t**&quot; and &quot;**t min**&quot; values in an intersection shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39602" PostHistoryTypeId="1" PostId="13236" RevisionGUID="b498848a-bd50-4ae4-8af1-1e1e6c05c971" CreationDate="2023-01-22T06:06:26.040" UserId="6496" Text="Porting from DXR/HLSL to Vulkan Ray Tracing Extension/GLSL" ContentLicense="CC BY-SA 4.0" />
  <row Id="39603" PostHistoryTypeId="3" PostId="13236" RevisionGUID="b498848a-bd50-4ae4-8af1-1e1e6c05c971" CreationDate="2023-01-22T06:06:26.040" UserId="6496" Text="|raytracing|glsl|vulkan|hlsl|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39604" PostHistoryTypeId="2" PostId="13237" RevisionGUID="7fe413cc-94e5-4e23-b648-600fd915eb70" CreationDate="2023-01-22T10:27:12.310" UserId="6496" Text="According to this [document][1], one should be able to extract those values through&#xD;&#xA;*gl_RayTminEXT* and *gl_RayTmaxEXT* **GLSL** built-ins for intersection shader.&#xD;&#xA;&#xD;&#xA;Further comments are welcome.&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_ray_tracing.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="39608" PostHistoryTypeId="2" PostId="13238" RevisionGUID="bfa00631-17fa-47c1-800d-c33fe29a7b0c" CreationDate="2023-01-25T03:17:51.860" UserId="7462" Text="I know of at leas tone way to project a point onto a triangle.&#xD;&#xA;&#xD;&#xA;Project onto the plane, check barycentric coordinates, if outisde triangle, project onto the 3 segments, check distance, retain closest projection.&#xD;&#xA;&#xD;&#xA;Is there a less convoluted approach?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39610" PostHistoryTypeId="1" PostId="13238" RevisionGUID="bfa00631-17fa-47c1-800d-c33fe29a7b0c" CreationDate="2023-01-25T03:17:51.860" UserId="7462" Text="Clever projection of point onto triangle?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39611" PostHistoryTypeId="3" PostId="13238" RevisionGUID="bfa00631-17fa-47c1-800d-c33fe29a7b0c" CreationDate="2023-01-25T03:17:51.860" UserId="7462" Text="|computational-geometry|geometry|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39612" PostHistoryTypeId="50" PostId="12900" RevisionGUID="dcd03ba0-f2a9-49cb-95a4-59cd438e9a11" CreationDate="2023-01-25T07:01:25.143" UserId="-1" />
  <row Id="39613" PostHistoryTypeId="50" PostId="10509" RevisionGUID="346a10c4-bca5-4644-9019-925943ef6f6a" CreationDate="2023-01-26T07:01:40.180" UserId="-1" />
  <row Id="39614" PostHistoryTypeId="2" PostId="13239" RevisionGUID="1dcef60c-bc80-4b09-bc21-aa17bc5e6e4e" CreationDate="2023-01-27T08:26:10.750" UserId="19497" Text="There a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes and this can get quite elaborate to do it nicely) and B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls." ContentLicense="CC BY-SA 4.0" />
  <row Id="39616" PostHistoryTypeId="5" PostId="13239" RevisionGUID="1aee6a4f-4609-422b-9156-4de41b65ac4f" CreationDate="2023-01-27T08:26:51.017" UserId="19497" Comment="added 9 characters in body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- and B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls." ContentLicense="CC BY-SA 4.0" />
  <row Id="39617" PostHistoryTypeId="5" PostId="13239" RevisionGUID="ce840f58-a155-445c-85a1-6df77cca9001" CreationDate="2023-01-27T08:28:11.427" UserId="19497" Comment="added 132 characters in body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- and B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls. They resembles ZSpheres in ZBrush in many &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ED6ue.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39622" PostHistoryTypeId="5" PostId="13239" RevisionGUID="d1007455-09c6-49e8-8ac2-c3e26dc3991c" CreationDate="2023-01-27T08:46:15.903" UserId="19497" Comment="edited body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily a problem with the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls. They resemble ZSpheres in ZBrush in a way.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ED6ue.png&#xD;&#xA;&#xD;&#xA;These assume a user parameter that adjusts the radius of the metaphorical spheres, sort of blended together, to form the final mesh associated with the joints between bones. And that's something I assume you'll need unless your resulting mesh from a bone hierarchy has uniform thickness throughout." ContentLicense="CC BY-SA 4.0" />
  <row Id="39623" PostHistoryTypeId="5" PostId="13239" RevisionGUID="4d7cb445-f713-41ba-8ad3-e05482b45bba" CreationDate="2023-01-27T08:51:56.863" UserId="19497" Comment="added 27 characters in body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily a problem with the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls. They resemble ZSpheres in ZBrush in a way.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ED6ue.png&#xD;&#xA;&#xD;&#xA;These assume a user parameter that adjusts the radius of the metaphorical spheres -- associated with the joints between bones -- sort of blended together almost like metaballs (but with a very clean polygon output), to form the final mesh. And that's something I assume you'll need unless your resulting mesh from a bone hierarchy is acceptable with uniform thickness throughout. There's some need for user input to say like this part is bigger/thicker, this part is smaller/thinner, but that's all they need to provide for the skeleton/bone hierarchy to get a pretty nice base mesh or even final mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="39624" PostHistoryTypeId="5" PostId="13239" RevisionGUID="689bd5b6-a756-409a-9185-74636e60d660" CreationDate="2023-01-27T08:57:35.610" UserId="19497" Comment="added 27 characters in body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily a problem with the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls. They resemble ZSpheres in ZBrush in a way.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ED6ue.png&#xD;&#xA;&#xD;&#xA;These assume a user parameter that adjusts the radius of the metaphorical spheres -- associated with the joints between bones -- sort of blended together almost like metaballs (but with a very clean polygon output), to form the final mesh. And that's something I assume you'll need unless your resulting mesh from a bone hierarchy is acceptable with uniform thickness throughout. There's usually some need for user input to say like this part is bigger/thicker, this part is smaller/thinner, but that's all they need to provide for the skeleton/bone hierarchy to get a pretty nice base mesh or even final mesh.&#xD;&#xA;&#xD;&#xA;My custom-tailored voxel solution is my favorite if you don't have too many topology concerns over the final output. Basically you rasterize (voxelize?) your skeletal hierarchy writing to a voxel grid (3D Bresenham) that encompasses the volume with a voxel rep that stores the index of the associated bone/joint. Then you can iteratively expand the voxels (make their neighbors copy the same voxel value) up to some threshold or number of iterations until reaching a desired uniform thickness. And that's an easy solution to adapt with variable maximum thickness for each joint." ContentLicense="CC BY-SA 4.0" />
  <row Id="39625" PostHistoryTypeId="5" PostId="13239" RevisionGUID="4b34a7a6-1c71-46a8-a7d2-ac977567f606" CreationDate="2023-01-27T09:03:19.103" UserId="19497" Comment="added 27 characters in body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily a problem with the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls. They resemble ZSpheres in ZBrush in a way.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ED6ue.png&#xD;&#xA;&#xD;&#xA;These assume a user parameter that adjusts the radius of the metaphorical spheres -- associated with the joints between bones -- sort of blended together almost like metaballs (but with a very clean polygon output), to form the final mesh. And that's something I assume you'll need unless your resulting mesh from a bone hierarchy is acceptable with uniform thickness throughout. There's usually some need for user input to say like this part is bigger/thicker, this part is smaller/thinner, but that's all they need to provide for the skeleton/bone hierarchy to get a pretty nice base mesh or even final mesh.&#xD;&#xA;&#xD;&#xA;My custom-tailored voxel solution is my favorite if you don't have too many topology concerns over the final output. Basically you rasterize (voxelize?) your skeletal hierarchy writing to a voxel grid (3D Bresenham) that encompasses the volume with a voxel rep that stores the index of the associated bone/joint. Then you can iteratively expand the voxels (make their neighbors copy the same voxel value not too unlike a basic flood fill or breadth-first search) up to some threshold or number of iterations until reaching a desired uniform thickness. And that's an easy solution to adapt with variable maximum thickness for each joint." ContentLicense="CC BY-SA 4.0" />
  <row Id="39626" PostHistoryTypeId="2" PostId="13241" RevisionGUID="2af2ed34-1492-4243-9307-fdffdb13aab3" CreationDate="2023-01-27T09:27:11.460" UserId="209" Text="I think any answer to this needs to start with the following immortal quote&#xD;&#xA;&#xD;&#xA;&gt;*Floating point numbers are like piles of sand;&lt;br&gt;&#xD;&#xA;every time you move them around,&lt;br&gt;&#xD;&#xA;you lose a little sand and pick up a little dirt.* &lt;br&gt;&lt;br&gt;&#xD;&#xA;[Kernighan][1] and Plauger&#xD;&#xA;&#xD;&#xA;Basically, floating-point numbers are just approximations to $\mathbb{R}$ - they aren't infinitely precise. If you do a multiply or divide, C = A op B, then C will have an *additional* *relative* error of *about* 1 part in $2^{24}$, AKA 1/2 a [ULP][2]&#xD;&#xA;&#xD;&#xA;If you do addition or subtraction, then although the amount of additional absolute error can be bounded, the amount of additional relative error than can be enormous (see [Catastrophic cancellation][3] )&#xD;&#xA;&#xD;&#xA;Now that I've possibly terrified you, it's not that bad.&#xD;&#xA;&#xD;&#xA;What you need to do is allow for the small amount of error that will occur in your RAY-AABB and RAY-triangle testing by making your AABB tests a bit more conservative. You mention making them 5x larger - but that's complete overkill.&#xD;&#xA;Having you code &quot;round down&quot; a little on the &quot;min&quot; bounds intersection (maybe by a one part in a million or so) and the round up on the &quot;max&quot; may help. &#xD;&#xA;&#xD;&#xA;Also, when you do your reciprocal, note that the answer might be too large pr too small - you could perhaps use &quot;nextafterf()&quot; to choose the values either side of your result to make the AABB more conservative.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/P._J._Plauger&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Unit_in_the_last_place&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Catastrophic_cancellation" ContentLicense="CC BY-SA 4.0" />
  <row Id="39628" PostHistoryTypeId="5" PostId="13239" RevisionGUID="2f00c421-9272-47ed-8155-ab66868af0c7" CreationDate="2023-01-27T09:33:52.113" UserId="19497" Comment="added 700 characters in body" Text="There are a bunch depending on your needs. My personal favorites (but admittedly based on our use cases) is voxel solutions (including converting back from voxels to meshes) and - this can get quite elaborate to do it nicely -- B-Meshes.&#xD;&#xA;&#xD;&#xA;https://onlinelibrary.wiley.com/doi/10.1111/j.1467-8659.2010.01805.x&#xD;&#xA;&#xD;&#xA;B-Meshes are quite interesting. I had to tinker a bit with the paper's implementation to improve the robustness. I ran into some edge cases at least with the way I implemented the paper (not necessarily a problem with the paper itself), but a lot of it was solved by coming up with the most robust algorithm to generate convex hulls. They resemble ZSpheres in ZBrush in a way.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ED6ue.png&#xD;&#xA;&#xD;&#xA;These assume a user parameter that adjusts the radius of the metaphorical spheres -- associated with the joints between bones -- sort of blended together almost like metaballs (but with a very clean polygon output), to form the final mesh. And that's something I assume you'll need unless your resulting mesh from a bone hierarchy is acceptable with uniform thickness throughout. There's usually some need for user input to say like this part is bigger/thicker, this part is smaller/thinner, but that's all they need to provide for the skeleton/bone hierarchy to get a pretty nice base mesh or even final mesh.&#xD;&#xA;&#xD;&#xA;My custom-tailored voxel solution is my favorite if you don't have too many topology concerns over the final output. Basically you rasterize (voxelize?) your skeletal hierarchy writing to a voxel grid (3D Bresenham) that encompasses the volume with a voxel rep that stores the index of the associated bone/joint. Then you can iteratively expand the voxels (make their neighbors copy the same voxel value not too unlike a basic flood fill or breadth-first search) up to some threshold or number of iterations until reaching a desired uniform thickness. And that's an easy solution to adapt with variable maximum thickness for each joint.&#xD;&#xA;&#xD;&#xA;Another solution is to treat your bones as signed distance fields (SDFs). You can associate a maximum thickness easily to a bone in your hierarchy (with variable thickness for each bone) that you can treat as a line SDF and render a nice looking thick result that looks very smooth and curvy and round (or even sharp and right-angular using Manhattan distance). The difficulty with this solution along with my preferred one is that you can't just use a straightforward triangle rasterizer to render the results. You have to do things like raymarching. Or you have to convert it back to polygons from SDF-&gt;polygons or voxels-&gt;polygons which isn't a trivial problem to do really well with results that are much nicer than your stereotypical marching cubes." ContentLicense="CC BY-SA 4.0" />
  <row Id="39629" PostHistoryTypeId="5" PostId="13241" RevisionGUID="96d8a8c5-0a75-416d-b6af-9579a4a9e7e5" CreationDate="2023-01-27T10:18:13.523" UserId="209" Comment="typo" Text="I think any answer to this needs to start with the following immortal quote&#xD;&#xA;&#xD;&#xA;&gt;*Floating point numbers are like piles of sand;&lt;br&gt;&#xD;&#xA;every time you move them around,&lt;br&gt;&#xD;&#xA;you lose a little sand and pick up a little dirt.* &lt;br&gt;&lt;br&gt;&#xD;&#xA;[Kernighan][1] and Plauger&#xD;&#xA;&#xD;&#xA;Basically, floating-point numbers are just approximations to $\mathbb{R}$ - they aren't infinitely precise. If you do a multiply or divide, C = A op B, then C will have an *additional* *relative* error of *about* 1 part in $2^{24}$, AKA 1/2 a [ULP][2]&#xD;&#xA;&#xD;&#xA;If you do addition or subtraction, then although the amount of additional absolute error can be bounded, the amount of additional relative error than can be enormous (see [Catastrophic cancellation][3] )&#xD;&#xA;&#xD;&#xA;Now that I've possibly terrified you, it's not that bad.&#xD;&#xA;&#xD;&#xA;What you need to do is allow for the small amount of error that will occur in your RAY-AABB and RAY-triangle testing by making your AABB tests a bit more conservative. You mention making them 5x larger - but that's complete overkill.&#xD;&#xA;Having you code &quot;round down&quot; a little on the &quot;min&quot; bounds intersection (maybe by a one part in a million or so) and the round up on the &quot;max&quot; may help. &#xD;&#xA;&#xD;&#xA;Also, when you do your reciprocal, note that the answer is very likely to be too large or too small - you could perhaps use &quot;nextafterf()&quot; to choose the values either side of your result to make the AABB more conservative.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/P._J._Plauger&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Unit_in_the_last_place&#xD;&#xA;  [3]: https://en.wikipedia.org/wiki/Catastrophic_cancellation" ContentLicense="CC BY-SA 4.0" />
  <row Id="39633" PostHistoryTypeId="2" PostId="13242" RevisionGUID="4f31a1f7-b992-4fc4-96f5-67f815bf3755" CreationDate="2023-01-28T16:17:37.803" UserId="1810" Text="A general answer is that behavior can be different using consts (i.e. solved at compile time) or variables (i.e. solved at runtime), because these are treated by 2 absolutely different engines. &#xD;&#xA;The GLSL spec is very lazy in terms of compulsory behaviors, but I observed that the worst is often when relying to early evaluation of functions (i.e. all const parameters), e.g. in term of IEEE754 compliance, behavior for swapped parameters, etc.&#xD;&#xA;Note also that despite some out-of-spec situations often work correctly ( i.e. as expected ), it can be very OS, GPU or browser dependant." ContentLicense="CC BY-SA 4.0" />
  <row Id="39635" PostHistoryTypeId="2" PostId="13243" RevisionGUID="168577e2-5cfe-4f7c-a7f0-ea01bd594263" CreationDate="2023-01-28T16:19:06.243" UserId="1810" Text="the wikipedia page is quite straightforward: [https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="39637" PostHistoryTypeId="2" PostId="13244" RevisionGUID="bd505f76-b0cd-4202-a4c7-6dd0dc154cf9" CreationDate="2023-01-28T16:32:49.850" UserId="1810" Text="The problem is due to MIPmapping: the derivative is 0 inside tiles then huge accross (same problem when repeating texture with explicit fract() ).&#xD;&#xA;→ Either use nearest instead of MIPmap, or compute the LOD manually via textureLod()" ContentLicense="CC BY-SA 4.0" />
  <row Id="39639" PostHistoryTypeId="50" PostId="8779" RevisionGUID="9e5bffd4-95f8-4f0d-8d9b-8f8a168c0524" CreationDate="2023-01-28T17:07:25.890" UserId="-1" />
  <row Id="39654" PostHistoryTypeId="50" PostId="12143" RevisionGUID="d6967f67-7e9d-4312-b959-f4c348fbc89a" CreationDate="2023-01-30T14:02:10.210" UserId="-1" />
  <row Id="39657" PostHistoryTypeId="2" PostId="13249" RevisionGUID="4dced52e-bb6f-4da4-8f19-10398c258138" CreationDate="2023-01-30T16:01:32.997" UserId="7952" Text="The approach you are taking works but isn't very efficient. &#xD;&#xA;&#xD;&#xA;Projection of a point onto a triangle can be boiled down to classifying the point into the various regions defined by the support planes of the edges. (there are 7 regions total)&#xD;&#xA;&#xD;&#xA;The seven regions are the triangle face, the 3 edge regions and the 3 vertex regions.&#xD;&#xA;(draw lines perpendicular to each of the 3 edges at the vertex's a,b,c to get a diagram of the regions)&#xD;&#xA;&#xD;&#xA;These are the Voronoi regions of the triangle. The vertex region at A has  normals of (B-A) and (C-A) for the intersecting half spaces. (by using The dot product with the vector (P-A) where P is the original point will tell us if P lies inside the region. IE the barycentric coordinates will be (1,0,0).&#xD;&#xA;&#xD;&#xA;A similar test can be done for vertex B and C getting barycentric coordinates of (0,1,0) and (0,0,1) for each.&#xD;&#xA;&#xD;&#xA;Here are the functions:&#xD;&#xA;&#xD;&#xA;    // Determine if point lies in vertex regions&#xD;&#xA;    AB = b-a;&#xD;&#xA;    AC = c-a;&#xD;&#xA;&#xD;&#xA;    AP = p-a;&#xD;&#xA;    dA1 = dot(AB,AP);&#xD;&#xA;    dA2 = dot(AC,AP);&#xD;&#xA;    if( dA1&lt;=0 and dA2 &lt;=0) return a; // vertex region a (bary coords 1,0,0)&#xD;&#xA;&#xD;&#xA;    BP = p - b;&#xD;&#xA;    dB1 = dot(AB, BP);&#xD;&#xA;    dB2 = dot(AC, BP);&#xD;&#xA;    if( dB1 &gt;= 0 &amp;&amp; dB2=&lt;0 ) return b; // vertex region b (bary coords 0,1,0)&#xD;&#xA;&#xD;&#xA;    CP = p - c;&#xD;&#xA;    dC1 = Dot(AB,CP);&#xD;&#xA;    dC2 = Dot(AC,CP);&#xD;&#xA;    if( dC2 &gt;= 0 &amp;&amp; dC1 &lt;= dC2 ) return c; // vertex region c (bary coords 0,0,1)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To determine if the point lies in the edge regions you can continue with the barycentric coordinate computations. ie summed area method. This computation boils down to using dot products used to compute the vertex regions to check if the point lies in the edge regions.&#xD;&#xA;&#xD;&#xA;    EdgeAB = dA1*dB2 - dB1*dA2;&#xD;&#xA;    if( EdgeAB &lt;= 0 and dA1 &gt;= 0 and dB1 &lt;=0) { &#xD;&#xA;       // lies in edge region bary coords (1-u, u,0); &#xD;&#xA;       // project point onto edge AB and return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    EdgeBC = dB1*dC2 - dC1*dB2; &#xD;&#xA;    if( EdgeBC &lt;= 0 and (dB2-dB1)&gt;=0 and (dC1-dC2)&gt;=0) {&#xD;&#xA;       // lies in edge region BC bary coords (0, 1-u, u)&#xD;&#xA;       // project point onto edge BC and return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    EdgeAC = dC1*dA2 - dA1*dC2;&#xD;&#xA;    if( EdgeAC &lt;= 0 and d2&gt;=0 and d6 &lt;= 0 ) {&#xD;&#xA;       // lies in edge region AC bary coords (1-u, 0 ,u )&#xD;&#xA;       // project point onto edge AC and return result&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Finally if it isn't in any of these regions it must be inside the triangle face. Luckily we have computed everything needed to find the barycentric coords at this point...&#xD;&#xA;&#xD;&#xA;     summed_area = EdgeAB + EdgeBC +EdgeAC;&#xD;&#xA;     v = EdgeAC / summed_area;&#xD;&#xA;     w = EdgeAB / summed_area;&#xD;&#xA;     return a + ab * v + ac * w;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39659" PostHistoryTypeId="5" PostId="10795" RevisionGUID="42545ebb-7162-4966-990c-14d3f49c4385" CreationDate="2023-01-30T16:05:41.927" UserId="2654" Comment="deleted 1 character in body" Text="When a shader accesses a resource (buffer or texture), it needs some information about that resource to be able to do so correctly. On a modern GPU, that information will generally just be some kind of number. It could be something as simple as a GPU virtual memory address (with the particular details of what kind of resource is being used defined by the shading language), or it may be an index into a table of resources.&#xD;&#xA;&#xD;&#xA;But all modern GPUs need is a number.&#xD;&#xA;&#xD;&#xA;From the CPU side, a resource is defined by some API-defined object. To bind a resource (API-agnosticly) means that you tell the API that the given API object's resource is to used by the shader through some resource binding location.&#xD;&#xA;&#xD;&#xA;This process therefore requires the API to take that object and convert it into the number that the shader will receive. The object itself cannot just be that integer because the API needs ancillary information for managing the resource. But when you're *rendering* with the resource, the integer is all you really need.&#xD;&#xA;&#xD;&#xA;So let's say you're rendering a complex scene. You may be rendering 100,000 different objects. That could mean 100,000 different binding operations per-frame. Each bind operation has to dereference an object pointer and fetch a single 64-bit integer from the object behind that pointer. And often, the nature of the API object requires *multiple* dereferences to get this integer.&#xD;&#xA;&#xD;&#xA;This is not a cache-friendly operation, as you're fetching a piece of data from storage that has a bunch of *unrelated* data near it. So not only is the read likely to be a cache-miss, you're doing a whole memory fetch for *just* 64-bits of data, that will not be used for anything else before that cache line gets evicted. This represents poor cache coherency.&#xD;&#xA;&#xD;&#xA;Across 100,000 objects at 60fps (or greater), that can add up.&#xD;&#xA;&#xD;&#xA;A bindless API allows the user to store the integer themselves and marshal it to the shader in whatever way they see fit. Any resource integers for an object's rendering call can be stored near other data that is relevant to the rendering process, thus improving cache coherency.&#xD;&#xA;&#xD;&#xA;It should also be noted that a bindless API means that any shader could access any information about any object, so long as it has been given access to the integers that represent those resources. This is rather important when doing something like ray-tracing.&#xD;&#xA;&#xD;&#xA;So it's not *just* about performance." ContentLicense="CC BY-SA 4.0" />
  <row Id="39660" PostHistoryTypeId="5" PostId="13249" RevisionGUID="27e433dd-31e8-4c76-8657-7f49cabd9bc1" CreationDate="2023-01-30T20:47:52.290" UserId="7952" Comment="added 123 characters in body" Text="The approach you are taking works but isn't very efficient. &#xD;&#xA;&#xD;&#xA;Projection of a point onto a triangle can be boiled down to classifying the point into the various regions defined by the support planes of the edges. (there are 7 regions total)&#xD;&#xA;&#xD;&#xA;The seven regions are the triangle face, the 3 edge regions and the 3 vertex regions.&#xD;&#xA;(draw lines perpendicular to each of the 3 edges at the vertex's a,b,c to get a diagram of the regions)&#xD;&#xA;&#xD;&#xA;These are the Voronoi regions of the triangle. The vertex region at A has  normals of (B-A) and (C-A) for the intersecting half spaces. (by using The dot product with the vector (P-A) where P is the original point will tell us if P lies inside the region. IE the barycentric coordinates will be (1,0,0).&#xD;&#xA;&#xD;&#xA;A similar test can be done for vertex B and C getting barycentric coordinates of (0,1,0) and (0,0,1) for each.&#xD;&#xA;&#xD;&#xA;Here are the functions:&#xD;&#xA;&#xD;&#xA;    // Determine if point lies in vertex regions&#xD;&#xA;    AB = b-a;&#xD;&#xA;    AC = c-a;&#xD;&#xA;&#xD;&#xA;    AP = p-a;&#xD;&#xA;    dA1 = dot(AB,AP);&#xD;&#xA;    dA2 = dot(AC,AP);&#xD;&#xA;    if( dA1&lt;=0 and dA2 &lt;=0) return a; // vertex region a (bary coords 1,0,0)&#xD;&#xA;&#xD;&#xA;    BP = p - b;&#xD;&#xA;    dB1 = dot(AB, BP);&#xD;&#xA;    dB2 = dot(AC, BP);&#xD;&#xA;    if( dB1 &gt;= 0 &amp;&amp; dB2=&lt;0 ) return b; // vertex region b (bary coords 0,1,0)&#xD;&#xA;&#xD;&#xA;    CP = p - c;&#xD;&#xA;    dC1 = Dot(AB,CP);&#xD;&#xA;    dC2 = Dot(AC,CP);&#xD;&#xA;    if( dC2 &gt;= 0 &amp;&amp; dC1 &lt;= dC2 ) return c; // vertex region c (bary coords 0,0,1)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To determine if the point lies in the edge regions you can continue with the barycentric coordinate computations. ie summed area method. This computation boils down to using dot products used to compute the vertex regions to check if the point lies in the edge regions.&#xD;&#xA;&#xD;&#xA;    EdgeAB = dA1*dB2 - dB1*dA2;&#xD;&#xA;    if( EdgeAB &lt;= 0 and dA1 &gt;= 0 and dB1 &lt;=0) { &#xD;&#xA;       // lies in edge region bary coords (1-u, u,0); &#xD;&#xA;       // project point onto edge AB and return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    EdgeBC = dB1*dC2 - dC1*dB2; &#xD;&#xA;    if( EdgeBC &lt;= 0 and (dB2-dB1)&gt;=0 and (dC1-dC2)&gt;=0) {&#xD;&#xA;       // lies in edge region BC bary coords (0, 1-u, u)&#xD;&#xA;       // project point onto edge BC and return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    EdgeAC = dC1*dA2 - dA1*dC2;&#xD;&#xA;    if( EdgeAC &lt;= 0 and d2&gt;=0 and d6 &lt;= 0 ) {&#xD;&#xA;       // lies in edge region AC bary coords (1-u, 0 ,u )&#xD;&#xA;       // project point onto edge AC and return result&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Finally if it isn't in any of these regions it must be inside the triangle face. Luckily we have computed everything needed to find the barycentric coords at this point...&#xD;&#xA;&#xD;&#xA;     summed_area = EdgeAB + EdgeBC +EdgeAC;&#xD;&#xA;     v = EdgeAC / summed_area;&#xD;&#xA;     w = EdgeAB / summed_area;&#xD;&#xA;     return a + ab * v + ac * w;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;According to my notes the original source of this method is the book Real Time Collision Detection by Christer Ericson." ContentLicense="CC BY-SA 4.0" />
  <row Id="39661" PostHistoryTypeId="2" PostId="13250" RevisionGUID="2f9af814-366a-4cfa-a0db-4a0619397926" CreationDate="2023-01-31T08:39:39.940" UserId="3242" Text="Rendering equation's value can be estimated with Monte Carlo (https://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection):&#xD;&#xA;&#xD;&#xA;$\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;L_o(p, \omega_o) &amp;= \int_{S^2}f(p, \omega_o, \omega_i) L_i(p, \omega_i) |\cos\theta_i| \mathrm{d}\omega_i\\&#xD;&#xA; &amp; = \frac{1}{N} \sum_{j=1}^{N} \frac{f(p, \omega_o, \omega_i) L_i(p, \omega_j) |\cos\theta_j|}{p(\omega_j)}&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}$&#xD;&#xA;&#xD;&#xA;So if the hit surface is a mirror and $\omega_j$ is the correct direction (only 1 sample is needed and $p(\omega_j)=1$) then this equation becomes:&#xD;&#xA;&#xD;&#xA;$\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;L_o(p, \omega_o) &amp; = f(p, \omega_o, \omega_i) L_i(p, \omega_j) |\cos\theta_j|&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}$&#xD;&#xA;&#xD;&#xA;For a ideal mirror that reflect without any energe loss, $f(p, \omega_o, \omega_i)$ is 1.&#xD;&#xA;&#xD;&#xA;Yet I couldn't find term $\cos\theta_j$ when reading code from Ray Tracing Weekend and smallpt.&#xD;&#xA;&#xD;&#xA;In Ray Tracing Weekend, the [ray tracing function](https://github.com/RayTracing/raytracing.github.io/blob/master/src/TheRestOfYourLife/main.cc#L25) is written as&#xD;&#xA;```cpp&#xD;&#xA;color ray_color(&#xD;&#xA;    const ray&amp; r,&#xD;&#xA;    const color&amp; background,&#xD;&#xA;    const hittable&amp; world,&#xD;&#xA;    shared_ptr&lt;hittable&gt; lights,&#xD;&#xA;    int depth&#xD;&#xA;) {&#xD;&#xA;    hit_record rec;&#xD;&#xA;&#xD;&#xA;    // If we've exceeded the ray bounce limit, no more light is gathered.&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;        return color(0,0,0);&#xD;&#xA;&#xD;&#xA;    // If the ray hits nothing, return the background color.&#xD;&#xA;    if (!world.hit(r, 0.001, infinity, rec))&#xD;&#xA;        return background;&#xD;&#xA;&#xD;&#xA;    scatter_record srec;&#xD;&#xA;    color emitted = rec.mat_ptr-&gt;emitted(r, rec, rec.u, rec.v, rec.p);&#xD;&#xA;&#xD;&#xA;    if (!rec.mat_ptr-&gt;scatter(r, rec, srec))&#xD;&#xA;        return emitted;&#xD;&#xA;&#xD;&#xA;    if (srec.is_specular) {&#xD;&#xA;        return srec.attenuation&#xD;&#xA;             * ray_color(srec.specular_ray, background, world, lights, depth-1);&#xD;&#xA;    }&#xD;&#xA;    ...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The last part&#xD;&#xA;```&#xD;&#xA;    if (srec.is_specular) {&#xD;&#xA;        return srec.attenuation&#xD;&#xA;             * ray_color(srec.specular_ray, background, world, lights, depth-1);&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;implies that when hitting a specular object, the result (color) got attenuated by `srec.attenuation` but the cosine term is gone.&#xD;&#xA;&#xD;&#xA;Similarly, neither [smallpt](https://www.kevinbeason.com/smallpt/) (line 61, 62) include cosine term when handling scatterring for specular object:&#xD;&#xA;```&#xD;&#xA;else if (obj.refl == SPEC)            // Ideal SPECULAR reflection &#xD;&#xA;    return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi));&#xD;&#xA;```&#xD;&#xA;it shoots a new ray to the reflected direction without having $\cos(\theta)$.&#xD;&#xA;&#xD;&#xA;So, how does $\cos(\theta)$ got cancelled for both renderer? Or did I misunderstand the equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39663" PostHistoryTypeId="1" PostId="13250" RevisionGUID="2f9af814-366a-4cfa-a0db-4a0619397926" CreationDate="2023-01-31T08:39:39.940" UserId="3242" Text="cosine term in rendering equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="39664" PostHistoryTypeId="3" PostId="13250" RevisionGUID="2f9af814-366a-4cfa-a0db-4a0619397926" CreationDate="2023-01-31T08:39:39.940" UserId="3242" Text="|raytracing|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39665" PostHistoryTypeId="2" PostId="13251" RevisionGUID="8941bbac-3eb7-4238-956f-cb0bbe5df727" CreationDate="2023-01-31T19:01:35.860" UserId="7567" Text="I am new at this particular site in the SE ecosystem, but not to computer graphics in general. If I'm in the wrong spot feel free to redirect me.&#xD;&#xA;&#xD;&#xA;My question regards glsl programming and binding two different layers from the same GL_TEXTURE_ARRAY for use in a compute shader.&#xD;&#xA;&#xD;&#xA;I am not sure if this is possible or if I am doing it correctly.&#xD;&#xA;&#xD;&#xA;What I have tried is to first create an array of 2D textures for &#xD;&#xA;&#xD;&#xA;    glGenTextures(1,&amp;im_mvs); glActiveTexture(GL_TEXTURE0+1);  &#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY,im_mvs);&#xD;&#xA;    // setting various parameters here&#xD;&#xA;    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1 , GL_RGBA32F, lMatDims[0]/lSSFact, lMatDims[1]/lSSFact, NMVS);&#xD;&#xA;    glBindImageTexture(1, im_mvs, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;Then when setting up the shader call I do something like:&#xD;&#xA;&#xD;&#xA;    glUseProgram(convProgram); // Now try to convolve.&#xD;&#xA;    glUniform1i(p4ImIn,0); glActiveTexture(GL_TEXTURE0+1); glBindImageTexture(1, im_mvs, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA32F);&#xD;&#xA;    glUniform1i(p4Filt,1); glActiveTexture(GL_TEXTURE0+4); glBindImageTexture(4, im_filt,0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA32F);&#xD;&#xA;    glUniform1i(p4ImOut,2); glActiveTexture(GL_TEXTURE0+1); glBindImageTexture(1, im_mvs, 0, GL_FALSE, 1, GL_WRITE_ONLY,GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;I currently can't get it to work, but as I still am quite new to opengl and glsl there is a fair chance that I may have made a mistake somewhere else.&#xD;&#xA;&#xD;&#xA;The behavior that I am hoping for is to be able to select which layer of the array should be used in in-image and out-image respectively. This would make it very convenient to construct automated sequences of filterings by just changing the pointing with glBindImageTexture command like above.&#xD;&#xA;&#xD;&#xA;I wonder if this is supposed to be possible or if I need to alter it somehow ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39667" PostHistoryTypeId="1" PostId="13251" RevisionGUID="8941bbac-3eb7-4238-956f-cb0bbe5df727" CreationDate="2023-01-31T19:01:35.860" UserId="7567" Text="GLSL trying to bind two different layers from the same texture array as images. Should it work and if so what am I doing wrong?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39668" PostHistoryTypeId="3" PostId="13251" RevisionGUID="8941bbac-3eb7-4238-956f-cb0bbe5df727" CreationDate="2023-01-31T19:01:35.860" UserId="7567" Text="|opengl|glsl|texture|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39669" PostHistoryTypeId="5" PostId="13251" RevisionGUID="6b260beb-9229-4361-ba1c-99556dcd990b" CreationDate="2023-01-31T19:08:18.323" UserId="7567" Comment="edited body" Text="I am new at this particular site in the SE ecosystem, but not to computer graphics in general. If I'm in the wrong spot feel free to redirect me.&#xD;&#xA;&#xD;&#xA;My question regards glsl programming and binding two different layers from the same GL_TEXTURE_ARRAY for use in a compute shader.&#xD;&#xA;&#xD;&#xA;I am not sure if this is possible or if I am doing it correctly.&#xD;&#xA;&#xD;&#xA;What I have tried is to first create an array of 2D textures for &#xD;&#xA;&#xD;&#xA;    glGenTextures(1,&amp;im_mvs); glActiveTexture(GL_TEXTURE0+1);  &#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY,im_mvs);&#xD;&#xA;    // setting various parameters here&#xD;&#xA;    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1 , GL_RGBA32F, lMatDims[0]/lSSFact, lMatDims[1]/lSSFact, NMVS);&#xD;&#xA;    glBindImageTexture(1, im_mvs, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;Then when setting up the shader call I do something like:&#xD;&#xA;&#xD;&#xA;    glUseProgram(convProgram); // Now try to convolve.&#xD;&#xA;    glUniform1i(p4ImIn,1); glActiveTexture(GL_TEXTURE0+1); glBindImageTexture(1, im_mvs, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA32F);&#xD;&#xA;    glUniform1i(p4Filt,4); glActiveTexture(GL_TEXTURE0+4); glBindImageTexture(4, im_filt,0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA32F);&#xD;&#xA;    glUniform1i(p4ImOut,1); glActiveTexture(GL_TEXTURE0+1); glBindImageTexture(1, im_mvs, 0, GL_FALSE, 1, GL_WRITE_ONLY,GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;I currently can't get it to work, but as I still am quite new to opengl and glsl there is a fair chance that I may have made a mistake somewhere else.&#xD;&#xA;&#xD;&#xA;The behavior that I am hoping for is to be able to select which layer of the array should be used in in-image and out-image respectively. This would make it very convenient to construct automated sequences of filterings by just changing the pointing with glBindImageTexture command like above.&#xD;&#xA;&#xD;&#xA;I wonder if this is supposed to be possible or if I need to alter it somehow ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39670" PostHistoryTypeId="2" PostId="13252" RevisionGUID="a715804f-bd40-45e9-b91d-124da85b4ebd" CreationDate="2023-01-31T22:49:31.423" UserId="2654" Text="There is no such thing as an &quot;in image&quot; and an &quot;out image&quot;. There are just [images used for load/store operations][1]. A particular image can be write-only or read-only, but what &quot;a particular image&quot; *means* is defined by the binding index used in the shader. That is, there is exactly and only one image bound to index 1 at any time, with exactly and only one set of properties (readable, writeable, etc). If you bind another image to index 1, then you have *unbound* the previous image, and you have changed the properties of the binding.&#xD;&#xA;&#xD;&#xA;Whatever `p4ImIn` and `p4ImOut` represent in your shader, they should have different binding indices. And therefore, you should be binding those images to different indices.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Image_Load_Store" ContentLicense="CC BY-SA 4.0" />
  <row Id="39672" PostHistoryTypeId="2" PostId="13253" RevisionGUID="ca71516d-4bef-4989-b1bd-fb815be3b13d" CreationDate="2023-02-01T09:25:44.667" UserId="19523" Text="I assume you mean glowing geometry (not sky functions). There are several ways to do this, but as a simple example (not optimized ofc): since you have a pointlight you could ray trace a sphere or project a 3D disk with analytic AA (would remove jaggies/flicker at great distance) into a separate texture (with visibility occlusion!) and apply a bloom filter on top of the sphere (maybe separated Gaussian filter or according to: &quot;https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom&quot;).&#xD;&#xA;&#xD;&#xA;Hope this was helpful!" ContentLicense="CC BY-SA 4.0" />
  <row Id="39674" PostHistoryTypeId="5" PostId="12883" RevisionGUID="b594eb98-3f4d-4fcc-8fb0-cee69d98df70" CreationDate="2023-02-01T09:50:05.390" UserId="18728" Comment="deleted 1 character in body" Text="Is it practical to implement the Lorenz-Mie(LM) phase function in a renderer ?&#xD;&#xA;&#xD;&#xA;$p(\cos\theta)=\frac{|S_1(\theta)|^2+|S_2(\theta)|^2}{4\pi\sum_{n=1}^\infty (2n+1)(|a_n|^2+|b_n|^2)}$&#xD;&#xA;&#xD;&#xA;I'll spare you the details but: $S_1(\theta), S_2(\theta), a_n, b_n$ are complex numbers involving Legendre polynomials, and their derivatives. All of that to say the computations are quite involved.&#xD;&#xA;&#xD;&#xA;So do the benefit of LM phase function(Physical accuracies mainly) outweighs the cost to compute them, or I better off with the standard Henyey-Greenstein or some modified version of it ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39675" PostHistoryTypeId="2" PostId="13254" RevisionGUID="d3b4f4f9-45a3-4501-a39c-61791b03341c" CreationDate="2023-02-01T09:51:58.040" UserId="19523" Text="Denote you ray as $\vec{P} + \vec{D}*t $ and $\vec{S}_h$ be the half size of the box (ie $ \vec{S}_h = (1,1,1)$). The following equation must be satisfied (with abusive notation): $ || \frac{\vec{P} + \vec{D}*t}{\vec{S}_h} - 1 ||_{L_{\infty}} = 1 $ where vector-division is defined as $\frac{\vec{a}}{\vec{b}} = (a_1/b_1,a_2/b_2,a_3/b_3,...)$ and subtraction $\vec{a} - b = (a_1-b,a_2-b,a_3-b,...)$. Note that the max norm is used. There are branchless solutions to finding both solutions to $t$ in this equation.&#xD;&#xA;&#xD;&#xA;To get the normal after computing $t$: evaluate the vector inside the norm, find the basis vector corresponding to the component with largest absolute value and multiply it by the sign of the component." ContentLicense="CC BY-SA 4.0" />
  <row Id="39677" PostHistoryTypeId="2" PostId="13255" RevisionGUID="8d787edf-49a5-4039-8037-190627c99233" CreationDate="2023-02-01T10:10:52.060" UserId="19523" Text="Here are some thoughts:&#xD;&#xA;&#xD;&#xA;1. Absolute SDF value clamping, large absolute values of the SDF will not improve the quality of the rendered text. So clamping the values will ensure that you can get higher precision when the SDF is close to 0.&#xD;&#xA;2. Force uniform precision by converting you $0-1$ value into a UINT integer and store it directly.&#xD;&#xA;3. Store a transformed value of the SDF value or your 0-1 value. For example logarithmic values." ContentLicense="CC BY-SA 4.0" />
  <row Id="39679" PostHistoryTypeId="5" PostId="13251" RevisionGUID="a8e262b9-3948-4c15-85a0-a251cce5ed65" CreationDate="2023-02-01T10:54:21.840" UserId="7567" Comment="added 1001 characters in body" Text="I am new at this particular site in the SE ecosystem, but not to computer graphics in general. If I'm in the wrong spot feel free to redirect me.&#xD;&#xA;&#xD;&#xA;My question regards glsl programming and binding two different layers from the same GL_TEXTURE_ARRAY for use in a compute shader.&#xD;&#xA;&#xD;&#xA;I am not sure if this is possible or if I am doing it correctly.&#xD;&#xA;&#xD;&#xA;What I have tried is to first create an array of 2D textures for &#xD;&#xA;&#xD;&#xA;    glGenTextures(1,&amp;im_mvs); glActiveTexture(GL_TEXTURE0+1);  &#xD;&#xA;    glBindTexture(GL_TEXTURE_2D_ARRAY,im_mvs);&#xD;&#xA;    // setting various parameters here&#xD;&#xA;    glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1 , GL_RGBA32F, lMatDims[0]/lSSFact, lMatDims[1]/lSSFact, NMVS);&#xD;&#xA;    glBindImageTexture(1, im_mvs, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;Then when setting up the shader call I do something like:&#xD;&#xA;&#xD;&#xA;    glUseProgram(convProgram); // Now try to convolve.&#xD;&#xA;    glUniform1i(p4ImIn,1); glActiveTexture(GL_TEXTURE0+1); glBindImageTexture(1, im_mvs, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA32F);&#xD;&#xA;    glUniform1i(p4Filt,4); glActiveTexture(GL_TEXTURE0+4); glBindImageTexture(4, im_filt,0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA32F);&#xD;&#xA;    glUniform1i(p4ImOut,1); glActiveTexture(GL_TEXTURE0+1); glBindImageTexture(1, im_mvs, 0, GL_FALSE, 1, GL_WRITE_ONLY,GL_RGBA32F);&#xD;&#xA;&#xD;&#xA;I currently can't get it to work, but as I still am quite new to opengl and glsl there is a fair chance that I may have made a mistake somewhere else.&#xD;&#xA;&#xD;&#xA;The behavior that I am hoping for is to be able to select which layer of the array should be used in in-image and out-image respectively. This would make it very convenient to construct automated sequences of filterings by just changing the pointing with glBindImageTexture command like above.&#xD;&#xA;&#xD;&#xA;I wonder if this is supposed to be possible or if I need to alter it somehow ?&#xD;&#xA;&#xD;&#xA;_______&#xD;&#xA;&#xD;&#xA;**Edit:** Just as Nicol mentioned in the answer there were several issues with my code. The most important was that I had mixed up *texture units* and *image units*.&#xD;&#xA;&#xD;&#xA;Inside my shader which defines uniform data like this :&#xD;&#xA;&#xD;&#xA;    layout(rgba32f, binding = 0) uniform image2D im_in;&#xD;&#xA;    layout(rgba32f, binding = 1) uniform image2D filt;&#xD;&#xA;    layout(rgba32f, binding = 2) uniform image2D im_out;&#xD;&#xA;&#xD;&#xA;The &quot;binding&quot; numbers there should correspond to the first argument in the call to *glBindImageTexture* as the types &quot;image2D&quot; is an image type. The glActiveTexture command is superflous as the variables im_mvs, im_filt already are tied to the texture(array)s which the image will be gotten from. I had them there previously to be able to transfer data.&#xD;&#xA;&#xD;&#xA;I changed to &#xD;&#xA;&#xD;&#xA;    glUniform1i(p4ImIn,0); glBindImageTexture(0, im_mvs, ...&#xD;&#xA;    glUniform1i(p4Filt,1); glBindImageTexture(1, im_filt,...&#xD;&#xA;    glUniform1i(p4ImOut,2); glBindImageTexture(2, im_mvs, ...&#xD;&#xA;&#xD;&#xA;and now the code works as I had hoped. I will now go ahead to investigate various ways to filter my MVs. Thank you for the help." ContentLicense="CC BY-SA 4.0" />
  <row Id="39680" PostHistoryTypeId="5" PostId="13250" RevisionGUID="cc678042-2215-4674-8e65-5de308f4450f" CreationDate="2023-02-01T13:48:31.497" UserId="3242" Comment="added 5 characters in body" Text="Rendering equation's value can be estimated with Monte Carlo (https://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection):&#xD;&#xA;&#xD;&#xA;$\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;L_o(p, \omega_o) &amp;= \int_{S^2}f(p, \omega_o, \omega_i) L_i(p, \omega_i) |\cos\theta_i| \mathrm{d}\omega_i\\&#xD;&#xA; &amp; = \frac{1}{N} \sum_{j=1}^{N} \frac{f(p, \omega_o, \omega_i) L_i(p, \omega_j) |\cos\theta_j|}{p(\omega_j)}&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}$&#xD;&#xA;&#xD;&#xA;So if the hit surface is a mirror and $\omega_j$ is the correct direction (only 1 sample is needed and $p(\omega_j)=1$) then this equation becomes:&#xD;&#xA;&#xD;&#xA;$\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;L_o(p, \omega_o) &amp; = f(p, \omega_o, \omega_i) L_i(p, \omega_j) |\cos\theta_j|&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}$&#xD;&#xA;&#xD;&#xA;For a ideal mirror that reflect without any energe loss, $f(p, \omega_o, \omega_i)$ is 1.&#xD;&#xA;&#xD;&#xA;Yet I couldn't find term $\cos\theta_j$ when reading code from Ray Tracing Weekend and smallpt.&#xD;&#xA;&#xD;&#xA;In Ray Tracing Weekend, the [ray tracing function](https://github.com/RayTracing/raytracing.github.io/blob/master/src/TheRestOfYourLife/main.cc#L25) is written as&#xD;&#xA;```cpp&#xD;&#xA;color ray_color(&#xD;&#xA;    const ray&amp; r,&#xD;&#xA;    const color&amp; background,&#xD;&#xA;    const hittable&amp; world,&#xD;&#xA;    shared_ptr&lt;hittable&gt; lights,&#xD;&#xA;    int depth&#xD;&#xA;) {&#xD;&#xA;    hit_record rec;&#xD;&#xA;&#xD;&#xA;    // If we've exceeded the ray bounce limit, no more light is gathered.&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;        return color(0,0,0);&#xD;&#xA;&#xD;&#xA;    // If the ray hits nothing, return the background color.&#xD;&#xA;    if (!world.hit(r, 0.001, infinity, rec))&#xD;&#xA;        return background;&#xD;&#xA;&#xD;&#xA;    scatter_record srec;&#xD;&#xA;    color emitted = rec.mat_ptr-&gt;emitted(r, rec, rec.u, rec.v, rec.p);&#xD;&#xA;&#xD;&#xA;    if (!rec.mat_ptr-&gt;scatter(r, rec, srec))&#xD;&#xA;        return emitted;&#xD;&#xA;&#xD;&#xA;    if (srec.is_specular) {&#xD;&#xA;        return srec.attenuation&#xD;&#xA;             * ray_color(srec.specular_ray, background, world, lights, depth-1);&#xD;&#xA;    }&#xD;&#xA;    ...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The last part&#xD;&#xA;```&#xD;&#xA;    if (srec.is_specular) {&#xD;&#xA;        return srec.attenuation&#xD;&#xA;             * ray_color(srec.specular_ray, background, world, lights, depth-1);&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;implies that when hitting a specular object, the result (color) got attenuated by `srec.attenuation` but the cosine term is gone.&#xD;&#xA;&#xD;&#xA;Similarly, neither [smallpt](https://www.kevinbeason.com/smallpt/) (line 61, 62) include cosine term when handling scatterring for specular object:&#xD;&#xA;```&#xD;&#xA;else if (obj.refl == SPEC)            // Ideal SPECULAR reflection &#xD;&#xA;    return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi));&#xD;&#xA;```&#xD;&#xA;it shoots a ray to a new direction without having $\cos(\theta)$ after reflection.&#xD;&#xA;&#xD;&#xA;So, how does $\cos(\theta)$ got cancelled for both renderer? Or did I misunderstand the equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39681" PostHistoryTypeId="2" PostId="13256" RevisionGUID="5c82d0c5-0c8b-4246-a6bb-562eec1a1432" CreationDate="2023-02-01T19:16:49.113" UserId="19510" Text="&lt;!-- language-all: lang-cpp --&gt;&#xD;&#xA;I'm writing a ray tracer but having trouble converting rays and normals between world space and object space.&#xD;&#xA;&#xD;&#xA;I am creating a Ray, then transforming it with transformation matrices, calculating intersections and return them.&#xD;&#xA;&#xD;&#xA;Constructing transformation matrices:&#xD;&#xA;```&#xD;&#xA;    glm::mat4 rotate = glm::eulerAngleYXZ(- _rotation.y, - _rotation.x, - _rotation.z);&#xD;&#xA;    glm::mat4 translate = glm::translate(- _position);&#xD;&#xA;    glm::mat4 scale = glm::scale(glm::vec3(1.0f) / _scale);&#xD;&#xA;&#xD;&#xA;    _transform_world_to_object = translate * rotate * scale;&#xD;&#xA;    _transform_object_to_world = glm::inverse(_transform_world_to_object);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Checking Ray Sphere intersection in object space, and adding according intersections with their normal, position and distance (in world space) to provided list:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    void Sphere::computeAllRayIntersections(Ray&amp; ray, IntersectionList&amp; intersections) {&#xD;&#xA;    //assuming ray has unit direction vector (easier calculation), then compensate for length later in distances&#xD;&#xA;    float ray_to_sphere_ray_dir_dot = glm::dot(glm::normalize(ray.getDirection()), ray.getOrigin());&#xD;&#xA;    float radicand = glm::dot(ray_to_sphere_ray_dir_dot, ray_to_sphere_ray_dir_dot) - (glm::dot(ray.getOrigin(), ray.getOrigin()) - 1.0f);&#xD;&#xA;&#xD;&#xA;    if(radicand &lt; 0.0f) {&#xD;&#xA;      return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float d1 = (- ray_to_sphere_ray_dir_dot + sqrtf(radicand)) / glm::length(ray.getDirection());&#xD;&#xA;&#xD;&#xA;    glm::vec3 position1 = ray.positionAtDistance(d1);&#xD;&#xA;    glm::vec3 normal1 = glm::normalize(ray.positionAtDistance(d1));&#xD;&#xA;    //invert normal when ray starting point lies in sphere:&#xD;&#xA;    if(glm::length(ray.getOrigin()) &lt; 1.0f) {&#xD;&#xA;      normal1 *= -1.0f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray hit1_data(position1, normal1);&#xD;&#xA;    hit1_data = this-&gt;transformHitObjectToWorld(hit1_data);&#xD;&#xA;   intersections.addIntersection(std::make_unique&lt;Intersection&gt;(&#xD;&#xA;      Intersection(&#xD;&#xA;        (IGeometricObject*) this,&#xD;&#xA;        glm::normalize(hit1_data.getDirection()),&#xD;&#xA;        hit1_data.getOrigin(),&#xD;&#xA;        d1)));&#xD;&#xA;&#xD;&#xA;    if(radicand == 0.0f) { //stop after calculating only intersection&#xD;&#xA;      return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float d2 = (- ray_to_sphere_ray_dir_dot - sqrtf(radicand)) / glm::length(ray.getDirection());&#xD;&#xA;&#xD;&#xA;    glm::vec3 position2 = ray.positionAtDistance(d2);&#xD;&#xA;    glm::vec3 normal2 = glm::normalize(ray.positionAtDistance(d2));&#xD;&#xA;    //invert normal when ray starting point lies in sphere:&#xD;&#xA;    if(glm::length(ray.getOrigin()) &lt; 1.0f) {&#xD;&#xA;      normal2 *= -1.0f;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    Ray hit2_data(position2, normal2);&#xD;&#xA;    hit2_data = this-&gt;transformHitObjectToWorld(hit2_data);&#xD;&#xA;   intersections.addIntersection(std::make_unique&lt;Intersection&gt;(&#xD;&#xA;      Intersection(&#xD;&#xA;        (IGeometricObject*) this,&#xD;&#xA;        glm::normalize(hit2_data.getDirection()),&#xD;&#xA;        hit2_data.getOrigin(),&#xD;&#xA;        d2)));                                                           &#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;With the following code I transform a point,vector pair between coordinate spaces: The conversion from world to object space doesn't normalize and doesn't uses normal formula, while converting the intersection from object to world space does. This differentiation is based on [this presentation][1].&#xD;&#xA;```&#xD;&#xA;    Ray Ray::transform(glm::mat4 transform, bool normalize_direction, bool is_normal) {&#xD;&#xA;    glm::vec3 transformed_direction;&#xD;&#xA;    if(is_normal) {&#xD;&#xA;      transformed_direction = glm::transpose(glm::inverse(transform)) * glm::vec4(_direction, 0.0f);&#xD;&#xA;    }&#xD;&#xA;    else {&#xD;&#xA;      transformed_direction = transform * glm::vec4(_direction, 0.0f);&#xD;&#xA;    }&#xD;&#xA;    //transformed_direction = transform * glm::vec4(_direction, 0.0f); &#xD;&#xA;    if(normalize_direction) {&#xD;&#xA;      transformed_direction = glm::normalize(transformed_direction);&#xD;&#xA;    }&#xD;&#xA;    return Ray(transform * glm::vec4(_origin, 1.0f), transformed_direction);&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    Ray BaseGeometricObject::transformRayWorldToObject(Ray&amp; ray) {&#xD;&#xA;    return ray.transform(_transform_world_to_object, false, false);&#xD;&#xA;  }&#xD;&#xA;  Ray BaseGeometricObject::transformHitObjectToWorld(Ray&amp; ray) {&#xD;&#xA;    return ray.transform(_transform_object_to_world, false, true);&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&lt;!-- language-all: lang-json --&gt;&#xD;&#xA;When rendering with uniform scaling, the output image looks (disregarding the normal) good:&#xD;&#xA;```&#xD;&#xA;{&#xD;&#xA;	&quot;Type&quot;: &quot;Sphere&quot;,&#xD;&#xA;	&quot;Material&quot;: &quot;Red&quot;,&#xD;&#xA;	&quot;Point&quot; : {&#xD;&#xA;		&quot;x&quot;: 0,&#xD;&#xA;		&quot;y&quot;: 0,&#xD;&#xA;		&quot;z&quot;: 4&#xD;&#xA;	},&#xD;&#xA;    &quot;Rotation&quot;: {&#xD;&#xA;        &quot;x&quot;: 0,&#xD;&#xA;        &quot;y&quot;: 0,&#xD;&#xA;        &quot;z&quot;: 0&#xD;&#xA;    },&#xD;&#xA;    &quot;Scale&quot;: {&#xD;&#xA;        &quot;x&quot;: 1,&#xD;&#xA;        &quot;y&quot;: 1,&#xD;&#xA;        &quot;z&quot;: 1&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;[![Image rendered correctly][2]][2]&#xD;&#xA;&#xD;&#xA;But when I use non uniform scaling, the sphere gets seemingly distorted on a axis not modified by scale:&#xD;&#xA;```&#xD;&#xA;{&#xD;&#xA;	&quot;Type&quot;: &quot;Sphere&quot;,&#xD;&#xA;	&quot;Material&quot;: &quot;Red&quot;,&#xD;&#xA;	&quot;Point&quot; : {&#xD;&#xA;		&quot;x&quot;: 0,&#xD;&#xA;		&quot;y&quot;: 0,&#xD;&#xA;		&quot;z&quot;: 4&#xD;&#xA;	},&#xD;&#xA;    &quot;Rotation&quot;: {&#xD;&#xA;        &quot;x&quot;: 0,&#xD;&#xA;        &quot;y&quot;: 0,&#xD;&#xA;        &quot;z&quot;: 0&#xD;&#xA;    },&#xD;&#xA;    &quot;Scale&quot;: {&#xD;&#xA;      &quot;x&quot;: 1,&#xD;&#xA;      &quot;y&quot;: 1,&#xD;&#xA;      &quot;z&quot;: 0.5&#xD;&#xA;     }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;[![Image rendered incorrectly][3]][3]&#xD;&#xA;&#xD;&#xA;My Camera is positioned as follows: (it's transformation matrices should't change the ray, they are applied using the Ray transform functions with a matrix built from translate * rotate).&#xD;&#xA;```&#xD;&#xA;{&#xD;&#xA;	&quot;FOV&quot;: 60,&#xD;&#xA;	&quot;Position&quot;: {&#xD;&#xA;		&quot;x&quot;:  0.0,&#xD;&#xA;		&quot;y&quot;:  0.0,&#xD;&#xA;		&quot;z&quot;:  0.0&#xD;&#xA;	},&#xD;&#xA;  &quot;Rotation&quot;: {&#xD;&#xA;    &quot;x&quot;: 0.0,&#xD;&#xA;    &quot;y&quot;: 0.0,&#xD;&#xA;    &quot;z&quot;: 0.0&#xD;&#xA;  }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now I'm wondering whether my code is correct or not. Have I got something conceptually wrong with the coordinate transformations? I've searched a lot on the internet, but didn't find a complete guide on how to perform that for points, vectors and normals.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.terathon.com/gdc12_lengyel.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/FhsvG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/uuevl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39683" PostHistoryTypeId="1" PostId="13256" RevisionGUID="5c82d0c5-0c8b-4246-a6bb-562eec1a1432" CreationDate="2023-02-01T19:16:49.113" UserId="19510" Text="Converting points, vectors, normals between world and object space for a ray tracer gives weird results" ContentLicense="CC BY-SA 4.0" />
  <row Id="39684" PostHistoryTypeId="3" PostId="13256" RevisionGUID="5c82d0c5-0c8b-4246-a6bb-562eec1a1432" CreationDate="2023-02-01T19:16:49.113" UserId="19510" Text="|raytracing|transformations|c++|glm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39685" PostHistoryTypeId="2" PostId="13257" RevisionGUID="62f40f3d-fea4-4024-88ea-ac55c342281c" CreationDate="2023-02-01T19:30:02.317" UserId="445" Text="I think you have the wrong order of matrix multiplication.&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;    _transform_world_to_object = translate * rotate * scale;&#xD;&#xA;    _transform_object_to_world = glm::inverse(_transform_world_to_object);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;`translate * rotate * scale` is the appropriate multiplication/composition order for a conventional object-to-world coordinate transformation: first, scale the object, then rotate the scaled object, then translate the rotated object.&#xD;&#xA;&#xD;&#xA;But you are instead doing them in the opposite order. Thus, the translation amount is scaled by the scale, so your z distance of 4 becomes 4 × 0.5 = 2, closer to the camera.&#xD;&#xA;&#xD;&#xA;Try this instead:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;    _transform_world_to_object = scale * rotate * translate;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Or you can compute the object-to-world matrix directly (this will require changing all your minus signs) and world-to-object as the inverse of it. Different path, same result." ContentLicense="CC BY-SA 4.0" />
  <row Id="39687" PostHistoryTypeId="5" PostId="13253" RevisionGUID="5973c509-5e4d-4659-9bc8-84f47b0faad4" CreationDate="2023-02-02T05:56:45.780" UserId="13273" Comment="URL is a link now" Text="I assume you mean glowing geometry (not sky functions). There are several ways to do this, but as a simple example (not optimized ofc): since you have a pointlight you could ray trace a sphere or project a 3D disk with analytic AA (would remove jaggies/flicker at great distance) into a separate texture (with visibility occlusion!) and apply a bloom filter on top of the sphere (maybe separated Gaussian filter or according to: [][1]https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom).&#xD;&#xA;&#xD;&#xA;Hope this was helpful!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom" ContentLicense="CC BY-SA 4.0" />
  <row Id="39688" PostHistoryTypeId="24" PostId="13253" RevisionGUID="5973c509-5e4d-4659-9bc8-84f47b0faad4" CreationDate="2023-02-02T05:56:45.780" Comment="Proposed by 13273 approved by 13095 edit id of 612" ContentLicense="CC BY-SA 4.0" />
  <row Id="39689" PostHistoryTypeId="2" PostId="13258" RevisionGUID="d583888b-5ff8-47d3-8651-2684ffe08484" CreationDate="2023-02-02T13:57:35.673" UserId="10932" Text="I've spent the past few months building a path tracing architecture but primarily focusing on just optimizing the speed of the tracing.  It can produce pretty images quickly, but now I need to actually calculate physically accurate values as I'm using this to process real data.  I have a quantum efficiency for the sensor (and thankfully I'm dealing with fairly narrow bands so can focus on specific wavelengths) and from that I must calculate the signal.  Obviously simulating each individual photon is completely infeasible but we can reasonably obtain an approximation of the number of photons by using the received power multiplied by exposure time and dividing by the photon energy. But this now means I must calculate the received power.&#xD;&#xA;&#xD;&#xA;A BRDF (or BTDF/BSDF) relate the outgoing radiance and the incoming radiance, where radiance has units of $\left[W \cdot sr^{−1} \cdot m^{−2}\right]$.  How would you go about using this radiance value to obtain the power incident on the sensor?  Thinking about it conceptually, my initial guess is:&#xD;&#xA;&#xD;&#xA;1. Calculate the solid angle subtended by the camera's aperture relative to the intersection point&#xD;&#xA;2. Multiply that solid angle by the radiance of the ray to obtain the *irradiance* (in units of $[W\cdot m^{-2}]$&#xD;&#xA;3. Multiply the *irradiance* by the area of the aperture to obtain the *power* (in units of $[W]$)&#xD;&#xA;&#xD;&#xA;This *feels* right as, assuming the radiance off of a surface point does not change much over small angles, integrating the radiance over just the portion of the hemisphere which points at the camera should be equal to multiplying by the solid angle subtended by the camera's aperture.  And multiplying the aperture would model the amount of light actually collected.  But doing both of these things seems like it is double counting the aperture.  And this completely ignores the area of the pixel.&#xD;&#xA;&#xD;&#xA;I thought that perhaps you would multiply the *irradiance* by the pixel area, but ideally the optical system is focusing light from a single point in the world onto a single point on the sensor, and is not distributing that across the pixel.  And I also wouldn't know how this works with trying to handle multiple rays.&#xD;&#xA;&#xD;&#xA;So my question can be summarized as follows:&#xD;&#xA;- How do you calculate the received power given an aperture and pixel size&#xD;&#xA;- How does this change if you have multiple rays&#xD;&#xA;- How would you do this for a point-source of light shining directly into the camera?  (Think, taking a picture of a star.  This obviously wouldn't be backward ray traced, but the same concept applies except now it is for a single point projected onto the image plane." ContentLicense="CC BY-SA 4.0" />
  <row Id="39691" PostHistoryTypeId="1" PostId="13258" RevisionGUID="d583888b-5ff8-47d3-8651-2684ffe08484" CreationDate="2023-02-02T13:57:35.673" UserId="10932" Text="How is Aperture and Pixel Size accounted for in calculating received intensity using ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39692" PostHistoryTypeId="3" PostId="13258" RevisionGUID="d583888b-5ff8-47d3-8651-2684ffe08484" CreationDate="2023-02-02T13:57:35.673" UserId="10932" Text="|raytracing|photo-realistic|radiosity|photometric|light|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39693" PostHistoryTypeId="5" PostId="13258" RevisionGUID="92f82089-322e-4415-95f7-805fcc463b58" CreationDate="2023-02-02T14:40:27.827" UserId="10932" Comment="added 1539 characters in body" Text="I've spent the past few months building a path tracing architecture but primarily focusing on just optimizing the speed of the tracing.  It can produce pretty images quickly, but now I need to actually calculate physically accurate values as I'm using this to process real data.  I have a quantum efficiency for the sensor (and thankfully I'm dealing with fairly narrow bands so can focus on specific wavelengths) and from that I must calculate the signal.  Obviously simulating each individual photon is completely infeasible but we can reasonably obtain an approximation of the number of photons by using the received power multiplied by exposure time and dividing by the photon energy. But this now means I must calculate the received power.&#xD;&#xA;&#xD;&#xA;A BRDF (or BTDF/BSDF) relate the outgoing radiance and the incoming radiance, where radiance has units of $\left[W \cdot sr^{−1} \cdot m^{−2}\right]$.  How would you go about using this radiance value to obtain the power incident on the sensor?  Thinking about it conceptually, my initial guess is:&#xD;&#xA;&#xD;&#xA;1. Calculate the solid angle subtended by the camera's aperture relative to the intersection point&#xD;&#xA;2. Multiply that solid angle by the radiance of the ray to obtain the *irradiance* (in units of $[W\cdot m^{-2}]$&#xD;&#xA;3. Multiply the *irradiance* by the area of the aperture to obtain the *power* (in units of $[W]$)&#xD;&#xA;&#xD;&#xA;This *feels* right as, assuming the radiance off of a surface point does not change much over small angles, integrating the radiance over just the portion of the hemisphere which points at the camera should be equal to multiplying by the solid angle subtended by the camera's aperture.  And multiplying the aperture would model the amount of light actually collected.  But doing both of these things seems like it is double counting the aperture.  And this completely ignores the area of the pixel.&#xD;&#xA;&#xD;&#xA;I thought that perhaps you would multiply the *irradiance* by the pixel area, but ideally the optical system is focusing light from a single point in the world onto a single point on the sensor, and is not distributing that across the pixel.  And I also wouldn't know how this works with trying to handle multiple rays.&#xD;&#xA;&#xD;&#xA;So my question can be summarized as follows:&#xD;&#xA;- How do you calculate the received power given an aperture and pixel size&#xD;&#xA;- How does this change if you have multiple rays&#xD;&#xA;- How would you do this for a point-source of light shining directly into the camera?  (Think, taking a picture of a star.  This obviously wouldn't be backward ray traced, but the same concept applies except now it is for a single point projected onto the image plane.&#xD;&#xA;&#xD;&#xA;# EDIT&#xD;&#xA;&#xD;&#xA;My original assumption was that the radiance was the irradiance distributed over the hemisphere above a point [![as might be depicted in this image.][1]][1].  However [this response to another question][2] states:&#xD;&#xA;&#xD;&#xA;&gt; Also note that you can't calculate radiance for a point source—it would be infinite, due to the fact the point source emits a finite amount of flux compressed into zero size. It subtends zero solid angle, from the receiver's point of view, so the $dω$ factor in the denominator of radiance would be zero.&#xD;&#xA;&#xD;&#xA;Which implies that the solid angle that matters is actually from the perspective of the observer.  Which I could understand as a BRDF is said to be reversible, in that the radiance along a ray is constant and it doesn't matter if that ray is followed in one direction or the other.&#xD;&#xA;&#xD;&#xA;This leaves me even more confused though, as then its not clear to me what to use as the solid angle to obtain the radiance.  Would you simply take the average of radiance values obtained by a pixel, then multiply by the solid angle of that pixel's field of view to obtain the irradiance?  This would seem to solve my problem as the size of the pixel is then directly proportional to the irradiance, which if multiplied by the aperture, means that I would be accounting for both aperture size and pixel size in the calculation of a pixel's received power.  Whether that is correct or not, I'm not sure.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/93tRY.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/a/10285/10932" ContentLicense="CC BY-SA 4.0" />
  <row Id="39694" PostHistoryTypeId="5" PostId="13258" RevisionGUID="8cd6d0d3-4f8a-4e56-a0d1-ac2060ed879c" CreationDate="2023-02-02T14:43:48.787" UserId="10932" Comment="added 839 characters in body" Text="I've spent the past few months building a path tracing architecture but primarily focusing on just optimizing the speed of the tracing.  It can produce pretty images quickly, but now I need to actually calculate physically accurate values as I'm using this to process real data.  I have a quantum efficiency for the sensor (and thankfully I'm dealing with fairly narrow bands so can focus on specific wavelengths) and from that I must calculate the signal.  Obviously simulating each individual photon is completely infeasible but we can reasonably obtain an approximation of the number of photons by using the received power multiplied by exposure time and dividing by the photon energy. But this now means I must calculate the received power.&#xD;&#xA;&#xD;&#xA;A BRDF (or BTDF/BSDF) relate the outgoing radiance and the incoming radiance, where radiance has units of $\left[W \cdot sr^{−1} \cdot m^{−2}\right]$.  How would you go about using this radiance value to obtain the power incident on the sensor?  Thinking about it conceptually, my initial guess is:&#xD;&#xA;&#xD;&#xA;1. Calculate the solid angle subtended by the camera's aperture relative to the intersection point&#xD;&#xA;2. Multiply that solid angle by the radiance of the ray to obtain the *irradiance* (in units of $[W\cdot m^{-2}]$&#xD;&#xA;3. Multiply the *irradiance* by the area of the aperture to obtain the *power* (in units of $[W]$)&#xD;&#xA;&#xD;&#xA;This *feels* right as, assuming the radiance off of a surface point does not change much over small angles, integrating the radiance over just the portion of the hemisphere which points at the camera should be equal to multiplying by the solid angle subtended by the camera's aperture.  And multiplying the aperture would model the amount of light actually collected.  But doing both of these things seems like it is double counting the aperture.  And this completely ignores the area of the pixel.&#xD;&#xA;&#xD;&#xA;I thought that perhaps you would multiply the *irradiance* by the pixel area, but ideally the optical system is focusing light from a single point in the world onto a single point on the sensor, and is not distributing that across the pixel.  And I also wouldn't know how this works with trying to handle multiple rays.&#xD;&#xA;&#xD;&#xA;So my question can be summarized as follows:&#xD;&#xA;- How do you calculate the received power given an aperture and pixel size&#xD;&#xA;- How does this change if you have multiple rays&#xD;&#xA;- How would you do this for a point-source of light shining directly into the camera?  (Think, taking a picture of a star.  This obviously wouldn't be backward ray traced, but the same concept applies except now it is for a single point projected onto the image plane.&#xD;&#xA;&#xD;&#xA;# EDIT&#xD;&#xA;&#xD;&#xA;My original assumption was that the radiance was the irradiance distributed over the hemisphere above a point [![as might be depicted in this image.][1]][1].  However [this response to another question][2] states:&#xD;&#xA;&#xD;&#xA;&gt; Also note that you can't calculate radiance for a point source—it would be infinite, due to the fact the point source emits a finite amount of flux compressed into zero size. It subtends zero solid angle, from the receiver's point of view, so the $dω$ factor in the denominator of radiance would be zero.&#xD;&#xA;&#xD;&#xA;Which implies that the solid angle that matters is actually from the perspective of the observer.  Which I could understand as a BRDF is said to be reversible, in that the radiance along a ray is constant and it doesn't matter if that ray is followed in one direction or the other.&#xD;&#xA;&#xD;&#xA;This leaves me even more confused though, as then its not clear to me what to use as the solid angle to obtain the radiance.  Would you simply take the average of radiance values obtained by a pixel, then multiply by the solid angle of that pixel's field of view to obtain the irradiance?  This would seem to solve my problem as the size of the pixel is then directly proportional to the irradiance, which if multiplied by the aperture, means that I would be accounting for both aperture size and pixel size in the calculation of a pixel's received power.  Whether that is correct or not, I'm not sure.  But it seems to be supported by the second half of that linked above response which states:&#xD;&#xA;&#xD;&#xA;&gt; Where radiance would actually show up is when dealing with an area light rather than a point light. Then you would have the flux being distributed over a finite solid angle from the receiver's point of view, and you'd get the incident irradiance by integrating the light's radiance over that solid angle.&#xD;&#xA;&#xD;&#xA;Whats not clear to me is if you are averaging the radiance received by all rays in a pixel and multiplying by the pixel's field-of-view solid angle, or if you are multiplying each ray by the solid angle the object subtends relative to the observer.  I believe it should be the former, as the solid angle subtended by the field-of-view of the pixel is what actually matters when calculating the amount of light received by the pixel.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/93tRY.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/a/10285/10932" ContentLicense="CC BY-SA 4.0" />
  <row Id="39695" PostHistoryTypeId="5" PostId="13258" RevisionGUID="2ed00377-ed6d-430e-9d38-061c19b4a1fc" CreationDate="2023-02-02T14:44:41.593" UserId="10932" Comment="added 47 characters in body" Text="I've spent the past few months building a path tracing architecture but primarily focusing on just optimizing the speed of the tracing.  It can produce pretty images quickly, but now I need to actually calculate physically accurate values as I'm using this to process real data.  I have a quantum efficiency for the sensor (and thankfully I'm dealing with fairly narrow bands so can focus on specific wavelengths) and from that I must calculate the signal.  Obviously simulating each individual photon is completely infeasible but we can reasonably obtain an approximation of the number of photons by using the received power multiplied by exposure time and dividing by the photon energy. But this now means I must calculate the received power.&#xD;&#xA;&#xD;&#xA;A BRDF (or BTDF/BSDF) relate the outgoing radiance and the incoming radiance, where radiance has units of $\left[W \cdot sr^{−1} \cdot m^{−2}\right]$.  How would you go about using this radiance value to obtain the power incident on the sensor?  Thinking about it conceptually, my initial guess is:&#xD;&#xA;&#xD;&#xA;1. Calculate the solid angle subtended by the camera's aperture relative to the intersection point&#xD;&#xA;2. Multiply that solid angle by the radiance of the ray to obtain the *irradiance* (in units of $[W\cdot m^{-2}]$&#xD;&#xA;3. Multiply the *irradiance* by the area of the aperture to obtain the *power* (in units of $[W]$)&#xD;&#xA;&#xD;&#xA;This *feels* right as, assuming the radiance off of a surface point does not change much over small angles, integrating the radiance over just the portion of the hemisphere which points at the camera should be equal to multiplying by the solid angle subtended by the camera's aperture.  And multiplying the aperture would model the amount of light actually collected.  But doing both of these things seems like it is double counting the aperture.  And this completely ignores the area of the pixel.&#xD;&#xA;&#xD;&#xA;I thought that perhaps you would multiply the *irradiance* by the pixel area, but ideally the optical system is focusing light from a single point in the world onto a single point on the sensor, and is not distributing that across the pixel.  And I also wouldn't know how this works with trying to handle multiple rays.&#xD;&#xA;&#xD;&#xA;So my question can be summarized as follows:&#xD;&#xA;- How do you calculate the received power given an aperture and pixel size&#xD;&#xA;- How does this change if you have multiple rays&#xD;&#xA;- How would you do this for a point-source of light shining directly into the camera?  (Think, taking a picture of a star.  This obviously wouldn't be backward ray traced, but the same concept applies except now it is for a single point projected onto the image plane.&#xD;&#xA;&#xD;&#xA;# EDIT&#xD;&#xA;&#xD;&#xA;My original assumption was that the radiance was the irradiance distributed over the hemisphere above a point such as depicted in the following figure.&#xD;&#xA;&#xD;&#xA;[![as might be depicted in this image.][1]][1].&#xD;&#xA;&#xD;&#xA;However [this response to another question][2] states:&#xD;&#xA;&#xD;&#xA;&gt; Also note that you can't calculate radiance for a point source—it would be infinite, due to the fact the point source emits a finite amount of flux compressed into zero size. It subtends zero solid angle, from the receiver's point of view, so the $dω$ factor in the denominator of radiance would be zero.&#xD;&#xA;&#xD;&#xA;Which implies that the solid angle that matters is actually from the perspective of the observer.  Which I could understand as a BRDF is said to be reversible, in that the radiance along a ray is constant and it doesn't matter if that ray is followed in one direction or the other.&#xD;&#xA;&#xD;&#xA;This leaves me even more confused though, as then its not clear to me what to use as the solid angle to obtain the radiance.  Would you simply take the average of radiance values obtained by a pixel, then multiply by the solid angle of that pixel's field of view to obtain the irradiance?  This would seem to solve my problem as the size of the pixel is then directly proportional to the irradiance, which if multiplied by the aperture, means that I would be accounting for both aperture size and pixel size in the calculation of a pixel's received power.  Whether that is correct or not, I'm not sure.  But it seems to be supported by the second half of that linked above response which states:&#xD;&#xA;&#xD;&#xA;&gt; Where radiance would actually show up is when dealing with an area light rather than a point light. Then you would have the flux being distributed over a finite solid angle from the receiver's point of view, and you'd get the incident irradiance by integrating the light's radiance over that solid angle.&#xD;&#xA;&#xD;&#xA;Whats not clear to me is if you are averaging the radiance received by all rays in a pixel and multiplying by the pixel's field-of-view solid angle, or if you are multiplying each ray by the solid angle the object subtends relative to the observer.  I believe it should be the former, as the solid angle subtended by the field-of-view of the pixel is what actually matters when calculating the amount of light received by the pixel.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/93tRY.png&#xD;&#xA;  [2]: https://computergraphics.stackexchange.com/a/10285/10932" ContentLicense="CC BY-SA 4.0" />
  <row Id="39696" PostHistoryTypeId="5" PostId="13258" RevisionGUID="71d09001-8aa8-4eed-9acc-2caefa0f678b" CreationDate="2023-02-02T16:36:31.933" UserId="10932" Comment="deleted 2024 characters in body; edited title" Text="*NOTE: Deleting the question to rephrase it after continuing to read other responses and toy around with it:*&#xD;&#xA;&#xD;&#xA;I've written a path tracer and am now working on implementing a physically accurate way of simulating the actual sensor response **for a given wavelength**$^*$, given an exposure time, aperture size, pixel size, and quantum efficiency.&#xD;&#xA;&#xD;&#xA;The current way I've thought about framing this is as follows (this algorithm is done for *each* pixel):&#xD;&#xA;1. Path-trace many rays and evaluate the [Bidirectional Reflectance Distribution Function (BRDF)][1] (or BTDF/BSDF) to obtain the radiance along each ray received by the pixel.  *This part is done*.&#xD;&#xA;2. Take all of the rays received by a pixel, and average their radiance values to obtain a &quot;received&quot; radiance (units of $[W\cdot sr^{-2} \cdot m^{-2}]$) for the pixel.&#xD;&#xA;4. Look up the solid angle field-of-view of a pixel (this is precalculated beforehand) and multiply that solid angle by the *radiance* to obtain the *irradiance* (units of $[W\cdot m^{-2}]$)&#xD;&#xA;5. Multiply the *irradiance* by the area of the aperture to obtain the received *power* (units of $[W]$)&#xD;&#xA;6. Multiply the *power* by the exposure time to obtain the *energy* (units of $[J]$)&#xD;&#xA;7. Divide the energy by the photon energy (given by $E = h f$) for a given wavelength to obtain the photon count.&#xD;&#xA;8. Multiply the photon count by the quantum efficiency and generate the signal.&#xD;&#xA;&#xD;&#xA;Is this the correct way of calculating this?  My primary concern is in **steps 2 and 3** as I am not terribly comfortable with solid angles.  My rationale is that the solid angle of the pixel's field-of-view determines how much of the scene is actually contributing light to the pixel, and we're approximating that part of the scene by casting discrete rays which we can then average.  And this should naturally capture the effect that increasing the pixel size correspondingly increases the pixel's solid angle thus an increase in the irradiance at the aperture that contributes to the pixel, and thus increased response.  But like I said, the nature of solid angles has me tripped up, particularly because it is often said that the radiance along a ray is reversible, and so I'm not sure &quot;which&quot; solid angle to actually be using.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;$^*$ *Currently I'm able to assume a single wavelength at a time, however in the future if I were to extend this to handle a broad-spectrum, I would modify **steps 1 and 2** to calculate the spectral radiance with units of $[W\cdot sr^{-2} \cdot m^{-2} \cdot Hz^{-1}]$.  Then when we continue on to **step 3** we would calculate a *spectral irradiance* with units of $[W\cdot m^{-2} \cdot Hz^{-1}]$, and then **step 4** would produce a spectral flux with units of $[W\cdot Hz^{-1}]$.  Then we calculate the energy of photons for each frequency in our spectrum to obtain the photon counts for each frequency and then convolve the resulting energy spectrum with the quantum efficiency spectrum.*&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="39697" PostHistoryTypeId="4" PostId="13258" RevisionGUID="71d09001-8aa8-4eed-9acc-2caefa0f678b" CreationDate="2023-02-02T16:36:31.933" UserId="10932" Comment="deleted 2024 characters in body; edited title" Text="How is Aperture and Pixel Size accounted for in calculating received power using ray tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39698" PostHistoryTypeId="2" PostId="13259" RevisionGUID="724930d9-676d-4be3-9502-a490118b5d08" CreationDate="2023-02-02T17:04:02.140" UserId="19526" Text="I'd like to identify transition points in an STL where the model goes from relatively large surface to a relatively small surface.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I think that if I had a function that showed me the minimal cross section area at any point I may be able to get this from a gradient of that scalar field.&#xD;&#xA;&#xD;&#xA;Forgive me, I'm not sure what this is called or even how to start googling around for this so anything is appreciated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ANUlC.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39700" PostHistoryTypeId="1" PostId="13259" RevisionGUID="724930d9-676d-4be3-9502-a490118b5d08" CreationDate="2023-02-02T17:04:02.140" UserId="19526" Text="Are there any techniques or algorithms for marking regions of a 3D model with small cross sections" ContentLicense="CC BY-SA 4.0" />
  <row Id="39701" PostHistoryTypeId="3" PostId="13259" RevisionGUID="724930d9-676d-4be3-9502-a490118b5d08" CreationDate="2023-02-02T17:04:02.140" UserId="19526" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39702" PostHistoryTypeId="2" PostId="13260" RevisionGUID="c29597c5-076f-4545-9462-12e5153b71a1" CreationDate="2023-02-02T19:04:39.533" UserId="10932" Text="So in my path tracer I sample both some bounce ray given an importance function for the current BRDF, and if applicable (reflection is non-specular) I directly sample all light sources (for my application, I am guaranteed to have very few).&#xD;&#xA;&#xD;&#xA;I recognize however, that directly sampling the light each time needs to be considered carefully, as we are no longer uniformly sampling our importance function.  But my hope is that by doing it this way the variance of the samples can be decreased and the image can converge faster.&#xD;&#xA;&#xD;&#xA;My understanding though is that we would need to directly calculate the radiance from the light separately which would require three things:&#xD;&#xA;&#xD;&#xA;1. Have the light source defined in terms of luminosity (in units of $W$)&#xD;&#xA;2. Calculate the emitted *irradiance* of the light by dividing the luminosity (total power output) by the surface area (in units of $[W\cdot m^{-2}]$)&#xD;&#xA;3. Calculate the *radiance* incoming at that point by dividing the *irradiance* by the solid-angle subtended by the light source (units of $[W\cdot sr^{-1}\cdot m^{-2}]$&#xD;&#xA;&#xD;&#xA;This seems like it would work fine so long as the following is true:&#xD;&#xA;- The solid-angle subtended by the light is easy to calculate.&#xD;&#xA;&#xD;&#xA;Thankfully, for my purposes, my lights are always going to be either spheres or rectangles and so calculating the solid-angle they subtend is not terribly complicated, but if some arbitrary complex geometry was used as a light, it would be far more complicated then, no?&#xD;&#xA;&#xD;&#xA;Beside that point of mild confusion, is the rest of what I outlined sensible?  " ContentLicense="CC BY-SA 4.0" />
  <row Id="39704" PostHistoryTypeId="1" PostId="13260" RevisionGUID="c29597c5-076f-4545-9462-12e5153b71a1" CreationDate="2023-02-02T19:04:39.533" UserId="10932" Text="Directly Sampling an Area Light" ContentLicense="CC BY-SA 4.0" />
  <row Id="39705" PostHistoryTypeId="3" PostId="13260" RevisionGUID="c29597c5-076f-4545-9462-12e5153b71a1" CreationDate="2023-02-02T19:04:39.533" UserId="10932" Text="|lighting|global-illumination|importance-sampling|radiosity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39706" PostHistoryTypeId="5" PostId="13258" RevisionGUID="db8d6ac0-2863-4a10-b0e3-4e2c74a169ce" CreationDate="2023-02-02T20:58:17.167" UserId="10932" Comment="edited body" Text="*NOTE: Deleting the question to rephrase it after continuing to read other responses and toy around with it:*&#xD;&#xA;&#xD;&#xA;I've written a path tracer and am now working on implementing a physically accurate way of simulating the actual sensor response **for a given wavelength**$^*$, given an exposure time, aperture size, pixel size, and quantum efficiency.&#xD;&#xA;&#xD;&#xA;The current way I've thought about framing this is as follows (this algorithm is done for *each* pixel):&#xD;&#xA;1. Path-trace many rays and evaluate the [Bidirectional Reflectance Distribution Function (BRDF)][1] (or BTDF/BSDF) to obtain the radiance along each ray received by the pixel.  *This part is done*.&#xD;&#xA;2. Take all of the rays received by a pixel, and average their radiance values to obtain a &quot;received&quot; radiance (units of $[W\cdot sr^{-1} \cdot m^{-2}]$) for the pixel.&#xD;&#xA;4. Look up the solid angle field-of-view of a pixel (this is precalculated beforehand) and multiply that solid angle by the *radiance* to obtain the *irradiance* (units of $[W\cdot m^{-2}]$)&#xD;&#xA;5. Multiply the *irradiance* by the area of the aperture to obtain the received *power* (units of $[W]$)&#xD;&#xA;6. Multiply the *power* by the exposure time to obtain the *energy* (units of $[J]$)&#xD;&#xA;7. Divide the energy by the photon energy (given by $E = h f$) for a given wavelength to obtain the photon count.&#xD;&#xA;8. Multiply the photon count by the quantum efficiency and generate the signal.&#xD;&#xA;&#xD;&#xA;Is this the correct way of calculating this?  My primary concern is in **steps 2 and 3** as I am not terribly comfortable with solid angles.  My rationale is that the solid angle of the pixel's field-of-view determines how much of the scene is actually contributing light to the pixel, and we're approximating that part of the scene by casting discrete rays which we can then average.  And this should naturally capture the effect that increasing the pixel size correspondingly increases the pixel's solid angle thus an increase in the irradiance at the aperture that contributes to the pixel, and thus increased response.  But like I said, the nature of solid angles has me tripped up, particularly because it is often said that the radiance along a ray is reversible, and so I'm not sure &quot;which&quot; solid angle to actually be using.&#xD;&#xA;&#xD;&#xA;***&#xD;&#xA;&#xD;&#xA;$^*$ *Currently I'm able to assume a single wavelength at a time, however in the future if I were to extend this to handle a broad-spectrum, I would modify **steps 1 and 2** to calculate the spectral radiance with units of $[W\cdot sr^{-1} \cdot m^{-2} \cdot Hz^{-1}]$.  Then when we continue on to **step 3** we would calculate a *spectral irradiance* with units of $[W\cdot m^{-2} \cdot Hz^{-1}]$, and then **step 4** would produce a spectral flux with units of $[W\cdot Hz^{-1}]$.  Then we calculate the energy of photons for each frequency in our spectrum to obtain the photon counts for each frequency and then convolve the resulting energy spectrum with the quantum efficiency spectrum.*&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function" ContentLicense="CC BY-SA 4.0" />
  <row Id="39709" PostHistoryTypeId="2" PostId="13262" RevisionGUID="daafa373-28f7-496d-80c9-d1ee5bd8ad4b" CreationDate="2023-02-03T05:53:18.313" UserId="19527" Text="I was reading a thread where you have comprehensively answered about radiometric units (https://computergraphics.stackexchange.com/questions/10284/deriving-radiance-from-irradiance-and-intensity/13261#13261). &#xD;&#xA;&#xD;&#xA;My question is whether we can convert from **W/cm2 ( or W/m2) to W/sr**.&#xD;&#xA;We are measuring the irradiance (W/cm2) at 1 meter distance.&#xD;&#xA;Please explain.&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 4.0" />
  <row Id="39711" PostHistoryTypeId="1" PostId="13262" RevisionGUID="daafa373-28f7-496d-80c9-d1ee5bd8ad4b" CreationDate="2023-02-03T05:53:18.313" UserId="19527" Text="Conversion from W/cm2 ( or W/m2) to W/sr" ContentLicense="CC BY-SA 4.0" />
  <row Id="39712" PostHistoryTypeId="3" PostId="13262" RevisionGUID="daafa373-28f7-496d-80c9-d1ee5bd8ad4b" CreationDate="2023-02-03T05:53:18.313" UserId="19527" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39713" PostHistoryTypeId="2" PostId="13263" RevisionGUID="04fd3e0e-b39d-4285-8593-9003c958e8b6" CreationDate="2023-02-03T08:59:20.120" UserId="13273" Text="I know that the OpenGL driver is implemented by hardware vendors, so this questions may not have a consistent answer.&#xD;&#xA;&#xD;&#xA;If I use one of the glGet methods, does OpenGL get the information from the GPU or from the CPU? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39715" PostHistoryTypeId="1" PostId="13263" RevisionGUID="04fd3e0e-b39d-4285-8593-9003c958e8b6" CreationDate="2023-02-03T08:59:20.120" UserId="13273" Text="Where does the OpenGL driver get the glGet values from?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39716" PostHistoryTypeId="3" PostId="13263" RevisionGUID="04fd3e0e-b39d-4285-8593-9003c958e8b6" CreationDate="2023-02-03T08:59:20.120" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39717" PostHistoryTypeId="2" PostId="13264" RevisionGUID="e3756ae1-6a3d-4f78-bca3-0eb4ffa94d6a" CreationDate="2023-02-03T12:40:32.827" UserId="7952" Text="It varies depending on the value you are getting. Some values come from files, such as values that are constant but GPU specific(inf files on windows if I remember correctly). Some come from the driver, run time values that are GPU specific. Some come from the GPU directly, values that are set directly or indirectly for a particular run. &#xD;&#xA;&#xD;&#xA;How each driver implements all that is probably going to vary widely." ContentLicense="CC BY-SA 4.0" />
  <row Id="39719" PostHistoryTypeId="5" PostId="13264" RevisionGUID="eb67f11c-b0dd-4838-8ffa-fa7b9fc4cd80" CreationDate="2023-02-03T13:09:58.883" UserId="7952" Comment="added 300 characters in body" Text="It varies depending on the value you are getting. Some values come from files, such as values that are constant but GPU specific(inf files on windows if I remember correctly). Some come from the driver, run time values that are GPU specific. Some come from the GPU directly, values that are set directly or indirectly for a particular run. &#xD;&#xA;&#xD;&#xA;How each driver implements all that is probably going to vary widely.&#xD;&#xA;&#xD;&#xA;Values like the clear color and culling state are runtime, so the driver is going to be tracking it. The value will almost certainly be sitting on the user side so it won't incur a  system call. (So that would be CPU) So it is very likely the driver will be able to fill the value directly. &#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="39721" PostHistoryTypeId="5" PostId="13262" RevisionGUID="d9582a1f-27cf-4fbc-9c39-ad2060a64df5" CreationDate="2023-02-03T15:17:51.733" UserId="13095" Comment="Update link since it pointed to an deleted contribution" Text="I was reading a thread where you have comprehensively answered about radiometric units (https://computergraphics.stackexchange.com/q/10284/13095). &#xD;&#xA;&#xD;&#xA;My question is whether we can convert from **W/cm2 ( or W/m2) to W/sr**.&#xD;&#xA;We are measuring the irradiance (W/cm2) at 1 meter distance.&#xD;&#xA;Please explain.&#xD;&#xA;Thanks " ContentLicense="CC BY-SA 4.0" />
  <row Id="39722" PostHistoryTypeId="2" PostId="13265" RevisionGUID="0a0461fe-2257-4c3c-80b9-6e491cb14fb6" CreationDate="2023-02-03T22:36:38.587" UserId="7952" Text="The regions you are looking for can be found using cross-section analysis.&#xD;&#xA;&#xD;&#xA;Cutting the model with a plane will result in a polygon(s). The area of the polygon can be computed saved and compared to other cross sections. This information is compared with changes in the cross section size to reject edge regions and find areas where there are sudden changes in size. The plane is rotated and the process repeated. The number of angles of the plane can be limited to about 16 to get a reasonable analysis.&#xD;&#xA;&#xD;&#xA;The entire algorithm depends on a relatively easy to write function that computes the distance from the plane. When the end points of an edge has both a positive and a negative distance to the plane, then the edge intersection point with the plane is computed and saved. (corner cases must be dealt with as well). The individual vertices that are generated also have to be bucket sorted into individual polygon's using the edge info.&#xD;&#xA;&#xD;&#xA;There are engineering tools that *might* be able to do this automatically such as  ParaView (open source) and SolidWorks (commercial).&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39724" PostHistoryTypeId="5" PostId="13253" RevisionGUID="503af04c-69a6-42af-a748-aa3caa2f5d59" CreationDate="2023-02-04T07:35:32.473" UserId="16241" Comment="Add title to bare hyperlink" Text="I assume you mean glowing geometry (not sky functions). There are several ways to do this, but as a simple example (not optimized ofc): since you have a pointlight you could ray trace a sphere or project a 3D disk with analytic AA (would remove jaggies/flicker at great distance) into a separate texture (with visibility occlusion!) and apply a bloom filter on top of the sphere (maybe separated Gaussian filter or according to: [Physically Based Bloom][1]).&#xD;&#xA;&#xD;&#xA;Hope this was helpful!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom" ContentLicense="CC BY-SA 4.0" />
  <row Id="39725" PostHistoryTypeId="24" PostId="13253" RevisionGUID="503af04c-69a6-42af-a748-aa3caa2f5d59" CreationDate="2023-02-04T07:35:32.473" Comment="Proposed by 16241 approved by 13095 edit id of 613" ContentLicense="CC BY-SA 4.0" />
  <row Id="39726" PostHistoryTypeId="2" PostId="13266" RevisionGUID="d54568ba-925c-4ced-b231-e80a5956f7ec" CreationDate="2023-02-04T16:59:25.543" UserId="10096" Text="To understand whether your steps are correct you should compare to the mathematical formulation.&#xD;&#xA;&#xD;&#xA;**Step 1** is supposedly solving the rendering equation for some collection of initial rays&#xD;&#xA;&#xD;&#xA;$$L_o(x_0, \omega_o) = L_e(x, \omega_o) + \int_{\mathcal{H}^2(x_0, N_{x_0})} f(\omega_o, x_0, \omega_i)L_i(x_0,\omega_i)(N_{x_0}\cdot \omega_i)\,d\omega_i.$$&#xD;&#xA;&#xD;&#xA;Here $L_o(x_0,\omega_o)$ is the outgoing radiance function, i.e. the radiance leaving some surface point $x_0$ in direction $\omega_o$. $L_e(x_0,\omega_o)$ is the emitted radiance function, i.e. the radiance emitted from point $x_0$ in direction $\omega_o$. Next we have an integral over the hemisphere at point $x_0$ whose up direction is aligned with the normal $N_{x_0}$ at $x_0$. You can formalize this set as $\mathcal{H}^2(x_0,N_{x_0}) = \{z\in\mathbb{R}^3\,:\, \|z-x_0\|=1, \, (z-x_0)\cdot N_{x_0}\geq 0\}$, in practice one parametrizes it using spherical coordinates. $f$ is the BRDF. $L_i$ is the incident radiance function, i.e. $L_i(x_0,\omega_i) = L_o(r(x_0, \omega_i), -\omega_i)$, where $r$ is the ray-tracing function. Finally $(N_{x_0}\cdot \omega_i) = \cos\theta_i$ is the Lambertian cosine term that accounts for the angle between the ray and the surface.&#xD;&#xA;&#xD;&#xA;For simplicity the above can be rewritten using linear operator notation as $L = L_e + TL$, from where one may get the Neumann expansion $L = \sum_{k=0}^{\infty}T^kL_e$, which is essentially a sum of increasingly dimensional integrals. You typically apply Monte Carlo to get an approximate solution of the latter.&#xD;&#xA;&#xD;&#xA;The question is also how you choose the rays. Since you mentioned that you have an aperture, a film, and an exposure time, let us model the aperture as some set $\mathcal{A}\subset\mathbb{R}^3$, the film as $\mathcal{F}\subset\mathbb{R}^3$, and the exposure time as an interval $[t_0,t_1]$. Both of $\mathcal{F}$ and $\mathcal{A}$ are two-dimensional manifolds, and usually $\mathcal{A}$ is chosen to be a disk some distance in front of the film $\mathcal{F}$, and $\mathcal{F}$ is chosen to be a rectangle (in order to match the screen). The response at a given pixel (i,j) can be modeled as a weighted integration over the arriving radiance on the film, with some sensitivity function $w_{ij}$:&#xD;&#xA;$$I_{ij} = \int_{t_0}^{t_1}\int_{\mathcal{F}}\int_{\mathcal{A}_{\mathcal{H}^2(x_{-1}, N_{x_{-1}})}}w_{ij}(x_{-1}, -\omega_o)L_i(x_{-1}, -\omega_o))(N_{x_{-1}}\cdot (-\omega_o))\, d(-\omega_o)dx_{-1}dt.$$&#xD;&#xA;&#xD;&#xA;Here $\mathcal{A}_{\mathcal{H}^2(x_{-1}, N_{x_{-1}})}$ is the solid angle set of the aperture as seen from pixel $x_{-1}$. Here I have assumed that nothing depends on times (i.e. brdf, scene geometry, lights, aperture, film, sensitivity, all stay the same). With this assumption you can pop out the time integral as a $(t_1-t_0)$ multiplicative term as you describe in **Step 5**.&#xD;&#xA;&#xD;&#xA;Note that physically the aperture is typically in front of the sensor, so I have modeled that. One could of course set the aperture behind the sensor in CG, and then you would get the solid angle of the film pixel's set instead. We also need to get rid of that cosine dot product, which can be done by setting the sensitivity $w_{ij} = (N_{x_{-1}}\cdot (-\omega_o))^{-1}$. You want to average the radiance (**step 2**) and then multiply by the solid angle measure of the aperture as seen by a specific point $x_{-1}$ (**step 3** in your aperture/pixel reversed scenario has the solid angle of the pixel), and the area of the pixel (**step 4** has the area of the aperture). This flip of the aperture and film pixel is not really an issue as noted, but I'll stick to the physical convention (i.e. the reverse of yours). The main issue is that averaging and then multiplying by the solid angle corresponding to the the aperture as seen by the whole pixel, vs by a single point is slightly wrong. Note that $\mathcal{A}_{\mathcal{H}^2(x_{-1}, N_{x_{-1}})}$ is defined per point, and it varies for the different points on the film's pixel, so you cannot precompute one value for the pixel and call it a day, unless the pixel consists only of a single point - then it would be valid.&#xD;&#xA;&#xD;&#xA;There is however, another formulation that is amenable to your idea, however it uses the area formulation instead of the solid angle one. Namely&#xD;&#xA;&#xD;&#xA;$$I_{ij} = \int_{t_0}^{t_1}\int_{\mathcal{F}}\int_{\mathcal{A}}w_{ij}(x_{-1}, x_{-1/2})L_i(x_{-1}, -\omega_o))G(x_{-1},x_{-1/2})\, d x_{-1/2}dx_{-1}dt.$$&#xD;&#xA;&#xD;&#xA;Here $x_{-1/2}$ is a point on the aperture, and $-\omega_o = \frac{x_{-1/2}-x_{-1}}{\|x_{-1/2}-x_{-1}\|}$, and $G(x_{-1},x_{-1/2}) = \frac{(N_{x_{-1}}\cdot(-\omega_o))(N_{x_{-1/2}}\cdot \omega_o)}{\|x_{-1/2}-x_{-1}\|^2}$. Choose&#xD;&#xA;&#xD;&#xA;$$w_{ij}(x_{-1}, x_{-1/2}) = \frac{\boldsymbol{1}_{\mathcal{P}_{ij}}(x_{-1})}{G(x_{-1},x_{-1/2})},$$&#xD;&#xA;&#xD;&#xA;where $\mathcal{P}_{ij}\subseteq \mathcal{F}$ is the set of pixel $(i,j)$ on the film, and $\boldsymbol{1}_{\mathcal{X}}$ is the indicator function. Then you get what you want, with the small change that you multiply the average by the areas $|\mathcal{A}|$ and $|\mathcal{P}_{ij}|$ , without involving solid angles of those." ContentLicense="CC BY-SA 4.0" />
  <row Id="39728" PostHistoryTypeId="5" PostId="13266" RevisionGUID="ee636e2c-af2f-4989-8ba4-74787179f51e" CreationDate="2023-02-04T17:10:00.450" UserId="10096" Comment="added 830 characters in body" Text="To understand whether your steps are correct you should compare to the mathematical formulation.&#xD;&#xA;&#xD;&#xA;**Step 1** is supposedly solving the rendering equation for some collection of initial rays&#xD;&#xA;&#xD;&#xA;$$L_o(x_0, \omega_o) = L_e(x, \omega_o) + \int_{\mathcal{H}^2(x_0, N_{x_0})} f(\omega_o, x_0, \omega_i)L_i(x_0,\omega_i)(N_{x_0}\cdot \omega_i)\,d\omega_i.$$&#xD;&#xA;&#xD;&#xA;Here $L_o(x_0,\omega_o)$ is the outgoing radiance function, i.e. the radiance leaving some surface point $x_0$ in direction $\omega_o$. $L_e(x_0,\omega_o)$ is the emitted radiance function, i.e. the radiance emitted from point $x_0$ in direction $\omega_o$. Next we have an integral over the hemisphere at point $x_0$ whose up direction is aligned with the normal $N_{x_0}$ at $x_0$. You can formalize this set as $\mathcal{H}^2(x_0,N_{x_0}) = \{z\in\mathbb{R}^3\,:\, \|z-x_0\|=1, \, (z-x_0)\cdot N_{x_0}\geq 0\}$, in practice one parametrizes it using spherical coordinates. $f$ is the BRDF. $L_i$ is the incident radiance function, i.e. $L_i(x_0,\omega_i) = L_o(r(x_0, \omega_i), -\omega_i)$, where $r$ is the ray-tracing function. Finally $(N_{x_0}\cdot \omega_i) = \cos\theta_i$ is the Lambertian cosine term that accounts for the angle between the ray and the surface.&#xD;&#xA;&#xD;&#xA;For simplicity the above can be rewritten using linear operator notation as $L = L_e + TL$, from where one may get the Neumann expansion $L = \sum_{k=0}^{\infty}T^kL_e$, which is essentially a sum of increasingly dimensional integrals. You typically apply Monte Carlo to get an approximate solution of the latter.&#xD;&#xA;&#xD;&#xA;The question is also how you choose the rays. Since you mentioned that you have an aperture, a film, and an exposure time, let us model the aperture as some set $\mathcal{A}\subset\mathbb{R}^3$, the film as $\mathcal{F}\subset\mathbb{R}^3$, and the exposure time as an interval $[t_0,t_1]$. Both of $\mathcal{F}$ and $\mathcal{A}$ are two-dimensional manifolds, and usually $\mathcal{A}$ is chosen to be a disk some distance in front of the film $\mathcal{F}$, and $\mathcal{F}$ is chosen to be a rectangle (in order to match the screen). The response at a given pixel (i,j) can be modeled as a weighted integration over the arriving radiance on the film, with some sensitivity function $w_{ij}$:&#xD;&#xA;$$I_{ij} = \int_{t_0}^{t_1}\int_{\mathcal{F}}\int_{\mathcal{A}_{\mathcal{H}^2(x_{-1}, N_{x_{-1}})}}w_{ij}(x_{-1}, -\omega_o)L_i(x_{-1}, -\omega_o))(N_{x_{-1}}\cdot (-\omega_o))\, d(-\omega_o)dx_{-1}dt.$$&#xD;&#xA;&#xD;&#xA;Here $\mathcal{A}_{\mathcal{H}^2(x_{-1}, N_{x_{-1}})}$ is the solid angle set of the aperture as seen from pixel $x_{-1}$. Here I have assumed that nothing depends on time (i.e. brdf, scene geometry, lights, aperture, film, sensitivity, all stay the same). With this assumption you can pop out the time integral as a $(t_1-t_0)$ multiplicative term as you describe in **Step 5**.&#xD;&#xA;&#xD;&#xA;Note that physically the aperture is typically in front of the sensor, so I have modeled that instead of what you did. One could of course set the aperture behind the sensor in CG for convenience, and then you would get the solid angle of the film pixel's set as you do. I will however stick to the physical formulation of the aperture being in front of the sensor. We also need to get rid of that cosine dot product and want to integrate only over the pixel and not the whole film, which can be done by setting the sensitivity $w_{ij}(x_{-1},-\omega_o) = \frac{\boldsymbol{1}_{\mathcal{P}_{ij}}(x_{-1})}{N_{x_{-1}}\cdot (-\omega_o)}$. Here $\mathcal{P}_{ij}\subset \mathcal{F}$ is the set of points of the pixel on the film, and $\boldsymbol{1}_{\mathcal{X}}$ is the indicator function (it is one on the set, and zero outside of it). You want to average the radiance (**step 2**) and then multiply by the solid angle measure of the aperture as seen by a specific point $x_{-1}$ (**step 3** in your aperture/pixel reversed scenario has the solid angle of the pixel), and the area of the pixel (**step 4** has the area of the aperture). This flip of the aperture and film pixel is not really an issue as noted, but I'll stick to the physical convention (i.e. the reverse of yours). The main issue is that averaging and then multiplying by the solid angle corresponding to the the aperture as seen by the whole pixel, vs by a single point is slightly wrong. Note that $\mathcal{A}_{\mathcal{H}^2(x_{-1}, N_{x_{-1}})}$ is defined per point, and it varies for the different points on the film's pixel, so you cannot precompute one value for the pixel and call it a day, unless the pixel consists only of a single point - then it would be valid.&#xD;&#xA;&#xD;&#xA;There is another formulation that is amenable to a slight modification of your idea, however it uses the area formulation instead of the solid angle one. Namely&#xD;&#xA;&#xD;&#xA;$$I_{ij} = \int_{t_0}^{t_1}\int_{\mathcal{F}}\int_{\mathcal{A}}w_{ij}(x_{-1}, x_{-1/2})L_i(x_{-1}, -\omega_o))G(x_{-1},x_{-1/2})\, d x_{-1/2}dx_{-1}dt.$$&#xD;&#xA;&#xD;&#xA;Here $x_{-1/2}$ is a point on the aperture, and $-\omega_o = \frac{x_{-1/2}-x_{-1}}{\|x_{-1/2}-x_{-1}\|}$, and $G(x_{-1},x_{-1/2}) = \frac{(N_{x_{-1}}\cdot(-\omega_o))(N_{x_{-1/2}}\cdot \omega_o)}{\|x_{-1/2}-x_{-1}\|^2}$. Choose&#xD;&#xA;&#xD;&#xA;$$w_{ij}(x_{-1}, x_{-1/2}) = \frac{\boldsymbol{1}_{\mathcal{P}_{ij}}(x_{-1})}{G(x_{-1},x_{-1/2})},$$&#xD;&#xA;&#xD;&#xA;where $\mathcal{P}_{ij}\subseteq \mathcal{F}$ is the set of pixel $(i,j)$ on the film, and $\boldsymbol{1}_{\mathcal{X}}$ is the indicator function. Then you get what you want, with the small change that you multiply the average by the areas $|\mathcal{A}|$ and $|\mathcal{P}_{ij}|$ , without involving solid angles of those.&#xD;&#xA;&#xD;&#xA;A general remark I have is that if you want to convert between different units then you need integration and differentiation. The multiplication and division is a special case of this, which is valid only in very specific scenarios. My takeaway from your explanation is that this was the main issue with your understanding of the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="39729" PostHistoryTypeId="2" PostId="13267" RevisionGUID="05448811-20c3-4fc7-991f-e158722f2fed" CreationDate="2023-02-04T20:18:16.760" UserId="7952" Text="In general $W/m^2$ and $W/sr$ are different units of measure for radiant energy so can not be converted between.&#xD;&#xA;&#xD;&#xA;However, given the geometry of the area to be measured and the radiant energy for that area then conversion can be done:&#xD;&#xA;&#xD;&#xA;To convert from watts per square meter (W/m²) to watts per steradian (W/sr), you would need to determine the solid angle subtended by the surface. The solid angle can be calculated from the surface area and the distance from the surface to the point at which the radiation is being measured.&#xD;&#xA;&#xD;&#xA;Once you have the solid angle, you can convert W/m² to W/sr by dividing by the surface area:&#xD;&#xA;&#xD;&#xA;$W/sr = (W/m²) / (surface area / (distance)^2)$&#xD;&#xA;&#xD;&#xA;where surface area is expressed in square meters and distance is expressed in meters.&#xD;&#xA;&#xD;&#xA;Note that the resulting unit will depend on the surface area and distance, and the formula is only valid for isotropic radiators, i.e., radiators that emit energy uniformly in all directions." ContentLicense="CC BY-SA 4.0" />
  <row Id="39731" PostHistoryTypeId="2" PostId="13268" RevisionGUID="c2560822-f79a-4d48-89af-9a63b94fddc4" CreationDate="2023-02-05T14:14:10.387" UserId="7952" Text="Another option to make objects glow for Ray tracers in particular is to add an emissive material to objects that need to glow.&#xD;&#xA;&#xD;&#xA;Essentially make the objects generate light. The color of the light is the color you want the object to glow. Radius, strength and density are also options. Implementation generally can play off existing code when rays are being traced. Also the implementation can start off fairly simple as an integration of a constant density over the distance a ray travels through the glowing region. Which can be solved analytically. It can also be extended without major changes to handle reflections, scattering, the list goes on and on. Essentially when a physically based effect is added to the system in general, it can be added to objects that glow, even made an option.&#xD;&#xA;&#xD;&#xA;It is a larger effort to get it up and running, but makes for a nice physically based implementation for ray tracers that are going that direction." ContentLicense="CC BY-SA 4.0" />
  <row Id="39733" PostHistoryTypeId="2" PostId="13269" RevisionGUID="7350cfe5-8b78-4243-83e2-3786e6918781" CreationDate="2023-02-05T14:24:11.887" UserId="13975" Text="I know, this is an easy question, but since I need this so often, I just want to double check that I made no mistake.&#xD;&#xA;&#xD;&#xA;Working with most shader languages, a texture can store $8$ bits per channels, which in the shader programm appear as value in the range range $r_8:=\{0, 1/255, 2/255,\dots,1\}$.  What I want to do is to transform between a single $32$ bit floating point value in $(0, 1)$ (I don't care about the floating point specifics here and just think of it as real number) and a $4$-tuple of values in $r_8$, i.e. $r_8^4$, so $\text{split}:(0,1)\to r_8^4$ and $\text{comb}:r_8^4\to(0,1)$&#xD;&#xA;&#xD;&#xA;I specifically want that $\text{comb}(\text{split}(x))=\text{round}(256^4 x)/256^4$ for almost all $x$ (i.e. I don't care about the ones lying on boundaries between bins).&#xD;&#xA;&#xD;&#xA;My implementation is the following:&#xD;&#xA;&#xD;&#xA; - $\text{split}(x)_i = \text{floor}(256^ix)/(255\cdot 256^{i-1})$&#xD;&#xA; - $\text{comb}(x_0,x_1,x_2,x_3)=255(x_0/256+x_1/256^2+x_2/256^3+x_3/256^4)+256^4/2$&#xD;&#xA;&#xD;&#xA;Is this correct or did I overlook something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39735" PostHistoryTypeId="1" PostId="13269" RevisionGUID="7350cfe5-8b78-4243-83e2-3786e6918781" CreationDate="2023-02-05T14:24:11.887" UserId="13975" Text="Splitting Floats To Texture Channels" ContentLicense="CC BY-SA 4.0" />
  <row Id="39736" PostHistoryTypeId="3" PostId="13269" RevisionGUID="7350cfe5-8b78-4243-83e2-3786e6918781" CreationDate="2023-02-05T14:24:11.887" UserId="13975" Text="|glsl|mathematics|float|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39737" PostHistoryTypeId="5" PostId="13269" RevisionGUID="9522d76c-edc1-4351-9a25-0c31f9e0e7b5" CreationDate="2023-02-05T15:58:44.417" UserId="13975" Comment="edited body" Text="I know, this is a silly question, but since I need this so often, I just want to double check that I made no mistake.&#xD;&#xA;&#xD;&#xA;Working with most shader languages, a texture can store $8$ bits per channels, which in the shader programm appear as value in the range range $r_8:=\{0, 1/255, 2/255,\dots,1\}$.  What I want to do is to transform between a single $32$ bit floating point value in $(0, 1)$ (I don't care about the floating point specifics here and just think of it as real number) and a $4$-tuple of values in $r_8$, so $\text{split}:(0,1)\to r_8^4$ and $\text{comb}:r_8^4\to(0,1)$.&#xD;&#xA;&#xD;&#xA;I specifically want that $\text{comb}(\text{split}(x))=\text{round}(256^4 x)/256^4$ for almost all $x$ (I don't care about the ones lying on boundaries between bins).&#xD;&#xA;&#xD;&#xA;My implementation is the following:&#xD;&#xA;&#xD;&#xA; - $\text{split}(x)_i := \text{floor}(256^ix)/(255\cdot 256^{i-1})$&#xD;&#xA; - $\text{comb}(x_0,\dots,x_3):=255(x_0/256+\dots+x_3/256^4)+256^4/2$&#xD;&#xA;&#xD;&#xA;Is this correct or did I overlook something?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39738" PostHistoryTypeId="2" PostId="13270" RevisionGUID="c713e227-a64b-40a0-b56c-ec687ed7e8a9" CreationDate="2023-02-05T17:20:08.243" UserId="445" Text="This will not work. The principle you are attempting to use would work (with some adjustment) if you were converting between a 32-bit unsigned _integer_ representation and four 8-bit integers, because there are exactly enough bits to use. But the 32-bit “single precision” floating point format uses some of its bits to represent the exponent and the sign:&#xD;&#xA;&#xD;&#xA;[![Diagram of 32-bit single precision floating point format][2]][2]&#xD;&#xA;&#xD;&#xA;*([Image](https://en.wikipedia.org/wiki/File:Float_example.PNG) by Wikipedia user Fresheneesz)*&#xD;&#xA;&#xD;&#xA;There are only 23 bits available (effectively 24) to represent an integer value. So, you cannot simply pack four 8-bit integers into an mathematically-integer value stored in a 32-bit float — you will run out of precision, and the component stored in the low bits will be corrupted.&#xD;&#xA;&#xD;&#xA;However, it _is_ possible to pack the _amount_ of data you want into a float; the key is that you have to _reinterpret the bits of the float_ as a 32-bit integer or vice versa. In GLSL, this is provided by the functions `floatBitsToUint()` and `uintBitsToFloat()`. Once you have the unsigned integer, you can proceed as you intended — **but the produced `float` will not be in the range 0 to 1.**&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/A1m0P.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39740" PostHistoryTypeId="2" PostId="13271" RevisionGUID="98866c52-6240-4212-9ce2-bacda1be7c2b" CreationDate="2023-02-06T02:45:07.930" UserId="19534" Text="My AO algorithm is as follows, whith the random vectors just all over the hemisphere:&#xD;&#xA;&#xD;&#xA;    vec3 ao_ray_position= random_in_hemisphere(gi_rec.normal);&#xD;&#xA;    &#xD;&#xA;    ao_ray = ray(gi_rec.p + gi_rec.normal * 0.001f, ao_ray_position);&#xD;&#xA;    ao_hit = !world.hit(ao_ray, 0, infinity, gi_rec);&#xD;&#xA;            &#xD;&#xA;    ao_result = Color(ao_hit / gi_samples, ao_hit/ gi_samples, ao_hit/ gi_samples);&#xD;&#xA;&#xD;&#xA;which renders this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this one is from V-Ray with falloff at 8,7, which is the setting I want to implement, but can't figure out how. I've seen many examples of limiting the hemisphere by cone angle but the image just renders black&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/01Nan.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/N8ECX.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39742" PostHistoryTypeId="1" PostId="13271" RevisionGUID="98866c52-6240-4212-9ce2-bacda1be7c2b" CreationDate="2023-02-06T02:45:07.930" UserId="19534" Text="How to implement falloff control in brute force ambient occlusion?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39743" PostHistoryTypeId="3" PostId="13271" RevisionGUID="98866c52-6240-4212-9ce2-bacda1be7c2b" CreationDate="2023-02-06T02:45:07.930" UserId="19534" Text="|ray|render|occlusion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39750" PostHistoryTypeId="5" PostId="13269" RevisionGUID="aa6fba02-c6ac-4551-9023-23fe7f3c9e5f" CreationDate="2023-02-06T07:04:58.730" UserId="13975" Comment="added 129 characters in body" Text="I know, this is a silly question, but since I need this so often, I just want to double check that I made no mistake.&#xD;&#xA;&#xD;&#xA;Working with most shader languages, a texture can store $8$ bits per channels, which in the shader programm appear as value in the range range $r_8:=\{0, 1/255, 2/255,\dots,1\}$.  What I want to do is to transform between a single $32$ bit floating point value in $(0, 1)$ (I don't care about the floating point specifics here and just think of it as real number) and a $4$-tuple of values in $r_8$, so $\text{split}:(0,1)\to r_8^4$ and $\text{comb}:r_8^4\to(0,1)$.&#xD;&#xA;&#xD;&#xA;I specifically want that $\text{comb}(\text{split}(x))=\text{round}(256^4 x)/256^4$ for almost all $x$ (I don't care about the ones lying on boundaries between bins).&#xD;&#xA;&#xD;&#xA;My implementation is the following:&#xD;&#xA;&#xD;&#xA; - $\text{split}(x)_i := \text{floor}(256^ix)/(255\cdot 256^{i-1})$&#xD;&#xA; - $\text{comb}(x_0,\dots,x_3):=255(x_0/256+\dots+x_3/256^4)+256^4/2$&#xD;&#xA;&#xD;&#xA;Is this correct or did I overlook something?&#xD;&#xA;&#xD;&#xA;## Edit&#xD;&#xA;&#xD;&#xA;I realized that the first part should be $$\text{split}(x)_i:=\lfloor(256(256^ix-\lfloor256^ix\rfloor)\rfloor/255$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39751" PostHistoryTypeId="2" PostId="13273" RevisionGUID="5e063024-1f31-4622-9bde-25ac42160643" CreationDate="2023-02-06T07:57:25.620" UserId="19537" Text="I am writing my first path tracer and kind of feeling confused by some mechanisms. For example, when I trace a ray and the ray hits a area emitter, then how to determine the radiance of this direct hit? I know that in rendering equation, we have:&#xD;&#xA;&#xD;&#xA;$L_o(w_o, x) = L_e(w_o, x) + \int f_r(w_i, w_o, x)\cos \theta dw_i$&#xD;&#xA;&#xD;&#xA;and here I should determine what $L_e(w_o, x)$ is. My question is, for $L_e(w_o, x)$ here, should it incorporate distance attenuation (e.g. for area light, pow(distance, 2)) and $\cos$ term? Because I've noticed that if I scale down the `emission_part` of when calculating the following code:&#xD;&#xA;```[![enter image description here][1]][1]&#xD;&#xA;color = (direct_part + emission_part) * throughput&#xD;&#xA;```&#xD;&#xA;The rendering actually converges **several times faster** (though I think it will lead to biased results), and the there is less aliasing effect around the emitter. Also, I tried to understand how other renderers cope with this situation (like mitsuba2, `path.cpp`):&#xD;&#xA;```&#xD;&#xA;result[active] += emission_weight * throughput * emitter-&gt;eval(si, active);&#xD;&#xA;```&#xD;&#xA;I don't see how `emitter-&gt;eval(si, active)` above leveraging `si` (surface interaction vertex), like calculating distance attenuation to the sampled intensity, `mitsuba2` just uses `Texture::eval(...)` to calculate the emitted radiance. Therefore, I think this is the reason for its rendering result to have no saw-tooth aliasing anywhere but places around the emitter (see the figure below: cornell box scene with area emitter):&#xD;&#xA;&#xD;&#xA;![cornellbox](https://i.stack.imgur.com/122CO.png)&#xD;&#xA;&#xD;&#xA;So, should I just use the formulation below, just like evaluating direct illumination&#xD;&#xA;```&#xD;&#xA;ret_int = emitter.intensity * distance_attenuate(ray_length) * cosine_term&#xD;&#xA;```&#xD;&#xA;Or simply returns its original intensity:&#xD;&#xA;```&#xD;&#xA;ret_int = emitter.intensity&#xD;&#xA;```&#xD;&#xA;When dealing with ray hitting an emitter?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39753" PostHistoryTypeId="1" PostId="13273" RevisionGUID="5e063024-1f31-4622-9bde-25ac42160643" CreationDate="2023-02-06T07:57:25.620" UserId="19537" Text="Path tracing: how to deal with ray hitting an emitter" ContentLicense="CC BY-SA 4.0" />
  <row Id="39754" PostHistoryTypeId="3" PostId="13273" RevisionGUID="5e063024-1f31-4622-9bde-25ac42160643" CreationDate="2023-02-06T07:57:25.620" UserId="19537" Text="|rendering|pathtracing|global-illumination|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39755" PostHistoryTypeId="5" PostId="12832" RevisionGUID="6c6c385e-5d10-42bc-9d91-5434cbbec6fe" CreationDate="2023-02-06T12:19:09.847" UserId="9199" Comment="English + formatting" Text="The paper [&quot;An Area-Preserving Parametrization for Spherical Rectangles&quot;][1] describes an efficient approach for sampling solid angles for ***rectangle*** light sources. &#xD;&#xA;&#xD;&#xA;I am wondering if &#xD;&#xA;&#xD;&#xA;- The light source in world space is a quad shape (not necessarily a perfect rect), can I transform it to its local space which will be a rectangle, apply the above to sample the solid angle, and then transform the sampled dir back to world coordinate? Would this approach be valid for sampling quad shapes (using the method in this paper)? &#xD;&#xA;&#xD;&#xA;- Also (I guess this is a more general thing) if the world to object (and obj to world) transformation has shear transformation in it, would sampling in local space and then transforming the sample back to world still be a valid one?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.arnoldrenderer.com/research/egsr2013_spherical_rectangle.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="39756" PostHistoryTypeId="24" PostId="12832" RevisionGUID="6c6c385e-5d10-42bc-9d91-5434cbbec6fe" CreationDate="2023-02-06T12:19:09.847" Comment="Proposed by 9199 approved by 7952, 6041 edit id of 615" ContentLicense="CC BY-SA 4.0" />
  <row Id="39757" PostHistoryTypeId="33" PostId="13098" RevisionGUID="daf27641-ffe1-4736-9e9c-8613549430a0" CreationDate="2023-02-06T13:38:35.297" UserId="13273" Comment="82" />
  <row Id="39758" PostHistoryTypeId="5" PostId="13154" RevisionGUID="eb63eb6a-3568-4502-b86f-35fd2c45dbd9" CreationDate="2023-02-06T17:41:51.967" UserId="9199" Comment="English + formatting" Text="The short answer is to use a UI extension like DearIMGUI, wxWidgets, or QT.&#xD;&#xA;&#xD;&#xA;I have pondered the question too, so much so that I'm partaking in the following.  So instead, using conversion types from GLUT (instead of using a wrapper).  I am plugging my extra time outside of development in to making a GLFW dependent extension, in the form of a `.dll`, and `.h` file, which allows you to create UI's, text input/output (though GLFW already supports this part (if you appropriately read documents)), image texture loader, and a separated loader for 3d models/animations.  Trying to assist in making development easier for GLFW users. 1 plugin to substitute all the additional plugins." ContentLicense="CC BY-SA 4.0" />
  <row Id="39759" PostHistoryTypeId="24" PostId="13154" RevisionGUID="eb63eb6a-3568-4502-b86f-35fd2c45dbd9" CreationDate="2023-02-06T17:41:51.967" Comment="Proposed by 9199 approved by 7952, 13095 edit id of 616" ContentLicense="CC BY-SA 4.0" />
  <row Id="39760" PostHistoryTypeId="5" PostId="13062" RevisionGUID="1c1f8bdf-fe80-40a0-9610-eab214701a20" CreationDate="2023-02-06T17:43:14.643" UserId="9199" Comment="English + formatting" Text="I botched together the following code to do a simple rotating radar display.&#xD;&#xA;&#xD;&#xA;1. How can I eliminate the flicker of the line being drawn and then drawn over? Can I use double buffering somehow?&#xD;&#xA;&#xD;&#xA;2. How can I get mouse and keyboard inputs and process/parse them?&#xD;&#xA;&#xD;&#xA;My goal is to read angle and distance data from an ultrasonic sensor and display that as a sweep. This data comes from an Arduino with an ultrasonic rangefinder mounted on a servo sweeping backwards and forwards 180 degrees. I also can't quite get the math right. I'd like it to go from 0 to 180, left to right and back depending on the angle data from the Arduino. 0 Deg is 90 Deg off to the right. So I know I have to offset it by 180 Deg but am hopeless at math. The sweep would have to start at 270 Deg and sweep through to 0 Deg. I will have to learn how to read the serial port and parse the data for the display.&#xD;&#xA;&#xD;&#xA;Here is my code. I used a tutorial as a base and kind of guessed my way through.&#xD;&#xA;&#xD;&#xA;    /*&#xD;&#xA;     * simple-drawing.c - demonstrate drawing of pixels, lines, arcs, etc.&#xD;&#xA;     *                    on a window. All drawings are done in black color&#xD;&#xA;     *                    over a white background.&#xD;&#xA;     */&#xD;&#xA;    &#xD;&#xA;    #include &lt;X11/Xlib.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;     /* getenv(), etc. */&#xD;&#xA;    #include &lt;unistd.h&gt;     /* sleep(), etc.  */&#xD;&#xA;&#xD;&#xA;    // Include math library functions.&#xD;&#xA;    #include &lt;math.h&gt;&#xD;&#xA;&#xD;&#xA;    /*&#xD;&#xA;     * function: create_simple_window. Creates a window with a white background&#xD;&#xA;     *           in the given size.&#xD;&#xA;     * input:    display, size of the window (in pixels), and location of the window&#xD;&#xA;     *           (in pixels).&#xD;&#xA;     * output:   the window's ID.&#xD;&#xA;     * notes:    window is created with a black border, 2 pixels wide.&#xD;&#xA;     *           the window is automatically mapped after its creation.&#xD;&#xA;     */&#xD;&#xA;    Window&#xD;&#xA;    create_simple_window(Display* display, int width, int height, int x, int y)&#xD;&#xA;    {&#xD;&#xA;      int screen_num = DefaultScreen(display);&#xD;&#xA;      int win_border_width = 2;&#xD;&#xA;      Window win;&#xD;&#xA;    &#xD;&#xA;      /* create a simple window, as a direct child of the screen's */&#xD;&#xA;      /* root window. Use the screen's black and white colors as   */&#xD;&#xA;      /* the foreground and background colors of the window,       */&#xD;&#xA;      /* respectively. Place the new window's top-left corner at   */&#xD;&#xA;      /* the given 'x,y' coordinates.                              */&#xD;&#xA;      win = XCreateSimpleWindow(display, RootWindow(display, screen_num),&#xD;&#xA;                                x, y, width, height, win_border_width,&#xD;&#xA;                                BlackPixel(display, screen_num),&#xD;&#xA;                                WhitePixel(display, screen_num));   &#xD;&#xA;    &#xD;&#xA;      /* make the window actually appear on the screen. */&#xD;&#xA;      XMapWindow(display, win);&#xD;&#xA;    &#xD;&#xA;      /* flush all pending requests to the X server. */&#xD;&#xA;      XFlush(display);&#xD;&#xA;    &#xD;&#xA;      return win;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    GC&#xD;&#xA;    create_gc(Display* display, Window win, int reverse_video)&#xD;&#xA;    {&#xD;&#xA;      GC gc;                /* handle of newly created GC.  */&#xD;&#xA;      unsigned long valuemask = 0;      /* which values in 'values' to  */&#xD;&#xA;                        /* check when creating the GC.  */&#xD;&#xA;      XGCValues values;         /* initial values for the GC.   */&#xD;&#xA;      unsigned int line_width = 2;      /* line width for the GC.       */&#xD;&#xA;      int line_style = LineSolid;       /* style for lines drawing and  */&#xD;&#xA;      int cap_style = CapButt;      /* style of the line's edje and */&#xD;&#xA;      int join_style = JoinBevel;       /*  joined lines.       */&#xD;&#xA;      int screen_num = DefaultScreen(display);&#xD;&#xA;    &#xD;&#xA;      gc = XCreateGC(display, win, valuemask, &amp;values);&#xD;&#xA;      if (gc &lt; 0) {&#xD;&#xA;        fprintf(stderr, &quot;XCreateGC: \n&quot;);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* allocate foreground and background colors for this GC. */&#xD;&#xA;      if (reverse_video) {&#xD;&#xA;        XSetForeground(display, gc, WhitePixel(display, screen_num));&#xD;&#xA;        XSetBackground(display, gc, BlackPixel(display, screen_num));&#xD;&#xA;      }&#xD;&#xA;      else {&#xD;&#xA;        XSetForeground(display, gc, BlackPixel(display, screen_num));&#xD;&#xA;        XSetBackground(display, gc, WhitePixel(display, screen_num));&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* define the style of lines that will be drawn using this GC. */&#xD;&#xA;      XSetLineAttributes(display, gc,&#xD;&#xA;                         line_width, line_style, cap_style, join_style);&#xD;&#xA;    &#xD;&#xA;      /* define the fill style for the GC. to be 'solid filling'. */&#xD;&#xA;      XSetFillStyle(display, gc, FillSolid);&#xD;&#xA;    &#xD;&#xA;      return gc;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void&#xD;&#xA;    main(int argc, char* argv[])&#xD;&#xA;    {&#xD;&#xA;      Display* display;     /* pointer to X Display structure.           */&#xD;&#xA;      int screen_num;       /* number of screen to place the window on.  */&#xD;&#xA;      Window win;           /* pointer to the newly created window.      */&#xD;&#xA;      unsigned int display_width,&#xD;&#xA;                   display_height;  /* height and width of the X display.        */&#xD;&#xA;      unsigned int width, height;   /* height and width for the new window.      */&#xD;&#xA;      char *display_name = getenv(&quot;DISPLAY&quot;);  /* address of the X display.      */&#xD;&#xA;      GC gc;            /* GC (graphics context) used for drawing    */&#xD;&#xA;                        /*  in our window.               */&#xD;&#xA;&#xD;&#xA;      // Added code to select simple black or white color to draw.&#xD;&#xA;      Colormap screen_colormap;     /* color map to use for allocating colors.   */&#xD;&#xA;      XColor black, white;&#xD;&#xA;                                    /* used for allocation of the given color    */&#xD;&#xA;                                    /* map entries.                              */&#xD;&#xA;      Status rc;                    /* return status of various Xlib functions.  */&#xD;&#xA;    &#xD;&#xA;    // Johns stuff. This code draws a line from starting co-ordinates at an angle&#xD;&#xA;    // &#xD;&#xA;    &#xD;&#xA;    int angle=0;&#xD;&#xA;    int x1,x2,y1,y2;&#xD;&#xA;    int px,py;&#xD;&#xA;    &#xD;&#xA;    // End&#xD;&#xA;    &#xD;&#xA;      /* open connection with the X server. */&#xD;&#xA;      display = XOpenDisplay(display_name);&#xD;&#xA;      if (display == NULL) {&#xD;&#xA;        fprintf(stderr, &quot;%s: cannot connect to X server '%s'\n&quot;,&#xD;&#xA;                argv[0], display_name);&#xD;&#xA;        exit(1);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* get the geometry of the default screen for our display. */&#xD;&#xA;      screen_num = DefaultScreen(display);&#xD;&#xA;      display_width = DisplayWidth(display, screen_num);&#xD;&#xA;      display_height = DisplayHeight(display, screen_num);&#xD;&#xA;    &#xD;&#xA;      /* make the new window occupy 1/9 of the screen's size. */&#xD;&#xA;      width = (display_width / 2); &#xD;&#xA;      height = (display_height / 2);&#xD;&#xA;      printf(&quot;window width - '%d'; height - '%d'\n&quot;, width, height);&#xD;&#xA;    &#xD;&#xA;      /* create a simple window, as a direct child of the screen's   */&#xD;&#xA;      /* root window. Use the screen's white color as the background */&#xD;&#xA;      /* color of the window. Place the new window's top-left corner */&#xD;&#xA;      /* at the given 'x,y' coordinates.                             */&#xD;&#xA;      win = create_simple_window(display, width, height, 50, 50);&#xD;&#xA;    &#xD;&#xA;      /* allocate a new GC (graphics context) for drawing in the window. */&#xD;&#xA;      gc = create_gc(display, win, 0);&#xD;&#xA;      XSync(display, False);&#xD;&#xA;    &#xD;&#xA;      // Following 3 lines needed or else we just see white background.&#xD;&#xA;&#xD;&#xA;      /* catch expose events */&#xD;&#xA;      XSelectInput(display, win, ExposureMask);&#xD;&#xA;    &#xD;&#xA;      /* wait for the expose event */&#xD;&#xA;      XEvent ev;&#xD;&#xA;      XNextEvent(display, &amp;ev);&#xD;&#xA; &#xD;&#xA;      // Follwing code borrowed to get colors to draw.    &#xD;&#xA;      /* get access to the screen's color map. */&#xD;&#xA;      screen_colormap = DefaultColormap(display, DefaultScreen(display));&#xD;&#xA;    &#xD;&#xA;      /* allocate the set of colors we will want to use for the drawing. */&#xD;&#xA;      rc = XAllocNamedColor(display, screen_colormap, &quot;black&quot;, &amp;black, &amp;black);&#xD;&#xA;      if (rc == 0) {&#xD;&#xA;        fprintf(stderr, &quot;XAllocNamedColor - failed to allocated 'black' color.\n&quot;);&#xD;&#xA;        exit(1);&#xD;&#xA;      }&#xD;&#xA;      rc = XAllocNamedColor(display, screen_colormap, &quot;white&quot;, &amp;white, &amp;white);&#xD;&#xA;      if (rc == 0) {&#xD;&#xA;        fprintf(stderr, &quot;XAllocNamedColor - failed to allocated 'white' color.\n&quot;);&#xD;&#xA;        exit(1);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      /* draw one pixel near each corner of the window */&#xD;&#xA;      XDrawPoint(display, win, gc, 5, 5);&#xD;&#xA;      XDrawPoint(display, win, gc, 5, height-5);&#xD;&#xA;      XDrawPoint(display, win, gc, width-5, 5);&#xD;&#xA;      XDrawPoint(display, win, gc, width-5, height-5);&#xD;&#xA;    &#xD;&#xA;    // Do our display. Loop forever because I don't know how to process keystrokes.&#xD;&#xA;    // If we start from the center of the display, 0 is to the right (E), 90 is to the&#xD;&#xA;    // bottom (S), 180 (W),270 (N). Don't quite know how to &quot;rotate&quot; the &quot;beam&quot; 180 Deg.&#xD;&#xA;    // Needs double buffering to remove the flicker.&#xD;&#xA;    // I would like to make a separate subroutine eg: DrawRadar( int angle, int distance);&#xD;&#xA;    &#xD;&#xA;      x1=width / 2;     //Find center of display.&#xD;&#xA;      y1=height / 2;&#xD;&#xA;      px=x1;            // Previous X and Y&#xD;&#xA;      py=y1;&#xD;&#xA;    &#xD;&#xA;    while(1){&#xD;&#xA;    &#xD;&#xA;      for(angle=0; angle &lt; 360; angle++)&#xD;&#xA;      {&#xD;&#xA;&#xD;&#xA;      // Distance set to 150 pixels. Radar returns value up to 3300 mm.&#xD;&#xA;      // Will have to scale down. &#xD;&#xA;        x2=x1 + cos((angle * M_PI) / 180) * 150;   // Must convert to radians.&#xD;&#xA;        y2=y1 + sin((angle * M_PI) / 180) * 150;   //  &quot;     &quot;      &quot;    &quot;&#xD;&#xA;    &#xD;&#xA;        XSetForeground(display, gc, black.pixel);  // &#xD;&#xA;        XDrawLine(display, win, gc, x1, y1, x2, y2);&#xD;&#xA;        px=x2;&#xD;&#xA;        py=y2;&#xD;&#xA;        XFlush(display);      // Display what we've drawn.&#xD;&#xA;        usleep(3500);         // Wait so eye can see it.&#xD;&#xA;        XSetForeground(display, gc, white.pixel);  // Rub out the line we just drew.&#xD;&#xA;        XDrawLine(display, win, gc, x1, y1, px ,py);&#xD;&#xA;        XFlush(display);      // Causes flickering but only way at the moment.&#xD;&#xA;        XSetForeground(display, gc, black.pixel);&#xD;&#xA;        usleep(3500);&#xD;&#xA;    &#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    // End. Never get past here.&#xD;&#xA;    &#xD;&#xA;      /* flush all pending requests to the X server. */&#xD;&#xA;      XFlush(display);&#xD;&#xA;      XSync(display, False);&#xD;&#xA;    &#xD;&#xA;      /* make a delay for a short period. */&#xD;&#xA;      sleep(4);&#xD;&#xA;    &#xD;&#xA;      /* close the connection to the X server. */&#xD;&#xA;      XCloseDisplay(display);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;I'm simply trying to draw a moving line without flicker. I understand the concept but am a crap coder. Any help would be appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="39761" PostHistoryTypeId="24" PostId="13062" RevisionGUID="1c1f8bdf-fe80-40a0-9610-eab214701a20" CreationDate="2023-02-06T17:43:14.643" Comment="Proposed by 9199 approved by 7952, 13095 edit id of 614" ContentLicense="CC BY-SA 4.0" />
  <row Id="39762" PostHistoryTypeId="2" PostId="13274" RevisionGUID="25909a4e-b00f-4df6-b1df-d8f680bbc497" CreationDate="2023-02-06T21:29:31.630" UserId="19542" Text="If I understood correctly this is the process of rendering an object:&#xD;&#xA;1) Array of 4d vector defining points 3d points(with the fourth component 1) representing object's vertices in object/local space:&lt;br&gt;&#xD;&#xA;`{1, 1.21, 2.12}`&lt;br&gt;&#xD;&#xA;`{1, 1.21, 2.12}`&lt;br&gt;&#xD;&#xA;`{1, 1.21, 2.12}`&lt;br&gt;&#xD;&#xA;`{1, 1.21, 2.12}`&lt;br&gt;&#xD;&#xA;2) Constructing a translation matrix(where x, y, z are the new position on each axis):&#xD;&#xA;```&#xD;&#xA;1 0 0 0&#xD;&#xA;0 1 0 0&#xD;&#xA;0 0 1 0&#xD;&#xA;x y z 1&#xD;&#xA;```&#xD;&#xA;3) Constructing a rotation matrix(here I didn't yet understand how quaternions and rotation work , what I know is that there is a rotation matrix where you fill with the sine and cosine of the angles on each axis)&#xD;&#xA;&#xD;&#xA;4) Construction a scaling matrix(x, y, z scaling amount on axis)&#xD;&#xA;```&#xD;&#xA;x 0 0 0&#xD;&#xA;0 y 0 0&#xD;&#xA;0 0 z 0&#xD;&#xA;0 0 0 1&#xD;&#xA;```&#xD;&#xA;5) Multiplying all tree to obtain the Model/Object Matrix&#xD;&#xA;&#xD;&#xA;6) The view/camera matrix(which handles the position of the scene observer, feed the location of the observer, the direction it is looking and the global up direction in the right places and this will move the scene acorrdingly):&#xD;&#xA;&#xD;&#xA;7) Projection matrix(Handles the aspect ratio, clipping planes, fov)&#xD;&#xA;&#xD;&#xA;8) Multiplying Model with View with Projection matrices. And multiplying the Final matrix with the  vertices position.&#xD;&#xA;&#xD;&#xA;9) On each vertex, divide the x, y, z components by their w to project the 3d scene in a 2d screen(obtaining vertices in NDC space ranging from -1, to 1).&#xD;&#xA;&#xD;&#xA;10) Remap the NDC values to match the screen coordinates by doing a simple calculus.&#xD;&#xA;&#xD;&#xA;11) GPU interpolates the pixels positions in screen coordinates and fills them with color accordingly.&#xD;&#xA;&#xD;&#xA;In DirectX and OpenGL I know that the matrices are computed in the CPU and sent to GPU in the vertex shader as vertexPOS * MVP(Model * View * Projection). And the GPU handles the perspective w division and the remapping to screen coordinates and interpolating pixels. But why doing the initial multiplication in the CPU if we can just send the parameters to the GPU(translation, rotation, scaling, eye position, eye direction, up, fov, aspect ratio, near/far clipping plane) and the GPU handles the matrix magic behind the scenes. Wouldn't GPU make those matrix multiplication faster than CPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39764" PostHistoryTypeId="1" PostId="13274" RevisionGUID="25909a4e-b00f-4df6-b1df-d8f680bbc497" CreationDate="2023-02-06T21:29:31.630" UserId="19542" Text="Why are the transformations of an object calculated on CPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39765" PostHistoryTypeId="3" PostId="13274" RevisionGUID="25909a4e-b00f-4df6-b1df-d8f680bbc497" CreationDate="2023-02-06T21:29:31.630" UserId="19542" Text="|3d|matrix|vertex-buffer-object|render|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39766" PostHistoryTypeId="2" PostId="13275" RevisionGUID="b6dd9d12-c0c3-40df-9b54-ae68bde4e694" CreationDate="2023-02-06T22:57:16.120" UserId="7952" Text="It is perfectly reasonable to do the multiplication on the GPU. The major reason it is taught this way is partly it is historically standard, but the main reason is if you have a vertex shader that has line like the following in it...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    gl_Position = ModelReflection * ModelScale * ModelTranslation * View * Projection * vertex;&#xD;&#xA;&#xD;&#xA;And there are in the neighborhood of 10 million vertices over thousands of models then you get in the neighborhood of 60 million 4x4 matrix multiplications.&#xD;&#xA;&#xD;&#xA;Each matrix multiplication is roughly 64 basic operations so that is 3.2billion basic operations that can be easily avoided.&#xD;&#xA;&#xD;&#xA;But if the majority of the multiplications are handled on the CPU then you can easily remove 40 or 50 million 4x4 matrix multiplications or billions of basic operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And that is one of the major reasons (perhaps the major reason) for doing as much work as possible on the CPU.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39768" PostHistoryTypeId="2" PostId="13276" RevisionGUID="a8ca08fe-0c29-4b71-8065-ea94492f3671" CreationDate="2023-02-07T03:30:43.253" UserId="2654" Text="&gt; Wouldn't GPU make those matrix multiplication faster than CPU?&#xD;&#xA;&#xD;&#xA;No. GPUs are not a magic &quot;make things go faster&quot; box.&#xD;&#xA;&#xD;&#xA;Vertex shaders operate on *every vertex*. If you render 1 million vertices, there have to be (roughly) one million executions of a vertex shader.&#xD;&#xA;&#xD;&#xA;So let's have a VS take these matrix parameters and build a matrix from them. *One million times*. But because these parameters are `uniform`s, they don't change; you're computing the *exact same matrix* each time. One million times.&#xD;&#xA;&#xD;&#xA;That is a fantastic waste of GPU processing time. Vertex shaders exist to do per-vertex processing. That's what they ought to do. Per-object computations, or per-scene computations ought to be handled by something else.&#xD;&#xA;&#xD;&#xA;Also, how many objects do you have? Maybe 100,000 at the most? A modern CPU can do 100,000 matrix multiplies per frame just fine.&#xD;&#xA;&#xD;&#xA;Furthermore, you're presupposing that a transformation for a model can be boiled down to a single &quot;translation, rotation, scaling&quot;. That is usually not the case.&#xD;&#xA;&#xD;&#xA;Let's say you have a base object, like a train. And you have a person on top of the train. If the train rotates, the person should rotate accordingly. But the person *also* needs to be able to rotate relative to the train. Same goes for the translation and such; if the train moves, it needs to move the person on it. But the person also needs to move relative to the train.&#xD;&#xA;&#xD;&#xA;You could send an array of translations/rotations/scaling/etc that the VS would then composed into a final transformation.&#xD;&#xA;&#xD;&#xA;Or the CPU can just multiply the train matrix and the local person matrix to produce the full composite transform for the person. Plus, you gain the benefit of being able to render both objects with the *same vertex shader*, since the VS does not need to know what the actual transformation matrix represents. It just needs to know that this one transformation matrix is how this object gets to camera space. Each object gets different data, but the *shape* of that data is always just one matrix." ContentLicense="CC BY-SA 4.0" />
  <row Id="39770" PostHistoryTypeId="2" PostId="13277" RevisionGUID="38938717-db36-4a5f-a5d3-e44bec1a5321" CreationDate="2023-02-07T10:47:57.650" UserId="19528" Text="are there any way to optimize this flow:&#xD;&#xA;1. The frame captured from camera (NV21 byte array)&#xD;&#xA;2. Convert this frame to I420 format&#xD;&#xA;3. Upload Y data to `y_tex`; U data to `u_tex`; V data to `v_tex`&#xD;&#xA;4. Run the following fragment shader:&#xD;&#xA;```&#xD;&#xA;...&#xD;&#xA; float greenValue(vec2 coord)&#xD;&#xA; {&#xD;&#xA;  return texture2D(y_tex, coord).r &#xD;&#xA;    - 0.344 * (texture2D(u_tex, coord).r - 0.5) &#xD;&#xA;    - 0.714 * (texture2D(v_tex, coord).r - 0.5);&#xD;&#xA; }&#xD;&#xA; // some code .... if (current pixel is skin color)&#xD;&#xA; vec2 blurCoordinates[20];&#xD;&#xA; blurCoordinates[0] = interp_tc.xy + singleStepOffset * vec2(0.0, -10.0);&#xD;&#xA; blurCoordinates[1] = interp_tc.xy + singleStepOffset * vec2(0.0, 10.0);&#xD;&#xA; blurCoordinates[2] = interp_tc.xy + singleStepOffset * vec2(-10.0, 0.0);&#xD;&#xA; blurCoordinates[3] = interp_tc.xy + singleStepOffset * vec2(10.0, 0.0);&#xD;&#xA; blurCoordinates[4] = interp_tc.xy + singleStepOffset * vec2(5.0, -8.0);&#xD;&#xA; blurCoordinates[5] = interp_tc.xy + singleStepOffset * vec2(5.0, 8.0);&#xD;&#xA; blurCoordinates[6] = interp_tc.xy + singleStepOffset * vec2(-5.0, 8.0);&#xD;&#xA; blurCoordinates[7] = interp_tc.xy + singleStepOffset * vec2(-5.0, -8.0);&#xD;&#xA; blurCoordinates[8] = interp_tc.xy + singleStepOffset * vec2(8.0, -5.0);&#xD;&#xA; blurCoordinates[9] = interp_tc.xy + singleStepOffset * vec2(8.0, 5.0);&#xD;&#xA; blurCoordinates[10] = interp_tc.xy + singleStepOffset * vec2(-8.0, 5.0);&#xD;&#xA; blurCoordinates[11] = interp_tc.xy + singleStepOffset * vec2(-8.0, -5.0);&#xD;&#xA; blurCoordinates[12] = interp_tc.xy + singleStepOffset * vec2(0.0, -6.0);&#xD;&#xA; blurCoordinates[13] = interp_tc.xy + singleStepOffset * vec2(0.0, 6.0);&#xD;&#xA; blurCoordinates[14] = interp_tc.xy + singleStepOffset * vec2(6.0, 0.0);&#xD;&#xA; blurCoordinates[15] = interp_tc.xy + singleStepOffset * vec2(-6.0, 0.0);&#xD;&#xA; blurCoordinates[16] = interp_tc.xy + singleStepOffset * vec2(-4.0, -4.0);&#xD;&#xA; blurCoordinates[17] = interp_tc.xy + singleStepOffset * vec2(-4.0, 4.0);&#xD;&#xA; blurCoordinates[18] = interp_tc.xy + singleStepOffset * vec2(4.0, -4.0);&#xD;&#xA; blurCoordinates[19] = interp_tc.xy + singleStepOffset * vec2(4.0, 4.0);&#xD;&#xA; // some code ....&#xD;&#xA; float sampleColor = centralColor.g * 20.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[0]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[1]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[2]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[3]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[4]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[5]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[6]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[7]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[8]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[9]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[10]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[11]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[12]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[13]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[14]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[15]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[16]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[17]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[18]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[19]) * 2.0;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Problem:**&#xD;&#xA;&#xD;&#xA;I tested on weak device (galaxy A6) and capture with HD resolution frame (1280x720). It take ~100ms/frame. The main reason of this bottle neck is the large number of `texture2D()` call. Each frame make ~60,000,000 call `texture2D()`.&#xD;&#xA;&#xD;&#xA;**Idea:**&#xD;&#xA;&#xD;&#xA;When I replace (`u_tex`, `v_tex`) by `y_tex` for test, it's very fast. So, I think performance maybe improved by use only **one texture** instead of **three textures** (`y_tex, u_tex, v_tex`).&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;Does my approach is feasible? Are there any way to optimize this shader or improve entire  this flow?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39772" PostHistoryTypeId="1" PostId="13277" RevisionGUID="38938717-db36-4a5f-a5d3-e44bec1a5321" CreationDate="2023-02-07T10:47:57.650" UserId="19528" Text="Bottle neck in fragment shader because large number of texture2D call" ContentLicense="CC BY-SA 4.0" />
  <row Id="39773" PostHistoryTypeId="3" PostId="13277" RevisionGUID="38938717-db36-4a5f-a5d3-e44bec1a5321" CreationDate="2023-02-07T10:47:57.650" UserId="19528" Text="|glsl|opengl-es|android|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39774" PostHistoryTypeId="5" PostId="13277" RevisionGUID="83a774e9-e031-4789-befb-35569e45d627" CreationDate="2023-02-07T10:48:19.033" UserId="19528" Comment="edited body" Text="Are there any way to optimize this flow:&#xD;&#xA;1. The frame captured from camera (NV21 byte array)&#xD;&#xA;2. Convert this frame to I420 format&#xD;&#xA;3. Upload Y data to `y_tex`; U data to `u_tex`; V data to `v_tex`&#xD;&#xA;4. Run the following fragment shader:&#xD;&#xA;```&#xD;&#xA;...&#xD;&#xA; float greenValue(vec2 coord)&#xD;&#xA; {&#xD;&#xA;  return texture2D(y_tex, coord).r &#xD;&#xA;    - 0.344 * (texture2D(u_tex, coord).r - 0.5) &#xD;&#xA;    - 0.714 * (texture2D(v_tex, coord).r - 0.5);&#xD;&#xA; }&#xD;&#xA; // some code .... if (current pixel is skin color)&#xD;&#xA; vec2 blurCoordinates[20];&#xD;&#xA; blurCoordinates[0] = interp_tc.xy + singleStepOffset * vec2(0.0, -10.0);&#xD;&#xA; blurCoordinates[1] = interp_tc.xy + singleStepOffset * vec2(0.0, 10.0);&#xD;&#xA; blurCoordinates[2] = interp_tc.xy + singleStepOffset * vec2(-10.0, 0.0);&#xD;&#xA; blurCoordinates[3] = interp_tc.xy + singleStepOffset * vec2(10.0, 0.0);&#xD;&#xA; blurCoordinates[4] = interp_tc.xy + singleStepOffset * vec2(5.0, -8.0);&#xD;&#xA; blurCoordinates[5] = interp_tc.xy + singleStepOffset * vec2(5.0, 8.0);&#xD;&#xA; blurCoordinates[6] = interp_tc.xy + singleStepOffset * vec2(-5.0, 8.0);&#xD;&#xA; blurCoordinates[7] = interp_tc.xy + singleStepOffset * vec2(-5.0, -8.0);&#xD;&#xA; blurCoordinates[8] = interp_tc.xy + singleStepOffset * vec2(8.0, -5.0);&#xD;&#xA; blurCoordinates[9] = interp_tc.xy + singleStepOffset * vec2(8.0, 5.0);&#xD;&#xA; blurCoordinates[10] = interp_tc.xy + singleStepOffset * vec2(-8.0, 5.0);&#xD;&#xA; blurCoordinates[11] = interp_tc.xy + singleStepOffset * vec2(-8.0, -5.0);&#xD;&#xA; blurCoordinates[12] = interp_tc.xy + singleStepOffset * vec2(0.0, -6.0);&#xD;&#xA; blurCoordinates[13] = interp_tc.xy + singleStepOffset * vec2(0.0, 6.0);&#xD;&#xA; blurCoordinates[14] = interp_tc.xy + singleStepOffset * vec2(6.0, 0.0);&#xD;&#xA; blurCoordinates[15] = interp_tc.xy + singleStepOffset * vec2(-6.0, 0.0);&#xD;&#xA; blurCoordinates[16] = interp_tc.xy + singleStepOffset * vec2(-4.0, -4.0);&#xD;&#xA; blurCoordinates[17] = interp_tc.xy + singleStepOffset * vec2(-4.0, 4.0);&#xD;&#xA; blurCoordinates[18] = interp_tc.xy + singleStepOffset * vec2(4.0, -4.0);&#xD;&#xA; blurCoordinates[19] = interp_tc.xy + singleStepOffset * vec2(4.0, 4.0);&#xD;&#xA; // some code ....&#xD;&#xA; float sampleColor = centralColor.g * 20.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[0]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[1]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[2]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[3]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[4]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[5]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[6]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[7]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[8]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[9]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[10]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[11]);&#xD;&#xA; sampleColor += greenValue(blurCoordinates[12]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[13]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[14]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[15]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[16]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[17]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[18]) * 2.0;&#xD;&#xA; sampleColor += greenValue(blurCoordinates[19]) * 2.0;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;**Problem:**&#xD;&#xA;&#xD;&#xA;I tested on weak device (galaxy A6) and capture with HD resolution frame (1280x720). It take ~100ms/frame. The main reason of this bottle neck is the large number of `texture2D()` call. Each frame make ~60,000,000 call `texture2D()`.&#xD;&#xA;&#xD;&#xA;**Idea:**&#xD;&#xA;&#xD;&#xA;When I replace (`u_tex`, `v_tex`) by `y_tex` for test, it's very fast. So, I think performance maybe improved by use only **one texture** instead of **three textures** (`y_tex, u_tex, v_tex`).&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;Does my approach is feasible? Are there any way to optimize this shader or improve entire  this flow?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39775" PostHistoryTypeId="50" PostId="8431" RevisionGUID="7b9f86c0-e664-49c4-bcd8-853a2cba448a" CreationDate="2023-02-07T15:06:10.667" UserId="-1" />
  <row Id="39776" PostHistoryTypeId="5" PostId="13275" RevisionGUID="8d638bd1-a925-4aa1-86e9-adb2487a2318" CreationDate="2023-02-07T15:17:04.080" UserId="7952" Comment="added 1839 characters in body" Text="It is perfectly reasonable to do the multiplication on the GPU. The major reason it is taught this way is partly it is historically standard, but the main reason is if you have a vertex shader that has line like the following in it...&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    gl_Position = ModelReflection * ModelScale * ModelTranslation * View * Projection * vertex;&#xD;&#xA;&#xD;&#xA;And there are in the neighborhood of 10 million vertices over thousands of models then you get in the neighborhood of 60 million 4x4 matrix multiplications.&#xD;&#xA;&#xD;&#xA;Each matrix multiplication is roughly 64 basic operations so that is 3.2billion basic operations that can be easily avoided.&#xD;&#xA;&#xD;&#xA;But if the majority of the multiplications are handled on the CPU then you can easily remove 40 or 50 million 4x4 matrix multiplications or billions of basic operations.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;And that is one of the major reasons (perhaps the major reason) for doing as much work as possible on the CPU.&#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;It is easy to say &quot;don't do that&quot; and give the standard argument but I wanted to elaborate a little bit on the pro's and con's of doing computations on the GPU.&#xD;&#xA;&#xD;&#xA;Also your question is more along of the lines of CPU vs GPU so I've included a few good reasons to use the GPU that don't include the vertex shader.&#xD;&#xA;&#xD;&#xA;Pros:&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;1) It reduces bandwidth usage between the GPU and CPU. If there is a lot of shatter between the GPU and CPU like transferring texture data. Then opportunities to reduce bandwidth should include *considering* recomputing matrices on the GPU perhaps in the vertex shader, perhaps in a compute shader.&#xD;&#xA;&#xD;&#xA;2) Don't use the Vertex shader but rather a dedicated compute shader that runs once, which does the computations. There is a window at the end of each frame where the GPU is still computing output and is &quot;ramping&quot; down. It is hard to squeeze graphics work in but compute shaders can sneak in and perform a considerable amount of work. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;3) Debugging and development reasons, once that's done, go back to using the CPU.&#xD;&#xA; &#xD;&#xA;4) Education, or you just feel like it! Don't let us push you around, the way break throughs are made is by stubborn developers that have an aha moment.&#xD;&#xA;&#xD;&#xA;Cons:&#xD;&#xA;&#xD;&#xA;1) What a waste of computational power! Especially when the numbers start to grow very large. Enough said.&#xD;&#xA;&#xD;&#xA;2) I see older GPU's, they're everywhere! Having an app that can run on as many GPU's as possible broadens it's user base.&#xD;&#xA;&#xD;&#xA;3) GPU's tend to be power hungry. Squeezing more work onto the GPU will just make that worse. This is particularly important for battery operated devices.&#xD;&#xA;&#xD;&#xA;4) Debugging and development. (it's on both lists!) Debugging on the GPU is not nearly as easy to do as it is on the CPU. If you lack confidence in the matrices themselves, debugging on the CPU will be much easier." ContentLicense="CC BY-SA 4.0" />
  <row Id="39791" PostHistoryTypeId="50" PostId="12158" RevisionGUID="20cd0798-408d-492f-89cf-65274f4672dd" CreationDate="2023-02-08T13:02:10.247" UserId="-1" />
  <row Id="39792" PostHistoryTypeId="2" PostId="13281" RevisionGUID="0a8a04d1-951d-4599-8dab-772f4ed799aa" CreationDate="2023-02-08T18:45:51.120" UserId="209" Text="Very briefly, the term you are looking for is *colour quantisation* which is a subset of the more general *Vector Quantisation*.&#xD;&#xA;&#xD;&#xA;Probably the simplest (and fastest?) one for colour data is that of [Heckbert][1]'s   &quot;[Color Image Quantization for Frame Buffer Display][2]&quot;. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If you want better quality, there a numerous others but I once wrote a VQ quantiser (for Dreamcast's texture compression) that was based on Wu's  &quot;[Color quantization by dynamic programming and principal analysis][3]&quot;  which I felt produced great results.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cs.cmu.edu/~ph/&#xD;&#xA;  [2]: https://dl.acm.org/doi/10.1145/800064.801294&#xD;&#xA;  [3]: https://dl.acm.org/doi/epdf/10.1145/146443.146475" ContentLicense="CC BY-SA 4.0" />
  <row Id="39794" PostHistoryTypeId="2" PostId="13282" RevisionGUID="0a485f57-8c74-47c5-a767-aebc16c3266f" CreationDate="2023-02-08T19:20:43.673" UserId="19552" Text="BRDF is the change in outgoing radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ turns the oblique differential surface (viewed along $-\omega_i$) into a normal differential surface (as viewed along $-n$). By the definition of the dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;The ratio of differential output radiance to differential irradiance is therefore&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39796" PostHistoryTypeId="5" PostId="13282" RevisionGUID="a8ea366d-9c6f-4d60-ad7c-9a412a8e956c" CreationDate="2023-02-08T19:48:30.473" UserId="19552" Comment="added 184 characters in body" Text="$cos (\theta_i)$ (or $\hat \omega_i ·\hat n$) accounts for the scaling of differential surface area at oblique angles. BRDF is the change in outgoing radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ turns the oblique differential surface (as viewed along $-\omega_i$) into a normal differential surface (as viewed along $-n$). By the definition of the dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;which matches the literature and the BRDF Wikipedia page. The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39797" PostHistoryTypeId="5" PostId="13282" RevisionGUID="94c42926-f29e-4ec9-a6a4-64e2946124f3" CreationDate="2023-02-08T20:07:30.217" UserId="19552" Comment="deleted 57 characters in body" Text="$cos (\theta_i)$ (or $\hat \omega_i ·\hat n$) accounts for the scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ turns the oblique differential surface (as viewed along $-\omega_i$) into a normal differential surface (as viewed along $-n$). By the definition of the dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39798" PostHistoryTypeId="5" PostId="13282" RevisionGUID="fa420e05-f877-4002-8458-5ee207ddd48c" CreationDate="2023-02-08T21:01:21.383" UserId="19552" Comment="added 15 characters in body" Text="$cos (\theta_i)$ (or $\hat \omega_i ·\hat n$) accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ converts the oblique differential surface area (viewed along $-\omega_i$) into normal differential surface area (viewed along $-n$). By the definition of the dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39799" PostHistoryTypeId="5" PostId="13282" RevisionGUID="5cb5d988-01c2-4b6d-af59-49cf747d068d" CreationDate="2023-02-08T21:24:58.200" UserId="19552" Comment="added 352 characters in body" Text="$cos (\theta_i)$, or $\hat \omega_i ·\hat n$, accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ converts the oblique differential surface area (viewed along $-\omega_i$) into normal differential surface area (viewed along $-n$). $\hat \omega_i$ is a unit vector with its tail anchored at the differential area of surface reflection. Imagine a hemispherical ceiling, with its origin at the $\hat \omega_i$ vector tail. The head of $\hat \omega_i$ would be integrated over a small area of that ceiling. By definition, solid angle is that area divided by the squared radial distance. &#xD;&#xA;&#xD;&#xA;By the definition of dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39800" PostHistoryTypeId="5" PostId="13282" RevisionGUID="0e02748d-e3e5-4784-a6b3-7beaa9207c3e" CreationDate="2023-02-08T21:26:13.683" UserId="19552" Comment="added 33 characters in body" Text="$cos (\theta_i)$, or $\hat \omega_i ·\hat n$, accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ converts the oblique differential surface area (viewed along $-\omega_i$) into normal differential surface area (viewed along $-n$). $\hat \omega_i$ is a unit vector that points to the light source, with its tail anchored at the differential area of surface reflection. Imagine a hemispherical ceiling, with its origin at the $\hat \omega_i$ vector tail. The head of $\hat \omega_i$ would be integrated over a small area of that ceiling. By definition, solid angle is that area divided by the squared radial distance. &#xD;&#xA;&#xD;&#xA;By the definition of dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39801" PostHistoryTypeId="5" PostId="13282" RevisionGUID="4a067c4e-7690-4637-a021-b3f10f7348f5" CreationDate="2023-02-08T22:33:27.857" UserId="19552" Comment="deleted 5 characters in body" Text="$cos (\theta_i)$, or $\hat \omega_i ·\hat n$, accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i ·\hat n$ converts the oblique differential surface area (viewed along $-\omega_i$) into normal differential surface area (viewed along $-n$). $\hat \omega_i$ is a unit vector that points to the light source, with its tail anchored at the differential area of surface reflection. Imagine a hemispherical ceiling, with its origin at the tail of $\hat \omega_i$. The head of $\hat \omega_i$ would be integrated over a small area of the ceiling. By definition, solid angle is that area divided by the squared radial distance. &#xD;&#xA;&#xD;&#xA;By the definition of dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential quantity of irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L = \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$" ContentLicense="CC BY-SA 4.0" />
  <row Id="39802" PostHistoryTypeId="5" PostId="13282" RevisionGUID="c2ccb861-407f-4581-a7d9-66885d3dd0d8" CreationDate="2023-02-08T22:57:28.103" UserId="19552" Comment="added 28 characters in body" Text="$cos (\theta_i)$, or $\hat \omega_i ·\hat n$, accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i) (\hat \omega_i ·\hat n) d\omega_i $&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i$ is a unit vector pointing toward the light source with its tail anchored to the differential area of surface reflection. Imagine a hemispherical ceiling with its origin at the $\hat \omega_i$ tail. The head of $\hat \omega_i$ would be integrated over a small area of the ceiling. By definition, solid angle is that area divided by the squared radial distance. The $\hat \omega_i ·\hat n$ term converts the oblique differential surface area (as would be viewed along $-\omega_i$) into normal differential surface area (as would be viewed along $-n$).&#xD;&#xA;&#xD;&#xA;By the definition of dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L_o = L_e + \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39803" PostHistoryTypeId="5" PostId="13282" RevisionGUID="5ca7ba96-6118-4f61-adc6-07aa57377160" CreationDate="2023-02-08T22:58:43.290" UserId="19552" Comment="added 4 characters in body" Text="$cos (\theta_i)$, or $\hat \omega_i ·\hat n$, accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i) (\hat \omega_i ·\hat n) d\omega_i $&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i$ is a unit vector pointing toward the light source with its tail anchored to the differential area of surface reflection. Imagine a hemispherical ceiling with its origin at the $\hat \omega_i$ tail. The head of $\hat \omega_i$ would be integrated over a small area of the ceiling. By definition, solid angle is that area divided by the squared radial distance. The $\hat \omega_i ·\hat n$ term converts the oblique differential surface area (as would be viewed along $-\omega_i$) into normal differential surface area (as would be viewed along $-n$).&#xD;&#xA;&#xD;&#xA;By the definition of the dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L_o = L_e + \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39804" PostHistoryTypeId="5" PostId="13282" RevisionGUID="680069aa-c1a3-4748-be02-06e505fb56db" CreationDate="2023-02-08T23:03:56.810" UserId="19552" Comment="added 25 characters in body" Text="$cos (\theta_i)$, or $\hat \omega_i ·\hat n$, accounts for the effective scaling of differential surface area at oblique angles. BRDF is the change in reflected radiance (L, W/m^2/sr) divided by the change in irradiance (E, W/m^2). Irradiance is radiance integrated over solid angle,&#xD;&#xA;&#xD;&#xA;$E = \int_Ω L_i(\omega_i) (\hat \omega_i ·\hat n) d\omega_i $&#xD;&#xA;&#xD;&#xA;where $\hat \omega_i$ is a unit vector pointing toward the light source with its tail anchored to the differential area of surface reflection. Imagine a hemispherical ceiling with its origin at the $\hat \omega_i$ tail. The head of $\hat \omega_i$ would be integrated over a small area of the ceiling. By definition, solid angle ($\Omega$) is that small ceiling area divided by the squared radial distance. The $\hat \omega_i ·\hat n$ term converts the oblique differential surface area (as would be viewed along $-\omega_i$) into normal differential surface area (as would be viewed along $-n$).&#xD;&#xA;&#xD;&#xA;By the definition of the dot product,&#xD;&#xA;&#xD;&#xA;$\hat \omega_i ·\hat n = |\hat \omega_i||\hat n| cos (\theta_i) = cos (\theta_i)$&#xD;&#xA;&#xD;&#xA;The differential irradiance is therefore&#xD;&#xA; &#xD;&#xA;$dE = L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i = L_i(\omega_i) cos (\theta_i) d\omega_i$&#xD;&#xA;&#xD;&#xA;and the ratio of differential output radiance to differential irradiance is&#xD;&#xA;&#xD;&#xA;$BRDF(\omega_i,\omega_r) = \frac{dL_r(\omega_r)} {L_i(\omega_i) cos (\theta_i) d\omega_i}$&#xD;&#xA;&#xD;&#xA;The same conversion of oblique differential surface area to normal differential surface area is required by the rendering equation,&#xD;&#xA;&#xD;&#xA;$L_o = L_e + \int_Ω BRDF(\omega_i,\omega_r)  L_i(\omega_i)(\hat \omega_i ·\hat n) d\omega_i$&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39805" PostHistoryTypeId="2" PostId="13283" RevisionGUID="82a521a8-fee1-44e0-a88e-502567d58cb2" CreationDate="2023-02-08T23:26:34.807" UserId="19552" Text="The area projected by a hemisphere is that of a circle, $A=\pi r^2$&#xD;&#xA;&#xD;&#xA;Solid angle is defined as $A/r^2$. &#xD;&#xA;&#xD;&#xA;$\pi r^2/r^2=\pi$." ContentLicense="CC BY-SA 4.0" />
  <row Id="39807" PostHistoryTypeId="5" PostId="13283" RevisionGUID="4e308d3d-d175-419f-abf7-3caa9078e4eb" CreationDate="2023-02-08T23:26:53.953" UserId="19552" Comment="added 1 character in body" Text="The area projected by a hemisphere is that of a circle, $A=\pi r^2$.&#xD;&#xA;&#xD;&#xA;Solid angle is defined as $A/r^2$. &#xD;&#xA;&#xD;&#xA;$\pi r^2/r^2=\pi$." ContentLicense="CC BY-SA 4.0" />
  <row Id="39808" PostHistoryTypeId="5" PostId="13283" RevisionGUID="8001a7d3-8a1c-42f1-9d25-348d28c073d4" CreationDate="2023-02-09T00:04:04.923" UserId="19552" Comment="added 435 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of the angle of view. The Lambertian BRDF is therefore constant. What is that constant? By the definition of BRDF, $BRDF=L/E$.&#xD;&#xA;&#xD;&#xA;Irradiance (E, W/m^2) is found by multiplying radiance (L, W/m^2/sr) by projected solid angle, $E=L \Omega$. It follows that $BRDF=1/\Omega$.&#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $A=\pi r^2$ and solid angle is defined as $\Omega = A/r^2$. Projected solid angle is therefore $\Omega = \pi r^2/r^2=\pi$ and so the Lambertian BRDF is $1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39809" PostHistoryTypeId="5" PostId="13283" RevisionGUID="428ff666-0549-49f1-9b74-3da62db9a1dd" CreationDate="2023-02-09T00:05:05.490" UserId="19552" Comment="added 1 character in body" Text="The apparent brightness of a Lambertian surface is the same regardless of the angle of view. The Lambertian BRDF is therefore constant. What is that constant? By the definition of BRDF, $BRDF=L/E$.&#xD;&#xA;&#xD;&#xA;Irradiance (E, W/m^2) is found by multiplying radiance (L, W/m^2/sr) by projected solid angle, $E=L \Omega$. By substitution, $BRDF=1/\Omega$.&#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $A=\pi r^2$ and solid angle is defined as $\Omega = A/r^2$. Projected solid angle is therefore $\Omega = \pi r^2/r^2=\pi$ and so the Lambertian BRDF is $1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39810" PostHistoryTypeId="5" PostId="13283" RevisionGUID="2a9a1a0b-94ec-4ee7-bd8d-694f692e463e" CreationDate="2023-02-09T00:06:36.633" UserId="19552" Comment="deleted 4 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of the angle of view. The Lambertian BRDF is therefore constant. What is that constant? By the definition of BRDF, $BRDF=L/E$.&#xD;&#xA;&#xD;&#xA;Irradiance (E, W/m^2) is found by multiplying radiance (L, W/m^2/sr) by projected solid angle, $E=L \Omega$. By substitution, $BRDF=1/\Omega$.&#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $A=\pi r^2$ and solid angle is defined as $\Omega = A/r^2$. Projected solid angle is therefore $\Omega = \pi r^2/r^2$ and so the Lambertian BRDF is $1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39811" PostHistoryTypeId="5" PostId="13283" RevisionGUID="c847e537-918e-4d76-8201-9a43cbc9eb8a" CreationDate="2023-02-09T00:07:08.220" UserId="19552" Comment="added 1 character in body" Text="The apparent brightness of a Lambertian surface is the same regardless of the angle of view. The Lambertian BRDF is therefore constant. What is that constant? By the definition of BRDF, $BRDF=L/E$.&#xD;&#xA;&#xD;&#xA;Irradiance (E, W/m^2) is found by multiplying radiance (L, W/m^2/sr) by projected solid angle, $E=L \Omega$. By substitution, $BRDF=1/\Omega$.&#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $A=\pi r^2$, and solid angle is defined as $\Omega = A/r^2$. Projected solid angle is therefore $\Omega = \pi r^2/r^2$ and so the Lambertian BRDF is $1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39812" PostHistoryTypeId="5" PostId="13283" RevisionGUID="bf875cb3-984e-478e-9f63-ac4e1b8f736d" CreationDate="2023-02-09T00:11:16.717" UserId="19552" Comment="deleted 4 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of viewing angle. The Lambertian BRDF is therefore constant. What is that constant? By the definition of BRDF, $BRDF=L/E$.&#xD;&#xA;&#xD;&#xA;Irradiance (E, W/m^2) is found by multiplying radiance (L, W/m^2/sr) by projected solid angle, $E=L \Omega$. By substitution, $BRDF=1/\Omega$.&#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $A=\pi r^2$, and solid angle is defined as $\Omega = A/r^2$. Projected solid angle is therefore $\Omega = \pi r^2/r^2$ and so the Lambertian BRDF is $1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39813" PostHistoryTypeId="2" PostId="13284" RevisionGUID="ca142354-5e51-42e9-a018-d9d7655389f8" CreationDate="2023-02-09T00:54:31.260" UserId="7462" Text="I read the Algorithmic Beauty of plants.The resource goes in depth as to how to generate plant topology, but it does not talk about how to make the geometry except for the leaves.&#xD;&#xA;&#xD;&#xA;I tried looking into packages such as [plantgl][1] bbut I am still not entirely sure how they are making it.&#xD;&#xA;&#xD;&#xA;I understand they use sweep surfaces, but are they putting any effort into ensuring their models are manifold? Or are they just piece wise parametrizing each 1D section and not bothering to guarantee watertighntnes?&#xD;&#xA;&#xD;&#xA;Is there a way to grab a plant topology and parametrize it into a watertight mesh?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/openalea/plantgl" ContentLicense="CC BY-SA 4.0" />
  <row Id="39815" PostHistoryTypeId="1" PostId="13284" RevisionGUID="ca142354-5e51-42e9-a018-d9d7655389f8" CreationDate="2023-02-09T00:54:31.260" UserId="7462" Text="How do algorithmic botany algorithms generate their plant geometry from a skeleton?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39816" PostHistoryTypeId="3" PostId="13284" RevisionGUID="ca142354-5e51-42e9-a018-d9d7655389f8" CreationDate="2023-02-09T00:54:31.260" UserId="7462" Text="|computational-geometry|geometry|parametrization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39817" PostHistoryTypeId="2" PostId="13285" RevisionGUID="92f90f08-08f8-4af2-ac43-cd843891d51c" CreationDate="2023-02-09T09:01:45.540" UserId="7647" Text="First, I'll note that `cpfg`, the plant-modeling software used in the creation of &quot;The Algorithmic Beauty of Plants&quot;, has recently been open-sourced at https://github.com/AlgorithmicBotany/vlab so you can look it up yourself!&#xD;&#xA;&#xD;&#xA;Briefly, though, you're right that plant axes are just cylinders swept along a polyline. There was no effort made into making these models watertight; the cylinder swept by lateral branches intersect the main branch geometry. In general, it's a hard problem to nicely skin branch intersections. There was some published work on it at that lab, [The Use of Subdivision Surfaces in the Modeling of Plants](http://algorithmicbotany.org/papers/macmurchy.th2004.html), which tried to solve the problem by using low-poly branch templates; they still had difficulties for axes with many close branch points, if I recall." ContentLicense="CC BY-SA 4.0" />
  <row Id="39819" PostHistoryTypeId="50" PostId="13199" RevisionGUID="99fa0e89-c4e3-4f19-9ad1-df48f08ef17e" CreationDate="2023-02-09T11:01:50.200" UserId="-1" />
  <row Id="39820" PostHistoryTypeId="5" PostId="13283" RevisionGUID="e2776533-11c1-4587-9729-1465d1918f77" CreationDate="2023-02-09T18:49:53.063" UserId="19552" Comment="added 39 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of viewing angle. This is accomplished mathematically by the Lambertian BRDF cosine function, which counteracts the 1/cosine change in differential surface area at oblique angles. Since BRDF is reflected radiance (W/m^2/sr) over irradiance (W/m^2), the scaling factor for a hemisphere is simply one divided by the projected solid angle. The area projected by a hemisphere is $\pi r^2$ and the definition of solid angle is $\Omega = A/r^2$. It follows that $\Omega_{h} = \pi r^2/r^2 = \pi$ and $f_{Lambert}=1/\Omega_h=1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39821" PostHistoryTypeId="5" PostId="13283" RevisionGUID="5d6a9610-91e6-4342-b81a-31a29cff7727" CreationDate="2023-02-09T18:51:13.047" UserId="19552" Comment="added 19 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of viewing angle. This is accomplished mathematically by the Lambertian BRDF cosine function, which counteracts the 1/cosine change in differential surface area at oblique angles. Since BRDF is reflected radiance (W/m^2/sr) over irradiance (W/m^2), the scaling factor for a hemisphere is simply one divided by the projected solid angle. The area projected by a hemisphere is that of a circle, $\pi r^2$, and the definition of solid angle is $\Omega = A/r^2$. It follows that $\Omega_{h} = \pi r^2/r^2 = \pi$ and $f_{Lambert}=1/\Omega_h=1/\pi$.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39822" PostHistoryTypeId="5" PostId="13283" RevisionGUID="430c4e4e-afa6-4960-be67-a46a73c2a27c" CreationDate="2023-02-09T19:13:00.920" UserId="19552" Comment="added 166 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of viewing angle. This is accomplished mathematically by the Lambertian BRDF cosine function, which counteracts the 1/cosine change in differential surface area at oblique angles. Since BRDF is reflected radiance (W/m^2/sr) over irradiance (W/m^2), the value for a hemisphere is simply the albedo divided by the projected solid angle of a hemisphere. &#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $\pi r^2$, and the definition of solid angle is $\Omega = A/r^2$. It follows that $\Omega_{h} = \pi r^2/r^2 = \pi$. Converting from irradiance to reflected radiance, i.e., applying the BRDF, is as simple as multiplying by $albedo/\Omega_{h}=albedo/\pi$, where $albedo=1$ for a non-emissive surface.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39823" PostHistoryTypeId="5" PostId="13283" RevisionGUID="f4e72b29-478a-4256-954a-22eddaabd745" CreationDate="2023-02-09T19:19:03.027" UserId="19552" Comment="added 5 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of viewing angle. This is accomplished mathematically by the Lambertian BRDF cosine function, which counteracts the 1/cosine change in differential surface area at oblique angles. Since BRDF is reflected radiance (W/m^2/sr) over irradiance (W/m^2), the value for a hemisphere is therefore the albedo divided by the projected solid angle of a hemisphere. &#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $\pi r^2$, and the definition of solid angle is $\Omega = A/r^2$. It follows that $\Omega_{h} = \pi r^2/r^2 = \pi$. Converting from irradiance to reflected radiance, i.e., *applying the BRDF*, is as simple as multiplying by $albedo/\Omega_{h}=albedo/\pi$, where $albedo=1$ for a non-emissive surface.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39824" PostHistoryTypeId="5" PostId="13283" RevisionGUID="6cb6b74a-f708-4878-93ad-4d78c118cee0" CreationDate="2023-02-09T19:19:42.497" UserId="19552" Comment="deleted 10 characters in body" Text="The apparent brightness of a Lambertian surface is the same regardless of viewing angle. This is accomplished mathematically by the Lambertian BRDF cosine function, which counteracts the 1/cosine change in differential surface area at oblique angles. Since BRDF is reflected radiance (W/m^2/sr) over irradiance (W/m^2), the value for a hemisphere is the albedo divided by the projected solid angle of a hemisphere. &#xD;&#xA;&#xD;&#xA;The area projected by a hemisphere is that of a circle, $\pi r^2$, and the definition of solid angle is $\Omega = A/r^2$. It follows that $\Omega_{h} = \pi r^2/r^2 = \pi$. Converting from irradiance to reflected radiance, i.e., *applying the BRDF*, is as simple as multiplying by $albedo/\Omega_{h}=albedo/\pi$, where $albedo=1$ for a non-emissive surface.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39825" PostHistoryTypeId="2" PostId="13286" RevisionGUID="2667e121-95a4-498e-9911-75b9c3cec3d0" CreationDate="2023-02-09T22:16:53.573" UserId="13124" Text="As I understand [GLSL_EXT_ray_tracing.txt](https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_ray_tracing.txt), `gl_RayTmaxEXT` contains the **current t** in intersection shaders, due to the following pieces of information given in [GLSL_EXT_ray_tracing.txt](https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GLSL_EXT_ray_tracing.txt):&#xD;&#xA;&#xD;&#xA;     In the intersection language, built-in variables are declared as follows&#xD;&#xA;&#xD;&#xA;        ...&#xD;&#xA;&#xD;&#xA;        // Ray parameters&#xD;&#xA;        in          float  gl_RayTminEXT;&#xD;&#xA;        in volatile float  gl_RayTmaxEXT;&#xD;&#xA;        in          uint   gl_IncomingRayFlagsEXT;&#xD;&#xA;&#xD;&#xA;        ...&#xD;&#xA;&#xD;&#xA;=&gt; due to the `volatile` declaration of `gl_RayTmaxEXT`.&#xD;&#xA;&#xD;&#xA;Also the description of `bool reportIntersectionEXT(float hitT, uint hitKind);` remarks that `gl_RayTmaxEXT` is not constant:&#xD;&#xA;&gt; If the intersection is not ignored in the&#xD;&#xA;    any-hit shader, &amp;lt;hitT&amp;gt; is committed as the new gl_RayTmaxEXT value of the&#xD;&#xA;    current ray, &lt;hitKind&gt; is committed as the new value for gl_HitKindEXT, and&#xD;&#xA;    true is returned." ContentLicense="CC BY-SA 4.0" />
  <row Id="39827" PostHistoryTypeId="2" PostId="13287" RevisionGUID="3cd19304-3393-449b-bc72-b5a693a990da" CreationDate="2023-02-09T23:54:03.820" UserId="5664" Text="I am creating a custom shading model in Unreal Engine and I would like to create a square shaped specular highlight, without changing the shape of the light itself.&#xD;&#xA;&#xD;&#xA;I tried following the approach described in the paper &quot;stylized highlights for cartoon rendering and animation&quot; by Ken-ichi Anjyo, but I am having difficulty parsing the math notation they are using.&#xD;&#xA;&#xD;&#xA;The idea is to start with a simple blinn-phong specular highlight, and apply transformations to its half vector `H`. The vectors $\textbf{du}$ and $\textbf{dv}$ represent the tangent and bitangent vectors at the pixel normal.&#xD;&#xA;&#xD;&#xA;&gt; The squaring operation, which we&#xD;&#xA;&gt;denote by $sqr(H)$, makes a highlight area more square&#xD;&#xA;&gt;shaped. We define this operation for a highlight vector&#xD;&#xA;$H$ as follows:&#xD;&#xA;&#xD;&#xA;$\theta := \min(\cos^{-1}(\textbf{H}, \textbf{du}), \cos^{-1}(\textbf{H}, \textbf{dv}))$&#xD;&#xA;&#xD;&#xA;$\text{sqrnorm} := \sin(2\theta)^n$&#xD;&#xA;&#xD;&#xA;$\textbf{H}^\wedge := \textbf{H} - \sigma \times \text{sqrnorm}(\langle \textbf{H}, \textbf{du}\rangle \textbf{du} + \langle \textbf{H}, \textbf{dv}\rangle \textbf{dv})$&#xD;&#xA;&#xD;&#xA;$sqr(\textbf{H}) := \frac{\textbf{H}^{\wedge}}{||\textbf{H}^{\wedge}||}$&#xD;&#xA;&#xD;&#xA;&gt;where integer n and positive number σ(0.0 ≤σ≤ 1.0)&#xD;&#xA;&gt;are given. The highlight area would then be square&#xD;&#xA;&gt;shaped along the du- and dv-axis. With a rotation operation, we can get the highlight area square shaped in a&#xD;&#xA;&gt;desired direction. With a larger n, the area becomes&#xD;&#xA;&gt;more sharpened, whereas σ prescribes the magnitude&#xD;&#xA;&gt;of the squared area.&#xD;&#xA;&#xD;&#xA;I tried implementing the previous equation in HLSL like so:&#xD;&#xA;```&#xD;&#xA;float3 H = normalize(ToCamera + ToLight);&#xD;&#xA;float3 du = cross(N, float3(0.f, 1.f, 0.f)); // Tangent.&#xD;&#xA;float3 dv = cross(N, du); // Bitangent.&#xD;&#xA;&#xD;&#xA;// Square the highlight.&#xD;&#xA;float theta = min(acos(dot(H, du)), acos(H, dv));&#xD;&#xA;float sqrnorm = pow(sin(2.f * theta), n);&#xD;&#xA;float3 H_hat = H - sigma * sqrnorm * dot(H, du) * du + dot(H, dv) * dv;&#xD;&#xA;H_hat = normalize(H_hat);&#xD;&#xA;&#xD;&#xA;return round(pow(dot(N, H_hat), SpecularPower));&#xD;&#xA;```&#xD;&#xA;But this is just my best guess, the end result looks wrong. The expected result is a more square shaped specular highlight:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What I get instead is something that looks like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tAud4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XISvL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39829" PostHistoryTypeId="1" PostId="13287" RevisionGUID="3cd19304-3393-449b-bc72-b5a693a990da" CreationDate="2023-02-09T23:54:03.820" UserId="5664" Text="How can I transform the circular blinn-phong specular into a square shaped highlight?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39830" PostHistoryTypeId="3" PostId="13287" RevisionGUID="3cd19304-3393-449b-bc72-b5a693a990da" CreationDate="2023-02-09T23:54:03.820" UserId="5664" Text="|rendering|shading|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39832" PostHistoryTypeId="50" PostId="10341" RevisionGUID="447de999-d477-4add-8613-4855cf6344e0" CreationDate="2023-02-10T12:05:30.713" UserId="-1" />
  <row Id="39833" PostHistoryTypeId="2" PostId="13288" RevisionGUID="5a13b783-58b2-4bb4-880e-1812f5928b7c" CreationDate="2023-02-10T14:43:35.850" UserId="7952" Text="To create a square shaped specular highlight you just need to convert that standard Blin-Phong specular to a step function. Where the step function determines the cut off point for the specular value and returns 0 instead of a specular value.&#xD;&#xA;&#xD;&#xA;Here is a pseudo codish example:&#xD;&#xA;&#xD;&#xA;    vec3 blinnSquare(vec3 N, vec3 V, vec3 L, vec3 H, float shininess) {&#xD;&#xA;        float specular = 0.0;&#xD;&#xA;        float ndotl = max(dot(N, L), 0.0);&#xD;&#xA;        if (ndotl &gt; 0.0) {&#xD;&#xA;            float ndoth = max(dot(N, H), 0.0);&#xD;&#xA;            float angle = acos(ndoth);&#xD;&#xA;            if (angle &gt;= 0.0 &amp;&amp; angle &lt;= 45.0) {&#xD;&#xA;                specular = pow(ndoth, shininess);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The use of acos isn't suitable for production but it does make clear what is going on here and that is the reason for its use.&#xD;&#xA;&#xD;&#xA;Just to be clear, I haven't actually tried this code, it was written as an example. Your mileage may vary." ContentLicense="CC BY-SA 4.0" />
  <row Id="39835" PostHistoryTypeId="2" PostId="13289" RevisionGUID="51f42e7f-b1b2-40c8-95c7-79b3f61d2546" CreationDate="2023-02-10T21:39:30.223" UserId="19523" Text="Note that if $cos$ is not removed, the distribution function won't (necessarily) integrate to $1$ (energy is not conserved). Specular rays means that $f(...)$ is proportional to $C(\omega_r) \delta(\omega_i,\omega_r)$, where $\delta$ is dirac's delta function and $\omega_r$ is the reflection direction. Lets put $L_i=1$ and integrate the distribution: $C(\omega_r)cos(\theta_r) = 1$ which implies that $cos(\theta_r)$ must be cancelled." ContentLicense="CC BY-SA 4.0" />
  <row Id="39837" PostHistoryTypeId="2" PostId="13290" RevisionGUID="5159773e-ecd9-428f-9fc0-16cc7a0f825f" CreationDate="2023-02-10T22:04:35.007" UserId="19523" Text="Assume that rays with a distance larger than $D$ won't contribute to the occlusion. Since I don't know exactly of V-ray implements their interpolation, we can create a weight function $w(\frac{d}{D})$ where $w(x) = \left\{\begin{matrix}&#xD;&#xA;f(x), \quad 0 \geq x \geq 1 \\ &#xD;&#xA;0, \quad otherwise&#xD;&#xA;\end{matrix}\right.$&#xD;&#xA;&#xD;&#xA;and compute $AO = 1 - \frac{1}{N} \sum_{i=0}^N w(\frac{d_i}{D})$.&#xD;&#xA;&#xD;&#xA;A simple example would be to let $f(x) = 1-x$ but this gives $w$ a non-continuous first derivative. Adding some additional constraints besides $f(0)=1, f(1)=0$, like $f'(1) = 0, f''(1)=0$ would give a polynomial like $f(x) = 1-3x+3x^2-x^3$ which decreases in value a bit faster than linear and would give smoother results." ContentLicense="CC BY-SA 4.0" />
  <row Id="39843" PostHistoryTypeId="5" PostId="13287" RevisionGUID="4cc6a86a-d4fa-48a9-9218-ff112ab69c83" CreationDate="2023-02-11T02:12:23.687" UserId="5664" Comment="added 83 characters in body" Text="I am creating a custom shading model in Unreal Engine and I would like to create a square shaped specular highlight, without changing the shape of the light itself.&#xD;&#xA;&#xD;&#xA;I tried following the approach described in the paper &quot;stylized highlights for cartoon rendering and animation&quot; by Ken-ichi Anjyo, but I am having difficulty parsing the math notation they are using.&#xD;&#xA;&#xD;&#xA;The idea is to start with a simple blinn-phong specular highlight, and apply transformations to its half vector `H`. The vectors $\textbf{du}$ and $\textbf{dv}$ represent the tangent and bitangent vectors at the pixel normal.&#xD;&#xA;&#xD;&#xA;&gt; The squaring operation, which we&#xD;&#xA;&gt;denote by $sqr(H)$, makes a highlight area more square&#xD;&#xA;&gt;shaped. We define this operation for a highlight vector&#xD;&#xA;$H$ as follows:&#xD;&#xA;&#xD;&#xA;$\theta := \min(\cos^{-1}(\textbf{H}, \textbf{du}), \cos^{-1}(\textbf{H}, \textbf{dv}))$&#xD;&#xA;&#xD;&#xA;$\text{sqrnorm} := \sin(2\theta)^n$&#xD;&#xA;&#xD;&#xA;$\textbf{H}^\wedge := \textbf{H} - \sigma \times \text{sqrnorm}(\langle \textbf{H}, \textbf{du}\rangle \textbf{du} + \langle \textbf{H}, \textbf{dv}\rangle \textbf{dv})$&#xD;&#xA;&#xD;&#xA;$sqr(\textbf{H}) := \frac{\textbf{H}^{\wedge}}{||\textbf{H}^{\wedge}||}$&#xD;&#xA;&#xD;&#xA;&gt;where integer n and positive number σ(0.0 ≤σ≤ 1.0)&#xD;&#xA;&gt;are given. The highlight area would then be square&#xD;&#xA;&gt;shaped along the du- and dv-axis. With a rotation operation, we can get the highlight area square shaped in a&#xD;&#xA;&gt;desired direction. With a larger n, the area becomes&#xD;&#xA;&gt;more sharpened, whereas σ prescribes the magnitude&#xD;&#xA;&gt;of the squared area.&#xD;&#xA;&#xD;&#xA;I tried implementing the previous equation in HLSL like so:&#xD;&#xA;```&#xD;&#xA;float3 H = normalize(ToCamera + ToLight);&#xD;&#xA;float3 du = cross(N, float3(0.f, 1.f, 0.f)); // Tangent.&#xD;&#xA;float3 dv = cross(N, du); // Bitangent.&#xD;&#xA;&#xD;&#xA;// Square the highlight.&#xD;&#xA;float theta = min(acos(dot(H, du)), acos(H, dv));&#xD;&#xA;float sqrnorm = pow(sin(2.f * theta), n);&#xD;&#xA;float3 H_hat = H - sigma * sqrnorm * dot(H, du) * du + dot(H, dv) * dv;&#xD;&#xA;H_hat = normalize(H_hat);&#xD;&#xA;&#xD;&#xA;return round(pow(dot(N, H_hat), SpecularPower));&#xD;&#xA;```&#xD;&#xA;But this is just my best guess, the end result looks wrong. The expected result is a more square shaped specular highlight:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;What I get instead is something that looks like this:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tAud4.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/XISvL.png&#xD;&#xA;&#xD;&#xA;You can see specular squaring in motion here: https://youtu.be/svhMHGIT4bI?t=66" ContentLicense="CC BY-SA 4.0" />
  <row Id="39844" PostHistoryTypeId="5" PostId="13271" RevisionGUID="74e7a412-4d04-4e9b-91a0-d301f995fab4" CreationDate="2023-02-11T06:11:30.063" UserId="19534" Comment="added 313 characters in body" Text="My AO algorithm is as follows, whith the random vectors just all over the hemisphere:&#xD;&#xA;```c++&#xD;&#xA;    vec3 ao_ray_position= random_in_hemisphere(gi_rec.normal);&#xD;&#xA;    &#xD;&#xA;    ao_ray = ray(gi_rec.p + gi_rec.normal * 0.001f, ao_ray_position);&#xD;&#xA;    ao_hit = !world.hit(ao_ray, 0, infinity, gi_rec);&#xD;&#xA;            &#xD;&#xA;    ao_result = Color(ao_hit / gi_samples, ao_hit/ gi_samples, ao_hit/ gi_samples);&#xD;&#xA;```&#xD;&#xA;which renders this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this one is from V-Ray with falloff at 8,7, which is the setting I want to implement, but can't figure out how. I've seen many examples of limiting the hemisphere by cone angle but the image just renders black&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Thanks to Mathis I got it working, the code and the result meanwhile:&#xD;&#xA;```c++&#xD;&#xA;    float ao = 1.0f;&#xD;&#xA;    float dist = distance(gi_rec.p, rec.p);&#xD;&#xA;    if (dist &lt; d) {&#xD;&#xA;    	ao = !gi_hit / dist;&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/01Nan.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/N8ECX.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/fP3el.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39845" PostHistoryTypeId="5" PostId="13271" RevisionGUID="08323964-7101-4e71-8ed6-b78b19821deb" CreationDate="2023-02-11T06:34:06.937" UserId="19534" Comment="deleted 4 characters in body" Text="My AO algorithm is as follows, whith the random vectors just all over the hemisphere:&#xD;&#xA;```c++&#xD;&#xA;    vec3 ao_ray_position= random_in_hemisphere(gi_rec.normal);&#xD;&#xA;    &#xD;&#xA;    ao_ray = ray(gi_rec.p + gi_rec.normal * 0.001f, ao_ray_position);&#xD;&#xA;    ao_hit = !world.hit(ao_ray, 0, infinity, gi_rec);&#xD;&#xA;            &#xD;&#xA;    ao_result = Color(ao_hit / gi_samples, ao_hit/ gi_samples, ao_hit/ gi_samples);&#xD;&#xA;```&#xD;&#xA;which renders this image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now this one is from V-Ray with falloff at 8,7, which is the setting I want to implement, but can't figure out how. I've seen many examples of limiting the hemisphere by cone angle but the image just renders black&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;Thanks to Mathis I got it working, the code and the result meanwhile:&#xD;&#xA;```c++&#xD;&#xA;    float ao = 1.0f;&#xD;&#xA;    float dist = distance(gi_rec.p, rec.p);&#xD;&#xA;    if (dist &lt; d) {&#xD;&#xA;    	ao = !gi_hit / dist;&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/01Nan.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/N8ECX.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/cv3jb.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39846" PostHistoryTypeId="2" PostId="13291" RevisionGUID="5313f023-cefd-43a8-abbd-002740fe2f45" CreationDate="2023-02-11T08:43:31.473" UserId="17063" Text="I have an openGL style matrix (column major, right handed ) that needs to be converted into two vectors (forward and up) &#xD;&#xA;I've managed to find, in a weird way, a solution that matches the the coordinates rotation, but if I move the camera there is a mismatch that increases if I'm moving the cam from the world center.&#xD;&#xA;&#xD;&#xA;What I do is taking an identity matrix and invert the 1.f values to -1.f (apart from the w axis) and then I multiply it by the cam matrix and then again to the identity matrix like this.&#xD;&#xA;&#xD;&#xA;new_base_matrix = (weird identity) * cam_camtrix * (weird identity).inverted();&#xD;&#xA;&#xD;&#xA;then I multiply the new_base_matrix by the camera eye (cam_matrix w axis), the forward vector (0,0,1) and the up vector (0,1,0).&#xD;&#xA;&#xD;&#xA;here is a bit of code:&#xD;&#xA;&#xD;&#xA;    Matrix4 input_cam__matrix = cam-&gt;matrix();&#xD;&#xA;    Matrix4 inverted_axis_m = {  -1.f, 0, 0, 0,&#xD;&#xA;    										0, -1.f, 0, 0,&#xD;&#xA;    										0, 0, -1.f, 0,&#xD;&#xA;    										0, 0, 0, 1.f };&#xD;&#xA;    input_cam__matrix = inverted_axis_m * input_cam__matrix * inverted_axis_m;&#xD;&#xA;    &#xD;&#xA;    //apply rotation scale and pos using the new base&#xD;&#xA;    Vector4 pos = input_cam__matrix * Vector4(input_cam__matrix.translation().x, input_cam__matrix.translation().y, input_cam__matrix.translation().z);&#xD;&#xA;    Vector4 dir = input_cam__matrix * Vector4(0, 0, 1.f, 0) ;&#xD;&#xA;    Vector4 up = input_cam__matrix * Vector4(0, 1.f, 0, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    //final vector for the left handed camera&#xD;&#xA;    float cam_pos[] =  { pos.x,  pos.y, pos.z };&#xD;&#xA;    float cam_view[] = { dir.x , dir.y, dir.z };&#xD;&#xA;    float cam_up[]   = {  up.x,   up.y,  up.z };&#xD;&#xA;    &#xD;&#xA;    float fov = 2 * atan(cam-&gt;film_height() / (2 * cam-&gt;focal_length()))  * (180 / M_PI);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39848" PostHistoryTypeId="1" PostId="13291" RevisionGUID="5313f023-cefd-43a8-abbd-002740fe2f45" CreationDate="2023-02-11T08:43:31.473" UserId="17063" Text="convert right handed matrix into left handed forward/up/right vectors" ContentLicense="CC BY-SA 4.0" />
  <row Id="39849" PostHistoryTypeId="3" PostId="13291" RevisionGUID="5313f023-cefd-43a8-abbd-002740fe2f45" CreationDate="2023-02-11T08:43:31.473" UserId="17063" Text="|opengl|raytracing|c++|matrix|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39850" PostHistoryTypeId="5" PostId="13291" RevisionGUID="2dbef315-3fb0-4d0f-b5cb-525436c5b88d" CreationDate="2023-02-11T09:11:09.410" UserId="17063" Comment="deleted 1 character in body" Text="I have an openGL style matrix (column major, right handed ) that needs to be converted into two vectors (forward and up) &#xD;&#xA;I've managed to find, in a weird way, a solution that matches the the coordinates rotation, but if I move the camera there is a mismatch that increases if I'm moving the cam from the world center.&#xD;&#xA;&#xD;&#xA;What I do is taking an identity matrix and invert the 1.f values to -1.f (apart from the w axis) and then I multiply it by the cam matrix and then again to the identity matrix like this.&#xD;&#xA;&#xD;&#xA;new_base_matrix = (weird identity) * cam_matrix * (weird identity).inverted();&#xD;&#xA;&#xD;&#xA;then I multiply the new_base_matrix by the camera eye (cam_matrix w axis), the forward vector (0,0,1) and the up vector (0,1,0).&#xD;&#xA;&#xD;&#xA;here is a bit of code:&#xD;&#xA;&#xD;&#xA;    Matrix4 input_cam__matrix = cam-&gt;matrix();&#xD;&#xA;    Matrix4 inverted_axis_m = {             -1.f, 0, 0, 0,&#xD;&#xA;    										0, -1.f, 0, 0,&#xD;&#xA;    										0, 0, -1.f, 0,&#xD;&#xA;    										0, 0, 0, 1.f };&#xD;&#xA;    input_cam__matrix = inverted_axis_m * input_cam__matrix * inverted_axis_m;&#xD;&#xA;    &#xD;&#xA;    //apply rotation scale and pos using the new base&#xD;&#xA;    Vector4 pos = input_cam__matrix * Vector4(input_cam__matrix.translation().x, input_cam__matrix.translation().y, input_cam__matrix.translation().z);&#xD;&#xA;    Vector4 dir = input_cam__matrix * Vector4(0, 0, 1.f, 0) ;&#xD;&#xA;    Vector4 up = input_cam__matrix * Vector4(0, 1.f, 0, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    //final vector for the left handed camera&#xD;&#xA;    float cam_pos[] =  { pos.x,  pos.y, pos.z };&#xD;&#xA;    float cam_view[] = { dir.x , dir.y, dir.z };&#xD;&#xA;    float cam_up[]   = {  up.x,   up.y,  up.z };&#xD;&#xA;    &#xD;&#xA;    float fov = 2 * atan(cam-&gt;film_height() / (2 * cam-&gt;focal_length()))  * (180 / M_PI);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39851" PostHistoryTypeId="5" PostId="13291" RevisionGUID="0c86a2de-dfb4-4dd2-b87d-1a8c62d4654a" CreationDate="2023-02-11T09:32:10.387" UserId="17063" Comment="added 162 characters in body" Text="I have an openGL style matrix (column major, right handed ) that needs to be converted into two vectors (forward and up) &#xD;&#xA;I've managed to find, in a weird way, a solution that matches the the coordinates rotation, but if I move the camera there is a mismatch that increases if I'm moving the cam from the world center.&#xD;&#xA;&#xD;&#xA;What I do is taking an identity matrix and invert the 1.f values to -1.f (apart from the w axis) and then I multiply it by the cam matrix and then again to the identity matrix like this.&#xD;&#xA;&#xD;&#xA;new_base_matrix = (weird identity) * cam_matrix * (weird identity).inverted();&#xD;&#xA;&#xD;&#xA;then I multiply the new_base_matrix by the camera eye (cam_matrix w axis), the forward vector (0,0,1) and the up vector (0,1,0).&#xD;&#xA;&#xD;&#xA;here is a bit of code:&#xD;&#xA;&#xD;&#xA;    Matrix4 input_cam__matrix = cam-&gt;matrix();&#xD;&#xA;    Matrix4 inverted_axis_m = {             -1.f, 0, 0, 0,&#xD;&#xA;    										0, -1.f, 0, 0,&#xD;&#xA;    										0, 0, -1.f, 0,&#xD;&#xA;    										0, 0, 0, 1.f };&#xD;&#xA;    input_cam__matrix = inverted_axis_m * input_cam__matrix * inverted_axis_m;&#xD;&#xA;    &#xD;&#xA;    //apply rotation scale and pos using the new base&#xD;&#xA;    Vector4 pos = input_cam__matrix * Vector4(input_cam__matrix.translation().x, input_cam__matrix.translation().y, input_cam__matrix.translation().z);&#xD;&#xA;    Vector4 dir = input_cam__matrix * Vector4(0, 0, 1.f, 0) ;&#xD;&#xA;    Vector4 up = input_cam__matrix * Vector4(0, 1.f, 0, 0);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    //final vector for the left handed camera&#xD;&#xA;    float cam_pos[] =  { pos.x,  pos.y, pos.z };&#xD;&#xA;    float cam_view[] = { dir.x , dir.y, dir.z };&#xD;&#xA;    float cam_up[]   = {  up.x,   up.y,  up.z };&#xD;&#xA;    &#xD;&#xA;    float fov = 2 * atan(cam-&gt;film_height() / (2 * cam-&gt;focal_length()))  * (180 / M_PI);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I don't know what sign the system that uses the up/forward vectors uses, but I think is +Y on the Y axis.&#xD;&#xA;My system, which is the input_camera_matrix is +X+Y+Z ." ContentLicense="CC BY-SA 4.0" />
  <row Id="39852" PostHistoryTypeId="5" PostId="13288" RevisionGUID="52fe6135-f20c-418c-b933-96c010248dba" CreationDate="2023-02-11T13:00:17.880" UserId="7952" Comment="reformulated code to be a little more user friendly" Text="To create a square shaped specular highlight you just need to convert that standard Blin-Phong specular to a step function. Where the step function determines the cut off point for the specular value and returns 0 instead of a specular value.&#xD;&#xA;&#xD;&#xA;Here is a pseudo example:&#xD;&#xA;&#xD;&#xA;    float squareSpecular(vec3 halfVec, vec3 surfaceNormal)&#xD;&#xA;    {&#xD;&#xA;       float angle = dot(halfVec, surfaceNormal);&#xD;&#xA;       angle = clamp(angle, 0.0, 1.0);&#xD;&#xA;       float specular = pow(angle, shininess);&#xD;&#xA;       return step(0.5, angle) * specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Again, the idea is to make use of a step to cut off the highlight at certain angles. The example code is just a basic outline of how to accomplish that.&#xD;&#xA;&#xD;&#xA;Or formulated another way: &#xD;&#xA;&#xD;&#xA;    vec3 L = normalize(lightDirection);&#xD;&#xA;    vec3 V = normalize(viewDirection);&#xD;&#xA;    vec3 H = normalize(L + V);&#xD;&#xA;&#xD;&#xA;    vec3 du = vec3(1.0, 0.0, 0.0);&#xD;&#xA;    vec3 dv = vec3(0.0, 1.0, 0.0);&#xD;&#xA;&#xD;&#xA;    float dotProductDU = dot(H, du);&#xD;&#xA;    float dotProductDV = dot(H, dv);&#xD;&#xA;&#xD;&#xA;    float squareHighlight = min(1.0, pow(max(dotProductDU, 0.0), shininess) * pow(max(dotProductDV, 0.0), shininess));&#xD;&#xA;&#xD;&#xA;    vec3 specularColor = lightColor * squareHighlight;&#xD;&#xA;&#xD;&#xA;Here du and dv are vectors that can be rotated to change the direction of the square." ContentLicense="CC BY-SA 4.0" />
  <row Id="39853" PostHistoryTypeId="5" PostId="13288" RevisionGUID="85f69466-a934-4fd8-b9f1-b2a3a26b072c" CreationDate="2023-02-11T13:15:18.960" UserId="7952" Comment="deleted 10 characters in body" Text="To create a square shaped specular highlight you just need to convert that standard Blin-Phong specular to a step function. Where the step function determines the cut off point for the specular value and returns 0 instead of a specular value.&#xD;&#xA;&#xD;&#xA;Here is a pseudo example:&#xD;&#xA;&#xD;&#xA;    float squareSpecular(vec3 halfVec, vec3 surfaceNormal)&#xD;&#xA;    {&#xD;&#xA;       float angle = dot(halfVec, surfaceNormal);&#xD;&#xA;       angle = clamp(angle, 0.0, 1.0);&#xD;&#xA;       float specular = pow(angle, shininess);&#xD;&#xA;       return step(0.5, angle) * specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Again, the idea is to make use of a step to cut off the highlight at certain angles. The example code is just a basic outline of how to accomplish that.&#xD;&#xA;&#xD;&#xA;Or formulated another way: &#xD;&#xA;&#xD;&#xA;    vec3 L = normalize(lightDirection);&#xD;&#xA;    vec3 V = normalize(viewDirection);&#xD;&#xA;    vec3 H = normalize(L + V);&#xD;&#xA;&#xD;&#xA;    vec3 du = vec3(1.0, 0.0, 0.0);&#xD;&#xA;    vec3 dv = vec3(0.0, 1.0, 0.0);&#xD;&#xA;&#xD;&#xA;    float dotProductDU = dot(H, du);&#xD;&#xA;    float dotProductDV = dot(H, dv);&#xD;&#xA;&#xD;&#xA;    float squareHighlight = pow(max(dotProductDU, 0.0), shininess) * pow(max(dotProductDV, 0.0), shininess);&#xD;&#xA;&#xD;&#xA;    vec3 specularColor = lightColor * squareHighlight;&#xD;&#xA;&#xD;&#xA;Here du and dv are vectors that can be rotated to change the direction of the square." ContentLicense="CC BY-SA 4.0" />
  <row Id="39854" PostHistoryTypeId="5" PostId="13288" RevisionGUID="db40e78f-ea83-430a-9fe5-fd9235f54c4b" CreationDate="2023-02-11T13:34:18.807" UserId="7952" Comment="added 55 characters in body" Text="To create a square shaped specular highlight you just need to convert that standard Blin-Phong specular to a step function. Where the step function determines the cut off point for the specular value and returns 0 instead of a specular value.&#xD;&#xA;&#xD;&#xA;Here is a pseudo example:&#xD;&#xA;&#xD;&#xA;    float squareSpecular(vec3 halfVec, vec3 surfaceNormal)&#xD;&#xA;    {&#xD;&#xA;       float angle = dot(halfVec, surfaceNormal);&#xD;&#xA;       angle = clamp(angle, 0.0, 1.0);&#xD;&#xA;       float specular = pow(angle, shininess);&#xD;&#xA;       return step(0.5, angle) * specular;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Again, the idea is to make use of a step to cut off the highlight at certain angles. The example code is just a basic outline of how to accomplish that.&#xD;&#xA;&#xD;&#xA;Or formulated another way: (this version should be close to the paper you mention)&#xD;&#xA;&#xD;&#xA;    vec3 L = normalize(lightDirection);&#xD;&#xA;    vec3 V = normalize(viewDirection);&#xD;&#xA;    vec3 H = normalize(L + V);&#xD;&#xA;&#xD;&#xA;    vec3 du = vec3(1.0, 0.0, 0.0);&#xD;&#xA;    vec3 dv = vec3(0.0, 1.0, 0.0);&#xD;&#xA;&#xD;&#xA;    float dotProductDU = dot(H, du);&#xD;&#xA;    float dotProductDV = dot(H, dv);&#xD;&#xA;&#xD;&#xA;    float squareHighlight = pow(max(dotProductDU, 0.0), shininess) * pow(max(dotProductDV, 0.0), shininess);&#xD;&#xA;&#xD;&#xA;    vec3 specularColor = lightColor * squareHighlight;&#xD;&#xA;&#xD;&#xA;Here du and dv are vectors that can be rotated to change the direction of the square." ContentLicense="CC BY-SA 4.0" />
  <row Id="39855" PostHistoryTypeId="50" PostId="13210" RevisionGUID="95240bb4-bc62-4818-85d8-20042f3df40f" CreationDate="2023-02-11T17:04:55.613" UserId="-1" />
  <row Id="39856" PostHistoryTypeId="50" PostId="9199" RevisionGUID="1515bbaf-3f69-43af-80eb-ead3c386a459" CreationDate="2023-02-12T04:07:45.983" UserId="-1" />
  <row Id="39857" PostHistoryTypeId="2" PostId="13292" RevisionGUID="533184c8-3f8e-4c34-8798-e3c338887899" CreationDate="2023-02-12T06:55:13.257" UserId="10932" Text="Obviously, conceptually, a meshlet *is* just a small mesh.  But what is the reason for making the distinction then?  I'm assuming it has to do with how they are implemented.&#xD;&#xA;&#xD;&#xA;In a meshlet architecture, does a parent mesh contain the complete vertex buffer while the meshlets contain their individual index buffers?  Or do meshlets contain more (or possibly less?) data than that?&#xD;&#xA;&#xD;&#xA;I can understand the benefits of being able to act on small clusters of geometry for culling/clipping/shading, and they seem incredibly powerful with LoD techniques such as those found in Nanite.  But im a bit unclear as to what, implementation wise, is actually meant by &quot;meshlet&quot;.  Or if there is even a standard at all." ContentLicense="CC BY-SA 4.0" />
  <row Id="39859" PostHistoryTypeId="1" PostId="13292" RevisionGUID="533184c8-3f8e-4c34-8798-e3c338887899" CreationDate="2023-02-12T06:55:13.257" UserId="10932" Text="What is the difference between a &quot;meshlet&quot; and just a small mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39860" PostHistoryTypeId="3" PostId="13292" RevisionGUID="533184c8-3f8e-4c34-8798-e3c338887899" CreationDate="2023-02-12T06:55:13.257" UserId="10932" Text="|rendering|mesh|gpu|rasterizer|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39861" PostHistoryTypeId="2" PostId="13293" RevisionGUID="a5c02b57-a2b9-40ce-86a0-22f636de7808" CreationDate="2023-02-12T10:04:38.307" UserId="19523" Text="Your first question seems a bit philosophical, but I think the reason is to make a distinction between the actual mesh and the optimized triangle groups (meshlets) to facilitate talking about them.&#xD;&#xA;I looked at (https://developer.nvidia.com/blog/introduction-turing-mesh-shaders/) and from what I read I think meshlets contain the same amount of data.&#xD;&#xA;&#xD;&#xA;Meshlets can be compared to wavelets, which describe functions in both frequency and time space. So it &quot;divides&quot; the function into parts that correspond to different sizes and positions. There is a similarity between the weighted wavelets (ie the projection of a function on that particular wavelet) and meshlets (group of triangles) that form the complete mesh, if that is what you mean by implementation." ContentLicense="CC BY-SA 4.0" />
  <row Id="39863" PostHistoryTypeId="2" PostId="13294" RevisionGUID="dd5574fd-fb88-47eb-9a22-ef4d68f0887a" CreationDate="2023-02-12T10:26:06.740" UserId="19523" Text="I am going to assume that you have the normals available for each point and that your vertex pass don't do this for you. For every pixel you will have an intersection point $p$ that exists on the nearest triangle surface defined by 3 points $p_i$, $p_j$ and $p_k$ with corresponding normals $n_i$, $n_j$ and $n_k$. Phong shading is the normalized interpolated normal, which can be found by:&#xD;&#xA;&#xD;&#xA;1. Computing the barycentric coordinates of $p$, (look at (https://github.com/Jojendersie/gpugi/blob/5d18526c864bbf09baca02bfab6bcec97b7e1210/gpugi/shader/intersectiontests.glsl#L63) in the function &quot;IntersectTriangle&quot;). Note that the order is important such that your coordinate values $u$, $v$ and $w$ has the same order as your points.&#xD;&#xA;&#xD;&#xA;2. Interpolating and normalizing: $\frac{un_i + vn_j + wn_k}{|| un_i + vn_j + wn_k ||}$.&#xD;&#xA;&#xD;&#xA;3. ???&#xD;&#xA;&#xD;&#xA;4. Profit!" ContentLicense="CC BY-SA 4.0" />
  <row Id="39865" PostHistoryTypeId="2" PostId="13295" RevisionGUID="f1859fec-178d-4d73-b983-8be962fc84a5" CreationDate="2023-02-12T15:23:08.710" UserId="2654" Text="A &quot;meshlet&quot; is a concept built around the specific architecture of how shaders work.&#xD;&#xA;&#xD;&#xA;Shaders are invoked in work groups, even when shader stages don't explicitly represent that concept in the API. This means that some number of invocations are executed in lock-step with each other on the same core. That's the natural way they work.&#xD;&#xA;&#xD;&#xA;In theory this could allow different invocations in the same work group to share data. This is what compute shaders and tessellation control shaders do with `shared` and `out` variables respectively.&#xD;&#xA;&#xD;&#xA;However, the nature of the traditional vertex processing pipeline makes this data sharing difficult. The order of execution of vertex shaders, which invocations go into which work groups, can change based on how indices are processed, the state of the post-T&amp;L vertex cache, etc. It is not reliable, and therefore you cannot really share information between VS invocations.&#xD;&#xA;&#xD;&#xA;The [mesh shader][1] pipeline is designed to more directly mirror hardware. In this pipeline, there are no equivalents to vertex attributes; if you want to get some vertex data, the shader must use SSBOs or similar tools to fetch them. That is, everything is up to you.&#xD;&#xA;&#xD;&#xA;The goal here is to process meshes in work groups. For a mesh of a given size, you execute some number of work groups on that mesh, with each group having some number of invocations that can share data between them.&#xD;&#xA;&#xD;&#xA;However, since work group sizes and shared storage is finite and quite small, it is reasonable for a work group to only operate on a portion of the mesh rather than the whole thing. To do this, the mesh needs to be broken down into appropriately sized chunks. We call these chunks &quot;meshlets&quot;.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL/extensions/NV/NV_mesh_shader.txt" ContentLicense="CC BY-SA 4.0" />
  <row Id="39867" PostHistoryTypeId="2" PostId="13296" RevisionGUID="9efe20c6-e563-4203-a497-b360578bae75" CreationDate="2023-02-12T16:06:24.180" UserId="17063" Text="I was applying the transform twice, here the solution:&#xD;&#xA;&#xD;&#xA;    Matrix4 input_cam__matrix = cam-&gt;matrix();&#xD;&#xA;    Vector3 translation = input_cam__matrix.translation();&#xD;&#xA;    input_cam__matrix.rotationOnly();&#xD;&#xA;    Matrix4 inverted_axis_m = {  -1.f, 0, 0, 0,&#xD;&#xA;    										0, -1.f, 0, 0,&#xD;&#xA;    										0, 0, -1.f, 0,&#xD;&#xA;    										0, 0, 0, 1.f &#xD;&#xA;    };&#xD;&#xA;    input_cam__matrix = inverted_axis_m * input_cam__matrix * inverted_axis_m;&#xD;&#xA;    &#xD;&#xA;    Vector3 pos = -translation;&#xD;&#xA;    Vector4 dir = input_cam__matrix * Vector4(0, 0, 1.f, 1.f) ;&#xD;&#xA;    Vector4 up = input_cam__matrix  * Vector4(0, 1.f, 0, 1.f);&#xD;&#xA;&#xD;&#xA;The forward and up vectors only get the rotation (I removed the position data from the cam_matrix) and then applied the position to the eye vector.&#xD;&#xA;&#xD;&#xA;Everything is inverted, position and rotation. I found this unique" ContentLicense="CC BY-SA 4.0" />
  <row Id="39869" PostHistoryTypeId="50" PostId="10025" RevisionGUID="fa33dde2-9326-4509-9ab9-51acdca4de00" CreationDate="2023-02-13T04:03:30.360" UserId="-1" />
  <row Id="39870" PostHistoryTypeId="50" PostId="9267" RevisionGUID="9a697230-dfe1-4dd3-89ec-64fc0ba1562e" CreationDate="2023-02-13T11:04:05.610" UserId="-1" />
  <row Id="39871" PostHistoryTypeId="2" PostId="13297" RevisionGUID="5021a906-3650-439c-b164-fc9d27878104" CreationDate="2023-02-13T13:44:32.450" UserId="7952" Text="A popular method of generating the mesh from an L system is called a &quot;Turtle Graphics&quot; system.&#xD;&#xA;&#xD;&#xA;In a turtle graphics system we imagine a turtle which starts at the root of the system reads a symbol from the L system and walks in a specific direction based on the symbol. The symbol itself is associated with a polygon and the entire system is seeded with a polygon from the root symbol.&#xD;&#xA;&#xD;&#xA;The polygons themselves can be generated algorithmically by the system and then modified for each generation of the plant or predefined such as a simple N sided circle. &#xD;&#xA;&#xD;&#xA;As the turtle marches through the L system each symbol gives it instructions on direction and how many steps to take. For example, a turtle may be instructed to move 3 steps in the up direction.&#xD;&#xA;&#xD;&#xA;The turtle starts at the seeded polygon, reads the symbol, takes a step and places the polygon for that symbol. Then the two polygon's are connected. A simple and effective way to do this is to connect nearest vertices. In a more complex system edges are associated between each polygon and connections are based on edge information.&#xD;&#xA;&#xD;&#xA;Normally there is one main &quot;trunk&quot; for the turtle to follow, each branch is reinterpreted as a new turtle with a new seed polygon. Branch's can be integrated into the main structure by clipping each branch against the triangles of the main trunk. Some systems will allow branch's to intersect, others will do collision checking.&#xD;&#xA;&#xD;&#xA;Leaves can be single symbols represented as a single polygon, or an entire L system with its own turtles which is slow to generate but the results are stunning. Yet another approach is to generate a handful of leaves and the L system associates a symbol with each leaf.&#xD;&#xA;&#xD;&#xA;Done correctly this results in a well defined structure. The root node can be closed off to make the polyhedron water tight." ContentLicense="CC BY-SA 4.0" />
  <row Id="39873" PostHistoryTypeId="5" PostId="13297" RevisionGUID="002b0df6-3dd2-48f3-ad60-07cec5fcf6b9" CreationDate="2023-02-13T13:52:50.957" UserId="7952" Comment="added 159 characters in body" Text="A popular method of generating the mesh from an L system is called a &quot;Turtle Graphics&quot; system.&#xD;&#xA;&#xD;&#xA;In a turtle graphics system we imagine a turtle which starts at the root of the system reads a symbol from the L system and walks in a specific direction based on the symbol. The symbol itself is associated with a polygon and the entire system is seeded with a polygon from the root symbol.&#xD;&#xA;&#xD;&#xA;The polygons themselves can be generated algorithmically by the system and then modified for each generation of the plant or predefined such as a simple N sided circle. &#xD;&#xA;&#xD;&#xA;As the turtle marches through the L system each symbol gives it instructions on direction and how many steps to take. For example, a turtle may be instructed to move 3 steps in the up direction.&#xD;&#xA;&#xD;&#xA;The turtle starts at the seeded polygon, reads the symbol, takes a step and places the polygon for that symbol. Then the two polygon's are connected. A simple and effective way to do this is to connect nearest vertices. In a more complex system edges are associated between each polygon and connections are based on edge information.&#xD;&#xA;&#xD;&#xA;Also there can be special transition symbols that transition between two polygon's in N number of steps. (Generally L systems can be very rich and diverse)&#xD;&#xA;&#xD;&#xA;Normally there is one main &quot;trunk&quot; for the turtle to follow, each branch is reinterpreted as a new turtle with a new seed polygon. Branch's can be integrated into the main structure by clipping each branch against the triangles of the main trunk. Some systems will allow branch's to intersect, others will do collision checking.&#xD;&#xA;&#xD;&#xA;Leaves can be single symbols represented as a single polygon, or an entire L system with its own turtles which is slow to generate but the results are stunning. Yet another approach is to generate a handful of leaves and the L system associates a symbol with each leaf.&#xD;&#xA;&#xD;&#xA;Done correctly this results in a well defined structure. The root node can be closed off to make the polyhedron water tight." ContentLicense="CC BY-SA 4.0" />
  <row Id="39874" PostHistoryTypeId="5" PostId="13297" RevisionGUID="b9cc7a08-3eef-4df7-991b-3818ea40d1d4" CreationDate="2023-02-13T13:59:42.937" UserId="7952" Comment="added 160 characters in body" Text="A popular method of generating the mesh from an L system is called a &quot;Turtle Graphics&quot; system.&#xD;&#xA;&#xD;&#xA;In a turtle graphics system we imagine a turtle which starts at the root of the system reads a symbol from the L system and walks in a specific direction based on the symbol. The symbol itself is associated with a polygon and the entire system is seeded with a polygon from the root symbol.&#xD;&#xA;&#xD;&#xA;The polygons themselves can be generated algorithmically by the system and then modified for each generation of the plant or predefined such as a simple N sided circle. &#xD;&#xA;&#xD;&#xA;As the turtle marches through the L system each symbol gives it instructions on direction and how many steps to take. For example, a turtle may be instructed to move 3 steps in the up direction.&#xD;&#xA;&#xD;&#xA;The turtle starts at the seeded polygon, reads the symbol, takes a step and places the polygon for that symbol. Then the two polygon's are connected. A simple and effective way to do this is to connect nearest vertices. In a more complex system edges are associated between each polygon and connections are based on edge information.&#xD;&#xA;&#xD;&#xA;Also there can be special transition symbols that transition between two polygon's in N number of steps. This can be used in places such as the root to give a big old oak tree the look of having a large root system and at branch intersections to help with transitions.&#xD;&#xA;&#xD;&#xA;Normally there is one main &quot;trunk&quot; for the turtle to follow, each branch is reinterpreted as a new turtle with a new seed polygon. Branch's can be integrated into the main structure by clipping each branch against the triangles of the main trunk. Some systems will allow branch's to intersect, others will do collision checking. Here again the can be special symbols that define the transition between the main structure and a branch, this allows for smooth transitions of UV coordinates.&#xD;&#xA;&#xD;&#xA;Leaves can be single symbols represented as a single polygon, or an entire L system with its own turtles which is slow to generate but the results are stunning. Yet another approach is to generate a handful of leaves and the L system associates a symbol with each leaf.&#xD;&#xA;&#xD;&#xA;Done correctly this results in a well defined structure. The root node can be closed off to make the polyhedron water tight." ContentLicense="CC BY-SA 4.0" />
  <row Id="39875" PostHistoryTypeId="50" PostId="8935" RevisionGUID="dbbd515c-5351-41a6-9fc0-6ec04d0426ea" CreationDate="2023-02-14T02:04:30.497" UserId="-1" />
  <row Id="39876" PostHistoryTypeId="5" PostId="13250" RevisionGUID="698304fa-992d-4bb5-b45d-5f8f6b6c133b" CreationDate="2023-02-14T05:38:13.067" UserId="16241" Comment="Add title to bare hyperlink" Text="Rendering equation's value can be estimated with Monte Carlo ([Physically Based Rendering: Light Transport I: Surface Reflection][1]):&#xD;&#xA;&#xD;&#xA;$\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;L_o(p, \omega_o) &amp;= \int_{S^2}f(p, \omega_o, \omega_i) L_i(p, \omega_i) |\cos\theta_i| \mathrm{d}\omega_i\\&#xD;&#xA; &amp; = \frac{1}{N} \sum_{j=1}^{N} \frac{f(p, \omega_o, \omega_i) L_i(p, \omega_j) |\cos\theta_j|}{p(\omega_j)}&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}$&#xD;&#xA;&#xD;&#xA;So if the hit surface is a mirror and $\omega_j$ is the correct direction (only 1 sample is needed and $p(\omega_j)=1$) then this equation becomes:&#xD;&#xA;&#xD;&#xA;$\begin{equation}&#xD;&#xA;\begin{split}&#xD;&#xA;L_o(p, \omega_o) &amp; = f(p, \omega_o, \omega_i) L_i(p, \omega_j) |\cos\theta_j|&#xD;&#xA;\end{split}&#xD;&#xA;\end{equation}$&#xD;&#xA;&#xD;&#xA;For a ideal mirror that reflect without any energe loss, $f(p, \omega_o, \omega_i)$ is 1.&#xD;&#xA;&#xD;&#xA;Yet I couldn't find term $\cos\theta_j$ when reading code from Ray Tracing Weekend and smallpt.&#xD;&#xA;&#xD;&#xA;In Ray Tracing Weekend, the [ray tracing function](https://github.com/RayTracing/raytracing.github.io/blob/master/src/TheRestOfYourLife/main.cc#L25) is written as&#xD;&#xA;```cpp&#xD;&#xA;color ray_color(&#xD;&#xA;    const ray&amp; r,&#xD;&#xA;    const color&amp; background,&#xD;&#xA;    const hittable&amp; world,&#xD;&#xA;    shared_ptr&lt;hittable&gt; lights,&#xD;&#xA;    int depth&#xD;&#xA;) {&#xD;&#xA;    hit_record rec;&#xD;&#xA;&#xD;&#xA;    // If we've exceeded the ray bounce limit, no more light is gathered.&#xD;&#xA;    if (depth &lt;= 0)&#xD;&#xA;        return color(0,0,0);&#xD;&#xA;&#xD;&#xA;    // If the ray hits nothing, return the background color.&#xD;&#xA;    if (!world.hit(r, 0.001, infinity, rec))&#xD;&#xA;        return background;&#xD;&#xA;&#xD;&#xA;    scatter_record srec;&#xD;&#xA;    color emitted = rec.mat_ptr-&gt;emitted(r, rec, rec.u, rec.v, rec.p);&#xD;&#xA;&#xD;&#xA;    if (!rec.mat_ptr-&gt;scatter(r, rec, srec))&#xD;&#xA;        return emitted;&#xD;&#xA;&#xD;&#xA;    if (srec.is_specular) {&#xD;&#xA;        return srec.attenuation&#xD;&#xA;             * ray_color(srec.specular_ray, background, world, lights, depth-1);&#xD;&#xA;    }&#xD;&#xA;    ...&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The last part&#xD;&#xA;```&#xD;&#xA;    if (srec.is_specular) {&#xD;&#xA;        return srec.attenuation&#xD;&#xA;             * ray_color(srec.specular_ray, background, world, lights, depth-1);&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;implies that when hitting a specular object, the result (color) got attenuated by `srec.attenuation` but the cosine term is gone.&#xD;&#xA;&#xD;&#xA;Similarly, neither [smallpt](https://www.kevinbeason.com/smallpt/) (line 61, 62) include cosine term when handling scatterring for specular object:&#xD;&#xA;```&#xD;&#xA;else if (obj.refl == SPEC)            // Ideal SPECULAR reflection &#xD;&#xA;    return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi));&#xD;&#xA;```&#xD;&#xA;it shoots a ray to a new direction without having $\cos(\theta)$ after reflection.&#xD;&#xA;&#xD;&#xA;So, how does $\cos(\theta)$ got cancelled for both renderer? Or did I misunderstand the equation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection" ContentLicense="CC BY-SA 4.0" />
  <row Id="39877" PostHistoryTypeId="24" PostId="13250" RevisionGUID="698304fa-992d-4bb5-b45d-5f8f6b6c133b" CreationDate="2023-02-14T05:38:13.067" Comment="Proposed by 16241 approved by 13095 edit id of 617" ContentLicense="CC BY-SA 4.0" />
  <row Id="39879" PostHistoryTypeId="34" PostId="13098" RevisionGUID="a6ff0b55-6912-47f4-9b14-169a6e8d0350" CreationDate="2023-02-14T15:00:25.097" UserId="-1" Comment="82" />
  <row Id="39881" PostHistoryTypeId="5" PostId="13288" RevisionGUID="0c53dfbf-c98e-43a0-adff-85e3612c0b13" CreationDate="2023-02-15T01:52:00.410" UserId="7952" Comment="Complete rewrite" Text="I took some time and got the square specular from the example posted to work. I was able to split, rotate and square it. It looks like using max instead of min is the key. The results are fairly unstable, they work for key frame animations I'm sure but they move a lot.&#xD;&#xA;&#xD;&#xA;I also took some time to work with the step version of square. It actually is more of a cut off function that produces a perfectly round specular highlight like a spot. Setting the cut off in the step to 0.99 gave a very nice spot.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Finally I worked on yet another version of the square spec highlight. This one actually generates a perfectly square highlight using a box filter(again using the step function). It contains the actual highlight inside a box, so if parameterized it could generate a wide range of effects. It could also be rotated. ( I won't be coding that up) I also include the step version that creates the perfect spot. A similar technique could be used on the square version to get a perfect square for the highlight.&#xD;&#xA;&#xD;&#xA;Here is the code: This code has been tested and works. I even created a shader toy to show it but have decided to keep it private mostly because the code is a conglomeration of several small tests.&#xD;&#xA;&#xD;&#xA;    float boxFilter(float x, float size) {&#xD;&#xA;      return step(size, x) - step(2.0 * size, x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float squareSpecular(vec3 halfVec, vec3 surfaceNormal)&#xD;&#xA;    { &#xD;&#xA;       float angle = dot(halfVec, surfaceNormal);&#xD;&#xA;       angle = clamp(angle, 0.0, 1.0);&#xD;&#xA;       float specular = pow(angle, 50.);&#xD;&#xA;       //return step(0.99, angle) * specular; // return a &quot;spot&quot;&#xD;&#xA;       float specSize = 0.3; // Size of the square highlight&#xD;&#xA;       float specSquare = boxFilter(halfVec.x, specSize) * boxFilter(halfVec.y, specSize);&#xD;&#xA;&#xD;&#xA;       return specular * specSquare;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I included stretching, splitting and translating. ddu and ddv must be recomputed using the new halfway vector to combine the effects.&#xD;&#xA;&#xD;&#xA;Here is the code for the versions from the paper:&#xD;&#xA;&#xD;&#xA;    float sgn(float x )&#xD;&#xA;    {&#xD;&#xA;      if( x== 0.0 ) return 1.0; &#xD;&#xA;      return x/abs(x);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float Specular( vec3 n, vec3 h )&#xD;&#xA;    {&#xD;&#xA;       const float shininess = 20.0;&#xD;&#xA;       vec3 du = cross(n, vec3(0,0,1));&#xD;&#xA;       vec3 dv = cross(du, n);&#xD;&#xA;&#xD;&#xA;       float ddu = dot(h, du);&#xD;&#xA;       float ddv = dot(h, dv);&#xD;&#xA;   &#xD;&#xA;       //vec3 hprimed = h + 0.5*dv + 0.5*du; // translation&#xD;&#xA;       //vec3 hprimed = h - (0.95*ddu * du); // stretching / lengthing&#xD;&#xA;       // vec3 hprimed = h - (0.7 * sgn(ddu) * du) - (0.0 *sgn(ddv)*dv); // splitting&#xD;&#xA;  &#xD;&#xA;       float sigma = 0.7;&#xD;&#xA;       float theta = max( acos(ddu), acos(ddv));&#xD;&#xA;       float sqrnorm = pow( sin(2.0*theta), 14.);&#xD;&#xA;       vec3 hprimed = h - sigma * sqrnorm * (ddu*du + ddv*dv);&#xD;&#xA;&#xD;&#xA;       return pow( clamp( dot( n, normalize(hprimed) ), 0.0, 1.0 ),shininess);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Many other shapes are possible...stars, ragged, filtered, the list goes on and on.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39882" PostHistoryTypeId="2" PostId="13298" RevisionGUID="b1966da3-544c-4407-a3ce-3192fd24b61d" CreationDate="2023-02-15T09:47:21.820" UserId="19580" Text="I am reading [NVIDIA's Get3D paper][1] in which they train a ML model to generate 3D models. They mention in &quot;Related Work&quot;:&#xD;&#xA;&#xD;&#xA;&gt; Early approaches aimed to directly extend the 2D [Convolutional Neural Network] generators to 3D voxel grids, **but the high memory footprint and computational complexity of 3D convolutions** hinder the generation process at high resolution&#xD;&#xA;&#xD;&#xA;But then they use a Convolutional Neural Network to create a Signed Distance Field, which is also a 3D grid. So they are still doing 3D convolutions.&#xD;&#xA;&#xD;&#xA;Why are the 3D convolutions for voxel grids so much more expensive, than for SDF? Does this only have to do with the amount of points in the grid?&#xD;&#xA;&#xD;&#xA;  [1]: https://nv-tlabs.github.io/GET3D/assets/paper.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="39884" PostHistoryTypeId="1" PostId="13298" RevisionGUID="b1966da3-544c-4407-a3ce-3192fd24b61d" CreationDate="2023-02-15T09:47:21.820" UserId="19580" Text="Memory footprint for 3D convolutions on signed distance fields vs. voxel grids" ContentLicense="CC BY-SA 4.0" />
  <row Id="39885" PostHistoryTypeId="3" PostId="13298" RevisionGUID="b1966da3-544c-4407-a3ce-3192fd24b61d" CreationDate="2023-02-15T09:47:21.820" UserId="19580" Text="|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39886" PostHistoryTypeId="2" PostId="13299" RevisionGUID="8c899ebf-3779-40bb-9aa7-8fd2fc7a05eb" CreationDate="2023-02-15T18:48:03.173" UserId="10932" Text="I understand backwards path tracing and bidirectional path tracing (BDPT).  However I'm failing to understand how Metrpolis Light Transport methods are even remotely feasible to run.&#xD;&#xA;&#xD;&#xA;My understanding is that MLT methods start with BDPT to generate an initial set of light paths.  Then it &quot;mutates&quot; these paths to explore the light paths nearby so that it can better converge in situations with difficult lighting.  This leaves me with two questions:&#xD;&#xA;&#xD;&#xA;1. Is that mutation process simply perturbing a given ray?  That is to say, if I have a light path `C -&gt; p1 -&gt; p2 -&gt; L` (where `C` is the Camera, `L` is the light, and `pi` is some intersection point), that I slightly perturb the ray `p1 -&gt; p2` and trace it so that I get some new `p2_mutated`, thus creating a new chain: `C -&gt; p1 -&gt; p2_mutated -&gt; L`?  Or is the mutation scheme somehow actually manipulating the intersection point directly?&#xD;&#xA;&#xD;&#xA;2. It would seem to me that you would needd to do this broard search and mutation scheme for every single primary ray.  But that would be totally computationally infeasible.  Is there some kind of assumption that the search for light paths with high contributions is done for only a subset of the primary rays, and then those light paths are &quot;applied&quot; to subsequent primary rays allowing you to skip the searching step for some rays?&#xD;&#xA;&#xD;&#xA;I'm having a difficult time understanding the papers but I feel like if someone could explain in plane english what is happening, I might be able to make more sense of it." ContentLicense="CC BY-SA 4.0" />
  <row Id="39888" PostHistoryTypeId="1" PostId="13299" RevisionGUID="8c899ebf-3779-40bb-9aa7-8fd2fc7a05eb" CreationDate="2023-02-15T18:48:03.173" UserId="10932" Text="Can anyone summarize in simple terms, how PSSMLT/MLT algorithms work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39889" PostHistoryTypeId="3" PostId="13299" RevisionGUID="8c899ebf-3779-40bb-9aa7-8fd2fc7a05eb" CreationDate="2023-02-15T18:48:03.173" UserId="10932" Text="|rendering|pathtracing|lighting|global-illumination|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39890" PostHistoryTypeId="2" PostId="13300" RevisionGUID="6835385d-fcbe-4589-9e0e-b0631f895ce1" CreationDate="2023-02-16T10:50:31.660" UserId="7462" Text="Let us say we have 2 boundaries of 2 meshes that are roughly aligned, for example 2 generalized cylinders (sweeping surfaces) with a small gap in between. And let us say we want to connect them to each other.&#xD;&#xA;&#xD;&#xA;The 2 don't necessarily have the same number of points. Is there an algorithm to find a triangulation of the space between the 2 boundaries?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Somtehing like this image, where we find connections between the boundaries such that the resulting graph forms a well behaved watertight manifold connecting the 2.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/AozCc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39892" PostHistoryTypeId="1" PostId="13300" RevisionGUID="6835385d-fcbe-4589-9e0e-b0631f895ce1" CreationDate="2023-02-16T10:50:31.660" UserId="7462" Text="Stitching 2 boundaries together" ContentLicense="CC BY-SA 4.0" />
  <row Id="39893" PostHistoryTypeId="3" PostId="13300" RevisionGUID="6835385d-fcbe-4589-9e0e-b0631f895ce1" CreationDate="2023-02-16T10:50:31.660" UserId="7462" Text="|computational-geometry|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39895" PostHistoryTypeId="2" PostId="13301" RevisionGUID="e9685b2a-cb11-4834-8c3d-c978475484f3" CreationDate="2023-02-17T09:23:52.490" UserId="16224" Text="&gt; For a ideal mirror that reflect without any energe loss,&#xD;&#xA;&gt; $f(p,ω_o,ω_i)$  is 1.&#xD;&#xA;&#xD;&#xA;I see your point, but unfortunately this is not true. If your material is an ideal mirror, your BRDF is proportionnal to a Dirac distribution, meaning that its integral is one, but all the reflectivity is contained in one single direction, that you note $\omega_j$.&#xD;&#xA;&#xD;&#xA;Therefore $f(p, \omega_i, \omega_o) \propto \delta(\omega_o - \omega_j)$. You should notice that I didn't put an equal sign, this is because we want to be sure that your BRDF resends exactly the same amount of energy that it receives. We should check if it is the case:&#xD;&#xA;&#xD;&#xA;$$\int_{S^2} L_i(p,\omega_i) \ \delta(\omega_o-\omega_j) \ |\cos (\theta_o) | \ \text{d}\omega_o = L_i(p,\omega_i) \ |\cos (\theta_j)|$$&#xD;&#xA;By definition of a Dirac distribution. Therefore you should add in your BRDF a cosine value at the denominator to be sure to obtain $L_i(\omega_i)$ value as an output:&#xD;&#xA;&#xD;&#xA;$$f(p,\omega_o, \omega_i) = \frac{\delta(\omega_o-\omega_j)}{|cos(\theta_j)|}$$&#xD;&#xA;&#xD;&#xA;Computing numerically Dirac distributions is complicated, it is better to simplify the rendering equation, that now simply gives:&#xD;&#xA;&#xD;&#xA;$$\int_{S^2} L_i(p,\omega_i) \ \frac{\delta(\omega_o-\omega_j)}{|cos(\theta_j)|} \ |\cos (\theta_o) | \ \text{d}\omega_o = L_i(p,\omega_i)$$&#xD;&#xA;&#xD;&#xA;Your cosine is not gone, it just vanishes with another one at the denominator." ContentLicense="CC BY-SA 4.0" />
  <row Id="39897" PostHistoryTypeId="2" PostId="13302" RevisionGUID="eeb88ec6-2111-4d2b-8a23-d0ad5d00b379" CreationDate="2023-02-17T15:26:08.077" UserId="19593" Text="For the old approach, generating a texture for the ImageTexture for compute shaders would look like this:&#xD;&#xA;&#xD;&#xA;    glGenTextures(1, &amp;m_texture);&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, m_texture);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_FLOAT, nullptr);&#xD;&#xA;&#xD;&#xA;However, in DSA, glTexImage2D is no longer a thing and we need to use `glTextureStorage2D` and `glTextureSubImage2D` to replace it.&#xD;&#xA;Yet, the new DSA functions don't work with ImageTextures, when I try to create texture for the ImageTextures, the texture returns black. Here is the code:&#xD;&#xA;&#xD;&#xA;    glCreateTextures(GL_TEXTURE_2D, 1, &amp;m_texture);&#xD;&#xA;    glTextureStorage2D(m_texture, 0, m_internalFormat, (GLsizei)width, (GLsizei)height);&#xD;&#xA;&#xD;&#xA;    glTextureParameteri(m_texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);&#xD;&#xA;    glTextureParameteri(m_texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);&#xD;&#xA;&#xD;&#xA;    glTextureParameteri(m_texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);&#xD;&#xA;    glTextureParameteri(m_texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);&#xD;&#xA;    glTextureSubImage2D(m_texture, 0, 0, 0, (GLsizei)width, (GLsizei)height, m_dataFormat, GL_UNSIGNED_BYTE, nullptr);&#xD;&#xA;&#xD;&#xA;I've read about that the new DSA functions are immutable textures and maybe that causes this problem? If that is the case, what is the DSA counterpart for creating mutable textures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39899" PostHistoryTypeId="1" PostId="13302" RevisionGUID="eeb88ec6-2111-4d2b-8a23-d0ad5d00b379" CreationDate="2023-02-17T15:26:08.077" UserId="19593" Text="How to properly create textures using DSA for ImageTexture in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="39900" PostHistoryTypeId="3" PostId="13302" RevisionGUID="eeb88ec6-2111-4d2b-8a23-d0ad5d00b379" CreationDate="2023-02-17T15:26:08.077" UserId="19593" Text="|opengl|texture|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39901" PostHistoryTypeId="2" PostId="13303" RevisionGUID="fdf2bc82-6c40-4692-bb6a-da3c171ab55c" CreationDate="2023-02-17T17:23:47.537" UserId="8704" Text="I've written a game engine in OpenGL and developed it on my computer with an NVidia GTX 1060. I'm now ready to start releasing it into the wild but I'm worried about hardware issues. I compile my shaders during start-up. I'm wondering if there's any software available that will let me virtually compile my shaders against different hardware. Or am I stuck releasing it, logging out crashes, and asking for user logs?&#xD;&#xA;&#xD;&#xA;Thanks in advance!" ContentLicense="CC BY-SA 4.0" />
  <row Id="39903" PostHistoryTypeId="1" PostId="13303" RevisionGUID="fdf2bc82-6c40-4692-bb6a-da3c171ab55c" CreationDate="2023-02-17T17:23:47.537" UserId="8704" Text="How can I test my GLSL code on different hardware?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39904" PostHistoryTypeId="3" PostId="13303" RevisionGUID="fdf2bc82-6c40-4692-bb6a-da3c171ab55c" CreationDate="2023-02-17T17:23:47.537" UserId="8704" Text="|opengl|glsl|hardware|compatibility|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39905" PostHistoryTypeId="50" PostId="8888" RevisionGUID="7fe7c489-b269-49d0-945e-105d83763239" CreationDate="2023-02-17T19:02:05.300" UserId="-1" />
  <row Id="39908" PostHistoryTypeId="2" PostId="13304" RevisionGUID="dfc217ab-5342-4c24-959e-2827c482776d" CreationDate="2023-02-18T05:58:03.737" UserId="19537" Text="I am guessing I had an misunderstanding here. Just as @lightxbulb said, cos term and distance attenuation do not come from $L_e$, yet I haven't quite understand why until recent days when I come to notice **the measure of an integral** and what exactly I am evaluating during $L_e$ evaluation. &#xD;&#xA;&#xD;&#xA;From [PBR-book: 14.4.3 The Surface Form of the LTE](https://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/The_Light_Transport_Equation#TheSurfaceFormoftheLTE), I understand the difference of $dA$ and $dw$, and how geometry term plays an important part in converting one measure to the other. Since $L_e$ evaluation has nothing to do with integration (the ray directly intersects the emitter), $L_e$ evaluation function returns **radiance** directly, which is related to the direction of the ray and requires no measure conversion. Also, since there is no participating medium, radiance from one point to another should remain the same all the way.&#xD;&#xA;&#xD;&#xA;I guess the main misunderstanding is that, I perceived emission evaluation as some kind of *illuminating by sampling the area emitter* problem, which is not the same. &#xD;&#xA;&#xD;&#xA;Guessing laying a solid foundation does help a lot." ContentLicense="CC BY-SA 4.0" />
  <row Id="39910" PostHistoryTypeId="2" PostId="13305" RevisionGUID="20d25994-bc71-4efb-8c96-3580e4b814e6" CreationDate="2023-02-19T14:12:37.573" UserId="7952" Text="I highly recommend getting at least 1 card from one of the other vendors like AMD. It doesn't have to be fancy, the cheapest thing you can get off ebay will help. Just make sure it supports the same version of OpenGL that game system uses. Software rendering will not exercise your code on other hardware *drivers*.  But if you get your code working on *any* other hardware it will at least give the code a fighting chance. If that isn't possible find folks that are willing to help you. There are people out there that are willing to test as long as they get free software. Also, make it as easy as possible to send errors. Such as shipping with an extra bit of code that will automate the sending of the logs. Whatever you don't just send the logs! Bring up a dialog that says there was an error, say that you want to send the logs and ask if that's okay. Also make a way for them to complain. For the bugs that your code doesn't detect. You can send errors to an email. That will help avoid malicious users. So long as the number is relatively small, which it should be for a version 0 test. " ContentLicense="CC BY-SA 4.0" />
  <row Id="39912" PostHistoryTypeId="50" PostId="12467" RevisionGUID="313b53d8-bac1-4473-8bd5-41b633acb79f" CreationDate="2023-02-19T15:05:55.670" UserId="-1" />
  <row Id="39921" PostHistoryTypeId="2" PostId="13308" RevisionGUID="b3ae4bde-c277-40ec-96ef-41be676f44d5" CreationDate="2023-02-20T10:03:56.843" UserId="19604" Text="I have the following code below, and it generates the following render. I am using a texture test image, and it looks like its just taking the bottom row of pixels of that image and repeating then. It looks like its correctly applied to the edge it starts on, at least. Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Create a sampler object&#xD;&#xA;        let samplerDescriptor = MTLSamplerDescriptor()&#xD;&#xA;        samplerDescriptor.minFilter = .linear&#xD;&#xA;        samplerDescriptor.magFilter = .linear&#xD;&#xA;        samplerDescriptor.mipFilter = .linear&#xD;&#xA;        samplerDescriptor.sAddressMode = .clampToEdge&#xD;&#xA;        samplerDescriptor.tAddressMode = .clampToEdge&#xD;&#xA;        textureSamplerState = device.makeSamplerState(descriptor: samplerDescriptor)!&#xD;&#xA;&#xD;&#xA;        // TEXTURES&#xD;&#xA;        let textureLoader = MTKTextureLoader(device: device)&#xD;&#xA;        try! textures.append(textureLoader.newTexture(name: &quot;test&quot;, scaleFactor: 1.0, bundle: nil, options: nil))&#xD;&#xA;        &#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zzof0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39923" PostHistoryTypeId="1" PostId="13308" RevisionGUID="b3ae4bde-c277-40ec-96ef-41be676f44d5" CreationDate="2023-02-20T10:03:56.843" UserId="19604" Text="Why is my texture stretched from 1 row of pixels? Metal/Swift" ContentLicense="CC BY-SA 4.0" />
  <row Id="39924" PostHistoryTypeId="3" PostId="13308" RevisionGUID="b3ae4bde-c277-40ec-96ef-41be676f44d5" CreationDate="2023-02-20T10:03:56.843" UserId="19604" Text="|texture|uv-mapping|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39925" PostHistoryTypeId="5" PostId="13308" RevisionGUID="7131b307-2b06-48bb-8e27-2a0f8af1e9aa" CreationDate="2023-02-20T10:10:23.353" UserId="19604" Comment="added 534 characters in body" Text="I have the following code below, and it generates the following render. I am using a texture test image, and it looks like its just taking the bottom row of pixels of that image and repeating then. It looks like its correctly applied to the edge it starts on, at least. Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Create a sampler object&#xD;&#xA;        let samplerDescriptor = MTLSamplerDescriptor()&#xD;&#xA;        samplerDescriptor.minFilter = .linear&#xD;&#xA;        samplerDescriptor.magFilter = .linear&#xD;&#xA;        samplerDescriptor.mipFilter = .linear&#xD;&#xA;        samplerDescriptor.sAddressMode = .clampToEdge&#xD;&#xA;        samplerDescriptor.tAddressMode = .clampToEdge&#xD;&#xA;        textureSamplerState = device.makeSamplerState(descriptor: samplerDescriptor)!&#xD;&#xA;&#xD;&#xA;        // TEXTURES&#xD;&#xA;        let textureLoader = MTKTextureLoader(device: device)&#xD;&#xA;        try! textures.append(textureLoader.newTexture(name: &quot;test&quot;, scaleFactor: 1.0, bundle: nil, options: nil))&#xD;&#xA;        &#xD;&#xA;My shader is:&#xD;&#xA;&#xD;&#xA;    fragment float4 fragmentShader(VertexOut vertexOut [[stage_in]],&#xD;&#xA;	                               metal::texture2d&lt;float&gt; texture [[texture(0)]],&#xD;&#xA;	                               metal::sampler textureSampler [[sampler(0)]])&#xD;&#xA;	{&#xD;&#xA;	    float4 color = vertexOut.color;&#xD;&#xA;	//    return color;&#xD;&#xA;	    float2 textureCoordinate = vertexOut.texCoord;&#xD;&#xA;	    float4 texel = texture.sample(textureSampler, textureCoordinate );&#xD;&#xA;	    float4 outputColor;&#xD;&#xA;	    outputColor.xyz = color.xyz * texel.xyz;&#xD;&#xA;	    outputColor.w = texel.w;&#xD;&#xA;	&#xD;&#xA;	    return outputColor;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zzof0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39926" PostHistoryTypeId="5" PostId="13308" RevisionGUID="8cf78cae-e104-4366-a0c6-ba8d7931a78c" CreationDate="2023-02-20T10:46:19.327" UserId="19604" Comment="deleted 229 characters in body" Text="I have the following code below, and it generates the following render. I am using a texture test image, and it looks like its just taking the bottom row of pixels of that image and repeating then. It looks like its correctly applied to the edge it starts on, at least. Any ideas?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;            // Create a sampler object&#xD;&#xA;        let samplerDescriptor = MTLSamplerDescriptor()&#xD;&#xA;        samplerDescriptor.minFilter = .linear&#xD;&#xA;        samplerDescriptor.magFilter = .linear&#xD;&#xA;        samplerDescriptor.mipFilter = .linear&#xD;&#xA;        samplerDescriptor.sAddressMode = .clampToEdge&#xD;&#xA;        samplerDescriptor.tAddressMode = .clampToEdge&#xD;&#xA;        textureSamplerState = device.makeSamplerState(descriptor: samplerDescriptor)!&#xD;&#xA;&#xD;&#xA;        // TEXTURES&#xD;&#xA;        let textureLoader = MTKTextureLoader(device: device)&#xD;&#xA;        try! textures.append(textureLoader.newTexture(name: &quot;test&quot;, scaleFactor: 1.0, bundle: nil, options: nil))&#xD;&#xA;        &#xD;&#xA;My shader is:&#xD;&#xA;&#xD;&#xA;    fragment float4 fragmentShader(VertexOut vertexOut [[stage_in]],&#xD;&#xA;	                               metal::texture2d&lt;float&gt; texture [[texture(0)]],&#xD;&#xA;	                               metal::sampler textureSampler [[sampler(0)]])&#xD;&#xA;	{&#xD;&#xA;	    float4 color = texture.sample(textureSampler, vertexOut.texCoord);&#xD;&#xA;		return color;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zzof0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="39927" PostHistoryTypeId="2" PostId="13309" RevisionGUID="8c0a1ad7-ae46-4157-8a2c-e2f01826f976" CreationDate="2023-02-20T10:56:00.243" UserId="19605" Text="I am trying to create a custom math library for a renderer. The renderer works when using glm but for educational purposes as well as for the sake of having a custom library to support multiple backends, I am creating my own. Currently focusing on Vulkan. I have written a matrix class. Switching to my own library renders a black screen. Vectors are intuitive for me but trying to understand 4x4 Matrices leaves my brain feeling like mush. From cross examining my code from text books and some open source projects, I don't see what could be wrong.&#xD;&#xA;&#xD;&#xA;Is there anything wrong with my calculations? Matrices are in Column major order.&#xD;&#xA;Could it possibly be an issue with alignment? I've tried changing the winding order. It's currently Counter Clockwise. Looking for any pointers in the correct direction.&#xD;&#xA;&#xD;&#xA;A condensed version of my Mat4 class is as follows~&#xD;&#xA;&#xD;&#xA;    class Mat4&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;&#xD;&#xA;        union{&#xD;&#xA;            // f32 is a custom float32 typedef&#xD;&#xA;            f32 mat[16];&#xD;&#xA;&#xD;&#xA;            struct &#xD;&#xA;            {&#xD;&#xA;                Vec4 right;&#xD;&#xA;                Vec4 up;&#xD;&#xA;                Vec4 forward;&#xD;&#xA;                Vec4 position;&#xD;&#xA;            };&#xD;&#xA;&#xD;&#xA;            struct&#xD;&#xA;            {&#xD;&#xA;                f32 xx, xy, xz, xw;&#xD;&#xA;                f32 yx, yy, yz, yw;&#xD;&#xA;                f32 zx, zy, zz, zw;&#xD;&#xA;                f32 tx, ty, tz, tw;&#xD;&#xA;            };&#xD;&#xA;            &#xD;&#xA;            struct&#xD;&#xA;            {&#xD;&#xA;                f32 r0c0, r1c0, r2c0, r3c0;&#xD;&#xA;                f32 r0c1, r1c1, r2c1, r3c1;&#xD;&#xA;                f32 r0c2, r1c2, r2c2, r3c2;&#xD;&#xA;                f32 r0c3, r1c3, r2c3, r3c3;&#xD;&#xA;            };&#xD;&#xA;        };&#xD;&#xA;&#xD;&#xA;        Mat4 LookAtRH(const Vec3&amp; Position, const Vec3&amp; Target, const Vec3&amp; Up)&#xD;&#xA;        {&#xD;&#xA;            Vec3 const front(Vec3::Normalize(Target - Position));&#xD;&#xA;		    Vec3 const right(Vec3::Normalize(Vec3::Cross(front, Up)));&#xD;&#xA;		    Vec3 const up(Vec3::Normalize(Vec3::Cross(right, front)));&#xD;&#xA;&#xD;&#xA;		    Vec3 target(&#xD;&#xA;			    Vec3::Dot(right, Position),&#xD;&#xA;			    Vec3::Dot(up, Position),&#xD;&#xA;			    Vec3::Dot(front, Position)&#xD;&#xA;		    );&#xD;&#xA;&#xD;&#xA;		    return Mat4(&#xD;&#xA;			    right.x, up.x, -front.x, 0.0f,&#xD;&#xA;			    right.y, up.y, -front.y, 0.0f,&#xD;&#xA;			    right.z, up.z, -front.z, 0.0f,&#xD;&#xA;			    -target.x, -target.y, target.z, 1.0f&#xD;&#xA;		    );&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        Mat4 PerspectiveRH(f32 FOV, f32 AspectRatio, f32 Near, f32 Far)&#xD;&#xA;        {&#xD;&#xA;                                    // DegToRad: Degrees * (PI/180.f)&#xD;&#xA;		    f32 half_tan_fov = tanf(Math::DegToRad(FOV) / 2.0f);&#xD;&#xA;&#xD;&#xA;		    Mat4 result;&#xD;&#xA;		    result.mat[0] = 1.0f / (AspectRatio * half_tan_fov);&#xD;&#xA;		    result.mat[5] = 1.0f / half_tan_fov;&#xD;&#xA;		    result.mat[10] = - (Far + Near) / (Far - Near);&#xD;&#xA;		    result.mat[11] = - 1.0f;&#xD;&#xA;		    result.mat[14] = -(2.0f * Far * Near) / (Far - Near);&#xD;&#xA;		    return result;&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39929" PostHistoryTypeId="1" PostId="13309" RevisionGUID="8c0a1ad7-ae46-4157-8a2c-e2f01826f976" CreationDate="2023-02-20T10:56:00.243" UserId="19605" Text="Custom LookAt and Perspective Matrix functions not rendering in Vulkan" ContentLicense="CC BY-SA 4.0" />
  <row Id="39930" PostHistoryTypeId="3" PostId="13309" RevisionGUID="8c0a1ad7-ae46-4157-8a2c-e2f01826f976" CreationDate="2023-02-20T10:56:00.243" UserId="19605" Text="|vulkan|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39931" PostHistoryTypeId="2" PostId="13310" RevisionGUID="c287c8cf-683d-4c20-b122-2870b561e02f" CreationDate="2023-02-20T13:00:11.520" UserId="19605" Text="Disregard, The issue was found to be an error in Vec3 overloaded division operator used when calculating Normals in Vec3::Normalize(). I will leave the problem up for anyone who wants to study" ContentLicense="CC BY-SA 4.0" />
  <row Id="39933" PostHistoryTypeId="2" PostId="13311" RevisionGUID="ffba4a5b-05d3-4b1d-887c-959cba96bc3d" CreationDate="2023-02-20T14:24:05.413" UserId="19606" Text="To give a bit of context MLT and PSSMLT fall into the broader family of Markov Chain Monte Carlo (MCMC) methods, so my answer will contain a small bit of Markov chain terminology. I assume you are familiar with it, but if you are not it might explain why you feel like you're struggling to understand papers (if so, see my ending note).&#xD;&#xA;&#xD;&#xA;1. If I rephrase your question, you're asking if more raycasting need to be performed, or if the geometry of the path can be directly modified.&#xD;&#xA;&#xD;&#xA;The theory doesn't put any constraint on it, but in practice it would be difficult to design a mutation strategy that guarantees that the new intersections fall on the surfaces of your scene. At least I'm not aware of any !&#xD;&#xA;&#xD;&#xA;A simplified answer is that to mutate a path, you replace a chosen subpath of the current path and replace it by tracing paths from the remaining paths on both the emitter side and the sensor side, and connect. It is more complex in practice, because you need to ensure that paths are connectable.&#xD;&#xA;&#xD;&#xA;The first version of Mitsuba used to have an [MLT implementation](https://github.com/mitsuba-renderer/mitsuba/blob/master/src/integrators/mlt/mlt_proc.cpp) using [BDPT mutation](https://github.com/mitsuba-renderer/mitsuba/blob/master/src/libbidir/mut_bidir.cpp) to which you can refer, looking for the sampleMutation method. In this, proposal is initialised to the l first vertices of the current path, then the emitter subpath is extended by s events and the sensor subpath by t events, and a connection is made. But this is only one implementation.&#xD;&#xA;&#xD;&#xA;2. Indeed this would be untractable.&#xD;&#xA;&#xD;&#xA;The point of the Metropolis-Hastings algorithms is that you perform a random walk in the space of your possible states (the possible paths, here), so you don't need to cover them all. It is too complex to detail more here, but the Chapter 11 of Eric Veach thesis is what you need. The mutations you use, combined with a given acceptance law, &quot;hard-code&quot; the assumptions you make about what light paths will bring the highest contributions. In a sense, you're encoding how you expect the contribution function to be, to be able to sample it better (i.e. take the most significant paths).&#xD;&#xA;&#xD;&#xA;Common assumptions includes that shorter paths bring more energy, and highly contributing paths are worth exploring by using small mutations while other may be skipped by performing larger mutations.&#xD;&#xA;&#xD;&#xA;In the case of PSSMLT, it is assumed that close points in the primary sample space make close paths in the light path space.&#xD;&#xA;&#xD;&#xA;The thing is, the mutations and acceptance strategies are what make the litterature of MCMC path tracers so populated (and precisely answering your question difficult) ! A good example — I think, although a bit off from original MLT — is MEPT [Jakob &amp; Marschner., 2012](https://www.cs.cornell.edu/projects/manifolds-sg12/), because it illustrates quite visually some assumptions that may drive the design of a mutation strategy. Also it's a much quicker read than Veach's thesis :D, and it completes my answer to your first question. Essentially you want to sample paths that are reflected similarly on a reflective surface ; this is a geometrical constraint, and the paper identifies a &quot;manifold&quot; (quickly, a subset of the path space that matches that constraint) and try to move around on it. Each mutation step has a modification step and a reprojection step, that guarantees the new path is a valid path." ContentLicense="CC BY-SA 4.0" />
  <row Id="39935" PostHistoryTypeId="2" PostId="13312" RevisionGUID="a1b16796-e347-41cb-8634-1c9d6e97f704" CreationDate="2023-02-20T15:48:44.643" UserId="7952" Text="&#xD;&#xA;&#xD;&#xA;The perspective matrix as written is setup for OpenGL here is one setup for vulkan:&#xD;&#xA;&#xD;&#xA;    // Radians is just a small wrapper around a float here&#xD;&#xA;    mat4 Projection( Radians fovy, flt32 s, flt32 near, flt32 far )&#xD;&#xA;    {&#xD;&#xA;       flt32 g = 1.0f / tan(fovy * 0.5f);&#xD;&#xA;       flt32 k = far / (far-near);&#xD;&#xA;    &#xD;&#xA;       return mat4{&#xD;&#xA;           g/s,  0.0f, 0.0f, 0.0f,&#xD;&#xA;           0.0f, g,    0.0f, 0.0f,&#xD;&#xA;           0.0f, 0.0f, k,    -near * k,&#xD;&#xA;           0.0f, 0.0f, 1.0f, 0.0f };&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39941" PostHistoryTypeId="2" PostId="13314" RevisionGUID="57432a81-caa2-42a9-8c93-e67ab0d4a7bc" CreationDate="2023-02-22T16:32:05.307" UserId="19615" Text="The **2nd argument** of glTextureStorage2D() API is **mip-map levels**, if you specify it as **0**, it causes troubles you may have.&#xD;&#xA;&#xD;&#xA;    glTextureStorage2D(m_texture, 0, m_internalFormat, (GLsizei)width, (GLsizei)height);&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39943" PostHistoryTypeId="2" PostId="13315" RevisionGUID="88ae6aaa-abdb-4ef6-886f-4f2f3884add2" CreationDate="2023-02-23T06:32:32.187" UserId="10932" Text="My understanding is that, while subdivision algorithms like Catmull-Clark can work for any polygonal mesh (including triangles) it's preferable to start with a quad mesh.&#xD;&#xA;&#xD;&#xA;Currently my rendering engine represents all meshes as meshes of triangles, but im now looking at adding tesselation/subdivision so I can make better use of displacement maps and what not.&#xD;&#xA;&#xD;&#xA;So my thought process is I'll need to be able to support quads in addition to triangles.  My `Mesh` class represents geometry using vertex and index buffers where the index buffer is an `std::vector&lt;std::array&lt;unit32_t, 3&gt;&gt;`.  This works fine under my current assumption of storing ONLY triangles, but im not sure how I can change things to support both triangle and quad meshes, as well as possibly meshes that contain some quads AND some triangles." ContentLicense="CC BY-SA 4.0" />
  <row Id="39945" PostHistoryTypeId="1" PostId="13315" RevisionGUID="88ae6aaa-abdb-4ef6-886f-4f2f3884add2" CreationDate="2023-02-23T06:32:32.187" UserId="10932" Text="How would you represent a mesh with tris and quads?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39946" PostHistoryTypeId="3" PostId="13315" RevisionGUID="88ae6aaa-abdb-4ef6-886f-4f2f3884add2" CreationDate="2023-02-23T06:32:32.187" UserId="10932" Text="|c++|mesh|polygon|subdivision|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39951" PostHistoryTypeId="2" PostId="13317" RevisionGUID="9cf26b83-2b63-4bd1-aa2c-479a963586db" CreationDate="2023-02-23T11:46:50.183" UserId="19622" Text="I've noticed a lot of confusion in the use of terminology in this field, sometimes also scientific papers or software packages misuse these words, I agree with @gallickgunner explanation. &#xD;&#xA;&#xD;&#xA;To sum up and from my understanding: &#xD;&#xA;-materials have diffuse and specular reflection only.&#xD;&#xA;-in dielectric, you have both (and for physically based workflow they should always sum up to 100%). If you have a certain amount of specular reflection you will have an inversely proportional amount of diffuse reflection and vice versa.&#xD;&#xA;-diffuse reflection is the light that scatters right underneath the surface and is reflected in all directions (diffuse reflection can be imagined as the base colour of the material or albedo), a material that has only the diffuse component looks flat and matte (like a very rough plaster), however, no materials in the world have only diffuse reflections.&#xD;&#xA;-the specular reflection is the light reflected on the surface of the material and can be sharp or blurry&#xD;&#xA;-the amount of blurriness of specular reflection is controlled by the glossiness parameter (or its inverse the roughness parameter)&#xD;&#xA;-for materials like metals the diffuse component is 0% and the specular is 100%, however, for coloured metals like gold or copper, the colour is given to the specular reflections and not to the diffuse reflections&#xD;&#xA;-a material that has 100% specular reflection with 100% glossiness, and 0% diffuse reflections it's a mirror&#xD;&#xA;-a material that has 100% specular reflection with 0% glossiness and 0% diffuse reflections looks like a very rough metal (like a heavily sandblasted silver) however, metals in real life always have some amount of glossiness it's never 0%&#xD;&#xA;-the &quot;specularity&quot; parameter is usually used to &quot;weight&quot; the % of specular reflection&#xD;&#xA;&#xD;&#xA;-the &quot;specular colour&quot; parameter is used to assign the colour to the specular reflections (metals and other strange hybrid materials can have coloured reflections; non-metallic/dielectric materials usually have white specular reflections)&#xD;&#xA;&#xD;&#xA;-the diffuse reflection might not always has a weighting factor as the specular reflections, usually it is controlled by the luminosity of its colour.&#xD;&#xA;&#xD;&#xA;-the &quot;diffuse colour&quot; parameter is the same as the specular colour but assigns a colour to the diffuse reflections rather than the specular ones.&#xD;&#xA;&#xD;&#xA;Additional observations: &#xD;&#xA;-the metalness does not describe a different type of reflection, but it basically makes sure that when increasing the specular reflections, the diffuse reflections are lowered proportionally. (so basically, when you increase specular reflections to 100%, even if there is a colour assigned to the diffuse colour channel you won't see it because it would be weighted down to 0%)&#xD;&#xA;-Do not mistake the diffuse reflection with the subsurface scattering (SSS), the SSS is an effect that scatters the light underneath the surface as the Diffuse, but it can go way farther underneath the surface compared to the diffuse, in theory, if you set the SSS distance to a very low number you could replicate the Diffuse reflection effect, however, it is much heavier to calculate, so when you don't need to go very far beneath the surface you just avoid calculating it and you rely only on the diffuse effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39953" PostHistoryTypeId="5" PostId="13317" RevisionGUID="f652e01d-b938-4ed5-80ba-a526057832b5" CreationDate="2023-02-23T11:47:33.847" UserId="19622" Comment="added 22 characters in body" Text="I've noticed a lot of confusion in the use of terminology in this field, sometimes also scientific papers or software packages misuse these words, I agree with @gallickgunner explanation. &#xD;&#xA;&#xD;&#xA;To sum up and from my understanding: &#xD;&#xA;&#xD;&#xA;-materials have diffuse and specular reflection only.&#xD;&#xA;&#xD;&#xA;-in dielectric, you have both (and for physically based workflow they should always sum up to 100%). If you have a certain amount of specular reflection you will have an inversely proportional amount of diffuse reflection and vice versa.&#xD;&#xA;&#xD;&#xA;-diffuse reflection is the light that scatters right underneath the surface and is reflected in all directions (diffuse reflection can be imagined as the base colour of the material or albedo), a material that has only the diffuse component looks flat and matte (like a very rough plaster), however, no materials in the world have only diffuse reflections.&#xD;&#xA;&#xD;&#xA;-the specular reflection is the light reflected on the surface of the material and can be sharp or blurry&#xD;&#xA;&#xD;&#xA;-the amount of blurriness of specular reflection is controlled by the glossiness parameter (or its inverse the roughness parameter)&#xD;&#xA;&#xD;&#xA;-for materials like metals the diffuse component is 0% and the specular is 100%, however, for coloured metals like gold or copper, the colour is given to the specular reflections and not to the diffuse reflections&#xD;&#xA;&#xD;&#xA;-a material that has 100% specular reflection with 100% glossiness, and 0% diffuse reflections it's a mirror&#xD;&#xA;&#xD;&#xA;-a material that has 100% specular reflection with 0% glossiness and 0% diffuse reflections looks like a very rough metal (like a heavily sandblasted silver) however, metals in real life always have some amount of glossiness it's never 0%&#xD;&#xA;&#xD;&#xA;-the &quot;specularity&quot; parameter is usually used to &quot;weight&quot; the % of specular reflection&#xD;&#xA;&#xD;&#xA;-the &quot;specular colour&quot; parameter is used to assign the colour to the specular reflections (metals and other strange hybrid materials can have coloured reflections; non-metallic/dielectric materials usually have white specular reflections)&#xD;&#xA;&#xD;&#xA;-the diffuse reflection might not always has a weighting factor as the specular reflections, usually it is controlled by the luminosity of its colour.&#xD;&#xA;&#xD;&#xA;-the &quot;diffuse colour&quot; parameter is the same as the specular colour but assigns a colour to the diffuse reflections rather than the specular ones.&#xD;&#xA;&#xD;&#xA;Additional observations: &#xD;&#xA;&#xD;&#xA;-the metalness does not describe a different type of reflection, but it basically makes sure that when increasing the specular reflections, the diffuse reflections are lowered proportionally. (so basically, when you increase specular reflections to 100%, even if there is a colour assigned to the diffuse colour channel you won't see it because it would be weighted down to 0%)&#xD;&#xA;&#xD;&#xA;-Do not mistake the diffuse reflection with the subsurface scattering (SSS), the SSS is an effect that scatters the light underneath the surface as the Diffuse, but it can go way farther underneath the surface compared to the diffuse, in theory, if you set the SSS distance to a very low number you could replicate the Diffuse reflection effect, however, it is much heavier to calculate, so when you don't need to go very far beneath the surface you just avoid calculating it and you rely only on the diffuse effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39954" PostHistoryTypeId="5" PostId="13317" RevisionGUID="e088207c-f890-41aa-88a5-979c3cc39966" CreationDate="2023-02-23T11:48:09.340" UserId="19622" Comment="deleted 4 characters in body" Text="I've noticed a lot of confusion in the use of terminology in this field, sometimes also scientific papers or software packages misuse these words, I agree with @gallickgunner explanation. &#xD;&#xA;&#xD;&#xA;To sum up and from my understanding: &#xD;&#xA;&#xD;&#xA;-materials have diffuse and specular reflection only.&#xD;&#xA;&#xD;&#xA;-in dielectric, you have both (and for physically based workflow they should never exceed 100%). If you have a certain amount of specular reflection you will have an inversely proportional amount of diffuse reflection and vice versa.&#xD;&#xA;&#xD;&#xA;-diffuse reflection is the light that scatters right underneath the surface and is reflected in all directions (diffuse reflection can be imagined as the base colour of the material or albedo), a material that has only the diffuse component looks flat and matte (like a very rough plaster), however, no materials in the world have only diffuse reflections.&#xD;&#xA;&#xD;&#xA;-the specular reflection is the light reflected on the surface of the material and can be sharp or blurry&#xD;&#xA;&#xD;&#xA;-the amount of blurriness of specular reflection is controlled by the glossiness parameter (or its inverse the roughness parameter)&#xD;&#xA;&#xD;&#xA;-for materials like metals the diffuse component is 0% and the specular is 100%, however, for coloured metals like gold or copper, the colour is given to the specular reflections and not to the diffuse reflections&#xD;&#xA;&#xD;&#xA;-a material that has 100% specular reflection with 100% glossiness, and 0% diffuse reflections it's a mirror&#xD;&#xA;&#xD;&#xA;-a material that has 100% specular reflection with 0% glossiness and 0% diffuse reflections looks like a very rough metal (like a heavily sandblasted silver) however, metals in real life always have some amount of glossiness it's never 0%&#xD;&#xA;&#xD;&#xA;-the &quot;specularity&quot; parameter is usually used to &quot;weight&quot; the % of specular reflection&#xD;&#xA;&#xD;&#xA;-the &quot;specular colour&quot; parameter is used to assign the colour to the specular reflections (metals and other strange hybrid materials can have coloured reflections; non-metallic/dielectric materials usually have white specular reflections)&#xD;&#xA;&#xD;&#xA;-the diffuse reflection might not always has a weighting factor as the specular reflections, usually it is controlled by the luminosity of its colour.&#xD;&#xA;&#xD;&#xA;-the &quot;diffuse colour&quot; parameter is the same as the specular colour but assigns a colour to the diffuse reflections rather than the specular ones.&#xD;&#xA;&#xD;&#xA;Additional observations: &#xD;&#xA;&#xD;&#xA;-the metalness does not describe a different type of reflection, but it basically makes sure that when increasing the specular reflections, the diffuse reflections are lowered proportionally. (so basically, when you increase specular reflections to 100%, even if there is a colour assigned to the diffuse colour channel you won't see it because it would be weighted down to 0%)&#xD;&#xA;&#xD;&#xA;-Do not mistake the diffuse reflection with the subsurface scattering (SSS), the SSS is an effect that scatters the light underneath the surface as the Diffuse, but it can go way farther underneath the surface compared to the diffuse, in theory, if you set the SSS distance to a very low number you could replicate the Diffuse reflection effect, however, it is much heavier to calculate, so when you don't need to go very far beneath the surface you just avoid calculating it and you rely only on the diffuse effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39955" PostHistoryTypeId="2" PostId="13318" RevisionGUID="a9fae843-3242-4f88-af85-b0f72e3fd7ca" CreationDate="2023-02-23T13:18:40.317" UserId="19623" Text="at this moment I am learning to do shadow mapping in webgl2.0, i was able to generate my first shadows in my 3D scene but I have a couple of doubts to clarify.&#xD;&#xA;This is the way im calculating my light space matrix:&#xD;&#xA;```&#xD;&#xA;const lightPos = vec3.create();&#xD;&#xA;vec3.set(lightPos, 0, 6, 1);&#xD;&#xA;const nearPlane = 1, farPlane = 20;&#xD;&#xA;const projection = mat4.create();&#xD;&#xA;mat4.ortho(projection, -10, 10, -10, 10, nearPlane, farPlane);&#xD;&#xA;const lightView = mat4.create();&#xD;&#xA;const center = vec3.create();&#xD;&#xA;const up = vec3.create();&#xD;&#xA;vec3.set(center, 0, 0, 0);&#xD;&#xA;vec3.set(up, 0, 1, 0);&#xD;&#xA;mat4.lookAt(lightView, lightPos, center, up);&#xD;&#xA;const result = mat4.create();&#xD;&#xA;mat4.mul(result, projection, lightView);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;In this way the shadow map is rendered correctly, but the question is the following, if the position of my light is vec3.set(lightPos, 0, 6, 0), the shadow does not render, why is this happening? Theoretically I am positioning the light in the middle, directly 6 units above the scene, why is this happening? As far as I understood, 2 of the properties of the position vector of the light cannot be 0, but why?.&#xD;&#xA;I hope I explained myself well, the light is a directional light and the library that im using for the math is gl-matrix, if you need anything else let me know, thanks in advance." ContentLicense="CC BY-SA 4.0" />
  <row Id="39957" PostHistoryTypeId="1" PostId="13318" RevisionGUID="a9fae843-3242-4f88-af85-b0f72e3fd7ca" CreationDate="2023-02-23T13:18:40.317" UserId="19623" Text="Doubt about Light space transform (Shadow map)" ContentLicense="CC BY-SA 4.0" />
  <row Id="39958" PostHistoryTypeId="3" PostId="13318" RevisionGUID="a9fae843-3242-4f88-af85-b0f72e3fd7ca" CreationDate="2023-02-23T13:18:40.317" UserId="19623" Text="|webgl|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39959" PostHistoryTypeId="50" PostId="10619" RevisionGUID="41432470-da29-42cf-9f4d-fce0dfe1c121" CreationDate="2023-02-23T18:00:50.113" UserId="-1" />
  <row Id="39964" PostHistoryTypeId="5" PostId="13317" RevisionGUID="11ebc9df-32d5-4fe7-b4b3-3f9af49498fb" CreationDate="2023-02-24T14:40:48.100" UserId="445" Comment="fix list formatting" Text="I've noticed a lot of confusion in the use of terminology in this field, sometimes also scientific papers or software packages misuse these words, I agree with @gallickgunner explanation. &#xD;&#xA;&#xD;&#xA;To sum up and from my understanding: &#xD;&#xA;&#xD;&#xA;- materials have diffuse and specular reflection only.&#xD;&#xA;&#xD;&#xA;- in dielectric, you have both (and for physically based workflow they should never exceed 100%). If you have a certain amount of specular reflection you will have an inversely proportional amount of diffuse reflection and vice versa.&#xD;&#xA;&#xD;&#xA;- diffuse reflection is the light that scatters right underneath the surface and is reflected in all directions (diffuse reflection can be imagined as the base colour of the material or albedo), a material that has only the diffuse component looks flat and matte (like a very rough plaster), however, no materials in the world have only diffuse reflections.&#xD;&#xA;&#xD;&#xA;- the specular reflection is the light reflected on the surface of the material and can be sharp or blurry&#xD;&#xA;&#xD;&#xA;- the amount of blurriness of specular reflection is controlled by the glossiness parameter (or its inverse the roughness parameter)&#xD;&#xA;&#xD;&#xA;- for materials like metals the diffuse component is 0% and the specular is 100%, however, for coloured metals like gold or copper, the colour is given to the specular reflections and not to the diffuse reflections&#xD;&#xA;&#xD;&#xA;- a material that has 100% specular reflection with 100% glossiness, and 0% diffuse reflections it's a mirror&#xD;&#xA;&#xD;&#xA;- a material that has 100% specular reflection with 0% glossiness and 0% diffuse reflections looks like a very rough metal (like a heavily sandblasted silver) however, metals in real life always have some amount of glossiness it's never 0%&#xD;&#xA;&#xD;&#xA;- the &quot;specularity&quot; parameter is usually used to &quot;weight&quot; the % of specular reflection&#xD;&#xA;&#xD;&#xA;- the &quot;specular colour&quot; parameter is used to assign the colour to the specular reflections (metals and other strange hybrid materials can have coloured reflections; non-metallic/dielectric materials usually have white specular reflections)&#xD;&#xA;&#xD;&#xA;- the diffuse reflection might not always has a weighting factor as the specular reflections, usually it is controlled by the luminosity of its colour.&#xD;&#xA;&#xD;&#xA;- the &quot;diffuse colour&quot; parameter is the same as the specular colour but assigns a colour to the diffuse reflections rather than the specular ones.&#xD;&#xA;&#xD;&#xA;Additional observations: &#xD;&#xA;&#xD;&#xA;- the metalness does not describe a different type of reflection, but it basically makes sure that when increasing the specular reflections, the diffuse reflections are lowered proportionally. (so basically, when you increase specular reflections to 100%, even if there is a colour assigned to the diffuse colour channel you won't see it because it would be weighted down to 0%)&#xD;&#xA;&#xD;&#xA;- Do not mistake the diffuse reflection with the subsurface scattering (SSS), the SSS is an effect that scatters the light underneath the surface as the Diffuse, but it can go way farther underneath the surface compared to the diffuse, in theory, if you set the SSS distance to a very low number you could replicate the Diffuse reflection effect, however, it is much heavier to calculate, so when you don't need to go very far beneath the surface you just avoid calculating it and you rely only on the diffuse effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39965" PostHistoryTypeId="24" PostId="13317" RevisionGUID="11ebc9df-32d5-4fe7-b4b3-3f9af49498fb" CreationDate="2023-02-24T14:40:48.100" Comment="Proposed by 445 approved by 13095 edit id of 618" ContentLicense="CC BY-SA 4.0" />
  <row Id="39966" PostHistoryTypeId="50" PostId="13002" RevisionGUID="42d22d6f-e121-48bb-8ab5-1ff0e549444a" CreationDate="2023-02-25T01:09:11.113" UserId="-1" />
  <row Id="39967" PostHistoryTypeId="2" PostId="13320" RevisionGUID="b11d2b0e-90f8-4f8e-abe5-647284217927" CreationDate="2023-02-25T05:06:43.477" UserId="19537" Text="When using MIS, we always want to express the PDF value in a unified measure in order not to render the ratio between them meaningless. Yet when I read through chapter 16 of PBR-book, I got confused by how to choose the correct measure.&#xD;&#xA;&#xD;&#xA;First, I see that in [subpath connection](https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/Bidirectional_Path_Tracing#SubpathConnections) `s == 1` (only one vertex on the light path is used) case, we first need to sample (sort of like) direct component if the light vertex is connectible:&#xD;&#xA;```c++ &#xD;&#xA;Spectrum lightWeight = light-&gt;Sample_Li(pt.GetInteraction(), sampler.Get2D(),&#xD;&#xA;                                                   &amp;wi, &amp;pdf, &amp;vis);&#xD;&#xA;```&#xD;&#xA;Here, `pdf` is computed in `Sample_Li` method, and it is later used for &#xD;&#xA;```c++&#xD;&#xA;sampled = Vertex::CreateLight(ei, lightWeight / (pdf * lightPdf), 0);&#xD;&#xA;```&#xD;&#xA;Typical MC estimation step, right? In unidirectional path tracing, `pdf * lightPdf` is defined in solid angle measure, so after sampling a vertex on an area source (with `pdf = 1. / area`), we should convert the pdf to solid angle measure using `length^2 / cos`. However, in `pbrt-v3`, `Sample_Li` seems to return pdf defined in area measure. Here I quote the code from `lights/diffusive.cpp` in `pbrt-v3`:&#xD;&#xA;```c++&#xD;&#xA;Interaction pShape = shape-&gt;Sample(ref, u, pdf);&#xD;&#xA;```&#xD;&#xA;And the sample method (for example, if the shape is triangle):&#xD;&#xA;```c++&#xD;&#xA;Interaction Triangle::Sample(const Point2f &amp;u, Float *pdf) const {&#xD;&#xA;    /** ... */&#xD;&#xA;    *pdf = 1 / Area();&#xD;&#xA;    /** ... */&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;To me, it doesn't seem like the conversion is done. To make it even more confusing, pbr-book says:&#xD;&#xA;&gt; Like Sample_Li(), the PDF value this method returns is defined with respect to **solid angle** at the reference point. [[reference]](https://www.pbr-book.org/3ed-2018/Light_Transport_III_Bidirectional_Methods/The_Path-Space_Measurement_Equation#Camera::Sample_Wi)&#xD;&#xA;&#xD;&#xA;And yes, `Sample_Wi()` does return pdf defined in solid angle measure:&#xD;&#xA;```c++&#xD;&#xA;// pdf calculation defined in Sample_Wi&#xD;&#xA;*pdf = (dist * dist) / (AbsDot(lensIntr.n, *wi) * lensArea);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Yet, `lightWeight` seems to be divided by pdf returned by `Sample_Li()`, which seems to be  defined in area measure. This is baffling me a lot? Did misunderstand anything here? Is this some kind of weird mechanism in BDPT?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39969" PostHistoryTypeId="1" PostId="13320" RevisionGUID="b11d2b0e-90f8-4f8e-abe5-647284217927" CreationDate="2023-02-25T05:06:43.477" UserId="19537" Text="Confusion about PDF defined in solid angle / area measure" ContentLicense="CC BY-SA 4.0" />
  <row Id="39970" PostHistoryTypeId="3" PostId="13320" RevisionGUID="b11d2b0e-90f8-4f8e-abe5-647284217927" CreationDate="2023-02-25T05:06:43.477" UserId="19537" Text="|pathtracing|pbrt|pdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39971" PostHistoryTypeId="2" PostId="13321" RevisionGUID="b0b4a409-187a-481e-8df8-38d5812ff190" CreationDate="2023-02-25T23:58:57.613" UserId="19631" Text="Consider the following code in an OpenGL shader:&#xD;&#xA;```glsl&#xD;&#xA;struct PointLight {&#xD;&#xA;    vec3 position;&#xD;&#xA;&#xD;&#xA;    float constant;&#xD;&#xA;    float linear;&#xD;&#xA;    float quadratic;&#xD;&#xA;&#xD;&#xA;    vec3 ambient;&#xD;&#xA;    vec3 diffuse;&#xD;&#xA;    vec3 specular;&#xD;&#xA;};&#xD;&#xA;uniform PointLight pointLights[4];&#xD;&#xA;```&#xD;&#xA;How can I query the size of `pointLights` using interface query?&#xD;&#xA;I tried this:&#xD;&#xA;```cpp&#xD;&#xA;auto idx = glGetProgramResourceIndex(prog, GL_UNIFORM, &quot;pointLights&quot;);&#xD;&#xA;auto blockProperty = (GLenum)GL_ARRAY_SIZE;&#xD;&#xA;auto arraySize = GLint{};&#xD;&#xA;glGetProgramResourceiv(prog, GL_UNIFORM, idx, 1, &amp;blockProperty, 1, nullptr, &amp;arraySize);&#xD;&#xA;```&#xD;&#xA;It returns 0, which corresponds to the documentation of `glGetProgramResourceiv`:&#xD;&#xA;&#xD;&#xA;&gt; For active variables not corresponding to an array of basic types, the value zero is written to params.&#xD;&#xA;&#xD;&#xA;Well, what should I do for non-basic types?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39973" PostHistoryTypeId="1" PostId="13321" RevisionGUID="b0b4a409-187a-481e-8df8-38d5812ff190" CreationDate="2023-02-25T23:58:57.613" UserId="19631" Text="Query the size of an array of non-basic types using interface query in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="39974" PostHistoryTypeId="3" PostId="13321" RevisionGUID="b0b4a409-187a-481e-8df8-38d5812ff190" CreationDate="2023-02-25T23:58:57.613" UserId="19631" Text="|opengl|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39976" PostHistoryTypeId="50" PostId="9926" RevisionGUID="dd664064-850d-44ce-9090-55b4595ef973" CreationDate="2023-02-26T02:07:10.920" UserId="-1" />
  <row Id="39977" PostHistoryTypeId="2" PostId="13322" RevisionGUID="ee9dd17e-a6e7-4145-ba36-cd8c378fb500" CreationDate="2023-02-26T02:09:34.873" UserId="2654" Text="To the uniform query API, there is no such thing as an &quot;array of non-basic types&quot;. There are just a bunch of uniforms that just so happen to have names that include array notation like &quot;pointLights[1].constant&quot;.&#xD;&#xA;&#xD;&#xA;Put another way, `pointLights` is not a uniform. Nor is `pointLights[1]`. Only the elements the aggregate are themselves uniforms. And as far as the API is concerned, &quot;pointLights[1].constant&quot; is a completely separate uniform from the one named &quot;pointLights[3].constant&quot; with no relationship between them.&#xD;&#xA;&#xD;&#xA;This is in part because you cannot *set* arrays of non-basic types with a single call. That is, there's no equivalent to `glProgramUniform4fv`, which has the ability to set a `vec4[N]` array uniform in a single function call.&#xD;&#xA;&#xD;&#xA;So if you want to know how big some array of aggregates is, you're going to have to deduce it by iterating through all of the uniform names and comparing them to see which has the largest index." ContentLicense="CC BY-SA 4.0" />
  <row Id="39979" PostHistoryTypeId="2" PostId="13323" RevisionGUID="879c15ed-11f1-48b1-a7b8-39a1cbcc965c" CreationDate="2023-02-26T16:26:43.347" UserId="19633" Text="I read a lot about lighting recently but I have (at least) one thing that remains a dark corner:&#xD;&#xA;The [Blinn-Phong][1] and [this opengl source][2]talks about an halfway vector.&#xD;&#xA;&#xD;&#xA;### My understanding:&#xD;&#xA;&#xD;&#xA; 1. This vector is only used in Blinn Phong or derivatives but not in GGX &#xD;&#xA; 2. It is essentially an optimization for old hardware to avoid too many calculations &#xD;&#xA; 3. Other more realistic methods (GGX..) don't limit themselves to a simple half vector but a random number of rays starting from the microfacet.&#xD;&#xA;&#xD;&#xA;### My question:&#xD;&#xA;&#xD;&#xA;Is my understanding correct so far?&#xD;&#xA;&#xD;&#xA;------&#xD;&#xA;It seems logical to reach more photorealism than Blinn-Phong, but again, **it has just been a few days** of studying path tracers source codes and reading as much litterature as I could on the subject of Lighting.&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model#Description&#xD;&#xA;  [2]: https://learnopengl.com/Advanced-Lighting/Advanced-Lighting" ContentLicense="CC BY-SA 4.0" />
  <row Id="39981" PostHistoryTypeId="1" PostId="13323" RevisionGUID="879c15ed-11f1-48b1-a7b8-39a1cbcc965c" CreationDate="2023-02-26T16:26:43.347" UserId="19633" Text="Blinn-Phong, GGX and half vector for light" ContentLicense="CC BY-SA 4.0" />
  <row Id="39982" PostHistoryTypeId="3" PostId="13323" RevisionGUID="879c15ed-11f1-48b1-a7b8-39a1cbcc965c" CreationDate="2023-02-26T16:26:43.347" UserId="19633" Text="|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39983" PostHistoryTypeId="2" PostId="13324" RevisionGUID="9006bfe6-e4a7-4c20-842f-79dc6f4228a9" CreationDate="2023-02-27T09:17:34.203" UserId="5388" Text="**3x3 matrices cannot represent 3D translations, but 4x4 matrices can**&#xD;&#xA;&#xD;&#xA;A simple argument why 3D translations are not possible with 3x3 matrices is that translation can take the origin vector:&#xD;&#xA;&#xD;&#xA;    0&#xD;&#xA;    0&#xD;&#xA;    0&#xD;&#xA;&#xD;&#xA;away from the origin, say to `x = 1`:&#xD;&#xA;&#xD;&#xA;    1&#xD;&#xA;    0&#xD;&#xA;    0&#xD;&#xA;&#xD;&#xA;But that would require a matrix such that:&#xD;&#xA;&#xD;&#xA;    | a b c |   |0|   |1|&#xD;&#xA;    | d e f | * |0| = |0|&#xD;&#xA;    | g h i |   |0|   |0|&#xD;&#xA;&#xD;&#xA;But that is impossible.&#xD;&#xA;&#xD;&#xA;A &quot;more overkill&quot;/&quot;more elegant&quot; argument is the [singular Value Decomposition theorem](https://en.wikipedia.org/wiki/Singular_value_decomposition), which says that every matrix can be made up with two rotations and one scaling operation:&#xD;&#xA;&#xD;&#xA;- rotate to align with eignevectors&#xD;&#xA;- scale with the eigenvectors&#xD;&#xA;- rotate to the final desired position&#xD;&#xA;&#xD;&#xA;No translations there.&#xD;&#xA;&#xD;&#xA;**Why is it possible to use matrices to represent rotations?**&#xD;&#xA;&#xD;&#xA;Many modeled objects (e.g. a car chassis) or part of modeled objects (e.g. a car tire, a driving wheel) are solids: the distances between vertexes never change.&#xD;&#xA;&#xD;&#xA;The only transformations we want to do to on them are rotations and translations.&#xD;&#xA;&#xD;&#xA;Matrix multiplication can encode both rotations (NxN matrix) and translations (we need one extra dimension).&#xD;&#xA;&#xD;&#xA;Rotation matrices have explicit formulas, e.g.: a 2D rotation matrix for angle `a` is of form:&#xD;&#xA;&#xD;&#xA;    cos(a) -sin(a)&#xD;&#xA;    sin(a)  cos(a)&#xD;&#xA;&#xD;&#xA;There are analogous formulas [for 3D](https://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions), but note that [3D rotations take 3 parameters instead of just 1](https://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions).&#xD;&#xA;&#xD;&#xA;Translations are less trivial and will be discussed later. They are the reason we need 4D matrices.&#xD;&#xA;&#xD;&#xA;As a cultural fact, the set of all rotation matrices in a dimension is called the [special orthogonal group (SO(n))](https://en.wikipedia.org/wiki/Orthogonal_group), which is also a [Lie group](https://en.wikipedia.org/wiki/Lie_group), and has fundamental applications in particle physics. &#xD;&#xA;&#xD;&#xA;**Why is it nice to use matrices at all?**&#xD;&#xA;&#xD;&#xA;Because the composition of multiple matrices can be pre-calculated by [matrix multiplication](https://en.wikipedia.org/wiki/Matrix_multiplication).&#xD;&#xA;&#xD;&#xA;E.g., if we are going to translate one thousand vectors `v` of our car chassis with matrix `T` and then rotate with matrix `R`, instead of doing:&#xD;&#xA;&#xD;&#xA;    v2 = T * v&#xD;&#xA;&#xD;&#xA;and then:&#xD;&#xA;&#xD;&#xA;    v3 = R * v2&#xD;&#xA;&#xD;&#xA;for each vector, we can pre-calculate:&#xD;&#xA;&#xD;&#xA;    RT = R * T&#xD;&#xA;&#xD;&#xA;and then do just one multiplication for every vertex:&#xD;&#xA;&#xD;&#xA;    v3 = RT * v&#xD;&#xA;&#xD;&#xA;Even better: if we then want place the vertexes of tire and driving wheel relative to the car, we just multiply the previous matrix `RT` by the matrix relative to the car itself.&#xD;&#xA;&#xD;&#xA;This naturally leads to maintaining a *stack* of matrices:&#xD;&#xA;&#xD;&#xA;- calculate chassis matrix&#xD;&#xA;- multiply by tire matrix (push)&#xD;&#xA;- remove tire matrix (pop)&#xD;&#xA;- multiply by driving wheel matrix (push)&#xD;&#xA;- ...&#xD;&#xA;&#xD;&#xA;This stack was explicitly present in the older deprecated [immediate mode](https://stackoverflow.com/questions/6733934/what-does-immediate-mode-mean-in-opengl) OpenGL APIs such as [glPushMatrix](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushMatrix.xml), but with the [advent of shaders](https://stackoverflow.com/questions/17789575/what-are-shaders-in-opengl-and-what-do-we-need-them-for/36211337#36211337) this responsibility was passed more directly to the shader authors.&#xD;&#xA;&#xD;&#xA;**How adding one dimension solves the problem**&#xD;&#xA;&#xD;&#xA;Let's consider the case from 1D to 2D which is easier to visualize.&#xD;&#xA;&#xD;&#xA;A matrix in 1D is just one number, and as we've seen in 3D it can't do a translation, only a scaling.&#xD;&#xA;&#xD;&#xA;But if we add the extra dimension as we get:&#xD;&#xA;&#xD;&#xA;    | 1 dx | * |x|  = | x + dx * y |&#xD;&#xA;    | 0  1 |   |y|    | y          |&#xD;&#xA;&#xD;&#xA;Now, since we added this extra dimension ourselves, we are free to choose a fixed value for `y` that suites our needs, so we choose `y == 1` to get:&#xD;&#xA;&#xD;&#xA;    | x + dx |&#xD;&#xA;    | 1      |&#xD;&#xA;&#xD;&#xA;And finally, if we forget about this new extra dimension, we get:&#xD;&#xA;&#xD;&#xA;    x + dx&#xD;&#xA;&#xD;&#xA;as we wanted.&#xD;&#xA;&#xD;&#xA;This 2D transformation is so important that it has a name: [shear transformation](https://en.wikipedia.org/wiki/Shear_mapping).&#xD;&#xA;&#xD;&#xA;It is cool to visualize this transformation:&#xD;&#xA;&#xD;&#xA;&lt;img src=&quot;https://i.stack.imgur.com/BIe70.png&quot; height=&quot;200&quot; /&gt;&#xD;&#xA;&#xD;&#xA;[Image source](https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/VerticalShear_m=1.25.svg/1225px-VerticalShear_m=1.25.svg.png).&#xD;&#xA;&#xD;&#xA;Note how every horizontal line (fixed `y`) is just translated (larger `y` being translated more).&#xD;&#xA;&#xD;&#xA;We just happened to take the line `y = 1` as our new 1D line, and translate it with a 2D matrix.&#xD;&#xA;&#xD;&#xA;Things are analogous in 3D, with 4D shear matrices of the form:&#xD;&#xA;&#xD;&#xA;    | 1 0 0 dx |   | x |   | x + dx |&#xD;&#xA;    | 0 1 0 dy | * | y | = | y + dy |&#xD;&#xA;    | 0 0 1 dz |   | z |   | z + dz |&#xD;&#xA;    | 0 0 0  1 |   | 1 |   |      1 |&#xD;&#xA;&#xD;&#xA;And our old 3D rotations / scaling are now of form:&#xD;&#xA;&#xD;&#xA;    | a b c 0 |&#xD;&#xA;    | d e f 0 |&#xD;&#xA;    | g h i 0 |&#xD;&#xA;    | 0 0 0 1 |&#xD;&#xA;&#xD;&#xA;[This Jamie King video tutorial](https://www.youtube.com/watch?v=2Snoepcmi9U) is also worth watching.&#xD;&#xA;&#xD;&#xA;**Affine space**&#xD;&#xA;&#xD;&#xA;Affine space is the space generated by all our 3D linear transformations (matrix multiplications) together with the 4D shear (3D translations).&#xD;&#xA;&#xD;&#xA;If we multiply a shear matrix and a 3D linear transformation, we always get something of the form:&#xD;&#xA;&#xD;&#xA;    | a b c dx |&#xD;&#xA;    | d e f dy |&#xD;&#xA;    | g h i dz |&#xD;&#xA;    | 0 0 0  1 |&#xD;&#xA;&#xD;&#xA;This is the most general possible affine transformation, which does 3D rotation / scaling and translation.&#xD;&#xA;&#xD;&#xA;One important property is that if we multiply 2 affine matrices:&#xD;&#xA;&#xD;&#xA;    | a b c dx |   | a2 b2 c2 dx2 |&#xD;&#xA;    | d e f dy | * | d2 e2 f2 dy2 |&#xD;&#xA;    | g h i dz |   | g2 h2 i2 dz2 |&#xD;&#xA;    | 0 0 0  1 |   |  0  0  0   1 |&#xD;&#xA;&#xD;&#xA;we *always* get another affine matrix of form:&#xD;&#xA;&#xD;&#xA;    | a3 b3 c3 (dx + dx2) |&#xD;&#xA;    | d3 e3 f3 (dy + dy2) |&#xD;&#xA;    | g3 h3 i3 (dz + dz2) |&#xD;&#xA;    |  0  0  0          1 |&#xD;&#xA;&#xD;&#xA;Mathematicians call this property *closure*, and is required to define a space.&#xD;&#xA;&#xD;&#xA;For us, it means that we can keep doing matrix multiplications to pre-calculate final transformations happily, which is why use used matrices in the first place, without ever getting more general 4D linear transformations which are not affine.&#xD;&#xA;&#xD;&#xA;**Frustum projection**&#xD;&#xA;&#xD;&#xA;But wait, there is one more important transformation that we do all the time: `glFrustum`, which makes an object 2x further, appear 2x smaller.&#xD;&#xA;&#xD;&#xA;First get some intuition about `glOrtho` vs `glFrustum` at: https://stackoverflow.com/questions/2571402/explain-the-usage-of-glortho/36046924#36046924&#xD;&#xA;&#xD;&#xA;As a quick reminder, a projection is the act of taking 3D points and plotting them on the 2D camera plane, possibly taking into account perspective if we want to be realistic. This is the key step to translate between the 3D world of vertex shaders and the 2D world of fragment shaders: https://stackoverflow.com/questions/17789575/what-are-shaders-in-opengl-and-what-do-we-need-them-for/36211337#36211337&#xD;&#xA;&#xD;&#xA;`glOrtho` can be done just with translations + scaling , but how can we implement `glFrustum` with matrices?&#xD;&#xA;&#xD;&#xA;Suppose that:&#xD;&#xA;&#xD;&#xA;- our eye is at the origin, looking at -z&#xD;&#xA;- the screen (near plane) is at `z = -1` that is a square of length 2&#xD;&#xA;- the far plane of the frustum is at `z = -2`&#xD;&#xA;&#xD;&#xA;If only we allowed more general 4-vectors of type:&#xD;&#xA;&#xD;&#xA;    (x, y, z, w)&#xD;&#xA;&#xD;&#xA;with `w != 0`, and in addition we identify every `(x, y, z, w)` with `(x/w, y/w, z/w, 1)`, then a frustum transformation with the matrix would be:&#xD;&#xA;&#xD;&#xA;    | 1 0  0 0 |   | x |   |  x |               | x / -z |&#xD;&#xA;    | 0 1  0 0 | * | y | = |  y | identified to | y / -z |&#xD;&#xA;    | 0 0  1 0 |   | z |   |  z |               |     -1 |&#xD;&#xA;    | 0 0 -1 0 |   | w |   | -z |               |      1 |&#xD;&#xA;&#xD;&#xA;If we throw away:&#xD;&#xA;&#xD;&#xA;- `z` because projection means to take a 3D point and place it in a 2D plane&#xD;&#xA;- `w` because it is just a mathematical calculation artifact we invented&#xD;&#xA;&#xD;&#xA;we get:&#xD;&#xA;&#xD;&#xA;- `x_proj = x / -z`&#xD;&#xA;- `y_proj = y / -z`&#xD;&#xA;&#xD;&#xA;which is exactly what we wanted! We can verify that for some values, e.g.:&#xD;&#xA;&#xD;&#xA;- if `z == -1`, exactly on the plane we're projecting to, `x_proj == x` and `y_proj == y`.&#xD;&#xA;- if `z == -2`, then `x_proj = x/2`: objects are half size.&#xD;&#xA;&#xD;&#xA;Note how the `glFrustum` transform is not of affine form: it cannot be implemented just with rotations and translations.&#xD;&#xA;&#xD;&#xA;The mathematical &quot;trickery&quot; of adding the `w` and dividing by it is called [homogeneous coordinates](https://en.wikipedia.org/wiki/Homogeneous_coordinates)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[Image source](http://www.glprogramming.com/red/chapter03.html).&#xD;&#xA;&#xD;&#xA;See also: related Stack Overflow question: https://stackoverflow.com/questions/2465116/understanding-opengl-matrices&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/QeV7z.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="39985" PostHistoryTypeId="2" PostId="13325" RevisionGUID="a04753ca-8eb7-44d0-82aa-f8e4bdfb5167" CreationDate="2023-02-27T10:54:23.427" UserId="19521" Text="I need to render a lot of objects that swap their model from frame to frame. &#xD;&#xA;&#xD;&#xA;Currently, I am putting every model into a single vertex buffer and giving every vertex an id. I store the same id in the instance buffer. If the vertex and instance buffer ids match in the vertex shader, then I render it. It works, but since I'm rendering tens of thousands of objects, I can only fit about 1000 vertices into the vertex buffer before rendering exceeds 16ms. This translates to about 2-3 models.&#xD;&#xA;&#xD;&#xA;Is there some other technique I could use to swap them out where I could get maybe 10-20 models?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="39987" PostHistoryTypeId="1" PostId="13325" RevisionGUID="a04753ca-8eb7-44d0-82aa-f8e4bdfb5167" CreationDate="2023-02-27T10:54:23.427" UserId="19521" Text="What technique can I use to swap thousands of models per frame?" ContentLicense="CC BY-SA 4.0" />
  <row Id="39988" PostHistoryTypeId="3" PostId="13325" RevisionGUID="a04753ca-8eb7-44d0-82aa-f8e4bdfb5167" CreationDate="2023-02-27T10:54:23.427" UserId="19521" Text="|3d|mesh|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="39989" PostHistoryTypeId="2" PostId="13326" RevisionGUID="b2c06d35-24f9-4d37-a6f1-868d24c7954d" CreationDate="2023-02-27T11:20:51.743" UserId="7952" Text="It is better to think of blinn-phong as a specialization of the more generalized PBR equations. Its major goal is efficiency, so, in that sense you are on the right path, but the light vector, view vector, normal vector and  *half-way* vector comes up repeatedly in PBR.&#xD;&#xA;&#xD;&#xA;The Cook-Torrence BRDF is very popular and the half way vector (often just called the half vector) is an important part of the computation. &#xD;&#xA;&#xD;&#xA;The half way vector comes up in microfacet distribution models (MDF) Beckman, GGX and Towbridge-Reitz all use the half way vector. &#xD;&#xA;&#xD;&#xA;Usually listed in the equations as just 'H'. &#xD;&#xA;&#xD;&#xA;$f_r(H,N,L,V)$&#xD;&#xA;&#xD;&#xA;Blinn-Phong is a excellent starting point for learning PBR since most of the concepts apply directly to physically based models." ContentLicense="CC BY-SA 4.0" />
  <row Id="39991" PostHistoryTypeId="5" PostId="13326" RevisionGUID="c91b3d6c-b2c3-4d84-bf26-042cba32ad25" CreationDate="2023-02-27T16:25:38.003" UserId="7952" Comment="added 475 characters in body" Text="It is better to think of blinn-phong as a specialization of the more generalized PBR equations. Its major goal is efficiency, so, in that sense you are on the right path, but the light vector, view vector, normal vector and  *half-way* vector comes up repeatedly in PBR.&#xD;&#xA;&#xD;&#xA;The Cook-Torrence BRDF is very popular and the half way vector (often just called the half vector) is an important part of the computation. &#xD;&#xA;&#xD;&#xA;The half way vector comes up in microfacet distribution models (MDF) Beckman, GGX and Towbridge-Reitz all use the half way vector. &#xD;&#xA;&#xD;&#xA;Usually listed in the equations as just 'H'. &#xD;&#xA;&#xD;&#xA;$f_r(H,N,L,V)$&#xD;&#xA;&#xD;&#xA;Blinn-Phong is a excellent starting point for learning PBR since most of the concepts apply directly to physically based models.&#xD;&#xA;&#xD;&#xA;One of the key principles of PBR rendering is the principle of energy conservation. This means that a surface never reflects more light than it receives. The halfway vector is more consistent with this principle because it accounts for both the view direction and the light direction, and does not overestimate the specular reflection as the reflection vector does. The halfway vector also allows for a smoother transition between different roughness levels of a surface." ContentLicense="CC BY-SA 4.0" />
  <row Id="39992" PostHistoryTypeId="2" PostId="13327" RevisionGUID="f056bae4-cc5a-40e8-9be3-137378daa28e" CreationDate="2023-02-27T17:57:34.043" UserId="19642" Text="I am following David Salomon's book &quot;[Transformations and Projections in Computer Graphics][1]&quot; where it is explained how to project a 3d object to the 2d canvas in perspective:&#xD;&#xA;&#xD;&#xA;Define a point for the viewer on the negative z-axis, a distance k away from the origin; Define the canvas as the x-y plane; Draw a line connecting a point on the object to the viewer and mark the intersection of this line with the x-y plane. This new point is the corresponding point when drawn in perspective.&#xD;&#xA;&#xD;&#xA;I have done exactly that for a cube with the help of a geometry software (GeoGebra) and added an option to change the value of k, the location of the viewer.&#xD;&#xA;&#xD;&#xA;Then I realized that the object actually looks larger on the canvas when k is increased. This is in contradiction to the expected illusion of perspective - objects further away should look smaller.&#xD;&#xA;&#xD;&#xA;I would like to have your opinion about why it is so in my case.&#xD;&#xA;&#xD;&#xA;** The drawing on the right hand side was created by following the exact procedure I explained above.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://books.google.com/books?id=6CzuydFlMpwC&#xD;&#xA;  [2]: https://i.stack.imgur.com/x340d.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="39994" PostHistoryTypeId="1" PostId="13327" RevisionGUID="f056bae4-cc5a-40e8-9be3-137378daa28e" CreationDate="2023-02-27T17:57:34.043" UserId="19642" Text="Why my object becomes larger when drawn in perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="39995" PostHistoryTypeId="3" PostId="13327" RevisionGUID="f056bae4-cc5a-40e8-9be3-137378daa28e" CreationDate="2023-02-27T17:57:34.043" UserId="19642" Text="|perspective|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40000" PostHistoryTypeId="2" PostId="13329" RevisionGUID="22c32cbc-49c7-45c4-9a54-3ae7cc4a8884" CreationDate="2023-02-27T18:41:07.513" UserDisplayName="user19644" Text="You can enclose arbitrary amount of vertices within glBegin/glEnd statements. Does OpenGL limit the number of vertices you create or it allocates memory for more?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40002" PostHistoryTypeId="1" PostId="13329" RevisionGUID="22c32cbc-49c7-45c4-9a54-3ae7cc4a8884" CreationDate="2023-02-27T18:41:07.513" UserDisplayName="user19644" Text="Does OpenGL allocates on glBegin/glEnd?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40003" PostHistoryTypeId="3" PostId="13329" RevisionGUID="22c32cbc-49c7-45c4-9a54-3ae7cc4a8884" CreationDate="2023-02-27T18:41:07.513" UserDisplayName="user19644" Text="|opengl|rendering|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40004" PostHistoryTypeId="2" PostId="13330" RevisionGUID="770b6ff4-21f6-4ea0-9065-ae9345c17d2e" CreationDate="2023-02-27T18:45:04.250" UserId="2654" Text="OpenGL implementations aren't assumed to have unlimited memory, but the specification imposes no specific restrictions on this. That is, you can't ask how many vertices you can send. Instead, if you trip some limit, you'll get a `GL_OUT_OF_MEMORY` error and rendering will fail.&#xD;&#xA;&#xD;&#xA;But in 2023... you're *really* should not care. If you're using old compatibility APIs from 1992, then you probably aren't going to be sending enough vertices to trip any limits from any card that was made after the year 2000. So this is basically sophistry." ContentLicense="CC BY-SA 4.0" />
  <row Id="40006" PostHistoryTypeId="2" PostId="13331" RevisionGUID="324a7d99-1083-46b0-a880-316a17df462d" CreationDate="2023-02-27T19:18:03.340" UserId="445" Text="One approach is to reframe the problem from “objects which change their models” to “objects which are replaced with other objects that happen to have the same position”.&#xD;&#xA;&#xD;&#xA;Create buffers (or ranges in one buffer) of instances that are all supposed to draw the _same_ model. Each frame, go through your list of objects, determine which model is to be drawn, and add the object's position (and other instance data) to the instance buffer _for that model._&#xD;&#xA;&#xD;&#xA;This of course requires uploading lots of instance data every frame, but you need to do that anyway if the objects are independently moving/animating, and it'll be faster than the GPU processing thousands of extraneous vertices." ContentLicense="CC BY-SA 4.0" />
  <row Id="40008" PostHistoryTypeId="2" PostId="13332" RevisionGUID="b5e56bc8-7c43-447a-bc99-5073f010873a" CreationDate="2023-02-28T05:12:06.633" UserId="445" Text="If you keep constant the scale at which you view the x-y plane (image plane), while changing the distance of the viewpoint to that plane, then you are not solely changing the viewpoint position; you are also changing the _field of view_ (FOV). Here is an “overhead” view of the effect you're getting. Notice that the solid horizontal line (representing your x-y plane) is the same length in both cases.&#xD;&#xA;&#xD;&#xA;[![Diagram of two different distances and FOVs][2]][2]&#xD;&#xA;&#xD;&#xA;When the viewpoint is far from the plane (*k* is large), the object is closer to the edge of the visible image. (In the limit $k = \infty$, this becomes an orthographic projection.) When *k* is smaller, the FOV widens, meaning that objects in the same “world” position get projected to regions of the image closer to the center — notice where the lines of intersection between the box and the image plane are.&#xD;&#xA;&#xD;&#xA;In order to avoid changing the field of view, what you must do is keep *k* constant, but instead translate _both_ the viewpoint and the image plane — or, equivalently, translate all the displayed objects in the opposite direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/xaIZc.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40010" PostHistoryTypeId="2" PostId="13333" RevisionGUID="e19e3d3f-28dc-428f-b787-8ab508122651" CreationDate="2023-02-28T11:03:05.757" UserId="7567" Text="I recently hit the roof for maximum texture size for my opengl implementation (GL_MAX_TEXTURE_SIZE contains $3379$) when I wanted to create a texture for a 4k resolution video frame ($3840 \times 2160$).&#xD;&#xA;&#xD;&#xA;This made me think about various ways to circumvent the problem that $3840&gt;3379$.&#xD;&#xA;&#xD;&#xA;I have used TEXTURE_2D_ARRAY, and I suppose one way would be to create such an array with sizes divided by two. In my case 4 slices of $1920\times 1080$ which then get to represent one &quot;quadrant&quot; each. Like a &quot;block-matrix&quot;, so to speak.&#xD;&#xA;&#xD;&#xA;I was thinking maybe there exist other, better solutions of how to address this." ContentLicense="CC BY-SA 4.0" />
  <row Id="40012" PostHistoryTypeId="1" PostId="13333" RevisionGUID="e19e3d3f-28dc-428f-b787-8ab508122651" CreationDate="2023-02-28T11:03:05.757" UserId="7567" Text="Which coding strategies exist to handle opengl texture size limit?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40013" PostHistoryTypeId="3" PostId="13333" RevisionGUID="e19e3d3f-28dc-428f-b787-8ab508122651" CreationDate="2023-02-28T11:03:05.757" UserId="7567" Text="|opengl|texture|data-structure|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40014" PostHistoryTypeId="5" PostId="13332" RevisionGUID="123284e0-d4d8-4284-8c8a-24731f8c0a7d" CreationDate="2023-02-28T16:42:20.203" UserId="445" Comment="added 906 characters in body" Text="If you keep constant the scale at which you view the x-y plane (image plane), while changing the distance of the viewpoint to that plane, then you are not solely changing the viewpoint position; you are also changing the _field of view_ (FOV). Here is an “overhead” view of the effect you're getting. Notice that the solid horizontal line (representing your x-y plane) is the same length in both cases.&#xD;&#xA;&#xD;&#xA;[![Diagram of two different distances and FOVs][1]][1]&#xD;&#xA;&#xD;&#xA;When the viewpoint is far from the plane (*k* is large), the object is closer to the edge of the visible image. (In the limit $k = \infty$, this becomes an orthographic projection.) When *k* is smaller, the FOV widens, meaning that objects in the same “world” position get projected to regions of the image closer to the center — notice where the lines of intersection between the box and the image plane are.&#xD;&#xA;&#xD;&#xA;In order to avoid changing the field of view, what you must do is keep *k* constant (relative to the size of the image plane), but instead translate _both_ the viewpoint and the image plane — or, equivalently, translate all the displayed objects in the opposite direction.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Here is how FOV relates to *k:*&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;$\theta$ is the FOV angle. Notice that the lines $k$ and $w$ (width) form a pair of right triangle. Split the picture down the middle and basic right-triangle trigonometry tells us that&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;k &amp;= r \cos(\theta/2) \\&#xD;&#xA;w/2 &amp;= r \sin(\theta/2) \\&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;for some radius $r$ which is irrelevant (there is no physical circle). Solving these to relate $k$ and $w$ gives us:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;w/2 = \tan(\theta/2) \cdot k&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This is how FOV is actually computed in the practice of real-time GPU graphics: a $k$ is chosen (called the “near plane” for unrelated reasons, chosen to be closer to the camera than any object in view), then the width and height of the rectangle are chosen based on the desired FOV and $k$.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xaIZc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FtRuI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40015" PostHistoryTypeId="5" PostId="13332" RevisionGUID="43d6a8f4-ba7a-4505-ba64-afed22699346" CreationDate="2023-02-28T16:47:26.383" UserId="445" Comment="added 906 characters in body" Text="If you keep constant the scale at which you view the x-y plane (image plane), while changing the distance of the viewpoint to that plane, then you are not solely changing the viewpoint position; you are also changing the _field of view_ (FOV). Here is an “overhead” view of the effect you're getting. Notice that the solid horizontal line (representing your x-y plane) is the same length in both cases.&#xD;&#xA;&#xD;&#xA;[![Diagram of two different distances and FOVs][1]][1]&#xD;&#xA;&#xD;&#xA;When the viewpoint is far from the plane (*k* is large), the object is closer to the edge of the visible image. (In the limit $k = \infty$, this becomes an orthographic projection.) When *k* is smaller, the FOV widens, meaning that objects in the same “world” position get projected to regions of the image closer to the center — notice where the lines of intersection between the box and the image plane are.&#xD;&#xA;&#xD;&#xA;In order to avoid changing the field of view, what you must do is keep *k* constant (relative to the size of the image plane), but instead translate _both_ the viewpoint and the image plane — or, equivalently, translate all the displayed objects in the opposite direction.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Here is how FOV expressed as angle relates to *k:*&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;$\theta$ is the FOV angle. Notice that the lines $k$ and $w$ (width) form a pair of right triangle. Split the picture down the middle and basic right-triangle trigonometry tells us that&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\begin{align}&#xD;&#xA;k &amp;= r \cos(\theta/2) \\&#xD;&#xA;w/2 &amp;= r \sin(\theta/2) \\&#xD;&#xA;\end{align}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;for some radius $r$ which is irrelevant (there is no physical circle). Solving these to relate $k$ and $w$ gives us:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;w/2 = \tan(\theta/2) \cdot k&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This is how FOV is actually computed in the practice of real-time GPU graphics: a $k$ is chosen (called the “near plane” for unrelated reasons, chosen to be closer to the camera than any object in view), then the width and height of the rectangle (actually one face of a [frustum](https://en.wikipedia.org/wiki/Viewing_frustum)) are chosen based on the desired FOV and $k$.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xaIZc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FtRuI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40016" PostHistoryTypeId="2" PostId="13334" RevisionGUID="a6fed379-3743-4d05-ba8c-0b6e58efc977" CreationDate="2023-02-28T18:20:17.397" UserId="2654" Text="First, a correction:&#xD;&#xA;&#xD;&#xA;&gt; GL_MAX_TEXTURE_SIZE contains 3379&#xD;&#xA;&#xD;&#xA;No, it does not. That is the value of the `GL_MAX_TEXTURE_SIZE` *enumerator* (0x0D33). The actual implementation-defined maximum size is queried with `glGetIntegerv` *using* that enumerator.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;As for how to render to a conceptual image larger than the size of the texture you can create... you're just going to have to render the scene several times, with different viewports to different images. You can employ [layered rendering][1] with array textures to shift viewports between the layers. And you should do different frustum culling for the different layers (so you're not rendering the exact same scene multiple times). But that's about it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Layered_rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="40018" PostHistoryTypeId="52" PostId="13333" RevisionGUID="83eb7162-7e6a-4c71-a972-d324a43afb10" CreationDate="2023-02-28T20:15:33.933" />
  <row Id="40019" PostHistoryTypeId="4" PostId="13329" RevisionGUID="f6d5e76e-b1f7-489e-8da6-54f99e9d0c32" CreationDate="2023-02-28T20:25:23.133" UserDisplayName="user19644" Comment="edited title" Text="Does OpenGL allocate on glBegin/glEnd?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40024" PostHistoryTypeId="2" PostId="13336" RevisionGUID="cc052fbe-78cb-4920-8e96-feee9d6d288a" CreationDate="2023-03-01T16:56:19.387" UserId="10547" Text="I want to avoid IBL (image based lighting), however my scenes are way too dark - especially close-to-mirror like surfaces, which get little contributions from other direct light sources in the scene.&#xD;&#xA;&#xD;&#xA;So I was thinking that I should add some sort of ambient light - with single color defined in the scene. How do I calculate the contribution of such light based on normal and view directions, material albedo, roughness and metallness, and the ambient color? Is there any standard or typical equation for that?&#xD;&#xA;&#xD;&#xA;Note that I would like it view-dependant - make it complement other light sources." ContentLicense="CC BY-SA 4.0" />
  <row Id="40026" PostHistoryTypeId="1" PostId="13336" RevisionGUID="cc052fbe-78cb-4920-8e96-feee9d6d288a" CreationDate="2023-03-01T16:56:19.387" UserId="10547" Text="replace IBL with single color - the lighting equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="40027" PostHistoryTypeId="3" PostId="13336" RevisionGUID="cc052fbe-78cb-4920-8e96-feee9d6d288a" CreationDate="2023-03-01T16:56:19.387" UserId="10547" Text="|lighting|pbr|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40028" PostHistoryTypeId="5" PostId="13336" RevisionGUID="62699989-91fa-4d66-8124-5cd64c742f3d" CreationDate="2023-03-02T10:42:44.810" UserId="10547" Comment="added 524 characters in body" Text="I want to avoid IBL (image based lighting), however my scenes are way too dark - especially close-to-mirror like surfaces, which get little contributions from other direct light sources in the scene.&#xD;&#xA;&#xD;&#xA;So I was thinking that I should add some sort of scene light - with single color defined in the scene. How do I calculate the contribution of such light based on normal and view directions, material albedo, roughness and metallness, and the ambient color? Is there any standard or typical equation for that?&#xD;&#xA;&#xD;&#xA;Note that I would like it view-dependant.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;[![roughness/metallic balls][1]][1]&#xD;&#xA;All the balls in this picture should have approximately the same apparent brightness, but the smooth metal balls are way darker.&#xD;&#xA;&#xD;&#xA;I am using smith+ggx brdf, possibly modified.&#xD;&#xA;Here is the whole fragment shader: https://gist.github.com/malytomas/b882c27c324a4f27ff56780717c9e4b2#file-cage_shader_engine_standard-glsl_fragment-glsl-L347&#xD;&#xA;Line 347 is where I would like to add additional term to compensate for the absence of IBL.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1O7CY.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40029" PostHistoryTypeId="5" PostId="13336" RevisionGUID="5669bc76-bc64-41dd-9f09-2861646ce576" CreationDate="2023-03-02T10:49:34.997" UserId="10547" Comment="deleted 2 characters in body" Text="I want to avoid IBL (image based lighting), however my scenes are way too dark - especially close-to-mirror like surfaces, which get little contributions from other direct light sources in the scene.&#xD;&#xA;&#xD;&#xA;So I was thinking that I should add some sort of scene light - with single color defined in the scene. How do I calculate the contribution of such light based on normal and view directions, material albedo, roughness and metallness, and the scene color? Is there any standard or typical equation for that?&#xD;&#xA;&#xD;&#xA;Note that I would like it view-dependant.&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;[![roughness/metallic balls][1]][1]&#xD;&#xA;All the balls in this picture should have approximately the same apparent brightness, but the smooth metal balls are way darker.&#xD;&#xA;&#xD;&#xA;I am using smith+ggx brdf, possibly modified.&#xD;&#xA;Here is the whole fragment shader: https://gist.github.com/malytomas/b882c27c324a4f27ff56780717c9e4b2#file-cage_shader_engine_standard-glsl_fragment-glsl-L347&#xD;&#xA;Line 347 is where I would like to add additional term to compensate for the absence of IBL.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1O7CY.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40030" PostHistoryTypeId="50" PostId="12746" RevisionGUID="df01fcb2-b2d1-4e6d-b3e4-0af0d3d70fcd" CreationDate="2023-03-02T18:06:00.803" UserId="-1" />
  <row Id="40031" PostHistoryTypeId="2" PostId="13337" RevisionGUID="c117a269-af6b-4d90-bbb8-9e1466583ba6" CreationDate="2023-03-02T19:12:50.677" UserId="19642" Text="As nicely stated by Kevin Reid, the field of view is not accounted for in the figures I uploaded.&#xD;&#xA;&#xD;&#xA;In order to get the correct coordinates for the projected points on the $x-y$ plane, one should also divide each component by the half width of the screen:&#xD;&#xA;&#xD;&#xA;If $\mathbf{P}=\left(P_{x},P_{y},P_{z}\right)$ is the point in 3d and $\mathbf{P^{*}}\in\mathbb{R}^{2}$ is its projection, then&#xD;&#xA;$$&#xD;&#xA;P^{*}=\left(\frac{x_{P}}{\left(\frac{z_{P}}{k}+1\right)\frac{w}{2}},\frac{y_{P}}{\left(\frac{z_{P}}{k}+1\right)\frac{w}{2}}\right)=\left(\frac{x_{P}}{\tan\frac{\theta}{2}\left(k+z_{P}\right)},\frac{y_{p}}{\tan\frac{\theta}{2}\left(k+z_{P}\right)}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;In the figure I provided, the coordinates for the $\mathbf{P^{*}}$ where almost similar, except of the scaling factor due to the finite width of the screen:&#xD;&#xA;$$&#xD;&#xA;P^{*}=\left(\frac{x_{P}}{\left(\frac{z_{P}}{k}+1\right)},\frac{y_{P}}{\left(\frac{z_{P}}{k}+1\right)}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Referring back to David Salomon's book, in §3.10, the cone of view (or viewing volume) is indeed mentioned but only in regard to “clipping” — to determine which points are outside the viewing volume and therefore to determine whether they should be displayed or not. Aside from that I couldn't find in his book the missing part I was looking for in this question." ContentLicense="CC BY-SA 4.0" />
  <row Id="40033" PostHistoryTypeId="4" PostId="13327" RevisionGUID="0920c195-3b3a-4e65-b0c8-1e7349b2e45a" CreationDate="2023-03-02T19:20:47.160" UserId="19642" Comment="edited title" Text="Why an object becomes larger when drawn in perspective" ContentLicense="CC BY-SA 4.0" />
  <row Id="40034" PostHistoryTypeId="50" PostId="12498" RevisionGUID="d9028f59-eb1e-46d9-924a-098cf0577a1b" CreationDate="2023-03-03T02:05:05.690" UserId="-1" />
  <row Id="40035" PostHistoryTypeId="2" PostId="13338" RevisionGUID="218fe9d4-f502-41a5-92f7-734cd2c7108d" CreationDate="2023-03-03T02:39:55.900" UserId="5989" Text="I was looking at [this glass ball rendering](https://sketchfab.com/3d-models/tfa-f5a74cf164c54e4a943352d750b8fac2) with an image inside of it (zoom out to see the glass ball), and noticed that it looks like they simulate the refraction of light as it crosses from inside of the glass ball to the air outside. I know that you can achieve this either by rendering to a texture and then using that texture on the surface of the transparent object, or moving the vertices of objects inside/behind the transparent object, but both of those methods are problematic in my situation.&#xD;&#xA;&#xD;&#xA;I want to simulate the transition between two spaces where light bends differently (If you will, you can think of it kind of like I'm entering a [worm](https://www.youtube.com/watch?v=gQF-7yZMdnA) [hole](https://www.youtube.com/watch?v=FR2TE_Wf5fw) and ending up at another location), and you should be able to smoothly transition between the two spaces without being able to see the transition. For the rendering, the boundary between the two spaces can simply be treated as a refracting surface, and I would like to use ray tracing to achieve this refraction, where I only trace a single refracting ray and no reflecting ray. For this, I have some questions:&#xD;&#xA;&#xD;&#xA;1. Is it possible to trigger OpenGL to render a new image consisting of just one pixel for the refracted ray in the `main` function in the fragment (pixel?) shader? This would allow me to rely on a lot of functionality that already exists in OpenGL which I imagine that I would otherwise have have to implement myself, such as testing intersections between the ray and polygons in the scene, and interpolation of vertex values to the point on the polygon that was hit. If I could trigger OpenGL to render a new image, this would also make it easier to get a more consistently rendered image, as I want to avoid getting an image that changes discontinuously when I transition from being on one side of the boundary to being on the other side of the boundary.&#xD;&#xA;&#xD;&#xA;2. If it is not possible to trigger the rendering of a new, single-pixel image in the `main` function in the fragment shader in OpenGL, does Vulkan, which is supposed to be more powerful, offer this possibility?&#xD;&#xA;&#xD;&#xA;3. If I can't trigger OpenGL or Vulkan to render a new image in the `main` function in the fragment shader, do I have to manually calculate which polygon the refracted ray hits and where on it it hits, or can I still get OpenGL/Vulkan to do that automatically for me somehow? If I have to calculate this manually, how can I do that most easily? Does OpenGL/Vulkan provide me with some functions that can make this process easier for me?&#xD;&#xA;&#xD;&#xA;4. Also, for the refracted ray, can I make OpenGL/Vulkan call the `main` function in the fragment shader with the appropriate interpolated values for all variables (like it does normally) for each successive hit, or do I have to interpolate those manually somehow too? Again, does OpenGL/Vulkan provide me with some functions that can make this process easier for me if I have to do it manually?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40037" PostHistoryTypeId="1" PostId="13338" RevisionGUID="218fe9d4-f502-41a5-92f7-734cd2c7108d" CreationDate="2023-03-03T02:39:55.900" UserId="5989" Text="Refraction of light with ray tracing in OpenGL or Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40038" PostHistoryTypeId="3" PostId="13338" RevisionGUID="218fe9d4-f502-41a5-92f7-734cd2c7108d" CreationDate="2023-03-03T02:39:55.900" UserId="5989" Text="|opengl|raytracing|shader|vulkan|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40039" PostHistoryTypeId="4" PostId="13338" RevisionGUID="7c37ac3e-e61f-4587-811f-d0d11fb7f8be" CreationDate="2023-03-03T03:45:18.553" UserId="5989" Comment="edited title" Text="Raytracing in OpenGL or Vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40040" PostHistoryTypeId="2" PostId="13339" RevisionGUID="27d2b99f-79bc-4ae1-a058-2d0dc24dd657" CreationDate="2023-03-03T06:12:38.750" UserId="10807" Text="I am reading computer graphics. I am unable to distinguish between Non-uniform Scaling and Shear. Can someone explain the difference with two different examples?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40042" PostHistoryTypeId="1" PostId="13339" RevisionGUID="27d2b99f-79bc-4ae1-a058-2d0dc24dd657" CreationDate="2023-03-03T06:12:38.750" UserId="10807" Text="Non Uniform Scaling vs Shear in Image Transformation" ContentLicense="CC BY-SA 4.0" />
  <row Id="40043" PostHistoryTypeId="3" PostId="13339" RevisionGUID="27d2b99f-79bc-4ae1-a058-2d0dc24dd657" CreationDate="2023-03-03T06:12:38.750" UserId="10807" Text="|transformations|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40044" PostHistoryTypeId="2" PostId="13340" RevisionGUID="03337fcc-6990-4086-80bf-2b5d5419cd54" CreationDate="2023-03-03T10:13:23.423" UserId="17270" Text="I'm implementing tunnel detection algorithm in the paper &quot;[Computing Geometry-aware Handle and Tunnel Loops in 3D Models](https://web.cse.ohio-state.edu/~dey.8/paper/hantun-persist/hantun.pdf)&quot;. &#xD;&#xA;&#xD;&#xA;Before the actual tunnel detection, the input needs to be preprocessed, as mentioned in paper Section 5 &#xD;&#xA;&gt;&quot;In order to apply the algorithm for persistence, we assume that the input surface M is presented with a simplicial complex K which tessellates the convex hull of M and M is a subcomplex of K. This means that we have the explicit simplicial representations for both inside space I and outside space O.&quot;&#xD;&#xA;&#xD;&#xA;My input is a triangular closed surface mesh, from the above quote, my understanding is that I should:&#xD;&#xA;&#xD;&#xA;1.Read in the the surface mesh, perform a delaunay 3d algorithm using the points of the surface mesh. The output of this step is a tetrahedron mesh.&#xD;&#xA;&#xD;&#xA;2.From step1, I can somehow get the boundary surface(boundary in terms of same boundary as input surface mesh), exterior triangles and interior triangles.&#xD;&#xA;&#xD;&#xA;The author of the paper actually posted a [video on Youtube](https://www.youtube.com/watch?v=qa4t1vBEvps) illustrating the steps mentioned above.&#xD;&#xA;&#xD;&#xA;My question is: In step2, how can I get the surface and exterior triangles from tetrahedron mesh? During delaunay triangulation 3d, all it needs are the point clouds(ie. positions of points). &#xD;&#xA;&#xD;&#xA;I've tried constructing the initial surface mesh's SDF and try to find the surface from tetrahedron using SDF, but this has proved to be not ideal.&#xD;&#xA;&#xD;&#xA;Can someone give me some hint? Or am I heading a wrong direction?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40046" PostHistoryTypeId="1" PostId="13340" RevisionGUID="03337fcc-6990-4086-80bf-2b5d5419cd54" CreationDate="2023-03-03T10:13:23.423" UserId="17270" Text="How to get the boundary of delaunay triangulation" ContentLicense="CC BY-SA 4.0" />
  <row Id="40047" PostHistoryTypeId="3" PostId="13340" RevisionGUID="03337fcc-6990-4086-80bf-2b5d5419cd54" CreationDate="2023-03-03T10:13:23.423" UserId="17270" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40048" PostHistoryTypeId="2" PostId="13341" RevisionGUID="9406b0a1-6329-4e0e-a3ba-2e49c9f7a3d7" CreationDate="2023-03-03T14:58:22.750" UserId="9438" Text="You can obtain a boundary surface of a tet mesh by identifying which tet faces are used once in a tet mesh of shared vertices. These by definition are the triangles of the tet mesh boundary surface. &#xD;&#xA;&#xD;&#xA;All 'interior' faces will be used by at most two tetrahedrons. All 'exterior' faces will be used only once.&#xD;&#xA;&#xD;&#xA;1. Share the vertices of the tet mesh.&#xD;&#xA;&#xD;&#xA;2. Create a list of all the triangles (faces) in the tet mesh (each tet has 4 faces, and since tet mesh uses shared vertices, each tet will have 4 vertices).&#xD;&#xA;&#xD;&#xA;3. Create a list of vertex usage wrt to triangles. i.e a list of vertices for each triangle.&#xD;&#xA;&#xD;&#xA;4. Most triangles should have 6 vertices used (3 unique vertices, so 3 pairs). The triangles which have 3 vertices (no duplicate vertex indexes) have no adjacent tet and so are boundary triangles.&#xD;&#xA;&#xD;&#xA;5. Rebuild a triangle surface using just the boundary triangles.&#xD;&#xA;&#xD;&#xA;Robustness is important, any cavities within the tet mesh will also be identified as boundary surfaces, however ime you can be quite liberal with equality tolerance when sharing vertices (checking which vertices are equal)." ContentLicense="CC BY-SA 4.0" />
  <row Id="40050" PostHistoryTypeId="5" PostId="13341" RevisionGUID="e043f549-e138-4aae-b19b-bce1d5f8f9a1" CreationDate="2023-03-03T15:46:25.700" UserId="9438" Comment="added 19 characters in body" Text="You can obtain a boundary surface of a tet mesh by identifying which tet faces are used once in a tet mesh of shared vertices. These by definition are the triangles of the tet mesh boundary surface. &#xD;&#xA;&#xD;&#xA;All 'interior' faces will be used by at most two tetrahedrons. All 'exterior' (boundary surface) faces will be used only once.&#xD;&#xA;&#xD;&#xA;1. Share the vertices of the tet mesh.&#xD;&#xA;&#xD;&#xA;2. Create a list of all the triangles (faces) in the tet mesh (each tet has 4 faces, and since tet mesh uses shared vertices, each tet will have 4 vertices).&#xD;&#xA;&#xD;&#xA;3. Create a list of vertex usage wrt to triangles. i.e a list of vertices for each triangle.&#xD;&#xA;&#xD;&#xA;4. Most triangles should have 6 vertices used (3 unique vertices, so 3 pairs). The triangles which have 3 vertices (no duplicate vertex indexes) have no adjacent tet and so are boundary triangles.&#xD;&#xA;&#xD;&#xA;5. Rebuild a triangle surface using just the boundary triangles.&#xD;&#xA;&#xD;&#xA;Robustness is important, any cavities within the tet mesh will also be identified as boundary surfaces, however ime you can be quite liberal with equality tolerance when sharing vertices (checking which vertices are equal)." ContentLicense="CC BY-SA 4.0" />
  <row Id="40051" PostHistoryTypeId="2" PostId="13342" RevisionGUID="9c303b17-037d-45c9-861a-22d1ab21c58d" CreationDate="2023-03-03T16:38:20.843" UserId="19664" Text="I have searched around in a lot of places but I have yet to find some place that explains 3D file formats in a way that aligns with the model I have right now. I have a simple problem (I think) but it's hard to get through all the file format documentation and to understand what the data actually resembles.&#xD;&#xA;&#xD;&#xA;Let's say one would have the following raw data in a data structure that resembles the below:&#xD;&#xA; - A index list, of numbers &#xD;&#xA;    - `int[]`&#xD;&#xA; - A list of objects containing vertices for a mesh, with their normals and texture coordinates&#xD;&#xA;    - ```{vertices: vec3[], normals: vec3[], UV: {u: float, v: float}}[]```&#xD;&#xA; - A list of pixels &#xD;&#xA;    - `float[]`&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;How would one go about turning this data structure into a popular file format? I don't know where to begin. GlTF would have my preference if that's doable/possible." ContentLicense="CC BY-SA 4.0" />
  <row Id="40053" PostHistoryTypeId="1" PostId="13342" RevisionGUID="9c303b17-037d-45c9-861a-22d1ab21c58d" CreationDate="2023-03-03T16:38:20.843" UserId="19664" Text="How does one construct a 3D file format from pixels and vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40054" PostHistoryTypeId="3" PostId="13342" RevisionGUID="9c303b17-037d-45c9-861a-22d1ab21c58d" CreationDate="2023-03-03T16:38:20.843" UserId="19664" Text="|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40055" PostHistoryTypeId="2" PostId="13343" RevisionGUID="f9cacee1-bbac-4f5a-8c0b-f079daf456e9" CreationDate="2023-03-03T22:00:39.320" UserId="7952" Text="The list of pixels would typically be encoded as one of the popular image formats like ktx if it is going to be consumed by other rendering programs, or jpg if it is just for viewing. The vertices, normals and UV values would be formatted into whatever file format you desire to output.&#xD;&#xA;&#xD;&#xA;This means picking a file format, like obj which is a nice simple format. &#xD;&#xA;&#xD;&#xA;Basically a program would output the &quot;pixels&quot; as texture data, the other data formatted to the file type chosen and the file would &quot;refer&quot; to the texture data. &#xD;&#xA;&#xD;&#xA;On the other hand some formats include the &quot;pixels&quot; directly in the format.&#xD;&#xA;&#xD;&#xA;There are libraries out there that can help, or you can write your own encoder.&#xD;&#xA;&#xD;&#xA;As Nicol Bolas pointed out it is difficult to give a more complete answer without knowing more details about the data and the file format.&#xD;&#xA;&#xD;&#xA;Are you coding this up or is it from one of the popular rendering programs out there?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40058" PostHistoryTypeId="2" PostId="13344" RevisionGUID="a2261704-462a-49e3-8dc8-ee32b13bbcac" CreationDate="2023-03-04T01:37:46.980" UserId="445" Text="Here is an overview of how you would go about producing an glTF asset from your data.&#xD;&#xA;&#xD;&#xA;First, write your index and vertex data arrays into files.&#xD;&#xA;&#xD;&#xA;* They can be all the same file, but for the conceptually simplest case, make them separate files.&#xD;&#xA;* You write the integers or floats as raw bytes, not text or any other format. This is just like you would pass the same data to a GPU buffer, **except** that they must be *little endian* integers (that is, swap the order of the bytes in each integer if your program is compiled for a big-endian processor; this is rare but possible).&#xD;&#xA;&#xD;&#xA;Your “pixels” — a texture for the object, I assume — should be written into a image file (PNG, JPEG, or a compressed texture format specified in a glTF extension).&#xD;&#xA;&#xD;&#xA;Then, you create the glTF file itself, which is a JSON structure that **describes how to use the contents of the above binary files.**&#xD;&#xA;&#xD;&#xA;The glTF file will specify that the indices are indices, and which one of the files contains vertex positions and which one contains normals, using “attributes” and “accessors”, and put them together into a “mesh”. It may also contain “node”, “scene”, “camera”, and “animation” objects, describing more about what to _do_ with the mesh, but these are all optional.&#xD;&#xA;&#xD;&#xA;There are a lot of details to glTF, but this is fundamentally all there is to it: write out your numerical data to binary files, then write out the glTF that describes the structure of those files. (It's also possible to pack all the data into a single `.glb` file.)&#xD;&#xA;&#xD;&#xA;Now that I've given you the big picture, I hope you will be able to able to figure out all the concrete details by following the [glTF specification](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html) and checking your work with a glTF scene viewer and a validator. When I was doing this, I found the [glTF Tools Extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=cesium.gltf-vscode) very useful — it does both preview and validation." ContentLicense="CC BY-SA 4.0" />
  <row Id="40060" PostHistoryTypeId="2" PostId="13345" RevisionGUID="cecc84b8-d391-4207-9a5b-c2dd1aabec7d" CreationDate="2023-03-04T08:56:42.607" UserId="19667" Text="I have a monitor with a resolution of 1360x768 (16:9), When I set the resolution to 1280x768 (5:3), 1024x768 (4:3), 800x600 (4:3), even 1920x1080 (16:9) it completely covers the screen and the monitor does not go black from the left, right, top and bottom.&#xD;&#xA;But when I set it to 1280x720 (16:9), the screen goes black from top and bottom.&#xD;&#xA;Now I have some questions&#xD;&#xA;How do pixels merge together?&#xD;&#xA;Why didn't the screen go black from the left and right in the 1280x768 (5:3), 1024x768 (4:3) resolutions?&#xD;&#xA;Why didn't the screen go black from the left, right, top and bottom in the 800x600 (4:3) resolution?&#xD;&#xA;Why in 1280x720 (16:9) resolution, the full screen was not covered and the pixels were black from the top and bottom?&#xD;&#xA;How in a monitor with a 16:9 aspect ratio, resolutions with aspect ratio 5:3 and 4:3 were covered full screen?&#xD;&#xA;How in a monitor with a 16:9 aspect ratio, the resolution with an aspect ratio of 16:9 does not cover the full screen?&#xD;&#xA;And what about the 1920x1080 (16:9) resolution? Are some pixels removed?&#xD;&#xA;OS: Windows 11&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40062" PostHistoryTypeId="1" PostId="13345" RevisionGUID="cecc84b8-d391-4207-9a5b-c2dd1aabec7d" CreationDate="2023-03-04T08:56:42.607" UserId="19667" Text="What happens when we select lower resolutions on a high-resolution monitor?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40063" PostHistoryTypeId="3" PostId="13345" RevisionGUID="cecc84b8-d391-4207-9a5b-c2dd1aabec7d" CreationDate="2023-03-04T08:56:42.607" UserId="19667" Text="|opengl|color|pixel-graphics|pixels|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40064" PostHistoryTypeId="2" PostId="13346" RevisionGUID="56d30ce2-ed92-4051-a7d2-7453403b0cb3" CreationDate="2023-03-04T09:22:07.377" UserId="19668" Text="i have a problem with RizomUV 2022.0. When program starts, it comes up with pop-up &quot;OpenGL 3.0 is not supported by the OpenGL driver&quot;, so i can't import any geometry and work. I temporary using **integrated graphics** and dont understand, there is a problem with unsupported OpenGL version or integrated graphics driver? Should i try to install older (before 3.0) version of OpenGL, if yes where i can find it?&#xD;&#xA;Thank you" ContentLicense="CC BY-SA 4.0" />
  <row Id="40066" PostHistoryTypeId="1" PostId="13346" RevisionGUID="56d30ce2-ed92-4051-a7d2-7453403b0cb3" CreationDate="2023-03-04T09:22:07.377" UserId="19668" Text="OpenGL 3.0 is not supported by the OpenGL driver - RizomUV" ContentLicense="CC BY-SA 4.0" />
  <row Id="40067" PostHistoryTypeId="3" PostId="13346" RevisionGUID="56d30ce2-ed92-4051-a7d2-7453403b0cb3" CreationDate="2023-03-04T09:22:07.377" UserId="19668" Text="|opengl|uv-mapping|driver|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40068" PostHistoryTypeId="50" PostId="10879" RevisionGUID="dc5b48f7-03a6-4e51-9fef-23bff78f4715" CreationDate="2023-03-04T12:04:35.673" UserId="-1" />
  <row Id="40069" PostHistoryTypeId="5" PostId="13344" RevisionGUID="e51abc79-f80d-474e-b4fc-7676b20555c2" CreationDate="2023-03-04T15:22:16.033" UserId="445" Comment="added 18 characters in body" Text="Here is an overview of how you would go about producing an glTF asset from your data.&#xD;&#xA;&#xD;&#xA;First, write your index and vertex data arrays into files.&#xD;&#xA;&#xD;&#xA;* They can be all the same file, but for the conceptually simplest case, make them separate files.&#xD;&#xA;* You write the integers or floats as raw bytes, not text or any other format, with no metadata. This is just like you would pass the same data to a GPU buffer, **except** that they must be *little endian* integers (that is, swap the order of the bytes in each integer if your program is compiled for a big-endian processor; this is rare but possible).&#xD;&#xA;&#xD;&#xA;Your “pixels” — a texture for the object, I assume — should be written into a image file (PNG, JPEG, or a compressed texture format specified in a glTF extension).&#xD;&#xA;&#xD;&#xA;Then, you create the glTF file itself, which is a JSON structure that **describes how to use the contents of the above binary files.**&#xD;&#xA;&#xD;&#xA;The glTF file will specify that the indices are indices, and which one of the files contains vertex positions and which one contains normals, using “attributes” and “accessors”, and put them together into a “mesh”. It may also contain “node”, “scene”, “camera”, and “animation” objects, describing more about what to _do_ with the mesh, but these are all optional.&#xD;&#xA;&#xD;&#xA;There are a lot of details to glTF, but this is fundamentally all there is to it: write out your numerical data to binary files, then write out the glTF that describes the structure of those files. (It's also possible to pack all the data into a single `.glb` file.)&#xD;&#xA;&#xD;&#xA;Now that I've given you the big picture, I hope you will be able to able to figure out all the concrete details by following the [glTF specification](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html) and checking your work with a glTF scene viewer and a validator. When I was doing this, I found the [glTF Tools Extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=cesium.gltf-vscode) very useful — it does both preview and validation." ContentLicense="CC BY-SA 4.0" />
  <row Id="40070" PostHistoryTypeId="2" PostId="13347" RevisionGUID="ee4368ad-a21d-4f3e-bffc-25e777f8b8f5" CreationDate="2023-03-04T16:17:36.393" UserId="19523" Text="I might be wrong here, but the &quot;up&quot; vector must be linearly independent of the light direction in order to create a proper 3-dimensional light space. When the light position is $(0,6,0)$, the light direction becomes $(0,-6,0)$ which is parallell with the &quot;up&quot; vector $(0,1,0)$. Note that the cross-product between two parallell vectors maps to the zero vector, so the resulting light space becomes 1 dimensional." ContentLicense="CC BY-SA 4.0" />
  <row Id="40072" PostHistoryTypeId="2" PostId="13348" RevisionGUID="087f0517-d1e4-4302-8698-b813bf56d444" CreationDate="2023-03-04T19:47:57.897" UserId="19671" Text="I'm an embedded developer here with very little experience in computer graphics. I'm currently working on a GUI that can display a calculated inertial solution at run time. I have hardware that can send an IMU's attitude (pitch, roll, and heading angles) to a PC. Currently I can display those numbers on the screen in real time, which change as I move the IMU in my hand. However, at the moment they are only numbers on a screen. &#xD;&#xA;&#xD;&#xA;I'm wanting to take it to the next level and display 3 orthogonal vectors rotating around a fixed reference frame (see screenshot attached). This rotation would take place in real time. The entire inertial solution is already calculated elsewhere, and outputs the 3 Euler angles required for the rotation. As far as the math goes, I think I'm moderately comfortable with the rotation matrix required here, I just don't know the best way to go about implementing this in terms of what software/libraries/programs to use. I also don't know if I'm over trivializing the effort here. Can someone point me in the right direction on how to implement this on the graphics side of things? &#xD;&#xA;[![Real time inertial solution rotation displayed ][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2v3hY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40074" PostHistoryTypeId="1" PostId="13348" RevisionGUID="087f0517-d1e4-4302-8698-b813bf56d444" CreationDate="2023-03-04T19:47:57.897" UserId="19671" Text="How to display real time 3-D orthogonal vector rotations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40075" PostHistoryTypeId="3" PostId="13348" RevisionGUID="087f0517-d1e4-4302-8698-b813bf56d444" CreationDate="2023-03-04T19:47:57.897" UserId="19671" Text="|rendering|3d|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40076" PostHistoryTypeId="50" PostId="10154" RevisionGUID="470723a6-c34b-4d68-ba9d-3b5ae1d50f71" CreationDate="2023-03-05T12:07:15.813" UserId="-1" />
  <row Id="40077" PostHistoryTypeId="2" PostId="13349" RevisionGUID="ed7ed3be-a993-4109-a6dc-6c944045177f" CreationDate="2023-03-05T19:25:28.057" UserId="18898" Text="&#xD;&#xA;I'm supposed to compute partial derivatives for 3D volume rendering (in ray tracing). I'm bad at math and so I can't understand what $f$ is in my case. In reviewing examples, I'm seeing the $f$ function being provided. Like in the Stewart Calculus [textbook][1], the first given example defines a function $(,)=^2−3+2^2−4+5−12$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Basic Computation**&#xD;&#xA;&#xD;&#xA;I'm told that we have $f(x)$ (black squiggly)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then for the derivative at any point on $x$, say $x_i$, I've been told I can use:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]/dx$. &#xD;&#xA;&#xD;&#xA;I'm told $dx$ is constant, so it is dropped:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]$. &#xD;&#xA;&#xD;&#xA;But what is $f$?&#xD;&#xA;&#xD;&#xA;What if I have $x_i=2$, for example? Or any number, since that *is* the info I do know. Please explain what I do, or how I ascertain $f$. &#xD;&#xA;&#xD;&#xA;**Working in 3D**&#xD;&#xA;&#xD;&#xA;Once I understand the basics, I need to compute the values for 3D, meaning I need partial derivatives for $x$, $y$ and $z$. I've been given the formulas to achieve this:&#xD;&#xA;&#xD;&#xA;$\frac{}{} =\frac{1}{2}(f(x_{i+1}, y_j, z_k,) - f(x_{i-1}, y_j, z_k))$&#xD;&#xA;$\frac{}{y} =\frac{1}{2}(f(x_i, y_{j+1}, z_k,) - f(x_i, y_{j-1}, z_k))$&#xD;&#xA;$\frac{}{z} =\frac{1}{2}(f(x_i, y_j, z_k,) - f(x_i, y_j, z_{k-1}))$&#xD;&#xA;&#xD;&#xA;I have the required $x$, $y$ and $z$ ranges, so if I can understand the math, my goal is compute the three above values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.libretexts.org/Bookshelves/Calculus/Map%3A_Calculus__Early_Transcendentals_(Stewart)/14%3A_Partial_Derivatives/14.03%3A_Partial_Derivatives&#xD;&#xA;  [2]: https://i.stack.imgur.com/hgy96.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40079" PostHistoryTypeId="1" PostId="13349" RevisionGUID="ed7ed3be-a993-4109-a6dc-6c944045177f" CreationDate="2023-03-05T19:25:28.057" UserId="18898" Text="How to compute discrete partial derivatives in 3D" ContentLicense="CC BY-SA 4.0" />
  <row Id="40080" PostHistoryTypeId="3" PostId="13349" RevisionGUID="ed7ed3be-a993-4109-a6dc-6c944045177f" CreationDate="2023-03-05T19:25:28.057" UserId="18898" Text="|raytracing|mathematics|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40081" PostHistoryTypeId="5" PostId="13349" RevisionGUID="b800e043-a802-4ce9-bc89-ed5ce6b61eea" CreationDate="2023-03-05T19:34:58.790" UserId="18898" Comment="Typo" Text="&#xD;&#xA;I'm supposed to compute partial derivatives for 3D volume rendering (in ray tracing). I'm bad at math and so I can't understand what $f$ is in my case. In reviewing examples, I'm seeing the $f$ function being provided. Like in the Stewart Calculus [textbook][1], the first given example defines a function $(,)=^2−3+2^2−4+5−12$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Basic Computation**&#xD;&#xA;&#xD;&#xA;I'm told that we have $f(x)$ (black squiggly)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then for the derivative at any point on $x$, say $x_i$, I've been told I can use:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]/dx$. &#xD;&#xA;&#xD;&#xA;I'm told $dx$ is constant, so it is dropped:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]$. &#xD;&#xA;&#xD;&#xA;But what is $f$?&#xD;&#xA;&#xD;&#xA;What if I have $x_i=2$, for example? Or any number, since that *is* the info I do know. Please explain what I do, or how I ascertain $f$. &#xD;&#xA;&#xD;&#xA;**Working in 3D**&#xD;&#xA;&#xD;&#xA;Once I understand the basics, I need to compute the values for 3D, meaning I need partial derivatives for $x$, $y$ and $z$. I've been given the formulas to achieve this:&#xD;&#xA;&#xD;&#xA;$\frac{}{} =\frac{1}{2}(f(x_{i+1}, y_j, z_k,) - f(x_{i-1}, y_j, z_k))$&#xD;&#xA;$\frac{}{y} =\frac{1}{2}(f(x_i, y_{j+1}, z_k,) - f(x_i, y_{j-1}, z_k))$&#xD;&#xA;$\frac{}{z} =\frac{1}{2}(f(x_i, y_j, z_{k+1}) - f(x_i, y_j, z_{k-1}))$&#xD;&#xA;&#xD;&#xA;I have the required $x$, $y$ and $z$ ranges, so if I can understand the math, my goal is compute the three above values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.libretexts.org/Bookshelves/Calculus/Map%3A_Calculus__Early_Transcendentals_(Stewart)/14%3A_Partial_Derivatives/14.03%3A_Partial_Derivatives&#xD;&#xA;  [2]: https://i.stack.imgur.com/hgy96.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40082" PostHistoryTypeId="5" PostId="13349" RevisionGUID="192a485c-fc50-497e-bc77-5291459e4c05" CreationDate="2023-03-05T19:49:03.507" UserId="18898" Comment="added 6 characters in body" Text="&#xD;&#xA;I'm supposed to compute partial derivatives for 3D volume rendering (in ray tracing). I'm bad at math and so I can't understand what $f$ is in my case. In reviewing examples, I'm seeing the $f$ function being provided. Like in the Stewart Calculus [textbook][1], the first given example defines a function $(,)=^2−3+2^2−4+5−12$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Basic Computation in 1D**&#xD;&#xA;&#xD;&#xA;I'm told that we have $f(x)$ (black squiggly)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then for the derivative at any point on $x$, say $x_i$, I've been told I can use:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]/dx$. &#xD;&#xA;&#xD;&#xA;I'm told $dx$ is constant, so it is dropped:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]$. &#xD;&#xA;&#xD;&#xA;But what is $f$?&#xD;&#xA;&#xD;&#xA;What if I have $x_i=2$, for example? Or any number, since that *is* the info I do know. Please explain what I do, or how I ascertain $f$. &#xD;&#xA;&#xD;&#xA;**Working in 3D**&#xD;&#xA;&#xD;&#xA;Once I understand the basics, I need to compute the values for 3D, meaning I need partial derivatives for $x$, $y$ and $z$. I've been given the formulas to achieve this:&#xD;&#xA;&#xD;&#xA;$\frac{}{} =\frac{1}{2}(f(x_{i+1}, y_j, z_k,) - f(x_{i-1}, y_j, z_k))$&#xD;&#xA;$\frac{}{y} =\frac{1}{2}(f(x_i, y_{j+1}, z_k,) - f(x_i, y_{j-1}, z_k))$&#xD;&#xA;$\frac{}{z} =\frac{1}{2}(f(x_i, y_j, z_{k+1}) - f(x_i, y_j, z_{k-1}))$&#xD;&#xA;&#xD;&#xA;I have the required $x$, $y$ and $z$ ranges, so if I can understand the math, my goal is compute the three above values.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.libretexts.org/Bookshelves/Calculus/Map%3A_Calculus__Early_Transcendentals_(Stewart)/14%3A_Partial_Derivatives/14.03%3A_Partial_Derivatives&#xD;&#xA;  [2]: https://i.stack.imgur.com/hgy96.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40083" PostHistoryTypeId="5" PostId="13349" RevisionGUID="422405d8-a72e-4492-9364-9ae6a0a1529a" CreationDate="2023-03-05T20:38:52.673" UserId="18898" Comment="add source material" Text="&#xD;&#xA;I'm supposed to compute partial derivatives for 3D volume rendering (in ray tracing). I'm bad at math and so I can't understand what $f$ is in my case. In reviewing examples, I'm seeing the $f$ function being provided. Like in the Stewart Calculus [textbook][1], the first given example defines a function $(,)=^2−3+2^2−4+5−12$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**My Basic Computation in 1D**&#xD;&#xA;&#xD;&#xA;I'm told that we have $f(x)$ (black squiggly)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Then for the derivative at any point on $x$, say $x_i$, I've been told I can use:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]/dx$. &#xD;&#xA;&#xD;&#xA;I'm told $dx$ is constant, so it is dropped:&#xD;&#xA;&#xD;&#xA;$f`(x_i) = df(x_i)/dx = [f(x_i) - f(x_i-1)]$. &#xD;&#xA;&#xD;&#xA;But what is $f$?&#xD;&#xA;&#xD;&#xA;What if I have $x_i=2$, for example? Or any number, since that *is* the info I do know. Please explain what I do, or how I ascertain $f$. &#xD;&#xA;&#xD;&#xA;**Working in 3D**&#xD;&#xA;&#xD;&#xA;Once I understand the basics, I need to compute the values for 3D, meaning I need partial derivatives for $x$, $y$ and $z$. I've been given the formulas to achieve this:&#xD;&#xA;&#xD;&#xA;$\frac{}{} =\frac{1}{2}(f(x_{i+1}, y_j, z_k,) - f(x_{i-1}, y_j, z_k))$&#xD;&#xA;$\frac{}{y} =\frac{1}{2}(f(x_i, y_{j+1}, z_k,) - f(x_i, y_{j-1}, z_k))$&#xD;&#xA;$\frac{}{z} =\frac{1}{2}(f(x_i, y_j, z_{k+1}) - f(x_i, y_j, z_{k-1}))$&#xD;&#xA;&#xD;&#xA;I have the required $x$, $y$ and $z$ ranges, so if I can understand the math, my goal is compute the three above values.&#xD;&#xA;&#xD;&#xA;Note: based on this [paper][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://math.libretexts.org/Bookshelves/Calculus/Map%3A_Calculus__Early_Transcendentals_(Stewart)/14%3A_Partial_Derivatives/14.03%3A_Partial_Derivatives&#xD;&#xA;  [2]: https://i.stack.imgur.com/hgy96.jpg&#xD;&#xA;  [3]: https://graphics.stanford.edu/papers/volume-cga88/volume.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="40085" PostHistoryTypeId="2" PostId="13350" RevisionGUID="67eaf0c5-a49b-4ada-bcad-46c9164273a9" CreationDate="2023-03-06T08:24:03.423" UserId="19678" Text="I am writing a simple material system for a game.&#xD;&#xA;Each material can have a specular value (phong) that is translated into &quot;smoothness&quot; via environment map.&#xD;&#xA;&#xD;&#xA;Similar to PBR, I compute a fresnel term that modulates the &quot;smoothness&quot;, to have reflections at gazing angles.&#xD;&#xA;&#xD;&#xA;The problem is that I seem to get a facetted look when I use the HLSL function `SampleBias` to modulate the mipmap selection in regards to the fresnel term.&#xD;&#xA;&#xD;&#xA;My shader looks roughly like this:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float roughness;&#xD;&#xA;float fresnel = pow(1 - saturate(dot(-viewDir, normal)), 3);&#xD;&#xA;roughness = saturate(1 - saturate(s * specularBoost));&#xD;&#xA;float environmentBias = roughness * 10; // 10 is the number of mipmaps for a 512x512px texture&#xD;&#xA;float3 r = normalize(reflect(viewDir, normal));&#xD;&#xA;float m = 2. * sqrt(&#xD;&#xA;pow(r.x, 2.) +&#xD;&#xA;pow(r.y, 2.) +&#xD;&#xA;pow(r.z + 1., 2.)&#xD;&#xA;);&#xD;&#xA;float2 uv = r.xy / m + 0.5f; // environment map is a sphere map, not a cube/equirectangular map&#xD;&#xA;float4 environmentMap = environment.SampleBias(texSampler, uv,environmentBias);&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;When I use `SampleBias`&#xD;&#xA;I receive a facetted look (vertex normals are 100% shared and normalized in the Pixel shader!)  &#xD;&#xA;It looks like the UVs are shifted across the polygons&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I use `SampleLevel` directly, I receive a smooth look:  &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have no clue what I am doing wrong.  &#xD;&#xA;&#xD;&#xA;This is roughness:  &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;calculated UVs:  &#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;`ddx(uv)*0.5+0.5` and `ddy(uv)*0.5+0.5` look like a constant yellow to me&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1oBT5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RQA1P.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/t3OLU.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/9lax9.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40087" PostHistoryTypeId="1" PostId="13350" RevisionGUID="67eaf0c5-a49b-4ada-bcad-46c9164273a9" CreationDate="2023-03-06T08:24:03.423" UserId="19678" Text="Facetted look when using SampleBias" ContentLicense="CC BY-SA 4.0" />
  <row Id="40088" PostHistoryTypeId="3" PostId="13350" RevisionGUID="67eaf0c5-a49b-4ada-bcad-46c9164273a9" CreationDate="2023-03-06T08:24:03.423" UserId="19678" Text="|rendering|hlsl|pixel-shader|mipmap|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40089" PostHistoryTypeId="2" PostId="13351" RevisionGUID="2cfdb452-2aab-44fb-be04-bd9b157faa73" CreationDate="2023-03-06T09:02:54.687" UserId="19523" Text="You can't drop $dx$, since it &quot;normalizes&quot; the difference in function value $df$. Numerically, you assign a value to $dx$, vall it $\Delta x$. Then you approximate the derivative as $\frac{f(x+\Delta x)-f(x)}{\Delta x}$.&#xD;&#xA;&#xD;&#xA;The paper suggests that $f$ is already known as input data, if I'm not mistaken.&#xD;&#xA;&#xD;&#xA;In a grid, you only know $f$ in determined coordinates (or cells). In one dimension, you function might be defined in an interval $[a,b]$. This interval is discretized into $N$ cells, indexed using $i$. So you values are $\{ f_i \}_{i=0}^N$.&#xD;&#xA;&#xD;&#xA;First, understand how your points are distributed. Including the boundary: $x_i = a + i \frac{b-a}{N-1}$ or only looking at the cell center: $x_i = a + \frac{b-a}{2N} + i \frac{b-a}{N}$. For these two cases, the distance between two gridpoints where $f$ is known is different. But lets assume the first case, then $dx \approx \Delta x = \frac{b-a}{N-1}$. This becomes your normalizing distance.&#xD;&#xA;&#xD;&#xA;Then you must approximate the derivative. Note that your boundaries are &quot;problematic&quot; and one must be handled separately. We can approximate the first order derivative for $1 \leq i&lt;N-1$ as: $\frac{df(x_i)}{dx} \approx \frac{f_{i+1}-f_i}{\Delta x}$. As you might figure out, when $i=N$ we can't index $i+1$. So we use the reverse derivative: $\frac{df(x_i)}{dx} \approx \frac{f_N-f_{N-1}}{\Delta x}$. Note that you might want higher order derivatives instead to avoid artifacts.&#xD;&#xA;&#xD;&#xA;In higher dimensions you apply the same logic on each separate axis or index. If $f(\vec{x}): \mathbb{R}^3 \rightarrow \mathbb{R}$, then we will index $f$ as $f_{ijk}$ or whatever characters you want to use.&#xD;&#xA;&#xD;&#xA;Edit: corrected a mistake" ContentLicense="CC BY-SA 4.0" />
  <row Id="40091" PostHistoryTypeId="5" PostId="13350" RevisionGUID="aa573cce-bba7-4707-854f-8c4ca1b476fa" CreationDate="2023-03-06T10:29:52.120" UserId="19678" Comment="added 158 characters in body" Text="I am writing a simple material system for a game.&#xD;&#xA;Each material can have a specular value (phong) that is translated into &quot;smoothness&quot; via environment map.&#xD;&#xA;&#xD;&#xA;Similar to PBR, I compute a fresnel term that modulates the &quot;smoothness&quot;, to have reflections at gazing angles.&#xD;&#xA;&#xD;&#xA;The problem is that I seem to get a facetted look when I use the HLSL function `SampleBias` to modulate the mipmap selection in regards to the fresnel term.&#xD;&#xA;&#xD;&#xA;My shader looks roughly like this:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;float roughness;&#xD;&#xA;float fresnel = pow(1 - saturate(dot(-viewDir, normal)), 3);&#xD;&#xA;roughness = saturate(1 - saturate(s * specularBoost));&#xD;&#xA;float environmentBias = roughness * 10; // 10 is the number of mipmaps for a 512x512px texture&#xD;&#xA;float3 r = normalize(reflect(viewDir, normal));&#xD;&#xA;float m = 2. * sqrt(&#xD;&#xA;pow(r.x, 2.) +&#xD;&#xA;pow(r.y, 2.) +&#xD;&#xA;pow(r.z + 1., 2.)&#xD;&#xA;);&#xD;&#xA;float2 uv = r.xy / m + 0.5f; // environment map is a sphere map, not a cube/equirectangular map&#xD;&#xA;float4 environmentMap = environment.SampleBias(texSampler, uv,environmentBias);&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;When I use `SampleBias`&#xD;&#xA;I receive a facetted look (vertex normals are 100% shared and normalized in the Pixel shader!)  &#xD;&#xA;It looks like the UVs are shifted across the polygons&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;When I use `SampleLevel` directly, I receive a smooth look:  &#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have no clue what I am doing wrong.  &#xD;&#xA;&#xD;&#xA;This is roughness:  &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;calculated UVs:  &#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;`ddx(uv)*0.5+0.5` and `ddy(uv)*0.5+0.5` look like a constant yellow to me&#xD;&#xA;&#xD;&#xA;Edit:&#xD;&#xA;&#xD;&#xA;here is the whole thing with different colored mip maps.  &#xD;&#xA;SampleBias:  &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;SampleLevel:  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/1oBT5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/RQA1P.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/t3OLU.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/9lax9.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/zqHra.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/TigQ1.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40092" PostHistoryTypeId="5" PostId="13138" RevisionGUID="7de5583c-ba7a-43fa-9617-cbcc97e6335f" CreationDate="2023-03-06T14:49:50.593" UserId="9199" Comment="English + formatting" Text="I want to implement shadows in my already existing glmatrix-based project.&#xD;&#xA;You can see [my project's github][1] source. It is classic scebe object based structure. I have draw functions, I render recalls.&#xD;&#xA;&#xD;&#xA;By this [youtube tutorial][2] + [code][3], I figured that draw calls must be in order.&#xD;&#xA;&#xD;&#xA;  Chronology of draw calls:&#xD;&#xA;```&#xD;&#xA;   this.gl.enable(this.gl.DEPTH_TEST);&#xD;&#xA;   this.gl.disable(this.gl.BLEND);&#xD;&#xA;   this.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;   - draw all `non fbo` and `no blend`&#xD;&#xA;&#xD;&#xA;    state.gl.enable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(false);&#xD;&#xA;&#xD;&#xA;   - draw all `non fbo` and `blend`&#xD;&#xA;    &#xD;&#xA;   (this line is after draw func in main render) &#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    // moment after all (non fbo objects) draws.&#xD;&#xA;&#xD;&#xA;    state.gl.bindFramebuffer(state.gl.FRAMEBUFFER, null);&#xD;&#xA;    state.gl.viewport(0, 0, state.canvas.width, state.canvas.height);  &#xD;&#xA;&#xD;&#xA;    state.gl.clearColor(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    state.gl.clear(state.gl.COLOR_BUFFER_BIT | state.gl.DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    // Draw again...&#xD;&#xA;    state.gl.enable(state.gl.DEPTH_TEST);&#xD;&#xA;    state.gl.disable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA;&#xD;&#xA;     - draw **all** but `no blend`&#xD;&#xA;&#xD;&#xA;    // Leave on the depth test!&#xD;&#xA;    state.gl.enable(state.gl.BLEND);&#xD;&#xA;    state.gl.depthMask(false);&#xD;&#xA;&#xD;&#xA;     - draw **all** but `blend`&#xD;&#xA;&#xD;&#xA;    state.gl.depthMask(true);&#xD;&#xA; ```&#xD;&#xA;   &#xD;&#xA;Is this correct?&#xD;&#xA;&#xD;&#xA;Is it necessary to use `createRenderbuffer`?&#xD;&#xA;&#xD;&#xA;I dont understand why this operation is put into the draw loop:&#xD;&#xA;```js&#xD;&#xA;    // Set FBOs&#xD;&#xA;    state.app.objects.forEach(function(obj) {&#xD;&#xA;      if (obj.state.hasTexture &amp;&amp; obj.state.hasFbo) {&#xD;&#xA;        obj.state.fbo = state.fbo;&#xD;&#xA;      }&#xD;&#xA;    });&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/zlatnaspirala/matrix-engine&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=txcgqWdZwR8&amp;ab_channel=DavidParker&#xD;&#xA;  [3]: https://github.com/davidwparker/programmingtil-webgl/blob/master/0091-framebuffer-part-2/index.js" ContentLicense="CC BY-SA 4.0" />
  <row Id="40093" PostHistoryTypeId="24" PostId="13138" RevisionGUID="7de5583c-ba7a-43fa-9617-cbcc97e6335f" CreationDate="2023-03-06T14:49:50.593" Comment="Proposed by 9199 approved by 7952, 7724 edit id of 620" ContentLicense="CC BY-SA 4.0" />
  <row Id="40094" PostHistoryTypeId="2" PostId="13352" RevisionGUID="d393b43a-35b2-4d77-8da8-fc5fad806036" CreationDate="2023-03-06T15:41:23.193" UserId="9438" Text="I'm getting a TDR trigger after 4ms with a GL4.3 compute shader. tdrDelay is currently set to 30 secs, this obviously isn't long enough to get a timeout with the default Windows 11 tdrDelay value let alone my registery value, however the error message is code 7 (RTX A2000, drivers 528.24) which is the generic nVidia TDR occurance.&#xD;&#xA;&#xD;&#xA;If there was a bad loop (infiniting) or something, I appreciate this could trigger a timeout, however can TDR's be triggered if the shader crashes (bad data, out of bounds etc) well before the tdrDelay is reached?&#xD;&#xA;&#xD;&#xA;In the past I got different error messages if the shader crashes (this was on K2200D iirc, much old drivers, 3XX.XX), however the only error message I seem to get these days is a generic TDR error message (latest nVidia drivers)?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40096" PostHistoryTypeId="1" PostId="13352" RevisionGUID="d393b43a-35b2-4d77-8da8-fc5fad806036" CreationDate="2023-03-06T15:41:23.193" UserId="9438" Text="Do GL compute shaders trigger TDR if they crash. Not just timeout?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40097" PostHistoryTypeId="3" PostId="13352" RevisionGUID="d393b43a-35b2-4d77-8da8-fc5fad806036" CreationDate="2023-03-06T15:41:23.193" UserId="9438" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40098" PostHistoryTypeId="5" PostId="13341" RevisionGUID="0a0dbf02-ccac-4296-bfa4-e968bac92a56" CreationDate="2023-03-06T17:50:50.830" UserId="9438" Comment="added 1306 characters in body" Text="Unless the original surface mesh triangles are used by the resultant tet mesh, it is imposible (improbable) to obtain the original boundary surface (unless of course, original boundary surface was a convex hull). The original surface mesh triangles can only be encoded into the resultant tet grid, if boundary tetrahedron faces retain the original tessellation. Non-constrained Delaunay methods may edge flip, thus loosing the original surface tessellation.&#xD;&#xA;&#xD;&#xA;Non-constrained Delaunay methods always produce a convex hull (of the original pointset... 2D and 3D), so it sounds like the routine is working (you would get a convex hull back), but its the method used to generate the tet grid which prevents what you want in this case.&#xD;&#xA;&#xD;&#xA;So unfortunately, in this case you cannot since the tet mesh was created using Delaunay, and not Constrained-Delaunay.&#xD;&#xA;&#xD;&#xA;Alternative methods to construct unstructured grids such as Constrained-Delaunay and Advancing front use the original surface mesh as boundary conditions and so can retain/encode the original surface mesh which can be extracted using the method outlined below to obtain the original boundary surface tessellation.&#xD;&#xA;&#xD;&#xA;If using one of the other methods for generating a tet mesh which preserve/encode the boundary surface into the tet faces, you can obtain a boundary surface of a tet mesh by identifying which tet faces are used once in a tet mesh of shared vertices. These by definition are the triangles of the tet mesh boundary surface. &#xD;&#xA;&#xD;&#xA;All 'interior' faces will be used by at most two tetrahedrons. All 'exterior' (boundary surface) faces will be used only once.&#xD;&#xA;&#xD;&#xA;1. Share the vertices of the tet mesh.&#xD;&#xA;&#xD;&#xA;2. Create a list of all the triangles (faces) in the tet mesh (each tet has 4 faces, and since tet mesh uses shared vertices, each tet will have 4 vertices).&#xD;&#xA;&#xD;&#xA;3. Create a list of vertex usage wrt to triangles. i.e a list of vertices for each triangle.&#xD;&#xA;&#xD;&#xA;4. Most triangles should have 6 vertices used (3 unique vertices, so 3 pairs). The triangles which have 3 vertices (no duplicate vertex indexes) have no adjacent tet and so are boundary triangles.&#xD;&#xA;&#xD;&#xA;5. Rebuild a triangle surface using just the boundary triangles.&#xD;&#xA;&#xD;&#xA;Robustness is important, any cavities within the tet mesh will also be identified as boundary surfaces, however ime you can be quite liberal with equality tolerance when sharing vertices (checking which vertices are equal).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40099" PostHistoryTypeId="5" PostId="13341" RevisionGUID="3150c7a2-a979-4cb8-a0d0-fee7bfc4e4d5" CreationDate="2023-03-06T18:00:17.673" UserId="9438" Comment="added 89 characters in body" Text="Unless the original surface mesh triangles are used by the resultant tet mesh, it is imposible (improbable) to obtain the original boundary surface (unless of course, original boundary surface was a convex hull). The original surface mesh triangles can only be encoded into the resultant tet grid, if boundary tetrahedron faces retain the original tessellation. The Delaunay method you use to generate the tet mesh (Non-constrained) does not do this. Non-constrained Delaunay methods may edge flip, thus loosing the original surface tessellation.&#xD;&#xA;&#xD;&#xA;Non-constrained Delaunay methods always produce a convex hull (of the original pointset... 2D and 3D), so it sounds like the routine is working (you would get a convex hull back), but its the method used to generate the tet grid which prevents what you want in this case.&#xD;&#xA;&#xD;&#xA;So unfortunately, in this case you cannot since the tet mesh was created using Delaunay, and not Constrained-Delaunay.&#xD;&#xA;&#xD;&#xA;Alternative methods to construct unstructured grids such as Constrained-Delaunay and Advancing front use the original surface mesh as boundary conditions and so can retain/encode the original surface mesh which can be extracted using the method outlined below to obtain the original boundary surface tessellation.&#xD;&#xA;&#xD;&#xA;If using one of the other methods for generating a tet mesh which preserve/encode the boundary surface into the tet faces, you can obtain a boundary surface of a tet mesh by identifying which tet faces are used once in a tet mesh of shared vertices. These by definition are the triangles of the tet mesh boundary surface. &#xD;&#xA;&#xD;&#xA;All 'interior' faces will be used by at most two tetrahedrons. All 'exterior' (boundary surface) faces will be used only once.&#xD;&#xA;&#xD;&#xA;1. Share the vertices of the tet mesh.&#xD;&#xA;&#xD;&#xA;2. Create a list of all the triangles (faces) in the tet mesh (each tet has 4 faces, and since tet mesh uses shared vertices, each tet will have 4 vertices).&#xD;&#xA;&#xD;&#xA;3. Create a list of vertex usage wrt to triangles. i.e a list of vertices for each triangle.&#xD;&#xA;&#xD;&#xA;4. Most triangles should have 6 vertices used (3 unique vertices, so 3 pairs). The triangles which have 3 vertices (no duplicate vertex indexes) have no adjacent tet and so are boundary triangles.&#xD;&#xA;&#xD;&#xA;5. Rebuild a triangle surface using just the boundary triangles.&#xD;&#xA;&#xD;&#xA;Robustness is important, any cavities within the tet mesh will also be identified as boundary surfaces, however ime you can be quite liberal with equality tolerance when sharing vertices (checking which vertices are equal).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40100" PostHistoryTypeId="50" PostId="13258" RevisionGUID="3f4358ce-3de1-41a9-ab36-cc5aa17e2134" CreationDate="2023-03-06T18:07:55.970" UserId="-1" />
  <row Id="40101" PostHistoryTypeId="2" PostId="13353" RevisionGUID="5655e25d-bcf1-40f7-9a09-aecc266d8df3" CreationDate="2023-03-06T20:44:02.547" UserId="19633" Text="I keep reading about fresnel and there is one thing I don't fully understand.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;#### My understanding :&#xD;&#xA;Here is my understanding so far, so please correct me where I am wrong.&#xD;&#xA;&#xD;&#xA; 1. Fresnel is related to ior (eta) of the surface. Snell's law enable to know where the ray should &quot;go&quot; when going through a surface with different ior. Fresnel is of use to know how much light reflects / is transmitted.&#xD;&#xA; 2. Applying Schlick's approximation enables to know the proportion of the reflected vs the refracted light.&#xD;&#xA;&#xD;&#xA;#### Now, my question:&#xD;&#xA;When a ray of light touches a refractable surface (glass..), I apply the Schlick's approximation which gives a coefficient. &#xD;&#xA;&#xD;&#xA;But does that mean that I take the ray and calculate both its reflection and transmission angles; and then, given the fresnel coefficient, reshoot the ray in **both directions** (reflection and refraction) but with the power of each rays further attenuated with the coefficient. &#xD;&#xA;&#xD;&#xA;Or is it **only one** ray with reduced power ?&#xD;&#xA;&#xD;&#xA;All my readings don't make that point clear.&#xD;&#xA;&#xD;&#xA;#### Example&#xD;&#xA;For an incident ray touching the surface with a power of 1, and a fresnel coefficient of 0.5, both reflected and refracted rays will both be 0.5 before leaving the surface. &#xD;&#xA;&#xD;&#xA;Is my understanding correct?&#xD;&#xA;&#xD;&#xA;Thanks" ContentLicense="CC BY-SA 4.0" />
  <row Id="40103" PostHistoryTypeId="1" PostId="13353" RevisionGUID="5655e25d-bcf1-40f7-9a09-aecc266d8df3" CreationDate="2023-03-06T20:44:02.547" UserId="19633" Text="Fresnel and light reflection/refraction" ContentLicense="CC BY-SA 4.0" />
  <row Id="40104" PostHistoryTypeId="3" PostId="13353" RevisionGUID="5655e25d-bcf1-40f7-9a09-aecc266d8df3" CreationDate="2023-03-06T20:44:02.547" UserId="19633" Text="|reflection|refraction|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40105" PostHistoryTypeId="50" PostId="13262" RevisionGUID="710c8b54-432b-47d5-bd79-dc6db4506fe8" CreationDate="2023-03-06T21:00:55.087" UserId="-1" />
  <row Id="40107" PostHistoryTypeId="10" PostId="13342" RevisionGUID="840c56dd-8cc8-4cae-8c59-831972a6c744" CreationDate="2023-03-07T00:32:52.310" UserId="482" Comment="103" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6,&quot;DisplayName&quot;:&quot;Christian Rau&quot;},{&quot;Id&quot;:2654,&quot;DisplayName&quot;:&quot;Nicol Bolas&quot;},{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}]}" />
  <row Id="40108" PostHistoryTypeId="5" PostId="13346" RevisionGUID="e0bbb54b-6d3d-4f07-8eab-0213c8b9cb0f" CreationDate="2023-03-07T00:34:20.330" UserId="9199" Comment="Typo fixes" Text="I have a problem with RizomUV 2022.0. When the program starts, it comes up with pop-up &quot;OpenGL 3.0 is not supported by the OpenGL driver&quot;, so I can't import any geometry and work. I'm temporary using **integrated graphics** and don't understand, is there a problem with unsupported OpenGL version or integrated graphics driver? Should I try to install an older (before 3.0) version of OpenGL? If yes, where i can find it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40109" PostHistoryTypeId="24" PostId="13346" RevisionGUID="e0bbb54b-6d3d-4f07-8eab-0213c8b9cb0f" CreationDate="2023-03-07T00:34:20.330" Comment="Proposed by 9199 approved by 7952, 482 edit id of 619" ContentLicense="CC BY-SA 4.0" />
  <row Id="40110" PostHistoryTypeId="50" PostId="13022" RevisionGUID="06d5b4eb-795b-4718-a272-fb6ac6f841f1" CreationDate="2023-03-07T02:00:20.047" UserId="-1" />
  <row Id="40111" PostHistoryTypeId="2" PostId="13354" RevisionGUID="ded85388-7612-4636-a80e-963c1c9143c9" CreationDate="2023-03-07T10:44:03.740" UserId="9438" Text="Yes, turns out an index out of range index was the culprit when attempting writing to a TBO in the last batch of a workgroup invocation.&#xD;&#xA;&#xD;&#xA;I long for the day when compute shaders have better dedicated tools for debugging and drivers supply more descriptive runtime error messages." ContentLicense="CC BY-SA 4.0" />
  <row Id="40113" PostHistoryTypeId="2" PostId="13355" RevisionGUID="ee2e6384-372e-48bc-acfd-dae29dc80882" CreationDate="2023-03-07T11:03:42.503" UserId="19683" Text="I am getting&#xD;&#xA;&#xD;&#xA;C:\Users\rasmu\AppData\Local\Temp\ccwOn3mM.o:main.c:(.text+0x11f): undefined reference to `SDL_setRenderDrawColor'&#xD;&#xA;&#xD;&#xA;C:\Users\rasmu\AppData\Local\Temp\ccwOn3mM.o:main.c:(.text+0x155): undefined reference to `SDL_setRenderDrawColor'&#xD;&#xA;&#xD;&#xA;when i try to compile my basic SDL2 c program.&#xD;&#xA;My code is &#xD;&#xA;```&#xD;&#xA;#define ASSERT(_e, ...) if (!(_e)) { fprintf(stderr, __VA_ARGS__); exit(1); }&#xD;&#xA;#include &lt;SDL.h&gt;&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;stdbool.h&gt;&#xD;&#xA;#include &lt;stdint.h&gt;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;typedef float f32;&#xD;&#xA;typedef double f64;&#xD;&#xA;typedef uint8_t u8;&#xD;&#xA;typedef uint16_t u16;&#xD;&#xA;typedef uint32_t u32;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;const int SCREEN_WIDTH = 1280;&#xD;&#xA;const int SCREEN_HEIGHT = 720;&#xD;&#xA;const int FPS = 30;&#xD;&#xA;&#xD;&#xA;typedef struct {&#xD;&#xA;	SDL_Window* window;&#xD;&#xA;	SDL_Texture* texture;&#xD;&#xA;	SDL_Renderer* renderer;&#xD;&#xA;	u32* pixels;&#xD;&#xA;	bool quit;&#xD;&#xA;} state;&#xD;&#xA;&#xD;&#xA;u32* init_pixels();&#xD;&#xA;void put_pixel(state state);&#xD;&#xA;&#xD;&#xA;int main( int argc, char* args[]){&#xD;&#xA;	state state;&#xD;&#xA;	ASSERT(&#xD;&#xA;		!SDL_Init(SDL_INIT_VIDEO),&#xD;&#xA;		&quot;SDL failed to init: %s\n&quot;,&#xD;&#xA;		SDL_GetError()&#xD;&#xA;	);&#xD;&#xA;	state.window = &#xD;&#xA;		SDL_CreateWindow(&#xD;&#xA;			&quot;Game&quot;,&#xD;&#xA;			SDL_WINDOWPOS_CENTERED_DISPLAY(1),&#xD;&#xA;			SDL_WINDOWPOS_CENTERED_DISPLAY(1),&#xD;&#xA;			1280,&#xD;&#xA;			720,&#xD;&#xA;			SDL_WINDOW_ALLOW_HIGHDPI&#xD;&#xA;		);&#xD;&#xA;		&#xD;&#xA;	ASSERT(state.window, &quot;failed to create SDL window: %s\n&quot;, SDL_GetError());&#xD;&#xA;	state.pixels = malloc(SCREEN_WIDTH * SCREEN_HEIGHT * 4);&#xD;&#xA;&#xD;&#xA;	state.renderer =&#xD;&#xA;		SDL_CreateRenderer(&#xD;&#xA;			state.window,&#xD;&#xA;			-1, &#xD;&#xA;			NULL&#xD;&#xA;		);&#xD;&#xA;&#xD;&#xA;	SDL_setRenderDrawColor(state.renderer,0,0,0,255);&#xD;&#xA;	SDL_RenderClear(state.renderer);&#xD;&#xA;	SDL_setRenderDrawColor(state.renderer,255,255,255,255);&#xD;&#xA;	SDL_RenderDrawPoint(state.renderer,SCREEN_WIDTH/2,SCREEN_HEIGHT/2);&#xD;&#xA;	SDL_RenderPresent(state.renderer);&#xD;&#xA;&#xD;&#xA;	while(!state.quit){&#xD;&#xA;		SDL_Event ev;&#xD;&#xA;		while(SDL_PollEvent(&amp;ev)){&#xD;&#xA;			switch(ev.type){&#xD;&#xA;				case SDL_QUIT:&#xD;&#xA;					state.quit = true;&#xD;&#xA;					break;&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;		&#xD;&#xA;    &#xD;&#xA;	SDL_DestroyWindow(state.window);&#xD;&#xA;	free(state.pixels);&#xD;&#xA;	SDL_QUIT;&#xD;&#xA;	return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;And my make file looks like this&#xD;&#xA;```&#xD;&#xA;OBJS = main.c&#xD;&#xA;&#xD;&#xA;CC = gcc&#xD;&#xA;&#xD;&#xA;INCLUDE_PATHS = -IC:\mingw_dev_lib\include\SDL2&#xD;&#xA;&#xD;&#xA;LIBRARY_PATHS = -LC:\mingw_dev_lib\lib&#xD;&#xA;&#xD;&#xA;COMPILER_FLAGS = -w -Wl,-subsystem,windows&#xD;&#xA;&#xD;&#xA;LINKER_FLAGS = -lmingw32 -lSDL2main -lSDL2 &#xD;&#xA;&#xD;&#xA;OBJ_NAME = game&#xD;&#xA;&#xD;&#xA;all : $(OBJS)&#xD;&#xA;	$(CC) $(OBJS) $(INCLUDE_PATHS) $(LIBRARY_PATHS) $(COMPILER_FLAGS) -o $(OBJ_NAME) $(LINKER_FLAGS)&#xD;&#xA;```&#xD;&#xA;I do believe it has something to do with the linking of the SDL2 library but it seems weird since the SDL.h works fine but only when I have tried to use the SDL_setRenderDrawColor() function. I am quite new to SDL and linking libraries." ContentLicense="CC BY-SA 4.0" />
  <row Id="40115" PostHistoryTypeId="1" PostId="13355" RevisionGUID="ee2e6384-372e-48bc-acfd-dae29dc80882" CreationDate="2023-03-07T11:03:42.503" UserId="19683" Text="undefined reference to `SDL_setRenderDrawColor'" ContentLicense="CC BY-SA 4.0" />
  <row Id="40116" PostHistoryTypeId="3" PostId="13355" RevisionGUID="ee2e6384-372e-48bc-acfd-dae29dc80882" CreationDate="2023-03-07T11:03:42.503" UserId="19683" Text="|2d-graphics|pixel-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40117" PostHistoryTypeId="5" PostId="13297" RevisionGUID="f6edd6e7-cef1-47e7-8ee7-5c054b4218e7" CreationDate="2023-03-07T12:08:24.887" UserId="7952" Comment="added 628 characters in body" Text="A popular method of generating the mesh from an L system is called a &quot;Turtle Graphics&quot; system.&#xD;&#xA;&#xD;&#xA;In a turtle graphics system we imagine a turtle which starts at the root of the system reads a symbol from the L system and walks in a specific direction based on the symbol. The symbol itself is associated with a polygon and the entire system is seeded with a polygon from the root symbol.&#xD;&#xA;&#xD;&#xA;The polygons themselves can be generated algorithmically by the system and then modified for each generation of the plant or predefined such as a simple N sided circle. &#xD;&#xA;&#xD;&#xA;As the turtle marches through the L system each symbol gives it instructions on direction and how many steps to take. For example, a turtle may be instructed to move 3 steps in the up direction.&#xD;&#xA;&#xD;&#xA;The turtle starts at the seeded polygon, reads the symbol, takes a step and places the polygon for that symbol. Taking a step usually includes a &quot;turn&quot; this translates into a rotation matrix for the polygon being placed where the turtle represents the origin for the coordinate frame used to do the rotation and the turtles position becomes the translation. Then the two polygon's are connected. A simple and effective way to connect two polygons is: find the two nearest vertices, n and m, the generate vertex attributes in the order n,m,n+1 mod t,m+1 mod t...n+t mod t,m+t mod t where t is the total number of vertices. When t is not equal in the two polygons a combination of splitting the longest edge,  and connecting multiple vertices in n to a single vertex in m (or vica versa depending on the vertex count) can be used.&#xD;&#xA;&#xD;&#xA;Some simple checks should be run for each pair of polygons. 1) Make sure the polygons are planer. 2) Make sure the polygons are wound consistently 3) At connection time make sure all vertices in the &#xD;&#xA; polygon being placed are on the same side of the connecting polygon's plane. Vertices that pass through the plane will need to be adjusted so they are slightly above the plane of the other polygon.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Normally there is one main &quot;trunk&quot; for the turtle to follow, each branch is reinterpreted as a new turtle with a new seed polygon. Branch's can be integrated into the main structure by clipping each branch against the triangles of the main trunk. Some systems will allow branch's to intersect, others will do collision checking. Here again the can be special symbols that define the transition between the main structure and a branch, this allows for smooth transitions of UV coordinates.&#xD;&#xA;&#xD;&#xA;Leaves can be single symbols represented as a single polygon, or an entire L system with its own turtles which is slow to generate but the results are stunning. Yet another approach is to generate a handful of leaves and the L system associates a symbol with each leaf.&#xD;&#xA;&#xD;&#xA;Done correctly this results in a well defined structure. The root node can be closed off to make the polyhedron water tight." ContentLicense="CC BY-SA 4.0" />
  <row Id="40122" PostHistoryTypeId="2" PostId="13357" RevisionGUID="297b0e93-2039-47a5-b6cd-2dd988ed3ea9" CreationDate="2023-03-07T17:37:38.867" UserId="19684" Text="After rewatching Bisqwit's [starfield renderer video](https://www.youtube.com/watch?v=VL0oGct1S4Q), I've decided to try to rewrite the program in order to learn more about compute shaders and shader programming in general. My knowledge at this point is limited to moderately simple vertex and pixel shaders. The original program is a software renderer written in some variant of BASIC that draws each frame roughly like so:  &#xD;&#xA;```text/plain&#xD;&#xA;for every rendered star:&#xD;&#xA;    update the star's position in the world&#xD;&#xA;    calculate the star's position on the screen&#xD;&#xA;    calculate the star's size on the screen&#xD;&#xA;&#xD;&#xA;for every pixel of the screen:&#xD;&#xA;    for every star of the screen:&#xD;&#xA;        calculate the influence of the current star on the color of the current pixel&#xD;&#xA;    do dithering&#xD;&#xA;    draw the pixel in the resulting color&#xD;&#xA;```&#xD;&#xA;Obvious issues with that approach aside, I'm a bit lost w.r.t. the perspective calulations. Where would I do the them, on the CPU or GPU? What would be a suitable mechanism to prevent having to do the calculation multiple times over? I wasn't able to find one through my research, so every pointer toward the solution is appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="40124" PostHistoryTypeId="1" PostId="13357" RevisionGUID="297b0e93-2039-47a5-b6cd-2dd988ed3ea9" CreationDate="2023-03-07T17:37:38.867" UserId="19684" Text="Rendering light balls: Where to do perspective calculations?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40125" PostHistoryTypeId="3" PostId="13357" RevisionGUID="297b0e93-2039-47a5-b6cd-2dd988ed3ea9" CreationDate="2023-03-07T17:37:38.867" UserId="19684" Text="|shader|transformations|compute-shader|pixel-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40126" PostHistoryTypeId="2" PostId="13358" RevisionGUID="574c142e-717d-4403-8107-52679481c75e" CreationDate="2023-03-08T01:18:07.317" UserId="19685" Text="I'd like to know the correct when of converting ACES AP0 color space into sRGB.  Let's say artists decide to pick colors outside of sRGB in AP0, will ACES handle this situation correctly, meaning no loss of detail in the image as it tries to map colors not found in sRGB into sRGB.&#xD;&#xA;&#xD;&#xA;If anybody out there knows which file in their github page I need to look at I'd appreciate it.  Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="40128" PostHistoryTypeId="1" PostId="13358" RevisionGUID="574c142e-717d-4403-8107-52679481c75e" CreationDate="2023-03-08T01:18:07.317" UserId="19685" Text="Converting ACES ap0 color space into srgb?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40129" PostHistoryTypeId="3" PostId="13358" RevisionGUID="574c142e-717d-4403-8107-52679481c75e" CreationDate="2023-03-08T01:18:07.317" UserId="19685" Text="|color|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40130" PostHistoryTypeId="2" PostId="13359" RevisionGUID="fd983b45-6c83-49e4-9680-d0521495fed1" CreationDate="2023-03-08T14:13:55.297" UserId="13273" Text="First of all a small introduction about the matrices you need.&#xD;&#xA;&#xD;&#xA; 1. **viewMatrix**: This matrix is a 4x4 matrix which stores the position and orientation of your camera with respect to the world origin. Multiplying a vector 4D to this matrix transforms this point with respect to your camera coordinate / orientation. So it is a basis change from world coordinate system to camera coordinate system.&#xD;&#xA; 2. **projectionMatrix**: This matrix is a 4x4 matrix which stores the projection aspect of your camera. There are multiple projection types which I don't want to go into detail... you are interested in `perspective projection`. So your camera has a frustum formed like a truncated pyramid.The tip of the pyramid is inside your camera. The foot of the pyramid is where you look to. Everything within the pyramid is visible, everything outside the pyramid is NOT visible. Information like `field of view``aspect ratio``near clipping plane` and `far clipping plane` is encoded into that matrix. As long as these parameters don't change, you can reuse this matrix.&#xD;&#xA; 3. **modelMatrix**: This matrix is a 4x4 matrix which stores information about the position, scaling, sheering and orientation of your model. So when having a model with tons of vertices, you don't need to move all vertices around. This matrix is doing it for you. When multiplying a vertex to this matrix, it will be transformed to world space.&#xD;&#xA;&#xD;&#xA;When having a point (vertex) in 3D space, you can store it as a 4D vector by adding the number (1) to the 4th dimension. Like this: `vector4d(positionX, positionY, positionZ, 1)`. This is called the `homogeneous coordinate`&#xD;&#xA;&#xD;&#xA;As you noticed, we have 4x4 matrices and a 4 component vector. So we can multiply them to receive another 4D vector. You can do it this way:&#xD;&#xA;&#xD;&#xA;$vertexWorldSpace = modelMatrix * vertex4D$ this transforms your vertex from model space to world space.&#xD;&#xA;&#xD;&#xA;$vertexViewSpace = viewMatrix * vertexWorldSpace$ This transforms your vertex from world coordinate space to view space.&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = projectionMatrix * vertexViewSpace$ This transforms your view space coordinate to a screen space coordinate.&#xD;&#xA;usually you have to divide the result by its 4th component, but OpenGL and direct3D is doing this for you when passing the position from vertex to pixel/fragment shader.&#xD;&#xA;&#xD;&#xA;Now you can write this multiplications into one equation:&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = projectionMatrix * viewMatrix * modelMatrix * vertex4D$&#xD;&#xA;&#xD;&#xA;And of cause all matrices can be combined to one matrix&#xD;&#xA;&#xD;&#xA;$modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix$&#xD;&#xA;&#xD;&#xA;This modelViewProjectionMatrix can be loaded to the GPU and each vertex within that model can be multiplied by this matrix to receive the screen coordinate.&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = modelViewProjectionMatrix * vertex4D$&#xD;&#xA;&#xD;&#xA;**Which matrices will change over time?**&#xD;&#xA;&#xD;&#xA; - As long as your camera parameters don't change, the projection matrix will not change. Camera position and orientation are NOT stored inside the projection matrix! But there is a near and a far clipping plane which is stored inside the projection matrix. everything in front of the near clipping plane and everything behind the far clipping plane will be clipped! So it is NOT visible. Have that in mind.&#xD;&#xA; - The viewMatrix will only change, when moving or rotating the camera.&#xD;&#xA; - The modelMatrix will change, when moving, rotating, scaling or&#xD;&#xA;   sheering the model.&#xD;&#xA;&#xD;&#xA;Matrix multiplications should be avoided as mush as you can on GPU. That means, do not move all these matrices to the GPU to multiply them there...&#xD;&#xA;You can do the multiplication on CPU to receive the modelViewProjectionMatrix. Then store this matrix to the GPU to do only one matrix multiplication per vertex.&#xD;&#xA;&#xD;&#xA;There is a very nice OpenGL tutorial about the matrix calculus in computer graphics [OpenGL matrix tutorial][1]. Be aware, that direct3D and vulkan uses different coordinates... So in case of using direct3D or vulkan please use another tutorial. But in principle it works the same way.&#xD;&#xA;&#xD;&#xA;In your case the compute shader should calculate each stars new position(world space). Afterwards you can render the result by using vertex shader to apply the modelViewProjectionMatrix and pixel/fragment shader to color the result.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40132" PostHistoryTypeId="5" PostId="13359" RevisionGUID="8474c4e5-ad13-4ac8-a62e-d7013650a50c" CreationDate="2023-03-08T14:22:26.883" UserId="13273" Comment="added 119 characters in body" Text="First of all a small introduction about the matrices you need.&#xD;&#xA;&#xD;&#xA; 1. **viewMatrix**: This matrix is a 4x4 matrix which stores the position and orientation of your camera with respect to the world origin. Multiplying a vector 4D to this matrix transforms this point with respect to your camera coordinate / orientation. So it is a basis change from world coordinate system to camera coordinate system.&#xD;&#xA; 2. **projectionMatrix**: This matrix is a 4x4 matrix which stores the projection aspect of your camera. There are multiple projection types which I don't want to go into detail... you are interested in `perspective projection`. So your camera has a frustum formed like a truncated pyramid.The tip of the pyramid is inside your camera. The foot of the pyramid is where you look to. Everything within the pyramid is visible, everything outside the pyramid is NOT visible. Information like `field of view``aspect ratio``near clipping plane` and `far clipping plane` is encoded into that matrix. As long as these parameters don't change, you can reuse this matrix.&#xD;&#xA; 3. **modelMatrix**: This matrix is a 4x4 matrix which stores information about the position, scaling, sheering and orientation of your model. So when having a model with tons of vertices, you don't need to move all vertices around. This matrix is doing it for you. When multiplying a vertex to this matrix, it will be transformed to world space.&#xD;&#xA;&#xD;&#xA;When having a point (vertex) in 3D space, you can store it as a 4D vector by adding the number (1) to the 4th dimension. Like this: `vector4d(positionX, positionY, positionZ, 1)`. This is called the `homogeneous coordinate`&#xD;&#xA;&#xD;&#xA;As you noticed, we have 4x4 matrices and a 4 component vector. So we can multiply them to receive another 4D vector. You can do it this way:&#xD;&#xA;&#xD;&#xA;$vertexWorldSpace = modelMatrix * vertex4D$ this transforms your vertex from model space to world space.&#xD;&#xA;&#xD;&#xA;$vertexViewSpace = viewMatrix * vertexWorldSpace$ This transforms your vertex from world coordinate space to view space.&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = projectionMatrix * vertexViewSpace$ This transforms your view space coordinate to a screen space coordinate.&#xD;&#xA;usually you have to divide the result by its 4th component, but OpenGL and direct3D is doing this for you when passing the position from vertex to pixel/fragment shader.&#xD;&#xA;&#xD;&#xA;Now you can write this multiplications into one equation:&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = projectionMatrix * viewMatrix * modelMatrix * vertex4D$&#xD;&#xA;&#xD;&#xA;And of cause all matrices can be combined to one matrix&#xD;&#xA;&#xD;&#xA;$modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix$&#xD;&#xA;&#xD;&#xA;This modelViewProjectionMatrix can be loaded to the GPU and each vertex within that model can be multiplied by this matrix to receive the screen coordinate.&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = modelViewProjectionMatrix * vertex4D$&#xD;&#xA;&#xD;&#xA;**Which matrices will change over time?**&#xD;&#xA;&#xD;&#xA; - As long as your camera parameters don't change, the projection matrix will not change. Camera position and orientation are NOT stored inside the projection matrix! But there is a near and a far clipping plane which is stored inside the projection matrix. everything in front of the near clipping plane and everything behind the far clipping plane will be clipped! So it is NOT visible. Have that in mind.&#xD;&#xA; - The viewMatrix will only change, when moving or rotating the camera.&#xD;&#xA; - The modelMatrix will change, when moving, rotating, scaling or&#xD;&#xA;   sheering the model.&#xD;&#xA;&#xD;&#xA;Matrix multiplications should be avoided as mush as you can on GPU. That means, do not move all these matrices to the GPU to multiply them there...&#xD;&#xA;You can do the multiplication on CPU to receive the modelViewProjectionMatrix. Then store this matrix to the GPU to do only one matrix multiplication per vertex. Rule of thump: Combine the parts of the matrices to one matrix which will be equal to all vertices in the render call.&#xD;&#xA;&#xD;&#xA;There is a very nice OpenGL tutorial about the matrix calculus in computer graphics [OpenGL matrix tutorial][1]. Be aware, that direct3D and vulkan uses different coordinates... So in case of using direct3D or vulkan please use another tutorial. But in principle it works the same way.&#xD;&#xA;&#xD;&#xA;In your case the compute shader should calculate each stars new position(world space). Afterwards you can render the result by using vertex shader to apply the modelViewProjectionMatrix and pixel/fragment shader to color the result.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40133" PostHistoryTypeId="5" PostId="13357" RevisionGUID="ed5e8295-0542-4ed0-82b9-ac683e3fa154" CreationDate="2023-03-08T20:52:27.457" UserId="19684" Comment="clarification" Text="After rewatching Bisqwit's [starfield renderer video](https://www.youtube.com/watch?v=VL0oGct1S4Q), I've decided to try to rewrite the program in order to learn more about compute shaders and shader programming in general. My knowledge at this point is limited to moderately simple vertex and pixel shaders. The original program is a software renderer written in some variant of BASIC that draws each frame roughly like so:  &#xD;&#xA;```text/plain&#xD;&#xA;for every rendered star:&#xD;&#xA;    update the star's position in the world&#xD;&#xA;    calculate the star's position on the screen&#xD;&#xA;    calculate the star's size on the screen&#xD;&#xA;&#xD;&#xA;for every pixel of the screen:&#xD;&#xA;    for every star of the screen:&#xD;&#xA;        calculate the influence of the current star on the color of the current pixel&#xD;&#xA;    do dithering&#xD;&#xA;    draw the pixel in the resulting color&#xD;&#xA;```&#xD;&#xA;Obvious issues with that approach aside, I'm a bit lost w.r.t. the perspective calulations. Where would I do the them, on the CPU or GPU? What would be a suitable mechanism to prevent having to do the calculation multiple times over? I wasn't able to find one through my research, so every pointer toward the solution is appreciated.&#xD;&#xA;&#xD;&#xA;**EDIT:**  &#xD;&#xA;I think I might have been a bit unclear about what a &quot;light ball&quot;/&quot;star&quot; is: It's just some point in the world that is rendered in a fancy way, not a model." ContentLicense="CC BY-SA 4.0" />
  <row Id="40134" PostHistoryTypeId="2" PostId="13360" RevisionGUID="60f81656-4f47-4dd5-8222-4614b18439d3" CreationDate="2023-03-09T09:33:03.090" UserId="209" Text="IIRC this and several other texture mapping/projection techniques are discussed in [Watt &amp; Watt's *Advanced Animation and Rendering Techniques*][1]  &#xD;&#xA;&#xD;&#xA;Though 'old', the book is well worth buying IMHO.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://archive.org/details/advanced-animation-and-rendering-techniques-1992" ContentLicense="CC BY-SA 4.0" />
  <row Id="40136" PostHistoryTypeId="5" PostId="13360" RevisionGUID="437d5449-0b27-4272-99b8-2a531240521f" CreationDate="2023-03-09T09:40:00.997" UserId="209" Comment="added 151 characters in body" Text="IIRC this and some other texture mapping/projection techniques are discussed in [Watt &amp; Watt's *Advanced Animation and Rendering Techniques*][1]  &#xD;&#xA;Skip forward to around page 180.  FWIW that has a reference to a 1946 (!) document but I haven't gone looking to see if it's the original source :)&#xD;&#xA;&#xD;&#xA;[![Spherical mapping excerpt from AAaRT][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Though 'old', *Watt &amp; Watt* is well worth buying IMHO.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://archive.org/details/advanced-animation-and-rendering-techniques-1992&#xD;&#xA;  [2]: https://i.stack.imgur.com/TTy4v.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40137" PostHistoryTypeId="5" PostId="13359" RevisionGUID="1e785dbf-faaa-42c0-92ed-11b915f1bd69" CreationDate="2023-03-09T13:08:29.073" UserId="13273" Comment="added 82 characters in body" Text="First of all a small introduction about the matrices you need.&#xD;&#xA;&#xD;&#xA; 1. **viewMatrix**: This matrix is a 4x4 matrix which stores the position and orientation of your camera with respect to the world origin. Multiplying a vector 4D to this matrix transforms this point with respect to your camera coordinate / orientation. So it is a basis change from world coordinate system to camera coordinate system.&#xD;&#xA; 2. **projectionMatrix**: This matrix is a 4x4 matrix which stores the projection aspect of your camera. There are multiple projection types which I don't want to go into detail... you are interested in `perspective projection`. So your camera has a frustum formed like a truncated pyramid.The tip of the pyramid is inside your camera. The foot of the pyramid is where you look to. Everything within the pyramid is visible, everything outside the pyramid is NOT visible. Information like `field of view``aspect ratio``near clipping plane` and `far clipping plane` is encoded into that matrix. As long as these parameters don't change, you can reuse this matrix.&#xD;&#xA; 3. **modelMatrix**: This matrix is a 4x4 matrix which stores information about the position, scaling, sheering and orientation of your model. So when having a model with tons of vertices, you don't need to move all vertices around. This matrix is doing it for you. When multiplying a vertex to this matrix, it will be transformed to world space.&#xD;&#xA;&#xD;&#xA;When having a point (vertex) in 3D space, you can store it as a 4D vector by adding the number (1) to the 4th dimension. Like this: `vector4d(positionX, positionY, positionZ, 1)`. This is called the `homogeneous coordinate`&#xD;&#xA;&#xD;&#xA;As you noticed, we have 4x4 matrices and a 4 component vector. So we can multiply them to receive another 4D vector. You can do it this way:&#xD;&#xA;&#xD;&#xA;$vertexWorldSpace = modelMatrix * vertex4D$ this transforms your vertex from model space to world space.&#xD;&#xA;&#xD;&#xA;$vertexViewSpace = viewMatrix * vertexWorldSpace$ This transforms your vertex from world coordinate space to view space.&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = projectionMatrix * vertexViewSpace$ This transforms your view space coordinate to a screen space coordinate.&#xD;&#xA;usually you have to divide the result by its 4th component, but OpenGL and direct3D is doing this for you when passing the position from vertex to pixel/fragment shader.&#xD;&#xA;&#xD;&#xA;Now you can write this multiplications into one equation:&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = projectionMatrix * viewMatrix * modelMatrix * vertex4D$&#xD;&#xA;&#xD;&#xA;And of cause all matrices can be combined to one matrix&#xD;&#xA;&#xD;&#xA;$modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix$&#xD;&#xA;&#xD;&#xA;This modelViewProjectionMatrix can be loaded to the GPU and each vertex within that model can be multiplied by this matrix to receive the screen coordinate.&#xD;&#xA;&#xD;&#xA;$vertexScreenSpace = modelViewProjectionMatrix * vertex4D$&#xD;&#xA;&#xD;&#xA;**Which matrices will change over time?**&#xD;&#xA;&#xD;&#xA; - As long as your camera parameters don't change, the projection matrix will not change. Camera position and orientation are NOT stored inside the projection matrix! But there is a near and a far clipping plane which is stored inside the projection matrix. everything in front of the near clipping plane and everything behind the far clipping plane will be clipped! So it is NOT visible. Have that in mind.&#xD;&#xA; - The viewMatrix will only change, when moving or rotating the camera.&#xD;&#xA; - The modelMatrix will change, when moving, rotating, scaling or&#xD;&#xA;   sheering the model.&#xD;&#xA;&#xD;&#xA;Matrix multiplications should be avoided as mush as you can on GPU. That means, do not move all these matrices to the GPU to multiply them there...&#xD;&#xA;You can do the multiplication on CPU to receive the modelViewProjectionMatrix. Then store this matrix to the GPU to do only one matrix multiplication per vertex. Rule of thump: Combine the parts of the matrices to one matrix which will be equal to all vertices in the render call. Have in mind: Matrix multiplications are NOT cummutative. So A * B is not B * A! &#xD;&#xA;&#xD;&#xA;There is a very nice OpenGL tutorial about the matrix calculus in computer graphics [OpenGL matrix tutorial][1]. Be aware, that direct3D and vulkan uses different coordinates... So in case of using direct3D or vulkan please use another tutorial. But in principle it works the same way.&#xD;&#xA;&#xD;&#xA;In your case the compute shader should calculate each stars new position(world space). Afterwards you can render the result by using vertex shader to apply the modelViewProjectionMatrix and pixel/fragment shader to color the result.&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40144" PostHistoryTypeId="2" PostId="13362" RevisionGUID="1366b77b-af6b-4bbf-9168-48d15094aa96" CreationDate="2023-03-11T12:39:09.187" UserId="19698" Text="Actually,shape-&gt;Sample(ref, u, pdf) returns the pdf in solid angle measure.The sample function in sample is actually this.&#xD;&#xA;&#xD;&#xA;    Interaction Shape::Sample(const Interaction &amp;ref, const Point2f &amp;u,&#xD;&#xA;                              Float *pdf) const {&#xD;&#xA;        Interaction intr = Sample(u, pdf);&#xD;&#xA;        Vector3f wi = intr.p - ref.p;&#xD;&#xA;        if (wi.LengthSquared() == 0)&#xD;&#xA;            *pdf = 0;&#xD;&#xA;        else {&#xD;&#xA;            wi = Normalize(wi);&#xD;&#xA;            // Convert from area measure, as returned by the Sample() call&#xD;&#xA;            // above, to solid angle measure.&#xD;&#xA;            *pdf *= DistanceSquared(ref.p, intr.p) / AbsDot(intr.n, -wi);&#xD;&#xA;            if (std::isinf(*pdf)) *pdf = 0.f;&#xD;&#xA;        }&#xD;&#xA;        return intr;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This function will call virtual function sample(    `virtual Interaction Sample(const Point2f &amp;u, Float *pdf) const = 0;`) ,which is also the function in your triangle example.So the virtual function computes pdf in area measure,and the non-virtual function comverts pdf to the solid angle measute" ContentLicense="CC BY-SA 4.0" />
  <row Id="40148" PostHistoryTypeId="50" PostId="10248" RevisionGUID="015bb60c-a1bd-48fd-9e0c-59c5f0979730" CreationDate="2023-03-12T13:04:11.270" UserId="-1" />
  <row Id="40149" PostHistoryTypeId="2" PostId="13363" RevisionGUID="30140c20-e0f6-479d-a3d4-c5b482c45ac5" CreationDate="2023-03-12T15:20:25.427" UserId="19704" Text="I'm developing a 3D rendering engine in Scratch, which is a block-based visual programming language. It does not have any support for bitmap rendering, but there is a &quot;pen&quot; plugin that lets you draw lines and dots on the screen programmatically. The main bottleneck seems to be the speed that the pen tool can draw stuff.&#xD;&#xA;&#xD;&#xA;Existing 3D rendering engines made with Scratch all seem to use some kind of optimized triangle drawing algorithm. The algorithm works by essentially drawing a large dot in the middle of the triangle and then drawing progressively smaller dots around it to minimize drawing operations. This algorithm is also capable of basic shading and transparency.&#xD;&#xA;&#xD;&#xA;My 3D engine does not necessarily need the capability to handle dynamically-moving objects. It would be nice if it had simple texture support. I'm currently planning on using a triangle drawing algorithm combined with binary space partitioning for fast Z-ordering and the ability to handle large scenes.&#xD;&#xA;&#xD;&#xA;What would be the best approach to rendering 3D geometry with these limitations? Should I design my rendering engine to be based on drawing triangles, or should I take another approach entirely?&#xD;&#xA;&#xD;&#xA;Bonus points if the method allows for adaptive levels of detail." ContentLicense="CC BY-SA 4.0" />
  <row Id="40151" PostHistoryTypeId="1" PostId="13363" RevisionGUID="30140c20-e0f6-479d-a3d4-c5b482c45ac5" CreationDate="2023-03-12T15:20:25.427" UserId="19704" Text="Optimized 3D rendering using dots and/or line segments of different sizes" ContentLicense="CC BY-SA 4.0" />
  <row Id="40152" PostHistoryTypeId="3" PostId="13363" RevisionGUID="30140c20-e0f6-479d-a3d4-c5b482c45ac5" CreationDate="2023-03-12T15:20:25.427" UserId="19704" Text="|rendering|3d|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40153" PostHistoryTypeId="4" PostId="13363" RevisionGUID="f4f2fe4a-f0c2-4dfe-9dd9-70b171eb2944" CreationDate="2023-03-12T17:29:08.287" UserId="19704" Comment="edited title" Text="Optimized 3D rendering using dots and/or line segments of different sizes in Scratch" ContentLicense="CC BY-SA 4.0" />
  <row Id="40154" PostHistoryTypeId="2" PostId="13364" RevisionGUID="5a70b497-8a3f-42ac-af27-7795b2c66dee" CreationDate="2023-03-13T01:17:01.210" UserId="19705" Text="I believe your suspicion is correct,otherwise dimensions won't match." ContentLicense="CC BY-SA 4.0" />
  <row Id="40156" PostHistoryTypeId="50" PostId="12259" RevisionGUID="f2f1f7ad-dc86-4986-97f0-34e4ad6c790c" CreationDate="2023-03-13T17:06:20.700" UserId="-1" />
  <row Id="40157" PostHistoryTypeId="2" PostId="13365" RevisionGUID="0df3dab7-e7d6-43c5-8b0e-a76bfb1efcee" CreationDate="2023-03-13T22:16:25.053" UserId="5989" Text="In [this YouTube video](https://www.youtube.com/watch?v=Id48CD5sgic&amp;t=4m34s), the creator mentions that reflections in Unreal Engine 5's [Lumen](https://docs.unrealengine.com/5.1/en-US/lumen-global-illumination-and-reflections-in-unreal-engine/) &quot;work by tracing the path of light as it bounces off of surfaces in the game world.&quot; Does this mean that Lumen uses raytracing? I thought that this was difficult to do in real time on consumer hardware. But more importantly, how can I implement the same technique? Can I do that with OpenGL or Vulkan? How much of the existing rendering pipeline do I in that case need to re-implement myself, and how much of it can I reuse?&#xD;&#xA;&#xD;&#xA;*Side note:* I don't only plan to use it for reflections, but also for transparent objects that [bend light](https://computergraphics.stackexchange.com/questions/13338/raytracing-in-opengl-or-vulkan) in various ways (for which rendering to a texture doesn't work because there is not a single point from which to do that rendering), but I—perhaps somewhat naively—assume that reflections and refractions can both be implemented using the same or very similar techniques." ContentLicense="CC BY-SA 4.0" />
  <row Id="40159" PostHistoryTypeId="1" PostId="13365" RevisionGUID="0df3dab7-e7d6-43c5-8b0e-a76bfb1efcee" CreationDate="2023-03-13T22:16:25.053" UserId="5989" Text="How does Unreal Engine 5's Lumen (most likely) implement reflections?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40160" PostHistoryTypeId="3" PostId="13365" RevisionGUID="0df3dab7-e7d6-43c5-8b0e-a76bfb1efcee" CreationDate="2023-03-13T22:16:25.053" UserId="5989" Text="|opengl|raytracing|vulkan|reflection|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40161" PostHistoryTypeId="2" PostId="13366" RevisionGUID="aba553e8-02fc-46ce-8e9b-65a51ea90124" CreationDate="2023-03-13T23:56:57.990" UserId="19523" Text="Whether you use Lumen with hardware acceleration or not, Lumen is based on ray tracing. Software mode uses signed distance fields (SDF) to find intersections along a ray and so called cards to store lighting on geometry. Hardware accelerated ray tracing finds intersection using triangle-based geometry, which can be more precise if the original geometry also is made out of triangles.&#xD;&#xA;&#xD;&#xA;You might find this interesting: &quot;https://knarkowicz.wordpress.com/2022/08/18/journey-to-lumen/&quot;, the history of Lumen. I would imagine that a lot of optimization was required, they use a LOD system as an example.&#xD;&#xA;&#xD;&#xA;I assume that you want to ray trace SDF:s in your program. Since I don't know enough about your project, I will just assume that you have triangle meshes. An approach is to use a SDF volume centered around each mesh object, inject them into a BVH and trace the SDF volumes along the ray (I think this is the unreal approach). Cards are harder to implement, maybe a volumetric approach is easier in your case?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40163" PostHistoryTypeId="50" PostId="9199" RevisionGUID="c99eb0f0-065d-4fbe-9ff6-7d2e490cd9b8" CreationDate="2023-03-14T11:04:05.463" UserId="-1" />
  <row Id="40164" PostHistoryTypeId="2" PostId="13367" RevisionGUID="6f5c5ada-db2a-4dd7-9f3f-fe51cf76ac54" CreationDate="2023-03-14T12:44:17.800" UserId="2320" Text="If AP0 are the primaries used for rendering, then colours outside the sRGB space will work fine (assuming the colours are still within the AP0 space of course). If you allow users to pick colours in AP0 and then render with sRGB primaries, you will either end up with invalid colours (outside the zero to one range) or gamut clipping.&#xD;&#xA;&#xD;&#xA;Assuming AP0 is used internally for rendering, then whether or not there will be data loss depends on the pipeline. &#xD;&#xA;&#xD;&#xA;If a user picks a floating point colour outside the sRGB space and it is converted and stored as an integer value in sRGB (for example a PNG texture of whatever), there will be a loss of colour gamut but very little loss of precision. If it is stored as a floating point texture in sRGB (such as OpenEXR), texture values outside the gamut end up being negative or greater than one but that is actually fine as long as they end up in the zero to one space again for rendering when converted back to AP0.&#xD;&#xA;&#xD;&#xA;If values are stored in integer format in AP0, you will keep the gamut but you lose precision. Because the AP0 gamut is larger than the sRGB gamut, you need more bits to store colour with the same degree of precision. When rendering in a wide gamut, I recommend using floating point for colours whenever possible. Using low dynamic range integer texture formats in sRGB is fine as *inputs* (normal JPG or PNG textures). Precision loss will be minimal. &#xD;&#xA;&#xD;&#xA;Attached are two test renderings. Both of them use the same sRGB 8-bit integer image as input, but one is rendered with ACES primaries and the other with sRGB primaries. Both of them are saved in sRGB. They are a little bit different. This is because the ACES version has rounding errors from having a low precision integer image converted from sRGB to ACES and back, while the sRGB version has less conversion here and there. If floating point colours / textures are used, the precision loss is far less.&#xD;&#xA;&#xD;&#xA;sRGB:&#xD;&#xA;[![sRGB version][1]][1]&#xD;&#xA;ACES:&#xD;&#xA;[![ACES version][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Wedb1.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/wTxPd.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40166" PostHistoryTypeId="2" PostId="13368" RevisionGUID="12969dba-53a6-41b0-9026-75f9405a1a35" CreationDate="2023-03-14T13:17:53.383" UserDisplayName="user1703" Text="A possible way is using bilinear interpolation. Assuming you know the normals at the triangle vertices, when doing a raster-scan conversion, you intersect the triangle projection with horizontals and each time obtain two intersection points. Then you fill the segment between them with further interpolated data.&#xD;&#xA;&#xD;&#xA;So interpolation takes place first between triangle vertices, then between intersection, and in both cases a linear interpolation can be used. Anyway, the resulting vector should be normalized to unit norm in order to apply Phong's model.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Note that as the first interpolation is done between two vertices, the continuity of the normal vectors is implicitly guaranteed along edges common to two faces." ContentLicense="CC BY-SA 4.0" />
  <row Id="40168" PostHistoryTypeId="2" PostId="13369" RevisionGUID="16d526a2-95fe-4b1e-a798-edf4fa6d25f2" CreationDate="2023-03-14T14:23:32.030" UserId="19633" Text="I am obviously not understanding something related to light for a ray tracer.&#xD;&#xA;&#xD;&#xA;Reading [Spectral representation][1] &#xD;&#xA;and [Point light calculation][2] &#xD;&#xA;&#xD;&#xA;### A bit of a context:&#xD;&#xA;My question is: in room at X degrees Celsius, for ray of light with an originating linear RGB color of (0.4,0.6,0.6), with an originating power in Watts of 750W, at what distance would it become invisible, with a color (0,0,0)?&#xD;&#xA;&#xD;&#xA;My limited understanding tells me that light intensity decreases at the rate given by 1/(d*d). &#xD;&#xA;&#xD;&#xA;At 500 meters: (what I am about to write is so ridiculous, but let's do it)&#xD;&#xA;So we would have A = 750 / (500*500) = .765 and put back in sRGB I multiply by 255&#xD;&#xA;&#xD;&#xA;(A * 0.4, A * 0.6, A* 0.6) = (0, 0, 0) approx.&#xD;&#xA;&#xD;&#xA;500m look way to high for a 750W light to reach a sRGB color of 0.&#xD;&#xA;So my calculation is wrong from the start.&#xD;&#xA;&#xD;&#xA;### My experiments so far:&#xD;&#xA;Using Blender, with a white spotlight of 750W oriented at 90d, it takes approx 80m for it to be invisible to my eye, on a white plane.&#xD;&#xA;&#xD;&#xA;We are talking of very non scientific measure, obviously but it gives an order of magnitude: 80m is far more plausible.&#xD;&#xA;&#xD;&#xA;Could someone tell me how to correctly calculate the power and color of a light, from its originating color at distance X meters?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;  [1]: https://pbr-book.org/3ed-2018/Color_and_Radiometry/Spectral_Representation#Spectrum&#xD;&#xA;  [2]: https://pbr-book.org/3ed-2018/Light_Sources/Point_Lights#" ContentLicense="CC BY-SA 4.0" />
  <row Id="40170" PostHistoryTypeId="1" PostId="13369" RevisionGUID="16d526a2-95fe-4b1e-a798-edf4fa6d25f2" CreationDate="2023-03-14T14:23:32.030" UserId="19633" Text="Ray light color at distance" ContentLicense="CC BY-SA 4.0" />
  <row Id="40171" PostHistoryTypeId="3" PostId="13369" RevisionGUID="16d526a2-95fe-4b1e-a798-edf4fa6d25f2" CreationDate="2023-03-14T14:23:32.030" UserId="19633" Text="|raytracing|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40172" PostHistoryTypeId="2" PostId="13370" RevisionGUID="b908c4a9-f041-4742-bbb9-7e1afa863445" CreationDate="2023-03-14T15:02:46.670" UserId="10932" Text="I have a rendering engine that has CPU path tracing support, as well as GPU (Vulkan) rasterization and path tracing support.  It uses a rasterization pre-processing step to identify the resolution of geometry that needs to be loaded prior to running the path tracing.  We now need to support this functionality on CPU in addition to GPU.&#xD;&#xA;&#xD;&#xA;The naive solution to rasterization is to simply loop over all triangles, projecting each to the image space and then determining which pixels lie inside the triangle.  The issue is, this process cannot be parallelized as stated.  If you simply try to process multiple triangles in parallel you could very easily end up with two triangles trying to write to the same pixels in the frame/color buffers.&#xD;&#xA;&#xD;&#xA;The &quot;easiest&quot; solution I could think of is to duplicate the render targets (color/depth buffer).  Parallelize over the triangles but have each thread write to its own copy of the color/depth buffer.  Then once all threads are completed, merge everything together.&#xD;&#xA;&#xD;&#xA;Another solution I can think of is to &quot;tile&quot; the frames such that, if I have N logical cores available, I create N tiles of the final image.  Each tile then gets its own frustrum and use that to identify what subset of the triangles appear in each tile, then simply run the rasterization on each (clipped) triangle in each tile in parallel.&#xD;&#xA;&#xD;&#xA;Both of these options feel a bit clunky.  The first would require a ton of additional memory overhead needing to duplicate the render targets for every available logical core, and then requires an additional merging step.  The second option requires a list of the triangles that may appear in it's tile.  I'm loosely aware of the existence of tiled rendering for mobile devices, but I have never explicitly done that.  Is this how that process works, and why it would be used?  To allow parallelization of rasterizing many triangles?&#xD;&#xA;&#xD;&#xA;Is there a better way of approaching this, or is creating a tile for every parallel thread the correct solution?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40174" PostHistoryTypeId="1" PostId="13370" RevisionGUID="b908c4a9-f041-4742-bbb9-7e1afa863445" CreationDate="2023-03-14T15:02:46.670" UserId="10932" Text="I need to implement a CPU Rasterizer but am unsure how to parallelize rasterization" ContentLicense="CC BY-SA 4.0" />
  <row Id="40175" PostHistoryTypeId="3" PostId="13370" RevisionGUID="b908c4a9-f041-4742-bbb9-7e1afa863445" CreationDate="2023-03-14T15:02:46.670" UserId="10932" Text="|rasterizer|tile-based-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40176" PostHistoryTypeId="5" PostId="13370" RevisionGUID="da2c66f9-b74a-4fdf-bc69-e0007c89a2ea" CreationDate="2023-03-14T15:17:47.057" UserId="10932" Comment="added 75 characters in body" Text="I have a rendering engine that has CPU path tracing support, as well as GPU (Vulkan) rasterization and path tracing support.  It uses a rasterization pre-processing step to identify the resolution of geometry that needs to be loaded prior to running the path tracing.  We now need to support this functionality on CPU in addition to GPU.  I have a basic rasterizer built on the CPU now, but its not parallelized.&#xD;&#xA;&#xD;&#xA;The naive solution to rasterization is to simply loop over all triangles, projecting each to the image space and then determining which pixels lie inside the triangle.  The issue is, this process cannot be parallelized as stated.  If you simply try to process multiple triangles in parallel you could very easily end up with two triangles trying to write to the same pixels in the frame/color buffers.&#xD;&#xA;&#xD;&#xA;The &quot;easiest&quot; solution I could think of is to duplicate the render targets (color/depth buffer).  Parallelize over the triangles but have each thread write to its own copy of the color/depth buffer.  Then once all threads are completed, merge everything together.&#xD;&#xA;&#xD;&#xA;Another solution I can think of is to &quot;tile&quot; the frames such that, if I have N logical cores available, I create N tiles of the final image.  Each tile then gets its own frustrum and use that to identify what subset of the triangles appear in each tile, then simply run the rasterization on each (clipped) triangle in each tile in parallel.&#xD;&#xA;&#xD;&#xA;Both of these options feel a bit clunky.  The first would require a ton of additional memory overhead needing to duplicate the render targets for every available logical core, and then requires an additional merging step.  The second option requires a list of the triangles that may appear in it's tile.  I'm loosely aware of the existence of tiled rendering for mobile devices, but I have never explicitly done that.  Is this how that process works, and why it would be used?  To allow parallelization of rasterizing many triangles?&#xD;&#xA;&#xD;&#xA;Is there a better way of approaching this, or is creating a tile for every parallel thread the correct solution?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40177" PostHistoryTypeId="5" PostId="13369" RevisionGUID="7d4b7811-99af-4b2c-b025-b789ac990e69" CreationDate="2023-03-15T08:17:59.357" UserId="19633" Comment="added 286 characters in body" Text="I am obviously not understanding something related to light for a ray tracer.&#xD;&#xA;&#xD;&#xA;Reading [Spectral representation][1] &#xD;&#xA;and [Point light calculation][2] &#xD;&#xA;&#xD;&#xA;### A bit of a context:&#xD;&#xA;My question is: in room at X degrees Celsius, for ray of light with an originating linear RGB color of (0.4,0.6,0.6), with an originating power in Watts of 750W, at what distance would it become invisible, with a color (0,0,0)?&#xD;&#xA;&#xD;&#xA;My limited understanding tells me that light intensity decreases at the rate given by 1/(d*d). &#xD;&#xA;&#xD;&#xA;At 500 meters: (what I am about to write is so ridiculous, but let's do it)&#xD;&#xA;So we would have A = 750 / (500*500) = .765 and put back in sRGB I multiply by 255&#xD;&#xA;&#xD;&#xA;(A * 0.4, A * 0.6, A* 0.6) = (0, 0, 0) approx.&#xD;&#xA;&#xD;&#xA;500m look way to high for a 750W light to reach a sRGB color of 0.&#xD;&#xA;So my calculation is wrong from the start.&#xD;&#xA;&#xD;&#xA;### My experiments so far:&#xD;&#xA;Using Blender, with a white spotlight of 750W oriented at 90d, it takes approx 80m for it to be invisible to my eye, on a white plane.&#xD;&#xA;&#xD;&#xA;We are talking of very non scientific measure, obviously but it gives an order of magnitude: 80m is far more plausible.&#xD;&#xA;&#xD;&#xA;Could someone tell me how to correctly calculate the power and color of a light, from its originating color at distance X meters?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;### Edit:&#xD;&#xA;My current decision is to use a completely different light calculation and it yields visually correct results.&#xD;&#xA;Instead of starting with known units, I just decide the length in meters a ray can have and apply my attenuation according to the cumulated distance.&#xD;&#xA;&#xD;&#xA;It works.&#xD;&#xA;  [1]: https://pbr-book.org/3ed-2018/Color_and_Radiometry/Spectral_Representation#Spectrum&#xD;&#xA;  [2]: https://pbr-book.org/3ed-2018/Light_Sources/Point_Lights#" ContentLicense="CC BY-SA 4.0" />
  <row Id="40178" PostHistoryTypeId="5" PostId="13369" RevisionGUID="c14d2a65-6bc6-478a-a949-49d81421d973" CreationDate="2023-03-15T08:53:19.320" UserId="19633" Comment="added 2 characters in body" Text="I am obviously not understanding something related to light for a ray tracer.&#xD;&#xA;&#xD;&#xA;Reading [Spectral representation][1] &#xD;&#xA;and [Point light calculation][2] &#xD;&#xA;&#xD;&#xA;### A bit of a context:&#xD;&#xA;My question is: in room at X degrees Celsius, for ray of light with an originating linear RGB color of (0.4,0.6,0.6), with an originating power in Watts of 750W, at what distance would it become invisible, with a color (0,0,0)?&#xD;&#xA;&#xD;&#xA;My limited understanding tells me that light intensity decreases at the rate given by 1/(d*d). &#xD;&#xA;&#xD;&#xA;At 500 meters: (what I am about to write is so ridiculous, but let's do it)&#xD;&#xA;So we would have A = 750 / (500*500) = .765 and put back in sRGB I multiply by 255&#xD;&#xA;&#xD;&#xA;(A * 0.4, A * 0.6, A* 0.6) = (0, 0, 0) approx.&#xD;&#xA;&#xD;&#xA;500m look way to high for a 750W light to reach a sRGB color of 0.&#xD;&#xA;So my calculation is wrong from the start.&#xD;&#xA;&#xD;&#xA;### My experiments so far:&#xD;&#xA;Using Blender, with a white spotlight of 750W oriented at 90d, it takes approx 80m for it to be invisible to my eye, on a white plane.&#xD;&#xA;&#xD;&#xA;We are talking of very non scientific measure, obviously but it gives an order of magnitude: 80m is far more plausible.&#xD;&#xA;&#xD;&#xA;Could someone tell me how to correctly calculate the power and color of a light, from its originating color at distance X meters?&#xD;&#xA;&#xD;&#xA;Thanks!&#xD;&#xA;&#xD;&#xA;### Edit:&#xD;&#xA;My current decision is to use a completely different light calculation and it yields visually correct results.&#xD;&#xA;Instead of starting with known units, I just decide the length in meters a ray can have and apply my attenuation according to the cumulated distance.&#xD;&#xA;&#xD;&#xA;It works.&#xD;&#xA;&#xD;&#xA;  [1]: https://pbr-book.org/3ed-2018/Color_and_Radiometry/Spectral_Representation#Spectrum&#xD;&#xA;  [2]: https://pbr-book.org/3ed-2018/Light_Sources/Point_Lights#" ContentLicense="CC BY-SA 4.0" />
  <row Id="40179" PostHistoryTypeId="2" PostId="13371" RevisionGUID="9e257a1f-5a4d-406f-a1e3-8775974f41b9" CreationDate="2023-03-16T00:03:51.427" UserId="19715" Text="I have been learning computer graphics and for some time and can't seem to wrap my head around one concept. How to handle vertex data changes?&#xD;&#xA;&#xD;&#xA;Ex. 1. I have a text rendering on a screen. And up on hitting a character corresponding glyph should be rendered. I have managed to achieve this using Open GL with dynamic draw where during each frame I would submit subbuffer data of the whole vertex and index set plus new verices for the new glyph at a 0 offset in memory. I would think this is not the optimal way to change what is shown on screen between frames, but it is good enough for learning. This aproach introduces a bug though. Or at least I have a bug. Where upon deleting a glyph and resubmiting vertex and index data the glyth would still be renderd during next frame. I guess it is because allocated buffer points to a contiguous block of memory and text rendering is just bunch of rectangles where the count of indices per glyph remains constant and until I do not clear or overwrite the subitted data at the address it will continue rendering.&#xD;&#xA;&#xD;&#xA;Ex. 2. I have an entity loaded from .obj file the vertex and index data is converted tiny_obj_loader library. I would like for the entity to move in a scene. And not by moving or changing UBO. So I have tried this using Open GL and have achieved this using similar method to my previous example, using dynamic draw. And it worked. But once I have tried this in vulkan I have almost hit a brick wall. I can not  change vertex data each frame since VkBufferMemory for vertices and indices is allocated before even commad buffers are created.&#xD;&#xA;&#xD;&#xA;So my question is how do I manage vertex/index data changes in vulkan or more in general?&#xD;&#xA;Should I write some alogorithms that would determine the place in memory should be cleared or is there a better way than dynamic draw? How does it look like using vulkan? Is there some way to rebind new data and send it to gpu on every render pass?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40181" PostHistoryTypeId="1" PostId="13371" RevisionGUID="9e257a1f-5a4d-406f-a1e3-8775974f41b9" CreationDate="2023-03-16T00:03:51.427" UserId="19715" Text="How does changes in vertex data work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40182" PostHistoryTypeId="3" PostId="13371" RevisionGUID="9e257a1f-5a4d-406f-a1e3-8775974f41b9" CreationDate="2023-03-16T00:03:51.427" UserId="19715" Text="|opengl|rendering|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40185" PostHistoryTypeId="5" PostId="13357" RevisionGUID="fab3ad53-3f98-4ce3-9ee6-6da0d0cfc220" CreationDate="2023-03-18T09:09:39.110" UserId="19684" Comment="added 387 characters in body" Text="After rewatching Bisqwit's [starfield renderer video](https://www.youtube.com/watch?v=VL0oGct1S4Q), I've decided to try to rewrite the program in order to learn more about compute shaders and shader programming in general. My knowledge at this point is limited to moderately simple vertex and pixel shaders. The original program is a software renderer written in some variant of BASIC that draws each frame roughly like so:  &#xD;&#xA;```text/plain&#xD;&#xA;for every rendered star:&#xD;&#xA;    update the star's position in the world&#xD;&#xA;    calculate the star's position on the screen&#xD;&#xA;    calculate the star's size on the screen&#xD;&#xA;&#xD;&#xA;for every pixel of the screen:&#xD;&#xA;    for every star of the screen:&#xD;&#xA;        calculate the influence of the current star on the color of the current pixel&#xD;&#xA;    do dithering&#xD;&#xA;    draw the pixel in the resulting color&#xD;&#xA;```&#xD;&#xA;I'd try to translate this to a compute shader that draws to a texture which is then rendered using a fullscreen quad. Obvious issues with that approach aside, I'm a bit lost w.r.t. the perspective calulations. Where would I do the them, on the CPU or GPU? What would be a suitable mechanism to prevent having to do the calculation multiple times over? I wasn't able to find one through my research, so every pointer toward the solution is appreciated.&#xD;&#xA;&#xD;&#xA;**EDIT:**  &#xD;&#xA;I think I might have been a bit unclear about what a &quot;light ball&quot;/&quot;star&quot; is: It's just some point in the world that is rendered in a fancy way, not a model.&#xD;&#xA;&#xD;&#xA;**EDIT 2:**&#xD;&#xA;Thanks to all of the pointers presented in the answer and comments, I've decided to use two compute shaders. One does the perspective calulation and the other draws the result onto a texture, which is rendered onto a fullscreen quad. Judging from the suboptimal performance, using a different approach like the one outlined in @Thomas' comments might be better overall but that's a topic for another question." ContentLicense="CC BY-SA 4.0" />
  <row Id="40186" PostHistoryTypeId="2" PostId="13372" RevisionGUID="83190c7f-b60d-4aef-9574-164993e035d7" CreationDate="2023-03-18T17:06:58.213" UserId="19735" Text="I have a 2d texture and a shape matte, the matte could be any shape, like a star, heart, and so on, and I want to use this matte to generate different-shaped bokeh blur, how can I do it? and normally, creating bokeh blur needs iterations, how to cope with the efficiency problem. hopefully, realize it in glsl" ContentLicense="CC BY-SA 4.0" />
  <row Id="40188" PostHistoryTypeId="1" PostId="13372" RevisionGUID="83190c7f-b60d-4aef-9574-164993e035d7" CreationDate="2023-03-18T17:06:58.213" UserId="19735" Text="want bokeh blur with custom shapes" ContentLicense="CC BY-SA 4.0" />
  <row Id="40189" PostHistoryTypeId="3" PostId="13372" RevisionGUID="83190c7f-b60d-4aef-9574-164993e035d7" CreationDate="2023-03-18T17:06:58.213" UserId="19735" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40190" PostHistoryTypeId="50" PostId="13250" RevisionGUID="79e47407-47bd-4256-a4a9-ab1b1122d907" CreationDate="2023-03-19T10:00:35.050" UserId="-1" />
  <row Id="40195" PostHistoryTypeId="50" PostId="7804" RevisionGUID="5b82a82d-17a1-474a-98ec-41a1fd7340be" CreationDate="2023-03-19T20:04:20.633" UserId="-1" />
  <row Id="40196" PostHistoryTypeId="2" PostId="13374" RevisionGUID="5ec78a0a-39f3-47f1-be6f-6f574c0ff984" CreationDate="2023-03-20T09:02:24.877" UserId="13273" Text="I have an application that uses only the default opengl framebuffer. It is initialized with color and depth buffer.&#xD;&#xA;I want to use the depth buffer as a uniform within a shader to access the current depth values.&#xD;&#xA;How can I make this happen? I tried to get the GLint ID of the depth buffer with the following command:&#xD;&#xA;&#xD;&#xA;    GLint params;&#xD;&#xA;    glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &amp;params);&#xD;&#xA;    std::cout &lt;&lt; &quot;Depthbuffer id:&quot; &lt;&lt; params &lt;&lt; std::endl;&#xD;&#xA;&#xD;&#xA;the output is something like 325462352776. so that doesn't work :(&#xD;&#xA;&#xD;&#xA;How can I get the correct ID of the depth buffer so I can use it to read its values in a shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40198" PostHistoryTypeId="1" PostId="13374" RevisionGUID="5ec78a0a-39f3-47f1-be6f-6f574c0ff984" CreationDate="2023-03-20T09:02:24.877" UserId="13273" Text="OpenGL get default depthbuffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="40199" PostHistoryTypeId="3" PostId="13374" RevisionGUID="5ec78a0a-39f3-47f1-be6f-6f574c0ff984" CreationDate="2023-03-20T09:02:24.877" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40200" PostHistoryTypeId="2" PostId="13375" RevisionGUID="c4c1abbd-b546-4d00-adef-bc29208a5354" CreationDate="2023-03-20T11:48:26.753" UserId="7952" Text="Here is a basic implementation for a rasterized scene.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;1) Bind and write the depth buffer as usual.&#xD;&#xA;2) Bind and write the stencil buffer with the shapes that need to be masked out. A simple 1 or 0 will do here.&#xD;&#xA;3) Generate the color buffer&#xD;&#xA;4) Run the bokeh filter as a full screen quad post processing effect.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The order here isn't terribly important the only step dependent on the other 3 is doing the actual blur.&#xD;&#xA;&#xD;&#xA;In the fragment shader: &#xD;&#xA;&#xD;&#xA;1) read the stencil and color buffers. If the stencil value is 1 return the unmodified color.&#xD;&#xA;2) read the depth buffer.&#xD;&#xA;3) Run the blur kernel.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Here is a basic fragment shader implementation:&#xD;&#xA; uBlurRadius is a uniform passed in to set the blur kernel size and uResolution is the width and height of the color buffer.&#xD;&#xA;&#xD;&#xA;    float stencil = texture(stencilBuffer, uv).r;&#xD;&#xA;&#xD;&#xA;    if (stencil == 1.0) {&#xD;&#xA;      // Keep the pixel in focus.&#xD;&#xA;      gl_FragColor = texture(colorBuffer, uv);&#xD;&#xA;      return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Compute the depth of field mask.&#xD;&#xA;    float focusDepth = texture( depthBuffer, uv);&#xD;&#xA;    float blurDepth = focusDepth + uBlurRadius;&#xD;&#xA;    float blurAmount = smoothstep(focusDepth, blurDepth, depth);&#xD;&#xA;&#xD;&#xA;    // Apply the bokeh blur effect.&#xD;&#xA;    vec4 color = vec4(0.0);&#xD;&#xA;    float totalWeight = 0.0;&#xD;&#xA;    for (float i = -uBlurRadius; i &lt;= uBlurRadius; i++) {&#xD;&#xA;      for (float j = -uBlurRadius; j &lt;= uBlurRadius; j++) {&#xD;&#xA;        vec2 offset = vec2(i, j) / uResolution;&#xD;&#xA;        float weight = exp(-length(offset) * length(offset) / 2.0);&#xD;&#xA;        totalWeight += weight;&#xD;&#xA;        color += texture(colorBuffer, uv + offset * blurAmount) * weight;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    gl_FragColor = color / totalWeight;&#xD;&#xA;&#xD;&#xA;The biggest issue with this code is that fragments that are in focus can bleed/smear into those that are out of focus inside the blur kernel. If you implement this and look closely at the edges around scene elements that are in focus you will be able to see the effect it has. But the code is simple and relatively fast. The blur kernel size can be used to limit blur and improve performance which can be an easy way to make this work on a variety of hardware." ContentLicense="CC BY-SA 4.0" />
  <row Id="40202" PostHistoryTypeId="2" PostId="13376" RevisionGUID="8e19ea66-cb94-4260-b7c9-a572c323ad1c" CreationDate="2023-03-20T13:51:07.783" UserId="2654" Text="Components of the default framebuffer do not have an &quot;ID&quot;. You can only use those images as components of the default framebuffer.&#xD;&#xA;&#xD;&#xA;If you want to use images in a framebuffer as textures or the like, then you're going to have to create them yourself. You cannot rely on the default framebuffer's images." ContentLicense="CC BY-SA 4.0" />
  <row Id="40204" PostHistoryTypeId="50" PostId="9626" RevisionGUID="c34c72bb-4159-4cab-b198-aaef062070ce" CreationDate="2023-03-20T17:00:09.920" UserId="-1" />
  <row Id="40205" PostHistoryTypeId="50" PostId="9307" RevisionGUID="3b935592-4f69-469a-b78a-e82bffc47ba8" CreationDate="2023-03-20T22:04:30.533" UserId="-1" />
  <row Id="40206" PostHistoryTypeId="50" PostId="13299" RevisionGUID="e898d931-9e6b-46a9-ac26-61163694387d" CreationDate="2023-03-22T15:02:35.290" UserId="-1" />
  <row Id="40207" PostHistoryTypeId="2" PostId="13377" RevisionGUID="7e5cbd40-966a-47ae-b189-718e0c3c8283" CreationDate="2023-03-24T09:21:30.433" UserId="8757" Text="I have the following problem I am currently facing.&#xD;&#xA;&#xD;&#xA;I am creating the vertices for a cone based on the number of segments and the radius of the base and top.&#xD;&#xA;&#xD;&#xA;This is done as follows:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;#include &lt;cmath&gt;&#xD;&#xA;#include &lt;fstream&gt;&#xD;&#xA;#include &lt;numbers&gt;&#xD;&#xA;#include &lt;iostream&gt;&#xD;&#xA;#include &lt;fmt/core.h&gt;&#xD;&#xA;&#xD;&#xA;struct Vec3D&#xD;&#xA;{&#xD;&#xA;    double x, y, z;&#xD;&#xA;    Vec3D(double x, double y, double z) : x(x), y(y), z(z) {}&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;int main()&#xD;&#xA;{&#xD;&#xA;    int n = 4;       // number of segments&#xD;&#xA;    double r1 = 0.8; // radius of the base, assume meters&#xD;&#xA;    double r2 = 1.0; // radius of the top, assume meters&#xD;&#xA;    double h = 1.0;  // height of the cone, assume meters&#xD;&#xA;&#xD;&#xA;    auto get_coordinates = [&amp;n](int32_t vertex_id, double radius, double height) {&#xD;&#xA;        double theta = vertex_id * 2 * std::numbers::pi / n;&#xD;&#xA;        double x = radius * cos(theta);&#xD;&#xA;        double y = radius * sin(theta);&#xD;&#xA;        double z = height;&#xD;&#xA;&#xD;&#xA;        return Vec3D(x, y, z);&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    for (int i = 0; i &lt; n; i++)&#xD;&#xA;    {&#xD;&#xA;        Vec3D pt = get_coordinates(i, r1, 0.0);&#xD;&#xA;        std::cout &lt;&lt; fmt::format(&quot;v {} {} {}\n&quot;, pt.x, pt.y, pt.z);&#xD;&#xA;        pt = get_coordinates(i, r1, h);&#xD;&#xA;        std::cout &lt;&lt; fmt::format(&quot;v {} {} {}\n&quot;, pt.x, pt.y, pt.z);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;(godbolt: https://godbolt.org/z/njdxznj9c)&#xD;&#xA;&#xD;&#xA;Which works perfectly fine, but now I want to automatically create a UV map, which of course in a cylinder case can be very straight forward by just&#xD;&#xA;distributing the uv coordinates for the top vertices between `[0, 1]` for `u` and `v = 1.0`, and for the bottom the same with `v = 0.0`.&#xD;&#xA;&#xD;&#xA;Now in a cone case this would lead to texture distorting.. which I want to avoid and therfore find an arc-like mapping, such that if the printed texture has the correct ratios and sizes (to the actual cup) you can wrap it without distortion, basically the same as blender can do &#xD;&#xA;&#xD;&#xA;[![Blender UV Unwrapping][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Assuming now only calculating the following points a, b, c, d&#xD;&#xA;my plan was that those points should be possible to calculate and from there on use some sort-of arc parametrisation based on the radii to calculate the other points.&#xD;&#xA;points `a` and `b` can be calculated under the assumptions of the coordinates that it is in relation to the ratio of the 2 cone radii.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;But I am not really sure how to follow up on that. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Sketch of uv map][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4mFeh.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/f1L3C.jpg&#xD;&#xA;&#xD;&#xA;I'm glad for any help on that." ContentLicense="CC BY-SA 4.0" />
  <row Id="40209" PostHistoryTypeId="1" PostId="13377" RevisionGUID="7e5cbd40-966a-47ae-b189-718e0c3c8283" CreationDate="2023-03-24T09:21:30.433" UserId="8757" Text="Creating a UV Map for a 3D Cone" ContentLicense="CC BY-SA 4.0" />
  <row Id="40210" PostHistoryTypeId="3" PostId="13377" RevisionGUID="7e5cbd40-966a-47ae-b189-718e0c3c8283" CreationDate="2023-03-24T09:21:30.433" UserId="8757" Text="|3d|geometry|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40211" PostHistoryTypeId="2" PostId="13378" RevisionGUID="2485b663-9fc8-404e-8c69-09e623f02558" CreationDate="2023-03-24T10:02:53.000" UserDisplayName="user1703" Text="Consider a circular sector of radius R equal to the apothem of the whole cone, and angular aperture α such that αR = 2πr, where r is the radius of the large base.&#xD;&#xA;&#xD;&#xA;Now you can subdivide the (truncated) sector in N faces. The coordinates are easily computed from the polar system.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Now if you want the same layout as on your diagram, rotate by α/2 and translate so that the bounding box (found from four extreme points) goes where you want.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XJoBC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fzRU4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40213" PostHistoryTypeId="5" PostId="13378" RevisionGUID="03785aed-0b86-4fb2-968a-6dcf7af73f3f" CreationDate="2023-03-24T10:08:54.567" UserDisplayName="user1703" Comment="deleted 101 characters in body" Text="Consider a circular sector of radius R equal to the apothem of the whole cone, and angular aperture 2α such that 2αR = 2πr, where r is the radius of the large base.&#xD;&#xA;&#xD;&#xA;Now you can subdivide the (truncated) sector in N faces. The coordinates are easily computed from the polar system.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now you can translate so that the bounding box (found from four extreme points) goes where you want.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XJoBC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fzRU4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40214" PostHistoryTypeId="5" PostId="13378" RevisionGUID="c149ce75-0ea7-4531-addb-1b5f05133887" CreationDate="2023-03-24T10:20:54.670" UserDisplayName="user1703" Comment="deleted 12 characters in body" Text="Consider a circular sector of radius R equal to the apothem of the whole cone, and angular aperture 2α such that 2αR = 2πr, where r is the radius of the large base.&#xD;&#xA;&#xD;&#xA;Subdivide the (truncated) sector in N faces. The coordinates are easily computed from the polar system.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now you can scale and translate so that the bounding box (found from four extreme points) goes where you want.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XJoBC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fzRU4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40215" PostHistoryTypeId="5" PostId="13378" RevisionGUID="42f627d5-a1c2-4c01-96e0-76217e201b27" CreationDate="2023-03-24T11:22:52.720" UserDisplayName="user1703" Comment="added 54 characters in body" Text="Consider a circular sector of radius R equal to the apothem of the whole cone, and angular aperture 2α such that 2αR = 2πr, where r is the radius of the large base.&#xD;&#xA;&#xD;&#xA;Subdivide the (truncated) sector in N faces. The coordinates are easily computed from the polar system.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Now you can scale and translate so that the bounding box (found from four extreme points) goes where you want. Note that anisotropic scaling will stretch the texture.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XJoBC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fzRU4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40216" PostHistoryTypeId="50" PostId="5996" RevisionGUID="afa3f440-8deb-4205-975b-e88c073bef67" CreationDate="2023-03-24T18:03:10.393" UserId="-1" />
  <row Id="40217" PostHistoryTypeId="50" PostId="13302" RevisionGUID="eea3a5a9-cc33-47d5-8d02-8995c1b302ef" CreationDate="2023-03-24T19:08:20.970" UserId="-1" />
  <row Id="40220" PostHistoryTypeId="2" PostId="13379" RevisionGUID="9c7d213c-70a5-4995-9b1f-ed29cb2244b0" CreationDate="2023-03-25T10:44:16.353" UserId="18034" Text="[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/veFQr.jpg&#xD;&#xA;&#xD;&#xA;I have been trying to apply normal maps to a rotating sphere with light shining directing from above the sphere (0,1,0). but lighting does not look correct under rotation as one side of the sphere appears darker and the top side of sphere does not seem lit as expected. &#xD;&#xA;&#xD;&#xA;I have tried using a fake normal of (0,0,1) and multiplying that by my TBN matrix to ensure the T,B,N are correct and that all seems to work as expected so I have run of ideas of what the issue might be.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA; if(has_normal_map){&#xD;&#xA;        simd_float3 colour = flatMap.sample(textureSampler, in.tex).rgb;&#xD;&#xA;        simd_float3 tangent = normalize(in.tangent - dot(in.tangent, in.normal) * in.normal);&#xD;&#xA;        simd_float3 bitangent = normalize(cross(in.normal, tangent));&#xD;&#xA;        simd_float3x3 TBN = simd_float3x3(normalize(tangent),bitangent,normalize(in.normal));&#xD;&#xA;        float3 normal = (normalMap.sample(textureSampler, in.tex)).rgb;&#xD;&#xA;        normal = (normal * 2.0 - 1.0);&#xD;&#xA;        normal = normalize(normal);&#xD;&#xA;        //normal = simd_float3(0,0,1);&#xD;&#xA;        normal = normalize(TBN * normal);&#xD;&#xA;        float attenuation = saturate(dot(light_vector,normal));&#xD;&#xA;        return float4(attenuation*colour,1);&#xD;&#xA;        &#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40222" PostHistoryTypeId="1" PostId="13379" RevisionGUID="9c7d213c-70a5-4995-9b1f-ed29cb2244b0" CreationDate="2023-03-25T10:44:16.353" UserId="18034" Text="Normal Map Under rotation Issue" ContentLicense="CC BY-SA 4.0" />
  <row Id="40223" PostHistoryTypeId="3" PostId="13379" RevisionGUID="9c7d213c-70a5-4995-9b1f-ed29cb2244b0" CreationDate="2023-03-25T10:44:16.353" UserId="18034" Text="|texture|transformations|lighting|normal-mapping|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40224" PostHistoryTypeId="2" PostId="13380" RevisionGUID="745997dc-1a1a-46ba-a5ea-2337638d29af" CreationDate="2023-03-25T15:35:00.707" UserDisplayName="user1703" Text="If Clipper has the capability of working with tagged edges (i.e. such that you can associate some label to every edge of the input polygons and retrieve these labels after clipping), then you can tag the edges with labels that relate to the individual original primitives (your circular arcs). Then by looking at the labels in the output, you can rebuild the modified arcs and from the endpoints determine the new angular extent. Beware that a single arc could be decomposed in several ones.&#xD;&#xA;&#xD;&#xA;If only vertices can be tagged, you can proceed similarly and use the edges having only one vertex with the correct tag, and obtain the arc endpoints from the other side of these edges.&#xD;&#xA;&#xD;&#xA;If no tags are possible, you can still perform a geometric matching between the original flattened arcs and the outlines produced by Clipper. In principle, comparison for strict equality should work because Clipper has no reason to alter the coordinates of the original vertices. For efficiency of the matching, a scanline method would be better than exhaustive comparison." ContentLicense="CC BY-SA 4.0" />
  <row Id="40226" PostHistoryTypeId="5" PostId="13380" RevisionGUID="5ed29b3e-c3bc-4e58-940e-79f5ec9d41b6" CreationDate="2023-03-25T15:45:52.923" UserDisplayName="user1703" Comment="added 516 characters in body" Text="If Clipper has the capability of working with tagged edges (i.e. such that you can associate some label to every edge of the input polygons and retrieve these labels after clipping), then you can tag the edges with labels that relate to the individual original primitives (your circular arcs). Then by looking at the labels in the output, you can rebuild the modified arcs and from the endpoints determine the new angular extent. Beware that a single arc could be decomposed in several ones.&#xD;&#xA;&#xD;&#xA;If only vertices can be tagged, you can proceed similarly and use the edges having only one vertex with the correct tag, and obtain the arc endpoints from the other side of these edges.&#xD;&#xA;&#xD;&#xA;If no tags are possible, you can still perform a geometric matching between the original flattened arcs and the outlines produced by Clipper. In principle, comparison for strict equality should work because Clipper has no reason to alter the coordinates of the original vertices. For efficiency of the matching, a scanline method would be better than exhaustive comparison.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Note that in your example, the discretization of the arc seems too fine. A simple rule is to adjust the discretization so that the distance between the chords and the arc do not exceed a given maximum distance.&#xD;&#xA;&#xD;&#xA;Now, after Clipper has computed the approximate intersections between lines and arcs (or between two arcs), if you know the identity of the original primitives, you can recompute the intersections exactly, using analytical formulas, and reconstruct the correct sequence of arcs/lines. As the primitives can intersect at more than one point, use the intersection closest to the Clipper point." ContentLicense="CC BY-SA 4.0" />
  <row Id="40227" PostHistoryTypeId="2" PostId="13381" RevisionGUID="fb97d883-7431-4b32-bfc5-e7296e7ceafb" CreationDate="2023-03-26T07:28:03.693" UserId="19766" Text="G'day,&#xD;&#xA;&#xD;&#xA;I have this strange effect when editing my image. It seems to happen a lot on photos with the sky in it, but in the CR2 file it doesn't show, only when i open it in the software i am using does it appear.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zxf3X.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40229" PostHistoryTypeId="1" PostId="13381" RevisionGUID="fb97d883-7431-4b32-bfc5-e7296e7ceafb" CreationDate="2023-03-26T07:28:03.693" UserId="19766" Text="how to fix this strange effect when editing image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40230" PostHistoryTypeId="3" PostId="13381" RevisionGUID="fb97d883-7431-4b32-bfc5-e7296e7ceafb" CreationDate="2023-03-26T07:28:03.693" UserId="19766" Text="|image-processing|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40231" PostHistoryTypeId="2" PostId="13382" RevisionGUID="05f26cf5-841a-4e7e-8a48-08ab8c0dbc86" CreationDate="2023-03-27T07:36:04.333" UserId="19537" Text="We have two different terms, for example, let's talk about scattering only.&#xD;&#xA;- Scattering coefficient&#xD;&#xA;- Scattering cross-section&#xD;&#xA;&#xD;&#xA;These two terms are supposed to have different physical meaning. I read it from the [PBR-book - Chapter 11](https://www.pbr-book.org/3ed-2018/Volume_Scattering/Volume_Scattering_Processes#Absorption) :&#xD;&#xA;&gt; Absorption is described by the medium’s absorption cross section, , which is the probability density that light is absorbed per unit distance traveled in the medium.&#xD;&#xA;&#xD;&#xA;But the wikipedia told me:&#xD;&#xA;&gt; The SI unit of attenuation coefficient is the reciprocal metre (m−1). [Reference](https://en.wikipedia.org/wiki/Attenuation_coefficient)&#xD;&#xA;&#xD;&#xA;And this:&#xD;&#xA;&gt; This is also commonly expressed as: $\sigma = \alpha /n$, where $\alpha$ is the absorption coefficient, $n$ is the atomic number density [Reference](https://en.wikipedia.org/wiki/Absorption_cross_section)&#xD;&#xA;&#xD;&#xA;So I suppose **xxx cross-section** and **xxx coefficient** should be different, therefore should have different unit. But it seems that, in rendering, these two terms are interchangeable? Like in mitsuba and PBRT we will set **$\sigma$** instead of $\mu$, although they are just names. In rendering, the so-called **cross-section** (in PBR-book) has the same unit as **xxx coefficient** ($m^{-1}$), but they should be distinguished by $N$, which should have the unit of $m^{-3}$.&#xD;&#xA;&#xD;&#xA;My confusion is what exactly are we setting in those renderers, and in theory, which term is the correct term to use? And, whether there is anything more work I should do, to convert the *unitless* distance in those renderers to be a physical value (Like multiply $\sigma_x$ by N)? " ContentLicense="CC BY-SA 4.0" />
  <row Id="40233" PostHistoryTypeId="1" PostId="13382" RevisionGUID="05f26cf5-841a-4e7e-8a48-08ab8c0dbc86" CreationDate="2023-03-27T07:36:04.333" UserId="19537" Text="Term confusion about volume scattering" ContentLicense="CC BY-SA 4.0" />
  <row Id="40234" PostHistoryTypeId="3" PostId="13382" RevisionGUID="05f26cf5-841a-4e7e-8a48-08ab8c0dbc86" CreationDate="2023-03-27T07:36:04.333" UserId="19537" Text="|physically-based|volume-rendering|theory|volumetric-scattering|scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40235" PostHistoryTypeId="2" PostId="13383" RevisionGUID="41516fc1-996c-45a0-bc60-f4aa4a19be2d" CreationDate="2023-03-29T16:38:07.880" UserId="19779" Text="Given a sequence of RGB-D images rendered by blender and the camera parameters for the blender camera(Perspective Projection camera). &#xD;&#xA;&#xD;&#xA;How can I back project the RGB images with depth map to a RGB point cloud? &#xD;&#xA;&#xD;&#xA;TL,DR: How to back project (Perspective Projection camera) the RGB point cloud with RGBD sequence?&#xD;&#xA;&#xD;&#xA;Thanks&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40237" PostHistoryTypeId="1" PostId="13383" RevisionGUID="41516fc1-996c-45a0-bc60-f4aa4a19be2d" CreationDate="2023-03-29T16:38:07.880" UserId="19779" Text="How to get back project point cloud from rendered rgbd images by rgbd?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40238" PostHistoryTypeId="3" PostId="13383" RevisionGUID="41516fc1-996c-45a0-bc60-f4aa4a19be2d" CreationDate="2023-03-29T16:38:07.880" UserId="19779" Text="|opengl|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40242" PostHistoryTypeId="2" PostId="13385" RevisionGUID="761c6283-05e1-4c3e-b9ca-ab920aa957b4" CreationDate="2023-03-30T17:40:48.220" UserId="19783" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Here are the tessellation shaders I'm using&#xD;&#xA;&#xD;&#xA;    // tessellation evaluation shader&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // tessellation control shader&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 128;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawArrays(GL_PATCHES, 0, 24);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BXmpD.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40244" PostHistoryTypeId="1" PostId="13385" RevisionGUID="761c6283-05e1-4c3e-b9ca-ab920aa957b4" CreationDate="2023-03-30T17:40:48.220" UserId="19783" Text="Having trouble rendering entire sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="40245" PostHistoryTypeId="3" PostId="13385" RevisionGUID="761c6283-05e1-4c3e-b9ca-ab920aa957b4" CreationDate="2023-03-30T17:40:48.220" UserId="19783" Text="|opengl|shader|glsl|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40246" PostHistoryTypeId="5" PostId="13385" RevisionGUID="b9d0fa7d-ee7b-44a4-9872-961d786b0bdc" CreationDate="2023-03-31T15:11:42.270" UserId="19783" Comment="Updated Source Code" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Here are the tessellation shaders I'm using&#xD;&#xA;&#xD;&#xA;    // tessellation evaluation shader&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // tessellation control shader&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(2);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BXmpD.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40247" PostHistoryTypeId="2" PostId="13386" RevisionGUID="b08ae4f9-0d8d-4627-a61a-7e58b6eb6b25" CreationDate="2023-03-31T16:27:56.080" UserId="19787" Text="*Re: do they need additional information about neighboring triangles?*&#xD;&#xA;If only the edge of the neighbor piece is known you cannot get smooth transitions to the neighbor piece.&#xD;&#xA;&#xD;&#xA;Try [Polyhedral Splines][1] &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://uf-cise-surflab.github.io/blender-polyhedral-splines-web/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40252" PostHistoryTypeId="50" PostId="10537" RevisionGUID="f7778d7e-7aeb-4d43-9d93-f5e93edc1237" CreationDate="2023-04-02T13:02:55.363" UserId="-1" />
  <row Id="40253" PostHistoryTypeId="2" PostId="13387" RevisionGUID="9ba10fd6-63a5-4bbf-af3a-b58fbb9c1c4d" CreationDate="2023-04-02T21:22:19.630" UserId="19796" Text="I am writing a renderer that uses a deferred clustered shading technique.&#xD;&#xA;On the CPU I group lights, decals, and environment maps into 3 seperate clustered structures (functionally, arrays of unsigned integers), and on the GPU at various stages in the shading pipeline I read from the clustered structure to decide which lights/decals/cubemaps to shade a pixel with. The shading stages are fullscreen passes.&#xD;&#xA;&#xD;&#xA;To move the cluster data from the CPU ot the GPU, I use a memcpy into a persistent mapped buffer (triple buffered, and using GL_MAP_COHERENT_BIT). The copy is to a Uniform Buffer Object. &#xD;&#xA;&#xD;&#xA;I see three possible ways I could order the CPU/GPU commands.&#xD;&#xA;&#xD;&#xA;Option A:&#xD;&#xA;&#xD;&#xA;    DecalClusterCPU();//Do the CPU stuff for Frame N&#xD;&#xA;    memcpy(...);//Copy the Data for Frame N&#xD;&#xA;    LightClusterCPU();&#xD;&#xA;    memcpy(...);&#xD;&#xA;    CubemapClusterCPU();&#xD;&#xA;    memcpy(...);&#xD;&#xA;    RenderGeometryGPU();&#xD;&#xA;    DecalPassGPU();//a compute shader, uses Decal Cluster data&#xD;&#xA;    ReflectionPassGPU();//a compute shader, uses Cubemap Cluster data&#xD;&#xA;    DenoiserPassGPU();//a compute shader&#xD;&#xA;    FinalShadingPassGPU();//a compute shader, uses Light Cluster Data&#xD;&#xA;    SwapBuffers();&#xD;&#xA;&#xD;&#xA;Option B:&#xD;&#xA;&#xD;&#xA;    DecalClusterCPU();&#xD;&#xA;    memcpy(...);&#xD;&#xA;    &#xD;&#xA;    RenderGeometryGPU();&#xD;&#xA;    DecalPassGPU();//a compute shader, uses Decal Cluster data&#xD;&#xA;    &#xD;&#xA;    CubemapClusterCPU();&#xD;&#xA;    memcpy(...);&#xD;&#xA;    &#xD;&#xA;    ReflectionPassGPU();//a compute shader, uses Cubemap Cluster data&#xD;&#xA;    DenoiserPassGPU();//a compute shader&#xD;&#xA;    &#xD;&#xA;    LightClusterCPU();&#xD;&#xA;    memcpy(...);&#xD;&#xA;    FinalShadingPassGPU();//a compute shader, uses Light Cluster Data&#xD;&#xA;    SwapBuffers();&#xD;&#xA;&#xD;&#xA;Option C:&#xD;&#xA;&#xD;&#xA;   &#xD;&#xA;    memcpy(...);//Copy the data for frame N&#xD;&#xA;    &#xD;&#xA;    memcpy(...);&#xD;&#xA; &#xD;&#xA;    memcpy(...);&#xD;&#xA;    RenderGeometryGPU();&#xD;&#xA;    DecalPassGPU();//a compute shader, uses Decal Cluster data&#xD;&#xA;    ReflectionPassGPU();//a compute shader, uses Cubemap Cluster data&#xD;&#xA;    DenoiserPassGPU();//a compute shader&#xD;&#xA;    FinalShadingPassGPU();//a compute shader, uses Light Cluster Data&#xD;&#xA;    SwapBuffers();&#xD;&#xA;    CubemapClusterCPU();//do the CPU stuff for frame N + 1&#xD;&#xA;    LightClusterCPU();&#xD;&#xA;    DecalClusterCPU();&#xD;&#xA;&#xD;&#xA; My essence of my question is:&#xD;&#xA; Is it a bad/good idea to perform CPU operations in the middle of performing OpenGL commands?&#xD;&#xA;How can rendering commands and CPU operations be ordered such to maximize concurrency (Avoid the GPU waiting for the CPU to add commands to the Queue).&#xD;&#xA;&#xD;&#xA;I have profiled the operations using CPU timings and Nvidia-Nsight and noted that on my machine:&#xD;&#xA;Decal CPU binning is about 2-3ms&#xD;&#xA;Light binning is about 0-1ms&#xD;&#xA;Cubemap binning is about 1ms&#xD;&#xA;&#xD;&#xA;Geometry Rendering is about 1.5ms&#xD;&#xA;Decal Pass is about 1.5ms&#xD;&#xA;Reflections (ray marched) is about 6ms&#xD;&#xA;Denoising is about 2ms&#xD;&#xA;&#xD;&#xA;The total frame time is about 15ms (including a shadow mapping section, particles, and the final shading pass). So performing the binning(GPU) in parallel with the GPU makes a lot of sense. For example, the Light binning could be done in parallel with the reflection pass, as the GPU doesnt need it until the final shading stage.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40255" PostHistoryTypeId="1" PostId="13387" RevisionGUID="9ba10fd6-63a5-4bbf-af3a-b58fbb9c1c4d" CreationDate="2023-04-02T21:22:19.630" UserId="19796" Text="Optimal Command Ordering for CPU/GPU concurrency" ContentLicense="CC BY-SA 4.0" />
  <row Id="40256" PostHistoryTypeId="3" PostId="13387" RevisionGUID="9ba10fd6-63a5-4bbf-af3a-b58fbb9c1c4d" CreationDate="2023-04-02T21:22:19.630" UserId="19796" Text="|opengl|shading|deferred-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40257" PostHistoryTypeId="5" PostId="13385" RevisionGUID="0313bebc-a9d0-4e0d-bfa7-bdb70c17fb28" CreationDate="2023-04-03T14:51:10.603" UserId="19783" Comment="Source code tidied up" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Here is my tessellation evaluation shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my tessellation control shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(2);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BXmpD.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40259" PostHistoryTypeId="50" PostId="9192" RevisionGUID="7e6ce839-72df-4e97-9657-3ac3e7d317a8" CreationDate="2023-04-04T04:06:55.827" UserId="-1" />
  <row Id="40260" PostHistoryTypeId="2" PostId="13388" RevisionGUID="50448edb-0b8e-4d4f-b0c5-d851738f0996" CreationDate="2023-04-04T12:30:21.693" UserId="19803" Text="I want to control the camera in an old game using head tracking (TrackIR, opentrack, etc.), such control was not provided by the game engine. I'm trying to find the camera coordinates and rotation angles in memory so that I can recalculate them with my program. I haven't worked seriously with 3D until now. So far I have found some float array in memory and am trying to figure out how it works.&#xD;&#xA;&#xD;&#xA;In the main menu of the game, when the map is not yet loaded, the values are:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the loaded map, I have screened 3 states when looking parallel to the axes of the map. In a practical way, moving around the map, I found the coordinates X, Y, Z (Z - height)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6z11L.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SzqpF.png&#xD;&#xA;&#xD;&#xA;Googling a bit, I think it's possible &quot;View matrix&quot; or &quot;Rotate matrix&quot;. I ask for help from those who understand 3D, did I determine correctly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40262" PostHistoryTypeId="1" PostId="13388" RevisionGUID="50448edb-0b8e-4d4f-b0c5-d851738f0996" CreationDate="2023-04-04T12:30:21.693" UserId="19803" Text="Unknown array of floating point numbers. View matrix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40263" PostHistoryTypeId="3" PostId="13388" RevisionGUID="50448edb-0b8e-4d4f-b0c5-d851738f0996" CreationDate="2023-04-04T12:30:21.693" UserId="19803" Text="|3d|camera|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40264" PostHistoryTypeId="5" PostId="13388" RevisionGUID="5c194e6d-73ba-4980-a306-6ead25e26502" CreationDate="2023-04-04T12:36:56.447" UserId="19803" Comment="added 49 characters in body" Text="I want to control the camera in an old game using head tracking (TrackIR, opentrack, etc.), such control was not provided by the game engine. I'm trying to find the camera coordinates and rotation angles in memory so that I can recalculate them with my program. I haven't worked seriously with 3D until now. So far I have found some float array in memory and am trying to figure out how it works.&#xD;&#xA;&#xD;&#xA;In the main menu of the game, when the map is not yet loaded, the values are:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;In the loaded map, I have screened 3 states when looking parallel to the axes of the map. In a practical way, moving around the map, I found the coordinates X, Y, Z (Z - height)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6z11L.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/SzqpF.png&#xD;&#xA;&#xD;&#xA;Googling a bit, I think it's possible &quot;View matrix&quot; or &quot;Rotate matrix&quot;. I ask for help from those who understand 3D, did I determine correctly? Links to articles on how it works are welcome :)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40265" PostHistoryTypeId="2" PostId="13389" RevisionGUID="fea8e16b-0ac1-4a4a-8dab-2646221480a9" CreationDate="2023-04-04T12:49:53.103" UserId="19804" Text="I've built a renderer which should render glTF materials, as they are defined in their [specification][1]. So I should be able to render satisfying (similar to Cycles and Ospray) results just from the base color, metallic and roughness factors. I've implemented their suggested [BRDF][2], but I'm afraid I'm using it wrong, or I'm making a mistake somewhere else. &#xD;&#xA;&#xD;&#xA;I'll now describe the steps in my renderer, using the simplest example: light is given by an HDR background and there is one object in the scene with **roughness = 0 and metallic = 1**. I've also attached a sketch of what I'm talking about so it's easier to follow.&#xD;&#xA;&#xD;&#xA;Steps in bouncing:&#xD;&#xA;1. Ray is shot from the camera&#xD;&#xA;2. Ray hits object&#xD;&#xA;3. Ray bounces in a mirror-like fashion because of the mentioned material properties&#xD;&#xA;4. Ray hits HDR (hit on the HDR = miss all other objects)&#xD;&#xA;5. Path ends&#xD;&#xA;&#xD;&#xA;Reporting works like this:&#xD;&#xA;1. I have the entire path with all three points (HDR, object, camera). &#xD;&#xA;2. I start from the HDR and assign the path RGB values to the RGB values at the sampled point on the HDR. For example, path.RGB = (0.2, 0.8, 0.9).&#xD;&#xA;3. I continue along the path and come to the point on the object. From the intersection data I get all the necessary information (base color, metallic, roughness and the normal at that point).&#xD;&#xA;4. I provide all that info to the BRDF function and it returns some RGB values.&#xD;&#xA;5. I multiply the RGB values which I got from the BRDF with the current path RGB (which is just the HDR values at this point) and that becomes the new path RGB.&#xD;&#xA;6. I get to the camera point, and save the path RGB for writing to image later.&#xD;&#xA;&#xD;&#xA;I simplified some parts which I'm fairly certain are not the cause of the problem, like the distance dependency and sampling and stuff like that.&#xD;&#xA;&#xD;&#xA;So to get to the **actual problem**,&#xD;&#xA;&#xD;&#xA;at the second point on the path (object intersection), my **light vector** is pointing towards the point on the HDR and my **view vector** is pointing towards the camera. Since the roughness at this point is 0, these two vectors are mirror images of one another, around the normal vector. So their **half vector** is the same vector as the **normal vector**. &#xD;&#xA;And when H (half vector) and N (normal vector) are the same, the BRDF produces a specular highlight, that happens because the D term (Trowbridge-Reitz/GGX microfacet distribution) ends up as a ridiculously large value. Now I'm aware that this should happen, If I were to use a point light source instead of the HDR, I would get the appropriate specular highlight, but that's because the light vector in that case is defined by the position of point light, and only a few points on the surface would fulfill the condition where H and N are the same (or no rays would in case of no roughness and point light with no radius). Problem appears when the light direction is the next point on the path since the direction towards it is the perfect reflection of the incident ray.&#xD;&#xA;&#xD;&#xA;In the image I've attached, all rays hitting the object would bounce mirror-like, and each point on the object would be considered a specular highlight by the BRDF and it would return RGB values which go up to 8e14. By multiplying the path.RGB with those values, I would break the energy conservation, so currently I normalize them, but that also leads to problems. Black objects report with values around 5e10, and white objects as 8e14, as mentioned. Both end up normalized to (1, 1, 1) and look the same, even though they're opposites. &#xD;&#xA;&#xD;&#xA;Now I'm not sure where exactly I'm I making a mistake, I've had my implementation of the BRDF checked multiple times, it's exactly like the specification.&#xD;&#xA;&#xD;&#xA;Is my mistake considering the light vector to be the next (or previous, depends where you start from) point on the path? Or is it something else?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Example][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#materials&#xD;&#xA;  [2]: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#appendix-b-brdf-implementation&#xD;&#xA;  [3]: https://i.stack.imgur.com/y4qsf.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40267" PostHistoryTypeId="1" PostId="13389" RevisionGUID="fea8e16b-0ac1-4a4a-8dab-2646221480a9" CreationDate="2023-04-04T12:49:53.103" UserId="19804" Text="How to properly use the BRDF from glTF 2.0 specification in path tracing while using metallic/roughness materials?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40268" PostHistoryTypeId="3" PostId="13389" RevisionGUID="fea8e16b-0ac1-4a4a-8dab-2646221480a9" CreationDate="2023-04-04T12:49:53.103" UserId="19804" Text="|raytracing|pathtracing|brdf|gltf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40269" PostHistoryTypeId="2" PostId="13390" RevisionGUID="139ff092-87f5-4ad4-a64b-a95cc514d829" CreationDate="2023-04-04T19:47:03.257" UserId="506" Text="Yep, that looks like a view matrix. A matrix can be stored in either [row- or column-major order](https://en.wikipedia.org/wiki/Row-_and_column-major_order); that one appears to be column-major. As you’ve identified, the last row / column of it (the values you’ve marked as X, Y, and Z) are the camera position (followed by a 1, for [complicated reasons](https://en.wikipedia.org/wiki/Homogeneous_coordinates)); that would make the other three rows / columns the X, Y, and Z [basis vectors](https://en.wikipedia.org/wiki/Basis_(linear_algebra)) (at …`98`, `A8`, and `B8` respectively).&#xD;&#xA;&#xD;&#xA;As Yves noted in the comments, getting a rotation out of those vectors is tricky. Fortunately, you may not have to: your head-tracking library should be able to give you a transform matrix containing the axes of the camera with the appropriate rotations applied. If you plug those values in to the appropriate places in your in-memory matrix (…and possibly spend some time swapping them around and/or negating them, to line up with whatever coordinate space your game uses), you should be good to go." ContentLicense="CC BY-SA 4.0" />
  <row Id="40271" PostHistoryTypeId="2" PostId="13391" RevisionGUID="0ac08b7d-bbf2-4377-b2a4-5fc4e66e64a8" CreationDate="2023-04-04T22:15:07.360" UserId="10178" Text="Twenty years ago I made a descriptive illustration program whose output was the industrial standard Encapsulated PostScript, which is also compatible with the LaTeX system. In order to write accented characters (a very important feature for Spanish texts), I created an ISOLatin1Encoding which was rather very simple. &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;/ISOLatin1Encoding where {&#xD;&#xA;} {&#xD;&#xA;	(ISOLatin1 does not exist, creating...) =&#xD;&#xA;	/ISOLatin1Encoding StandardEncoding STARTDIFFENC&#xD;&#xA;		144 /dotlessi /grave /acute /circumflex /tilde &#xD;&#xA;		/macron /breve /dotaccent /dieresis /.notdef /ring &#xD;&#xA;		/cedilla /.notdef /hungarumlaut /ogonek /caron /space &#xD;&#xA;		/exclamdown /cent /sterling /currency /yen /brokenbar &#xD;&#xA;		/section /dieresis /copyright /ordfeminine &#xD;&#xA;		/guillemotleft /logicalnot /hyphen /registered &#xD;&#xA;		/macron /degree /plusminus /twosuperior &#xD;&#xA;		/threesuperior /acute /mu /paragraph /periodcentered &#xD;&#xA;		/cedilla /onesuperior /ordmasculine /guillemotright &#xD;&#xA;		/onequarter /onehalf /threequarters /questiondown &#xD;&#xA;		/Agrave /Aacute /Acircumflex /Atilde /Adieresis &#xD;&#xA;		/Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex &#xD;&#xA;		/Edieresis /Igrave /Iacute /Icircumflex /Idieresis &#xD;&#xA;		/Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde &#xD;&#xA;		/Odieresis /multiply /Oslash /Ugrave /Uacute &#xD;&#xA;		/Ucircumflex /Udieresis /Yacute /Thorn /germandbls &#xD;&#xA;		/agrave /aacute /acircumflex /atilde /adieresis &#xD;&#xA;		/aring /ae /ccedilla /egrave /eacute /ecircumflex &#xD;&#xA;		/edieresis /igrave /iacute /icircumflex /idieresis &#xD;&#xA;		/eth /ntilde /ograve /oacute /ocircumflex /otilde &#xD;&#xA;		/odieresis /divide /oslash /ugrave /uacute &#xD;&#xA;		/ucircumflex /udieresis /yacute /thorn /ydieresis&#xD;&#xA;	ENDDIFFENC&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/REENCODEFONT { % /Newfont NewEncoding /Oldfont&#xD;&#xA;	findfont dup length 4 add dict&#xD;&#xA;	begin&#xD;&#xA;		{ % forall&#xD;&#xA;			1 index /FID ne &#xD;&#xA;&#xD;&#xA;			2 index /UniqueID ne and&#xD;&#xA;			2 index /XUID ne and&#xD;&#xA;			{ def } { pop pop } ifelse&#xD;&#xA;		} forall&#xD;&#xA;		/Encoding exch def&#xD;&#xA;		% defs for DPS&#xD;&#xA;		/BitmapWidths false def&#xD;&#xA;		/ExactSize 0 def&#xD;&#xA;		/InBetweenSize 0 def&#xD;&#xA;		/TransformedChar 0 def&#xD;&#xA;		currentdict&#xD;&#xA;	end&#xD;&#xA;	definefont pop&#xD;&#xA;} bind def&#xD;&#xA;&#xD;&#xA;/ISOTimes-Roman ISOLatin1Encoding /Times-Roman REENCODEFONT&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Nowadays Latin1 was replaced by UTF-8 and there is nothing I can do about it, it is currently supported by most operative systems. Is there a simple way to use UTF-8 in EPS files or I will have to create another code to reencoding?&#xD;&#xA;&#xD;&#xA;Thank you in advance for any hints." ContentLicense="CC BY-SA 4.0" />
  <row Id="40273" PostHistoryTypeId="1" PostId="13391" RevisionGUID="0ac08b7d-bbf2-4377-b2a4-5fc4e66e64a8" CreationDate="2023-04-04T22:15:07.360" UserId="10178" Text="How to encode UTF inside an Encapsulated PostScript" ContentLicense="CC BY-SA 4.0" />
  <row Id="40274" PostHistoryTypeId="3" PostId="13391" RevisionGUID="0ac08b7d-bbf2-4377-b2a4-5fc4e66e64a8" CreationDate="2023-04-04T22:15:07.360" UserId="10178" Text="|vector-graphics|font-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40279" PostHistoryTypeId="5" PostId="13385" RevisionGUID="d2927498-6479-43c8-a945-f90ec2b8eefe" CreationDate="2023-04-05T15:58:31.233" UserId="19783" Comment="deleted 138 characters in body" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Here is my tessellation evaluation shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my tessellation control shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BXmpD.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40280" PostHistoryTypeId="50" PostId="2516" RevisionGUID="524bc095-1760-4864-b80e-1ef1742c901f" CreationDate="2023-04-05T17:07:40.960" UserId="-1" />
  <row Id="40281" PostHistoryTypeId="5" PostId="13385" RevisionGUID="0e543f87-49a0-40c8-826c-955f85b861ed" CreationDate="2023-04-05T18:01:39.203" UserId="19783" Comment="added 91 characters in body" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Here is my tessellation evaluation shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my tessellation control shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from. Note that in this tutorial, the person uses an icosahedron, while I'm using an octahedron https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BXmpD.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40282" PostHistoryTypeId="50" PostId="9549" RevisionGUID="2c399a01-20ae-4032-b271-6cb0eab9f50b" CreationDate="2023-04-05T18:08:00.937" UserId="-1" />
  <row Id="40283" PostHistoryTypeId="50" PostId="13340" RevisionGUID="d188e40e-f933-4366-ab54-e6ea3ee2d885" CreationDate="2023-04-05T19:07:05.850" UserId="-1" />
  <row Id="40284" PostHistoryTypeId="50" PostId="13352" RevisionGUID="3dcd07ae-a9fe-4441-971d-7271bc930bde" CreationDate="2023-04-06T12:00:15.060" UserId="-1" />
  <row Id="40291" PostHistoryTypeId="2" PostId="13394" RevisionGUID="d79900d1-c169-474f-b292-56b42c729e99" CreationDate="2023-04-06T13:48:45.230" UserDisplayName="user19809" Text="I want to create a rendering engine that mostly renders parametric curves on a 2d screen. As far as it seems, todays graphics are all dependent on vertices and matrices, so not sure where to start or merge things.&#xD;&#xA;&#xD;&#xA;Lets say I want to draw a circle(starting simple), &#xD;&#xA;So my object is defined as (*r cos(t), r sin(t)*). Where t ranges from 0 to 2pi. Now whats the best approach to put this information to screen, (or say a png for example). I also want a uniform smooth path, of which i can control the stroke width, and thats being the hard piece of the puzzle. &#xD;&#xA;&#xD;&#xA;Is there exists a rendering method that does this? Where objects are defined and rendered mathematicaly ? And will it be possible to extend that to 3D as well?&#xD;&#xA;&#xD;&#xA;Also, I want my object to be defined the way it is; and not want to approximate points and then render them the opengl way. I want the process to feel more procedural. &#xD;&#xA;&#xD;&#xA;I would also really appreciate any advice or resources on this topic, its being really hard to even start." ContentLicense="CC BY-SA 4.0" />
  <row Id="40293" PostHistoryTypeId="1" PostId="13394" RevisionGUID="d79900d1-c169-474f-b292-56b42c729e99" CreationDate="2023-04-06T13:48:45.230" UserDisplayName="user19809" Text="Whats the best way to render (2D) parametric curves with uniform stroke width?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40294" PostHistoryTypeId="3" PostId="13394" RevisionGUID="d79900d1-c169-474f-b292-56b42c729e99" CreationDate="2023-04-06T13:48:45.230" UserDisplayName="user19809" Text="|rendering|mathematics|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40299" PostHistoryTypeId="50" PostId="10748" RevisionGUID="b12fa8f4-a1ba-4f49-be4c-b9f8245c33ab" CreationDate="2023-04-06T18:03:20.377" UserId="-1" />
  <row Id="40300" PostHistoryTypeId="2" PostId="13396" RevisionGUID="2610d30d-0fac-452e-8435-586604256499" CreationDate="2023-04-06T19:45:19.093" UserDisplayName="user1703" Text="Here is a method that is &quot;best&quot; is some sense.&#xD;&#xA;&#xD;&#xA;Scan the image, and for every pixel at $(x,y)$ compute the quantity&#xD;&#xA;&#xD;&#xA;$$t=\frac{2|\sqrt{(x-x_c)^2+(y-y_c)^2}-r|}{\theta}=\frac{2d}{\theta}$$&#xD;&#xA;&#xD;&#xA;where $(x_c,y_c)$ is the center of the circle, $r$ the radius, and $\theta$ the desired thickness. ($d$ is the distance of the pixel to the circle.)&#xD;&#xA;&#xD;&#xA;Now if $t&lt;1$ assign this pixel a color that is the linear interpolation between the foreground and the background color, with weights $t$ and $1-t$." ContentLicense="CC BY-SA 4.0" />
  <row Id="40302" PostHistoryTypeId="5" PostId="13396" RevisionGUID="12a6e244-5f4d-42ea-8e7f-88f034c0665c" CreationDate="2023-04-06T19:50:23.900" UserDisplayName="user1703" Comment="added 375 characters in body" Text="Here is a method that is &quot;best&quot; is some sense.&#xD;&#xA;&#xD;&#xA;Scan the image, and for every pixel at $(x,y)$ compute the quantity&#xD;&#xA;&#xD;&#xA;$$t=\frac{2|\sqrt{(x-x_c)^2+(y-y_c)^2}-r|}{\theta}=\frac{2d}{\theta}$$&#xD;&#xA;&#xD;&#xA;where $(x_c,y_c)$ is the center of the circle, $r$ the radius, and $\theta$ the desired thickness. ($d$ is the distance of the pixel to the circle.)&#xD;&#xA;&#xD;&#xA;Now if $t&lt;1$ assign this pixel a color that is the linear interpolation between the foreground and the background color, with weights $t$ and $1-t$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;This method is not efficient as is scans the whole image. You can fix that by using the parametric equation with a suitable step, and for every distinct pixel, apply the above computation in a neighborhood large enough to cover the stroke width.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;For other shapes, the procedure is the same, replacing $d$ by the distance to the given curve." ContentLicense="CC BY-SA 4.0" />
  <row Id="40303" PostHistoryTypeId="2" PostId="13397" RevisionGUID="400a7466-7d27-4ead-ad1a-7a31095b5ccd" CreationDate="2023-04-06T19:51:40.103" UserId="8925" Text="I am experimenting with procedural meshes. Those are generated at runtime in a compute shader. I'm getting to the point where those geometries are big enough to require some sort of culling/LODing techniques. Both requires the bounding box of the object, but this bounding box cannot be computed from the current LOD section, otherwise the information will be incomplete and thus the culling won't be conservative.&#xD;&#xA;&#xD;&#xA;For offline mesh generation, the problem doesn't exist, because the bounding box of the fully detailed object is available. This is not true with procedural geometries, as generating the most detailed version of the mesh is too costly, if not impossible for memory reasons.&#xD;&#xA;&#xD;&#xA;Computing the bounding box from the current sections works to some degree, but it's very dependent on the geometry, eg with a big enough frequency, it will be incorrect and sections will be culled when they should be visible.&#xD;&#xA;&#xD;&#xA;Depending on how the mesh is generated, it's possible to be conservative by computing the real bounding box by replacing variables by the min/max possible values. But it's only possible to be conservative by limiting how the mesh is generated. If the mesh is generated from complex maths functions such as noises, then the min/max are meaningless and this information is either hard or impossible to compute.&#xD;&#xA;&#xD;&#xA;I haven't seen much mentions of this problem before, yet it should affect any acceleration structure algorithm.. Maybe by lack of terminology, or maybe because runtime procedural meshes are not common enough. Anyway, I'm looking for directions on how to solve this problem, or articles where people mention this problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="40305" PostHistoryTypeId="1" PostId="13397" RevisionGUID="400a7466-7d27-4ead-ad1a-7a31095b5ccd" CreationDate="2023-04-06T19:51:40.103" UserId="8925" Text="LOD/culling algorithms with procedural meshes" ContentLicense="CC BY-SA 4.0" />
  <row Id="40306" PostHistoryTypeId="3" PostId="13397" RevisionGUID="400a7466-7d27-4ead-ad1a-7a31095b5ccd" CreationDate="2023-04-06T19:51:40.103" UserId="8925" Text="|mesh|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40307" PostHistoryTypeId="5" PostId="13394" RevisionGUID="14ea930a-96df-4546-b1ba-4084fbc2b4b9" CreationDate="2023-04-07T00:23:19.923" UserDisplayName="user19809" Comment="added 1 character in body" Text="I want to create a rendering engine that mostly renders parametric curves on a 2d screen. As far as it seems, todays graphics are all dependent on vertices and matrices, so not sure where to start or merge things.&#xD;&#xA;&#xD;&#xA;Lets say I want to draw a ellipse(starting simple), &#xD;&#xA;So my object is defined as (*a cos(t), b sin(t)*). Where t ranges from 0 to 2pi. Now whats the best approach to put this information to screen, (or say a png for example). I also want a uniform smooth path, of which i can control the stroke width, and thats being the hard piece of the puzzle. &#xD;&#xA;&#xD;&#xA;Is there exists a rendering method that does this? Where objects are defined and rendered mathematicaly ? And will it be possible to extend that to 3D as well?&#xD;&#xA;&#xD;&#xA;Also, I want my object to be defined the way it is; and not want to approximate points and then render them the opengl way. I want the process to feel more procedural. &#xD;&#xA;&#xD;&#xA;I would also really appreciate any advice or resources on this topic, its being really hard to even start." ContentLicense="CC BY-SA 4.0" />
  <row Id="40308" PostHistoryTypeId="2" PostId="13398" RevisionGUID="1a1c682b-d8f6-470a-b158-55d8d7086709" CreationDate="2023-04-07T13:42:39.480" UserId="7952" Text="&#xD;&#xA;Your question implies that *everything* has to be rendered with a vertex representing each small piece of a curve. This simply isn't accurate. It also implies that device rendering space is in some way continuous.&#xD;&#xA;&#xD;&#xA;In computer graphics all the devices we draw to are discreet. There is no continuous space so any rendering is going to be an approximation. Even the underlying math is discreet, in floating point math most computations will still be approximations of the actual answer since most results can not be fully represented.&#xD;&#xA;&#xD;&#xA;Having set an appropriate expectation we can still get pretty good approximations of most curves.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For example, a curve can be rendered inside a shape that is defined by vertex attributes which bound the curve. Once the curve is bounded each pixel inside the bounding area is tested for it's distance to the curve and its color set appropriately. The vertex data simply limits the region that is tested. When used properly this approach can greatly enhance the performance of a drawing algorithm.&#xD;&#xA;&#xD;&#xA;Throw away the strictly binary notion of &quot;on&quot; or &quot;off&quot; the curve. The curve itself is infinitesimally small and we can never hope to hit it exactly no matter the zoom. Instead it is a question of &quot;how far away&quot; is the *center* of this pixel from the curve. The *center* of a pixel can be thought of as being infinitesimally small so it has the potential of being exactly on the curve. But when the pixel is set, it takes up real space which will can't come close to representing a continuous curve. Instead combine &quot;at what distance&quot; do we want to start showing the curve with &quot;how far away&quot; is the center of the pixel from the curve to get an approximation for the color of the pixel.&#xD;&#xA;&#xD;&#xA;These two ideas allow curves to be render very thick, or very thin. It also allows the color of the pixels to be blended with the background color so that the pixels themselves have some representation of distance. Get to far away and the pixel is the background color, get close enough and the pixel is the foreground color. Everything in between not only helps with aliasing, but also helps us visualize the distances involved.&#xD;&#xA;&#xD;&#xA;This breaks the problem of rendering the curve down into two pieces.&#xD;&#xA;&#xD;&#xA;1) Calculate the bounding region for the curve and generate appropriate vertex data. Typically done either on the CPU or in a compute shader.&#xD;&#xA;&#xD;&#xA;2) Draw the curve by computing the distance from the center of each pixel to the curve. Typically done with a vertex/fragment shader combo.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40310" PostHistoryTypeId="5" PostId="13396" RevisionGUID="26040b59-c760-45fa-879c-37ba270365af" CreationDate="2023-04-07T15:56:23.643" UserDisplayName="user1703" Comment="added 44 characters in body" Text="Here is a method that is &quot;best&quot; is some sense.&#xD;&#xA;&#xD;&#xA;Scan the image, and for every pixel at $(x,y)$ compute the quantity&#xD;&#xA;&#xD;&#xA;$$t=\min\left(1,\theta-\frac12\left|\sqrt{(x-x_c)^2+(y-y_c)^2}-r\right|\right)=\min\left(1,|\theta-2d|\right)$$&#xD;&#xA;&#xD;&#xA;where $(x_c,y_c)$ is the center of the circle, $r$ the radius, and $\theta$ the desired thickness. ($d$ is the distance of the pixel to the circle.)&#xD;&#xA;&#xD;&#xA;Now if $t\ge 0$ assign this pixel a color that is the linear interpolation between the foreground and the background color, with weights $t$ and $1-t$.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;This method is not efficient as is scans the whole image. You can fix that by using the parametric equation with a suitable step, and for every distinct pixel, apply the above computation in a neighborhood large enough to cover the stroke width.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;For other shapes, the procedure is the same, replacing $d$ by the distance to the given curve." ContentLicense="CC BY-SA 4.0" />
  <row Id="40311" PostHistoryTypeId="2" PostId="13399" RevisionGUID="232e5671-e5e8-4b95-ac76-f8f8b8784868" CreationDate="2023-04-07T23:48:29.373" UserId="11224" Text="I think that VR / AR experts will know the answer to this.&#xD;&#xA;&#xD;&#xA;I believe I have read that the stars in the night sky are so far away that our human visual system cannot distinguish between the degree of vergence required to look at them, and &quot;parallel vergence&quot;, where the view directions of the two eyes are parallel. That is, the stars are so far away that in this particular sense, they may as well be infinitely far away.&#xD;&#xA;&#xD;&#xA;In my experiments with anaglyph displays on laptop screens, I have found that it is very uncomfortable to diverge my eyes to the point of parallel view directions, in order to resolve star field textures that are &quot;infinitely distant&quot;, i.e., in which the left and right images are separated horizontally by exactly my interpupillary distance.&#xD;&#xA;&#xD;&#xA;In case this might be due to measurement errors causing the separation on screen to very slightly exceed my actual interpupillary distance, I have experiment with reducing that separation one mm at a time, until the degree of vergence became tolerably comfortable. However, this required a separation difference that was significantly smaller than my actual interpupillary distance, tending to refute the &quot;measurement errors&quot; hypothesis.&#xD;&#xA;&#xD;&#xA;Is the discomfort likely to be due more to the well-known contradiction between vergence and accommodation (focus) that is a drawback of conventional stereoscopic displays ?&#xD;&#xA;&#xD;&#xA;In VR headsets, does the greater focal depth alleviate this problem, i.e. is the limit of comfort for vergence closer to parallel, in this case ?&#xD;&#xA;&#xD;&#xA;I have read that parallel vergence should be avoided in stereoscopic displays, because it is unnatural for our visual system, but I have not read any explanation as to why (almost) parallel vergence is perfectly comfortable for viewing stars in the real world. Might it also be to do with the fact that the solid angle subtended on earth by a star in the real world is very small ?&#xD;&#xA;&#xD;&#xA;Are some of my assumptions wrong ?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40313" PostHistoryTypeId="1" PostId="13399" RevisionGUID="232e5671-e5e8-4b95-ac76-f8f8b8784868" CreationDate="2023-04-07T23:48:29.373" UserId="11224" Text="&quot;Infinitely far away&quot; objects in stereoscopic displays" ContentLicense="CC BY-SA 4.0" />
  <row Id="40314" PostHistoryTypeId="3" PostId="13399" RevisionGUID="232e5671-e5e8-4b95-ac76-f8f8b8784868" CreationDate="2023-04-07T23:48:29.373" UserId="11224" Text="|texture|perspective|virtual-reality|human-vision|stereo-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40316" PostHistoryTypeId="50" PostId="12746" RevisionGUID="f7bc5993-3b1c-47d9-a20b-a738f89274be" CreationDate="2023-04-08T10:03:40.377" UserId="-1" />
  <row Id="40317" PostHistoryTypeId="50" PostId="2146" RevisionGUID="93a6a13b-bc58-4dc0-b907-54d037fb3ddf" CreationDate="2023-04-08T12:00:10.063" UserId="-1" />
  <row Id="40318" PostHistoryTypeId="5" PostId="13399" RevisionGUID="e92372ef-e8a7-43e2-b1f5-0a01f519f8dd" CreationDate="2023-04-08T17:47:03.097" UserId="11224" Comment="Corrected a typo by changing 'experiment' to 'experimented' and added a crucial question that I had forgotten to add." Text="I think that VR / AR experts will know the answer to this.&#xD;&#xA;&#xD;&#xA;I believe I have read that the stars in the night sky are so far away that our human visual system cannot distinguish between the degree of vergence required to look at them, and &quot;parallel vergence&quot;, where the view directions of the two eyes are parallel. That is, the stars are so far away that in this particular sense, they may as well be infinitely far away.&#xD;&#xA;&#xD;&#xA;In my experiments with anaglyph displays on laptop screens, I have found that it is very uncomfortable to diverge my eyes to the point of parallel view directions, in order to resolve star field textures that are &quot;infinitely distant&quot;, i.e., in which the left and right images are separated horizontally by exactly my interpupillary distance.&#xD;&#xA;&#xD;&#xA;In case this might be due to measurement errors causing the separation on screen to very slightly exceed my actual interpupillary distance, I have experimented with reducing that separation one mm at a time, until the degree of vergence became tolerably comfortable. However, this required a separation difference that was significantly smaller than my actual interpupillary distance, tending to refute the &quot;measurement errors&quot; hypothesis.&#xD;&#xA;&#xD;&#xA;Is the discomfort likely to be due more to the well-known contradiction between vergence and accommodation (focus) that is a drawback of conventional stereoscopic displays ?&#xD;&#xA;&#xD;&#xA;In VR headsets, does the greater focal depth alleviate this problem, i.e. is the limit of comfort for vergence closer to parallel, in this case ?&#xD;&#xA;&#xD;&#xA;I have read that parallel vergence should be avoided in stereoscopic displays, because it is unnatural for our visual system, but I have not read any explanation as to why (almost) parallel vergence is perfectly comfortable for viewing stars in the real world. Might it also be to do with the fact that the solid angle subtended on earth by a star in the real world is very small ?&#xD;&#xA;&#xD;&#xA;Are some of my assumptions wrong ?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I forgot to ask, what vergence angle do programmers of VR simulations with star fields choose for the distant stars ? Parallel ? Less than parallel ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40319" PostHistoryTypeId="50" PostId="11048" RevisionGUID="a0a2bb72-2ce5-42c2-b59b-e9ec2bb1ac68" CreationDate="2023-04-08T18:01:30.160" UserId="-1" />
  <row Id="40320" PostHistoryTypeId="2" PostId="13400" RevisionGUID="91b50819-3d1d-4651-a19e-5a057bf53d86" CreationDate="2023-04-08T19:39:15.833" UserId="19817" Text="I understand *what* C1 and G1 continuity are (e.g. this is not https://computergraphics.stackexchange.com/questions/12323/continuity-of-parametric-and-geometric-continuity).&#xD;&#xA;&#xD;&#xA;But let's say I have a list of cubic splines that are, together, G1 continuous. Is there a canonical way of producing a re-parametrization that has C1 continuity? This may be obvious and I have failed to consider it properly." ContentLicense="CC BY-SA 4.0" />
  <row Id="40322" PostHistoryTypeId="1" PostId="13400" RevisionGUID="91b50819-3d1d-4651-a19e-5a057bf53d86" CreationDate="2023-04-08T19:39:15.833" UserId="19817" Text="Is there a canonical way to convert G1 continuity to C1 continuity for splines" ContentLicense="CC BY-SA 4.0" />
  <row Id="40323" PostHistoryTypeId="3" PostId="13400" RevisionGUID="91b50819-3d1d-4651-a19e-5a057bf53d86" CreationDate="2023-04-08T19:39:15.833" UserId="19817" Text="|bezier-curve|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40324" PostHistoryTypeId="50" PostId="8886" RevisionGUID="c9f91aa5-73aa-4e99-ad80-fb765153a59b" CreationDate="2023-04-08T20:05:15.607" UserId="-1" />
  <row Id="40325" PostHistoryTypeId="50" PostId="11049" RevisionGUID="1af1f60a-4734-46b7-8a8e-da072fbc4353" CreationDate="2023-04-08T21:00:45.123" UserId="-1" />
  <row Id="40326" PostHistoryTypeId="2" PostId="13401" RevisionGUID="1d49a541-f7e9-49e2-b95b-d5d729ea3684" CreationDate="2023-04-09T01:02:11.293" UserId="19690" Text="i'am a junior in computer graphics , currently i learn how to draw ellipses with rotation .&#xD;&#xA;&#xD;&#xA;when i preform rotation with 90deg or 180deg nothing unusual happened ,&#xD;&#xA;but when i try to rotate with any other value the result will be like this :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lX7YK.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40328" PostHistoryTypeId="1" PostId="13401" RevisionGUID="1d49a541-f7e9-49e2-b95b-d5d729ea3684" CreationDate="2023-04-09T01:02:11.293" UserId="19690" Text="drawing ellipse with rotation cause inaccurate result" ContentLicense="CC BY-SA 4.0" />
  <row Id="40329" PostHistoryTypeId="3" PostId="13401" RevisionGUID="1d49a541-f7e9-49e2-b95b-d5d729ea3684" CreationDate="2023-04-09T01:02:11.293" UserId="19690" Text="|2d|drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40330" PostHistoryTypeId="5" PostId="13401" RevisionGUID="b98f80ab-bd55-42e8-b2d4-7f1422dd5d71" CreationDate="2023-04-09T08:23:32.207" UserId="19690" Comment="added 940 characters in body" Text="i'am a junior in computer graphics , currently i learn how to draw ellipses with rotation .&#xD;&#xA;&#xD;&#xA;when i preform rotation with 90deg or 180deg nothing unusual happened ,&#xD;&#xA;but when i try to rotate with any other value the result will be like this :&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lX7YK.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;here's a pseudo-code of what iam doing , i didn't put the original function because it's huge . &#xD;&#xA;&#xD;&#xA;    function draw_circle( x_origin , y_origin , width , height ){&#xD;&#xA;    &#xD;&#xA;    // go in scan-line order and try to find intercept x,y around the ellipse&#xD;&#xA;       for( y = 0 ; y &lt;= height ; y++ ){   &#xD;&#xA;    &#xD;&#xA;           for( x = width  ; x &gt;= 0; x-- ){&#xD;&#xA;    &#xD;&#xA;                // when we find point x , y&#xD;&#xA;                if( ( x*x / width ) + ( y*y / height  ) &lt;= 1 ){&#xD;&#xA;    &#xD;&#xA;                      // rotate a copy of x,y&#xD;&#xA;                      rotate_z( x , y , by_angle );&#xD;&#xA;    &#xD;&#xA;                      // draw the rotate x,y copy&#xD;&#xA;                      set_pixle( x_origin + x , y_origin + y );&#xD;&#xA;                       &#xD;&#xA;                      /*&#xD;&#xA;                         then preform reflection in the other side &#xD;&#xA;                         of the ellipse &#xD;&#xA;                      */&#xD;&#xA;                }&#xD;&#xA;    &#xD;&#xA;           }&#xD;&#xA;       }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40331" PostHistoryTypeId="2" PostId="13402" RevisionGUID="8912bb3b-5f88-4a1f-b8e9-f421672171e6" CreationDate="2023-04-09T08:55:19.993" UserId="19523" Text="I think you should transform your coordinates before checking if they touch the boundary. You seem to use a scatter approach and every pixel that touch the non-transformed ellipse will land on only one pixel. Because the number of pixels that touch the boundary are &quot;uniform&quot; along curves that correspond to a rotated pixel grid, you will get holes and clusters which you can see in your zoomed in example." ContentLicense="CC BY-SA 4.0" />
  <row Id="40333" PostHistoryTypeId="10" PostId="8886" RevisionGUID="24b67aa3-8e69-430b-9dba-39171a303615" CreationDate="2023-04-09T16:06:54.603" UserId="482" Comment="102" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:482,&quot;DisplayName&quot;:&quot;luser droog&quot;}],&quot;SiteSpecificCloseReasonIds&quot;:[]}" />
  <row Id="40334" PostHistoryTypeId="5" PostId="13385" RevisionGUID="47088914-03ea-48d4-9821-faa927fd6adb" CreationDate="2023-04-10T01:31:19.473" UserId="19783" Comment="added 43 characters in body" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it (when left as an octahedron, the problem is still present)&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;Here is my tessellation evaluation shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my tessellation control shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from. The guy making it uses an icosahedron, which did not work when I tried it https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/BXmpD.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40343" PostHistoryTypeId="5" PostId="13385" RevisionGUID="39797272-dced-4ce4-b1af-77ed60685a2a" CreationDate="2023-04-10T14:31:08.533" UserId="19783" Comment="added 132 characters in body" Text="I'm working on a program to draw a sphere. The method I'm using is creating an octahedron&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it. Keep in mind, this is the same when I stop normalizing the UVW coordinates through the evaluation shader&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;Here is my tessellation evaluation shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my tessellation control shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from. The guy making it uses an icosahedron, which did not work when I tried it https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/v1SB0.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/BXmpD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40344" PostHistoryTypeId="2" PostId="13404" RevisionGUID="5ab4d808-5a15-4ba0-92f8-975dc87e705c" CreationDate="2023-04-10T18:47:44.480" UserDisplayName="user1703" Text="I am not aware of a canonical way to achieve this (nor even any article on the topic).&#xD;&#xA;&#xD;&#xA;What you can try is to enforce the same &quot;travel speed&quot; $\dfrac{ds}{dt}$ where two cubic arcs meet. You know the values of $t,s$ at these points (though $s$ must be obtained by numerical integration), and you want to specify the values of the speeds, i.e. the derivatives. Considering the two endpoints of a cubic arc, that gives you four constraints that can be satisfied by Hermite interpolation in the $t$ domain.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aeTve.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40346" PostHistoryTypeId="5" PostId="13404" RevisionGUID="3ed7b842-6d66-4907-ac60-c87f98d4eda2" CreationDate="2023-04-10T18:54:53.143" UserDisplayName="user1703" Comment="added 3 characters in body" Text="I am not aware of a canonical way to achieve this (nor even of any article on the topic).&#xD;&#xA;&#xD;&#xA;What you can try is to enforce the same &quot;travel speed&quot; $\dfrac{ds}{dt}$ where two cubic arcs meet. You know the values of $t,s$ at these points (though $s$ must be obtained by numerical integration), and you want to specify the values of the speeds, i.e. the derivatives. Considering the two endpoints of a cubic arc, that gives you four constraints that can be satisfied by Hermite interpolation in the $t$ domain.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aeTve.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40348" PostHistoryTypeId="2" PostId="13405" RevisionGUID="7f1cafda-e180-45c9-85bb-a45fb5d08873" CreationDate="2023-04-10T20:27:53.790" UserDisplayName="user1703" Text="The guilty is the post-rotation after you have generated points of the un-rotated ellipse. Because rotation on a raster does not preserve the density of the pixels.&#xD;&#xA;&#xD;&#xA;A solution is to work directly with the equation of the rotated ellipse, of the (centered) form&#xD;&#xA;&#xD;&#xA;$$px^2+2qx+ry^2=1.$$&#xD;&#xA;&#xD;&#xA;You can obtain it by plugging $u=x\cos\theta-y\sin\theta,v=x\sin\theta+y\cos\theta$ in &#xD;&#xA;&#xD;&#xA;$$\frac{u^2}{a^2}+\frac{v^2}{b^2}=1.$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="40350" PostHistoryTypeId="5" PostId="13405" RevisionGUID="569e5b84-7f02-41ed-b200-c0df2988d92f" CreationDate="2023-04-10T20:34:16.050" UserDisplayName="user1703" Comment="added 466 characters in body" Text="The guilty is the post-rotation after you have generated points of the un-rotated ellipse. Because rotation on a raster does not preserve the density of the pixels.&#xD;&#xA;&#xD;&#xA;A solution is to work directly with the equation of the rotated ellipse, of the (centered) form&#xD;&#xA;&#xD;&#xA;$$px^2+2qxy+ry^2=1.$$&#xD;&#xA;&#xD;&#xA;You can obtain it by plugging $u=x\cos\theta-y\sin\theta,v=x\sin\theta+y\cos\theta$ in &#xD;&#xA;&#xD;&#xA;$$\frac{u^2}{a^2}+\frac{v^2}{b^2}=1.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Note that your computation is fairly heavy because you try all pixels, i.e. $w\cdot h$ of them, which can be a lot.&#xD;&#xA;&#xD;&#xA;You can reduce the number of computations by &#xD;&#xA;&#xD;&#xA;- looping on $y$,&#xD;&#xA;&#xD;&#xA;- for a given value of $y$, solving the quadratic equation $px^2+2qxy+ry^2-1=0$ for $x$&#xD;&#xA;&#xD;&#xA;- when the slope of the curve becomes less than $1$ (so that a rwo will contain several pixels of the outline), switching to a loop on $x$, computing the corresponding $x$.&#xD;&#xA;&#xD;&#xA;The switching points occur when the slope is $\pm1$, or&#xD;&#xA;&#xD;&#xA;$$|px+qy|=|qx+ry|.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Yet a faster method is by using an outline following algorithm on the digital domain &#xD;&#xA;&#xD;&#xA;$$px^2+2qxy+ry^2\le1.$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="40351" PostHistoryTypeId="5" PostId="13405" RevisionGUID="71b75c44-b58d-4eeb-afa4-0c4e3fd11ffd" CreationDate="2023-04-10T20:39:52.937" UserDisplayName="user1703" Comment="added 124 characters in body" Text="The guilty is the post-rotation after you have generated points of the un-rotated ellipse. Because rotation on a raster does not preserve the density of the pixels.&#xD;&#xA;&#xD;&#xA;A solution is to work directly with the equation of the rotated ellipse, of the (centered) form&#xD;&#xA;&#xD;&#xA;$$px^2+2qxy+ry^2=1.$$&#xD;&#xA;&#xD;&#xA;You can obtain it by plugging $u=x\cos\theta-y\sin\theta,v=x\sin\theta+y\cos\theta$ in &#xD;&#xA;&#xD;&#xA;$$\frac{u^2}{a^2}+\frac{v^2}{b^2}=1.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Note that your computation is fairly heavy because you try all pixels, i.e. $w\cdot h$ of them, which can be a lot.&#xD;&#xA;&#xD;&#xA;You can reduce the number of computations by &#xD;&#xA;&#xD;&#xA;- looping on $y$,&#xD;&#xA;&#xD;&#xA;- for a given value of $y$, solving the quadratic equation $px^2+2qxy+ry^2-1=0$ for $x$&#xD;&#xA;&#xD;&#xA;- when the slope of the curve becomes less than $1$ (so that a row will contain several pixels of the outline), switching to a loop on $x$, computing the corresponding $x$.&#xD;&#xA;&#xD;&#xA;The switching points occur when the slope is $\pm1$, or&#xD;&#xA;&#xD;&#xA;$$|px+qy|=|qx+ry|.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Yet a faster method is by using an outline following algorithm on the digital domain &#xD;&#xA;&#xD;&#xA;$$px^2+2qxy+ry^2\le1.$$&#xD;&#xA;&#xD;&#xA;https://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/alg.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="40352" PostHistoryTypeId="50" PostId="5697" RevisionGUID="9a4316d1-0285-4009-85a0-e28fa008f80c" CreationDate="2023-04-12T10:00:10.107" UserId="-1" />
  <row Id="40353" PostHistoryTypeId="5" PostId="13405" RevisionGUID="9d4c746b-b793-48a5-9218-b57357dc927c" CreationDate="2023-04-12T12:37:41.887" UserDisplayName="user1703" Comment="edited body" Text="The guilty is the post-rotation after you have generated points of the un-rotated ellipse. Because rotation on a raster does not preserve the density of the pixels.&#xD;&#xA;&#xD;&#xA;A solution is to work directly with the equation of the rotated ellipse, of the (centered) form&#xD;&#xA;&#xD;&#xA;$$px^2+2qxy+ry^2=1.$$&#xD;&#xA;&#xD;&#xA;You can obtain it by plugging $u=x\cos\theta-y\sin\theta,v=x\sin\theta+y\cos\theta$ in &#xD;&#xA;&#xD;&#xA;$$\frac{u^2}{a^2}+\frac{v^2}{b^2}=1.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Note that your computation is fairly heavy because you try all pixels, i.e. $w\cdot h$ of them, which can be a lot.&#xD;&#xA;&#xD;&#xA;You can reduce the number of computations by &#xD;&#xA;&#xD;&#xA;- looping on $y$,&#xD;&#xA;&#xD;&#xA;- for a given value of $y$, solving the quadratic equation $px^2+2qxy+ry^2-1=0$ for $x$&#xD;&#xA;&#xD;&#xA;- when the slope of the curve becomes less than $1$ (so that a row will contain several pixels of the outline), switching to a loop on $x$, computing the corresponding $y$.&#xD;&#xA;&#xD;&#xA;The switching points occur when the slope is $\pm1$, or&#xD;&#xA;&#xD;&#xA;$$|px+qy|=|qx+ry|.$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;Yet a faster method is by using an outline-following algorithm on the digital domain &#xD;&#xA;&#xD;&#xA;$$px^2+2qxy+ry^2\le1.$$&#xD;&#xA;&#xD;&#xA;https://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/alg.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="40354" PostHistoryTypeId="2" PostId="13406" RevisionGUID="1f8c4afc-043d-4d37-9630-4ef967bc8f46" CreationDate="2023-04-12T14:52:46.397" UserDisplayName="user1703" Text="Let the two triangles be $ABC$ and $DEF$. They define planar frames to which you attach coordinates $(u,v)$, giving $P=A+u\vec{AB}+v\vec{AC}$ and $Q=D+u\vec{DE}+v\vec{DF}$. The triangles are filled with $u,v\ge0,u+v\le1$. Now for $w\in[0,1]$, interpolate to get $R=(1-w)P+wQ$. This is indeed trilinear interpolation.&#xD;&#xA;&#xD;&#xA;Holding two coordinates constant, you get a line segment. Holding a single coordinate constant, you get an hyperboloidal patch." ContentLicense="CC BY-SA 4.0" />
  <row Id="40356" PostHistoryTypeId="5" PostId="13406" RevisionGUID="8873c1b6-c044-4f13-b0be-b1cb9174c5eb" CreationDate="2023-04-12T14:59:19.460" UserDisplayName="user1703" Comment="deleted 8 characters in body" Text="Let the two triangles be $ABC$ and $DEF$. They define planar frames to which you attach coordinates $(u,v)$, giving $P=A+u\vec{AB}+v\vec{AC}$ and $Q=D+u\vec{DE}+v\vec{DF}$. The triangles are filled with $u,v\ge0,u+v\le1$. Now for $w\in[0,1]$, interpolate to get $R=(1-w)P+wQ$. This is indeed trilinear interpolation.&#xD;&#xA;&#xD;&#xA;Holding two coordinates constant, you get a line segment. Holding a single coordinate constant, you get a planar patch." ContentLicense="CC BY-SA 4.0" />
  <row Id="40357" PostHistoryTypeId="2" PostId="13407" RevisionGUID="4c3d454f-fbe0-4a2c-a2f4-dde474e70c96" CreationDate="2023-04-13T01:36:27.663" UserId="19838" Text="Is it possible to enable accurate thumbnail previews for DDS files that use the newer DX10 headers (DirectX 10 headers)? It seems there is very limited information about this.&#xD;&#xA;&#xD;&#xA;I did find a couple posts on random sites that suggest using &quot;Sage Thumbs&quot; with any app that supports newer DDS formats, but this did not work for me. I tried setting (as the default primary app for DDS) the newest Photoshop with the NVidia exporter plugin, as well as the latest Paint.net. Sage Thumbs does enable thumbnails for newer DDS files, but all of the thumbnail images are garbled, with pixel bleeding, and some with pure pixel noise.&#xD;&#xA;&#xD;&#xA;Has anyone been able to do this successfully? Having these previews would make working with the compressed BC6 and BC7 formats far easier." ContentLicense="CC BY-SA 4.0" />
  <row Id="40359" PostHistoryTypeId="1" PostId="13407" RevisionGUID="4c3d454f-fbe0-4a2c-a2f4-dde474e70c96" CreationDate="2023-04-13T01:36:27.663" UserId="19838" Text="DDS BC7 Thumbnails on Windows 10" ContentLicense="CC BY-SA 4.0" />
  <row Id="40360" PostHistoryTypeId="3" PostId="13407" RevisionGUID="4c3d454f-fbe0-4a2c-a2f4-dde474e70c96" CreationDate="2023-04-13T01:36:27.663" UserId="19838" Text="|texture|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40361" PostHistoryTypeId="50" PostId="13358" RevisionGUID="106b42b8-7a61-45e9-aaec-d834a9ef685b" CreationDate="2023-04-13T13:04:20.500" UserId="-1" />
  <row Id="40362" PostHistoryTypeId="50" PostId="9199" RevisionGUID="5747aa86-5442-4661-98f9-13f56c3f998a" CreationDate="2023-04-13T14:01:30.203" UserId="-1" />
  <row Id="40363" PostHistoryTypeId="5" PostId="13399" RevisionGUID="c71721ca-f023-44ef-a6bf-f9cdc3db174e" CreationDate="2023-04-13T20:04:22.617" UserId="11224" Comment="added 71 characters in body; edited title" Text="I think that VR / AR experts will know the answer to this.&#xD;&#xA;&#xD;&#xA;At what vergence angle are &quot;infinitely far away&quot; objects such as star field textures drawn in head-mounted VR / AR displays ?&#xD;&#xA;&#xD;&#xA;I believe I have read that the stars in the night sky are so far away that our human visual system cannot distinguish the degree of vergence required to look at them from &quot;parallel vergence&quot;, where the view directions of the two eyes are parallel. That is, the stars are so far away that in this particular sense, they may as well be infinitely far away.&#xD;&#xA;&#xD;&#xA;In my experiments with anaglyph displays on laptop screens, I have found that it is very uncomfortable to diverge my eyes to the point of parallel view directions, in order to resolve star field textures that are &quot;infinitely distant&quot;, i.e., in which the left and right images are separated horizontally by exactly my interpupillary distance.&#xD;&#xA;&#xD;&#xA;In case this might be due to measurement errors causing the separation on screen to very slightly exceed my actual interpupillary distance, I have experimented with reducing that separation one mm at a time, until the degree of vergence became tolerably comfortable. However, this required a separation difference that was significantly smaller than my actual interpupillary distance, tending to refute the &quot;measurement errors&quot; hypothesis.&#xD;&#xA;&#xD;&#xA;Is the discomfort likely to be due more to the well-known contradiction between vergence and accommodation (focus) that is a drawback of conventional stereoscopic displays ?&#xD;&#xA;&#xD;&#xA;In VR headsets, does the greater focal depth alleviate this problem, i.e. is the limit of comfort for vergence closer to parallel, in this case ?&#xD;&#xA;&#xD;&#xA;I have read that parallel vergence should be avoided in stereoscopic displays, because it is unnatural for our visual system, but I have not read any explanation as to why (almost) parallel vergence is perfectly comfortable for viewing stars in the real world. Might it also be to do with the fact that the solid angle subtended on earth by a star in the real world is very small ?&#xD;&#xA;&#xD;&#xA;Are some of my assumptions wrong ?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I moved the most important part of the question to the top, and modified the title to emphasise it." ContentLicense="CC BY-SA 4.0" />
  <row Id="40364" PostHistoryTypeId="4" PostId="13399" RevisionGUID="c71721ca-f023-44ef-a6bf-f9cdc3db174e" CreationDate="2023-04-13T20:04:22.617" UserId="11224" Comment="added 71 characters in body; edited title" Text="What vergence angle is commonly used for &quot;infinitely far away&quot; objects in stereoscopic displays?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40365" PostHistoryTypeId="2" PostId="13408" RevisionGUID="862ee629-0c50-4dbd-b423-dfc0b791aa50" CreationDate="2023-04-14T11:58:04.540" UserId="19846" Text="I originally asked this question on the gamdev stack exchange but was told by a friend I would be better served here.&#xD;&#xA;&#xD;&#xA;[Original Question][1]&#xD;&#xA;&#xD;&#xA;So I will start off by laying out the relevant structure of my program.&#xD;&#xA;&#xD;&#xA;I am using vulkan to render the same mesh over a few instances. To do this I have:&#xD;&#xA;- a vertex buffer, used per vertex, which is an array of the following structure&#xD;&#xA;```rust&#xD;&#xA;pub struct ShaderVertexData {&#xD;&#xA;    pub position: na::Vector3&lt;f32&gt;,&#xD;&#xA;    pub uv: na::Vector2&lt;f32&gt;,&#xD;&#xA;    pub normal: na::Vector3&lt;f32&gt;,&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;- an &quot;instance&quot; buffer, used per instance, which is an array of this structure.&#xD;&#xA;```rust&#xD;&#xA;pub struct InstanceData {&#xD;&#xA;    pub model: [[f32; 4]; 4],&#xD;&#xA;    pub texture_index: u32,&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;- An array of textures provided via a descriptor set&#xD;&#xA;```rust&#xD;&#xA;let descriptor_binding_flags = [vk::DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT];&#xD;&#xA;let mut descriptorset_layout_binding_flags =&#xD;&#xA;    vk::DescriptorSetLayoutBindingFlagsCreateInfo::builder()&#xD;&#xA;        .binding_flags(&amp;descriptor_binding_flags);&#xD;&#xA;&#xD;&#xA;let layout_bindings = [DescriptorSetLayoutBinding::builder()&#xD;&#xA;    .stage_flags(vk::ShaderStageFlags::FRAGMENT)&#xD;&#xA;    .binding(0)&#xD;&#xA;    .descriptor_count(MAX_IMAGES)&#xD;&#xA;    .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)&#xD;&#xA;    .build()];&#xD;&#xA;&#xD;&#xA;let descriptor_set_layout_info = vk::DescriptorSetLayoutCreateInfo::builder()&#xD;&#xA;    .bindings(&amp;layout_bindings)&#xD;&#xA;    .push_next(&amp;mut descriptorset_layout_binding_flags);&#xD;&#xA;&#xD;&#xA;let descriptor_set_layout_texture = unsafe {&#xD;&#xA;    logical_device.create_descriptor_set_layout(&amp;descriptor_set_layout_info, None)&#xD;&#xA;}?;&#xD;&#xA;&#xD;&#xA;let descriptor_pool_sizes = [vk::DescriptorPoolSize::builder()&#xD;&#xA;    .ty(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)&#xD;&#xA;    .descriptor_count(MAX_IMAGES * 3)&#xD;&#xA;    .build()];&#xD;&#xA;&#xD;&#xA;let descriptor_pool_info = vk::DescriptorPoolCreateInfo::builder()&#xD;&#xA;    .pool_sizes(&amp;descriptor_pool_sizes)&#xD;&#xA;    .max_sets(3);&#xD;&#xA;&#xD;&#xA;let descriptor_pool =&#xD;&#xA;    unsafe { logical_device.create_descriptor_pool(&amp;descriptor_pool_info, None) }?;&#xD;&#xA;&#xD;&#xA;let desc_layouts_texture = vec![descriptor_set_layout_texture; 3];&#xD;&#xA;// TODO: Move this into the texture code to allocate as needed. For now I just hard-code 2 textures.&#xD;&#xA;let mut variable = DescriptorSetVariableDescriptorCountAllocateInfo::builder()&#xD;&#xA;    .descriptor_counts(&amp;[2, 2, 2]);&#xD;&#xA;let descriptor_set_allocate_info = vk::DescriptorSetAllocateInfo::builder()&#xD;&#xA;    .descriptor_pool(descriptor_pool)&#xD;&#xA;    .set_layouts(&amp;desc_layouts_texture)&#xD;&#xA;    .push_next(&amp;mut variable);&#xD;&#xA;&#xD;&#xA;let descriptor_sets =&#xD;&#xA;    unsafe { logical_device.allocate_descriptor_sets(&amp;descriptor_set_allocate_info) }?;&#xD;&#xA;&#xD;&#xA;let descriptor_set_layouts = [descriptor_set_layout_texture];&#xD;&#xA;&#xD;&#xA;let pipelinelayout_info = vk::PipelineLayoutCreateInfo::builder()&#xD;&#xA;    .push_constant_ranges(&amp;push_constant_ranges)&#xD;&#xA;    .set_layouts(&amp;descriptor_set_layouts);&#xD;&#xA;&#xD;&#xA;//------------------------------------------------&#xD;&#xA;// Later I copy in the texture info&#xD;&#xA;//------------------------------------------------&#xD;&#xA;let descriptor_image_infos = self.texture_store.get_descriptor_image_info();&#xD;&#xA;let descriptor_writes = [vk::WriteDescriptorSet {&#xD;&#xA;    descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,&#xD;&#xA;    dst_set: self.graphics_pipeline.descriptor_sets&#xD;&#xA;        [frame_buffer_info.image_index as usize],&#xD;&#xA;    dst_binding: 0,&#xD;&#xA;    dst_array_element: 0,&#xD;&#xA;    p_image_info: descriptor_image_infos.as_ptr(),&#xD;&#xA;    descriptor_count: 2,&#xD;&#xA;    ..Default::default()&#xD;&#xA;}];&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I then have the following shaders&#xD;&#xA;```glsl&#xD;&#xA;// vertex&#xD;&#xA;#version 450&#xD;&#xA;&#xD;&#xA;layout(push_constant)uniform constants{&#xD;&#xA;    mat4 proj;&#xD;&#xA;}PushConstants;&#xD;&#xA;&#xD;&#xA;layout(location=0)in mat4 model;&#xD;&#xA;layout(location=4)in uint tex_id;&#xD;&#xA;layout(location=5)in vec3 position;&#xD;&#xA;layout(location=6)in vec2 uv;&#xD;&#xA;layout(location=7)in vec3 normal;&#xD;&#xA;&#xD;&#xA;layout(location=0)out vec2 uv_for_fragment_shader;&#xD;&#xA;layout(location=1)out uint tex_id_for_fragment_shader;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;    gl_Position=PushConstants.proj*model*vec4(position,1);&#xD;&#xA;    tex_id_for_fragment_shader = tex_id;&#xD;&#xA;    uv_for_fragment_shader=uv;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// fragment&#xD;&#xA;#version 450&#xD;&#xA;#extension GL_EXT_nonuniform_qualifier : require&#xD;&#xA;&#xD;&#xA;layout(set=0,binding=0)uniform sampler2D tex_samplers[];&#xD;&#xA;&#xD;&#xA;layout(location=0)in vec2 uv_from_vertex_shader;&#xD;&#xA;layout(location=1)in flat uint tex_id_from_vertex_shader;&#xD;&#xA;&#xD;&#xA;layout(location=0)out vec4 output_colour;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;    output_colour = texture(tex_samplers[tex_id_from_vertex_shader], uv_from_vertex_shader);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Finally I draw the instances like so&#xD;&#xA;```rust&#xD;&#xA;self.logical_device.cmd_push_constants(&#xD;&#xA;    commandbuffer,&#xD;&#xA;    self.graphics_pipeline.layout,&#xD;&#xA;    vk::ShaderStageFlags::VERTEX,&#xD;&#xA;    0,&#xD;&#xA;    &amp;std::mem::transmute::&lt;[[f32; 4]; 4], [u8; 64]&gt;(projection),&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;self.logical_device.cmd_bind_descriptor_sets(&#xD;&#xA;    commandbuffer,&#xD;&#xA;    vk::PipelineBindPoint::GRAPHICS,&#xD;&#xA;    self.graphics_pipeline.layout,&#xD;&#xA;    0,&#xD;&#xA;    &amp;[self.graphics_pipeline.descriptor_sets&#xD;&#xA;        [frame_buffer_info.image_index as usize]],&#xD;&#xA;    &amp;[],&#xD;&#xA;);&#xD;&#xA;self.cube.bind(&amp;self.logical_device, commandbuffer);&#xD;&#xA;&#xD;&#xA;self.logical_device.cmd_bind_vertex_buffers(&#xD;&#xA;    commandbuffer,&#xD;&#xA;    VertexBufferBindings::InstanceBuffer as u32,&#xD;&#xA;    &amp;[self.instance_buffer.buffer],&#xD;&#xA;    &amp;[0],&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;self.logical_device.cmd_draw_indexed(&#xD;&#xA;    commandbuffer,&#xD;&#xA;    self.cube.index_count() as u32,&#xD;&#xA;    4,&#xD;&#xA;    0,&#xD;&#xA;    0,&#xD;&#xA;    0,&#xD;&#xA;);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;With that out of the way we can get to the problem at hand, The texture samplers seem to bleed over into the separate instances&#xD;&#xA;&#xD;&#xA;[![2 Cubes with different textures but patches of each-others textures][2]][2]&#xD;&#xA;&#xD;&#xA;I have checked that the texture index itself is consistent across the entire instance by rendering&#xD;&#xA;```glsl&#xD;&#xA;output_colour = vec4(tex_id_from_vertex_shader, 0,0,1);&#xD;&#xA;```&#xD;&#xA;And I get no artefacts&#xD;&#xA;&#xD;&#xA;[![No artefacts][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So it seems like the sampler itself is hanging around where it shouldn't. Any idea what might be causing this to happen?&#xD;&#xA;&#xD;&#xA;If it matters I am on an AMD Radeon 7900 XTX and using the latest drivers&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://gamedev.stackexchange.com/questions/205276/why-do-texture-samplers-seem-to-bleed-into-other-instances-when-rendering-multip&#xD;&#xA;  [2]: https://i.stack.imgur.com/vyAZq.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/N7k30.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40367" PostHistoryTypeId="1" PostId="13408" RevisionGUID="862ee629-0c50-4dbd-b423-dfc0b791aa50" CreationDate="2023-04-14T11:58:04.540" UserId="19846" Text="Why do texture samplers seem to bleed into other instances when rendering multiple instances of the same mesh with differing textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="40368" PostHistoryTypeId="3" PostId="13408" RevisionGUID="862ee629-0c50-4dbd-b423-dfc0b791aa50" CreationDate="2023-04-14T11:58:04.540" UserId="19846" Text="|texture|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40373" PostHistoryTypeId="5" PostId="13385" RevisionGUID="92378313-797d-4014-beb1-405a6848f5cd" CreationDate="2023-04-14T14:54:08.390" UserId="19783" Comment="added 18 characters in body" Text="I'm working on a program where I need to draw spheres. The method I'm using is creating an octahedron&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;And using tessellation shaders to subdivide it into a sphere, however there is a patch of the sphere that is not being rendered, and I don't know what's causing it. Keep in mind, this is the same when I stop normalizing the UVW coordinates through the evaluation shader&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;Here is my tessellation evaluation shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // from control shader&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // allows for object transformations and for movement&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // get / make the barycentric coordinates of the octahedron&#xD;&#xA;        vec3 u = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 v = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 w = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        // normalizing the positions of the triangles allows for every point to be&#xD;&#xA;        // the same distance away from the center, forming a sphere&#xD;&#xA;        vec3 pos = normalize(u + v + w);&#xD;&#xA;        // output patch point position in clip space&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my tessellation control shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;    &#xD;&#xA;    // specify control points per output per patch&#xD;&#xA;    // control size of input and output arrays&#xD;&#xA;    layout(vertices=3) out;&#xD;&#xA;    // input from vertex shader&#xD;&#xA;    in vec3 vert_coord[];&#xD;&#xA;    // output to evaluation shader&#xD;&#xA;    out vec3 vertex_coord[];&#xD;&#xA;    &#xD;&#xA;    // for tessellation&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // pass attributes through&#xD;&#xA;        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;&#xD;&#xA;        vertex_coord[gl_InvocationID] = vert_coord[gl_InvocationID];&#xD;&#xA;    &#xD;&#xA;        // control tessellation&#xD;&#xA;        if(gl_InvocationID==0)&#xD;&#xA;        {&#xD;&#xA;            // dynamic LOD step by step&#xD;&#xA;            // first: define rendering constants to control tessellation&#xD;&#xA;            const float MIN_TESS_LEVEL = 4;&#xD;&#xA;            const float MAX_TESS_LEVEL = 64;&#xD;&#xA;            const float MIN_DISTANCE = 20;&#xD;&#xA;            const float MAX_DISTANCE = 800;&#xD;&#xA;            // second: transform each vertex into each eye&#xD;&#xA;            vec4 eye_space_pos_1 = view * model * gl_in[0].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_2 = view * model * gl_in[1].gl_Position;&#xD;&#xA;            vec4 eye_space_pos_3 = view * model * gl_in[2].gl_Position;&#xD;&#xA;            // third: distance from camera scaled between 0 and 1&#xD;&#xA;            float distance_1 = clamp((abs(eye_space_pos_1.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_2 = clamp((abs(eye_space_pos_2.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            float distance_3 = clamp((abs(eye_space_pos_3.z)-MIN_DISTANCE)/(MAX_DISTANCE-MIN_DISTANCE), 0.0, 1.0);&#xD;&#xA;            // fourth: interpolate edge tessellation level based on closer vertex&#xD;&#xA;            float tess_level_1 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_3, distance_1));&#xD;&#xA;            float tess_level_2 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_1, distance_2));&#xD;&#xA;            float tess_level_3 = mix(MAX_TESS_LEVEL, MIN_TESS_LEVEL, min(distance_2, distance_1));&#xD;&#xA;            // fifth: set the corresponding outer tessellation levels&#xD;&#xA;            gl_TessLevelOuter[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelOuter[1] = tess_level_2;&#xD;&#xA;            gl_TessLevelOuter[2] = tess_level_3;&#xD;&#xA;            // sixth: set the inner tessellation levels&#xD;&#xA;            gl_TessLevelInner[0] = tess_level_1;&#xD;&#xA;            gl_TessLevelInner[1] = tess_level_2;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here is my vertex shader&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // position of the object&#xD;&#xA;    layout (location = 0) in vec3 pos;&#xD;&#xA;    layout (location = 1) in vec3 vert;&#xD;&#xA;    &#xD;&#xA;    // vertices to make the sphere&#xD;&#xA;    out vec3 vert_coord;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // position object&#xD;&#xA;        gl_Position = vec4(pos, 1.0f);&#xD;&#xA;        // put the vertices into a different vector&#xD;&#xA;        vert_coord = vert;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And finally, here are my octahedron vertices and buffers and draw call&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f,  -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int indices[] = {&#xD;&#xA;        // first triangle&#xD;&#xA;        0, 1, 2,&#xD;&#xA;        // second triangle&#xD;&#xA;        3, 4, 5,&#xD;&#xA;        // third triangle&#xD;&#xA;        6, 7, 8,&#xD;&#xA;        // fourth triangle&#xD;&#xA;        9, 10, 11,&#xD;&#xA;        // fifth triangle&#xD;&#xA;        12, 13, 14,&#xD;&#xA;        // sixth triangle&#xD;&#xA;        15, 16, 17,&#xD;&#xA;        // seventh triangle&#xD;&#xA;        18, 19, 20,&#xD;&#xA;        // eighth triangle&#xD;&#xA;        21, 22, 23&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    unsigned int vbo, vao, ebo;&#xD;&#xA;    glGenVertexArrays(1, &amp;vao);&#xD;&#xA;    glGenBuffers(1, &amp;vbo);&#xD;&#xA;    glGenBuffers(1, &amp;ebo);&#xD;&#xA;&#xD;&#xA;    glBindVertexArray(vao);&#xD;&#xA;&#xD;&#xA;    // upload vertex data to gpu&#xD;&#xA;    glBindBuffer(GL_ARRAY_BUFFER, vbo);&#xD;&#xA;    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &amp;vertices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // upload index data to gpu&#xD;&#xA;    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);&#xD;&#xA;    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(unsigned int), &amp;indices[0], GL_STATIC_DRAW);&#xD;&#xA;&#xD;&#xA;    // position attribute&#xD;&#xA;    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);&#xD;&#xA;    glEnableVertexAttribArray(0);&#xD;&#xA;&#xD;&#xA;    // normal attribute&#xD;&#xA;    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));&#xD;&#xA;    glEnableVertexAttribArray(1);&#xD;&#xA;&#xD;&#xA;    // max tessellation points / patches&#xD;&#xA;    glPatchParameteri(GL_PATCH_VERTICES, 3);&#xD;&#xA;    glDrawElements(GL_PATCHES, 24, GL_UNSIGNED_INT, 0);&#xD;&#xA;&#xD;&#xA;As a bonus, if it's helpful, this is where the tutorial where I adapted my code from. The guy making it uses an icosahedron, which did not work when I tried it https://prideout.net/blog/old/blog/index.html@p=48.html&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/xHpcm.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/v1SB0.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/BXmpD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40375" PostHistoryTypeId="2" PostId="13410" RevisionGUID="6dfbd2a2-014e-4a00-8ca5-7f7d9f922490" CreationDate="2023-04-16T12:04:02.190" UserId="19849" Text="dxf files emerge from various applications, for example Autocad, LibreCAD and so on.&#xD;&#xA;Sometimes a design should be flexible, e.g. one should be able to change one dimension of it and keep everything intact after such a change. This of course would require to parametrise everything from the very beginning, e.g.&#xD;&#xA;&#xD;&#xA; - Points may be either fixed or related to other points by given&#xD;&#xA;   distances and directions or how they were geometrically constructed&#xD;&#xA;   as intersections between other previously defined entities.&#xD;&#xA; - Lines become connections between points defined before or parallel to&#xD;&#xA;   some other line with a given distance, at a given angle to an&#xD;&#xA;   existing line and so on. Lines crossing other lines define&#xD;&#xA;   intersection points once they are used in a construction.&#xD;&#xA; - Circles depend on points (center) and radii or intersection&#xD;&#xA;   properties, being tangent to some line(s) and so on.&#xD;&#xA; - Whole sub-designs would be defined by how they were constructed and then copied, mirrored, arranged at other orientations and so on.&#xD;&#xA; - If one would continue to 3D, volumes are created as spheres, bricks and&#xD;&#xA;   other elementary bodies or as extrusions from 2d shapes constructed&#xD;&#xA;   before.&#xD;&#xA;&#xD;&#xA;So my question becomes: Is the dxf file format restricted on points being individually given as numerical coordinates and lines being defined by their end points only? How far is it open for relations where the actual values can be adapted later to some other numerical value and can the dependence of those entities be represented in an dxf file?&#xD;&#xA;&#xD;&#xA;Is there a free open source 2D CAD program which supports a parametric paradigm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40377" PostHistoryTypeId="1" PostId="13410" RevisionGUID="6dfbd2a2-014e-4a00-8ca5-7f7d9f922490" CreationDate="2023-04-16T12:04:02.190" UserId="19849" Text="Can dxf Files Represent a Parametric Design?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40378" PostHistoryTypeId="3" PostId="13410" RevisionGUID="6dfbd2a2-014e-4a00-8ca5-7f7d9f922490" CreationDate="2023-04-16T12:04:02.190" UserId="19849" Text="|2d|2d-graphics|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40379" PostHistoryTypeId="50" PostId="9591" RevisionGUID="84b34142-6d2f-4a45-bc47-b43f882c24b1" CreationDate="2023-04-17T03:06:15.790" UserId="-1" />
  <row Id="40380" PostHistoryTypeId="5" PostId="13399" RevisionGUID="784085ab-b56f-4efc-8cd5-650642198827" CreationDate="2023-04-17T05:45:50.667" UserId="11224" Comment="Add an observation about the bluriness of infinitely distant textures." Text="I think that VR / AR experts will know the answer to this.&#xD;&#xA;&#xD;&#xA;At what vergence angle are &quot;infinitely far away&quot; objects such as star field textures drawn in head-mounted VR / AR displays ?&#xD;&#xA;&#xD;&#xA;I believe I have read that the stars in the night sky are so far away that our human visual system cannot distinguish the degree of vergence required to look at them from &quot;parallel vergence&quot;, where the view directions of the two eyes are parallel. That is, the stars are so far away that in this particular sense, they may as well be infinitely far away.&#xD;&#xA;&#xD;&#xA;In my experiments with anaglyph displays on laptop screens, I have found that it is very uncomfortable to diverge my eyes to the point of parallel view directions, in order to resolve star field textures that are &quot;infinitely distant&quot;, i.e., in which the left and right images are separated horizontally by exactly my interpupillary distance.&#xD;&#xA;&#xD;&#xA;In case this might be due to measurement errors causing the separation on screen to very slightly exceed my actual interpupillary distance, I have experimented with reducing that separation one mm at a time, until the degree of vergence became tolerably comfortable. However, this required a separation difference that was significantly smaller than my actual interpupillary distance, tending to refute the &quot;measurement errors&quot; hypothesis.&#xD;&#xA;&#xD;&#xA;Is the discomfort likely to be due more to the well-known contradiction between vergence and accommodation (focus) that is a drawback of conventional stereoscopic displays ?&#xD;&#xA;&#xD;&#xA;(**EDIT** As well as the muscular discomfort, I noticed that the star field texture was blurry, as if my eyes were refusing to focus on the screen. Perhaps at this extreme of vergence, the physiological connection between vergence and accommodation forces accommodation at infinity ?)&#xD;&#xA;&#xD;&#xA;In VR headsets, does the greater focal depth alleviate this problem, i.e. is the limit of comfort for vergence closer to parallel, in this case ?&#xD;&#xA;&#xD;&#xA;I have read that parallel vergence should be avoided in stereoscopic displays, because it is unnatural for our visual system, but I have not read any explanation as to why (almost) parallel vergence is perfectly comfortable for viewing stars in the real world. Might it also be to do with the fact that the solid angle subtended on earth by a star in the real world is very small ?&#xD;&#xA;&#xD;&#xA;Are some of my assumptions wrong ?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I moved the most important part of the question to the top, and modified the title to emphasise it." ContentLicense="CC BY-SA 4.0" />
  <row Id="40381" PostHistoryTypeId="2" PostId="13411" RevisionGUID="e36ea207-fc38-4c08-8bdf-e32c32e428b0" CreationDate="2023-04-17T14:25:05.547" UserId="19783" Text="So I went onto a different forum and I asked this question, and somebody helped me solve it. It turns out that the coordinates for the octahedron were wrong. The problematic ones were top-north-east and bottom-south-east. I'll give a list of the new and improved coordinates as well as the output of it.&#xD;&#xA;&#xD;&#xA;        float vertices[] = {&#xD;&#xA;        //top-north-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-north-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-west&#xD;&#xA;         0.0f,  1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //top-south-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-east&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-north-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f,  1.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-west&#xD;&#xA;         0.0f, -1.0f,  0.0f,&#xD;&#xA;        -1.0f,  0.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;&#xD;&#xA;        //bottom-south-east&#xD;&#xA;         0.0f, 1.0f,  0.0f,&#xD;&#xA;         0.0f,  0.0f, -1.0f,&#xD;&#xA;         1.0f,  0.0f,  0.0f&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/sfoAk.png&#xD;&#xA;&#xD;&#xA;Finally solved after two months..." ContentLicense="CC BY-SA 4.0" />
  <row Id="40383" PostHistoryTypeId="2" PostId="13412" RevisionGUID="8c6107b6-189a-46ef-b754-5931901f40bc" CreationDate="2023-04-17T19:47:10.683" UserId="19854" Text="I am reverse-engineering two classes from a game. The two classes are responsible for generating sets of t values for interpolating / blending between two points through the formula:  &#xD;&#xA;```&#xD;&#xA;P = P0 * (1 - t) + P1 * t&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Both classes have the same interface, that is:&#xD;&#xA;```&#xD;&#xA;class CalcRatio:&#xD;&#xA;    start(blend_duration)  # In frames&#xD;&#xA;    calc()                 # Called once every frame&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The first class is implemented as follows:&#xD;&#xA;```&#xD;&#xA;start(blend_duration):&#xD;&#xA;    t = 0&#xD;&#xA;    counter = 0&#xD;&#xA;    inv_duration = 1 / blend_duration&#xD;&#xA;&#xD;&#xA;calc():&#xD;&#xA;    if t == 1:&#xD;&#xA;        return&#xD;&#xA;&#xD;&#xA;    counter += inv_duration&#xD;&#xA;    if counter &gt;= 1:&#xD;&#xA;        t = 1&#xD;&#xA;        counter = 1&#xD;&#xA;        inv_duration = 0&#xD;&#xA;        return&#xD;&#xA;&#xD;&#xA;    t += inv_duration&#xD;&#xA;```&#xD;&#xA;This is very clearly plain linear interpolation where `P = P0 * (1 - t) + P1 * t`, `t = frame / duration` and `frame` is the current frame number since calling `start()`. (I do not even know why the game even needed this class.)&#xD;&#xA;&#xD;&#xA;However, I do not understand the second class. It is implemented as follows:&#xD;&#xA;```&#xD;&#xA;start(blend_duration):&#xD;&#xA;    t = 0&#xD;&#xA;    counter = 0&#xD;&#xA;    unk = 1&#xD;&#xA;    inv_duration = 1 / blend_duration&#xD;&#xA;&#xD;&#xA;calc():&#xD;&#xA;    if unk == 0:&#xD;&#xA;        return&#xD;&#xA;&#xD;&#xA;    counter += inv_duration&#xD;&#xA;    if counter &gt;= 1:&#xD;&#xA;        t = 1&#xD;&#xA;        counter = 1&#xD;&#xA;        unk = 0&#xD;&#xA;        return&#xD;&#xA;&#xD;&#xA;    prev_unk = unk&#xD;&#xA;    unk -= prev_unk * counter * counter&#xD;&#xA;    unk2 = 1 / (unk / prev_unk + (1 - unk))&#xD;&#xA;    t = (1 - unk) * unk2&#xD;&#xA;    # Interesting fact: 1 - t == (unk / prev_unk) * unk2&#xD;&#xA;```&#xD;&#xA;I do not understand what this is doing. The new point is still calculated as `P = P0 * (1 - t) + P1 * t`, but any idea what `t` is in terms of `frame`? What are `unk` and `unk2` supposed to represent?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40385" PostHistoryTypeId="1" PostId="13412" RevisionGUID="8c6107b6-189a-46ef-b754-5931901f40bc" CreationDate="2023-04-17T19:47:10.683" UserId="19854" Text="What is this method of interpolation / blending?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40386" PostHistoryTypeId="3" PostId="13412" RevisionGUID="8c6107b6-189a-46ef-b754-5931901f40bc" CreationDate="2023-04-17T19:47:10.683" UserId="19854" Text="|interpolation|animation|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40387" PostHistoryTypeId="50" PostId="12853" RevisionGUID="85d21da4-a894-4735-aec3-d0b6760943c3" CreationDate="2023-04-18T12:02:05.367" UserId="-1" />
  <row Id="40388" PostHistoryTypeId="50" PostId="8260" RevisionGUID="a5d347a9-2b93-475f-a997-01d7fc5f9db7" CreationDate="2023-04-18T14:03:45.423" UserId="-1" />
  <row Id="40389" PostHistoryTypeId="33" PostId="13399" RevisionGUID="b5a2907f-727d-476f-a444-65c50df70bec" CreationDate="2023-04-19T01:48:21.350" UserId="11224" Comment="83" />
  <row Id="40391" PostHistoryTypeId="50" PostId="13372" RevisionGUID="36e39339-f5d0-48fc-bcf4-30f152eed7ac" CreationDate="2023-04-19T12:00:05.030" UserId="-1" />
  <row Id="40392" PostHistoryTypeId="2" PostId="13413" RevisionGUID="ec5f1ed5-d8d7-408b-a167-8d4492d124b0" CreationDate="2023-04-19T12:54:22.313" UserId="19846" Text="I finally got an answer on the [AMD Forums][1].&#xD;&#xA;&#xD;&#xA;The issue was that you need to tell the GPU when you plan on indexing resource arrays with non uniform values.&#xD;&#xA;&#xD;&#xA;My shader now looks like this:&#xD;&#xA;```glsl&#xD;&#xA;#version 450&#xD;&#xA;#extension GL_EXT_nonuniform_qualifier : require&#xD;&#xA;&#xD;&#xA;layout(set=0,binding=0)uniform sampler2D tex_samplers[];&#xD;&#xA;&#xD;&#xA;layout(location=0)in vec2 uv_from_vertex_shader;&#xD;&#xA;layout(location=1)in vec3 normal_from_vertex_shader;&#xD;&#xA;layout(location=2)in flat uint tex_id_from_vertex_shader;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;layout(location=0)out vec4 output_colour;&#xD;&#xA;&#xD;&#xA;void main(){&#xD;&#xA;    vec4 albedo = texture(tex_samplers[nonuniformEXT(tex_id_from_vertex_shader)], uv_from_vertex_shader);&#xD;&#xA;    float light = clamp(dot(normal_from_vertex_shader, normalize(vec3(1,1,1))), 0.2, 1);&#xD;&#xA;    output_colour =  vec4(albedo.rgb * light, albedo.a);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;The important part is the `nonuniformEXT` that wraps the index&#xD;&#xA;&#xD;&#xA;It is also worth mentioning that technically this also requires that you enable `shaderSampledImageArrayNonUniformIndexing` on your `VkPhysicalDeviceDescriptorIndexingFeatures`&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://community.amd.com/t5/opengl-vulkan/vulkan-fragment-shader-bug-when-using-array-of-textures/m-p/600999/thread-id/4659#M4661" ContentLicense="CC BY-SA 4.0" />
  <row Id="40394" PostHistoryTypeId="50" PostId="5220" RevisionGUID="70c51702-d878-48f4-be7a-c90eb912c719" CreationDate="2023-04-20T01:07:35.857" UserId="-1" />
  <row Id="40401" PostHistoryTypeId="2" PostId="13415" RevisionGUID="aa722e42-4831-4215-9f9d-99aeb51e3db4" CreationDate="2023-04-22T07:43:14.410" UserId="19819" Text="I am creating a cylinder, and there is fog around it. I can't handle two things: &#xD;&#xA;&#xD;&#xA;1) the inner surface of the cylinder, realized as a smaller diameter cylinder, actually gives me just a second cylinder inserted into a wider cylinder. How to achieve a monolithic figure? &#xD;&#xA;&#xD;&#xA;2) fog: now it turns out as shown in the screenshot. I need a full-fledged fog with a cloud texture. What's wrong with the code?&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I used any file with a cloud (fog) in the format.jpg. By the way, the .png format gave about the same error&#xD;&#xA;&#xD;&#xA;Code:&#xD;&#xA;```&#xD;&#xA;import pygame&#xD;&#xA;from pygame.locals import *&#xD;&#xA;import math&#xD;&#xA;from OpenGL.GL import *&#xD;&#xA;from OpenGL.GLU import *&#xD;&#xA;&#xD;&#xA;# creating a window&#xD;&#xA;pygame.init()&#xD;&#xA;display = (800, 600)&#xD;&#xA;pygame.display.set_mode(display, DOUBLEBUF|OPENGL)&#xD;&#xA;&#xD;&#xA;# animation&#xD;&#xA;glMatrixMode(GL_PROJECTION)&#xD;&#xA;gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)&#xD;&#xA;&#xD;&#xA;glMatrixMode(GL_MODELVIEW)&#xD;&#xA;gluLookAt(0, -10, 10, 0, 0, 0, 0, 1, 0)&#xD;&#xA;&#xD;&#xA;# setting the properties of the cylinders&#xD;&#xA;gluQuadric = gluNewQuadric()&#xD;&#xA;gluQuadricTexture(gluQuadric, GL_TRUE)&#xD;&#xA;&#xD;&#xA;def draw_cylinder(color):&#xD;&#xA;&#xD;&#xA;    glColor3fv(color)&#xD;&#xA;&#xD;&#xA;    gluCylinder(gluQuadric, cylinder_rad, cylinder_rad, cylinder_height, 32, 1)&#xD;&#xA;&#xD;&#xA;    # inner surface&#xD;&#xA;    glColor3f(color[0]*0.3, color[1]*0.3, color[2]*0.3)&#xD;&#xA;    gluCylinder(gluQuadric, cylinder_rad-cylinder_thickness, cylinder_rad-cylinder_thickness, cylinder_height, 32, 1)&#xD;&#xA;&#xD;&#xA;# objects&#xD;&#xA;cylinder_color = (0., 0.5, 0.5)&#xD;&#xA;cylinder_rad = 2.5&#xD;&#xA;cylinder_thickness = 1.8&#xD;&#xA;cylinder_height = 4&#xD;&#xA;&#xD;&#xA;# the radius of the circle along which the icosahedron and torus will rotate&#xD;&#xA;circle_radius = cylinder_rad * 2&#xD;&#xA;&#xD;&#xA;# creating a cloud texture&#xD;&#xA;cloud_texture = pygame.image.load('cloud_texture.jpg')&#xD;&#xA;cloud_texture_surface = pygame.image.tostring(cloud_texture, &quot;RGB&quot;, 1)&#xD;&#xA;cloud_texture_width = cloud_texture.get_width()&#xD;&#xA;cloud_texture_height = cloud_texture.get_height()&#xD;&#xA;&#xD;&#xA;# setting the position and size of the fog&#xD;&#xA;fog_size = 0.25&#xD;&#xA;fog_pos_x = - circle_radius - cylinder_rad/2&#xD;&#xA;fog_pos_y = cylinder_rad/2&#xD;&#xA;fog_pos_z = 1&#xD;&#xA;&#xD;&#xA;# the main rendering cycle&#xD;&#xA;while True:&#xD;&#xA;    for event in pygame.event.get():&#xD;&#xA;        if event.type == pygame.QUIT:&#xD;&#xA;            pygame.quit()&#xD;&#xA;            quit()&#xD;&#xA;&#xD;&#xA;    glClearColor(0, 0.1, 0.1, 1)&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&#xD;&#xA;    &#xD;&#xA;    glEnable(GL_DEPTH_TEST)&#xD;&#xA;&#xD;&#xA;    # setting up the matrix&#xD;&#xA;    glMatrixMode(GL_PROJECTION)&#xD;&#xA;    glLoadIdentity()&#xD;&#xA;    gluPerspective(45.0, float(display[0])/float(display[1]), 0.1, 50.0)&#xD;&#xA;    glMatrixMode(GL_MODELVIEW)&#xD;&#xA;    glLoadIdentity()&#xD;&#xA;&#xD;&#xA;    gluLookAt(0, -10, 10, 0, 0, 0, 0, 1, 0)&#xD;&#xA;    &#xD;&#xA;    # draw a cylinder&#xD;&#xA;    draw_cylinder(cylinder_color)&#xD;&#xA;    &#xD;&#xA;    # setting up the fog&#xD;&#xA;    glEnable(GL_BLEND)&#xD;&#xA;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)&#xD;&#xA;&#xD;&#xA;    glEnable(GL_TEXTURE_2D)&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, glGenTextures(1))&#xD;&#xA;    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, cloud_texture_width, cloud_texture_height, 0, GL_RGB, GL_UNSIGNED_BYTE, cloud_texture_surface)&#xD;&#xA;&#xD;&#xA;    glEnable(GL_FOG)&#xD;&#xA;    glFogi(GL_FOG_MODE, GL_EXP2)&#xD;&#xA;    &#xD;&#xA;    glFogfv(GL_FOG_COLOR, [1, 1, 1, 1])&#xD;&#xA;    glFogf(GL_FOG_DENSITY, 0.5)&#xD;&#xA;    glFogf(GL_FOG_START, 0.0)&#xD;&#xA;    glFogf(GL_FOG_END, 10.0)&#xD;&#xA;&#xD;&#xA;    # drawing the fog&#xD;&#xA;    glBegin(GL_QUADS)&#xD;&#xA;    glTexCoord2f(0.0, 0.0); glVertex3f(fog_pos_x-fog_size, fog_pos_y-fog_size, fog_pos_z)&#xD;&#xA;    glTexCoord2f(1.0, 0.0); glVertex3f(fog_pos_x+fog_size, fog_pos_y-fog_size, fog_pos_z)&#xD;&#xA;    glTexCoord2f(1.0, 1.0); glVertex3f(fog_pos_x+fog_size, fog_pos_y+fog_size, fog_pos_z)&#xD;&#xA;    glTexCoord2f(0.0, 1.0); glVertex3f(fog_pos_x-fog_size, fog_pos_y+fog_size, fog_pos_z)&#xD;&#xA;    glEnd()&#xD;&#xA;&#xD;&#xA;    glDisable(GL_FOG)&#xD;&#xA;    glDisable(GL_TEXTURE_2D)&#xD;&#xA;    glDisable(GL_BLEND)&#xD;&#xA;&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    pygame.time.wait(10)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/f3YV0.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40403" PostHistoryTypeId="1" PostId="13415" RevisionGUID="aa722e42-4831-4215-9f9d-99aeb51e3db4" CreationDate="2023-04-22T07:43:14.410" UserId="19819" Text="Why can't I get fog on OpenGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40404" PostHistoryTypeId="3" PostId="13415" RevisionGUID="aa722e42-4831-4215-9f9d-99aeb51e3db4" CreationDate="2023-04-22T07:43:14.410" UserId="19819" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40405" PostHistoryTypeId="50" PostId="8194" RevisionGUID="9980354d-751a-4e4f-ae26-e550163b8223" CreationDate="2023-04-22T11:05:00.587" UserId="-1" />
  <row Id="40406" PostHistoryTypeId="2" PostId="13416" RevisionGUID="813aeb2d-ec22-4e32-928c-5b85f32b6bd8" CreationDate="2023-04-22T12:40:30.213" UserId="10370" Text="I have two points in 3D space, A and B. I need to have a parametric equation of the **catenary** curve such that:&#xD;&#xA;&#xD;&#xA; Cat(0) = A, &#xD;&#xA;&#xD;&#xA; Cat(1) = B, &#xD;&#xA;&#xD;&#xA; Cat(t)= f(t, A, B)&#xD;&#xA;&#xD;&#xA;How can I derive the function f" ContentLicense="CC BY-SA 4.0" />
  <row Id="40408" PostHistoryTypeId="1" PostId="13416" RevisionGUID="813aeb2d-ec22-4e32-928c-5b85f32b6bd8" CreationDate="2023-04-22T12:40:30.213" UserId="10370" Text="Parametric equation for Catenary curve between two Points" ContentLicense="CC BY-SA 4.0" />
  <row Id="40409" PostHistoryTypeId="3" PostId="13416" RevisionGUID="813aeb2d-ec22-4e32-928c-5b85f32b6bd8" CreationDate="2023-04-22T12:40:30.213" UserId="10370" Text="|mathematics|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40410" PostHistoryTypeId="2" PostId="13417" RevisionGUID="5006d3ec-192d-42f1-90ff-a23496bfb146" CreationDate="2023-04-22T14:42:54.980" UserId="19876" Text="Color correction is tricky. It's always a lot of work to make everything look same.&#xD;&#xA;&#xD;&#xA;I have multiple products (clothing) to take a picture of. One is 100% red, other 100% Orange. Some are multicolor etc.&#xD;&#xA;&#xD;&#xA;If I have - let's say - 1000 images. Optimizing colors of each can take a lot of time.&#xD;&#xA;&#xD;&#xA;I was wondering, if there is any method to take a picture of clothing and put near it a card that is *color reference card*.  It contains RGB/CMYK Colors on it printed. &#xD;&#xA;&#xD;&#xA;Manual Way: I open image and mark on this image where are *reference colors*. Then script adjusts everything till reference colors are correct.&#xD;&#xA;&#xD;&#xA;Automatic way: I was thinking about it as on basis of QRCodes.&#xD;&#xA;&#xD;&#xA;- Script tries to detect reference card on picture&#xD;&#xA;- Script takes samples of each color and corrects image so reference colors are correct&#xD;&#xA;- Everything else should be corrected.&#xD;&#xA;&#xD;&#xA;It's an idea of mine I came up with. Came here to ask if maybe someone already created something like this and if it's possible at all." ContentLicense="CC BY-SA 4.0" />
  <row Id="40412" PostHistoryTypeId="1" PostId="13417" RevisionGUID="5006d3ec-192d-42f1-90ff-a23496bfb146" CreationDate="2023-04-22T14:42:54.980" UserId="19876" Text="Is there a way to automatically optimize imags based on predefined marker on image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40413" PostHistoryTypeId="3" PostId="13417" RevisionGUID="5006d3ec-192d-42f1-90ff-a23496bfb146" CreationDate="2023-04-22T14:42:54.980" UserId="19876" Text="|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40414" PostHistoryTypeId="2" PostId="13418" RevisionGUID="1a2039a1-dc53-4cd9-9d41-33d6945dbd36" CreationDate="2023-04-22T15:07:36.343" UserId="445" Text="&gt; the inner surface of the cylinder, realized as a smaller diameter cylinder, actually gives me just a second cylinder inserted into a wider cylinder. How to achieve a monolithic figure?&#xD;&#xA;&#xD;&#xA;`gluCylinder` does not draw ends — only the sides of a cylinder. You will need to also use [`gluDisk`](https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/gluDisk.xml) to draw flat ends too.&#xD;&#xA;&#xD;&#xA;If you want to have lighting, or back-face culling, you will also need to set `gluQuadricOrientation` to `INSIDE` while drawing the inner surface cylinder.&#xD;&#xA;&#xD;&#xA;Note that this entire style of drawing is obsolete — the modern way is to pre-compute the entire mesh (all surfaces of the cylinder together), put it in a vertex buffer (memory on the GPU), and command the GPU to draw that, rather than computing and sending all the vertices every frame. (This doesn't matter for a scene this simple, but if you wish to draw much more complex scenes, it is important to use buffers for better performance.)&#xD;&#xA;&#xD;&#xA;&gt; fog: now it turns out as shown in the screenshot. I need a full-fledged fog with a cloud texture. What's wrong with the code?&#xD;&#xA;&#xD;&#xA;The fog feature built into the GL fixed-function rendering pipeline does not use a texture, and also doesn't work the way you've set it up. What it does is, _when other objects are being drawn_, blend their color to the fog color based on distance. In order to use it you would have to enable fog while drawing your cylinder, not while drawing the cloud texture.&#xD;&#xA;&#xD;&#xA;But that won't get you textured fog. In order to use a texture, you will need to use a **fragment shader** which computes the fog blending itself and uses the texture instead of just a color. That's a much bigger topic and I'm not able to tell you all the steps to set up a shader in your particular environment, but I hope the pointer will be useful." ContentLicense="CC BY-SA 4.0" />
  <row Id="40416" PostHistoryTypeId="2" PostId="13419" RevisionGUID="5c85c23c-d8c3-499f-85b0-792ecd8d7e6e" CreationDate="2023-04-22T20:33:37.263" UserId="13778" Text="[![gradients][1]][1]&#xD;&#xA;&#xD;&#xA;I am making multiple gradients with GLSL. However, when I started using a loop instead&#xD;&#xA;of a lengthy `else if` condition, the compile time jumped from 2-4sec to 40sec !&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;// (simplified code)&#xD;&#xA;&#xD;&#xA;vec3 gradient(vec3 from, vec3 to, float cursor, int colorSpace) {&#xD;&#xA;    vec3 color;&#xD;&#xA;&#xD;&#xA;    // !! The more switch case there are, the slower it gets, but only perceptible when using a loop (in getBackgroundColor function bellow)&#xD;&#xA;    switch(colorSpace) {&#xD;&#xA;        case 0:&#xD;&#xA;            color = mix(&#xD;&#xA;                from,&#xD;&#xA;                to,&#xD;&#xA;                cursor&#xD;&#xA;            );&#xD;&#xA;            break;&#xD;&#xA;        case 1:&#xD;&#xA;          // return gradient, but using Oklab colors&#xD;&#xA;        case 2:&#xD;&#xA;          // return gradient but using IPT colors, etc&#xD;&#xA;&#xD;&#xA;        // ... up to 13&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    return color;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 getBackgroundColor (vec2 uv, EffectOptions opt) {&#xD;&#xA;    vec3 color;&#xD;&#xA;&#xD;&#xA;    if (opt.effect == 0) {&#xD;&#xA;        // transparent&#xD;&#xA;    } else if (opt.effect == 1) {&#xD;&#xA;        // pattern from image&#xD;&#xA;    } else if (opt.effect == 2) {&#xD;&#xA;        // gradient&#xD;&#xA;        color = gradient(&#xD;&#xA;            opt.color0,&#xD;&#xA;            backgroundColor,&#xD;&#xA;            uvxCursor,&#xD;&#xA;            opt.gradientColorSpace&#xD;&#xA;        );&#xD;&#xA;    } else if (opt.effect == 3) { // debug gradients by showing all of them&#xD;&#xA;        uv.y = -uv.y;&#xD;&#xA;        uv += 1.;&#xD;&#xA;        uv/= 2.;&#xD;&#xA;&#xD;&#xA;        float uvxCursor = clamp(uv.x, 0., 1.);&#xD;&#xA;&#xD;&#xA;        int totalBand = 13; // !! totalBand can be 2, it doesn't seem to changes the compile time at all&#xD;&#xA;&#xD;&#xA;        // Simple loop to avoid a lengthy elseif&#xD;&#xA;        // !! Extremely slow: 40sec compilation time. What is wrong with this loop ??&#xD;&#xA;        for (int i = 0; i &lt; totalBand; i++) {&#xD;&#xA;            if (uv.y &lt; float(i+1)/float(totalBand)) {&#xD;&#xA;                color = gradient(&#xD;&#xA;                    opt.color0,&#xD;&#xA;                    backgroundColor,&#xD;&#xA;                    uvxCursor,&#xD;&#xA;                    i&#xD;&#xA;                );&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    // else... up to 10&#xD;&#xA;&#xD;&#xA;    return vec4(color, 1.);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I use a else if statement like bellow, the compilation goes back to 2sec.&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;        if (uv.y &lt; 1./13.) {&#xD;&#xA;                    color = gradient(&#xD;&#xA;                        opt.color0,&#xD;&#xA;                        backgroundColor,&#xD;&#xA;                        uvxCursor,&#xD;&#xA;                        0&#xD;&#xA;                    );&#xD;&#xA;        } else if (uv.y &lt; 2./13.) {&#xD;&#xA;            color = gradient(&#xD;&#xA;                opt.color0,&#xD;&#xA;                backgroundColor,&#xD;&#xA;                uvxCursor,&#xD;&#xA;                1&#xD;&#xA;            );&#xD;&#xA;        } // ... up to 13&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I have seen this answer https://stackoverflow.com/questions/54408908/custom-shader-material-taking-forever-to-initialize , an it might have something to do with &quot;dynamic branching&quot;.&#xD;&#xA;&#xD;&#xA;But I am quite new to shaders and have a limited understanding. Is there something obviously wrong with using a loop that I am not seeing ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: I am also using ThreeJS version v135 right now (not the latest). I don't think it is an issue, but if nobody sees an issue with the loop above, than I will have to think outside the box.&#xD;&#xA;&#xD;&#xA;PS 2: I profiled my web page, and I think the issue is 9% likely to come from GLSL compilation based on https://discourse.threejs.org/t/getprograminfolog-performance-issue/41069 &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ha4z3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40418" PostHistoryTypeId="1" PostId="13419" RevisionGUID="5c85c23c-d8c3-499f-85b0-792ecd8d7e6e" CreationDate="2023-04-22T20:33:37.263" UserId="13778" Text="GLSL : Extremely slow compilation when using loop" ContentLicense="CC BY-SA 4.0" />
  <row Id="40419" PostHistoryTypeId="3" PostId="13419" RevisionGUID="5c85c23c-d8c3-499f-85b0-792ecd8d7e6e" CreationDate="2023-04-22T20:33:37.263" UserId="13778" Text="|glsl|performance|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40421" PostHistoryTypeId="5" PostId="13419" RevisionGUID="e52cb6fd-cf35-493e-a8c3-e9216801082c" CreationDate="2023-04-23T06:21:01.190" UserId="13778" Comment="typo" Text="[![gradients][1]][1]&#xD;&#xA;&#xD;&#xA;I am making multiple gradients with GLSL. However, when I started using a loop instead&#xD;&#xA;of a lengthy `else if` condition, the compile time jumped from 2-4sec to 40sec !&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;// (simplified code)&#xD;&#xA;&#xD;&#xA;vec3 gradient(vec3 from, vec3 to, float cursor, int colorSpace) {&#xD;&#xA;    vec3 color;&#xD;&#xA;&#xD;&#xA;    // !! The more switch case there are, the slower it gets, but only perceptible when using a loop (in getBackgroundColor function bellow)&#xD;&#xA;    switch(colorSpace) {&#xD;&#xA;        case 0:&#xD;&#xA;            color = mix(&#xD;&#xA;                from,&#xD;&#xA;                to,&#xD;&#xA;                cursor&#xD;&#xA;            );&#xD;&#xA;            break;&#xD;&#xA;        case 1:&#xD;&#xA;          // return gradient, but using Oklab colors&#xD;&#xA;        case 2:&#xD;&#xA;          // return gradient but using IPT colors, etc&#xD;&#xA;&#xD;&#xA;        // ... up to 13&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    return color;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec4 getBackgroundColor (vec2 uv, EffectOptions opt) {&#xD;&#xA;    vec3 color;&#xD;&#xA;&#xD;&#xA;    if (opt.effect == 0) {&#xD;&#xA;        // transparent&#xD;&#xA;    } else if (opt.effect == 1) {&#xD;&#xA;        // pattern from image&#xD;&#xA;    } else if (opt.effect == 2) {&#xD;&#xA;        // gradient&#xD;&#xA;        color = gradient(&#xD;&#xA;            opt.color0,&#xD;&#xA;            backgroundColor,&#xD;&#xA;            uvxCursor,&#xD;&#xA;            opt.gradientColorSpace&#xD;&#xA;        );&#xD;&#xA;    } else if (opt.effect == 3) { // debug gradients by showing all of them&#xD;&#xA;        uv.y = -uv.y;&#xD;&#xA;        uv += 1.;&#xD;&#xA;        uv/= 2.;&#xD;&#xA;&#xD;&#xA;        float uvxCursor = clamp(uv.x, 0., 1.);&#xD;&#xA;&#xD;&#xA;        int totalBand = 13; // !! totalBand can be 2, it doesn't seem to changes the compile time at all&#xD;&#xA;&#xD;&#xA;        // Simple loop to avoid a lengthy elseif&#xD;&#xA;        // !! Extremely slow: 40sec compilation time. What is wrong with this loop ??&#xD;&#xA;        for (int i = 0; i &lt; totalBand; i++) {&#xD;&#xA;            if (uv.y &lt; float(i+1)/float(totalBand)) {&#xD;&#xA;                color = gradient(&#xD;&#xA;                    opt.color0,&#xD;&#xA;                    backgroundColor,&#xD;&#xA;                    uvxCursor,&#xD;&#xA;                    i&#xD;&#xA;                );&#xD;&#xA;                break;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    // else... up to 10&#xD;&#xA;&#xD;&#xA;    return vec4(color, 1.);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I use a else if statement like bellow, the compilation goes back to 2sec.&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;        if (uv.y &lt; 1./13.) {&#xD;&#xA;                    color = gradient(&#xD;&#xA;                        opt.color0,&#xD;&#xA;                        backgroundColor,&#xD;&#xA;                        uvxCursor,&#xD;&#xA;                        0&#xD;&#xA;                    );&#xD;&#xA;        } else if (uv.y &lt; 2./13.) {&#xD;&#xA;            color = gradient(&#xD;&#xA;                opt.color0,&#xD;&#xA;                backgroundColor,&#xD;&#xA;                uvxCursor,&#xD;&#xA;                1&#xD;&#xA;            );&#xD;&#xA;        } // ... up to 13&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I have seen this answer https://stackoverflow.com/questions/54408908/custom-shader-material-taking-forever-to-initialize , and it might have something to do with &quot;dynamic branching&quot;.&#xD;&#xA;&#xD;&#xA;But I am quite new to shaders and have a limited understanding. Is there something obviously wrong with using a loop that I am not seeing ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;PS: I am also using ThreeJS version v135 right now (not the latest). I don't think it is an issue, but if nobody sees an issue with the loop above, then I will have to think outside the box.&#xD;&#xA;&#xD;&#xA;PS 2: I profiled my web page, and I think the issue is 99% likely to come from GLSL compilation based on https://discourse.threejs.org/t/getprograminfolog-performance-issue/41069 &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ha4z3.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40422" PostHistoryTypeId="2" PostId="13420" RevisionGUID="18008ba1-1567-4d77-9533-9a42ccfdb6f7" CreationDate="2023-04-23T08:35:04.443" UserId="7462" Text="Is there an algorithm to rasterize triangles into voxels (3D, not 2D) that is linear in the amount of voxels in the output?&#xD;&#xA;&#xD;&#xA;I.e. given a triangle and a grid, generate the exact voxels that the triangle touches.&#xD;&#xA;&#xD;&#xA;I know that with lines one can use DDA in any dimension to generate the voxels for the line.&#xD;&#xA;&#xD;&#xA;but what do I do if what I want is the full triangle and not just the edges?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40424" PostHistoryTypeId="1" PostId="13420" RevisionGUID="18008ba1-1567-4d77-9533-9a42ccfdb6f7" CreationDate="2023-04-23T08:35:04.443" UserId="7462" Text="3D triangle rasterization" ContentLicense="CC BY-SA 4.0" />
  <row Id="40425" PostHistoryTypeId="3" PostId="13420" RevisionGUID="18008ba1-1567-4d77-9533-9a42ccfdb6f7" CreationDate="2023-04-23T08:35:04.443" UserId="7462" Text="|computational-geometry|triangulation|voxelization|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40426" PostHistoryTypeId="50" PostId="12286" RevisionGUID="bfe28abe-3359-441d-a2da-d48391b18aa9" CreationDate="2023-04-23T09:07:15.857" UserId="-1" />
  <row Id="40433" PostHistoryTypeId="50" PostId="13377" RevisionGUID="e2127b37-6995-435c-98e1-eb07aa1bdb40" CreationDate="2023-04-23T12:00:30.120" UserId="-1" />
  <row Id="40434" PostHistoryTypeId="2" PostId="13422" RevisionGUID="c084351e-a6fc-4f57-899f-d5629c251d44" CreationDate="2023-04-23T19:39:44.813" UserId="19880" Text="It can be shown, with some algebra, that it selects the **shorter** pair of line segments over the longer pair.  This is consistent with bilinear interpolation, i.e. fitting a polynomial of the form&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d***&lt;br /&gt;&#xD;&#xA;to the given data values at the 4 corners of the cell.&#xD;&#xA;&#xD;&#xA;The contour curve at height ***h*** is the locus of points **(*x*, *y*)** that satisfy&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d* - *h* = 0**.&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;Such a contour curve is a hyperbola, which has 2 branches.  The portion of each branch of the hyperbola inside the cell is then approximated with a line segment connecting the intersection points of that branch with the 2 cell edges that it intersect." ContentLicense="CC BY-SA 4.0" />
  <row Id="40436" PostHistoryTypeId="5" PostId="13422" RevisionGUID="1a4bb22e-8eaa-4dca-96ad-4d4c46e859d7" CreationDate="2023-04-23T19:43:49.840" UserId="19880" Comment="edited body" Text="It can be shown (with some algebra) that it selects the **shorter** pair of line segments over the longer pair.  This is consistent with bilinear interpolation, i.e. fitting a polynomial of the form&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d***&lt;br /&gt;&#xD;&#xA;to the given data values at the 4 corners of the cell.&#xD;&#xA;&#xD;&#xA;The contour curve at height ***h*** is the locus of points **(*x*, *y*)** that satisfy&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d* - *h* = 0**.&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;Such a contour curve is a hyperbola, which has 2 branches.  The portion of each branch of the hyperbola inside the cell is then approximated with a line segment connecting the intersection points of that branch with the 2 cell edges that it intersect." ContentLicense="CC BY-SA 4.0" />
  <row Id="40438" PostHistoryTypeId="2" PostId="13423" RevisionGUID="8e3215b1-93dd-4c39-b27a-7874369209c6" CreationDate="2023-04-24T10:39:12.733" UserDisplayName="user1703" Text="Continuing on the answer by user3405743, using a bilinear model, we have that the intersection curve is an hyperbola with axis-aligned asymptotes, so we link the left intersection to the top or bottom one, whichever is leftmost (the segment lengths are unimportant).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The piecewise bilinear model is appropriate in that it defines a continuous surface.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zu70y.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40440" PostHistoryTypeId="5" PostId="13423" RevisionGUID="38590111-59aa-499a-9029-04c4699b190d" CreationDate="2023-04-24T10:48:03.777" UserDisplayName="user1703" Comment="added 11 characters in body" Text="Continuing on the answer by user3405743, using a bilinear model, we have that the intersection curve is an hyperbola with axis-aligned asymptotes, so we link the left intersection to the top or bottom one, whichever is leftmost (the segment lengths themselves are unimportant).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The piecewise bilinear model is appropriate in that it defines a continuous surface.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Zu70y.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40441" PostHistoryTypeId="2" PostId="13424" RevisionGUID="679c21b0-4856-4516-8372-a28e6a0aea12" CreationDate="2023-04-24T10:56:43.507" UserDisplayName="user1703" Text="A possibility is to rasterize the sides of the triangle, and consider all pairs of voxels so generated that have a common $z$. Then rasterize the segment between these voxels." ContentLicense="CC BY-SA 4.0" />
  <row Id="40443" PostHistoryTypeId="12" PostId="13424" RevisionGUID="398873ab-9fba-4691-832b-dd7a9b6cefb4" CreationDate="2023-04-24T10:57:27.367" UserDisplayName="user1703" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:1703,&quot;DisplayName&quot;:&quot;Yves Daoust&quot;}],&quot;DeleteType&quot;:1}" />
  <row Id="40444" PostHistoryTypeId="5" PostId="13424" RevisionGUID="79eb0326-794d-4f38-b7e9-0b5aa8f3d217" CreationDate="2023-04-24T12:16:33.870" UserDisplayName="user1703" Comment="added 99 characters in body" Text="A solution could be on the lines of:&#xD;&#xA;&#xD;&#xA;Consider the side that has the largest extent along some coordinate and draw the Bresenham line along it. Also draw the other two sides and for every voxel of the initial side, find the voxel that has the same coordinate on another side. Then draw segments between the corresponding voxels." ContentLicense="CC BY-SA 4.0" />
  <row Id="40445" PostHistoryTypeId="13" PostId="13424" RevisionGUID="66cc00bb-2db6-42cb-9df2-55f0b5848347" CreationDate="2023-04-24T12:16:41.340" UserDisplayName="user1703" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:1703,&quot;DisplayName&quot;:&quot;Yves Daoust&quot;}]}" />
  <row Id="40446" PostHistoryTypeId="2" PostId="13425" RevisionGUID="156b5a44-397e-4e68-b4fe-5bf8b2b66138" CreationDate="2023-04-24T13:18:11.460" UserId="19881" Text="Albedo in a broad sense is how many percent of the light is reflected. In computer graphics and materials, it is customary to understand it in this, the simplest sense. It does not matter whether the reflected light has a direction or not, whether it is specular or diffuse. Therefore, it can be used both for glossy highlights and for diffusion." ContentLicense="CC BY-SA 4.0" />
  <row Id="40448" PostHistoryTypeId="2" PostId="13426" RevisionGUID="ed09d174-b7d1-4d48-896f-2d950892e20b" CreationDate="2023-04-24T15:10:46.283" UserId="9438" Text="A brute force method which works well and we use in production code:&#xD;&#xA;&#xD;&#xA;1. Calculate AABB of triangle to crate a sublist of voxels that may or may not be intersected by the triangle...&#xD;&#xA;&#xD;&#xA;2. Identify which voxels are intersected by the triangle plane.&#xD;&#xA;&#xD;&#xA;3. Voxels which do intersect the triangle plane, calculate the triangle edge tangent planes and repeat the process for each tangent plane.&#xD;&#xA;    Voxels which are entirely 'in front' of any tangent plane are not intersecting the triangle.&#xD;&#xA;&#xD;&#xA;This process can be threaded (although is lighting fast on modern day CPU's, even with large voxel grids), as calculating the intersection of each voxel is mutatally exclusive of any other.&#xD;&#xA;&#xD;&#xA;To identify if a voxel intersects a plane, simply calculate the dot product of each voxel vertex and the plane and assign a 'weight' to each point of the voxel (i.e 1, 0, -1 for 'in front' of plane, on plane and 'behind' plane respectively) and sum them. Voxels with +/- 8 sums are not intersecting, voxels with sums != +/- 8 are.&#xD;&#xA;&#xD;&#xA;N.B This is if you consider a voxel vertex on the plane as 'intersecting' the plane. If not, you need to ignore any points on the plane when summing and consider the 'weighting' of the voxel wrt to the total number of valid points for that voxel.i.e if 7 not on plane and one is, triangle does not intersect voxel if weigthing sum is equal to +/- 7.&#xD;&#xA;&#xD;&#xA;Depending on the data structure of your voxel grid (voxel struct uses shared vertices i.e vertex indexes), you only need to check each vertex once (per plane, so 4 planes at most) within your sub grid, and then can calculate sums for each voxel. Also you only need to calculate voxel vertex-edge tangent plane intersections, if the voxel intersects the triangle plane in the first place." ContentLicense="CC BY-SA 4.0" />
  <row Id="40450" PostHistoryTypeId="2" PostId="13427" RevisionGUID="dea466de-ded3-4438-97ec-108e4a18af04" CreationDate="2023-04-24T17:15:37.020" UserDisplayName="user1703" Text="The catenary is known to follow the equation &#xD;&#xA;&#xD;&#xA;$$y=a\left(\cosh\left(\frac{x-x_0}a\right)-1\right)+y_0$$ in 2D, where $a, x_0$ and $y_0$ are adjustable parameters.&#xD;&#xA;&#xD;&#xA;You need to change the coordinates to work in the vertical plane that contains $A$ and $B$, and you also need a third piece of information to determine the parameters, such as the length of the curve.&#xD;&#xA;&#xD;&#xA;Unfortunately, due to the transcendental nature of the equations, only a numerical resolution is possible." ContentLicense="CC BY-SA 4.0" />
  <row Id="40452" PostHistoryTypeId="5" PostId="13420" RevisionGUID="e246c216-54d2-48d2-beec-66132ad845c1" CreationDate="2023-04-24T21:02:42.470" UserId="445" Comment="Make title more specific" Text="Is there an algorithm to rasterize triangles into voxels (3D, not 2D) that is linear in the amount of voxels in the output?&#xD;&#xA;&#xD;&#xA;I.e. given a triangle and a grid, generate the exact voxels that the triangle touches.&#xD;&#xA;&#xD;&#xA;I know that with lines one can use DDA in any dimension to generate the voxels for the line, but what do I do if what I want is the full triangle and not just the edges?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40453" PostHistoryTypeId="4" PostId="13420" RevisionGUID="e246c216-54d2-48d2-beec-66132ad845c1" CreationDate="2023-04-24T21:02:42.470" UserId="445" Comment="Make title more specific" Text="3D triangle rasterization to voxels" ContentLicense="CC BY-SA 4.0" />
  <row Id="40454" PostHistoryTypeId="24" PostId="13420" RevisionGUID="e246c216-54d2-48d2-beec-66132ad845c1" CreationDate="2023-04-24T21:02:42.470" Comment="Proposed by 445 approved by 7462 edit id of 622" ContentLicense="CC BY-SA 4.0" />
  <row Id="40455" PostHistoryTypeId="5" PostId="13426" RevisionGUID="21696b92-5442-44b6-916c-8422938c3da3" CreationDate="2023-04-24T21:55:00.297" UserId="9438" Comment="added 45 characters in body" Text="A brute force method which works well and we use in production code:&#xD;&#xA;&#xD;&#xA;1. Calculate AABB of triangle to create a sublist of voxels that may or may not be intersected by the triangle, also calculate the triangle edge tangent planes...&#xD;&#xA;&#xD;&#xA;2. Identify which voxels are intersected by the triangle plane.&#xD;&#xA;&#xD;&#xA;3. For voxels which do intersect the triangle plane, calculate the voxel vertex directions for each tangent plane. If these voxels are entirely 'in front' of any tangent plane, they are not intersecting the triangle.&#xD;&#xA;&#xD;&#xA;This process can be threaded (although is lighting fast on modern day CPU's anyway, even with large voxel grids), as calculating the intersection of each voxel is mutatally exclusive of any other.&#xD;&#xA;&#xD;&#xA;To identify if a voxel intersects a plane, simply calculate the dot product of each voxel vertex (vertexPosition-planePosition) and the plane normal and assign a 'weight' to each point of the voxel (i.e 1, 0, -1 for 'in front' of plane, on plane and 'behind' plane respectively) and sum them. Voxels with +/- 8 sums are not intersecting, voxels with sums != +/- 8 are.&#xD;&#xA;&#xD;&#xA;N.B This is if you consider a voxel vertex on the plane as 'intersecting' the plane. If not, you need to ignore any points on the plane when summing and consider the 'weighting' of the voxel wrt to the total number of valid points for that voxel.i.e if 7 not on plane and one is, triangle does not intersect voxel if weigthing sum is equal to +/- 7.&#xD;&#xA;&#xD;&#xA;Depending on the data structure of your voxel grid (voxel struct uses shared vertices i.e vertex indexes), you only need to check each vertex once (per plane, so 4 planes at most) within your sub grid, and then can calculate sums for each voxel. Also you only need to calculate voxel vertex-edge tangent plane intersections, if the voxel intersects the triangle plane in the first place." ContentLicense="CC BY-SA 4.0" />
  <row Id="40456" PostHistoryTypeId="2" PostId="13428" RevisionGUID="b4773cb3-e9aa-4a8c-9961-7e447f28375a" CreationDate="2023-04-25T07:37:18.717" UserDisplayName="user1703" Text="I have worked on such a project where the colors to be calibrated were surrounded by a reference color chart. The chart could be located by means of Aruco symbols and the location of the color pads deduced by knowing the geometry of the chart.&#xD;&#xA;&#xD;&#xA;You can relatively easily find color calibration target such as below (not the one used in my project):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;For calibration of the colors, a polynomial model can be fitted to the known colors. You will have to know the color coordinates in both the chart and the pictures that you take. RGB seems the most natural representation.&#xD;&#xA;&#xD;&#xA;An extra difficulty appeared in the project: due to shadowing effects, the correction also had to be spatially varying. Make sure that your illumination is uniform to avoid this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, yes, fully automated color calibration is possible.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/z3psB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40458" PostHistoryTypeId="5" PostId="13428" RevisionGUID="19823139-4a40-407e-ab90-fbcd646ebc4d" CreationDate="2023-04-25T08:46:39.477" UserDisplayName="user1703" Comment="added 1 character in body" Text="I have worked on such a project where the colors to be calibrated were surrounded by a reference color chart. The chart could be located by means of Aruco symbols and the location of the color pads deduced by knowing the geometry of the chart.&#xD;&#xA;&#xD;&#xA;You can relatively easily find color calibration targets such as below (not the one used in my project):&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;For calibration of the colors, a polynomial model can be fitted to the known colors. You will have to know the color coordinates in both the chart and the pictures that you take. RGB seems the most natural representation.&#xD;&#xA;&#xD;&#xA;An extra difficulty appeared in the project: due to shadowing effects, the correction also had to be spatially varying. Make sure that your illumination is uniform to avoid this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So, yes, fully automated color calibration is possible.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/z3psB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40459" PostHistoryTypeId="50" PostId="12807" RevisionGUID="cb1e9997-d76c-41f6-9a06-e4fb1234dae7" CreationDate="2023-04-25T19:08:31.080" UserId="-1" />
  <row Id="40461" PostHistoryTypeId="50" PostId="10535" RevisionGUID="ea66a675-f33f-4051-8b20-5cf877c7fc54" CreationDate="2023-04-26T00:05:20.680" UserId="-1" />
  <row Id="40462" PostHistoryTypeId="5" PostId="13422" RevisionGUID="a43b7681-94e7-45fc-b9e6-d723b93599c5" CreationDate="2023-04-26T03:56:43.657" UserId="19880" Comment="added 1 character in body" Text="It can be shown (with some algebra) that it selects the **shorter** pair of line segments over the longer pair.  This is consistent with bilinear interpolation, i.e. fitting a polynomial of the form&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d***&lt;br /&gt;&#xD;&#xA;to the given data values at the 4 corners of the cell.&#xD;&#xA;&#xD;&#xA;The contour curve at height ***h*** is the locus of points **(*x*, *y*)** that satisfy&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d* - *h* = 0**.&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;Such a contour curve is a hyperbola, which has 2 branches.  The portion of each branch of the hyperbola inside the cell is then approximated with a line segment connecting the intersection points of that branch with the 2 cell edges that it intersects." ContentLicense="CC BY-SA 4.0" />
  <row Id="40463" PostHistoryTypeId="5" PostId="13249" RevisionGUID="3abf4a3e-aa1a-43da-b690-462b20a3113d" CreationDate="2023-04-26T09:55:25.410" UserId="7952" Comment="edited body" Text="The approach you are taking works but isn't very efficient. &#xD;&#xA;&#xD;&#xA;Projection of a point onto a triangle can be boiled down to classifying the point into the various regions defined by the support planes of the edges. (there are 7 regions total)&#xD;&#xA;&#xD;&#xA;The seven regions are the triangle face, the 3 edge regions and the 3 vertex regions.&#xD;&#xA;(draw lines perpendicular to each of the 3 edges at the vertex's a,b,c to get a diagram of the regions)&#xD;&#xA;&#xD;&#xA;These are the Voronoi regions of the triangle. The vertex region at A has  normals of (B-A) and (C-A) for the intersecting half spaces. (by using The dot product with the vector (P-A) where P is the original point will tell us if P lies inside the region. IE the barycentric coordinates will be (1,0,0).&#xD;&#xA;&#xD;&#xA;A similar test can be done for vertex B and C getting barycentric coordinates of (0,1,0) and (0,0,1) for each.&#xD;&#xA;&#xD;&#xA;Here are the functions:&#xD;&#xA;&#xD;&#xA;    // Determine if point lies in vertex regions&#xD;&#xA;    AB = b-a;&#xD;&#xA;    AC = c-a;&#xD;&#xA;&#xD;&#xA;    AP = p-a;&#xD;&#xA;    dA1 = dot(AB,AP);&#xD;&#xA;    dA2 = dot(AC,AP);&#xD;&#xA;    if( dA1&lt;=0 and dA2 &lt;=0) return a; // vertex region a (bary coords 1,0,0)&#xD;&#xA;&#xD;&#xA;    BP = p - b;&#xD;&#xA;    dB1 = dot(AB, BP);&#xD;&#xA;    dB2 = dot(AC, BP);&#xD;&#xA;    if( dB1 &gt;= 0 &amp;&amp; dB2=&lt;0 ) return b; // vertex region b (bary coords 0,1,0)&#xD;&#xA;&#xD;&#xA;    CP = p - c;&#xD;&#xA;    dC1 = Dot(AB,CP);&#xD;&#xA;    dC2 = Dot(AC,CP);&#xD;&#xA;    if( dC2 &gt;= 0 &amp;&amp; dC1 &lt;= dC2 ) return c; // vertex region c (bary coords 0,0,1)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To determine if the point lies in the edge regions you can continue with the barycentric coordinate computations. ie summed area method. This computation boils down to using dot products used to compute the vertex regions to check if the point lies in the edge regions.&#xD;&#xA;&#xD;&#xA;    EdgeAB = dA1*dB2 - dB1*dA2;&#xD;&#xA;    if( EdgeAB &lt;= 0 and dA1 &gt;= 0 and dB1 &lt;=0) { &#xD;&#xA;       // lies in edge region bary coords (1-u, u,0); &#xD;&#xA;       // project point onto edge AB and return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    EdgeBC = dB1*dC2 - dC1*dB2; &#xD;&#xA;    if( EdgeBC &lt;= 0 and (dB2-dB1)&gt;=0 and (dC1-dC2)&gt;=0) {&#xD;&#xA;       // lies in edge region BC bary coords (0, 1-u, u)&#xD;&#xA;       // project point onto edge BC and return;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    EdgeAC = dC1*dA2 - dA1*dC2;&#xD;&#xA;    if( EdgeAC &lt;= 0 and dA2&gt;=0 and dC2&lt;=0 ) {&#xD;&#xA;       // lies in edge region AC bary coords (1-u, 0 ,u )&#xD;&#xA;       // project point onto edge AC and return result&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Finally if it isn't in any of these regions it must be inside the triangle face. Luckily we have computed everything needed to find the barycentric coords at this point...&#xD;&#xA;&#xD;&#xA;     summed_area = EdgeAB + EdgeBC +EdgeAC;&#xD;&#xA;     v = EdgeAC / summed_area;&#xD;&#xA;     w = EdgeAB / summed_area;&#xD;&#xA;     return a + ab * v + ac * w;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;According to my notes the original source of this method is the book Real Time Collision Detection by Christer Ericson." ContentLicense="CC BY-SA 4.0" />
  <row Id="40464" PostHistoryTypeId="2" PostId="13429" RevisionGUID="c47b776c-cd18-4f8b-b265-58ddcefbee64" CreationDate="2023-04-26T12:34:26.947" UserDisplayName="user1703" Text="Your problem is essentially planar, as on can be convinced by looking in the direction perpendicular to the plane of the triangle. (This is achieved by using a change of coordinate system such that the normal to the plane becomes $z$.)&#xD;&#xA;&#xD;&#xA;The point of interest can belong to one of seven regions, delimited by normal lines at the triangle vertices (in blue). To tell the region, you need to compare against all three triangle edges (left-of test). If the point falls inside, you are done; otherwise, if it lies on the right of two sides, you project on the common vertex; if it lies on the right of a single side, you need to test against two normals, and the projection will be on a side or a vertex.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TT6nt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40466" PostHistoryTypeId="5" PostId="13429" RevisionGUID="f77a2eab-a27a-41ca-9bab-403d50c128ea" CreationDate="2023-04-26T12:39:48.977" UserDisplayName="user1703" Comment="added 76 characters in body" Text="Your problem is essentially planar, as on can be convinced by looking in the direction perpendicular to the plane of the triangle. (This is achieved by using a change of coordinate system such that the normal to the plane becomes $z$.)&#xD;&#xA;&#xD;&#xA;The point of interest can belong to one of seven regions, delimited by normal lines at the triangle vertices (in blue). To tell the region, you need to compare against all three triangle edges (left-of test). If the point falls inside, you are done; otherwise, if it lies on the right of two sides, you project on the common vertex; if it lies on the right of a single side, you need to test against two normals, and the projection will be on a side or a vertex.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Caution: the discussion is slightly different when the triangle is obtuse.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/TT6nt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40467" PostHistoryTypeId="2" PostId="13430" RevisionGUID="0150c4b2-89c6-42ed-8f21-86a69b3f7626" CreationDate="2023-04-26T12:48:33.343" UserId="19889" Text="I had the same issue in version 0.140.0. Couldn't find any solutions, so I installed the latest Three.js version at the time (0.151.3). It solved the problem, now working as intended.  Maybe it has something to do with the inner workings of the OutlinePass.&#xD;&#xA;&#xD;&#xA;If you're already using the latest version and the problem persists, maybe going back to an older version might solve the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="40469" PostHistoryTypeId="5" PostId="13422" RevisionGUID="34ebd8e5-7fe6-4390-832c-55f9507de54b" CreationDate="2023-04-26T12:58:32.317" UserId="19880" Comment="added 21 characters in body" Text="It can be shown (with some algebra) that it *usually* selects the **shorter** pair of line segments over the longer pair.  When it does, it's consistent with bilinear interpolation, i.e. fitting a polynomial of the form&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d***&lt;br /&gt;&#xD;&#xA;to the given data values at the 4 corners of the cell.&#xD;&#xA;&#xD;&#xA;The contour curve at height ***h*** is the locus of points **(*x*, *y*)** that satisfy&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d* - *h* = 0**.&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;Such a contour curve is a hyperbola, which has 2 branches.  The portion of each branch of the hyperbola inside the cell is then approximated with a line segment connecting the intersection points of that branch with the 2 cell edges that it intersects." ContentLicense="CC BY-SA 4.0" />
  <row Id="40470" PostHistoryTypeId="2" PostId="13431" RevisionGUID="56e34649-0765-4e13-aef0-28db0e68f795" CreationDate="2023-04-26T15:01:10.023" UserId="18529" Text="Is there a way to make copy operations such as `CopyResurce`(d3d11) and `glBlitFramebuffer`(ogl) **on multi-sample resources** faster with Intel UHD integrated graphics?&#xD;&#xA;&#xD;&#xA;For Direct3D11 I was able to collect some data (using Intel's graphics frame analyzer), and it looks like a single call to `CopyResource` can take up to **6ms** (both textures being ~**1200x 800, r8g8b8a8_unorm, 8x**).&#xD;&#xA;&#xD;&#xA;1. Is it a known issue?&#xD;&#xA;2. Does it mean that it's basically impossible to copy ms textures during the render loop or is there something one could do to make the copy faster? &#xD;&#xA;3. Could that be a driver issue? (I used version 31.0.101.2115 while profiling)  " ContentLicense="CC BY-SA 4.0" />
  <row Id="40472" PostHistoryTypeId="1" PostId="13431" RevisionGUID="56e34649-0765-4e13-aef0-28db0e68f795" CreationDate="2023-04-26T15:01:10.023" UserId="18529" Text="Intel UHD extremely slow copy operations" ContentLicense="CC BY-SA 4.0" />
  <row Id="40473" PostHistoryTypeId="3" PostId="13431" RevisionGUID="56e34649-0765-4e13-aef0-28db0e68f795" CreationDate="2023-04-26T15:01:10.023" UserId="18529" Text="|opengl|texture|performance|directx11|memory|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40474" PostHistoryTypeId="5" PostId="13422" RevisionGUID="7f6b533c-75a8-41b3-929c-78697b476c33" CreationDate="2023-04-26T17:15:40.490" UserId="19880" Comment="added 57 characters in body" Text="That disambiguation method *often* selects the **shorter** pair of line segments over the longer pair.&#xD;&#xA;&#xD;&#xA;A different method which can be shown (with some algebra) to *always* select the shorter pair of line segments over the longer pair is based on bilinear interpolation, i.e. fitting a polynomial of the form&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d***&lt;br /&gt;&#xD;&#xA;to the given data values at the 4 corners of the cell.&#xD;&#xA;&#xD;&#xA;The contour curve at height ***h*** is the locus of points **(*x*, *y*)** that satisfy&lt;br /&gt;&#xD;&#xA;***axy* + *bx* + *cy* + *d* - *h* = 0**.&lt;br /&gt;&#xD;&#xA;&#xD;&#xA;Such a contour curve is a hyperbola, which has 2 branches.  The portion of each branch of the hyperbola inside the cell is then approximated with a line segment connecting the intersection points of that branch with the 2 cell edges that it intersects." ContentLicense="CC BY-SA 4.0" />
  <row Id="40475" PostHistoryTypeId="34" PostId="13399" RevisionGUID="399056fd-b808-4156-8f2e-c3e5a4723be0" CreationDate="2023-04-27T03:11:11.453" UserId="-1" Comment="83" />
  <row Id="40480" PostHistoryTypeId="2" PostId="13433" RevisionGUID="d1793840-e8f2-4eb4-ae04-29ef46736b33" CreationDate="2023-04-27T10:35:47.923" UserId="11224" Text="The authors of the article:&#xD;&#xA;&#xD;&#xA;[Impact of correct and simulated focus cues on perceived realism][1]&#xD;&#xA;&#xD;&#xA;seemed to find that simulated depth of field effects were actually detrimental to the illusion of realism, while actual depth of field effects were beneficial.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.cl.cam.ac.uk/~rkm38/pdfs/march2022_impact_of_focus_cues.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="40482" PostHistoryTypeId="2" PostId="13434" RevisionGUID="47397345-0a5a-4cd2-85bf-28fb4e3a6212" CreationDate="2023-04-27T22:17:48.513" UserId="19898" Text="I am trying to map a texture on a UV sphere. I created an algorithm to generate the vertices of the sphere and the UV texture coordinates for each vertex. How I do fix the distortion or aliasing? &#xD;&#xA;The formulas I used to generate the vertices of the sphere are:&#xD;&#xA;x = rsinΦcosθ&#xD;&#xA;y = rcosΦ&#xD;&#xA;z = -rsinΦsinθ&#xD;&#xA;&#xD;&#xA;The formulas used to generate the UV texture coordinates for each vertex are:&#xD;&#xA;θ = arctan(z / x) / 2π&#xD;&#xA;Φ = arcos(y) / π&#xD;&#xA;&#xD;&#xA;I am using Direct3D 12 to render the sphere.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/vQYIg.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40484" PostHistoryTypeId="1" PostId="13434" RevisionGUID="47397345-0a5a-4cd2-85bf-28fb4e3a6212" CreationDate="2023-04-27T22:17:48.513" UserId="19898" Text="Distortion or Aliasing of a UV Sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="40485" PostHistoryTypeId="3" PostId="13434" RevisionGUID="47397345-0a5a-4cd2-85bf-28fb4e3a6212" CreationDate="2023-04-27T22:17:48.513" UserId="19898" Text="|texture|uv-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40491" PostHistoryTypeId="2" PostId="13436" RevisionGUID="66f3aa47-7836-4774-9e89-d4bdd530274e" CreationDate="2023-04-28T07:18:02.293" UserId="13273" Text="This problem occurs, because the most left vertices and the most right vertices are connected while the UV coordinates (texture coordinates) are 1(right) and 0(left)... so the whole texture is interpolated within the small area. (See figure 1)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** This is what you have right now. The green triangles are correct, the red triangles show the problem you have...&#xD;&#xA;&#xD;&#xA;You can add an additional vertex column on the right, where the vertex positions are the same as the most left vertices. (see Figure 2)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** This is what you need. The orange vertices have the same position as the blue vertices. So this column of vertices is duplicated. But the texture coordinates are different. The blue vertices have a texture coordinate (x) = 0 and the orange vertices have a texture coordinate (x) = 1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MSIIx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DOx5q.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40494" PostHistoryTypeId="5" PostId="13436" RevisionGUID="efacf4c1-c813-4fff-a8fd-c896a1b2a5bb" CreationDate="2023-04-28T08:26:56.603" UserId="13273" Comment="added 5 characters in body" Text="This problem might occur, because the most left vertices and the most right vertices are connected while the UV coordinates (texture coordinates) are 1(right) and 0(left)... so the whole texture is interpolated within the small area. (See figure 1)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** This is what you have right now. The green triangles are correct, the red triangles show the problem you have...&#xD;&#xA;&#xD;&#xA;You can add an additional vertex column on the right, where the vertex positions are the same as the most left vertices. (see Figure 2)&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** This is what you need. The orange vertices have the same position as the blue vertices. So this column of vertices is duplicated. But the texture coordinates are different. The blue vertices have a texture coordinate (x) = 0 and the orange vertices have a texture coordinate (x) = 1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MSIIx.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/DOx5q.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40495" PostHistoryTypeId="2" PostId="13437" RevisionGUID="68178c00-717e-48f3-933e-dcf4831c434e" CreationDate="2023-04-28T08:56:33.557" UserId="13273" Text="I know, that when using compute shader, the invocations should to be grouped with respect to a multiple of the hardware minimum workgroup size (Nvidia 32, AMD 64). Otherwise cores are blocked. In case of no communication between invocations is required, does it makes sense to use a bigger workgroup size than the minimum workgroup size of 32 or 64?&#xD;&#xA;&#xD;&#xA;So let's say we have 3200 particles which need to be calculated. No collision detection, no communication between them... and we are working on a Nvidia machine. Is there a performance boost to create one workgroup with 3200 invocations instead of using 100 times one workgroup with 32 invocations?&#xD;&#xA;&#xD;&#xA;Or to put it another way, does the size of the workgroup make a difference, aside from the ability to use shared memory?&#xD;&#xA;&#xD;&#xA;Are there benefits to use smaller workgroup sizes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40497" PostHistoryTypeId="1" PostId="13437" RevisionGUID="68178c00-717e-48f3-933e-dcf4831c434e" CreationDate="2023-04-28T08:56:33.557" UserId="13273" Text="Workgroup size performance change?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40498" PostHistoryTypeId="3" PostId="13437" RevisionGUID="68178c00-717e-48f3-933e-dcf4831c434e" CreationDate="2023-04-28T08:56:33.557" UserId="13273" Text="|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40499" PostHistoryTypeId="5" PostId="13437" RevisionGUID="da761b66-7f6c-42a2-8fee-1de687188ad9" CreationDate="2023-04-28T09:08:06.340" UserId="13273" Comment="deleted 3 characters in body" Text="I know, that when using compute shader, the invocations should to be grouped with respect to a multiple of the hardware minimum workgroup size (Nvidia 32, AMD 64). Otherwise cores are blocked. In case of no communication between invocations is required, does it makes sense to use a bigger workgroup size than the minimum workgroup size of 32 or 64?&#xD;&#xA;&#xD;&#xA;So let's say we have 320 particles which need to be calculated. No collision detection, no communication between them... and we are working on a Nvidia machine. Is there a performance boost to create one workgroup with 320 invocations instead of using 10 times one workgroup with 32 invocations?&#xD;&#xA;&#xD;&#xA;Or to put it another way, does the size of the workgroup make a difference, aside from the ability to use shared memory?&#xD;&#xA;&#xD;&#xA;Are there benefits to use smaller workgroup sizes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40500" PostHistoryTypeId="2" PostId="13438" RevisionGUID="7258199f-1bdd-4498-abd7-ff7c2880ed6c" CreationDate="2023-04-28T12:39:04.697" UserId="13273" Text="For scientific reasons, we have to use doubles in our shaders. We don't need to talk about trying to store data in floating point numbers and so on.&#xD;&#xA;I know there is special GPU hardware for double precision to work faster than on regular GPUs.&#xD;&#xA;&#xD;&#xA;We are writing some GPU based software that should work for standard GPUs (2015 - now).&#xD;&#xA;Do OpenGL, Vulkan, CUDA and OpenCL support double precision?&#xD;&#xA;In the case of using a GPU that is not designed to use doubles, do the APIs emulate them?&#xD;&#xA;So would such software work on these hardware systems?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40502" PostHistoryTypeId="1" PostId="13438" RevisionGUID="7258199f-1bdd-4498-abd7-ff7c2880ed6c" CreationDate="2023-04-28T12:39:04.697" UserId="13273" Text="Graphics API and double precision" ContentLicense="CC BY-SA 4.0" />
  <row Id="40503" PostHistoryTypeId="3" PostId="13438" RevisionGUID="7258199f-1bdd-4498-abd7-ff7c2880ed6c" CreationDate="2023-04-28T12:39:04.697" UserId="13273" Text="|precision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40504" PostHistoryTypeId="2" PostId="13439" RevisionGUID="d9b059aa-9016-4f12-8a1b-fec985607d13" CreationDate="2023-04-29T00:03:13.797" UserId="9438" Text="In your specific example, where there are no race conditions, as long as the workgroup count is a multiple of what the architecture requires (wavefront/warp) there would be no difference as the GPU/driver will schedule as it see's fit and in all likelyhood, the GPU would be fully saturated in both cases (since both are multiple of 32/warp).&#xD;&#xA;&#xD;&#xA;However, if a specific shaders computation is quite heavy (each shader doing a lot), or they are unbalanced wrt to workload (one invocation in a group takes a lot longer than the rest of the group/other groups, 'stalling' the completion of that group), this may trigger a TDR (Timeout, Delay and Recovery) when invoking a lot of workgroups in a single dispatch.&#xD;&#xA;&#xD;&#xA;In these scenarios it is better to lighten the work each shader does (split algorithm into more digestable stages so that the workload is more balanced across the workgroup, and ideally across all workgroups) and/or dispatch batches, flushing/finishing inbetween batches so to keep the OS happy. Balancing the workgroup size vs number of dispatches can be quite difficult when targeting a wide gamut of hardware to achieve optimal performance and may require a 'calibration'/dry-run at runtime to deduce a safe batch/workgroup size." ContentLicense="CC BY-SA 4.0" />
  <row Id="40506" PostHistoryTypeId="2" PostId="13440" RevisionGUID="5b983309-d82e-484a-b7df-3fef4fd9756b" CreationDate="2023-04-29T00:18:41.177" UserId="2654" Text="Double-precision operations have been a requirement of desktop OpenGL and GLSL since 4.0. GPUs don't &quot;emulate&quot; double precision, but that doesn't mean they operate at full-speed either. As with most things, Vulkan is a bit more fine-grained, as SPIR-V requires you to use the `Float64` if you want to use them, and the implementation must support the `shaderFloat64` feature." ContentLicense="CC BY-SA 4.0" />
  <row Id="40511" PostHistoryTypeId="2" PostId="13441" RevisionGUID="d426dee9-fb90-4e03-84dd-614c7b7e7e7c" CreationDate="2023-04-29T03:06:37.070" UserId="19905" Text="Sorry for this question. I know there are many similar questions but I really know nothing about math that involves this case.&#xD;&#xA;&#xD;&#xA;I have a picture taken from a camera. I know some information about this camera and this picture:&#xD;&#xA;&#xD;&#xA;Camera:&#xD;&#xA;&#xD;&#xA;    * FOV       : 61 deg.&#xD;&#xA;    * Altitude  : 91 meters&#xD;&#xA;    * Long.     : -43.17687898427574&#xD;&#xA;    * Lat.      : -22.89925324277859&#xD;&#xA;    * Azimuth   : 109 deg.&#xD;&#xA;    * Pitch     : 91 deg. ( 1 degree below the horizon )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These numbers came from Cesium. I have no access to the camera specifications so they can be with approximate values. However, Cesium was extremely accurate in calculating the actual pixel coordinates of the image, so I think these numbers are pretty close to reality.&#xD;&#xA;&#xD;&#xA;Picture:&#xD;&#xA;&#xD;&#xA;    * Height    : 485px&#xD;&#xA;    * Width     : 496px&#xD;&#xA;&#xD;&#xA;Now, I need to know the real world geographic coordinates of a specific pixel in this image.&#xD;&#xA;&#xD;&#xA;I've made a test with Cesium, and I was able to check some results to serve as test parameters:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    * Pixel at 220 x 322 (w/h)&#xD;&#xA;    * Real world coordinates of that pixel: &#xD;&#xA;        Lat: -22.89974712930635&#xD;&#xA;        Lon: -43.167470162955375&#xD;&#xA;&#xD;&#xA;Cesium is a very good tool to do this job, but I need some backend resource like Java or Python and can't find any ( maybe due to my math limitations I can't determine what works and what doesn't ).&#xD;&#xA;&#xD;&#xA;I found a material I think is very close to what I need, but can't implement it because it is very theoretical: https://medium.com/swlh/ray-tracing-from-scratch-in-python-41670e6a96f9&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the picture from the test case. The red arrow is where the pixel is (approximately, of course. I'm not so precise with the mouse). Have in mind that this picture is a screenshot and may not have same dimensions that the real one I have.:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;... and this is the screenshot of my Cesium map to the same area ( but in 3D view ):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;... and 2D view ( the red mark is the point used in the test case. The Blue mark is where the camera is):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Resuming, I need to take the geographic coordinates of a pixel from a picture using Python or Java ( or any agnostic math pseudo code for laymen that I could implement ).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cQDJ7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6PLXf.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JoGDl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40513" PostHistoryTypeId="1" PostId="13441" RevisionGUID="d426dee9-fb90-4e03-84dd-614c7b7e7e7c" CreationDate="2023-04-29T03:06:37.070" UserId="19905" Text="Calculating world coordinates of a pixel from a camera picture" ContentLicense="CC BY-SA 4.0" />
  <row Id="40514" PostHistoryTypeId="3" PostId="13441" RevisionGUID="d426dee9-fb90-4e03-84dd-614c7b7e7e7c" CreationDate="2023-04-29T03:06:37.070" UserId="19905" Text="|raytracing|transformations|computational-geometry|simulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40515" PostHistoryTypeId="5" PostId="13441" RevisionGUID="4b0cb10c-284c-4f5c-bee4-f7707572ab5c" CreationDate="2023-04-29T05:35:21.313" UserId="19905" Comment="added 3942 characters in body" Text="Sorry for this question. I know there are many similar questions but I really know nothing about math that involves this case.&#xD;&#xA;&#xD;&#xA;I have a picture taken from a camera. I know some information about this camera and this picture:&#xD;&#xA;&#xD;&#xA;Camera:&#xD;&#xA;&#xD;&#xA;    * FOV       : 61 deg.&#xD;&#xA;    * Altitude  : 91 meters&#xD;&#xA;    * Long.     : -43.17687898427574&#xD;&#xA;    * Lat.      : -22.89925324277859&#xD;&#xA;    * Azimuth   : 109 deg.&#xD;&#xA;    * Pitch     : 91 deg. ( 1 degree below the horizon )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;These numbers came from Cesium. I have no access to the camera specifications so they can be with approximate values. However, Cesium was extremely accurate in calculating the actual pixel coordinates of the image, so I think these numbers are pretty close to reality.&#xD;&#xA;&#xD;&#xA;Picture:&#xD;&#xA;&#xD;&#xA;    * Height    : 485px&#xD;&#xA;    * Width     : 496px&#xD;&#xA;&#xD;&#xA;Now, I need to know the real world geographic coordinates of a specific pixel in this image.&#xD;&#xA;&#xD;&#xA;I've made a test with Cesium, and I was able to check some results to serve as test parameters:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    * Pixel at 220 x 322 (w/h)&#xD;&#xA;    * Real world coordinates of that pixel: &#xD;&#xA;        Lat: -22.89974712930635&#xD;&#xA;        Lon: -43.167470162955375&#xD;&#xA;&#xD;&#xA;Cesium is a very good tool to do this job, but I need some backend resource like Java or Python and can't find any ( maybe due to my math limitations I can't determine what works and what doesn't ).&#xD;&#xA;&#xD;&#xA;I found a material I think is very close to what I need, but can't implement it because it is very theoretical: https://medium.com/swlh/ray-tracing-from-scratch-in-python-41670e6a96f9&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is the picture from the test case. The red arrow is where the pixel is (approximately, of course. I'm not so precise with the mouse). Have in mind that this picture is a screenshot and may not have same dimensions that the real one I have.:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;... and this is the screenshot of my Cesium map to the same area ( but in 3D view ):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;... and 2D view ( the red mark is the point used in the test case. The Blue mark is where the camera is):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Resuming, I need to take the geographic coordinates of a pixel from a picture using Python or Java ( or any agnostic math pseudo code for laymen that I could implement ).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;Well... I have some help from ChatGPT and now I have this code in Python (sorry for PT_BR comments):&#xD;&#xA;&#xD;&#xA;    import numpy as np&#xD;&#xA;    &#xD;&#xA;    # FOV       : 61 deg.&#xD;&#xA;    # Altitude  : 91 meters&#xD;&#xA;    # Long.     : -43.17687898427574&#xD;&#xA;    # Lat.      : -22.89925324277859&#xD;&#xA;    # Azimuth   : 109 deg.&#xD;&#xA;    # Pitch     : 91 deg. ( 1 degree below the horizon )&#xD;&#xA;    &#xD;&#xA;    # Width     : 859.358px&#xD;&#xA;    # Height    : 484.983px&#xD;&#xA;    &#xD;&#xA;    # Pixel at 850.1561889648438 x 475.18054962158203 (w/h)&#xD;&#xA;    &#xD;&#xA;    camera_fov = 61            # FOV&#xD;&#xA;    image_width = 859.358      # largura da imagem em pixels&#xD;&#xA;    image_height = 484.983     # altura da imagem em pixels&#xD;&#xA;    camera_height = 90.0       # altura da câmera em metros&#xD;&#xA;    pitch_angle = 91.0         # ângulo de inclinação da câmera em graus&#xD;&#xA;    yaw_angle = 109.0          # ângulo de guinada da câmera em graus&#xD;&#xA;    camera_position = np.array([-43.17687898427574, -22.89925324277859, camera_height])  # posição da câmera no sistema de coordenadas do mundo&#xD;&#xA;    &#xD;&#xA;    # coordenadas 2D do pixel na imagem ( u=w  v=h)&#xD;&#xA;    u = 850.1561889648438     # w&#xD;&#xA;    v = 475.18054962158203    # h&#xD;&#xA;    &#xD;&#xA;    # cálculo das coordenadas 3D do pixel no espaço do mundo&#xD;&#xA;    aspect_ratio = image_width / image_height&#xD;&#xA;    fov = np.radians( camera_fov ) # campo de visão em radianos&#xD;&#xA;    y_fov = 2 * np.arctan(np.tan(fov / 2) * np.cos(np.radians(pitch_angle)))  # campo de visão vertical em radianos&#xD;&#xA;    y_angle = np.radians((v / image_height - 0.5) * y_fov * 180 / np.pi + pitch_angle)  # ângulo vertical em radianos&#xD;&#xA;    x_fov = 2 * np.arctan(np.tan(fov / 2) * np.cos(y_angle))  # campo de visão horizontal em radianos&#xD;&#xA;    x_angle = np.radians((u / image_width - 0.5) * x_fov * 180 / np.pi)  # ângulo horizontal em radianos&#xD;&#xA;    direction = np.array([-np.sin(x_angle), np.cos(x_angle) * np.sin(y_angle), np.cos(x_angle) * np.cos(y_angle)])&#xD;&#xA;    rotation_matrix = np.array([&#xD;&#xA;        [np.cos(np.radians(yaw_angle)), -np.sin(np.radians(yaw_angle)), 0],&#xD;&#xA;        [np.sin(np.radians(yaw_angle)), np.cos(np.radians(yaw_angle)), 0],&#xD;&#xA;        [0, 0, 1]&#xD;&#xA;    ])&#xD;&#xA;    &#xD;&#xA;    direction = rotation_matrix @ direction&#xD;&#xA;    world_coords = camera_position + direction * camera_height / np.tan(y_angle)&#xD;&#xA;    &#xD;&#xA;    # Real world coordinates of that pixel: &#xD;&#xA;    #    Lat: -22.901614465334827&#xD;&#xA;    #    Lon: -43.17465101364515&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    print(world_coords[1],&quot;/&quot;,world_coords[0] )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I've found the numbers very close to what Cesium gave me, then I've made some tests. First I found the pixel near the horizon. All pixels in height less than it will be sky. Then I take all four pixels from horizon to the image bottom:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The result is ( pixel pos ) LAT , LON : ( coordinates calculated by the code )&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    p1 : (   1,264)  -22.40093040092381 , -41.77409577136955&#xD;&#xA;    p2 : ( 858,254)  -22.42828595321902 , -41.76467637515944&#xD;&#xA;    p3 : (   1,481)  -22.68142494320101 , -42.55301747856779 &#xD;&#xA;    p4 : ( 858,481)  -22.68681453552334 , -42.55116168224547&#xD;&#xA;&#xD;&#xA;Now I need to check these coordinates the code gave against those the Cesium calculated to see if the results are the same. &#xD;&#xA;&#xD;&#xA;Don't, but was close.&#xD;&#xA;&#xD;&#xA;I'm curious about what coordinates the code are giving me, so I take a WKT Polygon (GeoJSON) and use the site geojson.io to draw it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;The gray area is the polygon representing the &quot;viewport&quot; ( to the horizon ) that I made from the camera picture ( p1 to p4 ) and calculated by the code.&#xD;&#xA;&#xD;&#xA;The red arrow is where the camera is.&#xD;&#xA;&#xD;&#xA;The Blue triangle is what I think the camera picture are actualy seeing.&#xD;&#xA;&#xD;&#xA;As you can see I'm very close. I also suspect that input values ​​such as pitch and yaw (azimuth) orientation may be different than what Cesium uses. Any help to check the math in the code will be wellcome!!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cQDJ7.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6PLXf.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JoGDl.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/pAmOK.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/4iJoL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40516" PostHistoryTypeId="5" PostId="13439" RevisionGUID="b0974960-fb75-4c07-aadb-d2971fb8cf1a" CreationDate="2023-04-29T07:03:24.417" UserId="9438" Comment="deleted 37 characters in body" Text="In your specific example, where there are no race conditions, as long as the workgroup size is a multiple of what the architecture requires (wavefront/warp) there would be no difference as the GPU/driver will schedule as it see's fit and in all likelyhood, the GPU would be fully saturated in both cases.&#xD;&#xA;&#xD;&#xA;However, if a specific shaders computation is quite heavy (each shader doing a lot), or they are unbalanced wrt to workload (one invocation in a group takes a lot longer than the rest of the group/other groups, 'delaying' the completion of that group), this may trigger a TDR (Timeout, Delay and Recovery) when invoking a lot of workgroups in a single dispatch.&#xD;&#xA;&#xD;&#xA;In these scenarios it is better to lighten the work each shader does (split algorithm into more digestable stages so that the workload is more balanced across the workgroup, and ideally across all workgroups) and/or dispatch batches, flushing/finishing inbetween batches so to keep the OS happy. Balancing the workgroup count vs number of dispatches can be quite difficult when targeting a wide gamut of hardware to achieve optimal performance and may require a 'calibration'/dry-run at runtime to deduce a safe batch size/workgroup count." ContentLicense="CC BY-SA 4.0" />
  <row Id="40517" PostHistoryTypeId="2" PostId="13442" RevisionGUID="6bded538-d37d-498f-a97b-e146243fd69c" CreationDate="2023-04-29T13:12:18.903" UserId="13273" Text="When using compute shaders, some workgroups can be faster than others, for example when all invocations within one group go into the 'if' case, where on another workgroup the invocations go into the 'if' and the 'else' case.&#xD;&#xA;My question: are the workgroups be released which have finished their work while others are still working? And can these warps be used at that time for other shaders? Or are they blocked till all workgroups within that dispatch compute call are finished? Is that hardware specific or driver specific? " ContentLicense="CC BY-SA 4.0" />
  <row Id="40519" PostHistoryTypeId="1" PostId="13442" RevisionGUID="6bded538-d37d-498f-a97b-e146243fd69c" CreationDate="2023-04-29T13:12:18.903" UserId="13273" Text="Partial Workgroup release of compute shaders?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40520" PostHistoryTypeId="3" PostId="13442" RevisionGUID="6bded538-d37d-498f-a97b-e146243fd69c" CreationDate="2023-04-29T13:12:18.903" UserId="13273" Text="|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40521" PostHistoryTypeId="2" PostId="13443" RevisionGUID="6f0018d0-c1cd-4523-868f-d928e54644b4" CreationDate="2023-04-29T13:15:14.847" UserId="19819" Text="I'm building a scene: a cylinder, and a torus and an icosahedron spin around it, enter the fog and exit the fog. Using a file with a fog texture (any). However, I get a black scene at the exit - why is that?&#xD;&#xA;&#xD;&#xA;Code:&#xD;&#xA;```&#xD;&#xA;# BLOCK 1: Imports and Window settings&#xD;&#xA;&#xD;&#xA;from pygame.locals import *&#xD;&#xA;import pygame&#xD;&#xA;import math&#xD;&#xA;from OpenGL.GL import *&#xD;&#xA;from OpenGL.GLU import *&#xD;&#xA;from OpenGL.GL.shaders import compileProgram, compileShader&#xD;&#xA;&#xD;&#xA;# creating a window&#xD;&#xA;pygame.init()&#xD;&#xA;display_size = (800, 600)&#xD;&#xA;pygame.display.set_mode(display_size, DOUBLEBUF | OPENGL)&#xD;&#xA;&#xD;&#xA;# BLOCK 2: Loading and configuring shaders&#xD;&#xA;&#xD;&#xA;vertex_shader = &quot;&quot;&quot;&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;in vec3 position;&#xD;&#xA;in vec2 texture_coords;&#xD;&#xA;&#xD;&#xA;out vec2 new_texture_coords;&#xD;&#xA;&#xD;&#xA;uniform mat4 model;&#xD;&#xA;uniform mat4 view_matrix;&#xD;&#xA;uniform mat4 projection;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    gl_Position = projection * view_matrix * model * vec4(position, 1.0);&#xD;&#xA;    new_texture_coords = texture_coords;&#xD;&#xA;}&#xD;&#xA;&quot;&quot;&quot;&#xD;&#xA;&#xD;&#xA;fragment_shader = &quot;&quot;&quot;&#xD;&#xA;#version 330&#xD;&#xA;&#xD;&#xA;in vec2 new_texture_coords;&#xD;&#xA;&#xD;&#xA;out vec4 outcolor;&#xD;&#xA;&#xD;&#xA;uniform sampler2D cloud_texture;&#xD;&#xA;uniform vec4 fog_color;&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;    vec4 texcolor = texture(cloud_texture, new_texture_coords);&#xD;&#xA;    outcolor = mix(fog_color, texcolor, texcolor.a);&#xD;&#xA;}&#xD;&#xA;&quot;&quot;&quot;&#xD;&#xA;&#xD;&#xA;scale = 1&#xD;&#xA;&#xD;&#xA;def vertex(x, y, z):&#xD;&#xA;    &quot;&quot;&quot; Returning the coordinates of the vertices of the icosahedron &quot;&quot;&quot;&#xD;&#xA;&#xD;&#xA;    length = math.sqrt(x**2 + y**2 + z**2)&#xD;&#xA;&#xD;&#xA;    return [(i * scale) / length for i in (x,y,z)]&#xD;&#xA;&#xD;&#xA;# Create an icosahedron&#xD;&#xA;&#xD;&#xA;# The Golden Ratio&#xD;&#xA;PHI = (1 + math.sqrt(5)) / 2&#xD;&#xA;&#xD;&#xA;vertices = [&#xD;&#xA;          vertex(-1,  PHI, 0), &#xD;&#xA;          vertex( 1,  PHI, 0), &#xD;&#xA;          vertex(-1, -PHI, 0), &#xD;&#xA;          vertex( 1, -PHI, 0), &#xD;&#xA;&#xD;&#xA;          vertex(0, -1, PHI), &#xD;&#xA;          vertex(0,  1, PHI), &#xD;&#xA;          vertex(0, -1, -PHI), &#xD;&#xA;          vertex(0,  1, -PHI), &#xD;&#xA;&#xD;&#xA;          vertex( PHI, 0, -1), &#xD;&#xA;          vertex( PHI, 0,  1), &#xD;&#xA;          vertex(-PHI, 0, -1), &#xD;&#xA;          vertex(-PHI, 0,  1),&#xD;&#xA;&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;            0.0, 1.0, 0.0,&#xD;&#xA;            0.0, 0.0, 1.0,&#xD;&#xA;            1.0, 0.0, 0.0,&#xD;&#xA;        ]&#xD;&#xA;&#xD;&#xA;indices = [&#xD;&#xA;         # 5 polygons around the zero point&#xD;&#xA;         0, 11, 5,&#xD;&#xA;         0, 5, 1,&#xD;&#xA;         0, 1, 7,&#xD;&#xA;         0, 7, 10,&#xD;&#xA;         0, 10, 11,&#xD;&#xA;&#xD;&#xA;         # Polygons around&#xD;&#xA;         1, 5, 9,&#xD;&#xA;         5, 11, 4,&#xD;&#xA;         11, 10, 2,&#xD;&#xA;         10, 7, 6,&#xD;&#xA;         7, 1, 8,&#xD;&#xA;&#xD;&#xA;         # 5 polygons around the third point&#xD;&#xA;         3, 9, 4,&#xD;&#xA;         3, 4, 2,&#xD;&#xA;         3, 2, 6,&#xD;&#xA;         3, 6, 8,&#xD;&#xA;         3, 8, 9,&#xD;&#xA;&#xD;&#xA;         # Polygons around&#xD;&#xA;         4, 9, 5,&#xD;&#xA;         2, 4, 11,&#xD;&#xA;         6, 2, 10,&#xD;&#xA;         8, 6, 7,&#xD;&#xA;         9, 8, 1&#xD;&#xA;]&#xD;&#xA;&#xD;&#xA;shader_program = compileProgram(&#xD;&#xA;    compileShader(vertex_shader, GL_VERTEX_SHADER),&#xD;&#xA;    compileShader(fragment_shader, GL_FRAGMENT_SHADER)&#xD;&#xA;)&#xD;&#xA;&#xD;&#xA;# we get the locations of uniform variables in shaders&#xD;&#xA;model_loc = glGetUniformLocation(shader_program, &quot;model&quot;)&#xD;&#xA;view_loc = glGetUniformLocation(shader_program, &quot;view&quot;)&#xD;&#xA;projection_loc = glGetUniformLocation(shader_program, &quot;projection&quot;)&#xD;&#xA;cloud_texture_loc = glGetUniformLocation(shader_program, &quot;cloud_texture&quot;)&#xD;&#xA;fog_color_loc = glGetUniformLocation(shader_program, &quot;fog_color&quot;)&#xD;&#xA;&#xD;&#xA;# BLOCK 3: Loading texture and setting cloud parameters&#xD;&#xA;&#xD;&#xA;# загружаем текстуру с облаком&#xD;&#xA;cloud_texture = pygame.image.load('fog.png')&#xD;&#xA;cloud_texture_data = pygame.image.tostring(cloud_texture, 'RGB', True)&#xD;&#xA;&#xD;&#xA;# create a texture&#xD;&#xA;cloud_texture_id = glGenTextures(1)&#xD;&#xA;glBindTexture(GL_TEXTURE_2D, cloud_texture_id)&#xD;&#xA;glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, cloud_texture.get_width(), cloud_texture.get_height(),&#xD;&#xA;             0, GL_RGB, GL_UNSIGNED_BYTE, cloud_texture_data)&#xD;&#xA;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)&#xD;&#xA;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)&#xD;&#xA;&#xD;&#xA;# setting the color of the fog&#xD;&#xA;fog_color = [0.4, 0.4, 0.3, 0.5]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# setting the properties of the cloud&#xD;&#xA;cloud_thickness = 0.1&#xD;&#xA;cloud_width = 4&#xD;&#xA;&#xD;&#xA;# BLOCK 4: Animation and setting display properties&#xD;&#xA;&#xD;&#xA;# animation&#xD;&#xA;glMatrixMode(GL_PROJECTION)&#xD;&#xA;gluPerspective(45, (display_size[0] / display_size[1]), 0.1, 50.0)&#xD;&#xA;&#xD;&#xA;glMatrixMode(GL_MODELVIEW)&#xD;&#xA;gluLookAt(0, -10, 10, 0, 0, 0, 0, 1, 0)&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;# BLOCK 5: Rendering the cloud and cylinder&#xD;&#xA;&#xD;&#xA;def draw_cloud():&#xD;&#xA;    glUseProgram(shader_program)  # using a shader program&#xD;&#xA;&#xD;&#xA;    # passing values of uniform variables (matrices) to shaders&#xD;&#xA;    &#xD;&#xA;    # sets the value of the modeling matrix to the shader program&#xD;&#xA;    glUniformMatrix4fv(model_loc, 1, GL_FALSE, glGetFloatv(GL_MODELVIEW_MATRIX))&#xD;&#xA;    &#xD;&#xA;    # sets the value of the view matrix to the shader program&#xD;&#xA;    glUniformMatrix4fv(view_loc, 1, GL_FALSE, glGetFloatv(GL_PROJECTION_MATRIX))&#xD;&#xA;    &#xD;&#xA;    # sets the value of the projection matrix to the shader program&#xD;&#xA;    glUniformMatrix4fv(projection_loc, 1, GL_FALSE, glGetFloatv(GL_PROJECTION_MATRIX))&#xD;&#xA;    &#xD;&#xA;    # sets the value of the fog color to the shader program&#xD;&#xA;    glUniform4fv(fog_color_loc, 1, fog_color)&#xD;&#xA;    &#xD;&#xA;    # sets the texture of clouds in the shader program&#xD;&#xA;    glUniform1i(cloud_texture_loc, 0)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;#     glEnable(GL_FOG)  # turning on the fog&#xD;&#xA;#     glFogfv(GL_FOG_COLOR, fog_color)&#xD;&#xA;#     glFogi(GL_FOG_MODE, GL_LINEAR)&#xD;&#xA;#     glFogf(GL_FOG_START, 2.0)&#xD;&#xA;#     glFogf(GL_FOG_END, 10.0)&#xD;&#xA;    &#xD;&#xA;        # turning on the fog&#xD;&#xA;    glEnable(GL_FOG)&#xD;&#xA;    glFogfv(GL_FOG_COLOR, fog_color)&#xD;&#xA;    glFogi(GL_FOG_MODE, GL_EXP2)&#xD;&#xA;    glFogf(GL_FOG_DENSITY, 0.05)&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;    # Drawing an icosahedron&#xD;&#xA;    glColor3f(1.0, 0.0, 0.0)&#xD;&#xA;    glBegin(GL_TRIANGLES)&#xD;&#xA;    for i in indices:&#xD;&#xA;        glVertex3fv(vertices[i])&#xD;&#xA;    glEnd()&#xD;&#xA;&#xD;&#xA;    # Drawing a cylinder&#xD;&#xA;    glColor3f(1.0, 1.0, 1.0)&#xD;&#xA;    glPushMatrix()&#xD;&#xA;    glTranslatef(5, 0, 0)&#xD;&#xA;    quad = gluNewQuadric()&#xD;&#xA;    glRotatef(90, 1, 0, 0)&#xD;&#xA;    gluDisk(quad, 0.0, 0.5, 32, 32)&#xD;&#xA;    gluCylinder(quad, 0.5, 0.5, 2, 32, 32)&#xD;&#xA;    gluDisk(quad, 0.0, 0.5, 32, 32)&#xD;&#xA;    gluDeleteQuadric(quad)&#xD;&#xA;    glPopMatrix()&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;def end_draw_cloud():&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;    Function to get rid of matrix stack overflow&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;    glDisable(GL_FOG)  # turning off the fog&#xD;&#xA;   &#xD;&#xA;    &#xD;&#xA;# BLOCK 6: Rendering the scene&#xD;&#xA;&#xD;&#xA;def draw_scene():&#xD;&#xA;    # clearing the screen&#xD;&#xA;    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&#xD;&#xA;&#xD;&#xA;    draw_cloud()&#xD;&#xA;&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;    &#xD;&#xA;# BLOCK 7: Main Rendering cycle&#xD;&#xA;&#xD;&#xA;while True:&#xD;&#xA;    for event in pygame.event.get():&#xD;&#xA;        if event.type == pygame.QUIT:&#xD;&#xA;            pygame.quit()&#xD;&#xA;            quit()&#xD;&#xA;&#xD;&#xA;    draw_scene()&#xD;&#xA;&#xD;&#xA;    end_draw_cloud()&#xD;&#xA;    &#xD;&#xA;    pygame.time.wait(10)&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="40523" PostHistoryTypeId="1" PostId="13443" RevisionGUID="6f0018d0-c1cd-4523-868f-d928e54644b4" CreationDate="2023-04-29T13:15:14.847" UserId="19819" Text="Why do I get a black scene in OpenGL in Python?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40524" PostHistoryTypeId="3" PostId="13443" RevisionGUID="6f0018d0-c1cd-4523-868f-d928e54644b4" CreationDate="2023-04-29T13:15:14.847" UserId="19819" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40525" PostHistoryTypeId="2" PostId="13444" RevisionGUID="09157320-3c4b-4c98-a542-3a62aab2b7f2" CreationDate="2023-04-29T23:05:43.940" UserId="38" Text="No DXF is an entirely geometry based format no history or graph functionality is retained.&#xD;&#xA;&#xD;&#xA;yes there eare free open source cad applications that support parametric design. Try freeCAD or SolveSpace both can do 2D only if you want. (there is no real point in developing a 2D only cad application as you for all intents and purposes get the 3rd dimension for free), id prefeer SolveSpace as its more open." ContentLicense="CC BY-SA 4.0" />
  <row Id="40527" PostHistoryTypeId="50" PostId="12872" RevisionGUID="5ef92173-62c5-458c-8ce6-98d71577bc01" CreationDate="2023-04-30T13:01:30.263" UserId="-1" />
  <row Id="40529" PostHistoryTypeId="50" PostId="9426" RevisionGUID="b8c3cb41-14e8-4726-ab08-0f8f2071f58f" CreationDate="2023-05-01T17:05:55.723" UserId="-1" />
  <row Id="40530" PostHistoryTypeId="2" PostId="13445" RevisionGUID="393f6457-32b7-4b7a-9c6f-4b74b95dc393" CreationDate="2023-05-01T18:19:17.123" UserId="19911" Text="I haven't been able to come up with a good solution for this myself, so I thought I'd ask if anyone else has any good ideas on how to approach this problem. Here's more or less what I'm trying to do and what I've been able to research / think of so far:&#xD;&#xA;&#xD;&#xA;I have implemented volumetric light rendering in my engine, and the way you feed atmospheric effects right now is either by a constant global fog (parametrized as optical length), a global height fog (pretty much the same as https://iquilezles.org/articles/fog/) or with a local volume that's parametrized using an AABB and density (which modules the optical length) and also the ability to do falloff in the same way as the height fog (so exponential, towards a user direction). One issue with the volume is that the cutoff at the edges of the volume is quite abrupt, so I'd like to add some feathering to it. An issue with this is that it needs to be integrateble along a ray segment in the same way as the height fog. It turns out that this problem is quite tricky.&#xD;&#xA;&#xD;&#xA;Here's the code from https://iquilezles.org/articles/fog/ which computes the global height fog, this is pretty much the same as in my engine so let's use this instead of my re-written version of it. The `fogAmount` is essentially computing the optical length from `rayOri` towards `rayDir` for a known `distance` (e.g. surface hit). Note that all it needs are these paramters, and it can analytically figure out the optical length from just that (it looks at height difference change to be able to do it analytically).&#xD;&#xA;&#xD;&#xA;    vec3 applyFog( in vec3  rgb,      // original color of the pixel&#xD;&#xA;                   in float distance, // camera to point distance&#xD;&#xA;                   in vec3  rayOri,   // camera position&#xD;&#xA;                   in vec3  rayDir )  // camera to point vector&#xD;&#xA;    {&#xD;&#xA;        float fogAmount = (a/b) * exp(-rayOri.y*b) * (1.0-exp( -distance*rayDir.y*b ))/rayDir.y;&#xD;&#xA;        vec3  fogColor  = vec3(0.5,0.6,0.7);&#xD;&#xA;        return mix( rgb, fogColor, fogAmount );&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The problem I'm trying to solve is similar, but I want to be able to, analytically, figure out the optical density if you had a AABB with some amount of feathering at the edge. The function signature is the same, but instead of `a` and `b` as parameters (these define the height falloff) we'd just have a `feather` parameter that represents how far the feathering should be applied inside the volume. Here's a figure of how something like this looks like:&#xD;&#xA;&#xD;&#xA;[![volume][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/bbUfs.png&#xD;&#xA;&#xD;&#xA;I've not been able to find a good representation to modulate the optical length to make it be numerically integrateable in the same way as Inigo Quilez's height fog. It's possible to find the distance from some point to the surface of an AABB like this:&#xD;&#xA;&#xD;&#xA;    float distance = length( max( max( aabb.min - point, 0.0f ), max( point - aabb.max, 0.0f ) );&#xD;&#xA;&#xD;&#xA;And it would be possible to use that as input to e.g. `smoothstep` to modulate the optical length: `smoothstep( 0.0f, feather, distance )` but there is no physical `point` to do this with, as this is a ray integral. So I guess my &quot;real&quot; question is: is this even possible to solve if this has the form of a ray integral? For height fog à la Inigo Quilez it's possible (it's mentioned in the article that it's possible to derive new such functions by solving the ray integral again with a different set of parameters) but is it also possible to do it in this case as well where we would want to have feathering on the edges of an AABB to change the optical length?&#xD;&#xA;&#xD;&#xA;I realize that this is a bit of an odd question that's more exploratory than anything else... and hopefully I was able to explain what the problem was. Any ideas and help are much appreciated! I've run out of good ideas for doing it as a ray integral :-(&#xD;&#xA;&#xD;&#xA;I have a gut feeling that this somehow involves computing rate of change based on the feathering and taking the incoming ray direction to modulate it (much like the height fog is doing)...&#xD;&#xA;&#xD;&#xA;Thanks for the help!" ContentLicense="CC BY-SA 4.0" />
  <row Id="40532" PostHistoryTypeId="1" PostId="13445" RevisionGUID="393f6457-32b7-4b7a-9c6f-4b74b95dc393" CreationDate="2023-05-01T18:19:17.123" UserId="19911" Text="Numerically integratable fog volume feathering along a ray" ContentLicense="CC BY-SA 4.0" />
  <row Id="40533" PostHistoryTypeId="3" PostId="13445" RevisionGUID="393f6457-32b7-4b7a-9c6f-4b74b95dc393" CreationDate="2023-05-01T18:19:17.123" UserId="19911" Text="|glsl|hlsl|volumetric-scattering|fog|atmospherics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40534" PostHistoryTypeId="2" PostId="13446" RevisionGUID="38535aec-6792-4ca8-b153-255df3ae9cea" CreationDate="2023-05-01T21:39:12.320" UserId="7952" Text="The value of an integration is the area under the curve between the limits of integration. Since the density of the fog is constantly increasing starting at zero until it reaches the density of the constant fog then the value of the increasing fog is directly related to the value of the constant fog by 1/2 since the function we are integrating for both is the same (or directly related only changing by density) at any give (infinitesimally small) slice. Also angle doesn't matter since the rate of change of the fog is still constant only being changed by the angle. &#xD;&#xA;&#xD;&#xA;But, this is only true where the view goes completely from zero to constant fog density. In regions where a fragment is partially inside the non-constant fog then the two are related by a ratio of the distance between the pixel and the edge of the constant region. For example if a pixel is half way through the non-constant fog then it's value is 1/2 of 1/2 or 1/4.&#xD;&#xA;&#xD;&#xA;Unfortunately there is another case where the camera is outside the fog and there is a pixel whose view vector runs parallel to the constant fog and passes only through the non-constant fog. In this case the non-constant fog is essentially constant but at a lowered density. This region has a changing section that increases until the lowered density and then has constant density until it saturates or leaves the lowered density region through another changing density region. In this case the new constant density is related to the ratio of the distance from the constant density fog again. All other calculations remain the same.&#xD;&#xA;&#xD;&#xA;Unfortunately there is another corner case where the view ray passes through the non-constant density region at a corner of the bounding region and the fragment is in a zero density region. In this case the fog calculation is equal to the same value as constant density region where the constant density is related to the distance of the constant bounding region from the view ray. (line to bounding box distance). It is equal to the constant calculation because it pass through an increasing section and a decreasing section of equal size. So it is 2 times 1/2 of constant.&#xD;&#xA;&#xD;&#xA;There is yet another set of corner cases where the view starts inside the non-constant region and looks into either the corners, the constant region or runs parallel to the constant region.&#xD;&#xA;&#xD;&#xA;Implementation boils down to doing line to box intersections where misses return the distance of the ray from the box and a time T along the ray where the ray is closest to the box or intersects with it. Then using the distance and T to classify the fragment into various corner cases. Then finally computing the fog as a sum of the various cases.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;At the end of the day there are so many corner cases (no pun intended) that switching to a ray marched implementation becomes the more attractive solution.  (at least using the method I described here)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40536" PostHistoryTypeId="2" PostId="13447" RevisionGUID="ab1e0451-42d1-490f-89a0-fafcec29fc24" CreationDate="2023-05-01T21:57:15.073" UserId="19913" Text="A well known way of interpolating the gradient field of a scalar field onto faces of a triangular mesh uses the following&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;(source: https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf)&#xD;&#xA;&#xD;&#xA;I'm wondering if there is a principled way of either (a) computing gradients on vertices or (b) average the face-based gradients (maybe by say the barycentric area of the vertex). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CScdz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40538" PostHistoryTypeId="1" PostId="13447" RevisionGUID="ab1e0451-42d1-490f-89a0-fafcec29fc24" CreationDate="2023-05-01T21:57:15.073" UserId="19913" Text="Interpolate Gradients to Vertices of triangular mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="40539" PostHistoryTypeId="3" PostId="13447" RevisionGUID="ab1e0451-42d1-490f-89a0-fafcec29fc24" CreationDate="2023-05-01T21:57:15.073" UserId="19913" Text="|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40540" PostHistoryTypeId="5" PostId="13447" RevisionGUID="bbd32c08-3044-47db-ae10-f7501eb5fad7" CreationDate="2023-05-01T21:57:34.690" UserId="19913" Comment="added 10 characters in body" Text="A well known way of interpolating the gradient field of a scalar field onto faces of a triangular mesh uses the following formula&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;(source: https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf)&#xD;&#xA;&#xD;&#xA;I'm wondering if there is a principled way of either (a) computing gradients on vertices or (b) average the face-based gradients (maybe by say the barycentric area of the vertex). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/CScdz.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40542" PostHistoryTypeId="2" PostId="13448" RevisionGUID="4429a9c6-41ac-4d03-ae74-9e4c12da6c78" CreationDate="2023-05-02T17:58:38.590" UserId="9036" Text="I've been going round in circles trying to understand OpenGL compute shader &quot;work groups&quot; and it's doing my head in. It's all about as clear as mud.&#xD;&#xA;&#xD;&#xA;In my compute program I have to set a local size with something like this:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So what happens if I need to use this shader on an image that's 17x17 pixels? There doesn't seem to be any way to tell OpenGL the actual size of the computation. glDispatchCompute() accepts 3 numbers but where does the 17 come from? &#xD;&#xA;&#xD;&#xA;Do I have to check the coordinates returned by gl_GlobalInvocationID in the shader to see if they're in range?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40544" PostHistoryTypeId="1" PostId="13448" RevisionGUID="4429a9c6-41ac-4d03-ae74-9e4c12da6c78" CreationDate="2023-05-02T17:58:38.590" UserId="9036" Text="OpenGL compute for arbitrary sizes" ContentLicense="CC BY-SA 4.0" />
  <row Id="40545" PostHistoryTypeId="3" PostId="13448" RevisionGUID="4429a9c6-41ac-4d03-ae74-9e4c12da6c78" CreationDate="2023-05-02T17:58:38.590" UserId="9036" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40546" PostHistoryTypeId="4" PostId="13448" RevisionGUID="03a73367-7c05-40ce-b422-ecbc73207000" CreationDate="2023-05-02T18:21:36.390" UserId="9036" Comment="edited title" Text="OpenGL compute for sizes that aren't a multiple of &quot;local_size&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40547" PostHistoryTypeId="2" PostId="13449" RevisionGUID="9b894674-becd-47d8-a36f-ad59bfd4bd61" CreationDate="2023-05-02T19:03:47.150" UserId="9036" Text="Does anybody know if using very small local sizes in compute shaders will hurt performance?&#xD;&#xA;&#xD;&#xA;eg. If I do this in a shader:&#xD;&#xA;&#xD;&#xA;    layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;Will it be slower than if I use larger sizes (eg. x=8, y=8)? &#xD;&#xA;&#xD;&#xA;If size 1 is bad for performance then what's the recommended size? Is it a rectangle based on the value returned by **aglGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE...)**?&#xD;&#xA;&#xD;&#xA;I've read many, many web pages today and the whole issue of &quot;threading&quot; in OpenGL compute shaders is about as clear as mud.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40549" PostHistoryTypeId="1" PostId="13449" RevisionGUID="9b894674-becd-47d8-a36f-ad59bfd4bd61" CreationDate="2023-05-02T19:03:47.150" UserId="9036" Text="OpenGL compute local size vs. performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="40550" PostHistoryTypeId="3" PostId="13449" RevisionGUID="9b894674-becd-47d8-a36f-ad59bfd4bd61" CreationDate="2023-05-02T19:03:47.150" UserId="9036" Text="|opengl|compute-shader|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40555" PostHistoryTypeId="2" PostId="13451" RevisionGUID="a3516465-7fbf-41d2-b751-a13357f52e4c" CreationDate="2023-05-02T20:12:43.547" UserId="13273" Text="Your workgroup size should be a multiple of 32 (Nvidia) or 64 (AMD).&#xD;&#xA;&#xD;&#xA;The reason is, that on the GPU the work units are grouped to a warp(Nvidia) or a wave (AMD) with the size of 32 or 64.&#xD;&#xA;Each unit does the same arithmetic operation within a workgroup. So when define a workgroup with 1 * 1 * 1=1 units, the other 31(Nvidia) or 63(AMD) are blocked. So your performance will drop. " ContentLicense="CC BY-SA 4.0" />
  <row Id="40557" PostHistoryTypeId="2" PostId="13452" RevisionGUID="808a7a96-a461-437c-960f-a06cff1360d9" CreationDate="2023-05-02T21:05:02.350" UserId="13273" Text="You can define you workgroup size as 8x8x1 within the shader. Outside the shader you can execute the glDispatchCompute(3,3,1).&#xD;&#xA;&#xD;&#xA;Now you have 24x24 invocations which is larger than you 17x17 image. &#xD;&#xA;&#xD;&#xA;Then, within the shader you can query the gl_GlobalInvocationID if you are still inside the image range and if so, do the work" ContentLicense="CC BY-SA 4.0" />
  <row Id="40559" PostHistoryTypeId="2" PostId="13453" RevisionGUID="d3b22746-4d47-4f40-83ce-a2721d25a367" CreationDate="2023-05-02T22:01:11.670" UserId="19114" Text="I need to write a program that evaluates a cubic bezier curve, using threejs and vertex shader.&#xD;&#xA;&#xD;&#xA;I tried to calculate the bezier curve based on the x axis and the control points using the cubic bezier formula as a function that returns the vertex position, but what I got was a random straight deformed line. Here it was my attempt:&#xD;&#xA;&#xD;&#xA;    &lt;script src=&quot;https://threejs.org/build/three.js&quot;&gt;&lt;/script&gt; &#xD;&#xA;        &lt;script type=&quot;module&quot;&gt;&#xD;&#xA;        const   rendSize    = new THREE.Vector2();&#xD;&#xA;    &#xD;&#xA;    var     controls, &#xD;&#xA;            scene,&#xD;&#xA;            camera,&#xD;&#xA;            renderer,&#xD;&#xA;            shaderMat;&#xD;&#xA;    &#xD;&#xA;    function main() {&#xD;&#xA;    &#xD;&#xA;        renderer = new THREE.WebGLRenderer();&#xD;&#xA;    &#xD;&#xA;        document.body.appendChild(renderer.domElement);&#xD;&#xA;    &#xD;&#xA;        scene   = new THREE.Scene();&#xD;&#xA;    &#xD;&#xA;        camera = new THREE.OrthographicCamera( -10., 10., 10., -10., -10.0, 10.0 );&#xD;&#xA;      &#xD;&#xA;            var vShader =  `&#xD;&#xA;            //bellow is bezier formula&#xD;&#xA;            vec3 toBezier(float t, vec3 P0, vec3 P1, vec3 P2, vec3 P3) {&#xD;&#xA;                    float t2 = t * t;&#xD;&#xA;                    float one_minus_t = 1.0 - t;&#xD;&#xA;                    float one_minus_t2 = one_minus_t * one_minus_t;&#xD;&#xA;                    return (P0 * one_minus_t2 * one_minus_t + P1 * 3.0 * t * one_minus_t2 + P2 * 3.0 * t2 * one_minus_t + P3 * t2 * t);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            uniform vec3 p0;&#xD;&#xA;            uniform vec3 p1;&#xD;&#xA;            uniform vec3 p2;&#xD;&#xA;            uniform vec3 p3;&#xD;&#xA;        &#xD;&#xA;            void main(void) {&#xD;&#xA;                //the plan was to create a bezier curve based on the x position and the control points&#xD;&#xA;                vec3 pos = toBezier(position.x, p0, p1, p2, p3);&#xD;&#xA;                gl_Position = projectionMatrix * modelViewMatrix * vec4(pos.x, pos.y, 0.0, 1.0);&#xD;&#xA;            }&#xD;&#xA;     &#xD;&#xA;      `;&#xD;&#xA;    &#xD;&#xA;        generateCurve(vShader);&#xD;&#xA;    &#xD;&#xA;        renderer.clear();&#xD;&#xA;        renderer.render(scene, camera);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    function generateCurve(vShader) {&#xD;&#xA;        var ptosControle =  [   new THREE.Vector3( 0.0, 0.0, 0.0 ),&#xD;&#xA;                                new THREE.Vector3( -0.5, Math.sin(Math.PI/2.0) / 2.0, 0.0 ),&#xD;&#xA;                                new THREE.Vector3(  0.5, Math.sin(3.0*Math.PI/2.0) / 2.0, 0.0 ),&#xD;&#xA;                                new THREE.Vector3(  1.0, 1.0, 0.0 )&#xD;&#xA;                            ];&#xD;&#xA;        shaderMat = new THREE.ShaderMaterial(   &#xD;&#xA;            {   uniforms        :   {   &#xD;&#xA;                                        p0          : { value   : ptosControle[0]},&#xD;&#xA;                                        p1          : { value   : ptosControle[1]},&#xD;&#xA;                                        p0          : { value   : ptosControle[2]},&#xD;&#xA;                                        p3          : { value   : ptosControle[3]},&#xD;&#xA;                                    },&#xD;&#xA;                vertexShader    :   vShader,&#xD;&#xA;            } );&#xD;&#xA;    &#xD;&#xA;        const objPolCtrl        = new THREE.Line (  new THREE.BufferGeometry().setFromPoints(ptosControle),&#xD;&#xA;                 &#xD;&#xA;&#xD;&#xA;                                   shaderMat&#xD;&#xA;                                            );&#xD;&#xA;    scene.add(objPolCtrl);&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;main();&#xD;&#xA;    &lt;/script&gt; " ContentLicense="CC BY-SA 4.0" />
  <row Id="40561" PostHistoryTypeId="1" PostId="13453" RevisionGUID="d3b22746-4d47-4f40-83ce-a2721d25a367" CreationDate="2023-05-02T22:01:11.670" UserId="19114" Text="Given 2d control points, how to write a vertex shader that evaluates a cubic bezier curve?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40562" PostHistoryTypeId="3" PostId="13453" RevisionGUID="d3b22746-4d47-4f40-83ce-a2721d25a367" CreationDate="2023-05-02T22:01:11.670" UserId="19114" Text="|opengl|shader|bezier-curve|javascript|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40564" PostHistoryTypeId="5" PostId="13451" RevisionGUID="0714d853-ad3e-4866-9e8e-4e3d9854bc29" CreationDate="2023-05-03T09:47:34.353" UserId="13273" Comment="added 187 characters in body" Text="Your workgroup size should be a multiple of 32 (Nvidia) or 64 (AMD).&#xD;&#xA;&#xD;&#xA;The reason is, that on the GPU the work units are grouped to a warp(Nvidia) or a wave (AMD) with the size of 32 or 64.&#xD;&#xA;Each unit does the same arithmetic operation within a workgroup. So when define a workgroup with 1 * 1 * 1=1 units, the other 31(Nvidia) or 63(AMD) are blocked. So your performance will drop (it will only drop in case you are using more warps or waves than your GPU has, because then they are in a kind of waiting queue and will be executed when free warps/waves are available). " ContentLicense="CC BY-SA 4.0" />
  <row Id="40565" PostHistoryTypeId="2" PostId="13454" RevisionGUID="7a9acc0a-908b-4e80-8b75-bfeaa92801bb" CreationDate="2023-05-03T12:23:50.873" UserId="17270" Text="[![loop illustrated in cyan][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0W2FL.png&#xD;&#xA;&#xD;&#xA;The input is a sphere(defined by radius and center) and a loop defined by a set of points(unordered, illustrated in cyan in the image above) that satisfy the implicit function of the sphere. How can I get the region enclosed by it? &#xD;&#xA;&#xD;&#xA;I've thought of using simple BFS(breadth first search) on sphere. &#xD;&#xA;1. first create a sphere mesh with specified center and radius&#xD;&#xA;2. inflate the boundary points several times to form a closed loop(if the points are ordered, then it's better to perform a shortest path algorithm to make sure the loop is closed)&#xD;&#xA;3. pick a random seed to extract the patch&#xD;&#xA;&#xD;&#xA;there are several drawbacks of this algorithm: &#xD;&#xA;1.because the seed is random, I might end up getting the outer region of the boundary&#xD;&#xA;2.even if I get the right region, the boundary is not perfect(ie. the extracted triangles are not clipped to fit the shape of the boundary)&#xD;&#xA;&#xD;&#xA;I'm wondering if there are alternatives to solve this kind of problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40567" PostHistoryTypeId="1" PostId="13454" RevisionGUID="7a9acc0a-908b-4e80-8b75-bfeaa92801bb" CreationDate="2023-05-03T12:23:50.873" UserId="17270" Text="How to extract region inside a loop on sphere" ContentLicense="CC BY-SA 4.0" />
  <row Id="40568" PostHistoryTypeId="3" PostId="13454" RevisionGUID="7a9acc0a-908b-4e80-8b75-bfeaa92801bb" CreationDate="2023-05-03T12:23:50.873" UserId="17270" Text="|mesh|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40569" PostHistoryTypeId="2" PostId="13455" RevisionGUID="765282bd-798f-4cac-b67f-58da0fbb24e3" CreationDate="2023-05-03T13:51:37.343" UserId="7952" Text="One solution is to use a simple polyhedron clipping algorithm.&#xD;&#xA;&#xD;&#xA;First, Generate a non-planar polygon from the path of the loop, it sounds like this is already available. Then for each segment of the polygon define a plane that is perpendicular to the surface of the sphere and passes through the polygon segment. The normal for the plane is tangent to the sphere at that point and contains a point on the line..&#xD;&#xA;&#xD;&#xA;Using the plane, iterate over every triangle in the sphere and classify the triangles as being on the negative side of the plane (distance to plane for all vertices of the triangle are negative), the positive side of the plane (all distances are positive) or crossing the plane (some combination of positive and negative). &#xD;&#xA;&#xD;&#xA;With the plane normal computed to point inside the polygon:&#xD;&#xA;Discard triangles on the negative side, keep triangles on the positive side, and clip triangles to fit that cross.&#xD;&#xA;&#xD;&#xA;Repeat this process for every segment of the polygon.&#xD;&#xA;&#xD;&#xA;At least 1 more plane should be created that clips away the back side of the sphere. (usually just choose 3 points on the polygon then form a plane from them, and offset it by a small amount so it doesn't intersect the polygon). Create another plane offset in the opposite direction could be done to complete a convex polyhedron surrounding the region to be clipped.&#xD;&#xA;&#xD;&#xA;This is similar to how decals are generated for a polygon mesh in some algorithms.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40571" PostHistoryTypeId="5" PostId="13455" RevisionGUID="841c6cad-5ceb-4b5d-afa1-16fc27cc4155" CreationDate="2023-05-03T14:15:59.250" UserId="7952" Comment="added 414 characters in body" Text="If the loop is convex then one solution is to use a simple polyhedron clipping algorithm.&#xD;&#xA;&#xD;&#xA;First, Generate a non-planar polygon from the path of the loop, it sounds like this is already available. Then for each segment of the polygon define a plane that is perpendicular to the surface of the sphere and passes through the polygon segment. The normal for the plane is tangent to the sphere at that point and contains a point on the line..&#xD;&#xA;&#xD;&#xA;Using the plane, iterate over every triangle in the sphere and classify the triangles as being on the negative side of the plane (distance to plane for all vertices of the triangle are negative), the positive side of the plane (all distances are positive) or crossing the plane (some combination of positive and negative). &#xD;&#xA;&#xD;&#xA;With the plane normal computed to point inside the polygon:&#xD;&#xA;Discard triangles on the negative side, keep triangles on the positive side, and clip triangles to fit that cross.&#xD;&#xA;&#xD;&#xA;Repeat this process for every segment of the polygon.&#xD;&#xA;&#xD;&#xA;At least 1 more plane should be created that clips away the back side of the sphere. (usually just choose 3 points on the polygon then form a plane from them, and offset it by a small amount so it doesn't intersect the polygon). Create another plane offset in the opposite direction could be done to complete a convex polyhedron surrounding the region to be clipped.&#xD;&#xA;&#xD;&#xA;This is similar to how decals are generated for a polygon mesh in some algorithms.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If the loop is not convex then a non-convex, non-planar (for polygon's that do not self intersect) polygon triangulation algorithm could be used. In this method triangulate the polygon, then align all vertices with the surface of the sphere (using a line formed between the center of the sphere and the generated point). Then tesselate to get triangle area near some preset value." ContentLicense="CC BY-SA 4.0" />
  <row Id="40572" PostHistoryTypeId="2" PostId="13456" RevisionGUID="7d88215d-ca5b-46a7-a2d9-f821198587c0" CreationDate="2023-05-03T17:00:10.940" UserDisplayName="user1703" Text="Given the low curvature of the curve, I guess that a simple nearest-neighbor strategy will allow you to reconstruct it. Start at an arbitrary point, link to the nearest neighbor, then link the nearest neighbor to its nearest neighbor *in the opposite direction* (disregard the points in the incoming half-plane). You can do this in the projected view or in spherical coordinates.&#xD;&#xA;&#xD;&#xA;Now unwrapping the mesh in spherical coordinates the problem becomes a planar one and you have to build the intersection of the triangles and the inside of the curve. An interesting option is to resample the curve on the parallels, meridians and the tile diagonals: this directly gives you the intersection points with the facets of the mesh.&#xD;&#xA;&#xD;&#xA;A final, uneasy step, is to determine which triangles are wholly contained inside the curve (those that carry no intersection on their sides and have a vertex inside it), and the remaining portions of those intersected by the curve. You will have to reconstruct the intersection polygons, and possibly triangulate them to keep triangular facets." ContentLicense="CC BY-SA 4.0" />
  <row Id="40574" PostHistoryTypeId="5" PostId="13452" RevisionGUID="db074327-44aa-43d6-95e5-9dc111a13780" CreationDate="2023-05-04T09:19:48.503" UserId="13273" Comment="added 4495 characters in body" Text="First of all, let me explain how `local_size_x local_size_y local_size_z` and `glDispatchCompute(x, y, z)` are related to each other:&#xD;&#xA;&#xD;&#xA;The workgroup size can be defined within the shader with the following command: `layout (local_size_x = ..., local_size_y = ..., local_size_z = ...) in;`&#xD;&#xA;The workgroup size is defined by the multiplication of all 3 local_sizes: `workgroupSize = local_size_x * local_size_y * local_size_z`&#xD;&#xA;&#xD;&#xA;The `glDispatchCompute(x, y, z)` command executes the defined workgroup x * y * z times.&#xD;&#xA;&#xD;&#xA;For example when saying: `layout (local_size_x = 2, local_size_y = 3, local_size_z = 4) in;` with `glDispatchCompute(5, 6, 7)` you will have 5 * 6 * 7 = 210 workgroups where workgroup has 2 * 3 * 4 = 24 invocations each.&#xD;&#xA;&#xD;&#xA;Within the compute shader you have the following built-in input variables:&#xD;&#xA;The following information is copied from [khronos website][1]&#xD;&#xA;&#xD;&#xA;    in uvec3 gl_NumWorkGroups; // This variable contains the number of work groups passed to the dispatch function.&#xD;&#xA;    in uvec3 gl_WorkGroupID; // This is the current work group for this shader invocation. Each of the XYZ components will be on the half-open range [0, gl_NumWorkGroups.XYZ).&#xD;&#xA;    in uvec3 gl_LocalInvocationID; // This is the current invocation of the shader within the work group. Each of the XYZ components will be on the half-open range [0, gl_WorkGroupSize.XYZ).&#xD;&#xA;    in uvec3 gl_GlobalInvocationID; // This value uniquely identifies this particular invocation of the compute shader among all invocations of this compute dispatch call. It's a short-hand for the math computation: gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID;&#xD;&#xA;    in uint  gl_LocalInvocationIndex; // This is a 1D version of gl_LocalInvocationID. It identifies this invocation's index within the work group. It is short-hand for this math computation: &#xD;&#xA;    // gl_LocalInvocationIndex =&#xD;&#xA;    //     gl_LocalInvocationID.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y +&#xD;&#xA;    //     gl_LocalInvocationID.y * gl_WorkGroupSize.x + &#xD;&#xA;    //     gl_LocalInvocationID.x;&#xD;&#xA;    const uvec3 gl_WorkGroupSize;   // GLSL ≥ 4.30. The gl_WorkGroupSize variable is a constant that contains the local work-group size of the shader, in 3 dimensions. It is defined by the layout qualifiers local_size_x/y/z. This is a compile-time constant.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;With these built-in variables you can figue out, which invocation is the current.&#xD;&#xA;&#xD;&#xA;Each workgroup shares memory where each invocation within that workgroup can access to. This memory can be defined in the following way:&#xD;&#xA;&#xD;&#xA;    shared vec3 variableName;&#xD;&#xA;&#xD;&#xA;The variable can NOT be initialized by declaration! The shared memory is faster in access than the global memory (ShaderStorageBufferObjects [SSBO]). So after identifying which invocation belongs to which pixel within an image, each invocation can load the one pixel data from the image (global memory (slow)) and stores the values to shared memory, so that other invocations within the same workgroup can access them. This is faster than telling each invocation to load multiple pixels directly from the image... Have in mind, this shared memory is very limited!&#xD;&#xA;&#xD;&#xA;Lets go back to the workgroup size. The values of the example from above were choosen to let you understand how the workgroup size and the `glDispatchCompute()`command are related to each other. But this workgroup size is choosen badly! And following reason tells you why:&#xD;&#xA;On GPUs the work units (each executing one invocation) are grouped to so called `warps` (Nvidia) and `waves` (AMD). The vendor (Nvidia and AMD) have different sizes for these `warps | waves`. Nvidia group 32 work units to one warp, where AMD group 64 work units to one wave. Your workgroup size should be a multiple of your vendors `warp`(Nvidia), `wave`(AMD) size. Because when for example defining the workgroup size to be 1, the other 31(Nvidia) 63(AMD) work units will be blocked...&#xD;&#xA;&#xD;&#xA;Thats not all... The next importent thing which you need to know when defining the workgroup size is: Each work unit within a workgroup calculate the same arithmetic operation. So when you have a conditional state within your shader (if(...){...} else {...}) then it would be good, if each invocation within the workgroup goes to the same branch (all should go to the `if` or all should go to the `else` branch). Because otherwise, when some invocations within the workgroup go to the `if` branch, all other invocation which would go to the `else` branch will wait until the `if` branch has finished their work. Then the `else` branch will start its work while the invocations from the `if` branch will wait till it is finished. So your shader will be very slow. &#xD;&#xA;&#xD;&#xA;As you can see, when defining the workgroup size several aspects have to be taken care of.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Compute_Shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="40575" PostHistoryTypeId="2" PostId="13457" RevisionGUID="f71abdf6-e9f7-46d6-98e1-fe9bb9722b54" CreationDate="2023-05-04T09:39:36.837" UserId="9438" Text="Yes resources will be availiable for the next command from the command queue, be it compute or other type of shader, even when the previous dispatch operations have not finished.&#xD;&#xA;&#xD;&#xA;For this reason, if subsequent shaders rely on output of a previous shader, these need to have barriers in place or wait until the command queue is empty and and the operations are finished (glFinish).&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    glUse(computeShader1);      &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;    &#xD;&#xA;    glUse(computeShader2);      &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;    &#xD;&#xA;    // Even at this point, shader1 could still have workgroups being processed... shader2 will either be in the command queue or currently being have workgroups being processed...&#xD;&#xA;&#xD;&#xA;To use glFinish()...&#xD;&#xA;&#xD;&#xA;    glUse(computeShader1);      &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;    &#xD;&#xA;    glFinish();     // Program will wait here until all GL operations in command queue are finished (queue will be empty)...&#xD;&#xA;    &#xD;&#xA;    // At this point, all of shader1's workgroups have finished...&#xD;&#xA;    &#xD;&#xA;    glUse(computeShader2);     &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;&#xD;&#xA;You could use glFlush if you wish to process the commands without stalling the program, however this will not guarantee that subsequent commands are not being processed prematurely to what you think (since program is not stalled, it only empties the command queue telling GL to process what was in the queue and empty the queue).&#xD;&#xA;&#xD;&#xA;It's important to note the difference between [glFlush][1] and [glFinish][2]. &#xD;&#xA;&#xD;&#xA;glFlush tells GL to process all the commands that have been queued up to that point and clears the queue upto that point. Main program thread is not halted, and can carry on filling up (a now empty) command queue (while GL processes the 'flushed' operations).&#xD;&#xA;&#xD;&#xA;glFinish tells GL to process all the commands that have been queued (like flush), but stalls the calling thread until GL is finished processing (which, in the example code, will prevent the second dispatch call until GL is finished processing its queue of commands, i.e no overlapping operations). When program continues, the queue will be empty and operations will have been processed.&#xD;&#xA;&#xD;&#xA;As mentioned above, for compute shaders this is especially important if the input of shader2 relies on the output of shader1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glFlush.xml&#xD;&#xA;  [2]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glFinish.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="40577" PostHistoryTypeId="5" PostId="13457" RevisionGUID="4fbe9e16-0924-4b93-bbf1-bb54d3c67b9d" CreationDate="2023-05-04T09:46:01.037" UserId="9438" Comment="added 14 characters in body" Text="Yes resources will be availiable for the next command from the command queue, be it compute or other type of shader, even when the previous dispatch operations have not finished.&#xD;&#xA;&#xD;&#xA;For this reason, if subsequent shaders rely on output of a previous shader, these need to have barriers in place or wait until the command queue is empty and and the operations are finished (glFinish).&#xD;&#xA;&#xD;&#xA;e.g.&#xD;&#xA;&#xD;&#xA;    glUseProgram(computeShader1);      &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;    &#xD;&#xA;    glUseProgram(computeShader2);      &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;    &#xD;&#xA;    // Even at this point, shader1 could still have workgroups being processed... shader2 will either be in the command queue or currently being have workgroups being processed...&#xD;&#xA;&#xD;&#xA;To use glFinish()...&#xD;&#xA;&#xD;&#xA;    glUseProgram(computeShader1);      &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;    &#xD;&#xA;    glFinish();     // Program will wait here until all GL operations in command queue are finished (queue will be empty)...&#xD;&#xA;    &#xD;&#xA;    // At this point, all of shader1's workgroups have finished...&#xD;&#xA;    &#xD;&#xA;    glUseProgram(computeShader2);     &#xD;&#xA;    glDispatchCompute(...)&#xD;&#xA;&#xD;&#xA;You could use glFlush if you wish to process the commands without stalling the program, however this will not guarantee that subsequent commands are not being processed prematurely to what you think (since program is not stalled, it only empties the command queue telling GL to process what was in the queue and empty the queue).&#xD;&#xA;&#xD;&#xA;It's important to note the difference between [glFlush][1] and [glFinish][2]. &#xD;&#xA;&#xD;&#xA;glFlush tells GL to process all the commands that have been queued up to that point and clears the queue upto that point. Main program thread is not halted, and can carry on filling up (a now empty) command queue (while GL processes the 'flushed' operations).&#xD;&#xA;&#xD;&#xA;glFinish tells GL to process all the commands that have been queued (like flush), but stalls the calling thread until GL is finished processing (which, in the example code, will prevent the second dispatch call until GL is finished processing its queue of commands, i.e no overlapping operations). When program continues, the queue will be empty and operations will have been processed.&#xD;&#xA;&#xD;&#xA;As mentioned above, for compute shaders this is especially important if the input of shader2 relies on the output of shader1.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glFlush.xml&#xD;&#xA;  [2]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glFinish.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="40578" PostHistoryTypeId="5" PostId="13448" RevisionGUID="369ea1a5-6ae4-412f-af19-4c75d38a0a32" CreationDate="2023-05-04T10:18:01.770" UserId="9036" Comment="added 19 characters in body" Text="I've been going round in circles trying to understand OpenGL compute shader &quot;work groups&quot; and it's doing my head in. It's all about as clear as mud.&#xD;&#xA;&#xD;&#xA;In my compute program I have to set a local size with something like this (for example):&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;So what happens if I need to use this shader on an image that's 17x17 pixels? There doesn't seem to be any way to tell OpenGL the actual size of the computation. glDispatchCompute() accepts 3 numbers but none of them are the number &quot;17&quot;? &#xD;&#xA;&#xD;&#xA;Do I have to check the coordinates returned by gl_GlobalInvocationID in the shader to see if they're in range?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40579" PostHistoryTypeId="5" PostId="13455" RevisionGUID="76de7cfd-11eb-4397-9ebc-3d5d9e208af1" CreationDate="2023-05-04T13:40:41.333" UserId="7952" Comment="added 1013 characters in body" Text="If the loop is convex then one solution is to use a simple polyhedron clipping algorithm.&#xD;&#xA;&#xD;&#xA;First, Generate a non-planar polygon from the path of the loop, it sounds like this is already available. Then for each segment of the polygon define a plane that is perpendicular to the surface of the sphere and passes through the polygon segment. The normal for the plane is tangent to the sphere at that point and contains a point on the line..&#xD;&#xA;&#xD;&#xA;Using the plane, iterate over every triangle in the sphere and classify the triangles as being on the negative side of the plane (distance to plane for all vertices of the triangle are negative), the positive side of the plane (all distances are positive) or crossing the plane (some combination of positive and negative). &#xD;&#xA;&#xD;&#xA;With the plane normal computed to point inside the polygon:&#xD;&#xA;Discard triangles on the negative side, keep triangles on the positive side, and clip triangles to fit that cross.&#xD;&#xA;&#xD;&#xA;Repeat this process for every segment of the polygon.&#xD;&#xA;&#xD;&#xA;At least 1 more plane should be created that clips away the back side of the sphere. (usually just choose 3 points on the polygon then form a plane from them, and offset it by a small amount so it doesn't intersect the polygon). Create another plane offset in the opposite direction could be done to complete a convex polyhedron surrounding the region to be clipped.&#xD;&#xA;&#xD;&#xA;This is similar to how decals are generated for a polygon mesh in some algorithms.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Another way to compute the planes normal is to compute the vector from the center of the sphere to a point on the polygon segment in question. Then compute a vector for the polygon segment take the cross product and normalize. This will give you a new vector that is perpendicular to the other two. Just make sure the ordering is done correctly so that new vector point to the inside of the loop. The plane distance becomes a point on the segment being clipped. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;--- &#xD;&#xA;computing a normal to the plane using the two line segments:&#xD;&#xA;If the sphere center is $r$, the line has end points $a,b$. Then the equation becomes $pN = normalize( cross( a-r, a-b))$ and the point for the plane becomes $a$. To put the plane into the implicit form compute d with $d= dot(-pN, a)$ and the final plane becomes $[pN | d]$. To compute the distance to this plane take the 4d dot product of the point and the plane which will result in a signed distance to the plane. Where the homogenous points is of the form $(x,y,z,1)$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If the loop is not convex then a non-convex, non-planar (for polygon's that do not self intersect) polygon triangulation algorithm could be used. In this method triangulate the polygon, then align all vertices with the surface of the sphere (using a line formed between the center of the sphere and the generated point). Then tesselate to get triangle area near some preset value." ContentLicense="CC BY-SA 4.0" />
  <row Id="40580" PostHistoryTypeId="2" PostId="13458" RevisionGUID="4ca009e9-34a9-4609-923d-c5e4289112aa" CreationDate="2023-05-04T23:32:48.267" UserId="19922" Text="I am trying to write a raytracing renderer using compute shaders in Metal. My implementation is based off of Peter Shirley's Raytracing in One Weekend: https://raytracing.github.io/books/RayTracingInOneWeekend.html.&#xD;&#xA;&#xD;&#xA;When I remove the code to generate randomness in the rays, this is what I get:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Notice how the second layer of black extends all the way around the bottom sphere.&#xD;&#xA;&#xD;&#xA;When I run my own code, I get an issue where that layer of black doesn't go all the way around:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This is all my code:&#xD;&#xA;&#xD;&#xA;    class ray{&#xD;&#xA;    public:&#xD;&#xA;        float3 origin;&#xD;&#xA;        float3 direction;&#xD;&#xA;        ray(const float3 orig, const float3 dir){&#xD;&#xA;            origin = orig;&#xD;&#xA;            direction = dir;&#xD;&#xA;        }&#xD;&#xA;        ray(){&#xD;&#xA;            origin = float3(0,0,0);&#xD;&#xA;            direction = float3(0,0,0);&#xD;&#xA;        }&#xD;&#xA;        float3 rayAtPoint(float t){&#xD;&#xA;            return origin + t*direction;&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;    class camera {&#xD;&#xA;    public:&#xD;&#xA;        camera() {&#xD;&#xA;            float aspectRatio = 16.0 / 9.0;&#xD;&#xA;            float cameraHeight = 2;&#xD;&#xA;            float cameraWidth = aspectRatio * cameraHeight;&#xD;&#xA;            float focalLength = 1.0;&#xD;&#xA;            &#xD;&#xA;            origin = float3(0, 0, 0);&#xD;&#xA;            horizontal = float3(cameraWidth, 0.0, 0.0);&#xD;&#xA;            vertical = float3(0.0, cameraHeight, 0.0);&#xD;&#xA;            lower_left_corner = origin - horizontal/2 - vertical/2 - float3(0, 0, focalLength);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        ray get_ray(float u, float v){&#xD;&#xA;            return ray(origin, lower_left_corner + u*horizontal + v*vertical - origin);&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;    private:&#xD;&#xA;        float3 origin;&#xD;&#xA;        float3 lower_left_corner;&#xD;&#xA;        float3 horizontal;&#xD;&#xA;        float3 vertical;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct hit_record {&#xD;&#xA;        float3 p;&#xD;&#xA;        float3 normal;&#xD;&#xA;        float t;&#xD;&#xA;        bool front_face;&#xD;&#xA;        &#xD;&#xA;        void set_face_normal(ray r, float3 outward_normal) {&#xD;&#xA;            front_face = dot(r.direction, outward_normal) &lt; 0;&#xD;&#xA;            normal = front_face ? outward_normal :-outward_normal;&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;    struct hit_return{&#xD;&#xA;        bool hit;&#xD;&#xA;        hit_record rec;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    class sphere{&#xD;&#xA;    public:&#xD;&#xA;        sphere() {&#xD;&#xA;            exists = false;&#xD;&#xA;        }&#xD;&#xA;        sphere(float3 cen, float r){&#xD;&#xA;            exists = true;&#xD;&#xA;            center = cen;&#xD;&#xA;            radius = r;&#xD;&#xA;            &#xD;&#xA;        };&#xD;&#xA;        &#xD;&#xA;        hit_return hit(ray r, float t_min, float t_max);&#xD;&#xA;        &#xD;&#xA;    public:&#xD;&#xA;        bool exists = false;&#xD;&#xA;        float3 center;&#xD;&#xA;        float radius;&#xD;&#xA;    };&#xD;&#xA;    float rand(int x, int y, int z)&#xD;&#xA;    {&#xD;&#xA;        int seed = x + y * 57 + z * 241;&#xD;&#xA;        seed= (seed&lt;&lt; 13) ^ seed;&#xD;&#xA;        return (( 1.0 - ( (seed * (seed * seed * 15731 + 789221) + 1376312589) &amp; 2147483647) / 1073741824.0f) + 1.0f) / 2.0f;&#xD;&#xA;    }&#xD;&#xA;    int simpleRand(int x, int y, int z){&#xD;&#xA;        return ((x + y + z) % 499);&#xD;&#xA;    }&#xD;&#xA;    float random_double(float min, float max, int x, int y, int z) {&#xD;&#xA;        // Returns a random real in [min,max).&#xD;&#xA;        return min + (max-min)*rand(x, y, z);&#xD;&#xA;    }&#xD;&#xA;    float3 random_float3(int x, int y, int z){&#xD;&#xA;        return float3(rand(x,y,z), rand(y,x,z), rand(z,x,y));&#xD;&#xA;    }&#xD;&#xA;    float3 random_float3(float min, float max, int x, int y, int z){&#xD;&#xA;        return float3(random_double(min, max, x, y, z), random_double(min, max, y, z, x), random_double(min, max, x, z, y));&#xD;&#xA;    }&#xD;&#xA;    float3 random_in_unit_sphere(int x, int y, int z){&#xD;&#xA;        while (true) {&#xD;&#xA;            auto p = random_float3(-1,1, x, y, z);&#xD;&#xA;            if (length_squared(p) &gt;= 1) continue;&#xD;&#xA;            return p;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    float hash(float3 p) {&#xD;&#xA;        return fract(sin(dot(p, float3(12.9898, 78.233, 45.5432))) * 43758.5453);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float3 random_point_in_unit_sphere(float2 seed)&#xD;&#xA;    {&#xD;&#xA;        float3 p;&#xD;&#xA;        do {&#xD;&#xA;            p = 2.0 * float3(fract(sin(float(seed.x) * 143758.5453 + float(seed.y) * 182673.7123)) - 0.5,&#xD;&#xA;                             fract(sin(float(seed.x) * 832438.1234 + float(seed.y) * 934657.2374)) - 0.5,&#xD;&#xA;                             fract(sin(float(seed.x) * 321632.9187 + float(seed.y) * 642547.3216)) - 0.5);&#xD;&#xA;        } while (dot(p, p) &gt;= 1.0);&#xD;&#xA;        return normalize(p);&#xD;&#xA;    }&#xD;&#xA;    float3 randomPointInUnitSphere(float x, float y, float z) {&#xD;&#xA;        float3 point;&#xD;&#xA;        float r = rand(x, y, z); // generate random value between 0 and 1&#xD;&#xA;        float theta = rand(y, z, x) * 2.0 * M_PI; // generate random angle between 0 and 2pi&#xD;&#xA;        float phi = acos(2.0 * rand(z, x, y) - 1.0); // generate random angle between 0 and pi&#xD;&#xA;        point.x = r * sin(phi) * cos(theta);&#xD;&#xA;        point.y = r * sin(phi) * sin(theta);&#xD;&#xA;        point.z = r * cos(phi);&#xD;&#xA;        return point;&#xD;&#xA;    }&#xD;&#xA;    hit_return sphere::hit(ray r, float t_min, float t_max){&#xD;&#xA;        hit_record rec;&#xD;&#xA;        hit_return ret;&#xD;&#xA;        &#xD;&#xA;        float3 oc = r.origin - center;&#xD;&#xA;        auto a = length_squared(r.direction);&#xD;&#xA;        auto half_b = dot(oc, r.direction);&#xD;&#xA;        auto c = length_squared(oc) - radius*radius;&#xD;&#xA;        &#xD;&#xA;        &#xD;&#xA;        auto discriminant = half_b*half_b - a*c;&#xD;&#xA;        if (discriminant &lt; 0){&#xD;&#xA;            ret.hit = false;&#xD;&#xA;            return ret;&#xD;&#xA;        }&#xD;&#xA;        auto sqrtd = sqrt(discriminant);&#xD;&#xA;        &#xD;&#xA;        // Find the nearest root that lies in the acceptable range.&#xD;&#xA;        auto root = (-half_b - sqrtd) / a;&#xD;&#xA;        if (root &lt; t_min || t_max &lt; root) {&#xD;&#xA;            root = (-half_b + sqrtd) / a;&#xD;&#xA;            if (root &lt; t_min || t_max &lt; root)&#xD;&#xA;                ret.hit = false;&#xD;&#xA;                return ret;&#xD;&#xA;            &#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        rec.t = root;&#xD;&#xA;        rec.p = r.rayAtPoint(rec.t);&#xD;&#xA;        float3 outward_normal = (rec.p - center) / radius;&#xD;&#xA;        rec.set_face_normal(r, outward_normal);&#xD;&#xA;        ret.rec = rec;&#xD;&#xA;        ret.hit = true;&#xD;&#xA;        return ret;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    class hittable_list {&#xD;&#xA;    public:&#xD;&#xA;        hittable_list(){&#xD;&#xA;            maxObjects = 2;&#xD;&#xA;            objectsUpTo = 0;&#xD;&#xA;            for(int i = 0; i &lt; 100; i++){&#xD;&#xA;                exits[i] = false;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        void add(sphere object) {&#xD;&#xA;            objects[objectsUpTo] = object;&#xD;&#xA;            exits[objectsUpTo] = true;&#xD;&#xA;            objectsUpTo++;&#xD;&#xA;        }&#xD;&#xA;        &#xD;&#xA;        hit_return hit(ray r, float t_min, float t_max);&#xD;&#xA;        &#xD;&#xA;    public:&#xD;&#xA;        int    maxObjects = 2;&#xD;&#xA;        int    objectsUpTo = 0;&#xD;&#xA;        bool   exits[100];&#xD;&#xA;        sphere objects[100];&#xD;&#xA;        &#xD;&#xA;    };&#xD;&#xA;    hit_return hittable_list::hit(ray r, float t_min, float t_max) {&#xD;&#xA;        hit_record rec;&#xD;&#xA;        hit_record temp_rec;&#xD;&#xA;        hit_return temp_ret;&#xD;&#xA;        bool hit_anything = false;&#xD;&#xA;        auto closest_so_far = t_max;&#xD;&#xA;        //For some reason if I just set it to maxObjects gpu time goes up to ~25ms (~35fps)&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        &#xD;&#xA;        for (int i = 0; i &lt; 2; i++) {&#xD;&#xA;                if ((temp_ret = objects[i].hit(r, t_min, closest_so_far)).hit) {&#xD;&#xA;                    temp_rec = temp_ret.rec;&#xD;&#xA;                    hit_anything = true;&#xD;&#xA;                    closest_so_far = temp_rec.t;&#xD;&#xA;                    rec = temp_rec;&#xD;&#xA;                }&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        hit_return returnn;&#xD;&#xA;        returnn.hit = hit_anything;&#xD;&#xA;        returnn.rec = rec;&#xD;&#xA;        return returnn;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    half hit_sphere(float3 center, float radius, ray r) {&#xD;&#xA;        float3 oc = r.origin - center;&#xD;&#xA;        auto a = pow(length(r.direction),2);&#xD;&#xA;        auto half_b = dot(oc, r.direction);&#xD;&#xA;        auto c = pow(length(oc),2) - radius*radius;&#xD;&#xA;        auto discriminant = half_b*half_b - a*c;&#xD;&#xA;        if (discriminant &lt; 0) {&#xD;&#xA;            return -1.0;&#xD;&#xA;            &#xD;&#xA;        } else {&#xD;&#xA;            return (-half_b - sqrt(discriminant) ) / a;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    float3 unit_vector(float3 v){&#xD;&#xA;        return v / length(v);&#xD;&#xA;    }&#xD;&#xA;    float3 ray_color(ray r, hittable_list world, int depth, int x, int y, int z){&#xD;&#xA;        hit_return ret;&#xD;&#xA;        hit_record rec;&#xD;&#xA;        float3 finalColor = float3(0,0,0);&#xD;&#xA;        for(int i = 0; i &lt; 2; i++){&#xD;&#xA;            &#xD;&#xA;            if ((ret = world.hit(r, 0, 1000)).hit) {&#xD;&#xA;                rec = ret.rec;&#xD;&#xA;                finalColor +=  (0.5 * (rec.normal + float3(1,1,1))) / 2;&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            half3 unit_dir = half3(unit_vector(r.direction));&#xD;&#xA;            auto t = 0.5*(unit_dir.y + 1.0);&#xD;&#xA;            finalColor += (((1-t)*float3(1.0,1.0,1.0) + t*float3(0.5, 0.7, 1.0)))/2;&#xD;&#xA;        }&#xD;&#xA;        return finalColor;&#xD;&#xA;    }&#xD;&#xA;    float3 ray_color_iterative(ray r, thread hittable_list* world, int depth, int x, int y, int z, constant float3 *points){&#xD;&#xA;        ray cur_ray = r;&#xD;&#xA;        float cur_attenuation = 1.0;&#xD;&#xA;        for (int i = 0; i &lt; 5; i++){&#xD;&#xA;            hit_return ret;&#xD;&#xA;            hit_record rec;&#xD;&#xA;            if((ret = world-&gt;hit(cur_ray, 0.1, 1000)).hit){&#xD;&#xA;               rec = ret.rec;&#xD;&#xA;                float3 target = rec.p + rec.normal;&#xD;&#xA;              cur_attenuation *= 0.5;&#xD;&#xA;              cur_ray = ray(rec.p, target - rec.p);&#xD;&#xA;            }else{&#xD;&#xA;                float3 unit_direction = unit_vector(cur_ray.direction);&#xD;&#xA;                float t = 0.5 * (unit_direction.y + 1);&#xD;&#xA;                float3 c = (1.0-t)*float3(1.0, 1.0, 1.0) + t*float3(0.5, 0.7, 1.0);&#xD;&#xA;                return cur_attenuation * c;&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;        return float3(0,0,0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    kernel void raytrace(uint2 pixel [[thread_position_in_grid]],&#xD;&#xA;                         texture2d&lt;half, access::write&gt; texture [[texture(1)]],&#xD;&#xA;                         texture2d&lt;half, access::write&gt; texture2 [[texture(2)]],&#xD;&#xA;                         constant float3 *points [[buffer(1)]],&#xD;&#xA;                         constant float2 &amp;randomSeed [[buffer(2)]]){&#xD;&#xA;        &#xD;&#xA;        //Image&#xD;&#xA;        half aspectRatio = 16.0/9.0;&#xD;&#xA;        uint16_t imageWidth  = 2560;&#xD;&#xA;        uint16_t imageHeight = imageWidth / aspectRatio;&#xD;&#xA;        uint16_t samplesPerPixel = 4;&#xD;&#xA;        &#xD;&#xA;        camera cam;&#xD;&#xA;        float3 color(0,0,0);&#xD;&#xA;    &#xD;&#xA;            //Scene&#xD;&#xA;            hittable_list scene;&#xD;&#xA;            sphere s(float3(0,0,-1), 0.5);&#xD;&#xA;            sphere sTwo(float3(0,-100.5,-1), 100);&#xD;&#xA;            scene.add(s);&#xD;&#xA;            scene.add(sTwo);&#xD;&#xA;        float2 newRandomSeed = randomSeed;&#xD;&#xA;        for(int i = 0; i &lt; samplesPerPixel; i++){&#xD;&#xA;            newRandomSeed.x *= i;&#xD;&#xA;            newRandomSeed.y /= i;&#xD;&#xA;            newRandomSeed.x += pixel.x;&#xD;&#xA;            newRandomSeed.y += pixel.y;&#xD;&#xA;            float u = (half(pixel.x) + rand(i, pixel.y, pixel.x)) / (imageWidth - 1);&#xD;&#xA;            float v = (half(pixel.y) + rand(pixel.x, pixel.y, i)) / (imageHeight - 1);&#xD;&#xA;            ray r = cam.get_ray(u, v);&#xD;&#xA;            color += ray_color_iterative(r, &amp;scene, 1,  pixel.x + randomSeed.x * 2, pixel.y - randomSeed.y, i + randomSeed.y, points);&#xD;&#xA;    //&#xD;&#xA;    //&#xD;&#xA;    //&#xD;&#xA;        }&#xD;&#xA;        uint2 newPixel = uint2(pixel.x, ((pixel.y-720)*-1)+720);&#xD;&#xA;        color /= samplesPerPixel;&#xD;&#xA;        texture.write(half4(float4(color, 1)), newPixel);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Using the metal debugger, and print statements in C, I can see that the target variable is exactly the same in both my reference code and my metal code, given the same pixel, if that helps at all.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/p8np2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5zEBB.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40582" PostHistoryTypeId="1" PostId="13458" RevisionGUID="4ca009e9-34a9-4609-923d-c5e4289112aa" CreationDate="2023-05-04T23:32:48.267" UserId="19922" Text="Raytracing Diffuse Function not Working as Expected" ContentLicense="CC BY-SA 4.0" />
  <row Id="40583" PostHistoryTypeId="3" PostId="13458" RevisionGUID="4ca009e9-34a9-4609-923d-c5e4289112aa" CreationDate="2023-05-04T23:32:48.267" UserId="19922" Text="|raytracing|metal|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40585" PostHistoryTypeId="2" PostId="13459" RevisionGUID="536b2d70-fc05-4fb3-9d1f-b7a95e61954d" CreationDate="2023-05-05T07:59:36.997" UserId="19924" Text="I want to draw a circle in 3D from line segments. There are plenty of examples how to do this with an even number of subdivisions in 3D space, but I want the minimum number of subdivisions to produce a smooth circle after projection, without under- or over-subdividing. So a small circle (after projection) should require few subdivisions, a large circle should require more.&#xD;&#xA;&#xD;&#xA;I could just calculate a fixed subdivision based on camera field-of-view and screen resolution, but that will only be correct for circles directly facing the camera.&#xD;&#xA;&#xD;&#xA;Before I dig into the maths to figure this out I want to ask if there is already a well-known solution to this, because searches didn't come up with anything useful so far.&#xD;&#xA;&#xD;&#xA;I have the feeling this is either solvable by stepping around the conic section projection of the circle in screen space, or by adjusting the step size based on the projection matrix." ContentLicense="CC BY-SA 4.0" />
  <row Id="40587" PostHistoryTypeId="1" PostId="13459" RevisionGUID="536b2d70-fc05-4fb3-9d1f-b7a95e61954d" CreationDate="2023-05-05T07:59:36.997" UserId="19924" Text="How do I evenly subdivide the projection of a circle in 3D?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40588" PostHistoryTypeId="3" PostId="13459" RevisionGUID="536b2d70-fc05-4fb3-9d1f-b7a95e61954d" CreationDate="2023-05-05T07:59:36.997" UserId="19924" Text="|projections|subdivision|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40589" PostHistoryTypeId="2" PostId="13460" RevisionGUID="e9cdc127-f586-4dc5-a097-461b445ed479" CreationDate="2023-05-05T08:33:21.800" UserDisplayName="user1703" Text="What you are after is a curve flattening, i.e. turning a curve (an ellipse in your case) into a polyline.&#xD;&#xA;&#xD;&#xA;This can be done by recursive subdivision: for a given arc of the curve, estimate the deviation from the line segment that joins the endpoints. If the deviation exceeds a visual threshold (a fraction of a pixel), split the arc in two subarcs and recurse.&#xD;&#xA;&#xD;&#xA;A gross estimate of the deviation is obtained by just taking the distance of some intermediate point of the arc to the segment. This is inaccurate when the deviation is large, but quite sufficient for small deviations.&#xD;&#xA;&#xD;&#xA;The method is suboptimal but easy and effective. It will not only adjust the point density for small vs. large circles, but also finely adjust as a function of local curvature. Needless to say, the flattening is completely viewpoint-dependent.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40591" PostHistoryTypeId="5" PostId="13460" RevisionGUID="80a74cf1-17b4-4d00-bdc1-a30a1c793383" CreationDate="2023-05-05T08:38:27.443" UserDisplayName="user1703" Comment="added 54 characters in body" Text="What you are after is a curve flattening, i.e. turning a curve (an ellipse in your case) into a polyline, in such a way that the discretization is not visible.&#xD;&#xA;&#xD;&#xA;This can be done by recursive subdivision: for a given arc of the curve, estimate the deviation from the line segment that joins the endpoints. If the deviation exceeds a visual threshold (a fraction of a pixel), split the arc in two subarcs and recurse.&#xD;&#xA;&#xD;&#xA;A gross estimate of the deviation is obtained by just taking the distance of some intermediate point of the arc to the segment. This is inaccurate when the deviation is large, but quite sufficient for small deviations.&#xD;&#xA;&#xD;&#xA;The method is suboptimal but easy and effective. It will not only adjust the point density for small vs. large circles, but also finely adjust as a function of local curvature. Needless to say, the flattening is completely viewpoint-dependent.&#xD;&#xA;&#xD;&#xA;Also note that you needn't compute the equation of the ellipse." ContentLicense="CC BY-SA 4.0" />
  <row Id="40592" PostHistoryTypeId="2" PostId="13461" RevisionGUID="953ab9c5-7abc-4241-aeb7-87695b96455c" CreationDate="2023-05-05T09:20:46.930" UserId="13273" Text="When doing it inside shader stages, one possibility is the following using vertex- and  tessellation-shader (only one triangle (3 lines) are needed):&#xD;&#xA;&#xD;&#xA;Within the vertex shader you can calculate the NDC by the following code:&#xD;&#xA;&#xD;&#xA;    vec4 NDC = mvp_matrix * vertexPosition;&#xD;&#xA;    NDC = NDC / NDC.a;&#xD;&#xA;&#xD;&#xA;The NDC coordinate need to be handled over to the tessellation-control shader. There you can check, how far are the two connected vertices away from each other. Only test the x/y coordinates, because we want to know the distance of the pixels.&#xD;&#xA;&#xD;&#xA;    vec2 len = abs(NDC[0].xy - NDC[1].xy);&#xD;&#xA;&#xD;&#xA;Finally, the screen resolution must be taken into account:&#xD;&#xA;&#xD;&#xA;    float numberOfDivisions = length(len * 2 * screenResolution); // the multiplication by 2 is required, because NDC range in x/y dimension is [-1, 1].&#xD;&#xA;&#xD;&#xA;**Pro:** &#xD;&#xA;&#xD;&#xA; 1. No vertex buffer object is needed... you can execute the shader for a minimum of three lines.&#xD;&#xA; 2. No uploading of vertex data. So except the draw command there is no CPU-&gt;GPU communication.&#xD;&#xA;&#xD;&#xA;**Contra:**&#xD;&#xA;&#xD;&#xA; 1. In case the circle lies partly outside the view frustum or partly behind the camera, the output will be not like expected. So you need to do some clipping before.&#xD;&#xA; 2. when having high screen resolution, the input of only 3 lines (1 triangle) can be not enough, because the maximum subdivision of the tessellation stage can be too poor." ContentLicense="CC BY-SA 4.0" />
  <row Id="40594" PostHistoryTypeId="2" PostId="13462" RevisionGUID="63873f2f-2c4e-46bf-a479-7beceb943997" CreationDate="2023-05-05T09:54:17.233" UserId="9036" Text="Short answer: Yes I have to check the coordinates.&#xD;&#xA;&#xD;&#xA;If I set a 16x16x1 local size then use it to process a 17x17 image I have to use glDispatchCompute(2,2,1).&#xD;&#xA;&#xD;&#xA;This generates four workgoups with size 16x16 even though the blocks to be processed have sizes 16x16, 16x1, 1x16 and 1x1&#xD;&#xA;&#xD;&#xA;Inside the shader I have to check the range of the xy coordinates to make sure I don't do an imageStore() outside the image.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40596" PostHistoryTypeId="5" PostId="13461" RevisionGUID="1308a197-62bf-45fc-b2a8-f5ddb54e9fd9" CreationDate="2023-05-05T10:11:01.483" UserId="13273" Comment="added 4 characters in body" Text="When doing it inside shader stages, one possibility is the following using vertex- and  tessellation-shader (only one triangle (3 lines) are needed):&#xD;&#xA;&#xD;&#xA;Within the vertex shader you can calculate the NDC by the following code:&#xD;&#xA;&#xD;&#xA;    vec4 NDC = mvp_matrix * vertexPosition;&#xD;&#xA;    NDC = NDC / NDC.a;&#xD;&#xA;&#xD;&#xA;The NDC coordinate need to be handled over to the tessellation-control shader. There you can check, how far are the two connected vertices away from each other. Only test the x/y coordinates, because we want to know the distance of the pixels.&#xD;&#xA;&#xD;&#xA;    vec2 len = abs(NDC[0].xy - NDC[1].xy);&#xD;&#xA;&#xD;&#xA;Finally, the screen resolution must be taken into account:&#xD;&#xA;&#xD;&#xA;    float numberOfDivisions = length(len * 0.5 * screenResolution); // the multiplication by 0.5 is required, because NDC range in x/y dimension is [-1, 1].&#xD;&#xA;&#xD;&#xA;**Pro:** &#xD;&#xA;&#xD;&#xA; 1. No vertex buffer object is needed... you can execute the shader for a minimum of three lines.&#xD;&#xA; 2. No uploading of vertex data. So except the draw command there is no CPU-&gt;GPU communication.&#xD;&#xA;&#xD;&#xA;**Contra:**&#xD;&#xA;&#xD;&#xA; 1. In case the circle lies partly outside the view frustum or partly behind the camera, the output will be not like expected. So you need to do some clipping before.&#xD;&#xA; 2. when having high screen resolution, the input of only 3 lines (1 triangle) can be not enough, because the maximum subdivision of the tessellation stage can be too poor." ContentLicense="CC BY-SA 4.0" />
  <row Id="40597" PostHistoryTypeId="52" PostId="13459" RevisionGUID="5fb6497c-c9ea-4f59-864e-9a2045c38787" CreationDate="2023-05-05T16:05:37.373" />
  <row Id="40598" PostHistoryTypeId="2" PostId="13463" RevisionGUID="bc78a379-d7b4-4cc6-ab8d-c65f9e0a3109" CreationDate="2023-05-05T19:50:27.703" UserId="19926" Text="![Text](https://i.gyazo.com/433790846f85cd7389f6c82e7cb111ea.png)&#xD;&#xA;&#xD;&#xA;The above problem is from a past Computer Graphics exam.&#xD;&#xA;&#xD;&#xA;I am particularly confused about the explanation given, firstly for the top and bottom planes (since the direction of normal for top plane seems to be opposite the direction of I) &#xD;&#xA;&#xD;&#xA;I tried to calculate the normal vectors, for the top plane for instance, by choosing two arbitrary points on the top plane ([1,1,1] and [0,1,0]), subtracting the two point vectors to get the vector lying across the plane. I then used the fact that the normal vector dot product with the vector lying across the plane equals zero to get a linear equation of the plane in the form Ax + By + Cz = 0, and used that to try to find the normal vector from the A,B,C components to multiply by the unit vector to yield the normal vector. This seems to be incorrect to me since it gave a normal vector defined as (1,0,1), which intuitively seems incorrect.&#xD;&#xA;&#xD;&#xA;I do intuitively understand that the normal vector from the top plane will be positive in the y axis, and the normal vector from the bottom plane will be negative in the y axis. I can also see that a vector in the positive y axis would go towards the magenta light source so the plane that defines that normal vector would be illuminated. I do not understand how the specific values were computed.&#xD;&#xA;&#xD;&#xA;If possible, an explanation of how they obtained values for the top plane, bottom plane, and 4 other planes would be appreciated. Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="40600" PostHistoryTypeId="1" PostId="13463" RevisionGUID="bc78a379-d7b4-4cc6-ab8d-c65f9e0a3109" CreationDate="2023-05-05T19:50:27.703" UserId="19926" Text="With a light source at (0,2,0) and unit cube (from [-1,1]) using a given shading formula, how is the r,g,b for each surface calculated?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40601" PostHistoryTypeId="3" PostId="13463" RevisionGUID="bc78a379-d7b4-4cc6-ab8d-c65f9e0a3109" CreationDate="2023-05-05T19:50:27.703" UserId="19926" Text="|rendering|mathematics|lighting|color|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40602" PostHistoryTypeId="2" PostId="13464" RevisionGUID="7705b2e5-fa3b-40f3-890d-e25c5fe23035" CreationDate="2023-05-05T21:42:30.180" UserId="19927" Text="So I just saw a video on [Marching Squares][1] by reducible, and I thought of a straightforward optimisation, but I couldn't find anything about it online. Basically here's the idea -  &#xD;&#xA;Start with a fairly large grid size, sample the points, this forms a very rough image, but what we do now is only for the cells which the contour passes through, we further divide them into more cells recursively (make the grid smaller but only inside those cells) and sample more points until a set recursion depth. For example turning a single cell into 4 different cells only require you to sample an additional 5 points&#xD;&#xA;This should give us a much sharper image without having to sample too many points, most of which give us no information.&#xD;&#xA;&#xD;&#xA;This came pretty naturally to me so I refuse to believe that no one else has thought of this, so is there any particular reason why I wasn't able to find anything about it?&#xD;&#xA;(Maybe it has some fault I don't see, or maybe there's a better optimisation, or maybe it just has a different name I don't know) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://youtu.be/6oMZb3yP_H8" ContentLicense="CC BY-SA 4.0" />
  <row Id="40604" PostHistoryTypeId="1" PostId="13464" RevisionGUID="7705b2e5-fa3b-40f3-890d-e25c5fe23035" CreationDate="2023-05-05T21:42:30.180" UserId="19927" Text="Recursive sampling in Marching Squares" ContentLicense="CC BY-SA 4.0" />
  <row Id="40605" PostHistoryTypeId="3" PostId="13464" RevisionGUID="7705b2e5-fa3b-40f3-890d-e25c5fe23035" CreationDate="2023-05-05T21:42:30.180" UserId="19927" Text="|2d-graphics|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40610" PostHistoryTypeId="2" PostId="13465" RevisionGUID="831f6cca-1da0-4232-8d35-b8345d4a3312" CreationDate="2023-05-06T05:32:36.317" UserId="445" Text="If the contour exists in a loop _entirely inside one of your coarse cells_ — or has some thin protrusion that passes between the corner points, at least — then it will be missed entirely; it will look just like empty space in that cell. This puts a limit on how large your initial grid can be: it must be fine enough that at least one point lies within and one point outside the contour.&#xD;&#xA;&#xD;&#xA;Now, if you know that _there must be at least one loop within a region_ then you can sample finer until you find it. But then you've given up on “plot any implicit curve”, because you need to know where to look.&#xD;&#xA;&#xD;&#xA;This doesn't mean there isn't any point in multiple resolutions. Once a grid of a certain resolution has found the features of the shape (as many as are coarse enough for it to notice), you can sample more finely to get _more smoothly curved_ lines/surfaces." ContentLicense="CC BY-SA 4.0" />
  <row Id="40612" PostHistoryTypeId="2" PostId="13466" RevisionGUID="200c7eaa-a5f9-4e5f-bda9-6fd8150740cc" CreationDate="2023-05-06T11:19:02.347" UserId="13273" Text="First of all, it is obvious that the normal vector of the upper surface is $(0,1,0)$. But you can calculate it in the following way:&#xD;&#xA;&#xD;&#xA;Given three points on a surface that are not aligned, you can calculate the normal direction. A very simple way is to use the cross product &#xD;&#xA;$n = |(p0 - p1)$ x $(p0 - p2)|$ . With this formula you have to be careful which points you choose for $p0$, $p1$ and $p2$, because the cross product gives the orthogonal direction of the two input vectors according to the right-hand rule.&#xD;&#xA;&#xD;&#xA;What is the right hand rule? &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Copied from [Wikipedia][2]. Shows how to easily remember the direction of the result of a cross product. (according to the right hand rule (Do **NOT** use the left hand ;P )&#xD;&#xA;&#xD;&#xA;So the result of $a$ x $b$ is not the same as $b$ x $a$. So the cross product is not commutative! When calculating the normal vector, this should be taken into account! The length of the result of the cross product must be normalized.&#xD;&#xA;&#xD;&#xA;Once we have the normal vectors of all 6 surfaces, we can proceed with the formula.&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * I + 1}{3} * (1,0,1) + \frac{1-n(x)*I}{3} * (1,1,1)$$&#xD;&#xA;We also know the value of $I = (0,1,0)$ (the direction vectors are normalized). So if we substitute $I$ into the equation, we get:&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-n(x)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;&#xD;&#xA;**Lets start with the top face:**&#xD;&#xA;$$n = (0,1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,1,0)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;because $n(x)*I$ is the dot product, we can shorten the equation:&#xD;&#xA;$$I_{RGB}(x) = \frac{2 + 1}{3} * (1,0,1) + \frac{1-1}{3} * (1,1,1)$$&#xD;&#xA;$$= 1 * (1,0,1) + 0 * (1,1,1)$$&#xD;&#xA;$$= (1,0,1)$$&#xD;&#xA;$(1,0,1)$ as RGB value is pure magenta.&#xD;&#xA;&#xD;&#xA;**Lets continue with the bottom face:**&#xD;&#xA;$$n = (0,-1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,-1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,-1,0)*(0,1,0)}{3}*(1,1,1)$$&#xD;&#xA;Lets shorten it like above, gives you:&#xD;&#xA;$$I_{RGB}(x) = \frac{-2 + 1}{3} * (1,0,1) + \frac{1-(-1)}{3}*(1,1,1)$$&#xD;&#xA;$$= (-\frac{1}{3},0,-\frac{1}{3}) + (\frac{2}{3},\frac{2}{3},\frac{2}{3})$$&#xD;&#xA;$$= (\frac{1}{3},\frac{2}{3},\frac{1}{3})$$&#xD;&#xA;&#xD;&#xA;I'll stop here, for the other 4 faces it works the same way...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDvch.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cross_product" ContentLicense="CC BY-SA 4.0" />
  <row Id="40614" PostHistoryTypeId="5" PostId="13466" RevisionGUID="012de209-3398-47d1-91da-9342821ddeec" CreationDate="2023-05-06T11:28:42.983" UserId="13273" Comment="added 43 characters in body" Text="First of all, it is obvious that the normal vector of the upper surface is $(0,1,0)$. But you can calculate it in the following way:&#xD;&#xA;&#xD;&#xA;Given three points on a surface that are not aligned, you can calculate the normal direction. A very simple way is to use the cross product &#xD;&#xA;$n = |(p0 - p1)$ x $(p0 - p2)|$ . With this formula you have to be careful which points you choose for $p0$, $p1$ and $p2$, because the cross product gives the orthogonal direction of the two input vectors according to the right-hand rule.&#xD;&#xA;&#xD;&#xA;What is the right hand rule? &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Copied from [Wikipedia][2]. Shows how to easily remember the direction of the result of a cross product. (according to the right hand rule (Do **NOT** use the left hand ;P )&#xD;&#xA;&#xD;&#xA;So the result of $a$ x $b$ is not the same as $b$ x $a$. So the cross product is not commutative! When calculating the normal vector, this should be taken into account! The length of the result of the cross product must be normalized.&#xD;&#xA;&#xD;&#xA;Once we have the normal vectors of all 6 surfaces, we can proceed with the formula.&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * I + 1}{3} * (1,0,1) + \frac{1-n(x)*I}{3} * (1,1,1)$$&#xD;&#xA;We also know the value of $I = (0,1,0)$ (where, $I$: the unit light source direction,) (direction vectors are normalized). So if we substitute $I$ into the equation, we get:&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-n(x)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;&#xD;&#xA;**Lets start with the top face:**&#xD;&#xA;$$n = (0,1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,1,0)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;because $n(x)*I$ is the dot product, we can shorten the equation:&#xD;&#xA;$$I_{RGB}(x) = \frac{2 + 1}{3} * (1,0,1) + \frac{1-1}{3} * (1,1,1)$$&#xD;&#xA;$$= 1 * (1,0,1) + 0 * (1,1,1)$$&#xD;&#xA;$$= (1,0,1)$$&#xD;&#xA;$(1,0,1)$ as RGB value is pure magenta.&#xD;&#xA;&#xD;&#xA;**Lets continue with the bottom face:**&#xD;&#xA;$$n = (0,-1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,-1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,-1,0)*(0,1,0)}{3}*(1,1,1)$$&#xD;&#xA;Lets shorten it like above, gives you:&#xD;&#xA;$$I_{RGB}(x) = \frac{-2 + 1}{3} * (1,0,1) + \frac{1-(-1)}{3}*(1,1,1)$$&#xD;&#xA;$$= (-\frac{1}{3},0,-\frac{1}{3}) + (\frac{2}{3},\frac{2}{3},\frac{2}{3})$$&#xD;&#xA;$$= (\frac{1}{3},\frac{2}{3},\frac{1}{3})$$&#xD;&#xA;&#xD;&#xA;I'll stop here, for the other 4 faces it works the same way...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDvch.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cross_product" ContentLicense="CC BY-SA 4.0" />
  <row Id="40615" PostHistoryTypeId="5" PostId="13466" RevisionGUID="8142f997-5ef4-45ac-b8a6-e7f86bfe83d5" CreationDate="2023-05-06T11:44:41.510" UserId="13273" Comment="added 428 characters in body" Text="First of all, it is obvious that the normal vector of the upper surface is $(0,1,0)$. But you can calculate it in the following way:&#xD;&#xA;&#xD;&#xA;Given three points on a surface that are not aligned, you can calculate the normal direction. A very simple way is to use the cross product &#xD;&#xA;$n = |(p1 - p0)$ x $(p2 - p0)|$ . With this formula you have to be careful which points you choose for $p0$, $p1$ and $p2$, because the cross product gives the orthogonal direction of the two input vectors according to the right-hand rule.&#xD;&#xA;&#xD;&#xA;What is the right hand rule? &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Copied from [Wikipedia][2]. Shows how to easily remember the direction of the result of a cross product. (according to the right hand rule (Do **NOT** use the left hand ;P ))&#xD;&#xA;&#xD;&#xA;So the result of $a$ x $b$ is not the same as $b$ x $a$. So the cross product is not commutative! When calculating the normal vector, this should be taken into account! The length of the result of the cross product must be normalized.&#xD;&#xA;&#xD;&#xA;Once we have the normal vectors of all 6 surfaces, we can proceed with the formula.&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * I + 1}{3} * (1,0,1) + \frac{1-n(x)*I}{3} * (1,1,1)$$&#xD;&#xA;We also know the value of $I = (0,1,0)$ (where, $I$: the **unit** light source direction,) (so this vectors is normalized). So if we substitute $I$ into the equation, we get:&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-n(x)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;&#xD;&#xA;**Lets start with the top face:**&#xD;&#xA;$$n = (0,1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,1,0)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;because $n(x)*I$ is the dot product, we can shorten the equation:&#xD;&#xA;$$I_{RGB}(x) = \frac{2 + 1}{3} * (1,0,1) + \frac{1-1}{3} * (1,1,1)$$&#xD;&#xA;$$= 1 * (1,0,1) + 0 * (1,1,1)$$&#xD;&#xA;$$= (1,0,1)$$&#xD;&#xA;$(1,0,1)$ as RGB value is pure magenta.&#xD;&#xA;&#xD;&#xA;**Lets continue with the bottom face:**&#xD;&#xA;$$n = (0,-1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,-1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,-1,0)*(0,1,0)}{3}*(1,1,1)$$&#xD;&#xA;Lets shorten it like above, gives you:&#xD;&#xA;$$I_{RGB}(x) = \frac{-2 + 1}{3} * (1,0,1) + \frac{1-(-1)}{3}*(1,1,1)$$&#xD;&#xA;$$= (-\frac{1}{3},0,-\frac{1}{3}) + (\frac{2}{3},\frac{2}{3},\frac{2}{3})$$&#xD;&#xA;$$= (\frac{1}{3},\frac{2}{3},\frac{1}{3})$$&#xD;&#xA;&#xD;&#xA;**Lets continue with the front face:**&#xD;&#xA;$$n = (0,0,1)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,0,1) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,0,1)*(0,1,0)}{3}*(1,1,1)$$&#xD;&#xA;Lets shorten it like above, gives you:&#xD;&#xA;$$I_{RGB}(x) = \frac{0 + 1}{3} * (1,0,1) + \frac{1-0}{3}*(1,1,1)$$&#xD;&#xA;$$= (\frac{1}{3},0,\frac{1}{3}) + (\frac{1}{3},\frac{1}{3},\frac{1}{3})$$&#xD;&#xA;$$= (\frac{2}{3},\frac{1}{3},\frac{2}{3})$$&#xD;&#xA;&#xD;&#xA;I'll stop here, for the other 3 faces it works the same way...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDvch.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cross_product" ContentLicense="CC BY-SA 4.0" />
  <row Id="40616" PostHistoryTypeId="50" PostId="12602" RevisionGUID="ea4cc8a3-2b4c-427f-b484-32d6408d8a79" CreationDate="2023-05-06T21:06:25.733" UserId="-1" />
  <row Id="40617" PostHistoryTypeId="50" PostId="12609" RevisionGUID="1f2458b9-063f-462d-a844-f3754847e4fc" CreationDate="2023-05-07T04:06:55.960" UserId="-1" />
  <row Id="40619" PostHistoryTypeId="5" PostId="13466" RevisionGUID="6ebf578b-9bfe-4073-9f5a-0363693c3fea" CreationDate="2023-05-07T07:34:50.507" UserId="13273" Comment="added 594 characters in body" Text="First of all, it is obvious that the normal vector of the upper surface is $(0,1,0)$. But you can calculate it in the following way:&#xD;&#xA;&#xD;&#xA;Given three points on a surface that are not aligned, you can calculate the normal direction. A very simple way is to use the cross product &#xD;&#xA;$n = |(p1 - p0)$ x $(p2 - p0)|$ . With this formula you have to be careful which points you choose for $p0$, $p1$ and $p2$, because the cross product gives the orthogonal direction of the two input vectors according to the right-hand rule.&#xD;&#xA;&#xD;&#xA;What is the right hand rule? &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Copied from [Wikipedia][2]. Shows how to easily remember the direction of the result of a cross product. (according to the right hand rule (Do **NOT** use the left hand ;P ))&#xD;&#xA;&#xD;&#xA;So the result of $a$ x $b$ is not the same as $b$ x $a$. So the cross product is not commutative! When calculating the normal vector, this should be taken into account! The length of the result of the cross product must be normalized.&#xD;&#xA;&#xD;&#xA;Once we have the normal vectors of all 6 surfaces, we can proceed with the formula.&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * I + 1}{3} * (1,0,1) + \frac{1-n(x)*I}{3} * (1,1,1)$$&#xD;&#xA;The question of the professor is not well defined, because the light source direction vary depending on the position of the point on surface... I would expect a well divined question from a university... The question could be defined when saying: the light source is infinity far away, which leeds to a directional light source. Or in case inside the course you only talked about directional light sources, they need to define the light cast direction. But when looking at the answer of the professor we see, that he/she expect you to use the direction of: $|lightPosition - centerCube|$. Therefore we know the value of $I = (0,1,0)$ (where, $I$: the **unit** light source direction,) (so this vectors is normalized). So if we substitute $I$ into the equation, we get:&#xD;&#xA;$$I_{RGB}(x) = \frac{2n(x) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-n(x)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;&#xD;&#xA;**Lets start with the top face:**&#xD;&#xA;$$n = (0,1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,1,0)*(0,1,0)}{3} * (1,1,1)$$&#xD;&#xA;because $n(x)*I$ is the dot product, we can shorten the equation:&#xD;&#xA;$$I_{RGB}(x) = \frac{2 + 1}{3} * (1,0,1) + \frac{1-1}{3} * (1,1,1)$$&#xD;&#xA;$$= 1 * (1,0,1) + 0 * (1,1,1)$$&#xD;&#xA;$$= (1,0,1)$$&#xD;&#xA;$(1,0,1)$ as RGB value is pure magenta.&#xD;&#xA;&#xD;&#xA;**Lets continue with the bottom face:**&#xD;&#xA;$$n = (0,-1,0)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,-1,0) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,-1,0)*(0,1,0)}{3}*(1,1,1)$$&#xD;&#xA;Lets shorten it like above, gives you:&#xD;&#xA;$$I_{RGB}(x) = \frac{-2 + 1}{3} * (1,0,1) + \frac{1-(-1)}{3}*(1,1,1)$$&#xD;&#xA;$$= (-\frac{1}{3},0,-\frac{1}{3}) + (\frac{2}{3},\frac{2}{3},\frac{2}{3})$$&#xD;&#xA;$$= (\frac{1}{3},\frac{2}{3},\frac{1}{3})$$&#xD;&#xA;&#xD;&#xA;**Lets continue with the front face:**&#xD;&#xA;$$n = (0,0,1)$$&#xD;&#xA;So placing the vector into the formular:&#xD;&#xA;$$I_{RGB}(x) = \frac{2(0,0,1) * (0,1,0) + 1}{3} * (1,0,1) + \frac{1-(0,0,1)*(0,1,0)}{3}*(1,1,1)$$&#xD;&#xA;Lets shorten it like above, gives you:&#xD;&#xA;$$I_{RGB}(x) = \frac{0 + 1}{3} * (1,0,1) + \frac{1-0}{3}*(1,1,1)$$&#xD;&#xA;$$= (\frac{1}{3},0,\frac{1}{3}) + (\frac{1}{3},\frac{1}{3},\frac{1}{3})$$&#xD;&#xA;$$= (\frac{2}{3},\frac{1}{3},\frac{2}{3})$$&#xD;&#xA;&#xD;&#xA;I'll stop here, for the other 3 faces it works the same way...&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RDvch.png&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Cross_product" ContentLicense="CC BY-SA 4.0" />
  <row Id="40625" PostHistoryTypeId="2" PostId="13468" RevisionGUID="d69f0169-3e17-412e-88ab-1a13e29f6fdf" CreationDate="2023-05-08T14:57:14.743" UserId="9036" Text="A question for the OpenGL spec lawyers:&#xD;&#xA;&#xD;&#xA;Imagine I have two uncompressed, 2D textures A and B with identical sizes and formats. I bind A to texture unit 0, and B to a framebuffer object.&#xD;&#xA;&#xD;&#xA;If I draw a full-size polygon in that framebuffer with this pixel shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D iChannel0;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;       fragColor = texelFetch(iChannel0, gl_FragCoord.xy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this guaranteed to make a perfect copy of texture A? &#xD;&#xA;&#xD;&#xA;ie. Will gl_FragCoord.xy give good numbers that map every input texel to every output texel? Will there be any filtering or clamping applied to the texels?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40627" PostHistoryTypeId="1" PostId="13468" RevisionGUID="d69f0169-3e17-412e-88ab-1a13e29f6fdf" CreationDate="2023-05-08T14:57:14.743" UserId="9036" Text="Can I copy one texture to another perfectly with texelFetch()" ContentLicense="CC BY-SA 4.0" />
  <row Id="40628" PostHistoryTypeId="3" PostId="13468" RevisionGUID="d69f0169-3e17-412e-88ab-1a13e29f6fdf" CreationDate="2023-05-08T14:57:14.743" UserId="9036" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40629" PostHistoryTypeId="5" PostId="13468" RevisionGUID="74fe28f6-4b73-4e1a-bb2a-ec5c5b4f015d" CreationDate="2023-05-08T18:39:41.003" UserId="7952" Comment="removed offensive comment" Text="&#xD;&#xA;&#xD;&#xA;Imagine I have two uncompressed, 2D textures A and B with identical sizes and formats. I bind A to texture unit 0, and B to a framebuffer object.&#xD;&#xA;&#xD;&#xA;If I draw a full-size polygon in that framebuffer with this pixel shader:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    uniform sampler2D iChannel0;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;       fragColor = texelFetch(iChannel0, gl_FragCoord.xy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this guaranteed to make a perfect copy of texture A? &#xD;&#xA;&#xD;&#xA;ie. Will gl_FragCoord.xy give good numbers that map every input texel to every output texel? Will there be any filtering or clamping applied to the texels?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40630" PostHistoryTypeId="2" PostId="13469" RevisionGUID="689aee62-1a4e-4488-90d6-ee88ea39d6e5" CreationDate="2023-05-08T20:35:36.853" UserId="19941" Text="Here is a paragraph of Shreiner and Angel's _Interactive Computer Graphics_:&#xD;&#xA;&#xD;&#xA;&quot;_Early graphics systems used general-purpose computers with the standard von&#xD;&#xA;Neumann architecture. Such computers are characterized by a single processing unit&#xD;&#xA;that processes a single instruction at a time. A simple model of these early graphics&#xD;&#xA;systems is shown in Figure 1.35. The display in these systems was based on a calligraphic CRT display that included the necessary circuitry to generate a line segment&#xD;&#xA;connecting two points. The job of the host computer was to run the application program and to compute the endpoints of the line segments in the image (in units of the&#xD;&#xA;display). This information had to be sent to the display at a rate high enough to avoid flicker on the display. In the early days of computer graphics, computers were so slow&#xD;&#xA;that refreshing even simple images, containing a few hundred line segments, would&#xD;&#xA;burden an expensive computer._&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I often struggle to understand explanations that are not 'pedantically rigorous'. I believe I would better understand the paragraph in question if I was given a detailed example so as to appreciate _exactly_ how the CRT display functions. &#xD;&#xA;&#xD;&#xA;**Could someone provide, or point me in the direction of, a step-by-step algorithm or drawn circuitry that meticulously shows how an instruction from the host is turned into a displayed image in a screen?**&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zjjAE.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40632" PostHistoryTypeId="1" PostId="13469" RevisionGUID="689aee62-1a4e-4488-90d6-ee88ea39d6e5" CreationDate="2023-05-08T20:35:36.853" UserId="19941" Text="Rigorous example of early graphics system" ContentLicense="CC BY-SA 4.0" />
  <row Id="40633" PostHistoryTypeId="3" PostId="13469" RevisionGUID="689aee62-1a4e-4488-90d6-ee88ea39d6e5" CreationDate="2023-05-08T20:35:36.853" UserId="19941" Text="|2d-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40634" PostHistoryTypeId="2" PostId="13470" RevisionGUID="549fe18b-0b7d-42c4-b704-aca6ff1a15bc" CreationDate="2023-05-09T02:20:29.083" UserId="445" Text="First of all, the type of system they describe is more commonly known today as a [vector display](https://en.wikipedia.org/wiki/Vector_monitor). (Until just now, I had never heard it called “calligraphic”.) Looking up information using that name may get you more useful context.&#xD;&#xA;&#xD;&#xA;Now as to the principle of operation:&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The __hardware__ may be extremely simple. You need:&#xD;&#xA;&#xD;&#xA;1. Two digital-to-analog converters (DACs), one for X position and one for Y position.&#xD;&#xA;2. Two amplifiers of an appropriate type to take those signals to...&#xD;&#xA;3. The deflection plates or coils of a CRT.&#xD;&#xA;&#xD;&#xA;That's all you need for the fundamental system. Then, to produce a cleaner image, you can optionally add a 3rd digital signal which allows the computer to turn on and off the CRT's beam, or an analog signal to control its brightness.&#xD;&#xA;&#xD;&#xA;Now, in order to draw a line, the **software** will send a series of samples to the DACs, instructing them to change their output analog signals linearly over a short time period. This causes the CRT to sweep the beam across the screen, exciting the phosphor **in the shape of a line**. Similarly, arbitrary curves can be drawn as long as the computer can calculate a finely-spaced series of points along them.&#xD;&#xA;&#xD;&#xA;In order to draw disconnected shapes, you turn off the beam (“blank” it) while you are moving it to the end point of one line to the start point of the new line. (Or, in a simpler system with no blanking, you can move the beam so fast that no visible line is produced — the brightness is inversely proportional to the speed, since the electron gun is firing electrons at the screen at a rate independent of how fast the beam deflection changes. However, this approach is constrained by the bandwidth and/or sample rate of the system.)&#xD;&#xA;&#xD;&#xA;Then, in order to keep the image on screen, or animate it, you repeat this entire process, drawing the scene over and over again (just like raster CRTs did). Between drawing cycles, the image is maintained by some combination of the phosphor's glow (it does not darken instantly when the beam leaves, but continues emitting light) and [flicker fusion](https://en.wikipedia.org/wiki/Flicker_fusion_threshold), also known as “persistence of vision”, in the human eye.&#xD;&#xA;&#xD;&#xA;The faster the computer can control the DACs, the more content you can put on the screen before the overall frame rate becomes low enough that flicker is perceived. (Note that it would be possible to have dedicated “video memory” containing the stream of X-Y points to send to the DACs, without involving the computer's processor except when it wanted to change the data. I don't know how many of the original vector display systems used such a system, if any of them did; I'm familiar with the theory, not the history.)&#xD;&#xA;&#xD;&#xA;So, in a sense, the algorithm and the circuitry are extremely simple. The computer is commanding a moving spot of light. Everything else is the details of how to cause this spot to make a picture.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**You can actually experience CRT vector graphics today,** at not too much expense; if you are interested in the field, I recommend trying, as it is an experience that **cannot be accurately reproduced in video** or on a modern monitor (due to the dynamic range of possible intensities and the lack of a mandatory frame rate). All you need is a traditional CRT [oscilloscope](https://en.wikipedia.org/wiki/Oscilloscope). These are no longer made, but, unlike vector monitors, plenty of them are available used. (A modern digital oscilloscope can show the shapes but cannot produce the same specific effects since it is using an LCD monitor just like your computer.)&#xD;&#xA;&#xD;&#xA;When placed into “X-Y” mode, an oscilloscope becomes parts (2) and (3) of the hardware system I described above; the signals provided via two input connectors are amplified and sent to the deflection plates of the CRT, unmodified.&#xD;&#xA;&#xD;&#xA;Then, you need two DAC channels. Where can you find them? In your computer's stereo audio output! Ideally, you want a “DC coupled” output (lack of a high-pass filter a.k.a. coupling capacitor) for a stably positioned image, but it will still work for a visible image even without.&#xD;&#xA;&#xD;&#xA;Simply obtain or make adapters to connect your audio output left and right channels to the X and Y inputs of the oscilloscope, and you're all set.&#xD;&#xA;&#xD;&#xA;To get “audio” data you can play to produce an image, look for the niche hobby of “oscilloscope music”, as popularized by [Jerobeam Fenderson](https://oscilloscopemusic.com/) with his album of the same name. Setup advice and more links can be found at [the subreddit](https://www.reddit.com/r/oscilloscopemusic/); an easy source of freely downloadable files is [C. Allen's work](https://www.youtube.com/playlist?list=PLc4EnsriUcfQPomSF3Eh6sB143HE2r0tf); each video has a link to download the `.wav` file. To reproduce the images you must download and play the original uncompressed audio files; audio compression as used by YouTube destroys both phase and high-frequency content required to produce a crisp and stable image.&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;*Example frame from [C. Allen | Next Gen](https://youtu.be/ooDrU0gkO_c).*&#xD;&#xA;&#xD;&#xA;These are all much lower quality than a purpose-built vector display; the limiting factor is the sample rate and therefore bandwidth of audio equipment, which generally only goes up to 192 kHz at most (and often no more than 44.1 kHz.) Additionally, the “oscilloscope music” field is about creating vector signals that are _also_ somewhat pleasing to listen to, which constrains them in ways a pure visual display does not care about.&#xD;&#xA;&#xD;&#xA;If you want to get even more hands-on, you can write a program which generates the samples yourself (in real-time to your system's audio hardware, or to a file for later playback) and make your own vector graphics. It's not hard, and it will teach you a lot about these systems and their benefits and limitations.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Another place you can find modern vector display implementations is “oscilloscope clocks” — these devices use oscilloscope CRTs, without the rest of the oscilloscope, to display the time. Since these are self-contained recently-built devices, studying the schematic and software of such a device might be a way to get the complete, unambiguous description you would like.&#xD;&#xA;&#xD;&#xA;Laser scanning projectors — used for [laser light shows](https://en.wikipedia.org/wiki/Laser_lighting_display) in live entertainment — are non-CRT devices which rapidly sweep a single beam of light. They have much lower bandwidth (amount of detail vs. flicker) because they must physically swivel mirrors to move the beam, but the principle of generating changing X-Y signals to produce graphics is exactly the same.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Ghrtw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40636" PostHistoryTypeId="5" PostId="13459" RevisionGUID="b5d87295-fc14-4c74-814d-544f7931011a" CreationDate="2023-05-09T08:18:17.227" UserId="19924" Comment="Added details about the solution I was thinking about.," Text="I want to draw a circle in 3D from line segments. There are plenty of examples how to do this with an even number of subdivisions in 3D space, but I want the minimum number of subdivisions to produce a smooth circle after projection, without under- or over-subdividing. So a small circle (after projection) should require few subdivisions, a large circle should require more.&#xD;&#xA;&#xD;&#xA;I could just calculate a fixed subdivision based on camera field-of-view and screen resolution, but that will only be correct for circles directly facing the camera.&#xD;&#xA;&#xD;&#xA;Before I dig into the maths to figure this out I want to ask if there is already a well-known solution to this, because searches didn't come up with anything useful so far.&#xD;&#xA;&#xD;&#xA;I have the feeling this is either solvable by stepping around the conic section projection of the circle in screen space, or by adjusting the step size based on the projection matrix.&#xD;&#xA;&#xD;&#xA;Edit: I think subdivision methods are good solutions, especially for arbitrary curves. I was wondering if there is a closed solution exploiting symmetries of the circle. I'll need to have a think, but at least I doesn't look like I'm missing an existing solution. " ContentLicense="CC BY-SA 4.0" />
  <row Id="40637" PostHistoryTypeId="5" PostId="13460" RevisionGUID="603f570f-b388-4868-9b24-a99a0c35ad0c" CreationDate="2023-05-09T18:45:48.660" UserDisplayName="user1703" Comment="added 178 characters in body" Text="What you are after is a curve flattening, i.e. turning a curve (an ellipse in your case) into a polyline, in such a way that the discretization is not visible.&#xD;&#xA;&#xD;&#xA;This can be done by recursive subdivision: for a given arc of the curve, estimate the deviation from the line segment that joins the endpoints. If the deviation exceeds a visual threshold (a fraction of a pixel), split the arc in two subarcs and recurse.&#xD;&#xA;&#xD;&#xA;A gross estimate of the deviation is obtained by just taking the distance of some intermediate point of the arc to the segment. This is inaccurate when the deviation is large, but quite sufficient for small deviations.&#xD;&#xA;&#xD;&#xA;The method is suboptimal but easy and effective. It will not only adjust the point density for small vs. large circles, but also finely adjust as a function of local curvature. Needless to say, the flattening is completely viewpoint-dependent.&#xD;&#xA;&#xD;&#xA;Also note that you needn't compute the equation of the ellipse.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;A uniform subdivision is not such a good idea, because under grazing incidence, the curvature can become high and the angular step would need to be very small." ContentLicense="CC BY-SA 4.0" />
  <row Id="40638" PostHistoryTypeId="2" PostId="13471" RevisionGUID="83b807c8-6924-4d2e-997e-5dcfb7e9186e" CreationDate="2023-05-09T19:52:25.220" UserId="13273" Text="It depends if you use layout qualifier identifiers (see [here][1]). The usual range is [0.5, 1023.5] for a viewport size of 1024, So it is the Pixel center. &#xD;&#xA;But you need other states to be set correctly like viewport size, depth test, stancil test... &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/gl_FragCoord.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="40640" PostHistoryTypeId="5" PostId="13471" RevisionGUID="114e6ef7-b166-4ac1-aaf5-91be306a8b4c" CreationDate="2023-05-09T20:08:53.633" UserId="13273" Comment="added 139 characters in body" Text="It depends if you use layout qualifier identifiers (see [here][1]). The usual range is [0.5, 1023.5] for a viewport size of 1024, So it is the Pixel center. &#xD;&#xA;But you need other states to be set correctly like viewport size, depth test, stancil test, blend mode, culling... &#xD;&#xA;&#xD;&#xA;There is the third parameter missing at the texelfetch command in your shader. It is the level of detail (mipmap level) this should be 0.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/gl_FragCoord.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="40641" PostHistoryTypeId="5" PostId="13471" RevisionGUID="d06f47ca-d04f-4f5d-a066-626ab6d675e3" CreationDate="2023-05-09T20:13:57.087" UserId="13273" Comment="added 139 characters in body" Text="You should take a look at the layout qualifier identifiers (see [here][1]). The usual range is [0.5, 1023.5] for a viewport size of 1024, So it is the Pixel center. But when casting it to ivecX to hand it over to the texelfetch command the Pixel positions is correct. &#xD;&#xA;&#xD;&#xA;But you need other states to be set correctly like viewport size, depth test, stancil test, blend mode, culling... &#xD;&#xA;&#xD;&#xA;There is the third parameter missing at the texelfetch command in your shader. It is the level of detail (mipmap level) this should be 0.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/gl_FragCoord.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="40642" PostHistoryTypeId="5" PostId="13471" RevisionGUID="f1ce5f63-d868-455e-968f-039fccc95e63" CreationDate="2023-05-10T05:55:18.743" UserId="13273" Comment="added 103 characters in body" Text="You should take a look at the layout qualifier identifiers (see [here][1]). The usual range is [0.5, 1023.5] for a viewport size of 1024, So it is the Pixel center. But when casting it to ivecX to hand it over to the texelfetch command the Pixel positions is correct. Texelfetch returns you the raw data, without filtering, because the input position is in integer form. &#xD;&#xA;&#xD;&#xA;But you need other states to be set correctly like viewport size, depth test, stancil test, blend mode, culling... &#xD;&#xA;&#xD;&#xA;There is the third parameter missing at the texelfetch command in your shader. It is the level of detail (mipmap level) this should be 0.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/gl_FragCoord.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="40644" PostHistoryTypeId="5" PostId="13469" RevisionGUID="532de977-53c8-4a89-ba5d-b9d0245a1d9a" CreationDate="2023-05-10T16:20:55.553" UserId="2654" Comment="deleted 4 characters in body" Text="Here is a paragraph of Shreiner and Angel's _Interactive Computer Graphics_:&#xD;&#xA;&#xD;&#xA;&quot;_Early graphics systems used general-purpose computers with the standard von&#xD;&#xA;Neumann architecture. Such computers are characterized by a single processing unit&#xD;&#xA;that processes a single instruction at a time. A simple model of these early graphics&#xD;&#xA;systems is shown in Figure 1.35. The display in these systems was based on a calligraphic CRT display that included the necessary circuitry to generate a line segment&#xD;&#xA;connecting two points. The job of the host computer was to run the application program and to compute the endpoints of the line segments in the image (in units of the&#xD;&#xA;display). This information had to be sent to the display at a rate high enough to avoid flicker on the display. In the early days of computer graphics, computers were so slow&#xD;&#xA;that refreshing even simple images, containing a few hundred line segments, would&#xD;&#xA;burden an expensive computer._&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I often struggle to understand explanations that are not 'pedantically rigorous'. I believe I would better understand the paragraph in question if I was given a detailed example so as to appreciate _exactly_ how the CRT display functions. &#xD;&#xA;&#xD;&#xA;Could someone provide, or point me in the direction of, a step-by-step algorithm or drawn circuitry that meticulously shows how an instruction from the host is turned into a displayed image in a screen?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zjjAE.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40645" PostHistoryTypeId="50" PostId="13400" RevisionGUID="04519e72-c6e3-4f57-a6d0-2fc6659d99e7" CreationDate="2023-05-10T19:01:45.417" UserId="-1" />
  <row Id="40648" PostHistoryTypeId="50" PostId="5697" RevisionGUID="448d60d3-677c-4c2f-a3cf-9ecbf3fa1f75" CreationDate="2023-05-12T15:03:25.343" UserId="-1" />
  <row Id="40649" PostHistoryTypeId="5" PostId="13468" RevisionGUID="f6ea3f0e-b9ad-42c8-a284-24a33628dfa3" CreationDate="2023-05-12T22:58:47.207" UserId="9036" Comment="added 69 characters in body" Text="&#xD;&#xA;&#xD;&#xA;Imagine I have two uncompressed, 2D textures A and B with identical sizes and formats. I bind A to texture unit 0, and B to a framebuffer object.&#xD;&#xA;&#xD;&#xA;If I draw a full-size polygon in that framebuffer with this pixel shader:&#xD;&#xA;&#xD;&#xA;    uniform sampler2D iChannel0;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;       fragColor = texelFetch(iChannel0, gl_FragCoord.xy);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this guaranteed to make a perfect copy of texture A? &#xD;&#xA;&#xD;&#xA;ie. Will gl_FragCoord.xy give good numbers that map every input texel to every output texel? Will there be any filtering or clamping applied to the texels?&#xD;&#xA;&#xD;&#xA;Edit: It should be &#xD;&#xA;&#xD;&#xA;    fragColor = texelFetch(iChannel0, ivec2(gl_FragCoord.xy), 0);" ContentLicense="CC BY-SA 4.0" />
  <row Id="40657" PostHistoryTypeId="2" PostId="13473" RevisionGUID="1223efcf-5d19-4b7c-bad1-5127ce30b224" CreationDate="2023-05-14T17:15:43.747" UserId="19939" Text="I'm struggling with understanding how blending works. Here's what I understand:&#xD;&#xA;when I set the following&#xD;&#xA;&#xD;&#xA;    glEnable(GL_BLEND);&#xD;&#xA;    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);&#xD;&#xA;then I would expect to have the following result when blending $scr$ with $dst$:&#xD;&#xA;$$&#xD;&#xA;result = src.a \cdot src + (1-scr.a) \cdot dst&#xD;&#xA;$$&#xD;&#xA;This is the blending function setup I commonly stumble upon. My problem is the following: when I have a completely opaque background, let's say $dst=(1,0,0,1)$, and I render a half opaque square in front of it $src=(0,1,0,0.5)$ then the resulting alpha for the new color will be&#xD;&#xA;$$&#xD;&#xA;result.a = src.a \cdot src.a + (1-src.a) \cdot dst.a = 0.5 \cdot 0.5 + 0.5 \cdot 1 = 0.75&#xD;&#xA;$$&#xD;&#xA;How does it make sense to have a half opaque object in front of a fully opaque object result in something that is not fully opaque again? I feel like I'm misunderstanding something, I'm glad for any help I can get." ContentLicense="CC BY-SA 4.0" />
  <row Id="40659" PostHistoryTypeId="1" PostId="13473" RevisionGUID="1223efcf-5d19-4b7c-bad1-5127ce30b224" CreationDate="2023-05-14T17:15:43.747" UserId="19939" Text="How is the alpha value treated when blending?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40660" PostHistoryTypeId="3" PostId="13473" RevisionGUID="1223efcf-5d19-4b7c-bad1-5127ce30b224" CreationDate="2023-05-14T17:15:43.747" UserId="19939" Text="|opengl|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40661" PostHistoryTypeId="2" PostId="13474" RevisionGUID="6fd9da88-18ef-4858-b101-b6cf2d5b5ac8" CreationDate="2023-05-15T00:15:56.510" UserId="2654" Text="&gt; How does it make sense to have a half opaque object in front of a fully opaque object result in something that is not fully opaque again?&#xD;&#xA;&#xD;&#xA;The problem here is one of concepts. The alpha component of a color has no *inherent* meaning. It doesn't mean opaque or transparent. It's just a value.&#xD;&#xA;&#xD;&#xA;It only takes on a meaning when you use it in a way that gives it that meaning. Your blending function performs linear interpolation between the source and destination colors based on the source's alpha component. One way to conceptualize this equation is to say that the source alpha represents the opacity of the source color overlaid on top of the destination color.&#xD;&#xA;&#xD;&#xA;However, this understanding of your blending equation only makes sense if we assume that the destination color is *opaque*. That is, you're always blending between a possibly transparent source and a definitely opaque destination.&#xD;&#xA;&#xD;&#xA;So what does the destination alpha mean in this equation? Nothing. It's just data in your framebuffer. It has no inherent meaning within the context of this blending operation." ContentLicense="CC BY-SA 4.0" />
  <row Id="40663" PostHistoryTypeId="50" PostId="12414" RevisionGUID="c4fcf6f6-41dd-4a58-a4f7-d5cb983329d5" CreationDate="2023-05-15T10:13:26.637" UserId="-1" />
  <row Id="40664" PostHistoryTypeId="2" PostId="13475" RevisionGUID="1c30888e-2d3a-4bf0-93cc-4f8d0b093f0a" CreationDate="2023-05-15T12:29:13.263" UserId="8830" Text="Looks like a typo since the compiler isn't complaining about the other SDL function calls. You probably need to change `SDL_setRenderDrawColor` to `SDL_SetRenderDrawColor`&#xD;&#xA;&#xD;&#xA;https://wiki.libsdl.org/SDL2/SDL_SetRenderDrawColor" ContentLicense="CC BY-SA 4.0" />
  <row Id="40666" PostHistoryTypeId="2" PostId="13476" RevisionGUID="fe923c14-6284-40d4-bd8c-d86f45b1d576" CreationDate="2023-05-15T14:31:55.753" UserId="13273" Text="I am looking for algorithms to create meshlets from triangulated meshes.&#xD;&#xA;I searched for articles, but could not find any.&#xD;&#xA;Maybe &quot;meshlet&quot; is not the right term?&#xD;&#xA;&#xD;&#xA;I want to split my geometries into smaller parts that have a maximum number of vertices and a nearly equal normal vector, and that are close to each other. The reason for this is early clipping / culling to speed up my rendering.&#xD;&#xA;&#xD;&#xA;I've tried to do it myself, but it's not as easy as it seems. I got &quot;bad&quot; looking results. On closer inspection I saw that many meshlets are very small. Probably because adjacent faces have already been grouped into other meshlets, or the normal vectors are too different.&#xD;&#xA;&#xD;&#xA;It also doesn't seem easy to keep the normal vectors similar without ending up with meshlets that are too small.&#xD;&#xA;&#xD;&#xA;What algorithms can I use? And what advantages do they have (compared to other algorithms)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40668" PostHistoryTypeId="1" PostId="13476" RevisionGUID="fe923c14-6284-40d4-bd8c-d86f45b1d576" CreationDate="2023-05-15T14:31:55.753" UserId="13273" Text="looking for meshlet generation algorithms" ContentLicense="CC BY-SA 4.0" />
  <row Id="40669" PostHistoryTypeId="3" PostId="13476" RevisionGUID="fe923c14-6284-40d4-bd8c-d86f45b1d576" CreationDate="2023-05-15T14:31:55.753" UserId="13273" Text="|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40670" PostHistoryTypeId="5" PostId="13476" RevisionGUID="c8d8d1e0-f8b3-4c75-b30a-a1807a153cc2" CreationDate="2023-05-15T15:33:27.433" UserId="13273" Comment="added 1 character in body" Text="I am looking for algorithms to create meshlets from triangulated meshes.&#xD;&#xA;I searched for articles, but could not find any.&#xD;&#xA;Maybe &quot;meshlet&quot; is not the right term?&#xD;&#xA;&#xD;&#xA;I want to split my geometries into smaller parts that have a maximum number of vertices and a nearly equal normal vector, and that are close to each other. The reason for this is early clipping / culling to speed up my rendering.&#xD;&#xA;&#xD;&#xA;I've tried to do it myself, but it's not as easy as it seems. I got &quot;bad&quot; looking results. On closer inspection I saw that many meshlets are very small. Probably because adjacent faces have already been grouped into other meshlets, or the normal vectors are too different.&#xD;&#xA;&#xD;&#xA;It also doesn't seem easy to keep the normal vectors similar without ending up with meshlets that are too small.&#xD;&#xA;&#xD;&#xA;Which algorithms can I use? And what advantages do they have (compared to other algorithms)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40671" PostHistoryTypeId="5" PostId="13474" RevisionGUID="8720ecce-ed12-444b-ac67-598802ca2a73" CreationDate="2023-05-15T17:12:39.077" UserId="2654" Comment="added 517 characters in body" Text="&gt; How does it make sense to have a half opaque object in front of a fully opaque object result in something that is not fully opaque again?&#xD;&#xA;&#xD;&#xA;The problem here is one of concepts. The alpha component of a color has no *inherent* meaning. It doesn't mean opaque or transparent. It's just a value.&#xD;&#xA;&#xD;&#xA;It only takes on a meaning when you use it in a way that gives it that meaning. Your blending function performs linear interpolation between the source and destination colors based on the source's alpha component. One way to conceptualize this equation is to say that the source alpha represents the opacity of the source color overlaid on top of the destination color.&#xD;&#xA;&#xD;&#xA;However, this understanding of your blending equation only makes sense if we assume that the destination color is *opaque*. That is, you're always blending between a possibly transparent source and a definitely opaque destination.&#xD;&#xA;&#xD;&#xA;So what does the destination alpha mean in this equation? Nothing. It's just data in your framebuffer. It has no inherent meaning within the context of this blending operation.&#xD;&#xA;&#xD;&#xA;&gt; So how would I set up the function to produce an alpha value which stays fully opaque when blended with a fully opaque color? &#xD;&#xA;&#xD;&#xA;By using [separate blending parameters for the alpha][1]. The RGB and A components of the output color can be processed with separate parameters (or even [equations][2]):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This will leave the destination alpha untouched.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Blending#Blending_Parameters&#xD;&#xA;  [2]: https://www.khronos.org/opengl/wiki/Blending#Blend_Equations" ContentLicense="CC BY-SA 4.0" />
  <row Id="40672" PostHistoryTypeId="5" PostId="13476" RevisionGUID="c3ecb824-2124-4f60-9205-f878a3eeaf1c" CreationDate="2023-05-16T07:15:02.257" UserId="13273" Comment="added 945 characters in body" Text="I am looking for algorithms to create meshlets from triangulated meshes.&#xD;&#xA;I searched for articles, but could not find any.&#xD;&#xA;Maybe &quot;meshlet&quot; is not the right term?&#xD;&#xA;&#xD;&#xA;I want to cluster the faces that have a maximum number of vertices and a nearly equal normal vector, and that are close to each other. The reason for this is early clipping / culling to speed up my rendering.&#xD;&#xA;&#xD;&#xA;I've tried to do it myself, but it's not as easy as it seems. I got &quot;bad&quot; looking results. On closer inspection I saw that many meshlets are very small. Probably because adjacent faces have already been grouped into other meshlets, or the normal vectors are too different.&#xD;&#xA;&#xD;&#xA;It also doesn't seem easy to keep the normal vectors similar without ending up with meshlets that are too small.&#xD;&#xA;&#xD;&#xA;Which algorithms can I use? And what advantages do they have (compared to other algorithms)?&#xD;&#xA;&#xD;&#xA;Edit: It seems unclear what I mean by meshlets. So I'll explain what I'm trying to do:&#xD;&#xA;&#xD;&#xA;I want to group the faces of a geometry into individual groups (meshlets). I don't want to increase the number of faces.... This is a preprocessing step that needs to be done once when loading the geometry. Each of the meshlets gets a bounding sphere for clipping tests, a normal vector with additional angle (normal vector cone) for culling tests. If geometry rendering is foreseen, clipping/culling tests are performed beforehand, along with a level of detail (LoD) test. During rendering, the results of the culling/clipping/LoD tests are loaded to finally render only the parts of the geometry that survived these tests.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure1** [Image source][2]. This is an example of a result I am trying to achieve.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nVndt.png&#xD;&#xA;  [2]: https://metalbyexample.com/mesh-shaders/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40673" PostHistoryTypeId="5" PostId="13476" RevisionGUID="b9cad328-5b93-4594-ba0d-af610fa03073" CreationDate="2023-05-16T07:19:08.827" UserId="13273" Comment="deleted 2 characters in body" Text="I am looking for algorithms to create meshlets from triangulated meshes.&#xD;&#xA;I searched for articles, but could not find any.&#xD;&#xA;Maybe &quot;meshlet&quot; is not the right term?&#xD;&#xA;&#xD;&#xA;I want to cluster the faces to have a maximum number of vertices and a nearly equal normal vector, and that are close to each other. The reason for this is early clipping / culling to speed up my rendering.&#xD;&#xA;&#xD;&#xA;I've tried to do it myself, but it's not as easy as it seems. I got &quot;bad&quot; looking results. On closer inspection I saw that many meshlets are very small. Probably because adjacent faces have already been grouped into other meshlets, or the normal vectors are too different.&#xD;&#xA;&#xD;&#xA;It also doesn't seem easy to keep the normal vectors similar without ending up with meshlets that are too small.&#xD;&#xA;&#xD;&#xA;Which algorithms can I use? And what advantages do they have (compared to other algorithms)?&#xD;&#xA;&#xD;&#xA;Edit: It seems unclear what I mean by meshlets. So I'll explain what I'm trying to do:&#xD;&#xA;&#xD;&#xA;I want to group the faces of a geometry into individual groups (meshlets). I don't want to increase the number of faces.... This is a preprocessing step that needs to be done once when loading the geometry. Each of the meshlets gets a bounding sphere for clipping tests, a normal vector with additional angle (normal vector cone) for culling tests. If geometry rendering is foreseen, clipping/culling tests are performed beforehand, along with a level of detail (LoD) test. During rendering, the results of the culling/clipping/LoD tests are loaded to finally render only the parts of the geometry that survived these tests.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure1** [Image source][2]. This is an example of a result I am trying to achieve.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nVndt.png&#xD;&#xA;  [2]: https://metalbyexample.com/mesh-shaders/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40674" PostHistoryTypeId="5" PostId="13476" RevisionGUID="c3a135b5-8af9-47fc-a73f-9310fadafbc6" CreationDate="2023-05-16T07:36:17.767" UserId="13273" Comment="added 50 characters in body" Text="I am looking for algorithms to create meshlets from triangulated meshes.&#xD;&#xA;I searched for articles, but could not find any.&#xD;&#xA;Maybe &quot;meshlet&quot; is not the right term?&#xD;&#xA;&#xD;&#xA;I want to cluster the faces to have a maximum number of vertices each (for example 64) and a nearly equal normal vector, and each face within a cluster should be close to each other. The reason for this is early clipping / culling to speed up my rendering.&#xD;&#xA;&#xD;&#xA;I've tried to do it myself, but it's not as easy as it seems. I got &quot;bad&quot; looking results. On closer inspection I saw that many meshlets are very small. Probably because adjacent faces have already been grouped into other meshlets, or the normal vectors are too different.&#xD;&#xA;&#xD;&#xA;It also doesn't seem easy to keep the normal vectors similar without ending up with meshlets that are too small.&#xD;&#xA;&#xD;&#xA;Which algorithms can I use? And what advantages do they have (compared to other algorithms)?&#xD;&#xA;&#xD;&#xA;Edit: It seems unclear what I mean by meshlets. So I'll explain what I'm trying to do:&#xD;&#xA;&#xD;&#xA;I want to group the faces of a geometry into individual groups (meshlets). I don't want to increase the number of faces.... This is a preprocessing step that needs to be done once when loading the geometry. Each of the meshlets gets a bounding sphere for clipping tests, a normal vector with additional angle (normal vector cone) for culling tests. If geometry rendering is foreseen, clipping/culling tests are performed beforehand, along with a level of detail (LoD) test. During rendering, the results of the culling/clipping/LoD tests are loaded to finally render only the parts of the geometry that survived these tests.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure1** [Image source][2]. This is an example of a result I am trying to achieve.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/nVndt.png&#xD;&#xA;  [2]: https://metalbyexample.com/mesh-shaders/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40676" PostHistoryTypeId="5" PostId="8985" RevisionGUID="321e6e8c-ae06-4f1b-b167-b4a82c7880b4" CreationDate="2023-05-16T21:22:03.167" UserId="9500" Comment="very cheap handwaved reference addition" Text="So, I'll start by saying I'm not a driver developer, but I have read many comments and docs in this regard. &#xD;&#xA;&#xD;&#xA;First of all, we can see how Khronos's own [slides][1] on presentation day were mentioning some rather vague &quot;any OpenGL ES 3.1 GPU&quot; (or desktop 4.X). This means [something][2] added around that mark would be the secret to it. Compute shaders are definitively [at least one of] the things, being confirmed [here][3], by an [Intel developer][4], and in [the spec][5] with no possible unsupported value for `MaxComputeWorkGroupSize` and this likely smoking gun: &#xD;&#xA;&gt; If an implementation exposes any queue family that supports graphics&#xD;&#xA;&gt; operations, at least one queue family of at least one physical device&#xD;&#xA;&gt; exposed by the implementation **must** support both graphics and&#xD;&#xA;&gt; compute operations.&#xD;&#xA;&#xD;&#xA;In addition to that though, it could *also* be there are other mandatory capabilities (such as indirect draws or [load&amp;store][6], mentioned in the comments above too). But I have some slight difficulty interpreting the document. With the exception of [robustBufferAccess][7], it seems like just about anything else big you could imagine is optional (from anisotropic filter, to geometry and tessellation shaders, to any special number format other than good old float32)&#xD;&#xA;&#xD;&#xA;This being the most hypothetically simple case then, doesn't mean it's all fine and dandy. Not having [virtual memory][8] will make your life a hell for example, and lack of other [architectural features][9] may basically nullify whatever theoretical advantage in speed the API has. &#xD;&#xA;&#xD;&#xA;These links should also answer your wonders about ATi cards. Likely same story for NVidia then (aside of perhaps some microbenchmarks, I'm not sure how much *really* workable [Fermi's][10] 2-years-delayed bare-bones DX12 support eventually is). As for Intel, I don't know what you are talking about, Gen8 is supported since [Day1][11] and in fact even [Gen7][12] *shakily* works now.&#xD;&#xA;&#xD;&#xA;Going even further back, I guess if any the question becomes &quot;what's so special about compute shaders again&quot;. &#xD;&#xA;&#xD;&#xA;And, well, the thing isn't probably the very specific [feature][13] itself (because it's [not that][14] you couldn't already do some sort of general purpose calculation even before the unified shader model), but more like the whole general GPU architecture needed to support it. Check [this][15] for some backstory. &#xD;&#xA;&#xD;&#xA;Before DX11 raised [the bar][16] for example, just think that you [couldn't][17] even run more than a single &quot;task&quot; on a Tesla GPU, without having to call a context switch (with comparable limitations also likely existing for TeraScale 1 and Gen6). And may God save us from when pixel and vertex units were separated hardware. &#xD;&#xA;&#xD;&#xA;fun fact: it turns out that if you are a low-end [kind-of-modern][18] mobile gpu (rather than an old desktop card from a time when certain concepts hadn't even been invented yet), engineers can cut you down so much that even if you just sport D3D 9_3 feature level that's still potentially [enough][19] to support Vulkan.&#xD;&#xA;&#xD;&#xA;EDIT: for such somewhat twisted reasons, it can also [happen][20] that while you are just GLES 2.0 compliant (and compute shaders themselves aren't supported atm, even though the architecture would be capable) a restricted version of Vulkan could also be possible. It doesn't give you everything, but it can still lead to benefits over just &quot;old apis&quot;. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/assets/uploads/developers/library/overview/Vk_201602_Overview_Feb16.pdf#page=13&#xD;&#xA;  [2]: https://www.anandtech.com/show/7867/khronos-announces-opengl-es-31&#xD;&#xA;  [3]: https://pcper.com/2015/03/gdc-15-what-is-vulkan-glnext-spir-v-and-opencl-2-1/&#xD;&#xA;  [4]: https://youtu.be/2ryvYS47V0E?t=3176&#xD;&#xA;  [5]: https://www.khronos.org/registry/vulkan/specs/1.1/pdf/vkspec.pdf&#xD;&#xA;  [6]: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6747#note_1702538&#xD;&#xA;  [7]: https://www.khronos.org/registry/vulkan/specs/1.0/html/chap30.html#features-requirements&#xD;&#xA;  [8]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/open-source-amd-linux/1004192-r600-gallium3d-now-effectively-at-opengl-4-4-a-nudge-away-from-gl-4-5/page2#post1004523&#xD;&#xA;  [9]: https://www.phoronix.com/forums/forum/linux-graphics-x-org-drivers/vulkan/845690-amd-s-vulkan-driver-will-only-work-with-the-amdgpu-kernel-driver/page3#post845730&#xD;&#xA;  [10]: https://techreport.com/news/32191/nvidia-finally-lets-fermi-gpu-owners-enjoy-directx-12/&#xD;&#xA;  [11]: https://01.org/linuxgraphics/blogs/jekstrand/2016/open-source-vulkan-drivers-intel-hardware&#xD;&#xA;  [12]: https://stackoverflow.com/questions/41497142/can-i-install-a-vulkan-driver-on-my-3rd-gen-intel-ivy-bridge-integrated-gpu-on-u&#xD;&#xA;  [13]: https://www.anandtech.com/show/2716/5&#xD;&#xA;  [14]: https://en.wikipedia.org/wiki/BrookGPU&#xD;&#xA;  [15]: https://www.gamedev.net/forums/topic/666419-what-are-your-opinions-on-dx12vulkanmantle/5215019/&#xD;&#xA;  [16]: https://stackoverflow.com/questions/3332782/can-directcompute-really-be-used-on-a-dx10-1-gpu&#xD;&#xA;  [17]: https://www.anandtech.com/show/2977/nvidia-s-geforce-gtx-480-and-gtx-470-6-months-late-was-it-worth-the-wait-/3&#xD;&#xA;  [18]: https://www.anandtech.com/show/8649/arm-announces-mali-800-series-gpus-t860-t830-t820&#xD;&#xA;  [19]: https://developer.arm.com/solutions/graphics/resources/faqs#vulkan_which&#xD;&#xA;  [20]: https://github.com/Yours3lf/rpi-vk-driver/issues/1" ContentLicense="CC BY-SA 4.0" />
  <row Id="40678" PostHistoryTypeId="2" PostId="13477" RevisionGUID="c9a73c15-2e23-4cfc-a1de-464d7ffc404a" CreationDate="2023-05-18T00:29:29.890" UserId="19967" Text="I have a program that is creating usdz 3D models from real world objects. I would like to be able to crop those objects in 3D space to remove extraneous nearby objects or walls. Is there a good existing solution for this on Mac? &#xD;&#xA;&#xD;&#xA;I am also able to output folders with unzipped contents including usda and obj files if that helps. I would prefer a standalone program, but could incorporate tools into a Swift Mac app." ContentLicense="CC BY-SA 4.0" />
  <row Id="40680" PostHistoryTypeId="1" PostId="13477" RevisionGUID="c9a73c15-2e23-4cfc-a1de-464d7ffc404a" CreationDate="2023-05-18T00:29:29.890" UserId="19967" Text="Cropping a .usdz file" ContentLicense="CC BY-SA 4.0" />
  <row Id="40681" PostHistoryTypeId="3" PostId="13477" RevisionGUID="c9a73c15-2e23-4cfc-a1de-464d7ffc404a" CreationDate="2023-05-18T00:29:29.890" UserId="19967" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40682" PostHistoryTypeId="50" PostId="9116" RevisionGUID="4576865f-34ea-44c4-87bb-d15a11d4955e" CreationDate="2023-05-18T12:01:35.190" UserId="-1" />
  <row Id="40683" PostHistoryTypeId="2" PostId="13478" RevisionGUID="9927f2af-315f-4103-a857-7d2292d6429e" CreationDate="2023-05-18T17:13:31.760" UserDisplayName="user1703" Text="If you have a good understanding of how the tongue deforms while speaking (presumably some part of it remains relatively fixed and other parts get a curvature), you might design a simple empirical model with a few degrees of freedom that maps any point in 3D space to the corresponding point after deformation.&#xD;&#xA;&#xD;&#xA;For instance, you might map a line segment on a symmetry axis of the tongue to a parabola, so the horizontal plane by this segment to a parabolic cylindre, and all parallel planes to &quot;parallel&quot; parabolic cylinders. (This is just a simple example, you know better than me.)&#xD;&#xA;&#xD;&#xA;Once you have this deformation model, you can use the tracked point(s) to determine the free parameters of the model (the number of degrees of freedom needs to match the number of independent measurements that you make).&#xD;&#xA;&#xD;&#xA;Then when you have the parameters, you can compute the deformed positions of any vertex of the mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="40685" PostHistoryTypeId="5" PostId="13478" RevisionGUID="5a2613a0-f9eb-4ef8-905b-720af54767ab" CreationDate="2023-05-18T17:22:17.227" UserDisplayName="user1703" Comment="added 266 characters in body" Text="If you have a good understanding of how the tongue deforms while speaking (presumably some part of it remains relatively fixed and other parts get a curvature), you might design a simple empirical model with a few degrees of freedom that maps any point in 3D space to the corresponding point after deformation.&#xD;&#xA;&#xD;&#xA;For instance, you might map a line segment on a symmetry axis along the resting tongue to a parabola, so the horizontal plane by this segment to a parabolic cylindre, and all parallel planes to &quot;parallel&quot; parabolic cylinders. (This is just a simple example, you know better than me.)&#xD;&#xA;&#xD;&#xA;I guess that you can focus on a median section, so that the problem is 2D and easier. From the 2D modelling, the shape of the transverse sections might be estimated from the position of the section along the tongue and the thickness after deformation.&#xD;&#xA;&#xD;&#xA;Once you have this deformation model, you can use the tracked point(s) to determine the free parameters of the model (the number of degrees of freedom needs to match the number of independent measurements that you make).&#xD;&#xA;&#xD;&#xA;Then when you have the parameters, you can compute the deformed positions of any vertex of the mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="40686" PostHistoryTypeId="2" PostId="13479" RevisionGUID="d5afe937-1b69-46d4-b257-1d50d09004af" CreationDate="2023-05-19T10:19:23.113" UserId="18064" Text="&#xD;&#xA;Assuming my viewing volume has x coordinates varies from l to r, and y varies from top to bottom, and finally z-axis varies n to f, I derived the following projection matrix: &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        mat4 projection = {&#xD;&#xA;                          2n/(r-l), 0,       (r+l)/(r-l), 0,&#xD;&#xA;                          0,        2n(t-b), (t+b)/(t-b), 0, &#xD;&#xA;                          0,        0,       (n+f)/(n-f), 2nf/(n-f),&#xD;&#xA;                          0,        0,       -1,          0&#xD;&#xA;&#xD;&#xA;which matches the projection matrix derived [here][1]&#xD;&#xA;&#xD;&#xA;Plugging in values for my cube coordinates, to be centered in the middle of the screen with Left = -100, Right = 100, Top = 100, Bottom = -100. I have the following vertices positions:&#xD;&#xA;&#xD;&#xA;        &#xD;&#xA;        f32 r =  100;&#xD;&#xA;        f32 l = -100;&#xD;&#xA;&#xD;&#xA;        f32 t =  100;&#xD;&#xA;        f32 b = -100;&#xD;&#xA;&#xD;&#xA;        f32 n = -1;&#xD;&#xA;        f32 f = -3;&#xD;&#xA;&#xD;&#xA;    GLfloat VertexData[40] = &#xD;&#xA;    {&#xD;&#xA;&#xD;&#xA;        //--------- Vertex Positions ---------//&#xD;&#xA;       -50.0f,  -50.0f,   1.0f,&#xD;&#xA;       +50.0f,  -50.0f,   1.0f,&#xD;&#xA;       +50.0f,  +50.0f,   1.0f, &#xD;&#xA;       -50.0f,  +50.0f,   1.0f,&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;       -50.0f,  -50.0f,   3.0f,&#xD;&#xA;       +50.0f,  -50.0f,   3.0f,&#xD;&#xA;       +50.0f,  +50.0f,   3.0f, &#xD;&#xA;       -50.0f,  +50.0f,   3.0f,&#xD;&#xA;       //-------Other data for texture coordinates------//&#xD;&#xA;       };&#xD;&#xA;which produces the expected image&#xD;&#xA;&#xD;&#xA;[![Image][2]][2]&#xD;&#xA;&#xD;&#xA;and here is my question: **if I am using a non-symmetric boundaries (Right != -Left) should not the output image be the same?** &#xD;&#xA;&#xD;&#xA;I set Right = 100, Left = 0, and I changed vertices positions to be from 25 to 75 ([-50,+50] range with respect to r =100, l = -100 should be equivalent to [+25,+75] with r = 100, l = 0) but the output image does not match&#xD;&#xA;&#xD;&#xA;[![https://cdn.discordapp.com/attachments/591343919598534681/1108811954308534392/image.png][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Looking at it, it seems like the perspective divide moves further away points to the edge of the screen, instead of the center of the screen. &#xD;&#xA;&#xD;&#xA;full source code for this example is available [here][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.songho.ca/opengl/gl_projectionmatrix.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/3I06J.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vBVzt.png&#xD;&#xA;  [4]: https://git.sr.ht/~aliabdulkareem/openGLTemplate/tree/master" ContentLicense="CC BY-SA 4.0" />
  <row Id="40688" PostHistoryTypeId="1" PostId="13479" RevisionGUID="d5afe937-1b69-46d4-b257-1d50d09004af" CreationDate="2023-05-19T10:19:23.113" UserId="18064" Text="My projection matrix for OpenGL fails on non-symmetric boundaries" ContentLicense="CC BY-SA 4.0" />
  <row Id="40689" PostHistoryTypeId="3" PostId="13479" RevisionGUID="d5afe937-1b69-46d4-b257-1d50d09004af" CreationDate="2023-05-19T10:19:23.113" UserId="18064" Text="|opengl|rendering|projections|perspective|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40690" PostHistoryTypeId="50" PostId="13408" RevisionGUID="a1774875-181a-46c0-9cd4-40421936c14c" CreationDate="2023-05-19T13:02:20.283" UserId="-1" />
  <row Id="40691" PostHistoryTypeId="2" PostId="13480" RevisionGUID="2225bf23-3833-48a1-956b-4d9a32f30beb" CreationDate="2023-05-19T21:07:36.847" UserId="445" Text="Nothing is wrong.&#xD;&#xA;&#xD;&#xA;If we suppose `n` is fixed, then `l`, `r`, `t`, and `b` control the _slope of the sides of the view frustum._ When you make `l` = 0, you are setting that slope to zero, and the left edge of the image corresponds to looking directly along the view direction of the camera.&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;Since you moved the cube too, and the cube is entirely to the right of the viewpoint, your projection is now allowing you a look at the left face of the cube.&#xD;&#xA;&#xD;&#xA;What you're doing is effectively the same as cutting off the left half of a normal perspective projection. (Generally, you can arbitrarily skew the view projection frustum without changing its volume by adding the _same_ amount to `l` and `r` or to `t` and `b`.)&#xD;&#xA;&#xD;&#xA;In order to change the coordinate system without changing the projection, you should apply a translation to your view matrix, and leave the projection parameters unchanged.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XxpSX.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40693" PostHistoryTypeId="50" PostId="9781" RevisionGUID="3ddcad82-164b-4876-ba51-329fdd3ae803" CreationDate="2023-05-19T22:07:55.973" UserId="-1" />
  <row Id="40695" PostHistoryTypeId="50" PostId="10177" RevisionGUID="6fe9b841-b03d-421b-a2fc-d110b04ee474" CreationDate="2023-05-20T07:05:05.583" UserId="-1" />
  <row Id="40696" PostHistoryTypeId="2" PostId="13481" RevisionGUID="0963cc6b-d38f-4217-99c7-ee74b6d1646b" CreationDate="2023-05-20T08:05:39.627" UserId="19975" Text="FYI, the first answer is very close to explaining the causes of Z-fighting, or Z-flashing. It is about decimal places and it does relate to distance, or the simulation of distance.&#xD;&#xA;&#xD;&#xA;To understand what causes the flashing, you want to consider the distances as a ratio. There is the distance between the two planes and then the distance between the two planes and the viewer, or the POV, point of view. If the two competing faces are extremely close together and the POV is extremely far from them, it will be as if the two surfaces are overlapping. If changes in distance are so subtle, that the decimals defining those changes are too small to register in the buffer, then it can be as if one face moves in front of the other, after another slight movement, the calculation changes, and the faces revert.&#xD;&#xA;&#xD;&#xA; When you scale the model, that ratio changes significantly. Moving the competing faces further apart, will also affect the ratio. Understanding what causes the flashing will allow artists to devise solutions. For example, an object that will always be viewed from a distance, can probably be created such that the faces that might conflict, are spaced farther apart, than would be optimal for close inspection viewing." ContentLicense="CC BY-SA 4.0" />
  <row Id="40698" PostHistoryTypeId="2" PostId="13482" RevisionGUID="d8a80626-1c02-47ce-8fa6-c93e2c515eb4" CreationDate="2023-05-20T22:09:34.880" UserId="2684" Text="I am reading this book about to code your own radiosity renderer by Ian Ashdown [Book link][1]&#xD;&#xA;&#xD;&#xA;There is a chapter about view-camera transformation, particularly the normalization process when he transform the frustum pyramid into a unit cube&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My problem with this transformation is that the author don't explain how the matrix's values are derived&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I never saw such a complex computation to normalize the front and back clipping planes for example&#xD;&#xA;&#xD;&#xA;Also he never explain why there is `1/2` translation offset in the x and y axis&#xD;&#xA;&#xD;&#xA;Can anybody bring some light to me with respect to these esoteric formulas, I will be greatly grateful&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.researchgate.net/publication/220690300_Radiosity_-_a_programmer's_perspective&#xD;&#xA;  [2]: https://i.stack.imgur.com/0x5om.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/1wyW8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40700" PostHistoryTypeId="1" PostId="13482" RevisionGUID="d8a80626-1c02-47ce-8fa6-c93e2c515eb4" CreationDate="2023-05-20T22:09:34.880" UserId="2684" Text="View system transformation by Ian Ashdown" ContentLicense="CC BY-SA 4.0" />
  <row Id="40701" PostHistoryTypeId="3" PostId="13482" RevisionGUID="d8a80626-1c02-47ce-8fa6-c93e2c515eb4" CreationDate="2023-05-20T22:09:34.880" UserId="2684" Text="|matrix|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40702" PostHistoryTypeId="2" PostId="13483" RevisionGUID="5eecca09-f67f-4ba4-8493-1ccf95d3ca62" CreationDate="2023-05-22T13:58:51.650" UserId="19984" Text="First of all, I am completely new to this so please excuse me if this is a dumb question.&#xD;&#xA;&#xD;&#xA;I am following the book Real-Time 3D Rendering with DirectX and HLSL, for now implementing shaders in Nvidia FX Composer.&#xD;&#xA;&#xD;&#xA;I have created a Phong-shader (P in the pictures) and a BlinnPhong-shader (BP), and both seem to work mostly correct. (The power-term in the specular calculation in the BP-shader is 2x that of the P-shader, as per recommendation).&#xD;&#xA;&#xD;&#xA;[![BlinnPhong left, Phong right][1]][1]&#xD;&#xA;&#xD;&#xA;There is a difference, and that is evident when viewing the reflection from an wider angle, where the reflection is spread around the edge of the sphere.&#xD;&#xA;This becomes clear in image 2. You can see that the reflection is being spread around the edge in the phong shader, but the reflection mostly keeps its shape in the BP-shader.&#xD;&#xA;I think the P-shader looks better, at least in the case of the sphere.&#xD;&#xA;&#xD;&#xA;[![BP - the reflection keeps the shape, P - the reflection is spread out.][2]][2]&#xD;&#xA;&#xD;&#xA;Is this correct behavior, or am I doing something wrong?&#xD;&#xA;My theory is that it has something to do with the normals, but I'm not quite sure how.&#xD;&#xA;&#xD;&#xA;I have supplied the source code here (nvidia fx composer). The only difference is in the pixel shaders, so I have only included the pixel shader from the BP-shader code.&#xD;&#xA;&#xD;&#xA;    /////////////////////////////// PHONG SHADER ///////////////////////////////&#xD;&#xA;    cbuffer CBufPerFrame&#xD;&#xA;    {&#xD;&#xA;    	float3 LightDirection : DIRECTION&#xD;&#xA;    	&lt;&#xD;&#xA;    		string Object = &quot;DirectionalLight0&quot;;&#xD;&#xA;    		string UIName = &quot;lightDirection&quot;;&#xD;&#xA;    		string Space = &quot;World&quot;;&#xD;&#xA;    	&gt; = {0.0, 0.0, -1.0};&#xD;&#xA;    	&#xD;&#xA;    	float3 CameraPosition : CAMERAPOSITION&#xD;&#xA;    	&lt;&gt;;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    cbuffer CBufPerObj&#xD;&#xA;    {&#xD;&#xA;    	float4x4 WVP : WORLDVIEWPROJECTION&#xD;&#xA;    	&lt;&gt;;&#xD;&#xA;    	&#xD;&#xA;    	float4x4 World : WORLD&#xD;&#xA;    	&lt;&gt;;&#xD;&#xA;    	&#xD;&#xA;    	float4 SpecularColor : SPECULAR&#xD;&#xA;    	&lt;&#xD;&#xA;    		string UIName = &quot;Specular Color&quot;;&#xD;&#xA;    		string UIWidget = &quot;Color&quot;;&#xD;&#xA;    	&gt; = {1.0, 1.0, 1.0, 1.0};&#xD;&#xA;    	&#xD;&#xA;    	float SpecularPower : SPECULARPOWER&#xD;&#xA;    	&lt;&#xD;&#xA;    		string UIName = &quot;Specular Power&quot;;&#xD;&#xA;    		string UIWidget = &quot;slider&quot;;&#xD;&#xA;    		float UIMin = 1.0;&#xD;&#xA;    		float UIMax = 255.0;&#xD;&#xA;    		float UIStep = 1.0;&#xD;&#xA;    	&gt; = {25.0};&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    RasterizerState RasterOpt&#xD;&#xA;    {&#xD;&#xA;    	CullMode = NONE;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VS_INPUT&#xD;&#xA;    {&#xD;&#xA;    	float4 ObjPos : POSITION;&#xD;&#xA;    	float3 Normal : NORMAL;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    struct VS_OUTPUT&#xD;&#xA;    {&#xD;&#xA;    	float4 Pos : SV_Position;&#xD;&#xA;    	float3 Normal : NORMAL;&#xD;&#xA;    	float3 LightDir : LIGHTDIR;&#xD;&#xA;    	float3 ViewDir : VIEWDIR;&#xD;&#xA;    };&#xD;&#xA;    &#xD;&#xA;    VS_OUTPUT vertex_shader(VS_INPUT In)&#xD;&#xA;    {&#xD;&#xA;    	VS_OUTPUT Out = (VS_OUTPUT)0;&#xD;&#xA;    	&#xD;&#xA;    	Out.Pos = mul(In.ObjPos, WVP);&#xD;&#xA;    	Out.Normal = normalize(mul(float4(In.Normal,0), World).xyz);&#xD;&#xA;    	Out.LightDir = normalize(-LightDirection);&#xD;&#xA;    	&#xD;&#xA;    	float3 worldPos = mul(In.ObjPos, World).xyz;&#xD;&#xA;    	Out.ViewDir = normalize(CameraPosition - worldPos);&#xD;&#xA;    	&#xD;&#xA;    	return Out;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float4 pixel_shader(VS_OUTPUT In) : SV_Target&#xD;&#xA;    {&#xD;&#xA;    	float4 Out = (float4)0;&#xD;&#xA;    	&#xD;&#xA;    	float3 normal = In.Normal;&#xD;&#xA;    	float3 lightDir = In.LightDir;&#xD;&#xA;    	float3 viewDir = In.ViewDir;&#xD;&#xA;    	&#xD;&#xA;    	float n_dot_l = dot(lightDir, normal);&#xD;&#xA;    	&#xD;&#xA;    	float4 texColor = float4(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    		&#xD;&#xA;    	float3 specular = (float3)0;&#xD;&#xA;    	&#xD;&#xA;    	if (n_dot_l &gt; 0)&#xD;&#xA;    	{&#xD;&#xA;    		float3 reflectionVec = normalize(2 * n_dot_l * normal - lightDir);		&#xD;&#xA;    		specular = SpecularColor.rgb * SpecularColor.a * min(pow(saturate(dot(reflectionVec, viewDir)), SpecularPower), texColor.a);&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	Out.rgb = specular;&#xD;&#xA;    	Out.a = 1.0f;&#xD;&#xA;    	&#xD;&#xA;    	return Out;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    technique10 phongSpec&#xD;&#xA;    {&#xD;&#xA;    	pass p0&#xD;&#xA;    	{&#xD;&#xA;    		SetVertexShader(CompileShader(vs_4_0, vertex_shader()));&#xD;&#xA;    		SetGeometryShader(NULL);&#xD;&#xA;    		SetPixelShader(CompileShader(ps_4_0, pixel_shader()));&#xD;&#xA;    		SetRasterizerState(RasterOpt);&#xD;&#xA;    	}&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    //////////////////////////////////////////////////////////////////&#xD;&#xA;    ////////////////BLINN PHONG PIXEL SHADER//////////////////////////&#xD;&#xA;    //////////////////////////////////////////////////////////////////&#xD;&#xA;    &#xD;&#xA;    float4 pixel_shader(VS_OUTPUT In) : SV_Target&#xD;&#xA;    {&#xD;&#xA;    	float4 Out = (float4)0;&#xD;&#xA;    	&#xD;&#xA;    	float3 normal = normalize(In.Normal);&#xD;&#xA;    	float3 lightDir = normalize(In.LightDir);&#xD;&#xA;    	float3 viewDir = normalize(In.ViewDir);&#xD;&#xA;    	&#xD;&#xA;    	float n_dot_l = dot(lightDir, normal);&#xD;&#xA;    	&#xD;&#xA;    	float4 texColor = float4(0.0, 0.0, 0.0, 1.0);&#xD;&#xA;    		&#xD;&#xA;    	float3 specular = (float3)0;&#xD;&#xA;    	&#xD;&#xA;    	if (n_dot_l &gt; 0)&#xD;&#xA;    	{&#xD;&#xA;    		float3 halfVec = normalize(lightDir + viewDir);&#xD;&#xA;    		specular = SpecularColor.rgb * SpecularColor.a * min(pow(saturate(dot(normal, halfVec)), SpecularPower), texColor.a);&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    	Out.rgb = specular;&#xD;&#xA;    	Out.a = 1.0f;&#xD;&#xA;    	&#xD;&#xA;    	return Out;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Kd4Ai.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/lkHQE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40704" PostHistoryTypeId="1" PostId="13483" RevisionGUID="5eecca09-f67f-4ba4-8493-1ccf95d3ca62" CreationDate="2023-05-22T13:58:51.650" UserId="19984" Text="BlinnPhong sphere edges look worse than Phong. Am I doing it wrong? (code and pictures included)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40705" PostHistoryTypeId="3" PostId="13483" RevisionGUID="5eecca09-f67f-4ba4-8493-1ccf95d3ca62" CreationDate="2023-05-22T13:58:51.650" UserId="19984" Text="|shader|lighting|hlsl|reflection|pixel-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40706" PostHistoryTypeId="2" PostId="13484" RevisionGUID="a022f104-06e9-445e-8af6-16a4cc2592c9" CreationDate="2023-05-23T07:06:15.030" UserId="19990" Text="I have the following code in python using the vedo package &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;mesh.lighting(style='plastic', ambient=None, diffuse=None, specular=None,&#xD;&#xA;              specular_color=None, specular_power=None, metallicity=None, roughness=None)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I know that I need a combination for ambient, diffuse, specular value to creating phong lighting. How do I determine these values? And how do I know I have created phong lighting? " ContentLicense="CC BY-SA 4.0" />
  <row Id="40708" PostHistoryTypeId="1" PostId="13484" RevisionGUID="a022f104-06e9-445e-8af6-16a4cc2592c9" CreationDate="2023-05-23T07:06:15.030" UserId="19990" Text="How to pick values of ambient, diffuse, specular for Phong Lighting?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40709" PostHistoryTypeId="3" PostId="13484" RevisionGUID="a022f104-06e9-445e-8af6-16a4cc2592c9" CreationDate="2023-05-23T07:06:15.030" UserId="19990" Text="|lighting|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40710" PostHistoryTypeId="2" PostId="13485" RevisionGUID="f7daba9b-d341-4253-a288-aa131db64326" CreationDate="2023-05-23T12:58:31.850" UserDisplayName="user1703" Text="From the manual:&#xD;&#xA;&#xD;&#xA;- `style` : (str) preset style, options are [metallic, plastic, shiny,&#xD;&#xA;   glossy, ambient, off] &#xD;&#xA;- `ambient` : (float) ambient fraction of emission&#xD;&#xA;   [0-1]&#xD;&#xA;- `diffuse` : (float) emission of diffused light in fraction [0-1]&#xD;&#xA; &#xD;&#xA;-  `specular` : (float) fraction of reflected light [0-1]&#xD;&#xA;- `specular_power` :&#xD;&#xA;   (float) precision of reflection [1-100]&#xD;&#xA;- `specular_color` : (color) color that is being reflected by the surface&#xD;&#xA;&#xD;&#xA;Set the `ambient`/`diffuse`/`specular` parameters to increasing values one at a time and observe the effect. A Phong model requires a combination of the three components. Also play with `specular_power` and `specular_color`  (only relevant with nonzero specular).&#xD;&#xA;&#xD;&#xA;I could not find any information on `metallicity` nor `roughness`. Have a try with values in range [0-1].&#xD;&#xA;&#xD;&#xA;It is possible (likely) that the preset styles enforce predefined sets of parameter values, and to use your own the `off` mode is required." ContentLicense="CC BY-SA 4.0" />
  <row Id="40716" PostHistoryTypeId="2" PostId="13487" RevisionGUID="5584c907-1256-4365-a9ab-db20a0dcd74c" CreationDate="2023-05-24T13:24:05.407" UserId="17270" Text="Usually a ray casting algorithm is used to determine whether a point is indide or outside a mesh. But this algorithm is slow.&#xD;&#xA;Is there any fast algorithm to do this check?&#xD;&#xA;My input mesh is a triangular closed mesh.&#xD;&#xA;this question has been previously asked here: https://stackoverflow.com/questions/6554313/algorithm-for-determining-whether-a-point-is-inside-a-3d-mesh&#xD;&#xA;.&#xD;&#xA;The author solved the problem, but I don't understand the solution he/she provided. " ContentLicense="CC BY-SA 4.0" />
  <row Id="40718" PostHistoryTypeId="1" PostId="13487" RevisionGUID="5584c907-1256-4365-a9ab-db20a0dcd74c" CreationDate="2023-05-24T13:24:05.407" UserId="17270" Text="fast algorithm to check if a point is inside/outside mesh" ContentLicense="CC BY-SA 4.0" />
  <row Id="40719" PostHistoryTypeId="3" PostId="13487" RevisionGUID="5584c907-1256-4365-a9ab-db20a0dcd74c" CreationDate="2023-05-24T13:24:05.407" UserId="17270" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40720" PostHistoryTypeId="2" PostId="13488" RevisionGUID="18a7e223-761f-46dd-a2c5-80b120336094" CreationDate="2023-05-24T16:39:54.473" UserId="13273" Text="In case your triangles are all directed CW or all directed CCW the following algorithm works very fast:&#xD;&#xA;&#xD;&#xA;When rendering with a orthographic projection from one direction (for example into direction X) with disabled depth test, each triangle which span an area will be rasterized. Inside the fragment shader you'll receive the depth value and the triangle direction ('bool gl_FrontFacing').&#xD;&#xA;These two information can be stored as a node to a linked list in a SHADER_STORAGE_BUFFER per pixel.&#xD;&#xA;&#xD;&#xA;After the rendering you can sort the linked list by the pixels depth values.&#xD;&#xA;&#xD;&#xA;By iteration of a singe pixel you should receive a front face node directly followed by a back face node.&#xD;&#xA;&#xD;&#xA;In case two following nodes are front face, only keep the node, which is closer to the camera. For two following back face nodes, keep the further away node and delete the other. This phenomenon usually appear on edges, where two triangles share the same edge.&#xD;&#xA;&#xD;&#xA;Now you can check your 3D point by first calculating the pixel position of the point. Now find out between which nodes of the pixel the point belongs. &#xD;&#xA;&#xD;&#xA;In case the point is closer to the camera as the first node, it is outside. &#xD;&#xA;&#xD;&#xA;In case the point is further away than the last node, it is outside. &#xD;&#xA;&#xD;&#xA;In case the point is between a front and back node, it is inside. &#xD;&#xA;&#xD;&#xA;In case the point is between a back and a front node, it is outside. &#xD;&#xA;&#xD;&#xA;Now after understanding how the algorithm works, I've to say, that you need to do that three times: in X direction, in Y direction and in Z direction. &#xD;&#xA;&#xD;&#xA;If the point is outside of all 3 tests, it is outside. Otherwise it is inside. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40722" PostHistoryTypeId="5" PostId="13488" RevisionGUID="5cc50659-f1dc-4aea-8723-e5f4acd5021d" CreationDate="2023-05-24T16:45:50.590" UserId="13273" Comment="added 18 characters in body" Text="In case your triangles are all directed CW or all directed CCW the following algorithm works very fast:&#xD;&#xA;&#xD;&#xA;When rendering with a orthographic projection from one direction (for example into direction X) with disabled depth test, each triangle which span an area will be rasterized. Inside the fragment shader you'll receive the depth value and the triangle direction ('bool gl_FrontFacing').&#xD;&#xA;These two information can be stored as a node to a linked list in a SHADER_STORAGE_BUFFER per pixel.&#xD;&#xA;&#xD;&#xA;After the rendering you can sort the linked list by the pixels depth values.&#xD;&#xA;&#xD;&#xA;By iteration of a singe pixel you should receive a front face node directly followed by a back face node.&#xD;&#xA;&#xD;&#xA;In case two following nodes are front face, only keep the node, which is closer to the camera. For two following back face nodes, keep the further away node and delete the other. This phenomenon usually appear on edges, where two triangles share the same edge.&#xD;&#xA;&#xD;&#xA;Now you can check your 3D point by first calculating the pixel position of the point. Now find out between which nodes of the pixel the point belongs. (the depth value) &#xD;&#xA;&#xD;&#xA;In case the point is closer to the camera as the first node, it is outside. &#xD;&#xA;&#xD;&#xA;In case the point is further away than the last node, it is outside. &#xD;&#xA;&#xD;&#xA;In case the point is between a front and back node, it is inside. &#xD;&#xA;&#xD;&#xA;In case the point is between a back and a front node, it is outside. &#xD;&#xA;&#xD;&#xA;Now after understanding how the algorithm works, I've to say, that you need to do that three times: in X direction, in Y direction and in Z direction. &#xD;&#xA;&#xD;&#xA;If the point is outside of all 3 tests, it is outside. Otherwise it is inside. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40723" PostHistoryTypeId="5" PostId="13488" RevisionGUID="cce3b27c-67f9-47c9-bbe5-c44cfcdac6d4" CreationDate="2023-05-24T18:11:24.110" UserId="13273" Comment="added 598 characters in body" Text="If your triangles are all aligned to CW or CCW, the following algorithm works very quickly:&#xD;&#xA;&#xD;&#xA;When rendering the entire mesh with an orthographic projection from one direction (e.g., in the X direction) with the depth test disabled, each triangle that spans an area is rasterized. Inside the fragment shader, the depth value and the triangle direction ('bool gl_FrontFacing') are obtained.&#xD;&#xA;These two information can be stored as a node in a linked list in a SHADER_STORAGE_BUFFER per pixel.&#xD;&#xA;&#xD;&#xA;After rendering, one has to sort the linked lists by the depth values of the pixels.&#xD;&#xA;&#xD;&#xA;When iterating a single pixel list, one should get a frontface node immediately followed by a backface node.&#xD;&#xA;&#xD;&#xA;For two consecutive frontface nodes, keep only the node that is closer to the camera. For two consecutive backface nodes, keep the node which is farther away and delete the other. This phenomenon usually occurs at edges where two triangles share the same edge.&#xD;&#xA;&#xD;&#xA;Now you can check your 3D point by first calculating the pixel position of the point. Now find out between which nodes of the pixel the point is located. (the depth value) &#xD;&#xA;&#xD;&#xA;If the point is closer to the camera than the first node, it is outside. &#xD;&#xA;&#xD;&#xA;If the point is further away than the last node, it is outside. &#xD;&#xA;&#xD;&#xA;If the point is between a front and a back node, it is inside. &#xD;&#xA;&#xD;&#xA;If the point is between a back node and a front node, it is outside. &#xD;&#xA;&#xD;&#xA;Now that we understand how the algorithm works, I have to say that you have to do this three times: in the X direction, in the Y direction, and in the Z direction. &#xD;&#xA;&#xD;&#xA;If the point is outside in all 3 direction tests, it is outside. Otherwise it is inside. &#xD;&#xA;&#xD;&#xA;**Why do you have to do this three times?** If a triangle is orthogonal to the X direction, it will not be rendered. If you do it in all (X, Y, Z) directions, each triangle will span an area in at least one of the three frames.&#xD;&#xA;&#xD;&#xA;Additional positive effects:&#xD;&#xA;After creating the three images (each with resolution_x * rosolution_y linked lists), you can easily check as many 3D points as you want. The size of a single linked list within the image is very small (depends on the complexity of your mesh), so finding the correct position within the nodes can be very fast." ContentLicense="CC BY-SA 4.0" />
  <row Id="40724" PostHistoryTypeId="5" PostId="13488" RevisionGUID="3474adaa-b50a-4c96-a3a4-78e0d35236e1" CreationDate="2023-05-24T21:02:02.787" UserId="13273" Comment="added 154 characters in body" Text="If your triangles are all aligned to CW or CCW, the following algorithm works very quickly:&#xD;&#xA;&#xD;&#xA;When rendering the entire mesh with an orthographic projection from one direction (e.g., in the X direction) with the depth test disabled, each triangle that spans an area is rasterized. Inside the fragment shader, the depth value and the triangle direction ('bool gl_FrontFacing') are obtained.&#xD;&#xA;These two information can be stored as a node in a linked list in a SHADER_STORAGE_BUFFER per pixel.&#xD;&#xA;&#xD;&#xA;After rendering, one has to sort the linked lists by the depth values of the pixels.&#xD;&#xA;&#xD;&#xA;When iterating a single pixel list, one should get a frontface node immediately followed by a backface node.This is not only the case, it can appear, that two following face directions are same. This usually occurs at edges were two triangles share the same edge. This need to be corrected by deleting the following one:&#xD;&#xA;For two consecutive frontface nodes, keep only the node that is closer to the camera. For two consecutive backface nodes, keep the node which is farther away and delete the other.&#xD;&#xA;&#xD;&#xA;Now you can check your 3D point by first calculating the pixel position of the point. Now find out between which nodes of the pixel the point is located. (the depth value) &#xD;&#xA;&#xD;&#xA;If the point is closer to the camera than the first node, it is outside. &#xD;&#xA;&#xD;&#xA;If the point is further away than the last node, it is outside. &#xD;&#xA;&#xD;&#xA;If the point is between a front and a back node, it is inside. &#xD;&#xA;&#xD;&#xA;If the point is between a back node and a front node, it is outside. &#xD;&#xA;&#xD;&#xA;Now that we understand how the algorithm works, I have to say that you have to do this three times: in the X direction, in the Y direction, and in the Z direction. &#xD;&#xA;&#xD;&#xA;If the point is outside in all 3 direction tests, it is outside. Otherwise it is inside. &#xD;&#xA;&#xD;&#xA;**Why do you have to do this three times?** If a triangle is aligned in the X direction, it will not be rendered. If you do it in all (X, Y, Z) directions, each triangle will span an area in at least one of the three frames.&#xD;&#xA;&#xD;&#xA;Additional positive effects:&#xD;&#xA;After creating the three images (each with resolution_x * rosolution_y linked lists) as preprocessing step, you can check very fast if 3d Points are inside the mesh. The size of a single linked list within the image is very small (depends on the complexity of your mesh), so finding the correct position within the nodes can be very fast." ContentLicense="CC BY-SA 4.0" />
  <row Id="40725" PostHistoryTypeId="2" PostId="13489" RevisionGUID="25b41031-4661-4f31-b256-1b56db29c5a0" CreationDate="2023-05-24T21:51:18.110" UserId="7952" Text="A very fast method is to convert the mesh to a signed distance field by computing a tight fighting bounding box for the mesh. Then subdividing that box into evenly sized &quot;voxels&quot; in the x,y,z direction. Finally compute the distance from the center of each voxel to the nearest point on the mesh. Points outside the mesh have values of 0 and points inside have values of 1.&#xD;&#xA;&#xD;&#xA;To check a point, first check the point against the AABB, if it is inside, simply read the corresponding point from the SDF. It's value tells if the point is inside our outside the mesh.&#xD;&#xA;&#xD;&#xA;Since a zero or a one is all we need the SDF can be reduced to a bit field which allows for fine grained SDF fields.&#xD;&#xA;&#xD;&#xA;The biggest downside of this method is that generating the SDF can be slow. But a basic implementation is easy to write. (there are some nice compute shader techniques to speed this up considerably) And a very fine grained field can consume a lot of memory even if we are only using 1 bit for each voxel.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40727" PostHistoryTypeId="5" PostId="13487" RevisionGUID="20f6956d-9a7b-426a-b124-6dc9e81528a9" CreationDate="2023-05-24T23:53:27.237" UserId="17270" Comment="added 347 characters in body" Text="Usually a ray casting algorithm is used to determine whether a point is indide or outside a mesh. But this algorithm is slow.&#xD;&#xA;Is there any fast algorithm to do this check?&#xD;&#xA;My input mesh is a triangular closed mesh.&#xD;&#xA;This question has been previously asked here: https://stackoverflow.com/questions/6554313/algorithm-for-determining-whether-a-point-is-inside-a-3d-mesh&#xD;&#xA;.&#xD;&#xA;The author solved the problem, but I don't understand the solution he/she provided. &#xD;&#xA;&#xD;&#xA;Update:&#xD;&#xA;there's another method mentioned in https://www.reddit.com/r/Houdini/comments/u2co9i/the_most_efficient_way_to_test_if_a_point_is/. The algorithm is to find a nearest point on mesh, let's call the B, and the point A. The algorithm simply tests the dot product of AB and the normal of B. What's the potential downside of this algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40728" PostHistoryTypeId="5" PostId="13487" RevisionGUID="04436da1-e746-4690-a298-b37014650145" CreationDate="2023-05-25T00:14:18.417" UserId="17270" Comment="added 11 characters in body" Text="Usually a ray casting algorithm is used to determine whether a point is indide or outside a mesh. But this algorithm is slow.&#xD;&#xA;Is there any fast algorithm to do this check?&#xD;&#xA;My input mesh is a triangular closed mesh.&#xD;&#xA;This question has been previously asked here: https://stackoverflow.com/questions/6554313/algorithm-for-determining-whether-a-point-is-inside-a-3d-mesh&#xD;&#xA;.&#xD;&#xA;The author solved the problem, but I don't understand the solution he/she provided. &#xD;&#xA;&#xD;&#xA;Update:&#xD;&#xA;there's another method mentioned in https://www.reddit.com/r/Houdini/comments/u2co9i/the_most_efficient_way_to_test_if_a_point_is/. The algorithm is to find a nearest point on mesh, let's call this nearest point B, and the point to test A. The algorithm simply tests the dot product of AB and the normal of B. What's the potential downside of this algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40729" PostHistoryTypeId="5" PostId="13487" RevisionGUID="3fb9cf9b-fce2-4f8e-8f70-dc3fb86ea669" CreationDate="2023-05-25T02:27:54.220" UserId="17270" Comment="added 61 characters in body" Text="Usually a ray casting algorithm is used to determine whether a point is indide or outside a mesh. But this algorithm is slow.&#xD;&#xA;Is there any fast algorithm to do this check?&#xD;&#xA;My input mesh is a triangular closed mesh.&#xD;&#xA;This question has been previously asked here: https://stackoverflow.com/questions/6554313/algorithm-for-determining-whether-a-point-is-inside-a-3d-mesh&#xD;&#xA;.&#xD;&#xA;The author solved the problem, but I don't understand the solution he/she provided. &#xD;&#xA;&#xD;&#xA;Update:&#xD;&#xA;there's another method mentioned in https://www.reddit.com/r/Houdini/comments/u2co9i/the_most_efficient_way_to_test_if_a_point_is/. The algorithm is to find a nearest point on mesh, let's call this nearest point B, and the point to test A. The algorithm simply tests the dot product of AB and the normal of B. However, this seems to only work with convex mesh. The algorithm should handle all different kinds of meshes." ContentLicense="CC BY-SA 4.0" />
  <row Id="40730" PostHistoryTypeId="2" PostId="13490" RevisionGUID="e3cee9a6-65fa-4e3c-85f6-cc3179bf207b" CreationDate="2023-05-25T03:44:51.953" UserId="20000" Text="A friend and I are considering using webgpu native (more specifically [C++ bindings][1]) for a project. We were wondering, since WebGPU likely runs on top of Vulkan XOR DirectX12 XOR Metal at any given time, and others have called it a &quot;union&quot; (interpreting the word in the set-theoretic sense) of the three if there were significant feature/functionality gaps with WebGPU as compared with these APIs? In other words, if Vulkan has a feature DirectX 12 does not or vise-versa, does WebGPU exclude it?&#xD;&#xA;What I am asking is: *are there significant features (or functionality differences) these other APIs have, that WebGPU does not, or do they have feature parity?*&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;NOTE: There is not webgpu tag yet so I did not put it here&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/eliemichel/WebGPU-Cpp" ContentLicense="CC BY-SA 4.0" />
  <row Id="40732" PostHistoryTypeId="1" PostId="13490" RevisionGUID="e3cee9a6-65fa-4e3c-85f6-cc3179bf207b" CreationDate="2023-05-25T03:44:51.953" UserId="20000" Text="Does WebGPU Have Significant Feature/Functionality Gaps As Compared to Vulkan/DirectX12/Metal?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40733" PostHistoryTypeId="3" PostId="13490" RevisionGUID="e3cee9a6-65fa-4e3c-85f6-cc3179bf207b" CreationDate="2023-05-25T03:44:51.953" UserId="20000" Text="|vulkan|directx12|metal|api|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40734" PostHistoryTypeId="12" PostId="13490" RevisionGUID="20d6e5c5-0279-4c0a-bb8e-d3d47d527255" CreationDate="2023-05-25T03:49:18.367" UserId="20000" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:20000,&quot;DisplayName&quot;:&quot;The Floating Brain&quot;}],&quot;DeleteType&quot;:1}" />
  <row Id="40735" PostHistoryTypeId="13" PostId="13490" RevisionGUID="3162c1c0-0fa7-4550-9b16-1fb01f0898ff" CreationDate="2023-05-25T03:49:42.803" UserId="20000" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:20000,&quot;DisplayName&quot;:&quot;The Floating Brain&quot;}]}" />
  <row Id="40736" PostHistoryTypeId="50" PostId="12900" RevisionGUID="416debcb-6bb6-4673-875c-533bdb1c7adf" CreationDate="2023-05-25T07:01:45.193" UserId="-1" />
  <row Id="40737" PostHistoryTypeId="2" PostId="13491" RevisionGUID="c4090556-e0b4-4c03-9ca5-e10e3b34331e" CreationDate="2023-05-25T11:49:41.750" UserId="19431" Text="Looking at the output of the angle of this double pendulum made me think this was a good candidate for generating realistic looking terrain profiles.  I can't be the first to notice this so I was wondering if this is used by anyone and if not, why not?&#xD;&#xA;&#xD;&#xA;[![Angle of first pendulum in double pendulum showing interesting terrain like profile][1]][1]&#xD;&#xA;&#xD;&#xA;[![Angle of second pendulum in double pendulum also showing interesting terrain like profile but with steeper sides][2]][2]&#xD;&#xA;&#xD;&#xA;[Link to Modelica Playground][3] where this is demonstrated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2aQqZ.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/xPbRd.png&#xD;&#xA;  [3]: https://playground.modelica.university/?model=ICBjb25zdGFudCBSZWFsIHNwZWVkPTAuMjsKICBjb25zdGFudCBSZWFsIGdyYXZpdHkodW5pdD0ibS9zMiIpPTkuOCAqIHNwZWVkOwogIGNvbnN0YW50IFJlYWwgbGVuZ3RoKHVuaXQ9Im0iKT0xOwogIGNvbnN0YW50IFJlYWwgbGVuZ3RoMih1bml0PSJtIik9MTsKICBjb25zdGFudCBSZWFsIG1hc3ModW5pdD0ia2ciKT00OwogIGNvbnN0YW50IFJlYWwgbWFzczIodW5pdD0ia2ciKT0xOwogIFJlYWwgYW5nbGUodW5pdD0icmFkIik7CiAgUmVhbCBtb21lbnR1bSh1bml0PSJrZy5tL3MiKTsKICBSZWFsIGFuZ2xlMih1bml0PSJyYWQiKTsKICBSZWFsIG1vbWVudHVtMih1bml0PSJrZy5tL3MiKTsKCmluaXRpYWwgZXF1YXRpb24KICBhbmdsZSA9IDEzMCAqICgzLjE0MiAvIDE4MCk7CiAgbW9tZW50dW0gPSAwOwogIGFuZ2xlMiA9IDA7IC8vIHJlbGF0aXZlIHRvIHZlcnRpY2FsCiAgbW9tZW50dW0yID0gMDsKZXF1YXRpb24KICBkZXIoYW5nbGUpID0gKDYvKG1hc3MgKiBsZW5ndGheMikpICogKCgyICogbW9tZW50dW0gLSAzICogY29zKGFuZ2xlIC0gYW5nbGUyKSAqIG1vbWVudHVtMikvKDE2IC0gOSAqIGNvcyhhbmdsZSAtIGFuZ2xlMileMikpOwogIGRlcihtb21lbnR1bSkgPSAtMC41ICogbWFzcyAqIGxlbmd0aF4yICogKGRlcihhbmdsZSkgKiBkZXIoYW5nbGUyKSAqIHNpbihhbmdsZSAtIGFuZ2xlMikgKyAoMyAqIChncmF2aXR5IC8gbGVuZ3RoKSAqIHNpbihhbmdsZSkpKTsKCiAgZGVyKGFuZ2xlMikgPSAoNi8obWFzczIgKiBsZW5ndGgyXjIpKSAqICgoOCAqIG1vbWVudHVtMiAtIDMgKiBjb3MoYW5nbGUgLSBhbmdsZTIpICogbW9tZW50dW0pLygxNiAtIDkgKiBjb3MoYW5nbGUgLSBhbmdsZTIpXjIpKTsKICBkZXIobW9tZW50dW0yKSA9IC0wLjUgKiBtYXNzMiAqIGxlbmd0aDJeMiAqICgtZGVyKGFuZ2xlKSAqIGRlcihhbmdsZTIpICogc2luKGFuZ2xlIC0gYW5nbGUyKSArICgzICogKGdyYXZpdHkgLyBsZW5ndGgyKSAqIHNpbihhbmdsZTIpKSk7CgogIC8vYW5ub3RhdGlvbihleHBlcmltZW50KFN0YXJ0VGltZT0wLFN0b3BUaW1lPTIwMCkpOyAvLyB0b2RvIGZpbmQgb3V0IGhvdyB0aGlzIHdvcmtzCg%253D%253D&amp;report=QSBwZW5kdWx1bSBpbiBNb2RlbGljYS4gIFByZXNzIHRoZSAiUGxheSIgYnV0dG9uIHRvIGFuaW1hdGUuCgo8c3ZnIGhlaWdodD0iNDAwIiB3aWR0aD0iMTAwJSIgdmlld2JveD0iLTIwMCAtMjAwIDQwMCA0MDAiPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIxMCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIzIiBmaWxsPSJyZWQiIC8%252BCiAgPGcgdHJhbnNmb3JtID0gInRyYW5zbGF0ZSgwLCAwKSByb3RhdGUoe3sgOTAgKyAobm93LmFuZ2xlICogKDE4MC8zLjE0MikpIH19IDAgMCkiPgogICAgPHJlY3QgeD0iMCIgeT0iLTMiIHdpZHRoPSIxMDAiIGhlaWdodD0iNiIgc3Ryb2tlPSJibGFjayIgLz4KICAgIDxnIHRyYW5zZm9ybSA9ICJ0cmFuc2xhdGUoMTAwLCAwKSByb3RhdGUoe3sgbm93LmFuZ2xlMiAqICgxODAvMy4xNDIpIH19IDAgMCkiPgogICAgICA8cmVjdCB4PSIwIiB5PSItMyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSI2IiBzdHJva2U9ImJsYWNrIiAvPgogICAgPC9nPiAKICA8L2c%252BCjwvc3ZnPgoKPGNoYXJ0IHNpZ25hbHM9ImFuZ2xlIj48L2NoYXJ0Pgo8Y2hhcnQgc2lnbmFscz0iYW5nbGUyIj48L2NoYXJ0PgoKPGNoYXJ0IHNpZ25hbHM9InZlbG9jaXR5Ij48L2NoYXJ0Pgo8Y2hhcnQgc2lnbmFscz0idmVsb2NpdHkyIj48L2NoYXJ0Pgo%253D" ContentLicense="CC BY-SA 4.0" />
  <row Id="40739" PostHistoryTypeId="1" PostId="13491" RevisionGUID="c4090556-e0b4-4c03-9ca5-e10e3b34331e" CreationDate="2023-05-25T11:49:41.750" UserId="19431" Text="Are systems like double pendulum used for generating terrain?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40740" PostHistoryTypeId="3" PostId="13491" RevisionGUID="c4090556-e0b4-4c03-9ca5-e10e3b34331e" CreationDate="2023-05-25T11:49:41.750" UserId="19431" Text="|algorithm|noise|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40741" PostHistoryTypeId="2" PostId="13492" RevisionGUID="e7d34d69-1fc9-4b18-b3ec-5305e8a462c0" CreationDate="2023-05-25T12:54:34.397" UserId="13273" Text="for the creation of a 2-dimensional terrains it seems to work well, as your picture shows most clearly. &#xD;&#xA;&#xD;&#xA;But it does not work for 3-dimensional terrains, because the behavior of a double pendulum is very complex. Thus, minimal changes in the initial values lead to completely different results. (see figure 1)&#xD;&#xA;&#xD;&#xA;[![Insert image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** two results of a double pendulum with very small change of initial position.&#xD;&#xA;&#xD;&#xA;So if you simulate two adjacent strips of your terrain, the elevation values will not be comparable.&#xD;&#xA;&#xD;&#xA;Mostly procedurally generated terrains are based on 2D/3D noise functions (e.g. Perlin noise, Simplex noise, ...), sometimes combined with a Voronoi diagram. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cA41l.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40743" PostHistoryTypeId="5" PostId="13492" RevisionGUID="bc12403e-2e5f-4897-b3ab-831fbec8a290" CreationDate="2023-05-25T13:09:35.453" UserId="13273" Comment="added 26 characters in body" Text="for the creation of a 2-dimensional terrains it seems to work well, as your picture shows most clearly. &#xD;&#xA;&#xD;&#xA;But it does not work for 3-dimensional terrains, because the behavior of a double pendulum is very complex. Thus, minimal changes in the initial values lead to completely different results. (see figure 1)&#xD;&#xA;&#xD;&#xA;[![Insert image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** two results of a double pendulum with very small change of initial position.&#xD;&#xA;&#xD;&#xA;So if you simulate two adjacent strips of your terrain, the elevation values will not be comparable.&#xD;&#xA;&#xD;&#xA;Terrains can be procedurally created in different ways.&#xD;&#xA;For example based on 2D/3D noise functions (e.g. Perlin noise, Simplex noise, ...), sometimes combined with a Voronoi diagram. &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cA41l.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40744" PostHistoryTypeId="50" PostId="10509" RevisionGUID="2e881ae9-d262-475e-95ff-374a3991f2ed" CreationDate="2023-05-26T07:06:40.787" UserId="-1" />
  <row Id="40745" PostHistoryTypeId="2" PostId="13493" RevisionGUID="42cf47f0-559e-4afb-a534-83d8eee553fd" CreationDate="2023-05-26T07:29:56.197" UserId="20008" Text="As a layperson in the field of computer graphics, I rarely see practical applications of algorithms that take 3D geometry as the input (along with some camera and lighting parameters) and output the 2D geometry of a projection, with (self-)occlusion removed. This seems to be uncommon even for simple 3D geometry such as triangle or tetrahedral meshes, let alone for 3D spline surfaces. At the same time, I can see demand for this: Architects, for instance, might like the ability to export SVG files from their CAD software, and scientists might prefer to have their 3D graphs as SVG files. In contrast, algorithms that take 3D geometry as the input and output a rasterized 2D image are very common. We even have special hardware for these.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My questions are: &#xD;&#xA;&#xD;&#xA;1. **What are real practical applications of 3D to 2D projection and occlusion handling?** For example, are such algorithms typically used as an intermediate step before rasterizing the projection views in CAD software?&#xD;&#xA;&#xD;&#xA;2. **What are obstacles?** (Does the form of projections of splines become too complex? Is the occlusion handling NP-hard for spline surfaces, and hard to approximate?)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40747" PostHistoryTypeId="1" PostId="13493" RevisionGUID="42cf47f0-559e-4afb-a534-83d8eee553fd" CreationDate="2023-05-26T07:29:56.197" UserId="20008" Text="What are real practical applications of 3D to 2D projection and occlusion handling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40748" PostHistoryTypeId="3" PostId="13493" RevisionGUID="42cf47f0-559e-4afb-a534-83d8eee553fd" CreationDate="2023-05-26T07:29:56.197" UserId="20008" Text="|geometry|projections|vector-graphics|occlusion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40749" PostHistoryTypeId="4" PostId="13493" RevisionGUID="94fa4d60-05f6-4278-b82b-2e40a8d37050" CreationDate="2023-05-26T07:38:28.380" UserId="20008" Comment="edited title" Text="What are applications of 3D geometry to 2D geometry projection and occlusion handling?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40750" PostHistoryTypeId="5" PostId="13493" RevisionGUID="94fa4d60-05f6-4278-b82b-2e40a8d37050" CreationDate="2023-05-26T07:38:28.380" UserId="20008" Comment="edited title" Text="As a layperson in the field of computer graphics, I rarely see practical applications of algorithms that take 3D geometry as the input (along with some camera and lighting parameters) and output the 2D geometry of a projection, with (self-)occlusion removed. This seems to be uncommon even for simple 3D geometry such as triangle or tetrahedral meshes, let alone for 3D spline surfaces. At the same time, I can see demand for this: Architects, for instance, might like the ability to export SVG files from their CAD software, and scientists might prefer to have their 3D graphs as SVG files. In contrast, algorithms that take 3D geometry as the input and output a rasterized 2D image are very common. We even have special hardware for these.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My questions are: &#xD;&#xA;&#xD;&#xA;1. **What are real practical applications of 3D geometry to 2D geometry projection and occlusion handling?** For example, are such algorithms typically used as an intermediate step before rasterizing the projection views in CAD software?&#xD;&#xA;&#xD;&#xA;2. **What are obstacles?** (Does the form of projections of splines become too complex? Is the occlusion handling NP-hard for spline surfaces, and hard to approximate?)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40751" PostHistoryTypeId="5" PostId="13493" RevisionGUID="c658bf8b-2460-4f35-8a1b-fe4fde73e57a" CreationDate="2023-05-26T10:59:38.247" UserId="20008" Comment="added 4 characters in body" Text="As a layperson in the field of computer graphics, I rarely see practical applications of algorithms that take 3D geometry as the input (along with some camera and lighting parameters) and output the 2D geometry of a projection, with (self-)occlusion removed. This seems to be uncommon even for simple 3D geometry such as triangle or tetrahedral meshes, let alone for 3D spline surfaces. &#xD;&#xA;&#xD;&#xA;At the same time, I can see demand for this: Architects, for instance, might like the ability to export SVG files from their CAD software, and scientists might prefer to have their 3D graphs as SVG files. &#xD;&#xA;&#xD;&#xA;In contrast, algorithms that take 3D geometry as the input and output a rasterized 2D image are very common. We even have special hardware for these.&#xD;&#xA;&#xD;&#xA;My questions are: &#xD;&#xA;&#xD;&#xA;1. **What are real practical applications of 3D geometry to 2D geometry projection and occlusion handling?** For example, are such algorithms typically used as an intermediate step before rasterizing the projection views in CAD software?&#xD;&#xA;&#xD;&#xA;2. **What are obstacles?** (Does the form of projections of splines become too complex? Is the occlusion handling NP-hard for spline surfaces, and hard to approximate?)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40752" PostHistoryTypeId="50" PostId="12995" RevisionGUID="47510c40-e5b7-4b6d-b42d-c8a2aed000b4" CreationDate="2023-05-26T13:01:25.220" UserId="-1" />
  <row Id="40753" PostHistoryTypeId="2" PostId="13494" RevisionGUID="ad93928b-5fbc-49ae-a3dd-edf466ede34a" CreationDate="2023-05-26T13:25:07.647" UserDisplayName="user1703" Text="Such a transformation is (was) mostly useful for line drawing. Because when rendering shaded surfaces, the 2D projections need to be painted with color gradients. These are quite difficult to compute even from a simple shading model when all you have are 2D vectorized primitives. (An exception is flat shading on polyhedral scenes).&#xD;&#xA;&#xD;&#xA;The line drawings were more fashionable before the raster display devices, such as random-scan CRT's, storage-tube screens and pen plotters, which are only able to draw lines and have no notion of writeable/readable pixels.&#xD;&#xA;&#xD;&#xA;Renderings with hidden-line removal (and also hidden surface removal) are pretty easy on polyhedral models. For general surfaces, they are much harder, due to the non-linear nature of the equations (in particular, intersections of algebraic curves need to be found, requiring numerical methods). In practice, the surfaces are meshed  to be approximated by polyhedra, even if not all mesh edges are drawn.&#xD;&#xA;&#xD;&#xA;Generation of the edges is sometimes used to enhance a classical rendering and/or produce a cartoon-like appearance.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40755" PostHistoryTypeId="5" PostId="13494" RevisionGUID="64865588-355b-4135-a7a3-68757f6d1062" CreationDate="2023-05-26T13:31:57.717" UserDisplayName="user1703" Comment="added 273 characters in body" Text="Such a transformation is (was) mostly useful for line drawing. Because when rendering shaded surfaces, the 2D projections need to be painted with color gradients. These are quite difficult to compute even from a simple shading model when all you have are 2D vectorized primitives. (An exception is flat shading on polyhedral scenes).&#xD;&#xA;&#xD;&#xA;The line drawings were more fashionable before the raster display devices, such as random-scan CRT's, storage-tube screens and pen plotters, which are only able to draw lines and have no notion of writeable/readable pixels.&#xD;&#xA;&#xD;&#xA;Renderings with hidden-line removal (and also hidden surface removal) are pretty easy on polyhedral models. For general surfaces, they are much harder, due to the non-linear nature of the equations (in particular, intersections of algebraic curves need to be found, requiring numerical methods). In practice, the surfaces are meshed to be approximated by polyhedra, even if not all mesh edges are drawn.&#xD;&#xA;&#xD;&#xA;For speed of display, wireframe models are still used (especially when no hardware acceleration is available). The speed is allowed by the fact that fewer pixels are drawn. Removing the hidden parts can further speed-up the display, but AFAIK, this is rarely done.&#xD;&#xA;&#xD;&#xA;Also, generation of the edges is sometimes used to enhance a classical rendering and/or produce a cartoon-like appearance.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40756" PostHistoryTypeId="5" PostId="13494" RevisionGUID="c27d187b-ac1c-44cd-a3d9-72fa7fdd9a47" CreationDate="2023-05-26T13:37:55.283" UserDisplayName="user1703" Comment="added 273 characters in body" Text="Such a transformation is (was) mostly useful for line drawing. Because when rendering shaded surfaces, the 2D projections need to be painted with color gradients. These are quite difficult to compute even from a simple shading model when all you have are 2D vectorized primitives. (An exception is flat shading on polyhedral scenes).&#xD;&#xA;&#xD;&#xA;The line drawings were more fashionable before the raster display devices, such as random-scan CRT's, storage-tube screens and pen plotters, which are only able to draw lines and have no notion of writeable/readable pixels.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Renderings with hidden-line removal (and also hidden surface removal) are pretty easy on polyhedral models. For general surfaces, they are much harder, due to the non-linear nature of the equations (in particular, intersections of algebraic curves need to be found, requiring numerical methods). In practice, the surfaces are meshed to be approximated by polyhedra, even if not all mesh edges are drawn.&#xD;&#xA;&#xD;&#xA;For speed of display, wireframe models are still used (especially when no hardware acceleration is available). The speed is allowed by the fact that fewer pixels are drawn. Removing the hidden parts can further speed-up the display, but AFAIK, this is rarely done.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;Also, generation of the edges is sometimes used to enhance a classical rendering and/or produce a cartoon-like appearance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/KY4IU.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/w3yd1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/ig5vj.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40757" PostHistoryTypeId="5" PostId="9116" RevisionGUID="dbcfd391-f166-4175-94aa-2dcb3699d5bc" CreationDate="2023-05-26T13:38:53.697" UserId="6" Comment="deleted 19 characters in body" Text="**Introduction to my project:**&#xD;&#xA;&#xD;&#xA;We are machine learning scientists and working on a biomedical system for tracking tongue for speech pathology using a technology called EMA (Electromagnetic articulography). In EMA a coil is attached to tongue surface using a glue and its 3D pos and orientation (roll and pitch) are read by EMA measurement system. So, you can track the coil and thus a point on the surface of tongue while speech is made. Also let's assume we have a low density 3D model of tongue for the patient is obtained by 3D MRI and we know exactly that which vertex in 3D model corresponds to the point that coil is attached.&#xD;&#xA;&#xD;&#xA;It would be very valuable for our research if we can visualize the tongue for the patient. But the issue is that we just track 1 or 2 points on the tongue but our 3D model has more than 100 vertices which are not tracked. Now, we think it might be possible to estimate the position of those point given these two points.&#xD;&#xA;&#xD;&#xA;**Here are some of the facts that we think it should be possible:**&#xD;&#xA;&#xD;&#xA; 1. Although tongue is not a solid object, it has a degree of rigidity thus the position of these 100 vertexes are correlated by physics For example how much they can be stretched or bent (Something like spring and mass model in physics). &#xD;&#xA; 2. by looking at a training set of 3D models for tongue during production of different sounds, we might say that the position of vertexes are not pure random and there is a distribution for them which might be estimated using the training dataset (sequence of MRI 3D models). &#xD;&#xA; 3.  we might assume that in our presentation the tongue can have just a bent toward the palate to simplify the modeling problem. or a 2D profile of tongue (like the line at the center) is enough for modeling. or any simplification that we can make. &#xD;&#xA;&#xD;&#xA;**Now my question:** &#xD;&#xA;&#xD;&#xA;What do you know in computer graphics literature which resembles to our problem (any model, method, tool, software, library,....)? What is your suggestion for us to do this task in more efficient way?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40758" PostHistoryTypeId="2" PostId="13495" RevisionGUID="41594819-f0e8-46d0-a146-331663083d3e" CreationDate="2023-05-26T17:17:33.037" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="40760" PostHistoryTypeId="1" PostId="13495" RevisionGUID="41594819-f0e8-46d0-a146-331663083d3e" CreationDate="2023-05-26T17:17:33.037" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="40761" PostHistoryTypeId="2" PostId="13496" RevisionGUID="0c2ff919-4bdd-481a-bd6e-f93196428d92" CreationDate="2023-05-26T17:17:33.037" UserId="-1" Text="" ContentLicense="CC BY-SA 4.0" />
  <row Id="40763" PostHistoryTypeId="1" PostId="13496" RevisionGUID="0c2ff919-4bdd-481a-bd6e-f93196428d92" CreationDate="2023-05-26T17:17:33.037" UserId="-1" ContentLicense="CC BY-SA 4.0" />
  <row Id="40766" PostHistoryTypeId="2" PostId="13497" RevisionGUID="83a2ce15-bea8-4c51-a548-55ccc98d5524" CreationDate="2023-05-27T17:12:02.660" UserId="20012" Text="There are 3 kinds of code that are contained in a GPU-utilizing program:&#xD;&#xA;1. CPU code.&#xD;&#xA;2. CPU-to-GPU or GPU-to-CPU bridge code. This is what DirectX actually is.&#xD;&#xA;3. GPU code. In NVidia speak, this is called a &quot;Cuda kernel&quot;, and this is where DirectX is actually _implemented_.&#xD;&#xA;&#xD;&#xA;Every program starts in 1 and uses 2 to call pre-compiled 3 on the GPU.&#xD;&#xA;&#xD;&#xA;Then, _exactly_ what kinds of code, using the above classification, is contained in GPU &quot;drivers&quot;? Does GPU need a sort of OS-like kernel (_not_ the Cuda kernel mentioned above) just like the CPU? Is this contained in the drivers (often GB-sized) as well?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40768" PostHistoryTypeId="1" PostId="13497" RevisionGUID="83a2ce15-bea8-4c51-a548-55ccc98d5524" CreationDate="2023-05-27T17:12:02.660" UserId="20012" Text="What is in a GPU driver?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40769" PostHistoryTypeId="3" PostId="13497" RevisionGUID="83a2ce15-bea8-4c51-a548-55ccc98d5524" CreationDate="2023-05-27T17:12:02.660" UserId="20012" Text="|cuda|driver|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40770" PostHistoryTypeId="2" PostId="13498" RevisionGUID="fff59802-6cf5-4d73-aab5-c9e9f1761f01" CreationDate="2023-05-28T02:09:39.790" UserId="2654" Text="Your taxonomy is at best imprecise. A more accurate taxonomy would be:&#xD;&#xA;&#xD;&#xA;1. Userland code. This is code that's executed by the CPU in user mode.&#xD;&#xA;2. Driver code. This is code that's executed on the CPU which runs with special privileges, allowing direct access to various OS internals and the like.&#xD;&#xA;3. Actual compiled GPU-native code. This is more-or-less arbitrary code that is transferred to the GPU and gets executed by some GPU-invoked process. These could be compute kernels, shaders invoked by a rendering command, etc.&#xD;&#xA;&#xD;&#xA;This differs from your taxonomy in many ways. &quot;DirectX&quot; is spread among *all* of this. Not every DirectX functions is driver code. For D3D12, building command buffers doesn't need driver privileges. It's just creating tokens specific to the GPU which will *eventually* be given to the GPU. Only the actual act of giving those commands to the GPU needs driver privileges.&#xD;&#xA;&#xD;&#xA;Furthermore, DirectX implementations can (and will) insert stuff into even your GPU shader code.&#xD;&#xA;&#xD;&#xA;&quot;GPU drivers&quot; therefore live in all three places. The code contained in them exists to implement whatever API abstraction that your userland code is using to communicate to the GPU. The driver uses whichever tools are needed to implement that abstraction.&#xD;&#xA;&#xD;&#xA;As for what the GPU is doing, it is generally pretty simple. Most GPUs have one or more queues, to which the driver will (at the request of userland code) submit a sequence of commands. This sequence of commands could be considered a &quot;program&quot;, but it's usually simpler than that. They're just commands that the queue will execute using various GPU resources, in order (somewhat), first to last.&#xD;&#xA;&#xD;&#xA;There may be a series of state setting commands followed by a rendering command. That rendering command will generate a number of vertex shader invocations, which cascades through the entire rendering pipeline. This operation will involve using a number of resources, including compute units.&#xD;&#xA;&#xD;&#xA;A command queue is not a program; it's just a series of operations. There's (probably) no conditional logic, no variables, etc. It's all hard-coded operations. The internals of those operations can be flexible, but which commands are available isn't.&#xD;&#xA;&#xD;&#xA;The driver's job (among many other things) is to manage the various queues at the request of user code. It also allocates memory to processes (usually upon request), pages things in and out of virtual GPU memory, etc.&#xD;&#xA;&#xD;&#xA;But this is all stuff happening largely on the CPU. The GPU is still a device largely controlled by direct CPU action." ContentLicense="CC BY-SA 4.0" />
  <row Id="40773" PostHistoryTypeId="5" PostId="13495" RevisionGUID="a801b098-c154-45e5-9bff-d94d63f1d56f" CreationDate="2023-05-28T03:49:53.720" UserId="87" Comment="added 259 characters in body" Text="HLSL is the High-Level Shading Language, used to author shaders for use with Direct3D, and cross-compilable to SPIR-V. Use this tag for questions which are specifically about shaders written in this language. For generic shader questions use [shader] instead." ContentLicense="CC BY-SA 4.0" />
  <row Id="40774" PostHistoryTypeId="24" PostId="13495" RevisionGUID="a801b098-c154-45e5-9bff-d94d63f1d56f" CreationDate="2023-05-28T03:49:53.720" Comment="Proposed by 87 approved by 482 edit id of 623" ContentLicense="CC BY-SA 4.0" />
  <row Id="40775" PostHistoryTypeId="5" PostId="13496" RevisionGUID="6d3b3611-76bd-44ac-9692-b37d3e4188c0" CreationDate="2023-05-28T03:50:02.807" UserId="87" Comment="added 259 characters in body" Text="HLSL is the High-Level Shading Language, used to author shaders for use with Direct3D, and cross-compilable to SPIR-V. Use this tag for questions which are specifically about shaders written in this language. For generic shader questions use [shader] instead." ContentLicense="CC BY-SA 4.0" />
  <row Id="40776" PostHistoryTypeId="24" PostId="13496" RevisionGUID="6d3b3611-76bd-44ac-9692-b37d3e4188c0" CreationDate="2023-05-28T03:50:02.807" Comment="Proposed by 87 approved by 482 edit id of 624" ContentLicense="CC BY-SA 4.0" />
  <row Id="40777" PostHistoryTypeId="50" PostId="8779" RevisionGUID="7916dafd-6d97-4f67-a2f4-0f0bb1551e0f" CreationDate="2023-05-28T18:07:05.877" UserId="-1" />
  <row Id="40779" PostHistoryTypeId="50" PostId="13410" RevisionGUID="cf9405e0-d97e-407c-836c-16a209d37b13" CreationDate="2023-05-30T00:07:05.923" UserId="-1" />
  <row Id="40780" PostHistoryTypeId="2" PostId="13499" RevisionGUID="94c6ae10-5173-40af-8f9a-499fe6d73bba" CreationDate="2023-05-30T03:17:17.417" UserId="20016" Text="I see a number of applications where polygons, lines, splines, etc., are algorithmically given a &quot;hand drawn&quot; look.  What algorithm or general approach is applicable for this?&#xD;&#xA;&#xD;&#xA;As an example, [sketchvis.com][1] does this for graphviz visualizations, and provides the option to turn the sketchiness off and on.&#xD;&#xA;&#xD;&#xA;[![sketchviz illustration][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://sketchviz.com/&#xD;&#xA;  [2]: https://i.stack.imgur.com/LIdkK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40782" PostHistoryTypeId="1" PostId="13499" RevisionGUID="94c6ae10-5173-40af-8f9a-499fe6d73bba" CreationDate="2023-05-30T03:17:17.417" UserId="20016" Text="What algorithm approximates a &quot;hand sketched&quot; look for rendering diagrams?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40783" PostHistoryTypeId="3" PostId="13499" RevisionGUID="94c6ae10-5173-40af-8f9a-499fe6d73bba" CreationDate="2023-05-30T03:17:17.417" UserId="20016" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40784" PostHistoryTypeId="2" PostId="13500" RevisionGUID="b24b2025-ef38-4d36-9802-fe7c6496dcd3" CreationDate="2023-05-30T07:05:38.560" UserDisplayName="user1703" Text="I don't know how they do it precisely, but if I was to do it, I would sample a few points along the lines/curves to be drawn, add small random perturbations, and join them with smooth interpolating curves such as cubic splines. Apparently, all lines are drawn twice.&#xD;&#xA;&#xD;&#xA;The characters are drawn the same way, because you don't have access to their definition as curves. You might also think to add small perturbations, writing character per character." ContentLicense="CC BY-SA 4.0" />
  <row Id="40786" PostHistoryTypeId="5" PostId="13500" RevisionGUID="7b37b273-c351-4e82-905d-261dda3b0ceb" CreationDate="2023-05-30T07:11:00.793" UserDisplayName="user1703" Comment="added 181 characters in body" Text="I don't know how they do it precisely, but if I was to do it, I would sample a few points along the lines/curves to be drawn, add small random perturbations, and join them with smooth interpolating curves such as cubic splines. Apparently, all lines are drawn twice.&#xD;&#xA;&#xD;&#xA;Possibly also, predefine Bezier curves to match a line segment or approximate an ellipse, transform them to match the desired placement, then move the control points randomly.&#xD;&#xA;&#xD;&#xA;The characters are drawn the same way, because you don't have access to their definition as curves. You might also think to add small perturbations, writing character per character." ContentLicense="CC BY-SA 4.0" />
  <row Id="40787" PostHistoryTypeId="5" PostId="13500" RevisionGUID="3882373f-01f5-4e76-866c-9a89ea41f80d" CreationDate="2023-05-30T07:28:51.933" UserDisplayName="user1703" Comment="added 3 characters in body" Text="I don't know how they do it precisely, but if I was to do it, I would sample a few points along the lines/curves to be drawn, add small random perturbations, and join them with smooth interpolating curves such as cubic splines. Apparently, all lines are drawn twice.&#xD;&#xA;&#xD;&#xA;Possibly also, predefine Bezier curves to match a line segment or approximate an ellipse, transform them to align to the desired placement, then move the control points randomly.&#xD;&#xA;&#xD;&#xA;In the example the characters are drawn the same way, because you don't have access to their definition as curves. You might also think to add small perturbations, writing character per character." ContentLicense="CC BY-SA 4.0" />
  <row Id="40792" PostHistoryTypeId="50" PostId="12143" RevisionGUID="60ddc181-f123-47ac-bd8c-2439444d6522" CreationDate="2023-05-30T15:07:55.940" UserId="-1" />
  <row Id="40796" PostHistoryTypeId="50" PostId="13445" RevisionGUID="2656dc14-271a-4f1f-bfc9-b3f8489d78ac" CreationDate="2023-05-31T22:07:05.810" UserId="-1" />
  <row Id="40797" PostHistoryTypeId="2" PostId="13502" RevisionGUID="21355de8-931f-40ae-ab9c-28b0e5546c32" CreationDate="2023-06-01T05:15:02.957" UserId="20023" Text="I have a vertex shader happily producing all the vertices I want for a 2D plot. Now I want to also render a plot of the same data, but each point relative to the previous one, like [SVG][1] **Paths** using `l` instead of `L`.&#xD;&#xA;&#xD;&#xA;I have tried a geometry shader, but the primitive would have to be a line strip with *all* the vertices -- 500,000 or more.&#xD;&#xA;&#xD;&#xA;I'm pretty sure a vertex shader can't use the output of the previous instance, and computing the sum of 1..n is difficult to parallelise.&#xD;&#xA;&#xD;&#xA;The only method I can think of is;&#xD;&#xA;&#xD;&#xA; 1. Use a compute shader to calculate the data&#xD;&#xA; 2. Calculate cumulative sums with CPU&#xD;&#xA; 3. Send data to vertex shader that does very little&#xD;&#xA;&#xD;&#xA;Is there a way of doing this with a vertex, geometry or mesh shader? Or with an extension that might help?&#xD;&#xA;&#xD;&#xA;It seems to be something basic enough, and useful enough to be included in SVG.&#xD;&#xA;&#xD;&#xA;What is the best method to tackle this?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/SVG#Design" ContentLicense="CC BY-SA 4.0" />
  <row Id="40799" PostHistoryTypeId="1" PostId="13502" RevisionGUID="21355de8-931f-40ae-ab9c-28b0e5546c32" CreationDate="2023-06-01T05:15:02.957" UserId="20023" Text="Relative coordinates -- cumulative sum" ContentLicense="CC BY-SA 4.0" />
  <row Id="40800" PostHistoryTypeId="3" PostId="13502" RevisionGUID="21355de8-931f-40ae-ab9c-28b0e5546c32" CreationDate="2023-06-01T05:15:02.957" UserId="20023" Text="|shader|algorithm|vulkan|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40811" PostHistoryTypeId="2" PostId="13506" RevisionGUID="3073fa77-b592-439d-a141-e9d07023197b" CreationDate="2023-06-02T15:21:58.853" UserId="2654" Text="&gt; Is it possible to trigger OpenGL to render a new image consisting of just one pixel for the refracted ray in the main function in the fragment (pixel?) shader?&#xD;&#xA;&#xD;&#xA;OpenGL does not know what your data is. It only knows what you tell it. It knows that you've bound some buffers and submitted some commands to render with them. It doesn't keep track of that information after it has processed those commands.&#xD;&#xA;&#xD;&#xA;In short, it doesn't know what your scene is. So even if a fragment shader could provoke rendering (which it cannot), it wouldn't know *what* to render.&#xD;&#xA;&#xD;&#xA;&gt; If it is not possible to trigger the rendering of a new, single-pixel image in the main function in the fragment shader in OpenGL, does Vulkan, which is supposed to be more powerful, offer this possibility?&#xD;&#xA;&#xD;&#xA;No.&#xD;&#xA;&#xD;&#xA;What Vulkan has is an (optional) raytracing rendering pipeline. It involves building data structures that represent &quot;the scene&quot; in some way, as well as dealing with a bunch of different shader stages that can create, test, and manipulate rays.&#xD;&#xA;&#xD;&#xA;This is not a simple system and it doesn't work at all like the standard rasterization graphics pipeline. It's also Vulkan (or D3D12) only, as the complexities of it are too great for OpenGL as an API to handle." ContentLicense="CC BY-SA 4.0" />
  <row Id="40816" PostHistoryTypeId="2" PostId="13508" RevisionGUID="d9f5b4b9-634d-4356-ad9d-3429c05c3caf" CreationDate="2023-06-02T17:59:18.650" UserId="20037" Text="I have a voxel based game, similar to Minecraft and want to apply the &quot;curved world effect&quot; like [described here](https://alastaira.wordpress.com/2013/10/25/animal-crossing-curved-world-shader/).&#xD;&#xA;&#xD;&#xA;As I was using a per 1x1 face quad renderer, applying the effect went well, but I implemented a greedy mesh optimization, that same faces are merged to one huge mesh.&#xD;&#xA;&#xD;&#xA;Now the curved world shader seems to not work anymore, but most of the sources describe, that it should just work for all meshes (whatever &quot;all&quot; means).&#xD;&#xA;&#xD;&#xA;[![greedy mesh optimization artifacts][1]][1]&#xD;&#xA;&#xD;&#xA;I somehow understand that it should not work, as quadratic bending and linear fragment interpolation between two vertices is different, but I don't find any hint when it does not work.&#xD;&#xA;&#xD;&#xA;That's the part of my vertex shader.&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;// offscreen.vert&#xD;&#xA;// ..&#xD;&#xA;vec3 diff = ubo.pos - inPosition;&#xD;&#xA;diff.y = 0;&#xD;&#xA;&#xD;&#xA;float dist = length(diff);&#xD;&#xA;vec3 d = vec3(0.0, 0.005 * -dist * dist, 0.0);&#xD;&#xA;&#xD;&#xA;vec3 p = inPosition + d;&#xD;&#xA;gl_Position = ubo.proj * ubo.view * vec4(p, 1.0);&#xD;&#xA;// ..&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Do have any idea? &#xD;&#xA;Thanks for helping&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Uawcn.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40818" PostHistoryTypeId="1" PostId="13508" RevisionGUID="d9f5b4b9-634d-4356-ad9d-3429c05c3caf" CreationDate="2023-06-02T17:59:18.650" UserId="20037" Text="Curved world effect shader for heterogeneous mesh faces" ContentLicense="CC BY-SA 4.0" />
  <row Id="40819" PostHistoryTypeId="3" PostId="13508" RevisionGUID="d9f5b4b9-634d-4356-ad9d-3429c05c3caf" CreationDate="2023-06-02T17:59:18.650" UserId="20037" Text="|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40820" PostHistoryTypeId="2" PostId="13509" RevisionGUID="56ca791a-52e4-4b9b-acc9-9d8eed969a0a" CreationDate="2023-06-02T20:23:45.320" UserId="2654" Text="Can a GPU do this? Sure. Can it do it fast? Not really, no.&#xD;&#xA;&#xD;&#xA;The nature of the algorithm is antagonistic to how a GPU wants to do work. GPUs gain performance through massive parallelism. Your algorithm is inherently single-threaded: no answer can be computed until the prior answer is computed.&#xD;&#xA;&#xD;&#xA;Will the processing time of such a single-threaded operation be greater than the cost of a full GPU-&gt;CPU-&gt;GPU synchronization? That depends on how much data you're talking about. That being said, unless the data is being computed *by* the GPU, the CPU could just hold onto a copy of it and compute the values itself." ContentLicense="CC BY-SA 4.0" />
  <row Id="40823" PostHistoryTypeId="2" PostId="13510" RevisionGUID="d9fbd83f-9a91-46fe-8347-2f4bd830b8d0" CreationDate="2023-06-03T03:23:55.067" UserId="445" Text="&gt; I somehow understand that it should not work, as quadratic bending and linear fragment interpolation between two vertices is different, &#xD;&#xA;&#xD;&#xA;Indeed. If you want to non-linearly distort a mesh object, then you have to _sample the nonlinear function frequently_ to get a reasonable linear approximation to it — that is, you must not have very large or long triangles.&#xD;&#xA;&#xD;&#xA;If that were the only problem, then your mesh would wobble weirdly but not be full of gaps. The gaps are a different, but related problem:&#xD;&#xA;&#xD;&#xA;&gt; but I implemented a greedy mesh optimization, that same faces are merged to one huge mesh.&#xD;&#xA;&#xD;&#xA;The greedy meshing algorithm is known to produce “T-junctions” — points where an edge of one quad (pair of triangles) meets the vertices of two (or more) others.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;|         Quad 1         |&#xD;&#xA;|                        |&#xD;&#xA;|V1         V2           |V3&#xD;&#xA;+-----------+------------+&#xD;&#xA;|           |            |&#xD;&#xA;|   Quad 2  |   Quad 3   |&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Under ordinary circumstances, this merely produces a few pixel-sized specks in the rendering, because the rasterization of the edge of quad 1 doesn't quite line up with the rasterizations of the other two.&#xD;&#xA;&#xD;&#xA;However, when you introduce a non-linear transformation, then those specks open up into big gaps, because the non-linear transformation moved vertex V2 so that **it is not on the line between V1 and V2 at all**. Those are the gaps you are seeing.&#xD;&#xA;&#xD;&#xA;To avoid these gaps, you must generate a mesh which **contains no T-junctions** — every edge of every triangle must exactly meet (share two vertices with) a neighboring triangle. (This is true of most meshes created by 3D modeling software, except where an object is intentionally incomplete, such as leaving off the bottom of a tree's trunk.)&#xD;&#xA;&#xD;&#xA;The simplest way to achieve this is to remove the greedy mesh optimization, and generate 2 triangles for every block face. Conveniently, this will also ensure that the visual effect of the distortion is consistently sampled.&#xD;&#xA;&#xD;&#xA;If you still want to optimize the mesh, you will have to use an algorithm which avoids T-junctions — it cannot simply generate one quad for a large area and must instead take neighbors into account. This is a nontrivial problem and I'm not aware of any articles describing a complete algorithm for it. (Perhaps one day I'll write one.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40825" PostHistoryTypeId="50" PostId="13454" RevisionGUID="021f76b2-7c73-452c-8529-4c1c5bd5296f" CreationDate="2023-06-03T14:01:15.143" UserId="-1" />
  <row Id="40826" PostHistoryTypeId="5" PostId="13510" RevisionGUID="85cd0798-29c2-4bc3-9388-d8ea713af038" CreationDate="2023-06-03T16:16:04.623" UserId="445" Comment="added 241 characters in body" Text="&gt; I somehow understand that it should not work, as quadratic bending and linear fragment interpolation between two vertices is different, &#xD;&#xA;&#xD;&#xA;Indeed. If you want to non-linearly distort a mesh object, then you have to _sample the nonlinear function frequently_ to get a reasonable linear approximation to it — that is, you must not have very large or long triangles.&#xD;&#xA;&#xD;&#xA;If that were the only problem, then your mesh would wobble weirdly but not be full of gaps. The gaps are a different, but related problem:&#xD;&#xA;&#xD;&#xA;&gt; but I implemented a greedy mesh optimization, that same faces are merged to one huge mesh.&#xD;&#xA;&#xD;&#xA;The greedy meshing algorithm is known to produce “T-junctions” — points where an edge of one quad (pair of triangles) meets the vertices of two (or more) others.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;|         Quad 1         |&#xD;&#xA;|                        |&#xD;&#xA;|V1         V2           |V3&#xD;&#xA;+-----------+------------+&#xD;&#xA;|           |            |&#xD;&#xA;|   Quad 2  |   Quad 3   |&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Under ordinary circumstances, this merely produces a few pixel-sized specks in the rendering, because the rasterization of the edge of quad 1 doesn't quite line up with the rasterizations of the other two.&#xD;&#xA;&#xD;&#xA;However, when you introduce a non-linear transformation, then those specks open up into big gaps, because the non-linear transformation moved vertex V2 so that **it is not on the line between V1 and V2 at all**. Those are the gaps you are seeing.&#xD;&#xA;&#xD;&#xA;To avoid these gaps, you must generate a mesh which **contains no T-junctions** — every edge of every triangle must exactly meet (share two vertices with) a neighboring triangle. (This is true of most meshes created by 3D modeling software, except where an object is intentionally incomplete, such as leaving off the bottom of a tree's trunk.)&#xD;&#xA;&#xD;&#xA;The simplest way to achieve this is to remove the greedy mesh optimization, and generate 2 triangles for every block face. Conveniently, this will also ensure that the visual effect of the distortion is consistently sampled.&#xD;&#xA;&#xD;&#xA;If you still want to optimize the mesh, you will have to use a different algorithm, which avoids T-junctions — it cannot simply generate one quad for a large area and must instead take neighboring triangles into account. Once the algorithm has decided to put a vertex at a certain corner, all other surfaces meeting that corner must also have a vertex there too rather than an edge passing by. This is a nontrivial problem and I'm not aware of any articles describing a complete algorithm for it, nor do I have such an algorithm in code form. (Perhaps one day I'll write one.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="40827" PostHistoryTypeId="5" PostId="13399" RevisionGUID="363d755c-5255-4ee3-a0cd-588b1700cf2e" CreationDate="2023-06-03T22:38:46.520" UserId="11224" Comment="added 136 characters in body" Text="I think that VR / AR experts will know the answer to this.&#xD;&#xA;&#xD;&#xA;At what vergence angle are &quot;infinitely far away&quot; objects such as star field textures drawn in head-mounted VR / AR displays ?&#xD;&#xA;&#xD;&#xA;I believe I have read that the stars in the night sky are so far away that our human visual system cannot distinguish the degree of vergence required to look at them from &quot;parallel vergence&quot;, where the view directions of the two eyes are parallel. That is, the stars are so far away that in this particular sense, they may as well be infinitely far away.&#xD;&#xA;&#xD;&#xA;In my experiments with anaglyph displays on laptop screens, I have found that it is very uncomfortable to diverge my eyes to the point of parallel view directions, in order to resolve star field textures that are &quot;infinitely distant&quot;, i.e., in which the left and right images are separated horizontally by exactly my interpupillary distance.&#xD;&#xA;&#xD;&#xA;In case this might be due to measurement errors causing the separation on screen to very slightly exceed my actual interpupillary distance, I have experimented with reducing that separation one mm at a time, until the degree of vergence became tolerably comfortable. However, this required a separation difference that was significantly smaller than my actual interpupillary distance, tending to refute the &quot;measurement errors&quot; hypothesis.&#xD;&#xA;&#xD;&#xA;Is the discomfort likely to be due more to the well-known contradiction between vergence and accommodation (focus) that is a drawback of conventional stereoscopic displays ?&#xD;&#xA;&#xD;&#xA;(**EDIT** As well as the muscular discomfort, I noticed that the star field texture was blurry, as if my eyes were refusing to focus on the screen. Perhaps at this extreme of vergence, the physiological connection between vergence and accommodation forces accommodation at infinity ?)&#xD;&#xA;&#xD;&#xA;In VR headsets, does the greater focal depth alleviate this problem, i.e. is the limit of comfort for vergence closer to parallel, in this case ?&#xD;&#xA;&#xD;&#xA;I have read that parallel vergence should be avoided in stereoscopic displays, because it is unnatural for our visual system, but I have not read any explanation as to why (almost) parallel vergence is perfectly comfortable for viewing stars in the real world. Might it also be to do with the fact that the solid angle subtended on earth by a star in the real world is very small ?&#xD;&#xA;&#xD;&#xA;Are some of my assumptions wrong ?&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I moved the most important part of the question to the top, and modified the title to emphasise it.&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;&#xD;&#xA;I have cross-posted this quesion on the gamedev stackexchange, here: https://gamedev.stackexchange.com/q/205830/145133 " ContentLicense="CC BY-SA 4.0" />
  <row Id="40828" PostHistoryTypeId="2" PostId="13511" RevisionGUID="848a3942-11ec-41cb-a943-a46ce4968d06" CreationDate="2023-06-04T22:17:19.813" UserId="20046" Text="I wrote my software renderer with C++20 and the DirectX Math library.&#xD;&#xA;The pipeline so far consists of these steps:&#xD;&#xA;&#xD;&#xA; 1. I use vertex buffers (`std::vector&lt;xgl::Vertex&gt;`) and index buffers (`std::vector&lt;DirectX::UINT3&gt;`).&#xD;&#xA; 2. I assemble triangles into a `std::vector&lt;Triangle&gt;` using 144 bytes per triangle multiplied by N. Each vertex takes up 48 bytes.&#xD;&#xA; 3. I perform vertex shading/processing using `std::function&lt;Vertex(const Vertex&amp;)&gt;`.&#xD;&#xA; 4. I apply culling.&#xD;&#xA; 5. I sort the triangles by average depth from farthest to nearest using the painter's algorithm.&#xD;&#xA; 6. I perform rasterization or fragment generation`std::vector&lt;Fragment&gt;`. Each fragment occupies 44 bytes. For example, if the resolution is 320x240, the maximum size of fragments would be 3,379,200 bytes.&#xD;&#xA; 7. I apply fragment shading using `std::function&lt;DirectX::XMFLOAT4(const Rasterizer::Fragment&amp;)&gt;`.&#xD;&#xA; 8. Finally, I output the pixels using `std::function&lt;void(DirectX::XMUINT2, DirectX::XMFLOAT4)&gt;`.&#xD;&#xA;&#xD;&#xA;All these steps happen in the `Renderer::DrawTriangles` function:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;&#xD;&#xA;auto SortTriangles(const std::vector&lt;xgl::Triangle&gt;&amp; transformed_triangles)&#xD;&#xA;    -&gt; std::vector&lt;xgl::Triangle&gt;;&#xD;&#xA;&#xD;&#xA;class Rasterizer {&#xD;&#xA; public:&#xD;&#xA;  struct Fragment {&#xD;&#xA;    DirectX::XMUINT2 raster_xy{};&#xD;&#xA;    DirectX::XMFLOAT3 normal{};&#xD;&#xA;    DirectX::XMFLOAT2 texture_uv{};&#xD;&#xA;    DirectX::XMFLOAT4 color{};&#xD;&#xA;&#xD;&#xA;    Fragment() = default;&#xD;&#xA;&#xD;&#xA;    Fragment(const DirectX::XMUINT2&amp; raster_xy, const DirectX::XMFLOAT3&amp; normal,&#xD;&#xA;             const DirectX::XMFLOAT2&amp; texture_uv,&#xD;&#xA;             const DirectX::XMFLOAT4&amp; color);&#xD;&#xA;  };&#xD;&#xA;&#xD;&#xA;  Rasterizer() = default;&#xD;&#xA;&#xD;&#xA;  explicit Rasterizer(DirectX::XMUINT2 raster_dimensions)&#xD;&#xA;      : raster_dimensions_{raster_dimensions} {}&#xD;&#xA;&#xD;&#xA;  [[nodiscard]] auto RasterizeTriangle(const Triangle&amp; triangle) const&#xD;&#xA;      -&gt; std::vector&lt;Fragment&gt;;&#xD;&#xA;&#xD;&#xA; private:&#xD;&#xA;  DirectX::XMUINT2 raster_dimensions_{};&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;class Renderer {&#xD;&#xA; public:&#xD;&#xA;  using OnDrawPixelFunction =&#xD;&#xA;      std::function&lt;void(DirectX::XMUINT2, DirectX::XMFLOAT4)&gt;;&#xD;&#xA;  Renderer() = default;&#xD;&#xA;  Renderer(const Renderer&amp;) = default;&#xD;&#xA;  auto operator=(const Renderer&amp;) -&gt; Renderer&amp; = default;&#xD;&#xA;  Renderer(OnDrawPixelFunction&amp;&amp; on_draw_pixel,&#xD;&#xA;           DirectX::XMUINT2 raster_dimensions, bool cull = true);&#xD;&#xA;&#xD;&#xA;  auto DrawTriangles(const std::vector&lt;xgl::Vertex&gt;&amp; vertices,&#xD;&#xA;                     const std::vector&lt;DirectX::XMUINT3&gt;&amp; indices,&#xD;&#xA;                     const VertexShader&amp; vertex_shader,&#xD;&#xA;                     const FragmentShader&amp; fragment_shader)&#xD;&#xA;      -&gt; std::pair&lt;size_t, size_t&gt;;&#xD;&#xA;&#xD;&#xA; private:&#xD;&#xA;  OnDrawPixelFunction on_draw_pixel_function_{};&#xD;&#xA;  Rasterizer rasterizer_{};&#xD;&#xA;  bool cull_{};&#xD;&#xA;};&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This pipeline draws some inspiration from OpenGL, but I have observed the following issues:&#xD;&#xA;&#xD;&#xA; - It complicates the implementation of flat shading.&#xD;&#xA; - It necessitates sorting all triangles in the scene, requiring me to merge the triangles before issuing a draw call. In contrast, OpenGL utilizes a depth buffer that stores the &quot;last depth,&quot; enabling subsequent draw calls (e.g., DrawTriangles) without concerns about correct ordering.&#xD;&#xA;&#xD;&#xA;To make it work, I can append the vertices to another buffer and adjust the indices or add indices, offsetting them by the number of vertices in the first mesh. However, this approach is not user-friendly:&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;auto DrawContent() -&gt; std::pair&lt;size_t, size_t&gt; {&#xD;&#xA;  auto [vertices_1, indices_1] = gCubeData;&#xD;&#xA;  auto [vertices_2, indices_2] = gOctahedronData;&#xD;&#xA;&#xD;&#xA;  // Make the second mesh a little distant from the first.&#xD;&#xA;  for (auto vertex : vertices_2) {&#xD;&#xA;    vertex.position.z += 4.0F;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  std::vector&lt;xgl::Vertex&gt; combined_vertices{};&#xD;&#xA;  std::vector&lt;DirectX::XMUINT3&gt; combined_indices{};&#xD;&#xA;&#xD;&#xA;  combined_vertices.insert(combined_vertices.end(), vertices_1.begin(),&#xD;&#xA;                           vertices_1.end());&#xD;&#xA;  combined_indices.insert(combined_indices.end(), indices_1.begin(),&#xD;&#xA;                          indices_1.end());&#xD;&#xA;&#xD;&#xA;  combined_vertices.insert(combined_vertices.end(), vertices_2.begin(),&#xD;&#xA;                           vertices_2.end());&#xD;&#xA;&#xD;&#xA;  // Add indices from second mesh, offset by the number of vertices in the first&#xD;&#xA;  // mesh.&#xD;&#xA;  for (const auto&amp; index : indices_2) {&#xD;&#xA;    const auto size = static_cast&lt;std::uint32_t&gt;(vertices_1.size());&#xD;&#xA;    const auto new_index =&#xD;&#xA;        DirectX::XMUINT3{index.x + size, index.y + size, index.z + size};&#xD;&#xA;    combined_indices.push_back(new_index);&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  auto vertex_shader = LoadVertexShader();&#xD;&#xA;  auto fragment_shader = LoadFragmentShader();&#xD;&#xA;  const auto triangle_and_fragment_count = gRenderer.DrawTriangles(&#xD;&#xA;      combined_vertices, combined_indices, vertex_shader, fragment_shader);&#xD;&#xA;  return triangle_and_fragment_count;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Furthermore, texturing (affine texture mapping) will become cumbersome as well, I need to store the texture ID somewhere, so that each triangle &quot;knows&quot; what texture it &quot;wants&quot;.&#xD;&#xA;&#xD;&#xA;In summary, the pipeline&#xD;&#xA;&#xD;&#xA; 1. Index/Vertex Buffer&#xD;&#xA; 2. Triangle Assembly&#xD;&#xA; 3. Vertex Shading (vertex transforms)&#xD;&#xA; 4. Culling (backface removal)&#xD;&#xA; 5. Painter's Algorithm (sorting triangles from farthest to nearest by average depth)&#xD;&#xA; 6. Fragment Generation (rasterization)&#xD;&#xA; 7. Fragment Shading (final color output using the interpolated vertex attributes, e.g., normal, color etc.)&#xD;&#xA; 8. Frame Buffer (pixel output or draw pixel function)&#xD;&#xA;&#xD;&#xA;Can you suggest me a more ergonomic pipeline or API design?&#xD;&#xA;&#xD;&#xA;The blog post by [David Colson](https://www.david-colson.com/2021/11/30/ps1-style-renderer.html) apparently does not implement painter's algorithm.&#xD;&#xA;So, he can issue `BeginObject` and `EndObject` (the draw call) without worrying about ordering issues, since he uses a depth buffer through OpenGL.&#xD;&#xA;&#xD;&#xA;In my opinion, if he were to implement a depth sorting method, then he would actually redesign the API, to first &quot;collect&quot; the triangles, then draw them.&#xD;&#xA;&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;BeginObject()&#xD;&#xA;...&#xD;&#xA;EndObject() // Collect all triangles from mesh 1 - a &quot;collect call&quot;&#xD;&#xA;BeginObject()&#xD;&#xA;...&#xD;&#xA;EndObject() // Collect all triangles from mesh 2 - a &quot;collect call&quot;&#xD;&#xA;&#xD;&#xA;DrawAllTriangles() // The actual draw call&#xD;&#xA;```&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40830" PostHistoryTypeId="1" PostId="13511" RevisionGUID="848a3942-11ec-41cb-a943-a46ce4968d06" CreationDate="2023-06-04T22:17:19.813" UserId="20046" Text="How to design an ergonomic software rendering pipeline with painter's algorithm?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40831" PostHistoryTypeId="3" PostId="13511" RevisionGUID="848a3942-11ec-41cb-a943-a46ce4968d06" CreationDate="2023-06-04T22:17:19.813" UserId="20046" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40832" PostHistoryTypeId="2" PostId="13512" RevisionGUID="84339ff1-f338-4653-b03f-90b63fbb1217" CreationDate="2023-06-05T03:06:16.137" UserId="20048" Text="I know that this Topic is highly Hardware dependent, so i am asking for the case that a monitor is connected to a GPU or motherboard via. Displayport/HDMI&#xD;&#xA;&#xD;&#xA;I would like to know is how the monitor is updated.&#xD;&#xA;&#xD;&#xA;Do monitors directly read from a GPU provided framebuffer, or do monitors have a internal framebuffer that the GPU updates each frame? Is always the entire Buffer updated or just changed Areas? or something different?&#xD;&#xA;&#xD;&#xA;Another thing that i am interested in is how this entire process incooperates Swapchains(with Back and Front Buffers) as example in Windows DXGI?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40834" PostHistoryTypeId="1" PostId="13512" RevisionGUID="84339ff1-f338-4653-b03f-90b63fbb1217" CreationDate="2023-06-05T03:06:16.137" UserId="20048" Text="How does the Communication between Monitor and GPU work?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40835" PostHistoryTypeId="3" PostId="13512" RevisionGUID="84339ff1-f338-4653-b03f-90b63fbb1217" CreationDate="2023-06-05T03:06:16.137" UserId="20048" Text="|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40836" PostHistoryTypeId="5" PostId="13512" RevisionGUID="4a12cbab-c9a5-4bf2-8794-fdac2ed4ce8c" CreationDate="2023-06-05T03:08:28.647" UserId="20048" Comment="added 1 character in body" Text="I know that this Topic is highly Hardware dependent, so i am asking for the case that a monitor is connected to a GPU or motherboard via. Displayport/HDMI&#xD;&#xA;&#xD;&#xA;I would like to know is how the monitor is updated.&#xD;&#xA;&#xD;&#xA;Do monitors directly read from a GPU provided framebuffer, or do monitors have a internal framebuffer that the GPU updates each frame? Is always the entire Buffer updated or just changed Areas? or something different?&#xD;&#xA;&#xD;&#xA;Another thing that i am interested in is how this entire process incooperates Swapchains(with Back and Front Buffers) for example in Windows DXGI?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40837" PostHistoryTypeId="50" PostId="13464" RevisionGUID="52230d46-492d-45b5-808e-6ba9ef23a8ff" CreationDate="2023-06-05T06:05:00.567" UserId="-1" />
  <row Id="40838" PostHistoryTypeId="2" PostId="13513" RevisionGUID="4c8cedb2-562e-4564-9f31-78c516ed32d2" CreationDate="2023-06-05T08:40:16.107" UserId="7869" Text="I am confused by a 'wavefront obj' file's `true triangle number`. For example, I downloaded the __Rungholt__ scene from [McGuire's Computer Graphics Archive](https://casual-effects.com/data/index.html). &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;// McGuire's site says the model has: &#xD;&#xA;Triangles: 6704264&#xD;&#xA;Vertices: 12308528&#xD;&#xA;&#xD;&#xA;//When I am using window's 3D viewer&#xD;&#xA;Triangles: 6704264&#xD;&#xA;Vertices: 20112792&#xD;&#xA;&#xD;&#xA;// To get the confirmation I used MeshLab and the numbers are&#xD;&#xA;Faces (Triangles): 6704264&#xD;&#xA;Vertices: 2527838&#xD;&#xA;```&#xD;&#xA;You see, __the triangle number__ is constant for all these three sources, but the __vertices__ vary a lot. Now, which one should be the right in the `context of vertices number`? How to verify? " ContentLicense="CC BY-SA 4.0" />
  <row Id="40840" PostHistoryTypeId="1" PostId="13513" RevisionGUID="4c8cedb2-562e-4564-9f31-78c516ed32d2" CreationDate="2023-06-05T08:40:16.107" UserId="7869" Text="How to get the accurate number of triangles of an wavefront obj model?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40841" PostHistoryTypeId="3" PostId="13513" RevisionGUID="4c8cedb2-562e-4564-9f31-78c516ed32d2" CreationDate="2023-06-05T08:40:16.107" UserId="7869" Text="|3d|mesh|triangulation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40842" PostHistoryTypeId="2" PostId="13514" RevisionGUID="e45e9be6-2016-4a07-a66b-7a58364d3d26" CreationDate="2023-06-05T10:12:58.847" UserId="13273" Text="The wavefront format (.obj) contains several abbreviations for vertex information:&#xD;&#xA;&#xD;&#xA;    v 1 2 3   #vertex position (x y z)&#xD;&#xA;    vt 1 2    #texture coordinate (u v)&#xD;&#xA;    vn 1 2 3  #normal direction (x y z)&#xD;&#xA;&#xD;&#xA;and definition of a triangle (surface):&#xD;&#xA;&#xD;&#xA;    f 1/2/3 4/5/6 7/8/9 #Triangle with texture coordinate and normal direction.&#xD;&#xA;    f 1/2 3/4 5/6       #Triangle with texture coordinate&#xD;&#xA;    f 1 2 3             #Triangle without additional information&#xD;&#xA;    f 1//2 3//4 5//6    #Triangle with normal direction&#xD;&#xA;&#xD;&#xA;However, counting vertices is complicated:&#xD;&#xA;&#xD;&#xA;When using a graphics API, the vertex information must be formatted in a different way. Let's say we have only 2 triangles that share an edge. The wavefront obj file can look like this:&#xD;&#xA;&#xD;&#xA;    v 0 0 0&#xD;&#xA;    v 0 1 0&#xD;&#xA;    v 1 0 0&#xD;&#xA;    v 1 1 0&#xD;&#xA;&#xD;&#xA;    vn 0 0 1&#xD;&#xA;&#xD;&#xA;    f 1//1 2//1 3//1&#xD;&#xA;    f 2//1 4//1 3//1&#xD;&#xA;&#xD;&#xA;Here we can say that the mesh contains 4 vertices with 2 faces. But if you change to the following:&#xD;&#xA;&#xD;&#xA;    v 0 0 0&#xD;&#xA;    v 0 1 0&#xD;&#xA;    v 1 0 0&#xD;&#xA;    v 1 1 0&#xD;&#xA;&#xD;&#xA;    vn 0 0 1&#xD;&#xA;    vn 0 1 1&#xD;&#xA;&#xD;&#xA;    f 1//1 2//1 3//1&#xD;&#xA;    f 2//2 4//2 3//2&#xD;&#xA;&#xD;&#xA;then the graphics API must generate 6 vertices: three vertices for the first vertex v1, v2 and v3 with normal n1 and three vertices for the second triangle v2, v4 and v3 with normal n2. Thus, the vertices v2 and v3 must be generated twice because they have different normal directions.&#xD;&#xA;&#xD;&#xA;Optimization algorithms can also play a role, for example if n1 is equal to n2, you only need 4 vertices. But does the software (MeshLab, 3D viewer) check this kind of optimization? I don't.&#xD;&#xA;&#xD;&#xA;For non-textured objects, the type of shading also matters: if you use flat shading for our example, you need 6 vertices because both v2 and v3 get two normal directions. With Gouraud shading, you need only 4 vertices, since the multiple normal directions of a vertex result in only one normal direction, which affects the shading of both triangles (faces).&#xD;&#xA;&#xD;&#xA;As you can see, your question cannot be answered without additional information." ContentLicense="CC BY-SA 4.0" />
  <row Id="40844" PostHistoryTypeId="2" PostId="13515" RevisionGUID="5cb78506-a569-4c1e-a463-9132f84518ca" CreationDate="2023-06-05T15:06:18.753" UserId="19783" Text="I'm making a space game and so far what I have is a system to generate spheres with noise on them, making them planets. I make a sphere, create noise data, write that data to an image file, and then bind it to the sphere as a texture, and from there, I use that to make terrain. The problem I'm having is there are too many hills and valleys, and just looks like a spikeball instead of a planet&#xD;&#xA;[![sphere][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![sphere wireframe][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HMGdf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/UNM3V.png&#xD;&#xA;&#xD;&#xA;Here's the function I use to generate the noise data&#xD;&#xA;&#xD;&#xA;    void write_noise_2d(int w, int h, int channels_num, const char* bmp_path)&#xD;&#xA;    {&#xD;&#xA;            // create random seed for noise&#xD;&#xA;            srand(time(NULL));&#xD;&#xA;            float seed = (float)rand()/RAND_MAX;&#xD;&#xA;            // initialize noise&#xD;&#xA;            fnl_state noise = fnlCreateState();&#xD;&#xA;            noise.noise_type = FNL_NOISE_OPENSIMPLEX2;&#xD;&#xA;            noise.octaves = 6;&#xD;&#xA;            noise.lacunarity = 2.0f;&#xD;&#xA;            noise.gain = 0.5f;&#xD;&#xA;            noise.frequency = 0.01f;&#xD;&#xA;            noise.seed = (int)seed;&#xD;&#xA;            printf(&quot;Seed: %i\n&quot;, seed);&#xD;&#xA;            noise.fractal_type = FNL_FRACTAL_FBM;&#xD;&#xA;            // create data array for noise&#xD;&#xA;            float* noise_data = malloc(w * h * channels_num * sizeof(float));&#xD;&#xA;            int index = 0;&#xD;&#xA;            // create noise throughout the entire image&#xD;&#xA;            for(int x=0; x&lt;w; x++)&#xD;&#xA;            {&#xD;&#xA;                for(int y=0; y&lt;h; y++)&#xD;&#xA;                {&#xD;&#xA;                    noise_data[index++] = fnlGetNoise2D(&amp;noise, x * 0.3f, y * 0.3f);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            stbi_write_bmp(bmp_path, w, h, channels_num, noise_data);&#xD;&#xA;            free(noise_data);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here's the function where I bind the noise to the sphere&#xD;&#xA;&#xD;&#xA;    unsigned int load_noise_2d(const char* path, unsigned int shader_program, const char* sampler, &#xD;&#xA;    bool remove_noise)&#xD;&#xA;    {&#xD;&#xA;        unsigned int noise;&#xD;&#xA;        glGenTextures(1, &amp;noise);&#xD;&#xA;        glActiveTexture(GL_TEXTURE0);&#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, noise);&#xD;&#xA;        // from what I heard no need to specify gl_repeat because that is the default&#xD;&#xA;        // filtering parameters&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_MIPMAP);&#xD;&#xA;    &#xD;&#xA;        // image stats&#xD;&#xA;        int width, height, num_channels;&#xD;&#xA;        // load image&#xD;&#xA;        unsigned char* noise_data = stbi_load(path, &amp;width, &amp;height, &amp;num_channels, 0);&#xD;&#xA;        if(noise_data)&#xD;&#xA;        {&#xD;&#xA;            // image options&#xD;&#xA;            glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, noise_data);&#xD;&#xA;            glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;            // send to the GPU for processing&#xD;&#xA;            set_int(shader_program, sampler, 0);&#xD;&#xA;            printf(&quot;Loaded noise map of %i by %i\n&quot;, width, height);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Failed to load noisemap\n&quot;);&#xD;&#xA;        }&#xD;&#xA;        // deallocate data that's no longer needed&#xD;&#xA;        stbi_image_free(noise_data);&#xD;&#xA;        if(remove_noise == true)&#xD;&#xA;        {&#xD;&#xA;            remove(path);&#xD;&#xA;            printf(&quot;Deleted noise file\n&quot;);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Kept noise file\n&quot;);&#xD;&#xA;            return 0;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        return noise;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For reference, this is how the function calls look like&#xD;&#xA;&#xD;&#xA;        // write noise data from FNL to texture&#xD;&#xA;    write_noise_2d(512, 512, 2, &quot;textures/2dnoise.bmp&quot;);&#xD;&#xA;    // now we load the noise map back into the program to be used later&#xD;&#xA;    load_noise_2d(&quot;textures/2dnoise.bmp&quot;, earthlike, &quot;noisemap&quot;, true);&#xD;&#xA;&#xD;&#xA;And finally, here's the tessellation shader, where I had a problem before with the intensity being too high, but that's solved&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // determines what type of tessellation to do&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    // simplex noise goes here&#xD;&#xA;    uniform sampler2D noisemap;&#xD;&#xA;    // allows for object transformations&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    out float height;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // gets barycentric coordinates from the triangles&#xD;&#xA;        vec3 x = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 y = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 z = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        vec3 v = x + y + z;&#xD;&#xA;        // scale noise between an acceptable value&#xD;&#xA;        float min_noise_value = 0.5f;&#xD;&#xA;        float max_noise_value = 2.5f;&#xD;&#xA;        float intensity_scale = 0.015f;&#xD;&#xA;        float noise_range = max_noise_value - min_noise_value;&#xD;&#xA;        // use texture for offsetting sphere vertices&#xD;&#xA;        float noise = texture(noisemap, vec2(v)).r;&#xD;&#xA;        // sphere offsetting multiplier&#xD;&#xA;        height = min_noise_value + noise_range * noise * intensity_scale;&#xD;&#xA;        // makes every triangle an equal distance from the center through normalization (that's how spheres are formed)&#xD;&#xA;        vec3 pos = normalize(x + y + z);&#xD;&#xA;        // apply noise&#xD;&#xA;        pos *= height;&#xD;&#xA;        // output tessellated shape&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40846" PostHistoryTypeId="1" PostId="13515" RevisionGUID="5cb78506-a569-4c1e-a463-9132f84518ca" CreationDate="2023-06-05T15:06:18.753" UserId="19783" Text="How to scale down noise frequency?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40847" PostHistoryTypeId="3" PostId="13515" RevisionGUID="5cb78506-a569-4c1e-a463-9132f84518ca" CreationDate="2023-06-05T15:06:18.753" UserId="19783" Text="|opengl|shader|glsl|noise|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40848" PostHistoryTypeId="2" PostId="13516" RevisionGUID="666c3f3e-9243-43f9-9f45-76c6a5908764" CreationDate="2023-06-05T15:19:00.727" UserId="445" Text="In the typical case, the video card transmits _all_ of the data in the image _every frame_ (every refresh).&#xD;&#xA;&#xD;&#xA;In the early days of television technology, it was impossible to do anything else; the display did not have any memory with which to store an entire frame. The incoming signal was turned directly into CRT phosphor excitation. With modern electronics, there is storage, but it is still practical to design the transmission this way.&#xD;&#xA;&#xD;&#xA;Why? If nothing else, it must be _possible_ for the monitor to receive a completely different image every time it refreshes. If it were not, then video recordings and video games could not display whatever they wanted; they would have to take into account what fits into the connection. The only thing transferring partial images would offer is a small amount of energy efficiency.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Also, the video transmission is **unidirectional**. It does not consist of a request to fetch bytes from some memory, followed by a response containing those bytes; instead, the data is just sent, and the monitor must handle it as it arrives. This has several technical advantages:&#xD;&#xA;&#xD;&#xA;* No requirement for high-performance bidirectional links (wiring, transmitters, and receivers); only one direction needs to be high-bandwidth and low-latency.&#xD;&#xA;&#xD;&#xA;* No latency from waiting for responses to requests.&#xD;&#xA;&#xD;&#xA;* Video signals can be split — sent to multiple displays or other devices (recorders, converters, etc.). A bidirectional protocol would need a much more complex intermediate buffer device.&#xD;&#xA;&#xD;&#xA;The small amount of information that is carried from the monitor back to the computer is configuration information like [the monitor's supported resolutions](https://en.wikipedia.org/wiki/Extended_Display_Identification_Data), and independent communication such as USB carried over the same cable.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;&gt; Do monitors directly read from a GPU provided framebuffer, or do monitors have a internal framebuffer that the GPU updates each frame?&#xD;&#xA;&#xD;&#xA;Modern monitors have an internal framebuffer, which the video card updates each frame.&#xD;&#xA;&#xD;&#xA;&gt; Is always the entire Buffer updated or just changed Areas?&#xD;&#xA;&#xD;&#xA;The entire buffer.&#xD;&#xA;&#xD;&#xA;&gt; how this entire process incooperates Swapchains(with Back and Front Buffers)&#xD;&#xA;&#xD;&#xA;Swapchains are entirely internal to the GPU; the monitor knows nothing about them. They control which framebuffer memory the GPU reads to produce the video signal carried on the cable, but that video signal contains no information about the swapchain." ContentLicense="CC BY-SA 4.0" />
  <row Id="40850" PostHistoryTypeId="52" PostId="13513" RevisionGUID="3fe6ae0a-4759-4f99-a63a-112dab634267" CreationDate="2023-06-05T16:40:36.153" />
  <row Id="40851" PostHistoryTypeId="5" PostId="13515" RevisionGUID="553a0208-cb07-47d5-8743-a801efa2d44d" CreationDate="2023-06-05T18:22:59.500" UserId="19783" Comment="made desire clearer for future visitors" Text="I'm making a space game and so far what I have is a system to generate spheres with noise on them, making them planets. I make a sphere, create noise data, write that data to an image file, and then bind it to the sphere as a texture, and from there, I use that to make terrain. The problem I'm having is there are too many hills and valleys, and just looks like a spikeball instead of a planet&#xD;&#xA;[![sphere][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![sphere wireframe][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here's the function I use to generate the noise data&#xD;&#xA;&#xD;&#xA;    void write_noise_2d(int w, int h, int channels_num, const char* bmp_path)&#xD;&#xA;    {&#xD;&#xA;            // create random seed for noise&#xD;&#xA;            srand(time(NULL));&#xD;&#xA;            float seed = (float)rand()/RAND_MAX;&#xD;&#xA;            // initialize noise&#xD;&#xA;            fnl_state noise = fnlCreateState();&#xD;&#xA;            noise.noise_type = FNL_NOISE_OPENSIMPLEX2;&#xD;&#xA;            noise.octaves = 6;&#xD;&#xA;            noise.lacunarity = 2.0f;&#xD;&#xA;            noise.gain = 0.5f;&#xD;&#xA;            noise.frequency = 0.01f;&#xD;&#xA;            noise.seed = (int)seed;&#xD;&#xA;            printf(&quot;Seed: %i\n&quot;, seed);&#xD;&#xA;            noise.fractal_type = FNL_FRACTAL_FBM;&#xD;&#xA;            // create data array for noise&#xD;&#xA;            float* noise_data = malloc(w * h * channels_num * sizeof(float));&#xD;&#xA;            int index = 0;&#xD;&#xA;            // create noise throughout the entire image&#xD;&#xA;            for(int x=0; x&lt;w; x++)&#xD;&#xA;            {&#xD;&#xA;                for(int y=0; y&lt;h; y++)&#xD;&#xA;                {&#xD;&#xA;                    noise_data[index++] = fnlGetNoise2D(&amp;noise, x * 0.3f, y * 0.3f);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            stbi_write_bmp(bmp_path, w, h, channels_num, noise_data);&#xD;&#xA;            free(noise_data);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Here's the function where I bind the noise to the sphere&#xD;&#xA;&#xD;&#xA;    unsigned int load_noise_2d(const char* path, unsigned int shader_program, const char* sampler, &#xD;&#xA;    bool remove_noise)&#xD;&#xA;    {&#xD;&#xA;        unsigned int noise;&#xD;&#xA;        glGenTextures(1, &amp;noise);&#xD;&#xA;        glActiveTexture(GL_TEXTURE0);&#xD;&#xA;        glBindTexture(GL_TEXTURE_2D, noise);&#xD;&#xA;        // from what I heard no need to specify gl_repeat because that is the default&#xD;&#xA;        // filtering parameters&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);&#xD;&#xA;        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_MIPMAP);&#xD;&#xA;    &#xD;&#xA;        // image stats&#xD;&#xA;        int width, height, num_channels;&#xD;&#xA;        // load image&#xD;&#xA;        unsigned char* noise_data = stbi_load(path, &amp;width, &amp;height, &amp;num_channels, 0);&#xD;&#xA;        if(noise_data)&#xD;&#xA;        {&#xD;&#xA;            // image options&#xD;&#xA;            glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, noise_data);&#xD;&#xA;            glGenerateMipmap(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;            // send to the GPU for processing&#xD;&#xA;            set_int(shader_program, sampler, 0);&#xD;&#xA;            printf(&quot;Loaded noise map of %i by %i\n&quot;, width, height);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Failed to load noisemap\n&quot;);&#xD;&#xA;        }&#xD;&#xA;        // deallocate data that's no longer needed&#xD;&#xA;        stbi_image_free(noise_data);&#xD;&#xA;        if(remove_noise == true)&#xD;&#xA;        {&#xD;&#xA;            remove(path);&#xD;&#xA;            printf(&quot;Deleted noise file\n&quot;);&#xD;&#xA;        }&#xD;&#xA;        else&#xD;&#xA;        {&#xD;&#xA;            printf(&quot;Kept noise file\n&quot;);&#xD;&#xA;            return 0;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        return noise;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For reference, this is how the function calls look like&#xD;&#xA;&#xD;&#xA;        // write noise data from FNL to texture&#xD;&#xA;    write_noise_2d(512, 512, 2, &quot;textures/2dnoise.bmp&quot;);&#xD;&#xA;    // now we load the noise map back into the program to be used later&#xD;&#xA;    load_noise_2d(&quot;textures/2dnoise.bmp&quot;, earthlike, &quot;noisemap&quot;, true);&#xD;&#xA;&#xD;&#xA;And finally, here's the tessellation shader, where I had a problem before with the intensity being too high, but that's solved&#xD;&#xA;&#xD;&#xA;    #version 450 core&#xD;&#xA;&#xD;&#xA;    // determines what type of tessellation to do&#xD;&#xA;    layout(triangles, equal_spacing, cw) in;&#xD;&#xA;    &#xD;&#xA;    // input from control shader&#xD;&#xA;    in vec3 vertex_coord[];&#xD;&#xA;    // output vec&#xD;&#xA;    out vec3 vert;&#xD;&#xA;    // simplex noise goes here&#xD;&#xA;    uniform sampler2D noisemap;&#xD;&#xA;    // allows for object transformations&#xD;&#xA;    uniform mat4 model;&#xD;&#xA;    uniform mat4 view;&#xD;&#xA;    uniform mat4 projection;&#xD;&#xA;    &#xD;&#xA;    out float height;&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        // gets barycentric coordinates from the triangles&#xD;&#xA;        vec3 x = gl_TessCoord.x * vertex_coord[0];&#xD;&#xA;        vec3 y = gl_TessCoord.y * vertex_coord[1];&#xD;&#xA;        vec3 z = gl_TessCoord.z * vertex_coord[2];&#xD;&#xA;        vec3 v = x + y + z;&#xD;&#xA;        // scale noise between an acceptable value&#xD;&#xA;        float min_noise_value = 0.5f;&#xD;&#xA;        float max_noise_value = 2.5f;&#xD;&#xA;        float intensity_scale = 0.015f;&#xD;&#xA;        float noise_range = max_noise_value - min_noise_value;&#xD;&#xA;        // use texture for offsetting sphere vertices&#xD;&#xA;        float noise = texture(noisemap, vec2(v)).r;&#xD;&#xA;        // sphere offsetting multiplier&#xD;&#xA;        height = min_noise_value + noise_range * noise * intensity_scale;&#xD;&#xA;        // makes every triangle an equal distance from the center through normalization (that's how spheres are formed)&#xD;&#xA;        vec3 pos = normalize(x + y + z);&#xD;&#xA;        // apply noise&#xD;&#xA;        pos *= height;&#xD;&#xA;        // output tessellated shape&#xD;&#xA;        gl_Position = projection * view * model * vec4(pos, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;For reference, this is sort of how I want my planet to look like instead&#xD;&#xA;[![notice how there is not a lot of frequency. It's just some occasional hills and valleys][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HMGdf.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/UNM3V.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/AHYC4.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40852" PostHistoryTypeId="5" PostId="13516" RevisionGUID="f023a5d9-2171-4c33-afae-8feb1155651e" CreationDate="2023-06-05T18:32:18.773" UserId="445" Comment="added 595 characters in body" Text="In the typical case, the video card transmits _all_ of the data in the image _every frame_ (every refresh).&#xD;&#xA;&#xD;&#xA;In the early days of television technology, it was impossible to do anything else; the display did not have any memory with which to store an entire frame. The incoming signal was turned directly into CRT phosphor excitation. With modern electronics, there is storage, but it is still practical to design the transmission this way.&#xD;&#xA;&#xD;&#xA;Why? If nothing else, it must be _possible_ for the monitor to receive a completely different image every time it refreshes. If it were not, then video recordings and video games could not display whatever they wanted; they would have to take into account what fits into the connection. The only thing transferring partial images would offer is a small amount of energy efficiency.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Also, the video transmission is **unidirectional**. It does not consist of a request to fetch bytes from some memory, followed by a response containing those bytes; instead, the data is just sent, and the monitor must handle it as it arrives. This has several technical advantages:&#xD;&#xA;&#xD;&#xA;* No requirement for high-performance bidirectional links (wiring, transmitters, and receivers); only one direction needs to be high-bandwidth and low-latency.&#xD;&#xA;&#xD;&#xA;* No latency from waiting for responses to requests.&#xD;&#xA;&#xD;&#xA;* Video signals can be split — sent to multiple displays or other devices (recorders, converters, etc.). A bidirectional protocol would need a much more complex intermediate buffer device.&#xD;&#xA;&#xD;&#xA;The small amount of information that is carried from the monitor back to the video card is configuration information like [the monitor's supported resolutions and refresh rates](https://en.wikipedia.org/wiki/Extended_Display_Identification_Data), and independent communication such as USB carried over the same cable.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The video card receives that configuration information and communicates it to the operating system, which then selects a supported resolution and refresh rate (or lets the user pick) as well as other parameters of the video signal format. This process normally ensures that the monitor receives a signal that it is capable of displaying. If that communication does not succeed (for example, if there is a bug, or if a video splitter is in use with two monitors or receiving divices of different capabilities), then the monitor might display garbage or an error message.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So:&#xD;&#xA;&#xD;&#xA;&gt; Do monitors directly read from a GPU provided framebuffer, or do monitors have a internal framebuffer that the GPU updates each frame?&#xD;&#xA;&#xD;&#xA;Modern monitors have an internal framebuffer, which the video card updates each frame.&#xD;&#xA;&#xD;&#xA;&gt; Is always the entire Buffer updated or just changed Areas?&#xD;&#xA;&#xD;&#xA;The entire buffer.&#xD;&#xA;&#xD;&#xA;&gt; how this entire process incooperates Swapchains(with Back and Front Buffers)&#xD;&#xA;&#xD;&#xA;Swapchains are entirely internal to the GPU; the monitor knows nothing about them. They control which framebuffer memory the GPU reads to produce the video signal carried on the cable, but that video signal contains no information about the swapchain." ContentLicense="CC BY-SA 4.0" />
  <row Id="40853" PostHistoryTypeId="2" PostId="13517" RevisionGUID="9de8b61b-588b-4739-b23b-3c1d7dfbc1ce" CreationDate="2023-06-06T00:26:59.213" UserId="7952" Text="Based on the shader and the way it is using the noise texture there is to much &quot;white noise&quot; / &quot;cell noise&quot; in the noise texture.&#xD;&#xA;&#xD;&#xA;Noise is usually built in layers with low frequencies making up the large features and higher frequencies making up the small features. The different frequencies are literally added together. Looking at the noise texture it looks like the high frequency &quot;bumps&quot; are either multiplied into the noise, or they are just overwritten directly. This will give very sharp edges and give the spiky result you are seeing.&#xD;&#xA;&#xD;&#xA;Basically anywhere you see a sudden change from black to white in the noise you will get a cliff/spike.&#xD;&#xA;&#xD;&#xA;To get the hilly looking terrain like the image you want then the noise texture should look something like this one:&#xD;&#xA;[![Gradual hills][1]][1]&#xD;&#xA;&#xD;&#xA;The slow transition from black to gray then white gives the hills. This &quot;noise&quot; could also be described as low frequency, high amplitude noise.&#xD;&#xA;&#xD;&#xA;To get the bumps this image would have the regular &quot;square&quot; pattern added in. This could be done in the shader itself by computing the pattern on a regular grid. That should make it easier to experiment with different amplitudes and frequencies for the pattern.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/YFnEN.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40858" PostHistoryTypeId="2" PostId="13518" RevisionGUID="f675c47f-a957-46e5-b67b-3d3f086021b7" CreationDate="2023-06-06T07:03:08.210" UserId="20045" Text="I'm trying to importance sample the Cook Torrance BRDF for my path tracer but I'm not sure about the part where you have to change the sample from one coordinate frame to another.&#xD;&#xA;&#xD;&#xA;[This][1] resource states that &#xD;&#xA;&#xD;&#xA;&gt; the strategy is to importance sample the distribution term to get a&#xD;&#xA;&gt; microfacet normal, and then transform everything from all vectors&#xD;&#xA;&gt; relative to the normal to relative to the origin.&#xD;&#xA;&#xD;&#xA;[This][2] blog doesn't mention any coordinate frame change. &#xD;&#xA;&#xD;&#xA;[This answer][3] uses it but doesn't explain why. &#xD;&#xA;&#xD;&#xA;I'm left confused as to when we need to change the coordinates of the sampled direction and more importantly, why it has to be done. &#xD;&#xA;&#xD;&#xA;Why do we need such a coordinate change (it seems we do at least)? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gamedev.net/blogs/entry/2261786-microfacet-importance-sampling-for-dummies/&#xD;&#xA;  [2]: https://agraphicsguynotes.com/posts/sample_microfacet_brdf/&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/questions/4979/what-is-importance-sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="40860" PostHistoryTypeId="1" PostId="13518" RevisionGUID="f675c47f-a957-46e5-b67b-3d3f086021b7" CreationDate="2023-06-06T07:03:08.210" UserId="20045" Text="Importance sampling microfacet BRDF and coordinate frame" ContentLicense="CC BY-SA 4.0" />
  <row Id="40861" PostHistoryTypeId="3" PostId="13518" RevisionGUID="f675c47f-a957-46e5-b67b-3d3f086021b7" CreationDate="2023-06-06T07:03:08.210" UserId="20045" Text="|pathtracing|importance-sampling|microfacet|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40862" PostHistoryTypeId="5" PostId="13518" RevisionGUID="48bd76db-1277-4996-8e7b-ce7dae136f96" CreationDate="2023-06-06T10:10:14.240" UserId="20045" Comment="added 497 characters in body" Text="I'm trying to importance sample the Cook Torrance BRDF for my path tracer but I'm not sure about the part where you have to change the sample from one coordinate frame to another.&#xD;&#xA;&#xD;&#xA;[This][1] resource states that &#xD;&#xA;&#xD;&#xA;&gt; the strategy is to importance sample the distribution term to get a&#xD;&#xA;&gt; microfacet normal, and then transform everything from all vectors&#xD;&#xA;&gt; relative to the normal to relative to the origin.&#xD;&#xA;&#xD;&#xA;[This][2] blog doesn't mention any coordinate frame change. &#xD;&#xA;&#xD;&#xA;[This answer][3] uses one with the `TransformToWorld` function but doesn't explain why. &#xD;&#xA;&#xD;&#xA;I'm left confused as to when we need to change the coordinates of the sampled direction and more importantly, why it has to be done.&#xD;&#xA;&#xD;&#xA;This article from GPU Gems even writes about a &quot;specular coordinate frame&quot;:&#xD;&#xA;&#xD;&#xA;&gt; Here, ![phis](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Cphi_s) and ![thetas](https://chart.googleapis.com/chart?cht=tx&amp;chl=%5Ctheta_s) are the spherical coordinates of the sample direction in a coordinate frame where the specular direction is the z-axis&#xD;&#xA;&#xD;&#xA;What is this specular coordinate frame? Where does it come from? Is it different from the coordinate frame handled by the `TransformToWorld` function of [this answer][3]? Is it specific to the Phong BRDF?&#xD;&#xA;&#xD;&#xA;Why do we need such a coordinate change?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.gamedev.net/blogs/entry/2261786-microfacet-importance-sampling-for-dummies/&#xD;&#xA;  [2]: https://agraphicsguynotes.com/posts/sample_microfacet_brdf/&#xD;&#xA;  [3]: https://computergraphics.stackexchange.com/a/4994/20045" ContentLicense="CC BY-SA 4.0" />
  <row Id="40863" PostHistoryTypeId="2" PostId="13519" RevisionGUID="cd3fb3af-b2cc-4779-a131-c56f2623b2a2" CreationDate="2023-06-07T09:19:35.743" UserId="13273" Text="To calculate the cumulative sum, I would highly recommend to compute shaders.&#xD;&#xA;The rendering pipeline (VS TC TE GS FS) is not a good design for this task.&#xD;&#xA;&#xD;&#xA;When storing the data in an shader storage buffer object (SSBO) you can use the compute shader in the following way:&#xD;&#xA;&#xD;&#xA;First of all define the workgroup size to be one dimensional with size 32 or 64 (Nvidia / AMD). &#xD;&#xA;Depending of the size generate a second SSBO with size $sizeof(float) * ceil(countPoints / workgroupSize)$. In there the compute shader will store the cumulative sum of the subpart. &#xD;&#xA;&#xD;&#xA;Each invocation of the compute shader should load the value from the first SSBO and stores it to shared memory. After the values are loaded, use a barrier and tell invocation 0 of each workgroup to accumulate all values together. During the accumulation store the current result to ssbo1 and the final result will be stored to SSBO2. &#xD;&#xA;&#xD;&#xA;Let's talk how your data has changed so far: within your SSBO1 all values are accumulated with respect to the workgroup size. When plotting, you would see each 32 or 64 values of each workgroup is accumulated correctly, but only with respect to the workgroup size. The other SSBO2 stores the accumulated difference for each workgroup. In general, the final result when accumulating SSBO2 from index 0 to the index of interest, with additional adding the result from SSBO1 would give you the correct value. &#xD;&#xA;&#xD;&#xA;A second compute shader (same workgroup size) can accumulate the values from SSBO2 in the same way as the first compute shader does. So that your data gets accumulated in a parallel way. The SSBO1 should be updated by adding the value from SSBO2 of the previous workgroup. &#xD;&#xA;&#xD;&#xA;Let's name the workgroup size s, the number of values n. The final algorithm would work in parallel in:&#xD;&#xA;&#xD;&#xA;$$O(log_s(n) *s)$$&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40866" PostHistoryTypeId="50" PostId="12158" RevisionGUID="7816cdbb-3e41-48a9-9fb3-1b35c09a8503" CreationDate="2023-06-08T13:02:45.370" UserId="-1" />
  <row Id="40867" PostHistoryTypeId="2" PostId="13520" RevisionGUID="60150852-4f8e-42a3-b767-82bc4a8703b8" CreationDate="2023-06-08T19:50:22.060" UserId="18765" Text="The importance sampling methods for the two reflection models you mentioned are different - they pretty much reflect their definition.&#xD;&#xA;&#xD;&#xA;Cook-Torrance model describes the surface as a collection of microscopic mirror-like facets. The width of the reflection lobe depends on how much the orientation of the facets varies relative to the surface normal. This is what the microfacet normal distribution function (NDF) represents. So importance sampling is based on generating a microfacet normal according to the NDF. Again, relative to the surface normal. So it has to be transformed to the world coordinate frame, that is what TransformToWorld does.&#xD;&#xA;&#xD;&#xA;Phong model instead uses a cosine fallof around the specular reflection. So it can be importance-sampled by choosing a zenith angle proportional to the cosine fallof and a uniform azimuth, relative to the reflected direction. And then again must be transformed to the world coordinate frame." ContentLicense="CC BY-SA 4.0" />
  <row Id="40869" PostHistoryTypeId="2" PostId="13521" RevisionGUID="f48a4b93-c354-420a-9cd7-08ba172eb47e" CreationDate="2023-06-09T14:03:43.423" UserId="20067" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (no distortion due to perspective)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis (North) is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is the way it needs to be in order for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means my best option is to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40871" PostHistoryTypeId="1" PostId="13521" RevisionGUID="f48a4b93-c354-420a-9cd7-08ba172eb47e" CreationDate="2023-06-09T14:03:43.423" UserId="20067" Text="How to setup a 3D camera" ContentLicense="CC BY-SA 4.0" />
  <row Id="40872" PostHistoryTypeId="3" PostId="13521" RevisionGUID="f48a4b93-c354-420a-9cd7-08ba172eb47e" CreationDate="2023-06-09T14:03:43.423" UserId="20067" Text="|3d|webgl|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40873" PostHistoryTypeId="5" PostId="13521" RevisionGUID="0a047303-6bf4-4e15-9a1d-d1b7e8e4ca8a" CreationDate="2023-06-09T18:14:17.750" UserId="20067" Comment="deleted 13 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (no distortion due to perspective)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis (North) is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary in order for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means my best option is to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40874" PostHistoryTypeId="5" PostId="13521" RevisionGUID="558670a8-f848-40ce-b4d6-1972824a77bc" CreationDate="2023-06-09T18:14:42.863" UserId="20067" Comment="deleted 9 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (no distortion due to perspective)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis (North) is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means my best option is to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40875" PostHistoryTypeId="5" PostId="13521" RevisionGUID="713c26d7-17ef-4787-aaf9-25a84262c746" CreationDate="2023-06-09T18:52:32.157" UserId="20067" Comment="added 15 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model looks the same)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis (North) is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means my best option is to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40876" PostHistoryTypeId="5" PostId="13521" RevisionGUID="385fb72a-a50e-4ac3-aec6-94618f109328" CreationDate="2023-06-09T18:53:34.650" UserId="20067" Comment="deleted 8 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model looks the same)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means my best option is to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40877" PostHistoryTypeId="5" PostId="13521" RevisionGUID="607b4454-a19e-4ecd-90ac-5f040768ebc4" CreationDate="2023-06-09T18:54:46.640" UserId="20067" Comment="deleted 11 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model looks the same)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40878" PostHistoryTypeId="5" PostId="13521" RevisionGUID="ce439323-8052-407a-a060-bc873eb0751c" CreationDate="2023-06-09T18:55:13.897" UserId="20067" Comment="added 23 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model looks the same regardless of position)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40879" PostHistoryTypeId="5" PostId="13521" RevisionGUID="ef3a44ed-25f1-4de7-90f7-4a014738e629" CreationDate="2023-06-09T18:56:47.653" UserId="20067" Comment="added 39 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model looks the same regardless of position)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight. Maybe this has some other explanation.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues thus far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40880" PostHistoryTypeId="5" PostId="13521" RevisionGUID="247b507e-19e4-4a60-9b74-e0663018532a" CreationDate="2023-06-09T18:57:35.573" UserId="20067" Comment="deleted 2 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model looks the same regardless of position)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight. Maybe this has some other explanation.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues so far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40881" PostHistoryTypeId="5" PostId="13521" RevisionGUID="0b1b0e01-77a2-42bb-b02f-ef6c070979ae" CreationDate="2023-06-09T18:58:49.493" UserId="20067" Comment="added 7 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - A rendered model should maintain its shape regardless of position (every instance of the same model should look identical regardless of position)&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight. Maybe this has some other explanation.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues so far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40882" PostHistoryTypeId="5" PostId="13521" RevisionGUID="c3cbc2b5-13da-4432-9ead-f66ca76aa198" CreationDate="2023-06-09T20:26:18.690" UserId="20067" Comment="added 26 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - Like in orthographic 3D, every instance of the same model should look identical regardless of position. Moving a model to a different position should not affect its shape.&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight. Maybe this has some other explanation.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues so far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40883" PostHistoryTypeId="5" PostId="13521" RevisionGUID="6fb5f4f8-1748-4429-97db-56b7da7f47a6" CreationDate="2023-06-09T20:39:55.140" UserId="20067" Comment="edited body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - As with orthographic 3D, every instance of the same model should look identical regardless of position. Moving a model to a different position should not affect its shape.&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, to make things more complicated, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case!&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight. Maybe this has some other explanation.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues so far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40884" PostHistoryTypeId="5" PostId="13521" RevisionGUID="f43eb603-d121-4c08-9f87-7fbdbb41baa2" CreationDate="2023-06-09T23:38:19.807" UserId="20067" Comment="deleted 30 characters in body" Text="I'm trying to figure out how to setup a 3D camera in WebGL. This is my first swing at 3D so a lot of the matrix stuff is new to me.&#xD;&#xA;&#xD;&#xA;Code&#xD;&#xA;-----------------&#xD;&#xA;The code can be reviewed in this CodePen: https://codepen.io/Candleout/pen/poxMLPB&#xD;&#xA;&#xD;&#xA;For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again. Just make any type of update to the code and it will work.&#xD;&#xA;&#xD;&#xA;Goal&#xD;&#xA;-----------------&#xD;&#xA; - Full control of camera movement&#xD;&#xA; - A rendered model should be able to visibly move in all three dimensions&#xD;&#xA; - As with orthographic 3D, moving an object to a different position should not affect its shape. Every instance of the same object should look identical regardless of position.&#xD;&#xA;&#xD;&#xA;Explanation&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;[![Setting up a 3D camera][1]][1]&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis (`up = [0, 0, -1]`), while X (red) and Y (green) represents the horizontal plane. The reason for this is that my scene is actually a map with a real world coordinate system. In this coordinate system, Z represents elevation, X represents East-West and and Y represents North-South. Z increases with elevation, X increases to the East and Y increases to the North.&#xD;&#xA;&#xD;&#xA;Also, the scene is viewed from an angle. The viewing point is located somewhere to the South-East of origo. Because of this, the Y axis is pointing to the upper right instead of straight up. The X axis is pointing to the lower right instead of straight to the right. &#xD;&#xA;&#xD;&#xA;You may notice that the camera position and up direction is inverted. I believe this is necessary for the axes to point in the right directions according to my particular requirements. Please let me know if this is not the case.&#xD;&#xA;&#xD;&#xA;Questions&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA; 1. How would you typically move the camera? My guess would be that you work with matrix calculations rather than adjusting `cameraPosition` and `cameraTarget` directly.&#xD;&#xA; 2. My first idea was to position the camera straight above the target (`cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];`) and then add transformations to reposition the camera in relation to that position. However, if I set the camera position to `[0, 0, distance]` the model disappears. Why is this?&#xD;&#xA; 3. How would you zoom a scene like this? By scaling the scene, or moving the camera? Well, since the scene is orthographic (in the sense that an object maintains its shape regardless of position) moving the camera won't do anything. I guess this means I need to scale the scene?&#xD;&#xA; 4. Let's say you want to change the viewing angle to make the top edge of the hexagon appear completely flat. This can be done by adding a 15 degree Z rotation to the view matrix (`viewMatrix = m4.zRotate(viewMatrix, 15 * Math.PI/180)`).&#xD;&#xA;[![Add rotation][2]][2]&#xD;&#xA;&#xD;&#xA;Is this a valid approach (is the math correct)? I think the hexagon looks a bit blurry at the top, as if not completely straight. Maybe this has some other explanation.&#xD;&#xA;&#xD;&#xA; 5. Is there some serious downside to assigning the upward direction to the Z axis? Like, issues relating to mathematics or compability with external resources? I believe the conventional way would be to use the Y axis.&#xD;&#xA; 6. Is it a bad idea to invert the Z axis (`up = [0, 0, -1]`)? Could it cause issues with depth calculations? I haven't noticed any issues so far.&#xD;&#xA;&#xD;&#xA;Please let me know if there is some other issue I should be aware of.&#xD;&#xA;&#xD;&#xA;Code breakdown&#xD;&#xA;-----------------&#xD;&#xA;&#xD;&#xA;1. Create an orthographic projection matrix, to convert between screen space and clip space&#xD;&#xA;```&#xD;&#xA;    let projectionMatrix = m4.orthographic(0, canvas.width, canvas.height, 0, -2000, 2000);&#xD;&#xA;```&#xD;&#xA;The orthographic function (the rest of the m4 functions can be found in the CodePen):&#xD;&#xA;```&#xD;&#xA;orthographic: function(left, right, bottom, top, near, far) {&#xD;&#xA;    return [&#xD;&#xA;      2 / (right - left), 0, 0, 0,&#xD;&#xA;      0, 2 / (top - bottom), 0, 0,&#xD;&#xA;      0, 0, 2 / (far - near), 0,&#xD;&#xA;      (left + right) / (left - right),&#xD;&#xA;      (bottom + top) / (bottom - top),&#xD;&#xA;      (far + near) / (far - near),&#xD;&#xA;      1,&#xD;&#xA;    ]&#xD;&#xA;  }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;2. Create a transformation matrix for the model&#xD;&#xA;```&#xD;&#xA;    let modelMatrix = m4.identityMatrix();&#xD;&#xA;    modelMatrix = m4.translate(modelMatrix, drawInfo.position[0], drawInfo.position[1], drawInfo.position[2])&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;3. Create a camera matrix from a lookAt function&#xD;&#xA;```&#xD;&#xA;    let cameraTarget = [0, 0, 0]; // origo&#xD;&#xA;    let cameraPosition = [-1, 1, -1];&#xD;&#xA;    let up = [0, 0, -1];&#xD;&#xA;    let cameraMatrix = m4.lookAt(cameraPosition, cameraTarget, up);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;4. Create view matrix by inverting the camera matrix&#xD;&#xA;```&#xD;&#xA;    let viewMatrix = m4.inverse(cameraMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;5. Create the view projection matrix by multiplying the projection matrix and the projection matrix&#xD;&#xA;```&#xD;&#xA;    let viewProjectionMatrix = m4.multiply(projectionMatrix, viewMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;6. Add in the model transformation to create the final matrix that is sent to the vertex shader&#xD;&#xA;```&#xD;&#xA;    const finalMatrix = m4.multiply(viewProjectionMatrix, modelMatrix);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7qL1Y.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/81co7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40887" PostHistoryTypeId="50" PostId="10341" RevisionGUID="d847f4fc-d0ff-4f12-8a86-c638a17e0fce" CreationDate="2023-06-10T12:06:15.747" UserId="-1" />
  <row Id="40888" PostHistoryTypeId="2" PostId="13522" RevisionGUID="d73078e2-5bd1-458f-b8e9-a9c13d2cce4c" CreationDate="2023-06-10T19:09:06.057" UserId="20071" Text="I'm trying to find the matrix form for the equation of a cubic b-spline. More specifically, the &quot;middle&quot; part, S_i(t), is pretty straightforward and available everywhere:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;M2 = [&#xD;&#xA;  [-1,  3, -3,  1],&#xD;&#xA;  [ 3, -6,  0,  4],&#xD;&#xA;  [-3,  3,  3,  1],&#xD;&#xA;  [ 1,  0,  0,  0]]) * 1/6.&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;But I struggle finding S_0(t) and S_n-3(t), that is, the first and last segment, that respectively start on the first control point and ends on the last control point&#xD;&#xA;&#xD;&#xA;To help explain what I'm looking for, here is exactly it for a quadratic B-Spline (taken from [here](https://www.youtube.com/watch?v=qhQrRCJ-mVg)):&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;M1 = [&#xD;&#xA;  [2, -4, 2],&#xD;&#xA;  [-3, 4, 0],&#xD;&#xA;  [1, 0, 0]]) * 1/2.&#xD;&#xA;M2 = [&#xD;&#xA;  [1, -2, 1],&#xD;&#xA;  [-2, 2, 1], &#xD;&#xA;  [1, 0, 0]]) * 1/2.&#xD;&#xA;M3 = [&#xD;&#xA;  [1, -2, 1],&#xD;&#xA;  [-3, 2, 1], &#xD;&#xA;  [2, 0, 0]]) * 1/2.&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;With those 3 matrices, if we work on `P0, P1, P2`, we use `M1`. If we work on `Pn-2, Pn-1, Pn`, we use `M3`. For everything else, `M2`.&#xD;&#xA;&#xD;&#xA;To summarize, I'm looking for M1 and M3, but for a cubic B-spline, not for a quadratic like just above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here is an image, to understand better:&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA; - *Green crosses: the control points of my cubic spline*&#xD;&#xA; - *Red curve: desired result*&#xD;&#xA; - *Yellow crosses: my current result. The middle part works, not the start/end (currently, this is just bezier)*&#xD;&#xA;&#xD;&#xA;Any help will be greatly appreciated, thank you!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2LSpa.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40890" PostHistoryTypeId="1" PostId="13522" RevisionGUID="d73078e2-5bd1-458f-b8e9-a9c13d2cce4c" CreationDate="2023-06-10T19:09:06.057" UserId="20071" Text="Matrix form of an open uniform cubic b-spline" ContentLicense="CC BY-SA 4.0" />
  <row Id="40891" PostHistoryTypeId="3" PostId="13522" RevisionGUID="d73078e2-5bd1-458f-b8e9-a9c13d2cce4c" CreationDate="2023-06-10T19:09:06.057" UserId="20071" Text="|matrix|vector-graphics|nurbs|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40892" PostHistoryTypeId="2" PostId="13523" RevisionGUID="e557f6d9-b0be-40e5-8342-83acd7f88dc5" CreationDate="2023-06-10T20:54:44.103" UserId="17223" Text="I understand that the normalized device coordinates are the result of the perspective divide of clip space coordinates and allow for an easy mapping of the xy coordinates to a physical screen. What I do not get however is why we need to normalize the z value? Why not fill the depth buffer with the actual camera space depths? Also by normalizing the z value we need to additionally keep track of the camera space depth for interpolation because that value gets lost in ndc space." ContentLicense="CC BY-SA 4.0" />
  <row Id="40894" PostHistoryTypeId="1" PostId="13523" RevisionGUID="e557f6d9-b0be-40e5-8342-83acd7f88dc5" CreationDate="2023-06-10T20:54:44.103" UserId="17223" Text="Normalized Device Coordinates: Why normalize the Z value?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40895" PostHistoryTypeId="3" PostId="13523" RevisionGUID="e557f6d9-b0be-40e5-8342-83acd7f88dc5" CreationDate="2023-06-10T20:54:44.103" UserId="17223" Text="|projections|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40896" PostHistoryTypeId="2" PostId="13524" RevisionGUID="5befd076-5e2d-4fe2-9739-7c200b591397" CreationDate="2023-06-11T12:46:54.993" UserId="20045" Text="I've been trying to importance sample the GGX NDF of my Cook-Torrance BRDF for some time now but I can't get it right.&#xD;&#xA;&#xD;&#xA;I've been following [this article][1].&#xD;&#xA;&#xD;&#xA;Here's my code for the importance sampling part. It samples a direction and returns it. It also computes the corresponding probability for that direction and stores it in the `pdf` argument of `cook_torrance_sample_direction`. The `PerRayData` argument is only used to generate uniform random numbers.&#xD;&#xA;&#xD;&#xA;    inline vec3f __device__ cook_torrance_sample_direction(PerRayData&amp; prd, vec3f&amp; view_direction, vec3f&amp; surface_normal, float roughness, float&amp; pdf)&#xD;&#xA;    {&#xD;&#xA;        float roughness2 = roughness * roughness;&#xD;&#xA;    &#xD;&#xA;        //rand_theta in [0.0, 1.0]&#xD;&#xA;        float rand_theta = prd.random();&#xD;&#xA;    &#xD;&#xA;        float theta = atan(roughness * sqrtf(rand_theta / (1.0f - rand_theta)));&#xD;&#xA;        float phi = prd.random() * 2.0f * M_PI;//Isotropic case&#xD;&#xA;    &#xD;&#xA;        float cos_theta = cos(theta);&#xD;&#xA;        float sin_theta = sin(theta);&#xD;&#xA;        float cos_phi = cos(phi);&#xD;&#xA;        float sin_phi = sin(phi);&#xD;&#xA;    &#xD;&#xA;        //+0.00001f to avoid dividing by 0&#xD;&#xA;        float denom = (roughness2 - 1.0f) * cos_theta * cos_theta + 1.0f + 0.00001;&#xD;&#xA;        float pdf_half_vector = (2 * roughness2 * cos_theta * sin_theta) / (denom * denom);&#xD;&#xA;    &#xD;&#xA;        vec3f sampled_normal_local = vec3f(cos_phi * sin_theta,&#xD;&#xA;                                           sin_phi * sin_theta,&#xD;&#xA;                                           cos_theta);&#xD;&#xA;    &#xD;&#xA;        vec3f view_direction_local = world_to_local(surface_normal, view_direction);&#xD;&#xA;    &#xD;&#xA;        //Section &quot;One Extra Step&quot; of the article&#xD;&#xA;        pdf = pdf_half_vector / (4 * dot(view_direction_local, sampled_normal_local) + 0.00001f);&#xD;&#xA;    &#xD;&#xA;        vec3f surface_normal_local = vec3f(0.0f, 0.0f, 1.0f);&#xD;&#xA;        vec3f reflected_direction_local = normalize(-view_direction_local - 2 * dot(-view_direction_local, sampled_normal_local) * sampled_normal_local);&#xD;&#xA;        vec3f reflected_dir_world = local_to_world(surface_normal, reflected_direction_local);&#xD;&#xA;    &#xD;&#xA;        return reflected_dir_world;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The sampled direction is then passed to the BRDF evaluation function (as the `light_direction` argument) which returns a color. I then divide this color by the PDF:&#xD;&#xA;&#xD;&#xA;    inline vec3f __device__ cook_torrance_brdf(const CookTorranceMaterial&amp; material, const vec3f&amp; view_dir, const vec3f&amp; light_direction, const vec3f&amp; normal)&#xD;&#xA;    {&#xD;&#xA;        vec3f halfway_vector = normalize(view_dir + light_direction);&#xD;&#xA;    &#xD;&#xA;        float NoV = max(dot(normal, view_dir),            0.0f);&#xD;&#xA;        float NoL = max(dot(normal, light_direction),  0.0f);&#xD;&#xA;        float NoH = max(dot(normal, halfway_vector),      0.0f);&#xD;&#xA;        float VoH = max(dot(view_dir, halfway_vector),    0.0f);&#xD;&#xA;    &#xD;&#xA;        vec3f F0 = (0.16f * (material.reflectance * material.reflectance));&#xD;&#xA;        //F0 for metals is equal to the albedo.&#xD;&#xA;        //We're going to lerp between the albedo and 0.04&#xD;&#xA;        //(previous value of F0) depending on&#xD;&#xA;        //the metalness of the material. A fully metalic material&#xD;&#xA;        //will thus have a F0 equal to its albedo&#xD;&#xA;        F0 = (1.0f - material.metallic) * F0 + material.metallic * material.albedo;&#xD;&#xA;    &#xD;&#xA;        //Fresnel: reflected portion of the light (1 - transmitted)&#xD;&#xA;        vec3f F = schlick_approximation(VoH, F0);&#xD;&#xA;        float NDF = GGX_NDF(NoH, material.roughness);&#xD;&#xA;        float G = geometry_Smith(NoV, NoL, material.roughness);&#xD;&#xA;    &#xD;&#xA;        vec3f kS = F;&#xD;&#xA;        vec3f kD = vec3f(1.0f) - kS;&#xD;&#xA;        kD *= 1.0 - material.metallic;&#xD;&#xA;    &#xD;&#xA;        vec3f numerator = NDF * G * F;&#xD;&#xA;        //+0.0001f to avoid dividng by zero if the dot products are 0&#xD;&#xA;        float denominator = 4.0f * NoV * NoL + 0.0001f;&#xD;&#xA;        vec3f specular = numerator / denominator;&#xD;&#xA;    &#xD;&#xA;        // add to outgoing radiance Lo&#xD;&#xA;        return (kD * material.albedo / (float)M_PI + specular);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    inline vec3f __device__ schlick_approximation(float cos_theta, const vec3f&amp; F0)&#xD;&#xA;    {&#xD;&#xA;        return F0 + (1.0f - F0) * powf((1.0f - cos_theta), 5.0f);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline float __device__ GGX_NDF(float NoH, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float alpha = roughness * roughness;&#xD;&#xA;        float alpha2 = alpha * alpha;&#xD;&#xA;        float NoH2 = NoH * NoH;&#xD;&#xA;    &#xD;&#xA;        float num = alpha2;&#xD;&#xA;        float denom = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;        denom = (float)M_PI * denom * denom;&#xD;&#xA;    &#xD;&#xA;        return num / denom;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline float __device__ geometry_Schlick_GGX(float NoX, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float r = (roughness + 1.0);&#xD;&#xA;        float k = (r*r) / 8.0;&#xD;&#xA;    &#xD;&#xA;        float num = NoX;&#xD;&#xA;        float denom = NoX * (1.0 - k) + k;&#xD;&#xA;    &#xD;&#xA;        return num / denom;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline float __device__ geometry_Smith(float NoV, float NoL, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float ggx2 = geometry_Schlick_GGX(NoV, roughness);&#xD;&#xA;        float ggx1 = geometry_Schlick_GGX(NoL, roughness);&#xD;&#xA;    &#xD;&#xA;        return ggx1 * ggx2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, this is giving me results brighter than expected for low roughness values. Here is a roughness of 0.05:&#xD;&#xA;&#xD;&#xA;[![Roughness = 0.05][2]][2]&#xD;&#xA;&#xD;&#xA;And for roughness lower than 0.013, black pixels start appearing (and eventually cover the entire image):&#xD;&#xA;&#xD;&#xA;[![Roughness = 0.012][3]][3]&#xD;&#xA;&#xD;&#xA;I noticed that for the too-bright case of the roughness = 0.05, my evaluation function returns color vectors whose RGB values are over 200. I suppose this is okay and expected as long as the PDF counter balances it (which it doesn't because in those cases, the value of the PDF is only between ~5.0 and ~15.0)?&#xD;&#xA;&#xD;&#xA;  [1]: https://agraphicsguynotes.com/posts/sample_microfacet_brdf/&#xD;&#xA;  [2]: https://i.stack.imgur.com/BsEFl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/7aokx.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40898" PostHistoryTypeId="1" PostId="13524" RevisionGUID="5befd076-5e2d-4fe2-9739-7c200b591397" CreationDate="2023-06-11T12:46:54.993" UserId="20045" Text="Bright results when importance sampling GGX NDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="40899" PostHistoryTypeId="3" PostId="13524" RevisionGUID="5befd076-5e2d-4fe2-9739-7c200b591397" CreationDate="2023-06-11T12:46:54.993" UserId="20045" Text="|pathtracing|importance-sampling|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40900" PostHistoryTypeId="5" PostId="13524" RevisionGUID="72ec0ca5-db03-414a-afd0-1cf3577e7106" CreationDate="2023-06-11T14:59:25.943" UserId="20045" Comment="added 51 characters in body" Text="I've been trying to importance sample the GGX NDF of my Cook-Torrance BRDF for some time now but I can't get it right.&#xD;&#xA;&#xD;&#xA;I've been following [this article][1].&#xD;&#xA;&#xD;&#xA;Here's my code for the importance sampling part. It samples a direction and returns it. It also computes the corresponding probability for that direction and stores it in the `pdf` argument of `cook_torrance_sample_direction`. The `PerRayData` argument is only used to generate uniform random numbers.&#xD;&#xA;&#xD;&#xA;    inline vec3f __device__ cook_torrance_sample_direction(PerRayData&amp; prd, vec3f&amp; view_direction, vec3f&amp; surface_normal, float roughness, float&amp; pdf)&#xD;&#xA;    {&#xD;&#xA;        float roughness2 = roughness * roughness;&#xD;&#xA;    &#xD;&#xA;        //rand_theta in [0.0, 1.0]&#xD;&#xA;        float rand_theta = prd.random();&#xD;&#xA;    &#xD;&#xA;        float theta = atan(roughness * sqrtf(rand_theta / (1.0f - rand_theta)));&#xD;&#xA;        float phi = prd.random() * 2.0f * M_PI;//Isotropic case&#xD;&#xA;    &#xD;&#xA;        float cos_theta = cos(theta);&#xD;&#xA;        float sin_theta = sin(theta);&#xD;&#xA;        float cos_phi = cos(phi);&#xD;&#xA;        float sin_phi = sin(phi);&#xD;&#xA;    &#xD;&#xA;        //+0.00001f to avoid dividing by 0&#xD;&#xA;        float denom = (roughness2 - 1.0f) * cos_theta * cos_theta + 1.0f + 0.00001;&#xD;&#xA;        float pdf_half_vector = (2 * roughness2 * cos_theta * sin_theta) / (denom * denom);&#xD;&#xA;    &#xD;&#xA;        vec3f sampled_normal_local = vec3f(cos_phi * sin_theta,&#xD;&#xA;                                           sin_phi * sin_theta,&#xD;&#xA;                                           cos_theta);&#xD;&#xA;    &#xD;&#xA;        vec3f view_direction_local = world_to_local(surface_normal, view_direction);&#xD;&#xA;    &#xD;&#xA;        //Section &quot;One Extra Step&quot; of the article&#xD;&#xA;        pdf = pdf_half_vector / (4 * dot(view_direction_local, sampled_normal_local) + 0.00001f);&#xD;&#xA;    &#xD;&#xA;        vec3f surface_normal_local = vec3f(0.0f, 0.0f, 1.0f);&#xD;&#xA;        vec3f reflected_direction_local = normalize(-view_direction_local - 2 * dot(-view_direction_local, sampled_normal_local) * sampled_normal_local);&#xD;&#xA;        vec3f reflected_dir_world = local_to_world(surface_normal, reflected_direction_local);&#xD;&#xA;    &#xD;&#xA;        return reflected_dir_world;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The sampled direction is then passed to the BRDF evaluation function (as the `light_direction` argument) which returns a color. I then divide this color by the PDF:&#xD;&#xA;&#xD;&#xA;    inline vec3f __device__ cook_torrance_brdf(const CookTorranceMaterial&amp; material, const vec3f&amp; view_dir, const vec3f&amp; light_direction, const vec3f&amp; normal)&#xD;&#xA;    {&#xD;&#xA;        vec3f halfway_vector = normalize(view_dir + light_direction);&#xD;&#xA;    &#xD;&#xA;        float NoV = max(dot(normal, view_dir),            0.0f);&#xD;&#xA;        float NoL = max(dot(normal, light_direction),  0.0f);&#xD;&#xA;        float NoH = max(dot(normal, halfway_vector),      0.0f);&#xD;&#xA;        float VoH = max(dot(view_dir, halfway_vector),    0.0f);&#xD;&#xA;    &#xD;&#xA;        vec3f F0 = (0.16f * (material.reflectance * material.reflectance));&#xD;&#xA;        //F0 for metals is equal to the albedo.&#xD;&#xA;        //We're going to lerp between the albedo and 0.04&#xD;&#xA;        //(previous value of F0) depending on&#xD;&#xA;        //the metalness of the material. A fully metalic material&#xD;&#xA;        //will thus have a F0 equal to its albedo&#xD;&#xA;        F0 = (1.0f - material.metallic) * F0 + material.metallic * material.albedo;&#xD;&#xA;    &#xD;&#xA;        //Fresnel: reflected portion of the light (1 - transmitted)&#xD;&#xA;        vec3f F = schlick_approximation(VoH, F0);&#xD;&#xA;        float NDF = GGX_NDF(NoH, material.roughness);&#xD;&#xA;        float G = geometry_Smith(NoV, NoL, material.roughness);&#xD;&#xA;    &#xD;&#xA;        vec3f kS = F;&#xD;&#xA;        vec3f kD = vec3f(1.0f) - kS;&#xD;&#xA;        kD *= 1.0 - material.metallic;&#xD;&#xA;    &#xD;&#xA;        vec3f numerator = NDF * G * F;&#xD;&#xA;        //+0.0001f to avoid dividng by zero if the dot products are 0&#xD;&#xA;        float denominator = 4.0f * NoV * NoL + 0.0001f;&#xD;&#xA;        vec3f specular = numerator / denominator;&#xD;&#xA;    &#xD;&#xA;        // add to outgoing radiance Lo&#xD;&#xA;        return (kD * material.albedo / (float)M_PI + specular);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    inline vec3f __device__ schlick_approximation(float cos_theta, const vec3f&amp; F0)&#xD;&#xA;    {&#xD;&#xA;        return F0 + (1.0f - F0) * powf((1.0f - cos_theta), 5.0f);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline float __device__ GGX_NDF(float NoH, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float alpha = roughness * roughness;&#xD;&#xA;        float alpha2 = alpha * alpha;&#xD;&#xA;        float NoH2 = NoH * NoH;&#xD;&#xA;    &#xD;&#xA;        float num = alpha2;&#xD;&#xA;        float denom = (NoH2 * (alpha2 - 1.0f) + 1.0f);&#xD;&#xA;        denom = (float)M_PI * denom * denom;&#xD;&#xA;    &#xD;&#xA;        return num / denom;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline float __device__ geometry_Schlick_GGX(float NoX, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float r = (roughness + 1.0);&#xD;&#xA;        float k = (r*r) / 8.0;&#xD;&#xA;    &#xD;&#xA;        float num = NoX;&#xD;&#xA;        float denom = NoX * (1.0 - k) + k;&#xD;&#xA;    &#xD;&#xA;        return num / denom;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    inline float __device__ geometry_Smith(float NoV, float NoL, float roughness)&#xD;&#xA;    {&#xD;&#xA;        float ggx2 = geometry_Schlick_GGX(NoV, roughness);&#xD;&#xA;        float ggx1 = geometry_Schlick_GGX(NoL, roughness);&#xD;&#xA;    &#xD;&#xA;        return ggx1 * ggx2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;However, this is giving me results brighter than expected for low roughness values. Here is a roughness of 0.05:&#xD;&#xA;&#xD;&#xA;[![Roughness = 0.05][2]][2]&#xD;&#xA;&#xD;&#xA;And for roughness lower than 0.013, black pixels start appearing (and eventually cover the entire image):&#xD;&#xA;&#xD;&#xA;[![Roughness = 0.012][3]][3]&#xD;&#xA;&#xD;&#xA;I noticed that for the too-bright case of the roughness = 0.05, my evaluation function returns color vectors whose RGB values are over 200 (sometimes way more than that, reaching thousands). I suppose this is okay and expected as long as the PDF counter balances it (which it doesn't because in those cases, the value of the PDF is only between ~5.0 and ~15.0)?&#xD;&#xA;&#xD;&#xA;  [1]: https://agraphicsguynotes.com/posts/sample_microfacet_brdf/&#xD;&#xA;  [2]: https://i.stack.imgur.com/BsEFl.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/7aokx.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="40901" PostHistoryTypeId="50" PostId="13210" RevisionGUID="ff3ed7bd-0b95-4d14-bfc9-3e3ca5295eab" CreationDate="2023-06-11T18:01:05.117" UserId="-1" />
  <row Id="40902" PostHistoryTypeId="5" PostId="13519" RevisionGUID="c86f96e4-0cc2-4ab6-a60b-83f6ced18c11" CreationDate="2023-06-12T11:14:10.503" UserId="13273" Comment="added 4805 characters in body" Text="I am rewriting this answer because of misunderstandings and a better explanation of the algorithm.&#xD;&#xA;&#xD;&#xA;The render pipeline is not well suited for this kind of task. It is better to use compute shaders instead.&#xD;&#xA;&#xD;&#xA;The following algorithm is designed to be run as a compute shader.&#xD;&#xA;&#xD;&#xA;First, let's start with a simple example:&#xD;&#xA;&#xD;&#xA;Suppose we have 50000 values stored in a shader storage buffer object (SSBO1). And let us further assume that all values are `1`. So figure 1 shows the input data.&#xD;&#xA;&#xD;&#xA;[![Enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** 50000 data points, each has the value `1`.&#xD;&#xA;&#xD;&#xA;This algorithm calculates the cumulative sum. For our simple example, the result looks like Figure 2.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** The final result of the simple example (cumulative sum / discrete integral).&#xD;&#xA;&#xD;&#xA;Compute shaders can have different workgroup sizes. In our case, we try to keep the workgroup size as small as possible, with respect to the minimum warp/wave length of 32 (Nvidia) 64 (AMD). Let's assume we are using an AMD graphics card, then our workgroup size is (x = 64, y = 1, z = 1).&#xD;&#xA;The algorithm needs additional SSBOs to store intermediate values. The additional SSBOs will contain the following number of values:&#xD;&#xA;    &#xD;&#xA;    unsigned int workgroupSize = 64;&#xD;&#xA;    unsigned int dataCount = 50000;&#xD;&#xA;&#xD;&#xA;    unsigned int SSBO2_count = static_cast&lt;unsigned int&gt;(ceil(static_cast&lt;float&gt;(inputDataCount) / workgroupSize)); // 782&#xD;&#xA;    unsigned int SSBO3_count = static_cast&lt;unsigned int&gt;(ceil(static_cast&lt;float&gt;(SSBO2_count) / workgroupSize)); //13&#xD;&#xA;&#xD;&#xA;The first compute shader will work as follows:&#xD;&#xA;Each invocation will load the global value from SSBO1 (original data) and store the value in shared memory so that other calls within that workgroup can quickly access that value. Then a `barrier` is needed to ensure that all data is loaded correctly. Then the first invocation within each workgroup accumulates these values while updating the original SSBO1, and stores the accumulated workgroup result to SSBO2.&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 1) buffer SSBOInput&#xD;&#xA;    {&#xD;&#xA;        float values[]; //first execution: 50000 values. Second execution: 782 values&#xD;&#xA;    }ssboInput;&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer SSBOOutput&#xD;&#xA;    {&#xD;&#xA;        float values[]; //first execution: 782 values. Second execution 13 values&#xD;&#xA;    }ssboOutput;    &#xD;&#xA;&#xD;&#xA;    shared float loadedValues[64];&#xD;&#xA;    uniform int countData;&#xD;&#xA;    uniform int writeToOutput;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        loadedValues[gl_LocalInvocationIndex] = 0.0;&#xD;&#xA;        if(gl_GlobalInvocationID.x &lt; countData) //check if inside ssbo1&#xD;&#xA;        {&#xD;&#xA;            loadedValues[gl_LocalInvocationIndex] = ssboInput.values[gl_GlobalInvocationID.x];&#xD;&#xA;        }&#xD;&#xA;        barrier(); //ensure, that all values are loaded to shared memory&#xD;&#xA;        if(gl_LocalInvocationIndex == 0)&#xD;&#xA;        {&#xD;&#xA;            float sum = 0;&#xD;&#xA;            for(int i = 0; i &lt; 64; ++i)&#xD;&#xA;            {&#xD;&#xA;                sum += loadedValues[i];&#xD;&#xA;                if(gl_GlobalInvocationID.x + i &lt; countData)&#xD;&#xA;                {&#xD;&#xA;                    ssboInput.values[gl_GlobalInvocationID.x + i] = sum;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            if(writeToOutput == 1)&#xD;&#xA;                ssboOutput.values[gl_WorkGroupID.x] = sum;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Bind SSBO1 to binding location 1 (ssboInput) and SSBO2 to binding location 2 (ssboOutput). The uniforms `countData` = 50000 and `writeToOutput` = 1.&#xD;&#xA;After running 782 workgroups, the values will look like Figure 3.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][3]][3]&#xD;&#xA;  &#xD;&#xA;**Figure 3:** These are the values stored in SSBO1 after the compute shader is executed.&#xD;&#xA;&#xD;&#xA;In our example, the SSBO2 (782 data points) will all store the value &quot;64&quot;. This is the case because the input values are all &quot;1&quot;. If we ask for the cumulative value of index (e.g. 200), we only need to calculate the following:&#xD;&#xA;&#xD;&#xA;$$indexMax = floor(200 / 64)$$&#xD;&#xA;$$CumulativeSum = SSBO1[200] + \sum_{i = 0}^{indexMax}(SSBO2[i])$$&#xD;&#xA;&#xD;&#xA;If we look at the equation, we will see that the problem is still the same, except that the difference is between 50000 and 782 data points.&#xD;&#xA;&#xD;&#xA;**So we do the same thing again.&#xD;&#xA;First, bind SSBO2 to binding slot 1. And bind SSBO3 to binding slot 2.&#xD;&#xA;Change the variable `countData` to 782. writeToOutput&quot; = 1. And run the compute shader with 13 workgroups.&#xD;&#xA;&#xD;&#xA;**Let's take a look at the SSBO value:**.&#xD;&#xA;SSBO1 is not touched and has the values from figure 3. SSBO2 has changed! The values are accumulated depending on the workgroup size (see Figure 4). SSBO3 is now filled, the values are all `4096`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Enter image description here][4]]&#xD;&#xA;&#xD;&#xA;**Figure 4:** These are the values stored in SSBO2 after the second compute shader call.&#xD;&#xA;&#xD;&#xA;**So we do the same thing again for the last time:** This time it is the last execution of this compute shader. We bind SSBO3 to binding slot 1 and disable `writeToOutput` = 0. `countData` = 13. We only need to execute one workgroup.&#xD;&#xA;&#xD;&#xA;**Final step!**&#xD;&#xA;&#xD;&#xA;The precalculations are finished. Now we can compute the cumulative sum of the individual values within $log_{64}(50000)$ steps. The following compute shader stores the cumulative sum in SSBO1.&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 1) buffer SSBO1&#xD;&#xA;    {&#xD;&#xA;        float values[]; //50000 values&#xD;&#xA;    }ssbo1;&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer SSBO2&#xD;&#xA;    {&#xD;&#xA;        float values[]; //782 values&#xD;&#xA;    }ssbo2;   &#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 3) buffer SSBO3&#xD;&#xA;    {&#xD;&#xA;        float values[]; //13 values&#xD;&#xA;    }ssbo3;    &#xD;&#xA;&#xD;&#xA;    uniform int countData;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        if(gl_GlobalInvocationID.x &lt; countData) //check if inside ssbo1&#xD;&#xA;        {&#xD;&#xA;            float sum1 = ssbo1.values[gl_GlobalInvocationID.x];&#xD;&#xA;            int index2 = gl_GlobalInvocationID.x / 64 - 1;&#xD;&#xA;            float sum2 = index2 &gt;= 0 ? ssbo2.values[index2] : 0;&#xD;&#xA;            int index3 = index2 / 64 - 1;&#xD;&#xA;            float sum3 = index3 &gt;= 0 ? ssbo3.values[index3] : 0;&#xD;&#xA;&#xD;&#xA;            //store cululative sum&#xD;&#xA;            ssbo1.values[gl_GlobalInvocationID.x] = sum1 + sum2 + sum3;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The cumulative sum is stored in SSBO1 (see Figure 2).&#xD;&#xA;&#xD;&#xA;This code has not been tested yet. So there might be some sintax errors in it.... Sorry for that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/37ZsO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wMKTM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/S33rn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/oqdv7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40903" PostHistoryTypeId="50" PostId="10025" RevisionGUID="4e341cd3-6697-454c-a787-67938301b214" CreationDate="2023-06-13T04:07:20.903" UserId="-1" />
  <row Id="40904" PostHistoryTypeId="5" PostId="13519" RevisionGUID="ed22225e-a5d9-4458-9d7a-88d9543b8a71" CreationDate="2023-06-13T08:13:32.263" UserId="13273" Comment="added 2 characters in body" Text="I am rewriting this answer because of misunderstandings and a better explanation of the algorithm.&#xD;&#xA;&#xD;&#xA;The render pipeline is not well suited for this kind of task. It is better to use compute shaders instead.&#xD;&#xA;&#xD;&#xA;The following algorithm is designed to be run as a compute shader.&#xD;&#xA;&#xD;&#xA;First, let's start with a simple example:&#xD;&#xA;&#xD;&#xA;Suppose we have 50000 values stored in a shader storage buffer object (SSBO1). And let us further assume that all values are `1`. So figure 1 shows the input data.&#xD;&#xA;&#xD;&#xA;[![Enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** 50000 data points, each has the value `1`.&#xD;&#xA;&#xD;&#xA;This algorithm calculates the cumulative sum. For our simple example, the result looks like Figure 2.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** The final result of the simple example (cumulative sum / discrete integral).&#xD;&#xA;&#xD;&#xA;Compute shaders can have different workgroup sizes. In our case, we try to keep the workgroup size as small as possible, with respect to the minimum warp/wave length of 32 (Nvidia) 64 (AMD). Let's assume we are using an AMD graphics card, then our workgroup size is (x = 64, y = 1, z = 1).&#xD;&#xA;The algorithm needs additional SSBOs to store intermediate values. The additional SSBOs will contain the following number of values:&#xD;&#xA;    &#xD;&#xA;    unsigned int workgroupSize = 64;&#xD;&#xA;    unsigned int dataCount = 50000;&#xD;&#xA;&#xD;&#xA;    unsigned int SSBO2_count = static_cast&lt;unsigned int&gt;(ceil(static_cast&lt;float&gt;(inputDataCount) / workgroupSize)); // 782&#xD;&#xA;    unsigned int SSBO3_count = static_cast&lt;unsigned int&gt;(ceil(static_cast&lt;float&gt;(SSBO2_count) / workgroupSize)); //13&#xD;&#xA;&#xD;&#xA;The first compute shader will work as follows:&#xD;&#xA;Each invocation will load the global value from SSBO1 (original data) and store the value in shared memory so that other calls within that workgroup can quickly access that value. Then a `barrier` is needed to ensure that all data is loaded correctly. Then the first invocation within each workgroup accumulates these values while updating the original SSBO1, and stores the accumulated workgroup result to SSBO2.&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 1) buffer SSBOInput&#xD;&#xA;    {&#xD;&#xA;        float values[]; //first execution: 50000 values. Second execution: 782 values&#xD;&#xA;    }ssboInput;&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer SSBOOutput&#xD;&#xA;    {&#xD;&#xA;        float values[]; //first execution: 782 values. Second execution 13 values&#xD;&#xA;    }ssboOutput;    &#xD;&#xA;&#xD;&#xA;    shared float loadedValues[64];&#xD;&#xA;    uniform int countData;&#xD;&#xA;    uniform int writeToOutput;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        loadedValues[gl_LocalInvocationIndex] = 0.0;&#xD;&#xA;        if(gl_GlobalInvocationID.x &lt; countData) //check if inside ssbo1&#xD;&#xA;        {&#xD;&#xA;            loadedValues[gl_LocalInvocationIndex] = ssboInput.values[gl_GlobalInvocationID.x];&#xD;&#xA;        }&#xD;&#xA;        barrier(); //ensure, that all values are loaded to shared memory&#xD;&#xA;        if(gl_LocalInvocationIndex == 0)&#xD;&#xA;        {&#xD;&#xA;            float sum = 0;&#xD;&#xA;            for(int i = 0; i &lt; 64; ++i)&#xD;&#xA;            {&#xD;&#xA;                sum += loadedValues[i];&#xD;&#xA;                if(gl_GlobalInvocationID.x + i &lt; countData)&#xD;&#xA;                {&#xD;&#xA;                    ssboInput.values[gl_GlobalInvocationID.x + i] = sum;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            if(writeToOutput == 1)&#xD;&#xA;                ssboOutput.values[gl_WorkGroupID.x] = sum;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Bind SSBO1 to binding location 1 (ssboInput) and SSBO2 to binding location 2 (ssboOutput). The uniforms `countData` = 50000 and `writeToOutput` = 1.&#xD;&#xA;After running 782 workgroups, the values will look like Figure 3.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][3]][3]&#xD;&#xA;  &#xD;&#xA;**Figure 3:** These are the values stored in SSBO1 after the compute shader is executed.&#xD;&#xA;&#xD;&#xA;In our example, the SSBO2 (782 data points) will all store the value &quot;64&quot;. This is the case because the input values are all &quot;1&quot;. If we ask for the cumulative value of index (e.g. 200), we only need to calculate the following:&#xD;&#xA;&#xD;&#xA;$$indexMax = floor(200 / 64)-1$$&#xD;&#xA;$$CumulativeSum = SSBO1[200] + \sum_{i = 0}^{indexMax}(SSBO2[i])$$&#xD;&#xA;&#xD;&#xA;If we look at the equation, we will see that the problem is still the same, except that the difference is between 50000 and 782 data points.&#xD;&#xA;&#xD;&#xA;**So we do the same thing again.&#xD;&#xA;First, bind SSBO2 to binding slot 1. And bind SSBO3 to binding slot 2.&#xD;&#xA;Change the variable `countData` to 782. writeToOutput&quot; = 1. And run the compute shader with 13 workgroups.&#xD;&#xA;&#xD;&#xA;**Let's take a look at the SSBO value:**.&#xD;&#xA;SSBO1 is not touched and has the values from figure 3. SSBO2 has changed! The values are accumulated depending on the workgroup size (see Figure 4). SSBO3 is now filled, the values are all `4096`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Enter image description here][4]]&#xD;&#xA;&#xD;&#xA;**Figure 4:** These are the values stored in SSBO2 after the second compute shader call.&#xD;&#xA;&#xD;&#xA;**So we do the same thing again for the last time:** This time it is the last execution of this compute shader. We bind SSBO3 to binding slot 1 and disable `writeToOutput` = 0. `countData` = 13. We only need to execute one workgroup.&#xD;&#xA;&#xD;&#xA;**Final step!**&#xD;&#xA;&#xD;&#xA;The precalculations are finished. Now we can compute the cumulative sum of the individual values within $log_{64}(50000)$ steps. The following compute shader stores the cumulative sum in SSBO1.&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 1) buffer SSBO1&#xD;&#xA;    {&#xD;&#xA;        float values[]; //50000 values&#xD;&#xA;    }ssbo1;&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer SSBO2&#xD;&#xA;    {&#xD;&#xA;        float values[]; //782 values&#xD;&#xA;    }ssbo2;   &#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 3) buffer SSBO3&#xD;&#xA;    {&#xD;&#xA;        float values[]; //13 values&#xD;&#xA;    }ssbo3;    &#xD;&#xA;&#xD;&#xA;    uniform int countData;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        if(gl_GlobalInvocationID.x &lt; countData) //check if inside ssbo1&#xD;&#xA;        {&#xD;&#xA;            float sum1 = ssbo1.values[gl_GlobalInvocationID.x];&#xD;&#xA;            int index2 = gl_GlobalInvocationID.x / 64 - 1;&#xD;&#xA;            float sum2 = index2 &gt;= 0 ? ssbo2.values[index2] : 0;&#xD;&#xA;            int index3 = index2 / 64 - 1;&#xD;&#xA;            float sum3 = index3 &gt;= 0 ? ssbo3.values[index3] : 0;&#xD;&#xA;&#xD;&#xA;            //store cululative sum&#xD;&#xA;            ssbo1.values[gl_GlobalInvocationID.x] = sum1 + sum2 + sum3;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The cumulative sum is stored in SSBO1 (see Figure 2).&#xD;&#xA;&#xD;&#xA;This code has not been tested yet. So there might be some sintax errors in it.... Sorry for that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/37ZsO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wMKTM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/S33rn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/oqdv7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40905" PostHistoryTypeId="50" PostId="9267" RevisionGUID="c20ba5a3-a9de-4069-b270-a01aebd41257" CreationDate="2023-06-13T12:01:35.257" UserId="-1" />
  <row Id="40906" PostHistoryTypeId="2" PostId="13525" RevisionGUID="a0101b5a-5197-4dd2-9d54-8f5edae14b8c" CreationDate="2023-06-13T17:18:44.400" UserId="7869" Text="Suppose, in a Kajiya style path tracing algorithm, I have `100x100` pixels, and I am using `32 samples per pixel`. So, the total number of samples `is 320000`. &#xD;&#xA;&#xD;&#xA;Now, if I render the same scene with `25x25` pixels (I meant, then upscale it to `100x100` resolution), and use `8 samples per pixel`, the total samples are `5000`. &#xD;&#xA;&#xD;&#xA;From these two, can I theoretically estimate that my new path tracing can be `(320000/5000) = 64 times` faster? &#xD;&#xA;&#xD;&#xA;How to calculate the theoretical performance gain in path tracing? Would appreciate any suggestions. " ContentLicense="CC BY-SA 4.0" />
  <row Id="40908" PostHistoryTypeId="1" PostId="13525" RevisionGUID="a0101b5a-5197-4dd2-9d54-8f5edae14b8c" CreationDate="2023-06-13T17:18:44.400" UserId="7869" Text="Theoretical speedup from sample number in path tracing algorithm" ContentLicense="CC BY-SA 4.0" />
  <row Id="40909" PostHistoryTypeId="3" PostId="13525" RevisionGUID="a0101b5a-5197-4dd2-9d54-8f5edae14b8c" CreationDate="2023-06-13T17:18:44.400" UserId="7869" Text="|pathtracing|performance|importance-sampling|supersampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40910" PostHistoryTypeId="2" PostId="13526" RevisionGUID="5b4fc71f-b343-4f3f-9ca3-9f8c2127ecbb" CreationDate="2023-06-13T18:39:42.867" UserDisplayName="user1703" Text="There is no reason to think that the time to trace a ray and evaluate the illumination model will vary significantly between the two cases at nearby  locations (even using acceleration techniques that exploit locality), nor is there a reason to think that upscaling will represent a significant fraction of the workload.&#xD;&#xA;&#xD;&#xA;So the ratio of the numbers of rays traced should be an excellent estimate of the speedup." ContentLicense="CC BY-SA 4.0" />
  <row Id="40916" PostHistoryTypeId="2" PostId="13528" RevisionGUID="f06c8ef5-5221-407d-ada8-13048e971b8d" CreationDate="2023-06-13T19:48:02.010" UserId="20083" Text="I have noticed that all GeForce RTX cards, without exception, have an equal number of RT cores as they have streaming multiprocessors (SM). From this fact I assume that each RT core is associated with one SM. In other words, each SM has an RT core available for it to use.&#xD;&#xA;&#xD;&#xA;But I am curious to know: How many rays can one RT core calculate simultaneously? Is it just one, or is it more than one?&#xD;&#xA;&#xD;&#xA;Given that an SM has (typically) 128 cores, I wouldn't be surprised if an RT core can likewise calculate 128 rays simultaneously, so that each SM core can have its own ray. Maybe even a multiple of 128, so that each SM core can have several rays traced at once. However, I cannot find corroboration of this anywhere.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40918" PostHistoryTypeId="1" PostId="13528" RevisionGUID="f06c8ef5-5221-407d-ada8-13048e971b8d" CreationDate="2023-06-13T19:48:02.010" UserId="20083" Text="How many rays can one RT core calculate simultaneously?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40919" PostHistoryTypeId="3" PostId="13528" RevisionGUID="f06c8ef5-5221-407d-ada8-13048e971b8d" CreationDate="2023-06-13T19:48:02.010" UserId="20083" Text="|raytracing|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40920" PostHistoryTypeId="2" PostId="13529" RevisionGUID="3fcb1418-b883-4181-9bee-c24716f40591" CreationDate="2023-06-13T22:29:11.327" UserId="10096" Text="In Veach's thesis the MIS weights (e.g. using the balance heuristic) for two strategies with densities $p_1, p_2$ are given as $w_1(x) = \frac{p_1(x)}{p_1(x)+p_2(x)}$ and $w_2(x) = \frac{p_2(x)}{p_1(x)+p_2(x)}$. Veach uses his path integral formulation, which essentially treats all densities as defined w.r.t. the area measure instead of the solid angle measure. I don't see anything stopping me from rewriting those w.r.t. the solid angle measure, or even keeping $p_1$ w.r.t. the solid angle measure, and $p_2$ w.r.t. the area measure. I have not seen the latter anywhere, however, and I assume there is a good reason for that.&#xD;&#xA;&#xD;&#xA;I mention that there is no constraint on the measure w.r.t. which the densities are defined in the weighting function, since the requirement here is that $w_1(x)+w_2(x) = 1$, as we use that to split the integral in two parts. It is clear that this holds regardless how I pick $p_1$ and $p_2$ (provided that $p_1+p_2\ne 0$). So is there a formal mathematical justification for the densities being considered exclusively w.r.t. the area measure or the solid angle measure? Would I necessarily get a higher variance by mixing densities w.r.t. different measures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40922" PostHistoryTypeId="1" PostId="13529" RevisionGUID="3fcb1418-b883-4181-9bee-c24716f40591" CreationDate="2023-06-13T22:29:11.327" UserId="10096" Text="Motivation for densities wrt the same measure in MIS" ContentLicense="CC BY-SA 4.0" />
  <row Id="40923" PostHistoryTypeId="3" PostId="13529" RevisionGUID="3fcb1418-b883-4181-9bee-c24716f40591" CreationDate="2023-06-13T22:29:11.327" UserId="10096" Text="|raytracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40924" PostHistoryTypeId="50" PostId="8935" RevisionGUID="059e00e3-c513-4cbb-9812-d471a7f0582e" CreationDate="2023-06-14T02:06:00.733" UserId="-1" />
  <row Id="40926" PostHistoryTypeId="50" PostId="13355" RevisionGUID="c2192e87-7eeb-4ced-b13c-609bb0f9a5b0" CreationDate="2023-06-14T13:00:50.177" UserId="-1" />
  <row Id="40927" PostHistoryTypeId="2" PostId="13530" RevisionGUID="5056a1a7-01b3-4fef-a85e-0d90a23d0386" CreationDate="2023-06-14T23:12:17.503" UserId="20089" Text="I've ran into the same problem in the same exact situation. How I fixed it was to draw using GL_LINE_STRIP inside the render loop and discard the glPolygonMode code.&#xD;&#xA;&#xD;&#xA;    glDrawArrays(GL_LINE_STRIP, 0, 3);&#xD;&#xA;&#xD;&#xA;This workaround does work, but it would be very appreciated if someone smarter than me could figure out why glPolygonMode doesn't work in such cases. I'm aware that this post is a year old, but I hope this helps the people out there!" ContentLicense="CC BY-SA 4.0" />
  <row Id="40929" PostHistoryTypeId="5" PostId="13519" RevisionGUID="cea294ed-a0e7-43a0-869b-15f995102d95" CreationDate="2023-06-15T07:02:31.640" UserId="13273" Comment="added 9 characters in body" Text="I am rewriting this answer because of misunderstandings and a better explanation of the algorithm.&#xD;&#xA;&#xD;&#xA;The render pipeline is not well suited for this kind of task. It is better to use compute shaders instead.&#xD;&#xA;&#xD;&#xA;The following algorithm is designed to be run as a compute shader.&#xD;&#xA;&#xD;&#xA;First, let's start with a simple example:&#xD;&#xA;&#xD;&#xA;Suppose we have 50000 values stored in a shader storage buffer object (SSBO1). And let us further assume that all values are `1`. So figure 1 shows the input data.&#xD;&#xA;&#xD;&#xA;[![Enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** 50000 data points, each has the value `1`.&#xD;&#xA;&#xD;&#xA;This algorithm calculates the cumulative sum. For our simple example, the result looks like Figure 2.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** The final result of the simple example (cumulative sum / discrete integral).&#xD;&#xA;&#xD;&#xA;Compute shaders can have different workgroup sizes. In our case, we try to keep the workgroup size as small as possible, with respect to the minimum warp/wave length of 32 (Nvidia) 64 (AMD). Let's assume we are using an AMD graphics card, then our workgroup size is (x = 64, y = 1, z = 1).&#xD;&#xA;The algorithm needs additional SSBOs to store intermediate values. The additional SSBOs will contain the following number of values:&#xD;&#xA;    &#xD;&#xA;    unsigned int workgroupSize = 64;&#xD;&#xA;    unsigned int dataCount = 50000;&#xD;&#xA;&#xD;&#xA;    unsigned int SSBO2_count = static_cast&lt;unsigned int&gt;(ceil(static_cast&lt;float&gt;(inputDataCount) / workgroupSize)); // 782&#xD;&#xA;    unsigned int SSBO3_count = static_cast&lt;unsigned int&gt;(ceil(static_cast&lt;float&gt;(SSBO2_count) / workgroupSize)); //13&#xD;&#xA;&#xD;&#xA;The first compute shader will work as follows:&#xD;&#xA;Each invocation will load the global value from SSBO1 (original data) and store the value in shared memory so that other invocations within that workgroup can quickly access that value. Then a `barrier` is needed to ensure that all data is loaded correctly. Then the first invocation within each workgroup accumulates these values while updating the original SSBO1, and stores the accumulated workgroup result to SSBO2.&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 1) buffer SSBOInput&#xD;&#xA;    {&#xD;&#xA;        float values[]; //first execution: 50000 values. Second execution: 782 values&#xD;&#xA;    }ssboInput;&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer SSBOOutput&#xD;&#xA;    {&#xD;&#xA;        float values[]; //first execution: 782 values. Second execution 13 values&#xD;&#xA;    }ssboOutput;    &#xD;&#xA;&#xD;&#xA;    shared float loadedValues[64];&#xD;&#xA;    uniform int countData;&#xD;&#xA;    uniform int writeToOutput;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        loadedValues[gl_LocalInvocationIndex] = 0.0;&#xD;&#xA;        if(gl_GlobalInvocationID.x &lt; countData) //check if inside ssbo1&#xD;&#xA;        {&#xD;&#xA;            loadedValues[gl_LocalInvocationIndex] = ssboInput.values[gl_GlobalInvocationID.x];&#xD;&#xA;        }&#xD;&#xA;        barrier(); //ensure, that all values are loaded to shared memory&#xD;&#xA;        if(gl_LocalInvocationIndex == 0)&#xD;&#xA;        {&#xD;&#xA;            float sum = 0;&#xD;&#xA;            for(int i = 0; i &lt; 64; ++i)&#xD;&#xA;            {&#xD;&#xA;                sum += loadedValues[i];&#xD;&#xA;                if(gl_GlobalInvocationID.x + i &lt; countData)&#xD;&#xA;                {&#xD;&#xA;                    ssboInput.values[gl_GlobalInvocationID.x + i] = sum;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            if(writeToOutput == 1)&#xD;&#xA;                ssboOutput.values[gl_WorkGroupID.x] = sum;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Bind SSBO1 to binding location 1 (ssboInput) and SSBO2 to binding location 2 (ssboOutput). The uniforms `countData` = 50000 and `writeToOutput` = 1.&#xD;&#xA;After running 782 workgroups, the values will look like Figure 3.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][3]][3]&#xD;&#xA;  &#xD;&#xA;**Figure 3:** These are the values stored in SSBO1 after the compute shader is executed.&#xD;&#xA;&#xD;&#xA;In our example, the SSBO2 (782 data points) will all store the value `64`. This is the case because the input values are all `1`. If we ask for the cumulative value of index (e.g. 200), we only need to calculate the following:&#xD;&#xA;&#xD;&#xA;$$indexMax = floor(200 / 64)-1$$&#xD;&#xA;$$CumulativeSum = SSBO1[200] + \sum_{i = 0}^{indexMax}(SSBO2[i])$$&#xD;&#xA;&#xD;&#xA;If we look at the equation, we will see that the problem is still the same, except that the difference is between 50000 and 782 data points.&#xD;&#xA;&#xD;&#xA;**So we do the same thing again.**&#xD;&#xA;First, bind SSBO2 to binding slot 1. And bind SSBO3 to binding slot 2.&#xD;&#xA;Change the variable `countData` to 782. `writeToOutput` = 1. And run the compute shader with 13 workgroups.&#xD;&#xA;&#xD;&#xA;**Let's take a look at the SSBO value:**.&#xD;&#xA;SSBO1 is not touched and has the values from figure 3. SSBO2 has changed! The values are accumulated depending on the workgroup size (see Figure 4). SSBO3 is now filled, the values are all `4096`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![Enter image description here][4]]&#xD;&#xA;&#xD;&#xA;**Figure 4:** These are the values stored in SSBO2 after the second compute shader call.&#xD;&#xA;&#xD;&#xA;**So we do the same thing again for the last time:** This time it is the last execution of this compute shader. We bind SSBO3 to binding slot 1 and disable `writeToOutput` = 0. `countData` = 13. We only need to execute one workgroup.&#xD;&#xA;&#xD;&#xA;**Final step!**&#xD;&#xA;&#xD;&#xA;The precalculations are finished. Now we can compute the cumulative sum of the individual values within $log_{64}(50000)$ steps. The following compute shader stores the cumulative sum in SSBO1.&#xD;&#xA;&#xD;&#xA;    #version 430 core&#xD;&#xA;    layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 1) buffer SSBO1&#xD;&#xA;    {&#xD;&#xA;        float values[]; //50000 values&#xD;&#xA;    }ssbo1;&#xD;&#xA;&#xD;&#xA;    layout(std430, binding = 2) buffer SSBO2&#xD;&#xA;    {&#xD;&#xA;        float values[]; //782 values&#xD;&#xA;    }ssbo2;   &#xD;&#xA;    &#xD;&#xA;    layout(std430, binding = 3) buffer SSBO3&#xD;&#xA;    {&#xD;&#xA;        float values[]; //13 values&#xD;&#xA;    }ssbo3;    &#xD;&#xA;&#xD;&#xA;    uniform int countData;&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        if(gl_GlobalInvocationID.x &lt; countData) //check if inside ssbo1&#xD;&#xA;        {&#xD;&#xA;            float sum1 = ssbo1.values[gl_GlobalInvocationID.x];&#xD;&#xA;            int index2 = gl_GlobalInvocationID.x / 64 - 1;&#xD;&#xA;            float sum2 = index2 &gt;= 0 ? ssbo2.values[index2] : 0;&#xD;&#xA;            int index3 = index2 / 64 - 1;&#xD;&#xA;            float sum3 = index3 &gt;= 0 ? ssbo3.values[index3] : 0;&#xD;&#xA;&#xD;&#xA;            //store cululative sum&#xD;&#xA;            ssbo1.values[gl_GlobalInvocationID.x] = sum1 + sum2 + sum3;&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The cumulative sum is stored in SSBO1 (see Figure 2).&#xD;&#xA;&#xD;&#xA;This code has not been tested yet. So there might be some sintax errors in it.... Sorry for that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/37ZsO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wMKTM.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/S33rn.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/oqdv7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40930" PostHistoryTypeId="2" PostId="13531" RevisionGUID="606ff1f6-5d31-4d87-914a-ec731c329791" CreationDate="2023-06-15T07:39:39.860" UserId="7724" Text="If you want to determine those matrices you have to use the knot vector $[0, 0, 0, 0, 4, 5, 6,...]$ and write out the expressions using the Cox-DeBoor algorithm. I believe you will need to compute the functions on two knot spans and therefore obtain two different matrices.&#xD;&#xA;&#xD;&#xA;However, you can also use a little trick here by constructing a ghost point. If You construct a point $P_{g} = (2P_0 - P_1)$ and then construct apply $M_2$ to $\begin{bmatrix} &#xD;&#xA;           P_{g} \\&#xD;&#xA;           P_0 \\&#xD;&#xA;           P_1 \\&#xD;&#xA;           P_2&#xD;&#xA;         \end{bmatrix}$ you will end up with the following situation:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Here curve $a$ is constructed using control points $[P_{g}, P_0, P_1, P_2]$ and curve $b$ with $[P_0, P_1, P_2, P_3]$. Naturally, the same can be done at the end of the curve by creating a ghost point $P_g = 2P_n - P_{n-1}$. If you need the matrix you will have to substitute $(2P_0 - P_1)$ for $P_g$ and find out which functions act on $P_0$ and $P_1$ by writing out the equations and collecting the terms.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m9l1L.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40932" PostHistoryTypeId="2" PostId="13532" RevisionGUID="c27076aa-658d-4a07-9633-54397dd6c7c0" CreationDate="2023-06-15T20:42:09.720" UserId="20093" Text="I have been programing a simple ray marcher with GLES, using [The Book of Shaders editor](http://editor.thebookofshaders.com/). I noticed that on scenes with multiple objects (multiple SDFs), I am getting glitches on edges of object which are superimposed over other objects:&#xD;&#xA;&#xD;&#xA;[![Shader output][1]][1]&#xD;&#xA;&#xD;&#xA;The source of this shader is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#ifdef GL_ES&#xD;&#xA;precision highp float;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;uniform vec2 u_resolution;&#xD;&#xA;&#xD;&#xA;vec3 floorColor(vec3 pos) {&#xD;&#xA;    if(mod(floor(pos.x) + floor(pos.z), 2.0) &lt; 1.0) {&#xD;&#xA;        return vec3(0.7, 0.8, 0.7);&#xD;&#xA;    } else {&#xD;&#xA;        return vec3(0.3,0.4,0.3);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 iterate(vec3 ray){&#xD;&#xA;    vec3 position = vec3(0.0);&#xD;&#xA;    for(int i = 0; i &lt; 100; i++) {&#xD;&#xA;        float sphereF = length(position - vec3(0.0, 0.0, 2.0)) - 1.0;&#xD;&#xA;    	float floorF = position.y + 1.;&#xD;&#xA;    	float minF = min(sphereF, floorF);&#xD;&#xA;        position += minF*ray;&#xD;&#xA;        &#xD;&#xA;        if(minF &lt;= 0.01) { &#xD;&#xA;            if(sphereF &lt; floorF) {&#xD;&#xA;               return vec3(0.9, 0.2, 0.2);&#xD;&#xA;            } else {&#xD;&#xA;               return floorColor(position);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    return vec3(0.2, 0.5, 0.8);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec2 st = gl_FragCoord.xy/u_resolution.xy;&#xD;&#xA;    st.x *= u_resolution.x/u_resolution.y;&#xD;&#xA;	st = 2.0 * st - vec2(1.0); &#xD;&#xA;    &#xD;&#xA;    vec3 color = iterate(normalize(vec3(st.x, st.y, 1.0)));&#xD;&#xA;&#xD;&#xA;    gl_FragColor = vec4(color, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After a lot of debugging, I realized that glitches are produced return stantments inside loop in `iterate` function, but I am still not sure *why* this happens. &#xD;&#xA;&#xD;&#xA;Using other shader editors produced similar glitches.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZIzbH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40934" PostHistoryTypeId="1" PostId="13532" RevisionGUID="c27076aa-658d-4a07-9633-54397dd6c7c0" CreationDate="2023-06-15T20:42:09.720" UserId="20093" Text="Glirches with raymarcher shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="40935" PostHistoryTypeId="3" PostId="13532" RevisionGUID="c27076aa-658d-4a07-9633-54397dd6c7c0" CreationDate="2023-06-15T20:42:09.720" UserId="20093" Text="|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40936" PostHistoryTypeId="4" PostId="13532" RevisionGUID="1458a7a9-d8d5-46c6-a52f-f8be082d7be7" CreationDate="2023-06-15T21:26:10.470" UserId="20093" Comment="edited title" Text="Glitches with raymarcher shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="40937" PostHistoryTypeId="2" PostId="13533" RevisionGUID="0e286f6f-cb14-4f98-9cbf-d334368924e0" CreationDate="2023-06-16T13:20:31.187" UserId="20101" Text="Your code just works !&#xD;&#xA;&#xD;&#xA;There is no problem with your shader on my windows 10 laptop.&#xD;&#xA;Maybe your should try on another device.&#xD;&#xA;&#xD;&#xA;[![The shader works][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/uEnRi.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40939" PostHistoryTypeId="2" PostId="13534" RevisionGUID="5d4465a7-43f9-4fa2-80ef-3055b0eaec79" CreationDate="2023-06-16T14:28:44.843" UserId="7952" Text="The code isn't taking enough steps for the ray to hit anything where the sphere and the floor meet. minF is smaller in that region, so the ray marches forward until it runs out of steps and then gives up and returns the background color.&#xD;&#xA;&#xD;&#xA;A simple &quot;fix&quot; is to increase the number of steps. 200 worked for me. Then you can also decrease the minF&lt;0.01 to something that gives a lot better rendering. Like 0.0001. &#xD;&#xA;&#xD;&#xA;Also position is being recomputed before calling floorColor this alters the pattern on the floor increasingly as the ray marches. It's usually best to recompute the ray at the very end of the loop." ContentLicense="CC BY-SA 4.0" />
  <row Id="40944" PostHistoryTypeId="50" PostId="8888" RevisionGUID="1f6c7de0-e745-49ce-90e8-908cc6f6f81b" CreationDate="2023-06-17T20:03:20.537" UserId="-1" />
  <row Id="40949" PostHistoryTypeId="2" PostId="13536" RevisionGUID="453440e2-637d-41e8-93b0-fe7157cd5e8d" CreationDate="2023-06-19T01:08:51.133" UserId="18200" Text="Many render engines implement the microfacet model for rendering surfaces that are rough, metallic, and/or transparent, a concept first published in &quot;[A Reflectance Model for Computer Graphics](https://dl.acm.org/doi/10.1145/357290.357293)&quot; This model implies that surfaces comprise a large number of microfacets, each with a random slope. The slopes of all the microfacets on a surface can be categorized with a facet slope distribution function.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Some render engines like EEVEE and Cycles allow users to select such function (called a &quot;light scattering distribution function&quot; in Blender), and the default is **GGX**.&#xD;&#xA;&#xD;&#xA; [![Blender nodes with GGX][1]][1] &#xD;&#xA;&#xD;&#xA;GGX is presented in the paper &quot;[Microfacet Models for Refraction through Rough Surfaces](https://dl.acm.org/doi/10.5555/2383847.2383874).&quot; &#xD;&#xA;&#xD;&#xA;In this paper's introduction:&#xD;&#xA;&#xD;&#xA;&gt; We also introduce a new microfacet distribution, which we call GGX...&#xD;&#xA;&#xD;&#xA;...but they never explain *why* they call it GGX. &#xD;&#xA;&#xD;&#xA;Perhaps it's mentioned somewhere else?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/GwBkJ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40951" PostHistoryTypeId="1" PostId="13536" RevisionGUID="453440e2-637d-41e8-93b0-fe7157cd5e8d" CreationDate="2023-06-19T01:08:51.133" UserId="18200" Text="What does GGX stand for?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40952" PostHistoryTypeId="3" PostId="13536" RevisionGUID="453440e2-637d-41e8-93b0-fe7157cd5e8d" CreationDate="2023-06-19T01:08:51.133" UserId="18200" Text="|rendering|specular|microfacet|distribution|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40954" PostHistoryTypeId="2" PostId="13537" RevisionGUID="aa93696e-fd27-4057-b3a7-7c2d5c4afd58" CreationDate="2023-06-19T06:44:59.673" UserId="10578" Text="In many tutorials and examples code of DirectX 12 we can find ways to manage descriptors by creating a few descriptor heaps and allocating manually descriptors inside of them&#xD;&#xA;(e.g. in Mini Engine the `DescriptorHeap` class or the `UploadBuffer` in the excellent 3dgep tutorial).&#xD;&#xA;&#xD;&#xA;So far every example I found on the web does support allocation of `n` continuous descriptors and therefore implement a non trivial allocator to support it. However all the call sites where several descriptors are allocated at once seems more like a convenience than a requirement since each individual descriptors is then bound individually later in the code.&#xD;&#xA;&#xD;&#xA;I don't really understand in which case we *do* need to have continuous descriptors, other than possible cache friendliness.&#xD;&#xA;&#xD;&#xA;Is there specific feature or cases where it's required to have several descriptors next to each others ?&#xD;&#xA;&#xD;&#xA;The examples I found:&#xD;&#xA;- Mini Engine `DescriptorHeap`: https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/MiniEngine/Core/DescriptorHeap.h#L33&#xD;&#xA;- 3dgep `UploadBuffer`: https://www.3dgep.com/learning-directx-12-3/#UploadBufferAllocate&#xD;&#xA;- bgfx `DescriptorAllocator`: https://github.com/bkaradzic/bgfx/blob/master/src/renderer_d3d12.h#L173&#xD;&#xA;- The-Forge `DescriptorHeap`: https://github.com/ConfettiFX/The-Forge/blob/master/Common_3/Graphics/Direct3D12/Direct3D12.cpp#L397&#xD;&#xA;- Dilligent Graphics: http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-descriptor-heaps/&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40956" PostHistoryTypeId="1" PostId="13537" RevisionGUID="aa93696e-fd27-4057-b3a7-7c2d5c4afd58" CreationDate="2023-06-19T06:44:59.673" UserId="10578" Text="When do we need Dx12 Descriptors to be contiguous?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40957" PostHistoryTypeId="3" PostId="13537" RevisionGUID="aa93696e-fd27-4057-b3a7-7c2d5c4afd58" CreationDate="2023-06-19T06:44:59.673" UserId="10578" Text="|rendering|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40958" PostHistoryTypeId="5" PostId="13537" RevisionGUID="127e2738-f3d9-4bb5-91d0-a3661c742194" CreationDate="2023-06-19T06:57:20.113" UserId="10578" Comment="added 19 characters in body" Text="In many tutorials and examples code of DirectX 12 we can find ways to manage descriptors by creating a few descriptor heaps and allocating manually descriptors inside of them&#xD;&#xA;(e.g. in Mini Engine the `DescriptorHeap` class or the `DescriptorAllocator` in the excellent 3dgep tutorial).&#xD;&#xA;&#xD;&#xA;So far every example I found on the web does support allocation of `n` continuous descriptors and therefore implement a non trivial allocator to support it. However all the call sites where several descriptors are allocated at once seems more like a convenience than a requirement since each individual descriptors is then bound individually later in the code.&#xD;&#xA;&#xD;&#xA;I don't really understand in which case we *do* need to have continuous descriptors, other than possible cache friendliness.&#xD;&#xA;&#xD;&#xA;Is there specific feature or cases where it's required to have several descriptors next to each others ?&#xD;&#xA;&#xD;&#xA;The examples I found:&#xD;&#xA;- Mini Engine `DescriptorHeap`: https://github.com/microsoft/DirectX-Graphics-Samples/blob/master/MiniEngine/Core/DescriptorHeap.h#L33&#xD;&#xA;- 3dgep `DescriptorAllocator`: https://www.3dgep.com/learning-directx-12-3/#DescriptorAllocator_Class&#xD;&#xA;- bgfx `DescriptorAllocator`: https://github.com/bkaradzic/bgfx/blob/master/src/renderer_d3d12.h#L173&#xD;&#xA;- The-Forge `DescriptorHeap`: https://github.com/ConfettiFX/The-Forge/blob/master/Common_3/Graphics/Direct3D12/Direct3D12.cpp#L397&#xD;&#xA;- Dilligent Graphics: http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-descriptor-heaps/&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="40959" PostHistoryTypeId="2" PostId="13538" RevisionGUID="a90c372a-db9c-4635-94ae-5704c67c9a9d" CreationDate="2023-06-19T14:00:22.523" UserId="20114" Text="I have a problem that I cannot really wrap my head around. &#xD;&#xA;&#xD;&#xA;I have a minimal light stage setup to scan heads:&#xD;&#xA;&#xD;&#xA;I have cross polarized cameras and parallel polarized cameras.&#xD;&#xA;I have parallel polarized LEDs&#xD;&#xA;I capture k-frames and tracking frames&#xD;&#xA;I am able to:&#xD;&#xA;&#xD;&#xA;calculate normals and color albedos from Photometric Stereo (Woodham)&#xD;&#xA;calculate a mesh via Photogrammetry&#xD;&#xA;project normals, albedo and appearance on the mesh&#xD;&#xA;create a reflectance map (via parallel - cross)&#xD;&#xA;Does anybody have a tip?&#xD;&#xA;&#xD;&#xA;Thank you for your time!" ContentLicense="CC BY-SA 4.0" />
  <row Id="40961" PostHistoryTypeId="1" PostId="13538" RevisionGUID="a90c372a-db9c-4635-94ae-5704c67c9a9d" CreationDate="2023-06-19T14:00:22.523" UserId="20114" Text="How to solve ggx roughness from existing maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="40962" PostHistoryTypeId="3" PostId="13538" RevisionGUID="a90c372a-db9c-4635-94ae-5704c67c9a9d" CreationDate="2023-06-19T14:00:22.523" UserId="20114" Text="|brdf|ggx|photometric|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40967" PostHistoryTypeId="2" PostId="13540" RevisionGUID="42f2e078-58bc-4ab8-a421-cad0b286e895" CreationDate="2023-06-19T16:57:55.470" UserId="19537" Text="I got confused when implementing my own renderer. I read this from the PBR-book:&#xD;&#xA;&gt; Fortunately, there is an elegant solution to these problems. When evaluating the BSDF, we can use the geometric normal to decide if we should be evaluating reflection or transmission: if $w_i$ and $w_o$ lie in the same hemisphere with respect to $n_g$, we evaluate the BRDFs, and otherwise we evaluate the BTDFs. In evaluating the scattering equation, however, the dot product of the normal and the incident direction is still taken with the shading normal rather than the geometric normal.&#xD;&#xA;&#xD;&#xA;But when it comes to the calculation of refraction, I just can't find myself convinced, about when to use $n_g$ and when to use $n_s$. Here is thing, if I have an object like this:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;and when the light beam tries to enter the medium from the outside, I need to know:&#xD;&#xA;- Whether I should have reflection or refraction (depending on sampling the Fresnel term)&#xD;&#xA;- The IOR for outside and the inside of the interface, which is confusing since normally I use the dot product of ray direction and geometric normal to determine whether the ray points inwards or outwards.However, when geometric normal tells me the ray points inwards, the shading normal tells me otherwise, so I can't actually know the IOR for both sides.&#xD;&#xA;&#xD;&#xA;I don't quite see how this corresponds to things said in the PBR-book, since if we decide to have a transmission event according to $n_g$, the final calculate according to $n_s$ might make it look like it's having a reflection event... Any help would be much appreciated, I got totally confused here. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/5Qd7i.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40969" PostHistoryTypeId="1" PostId="13540" RevisionGUID="42f2e078-58bc-4ab8-a421-cad0b286e895" CreationDate="2023-06-19T16:57:55.470" UserId="19537" Text="Shading normal and geometric normal for refractive surface rendering" ContentLicense="CC BY-SA 4.0" />
  <row Id="40970" PostHistoryTypeId="3" PostId="13540" RevisionGUID="42f2e078-58bc-4ab8-a421-cad0b286e895" CreationDate="2023-06-19T16:57:55.470" UserId="19537" Text="|pbr|shading|normal-mapping|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40971" PostHistoryTypeId="2" PostId="13541" RevisionGUID="295c9035-f22b-4890-a2a5-eb117e9b5232" CreationDate="2023-06-19T19:14:24.993" UserId="18765" Text="According to E. Heitz ([Sampling the GGX Distribution of Visible Normals][1]) it stands for &quot;ground glass unknown&quot;. I am not sure what the word unknown means though.&#xD;&#xA;&#xD;&#xA;By the way, it is equivalent to [Trowbridge-Reitz distribution][2], introduced much earlier.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://jcgt.org/published/0007/04/01/paper.pdf&#xD;&#xA;  [2]: https://pharr.org/matt/blog/images/average-irregularity-representation-of-a-rough-surface-for-ray-reflection.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="40973" PostHistoryTypeId="2" PostId="13542" RevisionGUID="6c76852a-b917-482a-a28b-8dfe56b54aa6" CreationDate="2023-06-20T12:03:43.137" UserId="10980" Text="In simple words, a [reflectance map](https://link.springer.com/referenceworkentry/10.1007/978-3-030-63416-2_546) is a function `f(n)` that map a surface patch with normal `n` to its reflected radiance given a fixed viewing direction. According to [1]:&#xD;&#xA;&#xD;&#xA;&gt; The amount of light reflected by a surface element in a given direction depends on its optical properties, on its microstructure, and on the spatial and spectral distribution of the light sources. For many materials, the fraction of the total irradiance reflected toward the viewer depends only on the surface orientation. Horn [1] introduced the reflectance map as a way to specify scene radiance as a function of surface orientation, given the following simplifying assumptions:&#xD;&#xA;&gt;&#xD;&#xA;&gt; 1. The direction toward the viewer is the same at every visible point on the surface. This holds when image projection is orthographic.&#xD;&#xA;&gt;&#xD;&#xA;&gt; 2. The direction toward the light source is the same at every visible point on the surface. This holds for point light sources at infinity and for parallel (i.e., collimated) light sources.&#xD;&#xA;&#xD;&#xA;Thus, it is trivial to synthesize a reflectance map using an orthographic camera. As the primary rays from the camera are all parallel to each other. To syhthesize a reflectance map from it, one only needs to store the pixel intensity and its corresponding shading normal in the camera space, both of which are readily available in the G-buffer.&#xD;&#xA;&#xD;&#xA;My question is how can I synthesize a reflectance map from an image which is rendered using a perspective camera?&#xD;&#xA;&#xD;&#xA;[1] https://link.springer.com/referenceworkentry/10.1007/978-3-030-63416-2_546" ContentLicense="CC BY-SA 4.0" />
  <row Id="40975" PostHistoryTypeId="1" PostId="13542" RevisionGUID="6c76852a-b917-482a-a28b-8dfe56b54aa6" CreationDate="2023-06-20T12:03:43.137" UserId="10980" Text="How can I generate a reflectance map using a perspective camera?" ContentLicense="CC BY-SA 4.0" />
  <row Id="40976" PostHistoryTypeId="3" PostId="13542" RevisionGUID="6c76852a-b917-482a-a28b-8dfe56b54aa6" CreationDate="2023-06-20T12:03:43.137" UserId="10980" Text="|transformations|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40977" PostHistoryTypeId="5" PostId="13538" RevisionGUID="bdda0c2b-8963-49c7-a054-16284fd1795b" CreationDate="2023-06-21T16:18:33.210" UserId="506" Comment="improved formatting and title capitalization" Text="I have a problem that I cannot really wrap my head around. &#xD;&#xA;&#xD;&#xA;I have a minimal light stage setup to scan heads:&#xD;&#xA;&#xD;&#xA;I have cross polarized cameras and parallel polarized cameras.&#xD;&#xA;I have parallel polarized LEDs&#xD;&#xA;I capture k-frames and tracking frames&#xD;&#xA;I am able to:&#xD;&#xA;&#xD;&#xA;- calculate normals and color albedos from Photometric Stereo (Woodham)&#xD;&#xA;- calculate a mesh via Photogrammetry&#xD;&#xA;- project normals, albedo and appearance on the mesh&#xD;&#xA;- create a reflectance map (via parallel - cross)&#xD;&#xA;Does anybody have a tip?&#xD;&#xA;&#xD;&#xA;Thank you for your time!" ContentLicense="CC BY-SA 4.0" />
  <row Id="40978" PostHistoryTypeId="4" PostId="13538" RevisionGUID="bdda0c2b-8963-49c7-a054-16284fd1795b" CreationDate="2023-06-21T16:18:33.210" UserId="506" Comment="improved formatting and title capitalization" Text="How to solve GGX roughness from existing maps" ContentLicense="CC BY-SA 4.0" />
  <row Id="40979" PostHistoryTypeId="50" PostId="13484" RevisionGUID="336302b5-3792-4621-bbc2-e814b7e05185" CreationDate="2023-06-22T13:04:25.507" UserId="-1" />
  <row Id="40980" PostHistoryTypeId="2" PostId="13543" RevisionGUID="3bf174a1-a00c-4a2c-9c4f-64b238dece0e" CreationDate="2023-06-22T17:59:36.067" UserId="19537" Text="Now it looks like I have to try to figure it out myself... since I've waited for days without an answer. So I decided to dig into the code of `pbrt-v3` and I found what I need:  &#xD;&#xA;&#xD;&#xA;`Spectrum BSDF::Sample_f`: first we convert the world direction vector into the local frame. This can be found in `line 714 of src/core/reflection.cpp`:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;Vector3f wi, wo = WorldToLocal(woWorld);&#xD;&#xA;&#xD;&#xA;// and the WorldToLocal function just uses shading normal:&#xD;&#xA;// This can be found in line 178 of src/core/reflection.h:&#xD;&#xA;Vector3f WorldToLocal(const Vector3f &amp;v) const {&#xD;&#xA;    return Vector3f(Dot(v, ss), Dot(v, ts), Dot(v, ns));&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;And then, we start to sample the BSDF. We take the typical BSDF used in glass material `FresnelSpecular` for an example (refer to `line 487 of src/core/reflection.cpp`).&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;Spectrum f = bxdf-&gt;Sample_f(wo, &amp;wi, uRemapped, pdf, sampledType);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;- First, sampling according to Fresnel's law, and we can see that we are using shading normal here:&#xD;&#xA;&#xD;&#xA;    ```c++&#xD;&#xA;    Float F = FrDielectric(CosTheta(wo), etaA, etaB);&#xD;&#xA;    ```&#xD;&#xA;&#xD;&#xA;    since `wo` is converted to local frame (defined by shading normal)&#xD;&#xA;&#xD;&#xA;- Reflection sampling has nothing to do with ROI therefore we just use shading normal to calculate reflection. This is kinda trivial but I think I need to get back to this later and explain this with the picture posted in my question since I think there are some nasty situations. So we skip the if branch and focus the else branch.&#xD;&#xA;&#xD;&#xA;- Obviously, shading normal is used to decide the interior and exterior (ROI) for the medium:&#xD;&#xA;&#xD;&#xA;    ```c++&#xD;&#xA;    bool entering = CosTheta(wo) &gt; 0;&#xD;&#xA;    Float etaI = entering ? etaA : etaB;&#xD;&#xA;    Float etaT = entering ? etaB : etaA;&#xD;&#xA;    ```&#xD;&#xA;&#xD;&#xA;Actually, for specular reflection/transmission materials, we have no more thing to explain: `line 767`: &#xD;&#xA;&#xD;&#xA;```c++ &#xD;&#xA;if (!(bxdf-&gt;type &amp; BSDF_SPECULAR)) {&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;skip the rest of the `f` part and even if we need to use `f`, due to being specular, all we would get is zero anyway, so why bother? Therefore for the situation shown in the figure below, if we are using simple specular reflection &amp; transmission material, maybe we only have to stick with $n_s$. &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;But what about non-specular situation? For example, what if I use `MicrofacetReflection` / `MicrofacetTransmission` (the former requires no ROI, so I use this as a simple example, the latter does, though)? I present two examples below, and the logic we should pay attention to in `pbrt-v3` is (starting from `line 766`):&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;// Compute value of BSDF for sampled direction&#xD;&#xA;if (!(bxdf-&gt;type &amp; BSDF_SPECULAR)) {&#xD;&#xA;    bool reflect = Dot(*wiWorld, ng) * Dot(woWorld, ng) &gt; 0;&#xD;&#xA;    f = 0.;&#xD;&#xA;    for (int i = 0; i &lt; nBxDFs; ++i)&#xD;&#xA;        if (bxdfs[i]-&gt;MatchesFlags(type) &amp;&amp;&#xD;&#xA;            ((reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_REFLECTION)) ||&#xD;&#xA;             (!reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_TRANSMISSION))))&#xD;&#xA;            f += bxdfs[i]-&gt;f(wo, wi);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;| Reflection                                                   | Transmission (Refraction)                              |&#xD;&#xA;| ------------------------------------------------------------ | ------------------------------------------------------ |&#xD;&#xA;| [![enter image description here][2]][2] | [![enter image description here][3]][3]|&#xD;&#xA;&#xD;&#xA;- Reflection example. This is weird, it has the conflicts I mentioned in the question: $n_g$ and $n_s$ propose differently. However, if I understand correctly,  in this situation we have two directions on the different sides of the geometric surface ($n_g$), therefore `bool reflect` is `false` here. During the for loop  `reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_REFLECTION` will be `false ` and `!reflect &amp;&amp; (bxdfs[i]-&gt;type &amp; BSDF_TRANSMISSION)`  will be `false` again since `reflect = false` and `MicrofacetReflection` has type `BSDF_REFLECTION`... so `f` will actually be zero. I think it is reasonable, since we can't let the light leak beneath the geometric surface.&#xD;&#xA;&#xD;&#xA;- Transmission example. We use `MicrofacetTransmission` and sampled a transmission event, great. However, `bool reflect ` here will be `true` since both directions are on the same side about $n_g$. Again, the for loop results in a zero, since there is again a miss match (BSDF has transmission type, we sampled a transmission according to $n_s$ but $n_g$ tells us we are having a reflection event). So the result is again invalidated, in case we mistook the same side as fictional interior and exterior. I have to admit that this example feels kinda weird to me..., it's just a feeling and I can't actually put it accurately, but basically I think this is the case.&#xD;&#xA;&#xD;&#xA;To wrap up:&#xD;&#xA;&#xD;&#xA;-  Specular reflection &amp; transmission: stick with $n_s$ will be okay.&#xD;&#xA;- Non-specular: check if $n_g$ and $n_s$ agree with each other on which event should happen, and if there is a conflict, the spectrum should be made zero.&#xD;&#xA;&#xD;&#xA;These are just my understanding, I don't know if these are correct or not. Maybe I'll just implement these in my own renderer for testing. Notify me if anything feels wrong.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U5c7X.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/fTdT1.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8MIHt.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40982" PostHistoryTypeId="2" PostId="13544" RevisionGUID="68032c66-a72d-495a-9b81-b1b649281a2a" CreationDate="2023-06-22T21:36:24.083" UserId="20067" Text="I'm trying to figure out how to move a camera in orthographic 3D. The scene is orthographic in the sense that an object looks the same regardless of position. The only thing that may affect the size or shape of an object is zooming the scene or changing the viewing angle.&#xD;&#xA;&#xD;&#xA;The scene is rendered in WebGL: https://codepen.io/Candleout/pen/poxMLPB For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again.&#xD;&#xA;&#xD;&#xA;As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without altering its shape. What I need now is a good and practical way to zoom and change the viewing angle.&#xD;&#xA;&#xD;&#xA;The camera is positioned with the help of a lookAt function. But something tells me you wouldn't want to use the lookAt function as the primary tool for moving the camera?&#xD;&#xA;&#xD;&#xA;My guess is that you work with matrix calculations? Maybe you set the camera in a neutral position (something like cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];) and then apply transformations to that position?&#xD;&#xA;&#xD;&#xA;How would you typically zoom? By scaling the scene, or moving the camera? With my current code, moving the camera doesn't affect the size of an object." ContentLicense="CC BY-SA 4.0" />
  <row Id="40984" PostHistoryTypeId="1" PostId="13544" RevisionGUID="68032c66-a72d-495a-9b81-b1b649281a2a" CreationDate="2023-06-22T21:36:24.083" UserId="20067" Text="Move the camera in orthographic 3D" ContentLicense="CC BY-SA 4.0" />
  <row Id="40985" PostHistoryTypeId="3" PostId="13544" RevisionGUID="68032c66-a72d-495a-9b81-b1b649281a2a" CreationDate="2023-06-22T21:36:24.083" UserId="20067" Text="|transformations|matrix|webgl|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40986" PostHistoryTypeId="5" PostId="13544" RevisionGUID="fbc76ef8-48f3-4176-81f6-d013089d41e8" CreationDate="2023-06-22T21:49:27.613" UserId="20067" Comment="added 176 characters in body" Text="I'm trying to figure out how to move a camera in orthographic 3D. The scene is orthographic in the sense that an object looks the same regardless of position. The only thing that may affect the size or shape of an object is zooming the scene or changing the viewing angle.&#xD;&#xA;&#xD;&#xA;The scene is rendered in WebGL: https://codepen.io/Candleout/pen/poxMLPB For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again.&#xD;&#xA;&#xD;&#xA;As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without altering its shape. What I need now is a good and practical way to zoom and change the viewing angle.&#xD;&#xA;&#xD;&#xA;The camera is positioned with the help of a lookAt function. But something tells me you wouldn't want to use the lookAt function as the primary tool for moving the camera?&#xD;&#xA;&#xD;&#xA;My guess is that you work with matrix calculations? Maybe you set the camera in a neutral position (something like cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];) and then apply transformations to that position?&#xD;&#xA;&#xD;&#xA;How would you typically zoom? By scaling the scene, or moving the camera? With my current code, moving the camera doesn't affect the size of an object.&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis, while X (red) and Y (green) represents the horizontal plane.&#xD;&#xA;&#xD;&#xA;[![axes][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NDg2J.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40987" PostHistoryTypeId="5" PostId="13544" RevisionGUID="b1976b9e-ec55-4c50-900c-c85546d3848e" CreationDate="2023-06-22T21:50:10.277" UserId="20067" Comment="deleted 2 characters in body" Text="I'm trying to figure out how to move a camera in orthographic 3D. The scene is orthographic in the sense that an object looks the same regardless of position. The only thing that may affect the size or shape of an object is zooming the scene or changing the viewing angle.&#xD;&#xA;&#xD;&#xA;The scene is rendered in WebGL: https://codepen.io/Candleout/pen/poxMLPB For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again.&#xD;&#xA;&#xD;&#xA;As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without altering its shape. What I need now is a good and practical way to zoom and change the viewing angle.&#xD;&#xA;&#xD;&#xA;The camera is positioned with the help of a lookAt function. But something tells me you wouldn't want to use the lookAt function as the primary tool for moving the camera?&#xD;&#xA;&#xD;&#xA;My guess is that you work with matrix calculations? Maybe you set the camera in a neutral position (something like cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];) and then add transformations to that position?&#xD;&#xA;&#xD;&#xA;How would you typically zoom? By scaling the scene, or moving the camera? With my current code, moving the camera doesn't affect the size of an object.&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis, while X (red) and Y (green) represents the horizontal plane.&#xD;&#xA;&#xD;&#xA;[![axes][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NDg2J.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40988" PostHistoryTypeId="5" PostId="13544" RevisionGUID="c5ed35ba-1f7e-4cd1-89c0-d23e111caa32" CreationDate="2023-06-22T21:50:57.647" UserId="20067" Comment="deleted 1 character in body" Text="I'm trying to figure out how to move a camera in orthographic 3D. The scene is orthographic in the sense that an object looks the same regardless of position. The only thing that may affect the size or shape of an object is zooming the scene or changing the viewing angle.&#xD;&#xA;&#xD;&#xA;The scene is rendered in WebGL: https://codepen.io/Candleout/pen/poxMLPB For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again.&#xD;&#xA;&#xD;&#xA;As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without altering its shape. What I need now is a good and practical way to zoom and change the viewing angle.&#xD;&#xA;&#xD;&#xA;The camera is positioned with the help of a lookAt function. But something tells me you wouldn't want to use the lookAt function as the primary tool for moving the camera?&#xD;&#xA;&#xD;&#xA;My guess is that you work with matrix calculations? Maybe you set the camera in a neutral position (something like cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];) and then add transformations to that position?&#xD;&#xA;&#xD;&#xA;How would you typically zoom? By scaling the scene, or moving the camera? With my current code, moving the camera doesn't affect the size of an object.&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis while X (red) and Y (green) represents the horizontal plane.&#xD;&#xA;&#xD;&#xA;[![axes][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NDg2J.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40989" PostHistoryTypeId="5" PostId="13544" RevisionGUID="7e5870c3-b302-4632-88af-97bb1a3cc6d0" CreationDate="2023-06-22T21:52:48.800" UserId="20067" Comment="deleted 108 characters in body" Text="I'm trying to figure out how to move a camera in orthographic 3D. The scene is orthographic in the sense that an object looks the same regardless of position. The only thing that may affect the size or shape of an object is zooming the scene or changing the viewing angle.&#xD;&#xA;&#xD;&#xA;The scene is rendered in WebGL: https://codepen.io/Candleout/pen/poxMLPB For some reason, the scene is sometimes empty (white) when you load the CodePen. If this happens, you can fix it by simply running the code again.&#xD;&#xA;&#xD;&#xA;As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without altering its shape. What I need now is a good and practical way to zoom and change the viewing angle.&#xD;&#xA;&#xD;&#xA;The camera is positioned with the help of a lookAt function. But something tells me you wouldn't want to use the lookAt function as the primary tool for moving the camera?&#xD;&#xA;&#xD;&#xA;My guess is that you work with matrix calculations? Maybe you set the camera in a neutral position (something like cameraTarget = [0, 0, 0]; cameraPosition = [0, 0, distance]; up = [0, 0, -1];) and then add transformations to that position?&#xD;&#xA;&#xD;&#xA;How would you typically zoom? By scaling the scene, or moving the camera? With my current code, moving the camera doesn't affect the size of an object.&#xD;&#xA;&#xD;&#xA;[![axes][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/NDg2J.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40990" PostHistoryTypeId="2" PostId="13545" RevisionGUID="3aee6d6f-4a66-494a-bdc7-8be98da3fc86" CreationDate="2023-06-22T22:24:30.823" UserId="20067" Text="I'm trying to setup a 3D camera in WebGL. The camera is setup with the help of a lookAt function. The lookAt function takes `cameraTarget`, `cameraPosition` and `up` as as inputs.&#xD;&#xA;&#xD;&#xA;The code can be found here: https://codepen.io/Candleout/pen/poxMLPB If the scene looks empty you load the CodePen, simply run the code again.&#xD;&#xA;&#xD;&#xA;[![axes][1]][1]&#xD;&#xA;&#xD;&#xA;How can I position the camera straightly above or below the target?&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis, while X (red) and Y (green) represents the horizontal plane. I have tried positioning the object at `[0, 0, 0]` and giving the camera a position of `[0, 0, distance]`. With a `cameraTarget` of `[0, 0, 0]` (same as the object) I was expecting this would give me a top-down view of the object. However, if I set the camera position to `[0, 0, distance]` the rendered object disappears. Any idea why this happens?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XMCAq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40992" PostHistoryTypeId="1" PostId="13545" RevisionGUID="3aee6d6f-4a66-494a-bdc7-8be98da3fc86" CreationDate="2023-06-22T22:24:30.823" UserId="20067" Text="Position a 3D camera directly above the target" ContentLicense="CC BY-SA 4.0" />
  <row Id="40993" PostHistoryTypeId="3" PostId="13545" RevisionGUID="3aee6d6f-4a66-494a-bdc7-8be98da3fc86" CreationDate="2023-06-22T22:24:30.823" UserId="20067" Text="|webgl|camera|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40994" PostHistoryTypeId="5" PostId="13545" RevisionGUID="b38c0115-0459-4a12-be85-f4d3b505b17b" CreationDate="2023-06-22T22:25:34.087" UserId="20067" Comment="deleted 13 characters in body; edited title" Text="I'm trying to setup a 3D camera in WebGL. The camera is setup with the help of a lookAt function. The lookAt function takes `cameraTarget`, `cameraPosition` and `up` as as inputs.&#xD;&#xA;&#xD;&#xA;The code can be found here: https://codepen.io/Candleout/pen/poxMLPB If the scene looks empty you load the CodePen, simply run the code again.&#xD;&#xA;&#xD;&#xA;[![axes][1]][1]&#xD;&#xA;&#xD;&#xA;How can I position the camera straightly above or below the target?&#xD;&#xA;&#xD;&#xA;In the scene, Z (blue) is the vertical axis, while X (red) and Y (green) represents the horizontal plane. I have tried putting the object at `[0, 0, 0]` and giving the camera a position of `[0, 0, distance]`. With a `cameraTarget` of `[0, 0, 0]` (same as the object) I was expecting this would give me a top-down view of the object. However, if I set the camera position to `[0, 0, distance]` the object disappears. Any idea why this happens?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/XMCAq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="40995" PostHistoryTypeId="4" PostId="13545" RevisionGUID="b38c0115-0459-4a12-be85-f4d3b505b17b" CreationDate="2023-06-22T22:25:34.087" UserId="20067" Comment="deleted 13 characters in body; edited title" Text="Position a 3D camera directly above or below the target" ContentLicense="CC BY-SA 4.0" />
  <row Id="40996" PostHistoryTypeId="6" PostId="13544" RevisionGUID="e17eaca8-08ef-4d33-a722-2c8982da552d" CreationDate="2023-06-22T22:28:18.260" UserId="20067" Comment="edited tags" Text="|matrix|webgl|camera|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="40997" PostHistoryTypeId="2" PostId="13546" RevisionGUID="16d6319c-1055-43e0-a97f-9d8613c23ae5" CreationDate="2023-06-23T08:01:33.590" UserId="13273" Text="It seems that some basic computer graphics knowledge is missing.&#xD;&#xA;&#xD;&#xA;Normally you have two matrices for the camera (viewMatrix and projectionMatrix), both are 4x4 matrices. The viewMatrix stores the camera position and orientation relative to world coordinates. The projection matrix stores the projection.... in your case it is an orthographic projection. The projection matrix does NOT contain any information about the camera position or orientation.&#xD;&#xA;&#xD;&#xA;Then you have a modelMatrix for each geometry. This matrix stores the position, scale, and orientation of a 3D object, relative to world coordinates.&#xD;&#xA;&#xD;&#xA;So when rendering, you want to transform each vertex of a geometry in the following way:&#xD;&#xA;&#xD;&#xA;First, you need to transform the vertex, which is stored in model coordinates, to world coordinates: $vec4 vertexWorldCoordinates = modelMatrix * vec4(vertex,1)$&#xD;&#xA;&#xD;&#xA;**Now you have each vertex of an object in world coordinates.&#xD;&#xA;&#xD;&#xA;The next step is to convert them to camera coordinates. Camera coordinates have nothing to do with projection! They are the coordinates related to the camera position and orientation. $vertexCameraSpace = viewMatrix * vertexWorldCoordinates$&#xD;&#xA;&#xD;&#xA;Now you have translated your vertices into camera coordinates. The next step is to translate them into screen coordinates by applying the projection matrix.&#xD;&#xA;$vertexProjectedCoordinates = projectionMatrix * vertexCameraSpace$.&#xD;&#xA;&#xD;&#xA;The final step is to bring the vertex projection coordinates to normalized device coordinates. In the case of a perspective projection (everything far away becomes smaller) you have to do the following: $vertexNormalizedDeviceCoordinates = vertexProjectedCoordinates / vertexProjectedCoordinates.w$. Here $vertexProjectedCoordinates.w$ is the 4th value of the vector.&#xD;&#xA;&#xD;&#xA;In the case of orthographic projection, there is no need to divide by the value $vertexProjectedCoordinates.w$, since this value is always `1`.&#xD;&#xA;&#xD;&#xA;Now let's talk about how to apply these matrices without storing each transformation in a separate vector: Matrices can be applied directly one after the other. So you can write: $vertexProjectedCoordinates = projectionMatrix * viewMatrix * modelMatrix * vec4(vertex, 1)$.&#xD;&#xA;&#xD;&#xA;You can combine matrices, which results in a matrix. So let's combine the projection matrix and the view matrix: $viewProjectionMatrix = projectionMatrix * viewMatrix$. This leads to better performance when computing this matrix on the CPU instead of the GPU. This is because: each vertex would have to calculate the multiplication of both matrices, and each vertex gets the same value from it. So, calculate the combined matrices and load them on the GPU.&#xD;&#xA;&#xD;&#xA;On the GPU you then only need: $vertexProjectedCoordinates = viewProjectionMatrix * modelMatrix * vec4(vertex, 1)$. You can also combine the modelMatrix and the viewProjectionMatrix in the same way...&#xD;&#xA;&#xD;&#xA;**Okay, now let's take a look at your questions:**&#xD;&#xA;&#xD;&#xA;&gt; I'm trying to figure out how to move a camera in orthographic 3D.&#xD;&#xA;&#xD;&#xA;Since the projection matrix is separate from the view matrix, camera movement works the same for orthographic cameras as it does for perspective cameras. You have to change the viewMatrix, then the position / orientation of the camera changes.&#xD;&#xA;&#xD;&#xA;&gt; As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without changing its shape.&#xD;&#xA;&#xD;&#xA;Here I would think about moving not the object, but the camera.... But I don't know what the final result will do... So maybe moving the object is the right choise.&#xD;&#xA;&#xD;&#xA;&gt; What I need now is a good and practical way to zoom and change the angle of view.&#xD;&#xA;&#xD;&#xA;zoom: what does zoom mean? As I understand it, you want to scale the camera projection to see more/less of the scenario. To do this, you need to change the projection matrix.&#xD;&#xA;&#xD;&#xA;Changing the angle of view: I hope you don't mean the field of view, because orthographic projections don't have a field of view. Do you mean the camera orientation (rotating the camera)? Then you just need to multiply your viewMatrix by a rotation matrix. Note that $viewMatrix * rotationMatrix$ is not the same as $rotationMatrix * viewMatrix$, because matrix multiplications are not commutative!&#xD;&#xA;&#xD;&#xA;&gt; The camera is positioned using a lookAt function. But something tells me that you don't want to use the lookAt function as the primary tool for moving the camera?&#xD;&#xA;&#xD;&#xA;The `lookAt` function is a nice function to initialize the camera position / orientation. You can perform transformations (translations, rotations) by multiplying matrices by the viewMatrix. Note that after some time (if you rotate a lot) the floating point precision introduces small errors into the viewMatrix. Then you need to orthonormalize the top 3x3 part of your viewMatrix. You can do this by simply creating a new viewMatrix using the function `lookAt`.&#xD;&#xA;&#xD;&#xA;&gt; How do you normally zoom? By scaling the scene or by moving the camera? With my current code, moving the camera does not affect the size of an object.&#xD;&#xA;&#xD;&#xA;Moving the camera will not work! As I said before, you need to change the projectionMatrix. If you use the library &quot;GLM&quot; you can use the function &quot;ortho&quot;.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;BTW: please take a look at the following tutorial. This tutorial discribes the different matrices, what they represent and how to change them: [OpenGL tutorial matrices][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/" ContentLicense="CC BY-SA 4.0" />
  <row Id="40999" PostHistoryTypeId="2" PostId="13547" RevisionGUID="cb9df990-0834-4784-a414-458fbcd4f897" CreationDate="2023-06-23T08:50:14.633" UserId="13273" Text="This can be because of multiple reasons:&#xD;&#xA;&#xD;&#xA;first as @gallickgunner said, the up vector which is passed to the `lookAt` function should not be alligned to the view direction! Here you need to pass in the up direction of the camera (not the world). So when having a top down view, up shoud be a vector within the plane x/y.&#xD;&#xA;&#xD;&#xA;The next thing why you maybe don't see anything can be, that your object don't lie within the projection matrix near and far clipping planes.&#xD;&#xA;&#xD;&#xA;Take a look at [OpenGL tutorial matrices][1].&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/" ContentLicense="CC BY-SA 4.0" />
  <row Id="41006" PostHistoryTypeId="50" PostId="10619" RevisionGUID="810dd26d-3611-40ef-b2e5-b3fb788bba0c" CreationDate="2023-06-23T18:09:21.190" UserId="-1" />
  <row Id="41008" PostHistoryTypeId="2" PostId="13549" RevisionGUID="e18d6cbf-3d10-47e8-bce7-4ea64a281119" CreationDate="2023-06-24T13:50:25.063" UserId="20129" Text="In Final Fantasy 16, a recent video game, when looking towards the setting sun, one sees several circles, which seem like the lens flare that one commonly sees in games. But the most prominent (circle) is this cardioid/fish-like curve that loops in on itself. I've never seen this before. FFXVI has insane polish, so I don't think this is some random mistake by the devs. Does this phenomenon have any basis in reality? Is it just some weird stylistic choice? Or is it just a graphical mistake?&#xD;&#xA;&#xD;&#xA;Here's an image from ffxvi, demonstrating what I'm talking about.&#xD;&#xA;&#xD;&#xA;https://files.catbox.moe/mgagg4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41010" PostHistoryTypeId="1" PostId="13549" RevisionGUID="e18d6cbf-3d10-47e8-bce7-4ea64a281119" CreationDate="2023-06-24T13:50:25.063" UserId="20129" Text="What is this cardioid/fish-like graphic that appears in FFXVI when looking at the sun?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41011" PostHistoryTypeId="3" PostId="13549" RevisionGUID="e18d6cbf-3d10-47e8-bce7-4ea64a281119" CreationDate="2023-06-24T13:50:25.063" UserId="20129" Text="|raytracing|lighting|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41012" PostHistoryTypeId="50" PostId="13491" RevisionGUID="612c2d9a-3a18-45e4-a273-f7246ed62e58" CreationDate="2023-06-24T14:07:20.817" UserId="-1" />
  <row Id="41014" PostHistoryTypeId="2" PostId="13550" RevisionGUID="cf864886-c55b-47f7-a49a-16924348ed32" CreationDate="2023-06-24T19:48:55.187" UserId="20131" Text="I'm not sure if this is the correct place to ask this, but does anyone here know why my screen flickers (not in a broken kind of way) when scrolling on this [image from Claude Mellan][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://upload.wikimedia.org/wikipedia/commons/c/ca/Claude_Mellan_-_Face_of_Christ_-_WGA14764.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41016" PostHistoryTypeId="1" PostId="13550" RevisionGUID="cf864886-c55b-47f7-a49a-16924348ed32" CreationDate="2023-06-24T19:48:55.187" UserId="20131" Text="Why does my screen flicker when scrolling the image below?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41017" PostHistoryTypeId="3" PostId="13550" RevisionGUID="cf864886-c55b-47f7-a49a-16924348ed32" CreationDate="2023-06-24T19:48:55.187" UserId="20131" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41018" PostHistoryTypeId="50" PostId="13002" RevisionGUID="f593d780-3e6f-42b9-9d8f-9d63f0c2ab59" CreationDate="2023-06-25T02:00:40.090" UserId="-1" />
  <row Id="41019" PostHistoryTypeId="2" PostId="13551" RevisionGUID="4fc2803c-c3f8-44a4-b03c-933f4f1e387c" CreationDate="2023-06-25T07:25:10.340" UserId="20133" Text="Firstly the VBO was initialized like below:&#xD;&#xA;```&#xD;&#xA;GLuint vertex_buffer;&#xD;&#xA;glGenBuffers(1, &amp;vertex_buffer);&#xD;&#xA;glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);&#xD;&#xA;glBufferData(GL_ARRAY_BUFFER, data_size_in_bytes, data_vertices, GL_STATIC_DRAW);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;data_vertices store some points data, then I push back another points into it and data_vertices will be resized(larger).&#xD;&#xA;&#xD;&#xA;If glDeleteBuffers/glGenBuffers needed to be called again or only just glBindBuffer the new data?&#xD;&#xA;```&#xD;&#xA;glDeleteBuffers(1, &amp;vertex_buffer); // is this necessary?&#xD;&#xA;glGenBuffers(1, &amp;vertex_buffer); // is this necessary?&#xD;&#xA;glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);&#xD;&#xA;glBufferData(GL_ARRAY_BUFFER, new_data_size_in_bytes, new_data_vertices, GL_STATIC_DRAW);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Now I did not call glDeleteBuffers/glGenBuffers in every update frame, and on some computers the points maybe disappear..." ContentLicense="CC BY-SA 4.0" />
  <row Id="41021" PostHistoryTypeId="1" PostId="13551" RevisionGUID="4fc2803c-c3f8-44a4-b03c-933f4f1e387c" CreationDate="2023-06-25T07:25:10.340" UserId="20133" Text="Is glDeleteBuffers/glGenBuffers needed if I want to resize the buffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41022" PostHistoryTypeId="3" PostId="13551" RevisionGUID="4fc2803c-c3f8-44a4-b03c-933f4f1e387c" CreationDate="2023-06-25T07:25:10.340" UserId="20133" Text="|opengl|opengl-es|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41023" PostHistoryTypeId="50" PostId="9116" RevisionGUID="8f0205fd-f08e-4bee-8b13-5283aa55ee87" CreationDate="2023-06-25T14:08:16.033" UserId="-1" />
  <row Id="41028" PostHistoryTypeId="2" PostId="13553" RevisionGUID="7c2f7a7d-2971-411b-b0a7-b70fabdd82ea" CreationDate="2023-06-25T16:55:45.527" UserId="13273" Text="glbufferData is the command with initializes the buffer size. So you can bind the old buffer with wrong size and use glbufferData to resize it. " ContentLicense="CC BY-SA 4.0" />
  <row Id="41030" PostHistoryTypeId="2" PostId="13554" RevisionGUID="837398ed-a41e-40e4-8543-05443e49deca" CreationDate="2023-06-25T17:35:32.790" UserId="18064" Text="I am making a Software renderer, and I noticed that there is a screen shaking like effect happening. shown in the first [video][1]:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I tried doing filling without clipping against the small square, and the result is much better, yet, there is some sort of shaking on the edges as shown in the second [video][2]&#xD;&#xA;&#xD;&#xA;Finally I tried drawing the clipped triangles outline, and the shaking is more apparent as shown in the third [video][3]&#xD;&#xA;&#xD;&#xA;My initial assumption was the line drawing was not accurate enough, so I tried both DDA and Bresenham line drawing without any success.&#xD;&#xA;&#xD;&#xA;Additionally, I tried different triangulation schemes, I noticed that when I increase the number of created triangles (such as when I triangulate a square using the center as a new vertex instead of using one of the corners) the shaking gets worse. That led me to believe to the issue is related to shared edges in the triangles, and indeed in my triangle filling algorithm, I tried to remove the shared edge and got a bit better results (but it introduced different artifacts, some pixels were missing): https://git.sr.ht/~aliabdulkareem/SoftwareRenderer/tree/FixTrianglulation/item/src/drawing.cpp#L450&#xD;&#xA;&#xD;&#xA;That did not however remove it entirely (I believe I should remove the shared edges from the triangulation phase as well, not entirely sure how to do that, one idea is when I triangulate the triangles after the first one, I always more pixel in the direction of the two newly formed edges)&#xD;&#xA;&#xD;&#xA;Also it does not explain entirely the second video shaking when there was a shared edge in the diagonal of a square, but it was fine, while the square edges were shaking despite not sharing an edge.&#xD;&#xA;&#xD;&#xA;I am a bit puzzled as how to debug this as I can at least think of three different reasons:&#xD;&#xA;&#xD;&#xA;1- Triangulation is wrong&#xD;&#xA;&#xD;&#xA;2- Floating point inaccuracy&#xD;&#xA;&#xD;&#xA;3- Aliasing (I heard that in animations, aliasing becomes very clear, not sure if that is the case)&#xD;&#xA;&#xD;&#xA;Full source code: https://git.sr.ht/~aliabdulkareem/SoftwareRenderer/tree/FixTrianglulation&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://ufile.io/uov1de8z&#xD;&#xA;  [2]: https://ufile.io/hkcymcii&#xD;&#xA;  [3]: https://ufile.io/uexgf1wk" ContentLicense="CC BY-SA 4.0" />
  <row Id="41032" PostHistoryTypeId="1" PostId="13554" RevisionGUID="837398ed-a41e-40e4-8543-05443e49deca" CreationDate="2023-06-25T17:35:32.790" UserId="18064" Text="Triangle Rasterization Shaking Issues" ContentLicense="CC BY-SA 4.0" />
  <row Id="41033" PostHistoryTypeId="3" PostId="13554" RevisionGUID="837398ed-a41e-40e4-8543-05443e49deca" CreationDate="2023-06-25T17:35:32.790" UserId="18064" Text="|rendering|c++|rasterizer|triangulation|clipping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41034" PostHistoryTypeId="2" PostId="13555" RevisionGUID="62f2763f-c18e-4375-8cf3-f94796af1109" CreationDate="2023-06-25T18:30:44.530" UserId="18765" Text="I understand that your pipeline looks like this: Transform polygon vertices -&gt; clip polygon -&gt; triangulate -&gt; draw edges of each triangle. &#xD;&#xA;&#xD;&#xA;I would start with simple line drawing and disregard the clipping, filling and triangulation for now and see if the shaking still occurs. Then you can try to add the triangulation and the rest, one by one. &#xD;&#xA;&#xD;&#xA;There is a couple of things that seem suspicous to me in the third video (see attached image):&#xD;&#xA;1) The horizontal green line stays still during the animation but shakes up and down. The other green horizontal line and the vertical lines dont shake, but that might be a coincidence. This seems to me like an inaccuracy in the transformation.&#xD;&#xA;2) The boundary edges of the red polygon dont connect in the vertices in some frames. If the endpoints of both edges are represented by a single point, that means there is an error in the line drawing algorithm.&#xD;&#xA;&#xD;&#xA;Aliasing is causing slight trembling of the rotating lines as their slope changes, but not any of the problems mentioned above.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qSL5C.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41036" PostHistoryTypeId="5" PostId="13553" RevisionGUID="69b12720-7784-4bdc-b53b-f9f6c1ba348d" CreationDate="2023-06-25T18:45:13.713" UserId="13273" Comment="added 50 characters in body" Text="glbufferData is the command with initializes the buffer size. So you can bind the old buffer with wrong size and use glbufferData to resize it. You don't have to delete and recreate the buffer. " ContentLicense="CC BY-SA 4.0" />
  <row Id="41037" PostHistoryTypeId="5" PostId="13553" RevisionGUID="2361fd1e-3f98-49f6-bd08-fc854710d60e" CreationDate="2023-06-25T18:51:31.330" UserId="13273" Comment="added 1 character in body" Text="glbufferData is the command which initializes the buffer size. So you can bind the old buffer with wrong size and use glbufferData to resize it. You don't have to delete and recreate the buffer. " ContentLicense="CC BY-SA 4.0" />
  <row Id="41038" PostHistoryTypeId="50" PostId="9926" RevisionGUID="f056e9f3-ccd0-43af-b236-6dd9ba43a638" CreationDate="2023-06-26T03:08:31.143" UserId="-1" />
  <row Id="41040" PostHistoryTypeId="5" PostId="13553" RevisionGUID="7a8fe0c7-3eaf-4651-8376-57e252a7fcd4" CreationDate="2023-06-26T06:57:17.500" UserId="13273" Comment="added 826 characters in body" Text="glbufferData is the command which initializes the buffer size. So you can bind the old buffer with wrong size and use glbufferData to resize it. You don't have to delete and recreate the buffer. &#xD;&#xA;&#xD;&#xA;    GLint size = 0;&#xD;&#xA;    GLuint bufferTest = 0;&#xD;&#xA;    glGenBuffers(1, &amp;bufferTest); //generate buffer item&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferTest);&#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, 16, nullptr, GL_STATIC_DRAW); //initialize buffer with size 16 bytes&#xD;&#xA;    glGetBufferParameteriv(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &amp;size); //get buffer size&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); //unbind buffer&#xD;&#xA;    &#xD;&#xA;`size` will be 16!&#xD;&#xA;&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferTest); &#xD;&#xA;    glBufferData(GL_SHADER_STORAGE_BUFFER, 24, nullptr, GL_STATIC_DRAW); //reinitialize buffer with size 24 bytes&#xD;&#xA;    glGetBufferParameteriv(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &amp;size); //get new buffer size&#xD;&#xA;    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); //unbind buffer&#xD;&#xA;&#xD;&#xA;`size`will be 24&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41042" PostHistoryTypeId="5" PostId="13532" RevisionGUID="036556cd-1d69-4ced-869a-2ef4fdd8e59b" CreationDate="2023-06-26T19:53:12.597" UserId="20093" Comment="added 509 characters in body" Text="I have been programing a simple ray marcher with GLES, using [The Book of Shaders editor](http://editor.thebookofshaders.com/). I noticed that on scenes with multiple objects (multiple SDFs), I am getting glitches on edges of object which are superimposed over other objects:&#xD;&#xA;&#xD;&#xA;[![Shader output][1]][1]&#xD;&#xA;&#xD;&#xA;The source of this shader is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;#ifdef GL_ES&#xD;&#xA;precision highp float;&#xD;&#xA;#endif&#xD;&#xA;&#xD;&#xA;uniform vec2 u_resolution;&#xD;&#xA;&#xD;&#xA;vec3 floorColor(vec3 pos) {&#xD;&#xA;    if(mod(floor(pos.x) + floor(pos.z), 2.0) &lt; 1.0) {&#xD;&#xA;        return vec3(0.7, 0.8, 0.7);&#xD;&#xA;    } else {&#xD;&#xA;        return vec3(0.3,0.4,0.3);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 iterate(vec3 ray){&#xD;&#xA;    vec3 position = vec3(0.0);&#xD;&#xA;    for(int i = 0; i &lt; 100; i++) {&#xD;&#xA;        float sphereF = length(position - vec3(0.0, 0.0, 2.0)) - 1.0;&#xD;&#xA;    	float floorF = position.y + 1.;&#xD;&#xA;    	float minF = min(sphereF, floorF);&#xD;&#xA;        position += minF*ray;&#xD;&#xA;        &#xD;&#xA;        if(minF &lt;= 0.01) { &#xD;&#xA;            if(sphereF &lt; floorF) {&#xD;&#xA;               return vec3(0.9, 0.2, 0.2);&#xD;&#xA;            } else {&#xD;&#xA;               return floorColor(position);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    return vec3(0.2, 0.5, 0.8);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec2 st = gl_FragCoord.xy/u_resolution.xy;&#xD;&#xA;    st.x *= u_resolution.x/u_resolution.y;&#xD;&#xA;	st = 2.0 * st - vec2(1.0); &#xD;&#xA;    &#xD;&#xA;    vec3 color = iterate(normalize(vec3(st.x, st.y, 1.0)));&#xD;&#xA;&#xD;&#xA;    gl_FragColor = vec4(color, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After a lot of debugging, I realized that glitches are produced return stantments inside loop in `iterate` function, but I am still not sure *why* this happens. &#xD;&#xA;&#xD;&#xA;Using other shader editors produced similar glitches.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZIzbH.png&#xD;&#xA;&#xD;&#xA;Edit: Provided source is the minimal shader that produced described artifacts (blue squares). I did try various combination of $\varepsilon$ or number of iterations, but that only made things worse. As I said, it seems that `return` statement inside a loop is source of the artifacts (If you do a slight rewrite of `iterate` function in such way that loop can't break before it reaches end, squares will be gone!). This is most surly a graphics driver/card bug as babali suggested in the accepted answer. " ContentLicense="CC BY-SA 4.0" />
  <row Id="41049" PostHistoryTypeId="2" PostId="13557" RevisionGUID="579378fa-6001-45bb-9cc9-ec3bafa5d253" CreationDate="2023-06-27T11:21:02.080" UserId="6041" Text="Could sampling GGX VNDF sampling, &#xD;&#xA;&#xD;&#xA;based on:&#xD;&#xA;&quot;[Sampling Visible GGX Normals with Spherical Caps][1]&quot; and&#xD;&#xA;&quot;[Sampling the GGX Distribution of Visible Normals][2]&quot;&#xD;&#xA;&#xD;&#xA;produce a normal that (based on the view direction) the reflected ray points below the surface geometry normal (i.e cosine of outgoing ray &lt; 0) ?&#xD;&#xA;&#xD;&#xA;In other words, my question is, does sampling VNDF take into account the cosine incidence term that appears in the rendering equation? or would it end up sampled rays that goes below the local hemisphere?&#xD;&#xA;Specifically looking at Figure 4 (of the first paper) for theta-i = 70, the reflected rays also point below the horizon. Which sugests using the generated normal can produce outgoing rays below horiozn?&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://arxiv.org/pdf/2306.05044.pdf&#xD;&#xA;  [2]: https://jcgt.org/published/0007/04/01/&#xD;&#xA;  [3]: https://i.stack.imgur.com/oi5cD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41051" PostHistoryTypeId="1" PostId="13557" RevisionGUID="579378fa-6001-45bb-9cc9-ec3bafa5d253" CreationDate="2023-06-27T11:21:02.080" UserId="6041" Text="Does sampling GGX VNDF take into account the cosine incidene of outgoing ray?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41052" PostHistoryTypeId="3" PostId="13557" RevisionGUID="579378fa-6001-45bb-9cc9-ec3bafa5d253" CreationDate="2023-06-27T11:21:02.080" UserId="6041" Text="|sampling|microfacet|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41054" PostHistoryTypeId="2" PostId="13558" RevisionGUID="9d26f24d-2a64-47d1-b033-7d6cc8dd0d9f" CreationDate="2023-06-28T09:21:24.303" UserId="20147" Text="I am new to computer graphics and have taken up a course in my university on computer graphics. Need help regarding a question as I could not find any relevant resource on the internet so hoping the reddit community can help me with the solution. Thanks a lot.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/99Ayc.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41056" PostHistoryTypeId="1" PostId="13558" RevisionGUID="9d26f24d-2a64-47d1-b033-7d6cc8dd0d9f" CreationDate="2023-06-28T09:21:24.303" UserId="20147" Text="Question regarding texture mapping sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="41057" PostHistoryTypeId="3" PostId="13558" RevisionGUID="9d26f24d-2a64-47d1-b033-7d6cc8dd0d9f" CreationDate="2023-06-28T09:21:24.303" UserId="20147" Text="|texture|sampling|mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41058" PostHistoryTypeId="2" PostId="13559" RevisionGUID="a74f5d09-ac31-4e75-956f-a7b6a22fd792" CreationDate="2023-06-28T10:46:46.870" UserId="13273" Text="Undersampling or oversampling occur when an image is projected to a different resolution.&#xD;&#xA;&#xD;&#xA;**Untersampling:**&#xD;&#xA;The texture (4x4 pixels) is projected on e.g. 3x3 pixels, see figure 1.&#xD;&#xA;As you can see, the first white stripe is no longer visible because it is between two pixels.&#xD;&#xA;&#xD;&#xA;**Oversampling:**&#xD;&#xA;The texture (4x4 pixels) is projected to e.g. 9x9 pixels, see Figure 1.&#xD;&#xA;The image is pixelated because too many pixels fall on each stripe.&#xD;&#xA;When using a LINEAR interpolation sampler, the pixels which are between two stripes will become grey (interpolated color value).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure1:** Example of under and oversampling.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q8Ft2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41060" PostHistoryTypeId="2" PostId="13560" RevisionGUID="9c74075e-99b3-4624-a7fe-343814ada5eb" CreationDate="2023-06-28T11:27:51.263" UserId="20148" Text="Here I try to combine scratchapixel's articles to understand the operation of the camera-to-world matrix and ray direction vector. Here &lt;https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays.html&gt; if you scroll the last part is about generating a direction vector without converting pixel coordinates from raster space to NDC, then to screen. I decided to take that approach. But, after multiplying the direction vector with the camera-to-world matrix, there is no added translation vector to the direction vector's coordinates (that is the 4th vector of the matrix). Maybe the camera is placed at (0,0,0). Idk. Also, are LookAt and camera-to-world matrices the same thing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41062" PostHistoryTypeId="1" PostId="13560" RevisionGUID="9c74075e-99b3-4624-a7fe-343814ada5eb" CreationDate="2023-06-28T11:27:51.263" UserId="20148" Text="Defining ray direction vector" ContentLicense="CC BY-SA 4.0" />
  <row Id="41063" PostHistoryTypeId="3" PostId="13560" RevisionGUID="9c74075e-99b3-4624-a7fe-343814ada5eb" CreationDate="2023-06-28T11:27:51.263" UserId="20148" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41069" PostHistoryTypeId="2" PostId="13562" RevisionGUID="b10716b2-41e3-4fa9-9971-81f295df15ab" CreationDate="2023-06-29T07:51:38.170" UserId="20154" Text="I am about to implement a framerate histogramm chart for a DirectX Renderer.&#xD;&#xA;&#xD;&#xA;Ideally I would do this in pure shader code, but for a a histogramm I need to store the timestamps of the last `x` frames. I guess I could store these to a texture, but I was wondering if there is a more appropriate way to achieve that?&#xD;&#xA;&#xD;&#xA;Thanks!" ContentLicense="CC BY-SA 4.0" />
  <row Id="41071" PostHistoryTypeId="1" PostId="13562" RevisionGUID="b10716b2-41e3-4fa9-9971-81f295df15ab" CreationDate="2023-06-29T07:51:38.170" UserId="20154" Text="Storing array of floats within shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="41072" PostHistoryTypeId="3" PostId="13562" RevisionGUID="b10716b2-41e3-4fa9-9971-81f295df15ab" CreationDate="2023-06-29T07:51:38.170" UserId="20154" Text="|hlsl|fragment-shader|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41073" PostHistoryTypeId="2" PostId="13563" RevisionGUID="2e9fcb9f-0f99-47c8-abd8-c254f7991ace" CreationDate="2023-06-29T13:17:32.013" UserId="226" Text="Consider this equation, where we have a surface integral over hemisphere with Lambertian BRDF and cos(theta) from The Rendering Equation:&#xD;&#xA;$$&#xD;&#xA;\int_{0}^{2\pi}\int_{0}^{\frac{\pi}{2}}\frac{albedo}{\pi}cos(\theta)sin(\theta)d\theta d\phi = 1&#xD;&#xA;$$&#xD;&#xA;However, in the code, we would usually do this, employing a Monte-Carlo estimator:&#xD;&#xA;$$&#xD;&#xA;\frac{1}{N}\sum_{i=1}^{N}cos(\theta)\frac{albedo}{\pi}\frac{1}{p(x_i)}&#xD;&#xA;$$&#xD;&#xA;where only cosine remains, but where does sin(theta) go?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41075" PostHistoryTypeId="1" PostId="13563" RevisionGUID="2e9fcb9f-0f99-47c8-abd8-c254f7991ace" CreationDate="2023-06-29T13:17:32.013" UserId="226" Text="Where does sin(theta) go in estimators of The Rendering Equation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41076" PostHistoryTypeId="3" PostId="13563" RevisionGUID="2e9fcb9f-0f99-47c8-abd8-c254f7991ace" CreationDate="2023-06-29T13:17:32.013" UserId="226" Text="|raytracing|mathematics|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41077" PostHistoryTypeId="2" PostId="13564" RevisionGUID="2eaf63ed-5e3b-43f1-821d-bebdb3bc81ae" CreationDate="2023-06-29T15:50:44.797" UserId="6588" Text="Your second equation is estimated with respect to solid angle $\Omega$, and the Jacobian of the transformation from spherical coordinates to solid angles is equal to $\sin\theta$. Since $\mathrm{d}\omega = \sin\theta\,\mathrm{d}\theta\mathrm{d}\phi$, you have that&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;p(\theta,\phi) = \sin\theta\, p(\omega),&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;so you are only left with the cosine. &#xD;&#xA;&#xD;&#xA;See [PBRT](https://pbr-book.org/3ed-2018/Monte_Carlo_Integration/Transforming_between_Distributions) for a more detailed explanation." ContentLicense="CC BY-SA 4.0" />
  <row Id="41079" PostHistoryTypeId="2" PostId="13565" RevisionGUID="0370580f-df86-4b25-ab99-d28cc751036c" CreationDate="2023-06-29T21:21:01.583" UserId="13273" Text="I don't think that you have access to the current time on GPU / pixel shader. So you need to transmit the information from CPU to GPU.&#xD;&#xA;&#xD;&#xA;If I would program a framerate histogram I would do it in the following way.&#xD;&#xA;&#xD;&#xA;First create a buffer on GPU where the framerates will be stored to and use it as ring buffer. Create a shader to visualize the histogram by passing an integer value as current position within the buffer and use modulo operator to find the correct position in the buffer when rendering with your pixel shader.&#xD;&#xA;&#xD;&#xA;**It has the following benefits:**&#xD;&#xA;&#xD;&#xA; 1. The buffer is very small in contrast to a texture.&#xD;&#xA; 2. You only need to transfer 2 values (current position in buffer, new framerate value). &#xD;&#xA; 3. You can pass min and max framerate value to scale the histogram. &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41081" PostHistoryTypeId="2" PostId="13566" RevisionGUID="e92d6c62-224f-4e1e-a395-b69efddddea9" CreationDate="2023-06-29T23:24:53.847" UserId="7952" Text="It sounds like you want to gather timings for say 100 frames (x frames) then show that data histogram style.&#xD;&#xA;&#xD;&#xA;You could store the histogram data directly in the shader as an array of floats and draw directly out of the array using the vertex index id, but to update the histogram the array would have to be rewritten inside the shader, then the shader reloaded and recompiled. Overall it is not a very appealing approach.&#xD;&#xA;&#xD;&#xA;A simple approach that is much more flexible, is to write the sample data into a vertex attributes buffer. Bind the vertex buffer and at draw time, the GPU feeds the data to your shader. Each histogram gl_line requires two values, so the first value would be zero and the second value would be the timing value. Repeat that for every timing value. The histogram then becomes a series of lines where the length of the line is determined by the passed in timing, the x position of the line is determined by the vertex index id, and the height of the lines can be uniformly scaled. Finally use a vec3 offset to move the histogram anywhere on the output buffer. gl line width can be used to thicken the lines up so the entire histogram isn't minuscule in size.&#xD;&#xA;&#xD;&#xA;Now the histogram draw is just a matter of binding the vertex buffer containing the timing data, and doing the draw call. Changing the number of values is just a matter of writing a bigger vertex buffer and changing the number of vertices in the draw call.&#xD;&#xA;&#xD;&#xA;To update the histogram gather more data, push it out to the vertex buffer and draw. &#xD;&#xA;&#xD;&#xA;Once this is working it is easy to get fancy with ring buffers, using quads for the histogram lines, animating, etc.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41083" PostHistoryTypeId="2" PostId="13567" RevisionGUID="092ef543-e92e-400c-aed1-2942bfa259fb" CreationDate="2023-06-30T01:55:22.867" UserId="10096" Text="Assume you want to estimate the following integral:&#xD;&#xA;$$I = \int_{\Omega} f d\mu$$&#xD;&#xA;on some set $\Omega\subseteq \mathbb{R}^n$. Suppose you are given a bijective and continuously differentiable parametrization $\varphi^{-1}:D\to\Omega$ where $D=[a^1,b^1]\times\ldots\times [a^m,b^m]$. That is, we have an $m$-manifold embedded in $\mathbb{R}^n$:&#xD;&#xA;$$\Omega = \varphi^{-1}(D) = \{\varphi^{-1}(t)\in\mathbb{R}^n\,:\, t\in D\}.$$&#xD;&#xA;You can now rewrite the integral using $m$ iterated integrals as follows:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_{a^1}^{b^1}\ldots \int_{a^m}^{b^m} f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}\,dt^m\ldots dt^1.$$&#xD;&#xA;The average value of the integrand:&#xD;&#xA;$$g(t) = f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}$$&#xD;&#xA;over $D$ can then be defined as $g_{avg} = I / |D|$, where $|D|$ is the measure/area/volume of $\Omega$: $|\Omega| =\prod_{j=1}^m(b^j-a^j)$. If we have a sequence of points $t_1,\ldots,t_N\in D$ that uniformly fills the box $D$ then we may estimate the integral using the following expression:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j).$$&#xD;&#xA;Using random independent uniformly distributed points in $D$ you get the Monte Carlo estimator. Since the sampling is uniform over $D$, you can interpret the density as $p(t) = \frac{1}{|D|}$:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j)= \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p(t_j)}.$$&#xD;&#xA;Generally, estimators resulting from integrands that are flatter (i.e. $g$ is close to $g_{avg}$ without much wiggling) have lower variance. This suggests that we may reduce the error for a fixed number of samples by applying a change of variables of our integral in order to flatten the integrand and get a &quot;better&quot; estimator. That is, assume that you have a bijective and continuously differentiable map $\psi:D\to D$ such that $|det[J_{\psi}]|\propto |g|$ or at the very least it is close to proportional to $|g|$. Then by the inverse function theorem $J_{\psi^{-1}} = J^{-1}_{\psi}$ and from $det[A^{-1}] = (det[A])^{-1}$ we get &#xD;&#xA;$$|det[J_{\psi^{-1}}]| = |det[J^{-1}_{\psi}]| = \frac{1}{|det[J_{\psi}]|} \propto \frac{1}{|g|}.$$&#xD;&#xA;Thus $|det[J_{\psi^{-1}}||g|$ is close to constant, and in the case where $g$ is non-negative we may also drop the absolute value around $g$. Let us look at the change of variables:&#xD;&#xA;$$\int_D g(t)\, dt = \int_D g(\psi^{-1}(s))|det[J_{\psi^{-1}}(s)]| \, ds.$$&#xD;&#xA;We can now also compare the two estimators:&#xD;&#xA;$$|D|\frac{1}{N} \sum_{j=1}^N g(t_j), \quad |D|\frac{1}{N}\sum_{j=1}^N g(\psi^{-1}(s_j)) |det[J_{\psi^{-1}}(s_j)]|.$$&#xD;&#xA;If $\psi$ was chosen as described then the latter estimator has a product close to constant in the sum, and in the ideal case it is constant - then only 1 sample is required to find the true solution. From a probabilistic point of view this is known as importwnce sampling, i.e. we can interpret theprobability density inthe first case being constant $p_1(t) = \frac{1}{|D|}$ and in the latter case being $p_2(t) = \frac{1}{|D||det[J_{\psi^{-1}}(t)]|}$ where this density can be achieved by first generating uniform samples $s_1,\ldots,s_N\in D$ and then remapping them as $t_k = \psi^{-1}(s_k)$. The two estimators can then be rewritten as:&#xD;&#xA;$$\frac{1}{N} \sum_{j=1}^N \frac{g(t_j)}{p_1(t_j)}, \quad \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p_2(t_j)}.$$&#xD;&#xA;Note that the $t_1,\ldots,t_N$ refer to points generated in a different manner for the 2 cases, in the first they are generated according to a density $p_1$, while in the second according to $p_2$.&#xD;&#xA;&#xD;&#xA;Now consider the special case where $\Omega$ is the unit hemisphere around some normal vector $n$. Let $t,b,n$ be an arbitrary orthonormal basis ($n$ is fixed), then we may form the rotation matrix $R=\begin{bmatrix} t &amp; b &amp; n\end{bmatrix}$. We can parametrize the unit hemisphere around $n$ using &#xD;&#xA;$$\varphi^{-1}(\phi,\theta) = R\begin{bmatrix}\cos\phi\sin\theta\\\sin\phi\sin\theta\\\cos\theta\end{bmatrix}, \quad \phi\in[0,2\pi), \, \theta \in [0,\pi/2].$$&#xD;&#xA;That is $\Omega = \varphi^{-1}(D)$ where $D=[0,2\pi)\times[0,\pi/2]$. We may compute the Jacobian of this map as follows:&#xD;&#xA;$$J_{\varphi^{-1}}(\phi,\theta) = R \begin{bmatrix} -\sin\phi\sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi \sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; -\sin\theta \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;You can now compute $J^TJ$ and the square root of its determinant as follows:&#xD;&#xA;$$J_{\varphi^{-1}}^T J_{\varphi^{-1}}=&#xD;&#xA;\begin{bmatrix} &#xD;&#xA;\sin^2\theta &amp; 0 \\ 0 &amp; 1&#xD;&#xA;\end{bmatrix} \implies \sqrt{det[J^TJ]} = |\sin\theta|.$$&#xD;&#xA;Then an integral over the hemisphere can be rewritten as:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_0^{2\pi}\int_0^{\pi/2} f(\varphi^{-1}(\phi, \theta))\sin\theta\,d\theta d\phi.$$&#xD;&#xA;We are allowed to drop the absolute value around the sine since it is non-negative in $[0,\pi/2]$.&#xD;&#xA;If you were to directly construct an estimator from this you would get:&#xD;&#xA;$$\frac{\pi^2}{N}\sum_{j=1}^{N}f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j = \frac{1}{N} \sum_{j=1}^N \frac{f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j}{p_1(\phi_j, \theta_j)},\, p_1(\phi,\theta) = \frac{1}{\pi^2}.$$&#xD;&#xA;So you see that this is the estimator for uniform sampling $D$. As discussed, ideally we want to flatten the integrand. One way to do this here (assuming $f$ is not inversely proportional to $\sin\theta$) would be to cancel out the $\sin\theta$ by using a change of variables with a map $\psi$ such $det[J_{\psi}] = \sin\theta$. Such a map $\psi$ can for example be constructed using inverse transform sampling, but there are many more ways to do so. The inverse transform sampling approach results in $\psi^{-1}(\phi,\theta) = (\phi, \arccos(1-2\theta/\pi))$, and you can verify that $det[J_{\psi^{-1}}(\phi,\theta)] = \frac{2}{\pi\sin\theta}$ as desired, then $p_2(\phi, \theta) = \frac{1}{|D||det[J_{\psi^{-1}}]|} = \frac{\sin\theta}{2\pi}$, and thus the $\sin\theta$ gets cancelled in the new estimator. When you have $\cos\theta\sin\theta$ people usually come up with a map $\psi$ that cancels out both. Similarly if there is a complex brdf people typically come up with a map that would cancel out some terms of it in order to get a better estimator. &#xD;&#xA;&#xD;&#xA;A minor remark - in the literature one usually picks $D$ to be the unit box. Another remark is that in the literature they sometimes write the pdf w.r.t. different measures:&#xD;&#xA;$$p_{\omega}(\theta) d\omega = p_{\omega}(\theta)|\sin\theta|\,d\theta d\phi = p_{\phi,\theta}(\theta)\,d\theta d\phi.$$&#xD;&#xA;From there you see that the relationship is $p_{\phi,\theta}(\theta) = p_{\omega}(\theta)|\sin\theta|$. So for example a constant pdf w.r.t. the solid angle measure is translated into a sine weighted pdf w.r.t. $\phi,\theta$. This corresponds to the $\arccos$ map I mentioned. A constant pdf w.r.t. $\phi, \theta$ corresponds to a uniform distribution in the rectangle $[0,2\pi)\to[0,\pi/2]$, but it is not uniform on the hemisphere. On the other hand a constant pdf wrt solid angle corresponds to a uniform distribution on the unit hemisphere but not in the rectangle $D$. In general if you have a parametrization $\varphi^{-1}$ of some manifold such that $d\mu = \sqrt{det[J^T_{\varphi^{-1}}(t)J_{\varphi^{-1}}(t)]}\,dt$, then a constant pdf wrt $d\mu$ will give you a uniform distribution on the manifold and will cancel out this square root of the determinant term. Of course it is not always trivial constructing a map $\psi^{-1}$ that produces the desired density. Things get even uglier when you consider the area formulation of the rendering equation and you have to compute weights for multiple importance sampling." ContentLicense="CC BY-SA 4.0" />
  <row Id="41085" PostHistoryTypeId="5" PostId="13567" RevisionGUID="74de0ba8-c4c8-451d-b242-c94aefe48ae3" CreationDate="2023-06-30T02:01:55.237" UserId="10096" Comment="added 3 characters in body" Text="Assume you want to estimate the following integral:&#xD;&#xA;$$I = \int_{\Omega} f d\mu$$&#xD;&#xA;on some set $\Omega\subseteq \mathbb{R}^n$. Suppose you are given a bijective and continuously differentiable parametrization $\varphi^{-1}:D\to\Omega$ where $D=[a^1,b^1]\times\ldots\times [a^m,b^m]$. That is, we have an $m$-manifold embedded in $\mathbb{R}^n$:&#xD;&#xA;$$\Omega = \varphi^{-1}(D) = \{\varphi^{-1}(t)\in\mathbb{R}^n\,:\, t\in D\}.$$&#xD;&#xA;You can now rewrite the integral using $m$ iterated integrals as follows:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_{a^1}^{b^1}\ldots \int_{a^m}^{b^m} f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}\,dt^m\ldots dt^1.$$&#xD;&#xA;The average value of the integrand:&#xD;&#xA;$$g(t) = f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}$$&#xD;&#xA;over $D$ can then be defined as $g_{avg} = I / |D|$, where $|D|$ is the measure/area/volume of $\Omega$: $|\Omega| =\prod_{j=1}^m(b^j-a^j)$. If we have a sequence of points $t_1,\ldots,t_N\in D$ that uniformly fills the box $D$ then we may estimate the integral using the following expression:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j).$$&#xD;&#xA;Using random independent uniformly distributed points in $D$ you get the Monte Carlo estimator. Since the sampling is uniform over $D$, you can interpret the density as $p(t) = \frac{1}{|D|}$:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j)= \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p(t_j)}.$$&#xD;&#xA;Generally, estimators resulting from integrands that are flatter (i.e. $g$ is close to $g_{avg}$ without much wiggling) have lower variance. This suggests that we may reduce the error for a fixed number of samples by applying a change of variables of our integral in order to flatten the integrand and get a &quot;better&quot; estimator. That is, assume that you have a bijective and continuously differentiable map $\psi:D\to D$ such that $|det[J_{\psi}]|\propto |g|$ or at the very least it is close to proportional to $|g|$. Then by the inverse function theorem $J_{\psi^{-1}} = J^{-1}_{\psi}$ and from $det[A^{-1}] = (det[A])^{-1}$ we get &#xD;&#xA;$$|det[J_{\psi^{-1}}]| = |det[J^{-1}_{\psi}]| = \frac{1}{|det[J_{\psi}]|} \propto \frac{1}{|g|}.$$&#xD;&#xA;Thus $|det[J_{\psi^{-1}}||g|$ is close to constant, and in the case where $g$ is non-negative we may also drop the absolute value around $g$. Let us look at the change of variables:&#xD;&#xA;$$\int_D g(t)\, dt = \int_D g(\psi^{-1}(s))|det[J_{\psi^{-1}}(s)]| \, ds.$$&#xD;&#xA;We can now also compare the two estimators:&#xD;&#xA;$$|D|\frac{1}{N} \sum_{j=1}^N g(t_j), \quad |D|\frac{1}{N}\sum_{j=1}^N g(\psi^{-1}(s_j)) |det[J_{\psi^{-1}}(s_j)]|.$$&#xD;&#xA;If $\psi$ was chosen as described then the latter estimator has a product close to constant in the sum, and in the ideal case it is constant - then only 1 sample is required to find the true solution. From a probabilistic point of view this is known as importwnce sampling, i.e. we can interpret theprobability density inthe first case being constant $p_1(t) = \frac{1}{|D|}$ and in the latter case being $p_2(t) = \frac{1}{|D||det[J_{\psi^{-1}}(t)]|}$ where this density can be achieved by first generating uniform samples $s_1,\ldots,s_N\in D$ and then remapping them as $t_k = \psi^{-1}(s_k)$. The two estimators can then be rewritten as:&#xD;&#xA;$$\frac{1}{N} \sum_{j=1}^N \frac{g(t_j)}{p_1(t_j)}, \quad \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p_2(t_j)}.$$&#xD;&#xA;Note that the $t_1,\ldots,t_N$ refer to points generated in a different manner for the 2 cases, in the first they are generated according to a density $p_1$, while in the second according to $p_2$.&#xD;&#xA;&#xD;&#xA;Now consider the special case where $\Omega$ is the unit hemisphere around some normal vector $n$. Let $t,b,n$ be an arbitrary orthonormal basis ($n$ is fixed), then we may form the rotation matrix $R=\begin{bmatrix} t &amp; b &amp; n\end{bmatrix}$. We can parametrize the unit hemisphere around $n$ using &#xD;&#xA;$$\varphi^{-1}(\phi,\theta) = R\begin{bmatrix}\cos\phi\sin\theta\\\sin\phi\sin\theta\\\cos\theta\end{bmatrix}, \quad \phi\in[0,2\pi), \, \theta \in [0,\pi/2].$$&#xD;&#xA;That is $\Omega = \varphi^{-1}(D)$ where $D=[0,2\pi)\times[0,\pi/2]$. We may compute the Jacobian of this map as follows:&#xD;&#xA;$$J_{\varphi^{-1}}(\phi,\theta) = R \begin{bmatrix} -\sin\phi\sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi \sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; -\sin\theta \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;You can now compute $J^TJ$ and the square root of its determinant as follows:&#xD;&#xA;$$J_{\varphi^{-1}}^T J_{\varphi^{-1}}=&#xD;&#xA;\begin{bmatrix} &#xD;&#xA;\sin^2\theta &amp; 0 \\ 0 &amp; 1&#xD;&#xA;\end{bmatrix} \implies \sqrt{det[J^TJ]} = |\sin\theta|.$$&#xD;&#xA;Then an integral over the hemisphere can be rewritten as:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_0^{2\pi}\int_0^{\pi/2} f(\varphi^{-1}(\phi, \theta))\sin\theta\,d\theta d\phi.$$&#xD;&#xA;We are allowed to drop the absolute value around the sine since it is non-negative in $[0,\pi/2]$.&#xD;&#xA;If you were to directly construct an estimator from this you would get:&#xD;&#xA;$$\frac{\pi^2}{N}\sum_{j=1}^{N}f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j = \frac{1}{N} \sum_{j=1}^N \frac{f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j}{p_1(\phi_j, \theta_j)},\, p_1(\phi,\theta) = \frac{1}{\pi^2}.$$&#xD;&#xA;So you see that this is the estimator for uniform sampling $D$. As discussed, ideally we want to flatten the integrand. One way to do this here (assuming $f$ is not inversely proportional to $\sin\theta$) would be to cancel out the $\sin\theta$ by using a change of variables with a map $\psi$ such $det[J_{\psi}] = \sin\theta$. Such a map $\psi$ can for example be constructed using inverse transform sampling, but there are many more ways to do so. The inverse transform sampling approach results in $\psi^{-1}(\phi,\theta) = (\phi, \arccos(1-2\theta/\pi))$, and you can verify that $det[J_{\psi^{-1}}(\phi,\theta)] = \frac{2}{\pi\sin\theta}$ as desired, then $p_2(\phi, \theta) = \frac{1}{|D||det[J_{\psi^{-1}}]|} = \frac{\sin\theta}{2\pi}$, and thus the $\sin\theta$ gets cancelled in the new estimator. When you have $\cos\theta\sin\theta$ people usually come up with a map $\psi$ that cancels out both. Similarly if there is a complex brdf people typically come up with a map that would cancel out some terms of it in order to get a better estimator. &#xD;&#xA;&#xD;&#xA;A minor remark - in the literature one usually picks $D$ to be the unit box. Another remark is that in the literature they sometimes write the pdf w.r.t. different measures:&#xD;&#xA;$$p_{\omega}(\theta) d\omega = p_{\omega}(\theta)|\sin\theta|\,d\theta d\phi = p_{\phi,\theta}(\theta)\,d\theta d\phi.$$&#xD;&#xA;From there you see that the relationship is $p_{\phi,\theta}(\theta) = p_{\omega}(\theta)|\sin\theta|$. So for example a constant pdf w.r.t. the solid angle measure is translated into a sine weighted pdf w.r.t. $\phi,\theta$. This corresponds to the $\arccos$ map I mentioned. A constant pdf w.r.t. $\phi, \theta$ corresponds to a uniform distribution in the rectangle $[0,2\pi)\times[0,\pi/2]$, but it is not uniform on the hemisphere. On the other hand a constant pdf wrt solid angle corresponds to a uniform distribution on the unit hemisphere but not in the rectangle $D$. In general if you have a parametrization $\varphi^{-1}$ of some manifold such that $d\mu = \sqrt{det[J^T_{\varphi^{-1}}(t)J_{\varphi^{-1}}(t)]}\,dt$, then a constant pdf wrt $d\mu$ will give you a uniform distribution on the manifold and will cancel out this square root of the determinant term. Of course it is not always trivial constructing a map $\psi^{-1}$ that produces the desired density. Things get even uglier when you consider the area formulation of the rendering equation and you have to compute weights for multiple importance sampling." ContentLicense="CC BY-SA 4.0" />
  <row Id="41086" PostHistoryTypeId="5" PostId="13567" RevisionGUID="5db515a5-8768-4e3f-9212-9ac7af8dd8c0" CreationDate="2023-06-30T09:14:33.823" UserId="10096" Comment="added 583 characters in body" Text="Assume you want to estimate the following integral:&#xD;&#xA;$$I = \int_{\Omega} f d\mu$$&#xD;&#xA;over the set $\Omega\subseteq \mathbb{R}^n$. Suppose you are given a bijective and continuously differentiable parametrization $\varphi^{-1}:D\to\Omega$ where $D=[a^1,b^1]\times\ldots\times [a^m,b^m]$ whose Jacobian has linearly independent columns almost everywhere (i.e. except on a set of measure zero). That is, we have an almost everywhere regular $m$-manifold embedded in $\mathbb{R}^n$:&#xD;&#xA;$$\Omega = \varphi^{-1}(D) = \{\varphi^{-1}(t)\in\mathbb{R}^n\,:\, t\in D\}.$$&#xD;&#xA;You can now rewrite the integral using $m$ iterated integrals as follows:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_{a^1}^{b^1}\ldots \int_{a^m}^{b^m} f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}\,dt^m\ldots dt^1.$$&#xD;&#xA;The average value of the integrand:&#xD;&#xA;$$g(t) = f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}$$&#xD;&#xA;over $D$ can then be defined as $g_{avg} = I / |D|$, where $|D|$ is the measure/area/volume of $\Omega$: $|\Omega| =\prod_{j=1}^m(b^j-a^j)$. If we have a sequence of points $t_1,\ldots,t_N\in D$ that uniformly fills the box $D$ then we may estimate the integral using the following expression:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j).$$&#xD;&#xA;Using random independent uniformly distributed points in $D$ you get the Monte Carlo estimator. Since the sampling is uniform over $D$, you can interpret the density as $p(t) = \frac{1}{|D|}$:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j)= \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p(t_j)}.$$&#xD;&#xA;Generally, estimators resulting from integrands that are flatter (i.e. $g$ is close to $g_{avg}$ without much wiggling) have lower variance. This suggests that we may reduce the error for a fixed number of samples by applying a change of variables of our integral in order to flatten the integrand and get a &quot;better&quot; estimator. That is, assume that you have a bijective and continuously differentiable map $\psi:D\to D$ that has a non-singular Jacobian almost everywhere, such that $|det[J_{\psi}]|\propto |g|$ or at the very least it is close to proportional to $|g|$. Then by the inverse function theorem $J_{\psi^{-1}} = J^{-1}_{\psi}$ and from $det[A^{-1}] = (det[A])^{-1}$ we get &#xD;&#xA;$$|det[J_{\psi^{-1}}]| = |det[J^{-1}_{\psi}]| = \frac{1}{|det[J_{\psi}]|} \propto \frac{1}{|g|}.$$&#xD;&#xA;Thus $|det[J_{\psi^{-1}}||g|$ is close to constant, and in the case where $g$ is non-negative we may also drop the absolute value around $g$. Let us look at the change of variables:&#xD;&#xA;$$\int_D g(t)\, dt = \int_D g(\psi^{-1}(s))|det[J_{\psi^{-1}}(s)]| \, ds.$$&#xD;&#xA;We can now also compare the two estimators:&#xD;&#xA;$$|D|\frac{1}{N} \sum_{j=1}^N g(t_j), \quad |D|\frac{1}{N}\sum_{j=1}^N g(\psi^{-1}(s_j)) |det[J_{\psi^{-1}}(s_j)]|.$$&#xD;&#xA;If $\psi$ was chosen as described then the latter estimator has a product close to constant in the sum, and in the ideal case it is constant - then only 1 sample is required to find the true solution. In probability and statistics the usage of such a map $\psi^{-1}$ is known as importance sampling, however note that this concept is more general and doesn't actually require any probabilistic considerations. Nevertheless, in the probabilistic setting we can interpret the probability density function (pdf) in the first case as being constant $p_1(t) = \frac{1}{|D|}$ and in the second case the pdf is $p_2(t) = \frac{1}{|D||det[J_{\psi^{-1}}(t)]|}$ where this density can be achieved by first generating uniform samples $s_1,\ldots,s_N\in D$ and then remapping them as $t_k = \psi^{-1}(s_k)$. The two estimators can then be rewritten as:&#xD;&#xA;$$\frac{1}{N} \sum_{j=1}^N \frac{g(t_j)}{p_1(t_j)}, \quad \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p_2(t_j)}.$$&#xD;&#xA;Note that the $t_1,\ldots,t_N$ refer to points generated in a different manner for the 2 cases, in the first they are generated according to a density $p_1$, while in the second according to $p_2$.&#xD;&#xA;&#xD;&#xA;Now consider the special case where $\Omega$ is the unit hemisphere around some normal vector $n$. Let $t,b,n$ be an arbitrary orthonormal basis ($n$ is fixed), then we may form the rotation matrix $R=\begin{bmatrix} t &amp; b &amp; n\end{bmatrix}$. We can parametrize the unit hemisphere around $n$ using &#xD;&#xA;$$\varphi^{-1}(\phi,\theta) = R\begin{bmatrix}\cos\phi\sin\theta\\\sin\phi\sin\theta\\\cos\theta\end{bmatrix}, \quad \phi\in[0,2\pi), \, \theta \in [0,\pi/2].$$&#xD;&#xA;That is $\Omega = \varphi^{-1}(D)$ where $D=[0,2\pi)\times[0,\pi/2]$. We may compute the Jacobian of this map as follows:&#xD;&#xA;$$J_{\varphi^{-1}}(\phi,\theta) = R \begin{bmatrix} -\sin\phi\sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi \sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; -\sin\theta \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;It is clear that the Jacobian has linearly independent columns for $\theta\in(0,\pi/2]$ and those are linearly dependent only for $\theta = 0$ or $\theta = \pi$, so as desired the map is regular almost everywhere.&#xD;&#xA;You can now compute $J^TJ$ and the square root of its determinant as follows:&#xD;&#xA;$$J_{\varphi^{-1}}^T J_{\varphi^{-1}}=&#xD;&#xA;\begin{bmatrix} &#xD;&#xA;\sin^2\theta &amp; 0 \\ 0 &amp; 1&#xD;&#xA;\end{bmatrix} \implies \sqrt{det[J^TJ]} = |\sin\theta|.$$&#xD;&#xA;Then the integral over the hemisphere can be rewritten as:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_0^{2\pi}\int_0^{\pi/2} f(\varphi^{-1}(\phi, \theta))\sin\theta\,d\theta d\phi.$$&#xD;&#xA;We are allowed to drop the absolute value around the sine since it is non-negative in $[0,\pi/2]$.&#xD;&#xA;If you were to directly construct an estimator from this you would get:&#xD;&#xA;$$\frac{\pi^2}{N}\sum_{j=1}^{N}f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j = \frac{1}{N} \sum_{j=1}^N \frac{f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j}{p_1(\phi_j, \theta_j)},\, p_1(\phi,\theta) = \frac{1}{\pi^2}.$$&#xD;&#xA;This is the estimator for uniform sampling $D$. As discussed, ideally we want to flatten the integrand. One way to do this here (assuming $f$ is not inversely proportional to $\sin\theta$) would be to cancel out the $\sin\theta$ by using a change of variables with a map $\psi$ such $det[J_{\psi}] = \sin\theta$. Such a map $\psi$ can for example be constructed using inverse transform sampling, but there are many more ways to do so. The inverse transform sampling approach results in $\psi^{-1}(\phi,\theta) = (\phi, \arccos(1-2\theta/\pi))$, and you can verify that $det[J_{\psi^{-1}}(\phi,\theta)] = \frac{2}{\pi\sin\theta}$ as desired, then $p_2(\phi, \theta) = \frac{1}{|D||det[J_{\psi^{-1}}]|} = \frac{\sin\theta}{2\pi}$, and thus the $\sin\theta$ gets cancelled in the new estimator. When you have $\cos\theta\sin\theta$ people usually come up with a map $\psi$ that cancels out both. Similarly if there is a complex brdf people typically come up with a map that would cancel out some terms of it in order to get a better estimator. &#xD;&#xA;&#xD;&#xA;A minor remark - in the literature one usually picks $D$ to be the unit box. Another remark is that in the literature they sometimes write the pdf w.r.t. different measures:&#xD;&#xA;$$p_{\omega}(\theta) d\omega = p_{\omega}(\theta)|\sin\theta|\,d\theta d\phi = p_{\phi,\theta}(\theta)\,d\theta d\phi.$$&#xD;&#xA;From there you see that the relationship is $p_{\phi,\theta}(\theta) = p_{\omega}(\theta)|\sin\theta|$. So for example a constant pdf w.r.t. the solid angle measure is translated into a sine weighted pdf w.r.t. $\phi,\theta$. This corresponds to the $\arccos$ map I mentioned. A constant pdf w.r.t. $\phi, \theta$ corresponds to a uniform distribution in the rectangle $[0,2\pi)\times[0,\pi/2]$, but it is not uniform on the hemisphere. On the other hand a constant pdf wrt solid angle corresponds to a uniform distribution on the unit hemisphere but not in the rectangle $D$. In general if you have a parametrization $\varphi^{-1}$ of some manifold such that $d\mu = \sqrt{det[J^T_{\varphi^{-1}}(t)J_{\varphi^{-1}}(t)]}\,dt$, then a constant pdf wrt $d\mu$ will give you a uniform distribution on the manifold and will cancel out this square root of the determinant term. Of course it is not always trivial constructing a map $\psi^{-1}$ that produces the desired density. Things get even uglier when you consider the area formulation of the rendering equation and you have to compute weights for multiple importance sampling." ContentLicense="CC BY-SA 4.0" />
  <row Id="41087" PostHistoryTypeId="5" PostId="13567" RevisionGUID="766a15ce-0e23-48a8-ae5d-42664468ef33" CreationDate="2023-06-30T14:14:55.830" UserId="10096" Comment="deleted 10 characters in body" Text="Assume you want to estimate the following integral:&#xD;&#xA;$$I = \int_{\Omega} f d\mu$$&#xD;&#xA;over the set $\Omega\subseteq \mathbb{R}^n$. Suppose you are given a bijective and continuously differentiable parametrization $\varphi^{-1}:D\to\Omega$ where $D=[a^1,b^1]\times\ldots\times [a^m,b^m]$ whose Jacobian has linearly independent columns almost everywhere (i.e. except on a set of measure zero). That is, we have an almost everywhere regular $m$-manifold embedded in $\mathbb{R}^n$:&#xD;&#xA;$$\Omega = \varphi^{-1}(D) = \{\varphi^{-1}(t)\in\mathbb{R}^n\,:\, t\in D\}.$$&#xD;&#xA;You can now rewrite the integral using $m$ iterated integrals as follows:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_{a^1}^{b^1}\ldots \int_{a^m}^{b^m} f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}\,dt^m\ldots dt^1.$$&#xD;&#xA;The average value of the integrand:&#xD;&#xA;$$g(t) = f(\varphi^{-1}(t))\sqrt{det[J_{\varphi^{-1}}^T(t)J_{\varphi^{-1}}(t)]}$$&#xD;&#xA;over $D$ can then be defined as $g_{avg} = I / |D|$, where $|D|$ is the measure/area/volume of $D$: $|D| =\prod_{j=1}^m(b^j-a^j)$. If we have a sequence of points $t_1,\ldots,t_N\in D$ that uniformly fills the box $D$ then we may estimate the integral using the following expression:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j).$$&#xD;&#xA;Using random independent uniformly distributed points in $D$ you get the Monte Carlo estimator. Since the sampling is uniform over $D$, you can interpret the density as $p(t) = \frac{1}{|D|}$:&#xD;&#xA;$$I = |D|g_{avg} \approx |D|\frac{1}{N}\sum_{j=1}^N g(t_j)= \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p(t_j)}.$$&#xD;&#xA;Generally, estimators resulting from integrands that are flatter (i.e. $g$ is close to $g_{avg}$ without much wiggling) have lower variance. This suggests that we may reduce the error for a fixed number of samples by applying a change of variables of our integral in order to flatten the integrand and get a &quot;better&quot; estimator. That is, assume that you have a bijective and continuously differentiable map $\psi:D\to D$ that has a non-singular Jacobian almost everywhere, such that $|det[J_{\psi}]|\propto |g|$ or at the very least it is close to proportional to $|g|$. Then by the inverse function theorem $J_{\psi^{-1}} = J^{-1}_{\psi}$ and from $det[A^{-1}] = (det[A])^{-1}$ we get &#xD;&#xA;$$|det[J_{\psi^{-1}}]| = |det[J^{-1}_{\psi}]| = \frac{1}{|det[J_{\psi}]|} \propto \frac{1}{|g|}.$$&#xD;&#xA;Thus $|det[J_{\psi^{-1}}||g|$ is close to constant, and in the case where $g$ is non-negative we may also drop the absolute value around $g$. Let us look at the change of variables:&#xD;&#xA;$$\int_D g(t)\, dt = \int_D g(\psi^{-1}(s))|det[J_{\psi^{-1}}(s)]| \, ds.$$&#xD;&#xA;We can now also compare the two estimators:&#xD;&#xA;$$|D|\frac{1}{N} \sum_{j=1}^N g(t_j), \quad |D|\frac{1}{N}\sum_{j=1}^N g(\psi^{-1}(s_j)) |det[J_{\psi^{-1}}(s_j)]|.$$&#xD;&#xA;If $\psi$ was chosen as described then the latter estimator has a product close to constant in the sum, and in the ideal case it is constant - then only 1 sample is required to find the true solution. In probability and statistics the usage of such a map $\psi^{-1}$ is known as importance sampling, however note that this concept is more general and doesn't actually require any probabilistic considerations. Nevertheless, in the probabilistic setting we can interpret the probability density function (pdf) in the first case as being constant $p_1(t) = \frac{1}{|D|}$ and in the second case the pdf is $p_2(t) = \frac{1}{|D||det[J_{\psi^{-1}}(t)]|}$ where this density can be achieved by first generating uniform samples $s_1,\ldots,s_N\in D$ and then remapping them as $t_k = \psi^{-1}(s_k)$. The two estimators can then be rewritten as:&#xD;&#xA;$$\frac{1}{N} \sum_{j=1}^N \frac{g(t_j)}{p_1(t_j)}, \quad \frac{1}{N}\sum_{j=1}^N \frac{g(t_j)}{p_2(t_j)}.$$&#xD;&#xA;Note that the $t_1,\ldots,t_N$ refer to points generated in a different manner for the 2 cases, in the first they are generated according to a density $p_1$, while in the second according to $p_2$.&#xD;&#xA;&#xD;&#xA;Now consider the special case where $\Omega$ is the unit hemisphere around some normal vector $n$. Let $t,b,n$ be an arbitrary orthonormal basis ($n$ is fixed), then we may form the rotation matrix $R=\begin{bmatrix} t &amp; b &amp; n\end{bmatrix}$. We can parametrize the unit hemisphere around $n$ using &#xD;&#xA;$$\varphi^{-1}(\phi,\theta) = R\begin{bmatrix}\cos\phi\sin\theta\\\sin\phi\sin\theta\\\cos\theta\end{bmatrix}, \quad \phi\in[0,2\pi), \, \theta \in [0,\pi/2].$$&#xD;&#xA;That is $\Omega = \varphi^{-1}(D)$ where $D=[0,2\pi)\times[0,\pi/2]$. We may compute the Jacobian of this map as follows:&#xD;&#xA;$$J_{\varphi^{-1}}(\phi,\theta) = R \begin{bmatrix} -\sin\phi\sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi \sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; -\sin\theta \end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;It is clear that the Jacobian has linearly independent columns for $\theta\in(0,\pi/2]$ and those are linearly dependent only for $\theta = 0$ or $\theta = \pi$, so as desired the map is regular almost everywhere.&#xD;&#xA;You can now compute $J^TJ$ and the square root of its determinant as follows:&#xD;&#xA;$$J_{\varphi^{-1}}^T J_{\varphi^{-1}}=&#xD;&#xA;\begin{bmatrix} &#xD;&#xA;\sin^2\theta &amp; 0 \\ 0 &amp; 1&#xD;&#xA;\end{bmatrix} \implies \sqrt{det[J^TJ]} = |\sin\theta|.$$&#xD;&#xA;Then the integral over the hemisphere can be rewritten as:&#xD;&#xA;$$I = \int_{\Omega} f\,d\mu = \int_0^{2\pi}\int_0^{\pi/2} f(\varphi^{-1}(\phi, \theta))\sin\theta\,d\theta d\phi.$$&#xD;&#xA;We are allowed to drop the absolute value around the sine since it is non-negative in $[0,\pi/2]$.&#xD;&#xA;If you were to directly construct an estimator from this you would get:&#xD;&#xA;$$\frac{\pi^2}{N}\sum_{j=1}^{N}f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j = \frac{1}{N} \sum_{j=1}^N \frac{f(\varphi^{-1}(\phi_j,\theta_j))\sin\theta_j}{p_1(\phi_j, \theta_j)},\, p_1(\phi,\theta) = \frac{1}{\pi^2}.$$&#xD;&#xA;This is the estimator for uniform sampling $D$. As discussed, ideally we want to flatten the integrand. One way to do this here (assuming $f$ is not inversely proportional to $\sin\theta$) would be to cancel out the $\sin\theta$ by using a change of variables with a map $\psi$ such $det[J_{\psi}] = \sin\theta$. Such a map $\psi$ can for example be constructed using inverse transform sampling, but there are many more ways to do so. The inverse transform sampling approach results in $\psi^{-1}(\phi,\theta) = (\phi, \arccos(1-2\theta/\pi))$, and you can verify that $det[J_{\psi^{-1}}(\phi,\theta)] = \frac{2}{\pi\sin\theta}$ as desired, then $p_2(\phi, \theta) = \frac{1}{|D||det[J_{\psi^{-1}}]|} = \frac{\sin\theta}{2\pi}$, and thus the $\sin\theta$ gets cancelled in the new estimator. When you have $\cos\theta\sin\theta$ people usually come up with a map $\psi$ that cancels out both. Similarly if there is a complex brdf people typically come up with a map that would cancel out some terms of it in order to get a better estimator. &#xD;&#xA;&#xD;&#xA;A minor remark - in the literature one usually picks $D$ to be the unit box. Another remark is that in the literature they sometimes write the pdf w.r.t. different measures:&#xD;&#xA;$$p_{\omega}(\theta) d\omega = p_{\omega}(\theta)|\sin\theta|\,d\theta d\phi = p_{\phi,\theta}(\theta)\,d\theta d\phi.$$&#xD;&#xA;From there you see that the relationship is $p_{\phi,\theta}(\theta) = p_{\omega}(\theta)|\sin\theta|$. So for example a constant pdf w.r.t. the solid angle measure is translated into a sine weighted pdf w.r.t. $\phi,\theta$. This corresponds to the $\arccos$ map I mentioned. A constant pdf w.r.t. $\phi, \theta$ corresponds to a uniform distribution in the rectangle $[0,2\pi)\times[0,\pi/2]$, but it is not uniform on the hemisphere. On the other hand a constant pdf wrt solid angle corresponds to a uniform distribution on the unit hemisphere but not in the rectangle $D$. In general if you have a parametrization $\varphi^{-1}$ of some manifold such that $d\mu = \sqrt{det[J^T_{\varphi^{-1}}(t)J_{\varphi^{-1}}(t)]}\,dt$, then a constant pdf wrt $d\mu$ will give you a uniform distribution on the manifold and will cancel out this square root of the determinant term. Of course it is not always trivial constructing a map $\psi^{-1}$ that produces the desired density. Things get even uglier when you consider the area formulation of the rendering equation and you have to compute weights for multiple importance sampling." ContentLicense="CC BY-SA 4.0" />
  <row Id="41098" PostHistoryTypeId="50" PostId="12498" RevisionGUID="3e3a169e-bab1-40bd-9503-147049d5b546" CreationDate="2023-07-01T03:09:06.027" UserId="-1" />
  <row Id="41099" PostHistoryTypeId="5" PostId="13565" RevisionGUID="af1cb958-91b3-4762-a823-a624d8ecc894" CreationDate="2023-07-01T09:30:53.500" UserId="13273" Comment="added 2036 characters in body" Text="I don't think that you have access to the current time on GPU / pixel shader. So you need to transmit the information from CPU to GPU.&#xD;&#xA;&#xD;&#xA;There are many ways to store the framerate results.&#xD;&#xA;&#xD;&#xA;**Example storing directly into a texture:**&#xD;&#xA;&#xD;&#xA;You can create a texture with height (framerate max) and width (number of samples) and store directly the new framerate value to this texture. The texture sampler can be set to mode `wrap` so that you can use the texture as ring buffer.&#xD;&#xA;This example has many disadvantages: &#xD;&#xA;&#xD;&#xA; 1. You need to define the maximum and minimum framerate which should be visible. This is a disadvantage because the framerate can vary a lot depending on the complexity of the rendered geometry and the complexity of the shader which render the geometry. So when rotating the camera the number of pixel which got hit may vary a lot, so you can have huge jumps within your texture (see figure1 a). &#xD;&#xA; 2. The next disadvantage is that when you render very complex geometries where your framerate drops a lot, your framerate will show the minimum framerate. But the framerate will not be the same. Lets say it changes from 0.01 frames per second to 0.4 frames per second. So each value within this range will be stored at `min framerate` but the factor from the minimum to the maximum is 40! (see figure1 b)&#xD;&#xA; 3. When rendering only a small triangle, your framerate can increase and be outside the scale of your texture. Therefor it will not be visible inside your texture (see figure1 c).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure1:** Displaying the disadvantages of storing the framerate directly to a texture.&#xD;&#xA;&#xD;&#xA;**Example storing framerate to a buffer:**&#xD;&#xA;&#xD;&#xA;First create a buffer on GPU where the framerates will be stored to and use it as ring buffer. Create a shader to visualize the histogram by passing an integer value as current position within the buffer and use modulo operator to find the correct position in the buffer when rendering with your pixel shader. This approch will have the following benefits:&#xD;&#xA;&#xD;&#xA; 1. The buffer is very small in contrast to a texture.&#xD;&#xA; 2. You only need to transfer 2 values (current position in buffer, new framerate value). &#xD;&#xA; 3. You are not restricted to a minimum or maximum framerate which can be displayed.&#xD;&#xA; 4. By passing the additional variables `minFramerate` and `maxFramerate` you can scale the histogram. So that in the example case b) will show you the big differences between 0.01 frames per second and 0.4 frames per second. The framerate also can not be outside of the maximal showable framerate (example case c).&#xD;&#xA; 5. you can draw lines from one value to the next value, so there will be no gabs in between.&#xD;&#xA; 6. you can change the shader from drawing connected lines to boxes if you like.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JHHEA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41100" PostHistoryTypeId="5" PostId="13565" RevisionGUID="9be891b4-b4ae-4a60-9ded-bd0c9b51cd96" CreationDate="2023-07-01T10:34:11.607" UserId="13273" Comment="deleted 4 characters in body" Text="I don't think that you have access to the current time on GPU / pixel shader. So you need to transmit the information from CPU to GPU.&#xD;&#xA;&#xD;&#xA;There are many ways to store the framerate results.&#xD;&#xA;&#xD;&#xA;**Example storing directly into a texture:**&#xD;&#xA;&#xD;&#xA;You can create a texture with height (framerate max) and width (number of samples) and store directly the new framerate value to this texture. The texture sampler can be set to mode `wrap` so that you can use the texture as ring buffer.&#xD;&#xA;This example has many disadvantages: &#xD;&#xA;&#xD;&#xA; 1. You need to define the maximum and minimum framerate which should be visible. This is a disadvantage because the framerate can vary a lot depending on the complexity of the rendered geometry and the complexity of the shader which render the geometry. So when rotating the camera the number of pixel which got hit may vary a lot, so you can have huge jumps within your texture (see figure1 a). &#xD;&#xA; 2. The next disadvantage is that when you render very complex geometries where your framerate drops a lot, your framerate will show the minimum framerate. But the framerate will not be the same. Lets say it changes from 0.01 frames per second to 0.4 frames per second. So each value within this range will be stored at `min framerate` but the factor from the minimum to the maximum is 40! (see figure1 b)&#xD;&#xA; 3. When rendering only a small triangle, your framerate can increase and be outside the scale of your texture. Therefor it will not be visible inside your texture (see figure1 c).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure1:** Displaying the disadvantages of storing the framerate directly to a texture.&#xD;&#xA;&#xD;&#xA;**Example storing framerate to a buffer:**&#xD;&#xA;&#xD;&#xA;First create a buffer on GPU where the framerates will be stored to and use it as ring buffer. Create a shader to visualize the histogram by passing an integer value as current position of the buffer and use modulo operator to find the correct position in the buffer when rendering with your pixel shader. This approch will have the following benefits:&#xD;&#xA;&#xD;&#xA; 1. The buffer is very small in contrast to a texture.&#xD;&#xA; 2. You only need to transfer 2 values (current position in buffer, new framerate value). &#xD;&#xA; 3. You are not restricted to a minimum or maximum framerate which can be displayed.&#xD;&#xA; 4. By passing the additional variables `minFramerate` and `maxFramerate` you can scale the histogram. So that in the example case b) will show you the big differences between 0.01 frames per second and 0.4 frames per second. The framerate also can not be outside of the maximal showable framerate (example case c).&#xD;&#xA; 5. you can draw lines from one value to the next value, so there will be no gabs in between.&#xD;&#xA; 6. you can change the shader from drawing connected lines to boxes if you like.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JHHEA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41101" PostHistoryTypeId="5" PostId="13566" RevisionGUID="51df46cb-3fa0-45e9-a3b8-57d0043d85c5" CreationDate="2023-07-01T14:08:37.537" UserId="7952" Comment="added 85 characters in body" Text="It sounds like you want to gather timings for say 100 frames (x frames) then show that data histogram style.&#xD;&#xA;&#xD;&#xA;You could store the histogram data directly in the shader as an array of floats and draw directly out of the array using the vertex index id, but to update the histogram the array would have to be rewritten inside the shader, then the shader reloaded and recompiled. Overall it is not a very appealing approach.&#xD;&#xA;&#xD;&#xA;A simple approach that is much more flexible, is to write the sample data into a vertex attributes buffer. Bind the vertex buffer and at draw time, the GPU feeds the data to your shader. Each histogram gl_line requires two values, so the first value would be zero and the second value would be the timing value. Repeat that for every timing value. The histogram then becomes a series of lines where the length of the line is determined by the passed in timing, the x position of the line is determined by the vertex index id, and the height of the lines can be uniformly scaled. Finally use a vec3 offset to move the histogram anywhere on the output buffer. gl line width can be used to thicken the lines up so the entire histogram isn't minuscule in size.&#xD;&#xA;&#xD;&#xA;Now the histogram draw is just a matter of binding the vertex buffer containing the timing data, and doing the draw call. Changing the number of values is just a matter of writing a bigger vertex buffer and changing the number of vertices in the draw call.&#xD;&#xA;&#xD;&#xA;To update the histogram gather more data, push it out to the vertex buffer and draw. &#xD;&#xA;&#xD;&#xA;Once this is working it is easy to get fancy with ring buffers, using quads for the histogram lines, animating, etc.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/IIHeQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41102" PostHistoryTypeId="2" PostId="13569" RevisionGUID="11023634-ccf9-494a-ba54-e65645fba2fe" CreationDate="2023-07-02T03:17:37.020" UserId="19537" Text="Recently I feel a bit confused about one-sample model MIS. One sample model MIS can be found here in [Veach 1997. 9.2.4 The one-sample model](https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter9.pdf), and this one-sample model is widely used in the opensource renderers, for example: the combination of BSDF sampling and emitter sampling in mitsuba2/3 and pbrt, path connection in BDPT for mitsuba and pbrt, etc. Basically, the estimator is:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{w_I(X)f(X)}{c_Ip_I(X)}&#xD;&#xA;$$&#xD;&#xA;$c_I$ is the discrete PMF for choosing $I$th sampling strategy, $p_I(·)$ is the PDF for the $I$th sampling strategy. This is reasonable, since I can easily prove that with several unbiased estimator, the one-sample model is unbiased. Here I present a simple case where balance heuristic is used:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\mathbb{E}\left(\frac{w_I(X)f(X)}{c_I p_I(X)}\right) = \int\frac{\frac{p_1(X)}{p_1(X)  + p_2(X)}f(X)}{p_{c_1} p_{1}(X)}\times \left(p_{c_1} p_1(X)\right) + \frac{\frac{p_2(X)}{p_1(X) + p_2(X)}f(X)}{p_{c_2} p_{2}(X)}\times \left(p_{c_2} p_2(X)\right)dX = \int \frac{p_1(X) + p_2(X)}{p_1(X) + p_2(X)}f(X) dX= \int f(X) dX&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;My problem is:&#xD;&#xA;&#xD;&#xA;- From the opensource renderers, I find that the one-sample model used in them **only samples via one strategy (other strategies have zero probability to get sampled)**. For example:&#xD;&#xA;    &#xD;&#xA;  - In path tracer NEE, we only use emitter sampling (and we don't actually sample BSDF when doing NEE). This can be found in pbrt-v3 and mitsuba2/3.&#xD;&#xA;  - In BDPT path connection, we only sample &quot;once&quot; and calculate the weight for that exact path.&#xD;&#xA;&#xD;&#xA;- Is this correct for one specific strategy to have zero probability to be sampled? I know that $p_{c_I}$ in the nominator and denominator will cancel each other out, but it still doesn't feel right.&#xD;&#xA;&#xD;&#xA;- If I use balance heuristic, the estimator can actually be simplified when we only use one strategy to sample (the corresponding discrete PMF is 1):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{\frac{p_1(X)}{p_1(X) + p_2(X)}f(X)}{p_{1}} = \frac{f(X)}{p_1(X) + p_2(X)} &lt; f(X) / p_1(X)&#xD;&#xA;$$&#xD;&#xA;My problem for the eqn above is: Can I say that using one-sample MIS with heuristic will produce smaller mean-value than the original Monte Carlo estimator? Since I know that the original estimator is unbiased, doesn't this indicate that the one-sample MIS which samples via only one strategy is biased? Did I misunderstand anything here?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41104" PostHistoryTypeId="1" PostId="13569" RevisionGUID="11023634-ccf9-494a-ba54-e65645fba2fe" CreationDate="2023-07-02T03:17:37.020" UserId="19537" Text="One-sample model Multiple Importance Sampling with balance heuristic" ContentLicense="CC BY-SA 4.0" />
  <row Id="41105" PostHistoryTypeId="3" PostId="13569" RevisionGUID="11023634-ccf9-494a-ba54-e65645fba2fe" CreationDate="2023-07-02T03:17:37.020" UserId="19537" Text="|rendering|sampling|pbr|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41106" PostHistoryTypeId="6" PostId="13569" RevisionGUID="68f715d8-1b41-4752-9acd-b6b5f2feec28" CreationDate="2023-07-02T09:24:36.130" UserId="19537" Comment="edited tags" Text="|rendering|mathematics|sampling|pbr|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41107" PostHistoryTypeId="50" PostId="10879" RevisionGUID="232c410e-fb61-4faa-8d95-8768df2268c4" CreationDate="2023-07-02T13:01:50.193" UserId="-1" />
  <row Id="41108" PostHistoryTypeId="2" PostId="13570" RevisionGUID="3973f72a-dc46-4dfa-82af-76a04b938fcd" CreationDate="2023-07-02T15:05:54.893" UserId="20171" Text="I have tried &#xD;&#xA;&#xD;&#xA;    Texture2D textures[64] : register(t0);&#xD;&#xA;    SameplerState smpl;&#xD;&#xA;    float4 main(float2 uv : TEXCOODS1, uint i : Index) : SV_Target &#xD;&#xA;    {&#xD;&#xA;       return textures[i].Sample(smpl, uv);&#xD;&#xA;    }&#xD;&#xA;But whe I compile I get an error that says array index must be literal experesion " ContentLicense="CC BY-SA 4.0" />
  <row Id="41110" PostHistoryTypeId="1" PostId="13570" RevisionGUID="3973f72a-dc46-4dfa-82af-76a04b938fcd" CreationDate="2023-07-02T15:05:54.893" UserId="20171" Text="Hlsl Texture2d array that can be accessed using a variable index" ContentLicense="CC BY-SA 4.0" />
  <row Id="41111" PostHistoryTypeId="3" PostId="13570" RevisionGUID="3973f72a-dc46-4dfa-82af-76a04b938fcd" CreationDate="2023-07-02T15:05:54.893" UserId="20171" Text="|hlsl|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41112" PostHistoryTypeId="50" PostId="13338" RevisionGUID="2b8ef5be-ca1b-4b20-a0b6-fed4d72c5765" CreationDate="2023-07-02T16:01:50.220" UserId="-1" />
  <row Id="41114" PostHistoryTypeId="5" PostId="12885" RevisionGUID="10845e11-6a72-4de5-abc7-8d901848ff5c" CreationDate="2023-07-03T12:36:26.063" UserId="6114" Comment="added 162 characters in body" Text="It's almost never a problem of computational costs, it's a matter of how well a function works in a Monte Carlo scenario. Ie. how well it can be importance sampled. That generally leads to how well it can be inversely transformed to get an importance sampled scattering direction.&#xD;&#xA;&#xD;&#xA;With HG or some modified HG phase fnc we can nicely match Mie for anything bigger than the wavelength and looking how well it can be importance sampled it makes no sense to use Mie for common cases like those we find generally in rendering. So yep you better off with HG.&#xD;&#xA;&#xD;&#xA;Eventually some good read : &#xD;&#xA;https://opg.optica.org/ao/abstract.cfm?uri=ao-35-18-3270&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;EDIT : with Siggraph2023 there's an HG_Drain phase fnc that better matches tabulated Mie phase fnc.. &#xD;&#xA;https://research.nvidia.com/labs/rtr/approximate-mie/&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41115" PostHistoryTypeId="2" PostId="13571" RevisionGUID="33d4edba-2919-4ac7-b9b0-c86854c95abf" CreationDate="2023-07-03T12:45:01.973" UserId="15920" Text="I've seen this in a lot of animations of spaceships, as well as the intro sequence to The Expanse which I've attached a screenshot of. https://vimeo.com/734114243 is also an example. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;The above screenshot again, but with the contrast boosted:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;While in both cases this overlay has been added in post, what kind of camera setup are they trying to emulate?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RWCH7.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/WX9Mo.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41117" PostHistoryTypeId="1" PostId="13571" RevisionGUID="33d4edba-2919-4ac7-b9b0-c86854c95abf" CreationDate="2023-07-03T12:45:01.973" UserId="15920" Text="What is the name for a film overlay where there is an array of crosses?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41118" PostHistoryTypeId="3" PostId="13571" RevisionGUID="33d4edba-2919-4ac7-b9b0-c86854c95abf" CreationDate="2023-07-03T12:45:01.973" UserId="15920" Text="|camera|post-processing|space|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41119" PostHistoryTypeId="2" PostId="13572" RevisionGUID="c3eb3b62-7944-4088-977d-f237e6f5f8cf" CreationDate="2023-07-03T15:24:39.887" UserId="20179" Text="is there a way to output the power in watts from an R, G and B value? I know there are many formulae to get perceived brightness but is there one to get an objective amount (relative or otherwise)? &#xD;&#xA;&#xD;&#xA;This is for an experiment I am working on which basically requires radiance to stay constant between images but I am not sure how to calculate radiance fro an image." ContentLicense="CC BY-SA 4.0" />
  <row Id="41121" PostHistoryTypeId="1" PostId="13572" RevisionGUID="c3eb3b62-7944-4088-977d-f237e6f5f8cf" CreationDate="2023-07-03T15:24:39.887" UserId="20179" Text="How can I get an Irradiance or power value from RGB?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41122" PostHistoryTypeId="3" PostId="13572" RevisionGUID="c3eb3b62-7944-4088-977d-f237e6f5f8cf" CreationDate="2023-07-03T15:24:39.887" UserId="20179" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41123" PostHistoryTypeId="2" PostId="13573" RevisionGUID="049eecbd-f8d6-4f06-bebb-43ada4bf928b" CreationDate="2023-07-04T18:49:59.113" UserDisplayName="user1703" Text="If all you need is to check constancy, I would rely on $R+G+B$, as the energies are additive. Make sure that none of the components saturate and don't change anything in the geometry.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41125" PostHistoryTypeId="50" PostId="13258" RevisionGUID="f307ad57-dca7-4b9c-8c9d-9643ead2b6ad" CreationDate="2023-07-04T19:06:25.847" UserId="-1" />
  <row Id="41126" PostHistoryTypeId="50" PostId="13262" RevisionGUID="b294ba4e-e0b9-4055-9af0-52e0ac03953b" CreationDate="2023-07-04T21:08:41.067" UserId="-1" />
  <row Id="41127" PostHistoryTypeId="50" PostId="13022" RevisionGUID="f761f7fc-1cce-434c-8ae1-ecdd067d9e23" CreationDate="2023-07-05T02:06:55.790" UserId="-1" />
  <row Id="41128" PostHistoryTypeId="6" PostId="13022" RevisionGUID="99348497-fe91-4aa7-b027-9db89f070360" CreationDate="2023-07-05T11:08:10.013" UserId="6" Comment="edited tags" Text="|3d|mathematics|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41129" PostHistoryTypeId="2" PostId="13574" RevisionGUID="6802e001-d4c8-4313-bcc0-4eabef983fd5" CreationDate="2023-07-05T17:13:49.527" UserDisplayName="user1703" Text="If the irradiance is constant over the surface considered (or if the surface is small enough), one steradian corresponds to an area of $1/4\pi\,m^2$ on the unit sphere so that $1 W/m^2$ is equivalent to $4\pi\,W/sr$ at $1\,m$." ContentLicense="CC BY-SA 4.0" />
  <row Id="41131" PostHistoryTypeId="2" PostId="13575" RevisionGUID="61d71f6e-5896-49c7-a0e9-2b78164db12a" CreationDate="2023-07-05T17:23:30.607" UserId="506" Text="It’s called a [Résau plate](https://en.wikipedia.org/wiki/Réseau_plate):&#xD;&#xA;&#xD;&#xA;&gt; …a transparent sheet of glass or plastic engraved with a grid of crosshatches called [fiducial markers](https://en.wikipedia.org/wiki/Fiducial_marker). It was commonly used in film cameras (before the advent of digital cameras) for scientific and technical photography.&#xD;&#xA;&#xD;&#xA;These were [used on several of the cameras on the Apollo missions](https://history.nasa.gov/alsj/a11/a11-hass.html), which is probably where this pattern entered public awareness. From the NASA article linked above:&#xD;&#xA;&#xD;&#xA;&gt; The crosses are recorded on every exposed frame and provided a means of determining angular distances between objects in the field-of-view." ContentLicense="CC BY-SA 4.0" />
  <row Id="41134" PostHistoryTypeId="2" PostId="13576" RevisionGUID="712542fb-f734-449b-8373-864b97981813" CreationDate="2023-07-05T22:20:41.573" UserId="20190" Text="so I'm working on a game engine.&#xD;&#xA;It's partially python and c++.&#xD;&#xA;&#xD;&#xA;One part that is currently a pain point is setting the uniforms for shaders.&#xD;&#xA;Currently I have to define a behavior for all 50+ methods used for setting the uniforms **glUniform{1,2,3,4}{uifd}{v}**&#xD;&#xA;&#xD;&#xA;Is there a single method that I could just call, give it some memory, and tell it, this is a *\&lt;inset type here&gt;* at this location and it repeats this many times?&#xD;&#xA;&#xD;&#xA;#### My motivation:&#xD;&#xA;These uniforms usually come from the &quot;mesh object&quot;, (containing single values, bones, textures, etc.) or they come from &quot;shader object&quot; where they're set per shader, (like light position, camera orientation etc.)&#xD;&#xA;&#xD;&#xA;So setting all of it programmatically, instead of having to deal with multiple different methods is preferable." ContentLicense="CC BY-SA 4.0" />
  <row Id="41136" PostHistoryTypeId="1" PostId="13576" RevisionGUID="712542fb-f734-449b-8373-864b97981813" CreationDate="2023-07-05T22:20:41.573" UserId="20190" Text="is there an universal way to set a uniform?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41137" PostHistoryTypeId="3" PostId="13576" RevisionGUID="712542fb-f734-449b-8373-864b97981813" CreationDate="2023-07-05T22:20:41.573" UserId="20190" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41138" PostHistoryTypeId="2" PostId="13577" RevisionGUID="b1d914e5-a70f-48ef-8348-09bb0490e2c0" CreationDate="2023-07-06T03:14:27.453" UserId="19537" Text="The increased radiance during sampling is known by:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_s = L_e + \sigma_s \int p(w, w')f_p(w, w')dw'&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The latter part, which accounts for in-scattering radiance bears a $\sigma_s$ in it. &#xD;&#xA;- The first question is, how to explain the physical functionality of $\sigma_s$ in a simple way? I think taking a look at the original differential form for volumetric RTE will be clearer? Since differential RTE clearly indicates &quot;increase&quot; and &quot;decrease&quot; of radiance.&#xD;&#xA;&#xD;&#xA;- The second problem is, since **I can use (almost) any sampling strategy I want for importance sampling**, and for the original exponential sampling, I can derive (during mfp-sampling):&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{p(x)} = \frac{\sigma_s e^{-\sigma_t d}}{\sigma_t e^{-\sigma_t d}} = \text{scattering albedo } \alpha&#xD;&#xA;$$&#xD;&#xA;Therefore, for high albedo medium, multiple scattering actually won't introduce much energy loss since it would only be $\alpha^{n-1}$ (n is the number of scattering events). **However**, we I choose to use other sampling distribution instead of exponential, the estimator tends to **yield small values**, since $p(x)$ no-longer cancels the exponent in $f(x)$, therefore I can't get $\alpha$ (which should be close to 1 for high-scattering medium). In the extreme case, where I use deterministic method to add a mfp sample, for example:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qNfua.png&#xD;&#xA;It seems that without $p(x)$ as the denominator, placing a deterministic sample here is **increasing** the radiance by a large amount (if distance is small enough and $\sigma_s$ is large). **So why would this happend?**. And, **is this correct that whenever a scattering event occurs (no matter stochatic / deterministic sampling), we should multiply a $\sigma_s$** somewhere during computation?&#xD;&#xA;- The third confusion of mine: deterministically placing a sample (like, during distance sampling) pdf is 1 (right?), but sampling in a extremely small interval results in a huge pdf value (for example, uniform distribution will have $1 / (\max - \min)$ which is pretty big), so what happened here?&#xD;&#xA;Any help will be appreciated!" ContentLicense="CC BY-SA 4.0" />
  <row Id="41140" PostHistoryTypeId="1" PostId="13577" RevisionGUID="b1d914e5-a70f-48ef-8348-09bb0490e2c0" CreationDate="2023-07-06T03:14:27.453" UserId="19537" Text="How to properly use scattering coefficient during volumetric path tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41141" PostHistoryTypeId="3" PostId="13577" RevisionGUID="b1d914e5-a70f-48ef-8348-09bb0490e2c0" CreationDate="2023-07-06T03:14:27.453" UserId="19537" Text="|mathematics|sampling|importance-sampling|volumetric-scattering|volume-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41142" PostHistoryTypeId="2" PostId="13578" RevisionGUID="2a90c384-032f-4af5-8ba9-871d809d9bc7" CreationDate="2023-07-06T14:54:25.087" UserId="445" Text="You should use [uniform buffer objects](https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object) instead of individual `glUniform` calls. Then the uniforms are all stored in one block of memory which you tell OpenGL about. The shader and the code that fills the buffer with data have to agree on what the memory layout is, but the code that selects the UBO while drawing doesn't need to care.&#xD;&#xA;&#xD;&#xA;You will likely also be able to have one UBO per “mesh object” and one per “shader object”, so that each combination can be activated just with two bindings." ContentLicense="CC BY-SA 4.0" />
  <row Id="41144" PostHistoryTypeId="2" PostId="13579" RevisionGUID="416036b9-f500-4c6d-a622-9f6629de24c1" CreationDate="2023-07-06T18:42:02.957" UserId="20193" Text="I am writing a polygon rasterization renderer. Some meshes render flawlessly, but some produce strange artefacts in the depth buffer. These artefacts do not just appear when I save the depth buffer for inspection but are clearly part of the buffer itself during runtime, as you can see it affecting the result of rendering very clearly. Does this look like some familiar problem? Do you have advice on how to diagnose this issue if not? I have attached two images, one of the render result and one of the saved depth buffer. I have also included a snippet of my code that handles depth testing:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/URthK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wlf5B.png&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;if(mat_min(zs) &lt; 0.0 || mat_max(zs) &gt; 1.0)&#xD;&#xA;{ return; }&#xD;&#xA;// Exit if vertex is outside of depth range ^&#xD;&#xA;...&#xD;&#xA;double zpc_inv = bary.data[0] / zcs.data[0] + bary.data[1] / zcs.data[1] + bary.data[2] / zcs.data[2];&#xD;&#xA;double zpc = 1.0 / zpc_inv;&#xD;&#xA;double upc = bary.data[1] * zpc / zcs.data[1];&#xD;&#xA;double vpc = bary.data[2] * zpc / zcs.data[2];&#xD;&#xA;double wpc = 1.0 - upc - vpc;&#xD;&#xA;bary = mat_row(3, wpc, upc, vpc);&#xD;&#xA;// Calculate new perspective-correct barycentric coordinates ^&#xD;&#xA;double z = mat_lincomb(zs, bary).data[0];&#xD;&#xA;double buf_z = depthbuf[y * frame-&gt;width + x];&#xD;&#xA;// Calculate depth from said coords ^&#xD;&#xA;if(z &gt; buf_z)&#xD;&#xA;{&#xD;&#xA;    ...&#xD;&#xA;    depthbuf[y * frame-&gt;width + x] = z;&#xD;&#xA;}&#xD;&#xA;// Draw if depth is suitable ^&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41146" PostHistoryTypeId="1" PostId="13579" RevisionGUID="416036b9-f500-4c6d-a622-9f6629de24c1" CreationDate="2023-07-06T18:42:02.957" UserId="20193" Text="Patchy patterned artefacting in depth buffer" ContentLicense="CC BY-SA 4.0" />
  <row Id="41147" PostHistoryTypeId="3" PostId="13579" RevisionGUID="416036b9-f500-4c6d-a622-9f6629de24c1" CreationDate="2023-07-06T18:42:02.957" UserId="20193" Text="|3d|rasterizer|depth-map|bitmap-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41154" PostHistoryTypeId="5" PostId="13577" RevisionGUID="a4b516fb-0388-4c7f-8e5e-7e2932517fad" CreationDate="2023-07-08T02:32:18.857" UserId="19537" Comment="added 2 characters in body" Text="The increased radiance during sampling is known by:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_s = L_e + \sigma_s \int p(w, w')f_p(w, w')dw'&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The latter part, which accounts for in-scattering radiance bears a $\sigma_s$ in it. &#xD;&#xA;- The first question is, how to explain the physical functionality of $\sigma_s$ in a simple way? I think taking a look at the original differential form for volumetric RTE will be clearer? Since differential RTE clearly indicates &quot;increase&quot; and &quot;decrease&quot; of radiance.&#xD;&#xA;&#xD;&#xA;- The second problem is, since **I can use (almost) any sampling strategy I want for importance sampling**, and for the original exponential sampling, I can derive (during mfp-sampling):&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{p(x)} = \frac{\sigma_s e^{-\sigma_t d}}{\sigma_t e^{-\sigma_t d}} = \text{scattering albedo } \alpha&#xD;&#xA;$$&#xD;&#xA;Therefore, for high albedo medium, multiple scattering actually won't introduce much energy loss since it would only be $\alpha^{n-1}$ (n is the number of scattering events). **However**, when I choose to use other sampling distribution instead of exponential, the estimator tends to **yield small values**, since $p(x)$ no-longer cancels the exponent in $f(x)$, therefore I can't get $\alpha$ (which should be close to 1 for high-scattering medium). In the extreme case, where I use deterministic method to add a mfp sample, for example:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qNfua.png&#xD;&#xA;It seems that without $p(x)$ as the denominator, placing a deterministic sample here is **increasing** the radiance by a large amount (if distance is small enough and $\sigma_s$ is large). **So why would this happend?**. And, **is this correct that whenever a scattering event occurs (no matter stochatic / deterministic sampling), we should multiply a $\sigma_s$** somewhere during computation?&#xD;&#xA;- The third confusion of mine: deterministically placing a sample (like, during distance sampling) pdf is 1 (right?), but sampling in a extremely small interval results in a huge pdf value (for example, uniform distribution will have $1 / (\max - \min)$ which is pretty big), so what happened here?&#xD;&#xA;Any help will be appreciated!" ContentLicense="CC BY-SA 4.0" />
  <row Id="41157" PostHistoryTypeId="2" PostId="13581" RevisionGUID="c49b6646-6701-45c8-b07e-8c4f05ba4e46" CreationDate="2023-07-09T13:20:37.503" UserId="19537" Text="I actually can't get enough information from the description and the variable names are... confusing to me. Also, I can't recall formulae similar to those in your question, so I can only make a guess, as I think it actually looks like ray-intersection op in ray tracing. I am not sure whether it would be the case of yours.&#xD;&#xA;&#xD;&#xA;Could it be something wrong with round off error? I know normally if it is so, the artifacts can be seen almost everywhere, but I do remember to have seen some rendering results partially spattered with round-off artifacts. It is basically like the following figures. I notice that there seems to be regular stripes in the artifacts, which looks familiar to me, as I've encountered similar artifacts in my own renderer:&#xD;&#xA;&#xD;&#xA;|Without roundoff protection|With roundoff protection|&#xD;&#xA;|---|---|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|&#xD;&#xA;&#xD;&#xA;I see that in your code:&#xD;&#xA;```c++&#xD;&#xA;if(z &gt; buf_z)&#xD;&#xA;{&#xD;&#xA;    ...&#xD;&#xA;    depthbuf[y * frame-&gt;width + x] = z;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;which seems to lack a bound check (necessary?) and a round-off error protection like this:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;for mesh_idx in range(start_id, tri_num + start_id):&#xD;&#xA;    p1 = self.prims[mesh_idx, 0]&#xD;&#xA;    v1 = self.precom_vec[mesh_idx, 0]&#xD;&#xA;    v2 = self.precom_vec[mesh_idx, 1]&#xD;&#xA;    mat = ti.Matrix.cols([v1, v2, -ray]).inverse()&#xD;&#xA;    u, v, t = mat @ (start_p - p1)&#xD;&#xA;    if u &gt;= 0 and v &gt;= 0 and u + v &lt;= 1.0:&#xD;&#xA;        if t &gt; 1e-4 and t &lt; min_depth:      # round-off error protection, a small value like 1e-4 here&#xD;&#xA;            min_depth = t&#xD;&#xA;``` &#xD;&#xA;&#xD;&#xA;For the code above, if I replace 1e-4 with 0 then there will be artifacts. So I think maybe you can try adding round-off error protection in your code.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/roC9G.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/1agt6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41161" PostHistoryTypeId="2" PostId="13583" RevisionGUID="bd495d5f-58d0-4a4f-bb41-42e13b3a6160" CreationDate="2023-07-09T23:45:02.070" UserId="11058" Text="I'm working on a simple 3d modeling application. I'm using 1 meter as unit of measurement. When working with small triangles where an edge length is around 0.01 units (1 centimeter) or less, I started to encounter issues with floating point precision. More specifically with the algorithm for calculating barycentric coordinates (which is used in ray triangle intersection). In rough terms the algorithm uses dot products of edge vectors and then multiplies the said dot products with each other, which results in very small values.&#xD;&#xA;&#xD;&#xA;From what I understand it seems Maya and some other modeling software use 1 cm as measurement unit. However not at all it seems, Blender for example uses 1 m as measurement unit.&#xD;&#xA;&#xD;&#xA;Would it make sense to switch to 1 cm to avoid these precision issues?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41163" PostHistoryTypeId="1" PostId="13583" RevisionGUID="bd495d5f-58d0-4a4f-bb41-42e13b3a6160" CreationDate="2023-07-09T23:45:02.070" UserId="11058" Text="Floating point precision in 3d modeling software" ContentLicense="CC BY-SA 4.0" />
  <row Id="41164" PostHistoryTypeId="3" PostId="13583" RevisionGUID="bd495d5f-58d0-4a4f-bb41-42e13b3a6160" CreationDate="2023-07-09T23:45:02.070" UserId="11058" Text="|mesh|model|float|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41165" PostHistoryTypeId="5" PostId="13583" RevisionGUID="508a87fa-1d3f-4ed2-a232-a67d5cf1f2c3" CreationDate="2023-07-09T23:50:10.177" UserId="11058" Comment="added 136 characters in body" Text="I'm working on a simple 3d modeling application. I'm using 1 meter as unit of measurement. When working with small triangles where an edge length is around 0.01 units (1 centimeter) or less, I started to encounter issues with floating point precision. More specifically with the algorithm for calculating barycentric coordinates (which is used in ray triangle intersection). In rough terms the algorithm uses dot products of edge vectors and then multiplies the said dot products with each other, which results in very small values.&#xD;&#xA;&#xD;&#xA;From what I understand it seems Maya and some other modeling software use 1 cm as measurement unit. However not at all it seems, Blender for example uses 1 m as measurement unit.&#xD;&#xA;&#xD;&#xA;Would it make sense to switch to 1 cm to avoid these precision issues? I would still get the precision issues at around 0.01 units, but this would then correspond to 0.1 mm which is more then enough for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="41167" PostHistoryTypeId="5" PostId="13583" RevisionGUID="43fb10a8-8911-4c2c-9627-94044781a1e6" CreationDate="2023-07-09T23:56:20.090" UserId="11058" Comment="added 6 characters in body" Text="I'm working on a simple 3d modeling application. I'm using 1 meter as unit of measurement. When working with small triangles where an edge length is around 0.01 units (1 centimeter) or less, I started to encounter issues with floating point precision. More specifically with the algorithm for calculating barycentric coordinates (which is used in ray triangle intersection). In rough terms the algorithm calculates dot products of edge vectors and then multiplies the said dot products with each other, which results in very small values.&#xD;&#xA;&#xD;&#xA;From what I understand it seems Maya and some other modeling software use 1 cm as measurement unit. However not at all it seems, Blender for example uses 1 m as measurement unit (?)&#xD;&#xA;&#xD;&#xA;Would it make sense to switch to 1 cm to avoid these precision issues? I would still get the precision issues at around 0.01 units, but this would then correspond to 0.1 mm which is more then enough for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="41168" PostHistoryTypeId="5" PostId="13583" RevisionGUID="674fd9e3-1395-4b0a-90bd-b7f1f990697f" CreationDate="2023-07-10T00:01:52.017" UserId="11058" Comment="[Edit removed during grace period]; deleted 9 characters in body" Text="I'm working on a simple 3d modeling application. I'm using 1 meter as unit of measurement. When working with small triangles where an edge length is around 0.01 units (1 centimeter) or less, I started to encounter issues with floating point precision. More specifically with the algorithm for calculating barycentric coordinates (which is used in ray triangle intersection). In rough terms the algorithm calculates dot products of edge vectors and then multiplies the said dot products with each other, which results in very small values.&#xD;&#xA;&#xD;&#xA;From what I understand Maya and some other modeling software use 1 cm as measurement unit. However not at all it seems, Blender for example uses 1 m as measurement unit (?)&#xD;&#xA;&#xD;&#xA;Would it make sense to switch to 1 cm to avoid these precision issues? I would still get the precision issues at around 0.01 units, but this would then correspond to 0.1 mm which is more then enough for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="41170" PostHistoryTypeId="5" PostId="13583" RevisionGUID="9c1ce443-003e-4744-b65a-bd8b213d06a5" CreationDate="2023-07-10T02:04:02.650" UserId="11058" Comment="edited body" Text="I'm working on a simple 3d modeling application. I'm using 1 meter as unit of measurement. When working with small triangles where an edge length is around 1 centimeter (0.01 units) or less, I started to encounter issues with floating point precision. More specifically with the algorithm for calculating barycentric coordinates (which is used in ray triangle intersection). In rough terms the algorithm calculates dot products of edge vectors and then multiplies the said dot products with each other, which results in very small values.&#xD;&#xA;&#xD;&#xA;From what I understand Maya and some other modeling software use 1 cm as measurement unit. However not all it seems, Blender for example uses 1 m as measurement unit (?)&#xD;&#xA;&#xD;&#xA;Would it make sense to switch to 1 cm to avoid these precision issues? I would still get the precision issues at around 0.01 units, but this would then correspond to 0.1 mm which is more then enough for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="41172" PostHistoryTypeId="50" PostId="10248" RevisionGUID="6167fd72-53c6-4f27-82db-98d3bedec729" CreationDate="2023-07-10T14:01:40.183" UserId="-1" />
  <row Id="41173" PostHistoryTypeId="5" PostId="13583" RevisionGUID="2f0540ca-b9cb-41b0-8732-9283cbaf4554" CreationDate="2023-07-10T16:15:10.393" UserId="11058" Comment="added 36 characters in body" Text="I'm working on a simple 3d modeling application. I'm using 1 meter as unit of measurement. When working with small triangles where an edge length is around 1 centimeter (0.01 units) or less, I started to encounter issues with floating point precision (I'm using 4 bytes float data type). More specifically with the algorithm for calculating barycentric coordinates (which is used in ray triangle intersection). In rough terms the algorithm calculates dot products of edge vectors and then multiplies the said dot products with each other, which results in very small values.&#xD;&#xA;&#xD;&#xA;From what I understand Maya and some other modeling software use 1 cm as measurement unit. However not all it seems, Blender for example uses 1 m as measurement unit (?)&#xD;&#xA;&#xD;&#xA;Would it make sense to switch to 1 cm to avoid these precision issues? I would still get the precision issues at around 0.01 units, but this would then correspond to 0.1 mm which is more then enough for me." ContentLicense="CC BY-SA 4.0" />
  <row Id="41174" PostHistoryTypeId="5" PostId="13579" RevisionGUID="edcba80f-6b56-4725-bc54-abf4fa88f015" CreationDate="2023-07-10T16:22:56.700" UserId="20193" Comment="added 392 characters in body" Text="I am writing a polygon rasterization renderer. Some meshes render flawlessly, but some produce strange artefacts in the depth buffer. These artefacts do not just appear when I save the depth buffer for inspection but are clearly part of the buffer itself during runtime, as you can see it affecting the result of rendering very clearly. Does this look like some familiar problem? Do you have advice on how to diagnose this issue if not? I have attached two images, one of the render result and one of the saved depth buffer. I have also included a snippet of my code that handles depth testing:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/URthK.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/wlf5B.png&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;if(mat_min(zs) &lt; 0.0 || mat_max(zs) &gt; 1.0)&#xD;&#xA;{ return; }&#xD;&#xA;// Exit if vertex is outside of depth range ^&#xD;&#xA;...&#xD;&#xA;double zpc_inv = bary.data[0] / zcs.data[0] + bary.data[1] / zcs.data[1] + bary.data[2] / zcs.data[2];&#xD;&#xA;double zpc = 1.0 / zpc_inv;&#xD;&#xA;double upc = bary.data[1] * zpc / zcs.data[1];&#xD;&#xA;double vpc = bary.data[2] * zpc / zcs.data[2];&#xD;&#xA;double wpc = 1.0 - upc - vpc;&#xD;&#xA;bary = mat_row(3, wpc, upc, vpc);&#xD;&#xA;// Calculate new perspective-correct barycentric coordinates ^&#xD;&#xA;double z = mat_lincomb(zs, bary).data[0];&#xD;&#xA;double buf_z = depthbuf[y * frame-&gt;width + x];&#xD;&#xA;// Calculate depth from said coords ^&#xD;&#xA;if(z &gt; buf_z)&#xD;&#xA;{&#xD;&#xA;    ...&#xD;&#xA;    depthbuf[y * frame-&gt;width + x] = z;&#xD;&#xA;}&#xD;&#xA;// Draw if depth is suitable ^&#xD;&#xA;```&#xD;&#xA;EDIT: Based on an answer given here, I decided to do some experimentation with bounds. The artefacting is somehow caused by pixels which should have invalid bounds passing bounds checks. By changins some `&lt;=` and `&gt;=` into `&lt;` and `&gt;`, I tightened the bounds on what is considered a &quot;valid&quot; barycentric coord for shading and it helped significantly but did not eliminate the problem entirely.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41179" PostHistoryTypeId="50" PostId="12259" RevisionGUID="8448cc8d-40d4-4562-8fbf-58fa7c382693" CreationDate="2023-07-11T17:08:01.010" UserId="-1" />
  <row Id="41180" PostHistoryTypeId="2" PostId="13585" RevisionGUID="1347b24e-e038-4eea-bf6d-c19a19b01669" CreationDate="2023-07-12T12:01:37.623" UserId="7008" Text="I have just activated the Vulkan [Best Practices Validation][1] and due to that I get the following warning:&#xD;&#xA;&#xD;&#xA;&gt; Validation Layer(WARNING):      Validation Warning: [ UNASSIGNED-BestPractices-vkCreateInstance-specialuse-extension-debugging ] Object 0: VK_NULL_HANDLE, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x822806fa | CreateInstance(): Attempting to enable extension VK_EXT_debug_utils, but this extension is intended to support use by applications when debugging and it is strongly recommended that it be otherwise avoided.&#xD;&#xA;&#xD;&#xA;Naturally, I don't need to see this in a debug build, so I'd like to filter this message out in debug builds. [According to the docs][2] one can use the message id filter with the `vk_layer_settings.txt`:&#xD;&#xA;&#xD;&#xA;&gt; By default, the settings file must be named `vk_layer_settings.txt` and reside in the working directory of the targeted application.&#xD;&#xA;&#xD;&#xA;I have checked the current directory with `std::filesystem::current_path()` (pointing to `/my/project/dir/build/src/`) and put the layer settings file there, and I have also tried to put it next to the debug .exe file (at `/my/project/dir/build/src/Debug/MyProject.exe`).&#xD;&#xA;&#xD;&#xA;The contents of my file are:&#xD;&#xA;&#xD;&#xA;    khronos_validation-message_id_filter = &quot;UNASSIGNED-BestPractices-vkCreateInstance-specialuse-extension-debugging&quot;&#xD;&#xA;&#xD;&#xA;I have tried to use the id instead of the message name:&#xD;&#xA;&#xD;&#xA;    khronos_validation-message_id_filter = &quot;0x822806fa&quot;&#xD;&#xA;&#xD;&#xA;Neither of the two has worked at either of the locations. How do I correctly use this filter then?&#xD;&#xA;&#xD;&#xA;If this is in any way important, the project is build with CMake with the main file residing at `/my/project/dir/CMakeLists.txt` and the build done through&#xD;&#xA;&#xD;&#xA;    cd /my/project/dir/build&#xD;&#xA;    cmake ..&#xD;&#xA;&#xD;&#xA;And finally compiling the solution via Visual Studio 2022&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://vulkan.lunarg.com/doc/view/1.2.189.0/linux/best_practices.html&#xD;&#xA;  [2]: https://vulkan.lunarg.com/doc/view/1.2.189.0/windows/layer_configuration.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="41182" PostHistoryTypeId="1" PostId="13585" RevisionGUID="1347b24e-e038-4eea-bf6d-c19a19b01669" CreationDate="2023-07-12T12:01:37.623" UserId="7008" Text="How to set Vulkan Validation Layer filter via the vk_layer_settings.txt?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41183" PostHistoryTypeId="3" PostId="13585" RevisionGUID="1347b24e-e038-4eea-bf6d-c19a19b01669" CreationDate="2023-07-12T12:01:37.623" UserId="7008" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41184" PostHistoryTypeId="2" PostId="13586" RevisionGUID="e53d96b7-848d-4c67-86c6-a477e4928be6" CreationDate="2023-07-12T12:11:42.290" UserId="7008" Text="Looks like I just had a typo in my file.&#xD;&#xA;&#xD;&#xA;The file had to be at `/my/project/dir/build/src` (i.e. the place I got from `std::filesystem::current_path()`) and the content now is &#xD;&#xA;&#xD;&#xA;    khronos_validation.message_id_filter = &quot;UNASSIGNED-BestPractices-vkCreateInstance-specialuse-extension-debugging&quot;&#xD;&#xA;&#xD;&#xA;(in my question it was `...validation_message...` instead of `...validation.message...`)" ContentLicense="CC BY-SA 4.0" />
  <row Id="41193" PostHistoryTypeId="2" PostId="13589" RevisionGUID="0179fcc5-c069-4c99-8798-a70afb505d94" CreationDate="2023-07-13T22:52:25.420" UserId="20224" Text="Before we start, I have to warn yall, this program was written in VEX. Which is a programming language for Houdini. So it is a language within a 3D software. Its not really meant for this sort of stuff, but is Python ish from what people tell me. So like, prepare for some &quot;interesting&quot; code.&#xD;&#xA;&#xD;&#xA;So i have been working on a Kerr Render Engine to draw a rotating black hole, following the equations of General Relativity, well just the Kerr Metric really. In an afford to make the renders more spicy I decided to include a Volumetric disk. Which, in this case, fairly intuitive because to draw the black hole we need to step through the scene anyways. &#xD;&#xA;&#xD;&#xA;As a model for the volumetrics, I followed [this][1] tut. &#xD;&#xA;&#xD;&#xA;On its surface, it all works more or less; [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Note, the light source is a ring on the XZ plane. Now, this render is done at a focal length of 28mm. But when I increase it to 50mm, this happens;&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you can see, the render gets darker. Even though precisely nothing about the volumetric setup changed. (Yes this is a screenshot D:). Also the camera position is not a total match, but the lose in light is not duo to that. If we go back to 28mm but put the Camera closer to the BH this happens; &#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;I am at a bit of a lose here. I do however have 2 theories.&#xD;&#xA;&#xD;&#xA;**Theory 1 - Its Einstein's fault**&#xD;&#xA;&#xD;&#xA;The way the engine works is by solving a set of 4 equations which describe the curved spacetime of the Kerr Metric (XYZ and Time... well r, theta, phi and Time because spherical hyperbolic coordinates ftw). These equations are solved 4 times (4th order integration scheme) to compute where a ray will go next. The step size of this is a function of distance to the Event Horizon and approaches 0 as the distance to the EH approaches 0. &#xD;&#xA;&#xD;&#xA;The theory goes that as the focal length gets longer and longer, more and more rays dive directly into the EH and don't have much chance to swirl around the black hole and get bright.&#xD;&#xA;&#xD;&#xA;Now, I don't really buy this theory because of this. I can make the disk 2D and add a &quot;light value&quot; each time a ray crosses the disk. So the more often a ray passes through the disk, the brighter it is. If I change the focal length with this setup, the brightness does not change. Which, should make sense since the physics do not change depending on the focal length.&#xD;&#xA;&#xD;&#xA;But I think considering the different physical scenarios is important.&#xD;&#xA;&#xD;&#xA;**Theory 2 - I done f´ed up**&#xD;&#xA;&#xD;&#xA;The much more likely answer is that I made a mistake in the volumetric part of the code. So, lets take a look at the relevant parts. I will use pseudo code for some parts that relate to the General Relativity stuff.&#xD;&#xA;&#xD;&#xA;From the renders, we know the issue has to be with the Focal length. The physical position of the Camera does not have an impact... aside from the render time (help me this has to run on the CPU and it takes 15min a frame).&#xD;&#xA;&#xD;&#xA;```vector rayDir = ((fragCoord + camPos) - rayOrig) * (1.0/nearPlane);```&#xD;&#xA;&#xD;&#xA;rayDir is the direction a ray will go and is used to calculate the 4D position for the equations. fragCoords is the 2D position of the point / pixel, camPos is the camera position in 3D space. The (1.0/nearPlane) is related to the near and far render plane.&#xD;&#xA;&#xD;&#xA;Now, here is the main render loop&#xD;&#xA;&#xD;&#xA;    for(int j = 0; j &lt; superSamples; j++) { &lt;- Super Sample loop for Anti Aliasing&#xD;&#xA;     &#xD;&#xA;     //Setup the Camera with a random offset to the Position and rayDir&#xD;&#xA;     //Set the Volume settings (Same for each loop)&#xD;&#xA;     //Set Singularity settings (Same for each loop)&#xD;&#xA;     //Covert XYZ coordinates into Hyperbolic Spherical Space&#xD;&#xA;     //Create vec4 to feed into GR equations&#xD;&#xA;     &#xD;&#xA;     for(int i = 0; i &lt; maxStep; i++) {&#xD;&#xA;      //Axis conditions, for example&#xD;&#xA;      if(length(rayOrig) &lt; (1+sqrt(1-pow(abs(spin),2)))*1.25) {&#xD;&#xA;       break;&#xD;&#xA;      }&#xD;&#xA;This checks if the rayOrig (so the 3D position of a ray) is inside the Event Horizon. There are other checks done before this which change the step Size, like;&#xD;&#xA;&#xD;&#xA;      if(abs(rayOrig.z) &lt; 0.2 &amp;&amp; length(rayOrig) &lt; 3) {&#xD;&#xA;       stepSize = 0.01;&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;This lowers the step size if a ray is close to the Z axis. This is done because the spherical coordinates have a mathematical singularity along the Z axis. If this is not done, &#xD;&#xA;the renders get huge spikes along the Z Axis&#xD;&#xA;&#xD;&#xA;      if(ray is inside Disks bounding box) {&#xD;&#xA;       float densityDistance = distance(lastOrig,rayOrig)&#xD;&#xA;&#xD;&#xA;&quot;densityDistance&quot; is the physical distance between the current ray position, and the one in the last step.&#xD;&#xA;&#xD;&#xA;       float jitter = nrandom();&#xD;&#xA;       jitter = fit(jitter,0,1,-densityDistance,densityDistance);&#xD;&#xA;       vector sampleOrig = lastOrig + (rayDir*jitter);&#xD;&#xA;&#xD;&#xA;       float density = getLocalDensity(sampleOrig)&#xD;&#xA;       float sampleAttenuation = exp(-densityDistance * density * sigma_t);&#xD;&#xA;       transparency *= sampleAttenuation;&#xD;&#xA;&#xD;&#xA;       if(density &gt; 0) {&#xD;&#xA;        vector lightDir = normalize(set(0,1,0)-sampleOrig);&#xD;&#xA;        if(sampleOrig.y &lt; 0) {&#xD;&#xA;         lightDir = normalize(set(0,-1,0-sampleOrig);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        float lightDist = distance(sampleOrig,lightDir) - diskSize.y;&#xD;&#xA;        float tau = getInScaterEvent(lightDist,sampleOrig,lightDir);&#xD;&#xA;        float lightRayAttenuation = exp(-tau * sigma_t);&#xD;&#xA;        float inverseSquare = pow(1.0 / length(sampleOrig),2);&#xD;&#xA;&#xD;&#xA;        result += lightCol * inverseSquare * lightRayAttenuation * (sigma_s/sigma_t) * transparency * stepSize * density;&#xD;&#xA;&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;       superSampleCol += result;&#xD;&#xA;&#xD;&#xA;      }&#xD;&#xA;        &#xD;&#xA;      //March ray in Curved space time&#xD;&#xA;&#xD;&#xA;     }&#xD;&#xA;    }&#xD;&#xA;    Col = superSampleCol / superSamples;&#xD;&#xA;&#xD;&#xA;Now, there are two functions we also need to consider. getLocalDensity and getInScatterEvent. I can add getDensity, but that function only returns a value. It generates the 3D Noise of the disk and tells you the density and the input position.&#xD;&#xA;&#xD;&#xA;    function float getInScatterEvent(float lightDist; vector lightSampleOrig; vector lightSampleDir) {&#xD;&#xA;    float temp = 0, maxDepth = lightDist, currentDepth = 0, t = 0, lightStep = 0;&#xD;&#xA;&#xD;&#xA;    while(currentDepth &lt; maxDepth) {&#xD;&#xA;     vector lightOrig = lightSampleOrig + (lightSampleDir*t*lightStep);&#xD;&#xA;     float jitter = nrandom();&#xD;&#xA;     jitter = fit(jitter,0,1,-lightStep,lightStep);&#xD;&#xA;     &#xD;&#xA;     float sampleDensity = getLocalDensity(lightOrig + (lightSampleDir * jitter));&#xD;&#xA;     lightStep = exp(-sampleDensity);&#xD;&#xA;&#xD;&#xA;     if(lightStep &gt; 0.1) {&#xD;&#xA;      lightStep = 0.1;&#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;     temp += sampleDensity * lightStep;&#xD;&#xA;     currentDepth += lightStep;&#xD;&#xA;     t++;&#xD;&#xA;    }&#xD;&#xA;    return temp;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;And this is where i struggle to see whats wrong. Non of the Volume computations care about the focal length. The only thing i can think of is the fact the rayDir is not normalized. It cant be because of the assumptions made in the GR math. But it shouldnt matter, because the rayDir gets normalized after the first step because then the math changes a bit.&#xD;&#xA;&#xD;&#xA;**Now, i can understand that all of this is a bit arcane so [here][5] is the full program.** &#xD;&#xA;&#xD;&#xA;We know that the issue has to, in some capacity, relate to the focal length. But literally the only point it comes up is here; &#xD;&#xA;&#xD;&#xA;    float FocalLength = 28;&#xD;&#xA;    vector fragCoord = (v@P*nearPlane); &#xD;&#xA;&#xD;&#xA;&quot;v@P&quot; is the position of each ray in 2D space&#xD;&#xA;&#xD;&#xA;    camPos = set(0.5,9,56);&#xD;&#xA;    rayOrig = set(0,0,(FocalLength*nearPlane) / 1000) + camPos;&#xD;&#xA;    rayDir = ((fragCoord + camPos) - rayOrig) * (1.0/nearPlane);&#xD;&#xA;&#xD;&#xA;So yeah, this is about all i got. I hope this question is not to loaded or incoherent. Just a bit of a frustrating bug xD I hope i provided enough context, if there are any questions left open i am happy to clarify / answer stuff.&#xD;&#xA;&#xD;&#xA;Thanks for reading !&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.scratchapixel.com/lessons/3d-basic-rendering/volume-rendering-for-developers/intro-volume-rendering.html&#xD;&#xA;  [2]: https://i.stack.imgur.com/WjiSP.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/vf71y.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/RU7DC.jpg&#xD;&#xA;  [5]: https://www.dropbox.com/scl/fi/r5uc6ccohjx5t7i8423mk/Program.txt?rlkey=5kxs77r110tugwiz4sqb37reo&amp;dl=0" ContentLicense="CC BY-SA 4.0" />
  <row Id="41195" PostHistoryTypeId="1" PostId="13589" RevisionGUID="0179fcc5-c069-4c99-8798-a70afb505d94" CreationDate="2023-07-13T22:52:25.420" UserId="20224" Text="Volumetric Renders become brighter as the focal length changes" ContentLicense="CC BY-SA 4.0" />
  <row Id="41196" PostHistoryTypeId="3" PostId="13589" RevisionGUID="0179fcc5-c069-4c99-8798-a70afb505d94" CreationDate="2023-07-13T22:52:25.420" UserId="20224" Text="|lighting|raymarching|debugging|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41198" PostHistoryTypeId="50" PostId="12470" RevisionGUID="497a6d00-cefa-4783-90d1-6d7537296a2d" CreationDate="2023-07-15T00:05:30.753" UserId="-1" />
  <row Id="41202" PostHistoryTypeId="50" PostId="13522" RevisionGUID="3344e4ab-425e-4fbd-bd5b-cb1db19565d5" CreationDate="2023-07-15T08:04:20.593" UserId="-1" />
  <row Id="41203" PostHistoryTypeId="2" PostId="13590" RevisionGUID="a70c2ee0-b1e2-4a56-a588-8fd896d8f2bc" CreationDate="2023-07-15T16:08:08.957" UserId="20105" Text="So, I'm attempting to implement a monte carlo path tracer that uses the ggx brdf model. However, I'm rather confused about how to sample the light direction. &#xD;&#xA;I know that theta and phi can be sampled like this:&#xD;&#xA;&#xD;&#xA;$\theta=\arctan\left(\alpha\sqrt\frac{\xi_1}{1-\xi_1}\right)$&#xD;&#xA;&#xD;&#xA;$\phi=2\pi\xi_2$&#xD;&#xA;&#xD;&#xA;But whose coordinates are these? Are they the microfacet normal's (half vector), or are they those of the light direction? &#xD;&#xA;&#xD;&#xA;If they are the coordinates of the light direction, how should they be transformed into the world-space coordinates?&#xD;&#xA;&#xD;&#xA;Also, can I use this $\theta$ directly to calculate the BRDF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41205" PostHistoryTypeId="1" PostId="13590" RevisionGUID="a70c2ee0-b1e2-4a56-a588-8fd896d8f2bc" CreationDate="2023-07-15T16:08:08.957" UserId="20105" Text="Importance sampling in a path tracer" ContentLicense="CC BY-SA 4.0" />
  <row Id="41206" PostHistoryTypeId="3" PostId="13590" RevisionGUID="a70c2ee0-b1e2-4a56-a588-8fd896d8f2bc" CreationDate="2023-07-15T16:08:08.957" UserId="20105" Text="|rendering|pathtracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41207" PostHistoryTypeId="12" PostId="13590" RevisionGUID="72c892b4-b9db-46f9-86ef-542ef069ad2a" CreationDate="2023-07-15T16:19:25.577" UserId="20105" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:20105,&quot;DisplayName&quot;:&quot;RandomPigYT&quot;}],&quot;DeleteType&quot;:1}" />
  <row Id="41208" PostHistoryTypeId="13" PostId="13590" RevisionGUID="3664ef0b-d8f8-470c-a96f-e8a8174d9300" CreationDate="2023-07-15T17:44:47.287" UserId="20105" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:20105,&quot;DisplayName&quot;:&quot;RandomPigYT&quot;}]}" />
  <row Id="41209" PostHistoryTypeId="2" PostId="13591" RevisionGUID="0c63c6e2-783d-4342-851b-939866d379cf" CreationDate="2023-07-16T08:27:04.057" UserId="19537" Text="I think the answer is: neither, since this GGX distribution is **NOT sampling the direction for a ray but a microfacet normal**. According to the paper of [GGX: Microfacet Models for Refraction through Rough Surfaces](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf), this distribution is used to sample the normal direction for the microfacet, which you can think of as sampling a new normal direction **with respect to** the original normal direction (macroscopic). Therefore, the coordinate frame is spanned by the original macroscopic normal, for example, we use the macroscopic normal as local z-axis, then the $\theta$ here is the angle between the newly sampled microfacet normal and the macroscopic normal, as shown in the following figure. &#xD;&#xA;&#xD;&#xA;So, how do you get the direction of the light? First, we get the normal we want just by using GGX, to sample a microfacet normal. Then, maybe we will start to sample surface event like whether we evaluate the diffuse part or the specular part. Take evaluating specular part as an example, now we have a incident direction, a microfacet normal, then we can directly calculate the outgoing direction.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&gt; Also, can I use this θ directly to calculate the BRDF?&#xD;&#xA;&#xD;&#xA;Yes. Sampling an outgoing direction will also require you to calculate the path throughput. This throughput coefficient is calculated using the parameters you've sampled.&#xD;&#xA;&#xD;&#xA;So, in all, sampling a new ray direction is usually pretty local around one specific normal (geometric / shading / sampled microfacet normal), so we will usually set the frame according to the normal. However, this is not the case when you are dealing with medium scattering (phase function). In this case, the sampling is usually done in the frame spanned by original incident ray direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/C9hey.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41211" PostHistoryTypeId="50" PostId="13250" RevisionGUID="a9ac8637-96f9-4f91-8ddc-a5db15281a6d" CreationDate="2023-07-17T10:06:15.727" UserId="-1" />
  <row Id="41212" PostHistoryTypeId="2" PostId="13592" RevisionGUID="ce5d2a61-f320-47a1-8add-f7fd38bb3768" CreationDate="2023-07-17T10:35:52.197" UserId="19678" Text="I am currently reading the [SSAO tutorial on learnopengl][1].&#xD;&#xA;&#xD;&#xA;In it, there is a &quot;kernel&quot; that has the dimension of `64` and contains `vec3`s.&#xD;&#xA;&#xD;&#xA;There is also a `noise` texture that contains the vector rotations across the hemisphere, it's size is `4x4`&#xD;&#xA;&#xD;&#xA;I fail to understand how they work together in regards of the sampling, since in the tutorial there are only 4x4 different random vector rotations, why is the kernel size `64`?&#xD;&#xA;&#xD;&#xA;The tutorial mentions that it wants to give samples closer to the current fragment more weight, wouldnt it then make more sense to store the weight directly in the vector rotations (in the A/W component)?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/Advanced-Lighting/SSAO" ContentLicense="CC BY-SA 4.0" />
  <row Id="41214" PostHistoryTypeId="1" PostId="13592" RevisionGUID="ce5d2a61-f320-47a1-8add-f7fd38bb3768" CreationDate="2023-07-17T10:35:52.197" UserId="19678" Text="What is the &quot;kernel&quot; in learnopengl SSAO tutorial?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41215" PostHistoryTypeId="3" PostId="13592" RevisionGUID="ce5d2a61-f320-47a1-8add-f7fd38bb3768" CreationDate="2023-07-17T10:35:52.197" UserId="19678" Text="|sampling|ssao|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41216" PostHistoryTypeId="2" PostId="13593" RevisionGUID="953df36d-bc69-42a2-a54e-8b530bfe01ea" CreationDate="2023-07-17T12:22:02.010" UserId="20236" Text="I'm currently making a game with [Python][1]'s [Ursina][2] module, and everything runs well, except:&#xD;&#xA;the grass texture (size: 8192x8192px) looks pixelated at big distance (everything inside the red marker). How can I make it look smoother?&#xD;&#xA;&#xD;&#xA;In the screenshot below, I'm standing on a hill and looking down to the grass.&#xD;&#xA;[![Pixelated grass texture from big distance (hill)][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://www.python.org/&#xD;&#xA;  [2]: https://www.ursinaengine.org/&#xD;&#xA;  [3]: https://i.stack.imgur.com/1t6pd.jpg&#xD;&#xA;  [4]: https://en.wikipedia.org/wiki/DirectX_Diagnostic_Tool" ContentLicense="CC BY-SA 4.0" />
  <row Id="41218" PostHistoryTypeId="1" PostId="13593" RevisionGUID="953df36d-bc69-42a2-a54e-8b530bfe01ea" CreationDate="2023-07-17T12:22:02.010" UserId="20236" Text="Game texture looks pixelated at big distance" ContentLicense="CC BY-SA 4.0" />
  <row Id="41219" PostHistoryTypeId="3" PostId="13593" RevisionGUID="953df36d-bc69-42a2-a54e-8b530bfe01ea" CreationDate="2023-07-17T12:22:02.010" UserId="20236" Text="|pixels|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41220" PostHistoryTypeId="2" PostId="13594" RevisionGUID="73ffd734-b298-4b90-80c4-54a55351a2ad" CreationDate="2023-07-17T12:53:59.713" UserId="19537" Text="I think mip-mapping will help. This is the aliasing effect when the sampling frequency is lower than needed. When a large patch of texture projects only to one (or less than one) pixel, things like this could happen. Mip-mapping, to put it simply, can help you select a suitable texture resolution when the texture is viewed from different distance. For example, when viewed far away, we can use a smoother version (low resolution, prefiltered) texture, and otherwise we use a sharp version of texture (high resolution). &#xD;&#xA;&#xD;&#xA;For specific implementations with Ursina, I am not familiar with this lib, but I took a look at the [source code (ursina/texture.py)](https://github.com/pokepetter/ursina/blob/master/ursina/texture.py) of this lib:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;class Texture():&#xD;&#xA;    default_filtering = None      # options: None / 'bilinear' / 'mipmap'&#xD;&#xA;    &quot;&quot;&quot;...&quot;&quot;&quot;&#xD;&#xA;    def __init__(self, value):&#xD;&#xA;        self.filtering = Texture.default_filtering      # None/'bilinear'/'mipmap' default: 'None'&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;I think this means that Ursina supports mip-mapping? You can just turn this on (use `mipmap`) and have a try.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41222" PostHistoryTypeId="2" PostId="13595" RevisionGUID="f1458312-5956-428b-909c-0bf4a9d2040d" CreationDate="2023-07-17T17:14:30.350" UserDisplayName="user1703" Text="Normally, 3D rendering does not work by setting individual pixels but by passing a complete (facettized) geometric model to the rendering engine. This is why addressing a single pixel is not convenient and inefficient.&#xD;&#xA;&#xD;&#xA;If you really want this, better use `SetPixel` :-)&#xD;&#xA;&#xD;&#xA;https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-setpixel&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41224" PostHistoryTypeId="52" PostId="13593" RevisionGUID="b2988267-373c-458e-bd12-58e65afd5688" CreationDate="2023-07-17T20:22:23.753" />
  <row Id="41225" PostHistoryTypeId="2" PostId="13596" RevisionGUID="94c8a2c2-63d9-4fdc-9318-30ca70852d08" CreationDate="2023-07-17T22:01:48.610" UserId="9438" Text="In this context, the 'Kernel' is the set of samples that are used in the 'Screen Space' domain. The name Kernel comes from image kernel (i.e convolution). The kernel contains the sample data that is ultimately transformed into screen space and used to sample against other depth values within an arbitary proximity of the pixel/fragment (the sampling radius). &#xD;&#xA;&#xD;&#xA;&gt; I fail to understand how they work together in regards of the&#xD;&#xA;&gt; sampling, since in the tutorial there are only 4x4 different random&#xD;&#xA;&gt; vector rotations, why is the kernel size 64?&#xD;&#xA;&#xD;&#xA;While the result depends on **both** the samples (in the kernel) and the 'noise' (a single random rotation) applied to ALL the samples (in tangent/view space) at that particular fragment, they **do not** depend on each other in the first place so do not need to be the same size/count.&#xD;&#xA;&#xD;&#xA;You could have 32 samples, and 144 'randoms' in your noise if you wanted, it does not matter. The number of samples in the kernel are what is sampled for each fragment. In this example you gave, each fragement will perform 64 samples, and will be transformed with a 'single' noise/random value at that particular fragment position. The noise size is picked to simply prevent adjacent repitition (banding) and give the impression of a larger distribution of sample randomness wrt to adjacent fragments (although it is infact repeated). &#xD;&#xA;&#xD;&#xA;The values 64 and 16 (4x4) are probably chosen for in this example as they are the happy medium for achieving a decent, natural looking, but fast result. The purpose of SSOA is a cheap, no-CPU approximation of ambient occlusion (shading from local occlusion), **not** done in world space, so there needs to be a balance of realistic looking quality, while remaining easy enough for the GPU. &#xD;&#xA;&#xD;&#xA;If you display the noise texture alone (using the scaling values when querying the texel in the tutorial) i.e&#xD;&#xA;&#xD;&#xA;    const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); // screen = 800x600, N.B '4' x '4' matrix&#xD;&#xA;    frag = texture(texNoise, TexCoords * noiseScale).rgb; &#xD;&#xA;&#xD;&#xA; you would see that it is tiled over the entirety of the screen, with each noise value occupying a single fragment/pixel, but repeated over the screen. &#xD;&#xA;e.g. for a 4x4 noise, the value (pixel colour) is repeated every 4 horizontal pixels, and every 4 vertical pixels. &#xD;&#xA;&#xD;&#xA; This would be the single 'noise' value used to transform all 64 samples at that particular fragment location.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&gt; The tutorial mentions that it wants to give samples closer to the&#xD;&#xA;&gt; current fragment more weight, wouldnt it then make more sense to store&#xD;&#xA;&gt; the weight directly in the vector rotations (in the A/W component)?&#xD;&#xA;&#xD;&#xA; This wouldn't make any sense since the samples are what are weighted, not the random noise, and since each fragment uses a single noise value it would be nothing more than a scalar applied to ALL samples done at that fragment location, which defeats the purpose of 'weighting the samples'.&#xD;&#xA; &#xD;&#xA; Also note, that any sample in the hemisphere is the same distance irrelevant of any rotation applied, and so this 'weighting' is in fact constant (since the samples are constant in the firstplace) so do not need evaluating each time they are used (waste of GPU cycles). &#xD;&#xA;&#xD;&#xA;This is done by CPU when populating the buffer (`lerp` in the tutorial code) by pushing the 'uniformly' distributed samples closer to the hempshere souce. i.e more samples closer to the fragment position (when transformed) as these are likely to add more 'effect' to close proximity occlusions. This is why the shading falls off quite fast, and is a lot darker in compacted corners.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="41227" PostHistoryTypeId="5" PostId="13596" RevisionGUID="77070b2c-5db4-40ae-aae6-66a5fb6e84ab" CreationDate="2023-07-17T22:08:23.923" UserId="9438" Comment="edited body" Text="In this context, the 'Kernel' is the set of samples that are used in the 'Screen Space' domain. The name Kernel comes from image kernel (i.e convolution). The kernel contains the sample data that is ultimately transformed into screen space and used to sample against other depth values within an arbitary proximity of the pixel/fragment (the sampling radius). &#xD;&#xA;&#xD;&#xA;&gt; I fail to understand how they work together in regards of the&#xD;&#xA;&gt; sampling, since in the tutorial there are only 4x4 different random&#xD;&#xA;&gt; vector rotations, why is the kernel size 64?&#xD;&#xA;&#xD;&#xA;While the result depends on **both** the samples (in the kernel) and the 'noise' (a single random rotation) applied to ALL the samples (in tangent/view space) at that particular fragment, they **do not** depend on each other in the first place so do not need to be the same size/count.&#xD;&#xA;&#xD;&#xA;You could have 32 samples, and 144 'randoms' in your noise if you wanted, it does not matter. The number of samples in the kernel are what is sampled for each fragment. In this example you gave, each fragment will perform 64 samples, and will be transformed with a 'single' noise/random jitter at that particular fragment position. The noise size is picked to simply prevent adjacent repitition (banding) and give the impression of a larger distribution of sample randomness wrt to adjacent fragments (although it is infact repeated). &#xD;&#xA;&#xD;&#xA;The values 64 and 16 (4x4) are probably chosen for in this example as they are probably the happy medium for achieving a decent, natural looking, but fast result in this scenario. The purpose of SSOA is a cheap, no-CPU approximation of ambient occlusion (shading from local occlusion), **not** done in world space, so there needs to be a balance of realistic looking quality, while remaining easy enough for the GPU to retain a decent FPS. &#xD;&#xA;&#xD;&#xA;If you display the noise texture alone (using the scaling values when querying the texel in the tutorial) i.e&#xD;&#xA;&#xD;&#xA;    const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); // screen = 800x600, N.B '4' x '4' matrix&#xD;&#xA;    frag = texture(texNoise, TexCoords * noiseScale).rgb; &#xD;&#xA;&#xD;&#xA; you would see that it is tiled over the entirety of the screen, with each noise value occupying a single fragment/pixel, but repeated over the screen. &#xD;&#xA;e.g. for a 4x4 noise, the value (pixel colour) is repeated every 4 horizontal pixels, and every 4 vertical pixels. &#xD;&#xA;&#xD;&#xA; This would be the single 'noise' value used to transform all 64 samples at that particular fragment location.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&gt; The tutorial mentions that it wants to give samples closer to the&#xD;&#xA;&gt; current fragment more weight, wouldnt it then make more sense to store&#xD;&#xA;&gt; the weight directly in the vector rotations (in the A/W component)?&#xD;&#xA;&#xD;&#xA; This wouldn't make any sense since the samples are what are weighted, not the random noise, and since each fragment uses a single noise value it would be nothing more than a scalar applied to ALL samples done at that fragment location, which defeats the purpose of 'weighting the samples'.&#xD;&#xA; &#xD;&#xA; Also note, that any sample in the hemisphere is the same distance irrelevant of any rotation applied, and so this 'weighting' is in fact constant (since the samples are constant in the firstplace) so do not need evaluating each time they are used in the shader (waste of GPU cycles). &#xD;&#xA;&#xD;&#xA;This is done by CPU when populating the buffer (`lerp` in the tutorial code) by pushing the 'uniformly' distributed samples closer to the hempshere souce. i.e more samples closer to the fragment position (when transformed) as these are likely to add more 'effect' to close proximity occlusions. This is why the shading falls off quite fast, and is a lot darker in compacted corners.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="41228" PostHistoryTypeId="5" PostId="13596" RevisionGUID="77f1109d-02ea-432f-918b-73538d3f9d60" CreationDate="2023-07-17T22:13:38.740" UserId="9438" Comment="edited body" Text="In this context, the 'Kernel' is the set of samples that are used in the 'Screen Space' domain. The name Kernel comes from image kernel (i.e convolution). The kernel contains the sample data that is ultimately transformed into screen space and used to sample against other depth values within an arbitary proximity of the pixel/fragment (the sampling radius). &#xD;&#xA;&#xD;&#xA;&gt; I fail to understand how they work together in regards of the&#xD;&#xA;&gt; sampling, since in the tutorial there are only 4x4 different random&#xD;&#xA;&gt; vector rotations, why is the kernel size 64?&#xD;&#xA;&#xD;&#xA;While the result depends on **both** the samples (in the kernel) and the 'noise' (a single random rotation) applied to ALL the samples (in tangent/view space) at that particular fragment, they **do not** depend on each other in the first place so do not need to be the same size/count.&#xD;&#xA;&#xD;&#xA;You could have 32 samples, and 144 'randoms' in your noise if you wanted, it does not matter. The number of samples in the kernel are what is sampled for each fragment. In this example you gave, each fragment will perform 64 samples, and will be transformed with a 'single' noise/random jitter at that particular fragment position. The noise size is picked to simply prevent adjacent repitition (banding) and give the impression of a larger distribution of sample randomness wrt to adjacent fragments (although it is infact repeated). &#xD;&#xA;&#xD;&#xA;The values 64 and 16 (4x4) are probably chosen for in this example as they are probably the happy medium for achieving a decent, natural looking, but fast result in this scenario. The purpose of SSOA is a cheap, no-CPU approximation of ambient occlusion (shading from local occlusion), **not** done in world space, so there needs to be a balance of realistic looking quality, while remaining easy enough for the GPU to retain a decent FPS. &#xD;&#xA;&#xD;&#xA;If you display the noise texture alone (using the scaling values when querying the texel in the tutorial) i.e&#xD;&#xA;&#xD;&#xA;    const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); // screen = 800x600, N.B '4' x '4' matrix&#xD;&#xA;    frag = texture(texNoise, TexCoords * noiseScale).rgb; &#xD;&#xA;&#xD;&#xA; you would see that it is tiled over the entirety of the screen, with each noise value occupying a single fragment/pixel, but repeated over the screen. &#xD;&#xA;e.g. for a 4x4 noise, the value (pixel colour) is repeated every 4 horizontal pixels, and every 4 vertical pixels. &#xD;&#xA;&#xD;&#xA; This would be the single 'noise' value used to transform all 64 samples at that particular fragment location.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&gt; The tutorial mentions that it wants to give samples closer to the&#xD;&#xA;&gt; current fragment more weight, wouldnt it then make more sense to store&#xD;&#xA;&gt; the weight directly in the vector rotations (in the A/W component)?&#xD;&#xA;&#xD;&#xA; This wouldn't make any sense since the samples are what are weighted, not the random noise, and since each fragment uses a single noise value it would be nothing more than a scalar applied to ALL samples done at that fragment location, which defeats the purpose of 'weighting the samples'.&#xD;&#xA; &#xD;&#xA; Also note, that any sample in the hemisphere is the same distance irrelevant of any rotation applied, and so this 'weighting' is in fact constant (since the samples are constant in the firstplace) so do not need evaluating each time they are used in the shader (waste of GPU cycles). &#xD;&#xA;&#xD;&#xA;The sample weighting is done by CPU when populating the buffer (`lerp` in the tutorial code) by pushing the 'uniformly' distributed samples closer to the hemisphere souce/origin. i.e more samples closer to the fragment position (when transformed) as these are likely to add more 'effect' to close proximity occlusions. This is why the shading falls off quite fast, and is a lot darker in compacted corners.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="41229" PostHistoryTypeId="5" PostId="13596" RevisionGUID="b66a994b-c609-4feb-a96a-ccd1f0ec88a3" CreationDate="2023-07-17T23:09:31.857" UserId="9438" Comment="added 30 characters in body" Text="In this context, the 'Kernel' is the set of samples that are used in the 'Screen Space' domain. The name Kernel comes from image kernel (i.e convolution). The kernel contains the sample data that is ultimately transformed into screen space and used to sample against other depth values within an arbitary proximity of the pixel/fragment (the sampling radius). &#xD;&#xA;&#xD;&#xA;&gt; I fail to understand how they work together in regards of the&#xD;&#xA;&gt; sampling, since in the tutorial there are only 4x4 different random&#xD;&#xA;&gt; vector rotations, why is the kernel size 64?&#xD;&#xA;&#xD;&#xA;While the result depends on **both** the samples (in the kernel) and the 'noise' (a single random rotation) applied during TBN transform to ALL the samples (in tangent/view space) at that particular fragment, they **do not** depend on each other in the first place so do not need to be the same size/count.&#xD;&#xA;&#xD;&#xA;You could have 32 samples, and 144 'randoms' in your noise if you wanted, it does not matter. The number of samples in the kernel are what is sampled for each fragment. In this example you gave, each fragment will perform 64 samples, and will be TBN transformed with a 'single' noise/random jitter at that particular fragment position. The noise size is picked to simply prevent adjacent repitition (banding) and give the impression of a larger distribution of sample randomness wrt to adjacent fragments (although it is infact repeated). &#xD;&#xA;&#xD;&#xA;The values 64 and 16 (4x4) are probably chosen for in this example as they are probably the happy medium for achieving a decent, natural looking, but fast result in this scenario. The purpose of SSOA is a cheap, no-CPU approximation of ambient occlusion (shading from local occlusion), **not** done in world space, so there needs to be a balance of realistic looking quality, while remaining easy enough for the GPU to retain a decent FPS. &#xD;&#xA;&#xD;&#xA;If you display the noise texture alone (using the scaling values when querying the texel in the tutorial) i.e&#xD;&#xA;&#xD;&#xA;    const vec2 noiseScale = vec2(800.0/4.0, 600.0/4.0); // screen = 800x600, N.B '4' x '4' matrix&#xD;&#xA;    frag = texture(texNoise, TexCoords * noiseScale).rgb; &#xD;&#xA;&#xD;&#xA; you would see that it is tiled over the entirety of the screen, with each noise value occupying a single fragment/pixel, but repeated over the screen. &#xD;&#xA;e.g. for a 4x4 noise, the value (pixel colour) is repeated every 4 horizontal pixels, and every 4 vertical pixels. &#xD;&#xA;&#xD;&#xA; This would be the single 'noise' value used when transforming all 64 samples at that particular fragment location.&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&gt; The tutorial mentions that it wants to give samples closer to the&#xD;&#xA;&gt; current fragment more weight, wouldnt it then make more sense to store&#xD;&#xA;&gt; the weight directly in the vector rotations (in the A/W component)?&#xD;&#xA;&#xD;&#xA; This wouldn't make any sense since the samples are what are weighted, not the random noise, and since each fragment uses a single noise value it would be nothing more than a scalar applied to ALL samples done at that fragment location, which defeats the purpose of 'weighting the samples'.&#xD;&#xA; &#xD;&#xA; Also note, that any sample in the hemisphere is the same distance irrelevant of any rotation applied, and so this 'weighting' is in fact constant (since the samples are constant in the firstplace) so do not need evaluating each time they are used in the shader (waste of GPU cycles). &#xD;&#xA;&#xD;&#xA;The sample weighting is done by CPU when populating the buffer (`lerp` in the tutorial code) by pushing the 'uniformly' distributed samples closer to the hemisphere souce/origin. i.e more samples closer to the fragment position (when transformed) as these are likely to add more 'effect' to close proximity occlusions. This is why the shading falls off quite fast, and is a lot darker in compacted corners.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="41234" PostHistoryTypeId="50" PostId="9626" RevisionGUID="5921ce0d-acbf-4505-97e1-c22d1cf8201c" CreationDate="2023-07-18T17:07:10.907" UserId="-1" />
  <row Id="41243" PostHistoryTypeId="2" PostId="13598" RevisionGUID="75af4314-1cc9-4a82-a5a8-f06e310feb85" CreationDate="2023-07-22T04:45:38.077" UserId="19537" Text="Recently I've been digging deeper into the volumetric rendering (volumetric path tracing, to be specific). I already know that for surface rendering, there are **two commonly used measures**: area measure and solid angle measure, which can be related via this equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{d \sigma(w_o)}{dA(\mathbf{x}')} = \frac{|\cos(\theta_i')|}{\Vert \mathbf{x} - \mathbf{x}'\Vert}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;which is physically intuitive: the geometric term (without visibility) here accounts for a change of measure --- how do we map an arbitrarily located differential area to a unit ball, as shown in the following figure. This is **quite useful** when we draw samples from another space other than the space we integrate.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;-  What is the measure for integration in the volumetric medium? Is there any intuitive explanation resembling to the figure above? I personally find it difficult to get everything straight.&#xD;&#xA;&#xD;&#xA;- What is the relation for this &quot;volumetric measure&quot; with other measures, mathematically? I don't think I've seen much difference in the renderer (a missing cosine term, tops).&#xD;&#xA;&#xD;&#xA;- Say, during distance sampling (mean-free-path sampling), I devised a new approach but it does not sample in the original space. Is there any extra stuff I need to put into the rendering equation? Like a Jacobian? For example, I get a mean-free-path path sample but actually the sample is originated from another space, then can I directly use NEE? I don't feel right about $I / d^2$ term for sampling a light source (diffusive area or point), which should be correct if I use samples from the original space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/y5WDb.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41245" PostHistoryTypeId="1" PostId="13598" RevisionGUID="75af4314-1cc9-4a82-a5a8-f06e310feb85" CreationDate="2023-07-22T04:45:38.077" UserId="19537" Text="Measure for volumetric rendering equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41246" PostHistoryTypeId="3" PostId="13598" RevisionGUID="75af4314-1cc9-4a82-a5a8-f06e310feb85" CreationDate="2023-07-22T04:45:38.077" UserId="19537" Text="|mathematics|importance-sampling|volume-rendering|integral|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41247" PostHistoryTypeId="5" PostId="13598" RevisionGUID="cb602347-eb7f-456d-9416-4803c4177b22" CreationDate="2023-07-22T05:41:39.447" UserId="19537" Comment="Change: area measure to area product measure. Add reference for the conversion between these two measures." Text="Recently I've been digging deeper into the volumetric rendering (volumetric path tracing, to be specific). I already know that for surface rendering, there are **two commonly used measures** [(reference here)](https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter8.pdf): area product measure and solid angle measure, which can be related via this equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{d \sigma(w_o)}{dA(\mathbf{x}')} = \frac{|\cos(\theta_i')|}{\Vert \mathbf{x} - \mathbf{x}'\Vert}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;which is physically intuitive: the geometric term (without visibility) here accounts for a change of measure --- how do we map an arbitrarily located differential area to a unit ball, as shown in the following figure. This is **quite useful** when we draw samples from another space other than the space we integrate.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;My questions are:&#xD;&#xA;-  What is the measure for integration in the volumetric medium? Is there any intuitive explanation resembling to the figure above? I personally find it difficult to get everything straight.&#xD;&#xA;&#xD;&#xA;- What is the relation for this &quot;volumetric measure&quot; with other measures, mathematically? I don't think I've seen much difference in the renderer (a missing cosine term, tops).&#xD;&#xA;&#xD;&#xA;- Say, during distance sampling (mean-free-path sampling), I devised a new approach but it does not sample in the original space. Is there any extra stuff I need to put into the rendering equation? Like a Jacobian? For example, I get a mean-free-path path sample but actually the sample is originated from another space, then can I directly use NEE? I don't feel right about $I / d^2$ term for sampling a light source (diffusive area or point), which should be correct if I use samples from the original space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/y5WDb.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41248" PostHistoryTypeId="50" PostId="13302" RevisionGUID="031d1759-a92f-4406-ad43-a7e869ac9ee7" CreationDate="2023-07-22T20:00:00.077" UserId="-1" />
  <row Id="41250" PostHistoryTypeId="2" PostId="13599" RevisionGUID="31204d12-88c0-4d2e-910f-1fcd3d3f7200" CreationDate="2023-07-24T07:07:12.617" UserId="7008" Text="I just stumbled upon this &quot;out-of-core&quot; term and tried to see what it is about. There are a few papers and even a few questions talking about it here at computergraphics.stackexchange, but I cannot find a definition / description of what it actually is.&#xD;&#xA;&#xD;&#xA;Is it the process(/technique) of dividing resources up such that only part is loaded onto the device?&#xD;&#xA;Is it the general happenstance that not everything fits onto the device?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41252" PostHistoryTypeId="1" PostId="13599" RevisionGUID="31204d12-88c0-4d2e-910f-1fcd3d3f7200" CreationDate="2023-07-24T07:07:12.617" UserId="7008" Text="What is out-of-core raytracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41253" PostHistoryTypeId="3" PostId="13599" RevisionGUID="31204d12-88c0-4d2e-910f-1fcd3d3f7200" CreationDate="2023-07-24T07:07:12.617" UserId="7008" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41259" PostHistoryTypeId="2" PostId="13601" RevisionGUID="cccf2580-bbef-4346-aa74-e860af9d380f" CreationDate="2023-07-25T06:23:20.833" UserId="9943" Text="I'm devising an algorithm to take a freehand curve and make a bezier spline from it. I can do this already just fine, but it's a naive implementation that creates about as many bezier curves as there are unique stylus inputs, which is a large amount. It works, but it would be better if I could reduce the curve only to an essential number of bezier segments necessary to approximate the freehand drawing. I've studied the results in other vector drawing programs and they will typically have many points around areas of high curvature and then few in straight parts of the curve. My question is how to best accomplish this. The best idea I have right now is to simply compare a freehand point with the two prior freehand points and if it does not deviate from some angle threshold on the line created by those two points, do not make a new segment from it. This sort of approximates what the curvature would be. But I am wondering if there is a more established algorithm for this?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41261" PostHistoryTypeId="1" PostId="13601" RevisionGUID="cccf2580-bbef-4346-aa74-e860af9d380f" CreationDate="2023-07-25T06:23:20.833" UserId="9943" Text="How do freehand vector drawing tools typically decide where to place the control points?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41262" PostHistoryTypeId="3" PostId="13601" RevisionGUID="cccf2580-bbef-4346-aa74-e860af9d380f" CreationDate="2023-07-25T06:23:20.833" UserId="9943" Text="|vector-graphics|bezier-curve|drawing|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41263" PostHistoryTypeId="5" PostId="13531" RevisionGUID="9b7cc59f-7aa2-4b98-9d5c-c7338134b26d" CreationDate="2023-07-25T07:14:15.680" UserId="7724" Comment="deleted 10 characters in body" Text="If you want to determine those matrices you have to use the knot vector $[0, 0, 0, 0, 4, 5, 6,...]$ and write out the expressions using the Cox-DeBoor algorithm. I believe you will need to compute the functions on two knot spans and therefore obtain two different matrices.&#xD;&#xA;&#xD;&#xA;However, you can also use a little trick here by constructing a ghost point. If You construct a point $P_{g} = (2P_0 - P_1)$ and then apply $M_2$ to $\begin{bmatrix} &#xD;&#xA;           P_{g} \\&#xD;&#xA;           P_0 \\&#xD;&#xA;           P_1 \\&#xD;&#xA;           P_2&#xD;&#xA;         \end{bmatrix}$ you will end up with the following situation:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Here curve $a$ is constructed using control points $[P_{g}, P_0, P_1, P_2]$ and curve $b$ with $[P_0, P_1, P_2, P_3]$. Naturally, the same can be done at the end of the curve by creating a ghost point $P_g = 2P_n - P_{n-1}$. If you need the matrix you will have to substitute $(2P_0 - P_1)$ for $P_g$ and find out which functions act on $P_0$ and $P_1$ by writing out the equations and collecting the terms.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/m9l1L.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41265" PostHistoryTypeId="2" PostId="13602" RevisionGUID="c0c7693f-2063-4504-a3cd-f112b15c81e7" CreationDate="2023-07-25T13:13:24.980" UserId="19678" Text="My world has the base unit of 1024. Each tile is 1024x1024 units.&#xD;&#xA;When the camera is at the center of a tile, the tile ranges from -512 to 512 in view space (no rotation).&#xD;&#xA;&#xD;&#xA;Does it make sense (and is it even possible) to compose a view matrix that &quot;scales&quot; the unit in such a way that [0,1024] maps to [0,1]?&#xD;&#xA;If the Camera is at the center of a tile, the tile should range from -0.5 to 0.5 in view space.&#xD;&#xA;&#xD;&#xA;I would prefer to not scale the world matrices of objects." ContentLicense="CC BY-SA 4.0" />
  <row Id="41267" PostHistoryTypeId="1" PostId="13602" RevisionGUID="c0c7693f-2063-4504-a3cd-f112b15c81e7" CreationDate="2023-07-25T13:13:24.980" UserId="19678" Text="Is it possible to scale a view matrix?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41268" PostHistoryTypeId="3" PostId="13602" RevisionGUID="c0c7693f-2063-4504-a3cd-f112b15c81e7" CreationDate="2023-07-25T13:13:24.980" UserId="19678" Text="|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41269" PostHistoryTypeId="2" PostId="13603" RevisionGUID="a30463d3-bd1d-48fb-9efb-60fceb88aeef" CreationDate="2023-07-25T16:28:41.613" UserId="19537" Text="I think you are right. The general *out-of-core* describes exactly the situation in which we have limitted memory (RAM for CPU and global memory for GPU) compared to the task.&#xD;&#xA;&#xD;&#xA;&gt; The term out-of-core typically refers to processing data that is too large to fit into a computer's main memory. [Out-of-core - MachineLearningWTF](https://machinelearning.wtf/terms/out-of-core/)&#xD;&#xA;&#xD;&#xA;The term mentioned more, I believe, is *out-of-core rendering*, which is a broader concept that we don't have to rely on ray-tracing related approaches to do the rendering. However, the underlying problems to solve are the same:&#xD;&#xA;&#xD;&#xA;- Geometry is too complex (tremendous amount of primitives)&#xD;&#xA;- Textures are too detailed (thus, large)&#xD;&#xA;- The scene is simply too large&#xD;&#xA;&#xD;&#xA;So locally we usually use tiled-based rendering (and load / store tiles dynamically) and paging (may swap the finished part to the external storage, or directly output as files and do a final composition) or even some more complex pipelines for GPU (since host/device memory is quite different) to solve the lack of memory problem.&#xD;&#xA;&#xD;&#xA;Note that I've seen no official definition from any literature before, but they do convey some very similar concepts for out-of-core ray-tracing (rendering):&#xD;&#xA;&gt; [1] Kirill Garanzha, Alexander Bely, Simon Premoze, and Vladimir Galaktionov. 2011. Out-of-core GPU ray tracing of complex scenes. In ACM SIGGRAPH 2011 Talks (SIGGRAPH '11). Association for Computing Machinery, New York, NY, USA, Article 21, 1. https://doi.org/10.1145/2037826.2037854&#xD;&#xA;&#xD;&#xA;&gt; [2] Budge, Brian, et al. &quot;Out‐of‐core data management for path tracing on hybrid resources.&quot; Computer Graphics Forum. Vol. 28. No. 2. Oxford, UK: Blackwell Publishing Ltd, 2009.&#xD;&#xA;&#xD;&#xA;&gt; [3] Rui Wang, Yuchi Huo, Yazhen Yuan, Kun Zhou, Wei Hua, and Hujun Bao. 2013. GPU-based out-of-core many-lights rendering. ACM Trans. Graph. 32, 6, Article 210 (November 2013), 10 pages. https://doi.org/10.1145/2508363.2508413&#xD;&#xA;&#xD;&#xA;&gt; [4] Wald, Ingo, Andreas Dietrich, and Philipp Slusallek. &quot;An interactive out-of-core rendering framework for visualizing massively complex models.&quot; ACM SIGGRAPH 2005 Courses. 2005. 17-es.&#xD;&#xA;&#xD;&#xA;&gt; [5] Varadhan, Gokul, and Dinesh Manocha. &quot;Out-of-core rendering of massive geometric environments.&quot; IEEE Visualization, 2002. VIS 2002.. IEEE, 2002.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41271" PostHistoryTypeId="50" PostId="13554" RevisionGUID="354e5768-1052-4dfc-b8d0-d5bb23944aee" CreationDate="2023-07-25T19:01:40.200" UserId="-1" />
  <row Id="41290" PostHistoryTypeId="2" PostId="13607" RevisionGUID="6718e3c4-23b9-4f2c-8365-5d5ca12fc175" CreationDate="2023-07-30T03:57:31.947" UserId="20307" Text="What is the transformation matrix M that transforms a square in the x-y plane defined by (1, 1)&lt;sup&gt;T&lt;/sup&gt; (-1, 1)&lt;sup&gt;T&lt;/sup&gt; (-1, -1)&lt;sup&gt;T&lt;/sup&gt; (1, -1)&lt;sup&gt;T&lt;/sup&gt; to a parallelogram whose corresponding vertices are (2, 1)&lt;sup&gt;T&lt;/sup&gt; (0,1)&lt;sup&gt;T&lt;/sup&gt; (-2, -1)&lt;sup&gt;T&lt;/sup&gt; and (0, -1)&lt;sup&gt;T&lt;/sup&gt; ? Following are options below. This is not a homework question.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I can easily find transformation matrix in 2X2 but how 3X3 ? I got confused between Option A and C. How third row and column is added ?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/D7MuE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41292" PostHistoryTypeId="1" PostId="13607" RevisionGUID="6718e3c4-23b9-4f2c-8365-5d5ca12fc175" CreationDate="2023-07-30T03:57:31.947" UserId="20307" Text="Computer Graphics Previous Year Question asked in UGC NET 2021" ContentLicense="CC BY-SA 4.0" />
  <row Id="41293" PostHistoryTypeId="3" PostId="13607" RevisionGUID="6718e3c4-23b9-4f2c-8365-5d5ca12fc175" CreationDate="2023-07-30T03:57:31.947" UserId="20307" Text="|transformations|matrix|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41294" PostHistoryTypeId="2" PostId="13608" RevisionGUID="dbcf8417-b472-46c6-a9f6-091e6711beab" CreationDate="2023-07-31T08:04:34.907" UserId="20312" Text="GPUs have a smaller instruction set than a CPU does, but that means that from an architecture POV all the instructions in a GPU have a combination of slower CPU equivalent instructions?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41296" PostHistoryTypeId="1" PostId="13608" RevisionGUID="dbcf8417-b472-46c6-a9f6-091e6711beab" CreationDate="2023-07-31T08:04:34.907" UserId="20312" Text="What is the theory behind a CPU being able to do everything a GPU can? Can I have something GPU based that can not run on a CPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41297" PostHistoryTypeId="3" PostId="13608" RevisionGUID="dbcf8417-b472-46c6-a9f6-091e6711beab" CreationDate="2023-07-31T08:04:34.907" UserId="20312" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41298" PostHistoryTypeId="50" PostId="10537" RevisionGUID="140c2e64-b6fd-4349-9f28-55375e8cdfc4" CreationDate="2023-07-31T13:09:21.223" UserId="-1" />
  <row Id="41299" PostHistoryTypeId="50" PostId="13562" RevisionGUID="1c8ee10e-2d73-4358-92f3-805fcb72bb50" CreationDate="2023-07-31T15:03:50.427" UserId="-1" />
  <row Id="41300" PostHistoryTypeId="2" PostId="13609" RevisionGUID="47458f4b-edbc-48cd-9c79-0072626dad52" CreationDate="2023-07-31T15:12:36.947" UserId="20314" Text="I'm looking for algorithms or methods suitable for filling the area enclosed between complex curves - for example, the area within an outer ellipse but outside an inner ellipse, or the area bounded by two or more Bezier curves.&#xD;&#xA;&#xD;&#xA;I'm familiar with the Flood Fill algorithm, which is quite universal, but it can also be inefficient and imprecise for complex shapes and large images.&#xD;&#xA;&#xD;&#xA;I'm interested in alternatives, especially scanline-based methods. I understand that these work by intersecting the curves with horizontal or vertical lines and filling in the pixels between intersection points. However, the implementation details can get quite complex, especially for curves like ellipses or Bezier curves that require solving equations to find the intersection points.&#xD;&#xA;&#xD;&#xA;Can anyone provide more detailed guidance or point me to resources about implementing these scanline fill methods for complex curves? Are there other, possibly more efficient or easier to implement, methods that I should consider?&#xD;&#xA;&#xD;&#xA;Is analytical way to fast determine if point is inside such areas?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41302" PostHistoryTypeId="1" PostId="13609" RevisionGUID="47458f4b-edbc-48cd-9c79-0072626dad52" CreationDate="2023-07-31T15:12:36.947" UserId="20314" Text="Methods for filling the area between complex curves" ContentLicense="CC BY-SA 4.0" />
  <row Id="41303" PostHistoryTypeId="3" PostId="13609" RevisionGUID="47458f4b-edbc-48cd-9c79-0072626dad52" CreationDate="2023-07-31T15:12:36.947" UserId="20314" Text="|bezier-curve|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41304" PostHistoryTypeId="2" PostId="13610" RevisionGUID="c02804de-dbc8-46d4-8435-80f95a83eae6" CreationDate="2023-08-01T08:31:04.937" UserId="9600" Text="&gt; The projection matrix is then essentially `K * [R | T]`&#xD;&#xA;&#xD;&#xA;Is incorrect, actually the K Matrix is similar to projection matrix and&#xD;&#xA;the R|T is called *camera transform matrix* or *view transform matrix*&#xD;&#xA;Or called *extrinsic matrix*. So focus on the projection stuff and forget about camera transform,&#xD;&#xA;what is the difference between *K Matrix* and Perspective Projection &#xD;&#xA;Matrix(call it *P Matrix* later)?&#xD;&#xA;&#xD;&#xA;- For *K Matrix* it transform 3D points to 2D pixels in image space.&#xD;&#xA;- For *P Matrix* it transform 3D points to NDC space.&#xD;&#xA;&#xD;&#xA;Take a look at two matrices:&#xD;&#xA;&#xD;&#xA;$$K = \begin{bmatrix}f_x&amp;   0&amp;  c_x\\  0&amp; f_y&amp;  c_y\\&#xD;&#xA;0  &amp;  0 &amp;    1\\\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;$$P = \begin{bmatrix}&#xD;&#xA;\frac{1}{t*aspect}&amp;   0&amp;  0&amp; 0\\0&amp; \frac{1}{t}&amp;  0&amp; 0\\&#xD;&#xA;0  &amp;  0 &amp;    A&amp; B&amp;\\ 0  &amp;  0 &amp;    -1&amp; 0\\ \end{bmatrix}$$&#xD;&#xA;$$t=tan(\frac{fovy}{2})$$&#xD;&#xA;&#xD;&#xA;Let's add perspective divide and show the result of the above two matrices:&#xD;&#xA;&#xD;&#xA;Intrinsic case: $$x_{2d} = \frac{x_0}{z_0 * \frac{1}{f_x}} + C_x$$&#xD;&#xA;&#xD;&#xA;Perspective case: $$x_{2d} = \frac{x_0}{-z_0(t*aspect)}$$&#xD;&#xA;&#xD;&#xA;Similar with some difference.&#xD;&#xA;&#xD;&#xA;The image space: Origin from left-top corner&#xD;&#xA;so should add Cx Cy as the offset from center to left-top corner.&#xD;&#xA;And in NDC space we assume Z-axis direct out of screen so P(3,2) = -1." ContentLicense="CC BY-SA 4.0" />
  <row Id="41306" PostHistoryTypeId="50" PostId="9192" RevisionGUID="bb6d4691-a28a-44f3-be35-d71b4291d4cf" CreationDate="2023-08-02T05:04:50.627" UserId="-1" />
  <row Id="41307" PostHistoryTypeId="2" PostId="13611" RevisionGUID="f8e979de-1678-4965-87d0-941589fc9df7" CreationDate="2023-08-02T13:08:33.330" UserId="19678" Text="I am considering using octahedron textures for environment mapping, opposed to sphere or cube mapping due to their low memory footprint and the quality they result in.&#xD;&#xA;&#xD;&#xA;Is there a possibility to render to such an octahedron texture directly (i.e. 3D -&gt; Octahedron)?&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Rendering to a cubemap and then to the octahedron is fairly straight forward since I can use the Octahedron Texture Coordinates to retrieve the cubemap direction for sampling.&#xD;&#xA;But I would like to skip the intermediate cubemap. The octahedron textures are supposed to be generated at load time behind a loading screen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4sLDo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41309" PostHistoryTypeId="1" PostId="13611" RevisionGUID="f8e979de-1678-4965-87d0-941589fc9df7" CreationDate="2023-08-02T13:08:33.330" UserId="19678" Text="Is it possible to render to a octahedron texture directly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41310" PostHistoryTypeId="3" PostId="13611" RevisionGUID="f8e979de-1678-4965-87d0-941589fc9df7" CreationDate="2023-08-02T13:08:33.330" UserId="19678" Text="|rendering|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41311" PostHistoryTypeId="2" PostId="13612" RevisionGUID="7651f679-bf49-4d8a-be42-5b376bd5a19f" CreationDate="2023-08-02T13:41:11.320" UserId="20339" Text="I am currently grappling with the computation of mipmaps for block compressed formats (BC7) in Vulkan. The limitation with these formats is that the size of the block compressed texture needs to be a multiple of 4. While I can comfortably make this adjustment for the level 0 of the mipmap chain, subsequent levels, which are half the size of the preceding level, present a challenge. For instance, if the size of level i is a multiple of 4, level i + 1 doesn't necessarily have to be. Could it be feasible to sidestep the traditional rules of image mip level sizing and establish custom sizes for each level?&#xD;&#xA;&#xD;&#xA;Here's an illustrative example:&#xD;&#xA;&#xD;&#xA;Level 0: 1080x1080 (remains 1080x1080)&#xD;&#xA;&#xD;&#xA;Level 1: 540x540 (remains 540x540)&#xD;&#xA;&#xD;&#xA;Level 2: 270x270 (becomes 272x272)&#xD;&#xA;&#xD;&#xA;Level 3: 135x135 (becomes 136x136)&#xD;&#xA;&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;Level n: 4x4&#xD;&#xA;&#xD;&#xA;I've also explored the possibility of converting Non-Power-Of-Two (NPOT) images to Power-Of-Two images. This adjustment could resolve the problem as the entire mipmap chain would then possess sizes that are multiples of 4 (with the exception of 2x2, 1x1, etc.). However, this approach seems suboptimal, particularly when a 1027x1027 texture would have to be adjusted to 2048x2048.&#xD;&#xA;&#xD;&#xA;Given these considerations, what possible solutions could be implemented to tackle this problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41313" PostHistoryTypeId="1" PostId="13612" RevisionGUID="7651f679-bf49-4d8a-be42-5b376bd5a19f" CreationDate="2023-08-02T13:41:11.320" UserId="20339" Text="Vulkan: Compressed image formats and mipmapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="41314" PostHistoryTypeId="3" PostId="13612" RevisionGUID="7651f679-bf49-4d8a-be42-5b376bd5a19f" CreationDate="2023-08-02T13:41:11.320" UserId="20339" Text="|texture|vulkan|mipmap|compression|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41315" PostHistoryTypeId="2" PostId="13613" RevisionGUID="877cb0c0-166e-4cf8-af94-cf3356c36082" CreationDate="2023-08-02T13:41:58.290" UserId="11058" Text="I have searched through a lot of libraries and sources, that include very diverse intersection algorithms, for computer graphics. And I've never found a capsule-box intersection algorithm. Despite that there are algorithms between capsules and many other shapes. I wonder if it's because a capsule can be represented as a cylinder with two spheres at the end, and is cheaper to calculate than doing a capsule box algorithm? Or does some other algorithm cover it? Or is there any other reason?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41317" PostHistoryTypeId="1" PostId="13613" RevisionGUID="877cb0c0-166e-4cf8-af94-cf3356c36082" CreationDate="2023-08-02T13:41:58.290" UserId="11058" Text="Why capsule box intersection algorithms not widely used" ContentLicense="CC BY-SA 4.0" />
  <row Id="41318" PostHistoryTypeId="3" PostId="13613" RevisionGUID="877cb0c0-166e-4cf8-af94-cf3356c36082" CreationDate="2023-08-02T13:41:58.290" UserId="11058" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41319" PostHistoryTypeId="2" PostId="13614" RevisionGUID="67853bd6-38d3-4f6f-b5a1-beadd491f92d" CreationDate="2023-08-03T05:18:31.490" UserId="19537" Text="I agree with @pmw1234, there is no theory. The intrsuction sets on CPU and GPU are both Turing complete, therefore CPU/GPU can do, in theory, whatever the other can. I found a [dicussion for this](https://www.quora.com/Since-GPUs-are-Turing-complete-does-that-mean-you-can-program-an-OS-similar-to-Windows-that-can-run-on-just-a-GPU-without-a-CPU) on Quora, maybe you will be interested.&#xD;&#xA;&#xD;&#xA;Note that, for one single thread, GPU processes slower than CPU (on average, device dependent) and it is much less flexible. GPU achieve its acceleration via a large number of concurrent threads (organized in warps -&gt; blocks -&gt; grids) processing the same or similar tasks, which resembles to [SIMD](https://en.wikipedia.org/wiki/Single_instruction,_multiple_data) in the CPU context. There are a few things that could make GPU much faster than CPU for some of the tasks:&#xD;&#xA;&#xD;&#xA;- Large scale GPU-thread-based parallelism (therefore, SIMD-like processing)&#xD;&#xA;- Latency hiding, I believe this would be a good reference: [latency hiding](https://news.ycombinator.com/item?id=26444397)&#xD;&#xA;- Memory management (shared / texture memory) / asynchronous load &amp; store&#xD;&#xA;- Stream-based multiprocessing&#xD;&#xA;&#xD;&#xA;Actually to the best of my knowledge, GPU threads can be very limitted for some tasks. For example, it does not perform as efficient as CPU threads when the program focuses more on branching logics than data-driven computation and large-scale similar simple tasks. There is a concept called &quot;warp divergence&quot; describing that when different threads in a GPU warp diverge during if-else branching, these threads could be serialized. Therefore, if your code (task) relies heavily on branching, you should be very careful when coding on GPU. A simple example is &quot;select-like&quot; function.&#xD;&#xA;&#xD;&#xA;CPU however, is well-designed for handling context changing, the switch between multiple processes, branch prediction and out-of-order execution (therefore well pipelined) therefore each core can process very sophisticated tasks independently. As a simple analogy, a CPU is like a handful of extremely efficient workers who can work independently while a GPU is like a large number of normal workers who work well in groups. Both of them are similarly capable while they focus differently.&#xD;&#xA;  " ContentLicense="CC BY-SA 4.0" />
  <row Id="41321" PostHistoryTypeId="2" PostId="13615" RevisionGUID="4de1379e-e23d-41f0-b49c-1990aeaabc30" CreationDate="2023-08-03T12:15:12.560" UserDisplayName="user1703" Text="I am surprised to read that capsule-capsule intersection algorithms are commonly found. This is an arduous problem, with many different cases, and complex high order curves that take quartic equations. Even cylindre-cylindre is daunting.&#xD;&#xA;&#xD;&#xA;Caspule-box is easier as it is essentially cutting surfaces with planes, leading to arcs of conics. Anyway, the complete discussion is tedious.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41323" PostHistoryTypeId="50" PostId="2516" RevisionGUID="f051e5cc-a9a7-40dc-9bea-f8cb67143983" CreationDate="2023-08-03T18:00:30.043" UserId="-1" />
  <row Id="41324" PostHistoryTypeId="2" PostId="13616" RevisionGUID="595f2882-76e8-4cdd-a769-e0beb736eaf3" CreationDate="2023-08-03T18:08:31.113" UserDisplayName="user1703" Text="Filling only requires pixel accuracy, so approximate solutions are quite acceptable. A simple but powerful method is to flatten the curves (i.e. turning them to polylines) and assemble the polylines to polygons.&#xD;&#xA;&#xD;&#xA;Polygons can be filled by scanline processing.&#xD;&#xA;&#xD;&#xA;Flattening can be done recursively as follows:&#xD;&#xA;- consider an arc of a parametric curve;&#xD;&#xA;- compute the point at the middle parameter value;&#xD;&#xA;- if the distance of that point to the chord exceeds a threshold, process both halves recursively;&#xD;&#xA;- otherwise, the curve is well approximated by the chord.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Technical note:**&#xD;&#xA;&#xD;&#xA;In some rare cases (around an inflexion point), the procedure can fail. A workaround is to subdivide one more time when the midpoint is found to be close. This is still not bulletproof, but the probability of failure is microscopic." ContentLicense="CC BY-SA 4.0" />
  <row Id="41326" PostHistoryTypeId="5" PostId="13616" RevisionGUID="0ec008ed-f842-4361-83d2-45876015cbf5" CreationDate="2023-08-03T18:17:11.637" UserDisplayName="user1703" Comment="added 168 characters in body" Text="Filling only requires pixel accuracy, so approximate solutions are quite acceptable. A simple but powerful method is to flatten the curves (i.e. turning them to polylines) and assemble the polylines to polygons.&#xD;&#xA;&#xD;&#xA;Polygons can be filled by scanline processing.&#xD;&#xA;&#xD;&#xA;Flattening can be done recursively as follows:&#xD;&#xA;- consider an arc of a parametric curve;&#xD;&#xA;- compute the point at the middle parameter value;&#xD;&#xA;- if the distance of that point to the chord exceeds a threshold, process both halves recursively;&#xD;&#xA;- otherwise, the curve is well approximated by the chord.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Technical note:**&#xD;&#xA;&#xD;&#xA;In some rare cases (around an inflexion point), the procedure can fail. A workaround is to subdivide one more time when the midpoint is found to be close. This is still not bulletproof, but the probability of failure is microscopic.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;**Also of interest:**&#xD;&#xA;&#xD;&#xA;https://stackoverflow.com/a/25992262/21508463&#xD;&#xA;&#xD;&#xA;The method also applies to elliptic arcs, that fulfill a conic equation.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41327" PostHistoryTypeId="50" PostId="13572" RevisionGUID="2d76fc28-b409-4ee4-af30-a3239b3f7489" CreationDate="2023-08-03T19:04:40.547" UserId="-1" />
  <row Id="41328" PostHistoryTypeId="50" PostId="13340" RevisionGUID="b2da8431-64c2-4ef1-94b8-fe56867b2d44" CreationDate="2023-08-03T20:03:35.440" UserId="-1" />
  <row Id="41329" PostHistoryTypeId="50" PostId="9549" RevisionGUID="93316b6f-1cf0-4563-8c50-6c71252d6fbb" CreationDate="2023-08-03T21:05:10.567" UserId="-1" />
  <row Id="41331" PostHistoryTypeId="50" PostId="13352" RevisionGUID="db2c553e-7659-47f1-afc4-2c6f0edce5ef" CreationDate="2023-08-04T12:03:55.463" UserId="-1" />
  <row Id="41332" PostHistoryTypeId="50" PostId="13022" RevisionGUID="6c3cf8b9-37ed-43ce-bd98-885a58368c23" CreationDate="2023-08-04T13:06:15.710" UserId="-1" />
  <row Id="41333" PostHistoryTypeId="50" PostId="13262" RevisionGUID="95c30e3a-6ea1-4d4b-995e-16a89c3d75f7" CreationDate="2023-08-04T18:03:00.353" UserId="-1" />
  <row Id="41334" PostHistoryTypeId="50" PostId="10748" RevisionGUID="96992934-58d4-458d-8a96-dd5668c98b34" CreationDate="2023-08-04T19:07:35.903" UserId="-1" />
  <row Id="41335" PostHistoryTypeId="2" PostId="13617" RevisionGUID="24dd5d89-e8f3-40e2-9ba9-2901f89ff22d" CreationDate="2023-08-04T20:35:49.563" UserId="20354" Text="I'm trying to write my own 3D engine using Python and Pygame.&#xD;&#xA;&#xD;&#xA;I have successfully implemented rotation and projection matrices to display 3D models. However I am so far unable to implement translation and scaling matrices, I have instead been opting for manually displace the model by Z-axis (after rotation has been applied).&#xD;&#xA;&#xD;&#xA;Also resizing the object and displacing it by X/Y-axises (after applying projection).&#xD;&#xA;&#xD;&#xA;After trying to add scaling and translation matrices and also a camera, this is the result:&#xD;&#xA;&lt;img src=&quot;https://i.imgur.com/KJKqbPp.gif&quot;&gt;&#xD;&#xA;&#xD;&#xA;With only rotation and perspective matrices and manual displacement:&#xD;&#xA;&lt;img src=&quot;https://i.imgur.com/sAe9vnt.gif&quot;&gt;&#xD;&#xA;&#xD;&#xA;Apologiez for posting so much code but I'm truly stuck right now. I've tried to add as many comments as possible.&#xD;&#xA;&#xD;&#xA;Very thankful for any help!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Code with camera and translation/scaling matrices:&#xD;&#xA;&#xD;&#xA;```py&#xD;&#xA;import pygame&#xD;&#xA;import math &#xD;&#xA;import copy&#xD;&#xA;import random&#xD;&#xA;import obj_loader as obj&#xD;&#xA;&#xD;&#xA;pygame.init()&#xD;&#xA;&#xD;&#xA;screen_width = 1920&#xD;&#xA;screen_height = 1080&#xD;&#xA;screen = pygame.display.set_mode([screen_width, screen_height])&#xD;&#xA;clock = pygame.time.Clock()&#xD;&#xA;FPS = 60&#xD;&#xA;run = True&#xD;&#xA;&#xD;&#xA;class Renderer():&#xD;&#xA;    def __init__(self):&#xD;&#xA;        &#xD;&#xA;        # random colors for model sides&#xD;&#xA;        self.colors = []&#xD;&#xA;        for _ in range(6):&#xD;&#xA;            self.colors.append([random.randint(0,255), random.randint(0,255), random.randint(0,255)])&#xD;&#xA;&#xD;&#xA;        #  Models:&#xD;&#xA;        # &quot;default&quot; (cube)&#xD;&#xA;        # &quot;cube&quot;&#xD;&#xA;        # &quot;pylon&quot;&#xD;&#xA;        # &quot;wireframe&quot; (cube)&#xD;&#xA;        # &quot;teapot&quot;&#xD;&#xA;&#xD;&#xA;        model = &quot;default&quot;&#xD;&#xA;        self.rotation = [0,1,0]&#xD;&#xA;        self.rotation_speed = 0.015&#xD;&#xA;        self.wireframes = 0&#xD;&#xA;        self.color_fill = 1&#xD;&#xA;&#xD;&#xA;        self.rotx = 0; self.roty = 0; self.rotz = 0&#xD;&#xA;&#xD;&#xA;        # use basic cube or load model from obj-file&#xD;&#xA;        if model == &quot;default&quot;:&#xD;&#xA;            &#xD;&#xA;            self.size = 1&#xD;&#xA;&#xD;&#xA;            self.model = [&#xD;&#xA;            [[0, 0, 0, 1],    [0, 1, 0, 1],    [1, 1, 0, 1], self.colors[0]],&#xD;&#xA;            [[0, 0, 0, 1],    [1, 1, 0, 1],    [1, 0, 0, 1], self.colors[0]],                                 &#xD;&#xA;            [[1, 0, 0, 1],    [1, 1, 0, 1],    [1, 1, 1, 1], self.colors[1]],&#xD;&#xA;            [[1, 0, 0, 1],    [1, 1, 1, 1],    [1, 0, 1, 1], self.colors[1]],                                       &#xD;&#xA;            [[1, 0, 1, 1],    [1, 1, 1, 1],    [0, 1, 1, 1], self.colors[2]],&#xD;&#xA;            [[1, 0, 1, 1],    [0, 1, 1, 1],    [0, 0, 1, 1], self.colors[2]],                                         &#xD;&#xA;            [[0, 0, 1, 1],    [0, 1, 1, 1],    [0, 1, 0, 1], self.colors[3]],&#xD;&#xA;            [[0, 0, 1, 1],    [0, 1, 0, 1],    [0, 0, 0, 1], self.colors[3]],                                          &#xD;&#xA;            [[0, 1, 0, 1],    [0, 1, 1, 1],    [1, 1, 1, 1], self.colors[4]],&#xD;&#xA;            [[0, 1, 0, 1],    [1, 1, 1, 1],    [1, 1, 0, 1], self.colors[4]],                                         &#xD;&#xA;            [[1, 0, 1, 1],    [0, 0, 1, 1],    [0, 0, 0, 1], self.colors[5]],&#xD;&#xA;            [[1, 0, 1, 1],    [0, 0, 0, 1],    [1, 0, 0, 1], self.colors[5]]]&#xD;&#xA;&#xD;&#xA;            for tri in self.model:&#xD;&#xA;                for point in tri:&#xD;&#xA;                    point[0] -= 0.5; point[1] -= 0.5; point[2] -= 0.5&#xD;&#xA;&#xD;&#xA;        # load from obj-file&#xD;&#xA;        else:&#xD;&#xA;&#xD;&#xA;            self.size = 3&#xD;&#xA;            self.model = obj.load_obj(model)&#xD;&#xA;&#xD;&#xA;            # add random colors to model sides&#xD;&#xA;            self.colors = []&#xD;&#xA;            amount_vertices = len(self.model)&#xD;&#xA;            for _ in range(amount_vertices):&#xD;&#xA;                self.colors.append([random.randint(0,255), random.randint(0,255), random.randint(0,255)])&#xD;&#xA;&#xD;&#xA;            for i, tri in enumerate(self.model):&#xD;&#xA;                tri.append(self.colors[i])&#xD;&#xA;        &#xD;&#xA;        # create empty projection matrix&#xD;&#xA;        self.projection = []&#xD;&#xA;        for _ in range(4):&#xD;&#xA;            self.projection.append([0] * 4) &#xD;&#xA;&#xD;&#xA;        self.aspect_ratio = screen_width/screen_height&#xD;&#xA;        n = 0.1&#xD;&#xA;        f = 1000     &#xD;&#xA;&#xD;&#xA;        # projection matrix&#xD;&#xA;        self.projection[0][0] = 1 / (math.tan(math.radians(90/2)) * self.aspect_ratio)&#xD;&#xA;        self.projection[0][1] = 0&#xD;&#xA;        self.projection[0][2] = 0&#xD;&#xA;        self.projection[0][3] = 0&#xD;&#xA;        &#xD;&#xA;        self.projection[1][0] = 0&#xD;&#xA;        self.projection[1][1] = 1 / math.tan(math.radians(90/2))&#xD;&#xA;        self.projection[1][2] = 0&#xD;&#xA;        self.projection[1][3] = 0&#xD;&#xA;&#xD;&#xA;        self.projection[2][0] = 0&#xD;&#xA;        self.projection[2][1] = 0&#xD;&#xA;        self.projection[2][2] = f / (f - n)&#xD;&#xA;        self.projection[2][3] = (-f * n) / (f - n)&#xD;&#xA;&#xD;&#xA;        self.projection[3][0] = 0&#xD;&#xA;        self.projection[3][1] = 0&#xD;&#xA;        self.projection[3][2] = 1&#xD;&#xA;        self.projection[3][3] = 0&#xD;&#xA;&#xD;&#xA;        # camera variables and matrix&#xD;&#xA;        self.camera_pos = [0,0,-1]&#xD;&#xA;        self.u          = [1,0,0]&#xD;&#xA;        self.v          = [0,1,0]&#xD;&#xA;        self.n          = [0,0,1]&#xD;&#xA;&#xD;&#xA;        self.camera = [&#xD;&#xA;            [self.u[0], self.u[1], self.u[2], -self.camera_pos[0]],&#xD;&#xA;            [self.v[0], self.v[1], self.v[2], -self.camera_pos[1]],&#xD;&#xA;            [self.n[0], self.n[1], self.n[2], -self.camera_pos[2]],&#xD;&#xA;            [0,         0,         0,         1                  ]&#xD;&#xA;        ]&#xD;&#xA;&#xD;&#xA;        # create rotation matrices&#xD;&#xA;        self.update_roty(); self.update_roty(); self.update_rotz()&#xD;&#xA;&#xD;&#xA;        # translation matrix&#xD;&#xA;        self.translation = [&#xD;&#xA;            [1, 0, 0, 100],&#xD;&#xA;            [0, 1, 0, 100],&#xD;&#xA;            [0, 0, 1, 0],&#xD;&#xA;            [0, 0, 0, 1]&#xD;&#xA;        ]&#xD;&#xA;        &#xD;&#xA;        # scaling matrix&#xD;&#xA;        scale = 100&#xD;&#xA;        self.scaling = [&#xD;&#xA;            [scale, 0,     0,     0],&#xD;&#xA;            [0,     scale, 0,     0],&#xD;&#xA;            [0,     0,     scale, 0],&#xD;&#xA;            [0,     0,     0,     1]&#xD;&#xA;        ]&#xD;&#xA;&#xD;&#xA;    # rotation X matrix&#xD;&#xA;    def update_rotx(self):&#xD;&#xA;        self.rotation_x = [&#xD;&#xA;            [1, 0, 0, 0],&#xD;&#xA;            [0, math.cos(self.rotx), math.sin(self.rotx), 0],&#xD;&#xA;            [0, -math.sin(self.rotx), math.cos(self.rotx), 0],&#xD;&#xA;            [0, 0, 0, 0]]&#xD;&#xA;&#xD;&#xA;    # rotation Y matrix&#xD;&#xA;    def update_roty(self):&#xD;&#xA;        self.rotation_y = [&#xD;&#xA;            [math.cos(self.roty), 0, math.sin(self.roty), 0],&#xD;&#xA;            [0, 1, 0, 0],&#xD;&#xA;            [-math.sin(self.roty), 0, math.cos(self.roty), 0],&#xD;&#xA;            [0, 0, 0, 0]]&#xD;&#xA;        &#xD;&#xA;    # rotation Z matrix&#xD;&#xA;    def update_rotz(self):&#xD;&#xA;        self.rotation_z = [&#xD;&#xA;            [math.cos(self.rotz), -math.sin(self.rotz), 0, 0],&#xD;&#xA;            [math.sin(self.rotz), math.cos(self.rotz), 0, 0],&#xD;&#xA;            [0, 0, 1, 0],&#xD;&#xA;            [0, 0, 0, 0]]&#xD;&#xA;&#xD;&#xA;    # Vector matrix multiplication&#xD;&#xA;    def Matrix_MultiplyVector(self, i, m):&#xD;&#xA;&#xD;&#xA;        vx = i[0] * m[0][0] + i[1] * m[0][1] + i[2] * m[0][2] + m[0][3]&#xD;&#xA;        vy = i[0] * m[1][0] + i[1] * m[1][1] + i[2] * m[1][2] + m[1][3]&#xD;&#xA;        vz = i[0] * m[2][0] + i[1] * m[2][1] + i[2] * m[2][2] + m[2][3]&#xD;&#xA;        vw = i[0] * m[3][0] + i[1] * m[3][1] + i[2] * m[3][2] + m[3][3]&#xD;&#xA;&#xD;&#xA;        if vw != 0:&#xD;&#xA;            vx /= vw&#xD;&#xA;            vy /= vw&#xD;&#xA;            vz /= vw&#xD;&#xA;        return [vx,vy,vz,vw]&#xD;&#xA;&#xD;&#xA;    # main render function&#xD;&#xA;    def draw(self):&#xD;&#xA;&#xD;&#xA;        # update rotation matrices&#xD;&#xA;        self.rotx += self.rotation_speed&#xD;&#xA;        self.roty += self.rotation_speed&#xD;&#xA;        self.rotz += self.rotation_speed&#xD;&#xA;        self.update_rotx(); self.update_roty(); self.update_rotz()&#xD;&#xA;&#xD;&#xA;        triangles_to_draw = []&#xD;&#xA;&#xD;&#xA;        # loop through triangles in model&#xD;&#xA;        for tri in self.model:&#xD;&#xA;            &#xD;&#xA;            # create copy of triangle to project&#xD;&#xA;            tricopy = copy.deepcopy(tri)&#xD;&#xA;            proj_points = []&#xD;&#xA;&#xD;&#xA;            # skip 4th element in triangle because it's color&#xD;&#xA;            for i, _ in enumerate(tri):&#xD;&#xA;                if i == 3:&#xD;&#xA;                    continue&#xD;&#xA;                &#xD;&#xA;                # translate triangles&#xD;&#xA;                tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.scaling)&#xD;&#xA;&#xD;&#xA;                # rotate triangles&#xD;&#xA;                if self.rotation[0] == 1:&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_x)&#xD;&#xA;                if self.rotation[1] == 1:&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_y)&#xD;&#xA;                if self.rotation[2] == 1:&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_z)&#xD;&#xA;                &#xD;&#xA;                # scale triangles&#xD;&#xA;                tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.translation)&#xD;&#xA;                &#xD;&#xA;&#xD;&#xA;            # calculate normal of triangle&#xD;&#xA;            line1 = [&#xD;&#xA;                tricopy[1][0] - tricopy[0][0],&#xD;&#xA;                tricopy[1][1] - tricopy[0][1],&#xD;&#xA;                tricopy[1][2] - tricopy[0][2],&#xD;&#xA;            ]&#xD;&#xA;&#xD;&#xA;            line2 = [&#xD;&#xA;                tricopy[2][0] - tricopy[0][0],&#xD;&#xA;                tricopy[2][1] - tricopy[0][1],&#xD;&#xA;                tricopy[2][2] - tricopy[0][2],&#xD;&#xA;            ]&#xD;&#xA;&#xD;&#xA;            Nx = line1[1] * line2[2] - line1[2] * line2[1]&#xD;&#xA;            Ny = line1[2] * line2[0] - line1[0] * line2[2]&#xD;&#xA;            Nz = line1[0] * line2[1] - line1[1] * line2[0]&#xD;&#xA;            l = math.sqrt(Nx * Nx + Ny * Ny + Nz * Nz)&#xD;&#xA;            Nx  /= l; Ny /= l; Nz /= l &#xD;&#xA;&#xD;&#xA;            # draw only if triangles normal compared with cameras normal is &lt; 0&#xD;&#xA;            if (Nx * (tricopy[0][0] - self.camera_pos[0]) + Ny * (tricopy[0][1] - self.camera_pos[1]) + Nz * (tricopy[0][2] - self.camera_pos[2])) &lt; 0:&#xD;&#xA;&#xD;&#xA;                for i, _ in enumerate(tri):&#xD;&#xA;                    # skip 4th element in triangle because it's color&#xD;&#xA;                    if i == 3: &#xD;&#xA;                        continue&#xD;&#xA;&#xD;&#xA;                    # camera and projection matrices&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.camera)&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.projection)&#xD;&#xA;&#xD;&#xA;                    &#xD;&#xA;                # calculate mean Z value and add triangles projected points to list&#xD;&#xA;                mean_z = (tricopy[0][2] + tricopy[1][2] + tricopy[2][2]) / 3&#xD;&#xA;                proj_points = [(tricopy[0][0], tricopy[0][1]), (tricopy[1][0], tricopy[1][1]), (tricopy[2][0], tricopy[2][1]), tricopy[3], mean_z]&#xD;&#xA;                triangles_to_draw.append(proj_points)&#xD;&#xA;        &#xD;&#xA;        # sort by mean Z value&#xD;&#xA;        triangles_to_draw.sort(key=lambda i: (i[4]), reverse=True)&#xD;&#xA;        &#xD;&#xA;        # draw triangles&#xD;&#xA;        for i, tri in enumerate(triangles_to_draw):&#xD;&#xA;&#xD;&#xA;            if self.color_fill == 1:&#xD;&#xA;                try:&#xD;&#xA;                    pygame.draw.polygon(screen, tri[3], (tri[0], tri[1], tri[2]))&#xD;&#xA;                except:&#xD;&#xA;                    print(tri[3])&#xD;&#xA;            if self.wireframes == 1:&#xD;&#xA;                pygame.draw.polygon(screen, [230,168,50], (tri[0], tri[1], tri[2]), 1)&#xD;&#xA;&#xD;&#xA;renderer = Renderer()&#xD;&#xA;&#xD;&#xA;# main loop&#xD;&#xA;while run:&#xD;&#xA;&#xD;&#xA;    screen.fill([47,79,83])&#xD;&#xA;    mx, my = pygame.mouse.get_pos()&#xD;&#xA;&#xD;&#xA;    for event in pygame.event.get():&#xD;&#xA;        if event.type == pygame.QUIT:&#xD;&#xA;            run = False&#xD;&#xA;        &#xD;&#xA;        if event.type == pygame.KEYDOWN:&#xD;&#xA;            if event.key == pygame.K_ESCAPE:&#xD;&#xA;                run = False&#xD;&#xA;                &#xD;&#xA;    keys = pygame.key.get_pressed()&#xD;&#xA;&#xD;&#xA;    # draw model&#xD;&#xA;    renderer.draw()&#xD;&#xA;&#xD;&#xA;    clock.tick(FPS)&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;&#xD;&#xA;pygame.quit()&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Code with just perspective and rotation matrices:&#xD;&#xA;&#xD;&#xA;```py&#xD;&#xA;import pygame&#xD;&#xA;import math &#xD;&#xA;import copy&#xD;&#xA;import random&#xD;&#xA;import obj_loader as obj&#xD;&#xA;&#xD;&#xA;pygame.init()&#xD;&#xA;&#xD;&#xA;screen_width = 1920&#xD;&#xA;screen_height = 1080&#xD;&#xA;screen = pygame.display.set_mode([screen_width, screen_height])&#xD;&#xA;clock = pygame.time.Clock()&#xD;&#xA;FPS = 60&#xD;&#xA;run = True&#xD;&#xA;&#xD;&#xA;class Renderer():&#xD;&#xA;    def __init__(self):&#xD;&#xA;        &#xD;&#xA;        # random colors for model sides&#xD;&#xA;        self.colors = []&#xD;&#xA;        for _ in range(6):&#xD;&#xA;            self.colors.append([random.randint(0,255), random.randint(0,255), random.randint(0,255)])&#xD;&#xA;&#xD;&#xA;        #  Models:&#xD;&#xA;        # &quot;default&quot; (cube)&#xD;&#xA;        # &quot;cube&quot;&#xD;&#xA;        # &quot;pylon&quot;&#xD;&#xA;        # &quot;wireframe&quot; (cube)&#xD;&#xA;        # &quot;teapot&quot;&#xD;&#xA;&#xD;&#xA;        model = &quot;default&quot;&#xD;&#xA;        self.rotation = [0,1,0]&#xD;&#xA;        self.rotation_speed = 0.015&#xD;&#xA;        self.wireframes = 0&#xD;&#xA;        self.color_fill = 1&#xD;&#xA;&#xD;&#xA;        self.rotx = 0; self.roty = 0; self.rotz = 0&#xD;&#xA;&#xD;&#xA;        # use basic cube or load model from obj-file&#xD;&#xA;        if model == &quot;default&quot;:&#xD;&#xA;            &#xD;&#xA;            self.model = [&#xD;&#xA;            [[0, 0, 0, 1],    [0, 1, 0, 1],    [1, 1, 0, 1], self.colors[0]],&#xD;&#xA;            [[0, 0, 0, 1],    [1, 1, 0, 1],    [1, 0, 0, 1], self.colors[0]],                                 &#xD;&#xA;            [[1, 0, 0, 1],    [1, 1, 0, 1],    [1, 1, 1, 1], self.colors[1]],&#xD;&#xA;            [[1, 0, 0, 1],    [1, 1, 1, 1],    [1, 0, 1, 1], self.colors[1]],                                       &#xD;&#xA;            [[1, 0, 1, 1],    [1, 1, 1, 1],    [0, 1, 1, 1], self.colors[2]],&#xD;&#xA;            [[1, 0, 1, 1],    [0, 1, 1, 1],    [0, 0, 1, 1], self.colors[2]],                                         &#xD;&#xA;            [[0, 0, 1, 1],    [0, 1, 1, 1],    [0, 1, 0, 1], self.colors[3]],&#xD;&#xA;            [[0, 0, 1, 1],    [0, 1, 0, 1],    [0, 0, 0, 1], self.colors[3]],                                          &#xD;&#xA;            [[0, 1, 0, 1],    [0, 1, 1, 1],    [1, 1, 1, 1], self.colors[4]],&#xD;&#xA;            [[0, 1, 0, 1],    [1, 1, 1, 1],    [1, 1, 0, 1], self.colors[4]],                                         &#xD;&#xA;            [[1, 0, 1, 1],    [0, 0, 1, 1],    [0, 0, 0, 1], self.colors[5]],&#xD;&#xA;            [[1, 0, 1, 1],    [0, 0, 0, 1],    [1, 0, 0, 1], self.colors[5]]]&#xD;&#xA;&#xD;&#xA;            for tri in self.model:&#xD;&#xA;                for point in tri:&#xD;&#xA;                    point[0] -= 0.5; point[1] -= 0.5; point[2] -= 0.5&#xD;&#xA;&#xD;&#xA;        # load from obj-file&#xD;&#xA;        else:&#xD;&#xA;&#xD;&#xA;            self.model = obj.load_obj(model)&#xD;&#xA;&#xD;&#xA;            # add random colors to model sides&#xD;&#xA;            self.colors = []&#xD;&#xA;            amount_vertices = len(self.model)&#xD;&#xA;            for _ in range(amount_vertices):&#xD;&#xA;                self.colors.append([random.randint(0,255), random.randint(0,255), random.randint(0,255)])&#xD;&#xA;&#xD;&#xA;            for i, tri in enumerate(self.model):&#xD;&#xA;                tri.append(self.colors[i])&#xD;&#xA;        &#xD;&#xA;        # create empty projection matrix&#xD;&#xA;        self.projection = []&#xD;&#xA;        for _ in range(4):&#xD;&#xA;            self.projection.append([0] * 4) &#xD;&#xA;&#xD;&#xA;        self.aspect_ratio = screen_width/screen_height&#xD;&#xA;        n = 0.1&#xD;&#xA;        f = 1000     &#xD;&#xA;&#xD;&#xA;        # projection matrix&#xD;&#xA;        self.projection[0][0] = 1 / (math.tan(math.radians(90/2)) * self.aspect_ratio)&#xD;&#xA;        self.projection[0][1] = 0&#xD;&#xA;        self.projection[0][2] = 0&#xD;&#xA;        self.projection[0][3] = 0&#xD;&#xA;        &#xD;&#xA;        self.projection[1][0] = 0&#xD;&#xA;        self.projection[1][1] = 1 / math.tan(math.radians(90/2))&#xD;&#xA;        self.projection[1][2] = 0&#xD;&#xA;        self.projection[1][3] = 0&#xD;&#xA;&#xD;&#xA;        self.projection[2][0] = 0&#xD;&#xA;        self.projection[2][1] = 0&#xD;&#xA;        self.projection[2][2] = f / (f - n)&#xD;&#xA;        self.projection[2][3] = (-f * n) / (f - n)&#xD;&#xA;&#xD;&#xA;        self.projection[3][0] = 0&#xD;&#xA;        self.projection[3][1] = 0&#xD;&#xA;        self.projection[3][2] = 1&#xD;&#xA;        self.projection[3][3] = 0&#xD;&#xA;&#xD;&#xA;        # camera variables and matrix&#xD;&#xA;        self.camera_pos = [0,0,-4]&#xD;&#xA;        self.u          = [1,0,0]&#xD;&#xA;        self.v          = [0,1,0]&#xD;&#xA;        self.n          = [0,0,1]&#xD;&#xA;&#xD;&#xA;        self.camera = [&#xD;&#xA;            [self.u[0], self.u[1], self.u[2], -self.camera_pos[0]],&#xD;&#xA;            [self.v[0], self.v[1], self.v[2], -self.camera_pos[1]],&#xD;&#xA;            [self.n[0], self.n[1], self.n[2], -self.camera_pos[2]],&#xD;&#xA;            [0,         0,         0,         1                  ]&#xD;&#xA;        ]&#xD;&#xA;&#xD;&#xA;        # create rotation matrices&#xD;&#xA;        self.update_roty(); self.update_roty(); self.update_rotz()&#xD;&#xA;&#xD;&#xA;        # translation matrix&#xD;&#xA;        self.translation = [&#xD;&#xA;            [1, 0, 0, 0],&#xD;&#xA;            [0, 1, 0, 0],&#xD;&#xA;            [0, 0, 1, 0],&#xD;&#xA;            [0, 0, 0, 1]&#xD;&#xA;        ]&#xD;&#xA;        &#xD;&#xA;        # scaling matrix&#xD;&#xA;        scale = 100&#xD;&#xA;        self.scaling = [&#xD;&#xA;            [scale, 0,     0,     0],&#xD;&#xA;            [0,     scale, 0,     0],&#xD;&#xA;            [0,     0,     scale, 0],&#xD;&#xA;            [0,     0,     0,     1]&#xD;&#xA;        ]&#xD;&#xA;&#xD;&#xA;    # rotation X matrix&#xD;&#xA;    def update_rotx(self):&#xD;&#xA;        self.rotation_x = [&#xD;&#xA;            [1, 0, 0, 0],&#xD;&#xA;            [0, math.cos(self.rotx), math.sin(self.rotx), 0],&#xD;&#xA;            [0, -math.sin(self.rotx), math.cos(self.rotx), 0],&#xD;&#xA;            [0, 0, 0, 0]]&#xD;&#xA;&#xD;&#xA;    # rotation Y matrix&#xD;&#xA;    def update_roty(self):&#xD;&#xA;        self.rotation_y = [&#xD;&#xA;            [math.cos(self.roty), 0, math.sin(self.roty), 0],&#xD;&#xA;            [0, 1, 0, 0],&#xD;&#xA;            [-math.sin(self.roty), 0, math.cos(self.roty), 0],&#xD;&#xA;            [0, 0, 0, 0]]&#xD;&#xA;        &#xD;&#xA;    # rotation Z matrix&#xD;&#xA;    def update_rotz(self):&#xD;&#xA;        self.rotation_z = [&#xD;&#xA;            [math.cos(self.rotz), -math.sin(self.rotz), 0, 0],&#xD;&#xA;            [math.sin(self.rotz), math.cos(self.rotz), 0, 0],&#xD;&#xA;            [0, 0, 1, 0],&#xD;&#xA;            [0, 0, 0, 0]]&#xD;&#xA;&#xD;&#xA;    # Vector matrix multiplication&#xD;&#xA;    def Matrix_MultiplyVector(self, i, m):&#xD;&#xA;&#xD;&#xA;        vx = i[0] * m[0][0] + i[1] * m[0][1] + i[2] * m[0][2] + m[0][3]&#xD;&#xA;        vy = i[0] * m[1][0] + i[1] * m[1][1] + i[2] * m[1][2] + m[1][3]&#xD;&#xA;        vz = i[0] * m[2][0] + i[1] * m[2][1] + i[2] * m[2][2] + m[2][3]&#xD;&#xA;        vw = i[0] * m[3][0] + i[1] * m[3][1] + i[2] * m[3][2] + m[3][3]&#xD;&#xA;&#xD;&#xA;        if vw != 0:&#xD;&#xA;            vx /= vw&#xD;&#xA;            vy /= vw&#xD;&#xA;            vz /= vw&#xD;&#xA;        return [vx,vy,vz,vw]&#xD;&#xA;&#xD;&#xA;    # main render function&#xD;&#xA;    def draw(self):&#xD;&#xA;&#xD;&#xA;        # update rotation matrices&#xD;&#xA;        self.rotx += self.rotation_speed&#xD;&#xA;        self.roty += self.rotation_speed&#xD;&#xA;        self.rotz += self.rotation_speed&#xD;&#xA;        self.update_rotx(); self.update_roty(); self.update_rotz()&#xD;&#xA;&#xD;&#xA;        triangles_to_draw = []&#xD;&#xA;&#xD;&#xA;        # loop through triangles in model&#xD;&#xA;        for tri in self.model:&#xD;&#xA;            &#xD;&#xA;            # create copy of triangle to project&#xD;&#xA;            tricopy = copy.deepcopy(tri)&#xD;&#xA;            proj_points = []&#xD;&#xA;&#xD;&#xA;            # skip 4th element in triangle because it's color&#xD;&#xA;            for i, _ in enumerate(tri):&#xD;&#xA;                if i == 3:&#xD;&#xA;                    continue&#xD;&#xA;                &#xD;&#xA;                # rotate triangles&#xD;&#xA;                if self.rotation[0] == 1:&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_x)&#xD;&#xA;                if self.rotation[1] == 1:&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_y)&#xD;&#xA;                if self.rotation[2] == 1:&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.rotation_z)&#xD;&#xA;                &#xD;&#xA;            # calculate normal of triangle&#xD;&#xA;            line1 = [&#xD;&#xA;                tricopy[1][0] - tricopy[0][0],&#xD;&#xA;                tricopy[1][1] - tricopy[0][1],&#xD;&#xA;                tricopy[1][2] - tricopy[0][2],&#xD;&#xA;            ]&#xD;&#xA;&#xD;&#xA;            line2 = [&#xD;&#xA;                tricopy[2][0] - tricopy[0][0],&#xD;&#xA;                tricopy[2][1] - tricopy[0][1],&#xD;&#xA;                tricopy[2][2] - tricopy[0][2],&#xD;&#xA;            ]&#xD;&#xA;&#xD;&#xA;            Nx = line1[1] * line2[2] - line1[2] * line2[1]&#xD;&#xA;            Ny = line1[2] * line2[0] - line1[0] * line2[2]&#xD;&#xA;            Nz = line1[0] * line2[1] - line1[1] * line2[0]&#xD;&#xA;            l = math.sqrt(Nx * Nx + Ny * Ny + Nz * Nz)&#xD;&#xA;            Nx  /= l; Ny /= l; Nz /= l &#xD;&#xA;&#xD;&#xA;            # draw only if triangles normal compared with cameras normal is &lt; 0&#xD;&#xA;            if (Nx * (tricopy[0][0] - self.camera_pos[0]) + Ny * (tricopy[0][1] - self.camera_pos[1]) + Nz * (tricopy[0][2] - self.camera_pos[2])) &lt; 0:&#xD;&#xA;&#xD;&#xA;                for i, _ in enumerate(tri):&#xD;&#xA;                    # skip 4th element in triangle because it's color&#xD;&#xA;                    if i == 3: &#xD;&#xA;                        continue&#xD;&#xA;&#xD;&#xA;                    # camera and projection matrices&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.camera)&#xD;&#xA;                    tricopy[i] = self.Matrix_MultiplyVector(tricopy[i], self.projection)&#xD;&#xA;&#xD;&#xA;                    tricopy[i][0] += 2; tricopy[i][0] *= 0.25 * screen_width&#xD;&#xA;                    tricopy[i][1] += 2; tricopy[i][1] *= 0.25 * screen_height&#xD;&#xA;                    &#xD;&#xA;                # calculate mean Z value and add triangles projected points to list&#xD;&#xA;                mean_z = (tricopy[0][2] + tricopy[1][2] + tricopy[2][2]) / 3&#xD;&#xA;                proj_points = [(tricopy[0][0], tricopy[0][1]), (tricopy[1][0], tricopy[1][1]), (tricopy[2][0], tricopy[2][1]), tricopy[3], mean_z]&#xD;&#xA;                triangles_to_draw.append(proj_points)&#xD;&#xA;        &#xD;&#xA;        # sort by mean Z value&#xD;&#xA;        triangles_to_draw.sort(key=lambda i: (i[4]), reverse=True)&#xD;&#xA;        &#xD;&#xA;        # draw triangles&#xD;&#xA;        for i, tri in enumerate(triangles_to_draw):&#xD;&#xA;&#xD;&#xA;            if self.color_fill == 1:&#xD;&#xA;                try:&#xD;&#xA;                    pygame.draw.polygon(screen, tri[3], (tri[0], tri[1], tri[2]))&#xD;&#xA;                except:&#xD;&#xA;                    print(tri[3])&#xD;&#xA;            if self.wireframes == 1:&#xD;&#xA;                pygame.draw.polygon(screen, [230,168,50], (tri[0], tri[1], tri[2]), 1)&#xD;&#xA;&#xD;&#xA;renderer = Renderer()&#xD;&#xA;&#xD;&#xA;# main loop&#xD;&#xA;while run:&#xD;&#xA;&#xD;&#xA;    screen.fill([47,79,83])&#xD;&#xA;    mx, my = pygame.mouse.get_pos()&#xD;&#xA;&#xD;&#xA;    for event in pygame.event.get():&#xD;&#xA;        if event.type == pygame.QUIT:&#xD;&#xA;            run = False&#xD;&#xA;        &#xD;&#xA;        if event.type == pygame.KEYDOWN:&#xD;&#xA;            if event.key == pygame.K_ESCAPE:&#xD;&#xA;                run = False&#xD;&#xA;                &#xD;&#xA;    keys = pygame.key.get_pressed()&#xD;&#xA;&#xD;&#xA;    # draw model&#xD;&#xA;    renderer.draw()&#xD;&#xA;&#xD;&#xA;    clock.tick(FPS)&#xD;&#xA;    pygame.display.flip()&#xD;&#xA;&#xD;&#xA;pygame.quit()&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="41337" PostHistoryTypeId="1" PostId="13617" RevisionGUID="24dd5d89-e8f3-40e2-9ba9-2901f89ff22d" CreationDate="2023-08-04T20:35:49.563" UserId="20354" Text="3D engine projection distortions" ContentLicense="CC BY-SA 4.0" />
  <row Id="41338" PostHistoryTypeId="3" PostId="13617" RevisionGUID="24dd5d89-e8f3-40e2-9ba9-2901f89ff22d" CreationDate="2023-08-04T20:35:49.563" UserId="20354" Text="|3d|projections|perspective|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41342" PostHistoryTypeId="2" PostId="13618" RevisionGUID="8a1d309a-b6d1-4306-9932-e7cc3098b720" CreationDate="2023-08-05T20:25:30.763" UserId="20359" Text="I'm trying to convert images that have a single object with an outline to a transparent background.  I'm currently using the image/png package in golang but can switch to any language thats more appropriate for the task.&#xD;&#xA;&#xD;&#xA;What i'm trying so far is to floodfill the white surrounding background with transparency, convert the outline to a transparency and then do the floodfill again to catch the white area surrounding the image.  This isn't working well so far.  I've tried using a two phase approach where I do a floodfill with a distance tolerance to get the white area outside of the outline. A similar approach to removing the outline then another tolerance floodfill to get the rest of the white area inside the outline.  &#xD;&#xA;&#xD;&#xA;My approaches have been too simple when it comes to the outline though and while I get parts of it, I can't come up with an approach that gets the whole outline taking into account the various shading. One approach, came closest to working which is to &quot;erase&quot; the area within a fixed number pixels away from the outer white area but even that had problems.&#xD;&#xA;&#xD;&#xA;Here are examples of before and after images that demonstrate what i'm trying to accomplish.  This seems like it should be simple but i'm stuck.&#xD;&#xA;&#xD;&#xA;Thanks in advance for any help.&#xD;&#xA;&#xD;&#xA;[![image without transparency][1]][1]&#xD;&#xA;&#xD;&#xA;[![image with transparency (hand processed)][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/fo1aT.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/FoYwb.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41344" PostHistoryTypeId="1" PostId="13618" RevisionGUID="8a1d309a-b6d1-4306-9932-e7cc3098b720" CreationDate="2023-08-05T20:25:30.763" UserId="20359" Text="Automatically convert field of white and an outline to transparent background" ContentLicense="CC BY-SA 4.0" />
  <row Id="41345" PostHistoryTypeId="3" PostId="13618" RevisionGUID="8a1d309a-b6d1-4306-9932-e7cc3098b720" CreationDate="2023-08-05T20:25:30.763" UserId="20359" Text="|transparency|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41346" PostHistoryTypeId="50" PostId="12746" RevisionGUID="0730cf0a-2439-43ec-b5eb-07ffaa0b6dc8" CreationDate="2023-08-06T10:04:10.507" UserId="-1" />
  <row Id="41347" PostHistoryTypeId="50" PostId="2146" RevisionGUID="2bcf81cf-79d4-4bd1-9378-dbd0fe0ee6f9" CreationDate="2023-08-06T12:01:40.193" UserId="-1" />
  <row Id="41348" PostHistoryTypeId="50" PostId="11048" RevisionGUID="8dc7e0b9-202d-4063-8de9-02373a2d4b30" CreationDate="2023-08-06T18:06:35.827" UserId="-1" />
  <row Id="41349" PostHistoryTypeId="50" PostId="11049" RevisionGUID="a0935806-351e-4c80-84e9-75813c5426d5" CreationDate="2023-08-06T21:03:40.433" UserId="-1" />
  <row Id="41373" PostHistoryTypeId="2" PostId="13622" RevisionGUID="9269f1fa-037f-4b1e-835d-41d89301f31c" CreationDate="2023-08-09T12:55:06.443" UserDisplayName="user1703" Text="You can try the following steps:&#xD;&#xA;&#xD;&#xA;- traverse the image until you touch the object (by finding a point with a color significantly different from that of the white strip - check the normal variations in the white strip).&#xD;&#xA;&#xD;&#xA;- when you have this point, perform contour following to delineate the object, and form a closed curve.&#xD;&#xA;&#xD;&#xA;- make all area outside of the curve transparent (by seed filling).&#xD;&#xA;&#xD;&#xA;- finally, create a matte by considering the pixels inside the outline and weight their transparency proportionally to the difference between white and the local color." ContentLicense="CC BY-SA 4.0" />
  <row Id="41375" PostHistoryTypeId="2" PostId="13623" RevisionGUID="85f6e817-1db6-493a-8d7e-1f7488f2223e" CreationDate="2023-08-10T08:09:32.380" UserId="20377" Text="I am looking at many games like Dead Island 2, Red Dead Redemption 2, and Minecraft and I see that while the render distance grows, the CPU load grows with it. Why could this be happening? Lack of optimization or fundamental limitations?&#xD;&#xA;&#xD;&#xA;How is higher render distance so CPU-intensive? Is it because of a higher number of draw calls? If so, can’t they just minimize draw calls by batching objects or other techniques?&#xD;&#xA;&#xD;&#xA;Does a high draw distance always imply high CPU usage, or is something that could be optimized, but sometimes isn't?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41377" PostHistoryTypeId="1" PostId="13623" RevisionGUID="85f6e817-1db6-493a-8d7e-1f7488f2223e" CreationDate="2023-08-10T08:09:32.380" UserId="20377" Text="How does higher draw distance strain the CPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41378" PostHistoryTypeId="3" PostId="13623" RevisionGUID="85f6e817-1db6-493a-8d7e-1f7488f2223e" CreationDate="2023-08-10T08:09:32.380" UserId="20377" Text="|rendering|performance|optimisation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41379" PostHistoryTypeId="2" PostId="13624" RevisionGUID="805ebd3d-b2fd-4e7f-b45b-7effcdbdb6ae" CreationDate="2023-08-10T11:23:08.690" UserId="13273" Text="This depends on the application.&#xD;&#xA;&#xD;&#xA;If the rendering distance is larger, more objects have to be managed by the CPU. For example Minecraft, there you have &quot;chunks&quot; that store the block information of an area of 16x16x256 blocks. When you move, new &quot;chunks&quot; come into the view area, so the CPU has to load or generate them.&#xD;&#xA;&#xD;&#xA;In other games, new objects (geometry) must be loaded from disk and sent to the GPU. Modern games have so many textures and models that the GPU is not able to store them all. So the CPU has to decide which textures and models are needed.&#xD;&#xA;&#xD;&#xA;Other aspects can also play a role. For example, animals walking around. As long as you are too far away to see them, they don't need to be updated. But if the rendering distance is greater, they should move." ContentLicense="CC BY-SA 4.0" />
  <row Id="41381" PostHistoryTypeId="2" PostId="13625" RevisionGUID="e9b8408e-6927-4b7f-b4e0-a04d8080dc63" CreationDate="2023-08-10T11:27:34.400" UserId="19537" Text="I recently stumbled into this question:&#xD;&#xA;Say, for example, we are doing mean-free-path sampling (distance sampling) in a scattering medium and to keep it simple, let's only consider the single scattering case, but I'm only interested in part of the region, as shown in the following figure. It won't feel like it is a problem if I just **discard all the samples outside of region**. &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;However, when I revisit the mathematical expression of the expectation, I found that:&#xD;&#xA;$$&#xD;&#xA;\mathbb{E}(\hat{I}) = \int_0^{+\inf} \underbrace{\frac{f(x)}{p(x)}}_{\text{estimator}} \underbrace{p(x)}_{\text{PDF}} \text{d}x&#xD;&#xA;$$&#xD;&#xA;Yeah, if the PDF term in the denominator of the estimator and the PDF of the sample $x$ are the same, these two terms will cancel each other out and we are left with the integral we want. Yet, **discarding all the samples outside of the interested region** is seemed to alter the PDF of the samples. I think that, for now, all the recorded samples have a conditional PDF:&#xD;&#xA;$$&#xD;&#xA;p(x|x\text{ in region})&#xD;&#xA;$$&#xD;&#xA;If we are using the original estimator, for example, if we sample $x$ from an exponential distribution, we will normally have this estimator:&#xD;&#xA;$$&#xD;&#xA;\frac{f(x)}{\sigma_t \exp(-\sigma_t x)}&#xD;&#xA;$$&#xD;&#xA;Since we are expecting that when we sample $x$ according to $-\log(1 - x)/\sigma_t$，the sample $x$ actually follows the same distribution, but it seems that when we discard samples, these two PDF terms can not be cancelled out.&#xD;&#xA;&#xD;&#xA;My question is:&#xD;&#xA;- Does this mean that we can should modify the PDF in the estimator according to the region we are interested? Am I right about this?&#xD;&#xA;- What should be the correct distribution of the samples? A exponential distribution &quot;confined&quot; in a small region?&#xD;&#xA;- What is the case for more bounces? If the one-bounce case is biased, does this mean that the multi-bounce case is also biased?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EFHR0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41383" PostHistoryTypeId="1" PostId="13625" RevisionGUID="e9b8408e-6927-4b7f-b4e0-a04d8080dc63" CreationDate="2023-08-10T11:27:34.400" UserId="19537" Text="Confusion about the bias during Monte Carlo integration" ContentLicense="CC BY-SA 4.0" />
  <row Id="41384" PostHistoryTypeId="3" PostId="13625" RevisionGUID="e9b8408e-6927-4b7f-b4e0-a04d8080dc63" CreationDate="2023-08-10T11:27:34.400" UserId="19537" Text="|mathematics|sampling|importance-sampling|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41385" PostHistoryTypeId="5" PostId="13624" RevisionGUID="094d7e44-cffb-400d-a994-cb3282564f25" CreationDate="2023-08-10T11:28:28.157" UserId="13273" Comment="added 326 characters in body" Text="This depends on the application.&#xD;&#xA;&#xD;&#xA;If the rendering distance is larger, more objects have to be managed by the CPU. For example Minecraft, there you have &quot;chunks&quot; that store the block information of an area of 16x16x256 blocks. When you move, new &quot;chunks&quot; come into the view area, so the CPU has to load or generate them.&#xD;&#xA;&#xD;&#xA;In other games, new objects (geometry) must be loaded from disk and sent to the GPU. Modern games have so many textures and models that the GPU is not able to store them all. So the CPU has to decide which textures and models are needed.&#xD;&#xA;&#xD;&#xA;Other aspects can also play a role. For example, animals walking around. As long as you are too far away to see them, they don't need to be updated. But if the rendering distance is greater, they should move.&#xD;&#xA;&#xD;&#xA;More rendering calls also play a role. However, not as strongly as the aspects mentioned above. Because in general, the number of different geometries that need to be rendered should not be too large. And with instance rendering, objects with the same geometry can be rendered multiple times with just one drawing call.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41386" PostHistoryTypeId="5" PostId="13624" RevisionGUID="a3ff5130-a5b4-40ff-88d7-e8d12cf69c29" CreationDate="2023-08-10T11:35:09.717" UserId="13273" Comment="added 326 characters in body" Text="This depends on the application.&#xD;&#xA;&#xD;&#xA;If the rendering distance is larger, more objects have to be managed by the CPU. For example Minecraft, there you have &quot;chunks&quot; that store the block information of an area of 16x16x256 blocks. When you move, new &quot;chunks&quot; come into the view area, so the CPU has to load or generate them.&#xD;&#xA;&#xD;&#xA;In other games, new objects (geometry) must be loaded from disk and sent to the GPU. Modern games have so many textures and models that the GPU is not able to store them all. So the CPU has to decide which textures and models are needed.&#xD;&#xA;&#xD;&#xA;Other aspects can also play a role. For example, animals walking around. As long as you are too far away to see them, they don't need to be updated. But if the rendering distance is greater, they should move.&#xD;&#xA;&#xD;&#xA;More rendering calls also play a role. However, not as strongly as the aspects mentioned above. Because in general, the number of different geometries that need to be rendered should not be too large. And with instance rendering, objects with the same geometry can be rendered multiple times with just one drawing call.&#xD;&#xA;&#xD;&#xA;&gt; Does a high draw distance always imply high CPU usage, or is something that could be optimized, but sometimes isn't?&#xD;&#xA;&#xD;&#xA;No. The render distance is part of the projection matrix. When comparing two render calls:&#xD;&#xA;&#xD;&#xA; 1. **Entire scenario is in range:** &#xD;&#xA; 2. **Entire scenario is in range, but render distance is doubled:**&#xD;&#xA;&#xD;&#xA;The rendering time will be the same.&#xD;&#xA;&#xD;&#xA;Even with drawing calls for each geometry in the world, both renderings will take the same amount of time (on CPU). On GPU, of course, things look different..." ContentLicense="CC BY-SA 4.0" />
  <row Id="41387" PostHistoryTypeId="2" PostId="13626" RevisionGUID="4822a6e5-a97a-4f54-b91d-b47eb03035ad" CreationDate="2023-08-10T11:47:26.807" UserId="7952" Text="There are a number of reasons CPU usage goes up with viewing distance but the fundamental reason is the number of objects that need to be processed goes up.&#xD;&#xA;&#xD;&#xA;Increasing viewing distance linearly increases the viewing area exponentially. Which means the number of items that must be considered for drawing increases exponentially.&#xD;&#xA;&#xD;&#xA;There are many techniques to mitigate this, some of which you suggested but at the end of the day the shear number of items that needs processing is going to drive CPU usage up.&#xD;&#xA;&#xD;&#xA;There are GPU based algorithms that can process millions of items but incorporating those into a game engine is non-trivial especially for a game that has already been published. There are also hardware limitations that must be considered when implementing GPU based algorithms.&#xD;&#xA;&#xD;&#xA;Also, there are many games that have very large viewing distances. World of Warcraft comes to mind as an older game that allowed scenery to be viewed for many kilometers, and it did so on &quot;ancient&quot; hardware. So it is possible to overcome this problem.&#xD;&#xA;&#xD;&#xA;At the end of the day it is going to depend on the goals of the project. The skills of the development team and the capabilities of the underlying hardware." ContentLicense="CC BY-SA 4.0" />
  <row Id="41389" PostHistoryTypeId="5" PostId="13626" RevisionGUID="8a6e3d5f-9e3d-4b9f-aff9-e741d373cc83" CreationDate="2023-08-10T11:58:09.460" UserId="7952" Comment="changed exponential to quadratic" Text="There are a number of reasons CPU usage goes up with viewing distance but the fundamental reason is the number of objects that need to be processed goes up.&#xD;&#xA;&#xD;&#xA;Increasing viewing distance linearly increases the viewing area quadratically. Which means the number of items that must be considered for drawing increases quadratically.&#xD;&#xA;&#xD;&#xA;There are many techniques to mitigate this, some of which you suggested but at the end of the day the shear number of items that needs processing is going to drive CPU usage up.&#xD;&#xA;&#xD;&#xA;There are GPU based algorithms that can process millions of items but incorporating those into a game engine is non-trivial especially for a game that has already been published. There are also hardware limitations that must be considered when implementing GPU based algorithms.&#xD;&#xA;&#xD;&#xA;Also, there are many games that have very large viewing distances. World of Warcraft comes to mind as an older game that allowed scenery to be viewed for many kilometers, and it did so on &quot;ancient&quot; hardware. So it is possible to overcome this problem.&#xD;&#xA;&#xD;&#xA;At the end of the day it is going to depend on the goals of the project. The skills of the development team and the capabilities of the underlying hardware." ContentLicense="CC BY-SA 4.0" />
  <row Id="41390" PostHistoryTypeId="2" PostId="13627" RevisionGUID="db974e19-c8ee-45af-a543-add2cb2c92b8" CreationDate="2023-08-10T12:30:15.570" UserDisplayName="user1703" Text="As said in other comments, the increased workload can be due to more objects visible, needing rendering (though this is a partial explanation because in a first approximation the rendering effort depends on the surface area to be painted).&#xD;&#xA;&#xD;&#xA;A possible cure is to handle several object geometries with simplified details and select the one to be rendered depending on the viewing distance. This principle is similar what is done in mipmapping for textures (texture images stored with different resolutions), though harder to implement with discrete surfaces." ContentLicense="CC BY-SA 4.0" />
  <row Id="41392" PostHistoryTypeId="50" PostId="13358" RevisionGUID="ee8ce38a-3eb9-4957-834d-1950c906201b" CreationDate="2023-08-11T13:06:20.800" UserId="-1" />
  <row Id="41393" PostHistoryTypeId="50" PostId="9199" RevisionGUID="816771ad-5e16-49e6-87b6-0ee53162caa8" CreationDate="2023-08-11T14:01:50.327" UserId="-1" />
  <row Id="41395" PostHistoryTypeId="2" PostId="13628" RevisionGUID="be8b3a8f-c3f4-49f6-87f0-c4bb2d2bad5a" CreationDate="2023-08-12T19:46:32.450" UserId="20388" Text="I am writing a program to display 3-dimensional lattices (honeycombs) using raymarching and reflections. I made a simple cubic honeycomb to start. The usual method is to use a repetition operator, by taking the fractional part of the input point before feeding it to some other SDF:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;float sceneSDF(vec3 pt) {&#xD;&#xA;    return sdf(fract(pt));&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;I have an example here: [Cubic honeycomb][1]&#xD;&#xA;&#xD;&#xA;However, for some other 3D lattices, like the rhombic dodecahedral lattice and hexagonal prism lattice, it's very difficult to use simple repetition operators. But, it is possible to achieve the desired effect using reflections. We simply make the faces of the polyhedron reflective, and multiply the reflected color by an &quot;attenuation&quot; value which decreases with each reflection bounce. The exact implementation I use is a bit more elaborate than that, however; that's why I have an example.&#xD;&#xA;&#xD;&#xA;I have an example here: [Cubic honeycomb using reflections][2]&#xD;&#xA;&#xD;&#xA;This achieves the desired effect, however leaves ugly borders between reflected images. I am fairly sure that this is due to the attenuation value being scaled discretely with each bounce, rather than continuously. Is there some sort of interpolation, or another way of remedying this?&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/mljcWw&#xD;&#xA;  [2]: https://www.shadertoy.com/view/dljyDw#" ContentLicense="CC BY-SA 4.0" />
  <row Id="41397" PostHistoryTypeId="1" PostId="13628" RevisionGUID="be8b3a8f-c3f4-49f6-87f0-c4bb2d2bad5a" CreationDate="2023-08-12T19:46:32.450" UserId="20388" Text="&quot;Smoothing out&quot; raymarched reflections" ContentLicense="CC BY-SA 4.0" />
  <row Id="41398" PostHistoryTypeId="3" PostId="13628" RevisionGUID="be8b3a8f-c3f4-49f6-87f0-c4bb2d2bad5a" CreationDate="2023-08-12T19:46:32.450" UserId="20388" Text="|glsl|gpu|webgl|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41399" PostHistoryTypeId="2" PostId="13629" RevisionGUID="ea4b1920-c310-43bc-b6d5-d78bbd91734f" CreationDate="2023-08-12T22:55:29.397" UserId="7462" Text="Assume that in 3D we have a polytope defined by the intersection of halfspaces.&#xD;&#xA;&#xD;&#xA;A half space is the set of all solutions of a linear inequality $P = N \cdot x + c \leq 0$ Where $N$ is the normal to the half space.&#xD;&#xA;&#xD;&#xA;The polytope is thus the boundary of $\cap_{i=0} P_i$ $P_i = N_i \cdot x + c_i \leq 0$.&#xD;&#xA;&#xD;&#xA;In 3D all vertices must be intersections of at least 3 planes. i.e. all vertices are a subset of all points such that:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;$$P_i = P_j = P_k = 0$$&#xD;&#xA;&#xD;&#xA;Which is a trivial 3x3 system that can be easily solved.&#xD;&#xA;&#xD;&#xA;However, the total number of points that you get out of this is exponentially larger than the actual number of points on the polytope. &#xD;&#xA;&#xD;&#xA;For example in this diagram:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The top plane intersects the other 2 at points which are not vertices of the polytope.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/c48wo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41401" PostHistoryTypeId="1" PostId="13629" RevisionGUID="ea4b1920-c310-43bc-b6d5-d78bbd91734f" CreationDate="2023-08-12T22:55:29.397" UserId="7462" Text="Finding vertices of a polytope?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41402" PostHistoryTypeId="3" PostId="13629" RevisionGUID="ea4b1920-c310-43bc-b6d5-d78bbd91734f" CreationDate="2023-08-12T22:55:29.397" UserId="7462" Text="|mathematics|computational-geometry|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41403" PostHistoryTypeId="2" PostId="13630" RevisionGUID="04606e6c-c5c9-46d6-8c53-15b95743f75c" CreationDate="2023-08-13T14:59:03.523" UserId="445" Text="(I'm going to use the word “polyhedron” instead of “polytope” because I haven't considered how to generalize it to more dimensions.)&#xD;&#xA;&#xD;&#xA;1. Being constructed of the intersection of half-spaces, the polyhedron must be convex; the interior volume is a region containing none of the planes.&#xD;&#xA;&#xD;&#xA;2. We can classify the intersection points of 3 unequal planes as follows:&#xD;&#xA;&#xD;&#xA;    * There cannot be an intersection point within the polyhedron, because per (1), none of the planes intersect the polyhedron.&#xD;&#xA;    * If it is on the surface, then it must be a vertex; it cannot lie on an edge or face because if it did, that would contradict the 3 planes defining a point.&#xD;&#xA;    * If it is outside the polyhedron, then it must not be a vertex.&#xD;&#xA;&#xD;&#xA;3. If an intersection point lies within the outside half of *any one* of the half-spaces making up the polyhedron, then it cannot be inside or on the surface of the polyhedron per (1), and therefore cannot be a vertex per (2).&#xD;&#xA;&#xD;&#xA;4. If an intersection point *does not* lie within the outside half of any half-space, then it cannot be inside per (1), so it must be on the surface of the polyhedron, and therefore per (2) must be a vertex.&#xD;&#xA;&#xD;&#xA;Therefore, it suffices to discard all intersections which are outside _any one_ of the half-spaces.&#xD;&#xA;&#xD;&#xA;This can be seen as applying the _separating axis theorem_ to the points; every plane defines a potential separating axis." ContentLicense="CC BY-SA 4.0" />
  <row Id="41405" PostHistoryTypeId="2" PostId="13631" RevisionGUID="dea66405-f8ba-472b-8661-bc3b18e5e35c" CreationDate="2023-08-13T15:22:17.587" UserDisplayName="user1703" Text="You can use an incremental approach.&#xD;&#xA;&#xD;&#xA;In 3D, it works as follows:&#xD;&#xA;&#xD;&#xA;- Assume that as some point you have constructed the (possibly open) polytope defined by the $k$ first plane.&#xD;&#xA;&#xD;&#xA;- Consider the next plane and change the coordinate system so that the equation simplifies to $z=0$.&#xD;&#xA;&#xD;&#xA;- For every edge of the polytope, check if the endpoints belong to the same half-plane defined by the next plane.&#xD;&#xA;&#xD;&#xA;- If both have $z&gt;0$, keep the edge; if both have $z&lt;0$, discard the edge; otherwise, compute the intersection point of the edge with the plane and trim the edge. Finally, join the intersection points to form a convex section polygon.&#xD;&#xA;&#xD;&#xA;- Repeat with the remaining planes.&#xD;&#xA;&#xD;&#xA;This method cannot avoid the $O(n^d)$ behavior in the worst case (no method can) but if you are lucky it can keep the number of useless vertex computations to a low value. (At best, $O(nm)$ for $n$ planes and $m$ vertices in the solution.)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41407" PostHistoryTypeId="5" PostId="13631" RevisionGUID="2db841b4-83c1-413b-889c-2a8c6ad486ea" CreationDate="2023-08-13T15:27:29.563" UserDisplayName="user1703" Comment="added 14 characters in body" Text="You can use an incremental approach.&#xD;&#xA;&#xD;&#xA;In 3D, it works as follows:&#xD;&#xA;&#xD;&#xA;- Assume that as some point you have constructed the (possibly open) polytope defined by the $k$ first plane.&#xD;&#xA;&#xD;&#xA;- Consider the next plane and change the coordinate system so that the equation simplifies to $z=0$.&#xD;&#xA;&#xD;&#xA;- For every edge of the polytope, check if the endpoints belong to the same half-plane defined by the next plane.&#xD;&#xA;&#xD;&#xA;- If both have $z&gt;0$, keep the edge; if both have $z&lt;0$, discard the edge; otherwise, compute the intersection point of the edge with the plane and trim the edge. Finally, join the intersection points to form a convex section polygon.&#xD;&#xA;&#xD;&#xA;- Repeat with the remaining planes.&#xD;&#xA;&#xD;&#xA;This method cannot avoid the $O(n^3)$ behavior in the worst case (no method can) but if you are lucky it can keep the number of useless vertex computations to a low value. (At best, $O(nm)$ intersections for $n$ planes and $m$ vertices in the solution.)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41408" PostHistoryTypeId="5" PostId="13631" RevisionGUID="a8d25ccd-383b-45f7-b63f-c96895034ac0" CreationDate="2023-08-13T16:20:32.013" UserDisplayName="user1703" Comment="added 1 character in body" Text="You can use an incremental approach.&#xD;&#xA;&#xD;&#xA;In 3D, it works as follows:&#xD;&#xA;&#xD;&#xA;- Assume that as some point you have constructed the (possibly open) polytope defined by the $k$ first planes.&#xD;&#xA;&#xD;&#xA;- Consider the next plane and change the coordinate system so that the equation simplifies to $z=0$.&#xD;&#xA;&#xD;&#xA;- For every edge of the polytope, check if the endpoints belong to the same half-plane defined by the plane ($z$ sign).&#xD;&#xA;&#xD;&#xA;- If both have $z&gt;0$, keep the edge; if both have $z&lt;0$, discard the edge; otherwise, compute the intersection point of the edge with the plane and trim the edge. Finally, join the intersection points to form a convex section polygon.&#xD;&#xA;&#xD;&#xA;- Repeat with the remaining planes.&#xD;&#xA;&#xD;&#xA;This method cannot avoid the $O(n^3)$ behavior in the worst case (no method can) but if you are lucky it can keep the number of useless vertex computations to a low value. (At best, $O(nm)$ intersections for $n$ planes and $m$ vertices in the solution.)&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41409" PostHistoryTypeId="5" PostId="13610" RevisionGUID="cdbd6294-a2ca-4452-a812-e89e3f181153" CreationDate="2023-08-14T01:29:19.657" UserId="9600" Comment="added 18 characters in body" Text="&gt; The projection matrix is then essentially `K * [R | T]`&#xD;&#xA;&#xD;&#xA;Is incorrect, actually the K Matrix is similar to projection matrix and&#xD;&#xA;the R|T is called *camera transform matrix* or *view transform matrix*&#xD;&#xA;Or called *extrinsic matrix*. So focus on the projection stuff and forget about camera transform,&#xD;&#xA;what is the difference between *K Matrix* and Perspective Projection &#xD;&#xA;Matrix(call it *P Matrix* later)?&#xD;&#xA;&#xD;&#xA;- For *K Matrix* it transform 3D points to 2D pixels in image space.&#xD;&#xA;- For *P Matrix* it transform 3D points to NDC space.&#xD;&#xA;&#xD;&#xA;Take a look at two matrices:&#xD;&#xA;&#xD;&#xA;$$K = \begin{bmatrix}f_x&amp;   0&amp;  c_x\\  0&amp; f_y&amp;  c_y\\&#xD;&#xA;0  &amp;  0 &amp;    1\\\end{bmatrix}$$&#xD;&#xA;&#xD;&#xA;$$P = \begin{bmatrix}&#xD;&#xA;\frac{1}{t*a}&amp;   0&amp;  0&amp; 0\\0&amp; \frac{1}{t}&amp;  0&amp; 0\\&#xD;&#xA;0  &amp;  0 &amp;    A&amp; B&amp;\\ 0  &amp;  0 &amp;    -1&amp; 0\\ \end{bmatrix}$$&#xD;&#xA;$$t=tan(\frac{fovy}{2})$$&#xD;&#xA;$$a=\frac{width}{height}$$&#xD;&#xA;&#xD;&#xA;Let's add perspective divide and show the result of the above two matrices:&#xD;&#xA;&#xD;&#xA;Intrinsic case: $$x_{2d} = \frac{x_0}{z_0 * \frac{1}{f_x}} + c_x$$&#xD;&#xA;&#xD;&#xA;Perspective case: $$x_{2d} = \frac{x_0}{-z_0(t*a)}$$&#xD;&#xA;&#xD;&#xA;Similar with some difference.&#xD;&#xA;&#xD;&#xA;The image space: Origin from left-top corner&#xD;&#xA;so should add Cx Cy as the offset from center to left-top corner.&#xD;&#xA;And in NDC space we assume Z-axis direct out of screen so P(3,2) = -1." ContentLicense="CC BY-SA 4.0" />
  <row Id="41414" PostHistoryTypeId="50" PostId="9591" RevisionGUID="3098fee4-b05b-4712-bbd4-000617dd1886" CreationDate="2023-08-15T04:10:06.110" UserId="-1" />
  <row Id="41415" PostHistoryTypeId="2" PostId="13633" RevisionGUID="5a220f07-7b13-4069-ad1a-17d8aacb9866" CreationDate="2023-08-15T10:55:35.720" UserId="20400" Text="I am following a tutorial on pathtracing ([path tracing course][1]) and i am implementing my own pathtracer on the way which is loosely based on the provided source code of the tutorial ([source code][2]). At the point of the tutorial where i am now, the author is showing how to importance sample different material brdfs like the lambert diffuse brdf and the phong brdf ([Material Importance Sampling][3]).&#xD;&#xA;&#xD;&#xA;For the importance sampling of the specular part of the phong brdf a cosine lobe with specular exponent n around the reflected direction (R vector of the phong brdf) has to be sampled according to [importance sampling note][4].&#xD;&#xA;&#xD;&#xA;The source code for importance sampling of the phong brdf is the following (slightly modified by me):&#xD;&#xA;&#xD;&#xA;    class MaterialPhong : public Material&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;        const Texture* k_d;&#xD;&#xA;        const Texture* k_s;&#xD;&#xA;        const Texture* s;&#xD;&#xA;    &#xD;&#xA;        MaterialPhong(const Texture* k_d, const Texture* k_s, const Texture* s) :&#xD;&#xA;            k_d(k_d), k_s(k_s), s(s)&#xD;&#xA;        {&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // compute phong brdf&#xD;&#xA;        // n  - normal at hitpoint&#xD;&#xA;        // l  - light vector (wi)&#xD;&#xA;        // v  - camera vector (wo)&#xD;&#xA;        // kd - diffuse constant&#xD;&#xA;        // ks - specular constant&#xD;&#xA;        // shininess - phong exponent&#xD;&#xA;        vec3 brdf(const vec3&amp; n, const vec3&amp; l, const vec3&amp; v,&#xD;&#xA;                  const vec3&amp; kd, const vec3&amp; ks, float shininess) const&#xD;&#xA;        {&#xD;&#xA;            // compute lambert diffuse&#xD;&#xA;            vec3 diffuse = kd / pi;&#xD;&#xA;            &#xD;&#xA;            // compute phong specular&#xD;&#xA;            float cosRV = std::max(dot(reflect(-l, n), v), 0.0f);&#xD;&#xA;            float normalization = (shininess + 2.0f) / (2.0f * pi);&#xD;&#xA;            vec3 specular = ks * normalization * pow(cosRV, shininess);&#xD;&#xA;            &#xD;&#xA;            // return combined result&#xD;&#xA;            return diffuse + specular;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // importance sampling of the phong brdf&#xD;&#xA;        // ray  - ray which hits the surface&#xD;&#xA;        // hr   - hitrecord contains information of the surface hitpoint (normal, texcoords, etc.)&#xD;&#xA;        // prng - random number generator for sampling&#xD;&#xA;        virtual ScatterRecord scatter(const Ray&amp; ray, const HitRecord&amp; hr, Prng&amp; prng) const override&#xD;&#xA;        {&#xD;&#xA;            // if hit on backside return&#xD;&#xA;            if (hr.backside)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // get diffuse, specular and shininess values from texture&#xD;&#xA;            vec3 kd = k_d-&gt;value(hr.texcoord);&#xD;&#xA;            vec3 ks = k_s-&gt;value(hr.texcoord);&#xD;&#xA;            float shininess = s-&gt;value(hr.texcoord).x();&#xD;&#xA;    &#xD;&#xA;            // sample the brdf&#xD;&#xA;            vec3 n = hr.normal;                     // n = normal at hitpoint&#xD;&#xA;            vec3 v = -ray.direction;                // v = wo = vector to camera&#xD;&#xA;            vec3 r = reflect(ray.direction, n);     // r = reflection vector for phong&#xD;&#xA;    &#xD;&#xA;            // use &quot;energy&quot; heuristic to decide wether a diffuse or &#xD;&#xA;            // specular sample should be taken&#xD;&#xA;            float sumKd = kd.x() + kd.y() + kd.z(); // red (x), green (y) and blue (z) &quot;wavelength&quot;-energies added&#xD;&#xA;            float sumKs = ks.x() + ks.y() + ks.z(); // to compute &quot;total energy&quot; from all wavelengths&#xD;&#xA;            float sum = sumKd + sumKs;              // sum it, so the probabilities add to 1&#xD;&#xA;            &#xD;&#xA;            // compute&#xD;&#xA;            float specularProbability = sumKs / sum;&#xD;&#xA;            specularProbability = clamp(specularProbability, 0.1, 0.9); // keep the probability between 0.1 and 0.9&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            // generate phong distributed sample light vector l (wi) around reflection vector&#xD;&#xA;            vec3 l; // this is the new direction&#xD;&#xA;            &#xD;&#xA;            // sample brdf depending on the random number&#xD;&#xA;            if (prng.in01() &lt; specularProbability) {&#xD;&#xA;                // act specular&#xD;&#xA;                &#xD;&#xA;                // generate phong distributed samples (phi, theta according to  &#xD;&#xA;                vec3 newDirectionAroundR = Sampler::phongWeightedOnHemisphere(shininess, prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around r (reflection vector as &quot;normal&quot; for the onb) -&gt; shading / tangent space&#xD;&#xA;                TangentSpace rts = TangentSpace(r);&#xD;&#xA;                &#xD;&#xA;                // transform back from hading / tangent space to world coordinates&#xD;&#xA;                l = normalize(rts.toWorldSpace(newDirectionAroundR));   &#xD;&#xA;            } else {&#xD;&#xA;                // act diffuse&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around n (normal)  &#xD;&#xA;                TangentSpace ts(n);&#xD;&#xA;                &#xD;&#xA;                // generate cosine distributed samples on hemisphere&#xD;&#xA;                vec3 newDirectionTS = Sampler::cosineWeightedOnHemisphere(prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // transform back from tangent space to world coordinates&#xD;&#xA;                l = normalize(ts.toWorldSpace(newDirectionTS)); &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // compute cos theta for pdf&#xD;&#xA;            float cosTheta = dot(l, n);&#xD;&#xA;            if (cosTheta &lt;= 0.0f)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // compute diffuse pdf&#xD;&#xA;            float diffusePdfValue = cosTheta / pi;&#xD;&#xA;            &#xD;&#xA;            // compute specular pdf&#xD;&#xA;            float specularPdfValue = 0.5f / pi * (shininess + 1.0f)&#xD;&#xA;                * std::pow(std::max(dot(r, l), 0.0f), shininess);&#xD;&#xA;            &#xD;&#xA;            // do &quot;lerp&quot; linear interpolation between the two depending on the specular probability&#xD;&#xA;            float pdf = mix(diffusePdfValue, specularPdfValue, specularProbability);&#xD;&#xA;    &#xD;&#xA;            // compute brdf value for wi (l) and wo (v)&#xD;&#xA;            vec3 attenuation = brdf(n, l, v, kd, ks, shininess) * cosTheta;&#xD;&#xA;            &#xD;&#xA;            // return result&#xD;&#xA;            return ScatterRecord(l, pdf, attenuation);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Now i want to write an equivalent material class for importance sampling of the blinn-phong brdf. But as i understand for the importance sampling of the specular part of the blinn phong brdf i would need to sample the cosine lobe around the half vector direction h of the specular part of the blinn phong brdf [importance sampling note][4]. &#xD;&#xA;&#xD;&#xA;But since the half vector is computed by h = (v + l) (half vector = viewer / camera vector plus the light vector) and i don't have the light vector (l = wi), because i do the sampling because i want to get the light vector as a result, i can't compute h and therefore i can't generate samples around h. Because i can't generate samples around h, i can't compute l ...&#xD;&#xA;I am going round in circles here.&#xD;&#xA;&#xD;&#xA;I tried to generate samples around the normal instead of the half vector using the following code but the result doesn't match the normal sampled blinn-phong version:&#xD;&#xA;&#xD;&#xA;    class MaterialBlinnPhong : public Material&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;        const Texture* k_d;&#xD;&#xA;        const Texture* k_s;&#xD;&#xA;        const Texture* s;&#xD;&#xA;    &#xD;&#xA;        MaterialBlinnPhong(const Texture* k_d, const Texture* k_s, const Texture* s) :&#xD;&#xA;            k_d(k_d), k_s(k_s), s(s)&#xD;&#xA;        {&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // compute blinn phong brdf&#xD;&#xA;        // n  - normal at hitpoint&#xD;&#xA;        // l  - light vector (wi)&#xD;&#xA;        // v  - camera vector (wo)&#xD;&#xA;        // kd - diffuse constant&#xD;&#xA;        // ks - specular constant&#xD;&#xA;        // shininess - blinn phong exponent&#xD;&#xA;        vec3 brdf(const vec3&amp; n, const vec3&amp; l, const vec3&amp; v,&#xD;&#xA;                const vec3&amp; kd, const vec3&amp; ks, float shininess) const&#xD;&#xA;        {&#xD;&#xA;            // compute lambert diffuse&#xD;&#xA;            vec3 diffuse = kd / pi;&#xD;&#xA;            &#xD;&#xA;            // compute phong specular&#xD;&#xA;            vec3 h = (v + l).normalize();&#xD;&#xA;            float cosNH = powf(std::max(dot(n, h), 0.0f), shininess);&#xD;&#xA;            &#xD;&#xA;            float normalization = ((shininess + 2.0f) * (shininess + 4.0f)) / (8.0f * M_PI * (powf(2.0, -shininess / 2.0f) + shininess));&#xD;&#xA;            vec3 specular = ks * cosNH * normalization;&#xD;&#xA;            &#xD;&#xA;            // return combined result&#xD;&#xA;            return diffuse + specular;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // importance sampling of the blinn phong brdf&#xD;&#xA;        // ray  - ray which hits the surface&#xD;&#xA;        // hr   - hitrecord contains information of the surface hitpoint (normal, texcoords, etc.)&#xD;&#xA;        // prng - random number generator for sampling&#xD;&#xA;        virtual ScatterRecord scatter(const Ray&amp; ray, const HitRecord&amp; hr, Prng&amp; prng) const override&#xD;&#xA;        {&#xD;&#xA;            // if hit on backside return&#xD;&#xA;            if (hr.backside)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // get diffuse, specular and shininess values from texture&#xD;&#xA;            vec3 kd = k_d-&gt;value(hr.texcoord);&#xD;&#xA;            vec3 ks = k_s-&gt;value(hr.texcoord);&#xD;&#xA;            float shininess = s-&gt;value(hr.texcoord).x();&#xD;&#xA;    &#xD;&#xA;            // sample the brdf&#xD;&#xA;            vec3 n = hr.normal;                     // n = normal at hitpoint&#xD;&#xA;            vec3 v = -ray.direction;                // v = wo = vector to camera&#xD;&#xA;            vec3 h;                                 // half vector of blinn phong&#xD;&#xA;    &#xD;&#xA;            // use &quot;energy&quot; heuristic to decide wether a diffuse or &#xD;&#xA;            // specular sample should be taken&#xD;&#xA;            float sumKd = kd.x() + kd.y() + kd.z(); // red (x), green (y) and blue (z) &quot;wavelength&quot;-energies added&#xD;&#xA;            float sumKs = ks.x() + ks.y() + ks.z(); // to compute &quot;total energy&quot; from all wavelengths&#xD;&#xA;            float sum = sumKd + sumKs;              // sum it, so the probabilities add to 1&#xD;&#xA;            &#xD;&#xA;            // compute&#xD;&#xA;            float specularProbability = sumKs / sum;&#xD;&#xA;            specularProbability = clamp(specularProbability, 0.1, 0.9); // keep the probability between 0.1 and 0.9&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            // generate phong distributed sample light vector l (wi) around reflection vector&#xD;&#xA;            vec3 l; // this is the new direction&#xD;&#xA;     &#xD;&#xA;            if (prng.in01() &lt; specularProbability) {&#xD;&#xA;                // act specular&#xD;&#xA;                &#xD;&#xA;                // generate phong distributed samples (phi, theta according to  &#xD;&#xA;                vec3 newDirectionAroundH = Sampler::phongWeightedOnHemisphere(shininess, prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around normal n &#xD;&#xA;                // (but i would probably need to compute the onb around h here since i want to sample the cosine lobe &#xD;&#xA;                // around the reflected direction h and not n, but i can't compute h because i need l &#xD;&#xA;                // to compute h (= (l + v)))&#xD;&#xA;                TangentSpace rts = TangentSpace(n);&#xD;&#xA;                &#xD;&#xA;                // transform back from hading / tangent space to world coordinates&#xD;&#xA;                l = normalize(rts.toWorldSpace(newDirectionAroundH));&#xD;&#xA;                &#xD;&#xA;                // now i can compute h (but it is probably wrong)&#xD;&#xA;                h = (l + v).normalize();    &#xD;&#xA;            } else {&#xD;&#xA;                // act diffuse&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around n (normal)  &#xD;&#xA;                TangentSpace ts(n);&#xD;&#xA;                &#xD;&#xA;                // generate cosine distributed samples on hemisphere&#xD;&#xA;                vec3 newDirectionTS = Sampler::cosineWeightedOnHemisphere(prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // transform back from tangent space to world coordinates&#xD;&#xA;                l = normalize(ts.toWorldSpace(newDirectionTS)); &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // compute cos theta for pdf&#xD;&#xA;            float cosTheta = dot(l, n);&#xD;&#xA;            if (cosTheta &lt;= 0.0f)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // compute diffuse pdf&#xD;&#xA;            float diffusePdfValue = cosTheta / pi;&#xD;&#xA;            &#xD;&#xA;            // compute specular pdf&#xD;&#xA;            float specularPdfValue = 0.5f / pi * (shininess + 1.0f)&#xD;&#xA;                * std::pow(std::max(dot(h, l), 0.0f), shininess);&#xD;&#xA;            &#xD;&#xA;            // do &quot;lerp&quot; linear interpolation between the two depending on the specular probability&#xD;&#xA;            float pdf = mix(diffusePdfValue, specularPdfValue, specularProbability);&#xD;&#xA;    &#xD;&#xA;            // compute brdf value for wi (l) and wo (v)&#xD;&#xA;            vec3 attenuation = brdf(n, l, v, kd, ks, shininess) * cosTheta;&#xD;&#xA;            &#xD;&#xA;            // return result&#xD;&#xA;            return ScatterRecord(l, pdf, attenuation);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;So does anyone know how to importance sample the blinn-phong brdf in a pathtracer?&#xD;&#xA;&#xD;&#xA;Thank you very much in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://marlam.de/path-tracing/course/&#xD;&#xA;  [2]: https://github.com/marlam/path-tracing-mirror/tree/main/src/09&#xD;&#xA;  [3]: https://marlam.de/path-tracing/path-tracing-07.pdf&#xD;&#xA;  [4]: https://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/code/ImportanceSampling/importance_sampling_notes.pdf&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41417" PostHistoryTypeId="1" PostId="13633" RevisionGUID="5a220f07-7b13-4069-ad1a-17d8aacb9866" CreationDate="2023-08-15T10:55:35.720" UserId="20400" Text="Importance sampling of the blinn-phong brdf in pathtracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="41418" PostHistoryTypeId="3" PostId="13633" RevisionGUID="5a220f07-7b13-4069-ad1a-17d8aacb9866" CreationDate="2023-08-15T10:55:35.720" UserId="20400" Text="|raytracing|pathtracing|brdf|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41419" PostHistoryTypeId="2" PostId="13634" RevisionGUID="e296824e-6b48-4df1-9037-ee1d5e30835e" CreationDate="2023-08-16T00:13:17.477" UserId="5256" Text="I have a C++ graphics engine and I would like to build an editor for it in C#. I want to be able to send data from the editor to the engine such as what tool is being used and any user-defined parameters." ContentLicense="CC BY-SA 4.0" />
  <row Id="41421" PostHistoryTypeId="1" PostId="13634" RevisionGUID="e296824e-6b48-4df1-9037-ee1d5e30835e" CreationDate="2023-08-16T00:13:17.477" UserId="5256" Text="How to send data from a C# application to a C++ DLL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41422" PostHistoryTypeId="3" PostId="13634" RevisionGUID="e296824e-6b48-4df1-9037-ee1d5e30835e" CreationDate="2023-08-16T00:13:17.477" UserId="5256" Text="|c++|ui|c#|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41423" PostHistoryTypeId="2" PostId="13635" RevisionGUID="cd560445-4745-449e-8002-22944725f750" CreationDate="2023-08-16T00:13:17.477" UserId="5256" Text="A C++ CLR (Common Language Runtime) Class Library simplifies the interop process between C++ and C#.&#xD;&#xA;&#xD;&#xA;&gt; Ensure that the project configurations (x86 or x64) match between the&#xD;&#xA;&gt; C# application and the C++ CLR Class Library to prevent compatibility&#xD;&#xA;&gt; issues.&#xD;&#xA;&#xD;&#xA;**1. Create the C++ CLR Class Library:**&#xD;&#xA;&#xD;&#xA;Start by creating a new C++ CLR Class Library project in Visual Studio. This type of project allows you to write managed C++ code that can be easily accessed from C#.&#xD;&#xA;&#xD;&#xA;**2. Define the Managed Class:**&#xD;&#xA;&#xD;&#xA;Start by creating a new C++ CLR Class Library project in Visual Studio. This type of project allows you to write managed C++ code that can be easily accessed from C#.&#xD;&#xA;&#xD;&#xA;*MyCppCLRClass.h*&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    using namespace System;&#xD;&#xA;    &#xD;&#xA;    namespace MyCppCLRClassLibrary&#xD;&#xA;    {&#xD;&#xA;        public ref class MyCppCLRClass&#xD;&#xA;        {&#xD;&#xA;            public:&#xD;&#xA;                void SendMessageFromCSharp(String^ message);&#xD;&#xA;        };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*MyCppCLRClass.cpp*&#xD;&#xA;&#xD;&#xA;    // MyCppCLRClass.cpp&#xD;&#xA;    #include &quot;MyCppCLRClass.h&quot;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    namespace MyCppCLRClassLibrary&#xD;&#xA;    {&#xD;&#xA;        void MyCppCLRClass::SendMessageFromCSharp(String^ message)&#xD;&#xA;        {&#xD;&#xA;            std::cout &lt;&lt; &quot;Message received in C++ CLR Class: &quot; &lt;&lt; msclr::interop::marshal_as&lt;std::string&gt;(message) &lt;&lt; std::endl;&#xD;&#xA;            // Process the message or perform any required actions&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**3. Build the C++ CLR Class Library:**&#xD;&#xA;&#xD;&#xA;Start by creating a new C++ CLR Class Library project in Visual Studio. This type of project allows you to write managed C++ code that can be easily accessed from C#.&#xD;&#xA;&#xD;&#xA;**4. Create the C# WPF Application:**&#xD;&#xA;&#xD;&#xA;Create a new C# WPF application project or use your existing one.&#xD;&#xA;&#xD;&#xA;**5. Reference the C++ CLR Class Library:**&#xD;&#xA;&#xD;&#xA;In your C# project, add a reference to the compiled C++ CLR Class Library DLL.&#xD;&#xA;&#xD;&#xA;**6. Call the Managed C++ Functions:**&#xD;&#xA;&#xD;&#xA;In your C# code, you can directly call the functions exposed by the managed C++ class:&#xD;&#xA;&#xD;&#xA;    using System;&#xD;&#xA;    using MyCppCLRClassLibrary;&#xD;&#xA;&#xD;&#xA;    namespace MyCSharpWpfApp&#xD;&#xA;    {&#xD;&#xA;        public partial class MainWindow : Window&#xD;&#xA;        {&#xD;&#xA;            public MainWindow()&#xD;&#xA;            {&#xD;&#xA;                InitializeComponent();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            private void Button_Click(object sender, RoutedEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                string message = &quot;Hello from C#!&quot;;&#xD;&#xA;                MyCppCLRClass myCppCLRInstance = new MyCppCLRClass();&#xD;&#xA;                myCppCLRInstance.SendMessageFromCSharp(message);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**7. Run the Application:**&#xD;&#xA;&#xD;&#xA;Run your C# WPF application, and when the button is clicked, it should call the function in the C++ CLR Class Library.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41425" PostHistoryTypeId="4" PostId="13634" RevisionGUID="a133287f-c69f-4138-8002-50f1e7056f7d" CreationDate="2023-08-16T00:23:10.203" UserId="5256" Comment="edited title" Text="How to send data from C# to a C++ DLL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41426" PostHistoryTypeId="5" PostId="13635" RevisionGUID="ca75e0f6-349c-4f94-9937-9df7327aa6f5" CreationDate="2023-08-16T00:54:07.043" UserId="5256" Comment="deleted 39 characters in body" Text="A C++ CLR (Common Language Runtime) Class Library simplifies the interop process between C++ and C#.&#xD;&#xA;&#xD;&#xA;&gt; Ensure that the project configurations (x86 or x64) match between the&#xD;&#xA;&gt; C# application and the C++ CLR Class Library to prevent compatibility&#xD;&#xA;&gt; issues.&#xD;&#xA;&#xD;&#xA;**1. Create the C++ CLR Class Library:**&#xD;&#xA;&#xD;&#xA;Start by creating a new C++ CLR Class Library project in Visual Studio. This type of project allows you to write managed C++ code that can be easily accessed from C#.&#xD;&#xA;&#xD;&#xA;**2. Define the Managed Class:**&#xD;&#xA;&#xD;&#xA;Start by creating a new C++ CLR Class Library project in Visual Studio. This type of project allows you to write managed C++ code that can be easily accessed from C#.&#xD;&#xA;&#xD;&#xA;*MyCppCLRClass.h*&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    using namespace System;&#xD;&#xA;    &#xD;&#xA;    namespace MyCppCLRClassLibrary&#xD;&#xA;    {&#xD;&#xA;        public ref class MyCppCLRClass&#xD;&#xA;        {&#xD;&#xA;            public:&#xD;&#xA;                void SendMessageFromCSharp(String^ message);&#xD;&#xA;        };&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;*MyCppCLRClass.cpp*&#xD;&#xA;&#xD;&#xA;    // MyCppCLRClass.cpp&#xD;&#xA;    #include &quot;MyCppCLRClass.h&quot;&#xD;&#xA;    #include &lt;iostream&gt;&#xD;&#xA;    &#xD;&#xA;    namespace MyCppCLRClassLibrary&#xD;&#xA;    {&#xD;&#xA;        void MyCppCLRClass::SendMessageFromCSharp(String^ message)&#xD;&#xA;        {&#xD;&#xA;            std::cout &lt;&lt; &quot;Message received in C++ CLR Class: &quot; &lt;&lt; msclr::interop::marshal_as&lt;std::string&gt;(message) &lt;&lt; std::endl;&#xD;&#xA;            // Process the message or perform any required actions&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**3. Build the C++ CLR Class Library:**&#xD;&#xA;&#xD;&#xA;Build the C++ CLR Class Library project. Visual Studio should generate a managed DLL that you can use from your C# application.&#xD;&#xA;&#xD;&#xA;**4. Create the C# WPF Application:**&#xD;&#xA;&#xD;&#xA;Create a new C# WPF application project or use your existing one.&#xD;&#xA;&#xD;&#xA;**5. Reference the C++ CLR Class Library:**&#xD;&#xA;&#xD;&#xA;In your C# project, add a reference to the compiled C++ CLR Class Library DLL.&#xD;&#xA;&#xD;&#xA;**6. Call the Managed C++ Functions:**&#xD;&#xA;&#xD;&#xA;In your C# code, you can directly call the functions exposed by the managed C++ class:&#xD;&#xA;&#xD;&#xA;    using System;&#xD;&#xA;    using MyCppCLRClassLibrary;&#xD;&#xA;&#xD;&#xA;    namespace MyCSharpWpfApp&#xD;&#xA;    {&#xD;&#xA;        public partial class MainWindow : Window&#xD;&#xA;        {&#xD;&#xA;            public MainWindow()&#xD;&#xA;            {&#xD;&#xA;                InitializeComponent();&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;            private void Button_Click(object sender, RoutedEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                string message = &quot;Hello from C#!&quot;;&#xD;&#xA;                MyCppCLRClass myCppCLRInstance = new MyCppCLRClass();&#xD;&#xA;                myCppCLRInstance.SendMessageFromCSharp(message);&#xD;&#xA;            }&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**7. Run the Application:**&#xD;&#xA;&#xD;&#xA;Run your C# WPF application, and when the button is clicked, it should call the function in the C++ CLR Class Library.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41427" PostHistoryTypeId="4" PostId="13634" RevisionGUID="7e9df214-c817-4975-9957-f7985310b4a2" CreationDate="2023-08-16T00:56:00.010" UserId="5256" Comment="edited title" Text="How to send data from a C# application to a C++ DLL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41428" PostHistoryTypeId="5" PostId="13634" RevisionGUID="0d9f7b92-a12f-4522-9382-b2122ea1bf2a" CreationDate="2023-08-16T01:14:24.787" UserId="5256" Comment="Provided a link to a previous Q&amp;A that may provide more context to this question." Text="I have a C++ graphics engine and I would like to build an editor for it in C#. I want to be able to send data from the editor to the engine such as what tool is being used and any user-defined parameters.&#xD;&#xA;&#xD;&#xA;In a previous [question][1], I have already found a method to render my C++ engine to a C# window.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/12791/hosting-opengl-c-window-in-c-wpf" ContentLicense="CC BY-SA 4.0" />
  <row Id="41430" PostHistoryTypeId="50" PostId="12853" RevisionGUID="ec8913f5-38ae-4ae1-b61c-26beac65f0db" CreationDate="2023-08-16T12:08:46.050" UserId="-1" />
  <row Id="41431" PostHistoryTypeId="50" PostId="8260" RevisionGUID="682d3ee9-2d90-468d-9245-a45f08d960df" CreationDate="2023-08-16T15:02:35.303" UserId="-1" />
  <row Id="41432" PostHistoryTypeId="2" PostId="13636" RevisionGUID="c5566ca5-94a9-4e38-bf02-cf9d907bab55" CreationDate="2023-08-16T16:42:52.453" UserId="19537" Text="Note that in the importance sampling from the [importance sampling note provided by you](https://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/code/ImportanceSampling/importance_sampling_notes.pdf) (equation 48-59), we are not sampling the reflection direction but the half-vector direction. This is somewhat similar to the microfacet theory and you can refer to [this answer post](https://computergraphics.stackexchange.com/questions/13590/importance-sampling-in-a-path-tracer/13591#13591) for more information on microfacet theory. You can think of this process as sampling the normal to be used for perfect specular reflection.  &#xD;&#xA;&#xD;&#xA;So the process is shown as follows:&#xD;&#xA;- We know that Blinn-Phong BRDF (regardless of the normalization term $Z$ for proper BRDF definition)&#xD;&#xA;$$&#xD;&#xA;\text{Blinn-Phong} = (N\cdot H)^\alpha \times Z&#xD;&#xA;$$&#xD;&#xA;Therefore, $H$ can be importance sampled according to this $\cos^\alpha$ term. This is actually stated in the importance sampling note:&#xD;&#xA;&gt; The Phong BRDF requires sampling a cosine lobe with specular exponent n around the reflected direction **(or half-vector direction in case of BlinnPhong)**&#xD;&#xA;- We have our $H$, so we can actually use this $H$ to get the reflected direction, then using the $w_o$ we can get the $w_i$ with vector $H$ via the simple law of reflection.&#xD;&#xA;&#xD;&#xA;Also, I believe you will find this paper useful: [Lafortune &amp; Willems, using the modified phong reflectance model for physically based rendering, 1994](https://www.researchgate.net/profile/Yves-Willems-2/publication/2361953_Using_the_Modied_Phong_Reflectance_Model_for_Physically_Based_Rendering/links/562e17af08ae22b170352271/Using-the-Modied-Phong-Reflectance-Model-for-Physically-Based-Rendering.pdf). Although old, it is the paper that put forward the **Modified-Phong BRDF model** and what it does is exactly: sample half vector and use the sampled half vector to compute incident direction via reflection. &#xD;&#xA;&#xD;&#xA;If you are looking for some specific implementation... I have implemented this (in a simple way) in [my own renderer](https://github.com/Enigmatisms/AdaPT). You can find the implementation in [bxdf/brdf.py:line-191 (whole BRDF) and line-209 (sampling the BRDF)](https://github.com/Enigmatisms/AdaPT/blob/master/bxdf/brdf.py), this is implemented in python so it might be easier to read than the implementation of [mitsuba-Phong-BRDF](https://github.com/mitsuba-renderer/mitsuba/blob/master/src/bsdfs/phong.cpp) (and I think mitsuba implements Phong but not Blinn-Phong).&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;# get the local direction for half vector&#xD;&#xA;local_new_dir, pdf = mod_phong_hemisphere(self.mean[2])&#xD;&#xA;# transform the local half vector to the world frame&#xD;&#xA;normal, _ = delocalize_rotate(it.n_s, local_new_dir)&#xD;&#xA;# reflect the incident (actually, outgoing direction in backward ray tracing)&#xD;&#xA;ray_out_d = (-2 * normal * tm.dot(incid, normal) + incid).normalized()&#xD;&#xA;# evaluate throughput&#xD;&#xA;spec = self.eval_mod_phong(it, incid, ray_out_d)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;At last I recommend the microfacet theory to you again, since you will find that all we do in microfacet BRDF is changing the distribution of the half vector to more complicated ones (like GGX, Beckmann). I hope I understand your question correctly and can be of help to you. Since it's been a while since I last learned this, feel free to point out anything wrong." ContentLicense="CC BY-SA 4.0" />
  <row Id="41434" PostHistoryTypeId="2" PostId="13637" RevisionGUID="c9efada2-66bc-42e0-bc93-c91f7b037400" CreationDate="2023-08-17T01:26:45.187" UserId="20405" Text="I've implemented a simple color burn function in one of my shaders and I understand the results (I think), but the math behind it, although simple, is unintuitive to me. I struggle to understand how would one invent this formula from scratch in search of the given effect. Could someone clarify how one comes from&#xD;&#xA;&#xD;&#xA;&quot;I need to increase the distance between the darkest and the lightest shades of the image.&quot;&#xD;&#xA;&#xD;&#xA;to&#xD;&#xA;&#xD;&#xA;&quot;invert bottom layer by the top layer, and then invert the result.&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41436" PostHistoryTypeId="1" PostId="13637" RevisionGUID="c9efada2-66bc-42e0-bc93-c91f7b037400" CreationDate="2023-08-17T01:26:45.187" UserId="20405" Text="What's the intuition behind color burn and other blend modes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41437" PostHistoryTypeId="3" PostId="13637" RevisionGUID="c9efada2-66bc-42e0-bc93-c91f7b037400" CreationDate="2023-08-17T01:26:45.187" UserId="20405" Text="|pixel-shader|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41438" PostHistoryTypeId="5" PostId="13637" RevisionGUID="944139b6-6c10-4182-8b35-3d15d254bdf4" CreationDate="2023-08-17T01:27:38.247" UserId="20405" Comment="added 11 characters in body" Text="I've implemented a simple color burn function in one of my shaders and I understand the results (I think), but the math behind it, although simple, is unintuitive to me. I struggle to understand how would one invent this formula from scratch in search of the given effect. Could someone clarify how one comes from&#xD;&#xA;&#xD;&#xA;&quot;I need to increase the distance between the darkest and the lightest shades of the image.&quot;&#xD;&#xA;&#xD;&#xA;to&#xD;&#xA;&#xD;&#xA;&quot;invert bottom layer and divide by the top layer, and then invert the result.&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41441" PostHistoryTypeId="5" PostId="13633" RevisionGUID="4a691208-4a2a-44c1-bc3a-f9f6993b0100" CreationDate="2023-08-17T10:10:57.787" UserId="20400" Comment="added 2646 characters in body" Text="tl;dr:&#xD;&#xA;=====&#xD;&#xA;**How do you importance sample the blinn-phong-brdf?**&#xD;&#xA;--&#xD;&#xA;&#xD;&#xA;**Recipe for importance sampling of the phong brdf as far as i understood it (pseudo-code):**&#xD;&#xA;&#xD;&#xA;    Tuple&lt;wi, pdf, brdfValue&gt; samplePhongBRDF(HitInfo hi, Vector3 wo) {&#xD;&#xA;&#xD;&#xA;        float sumKD = kd.r + kd.g + kd.b;    // compute diffuse &quot;energy&quot;&#xD;&#xA;        float sumKS = ks.r + ks.g + ks.b;    // compute specular &quot;energy&quot; &#xD;&#xA;        float sum = sumKD + sumKS;           // compute total sum&#xD;&#xA;&#xD;&#xA;        float specProbability = sumKs / sum; // compute probability for specular event&#xD;&#xA;        &#xD;&#xA;        float rn = generateRandomNumber();   // generate random number [0..1]&#xD;&#xA;        Vector3 r = reflect(ray.direction, n);  // compute reflection vector r&#xD;&#xA;    &#xD;&#xA;        Vector3 wi;&#xD;&#xA;        if rn &lt; specularProbability {&#xD;&#xA;            // sample specular -&gt; generate phong distributed sample&#xD;&#xA;            // around reflection vector r&#xD;&#xA;            Vector3 newDirectionAroundR = phongDistOnHemisphere(...);&#xD;&#xA;&#xD;&#xA;            // generate orthonormal basis around r (reflection vector as &quot;normal&quot;)&#xD;&#xA;            // -&gt; tangent space&#xD;&#xA;            TangentSpace rts = TangentSpace(r);    // sample around r&#xD;&#xA;&#xD;&#xA;            // transform back from tangent space to world coordinates&#xD;&#xA;            wi = rts.toWorldSpace(newDirectionAroundR));&#xD;&#xA;        } else {&#xD;&#xA;            // sample diffuse with cosine-distribution&#xD;&#xA;&#xD;&#xA;            // generate orthonormal basis around n (normal)  &#xD;&#xA;            TangentSpace ts(n);&#xD;&#xA;    &#xD;&#xA;            // generate cosine distributed samples on hemisphere&#xD;&#xA;            Vector3 newDirectionTS = cosineDistOnHemisphere(...);&#xD;&#xA;&#xD;&#xA;            // transform back from tangent space to world coordinates&#xD;&#xA;            l = normalize(ts.toWorldSpace(newDirectionTS)); &#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // compute cos theta for pdf&#xD;&#xA;        float cosTheta = dot(l, n);&#xD;&#xA;&#xD;&#xA;        // compute diffuse pdf&#xD;&#xA;        float diffusePdfValue = cosTheta / pi;&#xD;&#xA;        &#xD;&#xA;        // compute specular pdf&#xD;&#xA;        float specularPdfValue = 0.5f / pi * (shininess + 1.0f)&#xD;&#xA;            * std::pow(std::max(dot(r, l), 0.0f), shininess);&#xD;&#xA;        &#xD;&#xA;        // do &quot;lerp&quot; linear interpolation between the two &#xD;&#xA;        float pdf = mix(diffusePdfValue, specularPdfValue, specProbability);&#xD;&#xA;&#xD;&#xA;        // compute brdf value for wi (l) and wo (v)&#xD;&#xA;        vec3 attenuation = brdf(wo, wi ...) * cosTheta;&#xD;&#xA;&#xD;&#xA;        return Tuple(wi, pdf, brdfValue);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;--&#xD;&#xA;*How do i adapt the above code for importance sampling of the **phong-brdf** to the **blinn-phong-brdf** according to this [importance sampling note][4]?*&#xD;&#xA;&#xD;&#xA;Thank you very much in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Longer version:**&#xD;&#xA;-------------------&#xD;&#xA;I am following a tutorial on pathtracing ([path tracing course][1]) and i am implementing my own pathtracer on the way which is loosely based on the provided source code of the tutorial ([source code][2]). At the point of the tutorial where i am now, the author is showing how to importance sample different material brdfs like the lambert diffuse brdf and the phong brdf ([Material Importance Sampling][3]).&#xD;&#xA;&#xD;&#xA;For the importance sampling of the specular part of the phong brdf a cosine lobe with specular exponent n around the reflected direction (R vector of the phong brdf) has to be sampled according to [importance sampling note][4].&#xD;&#xA;&#xD;&#xA;The source code for importance sampling of the phong brdf is the following (slightly modified by me):&#xD;&#xA;&#xD;&#xA;    class MaterialPhong : public Material&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;        const Texture* k_d;&#xD;&#xA;        const Texture* k_s;&#xD;&#xA;        const Texture* s;&#xD;&#xA;    &#xD;&#xA;        MaterialPhong(const Texture* k_d, const Texture* k_s, const Texture* s) :&#xD;&#xA;            k_d(k_d), k_s(k_s), s(s)&#xD;&#xA;        {&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // compute phong brdf&#xD;&#xA;        // n  - normal at hitpoint&#xD;&#xA;        // l  - light vector (wi)&#xD;&#xA;        // v  - camera vector (wo)&#xD;&#xA;        // kd - diffuse constant&#xD;&#xA;        // ks - specular constant&#xD;&#xA;        // shininess - phong exponent&#xD;&#xA;        vec3 brdf(const vec3&amp; n, const vec3&amp; l, const vec3&amp; v,&#xD;&#xA;                  const vec3&amp; kd, const vec3&amp; ks, float shininess) const&#xD;&#xA;        {&#xD;&#xA;            // compute lambert diffuse&#xD;&#xA;            vec3 diffuse = kd / pi;&#xD;&#xA;            &#xD;&#xA;            // compute phong specular&#xD;&#xA;            float cosRV = std::max(dot(reflect(-l, n), v), 0.0f);&#xD;&#xA;            float normalization = (shininess + 2.0f) / (2.0f * pi);&#xD;&#xA;            vec3 specular = ks * normalization * pow(cosRV, shininess);&#xD;&#xA;            &#xD;&#xA;            // return combined result&#xD;&#xA;            return diffuse + specular;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // importance sampling of the phong brdf&#xD;&#xA;        // ray  - ray which hits the surface&#xD;&#xA;        // hr   - hitrecord contains information of the surface hitpoint (normal, texcoords, etc.)&#xD;&#xA;        // prng - random number generator for sampling&#xD;&#xA;        virtual ScatterRecord scatter(const Ray&amp; ray, const HitRecord&amp; hr, Prng&amp; prng) const override&#xD;&#xA;        {&#xD;&#xA;            // if hit on backside return&#xD;&#xA;            if (hr.backside)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // get diffuse, specular and shininess values from texture&#xD;&#xA;            vec3 kd = k_d-&gt;value(hr.texcoord);&#xD;&#xA;            vec3 ks = k_s-&gt;value(hr.texcoord);&#xD;&#xA;            float shininess = s-&gt;value(hr.texcoord).x();&#xD;&#xA;    &#xD;&#xA;            // sample the brdf&#xD;&#xA;            vec3 n = hr.normal;                     // n = normal at hitpoint&#xD;&#xA;            vec3 v = -ray.direction;                // v = wo = vector to camera&#xD;&#xA;            vec3 r = reflect(ray.direction, n);     // r = reflection vector for phong&#xD;&#xA;    &#xD;&#xA;            // use &quot;energy&quot; heuristic to decide wether a diffuse or &#xD;&#xA;            // specular sample should be taken&#xD;&#xA;            float sumKd = kd.x() + kd.y() + kd.z(); // red (x), green (y) and blue (z) &quot;wavelength&quot;-energies added&#xD;&#xA;            float sumKs = ks.x() + ks.y() + ks.z(); // to compute &quot;total energy&quot; from all wavelengths&#xD;&#xA;            float sum = sumKd + sumKs;              // sum it, so the probabilities add to 1&#xD;&#xA;            &#xD;&#xA;            // compute&#xD;&#xA;            float specularProbability = sumKs / sum;&#xD;&#xA;            specularProbability = clamp(specularProbability, 0.1, 0.9); // keep the probability between 0.1 and 0.9&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            // generate phong distributed sample light vector l (wi) around reflection vector&#xD;&#xA;            vec3 l; // this is the new direction&#xD;&#xA;            &#xD;&#xA;            // sample brdf depending on the random number&#xD;&#xA;            if (prng.in01() &lt; specularProbability) {&#xD;&#xA;                // act specular&#xD;&#xA;                &#xD;&#xA;                // generate phong distributed samples (phi, theta)  &#xD;&#xA;                vec3 newDirectionAroundR = Sampler::phongWeightedOnHemisphere(shininess, prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around r (reflection vector as &quot;normal&quot; for the onb) -&gt; shading / tangent space&#xD;&#xA;                TangentSpace rts = TangentSpace(r);&#xD;&#xA;                &#xD;&#xA;                // transform back from shading / tangent space to world coordinates&#xD;&#xA;                l = normalize(rts.toWorldSpace(newDirectionAroundR));   &#xD;&#xA;            } else {&#xD;&#xA;                // act diffuse&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around n (normal)  &#xD;&#xA;                TangentSpace ts(n);&#xD;&#xA;                &#xD;&#xA;                // generate cosine distributed samples on hemisphere&#xD;&#xA;                vec3 newDirectionTS = Sampler::cosineWeightedOnHemisphere(prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // transform back from tangent space to world coordinates&#xD;&#xA;                l = normalize(ts.toWorldSpace(newDirectionTS)); &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // compute cos theta for pdf&#xD;&#xA;            float cosTheta = dot(l, n);&#xD;&#xA;            if (cosTheta &lt;= 0.0f)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // compute diffuse pdf&#xD;&#xA;            float diffusePdfValue = cosTheta / pi;&#xD;&#xA;            &#xD;&#xA;            // compute specular pdf&#xD;&#xA;            float specularPdfValue = 0.5f / pi * (shininess + 1.0f)&#xD;&#xA;                * std::pow(std::max(dot(r, l), 0.0f), shininess);&#xD;&#xA;            &#xD;&#xA;            // do &quot;lerp&quot; linear interpolation between the two depending on the specular probability&#xD;&#xA;            float pdf = mix(diffusePdfValue, specularPdfValue, specularProbability);&#xD;&#xA;    &#xD;&#xA;            // compute brdf value for wi (l) and wo (v)&#xD;&#xA;            vec3 attenuation = brdf(n, l, v, kd, ks, shininess) * cosTheta;&#xD;&#xA;            &#xD;&#xA;            // return result&#xD;&#xA;            return ScatterRecord(l, pdf, attenuation);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Now i want to write an equivalent material class for importance sampling of the blinn-phong brdf. But as i understand for the importance sampling of the specular part of the blinn phong brdf i would need to sample the cosine lobe around the half vector direction h of the specular part of the blinn phong brdf [importance sampling note][4]. &#xD;&#xA;&#xD;&#xA;But since the half vector is computed by h = (v + l) (half vector = viewer / camera vector plus the light vector) and i don't have the light vector (l = wi), because i do the sampling because i want to get the light vector as a result, i can't compute h and therefore i can't generate samples around h. Because i can't generate samples around h, i can't compute l ...&#xD;&#xA;I am going round in circles here.&#xD;&#xA;&#xD;&#xA;I tried to generate samples around the normal instead of the half vector using the following code but the result doesn't match the normal sampled blinn-phong version:&#xD;&#xA;&#xD;&#xA;    class MaterialBlinnPhong : public Material&#xD;&#xA;    {&#xD;&#xA;    public:&#xD;&#xA;        const Texture* k_d;&#xD;&#xA;        const Texture* k_s;&#xD;&#xA;        const Texture* s;&#xD;&#xA;    &#xD;&#xA;        MaterialBlinnPhong(const Texture* k_d, const Texture* k_s, const Texture* s) :&#xD;&#xA;            k_d(k_d), k_s(k_s), s(s)&#xD;&#xA;        {&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // compute blinn phong brdf&#xD;&#xA;        // n  - normal at hitpoint&#xD;&#xA;        // l  - light vector (wi)&#xD;&#xA;        // v  - camera vector (wo)&#xD;&#xA;        // kd - diffuse constant&#xD;&#xA;        // ks - specular constant&#xD;&#xA;        // shininess - blinn phong exponent&#xD;&#xA;        vec3 brdf(const vec3&amp; n, const vec3&amp; l, const vec3&amp; v,&#xD;&#xA;                const vec3&amp; kd, const vec3&amp; ks, float shininess) const&#xD;&#xA;        {&#xD;&#xA;            // compute lambert diffuse&#xD;&#xA;            vec3 diffuse = kd / pi;&#xD;&#xA;            &#xD;&#xA;            // compute phong specular&#xD;&#xA;            vec3 h = (v + l).normalize();&#xD;&#xA;            float cosNH = powf(std::max(dot(n, h), 0.0f), shininess);&#xD;&#xA;            &#xD;&#xA;            float normalization = ((shininess + 2.0f) * (shininess + 4.0f)) / (8.0f * M_PI * (powf(2.0, -shininess / 2.0f) + shininess));&#xD;&#xA;            vec3 specular = ks * cosNH * normalization;&#xD;&#xA;            &#xD;&#xA;            // return combined result&#xD;&#xA;            return diffuse + specular;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        // importance sampling of the blinn phong brdf&#xD;&#xA;        // ray  - ray which hits the surface&#xD;&#xA;        // hr   - hitrecord contains information of the surface hitpoint (normal, texcoords, etc.)&#xD;&#xA;        // prng - random number generator for sampling&#xD;&#xA;        virtual ScatterRecord scatter(const Ray&amp; ray, const HitRecord&amp; hr, Prng&amp; prng) const override&#xD;&#xA;        {&#xD;&#xA;            // if hit on backside return&#xD;&#xA;            if (hr.backside)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // get diffuse, specular and shininess values from texture&#xD;&#xA;            vec3 kd = k_d-&gt;value(hr.texcoord);&#xD;&#xA;            vec3 ks = k_s-&gt;value(hr.texcoord);&#xD;&#xA;            float shininess = s-&gt;value(hr.texcoord).x();&#xD;&#xA;    &#xD;&#xA;            // sample the brdf&#xD;&#xA;            vec3 n = hr.normal;                     // n = normal at hitpoint&#xD;&#xA;            vec3 v = -ray.direction;                // v = wo = vector to camera&#xD;&#xA;            vec3 h;                                 // half vector of blinn phong&#xD;&#xA;    &#xD;&#xA;            // use &quot;energy&quot; heuristic to decide wether a diffuse or &#xD;&#xA;            // specular sample should be taken&#xD;&#xA;            float sumKd = kd.x() + kd.y() + kd.z(); // red (x), green (y) and blue (z) &quot;wavelength&quot;-energies added&#xD;&#xA;            float sumKs = ks.x() + ks.y() + ks.z(); // to compute &quot;total energy&quot; from all wavelengths&#xD;&#xA;            float sum = sumKd + sumKs;              // sum it, so the probabilities add to 1&#xD;&#xA;            &#xD;&#xA;            // compute&#xD;&#xA;            float specularProbability = sumKs / sum;&#xD;&#xA;            specularProbability = clamp(specularProbability, 0.1, 0.9); // keep the probability between 0.1 and 0.9&#xD;&#xA;            &#xD;&#xA;            &#xD;&#xA;            // generate phong distributed sample light vector l (wi) around reflection vector&#xD;&#xA;            vec3 l; // this is the new direction&#xD;&#xA;     &#xD;&#xA;            if (prng.in01() &lt; specularProbability) {&#xD;&#xA;                // act specular&#xD;&#xA;                &#xD;&#xA;                // generate phong distributed samples (phi, theta according to  &#xD;&#xA;                vec3 newDirectionAroundH = Sampler::phongWeightedOnHemisphere(shininess, prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around normal n &#xD;&#xA;                // (but i would probably need to compute the onb around h here since i want to sample the cosine lobe &#xD;&#xA;                // around the reflected direction h and not n, but i can't compute h because i need l &#xD;&#xA;                // to compute h (= (l + v)))&#xD;&#xA;                TangentSpace rts = TangentSpace(n);&#xD;&#xA;                &#xD;&#xA;                // transform back from shading / tangent space to world coordinates&#xD;&#xA;                l = normalize(rts.toWorldSpace(newDirectionAroundH));&#xD;&#xA;                &#xD;&#xA;                // now i can compute h (but it is probably wrong)&#xD;&#xA;                h = (l + v).normalize();    &#xD;&#xA;            } else {&#xD;&#xA;                // act diffuse&#xD;&#xA;                &#xD;&#xA;                // generate orthonormal basis around n (normal)  &#xD;&#xA;                TangentSpace ts(n);&#xD;&#xA;                &#xD;&#xA;                // generate cosine distributed samples on hemisphere&#xD;&#xA;                vec3 newDirectionTS = Sampler::cosineWeightedOnHemisphere(prng.in01(), prng.in01());&#xD;&#xA;                &#xD;&#xA;                // transform back from tangent space to world coordinates&#xD;&#xA;                l = normalize(ts.toWorldSpace(newDirectionTS)); &#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // compute cos theta for pdf&#xD;&#xA;            float cosTheta = dot(l, n);&#xD;&#xA;            if (cosTheta &lt;= 0.0f)&#xD;&#xA;                return ScatterRecord();&#xD;&#xA;    &#xD;&#xA;            // compute diffuse pdf&#xD;&#xA;            float diffusePdfValue = cosTheta / pi;&#xD;&#xA;            &#xD;&#xA;            // compute specular pdf&#xD;&#xA;            float specularPdfValue = 0.5f / pi * (shininess + 1.0f)&#xD;&#xA;                * std::pow(std::max(dot(h, l), 0.0f), shininess);&#xD;&#xA;            &#xD;&#xA;            // do &quot;lerp&quot; linear interpolation between the two depending on the specular probability&#xD;&#xA;            float pdf = mix(diffusePdfValue, specularPdfValue, specularProbability);&#xD;&#xA;    &#xD;&#xA;            // compute brdf value for wi (l) and wo (v)&#xD;&#xA;            vec3 attenuation = brdf(n, l, v, kd, ks, shininess) * cosTheta;&#xD;&#xA;            &#xD;&#xA;            // return result&#xD;&#xA;            return ScatterRecord(l, pdf, attenuation);&#xD;&#xA;        }&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;So does anyone know how to importance sample the blinn-phong brdf in a pathtracer?&#xD;&#xA;&#xD;&#xA;Thank you very much in advance.&#xD;&#xA;&#xD;&#xA;  [1]: https://marlam.de/path-tracing/course/&#xD;&#xA;  [2]: https://github.com/marlam/path-tracing-mirror/tree/main/src/09&#xD;&#xA;  [3]: https://marlam.de/path-tracing/path-tracing-07.pdf&#xD;&#xA;  [4]: https://www.mathematik.uni-marburg.de/~thormae/lectures/graphics1/code/ImportanceSampling/importance_sampling_notes.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41442" PostHistoryTypeId="50" PostId="13372" RevisionGUID="9172f2c3-59cf-4040-9ea4-52915259d5f7" CreationDate="2023-08-17T12:06:35.820" UserId="-1" />
  <row Id="41443" PostHistoryTypeId="2" PostId="13639" RevisionGUID="c9c9707d-7d50-4d23-81d1-08f05f474bf3" CreationDate="2023-08-17T15:12:30.497" UserId="445" Text="In general, notice that there is no particular reason for a blend mode or other color processing formula _in an image manipulation program_ to be reasonable “from first principles” at all. All we care about is that, empirically, it produces an artistically useful result.&#xD;&#xA;&#xD;&#xA;That said, we can make some useful observations about the structure of this particular operation:&#xD;&#xA;&#xD;&#xA;1. By inverting a color (that is, subtracting each component from 1), we can think of the resulting numbers as being “distance from white” in the same way that regular color components are “distance from black”. This preserves all the original information, but represents it differently.&#xD;&#xA;&#xD;&#xA;2. If you invert twice, you get the same color back. So, overall, the two inversions don't change the color; if we _didn't_ do something in the middle, the overall operation would do nothing.&#xD;&#xA;&#xD;&#xA;3. Thus, we can think of the operation in the middle, the division as “operating in distance-from-white space”. By dividing by a number less than 1 (the value from the top layer), we scale up the distance-from-white of the color — darkening it.&#xD;&#xA;&#xD;&#xA;Notice also that the “burn” in the name [comes from film photography](https://en.wikipedia.org/wiki/Dodging_and_burning). The ordinary process of developing photographs inverts color twice (which is why the developed “negative” film is called that and looks the way it does), and dodging and burning were about manipulating the intensity of the light that fell on the print after passing through the negative. Thus, the digital/mathematical emulation of the technique also involves two inversions and a scaling, performed by optical and chemical processes." ContentLicense="CC BY-SA 4.0" />
  <row Id="41445" PostHistoryTypeId="50" PostId="5220" RevisionGUID="b255dfb5-ff8d-464f-8b1c-3b7cf28b7f17" CreationDate="2023-08-18T02:07:46.003" UserId="-1" />
  <row Id="41446" PostHistoryTypeId="2" PostId="13640" RevisionGUID="6009983a-cc53-4fd0-84fd-633a119f9ced" CreationDate="2023-08-18T03:55:16.203" UserId="19537" Text="For your first question, the basic process should be (simplified version):&#xD;&#xA;```c++&#xD;&#xA;// Step1: Ray intersection: calculate the maximum extent for the ray before hitting the surface&#xD;&#xA;bool hit = ray_intersection(scene, ray);&#xD;&#xA;if (!hit) {&#xD;&#xA;    // check if the world itself contains scatter medium, if not then we return&#xD;&#xA;}&#xD;&#xA;/** Step2: distance sampling (free-path sampling).&#xD;&#xA; * For homogeneous scattering medium, it's easy to do with transmittance sampling&#xD;&#xA; * We sample a distance traveled before an scattering event&#xD;&#xA; * and evaluate transmittance&#xD;&#xA;*/&#xD;&#xA;MediumInteraction mi;&#xD;&#xA;Spectrum tr;&#xD;&#xA;bool medium_event = ray.medium.distance_sample(scene, mi, tr);&#xD;&#xA;if (medium_event) {&#xD;&#xA;    // we are here, if the sampled distance is less than the distance to the closest surface&#xD;&#xA;    // Step 3: phase function sampling to upate the ray direction,&#xD;&#xA;    // since distance sampling already updates the origin of the ray&#xD;&#xA;    ray = ray.medium.phase_sampling(mi);&#xD;&#xA;    path_throughput *= tr;&#xD;&#xA;} else {&#xD;&#xA;    // Nothing to be said here, it's just basic surface rendering process&#xD;&#xA;    // One thing to note is that, transmittance value should be evaluated&#xD;&#xA;    // via ray marching (or some other algorithms)&#xD;&#xA;}&#xD;&#xA;// Okay, then we update our ray for the next intersection and scattering event. Loop continues.&#xD;&#xA;```&#xD;&#xA;There are some details hidden in this pseudo code:&#xD;&#xA;- How do we sample the free path in step 2?&#xD;&#xA;In [Dartmouth distance-sampling, page 7](https://cs.dartmouth.edu/wjarosz/publications/novak18monte-slides-3-distance-sampling.pdf), the sampling process is well explained: first find the bin we are in (since we are using fixed steps, it lefts us several bins in the space), and find the exact position in that bin (so, from discrete bins to continuous distance). &#xD;&#xA;- How to evaluate the transmittance?&#xD;&#xA;For homogeneous medium, it's simple and can be done analytically (if, the medium is exponential). For heterogeneous medium, when ray marching is used, we just subdivide the space and evaluate each part then multiply them together.&#xD;&#xA;- Absorption &amp; scattering coefficient&#xD;&#xA;You will find them in most renders as `sigma_a` and `sigma_s`, they compose a extinction coefficient `sigma_t`. The transmittance of a certain distance is usually:&#xD;&#xA;$$&#xD;&#xA;\exp(-\sigma_t d), \text{ where } d \text{ is the distance} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;For the second question, I believe it has been answered: we **sample** the distance sample (distance traveled before a scattering event) according to the aggregated local transmittance, and we should be able to **evaluate** the transmittance (approximately) for any given path. So for non-uniform transmittance we can use ray marching here.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For the third question:&#xD;&#xA;No. Actually, for heterogeneous medium (not yet for SSS), some better ways are developed already: delta-tracking (woodcock tracking), residual tracking, etc. They are **unbiased** and efficient in multiple ways.&#xD;&#xA;For SSS, path tracing can have extremely poor converge in highly scattering medium (high `sigma_s`, low `sigma_a`) since the energy of the ray won't change much even we have hundreds of scattering events. This is decided by the sampling process, let's take a look at a homogeneous example:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\text{estimator} = \sigma_s\frac{f(x)}{p(x)} = \sigma_s\frac{\exp(-\sigma_t d)}{\sigma_t\exp(-\sigma_t d)} = \frac{\sigma_s}{\sigma_s + \sigma_a} \approx 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, a huge amount of scattering events need to be sampled (hence great `max_depth`) and the variance is pretty high. There are some interesting works on accelerating Monte Carlo SSS rendering, if you are interested:&#xD;&#xA;- Meng, Johannes, Johannes Hanika, and Carsten Dachsbacher. &quot;Improving the Dwivedi sampling scheme.&quot; Computer Graphics Forum. Vol. 35. No. 4. 2016.&#xD;&#xA;- Křivánek, Jaroslav, and Eugene d'Eon. &quot;A zero-variance-based sampling scheme for Monte Carlo subsurface scattering.&quot; ACM SIGGRAPH 2014 Talks. 2014. 1-1.&#xD;&#xA;&#xD;&#xA;The idea behind these works are basically: the ray will get lost in the highly scattering medium, so we should guide the ray out or to the emitter as quickly as possible.&#xD;&#xA;&#xD;&#xA;I think for SSS, BSSRDF can already be very efficient." ContentLicense="CC BY-SA 4.0" />
  <row Id="41448" PostHistoryTypeId="5" PostId="13640" RevisionGUID="b49fbb40-c23f-45fc-8707-8c3a5b9e1f3b" CreationDate="2023-08-18T06:24:08.447" UserId="19537" Comment="added 1 character in body" Text="For your first question, the basic process should be (simplified version):&#xD;&#xA;```c++&#xD;&#xA;// Step1: Ray intersection: calculate the maximum extent for the ray before hitting the surface&#xD;&#xA;bool hit = ray_intersection(scene, ray);&#xD;&#xA;if (!hit) {&#xD;&#xA;    // check if the world itself contains scatter medium, if not then we return&#xD;&#xA;}&#xD;&#xA;/** Step2: distance sampling (free-path sampling).&#xD;&#xA; * For homogeneous scattering medium, it's easy to do with transmittance sampling&#xD;&#xA; * We sample a distance traveled before an scattering event&#xD;&#xA; * and evaluate transmittance&#xD;&#xA;*/&#xD;&#xA;MediumInteraction mi;&#xD;&#xA;Spectrum tr;&#xD;&#xA;bool medium_event = ray.medium.distance_sample(scene, mi, tr);&#xD;&#xA;if (medium_event) {&#xD;&#xA;    // we are here, if the sampled distance is less than the distance to the closest surface&#xD;&#xA;    // Step 3: phase function sampling to upate the ray direction,&#xD;&#xA;    // since distance sampling already updates the origin of the ray&#xD;&#xA;    ray = ray.medium.phase_sampling(mi);&#xD;&#xA;    path_throughput *= tr;&#xD;&#xA;} else {&#xD;&#xA;    // Nothing to be said here, it's just basic surface rendering process&#xD;&#xA;    // One thing to note is that, transmittance value should be evaluated&#xD;&#xA;    // via ray marching (or some other algorithms)&#xD;&#xA;}&#xD;&#xA;// Okay, then we update our ray for the next intersection and scattering event. Loop continues.&#xD;&#xA;```&#xD;&#xA;There are some details hidden in this pseudo code:&#xD;&#xA;- How do we sample the free path in step 2?&#xD;&#xA;In [Dartmouth distance-sampling, page 7](https://cs.dartmouth.edu/wjarosz/publications/novak18monte-slides-3-distance-sampling.pdf), the sampling process is well explained: first find the bin we are in (since we are using fixed steps, it lefts us several bins in the space), and find the exact position in that bin (so, from discrete bins to continuous distance). &#xD;&#xA;- How to evaluate the transmittance?&#xD;&#xA;For homogeneous medium, it's simple and can be done analytically (if, the medium is exponential). For heterogeneous medium, when ray marching is used, we just subdivide the space and evaluate each part then multiply them together.&#xD;&#xA;- Absorption &amp; scattering coefficient&#xD;&#xA;You will find them in most renders as `sigma_a` and `sigma_s`, they compose a extinction coefficient `sigma_t`. The transmittance of a certain distance is usually:&#xD;&#xA;$$&#xD;&#xA;\exp(-\sigma_t d), \text{ where } d \text{ is the distance} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;For the second question, I believe it has been answered: we **sample** the distance sample (distance traveled before a scattering event) according to the aggregated local transmittance, and we should be able to **evaluate** the transmittance (approximately) for any given path. So for non-uniform transmittance we can use ray marching here.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For the third question:&#xD;&#xA;No. Actually, for heterogeneous medium (not yet for SSS), some better ways are developed already: delta-tracking (woodcock tracking), residual tracking, etc. They are **unbiased** and efficient in multiple ways.&#xD;&#xA;For SSS, path tracing can have extremely poor converge in highly scattering medium (high `sigma_s`, low `sigma_a`) since the energy of the ray won't change much even we have hundreds of scattering events. This is decided by the sampling process, let's take a look at a homogeneous example:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\text{estimator} = \sigma_s\frac{f(x)}{p(x)} = \sigma_s\frac{\exp(-\sigma_t d)}{\sigma_t\exp(-\sigma_t d)} = \frac{\sigma_s}{\sigma_s + \sigma_a} \approx 1&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So, a huge amount of scattering events need to be sampled (hence great `max_depth`) and the variance is pretty high. There are some interesting works on accelerating Monte Carlo SSS rendering, if you are interested:&#xD;&#xA;- Meng, Johannes, Johannes Hanika, and Carsten Dachsbacher. &quot;Improving the Dwivedi sampling scheme.&quot; Computer Graphics Forum. Vol. 35. No. 4. 2016.&#xD;&#xA;- Křivánek, Jaroslav, and Eugene d'Eon. &quot;A zero-variance-based sampling scheme for Monte Carlo subsurface scattering.&quot; ACM SIGGRAPH 2014 Talks. 2014. 1-1.&#xD;&#xA;&#xD;&#xA;The ideas behind these works are basically: the ray will get lost in the highly scattering medium, so we should guide the ray out or to the emitter as quickly as possible.&#xD;&#xA;&#xD;&#xA;I think for SSS, BSSRDF can already be very efficient." ContentLicense="CC BY-SA 4.0" />
  <row Id="41449" PostHistoryTypeId="2" PostId="13641" RevisionGUID="0b57b13d-ab72-440e-931b-6b6d9453096b" CreationDate="2023-08-18T14:33:23.943" UserId="20410" Text="I'm trying to use [Instant NGP][1] on a synthetic image dataset. I have image sequences of a moving object with the following information:&#xD;&#xA;- I have the object's xyz and the camera's xyz positions in a void.&#xD;&#xA;- The object can rotate, and I have it's yaw, pitch, and roll values.&#xD;&#xA;- The object is always centered in the images.&#xD;&#xA;&#xD;&#xA;To use Instant NGP, I need to provide [camera-to-world transforms][2] for each camera, with the camera rotated to look at the object which is centered around [0,0,0] and is in a yaw = pitch = roll = 0 state. I'm a 2D vision person and I can't quite wrap my head around this, and my latest implmentation (based on [this][3]) is close but not right.&#xD;&#xA;&#xD;&#xA;My current approach is:&#xD;&#xA;- Centre the object at [0,0,0]&#xD;&#xA;- Move the camera to the correct relative position (camera - object)&#xD;&#xA;- Rotate the camera's position about the origin to account for the rotation of the object.&#xD;&#xA;- Rotate the camera's look angle to be pointing at the origin.&#xD;&#xA;&#xD;&#xA;But there's a lot of signs, angles, and axes to keep track of and I'm getting something wrong.&#xD;&#xA;&#xD;&#xA;Any advice on how to do this, or the correct terminology for me to search for, would be appreciated. I'm working in python if there are any helper libraries I should be using.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/NVlabs/instant-ngp/tree/master&#xD;&#xA;  [2]: https://github.com/NVlabs/instant-ngp/issues/61&#xD;&#xA;  [3]: https://github.com/wingedrasengan927/Image-formation-and-camera-calibration/tree/master" ContentLicense="CC BY-SA 4.0" />
  <row Id="41451" PostHistoryTypeId="1" PostId="13641" RevisionGUID="0b57b13d-ab72-440e-931b-6b6d9453096b" CreationDate="2023-08-18T14:33:23.943" UserId="20410" Text="Rotating a set of cameras to look at a rotated object" ContentLicense="CC BY-SA 4.0" />
  <row Id="41452" PostHistoryTypeId="3" PostId="13641" RevisionGUID="0b57b13d-ab72-440e-931b-6b6d9453096b" CreationDate="2023-08-18T14:33:23.943" UserId="20410" Text="|3d|camera-matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41453" PostHistoryTypeId="2" PostId="13642" RevisionGUID="84d7935a-6a85-4e2d-b96d-0b65bdbc16ea" CreationDate="2023-08-18T15:33:02.090" UserId="20411" Text="I am trying to implement a simple shader. A round ball object is rendered with uniform albedo and I noticed some strange white spots on the outputs. &#xD;&#xA;I perform importance sampling with 512 light directions on the cosine-weighted hemisphere to render the scene. For debugging purposes, I dropped the specular component from the visualization and only show the `albedo*light` component: &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[\[higher resolution\]][1]&#xD;&#xA;&#xD;&#xA;The spots roughly align with the position of the sun in the env map. From what I have understood the issue is that some values in the hdr are very high (up to `~8384`, 12% of the environment map pixels have a value over `1`). So if one of the very high values is sampled, then the resulting average light intensity will be very high. However, I don't see why the resulting diffuse color is sparse like this.&#xD;&#xA;&#xD;&#xA;From this render, I expect to see a uniform color with a bright side on the left of the sphere. Could this issue be fixed with a more advanced sampling method based on the env map &#xD;&#xA;intensity, or am I missing something with the current approach?&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For additional reference, I use the following python code to query the env map:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;def get_light(self, incident_dir, envir_map):&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;        envir_map: shape (1, 3, H, W)&#xD;&#xA;        incident_dir: (3, point_num*samples_num)&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;    &#xD;&#xA;    # convert from cartesian to spherical&#xD;&#xA;    x,y,z = incident_dir&#xD;&#xA;    phi = torch.arccos(z).flatten() - 1e-6&#xD;&#xA;    theta = torch.atan2(y, x).flatten()&#xD;&#xA;&#xD;&#xA;    # normalize to [-1, 1]&#xD;&#xA;    query_y = (phi / np.pi) * 2 - 1&#xD;&#xA;    query_x = - theta / np.pi&#xD;&#xA;&#xD;&#xA;    # sampling grid is shaped (1, 1, pn*sn, 2)&#xD;&#xA;    grid = torch.stack((query_x, query_y)).permute(1, 0).unsqueeze(0).unsqueeze(0)&#xD;&#xA;    &#xD;&#xA;    # interpolate to query env map, &#xD;&#xA;    sampled = F.grid_sample(envir_map, grid, align_corners=True) # [1, 3, 1, pn*sn]&#xD;&#xA;    light_rgbs = sampled.squeeze().permute(1, 0).reshape(pn, -1, 3) # [pn, sn, 3]&#xD;&#xA;    return light_rgbs&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The environment map looks like so:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Lrzn5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Lrzn5m.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/iphaom.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41455" PostHistoryTypeId="1" PostId="13642" RevisionGUID="84d7935a-6a85-4e2d-b96d-0b65bdbc16ea" CreationDate="2023-08-18T15:33:02.090" UserId="20411" Text="White spots when rendering diffuse material with environment light" ContentLicense="CC BY-SA 4.0" />
  <row Id="41456" PostHistoryTypeId="3" PostId="13642" RevisionGUID="84d7935a-6a85-4e2d-b96d-0b65bdbc16ea" CreationDate="2023-08-18T15:33:02.090" UserId="20411" Text="|rendering|sampling|ibl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41458" PostHistoryTypeId="2" PostId="13643" RevisionGUID="dcf5b0a5-14f6-4bee-a655-fb693e6c88a7" CreationDate="2023-08-19T10:06:07.043" UserId="19537" Text="I think this question lacks some additional information. I used your code to implement a simple diffusive color visualizer, and found nothing strange:&#xD;&#xA;|'Guassian' surface|Lambertian surface|&#xD;&#xA;|:-:|:-:|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|&#xD;&#xA;(Note that, Guassian surface means that the outgoing ray samples is subject to a normal distribution around the normal vector, Lambertian surface just means the cosine-weighted sampling used by you).&#xD;&#xA;&#xD;&#xA;These images are the surface reflected color (cosine-weighted) visualized as a 2D image (mapped to theta and phi). The code can be found here: [Gist: env_map.py](https://gist.github.com/Enigmatisms/8aa4f626a128174f61852ef27bcb4fab), simply run this code with:&#xD;&#xA;```shell&#xD;&#xA;python3 ./env_map.py&#xD;&#xA;```&#xD;&#xA;and you can get these results. So I have no idea why these white spots are there, it seems to me that the code given works, even when I modify how the `theta` and `phi` are computed (in case there is something wrong with your coordinate frame).&#xD;&#xA;&#xD;&#xA;My suggestion is: input other environment maps to see what will happen to the diffuse component. For example, use an environment map with only one white circle and the other parts are black. More inputs get you more information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lBKkH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/820N7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41460" PostHistoryTypeId="5" PostId="13643" RevisionGUID="c0081671-b48a-4981-9123-f5d9df61f617" CreationDate="2023-08-19T13:05:19.990" UserId="19537" Comment="added 2 characters in body" Text="I think this question lacks some additional information. I used your code to implement a simple diffusive color visualizer, and found nothing strange:&#xD;&#xA;&#xD;&#xA;|'Guassian' surface|Lambertian surface|&#xD;&#xA;|:-:|:-:|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|&#xD;&#xA;(Note that, Guassian surface means that the outgoing ray samples is subject to a normal distribution around the normal vector, Lambertian surface just means the cosine-weighted sampling used by you).&#xD;&#xA;&#xD;&#xA;These images are the surface reflected color (cosine-weighted) visualized as a 2D image (mapped to theta and phi). The code can be found here: [Gist: env_map.py](https://gist.github.com/Enigmatisms/8aa4f626a128174f61852ef27bcb4fab), simply run this code with:&#xD;&#xA;```shell&#xD;&#xA;python3 ./env_map.py&#xD;&#xA;```&#xD;&#xA;and you can get these results. So I have no idea why these white spots are there, it seems to me that the code given works, even when I modify how the `theta` and `phi` are computed (in case there is something wrong with your coordinate frame).&#xD;&#xA;&#xD;&#xA;My suggestion is: input other environment maps to see what will happen to the diffuse component. For example, use an environment map with only one white circle and the other parts are black. More inputs get you more information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lBKkH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/820N7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41461" PostHistoryTypeId="2" PostId="13644" RevisionGUID="c23751b8-4e38-40f2-962b-2e84f09462f3" CreationDate="2023-08-19T14:42:26.970" UserId="20413" Text="I want to calculate the capacity that the planet Mars has regarding protecting against UV-light for a final project I will be doing my last year in upper secondary school. UV-light is mainly absorbed in the atmosphere by ozone gas particles and I'm wondering whether it is possible to simulate the ozone gas distribution on Mars and calculate its atmosphere's capacity to absorb the UV-light?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41463" PostHistoryTypeId="1" PostId="13644" RevisionGUID="c23751b8-4e38-40f2-962b-2e84f09462f3" CreationDate="2023-08-19T14:42:26.970" UserId="20413" Text="Can raytracing be used to determine a certain gas distribution in a real planet's atmosphere?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41464" PostHistoryTypeId="3" PostId="13644" RevisionGUID="c23751b8-4e38-40f2-962b-2e84f09462f3" CreationDate="2023-08-19T14:42:26.970" UserId="20413" Text="|raytracing|physics|atmospherics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41465" PostHistoryTypeId="2" PostId="13645" RevisionGUID="37fdb074-ae63-4251-97c5-b8935f5bd19f" CreationDate="2023-08-19T15:15:47.837" UserId="19537" Text="I think it is possible via differentiable rendering techniques, but you are going to need some data for it. Like when you have your model, for example, a spherical heterogeneous scattering medium represented by density grids, and to optimize the parameters you will need observation since this is going to be underdeterminated. &#xD;&#xA;&#xD;&#xA;I am merely stating a possibility here. Note that to get things right, there are some other things you should know:&#xD;&#xA;- Make sure geometric optics can handle your task since current theory based on wave-optics is not so mature. This is very task-specific, some might require the recently put forward ideas like wave-optics rendering, others might involve polarization related rendering.&#xD;&#xA;- Try to get a correct mathematical model, for example, the scattering medium is very likely to be non-exponential. For non-exponential medium, you can refer to:&#xD;&#xA;&#xD;&#xA;[1] Bitterli, Benedikt, et al. &quot;A radiative transfer framework for non-exponential media.&quot; (2018).&#xD;&#xA;&#xD;&#xA;[2] Jarabo, Adrian, Carlos Aliaga, and Diego Gutierrez. &quot;A radiative transfer framework for spatially-correlated materials.&quot; ACM Transactions on Graphics (TOG) 37.4 (2018): 1-13.&#xD;&#xA;&#xD;&#xA;[3] Vicini, Delio, Wenzel Jakob, and Anton Kaplanyan. &quot;A non-exponential transmittance model for volumetric scene representations.&quot; ACM Transactions on Graphics (TOG) 40.4 (2021): 1-16.&#xD;&#xA;&#xD;&#xA;These works are one of the earliest works that introduce non-exponential medium formally into the field of rendering. They are easier to understand compared to the follow up works (especially the first one). The third one has already put the non-exponential model into the inverse rendering problem. So,  if exponential model is not enough (wow, here comes pain), finding a good rendering framework and do refactoring work can be, yeah, fun.&#xD;&#xA;&#xD;&#xA;- To model the surface reflected radiance accurately, you will need a good PBR-BRDF for Mars.&#xD;&#xA;- Read more literature on this topic, being the first one to do something always means pain...&#xD;&#xA;  - Like how differentiable renderer can be used in estimating the density of scattering medium&#xD;&#xA;  - How to efficiently render heterogeneous medium&#xD;&#xA;&#xD;&#xA;Surely these are the problems you are going to solve, and I hope this would help you." ContentLicense="CC BY-SA 4.0" />
  <row Id="41467" PostHistoryTypeId="5" PostId="13643" RevisionGUID="848e88e5-2314-4e78-b63e-304b21828151" CreationDate="2023-08-19T15:31:16.117" UserId="19537" Comment="Update something related to the comments.; added 6 characters in body" Text="I think this question lacks some additional information. I used your code to implement a simple diffusive color visualizer, and found nothing strange:&#xD;&#xA;&#xD;&#xA;|'Guassian' surface|Lambertian surface|&#xD;&#xA;|:---:|:---:|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|&#xD;&#xA;&#xD;&#xA;(Note that, Guassian surface means that the outgoing ray samples is subject to a normal distribution around the normal vector, Lambertian surface just means the cosine-weighted sampling used by you).&#xD;&#xA;&#xD;&#xA;These images are the surface reflected color (cosine-weighted) visualized as a 2D image (mapped to theta and phi). The code can be found here: [Gist: env_map.py](https://gist.github.com/Enigmatisms/8aa4f626a128174f61852ef27bcb4fab), simply run this code with:&#xD;&#xA;```shell&#xD;&#xA;python3 ./env_map.py&#xD;&#xA;```&#xD;&#xA;and you can get these results. So I have no idea why these white spots are there, it seems to me that the code given works, even when I modify how the `theta` and `phi` are computed (in case there is something wrong with your coordinate frame).&#xD;&#xA;&#xD;&#xA;My suggestion is: input other environment maps to see what will happen to the diffuse component. For example, use an environment map with only one white circle and the other parts are black. More inputs get you more information.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Update: I implemented the Hammersley sequence based 'sampling' you mentioned in the comment in my code and the result is like the following. I'm not sure if I get this correctly, and the code is here: [hammersley.cc](https://gist.github.com/Enigmatisms/6b361126b3c6a3cbe28220ca72fa0434), to use it, you can follow the comment in that gist. The original code is also updated.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lBKkH.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/820N7.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/chlYs.png&#xD;&#xA;&#xD;&#xA;There are indeed some artifacts, but not the kind you are looking for (if I get it right)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41468" PostHistoryTypeId="5" PostId="13641" RevisionGUID="1b673974-97fc-4c35-904b-92755a09091a" CreationDate="2023-08-21T09:19:34.043" UserId="20410" Comment="Added detail + images" Text="I'm trying to use [Instant NGP][1] on a synthetic image dataset. I have image sequences of a moving object with the following information:&#xD;&#xA;- I have the object's xyz and the camera's xyz positions in a void.&#xD;&#xA;- The object can rotate, and I have it's yaw, pitch, and roll values.&#xD;&#xA;- The object is always centered in the images.&#xD;&#xA;&#xD;&#xA;To use Instant NGP, I need to provide [camera-to-world transforms][2] for each camera, with the camera rotated to look at the object which is centered around [0,0,0] and is in a yaw = pitch = roll = 0 state. I'm a 2D vision person and I can't quite wrap my head around this, and my latest implmentation (based on [this][3]) is close but not right.&#xD;&#xA;&#xD;&#xA;My current approach is:&#xD;&#xA;- Centre the object at [0,0,0]&#xD;&#xA;- Move the camera to the correct relative position (camera - object)&#xD;&#xA;- Rotate the camera's position about the origin to account for the rotation of the object (roll then yaw)&#xD;&#xA;- Rotate the camera's look angle to be pointing at the origin (roll, then yaw, then pitch)&#xD;&#xA;- Rotate a constant pi/2 roll offset to point the image up.&#xD;&#xA;&#xD;&#xA;But there's a lot of signs, angles, and axes to keep track of and I'm getting something wrong. It is entirely possible my definitions used above are wrong due to inconsistent axes labelling.&#xD;&#xA;&#xD;&#xA;Any advice on how to do this, or the correct terminology for me to search for, would be appreciated. I'm working in python if there are any helper libraries I should be using.&#xD;&#xA;&#xD;&#xA;EDIT TO ADD MORE DETAIL (approach above exapnded):&#xD;&#xA;I tried to get it working on 4 known points (a close pass over the object (in front, directly above, behind), and one from far above.) These are pointing in roughly the right direction but not exactly centered, but I'm happy with the relative positions between object and camera. &#xD;&#xA;&#xD;&#xA;[![Cameras used to develop code against, yellow box is an inset view][4]][4]&#xD;&#xA;&#xD;&#xA;This is an example sequence of views. Again the relative positions seem correct given the object's orientation, but the cameras are mostly looking in the wrong directions:&#xD;&#xA;&#xD;&#xA;[![Example image sequence][5]][5]&#xD;&#xA;[![Cameras pointing in the wrong direction][6]][6]&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/NVlabs/instant-ngp/tree/master&#xD;&#xA;  [2]: https://github.com/NVlabs/instant-ngp/issues/61&#xD;&#xA;  [3]: https://github.com/wingedrasengan927/Image-formation-and-camera-calibration/tree/master&#xD;&#xA;  [4]: https://i.stack.imgur.com/9Nhla.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/VLw5V.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/Yvg2V.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41469" PostHistoryTypeId="50" PostId="13377" RevisionGUID="9c3eb192-476f-437e-9071-e75e251198a2" CreationDate="2023-08-21T13:07:56.003" UserId="-1" />
  <row Id="41470" PostHistoryTypeId="2" PostId="13646" RevisionGUID="cbd02291-d8c1-41b2-b957-d764d375f21f" CreationDate="2023-08-21T15:31:08.223" UserId="20420" Text="I am analyzing a large amount of [Layers 0-4][1] Network Data. I am trying to render diagrams dynamically showing the Network Devices involved in the data (Desktop, Switch, Router, Server, etc.) and how they speak to each other (lines connecting them indicating a data flow). I have a pretty good heuristics from that data on where to place the devices in the diagrams (ARP, Gateways, etc.). My main issue is getting the lines that connect them to stop looking like spaghetti. PCB CAD programs seem to have and solve this issue, but also have to deal with other issues (length/impedance matching, N-layers, etc.).&#xD;&#xA;&#xD;&#xA;I was wondering if there was an algorithm that just did the initial part of PCB Trace layout, specifically:&#xD;&#xA;&#xD;&#xA;Given &#xD;&#xA;* a 2D space&#xD;&#xA;* the graphical location of nodes &#xD;&#xA;* requests to connect some of the nodes together with lines &#xD;&#xA;&#xD;&#xA;Generate line paths that &#xD;&#xA;* limit the number of [crossovers][2] &#xD;&#xA;* Minimize the length of a crossover when they occur&#xD;&#xA;* (not critical) Allow for 90 degree turns to be replaced with two 45 turns (the PCB trace look) &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/OSI_model&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Circuit_diagram" ContentLicense="CC BY-SA 4.0" />
  <row Id="41472" PostHistoryTypeId="1" PostId="13646" RevisionGUID="cbd02291-d8c1-41b2-b957-d764d375f21f" CreationDate="2023-08-21T15:31:08.223" UserId="20420" Text="What algorithms are typically used for finding 'PCB Trace'-like paths?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41473" PostHistoryTypeId="3" PostId="13646" RevisionGUID="cbd02291-d8c1-41b2-b957-d764d375f21f" CreationDate="2023-08-21T15:31:08.223" UserId="20420" Text="|pathtracing|computational-geometry|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41474" PostHistoryTypeId="2" PostId="13647" RevisionGUID="102d1611-8d0c-4109-9fa2-fbdf93796d05" CreationDate="2023-08-21T19:19:09.867" UserId="20422" Text="&quot;[Intersection of Box and Finite Cylinder][1]&quot;, David Eberly, Geometric Tools, Redmond WA 98052&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.geometrictools.com/Documentation/IntersectionBoxCylinder.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="41476" PostHistoryTypeId="2" PostId="13648" RevisionGUID="1792bfdb-7e4e-4aec-a2b4-b29d1c26d34b" CreationDate="2023-08-22T06:26:13.700" UserId="20424" Text="I think so. I did some numerical experiments using Monte-Carlo intergation.&#xD;&#xA;&#xD;&#xA;|                             | discard   | no-discard     | within-range uniform | GT       |&#xD;&#xA;| --------------------------- | --------- | -------------- | -------------------- | -------- |&#xD;&#xA;| $x^2,x\in[0, 2)$            | 14.705318 | **2.66772274** | **2.6668968**        | 2.666666 |&#xD;&#xA;| $\sin x, x\in[0, \pi)$      | 7.4154146 | **1.99990323** | **2.0004143**        | 2        |&#xD;&#xA;| $\text{sigmoid},x\in[0, 1)$ | 6.5161143 | **0.62023634** | **0.6201093**        | 0.620115 |&#xD;&#xA;| $1 / (x+1)^2,x\in[0, 1)$    | 5.2540569 | **0.49955521** | **0.4999410**        | 0.5      |&#xD;&#xA;&#xD;&#xA;`discard` means that we discard the samples that are outside of the range, `no-discard` means that those out-of-range samples will be kept track of. `within-range uniform` means that we sample in that range with uniform distribution so it does not have out-of-range samples in the first place. The original sampling approach is exponential which means that it samples in $[0, \infin)$ therefore will have out-of-range samples." ContentLicense="CC BY-SA 4.0" />
  <row Id="41478" PostHistoryTypeId="2" PostId="13649" RevisionGUID="f6a657d8-1794-4a7b-bef4-1bfbe465da90" CreationDate="2023-08-22T13:07:59.883" UserId="13273" Text="I have a triangular mesh that is read from an &quot;.obj&quot; file and is to be tessellated with respect to the camera position.&#xD;&#xA;&#xD;&#xA;I try to avoid T-junctions by tessellating common edges with the same rounded factor. To do this, I use only the vertices of the edge to calculate a tessellation factor. This way, the common edge for both triangles will have the same tessellation factor.&#xD;&#xA;&#xD;&#xA;**Code:**&#xD;&#xA;&#xD;&#xA;I am currently using the following code to calculate the tessellation levels.&#xD;&#xA;&#xD;&#xA;    vec3 center0 = (viewSpacePosTC[1].xyz + viewSpacePosTC[2].xyz) * 0.5;&#xD;&#xA;    vec3 center1 = (viewSpacePosTC[0].xyz + viewSpacePosTC[2].xyz) * 0.5;&#xD;&#xA;    vec3 center2 = (viewSpacePosTC[0].xyz + viewSpacePosTC[1].xyz) * 0.5;&#xD;&#xA;    float length0 = length(viewSpacePosTC[1].xyz - viewSpacePosTC[2].xyz);&#xD;&#xA;    float length1 = length(viewSpacePosTC[0].xyz - viewSpacePosTC[2].xyz);&#xD;&#xA;    float length2 = length(viewSpacePosTC[0].xyz - viewSpacePosTC[1].xyz);&#xD;&#xA;    float tanFactor0 = length0 / length(center0) / u_maxTan * u_maxCountDivisions;&#xD;&#xA;    float tanFactor1 = length1 / length(center1) / u_maxTan * u_maxCountDivisions;&#xD;&#xA;    float tanFactor2 = length2 / length(center2) / u_maxTan * u_maxCountDivisions;   &#xD;&#xA;&#xD;&#xA;    edgeLod[0] = round(clamp(tanFactor0, 1, u_maxCountDivisions));&#xD;&#xA;    edgeLod[1] = round(clamp(tanFactor1, 1, u_maxCountDivisions));&#xD;&#xA;    edgeLod[2] = round(clamp(tanFactor2, 1, u_maxCountDivisions));&#xD;&#xA;    gl_TessLevelOuter[0] = edgeLod[0];&#xD;&#xA;    gl_TessLevelOuter[1] = edgeLod[1];&#xD;&#xA;    gl_TessLevelOuter[2] = edgeLod[2];&#xD;&#xA;    gl_TessLevelInner[0] = round((edgeLod[0] + edgeLod[1] + edgeLod[2]) * 0.33);&#xD;&#xA;&#xD;&#xA;**The idea behind the code:**&#xD;&#xA;&#xD;&#xA;`length0` `length1` and `length2` are the lengths of the three edges inside the input triangle. `center0` `center1` and `center2` are the centers of the edges in the view space.&#xD;&#xA;`u_maxTan` is a uniform constant passed from the CPU to the shader and contains the value `max(tanX, tanY)`, where `tanX` and `tanY` are the frustum tangents in the x and y directions. `u_maxCountDivisions` is a uniform constant (32).&#xD;&#xA;&#xD;&#xA;The tessellation factor of an edge is rotation independent, since the edge length (rotation independent) and the position of the edge center (`length(center0)` rotation independent) are the only information used to calculate the tessellation factor. Think of it as rotating the edge orthogonally to the frustum and then using the distance to the camera to calculate the tessellation factor (see Figure 2). Beyond the tessellation, a noise function should later shift the generated vertices. The orthogonal approach is to avoid strong flickering when the camera moves.&#xD;&#xA;&#xD;&#xA;**Lets take a look at the output (see figure 1):**&#xD;&#xA;&#xD;&#xA;As we can see, adjacent triangles sharing an edge use the same tessellation factor for the same edge. Thus, no T-junctions occur. However, the inner and outer tessellation planes do not match.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Left: Input triangle mesh. Right: Tessellated output.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** Example of a single edge. Blue: The edge in view space. Red: Edge rotated orthogonally to the camera. The red edge is used to calculate the tessellation level of the edge.&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;How can I avoid the strange tessellation highlighted in Figure 1? I know this is because the inner and outer tessellation levels of this triangle are too different. Calculating a tessellation level for the entire triangle, where each edge gets the same tessellation level, will result in T-junctions. So this is not an option.&#xD;&#xA;&#xD;&#xA;Is it possible to instruct the tessellator to connect the vertices that are close to the edges to the nearest 2 vertices? Then these degenerate sub-triangles will not occur.&#xD;&#xA;&#xD;&#xA;The triangles of the input mesh do not have the same edge length for each edge. Some triangles are small, others are large. So you could say: The tessellation plane depends only on the distance, is not the way I want to solve this problem.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/poqUB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gDkQ7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41480" PostHistoryTypeId="1" PostId="13649" RevisionGUID="f6a657d8-1794-4a7b-bef4-1bfbe465da90" CreationDate="2023-08-22T13:07:59.883" UserId="13273" Text="Find good gl_TessLevel for asteroid surface" ContentLicense="CC BY-SA 4.0" />
  <row Id="41481" PostHistoryTypeId="3" PostId="13649" RevisionGUID="f6a657d8-1794-4a7b-bef4-1bfbe465da90" CreationDate="2023-08-22T13:07:59.883" UserId="13273" Text="|opengl|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41482" PostHistoryTypeId="4" PostId="13649" RevisionGUID="0c864f41-2b8b-4ed1-bd49-681ae6e1aefd" CreationDate="2023-08-22T13:19:06.143" UserId="13273" Comment="edited title" Text="Find good gl_TessLevel for edge distance and edge length" ContentLicense="CC BY-SA 4.0" />
  <row Id="41483" PostHistoryTypeId="5" PostId="13649" RevisionGUID="5d1be8fe-14fd-42c3-ad38-9db86be9b1db" CreationDate="2023-08-22T13:31:58.257" UserId="13273" Comment="edited body" Text="I have a triangular mesh that is read from an &quot;.obj&quot; file and is to be tessellated with respect to the camera position.&#xD;&#xA;&#xD;&#xA;I try to avoid T-junctions by tessellating common edges with the same rounded factor. To do this, I use only the vertices of the edge to calculate a tessellation factor. This way, the common edge for both triangles will have the same tessellation factor.&#xD;&#xA;&#xD;&#xA;**Code:**&#xD;&#xA;&#xD;&#xA;I am currently using the following code to calculate the tessellation levels.&#xD;&#xA;&#xD;&#xA;    vec3 center0 = (viewSpacePosTC[1].xyz + viewSpacePosTC[2].xyz) * 0.5;&#xD;&#xA;    vec3 center1 = (viewSpacePosTC[0].xyz + viewSpacePosTC[2].xyz) * 0.5;&#xD;&#xA;    vec3 center2 = (viewSpacePosTC[0].xyz + viewSpacePosTC[1].xyz) * 0.5;&#xD;&#xA;    float length0 = length(viewSpacePosTC[1].xyz - viewSpacePosTC[2].xyz);&#xD;&#xA;    float length1 = length(viewSpacePosTC[0].xyz - viewSpacePosTC[2].xyz);&#xD;&#xA;    float length2 = length(viewSpacePosTC[0].xyz - viewSpacePosTC[1].xyz);&#xD;&#xA;    float tanFactor0 = length0 / length(center0) / u_maxTan * u_maxCountDivisions;&#xD;&#xA;    float tanFactor1 = length1 / length(center1) / u_maxTan * u_maxCountDivisions;&#xD;&#xA;    float tanFactor2 = length2 / length(center2) / u_maxTan * u_maxCountDivisions;   &#xD;&#xA;&#xD;&#xA;    edgeLod[0] = round(clamp(tanFactor0, 1, u_maxCountDivisions));&#xD;&#xA;    edgeLod[1] = round(clamp(tanFactor1, 1, u_maxCountDivisions));&#xD;&#xA;    edgeLod[2] = round(clamp(tanFactor2, 1, u_maxCountDivisions));&#xD;&#xA;    gl_TessLevelOuter[0] = edgeLod[0];&#xD;&#xA;    gl_TessLevelOuter[1] = edgeLod[1];&#xD;&#xA;    gl_TessLevelOuter[2] = edgeLod[2];&#xD;&#xA;    gl_TessLevelInner[0] = round((edgeLod[0] + edgeLod[1] + edgeLod[2]) * 0.33);&#xD;&#xA;&#xD;&#xA;**The idea behind the code:**&#xD;&#xA;&#xD;&#xA;`length0` `length1` and `length2` are the lengths of the three edges inside the input triangle. `center0` `center1` and `center2` are the centers of the edges in the view space.&#xD;&#xA;`u_maxTan` is a uniform constant passed from the CPU to the shader and contains the value `max(tanX, tanY)`, where `tanX` and `tanY` are the frustum tangents in the x and y directions. `u_maxCountDivisions` is a uniform constant (32).&#xD;&#xA;&#xD;&#xA;The tessellation factor of an edge is rotation independent, since the edge length (rotation independent) and the position of the edge center (`length(center0)` rotation independent) are the only information used to calculate the tessellation factor. Think of it as rotating the edge orthogonally to the frustum and then using the distance to the camera to calculate the tessellation factor (see Figure 2). Beyond the tessellation, a noise function should later shift the generated vertices. The orthogonal approach is to avoid strong flickering when the camera moves.&#xD;&#xA;&#xD;&#xA;**Lets take a look at the output (see figure 1):**&#xD;&#xA;&#xD;&#xA;As we can see, adjacent triangles sharing an edge use the same tessellation factor for the same edge. Thus, no T-junctions occur. However, the inner and outer tessellation planes do not match.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Left: Input triangle mesh. Right: Tessellated output.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** Example of a single edge. Blue: The edge in view space. Red: Edge rotated orthogonally to the camera. The red edge is used to calculate the tessellation level of the edge.&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;How can I avoid the strange tessellation highlighted in Figure 1? I know this is because the inner and outer tessellation levels of this triangle are too different. Calculating a tessellation level for the entire triangle, where each edge gets the same tessellation level, will result in T-junctions. So this is not an option.&#xD;&#xA;&#xD;&#xA;Is it possible to instruct the tessellator to connect the vertices that are close to the edges to the nearest 2 vertices? Then these degenerate sub-triangles will not occur.&#xD;&#xA;&#xD;&#xA;The triangles of the input mesh do not have the same edge length for each edge. Some triangles are small, others are large. So you could say: The tessellation level depends only on the distance, is not the way I want to solve this problem.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/poqUB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gDkQ7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41484" PostHistoryTypeId="2" PostId="13650" RevisionGUID="a5c81e59-5d6b-438d-b5cb-cb8f977a116d" CreationDate="2023-08-22T17:01:36.643" UserId="19163" Text="i am trying to tile a hyperbolic plane using the poincaré or Beltrami–Klein disk model. I am doing it recursively and i don't know how to detect overlapping tiles. I think they are causing bugs because of floating point number precision and performance are very bad, so i need to remove them.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cZcd5.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41486" PostHistoryTypeId="1" PostId="13650" RevisionGUID="a5c81e59-5d6b-438d-b5cb-cb8f977a116d" CreationDate="2023-08-22T17:01:36.643" UserId="19163" Text="How to remove overlapping tiles in hyperbolic tesselation?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41487" PostHistoryTypeId="3" PostId="13650" RevisionGUID="a5c81e59-5d6b-438d-b5cb-cb8f977a116d" CreationDate="2023-08-22T17:01:36.643" UserId="19163" Text="|2d|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41488" PostHistoryTypeId="2" PostId="13651" RevisionGUID="35ad211d-f21e-47b5-a619-cbadeae4a8e8" CreationDate="2023-08-22T19:59:17.550" UserId="20431" Text="I'm working on educating myself more about computer graphics, and the more I learn and play with the technology, the more I get frustrated by the dependencies on C++ (even though I know why it exists). I've built prototype renderers with Vulkan in C# and Go using language-specific bindings to understand the general process. I really enjoy Vulkan and I feel like it's both a good time to learn graphics development and also a great low-level graphics platform.&#xD;&#xA;&#xD;&#xA;As I work through [Real-Time Rendering](https://www.realtimerendering.com/), on my way to [Physically Based Rendering](https://www.pbrt.org/), I want to create the foundations of a personal rendering platform so I can cement knowledge and get some experience. I just... *really don't want to do it in C++*. I know that Vulkan is an API specification (and ecosystem) for the low-level hardware drivers by NVIDIA/Intel/AMD/others, but that's about it.&#xD;&#xA;&#xD;&#xA;I want to evaluate the possibility of writing a non-C++-based Vulkan driver using native syscalls so I don't have to deal with the C++ ecosystem. I would like to assume the OS would pass along the Vulkan syscalls to the hardware drivers, and they would be executed from there, but I'm not really sure. I feel like it's possible, and likely extremely tedious and time-consuming, but it might be worth it if it means I don't have to work entirely in C++.&#xD;&#xA;&#xD;&#xA;Is it possible to make the low-level syscalls (or write ASM for the syscalls) for Vulkan without using the LunarG C/C++ SDK?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41490" PostHistoryTypeId="1" PostId="13651" RevisionGUID="35ad211d-f21e-47b5-a619-cbadeae4a8e8" CreationDate="2023-08-22T19:59:17.550" UserId="20431" Text="Vulkan Syscalls" ContentLicense="CC BY-SA 4.0" />
  <row Id="41491" PostHistoryTypeId="3" PostId="13651" RevisionGUID="35ad211d-f21e-47b5-a619-cbadeae4a8e8" CreationDate="2023-08-22T19:59:17.550" UserId="20431" Text="|c++|vulkan|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41492" PostHistoryTypeId="4" PostId="13650" RevisionGUID="277e1fa7-e80e-484c-a17e-9b7a38e22e26" CreationDate="2023-08-23T06:19:23.133" UserId="19163" Comment="edited title" Text="Hyperbolic tessellation : remove overlapping tiles" ContentLicense="CC BY-SA 4.0" />
  <row Id="41493" PostHistoryTypeId="5" PostId="13649" RevisionGUID="799edb7f-cc07-4825-ba88-07df82a46ed9" CreationDate="2023-08-23T07:39:10.763" UserId="13273" Comment="added 568 characters in body" Text="I have a triangular mesh that is read from an &quot;.obj&quot; file and is to be tessellated with respect to the camera position.&#xD;&#xA;&#xD;&#xA;I try to avoid T-junctions by tessellating common edges with the same rounded factor. To do this, I use only the vertices of the edge to calculate a tessellation factor. This way, the common edge for both triangles will have the same tessellation factor.&#xD;&#xA;&#xD;&#xA;**Code:**&#xD;&#xA;&#xD;&#xA;I am currently using the following code to calculate the tessellation levels.&#xD;&#xA;&#xD;&#xA;    vec3 center0 = (viewSpacePosTC[1].xyz + viewSpacePosTC[2].xyz) * 0.5;&#xD;&#xA;    vec3 center1 = (viewSpacePosTC[0].xyz + viewSpacePosTC[2].xyz) * 0.5;&#xD;&#xA;    vec3 center2 = (viewSpacePosTC[0].xyz + viewSpacePosTC[1].xyz) * 0.5;&#xD;&#xA;    float length0 = length(viewSpacePosTC[1].xyz - viewSpacePosTC[2].xyz);&#xD;&#xA;    float length1 = length(viewSpacePosTC[0].xyz - viewSpacePosTC[2].xyz);&#xD;&#xA;    float length2 = length(viewSpacePosTC[0].xyz - viewSpacePosTC[1].xyz);&#xD;&#xA;    float tanFactor0 = length0 / length(center0) / u_maxTan * u_maxCountDivisions;&#xD;&#xA;    float tanFactor1 = length1 / length(center1) / u_maxTan * u_maxCountDivisions;&#xD;&#xA;    float tanFactor2 = length2 / length(center2) / u_maxTan * u_maxCountDivisions;   &#xD;&#xA;&#xD;&#xA;    edgeLod[0] = round(clamp(tanFactor0, 1, u_maxCountDivisions));&#xD;&#xA;    edgeLod[1] = round(clamp(tanFactor1, 1, u_maxCountDivisions));&#xD;&#xA;    edgeLod[2] = round(clamp(tanFactor2, 1, u_maxCountDivisions));&#xD;&#xA;    gl_TessLevelOuter[0] = edgeLod[0];&#xD;&#xA;    gl_TessLevelOuter[1] = edgeLod[1];&#xD;&#xA;    gl_TessLevelOuter[2] = edgeLod[2];&#xD;&#xA;    gl_TessLevelInner[0] = round((edgeLod[0] + edgeLod[1] + edgeLod[2]) * 0.33);&#xD;&#xA;&#xD;&#xA;**The idea behind the code:**&#xD;&#xA;&#xD;&#xA;`length0` `length1` and `length2` are the lengths of the three edges inside the input triangle. `center0` `center1` and `center2` are the centers of the edges in the view space.&#xD;&#xA;`u_maxTan` is a uniform constant passed from the CPU to the shader and contains the value `max(tanX, tanY)`, where `tanX` and `tanY` are the frustum tangents in the x and y directions. `u_maxCountDivisions` is a uniform constant (32).&#xD;&#xA;&#xD;&#xA;The tessellation factor of an edge is rotation independent, since the edge length (rotation independent) and the position of the edge center (`length(center0)` rotation independent) are the only information used to calculate the tessellation factor. Think of it as rotating the edge orthogonally to the frustum and then using the distance to the camera to calculate the tessellation factor (see Figure 2). Beyond the tessellation, a noise function should later shift the generated vertices. The orthogonal approach is to avoid strong flickering when the camera moves.&#xD;&#xA;&#xD;&#xA;**Lets take a look at the output (see figure 1):**&#xD;&#xA;&#xD;&#xA;As we can see, adjacent triangles sharing an edge use the same tessellation factor for the same edge. Thus, no T-junctions occur. However, the inner and outer tessellation planes do not match.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Left: Input triangle mesh. Right: Tessellated output.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 2:** Example of a single edge. Blue: The edge in view space. Red: Edge rotated orthogonally to the camera. The red edge is used to calculate the tessellation level of the edge.&#xD;&#xA;&#xD;&#xA;**Question:**&#xD;&#xA;&#xD;&#xA;How can I avoid the strange tessellation highlighted in Figure 1? I know this is because the inner and outer tessellation levels of this triangle are too different (difference of about 10). Calculating a tessellation level for the entire triangle, where each edge gets the same tessellation level, will result in T-junctions. So this is not an option.&#xD;&#xA;&#xD;&#xA;Is it possible to instruct the tessellator to connect the vertices that are close to the edges to the nearest 2 vertices? Then these degenerate sub-triangles will not occur.&#xD;&#xA;&#xD;&#xA;The triangles of the input mesh do not have the same edge length for each edge. Some triangles are small, others are large. So you could say: The tessellation level depends only on the distance, is not the way I want to solve this problem.&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;I was thinking of writing my own tessellation in the following way: &#xD;&#xA;&#xD;&#xA; 1. create SSBO of all possible tessellations (inner and outer together with connections).&#xD;&#xA; 2. disable rasterization&#xD;&#xA; 3. render the geometry and write the created vertices (from TES) into a buffer (Vertex Buffer object). At the same time, write the triangle connection into an (IBO) using the SSBO from list item 1.&#xD;&#xA; 4. activate rasterization&#xD;&#xA; 5. Render new VBO and IBO&#xD;&#xA;&#xD;&#xA;But before I program this, I'd like to hear from you what you think about it?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/poqUB.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gDkQ7.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41494" PostHistoryTypeId="2" PostId="13652" RevisionGUID="d73446d4-6e60-41d5-9266-53ef65e68f40" CreationDate="2023-08-23T11:16:49.957" UserId="7952" Text="&#xD;&#xA;&#xD;&#xA;If you want to play with making the calls directly in assembly then write a program in c or C++ (debug it to life) then run it through the disassembler and you be able to find the calls in the assembly language that is output. There will usually be additional code that takes the input of your code and preps for the actual system call. Also, there will be functions that don't do any calls at all.&#xD;&#xA;&#xD;&#xA;I recommend keeping the code as short as possible or even just writing a function that does the call and disassemble that function. This is an excellent tool for various debugging work. ( it is over used in the name of performance)&#xD;&#xA;&#xD;&#xA;I highly recommend doing at least this first step. An excellent method of evaluating functions is to disassemble two similar functions and compare the assembly code. &#xD;&#xA; &#xD;&#xA;Also, this is a good exercise for anyone to go through and most folks gain a whole new appreciation for high level languages once they have written a few simple assembly level programs. Assembly isn't the panacea it was once thought of.&#xD;&#xA;&#xD;&#xA;For most graphics API's at least some portion is written for and executes in user space without actually doing any system calls, or only doing the call after a fair bit of work in the user address space. So some calls may not have a system call in them at all.&#xD;&#xA;&#xD;&#xA;If the goal is to capture the calls and then write another language interface around them, then capturing all the setup, and any work that is done after the call will be necessary as well. And frankly there are better methods.&#xD;&#xA;&#xD;&#xA;Also there will likely be calls down into the operating system that are unrelated to the API but which are, again, setting up for the API call. You will need to be able to filter/understand and recreate these calls before making an actual call.&#xD;&#xA;&#xD;&#xA;Finally, the last I heard, it is the c interface that is the more popular interface for Vulkan not the C++ interface (although most developers are writing programs in C++ and using the c interface). You may want to consider working in the c language. " ContentLicense="CC BY-SA 4.0" />
  <row Id="41496" PostHistoryTypeId="2" PostId="13653" RevisionGUID="1aa29a70-1653-4d50-9e19-f58c62ae91e9" CreationDate="2023-08-23T12:40:55.727" UserId="7464" Text="I want to make &quot;trails&quot; of objects on my shader that appear and disappear gradually.&#xD;&#xA;&#xD;&#xA;I am getting pixels (for fragment shader) where objects are from uniform texture.&#xD;&#xA;&#xD;&#xA;Basically, I have my TARGET_ALPHA for alpha for this pixel.&#xD;&#xA;&#xD;&#xA;How can I interpolate over time (1 second) current alpha for pixel to TARGET_ALPHA?&#xD;&#xA;&#xD;&#xA;I can't understand how to achieve this.&#xD;&#xA;I tried&#xD;&#xA;&#xD;&#xA;```gdscript&#xD;&#xA;ALPHA = mix(ALPHA, TARGET_ALPHA, 0.01); // mix is lerp in godot shader language&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;But it won't work like it's some kind of ordinary game engine code, because ALPHA won't retain it's value every call of shader function and value stays the same.&#xD;&#xA;&#xD;&#xA;I assume something can be done with TIME but I don't understand what. I tried sin(TIME) etc, but it just makes value go up and down, and I want to achieve interpolation without it going back. So my ALPHA would just always follow TARGET_ALPHA with interpolation." ContentLicense="CC BY-SA 4.0" />
  <row Id="41498" PostHistoryTypeId="1" PostId="13653" RevisionGUID="1aa29a70-1653-4d50-9e19-f58c62ae91e9" CreationDate="2023-08-23T12:40:55.727" UserId="7464" Text="How to interpolate alpha from CURRENT_ALPHA to TARGET_ALPHA for each pixel in shader language? (Godot/GLSL)" ContentLicense="CC BY-SA 4.0" />
  <row Id="41499" PostHistoryTypeId="3" PostId="13653" RevisionGUID="1aa29a70-1653-4d50-9e19-f58c62ae91e9" CreationDate="2023-08-23T12:40:55.727" UserId="7464" Text="|shader|glsl|fragment-shader|godot|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41500" PostHistoryTypeId="2" PostId="13654" RevisionGUID="b3e5ddf3-e110-49cb-bf0d-a01d49d3b178" CreationDate="2023-08-23T14:08:37.140" UserId="20435" Text="I am working with volumetric meshes - meshes that have vertices (0-cell), edges (1-cell), facets (2-cells) and volumes (3-cells) - and I'm interested in removing facets without breaking connectedness. &#xD;&#xA;&#xD;&#xA;**In other words, say my mesh has 1 connected component, and I don't want to remove a facet `f` if the resulting mesh has 2 (or more) connected components.**&#xD;&#xA;&#xD;&#xA;A simple approach is to count the number of connected component with and without `f`, with a breadth/depth-first search ([wikipedia.org/wiki/Component_(graph_theory)](https://en.wikipedia.org/wiki/Component_(graph_theory)#Algorithms)). But I don't care how many components there are before or after facet removal, I just don't want this number to change. Any way of estimating the number of connected components looks like a waste of computation time.&#xD;&#xA;&#xD;&#xA;My intuition is that a necessary (but not sufficient) condition for the removal of a facet `f` to possibly &quot;break&quot; connectedness is that both sides of `f` lie in the same volume, while the removal a facet `f'` whose incident volumes are two different volumes cannot modify the connectedness of the mesh. &#xD;&#xA;&#xD;&#xA;Am I wrong ?&#xD;&#xA;&#xD;&#xA;Below is an illustration of a case where the removal of the facet in red would result in two connected components (the little cube inside the big cube). Note that there is no 2-border in this case.&#xD;&#xA;&#xD;&#xA;[![Connectedness break case][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/MsSmr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41502" PostHistoryTypeId="1" PostId="13654" RevisionGUID="b3e5ddf3-e110-49cb-bf0d-a01d49d3b178" CreationDate="2023-08-23T14:08:37.140" UserId="20435" Text="Volumetric mesh processing: impact of facet removal on connectedness?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41503" PostHistoryTypeId="3" PostId="13654" RevisionGUID="b3e5ddf3-e110-49cb-bf0d-a01d49d3b178" CreationDate="2023-08-23T14:08:37.140" UserId="20435" Text="|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41504" PostHistoryTypeId="2" PostId="13655" RevisionGUID="8536d398-394a-4921-adc3-61beb6429d15" CreationDate="2023-08-23T14:14:21.770" UserId="13273" Text="Is there any way to enumerate the generated vertices of a tessellation patch (triangles only) inside the tessellation evaluation shader? &#xD;&#xA;&#xD;&#xA;I am thinking of something like `gl_VertexID`, but only within that one patch. Something that is unique and exactly the same for each rendering. And the enumeration should not contain unused numbers.&#xD;&#xA;&#xD;&#xA;The built-in variables of TES that seem to be useful for creating such a function are:&#xD;&#xA;&#xD;&#xA; - in vec3 gl_TessCoord&#xD;&#xA; - patch in float gl_TessLevelOuter[3]&#xD;&#xA; - patch in float gl_TessLevelInner[1]&#xD;&#xA;&#xD;&#xA;So we know the barycentric coordinates and the tess levels. &#xD;&#xA;How can we create such an enumeration function?&#xD;&#xA;Or does something like this already exist?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41506" PostHistoryTypeId="1" PostId="13655" RevisionGUID="8536d398-394a-4921-adc3-61beb6429d15" CreationDate="2023-08-23T14:14:21.770" UserId="13273" Text="enumerate vertices from tessellation evaluation stage (Triangle patch)" ContentLicense="CC BY-SA 4.0" />
  <row Id="41507" PostHistoryTypeId="3" PostId="13655" RevisionGUID="8536d398-394a-4921-adc3-61beb6429d15" CreationDate="2023-08-23T14:14:21.770" UserId="13273" Text="|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41508" PostHistoryTypeId="5" PostId="13655" RevisionGUID="933e06c9-afe3-4994-8707-02217d0b4de3" CreationDate="2023-08-23T19:12:25.783" UserId="13273" Comment="added 55 characters in body" Text="Is there any way to enumerate the generated vertices of a tessellation patch (triangles only) inside the tessellation evaluation shader? The tessellation levels will only be integer values... &#xD;&#xA;&#xD;&#xA;I am thinking of something like `gl_VertexID`, but only within that one patch. Something that is unique and exactly the same for each rendering. And the enumeration should not contain unused numbers.&#xD;&#xA;&#xD;&#xA;The built-in variables of TES that seem to be useful for creating such a function are:&#xD;&#xA;&#xD;&#xA; - in vec3 gl_TessCoord&#xD;&#xA; - patch in float gl_TessLevelOuter[3]&#xD;&#xA; - patch in float gl_TessLevelInner[1]&#xD;&#xA;&#xD;&#xA;So we know the barycentric coordinates and the tess levels. &#xD;&#xA;How can we create such an enumeration function?&#xD;&#xA;Or does something like this already exist?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41509" PostHistoryTypeId="5" PostId="13655" RevisionGUID="a6795555-aad6-4fe6-b2b2-2d24d9c6b043" CreationDate="2023-08-23T19:27:29.997" UserId="13273" Comment="added 17 characters in body" Text="Is there any way to enumerate the generated vertices of a tessellation patch (triangles only) inside the tessellation evaluation shader? The tessellation levels will only be integer values with equal_spacing. &#xD;&#xA;&#xD;&#xA;I am thinking of something like `gl_VertexID`, but only within that one patch. Something that is unique and exactly the same for each rendering. And the enumeration should not contain unused numbers.&#xD;&#xA;&#xD;&#xA;The built-in variables of TES that seem to be useful for creating such a function are:&#xD;&#xA;&#xD;&#xA; - in vec3 gl_TessCoord&#xD;&#xA; - patch in float gl_TessLevelOuter[3]&#xD;&#xA; - patch in float gl_TessLevelInner[1]&#xD;&#xA;&#xD;&#xA;So we know the barycentric coordinates and the tess levels. &#xD;&#xA;How can we create such an enumeration function?&#xD;&#xA;Or does something like this already exist?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41510" PostHistoryTypeId="50" PostId="12807" RevisionGUID="e7938e79-30ec-48d0-b212-9acd0ff7bbab" CreationDate="2023-08-23T20:04:20.450" UserId="-1" />
  <row Id="41511" PostHistoryTypeId="50" PostId="10535" RevisionGUID="a416403d-6df7-42f6-8d9b-1a7bc5b84761" CreationDate="2023-08-24T00:06:36.067" UserId="-1" />
  <row Id="41512" PostHistoryTypeId="2" PostId="13656" RevisionGUID="2246bb62-2c22-466d-bf75-881ef28c66c1" CreationDate="2023-08-24T04:31:20.080" UserId="20437" Text="If you are using two graphics cards, check if the control panel or drive on the graphics card is working properly&#xD;&#xA;In my case, the graphic card control panel was deleted for some reason and I had such an error." ContentLicense="CC BY-SA 4.0" />
  <row Id="41514" PostHistoryTypeId="5" PostId="13648" RevisionGUID="23040029-acb4-4811-be2f-27ca01d3e085" CreationDate="2023-08-24T06:03:12.417" UserId="10096" Comment="edited body" Text="I think so. I did some numerical experiments using Monte-Carlo intergation.&#xD;&#xA;&#xD;&#xA;|                             | discard   | no-discard     | within-range uniform | GT       |&#xD;&#xA;| --------------------------- | --------- | -------------- | -------------------- | -------- |&#xD;&#xA;| $x^2,x\in[0, 2)$            | 14.705318 | **2.66772274** | **2.6668968**        | 2.666666 |&#xD;&#xA;| $\sin x, x\in[0, \pi)$      | 7.4154146 | **1.99990323** | **2.0004143**        | 2        |&#xD;&#xA;| $\text{sigmoid},x\in[0, 1)$ | 6.5161143 | **0.62023634** | **0.6201093**        | 0.620115 |&#xD;&#xA;| $1 / (x+1)^2,x\in[0, 1)$    | 5.2540569 | **0.49955521** | **0.4999410**        | 0.5      |&#xD;&#xA;&#xD;&#xA;`discard` means that we discard the samples that are outside of the range, `no-discard` means that those out-of-range samples will be kept track of. `within-range uniform` means that we sample in that range with uniform distribution so it does not have out-of-range samples in the first place. The original sampling approach is exponential which means that it samples in $[0, \infty)$ therefore will have out-of-range samples." ContentLicense="CC BY-SA 4.0" />
  <row Id="41515" PostHistoryTypeId="5" PostId="13654" RevisionGUID="d01b7c19-28b5-4adf-828e-7eb77d6035a6" CreationDate="2023-08-24T06:07:58.613" UserId="20435" Comment="illustration update" Text="I am working with volumetric meshes - meshes that have vertices (0-cell), edges (1-cell), facets (2-cells) and volumes (3-cells) - and I'm interested in removing facets without breaking connectedness. &#xD;&#xA;&#xD;&#xA;**In other words, say my mesh has 1 connected component, and I don't want to remove a facet `f` if the resulting mesh has 2 (or more) connected components.**&#xD;&#xA;&#xD;&#xA;A simple approach is to count the number of connected component with and without `f`, with a breadth/depth-first search ([wikipedia.org/wiki/Component_(graph_theory)](https://en.wikipedia.org/wiki/Component_(graph_theory)#Algorithms)). But I don't care how many components there are before or after facet removal, I just don't want this number to change. Any way of estimating the number of connected components looks like a waste of computation time.&#xD;&#xA;&#xD;&#xA;My intuition is that a necessary (but not sufficient) condition for the removal of a facet `f` to possibly &quot;break&quot; connectedness is that both sides of `f` lie in the same volume, while the removal a facet `f'` whose incident volumes are two different volumes cannot modify the connectedness of the mesh. &#xD;&#xA;&#xD;&#xA;Am I wrong ?&#xD;&#xA;&#xD;&#xA;Below is an illustration of a case where the removal of the facet in red would result in two connected components (the little cube inside the big cube). Note that there is no 2-border in this case.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9656C.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41516" PostHistoryTypeId="2" PostId="13657" RevisionGUID="8904be44-c124-4bdf-83a5-ba6aff9f2bdc" CreationDate="2023-08-24T08:06:23.280" UserId="7724" Text="With glMultiDrawElementsBasevertex it becomes possible to render multiple sets of indices in one draw call. When using for instance GL_UNSIGNED_SHORT as the type of the indices is there still a restriction that only MAX_UNSIGNED_SHORT vertices can be rendered at a time? Or does the combination with multiple base vertices allow to exceed this number and allow for multiple sets of sub-draw calls provided that these do not exceed the MAX_UNSIGNED_SHORT restriction in relation to their base vertex? &#xD;&#xA;&#xD;&#xA;So for instance given the following input to the command:&#xD;&#xA;&#xD;&#xA;$count = [65535, 65535]$&#xD;&#xA;&#xD;&#xA;$indices = [indexOffset0, indexOffset1]$&#xD;&#xA;&#xD;&#xA;$baseVertex = [0, 65536]$&#xD;&#xA;&#xD;&#xA;will the basevertex offset (&gt;MAX_UNSIGNED_SHORT) be correctly added to the index found at indexOffset1? I don't believe the specs raise anything about the types of indices used and the number of vertices referenced." ContentLicense="CC BY-SA 4.0" />
  <row Id="41518" PostHistoryTypeId="1" PostId="13657" RevisionGUID="8904be44-c124-4bdf-83a5-ba6aff9f2bdc" CreationDate="2023-08-24T08:06:23.280" UserId="7724" Text="Is MultiDrawElementsBaseVertex bound by index type?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41519" PostHistoryTypeId="3" PostId="13657" RevisionGUID="8904be44-c124-4bdf-83a5-ba6aff9f2bdc" CreationDate="2023-08-24T08:06:23.280" UserId="7724" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41520" PostHistoryTypeId="2" PostId="13658" RevisionGUID="0ff030fc-c2ae-45c9-81b9-7b3b2699cd07" CreationDate="2023-08-24T13:00:27.767" UserId="20388" Text="I'm writing a raytracer in Java that draws a scene containing the elliptic paraboloid defined by the equation $x^2+z^2=y$. &#xD;&#xA;&#xD;&#xA;To compute the surface normal to this, I'm taking the normalized gradient of the equation:&#xD;&#xA;$\nabla F(x,y,z) = \left&lt;2x, -1, 2z\right&gt;$. To ensure that the normal is on the correct surface, I take the dot product with the incident ray and flip the normal if the dot product is negative.&#xD;&#xA;&#xD;&#xA;However, when I render the image, I observe this strange outline around the object:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have no idea why this is, but I believe it has something to do with rounding errors during this sign-change step. I'm not sure why this would be though; I'm using double-precision floating-point  numbers (Java's ```double``` type) for all calculations. When I remove this check, the normals are broken, but the outline disappears. How might I be able to fix this?&#xD;&#xA;&#xD;&#xA;Here's where the normal is computed:&#xD;&#xA;```java&#xD;&#xA;Vec3 dP = pt.sub(pos);&#xD;&#xA;Vec3 normal = new Vec3(2 * dP.x, -1, 2 * dP.z)&#xD;&#xA;       .getNormalized()&#xD;&#xA;       .faceForward(ray.rd);&#xD;&#xA;```&#xD;&#xA;where ```pos``` is the object's local position, and ```ray.rd``` is the ray's direction.&#xD;&#xA;&#xD;&#xA;Here's the code responsible for the check (the ```faceForward``` function in the above code):&#xD;&#xA;&#xD;&#xA;```java&#xD;&#xA;public Vec3 faceForward(Vec3 incident) {&#xD;&#xA;    boolean outside = (this.dot(incident) &lt; 0);&#xD;&#xA;    return (outside ? this : this.negate());&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HBdQO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41522" PostHistoryTypeId="1" PostId="13658" RevisionGUID="0ff030fc-c2ae-45c9-81b9-7b3b2699cd07" CreationDate="2023-08-24T13:00:27.767" UserId="20388" Text="Precision errors with raytracing normal" ContentLicense="CC BY-SA 4.0" />
  <row Id="41523" PostHistoryTypeId="3" PostId="13658" RevisionGUID="0ff030fc-c2ae-45c9-81b9-7b3b2699cd07" CreationDate="2023-08-24T13:00:27.767" UserId="20388" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41524" PostHistoryTypeId="5" PostId="13658" RevisionGUID="f49c0abc-6150-4361-ae26-b9c1f9627020" CreationDate="2023-08-24T13:06:36.353" UserId="20388" Comment="added 17 characters in body" Text="I'm writing a raytracer in Java that draws a scene containing the elliptic paraboloid defined by the equation $F(x,y,z)=x^2+z^2-y=0$. &#xD;&#xA;&#xD;&#xA;To compute the surface normal to this, I'm taking the normalized gradient of the equation:&#xD;&#xA;$\vec{\nabla} F(x,y,z) = \left&lt;2x, -1, 2z\right&gt;$. To ensure that the normal is on the correct surface, I take the dot product with the incident ray and flip the normal if the dot product is negative.&#xD;&#xA;&#xD;&#xA;However, when I render the image, I observe this strange outline around the object:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I have no idea why this is, but I believe it has something to do with rounding errors during this sign-change step. I'm not sure why this would be though; I'm using double-precision floating-point  numbers (Java's ```double``` type) for all calculations. When I remove this check, the normals are broken, but the outline disappears. How might I be able to fix this?&#xD;&#xA;&#xD;&#xA;Here's where the normal is computed:&#xD;&#xA;```java&#xD;&#xA;Vec3 dP = pt.sub(pos);&#xD;&#xA;Vec3 normal = new Vec3(2 * dP.x, -1, 2 * dP.z)&#xD;&#xA;       .getNormalized()&#xD;&#xA;       .faceForward(ray.rd);&#xD;&#xA;```&#xD;&#xA;where ```pos``` is the object's local position, and ```ray.rd``` is the ray's direction.&#xD;&#xA;&#xD;&#xA;Here's the code responsible for the check (the ```faceForward``` function in the above code):&#xD;&#xA;&#xD;&#xA;```java&#xD;&#xA;public Vec3 faceForward(Vec3 incident) {&#xD;&#xA;    boolean outside = (this.dot(incident) &lt; 0);&#xD;&#xA;    return (outside ? this : this.negate());&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HBdQO.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41525" PostHistoryTypeId="2" PostId="13659" RevisionGUID="ac97cd4e-a656-4834-a446-8f744cfaf4c1" CreationDate="2023-08-24T13:59:26.600" UserId="19537" Text="[Equiangular sampling](https://onlinelibrary.wiley.com/doi/abs/10.1111/j.1467-8659.2012.03148.x) is a sampling method for point (sphere) emitter in scattering medium. While it claims to be very efficient when dealing with point (sphere) emitter in scattering medium (see this [shadertoy example](https://www.shadertoy.com/view/Xdf3zB)), I find most of the reference and implementations to have only done about two bounces and for higher order scattering, equiangular sampling fails to distinguish itself from the standard exponential distance sampling:&#xD;&#xA;&#xD;&#xA;|Equiangular 2 bounces|Exponential 2 bounces|Equiangular 400 bounces|Exponential 400 bounces|&#xD;&#xA;|--|--|--|--|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|[![enter image description here][3]][3]|[![enter image description here][4]][4]|&#xD;&#xA;&#xD;&#xA;As can be seen above, when we have only 2 bounces the equiangular sampling is clearly better but if we do not clip the bounces to just 2 (the number of bounces up-to 400) the result is just ordinary. So why would this happen? Does this mean that equiangular sampling can't actually handle high-order scattering well? Or is there anything wrong with my code? My implementation is embedded in PBRT-v3, simply add a function in `media/homogeneous.cpp` and pass the position of the point source in `integrator/volpath.cpp`. &#xD;&#xA;&#xD;&#xA;The scene is cornell box scene with point source being `LightSource &quot;point&quot; &quot;rgb I&quot; [10. 10. 10.] &quot;point from&quot; [2.779 4.8 2.4]` and the parameters for scattering medium is: ` &quot;rgb sigma_s&quot; [0.4 0.4 0.4] &quot;rgb sigma_a&quot; [0.005 0.005 0.005]`. There is a homogeneous medium box enclosing the whole scene. Camera params: `LookAt 2.78 2.73 -8.00  2.78 2.73 0   0 1 0&#xD;&#xA;Camera &quot;perspective&quot; &quot;float fov&quot; [39.3077]`. The equiangular implementation is simple:&#xD;&#xA;&#xD;&#xA;```c++&#xD;&#xA;Spectrum HomogeneousMedium::equiangular_sample(&#xD;&#xA;    const Ray &amp;ray, Sampler &amp;sampler, MemoryArena &amp;arena, MediumInteraction *mi, const Point3f&amp; target_p&#xD;&#xA;) const {&#xD;&#xA;    ProfilePhase _(Prof::MediumSample);&#xD;&#xA;    // Sample a channel and distance along the ray&#xD;&#xA;    int channel = std::min((int)(sampler.Get1D() * Spectrum::nSamples),&#xD;&#xA;                           Spectrum::nSamples - 1);&#xD;&#xA;    // Sample a scattering event: surface or medium?&#xD;&#xA;    Float dist = -std::log(1 - sampler.Get1D()) / sigma_t[channel];&#xD;&#xA;    Float d_length = ray.d.Length(), t = std::min(dist / d_length, ray.tMax);&#xD;&#xA;    bool sampledMedium = t &lt; ray.tMax;&#xD;&#xA;&#xD;&#xA;    Float theta_a = 0, theta_b = 0, D = 0, sampled_t = 0, sample_pdf = 1.0;&#xD;&#xA;    if (sampledMedium) {&#xD;&#xA;        // equiangular sampling: overriding the sampled `t`&#xD;&#xA;        Vector3f diff_vec = target_p - ray.o;&#xD;&#xA;        Float dot_val = Dot(diff_vec, ray.d);&#xD;&#xA;        Float proj_len = dot_val / d_length;&#xD;&#xA;        D = sqrtf(diff_vec.LengthSquared() - proj_len * proj_len);&#xD;&#xA;        &#xD;&#xA;		theta_a = atan2f(1e-4 - proj_len, D);&#xD;&#xA;        theta_b = atan2f(ray.tMax - proj_len, D);&#xD;&#xA;        Float sample = sampler.Get1D();&#xD;&#xA;        sampled_t = D * tanf(theta_a * (1 - sample) + sample * theta_b);&#xD;&#xA;        t = (sampled_t + proj_len) / d_length;&#xD;&#xA;		&#xD;&#xA;        sample_pdf = D / fabsf(theta_b - theta_a) / (D * D + sampled_t * sampled_t);&#xD;&#xA;        *mi = allocate_it(ray, arena, t);&#xD;&#xA;    }&#xD;&#xA;    // Compute the transmittance and sampling density&#xD;&#xA;    // Note that we can not modify the sigma_t here, since it's calculating contribution&#xD;&#xA;    Float actual_d = std::min(t, MaxFloat) * d_length;&#xD;&#xA;    Float wall_pdf = expf(-sigma_t[channel] * std::min(ray.tMax, MaxFloat) * d_length);&#xD;&#xA;    Spectrum Tr = Exp(-sigma_t * actual_d);&#xD;&#xA;    &#xD;&#xA;    Float pdf = (1.f - wall_pdf) * sample_pdf;&#xD;&#xA;    return sampledMedium ? (Tr * sigma_s / pdf) : (Tr / wall_pdf);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cB02m.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gyhti.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/MjYe8.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/yI3R0.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41527" PostHistoryTypeId="1" PostId="13659" RevisionGUID="ac97cd4e-a656-4834-a446-8f744cfaf4c1" CreationDate="2023-08-24T13:59:26.600" UserId="19537" Text="Questions about equi-angular sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="41528" PostHistoryTypeId="3" PostId="13659" RevisionGUID="ac97cd4e-a656-4834-a446-8f744cfaf4c1" CreationDate="2023-08-24T13:59:26.600" UserId="19537" Text="|sampling|importance-sampling|monte-carlo|volume-rendering|pbrt-v3|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41529" PostHistoryTypeId="5" PostId="13657" RevisionGUID="606a7a45-a6c7-4c16-958e-27d21434c0ad" CreationDate="2023-08-24T15:58:14.303" UserId="445" Comment="fix words-in-math formatting; add code formatting" Text="With `glMultiDrawElementsBaseVertex` it becomes possible to render multiple sets of indices in one draw call. When using for instance `GL_UNSIGNED_SHORT` as the type of the indices is there still a restriction that only `MAX_UNSIGNED_SHORT` vertices can be rendered at a time? Or does the combination with multiple base vertices allow to exceed this number and allow for multiple sets of sub-draw calls provided that these do not exceed the `MAX_UNSIGNED_SHORT` restriction in relation to their base vertex? &#xD;&#xA;&#xD;&#xA;So for instance given the following input to the command:&#xD;&#xA;&#xD;&#xA;$\mathit{count} = [65535, 65535]$&#xD;&#xA;&#xD;&#xA;$\mathit{indices} = [\mathit{indexOffset0}, \mathit{indexOffset1}]$&#xD;&#xA;&#xD;&#xA;$\mathit{baseVertex} = [0, 65536]$&#xD;&#xA;&#xD;&#xA;will the baseVertex offset (&gt; `MAX_UNSIGNED_SHORT`) be correctly added to the index found at indexOffset1? I don't believe the specs raise anything about the types of indices used and the number of vertices referenced." ContentLicense="CC BY-SA 4.0" />
  <row Id="41530" PostHistoryTypeId="24" PostId="13657" RevisionGUID="606a7a45-a6c7-4c16-958e-27d21434c0ad" CreationDate="2023-08-24T15:58:14.303" Comment="Proposed by 445 approved by 7724 edit id of 625" ContentLicense="CC BY-SA 4.0" />
  <row Id="41531" PostHistoryTypeId="5" PostId="13658" RevisionGUID="46c2b15c-df3a-4c53-bb6d-b388b9c20135" CreationDate="2023-08-24T20:09:19.127" UserId="20388" Comment="Added more details" Text="I'm writing a raytracer in Java that draws a scene containing the elliptic paraboloid defined by the equation $F(x,y,z)=x^2+z^2-y=0$, as well as the hyperbolic paraboloid defined by $G(x,y,z)=x^2-z^2-y=0$. &#xD;&#xA;&#xD;&#xA;To compute the surface normal to this, I'm taking the normalized gradients of the equations:&#xD;&#xA;$\vec{\nabla} F(x,y,z) = \left&lt;2x, -1, 2z\right&gt;\\&#xD;&#xA;\vec{\nabla} G(x,y,z) = \left&lt;2x, -1, -2z\right&gt;$. &#xD;&#xA;&#xD;&#xA;To ensure that the normal is on the correct surface, I take the dot product with the incident ray and flip the normal if the dot product is negative.&#xD;&#xA;&#xD;&#xA;However, when I render the image, I observe this strange outline around the object:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I can tell that this is a normal-related issue because when I color the objects based on their normals, I can see discontinuities:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have no idea why this is, but I believe it has something to do with rounding errors during this sign-change step. I'm not sure why this would be though; I'm using double-precision floating-point  numbers (Java's ```double``` type) for all calculations. When I remove this check, the normals are broken, but the outline disappears. How might I be able to fix this?&#xD;&#xA;&#xD;&#xA;Here's where the normal is computed:&#xD;&#xA;```java&#xD;&#xA;Vec3 dP = pt.sub(pos);&#xD;&#xA;Vec3 normal = new Vec3(2 * dP.x, -1, 2 * dP.z)&#xD;&#xA;       .getNormalized()&#xD;&#xA;       .faceForward(ray.rd);&#xD;&#xA;```&#xD;&#xA;where ```pos``` is the object's local position, and ```ray.rd``` is the ray's direction.&#xD;&#xA;&#xD;&#xA;Here's the code responsible for the check (the ```faceForward``` function in the above code):&#xD;&#xA;&#xD;&#xA;```java&#xD;&#xA;public Vec3 faceForward(Vec3 incident) {&#xD;&#xA;    boolean outside = (this.dot(incident) &lt; 0);&#xD;&#xA;    return (outside ? this : this.negate());&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HBdQO.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/e4eDF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41532" PostHistoryTypeId="2" PostId="13660" RevisionGUID="9163268c-0b65-4ba3-bdd6-1c27a58a8acb" CreationDate="2023-08-25T00:25:17.237" UserId="20440" Text="I am using NVIDIA Nsight to debug my OpenGL state. In the screenshots below:&#xD;&#xA;&#xD;&#xA;- I generate a single texture with the ID `10`. &#xD;&#xA;- I activate `GL_TEXTURE0` and bind texture `10` to that texture unit.&#xD;&#xA;- I generate a single texture with the ID `11`. &#xD;&#xA;- I activate `GL_TEXTURE1` and bind texture `11` to that texture unit.&#xD;&#xA;&#xD;&#xA;When I view the API inspector, I see that texture `11` is bound to both `unit 0` and `unit 1`, which I presume is `GL_TEXTURE0` and `GL_TEXTURE1`.&#xD;&#xA;&#xD;&#xA;Am I misunderstanding something about how texture units work in OpenGL? This is not the behavior I would expect.&#xD;&#xA;&#xD;&#xA;[![Events tab][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![API Inspector, Textures][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Y6lUC.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/YTTcY.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41534" PostHistoryTypeId="1" PostId="13660" RevisionGUID="9163268c-0b65-4ba3-bdd6-1c27a58a8acb" CreationDate="2023-08-25T00:25:17.237" UserId="20440" Text="OpenGL texture unit bindings - Why is a single texture mapped to both texture units when each are individually assigned?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41535" PostHistoryTypeId="3" PostId="13660" RevisionGUID="9163268c-0b65-4ba3-bdd6-1c27a58a8acb" CreationDate="2023-08-25T00:25:17.237" UserId="20440" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41536" PostHistoryTypeId="2" PostId="13661" RevisionGUID="6d2c863b-a3af-482a-bc83-e374d86eaef4" CreationDate="2023-08-25T00:47:08.340" UserId="20440" Text="Fixed. I feel pretty silly. When I set `glActiveTexture` it primes the OpenGL context to set the active texture for **all** subsequence texture binds. Thus the bind at line 66 overwrites it. I solved this by setting `GL_TEXTURE0` as my 'reset' texture and setting `glActivateTexture(GL_TEXTURE0)` when I am done binding a texture unit." ContentLicense="CC BY-SA 4.0" />
  <row Id="41539" PostHistoryTypeId="2" PostId="13662" RevisionGUID="deabab2d-c77a-41f2-b44e-5e504dacf4d1" CreationDate="2023-08-25T09:25:09.970" UserId="13273" Text="I have written a function in GLSL that returns the min index (index 0 is the x component, 1 is the y component, and 2 is the z component) of a vec3 variable.&#xD;&#xA;&#xD;&#xA;    uint getMinIndex(vec3 vector)&#xD;&#xA;    {&#xD;&#xA;        float minValue = min(min(vector.x, vector.y), vector.z);&#xD;&#xA;        if(vector.x == minValue)&#xD;&#xA;            return 0;&#xD;&#xA;        if(vector.y == minValue)&#xD;&#xA;            return 1;&#xD;&#xA;        return 2;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As you can see, this function causes branching and slows down the whole shader.... Is there already such a function in GLSL? Or is there a better way to do this without branching?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41541" PostHistoryTypeId="1" PostId="13662" RevisionGUID="deabab2d-c77a-41f2-b44e-5e504dacf4d1" CreationDate="2023-08-25T09:25:09.970" UserId="13273" Text="GLSL get min/max index of vec3" ContentLicense="CC BY-SA 4.0" />
  <row Id="41542" PostHistoryTypeId="3" PostId="13662" RevisionGUID="deabab2d-c77a-41f2-b44e-5e504dacf4d1" CreationDate="2023-08-25T09:25:09.970" UserId="13273" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41543" PostHistoryTypeId="2" PostId="13663" RevisionGUID="f86392f0-a289-4b33-b782-0e44d0edebb7" CreationDate="2023-08-25T12:30:11.607" UserId="13273" Text="After a whole day of brain stress, I found a method to enumerate them:&#xD;&#xA;&#xD;&#xA;    //floats equal? with respect of epsilon&#xD;&#xA;    bool isNearlyTheSame(float value0, float value1) &#xD;&#xA;    {&#xD;&#xA;        return abs(value0 - value1) &lt; 0.001;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //result: x: 1 =&gt; inner triangles, 0 =&gt; inner most vertex, 2 =&gt; outer vertices&#xD;&#xA;    //result: y: lowest barycentric value is: 1 =&gt; x, 2 =&gt; y, 3 =&gt; z  &#xD;&#xA;    uvec2 getBarycentricCase() &#xD;&#xA;    {&#xD;&#xA;        uvec2 baryCase = uvec2(1,0);&#xD;&#xA;        if(gl_TessCoord.x &lt; gl_TessCoord.y &amp;&amp; gl_TessCoord.x &lt;= gl_TessCoord.z + 0.001)&#xD;&#xA;        {&#xD;&#xA;            baryCase.y = 1;&#xD;&#xA;        }&#xD;&#xA;        if(gl_TessCoord.y &lt;= gl_TessCoord.x + 0.001 &amp;&amp; gl_TessCoord.y &lt; gl_TessCoord.z)&#xD;&#xA;        {&#xD;&#xA;            baryCase.y = 2;&#xD;&#xA;        }&#xD;&#xA;        if(gl_TessCoord.z &lt; gl_TessCoord.x &amp;&amp; gl_TessCoord.z &lt;= gl_TessCoord.y + 0.001)&#xD;&#xA;        {&#xD;&#xA;            baryCase.y = 3;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if(gl_TessCoord.x == 0 || gl_TessCoord.y == 0 || gl_TessCoord.z == 0)&#xD;&#xA;            baryCase.x = 2;&#xD;&#xA;&#xD;&#xA;        if(isNearlyTheSame(gl_TessCoord.x, gl_TessCoord.y) &amp;&amp; isNearlyTheSame(gl_TessCoord.y, gl_TessCoord.z))&#xD;&#xA;            baryCase.x = 0;&#xD;&#xA;        return baryCase;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //returns a third of the count of the inner vertices with respect to the tessLevel&#xD;&#xA;    uint getNummTessPart(uint tessLevel)&#xD;&#xA;    {&#xD;&#xA;        float tesslvl = float(tessLevel);&#xD;&#xA;        return uint(tesslvl / 2.0 * (tesslvl / 2.0 - 1));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //returns the current patch vertex id with respect to this algorithm&#xD;&#xA;    uint getPatchVertexID()&#xD;&#xA;    {&#xD;&#xA;        uint result = 0;&#xD;&#xA;        uvec2 baryCase = getBarycentricCase();&#xD;&#xA;        float baseValue = min(min(gl_TessCoord.x,gl_TessCoord.y), gl_TessCoord.z);&#xD;&#xA;        float leftValue = baryCase.y == 1 ? gl_TessCoord.z : baryCase.y == 2 ? gl_TessCoord.x : baryCase.y == 3 ? gl_TessCoord.y : 0;&#xD;&#xA;        uint positionUp = 0;&#xD;&#xA;        uint positionLeft = 0;&#xD;&#xA;&#xD;&#xA;        float stepUp = 2.0 / 3.0 / float(gl_TessLevelInner[0]);&#xD;&#xA;        float stepLeft = 1.0 / gl_TessLevelInner[0];&#xD;&#xA;&#xD;&#xA;        if(baryCase.x == 1) //inner vertex&#xD;&#xA;        {&#xD;&#xA;            positionUp = uint(round(baseValue / stepUp));&#xD;&#xA;            positionLeft = uint(round(leftValue / stepLeft + (positionUp) * stepUp * gl_TessLevelInner[0] / 2 - positionUp));&#xD;&#xA;            result = getNummTessPart(uint(gl_TessLevelInner[0])) - getNummTessPart(uint(gl_TessLevelInner[0] - ((positionUp-1) * 2)));&#xD;&#xA;            result += positionLeft;&#xD;&#xA;            result += (baryCase.y - 1) * getNummTessPart(uint(gl_TessLevelInner[0]));&#xD;&#xA;        }&#xD;&#xA;        else if(baryCase.x == 0) // most inner vertex (only even tessellation)&#xD;&#xA;        {&#xD;&#xA;            result = getNummTessPart(uint(gl_TessLevelInner[0])) * 3;&#xD;&#xA;        }&#xD;&#xA;        else if(baryCase.x == 2) // outer vertex&#xD;&#xA;        {&#xD;&#xA;            result = getNummTessPart(uint(gl_TessLevelInner[0])) * 3;&#xD;&#xA;            float stepX = 1.0 / gl_TessLevelOuter[0];&#xD;&#xA;            float stepY = 1.0 / gl_TessLevelOuter[1];&#xD;&#xA;            float stepZ = 1.0 / gl_TessLevelOuter[2];&#xD;&#xA;&#xD;&#xA;            if(baryCase.y == 1) //on the x side&#xD;&#xA;            {&#xD;&#xA;                result += uint(round(leftValue / stepX));&#xD;&#xA;            }&#xD;&#xA;            if(baryCase.y == 2) //on the y side&#xD;&#xA;            {&#xD;&#xA;                result += uint(round(leftValue / stepY));&#xD;&#xA;                result += uint(gl_TessLevelOuter[0]);&#xD;&#xA;            }&#xD;&#xA;            if(baryCase.y == 3) //on the z side&#xD;&#xA;            {&#xD;&#xA;                result += uint(round(leftValue / stepZ));&#xD;&#xA;                result += uint(gl_TessLevelOuter[0] + gl_TessLevelOuter[1]);&#xD;&#xA;            }&#xD;&#xA;            if(mod(gl_TessLevelInner[0],2) == 0) //in case of even tessellation level there is an additional most inner vertex&#xD;&#xA;                result++;&#xD;&#xA;        }&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As can be seen in Figure 1, the algorithm first enumerates the inner vertices, dividing them into 3 parts. After the inner vertices, the innermost vertex (in case of an even innerTessLevel) is enumerated. At the end, the outer vertices are enumerated.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Enumeration sceme for: `gl_TessLevelInner[0] = 10`, `gl_TessLevelOuter[0] = 10`, `gl_TessLevelOuter[1] = 10`, `gl_TessLevelOuter[2] = 10`.&#xD;&#xA;&#xD;&#xA;This algorithm works for all types of triangles tessellation, where innerTessLevel and outerTessLevels are integer values. The enumeration only works for `equal_spacing`. As you can see from the code, the enumerated value is calculated by the following built-in variables of TES:&#xD;&#xA;&#xD;&#xA; - `in vec3 gl_TessCoord`&#xD;&#xA; - `patch in float gl_TessLevelOuter[3]`&#xD;&#xA; - `patch in float gl_TessLevelInner[1]`&#xD;&#xA;&#xD;&#xA;I will try to improve the algorithm from time to time.... at the moment it is very confusing and full of branches... maybe we can avoid branching in the end.&#xD;&#xA;&#xD;&#xA;Please feel free to give me tips on how to improve the algorithm =)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OvC91.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41545" PostHistoryTypeId="2" PostId="13664" RevisionGUID="52ee31a3-145e-4805-b9b8-598368ab6744" CreationDate="2023-08-25T13:05:26.447" UserId="13273" Text="I was very surprised when I ran my tessellation evaluation shader, which only counts the number of vertices through an atomicAdd command.&#xD;&#xA;&#xD;&#xA;for the following tessellation levels:&#xD;&#xA;&#xD;&#xA;    gl_TessLevelOuter[0] = 10;&#xD;&#xA;    gl_TessLevelOuter[1] = 10;&#xD;&#xA;    gl_TessLevelOuter[2] = 10;&#xD;&#xA;    gl_TessLevelInner[0] = 10;&#xD;&#xA;&#xD;&#xA;As we can see (Figure 1), there are only 91 vertices.... but the atomic counter tells me that there are 141 vertices.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 1:** generated vertices in the TES stage. &#xD;&#xA;all inner and outer TessLevels were set to value `10`.&#xD;&#xA;&#xD;&#xA;So I used my [TES vertex enumeration algorithm][1] to store the variable `gl_TessCoord` in SSBO along with a uint incremented by the function `atomicAdd`. I saved the result in an obj file and added a comment telling us how often this vertex is generated.&#xD;&#xA;&#xD;&#xA;	v 0.0666656 0.866653 0.0666809 #2&#xD;&#xA;	v 0.0666656 0.766647 0.166687 #3&#xD;&#xA;	v 0.0666656 0.666641 0.266693 #2&#xD;&#xA;	v 0.0666656 0.566635 0.366699 #2&#xD;&#xA;	v 0.0666656 0.46666 0.466675 #2&#xD;&#xA;	v 0.0666656 0.366684 0.56665 #2&#xD;&#xA;	v 0.0666656 0.266678 0.666656 #2&#xD;&#xA;	v 0.0666656 0.166672 0.766663 #2&#xD;&#xA;	v 0.133347 0.733307 0.133347 #2&#xD;&#xA;	v 0.133347 0.633301 0.233353 #1&#xD;&#xA;	v 0.133347 0.533295 0.333359 #1&#xD;&#xA;	v 0.133347 0.433319 0.433334 #1&#xD;&#xA;	v 0.133347 0.333344 0.53331 #1&#xD;&#xA;	v 0.133347 0.233337 0.633316 #1&#xD;&#xA;	v 0.200012 0.599976 0.200012 #1&#xD;&#xA;	v 0.200012 0.499969 0.300018 #1&#xD;&#xA;	v 0.200012 0.399994 0.399994 #1&#xD;&#xA;	v 0.200012 0.300018 0.499969 #1&#xD;&#xA;	v 0.266678 0.466629 0.266693 #2&#xD;&#xA;	v 0.266678 0.366653 0.366669 #2&#xD;&#xA;	v 0.0666656 0.0666656 0.866669 #3&#xD;&#xA;	v 0.166672 0.0666656 0.766663 #2&#xD;&#xA;	v 0.266678 0.0666656 0.666656 #2&#xD;&#xA;	v 0.366684 0.0666656 0.56665 #3&#xD;&#xA;	v 0.46666 0.0666656 0.466675 #3&#xD;&#xA;	v 0.566635 0.0666656 0.366699 #2&#xD;&#xA;	v 0.666641 0.0666656 0.266693 #2&#xD;&#xA;	v 0.766647 0.0666656 0.166687 #2&#xD;&#xA;	v 0.133331 0.133347 0.733322 #1&#xD;&#xA;	v 0.233337 0.133347 0.633316 #1&#xD;&#xA;	v 0.333344 0.133347 0.53331 #2&#xD;&#xA;	v 0.433319 0.133347 0.433334 #2&#xD;&#xA;	v 0.533295 0.133347 0.333359 #1&#xD;&#xA;	v 0.633301 0.133347 0.233353 #1&#xD;&#xA;	v 0.200012 0.200012 0.599976 #1&#xD;&#xA;	v 0.300018 0.200012 0.499969 #2&#xD;&#xA;	v 0.399994 0.200012 0.399994 #2&#xD;&#xA;	v 0.499969 0.200012 0.300018 #1&#xD;&#xA;	v 0.266678 0.266678 0.466644 #2&#xD;&#xA;	v 0.366653 0.266678 0.366669 #2&#xD;&#xA;	v 0.866653 0.0666809 0.0666656 #2&#xD;&#xA;	v 0.766647 0.166687 0.0666656 #2&#xD;&#xA;	v 0.666641 0.266693 0.0666656 #2&#xD;&#xA;	v 0.566635 0.366699 0.0666656 #3&#xD;&#xA;	v 0.46666 0.466675 0.0666656 #3&#xD;&#xA;	v 0.366684 0.56665 0.0666656 #2&#xD;&#xA;	v 0.266678 0.666656 0.0666656 #2&#xD;&#xA;	v 0.166672 0.766663 0.0666656 #2&#xD;&#xA;	v 0.733307 0.133347 0.133347 #1&#xD;&#xA;	v 0.633301 0.233353 0.133347 #1&#xD;&#xA;	v 0.533295 0.333359 0.133347 #1&#xD;&#xA;	v 0.433319 0.433334 0.133347 #3&#xD;&#xA;	v 0.333344 0.53331 0.133347 #3&#xD;&#xA;	v 0.233337 0.633316 0.133347 #2&#xD;&#xA;	v 0.599976 0.200012 0.200012 #1&#xD;&#xA;	v 0.499969 0.300018 0.200012 #1&#xD;&#xA;	v 0.399994 0.399994 0.200012 #2&#xD;&#xA;	v 0.300018 0.499969 0.200012 #2&#xD;&#xA;	v 0.466629 0.266693 0.266678 #1&#xD;&#xA;	v 0.366653 0.366669 0.266678 #2&#xD;&#xA;	v 0.333328 0.333328 0.333344 #2&#xD;&#xA;	v 0 1 0 #1&#xD;&#xA;	v 0 0.899994 0.100006 #1&#xD;&#xA;	v 0 0.799988 0.200012 #1&#xD;&#xA;	v 0 0.699982 0.300018 #1&#xD;&#xA;	v 0 0.599976 0.400024 #1&#xD;&#xA;	v 0 0.5 0.5 #1&#xD;&#xA;	v 0 0.400024 0.599976 #1&#xD;&#xA;	v 0 0.300018 0.699982 #1&#xD;&#xA;	v 0 0.200012 0.799988 #1&#xD;&#xA;	v 0 0.100006 0.899994 #1&#xD;&#xA;	v 0 0 1 #2&#xD;&#xA;	v 0.100006 0 0.899994 #1&#xD;&#xA;	v 0.200012 0 0.799988 #1&#xD;&#xA;	v 0.300018 0 0.699982 #1&#xD;&#xA;	v 0.400024 0 0.599976 #1&#xD;&#xA;	v 0.5 0 0.5 #1&#xD;&#xA;	v 0.599976 0 0.400024 #1&#xD;&#xA;	v 0.699982 0 0.300018 #1&#xD;&#xA;	v 0.799988 0 0.200012 #1&#xD;&#xA;	v 0.899994 0 0.100006 #1&#xD;&#xA;	v 1 0 0 #1&#xD;&#xA;	v 0.899994 0.100006 0 #1&#xD;&#xA;	v 0.799988 0.200012 0 #1&#xD;&#xA;	v 0.699982 0.300018 0 #2&#xD;&#xA;	v 0.599976 0.400024 0 #1&#xD;&#xA;	v 0.5 0.5 0 #1&#xD;&#xA;	v 0.400024 0.599976 0 #1&#xD;&#xA;	v 0.300018 0.699982 0 #1&#xD;&#xA;	v 0.200012 0.799988 0 #1&#xD;&#xA;	v 0.100006 0.899994 0 #1&#xD;&#xA;&#xD;&#xA;As you can see, some vertices are created up to three times.&#xD;&#xA;Is there an option in OpenGL or GLSL to disable the creation of these duplicates?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/13655/enumerate-vertices-from-tessellation-evaluation-stage-triangle-patch/13663#13663&#xD;&#xA;  [2]: https://i.stack.imgur.com/KDRo2.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41547" PostHistoryTypeId="1" PostId="13664" RevisionGUID="52ee31a3-145e-4805-b9b8-598368ab6744" CreationDate="2023-08-25T13:05:26.447" UserId="13273" Text="Tessellation evaluation shader: vertex duplicates on triangle tessellation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41548" PostHistoryTypeId="3" PostId="13664" RevisionGUID="52ee31a3-145e-4805-b9b8-598368ab6744" CreationDate="2023-08-25T13:05:26.447" UserId="13273" Text="|opengl|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41550" PostHistoryTypeId="2" PostId="13665" RevisionGUID="1c107c24-8581-4995-acc4-c72403d673db" CreationDate="2023-08-26T11:31:47.290" UserId="7952" Text="No, but the way this is written has a min of 3 branch's and max of 4. It would be better off with the plain old (x&lt;y)&amp;&amp;(x&lt;z) return 0, y&lt;z return 1, return 2.&#xD;&#xA;&#xD;&#xA;You could also do a pure logic op approach:&#xD;&#xA;&#xD;&#xA;    int mx = (y&lt;z)&amp;&amp;(y&lt;x);&#xD;&#xA;    int mz = (((z&lt;y) &amp;&amp; (z&lt;x))*2;&#xD;&#xA;    return mx + mz; // both are false if x is min value and sum is zero&#xD;&#xA;&#xD;&#xA;which would turn into this:&#xD;&#xA;&#xD;&#xA;    uint MinIndex( float x, float y, float z )&#xD;&#xA;    {&#xD;&#xA;       return ((y&lt;z)&amp;&amp;(y&lt;x)) + ((((z&lt;y)&amp;&amp;(z&lt;x))*2);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;If y,z could be equal and less then x then an extra  `+ ((y==z)&amp;&amp;(x&lt;y))` would be needed which would return 1. &#xD;&#xA;&#xD;&#xA;There may be some clever way to reduce this down to less operations but it's not popping into my head... at any rate logic operations are often fast but ugly to look at.&#xD;&#xA;&#xD;&#xA;You might also try the mix function, something along the lines of...&#xD;&#xA;&#xD;&#xA;    uint MinIndex(float x, float y, float z)&#xD;&#xA;    {&#xD;&#xA;       float YltX = float(y &lt; x);&#xD;&#xA;       float ZltX = float(z &lt; x);&#xD;&#xA;    &#xD;&#xA;       return uint(mix(YltX, 2.0 * ZltX, ZltX+float(y==z)));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I haven't checked this one for accuracy but using mix also tends to be rather speedy.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41552" PostHistoryTypeId="2" PostId="13666" RevisionGUID="b0797844-711e-4682-9ec3-f387a006cc73" CreationDate="2023-08-27T09:42:41.803" UserId="17924" Text="I have been reading and watching many raymarching tutorials, but almost all of them are only working in the perspective projection. Almost all assume, that to calculate the ray direction, you just have to calculate the `rd = hitpos - cameraPos`, where hitpos is vertex position. This approach doesn't work when we change the projection to orthographic though.&#xD;&#xA;&#xD;&#xA;Because there are a lot of hidden details in calculating and correctly interpolating the rays and positions, how to correctly calculate camera ray direction and ray origin like on the picture below (without any external scripts)? `Rd` is ray direction, `Ro` is ray origin, `near` and `far` are camera clip planes and `Hit` will be fragment's position.&#xD;&#xA;&#xD;&#xA;I am mainly interested in HLSL implementation, specifically in Unity, but the general approach would be welcome as well.&#xD;&#xA;&#xD;&#xA;[![raymarching][1]][1]&#xD;&#xA;&#xD;&#xA;The technique isn't trivial, I had to already deal with: &#xD;&#xA; - it has to account for both orthographic and perspective projection at the same time&#xD;&#xA; - interpolating directions in vertex shader can lead to weird interpolation issues later in fragment (looking similarly to issues with perspective-correct texture mapping)&#xD;&#xA; - the non-trivial thing about how interpolators work for data passed from vertex to fragment&#xD;&#xA; - accounting for depth buffer (and how it's not linear)&#xD;&#xA; - using only data already available in the shader routines without passing things like FOV, camera position and similar to shader explicitly&#xD;&#xA; - working in many different coordinate systems (local, world, view, clip)&#xD;&#xA; - if a depth buffer is reversed or not&#xD;&#xA;&#xD;&#xA;And I still don't quite understand the correct way of accounting all of those things and calculating things like worldspace pos from depth.&#xD;&#xA;&#xD;&#xA;I'm gonna mention, that I have already achieved desired effect, but in the fragment shader (origin on near plane or hit position, depending on control, direction universally calculated for perspective and ortho). It is overcomplicated and most probably very inefficient. It uses clip-space to generate a ray: it takes the fragment coordinates in clip-space, calculates direction vector from projecting this fragment to z=0 and z=1, then calculates an inverse projection matrix to bring this vector back to camera space.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FfSIH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41554" PostHistoryTypeId="1" PostId="13666" RevisionGUID="b0797844-711e-4682-9ec3-f387a006cc73" CreationDate="2023-08-27T09:42:41.803" UserId="17924" Text="How to calculate ray-origin and ray-direction in vertex shader working universally for any projection and using interpolators for performance" ContentLicense="CC BY-SA 4.0" />
  <row Id="41555" PostHistoryTypeId="3" PostId="13666" RevisionGUID="b0797844-711e-4682-9ec3-f387a006cc73" CreationDate="2023-08-27T09:42:41.803" UserId="17924" Text="|shader|hlsl|raymarching|unity|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41556" PostHistoryTypeId="2" PostId="13667" RevisionGUID="29f057ea-858d-48ac-bf5f-c0cc6a5a6329" CreationDate="2023-08-27T15:58:36.500" UserId="7952" Text="There is no universal solution here since there are many different small variations that can be applied to get a specific result.&#xD;&#xA;&#xD;&#xA;One of the things that trips people up when computing ray's in the vertex shader is how a vector's length changes when it is interpolated. This results in vectors that have slightly different lengths arriving in the fragment shader. This is the same problem that happens with lighting vectors. With lighting the solution is to re-normalize the vector in the fragment shader. With ray casting the vector length needs to be recomputed to match the needs of the technique. This means we can effectively ignore ray length in the vertex shader. But the code must be careful to compute the proper length in the fragment shader.&#xD;&#xA;&#xD;&#xA;One good technique is to compute the ray direction in the vertex shader and pass it to the fragment shader. The ray origin can then be computed in the fragment shader in a straight forward manner. Where ray direction is computed by finding the point of intersection with the camera space starting plane in 2D (not necessarily the projection near plane) and just plugging the distance from the camera to the plane in as the 'z' value. The vector length will be odd but its going to be changed with interpolation anyway, then transform it into the appropriate space for interpolation.&#xD;&#xA;&#xD;&#xA;Ray origin can be computed in the fragment shader after rescaling (or computing a scaling factor) for the interpolated ray. A scaling factor can be computed with something along the lines of &#xD;&#xA;&#xD;&#xA;`scale = plane_distance * (1/camera_vector_length)` &#xD;&#xA;&#xD;&#xA;And then the Ray origin computed with:&#xD;&#xA;&#xD;&#xA;`ray_origin = interpolated_ray_direction * scale + transformed_camera_postion`&#xD;&#xA;&#xD;&#xA;It can be better to just pass a camera space 2D &quot;ray&quot; and another ray transformed into the same space that the ray will be marched/cast in so that there is no need to do any transformations of the ray in the fragment shader and is the reason I wrote &quot;camera_vector_length&quot; above. The 2D ray is really just interpolating a point across the start plane then the plane distance is plugged in as the 'z' value in the fragment shader. (saving some interpolation hardware) Also, the `transformed_camera_position` above, is the camera position transformed into whatever space the ray marching will be done in.&#xD;&#xA;&#xD;&#xA;Another nice technique is to compute the ray end point, then compute a time `t` that is used to interpolate between the start and end points. Where `t` is a step size that can be set in the shader, or passed in as a parameter, computed on the fly, etc. The interpolated point is then used to sample the data. This drops ray direction out of the marching loops altogether.&#xD;&#xA;&#xD;&#xA;Yet another reason to use `t` is that a random offset can be *easily* added to it which helps &quot;jitter&quot; the sampling points breaking up regular artifacts that crop up often with ray casting. The goal hear is to move the rays slightly from frame to frame rather then within a single frame. &#xD;&#xA;&#xD;&#xA;Using these approach's results in shaders that look considerably different from the standard &quot;Rd = hitpos - camerapos&quot; but are more efficient and produce better results.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41558" PostHistoryTypeId="2" PostId="13668" RevisionGUID="938cee4f-e36a-4903-9d1f-eb42675883ac" CreationDate="2023-08-28T00:45:28.287" UserId="2654" Text="&gt; Is there an option in OpenGL or GLSL to disable the creation of these duplicates?&#xD;&#xA;&#xD;&#xA;No.&#xD;&#xA;&#xD;&#xA;The tessellation system generates primitives. That means that, at the point the primitive is generated, all of its vertices must be available to the next parts of the pipeline. However, that means having storage for all of that vertex data.&#xD;&#xA;&#xD;&#xA;Because you can tessellate one primitive into a *lot* of primitives, OpenGL gives implementations wide latitude over how many TES invocations are used. The TES can be invoked over the same coordinates multiple times. This usually represents contention for the cache memory used to store post-TES vertex data. That is, the system forced a vertex out of the cache, then needed it for a later primitive.&#xD;&#xA;&#xD;&#xA;There's no way to guarantee that this never happens.&#xD;&#xA;&#xD;&#xA;&gt; But I would like to use transform feedback buffer and after TES stage no other stages are used.&#xD;&#xA;&#xD;&#xA;The output of transform feedback is *always* a triangle list (or line list, or point list)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41560" PostHistoryTypeId="5" PostId="13663" RevisionGUID="27bfaaf6-5565-469b-a98c-2f5a36d305fd" CreationDate="2023-08-28T10:09:14.300" UserId="13273" Comment="added 332 characters in body" Text="After a whole day of brain stress, I found a method to enumerate them:&#xD;&#xA;&#xD;&#xA;    //floats equal? with respect of epsilon&#xD;&#xA;    bool isNearlyTheSame(float value0, float value1) &#xD;&#xA;    {&#xD;&#xA;        return abs(value0 - value1) &lt; 0.001;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //result: x: 1 =&gt; inner triangles, 0 =&gt; inner most vertex, 2 =&gt; outer vertices&#xD;&#xA;    //result: y: lowest barycentric value is: 1 =&gt; x, 2 =&gt; y, 3 =&gt; z  &#xD;&#xA;    uvec2 getBarycentricCase() &#xD;&#xA;    {&#xD;&#xA;        uvec2 baryCase = uvec2(1,0);&#xD;&#xA;        if(gl_TessCoord.x &lt; gl_TessCoord.y &amp;&amp; gl_TessCoord.x &lt;= gl_TessCoord.z + 0.001)&#xD;&#xA;        {&#xD;&#xA;            baryCase.y = 1;&#xD;&#xA;        }&#xD;&#xA;        if(gl_TessCoord.y &lt;= gl_TessCoord.x + 0.001 &amp;&amp; gl_TessCoord.y &lt; gl_TessCoord.z)&#xD;&#xA;        {&#xD;&#xA;            baryCase.y = 2;&#xD;&#xA;        }&#xD;&#xA;        if(gl_TessCoord.z &lt; gl_TessCoord.x &amp;&amp; gl_TessCoord.z &lt;= gl_TessCoord.y + 0.001)&#xD;&#xA;        {&#xD;&#xA;            baryCase.y = 3;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        if(gl_TessCoord.x == 0 || gl_TessCoord.y == 0 || gl_TessCoord.z == 0)&#xD;&#xA;            baryCase.x = 2;&#xD;&#xA;&#xD;&#xA;        if(isNearlyTheSame(gl_TessCoord.x, gl_TessCoord.y) &amp;&amp; isNearlyTheSame(gl_TessCoord.y, gl_TessCoord.z))&#xD;&#xA;            baryCase.x = 0;&#xD;&#xA;        return baryCase;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //returns a third of the count of the inner vertices with respect to the tessLevel&#xD;&#xA;    uint getNummTessPart(uint tessLevel)&#xD;&#xA;    {&#xD;&#xA;        float tesslvl = float(tessLevel);&#xD;&#xA;        return uint(tesslvl / 2.0 * (tesslvl / 2.0 - 1));&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //returns the current patch vertex id with respect to this algorithm&#xD;&#xA;    uint getPatchVertexID()&#xD;&#xA;    {&#xD;&#xA;        uint result = 0;&#xD;&#xA;        uvec2 baryCase = getBarycentricCase();&#xD;&#xA;        float baseValue = min(min(gl_TessCoord.x,gl_TessCoord.y), gl_TessCoord.z);&#xD;&#xA;        float leftValue = baryCase.y == 1 ? gl_TessCoord.z : baryCase.y == 2 ? gl_TessCoord.x : baryCase.y == 3 ? gl_TessCoord.y : 0;&#xD;&#xA;        uint positionUp = 0;&#xD;&#xA;        uint positionLeft = 0;&#xD;&#xA;&#xD;&#xA;        float stepUp = 2.0 / 3.0 / float(gl_TessLevelInner[0]);&#xD;&#xA;        float stepLeft = 1.0 / gl_TessLevelInner[0];&#xD;&#xA;&#xD;&#xA;        if(baryCase.x == 1) //inner vertex&#xD;&#xA;        {&#xD;&#xA;            positionUp = uint(round(baseValue / stepUp));&#xD;&#xA;            positionLeft = uint(round(leftValue / stepLeft + (positionUp) * stepUp * gl_TessLevelInner[0] / 2 - positionUp));&#xD;&#xA;            result = getNummTessPart(uint(gl_TessLevelInner[0])) - getNummTessPart(uint(gl_TessLevelInner[0] - ((positionUp-1) * 2)));&#xD;&#xA;            result += positionLeft;&#xD;&#xA;            result += (baryCase.y - 1) * getNummTessPart(uint(gl_TessLevelInner[0]));&#xD;&#xA;        }&#xD;&#xA;        else if(baryCase.x == 0) // most inner vertex (only even tessellation)&#xD;&#xA;        {&#xD;&#xA;            result = getNummTessPart(uint(gl_TessLevelInner[0])) * 3;&#xD;&#xA;        }&#xD;&#xA;        else if(baryCase.x == 2) // outer vertex&#xD;&#xA;        {&#xD;&#xA;            result = getNummTessPart(uint(gl_TessLevelInner[0])) * 3;&#xD;&#xA;            float stepX = 1.0 / gl_TessLevelOuter[0];&#xD;&#xA;            float stepY = 1.0 / gl_TessLevelOuter[1];&#xD;&#xA;            float stepZ = 1.0 / gl_TessLevelOuter[2];&#xD;&#xA;&#xD;&#xA;            if(baryCase.y == 1) //on the x side&#xD;&#xA;            {&#xD;&#xA;                result += uint(round(leftValue / stepX));&#xD;&#xA;            }&#xD;&#xA;            if(baryCase.y == 2) //on the y side&#xD;&#xA;            {&#xD;&#xA;                result += uint(round(leftValue / stepY));&#xD;&#xA;                result += uint(gl_TessLevelOuter[0]);&#xD;&#xA;            }&#xD;&#xA;            if(baryCase.y == 3) //on the z side&#xD;&#xA;            {&#xD;&#xA;                result += uint(round(leftValue / stepZ));&#xD;&#xA;                result += uint(gl_TessLevelOuter[0] + gl_TessLevelOuter[1]);&#xD;&#xA;            }&#xD;&#xA;            if(mod(gl_TessLevelInner[0],2) == 0) //in case of even tessellation level there is an additional most inner vertex&#xD;&#xA;                result++;&#xD;&#xA;        }&#xD;&#xA;        return result;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;As can be seen in Figure 1, the algorithm first enumerates the inner vertices, dividing them into 3 parts. After the inner vertices, the innermost vertex (in case of an even innerTessLevel) is enumerated. At the end, the outer vertices are enumerated.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Enumeration sceme for: `gl_TessLevelInner[0] = 10`, `gl_TessLevelOuter[0] = 10`, `gl_TessLevelOuter[1] = 10`, `gl_TessLevelOuter[2] = 10`.&#xD;&#xA;&#xD;&#xA;This algorithm works for all types of triangles tessellation, where innerTessLevel and outerTessLevels are integer values. The enumeration only works for `equal_spacing`. As you can see from the code, the enumerated value is calculated by the following built-in variables of TES:&#xD;&#xA;&#xD;&#xA; - `in vec3 gl_TessCoord`&#xD;&#xA; - `patch in float gl_TessLevelOuter[3]`&#xD;&#xA; - `patch in float gl_TessLevelInner[1]`&#xD;&#xA;&#xD;&#xA;I will try to improve the algorithm from time to time.... at the moment it is very confusing and full of branches... maybe we can avoid branching in the end. &#xD;&#xA;&#xD;&#xA;**Also important, when using this algorithm:**&#xD;&#xA;Multiple generated vertices within TES stage are on the same position. So the output of this algorithm gives you an enumeration with respect to the position. But not with respect to the vertex id. So multiple generated vertices will receive the same enumarated number at the end.&#xD;&#xA;&#xD;&#xA;Please feel free to give me tips on how to improve the algorithm =)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OvC91.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41561" PostHistoryTypeId="5" PostId="13667" RevisionGUID="832f38de-f9e6-4b89-9486-aef5b6f8dfec" CreationDate="2023-08-28T12:48:37.243" UserId="7952" Comment="Add some code and description" Text="There is no universal solution here since there are many different small variations that can be applied to get a specific result.&#xD;&#xA;&#xD;&#xA;One of the things that trips people up when computing ray's in the vertex shader is how a vector's length changes when it is interpolated. This results in vectors that have slightly different lengths arriving in the fragment shader. This is the same problem that happens with lighting vectors. With lighting the solution is to re-normalize the vector in the fragment shader. With ray casting the vector length needs to be recomputed to match the needs of the technique. This means we can effectively ignore ray length in the vertex shader. But the code must be careful to compute the proper length in the fragment shader.&#xD;&#xA;&#xD;&#xA;One good technique is to compute the ray direction in the vertex shader and pass it to the fragment shader. The ray origin can then be computed in the fragment shader in a straight forward manner. Where ray direction is computed by finding the point of intersection with the camera space starting plane in 2D (not necessarily the projection near plane) and just plugging the distance from the camera to the plane in as the 'z' value. The vector length will be odd but its going to be changed with interpolation anyway, then transform it into the appropriate space for interpolation.&#xD;&#xA;&#xD;&#xA;Ray origin can be computed in the fragment shader after rescaling (or computing a scaling factor) for the interpolated ray. A scaling factor can be computed with something along the lines of &#xD;&#xA;&#xD;&#xA;`scale = plane_distance * (1/camera_vector_length)` &#xD;&#xA;&#xD;&#xA;And then the Ray origin computed with:&#xD;&#xA;&#xD;&#xA;`ray_origin = interpolated_ray_direction * scale + transformed_camera_postion`&#xD;&#xA;&#xD;&#xA;It can be better to just pass a camera space 2D &quot;ray&quot; and another ray transformed into the same space that the ray will be marched/cast in so that there is no need to do any transformations of the ray in the fragment shader and is the reason I wrote &quot;camera_vector_length&quot; above. The 2D ray is really just interpolating a point across the start plane then the plane distance is plugged in as the 'z' value in the fragment shader. (saving some interpolation hardware) Also, the `transformed_camera_position` above, is the camera position transformed into whatever space the ray marching will be done in.&#xD;&#xA;&#xD;&#xA;Another nice technique is to compute the ray end point, then compute a time `t` that is used to interpolate between the start and end points. Where `t` is a step size that can be set in the shader, or passed in as a parameter, computed on the fly, etc. The interpolated point is then used to sample the data. This drops ray direction out of the marching loops altogether.&#xD;&#xA;&#xD;&#xA;Yet another reason to use `t` is that a random offset can be *easily* added to it which helps &quot;jitter&quot; the sampling points breaking up regular artifacts that crop up often with ray casting. The goal hear is to move the rays slightly from frame to frame rather then within a single frame. &#xD;&#xA;&#xD;&#xA;Using these approach's results in shaders that look considerably different from the standard &quot;Rd = hitpos - camerapos&quot; but are more efficient and produce better results.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    // out cs_ray == camera space ray&#xD;&#xA;    // out t_ray == transformed ray created using transform matrix&#xD;&#xA;    //    such as the camera to world matrix, or camera to shadow space matrix&#xD;&#xA;    void ComputeRayFromClipSpace( in float2 vp, out float2 cs_ray, out float3 t_ray ) &#xD;&#xA;    { &#xD;&#xA;      // Inputs to shader&#xD;&#xA;      float pd; // distance to camera space plane, ie Ray Origin plane&#xD;&#xA;      float s;  // aspect ratio&#xD;&#xA;      float g;  // focal distance&#xD;&#xA;&#xD;&#xA;      // Compute point on camera space plane&#xD;&#xA;      float3 hitpoint = float3( vp*pd*s/g, vp*pd*1.0/g, pd);&#xD;&#xA;&#xD;&#xA;      cs_ray = hitpoint.xy;&#xD;&#xA;      t_ray  = hitpoint * transform_matrix;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;This is setup for a &quot;full screen&quot; effect.  The inputs would usually be generated from a single clip space triangle that covers the entire vieport. [More info here][1]. It is also using info from a perspective frustum but similar info could be generated for a orthographic frustum. The main point here is to compute the points on the plane that intersect with the frustum using whatever method that is appropriate.&#xD;&#xA;&#xD;&#xA;This function is leaving some performance on the table for clarity, the constants and transform computations.&#xD;&#xA;&#xD;&#xA;Then in the fragment shader:&#xD;&#xA;&#xD;&#xA;    float3 camera_ray = float3( cameraRayIn, pd ); // pd == plane distance&#xD;&#xA;    float length = sqrt( dot( camera_ray, camera_ray));&#xD;&#xA;    float scale = pd * (1.0/length);&#xD;&#xA;    float3 scaled_ray = t_ray_in * scale;&#xD;&#xA;&#xD;&#xA;The scaled_ray can be used to compute the start point `scaled_ray+camera_pos` where camera_pos is the position of the camera in whatever space we are working in. The ray can then be rescaled (such as normalized or scaled to the required step distance) or used to compute a ray end point.&#xD;&#xA;&#xD;&#xA;The best sources I know of for this technique are talks and books describing ray casting effects used in games like fged2.&#xD;&#xA;&#xD;&#xA;  [1]: https://wallisc.github.io/rendering/2021/04/18/Fullscreen-Pass.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="41562" PostHistoryTypeId="2" PostId="13669" RevisionGUID="a674b3b0-377d-43e5-ae21-7aee5725df75" CreationDate="2023-08-28T15:41:35.187" UserId="20454" Text="I'm working on a 3D Renderer with the canvas element and JS but currently the cube I made is not rendering. I currently have it set to just render a wireframe of the cube and am hoping to render the full thing eventually, but when I try to draw the cube it's not showing up. My current rendering function is as follows:&#xD;&#xA;&#xD;&#xA;    render(){&#xD;&#xA;    for (var i=0;i&lt;this.faces.length;i++){&#xD;&#xA;      ctx.beginPath()&#xD;&#xA;      &#xD;&#xA;      for (var j=0;j&lt;this.faces[i].points.length;j++) {&#xD;&#xA;        ctx.lineTo(this.faces[i].points[j].x,this.faces[i].points[j].y)&#xD;&#xA;      }&#xD;&#xA;      ctx.lineTo(this.faces[i].points[this.faces[i].length-1].x,this.faces[i].points[this.faces[i].length-1].y)&#xD;&#xA;      &#xD;&#xA;      ctx.closePath()&#xD;&#xA;      if (faces[i].color!=null) {&#xD;&#xA;        ctx.fillstyle = faces[i].color&#xD;&#xA;      }&#xD;&#xA;      ctx.stroke()&#xD;&#xA;    }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Does anyone know why it's not drawing?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41564" PostHistoryTypeId="1" PostId="13669" RevisionGUID="a674b3b0-377d-43e5-ae21-7aee5725df75" CreationDate="2023-08-28T15:41:35.187" UserId="20454" Text="HTML Canvas not drawing" ContentLicense="CC BY-SA 4.0" />
  <row Id="41565" PostHistoryTypeId="3" PostId="13669" RevisionGUID="a674b3b0-377d-43e5-ae21-7aee5725df75" CreationDate="2023-08-28T15:41:35.187" UserId="20454" Text="|rendering|3d|javascript|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41566" PostHistoryTypeId="2" PostId="13670" RevisionGUID="a362a92a-45df-4992-a4e4-1cdc2950094b" CreationDate="2023-08-28T22:14:22.317" UserId="2654" Text="&gt; When using for instance `GL_UNSIGNED_SHORT` as the type of the indices is there still a restriction that only `MAX_UNSIGNED_SHORT` vertices can be rendered at a time&#xD;&#xA;&#xD;&#xA;No such restriction has ever existed (and I checked old versions of the specification). The limitations on `count` have never been related to the size of the index type. The type of the indices only describes the type of the *indices*; how many indices are being used is specified by `count` and is unrelated to the type." ContentLicense="CC BY-SA 4.0" />
  <row Id="41568" PostHistoryTypeId="2" PostId="13671" RevisionGUID="cfefe8c0-5886-4272-b9b5-9a190f92268f" CreationDate="2023-08-29T05:17:17.933" UserId="20456" Text="Hy guys I'm new to 3d graphics and i lack some Linear algebra knowledge. I tried to recreate Unity's worldToScreenPoint method with kotlin on android. I copied some code from their forum and wrote missing math with snippets that I found on the internet. I expected to see target put in the middle of the screen, but it appears in different places depending on pitch and yaw of camera.&#xD;&#xA;&#xD;&#xA;So here's my code. Could someone please verify validity of my code and math. Here's code to calculate worldToScreenPoint&#xD;&#xA;```&#xD;&#xA;class TrackingCalc {&#xD;&#xA;    companion object {&#xD;&#xA;        fun worldToLocal(aCamPos: Vector3, aCamRot: Quaternion, aPos: Vector3): Vector3 {&#xD;&#xA;//            Log.i(&quot;OnScreen2&quot;, (aCamRot.inverse() * (aPos - aCamPos)).toString())&#xD;&#xA;            val result = (aPos - aCamPos)&#xD;&#xA;            val length = result.getMagnitude()&#xD;&#xA;//            val result2 = rotate(aCamRot.inverse(), Quaternion(0.0, result.x, result.y, result.z))&#xD;&#xA;//            Log.i(&quot;WorldToLocal&quot;, result.toString())&#xD;&#xA;            aCamRot.invTransformPoint(result)&#xD;&#xA;            Log.i(&quot;WorldToLocal&quot;, result.toString())&#xD;&#xA;            return result&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        fun project(aPos: Vector3, aFov: Float, aAspect: Float): Vector3 {&#xD;&#xA;            var f = 1f / tan(Math.toRadians(aFov.toDouble()) / 2)&#xD;&#xA;            f /= aPos.z&#xD;&#xA;            aPos.x *= f / aAspect&#xD;&#xA;            aPos.y *= f&#xD;&#xA;            return aPos&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        fun clipSpaceToViewport(aPos: Vector3): Vector3 {&#xD;&#xA;            aPos.x = aPos.x * 0.5f + 0.5f&#xD;&#xA;            aPos.y = aPos.y * 0.5f + 0.5f&#xD;&#xA;            return aPos&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        fun worldToViewport(aCamPos: Vector3, aCamRot: Quaternion, aFov: Float, aAspect: Float, aPos: Vector3): Vector3 {&#xD;&#xA;            var p = worldToLocal(aCamPos, aCamRot, aPos)&#xD;&#xA;            p = project(p, aFov, aAspect)&#xD;&#xA;            return clipSpaceToViewport(p)&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        fun worldToScreenPos(aCamPos: Vector3, aCamRot: Quaternion, aFov: Float, aScrWidth: Float, aScrHeight: Float, aPos: Vector3): Vector3 {&#xD;&#xA;            var p = worldToViewport(aCamPos, aCamRot, aFov, aScrWidth / aScrHeight, aPos)&#xD;&#xA;            p.x *= aScrWidth&#xD;&#xA;            p.y *= aScrHeight&#xD;&#xA;            return p&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        fun worldToGUIPos(aCamPos: Vector3, aCamRot: Quaternion, aFov: Float, aScrWidth: Float, aScrHeight: Float, aPos: Vector3): Vector3 {&#xD;&#xA;            var p = worldToScreenPos(aCamPos, aCamRot, aFov, aScrWidth, aScrHeight, aPos)&#xD;&#xA;            p.y = aScrHeight - p.y&#xD;&#xA;            return p&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;data class Quaternion(var w: Double, var x: Double, var y: Double, var z: Double)&#xD;&#xA;&#xD;&#xA;fun Quaternion.inverse(): Quaternion {&#xD;&#xA;    val norm = x*x + y*y + z*z + w*w&#xD;&#xA;    return Quaternion(w / norm, -x / norm, -y / norm, -z / norm)&#xD;&#xA;}&#xD;&#xA;fun Quaternion.rotateYawPitchRoll(rotation: Vector3) {&#xD;&#xA;    rotateYawPitchRoll(rotation.x, rotation.y, rotation.z)&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;fun Quaternion.rotateYawPitchRoll(pitch: Double, yaw: Double, roll: Double) {&#xD;&#xA;    this.rotateY(-yaw)&#xD;&#xA;    this.rotateX(pitch)&#xD;&#xA;    this.rotateZ(roll)&#xD;&#xA;}&#xD;&#xA;fun Quaternion.rotateY(angleDegrees: Double) {&#xD;&#xA;    if (angleDegrees != 0.0) {&#xD;&#xA;        val r = 0.5 * Math.toRadians(angleDegrees)&#xD;&#xA;        rotateY_unsafe(Math.cos(r), Math.sin(r))&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;fun Quaternion.rotateX(angleDegrees: Double) {&#xD;&#xA;    if (angleDegrees != 0.0) {&#xD;&#xA;        val r = 0.5 * Math.toRadians(angleDegrees)&#xD;&#xA;        rotateX_unsafe(Math.cos(r), Math.sin(r))&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;fun Quaternion.rotateZ(angleDegrees: Double) {&#xD;&#xA;    if (angleDegrees != 0.0) {&#xD;&#xA;        val r = 0.5 * Math.toRadians(angleDegrees)&#xD;&#xA;        rotateZ_unsafe(Math.cos(r), Math.sin(r))&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;private fun Quaternion.rotateX_unsafe(fy: Double, fz: Double) {&#xD;&#xA;    val x = x * fy + w * fz&#xD;&#xA;    val y = y * fy + z * fz&#xD;&#xA;    val z = z * fy - this.y * fz&#xD;&#xA;    val w = w * fy - this.x * fz&#xD;&#xA;    this.x = x&#xD;&#xA;    this.y = y&#xD;&#xA;    this.z = z&#xD;&#xA;    this.w = w&#xD;&#xA;    this.normalize()&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;private fun Quaternion.rotateY_unsafe(fx: Double, fz: Double) {&#xD;&#xA;    val x = x * fx - z * fz&#xD;&#xA;    val y = y * fx + w * fz&#xD;&#xA;    val z = z * fx + this.x * fz&#xD;&#xA;    val w = w * fx - this.y * fz&#xD;&#xA;    this.x = x&#xD;&#xA;    this.y = y&#xD;&#xA;    this.z = z&#xD;&#xA;    this.w = w&#xD;&#xA;    this.normalize()&#xD;&#xA;}&#xD;&#xA;private fun Quaternion.rotateZ_unsafe(fx: Double, fy: Double) {&#xD;&#xA;    val x = x * fx + y * fy&#xD;&#xA;    val y = y * fx - this.x * fy&#xD;&#xA;    val z = z * fx + w * fy&#xD;&#xA;    val w = w * fx - this.z * fy&#xD;&#xA;    this.x = x&#xD;&#xA;    this.y = y&#xD;&#xA;    this.z = z&#xD;&#xA;    this.w = w&#xD;&#xA;    this.normalize()&#xD;&#xA;}&#xD;&#xA;private fun Quaternion.normalize() {&#xD;&#xA;    val norm = Math.sqrt((w * w + x * x + y * y + z * z).toDouble()).toFloat()&#xD;&#xA;    this.x /= norm&#xD;&#xA;    this.y /= norm&#xD;&#xA;    this.z /= norm&#xD;&#xA;    this.w /= norm&#xD;&#xA;}&#xD;&#xA;private fun Quaternion.invTransformPoint(point: Vector3) {&#xD;&#xA;&#xD;&#xA;    val px: Double = point.x&#xD;&#xA;    val py: Double = point.y&#xD;&#xA;    val pz: Double = point.z&#xD;&#xA;    point.x = ( px + 2.0 * (px*(-y*y-z*z) + py*(x*y+z*w) + pz*(x*z-y*w)) );&#xD;&#xA;    point.y = ( py + 2.0 * (px*(x*y-z*w) + py*(-x*x-z*z) + pz*(y*z+x*w)) );&#xD;&#xA;    point.z = ( pz + 2.0 * (px*(x*z+y*w) + py*(y*z-x*w) + pz*(-x*x-y*y)) );&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;And here's input:&#xD;&#xA;```&#xD;&#xA;-90 &lt; pitch &lt; 30&#xD;&#xA;0 &lt; heading &lt; 360&#xD;&#xA;fovY = 45f&#xD;&#xA;val quaternion = Quaternion(1.0, 0.0, 0.0, 0.0)&#xD;&#xA;quaternion.rotateYawPitchRoll(-pitch  , -heading, 0.0)&#xD;&#xA;    val onScreen = TrackingCalc.worldToGUIPos(Vector3(camera_x, camera_height, camera_y) , quaternion, 45f, 1920f, 1080f, Vector3(target_x, target_height, target_y) )&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="41570" PostHistoryTypeId="1" PostId="13671" RevisionGUID="cfefe8c0-5886-4272-b9b5-9a190f92268f" CreationDate="2023-08-29T05:17:17.933" UserId="20456" Text="Object appears in unintended parts of the screen when using manual WorldToScreenPoint" ContentLicense="CC BY-SA 4.0" />
  <row Id="41571" PostHistoryTypeId="3" PostId="13671" RevisionGUID="cfefe8c0-5886-4272-b9b5-9a190f92268f" CreationDate="2023-08-29T05:17:17.933" UserId="20456" Text="|3d|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41572" PostHistoryTypeId="50" PostId="9426" RevisionGUID="179e8065-40eb-4d45-beaf-7f846bbf426b" CreationDate="2023-08-29T18:02:10.280" UserId="-1" />
  <row Id="41573" PostHistoryTypeId="2" PostId="13672" RevisionGUID="4d83963b-2ae7-400c-928e-c3160ebb7b11" CreationDate="2023-08-30T06:48:59.127" UserId="20154" Text="we have a Windows/DirectX11 2D Renderer that paints textured triangles to the screen from back to front. There is no face-culling or depth test activated.&#xD;&#xA;&#xD;&#xA;Now on AMD GPUs it happens randomly that an already painted triangle disappears. That means it looks like something cleares the specific triangle out of the backbuffer after it has already been painted resulting in flickering graphics.&#xD;&#xA;&#xD;&#xA;When debugging with RenderDoc we found that it is complete random, which drawcall triggers this clearing. You can jump back and forth between any two drawcalls that come after the triangle has been painted and there is a chance that it will clear the triangle.&#xD;&#xA;&#xD;&#xA;These artefacts do not appear on NVidia or Intel GPUs.&#xD;&#xA;Thanks for any ideas what we could look for to debug and fix this issue further." ContentLicense="CC BY-SA 4.0" />
  <row Id="41575" PostHistoryTypeId="1" PostId="13672" RevisionGUID="4d83963b-2ae7-400c-928e-c3160ebb7b11" CreationDate="2023-08-30T06:48:59.127" UserId="20154" Text="AMD GPU specific triangles disappearing" ContentLicense="CC BY-SA 4.0" />
  <row Id="41576" PostHistoryTypeId="3" PostId="13672" RevisionGUID="4d83963b-2ae7-400c-928e-c3160ebb7b11" CreationDate="2023-08-30T06:48:59.127" UserId="20154" Text="|gpu|polygon|directx11|artifacts|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41577" PostHistoryTypeId="5" PostId="13672" RevisionGUID="b764956f-30cc-4529-bd78-07b5f1018948" CreationDate="2023-08-30T07:01:35.633" UserId="20154" Comment="added 219 characters in body" Text="we have a Windows/DirectX11 2D Renderer that paints textured triangles to the screen from back to front. There is no face-culling or depth test activated.&#xD;&#xA;&#xD;&#xA;Now on AMD GPUs it happens randomly that an already painted triangle disappears. That means it looks like something cleares the specific triangle out of the backbuffer after it has already been painted resulting in flickering graphics. It happens regardless how the triangle is painted (single Triangle, TriangleList, TriangleStrip).&#xD;&#xA;&#xD;&#xA;When debugging with RenderDoc we found that it is complete random, which drawcall triggers this clearing. You can jump back and forth between any two drawcalls that come after the triangle has been painted and there is a chance that it will clear the triangle.&#xD;&#xA;&#xD;&#xA;We have already checked for any `NaN`s or other uninitialized data being sent to the GPU, but couldn't find anything.&#xD;&#xA;&#xD;&#xA;These artefacts do not appear on NVidia or Intel GPUs.&#xD;&#xA;Thanks for any ideas what we could look for to debug and fix this issue further." ContentLicense="CC BY-SA 4.0" />
  <row Id="41578" PostHistoryTypeId="5" PostId="13672" RevisionGUID="c99040a1-3fe7-4601-b6e1-8278b6894f94" CreationDate="2023-08-30T08:55:00.017" UserId="20154" Comment="added 186 characters in body" Text="we have a Windows/DirectX11 2D Renderer that paints textured triangles to the screen from back to front. There is no face-culling or depth test activated.&#xD;&#xA;&#xD;&#xA;Now on AMD GPUs it happens randomly that an already painted triangle disappears. That means it looks like something cleares the specific triangle out of the backbuffer after it has already been painted resulting in flickering graphics. It happens regardless how the triangle is painted (single Triangle, TriangleList, TriangleStrip).&#xD;&#xA;&#xD;&#xA;When debugging with RenderDoc we found that it is complete random, which drawcall triggers this clearing. You can jump back and forth between any two drawcalls that come after the triangle has been painted and there is a chance that it will clear the triangle.&#xD;&#xA;The drawcalls that trigger the discarding are drawing on completely other areas on the screen/backbuffer. So they are not even overlapping the area that the affected triangle occupies.&#xD;&#xA;&#xD;&#xA;We have already checked for any `NaN`s or other uninitialized data being sent to the GPU, but couldn't find anything.&#xD;&#xA;&#xD;&#xA;These artefacts do not appear on NVidia or Intel GPUs.&#xD;&#xA;Thanks for any ideas what we could look for to debug and fix this issue further." ContentLicense="CC BY-SA 4.0" />
  <row Id="41579" PostHistoryTypeId="4" PostId="13672" RevisionGUID="f5e49815-7041-41ae-9e2c-678789a7d597" CreationDate="2023-08-30T08:55:38.003" UserId="20154" Comment="edited title" Text="AMD GPU specific triangles disappearing by subsequent draw calls in same frame" ContentLicense="CC BY-SA 4.0" />
  <row Id="41580" PostHistoryTypeId="2" PostId="13673" RevisionGUID="d4bc92fe-0943-4616-a599-a653dde6802c" CreationDate="2023-08-30T08:58:00.697" UserId="20464" Text="I am programming a camera viewer in Python to move around an object on a sphere given YPR Euler angles (intrinsic) from the user.&#xD;&#xA;&#xD;&#xA;Everything seemed nice until I pitched the camera 90 degrees up/down. The calculations then stopped working and I could not move as expected. I understand this has to do with the gimbal lock as it causes two rotation axes to align. &#xD;&#xA;&#xD;&#xA;So far I have only found solutions such as changing the order of Euler angles or using quaternions, but this is not compatible with the desired solution as:&#xD;&#xA;1. changing the order of Euler angles changes the intuitive behavior of YPR angles for the user&#xD;&#xA;2. using quaternions is far from intuitive in itself&#xD;&#xA;&#xD;&#xA;Is there some other way out of this mess? The key point is to maintain intuitive user control while avoiding gimbal locks.&#xD;&#xA;&#xD;&#xA;Thanks a lot beforehand!" ContentLicense="CC BY-SA 4.0" />
  <row Id="41582" PostHistoryTypeId="1" PostId="13673" RevisionGUID="d4bc92fe-0943-4616-a599-a653dde6802c" CreationDate="2023-08-30T08:58:00.697" UserId="20464" Text="Avoiding gimbal lock in spherical movement around an object - Python" ContentLicense="CC BY-SA 4.0" />
  <row Id="41583" PostHistoryTypeId="3" PostId="13673" RevisionGUID="d4bc92fe-0943-4616-a599-a653dde6802c" CreationDate="2023-08-30T08:58:00.697" UserId="20464" Text="|transformations|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41584" PostHistoryTypeId="2" PostId="13674" RevisionGUID="98a532f2-14c1-48ab-b5c6-a5463d027891" CreationDate="2023-08-30T10:49:14.663" UserId="20466" Text="Other answers already have explained the algorithm and logic behind. I want to add a pure C++ implementation and explain on the code step-by-step.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; 1. As the first step we need to generate a [Gaussian Kernel][1]. I am&#xD;&#xA;    using $$\frac{e^{-(x^2+y^2)/ (2 \sigma ^2) }}{{2\pi \sigma^2}}$$&#xD;&#xA;    &#xD;&#xA;            inline float gaussianKernel(int x, int y, float sigma) {&#xD;&#xA;                float coefficient = 1.0f / (2.0f * M_PI * sigma * sigma);&#xD;&#xA;                float exponent = -(x * x + y * y) / (2.0f * sigma * sigma);&#xD;&#xA;                return coefficient * exp(exponent);&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;    This function will simply give us the value of Gaussian Curve in 2D&#xD;&#xA;    with given x and y coordinates and a sigma.&#xD;&#xA; 2. Now we need to build the kernel that we will apply on points later.&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;        std::vector&lt;std::vector&lt;double&gt;&gt; GaussianFilter::Produce2dGaussianKernel(double sigma) {&#xD;&#xA;            int kernelSize = std::ceil(2 * sigma + 1);&#xD;&#xA;            if (kernelSize % 2 == 0) {&#xD;&#xA;                kernelSize++;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            std::vector&lt;std::vector&lt;double&gt;&gt; kernel2d(kernelSize, std::vector&lt;double&gt;(kernelSize));&#xD;&#xA;            double sum = 0;&#xD;&#xA;    &#xD;&#xA;            for (int row = 0; row &lt; kernel2d.size(); row++) {&#xD;&#xA;                for (int col = 0; col &lt; kernel2d[row].size(); col++) {&#xD;&#xA;                    int x = row - kernelSize / 2;&#xD;&#xA;                    int y = col - kernelSize / 2;&#xD;&#xA;                    double val = gaussianKernel(x, y, sigma);&#xD;&#xA;                    kernel2d[row][col] = val;&#xD;&#xA;                    sum += val;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            // normalization&#xD;&#xA;            for (int row = 0; row &lt; kernel2d.size(); row++) {&#xD;&#xA;                for (int col = 0; col &lt; kernel2d[row].size(); col++) {&#xD;&#xA;                    kernel2d[row][col] /= sum;&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            return kernel2d;&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;    Simply with the given sizes, this function will return a 2D kernel&#xD;&#xA;    whose values are the values of the gaussian curve at that specific&#xD;&#xA;    (x,y).&#xD;&#xA;&#xD;&#xA; 3. As the last step, we iterate through each pixel in the image and replace the original value with the result of the kernel operation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;        cv::Mat CV::Detection::GaussianFilter::ApplyGaussianBlur(cv::Mat input, double sigma)&#xD;&#xA;        {&#xD;&#xA;            cv::Mat blurredImage = input.clone();&#xD;&#xA;            auto kernel = Produce2dGaussianKernel(sigma);&#xD;&#xA;            auto kernelSize = kernel.size();&#xD;&#xA;    &#xD;&#xA;            for (int y = kernelSize / 2; y &lt; input.rows - kernelSize / 2; ++y) {&#xD;&#xA;                for (int x = kernelSize / 2; x &lt; input.cols - kernelSize / 2; ++x) {&#xD;&#xA;                    double newValue = 0.0;&#xD;&#xA;                    for (int i = 0; i &lt; kernelSize; ++i) {&#xD;&#xA;                        for (int j = 0; j &lt; kernelSize; ++j) {&#xD;&#xA;                            newValue += kernel[i][j] * input.at&lt;uchar&gt;(y + i - kernelSize / 2, x + j - kernelSize / 2);&#xD;&#xA;                        }&#xD;&#xA;                    }&#xD;&#xA;                    blurredImage.at&lt;uchar&gt;(y, x) = static_cast&lt;uchar&gt;(newValue);&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;            return blurredImage;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA; 4. Results:&#xD;&#xA;[![Original photo of the Buran][2]][2]&#xD;&#xA;&#xD;&#xA;And the result of the Gaussian Blur with $\sigma = 3$&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Gaussian_filter&#xD;&#xA;  [2]: https://i.stack.imgur.com/4BxDj.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/OarmK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41586" PostHistoryTypeId="2" PostId="13675" RevisionGUID="e1a57052-9e2d-4217-a051-af0b801322d4" CreationDate="2023-08-30T11:44:17.000" UserId="10096" Text="You can use rotations where only the deltas are based on Euler angles. Say you have a rotation matrix $R$, e.g. which can be the identity initially. Then you can update the rotation as $R'= R_z(\Delta roll) R_y(\Delta yaw) R_x(\Delta pitch)R$. Note that the $\Delta$ are only small angular changes. This will in general not cause gimbal lock and allow you to use Euler or Tait-Bryan angles (you have to change the above expression based on the conbention you use) at least for the frame to frame rotational changes." ContentLicense="CC BY-SA 4.0" />
  <row Id="41588" PostHistoryTypeId="5" PostId="13675" RevisionGUID="74fa6d81-09f9-420e-a3d9-e259e340a4d2" CreationDate="2023-08-30T13:11:05.623" UserId="7952" Comment="changed conbomation to combination" Text="You can use rotations where only the deltas are based on Euler angles. Say you have a rotation matrix $R$, e.g. which can be the identity initially. Then you can update the rotation as $R'= R_z(\Delta roll) R_y(\Delta yaw) R_x(\Delta pitch)R$. Note that the $\Delta$ are only small angular changes. This will in general not cause gimbal lock and allow you to use Euler or Tait-Bryan angles (you have to change the above expression based on the combination you use) at least for the frame to frame rotational changes." ContentLicense="CC BY-SA 4.0" />
  <row Id="41589" PostHistoryTypeId="2" PostId="13676" RevisionGUID="8fed284e-6942-4df9-a6b9-3bd784f37d89" CreationDate="2023-08-30T13:25:16.863" UserId="19537" Text="In a path tracer, if we want to sample a ray direction in scattering medium, we can use phase function sampling, which actually use the direction of the ray before sampling as a sort of anchor to sample around (just like normal vector in surface scattering). &#xD;&#xA;&#xD;&#xA;However, we could break this convention by devising new sampling approach. For example, if I want to point the ray towards the emitter. So maybe this sampling method does not sample around the incident (or, out-going, depends on what direction we are talking about) direction, as shown in the following figure. We sample $\beta$ instead of $\theta$.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tEQxj.png&#xD;&#xA;&#xD;&#xA;My question is: should we convert the PDF of $\cos\beta$ to $\cos\theta$? I think it is necessary when we want to use MIS. So how does this change of PDF work mathematically? Is this some kind of measure conversion like 'solid-angle to area product' problem? As I can tell, for example, if $\cos\beta$ is uniformly distributed, we won't have a uniformly distributed $\cos\theta$ so I think a conversion should be necessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="41591" PostHistoryTypeId="1" PostId="13676" RevisionGUID="8fed284e-6942-4df9-a6b9-3bd784f37d89" CreationDate="2023-08-30T13:25:16.863" UserId="19537" Text="Sampling scattering direction around directions other than the last ray direction" ContentLicense="CC BY-SA 4.0" />
  <row Id="41592" PostHistoryTypeId="3" PostId="13676" RevisionGUID="8fed284e-6942-4df9-a6b9-3bd784f37d89" CreationDate="2023-08-30T13:25:16.863" UserId="19537" Text="|rendering|mathematics|importance-sampling|volumetric-scattering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41596" PostHistoryTypeId="2" PostId="13678" RevisionGUID="1c602717-3e3a-4fe8-ac52-4192928a83e3" CreationDate="2023-08-30T18:45:36.423" UserId="7462" Text="If you have a map from a mesh into the 2D plane. How do you measure its distortion? I know that theoretically what you do is express the differential map of the transformation then use SVD to figure out your components and then find the magnitudes of the principal axes.&#xD;&#xA;&#xD;&#xA;But how do I even define the differential map on a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41598" PostHistoryTypeId="1" PostId="13678" RevisionGUID="1c602717-3e3a-4fe8-ac52-4192928a83e3" CreationDate="2023-08-30T18:45:36.423" UserId="7462" Text="How to measure distortion of a parametrization?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41599" PostHistoryTypeId="3" PostId="13678" RevisionGUID="1c602717-3e3a-4fe8-ac52-4192928a83e3" CreationDate="2023-08-30T18:45:36.423" UserId="7462" Text="|mathematics|computational-geometry|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41600" PostHistoryTypeId="5" PostId="13678" RevisionGUID="dbde0604-d972-433e-bf2f-fb16d0d512f6" CreationDate="2023-08-30T22:13:52.183" UserId="7462" Comment="added 282 characters in body" Text="If you have a map from a mesh into the 2D plane. How do you measure its distortion? I know that theoretically what you do is express the differential map of the transformation then use SVD to figure out your components and then find the magnitudes of the principal axes.&#xD;&#xA;&#xD;&#xA;But how do I even define the differential map on a mesh?&#xD;&#xA;&#xD;&#xA;When talking about distortion I mean the metrics of the differential map. i.e. things like the eigen values of the matrix obtained from the matrix representation of the differential map. &#xD;&#xA;&#xD;&#xA;https://www.researchgate.net/post/How-can-I-measure-distortion-of-mesh-parameterization" ContentLicense="CC BY-SA 4.0" />
  <row Id="41601" PostHistoryTypeId="2" PostId="13679" RevisionGUID="a39ab93f-115d-4cd2-a3bd-90fd8ba69dfb" CreationDate="2023-08-31T04:17:31.793" UserId="19537" Text="THIS IS NOT THE FINAL ANSWER. To be edited if more information is given.&#xD;&#xA;&#xD;&#xA;Ok, I think I've derived the mathematical form of this conversion, but **whether the conversion is needed** still remains unknown and I will leave it behind for now since I am contacting someone with this kind of area expertise to help, and the answer will be updated if I get a reasonable answer. **But I do need some reassurance for the correctness of this derivation** and I'd appreciate any help.&#xD;&#xA;&#xD;&#xA;Ok so first we re-formulate the problem setup, as shown in the following figure:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aMEF8.png&#xD;&#xA;So we will always have $\theta = \alpha - \beta$ and note that $\alpha$ (its cosine term) is the value to sample for the new approach, $\theta$ is the angle for original phase function sampling and $\beta$ is a known constant (given the ray direction before sampling and the position of current vertex and target vertex). So:&#xD;&#xA;$$&#xD;&#xA;\frac{dP}{d\cos\theta} =\underbrace{\frac{dP}{d\cos\alpha}}_{\text{known, should be converted}} \times |\frac{d\cos\alpha}{d\cos\theta}| = \frac{dP}{d\cos\alpha} |\frac{d\cos\alpha}{d\alpha}\left(\frac{d\cos(\alpha - \beta)}{d\alpha}\right)^{-1}|\\&#xD;&#xA;=\frac{dP}{d\cos\alpha} |\frac{\sin \alpha}{\sin(\alpha - \beta)}|&#xD;&#xA;$$ &#xD;&#xA;The term:&#xD;&#xA;$$&#xD;&#xA;|\frac{\sin \alpha}{\sin(\alpha - \beta)}|&#xD;&#xA;$$&#xD;&#xA;should be able to do this conversion (if needed). Note that this is just a Jacobian conversion.&#xD;&#xA;&#xD;&#xA;My point is, to apply MIS, **we can't directly use** PDF for sampling $\theta$ (cosine) and the PDF for sampling $\alpha$. The meaning of these two terms just doesn't match. We should convert both of them to the same meaning, like we are both talking about sampling $\alpha$ or $\theta$. I have done some numerical experiments, comparing hisogram of the cosine value with the analytical Jacobian I derived and I think the results match with each other.&#xD;&#xA;&#xD;&#xA;**So, this question now becomes**:&#xD;&#xA;- Whether my derivation is correct?&#xD;&#xA;- Whether this conversion is needed for MIS? Or even, since Monte Carlo estimator is of form $f(x) / p(x)$, should I multiply the PDF in the denominator by this Jacobian? " ContentLicense="CC BY-SA 4.0" />
  <row Id="41603" PostHistoryTypeId="5" PostId="13676" RevisionGUID="6004af2c-b7a9-4263-81c9-a9f4c7d1901b" CreationDate="2023-08-31T04:19:25.240" UserId="19537" Comment="A note for  the question after posting my own answer." Text="**My own answer (for part of the question) should be validated by the community.**&#xD;&#xA;&#xD;&#xA;In a path tracer, if we want to sample a ray direction in scattering medium, we can use phase function sampling, which actually use the direction of the ray before sampling as a sort of anchor to sample around (just like normal vector in surface scattering). &#xD;&#xA;&#xD;&#xA;However, we could break this convention by devising new sampling approach. For example, if I want to point the ray towards the emitter. So maybe this sampling method does not sample around the incident (or, out-going, depends on what direction we are talking about) direction, as shown in the following figure. We sample $\beta$ instead of $\theta$.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tEQxj.png&#xD;&#xA;&#xD;&#xA;My question is: should we convert the PDF of $\cos\beta$ to $\cos\theta$? I think it is necessary when we want to use MIS. So how does this change of PDF work mathematically? Is this some kind of measure conversion like 'solid-angle to area product' problem? As I can tell, for example, if $\cos\beta$ is uniformly distributed, we won't have a uniformly distributed $\cos\theta$ so I think a conversion should be necessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="41604" PostHistoryTypeId="2" PostId="13680" RevisionGUID="83660d91-5239-4209-9130-f7e2a445c2b6" CreationDate="2023-08-31T09:08:12.137" UserDisplayName="user1703" Text="Two non-parallel edges originating from a common vertex are mapped to two corresponding edges. From the two pairs of vectors, you derive a linear transformation, which gives you a local deformation matrix.&#xD;&#xA;&#xD;&#xA;[Depending on your mesh topology, you can find more pairs from a given vertex. That will give you slightly different deformation matrices.]&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41606" PostHistoryTypeId="5" PostId="13663" RevisionGUID="79a64f16-27fb-4913-92dd-7bf3106b4273" CreationDate="2023-08-31T11:06:12.963" UserId="13273" Comment="deleted 718 characters in body" Text="After a whole day of brain stress, I found a method to enumerate them:&#xD;&#xA;&#xD;&#xA;    //floats equal? with respect of epsilon&#xD;&#xA;    bool isNearlyTheSame(float value0, float value1) &#xD;&#xA;    {&#xD;&#xA;        return abs(value0 - value1) &lt; 0.001;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;	uint getMinIndex(vec3 vector)&#xD;&#xA;	{&#xD;&#xA;		uint y = uint(vector.y &lt;= vector.x + 0.001 &amp;&amp; vector.y &lt; vector.z);&#xD;&#xA;		uint z = uint(vector.z &lt; vector.x &amp;&amp; vector.z &lt;= vector.y + 0.001)*2;&#xD;&#xA;		return y + z;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;    //result: x: 0 =&gt; inner triangles, 1 =&gt; inner most vertex, 2 =&gt; outer vertices&#xD;&#xA;    //result: y: lowest barycentric value is: 0 =&gt; x, 1 =&gt; y, 2 =&gt; z  &#xD;&#xA;    uvec2 getBarycentricCase()&#xD;&#xA;	{&#xD;&#xA;		uvec2 baryCase = uvec2(0,0);&#xD;&#xA;		baryCase.y = getMinIndex(gl_TessCoord);&#xD;&#xA;		if(gl_TessCoord.x == 0 || gl_TessCoord.y == 0 || gl_TessCoord.z == 0)&#xD;&#xA;			baryCase.x = 2;&#xD;&#xA;		if(isNearlyTheSame(gl_TessCoord.x, gl_TessCoord.y) &amp;&amp; isNearlyTheSame(gl_TessCoord.y, gl_TessCoord.z))&#xD;&#xA;			baryCase.x = 1;&#xD;&#xA;		return baryCase;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;    //returns a third of the count of the inner vertices with respect to the tessLevel&#xD;&#xA;    uint getNummTessPart(uint tessLevel)&#xD;&#xA;    {&#xD;&#xA;        float oddAdd = mod(tessLevel, 2) == 0 ? 0 : 1;&#xD;&#xA;        return tessLevel / 2.0 * (tessLevel / 2.0 - 1) + oddAdd;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //returns the current patch vertex id with respect to this algorithm&#xD;&#xA;    uint getPatchVertexID()&#xD;&#xA;	{&#xD;&#xA;		uint result;&#xD;&#xA;		uvec2 baryCase = getBarycentricCase();&#xD;&#xA;		uint outerTesslevel0 = uint(gl_TessLevelOuter[0]);&#xD;&#xA;		uint outerTesslevel1 = uint(gl_TessLevelOuter[1]);&#xD;&#xA;		uint outerTesslevel2 = uint(gl_TessLevelOuter[2]);&#xD;&#xA;		uint innerTesslevel = uint(gl_TessLevelInner[0]);&#xD;&#xA;&#xD;&#xA;		uint numTessPartInner = uint(getNummTessPart(innerTesslevel));&#xD;&#xA;		float baseValue = min(min(gl_TessCoord.x,gl_TessCoord.y), gl_TessCoord.z);&#xD;&#xA;		float leftValue = baryCase.y == 0 ? gl_TessCoord.z : baryCase.y == 1 ? gl_TessCoord.x : baryCase.y == 2 ? gl_TessCoord.y : 0;&#xD;&#xA;&#xD;&#xA;		if(baryCase.x == 0) //inner vertices&#xD;&#xA;		{&#xD;&#xA;			float stepUp = 2.0 / 3.0 / innerTesslevel;&#xD;&#xA;			float stepLeft = 1.0 / innerTesslevel;&#xD;&#xA;			uint positionUp = uint(round(baseValue / stepUp));&#xD;&#xA;			uint positionLeft = uint(round(leftValue / stepLeft + (positionUp) * stepUp * innerTesslevel / 2 - positionUp));&#xD;&#xA;			result = numTessPartInner - uint(getNummTessPart(innerTesslevel - ((positionUp-1) * 2)));&#xD;&#xA;			result += positionLeft;&#xD;&#xA;			result += baryCase.y * numTessPartInner;&#xD;&#xA;		}&#xD;&#xA;		else if(baryCase.x == 1) //center vertex&#xD;&#xA;		{&#xD;&#xA;			result = numTessPartInner * 3;&#xD;&#xA;		}&#xD;&#xA;		else if(baryCase.x == 2) //outer&#xD;&#xA;		{&#xD;&#xA;			uint maxOuterTessLevel = max(max(outerTesslevel0, outerTesslevel1), outerTesslevel2);&#xD;&#xA;			bool hasCenter = (mod(innerTesslevel,2) == 0 &amp;&amp; innerTesslevel &gt; 1) || (maxOuterTessLevel &gt; 1 &amp;&amp; innerTesslevel &lt; 1);&#xD;&#xA;			bool hasInner = innerTesslevel &gt; 2;&#xD;&#xA;			uint outerAdd[3] = {0, outerTesslevel0, outerTesslevel0 + outerTesslevel1};&#xD;&#xA;			result = uint(hasInner) * numTessPartInner * 3;&#xD;&#xA;			result += uint(hasCenter);    &#xD;&#xA;			result += uint(round(leftValue * gl_TessLevelOuter[baryCase.y])) + outerAdd[baryCase.y];&#xD;&#xA;		}&#xD;&#xA;		return result;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;As can be seen in Figure 1, the algorithm first enumerates the inner vertices, dividing them into 3 parts. After the inner vertices, the innermost vertex (in case of an even innerTessLevel) is enumerated. At the end, the outer vertices are enumerated.&#xD;&#xA;&#xD;&#xA;[![Insert image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Enumeration sceme for: `gl_TessLevelInner[0] = 10`, `gl_TessLevelOuter[0] = 10`, `gl_TessLevelOuter[1] = 10`, `gl_TessLevelOuter[2] = 10`.&#xD;&#xA;&#xD;&#xA;This algorithm works for all types of triangles tessellation, where innerTessLevel and outerTessLevels are integer values. The enumeration only works for `equal_spacing`. As you can see from the code, the enumerated value is calculated by the following built-in variables of TES:&#xD;&#xA;&#xD;&#xA; - `in vec3 gl_TessCoord`&#xD;&#xA; - `patch in float gl_TessLevelOuter[3]`&#xD;&#xA; - `patch in float gl_TessLevelInner[1]`&#xD;&#xA;&#xD;&#xA;I will try to improve the algorithm from time to time.... at the moment it is very confusing and full of branches... maybe we can avoid branching in the end. &#xD;&#xA;&#xD;&#xA;**Also important, when using this algorithm:**&#xD;&#xA;Multiple generated vertices within TES stage are on the same position. So the output of this algorithm gives you an enumeration with respect to the position. But not with respect to the vertex id. So multiple generated vertices will receive the same enumarated number at the end.&#xD;&#xA;&#xD;&#xA;Please feel free to give me tips on how to improve the algorithm =)&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/OvC91.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41607" PostHistoryTypeId="2" PostId="13681" RevisionGUID="1b04e781-458c-426c-887b-6ad56beb3b85" CreationDate="2023-09-01T00:07:10.330" UserId="20471" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hbWDB.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise." ContentLicense="CC BY-SA 4.0" />
  <row Id="41609" PostHistoryTypeId="1" PostId="13681" RevisionGUID="1b04e781-458c-426c-887b-6ad56beb3b85" CreationDate="2023-09-01T00:07:10.330" UserId="20471" Text="Vulkan forward-only path tracer with caustics" ContentLicense="CC BY-SA 4.0" />
  <row Id="41610" PostHistoryTypeId="3" PostId="13681" RevisionGUID="1b04e781-458c-426c-887b-6ad56beb3b85" CreationDate="2023-09-01T00:07:10.330" UserId="20471" Text="|glsl|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41611" PostHistoryTypeId="5" PostId="13681" RevisionGUID="d096d75e-f944-43a0-ac8f-f7b3333718a8" CreationDate="2023-09-01T04:38:07.837" UserId="20471" Comment="added 760 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hbWDB.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="41612" PostHistoryTypeId="5" PostId="13681" RevisionGUID="5afbe556-ea03-423c-90e0-dd3d4c809ead" CreationDate="2023-09-01T04:40:13.690" UserId="20471" Comment="added 112 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hbWDB.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="41613" PostHistoryTypeId="5" PostId="13681" RevisionGUID="cea3104c-6ded-40de-a1a1-6d457cdd3c1e" CreationDate="2023-09-01T04:40:43.750" UserId="20471" Comment="deleted 5 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hbWDB.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}" ContentLicense="CC BY-SA 4.0" />
  <row Id="41614" PostHistoryTypeId="5" PostId="13680" RevisionGUID="ce9ef520-deec-43d0-8876-6f54e18fac2d" CreationDate="2023-09-01T07:13:39.417" UserDisplayName="user1703" Comment="added 115 characters in body" Text="Two non-parallel edges originating from a common vertex are mapped to two corresponding edges. From the two pairs of vectors, you derive a linear transformation, which gives you a local deformation matrix.&#xD;&#xA;&#xD;&#xA;[Depending on your mesh topology, you can find more pairs from a given vertex. That will give you slightly different deformation matrices.]&#xD;&#xA;&#xD;&#xA;You can get better accuracy by fitting an affine transform on more local vectors, or even with a nonlinear model." ContentLicense="CC BY-SA 4.0" />
  <row Id="41615" PostHistoryTypeId="5" PostId="13679" RevisionGUID="b6d7c55a-f9ae-444c-98e8-f0ef3d714d67" CreationDate="2023-09-01T09:28:57.863" UserId="19537" Comment="added 298 characters in body" Text="I think I got the answer via extensive numerical simulation. The result of the simulation is not listed here, so if you need it then you can comment to let me know.&#xD;&#xA;&#xD;&#xA;Ok, I think I've derived the mathematical form of this conversion, but **whether the conversion is needed** still remains unknown and I will leave it behind for now since I am contacting someone with this kind of area expertise to help, and the answer will be updated if I get a reasonable answer. **But I do need some reassurance for the correctness of this derivation** and I'd appreciate any help.&#xD;&#xA;&#xD;&#xA;Ok so first we re-formulate the problem setup, as shown in the following figure:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aMEF8.png&#xD;&#xA;So we will always have $\theta = \alpha - \beta$ and note that $\alpha$ (its cosine term) is the value to sample for the new approach, $\theta$ is the angle for original phase function sampling and $\beta$ is a known constant (given the ray direction before sampling and the position of current vertex and target vertex). So:&#xD;&#xA;$$&#xD;&#xA;\frac{dP}{d\cos\theta} =\underbrace{\frac{dP}{d\cos\alpha}}_{\text{known, should be converted}} \times |\frac{d\cos\alpha}{d\cos\theta}| = \frac{dP}{d\cos\alpha} |\frac{d\cos\alpha}{d\alpha}\left(\frac{d\cos(\alpha - \beta)}{d\alpha}\right)^{-1}|\\&#xD;&#xA;=\frac{dP}{d\cos\alpha} |\frac{\sin \alpha}{\sin(\alpha - \beta)}|&#xD;&#xA;$$ &#xD;&#xA;The term:&#xD;&#xA;$$&#xD;&#xA;|\frac{\sin \alpha}{\sin(\alpha - \beta)}|&#xD;&#xA;$$&#xD;&#xA;should be able to do this conversion (if needed). Note that this is just a Jacobian conversion.&#xD;&#xA;&#xD;&#xA;My point is, to apply MIS, **we can't directly use** PDF for sampling $\theta$ (cosine) and the PDF for sampling $\alpha$. The meaning of these two terms just doesn't match. We should convert both of them to the same meaning, like we are both talking about sampling $\alpha$ or $\theta$. I have done some numerical experiments, comparing hisogram of the cosine value with the analytical Jacobian I derived and I think the results match with each other.&#xD;&#xA;&#xD;&#xA;**So, this question now becomes**:&#xD;&#xA;- Whether my derivation is correct?&#xD;&#xA;    - The answer is yes. I did a numerical simulation, compared the histogram and the analytical curve and found they are matched.&#xD;&#xA;- Whether this conversion is needed for MIS? Or even, since Monte Carlo estimator is of form $f(x) / p(x)$, should I multiply the PDF in the denominator by this Jacobian? &#xD;&#xA;    - I think the answer is no, it is not needed. A numerical simulation again showed that when I add this conversion, the result will not be correct (won't match)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41616" PostHistoryTypeId="5" PostId="13676" RevisionGUID="adfb892a-50f3-44f4-bcbb-8ccdc3f97c86" CreationDate="2023-09-01T09:29:14.547" UserId="19537" Comment="deleted 86 characters in body" Text="In a path tracer, if we want to sample a ray direction in scattering medium, we can use phase function sampling, which actually use the direction of the ray before sampling as a sort of anchor to sample around (just like normal vector in surface scattering). &#xD;&#xA;&#xD;&#xA;However, we could break this convention by devising new sampling approach. For example, if I want to point the ray towards the emitter. So maybe this sampling method does not sample around the incident (or, out-going, depends on what direction we are talking about) direction, as shown in the following figure. We sample $\beta$ instead of $\theta$.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/tEQxj.png&#xD;&#xA;&#xD;&#xA;My question is: should we convert the PDF of $\cos\beta$ to $\cos\theta$? I think it is necessary when we want to use MIS. So how does this change of PDF work mathematically? Is this some kind of measure conversion like 'solid-angle to area product' problem? As I can tell, for example, if $\cos\beta$ is uniformly distributed, we won't have a uniformly distributed $\cos\theta$ so I think a conversion should be necessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="41617" PostHistoryTypeId="5" PostId="13681" RevisionGUID="dfb02a8e-eae0-46cb-aad5-8b2e329899ff" CreationDate="2023-09-01T14:28:31.223" UserId="20471" Comment="added 6 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41618" PostHistoryTypeId="5" PostId="13681" RevisionGUID="51488f46-dd42-4a6e-9e4a-481af873c631" CreationDate="2023-09-01T16:15:00.500" UserId="20471" Comment="added 91 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41621" PostHistoryTypeId="2" PostId="13682" RevisionGUID="c3fa8eed-6a30-4cc3-8804-a911f0f9a917" CreationDate="2023-09-02T08:44:57.033" UserId="18408" Text="I'm building a little 2D graphics library in Rust/WGPU as a means to learn graphics programming. I want to draw an outline around a shape and specify the outline's color. All of my shapes have a texture, either explicitly set or a 1x1 white pixel otherwise. When I draw a shape with the default white texture, the outline is as expected but when I do the same with another texture set, it samples the color and sets the outline to it.&#xD;&#xA;&#xD;&#xA;Here's  an example of the problem: the central rectangle has a white outline as desired, but the top left square has a red outline but it should be white.&#xD;&#xA;&#xD;&#xA;[![Example showing correct and incorrect behaviour][1]][1]&#xD;&#xA;&#xD;&#xA;I don't want to change pipelines to draw the border and I'd like to avoid changing bind groups (because of instancing). How can I conditionally decide in the shader whether to sample from the texture or not?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EWhOT.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41623" PostHistoryTypeId="1" PostId="13682" RevisionGUID="c3fa8eed-6a30-4cc3-8804-a911f0f9a917" CreationDate="2023-09-02T08:44:57.033" UserId="18408" Text="Conditionally sample from texture in shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="41624" PostHistoryTypeId="3" PostId="13682" RevisionGUID="c3fa8eed-6a30-4cc3-8804-a911f0f9a917" CreationDate="2023-09-02T08:44:57.033" UserId="18408" Text="|shader|texture|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41625" PostHistoryTypeId="50" PostId="13613" RevisionGUID="e88294bf-558f-406f-9192-8b0a80789da2" CreationDate="2023-09-02T13:00:35.060" UserId="-1" />
  <row Id="41626" PostHistoryTypeId="5" PostId="13682" RevisionGUID="aa2f2fcc-19ae-423d-98f0-d31219970ea8" CreationDate="2023-09-02T13:03:19.737" UserId="18408" Comment="Add relevant outline calculation and shader example" Text="I'm building a little 2D graphics library in Rust/WGPU as a means to learn graphics programming. I want to draw an outline around a shape and specify the outline's color. All of my shapes have a texture, either explicitly set or a 1x1 white pixel otherwise. When I draw a shape with the default white texture, the outline is as expected but when I do the same with another texture set, it samples the color and sets the outline to it.&#xD;&#xA;&#xD;&#xA;Here's  an example of the problem: the central rectangle has a white outline as desired, but the top left square has a red outline but it should be white.&#xD;&#xA;&#xD;&#xA;[![Example showing correct and incorrect behaviour][1]][1]&#xD;&#xA;&#xD;&#xA;The outline calculation is based on [this answer][2] and I'm calculating a triangle list so that I can use the same pipeline as the main shape which is also using a triangle list. Relevant aspects of my shaders and data structures are as follows:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;struct Vertex {&#xD;&#xA;    @location(0) coords: vec2&lt;f32&gt;,&#xD;&#xA;    @location(1) color: vec4&lt;f32&gt;,&#xD;&#xA;    @location(2) tex_coords: vec2&lt;f32&gt;,&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;struct VsOut {&#xD;&#xA;    @builtin(position) position: vec4&lt;f32&gt;,&#xD;&#xA;    @location(0) color: vec4&lt;f32&gt;,&#xD;&#xA;    @location(1) tex_coords: vec2&lt;f32&gt;,&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    return VsOut(&#xD;&#xA;        vertex.coords,&#xD;&#xA;        vertex.color,&#xD;&#xA;        vertex.tex_coords,&#xD;&#xA;    );&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;@group(1)&#xD;&#xA;@binding(0)&#xD;&#xA;var r_sampler: sampler;&#xD;&#xA;@group(1)&#xD;&#xA;@binding(1)&#xD;&#xA;var r_texture: texture_2d&lt;f32&gt;;&#xD;&#xA;&#xD;&#xA;@fragment&#xD;&#xA;fn fs_main(in: VsOut) -&gt; @location(0) vec4&lt;f32&gt; {&#xD;&#xA;    let sample = textureSample(r_texture, r_sampler, in.tex_coords);&#xD;&#xA;    return sample * in.color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I don't want to change pipelines to draw the border and I'd like to avoid changing bind groups (because of instancing). How can I conditionally decide in the shader whether to sample from the texture or not?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/EWhOT.png&#xD;&#xA;  [2]: https://stackoverflow.com/questions/68973103/how-to-create-outline?noredirect=1&amp;lq=1" ContentLicense="CC BY-SA 4.0" />
  <row Id="41627" PostHistoryTypeId="2" PostId="13683" RevisionGUID="e933b149-c396-4181-b6c6-8059ffacc274" CreationDate="2023-09-02T13:43:47.833" UserId="445" Text="&gt; How can I conditionally decide in the shader whether to sample from the texture or not?&#xD;&#xA;&#xD;&#xA;Abstractly, this is simple:&#xD;&#xA;&#xD;&#xA;* Add a vertex attribute that specifies whether to use the texture or not. Set that attribute appropriately for your outline and your fill (which I understand to be made of separate triangles).&#xD;&#xA;* Pass the attribute on to the fragment shader.&#xD;&#xA;* In the fragment shader, &#xD;&#xA;&#xD;&#xA;    ```wgsl&#xD;&#xA;    let sample = textureSample(r_texture, r_sampler, in.tex_coords);&#xD;&#xA;    if in.use_texture {&#xD;&#xA;        return sample * in.color;&#xD;&#xA;    } else {&#xD;&#xA;        return in.color;&#xD;&#xA;    }&#xD;&#xA;    ```&#xD;&#xA;&#xD;&#xA;(The `textureSample()` call is outside of the `if` because it needs to be in “uniform control flow”; this can be avoided but that's another entire topic.)&#xD;&#xA;&#xD;&#xA;However, you don't necessarily need to introduce a separate attribute; you can use one that already exists. For example, you could give all the border triangles texture coordinates of `[-1, -1]`, which are clearly not meaningful to the texture (…unless you're using repeating textures). Or, if you never actually want to color-tint a texture, you could designate a particular _color_ value to mean “use texture”.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Or, instead, you can make sure your textures always have at least one white texel. This is a more appropriate solution if your application uses a texture atlas (unrelated textures arranged inside only one actual texture object) already.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Or if you only ever want to draw rectangles, then you can stretch the texture coordinates a bit in your mesh construction and draw a border that way, instead of using extra triangles:&#xD;&#xA;&#xD;&#xA;```wgsl&#xD;&#xA;if any(in.tex_coords &lt; 0.0) || any(in.tex_coords &gt; 0.0) {&#xD;&#xA;    return sample * in.color;&#xD;&#xA;} else {&#xD;&#xA;    return in.color;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(Since you're using `wgpu` specifically, I'll mention that you can also use [clamp to border](https://docs.rs/wgpu/0.17.0/wgpu/enum.AddressMode.html#variant.ClampToBorder) to implement this directly in the sampler rather than in shader code. However, that's an extension and is not supported in WebGPU proper.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="41629" PostHistoryTypeId="2" PostId="13684" RevisionGUID="3a321ce5-78d7-4a6b-8aeb-de5d4d1bf609" CreationDate="2023-09-02T17:28:18.040" UserId="20476" Text="I have designed my graphics pipeline, actually similar to what exists now, you know, vertex shader, then rasterizer, interpolation, fragment shader and so on. But, some stuff are changed in my pipeline. Like the rasterization stage. Currently, as I have understood from [Computer Graphics From Scratch](https://gabrielgambetta.com/computer-graphics-from-scratch/)  book ( which I really recommend ) is that, rasterizer interpolates pixel coords, UVs, depth, Normals and etc. on (almost) every pixel.&#xD;&#xA;But I want to change that, **I want to define how the rasterizer should act and how it should interpolate**, but I have no idea how to.&#xD;&#xA;Some people on the web said it's impossible unless you are a driver programmer, then you might have a chance. &#xD;&#xA;I want to make sure that it is possible to distort that code, and maybe edit the whole code of current pipeline." ContentLicense="CC BY-SA 4.0" />
  <row Id="41631" PostHistoryTypeId="1" PostId="13684" RevisionGUID="3a321ce5-78d7-4a6b-8aeb-de5d4d1bf609" CreationDate="2023-09-02T17:28:18.040" UserId="20476" Text="re-writing the rasterizer of a pipeline" ContentLicense="CC BY-SA 4.0" />
  <row Id="41632" PostHistoryTypeId="3" PostId="13684" RevisionGUID="3a321ce5-78d7-4a6b-8aeb-de5d4d1bf609" CreationDate="2023-09-02T17:28:18.040" UserId="20476" Text="|rasterizer|driver|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41633" PostHistoryTypeId="50" PostId="13609" RevisionGUID="08c13534-0bfb-4ed0-8a83-b2b85a498773" CreationDate="2023-09-02T19:05:50.670" UserId="-1" />
  <row Id="41634" PostHistoryTypeId="5" PostId="13681" RevisionGUID="a192ac7d-87b6-43f7-8ea1-58619b8d187c" CreationDate="2023-09-03T01:14:40.440" UserId="20471" Comment="deleted 67 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41635" PostHistoryTypeId="2" PostId="13685" RevisionGUID="5a6d17da-92e4-4066-9451-4156d44679be" CreationDate="2023-09-03T12:42:15.273" UserId="2639" Text="I'm searching for an efficient data structure and algorithm to compute the minimum distance between a ray and a set of meshes in 3D.&#xD;&#xA;&#xD;&#xA;What I expect as a result are the coordinates of the nearest point on the nearest mesh.&#xD;&#xA;&#xD;&#xA;I'm interested in the general case where the (infinite) ray is not intersecting with any mesh, but I'd expect if it's actually intersecting to get as a result the nearest intersecting point.&#xD;&#xA;&#xD;&#xA;For efficiency purpose, I'm willing to set up some accelerating data structure with the list of meshes (and to simplify / decompose those as convex hulls if this is an algorithm expectation), instead of iterating on meshes and their components." ContentLicense="CC BY-SA 4.0" />
  <row Id="41637" PostHistoryTypeId="1" PostId="13685" RevisionGUID="5a6d17da-92e4-4066-9451-4156d44679be" CreationDate="2023-09-03T12:42:15.273" UserId="2639" Text="How to find point on mesh at a minimum distance from ray" ContentLicense="CC BY-SA 4.0" />
  <row Id="41638" PostHistoryTypeId="3" PostId="13685" RevisionGUID="5a6d17da-92e4-4066-9451-4156d44679be" CreationDate="2023-09-03T12:42:15.273" UserId="2639" Text="|3d|computational-geometry|mesh|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41639" PostHistoryTypeId="5" PostId="13675" RevisionGUID="e7f65b71-0675-43a8-be7c-dd0d54adc49f" CreationDate="2023-09-03T15:29:57.723" UserId="10096" Comment="deleted 1 character in body" Text="You can use rotations where only the deltas are based on Euler angles. Say you have a rotation matrix $R$, e.g. which can be the identity initially. Then you can update the rotation as $R'= R_z(\Delta roll) R_y(\Delta yaw) R_x(\Delta pitch)R$. Note that the $\Delta$ are only small angular changes. This will in general not cause gimbal lock and allow you to use Euler or Tait-Bryan angles (you have to change the above expression based on the convention you use) at least for the frame to frame rotational changes." ContentLicense="CC BY-SA 4.0" />
  <row Id="41640" PostHistoryTypeId="5" PostId="13681" RevisionGUID="14cdf420-b875-454e-be76-b48b0bb742d8" CreationDate="2023-09-03T17:35:15.970" UserId="20471" Comment="deleted 22 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	d = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41641" PostHistoryTypeId="2" PostId="13686" RevisionGUID="fc94003c-27b1-4ae6-aaad-77c03b3a72ef" CreationDate="2023-09-03T17:54:26.547" UserId="20354" Text="I'm working on a 2D (pseudo-3D) raycaster which operates on a 2D tile grid.&#xD;&#xA;&#xD;&#xA;For each ray sent out, the screen draws a rectangle with a certain height depending on the distance between the camera and the wall the ray collided with (like Wolfenstein 3D).&#xD;&#xA;&#xD;&#xA;I am now working on drawing texture images and have run into a problem:&#xD;&#xA;&#xD;&#xA;If for example six rays hits a wall segment (tile) then the image which corresponds to this tile should be sliced into six parts. If there was 100 rays then the image needs to have 100 slices.&#xD;&#xA;&#xD;&#xA;However, obviously there exist no image width which can be divided by all numbers.&#xD;&#xA;&#xD;&#xA;How to go about this?&#xD;&#xA;&#xD;&#xA;My current idea is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    Load several resolutions of the image texture, for example: (100x100, 200x200, 400x400, 800x800)&#xD;&#xA;&#xD;&#xA;    Identify how many rays has hit wall segment X&#xD;&#xA;&#xD;&#xA;    Identify which image resolution fits best to the scaled height of the rectangle (depending on distance from camera to target). Lower resolution for more distant objects etc.&#xD;&#xA;&#xD;&#xA;    Transform the selected image into the closest resolution which can be divided into a whole number by the amounts of rays which hit the segment&#xD;&#xA;&#xD;&#xA;I believe this could work in principle however I would hope there is an easier solution which requires less image transforms." ContentLicense="CC BY-SA 4.0" />
  <row Id="41643" PostHistoryTypeId="1" PostId="13686" RevisionGUID="fc94003c-27b1-4ae6-aaad-77c03b3a72ef" CreationDate="2023-09-03T17:54:26.547" UserId="20354" Text="Best approach for slicing texture images for raycasting" ContentLicense="CC BY-SA 4.0" />
  <row Id="41644" PostHistoryTypeId="3" PostId="13686" RevisionGUID="fc94003c-27b1-4ae6-aaad-77c03b3a72ef" CreationDate="2023-09-03T17:54:26.547" UserId="20354" Text="|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41645" PostHistoryTypeId="5" PostId="13681" RevisionGUID="14bab209-cf7e-49fa-a1fb-98d181cf8c57" CreationDate="2023-09-03T23:06:56.600" UserId="20471" Comment="added 102 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	vec3 d_cos = cosWeightedRandomHemisphereDirection(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41646" PostHistoryTypeId="5" PostId="13681" RevisionGUID="faaa6674-9867-4f5a-a82d-d3047fbaeb83" CreationDate="2023-09-03T23:07:54.043" UserId="20471" Comment="deleted 24 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(normalize(rayPayload.normal), prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41647" PostHistoryTypeId="5" PostId="13681" RevisionGUID="bdd48871-0b0f-4c4d-af2a-f0851549e56b" CreationDate="2023-09-03T23:09:05.573" UserId="20471" Comment="deleted 11 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + normalize(rayPayload.normal)*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41648" PostHistoryTypeId="5" PostId="13681" RevisionGUID="591802f1-ee2c-48ed-83f2-06c8f7ad6eef" CreationDate="2023-09-03T23:21:23.273" UserId="20471" Comment="deleted 11 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41649" PostHistoryTypeId="5" PostId="13681" RevisionGUID="40b9c927-bde0-4d8d-9f58-703af53343e2" CreationDate="2023-09-03T23:21:52.843" UserId="20471" Comment="deleted 2 characters in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41650" PostHistoryTypeId="5" PostId="13681" RevisionGUID="b1051f62-0735-410a-b30c-6a82803d27fb" CreationDate="2023-09-03T23:22:41.620" UserId="20471" Comment="deleted 1 character in body" Text="TL;DR -- who has discovered, in the past, a forward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known forward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41651" PostHistoryTypeId="2" PostId="13687" RevisionGUID="61f69c53-a9b8-489e-9e31-85cacd842cb1" CreationDate="2023-09-04T09:52:51.673" UserId="20482" Text="I had an old, broken hard disk containing a lot of JPEG files.&#xD;&#xA;&#xD;&#xA;I took that hard to an information recovery company.&#xD;&#xA;&#xD;&#xA;The company was able to extract part of the files well, But there are many others files that look like this...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8G87I.png&#xD;&#xA;&#xD;&#xA;Is it possible to repair these files? The file size is the same as before, and it even shows the image information (camera used, resolution....etc.)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41653" PostHistoryTypeId="1" PostId="13687" RevisionGUID="61f69c53-a9b8-489e-9e31-85cacd842cb1" CreationDate="2023-09-04T09:52:51.673" UserId="20482" Text="JPEG Corrupted file fixing" ContentLicense="CC BY-SA 4.0" />
  <row Id="41654" PostHistoryTypeId="3" PostId="13687" RevisionGUID="61f69c53-a9b8-489e-9e31-85cacd842cb1" CreationDate="2023-09-04T09:52:51.673" UserId="20482" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41660" PostHistoryTypeId="2" PostId="13689" RevisionGUID="cb7e50c7-b461-4902-8358-0423675f6e6d" CreationDate="2023-09-04T15:52:45.843" UserId="445" Text="You have independently rediscovered part of the problem known as [texture filtering](https://en.wikipedia.org/wiki/Texture_filtering).&#xD;&#xA;&#xD;&#xA;The simplest possible solution is to figure out where on the texture the ray hit, considering it as a mathematical rectangle, and just take whichever texel (or in your case, column of texels) is nearest to that point — _nearest-neighbor sampling_. This is probably (I'm not personally familiar) how Wolfenstein 3D actually works — it creates a blocky, pixelated look, which we now often find “retro” and aesthetically pleasing when applicable.&#xD;&#xA;&#xD;&#xA;To reduce the pixelated look, the next step is to _interpolate between multiple texels_ — nearly every texture in “realistic” graphics is processed this way. In this world, you think about texels as being infinitesimal point samples of the “real” texture, and approximate all the points in between the actual stored texels by linear interpolation. If the ray hit an x position that's 1/4 of the way to texture column 7 and 3/4 of the way to texture column 8, you'd compute 1/4 of column 7's texels + 3/4 of column 8's texels. This is done for every pixel, every frame.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Regardless of whether you use interpolation or not, you will observe chaotic noise (aliasing) when the texture is displayed so far away (relative to the screen resolution) that it is smaller than its original resolution and details are intermittently lost. Your idea of creating multiple resolutions of the input image is a way to solve this problem, and it is called [**mipmapping**](https://en.wikipedia.org/wiki/Mipmap). However, mipmapping can also cause textures to be noticeably low-resolution; it's a tradeoff, that should be made with consideration for the contents of the texture, the visual effect you want, and the maximum view distance.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;However, in all of the above cases, fitting the on-screen width to the texture width by an _exact ratio_ is never done. If it was, the user would observe glitchy effects as their viewpoint changed by small amounts. The answer here is to just not worry about it — just use floating-point or fixed-point arithmetic to compute where on the texture the ray landed, and find the nearest texel(s), and interpolate or don't as you see fit. **The calculation for each screen pixel (or column of pixels in your case) is independent of its neighbors** except for purposes of choosing a mipmap level if you are doing mipmapping." ContentLicense="CC BY-SA 4.0" />
  <row Id="41662" PostHistoryTypeId="5" PostId="13681" RevisionGUID="35103af6-6bbd-4b3a-8d1d-dbca58213a02" CreationDate="2023-09-04T17:25:07.910" UserId="20471" Comment="added 2 characters in body; edited title" Text="TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41663" PostHistoryTypeId="4" PostId="13681" RevisionGUID="35103af6-6bbd-4b3a-8d1d-dbca58213a02" CreationDate="2023-09-04T17:25:07.910" UserId="20471" Comment="added 2 characters in body; edited title" Text="Vulkan backward-only path tracer with caustics" ContentLicense="CC BY-SA 4.0" />
  <row Id="41665" PostHistoryTypeId="5" PostId="13681" RevisionGUID="f6ac09b1-e29f-42d7-810b-f664f1adbde3" CreationDate="2023-09-05T23:49:34.830" UserId="20471" Comment="added 85 characters in body" Text="TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/KLJiF.png&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41668" PostHistoryTypeId="2" PostId="13691" RevisionGUID="d88a729f-369e-471d-929f-fb27dff8642a" CreationDate="2023-09-06T12:45:21.390" UserId="20491" Text="i'm currently following a tutorial on youtube to get started with computer graphics (shaders) and it contains the following GLSL code:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;void mainImage(out vec4 fragColor, in vec2 fragCoord) {&#xD;&#xA;    vec2 uv = fragCoord / iResolution.xy * 2. - 1.; // Normalize &amp; center&#xD;&#xA;    uv.x *= iResolution.x / iResolution.y; // Account for aspect ratio&#xD;&#xA;&#xD;&#xA;    float d = length(uv);&#xD;&#xA;    fragColor = vec4(d, d, d, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However, in the tutorial the two first lines are simplified into:&#xD;&#xA;```glsl&#xD;&#xA;    vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;I can't understand how this simplification is made.&#xD;&#xA;I think I found the first part by merging both expressions in one:&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;    vec2 uv = (fragCoord * 2.0 / iResolution.xy - 1.0) * vec2(iResolution.x / iResolution.y, 1.0);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If possible, **could anyone provide me with the detailed steps of this simplification** please ?&#xD;&#xA;&#xD;&#xA;This is a picture of the expected result:[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Thank you&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Oz7b4.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41670" PostHistoryTypeId="1" PostId="13691" RevisionGUID="d88a729f-369e-471d-929f-fb27dff8642a" CreationDate="2023-09-06T12:45:21.390" UserId="20491" Text="Need help understanding this simplification/optimization for a very basic GLSL shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="41671" PostHistoryTypeId="3" PostId="13691" RevisionGUID="d88a729f-369e-471d-929f-fb27dff8642a" CreationDate="2023-09-06T12:45:21.390" UserId="20491" Text="|shader|glsl|mathematics|optimisation|optimization|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41672" PostHistoryTypeId="2" PostId="13692" RevisionGUID="610c8535-0a9a-47c1-9482-640def08ae52" CreationDate="2023-09-06T17:24:16.143" UserId="19537" Text="Is this what you are looking for? &#xD;&#xA;&#xD;&#xA;`fragCoord` and `iResolution` are both of `vec2` type and the **vector division is element-wise**. So the first step get you:&#xD;&#xA;```c++&#xD;&#xA;vec2 uv = fragCoord / iResolution.xy * 2. - 1.; // Normalize &amp; center&#xD;&#xA;// uv.x = fragCoord.x / iResolution.x * 2. - 1.&#xD;&#xA;```&#xD;&#xA;In the second step, we multiply `uv.x` by `iResolution.x / iResolution.y` so basically:&#xD;&#xA;```c++&#xD;&#xA;uv.x = (fragCoord.x / iResolution.x * 2. - 1.) * iResolution.x / iResolution.y&#xD;&#xA;// this can be simplified to the following since iResolution.x is cancelled out.&#xD;&#xA;uv.x = fragCoord.x / iResolution.y * 2. - iResolution.x / iResolution.y&#xD;&#xA;```&#xD;&#xA;You will find the `uv.x` is exactly the x field of:&#xD;&#xA;```c++&#xD;&#xA;vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;&#xD;&#xA;// uv.x = (fragCoord.x * 2.0 - iResolution.x) / iResolution.y&#xD;&#xA;// = fragCoord.x / iResolution.y * 2.0 - iResolution.x / iResolution.y;&#xD;&#xA;```&#xD;&#xA;which is the simplified version in the tutorial.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41674" PostHistoryTypeId="2" PostId="13693" RevisionGUID="34817c7b-0259-4383-8a99-b8e5056b7aa6" CreationDate="2023-09-06T20:53:41.547" UserId="20494" Text="I was reading [this question][1] regarding half from 3 years ago and the selected answer seemed pretty smart to me. However, while actually implementing it I'm confused at the part where I have to fill in the next pointer of an opposite half-edge of a half-edge.&#xD;&#xA;&#xD;&#xA;&gt; So the boundary edge actually does have an opposite (or pair pointer) and that opposite is fully integrated into the pointer structure, complete with next pointer and everything. Just that its face pointer in null, thus denoting an empty face or hole. So basically every hole is represented by a null face with half edges going around it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;So say that the half edges of a face are winded counter-clockwise (blue arrows). For the red half edge, the 'next' pointer of the edge should be the next purple half edge... But how do I obtain the purple half edge from the red half edge? For this case, I can get it from the red half edge by the sequence of the following operations: opposite - previous - opposite - next - next - opposite, but is this the best approach and is it scalable? I would appreciate it if someone could guide me to a smarter method.&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/9566/how-to-handle-half-edge-boundary-edge-iteration-from-vertex&#xD;&#xA;  [2]: https://i.stack.imgur.com/SOKur.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41676" PostHistoryTypeId="1" PostId="13693" RevisionGUID="34817c7b-0259-4383-8a99-b8e5056b7aa6" CreationDate="2023-09-06T20:53:41.547" UserId="20494" Text="What is a smart way to fill in the 'next' pointer of a opposite half-edge of a boundary?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41677" PostHistoryTypeId="3" PostId="13693" RevisionGUID="34817c7b-0259-4383-8a99-b8e5056b7aa6" CreationDate="2023-09-06T20:53:41.547" UserId="20494" Text="|mesh|half-edge|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41678" PostHistoryTypeId="5" PostId="13693" RevisionGUID="cbd66a7e-84ab-4b67-a47b-66aab17abd44" CreationDate="2023-09-06T20:53:54.513" UserId="20494" Comment="added 6 characters in body" Text="I was reading [this question][1] regarding half edges from 3 years ago and the selected answer seemed pretty smart to me. However, while actually implementing it I'm confused at the part where I have to fill in the next pointer of an opposite half-edge of a half-edge.&#xD;&#xA;&#xD;&#xA;&gt; So the boundary edge actually does have an opposite (or pair pointer) and that opposite is fully integrated into the pointer structure, complete with next pointer and everything. Just that its face pointer in null, thus denoting an empty face or hole. So basically every hole is represented by a null face with half edges going around it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;So say that the half edges of a face are winded counter-clockwise (blue arrows). For the red half edge, the 'next' pointer of the edge should be the next purple half edge... But how do I obtain the purple half edge from the red half edge? For this case, I can get it from the red half edge by the sequence of the following operations: opposite - previous - opposite - next - next - opposite, but is this the best approach and is it scalable? I would appreciate it if someone could guide me to a smarter method.&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/9566/how-to-handle-half-edge-boundary-edge-iteration-from-vertex&#xD;&#xA;  [2]: https://i.stack.imgur.com/SOKur.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41679" PostHistoryTypeId="6" PostId="13693" RevisionGUID="fdd26cfc-2c12-4745-b26b-7f3a2c492c3e" CreationDate="2023-09-06T21:05:05.343" UserId="20494" Comment="edited tags" Text="|c++|computational-geometry|algorithm|mesh|half-edge|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41680" PostHistoryTypeId="6" PostId="13693" RevisionGUID="0a9d64f1-9a3f-4743-886b-dacab868c661" CreationDate="2023-09-06T21:05:23.903" UserId="20494" Comment="edited tags" Text="|c++|computational-geometry|algorithm|geometry|half-edge|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41681" PostHistoryTypeId="2" PostId="13694" RevisionGUID="d4dad0e1-3c7c-4ed2-a3c4-529ae5b89276" CreationDate="2023-09-06T21:41:09.917" UserId="20466" Text="I don't quite get what you mean by voxel, but here you go. Please let me know if you need something special.&#xD;&#xA;   &#xD;&#xA; &#xD;&#xA;&#xD;&#xA;    def voxelize(point_cloud, voxel_size):&#xD;&#xA;            &quot;&quot;&quot;&#xD;&#xA;            Voxelize an Open3D point cloud.&#xD;&#xA;        &#xD;&#xA;            Parameters:&#xD;&#xA;            - point_cloud (open3d.geometry.PointCloud): Input point cloud.&#xD;&#xA;            - voxel_size (float): Voxel size for downsampling.&#xD;&#xA;        &#xD;&#xA;            &quot;&quot;&quot;&#xD;&#xA;        &#xD;&#xA;            points_np = np.asarray(point_cloud.points)&#xD;&#xA;        &#xD;&#xA;            min_bound = np.min(points_np, axis=0)&#xD;&#xA;            max_bound = np.max(points_np, axis=0)&#xD;&#xA;        &#xD;&#xA;            voxel_counts = np.ceil((max_bound - min_bound) / voxel_size).astype(int)&#xD;&#xA;        &#xD;&#xA;            voxel_indices = np.floor((points_np - min_bound) / voxel_size).astype(int)&#xD;&#xA;        &#xD;&#xA;            packed_indices = voxel_indices[:, 0] + voxel_indices[:, 1] * voxel_counts[0] + voxel_indices[:, 2] * voxel_counts[&#xD;&#xA;                0] * voxel_counts[1]&#xD;&#xA;        &#xD;&#xA;            voxel_dict = {}&#xD;&#xA;            voxel_to_point_index_dict = {}&#xD;&#xA;            for i, index in enumerate(packed_indices):&#xD;&#xA;                if index in voxel_dict:&#xD;&#xA;                    voxel_dict[index].append(points_np[i])&#xD;&#xA;                    voxel_to_point_index_dict[index].append(i)&#xD;&#xA;                else:&#xD;&#xA;                    voxel_dict[index] = [points_np[i]]&#xD;&#xA;                    voxel_to_point_index_dict[index] = [i]&#xD;&#xA;        return voxel_dict, voxel_to_point_index_dict&#xD;&#xA;&#xD;&#xA;This function simply puts points to voxels, hash maps `voxel_dict` and `voxel_to_point_index_dict` should provide you two way access." ContentLicense="CC BY-SA 4.0" />
  <row Id="41683" PostHistoryTypeId="2" PostId="13695" RevisionGUID="12a5a4ef-a9c3-4381-8f3e-2d08303886e5" CreationDate="2023-09-07T07:51:16.507" UserId="7724" Text="Assuming that all blue half edges have their *twin, next and prev* correctly set &#xD;&#xA;and &#xD;&#xA;assuming that all blue half edges have their purple *twin* assigned.&#xD;&#xA;&#xD;&#xA;Then assigning the *next* to the red half edge boils down to:&#xD;&#xA;&#xD;&#xA;    runner = red&#xD;&#xA;    while(runner-&gt;twin-&gt;prev) &#xD;&#xA;       runner = runner-&gt;twin-&gt;prev&#xD;&#xA;    &#xD;&#xA;    runner-&gt;twin-&gt;prev = red&#xD;&#xA;    (red-&gt;next = runner-&gt;twin)&#xD;&#xA;&#xD;&#xA;While building the mesh keep a list of all half edges which do not have a *twin*. Then when finished processing all faces create a new half edges for all half edges which have no twin (these are the purple edges). Then afterwards run this procedure.&#xD;&#xA;    &#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41685" PostHistoryTypeId="2" PostId="13696" RevisionGUID="ff5df6d9-0621-40f7-bb4d-5fef31d99e35" CreationDate="2023-09-07T11:11:29.620" UserId="7008" Text="I am trying to setup a buffer that contains material parameters. &#xD;&#xA;The problem is that I have to support a large number of materials, that may differ drastically in number of parameters, e.g. there might be an entry with two uints and then an entry with five floats.&#xD;&#xA;&#xD;&#xA;Since I assume using one buffer per material is bad (due to the number of layouts bindings I'd have to use) I wanted to tightly pack the material parameters into a single byte buffer and readout from the shader with a known offset to the material for the hit geometry.&#xD;&#xA;&#xD;&#xA;While I have basically set up the buffer (though apperantly the smallest chunks I am allowed to use are 4 bytes), I have trouble actually reading out of this buffer in GLSL. Given a simple struct for one material:&#xD;&#xA;&#xD;&#xA;    struct BlinnPhongParams&#xD;&#xA;    {&#xD;&#xA;        vec3 diffuse;&#xD;&#xA;        vec3 specular;&#xD;&#xA;        float specIntensity;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And the material buffer:&#xD;&#xA;&#xD;&#xA;    layout(binding = 123, set = 0) readonly buffer MaterialParamsBuffer&#xD;&#xA;    {&#xD;&#xA;        uint[] data;&#xD;&#xA;    }uMaterialParamsBuffer;&#xD;&#xA;&#xD;&#xA;Currently I am reading every member from the buffer individually:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        BlinnPhongParams bpParams = BlinnPhongParams(&#xD;&#xA;		    //DiffuseCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+1]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+2])),&#xD;&#xA;		    //SpecularCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+3]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+4]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+5])),&#xD;&#xA;		    //SpecIntensity&#xD;&#xA;		    uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+6])&#xD;&#xA;        );&#xD;&#xA;        return bpParams;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I would like to make reading from this buffer as easy as possible, ideally just say &quot;at this offset, I have a struct that looks like this&quot;, e.g. I would like to have something like this:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        // here is the problem&#xD;&#xA;        BlinnPhongParams params = BlinnPhongParams(&amp;uMaterialParamsBuffer.data[offset]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41687" PostHistoryTypeId="1" PostId="13696" RevisionGUID="ff5df6d9-0621-40f7-bb4d-5fef31d99e35" CreationDate="2023-09-07T11:11:29.620" UserId="7008" Text="Is it possible to read arbitrary data at arbitrary array offset in glsl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41688" PostHistoryTypeId="3" PostId="13696" RevisionGUID="ff5df6d9-0621-40f7-bb4d-5fef31d99e35" CreationDate="2023-09-07T11:11:29.620" UserId="7008" Text="|glsl|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41692" PostHistoryTypeId="5" PostId="13696" RevisionGUID="3767939b-9c00-4aab-a699-e78606b67265" CreationDate="2023-09-07T12:37:55.220" UserId="7008" Comment="added info about constraints" Text="***TL;DR***&#xD;&#xA;&#xD;&#xA;I have several shader files, all accessing the same material buffer of arbitrary data. All materials have an arbitrary layout, e.g. one might be a float, one might contain two vec3s and a float.&#xD;&#xA;Can I access a buffer (i.e. an array of uint type) with just an offset and read out a struct without having to read every member of the struct individually?&#xD;&#xA;&#xD;&#xA;***Long explanation***&#xD;&#xA;&#xD;&#xA;I am trying to setup a buffer that contains material parameters. &#xD;&#xA;The problem is that I have to support a large number of materials, that may differ drastically in number of parameters, e.g. there might be an entry with two uints and then an entry with five floats.&#xD;&#xA;&#xD;&#xA;Since I assume using one buffer per material is bad (due to the number of layouts bindings I'd have to use) I wanted to tightly pack the material parameters into a single byte buffer and readout from the shader with a known offset to the material for the hit geometry.&#xD;&#xA;I have a shader file per material, so no material is aware of other material structs - it just knows the offset into the array for its own data.&#xD;&#xA;&#xD;&#xA;While I have basically set up the buffer (though apperantly the smallest chunks I am allowed to use are 4 bytes), I have trouble actually reading out of this buffer in GLSL. Given a simple struct for one material:&#xD;&#xA;&#xD;&#xA;    struct BlinnPhongParams&#xD;&#xA;    {&#xD;&#xA;        vec3 diffuse;&#xD;&#xA;        vec3 specular;&#xD;&#xA;        float specIntensity;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And the material buffer:&#xD;&#xA;&#xD;&#xA;    layout(binding = 123, set = 0) readonly buffer MaterialParamsBuffer&#xD;&#xA;    {&#xD;&#xA;        uint[] data;&#xD;&#xA;    }uMaterialParamsBuffer;&#xD;&#xA;&#xD;&#xA;Currently I am reading every member from the buffer individually:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        BlinnPhongParams bpParams = BlinnPhongParams(&#xD;&#xA;		    //DiffuseCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+1]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+2])),&#xD;&#xA;		    //SpecularCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+3]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+4]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+5])),&#xD;&#xA;		    //SpecIntensity&#xD;&#xA;		    uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+6])&#xD;&#xA;        );&#xD;&#xA;        return bpParams;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I would like to make reading from this buffer as easy as possible, ideally just say &quot;at this offset, I have a struct that looks like this&quot;, e.g. I would like to have something like this:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        // here is the problem&#xD;&#xA;        BlinnPhongParams params = BlinnPhongParams(&amp;uMaterialParamsBuffer.data[offset]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41697" PostHistoryTypeId="2" PostId="13698" RevisionGUID="bf20e768-7830-408d-bcac-afe1fdacf0ae" CreationDate="2023-09-07T13:51:21.087" UserId="20486" Text="I was trying to find examples of GPUs with more than 3 queue families to see what edge cases programmatic selection of compute and transfer queues might encounter.&#xD;&#xA;&#xD;&#xA;[This card](https://vulkan.gpuinfo.org/displayreport.php?id=23434#queuefamilies) has six. Two of the extra ones make sense: they look to be specialized for video codec use. But the last queue family is exactly the same as the other &quot;transfer&quot; type family, except with one queue rather than two. Does anyone know the reason for this, or what it means?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41699" PostHistoryTypeId="1" PostId="13698" RevisionGUID="bf20e768-7830-408d-bcac-afe1fdacf0ae" CreationDate="2023-09-07T13:51:21.087" UserId="20486" Text="Can Vulkan Queue Families be separate but identical?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41700" PostHistoryTypeId="3" PostId="13698" RevisionGUID="bf20e768-7830-408d-bcac-afe1fdacf0ae" CreationDate="2023-09-07T13:51:21.087" UserId="20486" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41701" PostHistoryTypeId="2" PostId="13699" RevisionGUID="44f6e69c-8a2e-4b6d-9947-58e81f067e3c" CreationDate="2023-09-07T15:26:54.357" UserId="7952" Text="Some video cards report having multiple transfer queues. This usually correlates directly to hardware. In Vulkan this allows software devs to create addition queues which can be used as needed.&#xD;&#xA;&#xD;&#xA;A specialized transfer queue is not the same as a generalized graphics/transfer/compute queue that a lot of cards have, it allows data to be transferred independently of what's going on in the &quot;generic&quot; queue.&#xD;&#xA;&#xD;&#xA;So on the one hand graphics commands can be queued up on the graphics queue and at the same time another thread can be queueing data on the hardware transfer queue. Graphics commands can still make forward progress while transfers may be stalled out waiting for data.&#xD;&#xA;&#xD;&#xA;At the end of the day this means cards may report more then 1 transfer queue.&#xD;&#xA;&#xD;&#xA;The same can be said about compute queues. In this case the card manufacturer usually reports something like &quot;asynchronous compute&quot; meaning there is a compute queue that can run at the same time graphics commands are being queue." ContentLicense="CC BY-SA 4.0" />
  <row Id="41703" PostHistoryTypeId="50" PostId="13400" RevisionGUID="53804925-b8c0-4066-a6bb-7a8f5510558b" CreationDate="2023-09-07T19:06:40.810" UserId="-1" />
  <row Id="41704" PostHistoryTypeId="2" PostId="13700" RevisionGUID="696d6591-53a9-44a2-8f88-c2d710de98be" CreationDate="2023-09-08T02:53:13.680" UserId="20501" Text="We can use ARcore to create custom textures and 3D models for Augmented Faces, like the augmentation of a Fox ears. But aside from augmenting 3D objects, can we &quot;transform&quot; facemesh, for instance to make a filter that makes eyes smaller or nose bigger and change the whole face? If so, how? &#xD;&#xA;&#xD;&#xA;It doesn't have to be ARcore, any other free SDK would be fine.&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;Collection&lt;AugmentedFace&gt; faces = session.getAllTrackables(AugmentedFace.class);&#xD;&#xA;//....&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  if (face.getTrackingState() == TrackingState.TRACKING) {&#xD;&#xA;&#xD;&#xA;    // UVs and indices can be cached as they do not change during the session.&#xD;&#xA;&#xD;&#xA;    FloatBuffer uvs = face.getMeshTextureCoordinates();&#xD;&#xA;&#xD;&#xA;    ShortBuffer indices = face.getMeshTriangleIndices();&#xD;&#xA;&#xD;&#xA;    // Center and region poses, mesh vertices, and normals are updated each frame.&#xD;&#xA;&#xD;&#xA;    Pose facePose = face.getCenterPose();&#xD;&#xA;&#xD;&#xA;    FloatBuffer faceVertices = face.getMeshVertices();&#xD;&#xA;&#xD;&#xA;    FloatBuffer faceNormals = face.getMeshNormals();&#xD;&#xA;&#xD;&#xA;    // Render the face using these values with OpenGL.&#xD;&#xA;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;[![face transformation](https://i.stack.imgur.com/sa0fk.jpg)](https://i.stack.imgur.com/sa0fkm.jpg)&#xD;&#xA;&#xD;&#xA;I tried the Fox ear example to augment a 3D model on the face. But not sure how to change the actual face like in the image." ContentLicense="CC BY-SA 4.0" />
  <row Id="41706" PostHistoryTypeId="1" PostId="13700" RevisionGUID="696d6591-53a9-44a2-8f88-c2d710de98be" CreationDate="2023-09-08T02:53:13.680" UserId="20501" Text="How to transform face mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41707" PostHistoryTypeId="3" PostId="13700" RevisionGUID="696d6591-53a9-44a2-8f88-c2d710de98be" CreationDate="2023-09-08T02:53:13.680" UserId="20501" Text="|3d|texture|mesh|model|3dtexture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41708" PostHistoryTypeId="5" PostId="13696" RevisionGUID="84abf343-a329-4d3c-ae79-c2c9ee5bcfb7" CreationDate="2023-09-08T06:31:10.257" UserId="7008" Comment="Added Vulkan as C++ side API" Text="***TL;DR***&#xD;&#xA;&#xD;&#xA;In a Vulkan / GLSL program, I have several shader files, all accessing the same material buffer of arbitrary data. All materials have an arbitrary layout, e.g. one might be a float, one might contain two vec3s and a float.&#xD;&#xA;Can I access a buffer (i.e. an array of uint type) with just an offset and read out a struct without having to read every member of the struct individually?&#xD;&#xA;&#xD;&#xA;***Long explanation***&#xD;&#xA;&#xD;&#xA;I am trying to setup a buffer that contains material parameters. &#xD;&#xA;The problem is that I have to support a large number of materials, that may differ drastically in number of parameters, e.g. there might be an entry with two uints and then an entry with five floats.&#xD;&#xA;&#xD;&#xA;Since I assume using one buffer per material is bad (due to the number of layouts bindings I'd have to use) I wanted to tightly pack the material parameters into a single byte buffer and readout from the shader with a known offset to the material for the hit geometry.&#xD;&#xA;I have a shader file per material, so no material is aware of other material structs - it just knows the offset into the array for its own data.&#xD;&#xA;&#xD;&#xA;While I have basically set up the buffer (though apperantly the smallest chunks I am allowed to use are 4 bytes), I have trouble actually reading out of this buffer in GLSL. Given a simple struct for one material:&#xD;&#xA;&#xD;&#xA;    struct BlinnPhongParams&#xD;&#xA;    {&#xD;&#xA;        vec3 diffuse;&#xD;&#xA;        vec3 specular;&#xD;&#xA;        float specIntensity;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And the material buffer:&#xD;&#xA;&#xD;&#xA;    layout(binding = 123, set = 0) readonly buffer MaterialParamsBuffer&#xD;&#xA;    {&#xD;&#xA;        uint[] data;&#xD;&#xA;    }uMaterialParamsBuffer;&#xD;&#xA;&#xD;&#xA;Currently I am reading every member from the buffer individually:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        BlinnPhongParams bpParams = BlinnPhongParams(&#xD;&#xA;		    //DiffuseCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+1]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+2])),&#xD;&#xA;		    //SpecularCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+3]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+4]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+5])),&#xD;&#xA;		    //SpecIntensity&#xD;&#xA;		    uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+6])&#xD;&#xA;        );&#xD;&#xA;        return bpParams;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I would like to make reading from this buffer as easy as possible, ideally just say &quot;at this offset, I have a struct that looks like this&quot;, e.g. I would like to have something like this:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        // here is the problem&#xD;&#xA;        BlinnPhongParams params = BlinnPhongParams(&amp;uMaterialParamsBuffer.data[offset]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41709" PostHistoryTypeId="6" PostId="13696" RevisionGUID="84abf343-a329-4d3c-ae79-c2c9ee5bcfb7" CreationDate="2023-09-08T06:31:10.257" UserId="7008" Comment="Added Vulkan as C++ side API" Text="|glsl|vulkan|buffers|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41710" PostHistoryTypeId="5" PostId="13404" RevisionGUID="1a569f04-75b6-4af2-849c-ffbb91bea5f1" CreationDate="2023-09-08T07:11:25.737" UserDisplayName="user1703" Comment="added 88 characters in body" Text="I am not aware of a canonical way to achieve this (nor even of any article on the topic).&#xD;&#xA;&#xD;&#xA;What you can try is to enforce the same &quot;travel speed&quot; $\dfrac{ds}{dt}$ where two cubic arcs meet. You know the values of $t,s$ at these points (though $s$ must be obtained by numerical integration), and you want to specify the values of the speeds, i.e. the derivatives. Considering the two endpoints of a cubic arc, that gives you four constraints that can be satisfied by Hermite interpolation in the $t$ domain.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Caution: the figure does not show the spline; it is a graph of the reparameterization function.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aeTve.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41711" PostHistoryTypeId="2" PostId="13701" RevisionGUID="42382877-5d3e-4e50-8313-5a54b5b3dc48" CreationDate="2023-09-08T08:30:15.637" UserId="10096" Text="Assume your spline is given as a sequence of cubic polynomial segments defined through their endpoints $p_{i}^0, p_{i}^1$ and derivatives at those $d_{i}^0,d_{i}^1$ for $1\leq i \leq n$. That is, you can parametrize each piece as the following cubic polynomial curve for $t\in [0,1]$:&#xD;&#xA;$$u_i(t) = (2t^3 - 3t^2 +1) p_{i}^0+ (t^3 - 2t^2+t) d_{i}^0 + (-2t^3 + 3t^2) p_{i}^1 + (t^3 - t^2) d_{i}^1.$$&#xD;&#xA;$G_1$ means that the endpoints between two subsequent segments coincide $p_{i}^1=p_{i+1}^0$ (i.e. the spline is $C_0$), and that the derivatives at the inner nodes are parallel $\exists \kappa_i\ne 0, d_{i}^1 = \kappa_i d_{i+1}^0$. Finally, the points $p_{1}^0$, $p_{n}^1$, and the derivatives $d_{1}^0$, $d_{n}^1$, can be set as unrelated unless you have a looping curve. To turn this into a $C_1$ curve you need to make the derivatives equal. There are however infinitely many ways to do so, and none of those are considered canonical as far as I am aware. Let $f$ be the new tangents, some variants I can suggest are: use a linear combination of both with a fixed global parameter $\theta\in[0,1]$: $f_i^{1} = f_{i+1}^0 = \theta d_i^1 + (1-\theta)d_{i+1}^0$, e.g. you could take the aberage by setting $\theta = 1/2$. Another option would be to compute the derivative lengths that make the curve as close as possible to" ContentLicense="CC BY-SA 4.0" />
  <row Id="41713" PostHistoryTypeId="5" PostId="13701" RevisionGUID="750df95f-cb79-42d8-bb6d-b224d89985f2" CreationDate="2023-09-08T08:38:54.647" UserId="10096" Comment="added 319 characters in body" Text="Assume your spline is given as a sequence of cubic polynomial segments defined through their endpoints $p_{i}^0, p_{i}^1$ and derivatives at those $d_{i}^0,d_{i}^1$ for $1\leq i \leq n$. That is, you can parametrize each piece as the following cubic polynomial curve for $t\in [0,1]$:&#xD;&#xA;$$u_i(t) = (2t^3 - 3t^2 +1) p_{i}^0+ (t^3 - 2t^2+t) d_{i}^0 + (-2t^3 + 3t^2) p_{i}^1 + (t^3 - t^2) d_{i}^1,$$&#xD;&#xA;and you can parametrize the whole spline as:&#xD;&#xA;$$u(t) = u_i(t-(i-1)), \quad t \in [i-1, i].$$&#xD;&#xA;$G_1$ means that the endpoints between two subsequent segments coincide $p_{i}^1=p_{i+1}^0$ (i.e. the spline is $C_0$), and that the derivatives at the inner nodes are parallel $\exists \kappa_i\ne 0, d_{i}^1 = \kappa_i d_{i+1}^0$. Finally, the points $p_{1}^0$, $p_{n}^1$, and the derivatives $d_{1}^0$, $d_{n}^1$, can be set as unrelated unless you have a looping curve. To turn this into a $C_1$ curve you need to make the derivatives equal. There are however infinitely many ways to do so, and none of those are considered canonical as far as I am aware. Let $f$ be the new tangents, some variants I can suggest are: use a linear combination of both with a fixed global parameter $\theta\in[0,1]$: $f_i^{1} = f_{i+1}^0 = \theta d_i^1 + (1-\theta)d_{i+1}^0$, e.g. you could take the average by setting $\theta = 1/2$. Another option would be to compute the derivative lengths that make the spline as close as possible to a $C_2$ spline. One way to formulate something like this is to find the spline $u$ that minimizes the squared gradient magnitude $\int_{0}^{n} \|u'(t)\|^2 \, dt$ under the constraints that $f_{i}^1=f_{i+1}^0 \propto d_i^1$." ContentLicense="CC BY-SA 4.0" />
  <row Id="41714" PostHistoryTypeId="5" PostId="13701" RevisionGUID="6af96bf5-f36f-4539-89ef-1aedb249bd0f" CreationDate="2023-09-08T08:46:03.073" UserId="10096" Comment="added 319 characters in body" Text="Assume your spline is given as a sequence of cubic polynomial segments defined through their endpoints $p_{i}^0, p_{i}^1$ and derivatives at those $d_{i}^0,d_{i}^1$ for $1\leq i \leq n$. That is, you can parametrize each piece as the following cubic polynomial curve for $t\in [0,1]$:&#xD;&#xA;$$u_i(t) = (2t^3 - 3t^2 +1) p_{i}^0+ (t^3 - 2t^2+t) d_{i}^0 + (-2t^3 + 3t^2) p_{i}^1 + (t^3 - t^2) d_{i}^1,$$&#xD;&#xA;and you can parametrize the whole spline as:&#xD;&#xA;$$u(t) = u_i(t-(i-1)), \quad t \in [i-1, i].$$&#xD;&#xA;$G_1$ means that the endpoints between two subsequent segments coincide $p_{i}^1=p_{i+1}^0$ (i.e. the spline is $C_0$), and that the derivatives at the inner nodes are parallel $\exists \kappa_i\ne 0, d_{i}^1 = \kappa_i d_{i+1}^0$. Finally, the points $p_{1}^0$, $p_{n}^1$, and the derivatives $d_{1}^0$, $d_{n}^1$, can be set as unrelated unless you have a looping curve. To turn this into a $C_1$ curve you need to make the derivatives equal. There are however infinitely many ways to do so, and none of those are considered canonical as far as I am aware. Let $f$ be the new tangents, some variants I can suggest are: use a linear combination of both with a fixed global parameter $\theta\in[0,1]$: $f_i^{1} = f_{i+1}^0 = \theta d_i^1 + (1-\theta)d_{i+1}^0$, e.g. you could take the average by setting $\theta = 1/2$. Another option would be to compute the derivative lengths that make the spline as close as possible to a $C_2$ spline. One way to formulate something like this is to find the spline $u$ that minimizes the squared gradient magnitude $\int_{0}^{n} \|u'(t)\|^2 \, dt$ under the constraints that $f_{i}^1=f_{i+1}^0 \propto d_i^1$. You can split the integral as a sum of the integrals over all segments, then you can take the derivative of those, take the squared magnitude, and then integrate. Taking into account the constraints this will be a function only of the lengths of the tangents, you can then take the derivatives w.r.t. those and set them equal to zero to get a system for the solution. I believe the system you will get is linear, so this shouldn't be too hard to solve." ContentLicense="CC BY-SA 4.0" />
  <row Id="41715" PostHistoryTypeId="5" PostId="13701" RevisionGUID="621b0b62-537e-440d-b3e5-46f872669dcc" CreationDate="2023-09-08T09:06:36.730" UserId="10096" Comment="added 126 characters in body" Text="Assume your spline is given as a sequence of cubic polynomial segments defined through their endpoints $p_{i}^0, p_{i}^1$ and derivatives at those $d_{i}^0,d_{i}^1$ for $1\leq i \leq n$. That is, you can parametrize each piece as the following cubic polynomial curve for $t\in [0,1]$:&#xD;&#xA;$$u_i(t) = (2t^3 - 3t^2 +1) p_{i}^0+ (t^3 - 2t^2+t) d_{i}^0 + (-2t^3 + 3t^2) p_{i}^1 + (t^3 - t^2) d_{i}^1,$$&#xD;&#xA;and you can parametrize the whole spline as:&#xD;&#xA;$$u(t) = u_i(t-(i-1)), \quad t \in [i-1, i].$$&#xD;&#xA;$G_1$ means that the endpoints between two subsequent segments coincide $p_{i}^1=p_{i+1}^0$ (i.e. the spline is $C_0$), and that the derivatives at the inner nodes are parallel $\exists \kappa_i\ne 0, d_{i}^1 = \kappa_i d_{i+1}^0$. Finally, the points $p_{1}^0$, $p_{n}^1$, and the derivatives $d_{1}^0$, $d_{n}^1$, can be set as unrelated unless you have a looping curve. To turn this into a $C_1$ curve you need to make the derivatives equal. There are however infinitely many ways to do so, and none of those are considered canonical as far as I am aware. Let $f$ be the new tangents, some variants I can suggest are: use a linear combination of both with a fixed global parameter $\theta\in[0,1]$: $f_i^{1} = f_{i+1}^0 = \theta d_i^1 + (1-\theta)d_{i+1}^0$, e.g. you could take the average by setting $\theta = 1/2$. Another option would be to compute the derivative lengths that make the spline as close as possible to a $C_2$ spline. One way to formulate something like this is to find the spline $u$ that minimizes the squared gradient magnitude $\int_{0}^{n} \|u'(t)\|^2 \, dt$ under the constraints that $f_{i}^1=f_{i+1}^0 \propto d_i^1$. You can split the integral as a sum of the integrals over all segments, then you can take the derivative of those, take the squared magnitude, and then integrate. Taking into account the constraints this will be a function only of the lengths of the tangents, you can then take the derivatives w.r.t. those and set them equal to zero to get a system for the solution. I believe the system you will get is linear, so this shouldn't be too hard to solve.&#xD;&#xA;&#xD;&#xA;Edit: The way I wrote this corresponds to a uniform parametrization, you can make this nonuniform with some modifications." ContentLicense="CC BY-SA 4.0" />
  <row Id="41716" PostHistoryTypeId="2" PostId="13702" RevisionGUID="3b54a5c8-cbaa-4252-9306-09e2eb07cdc1" CreationDate="2023-09-08T12:12:59.940" UserId="7952" Text="&#xD;&#xA;The shaders themselves have the structure memory layout in them and indexing into the array is essentially `(sizeof(material)+alignment) * offset` So what the listed pseudocode is already doing is pretty close to what is needed to index directly. The `sizeof(material)` would also need to be carefully computed since data alignment inside a struct follows the buffer type layout rules. For example the two vec3's actually align to vec4 boundaries. So internally at least 8 bytes are lost for alignment. This complicates writing the data since it is up to the program to place the data at the correct offset for both the structure alignment and the internal alignment, which is basically identical to what the shader is going to do to access it. For a vec3 25% of the memory is being lost to alignment.&#xD;&#xA;&#xD;&#xA;As an example the listed struct layout would look something like the following in C++: (note that I am doing this from memory so please don't write these numbers in stone)&#xD;&#xA;&#xD;&#xA;    struct phong {&#xD;&#xA;       vec3 diffuse; float alignment;&#xD;&#xA;       vec3 specular; float alignment2;&#xD;&#xA;       int intensity;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;Where the actual size of the struct would add another 12 bytes to the end of the `int` so that `sizeof(phong) == 48` instead of the expected `28`.&#xD;&#xA;&#xD;&#xA;The unusable memory issue can be overcome with careful design of materials, like folding the specular intensity into the specular color to align it on a vec4 boundary, etc.&#xD;&#xA;&#xD;&#xA;So this is all doable but automating it so that the programmer doesn't have to hand tune every shader is more challenging." ContentLicense="CC BY-SA 4.0" />
  <row Id="41718" PostHistoryTypeId="50" PostId="13618" RevisionGUID="1b2d3ed5-467d-4270-891a-6236cc1756dc" CreationDate="2023-09-08T13:05:25.657" UserId="-1" />
  <row Id="41719" PostHistoryTypeId="5" PostId="13696" RevisionGUID="36fd0cdf-2716-4b48-9ead-3c793806af6b" CreationDate="2023-09-08T13:33:03.130" UserId="7008" Comment="added more explanations of the problem" Text="***TL;DR***&#xD;&#xA;&#xD;&#xA;In a Vulkan / GLSL program, I have several shader files, all accessing the same material buffer of arbitrary data. All materials have an arbitrary layout, e.g. one might be a float, one might contain two vec3s and a float.&#xD;&#xA;Can I access a buffer (i.e. an array of uint type) with just an offset and read out a struct without having to read every member of the struct individually? I am aware of not being able to read a vec3 from a buffer as just 3 values, but that is not my problem. Just assume I only read good data types that don't waste space.&#xD;&#xA;&#xD;&#xA;See in the image, I want to access at the given green position with just knowing the size of the struct that will follow at that position.&#xD;&#xA;&#xD;&#xA;[![Image of buffer data and where to access it][1]][1]&#xD;&#xA;&#xD;&#xA;In C++ it would be something like this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;uint32_t* buffer; //assume this has all the data in it&#xD;&#xA;struct mat2&#xD;&#xA;{&#xD;&#xA;    glm::vec3 data1;&#xD;&#xA;    float data2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//the following line is what I try to achieve&#xD;&#xA;mat2 matData = *((mat2)(buffer+offset);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;***Long explanation***&#xD;&#xA;&#xD;&#xA;I am trying to setup a buffer that contains material parameters. &#xD;&#xA;The problem is that I have to support a large number of materials, that may differ drastically in number of parameters, e.g. there might be an entry with two uints and then an entry with five floats.&#xD;&#xA;&#xD;&#xA;Since I assume using one buffer per material is bad (due to the number of layouts bindings I'd have to use) I wanted to tightly pack the material parameters into a single byte buffer and readout from the shader with a known offset to the material for the hit geometry.&#xD;&#xA;I have a shader file per material, so no material is aware of other material structs - it just knows the offset into the array for its own data.&#xD;&#xA;&#xD;&#xA;While I have basically set up the buffer (though apperantly the smallest chunks I am allowed to use are 4 bytes), I have trouble actually reading out of this buffer in GLSL. Given a simple struct for one material:&#xD;&#xA;&#xD;&#xA;    struct BlinnPhongParams&#xD;&#xA;    {&#xD;&#xA;        vec3 diffuse;&#xD;&#xA;        vec3 specular;&#xD;&#xA;        float specIntensity;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And the material buffer:&#xD;&#xA;&#xD;&#xA;    layout(binding = 123, set = 0) readonly buffer MaterialParamsBuffer&#xD;&#xA;    {&#xD;&#xA;        uint[] data;&#xD;&#xA;    }uMaterialParamsBuffer;&#xD;&#xA;&#xD;&#xA;Currently I am reading every member from the buffer individually:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        BlinnPhongParams bpParams = BlinnPhongParams(&#xD;&#xA;		    //DiffuseCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+1]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+2])),&#xD;&#xA;		    //SpecularCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+3]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+4]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+5])),&#xD;&#xA;		    //SpecIntensity&#xD;&#xA;		    uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+6])&#xD;&#xA;        );&#xD;&#xA;        return bpParams;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I would like to make reading from this buffer as easy as possible, ideally just say &quot;at this offset, I have a struct that looks like this&quot;, e.g. I would like to have something like this:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        // here is the problem&#xD;&#xA;        BlinnPhongParams params = BlinnPhongParams(&amp;uMaterialParamsBuffer.data[offset]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this possible?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/27ZwK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41720" PostHistoryTypeId="5" PostId="13699" RevisionGUID="0abd8f6d-4b5a-44f2-84d7-5d7a5b86791c" CreationDate="2023-09-08T13:38:29.017" UserId="7952" Comment="tweaked the wording to clarify the answer" Text="Some video cards report having multiple transfer queues. This usually correlates directly to hardware. In Vulkan this allows software devs to create addition queues which can be used as needed.&#xD;&#xA;&#xD;&#xA;A specialized transfer queue is not the same as a generalized graphics/transfer/compute queue that a lot of cards have, it allows data to be transferred independently of what's going on in the &quot;generic&quot; queue.&#xD;&#xA;&#xD;&#xA;So on the one hand graphics commands can be queued up on the graphics queue and at the same time another thread can be queueing data on the hardware transfer queue. Graphics commands can still make forward progress while transfers may be stalled out waiting for data.&#xD;&#xA;&#xD;&#xA;At the end of the day this means cards may report more then 1 transfer queue family.&#xD;&#xA;&#xD;&#xA;The same can be said about compute queues. In this case the card manufacturer usually reports something like &quot;asynchronous compute&quot; meaning there is a compute queue family that can run at the same time graphics commands are being queued." ContentLicense="CC BY-SA 4.0" />
  <row Id="41721" PostHistoryTypeId="2" PostId="13703" RevisionGUID="d02fcc9c-c799-47aa-81ad-4588e8b6dd3b" CreationDate="2023-09-08T15:19:45.840" UserId="20486" Text="The answer is &quot;Yes, and even for no reason&quot;&#xD;&#xA;&#xD;&#xA;The note in the spec says:&#xD;&#xA;&#xD;&#xA;&quot;The general expectation is that a physical device groups all queues of matching capabilities into a single family. However, while implementations **should** do this, it is possible that a physical device **may** return two separate queue families with the same capabilities.&quot;&#xD;&#xA;&#xD;&#xA;So while this provides no insight into _why_ NVIDIA put two transfer only queue families on this card (and it's possible that it is for a reason which VulkanCapsViewer does not detect,) it is perfectly *legal* for them to do it.&#xD;&#xA;&#xD;&#xA;At the end of the day, I suppose this is because queue families are simply a grouping abstraction, and have no physical or logical consequence: only queues themselves are &quot;real&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="41723" PostHistoryTypeId="2" PostId="13704" RevisionGUID="bbc53b4f-f3a4-4858-89fe-69cb2b5062e5" CreationDate="2023-09-08T21:40:24.940" UserId="20466" Text="I have been using FPFH features quite a lot in global registration and key-point extraction a lot, I also looked [pcl][1] page that *tries* to explain what it is, but fails to give detail to reader in my opinion. I have a general understanding of what it is, but for example I have no idea why it has 33 dims, but not 34? In short, I want to understand in detail. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pcl.readthedocs.io/projects/tutorials/en/latest/fpfh_estimation.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="41725" PostHistoryTypeId="1" PostId="13704" RevisionGUID="bbc53b4f-f3a4-4858-89fe-69cb2b5062e5" CreationDate="2023-09-08T21:40:24.940" UserId="20466" Text="How can I understand the logic of Fast Point Feature Histograms (FPFH) descriptor?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41726" PostHistoryTypeId="3" PostId="13704" RevisionGUID="bbc53b4f-f3a4-4858-89fe-69cb2b5062e5" CreationDate="2023-09-08T21:40:24.940" UserId="20466" Text="|3d|computational-geometry|mesh|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41730" PostHistoryTypeId="2" PostId="13705" RevisionGUID="b31c9d46-2205-475f-b1b9-154cfacdb5dc" CreationDate="2023-09-09T15:20:03.390" UserId="20508" Text="We know that in the RGB system we have three primary colors and each of them has a value from $0$ to $255$ (or $256$ values in total). So all possible colors are $256^{3}=16777216$.&#xD;&#xA;&#xD;&#xA;But in the CMYK system we have four primary colors and each of them has $101$ values (from $0$ to $100$). So in this case all possible colors should be $101^{4}=104060401$ which is far more than all possible colors ib the RGB system.&#xD;&#xA;&#xD;&#xA;So does CMYK system provide more colors? (but of course we can perceive only $16777216$ colors because of our vision which only perceives three primary colors)&#xD;&#xA;&#xD;&#xA;**Also another question**: In RGB system the hexadecimal codes again provide $16777216$ colors; because we have from 00 to FF for each primary color (again 256 possible codes). But for CMYK system the total possible colors differ from $104060401$ when using hex codes. Because the code range is from 00 to 64 (85 total codes) for each primary color and the total number of possible colors is $85^{4}=52200625$ which is again more than the possible colors of RGB system. But why are the number of colors differ in CMYK system when using values and hex codes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41732" PostHistoryTypeId="1" PostId="13705" RevisionGUID="b31c9d46-2205-475f-b1b9-154cfacdb5dc" CreationDate="2023-09-09T15:20:03.390" UserId="20508" Text="Does CMYK values provide more colors than RGB?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41733" PostHistoryTypeId="3" PostId="13705" RevisionGUID="b31c9d46-2205-475f-b1b9-154cfacdb5dc" CreationDate="2023-09-09T15:20:03.390" UserId="20508" Text="|mathematics|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41734" PostHistoryTypeId="5" PostId="13705" RevisionGUID="71785ee0-dec2-4aad-a5f1-f0063b75f02a" CreationDate="2023-09-09T15:27:13.153" UserId="20508" Comment="edited body" Text="We know that in the RGB system we have three primary colors and each of them has a value from $0$ to $255$ (or $256$ values in total). So all possible colors are $256^{3}=16777216$.&#xD;&#xA;&#xD;&#xA;But in the CMYK system we have four primary colors and each of them has $101$ values (from $0$ to $100$). So in this case all possible colors should be $101^{4}=104060401$ which is far more than all possible colors in the RGB system.&#xD;&#xA;&#xD;&#xA;So does CMYK system provide more colors? (but of course we can perceive only $16777216$ colors because of our vision which only perceives three primary colors)&#xD;&#xA;&#xD;&#xA;**Also another question**: In RGB system the hexadecimal codes again provide $16777216$ colors; because we have from 00 to FF for each primary color (again 256 possible codes). But for CMYK system the total possible colors differ from $104060401$ when using hex codes. Because the code range is from 00 to 64 (85 total codes) for each primary color and the total number of possible colors is $85^{4}=52200625$ which is again more than the possible colors of RGB system. But why are the number of colors differ in CMYK system when using values and hex codes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41736" PostHistoryTypeId="50" PostId="5697" RevisionGUID="35755e8e-0234-43fb-91d9-49ff4bb84dc7" CreationDate="2023-09-09T16:04:40.513" UserId="-1" />
  <row Id="41737" PostHistoryTypeId="2" PostId="13706" RevisionGUID="7893df24-b5b2-4fe1-b1f4-13ee7392c305" CreationDate="2023-09-10T15:45:54.823" UserId="445" Text="You are focusing far too much on the number of color codes in common implementations. There is no reason that RGB must have 256 values per component, and no reason that CMYK must have 101 values per component. Within any system, **we can choose to store more bits and therefore discriminate more finely between colors.** And if we don't have enough bits, [dithering](https://en.wikipedia.org/wiki/Dither) is an option.&#xD;&#xA;&#xD;&#xA;The true difference between RGB and CMYK is that they each encode color in a way that suits the limitations of a particular display technology.&#xD;&#xA;&#xD;&#xA;* RGB color representation suits television, computers, and other video displays that are directly emitting colored light. It can represent any color that is some mix of the red, green, and blue primary colors — any color that those displays can present.&#xD;&#xA;&#xD;&#xA;    However, there are still some colors that cannot be displayed by RGB monitors. Not because they are in-between the existing codes, but because they are _outside_ the [gamut](https://en.wikipedia.org/wiki/Gamut) defined by the choice of three primary colors. It's impossible to make a display that emits all possible colors unless each pixel could individually tune the wavelengths of light it emits.&#xD;&#xA;&#xD;&#xA;* CMYK color is used for printing — for putting ink on paper.&#xD;&#xA;    &#xD;&#xA;    The limitation of printing is that the image is formed by light hitting the ink pigments and being absorbed; the color that we see is *everything but* those absorbed colors. But when we make a color that is not a primary color, by the printer spraying or pressing a mixture of those inks onto the paper, _not all of the paper is covered by each one_. The result of this is that a color made by mixed inks will always be a little “muddy”. If you try to make black out of CMY, you will not succeed; you will get a dark brown color instead. Thus, the black (K) additional element is needed, and people designing for print use CMYK so that they are working within the limitations of the technology.&#xD;&#xA;&#xD;&#xA;    Thus, the _gamut_ of CMYK is typically smaller than RGB. If you use RGB to design for printing, you will often be unpleasantly surprised by your colors being less vibrant because the RGB colors you chose cannot be made by CMYK inks.&#xD;&#xA;&#xD;&#xA;You cannot meaningfully compare CMYK and RGB on the basis of the number of distinct colors; it's the gamut that matters — the _boundaries_ of the space of representable colors." ContentLicense="CC BY-SA 4.0" />
  <row Id="41739" PostHistoryTypeId="5" PostId="13706" RevisionGUID="21facaf8-55a6-48eb-b341-533904e49183" CreationDate="2023-09-10T16:17:24.890" UserId="445" Comment="added 52 characters in body" Text="You are focusing far too much on the number of color codes in common implementations. There is no reason that RGB must have 256 values per component, and no reason that CMYK must have 101 values per component. Within any system, **we can choose to store more bits and therefore discriminate more finely between colors.** And if we don't have enough bits, [dithering](https://en.wikipedia.org/wiki/Dither) is an option.&#xD;&#xA;&#xD;&#xA;The true difference between RGB and CMYK is that they each encode color in a way that suits the limitations of a particular display technology.&#xD;&#xA;&#xD;&#xA;* RGB color representation suits television, computers, and other video displays that are directly emitting colored light. It can represent any color that is some mix of the red, green, and blue primary colors — any color that those displays can present.&#xD;&#xA;&#xD;&#xA;    However, there are still some colors that cannot be displayed by RGB monitors. Not because they are in-between the existing codes, but because they are _outside_ the [gamut](https://en.wikipedia.org/wiki/Gamut) defined by the choice of three primary colors. It's impossible to make a display that emits all possible colors unless each pixel could individually tune the wavelengths of light it emits.&#xD;&#xA;&#xD;&#xA;* CMYK color is used for printing — for putting ink on paper.&#xD;&#xA;    &#xD;&#xA;    The limitation of printing is that the image is formed by light hitting the ink pigments and being absorbed; the color that we see is *everything but* those absorbed colors. But when we make a color that is not a primary color, by the printer spraying or pressing a mixture of those inks onto the paper, _not all of the paper is covered by each one_. The result of this is that a color made by mixed inks will always be a little “muddy”. If you try to make black out of CMY, you will not succeed; you will get a dark brown color instead. Thus, the black (K) additional element is needed, and people designing for print use CMYK so that they are working within the limitations of the technology.&#xD;&#xA;&#xD;&#xA;    Thus, the _gamut_ of CMYK is typically smaller than RGB — though both may contain colors the other does not. If you use RGB to design for printing, you will often be unpleasantly surprised by your colors being less vibrant because the RGB colors you chose cannot be made by CMYK inks.&#xD;&#xA;&#xD;&#xA;You cannot meaningfully compare CMYK and RGB on the basis of the number of distinct colors; it's the gamut that matters — the _boundaries_ of the space of representable colors." ContentLicense="CC BY-SA 4.0" />
  <row Id="41740" PostHistoryTypeId="5" PostId="13705" RevisionGUID="4219552f-73b9-4c3e-aafb-bb28671de551" CreationDate="2023-09-10T16:24:02.297" UserId="20508" Comment="added 4 characters in body" Text="We know that in the RGB system we have three primary colors and each of them has a value from $0$ to $255$ (or $256$ values in total). So all possible colors are $256^{3}=16777216$.&#xD;&#xA;&#xD;&#xA;But in the CMYK system we have four primary colors and each of them has $101$ values (from $0$ to $100$). So in this case all possible colors should be $101^{4}=104060401$ which is far more than all possible colors in the RGB system.&#xD;&#xA;&#xD;&#xA;So does CMYK system provide more colors? (but of course we can perceive only $16777216$ colors because of our vision which only perceives three primary colors)&#xD;&#xA;&#xD;&#xA;**Also another question**: In RGB system the hexadecimal codes again provide $16777216$ colors; because we have from 00 to FF for each primary color (again $256$ possible codes). But for CMYK system the total possible colors differ from $104060401$ when using hex codes. Because the code range is from 00 to 64 ($85$ total codes) for each primary color and the total number of possible colors is $85^{4}=52200625$ which is again more than the possible colors of RGB system. But why are the number of colors differ in CMYK system when using values and hex codes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41741" PostHistoryTypeId="5" PostId="13681" RevisionGUID="8412ba48-2ccd-4e55-9f9f-e0cf5ff3e68a" CreationDate="2023-09-10T16:34:21.767" UserId="20471" Comment="added 89 characters in body" Text="TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/KLJiF.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/27LYU.jpg&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41742" PostHistoryTypeId="5" PostId="13681" RevisionGUID="6aa3074d-ecbc-4319-8bb4-8773276263ec" CreationDate="2023-09-10T21:53:42.763" UserId="20471" Comment="added 127 characters in body" Text="TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/KLJiF.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/27LYU.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZEcn4.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration. Fog has been implemented in the 5th figure.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41743" PostHistoryTypeId="2" PostId="13707" RevisionGUID="4feede77-f2e2-43a9-8edf-c8ec4cc9aca6" CreationDate="2023-09-11T01:29:06.403" UserId="20518" Text="I have some graphic drawings of the floors of a hours that I want to display on a web page.  Drawn in GIMP, there are several layers:&#xD;&#xA;&#xD;&#xA;[![house layers][1]][1]&#xD;&#xA;&#xD;&#xA;From bottom to top, the layers are:&#xD;&#xA;&#xD;&#xA;* ground (grass and building outline)&#xD;&#xA;* first floor, with shutters outside the window&#xD;&#xA;* ground copy to cover those shutters&#xD;&#xA;* 67% opaque black &quot;scrim&quot;&#xD;&#xA;* second floor&#xD;&#xA;&#xD;&#xA;If there was no &quot;ground copy&quot; then the shutters from the first floor would be visible when viewing the second floor and, because they're black, not be distinguished as &quot;behind the scrim&quot; and thus on a lower level.  It doesn't look good and sometimes they clash with shutters from second-floor windows.  Hence: Just remove them by copying the ground over them.&#xD;&#xA;&#xD;&#xA;The result, when composited in GIMP is this:&#xD;&#xA;&#xD;&#xA;[![composited image][2]][2]&#xD;&#xA;&#xD;&#xA;For my web page, I want the &quot;ground&quot; level to always exist and just change floor graphics.  The first floor has only &quot;on&quot; or &quot;off&quot; transparency and works fine.  The second floor, with collapses the top 4 layers (including the scrim), ends up like this:&#xD;&#xA;&#xD;&#xA;[![second floor overlay][3]][3]&#xD;&#xA;&#xD;&#xA;You'll note that the &quot;ground cover&quot; is opaque (but dimmed) while the &quot;scrim&quot; is partially (33%) transparent.&#xD;&#xA;&#xD;&#xA;If I composite only that merged overlay with the original &quot;ground&quot; layer in GIMP, I get something identical to the original composited image, which is as you'd expect.&#xD;&#xA;&#xD;&#xA;However, when I place the composited &quot;second floor&quot; layer over the &quot;ground&quot; layer _on my web page_, it doesn't behave the same.  I get this:&#xD;&#xA;&#xD;&#xA;[![web composited result][4]][4]&#xD;&#xA;&#xD;&#xA;You can see that all the opaque areas of the second floor appear correctly but the &quot;ground&quot; behind it is much dimmer, passing maybe 1/2 as much color at a guess.&#xD;&#xA;&#xD;&#xA;There is no CSS.  It's currently just two overlaid images:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&lt;html&gt;&#xD;&#xA;&lt;head&gt;&lt;/head&gt;&#xD;&#xA;&lt;body&gt;&#xD;&#xA;&lt;div style=&quot;position: absolute;&quot;&gt;&lt;img src=&quot;1.webp&quot;&gt;&lt;/div&gt;&#xD;&#xA;&lt;div style=&quot;position: absolute;&quot;&gt;&lt;img src=&quot;2.webp&quot;&gt;&lt;/div&gt;&#xD;&#xA;&lt;/body&gt;&#xD;&#xA;&lt;/html&gt;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;_Can anybody explain why my web browser (Chrome) would composite two graphic layers differently than GIMP?_&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/55Nh2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6AIIB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/61VY6.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/uy5XL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41745" PostHistoryTypeId="1" PostId="13707" RevisionGUID="4feede77-f2e2-43a9-8edf-c8ec4cc9aca6" CreationDate="2023-09-11T01:29:06.403" UserId="20518" Text="How is HTML Transparency Different than GIMP?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41746" PostHistoryTypeId="3" PostId="13707" RevisionGUID="4feede77-f2e2-43a9-8edf-c8ec4cc9aca6" CreationDate="2023-09-11T01:29:06.403" UserId="20518" Text="|transparency|compositing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41747" PostHistoryTypeId="6" PostId="13646" RevisionGUID="6a6a07dc-4f12-424e-b093-192256a404f7" CreationDate="2023-09-11T06:19:10.777" UserId="13095" Comment="Remove pathtracing tag, since it seems to be misleading in the context of compute graphics/rendering" Text="|computational-geometry|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41748" PostHistoryTypeId="5" PostId="13686" RevisionGUID="6e660a94-b038-4722-b5d1-1f2a0af752d0" CreationDate="2023-09-11T06:26:26.173" UserId="445" Comment="list formatting" Text="I'm working on a 2D (pseudo-3D) raycaster which operates on a 2D tile grid.&#xD;&#xA;&#xD;&#xA;For each ray sent out, the screen draws a rectangle with a certain height depending on the distance between the camera and the wall the ray collided with (like Wolfenstein 3D).&#xD;&#xA;&#xD;&#xA;I am now working on drawing texture images and have run into a problem:&#xD;&#xA;&#xD;&#xA;If for example six rays hits a wall segment (tile) then the image which corresponds to this tile should be sliced into six parts. If there was 100 rays then the image needs to have 100 slices.&#xD;&#xA;&#xD;&#xA;However, obviously there exist no image width which can be divided by all numbers.&#xD;&#xA;&#xD;&#xA;How to go about this?&#xD;&#xA;&#xD;&#xA;My current idea is:&#xD;&#xA;&#xD;&#xA;* Load several resolutions of the image texture, for example: (100x100, 200x200, 400x400, 800x800)&#xD;&#xA;&#xD;&#xA;* Identify how many rays has hit wall segment X&#xD;&#xA;&#xD;&#xA;* Identify which image resolution fits best to the scaled height of the rectangle (depending on distance from camera to target). Lower resolution for more distant objects etc.&#xD;&#xA;&#xD;&#xA;* Transform the selected image into the closest resolution which can be divided into a whole number by the amounts of rays which hit the segment&#xD;&#xA;&#xD;&#xA;I believe this could work in principle; however I would hope there is an easier solution which requires less image transforms." ContentLicense="CC BY-SA 4.0" />
  <row Id="41749" PostHistoryTypeId="24" PostId="13686" RevisionGUID="6e660a94-b038-4722-b5d1-1f2a0af752d0" CreationDate="2023-09-11T06:26:26.173" Comment="Proposed by 445 approved by 13095 edit id of 626" ContentLicense="CC BY-SA 4.0" />
  <row Id="41750" PostHistoryTypeId="5" PostId="13707" RevisionGUID="90f8d880-bfd4-43e1-8ccd-aa6b0c9b4e4f" CreationDate="2023-09-11T14:09:17.277" UserId="20518" Comment="Change webp to png since the png allows only straight-alpha but the behavior is unchanged." Text="I have some graphic drawings of the floors of a hours that I want to display on a web page.  Drawn in GIMP, there are several layers:&#xD;&#xA;&#xD;&#xA;[![house layers][1]][1]&#xD;&#xA;&#xD;&#xA;From bottom to top, the layers are:&#xD;&#xA;&#xD;&#xA;* ground (grass and building outline)&#xD;&#xA;* first floor, with shutters outside the window&#xD;&#xA;* ground copy to cover those shutters&#xD;&#xA;* 67% opaque black &quot;scrim&quot;&#xD;&#xA;* second floor&#xD;&#xA;&#xD;&#xA;If there was no &quot;ground copy&quot; then the shutters from the first floor would be visible when viewing the second floor and, because they're black, not be distinguished as &quot;behind the scrim&quot; and thus on a lower level.  It doesn't look good and sometimes they clash with shutters from second-floor windows.  Hence: Just remove them by copying the ground over them.&#xD;&#xA;&#xD;&#xA;The result, when composited in GIMP is this:&#xD;&#xA;&#xD;&#xA;[![composited image][2]][2]&#xD;&#xA;&#xD;&#xA;For my web page, I want the &quot;ground&quot; level to always exist and just change floor graphics.  The first floor has only &quot;on&quot; or &quot;off&quot; transparency and works fine.  The second floor, with collapses the top 4 layers (including the scrim), ends up like this:&#xD;&#xA;&#xD;&#xA;[![second floor overlay][3]][3]&#xD;&#xA;&#xD;&#xA;You'll note that the &quot;ground cover&quot; is opaque (but dimmed) while the &quot;scrim&quot; is partially (33%) transparent.&#xD;&#xA;&#xD;&#xA;If I composite only that merged overlay with the original &quot;ground&quot; layer in GIMP, I get something identical to the original composited image, which is as you'd expect.&#xD;&#xA;&#xD;&#xA;However, when I place the composited &quot;second floor&quot; layer over the &quot;ground&quot; layer _on my web page_, it doesn't behave the same.  I get this:&#xD;&#xA;&#xD;&#xA;[![web composited result][4]][4]&#xD;&#xA;&#xD;&#xA;You can see that all the opaque areas of the second floor appear correctly but the &quot;ground&quot; behind it is much dimmer, passing maybe 1/2 as much color at a guess.&#xD;&#xA;&#xD;&#xA;There is no CSS.  It's currently just two overlaid images:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&lt;html&gt;&#xD;&#xA;&lt;head&gt;&lt;/head&gt;&#xD;&#xA;&lt;body&gt;&#xD;&#xA;&lt;div style=&quot;position: absolute;&quot;&gt;&lt;img src=&quot;1.png&quot;&gt;&lt;/div&gt;&#xD;&#xA;&lt;div style=&quot;position: absolute;&quot;&gt;&lt;img src=&quot;2.png&quot;&gt;&lt;/div&gt;&#xD;&#xA;&lt;/body&gt;&#xD;&#xA;&lt;/html&gt;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;_Can anybody explain why my web browser (Chrome) would composite two graphic layers differently than GIMP?_&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/55Nh2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6AIIB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/61VY6.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/uy5XL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41751" PostHistoryTypeId="5" PostId="13707" RevisionGUID="b7541f02-64a9-419f-aab9-7f36286f0a51" CreationDate="2023-09-11T14:17:41.033" UserId="20518" Comment="Document using &quot;normal&quot; mode in GIMP." Text="I have some graphic drawings of the floors of a hours that I want to display on a web page.  Drawn in GIMP, there are several layers all with &quot;normal&quot; mode:&#xD;&#xA;&#xD;&#xA;[![house layers][1]][1]&#xD;&#xA;&#xD;&#xA;From bottom to top, the layers are:&#xD;&#xA;&#xD;&#xA;* ground (grass and building outline)&#xD;&#xA;* first floor, with shutters outside the window&#xD;&#xA;* ground copy to cover those shutters&#xD;&#xA;* 67% opaque black &quot;scrim&quot;&#xD;&#xA;* second floor&#xD;&#xA;&#xD;&#xA;If there was no &quot;ground copy&quot; then the shutters from the first floor would be visible when viewing the second floor and, because they're black, not be distinguished as &quot;behind the scrim&quot; and thus on a lower level.  It doesn't look good and sometimes they clash with shutters from second-floor windows.  Hence: Just remove them by copying the ground over them.&#xD;&#xA;&#xD;&#xA;The result, when composited in GIMP is this:&#xD;&#xA;&#xD;&#xA;[![composited image][2]][2]&#xD;&#xA;&#xD;&#xA;For my web page, I want the &quot;ground&quot; level to always exist and just change floor graphics.  The first floor has only &quot;on&quot; or &quot;off&quot; transparency and works fine.  The second floor, with collapses the top 4 layers (including the scrim), ends up like this:&#xD;&#xA;&#xD;&#xA;[![second floor overlay][3]][3]&#xD;&#xA;&#xD;&#xA;You'll note that the &quot;ground cover&quot; is opaque (but dimmed) while the &quot;scrim&quot; is partially (33%) transparent.&#xD;&#xA;&#xD;&#xA;If I composite only that merged overlay with the original &quot;ground&quot; layer in GIMP, I get something identical to the original composited image, which is as you'd expect.&#xD;&#xA;&#xD;&#xA;However, when I place the composited &quot;second floor&quot; layer over the &quot;ground&quot; layer _on my web page_, it doesn't behave the same.  I get this:&#xD;&#xA;&#xD;&#xA;[![web composited result][4]][4]&#xD;&#xA;&#xD;&#xA;You can see that all the opaque areas of the second floor appear correctly but the &quot;ground&quot; behind it is much dimmer, passing maybe 1/2 as much color at a guess.&#xD;&#xA;&#xD;&#xA;There is no CSS.  It's currently just two overlaid images:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&lt;html&gt;&#xD;&#xA;&lt;head&gt;&lt;/head&gt;&#xD;&#xA;&lt;body&gt;&#xD;&#xA;&lt;div style=&quot;position: absolute;&quot;&gt;&lt;img src=&quot;1.png&quot;&gt;&lt;/div&gt;&#xD;&#xA;&lt;div style=&quot;position: absolute;&quot;&gt;&lt;img src=&quot;2.png&quot;&gt;&lt;/div&gt;&#xD;&#xA;&lt;/body&gt;&#xD;&#xA;&lt;/html&gt;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;_Can anybody explain why my web browser (Chrome) would composite two graphic layers differently than GIMP?_&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/55Nh2.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/6AIIB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/61VY6.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/uy5XL.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41752" PostHistoryTypeId="4" PostId="13707" RevisionGUID="b7541f02-64a9-419f-aab9-7f36286f0a51" CreationDate="2023-09-11T14:17:41.033" UserId="20518" Comment="Document using &quot;normal&quot; mode in GIMP." Text="How is HTML Alpha-Blending Different than GIMP?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41753" PostHistoryTypeId="2" PostId="13708" RevisionGUID="e5ccb0fa-44d3-4fbf-bf53-93916cb5023c" CreationDate="2023-09-11T14:57:54.170" UserId="20518" Text="I've discovered that GIMP (as of v2.10) has a new set of &quot;default&quot; blending modes which is what I used for creating my images.  If, using the two images, I blend them using &quot;legacy normal&quot; then I get results matching that of web browsers.&#xD;&#xA;&#xD;&#xA;&quot;Default&quot; blending is done in linear light while &quot;legacy&quot; blending is done in gamma-corrected (perceptual) space.&#xD;&#xA;&#xD;&#xA;By altering the blending of all my original layers (at least those with non-binary transparency) to be the &quot;legacy&quot; version and merging into two layers as described in the question, I can then overlay the results using a web browser to get the expected results.&#xD;&#xA;&#xD;&#xA;It seems a &quot;default normal&quot; blending opacity of 67% is equivalent to a &quot;legacy normal&quot; blending opacity of 40% (or at least close enough that I couldn't see any difference visually).&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41768" PostHistoryTypeId="2" PostId="13711" RevisionGUID="8267e696-f210-47bf-adab-da59edc04aae" CreationDate="2023-09-12T05:16:21.130" UserId="7462" Text="In the book [Polygon Mesh Processing][1], there is a section dedicated to fairing. In particular page 59 has this lovely figure:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am specially interested in the rightmost image. According to the text this is done by fin ding the set of values of x such that of $\Delta ^ 3 x = 0$&#xD;&#xA;&#xD;&#xA;The text claims that all that is needed in these cases is to solve &#xD;&#xA;&#xD;&#xA;$$L^3 = 0$$&#xD;&#xA;&#xD;&#xA;Where $L$ is a Laplacian matrix.&#xD;&#xA;&#xD;&#xA;What I am not following is how to construct this Laplacian matrix, in particular, the text mentions that it is simpler to fix 2 rings of vertices for the case where you want the middle figure, so I assume you want to fix 3 rings for the rightmost figure.&#xD;&#xA;&#xD;&#xA;I was hoping someone could explain to me how you actually feed in the coefficients of the fixed vertices into the system.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://staff.ustc.edu.cn/~lgliu/Courses/DGP_2014_autumn-winter/References/Book_Polygon%20Mesh%20Processing.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/nTlAb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41770" PostHistoryTypeId="1" PostId="13711" RevisionGUID="8267e696-f210-47bf-adab-da59edc04aae" CreationDate="2023-09-12T05:16:21.130" UserId="7462" Text="Faring a region of a mesh connecting two curves" ContentLicense="CC BY-SA 4.0" />
  <row Id="41771" PostHistoryTypeId="3" PostId="13711" RevisionGUID="8267e696-f210-47bf-adab-da59edc04aae" CreationDate="2023-09-12T05:16:21.130" UserId="7462" Text="|mathematics|computational-geometry|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41774" PostHistoryTypeId="5" PostId="13711" RevisionGUID="0a453f65-b9df-43ac-bc41-a7930ecdbe30" CreationDate="2023-09-12T08:18:37.133" UserId="7462" Comment="added 1 character in body" Text="In the book [Polygon Mesh Processing][1], there is a section dedicated to fairing. In particular page 59 has this lovely figure:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I am specially interested in the rightmost image. According to the text this is done by fin ding the set of values of x such that of $\Delta ^ 3 x = 0$&#xD;&#xA;&#xD;&#xA;The text claims that all that is needed in these cases is to solve &#xD;&#xA;&#xD;&#xA;$$L^3x = 0$$&#xD;&#xA;&#xD;&#xA;Where $L$ is a Laplacian matrix.&#xD;&#xA;&#xD;&#xA;What I am not following is how to construct this Laplacian matrix, in particular, the text mentions that it is simpler to fix 2 rings of vertices for the case where you want the middle figure, so I assume you want to fix 3 rings for the rightmost figure.&#xD;&#xA;&#xD;&#xA;I was hoping someone could explain to me how you actually feed in the coefficients of the fixed vertices into the system.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://staff.ustc.edu.cn/~lgliu/Courses/DGP_2014_autumn-winter/References/Book_Polygon%20Mesh%20Processing.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/nTlAb.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41776" PostHistoryTypeId="50" PostId="12414" RevisionGUID="96bd70eb-2cd3-4cf8-bc71-a1fac6f2ea40" CreationDate="2023-09-12T11:09:26.123" UserId="-1" />
  <row Id="41777" PostHistoryTypeId="2" PostId="13712" RevisionGUID="478c16fc-7576-4d1f-b0b3-efef7e939831" CreationDate="2023-09-12T16:36:55.337" UserId="20522" Text="I am studying from pbrt-v3 and the rendering equation has just been introduced as&#xD;&#xA;$$&#xD;&#xA;\underbrace{L_\mathrm{o}(\mathrm{p},\omega_\mathrm{o})}_\text{Outgoing radiance }=\underbrace{L_\mathrm{e}(\mathrm{p},\omega_\mathrm{o})}_\text{Emitted Radiance}+\underbrace{\int_{\mathrm{S}^2}f(\mathrm{p},\omega_\mathrm{o},\omega_\mathrm{i})L_\mathrm{i}(\mathrm{p},\omega_\mathrm{i})|\cos(\theta_\mathrm{i})|\mathrm{d}\omega_\mathrm{i}}_\text{Incident radiance from all directions}.&#xD;&#xA;$$&#xD;&#xA;Please bear with me as I have some confusion regarding the integration variable $\omega_\mathrm{i}$. It represents a point on the sphere $\mathrm{S}^2$, which is centred at $\mathrm{p}$, so wouldn't this mean the direction of the incoming light points *away* from $\mathrm{p}$? I took a look a at the [Wikipedia page][1] for the rendering equation and indeed, $\omega_\mathrm{i}$ is stated as the *negative* direction of incoming light.&#xD;&#xA;&#xD;&#xA;I'm wondering why the direction is stated as negative. Perhaps it makes the equation simpler?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41779" PostHistoryTypeId="1" PostId="13712" RevisionGUID="478c16fc-7576-4d1f-b0b3-efef7e939831" CreationDate="2023-09-12T16:36:55.337" UserId="20522" Text="Confusion regarding incident direction in render equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41780" PostHistoryTypeId="3" PostId="13712" RevisionGUID="478c16fc-7576-4d1f-b0b3-efef7e939831" CreationDate="2023-09-12T16:36:55.337" UserId="20522" Text="|mathematics|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41781" PostHistoryTypeId="5" PostId="13712" RevisionGUID="0e1e2815-19fd-4a96-83db-1c4b3e56df1c" CreationDate="2023-09-12T16:42:20.967" UserId="20522" Comment="added 115 characters in body" Text="I am studying from pbrt-v3 and the rendering equation has just been introduced as&#xD;&#xA;$$&#xD;&#xA;\underbrace{L_\mathrm{o}(\mathrm{p},\omega_\mathrm{o})}_\text{Outgoing radiance }=\underbrace{L_\mathrm{e}(\mathrm{p},\omega_\mathrm{o})}_\text{Emitted Radiance}+\underbrace{\int_{\mathrm{S}^2}f(\mathrm{p},\omega_\mathrm{o},\omega_\mathrm{i})L_\mathrm{i}(\mathrm{p},\omega_\mathrm{i})|\cos(\theta_\mathrm{i})|\mathrm{d}\omega_\mathrm{i}}_\text{Incident radiance from all directions}.&#xD;&#xA;$$&#xD;&#xA;Please bear with me as I have some confusion regarding the integration variable $\omega_\mathrm{i}$. It represents a point on the sphere $\mathrm{S}^2$, which is centred at $\mathrm{p}$, so wouldn't this mean the direction of the incoming light points *away* from $\mathrm{p}$? I took a look a at the [Wikipedia page][1] for the rendering equation and indeed, $\omega_\mathrm{i}$ is stated as the *negative* direction of incoming light.&#xD;&#xA;&#xD;&#xA;I'm wondering why the direction is stated as negative. Perhaps it makes the equation simpler? How would the incident radiance function $L_\mathrm{i}(\mathrm{p},\omega_\mathrm{i})$ handle a negative direction?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41782" PostHistoryTypeId="6" PostId="13712" RevisionGUID="bb8e6904-8738-40c0-9a34-f1ef11d4c3a9" CreationDate="2023-09-12T16:55:44.160" UserId="20522" Comment="edited tags" Text="|rendering|mathematics|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41783" PostHistoryTypeId="5" PostId="13681" RevisionGUID="781e9321-9076-47e6-b4ce-a3091df7c7d5" CreationDate="2023-09-13T01:45:18.430" UserId="20471" Comment="added 97 characters in body" Text="TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;Edit: Seems like Henrik Wann Jensen is likely the person who discovered this algorithm first.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/KLJiF.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/27LYU.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZEcn4.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration. Fog has been implemented in the 5th figure.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41784" PostHistoryTypeId="50" PostId="9492" RevisionGUID="6e4a2c5e-169d-4149-a5f6-9d21e6300cfd" CreationDate="2023-09-13T02:09:16.160" UserId="-1" />
  <row Id="41785" PostHistoryTypeId="2" PostId="13713" RevisionGUID="2bf04a96-3b1b-46c8-9fab-f4cf6eef41db" CreationDate="2023-09-13T09:23:35.507" UserId="19523" Text="L_i(p,w_i) = L_o(p+w_i*t,-w_i) where t is some distance to another point, so w_i is &quot;positive&quot; (-) when evaluating L_o but &quot;negative&quot; (+) for L_i. So if -w_i is used in L_i, we get problems in L_o since w_i points into geometry." ContentLicense="CC BY-SA 4.0" />
  <row Id="41787" PostHistoryTypeId="5" PostId="13713" RevisionGUID="9d967631-ee0e-4bae-ab6e-a98ae1d3c500" CreationDate="2023-09-13T09:58:06.670" UserId="10096" Comment="added 45 characters in body" Text="$L_i(p,\omega_i) = L_o(p+t\omega_i,-\omega_i)$ where t is some distance to another point, so $\omega_i$ is &quot;positive&quot; (-) when evaluating $L_o$ but &quot;negative&quot; (+) for $L_i$. So if $-\omega_i$ is used in $L_i$, we get problems in $L_o$ since $\omega_i$ points into geometry." ContentLicense="CC BY-SA 4.0" />
  <row Id="41788" PostHistoryTypeId="5" PostId="13712" RevisionGUID="6a66ea9a-1587-4413-970c-fecab17f35bb" CreationDate="2023-09-13T18:08:41.357" UserId="20522" Comment="deleted 2 characters in body" Text="I am studying from pbrt-v3 and the rendering equation has just been introduced as&#xD;&#xA;$$&#xD;&#xA;\underbrace{L_\mathrm{o}(\mathrm{p},\omega_\mathrm{o})}_\text{Outgoing radiance }=\underbrace{L_\mathrm{e}(\mathrm{p},\omega_\mathrm{o})}_\text{Emitted Radiance}+\underbrace{\int_{\mathrm{S}^2}f(\mathrm{p},\omega_\mathrm{o},\omega_\mathrm{i})L_\mathrm{i}(\mathrm{p},\omega_\mathrm{i})|\cos(\theta_\mathrm{i})|\mathrm{d}\omega_\mathrm{i}}_\text{Incident radiance from all directions}.&#xD;&#xA;$$&#xD;&#xA;Please bear with me as I have some confusion regarding the integration variable $\omega_\mathrm{i}$. It represents a point on the sphere $\mathrm{S}^2$, which is centred at $\mathrm{p}$, so wouldn't this mean the direction of the incoming light points *away* from $\mathrm{p}$? I took a look at the [Wikipedia page][1] for the rendering equation and indeed, $\omega_\mathrm{i}$ is stated as the *negative* direction of incoming light.&#xD;&#xA;&#xD;&#xA;I'm wondering why the direction is stated as negative. Perhaps it makes the equation simpler? How would the incident radiance function $L_\mathrm{i}(\mathrm{p},\omega_\mathrm{i})$ handle a negative direction?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Rendering_equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41789" PostHistoryTypeId="2" PostId="13714" RevisionGUID="d0cad965-83d4-45bd-8cc0-eb19cecafc0a" CreationDate="2023-09-13T22:32:34.467" UserId="10096" Text="Disclaimer: I haven't read most of the papers that the book refers to, so what you will find below is my own understanding based on very little data (i.e. I may have severely misunderstood some part of the book).&#xD;&#xA;&#xD;&#xA;**Laplace-Beltrami Operator**&#xD;&#xA;&#xD;&#xA;In a finite element formulation you typically have a stiffness matrix $W$ and a mass matrix $M$. For a 2-manifold one possible discretisation is the cotangent one:&#xD;&#xA;$$W_{ij} = &#xD;&#xA;\begin{cases}&#xD;&#xA;-\frac{1}{2}(\cot\alpha_{ij}+\cot\beta_{ij}) &amp;\text{for } j\in\mathcal{N}(i),\\&#xD;&#xA;\sum_{k\in\mathcal{N}(i)}C_{ik} &amp;\text{for } j=i, \\&#xD;&#xA;0 &amp;\text{for } j\ne i \land j\notin \mathcal{N}(i),&#xD;&#xA;\end{cases}&#xD;&#xA;$$&#xD;&#xA;where $\alpha_{ij}$ and $\beta_{ij}$ are the angles opposite to the edge $ij$. You can also find the same up to a factor $\frac{1}{2}$ in the appendix of the book you linked (note that in said book they use instead of $W$ and $M$, $M$ and $D$), or a few pages prior to the one you cite. In the appendix of the book that you have the mass matrix $M$ is a lumped (diagonal) matrix, where $M_{ii}$ is the Voronoi area for vertex $i$. Then finally they use $\Delta_S\approx L = -M^{-1}W$ (here $\Delta_S$ describes the Laplace-Beltrami operator on the manifold $S$).&#xD;&#xA;&#xD;&#xA;**Continuous Harmonic Formulation**&#xD;&#xA;&#xD;&#xA;As far as I can tell the continuous formulation of the fairing approach with a membrane surface would be something like this:&#xD;&#xA;\begin{align}&#xD;&#xA;\Delta_S x &amp;= 0, \quad x\in S, \\&#xD;&#xA;x &amp;= p, \quad x\in \partial S,&#xD;&#xA;\end{align}&#xD;&#xA;where $S$ is the blue part in the images, $\partial\Omega$ is the boundary (the interface between white and blue), and $p$ are the (fixed) positions at said boundary. You may note that the above is actually a non-linear equation. This is the case because $\Delta_{S}$ depends on the surface itself, and $x$ also depends on the surface itself. Thus I would actually suggest (for the sake of devising a numerical algorithm) to instead consider the time evolution equation:&#xD;&#xA;\begin{alignat}{3}&#xD;&#xA;\partial_t x(t) &amp;= \Delta_{S(t)} x(t), &amp;\quad&amp; x\in S(t), &amp;\quad&amp; t\in(0,\infty) \\&#xD;&#xA;x(t) &amp;= p, &amp;\quad&amp; x\in \partial S(t), &amp;\quad&amp; t\in[0,\infty), \\&#xD;&#xA;S(0) &amp;= S_0.&#xD;&#xA;\end{alignat}&#xD;&#xA;This should be equivalent to the first formulation at the steady state $\partial_t x = 0$.&#xD;&#xA;&#xD;&#xA;**Discrete Harmonic Formulation**&#xD;&#xA;&#xD;&#xA;The first continuous formulation can be discretised just as:&#xD;&#xA;$$(C-(I-C)L)X = CP,$$&#xD;&#xA;where $\Delta_{S} \approx L = -M^{-1}W\in\mathbb{R}^{n\times n}$, $X\in\mathbb{R}^{n\times 3}$ are the $n$ vertices' positions that are inside the blue region and also the ones from the boundary (vertices that are from the white region but have a blue neighbour), $P\in\mathbb{R}^{n\times 3}$ are the initial positions. Finally $C = \operatorname{diag}(c)$, where $c \approx 1_{\partial S}$:&#xD;&#xA;$$c_i=\begin{cases} 1, \quad \text{$i$ is a boundary vertex}, \\ 0, \quad \text{$i$ is not a boundary vertex}. \end{cases}$$&#xD;&#xA;$(C-(I-C)L)$ essentially negated $L$ and replaces its rows corresponding to Dirichlet vertices with $e_k$ (where $k$ is the index of the row being replaced). You can fully eliminate the Dirichlet vertices by considering the reduced formulation as in FEM also. Note however that in either case $L$ is actually a function of $X$ (since these cotan angles and areas depend on the position of the vertices), this means that the system is non-linear. A standard approach is to try and use a fixed point iteration, i.e. have an initial guess $X^0$, then compute $L^0$ from it, and solve the system $(C-(I-C)L^0)X^1 = CP$. Repeating this yields the iteration $(C-(I-C)L^k)X^{k+1} = CP$, and you stop when e.g. $\|X^{k+1}-X^k\|&lt;\epsilon$ in some iteration (note that the superscripts here are iteration indices and not powers). I have no idea how stable this is however. You can of course try other approaches for solving nonlinear systems of equations.&#xD;&#xA;&#xD;&#xA;For the time-evolution equation we can discretise the time derivative, e.g. using explicit or semi-implicit Euler. In the explicit variant you have:&#xD;&#xA;$$\partial_t x(t) = \Delta_{S(t)} x(t) \implies \frac{x^{k+1}-x^k}{\tau} = \Delta_{S^k} x^k,$$&#xD;&#xA;while in the semi-implicit variant you have:&#xD;&#xA;$$\partial_t x(t) = \Delta_{S(t)} x(t) \implies \frac{x^{k+1}-x^k}{\tau} = \Delta_{S^k} x^{k+1}.$$&#xD;&#xA;You can of course also try a fully-implicit variant, but that will result in a nonlinear system of equations that you must solve. Once you discretise also the spatial domain and incorporate the boundary conditions you get:&#xD;&#xA;\begin{alignat}{2}&#xD;&#xA;x^{k+1} &amp;= (I-C)(I+\tau L^k)x^k + CP &amp;\quad&amp;&amp; \text{(explicit Euler)}\\&#xD;&#xA;(C+(I-C)(I-\tau L^k))x^{k+1} &amp;= CP &amp;\quad&amp;&amp; \text{(semi-implicit Euler)}.&#xD;&#xA;\end{alignat}&#xD;&#xA;The semi-implicit variant should be stable for all $\tau&gt;0$ I believe, but larger step sizes may give poor results.&#xD;&#xA;&#xD;&#xA;**Polyharmonic Formulation**&#xD;&#xA;&#xD;&#xA;For the polyharmonic formulation you need additional boundary conditions. What I can suggest are Navier conditions:&#xD;&#xA;\begin{align}&#xD;&#xA;(-\Delta_S)^q x &amp;= 0, \quad x\in S, \\&#xD;&#xA;(-\Delta)^l x &amp;= p^l, \quad x\in \partial S, \, 0\leq l \leq q-1.&#xD;&#xA;\end{align}&#xD;&#xA;Then this gets discretised as&#xD;&#xA;$$\left(C\sum_{l=0}^{q-1}(-L)^{l}+(I-C)(-L)^q\right)X = C\sum_{l=0}^{q-1}P^l.$$&#xD;&#xA;Note that the superscripts here refer to powers, except for the superscript of $P$ which refers to just different matrix indices.&#xD;&#xA;&#xD;&#xA;**Implementation Details**&#xD;&#xA;&#xD;&#xA;When you solve the linear systems you do not have to solve simultaneously for each coordinate, you can solve them one at a time. The system matrix remains the same, only the right-hand side changes. You may also want symmetrize the $L$ as described in the book, then you could use a conjugate gradient solver since the matrices should be symmetric positive definite (provided you have at least 1 Dirichlet vertex)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41791" PostHistoryTypeId="5" PostId="13714" RevisionGUID="0347fda3-365a-46c2-ad3d-54bd8060bb28" CreationDate="2023-09-13T22:42:07.803" UserId="10096" Comment="added 563 characters in body" Text="Disclaimer: I haven't read most of the papers that the book refers to, so what you will find below is my own understanding based on very little data (i.e. I may have severely misunderstood some part of the book).&#xD;&#xA;&#xD;&#xA;**Laplace-Beltrami Operator**&#xD;&#xA;&#xD;&#xA;In a finite element formulation you typically have a stiffness matrix $W$ and a mass matrix $M$. For a 2-manifold one possible discretisation is the cotangent one:&#xD;&#xA;$$W_{ij} = &#xD;&#xA;\begin{cases}&#xD;&#xA;-\frac{1}{2}(\cot\alpha_{ij}+\cot\beta_{ij}) &amp;\text{for } j\in\mathcal{N}(i),\\&#xD;&#xA;\sum_{k\in\mathcal{N}(i)}C_{ik} &amp;\text{for } j=i, \\&#xD;&#xA;0 &amp;\text{for } j\ne i \land j\notin \mathcal{N}(i),&#xD;&#xA;\end{cases}&#xD;&#xA;$$&#xD;&#xA;where $\alpha_{ij}$ and $\beta_{ij}$ are the angles opposite to the edge $ij$. You can also find the same up to a factor $\frac{1}{2}$ in the appendix of the book you linked (note that in said book they use instead of $W$ and $M$, $M$ and $D$), or a few pages prior to the one you cite. In the appendix of the book that you have the mass matrix $M$ is a lumped (diagonal) matrix, where $M_{ii}$ is the Voronoi area for vertex $i$. Then finally they use $\Delta_S\approx L = -M^{-1}W$ (here $\Delta_S$ describes the Laplace-Beltrami operator on the manifold $S$).&#xD;&#xA;&#xD;&#xA;**Continuous Harmonic Formulation**&#xD;&#xA;&#xD;&#xA;As far as I can tell the continuous formulation of the fairing approach with a membrane surface would be something like this:&#xD;&#xA;\begin{align}&#xD;&#xA;\Delta_S x &amp;= 0, \quad x\in S, \\&#xD;&#xA;x &amp;= p, \quad x\in \partial S,&#xD;&#xA;\end{align}&#xD;&#xA;where $S$ is the blue part in the images, $\partial\Omega$ is the boundary (the interface between white and blue), and $p$ are the (fixed) positions at said boundary. You may note that the above is actually a non-linear equation. This is the case because $\Delta_{S}$ depends on the surface itself, and $x$ also depends on the surface itself. Thus I would actually suggest (for the sake of devising a numerical algorithm) to instead consider the time evolution equation:&#xD;&#xA;\begin{alignat}{3}&#xD;&#xA;\partial_t x(t) &amp;= \Delta_{S(t)} x(t), &amp;\quad&amp; x\in S(t), &amp;\quad&amp; t\in(0,\infty) \\&#xD;&#xA;x(t) &amp;= p, &amp;\quad&amp; x\in \partial S(t), &amp;\quad&amp; t\in[0,\infty), \\&#xD;&#xA;S(0) &amp;= S_0.&#xD;&#xA;\end{alignat}&#xD;&#xA;This should be equivalent to the first formulation at the steady state $\partial_t x = 0$.&#xD;&#xA;&#xD;&#xA;**Discrete Harmonic Formulation**&#xD;&#xA;&#xD;&#xA;The first continuous formulation can be discretised just as:&#xD;&#xA;$$(C-(I-C)L)X = CP,$$&#xD;&#xA;where $\Delta_{S} \approx L = -M^{-1}W\in\mathbb{R}^{n\times n}$, $X\in\mathbb{R}^{n\times 3}$ are the $n$ vertices' positions that are inside the blue region and also the ones from the boundary (vertices that are from the white region but have a blue neighbour), $P\in\mathbb{R}^{n\times 3}$ are the initial positions. Finally $C = \operatorname{diag}(c)$, where $c \approx 1_{\partial S}$:&#xD;&#xA;$$c_i=\begin{cases} 1, \quad \text{$i$ is a boundary vertex}, \\ 0, \quad \text{$i$ is not a boundary vertex}. \end{cases}$$&#xD;&#xA;$(C-(I-C)L)$ essentially negated $L$ and replaces its rows corresponding to Dirichlet vertices with $e_k$ (where $k$ is the index of the row being replaced). You can fully eliminate the Dirichlet vertices by considering the reduced formulation as in FEM also. Note however that in either case $L$ is actually a function of $X$ (since these cotan angles and areas depend on the position of the vertices), this means that the system is non-linear. A standard approach is to try and use a fixed point iteration, i.e. have an initial guess $X^0$, then compute $L^0$ from it, and solve the system $(C-(I-C)L^0)X^1 = CP$. Repeating this yields the iteration $(C-(I-C)L^k)X^{k+1} = CP$, and you stop when e.g. $\|X^{k+1}-X^k\|&lt;\epsilon$ in some iteration (note that the superscripts here are iteration indices and not powers). I have no idea how stable this is however. You can of course try other approaches for solving nonlinear systems of equations.&#xD;&#xA;&#xD;&#xA;For the time-evolution equation we can discretise the time derivative, e.g. using explicit or semi-implicit Euler. In the explicit variant you have:&#xD;&#xA;$$\partial_t x(t) = \Delta_{S(t)} x(t) \implies \frac{x^{k+1}-x^k}{\tau} = \Delta_{S^k} x^k,$$&#xD;&#xA;while in the semi-implicit variant you have:&#xD;&#xA;$$\partial_t x(t) = \Delta_{S(t)} x(t) \implies \frac{x^{k+1}-x^k}{\tau} = \Delta_{S^k} x^{k+1}.$$&#xD;&#xA;You can of course also try a fully-implicit variant, but that will result in a nonlinear system of equations that you must solve. Once you discretise also the spatial domain and incorporate the boundary conditions you get:&#xD;&#xA;\begin{alignat}{2}&#xD;&#xA;x^{k+1} &amp;= (I-C)(I+\tau L^k)x^k + CP &amp;\quad&amp;&amp; \text{(explicit Euler)}\\&#xD;&#xA;(C+(I-C)(I-\tau L^k))x^{k+1} &amp;= CP &amp;\quad&amp;&amp; \text{(semi-implicit Euler)}.&#xD;&#xA;\end{alignat}&#xD;&#xA;The semi-implicit variant should be stable for all $\tau&gt;0$ I believe, but larger step sizes may give poor results.&#xD;&#xA;&#xD;&#xA;**Polyharmonic Formulation**&#xD;&#xA;&#xD;&#xA;For the polyharmonic formulation you need additional boundary conditions. What I can suggest are Navier conditions:&#xD;&#xA;\begin{align}&#xD;&#xA;(-\Delta_S)^q x &amp;= 0, \quad x\in S, \\&#xD;&#xA;(-\Delta)^l x &amp;= p^l, \quad x\in \partial S, \, 0\leq l \leq q-1.&#xD;&#xA;\end{align}&#xD;&#xA;Then this gets discretised as&#xD;&#xA;$$\left(C\sum_{l=0}^{q-1}(-L)^{l}+(I-C)(-L)^q\right)X = C\sum_{l=0}^{q-1}P^l.$$&#xD;&#xA;Note that the superscripts here refer to powers, except for the superscript of $P$ which refers to just different matrix indices.&#xD;&#xA;&#xD;&#xA;**Implementation Details**&#xD;&#xA;&#xD;&#xA;When you solve the linear systems you do not have to solve simultaneously for each coordinate, you can solve them one at a time. The system matrix remains the same, only the right-hand side changes. You may also want symmetrize the $L$ as described in the book, then you could use a conjugate gradient solver since the matrices should be symmetric positive definite (provided you have at least 1 Dirichlet vertex).&#xD;&#xA;&#xD;&#xA;When you have to deal with the $(-L)^j$ powers you can just implement them initially as iterated matrix-vector products. Later on you can compute the explicit form of the matrices in order to reuse cache more.&#xD;&#xA;&#xD;&#xA;The choice of the Navier conditions for the polyharmonic case lets you directly use $(-L)^l$ (as seen in the last discretisation) instead of having to derive special modification for the boundary terms.&#xD;&#xA;&#xD;&#xA;Also, please post some screenshots if you make this work. It's nice to know if what I mentioned actually works out and see the result of it." ContentLicense="CC BY-SA 4.0" />
  <row Id="41792" PostHistoryTypeId="5" PostId="13681" RevisionGUID="bbe87a50-b86e-49f9-8b57-77ee34c9c13e" CreationDate="2023-09-14T01:20:06.550" UserId="20471" Comment="deleted 6 characters in body" Text="TL;DR -- who has discovered, in the past, a backward-only path tracer that generates caustics not needing extra convergence of any kind? I'm collecting similar algorithms, in order to fully understand physically accurate path tracing.&#xD;&#xA;&#xD;&#xA;Edit: Seems like James Kajiya is likely the person who discovered this algorithm first.&#xD;&#xA;&#xD;&#xA;The post:&#xD;&#xA;&#xD;&#xA;I am working on a Vulkan path tracer. The result is not physically correct, in the sense that it doesn't define a BDRF or PDF, etc. However, it does support caustics. Basically, I bounce the sampler ray around the scene, and if it hits a (semi-)transparent object, it gets redirected via refraction rather than a random reflection. So basically, it doesn't require a heavy load of computation in order for the algorithm to do its thing -- making beautiful caustics.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HDyTB.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/9ySk8.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/KLJiF.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/27LYU.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/ZEcn4.jpg&#xD;&#xA;&#xD;&#xA;Here the caustics form a rainbow-like pattern because of chromatic aberration. Fog has been implemented in the 5th figure.&#xD;&#xA;&#xD;&#xA;The full source is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;In particular, the raygen shader is at: https://github.com/sjhalayka/cornell_box_textured/blob/main/raygen.rgen&#xD;&#xA;&#xD;&#xA;The source code is based off of Sascha Willems' raytracingreflections code. The model (scene) was generated by Rob Rau.&#xD;&#xA;&#xD;&#xA;So, please, understand that I'm fairly new at path tracing. Can you please point me toward some well-known backward-only caustics algorithms?&#xD;&#xA;&#xD;&#xA;Thanks for your time and expertise.&#xD;&#xA;&#xD;&#xA;The relevant code is:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;vec3 hitPos = o + d * rayPayload.distance;&#xD;&#xA;&#xD;&#xA;// If partially transparent&#xD;&#xA;if(rayPayload.opacity != 1.0)&#xD;&#xA;{&#xD;&#xA;	// Incoming ray&#xD;&#xA;	if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;	{&#xD;&#xA;		o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;		d = refract(d, rayPayload.normal, eta);&#xD;&#xA;	}&#xD;&#xA;	else // Outgoing ray&#xD;&#xA;	{&#xD;&#xA;		vec3 temp_dir = refract(d, -rayPayload.normal, 1.0/eta);&#xD;&#xA;&#xD;&#xA;		if(temp_dir != vec3(0.0))&#xD;&#xA;		{&#xD;&#xA;			o = hitPos.xyz + rayPayload.normal * 0.01;&#xD;&#xA;			d = temp_dir;&#xD;&#xA;		}&#xD;&#xA;		else&#xD;&#xA;		{&#xD;&#xA;			// Total internal reflection&#xD;&#xA;			o = hitPos.xyz - rayPayload.normal * 0.01;&#xD;&#xA;			d = reflect(d, -rayPayload.normal);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;}&#xD;&#xA;else // Fully opaque&#xD;&#xA;{&#xD;&#xA;	o = hitPos + rayPayload.normal*0.01;&#xD;&#xA;	vec3 d_cos = cos_weighted(rayPayload.normal, prng_state);&#xD;&#xA;	d = mix(d_cos, reflect(d, rayPayload.normal), rayPayload.reflector);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41793" PostHistoryTypeId="2" PostId="13715" RevisionGUID="77d98241-9ea2-47af-9490-f75fbf966875" CreationDate="2023-09-14T09:37:45.427" UserId="7008" Text="Glsl does not support string / char data types, but obviously `debugPrintfEXT` works and takes some form of string. How are these handled in glsl?&#xD;&#xA;&#xD;&#xA;Ideally I would like to forward the input, such that I can very easily limit when `debugPrintfEXT` is called, something like this&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;layout(pushconstant) uniform DebugSettings&#xD;&#xA;{&#xD;&#xA;    bool Enabled;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;debugPrintLimited(string s)&#xD;&#xA;{&#xD;&#xA;    bool isCenter = gl_LaunchIDEXT.x == gl_LaunchSizeEXT.x / 2&#xD;&#xA;		&amp;&amp; gl_LaunchIDEXT.y == gl_LaunchSizeEXT.y / 2&#xD;&#xA;    if(DebugSettings.Enabled &amp;&amp; isCenter)&#xD;&#xA;    {&#xD;&#xA;        debugPrintfEXT(s);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Obviously the string here is not correct, but glsl has to handle the strings put into `debugPrintfEXT` somehow, so I would like to forward whatever they use, if at all possible." ContentLicense="CC BY-SA 4.0" />
  <row Id="41795" PostHistoryTypeId="1" PostId="13715" RevisionGUID="77d98241-9ea2-47af-9490-f75fbf966875" CreationDate="2023-09-14T09:37:45.427" UserId="7008" Text="How are strings for debugPrintfEXT handled in glsl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41796" PostHistoryTypeId="3" PostId="13715" RevisionGUID="77d98241-9ea2-47af-9490-f75fbf966875" CreationDate="2023-09-14T09:37:45.427" UserId="7008" Text="|glsl|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41801" PostHistoryTypeId="2" PostId="13717" RevisionGUID="9d091d2a-181d-4bce-9898-3315bc1ad306" CreationDate="2023-09-16T00:06:23.217" UserId="7952" Text="They get help from the compiler. The line `#extension GL_EXT_debug_printf : enable` tells the compiler to look for and process debugPrintf statements inside the shader it then parses them out, modifies them, adds its own instructions, creates buffers... Basically they can do whatever they need to make it work.&#xD;&#xA;&#xD;&#xA;You could forward just the variables but that would be pretty limited. And , unfortunately the printf would end up being very generic.&#xD;&#xA;&#xD;&#xA;Another choice would be to write a macro that expands to a call to the printf with a bool wrapper around it. Basically the macro would expand to the if statement that is need to gate the call without using a function call, and have the printf inside of its body. I haven't tried this in GLSL myself but it seems very doable. GLSL's macro language is pretty powerful. I've seen some crazy long macro's put together with long code segments passed as strings.&#xD;&#xA;&#xD;&#xA;Something along the lines of:&#xD;&#xA;&#xD;&#xA;    #ifdef DEBUG_ENABLED&#xD;&#xA;    #define printf( condition, message, value ) if( condition ){ \&#xD;&#xA;        printfDebugEXT( #message, value ); \&#xD;&#xA;     }&#xD;&#xA;    #elif&#xD;&#xA;    #define printf( condition, message, value )&#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    printf( x==40.0 &amp;&amp; y==20.0, &quot;at 20,40 color is %1fv4.&quot;, color );&#xD;&#xA;&#xD;&#xA;Unfortunately glsl doesn't support variadic macros so this has to be specific to 1 value or 2 values ect.&#xD;&#xA;&#xD;&#xA;Maybe a macro for 1,2,3 variable outputs like printf1, printf2, and printf3.&#xD;&#xA;&#xD;&#xA;Also the glsl language version can effect macro behavior but since the code is using debugprintf then it probably won't be an issue. &#xD;&#xA;&#xD;&#xA;Finally you may want to just preprocess this through the compiler a few times until you get the syntax just right." ContentLicense="CC BY-SA 4.0" />
  <row Id="41804" PostHistoryTypeId="50" PostId="13633" RevisionGUID="1f28c3dd-248f-4115-833e-4934701006eb" CreationDate="2023-09-16T11:07:50.920" UserId="-1" />
  <row Id="41805" PostHistoryTypeId="5" PostId="13717" RevisionGUID="246655c7-1f3b-46f5-b312-b42c425e7837" CreationDate="2023-09-16T11:53:51.607" UserId="7952" Comment="added 213 characters in body" Text="They get help from the compiler. The line `#extension GL_EXT_debug_printf : enable` tells the compiler to look for and process debugPrintf statements inside the shader it then parses them out, modifies them, adds its own instructions, creates buffers... Basically they can do whatever they need to make it work.&#xD;&#xA;&#xD;&#xA;You could forward just the variables but that would be pretty limited. And , unfortunately the printf would end up being very generic.&#xD;&#xA;&#xD;&#xA;Another choice would be to write a macro that expands to a call to the printf with a bool wrapper around it. Basically the macro would expand to the if statement that is need to gate the call without using a function call, and have the printf inside of its body. I haven't tried this in GLSL myself but it seems very doable. GLSL's macro language is pretty powerful. I've seen some crazy long macro's put together with long code segments passed as strings.&#xD;&#xA;&#xD;&#xA;Updated the code to the version that worked from the comment:&#xD;&#xA;&#xD;&#xA;    #ifdef DEBUG &#xD;&#xA;    #define printf( condition, message, value ) if( condition ){ \&#xD;&#xA;           debugPrintfEXT( message, value ); \&#xD;&#xA;         } &#xD;&#xA;    #define printfDbg(message, value) if(isCenter() &amp;&amp; pSettings.PrintDebugEnabled){ \&#xD;&#xA; 	     debugPrintfEXT(message, value);\&#xD;&#xA;      } &#xD;&#xA;    #else &#xD;&#xA;    #define printf( condition, message, value ) &#xD;&#xA;    #define printfDbg(message, value) &#xD;&#xA;    #endif&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;    printf( x==40.0 &amp;&amp; y==20.0, &quot;at 20,40 color is %1fv4.&quot;, color );&#xD;&#xA;&#xD;&#xA;Unfortunately glsl doesn't support variadic macros so this has to be specific to 1 value or 2 values ect.&#xD;&#xA;&#xD;&#xA;Maybe a macro for 1,2,3 variable outputs like printf1, printf2, and printf3.&#xD;&#xA;&#xD;&#xA;Also the glsl language version can effect macro behavior but since the code is using debugprintf then it probably won't be an issue. &#xD;&#xA;&#xD;&#xA;Finally you may want to just preprocess this through the compiler a few times until you get the syntax just right." ContentLicense="CC BY-SA 4.0" />
  <row Id="41806" PostHistoryTypeId="50" PostId="9781" RevisionGUID="da30ce91-5d45-445f-bc16-8b56b4168cd2" CreationDate="2023-09-16T23:04:00.483" UserId="-1" />
  <row Id="41807" PostHistoryTypeId="50" PostId="10177" RevisionGUID="e1156306-a3ff-45fe-838a-4bb5aff03cdc" CreationDate="2023-09-17T07:05:45.637" UserId="-1" />
  <row Id="41808" PostHistoryTypeId="50" PostId="5220" RevisionGUID="7cecfb8b-b759-43a6-bcbc-8efa3887a560" CreationDate="2023-09-17T08:00:45.150" UserId="-1" />
  <row Id="41809" PostHistoryTypeId="4" PostId="13650" RevisionGUID="9518505d-6602-44e8-99ba-6c65434eb29c" CreationDate="2023-09-17T16:16:26.990" UserId="19163" Comment="edited title" Text="tilling the Hyperbolic plane" ContentLicense="CC BY-SA 4.0" />
  <row Id="41820" PostHistoryTypeId="2" PostId="13720" RevisionGUID="efc79d9a-3a40-4476-a1a4-24b78207c677" CreationDate="2023-09-19T16:53:04.397" UserId="20471" Text="My code to do path tracing is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float trace_path2(out vec3 final_pos, const int steps, const vec3 origin, const vec3 direction, const float hue, float eta)&#xD;&#xA;    {&#xD;&#xA;    	const RayPayload r = rayPayload;&#xD;&#xA;    &#xD;&#xA;    	vec3 hitPos = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    	float ret_colour = 0;&#xD;&#xA;    &#xD;&#xA;    	vec3 o = origin;&#xD;&#xA;    	vec3 d = direction;&#xD;&#xA;    &#xD;&#xA;    	int count = 0;&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    	float energy = 100.0;&#xD;&#xA;    &#xD;&#xA;    	float local_colour = energy;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	float total = 0;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; steps; i++)&#xD;&#xA;    	{&#xD;&#xA;    		const float tmin = 0.001;&#xD;&#xA;    		const float tmax = 10000.0;&#xD;&#xA;    		traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o.xyz, tmin, d.xyz, tmax, 0);&#xD;&#xA;    &#xD;&#xA;    		const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));&#xD;&#xA;    &#xD;&#xA;    		total += mask.r;&#xD;&#xA;    		total += mask.g;&#xD;&#xA;    		total += mask.b;&#xD;&#xA;    &#xD;&#xA;    		local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.distance == -1)&#xD;&#xA;    			break;&#xD;&#xA;    &#xD;&#xA;    		hitPos = o + d * rayPayload.distance;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.color.r == 1.0 &amp;&amp; rayPayload.color.g == 1.0 &amp;&amp; rayPayload.color.b == 1.0)&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    		vec3 o_reflect = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    		vec3 d_reflect = reflect(d, rayPayload.normal);&#xD;&#xA;    &#xD;&#xA;    		vec3 temp_o = o_reflect;&#xD;&#xA;    		vec3 temp_d = d_reflect;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.reflector &lt; 1.0) // if less than fully reflective, do scattering&#xD;&#xA;    		{&#xD;&#xA;    			vec3 o_scatter = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    			vec3 d_scatter = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;    &#xD;&#xA;    			temp_o = mix(temp_o, o_scatter, 1.0 - rayPayload.reflector);&#xD;&#xA;    			temp_d = mix(temp_d, d_scatter, 1.0 - rayPayload.reflector);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return rayPayload.opacity;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.opacity &lt; 1.0) // if partially transparent, do refraction&#xD;&#xA;    		{&#xD;&#xA;    			vec3 o_transparent = vec3(0.0);&#xD;&#xA;    			vec3 d_transparent = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    			// Incoming&#xD;&#xA;    			if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;    			{&#xD;&#xA;    				o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    				d_transparent = refract(d, rayPayload.normal, eta);&#xD;&#xA;    			}&#xD;&#xA;    			else // Outgoing&#xD;&#xA;    			{&#xD;&#xA;    				vec3 temp_dir = refract(d, -rayPayload.normal, 1.0 / eta);&#xD;&#xA;    &#xD;&#xA;    				if(temp_dir != vec3(0.0))&#xD;&#xA;    				{&#xD;&#xA;    					o_transparent = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = temp_dir;&#xD;&#xA;    				}&#xD;&#xA;    				else&#xD;&#xA;    				{&#xD;&#xA;    					// total internal reflection&#xD;&#xA;    					o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = reflect(d, -rayPayload.normal);&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			temp_o = mix(temp_o, o_transparent, 1.0 - rayPayload.opacity);&#xD;&#xA;    			temp_d = mix(temp_d, d_transparent, 1.0 - rayPayload.opacity);&#xD;&#xA;    		}&#xD;&#xA;    			&#xD;&#xA;    		o = temp_o;&#xD;&#xA;    		d = normalize(temp_d);&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	final_pos = hitPos;&#xD;&#xA;    	rayPayload = r;&#xD;&#xA;    	return ret_colour / total;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When I make the statement return rayPayload.opacity; it returns the following image, which is what I expect:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3JVtR.png&#xD;&#xA;&#xD;&#xA;However, if you comment out that return statement, the if statement on the next line is never run, even though it's obviously not 1.0 in some parts of the image. It's the strangest problem.&#xD;&#xA;&#xD;&#xA;The full code is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;Basically, I have reflection caustics working, but I cannot get refraction caustics to work yet (in the new version 2.0 of my path tracer).&#xD;&#xA;&#xD;&#xA;Any big errors that I'm not seeing here?&#xD;&#xA;&#xD;&#xA;Thanks for your time." ContentLicense="CC BY-SA 4.0" />
  <row Id="41822" PostHistoryTypeId="1" PostId="13720" RevisionGUID="efc79d9a-3a40-4476-a1a4-24b78207c677" CreationDate="2023-09-19T16:53:04.397" UserId="20471" Text="Path tracer -- How to debug erroneous behaviour?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41823" PostHistoryTypeId="3" PostId="13720" RevisionGUID="efc79d9a-3a40-4476-a1a4-24b78207c677" CreationDate="2023-09-19T16:53:04.397" UserId="20471" Text="|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41824" PostHistoryTypeId="5" PostId="13720" RevisionGUID="7b299638-6323-4f59-aa0a-ebbaa6cf18a6" CreationDate="2023-09-19T17:36:21.167" UserId="20471" Comment="added 2 characters in body" Text="My code to do path tracing is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float trace_path2(out vec3 final_pos, const int steps, const vec3 origin, const vec3 direction, const float hue, float eta)&#xD;&#xA;    {&#xD;&#xA;    	const RayPayload r = rayPayload;&#xD;&#xA;    &#xD;&#xA;    	vec3 hitPos = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    	float ret_colour = 0;&#xD;&#xA;    &#xD;&#xA;    	vec3 o = origin;&#xD;&#xA;    	vec3 d = direction;&#xD;&#xA;    &#xD;&#xA;    	int count = 0;&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    	float energy = 100.0;&#xD;&#xA;    &#xD;&#xA;    	float local_colour = energy;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	float total = 0;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; steps; i++)&#xD;&#xA;    	{&#xD;&#xA;    		const float tmin = 0.001;&#xD;&#xA;    		const float tmax = 10000.0;&#xD;&#xA;    		traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o.xyz, tmin, d.xyz, tmax, 0);&#xD;&#xA;    &#xD;&#xA;    		const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));&#xD;&#xA;    &#xD;&#xA;    		total += mask.r;&#xD;&#xA;    		total += mask.g;&#xD;&#xA;    		total += mask.b;&#xD;&#xA;    &#xD;&#xA;    		local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.distance == -1)&#xD;&#xA;    			break;&#xD;&#xA;    &#xD;&#xA;    		hitPos = o + d * rayPayload.distance;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.color.r == 1.0 &amp;&amp; rayPayload.color.g == 1.0 &amp;&amp; rayPayload.color.b == 1.0)&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    		vec3 o_reflect = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    		vec3 d_reflect = reflect(d, rayPayload.normal);&#xD;&#xA;    &#xD;&#xA;    		vec3 temp_o = o_reflect;&#xD;&#xA;    		vec3 temp_d = d_reflect;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.reflector &lt; 1.0) // if less than fully reflective, do scattering&#xD;&#xA;    		{&#xD;&#xA;    			vec3 o_scatter = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    			vec3 d_scatter = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;    &#xD;&#xA;    			temp_o = mix(temp_o, o_scatter, 1.0 - rayPayload.reflector);&#xD;&#xA;    			temp_d = mix(temp_d, d_scatter, 1.0 - rayPayload.reflector);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return rayPayload.opacity;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.opacity &lt; 1.0) // if partially transparent, do refraction&#xD;&#xA;    		{&#xD;&#xA;    			vec3 o_transparent = vec3(0.0);&#xD;&#xA;    			vec3 d_transparent = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    			// Incoming&#xD;&#xA;    			if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;    			{&#xD;&#xA;    				o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    				d_transparent = refract(d, rayPayload.normal, eta);&#xD;&#xA;    			}&#xD;&#xA;    			else // Outgoing&#xD;&#xA;    			{&#xD;&#xA;    				vec3 temp_dir = refract(d, -rayPayload.normal, 1.0 / eta);&#xD;&#xA;    &#xD;&#xA;    				if(temp_dir != vec3(0.0))&#xD;&#xA;    				{&#xD;&#xA;    					o_transparent = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = temp_dir;&#xD;&#xA;    				}&#xD;&#xA;    				else&#xD;&#xA;    				{&#xD;&#xA;    					// total internal reflection&#xD;&#xA;    					o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = reflect(d, -rayPayload.normal);&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			temp_o = mix(temp_o, o_transparent, 1.0 - rayPayload.opacity);&#xD;&#xA;    			temp_d = mix(temp_d, d_transparent, 1.0 - rayPayload.opacity);&#xD;&#xA;    		}&#xD;&#xA;    			&#xD;&#xA;    		o = temp_o;&#xD;&#xA;    		d = normalize(temp_d);&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	final_pos = hitPos;&#xD;&#xA;    	rayPayload = r;&#xD;&#xA;    	return ret_colour / total;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When I make the statement `return rayPayload.opacity;` it returns the following image, which is what I expect:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3JVtR.png&#xD;&#xA;&#xD;&#xA;However, if you comment out that return statement, the if statement on the next line is never run, even though it's obviously not 1.0 in some parts of the image. It's the strangest problem.&#xD;&#xA;&#xD;&#xA;The full code is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;Basically, I have reflection caustics working, but I cannot get refraction caustics to work yet (in the new version 2.0 of my path tracer).&#xD;&#xA;&#xD;&#xA;Any big errors that I'm not seeing here?&#xD;&#xA;&#xD;&#xA;Thanks for your time." ContentLicense="CC BY-SA 4.0" />
  <row Id="41826" PostHistoryTypeId="2" PostId="13721" RevisionGUID="79e39d4d-09a7-4aa0-9b5d-05a374c4e7a5" CreationDate="2023-09-20T19:10:11.983" UserId="20568" Text="I am trying to make Terraria like game using WGPU and rust. There are gaps between tiles. The gaps are bigger and more common as I get far from world center. I've read that nearest filtering should help, hovewer I am already using it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Thanks for your help!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yXKW6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ksEIv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41828" PostHistoryTypeId="1" PostId="13721" RevisionGUID="79e39d4d-09a7-4aa0-9b5d-05a374c4e7a5" CreationDate="2023-09-20T19:10:11.983" UserId="20568" Text="Random spaces between textures" ContentLicense="CC BY-SA 4.0" />
  <row Id="41829" PostHistoryTypeId="3" PostId="13721" RevisionGUID="79e39d4d-09a7-4aa0-9b5d-05a374c4e7a5" CreationDate="2023-09-20T19:10:11.983" UserId="20568" Text="|texture|2d-graphics|tile-based-rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41830" PostHistoryTypeId="2" PostId="13722" RevisionGUID="45eac336-e618-4749-9826-75587ca5ce15" CreationDate="2023-09-20T19:49:54.843" UserId="20569" Text="I'm not a computer graphics engineer. I'm more of a quality engineer (primary language is C++). I've just started learning by myself about acceleration structures in computer graphics, especially Binary Space Partitioning (BSP) vs. Bounding Volume Hierarchy (BVH).&#xD;&#xA;&#xD;&#xA;I understand that a BSP kind of has a built-in visibility culling algorithm thanks to the way it's built. For example, given a node X in a BSP tree, all nodes in X's left subtree are in front of X, and all nodes in X's right subtree are behind X. On the other hand, a BVH is like an AABB tree whose nodes represent the hierarchical bounding boxes of objects. Unlike BSP, a BVH needs an explicit visibility culling algorithm.&#xD;&#xA;&#xD;&#xA;After building a BSP/BVH for objects in a 3D scene, if I change the camera's position (by rotating the scene, for example), I feel like for rendering the updated scene, the BVH won't need to be rebuilt because the bounding boxes remain relatively unchanged. We'll just need to run the explicit visibility culling algorithm on it again with the new viewpoint. The BSP will need to be rebuilt though because the front/back of a node in the BSP is now different with the new viewpoint. Am I understanding it correctly? Thank you in advance!" ContentLicense="CC BY-SA 4.0" />
  <row Id="41832" PostHistoryTypeId="1" PostId="13722" RevisionGUID="45eac336-e618-4749-9826-75587ca5ce15" CreationDate="2023-09-20T19:49:54.843" UserId="20569" Text="Does a BSP tree need to be rebuilt every time the camera's position changes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41833" PostHistoryTypeId="3" PostId="13722" RevisionGUID="45eac336-e618-4749-9826-75587ca5ce15" CreationDate="2023-09-20T19:49:54.843" UserId="20569" Text="|bounding-volume-hierarchy|space-partitioning|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41834" PostHistoryTypeId="5" PostId="13720" RevisionGUID="9ed97cfc-9e40-4a4e-96c3-8625367f5e4b" CreationDate="2023-09-21T01:14:47.493" UserId="20471" Comment="added 422 characters in body" Text="Edit: I've pinpointed the problem. If I change:&#xD;&#xA;&#xD;&#xA;    local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;&#xD;&#xA;into&#xD;&#xA;&#xD;&#xA;    local_colour += (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;&#xD;&#xA;... then I get caustics, but not vibrant colour. Any path tracing experts care to enlighten me as to what I'm doing wrong? :)&#xD;&#xA;&#xD;&#xA;The problem:&#xD;&#xA;&#xD;&#xA;My code to do path tracing is:&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    float trace_path2(out vec3 final_pos, const int steps, const vec3 origin, const vec3 direction, const float hue, float eta)&#xD;&#xA;    {&#xD;&#xA;    	const RayPayload r = rayPayload;&#xD;&#xA;    &#xD;&#xA;    	vec3 hitPos = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    	float ret_colour = 0;&#xD;&#xA;    &#xD;&#xA;    	vec3 o = origin;&#xD;&#xA;    	vec3 d = direction;&#xD;&#xA;    &#xD;&#xA;    	int count = 0;&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    	float energy = 100.0;&#xD;&#xA;    &#xD;&#xA;    	float local_colour = energy;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	float total = 0;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; steps; i++)&#xD;&#xA;    	{&#xD;&#xA;    		const float tmin = 0.001;&#xD;&#xA;    		const float tmax = 10000.0;&#xD;&#xA;    		traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o.xyz, tmin, d.xyz, tmax, 0);&#xD;&#xA;    &#xD;&#xA;    		const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));&#xD;&#xA;    &#xD;&#xA;    		total += mask.r;&#xD;&#xA;    		total += mask.g;&#xD;&#xA;    		total += mask.b;&#xD;&#xA;    &#xD;&#xA;    		local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.distance == -1)&#xD;&#xA;    			break;&#xD;&#xA;    &#xD;&#xA;    		hitPos = o + d * rayPayload.distance;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.color.r == 1.0 &amp;&amp; rayPayload.color.g == 1.0 &amp;&amp; rayPayload.color.b == 1.0)&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    		vec3 o_reflect = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    		vec3 d_reflect = reflect(d, rayPayload.normal);&#xD;&#xA;    &#xD;&#xA;    		vec3 temp_o = o_reflect;&#xD;&#xA;    		vec3 temp_d = d_reflect;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.reflector &lt; 1.0) // if less than fully reflective, do scattering&#xD;&#xA;    		{&#xD;&#xA;    			vec3 o_scatter = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    			vec3 d_scatter = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;    &#xD;&#xA;    			temp_o = mix(temp_o, o_scatter, 1.0 - rayPayload.reflector);&#xD;&#xA;    			temp_d = mix(temp_d, d_scatter, 1.0 - rayPayload.reflector);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		return rayPayload.opacity;&#xD;&#xA;    &#xD;&#xA;    		if(rayPayload.opacity &lt; 1.0) // if partially transparent, do refraction&#xD;&#xA;    		{&#xD;&#xA;    			vec3 o_transparent = vec3(0.0);&#xD;&#xA;    			vec3 d_transparent = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    			// Incoming&#xD;&#xA;    			if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;    			{&#xD;&#xA;    				o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    				d_transparent = refract(d, rayPayload.normal, eta);&#xD;&#xA;    			}&#xD;&#xA;    			else // Outgoing&#xD;&#xA;    			{&#xD;&#xA;    				vec3 temp_dir = refract(d, -rayPayload.normal, 1.0 / eta);&#xD;&#xA;    &#xD;&#xA;    				if(temp_dir != vec3(0.0))&#xD;&#xA;    				{&#xD;&#xA;    					o_transparent = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = temp_dir;&#xD;&#xA;    				}&#xD;&#xA;    				else&#xD;&#xA;    				{&#xD;&#xA;    					// total internal reflection&#xD;&#xA;    					o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = reflect(d, -rayPayload.normal);&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			temp_o = mix(temp_o, o_transparent, 1.0 - rayPayload.opacity);&#xD;&#xA;    			temp_d = mix(temp_d, d_transparent, 1.0 - rayPayload.opacity);&#xD;&#xA;    		}&#xD;&#xA;    			&#xD;&#xA;    		o = temp_o;&#xD;&#xA;    		d = normalize(temp_d);&#xD;&#xA;    		&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	final_pos = hitPos;&#xD;&#xA;    	rayPayload = r;&#xD;&#xA;    	return ret_colour / total;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;When I make the statement `return rayPayload.opacity;` it returns the following image, which is what I expect:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3JVtR.png&#xD;&#xA;&#xD;&#xA;However, if you comment out that return statement, the if statement on the next line is never run, even though it's obviously not 1.0 in some parts of the image. It's the strangest problem.&#xD;&#xA;&#xD;&#xA;The full code is at: https://github.com/sjhalayka/cornell_box_textured&#xD;&#xA;&#xD;&#xA;Basically, I have reflection caustics working, but I cannot get refraction caustics to work yet (in the new version 2.0 of my path tracer).&#xD;&#xA;&#xD;&#xA;Any big errors that I'm not seeing here?&#xD;&#xA;&#xD;&#xA;Thanks for your time.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41836" PostHistoryTypeId="2" PostId="13723" RevisionGUID="e70a305e-7831-4476-9dbc-5ec960632ebb" CreationDate="2023-09-21T09:57:38.687" UserId="13273" Text="I have a 3D geometry (an asteroid) that is to be tessellated with respect to the camera position. Each vertex in the original mesh has a unique position and is stored once (VBO with IBO)!&#xD;&#xA;&#xD;&#xA;In the evaluation phase of the tessellation, I shift the vertices with several layers of Perlin noise, curved PN triangles, and some crater kernels. So that the normal vector for each vertex cannot be computed analytically. Moreover, there is no way to interpolate the vertex parameters of the tessellation evaluation for the next stage. (At least I have not found such an interpolation option)&#xD;&#xA;&#xD;&#xA;For this reason, I considered disabling the rasterization and storing the vertices (with position/UV/normal) in an SSBO buffer as a later VBO. The triangle index connections are also stored in a separate SSBO as a later IBO. Similar to transformation feedback.&#xD;&#xA;&#xD;&#xA;    struct Vertex&#xD;&#xA;    {&#xD;&#xA;        vec4 position;&#xD;&#xA;        ivec4 normal; //here ivec4 is used to be able to do atomicAdd(). The normal vector is NOT normalized!&#xD;&#xA;        vec4 additionalInformation; //in here I can store UV coordinates or other information&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After generating the VBO and IBO, and before rendering these VBO/IBO, I want to add an additional compute shader to compute the normal vectors of each vertex with respect to the adjacent triangles.&#xD;&#xA;&#xD;&#xA;To do this, each compute shader-invocation loads a triangle from the IBO and uses a hash function to find the three vertex information (VBO). Compute the three angles and the normal vector of the triangle. Then the normal vector is multiplied by $1000 * angle_{rad}$ to get high numbers to store the normal vector in integer variables (atomicAdd) in the VBO buffer.&#xD;&#xA;&#xD;&#xA;Thus, when rendering the created VBO/IBO later, the shader only needs to load the integer (non-normalized) normal vector, store it in a vec3 and normalize it, and the surface can be rendered with interpolated normal vectors.&#xD;&#xA;&#xD;&#xA;To do this, several problems have to be solved:&#xD;&#xA;&#xD;&#xA;**Problems I was able to solve:**&#xD;&#xA;&#xD;&#xA; - Tessellation evaluation: generation of a unique vertexID per created vertex of a patch (triangle)&#xD;&#xA; - Tessellation evaluation: Generation of the IBO connections&#xD;&#xA;&#xD;&#xA;**Problems that need to be solved:**.&#xD;&#xA;&#xD;&#xA;I don't need hashing for vertices that are inside the triangle patch... because the IBO point directly to the VBO indexes. But at the three vertex corners and three edges of each triangle patch, the vertices would be stored multiple times. So normal interpolation would only work for faces that are not edge or corner faces of the original mesh. That is, the resulting image would look smooth, only the edges of those faces would look edgy....&#xD;&#xA;&#xD;&#xA;I thought about this for a long time and came to the conclusion that only the edge and corner points need to be hashed. But what should the hash key look like?&#xD;&#xA;&#xD;&#xA;I came up with 3 solutions:&#xD;&#xA;&#xD;&#xA;I just want to have a 32-bit hash key for performance and atomic function reasons.&#xD;&#xA;&#xD;&#xA; 1. the 3D position is hashed by taking 10/11/11 bits from each mantissa (x,y,z) and storing them in a 32-bit integer hash value. I think the mantissa is the right choice because the exponent is very often identical when two vertices are close to each other.&#xD;&#xA; 2. combine the two patch corner vertex IDs in the following way: 13 bits of the smaller vertex ID + 13 bits of the larger vertex ID + 6 bits of the outer tessellation ID (values: 0 - 63). The problem with this is that with the 13 bits of vertexID, I can only have a input mesh with a maximum of 8192 vertices. Which is way too small :(.&#xD;&#xA; 3. do it as in option 2. with the following changes: Take 23 bits of the smaller vertexID + 6 bits of the outer tessellation id (values: 0 - 63) + 3 bits for an edgeID. Thus, each vertex in the original mesh can be connected to a maximum of 8 other vertices (3 bits) to be computed when loading the mesh to the GPU. Therefore, the original mesh can have 8,388,608 vertices, which is still not enough. I don't like this option because calculating the pre-edge connection in the first step and loading this information into the shader, as well as being limited to 8 million vertices and 8 connections, is a significant overhead and restriction.&#xD;&#xA;&#xD;&#xA;Do you have a better idea how to hash the patch corners / edges vertices?&#xD;&#xA;&#xD;&#xA;Or do you have a better idea how I can access these generated vertices without hashing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="41838" PostHistoryTypeId="1" PostId="13723" RevisionGUID="e70a305e-7831-4476-9dbc-5ec960632ebb" CreationDate="2023-09-21T09:57:38.687" UserId="13273" Text="interpolated normal vectors after tessellation. How to hash patch corner / edge vertices?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41839" PostHistoryTypeId="3" PostId="13723" RevisionGUID="e70a305e-7831-4476-9dbc-5ec960632ebb" CreationDate="2023-09-21T09:57:38.687" UserId="13273" Text="|opengl|glsl|geometry|interpolation|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41840" PostHistoryTypeId="2" PostId="13724" RevisionGUID="882fb970-7803-424f-959e-c72f24db09cf" CreationDate="2023-09-21T10:03:01.673" UserId="13273" Text="you don't need to build the tree again! Even when you translate / rotate / scale the object. The trick is to use a transformation matrix for the object. When you want to check, if e.g. a ray is hitting your object, you only need to transform the ray to the object space by multiplying the ray with the inverse transformation matrix.&#xD;&#xA;&#xD;&#xA;So the ray will be transformed relative to the objects position / rotation / scale. The tree always stays the same.&#xD;&#xA;&#xD;&#xA;The tree only needs to be updated, when the mesh is deformed. (e.g. softbodies)" ContentLicense="CC BY-SA 4.0" />
  <row Id="41842" PostHistoryTypeId="5" PostId="13724" RevisionGUID="5de992c0-f78c-4220-b389-268c32c543a0" CreationDate="2023-09-21T10:10:29.127" UserId="13273" Comment="added 42 characters in body" Text="you don't need to build the tree again! Even when you translate / rotate / scale the object. The trick is to use a transformation matrix for the object. When you want to check, if e.g. a ray is hitting your object, you only need to transform the ray to the object space by multiplying the ray with the inverse transformation matrix.&#xD;&#xA;&#xD;&#xA;So the ray will be transformed relative to the objects position / rotation / scale. The tree always stays the same.&#xD;&#xA;&#xD;&#xA;Same for a plain test or frustum test.&#xD;&#xA;&#xD;&#xA;The tree only needs to be updated, when the mesh is deformed. (e.g. softbodies)" ContentLicense="CC BY-SA 4.0" />
  <row Id="41843" PostHistoryTypeId="5" PostId="13721" RevisionGUID="0dd034ba-4a58-4cc2-a1cf-322bd50b1df3" CreationDate="2023-09-21T16:57:47.907" UserId="20568" Comment="added code" Text="I am trying to make Terraria like game using WGPU and rust. There are gaps between tiles. The gaps are bigger and more common as I get far from world center. I've read that nearest filtering should help, hovewer I am already using it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yXKW6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ksEIv.png&#xD;&#xA;&#xD;&#xA;This is my code for calculating tile positions:&#xD;&#xA;```&#xD;&#xA;glam::vec3(                            &#xD;&#xA;    self.world_center.x + chunk_size * &#xD;&#xA;    (chunk.coords.0 as f32) - &#xD;&#xA;    chunk_size / 2.0 + self.block_size &#xD;&#xA;    / 2.0 + self.block_size * (x as &#xD;&#xA;    f32),&#xD;&#xA;    self.world_center.y + chunk_size * &#xD;&#xA;    (chunk.coords.1 as f32) - &#xD;&#xA;    chunk_size / 2.0 + self.block_size &#xD;&#xA;    / 2.0 + self.block_size * (y as &#xD;&#xA;    f32),&#xD;&#xA;    0.0,&#xD;&#xA;)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Thanks for your response!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41844" PostHistoryTypeId="5" PostId="13721" RevisionGUID="8ec6feac-ed3e-4f49-8189-b527e726740e" CreationDate="2023-09-21T17:18:36.697" UserId="20568" Comment="added 83 characters in body" Text="I am trying to make Terraria like game using WGPU and rust. There are gaps between tiles. The gaps are bigger and more common as I get far from world center. I've read that nearest filtering should help, hovewer I am already using it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yXKW6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/ksEIv.png&#xD;&#xA;&#xD;&#xA;This is my code for calculating tile positions:&#xD;&#xA;```&#xD;&#xA;glam::vec3(                            &#xD;&#xA;    self.world_center.x + chunk_size * &#xD;&#xA;    (chunk.coords.0 as f32) - &#xD;&#xA;    chunk_size / 2.0 + self.block_size &#xD;&#xA;    / 2.0 + self.block_size * (x as &#xD;&#xA;    f32),&#xD;&#xA;    self.world_center.y + chunk_size * &#xD;&#xA;    (chunk.coords.1 as f32) - &#xD;&#xA;    chunk_size / 2.0 + self.block_size &#xD;&#xA;    / 2.0 + self.block_size * (y as &#xD;&#xA;    f32),&#xD;&#xA;    0.0,&#xD;&#xA;)&#xD;&#xA;```&#xD;&#xA;x and y is a position of a tile in a  chunk. Tile (0, 0) is on the bottom left.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks for your response!&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41845" PostHistoryTypeId="2" PostId="13725" RevisionGUID="e441a6fa-324a-4813-a6ce-06916e0c987f" CreationDate="2023-09-21T17:45:03.697" UserId="6041" Text="I am reading on [&quot;Specular Manifold Sampling&quot;][1] paper with the implementaion(for the simple case) [here on Mitsuba at github][2]. As part of the calculation it needs to compute &#xD;&#xA;&#xD;&#xA;1. partial derivatives of spherical angles w.r.t surface u, v. which is calculated in [this method][3]&#xD;&#xA;&#xD;&#xA;    Basically given a normalized vector `w(x,y,z)` and it's partial derivatives `dw/du` and `dw/dv` vectors, how do you calculate:&#xD;&#xA;&#xD;&#xA;   `dtheta/du`,  `dtheta/dv` , `dphi/du` , `dphi/dv` ?  (theta and phi are spherical coords of w)&#xD;&#xA;&#xD;&#xA;2. partial derivatives of refracted ray w.r.t surface u, v [implemented here][4]. ie. Given an incoming ray, surface normal and their partial derivative vectors w.r.t to surface u,v, what are partial derivatives of the refracted ray w.r.t u and v?&#xD;&#xA;&#xD;&#xA;I guess it's using chain rule but I don't fully understand the math behind these two.&#xD;&#xA;&#xD;&#xA;For example for the first case :&#xD;&#xA;`dtheta/du = dtheta/dz . dz/du` and  `dtheta/dz` comes from derivative of `theta = cos^-1(z)` w.r.t `z`. But I don't understand how `dphi/du` is calculated.&#xD;&#xA;&#xD;&#xA;  [1]: http://rgl.epfl.ch/publications/Zeltner2020Specular&#xD;&#xA;  [2]: https://github.com/tizian/specular-manifold-sampling/blob/master/src/librender/manifold_ss.cpp&#xD;&#xA;  [3]: https://github.com/tizian/specular-manifold-sampling/blob/1f0e40342a8760450d5aa6202ea096feaa70256a/include/mitsuba/render/manifold.h#L430&#xD;&#xA;  [4]: https://github.com/tizian/specular-manifold-sampling/blob/1f0e40342a8760450d5aa6202ea096feaa70256a/include/mitsuba/render/manifold.h#L384" ContentLicense="CC BY-SA 4.0" />
  <row Id="41847" PostHistoryTypeId="1" PostId="13725" RevisionGUID="e441a6fa-324a-4813-a6ce-06916e0c987f" CreationDate="2023-09-21T17:45:03.697" UserId="6041" Text="Partial Derivatives of Spherical Angles and Refracted Ray w.r.t Surface u,v" ContentLicense="CC BY-SA 4.0" />
  <row Id="41848" PostHistoryTypeId="3" PostId="13725" RevisionGUID="e441a6fa-324a-4813-a6ce-06916e0c987f" CreationDate="2023-09-21T17:45:03.697" UserId="6041" Text="|rendering|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41850" PostHistoryTypeId="50" PostId="12900" RevisionGUID="67587eb4-fa93-4579-8722-ed27ef584361" CreationDate="2023-09-22T07:04:30.523" UserId="-1" />
  <row Id="41851" PostHistoryTypeId="5" PostId="13723" RevisionGUID="d7acbd3e-11be-41c3-af42-64213859c949" CreationDate="2023-09-22T07:33:26.840" UserId="13273" Comment="deleted 1 character in body" Text="I have a 3D geometry (an asteroid) that is to be tessellated with respect to the camera position. Each vertex in the original mesh has a unique position and is stored once (VBO with IBO)&#xD;&#xA;&#xD;&#xA;In the evaluation phase of the tessellation, I shift the vertices with several layers of Perlin noise, curved PN triangles, and some crater kernels. So that the normal vector for each vertex cannot be computed analytically. Moreover, there is no way to interpolate the vertex parameters of the tessellation evaluation for the next stage. (At least I have not found such an interpolation option)&#xD;&#xA;&#xD;&#xA;For this reason, I considered disabling the rasterization and storing the vertices (with position/UV/normal) in an SSBO buffer as a later VBO. The triangle index connections are also stored in a separate SSBO as a later IBO. Similar to transformation feedback.&#xD;&#xA;&#xD;&#xA;    struct Vertex&#xD;&#xA;    {&#xD;&#xA;        vec4 position;&#xD;&#xA;        ivec4 normal; //here ivec4 is used to be able to do atomicAdd(). The normal vector is NOT normalized!&#xD;&#xA;        vec4 additionalInformation; //in here I can store UV coordinates or other information&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;After generating the VBO and IBO, and before rendering these VBO/IBO, I want to add an additional compute shader to compute the normal vectors of each vertex with respect to the adjacent triangles.&#xD;&#xA;&#xD;&#xA;To do this, each compute shader-invocation loads a triangle from the IBO and uses a hash function to find the three vertex information (VBO). Compute the three angles and the normal vector of the triangle. Then the normal vector is multiplied by $1000 * angle_{rad}$ to get high numbers to store the normal vector in integer variables (atomicAdd) in the VBO buffer.&#xD;&#xA;&#xD;&#xA;Thus, when rendering the created VBO/IBO later, the shader only needs to load the integer (non-normalized) normal vector, store it in a vec3 and normalize it, and the surface can be rendered with interpolated normal vectors.&#xD;&#xA;&#xD;&#xA;To do this, several problems have to be solved:&#xD;&#xA;&#xD;&#xA;**Problems I was able to solve:**&#xD;&#xA;&#xD;&#xA; - Tessellation evaluation: generation of a unique vertexID per created vertex of a patch (triangle)&#xD;&#xA; - Tessellation evaluation: Generation of the IBO connections&#xD;&#xA;&#xD;&#xA;**Problems that need to be solved:**.&#xD;&#xA;&#xD;&#xA;I don't need hashing for vertices that are inside the triangle patch... because the IBO point directly to the VBO indexes. But at the three vertex corners and three edges of each triangle patch, the vertices would be stored multiple times. So normal interpolation would only work for faces that are not edge or corner faces of the original mesh. That is, the resulting image would look smooth, only the edges of those faces would look edgy....&#xD;&#xA;&#xD;&#xA;I thought about this for a long time and came to the conclusion that only the edge and corner points need to be hashed. But what should the hash key look like?&#xD;&#xA;&#xD;&#xA;I came up with 3 solutions:&#xD;&#xA;&#xD;&#xA;I just want to have a 32-bit hash key for performance and atomic function reasons.&#xD;&#xA;&#xD;&#xA; 1. the 3D position is hashed by taking 10/11/11 bits from each mantissa (x,y,z) and storing them in a 32-bit integer hash value. I think the mantissa is the right choice because the exponent is very often identical when two vertices are close to each other.&#xD;&#xA; 2. combine the two patch corner vertex IDs in the following way: 13 bits of the smaller vertex ID + 13 bits of the larger vertex ID + 6 bits of the outer tessellation ID (values: 0 - 63). The problem with this is that with the 13 bits of vertexID, I can only have a input mesh with a maximum of 8192 vertices. Which is way too small :(.&#xD;&#xA; 3. do it as in option 2. with the following changes: Take 23 bits of the smaller vertexID + 6 bits of the outer tessellation id (values: 0 - 63) + 3 bits for an edgeID. Thus, each vertex in the original mesh can be connected to a maximum of 8 other vertices (3 bits) to be computed when loading the mesh to the GPU. Therefore, the original mesh can have 8,388,608 vertices, which is still not enough. I don't like this option because calculating the pre-edge connection in the first step and loading this information into the shader, as well as being limited to 8 million vertices and 8 connections, is a significant overhead and restriction.&#xD;&#xA;&#xD;&#xA;Do you have a better idea how to hash the patch corners / edges vertices?&#xD;&#xA;&#xD;&#xA;Or do you have a better idea how I can access these generated vertices without hashing?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="41852" PostHistoryTypeId="50" PostId="13651" RevisionGUID="c73fa5df-703c-41d7-97e9-3118338ccfbd" CreationDate="2023-09-22T12:00:21.720" UserId="-1" />
  <row Id="41853" PostHistoryTypeId="2" PostId="13726" RevisionGUID="c22cc850-92c1-4826-a963-e930b623b698" CreationDate="2023-09-22T14:16:11.443" UserId="6" Text="I know that vertex attributes sourced from vertex buffers in OpenGL need to adhere to the basic alignment requirements of their base types, so e.g. 4 bytes for floats or uints. However, I am unable to find much clear information about the general alignment requirements of vertex attributes beyond (or rather below) that. Or put more concretely, **are byte-sized attributes allowed to be aligned only to byte offsets** (as well as being tightly packed as the only attributes in their buffer)?&#xD;&#xA;&#xD;&#xA;There are some claims that each individual attribute should be 4-byte aligned, as in [this article from the GL wiki](https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices). However, that article looks a little outdated in general and also doesn't really back these claims in any way (or clarify if that is a &quot;should&quot; or a &quot;shall&quot;). I wasn't really able to find something about it in the GL specification, but admittedly haven't read it end-to-end. So **is there any clear statement if individual attributes are allowed to be byte-aligned/packed?** While specific hardware experience would certainly be interesting, a clear yes/no from the spec would be optimal.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Now I know such sub-word alignment, even if allowed, might not exhibit the best performance characteristics when compared to bigger chunks. However, performance isn't of the most critical concern here, rather than making the most of the available memory. I also could basically implement such tightly packed attributes myself by just putting them as `uint`s into an SSBO instead and pulling them myself in the vertex shader with some bit-twiddling on the vertex ID. But it would still be nice for the project workflow if it was reliably doable within the normal GL vertex attribute pipeline." ContentLicense="CC BY-SA 4.0" />
  <row Id="41855" PostHistoryTypeId="1" PostId="13726" RevisionGUID="c22cc850-92c1-4826-a963-e930b623b698" CreationDate="2023-09-22T14:16:11.443" UserId="6" Text="Vertex attribute alignment &lt;4 bytes" ContentLicense="CC BY-SA 4.0" />
  <row Id="41856" PostHistoryTypeId="3" PostId="13726" RevisionGUID="c22cc850-92c1-4826-a963-e930b623b698" CreationDate="2023-09-22T14:16:11.443" UserId="6" Text="|opengl|vertex-buffer-object|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41857" PostHistoryTypeId="50" PostId="13346" RevisionGUID="aeaddcc4-4be5-494c-9a98-7502f3a90e9c" CreationDate="2023-09-23T05:07:50.893" UserId="-1" />
  <row Id="41858" PostHistoryTypeId="50" PostId="10509" RevisionGUID="f79aab35-9628-4908-b92a-a1e583d386fe" CreationDate="2023-09-23T08:00:50.100" UserId="-1" />
  <row Id="41859" PostHistoryTypeId="5" PostId="9177" RevisionGUID="63483ccd-310c-4dd8-ae65-5c7f6f7d7dbc" CreationDate="2023-09-23T09:34:39.947" UserId="6" Comment="deleted 15 characters in body" Text="When binding an attribute index using glVertexAttribPointer, what happens when a later bound program does not contain an attribute at said index?&#xD;&#xA;&#xD;&#xA;Is the behaviour undefined, or is the attribute ignored altogether?&#xD;&#xA;&#xD;&#xA;I have searched the docs quite extensively, and have not been able to find much info about the link between programs and dynamic attribute bindings." ContentLicense="CC BY-SA 4.0" />
  <row Id="41860" PostHistoryTypeId="2" PostId="13727" RevisionGUID="658e293e-0a39-423e-a3d1-d38b73fa799a" CreationDate="2023-09-23T09:46:42.530" UserId="6" Text="&gt; ...have not been able to find much info about the link between programs and dynamic attribute bindings.&#xD;&#xA;&#xD;&#xA;That is because there really is no link between them. Your vertex array data, i.e. the enabled attribute arrays and the buffers which they source their data from, don't really care at all which future shader programs they'll be used with.&#xD;&#xA;&#xD;&#xA;If they enable attribute arrays that are not needed by the program, that data is just ignored. It's not like the attributes are read from the buffers and will spill out of your GPU when the program doesn't consume them ;-), they're just not read at all.&#xD;&#xA;&#xD;&#xA;If on the other hand the program uses attributes for which you don't have an array/buffer enabled, that isn't an error either. Instead, the attribute data will be sourced from a single value that is constant over the entire draw call and can be set with the often somewhat forgotten [`glVertexAttrib`](https://registry.khronos.org/OpenGL-Refpages/gl4/html/glVertexAttrib.xhtml) functions." ContentLicense="CC BY-SA 4.0" />
  <row Id="41862" PostHistoryTypeId="2" PostId="13728" RevisionGUID="c2ac0be2-31d3-4402-99ce-18b0a5d17f36" CreationDate="2023-09-23T10:12:38.200" UserId="20568" Text="I've figured it out. It's bug in wgpu, if I use OpenGL backend everything is ok. The problem only occurs when using Vulkan." ContentLicense="CC BY-SA 4.0" />
  <row Id="41865" PostHistoryTypeId="50" PostId="12995" RevisionGUID="19c139c1-a1a7-4acd-8d9e-bf64001e5723" CreationDate="2023-09-23T13:06:20.713" UserId="-1" />
  <row Id="41866" PostHistoryTypeId="4" PostId="4550" RevisionGUID="3123a6e3-0553-4853-a0ab-98c2f7ff63d2" CreationDate="2023-09-23T18:58:28.243" UserId="5852" Comment="edited title" Text="How do double-buffers work in opengl?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41867" PostHistoryTypeId="2" PostId="13729" RevisionGUID="abad370c-a4bf-4384-8d4f-035b57553aff" CreationDate="2023-09-23T19:27:07.800" UserId="18408" Text="How can I avoid having to declare the sampler outside of the if statement in this shader code sample?&#xD;&#xA;&#xD;&#xA;    let sample = textureSample(r_texture, r_sampler, in.tex_coords);&#xD;&#xA;    if in.use_texture {&#xD;&#xA;        return sample * in.color;&#xD;&#xA;    } else {&#xD;&#xA;        return in.color;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This came up as an answer to another of my [questions][1], and it was suggested that the sampler needed to be declared here due to uniform control flow, but that it could be avoided.&#xD;&#xA;&#xD;&#xA;How to avoid it?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/13682/conditionally-sample-from-texture-in-shader/13683#13683" ContentLicense="CC BY-SA 4.0" />
  <row Id="41869" PostHistoryTypeId="1" PostId="13729" RevisionGUID="abad370c-a4bf-4384-8d4f-035b57553aff" CreationDate="2023-09-23T19:27:07.800" UserId="18408" Text="How to avoid declaring sampler outside of statement?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41870" PostHistoryTypeId="3" PostId="13729" RevisionGUID="abad370c-a4bf-4384-8d4f-035b57553aff" CreationDate="2023-09-23T19:27:07.800" UserId="18408" Text="|shader|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41871" PostHistoryTypeId="2" PostId="13730" RevisionGUID="1598927d-1d06-40f4-b06b-e94970d4e21d" CreationDate="2023-09-23T22:27:22.807" UserId="445" Text="## Background&#xD;&#xA;&#xD;&#xA;In order to support [mipmapping](https://en.wikipedia.org/wiki/Mipmap), the texture sampling system needs to know what scale the texture is being displayed at. In order to determine that scale automatically, the _derivatives_ (or “gradient”) of the texture coordinates are used. The way GPUs calculate derivatives is by comparing the results of the calculations performed in one fragment to adjacent fragments.&#xD;&#xA;&#xD;&#xA;The reason you can't put `textureSample` inside of `if` is because it is possible that the `if` takes different branches on different pixels, and so the derivative won't exist. “Uniform control flow” means “all fragments are guaranteed to execute this code”.&#xD;&#xA;&#xD;&#xA;## Possible solutions&#xD;&#xA;&#xD;&#xA;* If `r_texture` has no mipmaps, or if `r_sampler` is configured to prevent using them, then you don't need to select a mipmap level. Use `textureSampleLevel(r_texture, r_sampler, in.tex_coords, 0)` — the additional argument is the mipmap level, and 0 means the full-resolution texture, which is all you want in this case.&#xD;&#xA;&#xD;&#xA;* If you do wish to use mipmaps, then you can compute the relevant derivatives outside of the `if`, and use them inside:&#xD;&#xA;&#xD;&#xA;    ```wgsl&#xD;&#xA;    let ddx = dpdx(in.tex_coords);&#xD;&#xA;    let ddy = dpdy(in.tex_coords);&#xD;&#xA;    if in.use_texture {&#xD;&#xA;        let sample = textureSampleGrad(r_texture, r_sampler, in.tex_coords, ddx, ddy);&#xD;&#xA;        return sample * in.color;&#xD;&#xA;    } else {&#xD;&#xA;        return in.color;&#xD;&#xA;    }&#xD;&#xA;    ```&#xD;&#xA;&#xD;&#xA;    This is basically doing what `textureSample` would do implicitly, but moving just the parts that can't be in the `if` outside.&#xD;&#xA;&#xD;&#xA;## Language notes&#xD;&#xA;&#xD;&#xA;The code in this answer is [WGSL](https://www.w3.org/TR/WGSL/). Equivalent functions in GLSL:&#xD;&#xA;&#xD;&#xA;| WGSL | GLSL |&#xD;&#xA;|-----|-----|&#xD;&#xA;| textureSample() | texture() |&#xD;&#xA;| textureSampleGrad() | textureGrad() |&#xD;&#xA;| dpdx() | dFdx() |&#xD;&#xA;| dpdy() | dFdy() |&#xD;&#xA;&#xD;&#xA;Also, [here's another introduction to the same concepts from the Khronos OpenGL wiki (which uses GLSL)](https://www.khronos.org/opengl/wiki/Sampler_\(GLSL\)#Non-uniform_flow_control)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41873" PostHistoryTypeId="2" PostId="13731" RevisionGUID="fd740b27-de37-459a-9fb8-d171e88b2354" CreationDate="2023-09-24T18:30:38.150" UserId="19251" Text="I am implementing fresnel reflections for materials in my renderer.  &#xD;&#xA;Does it make sense for metals?&#xD;&#xA;&#xD;&#xA;Here my implementation:&#xD;&#xA;&#xD;&#xA;    float BlinnPhong(const DistributionFunction::SampleInput&amp; input, float shininess)&#xD;&#xA;    {&#xD;&#xA;	    const float normalizationFactor = (shininess + 8.0f) * Math::InvPi8.getValue();&#xD;&#xA;	    return std::pow(input.HoN, shininess) * normalizationFactor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float ComputeFresnel0(float ior)&#xD;&#xA;    {&#xD;&#xA;	    return std::powf((ior - 1.0f) / (ior + 1.0f), 2.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float ComputeFresnel(float F0, float HoV)&#xD;&#xA;    {&#xD;&#xA;	    return F0 + (1.0f - F0) * pow(1.0f - HoV, 5.0f);&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;    // Here: the sampling function.&#xD;&#xA;    RGBFColor SampleBrdf(const DistributionFunction::SampleInput&amp; sampleInput)&#xD;&#xA;    {&#xD;&#xA;	    static const float ior = 1.5f;&#xD;&#xA;	    const float F0 = ComputeFresnel0(ior);&#xD;&#xA;	    const float fresnel = ComputeFresnel(F0, sampleInput.HoV);  &#xD;&#xA;&#xD;&#xA;	    static const float shininess = 120.0f;&#xD;&#xA;	    const float specularFactor = BlinnPhong(sampleInput, shininess);&#xD;&#xA;&#xD;&#xA;	    static const RGBFColor baseColor = RGBFColor(1.0f);&#xD;&#xA;&#xD;&#xA;	    return baseColor * specularFactor * fresnel * sampleInput.NoL; // Multiply by distSampleInput.NoL here for purpose. &#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="41875" PostHistoryTypeId="1" PostId="13731" RevisionGUID="fd740b27-de37-459a-9fb8-d171e88b2354" CreationDate="2023-09-24T18:30:38.150" UserId="19251" Text="Does fresnel reflexions make sense for metals?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41876" PostHistoryTypeId="3" PostId="13731" RevisionGUID="fd740b27-de37-459a-9fb8-d171e88b2354" CreationDate="2023-09-24T18:30:38.150" UserId="19251" Text="|brdf|pbr|specular|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41877" PostHistoryTypeId="4" PostId="13731" RevisionGUID="9f628a00-d4dd-49aa-b405-71490bcb1947" CreationDate="2023-09-24T18:32:09.063" UserId="19251" Comment="edited title" Text="Does fresnel reflexion make sense for metals?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41878" PostHistoryTypeId="5" PostId="13731" RevisionGUID="04f3afe0-8359-4066-b5a0-a5c1d4538c81" CreationDate="2023-09-24T18:41:17.027" UserId="19251" Comment="added 5 characters in body" Text="I am implementing fresnel reflections for materials in my renderer.  &#xD;&#xA;Does it make sense for metals?&#xD;&#xA;&#xD;&#xA;Here my implementation:&#xD;&#xA;&#xD;&#xA;    float BlinnPhong(const DistributionFunction::SampleInput&amp; input, float shininess)&#xD;&#xA;    {&#xD;&#xA;	    const float normalizationFactor = (shininess + 8.0f) * Math::InvPi8.getValue();&#xD;&#xA;	    return std::pow(input.HoN, shininess) * normalizationFactor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float ComputeFresnel0(float ior)&#xD;&#xA;    {&#xD;&#xA;	    return std::powf((ior - 1.0f) / (ior + 1.0f), 2.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float ComputeFresnel(float F0, float HoV)&#xD;&#xA;    {&#xD;&#xA;	    return F0 + (1.0f - F0) * pow(1.0f - HoV, 5.0f);&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;    // Here: the sampling function.&#xD;&#xA;    RGBFColor SampleMetalBrdf(const DistributionFunction::SampleInput&amp; sampleInput)&#xD;&#xA;    {&#xD;&#xA;	    static const float ior = 1.5f;&#xD;&#xA;	    const float F0 = ComputeFresnel0(ior);&#xD;&#xA;	    const float fresnel = ComputeFresnel(F0, sampleInput.HoV);  &#xD;&#xA;&#xD;&#xA;	    static const float shininess = 120.0f;&#xD;&#xA;	    const float specularFactor = BlinnPhong(sampleInput, shininess);&#xD;&#xA;&#xD;&#xA;	    static const RGBFColor baseColor = RGBFColor(1.0f);&#xD;&#xA;&#xD;&#xA;	    return baseColor * specularFactor * fresnel * sampleInput.NoL; // Multiply by distSampleInput.NoL here for purpose. &#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="41879" PostHistoryTypeId="5" PostId="13731" RevisionGUID="7cc2be86-f18a-408d-af2b-1f1f07df1762" CreationDate="2023-09-24T18:42:09.603" UserId="19251" Comment="added 4 characters in body" Text="I am implementing fresnel reflections for materials in my renderer.  &#xD;&#xA;**Does it make sense for metals?**&#xD;&#xA;&#xD;&#xA;Here my implementation:&#xD;&#xA;&#xD;&#xA;    float BlinnPhong(const DistributionFunction::SampleInput&amp; input, float shininess)&#xD;&#xA;    {&#xD;&#xA;	    const float normalizationFactor = (shininess + 8.0f) * Math::InvPi8.getValue();&#xD;&#xA;	    return std::pow(input.HoN, shininess) * normalizationFactor;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float ComputeFresnel0(float ior)&#xD;&#xA;    {&#xD;&#xA;	    return std::powf((ior - 1.0f) / (ior + 1.0f), 2.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float ComputeFresnel(float F0, float HoV)&#xD;&#xA;    {&#xD;&#xA;	    return F0 + (1.0f - F0) * pow(1.0f - HoV, 5.0f);&#xD;&#xA;    }  &#xD;&#xA;&#xD;&#xA;    // Here: the sampling function.&#xD;&#xA;    RGBFColor SampleMetalBrdf(const DistributionFunction::SampleInput&amp; sampleInput)&#xD;&#xA;    {&#xD;&#xA;	    static const float ior = 1.5f;&#xD;&#xA;	    const float F0 = ComputeFresnel0(ior);&#xD;&#xA;	    const float fresnel = ComputeFresnel(F0, sampleInput.HoV);  &#xD;&#xA;&#xD;&#xA;	    static const float shininess = 120.0f;&#xD;&#xA;	    const float specularFactor = BlinnPhong(sampleInput, shininess);&#xD;&#xA;&#xD;&#xA;	    static const RGBFColor baseColor = RGBFColor(1.0f);&#xD;&#xA;&#xD;&#xA;	    return baseColor * specularFactor * fresnel * sampleInput.NoL; // Multiply by distSampleInput.NoL here for purpose. &#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="41880" PostHistoryTypeId="2" PostId="13732" RevisionGUID="0ffdaf82-3388-4fe1-99f2-c6d6d1fc53e9" CreationDate="2023-09-25T02:14:04.383" UserId="19537" Text="I think this question is a bit tricky to answer, since I have some seemingly contradictory knowledge about your implementation. If I recall correctly, you are using Schlick approximation for the Fresnel term, which is:&#xD;&#xA;- Used for physically based anisotropic surface reflection, like [FresnelBlend BRDF](https://collections.lib.utah.edu/dl_files/77/ea/77eac0c124401e935d08fd9208b98c0990cb078c.pdf), which matches closely with your code (the difference is that Blinn-Phong is replaced by microfacet distribution). This BRDF looks metallic and of course, it is used to model metallic surfaces.&#xD;&#xA;- Schlick approximation is designed for dieletric materials (glass / water, etc.), since conductor (metal) has different way to compute Fresnel term. The indices of refraction are simply (literally) complex. There are some paper stating that Schlick approximation produces erroneous results and should only be used for non-conductor surfaces.&#xD;&#xA;&#xD;&#xA;You see how things contradict here. I guess the answer for your question is:&#xD;&#xA;- If you want to model metallic (**metal-like**) surface, Schlick approximation (and hence your code) does make sense.&#xD;&#xA;- If you want to model metal (exact definition): no, it is not suggested to model metal this way. You can refer to [PBR-Book 8.2.1 Specular Reflection and Transmission](https://www.pbr-book.org/3ed-2018/Reflection_Models/Specular_Reflection_and_Transmission) for the modeling of conductor material.&#xD;&#xA;&#xD;&#xA;For the specific implementation (and possible bugs): why do you call this function `sample`? This looks like `evaluation` to me since you are not sampling Fresnel term or Blinn-Phong BRDF but evaluating them. This is minor though so you can ignore it." ContentLicense="CC BY-SA 4.0" />
  <row Id="41882" PostHistoryTypeId="50" PostId="8779" RevisionGUID="79e59d81-ddff-493f-93f4-e73c3d03c3a4" CreationDate="2023-09-25T18:09:36.203" UserId="-1" />
  <row Id="41883" PostHistoryTypeId="4" PostId="13731" RevisionGUID="f86ba94b-cded-4034-a0b0-1030b5beb4c1" CreationDate="2023-09-26T17:50:10.883" UserId="506" Comment="title spelling" Text="Does fresnel reflection make sense for metals?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41884" PostHistoryTypeId="5" PostId="13730" RevisionGUID="8acc8f34-6d73-4d3e-b55e-0559b79b5e1a" CreationDate="2023-09-26T20:19:27.710" UserId="445" Comment="fixed level type" Text="## Background&#xD;&#xA;&#xD;&#xA;In order to support [mipmapping](https://en.wikipedia.org/wiki/Mipmap), the texture sampling system needs to know what scale the texture is being displayed at. In order to determine that scale automatically, the _derivatives_ (or “gradient”) of the texture coordinates are used. The way GPUs calculate derivatives is by comparing the results of the calculations performed in one fragment to adjacent fragments.&#xD;&#xA;&#xD;&#xA;The reason you can't put `textureSample` inside of `if` is because it is possible that the `if` takes different branches on different pixels, and so the derivative won't exist. “Uniform control flow” means “all fragments are guaranteed to execute this code”.&#xD;&#xA;&#xD;&#xA;## Possible solutions&#xD;&#xA;&#xD;&#xA;* If `r_texture` has no mipmaps, or if `r_sampler` is configured to prevent using them, then you don't need to select a mipmap level. Use `textureSampleLevel(r_texture, r_sampler, in.tex_coords, 0.0)` — the additional argument is the mipmap level, and 0 means the full-resolution texture, which is all you want in this case.&#xD;&#xA;&#xD;&#xA;* If you do wish to use mipmaps, then you can compute the relevant derivatives outside of the `if`, and use them inside:&#xD;&#xA;&#xD;&#xA;    ```wgsl&#xD;&#xA;    let ddx = dpdx(in.tex_coords);&#xD;&#xA;    let ddy = dpdy(in.tex_coords);&#xD;&#xA;    if in.use_texture {&#xD;&#xA;        let sample = textureSampleGrad(r_texture, r_sampler, in.tex_coords, ddx, ddy);&#xD;&#xA;        return sample * in.color;&#xD;&#xA;    } else {&#xD;&#xA;        return in.color;&#xD;&#xA;    }&#xD;&#xA;    ```&#xD;&#xA;&#xD;&#xA;    This is basically doing what `textureSample` would do implicitly, but moving just the parts that can't be in the `if` outside.&#xD;&#xA;&#xD;&#xA;## Language notes&#xD;&#xA;&#xD;&#xA;The code in this answer is [WGSL](https://www.w3.org/TR/WGSL/). Equivalent functions in GLSL:&#xD;&#xA;&#xD;&#xA;| WGSL | GLSL |&#xD;&#xA;|-----|-----|&#xD;&#xA;| textureSample() | texture() |&#xD;&#xA;| textureSampleGrad() | textureGrad() |&#xD;&#xA;| dpdx() | dFdx() |&#xD;&#xA;| dpdy() | dFdy() |&#xD;&#xA;&#xD;&#xA;Also, [here's another introduction to the same concepts from the Khronos OpenGL wiki (which uses GLSL)](https://www.khronos.org/opengl/wiki/Sampler_\(GLSL\)#Non-uniform_flow_control)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41885" PostHistoryTypeId="2" PostId="13733" RevisionGUID="e08f23c9-7a35-4808-950a-20b11a2992de" CreationDate="2023-09-27T00:15:58.723" UserId="19251" Text="I am implementing fresnel reflections for materials in my renderer.  &#xD;&#xA;According to this [source][1], here the look I should obtain when rendering a sphere over a grey background:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**I have two implementations**. One of them is based on Cook Torrance model.  &#xD;&#xA;The implementations use theses helper functions:  &#xD;&#xA;&#xD;&#xA;	float ComputeFresnel0(float ior)&#xD;&#xA;	{&#xD;&#xA;		// @See: https://graphicscompendium.com/raytracing/11-fresnel-beer&#xD;&#xA;		return std::powf((ior - 1.0f ) / (ior + 1.0f), 2.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float ComputeFresnel(float F0, float NoV)&#xD;&#xA;	{&#xD;&#xA;		// @See: https://graphicscompendium.com/raytracing/11-fresnel-beer&#xD;&#xA;		return F0 + (1.0f - F0) * pow(1.0f - NoV, 5.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float BlinnPhong(const SampleInput&amp; input, float shininess)&#xD;&#xA;	{&#xD;&#xA;		//@See: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model&#xD;&#xA;		return std::pow(input.HoN, shininess);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;In term of output, here what i obtain:  &#xD;&#xA;&#xD;&#xA;**NO COOK-TORRANCE, I get this**:  &#xD;&#xA;*IOR = 1*  &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;&#xD;&#xA;*IOR = 4*  &#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Source code:&#xD;&#xA;&#xD;&#xA;	RGBFColor Evaluate_Brdf(const DistributionFunction::SampleInput&amp; distSampleInput, float ior)&#xD;&#xA;	{&#xD;&#xA;		// No diffuse. We are only interested in specular.&#xD;&#xA;		RGBFColor diffuse = RGBFColor(0.0f);&#xD;&#xA;&#xD;&#xA;		// Specular.&#xD;&#xA;		RGBFColor specular = RGBFColor(1.0f);&#xD;&#xA;		{&#xD;&#xA;			const float F0 = ComputeFresnel0(ior);&#xD;&#xA;			const float F = ComputeFresnel(F0, distSampleInput.NoV);&#xD;&#xA;&#xD;&#xA;			static const float shininesss = 256.0f;&#xD;&#xA;			const float specularFactor = F * BlinnPhong(distSampleInput, shininesss);&#xD;&#xA;&#xD;&#xA;			specular *= specularFactor;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return (diffuse + specular) * distSampleInput.NoL; //  Multiply by NoL here for purpose;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;  &#xD;&#xA;**WITH COOK-TORRANCE, I get this**:  &#xD;&#xA;&#xD;&#xA;*IOR = 1*  &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;&#xD;&#xA;*IOR = 4*  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;*IOR =4 but no Fresnel*  &#xD;&#xA;[![enter image description here][7]][7]    &#xD;&#xA;&#xD;&#xA;Source code:&#xD;&#xA;&#xD;&#xA;	RGBFColor Evaluate_Brdf(const DistributionFunction::SampleInput&amp; distSampleInput, float ior)&#xD;&#xA;	{&#xD;&#xA;		// No diffuse. We are only interested in specular.&#xD;&#xA;		RGBFColor diffuse = RGBFColor(0.0f);&#xD;&#xA;&#xD;&#xA;		// Specular.&#xD;&#xA;		RGBFColor specular = RGBFColor(1.0f);&#xD;&#xA;		{&#xD;&#xA;			const float F0 = ComputeFresnel0(ior);&#xD;&#xA;			const float F = ComputeFresnel(F0, distSampleInput.NoV);&#xD;&#xA;&#xD;&#xA;			static const float shininesss = 256.0f;&#xD;&#xA;			float specularFactor = F * BlinnPhong(distSampleInput, shininesss);&#xD;&#xA;&#xD;&#xA;			specularFactor /= (4.0f * distSampleInput.HoV * distSampleInput.NoL);// Cook Torrance.&#xD;&#xA;&#xD;&#xA;			specular *= specularFactor;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return (diffuse + specular) * distSampleInput.NoL; //  Multiply by NoL here for purpose;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**As you can see the version with the Cook-Torrance division has the fresnel effect, even without the fresnel term. What I am doing wrong? I outputted the following values to debug:** &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks for helping!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/Theory&#xD;&#xA;  [2]: https://i.stack.imgur.com/kzYVo.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/9jEMm.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/97F1n.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/elXfs.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/xH29d.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/qxjbx.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/125ac.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41887" PostHistoryTypeId="1" PostId="13733" RevisionGUID="e08f23c9-7a35-4808-950a-20b11a2992de" CreationDate="2023-09-27T00:15:58.723" UserId="19251" Text="Unable to compute fresnel reflections properly" ContentLicense="CC BY-SA 4.0" />
  <row Id="41888" PostHistoryTypeId="3" PostId="13733" RevisionGUID="e08f23c9-7a35-4808-950a-20b11a2992de" CreationDate="2023-09-27T00:15:58.723" UserId="19251" Text="|brdf|pbr|specular|fresnel|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41889" PostHistoryTypeId="5" PostId="13733" RevisionGUID="8ffba6a3-becd-4b6f-a369-0e293acab87d" CreationDate="2023-09-27T00:25:33.453" UserId="19251" Comment="added 7 characters in body" Text="I am implementing fresnel reflections for materials in my renderer.  &#xD;&#xA;According to this [source][1], here the look I should obtain when rendering a sphere over a grey background:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**I have two implementations**. One of them is based on Cook Torrance model.  &#xD;&#xA;The implementations use theses helper functions:  &#xD;&#xA;&#xD;&#xA;	float ComputeFresnel0(float ior)&#xD;&#xA;	{&#xD;&#xA;		// @See: https://graphicscompendium.com/raytracing/11-fresnel-beer&#xD;&#xA;		return std::powf((ior - 1.0f ) / (ior + 1.0f), 2.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float ComputeFresnel(float F0, float NoV)&#xD;&#xA;	{&#xD;&#xA;		// @See: https://graphicscompendium.com/raytracing/11-fresnel-beer&#xD;&#xA;		return F0 + (1.0f - F0) * pow(1.0f - NoV, 5.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	float BlinnPhong(const SampleInput&amp; input, float shininess)&#xD;&#xA;	{&#xD;&#xA;		//@See: https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_reflection_model&#xD;&#xA;		return std::pow(input.HoN, shininess);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;In term of output, here what i obtain:  &#xD;&#xA;&#xD;&#xA;**NO COOK-TORRANCE, I get this**:  &#xD;&#xA;*IOR = 1*  &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;&#xD;&#xA;*IOR = 4*  &#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Source code:&#xD;&#xA;&#xD;&#xA;	RGBFColor Evaluate_Brdf(const DistributionFunction::SampleInput&amp; distSampleInput, float ior)&#xD;&#xA;	{&#xD;&#xA;		// No diffuse. We are only interested in specular.&#xD;&#xA;		RGBFColor diffuse = RGBFColor(0.0f);&#xD;&#xA;&#xD;&#xA;		// Specular.&#xD;&#xA;		RGBFColor specular = RGBFColor(1.0f);&#xD;&#xA;		{&#xD;&#xA;			const float F0 = ComputeFresnel0(ior);&#xD;&#xA;			const float F = ComputeFresnel(F0, distSampleInput.NoV);&#xD;&#xA;&#xD;&#xA;			static const float shininesss = 256.0f;&#xD;&#xA;			const float specularFactor = F * BlinnPhong(distSampleInput, shininesss);&#xD;&#xA;&#xD;&#xA;			specular *= specularFactor;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return (diffuse + specular) * distSampleInput.NoL; //  Multiply by NoL here for purpose;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA; &#xD;&#xA;  &#xD;&#xA;**WITH COOK-TORRANCE, I get this**:  &#xD;&#xA;&#xD;&#xA;*IOR = 1*  &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;&#xD;&#xA;*IOR = 4*  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;*IOR =4 but no Fresnel*  &#xD;&#xA;[![enter image description here][7]][7]    &#xD;&#xA;&#xD;&#xA;Source code:&#xD;&#xA;&#xD;&#xA;	RGBFColor Evaluate_Brdf(const DistributionFunction::SampleInput&amp; distSampleInput, float ior)&#xD;&#xA;	{&#xD;&#xA;		// No diffuse. We are only interested in specular.&#xD;&#xA;		RGBFColor diffuse = RGBFColor(0.0f);&#xD;&#xA;&#xD;&#xA;		// Specular.&#xD;&#xA;		RGBFColor specular = RGBFColor(1.0f);&#xD;&#xA;		{&#xD;&#xA;			const float F0 = ComputeFresnel0(ior);&#xD;&#xA;			const float F = ComputeFresnel(F0, distSampleInput.NoV);&#xD;&#xA;&#xD;&#xA;			static const float shininesss = 256.0f;&#xD;&#xA;			float specularFactor = F * BlinnPhong(distSampleInput, shininesss);&#xD;&#xA;  &#xD;&#xA;			// Cook Torrance.&#xD;&#xA;			specularFactor /= (4.0f * distSampleInput.HoV * distSampleInput.NoL);&#xD;&#xA;&#xD;&#xA;			specular *= specularFactor;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		return (diffuse + specular) * distSampleInput.NoL; //  Multiply by NoL here for purpose;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;**As you can see the version with the Cook-Torrance division has the fresnel effect, even without the fresnel term. What I am doing wrong? I outputted the following values to debug:** &#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Thanks for helping!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/Theory&#xD;&#xA;  [2]: https://i.stack.imgur.com/kzYVo.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/9jEMm.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/97F1n.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/elXfs.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/xH29d.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/qxjbx.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/125ac.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41890" PostHistoryTypeId="50" PostId="13410" RevisionGUID="cb25f6ed-ce38-4ca7-ad65-8d134b11583e" CreationDate="2023-09-27T01:02:35.293" UserId="-1" />
  <row Id="41891" PostHistoryTypeId="2" PostId="13734" RevisionGUID="f3260e8d-18d2-4ae2-8ab2-4c4f30d05108" CreationDate="2023-09-27T06:15:16.360" UserId="19898" Text="I don't understand why this happening. I included the code that I am using to check if a vertex is inside the view frustum.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4HyKJ.png&#xD;&#xA;&#xD;&#xA;bool isPointInsideViewFrustrum(f4x4 mvp, float4 vertex)&#xD;&#xA;{&#xD;&#xA;	float4 clipSpace = mul(mvp, vertex);&#xD;&#xA;&#xD;&#xA;	return ((clipSpace.x &gt; -clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.x &lt; clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.y &gt; -clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.y &lt; clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.z &gt; -clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.z &lt; clipSpace.w));&#xD;&#xA;}" ContentLicense="CC BY-SA 4.0" />
  <row Id="41893" PostHistoryTypeId="1" PostId="13734" RevisionGUID="f3260e8d-18d2-4ae2-8ab2-4c4f30d05108" CreationDate="2023-09-27T06:15:16.360" UserId="19898" Text="Clip Space View Frustrum Culling Not Working Properly" ContentLicense="CC BY-SA 4.0" />
  <row Id="41894" PostHistoryTypeId="3" PostId="13734" RevisionGUID="f3260e8d-18d2-4ae2-8ab2-4c4f30d05108" CreationDate="2023-09-27T06:15:16.360" UserId="19898" Text="|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41897" PostHistoryTypeId="5" PostId="13734" RevisionGUID="1bfa0b4c-baa5-4fe9-8ac0-1481a79c263e" CreationDate="2023-09-27T08:04:47.753" UserId="13273" Comment="added 20 characters in body" Text="I don't understand why this happening. I included the code that I am using to check if a vertex is inside the view frustum.&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/4HyKJ.png&#xD;&#xA;&#xD;&#xA;    bool isPointInsideViewFrustrum(f4x4 mvp, float4 vertex)&#xD;&#xA;    {&#xD;&#xA;	    float4 clipSpace = mul(mvp, vertex);&#xD;&#xA;&#xD;&#xA;	    return ((clipSpace.x &gt; -clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.x &lt; clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.y &gt; -clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.y &lt; clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.z &gt; -clipSpace.w) &amp;&amp;&#xD;&#xA;		   (clipSpace.z &lt; clipSpace.w));&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="41901" PostHistoryTypeId="50" PostId="12143" RevisionGUID="635f24f2-8b7a-4157-95d4-ddb53dda56b6" CreationDate="2023-09-27T16:01:45.230" UserId="-1" />
  <row Id="41903" PostHistoryTypeId="50" PostId="13445" RevisionGUID="4412b00f-4179-4301-88bf-866767ac2781" CreationDate="2023-09-28T23:01:55.200" UserId="-1" />
  <row Id="41904" PostHistoryTypeId="2" PostId="13736" RevisionGUID="ac5946ec-4cda-4764-a65b-477c4e3bc071" CreationDate="2023-09-29T12:14:28.053" UserId="20615" Text="I am trying to create a mask which is required for a 3D inpainting task. My data contains 3D truncated SDF grid of size `64*64*64` with a truncated value of `3`. I tried a couple of methods including the following, but none is able to produce satisfactory results. What am I missing here?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;```python3&#xD;&#xA;def generate_mask(partial_object, ground_truth, device):&#xD;&#xA;&#xD;&#xA;    threshold = 3.0&#xD;&#xA;    truncation = 3.0&#xD;&#xA;    target_mask = torch.zeros(ground_truth.shape).bool()&#xD;&#xA;    target_mask[np.where((ground_truth.cpu().detach().numpy() &lt; threshold) &amp; (ground_truth.cpu().detach().numpy() &gt; -threshold))] = True   # True, if inside the surface&#xD;&#xA;    &#xD;&#xA;    input_mask = torch.zeros(partial_object.shape).bool()&#xD;&#xA;    input_mask[np.where((partial_object.cpu().detach().numpy() &lt; threshold) &amp; (partial_object.cpu().detach().numpy() &gt; -threshold))] = True&#xD;&#xA;    &#xD;&#xA;    mask = target_mask ^ input_mask&#xD;&#xA;    mask = mask.to(device)&#xD;&#xA;    &#xD;&#xA;    return mask&#xD;&#xA;```&#xD;&#xA;The code mostly results an object almost similar to the ground truth." ContentLicense="CC BY-SA 4.0" />
  <row Id="41906" PostHistoryTypeId="1" PostId="13736" RevisionGUID="ac5946ec-4cda-4764-a65b-477c4e3bc071" CreationDate="2023-09-29T12:14:28.053" UserId="20615" Text="How to retrieve a mask for a partially filled 3D Truncated SDF based on its ground truth?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41907" PostHistoryTypeId="3" PostId="13736" RevisionGUID="ac5946ec-4cda-4764-a65b-477c4e3bc071" CreationDate="2023-09-29T12:14:28.053" UserId="20615" Text="|3d|signed-distance-field|masking|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41908" PostHistoryTypeId="2" PostId="13737" RevisionGUID="f203a0de-3a81-4ae4-b80f-ee0e2b968b3e" CreationDate="2023-09-29T12:56:02.693" UserId="18711" Text="&#xD;&#xA;I have my own webgl library with scene objects who have position and rotation.&#xD;&#xA;I use for physics cannon.js library. In cannon.js for rotation logic it is used `quaternion`.&#xD;&#xA;My engine runs on simple local axis rotation (rotation.rotx ...).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This is most important part of code for this problem:&#xD;&#xA;&#xD;&#xA;Part from render:&#xD;&#xA;```js&#xD;&#xA;&#xD;&#xA;    while(physicsLooper &lt;= world.contentList.length - 1) {&#xD;&#xA;      if(world.contentList[physicsLooper].physics.enabled) {&#xD;&#xA;        var local = world.contentList[physicsLooper];&#xD;&#xA;&#xD;&#xA;        local.position.SetX(local.physics.currentBody.position.x)&#xD;&#xA;        local.position.SetZ(local.physics.currentBody.position.y)&#xD;&#xA;        local.position.SetY(local.physics.currentBody.position.z)&#xD;&#xA;        world.contentList[physicsLooper].rotation.rotx = radToDeg(local.physics.currentBody.quaternion.toAxisAngle()[1]);&#xD;&#xA;        world.contentList[physicsLooper].rotation.roty = radToDeg(local.physics.currentBody.quaternion.toAxisAngle()[1]);&#xD;&#xA;        world.contentList[physicsLooper].rotation.rotz = radToDeg(local.physics.currentBody.quaternion.toAxisAngle()[1]);&#xD;&#xA;        // matrixEngine.matrixWorld.world.physics.toDeg&#xD;&#xA;      }&#xD;&#xA;      physicsLooper++;&#xD;&#xA;    }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Also i can access `toAxisAngle()[0]` :&#xD;&#xA;&#xD;&#xA;```js&#xD;&#xA;quaternion.toAxisAngle()[0].x&#xD;&#xA;quaternion.toAxisAngle()[0].y&#xD;&#xA;quaternion.toAxisAngle()[0].z&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;For example i have very close to the right solution but steel not perfect...&#xD;&#xA;&#xD;&#xA;Example link for visual feel:&#xD;&#xA;[Navigate to the `Physics class - Cube` example][1]&#xD;&#xA;Source code: [matrix-engine][2]&#xD;&#xA;&#xD;&#xA;Any suggestion , will be very glad for any math suggestion?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://maximumroulette.com/apps/matrix-engine/examples-build.html&#xD;&#xA;  [2]: https://github.com/zlatnaspirala/matrix-engine" ContentLicense="CC BY-SA 4.0" />
  <row Id="41910" PostHistoryTypeId="1" PostId="13737" RevisionGUID="f203a0de-3a81-4ae4-b80f-ee0e2b968b3e" CreationDate="2023-09-29T12:56:02.693" UserId="18711" Text="Rotation from quaternion to glmatrix axis rotation" ContentLicense="CC BY-SA 4.0" />
  <row Id="41911" PostHistoryTypeId="3" PostId="13737" RevisionGUID="f203a0de-3a81-4ae4-b80f-ee0e2b968b3e" CreationDate="2023-09-29T12:56:02.693" UserId="18711" Text="|quaternions|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41913" PostHistoryTypeId="2" PostId="13738" RevisionGUID="8cb96534-c922-4793-98af-a0aa9358aed2" CreationDate="2023-10-01T07:03:18.830" UserId="20623" Text="I am trying to work with a .STEP file I have received. Upon opening it in CAD Assistant, I find &#xD;&#xA;its surface as jagged lines, like a low poly model. When I export it as OBJ from there, the edges and vertices are just the same.&#xD;&#xA;&#xD;&#xA;[![Screenshot from CAD Assisstant][1]][1]&#xD;&#xA;[![File exported as OBJ and imported in blender][2]][2]&#xD;&#xA;&#xD;&#xA;I want to use this model to create renderings. Although I can recreate this simple surface in Blender, this is a problem I frequently encounter with STEP files. &#xD;&#xA;&#xD;&#xA;I assumed STEP files only contain NURBS data. So is this a limitation on my end (CAD Assisstant), or the original source of this file? Thank you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/aTVbY.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/bkY1Q.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41915" PostHistoryTypeId="1" PostId="13738" RevisionGUID="8cb96534-c922-4793-98af-a0aa9358aed2" CreationDate="2023-10-01T07:03:18.830" UserId="20623" Text="Can STEP files contain polygon data? How do I get a smoother mesh out of a STEP file?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41916" PostHistoryTypeId="3" PostId="13738" RevisionGUID="8cb96534-c922-4793-98af-a0aa9358aed2" CreationDate="2023-10-01T07:03:18.830" UserId="20623" Text="|3d|mesh|polygon|nurbs|cad|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41917" PostHistoryTypeId="50" PostId="13454" RevisionGUID="cd5f52c2-443b-4089-8602-52f4e84669a4" CreationDate="2023-10-01T14:04:20.520" UserId="-1" />
  <row Id="41918" PostHistoryTypeId="2" PostId="13739" RevisionGUID="3e3ae1bd-7cc3-493c-bc0c-371cf5d1fd47" CreationDate="2023-10-03T01:52:46.220" UserId="7462" Text="I was reading &quot;Polygon Mesh Processing&quot; and in chapter 5 the authors present this little algorithm:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;remesh(target edge length)&#xD;&#xA;  low = 4/5 * target edge length&#xD;&#xA;  high = 4/3 * target edge length&#xD;&#xA;  for i = 0 to 10 do&#xD;&#xA;    split long edges(high)&#xD;&#xA;    collapse short edges(low,high)&#xD;&#xA;    equalize valences()&#xD;&#xA;    tangential relaxation()&#xD;&#xA;    project to surface()&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;They provide pseudocode and explanations for all steps except the last one. I assume that the reprojection must be done using the input mesh as a reference. Do you use some kind of BVH, find the triangle closest to the point and project to the plane?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41920" PostHistoryTypeId="1" PostId="13739" RevisionGUID="3e3ae1bd-7cc3-493c-bc0c-371cf5d1fd47" CreationDate="2023-10-03T01:52:46.220" UserId="7462" Text="How is re projection usually implemented in remeshing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41921" PostHistoryTypeId="3" PostId="13739" RevisionGUID="3e3ae1bd-7cc3-493c-bc0c-371cf5d1fd47" CreationDate="2023-10-03T01:52:46.220" UserId="7462" Text="|mathematics|computational-geometry|algorithm|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41922" PostHistoryTypeId="2" PostId="13740" RevisionGUID="3ec7d031-8851-4c4e-b7b9-83b7e0accdc4" CreationDate="2023-10-03T16:16:26.510" UserId="110" Text="in [GLSL spec][1] section 7.6.2.2 about Standard Uniform Block Layout, rule (4) says:&#xD;&#xA;&#xD;&#xA;&gt; If the member is an array of scalars or vectors,&#xD;&#xA;&gt; &#xD;&#xA;&gt; the base alignment &#xD;&#xA;&gt; &#xD;&#xA;&gt; and array stride&#xD;&#xA;&gt; &#xD;&#xA;&gt; are set to match &#xD;&#xA;&gt; &#xD;&#xA;&gt; the base alignment of a single array element, according to rules (1), (2), and (3),&#xD;&#xA;&gt; &#xD;&#xA;&gt; and rounded up to the base alignment of a vec4.&#xD;&#xA;&#xD;&#xA;I am not sure about the rounding of array stride to the base alignment of a vec4?&#xD;&#xA;  &#xD;&#xA;What does it mean the array element stride would be for a Uniform member looking like that:&#xD;&#xA;&#xD;&#xA;    struct MyStruct&#xD;&#xA;    {&#xD;&#xA;       float myArray[7];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    uniform MyStruct myStruct;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;[1]: https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41924" PostHistoryTypeId="1" PostId="13740" RevisionGUID="3ec7d031-8851-4c4e-b7b9-83b7e0accdc4" CreationDate="2023-10-03T16:16:26.510" UserId="110" Text="GLSL Uniform Layout Spec says member array stride alignment is rounded up to vec4?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41925" PostHistoryTypeId="3" PostId="13740" RevisionGUID="3ec7d031-8851-4c4e-b7b9-83b7e0accdc4" CreationDate="2023-10-03T16:16:26.510" UserId="110" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41926" PostHistoryTypeId="2" PostId="13741" RevisionGUID="2519bea3-d0c3-4728-bfa0-90b8db1f8934" CreationDate="2023-10-03T19:22:04.197" UserId="20643" Text="Are you sure the buffer isn't just defined as a host visible buffer? If you allocate it in CPU space it might have to transfer it a lot, I use ByteAddressBuffer a lot and it's not *that* slow for me. So maybe it's just not properly allocated." ContentLicense="CC BY-SA 4.0" />
  <row Id="41928" PostHistoryTypeId="2" PostId="13742" RevisionGUID="1a28b07e-8d79-41ca-8620-b1ff7376870a" CreationDate="2023-10-04T19:13:32.877" UserId="20504" Text="I've never worked with stencil buffers, but I'm researching if it is the right tool for my task. &#xD;&#xA;&#xD;&#xA;Basically I don't understand yet if stencil buffer can only be filled in by some hardcoded rules during geometry drawing (like depth buffer), or is possible to fill it in completely programmatically with the help of full-screen fragment shader, which will just draw black-and-white shape based on some 2D SDF? Also is it possible to use stencil buffer separate of depth buffer in this case, don't use depth buffer at all?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41930" PostHistoryTypeId="1" PostId="13742" RevisionGUID="1a28b07e-8d79-41ca-8620-b1ff7376870a" CreationDate="2023-10-04T19:13:32.877" UserId="20504" Text="Is it possible to fill in Stencil Buffer programmatically via fragment shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41931" PostHistoryTypeId="3" PostId="13742" RevisionGUID="1a28b07e-8d79-41ca-8620-b1ff7376870a" CreationDate="2023-10-04T19:13:32.877" UserId="20504" Text="|opengl|fragment-shader|metal|stencil-buffer|stencil-test|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41932" PostHistoryTypeId="2" PostId="13743" RevisionGUID="38eccc84-96bc-4995-a8ce-960399daa68e" CreationDate="2023-10-05T11:51:36.400" UserId="6" Text="There are a few confusing statements in your question. However, I'll still assume you're largely aware of how the stencil buffer and the stencil test actually work. I'll also talk about OpenGL, based on your tags, but the general principles should apply to any similar API.&#xD;&#xA;&#xD;&#xA;First of all, you say&#xD;&#xA;&gt; ...stencil buffer can only be filled in by some hardcoded rules during geometry drawing (like depth buffer)...&#xD;&#xA;&#xD;&#xA;But for the depth buffer that isn't actually true. You can very well decide what depth value you actually want to write by just writing anything to `gl_FragDepth` in your shader.&#xD;&#xA;&#xD;&#xA;Now you're right that in unextended GL you can't just write arbitrary values to the stencil buffer like this. However, **if your platform supports the [GL_ARB_shader_stencil_export](https://registry.khronos.org/OpenGL/extensions/ARB/ARB_shader_stencil_export.txt) extension, you can do exactly that by writing to `gl_FragStencilRefARB`**. Or more precisely, you write the reference value that is used in the stencil test. So if you have a stencil op of `GL_REPLACE`, you can basically just write the value per fragment.&#xD;&#xA;&#xD;&#xA;However, even if that extension isn't present, you can achieve similar things for simple scenarios by merely **deciding which fragments to write at all**. You can just globally specificy whichever stencil reference value you want to write for your fragments and then in the fragment shader simply **`discard` any fragments for which you don't want to write anything**. Of course this doesn't let you arbitrarily choose the value you want to write per fragment, but when using stencil testing you normally don't really need any such kind of fine-grained control over its bits (afterall, it's usually got just 256 different values anyway).&#xD;&#xA;&#xD;&#xA;As to your other question:&#xD;&#xA;&#xD;&#xA;&gt; ...is it possible to use stencil buffer separate of depth buffer in this case, don't use depth buffer at all?&#xD;&#xA;&#xD;&#xA;The stencil buffer really doesn't have anything to do with the depth buffer (at least functionally). Yes, the stencil op lets you choose different actions depending if the fragment passed the depth test or not. But **noone requires you to use the depth test at all. If you don't need depth testing, just don't do it.** Or if you don't need stencil testing and the depth buffer already works for you, then use that.&#xD;&#xA;&#xD;&#xA;There is a bit of a practical consideration that usually the actual **framebuffer is laid out so that the depth and stencil buffer share their storage** in a combined depth-stencil buffer, because for the common case of a 24-bit depth buffer and an 8-bit stencil buffer this goes well together. It's what the window system usually does for you and what you should strive for when binding storage to framebuffer objects, too. However, that is merely the **internal data layout and doesn't require you to always use depth and stencil testing together**. It does, however, mean, that sparing away the stencil buffer usually doesn't save you any actual memory (at least in case of a common 24-bit depth format).&#xD;&#xA;&#xD;&#xA;----------&#xD;&#xA;&#xD;&#xA;As a side note, though, from your question I have a bit of hunch that you might not even need the stencil buffer to begin with. Maybe you weren't aware that you can just `discard` fragments in the fragment shader or decide yourself which depth value you want to write and maybe your possible multi-pass algorithm (since that's usually how stencil testing is used) can be done in a single pass or just differently altogether. If you'd need to write compilated stencil values from your shader, it could be a sign that the stencil buffer might not actually be the tool you're looking for." ContentLicense="CC BY-SA 4.0" />
  <row Id="41934" PostHistoryTypeId="5" PostId="13740" RevisionGUID="ae2c2d70-cfd6-47db-abf3-a6a011239c05" CreationDate="2023-10-05T11:58:47.880" UserId="6" Comment="deleted 37 characters in body" Text="in [GLSL spec][1] section 7.6.2.2 about Standard Uniform Block Layout, rule (4) says:&#xD;&#xA;&#xD;&#xA;&gt; If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and rounded up to the base alignment of a vec4.&#xD;&#xA;&#xD;&#xA;I am not sure about the rounding of array stride to the base alignment of a vec4?&#xD;&#xA;  &#xD;&#xA;What does it mean the array element stride would be for a Uniform member looking like that:&#xD;&#xA;&#xD;&#xA;    struct MyStruct&#xD;&#xA;    {&#xD;&#xA;       float myArray[7];&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    uniform MyStruct myStruct;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;[1]: https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41935" PostHistoryTypeId="2" PostId="13744" RevisionGUID="e77d4bb3-b456-4245-b60f-f3b6b0581f52" CreationDate="2023-10-05T12:11:58.547" UserId="6" Text="It does mean exactly that. Whenever you have an array, it's **treated as an array of `vec4`s with regards to the memory layout**. So in your `float` array you actually have 28 `float`s with each of the 7 values followed by 3 values of (basically unnecessary) padding to **round each array element's alignment up to 16 byte** (the size of a `vec4`). And yes, that's why `std140` layout plain sucks! ;-)&#xD;&#xA;&#xD;&#xA;However, do keep in mind that **this only applies to uniform blocks, i.e. uniform data sourced from buffers**. Your example actually isn't that. You merely declared a non-block uniform that happens to be a structure/array. This doesn't adhere to the same layout rules as an actual uniform block (and you don't really know/care how it's laid out), as there is no need to synchronize the layout of an arbitrary memory chunk between the GL and youself. Good old `glUniform` explicitly knows what data it gets." ContentLicense="CC BY-SA 4.0" />
  <row Id="41937" PostHistoryTypeId="2" PostId="13745" RevisionGUID="d4ad218c-4b2a-4950-bb14-4193d7d182c9" CreationDate="2023-10-06T13:11:56.207" UserId="20655" Text="to get the radiance of the Lambertian diffuse reflected light, I have to multiply the constant pdf (rho/pi) with the incoming intensity I0*cos(theta_i), where cos(theta_i) is given by the scalar Product &lt;n *I&gt; and n is the normal vector for this problem (correct?). Now, if I add the Phong BRDF I'm confused. In the pdf here, there is an &lt;n * I&gt; in the denominator or not. In the first case the reflected intensity is proportional to &lt;n * I&gt;, but not in the second case. What's right?&#xD;&#xA;&#xD;&#xA;Uwe" ContentLicense="CC BY-SA 4.0" />
  <row Id="41939" PostHistoryTypeId="1" PostId="13745" RevisionGUID="d4ad218c-4b2a-4950-bb14-4193d7d182c9" CreationDate="2023-10-06T13:11:56.207" UserId="20655" Text="How to calculate the radiance of the reflected light ray using the Blin Phong BRDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="41940" PostHistoryTypeId="3" PostId="13745" RevisionGUID="d4ad218c-4b2a-4950-bb14-4193d7d182c9" CreationDate="2023-10-06T13:11:56.207" UserId="20655" Text="|raytracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41941" PostHistoryTypeId="50" PostId="12158" RevisionGUID="20c8b59b-1774-4ff1-bf1f-30bfbdec446d" CreationDate="2023-10-06T14:02:35.223" UserId="-1" />
  <row Id="41942" PostHistoryTypeId="50" PostId="10955" RevisionGUID="8ad58069-5533-4b25-a16a-94fa88f2eb82" CreationDate="2023-10-06T22:02:45.250" UserId="-1" />
  <row Id="41944" PostHistoryTypeId="2" PostId="13746" RevisionGUID="2372654b-d6be-44d3-86c9-5abd5bb729a3" CreationDate="2023-10-07T03:07:40.737" UserId="20504" Text="I may not need as precise pixel-perfect stenciling as my render target during stencil tested render pass. I could be okay with stencil test happening at half or quarter of resolution to save bandwidth, but is it even an option, or the way stencil test designed is to always work on matching dimensions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41946" PostHistoryTypeId="1" PostId="13746" RevisionGUID="2372654b-d6be-44d3-86c9-5abd5bb729a3" CreationDate="2023-10-07T03:07:40.737" UserId="20504" Text="Is stencil buffer dimensions required to match render target dimensions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41947" PostHistoryTypeId="3" PostId="13746" RevisionGUID="2372654b-d6be-44d3-86c9-5abd5bb729a3" CreationDate="2023-10-07T03:07:40.737" UserId="20504" Text="|opengl|fragment-shader|metal|stencil-buffer|stencil-test|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41948" PostHistoryTypeId="4" PostId="13746" RevisionGUID="a8c9f560-9e13-475e-9c08-896b7937877c" CreationDate="2023-10-07T04:51:05.387" UserId="20504" Comment="edited title" Text="Are stencil buffer dimensions required to match render target dimensions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41949" PostHistoryTypeId="2" PostId="13747" RevisionGUID="423df0ee-faef-4283-bad9-a546525778d6" CreationDate="2023-10-07T08:05:58.123" UserId="19537" Text="I believe you have a misunderstanding for the BRDF sampling process: PDF can be almost arbitrary if PDF is non-zero at the correspondig point where the  integrand is non-zero. We don't even have to importance sampling BRDF just for simplicity (though uniformly sampling everything can be extremely inefficient). So, &quot;in the pdf here&quot;, we don't know whether there should be a cosine term unless we know exactly what kind of sampling method you are using.&#xD;&#xA;&#xD;&#xA;Normally, we wish to be more efficient so we will importance-sample the integrand, then we wish to match the sampling PDF with the integrand  as closely as possible . So, let's therefore look at the Blinn-Phong (or Phong) BRDF, it has a power cosine term so the best practice is to use power cosine-weighted hemisphere sampling, but the original cosine hemisphere sampling would work, too. For these two sampling methods, you can refer to [Sampling the hemisphere](https://ameye.dev/notes/sampling-the-hemisphere/), which has thorough explanation and derivation for how you get the sample and its PDF.&#xD;&#xA;&#xD;&#xA;So for your question: Lambertian BRDF indeed has a cosine term which means that your are correct, Phong and Blinn-Phong have power cosine term so the throughput is proportional to $(\cos\theta)^\alpha$, but it won't hurt to use the same sampling method as Lambertian BRDF and get the same PDF for each sample, though it's suboptimal.&#xD;&#xA;&#xD;&#xA;BTW, I think your question should be improved in the following ways: &#xD;&#xA;- Use Latex to improve the readability of your post.&#xD;&#xA;- Clearly list your question and related subjects. For example, I am not sure whether you are confused about Phong model or Blinn-Phong model since these two differ in what kind of vector they sample. For clearer understanding of sampling Blinn-Phong model, you can refer to another answer of mine [sampling-of-the-blinn-phong-brdf-in-pathtracing](https://computergraphics.stackexchange.com/questions/13633/importance-sampling-of-the-blinn-phong-brdf-in-pathtracing/13636#13636)." ContentLicense="CC BY-SA 4.0" />
  <row Id="41951" PostHistoryTypeId="2" PostId="13748" RevisionGUID="9458a6a9-f0fe-4de5-9326-53d39d2e1eae" CreationDate="2023-10-07T11:22:02.103" UserId="9044" Text="A stencil buffer has to be of the same size as every other attachment, otherwise this would violate [framebuffer completeness][1] requirements.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Framebuffer_Object#Framebuffer_Completeness" ContentLicense="CC BY-SA 4.0" />
  <row Id="41953" PostHistoryTypeId="2" PostId="13749" RevisionGUID="0aff8a6d-d6e4-48bb-89d7-916ca0b71eaf" CreationDate="2023-10-07T11:52:47.513" UserId="20658" Text="thanks a lot for your given informations! Let me summarize what I want to do:&#xD;&#xA;&#xD;&#xA;1. I have a sun ray (parallel light) which is reflected at the inner wall of a cylinder,i.e. I have the input vector and direction theta_in.&#xD;&#xA;&#xD;&#xA;2. From this I can calculate the reflected vector. Now, I can generate a outgoing vector with the help of importance sampling of the - say modified Phong model. How to do this is given in the Lafortune &amp; Williams paper.&#xD;&#xA;&#xD;&#xA;3. If I'm correct, this modified Phong model includes the input direction via the cosine term which gives the cosine between the perfect specular reflective direction and the outgoing direction.&#xD;&#xA;&#xD;&#xA;4. The diffusive part of the modified Phong model doesn't include any input direction.&#xD;&#xA;&#xD;&#xA;5. Is it correct to multiply these values by I0*cos(theta_in) in order to get the output intensity?&#xD;&#xA;&#xD;&#xA;Thanks again,&#xD;&#xA;&#xD;&#xA;Uwe " ContentLicense="CC BY-SA 4.0" />
  <row Id="41955" PostHistoryTypeId="2" PostId="13750" RevisionGUID="7ecef8fd-a47f-45ba-a3a2-a4b93e7e7a2d" CreationDate="2023-10-07T15:50:38.397" UserId="20658" Text="thanks Enigmatisms for your answer. But unfortunately I thought it is just the other way around..... Is there anybody else who can contribute to this problem.&#xD;&#xA;&#xD;&#xA;Uwe" ContentLicense="CC BY-SA 4.0" />
  <row Id="41957" PostHistoryTypeId="5" PostId="13747" RevisionGUID="7035ad17-8fc0-42d7-938c-5301698d4837" CreationDate="2023-10-08T02:14:17.230" UserId="19537" Comment="Add more information" Text="I believe you have a misunderstanding for the BRDF sampling process: PDF can be almost arbitrary if PDF is non-zero at the correspondig point where the  integrand is non-zero. We don't even have to importance sampling BRDF just for simplicity (though uniformly sampling everything can be extremely inefficient). So, &quot;in the pdf here&quot;, we don't know whether there should be a cosine term unless we know exactly what kind of sampling method you are using.&#xD;&#xA;&#xD;&#xA;Normally, we wish to be more efficient so we will importance-sample the integrand, then we wish to match the sampling PDF with the integrand  as closely as possible . So, let's therefore look at the Blinn-Phong (or Phong) BRDF, it has a power cosine term so the best practice is to use power cosine-weighted hemisphere sampling, but the original cosine hemisphere sampling would work, too. For these two sampling methods, you can refer to [Sampling the hemisphere](https://ameye.dev/notes/sampling-the-hemisphere/), which has thorough explanation and derivation for how you get the sample and its PDF.&#xD;&#xA;&#xD;&#xA;So for your question: Lambertian BRDF indeed has a cosine term which means that your are correct, Phong and Blinn-Phong have power cosine term so the throughput is proportional to $(\cos\theta)^\alpha$, but it won't hurt to use the same sampling method as Lambertian BRDF and get the same PDF for each sample, though it's suboptimal.&#xD;&#xA;&#xD;&#xA;BTW, I think your question should be improved in the following ways: &#xD;&#xA;- Use Latex to improve the readability of your post.&#xD;&#xA;- Clearly list your question and related subjects. For example, I am not sure whether you are confused about Phong model or Blinn-Phong model since these two differ in what kind of vector they sample. For clearer understanding of sampling Blinn-Phong model, you can refer to another answer of mine [sampling-of-the-blinn-phong-brdf-in-pathtracing](https://computergraphics.stackexchange.com/questions/13633/importance-sampling-of-the-blinn-phong-brdf-in-pathtracing/13636#13636).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Update for further explanation, and I need to remind you that you can **comment** below my answer or my comment instead of posting your own answer.&#xD;&#xA;&#xD;&#xA;Well let's get this straight. The following figure shows the local light interaction:&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;So, your modified Phong BRDF is actually:&#xD;&#xA;$$&#xD;&#xA;k_d \frac{1}{\pi} + k_s \frac{n+2}{2\pi}\cos^n\alpha&#xD;&#xA;$$&#xD;&#xA;Yes, like I said, there is only one cosine term in the BRDF, which is $\cos\alpha$. Note that 'outgoing' direction is $\pmb{v}$ since this follows the convention of light tracing. &#xD;&#xA;&#xD;&#xA;So are we done? No, the surface rendering equation is:&#xD;&#xA;$$&#xD;&#xA;I(x, w) = \int_{\Omega}f(x, w, w')&lt;w, w'&gt;dw'&#xD;&#xA;$$&#xD;&#xA;and here, $&lt;w, w'&gt;$ means normalized dot product (cosine). So it doesn't matter whether you are dealing with diffusive lobe or specular lobe (unless it is mirror-specular), $\cos\theta$ always follows. You can find this in the code of PBR-book (from pbrt-v3, `src/integrator/path.cpp`):&#xD;&#xA;```c++&#xD;&#xA;// Account for the indirect subsurface scattering component&#xD;&#xA;Spectrum f = pi.bsdf-&gt;Sample_f(pi.wo, &amp;wi, sampler.Get2D(), &amp;pdf,&#xD;&#xA;                                BSDF_ALL, &amp;flags);&#xD;&#xA;if (f.IsBlack() || pdf == 0) break;&#xD;&#xA;beta *= f * AbsDot(wi, pi.shading.n) / pdf;&#xD;&#xA;```&#xD;&#xA;You see, `pi.bsdf-&gt;Sample_f` will evaluate BRDF value and assign it to f, but to get the real path through put `beta`, one must have $\cos\theta$ (`AbsDot(wi, pi.shading.n)`) since this is the **geometry term that would convert the solid angle measure to area product measure** (see [Veach Chapter 8: A Path Integral Formulation of Light Transport](https://graphics.stanford.edu/courses/cs348b-03/papers/veach-chapter8.pdf) for more information on this topic). So the problem falls back to: (1) I need to incorporate all cosine term to get the correct radiance (but for BRDF evaluation, $\cos\theta$ is not needed) (2) the PDF in the denominator (as I explained in the upper part of this answer).&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3jGRG.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41958" PostHistoryTypeId="5" PostId="13748" RevisionGUID="4642e582-95d6-41b6-abbf-9175db87e122" CreationDate="2023-10-08T08:48:30.433" UserId="9044" Comment="added 968 characters in body" Text="When the framebuffer attachment sizes differ, rendering will only happen to the smallest size supported by all attachments (i.e. a rectangle of minimal width &amp; height among all the attachments). See the [OpenGL wiki][1]&#xD;&#xA;&#xD;&#xA;&gt; Notice that there is no restriction based on size. The effective size of the FBO is the intersection of all of the sizes of the bound images (ie: the smallest in each dimension).&#xD;&#xA;&#xD;&#xA; or the [OpenGL specification][2], section 9.2 *Binding and Managing Framebuffer Objects*:&#xD;&#xA;&#xD;&#xA;&gt; If the attachment sizes are not all identical, the results of rendering are defined only within the largest area that can fit in all of the attachments. This&#xD;&#xA;area is defined as the intersection of rectangles having a lower left of (0, 0)&#xD;&#xA;and an upper right of (width, height) for each attachment. Contents of attachments outside this area are undefined after execution of a rendering command (as defined in section 2.4).&#xD;&#xA;&#xD;&#xA;So, if the stencil buffer is smaller than the color attachments, it will simply limit the rendering area to its size.&#xD;&#xA;&#xD;&#xA;  [1]: https://www.khronos.org/opengl/wiki/Framebuffer_Object#Completeness_Rules&#xD;&#xA;&#xD;&#xA;  [2]: https://registry.khronos.org/OpenGL/specs/gl/glspec46.core.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="41959" PostHistoryTypeId="50" PostId="13400" RevisionGUID="9bee9a60-9750-4a31-88cc-c115bd346dfa" CreationDate="2023-10-08T09:09:16.167" UserId="-1" />
  <row Id="41960" PostHistoryTypeId="5" PostId="13750" RevisionGUID="22ea1e31-d790-404b-bcdd-c0fe3b8a0e90" CreationDate="2023-10-08T11:00:18.473" UserId="20658" Comment="added 249 characters in body" Text="thanks Enigmatisms for your answer. But unfortunately I thought it is just the other way around..... Is there anybody else who can contribute to this problem.&#xD;&#xA;&#xD;&#xA;Rereading your first (edited?) answer, I came to the conclusion, that if f is the modified Phong probability function, then both parts have to be multiplied by the cosine of the angle between the incoming light ray and the oütgoing one. Correct?&#xD;&#xA;&#xD;&#xA;Uwe" ContentLicense="CC BY-SA 4.0" />
  <row Id="41961" PostHistoryTypeId="50" PostId="10341" RevisionGUID="b5cfe9ae-1f32-4758-8e76-43f8e606b305" CreationDate="2023-10-08T12:06:50.843" UserId="-1" />
  <row Id="41962" PostHistoryTypeId="50" PostId="13696" RevisionGUID="6c478124-fdd9-4067-a0a7-8dda4d40e8e2" CreationDate="2023-10-08T14:04:30.607" UserId="-1" />
  <row Id="41963" PostHistoryTypeId="50" PostId="13698" RevisionGUID="2d8074ba-3a15-4cd1-bc59-62d665f60d12" CreationDate="2023-10-08T16:06:50.767" UserId="-1" />
  <row Id="41964" PostHistoryTypeId="2" PostId="13751" RevisionGUID="e7b92925-3cec-4b35-bd2e-3ee76feea1b3" CreationDate="2023-10-08T22:04:49.540" UserId="7462" Text="Kobbelt et al. published a paper some 20 years ago where they specified how solving Poisson equations on the positions of a mesh lead to removing noise. This can be used for reconstructing mesh topology on holes, smooth out noisy meshes, mesh joints...&#xD;&#xA;&#xD;&#xA;I am trying to do something similar, but in my case the meshes are piecewise smooth:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What can I do at the corners so that they better reflect the geometry of the edges?&#xD;&#xA;&#xD;&#xA;For the record what I am doing is splititng the mesh into fixed and mobile vertices, computing a cotan laplacian matrix and then solving for $Lx=0$ where x are the itnerleaved cooridnates of the mobbile vertices.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qHnzr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41966" PostHistoryTypeId="1" PostId="13751" RevisionGUID="e7b92925-3cec-4b35-bd2e-3ee76feea1b3" CreationDate="2023-10-08T22:04:49.540" UserId="7462" Text="Piecewise smoothing of a mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41967" PostHistoryTypeId="3" PostId="13751" RevisionGUID="e7b92925-3cec-4b35-bd2e-3ee76feea1b3" CreationDate="2023-10-08T22:04:49.540" UserId="7462" Text="|mathematics|computational-geometry|algorithm|geometry|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41968" PostHistoryTypeId="5" PostId="13751" RevisionGUID="9da88d44-8b4c-420c-80bb-1b1a289ac73d" CreationDate="2023-10-08T23:28:06.890" UserId="7462" Comment="deleted 1 character in body" Text="Kobbelt et al. published a paper some 20 years ago where they specified how solving Poisson equations on the positions of a mesh lead to removing noise. This can be used for reconstructing mesh topology on holes, smooth out noisy meshes, mesh joints...&#xD;&#xA;&#xD;&#xA;I am trying to do something similar, but in my case the meshes are piecewise smooth:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;What can I do at the corners so that they better reflect the geometry of the edges?&#xD;&#xA;&#xD;&#xA;For the record what I am doing is splititng the mesh into fixed and mobile vertices, computing a cotan laplacian matrix and then solving for $Lx=0$ where x are the interleaved coordinates of the mobile vertices.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qHnzr.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41969" PostHistoryTypeId="50" PostId="13210" RevisionGUID="793580b9-2c80-4f14-a15f-033a0982ce0a" CreationDate="2023-10-09T18:04:40.550" UserId="-1" />
  <row Id="41970" PostHistoryTypeId="2" PostId="13752" RevisionGUID="7f5190e9-0707-4df5-8f36-161ab1322a9e" CreationDate="2023-10-11T01:16:38.083" UserId="7462" Text="Say you have 2 parametric cylinders represented as triangle meshes with very different geometries and you connect them together.&#xD;&#xA;&#xD;&#xA;Is there a method that allows you to join them together such that the shapes blend smoothly?&#xD;&#xA;&#xD;&#xA;So for example consider these geometries:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;let's say you have a cylinder with the geometry of the top left torus and one with that of the bottom right torus. You want to attach them together to get a new cylinder such that that half the cylinder is a normal cylinder, half is a corkscrew cylinder and you have a  smooth transition of the geometry from one to the other in the middle.&#xD;&#xA;&#xD;&#xA;I am trying to find literature on the topic but I am having little luck.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LjN8p.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="41972" PostHistoryTypeId="1" PostId="13752" RevisionGUID="7f5190e9-0707-4df5-8f36-161ab1322a9e" CreationDate="2023-10-11T01:16:38.083" UserId="7462" Text="Extrapolating geometry across a triangle mesh?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41973" PostHistoryTypeId="3" PostId="13752" RevisionGUID="7f5190e9-0707-4df5-8f36-161ab1322a9e" CreationDate="2023-10-11T01:16:38.083" UserId="7462" Text="|mathematics|computational-geometry|algorithm|geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41974" PostHistoryTypeId="50" PostId="10025" RevisionGUID="bdf69c30-2406-4149-8e46-7c5b3b7bf3bf" CreationDate="2023-10-11T05:02:30.323" UserId="-1" />
  <row Id="41975" PostHistoryTypeId="50" PostId="13686" RevisionGUID="21cec3ba-5bd2-48a2-8c1e-047711fb5b18" CreationDate="2023-10-11T07:08:31.030" UserId="-1" />
  <row Id="41976" PostHistoryTypeId="2" PostId="13753" RevisionGUID="da7dda0e-fa7e-4bd0-88c9-4c1429c62a5e" CreationDate="2023-10-11T08:17:00.973" UserId="7724" Text="I'm not sure what you mean by join together the shapes. I assume you mean you want a single torus but at different spots on the torus you want one of either geometry to shine through more. Assuming that parametrisation of the Torus is approximately the same (same $(u,v)$ values map to points close together). Then you could try the following:&#xD;&#xA;&#xD;&#xA;Assuming both cylinders have some parametrisation $R^2 \rightarrow R^3$ with $(u,v) \in [0,1]$. We then have two tori: $T_1(u,v)$ and $T_2(u,v)$. Then we can combine these together with additional blending functions $\alpha(u,v)$ and $\beta(u,v)$ which have the following properties: $\alpha(u,v)$ + $\beta(u,v) = 1$ and $\alpha(u,v)$, $\beta(u,v)  \in [0,1]$. Then we can create a blended torus:&#xD;&#xA;&#xD;&#xA;$$T_b(u,v) = \alpha(u,v) T_1(u,v) + \beta(u,v) T_1(u,v). $$&#xD;&#xA;&#xD;&#xA;Naturally, the question is what are these functions $\alpha$ and $\beta$ and that is what you have to decide yourself. If you do not really care about where exactly the blend is done you can set $\alpha$ to be determined by a Perlin noise function and then setting $\beta = 1 - \alpha$. If you require more customization you could try to create a custom height map or create a grid of Bezier patches on the UV plane. Having half of the torus as $T_1$ and the other as $T_2$ you could use just $$\alpha(u,v) =&#xD;&#xA;\begin{cases}&#xD;&#xA;1-2u, &amp; u \in [0, 0.5]\\&#xD;&#xA;2u - 1, &amp; u \in [0.5, 1]\\&#xD;&#xA;\end{cases}&#xD;&#xA;$$ and once again $\beta(u,v) = 1 - \alpha(u,v)$ (assuming they are both parametrised with $u$ along the toroidal direction). You can create smoother blends by using smoother blending functions.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="41978" PostHistoryTypeId="50" PostId="9267" RevisionGUID="214d38ba-83e3-48c4-88bd-5decbd487e4e" CreationDate="2023-10-11T12:06:05.747" UserId="-1" />
  <row Id="41979" PostHistoryTypeId="50" PostId="8935" RevisionGUID="9de0c0c7-456d-4e8c-a1b1-0d25ef0caf93" CreationDate="2023-10-12T03:09:46.197" UserId="-1" />
  <row Id="41980" PostHistoryTypeId="2" PostId="13754" RevisionGUID="96efd56c-a714-41bc-8002-e7847b1cd787" CreationDate="2023-10-12T11:41:35.947" UserId="11224" Text="As I understand it, with `glEnable(GL_MULTISAMPLE)`, `glEnable(GL_SAMPLE_SHADING)` and `glMinSampleShading(x)`, we can enable multisample antialiased (MSAA) rendering to a multisample frame buffer. The value of the floating-point `x`, between `0.0f` and `1.0f`, imposes a lower bound on the number of fragment shader invocations per sample points. Without setting `glMinSampleShading`, it seems that the fragment shader is invoked once per pixel per primitive, and its output is copied to each of the sample points in the pixel that are covered by the primitive. In this case I guess that the interpolation takes place at the centre of the pixel, which might not be one of the multisample sample points.&#xD;&#xA;&#xD;&#xA;Using values of `x` greater than `0.0f`, we can force the fragment shader to be invoked more than once per pixel, and the output of each invocation to be shared only with a proper subset of the samples. I guess that these subsets form a partition of the set of all samples. My questions are, what is that partition (how does it look, on a diagram of the sample positions) and for each subset, where is the corresponding point, at which the fragment shader carries out interpolation ? Is it one of the sample points ? Or their centroid, perhaps ?&#xD;&#xA;&#xD;&#xA;As far as I know, the answers are implementation dependent, but does anyone know the answers, in any particular cases ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41982" PostHistoryTypeId="1" PostId="13754" RevisionGUID="96efd56c-a714-41bc-8002-e7847b1cd787" CreationDate="2023-10-12T11:41:35.947" UserId="11224" Text="How are multisample samples partitioned in OpenGL, and at which points does interpolation take place?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41983" PostHistoryTypeId="3" PostId="13754" RevisionGUID="96efd56c-a714-41bc-8002-e7847b1cd787" CreationDate="2023-10-12T11:41:35.947" UserId="11224" Text="|opengl|glsl|fragment-shader|antialiasing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41984" PostHistoryTypeId="50" PostId="13355" RevisionGUID="88abc406-d159-4506-84a0-2548ddc791ff" CreationDate="2023-10-12T13:05:05.707" UserId="-1" />
  <row Id="41985" PostHistoryTypeId="50" PostId="13712" RevisionGUID="668278f0-a9d9-4066-888e-b84b33baa381" CreationDate="2023-10-13T19:06:50.873" UserId="-1" />
  <row Id="41991" PostHistoryTypeId="50" PostId="8888" RevisionGUID="e2a1dd61-d1c9-4513-8f81-2afea88fc5f4" CreationDate="2023-10-15T20:03:50.413" UserId="-1" />
  <row Id="41992" PostHistoryTypeId="2" PostId="13756" RevisionGUID="a1d65667-f706-4f98-92f5-ff96d4c734cf" CreationDate="2023-10-16T02:34:32.000" UserId="20700" Text="Looking at the windows HLSL documentation for Texture2DMS.Load found here: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/texture2dms-load&#xD;&#xA;&#xD;&#xA;can someone help me better understand different use cases for this? Specifically, I do not understand why you would need to specify BOTH the sample index and the location? Shouldn't those two pieces of information always be matched together? Why would you ever specify a sample index and simultaneously designate a location that is NOT that samples location???&#xD;&#xA;&#xD;&#xA;I am new to learning how MSAA is fully implemented in the graphics pipeline. This load method here makes me lack confidence in my understanding so far. It seems to me that this method would automatically match the sample index with the sample location." ContentLicense="CC BY-SA 4.0" />
  <row Id="41994" PostHistoryTypeId="1" PostId="13756" RevisionGUID="a1d65667-f706-4f98-92f5-ff96d4c734cf" CreationDate="2023-10-16T02:34:32.000" UserId="20700" Text="Help understanding Texture2D multi-sampling semantics: Why do we need sample index AND location?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41995" PostHistoryTypeId="3" PostId="13756" RevisionGUID="a1d65667-f706-4f98-92f5-ff96d4c734cf" CreationDate="2023-10-16T02:34:32.000" UserId="20700" Text="|rasterizer|hlsl|antialiasing|unity|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="41996" PostHistoryTypeId="5" PostId="13756" RevisionGUID="8153229d-4e19-46bb-b0bf-374db7125f77" CreationDate="2023-10-16T02:38:49.267" UserId="20700" Comment="added 92 characters in body" Text="Looking at the windows HLSL documentation for Texture2DMS.Load found here: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/texture2dms-load&#xD;&#xA;&#xD;&#xA;can someone help me better understand different use cases for this? Specifically, I do not understand why you would need to specify BOTH the sample index and the location? Shouldn't those two pieces of information always be matched together? Why would you ever specify a sample index and simultaneously designate a location that is NOT that samples location???&#xD;&#xA;&#xD;&#xA;I am new to learning how MSAA is fully implemented in the graphics pipeline. This load method here makes me lack confidence in my understanding so far. It seems to me that this method would automatically match the sample index with the sample location.&#xD;&#xA;&#xD;&#xA;Or does the location simply refer to the pixel, rather than a position inside the pixel?" ContentLicense="CC BY-SA 4.0" />
  <row Id="41997" PostHistoryTypeId="5" PostId="13696" RevisionGUID="58fd78ec-f252-4e79-8b80-77d8021e0d0f" CreationDate="2023-10-16T16:48:28.060" UserId="7008" Comment="added the fact, that offset has to be set in the shader, not the host code" Text="***TL;DR***&#xD;&#xA;&#xD;&#xA;In a Vulkan / GLSL ray tracing program, I have several shader files, all accessing the same material buffer of arbitrary data. All materials have an arbitrary layout, e.g. one might be a float, one might contain two vec3s and a float.&#xD;&#xA;Can I access a buffer (i.e. an array of uint type) with just an offset _within the shader (i.e. the same buffer binding is shared, I cannot use dynamic offsets set on the CPU side)_ and read out a struct without having to read every member of the struct individually? I am aware of not being able to read a vec3 from a buffer as just 3 values, but that is not my problem. Just assume I only read good data types that don't waste space.&#xD;&#xA;&#xD;&#xA;See in the image, I want to access at the given green position with just knowing the size of the struct that will follow at that position.&#xD;&#xA;&#xD;&#xA;[![Image of buffer data and where to access it][1]][1]&#xD;&#xA;&#xD;&#xA;In C++ it would be something like this:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;uint32_t* buffer; //assume this has all the data in it&#xD;&#xA;struct mat2&#xD;&#xA;{&#xD;&#xA;    glm::vec3 data1;&#xD;&#xA;    float data2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;//the following line is what I try to achieve&#xD;&#xA;mat2 matData = *((mat2)(buffer+offset);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;***Long explanation***&#xD;&#xA;&#xD;&#xA;I am trying to setup a buffer that contains material parameters. &#xD;&#xA;The problem is that I have to support a large number of materials, that may differ drastically in number of parameters, e.g. there might be an entry with two uints and then an entry with five floats.&#xD;&#xA;&#xD;&#xA;Since I assume using one buffer per material is bad (due to the number of layouts bindings I'd have to use) I wanted to tightly pack the material parameters into a single byte buffer and readout from the shader with a known offset to the material for the hit geometry.&#xD;&#xA;I have a shader file per material, so no material is aware of other material structs - it just knows the offset into the array for its own data.&#xD;&#xA;&#xD;&#xA;While I have basically set up the buffer (though apperantly the smallest chunks I am allowed to use are 4 bytes), I have trouble actually reading out of this buffer in GLSL. Given a simple struct for one material:&#xD;&#xA;&#xD;&#xA;    struct BlinnPhongParams&#xD;&#xA;    {&#xD;&#xA;        vec3 diffuse;&#xD;&#xA;        vec3 specular;&#xD;&#xA;        float specIntensity;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;And the material buffer:&#xD;&#xA;&#xD;&#xA;    layout(binding = 123, set = 0) readonly buffer MaterialParamsBuffer&#xD;&#xA;    {&#xD;&#xA;        uint[] data;&#xD;&#xA;    }uMaterialParamsBuffer;&#xD;&#xA;&#xD;&#xA;Currently I am reading every member from the buffer individually:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        BlinnPhongParams bpParams = BlinnPhongParams(&#xD;&#xA;		    //DiffuseCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+1]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+2])),&#xD;&#xA;		    //SpecularCol&#xD;&#xA;		    vec3(&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+3]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+4]),&#xD;&#xA;		    	uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+5])),&#xD;&#xA;		    //SpecIntensity&#xD;&#xA;		    uintBitsToFloat(uMaterialParamsUintBuffer.data[offset+6])&#xD;&#xA;        );&#xD;&#xA;        return bpParams;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I would like to make reading from this buffer as easy as possible, ideally just say &quot;at this offset, I have a struct that looks like this&quot;, e.g. I would like to have something like this:&#xD;&#xA;&#xD;&#xA;    BlinnPhongParams getMaterialParams(uint offset)&#xD;&#xA;    {&#xD;&#xA;        // here is the problem&#xD;&#xA;        BlinnPhongParams params = BlinnPhongParams(&amp;uMaterialParamsBuffer.data[offset]);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Is this possible?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/27ZwK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="41998" PostHistoryTypeId="2" PostId="13757" RevisionGUID="90312e0c-6cbe-4167-a2f5-26b5ed9bafe1" CreationDate="2023-10-16T17:27:20.233" UserId="20703" Text="I am currently reading the *Ray Tracing in One Weekend* tutorial ([link][1]), and I am dubious about their fix for shadow acne, which is to ignore ray-geometry intersections that occur at very small times.&#xD;&#xA;&#xD;&#xA;For background, my understanding of the basic algorithm of raytracing and shadow acne is as follows:&#xD;&#xA;1. For each pixel in the image, shoot a light ray from the **eye point / camera** through the pixel's designated region in the **image plane**.&#xD;&#xA;2. To find the color of each pixel, calculate the **closest intersection of the ray with the objects in the scene**. Also, use multiple random rays for each pixel (**anti-aliasing**).&#xD;&#xA;3. **Shadow acne:** Now, say that we have some ray $R$ and say its closest intersection time is some floating-point number $t$. Then, $t$ may be inaccurate; if it is a little larger than the actual closest intersection time, then the calculated intersection point will be little *inside* the first object $R$ intersects, rather than being flush with its surface. As a result, the reflected ray will originate from inside the object, and so it will bounce off the inside surface next and continue to bounce inside the object, losing color each time and resulting in the pixel being darker than it should be (essentially, the object will shadow itself).&#xD;&#xA; &#xD;&#xA;Now, the book suggests the following solution. Observe that if the next ray originates from inside the sphere due to $t$ being a little larger than it should have been, then the intersection time for the next ray will be very small, like $0.000001$. The book thus claims that **ignoring small intersection times** (such as all those below $0.001$) suffices to stop such occurrences of shadow acne.&#xD;&#xA;&#xD;&#xA;However, I am dubious. **Consider the following scenario:**&#xD;&#xA;&#xD;&#xA;1. Say we have a sphere $S$ and a ray $R$ that intersects $S$ at two times $t_1 &lt; t_2$.&#xD;&#xA;2. Now, say that $t_1 &lt; 0.001$. Then $t_1$ will be ignored by the book's method, and so $t_2$ will be chosen as the correct intersection time.&#xD;&#xA;3. However, if a ray intersects a sphere twice, then the second intersection will actually be when the ray intersects the sphere from the **inside**! As a result, the ray will be reflected inside the sphere as well, and so then it will bounce and bounce off the interior surface theoretically forever, which has resulted in stack overflows in my code and the given code.&#xD;&#xA;&#xD;&#xA;The main issue here is that **ignoring small intersection times may cause larger intersection times, where the ray actually goes _through_ objects, to be counted as the correct one**.&#xD;&#xA;&#xD;&#xA;**How do we resolve this fundamental issue with the approach of ignoring smaller intersection times where dealing with shadow acne?** Is this a known problem?&#xD;&#xA;&#xD;&#xA;  [1]: https://raytracing.github.io/books/RayTracingInOneWeekend.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="42000" PostHistoryTypeId="1" PostId="13757" RevisionGUID="90312e0c-6cbe-4167-a2f5-26b5ed9bafe1" CreationDate="2023-10-16T17:27:20.233" UserId="20703" Text="Why doesn't using depth biasing to fix shadow acne result in an even bigger problem?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42001" PostHistoryTypeId="3" PostId="13757" RevisionGUID="90312e0c-6cbe-4167-a2f5-26b5ed9bafe1" CreationDate="2023-10-16T17:27:20.233" UserId="20703" Text="|raytracing|shadow|shadow-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42002" PostHistoryTypeId="2" PostId="13758" RevisionGUID="a4e5b4b8-de1b-4a9f-a38c-3b2f776ad92a" CreationDate="2023-10-17T07:59:55.737" UserId="13273" Text="The book &quot;RAY TRACING GEMS (1)&quot; from Nvidia has a whole chapter about avoiding self-intersection. I highly recommend this book because they show different methods about all parts of problems using ray tracing and how to solve them with differently.&#xD;&#xA;&#xD;&#xA;Lets look into chapter 6 &quot;A Fast and Robust Method for Avoiding Self-Intersection&quot;&#xD;&#xA;&#xD;&#xA;I don't want to write down the hole chapter, so I'll collect the information and try to write it my own words.&#xD;&#xA;&#xD;&#xA;In the book they say, that the self intersection problem becomes bigger in case the object is further away from the ray origine. Due to the floating point precision. So when calculating the intersection point, you'll receive the value `t` which becomes less accurate over distance. Therefore the new ray position which is calculated from the value `t` can be behind or infront of the hit surface. Like you already discribed in the question. And those displacement of the calculated position leeds to the problem, that when doing the next ray object intersection, it is not enough to exclude an intersection of $t = 0$ to avoid self intersection.&#xD;&#xA;&#xD;&#xA;**In the book they explain different methods to avoid this:**&#xD;&#xA;&#xD;&#xA; **1. exclude the same primitive:** The idea is very simple. When a ray intersects a triangle, you can write down the unique triangles primitive id. When shooting the reflection ray, you compare the primitive id for each intersection. In case the primitive id is the same, you have a self intersection and you can easily ignore this intersection.&#xD;&#xA;&#xD;&#xA;Sounds good, efficient and easy to implement. But: Lets assume, the calculated hit position is behind the surface and we are extremly close to the neighboring   primitive. Now the reflection direction can lead the ray being through the neighboring primitive. There we have the problem of self intersection again.&#xD;&#xA;&#xD;&#xA;**2. Limiting the ray interval:** This method is what you discribe in your question. Defining an $t_{min} = \epsilon &gt; 0$. So we shoot the reflection ray and only take care of intersections, where $t &gt; t_{min}$. &#xD;&#xA;&#xD;&#xA;Sounds efficient and easy to implement as well. But: $\epsilon$ is scene depending! and will fail for grazing angles, resulting in self-intersection. The second problem is that intersections with neighboring primitives can be wrongly skipped by `t_{min}` and the ray goes inside the geometry as you have discribed in your question.&#xD;&#xA;&#xD;&#xA;**3. Offsetting along the old ray direction:** Same as number 2. But here the $t_{min}$ goes backwards the old ray direction. Again, the same problems occur than in number 2.&#xD;&#xA;&#xD;&#xA;**4. Offsetting along the normal direction of the hit surface:** Here the important part is, that the offset is not fixed distance. So $\epsilon$ has not a fixed value. The offset need to be depending on the distance to the origin. Which can be calculated:&#xD;&#xA;&#xD;&#xA;HLSL Code:&#xD;&#xA;&#xD;&#xA;    constexpr float origin()       { return 1.0f / 32.0f; }&#xD;&#xA;    constexpr float float_scale()  { return 1.0f / 65536.0f; }&#xD;&#xA;    constexpr float int_scale()    { return 1.0f / 256.0f; }&#xD;&#xA;&#xD;&#xA;    //normal points outward for rays exiting the surface, else is flipped.&#xD;&#xA;    float3 offset_ray(const float3 p, const float3 n)&#xD;&#xA;    {&#xD;&#xA;        int3 of_i(int_scale()*n.x, int_scale() *n.y, int_scale()*n.z);&#xD;&#xA;        float3 p_i(&#xD;&#xA;            int_as_float(float_as_int(p.x)+((p.x &lt; 0) ? -of_i.x : of_i.x)),&#xD;&#xA;            int_as_float(float_as_int(p.y)+((p.y &lt; 0) ? -of_i.y : of_i.y)),&#xD;&#xA;            int_as_float(float_as_int(p.z)+((p.z &lt; 0) ? -of_i.z : of_i.z)));&#xD;&#xA;        return float3(fabsf(p.x) &lt; origin() ? p.x+ float_scale()*n.x : p_i.x,&#xD;&#xA;                      fabsf(p.y) &lt; origin() ? p.y+ float_scale()*n.y : p_i.y,&#xD;&#xA;                      fabsf(p.z) &lt; origin() ? p.z+ float_scale()*n.z : p_i.z);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;This source code is from the book: &quot;RAY TRACING GEMS (1)&quot;.&#xD;&#xA;&#xD;&#xA;This solution works with two steps: first sets an initial position as close as possible to the plane of the surface using the surface parameterization. It then shifts the intersection away from the surface by applying a scale-invariant offset to the position, along the geometric normal. The provided program code is doing the second step!&#xD;&#xA;&#xD;&#xA;There are still cases, where problems can occur. But in the book they say these cases are extremly rare.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42004" PostHistoryTypeId="2" PostId="13759" RevisionGUID="ec08b07e-0240-44b6-b0a3-3c31b014836e" CreationDate="2023-10-17T19:19:16.793" UserId="20045" Text="I'm writing a small path tracer that currently:&#xD;&#xA;- Samples a random light source at each bounce (direct lighting)&#xD;&#xA;- Bounces rays around multiple times (indirect lighting)&#xD;&#xA;- The scene only contains lambertian materials so the directions for the ray bounces are generated according either to a uniform distribution over the hemisphere or a cosine weighted distribution.&#xD;&#xA;&#xD;&#xA;**The issue:** Generating the directions with the cosine weighted distribution gives a slightly darker results in some part of the image than when using a uniform distribution and the variance doesn't seem to be improved as much as it should. It also introduces fireflies (supposedly because of the PDF that can get very close to 0 when `rand_2` gets close to 0, see the code below).&#xD;&#xA;&#xD;&#xA;**Results:**&#xD;&#xA;&#xD;&#xA;Cosine weighted on the left, uniform distribution over the hemisphere on the right:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The fireflies are obvious when zooming in a little bit. The front face (visible) of the small cube is darker than in the right image (uniform distribution).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ilfmr.jpg&#xD;&#xA;&#xD;&#xA;**The code**:&#xD;&#xA;&#xD;&#xA;**Direction generation (uniform and cosine):**&#xD;&#xA;&#xD;&#xA;    void branchlessONB(const Vector&amp; n, Vector&amp; b1, Vector&amp; b2)&#xD;&#xA;    {&#xD;&#xA;        float sign = sycl::copysign(1.0f, n.z);&#xD;&#xA;        const float a = -1.0f / (sign + n.z);&#xD;&#xA;        const float b = n.x * n.y * a;&#xD;&#xA;        b1 = Vector(1.0f + sign * n.x * n.x * a, sign * b, -sign * n.x);&#xD;&#xA;        b2 = Vector(b, sign + n.y * n.y * a, -n.y);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Vector RenderKernel::rotate_vector_around_normal(const Vector&amp; normal, const Vector&amp; random_dir_local_space) const&#xD;&#xA;    {&#xD;&#xA;        Vector tangent, bitangent;&#xD;&#xA;        branchlessONB(normal, tangent, bitangent);&#xD;&#xA;    &#xD;&#xA;        //Transforming from the random_direction in its local space to the space around the normal&#xD;&#xA;        //given in parameter (the space with the given normal as the Z up vector)&#xD;&#xA;        return random_dir_local_space.x * tangent + random_dir_local_space.y * bitangent + random_dir_local_space.z * normal;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Vector RenderKernel::uniform_direction_around_normal(const Vector&amp; normal, float&amp; pdf, xorshift32_generator&amp; random_number_generator) const&#xD;&#xA;    {&#xD;&#xA;        float rand_1 = random_number_generator();&#xD;&#xA;        float rand_2 = random_number_generator();&#xD;&#xA;    &#xD;&#xA;        float phi = 2.0f * M_PI * rand_1;&#xD;&#xA;        float root = sycl::sqrt(1 - rand_2 * rand_2);&#xD;&#xA;    &#xD;&#xA;        pdf = 1.0f / (2.0f * M_PI);&#xD;&#xA;    &#xD;&#xA;        //Generating a random direction in a local space with Z as the Up vector&#xD;&#xA;        Vector random_dir_local_space(sycl::cos(phi) * root, sycl::sin(phi) * root, rand_2);&#xD;&#xA;        return rotate_vector_around_normal(normal, random_dir_local_space);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    Vector RenderKernel::cosine_weighted_direction_around_normal(const Vector&amp; normal, float&amp; pdf, xorshift32_generator&amp; random_number_generator) const&#xD;&#xA;    {&#xD;&#xA;        float rand_1 = random_number_generator();&#xD;&#xA;        float rand_2 = random_number_generator();&#xD;&#xA;    &#xD;&#xA;        float sqrt_rand_2 = sycl::sqrt(rand_2);&#xD;&#xA;        float phi = 2.0f * M_PI * rand_1;&#xD;&#xA;        float cos_theta = sqrt_rand_2;&#xD;&#xA;        float sin_theta = sycl::sqrt(sycl::max(0.0f, 1.0f - cos_theta * cos_theta));&#xD;&#xA;    &#xD;&#xA;        pdf = sqrt_rand_2 / M_PI;&#xD;&#xA;    &#xD;&#xA;        //Generating a random direction in a local space with Z as the Up vector&#xD;&#xA;        Vector random_dir_local_space = Vector(sycl::cos(phi) * sin_theta, sycl::sin(phi) * sin_theta, sqrt_rand_2);&#xD;&#xA;        return rotate_vector_around_normal(normal, random_dir_local_space);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;**Ray bounce part:**&#xD;&#xA;&#xD;&#xA;    for (int bounce = 0; bounce &lt; MAX_BOUNCES; bounce++)&#xD;&#xA;            {&#xD;&#xA;                if (next_ray_state == BOUNCE)&#xD;&#xA;                {&#xD;&#xA;                    HitInfo closest_hit_info;&#xD;&#xA;                    bool intersection_found = intersect_scene(ray, closest_hit_info);&#xD;&#xA;    &#xD;&#xA;                    if (intersection_found)&#xD;&#xA;                    {&#xD;&#xA;                        //Indirect lighting&#xD;&#xA;                        int material_index = m_materials_indices_buffer[closest_hit_info.triangle_index];&#xD;&#xA;                        SimpleMaterial mat = m_materials_buffer_access[material_index];&#xD;&#xA;    &#xD;&#xA;                        throughput *= mat.diffuse;&#xD;&#xA;                        if (bounce == 0)&#xD;&#xA;                            sample_color += mat.emission;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;                        // Direct lighting&#xD;&#xA;                        float pdf;&#xD;&#xA;                        LightSourceInformation light_source_info;&#xD;&#xA;                        Point random_light_point = sample_random_point_on_lights(random_number_generator, pdf, light_source_info);&#xD;&#xA;                        Point shadow_ray_origin = closest_hit_info.inter_point + closest_hit_info.normal_at_inter * 1.0e-4f;&#xD;&#xA;                        Vector shadow_ray_direction = random_light_point - shadow_ray_origin;&#xD;&#xA;                        float distance_to_light = length(shadow_ray_direction);&#xD;&#xA;                        Vector shadow_ray_direction_normalized = normalize(shadow_ray_direction);&#xD;&#xA;    &#xD;&#xA;                        Ray shadow_ray(shadow_ray_origin, shadow_ray_direction_normalized);&#xD;&#xA;    &#xD;&#xA;                        bool in_shadow = evaluate_shadow_ray(shadow_ray, distance_to_light);&#xD;&#xA;    &#xD;&#xA;                        Color radiance = Color(0.0f, 0.0f, 0.0f);&#xD;&#xA;                        if (!in_shadow)&#xD;&#xA;                        {&#xD;&#xA;                            const SimpleMaterial&amp; emissive_triangle_material = m_materials_buffer_access[m_materials_indices_buffer[light_source_info.emissive_triangle_index]];&#xD;&#xA;    &#xD;&#xA;                            radiance = emissive_triangle_material.emission;&#xD;&#xA;                            //Cosine angle on the illuminated surface&#xD;&#xA;                            radiance *= sycl::max(dot(closest_hit_info.normal_at_inter, shadow_ray_direction_normalized), 0.0f);&#xD;&#xA;                            //Cosine angle on the light surface&#xD;&#xA;                            radiance *= sycl::max(dot(light_source_info.light_source_normal, -shadow_ray_direction_normalized), 0.0f);&#xD;&#xA;                            //Falloff of the light intensity with the distance squared&#xD;&#xA;                            radiance /= distance_to_light * distance_to_light;&#xD;&#xA;                            //PDF: Probability of having chosen this point on this exact light source&#xD;&#xA;                            radiance /= pdf;&#xD;&#xA;                            //The illuminated surface is Lambertian&#xD;&#xA;                            radiance /= M_PI;&#xD;&#xA;                        }&#xD;&#xA;    &#xD;&#xA;                        Vector random_dir = cosine_weighted_direction_around_normal(closest_hit_info.normal_at_inter, random_direction_pdf, random_number_generator);&#xD;&#xA;                        Point new_ray_origin = closest_hit_info.inter_point + closest_hit_info.normal_at_inter * 1.0e-4f;&#xD;&#xA;    &#xD;&#xA;                        ray = Ray(new_ray_origin, normalize(random_dir));&#xD;&#xA;                        next_ray_state = RayState::BOUNCE;&#xD;&#xA;    &#xD;&#xA;                        sample_color += radiance * throughput / random_direction_pdf;&#xD;&#xA;                    }&#xD;&#xA;                    else&#xD;&#xA;                        next_ray_state = RayState::MISSED;&#xD;&#xA;                }&#xD;&#xA;                else if (next_ray_state == MISSED)&#xD;&#xA;                {&#xD;&#xA;                    //Handle skysphere here&#xD;&#xA;                    break;&#xD;&#xA;                }&#xD;&#xA;                else if (next_ray_state == TERMINATED)&#xD;&#xA;                    break;&#xD;&#xA;            }&#xD;&#xA;&#xD;&#xA;**Light source sampling part:**&#xD;&#xA;&#xD;&#xA;    Point RenderKernel::sample_random_point_on_lights(xorshift32_generator&amp; random_number_generator, float&amp; pdf, LightSourceInformation&amp; light_info) const&#xD;&#xA;    {&#xD;&#xA;        light_info.emissive_triangle_index = random_number_generator() * m_emissive_triangle_indices_buffer.size();&#xD;&#xA;        light_info.emissive_triangle_index = m_emissive_triangle_indices_buffer[light_info.emissive_triangle_index];&#xD;&#xA;        Triangle random_emissive_triangle = m_triangle_buffer_access[light_info.emissive_triangle_index];&#xD;&#xA;    &#xD;&#xA;        float rand_1 = random_number_generator();&#xD;&#xA;        float rand_2 = random_number_generator();&#xD;&#xA;    &#xD;&#xA;        float sqrt_r1 = sycl::sqrt(rand_1);&#xD;&#xA;        float u = 1.0f - sqrt_r1;&#xD;&#xA;        float v = (1.0f - rand_2) * sqrt_r1;&#xD;&#xA;    &#xD;&#xA;        Vector AB = random_emissive_triangle.m_b - random_emissive_triangle.m_a;&#xD;&#xA;        Vector AC = random_emissive_triangle.m_c - random_emissive_triangle.m_a;&#xD;&#xA;    &#xD;&#xA;        Point random_point_on_triangle = random_emissive_triangle.m_a + AB * u + AC * v;&#xD;&#xA;    &#xD;&#xA;        Vector normal = cross(AB, AC);&#xD;&#xA;        float length_normal = length(normal);&#xD;&#xA;        light_info.light_source_normal = normal / length_normal; //Normalized&#xD;&#xA;        float triangle_area = length_normal * 0.5f;&#xD;&#xA;        float nb_emissive_triangles = m_emissive_triangle_indices_buffer.size();&#xD;&#xA;        //m_out_stream &lt;&lt; triangle_area &lt;&lt; sycl::endl;&#xD;&#xA;        pdf = 1 / (nb_emissive_triangles * triangle_area);&#xD;&#xA;    &#xD;&#xA;        return random_point_on_triangle;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    bool RenderKernel::evaluate_shadow_ray(Ray&amp; ray, float t_max) const&#xD;&#xA;    {&#xD;&#xA;        HitInfo hit_info;&#xD;&#xA;        intersect_scene(ray, hit_info);&#xD;&#xA;        if (hit_info.t + 1.0e-4f &lt; t_max)&#xD;&#xA;            //There is something in between the light and the origin of the ray&#xD;&#xA;            return true;&#xD;&#xA;        else&#xD;&#xA;            return false;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42006" PostHistoryTypeId="1" PostId="13759" RevisionGUID="ec08b07e-0240-44b6-b0a3-3c31b014836e" CreationDate="2023-10-17T19:19:16.793" UserId="20045" Text="Cosine weighted hemisphere sampling is a little bit darker and arguably noisier than reference" ContentLicense="CC BY-SA 4.0" />
  <row Id="42007" PostHistoryTypeId="3" PostId="13759" RevisionGUID="ec08b07e-0240-44b6-b0a3-3c31b014836e" CreationDate="2023-10-17T19:19:16.793" UserId="20045" Text="|pathtracing|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42008" PostHistoryTypeId="2" PostId="13760" RevisionGUID="56e62b3b-f5c6-4910-b863-6749372e5e4a" CreationDate="2023-10-18T04:49:46.063" UserId="19537" Text="One thing confuses me in your code. Since you say that you are sampling BRDF and light source together, I figured it might be possible that you did change the sampling methods between `uniform` and `cosine-weight` but you forgot to have the corresponding PDF for the MIS weight. Then I found that you aren't using any MIS, and instead, the evaluation for direct and indirect components seem weird:&#xD;&#xA;- Direct illumination estimation:&#xD;&#xA;```c++&#xD;&#xA;sample_color += radiance * throughput / random_direction_pdf;&#xD;&#xA;```&#xD;&#xA;I don't think this is correct. You see, the `radiance` here is the direct component and has nothing to do with ray direction sampling (unless you are using MIS with BRDF PDF evaluation). That means:&#xD;&#xA;```c++&#xD;&#xA;Vector random_dir = cosine_weighted_direction_around_normal(..., random_direction_pdf, ...);&#xD;&#xA;Point new_ray_origin = ...;&#xD;&#xA;&#xD;&#xA;ray = Ray(new_ray_origin, normalize(random_dir));&#xD;&#xA;next_ray_state = ...;&#xD;&#xA;sample_color += radiance * throughput / random_direction_pdf;&#xD;&#xA;/// ======== should actually just be like the following ==========&#xD;&#xA;// accumulate direct illunination&#xD;&#xA;sample_color += radiance * throughput;&#xD;&#xA;// update ray direction to account for indirect subsequent bounces &#xD;&#xA;Vector random_dir = cosine_weighted_direction_around_normal(..., random_direction_pdf, ...);&#xD;&#xA;Point new_ray_origin = ...;&#xD;&#xA;&#xD;&#xA;ray = Ray(new_ray_origin, normalize(random_dir));&#xD;&#xA;next_ray_state = ...;&#xD;&#xA;```&#xD;&#xA;Why? See the following figure:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The red line segment is shadow ray, and the sampling decision is only related to how you: &#xD;&#xA;1. sample an emitter (if there are multiple) &#xD;&#xA;2. sample a point from that emitter. &#xD;&#xA;3. get PDF (area product measure) for sampling the very point on that emitter&#xD;&#xA;4. Transform to solid angle measure (falloff, cosine attenuation, etc. I think you did it right)&#xD;&#xA;&#xD;&#xA;Essentially, after `if (!in_shadow)` branch being finished, the direct illumination already has its unbiased estimation. So you just add it to `radiance` and account for the path throughput from the previous bounces.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- Throughput update:&#xD;&#xA;```c++&#xD;&#xA;throughput *= mat.diffuse;&#xD;&#xA;```&#xD;&#xA;Note that all the subsequent bounces are **sampled** (ray direction sampling and intersection test to obtain new ray origin and direction), you should account for the sampling event here by:&#xD;&#xA;```c++&#xD;&#xA;throughput *= mat.diffuse * sycl::max(dot(closest_hit_info.normal_at_inter, random_dir), 0.0f) / random_direction_pdf;&#xD;&#xA;```&#xD;&#xA;This should be correct for throughput update, the derivation is simple: the following figure shows how the incident ray gets attenuated by BRDF and cosine term.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Since our light incident direction (corresponds to `random_dir`) is sampled, we have the following estimator and we can easily verify its expectation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\hat{I}=L_i(x, w_i)\frac{f\cdot \cos\theta}{\text{PDF}(w_i)}\\&#xD;&#xA;\mathbb{E}(\hat{I}) = \int_{\Omega_{\text{hemisphere}}}\frac{L_i(x, w_i)f\cdot \cos\theta}{\text{PDF}(w_i)}\text{PDF}(w_i) dw_i = \int_{\Omega_{\text{hemisphere}}}L_i(x, w_i)f\cdot \cos\theta dw_i&#xD;&#xA;$$&#xD;&#xA;and obviously the expectation is what we are looking for: to integrate the incident radiance from all directions on the hemisphere and apply surface interaction terms.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So, in all, I think you should solve the following problems first before you can dive deeper into what the rendering results should actually be:&#xD;&#xA;- Direct illumination: use `sample_color += radiance * throughput;` instead.&#xD;&#xA;- Path through update: use `throughput *= mat.diffuse * sycl::max(dot(closest_hit_info.normal_at_inter, random_dir), 0.0f) / random_direction_pdf;` instead.&#xD;&#xA;&#xD;&#xA;and since you are using BRDF sampling and emitter sampling at the same time, you can try to use MIS to combine both sampling methods to converge even faster. For more information on the logic for simple path tracer, refer to [pbrt-v3: src/integrators/path.cpp:Li()](https://github.com/mmp/pbrt-v3/blob/master/src/integrators/path.cpp). If you find anything wrong or difficult to understand in this answer, comment to let me know.&#xD;&#xA;&#xD;&#xA;By the way, can you point me to the repo for your code? I'd like to try this when I 'm available.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6tHKs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/JXo9R.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42014" PostHistoryTypeId="2" PostId="13762" RevisionGUID="1785b1a9-c5cd-4fb9-b31a-76f7c9d3ff25" CreationDate="2023-10-19T21:57:38.203" UserId="9779" Text="I'd like to have a helper function in the Common tab that does something fancy with texture input and returns the result. I'd like the function in question to be able to use any `iChannel`, like:&#xD;&#xA;&#xD;&#xA;    vec3 do_something_fancy( in channelType channel, in vec2 uv, yodeling monkey_nuggets) {&#xD;&#xA;        vec4 lookup_result = texture(channel, uv);&#xD;&#xA;&#xD;&#xA;        ...&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I've taken a few guesses as to the type of `iChannel[0-4]` but have struck out. " ContentLicense="CC BY-SA 4.0" />
  <row Id="42016" PostHistoryTypeId="1" PostId="13762" RevisionGUID="1785b1a9-c5cd-4fb9-b31a-76f7c9d3ff25" CreationDate="2023-10-19T21:57:38.203" UserId="9779" Text="What's the type of iChannel[0-3] in Shadertoy?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42017" PostHistoryTypeId="3" PostId="13762" RevisionGUID="1785b1a9-c5cd-4fb9-b31a-76f7c9d3ff25" CreationDate="2023-10-19T21:57:38.203" UserId="9779" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42018" PostHistoryTypeId="2" PostId="13763" RevisionGUID="f3671d18-0665-47ad-8831-93b941829d27" CreationDate="2023-10-19T22:36:04.933" UserId="20718" Text="I am trying to raytrace an image of a black hole, but given my current difficulties of doing so with the formalism of relativity, I've decided to do my raytracing using Newton's law of gravitation instead:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;a = -GM / r^2&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is my code so far:&#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;import numpy as np&#xD;&#xA;from PIL import Image&#xD;&#xA;&#xD;&#xA;M = 500.0&#xD;&#xA;max_iterations = 100&#xD;&#xA;dt = 0.1&#xD;&#xA;&#xD;&#xA;img_width = 160&#xD;&#xA;img_height = 90&#xD;&#xA;resolution = (img_width, img_height)&#xD;&#xA;sensor_width = 0.035&#xD;&#xA;focal_length = 0.025&#xD;&#xA;camera_origin = np.array([0, 7 * M, 0])&#xD;&#xA;&#xD;&#xA;def norm(x):&#xD;&#xA;    return (x.dot(x)) ** (1/2)&#xD;&#xA;&#xD;&#xA;def normalize(x):&#xD;&#xA;    return x / norm(x)&#xD;&#xA;&#xD;&#xA;class Camera:&#xD;&#xA;    def __init__(self, pos=camera_origin, resolution=resolution, sensor_width=sensor_width, focal_length=focal_length, z_rotation=np.pi / 4):&#xD;&#xA;        rot_z = np.array([&#xD;&#xA;                    [np.cos(z_rotation), -np.sin(z_rotation), 0],&#xD;&#xA;                    [np.sin(z_rotation), np.cos(z_rotation), 0],&#xD;&#xA;                    [0, 0, 1]&#xD;&#xA;                ])&#xD;&#xA;        self.rot_matrix = rot_z&#xD;&#xA;        self.pos = np.matmul(rot_z, pos)&#xD;&#xA;        self.resolution = resolution&#xD;&#xA;        self.sensor_width = sensor_width&#xD;&#xA;        self.focal_length = focal_length&#xD;&#xA;    &#xD;&#xA;    def ray_vel(self, i, j):&#xD;&#xA;        w, h = self.resolution&#xD;&#xA;        aspect_ratio = w / h&#xD;&#xA;        # The u and v vectors are&#xD;&#xA;        # the vectors of the camera&#xD;&#xA;        # viewport&#xD;&#xA;        u = self.sensor_width&#xD;&#xA;        v = -self.sensor_width / aspect_ratio&#xD;&#xA;        du = u / w&#xD;&#xA;        dv = v / h&#xD;&#xA;        # Find the directional vector&#xD;&#xA;        # of a ray that passes through&#xD;&#xA;        # a given pixel&#xD;&#xA;        x = -u/2 + (i + 1) * du&#xD;&#xA;        y = self.focal_length&#xD;&#xA;        z = -v/2 + (j + 1) * dv&#xD;&#xA;        pixel_dir = np.array([x, y, z])&#xD;&#xA;        # Rotate the directional vector about&#xD;&#xA;        # the z-axis with given amount&#xD;&#xA;        pixel_dir = np.matmul(self.rot_matrix, pixel_dir)&#xD;&#xA;        # Make these unit vectors&#xD;&#xA;        # as speed of light in geometrized&#xD;&#xA;        # units is 1&#xD;&#xA;        return normalize(pixel_dir)&#xD;&#xA;&#xD;&#xA;class Ray:&#xD;&#xA;    def __init__(self, origin, direction):&#xD;&#xA;        self.origin = origin&#xD;&#xA;        self.direction = direction&#xD;&#xA;&#xD;&#xA;    def compute(self, t):&#xD;&#xA;        pos = self.origin&#xD;&#xA;        vels = self.direction&#xD;&#xA;        # Use Euler's method to&#xD;&#xA;        # numerically solve&#xD;&#xA;        # the differential equation&#xD;&#xA;        # a = -GM/r^2&#xD;&#xA;        for i in range(t):&#xD;&#xA;            r = norm(pos)&#xD;&#xA;            vels -= M / (r ** 2) * dt&#xD;&#xA;            pos += vels * dt&#xD;&#xA;        return vels&#xD;&#xA;&#xD;&#xA;    def trace(self, tmax=100):&#xD;&#xA;        ray_dir = self.compute(tmax)&#xD;&#xA;        v_x, v_y, v_z = normalize(ray_dir)&#xD;&#xA;        color_r = int(abs(v_x) * 255)&#xD;&#xA;        color_g = int(abs(v_y) * 255)&#xD;&#xA;        color_b = int(abs(v_z) * 255)&#xD;&#xA;        return (color_r, color_g, color_b)&#xD;&#xA;&#xD;&#xA;bh_img = Image.new(&quot;RGB&quot;, (img_width, img_height))&#xD;&#xA;counter = 0&#xD;&#xA;camera = Camera()&#xD;&#xA;&#xD;&#xA;print(&quot;Beginning raytracing...&quot;)&#xD;&#xA;for i in range(0, img_width):&#xD;&#xA;    for j in range(0, img_height):&#xD;&#xA;        ray_origin = camera.pos&#xD;&#xA;        ray_dir = camera.ray_vel(i, j)&#xD;&#xA;        ray = Ray(ray_origin, ray_dir)&#xD;&#xA;        color = ray.trace(max_iterations)&#xD;&#xA;        bh_img.putpixel((i, j), color)&#xD;&#xA;        if counter % 1000 == 0:&#xD;&#xA;            print(f&quot;Computed ray {counter} of {img_width * img_height}&quot;)&#xD;&#xA;        counter += 1&#xD;&#xA;&#xD;&#xA;bh_img.save(&quot;render_output.jpg&quot;)   &#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;My code essentially emits rays from the camera, computes their trajectories as they orbit around the black hole, and then finds their final direction, which I have outputted as an RGB color for debugging purposes. What is bizarre to me is that regardless of the values of `M` I use, the raytraced image looked exactly as if I just outputted the initial ray direction. There is seemingly no change in ray direction as the rays are traced around the black hole. Is there any reason why this is?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42020" PostHistoryTypeId="1" PostId="13763" RevisionGUID="f3671d18-0665-47ad-8831-93b941829d27" CreationDate="2023-10-19T22:36:04.933" UserId="20718" Text="Why would an image look the same pre-raytracing and post-raytracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42021" PostHistoryTypeId="3" PostId="13763" RevisionGUID="f3671d18-0665-47ad-8831-93b941829d27" CreationDate="2023-10-19T22:36:04.933" UserId="20718" Text="|raytracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42022" PostHistoryTypeId="2" PostId="13764" RevisionGUID="a18cf631-dbc0-4ddc-a2d4-7ed8549e36f1" CreationDate="2023-10-19T23:42:05.197" UserId="9779" Text="Google was useless for answering this one, but I was surprised that Bard got it on the first go:&#xD;&#xA;&#xD;&#xA;    vec3 do_something_fancy( in sample2D channel, in vec2 uv, yodeling monkey_nuggets) {&#xD;&#xA;        vec4 lookup_result = texture(channel, uv);&#xD;&#xA;&#xD;&#xA;        ...&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42025" PostHistoryTypeId="2" PostId="13765" RevisionGUID="0943e6fc-7676-4626-a2f5-948236e49504" CreationDate="2023-10-20T08:35:28.157" UserId="7724" Text="You can click 'Shader inputs' above the panel containing the code to obtain a dropdown with all the types:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;As can be seen here the type is either sampler2D or samplerCube.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/rhHky.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42027" PostHistoryTypeId="2" PostId="13766" RevisionGUID="e796905a-20c8-44b5-86ee-e15cb8201e2c" CreationDate="2023-10-20T08:57:52.463" UserId="20720" Text="## Information ##&#xD;&#xA;I have to render a map, that is rendered as a 2d collection of squares of different color, separated by white lines horizontally and vertically. There may be ~600000 squares surrounded by white area, and the actual borders of the map are arbitrary, only one part of map will be visible at a time, so it must not be rendered fully at once (the map is scrollable). The map is interactive, so it must change the color of square when hovering (dark green square) and it is possible to select some rectangle area (purple square collection), zoom in zoom out + a minimap to quickly move from one point to another. There are blue squares that are owned, and they have borders like in images. As an addition there can be images attached to any owned rectangular area.&#xD;&#xA;&#xD;&#xA;## Actual Implementation ##&#xD;&#xA;Below is the current implementation which is based on html canvases, and it is not as performant as I want, so I decided to use webgl for rendering.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;## What I've Tried / Research ##&#xD;&#xA;I tried using ThreeJS to achieve this, but I think it is mostly 3d oriented and also it has many unwanted functionality that I will not use, so I decided to go with bare minimum. I've tried to write some fragment shaders, and achieved some functionality (selected area, hovered object). I am quite new to WebGL/OpenGL, I've read somewhere that it is possible to pass buffer to fragment shader as a texture, and I was thinking about forming a buffer  of UInt8 from whole map (even the empty area, for shader to be able to correctly draw borders) and passing it to fragment shader, which will distinguish the state by number of each element and draw the squares accordingly. But then I realized that even before adding images functionality much load will be offloaded to fragment shader, and it was not clear will the fragment shader be able to handle all this much load alone. Doing some research I found out that it is possible to use points and their size parameter to achieve this, and I think that it could be beneficial to split some of work to vertex shader, instead of doing everything in fragment shader.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## What I want to achieve ##&#xD;&#xA;&#xD;&#xA;I want to be able to render this map on nearly every device, because in my opinion current hardware is able to do this kind of work very efficiently and very performant. I understand that it is very dependent on implementation, so here's my question.&#xD;&#xA;&#xD;&#xA;## Question ##&#xD;&#xA;&#xD;&#xA;Will it give some performance improvements or will it be worse to offload this type of work to vertex shader and draw each square as a point?&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/UxyzB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Mn3fO.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/URJfH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42029" PostHistoryTypeId="1" PostId="13766" RevisionGUID="e796905a-20c8-44b5-86ee-e15cb8201e2c" CreationDate="2023-10-20T08:57:52.463" UserId="20720" Text="How to correctly handle rendering of ~600000, arbitrary colored 2D squares with WebGL?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42030" PostHistoryTypeId="3" PostId="13766" RevisionGUID="e796905a-20c8-44b5-86ee-e15cb8201e2c" CreationDate="2023-10-20T08:57:52.463" UserId="20720" Text="|opengl|rendering|shader|glsl|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42031" PostHistoryTypeId="5" PostId="13766" RevisionGUID="f5688d22-a4b6-460f-9a66-cbbc03093d6e" CreationDate="2023-10-20T09:15:25.793" UserId="20720" Comment="added 182 characters in body" Text="## Information ##&#xD;&#xA;I have to render a map, that is rendered as a 2d collection of squares of different color, separated by white lines horizontally and vertically. There may be ~600000 squares surrounded by white area, and the actual borders of the map are arbitrary, only one part of map will be visible at a time, so it must not be rendered fully at once (the map is scrollable). The map is interactive, so it must change the color of square when hovering (dark green square) and it is possible to select some rectangle area (purple square collection), zoom in zoom out + a minimap to quickly move from one point to another. There are blue squares that are owned, and they have borders like in images. As an addition there can be images attached to any owned rectangular area.&#xD;&#xA;&#xD;&#xA;## Actual Implementation ##&#xD;&#xA;Below is the current implementation which is based on html canvases, and it is not as performant as I want, so I decided to use webgl for rendering.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;## What I've Tried / Research ##&#xD;&#xA;I tried using ThreeJS to achieve this, but I think it is mostly 3d oriented and also it has many unwanted functionality that I will not use, so I decided to go with bare minimum. I've tried to write some fragment shaders, and achieved some functionality (selected area, hovered object). I am quite new to WebGL/OpenGL, I've read somewhere that it is possible to pass buffer to fragment shader as a texture, and I was thinking about forming a buffer  of UInt8 from whole map (even the empty area, for shader to be able to correctly draw borders) and passing it to fragment shader, which will distinguish the state by number of each element and draw the squares accordingly. But then I realized that even before adding images functionality much load will be offloaded to fragment shader, and it was not clear will the fragment shader be able to handle all this much load alone. Doing some research I found out that it is possible to use points and their size parameter to achieve this, and I think that it could be beneficial to split some of work to vertex shader, instead of doing everything in fragment shader.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;## What I want to achieve ##&#xD;&#xA;&#xD;&#xA;I want to be able to render this map on nearly every device, because in my opinion current hardware is able to do this kind of work very efficiently and very performant. I understand that it is very dependent on implementation, so here are my questions:&#xD;&#xA;&#xD;&#xA;## Question ##&#xD;&#xA;&#xD;&#xA;Will it give some performance improvements or will it be worse to offload this type of work to vertex shader and draw each square as a point? What abilities of WebGL or techniques can I use (or are mostly used) to handle this kind of situation? How can I achieve performant rendering in case when there are multiple images?&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/UxyzB.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Mn3fO.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/URJfH.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42032" PostHistoryTypeId="2" PostId="13767" RevisionGUID="502dcf53-6f3a-4540-8f32-395b9de631f3" CreationDate="2023-10-20T11:00:32.450" UserId="7952" Text="Even the most modest modern GPU can breeze through 10 million triangles a frame and still hit acceptable frame rates, so performance of the vertex shader isn't likely to be an issue.&#xD;&#xA;&#xD;&#xA;For example each square could be defined as a pair of triangles. And the entire works drawn as a single draw call. The rasterizer (which is run after the vertex shader) would discard and trim triangles that are not visible or are partially visible (when zoomed for example). And vertex attributes can provide identifying information so the fragment shader can perform appropriate shading on a per square basis.&#xD;&#xA;&#xD;&#xA;Triangles are plainer so are inherently 2 dimensional, a 2D projection is applied to the 2D vertex position in the vertex shader, A fixed `z` value is set as the last step for setting the gl_postion. Which is then processed by the rasterizer. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;This would allow the fragment shader to focus on drawing a single square, and to draw the lines between the squares as variable sized. It would also allow for soothing operations on the lines just by computing the distance to the nearest line and using a mix operation. This would solve the rather tricky situation of being fully zoomed out where 775x775 lines could essentially take over the entire scene.&#xD;&#xA;&#xD;&#xA;So don't be afraid to go for a rasterized triangle based version of this, performance really shouldn't be an issue." ContentLicense="CC BY-SA 4.0" />
  <row Id="42034" PostHistoryTypeId="50" PostId="13484" RevisionGUID="c2a9fd95-1b2a-4f09-8826-672d6c250d51" CreationDate="2023-10-20T14:03:15.380" UserId="-1" />
  <row Id="42040" PostHistoryTypeId="50" PostId="13722" RevisionGUID="91dc3fc4-969a-4799-80df-ff14f03fc56d" CreationDate="2023-10-21T11:04:25.507" UserId="-1" />
  <row Id="42050" PostHistoryTypeId="50" PostId="10619" RevisionGUID="a3675d64-4326-4c59-9986-54d1b2d0c243" CreationDate="2023-10-21T19:06:40.773" UserId="-1" />
  <row Id="42051" PostHistoryTypeId="2" PostId="13771" RevisionGUID="b0c75f42-372d-4db0-94cd-991410c892fa" CreationDate="2023-10-22T12:59:52.000" UserId="6064" Text="I am trying to use 2 &quot;D3D12_DESCRIPTOR_RANGE&quot; in a root descriptor table,defined as follows:&#xD;&#xA;```&#xD;&#xA;//1st range &#xD;&#xA;D3D12_DESCRIPTOR_RANGE materialtablerange = {};&#xD;&#xA;materialtablerange.OffsetInDescriptorsFromTableStart = 0;&#xD;&#xA;materialtablerange.NumDescriptors = 1;&#xD;&#xA;materialtablerange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE::D3D12_DESCRIPTOR_RANGE_TYPE_SRV;&#xD;&#xA;materialtablerange.RegisterSpace = 0;&#xD;&#xA;materialtablerange.BaseShaderRegister = 1;&#xD;&#xA;D3D12_DESCRIPTOR_RANGE* tableranges = new D3D12_DESCRIPTOR_RANGE[2];&#xD;&#xA;//2nd range&#xD;&#xA;D3D12_DESCRIPTOR_RANGE texturesrvrange = {};&#xD;&#xA;texturesrvrange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE::D3D12_DESCRIPTOR_RANGE_TYPE_SRV;&#xD;&#xA;texturesrvrange.BaseShaderRegister = 0;&#xD;&#xA;texturesrvrange.RegisterSpace = 0;&#xD;&#xA;texturesrvrange.NumDescriptors = -1;&#xD;&#xA;texturesrvrange.OffsetInDescriptorsFromTableStart = 2;&#xD;&#xA;```&#xD;&#xA;So we have 1st range which specifies 1 srv and 2nd range which defines an unbound srv array.&#xD;&#xA;Unfortunately this does not seems to work as when I try to serialize the rootsignature via &quot;D3D12SerializeRootSignature&quot;.I get &quot;E_INVALIDARG&quot; return code and error msg(from blob as following:&#xD;&#xA;&quot;Shader register range of type SRV (root parameter [1], visibility PIXEL, descriptor table slot [1]) overlaps with another shader register range (root parameter[1], visibility PIXEL, descriptor table slot [0]).&quot;&#xD;&#xA;This issue seems to go away if I set NumDescriptors in 2nd range as 1.So I wanted to understand why these 2 ranges are raising an overlap error message in rootsignature Serialize and how to set it up properly,if possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42053" PostHistoryTypeId="1" PostId="13771" RevisionGUID="b0c75f42-372d-4db0-94cd-991410c892fa" CreationDate="2023-10-22T12:59:52.000" UserId="6064" Text="How to use unbound descriptor range properly in descriptor tables" ContentLicense="CC BY-SA 4.0" />
  <row Id="42054" PostHistoryTypeId="3" PostId="13771" RevisionGUID="b0c75f42-372d-4db0-94cd-991410c892fa" CreationDate="2023-10-22T12:59:52.000" UserId="6064" Text="|vulkan|hlsl|directx12|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42055" PostHistoryTypeId="2" PostId="13772" RevisionGUID="c71bd0a0-6d2a-4bd4-8f46-eed61dc91912" CreationDate="2023-10-22T20:16:10.293" UserId="20730" Text="Given a structure represented by the point cloud, most part of the points in the structure are rigid, and only a few points are flexible. If I have two representations of the point cloud, and I already known the point correspondence, how can I separate the rigid points with flexible points.&#xD;&#xA;&#xD;&#xA;For example, two point clouds represent same slingshot. One of the slingshots has a loose rubber band, and the other one has a tight rubber band. The handle of the slingshot remains rigid. Is there a way to distinguish the deformable part from the rigid part through these two point clouds.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;My intuitive solution is to design an Expectation–maximization algorithm.&lt;br&gt;&#xD;&#xA;Expectation: The whole is rigid and calculate the rotation and translation matrix.&lt;br&gt;&#xD;&#xA;Maximization: calculate the points with larger error(distance&gt;k) and exclude this part. Assume that the remaining parts are rigid.&#xD;&#xA;&#xD;&#xA;Doing this iteratively until all the point error are smaller than m. (m&lt;&lt;k)&#xD;&#xA;&#xD;&#xA;Is this a good idea? Is there any research paper focusing on this question?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42057" PostHistoryTypeId="1" PostId="13772" RevisionGUID="c71bd0a0-6d2a-4bd4-8f46-eed61dc91912" CreationDate="2023-10-22T20:16:10.293" UserId="20730" Text="Is it possible to separate rigid part and flexible part from a structure (point cloud)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42058" PostHistoryTypeId="3" PostId="13772" RevisionGUID="c71bd0a0-6d2a-4bd4-8f46-eed61dc91912" CreationDate="2023-10-22T20:16:10.293" UserId="20730" Text="|point|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42059" PostHistoryTypeId="5" PostId="13760" RevisionGUID="486dc7f3-e5f5-41b0-849a-12a8c8884a6c" CreationDate="2023-10-23T01:08:29.997" UserId="19537" Comment="Additional information (image)" Text="One thing confuses me in your code. Since you say that you are sampling BRDF and light source together, I figured it might be possible that you did change the sampling methods between `uniform` and `cosine-weight` but you forgot to have the corresponding PDF for the MIS weight. Then I found that you aren't using any MIS, and instead, the evaluation for direct and indirect components seem weird:&#xD;&#xA;- Direct illumination estimation:&#xD;&#xA;```c++&#xD;&#xA;sample_color += radiance * throughput / random_direction_pdf;&#xD;&#xA;```&#xD;&#xA;I don't think this is correct. You see, the `radiance` here is the direct component and has nothing to do with ray direction sampling (unless you are using MIS with BRDF PDF evaluation). That means:&#xD;&#xA;```c++&#xD;&#xA;Vector random_dir = cosine_weighted_direction_around_normal(..., random_direction_pdf, ...);&#xD;&#xA;Point new_ray_origin = ...;&#xD;&#xA;&#xD;&#xA;ray = Ray(new_ray_origin, normalize(random_dir));&#xD;&#xA;next_ray_state = ...;&#xD;&#xA;sample_color += radiance * throughput / random_direction_pdf;&#xD;&#xA;/// ======== should actually just be like the following ==========&#xD;&#xA;// accumulate direct illunination&#xD;&#xA;sample_color += radiance * throughput;&#xD;&#xA;// update ray direction to account for indirect subsequent bounces &#xD;&#xA;Vector random_dir = cosine_weighted_direction_around_normal(..., random_direction_pdf, ...);&#xD;&#xA;Point new_ray_origin = ...;&#xD;&#xA;&#xD;&#xA;ray = Ray(new_ray_origin, normalize(random_dir));&#xD;&#xA;next_ray_state = ...;&#xD;&#xA;```&#xD;&#xA;Why? See the following figure:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The red line segment is shadow ray, and the sampling decision is only related to how you: &#xD;&#xA;1. sample an emitter (if there are multiple) &#xD;&#xA;2. sample a point from that emitter. &#xD;&#xA;3. get PDF (area product measure) for sampling the very point on that emitter&#xD;&#xA;4. Transform to solid angle measure (falloff, cosine attenuation, etc. I think you did it right)&#xD;&#xA;&#xD;&#xA;Essentially, after `if (!in_shadow)` branch being finished, the direct illumination already has its unbiased estimation. So you just add it to `radiance` and account for the path throughput from the previous bounces.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;- Throughput update:&#xD;&#xA;```c++&#xD;&#xA;throughput *= mat.diffuse;&#xD;&#xA;```&#xD;&#xA;Note that all the subsequent bounces are **sampled** (ray direction sampling and intersection test to obtain new ray origin and direction), you should account for the sampling event here by:&#xD;&#xA;```c++&#xD;&#xA;throughput *= mat.diffuse * sycl::max(dot(closest_hit_info.normal_at_inter, random_dir), 0.0f) / random_direction_pdf;&#xD;&#xA;```&#xD;&#xA;This should be correct for throughput update, the derivation is simple: the following figure shows how the incident ray gets attenuated by BRDF and cosine term.&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;Since our light incident direction (corresponds to `random_dir`) is sampled, we have the following estimator and we can easily verify its expectation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\hat{I}=L_i(x, w_i)\frac{f\cdot \cos\theta}{\text{PDF}(w_i)}\\&#xD;&#xA;\mathbb{E}(\hat{I}) = \int_{\Omega_{\text{hemisphere}}}\frac{L_i(x, w_i)f\cdot \cos\theta}{\text{PDF}(w_i)}\text{PDF}(w_i) dw_i = \int_{\Omega_{\text{hemisphere}}}L_i(x, w_i)f\cdot \cos\theta dw_i&#xD;&#xA;$$&#xD;&#xA;and obviously the expectation is what we are looking for: to integrate the incident radiance from all directions on the hemisphere and apply surface interaction terms.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So, in all, I think you should solve the following problems first before you can dive deeper into what the rendering results should actually be:&#xD;&#xA;- Direct illumination: use `sample_color += radiance * throughput;` instead.&#xD;&#xA;- Path through update: use `throughput *= mat.diffuse * sycl::max(dot(closest_hit_info.normal_at_inter, random_dir), 0.0f) / random_direction_pdf;` instead.&#xD;&#xA;&#xD;&#xA;and since you are using BRDF sampling and emitter sampling at the same time, you can try to use MIS to combine both sampling methods to converge even faster. For more information on the logic for simple path tracer, refer to [pbrt-v3: src/integrators/path.cpp:Li()](https://github.com/mmp/pbrt-v3/blob/master/src/integrators/path.cpp). If you find anything wrong or difficult to understand in this answer, comment to let me know.&#xD;&#xA;&#xD;&#xA;By the way, can you point me to the repo for your code? I'd like to try this when I 'm available.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The output of my renderer (surface material setting might be different, they are all Lambertian though), which matches with pbrt-v3 and mitsuba0.6:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/6tHKs.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/JXo9R.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/swMGs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42060" PostHistoryTypeId="50" PostId="13002" RevisionGUID="c0ebbfc4-f1da-4e2c-bd14-b2070c278164" CreationDate="2023-10-23T02:03:00.323" UserId="-1" />
  <row Id="42062" PostHistoryTypeId="50" PostId="13721" RevisionGUID="9cd44f07-a111-4721-8c67-62c8c2ef15d1" CreationDate="2023-10-23T11:06:45.820" UserId="-1" />
  <row Id="42063" PostHistoryTypeId="50" PostId="9116" RevisionGUID="0c741377-4282-4eeb-9f71-e3e3a4f78d81" CreationDate="2023-10-23T15:07:15.840" UserId="-1" />
  <row Id="42064" PostHistoryTypeId="2" PostId="13773" RevisionGUID="1ee5f428-c713-49b5-bc63-3dbe186f8723" CreationDate="2023-10-23T19:58:28.233" UserId="20739" Text="## When converting from sRGB to CIEXYZ I seem to be off by a factor of 100&#xD;&#xA;I'm trying to convert from sRGB to CIELAB.&#xD;&#xA;&#xD;&#xA;### Calculation&#xD;&#xA; - First I need to go from sRGB to CIEXYZ. Using [this formula](https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ) I get i.e. for `sRGB(197, 199, 196) -&gt; &quot;linear&quot;RGB(0.558, 0.571, 0.552) -&gt; XYZ(0.534, 0.567, 0.604)`.&#xD;&#xA;&#xD;&#xA;   When comparing this some [online converter](https://colormine.org/convert/rgb-to-xyz) the values seem to be off by a factor of 100.&#xD;&#xA;&#xD;&#xA; - Next I use [this formula](https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB) to go to CIELAB (with the D65 illuminant (`Xn: 95.0489, Yn: 100, Zn: 108.884`)). With the example above I get `L*ab(5.122, -0.197, 0.198)` which to me seems completly off. &#xD;&#xA;   &#xD;&#xA;   Comparing to an [online converter](https://colormine.org/convert/rgb-to-lab) seems to further confirm my suspicion, since the difference in values it gives me can not be attributed to rounding errors or the use of slightly different constants.&#xD;&#xA;&#xD;&#xA;### Question:&#xD;&#xA; - Did I do something wrong in my calculations?&#xD;&#xA; - Is the CIEXYZ space supposed to go from 0 to 1 or from 0 to 100?&#xD;&#xA; - Am I misreading something in the Wikipedia articles or is [the first one](https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ) using 0 to 1 and [the second one](https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB) 0 to 100? If yes, why?&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42066" PostHistoryTypeId="1" PostId="13773" RevisionGUID="1ee5f428-c713-49b5-bc63-3dbe186f8723" CreationDate="2023-10-23T19:58:28.233" UserId="20739" Text="value range in CIEXYZ space" ContentLicense="CC BY-SA 4.0" />
  <row Id="42067" PostHistoryTypeId="3" PostId="13773" RevisionGUID="1ee5f428-c713-49b5-bc63-3dbe186f8723" CreationDate="2023-10-23T19:58:28.233" UserId="20739" Text="|mathematics|color|colorspace|conversion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42068" PostHistoryTypeId="2" PostId="13774" RevisionGUID="e50706e4-be2c-4449-aca6-a7dc0fd97a3e" CreationDate="2023-10-24T19:43:03.343" UserId="20742" Text="[![enter image description here][1]][1]how can I estimate the depth of an object with a bound box from just a few images where i moved it?(knowing how much i moved)&#xD;&#xA;&#xD;&#xA;For testing purposes I have a cube and a camera perpendicular to it and I need to estimate its z-axis and I only have a few images of it moving backwards or forwards.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/BfSOl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42070" PostHistoryTypeId="1" PostId="13774" RevisionGUID="e50706e4-be2c-4449-aca6-a7dc0fd97a3e" CreationDate="2023-10-24T19:43:03.343" UserId="20742" Text="how can I estimate the depth of an object with a bound box from just a few images where i moved it?(knowing how much i moved)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42071" PostHistoryTypeId="3" PostId="13774" RevisionGUID="e50706e4-be2c-4449-aca6-a7dc0fd97a3e" CreationDate="2023-10-24T19:43:03.343" UserId="20742" Text="|3d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42072" PostHistoryTypeId="2" PostId="13775" RevisionGUID="c257d8c7-f5ae-43c3-b5f0-6bb8ed2f00f8" CreationDate="2023-10-25T04:17:02.743" UserId="19537" Text="For your question: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;If the camera model and the scene settings are as simple as what you've stated in the post, I think simple geometry will do. Note that $f$ is the focal length and $p_i$ is the projected pixel length for one of the edges of the bounding box. $x$ is the unknown 3D length of the bounding box, $t$ is the distance you moved (known) and $d$ or $d-t$ is the depth you want.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;For more generally-purposed depth estimation, I think these are some methods you can try. Since it is easy for you to get the correspondences between images (especially when you have bounding boxes), you can use:&#xD;&#xA;- **Triangulation**: two known scene view points (two images) and the pixel coordinates projected by that 3D point. In an ideal situation, two rays from the pixels should intersect on that very 3D point of which the depth you want, but due to noise and discrete quantization (2D images), these two rays won't intersect. Therefore the depth is usually recovered from least-square methods.&#xD;&#xA;&#xD;&#xA;- **PnP** algorithms. You have at least four pairs of points (your bounding box). Using PnP algorithms, you can even recover the 3D position of each points in the camera coordinate frame, so depth won't be a problem. &#xD;&#xA;&#xD;&#xA;Even if you don't have bounding boxes, using feature point based pixel correspondence search should get you point pairs you need. For the methods above, you will need:&#xD;&#xA;- Camera intrinsic matrix (if it is CG generated, this is usually simple and only related to camera focal length).&#xD;&#xA;- Viewpoint transforms. As you've said, you know the transforms between different cameras, so this won't be a problem.&#xD;&#xA;- Pixel correspondences. For points of which depth is to be calculated, you should know the pixel coordinates for those points in at least two images. This won't be a problem for you.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/9mFDR.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42074" PostHistoryTypeId="50" PostId="9926" RevisionGUID="d5135576-6188-429d-9660-a5b7ee5788f2" CreationDate="2023-10-25T08:06:50.773" UserId="-1" />
  <row Id="42075" PostHistoryTypeId="2" PostId="13776" RevisionGUID="50d29b72-b7bc-455f-8851-2bec0b831c27" CreationDate="2023-10-25T10:33:21.497" UserId="7008" Text="I have a vulkan ray tracer in which I uploaded my vertices as a single buffer (for all meshes in the scene) as a storage buffer. I have one closest hit shader per way-of-calculating-lighting (e.g. one for a blinn phong lighting calculation for opaque objects, one for blinn phong with refractive properties, one for the disney BRDF). I have one hitgroup record per closest hit shader. I map every closest hit shader to an index, and then in the shader binding table I insert the hit groups according to that map. I set a custom instance index in the TLAS instances and the SBT offset is also used according to my map.&#xD;&#xA;&#xD;&#xA;In the shader, I read out the storage buffer to get to the vertex data (for this I jump through hoops - I have an extra buffer that stores offsets into my vertex buffer and all other buffers I have) and it works fine.&#xD;&#xA;&#xD;&#xA;Now I was trying to port my ray tracer to OptiX which essentially should work with the same set up, but I came across actually putting data, such as Vertex Buffers, into Hit Group records. &#xD;&#xA;&#xD;&#xA;Now my question is, should I change to a Hit Group record setup that utilizes these buffers meant for it (independent of OptiX or Vulkan, as both support this but I didn't know it before)? Are there any performance or other reasons to choose on over the other? As far as I can see, I'd need either a Hitgroup Record per shader - geometry combination such that I can read out the vertex buffer without calculating indices before hand and thus blow up my SBT, or I use the same idea of one giant vertex buffer and have to jump through the same hoops to get to my buffer indices.&#xD;&#xA;&#xD;&#xA;So far as I can see in samples, the vulkan folks use storage buffers as I did (I think that's why I went that route to start with) and the OptiX people tend to write Vertex data into the Hit Group records (Nvidia themselves [use][1] [storage buffers][2] in their vulkan samples and [record][3] [data][4] in their OptiX samples).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/nvpro-samples/vk_mini_samples/blob/main/samples/ray_trace/src/ray_trace.cpp&#xD;&#xA;  [2]: https://github.com/nvpro-samples/vk_raytracing_tutorial_KHR/blob/master/ray_tracing__advance/hello_vulkan.cpp&#xD;&#xA;  [3]: https://github.com/ingowald/optix7course/blob/master/example07_firstRealModel/SampleRenderer.cpp&#xD;&#xA;  [4]: https://raytracing-docs.nvidia.com/optix8/guide/index.html#shader_binding_table#records" ContentLicense="CC BY-SA 4.0" />
  <row Id="42077" PostHistoryTypeId="1" PostId="13776" RevisionGUID="50d29b72-b7bc-455f-8851-2bec0b831c27" CreationDate="2023-10-25T10:33:21.497" UserId="7008" Text="What is the difference between Uniform/Storage Buffer and Hitgroup Record data buffer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42078" PostHistoryTypeId="3" PostId="13776" RevisionGUID="50d29b72-b7bc-455f-8851-2bec0b831c27" CreationDate="2023-10-25T10:33:21.497" UserId="7008" Text="|raytracing|vulkan|optix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42079" PostHistoryTypeId="2" PostId="13777" RevisionGUID="d2a52ffa-5e32-4014-ba55-949babe50763" CreationDate="2023-10-25T15:42:06.083" UserId="18529" Text="I need to solve the following problem: do some **anti-aliasing onto an image that contains rasterized &quot;lines&quot;**. &#xD;&#xA;&#xD;&#xA;I have some post-processing effects that output super-thin (~1px) features such as silhouette-edges and outlines as shown here:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I tried with an FXAA shader I found online, which works fine if the line is at least 2px wide, doesn't work with 1px lines. I guess the edge detection method completely breaks with such thin features (also the common optimization to sample at the boundary of the edge won't work with lines).&#xD;&#xA;&#xD;&#xA;How should I address this issue? &#xD;&#xA;&#xD;&#xA;Is there a technique out there specifically designed to solve this problem?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/WYymi.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42081" PostHistoryTypeId="1" PostId="13777" RevisionGUID="d2a52ffa-5e32-4014-ba55-949babe50763" CreationDate="2023-10-25T15:42:06.083" UserId="18529" Text="Screen space line anti aliasing" ContentLicense="CC BY-SA 4.0" />
  <row Id="42082" PostHistoryTypeId="3" PostId="13777" RevisionGUID="d2a52ffa-5e32-4014-ba55-949babe50763" CreationDate="2023-10-25T15:42:06.083" UserId="18529" Text="|image-processing|antialiasing|post-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42091" PostHistoryTypeId="2" PostId="13779" RevisionGUID="759b16ad-c9f3-4c4e-b8e8-4acf7cd4e556" CreationDate="2023-10-26T16:04:41.993" UserId="20753" Text="I have one question.&#xD;&#xA;How to calculate source color after blending operation. &#xD;&#xA;For example. I have &#xD;&#xA;&#xD;&#xA;1 - Background color (r-115, g-94, b-67, a-1)&#xD;&#xA;&#xD;&#xA;2 - Foreground color above background color, which blended with normal blend mode (r-255, g-255, b-255, a-0.2)&#xD;&#xA;&#xD;&#xA;3 - Result color - with this operation will be (r-143, g-126, b-105, a-1)&#xD;&#xA;&#xD;&#xA;Question - How to calculate Background color with given Foreground color and Result color?&#xD;&#xA;&#xD;&#xA;Images below &#xD;&#xA;&#xD;&#xA;1 - Background color &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;2 - Foreground color. White with alpha 0.2. Can't see clearly, because this color have alpha 0.2&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;3 - Result color.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;All this operation made in Photoshop &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/FQfpc.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/i0NwW.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/Gr8Dd.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42093" PostHistoryTypeId="1" PostId="13779" RevisionGUID="759b16ad-c9f3-4c4e-b8e8-4acf7cd4e556" CreationDate="2023-10-26T16:04:41.993" UserId="20753" Text="Normal blend mode math" ContentLicense="CC BY-SA 4.0" />
  <row Id="42094" PostHistoryTypeId="3" PostId="13779" RevisionGUID="759b16ad-c9f3-4c4e-b8e8-4acf7cd4e556" CreationDate="2023-10-26T16:04:41.993" UserId="20753" Text="|algorithm|color|color-science|blending|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42095" PostHistoryTypeId="2" PostId="13780" RevisionGUID="201289e4-3c50-46cb-92e1-6868dff80701" CreationDate="2023-10-27T00:50:17.583" UserId="20758" Text="How do I tell what kind of shader this is: https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianSplatting.hlsl&#xD;&#xA;Among these options:&#xD;&#xA;vs – vertex shader&#xD;&#xA;&#xD;&#xA;ps – pixel shader&#xD;&#xA;&#xD;&#xA;gs – geometry shader&#xD;&#xA;&#xD;&#xA;ds – domain shader&#xD;&#xA;&#xD;&#xA;hs – hull shader&#xD;&#xA;&#xD;&#xA;cs – compute shader&#xD;&#xA;&#xD;&#xA;By looking at the code?&#xD;&#xA;I need to know in order to convert it to a glsl shader. Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="42097" PostHistoryTypeId="1" PostId="13780" RevisionGUID="201289e4-3c50-46cb-92e1-6868dff80701" CreationDate="2023-10-27T00:50:17.583" UserId="20758" Text="How do I tell what kind of shader an hlsl shader is by looking at the code?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42098" PostHistoryTypeId="3" PostId="13780" RevisionGUID="201289e4-3c50-46cb-92e1-6868dff80701" CreationDate="2023-10-27T00:50:17.583" UserId="20758" Text="|shader|glsl|compute-shader|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42100" PostHistoryTypeId="2" PostId="13781" RevisionGUID="5412d44f-b4ce-45e7-9f74-3a4cd66a13d4" CreationDate="2023-10-27T03:12:17.017" UserId="20758" Text="I'm trying to create the simplest possible implementation of the gaussian visualization code from this paper in Godot, https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/ but I just don't even know where to start, if I knew how to visualize even just one 3D gaussian using C# mono code or GDScript code or Godot Shader code or GLSL code then I feel like I'd have a leg on implementing something for my classes, but I read the code in the github: https://github.com/graphdeco-inria/gaussian-splatting/tree/main and it's like 1000s of lines across 50 files all intermingled to do what it's doing. There's no getting started tutorial to implementing this code, so that's what I'm asking for, how do I draw a 3D gaussian with alpha?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42102" PostHistoryTypeId="1" PostId="13781" RevisionGUID="5412d44f-b4ce-45e7-9f74-3a4cd66a13d4" CreationDate="2023-10-27T03:12:17.017" UserId="20758" Text="What kind of code would it take to visualize just 1 3d gaussian in Godot?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42103" PostHistoryTypeId="3" PostId="13781" RevisionGUID="5412d44f-b4ce-45e7-9f74-3a4cd66a13d4" CreationDate="2023-10-27T03:12:17.017" UserId="20758" Text="|rendering|shader|glsl|c#|godot|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42104" PostHistoryTypeId="6" PostId="13780" RevisionGUID="fb968e0a-2faa-49c7-804b-63e29d9305d8" CreationDate="2023-10-27T23:00:51.943" UserId="2654" Comment="edited tags" Text="|shader|compute-shader|hlsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42107" PostHistoryTypeId="2" PostId="13782" RevisionGUID="0882a012-4de3-49ea-acb7-70c02334826b" CreationDate="2023-10-28T09:03:57.813" UserId="7952" Text="To help get you going I looked up a shader which has the fragment and vertex code in it. It is in this [file][1].&#xD;&#xA;&#xD;&#xA;One of the first things it does at line 19 is:&#xD;&#xA;&#xD;&#xA;    #include &quot;GaussianSplatting.hlsl&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Which is a reference to the file in the question.&#xD;&#xA;&#xD;&#xA;At line 32 it has:&#xD;&#xA;&#xD;&#xA;    v2f vert (uint vtxID : SV_VertexID, uint instID : SV_InstanceID)&#xD;&#xA;&#xD;&#xA;and then at line 58&#xD;&#xA;&#xD;&#xA;    half4 frag (v2f i) : SV_Target&#xD;&#xA;&#xD;&#xA;The file: https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianDebugRenderBoxes.shader and https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianComposite.shader&#xD;&#xA;&#xD;&#xA;have similar lines.&#xD;&#xA;&#xD;&#xA;These are the actual shader entry points and they include gaussian splatting to get functionality it provides.&#xD;&#xA;&#xD;&#xA;Hope this helps.&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianDebugRenderPoints.shader" ContentLicense="CC BY-SA 4.0" />
  <row Id="42109" PostHistoryTypeId="5" PostId="13782" RevisionGUID="45eacde4-75ea-48e9-ab34-a4bc4083d03e" CreationDate="2023-10-28T09:16:34.660" UserId="7952" Comment="Add more detail" Text="&#xD;&#xA;The real work horse shader looks to be the compute shader near the bottom of the list in [this file][2].&#xD;&#xA;&#xD;&#xA;The other shaders which has fragment and vertex code in it is in this [file][1].&#xD;&#xA;&#xD;&#xA;One of the first things it does at line 19 is:&#xD;&#xA;&#xD;&#xA;    #include &quot;GaussianSplatting.hlsl&quot;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Which is a reference to the file in the question.&#xD;&#xA;&#xD;&#xA;At line 32 it has:&#xD;&#xA;&#xD;&#xA;    v2f vert (uint vtxID : SV_VertexID, uint instID : SV_InstanceID)&#xD;&#xA;&#xD;&#xA;and then at line 58&#xD;&#xA;&#xD;&#xA;    half4 frag (v2f i) : SV_Target&#xD;&#xA;&#xD;&#xA;The file: https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianDebugRenderBoxes.shader and https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianComposite.shader&#xD;&#xA;&#xD;&#xA;have similar lines.&#xD;&#xA;&#xD;&#xA;It looks like the compute shader is implementing the algorithm and the other shaders are there largely, for showing the results.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Hope this helps.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/GaussianDebugRenderPoints.shader&#xD;&#xA;  [2]: https://github.com/aras-p/UnityGaussianSplatting/blob/main/package/Shaders/SplatUtilities.compute" ContentLicense="CC BY-SA 4.0" />
  <row Id="42111" PostHistoryTypeId="2" PostId="13783" RevisionGUID="7a5f4405-07c4-409c-a038-909cd0bd7d77" CreationDate="2023-10-28T23:57:11.830" UserId="10096" Text="**Motivation**&#xD;&#xA;&#xD;&#xA;I am trying to refine a mesh such that each triangle gets subdivided into 4 triangles, but I want the vertices to be shared. For that purpose I need a half-edge data structure so I can count and address the vertices on the edges properly. The problem below is formulated a bit more generally - it just assumes a given index list, and doesn't even provide the vertices coordinates. The problem is in 3D, so sorting based on angles for DCEL construction will not work.&#xD;&#xA;&#xD;&#xA;**Problem Statement**&#xD;&#xA;&#xD;&#xA;I am given an index list $T = [i_{0}, i_{1}, i_{2}, \ldots, i_{3(n-1)}, t_{3(n-1)+1}, t_{3(n-1)+2}]$ of triplets of vertex indices corresponding to a specific triangle. Here $i_{3k+j}$ is the index of the $j$-th vertex in the $k$-th triangle (I have $n$ triangles in the above). I define $n(j) = 3\cdot\lfloor j/3\rfloor + \bigl(((j \text{ mod } 3)+1)\text{ mod }3\bigr)$. This cyclically gives me the next index belonging to the same triangle. For example:&#xD;&#xA;&#xD;&#xA;$$n(0) = 1, \,n(1) = 2,\, n(2) = 0,\, n(3) = 4, \, n(4) = 5,\, n(5) = 3, \ldots$$  &#xD;&#xA;I want to build a half-edge table: a table such that $(h(j) = k)\land (h(k) = j) \iff (i_j = i_{n(k)})\land (i_{n(j)}=i_k)$. Given a half-edge index $j$ it returns the index corresponding to the half-edge in the opposite triangle. I am trying to avoid using a hash table since I don't have a nice implementation in C and I don't plan to implement my own (though if you have any good suggestions for hash table code I'll gladly have a look, but that's outside the scope of the question really - I will still be curious about suggestions not using a hash table even if I have one). &#xD;&#xA;&#xD;&#xA;**My Algorithm**&#xD;&#xA;&#xD;&#xA;What I came up with is to iterate over all triangles and count the number of triangles per vertex (meaning I have an array $nt(i) = \text{# adjacent triangles to vertex $i$}$, for $0\leq i \leq m-1$, where $m$ is the number of vertices). Once I have the count I can allocate a compressed row storage matrix with $nt(i)$ elements per vertex ($row(i) = nt(i-1) + row(i-1)$), and fill a triangle adjacency matrix $A$ with the indices of the adjacent triangles. Then for each vertex in the matrix I can go over pairs of its triangles ($C^{nt(i)}_{2}$ such pairs) and link those that share an edge (in a closed mesh I can even sort them). As long as $n(i)$ is not too large this is not very problematic. For simplicity one may assume that the mesh is manifold (an edge has no more than two adjacent faces) and that it is orientable (no funny Mobius strip stories), although I think the latter is not as important as I don't care about the orientation of the halfedges, I just need face adjacency.&#xD;&#xA;&#xD;&#xA;**Question**&#xD;&#xA;&#xD;&#xA;My question is whether someone has any better ideas for an algorithm, or suggestions for improvements of the above (or pointing out a mistake)?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42113" PostHistoryTypeId="1" PostId="13783" RevisionGUID="7a5f4405-07c4-409c-a038-909cd0bd7d77" CreationDate="2023-10-28T23:57:11.830" UserId="10096" Text="Constructing half-edges table from triangle list without hash" ContentLicense="CC BY-SA 4.0" />
  <row Id="42114" PostHistoryTypeId="3" PostId="13783" RevisionGUID="7a5f4405-07c4-409c-a038-909cd0bd7d77" CreationDate="2023-10-28T23:57:11.830" UserId="10096" Text="|computational-geometry|algorithm|mesh|triangulation|half-edge|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42115" PostHistoryTypeId="50" PostId="12498" RevisionGUID="212dcbc8-2f95-4906-b0e2-eefe00522b2b" CreationDate="2023-10-29T03:09:16.070" UserId="-1" />
  <row Id="42117" PostHistoryTypeId="2" PostId="13784" RevisionGUID="568c40d2-743e-4ad4-82e1-9d80edcb5eeb" CreationDate="2023-10-29T13:11:09.267" UserId="20769" Text="I'd say it's InterpolationMode.NearestNeighbor plus a minimum width/height threshold below you cannot scale down." ContentLicense="CC BY-SA 4.0" />
  <row Id="42119" PostHistoryTypeId="2" PostId="13785" RevisionGUID="6c32c343-11cf-448c-be4c-9a0f9663a38e" CreationDate="2023-10-29T17:17:03.727" UserId="20770" Text="On some architectures at least, uniform/constant buffer loads will serialize if threads in a warp fetch from different addresses. Worst case, the load might be 32 or 64 times slower.&#xD;&#xA;&#xD;&#xA;This can be a problem if, for example, you're indexing matrices for skinning which are stored in a uniform buffer, from a vertex shader. It's likely that threads/vertices will have a lot of disagreement about which matrices to load, and these loads will serialize.&#xD;&#xA;&#xD;&#xA;I'm not sure about the state of things across vendors in 2023, though.&#xD;&#xA;&#xD;&#xA;If your access pattern is such that different threads might try to load from different addresses at the same time, I recommend using a regular buffer to be on the safe side.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42121" PostHistoryTypeId="2" PostId="13786" RevisionGUID="10d11cb3-6df6-45ec-85e7-fa54db7d75fc" CreationDate="2023-10-29T19:41:10.963" UserId="10096" Text="I worked some more on this, and the comparisons complexity can be reduced at the expense of memory. To make this work I made arrays of the indices of the outgoing and incident half-edges for each vertex. Then the array with outgoing half-edges can be sorted according to the indices of the vertices at situated at the heads of the outgoing half-edges, and the array with the incident half-edges can be sorted according to the indices of the vertices at the tails of the incident half-edges. Then for an oriented closed manifold triangulation, the elements with the same index in the two sorted arrays will be twin half-edges. For a non-closed manifold the comparison can be done in linear time.&#xD;&#xA;&#xD;&#xA;It seems like a hash is entirely unnecessary." ContentLicense="CC BY-SA 4.0" />
  <row Id="42124" PostHistoryTypeId="2" PostId="13787" RevisionGUID="f8a84ff1-540f-4c2e-b9c3-a9e2d8e7ef14" CreationDate="2023-10-30T08:03:59.733" UserId="20776" Text="According to [learnopengl.com][1], the term $G(l, v, n)$ in the Cook-Torrance Specular BRDF can be written as&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;G=\frac{n \cdot v}{(n \cdot v)(1-k)+k} \cdot \frac{n \cdot l}{(n \cdot l)(1-k)+k}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;and this is the specular term of the Cook-Torrance BRDF&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f=\frac{FGD}{4(n \cdot l)(n \cdot v)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;we can see that both $f$ and $G$ have $n \cdot v$ and $n \cdot l$ terms that cancel each other out. When $n \cdot v$ becomes really small and approaches 0 we get a $0/0$ situation which is what causes artifacts at grazing angles due to floating point precision errors near 0.&#xD;&#xA;&#xD;&#xA;Solution&#xD;&#xA;-&#xD;&#xA;The problem can be solved by canceling the terms $n \cdot v$ and $n \cdot l$ in $f$ and $G$. The new specular Cook-Torrance BRDF becomes&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f=\frac{FGD}{4}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;G=\frac{1}{(n \cdot v)(1-k)+k} \cdot \frac{1}{(n \cdot l)(1-k)+k}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://learnopengl.com/PBR/Theory" ContentLicense="CC BY-SA 4.0" />
  <row Id="42126" PostHistoryTypeId="2" PostId="13788" RevisionGUID="5bf67ad1-ae49-47e0-8313-05258ce21d36" CreationDate="2023-10-30T23:47:05.380" UserId="7952" Text="A gaussian blur with a small kernel size, like 3, would blur the line into adjacent pixels and may be all that is needed.&#xD;&#xA;&#xD;&#xA;There is a technique called jump flooding that will turn an image like this, even with very thin lines into a signed distance field. The signed distance field can then be used to recreate the lines at any thickness, with anti-aliasing. There was a paper written &quot;Jump Flooding in GPU with Applications to Voronoi Diagram and Distance Transform&quot; and there is an interesting blog post at https://bgolus.medium.com/the-quest-for-very-wide-outlines-ba82ed442cd9. The blog post is about generating wide outlines but it applies to thin lines and anti-aliasing lines as well. &#xD;&#xA;&#xD;&#xA;One interesting thing about jump flooding is it allows for fractional pixel widths like 1.5px wide lines." ContentLicense="CC BY-SA 4.0" />
  <row Id="42128" PostHistoryTypeId="2" PostId="13789" RevisionGUID="81c1c22e-6ead-4ca8-b434-31c44a26618e" CreationDate="2023-11-01T11:17:03.317" UserId="20789" Text="***Originally asked in Graphic Design site [here][1]*** *(but I don't know how to 'move' a question to another site)*&#xD;&#xA;&#xD;&#xA;I have a bunch of scanned document images and in each image there is a variance in background colour (sometimes a wide variance).&#xD;&#xA;&#xD;&#xA;I want to adjust all image pixels such that they are 'normalized' towards the pixel colour mean. To put it another way, I want to adjust all pixel colour values (or grayscale) so that the background colour (e.g. the 'white page') loses the colour gradients and variation and instead becomes as close as possible to white (or white).&#xD;&#xA;&#xD;&#xA;I have been looking into colour gradients, vectorization and various filters, thresh-holding and blurring techniques, but I can't quite work out how to do what I see in my head.&#xD;&#xA;&#xD;&#xA;**Take the following example image:** *(ignore my red annotation)*&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I want to find out what the overall mean colour is for all pixels, then for each pixel reduce or increase it towards the mean value to create a more 'flat' image. The reason I want to do that is because I believe it will improve the next step, which is to detect contours and edges for the purpose of text detection (and ultimately better OCR results).&#xD;&#xA;&#xD;&#xA;So in the above example, the goal is to effectively remove the gray diagonal lines, but leave the text. I think there might be a way to automatically determine a threshold value (or have a dynamic threshold) but I am not sure exactly how to do that.&#xD;&#xA;&#xD;&#xA;**Here is another example image:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;The goal for this second image would be to effectively remove the target logo and most of the other background 'document colour mess' picked up by the scanner, as per the annotation.&#xD;&#xA;&#xD;&#xA;The overall objective is to improve text block detection to then improve OCR accuracy.&#xD;&#xA;&#xD;&#xA;I know I can play around with filters and image enhancements using slides in GIMP or some other graphics GUI, but one of the key points is that ***this process has to be automated*** because doing it manually would essentially defeat the purpose and I may as well go back to manual data entry by eyeballing every document (ugh!).&#xD;&#xA;&#xD;&#xA;This is why I have been trying to use OpenCV in Python.&#xD;&#xA;&#xD;&#xA;The second point is that since every image is different I need to be able to determine the threshold (for final binarization prior to OCR) automatically, which is kind of what I mean by 'normalization' above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphicdesign.stackexchange.com/questions/162596/how-do-i-normalize-all-pixel-values-such-that-all-pixel-values-are-pulled-towar&#xD;&#xA;  [2]: https://i.stack.imgur.com/JOPkG.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/DGQKM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42130" PostHistoryTypeId="1" PostId="13789" RevisionGUID="81c1c22e-6ead-4ca8-b434-31c44a26618e" CreationDate="2023-11-01T11:17:03.317" UserId="20789" Text="How do I normalize all pixel values such that all pixel values are 'pulled towards' the mean?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42131" PostHistoryTypeId="3" PostId="13789" RevisionGUID="81c1c22e-6ead-4ca8-b434-31c44a26618e" CreationDate="2023-11-01T11:17:03.317" UserId="20789" Text="|image-processing|vector-graphics|pixel-graphics|filtering|opencv|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42132" PostHistoryTypeId="5" PostId="13789" RevisionGUID="718bf908-b4db-44ad-90cb-5ea9ba5dd225" CreationDate="2023-11-01T11:42:20.777" UserId="20789" Comment="Added link to YouTube video (channel) to give credit." Text="***Originally asked in Graphic Design site [here][1]*** *(but I don't know how to 'move' a question to another site)*&#xD;&#xA;&#xD;&#xA;* *Credit to this guy: [Python Tutorials for Digital Humanities][2] - I followed a lot of his ideas, but I haven't got it down yet*&#xD;&#xA;&#xD;&#xA;**I have a bunch of scanned document images** and in each image there is a variance in background colour (sometimes a wide variance).&#xD;&#xA;&#xD;&#xA;I want to adjust all image pixels such that they are 'normalized' towards the pixel colour mean. To put it another way, I want to adjust all pixel colour values (or grayscale) so that the background colour (e.g. the 'white page') loses the colour gradients and variation and instead becomes as close as possible to white (or white).&#xD;&#xA;&#xD;&#xA;I have been looking into colour gradients, vectorization and various filters, thresh-holding and blurring techniques, but I can't quite work out how to do what I see in my head.&#xD;&#xA;&#xD;&#xA;**Take the following example image:** *(ignore my red annotation)*&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I want to find out what the overall mean colour is for all pixels, then for each pixel reduce or increase it towards the mean value to create a more 'flat' image. The reason I want to do that is because I believe it will improve the next step, which is to detect contours and edges for the purpose of text detection (and ultimately better OCR results).&#xD;&#xA;&#xD;&#xA;So in the above example, the goal is to effectively remove the gray diagonal lines, but leave the text. I think there might be a way to automatically determine a threshold value (or have a dynamic threshold) but I am not sure exactly how to do that.&#xD;&#xA;&#xD;&#xA;**Here is another example image:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;The goal for this second image would be to effectively remove the target logo and most of the other background 'document colour mess' picked up by the scanner, as per the annotation.&#xD;&#xA;&#xD;&#xA;The overall objective is to improve text block detection to then improve OCR accuracy.&#xD;&#xA;&#xD;&#xA;I know I can play around with filters and image enhancements using slides in GIMP or some other graphics GUI, but one of the key points is that ***this process has to be automated*** because doing it manually would essentially defeat the purpose and I may as well go back to manual data entry by eyeballing every document (ugh!).&#xD;&#xA;&#xD;&#xA;This is why I have been trying to use OpenCV in Python.&#xD;&#xA;&#xD;&#xA;The second point is that since every image is different I need to be able to determine the threshold (for final binarization prior to OCR) automatically, which is kind of what I mean by 'normalization' above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://graphicdesign.stackexchange.com/questions/162596/how-do-i-normalize-all-pixel-values-such-that-all-pixel-values-are-pulled-towar&#xD;&#xA;  [2]: https://www.youtube.com/watch?v=ADV-AjAXHdc&amp;list=PL2VXyKi-KpYuTAZz__9KVl1jQz74bDG7i&amp;index=6&amp;ab_channel=PythonTutorialsforDigitalHumanities&#xD;&#xA;  [3]: https://i.stack.imgur.com/JOPkG.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/DGQKM.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42133" PostHistoryTypeId="50" PostId="13258" RevisionGUID="82b9607b-26fc-485b-b890-46329dc77b28" CreationDate="2023-11-01T19:08:41.023" UserId="-1" />
  <row Id="42134" PostHistoryTypeId="2" PostId="13790" RevisionGUID="550f1264-36b3-46ff-9245-b0c82d3d7f2e" CreationDate="2023-11-01T19:32:56.060" UserId="20793" Text="In research on making the rendering of learned radiance fields (e.g., neural radiance fields) faster, many approaches use Spherical Harmonics (SH) to approximate view-dependent color (e.g. baking SH into classical 3D structures such as meshes with textures, or point clouds).&#xD;&#xA;&#xD;&#xA;Historically, it seems that SH have predominantly been used to represent diffuse lighting. Why are they now also employed for view-dependent color?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42136" PostHistoryTypeId="1" PostId="13790" RevisionGUID="550f1264-36b3-46ff-9245-b0c82d3d7f2e" CreationDate="2023-11-01T19:32:56.060" UserId="20793" Text="Spherical Harmonics for view-dependent effects in research of learned radiance fields (NeRF)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42137" PostHistoryTypeId="3" PostId="13790" RevisionGUID="550f1264-36b3-46ff-9245-b0c82d3d7f2e" CreationDate="2023-11-01T19:32:56.060" UserId="20793" Text="|rendering|lighting|volume-rendering|spherical-harmonics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42138" PostHistoryTypeId="4" PostId="13790" RevisionGUID="3c23232f-1feb-4af8-9cad-510b5b76b33c" CreationDate="2023-11-01T19:33:25.040" UserId="20793" Comment="edited title" Text="Spherical Harmonics for view-dependent effects in research of learned radiance fields (NeRF, 3D Gaussian Splatting)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42140" PostHistoryTypeId="2" PostId="13791" RevisionGUID="67880c38-454e-4e46-9021-9ac65687faae" CreationDate="2023-11-02T10:35:58.983" UserId="7952" Text="Here are both images &quot;cleaned&quot; using simple luminance thresholding like I suggested in the comments. There was nothing special done to these images, a simple &quot;is the luminance below threshold for this texel&quot; is all that was done. The image was first converted to gray scale.&#xD;&#xA;&#xD;&#xA;If the scan was better quality with a higher resolution the results would better.&#xD;&#xA;&#xD;&#xA;The real challenge with this technique is finding the threshold, again a scan with higher resolution would help. But one of the images looked best at a cutoff of 0.55 and the other at 0.68. &#xD;&#xA;&#xD;&#xA;I did this in a small program that I threw together, but there must be an image tool that can do this easily. (I am no expert at tools that would be a question for the photoshop/gimp forums)&#xD;&#xA;&#xD;&#xA;The program was just the stbi image header (a c++ header file that can load and save various image types like jpg and png) and a loop that spun over the values computed the gray scale, tested the threshold, and output the result.&#xD;&#xA;&#xD;&#xA;Here are the results:&#xD;&#xA;&#xD;&#xA; - https://i.stack.imgur.com/VJkXk.jpg   &#xD;&#xA;   https://i.stack.imgur.com/lcOEh.jpg&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VJkXk.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/lcOEh.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42142" PostHistoryTypeId="2" PostId="13792" RevisionGUID="22c4ab17-604d-4a22-af5b-ce4133ff3265" CreationDate="2023-11-03T11:38:37.493" UserId="20658" Text="I'm really sure that this question was asked before, and I found some code snippets by searching this via google. Unfortunately these snippets are in openGL or some other high level computer graphics language. I have an input light vector I(phi,theta). I can calculate the reflected vector quite easily. The Phong BRDF assumes that this vector is the z-axis and one can generate a random direction to this R-vector. I want to know, how I can add this vector to R(phi,theta) to generate a random view direction out of the input direction I(phi,theta), say V(phi,theta). I know this can be done by rotation matrices and their transposed ones, but I'm stuck. Can you please give some algebraic formulas for this problem?&#xD;&#xA;&#xD;&#xA;Physics behind this problem: I have a cylinder which points to the sun. This cylinder is&#xD;&#xA;tilted by an angle alpha. The inside of this cylinder is painted &quot;black&quot; and I want to know the output of this arrangement at the end of the cylinder in dependence of the tilt angle alpha.&#xD;&#xA;&#xD;&#xA;Thanks in advance,&#xD;&#xA;&#xD;&#xA;Uwe " ContentLicense="CC BY-SA 4.0" />
  <row Id="42144" PostHistoryTypeId="1" PostId="13792" RevisionGUID="22c4ab17-604d-4a22-af5b-ce4133ff3265" CreationDate="2023-11-03T11:38:37.493" UserId="20658" Text="How to imlement the Phong BRDF" ContentLicense="CC BY-SA 4.0" />
  <row Id="42145" PostHistoryTypeId="3" PostId="13792" RevisionGUID="22c4ab17-604d-4a22-af5b-ce4133ff3265" CreationDate="2023-11-03T11:38:37.493" UserId="20658" Text="|raytracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42149" PostHistoryTypeId="2" PostId="13793" RevisionGUID="7d24e202-aa40-4df5-9dad-00171cebea40" CreationDate="2023-11-04T02:06:26.690" UserId="19537" Text="The following are the steps you need to follow:&#xD;&#xA;1. Get the normal vector for the reflecting point as $n$.&#xD;&#xA;2. Calculate reflected direction from normal vector and $I$ in the **world frame**, as $I_r$&#xD;&#xA;3. Sample Phong BRDF. This will yield a **local frame** vector as $r$. The next thing you need to do is to convert this local vector to **world frame** vector (details are below).&#xD;&#xA;4. Once you converted this to world frame as $r_w$, the view direction you want will be $r_w$. Now you just need to evaluate the BRDF, return PDF, sampled direction and throughput.&#xD;&#xA;&#xD;&#xA;I assume the difficult part for you is the 3rd step. How do I convert a local vector to the world vector? How does the frame get defined? Let's answer the second question first.&#xD;&#xA;&#xD;&#xA;The Phong model proposes that the view direction should be sampled around the **reflected ray direction**. So we know that one of the axis of the coordinate frame is the reflected ray direction. The convention is that this vector usually serves as the z-axis for this local frame. That is, if you are talking about $(0, 0, 1)^T$ in this local sampling frame, the actual vector in the world frame for $(0, 0, 1)^T$ is the reflected ray direction. Since Phong model is isotropic on $\phi$ direction, the other two axes are free to choose.&#xD;&#xA;&#xD;&#xA;Next, how to convert from local frame to world frame? Say we have this $r$ which is sampled in a frame of which the z-axis is $(0, 0, 1)^T$, and we want to convert it as if it was sampled in a frame of which the z-axis is the reflected ray direction ($I_r$). You actually need to calculate the rotation matrix between $(0, 0, 1)^T$ and $I_r$. This can be done with the following steps:&#xD;&#xA;1. Calculate the cross product of $(0, 0, 1)^T$ and $I_r$. Since we know that cross product will yield a vector that is perpendicular to both input vectors, this will be our **axis of rotation**, that is, we will later rotate around this axis.&#xD;&#xA;2. Calculate the dot product of $(0, 0, 1)^T$ and $I_r$. This will yield **the cosine value for the angle between the two vectors**, and actually, if we rotate one of the vectors around the axis we get in step 1 by this angle, we will get the other vector.&#xD;&#xA;3. So, we rotate the vector around the cross-product axis by the dot-product angle. This can be achieved by [Rodrigues' rotation formula](https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula).&#xD;&#xA;&#xD;&#xA;The following is the code for Rodrigues' rotation formula. `np_rotation_between` uses the transform lib provided by `scipy` and `rotation_between` is hand-crafted (though in Taichi Lang). &#xD;&#xA;&#xD;&#xA;```python&#xD;&#xA;from scipy.spatial.transform import Rotation as Rot&#xD;&#xA;&#xD;&#xA;@ti.func&#xD;&#xA;def skew_symmetry(vec: vec3):&#xD;&#xA;    return mat3([&#xD;&#xA;        [0, -vec[2], vec[1]], &#xD;&#xA;        [vec[2], 0, -vec[0]], &#xD;&#xA;        [-vec[1], vec[0], 0]&#xD;&#xA;    ])&#xD;&#xA;    &#xD;&#xA;def np_rotation_between(fixed: Arr, target: Arr) -&gt; Arr:&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;        Transform parsed from xml file is merely camera orientation (numpy CPU version)&#xD;&#xA;        INPUT arrays [MUST] be normalized&#xD;&#xA;        Orientation should be transformed to be camera rotation matrix&#xD;&#xA;        Rotation from &lt;fixed&gt; vector to &lt;target&gt; vector, defined by cross product and angle-axis&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;    axis = np.cross(fixed, target)&#xD;&#xA;    dot = np.dot(fixed, target)&#xD;&#xA;    if abs(dot) &gt; 1. - 1e-5:            # nearly parallel&#xD;&#xA;        return np.sign(dot) * np.eye(3, dtype = np.float32)  &#xD;&#xA;    else:&#xD;&#xA;        # Not in-line, cross product is valid&#xD;&#xA;        axis /= np.linalg.norm(axis)&#xD;&#xA;        axis *= np.arccos(dot)&#xD;&#xA;        euler_vec = Rot.from_rotvec(axis).as_euler('zxy')&#xD;&#xA;        euler_vec[0] = 0                                                # eliminate roll angle&#xD;&#xA;        return Rot.from_euler('zxy', euler_vec).as_matrix()&#xD;&#xA;&#xD;&#xA;@ti.func&#xD;&#xA;def rotation_between(fixed: vec3, target: vec3) -&gt; mat3:&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;        Transform parsed from xml file is merely camera orientation (Taichi version)&#xD;&#xA;        Rodrigues transformation is implemented here&#xD;&#xA;        INPUT arrays [MUST] be normalized&#xD;&#xA;        Orientation should be transformed to be camera rotation matrix&#xD;&#xA;        Rotation from &lt;fixed&gt; vector to &lt;target&gt; vector, defined by cross product and angle-axis&#xD;&#xA;    &quot;&quot;&quot;&#xD;&#xA;    axis = tm.cross(fixed, target)&#xD;&#xA;    cos_theta = tm.dot(fixed, target)&#xD;&#xA;    ret_R = ti.Matrix.zero(float, 3, 3)&#xD;&#xA;    if ti.abs(cos_theta) &lt; 1. - 1e-5:&#xD;&#xA;        normed_axis = axis.normalized()&#xD;&#xA;        ret_R = ti.Matrix.diag(3, cos_theta) + ((1 - cos_theta) * colv3(*normed_axis)) @ rowv3(*normed_axis) + skew_symmetry(axis)&#xD;&#xA;    else:&#xD;&#xA;        ret_R = ti.Matrix.diag(3, tm.sign(cos_theta))&#xD;&#xA;    return ret_R&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA; &#xD;&#xA;With this, you can get the rotation matrix between $(0, 0, 1)^T$ and $I_r$. Let's suppose you get the rotation matrix to rotate $(0, 0, 1)^T$ to $I_r$ as $R$, then the sampled view direction for you will be:&#xD;&#xA;$$&#xD;&#xA;v = R(0, 0, 1)^T&#xD;&#xA;$$&#xD;&#xA;Otherwise, if the rotation is in the opposite direction, just use $R^T$ for this matrix-vector multiplication. There you go, the core mathematical formulae you need are (1) reflection (2) Phong local sampling (3) Rodrigues' rotation formula. " ContentLicense="CC BY-SA 4.0" />
  <row Id="42151" PostHistoryTypeId="2" PostId="13794" RevisionGUID="007f8e65-c2c8-413f-b588-b30934dc0886" CreationDate="2023-11-04T11:36:33.960" UserId="10096" Text="I am looking for code or pseudo-code for the generation of genus $k$ tori triangle meshes. I want to get something like in the image [here][1]. Book/paper references, code, github links, etc. are all welcome.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Connected_sum" ContentLicense="CC BY-SA 4.0" />
  <row Id="42153" PostHistoryTypeId="1" PostId="13794" RevisionGUID="007f8e65-c2c8-413f-b588-b30934dc0886" CreationDate="2023-11-04T11:36:33.960" UserId="10096" Text="Procedural generation of genus $k$ tori triangle meshes" ContentLicense="CC BY-SA 4.0" />
  <row Id="42154" PostHistoryTypeId="3" PostId="13794" RevisionGUID="007f8e65-c2c8-413f-b588-b30934dc0886" CreationDate="2023-11-04T11:36:33.960" UserId="10096" Text="|mesh|triangulation|procedural-generation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42155" PostHistoryTypeId="2" PostId="13795" RevisionGUID="62a52bc9-b841-47d7-97cc-bea1d6777d2d" CreationDate="2023-11-04T16:56:47.457" UserId="20471" Text="I can't leave a comment, because I don't have enough reputation points.&#xD;&#xA;&#xD;&#xA;Do you know how to represent your objects using a parametric function like f(x, y, z)? If so, then you can use Marching Cubes or Dual Contouring, or some similar algorithm to convert that field into a triangle mesh.&#xD;&#xA;&#xD;&#xA;Here is an implementation based off of Paul Bourke's code:&#xD;&#xA;&#xD;&#xA;https://github.com/sjhalayka/marching_cubes&#xD;&#xA;&#xD;&#xA;https://paulbourke.net/geometry/polygonise/&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42157" PostHistoryTypeId="5" PostId="13795" RevisionGUID="ca6b0590-7488-442a-83cc-3cbde3fce3c3" CreationDate="2023-11-04T19:11:54.670" UserId="20471" Comment="added 1 character in body" Text="I can't leave a comment, because I don't have enough reputation points.&#xD;&#xA;&#xD;&#xA;Do you know how to represent your objects using an *implicit* function like f(x, y, z)? If so, then you can use Marching Cubes or Dual Contouring, or some similar algorithm to convert that field into a triangle mesh.&#xD;&#xA;&#xD;&#xA;Here is an implementation based off of Paul Bourke's code:&#xD;&#xA;&#xD;&#xA;https://github.com/sjhalayka/marching_cubes&#xD;&#xA;&#xD;&#xA;https://paulbourke.net/geometry/polygonise/&#xD;&#xA;&#xD;&#xA;https://math.stackexchange.com/questions/152256/implicit-equation-for-double-torus-genus-2-orientable-surface&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42158" PostHistoryTypeId="2" PostId="13796" RevisionGUID="e94dcefb-6b13-456f-8917-53a89f938e04" CreationDate="2023-11-05T16:57:01.613" UserId="18894" Text="To quote from the Wikipedia page for the CIE 1931 color space &quot;The unit of the tristimulus values X, Y, and Z is often arbitrarily chosen so that Y = 1 or Y = 100 is the brightest white that a color display supports.&quot;&#xD;&#xA;&#xD;&#xA;Sometimes the values are in the range 0 to 1, and sometimes in the range 0 to 100. You just need to specify the illuminant using the same range as other XYZ values you are using. As the linear RGB values and resulting XYZ values are in the range 0 to 1, if you give the D65 values as X=0.950489, Y=1, Z = 1.08884 I think you'll get the results you want." ContentLicense="CC BY-SA 4.0" />
  <row Id="42160" PostHistoryTypeId="2" PostId="13797" RevisionGUID="a2e9e09f-8f22-4a03-8b28-0184d375cb84" CreationDate="2023-11-06T01:27:40.543" UserId="20817" Text="Im currently making some modifications for a [path tracer for Minecraft][1], specifically adding glossy refractions. The program currently uses for specular reflections [this method][2], linear interpolation between the diffuse lobe and the perfect specular refection depending on the roughness parameter. However this introduces a direction bias that is quite noticeable in renders. &#xD;&#xA;Here I have reproduced in in python, the red line is the mean vector while the green line is the specular refection for roughness values of 1, 0.7, 0.5, 0.3, 0.1 and 0.&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What would be the best way to correct for this bias without introducing substantial computation overhead. &#xD;&#xA;I do plan evenly to include more sophisticated BSDF like Cook-Tolerance in the renderer but wanted to have simpler model as an option. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/chunky-dev/chunky&#xD;&#xA;  [2]: https://blog.demofox.org/2020/06/06/casual-shadertoy-path-tracing-2-image-improvement-and-glossy-reflections/&#xD;&#xA;  [3]: https://i.stack.imgur.com/ELDeI.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42162" PostHistoryTypeId="1" PostId="13797" RevisionGUID="a2e9e09f-8f22-4a03-8b28-0184d375cb84" CreationDate="2023-11-06T01:27:40.543" UserId="20817" Text="Fixing bias in Specular lobe" ContentLicense="CC BY-SA 4.0" />
  <row Id="42163" PostHistoryTypeId="3" PostId="13797" RevisionGUID="a2e9e09f-8f22-4a03-8b28-0184d375cb84" CreationDate="2023-11-06T01:27:40.543" UserId="20817" Text="|pathtracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42164" PostHistoryTypeId="50" PostId="10248" RevisionGUID="062a33b2-f30b-46eb-9acf-72943d33b283" CreationDate="2023-11-07T14:07:30.907" UserId="-1" />
  <row Id="42165" PostHistoryTypeId="2" PostId="13798" RevisionGUID="3d8449d9-e70d-44bb-a67b-b47082d9b385" CreationDate="2023-11-08T08:13:38.667" UserId="9779" Text="I'm using GLSL to do spectral analysis of an input signal. I do the math to associate each pixel (in a single row) with a frequency, then use [The Goertzel Algorithm][1] to determine the contribution of that frequency in the signal.&#xD;&#xA;&#xD;&#xA;I'm having a lot of problems with this approach. First, GLSL's float isn't terribly high-precision, and I get a lot of loss of fidelity in the higher frequencies. I'm only going up to about 5kHz here, but you can see how bad the problem is. Eventually, I'd like to get up to 10-15kHz.&#xD;&#xA;&#xD;&#xA;[![Ouch][2]][2]&#xD;&#xA;&#xD;&#xA;Second, the error margins are massive. To get a reasonable result at typical audible frequencies, I have to sample at least 30-40 cycles of the frequency I'm looking at. This isn't too much of a problem for a 440Hz signal, but 40 cycles of a 27.5Hz (lowest frequency on a piano) is a whopping 52,000 samples!!!&#xD;&#xA;&#xD;&#xA;So, I'm getting a crappy result with both the range and the domain of my work. The standard FFT algorithm is no good in GLSL for a number of reasons. Is there any other way I can, in GLSL, get this kind of fidelity?&#xD;&#xA;&#xD;&#xA;[![Screen Grab from Voxengo SPAN][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.mstarlabs.com/dsp/goertzel/goertzel.html#:~:text=A%20discrete%20Fourier%20transform%20(DFT,arithmetic%2C%20roughly%20doubling%20the%20efficiency.&#xD;&#xA;  [2]: https://i.stack.imgur.com/f0FAv.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/teSr6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42167" PostHistoryTypeId="1" PostId="13798" RevisionGUID="3d8449d9-e70d-44bb-a67b-b47082d9b385" CreationDate="2023-11-08T08:13:38.667" UserId="9779" Text="Doing spectral analysis in GLSL, how can I get FFT-level fidelity in my results?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42168" PostHistoryTypeId="3" PostId="13798" RevisionGUID="3d8449d9-e70d-44bb-a67b-b47082d9b385" CreationDate="2023-11-08T08:13:38.667" UserId="9779" Text="|glsl|fourier-transform|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42169" PostHistoryTypeId="2" PostId="13799" RevisionGUID="83d6529d-f6ef-4bf7-b7da-1415162d95e9" CreationDate="2023-11-08T11:41:46.320" UserId="20829" Text="I'm trying to move my camera around the object, a house, using some keyboard keys and the `gluLookAt()` function.&#xD;&#xA;&#xD;&#xA;```lang-c&#xD;&#xA;#include &lt;GL/gl.h&gt;&#xD;&#xA;#include &lt;GL/glu.h&gt;&#xD;&#xA;#include &lt;GL/glut.h&gt;&#xD;&#xA;#include &lt;stdlib.h&gt;&#xD;&#xA;#include &lt;stdio.h&gt;&#xD;&#xA;#include &lt;math.h&gt;&#xD;&#xA;&#xD;&#xA;int win_id;&#xD;&#xA;const float raio = 100;&#xD;&#xA;float camera_x = 0.0f, camera_y = 0.0f, camera_z = raio;  // Posicao inicial da camera&#xD;&#xA;float up_x = 0.0f, up_y = 1.0f, up_z = 0.0f;  // Posicao inicial do Up Vector&#xD;&#xA;float phi = 0, theta = 0;&#xD;&#xA;&#xD;&#xA;// Desenha uma piramide de base quadrangular de lado 1 centrado na origem e altura 0.5&#xD;&#xA;void desenhaPiramide(){&#xD;&#xA;    glBegin(GL_QUADS);&#xD;&#xA;        glVertex3f(-0.5, 0, -0.5);&#xD;&#xA;        glVertex3f(-0.5, 0, 0.5);&#xD;&#xA;        glVertex3f(0.5, 0, 0.5);&#xD;&#xA;        glVertex3f(0.5, 0, -0.5);&#xD;&#xA;    glEnd();&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;        glVertex3f(-0.5, 0, -0.5);&#xD;&#xA;        glVertex3f(-0.5, 0, 0.5);&#xD;&#xA;        glVertex3f(0, 0.5, 0);&#xD;&#xA;    glEnd();&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;        glVertex3f(-0.5, 0, 0.5);&#xD;&#xA;        glVertex3f(0.5, 0, 0.5);&#xD;&#xA;        glVertex3f(0, 0.5, 0);&#xD;&#xA;    glEnd();&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;        glVertex3f(0.5, 0, 0.5);&#xD;&#xA;        glVertex3f(0.5, 0, -0.5);&#xD;&#xA;        glVertex3f(0, 0.5, 0);&#xD;&#xA;    glEnd();&#xD;&#xA;    glBegin(GL_TRIANGLES);&#xD;&#xA;        glVertex3f(0.5, 0, -0.5);&#xD;&#xA;        glVertex3f(-0.5, 0, -0.5);&#xD;&#xA;        glVertex3f(0, 0.5, 0);&#xD;&#xA;    glEnd();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Desenha um quadrado de lado 1&#xD;&#xA;void desenhaQuadrado(){&#xD;&#xA;    glBegin(GL_QUADS);&#xD;&#xA;        glVertex3f(-0.5, -0.5, 0);&#xD;&#xA;        glVertex3f(-0.5, 0.5, 0);&#xD;&#xA;        glVertex3f(0.5, 0.5, 0);&#xD;&#xA;        glVertex3f(0.5, -0.5, 0);&#xD;&#xA;    glEnd();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Aqui se capturam as teclas comuns (letras, números e ESC, por exemplo)&#xD;&#xA;void myKeyboard(unsigned char key, int x, int y){&#xD;&#xA;    float camera_speed = 0.1f;&#xD;&#xA;    switch (key){&#xD;&#xA;        case 'a': // Rotação para cima&#xD;&#xA;            phi += camera_speed;&#xD;&#xA;            break;&#xD;&#xA;        case 'w': // Rotação para a esquerda&#xD;&#xA;            theta -= camera_speed;&#xD;&#xA;            break;&#xD;&#xA;        case 'd': // Rotação para baixo&#xD;&#xA;            phi -= camera_speed;&#xD;&#xA;            break;&#xD;&#xA;        case 's': // Rotação para a direita&#xD;&#xA;            theta += camera_speed;&#xD;&#xA;            break;&#xD;&#xA;        case 'r':&#xD;&#xA;            phi = 0.0f;&#xD;&#xA;            theta = 0.0f;&#xD;&#xA;            up_y = 1;&#xD;&#xA;            break;&#xD;&#xA;        case 27:&#xD;&#xA;            glutDestroyWindow(win_id);&#xD;&#xA;            exit(0);&#xD;&#xA;            break;&#xD;&#xA;        default:&#xD;&#xA;            printf(&quot;Voce apertou a tecla codigo: %d\n&quot;, key);&#xD;&#xA;            break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (theta &gt;= 359){&#xD;&#xA;        theta = 0;&#xD;&#xA;    } else if (theta &lt; 0){&#xD;&#xA;        theta = 359;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (phi &gt;= 179){&#xD;&#xA;        phi = 0;&#xD;&#xA;    } else if (phi &lt; 0){&#xD;&#xA;        phi = 179;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    camera_x = raio * cos(theta) * sin(phi);&#xD;&#xA;    camera_y = raio * sin(theta) * sin(phi);&#xD;&#xA;    camera_z = raio * cos(phi);&#xD;&#xA;&#xD;&#xA;    glutPostRedisplay();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Aqui se capturam as teclas especiais (Alt, Control, Shift, F1, F2, etc.)&#xD;&#xA;void myKeyboardSpecial(int key, int x, int y ){&#xD;&#xA;    switch (key){&#xD;&#xA;        case GLUT_KEY_UP:&#xD;&#xA;            glutFullScreen(); // Modo tela cheia&#xD;&#xA;            break;&#xD;&#xA;        case GLUT_KEY_DOWN:&#xD;&#xA;            glutReshapeWindow(800, 600); // Modo janela de 800 por 600&#xD;&#xA;            break;&#xD;&#xA;        default:&#xD;&#xA;            printf(&quot;Voce apertou a tecla especial codigo: %d\n&quot;, key);&#xD;&#xA;            break;&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;// Trecho de codigo para interacoes com o mouse&#xD;&#xA;/*&#xD;&#xA;void myMouse(int button, int state, int x, int y){&#xD;&#xA;    if (button == GLUT_LEFT_BUTTON)&#xD;&#xA;    if (state == GLUT_DOWN){&#xD;&#xA;      float r, g, b;&#xD;&#xA;      r = (double)rand() / (double)RAND_MAX;&#xD;&#xA;      g = (double)rand() / (double)RAND_MAX;&#xD;&#xA;      b = (double)rand() / (double)RAND_MAX;&#xD;&#xA;      glColor3f(r,g,b);&#xD;&#xA;      printf(&quot;%.2f, %.2f, %.2f\n&quot;, r, g, b);&#xD;&#xA;    }&#xD;&#xA;    glutPostRedisplay();&#xD;&#xA;}&#xD;&#xA;*/&#xD;&#xA;&#xD;&#xA;void init(void){&#xD;&#xA;    glClearColor(0.5, 0.9, 0.4, 0.0);&#xD;&#xA;&#xD;&#xA;    // Define o modo de rastreio de cor utilizado para misturar a cor do material nos pontos da face (smoothing)&#xD;&#xA;    glShadeModel(GL_SMOOTH);&#xD;&#xA;&#xD;&#xA;    // Habilita a definição da cor do material a partir da cor corrente&#xD;&#xA;    glEnable(GL_COLOR_MATERIAL);&#xD;&#xA;&#xD;&#xA;    // Parâmetros para a luz ambiente, difusa e especular, definindo também a posição da luz&#xD;&#xA;    GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };&#xD;&#xA;    GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };&#xD;&#xA;    GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };&#xD;&#xA;    GLfloat light_position[] = { 10.0, 10.0, 10.0, 0.0 };&#xD;&#xA;&#xD;&#xA;    // Passa os parâmetros definidos acima para a OpenGL&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);&#xD;&#xA;    glLightfv(GL_LIGHT0, GL_POSITION, light_position);&#xD;&#xA;&#xD;&#xA;    // Habilita a luz ambiente, a luz zero e o depth buffer&#xD;&#xA;    glEnable(GL_LIGHTING);&#xD;&#xA;    glEnable(GL_LIGHT0);&#xD;&#xA;    glEnable(GL_DEPTH_TEST);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void display(void){&#xD;&#xA;    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;    glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;&#xD;&#xA;    // Define a posição da câmera, para onde ela aponta e qual o vetor UP&#xD;&#xA;    gluLookAt(camera_x, camera_y, camera_z, 0.0f, 0.0f, 0.0f, up_x, up_y, up_z);&#xD;&#xA;&#xD;&#xA;    // Base da casa&#xD;&#xA;    glPushMatrix();&#xD;&#xA;        glColor3f(0.392, 0.584, 0.929);&#xD;&#xA;        glScalef(0.75, 1, 1.5);&#xD;&#xA;        glutSolidCube(35);&#xD;&#xA;    glPopMatrix();&#xD;&#xA;&#xD;&#xA;    // Porta da casa&#xD;&#xA;    glPushMatrix();&#xD;&#xA;        glColor3f(0.21, 0.27, 0.31);&#xD;&#xA;        glTranslatef(0, -10, 26.50);&#xD;&#xA;        glScalef(8, 15, 1);&#xD;&#xA;        desenhaQuadrado();&#xD;&#xA;    glPopMatrix();&#xD;&#xA;&#xD;&#xA;    // Telhado da casa&#xD;&#xA;    glPushMatrix();&#xD;&#xA;        glColor3f(0.804, 0.522, 0.247);&#xD;&#xA;        glTranslatef(0, 17.5, 0);&#xD;&#xA;        glScalef(26.25, 30, 52.5);&#xD;&#xA;        desenhaPiramide();&#xD;&#xA;    glPopMatrix();&#xD;&#xA;&#xD;&#xA;    glFlush();&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;void reshape (int w, int h){&#xD;&#xA;    glViewport(0, 0, (GLsizei) w, (GLsizei) h);&#xD;&#xA;    glMatrixMode(GL_PROJECTION);&#xD;&#xA;    glLoadIdentity();&#xD;&#xA;    if (w &lt;= h)&#xD;&#xA;        // Se a largura for menor que a altura, a projeção é feita para manter a proporção da janela&#xD;&#xA;        glOrtho(-50, 50, -50*(GLfloat)h/(GLfloat)w, 50*(GLfloat)h/(GLfloat)w, -500.0, 500.0);&#xD;&#xA;    else&#xD;&#xA;        // Se a altura for menor que a largura, a projeção é feita para manter a proporção da janela&#xD;&#xA;        glOrtho(-50*(GLfloat)w/(GLfloat)h, 50*(GLfloat)w/(GLfloat)h, -50, 50, -500.0, 500.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;int main(int argc, char** argv){&#xD;&#xA;    glutInit(&amp;argc, argv);&#xD;&#xA;    glutInitDisplayMode(GLUT_SINGLE | GLUT_DEPTH | GLUT_RGB);&#xD;&#xA;    glutInitWindowSize(800, 600);&#xD;&#xA;    glutInitWindowPosition(300, 50);&#xD;&#xA;    win_id = glutCreateWindow(&quot;Casa_OpenGL_3D&quot;);&#xD;&#xA;    init();&#xD;&#xA;    glutDisplayFunc(display);&#xD;&#xA;    glutReshapeFunc(reshape);&#xD;&#xA;    glutKeyboardFunc(myKeyboard);&#xD;&#xA;    glutSpecialFunc(myKeyboardSpecial);&#xD;&#xA;    // glutMouseFunc(myMouse);&#xD;&#xA;    glutMainLoop();&#xD;&#xA;    return 0;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I press the 'a' or 'd' keys, the movement occurs exactly as it should, as if the object itself were rotating, but in reality, it's just the camera that is moving. An odd detail is that if my first keyboard input is 'w' or 's', nothing happens, but if I press that after having already pressed 'a' or 'd', the movement starts to occur.&#xD;&#xA;&#xD;&#xA;The major issue is that this translation isn't happening as I imagined... My idea was as if the house were enclosed by a sphere and the camera positioned on the face/perimeter of that sphere, so that it would only move in that region, enabling viewing the house from all angles and positions. But for some reason, when trying to perform a 360-degree translation, for example, the movement doesn't occur as planned.&#xD;&#xA;&#xD;&#xA;It's difficult to explain in detail; it's easier to understand by analyzing the result for yourself. Here is an image exemplifying the result I have in mind.&#xD;&#xA;&#xD;&#xA;[Camera movement on the 'plane' of the sphere][1]&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/lnMMN.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42171" PostHistoryTypeId="1" PostId="13799" RevisionGUID="83d6529d-f6ef-4bf7-b7da-1415162d95e9" CreationDate="2023-11-08T11:41:46.320" UserId="20829" Text="How to implement camera translation arround object using gluLookAt?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42172" PostHistoryTypeId="3" PostId="13799" RevisionGUID="83d6529d-f6ef-4bf7-b7da-1415162d95e9" CreationDate="2023-11-08T11:41:46.320" UserId="20829" Text="|opengl|computational-geometry|geometry|camera|glut|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42173" PostHistoryTypeId="2" PostId="13800" RevisionGUID="a249d310-4f2b-4a8a-8c1c-c51c560dc7d2" CreationDate="2023-11-08T16:01:58.363" UserId="445" Text="&gt;  An odd detail is that if my first keyboard input is 'w' or 's', nothing happens, but if I press that after having already pressed 'a' or 'd', the movement starts to occur.&#xD;&#xA;&#xD;&#xA;Okay, let's look at what `w` and `s` do:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;        case 'w': // Rotação para a esquerda&#xD;&#xA;            theta -= camera_speed;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;They modify the `theta` variable. Now, how is `theta` used?&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;    camera_x = raio * cos(theta) * sin(phi);&#xD;&#xA;    camera_y = raio * sin(theta) * sin(phi);&#xD;&#xA;    camera_z = raio * cos(phi);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The `theta` variable has no effect on the camera position if `sin(phi)` is zero. And the initial value of `phi` is zero, so `sin(phi)` _is_ initially zero. That explains it.&#xD;&#xA;&#xD;&#xA;In the bigger picture, the problem here is that you've defined the initial state to be `phi = 0` to be at the _pole_ of your spherical coordinate system. You probably want the initial state to be at the equator. That means you either:&#xD;&#xA;&#xD;&#xA;* Swap `sin(phi)` and `cos(phi)`, or&#xD;&#xA;* Make the initial `phi` angle be 90° or 270° instead of 0°.&#xD;&#xA;&#xD;&#xA;(By the way, the `sin` and `cos` functions accept radians, not degrees, but your code is assuming degrees. That won't immediately break things but you should probably fix it.)&#xD;&#xA;&#xD;&#xA;Note that there is a completely different way to implement a camera which you might want to use: don't use `gluLookAt` and instead convert your `phi` and `theta` directly into rotations of the modelview matrix. (This is closer to the usual style for first-person cameras.) The advantage of doing that, in this context, is that the keys will _always_ do something even at the pole; changing `theta` will control the camera's orientation in the world even if that means it's spinning in place at the pole, whereas in your code, at the pole the camera's roll is actually undefined (because the camera position vector is parallel to the `up` vector). However, this doesn't matter at all if you restrict the angle range to not hit the pole." ContentLicense="CC BY-SA 4.0" />
  <row Id="42175" PostHistoryTypeId="50" PostId="12259" RevisionGUID="e814b247-abf6-4259-a975-010b7a20af3d" CreationDate="2023-11-08T18:04:50.583" UserId="-1" />
  <row Id="42176" PostHistoryTypeId="2" PostId="13801" RevisionGUID="daf6f3dd-6f8c-4d99-bf40-9609f25e5aba" CreationDate="2023-11-08T19:50:09.440" UserId="20471" Text="I've been trying to implement this k-torus code that I found, but all it does is return a cylinder (torus of outer radius infinity). Is there anything that I'm missing here?&#xD;&#xA;&#xD;&#xA;    #include &quot;main.h&quot;&#xD;&#xA;    &#xD;&#xA;    float f(const float x, const int n)&#xD;&#xA;    {&#xD;&#xA;    	float result = 1.0;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 1; i &lt;= n; i++)&#xD;&#xA;    	{&#xD;&#xA;    		const float i_float = static_cast&lt;float&gt;(i);&#xD;&#xA;    &#xD;&#xA;    		result *= (result - (i_float - 1.0f)) * (result - i_float);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return result;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float g(const float x, const float y, const int n) &#xD;&#xA;    {&#xD;&#xA;    	return f(x, n) + powf(y, 2.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float h(const float x, const float y, const float z, const int n, const float r, const float R)&#xD;&#xA;    {&#xD;&#xA;    	return powf(g(x, y, n), 1.0) + powf(z, 2.0) - powf(r, 2.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    int main(void)&#xD;&#xA;    {&#xD;&#xA;    	const float grid_max = 10.0;&#xD;&#xA;    	const float grid_min = -grid_max;&#xD;&#xA;    	const size_t res = 100;&#xD;&#xA;    	const bool make_border = true;&#xD;&#xA;    	const float isovalue = 0.1f;&#xD;&#xA;    	const float border_value = 1.0f + isovalue;&#xD;&#xA;    	const int n = 2;&#xD;&#xA;    	const float radius = 0.1f;&#xD;&#xA;    	const float outer_radius = 1.0f;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	vector&lt;triangle&gt; triangles;&#xD;&#xA;    	vector&lt;float&gt; xyplane0(res*res, 0);&#xD;&#xA;    	vector&lt;float&gt; xyplane1(res*res, 0);&#xD;&#xA;    &#xD;&#xA;    	const float step_size = (grid_max - grid_min) / (res - 1);&#xD;&#xA;    &#xD;&#xA;    	size_t z = 0;&#xD;&#xA;    &#xD;&#xA;    	vertex_3 pos(grid_min, grid_min, grid_min);&#xD;&#xA;    &#xD;&#xA;    	// Calculate xy plane 0.&#xD;&#xA;    	for (size_t x = 0; x &lt; res; x++, pos.x += step_size)&#xD;&#xA;    	{&#xD;&#xA;    		pos.y = grid_min;&#xD;&#xA;    &#xD;&#xA;    		for (size_t y = 0; y &lt; res; y++, pos.y += step_size)&#xD;&#xA;    		{&#xD;&#xA;    			if (true == make_border &amp;&amp; (x == 0 || y == 0 || z == 0 || x == res - 1 || y == res - 1 || z == res - 1))&#xD;&#xA;    				xyplane0[x * res + y] = border_value;&#xD;&#xA;    			else&#xD;&#xA;    				xyplane0[x * res + y] = h(pos.x, pos.y, pos.z, n, radius, outer_radius);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	// Prepare for xy plane 1.&#xD;&#xA;    	z++;&#xD;&#xA;    	pos.z += step_size;&#xD;&#xA;    &#xD;&#xA;    	size_t box_count = 0;&#xD;&#xA;    &#xD;&#xA;    	// Calculate xy planes 1 and greater.&#xD;&#xA;    	for (; z &lt; res; z++, pos.z += step_size)&#xD;&#xA;    	{&#xD;&#xA;    		pos.x = grid_min;&#xD;&#xA;    &#xD;&#xA;    		cout &lt;&lt; &quot;Calculating triangles from xy-plane pair &quot; &lt;&lt; z &lt;&lt; &quot; of &quot; &lt;&lt; res - 1 &lt;&lt; endl;&#xD;&#xA;    &#xD;&#xA;    		for (size_t x = 0; x &lt; res; x++, pos.x += step_size)&#xD;&#xA;    		{&#xD;&#xA;    			pos.y = grid_min;&#xD;&#xA;    &#xD;&#xA;    			for (size_t y = 0; y &lt; res; y++, pos.y += step_size)&#xD;&#xA;    			{&#xD;&#xA;    				if (true == make_border &amp;&amp; (x == 0 || y == 0 || z == 0 || x == res - 1 || y == res - 1 || z == res - 1))&#xD;&#xA;    					xyplane1[x * res + y] = border_value;&#xD;&#xA;    				else&#xD;&#xA;    					xyplane1[x * res + y] = h(pos.x, pos.y, pos.z, n, radius, outer_radius);&#xD;&#xA;    			}&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		tesselate_adjacent_xy_plane_pair(&#xD;&#xA;    			box_count,&#xD;&#xA;    			xyplane0, xyplane1,&#xD;&#xA;    			z - 1,&#xD;&#xA;    			triangles,&#xD;&#xA;    			isovalue,&#xD;&#xA;    			grid_min, grid_max, res,&#xD;&#xA;    			grid_min, grid_max, res,&#xD;&#xA;    			grid_min, grid_max, res);&#xD;&#xA;    &#xD;&#xA;    		xyplane1.swap(xyplane0);&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	cout &lt;&lt; endl;&#xD;&#xA;    &#xD;&#xA;    	if (0 &lt; triangles.size())&#xD;&#xA;    		write_triangles_to_binary_stereo_lithography_file(triangles, &quot;out.stl&quot;);&#xD;&#xA;    &#xD;&#xA;    	// Print box-counting dimension&#xD;&#xA;    	// Make sure that step_size != 1.0f :)&#xD;&#xA;    	cout &lt;&lt; &quot;Box counting dimension: &quot; &lt;&lt; logf(static_cast&lt;float&gt;(box_count)) / logf(1.0f/step_size) &lt;&lt; endl;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/iZYnf.png&#xD;&#xA;&#xD;&#xA;The relevant documents are at:&#xD;&#xA;&#xD;&#xA;https://computergraphics.stackexchange.com/questions/13794/procedural-generation-of-genus-k-tori-triangle-meshes&#xD;&#xA;&#xD;&#xA;and &#xD;&#xA;&#xD;&#xA;https://math.stackexchange.com/questions/152256/implicit-equation-for-double-torus-genus-2-orientable-surface&#xD;&#xA;&#xD;&#xA;and&#xD;&#xA;&#xD;&#xA;https://github.com/sjhalayka/k-torus&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42178" PostHistoryTypeId="1" PostId="13801" RevisionGUID="daf6f3dd-6f8c-4d99-bf40-9609f25e5aba" CreationDate="2023-11-08T19:50:09.440" UserId="20471" Text="k-torus code in C++" ContentLicense="CC BY-SA 4.0" />
  <row Id="42179" PostHistoryTypeId="3" PostId="13801" RevisionGUID="daf6f3dd-6f8c-4d99-bf40-9609f25e5aba" CreationDate="2023-11-08T19:50:09.440" UserId="20471" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42181" PostHistoryTypeId="50" PostId="13752" RevisionGUID="8c53bc85-97b6-4cec-86b4-8d087e739ee8" CreationDate="2023-11-10T10:02:40.330" UserId="-1" />
  <row Id="42182" PostHistoryTypeId="5" PostId="13795" RevisionGUID="0a02a094-9d9e-4f1d-95d4-086038e0ed23" CreationDate="2023-11-11T03:46:42.153" UserId="20471" Comment="deleted 27 characters in body" Text="I can't leave a comment, because I don't have enough reputation points.&#xD;&#xA;&#xD;&#xA;Do you know how to represent your objects using an *implicit* function like f(x, y, z)? If so, then you can use Marching Cubes or Dual Contouring, or some similar algorithm to convert that field into a triangle mesh.&#xD;&#xA;&#xD;&#xA;As you can see in the source, the tori are multiplied together, and a non-zero isovalue is used.&#xD;&#xA;&#xD;&#xA;The final code is at: https://github.com/sjhalayka/k-genus_torus&#xD;&#xA;&#xD;&#xA;[![genus 5 tori][1]][1] &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r38ND.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42183" PostHistoryTypeId="2" PostId="13802" RevisionGUID="9f55b498-a814-473b-8d9f-d0e48f8b0d40" CreationDate="2023-11-11T03:54:57.727" UserId="20471" Text="As you will see in the code, the tori are multiplied together, and a non-zero isovalue is used.&#xD;&#xA;&#xD;&#xA;The final code is at: https://github.com/sjhalayka/k-genus_torus&#xD;&#xA;&#xD;&#xA;[![genus 5 tori][1]][1] &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r38ND.png&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42185" PostHistoryTypeId="5" PostId="13802" RevisionGUID="4118c09f-7f01-42e7-ad93-a9d808949312" CreationDate="2023-11-11T04:02:21.793" UserId="20471" Comment="added 87 characters in body" Text="As you will see in the code, the tori are multiplied together, and a non-zero isovalue is used.&#xD;&#xA;&#xD;&#xA;The final code is at: https://github.com/sjhalayka/k-genus_torus&#xD;&#xA;&#xD;&#xA;[![genus 5 tori][1]][1] &#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/r38ND.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/erb2G.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42186" PostHistoryTypeId="2" PostId="13803" RevisionGUID="41339194-f379-423f-bfe2-3367e7daaefc" CreationDate="2023-11-11T16:55:51.000" UserId="20840" Text="I've been following TheCherno's OpenGL tutorials and I got to the point where I could render a square by using an index buffer. Now I wanted to vary the color of the square by using $$\frac{\sin(t) + 1}{2}$$ as my normalized time-varying function to be used in each of the RGB entries in color. I thought I might proceed as follows: this is my fragment shader. &#xD;&#xA;&#xD;&#xA;    #shader fragment&#xD;&#xA;    #version 330 core&#xD;&#xA;    layout(location = 0) out vec4 color;&#xD;&#xA;    uniform float time;&#xD;&#xA;    &#xD;&#xA;    float time_Color(float t) {&#xD;&#xA;    	return (sin(t) + 1) / 2;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;    	color = vec4(time_Color(time), time_Color(time - 0.2), time_Color(time - 0.4), 1.0f);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;in my main loop in main.cpp, I have:&#xD;&#xA;&#xD;&#xA;	int location = glGetUniformLocation(theProgram, &quot;time&quot;);&#xD;&#xA;	&#xD;&#xA;	//Main loop&#xD;&#xA;	glfwSetTime(0);&#xD;&#xA;	while (!glfwWindowShouldClose(mainWindow)) {&#xD;&#xA;		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);&#xD;&#xA;		glClear(GL_COLOR_BUFFER_BIT);&#xD;&#xA;&#xD;&#xA;		glUniform1f(location, static_cast&lt;float&gt;(glfwGetTime()));&#xD;&#xA;		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);&#xD;&#xA;&#xD;&#xA;		glfwSwapBuffers(mainWindow);&#xD;&#xA;&#xD;&#xA;		glfwWaitEvents();&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;When I run this program, I do see a color-varying square but the change in color becomes slower and slower as the program continues. Initially the change is gradual but then sometime after like 7 secs, I start to get abrupt changes in color that only get updated after a long time. I suspect this is to do with the sin computation in the GPU but I don't actually know since I'm just beginning out. So why is this code working so slowly/inefficiently the longer the program executes?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42188" PostHistoryTypeId="1" PostId="13803" RevisionGUID="41339194-f379-423f-bfe2-3367e7daaefc" CreationDate="2023-11-11T16:55:51.000" UserId="20840" Text="Why does my implementation of a sinusoidally time-varying color work so slowly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42189" PostHistoryTypeId="3" PostId="13803" RevisionGUID="41339194-f379-423f-bfe2-3367e7daaefc" CreationDate="2023-11-11T16:55:51.000" UserId="20840" Text="|opengl|shader|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42190" PostHistoryTypeId="2" PostId="13804" RevisionGUID="be4ee491-6019-422d-8499-d6c007c1bdfd" CreationDate="2023-11-11T20:11:03.103" UserId="20847" Text="I'm sorry if this question is imprecise, or violates any guidelines. This is my first post on Stack Exchange, so any feedback is welcome.&#xD;&#xA;&#xD;&#xA;I am working on a ray-marcher in my spare time, which you can see for reference at https://replit.com/@GriffinSchreibe/My-First-Raymarcher (Please press view code to see what's happening, as it does not output anything to the console you can see just from viewing the project). Yes, I am working on an online IDE, purely because I do not have sufficient compute power on my laptop.&#xD;&#xA;My code is **heavily** based on Ray-tracing in one weekend. I have gradually worked through the first few sections, but one section has been stumping me, namely the refraction section.&#xD;&#xA;&#xD;&#xA;In my code I have this function that returns the ray color, given a ray shot from the camera:&#xD;&#xA;```&#xD;&#xA;vec3 ray_color(const ray &amp;r, int depth, float current_medium_ior = 1) {&#xD;&#xA;  // A medium ior of 1 means air.&#xD;&#xA;  if (depth &lt;= 0) {&#xD;&#xA;    return vec3(0, 0, 0);&#xD;&#xA;  }&#xD;&#xA;  // setup parameters and variables&#xD;&#xA;  float total_distance_traveled = 0.0;&#xD;&#xA;  const int NUMBER_OF_STEPS = 64; // 32;&#xD;&#xA;  const float MAXIMUM_HIT_DISTANCE = 0.001;&#xD;&#xA;  const float MAXIMUM_TRACE_DISTANCE = 1000.0;&#xD;&#xA;&#xD;&#xA;  vec3 color;&#xD;&#xA;&#xD;&#xA;  // iterate through the max number of steps&#xD;&#xA;  for (int i = 0; i &lt; NUMBER_OF_STEPS; ++i) {&#xD;&#xA;    // update the position&#xD;&#xA;    vec3 current_position =&#xD;&#xA;        r.origin() + total_distance_traveled * r.direction();&#xD;&#xA;    // find the distance&#xD;&#xA;    Surface closest_surface = map_the_world(current_position);&#xD;&#xA;    float distance_to_closest = step_size * closest_surface.sd;&#xD;&#xA;    &#xD;&#xA;    // if we hit something&#xD;&#xA;    float abs_dist = abs(distance_to_closest);&#xD;&#xA;    if (abs_dist &lt; MAXIMUM_HIT_DISTANCE) {&#xD;&#xA;      vec3 normal = calculate_normal(current_position);&#xD;&#xA;      vec3 direction;&#xD;&#xA;&#xD;&#xA;      float new_medium_ior = closest_surface.ior;&#xD;&#xA;      if (closest_surface.surface_type == &quot;REFRACTIVE&quot;) {&#xD;&#xA;&#xD;&#xA;          // Check if the medium has changed&#xD;&#xA;          if (new_medium_ior != current_medium_ior) {&#xD;&#xA;            std::clog&lt;&lt;&quot;Medium change!\n&quot;;&#xD;&#xA;              float ior_ratio = new_medium_ior / current_medium_ior;&#xD;&#xA;&#xD;&#xA;              vec3 direction = refract(r.direction(), normal, ior_ratio);&#xD;&#xA;&#xD;&#xA;              // Recursion&#xD;&#xA;              color = ray_color(ray(current_position + 0.004 * direction, direction), depth - 1, current_medium_ior);&#xD;&#xA;              return color;&#xD;&#xA;          } else {&#xD;&#xA;              // Continue with loop for further intersections within the medium or other behavior&#xD;&#xA;          }&#xD;&#xA;      }&#xD;&#xA; else {&#xD;&#xA;        direction = closest_surface.scatter_direction(r.direction(), normal);&#xD;&#xA;        // Catch degenerate scatter direction&#xD;&#xA;        if (direction.near_zero())&#xD;&#xA;          direction = normal;&#xD;&#xA;        // Recursion.&#xD;&#xA;        color = 0.5 * ray_color(ray(current_position + 0.004 * normal, direction), depth - 1, current_medium_ior);&#xD;&#xA;        return color;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // if we have been going for too long&#xD;&#xA;    if (total_distance_traveled &gt; MAXIMUM_TRACE_DISTANCE) {&#xD;&#xA;      break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // update the distance&#xD;&#xA;    total_distance_traveled += distance_to_closest;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // if we didn't find anything&#xD;&#xA;  // then we do a blue-white gradient.&#xD;&#xA;  vec3 unit_direction = unit_vector(r.direction());&#xD;&#xA;  auto a = 0.5 * (unit_direction.y() + 1.0);&#xD;&#xA;  return (1.0 - a) * vec3(1.0, 1.0, 1.0) + a * vec3(0.5, 0.7, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As you can see, I attempt to implement refraction, but only when the medium changes. After weeks of toil, I am still perplexed as to how to properly implement ray-marched refraction in the spirit of Ray-tracing in one Weekend (By that I mean no &quot;hacky&quot; solutions).&#xD;&#xA;&#xD;&#xA;I would be deeply grateful to anyone who could help me solve this problem.&#xD;&#xA;Oh, and you can play around with the code in the link above.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42192" PostHistoryTypeId="1" PostId="13804" RevisionGUID="be4ee491-6019-422d-8499-d6c007c1bdfd" CreationDate="2023-11-11T20:11:03.103" UserId="20847" Text="Raymarching Refraction" ContentLicense="CC BY-SA 4.0" />
  <row Id="42193" PostHistoryTypeId="3" PostId="13804" RevisionGUID="be4ee491-6019-422d-8499-d6c007c1bdfd" CreationDate="2023-11-11T20:11:03.103" UserId="20847" Text="|raymarching|refraction|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42194" PostHistoryTypeId="50" PostId="12470" RevisionGUID="fa411f3c-8609-4820-8c54-d51d042b1ac1" CreationDate="2023-11-12T00:07:45.893" UserId="-1" />
  <row Id="42199" PostHistoryTypeId="5" PostId="13804" RevisionGUID="79dddf8c-91e8-4d28-b9c0-127cf5ef5336" CreationDate="2023-11-14T11:02:03.590" UserId="20847" Comment="Partial solution problem." Text="I'm sorry if this question is imprecise, or violates any guidelines. This is my first post on Stack Exchange, so any feedback is welcome.&#xD;&#xA;&#xD;&#xA;I am working on a ray-marcher in my spare time, which you can see for reference at https://replit.com/@GriffinSchreibe/My-First-Raymarcher (Please press view code to see what's happening, as it does not output anything to the console you can see just from viewing the project). Yes, I am working on an online IDE, purely because I do not have sufficient compute power on my laptop.&#xD;&#xA;My code is **heavily** based on Ray-tracing in one weekend. I have gradually worked through the first few sections, but one section has been stumping me, namely the refraction section.&#xD;&#xA;&#xD;&#xA;In my code I have this function that returns the ray color, given a ray shot from the camera:&#xD;&#xA;```&#xD;&#xA;vec3 ray_color(const ray &amp;r, int depth, float current_medium_ior = 1) {&#xD;&#xA;  // A medium ior of 1 means air.&#xD;&#xA;  if (depth &lt;= 0) {&#xD;&#xA;    return vec3(0, 0, 0);&#xD;&#xA;  }&#xD;&#xA;  // setup parameters and variables&#xD;&#xA;  float total_distance_traveled = 0.0;&#xD;&#xA;  const int NUMBER_OF_STEPS = 64; // 32;&#xD;&#xA;  const float MAXIMUM_HIT_DISTANCE = 0.001;&#xD;&#xA;  const float MAXIMUM_TRACE_DISTANCE = 1000.0;&#xD;&#xA;&#xD;&#xA;  vec3 color;&#xD;&#xA;&#xD;&#xA;  // iterate through the max number of steps&#xD;&#xA;  for (int i = 0; i &lt; NUMBER_OF_STEPS; ++i) {&#xD;&#xA;    // update the position&#xD;&#xA;    vec3 current_position =&#xD;&#xA;        r.origin() + total_distance_traveled * r.direction();&#xD;&#xA;    // find the distance&#xD;&#xA;    Surface closest_surface = map_the_world(current_position);&#xD;&#xA;    float distance_to_closest = step_size * closest_surface.sd;&#xD;&#xA;    &#xD;&#xA;    // if we hit something&#xD;&#xA;    float abs_dist = abs(distance_to_closest);&#xD;&#xA;    if (abs_dist &lt; MAXIMUM_HIT_DISTANCE) {&#xD;&#xA;      vec3 normal = calculate_normal(current_position);&#xD;&#xA;      vec3 direction;&#xD;&#xA;&#xD;&#xA;      float new_medium_ior = closest_surface.ior;&#xD;&#xA;      if (closest_surface.surface_type == &quot;REFRACTIVE&quot;) {&#xD;&#xA;&#xD;&#xA;          // Check if the medium has changed&#xD;&#xA;          if (new_medium_ior != current_medium_ior) {&#xD;&#xA;            std::clog&lt;&lt;&quot;Medium change!\n&quot;;&#xD;&#xA;              float ior_ratio = new_medium_ior / current_medium_ior;&#xD;&#xA;&#xD;&#xA;              vec3 direction = refract(r.direction(), normal, ior_ratio);&#xD;&#xA;&#xD;&#xA;              // Recursion&#xD;&#xA;              color = ray_color(ray(current_position + 0.004 * direction, direction), depth - 1, current_medium_ior);&#xD;&#xA;              return color;&#xD;&#xA;          } else {&#xD;&#xA;              // Continue with loop for further intersections within the medium or other behavior&#xD;&#xA;          }&#xD;&#xA;      }&#xD;&#xA; else {&#xD;&#xA;        direction = closest_surface.scatter_direction(r.direction(), normal);&#xD;&#xA;        // Catch degenerate scatter direction&#xD;&#xA;        if (direction.near_zero())&#xD;&#xA;          direction = normal;&#xD;&#xA;        // Recursion.&#xD;&#xA;        color = 0.5 * ray_color(ray(current_position + 0.004 * normal, direction), depth - 1, current_medium_ior);&#xD;&#xA;        return color;&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    // if we have been going for too long&#xD;&#xA;    if (total_distance_traveled &gt; MAXIMUM_TRACE_DISTANCE) {&#xD;&#xA;      break;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // update the distance&#xD;&#xA;    total_distance_traveled += distance_to_closest;&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;  // if we didn't find anything&#xD;&#xA;  // then we do a blue-white gradient.&#xD;&#xA;  vec3 unit_direction = unit_vector(r.direction());&#xD;&#xA;  auto a = 0.5 * (unit_direction.y() + 1.0);&#xD;&#xA;  return (1.0 - a) * vec3(1.0, 1.0, 1.0) + a * vec3(0.5, 0.7, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As you can see, I attempt to implement refraction, but only when the medium changes. After weeks of toil, I am still perplexed as to how to properly implement ray-marched refraction in the spirit of Ray-tracing in one Weekend (By that I mean no &quot;hacky&quot; solutions).&#xD;&#xA;&#xD;&#xA;I would be deeply grateful to anyone who could help me solve this problem.&#xD;&#xA;Oh, and you can play around with the code in the link above.&#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;After fixing the medium change check to see if the origin medium was different from the current medium, I am now getting the refracting sphere as blue.&#xD;&#xA;I think that what is happening is that the step size is getting tiny inside the material, as I had the Distance Estimator return 0 inside the material. It then ran out of steps, and returned sky color.&#xD;&#xA;I am still curious about the best way to stop the ray-marcher running out of steps, though." ContentLicense="CC BY-SA 4.0" />
  <row Id="42200" PostHistoryTypeId="50" PostId="13250" RevisionGUID="f2f0b2d9-98cf-4b27-b8a9-b17d517a076e" CreationDate="2023-11-14T11:06:45.963" UserId="-1" />
  <row Id="42205" PostHistoryTypeId="50" PostId="13696" RevisionGUID="f12e0744-4c6d-4704-af81-84bbd85b72e7" CreationDate="2023-11-15T18:03:20.367" UserId="-1" />
  <row Id="42207" PostHistoryTypeId="2" PostId="13807" RevisionGUID="d3799449-0636-4bf8-a7ca-3ec404de43af" CreationDate="2023-11-16T09:43:56.717" UserId="7389" Text="In Wikipedia, a [polygon][1] is defined as a [ closed polygonal chain][2]. In other words, the term &quot;polygon&quot; implies that the curve is closed.&#xD;&#xA;&#xD;&#xA;My question is: Is it common to refer to non-closed, piecewise linear curves as &quot;polygons&quot;, too? Otherwise, is there a different term that describes general polygonal chains (other than &quot;polygonal chain&quot; which I find a bit long)?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Polygon&#xD;&#xA;  [2]: https://en.wikipedia.org/wiki/Polygonal_chain" ContentLicense="CC BY-SA 4.0" />
  <row Id="42209" PostHistoryTypeId="1" PostId="13807" RevisionGUID="d3799449-0636-4bf8-a7ca-3ec404de43af" CreationDate="2023-11-16T09:43:56.717" UserId="7389" Text="Nomenclature: Other word for non-closed polygon?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42210" PostHistoryTypeId="3" PostId="13807" RevisionGUID="d3799449-0636-4bf8-a7ca-3ec404de43af" CreationDate="2023-11-16T09:43:56.717" UserId="7389" Text="|polygon|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42211" PostHistoryTypeId="2" PostId="13808" RevisionGUID="a763d0e0-f6eb-4b44-852f-7faa6143bfee" CreationDate="2023-11-16T09:59:27.450" UserId="7724" Text="I personally wouldn't like to describe non-closed piecewise linear curves as polygons. You might find *polyline* a better word to describe it. A *polyline* is a collection of connected straight line segments." ContentLicense="CC BY-SA 4.0" />
  <row Id="42213" PostHistoryTypeId="2" PostId="13809" RevisionGUID="45650c49-5612-4b9a-9f52-38913dd2d7f6" CreationDate="2023-11-16T11:56:19.273" UserId="6172" Text="If you are using the GLM library, you can define `GLM_FORCE_DEPTH_ZERO_TO_ONE`, as deabird11 said.&#xD;&#xA;&#xD;&#xA;But you can also call specific functions suited for the projection of each API.&#xD;&#xA;&#xD;&#xA;- For OpenGL call: `glm::perspectiveRH_NO`&#xD;&#xA;- For Vulkan call: `glm::perspectiveRH_ZO`&#xD;&#xA;&#xD;&#xA;This could be useful if you are making an engine that supports both OpenGL and Vulkan (using a define would lock you to use one convention).&#xD;&#xA;&#xD;&#xA;I recommend reading this article for a good explanation on the differences between OpenGL and Vulkan coordinate systems: https://johannesugb.github.io/gpu-programming/why-do-opengl-proj-matrices-fail-in-vulkan." ContentLicense="CC BY-SA 4.0" />
  <row Id="42215" PostHistoryTypeId="12" PostId="13809" RevisionGUID="65dd21d9-cf80-4c99-9019-a6d63928a9a6" CreationDate="2023-11-16T12:55:38.233" UserId="6172" Comment="via Vote" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6172,&quot;DisplayName&quot;:&quot;user1754322&quot;}],&quot;DeleteType&quot;:1}" />
  <row Id="42216" PostHistoryTypeId="5" PostId="13809" RevisionGUID="66dfa418-65c9-4b29-86a8-0179f9e2e382" CreationDate="2023-11-16T13:13:06.667" UserId="6172" Comment="added 78 characters in body" Text="If you are using the GLM library, you can define `GLM_FORCE_DEPTH_ZERO_TO_ONE`, as deabird11 said.&#xD;&#xA;&#xD;&#xA;But you can also call specific functions suited for the projection of each API.&#xD;&#xA;&#xD;&#xA;- For OpenGL call: `glm::perspectiveRH_NO` or `glm::perspectiveNO`, or simply `glm::perspective`&#xD;&#xA;- For Vulkan call: `glm::perspectiveRH_ZO` or `glm::perspectiveZO`&#xD;&#xA;&#xD;&#xA;This could be useful if you are making an engine that supports both OpenGL and Vulkan (using a define would lock you to use one convention).&#xD;&#xA;&#xD;&#xA;I recommend reading this article for a good explanation on the differences between OpenGL and Vulkan coordinate systems: https://johannesugb.github.io/gpu-programming/why-do-opengl-proj-matrices-fail-in-vulkan." ContentLicense="CC BY-SA 4.0" />
  <row Id="42217" PostHistoryTypeId="5" PostId="13809" RevisionGUID="601879a1-7638-4187-b8de-c323cdf6c74f" CreationDate="2023-11-16T13:47:59.827" UserId="6172" Comment="added 78 characters in body" Text="If you are using the GLM library, you can define `GLM_FORCE_DEPTH_ZERO_TO_ONE`, as deabird11 said.&#xD;&#xA;&#xD;&#xA;But you can also call specific functions suited for the projection of each API.&#xD;&#xA;&#xD;&#xA;- For OpenGL call: `glm::perspectiveRH_NO` or `glm::perspectiveNO`, or simply `glm::perspective`&#xD;&#xA;- For Vulkan call: `glm::perspectiveRH_ZO` or `glm::perspectiveZO`&#xD;&#xA;&#xD;&#xA;This could be useful if you are making an engine that supports both OpenGL and Vulkan (using a define would lock you to use one convention).&#xD;&#xA;&#xD;&#xA;You still need to invert the Y: `proj[1][1] *= -1;` for Vulkan. After all, GLM is designed for OpenGL.&#xD;&#xA;&#xD;&#xA;I recommend reading this article for a good explanation on the differences between OpenGL and Vulkan coordinate systems: https://johannesugb.github.io/gpu-programming/why-do-opengl-proj-matrices-fail-in-vulkan." ContentLicense="CC BY-SA 4.0" />
  <row Id="42218" PostHistoryTypeId="13" PostId="13809" RevisionGUID="bd07398a-c809-4930-a43c-a3d61cb13e6d" CreationDate="2023-11-16T13:48:18.163" UserId="6172" Text="{&quot;Voters&quot;:[{&quot;Id&quot;:6172,&quot;DisplayName&quot;:&quot;user1754322&quot;}]}" />
  <row Id="42219" PostHistoryTypeId="5" PostId="12453" RevisionGUID="6c843525-050a-459a-9480-286b223473ef" CreationDate="2023-11-16T15:09:53.187" UserId="7952" Comment="fixed typos" Text="Note that there is a little extra info here to (hopefully) provide the info need to understand the answer at the end. Plus I don't know of any sources that gives all the solutions in one place....&#xD;&#xA;&#xD;&#xA;Vulkan clip space has [1, -1] for the y axis where OpenGL has [-1, 1] so just multiplying the perspective matrix [1][1] value by -1 will &quot;correct&quot; the OpenGL matrix to work with Vulkan. All it really does is flip the y axis.&#xD;&#xA;(or you can also use gl_Postion.y *= -1) &#xD;&#xA;&#xD;&#xA;As of Vulkan 1.1 negative values are allowed when setting up the viewport which gives a fairly natural solution to the same problem.&#xD;&#xA;&#xD;&#xA;For the depth range:&#xD;&#xA;Vulkan has a [0, 1] range for the Z axis in NDC space where OpenGL has [-1, 1] range (by default). There are a couple ways to handle this. You can remap the OpenGL range to the Vulkan range fairly easily with:&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    gl_Position.z = (gl_Position.z + gl_Position.w) / 2.0;&#xD;&#xA;&#xD;&#xA;The other option is to modify the perspective matrix to match up with Vulkan. The Vulkan approach (which is also used in directx) maps to floating point numbers better since floating point numbers have more accuracy near zero. Also, some depth conversion code is simplified using a range of [0,1]. Finally, using a range [0,1] allows for &quot;reverse Z&quot; (improving floating point number distribution)&#xD;&#xA;&#xD;&#xA;Here is some code for generating a Vulkan friendly perspective matrix. Note that this code looks a lot simpler then what GLM uses because it expects a symmetric frustum. This code is copied from the FGED website...mostly&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	mat4 MakeProjectionMatrix(float fovy_rads, float s, float near, float far)&#xD;&#xA;	{&#xD;&#xA;		float g = 1.0f / tan(fovy_rads * 0.5);&#xD;&#xA;		float k = far / (far - near);&#xD;&#xA;&#xD;&#xA;		return mat4(g / s,	0.0f,	0.0f,	0.0f,&#xD;&#xA;			         0.0f,	g,		0.0f,	0.0f,&#xD;&#xA;			         0.0f,	0.0f,	k,		-near * k,&#xD;&#xA;			         0.0f,	0.0f,	1.0f,	0.0f);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;(This solution does not flip the y-axis.)&#xD;&#xA;&#xD;&#xA;Finally: A perspective matrix setup for OpenGL will work in Vulkan but it has limitations. The y axis will be flipped and objects falling in the [0,1] range will be visible. But objects falling in the [-1,0) range will not. Since Vulkan has a depth range of [0,1] it is easy to get the &quot;illusion&quot; that it is fully functional since the camera will appear to map correctly to the full depth range.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42220" PostHistoryTypeId="52" PostId="13807" RevisionGUID="b5c01948-7dcc-42a1-a124-52554d3dd363" CreationDate="2023-11-16T17:45:11.243" />
  <row Id="42221" PostHistoryTypeId="2" PostId="13810" RevisionGUID="4996a4ea-2e34-46b8-858e-918418c94623" CreationDate="2023-11-17T09:13:10.320" UserId="8877" Text="https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)&#xD;&#xA;&#xD;&#xA;uniform without buffer backed, only location, no binding.&#xD;&#xA;&#xD;&#xA;location similar to position offset.&#xD;&#xA;&#xD;&#xA;    // shader code&#xD;&#xA;    layout (location = 0) uniform float fTime;&#xD;&#xA;&#xD;&#xA;    // host code&#xD;&#xA;    location = 0;&#xD;&#xA;    glUniform1f(location, 45.2f);  // update data to uniform location 0&#xD;&#xA;&#xD;&#xA;more shader example&#xD;&#xA;&#xD;&#xA;    // each array element consume 1 location&#xD;&#xA;    layout(location = 0) out vec3 vals[4];      // Consumes 4 locations&#xD;&#xA;    // each struct field consume location&#xD;&#xA;    struct OutData{&#xD;&#xA;        vec3 data1;                             // Consumes 1 location&#xD;&#xA;        dvec4 data2;                            // Consumes 2 location&#xD;&#xA;        float val[3];                           // Consumes 3 location&#xD;&#xA;    };&#xD;&#xA;    layout(location = 4) out OutData myOut;     // Consumes 6 locations&#xD;&#xA;    layout(location = 10) out vec2 texCoord;    // Consumes 1 location&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;uniform block with buffer backed, only binding, no location.&#xD;&#xA;&#xD;&#xA;binding is something like block index, the field offset inside the buffer similar to location.&#xD;&#xA;&#xD;&#xA;    // shader code&#xD;&#xA;    layout(binding = 0, std140) uniform MainBlock { // blockIndex = 0&#xD;&#xA;        vec3 data;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    // host code&#xD;&#xA;    storageBlockIndex= 0;&#xD;&#xA;    uniformBlockBinding = 1; // any value&#xD;&#xA;    glUniformBlockBinding(program, storageBlockIndex, uniformBlockBinding);&#xD;&#xA;    glBindBufferBase(GL_UNIFORM_BUFFER, uniformBlockBinding, bufferId);&#xD;&#xA;&#xD;&#xA;relation of block index and binding point:&#xD;&#xA;&#xD;&#xA;    buffer id          binding points 0            uniform block index&#xD;&#xA;    buffer id   \/     binding points 1    \/      uniform block index&#xD;&#xA;    buffer id   /\     binding points 2    /\      uniform block index&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;for sampler, binding is texture unit&#xD;&#xA;    &#xD;&#xA;    // shader code&#xD;&#xA;    layout (binding = 0) uniform sampler2D foo;&#xD;&#xA;&#xD;&#xA;    // host code&#xD;&#xA;    unit = 0;&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId);&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + unit);&#xD;&#xA;    glUniformli(location, unit);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;relation of texture unit and uniform location:&#xD;&#xA;&#xD;&#xA;    texture id          texture unit 0            uniform location&#xD;&#xA;    texture id   \/     texture unit 1    \/      uniform location&#xD;&#xA;    texture id   /\     texture unit 2    /\      uniform location&#xD;&#xA;&#xD;&#xA;     " ContentLicense="CC BY-SA 4.0" />
  <row Id="42223" PostHistoryTypeId="5" PostId="13810" RevisionGUID="dc925b97-618b-43ac-af93-4d42a806052c" CreationDate="2023-11-17T09:49:11.797" UserId="8877" Comment="added 57 characters in body" Text="https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)&#xD;&#xA;&#xD;&#xA;uniform without buffer backed, only location, no binding.&#xD;&#xA;&#xD;&#xA;location similar to position offset.&#xD;&#xA;&#xD;&#xA;    // shader code&#xD;&#xA;    layout (location = 0) uniform float fTime;&#xD;&#xA;&#xD;&#xA;    // host code&#xD;&#xA;    location = 0;&#xD;&#xA;    glUniform1f(location, 45.2f);  // update data to uniform location 0&#xD;&#xA;&#xD;&#xA;more shader example&#xD;&#xA;&#xD;&#xA;    // each array element consume 1 location&#xD;&#xA;    layout(location = 0) out vec3 vals[4];      // Consumes 4 locations&#xD;&#xA;    // each struct field consume location&#xD;&#xA;    struct OutData{&#xD;&#xA;        vec3 data1;                             // Consumes 1 location&#xD;&#xA;        dvec4 data2;                            // Consumes 2 location&#xD;&#xA;        float val[3];                           // Consumes 3 location&#xD;&#xA;    };&#xD;&#xA;    layout(location = 4) out OutData myOut;     // Consumes 6 locations&#xD;&#xA;    layout(location = 10) out vec2 texCoord;    // Consumes 1 location&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;uniform block with buffer backed, only binding, no location.&#xD;&#xA;&#xD;&#xA;binding is something like block index, the field offset inside the buffer similar to location.&#xD;&#xA;&#xD;&#xA;    // shader code&#xD;&#xA;    layout(binding = 0, std140) uniform MainBlock { // blockIndex = 0&#xD;&#xA;        vec3 data;&#xD;&#xA;    };&#xD;&#xA;&#xD;&#xA;    // host code&#xD;&#xA;    storageBlockIndex= 0;&#xD;&#xA;    uniformBlockBinding = 1; // any value&#xD;&#xA;    glUniformBlockBinding(program, storageBlockIndex, uniformBlockBinding);&#xD;&#xA;    glBindBufferBase(GL_UNIFORM_BUFFER, uniformBlockBinding, bufferId);&#xD;&#xA;&#xD;&#xA;relation of block index and binding point:&#xD;&#xA;&#xD;&#xA;    buffer id          binding points 0            uniform block index&#xD;&#xA;    buffer id   \/     binding points 1    \/      uniform block index&#xD;&#xA;    buffer id   /\     binding points 2    /\      uniform block index&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;for sampler, binding is texture unit, also can specify location &#xD;&#xA;    &#xD;&#xA;    // shader code&#xD;&#xA;    //layout (binding = 0) uniform sampler2D foo;&#xD;&#xA;    layout (location = 0, binding = 1) uniform sampler2D foo;&#xD;&#xA;&#xD;&#xA;    // host code&#xD;&#xA;    location = 0;&#xD;&#xA;    unit = 1;&#xD;&#xA;    glActiveTexture(GL_TEXTURE0 + unit);      // set active unit&#xD;&#xA;    glBindTexture(GL_TEXTURE_2D, textureId);  // put to current active unit&#xD;&#xA;    &#xD;&#xA;    glUniformli(location, unit);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;relation of texture unit and uniform location:&#xD;&#xA;&#xD;&#xA;    texture id          texture unit 0            uniform location&#xD;&#xA;    texture id   \/     texture unit 1    \/      uniform location&#xD;&#xA;    texture id   /\     texture unit 2    /\      uniform location&#xD;&#xA;&#xD;&#xA;     " ContentLicense="CC BY-SA 4.0" />
  <row Id="42226" PostHistoryTypeId="2" PostId="13811" RevisionGUID="f093e729-0bd0-4554-8d32-b308530ea8a9" CreationDate="2023-11-18T19:46:30.457" UserId="523" Text="Just so we're on the same page, you should have stated the method you're talking about—something like (rewritten from link) (disclaimer: none of the code in this answer has been tested):&#xD;&#xA;```glsl&#xD;&#xA;vec3 diff_dir = normalize( normal + rand_unit_vec() );&#xD;&#xA;&#xD;&#xA;vec3 mirr_dir = reflect( ray_in, normal );&#xD;&#xA;vec3 spec_dir = normalize(mix( mirr_dir,diff_dir, roughness ));&#xD;&#xA;&#xD;&#xA;vec3 ray_out = mix( diff_dir,spec_dir, specular_enabled );&#xD;&#xA;```&#xD;&#xA;**Fundamentally, your question is how you can cheaply remove directional &quot;bias&quot; from this.**&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;The reason there's bias here should be apparent from what the code is doing—it's blending the specular reflection with the diffuse reflection—the diffuse reflection being random and in the upper hemisphere, and the specular reflection being the mirror direction.&#xD;&#xA;&#xD;&#xA;The effect is that the specular gets blurred, but the diffuse being in only the upper hemisphere also pulls the result upward.  They probably did it this way because it prevents having to check that the specular direction is above the plane.&#xD;&#xA;&#xD;&#xA;**A simple way to change that would be to do something else**.  E.g. maybe instead calculate `spec_dir` as:&#xD;&#xA;```glsl&#xD;&#xA;vec3 mirr_dir=reflect( ray_in, normal ), spec_dir;&#xD;&#xA;do {&#xD;&#xA;    spec_dir = normalize( mirr_dir + roughness*rand_unit_vec() );&#xD;&#xA;} while ( dot(spec_dir,normal) &lt; 0.0 );&#xD;&#xA;```&#xD;&#xA;That'll do a &quot;fuzzy&quot; specular reflection that's centered around the reflection direction and clipped (with rejection sampling) against the plane.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;**However, I *do not* recommend you do this**.&#xD;&#xA;&#xD;&#xA;First, a good specular BRDF *should* have this sort of biased-upward behavior, so this is a feature, not a bug.  A more familiar but still basic example will be the Phong BRDF (which is centered around the reflection direction) and the Blinn–Phong BRDF (which has more upward bias).  Although both BRDFs are obsolete for production purposes, the Blinn–Phong BRDF is widely considered to be superior for this biasing behavior—it leads to important perceptual effects like smearing out highlights lengthwise at glancing angles (see e.g. &quot;[Crafting Physically Motivated Shading Models for Game Development](https://renderwonk.com/publications/s2010-shading-course/hoffman/s2010_physically_based_shading_hoffman_b.pdf)&quot; for discussion and examples).&#xD;&#xA;&#xD;&#xA;Second and more fundamentally, this is this is not a proper BRDF anyway and messing with its shape is not productive.  It was broken before you started.  Sampling the diffuse ray like this will not give you (e.g.) Lambertian, and this specular distribution is a poorly concealed blurred mirror.  You would be much better with a microfacet model like you were thinking of doing—and it's not even that much more difficult to implement!  Please just do that instead." ContentLicense="CC BY-SA 4.0" />
  <row Id="42228" PostHistoryTypeId="2" PostId="13812" RevisionGUID="911483e9-59d5-4c54-a3e1-6d0bc2e01479" CreationDate="2023-11-18T21:19:50.073" UserId="20847" Text="The answer, I realized, is to specify a minimum stepsize inside refractive materials." ContentLicense="CC BY-SA 4.0" />
  <row Id="42230" PostHistoryTypeId="2" PostId="13813" RevisionGUID="48f3f3d9-833e-4072-b697-cdcfe9a4ea23" CreationDate="2023-11-18T22:05:15.250" UserId="523" Text="In rendering, we want to *integrate* over the light paths (with Monte Carlo integration).  The common simplification is that the emissive surfaces emit radiance and the camera is sensitive to radiance, so the game becomes integrating radiance.  Whereas, it looks like you're just tracing rays and multiplying stuff together.&#xD;&#xA;&#xD;&#xA;Intuitively, let's suppose you have a *very* specular BRDF.  For any particular incident ray, the value of the BRDF within the lobe *is* high, but the solid angle of the lobe itself is *small*.  This is the part you're not accounting for, the integration domain.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Recall the rendering equation, and notice that it's an integral:&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) = \int_\Omega L(x,\omega_i) ~ ( n \cdot \omega_i ) ~ f_r(\omega_i,x,\omega_o) ~ d \omega_i&#xD;&#xA;$$&#xD;&#xA;The Monte Carlo integration for this is what we expect: **take a sample from the integrand and divide by the probability density of choosing it**.  Averaging a bunch of such calculations produces the same thing in expectation:&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) = E\left[ \frac{1}{N}\sum_{k=1}^N&#xD;&#xA;        \frac{L(x,\omega_k) ~ ( n \cdot \omega_k ) ~ f_r(\omega_k,x,\omega_o)&#xD;&#xA;    }{\text{pdf}(\omega_k)} \right]\\&#xD;&#xA;    \hspace{5cm}\text{where each }\omega_k\text{ sampled from }\Omega\text{ according}\\&#xD;&#xA;    \hspace{5.3cm}\text{to a distribution characterized by }\text{pdf}(\omega_k)&#xD;&#xA;$$&#xD;&#xA;That averaging step is generally done in the main loop (averaging a bunch of paths instead of individual surface interactions), so the Monte Carlo estimator for a single surface interaction is just:&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) ~~\sim~~ L(x,\omega_k) ~ ( n \cdot \omega_k ) ~ f_r(\omega_k,x,\omega_o) ~/~ \text{pdf}(\omega_k)&#xD;&#xA;$$&#xD;&#xA;*I reckon the proximate problem is that you're missing that division.*&#xD;&#xA;&#xD;&#xA;The $\text{pdf}(\omega_k)$ term is the probability density of sampling your ray.  For example, if you choose rays uniformly at random, then the probability density is just the total probability ($1$) divided by the integration domain ($\Omega$, the surface area of the hemisphere, $2\pi$).  That is, $\text{pdf}(\omega_k)=1/(2\pi)$:&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) ~~\sim~~ L(x,\omega_k) ~ ( n \cdot \omega_k ) ~ f_r(\omega_k,x,\omega_o) ~/~ (1/(2\pi))\\&#xD;&#xA;    \hspace{5cm}\text{when }\omega_k\text{ sampled uniformly from }\Omega&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now, sampling uniformly from the hemisphere is a terrible way to sample essentially every BRDF.  A slightly more complicated way is to sample proportional to the cosine-weighted hemisphere—i.e., $\text{pdf}(\omega_k)=( n \cdot \omega_k )/\pi$:&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) ~~\sim~~ L(x,\omega_k) ~ ( n \cdot \omega_k ) ~ f_r(\omega_k,x,\omega_o) ~/~ (( n \cdot \omega_k )/\pi)\\&#xD;&#xA;    \hspace{5cm}\text{when }\omega_k\text{ sampled cosine-weighted from }\Omega&#xD;&#xA;$$&#xD;&#xA;This is much better for most BRDFs (in fact it's optimal for a Lambertian BRDF, because it exactly matches it).  It's still pretty bad for most BRDFs, but it's a reasonable &quot;default&quot; sampler if you have no idea what the BRDF looks like or you're just testing.&#xD;&#xA;&#xD;&#xA;**You can freely choose *how* you sample rays, but you must always account for that sampling technique by dividing out its probability density**.&#xD;&#xA;&#xD;&#xA;In this case, you mentioned sampling in &quot;a mirror-like fashion&quot;, which could mean anything, and you're working with a microfacet BRDF, which is nontrivial.  Sampling these more complicated BRDFs is difficult, but there are resources available, and you can always use a simpler sampler (e.g. cosine-weight sampling) and it will still *work* (the integral estimate will just converge slower).&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;P.S.: for testing purposes, I recommend you get this working for a Lambertian BRDF with the uniformly random sampler.  Then upgrade to the cosine-weighted sampler.  Then add the microfacet BRDF.  Then work on more advanced samplers for the microfacet BRDF.&#xD;&#xA;&#xD;&#xA;P.P.S.: I strongly recommend doing a &quot;white furnace test&quot; for each test.  You render a plane with albedo 1 inside of a flat-gray environment map.  If everything is working correctly, the plane will converge to exactly the same color as the background and &quot;disappear&quot;." ContentLicense="CC BY-SA 4.0" />
  <row Id="42232" PostHistoryTypeId="2" PostId="13814" RevisionGUID="cd1fca8b-2d41-4dd6-adbc-f71a447849c0" CreationDate="2023-11-19T06:08:12.407" UserId="523" Text="## Specular, Color, Fresnel&#xD;&#xA;&#xD;&#xA;&gt; BSDF of purely specular surfaces is zero almost everywhere and infinite in one point [...] how do you know what is the reflectance of the surface at that point? From the infinity you can['t] really tell.&#xD;&#xA;&#xD;&#xA;Let's consider a mirror BRDF as our example throughout (a specular BTDF and similar such objects are analogous).  For this BRDF, we have (see e.g. [PBRT 3 §8.2.2](https://pbr-book.org/3ed-2018/Reflection_Models/Specular_Reflection_and_Transmission#SpecularReflection)):&#xD;&#xA;$$&#xD;&#xA;    f_r(\omega_i,x,\omega_o) ~:=~ F ~ \delta(\omega_i-\omega_r) ~/~ (n \cdot \omega_i)&#xD;&#xA;$$&#xD;&#xA;where $F$ is the Fresnel coefficient and $\delta$ is the [Dirac delta function](https://en.wikipedia.org/wiki/Dirac_delta_function).  The full Fresnel term, because the complex-valued IOR varies per-wavelength, will produce a scalar that varies per-wavelength.  Thus, different wavelengths of light reflect more or less out of the surface, and thus you get an albedo and a color.  In practice, *essentially everyone* special-cases this to just be configurable to a constant color:&#xD;&#xA;$$&#xD;&#xA;    f_r(\omega_i,x,\omega_o) ~=~ \rho_s ~ \delta(\omega_i-\omega_r) ~/~ (n \cdot \omega_i)&#xD;&#xA;$$&#xD;&#xA;This is especially useful for making metallic mirrors, which need complex-valued (and therefore finicky and advanced) IORs to work.  It's also useful because RGB rendering is unfortunately more popular than is spectral rendering.&#xD;&#xA;&#xD;&#xA;We will see how this works out in a calculation below.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Integrating Infinity, Functions, and Measures&#xD;&#xA;&#xD;&#xA;&gt; Furthermore from mathematical standpoint of view you cannot integrate infinite valued function, even if you could than the only sensible answers would be zero or infinity.&#xD;&#xA;&#xD;&#xA;We have to be careful and precise here.  If you mean &quot;a function whose values *diverge to* infinity&quot;, then we definitely *can* integrate it using the usual tools.  (Formally; this is just an &quot;improper Riemann integral of the second kind&quot;.  For example, $\int_0^1 x^{-1/2} d x = 2$, which you can [see plotted and solved](https://www.wolframalpha.com/input?i=integrate+1%2Fsqrt%28x%29+from+0+to+1) or [read a very short proof of](https://en.wikipedia.org/wiki/Improper_integral#Examples).)&#xD;&#xA;&#xD;&#xA;The Dirac delta function is a *generalized* function (which is why some people describe it variously as a distribution, a linear functional, or (incorrectly) not-a-function).  In particular, it [is not Lebesgue-integrable](https://en.wikipedia.org/wiki/Lebesgue_integration#Basic_theorems_of_the_Lebesgue_integral) (because $\delta(x) = 0$ almost everywhere, yet $\int \delta(x)~dx = 1 \neq 0 = \int 0~dx$).&#xD;&#xA;&#xD;&#xA;For the delta function, the informal definition is a sequence of functions that diverge to an infinite value, but that are each individually everywhere-finite.  For example, as a series of Gaussians:&#xD;&#xA;$$&#xD;&#xA;    \delta(x) := \lim_{b \rightarrow 0} ~ \frac{1}{|b|\sqrt{\pi}} ~ e^{-(x/b)^2}&#xD;&#xA;$$&#xD;&#xA;That's probably what you're used to thinking of, but for full formality, we need to drop this idea and instead [define it through measure theory](https://en.wikipedia.org/wiki/Dirac_measure).  The following is the Dirac measure concentrated at $\omega_r$, which you can think of as &quot;checking&quot; that the perfect reflection direction $\omega_r$ is in the set $A$, a measurable subset of the unit ball $B^3 \subset \mathbb{R}^3$:&#xD;&#xA;$$&#xD;&#xA;    \delta_{\omega_r}(A) := 1_A(\omega_r) = \begin{cases}&#xD;&#xA;        0 &amp; \text{if } \omega_r \notin A \\&#xD;&#xA;        1 &amp; \text{if } \omega_r \in A&#xD;&#xA;    \end{cases}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## A Lemma About the Dirac Delta&#xD;&#xA;&#xD;&#xA;We can develop an important property from this from [a certain property of](https://en.wikipedia.org/wiki/Lebesgue_integration#Via_improper_Riemann_integral) Lebesgue integration.  Let $L(x,\omega_i)$ be the usual radiance-at-$x$-in-direction-$\omega_i$ function from the rendering equation (treated as a scalar for your sanity) and define:&#xD;&#xA;$$&#xD;&#xA;    M(t) := \delta_{\omega_r}(\{~ \omega_i \in B^3 ~|~ L(x,\omega_i)&gt;t ~\})&#xD;&#xA;$$&#xD;&#xA;The Lebesgue integral can be re-defined in terms of the improper Riemann integral:&#xD;&#xA;$$&#xD;&#xA;    \int_{B^3} L ~ d\delta_{\omega_r} := \int_0^\infty M(t) ~ dt&#xD;&#xA;$$&#xD;&#xA;Let's look at $M(t)$ a bit more closely.  The set we pass in is the set of all directions with radiance at least $t$.  The Dirac delta &quot;checks&quot; for the presence of the $\omega_r$ direction, so that's the only one that matters.  Specifically, if the radiance from $\omega_r$ is at least $L(x,\omega_r)&gt;t$, then $\omega_r$ is in the set we pass in and the measure outputs $M(t)=1$.  However, if $L(x,\omega_r)\leq t$, then $\omega_r$ is not in the set we pass in, and so $M(t)=0$:&#xD;&#xA;$$&#xD;&#xA;    M(t) = \begin{cases}&#xD;&#xA;        0 &amp; \text{if } L(x,\omega_r) \leq t \\&#xD;&#xA;        1 &amp; \text{if } L(x,\omega_r) &gt; t&#xD;&#xA;    \end{cases}&#xD;&#xA;$$&#xD;&#xA;The above integrand on the right-hand-side is $1$ exactly for $0&lt;t&lt;L(x,\omega_r)$ and $0$ above that.  The integral therefore has value $L(x,\omega_r)$, giving us the following property of the Dirac delta:&#xD;&#xA;$$&#xD;&#xA;    \int_{B^3} L ~ d\delta_{\omega_r} = L(x,\omega_r)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Rendering Equation with a Specular BRDF&#xD;&#xA;&#xD;&#xA;Let's try to put the specular BRDF into the rendering equation, shall we?&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) = \int_\Omega L(x,\omega_i) ~ (n \cdot \omega_i) ~ f_r(\omega_i,x,\omega_o) ~ d \omega_i&#xD;&#xA;$$&#xD;&#xA;Substituting the Dirac delta into the BRDF, and substituting the BRDF into the rendering equation, we get:&#xD;&#xA;\begin{align}&#xD;&#xA;    L(x,\omega_o) &amp;= \int_\Omega L(x,\omega_i) ~ (n \cdot \omega_i) ~&#xD;&#xA;        \rho_s ~ \delta(\omega_i-\omega_r) ~/~ (n \cdot \omega_i) ~&#xD;&#xA;        d \omega_i\\&#xD;&#xA;                  &amp;= \rho_s ~ \int_\Omega L(x,\omega_i) ~&#xD;&#xA;        \delta(\omega_i-\omega_r) ~&#xD;&#xA;        d \omega_i&#xD;&#xA;\end{align}&#xD;&#xA;We apply the lemma proved above to get:&#xD;&#xA;$$&#xD;&#xA;    L(x,\omega_o) = \rho_s ~ L(x,\omega_r)&#xD;&#xA;$$&#xD;&#xA;That is, the reflected radiance out is a simple constant color times the radiance in, which is what people expect from their mirrors.&#xD;&#xA;&#xD;&#xA;Note you should also special-case it and compute it this way.  Perhaps it's obvious, but I can say from experience that in particular leaving the geometry terms uncancelled can lead to nasty numerical issues.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;## Final Thoughts&#xD;&#xA;&#xD;&#xA;&gt; The question is: Is there any work which reformulates rendering equation, BSDF and radiance in such a way that it does not suffer from mentioned problems? [...] The main purpose of this question is to find out if someone else already did it, so I can read it and then focus my energy somewhere else.&#xD;&#xA;&#xD;&#xA;I'm not immediately aware of such a work, but at any rate if you've gotten this far, hopefully it is no longer necessary.  Most of this post was dedicated to explaining where the specular BRDF came from and formally grounding the Dirac delta function.&#xD;&#xA;&#xD;&#xA;Few people would care about these details because if you accept them on faith and just kindof gloss over the formal grounding, you can still prove what you want to prove (the rendering-equation section) and it Just Works.  Still, it's good to know it can be shown at a deeper level.  I hope this helps and apologize in advance for any mathematical typos." ContentLicense="CC BY-SA 4.0" />
  <row Id="42234" PostHistoryTypeId="2" PostId="13815" RevisionGUID="4c416d89-4745-44c9-aee2-02ce68c5e492" CreationDate="2023-11-19T07:55:01.280" UserId="20067" Text="I'm working on a a simple 3D scene in WebGL. The purpose is to:&#xD;&#xA;1. Implement an isometric viewing angle in orthographic 3D&#xD;&#xA;2. Translate between XY screen coordinates and XY world coordinates&#xD;&#xA;&#xD;&#xA;Codepen: https://codepen.io/Candleout/pen/RwvxOJy&#xD;&#xA;&#xD;&#xA;Sometimes when I load the page the scene appears blank. If this happens to you, simply refresh it and it should work.&#xD;&#xA;&#xD;&#xA;In the scene, X (red axis) represent East-West and Y (green axis) represents North-South. X increases to the East and Y increases to the North. Z (blue axis) represents the vertical axis and increases with elevation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Camera setup:&#xD;&#xA;``` &#xD;&#xA;cameraPosition = [x + 1, y - 1, 1]&#xD;&#xA;cameraTarget = [x, y, 0]&#xD;&#xA;up = [0, 0, 1]&#xD;&#xA;``` &#xD;&#xA;With this setup, the objects are correctly positioned (or so it appears) in three dimensions. But how do you convert between screen coords and world coords?&#xD;&#xA;&#xD;&#xA;Below is my current (failed) attempt to converting from screen space to world space. It includes the following steps:&#xD;&#xA;* Normalize the screen coordinates&#xD;&#xA;* Invert the view projection matrix&#xD;&#xA;* Apply the inverted matrix to the normalized screen coordinates&#xD;&#xA;&#xD;&#xA;With this code, only the coordinate in the center of the screen is turning out correct (500, -150). Everything else is skewed in some way. If you follow the y axis with the mouse, the x values will update as well, and vice versa.&#xD;&#xA;&#xD;&#xA;If anyone can tell me why this is happening and what I should be doing instead it would be very much appreciated.&#xD;&#xA;&#xD;&#xA;The world coordinates are visible in the bottom left corner of the Codepen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;``` &#xD;&#xA;function screenToWorld(screenCoords, viewProjectionMatrix, screenWidth, screenHeight) {&#xD;&#xA;  // Convert screen coords into clip coords&#xD;&#xA;  const ndcX = (screenCoords[0] / screenWidth) * 2 - 1;&#xD;&#xA;  const ndcY = 1 - (screenCoords[1] / screenHeight) * 2;&#xD;&#xA;  let clipCoords = [ndcX, ndcY, 0, 1];&#xD;&#xA;&#xD;&#xA;  // Invert view projection matrix&#xD;&#xA;  const inverseViewProjectionMatrix = m4.inverse(viewProjectionMatrix);&#xD;&#xA;&#xD;&#xA;  // Apply inverted matrix to normalized screen coords&#xD;&#xA;  let worldCoords = m4.transformMat4([], clipCoords, inverseViewProjectionMatrix);&#xD;&#xA;&#xD;&#xA;  return worldCoords.slice(0, 3);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function inverse(m) {&#xD;&#xA;    let m00 = m[0 * 4 + 0];&#xD;&#xA;    let m01 = m[0 * 4 + 1];&#xD;&#xA;    let m02 = m[0 * 4 + 2];&#xD;&#xA;    let m03 = m[0 * 4 + 3];&#xD;&#xA;    let m10 = m[1 * 4 + 0];&#xD;&#xA;    let m11 = m[1 * 4 + 1];&#xD;&#xA;    let m12 = m[1 * 4 + 2];&#xD;&#xA;    let m13 = m[1 * 4 + 3];&#xD;&#xA;    let m20 = m[2 * 4 + 0];&#xD;&#xA;    let m21 = m[2 * 4 + 1];&#xD;&#xA;    let m22 = m[2 * 4 + 2];&#xD;&#xA;    let m23 = m[2 * 4 + 3];&#xD;&#xA;    let m30 = m[3 * 4 + 0];&#xD;&#xA;    let m31 = m[3 * 4 + 1];&#xD;&#xA;    let m32 = m[3 * 4 + 2];&#xD;&#xA;    let m33 = m[3 * 4 + 3];&#xD;&#xA;    let tmp_0  = m22 * m33;&#xD;&#xA;    let tmp_1  = m32 * m23;&#xD;&#xA;    let tmp_2  = m12 * m33;&#xD;&#xA;    let tmp_3  = m32 * m13;&#xD;&#xA;    let tmp_4  = m12 * m23;&#xD;&#xA;    let tmp_5  = m22 * m13;&#xD;&#xA;    let tmp_6  = m02 * m33;&#xD;&#xA;    let tmp_7  = m32 * m03;&#xD;&#xA;    let tmp_8  = m02 * m23;&#xD;&#xA;    let tmp_9  = m22 * m03;&#xD;&#xA;    let tmp_10 = m02 * m13;&#xD;&#xA;    let tmp_11 = m12 * m03;&#xD;&#xA;    let tmp_12 = m20 * m31;&#xD;&#xA;    let tmp_13 = m30 * m21;&#xD;&#xA;    let tmp_14 = m10 * m31;&#xD;&#xA;    let tmp_15 = m30 * m11;&#xD;&#xA;    let tmp_16 = m10 * m21;&#xD;&#xA;    let tmp_17 = m20 * m11;&#xD;&#xA;    let tmp_18 = m00 * m31;&#xD;&#xA;    let tmp_19 = m30 * m01;&#xD;&#xA;    let tmp_20 = m00 * m21;&#xD;&#xA;    let tmp_21 = m20 * m01;&#xD;&#xA;    let tmp_22 = m00 * m11;&#xD;&#xA;    let tmp_23 = m10 * m01;&#xD;&#xA;&#xD;&#xA;    let t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -&#xD;&#xA;             (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);&#xD;&#xA;    let t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -&#xD;&#xA;             (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);&#xD;&#xA;    let t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -&#xD;&#xA;             (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);&#xD;&#xA;    let t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -&#xD;&#xA;             (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);&#xD;&#xA;&#xD;&#xA;    let d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);&#xD;&#xA;&#xD;&#xA;    return [&#xD;&#xA;      d * t0,&#xD;&#xA;      d * t1,&#xD;&#xA;      d * t2,&#xD;&#xA;      d * t3,&#xD;&#xA;      d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -&#xD;&#xA;           (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),&#xD;&#xA;      d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -&#xD;&#xA;           (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),&#xD;&#xA;      d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -&#xD;&#xA;           (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),&#xD;&#xA;      d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -&#xD;&#xA;           (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),&#xD;&#xA;      d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -&#xD;&#xA;           (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),&#xD;&#xA;      d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -&#xD;&#xA;           (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),&#xD;&#xA;      d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -&#xD;&#xA;           (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),&#xD;&#xA;      d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -&#xD;&#xA;           (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),&#xD;&#xA;      d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -&#xD;&#xA;           (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),&#xD;&#xA;      d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -&#xD;&#xA;           (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),&#xD;&#xA;      d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -&#xD;&#xA;           (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),&#xD;&#xA;      d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -&#xD;&#xA;           (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)),&#xD;&#xA;    ];&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;function transformMat4(out, vec, mat) {&#xD;&#xA;    const x = vec[0];&#xD;&#xA;    const y = vec[1];&#xD;&#xA;    const z = vec[2] || 0;&#xD;&#xA;    const w = vec[3] || 1;&#xD;&#xA;  &#xD;&#xA;    out[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w;&#xD;&#xA;    out[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w;&#xD;&#xA;    out[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w;&#xD;&#xA;    out[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w;&#xD;&#xA;  &#xD;&#xA;    if (out[3] !== 0) {&#xD;&#xA;      out[0] /= out[3];&#xD;&#xA;      out[1] /= out[3];&#xD;&#xA;      out[2] /= out[3];&#xD;&#xA;      out[3] /= out[3];&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    return out;&#xD;&#xA;  }&#xD;&#xA;``` &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/50hDq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42236" PostHistoryTypeId="1" PostId="13815" RevisionGUID="4c416d89-4745-44c9-aee2-02ce68c5e492" CreationDate="2023-11-19T07:55:01.280" UserId="20067" Text="Convert between screen and world coordinates in isometric 3D" ContentLicense="CC BY-SA 4.0" />
  <row Id="42237" PostHistoryTypeId="3" PostId="13815" RevisionGUID="4c416d89-4745-44c9-aee2-02ce68c5e492" CreationDate="2023-11-19T07:55:01.280" UserId="20067" Text="|webgl|camera|javascript|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42238" PostHistoryTypeId="50" PostId="13766" RevisionGUID="16a11e47-5e95-4465-9f0b-2378b29884da" CreationDate="2023-11-19T11:01:35.217" UserId="-1" />
  <row Id="42239" PostHistoryTypeId="5" PostId="13815" RevisionGUID="1d2eb965-5829-44dd-8ff0-c73578aa6c02" CreationDate="2023-11-19T13:05:26.540" UserId="20067" Comment="added 121 characters in body" Text="I'm working on a a simple 3D scene in WebGL. The purpose is to:&#xD;&#xA;1. Implement an isometric viewing angle in orthographic 3D&#xD;&#xA;2. Translate between XY screen coordinates and XY world coordinates&#xD;&#xA;&#xD;&#xA;Codepen: https://codepen.io/Candleout/pen/RwvxOJy&#xD;&#xA;&#xD;&#xA;Sometimes when I load the page the scene appears blank or is not rendered correctly. Not sure why this happens. If this happens to you, refresh the page and/or scene it and it should hopefully work (x = 500 and y = -150 at screen center).&#xD;&#xA;&#xD;&#xA;In the scene, X (red axis) represent East-West and Y (green axis) represents North-South. X increases to the East and Y increases to the North. Z (blue axis) represents the vertical axis and increases with elevation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Camera setup:&#xD;&#xA;``` &#xD;&#xA;cameraPosition = [x + 1, y - 1, 1]&#xD;&#xA;cameraTarget = [x, y, 0]&#xD;&#xA;up = [0, 0, 1]&#xD;&#xA;``` &#xD;&#xA;With this setup, the objects are correctly positioned (or so it appears) in three dimensions. But how do you convert between screen coords and world coords?&#xD;&#xA;&#xD;&#xA;Below is my current (failed) attempt to converting from screen space to world space. It includes the following steps:&#xD;&#xA;* Normalize the screen coordinates&#xD;&#xA;* Invert the view projection matrix&#xD;&#xA;* Apply the inverted matrix to the normalized screen coordinates&#xD;&#xA;&#xD;&#xA;With this code, only the coordinate in the center of the screen is turning out correct (500, -150). Everything else is skewed in some way. If you follow the y axis with the mouse, the x values will update as well, and vice versa.&#xD;&#xA;&#xD;&#xA;If anyone can tell me why this is happening and what I should be doing instead it would be very much appreciated.&#xD;&#xA;&#xD;&#xA;The world coordinates are visible in the bottom left corner of the Codepen.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;``` &#xD;&#xA;function screenToWorld(screenCoords, viewProjectionMatrix, screenWidth, screenHeight) {&#xD;&#xA;  // Convert screen coords into clip coords&#xD;&#xA;  const ndcX = (screenCoords[0] / screenWidth) * 2 - 1;&#xD;&#xA;  const ndcY = 1 - (screenCoords[1] / screenHeight) * 2;&#xD;&#xA;  let clipCoords = [ndcX, ndcY, 0, 1];&#xD;&#xA;&#xD;&#xA;  // Invert view projection matrix&#xD;&#xA;  const inverseViewProjectionMatrix = m4.inverse(viewProjectionMatrix);&#xD;&#xA;&#xD;&#xA;  // Apply inverted matrix to normalized screen coords&#xD;&#xA;  let worldCoords = m4.transformMat4([], clipCoords, inverseViewProjectionMatrix);&#xD;&#xA;&#xD;&#xA;  return worldCoords.slice(0, 3);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;function inverse(m) {&#xD;&#xA;    let m00 = m[0 * 4 + 0];&#xD;&#xA;    let m01 = m[0 * 4 + 1];&#xD;&#xA;    let m02 = m[0 * 4 + 2];&#xD;&#xA;    let m03 = m[0 * 4 + 3];&#xD;&#xA;    let m10 = m[1 * 4 + 0];&#xD;&#xA;    let m11 = m[1 * 4 + 1];&#xD;&#xA;    let m12 = m[1 * 4 + 2];&#xD;&#xA;    let m13 = m[1 * 4 + 3];&#xD;&#xA;    let m20 = m[2 * 4 + 0];&#xD;&#xA;    let m21 = m[2 * 4 + 1];&#xD;&#xA;    let m22 = m[2 * 4 + 2];&#xD;&#xA;    let m23 = m[2 * 4 + 3];&#xD;&#xA;    let m30 = m[3 * 4 + 0];&#xD;&#xA;    let m31 = m[3 * 4 + 1];&#xD;&#xA;    let m32 = m[3 * 4 + 2];&#xD;&#xA;    let m33 = m[3 * 4 + 3];&#xD;&#xA;    let tmp_0  = m22 * m33;&#xD;&#xA;    let tmp_1  = m32 * m23;&#xD;&#xA;    let tmp_2  = m12 * m33;&#xD;&#xA;    let tmp_3  = m32 * m13;&#xD;&#xA;    let tmp_4  = m12 * m23;&#xD;&#xA;    let tmp_5  = m22 * m13;&#xD;&#xA;    let tmp_6  = m02 * m33;&#xD;&#xA;    let tmp_7  = m32 * m03;&#xD;&#xA;    let tmp_8  = m02 * m23;&#xD;&#xA;    let tmp_9  = m22 * m03;&#xD;&#xA;    let tmp_10 = m02 * m13;&#xD;&#xA;    let tmp_11 = m12 * m03;&#xD;&#xA;    let tmp_12 = m20 * m31;&#xD;&#xA;    let tmp_13 = m30 * m21;&#xD;&#xA;    let tmp_14 = m10 * m31;&#xD;&#xA;    let tmp_15 = m30 * m11;&#xD;&#xA;    let tmp_16 = m10 * m21;&#xD;&#xA;    let tmp_17 = m20 * m11;&#xD;&#xA;    let tmp_18 = m00 * m31;&#xD;&#xA;    let tmp_19 = m30 * m01;&#xD;&#xA;    let tmp_20 = m00 * m21;&#xD;&#xA;    let tmp_21 = m20 * m01;&#xD;&#xA;    let tmp_22 = m00 * m11;&#xD;&#xA;    let tmp_23 = m10 * m01;&#xD;&#xA;&#xD;&#xA;    let t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -&#xD;&#xA;             (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);&#xD;&#xA;    let t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -&#xD;&#xA;             (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);&#xD;&#xA;    let t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -&#xD;&#xA;             (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);&#xD;&#xA;    let t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -&#xD;&#xA;             (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);&#xD;&#xA;&#xD;&#xA;    let d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);&#xD;&#xA;&#xD;&#xA;    return [&#xD;&#xA;      d * t0,&#xD;&#xA;      d * t1,&#xD;&#xA;      d * t2,&#xD;&#xA;      d * t3,&#xD;&#xA;      d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -&#xD;&#xA;           (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),&#xD;&#xA;      d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -&#xD;&#xA;           (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),&#xD;&#xA;      d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -&#xD;&#xA;           (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),&#xD;&#xA;      d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -&#xD;&#xA;           (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),&#xD;&#xA;      d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -&#xD;&#xA;           (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),&#xD;&#xA;      d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -&#xD;&#xA;           (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),&#xD;&#xA;      d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -&#xD;&#xA;           (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),&#xD;&#xA;      d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -&#xD;&#xA;           (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),&#xD;&#xA;      d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -&#xD;&#xA;           (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),&#xD;&#xA;      d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -&#xD;&#xA;           (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),&#xD;&#xA;      d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -&#xD;&#xA;           (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),&#xD;&#xA;      d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -&#xD;&#xA;           (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)),&#xD;&#xA;    ];&#xD;&#xA;  }&#xD;&#xA;&#xD;&#xA;function transformMat4(out, vec, mat) {&#xD;&#xA;    const x = vec[0];&#xD;&#xA;    const y = vec[1];&#xD;&#xA;    const z = vec[2] || 0;&#xD;&#xA;    const w = vec[3] || 1;&#xD;&#xA;  &#xD;&#xA;    out[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w;&#xD;&#xA;    out[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w;&#xD;&#xA;    out[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w;&#xD;&#xA;    out[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w;&#xD;&#xA;  &#xD;&#xA;    if (out[3] !== 0) {&#xD;&#xA;      out[0] /= out[3];&#xD;&#xA;      out[1] /= out[3];&#xD;&#xA;      out[2] /= out[3];&#xD;&#xA;      out[3] /= out[3];&#xD;&#xA;    }&#xD;&#xA;  &#xD;&#xA;    return out;&#xD;&#xA;  }&#xD;&#xA;``` &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/50hDq.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42240" PostHistoryTypeId="50" PostId="13302" RevisionGUID="97962999-9ffd-43a8-9d31-af5c35298a52" CreationDate="2023-11-19T20:01:35.260" UserId="-1" />
  <row Id="42241" PostHistoryTypeId="2" PostId="13816" RevisionGUID="38947551-91a1-4dfd-ac29-e07209400c6f" CreationDate="2023-11-20T08:59:52.433" UserId="13273" Text="Since the screen coordinates are 2D, while the world coordinates are 3D, the problem arises that you still have one degree of freedom open.&#xD;&#xA;A pixel on the screen therefore represents a line in world coordinates. Each position on this line is mapped exactly to the pixel on the screen.&#xD;&#xA;For this reason, we need to define a plane where the line intersects. The intersection point then only needs to be calculated.&#xD;&#xA;&#xD;&#xA;First we define the plane in world space. To do this, we need the plane normal and a point within the plane:&#xD;&#xA;&#xD;&#xA;    planeNormal = vec3(0, 0, 1);&#xD;&#xA;    planePoint = vec3(0, 0, 0);&#xD;&#xA;&#xD;&#xA;To define the line, we can then simply use the same screen coordinates with two different z values.&#xD;&#xA;&#xD;&#xA;    vec2 screenCoordinate = vec2(someXValue, someYValue); // normalized screen coordinates [-1, 1]&#xD;&#xA;    vec4 linePoint0ScreenSpace = vec4(screenCoordinate.x, screenCoordinate.y, 0.0f, 1.0f); //Note: the z-value is set to 0&#xD;&#xA;    vec4 linePoint1ScreenSpace = vec4(screenCoordinate.x, screenCoordinate.y, 1.0f, 1.0f); //Note: the z-value is set to 1&#xD;&#xA;&#xD;&#xA;we use 4D points because the view and the projection matrix are 4x4 matrices. &#xD;&#xA;&#xD;&#xA;Now we convert both points into world space by multiplying the inverse matrix of viewProjection with the two 4D points.&#xD;&#xA;&#xD;&#xA;    mat4 vpInverse = inverse(viewProjectionMatrix);&#xD;&#xA;    vec4 linePoint0WorldSpace = vpInverse * linePoint0ScreenSpace;&#xD;&#xA;    vec4 linePoint1WorldSpace = vpInverse * linePoint1ScreenSpace;&#xD;&#xA;&#xD;&#xA;The following step is only required if your projection is not linear, e.g. for perspective projections. Otherwise, this step is not required:&#xD;&#xA;&#xD;&#xA;    linePoint0WorldSpace /= linePoint0WorldSpace.w;&#xD;&#xA;    linePoint1WorldSpace /= linePoint1WorldSpace.w;&#xD;&#xA;&#xD;&#xA;Okay, what do we have now?&#xD;&#xA;&#xD;&#xA;We have two points in world space that are mapped to exactly the same pixel in screen space. These two points define a line in world space. &#xD;&#xA;&#xD;&#xA;Using this line and the defined plane at the top of this answer, we can calculate the intersection point using the following method:&#xD;&#xA;&#xD;&#xA;    vec3 intersectionRayPlane(vec3 rayDirection, vec3 rayPoint, vec3 planeNormal, vec3 planePoint)&#xD;&#xA;    {&#xD;&#xA;        return rayPoint - rayDirection * dot(rayPoint - planePoint, planeNormal) / dot(rayDirection, planeNormal);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;So let's put our line in the right format and use the intersection method to calculate the 3D position in world space:&#xD;&#xA;&#xD;&#xA;    vec3 rayDirection = linePoint1WorldSpace.xyz - linePoint0WorldSpace.xyz;&#xD;&#xA;    vec3 rayPoint = linePoint1WorldSpace.xyz;&#xD;&#xA;&#xD;&#xA;    vec3 positionWorldSpace = intersectionRayPlane(rayDirection, rayPoint, planeNormal, planePoint);&#xD;&#xA;&#xD;&#xA;The result is in `positionWorldSpace`.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42243" PostHistoryTypeId="2" PostId="13817" RevisionGUID="52dcac65-1fc3-425f-a94d-f3c455538f6d" CreationDate="2023-11-20T23:31:24.117" UserId="10096" Text="**The Rendering Equation**&#xD;&#xA;&#xD;&#xA;First thing first, the rendering equation in its solid angle formulation in vacuum is:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{S^2} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta_x| d\sigma(\omega).$$&#xD;&#xA;You forgot the emission function $L_e$ in your question.  The solution $L:M\times S^2 \to \mathbb{R}$ (where $S^2=\{p\in\mathbb{R}^3\,:\, \|p\|_2=1\}$ is just the 2-sphere) is fully determined by the collection $(M, n, f, L_e)$, where $M\subset \mathbb{R}^3$ is the set of points forming the scene surfaces, $n:M\to S^2$ is the function that assigns a normal to every point of $M$, $f:M\times S^2 \times S^2 \to \mathbb{R}_+$ is the BSDF (it represents the light scattering properties of the materials of your surfaces), and $L_e:M\times S^2 \to \mathbb{R}_+$ is the emitted radiance function (it is non-zero on your light sources). It is fairly natural that your geometry $(M,n$), the materials $f$, and the light sources $L_e$ will determine the steady state of the radiance $L$ in the scene.&#xD;&#xA;&#xD;&#xA;The function $r:M\times S^2 \to M\cup (\infty\cdot S^2)$ is the ray-tracing function that returns the first intersection point $r(x,\omega)$ along the ray with origin $x$ and direction $\omega$, if there is no intersection you can formally claim that it returns the intersection with some sphere at infinity (e.g. your environment map). Typically the rendering equation is formulated in terms of the incident radiance $L_i(x, \omega)$, however, in vacuum we have $L_i(x,\omega) = (GL)(x,\omega) = L(r(x,\omega),-\omega)$ - the radiance that arrives at $x$ from direction $\omega$ is equal to the radiance leaving $r(x,\omega)$ in direction $-\omega$, which is also fairly intuitive. The term $|\cos\theta_x| = |n(x)\cdot \omega|$ is due to Lambert's cosine law, but it can be derived also by just integrating a differential $2$-density on the sphere (think surface flux integrals from calculus 3). The $d\sigma(\omega)$ is the area measure on the sphere, i.e. if you take the standard spherical coordinates parametrization $x = \sin\theta\cos\phi$, $y=\sin\theta\sin\phi$, $z=\cos\theta$ and your rotate them so that $z$ is aligned with $n(x)$, then you may rewrite $d\sigma(\omega) = |\sin\theta| d\theta d\phi$ and thus:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{0}^{2\pi}\int_0^{\pi} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta| |\sin\theta|d\theta d\phi.$$&#xD;&#xA;&#xD;&#xA;**Formal Solution**&#xD;&#xA;&#xD;&#xA;For brevity one typically writes the above in operator form $L = L_e +TL$ where $T:(M\times S^2\to \mathbb{R})\to (M\times S^2\to \mathbb{R})$ is the operator that stands for the integral. If we define the scattering operator $K$ and the propagation operator $G$:&#xD;&#xA;$$(Kg)(x,\omega) = \int_{S^2}f(x,\omega,\omega_o)g(x,\omega)d\sigma_{x}^{\perp}(\omega), \quad (Gh)(x,\omega) = h(r(x,\omega),-\omega),$$&#xD;&#xA;then $T=K\circ G$.&#xD;&#xA; Since we have the identity $L=L_e+TL$ we can just plug it in itself once yielding $L=L_e + T(L_e + TL) = L_e+TL_e+T^2L$. Repeating this process until infinity yields the series $L = \sum_{k=0}^{\infty}T^kL_e$. Formally $\sum_{k=0}^{\infty}T^k$ is the solution operator for the rendering equation:&#xD;&#xA;\begin{align}&#xD;&#xA;L = L_e +TL \implies (I-T)L = L_e \implies L = (I-T)^{-1}L_e \implies (I-T)^{-1} = \sum_{k=0}^{\infty}T^k.&#xD;&#xA;\end{align}&#xD;&#xA;The latter is the Neumann series for $T$. While $\|T\|&lt;1$ is a sufficient condition for convergence (i.e. if the brdf is energy conserving), it is not a necessary condition - for specific choices of $L_e$ the above series may be convergent even if $(I-T)^{-1}$ is unbounded. Note that $f,L,L_e$ are actual functions (i.e. $T$ maps functions to functions). In practice one may want to model specular reflection, point and directional lights etc., which according to &quot;many treatments&quot; cannot be modeled with classical functions and require distribution. Veach discusses this in his thesis (e.g. in some appendices on specular reflection and refraction), and even has a nice table 8.3 showing some examples.&#xD;&#xA;&#xD;&#xA;**Veach's Extension to Distributions**&#xD;&#xA;&#xD;&#xA;If you go to 5.A.1, Veach has a short note that $\int_{\mathbb{R}} f(x)\delta(x-x_0)\,dx$ is just symbolic notation for the evaluation functional $\Lambda_{x_0}(f) = f(x_0)$. This symbolic expression could also be framed as $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx := \int_{\mathbb{R}} f(x)\,d\delta_{x_0}(x)$ where $\delta_{x_0}$ is the Dirac measure. Note however that $\delta$ is not the Radon-Nikodym derivative of this measure, i.e. the expression $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx$ is still purely symbolic if not abuse of notation. When you write $$\int_{S^2} f(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega) = \int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega),$$&#xD;&#xA;the second expression is purely symbolic and means&#xD;&#xA;\begin{align}&#xD;&#xA;\int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega)&amp;:= \int_{S^2} \rho(x,\omega,\omega_o)L_i(x,\omega)\,d\delta_{\omega_r}(\omega) \\&#xD;&#xA;= \Lambda_{\omega_r}(\rho(x,\cdot,\omega_o)L_i(x,\cdot)) &amp;= \rho(x,\omega_r,\omega_o) L_i(x,\omega_r).&#xD;&#xA;\end{align}&#xD;&#xA;The linear operator $\Lambda_{\omega_r}$ is not the BSDF itself, it is the operator $T$ when restricted to this specific specular vertex $x$, thus the BSDF cannot be a distribution even though Veach abuses notation (as is often done elsewhere) and calls it a distribution. What's really going on at a specular vertex $p$ is that the definition of $K$ at point $p$ is modified to $$(Kg)(p,\omega_o) = \int_{S^2}\rho(p,\omega,\omega_o)g(p,\omega)\,d\delta_{\omega_r}(\omega) = \rho(p,\omega_r,\omega_o)g(p,\omega_r).$$&#xD;&#xA;Formally you could pretend that:&#xD;&#xA;$$f(x,\omega,\omega_r) = \rho(x,\omega,\omega_o)\frac{d\delta_{\omega_r}(\omega)}{d\sigma_x^{\perp}(\omega)} =\rho(x,\omega,\omega_o)\delta_{\sigma_x^{\perp}}(\omega-\omega_r).$$&#xD;&#xA;The only issue is that the function/Radon-Nikodym derivative doesn't exist because the Dirac measure $\delta_{\omega_r}$ is not absolutely continuous, but the notation is convenient enough that everyone abuses it.&#xD;&#xA;&#xD;&#xA;**Extension to Dirac Delta Light Sources**&#xD;&#xA;&#xD;&#xA;As we saw above the whole &quot;distribution&quot; business is tantamount to modifying your scattering operator at specific points. There are many ways to achieve this - you could tie the measure to your bsdf, then a specular vertex you would have a &quot;differential bsdf-measure&quot; $fd\delta$ while at a normal vertex it would be $fd\sigma_{x}^{\perp}$. The other way is of course to abuse notation and pretend that $\delta$ is the Radon-Nikodym derivative. The most theoretically sound, but least intuitive way, is to probably not touch the bsdf and just modify the scattering operator. Until this point we were lucky that we had an operator which to convert to our functional. It may not be readily obvious what should be done if we want a point or directional light source however. &#xD;&#xA;&#xD;&#xA;As an example consider just the $0$-th term $L_e$ of the Neumann expansion with only a directional light source. To get the contribution from zero bounces away we integrate $L_e$ directly on the film. For a specific pixel  on the film we may assume that the contribution is computed as $$\int_{A}\left(\int_{S^2}W_e(x,\omega)L_e(r(x,\omega),-\omega)\,d\sigma_{x}^{\perp}(\omega)\right)\,dx.$$&#xD;&#xA;Here $A$ is the film area and $W_e$ is the sensitivity function. The aperture is implicitly taken into account by the ray-tracing function. But for simplicity assume there is no aperture, there are now two options: you either treat $L_e$ as an actual Dirac delta $L_e(y,\omega) = e(y,\omega)\delta(\omega-\omega_d)$ in which case you modify the integral to:&#xD;&#xA;$$\int_{A}\left(\int_{S^2}W_e(x,\omega)e(r(x,\omega),-\omega)|n(x)\cdot\omega|\,d\delta_{-\omega_d}(\omega)\right)\,dx =\\= \int_{A}W_e(x,-\omega_d)e(r(x,-\omega_d),\omega_d)|n(x)\cdot\omega_d|\,dx.$$&#xD;&#xA;You could however also require that $W_e$ is a Dirac delta, e.g. both w.r.t. position and direction. Once you do this the result will be a Dirac delta if you work with the abuse of notation approach (you will have one extra left over). This is not necessarily entirely wrong, if you assume that you really want a Dirac delta to mean that it carries infinite energy. As an example, if your sensor has both a positional (on the film) and directional Dirac delta, it would return the radiance of a normal light source when an importance ray hits it. However if that light source has a directional Dirac delta aligning with the one from the sensor, it is not that far fetched to say that you get an infinite contribution - and such an infinity that when integrated against a kernel would spit out the value at the kernel's specific location.&#xD;&#xA;&#xD;&#xA;However, as far as I am aware we do not do this in computer graphics, e.g. when we have a point light source, directional light source, or even a laser, shining into the camera/film is not reproduced in the ray-tracers I am aware of. This means that they opted for treating this in a different way than the abuse of notation would suggest. E.g. if they have a specular light and then diffuse they treat it like a Dirac delta, however if they have a specular light and then a specular surface they do not use two Dirac deltas, instead they produce at most one Dirac delta, and that is only if the arguments of the two supposed Dirac deltas agree, so in this case $\int g(\omega)\delta(\omega-\omega_1)\delta(\omega-\omega_2)\,d\omega = g(\omega_1)\delta_{\omega_1=\omega_2} \ne g(\omega_1)\delta(\omega_1-\omega_2)$, note that in the middle expression the delta is a Kronecker delta and not a Dirac delta. The middle expression is consistent with how you do not visualize point/directional light sources on the film. &#xD;&#xA;&#xD;&#xA;**Conclusion** &#xD;&#xA;&#xD;&#xA;Ultimately how you decide to treat it is up to you, probably the most consistent way is using the abuse of notation, because then you can actually have multibounce specular contributions from a Dirac light source (e.g. &quot;directional light&quot; seen in a mirror), and it's also consistent as a limiting case of decreasing the solid angle emission of some light source and increasing its power - in the limit you get the directional Dirac delta, but the limiting emissions do not magically stop working after one bounce, so it's probably consistent to keep that for a Dirac delta light also. I think the main reason the Dirac delta nature of the light is not visualized on the film is because it is typically used as a cheap approximation of an actual light source, but the face that it has infinite energy at a point would probably be perceived as an artefact on the film." ContentLicense="CC BY-SA 4.0" />
  <row Id="42245" PostHistoryTypeId="5" PostId="13817" RevisionGUID="d71c51cc-46ad-4cfd-8fa0-04967d672b87" CreationDate="2023-11-20T23:38:11.830" UserId="10096" Comment="added 2 characters in body" Text="**The Rendering Equation**&#xD;&#xA;&#xD;&#xA;First thing first, the rendering equation in its solid angle formulation in vacuum is:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{S^2} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta_x| d\sigma(\omega).$$&#xD;&#xA;You forgot the emission function $L_e$ in your question.  The solution $L:M\times S^2 \to \mathbb{R}$ (where $S^2=\{p\in\mathbb{R}^3\,:\, \|p\|_2=1\}$ is just the 2-sphere) is fully determined by the collection $(M, n, f, L_e)$, where $M\subset \mathbb{R}^3$ is the set of points forming the scene surfaces, $n:M\to S^2$ is the function that assigns a normal to every point of $M$, $f:M\times S^2 \times S^2 \to \mathbb{R}_+$ is the BSDF (it represents the light scattering properties of the materials of your surfaces), and $L_e:M\times S^2 \to \mathbb{R}_+$ is the emitted radiance function (it is non-zero on your light sources). It is fairly natural that your geometry $(M,n$), the materials $f$, and the light sources $L_e$ will determine the steady state of the radiance $L$ in the scene.&#xD;&#xA;&#xD;&#xA;The function $r:M\times S^2 \to M\cup (\infty\cdot S^2)$ is the ray-tracing function that returns the first intersection point $r(x,\omega)$ along the ray with origin $x$ and direction $\omega$, if there is no intersection you can formally claim that it returns the intersection with some sphere at infinity (e.g. your environment map). Typically the rendering equation is formulated in terms of the incident radiance $L_i(x, \omega)$, however, in vacuum we have $L_i(x,\omega) = (GL)(x,\omega) = L(r(x,\omega),-\omega)$ - the radiance that arrives at $x$ from direction $\omega$ is equal to the radiance leaving $r(x,\omega)$ in direction $-\omega$, which is also fairly intuitive. The term $|\cos\theta_x| = |n(x)\cdot \omega|$ is due to Lambert's cosine law, but it can be derived also by just integrating a differential $2$-density on the sphere (think surface flux integrals from calculus 3). The $d\sigma(\omega)$ is the area measure on the sphere, i.e. if you take the standard spherical coordinates parametrization $x = \sin\theta\cos\phi$, $y=\sin\theta\sin\phi$, $z=\cos\theta$ and your rotate them so that $z$ is aligned with $n(x)$, then you may rewrite $d\sigma(\omega) = |\sin\theta| d\theta d\phi$ and thus:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{0}^{2\pi}\int_0^{\pi} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta| |\sin\theta|d\theta d\phi.$$&#xD;&#xA;&#xD;&#xA;**Formal Solution**&#xD;&#xA;&#xD;&#xA;For brevity one typically writes the above in operator form $L = L_e +TL$ where $T:(M\times S^2\to \mathbb{R})\to (M\times S^2\to \mathbb{R})$ is the operator that stands for the integral. If we define the scattering operator $K$ and the propagation operator $G$:&#xD;&#xA;$$(Kg)(x,\omega) = \int_{S^2}f(x,\omega,\omega_o)g(x,\omega)d\sigma_{x}^{\perp}(\omega), \quad (Gh)(x,\omega) = h(r(x,\omega),-\omega),$$&#xD;&#xA;then $T=K\circ G$.&#xD;&#xA; Since we have the identity $L=L_e+TL$ we can just plug it in itself once yielding $L=L_e + T(L_e + TL) = L_e+TL_e+T^2L$. Repeating this process until infinity yields the series $L = \sum_{k=0}^{\infty}T^kL_e$. Formally $\sum_{k=0}^{\infty}T^k$ is the solution operator for the rendering equation:&#xD;&#xA;\begin{align}&#xD;&#xA;L = L_e +TL \implies (I-T)L = L_e \implies L = (I-T)^{-1}L_e \implies (I-T)^{-1} = \sum_{k=0}^{\infty}T^k.&#xD;&#xA;\end{align}&#xD;&#xA;The latter is the Neumann series for $T$. While $\|T\|&lt;1$ is a sufficient condition for convergence (i.e. if the brdf is energy conserving), it is not a necessary condition - for specific choices of $L_e$ the above series may be convergent even if $(I-T)^{-1}$ is unbounded. Note that $f,L,L_e$ are actual functions (i.e. $T$ maps functions to functions). In practice one may want to model specular reflection, point and directional lights etc., which according to &quot;many treatments&quot; cannot be modeled with classical functions and require distribution. Veach discusses this in his thesis (e.g. in some appendices on specular reflection and refraction), and even has a nice table 8.3 showing some examples.&#xD;&#xA;&#xD;&#xA;**Veach's Extension to Distributions**&#xD;&#xA;&#xD;&#xA;If you go to 5.A.1, Veach has a short note that $\int_{\mathbb{R}} f(x)\delta(x-x_0)\,dx$ is just symbolic notation for the evaluation functional $\Lambda_{x_0}(f) = f(x_0)$. This symbolic expression could also be framed as $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx := \int_{\mathbb{R}} f(x)\,d\delta_{x_0}(x)$ where $\delta_{x_0}$ is the Dirac measure. Note however that $\delta$ is not the Radon-Nikodym derivative of this measure, i.e. the expression $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx$ is still purely symbolic if not abuse of notation. When you write $$\int_{S^2} f(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega) = \int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega),$$&#xD;&#xA;the second expression is purely symbolic and means&#xD;&#xA;\begin{align}&#xD;&#xA;\int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega)&amp;:= \int_{S^2} \rho(x,\omega,\omega_o)L_i(x,\omega)\,d\delta_{\omega_r}(\omega) \\&#xD;&#xA;= \Lambda_{\omega_r}(\rho(x,\cdot,\omega_o)L_i(x,\cdot)) &amp;= \rho(x,\omega_r,\omega_o) L_i(x,\omega_r).&#xD;&#xA;\end{align}&#xD;&#xA;The linear operator $\Lambda_{\omega_r}$ is not the BSDF itself, it is the operator $T$ when restricted to this specific specular vertex $x$, thus the BSDF cannot be a distribution even though Veach abuses notation (as is often done elsewhere) and calls it a distribution. What's really going on at a specular vertex $p$ is that the definition of $K$ at point $p$ is modified to $$(Kg)(p,\omega_o) = \int_{S^2}\rho(p,\omega,\omega_o)g(p,\omega)\,d\delta_{\omega_r}(\omega) = \rho(p,\omega_r,\omega_o)g(p,\omega_r).$$&#xD;&#xA;Formally you could pretend that:&#xD;&#xA;$$f(x,\omega,\omega_r) = \rho(x,\omega,\omega_o)\frac{d\delta_{\omega_r}(\omega)}{d\sigma_x^{\perp}(\omega)} =\rho(x,\omega,\omega_o)\delta_{\sigma_x^{\perp}}(\omega-\omega_r).$$&#xD;&#xA;The only issue is that the function/Radon-Nikodym derivative doesn't exist because the Dirac measure $\delta_{\omega_r}$ is not absolutely continuous, but the notation is convenient enough that everyone abuses it.&#xD;&#xA;&#xD;&#xA;**Extension to Dirac Delta Light Sources**&#xD;&#xA;&#xD;&#xA;As we saw above the whole &quot;distribution&quot; business is tantamount to modifying your scattering operator at specific points. There are many ways to achieve this - you could tie the measure to your bsdf, then a specular vertex you would have a &quot;differential bsdf-measure&quot; $fd\delta$ while at a normal vertex it would be $fd\sigma_{x}^{\perp}$. The other way is of course to abuse notation and pretend that $\delta$ is the Radon-Nikodym derivative. The most theoretically sound, but least intuitive way, is to probably not touch the bsdf and just modify the scattering operator. Until this point we were lucky that we had an operator which to convert to our functional. It may not be readily obvious what should be done if we want a point or directional light source however. &#xD;&#xA;&#xD;&#xA;As an example consider just the $0$-th term $L_e$ of the Neumann expansion with only a directional light source. To get the contribution from zero bounces away we integrate $L_e$ directly on the film. For a specific pixel  on the film we may assume that the contribution is computed as $$\int_{A}\left(\int_{S^2}W_e(x,\omega)L_e(r(x,\omega),-\omega)\,d\sigma_{x}^{\perp}(\omega)\right)\,dx.$$&#xD;&#xA;Here $A$ is the film area and $W_e$ is the sensitivity function. The aperture is implicitly taken into account by the ray-tracing function. But for simplicity assume there is no aperture, there are now two options: you either treat $L_e$ as an actual Dirac delta $L_e(y,\omega) = e(y,\omega)\delta(\omega-\omega_d)$ in which case you modify the integral to:&#xD;&#xA;$$\int_{A}\left(\int_{S^2}W_e(x,\omega)e(r(x,\omega),-\omega)|n(x)\cdot\omega|\,d\delta_{-\omega_d}(\omega)\right)\,dx =\\= \int_{A}W_e(x,-\omega_d)e(r(x,-\omega_d),\omega_d)|n(x)\cdot\omega_d|\,dx.$$&#xD;&#xA;You could however also require that $W_e$ is a Dirac delta, e.g. both w.r.t. position and direction. Once you do this the result will be a Dirac delta if you work with the abuse of notation approach (you will have one extra left over). This is not necessarily entirely wrong, if you assume that you really want a Dirac delta to mean that it carries infinite energy. As an example, if your sensor has both a positional (on the film) and directional Dirac delta, it would return the radiance of a normal light source when an importance ray hits it. However if that light source has a directional Dirac delta aligning with the one from the sensor, it is not that far fetched to say that you get an infinite contribution - and such an infinity that when integrated against a kernel would spit out the value at the kernel's specific location.&#xD;&#xA;&#xD;&#xA;However, as far as I am aware we do not do this in computer graphics, e.g. when we have a point light source, directional light source, or even a laser, shining into the camera/film is not reproduced in the ray-tracers I am aware of. This means that they opted for treating this in a different way than the abuse of notation would suggest. E.g. if they have a specular light and then diffuse they treat it like a Dirac delta, however if they have a specular light and then a specular surface they do not use two Dirac deltas, instead they produce at most one Dirac delta, and that is only if the arguments of the two supposed Dirac deltas agree, so in this case $\int g(\omega)\delta(\omega-\omega_1)\delta(\omega-\omega_2)\,d\omega = g(\omega_1)\delta_{\omega_1=\omega_2} \ne g(\omega_1)\delta(\omega_1-\omega_2)$, note that in the middle expression the delta is a Kronecker delta and not a Dirac delta. The middle expression is consistent with how you do not visualize point/directional light sources on the film. &#xD;&#xA;&#xD;&#xA;**Conclusion** &#xD;&#xA;&#xD;&#xA;Ultimately how you decide to treat it is up to you, probably the most consistent way is using the abuse of notation, because then you can actually have multibounce specular contributions from a Dirac light source (e.g. &quot;directional light&quot; seen in a mirror), and it's also consistent as a limiting case of decreasing the solid angle emission of some light source and increasing its power - in the limit you get the directional Dirac delta, but the limiting emissions do not magically stop working after one bounce, so it's probably consistent to keep that for a Dirac delta light also. I think the main reason the Dirac delta nature of the light is not visualized on the film is because it is typically used as a cheap approximation of an actual light source, but the fact that it has infinite energy at a point would probably be perceived as an artefact on the film.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42246" PostHistoryTypeId="5" PostId="13817" RevisionGUID="3ef7ae91-5a0a-46d5-8513-3684bb0606d5" CreationDate="2023-11-21T00:19:09.173" UserId="10096" Comment="added 9 characters in body" Text="**The Rendering Equation**&#xD;&#xA;&#xD;&#xA;First thing first, the rendering equation in its solid angle formulation in vacuum is:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{S^2} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta_x| d\sigma(\omega).$$&#xD;&#xA;You forgot the emission function $L_e$ in your question.  The solution $L:M\times S^2 \to \mathbb{R}$ (where $S^2=\{p\in\mathbb{R}^3\,:\, \|p\|_2=1\}$ is just the 2-sphere) is fully determined by the collection $(M, n, f, L_e)$, where $M\subset \mathbb{R}^3$ is the set of points forming the scene surfaces, $n:M\to S^2$ is the function that assigns a normal to every point of $M$, $f:M\times S^2 \times S^2 \to \mathbb{R}_+$ is the BSDF (it represents the light scattering properties of the materials of your surfaces), and $L_e:M\times S^2 \to \mathbb{R}_+$ is the emitted radiance function (it is non-zero on your light sources). It is fairly natural that your geometry $(M,n$), the materials $f$, and the light sources $L_e$ will determine the steady state of the radiance $L$ in the scene.&#xD;&#xA;&#xD;&#xA;The function $r:M\times S^2 \to M\cup (\infty\cdot S^2)$ is the ray-tracing function that returns the first intersection point $r(x,\omega)$ along the ray with origin $x$ and direction $\omega$, if there is no intersection you can formally claim that it returns the intersection with some sphere at infinity (e.g. your environment map). Typically the rendering equation is formulated in terms of the incident radiance $L_i(x, \omega)$, however, in vacuum we have $L_i(x,\omega) = (GL)(x,\omega) = L(r(x,\omega),-\omega)$ - the radiance that arrives at $x$ from direction $\omega$ is equal to the radiance leaving $r(x,\omega)$ in direction $-\omega$, which is also fairly intuitive. The term $|\cos\theta_x| = |n(x)\cdot \omega|$ is due to Lambert's cosine law, but it can be derived also by just integrating a differential $2$-density on the sphere (think surface flux integrals from calculus 3). The $d\sigma(\omega)$ is the area measure on the sphere, i.e. if you take the standard spherical coordinates parametrization $x = \sin\theta\cos\phi$, $y=\sin\theta\sin\phi$, $z=\cos\theta$ and your rotate them so that $z$ is aligned with $n(x)$, then you may rewrite $d\sigma(\omega) = |\sin\theta| d\theta d\phi$ and thus:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{0}^{2\pi}\int_0^{\pi} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta| |\sin\theta|d\theta d\phi.$$&#xD;&#xA;&#xD;&#xA;**Formal Solution**&#xD;&#xA;&#xD;&#xA;For brevity one typically writes the above in operator form $L = L_e +TL$ where $T:(M\times S^2\to \mathbb{R})\to (M\times S^2\to \mathbb{R})$ is the operator that stands for the integral. If we define the scattering operator $K$ and the propagation operator $G$:&#xD;&#xA;$$(Kg)(x,\omega) = \int_{S^2}f(x,\omega,\omega_o)g(x,\omega)d\sigma_{x}^{\perp}(\omega), \quad (Gh)(x,\omega) = h(r(x,\omega),-\omega),$$&#xD;&#xA;then $T=K\circ G$.&#xD;&#xA; Since we have the identity $L=L_e+TL$ we can just plug it in itself once yielding $L=L_e + T(L_e + TL) = L_e+TL_e+T^2L$. Repeating this process until infinity yields the series $L = \sum_{k=0}^{\infty}T^kL_e$. Formally $\sum_{k=0}^{\infty}T^k$ is the solution operator for the rendering equation:&#xD;&#xA;\begin{align}&#xD;&#xA;L = L_e +TL \implies (I-T)L = L_e \implies L = (I-T)^{-1}L_e \implies (I-T)^{-1} = \sum_{k=0}^{\infty}T^k.&#xD;&#xA;\end{align}&#xD;&#xA;The latter is the Neumann series for $T$. While $\|T\|&lt;1$ is a sufficient condition for convergence (i.e. if the brdf is energy conserving), it is not a necessary condition - for specific choices of $L_e$ the above series may be convergent even if $(I-T)^{-1}$ is unbounded. Note that $f,L,L_e$ are actual functions (i.e. $T$ maps functions to functions). In practice one may want to model specular reflection, point and directional lights etc., which according to &quot;many treatments&quot; cannot be modeled with classical functions and require distribution. Veach discusses this in his thesis (e.g. in some appendices on specular reflection and refraction), and even has a nice table 8.3 showing some examples.&#xD;&#xA;&#xD;&#xA;**Veach's Extension to Distributions**&#xD;&#xA;&#xD;&#xA;If you go to 5.A.1, Veach has a short note that $\int_{\mathbb{R}} f(x)\delta(x-x_0)\,dx$ is just symbolic notation for the evaluation functional $\Lambda_{x_0}(f) = f(x_0)$. This symbolic expression could also be framed as $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx := \int_{\mathbb{R}} f(x)\,d\delta_{x_0}(x)$ where $\delta_{x_0}$ is the Dirac measure. Note however that $\delta$ is not the Radon-Nikodym derivative of this measure, i.e. the expression $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx$ is still purely symbolic if not abuse of notation. When you write $$\int_{S^2} f(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega) = \int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega),$$&#xD;&#xA;the second expression is purely symbolic and means&#xD;&#xA;\begin{align}&#xD;&#xA;\int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega)&amp;:= \int_{S^2} \rho(x,\omega,\omega_o)L_i(x,\omega)\,d\delta_{\omega_r}(\omega) \\&#xD;&#xA;= \Lambda_{\omega_r}(\rho(x,\cdot,\omega_o)L_i(x,\cdot)) &amp;= \rho(x,\omega_r,\omega_o) L_i(x,\omega_r).&#xD;&#xA;\end{align}&#xD;&#xA;The linear operator $\Lambda_{\omega_r}$ is not the BSDF itself, it is the operator $T$ when restricted to this specific specular vertex $x$, thus the BSDF cannot be a distribution even though Veach abuses notation (as is often done elsewhere) and calls it a distribution. What's really going on at a specular vertex $p$ is that the definition of $K$ at point $p$ is modified to $$(Kg)(p,\omega_o) = \int_{S^2}\rho(p,\omega,\omega_o)g(p,\omega)\,d\delta_{\omega_r}(\omega) = \rho(p,\omega_r,\omega_o)g(p,\omega_r).$$&#xD;&#xA;Formally you could pretend that:&#xD;&#xA;$$f(x,\omega,\omega_r) = \rho(x,\omega,\omega_o)\frac{d\delta_{\omega_r}(\omega)}{d\sigma_x^{\perp}(\omega)} =\rho(x,\omega,\omega_o)\delta_{\sigma_x^{\perp}}(\omega-\omega_r).$$&#xD;&#xA;The only issue is that the function/Radon-Nikodym derivative doesn't exist because the Dirac measure $\delta_{\omega_r}$ is not absolutely continuous, but the notation is convenient enough that everyone abuses it.&#xD;&#xA;&#xD;&#xA;**Extension to Dirac Delta Light Sources**&#xD;&#xA;&#xD;&#xA;As we saw above the whole &quot;distribution&quot; business is tantamount to modifying your scattering operator at specific points. There are many ways to achieve this - you could tie the measure to your bsdf, then a specular vertex you would have a &quot;differential bsdf-measure&quot; $fd\delta$ while at a normal vertex it would be $fd\sigma_{x}^{\perp}$. The other way is of course to abuse notation and pretend that $\delta$ is the Radon-Nikodym derivative. The most theoretically sound, but least intuitive way, is to probably not touch the bsdf and just modify the scattering operator. Until this point we were lucky that we had an operator which to convert to our functional. It may not be readily obvious what should be done if we want a point or directional light source however. &#xD;&#xA;&#xD;&#xA;As an example consider just the $0$-th term $L_e$ of the Neumann expansion with only a directional light source. To get the contribution from zero bounces away we integrate $L_e$ directly on the film. For a specific pixel  on the film we may assume that the contribution is computed as $$\int_{A}\left(\int_{S^2}W_e(x,\omega)L_e(r(x,\omega),-\omega)\,d\sigma_{x}^{\perp}(\omega)\right)\,dx.$$&#xD;&#xA;Here $A$ is the film area and $W_e$ is the sensitivity function. The aperture is implicitly taken into account by the ray-tracing function. But for simplicity assume there is no aperture, there are now two options: you either treat $L_e$ as an actual Dirac delta $L_e(y,\omega) = e(y,\omega)\delta(\omega-\omega_d)$ in which case you modify the integral to:&#xD;&#xA;$$\int_{A}\left(\int_{S^2}W_e(x,\omega)e(r(x,\omega),-\omega)|n(x)\cdot\omega|\,d\delta_{-\omega_d}(\omega)\right)\,dx =\\= \int_{A}W_e(x,-\omega_d)e(r(x,-\omega_d),\omega_d)|n(x)\cdot\omega_d|\,dx.$$&#xD;&#xA;You could however also require that $W_e$ is a Dirac delta, e.g. both w.r.t. position and direction. Once you do this the result will be a Dirac delta if you work with the abuse of notation approach (you will have one extra left over). This is not necessarily entirely wrong, if you assume that you really want a Dirac delta to mean that it carries infinite energy. As an example, if your sensor has both a positional (on the film) and directional Dirac delta, it would return the radiance of a normal light source when an importance ray hits it. However if that light source has a directional Dirac delta aligning with the one from the sensor, it is not that far fetched to say that you get an infinite contribution - and such an infinity that when integrated against a kernel would spit out the value at the kernel's specific location.&#xD;&#xA;&#xD;&#xA;However, as far as I am aware we do not do this in computer graphics, e.g. when we have a point light source, directional light source, or even a laser, shining into the camera/film is not reproduced in the ray-tracers I am aware of. This means that they opted for treating this in a different way than the abuse of notation would suggest. E.g. if they have a specular light and then diffuse they treat it like a Dirac delta, however if they have a specular light and then a specular surface they do not use two Dirac deltas, instead they produce at most one Dirac delta, and that is only if the arguments of the two supposed Dirac deltas agree, so in this case $\int g(\omega)\delta(\omega-\omega_1)\delta(\omega-\omega_2)\,d\omega = g(\omega_1)\delta_{\omega_1=\omega_2} \ne g(\omega_1)\delta(\omega_1-\omega_2)$, note that in the middle expression the delta is a Kronecker delta and not a Dirac delta. The middle expression is consistent with how you do not visualize point/directional light sources on the film. &#xD;&#xA;&#xD;&#xA;**Conclusion** &#xD;&#xA;&#xD;&#xA;Ultimately how you decide to treat it is up to you, probably the most consistent way is using the abuse of notation, because then you can actually have multibounce specular contributions from a Dirac light source (e.g. &quot;directional light&quot; seen in a mirror), and it's also consistent as a limiting case of decreasing the solid angle emission of some light source and increasing its power - in the limit you get the directional Dirac delta, but the limiting emissions do not magically stop working after one bounce, so it's probably consistent to keep that for a Dirac delta light also. I think the main reason the Dirac delta nature of the light is not visualized on the film is because it is typically used as a cheap approximation of an actual physical light source, and the fact that it has infinite energy at a point would probably be perceived as an artefact on the film.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42247" PostHistoryTypeId="50" PostId="13554" RevisionGUID="c6fe6247-6f9e-4e68-be62-3e493026b92a" CreationDate="2023-11-22T19:03:40.463" UserId="-1" />
  <row Id="42248" PostHistoryTypeId="2" PostId="13818" RevisionGUID="9fc8a7c7-44c1-4948-82d5-822efa8319a8" CreationDate="2023-11-22T22:29:24.887" UserId="20881" Text="I am trying to write a raytracer in Rust that is able to load a .gltf file and render it. To do this I model a scene in Blende, export it to gltf (y up) and use my renderer to render the scene.&#xD;&#xA;&#xD;&#xA;The Issue I am currently having is that the rotations in Blender and the exported gltf file do not seem to match up. If I for example set a rotation of ``(0,0.5,0.5,0|XYZW)`` in Blender, it gets exported as ``(0,1,0,0|XYZW)``. If I however render this Image using my code, yet another rotation seems to be used (an image is produced corresponding to a rotation of (0.5,0,0,0.5|XYZW) in Blender).&#xD;&#xA;`easy_gltf` yields the following transform matrix (world -&gt; camera):&#xD;&#xA;```&#xD;&#xA;camera.transform = Matrix4 &#xD;&#xA;[-1.0, 0.0, 0.0, 2.0&#xD;&#xA;0.0, 1.0, 0.0, 10.0&#xD;&#xA;0.0, 0.0, -1.0, -2&#xD;&#xA;0.0, 0.0, 0.0, 1.0]&#xD;&#xA;```&#xD;&#xA;The camera is located at (2,2,10) in Blender, so at least the translational component appears to be working.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To load the gltf file, I use ``easy_gltf`` in Rust. The following code is used to generate the ray directions:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;//ray origin in world space&#xD;&#xA;let origin_world_space = camera.position();&#xD;&#xA;// the distance from the camera origin to the view plane&#xD;&#xA;let z: f32 = height as f32 / (2.0 * fovy.mul(0.5).tan());&#xD;&#xA;&#xD;&#xA;//obtain the inverse transformation Matrix&#xD;&#xA;let inverse_transform = camera.transform.invert().unwrap_or_else(||&#xD;&#xA;    panic!(&quot;Non invertible transform Matrix. giving up.&quot;)&#xD;&#xA;);&#xD;&#xA;&#xD;&#xA;//TODO: take ray multiplier per pixel into account here&#xD;&#xA;let mut rays: Vec&lt;Ray&gt; = Vec::with_capacity(height * width);&#xD;&#xA;&#xD;&#xA;//generate all rays for this pixel and add them to the rays vector&#xD;&#xA;//TODO: use blue noise here to generate multiple rays per pixel&#xD;&#xA;rays.push(generate_single_primary_ray(&#xD;&#xA;    width,&#xD;&#xA;    height,&#xD;&#xA;    &amp;inverse_transform,&#xD;&#xA;    z,&#xD;&#xA;    pixel_x_coord,&#xD;&#xA;    pixel_y_coord,&#xD;&#xA;    origin_world_space));&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;fn generate_single_primary_ray(image_width: usize,&#xD;&#xA;                               image_height: usize,&#xD;&#xA;                               inverse_transform: &amp;Matrix4&lt;f32&gt;,&#xD;&#xA;                               focal_length: f32,&#xD;&#xA;                               u: usize,&#xD;&#xA;                               v: usize,&#xD;&#xA;                               ray_origin: Vector3&lt;f32&gt;) -&gt; Ray {&#xD;&#xA;    //calculate the ray direction and translate it to world space&#xD;&#xA;    let direction_view_space: Vector4&lt;f32&gt; =&#xD;&#xA;        Vector4::new(u as f32 - (image_width as f32 / 2.0),&#xD;&#xA;                     v as f32 - (image_height as f32 / 2.0),&#xD;&#xA;                     focal_length,&#xD;&#xA;                     0.0);&#xD;&#xA;    //TODO: Rotation is fucked&#xD;&#xA;    //x rotation has sign wrong, y and z are flipped&#xD;&#xA;    let direction_world_space = inverse_transform * direction_view_space.normalize();&#xD;&#xA;&#xD;&#xA;    Ray { source: ray_origin, direction: direction_world_space.truncate().normalize() }&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;As you may see from the code above, to calculate the ray direction I first calculate the distance from the camera origin to the projection plane, take the inverse of the World-to-Camera-Matrix and then map the Camera space coordinates to world space directions using the inverse transform matrix (which I get from the `eays_gltf` API -&gt; no influence on that).&#xD;&#xA;&#xD;&#xA;Now I tried debugging this for hours but I cannot seem to pin down the issue. Is the export process wrong? Is easy gltf constructing the Matrix wrongly or do I have an issue in my code?&#xD;&#xA;&#xD;&#xA;The code, .blend file and .gltf file are available here: https://git.cdaut.de/CDaut/raytrace-rs" ContentLicense="CC BY-SA 4.0" />
  <row Id="42250" PostHistoryTypeId="1" PostId="13818" RevisionGUID="9fc8a7c7-44c1-4948-82d5-822efa8319a8" CreationDate="2023-11-22T22:29:24.887" UserId="20881" Text="Issues understanding rotations exported from Blender to gltf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42251" PostHistoryTypeId="3" PostId="13818" RevisionGUID="9fc8a7c7-44c1-4948-82d5-822efa8319a8" CreationDate="2023-11-22T22:29:24.887" UserId="20881" Text="|gltf|blender|quaternions|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42252" PostHistoryTypeId="2" PostId="13819" RevisionGUID="587c6b8b-07fe-4800-b11f-10218e6cce38" CreationDate="2023-11-23T08:31:22.300" UserId="13273" Text="I am trying to implement the Triangular Gregory patch from [this][1] paper.&#xD;&#xA;The goal is to create a $G^1$ continuity across the patch boundaries. So that the normal vectors of neighboring triangles are equal.&#xD;&#xA;&#xD;&#xA;Right now I'm trying to understand how to calculate the Bézier ordinates: $b_{i,j,k}$ where $i,j,k \geq 0$ and $i+j+k = n$&#xD;&#xA;&#xD;&#xA;The second thing I'm not sure about is the degree $n$. How to choose a good $n$?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www2.eecs.berkeley.edu/Pubs/TechRpts/1987/CSD-87-313.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42254" PostHistoryTypeId="1" PostId="13819" RevisionGUID="587c6b8b-07fe-4800-b11f-10218e6cce38" CreationDate="2023-11-23T08:31:22.300" UserId="13273" Text="Gregory triangle patch, calculating $b_{i,j,k}$" ContentLicense="CC BY-SA 4.0" />
  <row Id="42255" PostHistoryTypeId="3" PostId="13819" RevisionGUID="587c6b8b-07fe-4800-b11f-10218e6cce38" CreationDate="2023-11-23T08:31:22.300" UserId="13273" Text="|bezier-curve|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42256" PostHistoryTypeId="2" PostId="13820" RevisionGUID="16f9796f-52e5-4937-a44e-f6e9df67154c" CreationDate="2023-11-23T12:39:38.290" UserId="7724" Text="If you want to implement triangular Gregory patches then you do not have to choose $n$ since a triangular Gregory patch is special kind of quartic B\'ezier triangle, so $n = 4$. The patch has special inner control points which are constructed from cubic B\'ezier curves on the edges of the triangles.&#xD;&#xA;&#xD;&#xA;I take your question about how to compute the control points $b_{ijk}$ (ordinates) to be how to go from a standard triangular mesh to a mesh of Gregory patches. The easiest way to construct B\'ezier control points (ordinates) from a triangular mesh is to first construct vertex normals (by averaging incident face normals) and then to use the procedure from PN triangles ([Section 3.1][1]) to construct the edge control points of each triangle. Each one of these edges is then a cubic B\'ezier curve which can be used as input to construct, through the Chiyokura-Kimura basis patch technique, the inner control points of the Gregory patch.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://citeseerx.ist.psu.edu/document?repid=rep1&amp;type=pdf&amp;doi=72297b633af266e8a22e861a5c0d8d04281b877a" ContentLicense="CC BY-SA 4.0" />
  <row Id="42258" PostHistoryTypeId="5" PostId="13817" RevisionGUID="0e64e083-4622-4332-a6ad-c32afa70b78d" CreationDate="2023-11-23T16:54:09.530" UserId="10096" Comment="added 13246 characters in body" Text="**The Rendering Equation**&#xD;&#xA;&#xD;&#xA;First thing first, the rendering equation in its solid angle formulation in vacuum is:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{S^2} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta_x| d\sigma(\omega).$$&#xD;&#xA;You forgot the emission function $L_e$ in your question.  The solution $L:M\times S^2 \to \mathbb{R}$ (where $S^2=\{p\in\mathbb{R}^3\,:\, \|p\|_2=1\}$ is just the 2-sphere) is fully determined by the collection $(M, n, f, L_e)$, where $M\subset \mathbb{R}^3$ is the set of points forming the scene surfaces, $n:M\to S^2$ is the function that assigns a normal to every point of $M$, $f:M\times S^2 \times S^2 \to \mathbb{R}_+$ is the BSDF (it represents the light scattering properties of the materials of your surfaces), and $L_e:M\times S^2 \to \mathbb{R}_+$ is the emitted radiance function (it is non-zero on your light sources). It is fairly natural that your geometry $(M,n$), the materials $f$, and the light sources $L_e$ will determine the steady state of the radiance $L$ in the scene.&#xD;&#xA;&#xD;&#xA;The function $r:M\times S^2 \to M\cup (\infty\cdot S^2)$ is the ray-tracing function that returns the first intersection point $r(x,\omega)$ along the ray with origin $x$ and direction $\omega$, if there is no intersection you can formally claim that it returns the intersection with some sphere at infinity (e.g. your environment map). Typically the rendering equation is formulated in terms of the incident radiance $L_i(x, \omega)$, however, in vacuum we have $L_i(x,\omega) = (GL)(x,\omega) = L(r(x,\omega),-\omega)$ - the radiance that arrives at $x$ from direction $\omega$ is equal to the radiance leaving $r(x,\omega)$ in direction $-\omega$, which is also fairly intuitive. The term $|\cos\theta_x| = |n(x)\cdot \omega|$ is due to Lambert's cosine law, but it can be derived also by just integrating a differential $2$-density on the sphere (think surface flux integrals from calculus 3). The $d\sigma(\omega)$ is the area measure on the sphere, i.e. if you take the standard spherical coordinates parametrization $x = \sin\theta\cos\phi$, $y=\sin\theta\sin\phi$, $z=\cos\theta$ and your rotate them so that $z$ is aligned with $n(x)$, then you may rewrite $d\sigma(\omega) = |\sin\theta| d\theta d\phi$ and thus:&#xD;&#xA;$$L(x,\omega) = L_e(x,\omega) + \int_{0}^{2\pi}\int_0^{\pi} f(x, \omega_i, \omega_o) L(r(x,\omega), -\omega)|\cos\theta| |\sin\theta|d\theta d\phi.$$&#xD;&#xA;&#xD;&#xA;**Formal Solution**&#xD;&#xA;&#xD;&#xA;For brevity one typically writes the above in operator form $L = L_e +TL$ where $T:(M\times S^2\to \mathbb{R})\to (M\times S^2\to \mathbb{R})$ is the operator that stands for the integral. If we define the scattering operator $K$ and the propagation operator $G$:&#xD;&#xA;$$(Kg)(x,\omega) = \int_{S^2}f(x,\omega,\omega_o)g(x,\omega)d\sigma_{x}^{\perp}(\omega), \quad (Gh)(x,\omega) = h(r(x,\omega),-\omega),$$&#xD;&#xA;then $T=K\circ G$.&#xD;&#xA; Since we have the identity $L=L_e+TL$ we can just plug it in itself once yielding $L=L_e + T(L_e + TL) = L_e+TL_e+T^2L$. Repeating this process until infinity yields the series $L = \sum_{k=0}^{\infty}T^kL_e$. Formally $\sum_{k=0}^{\infty}T^k$ is the solution operator for the rendering equation:&#xD;&#xA;\begin{align}&#xD;&#xA;L = L_e +TL \implies (I-T)L = L_e \implies L = (I-T)^{-1}L_e \implies (I-T)^{-1} = \sum_{k=0}^{\infty}T^k.&#xD;&#xA;\end{align}&#xD;&#xA;The latter is the Neumann series for $T$. While $\|T\|&lt;1$ is a sufficient condition for convergence (i.e. if the brdf is energy conserving), it is not a necessary condition - for specific choices of $L_e$ the above series may be convergent even if $(I-T)^{-1}$ is unbounded. Note that $f,L,L_e$ are actual functions (i.e. $T$ maps functions to functions). In practice one may want to model specular reflection, point and directional lights etc., which according to &quot;many treatments&quot; cannot be modeled with classical functions and require distribution. Veach discusses this in his thesis (e.g. in some appendices on specular reflection and refraction), and even has a nice table 8.3 showing some examples.&#xD;&#xA;&#xD;&#xA;**Veach's Extension to Distributions**&#xD;&#xA;&#xD;&#xA;If you go to 5.A.1, Veach has a short note that $\int_{\mathbb{R}} f(x)\delta(x-x_0)\,dx$ is just symbolic notation for the evaluation functional $\Lambda_{x_0}(f) = f(x_0)$. This symbolic expression could also be framed as $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx := \int_{\mathbb{R}} f(x)\,d\delta_{x_0}(x)$ where $\delta_{x_0}$ is the Dirac measure. Note however that $\delta$ is not the Radon-Nikodym derivative of this measure, i.e. the expression $\int_{\mathbb{R}} f(x)\delta(x-x_0)dx$ is still purely symbolic if not abuse of notation. When you write $$\int_{S^2} f(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega) = \int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega),$$&#xD;&#xA;the second expression is purely symbolic and means&#xD;&#xA;\begin{align}&#xD;&#xA;\int_{S^2} \delta_{\sigma_x^{\perp}}(\omega-\omega_r)\rho(x,\omega,\omega_o)L_i(x,\omega)\,d\sigma_x^{\perp}(\omega)&amp;:= \int_{S^2} \rho(x,\omega,\omega_o)L_i(x,\omega)\,d\delta_{\omega_r}(\omega) \\&#xD;&#xA;= \Lambda_{\omega_r}(\rho(x,\cdot,\omega_o)L_i(x,\cdot)) &amp;= \rho(x,\omega_r,\omega_o) L_i(x,\omega_r).&#xD;&#xA;\end{align}&#xD;&#xA;The linear operator $\Lambda_{\omega_r}$ is not the BSDF itself, it is the operator $T$ when restricted to this specific specular vertex $x$, thus the BSDF cannot be a distribution even though Veach abuses notation (as is often done elsewhere) and calls it a distribution. What's really going on at a specular vertex $p$ is that the definition of $K$ at point $p$ is modified to $$(Kg)(p,\omega_o) = \int_{S^2}\rho(p,\omega,\omega_o)g(p,\omega)\,d\delta_{\omega_r}(\omega) = \rho(p,\omega_r,\omega_o)g(p,\omega_r).$$&#xD;&#xA;Formally you could pretend that:&#xD;&#xA;$$f(x,\omega,\omega_r) = \rho(x,\omega,\omega_o)\frac{d\delta_{\omega_r}(\omega)}{d\sigma_x^{\perp}(\omega)} =\rho(x,\omega,\omega_o)\delta_{\sigma_x^{\perp}}(\omega-\omega_r).$$&#xD;&#xA;The only issue is that the function/Radon-Nikodym derivative doesn't exist because the Dirac measure $\delta_{\omega_r}$ is not absolutely continuous, but the notation is convenient enough that everyone abuses it.&#xD;&#xA;&#xD;&#xA;**Extension to Dirac Delta Light Sources**&#xD;&#xA;&#xD;&#xA;As we saw above the whole &quot;distribution&quot; business is tantamount to modifying your scattering operator at specific points. There are many ways to achieve this - you could tie the measure to your bsdf, then a specular vertex you would have a &quot;differential bsdf-measure&quot; $fd\delta$ while at a normal vertex it would be $fd\sigma_{x}^{\perp}$. The other way is of course to abuse notation and pretend that $\delta$ is the Radon-Nikodym derivative. The most theoretically sound, but least intuitive way, is to probably not touch the bsdf and just modify the scattering operator. Until this point we were lucky that we had an operator which to convert to our functional. It may not be readily obvious what should be done if we want a point or directional light source however. &#xD;&#xA;&#xD;&#xA;As an example consider just the $0$-th term $L_e$ of the Neumann expansion with only a directional light source. To get the contribution from zero bounces away we integrate $L_e$ directly on the film. For a specific pixel  on the film we may assume that the contribution is computed as $$\int_{A}\left(\int_{S^2}W_e(x,\omega)L_e(r(x,\omega),-\omega)\,d\sigma_{x}^{\perp}(\omega)\right)\,dx.$$&#xD;&#xA;Here $A$ is the film area and $W_e$ is the sensitivity function. The aperture is implicitly taken into account by the ray-tracing function. But for simplicity assume there is no aperture, there are now two options: you either treat $L_e$ as an actual Dirac delta $L_e(y,\omega) = e(y,\omega)\delta(\omega-\omega_d)$ in which case you modify the integral to:&#xD;&#xA;$$\int_{A}\left(\int_{S^2}W_e(x,\omega)e(r(x,\omega),-\omega)|n(x)\cdot\omega|\,d\delta_{-\omega_d}(\omega)\right)\,dx =\\= \int_{A}W_e(x,-\omega_d)e(r(x,-\omega_d),\omega_d)|n(x)\cdot\omega_d|\,dx.$$&#xD;&#xA;You could however also require that $W_e$ is a Dirac delta, e.g. both w.r.t. position and direction. Once you do this the result will be a Dirac delta if you work with the abuse of notation approach (you will have one extra left over). This is not necessarily entirely wrong, if you assume that you really want a Dirac delta to mean that it carries infinite energy. As an example, if your sensor has both a positional (on the film) and directional Dirac delta, it would return the radiance of a normal light source when an importance ray hits it. However if that light source has a directional Dirac delta aligning with the one from the sensor, it is not that far fetched to say that you get an infinite contribution - and such an infinity that when integrated against a kernel would spit out the value at the kernel's specific location.&#xD;&#xA;&#xD;&#xA;However, as far as I am aware we do not do this in computer graphics, e.g. when we have a point light source, directional light source, or even a laser, shining into the camera/film is not reproduced in the ray-tracers I am aware of. This means that they opted for treating this in a different way than the abuse of notation would suggest. E.g. if they have a specular light and then diffuse they treat it like a Dirac delta, however if they have a specular light and then a specular surface they do not use two Dirac deltas, instead they produce at most one Dirac delta, and that is only if the arguments of the two supposed Dirac deltas agree, so in this case $\int g(\omega)\delta(\omega-\omega_1)\delta(\omega-\omega_2)\,d\omega = g(\omega_1)\delta_{\omega_1=\omega_2} \ne g(\omega_1)\delta(\omega_1-\omega_2)$, note that in the middle expression the delta is a Kronecker delta and not a Dirac delta. The middle expression is consistent with how you do not visualize point/directional light sources on the film. &#xD;&#xA;&#xD;&#xA;**Conclusion** &#xD;&#xA;&#xD;&#xA;Ultimately how you decide to treat it is up to you, probably the most consistent way is using the abuse of notation, because then you can actually have multibounce specular contributions from a Dirac light source (e.g. &quot;directional light&quot; seen in a mirror), and it's also consistent as a limiting case of decreasing the solid angle emission of some light source and increasing its power - in the limit you get the directional Dirac delta, but the limiting emissions do not magically stop working after one bounce, so it's probably consistent to keep that for a Dirac delta light also. I think the main reason the Dirac delta nature of the light is not visualized on the film is because it is typically used as a cheap approximation of an actual physical light source, and the fact that it has infinite energy at a point would probably be perceived as an artefact on the film.&#xD;&#xA;&#xD;&#xA;$$$$&#xD;&#xA;**Appendix: Some Details on the Dirac Delta**&#xD;&#xA;&#xD;&#xA;Here are some additional clarifications regarding the object (or I should rather say notational tool) that we call the Dirac delta. Essentially we wish for a function $\delta : \mathbb{R} \to \mathbb{R}\cup \{\pm\infty\}$ such that for any function $g$ we have $\int_{\mathbb{R}} g(t)\delta(t-x)\,dt = g(x)$. Unfortunately, such a function doesn't exist, however, there are objects (that are not functions) that behave in this way. I will list those roughly in order of most general to least general. The most general ones have the least assumptions on the class of functions $g$ for which they hold, while the least general ones have the most constraints on $g$.&#xD;&#xA;&#xD;&#xA;**Evaluation Functional $\delta_x$ (Constraint: Functions)**&#xD;&#xA;&#xD;&#xA;Let $V$ be the set of functions from some set $X$ to some set $Y$, i.e. $g:X\to Y$. Define $\delta_x(g) = g(x)$ - in this specific case we didn't assume anything about $g$ except that it is a function. If $Y$ is a vector space over a field $\mathbb{F}$, then $V$ is also a vector space over $\mathbb{F}$ with the function-function addition $(g+h)(x) := g(x)+h(x)$ and scalar-function multiplication $(\alpha\cdot g)(x) := \alpha\cdot g(x)$. Specifically if $Y=\mathbb{F}$ then $\delta_x : V \to \mathbb{F}$ is from the algebraic dual $V'$ of $V$, that is, the space of linear functions $f^*:V\to \mathbb{F}$ (also called functionals). Then $\delta_x (g) = g(x)$ is known as the evaluation functional (here we just assumed that $g$ are scalar functions). However you should notice that in this most general case we do not even have a notion of integration, i.e. we just have a notion of pointwise evaluation $\delta_x(g) = g(x)$ - the integral from our desired identity has been replaced by some map $\delta_x$.&#xD;&#xA;&#xD;&#xA;Note also that $V$ being a set of functions is crucial. If I had taken $V$ to be $L_2(X)$ then I would be working with equivalence classes of functions and even the evaluation functional and the meaning of $g(x)$ would not be well-defined. One could of course try and pick out a representative from each equivalence class to which to apply the evaluation functional, but there is generally no well-defined way to do so for $L_2$. There is, however, a way to generalize this to some other spaces of equivalence classes, e.g. you could do so for Sobolev spaces $H^{q}(\mathcal{X})$ where $q\in(0,\infty)$ and $2q&gt; \dim X$ (the dimension here is in the sense of manifold dimension).&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Measure $\delta_x$ (Constraint: Measurable Functions)**&#xD;&#xA;&#xD;&#xA;If you have two measurable spaces $(X,\mathcal{X})$ and $(Y,\mathcal{Y})$ (those can be equal) and a function $g:X\to Y$ such that the preimage $g^{-1}$ of any set $B$ from $\mathcal{Y}$ is from $\mathcal{X}$: $B\in \mathcal{Y} \implies g^{-1}(B)\in \mathcal{X}$, then $g$ is termed a measurable function. If you additionally have a measure $\mu$ (e.g. the Lebesgue measure) then you can further limit $\mathcal{X}$ to be sets of Lebesgue-measurable sets, and we speak of $\mu$-measurable functions. For any $A\in \mathcal{X}$ you could now define the Dirac measure:&#xD;&#xA;$$\delta_x(A) = 1_A(x) = \begin{cases} 1, &amp; x\in A, \\ 0, &amp; x\not\in A.\end{cases}$$&#xD;&#xA;Then you can define the integral of $g$ w.r.t. $\delta_x$ as:&#xD;&#xA;$$\int_{A} g(t)\,\delta_x(dt) = g(x)\delta_x(A)=&#xD;&#xA;\begin{cases}&#xD;&#xA;g(x), &amp; x\in A, \\&#xD;&#xA;0, &amp;x\not\in A,&#xD;&#xA;\end{cases}$$&#xD;&#xA;Note that $0$ should be well-defined in $Y$ for this to make sense (all the practical examples you care about satisfy this however).&#xD;&#xA;&#xD;&#xA;Now take $X$ to be some subset of $\mathbb{R}^n$ and $Y\subseteq \mathbb{R}$ then let $\mathcal{X}$ be the Lebesgue measurable subsets of $X$, and let $\mu:\mathcal{X}\to\mathbb{R}_+$ be the Lebesgue measure,  then you can define integrals of the form $\int_A g(t) \,\mu(dt)$ for $A\in\mathcal{X}$. Each $\mu$-measurable function $f$ can then be interpreted as a density and it induces a measure $\mu_f(A) = \int_A f(t)\,\mu(dt)$. The Radon-Nikodym theorem goes in the opposite direction - it says that if you have two measures $\mu$ and $\nu$, then under some constraints (the measures being sigma-finite and $\nu$ being absolutely continuous w.r.t. $\mu$) there exists a $\mu$-measurable density function $f$ such that $\nu(A) = \int_A f(t)\,\mu(dt)$. Then $f$ is termed the Radon-Nikodym derivative of $\nu$ w.r.t. $\mu$: $f(t) = \frac{\nu(dt)}{\mu(dt)}$ and you can compute integrals w.r.t. $\nu$ by rewriting them as integrals w.r.t. $\mu$ (that is e.g. how you define $n$-volume integration on $n$-manifolds): $$\int_A g(t)\nu(dt) = \int_A g(t)f(t) \,\mu(dt).$$&#xD;&#xA;&#xD;&#xA;In any case, using the above we see that if we have many compatible measures we can pick one common measure $\mu$ (e.g. the Lebesgue measure) and define all integrals w.r.t. it. It's what you do in practice, except when you encounter a Dirac delta, but then you modify your notation to look as if you're still using integration w.r.t. the Lebesgue measure for the Dirac delta. In our specific case it would be convenient if we could write&#xD;&#xA;$$\int_{A} g(t)\,\delta_x(dt) = \int_A g(t)\delta_{\mu}(t-x)\,d\mu(t) = g(x)\delta_{x}(A).$$&#xD;&#xA;And that would have been possible if it weren't for the fact that $\delta_x$ is not absolutely continuous w.r.t. $\mu$. Notably $\mu(\{x\}) = 0$ but $\delta_x(\{x\})=1$ which violates absolute continuity. This means that such a measurable density function $\delta_{\mu}(t-x)$ does not exist/the Radon-Nikodym derivative $\frac{d\delta_x}{d\mu}$ does not exist. But since it is convenient notation, one goes ahead and defines the formal symbolic expression by analogy to the cases where the Radon-Nikodym derivative exists:&#xD;&#xA;$$\int_{A}f(t)\delta_{\mu}(t-x)\,\mu(dt) = \int_{A}f(t)\frac{\delta_x(dt)}{\mu(dt)}\,\mu(dt) := \int_A f(t)\,\delta_x(dt) = f(x)\delta_x(A).$$&#xD;&#xA;The first two expressions are purely symbolic and equal to what's on the right by definition. Here $\mu$ is the Lebesgue measure or any other measure derived from the Lebesgue measure such as the solid angle or area measure used in the rendering equation. Note that you could try and define:&#xD;&#xA;$$\delta_{\mu}(x-t) := \frac{\delta_x(dt)}{\mu(dt)}, \text{ but } \frac{\delta_x(dt)}{\mu(dt)} \text{ doesn't exist.}$$&#xD;&#xA;So the $\delta_{\mu}$ can only show up in an integral, and then it's just symbolic notation that translates to what we defined it as. Notably the following expression (potentially corresponding to a specular light and bsdf) is not defined:&#xD;&#xA;$$\int_{A} g(t)\delta_{\mu}(t-x)\delta_{\mu}(t-y)\,d\mu(dt) = \int_{A} g(t)\delta_{\mu}(t-y)\,\delta_x(dt) = ?,$$&#xD;&#xA;simply because we never defined what $\int_{A} \delta_{\mu}(t-y)\,\delta_x(dt)$ means - remember that $\delta_{\mu}(t-x)$ doesn't actually exist and we only introduced notation for it w.r.t. an integral w.r.t. $\mu$ $\mu$. We could try and define a second &quot;integral&quot; of the above (remember that this is purely symbolic notation, so we're just mimicking what would have happened if the Radon-Nikodym derivative existed):&#xD;&#xA;\begin{align}&#xD;&#xA;I &amp;=\int_B \int_{A} g(t)\delta_{\mu}(t-x)\delta_{\mu}(t-y)\,d\mu(dt)\,d\mu(dx) \\&#xD;&#xA;&amp;= \int_B\int_{A} g(t)\delta_{\mu}(t-y)\,\delta_x(dt)\,d\mu(dx) \\&#xD;&#xA;&amp;= \int_B g(x)\delta_{\mu}(x-y)1_A(x)\,\mu(dx) \\&#xD;&#xA;&amp;= \int_B g(x)1_A(x)\,\delta_y(dx) \\&#xD;&#xA;&amp;= g(y)1_A(y)1_B(y) = g(y)1_{A\cap B}(y).\end{align}&#xD;&#xA;So we could claim that the result is a differential measure element $g(x)1_A(x)\,\delta_y(dx)$ that expects to be integrated. Later on we can argue what this should mean if we treat $dx$ as a finite measure set and we shrink it down to zero - then naturally you would expect this result to blow up to infinity.&#xD;&#xA;&#xD;&#xA;However, whenever you have a specular light + specular bsdf, another way to model it is as follows:&#xD;&#xA;\begin{align}&#xD;&#xA;I &amp;=\int_{A} g(t)\delta_{\mu}(t-x)\delta_{\delta_x}(t-y)\,d\mu(dt) \\&#xD;&#xA;&amp;= \int_A g(t)\delta_{\delta_x}(t-y)\,d\delta_x(dt) \\&#xD;&#xA;&amp;= \int_A g(t)\delta_{\delta_x}(t-y)\frac{\delta_y(dt)}{\delta_x(dt)}\,d\delta_x(dt) \\&#xD;&#xA;&amp;= \int_A g(t) \delta_y(dt) = g(y)1_A(y).&#xD;&#xA;\end{align}&#xD;&#xA;Now this corresponds to what is done in graphics $\delta_{\delta_x}$, but I think that the first approach is more consistent with what would happen in reality. I believe that what we do in graphics is motivated more from practical considerations than trying to model things realistically. For example if you were to take a disk light source with directional Dirac deltas for each point of it, and if you have complex ideal mirrors after it until the film, which say is also such a Dirac delta directional disk, you would have to track an infinite amount of specular rays. You could of course try to Monte Carlo this, but if you say that these carry infinite energy then missing even just one can result in an infinite error at the film.&#xD;&#xA;&#xD;&#xA;In either case, since the Radon-Nikodym derivative doesn't actually exist both approaches amount to just changing the integration measure associated with the operator $K$ at specific points of the scene - so in theory you are free to pick whichever you like. &#xD;&#xA;&#xD;&#xA;**Distribution $\delta_x$ (Constraint: $C^{k}$ Functions)**&#xD;&#xA;&#xD;&#xA;You may require $\delta_{x}$ to be from the continuous dual $V^*$ (you need to have a topology to define the continuous dual unlike for the algebraic dual). If $V=C^{\infty}_c(X)$ then the continuos dual $V^*$ is the space of distributions. A regular distribution is one arising as an integral of a locally $L_1$ integrable function, e.g. $f^*(\phi) = \int f(t)\phi(t)\,dt$. You can multiply a distribution $D$ by another distribution $f^*$, if the latter is a regular distribution arising from $f\in C^{\infty}(X)$. So if your radiance and BSDF were infinitely many times differentiable you could make distributions out of those and multiply those distributions, similar to how you would deal with functions. The infinitely many times differentiability condition can be relaxed if you consider distributions of finite order. What cannot be relaxed however is the fact that the Dirac delta distribution is not a regular distribution - meaning that there exists no functions $\delta$ such that $\delta_x(\phi) = \int \delta(t-x) \phi(t)\,dt$. So once again such notation would be purely symbolic. Furthermore while distribution multiplication is defined between a regular distribution (arising from a function in $C^k$) and a non-regular one, the multiplication between two arbitrary distributions is not well-defined (e.g. between two Dirac delta distributions). As before you can try to define what it should be in your case depending on how you want to model your problem.&#xD;&#xA;&#xD;&#xA;**Reproducing Kernel $\delta_x$ (Constraint: Reproducing Kernel Hilbert Spaces)**&#xD;&#xA;&#xD;&#xA;I should note that the Dirac delta exists as a function in the sense $\int \delta(t-x) f(t)\,dt = f(x)$ if you consider a reproducing kernel Hilbert space. Then the Dirac delta function could be identified with the reproducing kernel for the space. For example bandlimited continuous functions have the sinc kernel as a reproducing kernel. Unfortunately you cannot guarantee that your functions are bandlimited and continuous in graphics - any hard edge can produce a non-bandlimited or discontinuous function in your radiance, or e.g. an edge in the BSDF can do the same (e.g. checkerboard texture).&#xD;&#xA;&#xD;&#xA;**The Dirac Delta as a Limit**&#xD;&#xA;&#xD;&#xA;You can study the following limit:&#xD;&#xA;$$\lim_{\sigma\to 0}\int_{-\infty}^{\infty}f(t)\frac{1}{\sqrt{2\pi\sigma^2}}\exp\left(-\frac{(t-x)^2}{2\sigma^2}\right)\,dt = f(x).$$&#xD;&#xA;As you can see it acts as a Dirac delta (for reasonable $f$). One may be tempted to move the limit inside the integral and state:&#xD;&#xA;$$\delta(t-x) = \lim_{\sigma\to 0}\exp\left(-\frac{(t-x)^2}{2\sigma^2}\right),$$&#xD;&#xA;but you actually cannot do so as the two are not equivalent:&#xD;&#xA;$$\int_{-\infty}^{\infty}f(t)\lim_{\sigma\to 0}\frac{1}{\sqrt{2\pi\sigma^2}}\exp\left(-\frac{(t-x)^2}{2\sigma^2}\right)\,dt = 0&#xD;&#xA;\ne f(x) = \lim_{\sigma\to 0}\int_{-\infty}^{\infty}f(t)\frac{1}{\sqrt{2\pi\sigma^2}}\exp\left(-\frac{(t-x)^2}{2\sigma^2}\right)\,dt.$$&#xD;&#xA;However as before you could formally define the following symbolic expression:&#xD;&#xA;$$\int_{-\infty}^{\infty}f(t)\delta(t-x)\,dt := \lim_{\sigma\to 0}\int_{-\infty}^{\infty}f(t)\frac{1}{\sqrt{2\pi\sigma^2}}\exp\left(-\frac{(t-x)^2}{2\sigma^2}\right)\,dt.$$&#xD;&#xA;Then you could choose to define the product of two Dirac deltas as:&#xD;&#xA;$$\int_{-\infty}^{\infty}\delta(t-x)\delta(t-y)\,dt := \lim_{\sigma_1,\sigma_2\to 0}\int_{-\infty}^{\infty}\frac{1}{2\pi|\sigma_1\sigma_2|}\exp\left(-\frac{(t-x)^2}{2\sigma_1^2}+\frac{(t-y)^2}{2\sigma^2_2}\right)\,dt.$$&#xD;&#xA;My guess is that this integral should give you the following (I haven't checked it):&#xD;&#xA;$$\lim_{\sigma\to 0}\exp\left(-\frac{(t-x)^2}{2\sigma^2}\right) = \begin{cases} \infty, &amp; x=y, \\ 0, &amp;x\ne y\end{cases}.$$&#xD;&#xA;Based on the above and based on the idea of representing a Dirac delta light source as a limit of physical light sources where you increase the power while decreasing the solid angle or/and area, you could argue that e.g. a directional light source should show up as infinity if the film also has a directional Dirac delta importance/sensor function. So probably the first approach discussed in the section on $\delta_x$ as a measure is the physically more relevant one, since it would agree with this limiting process." ContentLicense="CC BY-SA 4.0" />
  <row Id="42259" PostHistoryTypeId="2" PostId="13821" RevisionGUID="99165b5e-8cb2-4d8a-a51f-cb163b04c369" CreationDate="2023-11-24T12:30:11.533" UserId="20870" Text="I am having an issue with wall heights in my 2D raycasting playground I made for practice.&#xD;&#xA;&#xD;&#xA;## Problem ##&#xD;&#xA;&lt;i&gt;Test code in P5.js editor:&lt;/i&gt; https://editor.p5js.org/tomekp/sketches/6fKPIAHNx  (WASD to move, Left/Right arrow to turn)&lt;br/&gt;&#xD;&#xA;In the code above, I have an implementation of 2D raycasting, it is the best I have so far in that the walls are mostly the correct height depending on the player's position. The core of the logic is in &lt;b&gt;sketch.js&lt;/b&gt; (you may need to open the sidebar menu if it doesn't open by default).&#xD;&#xA;&lt;br/&gt;&#xD;&#xA;However, &lt;b&gt;the problem&lt;/b&gt; is that when you are standing directly in front of a wall (or walls), just far back enough to see the top and bottom of the wall slices you are looking at, the top and bottom of the lines that are being drawn vary in size just enough to make the wall look sort of concave.&lt;br/&gt;&#xD;&#xA;I've also attached an image at the bottom from the P5 link above to illustrate the issue further.&#xD;&#xA;&#xD;&#xA;## What I've tried ##&#xD;&#xA;I've read the Lodev's tutorial (https://lodev.org/cgtutor/raycasting.html), and a number of other articles online that explain the maths behind raycasting. I learned that I should be using `cos(rayAngle) * rayLength` to get the perpendicular distance from wall to player. And after trying various code changes &amp; studying up on my maths I still can't seem to grasp what's going wrong. &#xD;&#xA;&#xD;&#xA;I think the issue is that despite the perpendicular distance being used there are still small variations in that distance causing the concave effect on the walls that you are directly perpendicular to, but not sure.&#xD;&#xA;&#xD;&#xA;Any help/pointers would be appreciated, for context, I've been been mainly focusing on trigonometry when brushing up on my maths so I wonder if I am maybe just missing some required bit of maths to understand what I am doing wrong or if it's a case of misunderstanding how the computer renders rects/lines at specific canvas sizes. I think I basically don't know what I don't know to solve this problem.&#xD;&#xA;&#xD;&#xA;### Image  of issue ###&#xD;&#xA;[![Example of concave wall issue][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/i88wD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42261" PostHistoryTypeId="1" PostId="13821" RevisionGUID="99165b5e-8cb2-4d8a-a51f-cb163b04c369" CreationDate="2023-11-24T12:30:11.533" UserId="20870" Text="Raycasting wall slice height issue" ContentLicense="CC BY-SA 4.0" />
  <row Id="42262" PostHistoryTypeId="3" PostId="13821" RevisionGUID="99165b5e-8cb2-4d8a-a51f-cb163b04c369" CreationDate="2023-11-24T12:30:11.533" UserId="20870" Text="|2d|ray|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42264" PostHistoryTypeId="2" PostId="13822" RevisionGUID="da6f18c7-c4cf-49f7-a3fd-1008cff6c51b" CreationDate="2023-11-24T19:13:07.267" UserId="445" Text="You've made a classic mistake, not primarily in your raycasting, but in how you compute the rays. You wrote:&#xD;&#xA;&#xD;&#xA;```javascript&#xD;&#xA;const rayAngleIncrement = FOV / width;&#xD;&#xA;...&#xD;&#xA;let angle = -FOV/2;&#xD;&#xA;...&#xD;&#xA;    let rayDirection = createVector(&#xD;&#xA;      cos(radians(angle + playerHeading)),&#xD;&#xA;      sin(radians(angle + playerHeading))&#xD;&#xA;    );&#xD;&#xA;    ...&#xD;&#xA;    angle += rayAngleIncrement;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This math is consistent in itself, *but* it does not create a perspective projection — instead, it creates a cylindrical projection, as if the world is first projected onto a cylinder surrounding your eye, then the cylinder is cut and unrolled onto the flat screen. This process distorts straight lines into curves.&#xD;&#xA;&#xD;&#xA;[![Diagram of two projections][1]][1]&#xD;&#xA;&#xD;&#xA;In a perspective projection, every part of the transformation is linear, and this preserves straight lines. Here is a standalone piece of JavaScript showing how to compute rays in a perspective projection:&#xD;&#xA;&#xD;&#xA;```javascript&#xD;&#xA;const FOV = 60;&#xD;&#xA;// Note this is tan() rather than sin(). We could use sin() here, but then&#xD;&#xA;// we'd also need to change the length of ray_direction_y, which is more complex.&#xD;&#xA;const rayXAtImageEdge = Math.tan(FOV / 2 * (Math.PI / 180));&#xD;&#xA;&#xD;&#xA;const width = 100;&#xD;&#xA;for (let pixelX = 0; pixelX &lt; width; pixelX++) {&#xD;&#xA;  // This value ranges from -1 to +1 across the image, regardless of pixel width&#xD;&#xA;  const normalizedX = -1 + (pixelX + 0.5) * (2 / width);&#xD;&#xA;  &#xD;&#xA;  // This is the vector for the pixel/slice.&#xD;&#xA;  const rayX = normalizedX * rayXAtImageEdge;&#xD;&#xA;  const rayY = 1;&#xD;&#xA;  &#xD;&#xA;  console.log(normalizedX, rayX);&#xD;&#xA;  // This vector is in &quot;eye space&quot;, so the next step would be to rotate the vector&#xD;&#xA;  // according to playerHeading, then cast it.&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Notice that this ray is _not_ of constant length, since `rayY` is always 1 — this actually makes the math simpler. You can think of it as if, if the image were in front of you in 3D space like a window pane, these were the coordinates of a specific pixel of the image, and the `1` is how far the image is in front of you.&#xD;&#xA;&#xD;&#xA;Now in order to actually put that in your raycaster, get rid of the `angle` variable entirely, and replace your `rayDirection` calculation with this:&#xD;&#xA;&#xD;&#xA;```javascript&#xD;&#xA;    let rayDirection = createVector(&#xD;&#xA;      normalizedX * rayXAtImageEdge,&#xD;&#xA;      -1,&#xD;&#xA;    );&#xD;&#xA;    rayDirection.rotate(radians(90 + playerHeading));&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;(The depth (forward) direction got flipped to -1 to make it work with your existing choice of coordinate system. This is not unusual — different computer graphics systems have different choices of whether a depth coordinate increases when going “into the screen” or “out of the screen”.)&#xD;&#xA;&#xD;&#xA;Finally, you'll find that the calculation of the height of walls is wrong. But we actually have the figure we need already:&#xD;&#xA;&#xD;&#xA;```javascript&#xD;&#xA;// Change the raycast loop to let `iter` be visible outside:&#xD;&#xA;let iter = 0;&#xD;&#xA;for (; iter &lt; RAY_LENGTH; iter++) {&#xD;&#xA;    ...&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;...&#xD;&#xA;&#xD;&#xA;// instead of perpendicularDistance = hyp * cos(radians(angle));&#xD;&#xA;let perpendicularDistance = iter;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This works because `rayDirection`'s length in the image depth direction is always 1, and so `iter` is equal to the distance _in the depth axis only_ to the hit, which is exactly the quantity that the sizes of objects should be divided by to make a perspective projection.&#xD;&#xA;&#xD;&#xA;It will not be _exactly_ the right height, because it doesn't account for the exact depth of the intersection between the ray and the hit cell, only the number of steps. Fixing that (with a ray-line intersection calculation, or a different raycasting algorithm) is another topic entirely. For now, your edges will be ragged by an amount that scales with `CELL_SIZE`, but in the large scale they'll be _straight_, which is what you wanted.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Oqbpx.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42266" PostHistoryTypeId="2" PostId="13823" RevisionGUID="9a8af743-cd4c-42bf-8d7d-a0794cadc159" CreationDate="2023-11-26T10:23:35.873" UserId="20888" Text="So I seem to have some trouble getting a &quot;passthrough&quot; geometry shader working with &quot;glDrawArrays(GL_LINE_STRIP, 0, 4);&quot;. When I omit the geometry shader and make some minor variable changes, the vertex and fragment shader outputs the line strips properly, but adding the geometry shader somehow doesn't output anything (there doesn't seem to be any compile issues).&#xD;&#xA;&#xD;&#xA;I have also tried modifying the geometry shader to be a passthrough shader, and even that fails to output anything.&#xD;&#xA;&#xD;&#xA;Code attached below. Intention of the pipeline is to interpolate 4 colors across corners of a quad given as 4 vertices, so geometry shader is for coalescing data. Note that &quot;pos&quot; in &quot;GS_OUT&quot; in the fragment shader is unused right now because code has been heavily modified after testing.&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    in vec2 in_Position;&#xD;&#xA;    in vec3 in_Color;&#xD;&#xA;&#xD;&#xA;    out VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } vs_out;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;        vs_out.position = in_Position;&#xD;&#xA;        vs_out.color = in_Color;&#xD;&#xA;        gl_Position = vec4(in_Position, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Geometry Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    layout (lines_adjacency) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 4) out;&#xD;&#xA;&#xD;&#xA;    in VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } gs_in[4];&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    out GS_OUT&#xD;&#xA;    {&#xD;&#xA;        flat vec2 pos[4];&#xD;&#xA;        flat vec3 rgb[4];&#xD;&#xA;    } gs_out;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        for (int i = 0; i &lt; 4; i++)&#xD;&#xA;        {&#xD;&#xA;            for (int j = 0; j &lt; 4; j++)&#xD;&#xA;            {&#xD;&#xA;                gs_out.pos[j] = gs_in[j].position;&#xD;&#xA;                gs_out.rgb[j] = gs_in[j].color;&#xD;&#xA;            }&#xD;&#xA;            gl_Position = gl_in[i].gl_Position;&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }&#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    in GS_OUT&#xD;&#xA;    {&#xD;&#xA;        flat vec2 pos[4];&#xD;&#xA;        flat vec3 rgb[4];&#xD;&#xA;    } fs_in;&#xD;&#xA;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {    &#xD;&#xA;        fragColor = vec4(fs_in.rgb[0], 1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42268" PostHistoryTypeId="1" PostId="13823" RevisionGUID="9a8af743-cd4c-42bf-8d7d-a0794cadc159" CreationDate="2023-11-26T10:23:35.873" UserId="20888" Text="Geometry Shader Not Working" ContentLicense="CC BY-SA 4.0" />
  <row Id="42269" PostHistoryTypeId="3" PostId="13823" RevisionGUID="9a8af743-cd4c-42bf-8d7d-a0794cadc159" CreationDate="2023-11-26T10:23:35.873" UserId="20888" Text="|glsl|geometry-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42270" PostHistoryTypeId="5" PostId="13823" RevisionGUID="acf66dc9-c9ec-4d17-94f9-775055730282" CreationDate="2023-11-26T11:16:41.140" UserId="13273" Comment="added 2 characters in body" Text="So I seem to have some trouble getting a &quot;passthrough&quot; geometry shader working with &quot;glDrawArrays(GL_LINE_STRIP, 0, 4);&quot;. When I omit the geometry shader and make some minor variable changes, the vertex and fragment shader outputs the line strips properly, but adding the geometry shader somehow doesn't output anything (there doesn't seem to be any compile issues).&#xD;&#xA;&#xD;&#xA;I have also tried modifying the geometry shader to be a passthrough shader, and even that fails to output anything.&#xD;&#xA;&#xD;&#xA;Code attached below. Intention of the pipeline is to interpolate 4 colors across corners of a quad given as 4 vertices, so geometry shader is for coalescing data. Note that &quot;pos&quot; in &quot;GS_OUT&quot; in the fragment shader is unused right now because code has been heavily modified after testing.&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    in vec2 in_Position;&#xD;&#xA;    in vec3 in_Color;&#xD;&#xA;&#xD;&#xA;    out VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } vs_out;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;        vs_out.position = in_Position;&#xD;&#xA;        vs_out.color = in_Color;&#xD;&#xA;        gl_Position = vec4(in_Position, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Geometry Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    layout (lines_adjacency) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 4) out;&#xD;&#xA;&#xD;&#xA;    in VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } gs_in[4];&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    out GS_OUT&#xD;&#xA;    {&#xD;&#xA;        flat vec2 pos[4];&#xD;&#xA;        flat vec3 rgb[4];&#xD;&#xA;    } gs_out;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        for (int i = 0; i &lt; 4; i++)&#xD;&#xA;        {&#xD;&#xA;            for (int j = 0; j &lt; 4; j++)&#xD;&#xA;            {&#xD;&#xA;                gs_out.pos[j] = gs_in[j].position;&#xD;&#xA;                gs_out.rgb[j] = gs_in[j].color;&#xD;&#xA;            }&#xD;&#xA;            gl_Position = gl_in[i].gl_Position;&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }&#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    in GS_OUT&#xD;&#xA;    {&#xD;&#xA;        flat vec2 pos[4];&#xD;&#xA;        flat vec3 rgb[4];&#xD;&#xA;    } fs_in;&#xD;&#xA;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {    &#xD;&#xA;        fragColor = vec4(fs_in.rgb[0], 1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42271" PostHistoryTypeId="5" PostId="13823" RevisionGUID="82d0486b-914a-4971-a3f9-f129e777da3c" CreationDate="2023-11-27T00:51:11.140" UserId="20888" Comment="deleted 14 characters in body" Text="So I seem to have some trouble getting a geometry shader working with &quot;glDrawArrays(GL_LINE_STRIP, 0, 4);&quot;. When I omit the geometry shader and make some minor variable changes, the vertex and fragment shader outputs the line strips properly, but adding the geometry shader somehow doesn't output anything (there doesn't seem to be any compile issues).&#xD;&#xA;&#xD;&#xA;I have also tried modifying the geometry shader to be a passthrough shader, and even that fails to output anything.&#xD;&#xA;&#xD;&#xA;Code attached below. Intention of the pipeline is to interpolate 4 colors across corners of a quad given as 4 vertices, so geometry shader is for coalescing data. Note that &quot;pos&quot; in &quot;GS_OUT&quot; in the fragment shader is unused right now because code has been heavily modified after testing.&#xD;&#xA;&#xD;&#xA;Vertex Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    in vec2 in_Position;&#xD;&#xA;    in vec3 in_Color;&#xD;&#xA;&#xD;&#xA;    out VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } vs_out;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {&#xD;&#xA;        vs_out.position = in_Position;&#xD;&#xA;        vs_out.color = in_Color;&#xD;&#xA;        gl_Position = vec4(in_Position, 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Geometry Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    layout (lines_adjacency) in;&#xD;&#xA;    layout (triangle_strip, max_vertices = 4) out;&#xD;&#xA;&#xD;&#xA;    in VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } gs_in[4];&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    out GS_OUT&#xD;&#xA;    {&#xD;&#xA;        flat vec2 pos[4];&#xD;&#xA;        flat vec3 rgb[4];&#xD;&#xA;    } gs_out;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        for (int i = 0; i &lt; 4; i++)&#xD;&#xA;        {&#xD;&#xA;            for (int j = 0; j &lt; 4; j++)&#xD;&#xA;            {&#xD;&#xA;                gs_out.pos[j] = gs_in[j].position;&#xD;&#xA;                gs_out.rgb[j] = gs_in[j].color;&#xD;&#xA;            }&#xD;&#xA;            gl_Position = gl_in[i].gl_Position;&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }&#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;Fragment Shader:&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;&#xD;&#xA;    precision highp float;&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    in GS_OUT&#xD;&#xA;    {&#xD;&#xA;        flat vec2 pos[4];&#xD;&#xA;        flat vec3 rgb[4];&#xD;&#xA;    } fs_in;&#xD;&#xA;&#xD;&#xA;    out vec4 fragColor;&#xD;&#xA;&#xD;&#xA;    void main(void)&#xD;&#xA;    {    &#xD;&#xA;        fragColor = vec4(fs_in.rgb[0], 1.0);&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42272" PostHistoryTypeId="2" PostId="13824" RevisionGUID="653e528e-b24b-4b17-a9e4-9994fe109591" CreationDate="2023-11-28T12:33:28.150" UserId="20899" Text=" Consider the square shown below on the left, which has been textured with the image shown on the right. What are the texture coordinates of the vertices a, b, c, and d?&#xD;&#xA;&#xD;&#xA;[![Question][1]][1]&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/Umtrl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42274" PostHistoryTypeId="1" PostId="13824" RevisionGUID="653e528e-b24b-4b17-a9e4-9994fe109591" CreationDate="2023-11-28T12:33:28.150" UserId="20899" Text="Texture coordinates" ContentLicense="CC BY-SA 4.0" />
  <row Id="42275" PostHistoryTypeId="3" PostId="13824" RevisionGUID="653e528e-b24b-4b17-a9e4-9994fe109591" CreationDate="2023-11-28T12:33:28.150" UserId="20899" Text="|texture|coordinates|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42276" PostHistoryTypeId="5" PostId="13824" RevisionGUID="8e6d9352-6db0-48f3-b8ef-7b582a507cdb" CreationDate="2023-11-28T12:34:08.380" UserId="20899" Comment="added 40 characters in body" Text=" Consider the square shown below on the left, which has been textured with the image shown on the right. What are the texture coordinates of the vertices a, b, c, and d?&#xD;&#xA;&#xD;&#xA;Does anyone know how to answer this?&#xD;&#xA;&#xD;&#xA;[![Question][1]][1]&#xD;&#xA;&#xD;&#xA;[1]: https://i.stack.imgur.com/Umtrl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42277" PostHistoryTypeId="2" PostId="13825" RevisionGUID="f9f5726c-d835-435b-9ee1-ae95eeff819c" CreationDate="2023-11-28T13:22:13.720" UserId="7952" Text="The geometry shader should look something like this: the fragment shader should be changed to match.&#xD;&#xA;&#xD;&#xA;    #version 460 core&#xD;&#xA;    layout (lines_adjacency) in; // converting lines to triangles?&#xD;&#xA;    layout (triangle_strip, max_vertices = 4) out;&#xD;&#xA;&#xD;&#xA;    in VS_OUT&#xD;&#xA;    {&#xD;&#xA;        vec2 position;&#xD;&#xA;        vec3 color;&#xD;&#xA;    } gs_in[];&#xD;&#xA;&#xD;&#xA;    // tl, tr, bl, br&#xD;&#xA;    out GS_OUT&#xD;&#xA;    {&#xD;&#xA;        // vec2 pos; the fragment shader isn't using it so why output it?&#xD;&#xA;        vec3 rgb;  &#xD;&#xA;    } gs_out;&#xD;&#xA;&#xD;&#xA;    void main() {&#xD;&#xA;        for (int i = 0; i &lt; 4; i++)&#xD;&#xA;        {&#xD;&#xA;            //gs_out.pos = gs_in.position; -- don't output it if it isn't being used&#xD;&#xA;&#xD;&#xA;            gs_out.rgb = gs_in[i].color;&#xD;&#xA;            gl_Position = gl_in[i].gl_Position;&#xD;&#xA;            EmitVertex();&#xD;&#xA;        }&#xD;&#xA;        EndPrimitive();&#xD;&#xA;    }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42279" PostHistoryTypeId="2" PostId="13826" RevisionGUID="1fdd2449-1861-4bf6-b07c-8740f6a6a8e5" CreationDate="2023-11-28T13:30:42.977" UserId="7724" Text="I'm guessing that the centre of the star has texture coordinates $[0.5, 0.5]$ then $a,b,c,d$ all have the same texture coordinate $[0.5, 0.5]$." ContentLicense="CC BY-SA 4.0" />
  <row Id="42281" PostHistoryTypeId="50" PostId="2246" RevisionGUID="8b94d1da-4d8a-4ed9-8238-6f029f249745" CreationDate="2023-11-28T14:03:25.513" UserId="-1" />
  <row Id="42282" PostHistoryTypeId="50" PostId="13562" RevisionGUID="f89ff052-d9c2-4a77-b427-290aacf16b3a" CreationDate="2023-11-28T15:05:00.657" UserId="-1" />
  <row Id="42283" PostHistoryTypeId="2" PostId="13827" RevisionGUID="f0716b60-3f72-46b6-a094-fe46b1c05ed6" CreationDate="2023-11-28T15:17:29.690" UserId="18529" Text="I'm trying to profile a d3d11 application using queries (pretty much exactly as described [here][1]).&#xD;&#xA;&#xD;&#xA;I noticed something strange with the data I was getting from the queries and I think I managed to isolate the issue:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The green line (*Cpu*) represent the time between two consecutive `swapChain-&gt;Present`, while the blue one represents the time to complete some gpu work for the current frame (measured using queries as explained above).&#xD;&#xA;The GPU work is always the same, however, as the time interval between two `Present` becomes bigger, the measured GPU time increases too. &#xD;&#xA;&#xD;&#xA;I guess this could be a way to reduce power consumption, however, I don't know if that's the case. Is this something you'd expect from the GPU? &#xD;&#xA;&#xD;&#xA;Is there a way to prevent this from happening? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://therealmjp.github.io/posts/profiling-in-dx11-with-queries/&#xD;&#xA;  [2]: https://i.stack.imgur.com/lb0ZA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42285" PostHistoryTypeId="1" PostId="13827" RevisionGUID="f0716b60-3f72-46b6-a094-fe46b1c05ed6" CreationDate="2023-11-28T15:17:29.690" UserId="18529" Text="Profile GPU performance in Direct3D 11" ContentLicense="CC BY-SA 4.0" />
  <row Id="42286" PostHistoryTypeId="3" PostId="13827" RevisionGUID="f0716b60-3f72-46b6-a094-fe46b1c05ed6" CreationDate="2023-11-28T15:17:29.690" UserId="18529" Text="|performance|directx11|instrumentation|profiling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42287" PostHistoryTypeId="50" PostId="10537" RevisionGUID="5868fbcf-525e-4813-a094-ac90ffb3140a" CreationDate="2023-11-28T16:08:46.117" UserId="-1" />
  <row Id="42288" PostHistoryTypeId="2" PostId="13828" RevisionGUID="664b76d2-b847-400b-a37b-abcabc81319e" CreationDate="2023-11-28T16:47:11.990" UserId="13273" Text="Also guessing the center of the star is 0.5 so&#xD;&#xA;&#xD;&#xA;A = (-0.5,0.5)&#xD;&#xA;B = (0.5,1.5)&#xD;&#xA;C = (1.5,0.5)&#xD;&#xA;D = (0.5,-0.5)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42290" PostHistoryTypeId="2" PostId="13829" RevisionGUID="8b1689e9-aa65-49ae-8731-080a4bd2a5d8" CreationDate="2023-11-28T17:15:52.380" UserId="7869" Text="I am studying Monte Carlo Path Tracing from different sources. However, I have some confusion about the `sampling` part and dare to post here for experts' clarification. &#xD;&#xA;&#xD;&#xA;Most of the [sources](https://www.scratchapixel.com/lessons/3d-basic-rendering/global-illumination-path-tracing/introduction-global-illumination-path-tracing.html) present path tracing as figure below: &#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This represents, the light ray starts from the camera/eye, has 3 bounces (whatever is the predefined bounce number), and then hits the light source (`L_e &gt;0`). If I am not wrong, when a ray hits the surface, it has surface information like `normal` and `material`. So if it hits a diffuse surface, it will flow the output angle wrt. the normal anywhere in the scene until the next hit (below figure). &#xD;&#xA;&#xD;&#xA;I assume in this figure above, I have one sample per pixel, and that sample is traveling throughout the scene (the deep orange color ray). The rest of the 5 rays are randomly generated reflected rays over the hemisphere (point `P` in the above figure). &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; [![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&gt; __Question:__ Can I call this one primary ray to 5 other reflected ray creation `ray splitting`? How do I define these 5 random `splitting`? Is it the `hemisphere sampling`? with some pseudorandom number generation like `LCG, TEA`?&#xD;&#xA;&#xD;&#xA;Now come to the second confusing point, according to `pbr book`, each sample is a complete path in the path tracing algorithm. If that is true, according to the first figure, I am just shooting one sample (one path) like below. but the first figure shows I am actually creating `6*6*6 =216` paths within 3 bounces. How that could be possible?   &#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3] &#xD;&#xA;&#xD;&#xA;Now, if I shoot multiple samples per pixel, like the figure below, I guess that should follow some pattern as well (lets say, adaptive sampling)&#xD;&#xA; &#xD;&#xA; [![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;[![enter image description here][5]][5]&#xD;&#xA;&#xD;&#xA;Now, instead of shooting at a point, the `light rays` will hit in a similar area and finally the average the `final color` value. &#xD;&#xA;&#xD;&#xA;&gt; __Question__ How this `pixel sampling` is different than the hemisphere sampling? &#xD;&#xA;&#xD;&#xA;My whole understanding is like this, I guess if I shoot 5 primary rays, they will hit the surface in 5 different points (similar area), and reflect according to the material and attenuation. However, I need to create `hemisphere sampling` separately for the hemisphere and determine, how many random points I am going to create over the hemisphere. __Am I right?__ &#xD;&#xA;&#xD;&#xA;Instead of these two types of sampling, I also see there are `material sampling`, `light sampling`, etc. Is there any other type of sampling? &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/qGWLom.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2wSpum.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/oZXESs.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/Hf9D3s.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/IctW4m.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42292" PostHistoryTypeId="1" PostId="13829" RevisionGUID="8b1689e9-aa65-49ae-8731-080a4bd2a5d8" CreationDate="2023-11-28T17:15:52.380" UserId="7869" Text="Confusion about different sampling strategies in Monte Carlo Path Tracing" ContentLicense="CC BY-SA 4.0" />
  <row Id="42293" PostHistoryTypeId="3" PostId="13829" RevisionGUID="8b1689e9-aa65-49ae-8731-080a4bd2a5d8" CreationDate="2023-11-28T17:15:52.380" UserId="7869" Text="|raytracing|pathtracing|importance-sampling|monte-carlo|hemisphere|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42294" PostHistoryTypeId="5" PostId="13828" RevisionGUID="9bf378f6-9430-4b1f-b6fe-72bd7804529c" CreationDate="2023-11-28T17:38:44.620" UserId="13273" Comment="added 82 characters in body" Text="Also guessing the center of the star is [0.5, 0.5] so&#xD;&#xA;&#xD;&#xA;    a = [-0.5+x, 0.5+y] &#xD;&#xA;    b = [0.5+x, 1.5+y] &#xD;&#xA;    c = [1.5+x, 0.5+y] &#xD;&#xA;    d = [0.5+x, -0.5+y]&#xD;&#xA;&#xD;&#xA; $ \forall x, y \in \mathbb{Z} $" ContentLicense="CC BY-SA 4.0" />
  <row Id="42295" PostHistoryTypeId="2" PostId="13830" RevisionGUID="4bfc500c-b5be-418f-aa4e-06fb8eb6e4a1" CreationDate="2023-11-28T19:04:37.513" UserId="20888" Text="So as @Thomas mentioned, the issue seems to be the fact that I was passing &quot;GL_LINE_STRIP&quot; instead of &quot;GL_LINE_STRIP_ADJACENCY&quot; to the glDrawArrays() call. Apparently, &quot;GL_LINE_STRIP_ADJACENCY is needed when there is ageometry shader involved (&quot;https://www.khronos.org/opengl/wiki/Primitive#Adjacency_primitives&quot;)." ContentLicense="CC BY-SA 4.0" />
  <row Id="42297" PostHistoryTypeId="5" PostId="13830" RevisionGUID="8cc97419-4537-4da2-8a59-30807ee6cebb" CreationDate="2023-11-28T19:04:59.413" UserId="20888" Comment="added 1 character in body" Text="So as @Thomas mentioned, the issue seems to be the fact that I was passing &quot;GL_LINE_STRIP&quot; instead of &quot;GL_LINE_STRIP_ADJACENCY&quot; to the glDrawArrays() call. Apparently, &quot;GL_LINE_STRIP_ADJACENCY is needed when there is a geometry shader involved (&quot;https://www.khronos.org/opengl/wiki/Primitive#Adjacency_primitives&quot;)." ContentLicense="CC BY-SA 4.0" />
  <row Id="42298" PostHistoryTypeId="50" PostId="13783" RevisionGUID="3b0a0595-0b81-4c26-a531-d0425bb39fa7" CreationDate="2023-11-28T20:02:05.283" UserId="-1" />
  <row Id="42299" PostHistoryTypeId="2" PostId="13831" RevisionGUID="ebf63a84-1eaf-49a1-a865-117d2852cd6b" CreationDate="2023-11-28T22:18:11.003" UserId="20471" Text="I cannot leave a comment because I do not have enough reputation points.&#xD;&#xA;&#xD;&#xA;You could rotate the UV coordinates by pi/4.0.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8S7CW.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42301" PostHistoryTypeId="5" PostId="13831" RevisionGUID="f92148b3-bd3a-49c7-8b46-89e62234a2e3" CreationDate="2023-11-29T02:39:51.870" UserId="20471" Comment="added 40 characters in body" Text="I cannot leave a comment because I do not have enough reputation points.&#xD;&#xA;&#xD;&#xA;You could rotate the UV coordinates by pi/4.0. You'll also have to scale by sqrt(2.0).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/8S7CW.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42302" PostHistoryTypeId="2" PostId="13832" RevisionGUID="459a0f72-1e86-4a8e-acba-ad6c59e75de9" CreationDate="2023-11-29T05:27:10.067" UserId="20902" Text="Seems like there are two techniques&#xD;&#xA;&#xD;&#xA;- `Interpolation`: Interpolate the minimum distance from the canter of the pixel to the line. &#xD;&#xA;&#xD;&#xA;- `Coverage`: The fraction of the pixel covered by the line&#xD;&#xA;&#xD;&#xA;Are the results the same?&#xD;&#xA;&#xD;&#xA;For interpolation, are the edges always linearly interpolated?&#xD;&#xA;&#xD;&#xA;What about for the intersection of two lines? I imagine coverage would make better sense?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42304" PostHistoryTypeId="1" PostId="13832" RevisionGUID="459a0f72-1e86-4a8e-acba-ad6c59e75de9" CreationDate="2023-11-29T05:27:10.067" UserId="20902" Text="Alpha calculation for anti aliased line" ContentLicense="CC BY-SA 4.0" />
  <row Id="42305" PostHistoryTypeId="3" PostId="13832" RevisionGUID="459a0f72-1e86-4a8e-acba-ad6c59e75de9" CreationDate="2023-11-29T05:27:10.067" UserId="20902" Text="|antialiasing|line-drawing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42306" PostHistoryTypeId="50" PostId="8131" RevisionGUID="6f351520-d5cf-4abe-a298-ab089d13b324" CreationDate="2023-11-29T09:00:40.140" UserId="-1" />
  <row Id="42307" PostHistoryTypeId="5" PostId="13827" RevisionGUID="4630452f-e60f-42ec-b516-c7e43e5c9406" CreationDate="2023-11-29T09:35:24.503" UserId="18529" Comment="added 254 characters in body" Text="I'm trying to profile a d3d11 application using queries (pretty much exactly as described [here][1]).&#xD;&#xA;&#xD;&#xA;I noticed something strange with the data I was getting from the queries and I think I managed to isolate the issue:&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;The green line (*Cpu*) represent the time between two consecutive `swapChain-&gt;Present`, while the blue one represents the time to complete some gpu work for the current frame (measured using queries as explained above).&#xD;&#xA;The GPU work is always the same, however, as the time interval between two `Present` becomes bigger, the measured GPU time increases too. &#xD;&#xA;&#xD;&#xA;I guess this could be a way to reduce power consumption, however, I don't know if that's the case. Is this something you'd expect from the GPU? &#xD;&#xA;&#xD;&#xA;Is there a way to prevent this from happening? &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**EDIT:**&#xD;&#xA;Apparently, this is the answer to my question (at least on NVidia GPUs): https://developer.nvidia.com/blog/advanced-api-performance-setstablepowerstate/&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://therealmjp.github.io/posts/profiling-in-dx11-with-queries/&#xD;&#xA;  [2]: https://i.stack.imgur.com/lb0ZA.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/1nM5S.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42308" PostHistoryTypeId="2" PostId="13833" RevisionGUID="33801b60-fe0b-4c61-8533-28f773aa8136" CreationDate="2023-11-30T04:22:05.287" UserId="228" Text="There's a lot of research being done in 3D shape analysis when it comes to PDE methods. Recently I've been reading quite a bit of literature on this subject and recent trends in this subject propose different basis all the time.&#xD;&#xA;&#xD;&#xA;The common way to define such a basis is to define an operator or an energy function whose minimization leads to an eigenvalue problem.&#xD;&#xA;&#xD;&#xA;In some situations equations of the form&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;Tx = \lambda x&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Lead to an orthonormal basis, classic example of this is the well known Spherical Harmonics. However I thought I had is whether or not people have used different basis from Spherical Harmonics to represent light.&#xD;&#xA;&#xD;&#xA;Can anyone provide me examples or some literature to look into?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42310" PostHistoryTypeId="1" PostId="13833" RevisionGUID="33801b60-fe0b-4c61-8533-28f773aa8136" CreationDate="2023-11-30T04:22:05.287" UserId="228" Text="Different basis from spherical harmonics to represent light?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42311" PostHistoryTypeId="3" PostId="13833" RevisionGUID="33801b60-fe0b-4c61-8533-28f773aa8136" CreationDate="2023-11-30T04:22:05.287" UserId="228" Text="|lighting|linear-algebra|spherical-harmonics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42312" PostHistoryTypeId="50" PostId="9192" RevisionGUID="bf5fc929-a2d6-4cf9-92e1-76eba880f967" CreationDate="2023-11-30T05:08:00.977" UserId="-1" />
  <row Id="42313" PostHistoryTypeId="2" PostId="13834" RevisionGUID="bcf76aec-3c7e-4e02-8311-5496c1a76c86" CreationDate="2023-12-01T08:47:37.373" UserId="11709" Text="I am trying to implement rendering in &quot;Camera-World&quot; space following PBRT-V4's camera implementation in my Rust ray tracer. I Have been trying to solve that for days&#xD;&#xA;  &#xD;&#xA;I read these multiple times:&#xD;&#xA;* https://www.pbr-book.org/4ed/Cameras_and_Film/Camera_Interface#TheCameraBaseClass&#xD;&#xA;* https://www.pbr-book.org/4ed/Cameras_and_Film/Projective_Camera_Models&#xD;&#xA;* https://pharr.org/matt/blog/2018/03/02/rendering-in-camera-space&#xD;&#xA;&#xD;&#xA;And yet, I can't make it work.  &#xD;&#xA;I have a perspective camera located at [0, 1, 4], looking at the origin, and four spheres:&#xD;&#xA;```rust&#xD;&#xA;let mut scene = Scene::new();&#xD;&#xA;scene.push(Sphere::new(Vec3::new(0.0, -100.5, 0.0), 100.0, Vec3::new(0.8, 0.8, 0.0), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(0.0, 0.0, 0.0), 0.5, Vec3::new(0.1, 0.2, 0.5), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(-1.0, 0.0, -1.0), 0.5, Vec3::new(0.8, 0.8, 0.8), camera.transform.render_from_world).into());&#xD;&#xA;```  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are my image outputs for each space:  &#xD;&#xA;[![World Space (Intended)][1]][1]  &#xD;&#xA;World Space (Intended)  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Camera Space  &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;Camera-World Space  &#xD;&#xA;&#xD;&#xA;I reviewed my transformations multiple times and I can't find what's wrong.  &#xD;&#xA;&#xD;&#xA;Relevant code:&#xD;&#xA;* Camera implementation: https://pastebin.com/sY2JRxDf&#xD;&#xA;* Main: https://pastebin.com/C1EnGddT&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3q5k5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/HtcFI.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/l6TLu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42315" PostHistoryTypeId="1" PostId="13834" RevisionGUID="bcf76aec-3c7e-4e02-8311-5496c1a76c86" CreationDate="2023-12-01T08:47:37.373" UserId="11709" Text="Ray Tracing in Camera-World Space" ContentLicense="CC BY-SA 4.0" />
  <row Id="42316" PostHistoryTypeId="3" PostId="13834" RevisionGUID="bcf76aec-3c7e-4e02-8311-5496c1a76c86" CreationDate="2023-12-01T08:47:37.373" UserId="11709" Text="|raytracing|rendering|camera|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42317" PostHistoryTypeId="5" PostId="13834" RevisionGUID="beb32cd9-1d45-43d2-9f1f-7074eb8eee4e" CreationDate="2023-12-01T10:17:13.343" UserId="11709" Comment="edited body" Text="I am trying to implement rendering in &quot;Camera-World&quot; space following PBRT-V4's camera implementation in my Rust ray tracer. I Have been trying to solve that for days&#xD;&#xA;  &#xD;&#xA;I read these multiple times:&#xD;&#xA;* https://www.pbr-book.org/4ed/Cameras_and_Film/Camera_Interface#TheCameraBaseClass&#xD;&#xA;* https://www.pbr-book.org/4ed/Cameras_and_Film/Projective_Camera_Models&#xD;&#xA;* https://pharr.org/matt/blog/2018/03/02/rendering-in-camera-space&#xD;&#xA;&#xD;&#xA;And yet, I can't make it work.  &#xD;&#xA;I have a perspective camera located at [0, 1, 4], looking at the origin, and four spheres:&#xD;&#xA;```rust&#xD;&#xA;let mut scene = Scene::new();&#xD;&#xA;scene.push(Sphere::new(Vec3::new(0.0, -100.5, 0.0), 100.0, Vec3::new(0.8, 0.8, 0.0), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(0.0, 0.0, 0.0), 0.5, Vec3::new(0.1, 0.2, 0.5), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(-1.0, 0.0, -1.0), 0.5, Vec3::new(0.8, 0.8, 0.8), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(1.0, 0.0, 1.0), 0.5, Vec3::new(0.8, 0.4, 0.5), camera.transform.render_from_world).into());&#xD;&#xA;```  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are my image outputs for each space:  &#xD;&#xA;[![World Space (Intended)][1]][1]  &#xD;&#xA;World Space (Intended)  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Camera Space  &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;Camera-World Space  &#xD;&#xA;&#xD;&#xA;I reviewed my transformations multiple times and I can't find what's wrong.  &#xD;&#xA;&#xD;&#xA;Relevant code:&#xD;&#xA;* Camera implementation: https://pastebin.com/sY2JRxDf&#xD;&#xA;* Main: https://pastebin.com/C1EnGddT&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3q5k5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CNUuu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/pvERp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42318" PostHistoryTypeId="5" PostId="13834" RevisionGUID="690a2757-0f06-421d-b4d3-750a9c185d43" CreationDate="2023-12-01T10:32:17.203" UserId="11709" Comment="added 2 characters in body" Text="I am trying to implement rendering in &quot;Camera-World&quot; space following PBRT-V4's camera implementation in my Rust ray tracer. I Have been trying to solve that for days&#xD;&#xA;  &#xD;&#xA;I read these multiple times:&#xD;&#xA;* https://www.pbr-book.org/4ed/Cameras_and_Film/Camera_Interface#TheCameraBaseClass&#xD;&#xA;* https://www.pbr-book.org/4ed/Cameras_and_Film/Projective_Camera_Models&#xD;&#xA;* https://pharr.org/matt/blog/2018/03/02/rendering-in-camera-space&#xD;&#xA;&#xD;&#xA;And yet, I can't make it work.  &#xD;&#xA;I have a perspective camera located at [0, 1, 4], looking at the origin, and four spheres:&#xD;&#xA;```rust&#xD;&#xA;let mut scene = Scene::new();&#xD;&#xA;scene.push(Sphere::new(Vec3::new(0.0, -100.5, 0.0), 100.0, Vec3::new(0.8, 0.8, 0.0), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(0.0, 0.0, 0.0), 0.5, Vec3::new(0.1, 0.2, 0.5), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(-1.0, 0.0, -1.0), 0.5, Vec3::new(0.8, 0.8, 0.8), camera.transform.render_from_world).into());&#xD;&#xA;scene.push(Sphere::new(Vec3::new(1.0, 0.0, 1.0), 0.5, Vec3::new(0.8, 0.4, 0.5), camera.transform.render_from_world).into());&#xD;&#xA;```  &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Here are my image outputs for each space:  &#xD;&#xA;[![World Space (Intended)][1]][1]  &#xD;&#xA;World Space (Intended)  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Camera Space  &#xD;&#xA;[![enter image description here][3]][3]  &#xD;&#xA;Camera-World Space  &#xD;&#xA;&#xD;&#xA;I reviewed my transformations multiple times and I can't find what's wrong.  &#xD;&#xA;&#xD;&#xA;Relevant code:&#xD;&#xA;* Camera implementation: https://pastebin.com/sY2JRxDf&#xD;&#xA;* Main: https://pastebin.com/C1EnGddT&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/3q5k5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/CNUuu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/pvERp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42319" PostHistoryTypeId="2" PostId="13835" RevisionGUID="370a507b-209c-4499-9d5a-30989aaa0923" CreationDate="2023-12-01T13:14:58.827" UserId="13509" Text="I did some math with orthographic projection matrix to compute viewing direction vectors in screen space.&#xD;&#xA;&#xD;&#xA;I thought all viewing direction vectors should be parallel in orthographic projection because, in orthographic projection, eye sight lines will be always parallel.&#xD;&#xA;&#xD;&#xA;However, the math doesn't show the parallel directions.&#xD;&#xA;&#xD;&#xA;```cpp&#xD;&#xA;    QMatrix4x4 proj;&#xD;&#xA;    proj.ortho(-100, 100, -100, 100, 1, 1001);&#xD;&#xA;    qDebug() &lt;&lt; &quot;projection matrix:&quot; &lt;&lt; proj;&#xD;&#xA;    auto inv = proj.inverted();&#xD;&#xA;    qDebug() &lt;&lt; &quot;inverse projection matrix:&quot; &lt;&lt; inv;&#xD;&#xA;    qDebug() &lt;&lt; &quot;viewing direction at bottom left corner:&quot; &lt;&lt; inv.map(QVector3D(-1, -1, 0)).normalized();&#xD;&#xA;    qDebug() &lt;&lt; &quot;viewing direction at top right corner  :&quot; &lt;&lt; inv.map(QVector3D(1, 1, 0)).normalized();&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;This is small code to compute what I mentioned and the results are:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;projection matrix: QMatrix4x4(type:Translation,Scale&#xD;&#xA;      0.01         0         0         0         &#xD;&#xA;         0      0.01         0         0         &#xD;&#xA;         0         0    -0.002    -1.002         &#xD;&#xA;         0         0         0         1         &#xD;&#xA;)&#xD;&#xA;inverse projection matrix: QMatrix4x4(type:Translation,Scale&#xD;&#xA;       100         0         0         0         &#xD;&#xA;         0       100         0         0         &#xD;&#xA;         0         0      -500      -501         &#xD;&#xA;         0         0         0         1         &#xD;&#xA;)&#xD;&#xA;viewing direction at bottom left corner: QVector3D(-0.192094, -0.192094, -0.962393)&#xD;&#xA;viewing direction at top right corner  : QVector3D(0.192094, 0.192094, -0.962393)&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here, viewing direction vectors at opposite corners don't look parallel.&#xD;&#xA;&#xD;&#xA;Did I do something wrong here? Or, did I misunderstand orthographic projection?&#xD;&#xA;Why can't I get parallel rays here? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42321" PostHistoryTypeId="1" PostId="13835" RevisionGUID="370a507b-209c-4499-9d5a-30989aaa0923" CreationDate="2023-12-01T13:14:58.827" UserId="13509" Text="viewing direction vectors are not parallel in orthographic projection" ContentLicense="CC BY-SA 4.0" />
  <row Id="42322" PostHistoryTypeId="3" PostId="13835" RevisionGUID="370a507b-209c-4499-9d5a-30989aaa0923" CreationDate="2023-12-01T13:14:58.827" UserId="13509" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42323" PostHistoryTypeId="2" PostId="13836" RevisionGUID="e1b84948-7e55-4072-bfb3-f20731c3f3a5" CreationDate="2023-12-01T17:19:09.010" UserId="13273" Text="You only transferred a single point from projection space to view space.&#xD;&#xA;&#xD;&#xA;But you are interested in directions, so you need to convert two points to be able to see the view direction.&#xD;&#xA;&#xD;&#xA;    //check view direction of lower left corner &#xD;&#xA;    vec4 p0_0 = vec4(-1,-1,0,1);&#xD;&#xA;    vec4 p0_1 = vec4(-1,-1,1,1);&#xD;&#xA;&#xD;&#xA;    //check view direction of upper right corner&#xD;&#xA;    vec4 p1_0 = vec4(1,1,0,1);&#xD;&#xA;    vec4 p1_1 = vec4(1,1,1,1);&#xD;&#xA;&#xD;&#xA;    Vec4 ip0_0 = inverprojection * p0_0&#xD;&#xA;    Vec4 ip0_1 = inverprojection * p0_1&#xD;&#xA;    Vec4 ip1_0 = inverprojection * p1_0&#xD;&#xA;    Vec4 ip1_1 = inverprojection * p1_1&#xD;&#xA;&#xD;&#xA;So we have two points per view direction test. &#xD;&#xA;&#xD;&#xA;    Vec4 viewDir0 = ip0_0 - ip0_1&#xD;&#xA;    Vec4 viewDir1 = ip1_0 - ip1_1&#xD;&#xA;&#xD;&#xA;Last step is to compare viewDir0 with viewDir1" ContentLicense="CC BY-SA 4.0" />
  <row Id="42325" PostHistoryTypeId="50" PostId="2516" RevisionGUID="bccc477a-7161-4b79-aade-7d8eecd61e1c" CreationDate="2023-12-01T18:07:20.837" UserId="-1" />
  <row Id="42326" PostHistoryTypeId="50" PostId="13572" RevisionGUID="6228f985-cbb9-4892-ac3d-4646fd78293d" CreationDate="2023-12-01T20:00:40.107" UserId="-1" />
  <row Id="42327" PostHistoryTypeId="50" PostId="13340" RevisionGUID="11ff60ad-4857-43c9-b8c5-24d6c837e295" CreationDate="2023-12-01T21:02:30.270" UserId="-1" />
  <row Id="42328" PostHistoryTypeId="50" PostId="9549" RevisionGUID="f4c3c3f4-f78b-4cbd-8337-5fec9f0e3451" CreationDate="2023-12-01T22:03:05.317" UserId="-1" />
  <row Id="42332" PostHistoryTypeId="50" PostId="13352" RevisionGUID="00790834-f87b-4745-902d-78ab0de7e7e2" CreationDate="2023-12-02T12:04:15.497" UserId="-1" />
  <row Id="42333" PostHistoryTypeId="50" PostId="13022" RevisionGUID="0a6f13d4-1bc2-458d-9f4c-76a2459d505e" CreationDate="2023-12-02T13:06:25.700" UserId="-1" />
  <row Id="42334" PostHistoryTypeId="2" PostId="13837" RevisionGUID="f47c9f41-ce67-4fa3-92f0-7d6afbc75a6e" CreationDate="2023-12-02T15:49:30.973" UserId="20917" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep those comparisons grouped together correctly. Adding values to an append buffer is never done in a predictable order...  [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not a compute graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [2]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42336" PostHistoryTypeId="1" PostId="13837" RevisionGUID="f47c9f41-ce67-4fa3-92f0-7d6afbc75a6e" CreationDate="2023-12-02T15:49:30.973" UserId="20917" Text="Most efficient way to calculate signed distance field (SDF) for pixel subsamples?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42337" PostHistoryTypeId="3" PostId="13837" RevisionGUID="f47c9f41-ce67-4fa3-92f0-7d6afbc75a6e" CreationDate="2023-12-02T15:49:30.973" UserId="20917" Text="|performance|compute-shader|hlsl|antialiasing|signed-distance-field|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42338" PostHistoryTypeId="5" PostId="13837" RevisionGUID="2edf6744-2f2b-4250-bda6-c77e8bd715a1" CreationDate="2023-12-02T15:51:24.290" UserId="20917" Comment="added 69 characters in body" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. This texture represents a mask that only colors pixels near an edge. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep those comparisons grouped together correctly. Adding values to an append buffer is never done in a predictable order...  [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not a compute graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [2]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42339" PostHistoryTypeId="5" PostId="13837" RevisionGUID="bfea627a-43d2-44e9-b168-5d91752fc0ee" CreationDate="2023-12-02T15:52:41.617" UserId="20917" Comment="added 4 characters in body" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. This texture represents a mask that only colors pixels near an edge. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those two subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep those comparisons grouped together correctly. Adding values to an append buffer is never done in a predictable order...  [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not a compute graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [2]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42340" PostHistoryTypeId="5" PostId="13837" RevisionGUID="13ee6425-0acf-44ec-b0f4-5c0cc6f05455" CreationDate="2023-12-02T15:56:14.193" UserId="20917" Comment="deleted 8 characters in body" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. This texture represents a mask that only colors pixels near an edge. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those two subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep those comparisons grouped together correctly. Adding values to an append buffer is never done in a predictable order...  [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not a graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [2]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42341" PostHistoryTypeId="5" PostId="13837" RevisionGUID="f68f6bb0-3e0e-45b4-b735-0d6699fdbb04" CreationDate="2023-12-02T15:59:19.970" UserId="20917" Comment="added 129 characters in body" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. This texture represents a mask that only colors pixels near an edge. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those two subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep arrays for the same subsample stored adjacently in the appendbuffer. Therefore there is not an obvious logic to ensure that the correct minimums are compared with each other. Adding values to an append buffer is never done in a predictable order...  [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I am not a graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [2]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42342" PostHistoryTypeId="5" PostId="13837" RevisionGUID="b9581127-4171-4807-9e4f-f80b183ed0ec" CreationDate="2023-12-02T16:05:10.367" UserId="20917" Comment="added 109 characters in body" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. This texture represents a mask that only colors pixels near an edge. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those two subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep arrays for the same subsample stored adjacently in the appendbuffer. Therefore there is not an obvious logic to ensure that the correct minimums are compared with each other. Adding values to an append buffer is never done in a predictable order. This approach might also be suboptimal in terms of cache coherency  &#xD;&#xA;&#xD;&#xA;I am not a graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/84316.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [3]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42343" PostHistoryTypeId="5" PostId="13837" RevisionGUID="13b499e6-4401-45e1-9d04-5cf460b6955c" CreationDate="2023-12-02T16:07:54.807" UserId="20917" Comment="added 76 characters in body" Text="Looking how to utilize as much parallelization processing as possible for the following task:&#xD;&#xA;&#xD;&#xA;A screen-sized texture is completely black except for blue pixels which are in close proximity to geometry edges (this is a game scene). So at a given time, a small percentage of the texture is blue. This texture represents a mask that only colors pixels near an edge. Each blue pixel can access four unique subsample values of the depth buffer. For each subsample, I need to calculate the difference between its own depth value and the depth value of all of its surrounding subsamples (up to two or three pixels away, not sure yet), check if the difference is greater than a threshold value, and if so, store the distance between those two subsamples. Finally, find the minimum distance stored. This generates an SDF value which describes how close that subsample is to an 'edge.' The image illustrates one of these groups of comparisons. This has to be performed again for every subsample.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is obviously a very large task which is why I am trying to utilize the parallel processing capabilities of a compute shader. I want to disperse the calculations to as many threads as possible, **in order to avoid a small number of threads performing very large loops** but I am challenged to find a way to organize the calculations so that only nearby subsamples are compared with each other.&#xD;&#xA;&#xD;&#xA;I originally thought of having the blue pixels send out groups of values into an appendbuffer (where the element type would be an array), and then each thread could look-up&#xD;&#xA;the array in that appendbuffer that corresponds to its index (ie appendbuffer[(globalID.y * screenWidth) + globalID.x)]) and find the minimum distance for the values in that array. The trouble comes after this step though. I would need to then find the minimum of THOSE minimums to find the absolute minimum, and there doesn't seem to be an obvious way to keep arrays for the same subsample stored adjacently in the appendbuffer. Therefore there is not an obvious logic to ensure that the correct minimums are compared with each other. Adding values to an append buffer is never done in a predictable order. This approach might also be suboptimal in terms of cache coherency  &#xD;&#xA;&#xD;&#xA;I am not a graphics programmer (or any programmer for that matter) by profession. Hoping someone with a lot of experience can weigh in here and give a good recommendation. I am measuring the compute shader's performance in [RenderDoc][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/84316.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/LxPvP.png&#xD;&#xA;  [3]: https://renderdoc.org/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42344" PostHistoryTypeId="2" PostId="13838" RevisionGUID="b8617899-81b1-4c2d-b9e2-0b6e7ef8fb0f" CreationDate="2023-12-02T16:13:20.697" UserId="20918" Text="I’m currently working on a project involving animation programming using OpenGL and BVH (Biovision Hierarchy) data for animation, and I am trying to get my head around it. I’ve run into some issues and could use some insight.&#xD;&#xA;&#xD;&#xA;The problem I’m facing is that when I render my animation, it doesn’t come out as expected. I find the format of BVH quite confusing but this seems correct and it should work but the animation looks quite odd.&#xD;&#xA;&#xD;&#xA;I am unsure if, for each rotation you need to multiply it by the parentMatrix? doing this seemed to prevent the legs going up to the up and flicking back down so I assumed it was correct?&#xD;&#xA;BVH file: [mixamo.bvh][1]&#xD;&#xA;&#xD;&#xA;    [![enter image description here][2]][2]void Skeleton::drawJoint(Mat4&amp; viewMatrix, Mat4 parentMatrix, Joint* joint, uint32_t currFrame)&#xD;&#xA;    { &#xD;&#xA;        &#xD;&#xA;        vec3 offset_from_parent = vec3(&#xD;&#xA;        	joint-&gt;jointOffsetX,&#xD;&#xA;        	joint-&gt;jointOffsetY,&#xD;&#xA;        	joint-&gt;jointOffsetZ&#xD;&#xA;        );&#xD;&#xA;            &#xD;&#xA;        	vec3 anotherRot = vec3(&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[0]]],&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[1]]],&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[2]]]&#xD;&#xA;        );&#xD;&#xA;        &#xD;&#xA;        auto jointPos = parentMatrix * (offset_from_parent);&#xD;&#xA;            // get rotation for current joint for current frame&#xD;&#xA;        auto boneRot =  parentMatrix * bone_rotations[currFrame][joint-&gt;id];&#xD;&#xA;        &#xD;&#xA;        // BVH stores rotation as Z,Y,X so, boneRot.x would be rotation for z&#xD;&#xA;        auto z = boneRot.x;&#xD;&#xA;        auto y = boneRot.y;&#xD;&#xA;        auto x = boneRot.z;&#xD;&#xA;        &#xD;&#xA;        //z,y,x multiply like: x,y,z&#xD;&#xA;        auto local = Mat4::Translate(jointPos) * (Mat4::RotateX(x) * Mat4::RotateY(y) * Mat4::RotateZ(z));&#xD;&#xA;        &#xD;&#xA;        for(auto&amp; child : joint-&gt;Children)&#xD;&#xA;        {&#xD;&#xA;            vec3 end = local * vec3(child.joint_offset[0], child.joint_offset[1], child.joint_offset[2]);&#xD;&#xA;        	drawCylinder(viewMatrix, jointPos, end);&#xD;&#xA;        &#xD;&#xA;            drawJoint(viewMatrix, localMatrix, &amp;child, scale, frame);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pastebin.com/4w2Qv5TD&#xD;&#xA;  [2]: https://i.stack.imgur.com/WEZV2.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="42346" PostHistoryTypeId="1" PostId="13838" RevisionGUID="b8617899-81b1-4c2d-b9e2-0b6e7ef8fb0f" CreationDate="2023-12-02T16:13:20.697" UserId="20918" Text="Animation issue using BVH data in OpenGL" ContentLicense="CC BY-SA 4.0" />
  <row Id="42347" PostHistoryTypeId="3" PostId="13838" RevisionGUID="b8617899-81b1-4c2d-b9e2-0b6e7ef8fb0f" CreationDate="2023-12-02T16:13:20.697" UserId="20918" Text="|opengl|transformations|animation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42348" PostHistoryTypeId="5" PostId="13838" RevisionGUID="9babcd90-3697-4528-9548-d009f9152273" CreationDate="2023-12-02T16:14:17.003" UserId="20918" Comment="added 45 characters in body" Text="I’m currently working on a project involving animation programming using OpenGL and BVH (Biovision Hierarchy) data for animation, and I am trying to get my head around it. I’ve run into some issues and could use some insight.&#xD;&#xA;&#xD;&#xA;The problem I’m facing is that when I render my animation, it doesn’t come out as expected. I find the format of BVH quite confusing but this seems correct and it should work but the animation looks quite odd.&#xD;&#xA;&#xD;&#xA;I am unsure if, for each rotation you need to multiply it by the parentMatrix? doing this seemed to prevent the legs going up to the up and flicking back down so I assumed it was correct?&#xD;&#xA;BVH file: [mixamo.bvh][1]&#xD;&#xA;&#xD;&#xA;    [![enter image description here][2]][2]void Skeleton::drawJoint(Mat4&amp; viewMatrix, Mat4 parentMatrix, Joint* joint, uint32_t currFrame)&#xD;&#xA;    { &#xD;&#xA;        &#xD;&#xA;        vec3 offset_from_parent = vec3(&#xD;&#xA;        	joint-&gt;jointOffsetX,&#xD;&#xA;        	joint-&gt;jointOffsetY,&#xD;&#xA;        	joint-&gt;jointOffsetZ&#xD;&#xA;        );&#xD;&#xA;            &#xD;&#xA;        	vec3 anotherRot = vec3(&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[0]]],&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[1]]],&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[2]]]&#xD;&#xA;        );&#xD;&#xA;        &#xD;&#xA;        auto jointPos = parentMatrix * (offset_from_parent);&#xD;&#xA;            // get rotation for current joint for current frame&#xD;&#xA;        auto boneRot =  parentMatrix * bone_rotations[currFrame][joint-&gt;id];&#xD;&#xA;        &#xD;&#xA;        // BVH stores rotation as Z,Y,X so, boneRot.x would be rotation for z&#xD;&#xA;        auto z = boneRot.x;&#xD;&#xA;        auto y = boneRot.y;&#xD;&#xA;        auto x = boneRot.z;&#xD;&#xA;        &#xD;&#xA;        //z,y,x multiply like: x,y,z&#xD;&#xA;        auto local = Mat4::Translate(jointPos) * (Mat4::RotateX(x) * Mat4::RotateY(y) * Mat4::RotateZ(z));&#xD;&#xA;        &#xD;&#xA;        for(auto&amp; child : joint-&gt;Children)&#xD;&#xA;        {&#xD;&#xA;            vec3 end = local * vec3(child.joint_offset[0], child.joint_offset[1], child.joint_offset[2]);&#xD;&#xA;        	drawCylinder(viewMatrix, jointPos, end);&#xD;&#xA;        &#xD;&#xA;            drawJoint(viewMatrix, localMatrix, &amp;child, scale, frame);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pastebin.com/4w2Qv5TD&#xD;&#xA;  [2]: https://i.stack.imgur.com/1UGte.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="42349" PostHistoryTypeId="5" PostId="13838" RevisionGUID="3b90ca56-1c1c-4496-8074-0900418edd68" CreationDate="2023-12-02T16:14:34.380" UserId="20918" Comment="deleted 39 characters in body" Text="I’m currently working on a project involving animation programming using OpenGL and BVH (Biovision Hierarchy) data for animation, and I am trying to get my head around it. I’ve run into some issues and could use some insight.&#xD;&#xA;&#xD;&#xA;The problem I’m facing is that when I render my animation, it doesn’t come out as expected. I find the format of BVH quite confusing but this seems correct and it should work but the animation looks quite odd.&#xD;&#xA;&#xD;&#xA;I am unsure if, for each rotation you need to multiply it by the parentMatrix? doing this seemed to prevent the legs going up to the up and flicking back down so I assumed it was correct?&#xD;&#xA;BVH file: [mixamo.bvh][1]&#xD;&#xA;&#xD;&#xA;    void Skeleton::drawJoint(Mat4&amp; viewMatrix, Mat4 parentMatrix, Joint* joint, uint32_t currFrame)&#xD;&#xA;    { &#xD;&#xA;        &#xD;&#xA;        vec3 offset_from_parent = vec3(&#xD;&#xA;        	joint-&gt;jointOffsetX,&#xD;&#xA;        	joint-&gt;jointOffsetY,&#xD;&#xA;        	joint-&gt;jointOffsetZ&#xD;&#xA;        );&#xD;&#xA;            &#xD;&#xA;        	vec3 anotherRot = vec3(&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[0]]],&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[1]]],&#xD;&#xA;        	frames[currFrame][BVH_CHANNEL[joint-&gt;joint_channel[2]]]&#xD;&#xA;        );&#xD;&#xA;        &#xD;&#xA;        auto jointPos = parentMatrix * (offset_from_parent);&#xD;&#xA;            // get rotation for current joint for current frame&#xD;&#xA;        auto boneRot =  parentMatrix * bone_rotations[currFrame][joint-&gt;id];&#xD;&#xA;        &#xD;&#xA;        // BVH stores rotation as Z,Y,X so, boneRot.x would be rotation for z&#xD;&#xA;        auto z = boneRot.x;&#xD;&#xA;        auto y = boneRot.y;&#xD;&#xA;        auto x = boneRot.z;&#xD;&#xA;        &#xD;&#xA;        //z,y,x multiply like: x,y,z&#xD;&#xA;        auto local = Mat4::Translate(jointPos) * (Mat4::RotateX(x) * Mat4::RotateY(y) * Mat4::RotateZ(z));&#xD;&#xA;        &#xD;&#xA;        for(auto&amp; child : joint-&gt;Children)&#xD;&#xA;        {&#xD;&#xA;            vec3 end = local * vec3(child.joint_offset[0], child.joint_offset[1], child.joint_offset[2]);&#xD;&#xA;        	drawCylinder(viewMatrix, jointPos, end);&#xD;&#xA;        &#xD;&#xA;            drawJoint(viewMatrix, localMatrix, &amp;child, scale, frame);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://pastebin.com/4w2Qv5TD&#xD;&#xA;  [2]: https://i.stack.imgur.com/1UGte.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="42350" PostHistoryTypeId="50" PostId="13262" RevisionGUID="c6f85ea7-f6c4-4a36-b1e6-e774af36944a" CreationDate="2023-12-02T19:03:40.447" UserId="-1" />
  <row Id="42351" PostHistoryTypeId="50" PostId="10748" RevisionGUID="00d82217-00ab-40d3-a5d0-4a5cff78c055" CreationDate="2023-12-02T20:01:15.127" UserId="-1" />
  <row Id="42357" PostHistoryTypeId="50" PostId="12746" RevisionGUID="1ab8676d-863c-4f57-a26f-eafc202dcf60" CreationDate="2023-12-04T10:06:30.790" UserId="-1" />
  <row Id="42358" PostHistoryTypeId="50" PostId="2146" RevisionGUID="8348bc2e-cd84-4740-8033-d9b7c9738757" CreationDate="2023-12-04T12:08:10.973" UserId="-1" />
  <row Id="42359" PostHistoryTypeId="50" PostId="11048" RevisionGUID="8ffa182d-84c8-4598-af8c-62b4a1ae8503" CreationDate="2023-12-04T19:06:50.780" UserId="-1" />
  <row Id="42360" PostHistoryTypeId="50" PostId="11049" RevisionGUID="ccf41da5-0a2d-4cb5-92a9-7ca5e0e25719" CreationDate="2023-12-04T21:07:10.823" UserId="-1" />
  <row Id="42361" PostHistoryTypeId="5" PostId="13830" RevisionGUID="83aeb8c1-688c-4101-a9a7-cca4cd7dff70" CreationDate="2023-12-05T02:22:33.950" UserId="20888" Comment="added 122 characters in body" Text="So as @Thomas mentioned, the issue seems to be the fact that I was passing &quot;GL_LINE_STRIP&quot; instead of &quot;GL_LINE_STRIP_ADJACENCY&quot; to the glDrawArrays() call. Apparently, &quot;GL_LINE_STRIP_ADJACENCY is needed when there is a geometry shader involved (&quot;https://www.khronos.org/opengl/wiki/Primitive#Adjacency_primitives&quot;).&#xD;&#xA;&#xD;&#xA;Edit: Originally I meant to use &quot;GL_LINES_ADJACENCY&quot; and somehow got mixed up with &quot;GL_LINE_STRIP&quot;. Don't code at 5am." ContentLicense="CC BY-SA 4.0" />
  <row Id="42362" PostHistoryTypeId="2" PostId="13840" RevisionGUID="b18d32a0-e692-4351-8a7d-38c8e7fd07e8" CreationDate="2023-12-05T18:06:49.373" UserId="20931" Text="The effect I'm trying to achieve is to have it so that the texture is pixilated/quantized, but the &quot;grid,&quot; stays aligned to world coordinates even as the object with it's own UV coordinates moves around. &#xD;&#xA;&#xD;&#xA;The closest I've gotten is the following psuedocode, which at least should give kind of an idea of what I'm after (though I can't get the grid to actually stay still like I want). &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float DIVISIONS = 16.0;&#xD;&#xA;vec3 coords = UV + world_position;&#xD;&#xA;&#xD;&#xA;//quantize&#xD;&#xA;coords = floor(coords * DIV) / DIV;&#xD;&#xA;&#xD;&#xA;OUT_COLOR = coords - world_position;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;In my own head it's scratching the area right between &quot;this likely isn't possible,&quot; and &quot;this feels like it should be solvable with some math,&quot; but I just can't seem to get the right equation down.  " ContentLicense="CC BY-SA 4.0" />
  <row Id="42364" PostHistoryTypeId="1" PostId="13840" RevisionGUID="b18d32a0-e692-4351-8a7d-38c8e7fd07e8" CreationDate="2023-12-05T18:06:49.373" UserId="20931" Text="Pixilate/Quantize UV coordinates in world space?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42365" PostHistoryTypeId="3" PostId="13840" RevisionGUID="b18d32a0-e692-4351-8a7d-38c8e7fd07e8" CreationDate="2023-12-05T18:06:49.373" UserId="20931" Text="|shader|mathematics|fragment-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42366" PostHistoryTypeId="2" PostId="13841" RevisionGUID="84e38f94-0099-4247-a5cc-8ff3aa715fb8" CreationDate="2023-12-05T22:50:48.090" UserId="19939" Text="I am currently studying the basics of photometry to better understand the rendering equation of Kajiya. One thing I'm currently struggling with is Lambert's cosine law.&#xD;&#xA;&#xD;&#xA;Let's go over the premises:&#xD;&#xA; - A lambertian surface scatters light evenly in all directions.&#xD;&#xA; - The projected surface area decreases with the cosine of the viewing angle.&#xD;&#xA;&#xD;&#xA;For the luminous intensity from a viewing angle $I_\theta$ I have the following equation:&#xD;&#xA;$$I_\theta = I_0 \cdot cos(\theta).$$&#xD;&#xA;My question is: why should the luminous intensity be decreasing with the angle if I can still see the whole surface? If the light is scattering evenly in every direction, as was the premise for a lambertian surface, why should the projected surface area matter at all. Shouldn't I still recieve the same amount of light, but only in a more concentrated beam?&#xD;&#xA;&#xD;&#xA;Thank's in advance to anyone who can help me get out of my confision, which I've been stuck in for the whole last week." ContentLicense="CC BY-SA 4.0" />
  <row Id="42368" PostHistoryTypeId="1" PostId="13841" RevisionGUID="84e38f94-0099-4247-a5cc-8ff3aa715fb8" CreationDate="2023-12-05T22:50:48.090" UserId="19939" Text="Lambertian surface and the luminous intensity" ContentLicense="CC BY-SA 4.0" />
  <row Id="42369" PostHistoryTypeId="3" PostId="13841" RevisionGUID="84e38f94-0099-4247-a5cc-8ff3aa715fb8" CreationDate="2023-12-05T22:50:48.090" UserId="19939" Text="|raytracing|rendering|brdf|light|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42371" PostHistoryTypeId="2" PostId="13842" RevisionGUID="63b6937f-8206-4fee-be75-4ebb0d999f3b" CreationDate="2023-12-07T23:39:26.497" UserId="445" Text="I'm not particularly educated in the formal theory of rendering / optics, so I may have something wrong, but I think I can identify the problem here:&#xD;&#xA;&#xD;&#xA;&gt;  why should the luminous intensity be decreasing with the angle if I can still see the whole surface?&#xD;&#xA;&#xD;&#xA;You're mixing up different cases (one of which must not be what was meant) and getting a contradiction.&#xD;&#xA;&#xD;&#xA;For concreteness, Imagine you're looking at an illuminated Lambertian disk, at some angle, against a black or unlit background. The image your eye or camera receives is of an ellipse (rotated disk) whose area is proportional to the cosine of the angle:&#xD;&#xA;&#xD;&#xA;[![White ellipse on black background][1]][1]&#xD;&#xA;&#xD;&#xA;Now let's consider _what you're integrating over_ — that is, what counts as part of the thing you want to measure the luminous intensity of.&#xD;&#xA;&#xD;&#xA;1. Suppose you integrate over this entire field of view (or any field of view that contains the entire disk). In that case, the luminous intensity, the _[luminous flux](https://en.wikipedia.org/wiki/Luminous_flux) per solid angle,_ must be decreasing as the rotation angle increases, because there is less lit surface (of constant luminance) and more black _within the solid angle we are considering._ The proportion of the integral's value contributed by the lit surface's luminance is lesser.&#xD;&#xA;&#xD;&#xA;    This is the case that the cosine law is written for, I think.&#xD;&#xA;&#xD;&#xA;2. Suppose you integrate over the projected area of the disk. In that case, you can compute a luminous intensity that is indeed constant, but the _area over which it applies_ is decreasing with the rotation angle, so anything that _uses_ that luminous intensity value to produce an image will be decreasing its contribution to the image.&#xD;&#xA;&#xD;&#xA;3. Suppose you integrate over a solid angle that that is much smaller than the disk — like one image pixel — but still entirely covered by the disk. Then again the luminous intensity is constant, but “you can see the whole surface” is false because the pixel only sees a part of the disk.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/C0Vsu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42373" PostHistoryTypeId="2" PostId="13843" RevisionGUID="7d6e5262-05fd-4056-aa45-e0b9a6bf90eb" CreationDate="2023-12-08T12:55:11.067" UserId="13273" Text="I found an implementation of the Triangular Gregory Patch [here][1] on CGSE. Their question is about the normal vectors, which I don't need at the moment because I only need the geometry&#xD;&#xA;I was thinking of trying the code on the CPU to test the algorithm, but it seems that the control points (p400, p310, p220...,p004) in the tessellation control shader are calculated incorrectly.&#xD;&#xA;&#xD;&#xA;    Vector3D p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz();&#xD;&#xA;    Vector3D n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;    const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;    Vector3D edge = gl_in[nextInvID].gl_Position.xyz() - p0;&#xD;&#xA;    Vector3D nNext = vertOut[nextInvID].normal;&#xD;&#xA;    float d = edge.length();&#xD;&#xA;    float a = n.dot(nNext);&#xD;&#xA;    Vector3D gama = edge / d;&#xD;&#xA;    float a0 = n.dot(gama);&#xD;&#xA;    float a1 = nNext.dot(gama);&#xD;&#xA;    float ro = 6.0 * (2.0 * a0 + a * a1) / (4.0 - a * a);&#xD;&#xA;    float sigma = 6.0 * (2.0 * a1 + a * a0) / (4.0 - a * a);&#xD;&#xA;&#xD;&#xA;    Vector3D v[4];&#xD;&#xA;    v[0] = p0;&#xD;&#xA;    v[1] = p0 + (gama * 6.0 - n * ro * 2.0 + nNext * sigma) * (d / 18.0);&#xD;&#xA;    v[2] = gl_in[nextInvID].gl_Position.xyz() - (gama * 6.0 + n * ro - nNext * 2.0 * sigma) * (d / 18.0);&#xD;&#xA;    v[3] = gl_in[nextInvID].gl_Position.xyz();&#xD;&#xA;&#xD;&#xA;    edge = gl_in[nextInvID].gl_Position.xyz();&#xD;&#xA;&#xD;&#xA;    Vector3D w[3];&#xD;&#xA;    w[0] = v[1] - v[0];&#xD;&#xA;    w[1] = v[2] - v[1];&#xD;&#xA;    w[2] = v[3] - v[2];&#xD;&#xA;&#xD;&#xA;    Vector3D A[3];&#xD;&#xA;    A[0] = n.cross(w[0].normalized());&#xD;&#xA;    A[2] = nNext.cross(w[2].normalized());&#xD;&#xA;&#xD;&#xA;    A[1] = (A[0] + A[2]).normalized();&#xD;&#xA;&#xD;&#xA;    Vector3D l[5];&#xD;&#xA;    l[0] = v[0];&#xD;&#xA;    l[1] = (v[0] + v[1] * 3.0) * 0.25;&#xD;&#xA;    l[2] = (v[1] * 2.0 + v[2] * 2.0) * 0.25;&#xD;&#xA;    l[3] = (v[2] * 3.0 + v[3]) * 0.25;&#xD;&#xA;    l[4] = v[3];&#xD;&#xA;&#xD;&#xA;    Vector3D p1 = l[1];&#xD;&#xA;    Vector3D p2 = l[2];&#xD;&#xA;    Vector3D p3 = l[3];&#xD;&#xA;&#xD;&#xA;    tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;    tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;    tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;The points (p400... p004) can be found in: `tescOut[]`&#xD;&#xA;The coding is as follows:&#xD;&#xA;&#xD;&#xA;    p400  = tescOut[0].p0&#xD;&#xA;    p310  = tescOut[0].p1&#xD;&#xA;    p220  = tescOut[0].p2&#xD;&#xA;    p130  = tescOut[0].p3&#xD;&#xA;    G01   = tescOut[0].g0&#xD;&#xA;    G02   = tescOut[0].g1&#xD;&#xA;    p040  = tescOut[1].p0&#xD;&#xA;    p031  = tescOut[1].p1&#xD;&#xA;    p022  = tescOut[1].p2&#xD;&#xA;    p013  = tescOut[1].p3&#xD;&#xA;    G11   = tescOut[1].g0&#xD;&#xA;    G12   = tescOut[1].g1&#xD;&#xA;    p004  = tescOut[2].p0&#xD;&#xA;    p103  = tescOut[2].p1&#xD;&#xA;    p202  = tescOut[2].p2&#xD;&#xA;    p301  = tescOut[2].p3&#xD;&#xA;    G21   = tescOut[2].g0&#xD;&#xA;    G22   = tescOut[2].g1&#xD;&#xA;&#xD;&#xA;**Applying this algorithm an a cube with shared normals:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 1:** *Left:* The input cube with 8 vertices. The 12 triangles share these vertices. Hence the normal vectors pointing away from the origin of the cube. *Right:* The marked points (p400,...,p004) of all 12 triangles.&#xD;&#xA;&#xD;&#xA;As this is very confusing, I have only applied the algorithm to one of the triangles:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Figure 2:** A triangle from the cube with its points (p400,...,p004).&#xD;&#xA;&#xD;&#xA;Initially, it is not visible in this one image: The points that belong to the same edge all lie in a plane that is spanned by the vertex normals of the two corners. This is correct.&#xD;&#xA;&#xD;&#xA;But: To me, the scale of the points looks wrong. They seem to be too far away from each other.&#xD;&#xA;&#xD;&#xA;does anyone have any ideas on how to fix this?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/9317/how-to-compute-normal-in-quartic-walton-meeks-gregory-patch-in-tessellation-sha&#xD;&#xA;  [2]: https://i.stack.imgur.com/T0nRG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PFruD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42375" PostHistoryTypeId="1" PostId="13843" RevisionGUID="7d6e5262-05fd-4056-aa45-e0b9a6bf90eb" CreationDate="2023-12-08T12:55:11.067" UserId="13273" Text="Triangular Gregory patch" ContentLicense="CC BY-SA 4.0" />
  <row Id="42376" PostHistoryTypeId="3" PostId="13843" RevisionGUID="7d6e5262-05fd-4056-aa45-e0b9a6bf90eb" CreationDate="2023-12-08T12:55:11.067" UserId="13273" Text="|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42377" PostHistoryTypeId="5" PostId="13843" RevisionGUID="b30a26d4-3d8a-4084-969e-0f3c1222080a" CreationDate="2023-12-08T13:05:56.663" UserId="13273" Comment="added 231 characters in body" Text="I found an implementation of the Triangular Gregory Patch [here][1] on CGSE. Their question is about the normal vectors, which I don't need at the moment because I only need the geometry&#xD;&#xA;I was thinking of trying the code on the CPU to test the algorithm, but it seems that the control points (p400, p310, p220...,p004) in the tessellation control shader are calculated incorrectly.&#xD;&#xA;&#xD;&#xA;    Vector3D p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz();&#xD;&#xA;    Vector3D n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;    const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;    Vector3D edge = gl_in[nextInvID].gl_Position.xyz() - p0;&#xD;&#xA;    Vector3D nNext = vertOut[nextInvID].normal;&#xD;&#xA;    float d = edge.length();&#xD;&#xA;    float a = n.dot(nNext);&#xD;&#xA;    Vector3D gama = edge / d;&#xD;&#xA;    float a0 = n.dot(gama);&#xD;&#xA;    float a1 = nNext.dot(gama);&#xD;&#xA;    float ro = 6.0 * (2.0 * a0 + a * a1) / (4.0 - a * a);&#xD;&#xA;    float sigma = 6.0 * (2.0 * a1 + a * a0) / (4.0 - a * a);&#xD;&#xA;&#xD;&#xA;    Vector3D v[4];&#xD;&#xA;    v[0] = p0;&#xD;&#xA;    v[1] = p0 + (gama * 6.0 - n * ro * 2.0 + nNext * sigma) * (d / 18.0);&#xD;&#xA;    v[2] = gl_in[nextInvID].gl_Position.xyz() - (gama * 6.0 + n * ro - nNext * 2.0 * sigma) * (d / 18.0);&#xD;&#xA;    v[3] = gl_in[nextInvID].gl_Position.xyz();&#xD;&#xA;&#xD;&#xA;    edge = gl_in[nextInvID].gl_Position.xyz();&#xD;&#xA;&#xD;&#xA;    Vector3D w[3];&#xD;&#xA;    w[0] = v[1] - v[0];&#xD;&#xA;    w[1] = v[2] - v[1];&#xD;&#xA;    w[2] = v[3] - v[2];&#xD;&#xA;&#xD;&#xA;    Vector3D A[3];&#xD;&#xA;    A[0] = n.cross(w[0].normalized());&#xD;&#xA;    A[2] = nNext.cross(w[2].normalized());&#xD;&#xA;&#xD;&#xA;    A[1] = (A[0] + A[2]).normalized();&#xD;&#xA;&#xD;&#xA;    Vector3D l[5];&#xD;&#xA;    l[0] = v[0];&#xD;&#xA;    l[1] = (v[0] + v[1] * 3.0) * 0.25;&#xD;&#xA;    l[2] = (v[1] * 2.0 + v[2] * 2.0) * 0.25;&#xD;&#xA;    l[3] = (v[2] * 3.0 + v[3]) * 0.25;&#xD;&#xA;    l[4] = v[3];&#xD;&#xA;&#xD;&#xA;    Vector3D p1 = l[1];&#xD;&#xA;    Vector3D p2 = l[2];&#xD;&#xA;    Vector3D p3 = l[3];&#xD;&#xA;&#xD;&#xA;    tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;    tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;    tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;The input parameters are:&#xD;&#xA;`gl_in[gl_InvocationID].gl_Position` in there is the vertex position in model space.&#xD;&#xA;`vertOut[nextInvID].normal` in there is the vertex normal in model space (the normal is already normalized).&#xD;&#xA;&#xD;&#xA;The output: points (p400... p004) can be found in `tescOut[]`.&#xD;&#xA;The coding is as follows:&#xD;&#xA;&#xD;&#xA;    p400  = tescOut[0].p0&#xD;&#xA;    p310  = tescOut[0].p1&#xD;&#xA;    p220  = tescOut[0].p2&#xD;&#xA;    p130  = tescOut[0].p3&#xD;&#xA;    G01   = tescOut[0].g0&#xD;&#xA;    G02   = tescOut[0].g1&#xD;&#xA;    p040  = tescOut[1].p0&#xD;&#xA;    p031  = tescOut[1].p1&#xD;&#xA;    p022  = tescOut[1].p2&#xD;&#xA;    p013  = tescOut[1].p3&#xD;&#xA;    G11   = tescOut[1].g0&#xD;&#xA;    G12   = tescOut[1].g1&#xD;&#xA;    p004  = tescOut[2].p0&#xD;&#xA;    p103  = tescOut[2].p1&#xD;&#xA;    p202  = tescOut[2].p2&#xD;&#xA;    p301  = tescOut[2].p3&#xD;&#xA;    G21   = tescOut[2].g0&#xD;&#xA;    G22   = tescOut[2].g1&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Applying this algorithm an a cube with shared normals:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 1:** *Left:* The input cube with 8 vertices. The 12 triangles share these vertices. Hence the normal vectors pointing away from the origin of the cube. *Right:* The marked points (p400,...,p004) of all 12 triangles.&#xD;&#xA;&#xD;&#xA;As this is very confusing, I have only applied the algorithm to one of the triangles:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Figure 2:** A triangle from the cube with its points (p400,...,p004).&#xD;&#xA;&#xD;&#xA;Initially, it is not visible in this one image: The points that belong to the same edge all lie in a plane that is spanned by the vertex normals of the two corners. This is correct.&#xD;&#xA;&#xD;&#xA;But: To me, the scale of the points looks wrong. They seem to be too far away from each other.&#xD;&#xA;&#xD;&#xA;does anyone have any ideas on how to fix this?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/9317/how-to-compute-normal-in-quartic-walton-meeks-gregory-patch-in-tessellation-sha&#xD;&#xA;  [2]: https://i.stack.imgur.com/T0nRG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PFruD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42378" PostHistoryTypeId="5" PostId="13843" RevisionGUID="48419a62-a86b-4d7c-bfa4-3a659bc8f25a" CreationDate="2023-12-08T15:35:48.067" UserId="13273" Comment="deleted 160 characters in body" Text="I found an implementation of the Triangular Gregory Patch [here][1] on CGSE. Their question is about the normal vectors, which I don't need at the moment because I only need the geometry&#xD;&#xA;I was thinking of trying the code on the CPU to test the algorithm, but it seems that the control points (p400, p310, p220...,p004) in the tessellation control shader are calculated incorrectly.&#xD;&#xA;&#xD;&#xA;    Vector3D p0 = tescOut[gl_InvocationID].p0 = gl_in[gl_InvocationID].gl_Position.xyz();&#xD;&#xA;    Vector3D n = tescOut[gl_InvocationID].n = vertOut[gl_InvocationID].normal;&#xD;&#xA;&#xD;&#xA;    const int nextInvID = gl_InvocationID &lt; 2 ? gl_InvocationID + 1 : 0;&#xD;&#xA;    Vector3D edge = gl_in[nextInvID].gl_Position.xyz() - p0;&#xD;&#xA;    Vector3D nNext = vertOut[nextInvID].normal;&#xD;&#xA;    float d = edge.length();&#xD;&#xA;    float a = n.dot(nNext);&#xD;&#xA;    Vector3D gama = edge / d;&#xD;&#xA;    float a0 = n.dot(gama);&#xD;&#xA;    float a1 = nNext.dot(gama);&#xD;&#xA;    float ro = 6.0 * (2.0 * a0 + a * a1) / (4.0 - a * a);&#xD;&#xA;    float sigma = 6.0 * (2.0 * a1 + a * a0) / (4.0 - a * a);&#xD;&#xA;&#xD;&#xA;    Vector3D v[4];&#xD;&#xA;    v[0] = p0;&#xD;&#xA;    v[1] = p0 + (gama * 6.0 - n * ro * 2.0 + nNext * sigma) * (d / 18.0);&#xD;&#xA;    v[2] = gl_in[nextInvID].gl_Position.xyz() - (gama * 6.0 + n * ro - nNext * 2.0 * sigma) * (d / 18.0);&#xD;&#xA;    v[3] = gl_in[nextInvID].gl_Position.xyz();&#xD;&#xA;&#xD;&#xA;    edge = gl_in[nextInvID].gl_Position.xyz();&#xD;&#xA;&#xD;&#xA;    Vector3D w[3];&#xD;&#xA;    w[0] = v[1] - v[0];&#xD;&#xA;    w[1] = v[2] - v[1];&#xD;&#xA;    w[2] = v[3] - v[2];&#xD;&#xA;&#xD;&#xA;    Vector3D A[3];&#xD;&#xA;    A[0] = n.cross(w[0].normalized());&#xD;&#xA;    A[2] = nNext.cross(w[2].normalized());&#xD;&#xA;&#xD;&#xA;    A[1] = (A[0] + A[2]).normalized();&#xD;&#xA;&#xD;&#xA;    Vector3D l[5];&#xD;&#xA;    l[0] = v[0];&#xD;&#xA;    l[1] = (v[0] + v[1] * 3.0) * 0.25;&#xD;&#xA;    l[2] = (v[1] * 2.0 + v[2] * 2.0) * 0.25;&#xD;&#xA;    l[3] = (v[2] * 3.0 + v[3]) * 0.25;&#xD;&#xA;    l[4] = v[3];&#xD;&#xA;&#xD;&#xA;    Vector3D p1 = l[1];&#xD;&#xA;    Vector3D p2 = l[2];&#xD;&#xA;    Vector3D p3 = l[3];&#xD;&#xA;&#xD;&#xA;    tescOut[gl_InvocationID].p1 = l[1];&#xD;&#xA;    tescOut[gl_InvocationID].p2 = l[2];&#xD;&#xA;    tescOut[gl_InvocationID].p3 = l[3];&#xD;&#xA;&#xD;&#xA;The input parameters are:&#xD;&#xA;`gl_in[gl_InvocationID].gl_Position` in there is the vertex position in model space.&#xD;&#xA;`vertOut[nextInvID].normal` in there is the vertex normal in model space (the normal is already normalized).&#xD;&#xA;&#xD;&#xA;The output: points (p400... p004) can be found in `tescOut[]`.&#xD;&#xA;The coding is as follows:&#xD;&#xA;&#xD;&#xA;    p400  = tescOut[0].p0&#xD;&#xA;    p310  = tescOut[0].p1&#xD;&#xA;    p220  = tescOut[0].p2&#xD;&#xA;    p130  = tescOut[0].p3&#xD;&#xA;    p040  = tescOut[1].p0&#xD;&#xA;    p031  = tescOut[1].p1&#xD;&#xA;    p022  = tescOut[1].p2&#xD;&#xA;    p013  = tescOut[1].p3&#xD;&#xA;    p004  = tescOut[2].p0&#xD;&#xA;    p103  = tescOut[2].p1&#xD;&#xA;    p202  = tescOut[2].p2&#xD;&#xA;    p301  = tescOut[2].p3&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**Applying this algorithm an a cube with shared normals:**&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;**Figure 1:** *Left:* The input cube with 8 vertices. The 12 triangles share these vertices. Hence the normal vectors pointing away from the origin of the cube. *Right:* The marked points (p400,...,p004) of all 12 triangles.&#xD;&#xA;&#xD;&#xA;As this is very confusing, I have only applied the algorithm to one of the triangles:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;**Figure 2:** A triangle from the cube with its points (p400,...,p004).&#xD;&#xA;&#xD;&#xA;Initially, it is not visible in this one image: The points that belong to the same edge all lie in a plane that is spanned by the vertex normals of the two corners. This is correct.&#xD;&#xA;&#xD;&#xA;But: To me, the scale of the points looks wrong. They seem to be too far away from each other.&#xD;&#xA;&#xD;&#xA;does anyone have any ideas on how to fix this?&#xD;&#xA;&#xD;&#xA;  [1]: https://computergraphics.stackexchange.com/questions/9317/how-to-compute-normal-in-quartic-walton-meeks-gregory-patch-in-tessellation-sha&#xD;&#xA;  [2]: https://i.stack.imgur.com/T0nRG.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PFruD.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42383" PostHistoryTypeId="50" PostId="9199" RevisionGUID="c2dfe182-7fac-4c0d-b141-5a1f948ae693" CreationDate="2023-12-09T15:03:15.380" UserId="-1" />
  <row Id="42384" PostHistoryTypeId="5" PostId="13840" RevisionGUID="4eb8a3b9-e9f5-4d54-b145-35dc97375dd0" CreationDate="2023-12-09T22:26:38.123" UserId="20931" Comment="added link" Text="The effect I'm trying to achieve is to have it so that the texture is pixilated/quantized, but the &quot;grid,&quot; stays aligned to world coordinates even as the object with it's own UV coordinates moves around. &#xD;&#xA;&#xD;&#xA;The closest I've gotten is the following psuedocode, which at least should give kind of an idea of what I'm after (though I can't get the grid to actually stay still like I want). &#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;float DIVISIONS = 16.0;&#xD;&#xA;vec3 coords = UV + world_position;&#xD;&#xA;&#xD;&#xA;//quantize&#xD;&#xA;coords = floor(coords * DIV) / DIV;&#xD;&#xA;&#xD;&#xA;OUT_COLOR = coords - world_position;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;In my own head it's scratching the area right between &quot;this likely isn't possible,&quot; and &quot;this feels like it should be solvable with some math,&quot; but I just can't seem to get the right equation down. &#xD;&#xA;&#xD;&#xA;EDIT: Here is a video demonstration made using some compositing effects of roughly what I'm trying to acheive (though not perfect) https://youtu.be/eFJIG47Wp_E" ContentLicense="CC BY-SA 4.0" />
  <row Id="42385" PostHistoryTypeId="5" PostId="13842" RevisionGUID="26fef440-a0bb-46a0-b476-a1ed1ed7668e" CreationDate="2023-12-11T01:11:51.563" UserId="445" Comment="typo" Text="I'm not particularly educated in the formal theory of rendering / optics, so I may have something wrong, but I think I can identify the problem here:&#xD;&#xA;&#xD;&#xA;&gt;  why should the luminous intensity be decreasing with the angle if I can still see the whole surface?&#xD;&#xA;&#xD;&#xA;You're mixing up different cases (one of which must not be what was meant) and getting a contradiction.&#xD;&#xA;&#xD;&#xA;For concreteness, imagine you're looking at an illuminated Lambertian disk, at some angle, against a black or unlit background. The image your eye or camera receives is of an ellipse (rotated disk) whose area is proportional to the cosine of the angle:&#xD;&#xA;&#xD;&#xA;[![White ellipse on black background][1]][1]&#xD;&#xA;&#xD;&#xA;Now let's consider _what you're integrating over_ — that is, what counts as part of the thing you want to measure the luminous intensity of.&#xD;&#xA;&#xD;&#xA;1. Suppose you integrate over this entire field of view (or any field of view that contains the entire disk). In that case, the luminous intensity, the _[luminous flux](https://en.wikipedia.org/wiki/Luminous_flux) per solid angle,_ must be decreasing as the rotation angle increases, because there is less lit surface (of constant luminance) and more black _within the solid angle we are considering._ The proportion of the integral's value contributed by the lit surface's luminance is lesser.&#xD;&#xA;&#xD;&#xA;    This is the case that the cosine law is written for, I think.&#xD;&#xA;&#xD;&#xA;2. Suppose you integrate over the projected area of the disk. In that case, you can compute a luminous intensity that is indeed constant, but the _area over which it applies_ is decreasing with the rotation angle, so anything that _uses_ that luminous intensity value to produce an image will be decreasing its contribution to the image.&#xD;&#xA;&#xD;&#xA;3. Suppose you integrate over a solid angle that that is much smaller than the disk — like one image pixel — but still entirely covered by the disk. Then again the luminous intensity is constant, but “you can see the whole surface” is false because the pixel only sees a part of the disk.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/C0Vsu.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42386" PostHistoryTypeId="2" PostId="13845" RevisionGUID="7059476f-aba3-4cba-9db4-f913a39733f1" CreationDate="2023-12-11T21:33:29.463" UserId="20956" Text="I am using a Linux VM with 16 MB of Video Memory, so I am resorting to Assembly to create the graphics of my game by interacting with the GPU through its registers, but I don't know any of the registers." ContentLicense="CC BY-SA 4.0" />
  <row Id="42388" PostHistoryTypeId="1" PostId="13845" RevisionGUID="7059476f-aba3-4cba-9db4-f913a39733f1" CreationDate="2023-12-11T21:33:29.463" UserId="20956" Text="What are all of the registers inside the GPU called?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42389" PostHistoryTypeId="3" PostId="13845" RevisionGUID="7059476f-aba3-4cba-9db4-f913a39733f1" CreationDate="2023-12-11T21:33:29.463" UserId="20956" Text="|texture|gpu|assembly|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42390" PostHistoryTypeId="6" PostId="13845" RevisionGUID="f88e0ce4-7d28-4f96-9c54-b4127306c268" CreationDate="2023-12-11T21:35:29.097" UserId="20956" Comment="edited tags" Text="|gpu|assembly|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42391" PostHistoryTypeId="5" PostId="13845" RevisionGUID="9cbf625d-5bc2-4ab3-861d-295a288f4a85" CreationDate="2023-12-11T21:48:39.843" UserId="20956" Comment="deleted 87 characters in body" Text="I have a GeForce GTX 980 GPU and wanted to know their register names and what they do so I can code my game in NASM." ContentLicense="CC BY-SA 4.0" />
  <row Id="42392" PostHistoryTypeId="5" PostId="13845" RevisionGUID="cd5f8307-672f-49bb-bef8-9fd9dccdefeb" CreationDate="2023-12-11T23:31:55.787" UserId="20956" Comment="added 141 characters in body" Text="I have a GeForce GTX 980 GPU and wanted to know their register names and what they do so I can code my game in NASM for the physics, logic and communicating with the GPU Assembler. However, I haven't thought about the GPU Assembler and wanted help with one." ContentLicense="CC BY-SA 4.0" />
  <row Id="42393" PostHistoryTypeId="2" PostId="13846" RevisionGUID="8de69c30-130c-43e5-8d42-46f89d1b4b98" CreationDate="2023-12-13T10:45:46.850" UserId="13273" Text="I have rendered an image with 32bit float color channels and want to simulate the smear effect of a CCD sensor (see figure 1).&#xD;&#xA;&#xD;&#xA;[![Enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Image of a light source. Here the full-well capacities of the pixels are oversaturated. Therefore, the charge has jumped to neighboring pixels. Since the vertical pixels of a CCD sensor are connected to each other, the charge flow is vertical. Whenever a pixel is fully saturated, the overcharge iteratively jumps to neighboring pixels.&#xD;&#xA;&#xD;&#xA;In principle, each pixel is a bucket and each photon is a drop of water. When the bucket is full, the water flows into the neighboring bucket until it is also full and so on... The smear ends as soon as the excess overload has been accommodated in neighboring buckets. This is why this effect ends directly without fading.&#xD;&#xA;&#xD;&#xA;I am looking for an algorithm that can calculate the saturation shift of a column in parallel. The problem is that the rendered image does not look like the image in the example. The rendered image has a natural environment with a light source that is larger than one pixel. This means that the buckets are partially filled from the start and not only one pixel is over saturated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What I did already:**&#xD;&#xA;&#xD;&#xA;I've been thinking a lot about how to quickly check if a column of pixels is fully saturated:&#xD;&#xA;Each pixel within the column can perform an atomicAdd operation on an SSBO variable. With this information, we can easily check whether the entire column is fully saturated: &#xD;&#xA;&#xD;&#xA;    bool columnIsFullySaturated = atomicCounter &gt;= countPixelInColumn * fullWellCapacity&#xD;&#xA;&#xD;&#xA;If `columnIsFullySaturated` is true, we can simply set all pixels to 100% saturated. If not, we need to do further checks. We can also add a second SSBO variable to store the number of pixels that are oversaturated. If this number is zero, we do not need to make any further changes for this column. If this number is greater than zero, we need a parallel algorithm to distribute the oversaturation to the neighboring cells.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have an algorithm in mind where each pixel is calculated by a compute shader call. A workgroup is created for each column. It looks like this:&#xD;&#xA;&#xD;&#xA;    shared int32 saturation[columnSize]; // here the saturation is stored&#xD;&#xA;    shared bool isOversaturated = true; // some helper variable to check for a termination&#xD;&#xA;&#xD;&#xA;    //load values to shared memory&#xD;&#xA;    saturation[gl_localInvocationID.y] = texture(tex, coord).r;&#xD;&#xA;&#xD;&#xA;    atomicAdd(atomicCounter , saturation[gl_localInvocationID.y]);&#xD;&#xA;&#xD;&#xA;    barrier();    &#xD;&#xA;&#xD;&#xA;    bool columnIsFullySaturated = atomicCounter &gt;= countPixelInColumn * fullWellCapacity&#xD;&#xA;&#xD;&#xA;    if(columnIsFullySaturated) // set all to 100% saturated&#xD;&#xA;    {&#xD;&#xA;        saturation[gl_localInvocationID.y] = fullWellCapacity;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;    if(atomicCounterHasOverSaturation == 0) // keep it as it is&#xD;&#xA;    {&#xD;&#xA;        return; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //this is the else part (we need to manage the over saturation)&#xD;&#xA;&#xD;&#xA;    do&#xD;&#xA;    {&#xD;&#xA;        //check both neighbors and exchange over load to the lower saturation neighbor. By atomicAdd operation&#xD;&#xA;        isOversaturated = false;&#xD;&#xA;        barrier();&#xD;&#xA;        isOversaturated |= saturation[gl_localInvocationID.y] &gt; fullWellCapacity;&#xD;&#xA;    }while(isOversaturated);&#xD;&#xA;&#xD;&#xA;With this algorithm, I have the problem that when the column is almost completely oversaturated, the cells shift the overcharge backwards and forwards... and that takes too long.&#xD;&#xA;I hope there is an algorithm that does this more analytically than just shifting each charge.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U0vYs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42395" PostHistoryTypeId="1" PostId="13846" RevisionGUID="8de69c30-130c-43e5-8d42-46f89d1b4b98" CreationDate="2023-12-13T10:45:46.850" UserId="13273" Text="CCD Sensor parallel implementation of Smear" ContentLicense="CC BY-SA 4.0" />
  <row Id="42396" PostHistoryTypeId="3" PostId="13846" RevisionGUID="8de69c30-130c-43e5-8d42-46f89d1b4b98" CreationDate="2023-12-13T10:45:46.850" UserId="13273" Text="|compute-shader|photo-realistic|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42397" PostHistoryTypeId="5" PostId="13846" RevisionGUID="571b6f1a-1915-4720-9378-858c385dd962" CreationDate="2023-12-13T12:22:38.787" UserId="13273" Comment="added 20 characters in body" Text="I have rendered an image with 32bit float color channels and want to simulate the smear effect of a CCD sensor (see figure 1).&#xD;&#xA;&#xD;&#xA;[![Enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure 1:** Image of a light source. Here the full-well capacities of the pixels are oversaturated. Therefore, the charge has jumped to neighboring pixels. Since the vertical pixels of a CCD sensor are connected to each other, the charge flow is vertical. Whenever a pixel is fully saturated, the overcharge iteratively jumps to neighboring pixels.&#xD;&#xA;&#xD;&#xA;In principle, each pixel is a bucket and each photon is a drop of water. When the bucket is full, the water flows into the neighboring bucket until it is also full and so on... The smear ends as soon as the excess overload has been accommodated in neighboring buckets. This is why this effect ends directly without fading.&#xD;&#xA;&#xD;&#xA;I am looking for an algorithm that can calculate the saturation shift of a column in parallel. The problem is that the rendered image does not look like the image in the example. The rendered image has a natural environment with a light source that is larger than one pixel. This means that the buckets are partially filled from the start and not only one pixel is over saturated.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;**What I did already:**&#xD;&#xA;&#xD;&#xA;I've been thinking a lot about how to quickly check if a column of pixels is fully saturated:&#xD;&#xA;Each pixel within the column can perform an atomicAdd operation on an SSBO variable. With this information, we can easily check whether the entire column is fully saturated: &#xD;&#xA;&#xD;&#xA;    bool columnIsFullySaturated = atomicCounter &gt;= countPixelInColumn * fullWellCapacity&#xD;&#xA;&#xD;&#xA;If `columnIsFullySaturated` is true, we can simply set all pixels to 100% saturated. If not, we need to do further checks. We can also add a second SSBO variable to store the number of pixels that are oversaturated. If this number is zero, we do not need to make any further changes for this column. If this number is greater than zero, we need a parallel algorithm to distribute the oversaturation to the neighboring cells.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;I have an algorithm in mind where each pixel is calculated by a compute shader call. A workgroup is created for each column. It looks like this:&#xD;&#xA;&#xD;&#xA;    shared int32 saturation[columnSize]; // here the saturation is stored&#xD;&#xA;    shared bool isOversaturated = true; // some helper variable to check for a termination&#xD;&#xA;&#xD;&#xA;    //load values to shared memory&#xD;&#xA;    saturation[gl_localInvocationID.y] = texture(tex, coord).r;&#xD;&#xA;&#xD;&#xA;    atomicAdd(atomicCounter , saturation[gl_localInvocationID.y]);&#xD;&#xA;&#xD;&#xA;    barrier();    &#xD;&#xA;&#xD;&#xA;    bool columnIsFullySaturated = atomicCounter &gt;= countPixelInColumn * fullWellCapacity&#xD;&#xA;&#xD;&#xA;    if(columnIsFullySaturated) // set all to 100% saturated&#xD;&#xA;    {&#xD;&#xA;        saturation[gl_localInvocationID.y] = fullWellCapacity;&#xD;&#xA;        return;&#xD;&#xA;    }&#xD;&#xA;    if(atomicCounterHasOverSaturation == 0) // keep it as it is&#xD;&#xA;    {&#xD;&#xA;        return; &#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //this is the else part (we need to manage the over saturation)&#xD;&#xA;&#xD;&#xA;    do&#xD;&#xA;    {&#xD;&#xA;        //check both neighbors and exchange over load to the lower saturation neighbor. By atomicAdd operation&#xD;&#xA;        isOversaturated = false;&#xD;&#xA;        barrier();&#xD;&#xA;        isOversaturated |= saturation[gl_localInvocationID.y] &gt; fullWellCapacity;&#xD;&#xA;        barrier();&#xD;&#xA;    }while(isOversaturated);&#xD;&#xA;&#xD;&#xA;With this algorithm, I have the problem that when the column is almost completely oversaturated, the cells shift the overcharge backwards and forwards... and that takes too long.&#xD;&#xA;I hope there is an algorithm that does this more analytically than just shifting each charge.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/U0vYs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42398" PostHistoryTypeId="33" PostId="13726" RevisionGUID="9b35bd84-b5df-4d88-957b-1241dac907d6" CreationDate="2023-12-13T12:54:53.487" UserId="6" Comment="84" />
  <row Id="42399" PostHistoryTypeId="50" PostId="12853" RevisionGUID="1305a15e-2748-49df-84bc-1a31ce6382c1" CreationDate="2023-12-14T13:03:05.343" UserId="-1" />
  <row Id="42400" PostHistoryTypeId="50" PostId="8260" RevisionGUID="59a57efb-0a32-460c-bfb3-6a9ff6096616" CreationDate="2023-12-14T15:05:15.613" UserId="-1" />
  <row Id="42402" PostHistoryTypeId="2" PostId="13847" RevisionGUID="0475c85e-30d2-494d-bae9-673c248df3df" CreationDate="2023-12-15T02:35:18.170" UserId="20970" Text="I'm trying to implementing the paper &quot;[Deep Kernel Density Estimation for Photon Mapping][1]&quot;. One part that has me confused is when the authors describe their rendering algorithm as hybrid algorithm combining Path Tracing and Photon Mapping (with their neural network):&#xD;&#xA;&#xD;&#xA;&gt; Moreover, our experiments leverages an effective practical hybrid&#xD;&#xA;approach: using our method for reconstructing light-specular (LS)&#xD;&#xA;paths – the light transport paths that interact with specular surfaces&#xD;&#xA;before arriving at light sources—and low sample-count path tracing&#xD;&#xA;with learning-based denoising for all other light transport paths.&#xD;&#xA;This leverages the advantages of both MC denoising and our efficient&#xD;&#xA;photon density estimation technique.&#xD;&#xA;&#xD;&#xA;another section:&#xD;&#xA;&#xD;&#xA;&gt; Combining MC denoising and deep photon mapping. We evaluate&#xD;&#xA;our deep photon density estimation by combining our method&#xD;&#xA;with MC denoising. Specifically, we apply our learning-based density&#xD;&#xA;estimation to only compute the challenging light transport effects which involve LS paths that are extremely hard to trace in PT&#xD;&#xA;and likely to introduce caustics. In addition, we use path tracing&#xD;&#xA;with relatively low sample counts to compute the remaining light&#xD;&#xA;transport paths, and use modern learning-based denoising—the Optix&#xD;&#xA;built-in denoiser based on [CKS17]—to remove the MC noise.&#xD;&#xA;&#xD;&#xA; But there are not enough details about the way they combine them. Of course, I'm familiar with multiple importance sampling and the paper &quot;Vertex Connection and Merging&quot; but the way they describe it seems to be more about flipping a switch between them based on if they are rending caustics/SDS paths or not. I can't really imagine how to decide between them while rendering without MIS. But I also don't think they implemented VCM with the paper since it will severely hurt the performance which is one of the main parts of the evaluation.&#xD;&#xA;&#xD;&#xA;Any ideas on how this could be done?&#xD;&#xA;&#xD;&#xA;Thanks in advance!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://graphics.ucsd.edu/~henrik/papers/deep_photon_mapping.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42404" PostHistoryTypeId="1" PostId="13847" RevisionGUID="0475c85e-30d2-494d-bae9-673c248df3df" CreationDate="2023-12-15T02:35:18.170" UserId="20970" Text="Combining Path Tracing and Photon Mapping" ContentLicense="CC BY-SA 4.0" />
  <row Id="42405" PostHistoryTypeId="3" PostId="13847" RevisionGUID="0475c85e-30d2-494d-bae9-673c248df3df" CreationDate="2023-12-15T02:35:18.170" UserId="20970" Text="|pathtracing|implementation|photon-mapping|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42406" PostHistoryTypeId="50" PostId="13372" RevisionGUID="6603ceff-bc07-4837-8914-85b92a557fda" CreationDate="2023-12-15T13:03:26.913" UserId="-1" />
  <row Id="42407" PostHistoryTypeId="2" PostId="13848" RevisionGUID="654952d1-d4d3-4836-b40f-0948944f8fa8" CreationDate="2023-12-15T19:21:10.783" UserId="20973" Text="For example: I have an AMD graphics card, can I &quot;recreate&quot; Nvidia's OpenGL extensions? And vice versa?&#xD;&#xA;&#xD;&#xA;By &quot;recreate&quot; I mean to write my implementation in some way. In general, how critical is the loss of features due to vendor? Or is it not worth bothering about it at all?&#xD;&#xA;&#xD;&#xA;I apologize in advance if someone has already asked this question, or perhaps that it is silly and inappropriate" ContentLicense="CC BY-SA 4.0" />
  <row Id="42409" PostHistoryTypeId="1" PostId="13848" RevisionGUID="654952d1-d4d3-4836-b40f-0948944f8fa8" CreationDate="2023-12-15T19:21:10.783" UserId="20973" Text="Can I &quot;recreate&quot; vendor-specific OpenGL extensions?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42410" PostHistoryTypeId="3" PostId="13848" RevisionGUID="654952d1-d4d3-4836-b40f-0948944f8fa8" CreationDate="2023-12-15T19:21:10.783" UserId="20973" Text="|opengl|legacy-opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42413" PostHistoryTypeId="2" PostId="13849" RevisionGUID="8632a737-00cb-479e-b302-48d9255006a2" CreationDate="2023-12-17T10:19:07.953" UserId="20977" Text="In [this article][1] on Wikipedia, under saturation, it's written that &quot;The purest (most saturated) color is achieved by using just one wavelength at a high intensity, such as in laser light. If the intensity drops, then as a result the saturation drops&quot;&#xD;&#xA;&#xD;&#xA;I don't get the relation between light intensity and saturation. From what I know, saturation is the chromatic intensity for a given brightness or lightness, and is roughly related to the excitation purity of the light. In which case, just having a single wavelength or small band of wavelengths should render a color fully saturated. &#xD;&#xA;&#xD;&#xA;Looked into this in the book &quot;Color Appearance Models&quot; by Mark Fairchild, where I found: &quot;For given viewing conditions and at luminance levels within the range of photopic vision, a color stimulus of a given chromaticity exhibits approximately constant saturation for all luminance levels, except when brightness is very high.&quot;&#xD;&#xA;&#xD;&#xA;Am I missing something?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.m.wikipedia.org/wiki/Colorfulness" ContentLicense="CC BY-SA 4.0" />
  <row Id="42415" PostHistoryTypeId="1" PostId="13849" RevisionGUID="8632a737-00cb-479e-b302-48d9255006a2" CreationDate="2023-12-17T10:19:07.953" UserId="20977" Text="Is color saturation really related to light intensity?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42416" PostHistoryTypeId="3" PostId="13849" RevisionGUID="8632a737-00cb-479e-b302-48d9255006a2" CreationDate="2023-12-17T10:19:07.953" UserId="20977" Text="|color|color-science|color-management|colorspace|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42417" PostHistoryTypeId="5" PostId="9203" RevisionGUID="3eb7c1d3-7a7f-4699-aedf-f488a79c2f3f" CreationDate="2023-12-18T08:58:53.017" UserId="5349" Comment="original links are dead &amp; was not able to find them via wayback machine; subbed in links to author's personal web site" Text="It sounds like you want to know how to ray trace ***a bilinear surface patch***.&#xD;&#xA;&#xD;&#xA;A quick search [turned up this page][1] by Ramsey, Potter &amp; Hansen, which includes a [paper][2] and, probably better still, *source code*!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, if you just want a &quot;cheap and cheerful&quot; &lt;strike&gt;hack&lt;/strike&gt; approach, you could try replacing the quad with **4** triangles. That is, by a new vertex at the 'centre' (i.e. computing the average of the corners) and joining each edge to that new vertex. This is generally produces a better looking, and order-independent result than just using a pair of triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://shaunramsey.com/research/bp/&#xD;&#xA;  [2]: http://shaunramsey.com/research/bp/ramseybilinear.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42418" PostHistoryTypeId="24" PostId="9203" RevisionGUID="3eb7c1d3-7a7f-4699-aedf-f488a79c2f3f" CreationDate="2023-12-18T08:58:53.017" Comment="Proposed by 5349 approved by 209 edit id of 628" ContentLicense="CC BY-SA 4.0" />
  <row Id="42419" PostHistoryTypeId="2" PostId="13850" RevisionGUID="4f04ceae-9fde-496d-beb6-d9cceb7b35a3" CreationDate="2023-12-18T16:54:00.397" UserId="7952" Text="Extensions generally get compiler and driver support in order to take advantage of vendor specific hardware/software. The extensions can go out of &quot;style&quot; because they are replaced by something different, accepted and added to the GLSL specification and slightly change to be more general or a better fit for a wider range of hardware, some just don't get the industry traction the creators had hoped for, etc.&#xD;&#xA;&#xD;&#xA;But this doesn't mean they can't be *emulated*. Often the basic behavior can be emulated using modern GLSL code and extensions. But every extension will be different and some may not be doable.&#xD;&#xA;&#xD;&#xA;One other possibility is to get ahold of the open source drivers for the target hardware and edit the code to add the extension. " ContentLicense="CC BY-SA 4.0" />
  <row Id="42421" PostHistoryTypeId="50" PostId="13797" RevisionGUID="f8bbb79e-b11a-4391-84ba-b917ea9873f0" CreationDate="2023-12-18T20:04:10.503" UserId="-1" />
  <row Id="42422" PostHistoryTypeId="50" PostId="13377" RevisionGUID="2f27d64f-8a07-4101-8ab8-0d74bcce2387" CreationDate="2023-12-19T14:06:15.717" UserId="-1" />
  <row Id="42423" PostHistoryTypeId="2" PostId="13851" RevisionGUID="aeedc15e-43c9-409b-b20f-c8df9a36ecfa" CreationDate="2023-12-19T16:15:22.667" UserId="2654" Text="Most vendor-specific extensions (particularly those of more recent vintage) are based on the particular nature of that vendor's hardware. And even if some other vendor's hardware could do something similar, emulating that functionality without actually being part of the *driver* would be, if not impossible, then exceedingly inefficient.&#xD;&#xA;&#xD;&#xA;There may be specific cases where you might be able to implement something reasonably with a wrapper atop OpenGL, but most vendor extensions are too reliant on the specific internals of their hardware to make this viable.&#xD;&#xA;&#xD;&#xA;Consider NV_texture_barrier. It was technically an NVIDIA extension, but it was widely implemented by others before being standardized into ARB_texture_barrier. But the fact that it could be implemented by other vendors didn't mean that *you*, code outside of the driver, could implement it. The core aspect of the functionality *requires* direct access to the GPU. Calling `glTextureBarrierNV` causes caches to be cleared and other synchronization operations that are specific to each piece of hardware.&#xD;&#xA;&#xD;&#xA;That's not something you can do from outside of the driver." ContentLicense="CC BY-SA 4.0" />
  <row Id="42425" PostHistoryTypeId="2" PostId="13852" RevisionGUID="f65f2ea3-6296-40e3-9c24-2febbf2e05e3" CreationDate="2023-12-20T18:46:17.047" UserId="20919" Text="I've been working on adding HDR rendering, auto exposure, and tone-mapping to my rendering engine, following [this blog post](https://bruop.github.io/exposure/) for doing auto exposure and it sequel as well as a few side resources for tone mapping. I've gotten tone mapping to work, but not auto exposure, although I feel like I have a solid grasp of the &#xD;&#xA;concepts.&#xD;&#xA;&#xD;&#xA;First, let's start with my code. Here are the two shaders I'm using to calculate the average luminence:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;&#xD;&#xA;/////////// CALCULATE HISTOGRAM&#xD;&#xA;&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#define GROUP_SIZE 256&#xD;&#xA;&#xD;&#xA;#define EPSILON 0.005&#xD;&#xA;#define RGB_TO_LUM vec3(0.2125, 0.7154, 0.0721)&#xD;&#xA;&#xD;&#xA;uniform vec4 params;&#xD;&#xA;// params.x = minimum log_2 luminance&#xD;&#xA;// params.y = inverse of the log_2 luminance range&#xD;&#xA;&#xD;&#xA;layout (binding = 0, rgba16f) uniform image2D hdrImage;&#xD;&#xA;layout (binding = 1, std140) buffer Histogram {&#xD;&#xA;    uint histogram[256];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;shared uint histogramShared[GROUP_SIZE];&#xD;&#xA;&#xD;&#xA;uint colorToBin(vec3 hdrColor, float minLogLum, float inverseLogLumRange) {&#xD;&#xA;    float lum = dot(hdrColor, RGB_TO_LUM);&#xD;&#xA;&#xD;&#xA;    if (lum &lt; EPSILON) {&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float logLum = clamp((log2(lum) - minLogLum) * inverseLogLumRange, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;    return uint(logLum * 254.0 + 1.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 16, local_size_y = 16) in;&#xD;&#xA;void main() {&#xD;&#xA;    histogramShared[gl_LocalInvocationIndex] = 0;&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    uvec2 dim = imageSize(hdrImage).xy;&#xD;&#xA;&#xD;&#xA;    if (gl_GlobalInvocationID.x &lt; dim.x &amp;&amp; gl_GlobalInvocationID.y &lt; dim.y) {&#xD;&#xA;        vec3 hdrColor = imageLoad(hdrImage, ivec2(gl_GlobalInvocationID.xy)).xyz;&#xD;&#xA;        uint binIndex = colorToBin(hdrColor, params.x, params.y);&#xD;&#xA;&#xD;&#xA;        atomicAdd(histogramShared[binIndex], 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    atomicAdd(histogram[gl_LocalInvocationIndex], histogramShared[gl_LocalInvocationIndex]);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/////////// CALCULATE WEIGHTED AVERAGE&#xD;&#xA;&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#define GROUP_SIZE 256&#xD;&#xA;&#xD;&#xA;uniform vec4 params;&#xD;&#xA;// params.x = minLogLum&#xD;&#xA;// params.y = logLumRange&#xD;&#xA;// param.z = timeCoeff&#xD;&#xA;// param.w = numPixels&#xD;&#xA;&#xD;&#xA;layout (binding = 0, r16f) uniform image1D target;&#xD;&#xA;layout (binding = 1, std140) buffer Histogram {&#xD;&#xA;    uint histogram[256];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;shared uint histogramShared[GROUP_SIZE];&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 256, local_size_y = 1) in;&#xD;&#xA;void main() {&#xD;&#xA;    uint countForThisBin = histogram[gl_LocalInvocationIndex];&#xD;&#xA;    histogramShared[gl_LocalInvocationIndex] = countForThisBin * gl_LocalInvocationIndex;&#xD;&#xA;&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    histogram[gl_LocalInvocationIndex] = 0;&#xD;&#xA;&#xD;&#xA;    #pragma unroll&#xD;&#xA;    for (uint cutoff = (GROUP_SIZE &gt;&gt; 1); cutoff &gt; 0; cutoff &gt;&gt;= 1) {&#xD;&#xA;        if (uint(gl_LocalInvocationIndex) &lt; cutoff)&#xD;&#xA;            histogramShared[gl_LocalInvocationIndex] += histogramShared[gl_LocalInvocationIndex + cutoff];&#xD;&#xA;        barrier();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (gl_LocalInvocationIndex == 0) {&#xD;&#xA;        float weightedLogAverage = (histogramShared[0] / max(params.w - float(countForThisBin), 1.0)) - 1.0;&#xD;&#xA;        float weightedAvgLum = exp2(((weightedLogAverage / 254.0) * params.y) + params.x);&#xD;&#xA;        float lumLastFrame = imageLoad(target, 0).x;&#xD;&#xA;        float adaptedLum = lumLastFrame + (weightedAvgLum - lumLastFrame) * params.z;&#xD;&#xA;        imageStore(target, 0, vec4(adaptedLum, 0.0, 0.0, 0.0));&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As far as I can tell, these are functionally identical to the code samples from the blog, with the BGFX-specific stuff replaced with pure GLSL/OpenGL stuff.&#xD;&#xA;&#xD;&#xA;Next, here's the relevant part of my final fragment shader where I'm applying the auto exposure:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;layout (binding = 0, r16f) uniform readonly image1D lumAvg;&#xD;&#xA;layout (binding = 1, rgba16f) uniform readonly image2D hdrImage;&#xD;&#xA;&#xD;&#xA;// ...&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 C_in = imageLoad(hdrImage, ivec2(gl_FragCoord.xy));&#xD;&#xA;    // I'm having to multiply the average luminence produced by the above shaders by *one hundred times* in order to get anything remotely like a difference between the different values that are being produced!&#xD;&#xA;    float L_avg = imageLoad(lumAvg, 0).r * 100.0;&#xD;&#xA;    // Get luminance of this pixel&#xD;&#xA;    float L_in = dot(C_in.rgb, RGB_TO_LUM);&#xD;&#xA;    // Get the new target luminence, determined by a relationship with the average luminence of the scene it's in. This is the core of the auto exposure, and I just copied it from the blog post.&#xD;&#xA;    float L_prime = L_in / (9.6 * L_avg);&#xD;&#xA;&#xD;&#xA;    // Make the input color have the desired luminence by multiplying each channel by the ratio between the desired luminence and the current luminence of the channel.&#xD;&#xA;    C_in.rgb = C_in.rgb * vec3(L_prime / L_in);&#xD;&#xA;&#xD;&#xA;    // apply tone mapping (irrelevant here)&#xD;&#xA;    C_in.rgb = lottes(C_in.rgb);&#xD;&#xA;&#xD;&#xA;    // Gamma correction&#xD;&#xA;    C_in.rgb = pow(C_in.rgb, vec3(1.0 / 2.22));&#xD;&#xA;&#xD;&#xA;    FragColor = C_in;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Essentially, what's happening is that the calculated average luminence appears to *decrease* with the overall brightness of the scene instead of increasing. This in turn is causing my auto exposure calculations to be inverted, so that the darker a scene gets the lower the exposure gets, and the brighter it gets the higher the exposure, which is undesired behavior for me. Additionally, the luminence average seems to be far too small (and vary by very little). I'm getting values of `0.0038` for a very bright area, and `0.005` for pitch blackness, and that's the extent of it.  I've double checked all the equations, but I can't seem to find out where I went wrong. Is this supposed to be correct behavior? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42427" PostHistoryTypeId="1" PostId="13852" RevisionGUID="f65f2ea3-6296-40e3-9c24-2febbf2e05e3" CreationDate="2023-12-20T18:46:17.047" UserId="20919" Text="Average luminence and auto exposure algorithm not seeming to work properly" ContentLicense="CC BY-SA 4.0" />
  <row Id="42428" PostHistoryTypeId="3" PostId="13852" RevisionGUID="f65f2ea3-6296-40e3-9c24-2febbf2e05e3" CreationDate="2023-12-20T18:46:17.047" UserId="20919" Text="|opengl|shader|color|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42429" PostHistoryTypeId="5" PostId="13852" RevisionGUID="579365b4-79aa-47df-bcfd-d0da4694a161" CreationDate="2023-12-21T01:58:30.470" UserId="20919" Comment="added 19 characters in body" Text="I've been working on adding HDR rendering, auto exposure, and tone-mapping to my rendering engine, following [this blog post](https://bruop.github.io/exposure/) for doing auto exposure and it sequel as well as a few side resources for tone mapping. I've gotten tone mapping to work, but not auto exposure, although I feel like I have a solid grasp of the &#xD;&#xA;concepts.&#xD;&#xA;&#xD;&#xA;First, let's start with my code. Here are the two shaders I'm using to calculate the average luminence:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;&#xD;&#xA;/////////// CALCULATE HISTOGRAM&#xD;&#xA;&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#define GROUP_SIZE 256&#xD;&#xA;&#xD;&#xA;#define EPSILON 0.005&#xD;&#xA;#define RGB_TO_LUM vec3(0.2125, 0.7154, 0.0721)&#xD;&#xA;&#xD;&#xA;uniform vec4 params;&#xD;&#xA;// params.x = minimum log_2 luminance&#xD;&#xA;// params.y = inverse of the log_2 luminance range&#xD;&#xA;&#xD;&#xA;layout (binding = 0, rgba16f) uniform image2D hdrImage;&#xD;&#xA;layout (binding = 1, std140) buffer Histogram {&#xD;&#xA;    uint histogram[256];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;shared uint histogramShared[GROUP_SIZE];&#xD;&#xA;&#xD;&#xA;uint colorToBin(vec3 hdrColor, float minLogLum, float inverseLogLumRange) {&#xD;&#xA;    float lum = dot(hdrColor, RGB_TO_LUM);&#xD;&#xA;&#xD;&#xA;    if (lum &lt; EPSILON) {&#xD;&#xA;        return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    float logLum = clamp((log2(lum) - minLogLum) * inverseLogLumRange, 0.0, 1.0);&#xD;&#xA;&#xD;&#xA;    return uint(logLum * 254.0 + 1.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 16, local_size_y = 16) in;&#xD;&#xA;void main() {&#xD;&#xA;    histogramShared[gl_LocalInvocationIndex] = 0;&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    uvec2 dim = imageSize(hdrImage).xy;&#xD;&#xA;&#xD;&#xA;    if (gl_GlobalInvocationID.x &lt; dim.x &amp;&amp; gl_GlobalInvocationID.y &lt; dim.y) {&#xD;&#xA;        vec3 hdrColor = imageLoad(hdrImage, ivec2(gl_GlobalInvocationID.xy)).xyz;&#xD;&#xA;        uint binIndex = colorToBin(hdrColor, params.x, params.y);&#xD;&#xA;&#xD;&#xA;        atomicAdd(histogramShared[binIndex], 1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    atomicAdd(histogram[gl_LocalInvocationIndex], histogramShared[gl_LocalInvocationIndex]);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;/////////// CALCULATE WEIGHTED AVERAGE&#xD;&#xA;&#xD;&#xA;#version 430&#xD;&#xA;&#xD;&#xA;#define GROUP_SIZE 256&#xD;&#xA;&#xD;&#xA;uniform vec4 params;&#xD;&#xA;// params.x = minLogLum&#xD;&#xA;// params.y = logLumRange&#xD;&#xA;// param.z = timeCoeff&#xD;&#xA;// param.w = numPixels&#xD;&#xA;&#xD;&#xA;layout (binding = 0, r16f) uniform image1D target;&#xD;&#xA;layout (binding = 1, std140) buffer Histogram {&#xD;&#xA;    uint histogram[256];&#xD;&#xA;};&#xD;&#xA;&#xD;&#xA;shared uint histogramShared[GROUP_SIZE];&#xD;&#xA;&#xD;&#xA;layout (local_size_x = 256, local_size_y = 1) in;&#xD;&#xA;void main() {&#xD;&#xA;    uint countForThisBin = histogram[gl_LocalInvocationIndex];&#xD;&#xA;    histogramShared[gl_LocalInvocationIndex] = countForThisBin * gl_LocalInvocationIndex;&#xD;&#xA;&#xD;&#xA;    barrier();&#xD;&#xA;&#xD;&#xA;    histogram[gl_LocalInvocationIndex] = 0;&#xD;&#xA;&#xD;&#xA;    #pragma unroll&#xD;&#xA;    for (uint cutoff = (GROUP_SIZE &gt;&gt; 1); cutoff &gt; 0; cutoff &gt;&gt;= 1) {&#xD;&#xA;        if (uint(gl_LocalInvocationIndex) &lt; cutoff)&#xD;&#xA;            histogramShared[gl_LocalInvocationIndex] += histogramShared[gl_LocalInvocationIndex + cutoff];&#xD;&#xA;        barrier();&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if (gl_LocalInvocationIndex == 0) {&#xD;&#xA;        float weightedLogAverage = (histogramShared[0] / max(params.w - float(countForThisBin), 1.0)) - 1.0;&#xD;&#xA;        float weightedAvgLum = exp2(((weightedLogAverage / 254.0) * params.y) + params.x);&#xD;&#xA;        float lumLastFrame = imageLoad(target, 0).x;&#xD;&#xA;        float adaptedLum = lumLastFrame + (weightedAvgLum - lumLastFrame) * params.z;&#xD;&#xA;        imageStore(target, 0, vec4(adaptedLum, 0.0, 0.0, 0.0));&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;As far as I can tell, these are functionally identical to the code samples from the blog, with the BGFX-specific stuff replaced with pure GLSL/OpenGL stuff.&#xD;&#xA;&#xD;&#xA;Next, here's the relevant part of my final fragment shader where I'm applying the auto exposure:&#xD;&#xA;&#xD;&#xA;```c&#xD;&#xA;layout (binding = 0, r16f) uniform readonly image1D lumAvg;&#xD;&#xA;layout (binding = 1, rgba16f) uniform readonly image2D hdrImage;&#xD;&#xA;&#xD;&#xA;// ...&#xD;&#xA;&#xD;&#xA;void main() {&#xD;&#xA;    vec4 C_in = imageLoad(hdrImage, ivec2(gl_FragCoord.xy));&#xD;&#xA;    // I'm having to multiply the average luminence produced by the above shaders by *one hundred times* in order to get anything remotely like a difference between the different values that are being produced!&#xD;&#xA;    float L_avg = imageLoad(lumAvg, 0).r * 100.0;&#xD;&#xA;    // Get luminance of this pixel&#xD;&#xA;    float L_in = dot(C_in.rgb, RGB_TO_LUM);&#xD;&#xA;    // Get the new target luminence, determined by a relationship with the average luminence of the scene it's in. This is the core of the auto exposure, and I just copied it from the blog post.&#xD;&#xA;    float L_prime = L_in / (9.6 * L_avg);&#xD;&#xA;&#xD;&#xA;    // Make the input color have the desired luminence by multiplying each channel by the ratio between the desired luminence and the current luminence of the channel.&#xD;&#xA;    C_in.rgb = C_in.rgb * vec3(L_prime / L_in);&#xD;&#xA;&#xD;&#xA;    // apply tone mapping (irrelevant here)&#xD;&#xA;    C_in.rgb = lottes(C_in.rgb);&#xD;&#xA;&#xD;&#xA;    // Gamma correction&#xD;&#xA;    C_in.rgb = pow(C_in.rgb, vec3(1.0 / 2.22));&#xD;&#xA;&#xD;&#xA;    FragColor = C_in;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Essentially, what's happening is that the calculated average luminence appears to *decrease* with the overall brightness of the scene instead of increasing. This in turn is causing my auto exposure calculations to be inverted, so that the darker a scene gets the lower the exposure gets, and the brighter it gets the higher the exposure, which is undesired behavior for me. Additionally, the luminence average seems to be far too small (and vary by very little). I'm getting values of `0.0038` for a very bright area (14+ luminence), and `0.005` for pitch blackness, and that's the extent of it.  I've double checked all the equations, but I can't seem to find out where I went wrong. Is this supposed to be correct behavior? &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42430" PostHistoryTypeId="2" PostId="13853" RevisionGUID="45156364-23c9-4b58-bb7f-f02f8d0aac8f" CreationDate="2023-12-21T03:32:35.973" UserId="20919" Text="As it turns out, what was happening is that the number of black pixels was being subtracted from the total number of pixels when calculating the average log luminence per pixel, which meant very dark scenes with a lot of deep black pixels ended up having a miniscule denominator in their average calculation compared to brighter scenes, which made the average much higher despite the numerator, the actual weighted luminosity value, being much smaller. So I just had to remove the `- countForThisBin` part." ContentLicense="CC BY-SA 4.0" />
  <row Id="42436" PostHistoryTypeId="34" PostId="13726" RevisionGUID="21a9e03a-6e23-489d-a694-616fb25152c0" CreationDate="2023-12-21T14:06:40.807" UserId="-1" Comment="84" />
  <row Id="42437" PostHistoryTypeId="2" PostId="13855" RevisionGUID="c9139dd4-5351-4199-a6e9-c03a4bd3b7fe" CreationDate="2023-12-21T14:54:13.283" UserId="228" Text="In the documentation of [GLSL - reflect][1] given a surface normal $N$ and an incident vector $I$ the calculation being performed is reported as&#xD;&#xA;$$&#xD;&#xA;\text{reflect}(I,N) = I - 2\text{dot}(I,N)N&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I wonder if this math is correct because in my calculations the sign should be swapped.&#xD;&#xA;&#xD;&#xA;Can anyone confirm?&#xD;&#xA;&#xD;&#xA;Maybe if $I$ is not incident but outgoing from the point of application the sign would be swapped?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://registry.khronos.org/OpenGL-Refpages/gl4/html/reflect.xhtml" ContentLicense="CC BY-SA 4.0" />
  <row Id="42439" PostHistoryTypeId="1" PostId="13855" RevisionGUID="c9139dd4-5351-4199-a6e9-c03a4bd3b7fe" CreationDate="2023-12-21T14:54:13.283" UserId="228" Text="GLSL reflect function math correct?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42440" PostHistoryTypeId="3" PostId="13855" RevisionGUID="c9139dd4-5351-4199-a6e9-c03a4bd3b7fe" CreationDate="2023-12-21T14:54:13.283" UserId="228" Text="|glsl|mathematics|vectors|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42441" PostHistoryTypeId="50" PostId="12807" RevisionGUID="70a08301-cc19-4257-87de-be06d00bf2a8" CreationDate="2023-12-21T21:08:05.970" UserId="-1" />
  <row Id="42442" PostHistoryTypeId="50" PostId="10535" RevisionGUID="9f87b923-5748-4f6f-85ea-d0d1d5a528a9" CreationDate="2023-12-22T00:08:15.903" UserId="-1" />
  <row Id="42445" PostHistoryTypeId="5" PostId="1551" RevisionGUID="d308b392-06d6-4012-ac3b-c9fbf2e90813" CreationDate="2023-12-22T11:20:39.470" UserId="209" Comment="Fixed an error with the bit allocation of the YAB/narrow channel format 322-&gt;422" Text="*&quot;How (hardware) texture compression works&quot;* is a large topic. Hopefully I can provide some insights without duplicating the content of [Nathan's answer](https://computergraphics.stackexchange.com/questions/1523/how-does-hardware-texture-compression-work/1545#1545).&#xD;&#xA;&#xD;&#xA;## Requirements ##&#xD;&#xA;Texture compression typically differs from 'standard' image compression techniques e.g. JPEG/PNG in four main ways, as outlined in Beers et al's [Rendering from Compressed Textures](https://graphics.stanford.edu/projects/flashg/papers/texture_compression/):&#xD;&#xA;&#xD;&#xA; 1. *Decoding Speed*: You don't want texture compression to be slower (at least not noticeably so) than using uncompressed textures. It should also be relatively simple to decompress since that can help achieve fast decompression without excessive hardware and power costs.&#xD;&#xA;&#xD;&#xA; 2. *Random Access*: You can't easily predict which texels will be required during a given render. If some subset, *M*, of the accessed texels come from, say, the middle of the image, it's essential that you don't have to decode all of the 'previous' lines of the texture in order to determine *M*; with JPEG and PNG this is necessary as pixel decoding depends on the previously decoded data.  &#xD;&#xA;Note, having said this, just because you have &quot;random&quot; access, [doesn't mean you should try to sample completely arbitrarily](https://computergraphics.stackexchange.com/questions/357/is-using-many-texture-maps-bad-for-caching/419#419)&#xD;&#xA;&#xD;&#xA; 3. *Compression Rate and Visual Quality*: Beers et al argue (convincingly) that losing some quality in the compressed result in order to improve compression rate is a worthwhile trade-off. In 3D rendering, the data is probably going to be manipulated (e.g. filtered &amp; shaded etc) and so some loss of quality may well be masked.&#xD;&#xA;&#xD;&#xA; 4. *Asymmetric encoding/decoding*: Though perhaps slightly more contentious, they argue that it is acceptable to have the encoding process much slower than the decoding. Given that the decoding needs to be at HW fill rates, this is generally acceptable. (I will admit that compression of PVRTC, ETC2 and some others at maximum quality could be faster)&#xD;&#xA;&#xD;&#xA;## Early History &amp; Techniques ##&#xD;&#xA;It may surprise some to learn that texture compression has been around for over four decades. Flight simulators from the 70s and 80s needed access to *relatively* large amounts of texture data and given that [1MB of RAM in 1980 was &gt; $6000](http://www.jcmit.com/memoryprice.htm), reducing the texture footprint was essential. As another example, in the mid 70s, even a small amount of high speed memory and logic, e.g. enough for [a modest 512x512 RGB frame buffer](https://en.wikipedia.org/wiki/Framebuffer#History)) could set you back the price of small house.&#xD;&#xA;&#xD;&#xA;Though, AFAIK, not explicitly referred to as texture compression, in the literature and patents you can find references to techniques including:  &#xD;&#xA; a. simple forms of mathematical/procedural texture synthesis,  &#xD;&#xA; b. use of a single channel texture (e.g. 4bpp) that is then multiplied by a per-texture RGB value,  &#xD;&#xA; c. YUV, and  &#xD;&#xA; d. palettes (the literature suggesting use of [Heckbert's approach](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.1334) to do the compression) &#xD;&#xA;&#xD;&#xA;## Modelling Image Data ##&#xD;&#xA;As noted above, texture compression is nearly always lossy and thus the problem becomes one of trying to represent the important data in a compact way whilst disposing of the less significant information. The various schemes that will be described below all have an implicit 'parameterised' model that approximates the typical behaviour of texture data and of the eye's response. &#xD;&#xA;&#xD;&#xA;Further, since texture compression tends to use fixed-rate encoding, the compression process usually includes a search step to find the set of parameters which, when fed in to the model, will generate a good approximation of the original texture. That search step, however, can be time consuming.  &#xD;&#xA;*(With the possible exception of tools such as [optipng](http://optipng.sourceforge.net/), this is another area where typical use of PNG &amp; JPEG differ from texture compression schemes)*&#xD;&#xA;&#xD;&#xA;Before progressing further, to help with further understanding of TC it's worth taking a look at [Principal Component Analysis (PCA)](https://en.wikipedia.org/wiki/Principal_component_analysis) - a very useful mathematical tool for data compression.&#xD;&#xA;### Example texture ###&#xD;&#xA;To compare the various methods, we'll use the following image:&#xD;&#xA;&#xD;&#xA;[![small lorikeet+text][1]][1]  &#xD;&#xA;Note that this is a fairly tough image, especially for palette and VQTC methods as it spans much of the RGB colour cube and only 15% of the texels use repeated colours.&#xD;&#xA;&#xD;&#xA;## PC and (post mid 90s) Console Texture compression ##&#xD;&#xA;To reduce data costs, some PC games and early games consoles also made use of palette images, which is a form of Vector Quantisation (VQ).&#xD;&#xA;Palette-based approaches make the assumption that a given image only uses relatively small portions of the RGB(A) colour cube.  A problem with palette textures is that the compression rates for the achieved quality is generally rather modest. The example texture compressed to &quot;4bpp&quot; (using GIMP) produced  &#xD;&#xA;[![enter image description here][2]][2]  &#xD;&#xA;Note again that this is a relatively tough image for VQ schemes.&#xD;&#xA;&#xD;&#xA;### VQ with larger vectors (e.g. 2bpp ARGB) ###&#xD;&#xA;Inspired by Beers et al, the Dreamcast console used VQ to encode 2x2  or even 2x4 pixel blocks with single bytes. While the &quot;vectors&quot; in the palette textures are 3 or 4 dimensional, the 2x2 pixel blocks can be considered to be 16 dimensional. The compression scheme assumes there is sufficient, approximate repetition of these vectors. &#xD;&#xA;&#xD;&#xA;Even though VQ can achieve satisfactory quality with ~2bpp, the problem with these schemes is that it requires dependent memory reads: An initial read from the index map to determine the code for the pixel is followed by a second to actually fetch the pixel data associated with that code. Additional caches can help alleviate some of the incurred latency, but adds complexity to the hardware.&#xD;&#xA;&#xD;&#xA;The example image compressed with the 2bpp Dreamcast scheme is &#xD;&#xA;[![2bpp VQ result][3]][3]. &#xD;&#xA;The index map is: [![2bpp VQ index map][4]][4]&#xD;&#xA;&#xD;&#xA;Compression of VQ data can be done in various ways however, *IIRC*, the above was done using PCA to derive and then partition the 16D vectors along the principal vector into 2 sets such that two representative vectors minimised the mean squared error. The process then recursed until 256 candidate vectors were produced. &#xD;&#xA;A global [k-means/Lloyd's algorithm](https://en.wikipedia.org/wiki/K-means_clustering#Standard_algorithm) approach was then applied to improve the representatives.&#xD;&#xA;### Colour Space Transformations&#xD;&#xA;Colour space transformations also make use of PCA noting that the global distribution of colour is often spread along a major axis with far less spread along the other axes. For YUV representations, the assumptions are that a) the major axis is often in the luma direction and that b) the eye is more sensitive to changes in this direction.&#xD;&#xA;&#xD;&#xA;The 3dfx Voodoo system provided [&quot;YAB&quot;](http://www.gamers.org/dEngine/xf3D/glide/glidepgm.htm), an 8bpp, &quot;Narrow Channel&quot; compression system that split each 8 bit texel into a 422 format, and applied a user selected colour transform to that data to map it into RGB. The main axis thus had 16 levels and the smaller axes, 4 each.&#xD;&#xA;&#xD;&#xA;The S3 Virge chip had a slightly simpler, 4bpp, scheme that allowed the user to specify, for *the entire texture*, two end colours, which should lie on the principal axis, along with a 4bpp monochrome texture. The per-pixel value then blended the end colours with appropriate weights to produce the RGB result.&#xD;&#xA;&#xD;&#xA;### BTC-based schemes&#xD;&#xA;Rewinding some number of years, Delp and Mitchell designed a simple (monochrome) image compression scheme called [*Block Truncation Coding*, (BTC)](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1094560). This paper also included a compression algorithm but, for our purposes, we are mainly interested in the resulting compressed data and of the decompression process.  &#xD;&#xA;&#xD;&#xA;In this scheme, images are broken into, typically, 4x4 pixel blocks, which can be compressed independently with, in effect, a localised VQ algorithm. Each block is represented by two &quot;values&quot;, *a* and *b*, and a 4x4 set of index bits, which identify which of the two values to use for each pixel.&#xD;&#xA;&#xD;&#xA;_S3TC_:  4bpp RGB (+1bit alpha)  &#xD;&#xA;Although several colour-variants of BTC for image compression were proposed, of interest to us is [Iourcha et al's S3TC](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5,956,431.PN.&amp;OS=PN/5,956,431&amp;RS=PN/5,956,431), some of which appears to be a rediscovery of the somewhat forgotten work of [Hoffert et al](http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&amp;Sect2=HITOFF&amp;d=PALL&amp;p=1&amp;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&amp;r=1&amp;f=G&amp;l=50&amp;s1=5046119.PN.&amp;OS=PN/5046119&amp;RS=PN/5046119) that was used in Apple's Quicktime.&#xD;&#xA;&#xD;&#xA;The original S3TC, without the DirectX variants, compresses blocks of either RGB or RGB+1bit Alpha to 4bpp. Each 4x4 block in the texture is replaced by two end colours, *A* and *B*, from which up to two other colours are derived by fixed-weight, linear blends. Further, each texel in the block has a 2-bit index that determines how to select one of these four colours. &#xD;&#xA;&#xD;&#xA;For example the following is a 4x4 pixel section of the test image compressed with the AMD/ATI Compressenator tool. (*Technically it's taken from a 512x512 version of the test image but forgive my lack of time to update the examples*).   &#xD;&#xA;[![enter image description here][5]][5]  &#xD;&#xA;This illustrates the compression process: The average and the principal axis of the colours are calculated.  A best fit is then performed to find two end points that 'lie on' the axis which, along with the two derived 1:2 and 2:1 blends (or in some cases a 50:50 blend) of those end points, that minimises the error.  Each original pixel is then mapped to one of those colours to produce the result.&#xD;&#xA;&#xD;&#xA;If, as in this case, the colours are reasonable approximated by the principal axis, the error will be relatively low. However if, like in the neighbouring 4x4 block shown below, the colours are more diverse, the error will be higher.  &#xD;&#xA;[![enter image description here][6]][6]  &#xD;&#xA;&#xD;&#xA;The example image, compressed with the [AMD Compressonator](http://developer.amd.com/tools-and-sdks/archive/legacy-cpu-gpu-tools/the-compressonator/) produces:  &#xD;&#xA;[![enter image description here][7]][7]  &#xD;&#xA;&#xD;&#xA;Since the colours are determined independently per-block, there can be discontinuities at block boundaries but, as long as the resolution is kept sufficiently high, these block artefacts may go unnoticed:  &#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;&#xD;&#xA;_ETC1_:  4bpp RGB  &#xD;&#xA;Ericsson Texture Compression also works with 4x4 blocks of texels but makes the assumption that, much like YUV, the principal axis of a local set of texels is often very strongly correlated with &quot;luma&quot;. The set of texels can then be represented by just an average colour and a highly quantised, scalar 'length' of the projection of the texels onto that assumed axis.  &#xD;&#xA;&#xD;&#xA;Since this reduces the data storage costs relative to say, S3TC, it allows ETC to introduce a partitioning scheme, whereby the 4x4 block is subdivided into a pair of horizontal 4x2 or vertical 2x4 sub-blocks. These each have their own average colour. &#xD;&#xA;The example image produces:  &#xD;&#xA;[![enter image description here][9]][9]  &#xD;&#xA;The area around the beak also illustrates the horizontal and vertical partitioning of the 4x4 blocks.&#xD;&#xA;[![enter image description here][10]][10]    &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;### Global+Local ###&#xD;&#xA;There are some texture compression systems that are a cross between global and local schemes, such as that of the distributed palettes of [Ivanov and Kuzmin](http://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00420/abstract) or the method of [PVRTC](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.61.7956).  &#xD;&#xA;&#xD;&#xA;_PVRTC_:  4 &amp; 2 bpp RGBA  &#xD;&#xA;PVRTC assumes that an (in practice, bilinearly) upscaled image is a good approximation to the full-resolution target and that the difference between the approximation and the target, i.e. the delta image, is locally monochromatic, i.e. has a dominant principal axis. Further, it assumes the local principal axis can be interpolated across the image.&#xD;&#xA;&#xD;&#xA;(to do: Add images showing breakdown)&#xD;&#xA;&#xD;&#xA;The example texture, compressed with PVRTC1 4bpp produces:  &#xD;&#xA;[![enter image description here][11]][11]  &#xD;&#xA;with the area around the beak:  &#xD;&#xA;[![enter image description here][12]][12]  &#xD;&#xA;Compared to BTC-schemes, the block artefacts typically are eliminated but there can sometimes be &quot;overshoot&quot; if there are strong discontinuities in the source image, for example around the silhouette of the lorikeet's head.&#xD;&#xA;&#xD;&#xA;The 2bpp variant has, naturally, higher error than the 4bpp (note loss of precision around the blue, high frequency areas near the neck) but arguably still of reasonably quality:  &#xD;&#xA;[![enter image description here][13]][13]&#xD;&#xA;&#xD;&#xA;### A note on decompression costs ###&#xD;&#xA;Although the compression algorithms for the schemes described above have a moderate to high evaluation cost, the decompression algorithms, especially for hardware implementations, are relatively inexpensive. ETC1, for example, requires little more than a few MUXes and low-precision adders; S3TC effectively slightly more addition units to perform the blending; and PVRTC, slightly more again.  In theory, these simple TC schemes could allow a GPU architecture to avoid decompression until just prior to the filtering stage, thus maximising the effectiveness of internal caches.&#xD;&#xA;&#xD;&#xA;### Other Schemes ###&#xD;&#xA;Other common TC modes that should be mentioned are:&#xD;&#xA;&#xD;&#xA; - ETC2 - is a (4bpp) superset of ETC1 that improves the handling of regions with colour distributions that don't align well with 'luma'. There are also a 4bpp variant that supports 1 bit alpha, and an 8bpp format for RGBA.&#xD;&#xA;&#xD;&#xA; - ATC - Is effectively a small [variation on S3TC][14].  &#xD;&#xA;&#xD;&#xA; - FXT1 (3dfx) was a more ambitious [variant of the S3TC theme](https://www.opengl.org/registry/specs/3DFX/texture_compression_FXT1.txt).&#xD;&#xA;&#xD;&#xA; - BC6 &amp; BC7 : An 8bpp, block-based system supporting ARGB. Apart from HDR modes, these use a more complex partitioning system than that of ETC to attempt to better model image colour distribution.&#xD;&#xA;&#xD;&#xA; - PVRTC2 : 2&amp;4bpp ARGB. This introduces additional modes including one to overcome limitations with strong boundaries in the images.&#xD;&#xA;&#xD;&#xA; - ASTC : This is also a block based system but is somewhat more complicated in that it has a large number of possible block sizes targeting a wide range of bpp. It also includes features such as up to 4 partition regions with a pseudo-random partition generator, and variable resolution for the index data and/or colour precision and colour models.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/SM000.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Vpv0t.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/8tnag.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/YNJww.png&#xD;&#xA;  [5]: https://i.stack.imgur.com/YCI3n.png&#xD;&#xA;  [6]: https://i.stack.imgur.com/d5dZ8.png&#xD;&#xA;  [7]: https://i.stack.imgur.com/ZFrSa.png&#xD;&#xA;  [8]: https://i.stack.imgur.com/Fa779.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/cYOmr.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/Uwd5F.png&#xD;&#xA;  [11]: https://i.stack.imgur.com/5jKnQ.png&#xD;&#xA;  [12]: https://i.stack.imgur.com/ODTd4.png&#xD;&#xA;  [13]: https://i.stack.imgur.com/ASiRE.png&#xD;&#xA;  [14]: http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42446" PostHistoryTypeId="2" PostId="13856" RevisionGUID="d41703c1-0037-494d-ab1b-dd524c788bc9" CreationDate="2023-12-22T14:15:54.933" UserId="19936" Text="I tried porting the main &quot;Image&quot; shader here [this][1]. My results are somewhat similar apart from the fact that &quot;IRES&quot; does not seem to behave in the same way as it does in Shadertoy. It is supposed to alter the &quot;resolution&quot; of the fake &quot;CRT&quot; monitor, but when I apply this to a `color rect` and alter &quot;IRES&quot; it will just zoom on the upper left corner of the scene behind it. How can I alter the code below to make it behave similarly to the original shader?&#xD;&#xA;&#xD;&#xA;    shader_type canvas_item;&#xD;&#xA;    &#xD;&#xA;    #define gaussian(a,b)	exp2((a)*(a)*-(b))&#xD;&#xA;    &#xD;&#xA;    uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;&#xD;&#xA;    &#xD;&#xA;    uniform float SCREEN_CURVE_RADIUS = 5;&#xD;&#xA;    uniform float SCREEN_CORNER_RADIUS = 0.1;&#xD;&#xA;    uniform float BRIGHTNESS = 1.5;&#xD;&#xA;    uniform float PIXEL_SHARPNESS = 2.0;&#xD;&#xA;    uniform float LINE_SHARPNESS = 6.0;&#xD;&#xA;    uniform float MASK_STRENGTH = 0.15;&#xD;&#xA;    &#xD;&#xA;    uniform bool CURVE_SCREEN = true;&#xD;&#xA;    uniform bool SCANLINES = true;&#xD;&#xA;    uniform bool SHADOW_MASK = true;&#xD;&#xA;    uniform bool LIGHT_EFFECTS = true;&#xD;&#xA;    &#xD;&#xA;    uniform float TILES = 2.0;&#xD;&#xA;    const vec2 IRES = vec2(16, 9) * 5.0;&#xD;&#xA;    &#xD;&#xA;    vec3 ACESFilm(vec3 x) {&#xD;&#xA;        return clamp((x*(2.51*x + 0.03)) / (x*(2.43*x + 0.59) + 0.14), 0.0, 1.0);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec2 curveScreen(vec2 uv) {&#xD;&#xA;        float r = 3.14159265 * 0.5 / SCREEN_CURVE_RADIUS;&#xD;&#xA;        float d = 1.0-cos(uv.x*r)*cos(uv.y*r);		// distance to screen&#xD;&#xA;        float s = cos(r);							// scale factor to re-fit window&#xD;&#xA;        return uv / (1.0-d) * s;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float discardCorners(vec2 pos) {&#xD;&#xA;        pos = abs(pos);&#xD;&#xA;        pos.x = pos.x*1.333-0.333;											// 4:3 aspect ratio correction&#xD;&#xA;        if (min(pos.x, pos.y) &lt; 1.0-SCREEN_CORNER_RADIUS) return 1.0;		// not near corner -- break early&#xD;&#xA;        float d = distance(pos, vec2(1.0 - SCREEN_CORNER_RADIUS));&#xD;&#xA;        return float(d &lt; SCREEN_CORNER_RADIUS);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getSample(vec2 pos, vec2 off) {&#xD;&#xA;    	//get nearest emulated sample&#xD;&#xA;    	vec2 ir = IRES * TILES;&#xD;&#xA;        pos = floor(pos*ir) + vec2(0.5) + off;&#xD;&#xA;    	vec3 col = vec3(0.0);&#xD;&#xA;    	if ( pos.x&gt;=0.0 &amp;&amp; pos.x&lt;=ir.x*2.0 &amp;&amp; pos.y&gt;=0.0 &amp;&amp; pos.y&lt;=ir.y ) {&#xD;&#xA;            col = texelFetch(SCREEN_TEXTURE, ivec2(pos), 0).rgb;&#xD;&#xA;            col = pow( ( (col + 0.055) / 1.055), vec3(2.4) );		// SRGB =&gt; linear&#xD;&#xA;    	}&#xD;&#xA;    	return col;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getScanline( vec2 pos, float off ) {&#xD;&#xA;    	// 3-tap gaussian filter to get colour at arbitrary point along scanline&#xD;&#xA;        vec2 ir = IRES * TILES;&#xD;&#xA;        float d = 0.5-fract(pos.x*ir.x);&#xD;&#xA;    	vec3 ca = getSample( pos, vec2(-1.0, off ) );&#xD;&#xA;    	vec3 cb = getSample( pos, vec2( 0.0, off ) );&#xD;&#xA;    	vec3 cc = getSample( pos, vec2( 1.0, off ) );&#xD;&#xA;    	float wa = gaussian( d-1.0, PIXEL_SHARPNESS );&#xD;&#xA;    	float wb = gaussian( d,     PIXEL_SHARPNESS );&#xD;&#xA;    	float wc = gaussian( d+1.0, PIXEL_SHARPNESS );&#xD;&#xA;    	return ( ca*wa + cb*wb + cc*wc ) / ( wa+wb+wc);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 getScreenColour(vec2 pos) {&#xD;&#xA;    	//Get influence of 3 nearest scanlines&#xD;&#xA;        vec2 ir = IRES * TILES;&#xD;&#xA;        float d = 0.5-fract(pos.y*ir.y);&#xD;&#xA;    	vec3 ca = getScanline( pos,-1.0 );&#xD;&#xA;    	vec3 cb = getScanline( pos, 0.0 );&#xD;&#xA;    	vec3 cc = getScanline( pos, 1.0 );&#xD;&#xA;        float wa = gaussian( d-1.0, LINE_SHARPNESS );&#xD;&#xA;    	float wb = gaussian( d,     LINE_SHARPNESS );&#xD;&#xA;    	float wc = gaussian( d+1.0, LINE_SHARPNESS );&#xD;&#xA;        return ( ca*wa + cb*wb + cc*wc );&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    vec3 SlotMask_PixelPerfect(vec2 pos, float resolution_y) {&#xD;&#xA;        //pos /= 1.0 + floor( resolution_y / 1440.0 );&#xD;&#xA;        pos /= 1.0 + floor(resolution_y / (IRES.y*15.0));&#xD;&#xA;        float glow = 0.5;&#xD;&#xA;        float f = mod(pos.x,3.0);&#xD;&#xA;    	vec3 col = vec3(float(f &lt;= 1.0), float(f &gt; 1.0 &amp;&amp; f &lt;= 2.0), float(f &gt; 2.0));&#xD;&#xA;        col += vec3(float(f&lt;1.5 || f&gt;=2.5), float(f&gt;0.5 &amp;&amp; f&lt;=2.5), float(f&gt;1.5 || f&lt;=0.5)) * glow;&#xD;&#xA;        col *= (mod(pos.y+(fract(pos.x/6.0)&gt;0.5?1.5:0.0),3.0)&lt;1.0) ? glow : 1.0;&#xD;&#xA;        col /= 1.0+glow;&#xD;&#xA;        return col;&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    void fragment(){&#xD;&#xA;    	vec2 uv =  FRAGCOORD.xy / (1.0 / SCREEN_PIXEL_SIZE).xy;&#xD;&#xA;    	vec2 pos = SCREEN_UV;&#xD;&#xA;    	pos = pos*2.0 - 1.0;&#xD;&#xA;        pos.x *= (1.0 / SCREEN_PIXEL_SIZE).x/(1.0 / SCREEN_PIXEL_SIZE).y*(IRES.y/IRES.x);&#xD;&#xA;    	&#xD;&#xA;    	if (CURVE_SCREEN) pos = curveScreen(pos);&#xD;&#xA;    	&#xD;&#xA;    	if(max( abs(pos.x), abs(pos.y) )&lt;1.0) {							// skip everything if we're beyond the screen edge&#xD;&#xA;        	&#xD;&#xA;            vec3 col = vec3(1.0);&#xD;&#xA;            &#xD;&#xA;            if (CURVE_SCREEN) col *= discardCorners(pos);&#xD;&#xA;            &#xD;&#xA;            if (LIGHT_EFFECTS) col *= 1.0 - sqrt(length(pos)*0.25);						// vignette&#xD;&#xA;            &#xD;&#xA;            pos = pos*0.5 + 0.5;&#xD;&#xA;    &#xD;&#xA;           if (SCANLINES) col *= getScreenColour( pos );&#xD;&#xA;           else col *= getSample( pos, vec2(0.0) );&#xD;&#xA;            &#xD;&#xA;           if (SHADOW_MASK) {&#xD;&#xA;            vec3 shadowmask = SlotMask_PixelPerfect(FRAGCOORD.xy, (1.0 / SCREEN_PIXEL_SIZE).y);&#xD;&#xA;            col *= mix( vec3(1.0-MASK_STRENGTH), vec3(1.0+MASK_STRENGTH), shadowmask);&#xD;&#xA;            }&#xD;&#xA;            &#xD;&#xA;            if (LIGHT_EFFECTS) {&#xD;&#xA;    			col *= BRIGHTNESS;&#xD;&#xA;    	    	col = ACESFilm(col);&#xD;&#xA;            }&#xD;&#xA;        &#xD;&#xA;        	col = pow(col, vec3(1.0/2.4)) * 1.055 - 0.055;			// linear =&gt; SRGB&#xD;&#xA;        &#xD;&#xA;        	COLOR = vec4(col, 1.0);&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.shadertoy.com/view/tt3yR2" ContentLicense="CC BY-SA 4.0" />
  <row Id="42448" PostHistoryTypeId="1" PostId="13856" RevisionGUID="d41703c1-0037-494d-ab1b-dd524c788bc9" CreationDate="2023-12-22T14:15:54.933" UserId="19936" Text="Shader ported from shadertoy does not behave in the same way" ContentLicense="CC BY-SA 4.0" />
  <row Id="42449" PostHistoryTypeId="3" PostId="13856" RevisionGUID="d41703c1-0037-494d-ab1b-dd524c788bc9" CreationDate="2023-12-22T14:15:54.933" UserId="19936" Text="|shader|glsl|godot|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42450" PostHistoryTypeId="2" PostId="13857" RevisionGUID="588df29c-3d8c-436a-b121-0af9ac9476bb" CreationDate="2023-12-23T12:09:58.817" UserId="20996" Text="I am implementing IPC from siggraph2020, and one of its step is about CCD line search, where CCD is applied each iteration in the descent method in a part of the algorithm.&#xD;&#xA;&#xD;&#xA;I have implemented CCD functions for primitive pairs (triangle-point, edge-edge), which returns time of impact (TOI) given the original positions of primitives and their moving directions. &#xD;&#xA;&#xD;&#xA;What i want is the minimum of TOIs from all primitive pairs.&#xD;&#xA;&#xD;&#xA;Now I wonder how do i build the topology of the tetrahedron mesh to find the primitives pairs that could possibly collide, and how to loop through them? &#xD;&#xA;&#xD;&#xA;More specifically, &#xD;&#xA;- what the will the data structure of triangles(faces) and edges be like&#xD;&#xA;- what will the loop be like? &#xD;&#xA;- How to examine if a vertex is adjacent to an edge, or is it a part of a triangle? simply looping through the two(three) vertices to see if they are equal, or are there other elegant ways?&#xD;&#xA;&#xD;&#xA;The data i hold in simulation is probably like `Vector3 vertex[]` where each represents the position of a vertex, `Vector3 vertexDelta[]` where each represents the position offset of a vertex(which i want to test if intersection happen when `vertex[i] := vertex[i] + t * vertexDelta[i]`), and `Vector4Int tetra[]` where each represents the **indices** of the 4 vertices in the tetrahedron." ContentLicense="CC BY-SA 4.0" />
  <row Id="42452" PostHistoryTypeId="1" PostId="13857" RevisionGUID="588df29c-3d8c-436a-b121-0af9ac9476bb" CreationDate="2023-12-23T12:09:58.817" UserId="20996" Text="Narrow-phase CCD in FEM topology query (finite element method)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42453" PostHistoryTypeId="3" PostId="13857" RevisionGUID="588df29c-3d8c-436a-b121-0af9ac9476bb" CreationDate="2023-12-23T12:09:58.817" UserId="20996" Text="|physically-based|physics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42454" PostHistoryTypeId="5" PostId="13857" RevisionGUID="15edc40b-fb57-486b-a71e-7712dcebdfbb" CreationDate="2023-12-23T12:11:46.167" UserId="20996" Comment="added 34 characters in body" Text="I am implementing IPC from siggraph2020, and one of its step is about CCD line search, where CCD is applied each iteration in the descent method in a part of the algorithm.&#xD;&#xA;&#xD;&#xA;I have implemented CCD functions for primitive pairs (triangle-point, edge-edge), which returns time of impact (TOI) given the original positions of primitives and their moving directions. &#xD;&#xA;&#xD;&#xA;What i want is the minimum of TOIs from all primitive pairs.&#xD;&#xA;&#xD;&#xA;Now I wonder how do i build the topology of the tetrahedron mesh to find the primitives pairs that could possibly collide, and how to loop through them? &#xD;&#xA;&#xD;&#xA;More specifically, &#xD;&#xA;- what the will the data structure of triangles(faces) and edges be like&#xD;&#xA;- what will the loop be like? &#xD;&#xA;- How to examine if a vertex is adjacent to an edge, or is it a part of a triangle? simply looping through the two(three) vertices to see if they are equal, or are there other elegant ways?&#xD;&#xA;&#xD;&#xA;The data i hold in simulation is probably like `Vector3 vertex[]` where each represents the position of a vertex, `Vector3 vertexDelta[]` where each represents the position offset of a vertex(which i want to test if intersection happen when `vertex[i] := vertex[i] + t * vertexDelta[i]`), and `Vector4Int tetra[]` where each represents the **indices** of the 4 vertices in the tetrahedron.&#xD;&#xA;&#xD;&#xA;Apologies for my poor english." ContentLicense="CC BY-SA 4.0" />
  <row Id="42456" PostHistoryTypeId="50" PostId="9426" RevisionGUID="385f7a6e-7b19-4ced-8c4b-9bc96b260746" CreationDate="2023-12-27T18:06:15.737" UserId="-1" />
  <row Id="42457" PostHistoryTypeId="2" PostId="13858" RevisionGUID="18fb01a7-af93-4aca-8219-7c1b36ecc04b" CreationDate="2023-12-28T07:21:04.440" UserId="21008" Text="I've noticed this shade of green a few different times when I experience graphical errors on computers. most recently when I had to disable / re-enable my GPU to fix a error with how videos were being displayed on youtube, and the videos that were loaded were all this green color after the restart.&#xD;&#xA;&#xD;&#xA;[![An example][1]][1]&#xD;&#xA;&#xD;&#xA; [1]: https://i.stack.imgur.com/GU4Q0.png&#xD;&#xA;&#xD;&#xA;I've also noticed this color before the thumbnails on youtube videos load in and once when It took up the whole screen for a second because of some kind of bug.&#xD;&#xA;&#xD;&#xA;I think this is some kind of fallback color GPUs use because I've seen it on multiple computers, but I wasn't able to find anything about it searching the hex code." ContentLicense="CC BY-SA 4.0" />
  <row Id="42459" PostHistoryTypeId="1" PostId="13858" RevisionGUID="18fb01a7-af93-4aca-8219-7c1b36ecc04b" CreationDate="2023-12-28T07:21:04.440" UserId="21008" Text="What's with this green color ( #004D00 )" ContentLicense="CC BY-SA 4.0" />
  <row Id="42460" PostHistoryTypeId="3" PostId="13858" RevisionGUID="18fb01a7-af93-4aca-8219-7c1b36ecc04b" CreationDate="2023-12-28T07:21:04.440" UserId="21008" Text="|gpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42461" PostHistoryTypeId="2" PostId="13859" RevisionGUID="e596a8bf-b526-400e-bd66-c1363ff1e8d8" CreationDate="2023-12-28T16:43:15.830" UserId="21006" Text="I am analyzing the article Parameterization of triangular meshes (Michael S. Floater November 10, 2009) and have reached the point where the uniqueness of the solution to a system of linear equations.&#xD;&#xA;&#xD;&#xA;&gt; We now describe a general method for constructing a parameterization of&#xD;&#xA;triangular mesh in $R^3$. We denote by $S$ the set of triangles in the mesh and&#xD;&#xA;$V$ its vertices and $E$ its edges. We let $Ω_S ⊂ R^3$ be the union of the triangles&#xD;&#xA;in $S$. Then we define a parameterization of $S$ as a continuous piecewise linear mapping $ψ : Ω_S → R^2$. Then $ψ$ maps each vertex, edge, and triangle of $S$ to a corresponding vertex, edge, and triangle in $R^2$. Such a mapping is completely determined by the points $ψ(v), v ∈ V$. Let $V_I$ denote the interior vertices of $S$ and $V_B$ the boundary ones. The boundary vertices of $S$ form a polygon $∂S$ in $R^3$ which we call the boundary polygon of $S$. Two distinct vertices $v$ and $w$ in $S$ are neighbours if they are the end points of some edge&#xD;&#xA;in $S$. For each $v ∈ V$ , let $$N_v = {w ∈ V : [w, v] ∈ E},$$ the set of neighbours of $v$, where $E = E(S)$ is the set of edges in $S$.&#xD;&#xA;The first step of the method is to choose any points $ψ(v) ∈ R^2$, for $v ∈ V_B$, such that the boundary polygon $∂S$ of $S$ is mapped into a simple polygon $ψ(∂S)$ in the plane. In the second step, for $v ∈ V_I$ , we choose a set of strictly positive values $λ_{vw}$, for $w ∈ N_v$, such that $$ \sum_{w∈N_v}λ_{vw} = 1. (3)$$&#xD;&#xA;Then we let the points $ψ(v)$ in $R^2$, for $v ∈ V_I$ , be the unique solutions of the&#xD;&#xA;linear system of equations $$ ψ(v) = \sum_{w∈N_v}λ_{vw}ψ(w), v ∈ V_I . (4)$$&#xD;&#xA;Since these equations force each point ψ(v) to be a convex combination of its neighbouring points $ψ(w)$, we call $ψ$ a convex combination mapping.&#xD;&#xA;Let us take a closer look at the linear system. We must show that it has a unique solution. To this end, note that it can be rewritten in the form&#xD;&#xA;$$ψ(v) − \sum_{w∈N_v∩V_I}λ_{vw}ψ(w) = \sum_{w∈N_v∩V_B}λ_{vw}ψ(w), v ∈ VI . (5)$$&#xD;&#xA;This can be written as the matrix equation&#xD;&#xA;$$Ax = b,$$&#xD;&#xA;where $x = (ψ(w))_{w∈V_I}$ is the column vector of unknowns in some arbitrary ordering, $b$ is the column vector whose elements are the right hand sides of (5), and the matrix $A = (a_{vw})_{v,w∈V_I}$ has dimension $n × n$, with $n = |V_I|$,&#xD;&#xA;and elements&#xD;&#xA;\begin{equation}&#xD;&#xA;a_{vw} =&#xD;&#xA;    \begin{cases}&#xD;&#xA;      1, w = v,\\&#xD;&#xA;      −λ_{vw}, w ∈ Nv,\\&#xD;&#xA;      0, otherwise&#xD;&#xA;    \end{cases}\,.&#xD;&#xA;\end{equation}&#xD;&#xA;&#xD;&#xA;I don't understand where the $a_{vw}$ values come from. How can this be calculated, please tell me?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42463" PostHistoryTypeId="1" PostId="13859" RevisionGUID="e596a8bf-b526-400e-bd66-c1363ff1e8d8" CreationDate="2023-12-28T16:43:15.830" UserId="21006" Text="How is a system for parametrizing a triangular mesh obtained?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42464" PostHistoryTypeId="3" PostId="13859" RevisionGUID="e596a8bf-b526-400e-bd66-c1363ff1e8d8" CreationDate="2023-12-28T16:43:15.830" UserId="21006" Text="|linear-algebra|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42465" PostHistoryTypeId="50" PostId="13824" RevisionGUID="6fca97f0-b5d4-43f1-bd12-ac1a5a595b14" CreationDate="2023-12-29T03:01:40.203" UserId="-1" />
  <row Id="42467" PostHistoryTypeId="50" PostId="13609" RevisionGUID="9a258a3f-701c-4548-baa4-826ebbe5136c" CreationDate="2023-12-31T19:06:35.787" UserId="-1" />
  <row Id="42468" PostHistoryTypeId="2" PostId="13860" RevisionGUID="dfbd83d4-c07c-4390-94ec-398f69025db6" CreationDate="2024-01-01T12:59:43.507" UserId="20658" Text="a happy New Year to everybody! But, a new year means a new question: In my problem, a mirror is placed in a vertical position, i.e. along the z-axis.The x- and y-axis are perpendicular to this axis. The hemisphere in question is -1 &lt; z &lt; 1, meaning 0 &lt;= theta &lt;= PI. and the azimuthal angle phi is defined by -Pi/2 &lt;= phi &lt;= PI/2. Using a pure diffuse reflection, one can get a random phi as phi = -PI/2+PI*U1 with 0 &lt; U1 &lt; 1 and a random cos(theta) as cos(theta) = 2.*U2-1.&#xD;&#xA;&#xD;&#xA;But what are the similar expressions for Phong or Blin Phong BRDF? Looking in to the well known article by Lafortune and Willems, can this be done by sampling phi in the same way&#xD;&#xA;as above and for sampling cos(theta) changing U2 into U2**(1./n+1)?&#xD;&#xA;&#xD;&#xA;Thanks for reading and answering (?),&#xD;&#xA;&#xD;&#xA;Uwe   " ContentLicense="CC BY-SA 4.0" />
  <row Id="42470" PostHistoryTypeId="1" PostId="13860" RevisionGUID="dfbd83d4-c07c-4390-94ec-398f69025db6" CreationDate="2024-01-01T12:59:43.507" UserId="20658" Text="Blin Phong BRDF in an unusual coordinate system" ContentLicense="CC BY-SA 4.0" />
  <row Id="42471" PostHistoryTypeId="3" PostId="13860" RevisionGUID="dfbd83d4-c07c-4390-94ec-398f69025db6" CreationDate="2024-01-01T12:59:43.507" UserId="20658" Text="|raytracing|brdf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42472" PostHistoryTypeId="2" PostId="13861" RevisionGUID="fd332baf-ee4d-4c8c-8313-323f4c31a3ba" CreationDate="2024-01-02T16:34:39.327" UserId="7952" Text="Define the curves to have a positive and negative side then determine which side of the curve the point in question lies on. &#xD;&#xA;&#xD;&#xA;There are a few ways to do this, one method is to shoot a ray out, usually along one of the primary axis, such as the positive x axis and count how many times the ray crosses the curve. If the number is even it can be considered positive, if it is odd it can be considered negative.&#xD;&#xA;&#xD;&#xA;Do this with every curve and keep a collision count.  If the count is even it is inside, if it is odd it is outside depending on the direction the ray was cast.&#xD;&#xA;&#xD;&#xA;This boils the problem down to colliding a ray with a Bezier curve for which there are many possible solutions.&#xD;&#xA;&#xD;&#xA;It also depends on the winding direction of the curve which can be computed before hand." ContentLicense="CC BY-SA 4.0" />
  <row Id="42474" PostHistoryTypeId="2" PostId="13862" RevisionGUID="34eec985-f713-4b71-b736-73c0f40180d9" CreationDate="2024-01-04T20:19:15.117" UserId="21025" Text="Trying to implement the Cook-Torrance BRDF for my path tracer. Confused about how to do it though. I've seen two approaches:&#xD;&#xA;1: Sample the NDF, evaluate diffuse and specular components and add them weighed by the fresnel (between microfacet normal and view direction?)&#xD;&#xA;2: Based on the fresnel (again, between microfacet normal and view direction?), randomly choose to evaluate a diffuse or specular path. If diffuse, sample uniformly/cosine, and if specular, sample the NDF. Correct/weigh by fresnel factor.&#xD;&#xA;&#xD;&#xA;Why would you use the second approach though? When roughness is 1.0, sampling the NDF should be equivalent to cosine sampling, so approach 2 just seems like a more complicated way to do achieve the same thing.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42476" PostHistoryTypeId="1" PostId="13862" RevisionGUID="34eec985-f713-4b71-b736-73c0f40180d9" CreationDate="2024-01-04T20:19:15.117" UserId="21025" Text="How to approach implementing Cook-Torrence microfacet brdf?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42477" PostHistoryTypeId="3" PostId="13862" RevisionGUID="34eec985-f713-4b71-b736-73c0f40180d9" CreationDate="2024-01-04T20:19:15.117" UserId="21025" Text="|pathtracing|importance-sampling|ggx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42478" PostHistoryTypeId="2" PostId="13863" RevisionGUID="a72b3325-561b-4920-8d0e-4504421901a8" CreationDate="2024-01-05T07:47:50.490" UserId="19537" Text="Let's take a look at what' going on here. The Monte Carlo estimator is given by:&#xD;&#xA;$$&#xD;&#xA;\hat{I} = \sum_{i=1}^N\frac{f(X_i)}{p(X_i)}&#xD;&#xA;$$&#xD;&#xA;The $f(x)$ (evaluation function) here can be writen as (simplified form, ignored some terms in the BRDF):&#xD;&#xA;$$&#xD;&#xA;f(\omega) = \biggl((1 - F)K_df_{\text{Lambert}}(\omega) + FK_sf_{\text{C-T}}(\omega) \biggr)\cos\theta&#xD;&#xA;$$&#xD;&#xA;$F$ here is the Fresnel term, which weights the direct reflected specular radiance and the radiance that *penetrates* to the substrate and gets reflected back. The goal of importance sampling is to approximate $f(x)$ as closely as possible to achieve maximum variance reduction. So what's with the two approaches given?&#xD;&#xA;&#xD;&#xA;- The first approach: since we only sample the NDF, the $p(X)$ should simply be related to $f_{\text{C-T}}$ part (specular component), which is normally good, since diffuse component is generally easy to sample.&#xD;&#xA;- The second approach: Note that we are alternating between Lambertian sampling and Cook-Torrance sampling, therefore the PDF is a weighted one:&#xD;&#xA;$$&#xD;&#xA;p(\omega) = p_{\text{Lambert}}(\omega|\text{diffuse})p(\text{diffuse}) + p_{\text{C-T}}(\omega|\text{specular})p(\text{specular})&#xD;&#xA;$$&#xD;&#xA;So generally, I think the PDF of the second approach is a better approximation to the integrand. So in this way I will prefer the second approach.&#xD;&#xA;&#xD;&#xA;Also, the first approach will always compute NDF sampling and Cook-Torrance BRDF evaluation while the second approach can avoid this. NDF sampling and Cook-Torrance BRDF evaluation are significantly (yes, they are) more complex than our simple, adorable cosine-weighted sampling and Lambertian BRDF evaluation. So this might actually save you some rendering time (but, well, this should be negligible).&#xD;&#xA;&#xD;&#xA;Moreover, we can actually find some similar examples to discourage you from using the first approach. For example, we have a material with IOR = 1. What should happen is that since $F$ is 0, we don't even have to consider the specular lobe. Therefore, it is just a waste of CPU cycles to sample the NDF and evaluate Cook-Torrance BRDF.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;So, when should you use the two approaches? My suggestion is:&#xD;&#xA;- For the first approach: When you are implementing your path tracer on GPU, or the random sampler is complex and takes time to do the state update (like, Sobol or something): 1. GPU works more efficiently when each thread has similar workload (Google: thread divergence). 2. The second approach will have an extra sample to draw from the sampler, so when the sampling process is (too) expensive, the first approach is prefered.&#xD;&#xA;- For the second approach: well you can just implement this in your code, generally. If I recall correctly, Tungsten renderer does this the same way. Do note that if the BSDF contains both reflection and transmission... I think only the second approach works.&#xD;&#xA;&#xD;&#xA;Hope this would help. Feel free to point out anything wrong." ContentLicense="CC BY-SA 4.0" />
  <row Id="42480" PostHistoryTypeId="2" PostId="13864" RevisionGUID="d388f37f-f434-4d82-a203-57e560d02eb5" CreationDate="2024-01-05T09:42:44.517" UserId="21027" Text="Consider a 2-dimensional polygon with unknown vertices $V_1, \dots, V_n \in \mathbb{R}^2$. Given a random set of points $p_1,\dots, p_m \in \mathbb{R}^2$ lying approximately on the perimeter of such a polygon, is it possible to estimate $V_1,\dots, V_n?&#xD;&#xA;&#xD;&#xA;To simplify the problem I assume that: &#xD;&#xA;&#xD;&#xA; - $m\ggg n$. &#xD;&#xA; - the given points $p_1, \dots, p_m$ are ordered along the perimeter, i.e., if we walk along the perimeter, we will find the points in the &quot;circular&quot; order $p_1, p_2, \dots, p_m, p_1, p_2, \dots$&#xD;&#xA; - any observed point is obtained as&#xD;&#xA;\begin{equation*}p_i = \bar{p}_i + v_i \qquad v_i \sim \mathcal{N}(0_{2\times 1}, \sigma^2\,I_2)\end{equation*}&#xD;&#xA;where $\bar{p}_i$ is a point lying exactly on the perimeter and $v_i$ is zero-mean Gaussian noise.&#xD;&#xA;&#xD;&#xA;**My approach to the problem:**&#xD;&#xA;&#xD;&#xA; - Starting from $p_1$, I search for the best line interpolating the&#xD;&#xA;   points $p_1,\dots, p_k$, where $k$ is a design parameter. By &quot;best,&quot;&#xD;&#xA;   I mean in the least squares sense. In particular, $k$ should not be&#xD;&#xA;   too small because I need to compensate for the noise and run a&#xD;&#xA;   meaningful regression, but at the same time, $k$ should not be too&#xD;&#xA;   large because I want to compute the regression only with points lying&#xD;&#xA;   on the same edge of the polygon. As $k$ increases, the risk of&#xD;&#xA;   considering points over different edges increases as well.&#xD;&#xA;&#xD;&#xA; - Given the first optimal line, I search for the first vertex. I&#xD;&#xA;   achieve this task by looking at the distances between the line and&#xD;&#xA;   the points $p_{k+1}, \dots, p_m$. If the distance between the line&#xD;&#xA;   and a point $p_i$ (where $i$ ranges from $k+1$ to $m$) is similar to&#xD;&#xA;   the distances between the line and the points $p_1, \dots, p_k$, then&#xD;&#xA;   I consider $p_i$ as a point on the first edge (by the definition of&#xD;&#xA;   the regression, I consider $p_1, \dots, p_k$ belonging to the first&#xD;&#xA;   edge). When I spot the first &quot;big&quot; deviation, say with point $p_i$, I&#xD;&#xA;   define the first edge $V_1$ as the projection of $p_{i-1}$ over the&#xD;&#xA;   optimal line.&#xD;&#xA;&#xD;&#xA; - I delete $p_1, \dots, p_{i-1}$ from the dataset $p_1,\dots, p_m$.&#xD;&#xA;   Starting from $p_i$, I repeat the previous procedure: I run a local&#xD;&#xA;   search for the optimal line with $p_i,\dots, p_{i+k}$, then I&#xD;&#xA;   identify the second vertex $V_2, and finally, I remove the points&#xD;&#xA;   belonging to the new edge.&#xD;&#xA;&#xD;&#xA; - I repeat the entire process until the dataset becomes empty.&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;I've implemented the method, and unfortunately, it seems to work only for a negligible noise level $\sigma$. My questions are the following:&#xD;&#xA;&#xD;&#xA;Has my problem already been solved? If yes, with which algorithms?&#xD;&#xA;Do you have any suggestions to improve the robustness of my method with respect to the noise?&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="42482" PostHistoryTypeId="1" PostId="13864" RevisionGUID="d388f37f-f434-4d82-a203-57e560d02eb5" CreationDate="2024-01-05T09:42:44.517" UserId="21027" Text="Vertex detection" ContentLicense="CC BY-SA 4.0" />
  <row Id="42483" PostHistoryTypeId="3" PostId="13864" RevisionGUID="d388f37f-f434-4d82-a203-57e560d02eb5" CreationDate="2024-01-05T09:42:44.517" UserId="21027" Text="|edge-detection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42484" PostHistoryTypeId="2" PostId="13865" RevisionGUID="aa5d8e16-2987-4cae-876e-a5c51ad0ec8f" CreationDate="2024-01-05T12:09:10.223" UserId="16800" Text="I am currently writing a fairly basic pathtracer as a compute shader in C++/CUDA, which has been running on a GTX 1080, and I have noticed that when logging some statistics, I get around ~1 billion ray-entity collision checks per second, which translates into a few tens of millions of rays per second, depending on the scene. While changing the scene effects the number of rays produced, the number of ray-entity collision checks (including bvh node collision checks) remains fairly consistent around this ~1 Billion/s mark. &#xD;&#xA;&#xD;&#xA;My concern is that a GTX 1080 is rated for ~8Tflops, and while I understand it's naive to neglect memory transfer costs in non-trivial access patterns, *8000* &quot;operations&quot; per, for the most part, AABB collision checks, feels rather excessive. Does anyone have any experience with optimising a pathtracer, or know what a good value for rays/checks per second might look like? I am more concerned about the collision checks per second, as it seems to reflect the effeciency of the code a lot more and I believe the rays per second has a lot more potential to be improved algorithmically. I would nevertheless appreciate any leads into optimisations I could look into making. &#xD;&#xA;&#xD;&#xA;For reference, the main optimisations I have made thus far are &#xD;&#xA;&#xD;&#xA; - Removing polymorphism from all objects, using an enum to represent object type and a switch statement to bind a collision detection function to an entity&#xD;&#xA;- Using a BVH, implemented similarly as in Peter Shirley's [Raytracing: The Next Week][1] &#xD;&#xA;- Converting scene to a SoA, allocated via cudaMalloc. Though often times device side functions reconstruct structs within the object, which may be voiding some of the benefits it yields.&#xD;&#xA;- inlining where possible, device compiler optimisations -O2 and fast math, branchless code where possible, unrolled loops, passing by const reference or move, generally (what I like to believe) good C++ practice. &#xD;&#xA;- floating point precision (i.e no doubles)&#xD;&#xA;- Reduced quality to 1 reflection, and 1 sample per pixel to check for divergence. Regardless, still around ~1-2 Billion entity collision checks/sec when extrapolated from a tiny runtime&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://raytracing.github.io/books/RayTracingTheNextWeek.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="42486" PostHistoryTypeId="1" PostId="13865" RevisionGUID="aa5d8e16-2987-4cae-876e-a5c51ad0ec8f" CreationDate="2024-01-05T12:09:10.223" UserId="16800" Text="What performance to expect from an optimised pathtracer?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42487" PostHistoryTypeId="3" PostId="13865" RevisionGUID="aa5d8e16-2987-4cae-876e-a5c51ad0ec8f" CreationDate="2024-01-05T12:09:10.223" UserId="16800" Text="|pathtracing|c++|optimisation|cuda|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42488" PostHistoryTypeId="2" PostId="13866" RevisionGUID="296d4e09-4cfc-4de7-9753-0ea6975a7f2b" CreationDate="2024-01-06T12:41:32.497" UserId="21031" Text="This question is about the best strategy to choose a local_size in OpenGL's compute shader.&#xD;&#xA;The application is a Lattice Boltzmann Method (LBM) with a number of cells ranging from 100,000 to 1 million. This LBM will be run by end-users with a variety of different graphics cards and they will set the number of cells depending on the capability of their machine. &#xD;&#xA;&#xD;&#xA;Although this LBM is 2d, the work to dispatch to the compute shader is, as far as I understand, one-dimensional since each cell can be processed independently.&#xD;&#xA;&#xD;&#xA;As it is right now, I've set up the work in the following way. &#xD;&#xA;&#xD;&#xA;In the compute shader:&#xD;&#xA;&#xD;&#xA;    #define LOCAL_GROUP_SIZE 64&#xD;&#xA;    layout (local_size_x = LOCAL_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;&#xD;&#xA;&#xD;&#xA;And in the calling function&#xD;&#xA;&#xD;&#xA;    int nGroups = int(nCells/LOCAL_GROUP_SIZE);&#xD;&#xA;    nGroups++; // nGroups x LOCAL_GROUP_SIZE must be greater than the number of cells, otherwise the back ones won't be processed&#xD;&#xA;    // [...]&#xD;&#xA;    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssboCells.bufferId());&#xD;&#xA;    glDispatchCompute(nGroups, 1, 1);&#xD;&#xA;    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);&#xD;&#xA;    glFinish();&#xD;&#xA;&#xD;&#xA;The questions I have in mind:&#xD;&#xA;&#xD;&#xA; 1. How to choose the LOCAL_GROUP_SIZE to get good performance on average over a variety of GPUs? As far as I understand this size is required to be hard-coded in the CS and cannot be set at run time depending on the user's GPU. &#xD;&#xA; 2. Is there any reason to use a 2 or 3 dimensional work&#xD;&#xA;    group in this case?  &#xD;&#xA; 3. Not sure if the glMemoryBarrier is of any use&#xD;&#xA;    given that each cell is processed independently.&#xD;&#xA;&#xD;&#xA;Thanks in advance for any insight.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42490" PostHistoryTypeId="1" PostId="13866" RevisionGUID="296d4e09-4cfc-4de7-9753-0ea6975a7f2b" CreationDate="2024-01-06T12:41:32.497" UserId="21031" Text="OpenGL - Compute Shader - How to set local_size" ContentLicense="CC BY-SA 4.0" />
  <row Id="42491" PostHistoryTypeId="3" PostId="13866" RevisionGUID="296d4e09-4cfc-4de7-9753-0ea6975a7f2b" CreationDate="2024-01-06T12:41:32.497" UserId="21031" Text="|opengl|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42492" PostHistoryTypeId="50" PostId="13618" RevisionGUID="c1fadcd4-bc05-44ea-bf70-c6367d1b2cf1" CreationDate="2024-01-06T14:02:50.327" UserId="-1" />
  <row Id="42493" PostHistoryTypeId="2" PostId="13867" RevisionGUID="da8dabe2-1ba4-4591-92b8-f0f4d35116c5" CreationDate="2024-01-06T18:52:46.810" UserId="13273" Text="So you say, that each cell do their own stuff without communication in between... So the local work group size will not affect on the result. &#xD;&#xA;&#xD;&#xA;&gt; How to choose the LOCAL_GROUP_SIZE to get good performance on average over a variety of GPUs? As far as I understand this size is required to be hard-coded in the CS and cannot be set at run time depending on the user's GPU.&#xD;&#xA;&#xD;&#xA;In general, Nvidia uses 32 invocations per warp, whereas AMD uses 64 invocations. As you mentioned, the local work group size is hardcoded in the shader... But the shader can be compiled on runtime. So you can request the GPU model and decide which number to use. &#xD;&#xA;&#xD;&#xA;&gt; Is there any reason to use a 2 or 3 dimensional work group in this case?&#xD;&#xA;&#xD;&#xA;Your problem seems to be one dimensional. So I would keep it one dimensional. &#xD;&#xA;&#xD;&#xA;I don't know the Lattice Boltzmann Method... But have in mind, that when invocations within the same workgroup go to different conditional states (if and else), your performance will drop!&#xD;&#xA;Because the invocations do all the same at nearly the same time. So if e. G. One invocation within the group goes into the 'if' part, the others will wait until the entire 'if' part is done. Same with the other invocations... If they go to the 'else' part, the one invocation which goes to the 'if' part will wait until the 'else' part is done...&#xD;&#xA;Because of that there are different strategies on how to group the tasks.&#xD;&#xA;&#xD;&#xA;For example, we have a long 'if' and a long 'else' part... It can make sense to first check where each invocation goes to and then in a second step group the tasks which go to the same condition together.&#xD;&#xA;&#xD;&#xA;But this does not make sense for all conditional paths, because this method also takes some time.&#xD;&#xA;&#xD;&#xA;But in general a rule of thumb is, keep the workgroups as small as possible with respect to the multiple of a warp/wave size (nvidia 32, AMD 64). This is useful because your GPU is limited in invocations which can do work at the same time. So your GPU will load a few workgroups to execute. When a workgroup has finished, another workgroup can be loaded. So when having only one workgroup where invocations go to both conditional states, only this one workgroup will need time. The other workgroups will be calculated fast and will free their slot for the next workgroup in the queue while the long workgroup still do some work. When keeping the local work group size small, less workgroups will pop up with both conditions. And less invocations are blocked. " ContentLicense="CC BY-SA 4.0" />
  <row Id="42495" PostHistoryTypeId="50" PostId="5697" RevisionGUID="2d99fd5a-f761-4857-8a4f-2d16a628f7bb" CreationDate="2024-01-07T16:08:46.260" UserId="-1" />
  <row Id="42496" PostHistoryTypeId="2" PostId="13868" RevisionGUID="a52a1fce-45a7-4a3a-abdd-1b4d6227cf2d" CreationDate="2024-01-09T15:03:59.753" UserId="15886" Text="While it's an old question, someone may find the following approach useful nonetheless.&#xD;&#xA;&#xD;&#xA; 1. Calculate the (axis aligned) bounding box for your input point cloud.&#xD;&#xA; 2. From that, calculate the (axis aligned) bounding cube centered around the centroid of the bounding box (so the two are either identical or the bounding box is fully enclosed in the bounding cube).&#xD;&#xA; 3. Scale the bounding cube up by a factor of three about its centroid (so the scaling will not implicitly transform it in worldspace).&#xD;&#xA;4. Derrive any of the regular tetrahedra embedded in the cube. That is, take the diagonals of two opposing faces of the cube, but such that both diagonals are orthogonal rather than colinear. The four cube vertices connected to those two diagonals are the vertices of your bounding (regular) tetrahedron.&#xD;&#xA;&#xD;&#xA;____________________&#xD;&#xA;[![Regular octahedron (red) and embedded (dual) cube (yellow)][1]][1]&#xD;&#xA;The yellow cube's vertices touch the red octahedron's faces on their centroids.&#xD;&#xA;&#xD;&#xA;[![Regular tetrahedron (yellow) embedded in cube (blue)][3]][3]&#xD;&#xA;The red octahedron's vertices are the centroids of the blue cube. The blue cube's edge length is three times that of the yellow cube. The red octahedron is identical in both images.&#xD;&#xA;&#xD;&#xA;[![Regular octahedron (orange) embedded in (yellow) regular tetrahedron][2]][2]&#xD;&#xA;The orange octahedron's vertices are the midpoints of the yellow regular tetrahedron. The yellow tetrahedron's bounding box is the blue cube shown above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_______________________&#xD;&#xA;_______________________&#xD;&#xA;Explanation: A cube's dual is a regular octahedron. So if we take the centroid of each cube face, we get the embedded (dual) octahedron.&#xD;&#xA;&#xD;&#xA;This octahedron's volume equals one third of the cube's volume. As the duality works both ways, we can, for a given minimum bounding cube, imagine a regular octahedron inside which our cube is embedded itself.&#xD;&#xA;This bounding octahedron naturally has to be three times the size of the bounding cube.&#xD;&#xA;&#xD;&#xA;A regular octahedron on the other hand can be neatly embedded in a regular tetrahedron, where the octahedron's vertices are the midpoints of the tetrahedron's edges.&#xD;&#xA;&#xD;&#xA;A regular tetrahedron can be embedded in a cube such that four vertices of the cube make up for the tetrahedron's vertices and the tetrahedron's edges are all diagonals of the cube's face.&#xD;&#xA;&#xD;&#xA;It follows we can imagine a regular octahedron which embeds our original bounding cube while itself being embedded in a regular tetrahedron (which we need), itself embedded in a larger cube. The volume of the tetrahedron is exactly one third of that of the large cube, which is where the above-mentioned scaling factor comes from.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eMddF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LwVNi.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/iu8Nt.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42498" PostHistoryTypeId="2" PostId="13869" RevisionGUID="3f3b38f3-c277-4c5c-9b84-bb0d6553c591" CreationDate="2024-01-10T12:00:28.257" UserId="21042" Text="I wonder, why black-white pixels pattern as seen on this page http://www.lagom.nl/lcd-test/clock_phase.php is displayed wrongly by UHD LCDs (on all i tried).&#xD;&#xA;Please note, that it must be displayed 1:1 (no browser / windows zooming).&#xD;&#xA;&#xD;&#xA;On some monitors, that pattern is immediately seen as very green, usually on top it's most green, in lower parts there is not so much green. On some it's not so obvious, but to spot it, it's e.g. enough to lower contract from 75-80 to e.g. 50-60.&#xD;&#xA;&#xD;&#xA;Even more, if pattern is present on screen more time, with certain offset, then screen becomes purple. See this foto, it's from lenovo y32p-30 display:&#xD;&#xA;https://rt.sk/~jmi/uhd_issue/lenovo_foto.jpg&#xD;&#xA;&#xD;&#xA;This is the screenshot, so you can try yourself: https://rt.sk/~jmi/uhd_issue/lenovo.png (view 1:1 with no scaling)&#xD;&#xA;&#xD;&#xA;On dell S2722qc it's same issue (better visible if contrast is lowered to 50-60) with green and purple.&#xD;&#xA;&#xD;&#xA;Video demonstration:&#xD;&#xA;https://rt.sk/~jmi/uhd_issue/PXL_20231226_221917539.TS.mp4&#xD;&#xA;&#xD;&#xA;Important: when i open OSD menu, then on lines where OSD is located are less green than without OSD. Hence visible &quot;border line&quot; between two areas appears, where y-possition is top and bottom of OSD menu. See photos for better understanding:&#xD;&#xA;https://rt.sk/~jmi/uhd_issue/PXL_20231226_222856271.MP.jpg&#xD;&#xA;https://rt.sk/~jmi/uhd_issue/PXL_20231227_111708420.MP.jpg&#xD;&#xA;&#xD;&#xA;What is reason of such behavior?&#xD;&#xA;&#xD;&#xA;Now i'm testing asus proart PA279CRV. Here things are little different. From dell xps over both hdmi and usbc pattern was greenish as usually. But on desktop PC it's greenish only for fraction of second and then it corrects itself. Why does it fix itself?&#xD;&#xA;&#xD;&#xA;And i spotted new problem, e.g. when having dark bookmark tab on side and switch back to tab such pattern, for fraction of second a bookmark tab contains lots of lines accross.&#xD;&#xA;While experimenting more, i found also cases, when problem is persistent (not just flicker) and is best visible on artificial image (again must be observed without any zooming/scaling):&#xD;&#xA;https://rt.sk/~jmi/uhd_issue/asus_issue_1.png&#xD;&#xA;&#xD;&#xA;Result is similar on asus and dell S2722QC  (don't have lenovo anymore and any other to test more): &#xD;&#xA;https://rt.sk/~jmi/uhd_issue/PXL_20240110_112757340.MP.jpg&#xD;&#xA;zoomed links will be posted to comment as i cannot use more links as newbe user.&#xD;&#xA;&#xD;&#xA;Can someone explain this? Is it caused by my PC (input signal quality) or by monitor? Is it common issue, or was i just unlucky on selecting affected monitor models?&#xD;&#xA;&#xD;&#xA;I tried several UHD monitors, combined with several PCs connected over different cables (HDMI/DP/usbC). Issue with greenish picture was present in all combinations.&#xD;&#xA;Doesn't matter if pattern is displayed from browser or image viewer.&#xD;&#xA;&#xD;&#xA;Note: some monitors allow to not use full signal range (0-255), but only e.g. 16-254 or 16-235. Make sure to use full range, as in my tests, some of them &quot;worked&quot; fine if full range was not used.&#xD;&#xA;&#xD;&#xA;thank you&#xD;&#xA;&#xD;&#xA;best regards&#xD;&#xA;&#xD;&#xA;saliem12" ContentLicense="CC BY-SA 4.0" />
  <row Id="42500" PostHistoryTypeId="1" PostId="13869" RevisionGUID="3f3b38f3-c277-4c5c-9b84-bb0d6553c591" CreationDate="2024-01-10T12:00:28.257" UserId="21042" Text="UHD monitor showing artifacts for cetrain patterns, e.g. lighter lines, or image turns to green on purple" ContentLicense="CC BY-SA 4.0" />
  <row Id="42501" PostHistoryTypeId="3" PostId="13869" RevisionGUID="3f3b38f3-c277-4c5c-9b84-bb0d6553c591" CreationDate="2024-01-10T12:00:28.257" UserId="21042" Text="|color|processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42502" PostHistoryTypeId="50" PostId="12414" RevisionGUID="949ce789-0b07-4820-ac40-4e03d16dc78a" CreationDate="2024-01-10T12:03:30.397" UserId="-1" />
  <row Id="42509" PostHistoryTypeId="5" PostId="13868" RevisionGUID="ce321975-cb4e-4ce0-bcd6-507b78cd833b" CreationDate="2024-01-11T00:00:06.027" UserId="15886" Comment="added 41 characters in body" Text="While it's an old question, someone may find the following approach useful nonetheless.&#xD;&#xA;&#xD;&#xA; 1. Calculate the (axis aligned) bounding box for your input point cloud.&#xD;&#xA; 2. From that, calculate the (axis aligned) bounding cube centered around the centroid of the bounding box (so the two are either identical or the bounding box is fully enclosed in the bounding cube).&#xD;&#xA; 3. Scale the bounding cube up by a factor of three about its centroid (so the scaling will not implicitly transform it in worldspace).&#xD;&#xA;4. Derrive any of the regular tetrahedra embedded in the cube. That is, take the diagonals of two opposing faces of the cube, more precisely the top- and bottom-face, but such that both diagonals are orthogonal rather than colinear. The four cube vertices connected to those two diagonals are the vertices of your bounding (regular) tetrahedron.&#xD;&#xA;&#xD;&#xA;____________________&#xD;&#xA;[![Regular octahedron (red) and embedded (dual) cube (yellow)][1]][1]&#xD;&#xA;The yellow cube's vertices touch the red octahedron's faces on their centroids.&#xD;&#xA;&#xD;&#xA;[![Regular tetrahedron (yellow) embedded in cube (blue)][3]][3]&#xD;&#xA;The red octahedron's vertices are the centroids of the blue cube. The blue cube's edge length is three times that of the yellow cube. The red octahedron is identical in both images.&#xD;&#xA;&#xD;&#xA;[![Regular octahedron (orange) embedded in (yellow) regular tetrahedron][2]][2]&#xD;&#xA;The orange octahedron's vertices are the midpoints of the yellow regular tetrahedron. The yellow tetrahedron's bounding box is the blue cube shown above.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;_______________________&#xD;&#xA;_______________________&#xD;&#xA;Explanation: A cube's dual is a regular octahedron. So if we take the centroid of each cube face, we get the embedded (dual) octahedron.&#xD;&#xA;&#xD;&#xA;This octahedron's volume equals one third of the cube's volume. As the duality works both ways, we can, for a given minimum bounding cube, imagine a regular octahedron inside which our cube is embedded itself.&#xD;&#xA;This bounding octahedron naturally has to be three times the size of the bounding cube.&#xD;&#xA;&#xD;&#xA;A regular octahedron on the other hand can be neatly embedded in a regular tetrahedron, where the octahedron's vertices are the midpoints of the tetrahedron's edges.&#xD;&#xA;&#xD;&#xA;A regular tetrahedron can be embedded in a cube such that four vertices of the cube make up for the tetrahedron's vertices and the tetrahedron's edges are all diagonals of the cube's face.&#xD;&#xA;&#xD;&#xA;It follows we can imagine a regular octahedron which embeds our original bounding cube while itself being embedded in a regular tetrahedron (which we need), itself embedded in a larger cube. The volume of the tetrahedron is exactly one third of that of the large cube, which is where the above-mentioned scaling factor comes from.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/eMddF.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/LwVNi.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/iu8Nt.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42510" PostHistoryTypeId="2" PostId="13872" RevisionGUID="aad3ab13-9d41-4ccb-9676-ad08adfce95b" CreationDate="2024-01-11T12:41:20.300" UserId="7952" Text="Monitors are made up of red green and blue components those components have different visibility from different angles and distances. This can effect how we perceive the image on the monitor.&#xD;&#xA;&#xD;&#xA;This can can be seen in the linked images as the color shifts from green at the edges towards gray in the center. You can get virtually any monitor to exhibit this behavior. Camera's make the issue even more apparent, especially if the image is taken at an angle.&#xD;&#xA;&#xD;&#xA;Why green? Our eyes are more sensitive to colors at around 550nm in day light which we perceive as green. Our eye's are also sensitive to blue's (450nm) blue+green is purple. Finally our eye's are least sensitive to red, around 700nm.&#xD;&#xA;&#xD;&#xA;So if you cover an entire screen with a gray color that sets all the red,blue, and green components to the same brightness small shifts in brightness resulting from viewing angle of those components will cause us to perceive the color differently, and the most likely colors we will see are greens followed by blues. Which gives the effect listed in the question.&#xD;&#xA;&#xD;&#xA;On both of my monitors when viewed straight on with the monitors at eye level the images look like I expect. But if I change my viewing angle just by moving my seated position I can get them to shift towards green, although on both of my monitors the effect is much less pronounced then in the linked images.&#xD;&#xA;&#xD;&#xA;I should add the hardware plays a role here, and small difference in brightness caused by the technical details of how a monitor works also cause some of this effect.&#xD;&#xA;&#xD;&#xA;This exemplifies how setting up monitors correctly effects viewing.&#xD;&#xA;&#xD;&#xA;Finally, I find myself wondering what my cat see's when viewing this effect." ContentLicense="CC BY-SA 4.0" />
  <row Id="42513" PostHistoryTypeId="2" PostId="13873" RevisionGUID="688c8229-83ed-4ade-9329-b92da78b2be3" CreationDate="2024-01-13T11:17:26.540" UserId="21055" Text="I am trying to scale the value of the input vector along one axis depending on the value of the input vector along another axis, while leaving everything else unchanged.&#xD;&#xA;&#xD;&#xA;Given (pseudocode):&#xD;&#xA;&#xD;&#xA;    Vec4   V_in{x,y,z,1}&#xD;&#xA;    Mat4x4 M&#xD;&#xA;    Vec4   V_m = V_in * M&#xD;&#xA;    Vec4   V_out = V_m / V_m.w&#xD;&#xA;&#xD;&#xA;I want to design `M` such that (for example):&#xD;&#xA;&#xD;&#xA;    V_out.x == V_in.x&#xD;&#xA;    V_out.y == V_in.y / (V_in.x * (N - 1) + 1)&#xD;&#xA;    V_out.z == V_in.z&#xD;&#xA;&#xD;&#xA;This example should achieve a multiplication of Y between 1 and 1/N for an input X from 0 to 1.&#xD;&#xA;&#xD;&#xA;I did succeed in scaling the Y axis, but was not able to keep the other axes constant.&#xD;&#xA;&#xD;&#xA;Is this possible?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42515" PostHistoryTypeId="1" PostId="13873" RevisionGUID="688c8229-83ed-4ade-9329-b92da78b2be3" CreationDate="2024-01-13T11:17:26.540" UserId="21055" Text="4x4 matrix to scale only one axis depending on another axis" ContentLicense="CC BY-SA 4.0" />
  <row Id="42516" PostHistoryTypeId="3" PostId="13873" RevisionGUID="688c8229-83ed-4ade-9329-b92da78b2be3" CreationDate="2024-01-13T11:17:26.540" UserId="21055" Text="|transformations|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42517" PostHistoryTypeId="50" PostId="13633" RevisionGUID="18dce81d-30fb-467a-a07d-91798cf3eef2" CreationDate="2024-01-14T12:04:55.587" UserId="-1" />
  <row Id="42518" PostHistoryTypeId="50" PostId="9781" RevisionGUID="13640622-87a1-4721-9486-71f9fbc13f51" CreationDate="2024-01-14T23:05:15.660" UserId="-1" />
  <row Id="42519" PostHistoryTypeId="2" PostId="13874" RevisionGUID="768352c7-0be3-41f5-9181-aa5b419ae7a1" CreationDate="2024-01-14T23:07:40.203" UserId="21062" Text="Here is another approach that handles the case where multiple components may be the minimum/maximum and you want to handle that. You calculate a &quot;mask&quot; that indicates whether the component is a min/max.&#xD;&#xA;&#xD;&#xA;    bvec3 mask = lessThanEqual(vector.xyz, min(vector.yzx, vector.zxy); // makes a &quot;one-hot&quot; bool vector, where the min component(s) is true and the others are false.&#xD;&#xA;&#xD;&#xA;To use it, multiply your operation by the mask, e.g.&#xD;&#xA;&#xD;&#xA;    vec3f colorMask = greaterThanEqual(color.rgb, min(color.gbr, color.brg));&#xD;&#xA;    vec3f maxColor = color * vec3f(colorMask);&#xD;&#xA;&#xD;&#xA;You can also convert the vector to a scalar, like so:&#xD;&#xA;&#xD;&#xA;    uint index = dot(ivec3(mask), ivec3(0, 1, 2));&#xD;&#xA;&#xD;&#xA;But that fails if multiple components are minimum/maximum." ContentLicense="CC BY-SA 4.0" />
  <row Id="42521" PostHistoryTypeId="50" PostId="10177" RevisionGUID="25dc15bd-057c-4089-acd5-056661617808" CreationDate="2024-01-15T07:06:00.820" UserId="-1" />
  <row Id="42524" PostHistoryTypeId="5" PostId="13142" RevisionGUID="faccadfe-8a07-48a0-a386-3697b9b5e33e" CreationDate="2024-01-16T16:20:53.900" UserId="445" Comment="note on the existence of “maxel”." Text="As I understand it, the usual concept of a “material” in computer graphics, particularly 3D modeling, is a set of parameters (_for example,_ color, specular reflectivity, IOR, light emission, etc.), some specified by textures and some by constants, that are sufficient to simulate the appearance of some substance when applied to some shape.&#xD;&#xA;&#xD;&#xA;However, when computing the appearance of a single _point on a surface_ (or within a volume), these parameters take on single values (which may have been sampled from a texture) which are sufficient for the shader or raytracer to compute the effect of hitting that surface with that ray(/viewing angle).&#xD;&#xA;&#xD;&#xA;**Is there an established/recognizable name for the full set (whatever the shading technique in use requires) of these single-point values,** as distinct from the overall material? (Or, perhaps, are these too just “the material”?)&#xD;&#xA;&#xD;&#xA;* The best description that has been suggested to me so far is “material sample” (sample of the material) but ideally, I would like a term that does not as strongly suggest that it is a piece of a larger entity that already existed, but rather an “atom” itself that could perhaps, but does not have to, be _assembled with others to create_ a material (including procedural generation that does not necessarily contain the original value at any point). I don't expect to necessarily find that, though.&#xD;&#xA;&#xD;&#xA;* The term “maxel” is in active use as a “material element” by analogy with “pixel” and “voxel”. However, its usage is exclusively [in materials science and additive manufacturing](https://en.wikipedia.org/wiki/Functionally_graded_material), to describe a mix of substances (materials) that might make up a part of an object, so it is the wrong quantities and also a point in the wrong space/axes — object/mesh space rather than material space. One could reuse the word construction but that seems likely to increase confusion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;While the reason I'm asking this is to come up with vocabulary I can use in my program, to keep this question reasonably objective, please do not propose newly invented names — I'm only looking for any established terminology that I could use or at least take inspiration from." ContentLicense="CC BY-SA 4.0" />
  <row Id="42525" PostHistoryTypeId="5" PostId="13142" RevisionGUID="2eb12363-67f0-4308-9771-cd679a4581e4" CreationDate="2024-01-16T19:56:53.053" UserId="445" Comment="added 75 characters in body" Text="As I understand it, the usual concept of a “material” in computer graphics, particularly 3D modeling, is a set of parameters (_for example,_ color, specular reflectivity, IOR, light emission, etc.), some specified by textures and some by constants, that are sufficient to simulate the appearance of some substance when applied to some shape.&#xD;&#xA;&#xD;&#xA;However, when computing the appearance of a single _point on a surface_ (or within a volume), these parameters take on single values (which may have been sampled from a texture) which are sufficient for the shader or raytracer to compute the effect of hitting/viewing that surface (when combined with the incoming and outgoing ray directions, which are not part of this sample).&#xD;&#xA;&#xD;&#xA;**Is there an established/recognizable name for the full set (whatever the shading technique in use requires) of these single-point values,** as distinct from the overall material? (Or, perhaps, are these too just “the material”?)&#xD;&#xA;&#xD;&#xA;* The best description that has been suggested to me so far is “material sample” (sample of the material) but ideally, I would like a term that does not as strongly suggest that it is a piece of a larger entity that already existed, but rather an “atom” itself that could perhaps, but does not have to, be _assembled with others to create_ a material (including procedural generation that does not necessarily contain the original value at any point). I don't expect to necessarily find that, though.&#xD;&#xA;&#xD;&#xA;* The term “maxel” is in active use as a “material element” by analogy with “pixel” and “voxel”. However, its usage is exclusively [in materials science and additive manufacturing](https://en.wikipedia.org/wiki/Functionally_graded_material), to describe a mix of substances (materials) that might make up a part of an object, so it is the wrong quantities and also a point in the wrong space/axes — object/mesh space rather than material space. One could reuse the word construction but that seems likely to increase confusion.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;While the reason I'm asking this is to come up with vocabulary I can use in my program, to keep this question reasonably objective, please do not propose newly invented names — I'm only looking for any established terminology that I could use or at least take inspiration from." ContentLicense="CC BY-SA 4.0" />
  <row Id="42526" PostHistoryTypeId="2" PostId="13875" RevisionGUID="fb9bca24-c15b-4329-9c09-e9020a48dc66" CreationDate="2024-01-17T12:28:16.677" UserId="13273" Text="Barycentric coordinates of a triangle are very useful for interpolating texture coordinates, for example. Each corner contains the texture coordinate and multiplies this coordinate by the barycentric coordinate. (very simple). Also very useful is that the addition of all 3 components of the barycentric coordinate is always `1`. The barycentric coordinate is therefore well suited for the interpolation of information based on corner points. But can it also be used to interpolate triangle edge based data instead of vertex based data?&#xD;&#xA;&#xD;&#xA;**The problem:**&#xD;&#xA;&#xD;&#xA;I have a triangular mesh that needs to be tessellated in different ways depending on a variable called `biome`. Within the tessellation control shader, each edge generates a `biome` number depending on the position and normals of the vertices. The normals are stored per vertex and not per face, so that neighboring faces receive the same normal for common vertices. The neighboring edge of two neighboring triangles will therefore generate the same `biome` number. &#xD;&#xA;This is very important as otherwise holes will appear during the evaluation shader.&#xD;&#xA;These `biome` numbers are stored in the following way:&#xD;&#xA;&#xD;&#xA;A varying `vec3` patch variable contains the 3 `biom` numbers. The number generated by vertex0 and vertex1 is stored under index [2]. The number generated by vertex1 and vertex2 is stored under index [0]. And vertex0 and vertex2 is stored in index [1]. In comparison to `gl_TessCoord`, the biome number of the edge is therefore stored in the opposite corner.&#xD;&#xA;The tessellation evaluation shader receives the barycentric coordinates via the `gl_TessCoord` vector. So this is the point where I want to start.&#xD;&#xA;&#xD;&#xA;Now I am looking for an algorithm that performs the interpolation between the edges.&#xD;&#xA;&#xD;&#xA;An image shows more than 100 words...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Within this triangle, the edges should retain their biome numbers (no interpolation at the edges), and the area in between should be an interpolation of the numbers.&#xD;&#xA;&#xD;&#xA;So, as with barycentric coordinates, the sum of the weights should not be greater than 1.&#xD;&#xA;&#xD;&#xA;I know that the vertices are not defined within the interpolation. That will be handled later... so don't think about it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pp9ko.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42528" PostHistoryTypeId="1" PostId="13875" RevisionGUID="fb9bca24-c15b-4329-9c09-e9020a48dc66" CreationDate="2024-01-17T12:28:16.677" UserId="13273" Text="triangle barycentric coordinates interpolate edge dependent" ContentLicense="CC BY-SA 4.0" />
  <row Id="42529" PostHistoryTypeId="3" PostId="13875" RevisionGUID="fb9bca24-c15b-4329-9c09-e9020a48dc66" CreationDate="2024-01-17T12:28:16.677" UserId="13273" Text="|interpolation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42530" PostHistoryTypeId="5" PostId="13875" RevisionGUID="1cc5c964-16f6-4688-9968-ca320599a0f2" CreationDate="2024-01-17T13:00:28.370" UserId="13273" Comment="deleted 10 characters in body" Text="Barycentric coordinates of a triangle are very useful for interpolating texture coordinates, for example. Each corner contains the texture coordinate and multiplies this coordinate by the barycentric coordinate. (very simple). Also very useful is that the addition of all 3 components of the barycentric coordinate is always `1`. The barycentric coordinate is therefore well suited for the interpolation of information based on corner points. But can it also be used to interpolate triangle edge based data instead of vertex based data?&#xD;&#xA;&#xD;&#xA;**The problem:**&#xD;&#xA;&#xD;&#xA;I have a triangular mesh that needs to be tessellated in different ways depending on a variable called `biome`. Within the tessellation control shader, each edge generates a `biome` number depending on the position and normals of the vertices. The normals are stored per vertex and not per face, so that neighboring faces receive the same normal for common vertices. The neighboring edge of two neighboring triangles will therefore generate the same `biome` number. &#xD;&#xA;This is very important as otherwise holes will appear during the evaluation shader.&#xD;&#xA;These `biome` numbers are stored in the following way:&#xD;&#xA;&#xD;&#xA;A varying `vec3` patch variable contains the 3 `biom` numbers. The number generated by vertex0 and vertex1 is stored under index [2]. The number generated by vertex1 and vertex2 is stored under index [0]. And vertex0 and vertex2 is stored in index [1]. In comparison to `gl_TessCoord`, the biome number of the edge is therefore stored in the opposite corner.&#xD;&#xA;The tessellation evaluation shader receives the barycentric coordinates via the `gl_TessCoord` vector. So this is the point where I want to start.&#xD;&#xA;&#xD;&#xA;Now I am looking for an algorithm that performs the interpolation between the edges.&#xD;&#xA;&#xD;&#xA;An image shows more than 1000 words...&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Within this triangle, the edges should retain their biome numbers (no interpolation at the edges), and the area in between should be an interpolation of the numbers.&#xD;&#xA;&#xD;&#xA;So, as with barycentric coordinates, the sum of the weights should be around 1.&#xD;&#xA;&#xD;&#xA;I know that the vertices are not defined within the interpolation. That will be handled later... so don't think about it.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/pp9ko.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42531" PostHistoryTypeId="2" PostId="13876" RevisionGUID="47cb17dd-aa0e-4e0f-a3f3-6b95208f1adb" CreationDate="2024-01-17T16:03:14.353" UserId="7724" Text="Let $[\lambda_0, \lambda_1, \lambda_2]$ be the barycentric coordinates with respect to triangle $v_0$, $v_1$, $v_2$. In the following all subscripts are taken modulo $3$.&#xD;&#xA;&#xD;&#xA;For each side $s_i$ (the edge $v_iv_{i+1}$) we can construct functions $h_i$. Where $$h_i = 1 - \lambda_i - \lambda_{i+1}.$$&#xD;&#xA;&#xD;&#xA;Then we can create rational blending functions $\alpha_i = \frac{h_{i-1}}{h_{i-1} + h_i}$ and $\beta_i = \frac{h_{i+1}}{h_{i+1} + h_i}$. &#xD;&#xA;&#xD;&#xA;By combining these blending functions we can set up the following function for side $s_i$&#xD;&#xA;&#xD;&#xA;$$e_i = \lambda_i \alpha_i + \lambda_{i+1} \beta_i.$$ This function has the following properties. It is $1$ everywhere on $s_i$ and $0$ on all $s_j$ where $i \neq j$. It are singular at the vertices $v_i$ and $v_{i+1}$ (division by zero) and on the triangle it is smooth.&#xD;&#xA;&#xD;&#xA;We can then interpolate edge values using: &#xD;&#xA;&#xD;&#xA;$$F(\lambda) = \frac{\text{biom}_0 \cdot e_0 + \text{biom}_1 \cdot e_1 + \text{biom}_2 \cdot e_2}{S}$$&#xD;&#xA;&#xD;&#xA;where S is the sum of all $e_i$ in order to normalize the equation (making all functions sum to one). The function $\alpha_i$ and $\beta_i$ are singular at the vertices, but you said I should not worry about this.&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="42533" PostHistoryTypeId="5" PostId="13876" RevisionGUID="56484e34-2323-4864-bb53-e4dc02d9e030" CreationDate="2024-01-18T21:33:32.310" UserId="7724" Comment="I added a shader implementation of the interpolation." Text="Let $[\lambda_0, \lambda_1, \lambda_2]$ be the barycentric coordinates with respect to triangle $v_0$, $v_1$, $v_2$. In the following all subscripts are taken modulo $3$.&#xD;&#xA;&#xD;&#xA;For each side $s_i$ (the edge $v_iv_{i+1}$) we can construct functions $h_i$. Where $$h_i = 1 - \lambda_i - \lambda_{i+1}.$$&#xD;&#xA;&#xD;&#xA;Then we can create rational blending functions $\alpha_i = \frac{h_{i-1}}{h_{i-1} + h_i}$ and $\beta_i = \frac{h_{i+1}}{h_{i+1} + h_i}$. &#xD;&#xA;&#xD;&#xA;By combining these blending functions we can set up the following function for side $s_i$&#xD;&#xA;&#xD;&#xA;$$e_i = \lambda_i \alpha_i + \lambda_{i+1} \beta_i.$$ This function has the following properties. It is $1$ everywhere on $s_i$ and $0$ on all $s_j$ where $i \neq j$. It are singular at the vertices $v_i$ and $v_{i+1}$ (division by zero) and on the triangle it is smooth.&#xD;&#xA;&#xD;&#xA;We can then interpolate edge values using: &#xD;&#xA;&#xD;&#xA;$$F(\lambda) = \frac{\text{biom}_0 \cdot e_0 + \text{biom}_1 \cdot e_1 + \text{biom}_2 \cdot e_2}{S}$$&#xD;&#xA;&#xD;&#xA;where $S$ is the sum of all $e_i$ in order to normalize the equation (making all functions sum to one). However, given the nice properties of barycentric coordinates in turns out that the sum of $e_i$ is already $1$. The function $\alpha_i$ and $\beta_i$ are singular at the vertices, but you said I should not worry about this.&#xD;&#xA; &#xD;&#xA;I implemented this in a Shadertoy so you can see what the interpolation looks like:&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/MfsSRs&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42534" PostHistoryTypeId="2" PostId="13877" RevisionGUID="49721586-0e8e-49f2-b5c2-3f3b3dcb3583" CreationDate="2024-01-19T11:39:12.000" UserId="13273" Text="I have a triangular mesh with common vertices (VBO and EBO/IBO) that contain the normal vectors.&#xD;&#xA;If I tessellate this mesh, the subdivision of the triangle edges of neighboring triangles has the same tessellation level. (The mesh therefore has no holes).&#xD;&#xA;&#xD;&#xA;Each partial triangle created by the tessellation performs a normal calculation in the geometry shader, which results in flat shading. The individual triangles are therefore visible.&#xD;&#xA;&#xD;&#xA;To avoid this flat shading and also to carry out some transformations afterwards, I decided to save the generated vertices in an SSBO buffer. The indices of the individual triangles are also saved in another SSBO buffer.&#xD;&#xA;&#xD;&#xA;To avoid duplicates within the vbo SSBO, I try to hash the vertices according to their position.&#xD;&#xA;&#xD;&#xA;But that doesn't seem to work properly. If you look at Figure 1, you can see the edge of two neighboring triangles that are tessellated. On the left side, some parts of the edge are &quot;blurred&quot;, these are the parts that work correctly. The vertices that meet at this point share their normal vector, the normal is interpolated, resulting in this blurred edge. At the other points of the edge, my hashing did not work. I saved the generated positions in a file to see where the problem is. Within the VBO-SSBO, each vertex position should be unique! But they are not! All vertices within the same triangle patch are unique, but on the edges where two triangle patches share the same edge, I get duplicates.&#xD;&#xA;&#xD;&#xA;The exact same vertex position of two vertices therefore results in two different hash keys. So my problem seems to be the hash key generation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**This code generates the Hashkey:**&#xD;&#xA;&#xD;&#xA;	// 32 bit Murmur3 hash&#xD;&#xA;	uint HASH_hashKey(uint key)&#xD;&#xA;	{&#xD;&#xA;		uint HASH_TABLE_CAPACITY = 64 * 1024 * 1024;&#xD;&#xA;		key ^= key &gt;&gt; 16;&#xD;&#xA;		key *= 0x85ebca6b;&#xD;&#xA;		key ^= key &gt;&gt; 13;&#xD;&#xA;		key *= 0xc2b2ae35;&#xD;&#xA;		key ^= key &gt;&gt; 16;&#xD;&#xA;		return key &amp; (HASH_TABLE_CAPACITY - 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;    //generates a hash key (uint) depending on the mantissa of the 3D position. This hash key is NOT unique!! because the uint has not enough bits.&#xD;&#xA;    uint HASH_uvec3ToHash(uvec3 vector)&#xD;&#xA;    {&#xD;&#xA;        return (vector.x &amp; 0x7ff) | ((vector.y &amp; 0x7ff) &lt;&lt; 11) | ((vector.z &amp; 0x3ff) &lt;&lt; 22);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //creates or returns a slot for the given vertex position(key) reinterpretes as an uvec3.&#xD;&#xA;    //uvec4 HashKeyValue[] is the hash table HashKeyValue[].xyz: vertexPosition (reinterpreted)&#xD;&#xA;	uint HASH_getHashSlot(uvec3 key)&#xD;&#xA;	{&#xD;&#xA;		//key = uvec3(key.x | 1, key.y | 1, key.z | 1);&#xD;&#xA;		uint HASH_TABLE_CAPACITY = 64 * 1024 * 1024;&#xD;&#xA;		uint slot = HASH_hashKey(HASH_uvec3ToHash(key));&#xD;&#xA;		uint empty = 0xffffffff;&#xD;&#xA;		while (true)&#xD;&#xA;		{&#xD;&#xA;			uint prevX = atomicCompSwap(HashKeyValue[slot].x, empty, key.x);&#xD;&#xA;			if (prevX == empty || prevX == key.x)&#xD;&#xA;			{&#xD;&#xA;				uint prevY = atomicCompSwap(HashKeyValue[slot].y, empty, key.y);&#xD;&#xA;				if (prevY == empty || prevY == key.y)&#xD;&#xA;				{&#xD;&#xA;					uint prevZ = atomicCompSwap(HashKeyValue[slot].z, empty, key.z);&#xD;&#xA;					if (prevZ == empty || prevZ == key.z)&#xD;&#xA;					{&#xD;&#xA;						return slot;&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			slot = (slot + 1) &amp; (HASH_TABLE_CAPACITY - 1);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The parameter &quot;key&quot; is the position of the vertex, reinterpreted as an unsigned integer (to be able to use atomic functions).&#xD;&#xA;&#xD;&#xA;**The idea behind the code:**&#xD;&#xA;&#xD;&#xA;`uint slot = HASH_hashKey(HASH_uvec3ToHash(key));` This line should point to a slot in the hash table that depends on the vertex position. However, it is possible that different positions receive the same value. For this reason, we then perform an x, y and z test. It is important to say that we do not delete any vertices so that we can iterate from the 'slot' position until we find a free hash slot. This is done in the `while (true)` loop:&#xD;&#xA;&#xD;&#xA;Here we first test whether the x-value of the slot is empty and atomicCompSwap the new x-position.&#xD;&#xA;The atomicCompSwap command returns the original value. This can be `empty 0xffffffffff` or the x-position we are looking for =&gt; we move on to the next test. Otherwise, this slot is used by another vertex with a different position, which was hashed here.&#xD;&#xA;The same happens with `y` and `z`. If all three conditions are true (x, y, z), then we have found the perfect hashing slot. Otherwise, we check the next slot.&#xD;&#xA;&#xD;&#xA;Somewhere here must be my mistake, because the VBO-SSBO output has duplicates generated by different hash slots.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LMGmQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42536" PostHistoryTypeId="1" PostId="13877" RevisionGUID="49721586-0e8e-49f2-b5c2-3f3b3dcb3583" CreationDate="2024-01-19T11:39:12.000" UserId="13273" Text="OpenGL hash vertices by position does not work on shared tessellated edges" ContentLicense="CC BY-SA 4.0" />
  <row Id="42537" PostHistoryTypeId="3" PostId="13877" RevisionGUID="49721586-0e8e-49f2-b5c2-3f3b3dcb3583" CreationDate="2024-01-19T11:39:12.000" UserId="13273" Text="|opengl|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42538" PostHistoryTypeId="5" PostId="13877" RevisionGUID="72e8fef7-db53-428d-9d41-4f83ad931867" CreationDate="2024-01-19T13:52:22.817" UserId="13273" Comment="added 331 characters in body" Text="I have a triangular mesh with common vertices (VBO and EBO/IBO) that contain the normal vectors.&#xD;&#xA;If I tessellate this mesh, the subdivision of the triangle edges of neighboring triangles has the same tessellation level. (The mesh therefore has no holes).&#xD;&#xA;&#xD;&#xA;Each partial triangle created by the tessellation performs a normal calculation in the geometry shader, which results in flat shading. The individual triangles are therefore visible.&#xD;&#xA;&#xD;&#xA;To avoid this flat shading and also to carry out some transformations afterwards, I decided to save the generated vertices in an SSBO buffer. The indices of the individual triangles are also saved in another SSBO buffer.&#xD;&#xA;&#xD;&#xA;To avoid duplicates within the vbo SSBO, I try to hash the vertices according to their position.&#xD;&#xA;&#xD;&#xA;But that doesn't seem to work properly. If you look at Figure 1, you can see the edge of two neighboring triangles that are tessellated. On the left side, some parts of the edge are &quot;blurred&quot;, these are the parts that work correctly. The vertices that meet at this point share their normal vector, the normal is interpolated, resulting in this blurred edge. At the other points of the edge, my hashing did not work. I saved the generated positions in a file to see where the problem is. Within the VBO-SSBO, each vertex position should be unique! But they are not! All vertices within the same triangle patch are unique, but on the edges where two triangle patches share the same edge, I get duplicates.&#xD;&#xA;&#xD;&#xA;The exact same vertex position of two vertices therefore results in two different hash keys. So my problem seems to be the hash key generation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**This code generates the Hashkey:**&#xD;&#xA;&#xD;&#xA;	// 32 bit Murmur3 hash&#xD;&#xA;	uint HASH_hashKey(uint key)&#xD;&#xA;	{&#xD;&#xA;		uint HASH_TABLE_CAPACITY = 64 * 1024 * 1024;&#xD;&#xA;		key ^= key &gt;&gt; 16;&#xD;&#xA;		key *= 0x85ebca6b;&#xD;&#xA;		key ^= key &gt;&gt; 13;&#xD;&#xA;		key *= 0xc2b2ae35;&#xD;&#xA;		key ^= key &gt;&gt; 16;&#xD;&#xA;		return key &amp; (HASH_TABLE_CAPACITY - 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;    //generates a hash key (uint) depending on the mantissa of the 3D position. This hash key is NOT unique!! because the uint has not enough bits.&#xD;&#xA;    uint HASH_uvec3ToHash(uvec3 vector)&#xD;&#xA;    {&#xD;&#xA;        return (vector.x &amp; 0x7ff) | ((vector.y &amp; 0x7ff) &lt;&lt; 11) | ((vector.z &amp; 0x3ff) &lt;&lt; 22);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //creates or returns a slot for the given vertex position(key) reinterpretes as an uvec3.&#xD;&#xA;    //uvec4 HashKeyValue[] is the hash table HashKeyValue[].xyz: vertexPosition (reinterpreted)&#xD;&#xA;	uint HASH_getHashSlot(uvec3 key)&#xD;&#xA;	{&#xD;&#xA;		//key = uvec3(key.x | 1, key.y | 1, key.z | 1);&#xD;&#xA;		uint HASH_TABLE_CAPACITY = 64 * 1024 * 1024;&#xD;&#xA;		uint slot = HASH_hashKey(HASH_uvec3ToHash(key));&#xD;&#xA;		uint empty = 0xffffffff;&#xD;&#xA;		while (true)&#xD;&#xA;		{&#xD;&#xA;			uint prevX = atomicCompSwap(HashKeyValue[slot].x, empty, key.x);&#xD;&#xA;			if (prevX == empty || prevX == key.x)&#xD;&#xA;			{&#xD;&#xA;				uint prevY = atomicCompSwap(HashKeyValue[slot].y, empty, key.y);&#xD;&#xA;				if (prevY == empty || prevY == key.y)&#xD;&#xA;				{&#xD;&#xA;					uint prevZ = atomicCompSwap(HashKeyValue[slot].z, empty, key.z);&#xD;&#xA;					if (prevZ == empty || prevZ == key.z)&#xD;&#xA;					{&#xD;&#xA;						return slot;&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			slot = (slot + 1) &amp; (HASH_TABLE_CAPACITY - 1);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The parameter &quot;key&quot; is the position of the vertex, reinterpreted as an unsigned integer (to be able to use atomic functions).&#xD;&#xA;&#xD;&#xA;**The idea behind the code:**&#xD;&#xA;&#xD;&#xA;`uint slot = HASH_hashKey(HASH_uvec3ToHash(key));` This line should point to a slot in the hash table that depends on the vertex position. However, it is possible that different positions receive the same value. For this reason, we then perform an x, y and z test. It is important to say that we do not delete any vertices so that we can iterate from the 'slot' position until we find a free hash slot. This is done in the `while (true)` loop:&#xD;&#xA;&#xD;&#xA;Here we first test whether the x-value of the slot is empty and atomicCompSwap the new x-position.&#xD;&#xA;The atomicCompSwap command returns the original value. This can be `empty 0xffffffffff` or the x-position we are looking for =&gt; we move on to the next test. Otherwise, this slot is used by another vertex with a different position, which was hashed here.&#xD;&#xA;The same happens with `y` and `z`. If all three conditions are true (x, y, z), then we have found the perfect hashing slot. Otherwise, we check the next slot.&#xD;&#xA;&#xD;&#xA;Somewhere here must be my mistake, because the VBO-SSBO output has duplicates generated by different hash slots.&#xD;&#xA;&#xD;&#xA;**EDIT:** Tessellation takes place in ModelSpace, so that rotating the camera has no influence on the hash. Only race conditions can affect the hash slot if multiple positions refer to the same slot in the first hash. The bug is not flickering... so every frame is identical. therefore the same positions cause the same mismatch.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LMGmQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42539" PostHistoryTypeId="5" PostId="13877" RevisionGUID="4c1c7bcc-e798-48d0-9334-a2872945dab0" CreationDate="2024-01-19T14:32:48.073" UserId="13273" Comment="added 237 characters in body" Text="I have a triangular mesh with common vertices (VBO and EBO/IBO) that contain the normal vectors.&#xD;&#xA;If I tessellate this mesh, the subdivision of the triangle edges of neighboring triangles has the same tessellation level. (The mesh therefore has no holes).&#xD;&#xA;&#xD;&#xA;Each partial triangle created by the tessellation performs a normal calculation in the geometry shader, which results in flat shading. The individual triangles are therefore visible.&#xD;&#xA;&#xD;&#xA;To avoid this flat shading and also to carry out some transformations afterwards, I decided to save the generated vertices in an SSBO buffer. The indices of the individual triangles are also saved in another SSBO buffer.&#xD;&#xA;&#xD;&#xA;To avoid duplicates within the vbo SSBO, I try to hash the vertices according to their position.&#xD;&#xA;&#xD;&#xA;But that doesn't seem to work properly. If you look at Figure 1, you can see the edge of two neighboring triangles that are tessellated. On the left side, some parts of the edge are &quot;blurred&quot;, these are the parts that work correctly. The vertices that meet at this point share their normal vector, the normal is interpolated, resulting in this blurred edge. At the other points of the edge, my hashing did not work. I saved the generated positions in a file to see where the problem is. Within the VBO-SSBO, each vertex position should be unique! But they are not! All vertices within the same triangle patch are unique, but on the edges where two triangle patches share the same edge, I get duplicates.&#xD;&#xA;&#xD;&#xA;The exact same vertex position of two vertices therefore results in two different hash keys. So my problem seems to be the hash key generation.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**This code generates the Hashkey:**&#xD;&#xA;&#xD;&#xA;	// 32 bit Murmur3 hash&#xD;&#xA;	uint HASH_hashKey(uint key)&#xD;&#xA;	{&#xD;&#xA;		uint HASH_TABLE_CAPACITY = 64 * 1024 * 1024;&#xD;&#xA;		key ^= key &gt;&gt; 16;&#xD;&#xA;		key *= 0x85ebca6b;&#xD;&#xA;		key ^= key &gt;&gt; 13;&#xD;&#xA;		key *= 0xc2b2ae35;&#xD;&#xA;		key ^= key &gt;&gt; 16;&#xD;&#xA;		return key &amp; (HASH_TABLE_CAPACITY - 1);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;    //generates a hash key (uint) depending on the mantissa of the 3D position. This hash key is NOT unique!! because the uint has not enough bits.&#xD;&#xA;    uint HASH_uvec3ToHash(uvec3 vector)&#xD;&#xA;    {&#xD;&#xA;        return (vector.x &amp; 0x7ff) | ((vector.y &amp; 0x7ff) &lt;&lt; 11) | ((vector.z &amp; 0x3ff) &lt;&lt; 22);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    //creates or returns a slot for the given vertex position(key) reinterpretes as an uvec3.&#xD;&#xA;    //uvec4 HashKeyValue[] is the hash table HashKeyValue[].xyz: vertexPosition (reinterpreted)&#xD;&#xA;	uint HASH_getHashSlot(uvec3 key)&#xD;&#xA;	{&#xD;&#xA;		//key = uvec3(key.x | 1, key.y | 1, key.z | 1);&#xD;&#xA;		uint HASH_TABLE_CAPACITY = 64 * 1024 * 1024;&#xD;&#xA;		uint slot = HASH_hashKey(HASH_uvec3ToHash(key));&#xD;&#xA;		uint empty = 0xffffffff;&#xD;&#xA;		while (true)&#xD;&#xA;		{&#xD;&#xA;			uint prevX = atomicCompSwap(HashKeyValue[slot].x, empty, key.x);&#xD;&#xA;			if (prevX == empty || prevX == key.x)&#xD;&#xA;			{&#xD;&#xA;				uint prevY = atomicCompSwap(HashKeyValue[slot].y, empty, key.y);&#xD;&#xA;				if (prevY == empty || prevY == key.y)&#xD;&#xA;				{&#xD;&#xA;					uint prevZ = atomicCompSwap(HashKeyValue[slot].z, empty, key.z);&#xD;&#xA;					if (prevZ == empty || prevZ == key.z)&#xD;&#xA;					{&#xD;&#xA;						return slot;&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;			slot = (slot + 1) &amp; (HASH_TABLE_CAPACITY - 1);&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The parameter &quot;key&quot; is the position of the vertex, reinterpreted as an unsigned integer (to be able to use atomic functions).&#xD;&#xA;&#xD;&#xA;**The idea behind the code:**&#xD;&#xA;&#xD;&#xA;`uint slot = HASH_hashKey(HASH_uvec3ToHash(key));` This line should point to a slot in the hash table that depends on the vertex position. However, it is possible that different positions receive the same value. For this reason, we then perform an x, y and z test. It is important to say that we do not delete any vertices so that we can iterate from the 'slot' position until we find a free hash slot. This is done in the `while (true)` loop:&#xD;&#xA;&#xD;&#xA;Here we first test whether the x-value of the slot is empty and atomicCompSwap the new x-position.&#xD;&#xA;The atomicCompSwap command returns the original value. This can be `empty 0xffffffffff` or the x-position we are looking for =&gt; we move on to the next test. Otherwise, this slot is used by another vertex with a different position, which was hashed here.&#xD;&#xA;The same happens with `y` and `z`. If all three conditions are true (x, y, z), then we have found the perfect hashing slot. Otherwise, we check the next slot.&#xD;&#xA;&#xD;&#xA;Somewhere here must be my mistake, because the VBO-SSBO output has duplicates generated by different hash slots.&#xD;&#xA;&#xD;&#xA;**EDIT:** Tessellation takes place in ModelSpace, so that rotating the camera has no influence on the hash. Only race conditions can affect the hash slot if multiple positions refer to the same slot in the first hash. The bug is not flickering... so every frame is identical. therefore the same positions cause the same mismatch.&#xD;&#xA;&#xD;&#xA;For those who are interested in the way the normals are calculated:&#xD;&#xA;&#xD;&#xA;Each normal is multiplied by 1000 and saved as an integer. An atomicAdd function adds up all normals and during rendering it is converted to float and normalized.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/LMGmQ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42541" PostHistoryTypeId="50" PostId="12900" RevisionGUID="88426afe-4946-4f92-8604-73f850ea0872" CreationDate="2024-01-20T08:02:50.303" UserId="-1" />
  <row Id="42542" PostHistoryTypeId="50" PostId="13651" RevisionGUID="af2914d1-b7f2-481e-8931-ed33569c588a" CreationDate="2024-01-20T12:04:25.490" UserId="-1" />
  <row Id="42543" PostHistoryTypeId="2" PostId="13878" RevisionGUID="8633c2b3-52a0-4771-8be4-3efb46936a3c" CreationDate="2024-01-20T14:06:19.197" UserId="21079" Text="I've been struggling to implement the correct steps (matrices, white-points, etc) to convert some sRGB (RGB) values (already in 0-1 range) to Lab/CIELAB color space.&#xD;&#xA;&#xD;&#xA;I've tried following guides on multiple sites like:&#xD;&#xA;&#xD;&#xA; - [www.fujiwaratko.sakura.ne.jp - RGB to XYZ][1]&#xD;&#xA; - [www.fujiwaratko.sakura.ne.jp - XYZ to Lab][2]&#xD;&#xA; - [www.brucelindbloom.com][3]&#xD;&#xA;&#xD;&#xA;...but the guides show multiple ways of doing it depending on various factors and are divided by multiple pages, which seem to re-reference steps sometimes, and basically the values I end up with are not correct so I must be doing it wrong (color math is also new to me). &#xD;&#xA;&#xD;&#xA;I'm using a program to do the math so the mistake isn't in me doing the calculations per se wrong.&#xD;&#xA;&#xD;&#xA;Also, the whole equations behind the values of the matrices is not really necessary, to be clear. I'm just trying to find a one-piece guide with the formulas to transform sRGB into Lab. &#xD;&#xA;&#xD;&#xA;I've been struggling with this for days, If anyone would take their time to help me, I would really appreciate it!&#xD;&#xA;&#xD;&#xA;  [1]: https://fujiwaratko.sakura.ne.jp/infosci/colorspace/colorspace2_e.html&#xD;&#xA;  [2]: https://fujiwaratko.sakura.ne.jp/infosci/colorspace/colorspace3_e.html&#xD;&#xA;  [3]: http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html" ContentLicense="CC BY-SA 4.0" />
  <row Id="42545" PostHistoryTypeId="1" PostId="13878" RevisionGUID="8633c2b3-52a0-4771-8be4-3efb46936a3c" CreationDate="2024-01-20T14:06:19.197" UserId="21079" Text="What are the exact math steps to convert sRGB (D65) to Lab (D50) colorspace?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42546" PostHistoryTypeId="3" PostId="13878" RevisionGUID="8633c2b3-52a0-4771-8be4-3efb46936a3c" CreationDate="2024-01-20T14:06:19.197" UserId="21079" Text="|mathematics|matrix|colorspace|conversion|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42547" PostHistoryTypeId="50" PostId="13346" RevisionGUID="12aef8bc-b8ee-42e0-9c8a-60e645d0fa29" CreationDate="2024-01-21T06:04:00.533" UserId="-1" />
  <row Id="42550" PostHistoryTypeId="50" PostId="12995" RevisionGUID="a2c82358-33bb-457f-8990-6a32458304c8" CreationDate="2024-01-21T14:02:50.297" UserId="-1" />
  <row Id="42551" PostHistoryTypeId="2" PostId="13880" RevisionGUID="bebf9ba4-b993-4d17-bf7a-75ba61b6a71c" CreationDate="2024-01-21T14:11:23.150" UserId="7952" Text="&#xD;&#xA; 1) convert sRGB to RGB by first removing gamma (colors must be in linear  color space for the conversions to be accurate) The Fujiwaratko site is confusing since it lists sRGB in its table but the Lindbloom site correctly lists that the color must be in linear space to get a valid transform.&#xD;&#xA; 1) convert from RGB to XYZ. Be careful with the illuminate here. Lab often uses D50 for the illuminate. So... &#xD;&#xA; 1) if the illuminate needs to be converted from D65 to D50 use one of the conversion matrices needed for this. The Lindbloom site gives a nice overview and the steps needed here: http://www.brucelindbloom.com/Eqn_ChromAdapt.html&#xD;&#xA; 1) Finally convert from XYZ to LaB. This conversion is non-linear so a simple matrix can't be used. The tables on the Fujiwaratko site on the XYZ to Lab page give the combined matrix that includes D65 to D50 conversion. I recommend just breaking it into multiple steps until the code is producing the expected results. This gives more opportunities to check that the conversion has been done correctly.&#xD;&#xA;&#xD;&#xA;Unfortunately there is no simple function to do this conversion. Even the online converters will give different results depending on the setup. The Lindbloom site has a conversion tool that allows for the most variables to be set which can be helpful in getting accurate conversions but can also be confusing to use.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42554" PostHistoryTypeId="50" PostId="8779" RevisionGUID="a210826b-4d2b-4f2e-8f8f-c3b0151dd47f" CreationDate="2024-01-23T19:07:00.860" UserId="-1" />
  <row Id="42555" PostHistoryTypeId="50" PostId="13410" RevisionGUID="400de405-2690-4927-8ee9-b3a5e48f3fc6" CreationDate="2024-01-25T01:05:25.593" UserId="-1" />
  <row Id="42560" PostHistoryTypeId="50" PostId="12143" RevisionGUID="3bed0c58-5e1d-472d-9088-b6b8202f04b9" CreationDate="2024-01-25T16:02:25.313" UserId="-1" />
  <row Id="42561" PostHistoryTypeId="2" PostId="13882" RevisionGUID="67962272-2572-4cc4-b3aa-a538bcf246a3" CreationDate="2024-01-25T16:23:06.270" UserId="11824" Text="I'm working on a game that has a big proc. generated map (10000km by 20000km). The map generation is based on multi-octave perlin noise.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;    ...&#xD;&#xA;    vec2 step = vec2(1.3, 1.7);&#xD;&#xA;    float n = 0.0;&#xD;&#xA;    n += color(uv.xy, t);&#xD;&#xA;    n += 0.5 * color(uv.xy * 2.0 - step, t);&#xD;&#xA;    n += 0.25 * color(uv.xy * 4.0 - 2.0 * step, t);&#xD;&#xA;    n += 0.125 * color(uv.xy * 8.0 - 3.0 * step, t);&#xD;&#xA;    n += 0.0625 * color(uv.xy * 16.0 - 4.0 * step, t);&#xD;&#xA;    n += 0.03125 * color(uv.xy * 32.0 - 5.0 * step, t);&#xD;&#xA;    n += 0.015625 * color(uv.xy * 64.0 - 6.0 * step, t);&#xD;&#xA;    n += 0.0078125 * color(uv.xy * 128.0 - 7.0 * step, t);&#xD;&#xA;    n += 0.00390625 * color(uv.xy * 256.0 - 8.0 * step, t);&#xD;&#xA;    n += (0.00390625 / 2.0) * color(uv.xy * (256.0 * 2.0) - (8.0 * 2.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 4.0) * color(uv.xy * (256.0 * 4.0) - (8.0 * 4.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 8.0) * color(uv.xy * (256.0 * 8.0) - (8.0 * 8.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 16.0) * color(uv.xy * (256.0 * 16.0) - (8.0 * 16.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 32.0) * color(uv.xy * (256.0 * 32.0) - (8.0 * 32.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 64.0) * color(uv.xy * (256.0 * 64.0) - (8.0 * 64.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 128.0) * color(uv.xy * (256.0 * 128.0) - (8.0 * 128.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 256.0) * color(uv.xy * (256.0 * 256.0) - (8.0 * 256.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 512.0) * color(uv.xy * (256.0 * 512.0) - (8.0 * 512.0) * step, t);&#xD;&#xA;    n += (0.00390625 / 1024.0) * color(uv.xy * (256.0 * 1024.0) - (8.0 * 1024.0) * step, t);&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;Showing the noise's code just to give an idea about the size of small values in use.&#xD;&#xA;&#xD;&#xA;The goal here is to render the map as topo lines, each one representing small change in terrain height.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is the current result.&#xD;&#xA;&#xD;&#xA;The screenshot below spans for about 19000 kms[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;This one for about 50 kms (the purple line shows what 1km looks like)&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;As you can see the closer we get to the ground the less topo lines we get, which is not what I want. My goal is to have high precision topo lines even at small scales like few kilometers.&#xD;&#xA;&#xD;&#xA;I use the following GLSL code to detect edges:&#xD;&#xA;&#xD;&#xA;    const float STEPS = 10000000.;&#xD;&#xA;    &#xD;&#xA;    const mat3 EDGE_KERNEL = mat3(&#xD;&#xA;        -1, -1, -1,&#xD;&#xA;        -1,  8, -1,&#xD;&#xA;        -1, -1, -1&#xD;&#xA;    );&#xD;&#xA;&#xD;&#xA;    float discretize(float value, float offset) {&#xD;&#xA;        return floor(value * float(STEPS) + offset) / float(STEPS);&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    float tex(vec2 p) {&#xD;&#xA;        return discretize(texture2D(heightmap, p).x, .5);&#xD;&#xA;    }&#xD;&#xA;    ...&#xD;&#xA;    //outlines&#xD;&#xA;    float edge = 0.;&#xD;&#xA;    for (int i = 0; i &lt; 3; i++) {&#xD;&#xA;        for (int j = 0; j &lt; 3; j++) {&#xD;&#xA;            vec2 offset = vec2(float(j - 1), float(i - 1)) / resolution.xy;&#xD;&#xA;            vec2 texCoord = uv + offset;&#xD;&#xA;            edge += 1. / tex(texCoord) * EDGE_KERNEL[j][i];&#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;    vec3 outlineMask = edge &gt; 0.01 ? vec3(0.) : vec3(1.);&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;Unfortunately, I cannot provide the full code or even stripped one since it's pretty hard to strip this code, but I'm ready to provide any details necessary.&#xD;&#xA;&#xD;&#xA;The question is why the edges are not being detected for small float differences. I tried different values in the `edge &gt; 0.01` condition, but no good results there either.&#xD;&#xA;&#xD;&#xA;Did I hit the float precision limit, or is it my noise (it looks like it has enough octaves to give the actual differences to those height), or is it the edge detection algo I use?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lXRON.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/lzhU4.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/6yZYJ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42563" PostHistoryTypeId="1" PostId="13882" RevisionGUID="67962272-2572-4cc4-b3aa-a538bcf246a3" CreationDate="2024-01-25T16:23:06.270" UserId="11824" Text="Detecting edges on really small float-value differences" ContentLicense="CC BY-SA 4.0" />
  <row Id="42564" PostHistoryTypeId="3" PostId="13882" RevisionGUID="67962272-2572-4cc4-b3aa-a538bcf246a3" CreationDate="2024-01-25T16:23:06.270" UserId="11824" Text="|glsl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42570" PostHistoryTypeId="5" PostId="13864" RevisionGUID="9c932755-b580-4731-9cfa-8d453bc20e03" CreationDate="2024-01-25T16:42:27.497" UserId="6" Comment="added 1 character in body" Text="Consider a 2-dimensional polygon with unknown vertices $V_1, \dots, V_n \in \mathbb{R}^2$. Given a random set of points $p_1,\dots, p_m \in \mathbb{R}^2$ lying approximately on the perimeter of such a polygon, is it possible to estimate $V_1,\dots, V_n$?&#xD;&#xA;&#xD;&#xA;To simplify the problem I assume that: &#xD;&#xA;&#xD;&#xA; - $m\ggg n$. &#xD;&#xA; - the given points $p_1, \dots, p_m$ are ordered along the perimeter, i.e., if we walk along the perimeter, we will find the points in the &quot;circular&quot; order $p_1, p_2, \dots, p_m, p_1, p_2, \dots$&#xD;&#xA; - any observed point is obtained as&#xD;&#xA;\begin{equation*}p_i = \bar{p}_i + v_i \qquad v_i \sim \mathcal{N}(0_{2\times 1}, \sigma^2\,I_2)\end{equation*}&#xD;&#xA;where $\bar{p}_i$ is a point lying exactly on the perimeter and $v_i$ is zero-mean Gaussian noise.&#xD;&#xA;&#xD;&#xA;**My approach to the problem:**&#xD;&#xA;&#xD;&#xA; - Starting from $p_1$, I search for the best line interpolating the&#xD;&#xA;   points $p_1,\dots, p_k$, where $k$ is a design parameter. By &quot;best,&quot;&#xD;&#xA;   I mean in the least squares sense. In particular, $k$ should not be&#xD;&#xA;   too small because I need to compensate for the noise and run a&#xD;&#xA;   meaningful regression, but at the same time, $k$ should not be too&#xD;&#xA;   large because I want to compute the regression only with points lying&#xD;&#xA;   on the same edge of the polygon. As $k$ increases, the risk of&#xD;&#xA;   considering points over different edges increases as well.&#xD;&#xA;&#xD;&#xA; - Given the first optimal line, I search for the first vertex. I&#xD;&#xA;   achieve this task by looking at the distances between the line and&#xD;&#xA;   the points $p_{k+1}, \dots, p_m$. If the distance between the line&#xD;&#xA;   and a point $p_i$ (where $i$ ranges from $k+1$ to $m$) is similar to&#xD;&#xA;   the distances between the line and the points $p_1, \dots, p_k$, then&#xD;&#xA;   I consider $p_i$ as a point on the first edge (by the definition of&#xD;&#xA;   the regression, I consider $p_1, \dots, p_k$ belonging to the first&#xD;&#xA;   edge). When I spot the first &quot;big&quot; deviation, say with point $p_i$, I&#xD;&#xA;   define the first edge $V_1$ as the projection of $p_{i-1}$ over the&#xD;&#xA;   optimal line.&#xD;&#xA;&#xD;&#xA; - I delete $p_1, \dots, p_{i-1}$ from the dataset $p_1,\dots, p_m$.&#xD;&#xA;   Starting from $p_i$, I repeat the previous procedure: I run a local&#xD;&#xA;   search for the optimal line with $p_i,\dots, p_{i+k}$, then I&#xD;&#xA;   identify the second vertex $V_2, and finally, I remove the points&#xD;&#xA;   belonging to the new edge.&#xD;&#xA;&#xD;&#xA; - I repeat the entire process until the dataset becomes empty.&#xD;&#xA;&#xD;&#xA;**Questions:**&#xD;&#xA;I've implemented the method, and unfortunately, it seems to work only for a negligible noise level $\sigma$. My questions are the following:&#xD;&#xA;&#xD;&#xA;Has my problem already been solved? If yes, with which algorithms?&#xD;&#xA;Do you have any suggestions to improve the robustness of my method with respect to the noise?&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="42571" PostHistoryTypeId="2" PostId="13884" RevisionGUID="94ea2931-8ec8-4844-b7b8-828ba4602395" CreationDate="2024-01-25T18:22:24.773" UserId="11824" Text="Alright, so the issue was that the shader is a multipass one, so before detecting edges I exported my noise into a 2d sampler at which point it seems it loses some (a lot of) precision.&#xD;&#xA;&#xD;&#xA;So I went to packing/unpacking float (e.g. as described here https://stackoverflow.com/questions/13005391/loss-of-precision-in-glsl-fragment-shader).&#xD;&#xA;&#xD;&#xA;With this approach I was able to get this much of topo lines (again, purple line shows 1 km):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;There are some artifacts here, but I'm sure it's just a matter of coefficients.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/i8a29.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42574" PostHistoryTypeId="2" PostId="13885" RevisionGUID="991be508-cd83-4a5d-87bc-08e7e1217fec" CreationDate="2024-01-25T21:42:42.040" UserId="21100" Text="I would like to know how to &quot;parameterize&quot; the control points for the 6 faces of the commonly used NURBS mutli-patch sphere (&quot;Cobb sphere&quot;), for an arbitrary-size control point grid. Ideally with degree 3 and uniform knot vectors. &#xD;&#xA;&#xD;&#xA;For example, given a 6x6 grid, where would I place the control points and how would I weight them in order to achieve perfect curvature? Then, extend this to a 5x5 grid, 7x7, 10x10, etc. I have seen this done with 2D circles/arcs, and I know rational/non-one weights are probably needed, but I can't find a good method. &#xD;&#xA;&#xD;&#xA;I asked a [similar question](https://math.stackexchange.com/questions/4842413/defining-a-quad-spherical-cube-tile-as-a-uniform-nurbs-surface) in Mathematics Exchange, but it was perhaps too verbose or better suited for here, and did not receive any feedback. Thanks in advance for any advice or direction someone could provide." ContentLicense="CC BY-SA 4.0" />
  <row Id="42576" PostHistoryTypeId="1" PostId="13885" RevisionGUID="991be508-cd83-4a5d-87bc-08e7e1217fec" CreationDate="2024-01-25T21:42:42.040" UserId="21100" Text="How can I determine ideal NURBS surface control points for a multi-patch sphere?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42577" PostHistoryTypeId="3" PostId="13885" RevisionGUID="991be508-cd83-4a5d-87bc-08e7e1217fec" CreationDate="2024-01-25T21:42:42.040" UserId="21100" Text="|mathematics|matrix|nurbs|spline|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42578" PostHistoryTypeId="2" PostId="13886" RevisionGUID="0a95ab90-c225-4a75-970d-9cfb45451db8" CreationDate="2024-01-26T05:43:50.287" UserId="19738" Text="I have figure out the math with use legacy checked.&#xD;&#xA;but I don't know what is the math ps use with use legacy unchecked." ContentLicense="CC BY-SA 4.0" />
  <row Id="42580" PostHistoryTypeId="1" PostId="13886" RevisionGUID="0a95ab90-c225-4a75-970d-9cfb45451db8" CreationDate="2024-01-26T05:43:50.287" UserId="19738" Text="what is the math behind contrast&amp;brightness adjustmentlayer in photoshop?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42581" PostHistoryTypeId="3" PostId="13886" RevisionGUID="0a95ab90-c225-4a75-970d-9cfb45451db8" CreationDate="2024-01-26T05:43:50.287" UserId="19738" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42582" PostHistoryTypeId="50" PostId="13445" RevisionGUID="1de0ae8d-054a-478c-9c37-fcec3e0c32d9" CreationDate="2024-01-27T00:09:01.067" UserId="-1" />
  <row Id="42585" PostHistoryTypeId="2" PostId="13887" RevisionGUID="d4f7fb33-5e53-4b5d-9016-d90e99e51448" CreationDate="2024-01-27T20:19:09.107" UserId="21105" Text="I am trying to understand the function [computeColorFromSH](https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/main/cuda_rasterizer/forward.cu#L20). It is a part of the differentiable gaussian rasterizer implementation used by the paper [3D Gaussian Splatting for Real-Time Radiance Field Rendering](https://arxiv.org/abs/2308.04079).&#xD;&#xA;&#xD;&#xA;I am trying (and failing) to understand the formula that the code is based upon. Take this code for example:&#xD;&#xA;&#xD;&#xA;				result = result +&#xD;&#xA;					SH_C3[0] * y * (3.0f * xx - yy) * sh[9] +&#xD;&#xA;					SH_C3[1] * xy * z * sh[10] +&#xD;&#xA;					SH_C3[2] * y * (4.0f * zz - xx - yy) * sh[11] +&#xD;&#xA;					SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh[12] +&#xD;&#xA;					SH_C3[4] * x * (4.0f * zz - xx - yy) * sh[13] +&#xD;&#xA;					SH_C3[5] * z * (xx - yy) * sh[14] +&#xD;&#xA;					SH_C3[6] * x * (xx - 3.0f * yy) * sh[15];&#xD;&#xA;&#xD;&#xA;It seems to be some kind of polynomial that uses spherical harmonic coefficients and (x,y) to determine color. The Wikipedia article doesn't have anything similar to this, so I'm guessing that at some point someone derived it from the more general form.&#xD;&#xA;&#xD;&#xA;Does anyone know what the official name of the formula is or where I can read about it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42587" PostHistoryTypeId="1" PostId="13887" RevisionGUID="d4f7fb33-5e53-4b5d-9016-d90e99e51448" CreationDate="2024-01-27T20:19:09.107" UserId="21105" Text="Understanding spherical harmonics derivation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42588" PostHistoryTypeId="3" PostId="13887" RevisionGUID="d4f7fb33-5e53-4b5d-9016-d90e99e51448" CreationDate="2024-01-27T20:19:09.107" UserId="21105" Text="|3d|spherical-harmonics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42589" PostHistoryTypeId="5" PostId="13887" RevisionGUID="3b168c6d-7ce4-42cd-80f5-ce99a7febc7a" CreationDate="2024-01-27T20:40:46.777" UserId="21105" Comment="added 2 characters in body; edited title" Text="I am trying to understand the function [computeColorFromSH](https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/main/cuda_rasterizer/forward.cu#L20). It is a part of the differentiable gaussian rasterizer implementation used by the paper [3D Gaussian Splatting for Real-Time Radiance Field Rendering](https://arxiv.org/abs/2308.04079).&#xD;&#xA;&#xD;&#xA;I am trying (and failing) to understand the formula that the code is based upon. Take this code for example:&#xD;&#xA;&#xD;&#xA;				result = result +&#xD;&#xA;					SH_C3[0] * y * (3.0f * xx - yy) * sh[9] +&#xD;&#xA;					SH_C3[1] * xy * z * sh[10] +&#xD;&#xA;					SH_C3[2] * y * (4.0f * zz - xx - yy) * sh[11] +&#xD;&#xA;					SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh[12] +&#xD;&#xA;					SH_C3[4] * x * (4.0f * zz - xx - yy) * sh[13] +&#xD;&#xA;					SH_C3[5] * z * (xx - yy) * sh[14] +&#xD;&#xA;					SH_C3[6] * x * (xx - 3.0f * yy) * sh[15];&#xD;&#xA;&#xD;&#xA;It seems to be some kind of polynomial that uses spherical harmonic coefficients and (x,y,z) to determine color. The Wikipedia article doesn't have anything similar to this, so I'm guessing that at some point someone derived it from the more general form.&#xD;&#xA;&#xD;&#xA;Does anyone know what the official name of the formula is or where I can read about it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42590" PostHistoryTypeId="4" PostId="13887" RevisionGUID="3b168c6d-7ce4-42cd-80f5-ce99a7febc7a" CreationDate="2024-01-27T20:40:46.777" UserId="21105" Comment="added 2 characters in body; edited title" Text="Understanding spherical harmonics code" ContentLicense="CC BY-SA 4.0" />
  <row Id="42591" PostHistoryTypeId="5" PostId="13887" RevisionGUID="41f08f5f-2673-4c97-add8-3763fc237b54" CreationDate="2024-01-28T00:34:23.430" UserId="21105" Comment="deleted 25 characters in body" Text="I am trying to understand the function [computeColorFromSH](https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/main/cuda_rasterizer/forward.cu#L20), which is a part of the differentiable gaussian rasterizer used by the paper [3D Gaussian Splatting for Real-Time Radiance Field Rendering](https://arxiv.org/abs/2308.04079).&#xD;&#xA;&#xD;&#xA;I am looking for the formula that the code is based on. Here's an excerpt for the `degree &gt; 2` part:&#xD;&#xA;&#xD;&#xA;				result = result +&#xD;&#xA;					SH_C3[0] * y * (3.0f * xx - yy) * sh[9] +&#xD;&#xA;					SH_C3[1] * xy * z * sh[10] +&#xD;&#xA;					SH_C3[2] * y * (4.0f * zz - xx - yy) * sh[11] +&#xD;&#xA;					SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh[12] +&#xD;&#xA;					SH_C3[4] * x * (4.0f * zz - xx - yy) * sh[13] +&#xD;&#xA;					SH_C3[5] * z * (xx - yy) * sh[14] +&#xD;&#xA;					SH_C3[6] * x * (xx - 3.0f * yy) * sh[15];&#xD;&#xA;&#xD;&#xA;It seems to be some kind of polynomial. The Wikipedia article on Spherical Harmonics has only integrals, so I'm guessing that this is a special case and maybe even a well-known one.&#xD;&#xA;&#xD;&#xA;Is anyone familiar with this? Where I can read more about it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42592" PostHistoryTypeId="2" PostId="13888" RevisionGUID="5ccb0238-363a-4a26-9e64-f1109f3763bd" CreationDate="2024-01-28T02:43:28.030" UserId="19537" Text="You can check this out ([the appendix of PlenOctree, Section B.1](https://arxiv.org/pdf/2103.14024.pdf)), since the SH implementation of 3D GS is directly borrowed from PlenOctree. I can walk you through it with an example. First, take a look at the real form of SH (I won't use Latex here since, you know it's painful):&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;Where $P_l^{|m|}(\cdot)$ is the [associative Legendre Polynomial](https://en.wikipedia.org/wiki/Associated_Legendre_polynomials):&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;(From Wikipedia)&#xD;&#xA;&#xD;&#xA;So where are those `SH_C3`? They have some thing to do with:&#xD;&#xA;$$&#xD;&#xA;K_{lm} = \sqrt{\frac{2l+1}{4\pi}\frac{(l - |m|)!}{(l+|m|)!}}&#xD;&#xA;$$&#xD;&#xA;Ok, so basically, we first get $\theta$ and $\phi$, as the direction $(x, y, z)$ can be easily converted to the spherical coordinates $(\theta, \phi)$. Therefore, the corresponding $\cos(\cdot), \sin(\cdot)$ values can be obtained.&#xD;&#xA;&#xD;&#xA;Then we use the formula of associative Legendre Polynomial to get, say $m=0, l = 0$ case:&#xD;&#xA;$$&#xD;&#xA;P_0^0=1&#xD;&#xA;$$&#xD;&#xA;We next evaluate SH basis function (given in the first image), for example: $Y_{00}, l=0,m=0$ will be $\sqrt{1 / 4\pi} \approx 0.282095$, which equals to  `SH_C0` in the code. Other coefficients can be derived similarly: substitute $l, m$ with the order you need, then evaluate the whole formula and store the constant part. With all the precomputed coefficients, now you can multiply your learned SH coefficients with these precomputed ones. Hope this will help.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wyJ11.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/miPb8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42594" PostHistoryTypeId="2" PostId="13889" RevisionGUID="09b8ba7d-5677-41a3-87a6-29fdf8b01ec3" CreationDate="2024-01-28T11:12:08.177" UserId="21109" Text="based on the ray tracing stunning effect, I'm considering a resilient distributed ray tracing implementation, I've just finished a basic computer graphics course, and I'm currently working on directX and directML, I'd like to ask if the particle system and rendering in computer graphics can be scheduled based on directX with a distributed program  such as MPI to schedule multiple GPUs to work on it?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42596" PostHistoryTypeId="1" PostId="13889" RevisionGUID="09b8ba7d-5677-41a3-87a6-29fdf8b01ec3" CreationDate="2024-01-28T11:12:08.177" UserId="21109" Text="Problems with distributed ray tracing and particle system" ContentLicense="CC BY-SA 4.0" />
  <row Id="42597" PostHistoryTypeId="3" PostId="13889" RevisionGUID="09b8ba7d-5677-41a3-87a6-29fdf8b01ec3" CreationDate="2024-01-28T11:12:08.177" UserId="21109" Text="|raytracing|rendering|3d|directx12|particles|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42598" PostHistoryTypeId="5" PostId="8163" RevisionGUID="2e160d09-728d-4249-9bd7-057c80474750" CreationDate="2024-01-29T07:47:02.327" UserId="9533" Comment="Minor rewording and additions." Text="Talking about *Linear RGB* must be avoided because it does not tell you anything about the RGB colourspace intrinsics, i.e., Primaries, Whitepoint and Colour Component Transfer Functions. A few years ago, assuming it was sRGB was middling but nowadays with DCI-P3, BT.2020 and ACEScg being very common, it must be ruled out.&#xD;&#xA;&#xD;&#xA;The ideal gamut for rendering is the one that will minimize errors in respect to a real-world reference or more conveniently a ground truth spectral render. The first takeaway from this sentence is that the various RGB colourspaces are not equivalent and will not produce similar results.&#xD;&#xA;&#xD;&#xA;One might think that performing two renders with the same base colours but one where they are encoded with sRGB/BT.709 and the other one where they are encoded with DCI-P3 and then converting the two resulting images to for example ACES2065-1 will yield the same images but it is not the case. Some mathematical operations because of the nature of linear algebra and matrices are dependent on the given RGB colourspace primaries, i.e., on the colourspaces basis. The same operations performed in different RGB colourspace will yield different tristimulus values once converted back to CIE XYZ color space. For example multiplication, division and power operations are RGB colourspace primaries dependent while addition and subtraction are not.&#xD;&#xA;&#xD;&#xA;[![RGB Colourspaces and Exponentiation][1]][1]&#xD;&#xA;&#xD;&#xA;This image illustrates the effect of multiplying various colours by themselves into different RGB colourspaces: the resulting colours are different. The various samples are generated as follows: 3 random sRGB colourspace values are picked and converted to the three studied RGB colourspaces, they are exponentiated, converted back to sRGB colourspace, plotted in the CIE 1931 Chromaticity Diagram on the left and displayed as swatches on the right.&#xD;&#xA;&#xD;&#xA;Tests and research conducted by [Ward and Eydelberg-Vileshin (2002)][2], [Langlands and Mansencal (2014)][3] and [Mansencal (2014)][4] showed that gamuts with primaries closest to the spectral locus, i.e. spectrally sharp primaries, tend to minimize the errors compared to ground truth spectral renders.&#xD;&#xA;&#xD;&#xA;Here is an image I recently rendered with Mitsuba to re-validate our findings with Anders:&#xD;&#xA;&#xD;&#xA;[![Rendering Colourspaces][5]][5]&#xD;&#xA;&#xD;&#xA;Those are renders of the same scene using BT.709 primaries (first row), 47 spectral bins (second row), BT.2020 primaries (third row), spectral minus BT.709 primaries renders residuals (fourth row), spectral minus BT.2020 primaries renders residuals (fifth row). The last row showcases composite images assembled with three vertical stripes of respectively the BT.709 primaries, spectral and, BT.2020 primaries renders. Direct illumination tends to match between the renders. Areas that show the effect of multiple light bounces, i.e., the ceiling, in the BT.709 and BT.2020 primaries renders tend to exhibit increased saturation, especially in the BT.709 primaries render or slight loss of energy, especially in the BT.2020 render. Excluding outliers, e.g., the visible light source, the RMSE with the spectral render are **0.0083** and **0.0116** for respectively the BT.2020 primaries and BT.709 primaries renders.&#xD;&#xA;&#xD;&#xA;Now it does not mean they will always perform better, and one might be able to produce examples that will exhibit a bias toward BT.709/sRGB. The main takeaway is that RGB renders cannot match spectral renders and sharp wide gamuts tend to perform better. As for choosing a rendering colourspace, I would pick one with a wide gamut that encompasses Pointer's Gamut and DCI-P3, **BT.2020** or **ACEScg** are excellent candidates for that.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7SQRJ.png&#xD;&#xA;  [2]: http://diglib.eg.org/handle/10.2312/EGWR.EGWR02.117-124&#xD;&#xA;  [3]: https://www.colour-science.org/anders-langlands/&#xD;&#xA;  [4]: https://www.colour-science.org/posts/about-rgb-colourspace-models-performance/&#xD;&#xA;  [5]: https://i.stack.imgur.com/7GseL.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42599" PostHistoryTypeId="2" PostId="13890" RevisionGUID="77cba064-a9f3-4501-8dbd-1e904a1adf03" CreationDate="2024-01-29T08:03:19.833" UserId="7724" Text="I was able to find control point locations for a biquartic rational B\'ezier patch for a cube tiling here:&#xD;&#xA;&#xD;&#xA;https://lirias.kuleuven.be/bitstream/123456789/607807/1/SphereTiling.pdf&#xD;&#xA;&#xD;&#xA;which is based on the paper by Cobb:&#xD;&#xA;&#xD;&#xA;https://collections.lib.utah.edu/dl_files/4e/77/4e7746dd53c79f8557272b92b47d2d407da4931a.pdf&#xD;&#xA;&#xD;&#xA;The control point values can be found in table A.2. The control positions of the other faces can be determined by symmetry. &#xD;&#xA;&#xD;&#xA;From this representation there might be a way to represent it as a rational B-spline. Naturally, the Bezier representation could also be subdivided into more biquartic pieces." ContentLicense="CC BY-SA 4.0" />
  <row Id="42601" PostHistoryTypeId="5" PostId="9203" RevisionGUID="249a472b-c27d-4cb2-a07d-7697370c2251" CreationDate="2024-01-29T14:33:38.097" UserId="209" Comment="fixed some missing text" Text="It sounds like you want to know how to ray trace ***a bilinear surface patch***.&#xD;&#xA;&#xD;&#xA;A quick search [turned up this page][1] by Ramsey, Potter &amp; Hansen, which includes a [paper][2] and, probably better still, *source code*!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;However, if you just want a &quot;cheap and cheerful&quot; &lt;strike&gt;hack&lt;/strike&gt; approach, you could try replacing the quad with **4** triangles. That is, by adding a new vertex at the 'centre' (i.e. computing the average of the corners) and joining each edge to that new vertex. This is generally produces a better looking, and order-independent result than just using a pair of triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://shaunramsey.com/research/bp/&#xD;&#xA;  [2]: http://shaunramsey.com/research/bp/ramseybilinear.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42602" PostHistoryTypeId="50" PostId="13454" RevisionGUID="076ab41b-aea5-4501-b192-a8f53f5f5487" CreationDate="2024-01-29T15:03:45.483" UserId="-1" />
  <row Id="42608" PostHistoryTypeId="2" PostId="13892" RevisionGUID="ebee5df5-9fe1-43f2-83ff-b044552847d7" CreationDate="2024-01-30T13:39:37.293" UserId="13273" Text="If you use the tessellation shader for triangle patches, you can only set the following four values to define the tessellation structure of the triangle:&#xD;&#xA;&#xD;&#xA;    gl_TessLevelOuter[0]&#xD;&#xA;    gl_TessLevelOuter[1]&#xD;&#xA;    gl_TessLevelOuter[2]&#xD;&#xA;    gl_TessLevelInner[0]&#xD;&#xA;&#xD;&#xA;But if the original triangle patch is degenerated. For example, 2 edges are 2 units long, while the last edge is 0.5 units long. How can I tessellate it so that the generated triangles have almost the same edge length?&#xD;&#xA;&#xD;&#xA;Well, the `gl_TessLevelOuter` values of the three edges can easily be set to values so that the length of the generated edges of the shorter and the longer edges are nearly equal. But the `gl_TessLevelInner` cannot be set to a simple value where the inner genated vertices match different outer tessellation levels. The outermost triangle ring is always mapped to the outer tessellation levels, and the inner generated vertices remain the same.&#xD;&#xA;&#xD;&#xA;Are there any papers to fix something like this? Maybe directly in the render pipeline? Or through a compute shader? I'm only interested in **real time** implementations." ContentLicense="CC BY-SA 4.0" />
  <row Id="42610" PostHistoryTypeId="1" PostId="13892" RevisionGUID="ebee5df5-9fe1-43f2-83ff-b044552847d7" CreationDate="2024-01-30T13:39:37.293" UserId="13273" Text="How can you tessellate degenerate triangles evenly?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42611" PostHistoryTypeId="3" PostId="13892" RevisionGUID="ebee5df5-9fe1-43f2-83ff-b044552847d7" CreationDate="2024-01-30T13:39:37.293" UserId="13273" Text="|opengl|glsl|tesselation|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42612" PostHistoryTypeId="5" PostId="13892" RevisionGUID="f37be4f7-eb03-401b-b4f0-e4ae20025681" CreationDate="2024-01-30T17:19:21.350" UserId="13273" Comment="deleted 5 characters in body" Text="If you use the tessellation shader for triangle patches, you can only set the following four values to define the tessellation structure of the triangle:&#xD;&#xA;&#xD;&#xA;    gl_TessLevelOuter[0]&#xD;&#xA;    gl_TessLevelOuter[1]&#xD;&#xA;    gl_TessLevelOuter[2]&#xD;&#xA;    gl_TessLevelInner[0]&#xD;&#xA;&#xD;&#xA;But if the original triangle patch is degenerated. For example, 2 edges are 2 units long, while the last edge is 0.5 units long. How can I tessellate it so that the generated triangles have almost the same edge length?&#xD;&#xA;&#xD;&#xA;Well, the `gl_TessLevelOuter` values of the three edges can easily be set to values so that the length of the generated edges of the shorter and the longer edges are nearly equal. But the `gl_TessLevelInner` cannot be set to a simple value where the inner genated vertices match different outer tessellation levels. The outermost triangle ring is always mapped to the outer tessellation levels, and the inner generated vertices remain the same.&#xD;&#xA;&#xD;&#xA;Are there any papers to fix something like this? Maybe directly in the render pipeline? Or through a compute shader? I'm only interested in **real time** algorithms." ContentLicense="CC BY-SA 4.0" />
  <row Id="42613" PostHistoryTypeId="5" PostId="13885" RevisionGUID="a0d4a1f9-2497-4bb7-9b5a-934dd8936c53" CreationDate="2024-01-30T20:42:33.473" UserId="21100" Comment="added 845 characters in body" Text="I would like to know how to &quot;parameterize&quot; the control points for the 6 faces of the commonly used NURBS mutli-patch sphere (&quot;Cobb sphere&quot;), for an arbitrary-size control point grid. Ideally with degree 3 and uniform knot vectors. &#xD;&#xA;&#xD;&#xA;For example, given a 6x6 grid, where would I place the control points and how would I weight them in order to achieve perfect curvature? Then, extend this to a 5x5 grid, 7x7, 10x10, etc. I have seen this done with 2D circles/arcs, and I know rational/non-one weights are probably needed, but I can't find a good method. &#xD;&#xA;&#xD;&#xA;I asked a [similar question](https://math.stackexchange.com/questions/4842413/defining-a-quad-spherical-cube-tile-as-a-uniform-nurbs-surface) in Mathematics Exchange, but it was perhaps too verbose or better suited for here, and did not receive any feedback. Thanks in advance for any advice or direction someone could provide.&#xD;&#xA;&#xD;&#xA;___&#xD;&#xA;Edit:&#xD;&#xA;I tried out the points suggested by user Reynolds from the Dedoncker et al paper, but the tiles don't perfectly fit a sphere. Adding an image showing some of my evaluations of those points in a few different platforms: [![enter image description here][1]][1]&#xD;&#xA;The paper mentions the CVs were implemented in Octave (albeit, scaled or otherwise modified), and indeed I had actually seen them before in Octave during previous searches. They're called &quot;NURBS&quot;, but now when I export the CVs (although, called &quot;coefs&quot; here...) and evaluate them with my Python NURBS functions, they do not match the Octave plot. Maybe they are actually Bézier? I believe I need to convert these from Bézier to NURBS but I don't totally understand that process, and ultimately I need to work with NURBS. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/UcPkd.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42614" PostHistoryTypeId="2" PostId="13893" RevisionGUID="78e604cc-2c92-4c80-afaf-a71a2afa7a09" CreationDate="2024-01-31T06:49:47.133" UserId="21117" Text="I'm currently studying about world space transformation matrices and encountered some confusion regarding their application in different matrix orders (row major vs column major).&#xD;&#xA;&#xD;&#xA;**Context**&#xD;&#xA;&#xD;&#xA;In row major order, a point is represented as \begin{bmatrix}&#xD;&#xA;x,y,z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;In column major order, the same point is represented as &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;**World Space Transformation**&#xD;&#xA;&#xD;&#xA;For column major order, we use post-multiplication: $P1 = WST * p1 = S * Rx * Ry * Rz * T * p1$&#xD;&#xA;&#xD;&#xA;For row major order, it's we use pre-multiplication: $P2 = p2 * WST = p2 * T * Rz * Ry * Rx * S$&#xD;&#xA;&#xD;&#xA;However, I feel, for row major it should instead be: $P2 = p2 * WST' = p2 * T' * Rz' * Ry' * Rx' * S$ where ' denotes transpose of the matrix.&#xD;&#xA;&#xD;&#xA;**My Reasoning** &#xD;&#xA;&#xD;&#xA;Both P1 and P2 represent the same transformed point, just in different orders (column major vs row major).&#xD;&#xA;&#xD;&#xA;So, $P2 = P1' = (S * Rx * Ry * Rz * T *  p1)'$ &#xD;&#xA;&#xD;&#xA;Since, $(AB)' = B'A'$&#xD;&#xA;&#xD;&#xA;We can say that, $P1 = p1' * T * Rz * Ry * Rx * S =  p2 * T * Rz * Ry * Rx * S$ (as $p1' = p2$)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42616" PostHistoryTypeId="1" PostId="13893" RevisionGUID="78e604cc-2c92-4c80-afaf-a71a2afa7a09" CreationDate="2024-01-31T06:49:47.133" UserId="21117" Text="Pre and Post Multiplication World Space Transform Matrix ambiguity" ContentLicense="CC BY-SA 4.0" />
  <row Id="42617" PostHistoryTypeId="3" PostId="13893" RevisionGUID="78e604cc-2c92-4c80-afaf-a71a2afa7a09" CreationDate="2024-01-31T06:49:47.133" UserId="21117" Text="|transformations|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42618" PostHistoryTypeId="2" PostId="13894" RevisionGUID="9ecfc14e-eb0f-40d2-961b-a3495e0120a9" CreationDate="2024-01-31T11:07:08.427" UserId="21119" Text="I already have experience with Vulkan on my home computer, however I live in a dorm with a kinda old laptop.&#xD;&#xA;&#xD;&#xA;The processor, an Intel(R) HD 4600 Graphics, is incompatible on windows with Vulkan.&#xD;&#xA;&#xD;&#xA;I've read it might be compatible on Linux, I however have little experience of Linux and no knowledge of how I could install it on my computer/on a virtual machine.&#xD;&#xA;&#xD;&#xA;My question is : are there any other solutions to use Vulkan with windows ?&#xD;&#xA;Else, could I use a virtual machine, and which VM and OS should I use to have good performance and debugging friendliness ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42620" PostHistoryTypeId="1" PostId="13894" RevisionGUID="9ecfc14e-eb0f-40d2-961b-a3495e0120a9" CreationDate="2024-01-31T11:07:08.427" UserId="21119" Text="How can I use Vulkan on windows with an incompatible processor?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42621" PostHistoryTypeId="3" PostId="13894" RevisionGUID="9ecfc14e-eb0f-40d2-961b-a3495e0120a9" CreationDate="2024-01-31T11:07:08.427" UserId="21119" Text="|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42622" PostHistoryTypeId="5" PostId="13893" RevisionGUID="0a0a9d96-3681-46b0-bb47-bdfe5f3c3606" CreationDate="2024-01-31T15:39:31.167" UserId="21117" Comment="added 1 character in body" Text="I'm currently studying about world space transformation matrices and encountered some confusion regarding their application in different matrix orders (row major vs column major).&#xD;&#xA;&#xD;&#xA;**Context**&#xD;&#xA;&#xD;&#xA;In row major order, a point is represented as \begin{bmatrix}&#xD;&#xA;x,y,z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;In column major order, the same point is represented as &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;**World Space Transformation**&#xD;&#xA;&#xD;&#xA;For column major order, we use post-multiplication: $P1 = WST * p1 = S * Rx * Ry * Rz * T * p1$&#xD;&#xA;&#xD;&#xA;For row major order, it's we use pre-multiplication: $P2 = p2 * WST = p2 * T * Rz * Ry * Rx * S'$&#xD;&#xA;&#xD;&#xA;However, I feel, for row major it should instead be: $P2 = p2 * WST' = p2 * T' * Rz' * Ry' * Rx' * S$ where ' denotes transpose of the matrix.&#xD;&#xA;&#xD;&#xA;**My Reasoning** &#xD;&#xA;&#xD;&#xA;Both P1 and P2 represent the same transformed point, just in different orders (column major vs row major).&#xD;&#xA;&#xD;&#xA;So, $P2 = P1' = (S * Rx * Ry * Rz * T *  p1)'$ &#xD;&#xA;&#xD;&#xA;Since, $(AB)' = B'A'$&#xD;&#xA;&#xD;&#xA;We can say that, $P1 = p1' * T * Rz * Ry * Rx * S =  p2 * T * Rz * Ry * Rx * S$ (as $p1' = p2$)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42625" PostHistoryTypeId="2" PostId="13895" RevisionGUID="261f4173-4f0b-4420-9828-3b9912757a43" CreationDate="2024-01-31T20:45:27.833" UserId="7952" Text="I was going to do a bunch of fancy matrices but I really I think your confusion is surrounding matrix-major order.&#xD;&#xA;&#xD;&#xA;A matrix is either column major or row major. It's best to pick one and stick to it. Such as in OpenGL we almost always talk column major order which is the world of post multiply. So for the rest of this question I will stick to column major.&#xD;&#xA;&#xD;&#xA;Transposing a column major matrix doesn't change it into a Row major matrix, we still have a column major matrix it is just transposed. We can make equivocations between row and column major but the two worlds really should be kept separated.&#xD;&#xA;&#xD;&#xA;So when we talk about multiplying column major matrices we should be careful to use only column major matrices in the calculation.&#xD;&#xA;&#xD;&#xA;$ p_1 = C*p1 $  // C and p1 are column major&#xD;&#xA;&#xD;&#xA;$p_2 = p1^T *C^T$ // the superscript indicates transpose &#xD;&#xA;&#xD;&#xA;$p_1 == p_2$&#xD;&#xA;&#xD;&#xA;These 3 statement make sense only because we are talking column major matrices. We can switch between row and column major but it should be a clean break so to speak. &#xD;&#xA;&#xD;&#xA;The question seems to treat the matrices kind of as both at the same time. That will get you into trouble quickly. Even though we all know that if we transpose a column major matrix it is equivalent to a row major matrix, it is much better to say it is a column major matrix transposed. &#xD;&#xA;&#xD;&#xA;I'm not sure if I got to the heart of your question here, but hopefully it helps clear things up a little.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42627" PostHistoryTypeId="5" PostId="13890" RevisionGUID="f9b5e04b-513d-4df9-ba6f-2921b4619874" CreationDate="2024-02-01T08:17:48.600" UserId="7724" Comment="added 195 characters in body" Text="I was able to find control point locations for a biquartic rational B\'ezier patch for a cube tiling here:&#xD;&#xA;&#xD;&#xA;https://lirias.kuleuven.be/bitstream/123456789/607807/1/SphereTiling.pdf&#xD;&#xA;&#xD;&#xA;which is based on the paper by Cobb:&#xD;&#xA;&#xD;&#xA;https://collections.lib.utah.edu/dl_files/4e/77/4e7746dd53c79f8557272b92b47d2d407da4931a.pdf&#xD;&#xA;&#xD;&#xA;The control point values can be found in table A.2. The control positions of the other faces can be determined by symmetry. &#xD;&#xA;&#xD;&#xA;To represent this patch as a NURBS surface remember that a Bezier curve is a special type of NURBS curve with a knot vector with multiple knots. So use the knot vectors for a quartic NURBS piece $t_u$ and $t_v$:&#xD;&#xA;&#xD;&#xA;$$t_u = t_v = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]$$&#xD;&#xA;&#xD;&#xA;Then, to obtain larger grid sizes you could use knot insertion, or plain subdivision of the Bezier patch." ContentLicense="CC BY-SA 4.0" />
  <row Id="42628" PostHistoryTypeId="5" PostId="13893" RevisionGUID="7dd12f37-5c32-48f7-bc44-342d486beec7" CreationDate="2024-02-01T15:04:27.593" UserId="21117" Comment="added 1 character in body" Text="I'm currently studying about world space transformation matrices and encountered some confusion regarding their application in different matrix orders (row major vs column major).&#xD;&#xA;&#xD;&#xA;**Context**&#xD;&#xA;&#xD;&#xA;In row major order, a point is represented as \begin{bmatrix}&#xD;&#xA;x,y,z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;In column major order, the same point is represented as &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;**World Space Transformation**&#xD;&#xA;&#xD;&#xA;For column major order, we use post-multiplication: $P1 = WST * p1 = S * Rx * Ry * Rz * T * p1$&#xD;&#xA;&#xD;&#xA;For row major order, it's we use pre-multiplication: $P2 = p2 * WST = p2 * T * Rz * Ry * Rx * S'$&#xD;&#xA;&#xD;&#xA;However, I feel, for row major it should instead be: $P2 = p2 * WST' = p2 * T' * Rz' * Ry' * Rx' * S'$ where ' denotes transpose of the matrix.&#xD;&#xA;&#xD;&#xA;**My Reasoning** &#xD;&#xA;&#xD;&#xA;Both P1 and P2 represent the same transformed point, just in different orders (column major vs row major).&#xD;&#xA;&#xD;&#xA;So, $P2 = P1' = (S * Rx * Ry * Rz * T *  p1)'$ &#xD;&#xA;&#xD;&#xA;Since, $(AB)' = B'A'$&#xD;&#xA;&#xD;&#xA;We can say that, $P1 = p1' * T * Rz * Ry * Rx * S =  p2 * T * Rz * Ry * Rx * S$ (as $p1' = p2$)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42629" PostHistoryTypeId="2" PostId="13896" RevisionGUID="e3222738-9e0b-4872-9615-4d17232e554f" CreationDate="2024-02-01T15:26:42.490" UserId="21125" Text="I'm working on a project that involves real-time visualization of large datasets to create detailed surfaces from heightmap representations. As I'm relatively new to the field of real-time rendering, I'm exploring techniques to improve performance and responsiveness, particularly focusing on view-dependent Level of Detail (LOD) and progressive rendering strategies, but I am a bit overwhelmed at the moment. I am currently utilizing webgl and a server-client infrastructure.&#xD;&#xA;&#xD;&#xA;The goal is to achieve smoother interactions (rotating and zooming) and faster load times by dynamically adjusting the mesh complexity based on the viewer's perspective and incrementally refining the visualization. I'm open to other suggestions that could enhance the visualization performance as well.&#xD;&#xA;&#xD;&#xA;I'm currently seeking resources, guides, or any form of literature that could help me understand and implement these techniques, or general best practices.&#xD;&#xA;If you have experience with these techniques or know of any resources that could assist someone new to the field, I would greatly appreciate your guidance.&#xD;&#xA;&#xD;&#xA;Thank you!" ContentLicense="CC BY-SA 4.0" />
  <row Id="42631" PostHistoryTypeId="1" PostId="13896" RevisionGUID="e3222738-9e0b-4872-9615-4d17232e554f" CreationDate="2024-02-01T15:26:42.490" UserId="21125" Text="Advice on Implementing View-Dependent LOD and Progressive Rendering for Real-Time Visualization" ContentLicense="CC BY-SA 4.0" />
  <row Id="42632" PostHistoryTypeId="3" PostId="13896" RevisionGUID="e3222738-9e0b-4872-9615-4d17232e554f" CreationDate="2024-02-01T15:26:42.490" UserId="21125" Text="|webgl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42633" PostHistoryTypeId="5" PostId="13893" RevisionGUID="b94a87ff-66ef-462b-b779-00d605abe186" CreationDate="2024-02-01T23:20:19.980" UserId="21117" Comment="added 10 characters in body" Text="I'm currently studying about world space transformation matrices and encountered some confusion regarding their application in different matrix orders (row major vs column major).&#xD;&#xA;&#xD;&#xA;**Context**&#xD;&#xA;&#xD;&#xA;In row major order, a point is represented as \begin{bmatrix}&#xD;&#xA;x,y,z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;In column major order, the same point is represented as &#xD;&#xA;\begin{bmatrix}&#xD;&#xA;x \\&#xD;&#xA;y \\&#xD;&#xA;z&#xD;&#xA;\end{bmatrix}&#xD;&#xA;&#xD;&#xA;**World Space Transformation**&#xD;&#xA;&#xD;&#xA;For column major order, we use post-multiplication: $P1 = WST * p1 = S * Rx * Ry * Rz * T * p1$&#xD;&#xA;&#xD;&#xA;For row major order, it's we use pre-multiplication: $P2 = p2 * WST = p2 * T * Rz * Ry * Rx * S'$&#xD;&#xA;&#xD;&#xA;However, I feel, for row major it should instead be: $P2 = p2 * WST' = p2 * T' * Rz' * Ry' * Rx' * S'$ where ' denotes transpose of the matrix.&#xD;&#xA;&#xD;&#xA;**My Reasoning** &#xD;&#xA;&#xD;&#xA;Both P1 and P2 represent the same transformed point, just in different orders (column major vs row major).&#xD;&#xA;&#xD;&#xA;So, $P2 = P1' = (S * Rx * Ry * Rz * T *  p1)'$ &#xD;&#xA;&#xD;&#xA;Since, $(AB)' = B'A'$&#xD;&#xA;&#xD;&#xA;We can say that, $P2 = p1' * T' * Rz' * Ry' * Rx' * S' =  p2 * T' * Rz' * Ry' * Rx' * S'$ (as $p1' = p2$)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42634" PostHistoryTypeId="5" PostId="13895" RevisionGUID="7285504e-69bc-4dac-8a70-042aa9b103e7" CreationDate="2024-02-02T00:05:29.617" UserId="7952" Comment="added 477 characters in body" Text="I was going to do a bunch of fancy matrices but I really I think your confusion is surrounding matrix-major order.&#xD;&#xA;&#xD;&#xA;A matrix is either column major or row major. It's best to pick one and stick to it. Such as in OpenGL we almost always talk column major order which is the world of post multiply. So for the rest of this question I will stick to column major.&#xD;&#xA;&#xD;&#xA;Transposing a column major matrix doesn't change it into a Row major matrix, we still have a column major matrix it is just transposed. We can make equivocations between row and column major but the two worlds really should be kept separated.&#xD;&#xA;&#xD;&#xA;So when we talk about multiplying column major matrices we should be careful to use only column major matrices in the calculation.&#xD;&#xA;&#xD;&#xA;$ p_1 = C*p1 $  // C and p1 are column major&#xD;&#xA;&#xD;&#xA;$p_2 = p1^T *C^T$ // the superscript indicates transpose &#xD;&#xA;&#xD;&#xA;$p_1 == p_2$&#xD;&#xA;&#xD;&#xA;These 3 statement make sense only because we are talking column major matrices. We can switch between row and column major but it should be a clean break so to speak. &#xD;&#xA;&#xD;&#xA;The question seems to treat the matrices kind of as both at the same time. That will get you into trouble quickly. Even though we all know that if we transpose a column major matrix it is equivalent to a row major matrix, it is much better to say it is a column major matrix transposed. &#xD;&#xA;&#xD;&#xA;I'm not sure if I got to the heart of your question here, but hopefully it helps clear things up a little.&#xD;&#xA;&#xD;&#xA;A Column Major 4x4 matrix is laid out like this:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;    a  &amp; e &amp; i &amp; m \\&#xD;&#xA;    b  &amp; f &amp; j &amp; n \\&#xD;&#xA;    c  &amp; g &amp; k &amp; o \\&#xD;&#xA;    d  &amp; h &amp; l &amp; p&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;Think of it as 4 4x1 vectors stacked next to each other.&#xD;&#xA;&#xD;&#xA;A row major 4x4 matrix has a data layout out like this:&#xD;&#xA;&#xD;&#xA;$\begin{bmatrix}&#xD;&#xA;    a  &amp; b &amp; c &amp; d \\&#xD;&#xA;    e  &amp; f &amp; g &amp; h \\&#xD;&#xA;    i  &amp; j &amp; k &amp; l \\&#xD;&#xA;    m  &amp; n &amp; o &amp; p&#xD;&#xA;\end{bmatrix}$&#xD;&#xA;Think of it as 4 1x4 vectors stacked on top of each other.&#xD;&#xA;&#xD;&#xA;Notice that the diagonals of each have the same values and that the transpose of each produces the other.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42635" PostHistoryTypeId="5" PostId="13890" RevisionGUID="6d6e9e3f-c7e4-4f83-a19d-4653f6ec7f94" CreationDate="2024-02-02T11:12:06.750" UserId="7724" Comment="added 5520 characters in body" Text="I was able to find control point locations for a biquartic rational B\'ezier patch for a cube tiling by [Dedoncker et al][1] which is based on the paper by [Cobb][2]. The control point values can be found in table A.2. The control positions of the other faces can be determined by symmetry. &#xD;&#xA;&#xD;&#xA;To represent this patch as a NURBS surface remember that a Bezier curve is a special type of NURBS curve with a knot vector with multiple knots. So use the knot vectors for a quartic NURBS piece $t_u$ and $t_v$:&#xD;&#xA;&#xD;&#xA;$$t_u = t_v = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]$$&#xD;&#xA;&#xD;&#xA;Then, to obtain larger grid sizes you could use knot insertion, or plain subdivision of the Bezier patch.&#xD;&#xA;&#xD;&#xA;Here I have a simple python script that creates a NURBS sphere from the control points from the paper of Dedoncker et al:&#xD;&#xA;&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    from scipy.linalg import expm, norm&#xD;&#xA;    import numpy as np&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    cps = np.zeros([5, 5, 4])&#xD;&#xA;    cps[0][0] = np.array([0.577350269189626, 0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    cps[1][0] = np.array([0.278838767912603, 0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[2][0] = np.array([0, 0.647791890991355, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    cps[3][0] = np.array([-0.278838767912603, 0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[4][0] = np.array([-0.577350269189626, 0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    &#xD;&#xA;    cps[0][1] = np.array([0.632392158505876, 0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[1][1] = np.array([0.315090742770461, 0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[2][1] = np.array([0, 0.328648516366383, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[3][1] = np.array([-0.315090742770461, 0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[4][1] = np.array([-0.632392158505876, 0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    &#xD;&#xA;    cps[0][2] = np.array([0.647791890991355, 0, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    cps[1][2] = np.array([0.328648516366383, 0, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[2][2] = np.array([0, 0, -0.859116756396542, 0.671272431591931])&#xD;&#xA;    cps[3][2] = np.array([-0.328648516366383, 0, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[4][2] = np.array([-0.647791890991355, 0, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    &#xD;&#xA;    cps[0][3] = np.array([0.632392158505876, -0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[1][3] = np.array([0.315090742770461, -0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[2][3] = np.array([0, -0.328648516366383, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[3][3] = np.array([-0.315090742770461, -0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[4][3] = np.array([-0.632392158505876, -0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    &#xD;&#xA;    cps[0][4] = np.array([0.577350269189626, -0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    cps[1][4] = np.array([0.278838767912603, -0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[2][4] = np.array([0, -0.647791890991355, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    cps[3][4] = np.array([-0.278838767912603, -0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[4][4] = np.array([-0.577350269189626, -0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    &#xD;&#xA;    #rotation matrix to get other patch cps&#xD;&#xA;    def M(axis, theta):&#xD;&#xA;        M_3 = expm(np.cross(np.eye(3), axis/norm(axis)*theta))&#xD;&#xA;        M_4 = np.eye(4)&#xD;&#xA;        M_4[0:3, 0:3] = M_3&#xD;&#xA;        return M_4&#xD;&#xA;    &#xD;&#xA;    Y_0 = M(np.array([0, 1, 0]), math.pi / 2)&#xD;&#xA;    Y_1 = M(np.array([0, 1, 0]), math.pi)&#xD;&#xA;    Y_2 = M(np.array([0, 1, 0]), 1.5 * math.pi)&#xD;&#xA;    &#xD;&#xA;    Z_0 = M(np.array([0, 0, 1]), math.pi / 2)&#xD;&#xA;    Z_1 = M(np.array([0, 0, 1]), 1.5 * math.pi)&#xD;&#xA;    &#xD;&#xA;    cps2 = np.dot(cps, Y_0)&#xD;&#xA;    cps3 = np.dot(cps, Y_1)&#xD;&#xA;    cps4 = np.dot(cps, Y_2)&#xD;&#xA;    &#xD;&#xA;    cps5 = np.dot(cps2, Z_0)&#xD;&#xA;    cps6 = np.dot(cps2, Z_1)&#xD;&#xA;    &#xD;&#xA;    #Bezier basis functions&#xD;&#xA;    def B_0(t):&#xD;&#xA;        return (1-t)**4&#xD;&#xA;    &#xD;&#xA;    def B_1(t):&#xD;&#xA;        return 4*(1-t)**3 * t&#xD;&#xA;    &#xD;&#xA;    def B_2(t):&#xD;&#xA;        return 6*(1-t)**2 * t**2&#xD;&#xA;    &#xD;&#xA;    def B_3(t):&#xD;&#xA;        return 4*(1-t) * t**3&#xD;&#xA;    &#xD;&#xA;    def B_4(t):&#xD;&#xA;        return t**4&#xD;&#xA;    &#xD;&#xA;    def B(i, t):&#xD;&#xA;        if(i == 0):&#xD;&#xA;            return B_0(t)&#xD;&#xA;        elif(i == 1):&#xD;&#xA;            return B_1(t)&#xD;&#xA;        elif(i == 2):&#xD;&#xA;            return B_2(t)&#xD;&#xA;        elif(i == 3):&#xD;&#xA;            return B_3(t)&#xD;&#xA;        elif(i == 4):&#xD;&#xA;            return B_4(t)&#xD;&#xA;    &#xD;&#xA;    def surface(u, v, cps):&#xD;&#xA;        S = np.array([0, 0, 0, 0])&#xD;&#xA;        W = 0&#xD;&#xA;        for i in range(0, 5):&#xD;&#xA;            for j in range(0, 5):&#xD;&#xA;                w = cps[i][j][3] * B(i, u) * B(j, v)&#xD;&#xA;                S = S + w * cps[i][j]&#xD;&#xA;                W = W + w&#xD;&#xA;        &#xD;&#xA;        h = S / W&#xD;&#xA;        return h&#xD;&#xA;    &#xD;&#xA;    def spheretile(cps, N):&#xD;&#xA;        U = np.linspace(0, 1, N)&#xD;&#xA;        V = np.linspace(0, 1, N)&#xD;&#xA;    &#xD;&#xA;        spheretile = np.zeros([N, N, 4])&#xD;&#xA;        i = 0&#xD;&#xA;        j = 0&#xD;&#xA;        for u in U:&#xD;&#xA;            j = 0&#xD;&#xA;            for v in V:&#xD;&#xA;                spheretile[i][j] = surface(u, v, cps)&#xD;&#xA;    #division from homogeneous coordinates happens here&#xD;&#xA;                spheretile[i][j] = spheretile[i][j] / spheretile[i][j][3]&#xD;&#xA;    &#xD;&#xA;                j = j+ 1&#xD;&#xA;            i = i + 1&#xD;&#xA;        &#xD;&#xA;        return spheretile&#xD;&#xA;    &#xD;&#xA;    s1 = spheretile(cps, 20)&#xD;&#xA;    s2 = spheretile(cps2, 20)&#xD;&#xA;    s3 = spheretile(cps3, 20)&#xD;&#xA;    s4 = spheretile(cps4, 20)&#xD;&#xA;    s5 = spheretile(cps5, 20)&#xD;&#xA;    s6 = spheretile(cps6, 20)&#xD;&#xA;    &#xD;&#xA;    def plotSphereTile(s, ax):&#xD;&#xA;        Xs = s[:, :, 0]&#xD;&#xA;        Ys = s[:, :, 1]&#xD;&#xA;        Zs = s[:, :, 2]&#xD;&#xA;        ax.plot_surface(Xs, Ys, Zs)&#xD;&#xA;    &#xD;&#xA;    fig = plt.figure()&#xD;&#xA;    ax = fig.add_subplot(111, projection='3d')&#xD;&#xA;    plotSphereTile(s1, ax)&#xD;&#xA;    plotSphereTile(s2, ax)&#xD;&#xA;    plotSphereTile(s3, ax)&#xD;&#xA;    plotSphereTile(s4, ax)&#xD;&#xA;    plotSphereTile(s5, ax)&#xD;&#xA;    plotSphereTile(s6, ax)&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;Here is the resulting figure of the script:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lirias.kuleuven.be/bitstream/123456789/607807/1/SphereTiling.pdf&#xD;&#xA;  [2]: https://collections.lib.utah.edu/dl_files/4e/77/4e7746dd53c79f8557272b92b47d2d407da4931a.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/PHWZl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42636" PostHistoryTypeId="5" PostId="13890" RevisionGUID="3a5314e3-25b0-42ff-b1ef-9bdefc5f3f49" CreationDate="2024-02-02T12:11:54.693" UserId="7724" Comment="added 74 characters in body" Text="I was able to find control point locations for a biquartic rational B\'ezier patch for a cube tiling by [Dedoncker et al][1] which is based on the paper by [Cobb][2]. The control point values can be found in table A.2. One important thing to notice is that the control points are homogeneous. The control positions of the other faces can be determined by symmetry. &#xD;&#xA;&#xD;&#xA;To represent this patch as a NURBS surface remember that a Bezier curve is a special type of NURBS curve with a knot vector with multiple knots. So use the knot vectors for a quartic NURBS piece $t_u$ and $t_v$:&#xD;&#xA;&#xD;&#xA;$$t_u = t_v = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]$$&#xD;&#xA;&#xD;&#xA;Then, to obtain larger grid sizes you could use knot insertion, or plain subdivision of the Bezier patch.&#xD;&#xA;&#xD;&#xA;Here I have a simple python script that creates a NURBS sphere from the control points from the paper of Dedoncker et al:&#xD;&#xA;&#xD;&#xA;    import matplotlib.pyplot as plt&#xD;&#xA;    from scipy.linalg import expm, norm&#xD;&#xA;    import numpy as np&#xD;&#xA;    import math&#xD;&#xA;    &#xD;&#xA;    cps = np.zeros([5, 5, 4])&#xD;&#xA;    cps[0][0] = np.array([0.577350269189626, 0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    cps[1][0] = np.array([0.278838767912603, 0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[2][0] = np.array([0, 0.647791890991355, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    cps[3][0] = np.array([-0.278838767912603, 0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[4][0] = np.array([-0.577350269189626, 0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    &#xD;&#xA;    cps[0][1] = np.array([0.632392158505876, 0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[1][1] = np.array([0.315090742770461, 0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[2][1] = np.array([0, 0.328648516366383, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[3][1] = np.array([-0.315090742770461, 0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[4][1] = np.array([-0.632392158505876, 0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    &#xD;&#xA;    cps[0][2] = np.array([0.647791890991355, 0, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    cps[1][2] = np.array([0.328648516366383, 0, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[2][2] = np.array([0, 0, -0.859116756396542, 0.671272431591931])&#xD;&#xA;    cps[3][2] = np.array([-0.328648516366383, 0, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[4][2] = np.array([-0.647791890991355, 0, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    &#xD;&#xA;    cps[0][3] = np.array([0.632392158505876, -0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[1][3] = np.array([0.315090742770461, -0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[2][3] = np.array([0, -0.328648516366383, -0.804938188574224, 0.71866517354005])&#xD;&#xA;    cps[3][3] = np.array([-0.315090742770461, -0.315090742770461, -0.762259526419164, 0.762259526419164])&#xD;&#xA;    cps[4][3] = np.array([-0.632392158505876, -0.278838767912603, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    &#xD;&#xA;    cps[0][4] = np.array([0.577350269189626, -0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    cps[1][4] = np.array([0.278838767912603, -0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[2][4] = np.array([0, -0.647791890991355, -0.647791890991355, 0.859116756396542])&#xD;&#xA;    cps[3][4] = np.array([-0.278838767912603, -0.632392158505876, -0.632392158505876, 0.891211203608397])&#xD;&#xA;    cps[4][4] = np.array([-0.577350269189626, -0.577350269189626, -0.577350269189626, 1])&#xD;&#xA;    &#xD;&#xA;    #rotation matrix to get other patch cps&#xD;&#xA;    def M(axis, theta):&#xD;&#xA;        M_3 = expm(np.cross(np.eye(3), axis/norm(axis)*theta))&#xD;&#xA;        M_4 = np.eye(4)&#xD;&#xA;        M_4[0:3, 0:3] = M_3&#xD;&#xA;        return M_4&#xD;&#xA;    &#xD;&#xA;    Y_0 = M(np.array([0, 1, 0]), math.pi / 2)&#xD;&#xA;    Y_1 = M(np.array([0, 1, 0]), math.pi)&#xD;&#xA;    Y_2 = M(np.array([0, 1, 0]), 1.5 * math.pi)&#xD;&#xA;    &#xD;&#xA;    Z_0 = M(np.array([0, 0, 1]), math.pi / 2)&#xD;&#xA;    Z_1 = M(np.array([0, 0, 1]), 1.5 * math.pi)&#xD;&#xA;    &#xD;&#xA;    cps2 = np.dot(cps, Y_0)&#xD;&#xA;    cps3 = np.dot(cps, Y_1)&#xD;&#xA;    cps4 = np.dot(cps, Y_2)&#xD;&#xA;    &#xD;&#xA;    cps5 = np.dot(cps2, Z_0)&#xD;&#xA;    cps6 = np.dot(cps2, Z_1)&#xD;&#xA;    &#xD;&#xA;    #Bezier basis functions&#xD;&#xA;    def B_0(t):&#xD;&#xA;        return (1-t)**4&#xD;&#xA;    &#xD;&#xA;    def B_1(t):&#xD;&#xA;        return 4*(1-t)**3 * t&#xD;&#xA;    &#xD;&#xA;    def B_2(t):&#xD;&#xA;        return 6*(1-t)**2 * t**2&#xD;&#xA;    &#xD;&#xA;    def B_3(t):&#xD;&#xA;        return 4*(1-t) * t**3&#xD;&#xA;    &#xD;&#xA;    def B_4(t):&#xD;&#xA;        return t**4&#xD;&#xA;    &#xD;&#xA;    def B(i, t):&#xD;&#xA;        if(i == 0):&#xD;&#xA;            return B_0(t)&#xD;&#xA;        elif(i == 1):&#xD;&#xA;            return B_1(t)&#xD;&#xA;        elif(i == 2):&#xD;&#xA;            return B_2(t)&#xD;&#xA;        elif(i == 3):&#xD;&#xA;            return B_3(t)&#xD;&#xA;        elif(i == 4):&#xD;&#xA;            return B_4(t)&#xD;&#xA;    &#xD;&#xA;    def surface(u, v, cps):&#xD;&#xA;        S = np.array([0, 0, 0, 0])&#xD;&#xA;        W = 0&#xD;&#xA;        for i in range(0, 5):&#xD;&#xA;            for j in range(0, 5):&#xD;&#xA;                w = cps[i][j][3] * B(i, u) * B(j, v)&#xD;&#xA;                S = S + w * cps[i][j]&#xD;&#xA;                W = W + w&#xD;&#xA;        &#xD;&#xA;        h = S / W&#xD;&#xA;        return h&#xD;&#xA;    &#xD;&#xA;    def spheretile(cps, N):&#xD;&#xA;        U = np.linspace(0, 1, N)&#xD;&#xA;        V = np.linspace(0, 1, N)&#xD;&#xA;    &#xD;&#xA;        spheretile = np.zeros([N, N, 4])&#xD;&#xA;        i = 0&#xD;&#xA;        j = 0&#xD;&#xA;        for u in U:&#xD;&#xA;            j = 0&#xD;&#xA;            for v in V:&#xD;&#xA;                spheretile[i][j] = surface(u, v, cps)&#xD;&#xA;    #division from homogeneous coordinates happens here&#xD;&#xA;                spheretile[i][j] = spheretile[i][j] / spheretile[i][j][3]&#xD;&#xA;    &#xD;&#xA;                j = j+ 1&#xD;&#xA;            i = i + 1&#xD;&#xA;        &#xD;&#xA;        return spheretile&#xD;&#xA;    &#xD;&#xA;    s1 = spheretile(cps, 20)&#xD;&#xA;    s2 = spheretile(cps2, 20)&#xD;&#xA;    s3 = spheretile(cps3, 20)&#xD;&#xA;    s4 = spheretile(cps4, 20)&#xD;&#xA;    s5 = spheretile(cps5, 20)&#xD;&#xA;    s6 = spheretile(cps6, 20)&#xD;&#xA;    &#xD;&#xA;    def plotSphereTile(s, ax):&#xD;&#xA;        Xs = s[:, :, 0]&#xD;&#xA;        Ys = s[:, :, 1]&#xD;&#xA;        Zs = s[:, :, 2]&#xD;&#xA;        ax.plot_surface(Xs, Ys, Zs)&#xD;&#xA;    &#xD;&#xA;    fig = plt.figure()&#xD;&#xA;    ax = fig.add_subplot(111, projection='3d')&#xD;&#xA;    plotSphereTile(s1, ax)&#xD;&#xA;    plotSphereTile(s2, ax)&#xD;&#xA;    plotSphereTile(s3, ax)&#xD;&#xA;    plotSphereTile(s4, ax)&#xD;&#xA;    plotSphereTile(s5, ax)&#xD;&#xA;    plotSphereTile(s6, ax)&#xD;&#xA;    &#xD;&#xA;    plt.show()&#xD;&#xA;&#xD;&#xA;Here is the resulting figure of the script:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://lirias.kuleuven.be/bitstream/123456789/607807/1/SphereTiling.pdf&#xD;&#xA;  [2]: https://collections.lib.utah.edu/dl_files/4e/77/4e7746dd53c79f8557272b92b47d2d407da4931a.pdf&#xD;&#xA;  [3]: https://i.stack.imgur.com/PHWZl.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42637" PostHistoryTypeId="2" PostId="13897" RevisionGUID="0fc0d110-119f-43fe-8941-92f8e915323c" CreationDate="2024-02-02T12:45:28.760" UserId="21128" Text="**Situation**: I am using Open3D python,The mesh generation algorithm ( like ball pivot, poisson reconstruction ) are dependent on normal direction. I used `estimate_normals` and `orient_normals_consistent_tangent_plane` methods on the point cloud to make sure vertex normals are facing outward.&#xD;&#xA;After generating the mesh, i want to check if the face normals are facing outward. If not, I need to flip it.&#xD;&#xA; &#xD;&#xA;**Help** : how to represent &quot;outward&quot; condition for a face normal, mathematically. I can get face normal from `mesh.triangle_normals`. &#xD;&#xA;&#xD;&#xA;**context** : I am novice engineer, so Any links to theory or examples would help me understand. open3d solution is also welcome :) " ContentLicense="CC BY-SA 4.0" />
  <row Id="42639" PostHistoryTypeId="1" PostId="13897" RevisionGUID="0fc0d110-119f-43fe-8941-92f8e915323c" CreationDate="2024-02-02T12:45:28.760" UserId="21128" Text="how to check if all the faces face outward" ContentLicense="CC BY-SA 4.0" />
  <row Id="42640" PostHistoryTypeId="3" PostId="13897" RevisionGUID="0fc0d110-119f-43fe-8941-92f8e915323c" CreationDate="2024-02-02T12:45:28.760" UserId="21128" Text="|opengl|mesh|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42641" PostHistoryTypeId="5" PostId="13897" RevisionGUID="d1c2604e-5652-44f1-bb02-29f3611ab062" CreationDate="2024-02-02T12:46:29.430" UserId="21128" Comment="edited body" Text="**Situation**: I am using Open3D python,The mesh generation algorithm ( like ball pivot, poisson reconstruction ) are dependent on normal direction. I used `estimate_normals` and `orient_normals_consistent_tangent_plane` methods on the point cloud to make sure vertex normals are facing outward.&#xD;&#xA;After generating the mesh, i want to check if the face normals are facing outward. If not, I need to flip it.&#xD;&#xA; &#xD;&#xA;**Help** : how to represent &quot;outward&quot; condition for a face normal, mathematically. I can get face normal from `mesh.triangle_normals`. &#xD;&#xA;&#xD;&#xA;**context** : I am rookie engineer, so Any links to theory or examples would help me understand. open3d solution is also welcome :) " ContentLicense="CC BY-SA 4.0" />
  <row Id="42642" PostHistoryTypeId="2" PostId="13898" RevisionGUID="05f4a702-e05f-4cb9-a750-ab9e3918f529" CreationDate="2024-02-02T14:18:30.727" UserId="7952" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. A positive cross product indicates clockwise, a negative cross product indicates counter clockwise, and zero indicates a degenerate triangle.&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh." ContentLicense="CC BY-SA 4.0" />
  <row Id="42644" PostHistoryTypeId="5" PostId="13898" RevisionGUID="5ee8eb9c-c276-4613-a0e2-672c031be525" CreationDate="2024-02-02T14:23:58.633" UserId="7952" Comment="added 281 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. A positive cross product indicates clockwise, a negative cross product indicates counter clockwise, and zero indicates a degenerate triangle.&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces." ContentLicense="CC BY-SA 4.0" />
  <row Id="42645" PostHistoryTypeId="5" PostId="13898" RevisionGUID="770568e1-1364-4a5c-ada2-cf5e377bbafb" CreationDate="2024-02-02T14:33:47.863" UserId="7952" Comment="added 227 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. A positive cross product indicates clockwise, a negative cross product indicates counter clockwise, and zero indicates a degenerate triangle.&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="42646" PostHistoryTypeId="5" PostId="13898" RevisionGUID="2c5764b5-e6ad-4df4-abf8-af5d1f7b1fee" CreationDate="2024-02-02T14:52:38.733" UserId="7952" Comment="Fixed stupid mistake of leaving out the dot product." Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem." ContentLicense="CC BY-SA 4.0" />
  <row Id="42647" PostHistoryTypeId="2" PostId="13899" RevisionGUID="5c84332c-0cc8-41f4-babd-c894a8410f9e" CreationDate="2024-02-02T16:22:20.080" UserId="13273" Text="When having a simple continuous triangle mesh which is closed, each edge of a triangle is used twice. So two triangles share one edge. Each face (Triangle) consists of 3 vertices. Here the winding order is from major importance. &#xD;&#xA;&#xD;&#xA;You can hash the edges by a hash key which must be the same for v0-v1 and v1-v0. &#xD;&#xA;&#xD;&#xA;When iterating all triangles add the three edges to the hashtable. There you need to store the order of the two vertices so that you know if it is v0-v1 or v1-v0. &#xD;&#xA;&#xD;&#xA;During this iteration you will have half of the time an empty hash slot. There you add the edge. Else you check winding order. This time it need to be the opposite winding order. Otherwise you have two neighboring faces with different face direction. &#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42649" PostHistoryTypeId="5" PostId="13898" RevisionGUID="3bc56fb7-c2fe-4399-a9f8-53969d3e30f4" CreationDate="2024-02-02T16:44:00.720" UserId="7952" Comment="Add some info resources and a short algorithm" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42650" PostHistoryTypeId="2" PostId="13900" RevisionGUID="927a2e03-a58b-4b36-81de-ccf7d43cf1dc" CreationDate="2024-02-02T20:13:03.650" UserId="17045" Text="I'm rendering a simple triangle using Direct3D11 and I'm seeing a very visible staircase pattern despite enabling 4x MSAA with quality level = 16 on the swap chain (I'm not even using any depth/stencil buffer at this time).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Question: is this really what I should expect, or am I doing something wrong? There's clearly some antialiasing going on, but I expected it to do a better job. &#xD;&#xA;&#xD;&#xA;8x MSAA isn't looking much better:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/omYbd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/Znk1l.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42652" PostHistoryTypeId="1" PostId="13900" RevisionGUID="927a2e03-a58b-4b36-81de-ccf7d43cf1dc" CreationDate="2024-02-02T20:13:03.650" UserId="17045" Text="Direct3D11 4x MSAA enabled - still looking bad" ContentLicense="CC BY-SA 4.0" />
  <row Id="42653" PostHistoryTypeId="3" PostId="13900" RevisionGUID="927a2e03-a58b-4b36-81de-ccf7d43cf1dc" CreationDate="2024-02-02T20:13:03.650" UserId="17045" Text="|antialiasing|directx11|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42654" PostHistoryTypeId="5" PostId="13900" RevisionGUID="3592d0da-bd18-4952-918e-f9f99d853670" CreationDate="2024-02-02T20:25:38.850" UserId="17045" Comment="added 85 characters in body" Text="I'm rendering a simple triangle using Direct3D11 and I'm seeing a very visible staircase pattern despite enabling 4x MSAA with quality level = 16 on the swap chain (I'm not even using any depth/stencil buffer at this time).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Question: is this really what I should expect, or am I doing something wrong? There's clearly some antialiasing going on, but I expected it to do a better job. Why is there a clear drop-off point forming the staircase - shouldn't it be smoother?&#xD;&#xA;&#xD;&#xA;8x MSAA isn't looking much better:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/omYbd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QXk48.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42655" PostHistoryTypeId="5" PostId="13900" RevisionGUID="40f87a9d-0ae8-471d-abdd-3a8e7290d3bd" CreationDate="2024-02-03T00:20:59.153" UserId="17045" Comment="added 4 characters in body" Text="I'm rendering a simple triangle using Direct3D11 and I'm seeing a very visible staircase pattern despite enabling 4x MSAA with quality level = 16 on the swap chain (I'm not even using any depth/stencil buffer at this time).&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Question: is this really what I should expect, or am I doing something wrong?** There's clearly some antialiasing going on, but I expected it to do a better job. Why is there a clear drop-off point forming the staircase - shouldn't it be smoother?&#xD;&#xA;&#xD;&#xA;8x MSAA isn't looking much better:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/omYbd.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/QXk48.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42657" PostHistoryTypeId="5" PostId="13898" RevisionGUID="d89da6a0-6cff-476c-a470-f132e3bfe9b0" CreationDate="2024-02-03T11:56:59.267" UserId="7952" Comment="added 801 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA;The rational behind this method is that most normal vectors are computed as averaged values. So if you have a mesh that is largely valid then the averaged normal will very likely face the correct direction. &#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;Another way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order then they have opposite winding. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, or CA.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42658" PostHistoryTypeId="5" PostId="13898" RevisionGUID="3b6937c7-fb99-4e9e-9731-10bc2758cbed" CreationDate="2024-02-03T12:37:38.077" UserId="7952" Comment="added 145 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;So checking that normal vectors are facing the correct direction is a matter of verifying that all triangles are wound in the same direction.&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA;The rational behind this method is that most normal vectors are computed as averaged values. So if you have a mesh that is largely valid then the averaged normal will very likely face the correct direction. &#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;Another way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order then they have opposite winding. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, or CA.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42659" PostHistoryTypeId="5" PostId="13898" RevisionGUID="fe516f38-68e7-46cc-9230-411fd8d019d9" CreationDate="2024-02-03T12:44:05.613" UserId="7952" Comment="added 145 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. So checking that normal vectors are facing the &quot;outward&quot; is a matter of verifying that all triangles are wound in the same direction.&#xD;&#xA;&#xD;&#xA; There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA;The rational behind this method is that most normal vectors are computed as averaged values. So if you have a mesh that is largely valid then the averaged normal will very likely face the correct direction. &#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;Another way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order the connected triangle has opposite winding and can be fixed by swapping the order of the vertices. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, and CA.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42660" PostHistoryTypeId="5" PostId="13898" RevisionGUID="09664783-531c-4468-9e9f-150e94924839" CreationDate="2024-02-03T12:55:01.837" UserId="7952" Comment="deleted 4 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. So checking that normal vectors are facing &quot;outward&quot; is a matter of verifying that all triangles are wound in the same direction.&#xD;&#xA;&#xD;&#xA; There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA;The rational behind this method is that most normal vectors are computed as averaged values. So if you have a mesh that is largely valid then the averaged normal will very likely face the correct direction. &#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;Another way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order the connected triangle has opposite winding and can be fixed by swapping the order of the vertices. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, and CA.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42661" PostHistoryTypeId="50" PostId="12158" RevisionGUID="9d0a2a0f-3670-4e92-90ce-e0604b5ee7eb" CreationDate="2024-02-03T14:04:15.467" UserId="-1" />
  <row Id="42662" PostHistoryTypeId="5" PostId="13899" RevisionGUID="3647ff23-8565-4513-a399-128b7d5317e2" CreationDate="2024-02-03T17:11:03.647" UserId="13273" Comment="added 4497 characters in body" Text="When having a simple continuous triangle mesh which is closed, each edge of a triangle is used twice. So two triangles share one edge. Each face (Triangle) consists of 3 vertices. Here the winding order is from major importance. &#xD;&#xA;&#xD;&#xA;You can hash the edges by a hash key which must be the same for v0-v1 and v1-v0. &#xD;&#xA;&#xD;&#xA;When iterating all triangles add the three edges to the hashtable. There you need to store the order of the two vertices so that you know if it is v0-v1 or v1-v0. &#xD;&#xA;&#xD;&#xA;During this iteration you will have half of the time an empty hash slot. There you add the edge. Else you check winding order. This time it need to be the opposite winding order. Otherwise you have two neighboring faces with different face direction. &#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	#include &lt;vector&gt;&#xD;&#xA;	#include &lt;map&gt;&#xD;&#xA;&#xD;&#xA;	struct Vertex&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;&#xD;&#xA;		bool operator &gt; (const Vertex&amp; otherVertex) const&#xD;&#xA;		{&#xD;&#xA;			if (positionX &gt; otherVertex.positionX)&#xD;&#xA;			{&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else if (positionX == otherVertex.positionX)&#xD;&#xA;			{&#xD;&#xA;				if (positionY &gt; otherVertex.positionY)&#xD;&#xA;				{&#xD;&#xA;					return true;&#xD;&#xA;				}&#xD;&#xA;				else if (positionY == otherVertex.positionY)&#xD;&#xA;				{&#xD;&#xA;					if (positionZ &gt; otherVertex.positionZ)&#xD;&#xA;					{&#xD;&#xA;						return true;&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}		&#xD;&#xA;			return false;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		bool operator == (const Vertex&amp; otherVertex) const&#xD;&#xA;		{&#xD;&#xA;			return positionX == otherVertex.positionX &amp;&amp;&#xD;&#xA;				positionY == otherVertex.positionY &amp;&amp;&#xD;&#xA;				positionZ == otherVertex.positionZ;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		float positionX;&#xD;&#xA;		float positionY;&#xD;&#xA;		float positionZ;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct Face&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;		Vertex vertex0;&#xD;&#xA;		Vertex vertex1;&#xD;&#xA;		Vertex vertex2;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	/**&#xD;&#xA;	Doesn't matter which vertex is the first of the two. This is important!&#xD;&#xA;	**/&#xD;&#xA;	struct EdgeHashKey&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;		static EdgeHashKey generateHashKey(const Vertex&amp; vertex0, const Vertex&amp; vertex1)&#xD;&#xA;		{&#xD;&#xA;			EdgeHashKey result;&#xD;&#xA;			if (vertex0 &gt; vertex1)&#xD;&#xA;			{&#xD;&#xA;				result.lowerVertex = vertex1;&#xD;&#xA;				result.higherVertex = vertex0;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				result.lowerVertex = vertex0;&#xD;&#xA;				result.higherVertex = vertex1;&#xD;&#xA;			}&#xD;&#xA;			return result;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		bool operator &lt; (const EdgeHashKey&amp; otherHashKey) const&#xD;&#xA;		{&#xD;&#xA;			return otherHashKey.higherVertex == higherVertex &amp;&amp; otherHashKey.lowerVertex == lowerVertex;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;	private:&#xD;&#xA;		Vertex lowerVertex;&#xD;&#xA;		Vertex higherVertex;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	std::vector&lt;Face&gt; loadMesh()&#xD;&#xA;	{&#xD;&#xA;		//in here you can bring your mesh into the correct format (struct Vertex and struct Face)&#xD;&#xA;		std::vector&lt;Face&gt; result;&#xD;&#xA;		//...&#xD;&#xA;		return result;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	bool faceDirectionTest(const std::vector&lt;Face&gt;&amp; mesh)&#xD;&#xA;	{&#xD;&#xA;		std::map&lt;EdgeHashKey, bool&gt; hashTable; //the edge is the hashkey. The boolian: true =&gt; first lowerVertex, secound higherVertex. false =&gt; first higherVertex, secound lowerVertex&#xD;&#xA;&#xD;&#xA;		for (std::vector&lt;Face&gt;::const_iterator it = mesh.cbegin(); it != mesh.cend(); ++it)&#xD;&#xA;		{&#xD;&#xA;			//Step1: generate hashkey for all three edges&#xD;&#xA;			//Also get the additional boolian value for all three edges&#xD;&#xA;			EdgeHashKey hashKeyV01 = EdgeHashKey::generateHashKey(it-&gt;vertex0, it-&gt;vertex1);&#xD;&#xA;			EdgeHashKey hashKeyV12 = EdgeHashKey::generateHashKey(it-&gt;vertex1, it-&gt;vertex2);&#xD;&#xA;			EdgeHashKey hashKeyV20 = EdgeHashKey::generateHashKey(it-&gt;vertex2, it-&gt;vertex0);&#xD;&#xA;			bool directionV01 = it-&gt;vertex0 &gt; it-&gt;vertex1;&#xD;&#xA;			bool directionV12 = it-&gt;vertex1 &gt; it-&gt;vertex2;&#xD;&#xA;			bool directionV20 = it-&gt;vertex2 &gt; it-&gt;vertex0;&#xD;&#xA;&#xD;&#xA;			//Step2: get the hash slot:&#xD;&#xA;			std::map&lt;EdgeHashKey, bool&gt;::iterator hashSlotV01 = hashTable.find(hashKeyV01);&#xD;&#xA;			std::map&lt;EdgeHashKey, bool&gt;::iterator hashSlotV12 = hashTable.find(hashKeyV12);&#xD;&#xA;			std::map&lt;EdgeHashKey, bool&gt;::iterator hashSlotV20 = hashTable.find(hashKeyV20);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;			///Edge 01&#xD;&#xA;			//per check there are two possibilitiers: 1 =&gt; this edge is not in the list: store it. 2 =&gt; this edge is already in the list: check it!&#xD;&#xA;			if (hashSlotV01 == hashTable.cend()) //not in hash table, so we add it&#xD;&#xA;			{&#xD;&#xA;				hashTable[hashKeyV01] = directionV01;&#xD;&#xA;			}&#xD;&#xA;			else //this edge is inside the hash table, so we check the winding order&#xD;&#xA;			{&#xD;&#xA;				if (hashSlotV01-&gt;second == directionV01) // two neighboring faces have different face direction!!!&#xD;&#xA;				{&#xD;&#xA;					return false;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			///Edge 12&#xD;&#xA;			//per check there are two possibilitiers: 1 =&gt; this edge is not in the list: store it. 2 =&gt; this edge is already in the list: check it!&#xD;&#xA;			if (hashSlotV12 == hashTable.cend()) //not in hash table, so we add it&#xD;&#xA;			{&#xD;&#xA;				hashTable[hashKeyV12] = directionV12;&#xD;&#xA;			}&#xD;&#xA;			else //this edge is inside the hash table, so we check the winding order&#xD;&#xA;			{&#xD;&#xA;				if (hashSlotV12-&gt;second == directionV12) // two neighboring faces have different face direction!!!&#xD;&#xA;				{&#xD;&#xA;					return false;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			///Edge 20&#xD;&#xA;			//per check there are two possibilitiers: 1 =&gt; this edge is not in the list: store it. 2 =&gt; this edge is already in the list: check it!&#xD;&#xA;			if (hashSlotV20 == hashTable.cend()) //not in hash table, so we add it&#xD;&#xA;			{&#xD;&#xA;				hashTable[hashKeyV20] = directionV20;&#xD;&#xA;			}&#xD;&#xA;			else //this edge is inside the hash table, so we check the winding order&#xD;&#xA;			{&#xD;&#xA;				if (hashSlotV20-&gt;second == directionV20) // two neighboring faces have different face direction!!!&#xD;&#xA;				{&#xD;&#xA;					return false;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		return true;&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="42663" PostHistoryTypeId="50" PostId="10955" RevisionGUID="7ec8d2c6-e49e-42d7-8159-d9410f007928" CreationDate="2024-02-03T23:03:00.300" UserId="-1" />
  <row Id="42664" PostHistoryTypeId="2" PostId="13901" RevisionGUID="38e29609-4599-498f-8279-3d791255b25f" CreationDate="2024-02-04T23:51:35.557" UserId="20471" Text="If you're looking for a C++ solution, try this one:&#xD;&#xA;&#xD;&#xA;[https://github.com/sjhalayka/point_to_mesh_text][1]&#xD;&#xA;&#xD;&#xA;The input looks like:&#xD;&#xA;&#xD;&#xA;    -0.0757585 -0.136365 -1.16667&#xD;&#xA;    -0.0757585 -0.106062 -1.16667&#xD;&#xA;    -0.0757585 -0.0757585 -1.16667&#xD;&#xA;    -0.0757585 -0.0454555 -1.16667&#xD;&#xA;    -0.0757585 -0.0151525 -1.16667&#xD;&#xA;    -0.0757585 0.0151506 -1.16667&#xD;&#xA;    -0.0757585 0.0454536 -1.16667&#xD;&#xA;    -0.0757585 0.0757566 -1.16667&#xD;&#xA;    -0.0757585 0.10606 -1.16667&#xD;&#xA;    -0.0757585 0.136363 -1.16667&#xD;&#xA;    -0.0757585 0.166666 -1.16667&#xD;&#xA;    -0.0454555 -0.106062 -1.16667&#xD;&#xA;    -0.0454555 -0.0757585 -1.16667&#xD;&#xA;    -0.0454555 -0.0454555 -1.16667&#xD;&#xA;    ...&#xD;&#xA;&#xD;&#xA;and the resulting mesh looks like:&#xD;&#xA;&#xD;&#xA;[![fractal mesh][2]][2]&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/sjhalayka/point_to_mesh_text&#xD;&#xA;  [2]: https://i.stack.imgur.com/4sQbo.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42670" PostHistoryTypeId="5" PostId="13899" RevisionGUID="3b0d2b0e-6616-4f56-bfdd-eff6aa742e20" CreationDate="2024-02-05T07:32:23.710" UserId="13273" Comment="added 228 characters in body" Text="When having a simple continuous triangle mesh which is closed, each edge of a triangle is used twice. So two triangles share one edge. Each face (Triangle) consists of 3 vertices. Here the winding order is from major importance. &#xD;&#xA;&#xD;&#xA;You can hash the edges by a hash key which must be the same for v0-v1 and v1-v0. &#xD;&#xA;&#xD;&#xA;When iterating all triangles add the three edges to the hashtable. There you need to store the order of the two vertices so that you know if it is v0-v1 or v1-v0. &#xD;&#xA;&#xD;&#xA;During this iteration you will have half of the time an empty hash slot. There you add the edge. Else you check winding order. This time it need to be the opposite winding order. Otherwise you have two neighboring faces with different face direction. &#xD;&#xA;&#xD;&#xA;EDIT:&#xD;&#xA;&#xD;&#xA;	#include &lt;iostream&gt;&#xD;&#xA;	#include &lt;vector&gt;&#xD;&#xA;	#include &lt;map&gt;&#xD;&#xA;&#xD;&#xA;	struct Vertex&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;&#xD;&#xA;		bool operator &gt; (const Vertex&amp; otherVertex) const&#xD;&#xA;		{&#xD;&#xA;			if (positionX &gt; otherVertex.positionX)&#xD;&#xA;			{&#xD;&#xA;				return true;&#xD;&#xA;			}&#xD;&#xA;			else if (positionX == otherVertex.positionX)&#xD;&#xA;			{&#xD;&#xA;				if (positionY &gt; otherVertex.positionY)&#xD;&#xA;				{&#xD;&#xA;					return true;&#xD;&#xA;				}&#xD;&#xA;				else if (positionY == otherVertex.positionY)&#xD;&#xA;				{&#xD;&#xA;					if (positionZ &gt; otherVertex.positionZ)&#xD;&#xA;					{&#xD;&#xA;						return true;&#xD;&#xA;					}&#xD;&#xA;				}&#xD;&#xA;			}		&#xD;&#xA;			return false;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		bool operator == (const Vertex&amp; otherVertex) const&#xD;&#xA;		{&#xD;&#xA;			return positionX == otherVertex.positionX &amp;&amp;&#xD;&#xA;				positionY == otherVertex.positionY &amp;&amp;&#xD;&#xA;				positionZ == otherVertex.positionZ;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		float positionX;&#xD;&#xA;		float positionY;&#xD;&#xA;		float positionZ;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	struct Face&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;		Vertex vertex0;&#xD;&#xA;		Vertex vertex1;&#xD;&#xA;		Vertex vertex2;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	/**&#xD;&#xA;	Doesn't matter which vertex is the first of the two. This is important!&#xD;&#xA;	**/&#xD;&#xA;	struct EdgeHashKey&#xD;&#xA;	{&#xD;&#xA;	public:&#xD;&#xA;		static EdgeHashKey generateHashKey(const Vertex&amp; vertex0, const Vertex&amp; vertex1)&#xD;&#xA;		{&#xD;&#xA;			EdgeHashKey result;&#xD;&#xA;			if (vertex0 &gt; vertex1)&#xD;&#xA;			{&#xD;&#xA;				result.lowerVertex = vertex1;&#xD;&#xA;				result.higherVertex = vertex0;&#xD;&#xA;			}&#xD;&#xA;			else&#xD;&#xA;			{&#xD;&#xA;				result.lowerVertex = vertex0;&#xD;&#xA;				result.higherVertex = vertex1;&#xD;&#xA;			}&#xD;&#xA;			return result;&#xD;&#xA;		}&#xD;&#xA;&#xD;&#xA;		bool operator &lt; (const EdgeHashKey&amp; otherHashKey) const&#xD;&#xA;        {&#xD;&#xA;        	if (lowerVertex &lt; otherHashKey.lowerVertex)&#xD;&#xA;        	{&#xD;&#xA;        		return true;&#xD;&#xA;        	}&#xD;&#xA;        	if (lowerVertex == otherHashKey.lowerVertex)&#xD;&#xA;        	{&#xD;&#xA;        		if (higherVertex &lt; otherHashKey.higherVertex)&#xD;&#xA;        		{&#xD;&#xA;        			return true;&#xD;&#xA;        		}&#xD;&#xA;        	}&#xD;&#xA;        	return false;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;	private:&#xD;&#xA;		Vertex lowerVertex;&#xD;&#xA;		Vertex higherVertex;&#xD;&#xA;	};&#xD;&#xA;&#xD;&#xA;	std::vector&lt;Face&gt; loadMesh()&#xD;&#xA;	{&#xD;&#xA;		//in here you can bring your mesh into the correct format (struct Vertex and struct Face)&#xD;&#xA;		std::vector&lt;Face&gt; result;&#xD;&#xA;		//...&#xD;&#xA;		return result;&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	bool faceDirectionTest(const std::vector&lt;Face&gt;&amp; mesh)&#xD;&#xA;	{&#xD;&#xA;		std::map&lt;EdgeHashKey, bool&gt; hashTable; //the edge is the hashkey. The boolian: true =&gt; first lowerVertex, secound higherVertex. false =&gt; first higherVertex, secound lowerVertex&#xD;&#xA;&#xD;&#xA;		for (std::vector&lt;Face&gt;::const_iterator it = mesh.cbegin(); it != mesh.cend(); ++it)&#xD;&#xA;		{&#xD;&#xA;			//Step1: generate hashkey for all three edges&#xD;&#xA;			//Also get the additional boolian value for all three edges&#xD;&#xA;			EdgeHashKey hashKeyV01 = EdgeHashKey::generateHashKey(it-&gt;vertex0, it-&gt;vertex1);&#xD;&#xA;			EdgeHashKey hashKeyV12 = EdgeHashKey::generateHashKey(it-&gt;vertex1, it-&gt;vertex2);&#xD;&#xA;			EdgeHashKey hashKeyV20 = EdgeHashKey::generateHashKey(it-&gt;vertex2, it-&gt;vertex0);&#xD;&#xA;			bool directionV01 = it-&gt;vertex0 &gt; it-&gt;vertex1;&#xD;&#xA;			bool directionV12 = it-&gt;vertex1 &gt; it-&gt;vertex2;&#xD;&#xA;			bool directionV20 = it-&gt;vertex2 &gt; it-&gt;vertex0;&#xD;&#xA;&#xD;&#xA;			//Step2: get the hash slot:&#xD;&#xA;			std::map&lt;EdgeHashKey, bool&gt;::iterator hashSlotV01 = hashTable.find(hashKeyV01);&#xD;&#xA;			std::map&lt;EdgeHashKey, bool&gt;::iterator hashSlotV12 = hashTable.find(hashKeyV12);&#xD;&#xA;			std::map&lt;EdgeHashKey, bool&gt;::iterator hashSlotV20 = hashTable.find(hashKeyV20);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;			///Edge 01&#xD;&#xA;			//per check there are two possibilitiers: 1 =&gt; this edge is not in the list: store it. 2 =&gt; this edge is already in the list: check it!&#xD;&#xA;			if (hashSlotV01 == hashTable.cend()) //not in hash table, so we add it&#xD;&#xA;			{&#xD;&#xA;				hashTable[hashKeyV01] = directionV01;&#xD;&#xA;			}&#xD;&#xA;			else //this edge is inside the hash table, so we check the winding order&#xD;&#xA;			{&#xD;&#xA;				if (hashSlotV01-&gt;second == directionV01) // two neighboring faces have different face direction!!!&#xD;&#xA;				{&#xD;&#xA;					return false;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			///Edge 12&#xD;&#xA;			//per check there are two possibilitiers: 1 =&gt; this edge is not in the list: store it. 2 =&gt; this edge is already in the list: check it!&#xD;&#xA;			if (hashSlotV12 == hashTable.cend()) //not in hash table, so we add it&#xD;&#xA;			{&#xD;&#xA;				hashTable[hashKeyV12] = directionV12;&#xD;&#xA;			}&#xD;&#xA;			else //this edge is inside the hash table, so we check the winding order&#xD;&#xA;			{&#xD;&#xA;				if (hashSlotV12-&gt;second == directionV12) // two neighboring faces have different face direction!!!&#xD;&#xA;				{&#xD;&#xA;					return false;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;&#xD;&#xA;			///Edge 20&#xD;&#xA;			//per check there are two possibilitiers: 1 =&gt; this edge is not in the list: store it. 2 =&gt; this edge is already in the list: check it!&#xD;&#xA;			if (hashSlotV20 == hashTable.cend()) //not in hash table, so we add it&#xD;&#xA;			{&#xD;&#xA;				hashTable[hashKeyV20] = directionV20;&#xD;&#xA;			}&#xD;&#xA;			else //this edge is inside the hash table, so we check the winding order&#xD;&#xA;			{&#xD;&#xA;				if (hashSlotV20-&gt;second == directionV20) // two neighboring faces have different face direction!!!&#xD;&#xA;				{&#xD;&#xA;					return false;&#xD;&#xA;				}&#xD;&#xA;			}&#xD;&#xA;		}&#xD;&#xA;		return true;&#xD;&#xA;	}" ContentLicense="CC BY-SA 4.0" />
  <row Id="42671" PostHistoryTypeId="50" PostId="13400" RevisionGUID="bb151569-e5f7-4d78-aacf-aec826ed1b4d" CreationDate="2024-02-05T10:02:55.340" UserId="-1" />
  <row Id="42672" PostHistoryTypeId="50" PostId="10341" RevisionGUID="098f0af3-a311-484c-80c2-bbbcd7a2188c" CreationDate="2024-02-05T12:09:56.183" UserId="-1" />
  <row Id="42673" PostHistoryTypeId="5" PostId="13898" RevisionGUID="b5266548-d7c9-4555-9cf1-083c5a4fac9b" CreationDate="2024-02-05T12:52:39.687" UserId="7952" Comment="added 481 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. So checking that normal vectors are facing &quot;outward&quot; is a matter of verifying that all triangles are wound in the same direction.&#xD;&#xA;&#xD;&#xA; There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;To compute the winding order take the first two edges of each triangle in the order they are given and compute the cross product. Then compute the dot product of the given normal and our computed vector (which is a faceted normal) A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA;The rational behind this method is that most normal vectors are computed as averaged values. So if you have a mesh that is largely valid then the averaged normal will very likely face the correct direction. &#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;Another way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order the connected triangle has opposite winding and can be fixed by swapping the order of the vertices. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, and CA.&#xD;&#xA;&#xD;&#xA;    Implementation:&#xD;&#xA;The property &quot;connected triangles with the same winding have edges with the opposite order&quot; makes this particularly easy to implement since this means that if edge AB is repeated anywhere then there is a problem. IE AB is unique in the mesh. Implementation is just a matter of picking your favorite data structure and using insert unique. That's it we're done. Non-unique means there is a problem, reverse the winding of that triangle and continue. Done.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42674" PostHistoryTypeId="50" PostId="13698" RevisionGUID="173120e0-360a-4644-9893-925b4670620b" CreationDate="2024-02-05T17:04:00.463" UserId="-1" />
  <row Id="42675" PostHistoryTypeId="2" PostId="13903" RevisionGUID="a183e2a8-a366-4ba5-b751-5617fb7f9bca" CreationDate="2024-02-06T09:14:27.387" UserId="21149" Text="I am trying to write an L-System to generate the Penrose P3 tiling (with thin and thick rhombi, I will call them Rhombus-A and Rhombus-B.&#xD;&#xA;&#xD;&#xA;For render, I am planning to use the following chars.&#xD;&#xA;&#xD;&#xA; + '+' means rotate counter-clockwise TWO_PI/10&#xD;&#xA; + '-' means rotate clockwise TWO_PI/10&#xD;&#xA; + 'A' means draw Rhombus-A&#xD;&#xA; + 'B' means draw Rhombus-B&#xD;&#xA; + '[' push transformation matrix&#xD;&#xA; + ']' pop transformation matrix&#xD;&#xA;&#xD;&#xA;And my question is what would the L-System be to generate an Penrose P3 tiling?&#xD;&#xA;&#xD;&#xA;Any re" ContentLicense="CC BY-SA 4.0" />
  <row Id="42677" PostHistoryTypeId="1" PostId="13903" RevisionGUID="a183e2a8-a366-4ba5-b751-5617fb7f9bca" CreationDate="2024-02-06T09:14:27.387" UserId="21149" Text="L-System to generate the Penrose P3 tiling" ContentLicense="CC BY-SA 4.0" />
  <row Id="42678" PostHistoryTypeId="3" PostId="13903" RevisionGUID="a183e2a8-a366-4ba5-b751-5617fb7f9bca" CreationDate="2024-02-06T09:14:27.387" UserId="21149" Text="|algorithm|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42679" PostHistoryTypeId="2" PostId="13904" RevisionGUID="ad5a5eb5-4642-4711-83e8-28f6fc0951a0" CreationDate="2024-02-06T14:43:17.130" UserId="7647" Text="Let's take a look at the rules for generating the P3 tiling, from the great [Tilings Encyclopedia][1]:&#xD;&#xA;&#xD;&#xA;[![Subdivision rules for the Penrose P3 tiling][2]][2]&#xD;&#xA;&#xD;&#xA;Let's put the reference point for these rhombs at the bottom of each, pointing up.&#xD;&#xA;&#xD;&#xA;The fat rhomb has four children. We can place the lower two on each side (one fat, one thin) together, as their reference points coincide. On the left:&#xD;&#xA;&#xD;&#xA;    + to align us to the left edge of the old rhomb&#xD;&#xA;    F to move us to the left point of the old rhomb&#xD;&#xA;    -- to point us up and to the right&#xD;&#xA;    B to place the thin rhomb&#xD;&#xA;    --- to point us down and to the right&#xD;&#xA;    A to place the fat rhomb&#xD;&#xA;&#xD;&#xA;On the right is the same, with left and right reversed.&#xD;&#xA;&#xD;&#xA;Finally, we place the top child by moving up the sides. The final production for the fat rhomb is something like&#xD;&#xA;&#xD;&#xA;    A --&gt; [ + F -- B --- A ] [ - F ++ B +++ A ] [ - F ++ F ++++ A ]&#xD;&#xA;&#xD;&#xA;The thin rhomb has four children, with three different reference points. We can place the fat child on the left with&#xD;&#xA;&#xD;&#xA;    ++ to align with the left edge&#xD;&#xA;    F  to move to the left point&#xD;&#xA;    -----  to turn around&#xD;&#xA;    A  to place the rhomb&#xD;&#xA;&#xD;&#xA;The fat child on the right is symmetrical. The two thin children share a reference point, so we can do them together:&#xD;&#xA;&#xD;&#xA;    ++ to align with the bottom left edge&#xD;&#xA;    F  to move to the left point&#xD;&#xA;    ---- to align with the top left edge&#xD;&#xA;    F  to move to the top point&#xD;&#xA;    - to align with the top right edge&#xD;&#xA;    B  to place the thin rhomb&#xD;&#xA;    ---- to align with the top left edge&#xD;&#xA;    B to place the second thin rhomb&#xD;&#xA;&#xD;&#xA;The second production is then&#xD;&#xA;&#xD;&#xA;    B --&gt; [ ++ F ----- A ] [ -- F +++++ A ] [ ++ F ---- F - B ---- B ]&#xD;&#xA;&#xD;&#xA;Hopefully you can see how this works in general. We choose a reference point on the predecessor; then the production moves from that point to the reference points on each successor, aligns correctly, and places the successor.&#xD;&#xA;&#xD;&#xA;  [1]: https://tilings.math.uni-bielefeld.de/substitution/penrose-rhomb/&#xD;&#xA;  [2]: https://i.stack.imgur.com/n1PEr.png&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42681" PostHistoryTypeId="50" PostId="13210" RevisionGUID="6ffcbf39-6374-49d1-a7a5-74efe7442735" CreationDate="2024-02-06T18:08:26.063" UserId="-1" />
  <row Id="42682" PostHistoryTypeId="2" PostId="13905" RevisionGUID="abb2e0e6-8135-4f03-ad40-5978aab6a525" CreationDate="2024-02-06T18:58:41.770" UserId="21150" Text="If you are using OpenGL and if you are referring to Photoshop's layer blend functions. This may be a complete answer for you &#xD;&#xA;&#xD;&#xA;https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/&#xD;&#xA;&#xD;&#xA;I found that link from this one&#xD;&#xA;&#xD;&#xA;https://stackoverflow.com/questions/818230/photoshop-blending-mode-to-opengl-es-without-shaders?rq=3&#xD;&#xA;&#xD;&#xA;The rest here is not EXACTLY an answer to your question, because I do not fully understand your question. Do please add more information about how you need to apply this math for more practical answers. &#xD;&#xA;&#xD;&#xA;While I don't know what the exact equations are, the blend options in Photoshop have been available for a very long time. My guess is that each layer (legacy) blend mode represents a fairly simple mathematical equation. &#xD;&#xA;&#xD;&#xA;Given what photoshop is and who adobe is and how advanced their functionality has always been I would not be at all surprised if they were writing custom GFX card code way back when. However with the shear amount of GFX card code that was written for very specific hardware for specific engines like DirectX and OpenGL historically(and currently), chances are that they leveraged capabilities that have been directly available in these engines for a long time. &#xD;&#xA;&#xD;&#xA;My guess is that you can simulate all of the layer blend modes with something like OpenGL's &quot;blendEquation&quot; and &quot;blendFunc&quot;, which amounts to modifying how the values between two layers are added together. &#xD;&#xA;https://learnopengl.com/Advanced-OpenGL/Blending#Blending" ContentLicense="CC BY-SA 4.0" />
  <row Id="42684" PostHistoryTypeId="2" PostId="13906" RevisionGUID="16eaacf6-baf1-42dd-8da5-99f0986852ea" CreationDate="2024-02-06T22:52:35.890" UserId="21151" Text="At the beginning I thought they were like Fast and Fine compression of Photoshop's Intel texture tools, but I later found the tool uses a different compressor called Intel's ISPCTextureCompressor,&#xD;&#xA;&#xD;&#xA;So I want to know does those flags affect the image quality in any way?&#xD;&#xA;Is there a benefit of using them?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42686" PostHistoryTypeId="1" PostId="13906" RevisionGUID="16eaacf6-baf1-42dd-8da5-99f0986852ea" CreationDate="2024-02-06T22:52:35.890" UserId="21151" Text="What the diffrence between BC7_QUICK and BC7_USE_3SUBSETS compression flags in DirectXtex lib?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42687" PostHistoryTypeId="3" PostId="13906" RevisionGUID="16eaacf6-baf1-42dd-8da5-99f0986852ea" CreationDate="2024-02-06T22:52:35.890" UserId="21151" Text="|image-processing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42688" PostHistoryTypeId="5" PostId="13898" RevisionGUID="7d6b57d7-8f08-4db2-bcd9-45e3f8223b06" CreationDate="2024-02-07T12:49:29.503" UserId="7952" Comment="added 189 characters in body" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. So checking that normal vectors are facing &quot;outward&quot; is a matter of verifying that all triangles are wound in the same direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA; There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;Method 1:&#xD;&#xA;&#xD;&#xA;This is more of a quick check but is fairly effective in practice.&#xD;&#xA;Given a mesh with averaged normals, for each triangle compute the faceted normal and compute the cos of the angle between the averaged normal and the faceted normal using the dot product.  A positive result indicates clockwise, a negative result indicates counter clockwise, and zero indicates that the two normals are very close to each other. Keeping a count of clockwise and counter clockwise where one of the two should be zero depending on the winding order of the mesh.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;If all the triangles have the same winding order then the mesh can be accepted as being consistent and &quot;outward&quot; is defined as all faces having either clock wise or counter clock wise orientation depending on the handedness of the mesh.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The rational behind this method is that most normal vectors are computed as averaged values. So if you have a mesh that is largely valid then the averaged normal will very likely face the correct direction. &#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;Method 2:&#xD;&#xA;&#xD;&#xA;Another way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order the connected triangle has opposite winding and can be fixed by swapping the order of the vertices. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, and CA.&#xD;&#xA;&#xD;&#xA;Implementation:&#xD;&#xA;&#xD;&#xA;The property &quot;connected triangles with the same winding have edges with the opposite order&quot; makes this particularly easy to implement since this means that if edge AB is repeated anywhere then there is a problem. IE AB is unique in the mesh. Implementation is just a matter of picking your favorite data structure and using insert unique. That's it we're done. Non-unique means there is a problem, reverse the winding of that triangle and continue. Done.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42689" PostHistoryTypeId="50" PostId="10025" RevisionGUID="0810f2e4-5271-4469-9cce-3ac833619503" CreationDate="2024-02-08T05:07:30.863" UserId="-1" />
  <row Id="42690" PostHistoryTypeId="50" PostId="13686" RevisionGUID="c0535e5a-3e6e-401c-92c2-d3bbb29f5be3" CreationDate="2024-02-08T08:08:15.977" UserId="-1" />
  <row Id="42691" PostHistoryTypeId="2" PostId="13907" RevisionGUID="10606ac1-3c45-4413-8ee0-ea64ab841162" CreationDate="2024-02-08T12:29:39.290" UserId="7952" Text="BC7 dedicates the first byte of each block to a &quot;mode&quot; of which there are 8 possibilities. 7 of those possibilities are defined and the 8th is reserved. So, unlike other block compression methods, every block of BC7 can be a different mode. This vastly increases the search space for finding a good compression and can slow the compression down to a crawl.&#xD;&#xA;&#xD;&#xA;By default DirectXtex lib skips modes 0 &amp; 2 as part of that search space, the flag BC7_USE_3SUBSETS adds those modes back in.&#xD;&#xA;&#xD;&#xA;BC7_QUICK on the other hands further restricts the number of modes that can be searched for each block, usually just down to mode 6.&#xD;&#xA;&#xD;&#xA;So we should see better quality results from the use 3 subsets along with slightly smaller or same sized compressed images.&#xD;&#xA;&#xD;&#xA;The compressors are still new enough, and the problem complex enough that results are likely to vary from image to image though.&#xD;&#xA;&#xD;&#xA;Here is some reference material:&#xD;&#xA;&#xD;&#xA;https://github.com/microsoft/DirectXTex/wiki/Compress&#xD;&#xA;https://github.com/microsoft/DirectXTex/blob/main/DirectXTex/BC.h" ContentLicense="CC BY-SA 4.0" />
  <row Id="42693" PostHistoryTypeId="50" PostId="9267" RevisionGUID="0c542c08-bc57-4733-85d6-3c76966f55fa" CreationDate="2024-02-08T13:03:10.427" UserId="-1" />
  <row Id="42694" PostHistoryTypeId="50" PostId="8935" RevisionGUID="4cdf8895-9c15-4012-8b87-4f55beb1a6cc" CreationDate="2024-02-09T04:05:55.660" UserId="-1" />
  <row Id="42695" PostHistoryTypeId="50" PostId="13355" RevisionGUID="19cc4be7-75d8-47f7-ace0-b18cf69e8b67" CreationDate="2024-02-09T14:00:00.017" UserId="-1" />
  <row Id="42696" PostHistoryTypeId="2" PostId="13908" RevisionGUID="7053dd05-e9a9-4091-be0e-8c0f51215b32" CreationDate="2024-02-09T21:16:37.147" UserId="9254" Text="I want to render scenes like they are used in mitsuba or pbrt (see https://benedikt-bitterli.me/resources/ for example scene description files).&#xD;&#xA;&#xD;&#xA;That is, I have a list of obj-files. Each Obj file contains a mesh. And to each obj file a different BSDF is related. What I'm currently doing is creating a separate vertex and index buffer per obj file. Moreover, I'm creating a separate bottom level acceleration structure (BLAS) per obj file. I'm assing an `InstanceID` of `i` to the $i$th obj file so that I can figure out which one was hit using the `InstanceID()` intrinsic in my closesthit shader.&#xD;&#xA;&#xD;&#xA;Now, that's fine. However, I wonder how I'm able to access the vertex buffer in my shaders. When I only have a single obj file (and hence a single BLAS), I can simply upload the corresponding vertex and index buffers. So, in that case I have something like this in my code:&#xD;&#xA;&#xD;&#xA;	RaytracingAccelerationStructure accelerationStructure : register(t0);&#xD;&#xA;	StructuredBuffer&lt;Vertex&gt;		vertices			  : register(t1);&#xD;&#xA;	StructuredBuffer&lt;uint&gt;			indices				  : register(t2);&#xD;&#xA;&#xD;&#xA;But what am I doing if I have multiple BLASs with different vertex/index buffers? Do I need to concatenate them together? But how do I distinguish them in the code then? For example, if the $i$th mesh was hit, how do I skip over the vertices corresponding to the first $i-1$ meshes?&#xD;&#xA;&#xD;&#xA;This is such a common problem that there must be general advice on this. Looking into the existing tutorials is not of much help, since they are either way to simple or way too complex ..." ContentLicense="CC BY-SA 4.0" />
  <row Id="42698" PostHistoryTypeId="1" PostId="13908" RevisionGUID="7053dd05-e9a9-4091-be0e-8c0f51215b32" CreationDate="2024-02-09T21:16:37.147" UserId="9254" Text="How do I access vertex buffers corresponding to different (bottom level) acceleration structures?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42699" PostHistoryTypeId="3" PostId="13908" RevisionGUID="7053dd05-e9a9-4091-be0e-8c0f51215b32" CreationDate="2024-02-09T21:16:37.147" UserId="9254" Text="|raytracing|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42705" PostHistoryTypeId="50" PostId="13869" RevisionGUID="578bb635-93b3-4d5c-8855-cb0d8e9e8fef" CreationDate="2024-02-10T13:07:25.910" UserId="-1" />
  <row Id="42706" PostHistoryTypeId="36" PostId="13909" RevisionGUID="35769152-3806-4c34-b1d9-697fef8938bf" CreationDate="2024-02-10T18:30:18.330" UserId="-1" Comment="from https://photo.stackexchange.com/questions/133483/hugin-panorama-force-align-all-images-to-one-wide-shot-for-a-super-res-mosaic" />
  <row Id="42707" PostHistoryTypeId="2" PostId="13909" RevisionGUID="3bb62717-ec86-452e-bc6b-bff54bfc3325" CreationDate="2024-02-08T04:07:52.847" UserDisplayName="Peter" Text="Anybody have experience stitching panoramas with Hugin (or other software)?&#xD;&#xA;&#xD;&#xA;# My Situation&#xD;&#xA;&#xD;&#xA;I have one &quot;master&quot; wide shot that shows everything (horiz. FOV ≈ 105°), and a bunch of tighter-zoom images that show detail (horiz. FOV ≈ 34°). All images are 4096 x 2176 pixels.&#xD;&#xA;&#xD;&#xA;I want to stitch them all together into one super-resolution photo mosaic. The final image should show everything that's in the wide shot, but have all the detail from the tight shots.&#xD;&#xA;&#xD;&#xA;This thumbnail grouping should give you a rough idea of things (wide shot on the left):&#xD;&#xA;[![Thumbnails of all my images][1]][1]&#xD;&#xA;&#xD;&#xA;Basically I want one full-view image like the wide shot, but with the resolution of the tight shots.&#xD;&#xA;&#xD;&#xA;[![Comparing resolution between wide and tight shots][2]][2]&#xD;&#xA;&#xD;&#xA;# What's Going Wrong&#xD;&#xA;&#xD;&#xA;I've been trying to use Hugin. It wants to treat all images with equal importance, but the alignment between the tighter shots is just never perfect enough and always comes out with ugly seams.&#xD;&#xA;&#xD;&#xA;| example 1 | example 2 | example 3 |&#xD;&#xA;|---|---|---|&#xD;&#xA;|[![Seam 1][3]][3]|[![Seam 2][4]][4]|[![Seam 3][5]][5]|&#xD;&#xA;&#xD;&#xA;I know the data is there. If I could treat the wide shot as the perfect standard, and align each tight shot against it while ignoring the others, then theoretically the alignment would be perfect at least to within the resolution of the wide shot. (I don't care whether the final image is re-projected or retains the wide shot's projection, as long as it looks natural and cohesive.)&#xD;&#xA;&#xD;&#xA;# Things I've Tried&#xD;&#xA;## Weird Hugin Setup&#xD;&#xA;&#xD;&#xA;I tried removing all control points between pairs of tight shots, leaving only control points tying everything to the wide shot.&#xD;&#xA;&#xD;&#xA;This may have mildly improved things, but no matter what I can't seem to convince Hugin to treat a single image (the wide shot) as &quot;gospel truth&quot; for alignment purposes.&#xD;&#xA;&#xD;&#xA;I think maybe one of two things is wrong. Either:&#xD;&#xA;1. There's still too much cross-influence among the tight shots, or&#xD;&#xA;2. Maybe Hugin is unwilling to _arbitrarily deform_ the tight shots to match their control points to the wide shot. Maybe it's just doing a re-projection calculation, feathering the seams, and calling it a day?&#xD;&#xA;&#xD;&#xA;I'm currently thinking that I need to arbitrarily deform the tight shots for optimal adherence at all the control points, and just interpolate between them. But I don't know what software (if any) can do that.&#xD;&#xA;&#xD;&#xA;I could spend a month and write my own, but ... I have a life. &#xD;&#xA;&#xD;&#xA;## Gimp Cage Tool&#xD;&#xA;&#xD;&#xA;I'm not afraid of pain or tedium, if the end result is good. I actually tried opening all the raw images in Gimp and using its [Cage tool](https://docs.gimp.org/2.10/en/gimp-tool-cage.html), but it was so hopelessly sloppy that I gave up after &quot;aligning&quot; just one image.&#xD;&#xA;&#xD;&#xA;# Note&#xD;&#xA;&#xD;&#xA;As I'm sure you can tell, these are video game screenshots instead of real photos. There's a lot of repeating textures and areas of flat color that are messing things up a little.&#xD;&#xA;&#xD;&#xA;However, there are advantages too:&#xD;&#xA;- Perfect rotation around parallax point / no camera translation.&#xD;&#xA;- No other movement or change in the scene.&#xD;&#xA;- Perfect mathematical lens (no defects or aberration, etc.)&#xD;&#xA;&#xD;&#xA;I was really pushing my GPU getting these screenshots. I had to wait several minutes for all the scenery to load, and I was getting &lt;1 fps (especially if I turned the camera too much).&#xD;&#xA;&#xD;&#xA;All that to say, I'm not really sure if it's feasible to set my game window to 10,000 pixels and retake this as a single screenshot ... whereas I feel sure there's a way to stitch this as a mosaic.&#xD;&#xA;&#xD;&#xA;Any thoughts or help would be very much appreciated!&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zYfA3.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/XkeyY.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/0XET7.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/GMxnJ.jpg&#xD;&#xA;  [5]: https://i.stack.imgur.com/bRFc8.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42709" PostHistoryTypeId="1" PostId="13909" RevisionGUID="3bb62717-ec86-452e-bc6b-bff54bfc3325" CreationDate="2024-02-08T04:07:52.847" UserDisplayName="Peter" Text="Hugin Panorama: force-align all images to one wide shot for a super-res mosaic?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42710" PostHistoryTypeId="3" PostId="13909" RevisionGUID="3bb62717-ec86-452e-bc6b-bff54bfc3325" CreationDate="2024-02-08T04:07:52.847" UserDisplayName="Peter" Text="|untagged|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42711" PostHistoryTypeId="2" PostId="13910" RevisionGUID="e57099da-09d9-430b-9a5e-535090063816" CreationDate="2024-02-10T04:31:56.210" UserDisplayName="Peter" Text="[I posted on Pixls.us](https://discuss.pixls.us/t/hugin-panorama-force-align-all-images-to-one-wide-shot-for-a-super-res-mosaic/42008/11) and got a little help there. But I also had to get a bit creative. For more details on my process, see my thread on Pixls.us. The gist is:&#xD;&#xA;&#xD;&#xA; 1. I had to find more accurate FOV numbers for my images. This got me a little closer.&#xD;&#xA; 2. I was only leveraging part of Hugin's auto-alignment algorithm. I enabled more alignment variables before pressing &quot;optimize,&quot; and this got me 90% of the way.&#xD;&#xA; 3. For a final improvement, I ran the stitch with &quot;Keep intermediate images&quot; enabled, imported those to Blender, and performed a manual fine-tune on them using [Blender's U/V Mapping](https://docs.blender.org/manual/en/latest/modeling/meshes/uv/applying_image.html).&#xD;&#xA;&#xD;&#xA;I spent about 30 minutes in Blender on the first tight shot, and here is a before/after comparison.&#xD;&#xA;&#xD;&#xA;Each GIF switches between the wide shot and the tight shot. Bad alignment shows movement, good alignment shows no movement:&#xD;&#xA;&#xD;&#xA;| Hugin output | Blender manual alignment |&#xD;&#xA;|---|---|&#xD;&#xA;| [![Hugin output][1]][1] | [![Blender manual alignment][2]][2] |&#xD;&#xA;&#xD;&#xA;It’s possible that with a lot more tinkering I could’ve gotten results this good using only Hugin. But personally, I find Hugin to be something of a frustrating black box so my tinkering was usually blind. This process I found allows me to feel in control again.&#xD;&#xA;&#xD;&#xA;Here's what my mesh looked like in Blender. All things considered, it's not that many vertices to worry about. And it gets me exactly the results I wanted. ☺️&#xD;&#xA;&#xD;&#xA;[![Aligning with U/V Mapping][3]][3]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/zXuli.gif&#xD;&#xA;  [2]: https://i.stack.imgur.com/nRWOQ.gif&#xD;&#xA;  [3]: https://i.stack.imgur.com/bWzcn.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42713" PostHistoryTypeId="36" PostId="13910" RevisionGUID="248f40ed-7879-4862-a4b1-2aae6f856997" CreationDate="2024-02-10T18:30:18.330" UserId="-1" Comment="from https://photo.stackexchange.com/questions/133483/hugin-panorama-force-align-all-images-to-one-wide-shot-for-a-super-res-mosaic/133499#133499" />
  <row Id="42714" PostHistoryTypeId="2" PostId="13911" RevisionGUID="34c67a27-ea7d-469d-a70d-755ed84e2da3" CreationDate="2024-02-10T18:49:19.557" UserId="20471" Text="After some experimentation, I found a working code. Here we use a vector&lt;float&gt; called float_data. This vector stores the colour data input as well as output.&#xD;&#xA;&#xD;&#xA;    vector&lt;float&gt; float_data(3 * px * py);&#xD;&#xA;&#xD;&#xA;	oidn::DeviceRef dev = oidn::newDevice();&#xD;&#xA;	dev.commit();&#xD;&#xA;&#xD;&#xA;	oidn::BufferRef colorBuf = dev.newBuffer(px * py * 3 * sizeof(float));&#xD;&#xA;	colorBuf.write(0, px* py * 3 * sizeof(float), &amp;float_data[0]);&#xD;&#xA;&#xD;&#xA;	oidn::FilterRef filter = dev.newFilter(&quot;RT&quot;);&#xD;&#xA;	&#xD;&#xA;	filter.setImage(&quot;color&quot;,  colorBuf, oidn::Format::Float3, px, py);&#xD;&#xA;	filter.setImage(&quot;output&quot;, colorBuf, oidn::Format::Float3, px, py);&#xD;&#xA;	filter.set(&quot;hdr&quot;, false);&#xD;&#xA;	filter.commit();&#xD;&#xA;	filter.execute();&#xD;&#xA;&#xD;&#xA;	// Check for errors&#xD;&#xA;	const char* errorMessage;&#xD;&#xA;	if (dev.getError(errorMessage) != oidn::Error::None)&#xD;&#xA;		MessageBox(NULL, errorMessage, &quot;Error&quot;, MB_OK);&#xD;&#xA;&#xD;&#xA;	colorBuf.read(0, px * py * 3 * sizeof(float), &amp;float_data[0]);&#xD;&#xA;&#xD;&#xA;The image can be then written to disk like:&#xD;&#xA;&#xD;&#xA;	vector &lt;unsigned char&gt; uc_output_data(4 * px * py, 0);&#xD;&#xA;&#xD;&#xA;	for (size_t i = 0; i &lt; px; i++)&#xD;&#xA;	{&#xD;&#xA;		for (size_t j = 0; j &lt; py; j++)&#xD;&#xA;		{&#xD;&#xA;			size_t uc_index = 4 * (j * px + i);&#xD;&#xA;			size_t data_index = 3 * (j * px + i);&#xD;&#xA;&#xD;&#xA;			uc_output_data[uc_index + 0] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 0]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 1] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 1]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 2] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 2]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 3] = 255;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	int result = stbi_write_png(filename, px, py, 4, &amp;uc_output_data[0], 0);&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PXCxl.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42716" PostHistoryTypeId="5" PostId="13911" RevisionGUID="c56be5a5-ce90-4149-8c75-a4f7887db65c" CreationDate="2024-02-10T18:55:23.143" UserId="20471" Comment="added 500 characters in body" Text="After some experimentation, I found a working code. Here we use a vector&lt;float&gt; called float_data. This vector stores the colour data input as well as output. Here, pixel_data is a copy of the screen in RGBA 8-bits per channel.&#xD;&#xA;&#xD;&#xA;    vector&lt;float&gt; float_data(3 * px * py);&#xD;&#xA;&#xD;&#xA;	for (size_t i = 0; i &lt; px; i++)&#xD;&#xA;	{&#xD;&#xA;		for (size_t j = 0; j &lt; py; j++)&#xD;&#xA;		{&#xD;&#xA;			size_t float_index = 3 * (j * px + i);&#xD;&#xA;			size_t index = 4 * (j * px + i);&#xD;&#xA;&#xD;&#xA;			float_data[float_index + 0] = static_cast&lt;float&gt;(pixel_data[index + 0]) / 255.0f;&#xD;&#xA;			float_data[float_index + 1] = static_cast&lt;float&gt;(pixel_data[index + 1]) / 255.0f;&#xD;&#xA;			float_data[float_index + 2] = static_cast&lt;float&gt;(pixel_data[index + 2]) / 255.0f;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	oidn::DeviceRef dev = oidn::newDevice();&#xD;&#xA;	dev.commit();&#xD;&#xA;&#xD;&#xA;	oidn::BufferRef colorBuf = dev.newBuffer(px * py * 3 * sizeof(float));&#xD;&#xA;	colorBuf.write(0, px* py * 3 * sizeof(float), &amp;float_data[0]);&#xD;&#xA;&#xD;&#xA;	oidn::FilterRef filter = dev.newFilter(&quot;RT&quot;);&#xD;&#xA;	&#xD;&#xA;	filter.setImage(&quot;color&quot;,  colorBuf, oidn::Format::Float3, px, py);&#xD;&#xA;	filter.setImage(&quot;output&quot;, colorBuf, oidn::Format::Float3, px, py);&#xD;&#xA;	filter.set(&quot;hdr&quot;, false);&#xD;&#xA;	filter.commit();&#xD;&#xA;	filter.execute();&#xD;&#xA;&#xD;&#xA;	// Check for errors&#xD;&#xA;	const char* errorMessage;&#xD;&#xA;	if (dev.getError(errorMessage) != oidn::Error::None)&#xD;&#xA;		MessageBox(NULL, errorMessage, &quot;Error&quot;, MB_OK);&#xD;&#xA;&#xD;&#xA;	colorBuf.read(0, px * py * 3 * sizeof(float), &amp;float_data[0]);&#xD;&#xA;&#xD;&#xA;The image can be then written to disk like:&#xD;&#xA;&#xD;&#xA;	vector &lt;unsigned char&gt; uc_output_data(4 * px * py, 0);&#xD;&#xA;&#xD;&#xA;	for (size_t i = 0; i &lt; px; i++)&#xD;&#xA;	{&#xD;&#xA;		for (size_t j = 0; j &lt; py; j++)&#xD;&#xA;		{&#xD;&#xA;			size_t uc_index = 4 * (j * px + i);&#xD;&#xA;			size_t data_index = 3 * (j * px + i);&#xD;&#xA;&#xD;&#xA;			uc_output_data[uc_index + 0] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 0]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 1] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 1]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 2] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 2]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 3] = 255;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	int result = stbi_write_png(filename, px, py, 4, &amp;uc_output_data[0], 0);&#xD;&#xA;&#xD;&#xA;The result is:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/PXCxl.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42717" PostHistoryTypeId="5" PostId="13911" RevisionGUID="35795a68-5f07-4d54-bf74-02d07c4fd6a5" CreationDate="2024-02-10T19:03:59.347" UserId="20471" Comment="added 50 characters in body" Text="After some experimentation, I found a working code. Here we use a vector&lt;float&gt; called float_data. This vector stores the colour data input as well as output. Here, pixel_data is a copy of the screen in RGBA 8-bits per channel.&#xD;&#xA;&#xD;&#xA;    vector&lt;float&gt; float_data(3 * px * py);&#xD;&#xA;&#xD;&#xA;	for (size_t i = 0; i &lt; px; i++)&#xD;&#xA;	{&#xD;&#xA;		for (size_t j = 0; j &lt; py; j++)&#xD;&#xA;		{&#xD;&#xA;			size_t float_index = 3 * (j * px + i);&#xD;&#xA;			size_t index = 4 * (j * px + i);&#xD;&#xA;&#xD;&#xA;			float_data[float_index + 0] = static_cast&lt;float&gt;(pixel_data[index + 0]) / 255.0f;&#xD;&#xA;			float_data[float_index + 1] = static_cast&lt;float&gt;(pixel_data[index + 1]) / 255.0f;&#xD;&#xA;			float_data[float_index + 2] = static_cast&lt;float&gt;(pixel_data[index + 2]) / 255.0f;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;	oidn::DeviceRef dev = oidn::newDevice();&#xD;&#xA;	dev.commit();&#xD;&#xA;&#xD;&#xA;	oidn::BufferRef colorBuf = dev.newBuffer(px * py * 3 * sizeof(float));&#xD;&#xA;	colorBuf.write(0, px* py * 3 * sizeof(float), &amp;float_data[0]);&#xD;&#xA;&#xD;&#xA;	oidn::FilterRef filter = dev.newFilter(&quot;RT&quot;);&#xD;&#xA;	&#xD;&#xA;	filter.setImage(&quot;color&quot;,  colorBuf, oidn::Format::Float3, px, py);&#xD;&#xA;	filter.setImage(&quot;output&quot;, colorBuf, oidn::Format::Float3, px, py);&#xD;&#xA;	filter.set(&quot;hdr&quot;, false);&#xD;&#xA;	filter.commit();&#xD;&#xA;	filter.execute();&#xD;&#xA;&#xD;&#xA;	// Check for errors&#xD;&#xA;	const char* errorMessage;&#xD;&#xA;	if (dev.getError(errorMessage) != oidn::Error::None)&#xD;&#xA;		MessageBox(NULL, errorMessage, &quot;Error&quot;, MB_OK);&#xD;&#xA;&#xD;&#xA;	colorBuf.read(0, px * py * 3 * sizeof(float), &amp;float_data[0]);&#xD;&#xA;&#xD;&#xA;The image can be then written to disk like:&#xD;&#xA;&#xD;&#xA;	vector &lt;unsigned char&gt; uc_output_data(4 * px * py, 0);&#xD;&#xA;&#xD;&#xA;	for (size_t i = 0; i &lt; px; i++)&#xD;&#xA;	{&#xD;&#xA;		for (size_t j = 0; j &lt; py; j++)&#xD;&#xA;		{&#xD;&#xA;			size_t uc_index = 4 * (j * px + i);&#xD;&#xA;			size_t data_index = 3 * (j * px + i);&#xD;&#xA;&#xD;&#xA;			uc_output_data[uc_index + 0] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 0]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 1] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 1]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 2] = static_cast&lt;unsigned char&gt;(fabsf(float_data[data_index + 2]) * 255.0f);&#xD;&#xA;			uc_output_data[uc_index + 3] = 255;&#xD;&#xA;		}&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;	int result = stbi_write_png(filename, px, py, 4, &amp;uc_output_data[0], 0);&#xD;&#xA;&#xD;&#xA;The result is an image -- denoised on the left, noisy on the right, for comparison purposes:&#xD;&#xA;&#xD;&#xA;[![][1]][1]&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ffY8U.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42718" PostHistoryTypeId="2" PostId="13912" RevisionGUID="8ea1572c-9e1f-4d6d-870f-0bdbeada92ae" CreationDate="2024-02-10T23:36:27.130" UserId="21161" Text="I have a small script that does drawio automation https://github.com/GanizaniSitara/drawio_application_landscape " ContentLicense="CC BY-SA 4.0" />
  <row Id="42720" PostHistoryTypeId="5" PostId="12791" RevisionGUID="1655cecb-749b-4f6c-af9b-9d774803c605" CreationDate="2024-02-11T07:06:54.430" UserId="5256" Comment="added 53 characters in body" Text="I am following this [tutorial][1] on how to host Win32 OpenGL windows in WPF. There is also a Microsoft walkthrough on how to [Host a Win32 Control in WPF][2] that is useful aswell. The original project is from 2009 and uses managed C++ but doesn't actually render. I have rebuilt the program using the same source code (a few modifications due to debugging) using a C++ CLR Class Library. I use the compiled DLL in C# WPF however, when I run the program I get a blank window as opposed to the triangle in the tutorial.&#xD;&#xA;&#xD;&#xA;I was wondering if someone could take a look at my program and see why nothing is rendering.&#xD;&#xA;&#xD;&#xA;What the original program renders:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What I am getting:&#xD;&#xA;&#xD;&#xA;[![enter image description here][4]][4]&#xD;&#xA;&#xD;&#xA;Here is a [link][5] to the source on GitHub.&#xD;&#xA;&#xD;&#xA;OpenGLCpp.h&#xD;&#xA;&#xD;&#xA;    #pragma once&#xD;&#xA;    &#xD;&#xA;    // Exclude rarely used parts of the windows headers&#xD;&#xA;    #define WIN32_LEAN_AND_MEAN&#xD;&#xA;    &#xD;&#xA;    #include &lt;Windows.h&gt;&#xD;&#xA;    &#xD;&#xA;    #include &quot;Helper.h&quot;&#xD;&#xA;    #include &quot;OpenGL.h&quot;&#xD;&#xA;    &#xD;&#xA;    // To use these, we must add some references...&#xD;&#xA;    //	o PresentationFramework (for HwndHost)&#xD;&#xA;    //		* PresentationCore&#xD;&#xA;    //		* WindowsBase&#xD;&#xA;    using namespace System;&#xD;&#xA;    using namespace System::Windows;&#xD;&#xA;    using namespace System::Windows::Interop;&#xD;&#xA;    using namespace System::Windows::Input;&#xD;&#xA;    using namespace System::Windows::Media;&#xD;&#xA;    using namespace System::Runtime::InteropServices;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLCpp &#xD;&#xA;    {&#xD;&#xA;    	LRESULT WINAPI MyMsgProc(HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam)&#xD;&#xA;    	{&#xD;&#xA;    		switch (_msg)&#xD;&#xA;    		{&#xD;&#xA;    			// Make sure the window gets focus when it has to!&#xD;&#xA;    		case WM_IME_SETCONTEXT:&#xD;&#xA;    			// LOWORD(wParam) = 0 stands for deactivation, so don't set&#xD;&#xA;    			// focus then (results in a rather, err... 'greedy' window...)&#xD;&#xA;    			if (LOWORD(_wParam) &gt; 0)&#xD;&#xA;    				SetFocus(_hWnd);&#xD;&#xA;    &#xD;&#xA;    			return 0;&#xD;&#xA;    &#xD;&#xA;    		default:&#xD;&#xA;    			return DefWindowProc(_hWnd, _msg, _wParam, _lParam);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	//&#xD;&#xA;    	// This class implements HwndHost&#xD;&#xA;    	//&#xD;&#xA;    	// We have to overwrite BuildWindowCore and DestroyWindowCore&#xD;&#xA;    	//&#xD;&#xA;    	// A very simple example which creates a Win32 ListBox can be found in the MSDN:&#xD;&#xA;    	// http://msdn2.microsoft.com/en-us/library/aa970061.aspx&#xD;&#xA;    	//&#xD;&#xA;    	public ref class OpenGLHwnd : public HwndHost&#xD;&#xA;    	{&#xD;&#xA;    	public:&#xD;&#xA;    		OpenGLHwnd() : m_hRC(NULL),&#xD;&#xA;    			m_hDC(NULL),&#xD;&#xA;    			m_hWnd(NULL),&#xD;&#xA;    			m_hInstance(NULL),&#xD;&#xA;    			m_sWindowName(NULL),&#xD;&#xA;    			m_sClassName(NULL),&#xD;&#xA;    			m_fRotationAngle(0.0f)&#xD;&#xA;    		{&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    	private:&#xD;&#xA;    		HGLRC					m_hRC;&#xD;&#xA;    		HDC						m_hDC;&#xD;&#xA;    		HWND					m_hWnd;&#xD;&#xA;    		HINSTANCE				m_hInstance;&#xD;&#xA;    		LPCWSTR					m_sWindowName;&#xD;&#xA;    		LPCWSTR					m_sClassName;&#xD;&#xA;    &#xD;&#xA;    		float					m_fRotationAngle;&#xD;&#xA;    &#xD;&#xA;    		// DPI Scaling&#xD;&#xA;    		double					m_dScaleX;&#xD;&#xA;    		double					m_dScaleY;&#xD;&#xA;    &#xD;&#xA;    	protected:&#xD;&#xA;    		/*virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, bool% handled) override&#xD;&#xA;    		{&#xD;&#xA;    			switch( msg )&#xD;&#xA;    			{&#xD;&#xA;    				case WM_IME_SETCONTEXT:&#xD;&#xA;    					if(LOWORD(wParam.ToInt32()) &gt; 0)&#xD;&#xA;    						SetFocus(m_hWnd);&#xD;&#xA;    &#xD;&#xA;    					handled = true;&#xD;&#xA;    					return System::IntPtr::Zero;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			handled = false;&#xD;&#xA;    			return System::IntPtr::Zero;&#xD;&#xA;    		}*/&#xD;&#xA;    	public:&#xD;&#xA;    		virtual void OnRenderSizeChanged(SizeChangedInfo^ sizeInfo) override&#xD;&#xA;    		{&#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			// Apply DPI correction&#xD;&#xA;    			// NOTE: sizeInfo-&gt;NewSize contains doubles, so we do the multiplication before&#xD;&#xA;    			// converting to int.&#xD;&#xA;    			int iHeight = (int)(sizeInfo-&gt;NewSize.Height * m_dScaleY);&#xD;&#xA;    			int iWidth = (int)(sizeInfo-&gt;NewSize.Width * m_dScaleX);&#xD;&#xA;    &#xD;&#xA;    			if (iWidth == 0 || iHeight == 0)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    			glViewport(0, 0, iWidth, iHeight);&#xD;&#xA;    &#xD;&#xA;    			glMatrixMode(GL_PROJECTION);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    			glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 100.0);&#xD;&#xA;    			// gluPerspective( 67.5, ((double)(iWidth) / (double)(iHeight)), 1.0, 500.0);&#xD;&#xA;    			glMatrixMode(GL_MODELVIEW);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// Communicating with this method will be considerably more complicated in a real-&#xD;&#xA;    		// world application...&#xD;&#xA;    		//&#xD;&#xA;    		virtual void OnRender(System::Windows::Media::DrawingContext^ drawingContext) override&#xD;&#xA;    		{&#xD;&#xA;    			UNREF(drawingContext);&#xD;&#xA;    &#xD;&#xA;    			if (m_hDC == NULL || m_hRC == NULL)&#xD;&#xA;    				return;&#xD;&#xA;    &#xD;&#xA;    			wglMakeCurrent(m_hDC, m_hRC);&#xD;&#xA;    &#xD;&#xA;    			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#xD;&#xA;    			glLoadIdentity();&#xD;&#xA;    &#xD;&#xA;    			glTranslatef(0.0f, 0.0f, -2.6f);&#xD;&#xA;    			glRotatef(m_fRotationAngle, 0.0f, 1.0f, 0.0f);&#xD;&#xA;    &#xD;&#xA;    			glBegin(GL_TRIANGLES);&#xD;&#xA;    			glColor3f(1.0f, 0.0f, 0.0f);	glVertex3f(-1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 1.0f, 0.0f);	glVertex3f(0.0f, 1.0f, 0.0f);&#xD;&#xA;    			glColor3f(0.0f, 0.0f, 1.0f);	glVertex3f(1.0f, -1.0f, 0.0f);&#xD;&#xA;    			glEnd();&#xD;&#xA;    &#xD;&#xA;    			glFlush();&#xD;&#xA;    			SwapBuffers(m_hDC); // NOTE: This is no longer wglSwapBuffers&#xD;&#xA;    &#xD;&#xA;    			// For constant rotation speed, and correct rotation speeds on different machines,&#xD;&#xA;    			// we'd need a timer here. However, I don't want to bloat the example code.&#xD;&#xA;    			m_fRotationAngle += 1.0;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		virtual void DestroyWindowCore(HandleRef hwnd) override&#xD;&#xA;    		{&#xD;&#xA;    			if (NULL != m_hRC)&#xD;&#xA;    			{&#xD;&#xA;    				wglDeleteContext(m_hRC);&#xD;&#xA;    				m_hRC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; NULL != m_hDC)&#xD;&#xA;    			{&#xD;&#xA;    				ReleaseDC(m_hWnd, m_hDC);&#xD;&#xA;    				m_hDC = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if (NULL != m_hWnd &amp;&amp; m_hWnd == (HWND)hwnd.Handle.ToPointer())&#xD;&#xA;    			{&#xD;&#xA;    				::DestroyWindow(m_hWnd);&#xD;&#xA;    				m_hWnd = NULL;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			UnregisterClass(m_sClassName, m_hInstance);&#xD;&#xA;    		}&#xD;&#xA;&#xD;&#xA;            //Allowing Multiple Instances of the Window&#xD;&#xA;    		bool RegisterWindowClass()&#xD;&#xA;    		{&#xD;&#xA;    			//&#xD;&#xA;    			// Create custom WNDCLASS&#xD;&#xA;    			//&#xD;&#xA;    			WNDCLASS wndClass;&#xD;&#xA;    &#xD;&#xA;    			if (GetClassInfo(m_hInstance, m_sClassName, &amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				// Class is already registered!&#xD;&#xA;    				return true;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;&#xD;&#xA;    &#xD;&#xA;    			// Not providing a WNDPROC here results in a crash on my system:&#xD;&#xA;    			wndClass.lpfnWndProc = (WNDPROC)MyMsgProc;&#xD;&#xA;    			wndClass.cbClsExtra = 0;&#xD;&#xA;    			wndClass.cbWndExtra = 0;&#xD;&#xA;    			wndClass.hInstance = m_hInstance;&#xD;&#xA;    			wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);&#xD;&#xA;    			wndClass.hCursor = LoadCursor(0, IDC_ARROW);&#xD;&#xA;    			wndClass.hbrBackground = 0;&#xD;&#xA;    			wndClass.lpszMenuName = 0; // No menu&#xD;&#xA;    			wndClass.lpszClassName = m_sClassName;&#xD;&#xA;    &#xD;&#xA;    			// ... and register it&#xD;&#xA;    			if (!RegisterClass(&amp;wndClass))&#xD;&#xA;    			{&#xD;&#xA;    				Helper::ErrorExit(L&quot;RegisterWindowClass&quot;);&#xD;&#xA;    				return false;&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return true;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		//&#xD;&#xA;    		// This is the key method to override&#xD;&#xA;    		//&#xD;&#xA;    		virtual HandleRef BuildWindowCore(HandleRef hwndParent) override&#xD;&#xA;    		{&#xD;&#xA;    			// Get HINSTANCE&#xD;&#xA;    			m_hInstance = (HINSTANCE)GetModuleHandle(NULL);&#xD;&#xA;    			m_sWindowName = L&quot;OpenGL in HwndHost&quot;;&#xD;&#xA;    			m_sClassName = L&quot;OGLClassHwnd&quot;;&#xD;&#xA;    &#xD;&#xA;    			if (RegisterWindowClass())&#xD;&#xA;    			{&#xD;&#xA;    				// some default size&#xD;&#xA;    				int iWidth = 2;&#xD;&#xA;    				int iHeight = 2;&#xD;&#xA;    &#xD;&#xA;    				DWORD dwStyle = WS_CHILD | WS_VISIBLE;&#xD;&#xA;    &#xD;&#xA;    				// Get the parent (WPF) Hwnd. This is important: Windows won't let you create&#xD;&#xA;    				// the Hwnd otherwise.&#xD;&#xA;    				HWND parentHwnd = (HWND)hwndParent.Handle.ToPointer();&#xD;&#xA;    &#xD;&#xA;    				m_hWnd = CreateWindowEx(0,&#xD;&#xA;    					m_sClassName,&#xD;&#xA;    					m_sWindowName,&#xD;&#xA;    					dwStyle,&#xD;&#xA;    					0,	// X Pos&#xD;&#xA;    					0,	// Y Pos&#xD;&#xA;    					iWidth,&#xD;&#xA;    					iHeight,&#xD;&#xA;    					parentHwnd, // Parent&#xD;&#xA;    					0,	// Menu&#xD;&#xA;    					m_hInstance,&#xD;&#xA;    					0); // Param&#xD;&#xA;    &#xD;&#xA;    				if (!m_hWnd)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hDC = GetDC(m_hWnd);&#xD;&#xA;    				if (!m_hDC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Create PixelFormatDescriptor and choose pixel format&#xD;&#xA;    				//&#xD;&#xA;    				uint PixelFormat;&#xD;&#xA;    &#xD;&#xA;    				BYTE iAlphaBits = 0;&#xD;&#xA;    				BYTE iColorBits = 32;&#xD;&#xA;    				BYTE iDepthBits = 16;&#xD;&#xA;    				BYTE iAccumBits = 0;&#xD;&#xA;    				BYTE iStencilBits = 0;&#xD;&#xA;    &#xD;&#xA;    				static PIXELFORMATDESCRIPTOR pfd =&#xD;&#xA;    				{&#xD;&#xA;    					sizeof(PIXELFORMATDESCRIPTOR),	//size&#xD;&#xA;    					1,								//version&#xD;&#xA;    					PFD_DRAW_TO_WINDOW |				//flags&#xD;&#xA;    					PFD_SUPPORT_OPENGL |&#xD;&#xA;    					PFD_DOUBLEBUFFER,&#xD;&#xA;    					PFD_TYPE_RGBA,					//pixeltype&#xD;&#xA;    					iColorBits,&#xD;&#xA;    					0, 0, 0, 0, 0, 0,				//color bits ignored&#xD;&#xA;    					iAlphaBits,&#xD;&#xA;    					0,								//alpha shift ignored&#xD;&#xA;    					iAccumBits,						//accum. buffer&#xD;&#xA;    					0, 0, 0, 0,						//accum bits ignored&#xD;&#xA;    					iDepthBits,						//depth buffer&#xD;&#xA;    					iStencilBits,					//stencil buffer&#xD;&#xA;    					0,								//aux buffer&#xD;&#xA;    					PFD_MAIN_PLANE,					//layer type&#xD;&#xA;    					0,								//reserved&#xD;&#xA;    					0, 0, 0							//masks ignored&#xD;&#xA;    				};&#xD;&#xA;    &#xD;&#xA;    				PixelFormat = ChoosePixelFormat(m_hDC, &amp;pfd);&#xD;&#xA;    				if (!PixelFormat)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!SetPixelFormat(m_hDC, PixelFormat, &amp;pfd))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				m_hRC = wglCreateContext(m_hDC);&#xD;&#xA;    				if (!m_hRC)&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				if (!wglMakeCurrent(m_hDC, m_hRC))&#xD;&#xA;    				{&#xD;&#xA;    					Helper::ErrorExit(L&quot;BuildWindowCore&quot;);&#xD;&#xA;    				}&#xD;&#xA;    &#xD;&#xA;    				//&#xD;&#xA;    				// Get DPI information and store scaling relative to 96 DPI.&#xD;&#xA;    				// See http://msdn2.microsoft.com/en-us/library/ms969894.aspx&#xD;&#xA;    				//&#xD;&#xA;    				m_dScaleX = GetDeviceCaps(m_hDC, LOGPIXELSX) / 96.0;&#xD;&#xA;    				m_dScaleY = GetDeviceCaps(m_hDC, LOGPIXELSY) / 96.0;&#xD;&#xA;    &#xD;&#xA;    				glEnable(GL_DEPTH_TEST);&#xD;&#xA;    				glDisable(GL_TEXTURE_2D);&#xD;&#xA;    &#xD;&#xA;    				return HandleRef(this, IntPtr(m_hWnd));&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			return HandleRef(nullptr, System::IntPtr::Zero);&#xD;&#xA;    		}&#xD;&#xA;    	};&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;OpenGLHWND.xaml.cs&#xD;&#xA;&#xD;&#xA;    using System;&#xD;&#xA;    using System.Collections.Generic;&#xD;&#xA;    using System.Linq;&#xD;&#xA;    using System.Text;&#xD;&#xA;    using System.Threading.Tasks;&#xD;&#xA;    using System.Windows;&#xD;&#xA;    using System.Windows.Controls;&#xD;&#xA;    using System.Windows.Data;&#xD;&#xA;    using System.Windows.Documents;&#xD;&#xA;    using System.Windows.Input;&#xD;&#xA;    using System.Windows.Media;&#xD;&#xA;    using System.Windows.Media.Imaging;&#xD;&#xA;    using System.Windows.Shapes;&#xD;&#xA;    &#xD;&#xA;    using System.Windows.Interop; //HwndHost&#xD;&#xA;    using OpenGLCpp;&#xD;&#xA;    &#xD;&#xA;    namespace OpenGLinWPF&#xD;&#xA;    {&#xD;&#xA;        /// &lt;summary&gt;&#xD;&#xA;        /// Interaction logic for OpenGLHWND.xaml&#xD;&#xA;        /// &lt;/summary&gt;&#xD;&#xA;        public partial class OpenGLHWND : Window&#xD;&#xA;        {&#xD;&#xA;            public OpenGLHWND()&#xD;&#xA;            {&#xD;&#xA;                InitializeComponent();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private System.Windows.Threading.DispatcherTimer updateTimer = new System.Windows.Threading.DispatcherTimer();&#xD;&#xA;    &#xD;&#xA;            public override void BeginInit()&#xD;&#xA;            {&#xD;&#xA;                updateTimer.Interval = new TimeSpan(160000);&#xD;&#xA;                updateTimer.Tick += new EventHandler(updateTimer_Tick);&#xD;&#xA;                updateTimer.Start();&#xD;&#xA;                base.BeginInit();&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            protected override void OnClosing(System.ComponentModel.CancelEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                base.OnClosing(e);&#xD;&#xA;    &#xD;&#xA;                if (!e.Cancel)&#xD;&#xA;                {&#xD;&#xA;                    if (null != updateTimer)&#xD;&#xA;                    {&#xD;&#xA;                        updateTimer.Stop();&#xD;&#xA;                        updateTimer = null;&#xD;&#xA;                    }&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void updateTimer_Tick(object sender, EventArgs e)&#xD;&#xA;            {&#xD;&#xA;                if (null != hwndPlaceholder &amp;&amp;&#xD;&#xA;                    null != hwndPlaceholder.Child)&#xD;&#xA;                {&#xD;&#xA;                    hwndPlaceholder.Child.InvalidateVisual();&#xD;&#xA;                }&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;            private void Window_Loaded(object sender, RoutedEventArgs e)&#xD;&#xA;            {&#xD;&#xA;                // Create our OpenGL Hwnd 'control'...&#xD;&#xA;                HwndHost host = new OpenGLCpp.OpenGLHwnd(); &#xD;&#xA;    &#xD;&#xA;                // ... and attach it to the placeholder control:&#xD;&#xA;                hwndPlaceholder.Child = host;&#xD;&#xA;            }&#xD;&#xA;    &#xD;&#xA;        }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://www.codeproject.com/Articles/23736/Creating-OpenGL-Windows-in-WPF&#xD;&#xA;  [2]: https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-hosting-a-win32-control-in-wpf?view=netframeworkdesktop-4.8&#xD;&#xA;  [3]: https://i.stack.imgur.com/FAd3o.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/tp3tP.png&#xD;&#xA;  [5]: https://github.com/arjansingh00/OpenGLinWPF" ContentLicense="CC BY-SA 4.0" />
  <row Id="42721" PostHistoryTypeId="2" PostId="13913" RevisionGUID="dec1646f-b2ea-4cc2-aa84-533281e12cc1" CreationDate="2024-02-11T20:41:30.917" UserId="20471" Text="Using Vulkan, I am reading from an image to a vector of unsigned char. It works great.&#xD;&#xA;&#xD;&#xA;    vkCmdTraceRaysKHR(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	&amp;shaderBindingTables.raygen.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;shaderBindingTables.miss.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;shaderBindingTables.hit.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;emptySbtEntry,&#xD;&#xA;    	size_x,&#xD;&#xA;    	size_y,&#xD;&#xA;    	1);&#xD;&#xA;    &#xD;&#xA;    vks::tools::setImageLayout(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_GENERAL,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,&#xD;&#xA;    	subresourceRange);&#xD;&#xA;    &#xD;&#xA;    VkBufferImageCopy copyRegion{};&#xD;&#xA;    copyRegion.bufferOffset = 0;&#xD;&#xA;    copyRegion.bufferRowLength = 0;&#xD;&#xA;    copyRegion.bufferImageHeight = 0;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;    copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;    copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;    copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;    copyRegion.imageExtent.width = size_x;&#xD;&#xA;    copyRegion.imageExtent.height = size_y;&#xD;&#xA;    copyRegion.imageExtent.depth = 1;&#xD;&#xA;    &#xD;&#xA;    vkCmdCopyImageToBuffer(screenshotCmdBuffer, screenshotStorageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, screenshotStagingBuffer.buffer, 1, &amp;copyRegion);&#xD;&#xA;    &#xD;&#xA;    VkBufferMemoryBarrier barrier = {};&#xD;&#xA;    barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;&#xD;&#xA;    barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;    barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;    barrier.buffer = screenshotStagingBuffer.buffer;&#xD;&#xA;    barrier.size = screenshotStagingBuffer.size;&#xD;&#xA;    &#xD;&#xA;    vkCmdPipelineBarrier(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;    	0,&#xD;&#xA;    	0, nullptr,&#xD;&#xA;    	1, &amp;barrier,&#xD;&#xA;    	0, nullptr&#xD;&#xA;    );&#xD;&#xA;    &#xD;&#xA;    vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;    &#xD;&#xA;    memcpy(&amp;fbpixels[0], screenshotStagingBuffer.mapped, size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How would I go about writing from a vector of unsigned char to an image?&#xD;&#xA;&#xD;&#xA;This is a code that I've been trying, but it does not work:&#xD;&#xA;&#xD;&#xA;    memcpy(screenshotStagingBuffer.mapped, &amp;uc_output_data[0], size);&#xD;&#xA;    &#xD;&#xA;    VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };&#xD;&#xA;    &#xD;&#xA;    vks::tools::setImageLayout(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_GENERAL,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;    	subresourceRange);&#xD;&#xA;    &#xD;&#xA;    VkBufferImageCopy copyRegion{};&#xD;&#xA;    copyRegion.bufferOffset = 0;&#xD;&#xA;    copyRegion.bufferRowLength = 0;&#xD;&#xA;    copyRegion.bufferImageHeight = 0;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;    copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;    copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;    copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;    copyRegion.imageExtent.width = size_x;&#xD;&#xA;    copyRegion.imageExtent.height = size_y;&#xD;&#xA;    copyRegion.imageExtent.depth = 1;&#xD;&#xA;    &#xD;&#xA;    vkCmdCopyBufferToImage(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStagingBuffer.buffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;    	1,&#xD;&#xA;    	&amp;copyRegion);&#xD;&#xA;    &#xD;&#xA;    VkBufferMemoryBarrier barrier = {};&#xD;&#xA;    barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;&#xD;&#xA;    barrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;    barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;    barrier.buffer = screenshotStagingBuffer.buffer;&#xD;&#xA;    barrier.size = screenshotStagingBuffer.size;&#xD;&#xA;    &#xD;&#xA;    vkCmdPipelineBarrier(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;    	VK_PIPELINE_STAGE_TRANSFER_BIT,&#xD;&#xA;    	0,&#xD;&#xA;    	0, nullptr,&#xD;&#xA;    	1, &amp;barrier,&#xD;&#xA;    	0, nullptr);&#xD;&#xA;    &#xD;&#xA;    vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;&#xD;&#xA;I am in the middle of enabling the validation layers.&#xD;&#xA;&#xD;&#xA;Any help is much appreciated." ContentLicense="CC BY-SA 4.0" />
  <row Id="42723" PostHistoryTypeId="1" PostId="13913" RevisionGUID="dec1646f-b2ea-4cc2-aa84-533281e12cc1" CreationDate="2024-02-11T20:41:30.917" UserId="20471" Text="Vulkan memcpy from image works, but memcpy to image not working" ContentLicense="CC BY-SA 4.0" />
  <row Id="42724" PostHistoryTypeId="3" PostId="13913" RevisionGUID="dec1646f-b2ea-4cc2-aa84-533281e12cc1" CreationDate="2024-02-11T20:41:30.917" UserId="20471" Text="|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42725" PostHistoryTypeId="5" PostId="13913" RevisionGUID="e0192195-56b8-4aca-8a86-308791c23b3d" CreationDate="2024-02-11T22:04:29.650" UserId="20471" Comment="added 6638 characters in body" Text="Using Vulkan, I am reading from an image to a vector of unsigned char. It works great.&#xD;&#xA;&#xD;&#xA;    vkCmdTraceRaysKHR(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	&amp;shaderBindingTables.raygen.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;shaderBindingTables.miss.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;shaderBindingTables.hit.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;emptySbtEntry,&#xD;&#xA;    	size_x,&#xD;&#xA;    	size_y,&#xD;&#xA;    	1);&#xD;&#xA;    &#xD;&#xA;    vks::tools::setImageLayout(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_GENERAL,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,&#xD;&#xA;    	subresourceRange);&#xD;&#xA;    &#xD;&#xA;    VkBufferImageCopy copyRegion{};&#xD;&#xA;    copyRegion.bufferOffset = 0;&#xD;&#xA;    copyRegion.bufferRowLength = 0;&#xD;&#xA;    copyRegion.bufferImageHeight = 0;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;    copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;    copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;    copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;    copyRegion.imageExtent.width = size_x;&#xD;&#xA;    copyRegion.imageExtent.height = size_y;&#xD;&#xA;    copyRegion.imageExtent.depth = 1;&#xD;&#xA;    &#xD;&#xA;    vkCmdCopyImageToBuffer(screenshotCmdBuffer, screenshotStorageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, screenshotStagingBuffer.buffer, 1, &amp;copyRegion);&#xD;&#xA;    &#xD;&#xA;    VkBufferMemoryBarrier barrier = {};&#xD;&#xA;    barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;&#xD;&#xA;    barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;    barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;    barrier.buffer = screenshotStagingBuffer.buffer;&#xD;&#xA;    barrier.size = screenshotStagingBuffer.size;&#xD;&#xA;    &#xD;&#xA;    vkCmdPipelineBarrier(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;    	0,&#xD;&#xA;    	0, nullptr,&#xD;&#xA;    	1, &amp;barrier,&#xD;&#xA;    	0, nullptr&#xD;&#xA;    );&#xD;&#xA;    &#xD;&#xA;    vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;    &#xD;&#xA;    memcpy(&amp;fbpixels[0], screenshotStagingBuffer.mapped, size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How would I go about writing from a vector of unsigned char to an image?&#xD;&#xA;&#xD;&#xA;This is a code that I've been trying, but it does not work:&#xD;&#xA;&#xD;&#xA;    memcpy(screenshotStagingBuffer.mapped, &amp;uc_output_data[0], size);&#xD;&#xA;    &#xD;&#xA;    VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };&#xD;&#xA;    &#xD;&#xA;    vks::tools::setImageLayout(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_GENERAL,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;    	subresourceRange);&#xD;&#xA;    &#xD;&#xA;    VkBufferImageCopy copyRegion{};&#xD;&#xA;    copyRegion.bufferOffset = 0;&#xD;&#xA;    copyRegion.bufferRowLength = 0;&#xD;&#xA;    copyRegion.bufferImageHeight = 0;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;    copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;    copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;    copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;    copyRegion.imageExtent.width = size_x;&#xD;&#xA;    copyRegion.imageExtent.height = size_y;&#xD;&#xA;    copyRegion.imageExtent.depth = 1;&#xD;&#xA;    &#xD;&#xA;    vkCmdCopyBufferToImage(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStagingBuffer.buffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;    	1,&#xD;&#xA;    	&amp;copyRegion);&#xD;&#xA;    &#xD;&#xA;    VkBufferMemoryBarrier barrier = {};&#xD;&#xA;    barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;&#xD;&#xA;    barrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;    barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;    barrier.buffer = screenshotStagingBuffer.buffer;&#xD;&#xA;    barrier.size = screenshotStagingBuffer.size;&#xD;&#xA;    &#xD;&#xA;    vkCmdPipelineBarrier(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;    	VK_PIPELINE_STAGE_TRANSFER_BIT,&#xD;&#xA;    	0,&#xD;&#xA;    	0, nullptr,&#xD;&#xA;    	1, &amp;barrier,&#xD;&#xA;    	0, nullptr);&#xD;&#xA;    &#xD;&#xA;    vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;&#xD;&#xA;The validation layers says that:&#xD;&#xA;&#xD;&#xA;    ERROR: [1458672316][VUID-VkSamplerCreateInfo-anisotropyEnable-01070] : Validation Error: [ VUID-VkSamplerCreateInfo-anisotropyEnable-01070 ] | MessageID = 0x56f192bc | vkCreateSampler(): Anisotropic sampling feature is not enabled, pCreateInfo-&gt;anisotropyEnable must be VK_FALSE. The Vulkan spec states: If the samplerAnisotropy feature is not enabled, anisotropyEnable must be VK_FALSE (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)&#xD;&#xA;    &#xD;&#xA;    ERROR: [1458672316][VUID-VkSamplerCreateInfo-anisotropyEnable-01070] : Validation Error: [ VUID-VkSamplerCreateInfo-anisotropyEnable-01070 ] | MessageID = 0x56f192bc | vkCreateSampler(): Anisotropic sampling feature is not enabled, pCreateInfo-&gt;anisotropyEnable must be VK_FALSE. The Vulkan spec states: If the samplerAnisotropy feature is not enabled, anisotropyEnable must be VK_FALSE (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [1132206547][VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849] : Validation Error: [ VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 ] | MessageID = 0x437c19d3 | vkCreateRayTracingPipelinesKHR(): pCreateInfos[0] After specialization was applied, VkShaderModule 0x5011aa0000000066[] does not contain valid spirv for stage VK_SHADER_STAGE_RAYGEN_BIT_KHR. The Vulkan spec states: If a shader module identifier is not specified, the shader code used by the pipeline must be valid as described by the Khronos SPIR-V Specification after applying the specializations provided in pSpecializationInfo, if any, and then converting all specialization constants into fixed constants (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849)&#xD;&#xA;    &#xD;&#xA;    ERROR: [-507995293][VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358] : Validation Error: [ VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358 ] Object 0: handle = 0x612f93000000004e, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0xe1b89b63 | vkCmdBindDescriptorSets(): descriptorSet #1 being bound is not compatible with overlapping descriptorSetLayout at index 1 of VkPipelineLayout 0x5dbcf90000000065[] due to: Binding 0 for VkDescriptorSetLayout 0x9f58380000000064[] from pipeline layout has stageFlags VK_SHADER_STAGE_RAYGEN_BIT_KHR|VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR but binding 0 for VkDescriptorSetLayout 0x73a850000000004d[], which is bound, has stageFlags VK_SHADER_STAGE_FRAGMENT_BIT. The Vulkan spec states: Each element of pDescriptorSets must have been allocated with a VkDescriptorSetLayout that matches (is the same as, or identically defined as) the VkDescriptorSetLayout at set n in layout, where n is the sum of firstSet and the index into pDescriptorSets (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358)&#xD;&#xA;    &#xD;&#xA;    ERROR: [387543851][VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189] : Validation Error: [ VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189 ] Object 0: handle = 0x1f51f40a150, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x421a0f0000000074, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x1719732b | vkCmdCopyImageToBuffer: Cannot use VkImage 0x421a0f0000000074[] (layer=0 mip=0) with specific layout VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL that doesn't match the previous known layout VK_IMAGE_LAYOUT_GENERAL. The Vulkan spec states: srcImageLayout must specify the layout of the image subresources of srcImage specified in pRegions at the time this command is executed on a VkDevice (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189)&#xD;&#xA;    &#xD;&#xA;    ERROR: [455308668][VUID-vkCmdPipelineBarrier-commandBuffer-parameter] : Validation Error: [ VUID-vkCmdPipelineBarrier-commandBuffer-parameter ] Object 0: handle = 0x1f50c70d820, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x1b23757c | vkCmdPipelineBarrier(): Invalid VkCommandBuffer Object 0x1f51f40a150. The Vulkan spec states: commandBuffer must be a valid VkCommandBuffer handle (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdPipelineBarrier-commandBuffer-parameter)&#xD;&#xA;&#xD;&#xA;Any help is much appreciated.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42726" PostHistoryTypeId="5" PostId="13913" RevisionGUID="ce382e20-61e4-49f5-82e0-ad3cef39f76a" CreationDate="2024-02-12T01:38:56.037" UserId="20471" Comment="added 81 characters in body" Text="Using Vulkan, I am reading from an image to a vector of unsigned char. It works great.&#xD;&#xA;&#xD;&#xA;    vkCmdTraceRaysKHR(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	&amp;shaderBindingTables.raygen.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;shaderBindingTables.miss.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;shaderBindingTables.hit.stridedDeviceAddressRegion,&#xD;&#xA;    	&amp;emptySbtEntry,&#xD;&#xA;    	size_x,&#xD;&#xA;    	size_y,&#xD;&#xA;    	1);&#xD;&#xA;    &#xD;&#xA;    vks::tools::setImageLayout(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_GENERAL,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,&#xD;&#xA;    	subresourceRange);&#xD;&#xA;    &#xD;&#xA;    VkBufferImageCopy copyRegion{};&#xD;&#xA;    copyRegion.bufferOffset = 0;&#xD;&#xA;    copyRegion.bufferRowLength = 0;&#xD;&#xA;    copyRegion.bufferImageHeight = 0;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;    copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;    copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;    copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;    copyRegion.imageExtent.width = size_x;&#xD;&#xA;    copyRegion.imageExtent.height = size_y;&#xD;&#xA;    copyRegion.imageExtent.depth = 1;&#xD;&#xA;    &#xD;&#xA;    vkCmdCopyImageToBuffer(screenshotCmdBuffer, screenshotStorageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, screenshotStagingBuffer.buffer, 1, &amp;copyRegion);&#xD;&#xA;    &#xD;&#xA;    VkBufferMemoryBarrier barrier = {};&#xD;&#xA;    barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;&#xD;&#xA;    barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;    barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;    barrier.buffer = screenshotStagingBuffer.buffer;&#xD;&#xA;    barrier.size = screenshotStagingBuffer.size;&#xD;&#xA;    &#xD;&#xA;    vkCmdPipelineBarrier(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;    	0,&#xD;&#xA;    	0, nullptr,&#xD;&#xA;    	1, &amp;barrier,&#xD;&#xA;    	0, nullptr&#xD;&#xA;    );&#xD;&#xA;    &#xD;&#xA;    vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;    &#xD;&#xA;    memcpy(&amp;fbpixels[0], screenshotStagingBuffer.mapped, size);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;How would I go about writing from a vector of unsigned char to an image?&#xD;&#xA;&#xD;&#xA;This is a code that I've been trying, but it does not work:&#xD;&#xA;&#xD;&#xA;    memcpy(screenshotStagingBuffer.mapped, &amp;uc_output_data[0], size);&#xD;&#xA;    &#xD;&#xA;    VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };&#xD;&#xA;    &#xD;&#xA;    vks::tools::setImageLayout(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_GENERAL,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;    	subresourceRange);&#xD;&#xA;    &#xD;&#xA;    VkBufferImageCopy copyRegion{};&#xD;&#xA;    copyRegion.bufferOffset = 0;&#xD;&#xA;    copyRegion.bufferRowLength = 0;&#xD;&#xA;    copyRegion.bufferImageHeight = 0;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;    copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;    copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;    copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;    &#xD;&#xA;    copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;    copyRegion.imageExtent.width = size_x;&#xD;&#xA;    copyRegion.imageExtent.height = size_y;&#xD;&#xA;    copyRegion.imageExtent.depth = 1;&#xD;&#xA;    &#xD;&#xA;    vkCmdCopyBufferToImage(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	screenshotStagingBuffer.buffer,&#xD;&#xA;    	screenshotStorageImage.image,&#xD;&#xA;    	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;    	1,&#xD;&#xA;    	&amp;copyRegion);&#xD;&#xA;    &#xD;&#xA;    VkBufferMemoryBarrier barrier = {};&#xD;&#xA;    barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;&#xD;&#xA;    barrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;    barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;    barrier.buffer = screenshotStagingBuffer.buffer;&#xD;&#xA;    barrier.size = screenshotStagingBuffer.size;&#xD;&#xA;    &#xD;&#xA;    vkCmdPipelineBarrier(&#xD;&#xA;    	screenshotCmdBuffer,&#xD;&#xA;    	VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;    	VK_PIPELINE_STAGE_TRANSFER_BIT,&#xD;&#xA;    	0,&#xD;&#xA;    	0, nullptr,&#xD;&#xA;    	1, &amp;barrier,&#xD;&#xA;    	0, nullptr);&#xD;&#xA;    &#xD;&#xA;    vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;&#xD;&#xA;Should I be using an image memory barrier instead of a buffer memory barrier?&#xD;&#xA;&#xD;&#xA;The validation layers says that:&#xD;&#xA;&#xD;&#xA;    ERROR: [1458672316][VUID-VkSamplerCreateInfo-anisotropyEnable-01070] : Validation Error: [ VUID-VkSamplerCreateInfo-anisotropyEnable-01070 ] | MessageID = 0x56f192bc | vkCreateSampler(): Anisotropic sampling feature is not enabled, pCreateInfo-&gt;anisotropyEnable must be VK_FALSE. The Vulkan spec states: If the samplerAnisotropy feature is not enabled, anisotropyEnable must be VK_FALSE (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)&#xD;&#xA;    &#xD;&#xA;    ERROR: [1458672316][VUID-VkSamplerCreateInfo-anisotropyEnable-01070] : Validation Error: [ VUID-VkSamplerCreateInfo-anisotropyEnable-01070 ] | MessageID = 0x56f192bc | vkCreateSampler(): Anisotropic sampling feature is not enabled, pCreateInfo-&gt;anisotropyEnable must be VK_FALSE. The Vulkan spec states: If the samplerAnisotropy feature is not enabled, anisotropyEnable must be VK_FALSE (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)&#xD;&#xA;    &#xD;&#xA;    ERROR: [1132206547][VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849] : Validation Error: [ VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 ] | MessageID = 0x437c19d3 | vkCreateRayTracingPipelinesKHR(): pCreateInfos[0] After specialization was applied, VkShaderModule 0x5011aa0000000066[] does not contain valid spirv for stage VK_SHADER_STAGE_RAYGEN_BIT_KHR. The Vulkan spec states: If a shader module identifier is not specified, the shader code used by the pipeline must be valid as described by the Khronos SPIR-V Specification after applying the specializations provided in pSpecializationInfo, if any, and then converting all specialization constants into fixed constants (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849)&#xD;&#xA;    &#xD;&#xA;    ERROR: [-507995293][VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358] : Validation Error: [ VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358 ] Object 0: handle = 0x612f93000000004e, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0xe1b89b63 | vkCmdBindDescriptorSets(): descriptorSet #1 being bound is not compatible with overlapping descriptorSetLayout at index 1 of VkPipelineLayout 0x5dbcf90000000065[] due to: Binding 0 for VkDescriptorSetLayout 0x9f58380000000064[] from pipeline layout has stageFlags VK_SHADER_STAGE_RAYGEN_BIT_KHR|VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR but binding 0 for VkDescriptorSetLayout 0x73a850000000004d[], which is bound, has stageFlags VK_SHADER_STAGE_FRAGMENT_BIT. The Vulkan spec states: Each element of pDescriptorSets must have been allocated with a VkDescriptorSetLayout that matches (is the same as, or identically defined as) the VkDescriptorSetLayout at set n in layout, where n is the sum of firstSet and the index into pDescriptorSets (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358)&#xD;&#xA;    &#xD;&#xA;    ERROR: [387543851][VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189] : Validation Error: [ VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189 ] Object 0: handle = 0x1f51f40a150, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x421a0f0000000074, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x1719732b | vkCmdCopyImageToBuffer: Cannot use VkImage 0x421a0f0000000074[] (layer=0 mip=0) with specific layout VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL that doesn't match the previous known layout VK_IMAGE_LAYOUT_GENERAL. The Vulkan spec states: srcImageLayout must specify the layout of the image subresources of srcImage specified in pRegions at the time this command is executed on a VkDevice (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189)&#xD;&#xA;    &#xD;&#xA;    ERROR: [455308668][VUID-vkCmdPipelineBarrier-commandBuffer-parameter] : Validation Error: [ VUID-vkCmdPipelineBarrier-commandBuffer-parameter ] Object 0: handle = 0x1f50c70d820, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x1b23757c | vkCmdPipelineBarrier(): Invalid VkCommandBuffer Object 0x1f51f40a150. The Vulkan spec states: commandBuffer must be a valid VkCommandBuffer handle (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdPipelineBarrier-commandBuffer-parameter)&#xD;&#xA;&#xD;&#xA;Any help is much appreciated.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42731" PostHistoryTypeId="2" PostId="13914" RevisionGUID="b536fdca-f75f-4c4e-8d6c-415acafeeffd" CreationDate="2024-02-12T18:58:45.480" UserId="20471" Text="I was not creating a command buffer properly. I added one line pertaining to the screenshot command buffer, and it all works now, using an image memory barrier:&#xD;&#xA;&#xD;&#xA;	if (num_cams_wide == 1)&#xD;&#xA;	{&#xD;&#xA;		// This is the line that I added to make it all work...&#xD;&#xA;		VkCommandBuffer screenshotCmdBuffer = vulkanDevice-&gt;createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);&#xD;&#xA;&#xD;&#xA;		memcpy(screenshotStagingBuffer.mapped, &amp;uc_output_data[0], size);&#xD;&#xA;&#xD;&#xA;		VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };&#xD;&#xA;&#xD;&#xA;		vks::tools::setImageLayout(&#xD;&#xA;			screenshotCmdBuffer,&#xD;&#xA;			screenshotStorageImage.image,&#xD;&#xA;			VK_IMAGE_LAYOUT_UNDEFINED,&#xD;&#xA;			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;			subresourceRange);&#xD;&#xA;&#xD;&#xA;		VkBufferImageCopy copyRegion{};&#xD;&#xA;		copyRegion.bufferOffset = 0;&#xD;&#xA;		copyRegion.bufferRowLength = 0;&#xD;&#xA;		copyRegion.bufferImageHeight = 0;&#xD;&#xA;		copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;&#xD;&#xA;		copyRegion.imageSubresource.mipLevel = 0;&#xD;&#xA;		copyRegion.imageSubresource.baseArrayLayer = 0;&#xD;&#xA;		copyRegion.imageSubresource.layerCount = 1;&#xD;&#xA;		copyRegion.imageOffset = { 0, 0, 0 };&#xD;&#xA;		copyRegion.imageExtent.width = size_x;&#xD;&#xA;		copyRegion.imageExtent.height = size_y;&#xD;&#xA;		copyRegion.imageExtent.depth = 1;&#xD;&#xA;&#xD;&#xA;		VkImageMemoryBarrier imageMemoryBarrier;&#xD;&#xA;		imageMemoryBarrier.image = screenshotStorageImage.image;&#xD;&#xA;		imageMemoryBarrier.subresourceRange = subresourceRange;&#xD;&#xA;		imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT;&#xD;&#xA;		imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;&#xD;&#xA;		imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;&#xD;&#xA;		imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;&#xD;&#xA;		imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;&#xD;&#xA;&#xD;&#xA;		vkCmdCopyBufferToImage(&#xD;&#xA;			screenshotCmdBuffer,&#xD;&#xA;			screenshotStagingBuffer.buffer,&#xD;&#xA;			screenshotStorageImage.image,&#xD;&#xA;			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,&#xD;&#xA;			1,&#xD;&#xA;			&amp;copyRegion);&#xD;&#xA;&#xD;&#xA;		vkCmdPipelineBarrier(&#xD;&#xA;			screenshotCmdBuffer,&#xD;&#xA;			VK_PIPELINE_STAGE_HOST_BIT,&#xD;&#xA;			VK_PIPELINE_STAGE_TRANSFER_BIT,&#xD;&#xA;			0,&#xD;&#xA;			0, nullptr,&#xD;&#xA;			0, nullptr,&#xD;&#xA;			1, &amp;imageMemoryBarrier);&#xD;&#xA;&#xD;&#xA;		vulkanDevice-&gt;flushCommandBuffer(screenshotCmdBuffer, queue);&#xD;&#xA;	}&#xD;&#xA;&#xD;&#xA;The results are a denoised on screen image:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JvDIv.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42733" PostHistoryTypeId="50" PostId="8888" RevisionGUID="f34b1b69-8875-489e-9844-6257dd4e5c11" CreationDate="2024-02-12T20:04:05.463" UserId="-1" />
  <row Id="42734" PostHistoryTypeId="2" PostId="13915" RevisionGUID="026f0758-aed5-466b-9aa9-ae8628336b2a" CreationDate="2024-02-13T03:32:15.960" UserId="20726" Text="I want to learn graphics on a lower level but I have no clue where to start. &#xD;&#xA;&#xD;&#xA;I know that I will need some hard mathematics (linear algebra, vectors, matrices, transformations...) rooted inside my head. Would it be a viable and better pathway to pursue a degree in mathematics rather than one in computer science ? and try to somehow combine this with the rendering programming part (c++, shaders, geometry, pixels, frame buffers, image processing...) ?&#xD;&#xA;&#xD;&#xA;I wanted to learn how to generate the data to draw using algorithms without accessing a video card or API. I think you also need to learn some assembly for this ?&#xD;&#xA;&#xD;&#xA;Basically, I want to learn the specific math and algorithms for Computer Graphics and start from these foundations. Which degree would be a better option to start a career in Computer Graphics ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="42736" PostHistoryTypeId="1" PostId="13915" RevisionGUID="026f0758-aed5-466b-9aa9-ae8628336b2a" CreationDate="2024-02-13T03:32:15.960" UserId="20726" Text="Degree for Computer Graphics : Computer Science or Mathematics?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42737" PostHistoryTypeId="3" PostId="13915" RevisionGUID="026f0758-aed5-466b-9aa9-ae8628336b2a" CreationDate="2024-02-13T03:32:15.960" UserId="20726" Text="|mathematics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42738" PostHistoryTypeId="5" PostId="13915" RevisionGUID="f47e1cdd-862b-401a-b2d5-a99931c64511" CreationDate="2024-02-13T03:38:04.497" UserId="20726" Comment="added 4 characters in body" Text="I want to learn graphics on a lower level but I have no clue where to start. &#xD;&#xA;&#xD;&#xA;I know that I will need some hard mathematics (linear algebra, vectors, matrices, transformations...) rooted inside my head. Would it be a viable and better pathway to pursue a degree in mathematics rather than one in computer science ? ... and try to somehow combine this with the rendering programming part (c++, shaders, geometry, pixels, frame buffers, image processing...) ?&#xD;&#xA;&#xD;&#xA;I wanted to learn how to generate the data to draw using algorithms without accessing a video card or API. I think you also need to learn some assembly for this ?&#xD;&#xA;&#xD;&#xA;Basically, I want to learn the specific math and algorithms for Computer Graphics and start from these foundations. Which degree would be a better option to start a career in Computer Graphics ? " ContentLicense="CC BY-SA 4.0" />
  <row Id="42739" PostHistoryTypeId="5" PostId="13915" RevisionGUID="be990265-af20-4347-b3e8-d8429b95520d" CreationDate="2024-02-13T03:44:35.077" UserId="20726" Comment="added 13 characters in body" Text="I want to learn graphics on a lower level but I have no clue where to start. &#xD;&#xA;&#xD;&#xA;I know that I will need some hard mathematics (linear algebra, vectors, matrices, transformations...) rooted inside my head. Would it be a viable and better pathway to pursue a degree in mathematics rather than one in computer science ? ... and try to somehow combine this with the rendering programming part (c++, shaders, geometry, pixels, frame buffers, image processing...) ?&#xD;&#xA;&#xD;&#xA;I wanted to learn how to generate the data to draw using algorithms without accessing a video card or API. I think you also need to learn some assembly for this ?&#xD;&#xA;&#xD;&#xA;Basically, I want to learn the specific math and algorithms for Computer Graphics and start from these foundations. &#xD;&#xA;&#xD;&#xA;Would a degree in mathematics be seen as a risky option to try and enter this industry ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42740" PostHistoryTypeId="5" PostId="13915" RevisionGUID="39d7047a-9374-4959-9673-a2ee77467fa3" CreationDate="2024-02-13T03:45:36.487" UserId="20726" Comment="added 10 characters in body" Text="I want to learn graphics on a lower level but I have no clue where to start. &#xD;&#xA;&#xD;&#xA;I know that I will need some hard mathematics (linear algebra, vectors, matrices, transformations...) rooted inside my head. Would it be a viable and better pathway to pursue a degree in mathematics rather than one in computer science ? ... and try to somehow combine this knowledge with the rendering programming part (c++, shaders, geometry, pixels, frame buffers, image processing...) ?&#xD;&#xA;&#xD;&#xA;I wanted to learn how to generate the data to draw using algorithms without accessing a video card or API. I think you also need to learn some assembly for this ?&#xD;&#xA;&#xD;&#xA;Basically, I want to learn the specific math and algorithms for Computer Graphics and start from these foundations. &#xD;&#xA;&#xD;&#xA;Would a degree in mathematics be seen as a risky option to try and enter this industry ?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42741" PostHistoryTypeId="2" PostId="13916" RevisionGUID="2abe13f1-1417-4ece-98f9-601e9b98da08" CreationDate="2024-02-13T12:00:54.557" UserId="10096" Text="I studied computer science with an emphasis on mathematics for my bachelor degree and computer science with an emphasis in computer graphics, signal processing, numerics for my masters. Most of the core computer science courses (automata, compilers, algorithms and data structures, databases, software engineering, etc.) are entirely irrelevant to anything computer graphics and signal processing related. &#xD;&#xA;&#xD;&#xA;What is used in computer graphics is a very specific subset of mathematics and bits and pieces of physics, so also my pure math courses were useless for that. You would likely be better served by an applied mathematics or physics degree, but to be honest one doesn't require a degree to do computer graphics.&#xD;&#xA;&#xD;&#xA;If you don't care about APIs I would suggest starting with: ray-tracing in one weekend to familiarise yourself with ray-tracing and maybe https://github.com/ssloy/tinyrenderer to familiarise yourself with software rendering. After ray-tracing in one weekend you can go through the other two books and then jump onto Veach and pbrt. After the software renderer I mentioned, or along with it, you could try to learn an api, e.g. https://learnopengl.com/&#xD;&#xA;&#xD;&#xA;As far as the CG industry goes - unless you meant academia or R&amp;D, then the amount of mathematics involved is much more limited than what you would find in Veach and even pbrt." ContentLicense="CC BY-SA 4.0" />
  <row Id="42743" PostHistoryTypeId="2" PostId="13917" RevisionGUID="b3e1c737-fb5e-4a18-b04c-256f97613c21" CreationDate="2024-02-14T00:27:06.637" UserId="9438" Text="As someone who has a degree in &quot;Computer Graphics and Mathematical Modelling&quot; and worked as a CAD/CAM developer for over 17 years. I would say 100% you want a degree in computer science rather than mathematics if you want to pursue it as a career. &#xD;&#xA;&#xD;&#xA;Mainly...&#xD;&#xA;&#xD;&#xA;* You need to know how to program, and beyond basic algorithms/problem solving. Actual hands on experience with a language used in industry. Doing a maths degree, you may go over some basics about program flow and algorithms etc, and you may do some basic programs in something like C (if you're lucky, although it may probably be something like matlab). But you will probably not go into certain concepts like OO, memory, linking, architecture etc, all of which are important in programming no matter which CS path you go down, or even use said programming language as much as you would with CS.&#xD;&#xA;&#xD;&#xA;* There are many concepts and processes you will need to understand and use in the industry (source control, compilers, optimisations) which you will not learn with a maths degree.&#xD;&#xA;&#xD;&#xA;* A computer science degree will no doubt be modular, and I highly suspect there will be modules specifically for computer graphics. This is very unlikely during a maths degree.&#xD;&#xA;&#xD;&#xA;* Modules in computer graphics will teach you many of the applicable fundamental concepts of computer graphics as well as exposing you to actual modern day graphics programming. There are many things we used to do in the fields of computer graphics which are just not done or needed these days (software rendering, rasterisers etc), but having the skill set you get from programming/CS degree, you will find it a lot easier to do these yourself to satisfy your own curiosity.&#xD;&#xA;&#xD;&#xA;* When you apply for your first job in industry, not having exposure to computing may put you at a disadvantage against other candidates who do (although having a maths a degree will have other advantages... see below).&#xD;&#xA;&#xD;&#xA;* While yes there is overlap, overall a mathematics degree will give you more theoretical skills but also give you more irrelevant knowledge in some quite complex fields of mathematics which will not ever be applicable in computing or specifically computer graphics.&#xD;&#xA;&#xD;&#xA;A degree in mathematics is hard, harder than computer science, but it certainly says a lot about your capability to any future employer. It would carry a lot of prestige when looking for a career in computer graphics/software, and any interviewer/employer worth their salt would understand that you would probably be more than capable in the role with a maths degree. However, it also suggests limited exposure to fundamental concepts and processes in the software development world, and thus longer prep time to get you functioning efficiently. Problem solving and understanding concepts is just a part of professional software development, deadlines are a real thing and pressure is a real thing. You need a lot of discipline with processes, patience (bug hunting) and in many cases you need to find solutions which may not always be the most elegant or mathematically pure way of doing things requiring you to be willing to make exceptions where required to get a solution.&#xD;&#xA;&#xD;&#xA;Understanding strong mathematical conecepts is one thing, throw in things like floating point precision error and the fact that real-world data is never like the canned examples you get in scientific papers, and you soon realise that a deeper knowledge of programming with skill sets that are specific to programming (and nothing to do with maths) are required to actually implement this understanding into working solutions. These things you would learn with a CS degree rather than a maths degree.&#xD;&#xA;&#xD;&#xA;I wouldn't have been able to do my first job without the degree I had as it gave me all the tools, skills and basic understanding I needed to do the job, but can honestly say I learnt more in the first 3 years of working in industry, and relevant experience, to doing the job that I do (and still love after all these years). I still learn today and suspect will keep learning for the rest of my career. In this respect, it's definately not impossible to have a very sucessful career in computer graphics without a CS degree (or more specifically a maths degree), and having a maths degree will keep more doors open for you, but ultimately, to get there faster, a CS background would be more advantageous. &#xD;&#xA;&#xD;&#xA;Degree content may be very different these days (got my degree 20+ years ago), so I can only guide/suggest based on my academic experience. I would suggest also looking in to the modules that would be avaliable to you to fully understand what you would be doing, and then you can be better informed if they would be applicable to what you want to do.&#xD;&#xA;&#xD;&#xA;For the record, my maths modules were (iirc)...&#xD;&#xA;&#xD;&#xA;Calculus (many modules, higher dimension calculus etc), Geometry and Set theory (Graphs, Cyclic groups etc), Trigonometry, Logic and flow, Statistics and Probability (Stochastic, dsitributions etc), Numerical analysis and methods (Newton, Monte Carlo, Fuzzy etc), Fluid Dynamics (losts of ODE, PDE, fields etc), Number theory (primes etc), Cryptography... plus others which I can't remember tbh...&#xD;&#xA;&#xD;&#xA;And out of them, the areas of maths that I have used the most is geometry by far, with the rest taken up by numerical methods, fluid dynamics (I've done CFD work in the past) and more probability/statistics (tensors) these days...&#xD;&#xA;&#xD;&#xA;Over my career, I always specialised more in the computer graphics and geometry realms, however this alone probably hasn't taken up half the time at work. Software architecture and other general stuff (bug fixing, not just in the realm of graphics, but anything) has also been a big part of my time at work.&#xD;&#xA;&#xD;&#xA;I hope I haven't put you off with some of the things I have said. I can honestly say that software development (computer graphics) is a very rewarding career and feel priviledged that I made the career choice that I did all those years ago as I still love my job every day. The 'ups' far out-weigh the 'downs'." ContentLicense="CC BY-SA 4.0" />
  <row Id="42745" PostHistoryTypeId="5" PostId="13917" RevisionGUID="74b775a8-32a5-49f2-a5b6-73dbf57530a7" CreationDate="2024-02-14T00:32:50.113" UserId="9438" Comment="deleted 68 characters in body" Text="As someone who has a degree in &quot;Computer Graphics and Mathematical Modelling&quot; and worked as a CAD/CAM developer for over 17 years. I would say 100% you want a degree in computer science rather than mathematics if you want to pursue it as a career. &#xD;&#xA;&#xD;&#xA;Mainly...&#xD;&#xA;&#xD;&#xA;* You need to know how to program, and beyond basic algorithms/problem solving. Actual hands on experience with a language used in industry. Doing a maths degree, you may go over some basics about program flow and algorithms etc, and you may do some basic programs in something like C (if you're lucky, although it may probably be something like matlab). But you will probably not go into certain concepts like OO, memory, linking, architecture etc, all of which are important in programming no matter which CS path you go down.&#xD;&#xA;&#xD;&#xA;* There are many concepts and processes you will need to understand and use in the industry (source control, compilers, optimisations) which you will not learn with a maths degree.&#xD;&#xA;&#xD;&#xA;* A computer science degree will no doubt be modular, and I highly suspect there will be modules specifically for computer graphics. This is very unlikely during a maths degree.&#xD;&#xA;&#xD;&#xA;* Modules in computer graphics will teach you many of the applicable fundamental concepts of computer graphics as well as exposing you to actual modern day graphics programming. There are many things we used to do in the fields of computer graphics which are just not done or needed these days (software rendering, rasterisers etc), but having the skill set you get from programming/CS degree, you will find it a lot easier to do these yourself to satisfy your own curiosity.&#xD;&#xA;&#xD;&#xA;* When you apply for your first job in industry, not having exposure to computing may put you at a disadvantage against other candidates who do (although having a maths a degree will have other advantages... see below).&#xD;&#xA;&#xD;&#xA;* While yes there is overlap, overall a mathematics degree will give you more theoretical skills but also give you more irrelevant knowledge in some quite complex fields of mathematics which will not ever be applicable in computing or specifically computer graphics.&#xD;&#xA;&#xD;&#xA;A degree in mathematics is hard, harder than computer science, but it certainly says a lot about your capability to any future employer. It would carry a lot of prestige when looking for a career in computer graphics/software, and any interviewer/employer worth their salt would understand that you would probably be more than capable in the role with a maths degree. However, it also suggests limited exposure to fundamental concepts and processes in the software development world, and thus longer prep time to get you functioning efficiently. Problem solving and understanding concepts is just a part of professional software development, deadlines are a real thing and pressure is a real thing. You need a lot of discipline with processes, patience (bug hunting) and in many cases you need to find solutions which may not always be the most elegant or mathematically pure way of doing things, requiring you to be willing to make exceptions where required to get a solution.&#xD;&#xA;&#xD;&#xA;Understanding strong mathematical conecepts is one thing, throw in things like floating point precision error and the fact that real-world data is never like the canned examples you get in scientific papers, and you soon realise that a deeper knowledge of programming with skill sets that are specific to programming (and nothing to do with maths) are required to actually implement this understanding into working solutions. These things you would learn with a CS degree rather than a maths degree.&#xD;&#xA;&#xD;&#xA;I wouldn't have been able to do my first job without the degree I had as it gave me all the tools, skills and basic understanding I needed to do the job, but can honestly say I learnt more in the first 3 years of working in industry, and relevant experience, to doing the job that I do (and still love after all these years). I still learn today and suspect will keep learning for the rest of my career. In this respect, it's definately not impossible to have a very sucessful career in computer graphics without a CS degree (or more specifically a maths degree), and having a maths degree will keep more doors open for you, but ultimately, to get there faster, a CS background would be more advantageous. &#xD;&#xA;&#xD;&#xA;Degree content may be very different these days (got my degree 20+ years ago), so I can only guide/suggest based on my academic experience. I would suggest also looking in to the modules that would be avaliable to you to fully understand what you would be doing, and then you can be better informed if they would be applicable to what you want to do.&#xD;&#xA;&#xD;&#xA;For the record, my maths modules were (iirc)...&#xD;&#xA;&#xD;&#xA;Calculus (many modules, higher dimension calculus etc), Geometry and Set theory (Graphs, Cyclic groups etc), Trigonometry, Logic and flow, Statistics and Probability (Stochastic, dsitributions etc), Numerical analysis and methods (Newton, Monte Carlo, Fuzzy etc), Fluid Dynamics (losts of ODE, PDE, fields etc), Number theory (primes etc), Cryptography... plus others which I can't remember tbh...&#xD;&#xA;&#xD;&#xA;And out of them, the areas of maths that I have used the most is geometry by far, with the rest taken up by numerical methods, fluid dynamics (I've done CFD work in the past) and more probability/statistics (tensors) these days...&#xD;&#xA;&#xD;&#xA;Over my career, I always specialised more in the computer graphics and geometry realms, however this alone probably hasn't taken up half the time at work. Software architecture and other general stuff (bug fixing, not just in the realm of graphics, but anything) has also been a big part of my time at work.&#xD;&#xA;&#xD;&#xA;I hope I haven't put you off with some of the things I have said. I can honestly say that software development (computer graphics) is a very rewarding career and feel priviledged that I made the career choice that I did all those years ago as I still love my job every day. The 'ups' far out-weigh the 'downs'." ContentLicense="CC BY-SA 4.0" />
  <row Id="42746" PostHistoryTypeId="5" PostId="13917" RevisionGUID="26ae964d-0ef9-4e8e-8150-250f0b1373b4" CreationDate="2024-02-14T00:48:41.067" UserId="9438" Comment="added 17 characters in body" Text="As someone who has a degree in &quot;Computer Graphics and Mathematical Modelling&quot; and worked as a CAD/CAM developer for over 17 years. I would say 100% you want a degree in computer science rather than mathematics if you want to pursue it as a career. &#xD;&#xA;&#xD;&#xA;Mainly...&#xD;&#xA;&#xD;&#xA;* You need to know how to program, and beyond basic algorithms/problem solving. Actual hands on experience with a language used in industry. Doing a maths degree, you may go over some basics about program flow and algorithms etc, and you may do some basic programs in something like C (if you're lucky, although it may probably be something like matlab). But you will probably not go into certain concepts like OO, memory, linking, architecture etc, all of which are important in programming no matter which CS path you go down.&#xD;&#xA;&#xD;&#xA;* There are many concepts and processes you will need to understand and use in the industry (source control, compilers, optimisations) which you will not learn with a maths degree.&#xD;&#xA;&#xD;&#xA;* A computer science degree will no doubt be modular, and I highly suspect there will be modules specifically for computer graphics. This is very unlikely during a maths degree.&#xD;&#xA;&#xD;&#xA;* Modules in computer graphics will teach you many of the applicable fundamental concepts of computer graphics as well as exposing you to actual modern day graphics programming. There are many things we used to do in the fields of computer graphics which are just not done or needed these days (software rendering, rasterisers etc), but having the skill set you get from programming/CS degree, you will find it a lot easier to do these yourself to satisfy your own curiosity.&#xD;&#xA;&#xD;&#xA;* When you apply for your first job in industry, not having exposure to computing may put you at a disadvantage against other candidates who do (although having a maths a degree will have other advantages... see below).&#xD;&#xA;&#xD;&#xA;* While yes there is overlap, overall a mathematics degree will give you more theoretical skills but also give you more irrelevant knowledge in some quite complex fields of mathematics which will not ever be applicable in computing or specifically computer graphics.&#xD;&#xA;&#xD;&#xA;A degree in mathematics is hard, harder than computer science, but it certainly says a lot about your capability to any future employer. It would carry a lot of prestige when looking for a career in computer graphics/software, and any interviewer/employer worth their salt would understand that you would probably be more than capable in the role with a maths degree. However, it also suggests limited exposure to fundamental concepts and processes in the software development world, and thus longer prep time to get you functioning efficiently. Problem solving and understanding concepts is just a part of professional software development, deadlines are a real thing and pressure is a real thing. You need a lot of discipline with processes, patience (bug hunting) and in many cases you need to find solutions which may not always be the most elegant or mathematically pure way of doing things, requiring you to be willing to make exceptions where required to get a solution.&#xD;&#xA;&#xD;&#xA;Understanding strong mathematical conecepts is one thing, throw in things like floating point precision error and the fact that real-world data is never like the canned examples you get in scientific papers, and you soon realise that a deeper knowledge of programming with skill sets that are specific to programming (and nothing to do with maths) are required to actually implement this understanding into working solutions. These things you would learn with a CS degree rather than a maths degree.&#xD;&#xA;&#xD;&#xA;I wouldn't have been able to do my first job without the degree I had as it gave me all the tools, skills and basic understanding I needed to do the job, but can honestly say I learnt more in the first 3 years of working in industry, and relevant experience, to doing the job that I do (and still love after all these years). I still learn today and suspect will keep learning for the rest of my career. In this respect, it's definately not impossible to have a very sucessful career in computer graphics without a CS degree (or more specifically a maths degree), and having a maths degree will keep more doors open for you, but ultimately, to get there faster, a CS background would be more advantageous. &#xD;&#xA;&#xD;&#xA;Degree content may be very different these days (got my degree 20+ years ago), so I can only guide/suggest based on my academic experience. I would suggest also looking in to the modules that would be avaliable to you to fully understand what you would be doing, and then you can be better informed if they would be applicable to what you want to do.&#xD;&#xA;&#xD;&#xA;For the record, my maths modules were (iirc)...&#xD;&#xA;&#xD;&#xA;Calculus (many modules, higher dimension calculus, vector calculus etc), Geometry and Set theory (Graphs, Cyclic groups etc), Trigonometry, Logic and flow, Statistics and Probability (Stochastic, dsitributions etc), Numerical analysis and methods (Newton, Monte Carlo, Fuzzy etc), Fluid Dynamics (losts of ODE, PDE, fields etc), Number theory (primes etc), Cryptography... plus others which I can't remember tbh...&#xD;&#xA;&#xD;&#xA;And out of them, the areas of maths that I have used the most is geometry by far, with the rest taken up by numerical methods, fluid dynamics (I've done CFD work in the past) and more probability/statistics (tensors) these days...&#xD;&#xA;&#xD;&#xA;Over my career, I always specialised more in the computer graphics and geometry realms, however this alone probably hasn't taken up half the time at work. Software architecture and other general stuff (bug fixing, not just in the realm of graphics, but anything) has also been a big part of my time at work.&#xD;&#xA;&#xD;&#xA;I hope I haven't put you off with some of the things I have said. I can honestly say that software development (computer graphics) is a very rewarding career and feel priviledged that I made the career choice that I did all those years ago as I still love my job every day. The 'ups' far out-weigh the 'downs'." ContentLicense="CC BY-SA 4.0" />
  <row Id="42747" PostHistoryTypeId="5" PostId="13917" RevisionGUID="8bf02769-7a11-4fc4-98f3-19fb0d36f238" CreationDate="2024-02-14T10:09:01.267" UserId="9438" Comment="added 20 characters in body" Text="As someone who has a degree in &quot;Computer Graphics and Mathematical Modelling&quot; and worked as a CAD/CAM developer for over 17 years. I would say 100% you want a degree in computer science rather than mathematics if you want to pursue it as a career. &#xD;&#xA;&#xD;&#xA;Mainly...&#xD;&#xA;&#xD;&#xA;* You need to know how to program, and beyond basic algorithms/problem solving. Actual hands on experience with a language used in industry. Doing a maths degree, you may go over some basics about program flow and algorithms etc, and you may do some basic programs in something like C (if you're lucky, although it may probably be something like matlab). But you will probably not go into certain concepts like OO, memory, compilers, optimisations, architecture etc, all of which are important in programming no matter which CS path you go down.&#xD;&#xA;&#xD;&#xA;* There are many concepts and processes you will need to understand and use in the industry (source control, issue tracking, tool chains) which you will not learn with a maths degree.&#xD;&#xA;&#xD;&#xA;* A computer science degree will no doubt be modular, and I highly suspect there will be modules specifically for computer graphics. This is very unlikely during a maths degree.&#xD;&#xA;&#xD;&#xA;* Modules in computer graphics will teach you many of the applicable fundamental concepts of computer graphics as well as exposing you to actual modern day graphics programming. There are many things we used to do in the fields of computer graphics which are just not done or needed these days (software rendering, rasterisers etc), but having the skill set you get from programming/CS degree, you will find it a lot easier to do these yourself to satisfy your own curiosity.&#xD;&#xA;&#xD;&#xA;* When you apply for your first job in industry, not having exposure to computing may put you at a disadvantage against other candidates who do (although having a maths a degree will have other advantages... see below).&#xD;&#xA;&#xD;&#xA;* While yes there is overlap, overall a mathematics degree will give you more theoretical skills but also give you more irrelevant knowledge in some quite complex fields of mathematics which will not ever be applicable in computing or specifically computer graphics.&#xD;&#xA;&#xD;&#xA;A degree in mathematics is hard, harder than computer science, but it certainly says a lot about your capability to any future employer. It would carry a lot of prestige when looking for a career in computer graphics/software, and any interviewer/employer worth their salt would understand that you would probably be more than capable in the role with a maths degree. However, it also suggests limited exposure to fundamental concepts and processes in the software development world, and thus longer prep time to get you functioning efficiently. Problem solving and understanding concepts is just a part of professional software development, deadlines are a real thing and pressure is a real thing. You need a lot of discipline with processes, patience (bug hunting) and in many cases you need to find solutions which may not always be the most elegant or mathematically pure way of doing things, requiring you to be willing to make exceptions where required to get a solution.&#xD;&#xA;&#xD;&#xA;Understanding strong mathematical conecepts is one thing, throw in things like floating point precision error and the fact that real-world data is never like the canned examples you get in scientific papers, and you soon realise that a deeper knowledge of programming with skill sets that are specific to programming (and nothing to do with maths) are required to actually implement this understanding into working solutions. These things you would learn with a CS degree rather than a maths degree.&#xD;&#xA;&#xD;&#xA;I wouldn't have been able to do my first job without the degree I had as it gave me all the tools, skills and basic understanding I needed to do the job, but can honestly say I learnt more in the first 3 years of working in industry, and relevant experience, to doing the job that I do (and still love after all these years). I still learn today and suspect will keep learning for the rest of my career. In this respect, it's definately not impossible to have a very sucessful career in computer graphics without a CS degree (or more specifically a maths degree), and having a maths degree will keep more doors open for you, but ultimately, to get there faster, a CS background would be more advantageous. &#xD;&#xA;&#xD;&#xA;Degree content may be very different these days (got my degree 20+ years ago), so I can only guide/suggest based on my academic experience. I would suggest also looking in to the modules that would be avaliable to you to fully understand what you would be doing, and then you can be better informed if they would be applicable to what you want to do.&#xD;&#xA;&#xD;&#xA;For the record, my maths modules were (iirc)...&#xD;&#xA;&#xD;&#xA;Calculus (many modules, higher dimension calculus, vector calculus etc), Geometry and Set theory (Graphs, Cyclic groups etc), Trigonometry, Logic and flow, Statistics and Probability (Stochastic, dsitributions etc), Numerical analysis and methods (Newton, Monte Carlo, Fuzzy etc), Fluid Dynamics (losts of ODE, PDE, fields etc), Number theory (primes etc), Cryptography... plus others which I can't remember tbh...&#xD;&#xA;&#xD;&#xA;And out of them, the areas of maths that I have used the most is geometry by far, with the rest taken up by numerical methods, fluid dynamics (I've done CFD work in the past) and more probability/statistics (tensors) these days...&#xD;&#xA;&#xD;&#xA;Over my career, I always specialised more in the computer graphics and geometry realms, however this alone probably hasn't taken up half the time at work. Software architecture and other general stuff (bug fixing, not just in the realm of graphics, but anything) has also been a big part of my time at work.&#xD;&#xA;&#xD;&#xA;I hope I haven't put you off with some of the things I have said. I can honestly say that software development (computer graphics) is a very rewarding career and feel priviledged that I made the career choice that I did all those years ago as I still love my job every day. The 'ups' far out-weigh the 'downs'." ContentLicense="CC BY-SA 4.0" />
  <row Id="42748" PostHistoryTypeId="5" PostId="13917" RevisionGUID="1ed06868-8b1c-42dc-8480-f3362d6c289d" CreationDate="2024-02-14T10:16:20.767" UserId="9438" Comment="added 23 characters in body" Text="As someone who has a degree in &quot;Computer Graphics and Mathematical Modelling&quot; and worked as a CAD/CAM/CAE developer for over 17 years. I would say 100% you want a degree in computer science rather than mathematics if you want to pursue it as a career. &#xD;&#xA;&#xD;&#xA;Mainly...&#xD;&#xA;&#xD;&#xA;* You need to know how to program, and beyond basic algorithms/problem solving. Actual hands on experience with a language used in industry. Doing a maths degree, you may go over some basics about program flow and algorithms etc, and you may do some basic programs in something like C (if you're lucky, although it may probably be something like matlab). But you will probably not go into certain concepts like OO, memory, compilers, optimisations, architecture etc, all of which are important in programming no matter which CS path you go down.&#xD;&#xA;&#xD;&#xA;* There are many concepts and processes you will need to understand and use in the industry (source control, issue tracking, tool chains) which you will not learn with a maths degree.&#xD;&#xA;&#xD;&#xA;* A computer science degree will no doubt be modular, and I highly suspect there will be modules specifically for computer graphics. This is very unlikely during a maths degree.&#xD;&#xA;&#xD;&#xA;* Modules in computer graphics will teach you many of the applicable fundamental concepts of computer graphics as well as exposing you to actual modern day graphics programming. There are many things we used to do in the fields of computer graphics which are just not done or needed these days (software rendering, rasterisers etc), but having the skill set you get from programming/CS degree, you will find it a lot easier to do these yourself to satisfy your own curiosity.&#xD;&#xA;&#xD;&#xA;* When you apply for your first job in industry, not having exposure to computing may put you at a disadvantage against other candidates who do (although having a maths a degree will have other advantages... see below).&#xD;&#xA;&#xD;&#xA;* While yes there is overlap, overall a mathematics degree will give you more theoretical skills but also give you more irrelevant knowledge in some quite complex fields of mathematics which will not ever be applicable in computing or specifically computer graphics.&#xD;&#xA;&#xD;&#xA;A degree in mathematics is hard, harder than computer science, but it certainly says a lot about your capability to any future employer. It would carry a lot of prestige when looking for a career in computer graphics/software, and any interviewer/employer worth their salt would understand that you would probably be more than capable in the role with a maths degree. However, it also suggests limited exposure to fundamental concepts and processes in the software development world, and thus longer prep time to get you functioning efficiently. Problem solving and understanding concepts is just a part of professional software development, deadlines are a real thing and pressure is a real thing. You need a lot of discipline with processes, patience (bug hunting) and in many cases you need to find solutions which may not always be the most elegant or mathematically pure way of doing things, requiring you to be willing to make exceptions where required to get a solution.&#xD;&#xA;&#xD;&#xA;Understanding strong mathematical conecepts is one thing, throw in things like floating point precision error and the fact that real-world data is never like the canned examples you get in scientific papers, and you soon realise that a deeper knowledge of programming with skill sets that are specific to programming (and nothing to do with maths) are required to actually implement this understanding into working solutions. These things you would learn with a CS degree rather than a maths degree.&#xD;&#xA;&#xD;&#xA;I wouldn't have been able to do my first job without the degree I had as it gave me all the tools, skills and basic understanding I needed to do the job, but can honestly say I learnt more in the first 3 years of working in industry, and relevant experience, to doing the job that I do (and still love after all these years). I still learn today and suspect will keep learning for the rest of my career. In this respect, it's definately not impossible to have a very sucessful career in computer graphics without a CS degree (or more specifically a maths degree), and having a maths degree will keep more doors open for you, but ultimately, to get there faster, a CS background would be more advantageous. &#xD;&#xA;&#xD;&#xA;Degree content may be very different these days (got my degree 20+ years ago), so I can only guide/suggest based on my academic experience. I would suggest also looking in to the modules that would be avaliable to you to fully understand what you would be doing, and then you can be better informed if they would be applicable to what you want to do.&#xD;&#xA;&#xD;&#xA;For the record, my maths modules were (iirc)...&#xD;&#xA;&#xD;&#xA;Calculus (many modules, higher dimension calculus, vector calculus etc), Geometry (Trigonometry), Groups and Set theory (Graphs, Cyclic groups etc), Trigonometry, Logic and flow, Statistics and Probability (Stochastic, dsitributions etc), Numerical analysis and methods (Newton, Monte Carlo, Fuzzy etc), Fluid Dynamics (losts of ODE, PDE, Fields etc), Number theory (Primes etc), Cryptography... plus others which I can't remember tbh...&#xD;&#xA;&#xD;&#xA;And out of them, the areas of maths that I have used the most is geometry by far, with the rest taken up by numerical methods, fluid dynamics (I've done CFD work in the past) and more probability/statistics (tensors) these days...&#xD;&#xA;&#xD;&#xA;Over my career, I always specialised more in the computer graphics and geometry realms, however this alone probably hasn't taken up half the time at work. Software architecture and other general stuff (bug fixing, not just in the realm of graphics, but anything) has also been a big part of my time at work.&#xD;&#xA;&#xD;&#xA;I hope I haven't put you off with some of the things I have said. I can honestly say that software development (computer graphics) is a very rewarding career and feel priviledged that I made the career choice that I did all those years ago as I still love my job every day. The 'ups' far out-weigh the 'downs'." ContentLicense="CC BY-SA 4.0" />
  <row Id="42749" PostHistoryTypeId="2" PostId="13918" RevisionGUID="99302e45-ca52-44c6-b1e5-75eb14a74adb" CreationDate="2024-02-14T22:56:32.053" UserId="21175" Text="I've been implementing a path tracer in Vulkan using the VK_ray_tracing extension and am a bit confused on how to set up the pipeline. Currently I've been following the style of the Reference Path Tracer in Chapter 14 of Ray Tracing Gems II. Basically, having the raygen be an uber shader that does all of the iterative ray bounces and material calculations.&#xD;&#xA;&#xD;&#xA;I've also heard of using a wavefront ray tracing approach for handling the different shader stages in hopes of getting better utilization.&#xD;&#xA;&#xD;&#xA;In terms of implementing a path tracer, which approach is better from a performance perspective? Does the setup of VK_ray_tracing with hardware ray tracing invalidate the need for manually formulating the pathtracing in a wavefront manner or could it still benefit from that setup over a &quot;naive&quot; uber shader approach." ContentLicense="CC BY-SA 4.0" />
  <row Id="42751" PostHistoryTypeId="1" PostId="13918" RevisionGUID="99302e45-ca52-44c6-b1e5-75eb14a74adb" CreationDate="2024-02-14T22:56:32.053" UserId="21175" Text="Vulkan (Hardware) Path Tracing Formulation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42752" PostHistoryTypeId="3" PostId="13918" RevisionGUID="99302e45-ca52-44c6-b1e5-75eb14a74adb" CreationDate="2024-02-14T22:56:32.053" UserId="21175" Text="|raytracing|pathtracing|vulkan|performance|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42753" PostHistoryTypeId="2" PostId="13919" RevisionGUID="de37f95e-400d-4730-8aff-3c021d99b53b" CreationDate="2024-02-15T06:23:24.490" UserId="9945" Text="I am trying to support hardware sparse virtual texture in my little engine but I found that there are almost no examples on the internet. Can anybody provide me with a little example to illustrate the usage of these two extensions? Or at least the necessary steps to make it work?&#xD;&#xA;&#xD;&#xA;I have already examined the following documents/links:&#xD;&#xA;&#xD;&#xA;Khronos document pages: no code samples&#xD;&#xA;&#xD;&#xA;- https://registry.khronos.org/OpenGL/extensions/ARB/ARB_sparse_texture.txt&#xD;&#xA;- https://registry.khronos.org/OpenGL/extensions/ARB/ARB_sparse_texture2.txt&#xD;&#xA;&#xD;&#xA;g-truc OpenGL samples: I don't see a memory/disk swap in/out process in this simple sample&#xD;&#xA;&#xD;&#xA;- https://github.com/g-truc/ogl-samples/blob/master/samples/gl-500-texture-sparse-arb.cpp&#xD;&#xA;&#xD;&#xA;software virtual texture: I would like to use the hardware virtual texture technique rather than the software one&#xD;&#xA;&#xD;&#xA;- https://studiopixl.com/2022-04-27/sparse-virtual-textures&#xD;&#xA;- https://www.youtube.com/watch?v=MejJL87yNgI&amp;ab_channel=SeanBarrett&#xD;&#xA;- https://ktstephano.github.io/rendering/stratusgfx/svsm&#xD;&#xA;- https://www.renaudpradenc.com/?p=517" ContentLicense="CC BY-SA 4.0" />
  <row Id="42755" PostHistoryTypeId="1" PostId="13919" RevisionGUID="de37f95e-400d-4730-8aff-3c021d99b53b" CreationDate="2024-02-15T06:23:24.490" UserId="9945" Text="Can anybody give me an example of how to use ARB_sparse_texture and ARB_sparse_texture2?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42756" PostHistoryTypeId="3" PostId="13919" RevisionGUID="de37f95e-400d-4730-8aff-3c021d99b53b" CreationDate="2024-02-15T06:23:24.490" UserId="9945" Text="|opengl|texture|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42762" PostHistoryTypeId="2" PostId="13921" RevisionGUID="08f2bf70-1130-4473-98ee-706585e28a32" CreationDate="2024-02-15T21:14:07.863" UserId="21180" Text="I am working with the standford2d3d dataset http://buildingparser.stanford.edu/dataset.html which contains panoramas of various scenes and a .mat file of the point cloud information of all the scenes. I have been able to write a script that will extract the point cloud information from each scene according to the position of the camera. So for example there might be an RGB panorama of a specific office (let's say office_26 for example). I can extract the office_26 point cloud information so that now I have the panorama and the point cloud information of the scene.&#xD;&#xA;&#xD;&#xA;Ultimately what I want to do is get each face of the panorama using a CMP script I wrote but also get the point cloud information of each face. Something to note is that my CMP script allows me to have different width and height dimensions (the theta shift is just to shift the panorama x degrees to the right):&#xD;&#xA;&#xD;&#xA;    def spherical_to_cube(face_width, face_height, img, theta_shift):&#xD;&#xA;        &quot;&quot;&quot;&#xD;&#xA;        Converts an equirectangular (spherical) panorama image into a cube map representation.&#xD;&#xA;        &quot;&quot;&quot;&#xD;&#xA;&#xD;&#xA;The route I have tried to go down is to create a view frustum and extract the points inside the frustum but I haven't figured out a proper way of doing it and keep getting weird behaviour. There is also the fact that I have no way of aligning the panorama with the point cloud data properly. &#xD;&#xA;&#xD;&#xA;**Some useful information:** the point cloud data includes the camera position and rotation." ContentLicense="CC BY-SA 4.0" />
  <row Id="42764" PostHistoryTypeId="1" PostId="13921" RevisionGUID="08f2bf70-1130-4473-98ee-706585e28a32" CreationDate="2024-02-15T21:14:07.863" UserId="21180" Text="How to extract points corresponding to faces from cube map projection (CMP) of panorama from point cloud data" ContentLicense="CC BY-SA 4.0" />
  <row Id="42765" PostHistoryTypeId="3" PostId="13921" RevisionGUID="08f2bf70-1130-4473-98ee-706585e28a32" CreationDate="2024-02-15T21:14:07.863" UserId="21180" Text="|3d|computational-geometry|image-processing|projections|2d|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42766" PostHistoryTypeId="5" PostId="13921" RevisionGUID="805c9bd6-0b9f-4729-8aed-49a55ec21dd9" CreationDate="2024-02-15T21:27:55.197" UserId="21180" Comment="added 91 characters in body" Text="I am working with the standford2d3d dataset http://buildingparser.stanford.edu/dataset.html which contains panoramas of various scenes and a .mat file of the point cloud information of all the scenes. I have been able to write a script that will extract the point cloud information from each scene according to the position of the camera. So for example there might be an RGB panorama of a specific office (let's say office_26 for example). I can extract the office_26 point cloud information so that now I have the panorama and the point cloud information of the scene.&#xD;&#xA;&#xD;&#xA;Ultimately what I want to do is get each face of the panorama using a CMP script I wrote but also get the point cloud information of each face. Something to note is that my CMP script allows me to have different width and height dimensions (the theta shift is just to shift the panorama x degrees to the right):&#xD;&#xA;&#xD;&#xA;    def spherical_to_cube(face_width, face_height, img, theta_shift):&#xD;&#xA;        &quot;&quot;&quot;&#xD;&#xA;        Converts an equirectangular (spherical) panorama image into a cube map representation.&#xD;&#xA;        &quot;&quot;&quot;&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The route I have tried to go down is to create a view frustum and extract the points inside the frustum but I haven't figured out a proper way of doing it and keep getting weird behaviour. There is also the fact that I have no way of aligning the panorama with the point cloud data properly. &#xD;&#xA;&#xD;&#xA;**Some useful information:** the point cloud data includes the camera position and rotation.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/lSWY6.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42767" PostHistoryTypeId="2" PostId="13922" RevisionGUID="289cb821-589b-44b8-8798-bc31b0a66ca6" CreationDate="2024-02-15T23:18:39.727" UserId="10932" Text="My understanding is that path tracers deal with radiance because radiance is constant along a ray.  You simply go through and evaluate the light transport equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(p, \omega_o) = L_e(p,\omega_o) + \int_S f(p,\omega_o,\omega_i)L_i(p,\omega_i) | \cos{\theta_i}| \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with the goal of tracing a path through the scene and calculating the total radiance contributed to that path.  My confusion comes from the following:&#xD;&#xA;&#xD;&#xA;Say I have a spherical light, that has a radius of $1m$, and has a total radiant power of $100W$.  Assuming the light is isotropic, I can calculate the radiant exitance from this light by dividing the total radiant power, by its surface area, giving:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;M_e = \frac{100 W}{4\pi(1m)^2} = 7.9577 \frac{W}{m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Using the following relations:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;M_e &amp;= \frac{\partial \Phi_e}{\partial A} \\&#xD;&#xA;L_{e,\Omega} &amp;= \frac{\partial^2 \Phi_e}{\partial\Omega \partial (A\cos{\theta})}\\&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;I can calculate the emitted radiance from its surface by the following:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;L_{e,\Omega} &amp;= \frac{\partial M_e}{\partial \Omega} \frac{1}{\cos{\theta}}\\&#xD;&#xA;\int_SL_{e,\Omega} \cos{\theta} \ d\Omega &amp;= M_e\\&#xD;&#xA;\int_0^{2\pi}\int_0^{\pi/2} L_{e,\Omega}\cos{\theta}\sin{\theta} \ d\theta \ d\phi &amp;= M_e\\&#xD;&#xA;L_{e,\Omega} \pi &amp;= M_e\\&#xD;&#xA;L_{e,\Omega} &amp;= \frac{M_e}{\pi}\\&#xD;&#xA;\boxed{L_{e,\Omega} = 2.533 \frac{W}{sr \cdot m^2}}&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Now if I cast two rays into the scene, one which lands 100m from the light, and the other which lands 10m from the light, they should be illuminated very differently.  Yet, when I sample the light source, I'll obtain a ray which carries a radiance of $2.533 \frac{W}{sr \cdot m^2}$.  How is the fact that less total energy (and thus less &quot;illumination&quot;) makes it to the further away spot, accounted for in this process?&#xD;&#xA;&#xD;&#xA;My first thought would be to account for the angular size of the light.  That is to say, for a point $100m$ away ($d$) I can calculate the solid angle subtended by the light with respect to the point I'm evaluating using:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;\Omega &amp;= 2\pi\left(1 - \frac{\sqrt{d^2 - R^2}}{d}\right)\\&#xD;&#xA;&amp;= 3.1417\times10^{-4} \ sr&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;I can use this to get the irradiance by multiplying this solid angle by the previously calculated radiance, I get:&#xD;&#xA;&#xD;&#xA;\begin{aligned}&#xD;&#xA;E_e &amp;= \Omega\cdot L_{e,\Omega}\\&#xD;&#xA;&amp;= (3.1417\times10^-4 \ sr) \cdot (2.533 \frac{W}{sr \cdot m^2})\\&#xD;&#xA;&amp;= 7.9579\times 10^{-4} \frac{W}{m^2}&#xD;&#xA;\end{aligned}&#xD;&#xA;&#xD;&#xA;This matches with the irradiance you'd calculate from a point light with a radiant power of $100W$, so it appears as if all has been calculated correctly.&#xD;&#xA;&#xD;&#xA;But that quantity is irradiance, with units of $\frac{W}{m^2}$.  And without multiplying by this solid angle, the radiance remains constant regardless of the distance to the light source.  So how exactly does a path tracer accurately simulate light falloff, if it only tracks the radiance along the whole path?&#xD;&#xA;&#xD;&#xA;Looking at [PBR's section of Sampling Light Sources](https://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Sampling_Light_Sources) still leaves me confused.  Part of it states:&#xD;&#xA;&gt;The Light’s `Pdf_Li()` method returns the probability density with respect to solid angle for the light’s `Sample_Li()` method to sample the direction `wi` from the reference point ref.&#xD;&#xA;&#xD;&#xA;**This feels similar in spirit to what I have done.  As the light is further away, it subtends a much smaller solid angle, and so conceivably you'd weight its radiance contribution less (as the further away the light gets, the less likely it is you'd intersect the light).  But I'm struggling to see how this weighting process is different than simply multiplying the radiance by the solid angle subtended by the light, which would yield *irradiance*, thus breaking the whole path tracing concept of summing radiance along a path.**&#xD;&#xA;&#xD;&#xA;[![Light Falloff Example][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ppz3q.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42769" PostHistoryTypeId="1" PostId="13922" RevisionGUID="289cb821-589b-44b8-8798-bc31b0a66ca6" CreationDate="2024-02-15T23:18:39.727" UserId="10932" Text="How does a path tracer capture light falloff if it deals exclusively with radiance?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42770" PostHistoryTypeId="3" PostId="13922" RevisionGUID="289cb821-589b-44b8-8798-bc31b0a66ca6" CreationDate="2024-02-15T23:18:39.727" UserId="10932" Text="|rendering|pathtracing|lighting|sampling|importance-sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42771" PostHistoryTypeId="5" PostId="13922" RevisionGUID="739acbce-de87-41b0-aea9-060013a75d36" CreationDate="2024-02-16T04:38:53.153" UserId="10932" Comment="added 224 characters in body" Text="My understanding is that path tracers deal with radiance because radiance is constant along a ray.  You simply go through and evaluate the light transport equation:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(p, \omega_o) = L_e(p,\omega_o) + \int_S f(p,\omega_o,\omega_i)L_i(p,\omega_i) | \cos{\theta_i}| \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;with the goal of tracing a path through the scene and calculating the total radiance contributed to that path.  My confusion comes from the following:&#xD;&#xA;&#xD;&#xA;Say I have a spherical light, that has a radius of $1m$, and has a total radiant power of $100W$.  Assuming the light is isotropic, I can calculate the radiant exitance from this light by dividing the total radiant power, by its surface area, giving:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;M_e = \frac{100 W}{4\pi(1m)^2} = 7.9577 \frac{W}{m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Using the following relations:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;M_e &amp;= \frac{\partial \Phi_e}{\partial A} \\&#xD;&#xA;L_{e,\Omega} &amp;= \frac{\partial^2 \Phi_e}{\partial\Omega \partial (A\cos{\theta})}\\&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;I can calculate the emitted radiance from its surface by the following:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;L_{e,\Omega} &amp;= \frac{\partial M_e}{\partial \Omega} \frac{1}{\cos{\theta}}\\&#xD;&#xA;\int_SL_{e,\Omega} \cos{\theta} \ d\Omega &amp;= M_e\\&#xD;&#xA;\int_0^{2\pi}\int_0^{\pi/2} L_{e,\Omega}\cos{\theta}\sin{\theta} \ d\theta \ d\phi &amp;= M_e\\&#xD;&#xA;L_{e,\Omega} \pi &amp;= M_e\\&#xD;&#xA;L_{e,\Omega} &amp;= \frac{M_e}{\pi}\\&#xD;&#xA;\boxed{L_{e,\Omega} = 2.533 \frac{W}{sr \cdot m^2}}&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Now if I cast two rays into the scene, one which lands 100m from the light, and the other which lands 10m from the light, they should be illuminated very differently.  Yet, when I sample the light source, I'll obtain a ray which carries a radiance of $2.533 \frac{W}{sr \cdot m^2}$.  How is the fact that less total energy (and thus less &quot;illumination&quot;) makes it to the further away spot, accounted for in this process?&#xD;&#xA;&#xD;&#xA;My first thought would be to account for the angular size of the light.  That is to say, for a point $100m$ away ($d$) I can calculate the solid angle subtended by the light with respect to the point I'm evaluating using:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;\Omega &amp;= 2\pi\left(1 - \frac{\sqrt{d^2 - R^2}}{d}\right)\\&#xD;&#xA;&amp;= 3.1417\times10^{-4} \ sr&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;I can use this to get the irradiance by multiplying this solid angle by the previously calculated radiance, I get:&#xD;&#xA;&#xD;&#xA;\begin{aligned}&#xD;&#xA;E_e &amp;= \Omega\cdot L_{e,\Omega}\\&#xD;&#xA;&amp;= (3.1417\times10^-4 \ sr) \cdot (2.533 \frac{W}{sr \cdot m^2})\\&#xD;&#xA;&amp;= 7.9579\times 10^{-4} \frac{W}{m^2}&#xD;&#xA;\end{aligned}&#xD;&#xA;&#xD;&#xA;This matches with the irradiance you'd calculate from a point light with a radiant power of $100W$, so it appears as if all has been calculated correctly.&#xD;&#xA;&#xD;&#xA;But that quantity is irradiance, with units of $\frac{W}{m^2}$.  And without multiplying by this solid angle, the radiance remains constant regardless of the distance to the light source.  So how exactly does a path tracer accurately simulate light falloff, if it only tracks the radiance along the whole path?&#xD;&#xA;&#xD;&#xA;Looking at [PBR's section of Sampling Light Sources](https://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Sampling_Light_Sources) still leaves me confused.  Part of it states:&#xD;&#xA;&gt;The Light’s `Pdf_Li()` method returns the probability density with respect to solid angle for the light’s `Sample_Li()` method to sample the direction `wi` from the reference point ref.&#xD;&#xA;&#xD;&#xA;**This feels similar in spirit to what I have done.  As the light is further away, it subtends a much smaller solid angle, and so conceivably you'd weight its radiance contribution less (as the further away the light gets, the less likely it is you'd intersect the light).  But I'm struggling to see how this weighting process is different than simply multiplying the radiance by the solid angle subtended by the light, which would yield *irradiance*, thus breaking the whole path tracing concept of summing radiance along a path.  And why do we even need to weight the ray this way?  If a light is visible to a point, the radiance from that light is landing on the point.  So I'm not following how to properly compute this kind of direction illumination**&#xD;&#xA;&#xD;&#xA;[![Light Falloff Example][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ppz3q.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42772" PostHistoryTypeId="2" PostId="13923" RevisionGUID="74a9ca58-41f5-4fb5-9cfc-2a1c8dd1412b" CreationDate="2024-02-16T09:04:40.670" UserId="10096" Text="The inverse square law does not apply to radiance. We can compute irradiance as \begin{align}&#xD;&#xA;E(x, \Omega) &amp;= \int_{\Omega} L_i(x, \omega_i) \underbrace{\cos\theta_x}_{N_x \cdot \omega_i} \, dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega} L_o(\underbrace{r(x,\omega_i)}_{y}, \underbrace{-\omega_i}_{y\to x}) \cos\theta_x \, dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega} L_o(y, y\to x) \cos\theta_x dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega_M} L_o(y, y\to x) \cos\theta_x \underbrace{\cos\theta_y}_{N_y \cdot (y\to x)} \frac{1}{\|y-x\|^2_2} \, dA(\underbrace{y}_{r(x, \omega_i)}) \\&#xD;&#xA;&amp;= \int_{M} L_o(z, z\to x) \frac{\cos\theta_x \cos\theta_z}{\|z-x\|^2_2}V(x,z) \, dA(z) \\&#xD;&#xA;&amp;= \int_M L_o(z, z\to x) G(x,z) \,dA(z).&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Here $\Omega$ is some subset of the hemisphere at $x$ around the normal $N_x$. The term $L_i(x, \omega_i)$ is incident radiance at $x$ from direction $\omega_i$ (this direction points outwards from $x$). The $dA(\omega_i)$ is the differential area element on this hemisphere. In vacuum the incident radiance at $x$ along $\omega_i$ is equal to the outgoing radiance from $y=r(x, \omega_i)$ along $-\omega_i$, where $r(x, \omega_i)$ is the ray-tracing function and returns the first intersection $y$ along the ray from $x$ in direction $\omega_i$. The $\cos\theta_x$ is due to Lambert's law. In line four I have done a change of variables $y=r(x, \omega_i)$ - so now I integrate over the projection of $\Omega$ onto the scene surfaces: $\Omega_M=\{r(x, \omega_i) \in M \, : \, \omega_i \in \Omega\}$. This change of variables is accounted for by the factors $\cos\theta_y$ and $\|y - x\|^{-2}_2$. The $\cos\theta_y$ accounts for how slanted a small area around $y$ is wrt $\omega_i$, and $\|y-x\|^{-2}_2$ accounts for the fact that further away objects subtend a smaller solid angle. The step before last is just rewriting the integral over all scene points instead of just $M$, by introducing a visibility function $V(x,z)$ which is one if $r(x, x\to z) = z$, and zero otherwise. That is what is typically termed the area formulation.&#xD;&#xA;&#xD;&#xA;As you can see, the inverse square distance term arises from parametrising integration over points as opposed to directions. But the two integrals are equal, so in theory it doesn't matter which you use (in practice you use the area formulation for light sampling). There's no issue that this isn't part of radiance, since radiance does not fall off quadratically." ContentLicense="CC BY-SA 4.0" />
  <row Id="42774" PostHistoryTypeId="5" PostId="13923" RevisionGUID="9211ac9b-0fcb-478c-b87e-b364b0935d42" CreationDate="2024-02-16T09:26:00.363" UserId="10096" Comment="added 193 characters in body" Text="The inverse square law does not apply to radiance. We can compute irradiance as \begin{align}&#xD;&#xA;E(x, \Omega) &amp;= \int_{\Omega} L_i(x, \omega_i) \underbrace{\cos\theta_x}_{N_x \cdot \omega_i} \, dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega} L_o(\underbrace{r(x,\omega_i)}_{y}, \underbrace{-\omega_i}_{y\to x}) \cos\theta_x \, dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega} L_o(y, y\to x) \cos\theta_x dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega_M} L_o(y, y\to x) \cos\theta_x \underbrace{\cos\theta_y}_{N_y \cdot (y\to x)} \frac{1}{\|y-x\|^2_2} \, dA(\underbrace{y}_{r(x, \omega_i)}) \\&#xD;&#xA;&amp;= \int_{M} L_o(z, z\to x) \frac{\cos\theta_x \cos\theta_z}{\|z-x\|^2_2}V(x,z) \, dA(z) \\&#xD;&#xA;&amp;= \int_M L_o(z, z\to x) G(x,z) \,dA(z).&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Here $\Omega$ is some subset of the hemisphere at $x$ around the normal $N_x$. The term $L_i(x, \omega_i)$ is incident radiance at $x$ from direction $\omega_i$ (this direction points outwards from $x$). The $dA(\omega_i)$ is the differential area element on this hemisphere. In vacuum the incident radiance at $x$ along $\omega_i$ is equal to the outgoing radiance from $y=r(x, \omega_i)$ along $-\omega_i$, where $r(x, \omega_i)$ is the ray-tracing function and returns the first intersection $y$ along the ray from $x$ in direction $\omega_i$. The $\cos\theta_x$ is due to Lambert's law. In line four I have done a change of variables $y=r(x, \omega_i)$ - so now I integrate over the projection of $\Omega$ onto the scene surfaces: $\Omega_M=\{r(x, \omega_i) \in M \, : \, \omega_i \in \Omega\}$. This change of variables is accounted for by the factors $\cos\theta_y$ and $\|y - x\|^{-2}_2$. The $\cos\theta_y$ accounts for how slanted a small area around $y$ is wrt $\omega_i$, and $\|y-x\|^{-2}_2$ accounts for the fact that further away objects subtend a smaller solid angle. The step before last is just rewriting the integral over all scene points instead of just $M$, by introducing a visibility function $V(x,z)$ which is one if $r(x, x\to z) = z$, and zero otherwise. That is what is typically termed the area formulation.&#xD;&#xA;&#xD;&#xA;As you can see, the inverse square distance term arises from parametrising integration over points as opposed to directions. But the two integrals are equal, so in theory it doesn't matter which you use (in practice you use the area formulation for light sampling). There's no issue that this isn't part of radiance, since radiance does not fall off quadratically.&#xD;&#xA;&#xD;&#xA;There is no issue in a path tracer either as it is estimating integrals that either implicitly (solid angle formulation) or explicitly (area formulation) include the quadratic falloff term." ContentLicense="CC BY-SA 4.0" />
  <row Id="42775" PostHistoryTypeId="5" PostId="13923" RevisionGUID="8ddd6c19-461c-459a-95bd-036f8cf92064" CreationDate="2024-02-16T12:07:41.517" UserId="10096" Comment="added 11 characters in body" Text="The inverse square law does not apply to radiance. We can compute irradiance as \begin{align}&#xD;&#xA;E(x, \Omega) &amp;= \int_{\Omega} L_i(x, \omega_i) \underbrace{\cos\theta_x}_{N_x \cdot \omega_i} \, dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega} L_o(\underbrace{r(x,\omega_i)}_{y}, \underbrace{-\omega_i}_{y\to x}) \cos\theta_x \, dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega} L_o(y, y\to x) \cos\theta_x dA(\omega_i) \\&#xD;&#xA;&amp;= \int_{\Omega_M} L_o(y, y\to x) \cos\theta_x \underbrace{\cos\theta_y}_{N_y \cdot (y\to x)} \frac{1}{\|y-x\|^2_2} \, dA(\underbrace{y}_{r(x, \omega_i)}) \\&#xD;&#xA;&amp;= \int_{M} L_o(z, z\to x) \frac{\cos\theta_x \cos\theta_z}{\|z-x\|^2_2}V(x,z) \, dA(z) \\&#xD;&#xA;&amp;= \int_M L_o(z, z\to x) G(x,z) \,dA(z).&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;Here $\Omega$ is some subset of the hemisphere at $x$ around the normal $N_x$. The term $L_i(x, \omega_i)$ is incident radiance at $x$ from direction $\omega_i$ (this direction points outwards from $x$). The $dA(\omega_i)$ is the differential area element on this hemisphere. In vacuum the incident radiance at $x$ along $\omega_i$ is equal to the outgoing radiance from $y=r(x, \omega_i)$ along $-\omega_i$, where $r(x, \omega_i)$ is the ray-tracing function and returns the first intersection $y$ along the ray from $x$ in direction $\omega_i$. The $\cos\theta_x$ is due to Lambert's law. In line four I have done a change of variables $y=r(x, \omega_i)$ - so now I integrate over the projection of $\Omega$ onto the scene surfaces: $\Omega_M=\{r(x, \omega_i) \in M \, : \, \omega_i \in \Omega\}$. This change of variables is accounted for by the factors $\cos\theta_y$ and $\|y - x\|^{-2}_2$. The $\cos\theta_y$ accounts for how slanted a small area around $y$ is wrt $\omega_i$, and $\|y-x\|^{-2}_2$ accounts for the fact that further away objects subtend a smaller solid angle. The step before last is just rewriting the integral over all scene points $M$ instead of just $\Omega_M$, by introducing a visibility function $V(x,z)$ which is one if $r(x, x\to z) = z$, and zero otherwise. That is what is typically termed the area formulation.&#xD;&#xA;&#xD;&#xA;As you can see, the inverse square distance term arises from parametrising integration over points as opposed to directions. But the two integrals are equal, so in theory it doesn't matter which you use (in practice you use the area formulation for light sampling). There's no issue that this isn't part of radiance, since radiance does not fall off quadratically.&#xD;&#xA;&#xD;&#xA;There is no issue in a path tracer either as it is estimating integrals that either implicitly (solid angle formulation) or explicitly (area formulation) include the quadratic falloff term." ContentLicense="CC BY-SA 4.0" />
  <row Id="42776" PostHistoryTypeId="2" PostId="13924" RevisionGUID="bbf38e8d-a1e2-4f0f-bb14-df6355af86e2" CreationDate="2024-02-17T04:15:32.927" UserId="10932" Text="I'm trying to make intuitive sense of the rendering equation and so I'm trying to work out a trivial example by hand, though ultimately I'm just trying to understand how monte carlo importance sampling is applied.&#xD;&#xA;&#xD;&#xA;Lets ignore for emittance, and so the rendering equation is simply:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(x, \omega_o) = \int_{\Omega} f(x,\omega_o,\omega_i)L_i(x,\omega_i) \left(\omega_i \cdot \hat{n}\right) \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now for my purposes, I'm considering a spherical light with a radius $R$ and a radiant power of $\Phi$, that is $d$ away from point $x$ directly along the surface normal vector $\hat{n}$.  I'm also assuming the BRDF is lambertian:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r = \frac{\rho}{\pi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $\rho$ is the surface's albedo.  In this case, the integral simply becomes:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r = \frac{\rho}{\pi}\int_{\Omega}L_i(x,\omega_i) \left(\omega_i \cdot \hat{n}\right) \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $L_r$ is the total reflected radiance.  If I assume that the radiant power of the light is constant across its entire surface (and thus across the entire solid angle it subtends) I can pull that out of the integral as well, leaving me with:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r = \frac{\rho}{\pi} L_i \int_{\Omega} \left(\omega_i \cdot \hat{n}\right) \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Given that the light is located directly above the point, along $\hat{n}$, then all of the light incident on $x$ is within $\delta$ of $\hat{n}$, where $\delta$ is the half the angular diameter of the light.  The angular diameter is defined as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\delta = \sin^{-1}\left(\frac{R}{d}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Therefore, our integral can be rewritten as:&#xD;&#xA;$$&#xD;&#xA;L_r = \frac{\rho}{\pi} L_i \int_0^{2\pi} \int_0^{\delta} \cos{\theta_i}\sin{\theta_i} \ d\theta d\phi&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;= \frac{\rho}{\pi} L_i \int_0^{2\pi} \left[\frac{-\cos^2{\theta}}{2}\right]_0^\delta  \ d\phi&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;= \frac{\rho}{\pi} L_i \left(\pi \sin^2\left(\sin^{-1}\frac{R}{d}\right)\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\boxed{L_r = \rho L_i \frac{R^2}{d^2}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This looks as though it could be right, but I'm not sure.  Now lets say I want to setup a monte carlo estimator:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;F = \int f(x) dx \Rightarrow F \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{p(x_i)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;For our particular problem here, that would look like this:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r \approx \frac{\rho}{\pi} \frac{1}{N} \sum_{i=1}^N \frac{L_i(\omega_i)\cos{\theta_i}}{p(\omega_i)} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If I uniformly sample $\omega_i$ from the hemisphere, then $p(\omega_i) = \frac{1}{2\pi}$ and so the estimator simplifies to:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r \approx 2\rho \frac{1}{N} \sum_{i=1}^N L_i(\omega_i)\cos{\theta_i} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If instead, I were to use importance sampling and directly sample the light, I would need a more complex $p(\omega_i)$.  My intuition tells me it should be 1 over the solid angle subtended by the light divided by $2\pi$ (the solid angle of the entire hemisphere):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) = \frac{1}{\Omega_{light} / 2\pi} = \frac{2\pi}{\Omega_{light}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $\Omega_{light}$ can be calculated using:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Omega_{light} = 2\pi\left(1 - \frac{\sqrt{d^2 - R^2}}{d}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;My rationale being, if every direction in the hemisphere is equally likely, then the probability of a ray hitting the light should be equal to the proportion of the hemisphere the light occupies.&#xD;&#xA;&#xD;&#xA;Introducing this to our monte carlo estimator gives us an importance sampled version written as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r \approx \frac{\rho}{\pi} \frac{\Omega_{light}}{2\pi} \frac{1}{N} \sum_{i=1}^N L_i(\omega_i)\cos{\theta_i} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Coding this up quickly, if I assume $\Phi = 100W$, $d = 100m$, $R = 10m$, $\rho = 0.4$, my analytical solution yields:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L = 1.0132\times10^{-4} \frac{W}{sr\cdot m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If I use the uniformly sampled monte carlo method with a million samples, I get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{uniform} = 1.0141\times10^{-4} \frac{W}{sr\cdot m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And if I use the importance sampled version, I get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{importance} = 1.6126\times10^{-5} \frac{W}{sr\cdot m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So $L_{uniform}$ matches the analytical solution to within only .09%.  So that gives me some confidence in both solutions.  However the estimate from importance sampling is off by a clean factor of $2\pi$:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1.0132\times10^{-4}}{1.6126\times10^{-5}} = 6.2832 \approx 2\pi&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I'm not entirely sure where I went wrong with my methods.  Further, I'm confused of what happens when the BRDF is not constant.  How is it possible to properly integrate this (either analytically or numerically) when your integral also depends on a BRDF that depends on $\omega_o$ and $\omega_i$ as well?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42778" PostHistoryTypeId="1" PostId="13924" RevisionGUID="bbf38e8d-a1e2-4f0f-bb14-df6355af86e2" CreationDate="2024-02-17T04:15:32.927" UserId="10932" Text="Evaluating the Rendering Equation by hand (simple case)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42779" PostHistoryTypeId="3" PostId="13924" RevisionGUID="bbf38e8d-a1e2-4f0f-bb14-df6355af86e2" CreationDate="2024-02-17T04:15:32.927" UserId="10932" Text="|raytracing|pathtracing|sampling|importance-sampling|monte-carlo|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42780" PostHistoryTypeId="5" PostId="13924" RevisionGUID="0d4efe1a-a3ce-4fc6-80bc-f4dffa0774ba" CreationDate="2024-02-17T04:21:40.857" UserId="10932" Comment="added 197 characters in body" Text="I'm trying to make intuitive sense of the rendering equation and so I'm trying to work out a trivial example by hand, though ultimately I'm just trying to understand how monte carlo importance sampling is applied.&#xD;&#xA;&#xD;&#xA;Lets ignore for emittance, and so the rendering equation is simply:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_o(x, \omega_o) = \int_{\Omega} f(x,\omega_o,\omega_i)L_i(x,\omega_i) \left(\omega_i \cdot \hat{n}\right) \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Now for my purposes, I'm considering a spherical light with a radius $R$ and a radiant power of $\Phi$, that is $d$ away from point $x$ directly along the surface normal vector $\hat{n}$.  I'm also assuming the BRDF is lambertian:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f_r = \frac{\rho}{\pi}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $\rho$ is the surface's albedo.  In this case, the integral simply becomes:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r = \frac{\rho}{\pi}\int_{\Omega}L_i(x,\omega_i) \left(\omega_i \cdot \hat{n}\right) \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $L_r$ is the total reflected radiance.  If I assume that the radiant power of the light is constant across its entire surface (and thus across the entire solid angle it subtends) I can pull that out of the integral as well, leaving me with:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r = \frac{\rho}{\pi} L_i \int_{\Omega} \left(\omega_i \cdot \hat{n}\right) \ d\omega_i&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Given that the light is located directly above the point, along $\hat{n}$, then all of the light incident on $x$ is within $\delta$ of $\hat{n}$, where $\delta$ is the half the angular diameter of the light.  The angular diameter is defined as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\delta = \sin^{-1}\left(\frac{R}{d}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Therefore, our integral can be rewritten as:&#xD;&#xA;$$&#xD;&#xA;L_r = \frac{\rho}{\pi} L_i \int_0^{2\pi} \int_0^{\delta} \cos{\theta_i}\sin{\theta_i} \ d\theta d\phi&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;= \frac{\rho}{\pi} L_i \int_0^{2\pi} \left[\frac{-\cos^2{\theta}}{2}\right]_0^\delta  \ d\phi&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;= \frac{\rho}{\pi} L_i \left(\pi \sin^2\left(\sin^{-1}\frac{R}{d}\right)\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\boxed{L_r = \rho L_i \frac{R^2}{d^2}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;This looks as though it could be right, but I'm not sure.  Now lets say I want to setup a monte carlo estimator:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;F = \int f(x) dx \Rightarrow F \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{p(x_i)}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;For our particular problem here, that would look like this:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r \approx \frac{\rho}{\pi} \frac{1}{N} \sum_{i=1}^N \frac{L_i(\omega_i)\cos{\theta_i}}{p(\omega_i)} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If I uniformly sample $\omega_i$ from the hemisphere, then $p(\omega_i) = \frac{1}{2\pi}$ and so the estimator simplifies to:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r \approx 2\rho \frac{1}{N} \sum_{i=1}^N L_i(\omega_i)\cos{\theta_i} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If instead, I were to use importance sampling and directly sample the light, I would need a more complex $p(\omega_i)$.  My intuition tells me it should be 1 over the solid angle subtended by the light divided by $2\pi$ (the solid angle of the entire hemisphere):&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) = \frac{1}{\Omega_{light} / 2\pi} = \frac{2\pi}{\Omega_{light}}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;where $\Omega_{light}$ can be calculated using:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\Omega_{light} = 2\pi\left(1 - \frac{\sqrt{d^2 - R^2}}{d}\right)&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;My rationale being, if every direction in the hemisphere is equally likely, then the probability of a ray hitting the light should be equal to the proportion of the hemisphere the light occupies.&#xD;&#xA;&#xD;&#xA;Introducing this to our monte carlo estimator gives us an importance sampled version written as:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_r \approx \frac{\rho}{\pi} \frac{\Omega_{light}}{2\pi} \frac{1}{N} \sum_{i=1}^N L_i(\omega_i)\cos{\theta_i} &#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;Coding this up quickly, if I assume $\Phi = 100W$, $d = 100m$, $R = 10m$, $\rho = 0.4$, my analytical solution yields:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L = 1.0132\times10^{-4} \frac{W}{sr\cdot m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;If I use the uniformly sampled monte carlo method with a million samples, I get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{uniform} = 1.0141\times10^{-4} \frac{W}{sr\cdot m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;And if I use the importance sampled version, I get:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;L_{importance} = 1.6126\times10^{-5} \frac{W}{sr\cdot m^2}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;So $L_{uniform}$ matches the analytical solution to within only .09%.  So that gives me some confidence in both solutions.  However the estimate from importance sampling is off by a clean factor of $2\pi$:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;\frac{1.0132\times10^{-4}}{1.6126\times10^{-5}} = 6.2832 \approx 2\pi&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;I'm not entirely sure where I went wrong with my methods.  This discrepancy, if not an issue in my derivation/integration, would imply that the probability is actually:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;p(\omega_i) = \frac{1}{\Omega}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;But I'm not sure how that makes sense.&#xD;&#xA;&#xD;&#xA;Further, I'm confused of what happens when the BRDF is not constant.  How is it possible to properly integrate this (either analytically or numerically) when your integral also depends on a BRDF that depends on $\omega_o$ and $\omega_i$ as well?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42781" PostHistoryTypeId="2" PostId="13925" RevisionGUID="c36d00ac-99a8-4c57-b195-76a3e00583a0" CreationDate="2024-02-17T09:07:50.143" UserId="10096" Text="**Probability Density Function**&#xD;&#xA;&#xD;&#xA;Say you want to uniformly generate directions only within $\theta \in [0,\delta)$. We know that the probability density w.r.t. the solid angle measure must be constant and integrate to one:&#xD;&#xA;$$1 = \int_{\Omega_{\delta}} p(\omega)\,d\omega = \int_{\Omega_{\delta}} C\,d\omega =\int_0^{2\pi} \int_0^{\delta} C \sin\theta\,d\theta\,d\phi = 2\pi (1-\cos\delta) C\implies C = \frac{1}{2\pi (1-\cos\delta)}.$$&#xD;&#xA;&#xD;&#xA;Using $\delta = \arcsin(R/d)$ and &#xD;&#xA;$$\cos\arcsin x= \sqrt{1-(\sin\arcsin x)^2} = \sqrt{1-x^2},$$ &#xD;&#xA;you get $\cos\arcsin \delta = \sqrt{1-R^2/d^2}$. Then your probability density function is:&#xD;&#xA;$$p(\omega) = \frac{1}{2\pi \left(1-\frac{\sqrt{d^2-R^2}}{d}\right)}.$$&#xD;&#xA;There is no $2\pi$ divided by it. For some reason you decided that the pdf is the ratio of the areas, but as you can see that is not the case. It is the reciprocal of the area in $[0,2\pi)\times [0,\delta)$. Note that in $2\pi (1-\cos\delta)$ if you set $\delta = \pi/2$ you will recover the area of the whole hemisphere.&#xD;&#xA;&#xD;&#xA;**Non-constant BRDF**&#xD;&#xA;&#xD;&#xA;Let's take some strange diffuse pdf that is easy to integrate: $f(\theta) = \frac{\alpha+2}{2\pi}\cos^{\alpha}\theta$ (for simplicitly $\alpha&gt;0$). You can now compute the integral explicitly:&#xD;&#xA;\begin{align}&#xD;&#xA;L_r(x,\omega_o) &amp;= \int_{\Omega} f(\theta) L_i(x,\theta) \cos\theta_i \,d\omega_i \\&#xD;&#xA;&amp;= L_e\int_0^{2\pi} \int_0^{\delta} \frac{\alpha+2}{2\pi}\cos^{\alpha+1}\theta_i \sin\theta_i \,d\theta_i \,d\phi_i \\&#xD;&#xA;&amp;= -(\alpha+2)L_e \int_0^{\delta}\cos^{\alpha+1}\theta_i \,d\cos\theta_i \\&#xD;&#xA;&amp;= -(\alpha+2)L_e \left[\frac{\cos^{\alpha+2}\theta_i}{\alpha+2}\right]^{\delta}_0 = L_e (\cos^{\alpha+2} 0 - \cos^{\alpha+2}\delta) \\&#xD;&#xA;&amp;= L_e(1-(1-\delta^2)^{\frac{\alpha}{2}+1})&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;**Numerical Integration**&#xD;&#xA;&#xD;&#xA;Numerically you can be as general as you like:&#xD;&#xA;$$L_r(x,\omega_o) = \int_{\Omega} f(\omega_o, x, \omega_i) L_i(x,\omega_i) \cos\theta_i\,d\omega_i \approx \frac{1}{N}\sum_{k=1}^N \frac{f(\omega_o, x, \omega_i^k) L_i(x,\omega^k_i)\cos\theta^k_i}{p(\omega_i^k)}.$$&#xD;&#xA;Here $\omega^k_i$ is the $k$-th sampled direction according to the pdf $p$, and $\cos\theta^k_i = N_x \cdot \omega_i^k$." ContentLicense="CC BY-SA 4.0" />
  <row Id="42783" PostHistoryTypeId="50" PostId="13484" RevisionGUID="49b2369b-93b1-4592-a787-a7b7a2dc1736" CreationDate="2024-02-17T14:06:00.707" UserId="-1" />
  <row Id="42784" PostHistoryTypeId="5" PostId="13925" RevisionGUID="5a68fa59-98c9-4c0f-9870-0f56420894d3" CreationDate="2024-02-17T18:03:23.707" UserId="10096" Comment="deleted 1 character in body" Text="**Probability Density Function**&#xD;&#xA;&#xD;&#xA;Say you want to uniformly generate directions only within $\theta \in [0,\delta)$. We know that the probability density w.r.t. the solid angle measure must be constant and integrate to one:&#xD;&#xA;$$1 = \int_{\Omega_{\delta}} p(\omega)\,d\omega = \int_{\Omega_{\delta}} C\,d\omega =\int_0^{2\pi} \int_0^{\delta} C \sin\theta\,d\theta\,d\phi = 2\pi (1-\cos\delta) C\implies C = \frac{1}{2\pi (1-\cos\delta)}.$$&#xD;&#xA;&#xD;&#xA;Using $\delta = \arcsin(R/d)$ and &#xD;&#xA;$$\cos\arcsin x= \sqrt{1-(\sin\arcsin x)^2} = \sqrt{1-x^2},$$ &#xD;&#xA;you get $\cos\arcsin \delta = \sqrt{1-R^2/d^2}$. Then your probability density function is:&#xD;&#xA;$$p(\omega) = \frac{1}{2\pi \left(1-\frac{\sqrt{d^2-R^2}}{d}\right)}.$$&#xD;&#xA;There is no $2\pi$ divided by it. For some reason you decided that the pdf is the ratio of the areas, but as you can see that is not the case. It is the reciprocal of the area in $[0,2\pi)\times [0,\delta)$. Note that in $2\pi (1-\cos\delta)$ if you set $\delta = \pi/2$ you will recover the area of the whole hemisphere.&#xD;&#xA;&#xD;&#xA;**Non-constant BRDF**&#xD;&#xA;&#xD;&#xA;Let's take some strange diffuse pdf that is easy to integrate: $f(\theta) = \frac{\alpha+2}{2\pi}\cos^{\alpha}\theta$ (for simplicitly $\alpha&gt;0$). You can now compute the integral explicitly:&#xD;&#xA;\begin{align}&#xD;&#xA;L_r(x,\omega_o) &amp;= \int_{\Omega} f(\theta) L_i(x,\theta) \cos\theta_i \,d\omega_i \\&#xD;&#xA;&amp;= L_e\int_0^{2\pi} \int_0^{\delta} \frac{\alpha+2}{2\pi}\cos^{\alpha+1}\theta_i \sin\theta_i \,d\theta_i \,d\phi_i \\&#xD;&#xA;&amp;= -(\alpha+2)L_e \int_0^{\delta}\cos^{\alpha+1}\theta_i \,d\cos\theta_i \\&#xD;&#xA;&amp;= -(\alpha+2)L_e \left[\frac{\cos^{\alpha+2}\theta_i}{\alpha+2}\right]^{\delta}_0 = L_e (\cos^{\alpha+2} 0 - \cos^{\alpha+2}\delta) \\&#xD;&#xA;&amp;= L_e(1-(1-R^2/d^2)^{\frac{\alpha}{2}+1})&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;**Numerical Integration**&#xD;&#xA;&#xD;&#xA;Numerically you can be as general as you like:&#xD;&#xA;$$L_r(x,\omega_o) = \int_{\Omega} f(\omega_o, x, \omega_i) L_i(x,\omega_i) \cos\theta_i\,d\omega_i \approx \frac{1}{N}\sum_{k=1}^N \frac{f(\omega_o, x, \omega_i^k) L_i(x,\omega^k_i)\cos\theta^k_i}{p(\omega_i^k)}.$$&#xD;&#xA;Here $\omega^k_i$ is the $k$-th sampled direction according to the pdf $p$, and $\cos\theta^k_i = N_x \cdot \omega_i^k$." ContentLicense="CC BY-SA 4.0" />
  <row Id="42785" PostHistoryTypeId="5" PostId="13925" RevisionGUID="f7fd5a99-765f-4f1a-af64-de94f4a7e55e" CreationDate="2024-02-17T22:04:12.930" UserId="10096" Comment="added 1 character in body" Text="**Probability Density Function**&#xD;&#xA;&#xD;&#xA;Say you want to uniformly generate directions only within $\theta \in [0,\delta)$. We know that the probability density w.r.t. the solid angle measure must be constant and integrate to one:&#xD;&#xA;$$1 = \int_{\Omega_{\delta}} p(\omega)\,d\omega = \int_{\Omega_{\delta}} C\,d\omega =\int_0^{2\pi} \int_0^{\delta} C \sin\theta\,d\theta\,d\phi = 2\pi (1-\cos\delta) C\implies C = \frac{1}{2\pi (1-\cos\delta)}.$$&#xD;&#xA;&#xD;&#xA;Using $\delta = \arcsin(R/d)$ and &#xD;&#xA;$$\cos\arcsin x= \sqrt{1-(\sin\arcsin x)^2} = \sqrt{1-x^2},$$ &#xD;&#xA;you get $\cos\arcsin \delta = \sqrt{1-R^2/d^2}$. Then your probability density function is:&#xD;&#xA;$$p(\omega) = \frac{1}{2\pi \left(1-\frac{\sqrt{d^2-R^2}}{d}\right)}.$$&#xD;&#xA;There is no $2\pi$ divided by it. For some reason you decided that the pdf is the ratio of the areas, but as you can see that is not the case. It is the reciprocal of the area in $[0,2\pi)\times [0,\delta)$. Note that in $2\pi (1-\cos\delta)$ if you set $\delta = \pi/2$ you will recover the area of the whole hemisphere.&#xD;&#xA;&#xD;&#xA;**Non-constant BRDF**&#xD;&#xA;&#xD;&#xA;Let's take some strange diffuse brdf that is easy to integrate: $f(\theta) = \frac{\alpha+2}{2\pi}\cos^{\alpha}\theta$ (for simplicitly $\alpha&gt;0$). You can now compute the integral explicitly:&#xD;&#xA;\begin{align}&#xD;&#xA;L_r(x,\omega_o) &amp;= \int_{\Omega} f(\theta) L_i(x,\theta) \cos\theta_i \,d\omega_i \\&#xD;&#xA;&amp;= L_e\int_0^{2\pi} \int_0^{\delta} \frac{\alpha+2}{2\pi}\cos^{\alpha+1}\theta_i \sin\theta_i \,d\theta_i \,d\phi_i \\&#xD;&#xA;&amp;= -(\alpha+2)L_e \int_0^{\delta}\cos^{\alpha+1}\theta_i \,d\cos\theta_i \\&#xD;&#xA;&amp;= -(\alpha+2)L_e \left[\frac{\cos^{\alpha+2}\theta_i}{\alpha+2}\right]^{\delta}_0 = L_e (\cos^{\alpha+2} 0 - \cos^{\alpha+2}\delta) \\&#xD;&#xA;&amp;= L_e(1-(1-R^2/d^2)^{\frac{\alpha}{2}+1})&#xD;&#xA;\end{align}&#xD;&#xA;&#xD;&#xA;**Numerical Integration**&#xD;&#xA;&#xD;&#xA;Numerically you can be as general as you like:&#xD;&#xA;$$L_r(x,\omega_o) = \int_{\Omega} f(\omega_o, x, \omega_i) L_i(x,\omega_i) \cos\theta_i\,d\omega_i \approx \frac{1}{N}\sum_{k=1}^N \frac{f(\omega_o, x, \omega_i^k) L_i(x,\omega^k_i)\cos\theta^k_i}{p(\omega_i^k)}.$$&#xD;&#xA;Here $\omega^k_i$ is the $k$-th sampled direction according to the pdf $p$, and $\cos\theta^k_i = N_x \cdot \omega_i^k$." ContentLicense="CC BY-SA 4.0" />
  <row Id="42786" PostHistoryTypeId="2" PostId="13926" RevisionGUID="4717129f-f6a6-46e9-b50f-a137f6aacf57" CreationDate="2024-02-18T03:00:17.087" UserId="10932" Text="Through reading various sources online, I've become a bit confused.  I'll briefly outline what I think I *do* understand:&#xD;&#xA;&#xD;&#xA;My understanding is that microfacet-based BRDFs assume there is always a perfect reflection, but the true microscopic normal changes according to some Normal Distribution Function (NDF), resulting in a non-perfect macroscopic reflection.  When ray tracing, you sample this NDF to generate a &quot;true&quot; normal, and then you can compute a bounce ray using your incident ray, and a specular reflection with your &quot;true&quot; normal.&#xD;&#xA;&#xD;&#xA;My confusion comes from a few things:&#xD;&#xA;&#xD;&#xA;1. What is the reason that some microfacet-based BRDFs are diffuse only (such as Oren-Nayar) or specular only (such as Cook-Torrance)?  My assumption would be that if a roughness value of 0 were used, all of the normals should align and thus you would get a purely specular reflection.  Similarly, if a roughness value of 1 was used, the normals would be all scattered, and you'd obtain a more diffuse reflection.  Yet, Wikipedia states for the [Oren-Nayar model](https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model#:~:text=thus%20the%20Oren%2DNayar%20model%20simplifies%20to%20the%20Lambertian%20model%3A): **&quot;In the case of $\sigma = 0$ (i.e., all facets in the same plane), and thus the Oren-Nayar model simplifies to the Lambertian model&quot;**  If all of the microfacets align to the same plane, how could the computed reflection still be diffuse?  What happens when I sample a bounce ray, as surely if the normals are all aligned, the sampled ray should be specular?&#xD;&#xA;&#xD;&#xA;2. If Oren-Nayar is a BRDF, and Cook-Torrance is a BRDF, but you need both to fully represent a single material's diffuse and specular components, is the combination of them also a BRDF?  Is combining simple BRDFs that capture only a single aspect of reflection how you create a full PBR BRDF?  (Looking at the [OpenPBR](https://academysoftwarefoundation.github.io/OpenPBR/#model) white-paper, it seems that a single material is defined as a mixing of multiple simpler BRDFs)&#xD;&#xA;&#xD;&#xA;3. If you require multiple BRDFs to describe a single material, do they share the same NDF?  When path tracing, how do you sample a bounce ray?  If you are always simply performing a specular reflection on some sampled normal, how would you importance sample a BRDF or a light source?&#xD;&#xA;&#xD;&#xA;I think I am getting confused by the fundamental difference between a BRDF and an NDF, and the roles they play." ContentLicense="CC BY-SA 4.0" />
  <row Id="42788" PostHistoryTypeId="1" PostId="13926" RevisionGUID="4717129f-f6a6-46e9-b50f-a137f6aacf57" CreationDate="2024-02-18T03:00:17.087" UserId="10932" Text="Confusion over Microfacet-based BRDFs and Normal Distribution Functions" ContentLicense="CC BY-SA 4.0" />
  <row Id="42789" PostHistoryTypeId="3" PostId="13926" RevisionGUID="4717129f-f6a6-46e9-b50f-a137f6aacf57" CreationDate="2024-02-18T03:00:17.087" UserId="10932" Text="|brdf|pbr|specular|diffuse|ndf|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42790" PostHistoryTypeId="2" PostId="13927" RevisionGUID="f2a8ddd0-5fb5-4971-9dda-44d3cf3fe7af" CreationDate="2024-02-18T03:36:28.343" UserId="19537" Text="Actually, the confusion of yours mainly results from:&#xD;&#xA;&#xD;&#xA;&gt; My understanding is that microfacet-based BRDFs assume there is always **a perfect reflection**, but the true microscopic normal changes according to some Normal Distribution Function (NDF), resulting in a non-perfect macroscopic reflection.&#xD;&#xA;&#xD;&#xA;, which is NOT the case. There are two types of microfacet BSDF mainly:&#xD;&#xA;&#xD;&#xA;- Physically-based glossy (specular) material: each microfacet represents a infinitesimal specular mirror and **there is always a perfect reflection**. For example, Cook-Torrance is one of the representative models of this category.&#xD;&#xA;- Physically-based diffuse material: instead of modeling every infinitesimal facet as mirrors, this material assumes that they all have Lambertian reflection. It is known that Lambertian BRDF is empirical, so when representing diffuse object, object parts where the normals face away from the viewing direction appears to be dimmer, which is not realistic enough. Models like Oren-Nayar **model each microfacet as perfect Lambertian diffusers** and achieved more photo-realistic renderings.&#xD;&#xA;&#xD;&#xA;Therefore, I think all of your confusions can be resolved:&#xD;&#xA;&#xD;&#xA;(1) when all the normals are aligned, the surface properties depend on whether each microfacet is modeled to be mirror-specular or diffuse. &#xD;&#xA;&#xD;&#xA;(2) Yes, mixture BSDFs can be seen in various renderers such as Mitsuba. However, in terms of *combining simple BSDFs*... it depends on what *simple* means to you. Some appearance are extremely difficult to model, for example: substrate (coated) materials, which needs more than simple surface reflection/refraction model. You can refer to the mitsuba documentation for more examples. &#xD;&#xA;&#xD;&#xA;(3) They can or can not share the same NDF. It is implementation-dependent. You already know that different microfacet models can be modeled entirely different, so we should make NDFs of theirs independent. Or, when you want to conserve memory (in a weird way), you can make them all-coupled. To sample a ray in these BSDF, you can simply sample the BSDF to use as a first step, then sample the sampled BSDF as the second step. So, different sampled BSDF will yield different normal for you to use." ContentLicense="CC BY-SA 4.0" />
  <row Id="42792" PostHistoryTypeId="5" PostId="13926" RevisionGUID="6bb0709d-cdb2-4ab7-b762-96da8f82a9a8" CreationDate="2024-02-18T03:59:48.580" UserId="10932" Comment="added 452 characters in body" Text="Through reading various sources online, I've become a bit confused.  I'll briefly outline what I think I *do* understand:&#xD;&#xA;&#xD;&#xA;My understanding is that microfacet-based BRDFs assume there is always a perfect reflection, but the true microscopic normal changes according to some Normal Distribution Function (NDF), resulting in a non-perfect macroscopic reflection.  When ray tracing, you sample this NDF to generate a &quot;true&quot; normal, and then you can compute a bounce ray using your incident ray, and a specular reflection with your &quot;true&quot; normal.&#xD;&#xA;&#xD;&#xA;My confusion comes from a few things:&#xD;&#xA;&#xD;&#xA;1. What is the reason that some microfacet-based BRDFs are diffuse only (such as Oren-Nayar) or specular only (such as Cook-Torrance)?  My assumption would be that if a roughness value of 0 were used, all of the normals should align and thus you would get a purely specular reflection.  Similarly, if a roughness value of 1 was used, the normals would be all scattered, and you'd obtain a more diffuse reflection.  Yet, Wikipedia states for the [Oren-Nayar model](https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model#:~:text=thus%20the%20Oren%2DNayar%20model%20simplifies%20to%20the%20Lambertian%20model%3A): **&quot;In the case of $\sigma = 0$ (i.e., all facets in the same plane), and thus the Oren-Nayar model simplifies to the Lambertian model&quot;**  If all of the microfacets align to the same plane, how could the computed reflection still be diffuse?  What happens when I sample a bounce ray, as surely if the normals are all aligned, the sampled ray should be specular?&#xD;&#xA;&#xD;&#xA;2. If Oren-Nayar is a BRDF, and Cook-Torrance is a BRDF, but you need both to fully represent a single material's diffuse and specular components, is the combination of them also a BRDF?  Is combining simple BRDFs that capture only a single aspect of reflection how you create a full PBR BRDF?  (Looking at the [OpenPBR](https://academysoftwarefoundation.github.io/OpenPBR/#model) white-paper, it seems that a single material is defined as a mixing of multiple simpler BRDFs)&#xD;&#xA;&#xD;&#xA;3. If you require multiple BRDFs to describe a single material, do they share the same NDF?  When path tracing, how do you sample a bounce ray?  If you are always simply performing a specular reflection on some sampled normal, how would you importance sample a BRDF or a light source?&#xD;&#xA;&#xD;&#xA;I think I am getting confused by the fundamental difference between a BRDF and an NDF, and the roles they play.&#xD;&#xA;&#xD;&#xA;# Edit:&#xD;&#xA;Someone has pointed out that microfacet-models don't *all* assume that reflections are specular, some (like Oren-Nayar) assume they are lambertian.  But it still seems like a collection of misaligned specularly reflecting microfacets would produce a diffuse effect (where, as roughness increases, you'd slowly transition from a perfect mirror, through glossy &quot;soft&quot; reflections, to diffuse).  So why is a separate diffuse component needed?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42793" PostHistoryTypeId="5" PostId="13926" RevisionGUID="97cf4aa1-2619-4db9-8976-5421a6fe3406" CreationDate="2024-02-18T04:08:31.753" UserId="10932" Comment="added 452 characters in body" Text="Through reading various sources online, I've become a bit confused.  I'll briefly outline what I think I *do* understand:&#xD;&#xA;&#xD;&#xA;My understanding is that microfacet-based BRDFs assume there is always a perfect reflection, but the true microscopic normal changes according to some Normal Distribution Function (NDF), resulting in a non-perfect macroscopic reflection.  When ray tracing, you sample this NDF to generate a &quot;true&quot; normal, and then you can compute a bounce ray using your incident ray, and a specular reflection with your &quot;true&quot; normal.&#xD;&#xA;&#xD;&#xA;My confusion comes from a few things:&#xD;&#xA;&#xD;&#xA;1. What is the reason that some microfacet-based BRDFs are diffuse only (such as Oren-Nayar) or specular only (such as Cook-Torrance)?  My assumption would be that if a roughness value of 0 were used, all of the normals should align and thus you would get a purely specular reflection.  Similarly, if a roughness value of 1 was used, the normals would be all scattered, and you'd obtain a more diffuse reflection.  Yet, Wikipedia states for the [Oren-Nayar model](https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model#:~:text=thus%20the%20Oren%2DNayar%20model%20simplifies%20to%20the%20Lambertian%20model%3A): **&quot;In the case of $\sigma = 0$ (i.e., all facets in the same plane), and thus the Oren-Nayar model simplifies to the Lambertian model&quot;**  If all of the microfacets align to the same plane, how could the computed reflection still be diffuse?  What happens when I sample a bounce ray, as surely if the normals are all aligned, the sampled ray should be specular?&#xD;&#xA;&#xD;&#xA;2. If Oren-Nayar is a BRDF, and Cook-Torrance is a BRDF, but you need both to fully represent a single material's diffuse and specular components, is the combination of them also a BRDF?  Is combining simple BRDFs that capture only a single aspect of reflection how you create a full PBR BRDF?  (Looking at the [OpenPBR](https://academysoftwarefoundation.github.io/OpenPBR/#model) white-paper, it seems that a single material is defined as a mixing of multiple simpler BRDFs)&#xD;&#xA;&#xD;&#xA;3. If you require multiple BRDFs to describe a single material, do they share the same NDF?  When path tracing, how do you sample a bounce ray?  If you are always simply performing a specular reflection on some sampled normal, how would you importance sample a BRDF or a light source?&#xD;&#xA;&#xD;&#xA;I think I am getting confused by the fundamental difference between a BRDF and an NDF, and the roles they play.&#xD;&#xA;&#xD;&#xA;# Edit:&#xD;&#xA;Someone has pointed out that microfacet-models don't *all* assume that reflections are specular, some (like Oren-Nayar) assume they are lambertian.  But it still seems like a collection of misaligned specularly reflecting microfacets would produce a diffuse effect (where, as roughness increases, you'd slowly transition from a perfect mirror, through glossy &quot;soft&quot; reflections, to diffuse).  So why is a separate diffuse component needed?  What is the conceptual reason for the distinction?&#xD;&#xA;&#xD;&#xA;I have seen it said many times, that in reality *all* reflections, at the smallest scale, are only specular.  Is it that Cook-Torrance is modeling each microfacet as a perfectly smooth mirror, but Oren-Nayar is modeling each microfacet as *itself* being composed of much smaller microfacets exhibiting diffuse behavior?&#xD;&#xA;&#xD;&#xA;I'm still struggling to understand why both components are needed separately, and how a bounce ray is actually to be sampled.  What does a roughness value even mean then, if a perfectly smooth surface still has a diffuse component from the Oren-Nayar model?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42794" PostHistoryTypeId="5" PostId="13926" RevisionGUID="91fc7b4e-2e87-4e91-a5f7-0fa4767f6de1" CreationDate="2024-02-18T06:35:30.893" UserId="10932" Comment="added 1694 characters in body" Text="Through reading various sources online, I've become a bit confused.  I'll briefly outline what I think I *do* understand:&#xD;&#xA;&#xD;&#xA;My understanding is that microfacet-based BRDFs assume there is always a perfect reflection, but the true microscopic normal changes according to some Normal Distribution Function (NDF), resulting in a non-perfect macroscopic reflection.  When ray tracing, you sample this NDF to generate a &quot;true&quot; normal, and then you can compute a bounce ray using your incident ray, and a specular reflection with your &quot;true&quot; normal.&#xD;&#xA;&#xD;&#xA;My confusion comes from a few things:&#xD;&#xA;&#xD;&#xA;1. What is the reason that some microfacet-based BRDFs are diffuse only (such as Oren-Nayar) or specular only (such as Cook-Torrance)?  My assumption would be that if a roughness value of 0 were used, all of the normals should align and thus you would get a purely specular reflection.  Similarly, if a roughness value of 1 was used, the normals would be all scattered, and you'd obtain a more diffuse reflection.  Yet, Wikipedia states for the [Oren-Nayar model](https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model#:~:text=thus%20the%20Oren%2DNayar%20model%20simplifies%20to%20the%20Lambertian%20model%3A): **&quot;In the case of $\sigma = 0$ (i.e., all facets in the same plane), and thus the Oren-Nayar model simplifies to the Lambertian model&quot;**  If all of the microfacets align to the same plane, how could the computed reflection still be diffuse?  What happens when I sample a bounce ray, as surely if the normals are all aligned, the sampled ray should be specular?&#xD;&#xA;&#xD;&#xA;2. If Oren-Nayar is a BRDF, and Cook-Torrance is a BRDF, but you need both to fully represent a single material's diffuse and specular components, is the combination of them also a BRDF?  Is combining simple BRDFs that capture only a single aspect of reflection how you create a full PBR BRDF?  (Looking at the [OpenPBR](https://academysoftwarefoundation.github.io/OpenPBR/#model) white-paper, it seems that a single material is defined as a mixing of multiple simpler BRDFs)&#xD;&#xA;&#xD;&#xA;3. If you require multiple BRDFs to describe a single material, do they share the same NDF?  When path tracing, how do you sample a bounce ray?  If you are always simply performing a specular reflection on some sampled normal, how would you importance sample a BRDF or a light source?&#xD;&#xA;&#xD;&#xA;I think I am getting confused by the fundamental difference between a BRDF and an NDF, and the roles they play.&#xD;&#xA;&#xD;&#xA;# Edit:&#xD;&#xA;Someone has pointed out that microfacet-models don't *all* assume that reflections are specular, some (like Oren-Nayar) assume they are lambertian.  But it still seems like a collection of misaligned specularly reflecting microfacets would produce a diffuse effect (where, as roughness increases, you'd slowly transition from a perfect mirror, through glossy &quot;soft&quot; reflections, to diffuse).  So why is a separate diffuse component needed?  What is the conceptual reason for the distinction?&#xD;&#xA;&#xD;&#xA;I have seen it said many times, that in reality *all* reflections, at the smallest scale, are only specular.  Is it that Cook-Torrance is modeling each microfacet as a perfectly smooth mirror, but Oren-Nayar is modeling each microfacet as *itself* being composed of much smaller microfacets exhibiting diffuse behavior?&#xD;&#xA;&#xD;&#xA;I'm still struggling to understand why both components are needed separately, and how a bounce ray is actually to be sampled.  What does a roughness value even mean then, if a perfectly smooth surface still has a diffuse component from the Oren-Nayar model?&#xD;&#xA;&#xD;&#xA;# Edit 2:&#xD;&#xA;&#xD;&#xA;After reading some more on the fresnel effect, as well as [this answer on another question](https://computergraphics.stackexchange.com/questions/13862/how-to-approach-implementing-cook-torrence-microfacet-brdf/13863?fbclid=IwAR0vOe7dNcBrcgxif-hZP7aWSP0AAp-Y8uIp5_LgN39mS13D-hQfirItqnU#13863), I believe I understand what is happening now.&#xD;&#xA;&#xD;&#xA;The Fresnel equations describe the reflection and transmission of light when it is incident on an interface between two different mediums.  It tells us how much of the light is transmitted into the new medium, and how much is reflected away.  The reflection is *always* specular, but can appear more or less diffuse based on how well-aligned the microfacets are (e.g. how rough the surface is).  The refracted ray that is transmitted into the material, if the material is opaque, quickly interacts with the internal structure and is reflected back out in a different direction, hence appearing diffuse.  But *this is separate from the diffuse nature caused by the microfacets on the surface*.  A colleague of mine included this diagram in his dissertation:&#xD;&#xA;&#xD;&#xA;[![reflection][1]][1]&#xD;&#xA;&#xD;&#xA;(It isn't 100% clear to me how it differs from subsurface scattering.  Perhaps, the only difference is the depth the rays are able to penetrate?)&#xD;&#xA;&#xD;&#xA;So when we write the BRDF like this:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f(\omega) = \biggl((1 - F)K_df_{\text{Lambert}}(\omega) + FK_sf_{\text{C-T}}(\omega) \biggr)\cos\theta&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;we're using the Fresnel equations to tell us how much light is going to be reflected off the surface (specularly, off the microfacet structure).  The remainder of the light ($1-F$) is transmitted into the structure but then quickly reflected back out diffusely.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v3ryk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42795" PostHistoryTypeId="5" PostId="13926" RevisionGUID="3cb61672-ab30-43e9-a419-cca582e80404" CreationDate="2024-02-18T07:06:47.680" UserId="10932" Comment="deleted 6 characters in body" Text="Through reading various sources online, I've become a bit confused.  I'll briefly outline what I think I *do* understand:&#xD;&#xA;&#xD;&#xA;My understanding is that microfacet-based BRDFs assume there is always a perfect reflection, but the true microscopic normal changes according to some Normal Distribution Function (NDF), resulting in a non-perfect macroscopic reflection.  When ray tracing, you sample this NDF to generate a &quot;true&quot; normal, and then you can compute a bounce ray using your incident ray, and a specular reflection with your &quot;true&quot; normal.&#xD;&#xA;&#xD;&#xA;My confusion comes from a few things:&#xD;&#xA;&#xD;&#xA;1. What is the reason that some microfacet-based BRDFs are diffuse only (such as Oren-Nayar) or specular only (such as Cook-Torrance)?  My assumption would be that if a roughness value of 0 were used, all of the normals should align and thus you would get a purely specular reflection.  Similarly, if a roughness value of 1 was used, the normals would be all scattered, and you'd obtain a more diffuse reflection.  Yet, Wikipedia states for the [Oren-Nayar model](https://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model#:~:text=thus%20the%20Oren%2DNayar%20model%20simplifies%20to%20the%20Lambertian%20model%3A): **&quot;In the case of $\sigma = 0$ (i.e., all facets in the same plane), and thus the Oren-Nayar model simplifies to the Lambertian model&quot;**  If all of the microfacets align to the same plane, how could the computed reflection still be diffuse?  What happens when I sample a bounce ray, as surely if the normals are all aligned, the sampled ray should be specular?&#xD;&#xA;&#xD;&#xA;2. If Oren-Nayar is a BRDF, and Cook-Torrance is a BRDF, but you need both to fully represent a single material's diffuse and specular components, is the combination of them also a BRDF?  Is combining simple BRDFs that capture only a single aspect of reflection how you create a full PBR BRDF?  (Looking at the [OpenPBR](https://academysoftwarefoundation.github.io/OpenPBR/#model) white-paper, it seems that a single material is defined as a mixing of multiple simpler BRDFs)&#xD;&#xA;&#xD;&#xA;3. If you require multiple BRDFs to describe a single material, do they share the same NDF?  When path tracing, how do you sample a bounce ray?  If you are always simply performing a specular reflection on some sampled normal, how would you importance sample a BRDF or a light source?&#xD;&#xA;&#xD;&#xA;I think I am getting confused by the fundamental difference between a BRDF and an NDF, and the roles they play.&#xD;&#xA;&#xD;&#xA;# Edit:&#xD;&#xA;Someone has pointed out that microfacet-models don't *all* assume that reflections are specular, some (like Oren-Nayar) assume they are lambertian.  But it still seems like a collection of misaligned specularly reflecting microfacets would produce a diffuse effect (where, as roughness increases, you'd slowly transition from a perfect mirror, through glossy &quot;soft&quot; reflections, to diffuse).  So why is a separate diffuse component needed?  What is the conceptual reason for the distinction?&#xD;&#xA;&#xD;&#xA;I have seen it said many times, that in reality *all* reflections, at the smallest scale, are only specular.  Is it that Cook-Torrance is modeling each microfacet as a perfectly smooth mirror, but Oren-Nayar is modeling each microfacet as *itself* being composed of much smaller microfacets exhibiting diffuse behavior?&#xD;&#xA;&#xD;&#xA;I'm still struggling to understand why both components are needed separately, and how a bounce ray is actually to be sampled.  What does a roughness value even mean then, if a perfectly smooth surface still has a diffuse component from the Oren-Nayar model?&#xD;&#xA;&#xD;&#xA;# Edit 2:&#xD;&#xA;&#xD;&#xA;After reading some more on the fresnel effect, as well as [this answer on another question](https://computergraphics.stackexchange.com/questions/13862/how-to-approach-implementing-cook-torrence-microfacet-brdf/13863?fbclid=IwAR0vOe7dNcBrcgxif-hZP7aWSP0AAp-Y8uIp5_LgN39mS13D-hQfirItqnU#13863), I believe I understand what is happening now.&#xD;&#xA;&#xD;&#xA;The Fresnel equations describe the reflection and transmission of light when it is incident on an interface between two different mediums.  It tells us how much of the light is transmitted into the new medium, and how much is reflected away.  The reflection is *always* specular, but can appear more or less diffuse based on how well-aligned the microfacets are (e.g. how rough the surface is).  The refracted ray that is transmitted into the material, if the material is opaque, quickly interacts with the internal structure and is reflected back out in a different direction, hence appearing diffuse.  But *this is separate from the diffuse nature caused by the microfacets on the surface*.  A colleague of mine included this diagram in his dissertation:&#xD;&#xA;&#xD;&#xA;[![reflection][1]][1]&#xD;&#xA;&#xD;&#xA;(It isn't 100% clear to me how it differs from subsurface scattering.  Perhaps, the only difference is the depth the rays are able to penetrate?)&#xD;&#xA;&#xD;&#xA;So when we write the BRDF like this:&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;f(\omega) = \biggl((1 - F)f_{\text{Lambert}}(\omega) + Ff_{\text{C-T}}(\omega) \biggr)\cos\theta&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;we're using the Fresnel equations to tell us how much light is going to be reflected off the surface (specularly, off the microfacet structure).  The remainder of the light ($1-F$) is transmitted into the structure but then quickly reflected back out diffusely.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/v3ryk.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42796" PostHistoryTypeId="52" PostId="13926" RevisionGUID="dc6018fb-42f6-45a7-828f-954b62d76c5d" CreationDate="2024-02-18T11:00:27.583" />
  <row Id="42797" PostHistoryTypeId="50" PostId="10619" RevisionGUID="73e5d62c-7763-4215-b0cc-1f829c3db58e" CreationDate="2024-02-18T20:07:30.880" UserId="-1" />
  <row Id="42798" PostHistoryTypeId="2" PostId="13928" RevisionGUID="aa09be38-06fb-45bd-bb6f-8d0bc29ce849" CreationDate="2024-02-19T13:38:58.087" UserId="7008" Text="I have an OptiX ray tracer and a Vulkan renderer. In Vulkan, so far I have only been displaying the image the ray tracer created.&#xD;&#xA;Now I want to add rendering in the Vulkan renderer.&#xD;&#xA;&#xD;&#xA;For the interop, I created a VkImage with linear tiling, such that I can write to the image's buffer in OptiX. This works fine, but I cannot change the linear tiling (I believe), as otherwise OptiX would probably write garbage (or rather Vulkan would interpret garbage from the OptiX buffer writing).&#xD;&#xA;&#xD;&#xA;Currently I want to add drawing lines in Vulkan, so my approach was: Use the image shared between OptiX and Vulkan as a framebuffer and render lines to it with a new graphics pipeline.&#xD;&#xA;However, this requires the image to have usage `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT`. This is prohibited when having a linear tiling image in the specs, the validation layers tell me as much.&#xD;&#xA;&#xD;&#xA;Now there is this NVidia extension about having a linear color attachment: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_NV_linear_color_attachment.html&#xD;&#xA;So this looks like a solution to me. But I can't get it to work.&#xD;&#xA;&#xD;&#xA;My image's format is `VK_FORMAT_R32G32B32A32_SFLOAT`. I have queried support: &#xD;&#xA;&#xD;&#xA;    VkFormatProperties3 formatProperties3{};&#xD;&#xA;    formatProperties3.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3;&#xD;&#xA;    VkFormatProperties2 formatProperties2{};&#xD;&#xA;    formatProperties2.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;&#xD;&#xA;    formatProperties2.pNext = &amp;formatProperties3;&#xD;&#xA;&#xD;&#xA;    vkGetPhysicalDeviceFormatProperties2(Device-&gt;PhysicalDevice,&#xD;&#xA;	VK_FORMAT_R32G32B32A32_SFLOAT, &amp;formatProperties2);&#xD;&#xA;&#xD;&#xA;    if (formatProperties3.linearTilingFeatures &amp;     &#xD;&#xA;        VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV)&#xD;&#xA;    {&#xD;&#xA;	    // this is reached, so is supported&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;I have also set the device feature when creating the logical device:&#xD;&#xA;&#xD;&#xA;    physicalDeviceFeatures.pNext = &amp;otherFeature;&#xD;&#xA;&#xD;&#xA;    VkPhysicalDeviceLinearColorAttachmentFeaturesNV linearColorAttachmentFeature{};&#xD;&#xA;    linearColorAttachmentFeature.sType =&#xD;&#xA;	    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV;&#xD;&#xA;    otherFeature.pNext = &amp;linearColorAttachmentFeature;&#xD;&#xA;    vkGetPhysicalDeviceFeatures2(Device-&gt;PhysicalDevice, &amp;physicalDeviceFeatures);&#xD;&#xA;&#xD;&#xA;    vkGetPhysicalDeviceFeatures2(physicalDevice, &amp;physicalDeviceFeatures);&#xD;&#xA;&#xD;&#xA;    VkDeviceCreateInfo createInfo{};&#xD;&#xA;    createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;&#xD;&#xA;    // ...&#xD;&#xA;    createInfo.pNext = &amp;physicalDeviceFeatures;&#xD;&#xA;    VkResult result = vkCreateDevice(physicalDevice, &amp;createInfo, nullptr, &amp;device);&#xD;&#xA;&#xD;&#xA;From what I understand, this should already enable using a linear tiling image with color attachment bit. However, when I create the image view, I still get the following error in my validation layers:&#xD;&#xA;&#xD;&#xA;&gt; Validation Layer(ERROR):        Validation Error: [ VUID-VkImageViewCreateInfo-usage-02276 ] Object 0: handle = 0xf443490000000006, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x27cb6471 | vkCreateImageView(): pCreateInfo-&gt;format VK_FORMAT_R32G32B32A32_SFLOAT with tiling VK_IMAGE_TILING_LINEAR does not support usage that includes VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. The Vulkan spec states: If usage contains VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, then the image view's format features must contain VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT (https://vulkan.lunarg.com/doc/view/1.3.250.1/windows/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-usage-02276)&#xD;&#xA;&#xD;&#xA;Therefore the question: How to use the linear color attachment extension for NVidia?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42800" PostHistoryTypeId="1" PostId="13928" RevisionGUID="aa09be38-06fb-45bd-bb6f-8d0bc29ce849" CreationDate="2024-02-19T13:38:58.087" UserId="7008" Text="How to use linear color attachment with NV extension in vulkan?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42801" PostHistoryTypeId="3" PostId="13928" RevisionGUID="aa09be38-06fb-45bd-bb6f-8d0bc29ce849" CreationDate="2024-02-19T13:38:58.087" UserId="7008" Text="|vulkan|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42802" PostHistoryTypeId="2" PostId="13929" RevisionGUID="1f44f4b3-90bd-4dc0-9feb-1ae18e33b3d6" CreationDate="2024-02-19T21:57:43.880" UserId="20703" Text="I am studying the BRDF equation. From [Wikipedia][1], the equation is as follows:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;I have one main question:&#xD;&#xA;- **Where does the $\cos{\theta_i}$ in the denominator come from?** \&#xD;&#xA;The denominator implies that $dE_i(\omega_i) = L_i(\omega_i)\cos{\theta_i}d\omega_i$. Now, the text below the equation states that $L$ measures the power received on a projected area. But this should mean $L_i$ itself includes a cosine factor already; then, why do we need a $\cos{\theta_i}$ when equating $dE_i(\omega_i)$ to $L_i(\omega_i)$? Isn't the cosine factor already included from $L_i(\omega_i)$?&#xD;&#xA;&#xD;&#xA;I am also confused about Wikipedia's reasoning for why $f_r$ is defined in terms of two differentials rather than the undifferentiated quantities:&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;What does &quot;irradiating light other than $d E_i(\omega_i)$, which are of no interest for $f_r(\omega_i, \omega_r)$, might illuminate the surface&quot; mean? How does the amount of light considered change when using $d E_i(\omega_i)$ in place of $E_i(\omega_i)$? And how  exactly would this &quot;unintentionally affect&quot; $L_r$?&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Bidirectional_reflectance_distribution_function#Definition&#xD;&#xA;  [2]: https://i.stack.imgur.com/VQwHw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/4EYoK.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42804" PostHistoryTypeId="1" PostId="13929" RevisionGUID="1f44f4b3-90bd-4dc0-9feb-1ae18e33b3d6" CreationDate="2024-02-19T21:57:43.880" UserId="20703" Text="Understanding the BRDF Equation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42805" PostHistoryTypeId="3" PostId="13929" RevisionGUID="1f44f4b3-90bd-4dc0-9feb-1ae18e33b3d6" CreationDate="2024-02-19T21:57:43.880" UserId="20703" Text="|raytracing|pathtracing|brdf|physically-based|reflection|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42806" PostHistoryTypeId="50" PostId="13002" RevisionGUID="2ad82759-cdc9-4bcf-bd7a-d54782456925" CreationDate="2024-02-20T02:08:06.027" UserId="-1" />
  <row Id="42807" PostHistoryTypeId="50" PostId="13721" RevisionGUID="abf66f8e-e3ca-4773-8e7e-0e8fa5790571" CreationDate="2024-02-20T11:09:31.140" UserId="-1" />
  <row Id="42808" PostHistoryTypeId="50" PostId="9116" RevisionGUID="2eac17ef-e727-45e9-b1b9-c8e0f7bcac39" CreationDate="2024-02-20T16:05:20.660" UserId="-1" />
  <row Id="42809" PostHistoryTypeId="2" PostId="13930" RevisionGUID="d5698912-cdeb-4a06-839d-32cb2762039e" CreationDate="2024-02-21T11:33:05.397" UserId="7952" Text="I would be tempted to solve this problem using sets and subsets, and combine that with the symmetry that tongues tend to exhibit to get an approximation of the overall shape.&#xD;&#xA;&#xD;&#xA;The first premise is: I can't imagine a tongue curled up on the left side and down on the right side, whatever the left side is doing the right side is almost always mirroring. So if we can figure out what one side of the tongue is doing then we can mirror that to the opposite side. This greatly reduces our search space for a solution.&#xD;&#xA;&#xD;&#xA;The second premise is: Create a set of &quot;major&quot; positions the tongue can be in. Then inside each of the major positions create a subset of &quot;minor&quot; positions that are essentially refinements of the major position. &#xD;&#xA;&#xD;&#xA;For a first pass at the solution I might just go for the major positions only to see if the overall approach was worth pursuing.&#xD;&#xA;&#xD;&#xA;I would further limit the major sets to only track one half the tongue and assume that the opposite half is mirroring the behavior of the side that is being tracked. (for a first pass solution this seems reasonable)&#xD;&#xA;&#xD;&#xA;The sensor data can then be used to filter the major sets into a limited group of sets of tongue shapes that are possible given the sensor position.&#xD;&#xA;&#xD;&#xA;If we start with a known position of the tongue and we know the rate that the data is being collected then this further limits the positions the tongue can be in since it can't jump from one deformation to the next without going through other deformations first. &#xD;&#xA;&#xD;&#xA;With one sensor I think the data would only be able to give major positions, but with two sensors it may be possible to get a fairly good approximation of the final shape of the tongue.&#xD;&#xA;&#xD;&#xA;One way to increase the amount of data would be to have the person with the sensors repeat a sentence over and over, and then move the sensor to a new position and get them to do it again, and keep doing that until multiple positions have been tracked. Take the repetitions and average the sensor data for a single sensor tracking session, then combine multiple sessions of data to get an approximation of having many sensors on the tongue at once.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Once the tongue positions have been estimated for each sensor reading standard animation techniques could be used to show the tongues movement. With two sensors it might be possible to get a descent real time (or near real time) image of the tongue in action." ContentLicense="CC BY-SA 4.0" />
  <row Id="42811" PostHistoryTypeId="2" PostId="13931" RevisionGUID="75893fd2-e78f-465b-ae78-d0040e8cfc39" CreationDate="2024-02-21T17:17:43.140" UserId="7008" Text="I want to add a debug feature to my ray tracer (runs in both Vulkan and OptiX). For that, I'd like to switch *all* objects to use a specific closest hit shader. Can I do this? I have only found the shader offset, but I wouldn't be able to get all objects to use the same shader that way.&#xD;&#xA;&#xD;&#xA;The alternative I'm using right now is to rebuild the acceleration structures with the hardcoded shader index, but that seems to be a lot of computation for a conceptually simple problem..." ContentLicense="CC BY-SA 4.0" />
  <row Id="42813" PostHistoryTypeId="1" PostId="13931" RevisionGUID="75893fd2-e78f-465b-ae78-d0040e8cfc39" CreationDate="2024-02-21T17:17:43.140" UserId="7008" Text="Is there a way to force a closest hit shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42814" PostHistoryTypeId="3" PostId="13931" RevisionGUID="75893fd2-e78f-465b-ae78-d0040e8cfc39" CreationDate="2024-02-21T17:17:43.140" UserId="7008" Text="|raytracing|shader|vulkan|optix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42815" PostHistoryTypeId="36" PostId="13932" RevisionGUID="5a81e4e9-1218-4073-a23e-2b9bc39a610d" CreationDate="2024-02-21T22:18:14.727" UserId="-1" Comment="from https://retrocomputing.stackexchange.com/questions/28550/what-where-the-benefits-of-quadratic-surface-rendering-used-by-nvidias-nv1-over" />
  <row Id="42816" PostHistoryTypeId="2" PostId="13932" RevisionGUID="16583a7b-6cca-434c-af1e-5d143c116345" CreationDate="2024-02-21T15:43:37.283" UserId="21021" Text="What where the benefits of quadratic surface rendering used by Nvidia's NV1 graphic chip over triangle based rendering? And what was the reason why Nvidia followed this approach?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42818" PostHistoryTypeId="1" PostId="13932" RevisionGUID="16583a7b-6cca-434c-af1e-5d143c116345" CreationDate="2024-02-21T15:43:37.283" UserId="21021" Text="What where the benefits of quadratic surface rendering used by Nvidia's NV1 over triangle based rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42819" PostHistoryTypeId="3" PostId="13932" RevisionGUID="16583a7b-6cca-434c-af1e-5d143c116345" CreationDate="2024-02-21T15:43:37.283" UserId="21021" Text="|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42822" PostHistoryTypeId="50" PostId="9926" RevisionGUID="5e0b44d6-e3ac-44fb-95b1-51bf4443fe54" CreationDate="2024-02-22T09:02:10.277" UserId="-1" />
  <row Id="42823" PostHistoryTypeId="2" PostId="13933" RevisionGUID="05a98e09-24cf-4295-815b-9157604719a7" CreationDate="2024-02-22T10:09:01.563" UserId="9169" Text="# Tight frustum&#xD;&#xA;&#xD;&#xA;I intend to create a tight frustum around a 3D model:&#xD;&#xA;&#xD;&#xA;[![Frustum schematics][1]][1]&#xD;&#xA;&#xD;&#xA;I have these variables:&#xD;&#xA;&#xD;&#xA;* Inputs:&#xD;&#xA;   * 3D model bounding box or bounding sphere or bounding volume.&#xD;&#xA;* To be determined:&#xD;&#xA;   * Eye distance and location.&#xD;&#xA;   * Up vector.&#xD;&#xA;   * Vertical field of view in degrees.&#xD;&#xA;   * Near plane.&#xD;&#xA;   * Far plane.&#xD;&#xA;   * ...?&#xD;&#xA;&#xD;&#xA;# Question&#xD;&#xA;&#xD;&#xA;How can I determine my variables so that the frustum would be tightly surrounding the 3D model? I'm looking for some approaches, algorithms, or even keywords and terminology.&#xD;&#xA;&#xD;&#xA;Looks like there is [Frustum Culling](https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling) approach to figure out if a bounding volume is on a frustum. But what I want is kind of reverse of that. I want to create a tight frustum around a bounding volume. I'd appreciate any hint or help.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/2F4K8.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42825" PostHistoryTypeId="1" PostId="13933" RevisionGUID="05a98e09-24cf-4295-815b-9157604719a7" CreationDate="2024-02-22T10:09:01.563" UserId="9169" Text="Create a tight frustum around a 3D model bounding volume" ContentLicense="CC BY-SA 4.0" />
  <row Id="42826" PostHistoryTypeId="3" PostId="13933" RevisionGUID="05a98e09-24cf-4295-815b-9157604719a7" CreationDate="2024-02-22T10:09:01.563" UserId="9169" Text="|opengl|transformations|mesh|camera|bounding-volume-hierarchy|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42827" PostHistoryTypeId="2" PostId="13934" RevisionGUID="3d866386-0b3c-4cfa-9557-d9f408983491" CreationDate="2024-02-22T12:09:53.513" UserId="9169" Text="Estimating the eye distance by max dimension of b-box and the `fovy` angle might help:&#xD;&#xA;&#xD;&#xA;[![Schematics][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7IcdL.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42829" PostHistoryTypeId="5" PostId="13932" RevisionGUID="ad13773a-d65a-4367-b25b-76a59ea9b676" CreationDate="2024-02-22T13:38:44.823" UserId="19369" Comment="Hopefully clarified question a bit." Text="What were the benefits of primitive quadrilateral rendering used by Nvidia's NV1 graphic chip over triangle based rendering? And what was the reason why Nvidia followed this approach?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42830" PostHistoryTypeId="4" PostId="13932" RevisionGUID="ad13773a-d65a-4367-b25b-76a59ea9b676" CreationDate="2024-02-22T13:38:44.823" UserId="19369" Comment="Hopefully clarified question a bit." Text="What were the benefits of quads used by Nvidia's NV1 over tri based rendering?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42831" PostHistoryTypeId="6" PostId="13932" RevisionGUID="ad13773a-d65a-4367-b25b-76a59ea9b676" CreationDate="2024-02-22T13:38:44.823" UserId="19369" Comment="Hopefully clarified question a bit." Text="|gpu|hardware|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42832" PostHistoryTypeId="24" PostId="13932" RevisionGUID="ad13773a-d65a-4367-b25b-76a59ea9b676" CreationDate="2024-02-22T13:38:44.823" Comment="Proposed by 19369 approved by 21021 edit id of 629" ContentLicense="CC BY-SA 4.0" />
  <row Id="42834" PostHistoryTypeId="2" PostId="13935" RevisionGUID="25c6ffc3-57df-4498-b99c-1b272c5d00ef" CreationDate="2024-02-22T20:08:18.397" UserId="7952" Text="Quads are an overloaded term in this context. The NV1 processed geometry using triangles and did not process quads as geometry. However it did process textures as 2x2 groups that was called &quot;Quadrilinear&quot; rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The NV1 had a fixed function pipeline. With a fixed function pipeline, processing textures in 2x2 groups allowed the pixels to be processed in parallel improving texture throughput which in turn improved rending speed and performance.&#xD;&#xA;&#xD;&#xA;Programmable pipelines required changes that made quadrilinear rendering infeasible." ContentLicense="CC BY-SA 4.0" />
  <row Id="42836" PostHistoryTypeId="5" PostId="13935" RevisionGUID="a2c45d0c-21f3-409f-9f99-57e28640ff90" CreationDate="2024-02-22T22:09:15.793" UserId="7952" Comment="added 7 characters in body" Text="Quads are an overloaded term in this context. &lt;s&gt;The NV1 processed geometry using triangles and did not process quads as geometry.&lt;/s&gt; However it did process textures as 2x2 groups that was called &quot;Quadrilinear&quot; rendering.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The NV1 had a fixed function pipeline. With a fixed function pipeline, processing textures in 2x2 groups allowed the pixels to be processed in parallel improving texture throughput which in turn improved rending speed and performance.&#xD;&#xA;&#xD;&#xA;Programmable pipelines required changes that made quadrilinear rendering infeasible." ContentLicense="CC BY-SA 4.0" />
  <row Id="42837" PostHistoryTypeId="2" PostId="13936" RevisionGUID="adf843bc-34c9-4c09-b8c1-79c6190addfa" CreationDate="2024-02-23T07:17:09.740" UserId="21209" Text="There seems to be a lot of confusion around the NV1, so I tried to find a few actual sources.&#xD;&#xA;&#xD;&#xA;It looks like NVidia and SGS-Thomson entered a partnership [#1] [#2] for a &quot;Multimedia Accelerator&quot;, and then NVidia sold the NV1 chip as the VRAM version, while Thomson sold the STG 2000 chip as the DRAM version. &#xD;&#xA;&#xD;&#xA;The Sega Saturn did **not** use the NV1, the Sega Saturn used the VDP1 [#3], and while some people say they are comparable [#4], and potentially the NV1/STG2000 was based on the VDP1, they are different.&#xD;&#xA;&#xD;&#xA;The VDP1 has detailed documentation [#5], and it's less of a 3D-pipeline engine and more of a sprite engine that can distort and texture sprites. That's what [forward texture mapping](https://en.wikipedia.org/wiki/Texture_mapping#Forward_texture_mapping) means: You iterate over the texture and map the result to the framebuffer, instead of iterating over the framebuffer pixels of the geometric primitive, sampling the texture while you do so (which is what modern engines do). &#xD;&#xA;&#xD;&#xA;Forward mapping also does not have to deal with the case where a rendered quadrilateral is not flat, as the source image is flat by definition, and using a quadrilateral instead of a triangle makes iterating over it simpler.&#xD;&#xA;&#xD;&#xA;I have not been able to find detailed documentation for the NV1 or the STG 2000, and apparently other people have also been looking and have found nothing. However, there's *some* basic documention for the STG 2000 [#6], which doesn't describe the rendering in detail, but says on page 9:&#xD;&#xA;&#xD;&#xA;&gt; * High performance acceleration of perspective-correct triangles, quadrilaterals and curves &#xD;&#xA;&gt; * [...]&#xD;&#xA;&gt; * Photorealistic 3D texture mapping, including lighting, fog, transparency, etc.&#xD;&#xA;&gt; * Video Texturing - ability to treat video as a texture.&#xD;&#xA;&#xD;&#xA;So the claim that the NV1 used &quot;primitive quadrilateral rendering over triangle based rendering&quot; is wrong, both triangles and quadrilaterals are available as primitives.&#xD;&#xA;&#xD;&#xA;It also doesn't say anything about the texture mapping mode used, and having triangles and curves as primitives makes it more likely that it was the modern &quot;reverse&quot; texture mapping, and not the forward mapping of the VDP1 used in the Sega Saturn.&#xD;&#xA;&#xD;&#xA;In general, the assumption of the question that there was somehow an &quot;advantage&quot; to the way the NV1 implemented also does not apply: There was a lot of experimenting going on at that time, the rendering pipeline had not yet settled into the &quot;generally accepted&quot; flavour that turned out to be optimum for that era, and the actual details of the way of doing things were more historical accident, or a development of existing architectures.&#xD;&#xA;&#xD;&#xA;* #1 https://archive.org/details/edn-1995_08_17/page/n113/mode/2up?q=stg2000&#xD;&#xA;* #2 https://archive.org/details/InterActivity05Jan1996/page/n19/mode/2up?q=stg2000&#xD;&#xA;* #3 https://segaretro.org/VDP1_(Saturn)&#xD;&#xA;* #4 https://segaretro.org/NV1&#xD;&#xA;* #5 https://segaretro.org/images/8/8b/ST-013-R3-061694.pdf&#xD;&#xA;* #6 https://archive.org/details/manuallib-id-2715792/mode/1up&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42839" PostHistoryTypeId="5" PostId="13936" RevisionGUID="5727c2cc-734b-4397-ba0c-8534d6be2a41" CreationDate="2024-02-23T12:13:41.820" UserId="21209" Comment="added 1561 characters in body" Text="There seems to be a lot of confusion around the NV1, so I tried to find a few actual sources.&#xD;&#xA;&#xD;&#xA;It looks like NVidia and SGS-Thomson entered a partnership [#1] [#2] for a &quot;Multimedia Accelerator&quot;, and then NVidia sold the NV1 chip as the VRAM version, while Thomson sold the STG 2000 chip as the DRAM version. &#xD;&#xA;&#xD;&#xA;The Sega Saturn did **not** use the NV1, the Sega Saturn used the VDP1 [#3], and while some people say they are comparable [#4], and potentially the NV1/STG2000 was based on the VDP1, they are different.&#xD;&#xA;&#xD;&#xA;The VDP1 has detailed documentation [#5], and it's less of a 3D-pipeline engine and more of a sprite engine that can distort and texture sprites. That's what [forward texture mapping](https://en.wikipedia.org/wiki/Texture_mapping#Forward_texture_mapping) means: You iterate over the texture and map the result to the framebuffer, instead of iterating over the framebuffer pixels of the geometric primitive, sampling the texture while you do so (which is what modern engines do). &#xD;&#xA;&#xD;&#xA;Forward mapping also does not have to deal with the case where a rendered quadrilateral is not flat, as the source image is flat by definition, and using a quadrilateral instead of a triangle makes iterating over it simpler.&#xD;&#xA;&#xD;&#xA;I have not been able to find detailed documentation for the NV1 or the STG 2000, and apparently other people have also been looking and have found nothing. However, there's *some* basic documention for the STG 2000 [#6], which doesn't describe the rendering in detail, but says on page 9:&#xD;&#xA;&#xD;&#xA;&gt; * High performance acceleration of perspective-correct triangles, quadrilaterals and curves &#xD;&#xA;&gt; * [...]&#xD;&#xA;&gt; * Photorealistic 3D texture mapping, including lighting, fog, transparency, etc.&#xD;&#xA;&gt; * Video Texturing - ability to treat video as a texture.&#xD;&#xA;&#xD;&#xA;So the claim that the NV1 used &quot;primitive quadrilateral rendering over triangle based rendering&quot; is wrong, both triangles and quadrilaterals are available as primitives.&#xD;&#xA;&#xD;&#xA;It also doesn't say anything about the texture mapping mode used, and having triangles and curves as primitives makes it more likely that it was the modern &quot;reverse&quot; texture mapping, and not the forward mapping of the VDP1 used in the Sega Saturn.&#xD;&#xA;&#xD;&#xA;In general, the assumption of the question that there was somehow an &quot;advantage&quot; to the way the NV1 implemented also does not apply: There was a lot of experimenting going on at that time, the rendering pipeline had not yet settled into the &quot;generally accepted&quot; flavour that turned out to be optimum for that era, and the actual details of the way of doing things were more historical accident, or a development of existing architectures.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Thanks for pointing out the &quot;nVidia NV1 Windows 95 Software Development Kit 1.50&quot; (SDK) on Vogons [#7]. The NV/SDK/DOCS directory contains a file TECHOVER.PDF which gives a technical overview. This confirms that the primitives are (p. 8)&#xD;&#xA;&#xD;&#xA;&gt; * Points, lines, polylines&#xD;&#xA;&gt; * Flat triangles&#xD;&#xA;&gt; * Flat quadrilaterals (quads)&#xD;&#xA;&gt; * Flat triangle strips, triangle chains&#xD;&#xA;&gt; * Flat quadstrips, quadchains, quadmeshes&#xD;&#xA;&#xD;&#xA;and in addition, either bilinear textured or quadratic textured&#xD;&#xA;&#xD;&#xA;&gt; * triangles&#xD;&#xA;&gt; * triangle strips and chains&#xD;&#xA;&gt; * quadrilaterals&#xD;&#xA;&gt; * quadstrips, quadchains, quadmeshes&#xD;&#xA;&#xD;&#xA;They also split the &quot;standard&quot; rendering pipeline into a CPU based part (transformation, clipping, Z-sorting; if you want, vector shader operations) and an accelerated part (lighting, texture mapping, transparency, depth, buffering). So they were indeed very familiar with the &quot;standard&quot; pipeline.&#xD;&#xA;&#xD;&#xA;Nevertheless, they chose to implement only forward texture mapping (which was probably their mistake), though they give their reasoning and compare the forward texture mapping approach to the inverse texture mapping approach (p. 11 ff.) &#xD;&#xA;&#xD;&#xA;Which means that porting games from the Sega Saturn was really easy, as the features of the VDP1 could easily be mimicked by using a particular choice of primitives and texture interpolation. (This may of course have also influenced the decision to implement forward mapping in the first place, though they did not restrict the functionality to it).&#xD;&#xA;&#xD;&#xA;* #1 https://archive.org/details/edn-1995_08_17/page/n113/mode/2up?q=stg2000&#xD;&#xA;* #2 https://archive.org/details/InterActivity05Jan1996/page/n19/mode/2up?q=stg2000&#xD;&#xA;* #3 https://segaretro.org/VDP1_(Saturn)&#xD;&#xA;* #4 https://segaretro.org/NV1&#xD;&#xA;* #5 https://segaretro.org/images/8/8b/ST-013-R3-061694.pdf&#xD;&#xA;* #6 https://archive.org/details/manuallib-id-2715792/mode/1up&#xD;&#xA;* #7 http://vogonsdrivers.com/getfile.php?fileid=706&amp;menustate=0&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42840" PostHistoryTypeId="5" PostId="13936" RevisionGUID="afe5b345-b751-4c8b-ad6e-9df84feb0819" CreationDate="2024-02-23T12:33:41.507" UserId="21209" Comment="added 197 characters in body" Text="There seems to be a lot of confusion around the NV1, so I tried to find a few actual sources.&#xD;&#xA;&#xD;&#xA;It looks like NVidia and SGS-Thomson entered a partnership [#1] [#2] for a &quot;Multimedia Accelerator&quot;, and then NVidia sold the NV1 chip as the VRAM version, while Thomson sold the STG 2000 chip as the DRAM version. &#xD;&#xA;&#xD;&#xA;The Sega Saturn did **not** use the NV1, the Sega Saturn used the VDP1 [#3], and while some people say they are comparable [#4], and potentially the NV1/STG2000 was based on the VDP1, they are different.&#xD;&#xA;&#xD;&#xA;The VDP1 has detailed documentation [#5], and it's less of a 3D-pipeline engine and more of a sprite engine that can distort and texture sprites. That's what [forward texture mapping](https://en.wikipedia.org/wiki/Texture_mapping#Forward_texture_mapping) means: You iterate over the texture and map the result to the framebuffer, instead of iterating over the framebuffer pixels of the geometric primitive, sampling the texture while you do so (which is what modern engines do). &#xD;&#xA;&#xD;&#xA;Forward mapping also does not have to deal with the case where a rendered quadrilateral is not flat, as the source image is flat by definition, and using a quadrilateral instead of a triangle makes iterating over it simpler.&#xD;&#xA;&#xD;&#xA;I have not been able to find detailed documentation for the NV1 or the STG 2000, and apparently other people have also been looking and have found nothing. However, there's *some* basic documention for the STG 2000 [#6], which doesn't describe the rendering in detail, but says on page 9:&#xD;&#xA;&#xD;&#xA;&gt; * High performance acceleration of perspective-correct triangles, quadrilaterals and curves &#xD;&#xA;&gt; * [...]&#xD;&#xA;&gt; * Photorealistic 3D texture mapping, including lighting, fog, transparency, etc.&#xD;&#xA;&gt; * Video Texturing - ability to treat video as a texture.&#xD;&#xA;&#xD;&#xA;So the claim that the NV1 used &quot;primitive quadrilateral rendering over triangle based rendering&quot; is wrong, both triangles and quadrilaterals are available as primitives.&#xD;&#xA;&#xD;&#xA;It also doesn't say anything about the texture mapping mode used, and having triangles and curves as primitives makes it more likely that it was the modern &quot;reverse&quot; texture mapping, and not the forward mapping of the VDP1 used in the Sega Saturn.&#xD;&#xA;&#xD;&#xA;In general, the assumption of the question that there was somehow an &quot;advantage&quot; to the way the NV1 implemented also does not apply: There was a lot of experimenting going on at that time, the rendering pipeline had not yet settled into the &quot;generally accepted&quot; flavour that turned out to be optimum for that era, and the actual details of the way of doing things were more historical accident, or a development of existing architectures.&#xD;&#xA;&#xD;&#xA;----&#xD;&#xA;&#xD;&#xA;Thanks for pointing out the &quot;nVidia NV1 Windows 95 Software Development Kit 1.50&quot; (SDK) on Vogons [#7]. The NV/SDK/DOCS directory contains a file TECHOVER.PDF which gives a technical overview. This confirms that the primitives are (p. 8)&#xD;&#xA;&#xD;&#xA;&gt; * Points, lines, polylines&#xD;&#xA;&gt; * Flat triangles&#xD;&#xA;&gt; * Flat quadrilaterals (quads)&#xD;&#xA;&gt; * Flat triangle strips, triangle chains&#xD;&#xA;&gt; * Flat quadstrips, quadchains, quadmeshes&#xD;&#xA;&#xD;&#xA;and in addition, either bilinear textured or quadratic textured&#xD;&#xA;&#xD;&#xA;&gt; * triangles&#xD;&#xA;&gt; * triangle strips and chains&#xD;&#xA;&gt; * quadrilaterals&#xD;&#xA;&gt; * quadstrips, quadchains, quadmeshes&#xD;&#xA;&#xD;&#xA;They also split the &quot;standard&quot; rendering pipeline into a CPU based part (transformation, clipping, Z-sorting; if you want, vector shader operations) and an accelerated part (lighting, texture mapping, transparency, depth, buffering; if you want, pixel shader operations). So they were indeed very familiar with the &quot;standard&quot; pipeline.&#xD;&#xA;&#xD;&#xA;Nevertheless, they chose to implement only forward texture mapping (which was probably their mistake), though they give their reasoning and compare the forward texture mapping approach to the inverse texture mapping approach (p. 11 ff.) The reasons more or less boil down to performance on consumer hardware, and expectations for behaviour on consumer hardware.&#xD;&#xA;&#xD;&#xA;However, that means that porting games from the Sega Saturn was really easy (as noted in the comments), as the features of the VDP1 could easily be mimicked by using a particular choice of primitives and texture interpolation. (This may of course have also influenced the decision to implement forward mapping in the first place, though they did not restrict the functionality to it).&#xD;&#xA;&#xD;&#xA;* #1 https://archive.org/details/edn-1995_08_17/page/n113/mode/2up?q=stg2000&#xD;&#xA;* #2 https://archive.org/details/InterActivity05Jan1996/page/n19/mode/2up?q=stg2000&#xD;&#xA;* #3 https://segaretro.org/VDP1_(Saturn)&#xD;&#xA;* #4 https://segaretro.org/NV1&#xD;&#xA;* #5 https://segaretro.org/images/8/8b/ST-013-R3-061694.pdf&#xD;&#xA;* #6 https://archive.org/details/manuallib-id-2715792/mode/1up&#xD;&#xA;* #7 http://vogonsdrivers.com/getfile.php?fileid=706&amp;menustate=0&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42841" PostHistoryTypeId="5" PostId="13935" RevisionGUID="4a4ca7e9-23ae-4b38-88f3-5b9786f05c38" CreationDate="2024-02-23T13:15:54.667" UserId="7952" Comment="added 60 characters in body" Text="Quads are an overloaded term in this context. The NV1 processed geometry using triangles and did not process quads as geometry. However it did process textures as 2x2 groups that was called &quot;Quadrilinear&quot; rendering.&#xD;&#xA;&#xD;&#xA;I retract my retraction, the geometry processing was triangles.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;The NV1 had a fixed function pipeline. With a fixed function pipeline, processing textures in 2x2 groups allowed the pixels to be processed in parallel improving texture throughput which in turn improved rending speed and performance.&#xD;&#xA;&#xD;&#xA;Programmable pipelines required changes that made quadrilinear rendering infeasible." ContentLicense="CC BY-SA 4.0" />
  <row Id="42851" PostHistoryTypeId="2" PostId="13938" RevisionGUID="7865d600-578b-4f3f-b309-b8942fa0b43e" CreationDate="2024-02-25T14:03:17.283" UserId="21151" Text="I have This 3D mesh class ,&#xD;&#xA;I use helixToolKit to display the mesh and transformations ,&#xD;&#xA;but i want to apply these transformations to the vertcies dirctly so the nesh can be exported with these transformations &#xD;&#xA;how to do that ?&#xD;&#xA;&#xD;&#xA;    public class Vertex&#xD;&#xA;    {&#xD;&#xA;        public Vector3 Position { get; set; }&#xD;&#xA;        public Vector3 Normal { get; set; }&#xD;&#xA;        public int NormalW { get; set; }&#xD;&#xA;        public List&lt;Vector3&gt; UVs { get; set; }&#xD;&#xA;        public List&lt;Vector4&gt; Tangents { get; set; }&#xD;&#xA;        public Vector4 Bitangent { get; set; }&#xD;&#xA;        public List&lt;VertexColor&gt; Colors { get; set; }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;     public class Mesh&#xD;&#xA;     {&#xD;&#xA;    &#xD;&#xA;        public Vector3 Translation { get; set; }&#xD;&#xA;    &#xD;&#xA;        public Vector3 Rotation { get; set; } //radian values of Euler angels&#xD;&#xA;    &#xD;&#xA;        public Vector3 Scale { get; set; }&#xD;&#xA;    &#xD;&#xA;        public List&lt;Vertex&gt; Vertices { get; set; }&#xD;&#xA;    &#xD;&#xA;        public List&lt;int&gt; Indices { get; set; }&#xD;&#xA;    &#xD;&#xA;     }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42853" PostHistoryTypeId="1" PostId="13938" RevisionGUID="7865d600-578b-4f3f-b309-b8942fa0b43e" CreationDate="2024-02-25T14:03:17.283" UserId="21151" Text="How apply 3d transformations on 3d Mesh vertcies" ContentLicense="CC BY-SA 4.0" />
  <row Id="42854" PostHistoryTypeId="3" PostId="13938" RevisionGUID="7865d600-578b-4f3f-b309-b8942fa0b43e" CreationDate="2024-02-25T14:03:17.283" UserId="21151" Text="|3d|transformations|c#|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42855" PostHistoryTypeId="2" PostId="13939" RevisionGUID="09690790-c3ba-4672-b617-ad07bb211bec" CreationDate="2024-02-25T14:44:48.227" UserId="19537" Text="Maybe you can try the the following code, I haven't used this for a while so usability is not guaranteed. Let's approach this in the most intuitive way (maybe there is some other API that can do the job but I simply can't recall). Essentially, you need to transform the position of each vertex, given translation, rotation and scaling factor. However, do not forget to transform the normal vector, tangents and bi-tangents (assume they are all in the same global coordinate frame). Note that the last field of tangents (and bitangents) should be preserved.&#xD;&#xA;&#xD;&#xA;```csharp&#xD;&#xA;using HelixToolkit.Wpf;&#xD;&#xA;&#xD;&#xA;public void ApplyTransformationsToVertices(Mesh3D mesh) {&#xD;&#xA;    Transform3DGroup transformGroup = new Transform3DGroup();       // translation, rotation, and scale all at once&#xD;&#xA;    transformGroup.Children.Add(new TranslateTransform3D(mesh.Translation.ToVector3D())); // translation&#xD;&#xA;&#xD;&#xA;    // I don't know a way to directly transform from Euler angle to Quaternion or Rotation Matrix &#xD;&#xA;    Quaternion rotationQuaternion = new QuaternionRotation3D(&#xD;&#xA;        new Quaternion(new Vector3D(1, 0, 0), mesh.Rotation.X) *&#xD;&#xA;        new Quaternion(new Vector3D(0, 1, 0), mesh.Rotation.Y) *&#xD;&#xA;        new Quaternion(new Vector3D(0, 0, 1), mesh.Rotation.Z)&#xD;&#xA;    );&#xD;&#xA;    transformGroup.Children.Add(new RotateTransform3D(rotationQuaternion));     // rotation&#xD;&#xA;    transformGroup.Children.Add(new ScaleTransform3D(mesh.Scale.ToVector3D())); // scale&#xD;&#xA;&#xD;&#xA;    foreach (var vertex in mesh.Vertices) {&#xD;&#xA;        Point3D vertexPosition = new Point3D(vertex.Position.X, vertex.Position.Y, vertex.Position.Z);&#xD;&#xA;&#xD;&#xA;        // transform vertex position&#xD;&#xA;        Point3D transformedVertexPosition = transformGroup.Transform(vertexPosition);&#xD;&#xA;        vertex.Position = transformedVertexPosition.ToVector3();&#xD;&#xA;&#xD;&#xA;        // transform normals&#xD;&#xA;        vertex.Normal = TransformVector3d(vertex.Normal, rotationQuaternion);&#xD;&#xA;&#xD;&#xA;        // transform tangents (the w field is not accounted for)&#xD;&#xA;        for (int i = 0; i &lt; vertex.Tangents.Count; i++) {&#xD;&#xA;            vertex.Tangents[i] = TransformVector3d(vertex.Tangents[i], rotationQuaternion);&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        // transform bi-tangents (the w field is not accounted for)&#xD;&#xA;        vertex.Bitangent = TransformVector3d(vertex.Bitangent, rotationQuaternion);&#xD;&#xA;    }&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;public Vector3 TransformVector3d(Vector3 vector, Quaternion rotationQuaternion) {&#xD;&#xA;    Vector3D vector3D = new Vector3D(vector.X, vector.Y, vector.Z);&#xD;&#xA;    Vector3D rotatedVector3D = rotationQuaternion.Rotate(vector3D);&#xD;&#xA;    return new Vector3((float)rotatedVector3D.X, (float)rotatedVector3D.Y, (float)rotatedVector3D.Z);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;public Vector3 TransformVector4d(Vector4 vector, Quaternion rotationQuaternion) {&#xD;&#xA;    Vector3 vector3 = new Vector3(vector.X, vector.Y, vector.Z);        // extract&#xD;&#xA;    Vector3D vector3D = new Vector3D(vector3.X, vector3.Y, vector3.Z);&#xD;&#xA;    Vector3D rotatedVector3D = rotationQuaternion.Rotate(vector3D);&#xD;&#xA;    return new Vector4((float)rotatedVector3D.X, (float)rotatedVector3D.Y, (float)rotatedVector3D.Z, vector.W);&#xD;&#xA;}&#xD;&#xA;```" ContentLicense="CC BY-SA 4.0" />
  <row Id="42857" PostHistoryTypeId="5" PostId="13938" RevisionGUID="1d76d8e3-cd82-47a9-9778-3a20e87c0bcc" CreationDate="2024-02-25T21:11:45.147" UserId="21151" Comment="added 799 characters in body" Text="I have This 3D mesh class ,&#xD;&#xA;I use helixToolKit SharpDX to display the mesh and transformations ,&#xD;&#xA;but i want to apply these transformations to the vertcies dirctly so the mesh can be exported with these transformations .&#xD;&#xA;how to do that ?&#xD;&#xA;&#xD;&#xA;        using HelixToolkit.SharpDX.Core;&#xD;&#xA;    using SharpDX;&#xD;&#xA;    using System.Windows.Media.Media3D;&#xD;&#xA;&#xD;&#xA;    public class Vertex&#xD;&#xA;    {&#xD;&#xA;        public Vector3 Position { get; set; }&#xD;&#xA;        public Vector3 Normal { get; set; }&#xD;&#xA;        public int NormalW { get; set; }&#xD;&#xA;        public List&lt;Vector3&gt; UVs { get; set; }&#xD;&#xA;        public List&lt;Vector4&gt; Tangents { get; set; }&#xD;&#xA;        public Vector4 Bitangent { get; set; }&#xD;&#xA;        public List&lt;VertexColor&gt; Colors { get; set; }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;     public class Mesh&#xD;&#xA;     {&#xD;&#xA;    &#xD;&#xA;        public Vector3 Translation { get; set; }&#xD;&#xA;    &#xD;&#xA;        public Vector3 Rotation { get; set; } //radian values of Euler angels&#xD;&#xA;    &#xD;&#xA;        public Vector3 Scale { get; set; }&#xD;&#xA;    &#xD;&#xA;        public List&lt;Vertex&gt; Vertices { get; set; }&#xD;&#xA;    &#xD;&#xA;        public List&lt;int&gt; Indices { get; set; }&#xD;&#xA;        &#xD;&#xA;        public Transform3D Transform&#xD;&#xA;        {&#xD;&#xA;            get =&gt; new MatrixTransform3D(this.GetTransformMatrix().ToMatrix3D());&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;and here how i build the transformation matrix &#xD;&#xA;&#xD;&#xA;     public static Matrix GetTransformMatrix(this Mesh mesh)&#xD;&#xA;     {&#xD;&#xA;         var tm =  Matrix.Translation(mesh.Translation);&#xD;&#xA;         var sm =  Matrix.Scaling(mesh.Scale);&#xD;&#xA;         var rxm = Matrix.RotationX(mesh.Rotation.X);&#xD;&#xA;         var rym = Matrix.RotationY(mesh.Rotation.Y);&#xD;&#xA;         var rzm = Matrix.RotationZ(mesh.Rotation.Z);&#xD;&#xA;         // Apply the transformations in the correct order (SRT order)&#xD;&#xA;         return sm * (rxm * (rzm * (rym * tm)));&#xD;&#xA;    &#xD;&#xA;     }" ContentLicense="CC BY-SA 4.0" />
  <row Id="42861" PostHistoryTypeId="5" PostId="13938" RevisionGUID="6c790ae7-64d4-45ea-b6a6-db823ef7af97" CreationDate="2024-02-25T23:36:20.410" UserId="21151" Comment="Reached an answer but still needs help" Text="I have This 3D mesh class ,&#xD;&#xA;I use helixToolKit SharpDX to display the mesh and transformations ,&#xD;&#xA;but i want to apply these transformations to the vertcies dirctly so the mesh can be exported with these transformations .&#xD;&#xA;how to do that ?&#xD;&#xA;&#xD;&#xA;        using HelixToolkit.SharpDX.Core;&#xD;&#xA;    using SharpDX;&#xD;&#xA;    using System.Windows.Media.Media3D;&#xD;&#xA;&#xD;&#xA;    public class Vertex&#xD;&#xA;    {&#xD;&#xA;        public Vector3 Position { get; set; }&#xD;&#xA;        public Vector3 Normal { get; set; }&#xD;&#xA;        public int NormalW { get; set; }&#xD;&#xA;        public List&lt;Vector3&gt; UVs { get; set; }&#xD;&#xA;        public List&lt;Vector4&gt; Tangents { get; set; }&#xD;&#xA;        public Vector4 Bitangent { get; set; }&#xD;&#xA;        public List&lt;VertexColor&gt; Colors { get; set; }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;     public class Mesh&#xD;&#xA;     {&#xD;&#xA;    &#xD;&#xA;        public Vector3 Translation { get; set; }&#xD;&#xA;    &#xD;&#xA;        public Vector3 Rotation { get; set; } //radian values of Euler angels&#xD;&#xA;    &#xD;&#xA;        public Vector3 Scale { get; set; }&#xD;&#xA;    &#xD;&#xA;        public List&lt;Vertex&gt; Vertices { get; set; }&#xD;&#xA;    &#xD;&#xA;        public List&lt;int&gt; Indices { get; set; }&#xD;&#xA;        &#xD;&#xA;        public Transform3D Transform&#xD;&#xA;        {&#xD;&#xA;            get =&gt; new MatrixTransform3D(this.GetTransformMatrix().ToMatrix3D());&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;    &#xD;&#xA;     }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Following Enigmatisms answer and using SharpDX Namespace&#xD;&#xA;&#xD;&#xA;it should be something like this&#xD;&#xA;&#xD;&#xA;  &#xD;&#xA;&#xD;&#xA;    public static void ApplyTransformations(this MeshNodeViewModel mesh)&#xD;&#xA;      {&#xD;&#xA;          //Obtain the total transformations&#xD;&#xA;          var tm = SharpMatrix.Translation(mesh.Translation);&#xD;&#xA;          var sm = SharpMatrix.Scaling(mesh.Scale);&#xD;&#xA;          var rxm = SharpMatrix.RotationX(mesh.Rotation.X);&#xD;&#xA;          var rym = SharpMatrix.RotationY(mesh.Rotation.Y);&#xD;&#xA;          var rzm = SharpMatrix.RotationZ(mesh.Rotation.Z);&#xD;&#xA;          // Apply the transformations in the SRT order&#xD;&#xA;          var transformations = sm * (rxm * (rzm * (rym * tm)));&#xD;&#xA;    &#xD;&#xA;          //Obtain the total rotations&#xD;&#xA;          SharpQuaternion rotationQuaternion = SharpQuaternion.RotationMatrix(rxm * rzm * rym);&#xD;&#xA;    &#xD;&#xA;          List&lt;MyVertex&gt; vertices = new List&lt;MyVertex&gt;(mesh.Vertices);&#xD;&#xA;          foreach (var vertex in vertices)&#xD;&#xA;          {&#xD;&#xA;              // transform vertex position&#xD;&#xA;              SharpVector3 pos = vertex.Position;&#xD;&#xA;              SharpVector3.Transform(ref pos, ref transformations, out SharpVector3 newPos);&#xD;&#xA;    &#xD;&#xA;              vertex.Position = newPos;&#xD;&#xA;    &#xD;&#xA;              // transform normals&#xD;&#xA;              vertex.Normal = TransformVector3(vertex.Normal, rotationQuaternion);&#xD;&#xA;    &#xD;&#xA;              // transform tangents (the w field is not accounted for)&#xD;&#xA;              for (int i = 0; i &lt; vertex.Tangents.Count; i++)&#xD;&#xA;              {&#xD;&#xA;                  vertex.Tangents[i] = TransformVector4(&#xD;&#xA;                          vertex.Tangents[i].ToSharp4(),&#xD;&#xA;                          rotationQuaternion&#xD;&#xA;                      )&#xD;&#xA;                      .ToNumerics();&#xD;&#xA;              }&#xD;&#xA;    &#xD;&#xA;              // transform bi-tangents (the w field is not accounted for)&#xD;&#xA;              vertex.Bitangent = TransformVector4(vertex.Bitangent.ToSharp4(), rotationQuaternion)&#xD;&#xA;                  .ToNumerics();&#xD;&#xA;          }&#xD;&#xA;    &#xD;&#xA;          mesh.Vertices = vertices;&#xD;&#xA;          //Clear Transformations&#xD;&#xA;          mesh.Translation = SharpVector3.Zero;&#xD;&#xA;          mesh.Rotation = SharpVector3.Zero;&#xD;&#xA;          mesh.Scale = SharpVector3.One;&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      public static SharpVector3 TransformVector3(&#xD;&#xA;          SharpVector3 vector,&#xD;&#xA;          SharpQuaternion rotationQuaternion&#xD;&#xA;      )&#xD;&#xA;      {&#xD;&#xA;          Vector3D vector3D = new Vector3D(vector.X, vector.Y, vector.Z);&#xD;&#xA;          SharpVector3.Transform(&#xD;&#xA;              ref vector,&#xD;&#xA;              ref rotationQuaternion,&#xD;&#xA;              out SharpVector3 rotatedVector3D&#xD;&#xA;          );&#xD;&#xA;          return new SharpVector3(&#xD;&#xA;              (float)rotatedVector3D.X,&#xD;&#xA;              (float)rotatedVector3D.Y,&#xD;&#xA;              (float)rotatedVector3D.Z&#xD;&#xA;          );&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      public static SharpVector4 TransformVector4(&#xD;&#xA;          SharpVector4 vector,&#xD;&#xA;          SharpQuaternion rotationQuaternion&#xD;&#xA;      )&#xD;&#xA;      {&#xD;&#xA;          SharpVector3 vector3 = new SharpVector3(vector.X, vector.Y, vector.Z); // extract&#xD;&#xA;          SharpVector3.Transform(&#xD;&#xA;              ref vector3,&#xD;&#xA;              ref rotationQuaternion,&#xD;&#xA;              out SharpVector3 rotatedVector3D&#xD;&#xA;          );&#xD;&#xA;          return new SharpVector4(&#xD;&#xA;              (float)rotatedVector3D.X,&#xD;&#xA;              (float)rotatedVector3D.Y,&#xD;&#xA;              (float)rotatedVector3D.Z,&#xD;&#xA;              vector.W&#xD;&#xA;          );&#xD;&#xA;      }&#xD;&#xA;&#xD;&#xA;however the normals/Light reflection would change a little after appling the transformations,&#xD;&#xA;But this will only happens if a scale is applied .&#xD;&#xA;Is this supposed to happen ?&#xD;&#xA;&#xD;&#xA;before &#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;after&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;or as gif &#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/RWHt6.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/cxiJu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/PbKiW.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="42862" PostHistoryTypeId="50" PostId="12498" RevisionGUID="a83d5bc9-97ac-4c82-8b87-3a0551e8c821" CreationDate="2024-02-26T04:05:00.593" UserId="-1" />
  <row Id="42863" PostHistoryTypeId="2" PostId="13941" RevisionGUID="53fd15af-9adc-4ec6-b882-23f16e5416b5" CreationDate="2024-02-26T14:34:57.400" UserId="21021" Text="Wouldn't it be better if instead of unified shaders on the GPU you had separate pixels and vertex shaders again and the vertex shaders together with the Z-buffer were on the CPU die instead of on the GPU?&#xD;&#xA;That way, like before, you could do the calculation of the polygon world directly on the CPU die and filter out the triangles that shouldn't be shown using the Z-buffer and then send only the triangles that should be shown to the GPU to fill the pixels?&#xD;&#xA;&#xD;&#xA;Wouldn't this then save bandwidth from the CPU to the GPU and allow for much faster updating of 3D objects? In addition, the 3D world calculation would then be on the CPU, where the gameplay-critical physics calculation also takes place. (of course there are also physics calculations as an accessory, but these are the ones that don't affect the gameplay)&#xD;&#xA;In addition, these calculations would then be able to be calculated using the clock frequency of the CPU.&#xD;&#xA;And finally, there would also be a lot more RAM available, since a computer usually has more RAM than VRAM.&#xD;&#xA;&#xD;&#xA;So why was this approach never pursued?&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42865" PostHistoryTypeId="1" PostId="13941" RevisionGUID="53fd15af-9adc-4ec6-b882-23f16e5416b5" CreationDate="2024-02-26T14:34:57.400" UserId="21021" Text="Wouldn't it be better if the vertex shaders and Z-Buffer were on the CPU instead of the GPU?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42866" PostHistoryTypeId="3" PostId="13941" RevisionGUID="53fd15af-9adc-4ec6-b882-23f16e5416b5" CreationDate="2024-02-26T14:34:57.400" UserId="21021" Text="|gpu|hardware|cpu|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42867" PostHistoryTypeId="2" PostId="13942" RevisionGUID="817d80d9-0cb4-498b-b4e3-5c1c29603ed4" CreationDate="2024-02-26T15:49:32.300" UserId="445" Text="&gt; … you could do the calculation of the polygon world directly on the CPU die and filter out the triangles that shouldn't be shown using the Z-buffer and then send only the triangles that should be shown to the GPU to fill the pixels?&#xD;&#xA;&#xD;&#xA;The depth buffer (Z buffer) is tested *per-fragment* — it doesn't hide whole triangles but individual pixels of the triangles. That means that&#xD;&#xA;&#xD;&#xA;* The GPU's parallel processing is advantageous for this job. (Generally, all per-pixel operations should be done on the GPU.)&#xD;&#xA;* The depth test (which must happen after rasterization and before executing the fragment shader) is executed more like the fragment shader than the vertex shader.&#xD;&#xA;* If we did the depth tests on the CPU, then you wouldn't just be deciding which _triangles_ to send to the GPU, but you'd have to send a list of individual pixels.&#xD;&#xA;&#xD;&#xA;Also, if depth tests _were_ done per-triangle, then you'd see lots of triangle-shaped artifacts whenever two objects slightly intersect. It's routine practice when putting together an environment to make overlaps, to save time on precisely modeling specific situations — for example, rocks might be placed slightly intersecting the terrain, or a door frame or arch intersecting the material of the wall it passes through. This only works because depth testing allows drawing intersecting objects near-perfectly.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;&gt; Wouldn't this then save bandwidth … gameplay-critical physics calculation also takes place … calculated using the clock frequency of the CPU.&#xD;&#xA;&#xD;&#xA;Separate from the triangles vs. pixels difference, another factor is that (in most applications) each object that the CPU tracks separately has a _mesh_ which is made of many triangles. The CPU only has to process the object's position and rotation, then pass that to the GPU; the GPU handles (as directed by the vertex shader) transforming *all the vertices of the mesh* from their positions in the mesh data to their positions on screen. This operation benefits from being executed on the GPU because it is highly parallel, and because the GPU's triangle rasterizers take instructions directly from the outputs of the vertex shader.&#xD;&#xA;&#xD;&#xA;The CPU never needs to calculate anything about thousands-to-millions of triangles, except for initially loading them from disk. That's a big advantage.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42869" PostHistoryTypeId="2" PostId="13943" RevisionGUID="d0f586ec-3d2b-4ffc-aaa1-98c95448536a" CreationDate="2024-02-27T14:51:44.827" UserId="21238" Text="I am trying to write an algorithm to remove a control point from a NURBS curve, similarly to what can be achieved using the [CVREMOVE][1] command in AutoCAD.&#xD;&#xA;&#xD;&#xA;[![control point removal][2]][2]&#xD;&#xA;&#xD;&#xA;I searched online but I was unable to find a single article about this topic, so here I am.&#xD;&#xA;Thanks a lot in advance for any hint you may have!&#xD;&#xA;&#xD;&#xA;  [1]: https://help.autodesk.com/view/ACDMAC/2023/ENU/?guid=GUID-7BF8CDE4-9440-4860-9D84-9341006E600A&#xD;&#xA;  [2]: https://i.stack.imgur.com/KbGZs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42871" PostHistoryTypeId="1" PostId="13943" RevisionGUID="d0f586ec-3d2b-4ffc-aaa1-98c95448536a" CreationDate="2024-02-27T14:51:44.827" UserId="21238" Text="How to remove a control point from a NURBS curve?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42872" PostHistoryTypeId="3" PostId="13943" RevisionGUID="d0f586ec-3d2b-4ffc-aaa1-98c95448536a" CreationDate="2024-02-27T14:51:44.827" UserId="21238" Text="|curve|nurbs|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42873" PostHistoryTypeId="2" PostId="13944" RevisionGUID="0b527cea-ec3e-4c41-abb0-3bdd45c93d6e" CreationDate="2024-02-28T12:43:27.327" UserId="7952" Text="A simple effective way to do this is simply not to remove the point at all, instead compute a straight line between the points on either side of the point to be removed. Then move the point that we want removed to the midpoint of that line. Mark it as hidden and then draw everything as normal except don't draw the hidden points.&#xD;&#xA;&#xD;&#xA;Another approach is to keep the relative distances from the two ends proportional and place the new point at the proportional distance from the other two." ContentLicense="CC BY-SA 4.0" />
  <row Id="42876" PostHistoryTypeId="2" PostId="13945" RevisionGUID="f58f3462-7f72-43ff-8e05-f9a7a716a354" CreationDate="2024-02-29T15:07:31.840" UserId="13273" Text="I have created a too large buffer with some vertex data (position, normal vector...).&#xD;&#xA;&#xD;&#xA;Within the render pipeline, I want to append new data to the end of the currently used buffer.&#xD;&#xA;To do this, I thought of binding this buffer as `GL_ARRAY_BUFFER` and `GL_SHADER_STORAGE_BUFFER` at the same time.&#xD;&#xA;&#xD;&#xA;Within the geometry shader, I only want to modify this buffer after the last vertex information used by this render call. So no input data will be changed.&#xD;&#xA;&#xD;&#xA;Is this allowed? Or do I HAVE to create a second separate buffer in which I store the generated data?&#xD;&#xA;&#xD;&#xA;Translated with DeepL.com (free version)" ContentLicense="CC BY-SA 4.0" />
  <row Id="42878" PostHistoryTypeId="1" PostId="13945" RevisionGUID="f58f3462-7f72-43ff-8e05-f9a7a716a354" CreationDate="2024-02-29T15:07:31.840" UserId="13273" Text="OpenGL Bind same buffer as VBO and SSBO at the same time" ContentLicense="CC BY-SA 4.0" />
  <row Id="42879" PostHistoryTypeId="3" PostId="13945" RevisionGUID="f58f3462-7f72-43ff-8e05-f9a7a716a354" CreationDate="2024-02-29T15:07:31.840" UserId="13273" Text="|opengl|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42880" PostHistoryTypeId="5" PostId="13943" RevisionGUID="630298f9-a83a-467d-9641-49109f4052bb" CreationDate="2024-02-29T15:13:54.927" UserId="21238" Comment="added 61 characters in body" Text="I am trying to write an algorithm to remove a control point from a NURBS curve, similarly to what can be achieved using the [CVREMOVE][1] command in AutoCAD.&#xD;&#xA;&#xD;&#xA;[![control point removal][2]][2]&#xD;&#xA;&#xD;&#xA;I searched online but I was unable to find a single article about this topic, so here I am.&#xD;&#xA;Thanks a lot in advance for any hint you may have!&#xD;&#xA;&#xD;&#xA;Edit: the NURBS curve definition comes from a STEP file. &#xD;&#xA;&#xD;&#xA;  [1]: https://help.autodesk.com/view/ACDMAC/2023/ENU/?guid=GUID-7BF8CDE4-9440-4860-9D84-9341006E600A&#xD;&#xA;  [2]: https://i.stack.imgur.com/KbGZs.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42881" PostHistoryTypeId="2" PostId="13946" RevisionGUID="3d425399-5fe7-4b23-83f5-ce081070958a" CreationDate="2024-02-29T16:06:47.177" UserId="21251" Text="I'm currently visualizing scientific data as volumes using Three and GLSL. I have a raymarching script that is pretty standard and colors based on a colormap I feed into the shader. &#xD;&#xA;&#xD;&#xA;It looks like this&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I want to be able to slice through the data using the slice sliders. However, I'm not certain how to implement this in my raymarching script. I originally had it discard fragments with positions less than the *slice* sliders. However, that method discards all rays if the camera is also positioned to the negative of that slice value. Not to mention it won't show me the side of the volume.&#xD;&#xA;&#xD;&#xA;Here is the main of my shader.&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;void main(){&#xD;&#xA;    vec3 rayDir = normalize( vDirection );&#xD;&#xA;    vec2 bounds = hitBox( vOrigin, rayDir );&#xD;&#xA;&#xD;&#xA;    if ( bounds.x &gt; bounds.y ) discard;&#xD;&#xA;&#xD;&#xA;    bounds.x = max( bounds.x, 0.0 );&#xD;&#xA;&#xD;&#xA;    vec3 p = vOrigin + bounds.x * rayDir;&#xD;&#xA;    vec3 inc = 1.0 / abs( rayDir );&#xD;&#xA;    float delta = min( inc.x, min( inc.y, inc.z ) );&#xD;&#xA;    delta /= steps;&#xD;&#xA;&#xD;&#xA;    for ( float t = bounds.x; t &lt; bounds.y; t += delta ) {&#xD;&#xA;&#xD;&#xA;        float d = sample1( p/scaleVec/scale + 0.5 );&#xD;&#xA;        bool cond = d &gt; threshold;&#xD;&#xA;        cond = flip ? !cond: cond;&#xD;&#xA;&#xD;&#xA;        if ( cond ) {&#xD;&#xA;            color.rgb = texture2D(cmap, vec2(d, 0.5)).rgb;&#xD;&#xA;            color.a = 1.;&#xD;&#xA;&#xD;&#xA;            break;&#xD;&#xA;        }&#xD;&#xA;&#xD;&#xA;        p += rayDir * delta;&#xD;&#xA;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    if ( color.a == 0.0 ) discard;&#xD;&#xA;&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;What is the correct way to be able to slice this while also seeing the side of the volume? &#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/HpkXp.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42883" PostHistoryTypeId="1" PostId="13946" RevisionGUID="3d425399-5fe7-4b23-83f5-ce081070958a" CreationDate="2024-02-29T16:06:47.177" UserId="21251" Text="Slice a volume in GLSL using raymarching" ContentLicense="CC BY-SA 4.0" />
  <row Id="42884" PostHistoryTypeId="3" PostId="13946" RevisionGUID="3d425399-5fe7-4b23-83f5-ce081070958a" CreationDate="2024-02-29T16:06:47.177" UserId="21251" Text="|glsl|three.js|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42885" PostHistoryTypeId="2" PostId="13947" RevisionGUID="7268d829-caef-490a-b4bf-9e9eda0f91bf" CreationDate="2024-03-01T08:53:07.047" UserId="21251" Text="I was over thinking it. &#xD;&#xA;&#xD;&#xA;Instead of discarding it, I needed to just let the ray keep marching.&#xD;&#xA;&#xD;&#xA;adding&#xD;&#xA;&#xD;&#xA;```glsl&#xD;&#xA;if (p.x &lt; xSlicer.x){&#xD;&#xA;       p += rayDir * delta;&#xD;&#xA;       continue;&#xD;&#xA;   }&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;To the top of the for loop fixed it.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ZOUmh.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42887" PostHistoryTypeId="2" PostId="13948" RevisionGUID="924f742f-4ca7-4ca0-be69-83cdd5fb742e" CreationDate="2024-03-01T10:18:30.863" UserId="10129" Text="I'm having a problem with loading texture in DX12 with DirectXTK. It seems to be loading all the metadata, since in PIX, I can see bound resource with correct width/height and format. But it's entirely black as if data wasn't actually copied to the resource:&#xD;&#xA;&#xD;&#xA;[![PIX][1]][1]&#xD;&#xA;&#xD;&#xA;Code:&#xD;&#xA;&#xD;&#xA;    // Resources&#xD;&#xA;    D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};&#xD;&#xA;    srvHeapDesc.NumDescriptors = 1;&#xD;&#xA;    srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;    srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;    ThrowIfFailed(m_device-&gt;CreateDescriptorHeap(&amp;srvHeapDesc, IID_PPV_ARGS(&amp;m_srvHeap)));&#xD;&#xA;&#xD;&#xA;    ComPtr&lt;ID3D12Resource&gt; texture;&#xD;&#xA;    ComPtr&lt;ID3D12Resource&gt; uploadHeap;&#xD;&#xA;    const wchar_t* path = L&quot;example_image.png&quot;;&#xD;&#xA;&#xD;&#xA;    // Load file data and save to resource&#xD;&#xA;    std::unique_ptr&lt;uint8_t[]&gt; decodedData;&#xD;&#xA;    std::vector&lt;D3D12_SUBRESOURCE_DATA&gt; textureData;&#xD;&#xA;    D3D12_SUBRESOURCE_DATA textureDataSingle;&#xD;&#xA;    const CD3DX12_HEAP_PROPERTIES heapUpload = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);&#xD;&#xA;&#xD;&#xA;    HRESULT hr = LoadWICTextureFromFileEx(device, path, 0, flags, WIC_LOADER_DEFAULT, texture.ReleaseAndGetAddressOf(), decodedData, textureDataSingle);&#xD;&#xA;    ThrowIfFailed(hr);&#xD;&#xA;&#xD;&#xA;    const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, 1);&#xD;&#xA;    const CD3DX12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize);&#xD;&#xA;&#xD;&#xA;    ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;        &amp;heapUpload,&#xD;&#xA;        D3D12_HEAP_FLAG_NONE,&#xD;&#xA;        &amp;resourceDesc,&#xD;&#xA;        D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;        nullptr,&#xD;&#xA;        IID_PPV_ARGS(&amp;uploadHeap)&#xD;&#xA;    ));&#xD;&#xA;&#xD;&#xA;    UpdateSubresources(commandList.Get(), texture.Get(), uploadHeap.Get(), 0, 0, 1, &amp;textureDataSingle);&#xD;&#xA;    const CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);&#xD;&#xA;    commandList-&gt;ResourceBarrier(1, &amp;barrier);&#xD;&#xA;&#xD;&#xA;    // Create SRV&#xD;&#xA;    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = { texture-&gt;GetDesc().Format, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING };&#xD;&#xA;    srvDesc.Texture2D.MipLevels = 1;&#xD;&#xA;    CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(srvHeap-&gt;GetCPUDescriptorHandleForHeapStart(), srvIndex, device-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));&#xD;&#xA;    device-&gt;CreateShaderResourceView(texture.Get(), &amp;srvDesc, srvHandle);&#xD;&#xA;&#xD;&#xA;    // Binding&#xD;&#xA;    ID3D12DescriptorHeap* ppHeaps[] = { m_srvHeap.Get() };&#xD;&#xA;    m_commandList-&gt;SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);&#xD;&#xA;    CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle0(m_srvHeap-&gt;GetGPUDescriptorHandleForHeapStart(), 0, m_device-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));&#xD;&#xA;    m_commandList-&gt;SetGraphicsRootDescriptorTable(3, srvHandle0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JNcff.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42889" PostHistoryTypeId="1" PostId="13948" RevisionGUID="924f742f-4ca7-4ca0-be69-83cdd5fb742e" CreationDate="2024-03-01T10:18:30.863" UserId="10129" Text="Empty texture passed down to GPU in DirectX12" ContentLicense="CC BY-SA 4.0" />
  <row Id="42890" PostHistoryTypeId="3" PostId="13948" RevisionGUID="924f742f-4ca7-4ca0-be69-83cdd5fb742e" CreationDate="2024-03-01T10:18:30.863" UserId="10129" Text="|texture|directx12|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42891" PostHistoryTypeId="2" PostId="13949" RevisionGUID="fe28013e-5dc2-48e5-a10e-ec11ef8660e1" CreationDate="2024-03-01T10:44:59.190" UserId="21254" Text="I am looking for an algorithm which is able to compute the distribution of ellipses on a 2D surface in order to reach a good degree of covering.&#xD;&#xA;&#xD;&#xA;I am doing this in order to cover a UV unwrapped texture with ellipses in a tight way.&#xD;&#xA;Something like [this][1], but that generalizes to any shape.&#xD;&#xA;&#xD;&#xA;Thank you for your time!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://erich-friedman.github.io/packing/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42893" PostHistoryTypeId="1" PostId="13949" RevisionGUID="fe28013e-5dc2-48e5-a10e-ec11ef8660e1" CreationDate="2024-03-01T10:44:59.190" UserId="21254" Text="Covering texture surface with ellipses" ContentLicense="CC BY-SA 4.0" />
  <row Id="42894" PostHistoryTypeId="3" PostId="13949" RevisionGUID="fe28013e-5dc2-48e5-a10e-ec11ef8660e1" CreationDate="2024-03-01T10:44:59.190" UserId="21254" Text="|texture|computational-geometry|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42895" PostHistoryTypeId="5" PostId="13949" RevisionGUID="7d6979a1-bf30-4730-bc20-9fac869144d5" CreationDate="2024-03-01T10:46:09.983" UserId="21254" Comment="added 52 characters in body" Text="I am looking for an algorithm which is able to compute the distribution of ellipses on a 2D surface in order to reach a good degree of covering.&#xD;&#xA;&#xD;&#xA;I am doing this in order to cover a UV unwrapped texture with ellipses in a tight way.&#xD;&#xA;Something like [this][1], but that generalizes to any shape.&#xD;&#xA;Overlapping, to a certain level, is not a problem.&#xD;&#xA;&#xD;&#xA;Thank you for your time!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://erich-friedman.github.io/packing/" ContentLicense="CC BY-SA 4.0" />
  <row Id="42896" PostHistoryTypeId="5" PostId="13949" RevisionGUID="c6b15bee-46a2-4432-ae41-8da6471e1067" CreationDate="2024-03-01T10:49:43.417" UserId="21254" Comment="added 145 characters in body" Text="I am looking for an algorithm which is able to compute the distribution of ellipses on a 2D surface in order to reach a good degree of covering.&#xD;&#xA;&#xD;&#xA;I am doing this in order to cover a UV unwrapped texture with ellipses in a tight way and that generalizes to any shape.&#xD;&#xA;Overlapping, to a certain level, is not a problem.&#xD;&#xA;Here an image I found that describes something very similar to what I want to achieve (in the image they use circles and not ellipses)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Thank you for your time!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ml3KA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42897" PostHistoryTypeId="5" PostId="13949" RevisionGUID="40a0ccce-4ef4-4d0d-8e7c-e07f4470af2f" CreationDate="2024-03-01T10:51:04.103" UserId="21254" Comment="added 52 characters in body" Text="I am looking for an algorithm (also ideas on possible directions are appreciated) which is able to compute the distribution of ellipses on a 2D surface in order to reach a good degree of covering.&#xD;&#xA;&#xD;&#xA;I am doing this in order to cover a UV unwrapped texture with ellipses in a tight way and that generalizes to any shape.&#xD;&#xA;Overlapping, to a certain level, is not a problem.&#xD;&#xA;Here an image I found that describes something very similar to what I want to achieve (in the image they use circles and not ellipses)&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Thank you for your time!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ml3KA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42898" PostHistoryTypeId="5" PostId="13949" RevisionGUID="7ce84a3e-e944-4a15-b8cf-f86d22c46747" CreationDate="2024-03-01T10:53:38.903" UserId="21254" Comment="added 96 characters in body" Text="I am looking for an algorithm (also ideas on possible directions are appreciated) which is able to compute the distribution of ellipses on a 2D surface in order to reach a good degree of covering.&#xD;&#xA;&#xD;&#xA;I am doing this in order to cover a UV unwrapped texture with ellipses in a tight way and that generalizes to any shape.&#xD;&#xA;Overlapping, to a certain level, is not a problem.&#xD;&#xA;Here an image I found that describes something very similar to what I want to achieve (in the image they use circles and not ellipses).&#xD;&#xA;Furthermore, ellipses should not cross the shapes's boundary, or do it the least as possible.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;Thank you for your time!&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ml3KA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42899" PostHistoryTypeId="5" PostId="13948" RevisionGUID="2df285bd-9a4f-46b9-b9bb-14a5b2131fdd" CreationDate="2024-03-01T21:06:48.167" UserId="10129" Comment="added 31 characters in body" Text="I'm having a problem with loading texture in DX12 with DirectXTK. It seems to be loading all the metadata, since in PIX, I can see bound resource with correct width/height and format. But it's entirely black as if data wasn't actually copied to the resource:&#xD;&#xA;&#xD;&#xA;[![PIX][1]][1]&#xD;&#xA;&#xD;&#xA;Code:&#xD;&#xA;&#xD;&#xA;    // Resources&#xD;&#xA;    D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};&#xD;&#xA;    srvHeapDesc.NumDescriptors = 1;&#xD;&#xA;    srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;&#xD;&#xA;    srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;&#xD;&#xA;    ThrowIfFailed(m_device-&gt;CreateDescriptorHeap(&amp;srvHeapDesc, IID_PPV_ARGS(&amp;m_srvHeap)));&#xD;&#xA;&#xD;&#xA;    ComPtr&lt;ID3D12Resource&gt; texture;&#xD;&#xA;    ComPtr&lt;ID3D12Resource&gt; uploadHeap;&#xD;&#xA;    const wchar_t* path = L&quot;C:\some_path\example_image.png&quot;; // Full file path&#xD;&#xA;&#xD;&#xA;    // Load file data and save to resource&#xD;&#xA;    std::unique_ptr&lt;uint8_t[]&gt; decodedData;&#xD;&#xA;    std::vector&lt;D3D12_SUBRESOURCE_DATA&gt; textureData;&#xD;&#xA;    D3D12_SUBRESOURCE_DATA textureDataSingle;&#xD;&#xA;    const CD3DX12_HEAP_PROPERTIES heapUpload = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);&#xD;&#xA;&#xD;&#xA;    HRESULT hr = LoadWICTextureFromFileEx(device, path, 0, flags, WIC_LOADER_DEFAULT, texture.ReleaseAndGetAddressOf(), decodedData, textureDataSingle);&#xD;&#xA;    ThrowIfFailed(hr);&#xD;&#xA;&#xD;&#xA;    const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture.Get(), 0, 1);&#xD;&#xA;    const CD3DX12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize);&#xD;&#xA;&#xD;&#xA;    ThrowIfFailed(device-&gt;CreateCommittedResource(&#xD;&#xA;        &amp;heapUpload,&#xD;&#xA;        D3D12_HEAP_FLAG_NONE,&#xD;&#xA;        &amp;resourceDesc,&#xD;&#xA;        D3D12_RESOURCE_STATE_GENERIC_READ,&#xD;&#xA;        nullptr,&#xD;&#xA;        IID_PPV_ARGS(&amp;uploadHeap)&#xD;&#xA;    ));&#xD;&#xA;&#xD;&#xA;    UpdateSubresources(commandList.Get(), texture.Get(), uploadHeap.Get(), 0, 0, 1, &amp;textureDataSingle);&#xD;&#xA;    const CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);&#xD;&#xA;    commandList-&gt;ResourceBarrier(1, &amp;barrier);&#xD;&#xA;&#xD;&#xA;    // Create SRV&#xD;&#xA;    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = { texture-&gt;GetDesc().Format, D3D12_SRV_DIMENSION_TEXTURE2D, D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING };&#xD;&#xA;    srvDesc.Texture2D.MipLevels = 1;&#xD;&#xA;    CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(srvHeap-&gt;GetCPUDescriptorHandleForHeapStart(), srvIndex, device-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));&#xD;&#xA;    device-&gt;CreateShaderResourceView(texture.Get(), &amp;srvDesc, srvHandle);&#xD;&#xA;&#xD;&#xA;    // Binding&#xD;&#xA;    ID3D12DescriptorHeap* ppHeaps[] = { m_srvHeap.Get() };&#xD;&#xA;    m_commandList-&gt;SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);&#xD;&#xA;    CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle0(m_srvHeap-&gt;GetGPUDescriptorHandleForHeapStart(), 0, m_device-&gt;GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));&#xD;&#xA;    m_commandList-&gt;SetGraphicsRootDescriptorTable(3, srvHandle0);&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/JNcff.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42902" PostHistoryTypeId="2" PostId="13950" RevisionGUID="5cc7f2d1-5f23-4ba7-8d25-4c8c67be29d1" CreationDate="2024-03-02T06:56:30.257" UserId="18408" Text="I’m writing a multithreaded renderer. It happens to use wgpu in Rust, but that probably has no bearing on my question except perhaps it will influence my terminology.&#xD;&#xA;&#xD;&#xA;Currently, I have two threads, a main thread and a render thread. My window is owned by the main thread but a thread safe reference is given to the render thread. The render thread uses this to create and manage a window surface (handle resizes, presentation mode changes, obtaining swap chain texture per frame). I.e. the render thread owns the surface.&#xD;&#xA;&#xD;&#xA;In conversation, someone mentioned that the main thread should also own the surface. If that’s the case, is the main thread responsible for acquiring the swap chain texture and passing that to the render thread?&#xD;&#xA;&#xD;&#xA;I suppose my main questions are:&#xD;&#xA; - is there a definitive, perhaps generalised for all platforms, answer to which thread should own the surface?&#xD;&#xA; - Does ownership equate to responsibility for acquiring and presenting, or can that be done on another thread?&#xD;&#xA; - I’ve tried searching for this information; where should I be looking to find this out?&#xD;&#xA;&#xD;&#xA;I realise this could be subjective, but I’ve tried to make it objective and as specific questions. Please let me know if it’s too open for opinion and I’ll try to edit it. Thanks." ContentLicense="CC BY-SA 4.0" />
  <row Id="42904" PostHistoryTypeId="1" PostId="13950" RevisionGUID="5cc7f2d1-5f23-4ba7-8d25-4c8c67be29d1" CreationDate="2024-03-02T06:56:30.257" UserId="18408" Text="Which thread should own, acquire and present a window surface?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42905" PostHistoryTypeId="3" PostId="13950" RevisionGUID="5cc7f2d1-5f23-4ba7-8d25-4c8c67be29d1" CreationDate="2024-03-02T06:56:30.257" UserId="18408" Text="|rendering|multithreading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42906" PostHistoryTypeId="2" PostId="13951" RevisionGUID="6ae87999-c4f4-4180-8379-e543cd0e06d6" CreationDate="2024-03-02T10:27:14.493" UserId="10129" Text="The problem was that I didn't call &quot;ExecuteCommandLists&quot; at the very end of function declaring and creating resources. I did execute command lists every frame but first I clear it and then record per frame commands.&#xD;&#xA;&#xD;&#xA;Not sure why other stuff worked so far i.e. CBVs, device creation." ContentLicense="CC BY-SA 4.0" />
  <row Id="42908" PostHistoryTypeId="2" PostId="13952" RevisionGUID="d13299e8-c586-432f-aaa7-a5f16fcf11f8" CreationDate="2024-03-02T13:00:00.067" UserId="21255" Text="I'm trying to implement a basic form of **physically based rendering (PBR)** and I am using the PBR tutorial from learnopengl dot com as a reference.&#xD;&#xA;&#xD;&#xA;The PBR I am implementing consists of two parts, direct illumination and indirect illumination. The direct illumination is quite straight forward and is working as expected (well, according to my untrained eye...). It's the indirect illumination that I'm having troubles implementing. I want to use **image based lighting (IBL)** for this part.&#xD;&#xA;&#xD;&#xA;The following image showcases the output after rendering spheres with [this scuffed titanium PBR metal material](https://freepbr.com/materials/scuffed-titanium-pbr-metal-material/) using only direct illumination.&#xD;&#xA;&#xD;&#xA;[![close up of only direct illumination][2]][2]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;When I also include indirect illumination (from the environment map), this is what I get&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;[![direct illumination and indirect illumination][3]][3]&#xD;&#xA;&#xD;&#xA;[![close up of direct illumination and indirect illumination][4]][4]&#xD;&#xA;&#xD;&#xA;I would've expected to see something much more like the preview picture from the page where I found the PBR material from, see link above.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;Here is another image of another more sophisticated model with direct and indirect illumination&#xD;&#xA;&#xD;&#xA;[![jet engine with both direct and indirect illumination][6]][6]&#xD;&#xA;&#xD;&#xA;if I remove the indirect illumination I get this&#xD;&#xA;&#xD;&#xA;[![jet engine with only direct illumination][7]][7]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;Instead the environment map seems to be overpowering everything which looks odd to me.&#xD;&#xA;&#xD;&#xA;I am using a pre-convolved reflectance map that is mipmapped (7 HDR images in total) as well as an irradiance map (HDR image). These are correct and are not the issue.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;If I use a plain-sphere with a red base color and vary the metalness (growing vertically) and the roughness (growing horizontally) I get this with NO indirect illumination.&#xD;&#xA;&#xD;&#xA;[![plain-red spheres with varying metalness and roughness with only direct illumination][8]][8]&#xD;&#xA;&#xD;&#xA;note how the left-most spheres (with `roughness=0.0`) have no specular reflection, that seems odd to me.&#xD;&#xA;&#xD;&#xA;... with indirect illumination&#xD;&#xA;&#xD;&#xA;[![plain-red spheres with varying metalness and roughness with direct illumination and indirect illumination][10]][10]&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;I am not sure where I'm going wrong. Below you'll find the fragment shader used to render the seen images (excluding the last shown image)&#xD;&#xA;```glsl&#xD;&#xA;#version 460 core&#xD;&#xA;&#xD;&#xA;#define EPSILON 0.00001&#xD;&#xA;#define PI 3.14159265359&#xD;&#xA;&#xD;&#xA;/////////////////////////&#xD;&#xA;// VERTEX SHADER INPUT //&#xD;&#xA;/////////////////////////&#xD;&#xA;in vec3 position; // world space&#xD;&#xA;in vec3 normal;&#xD;&#xA;in vec2 texcoord;&#xD;&#xA;&#xD;&#xA;/////////////////////////&#xD;&#xA;// Material properties //&#xD;&#xA;/////////////////////////&#xD;&#xA;struct Material {&#xD;&#xA;    ...&#xD;&#xA;};&#xD;&#xA;layout (binding = 5) uniform sampler2D u_DiffuseMap;&#xD;&#xA;layout (binding = 6) uniform sampler2D u_RoughnessMap;&#xD;&#xA;layout (binding = 7) uniform sampler2D u_MetalnessMap;&#xD;&#xA;layout (binding = 8) uniform sampler2D u_EmissionMap;&#xD;&#xA;layout (binding = 9) uniform sampler2D u_NormalMap;&#xD;&#xA;layout (binding = 11) uniform sampler2D u_AoMap;&#xD;&#xA;uniform Material u_Material;&#xD;&#xA;&#xD;&#xA;/////////////////////&#xD;&#xA;// Environment map //&#xD;&#xA;/////////////////////&#xD;&#xA;layout (binding = 3) uniform sampler2D u_ReflectanceMap; // 8 maps in total, mipmapped&#xD;&#xA;layout (binding = 4) uniform sampler2D u_IrradianceMap;&#xD;&#xA;&#xD;&#xA;///////////////////////////&#xD;&#xA;// Pointlight properties //&#xD;&#xA;///////////////////////////&#xD;&#xA;struct PointLight {&#xD;&#xA;	vec3 position; // in world space&#xD;&#xA;	vec3 color; // [0, 1]&#xD;&#xA;};&#xD;&#xA;uniform PointLight u_PointLights[1]; // only supporting one light source right now&#xD;&#xA;&#xD;&#xA;////////////&#xD;&#xA;// Camera //&#xD;&#xA;////////////&#xD;&#xA;uniform vec3 u_CameraPosition; // in world space&#xD;&#xA;&#xD;&#xA;////////////&#xD;&#xA;// OUTPUT //&#xD;&#xA;////////////&#xD;&#xA;out vec4 FragColor;&#xD;&#xA;&#xD;&#xA;///////////////////////////////////////////////////////////////////////&#xD;&#xA;///////////////////////////////////////////////////////////////////////&#xD;&#xA;///////////////////////////////////////////////////////////////////////&#xD;&#xA;&#xD;&#xA;vec3 getNormalFromMap()&#xD;&#xA;{&#xD;&#xA;    vec3 tangentNormal = texture(u_NormalMap, texcoord).xyz * 2.0 - 1.0;&#xD;&#xA;&#xD;&#xA;    vec3 Q1  = dFdx(position);&#xD;&#xA;    vec3 Q2  = dFdy(position);&#xD;&#xA;    vec2 st1 = dFdx(texcoord);&#xD;&#xA;    vec2 st2 = dFdy(texcoord);&#xD;&#xA;&#xD;&#xA;    vec3 N  = normalize(normal);&#xD;&#xA;    vec3 T  = normalize(Q1 * st2.t - Q2 * st1.t);&#xD;&#xA;    vec3 B  = -normalize(cross(N, T));&#xD;&#xA;    mat3 TBN = mat3(T, B, N);&#xD;&#xA;&#xD;&#xA;    return normalize(TBN * tangentNormal);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float DistributionGGX(vec3 N, vec3 H, float roughness)&#xD;&#xA;{&#xD;&#xA;    float a = roughness*roughness;&#xD;&#xA;    float a2 = a*a;&#xD;&#xA;    float NdotH = max(dot(N, H), 0.0);&#xD;&#xA;    float NdotH2 = NdotH*NdotH;&#xD;&#xA;&#xD;&#xA;    float nom   = a2;&#xD;&#xA;    float denom = (NdotH2 * (a2 - 1.0) + 1.0);&#xD;&#xA;    denom = PI * denom * denom;&#xD;&#xA;&#xD;&#xA;    return nom / denom;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float GeometrySchlickGGX(float NdotV, float roughness)&#xD;&#xA;{&#xD;&#xA;    float r = (roughness + 1.0);&#xD;&#xA;    float k = (r*r) / 8.0;&#xD;&#xA;&#xD;&#xA;    float nom   = NdotV;&#xD;&#xA;    float denom = NdotV * (1.0 - k) + k;&#xD;&#xA;&#xD;&#xA;    return nom / denom;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)&#xD;&#xA;{&#xD;&#xA;    float NdotV = max(dot(N, V), 0.0);&#xD;&#xA;    float NdotL = max(dot(N, L), 0.0);&#xD;&#xA;    float ggx2 = GeometrySchlickGGX(NdotV, roughness);&#xD;&#xA;    float ggx1 = GeometrySchlickGGX(NdotL, roughness);&#xD;&#xA;&#xD;&#xA;    return ggx1 * ggx2;&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 fresnelSchlick(float cosTheta, vec3 F0)&#xD;&#xA;{&#xD;&#xA;    return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);&#xD;&#xA;}&#xD;&#xA;&#xD;&#xA;vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)&#xD;&#xA;{&#xD;&#xA;    return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);&#xD;&#xA;} &#xD;&#xA;&#xD;&#xA;///////////////////////////////////////////////////////////////////////&#xD;&#xA;///////////////////////////////////////////////////////////////////////&#xD;&#xA;///////////////////////////////////////////////////////////////////////&#xD;&#xA;&#xD;&#xA;void main()&#xD;&#xA;{&#xD;&#xA;&#xD;&#xA;	// NOTE: Lighting calculations being done in world space.&#xD;&#xA;&#xD;&#xA;	vec3 baseColor = u_Material.color;&#xD;&#xA;	if (u_Material.has_color_texture)&#xD;&#xA;		baseColor = texture(u_DiffuseMap, texcoord).rgb;&#xD;&#xA;&#xD;&#xA;	float metalness = u_Material.metalness;&#xD;&#xA;	if (u_Material.has_metalness_texture)&#xD;&#xA;		metalness = texture(u_MetalnessMap, texcoord).r;&#xD;&#xA;&#xD;&#xA;	float roughness = u_Material.roughness;&#xD;&#xA;	if (u_Material.has_roughness_texture)&#xD;&#xA;		roughness = texture(u_RoughnessMap, texcoord).r;&#xD;&#xA;&#xD;&#xA;	vec3 emission = u_Material.emission;&#xD;&#xA;	if (u_Material.has_emission_texture)&#xD;&#xA;		emission = texture(u_EmissionMap, texcoord).rgb;&#xD;&#xA;&#xD;&#xA;	vec3 N = normalize(normal);&#xD;&#xA;	if (u_Material.has_normal_texture)&#xD;&#xA;		N = getNormalFromMap();&#xD;&#xA;&#xD;&#xA;	float ao = 0.0;&#xD;&#xA;	if (u_Material.has_ao_texture)&#xD;&#xA;		ao = texture(u_AoMap, texcoord).r;&#xD;&#xA;&#xD;&#xA;    vec3 V = normalize(u_CameraPosition - position);&#xD;&#xA;&#xD;&#xA;    // Disney us&#xD;&#xA;    vec3 F0 = vec3(0.04); &#xD;&#xA;    F0 = mix(F0, baseColor, metalness);&#xD;&#xA;&#xD;&#xA;    vec3 Lo = vec3(0.0);&#xD;&#xA;    for(int i = 0; i &lt; 1; i++) // only 1 pointlight at the moment&#xD;&#xA;    {&#xD;&#xA;        vec3 L = u_PointLights[i].position - position;&#xD;&#xA;        vec3 H = normalize(V + normalize(L));&#xD;&#xA;        float d = length(L);&#xD;&#xA;        float attenuation = 1.0 / (d * d);&#xD;&#xA;        vec3 radiance = 125 * u_PointLights[i].color * attenuation;&#xD;&#xA;		// --------------^ pointlight_intensity, without envmap&#xD;&#xA;		//                 objects come out way too dark without this factor.&#xD;&#xA;        //                 What's a good number depends on scene.&#xD;&#xA;&#xD;&#xA;        float NDF = DistributionGGX(N, H, roughness);   &#xD;&#xA;        float G = GeometrySmith(N, V, L, roughness);      &#xD;&#xA;        vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);&#xD;&#xA;        &#xD;&#xA;        // Cook-Torrance model&#xD;&#xA;        vec3 numerator = NDF * G * F; &#xD;&#xA;        float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + EPSILON;&#xD;&#xA;        vec3 specular = numerator / denominator;&#xD;&#xA;        &#xD;&#xA;        vec3 kS = F;&#xD;&#xA;        vec3 kD = vec3(1.0) - kS;&#xD;&#xA;        kD *= 1.0 - metalness;	  &#xD;&#xA;&#xD;&#xA;        float NdotL = max(dot(N, L), 0.0);        &#xD;&#xA;&#xD;&#xA;        Lo += (kD * baseColor / PI + specular) * radiance * NdotL;&#xD;&#xA;    }   &#xD;&#xA;&#xD;&#xA;    vec3 F = fresnelSchlickRoughness(max(dot(N, V), 0.0), F0, roughness);&#xD;&#xA;    &#xD;&#xA;    vec3 kS = F;&#xD;&#xA;    vec3 kD = 1.0 - kS;&#xD;&#xA;    kD *= 1.0 - metalness;&#xD;&#xA;    &#xD;&#xA;    // Sample irradiance map&#xD;&#xA;	float theta = acos(max(-1.0f, min(1.0f, N.y)));&#xD;&#xA;	float phi = atan(N.z, N.x);&#xD;&#xA;	if(phi &lt; 0.0f)&#xD;&#xA;		phi = phi + 2.0f * PI;&#xD;&#xA;	vec2 lookup = vec2(phi / (2.0 * PI), 1 - theta / PI);&#xD;&#xA;	vec3 irradiance = texture(u_IrradianceMap, lookup).rgb;&#xD;&#xA;    vec3 diffuse = irradiance * baseColor;&#xD;&#xA;    &#xD;&#xA;	// Sample reflectance map&#xD;&#xA;	vec3 wi = normalize(reflect(-V, N));&#xD;&#xA;	float theta2 = acos(max(-1.0f, min(1.0f, wi.y)));&#xD;&#xA;	float phi2 = atan(wi.z, wi.x);&#xD;&#xA;	if(phi2 &lt; 0.0f)&#xD;&#xA;		phi2 = phi2 + 2.0f * PI;&#xD;&#xA;	vec2 lookup2 = vec2(phi2 / (2.0 * PI), 1 - theta2 / PI);&#xD;&#xA;    const float MAX_LOD = 7.0;&#xD;&#xA;    vec3 specular = textureLod(u_ReflectanceMap, lookup2, roughness * MAX_LOD).rgb;    &#xD;&#xA;&#xD;&#xA;    vec3 ambient = (kD * diffuse + specular) * ao;&#xD;&#xA;&#xD;&#xA;	/////////////////////////////////////&#xD;&#xA;&#xD;&#xA;    vec3 color = ambient + emission + Lo;&#xD;&#xA;&#xD;&#xA;    // HDR tonemapping&#xD;&#xA;    color = color / (color + vec3(1.0));&#xD;&#xA;    // gamma correct&#xD;&#xA;    color = pow(color, vec3(1.0/2.2)); &#xD;&#xA;&#xD;&#xA;    FragColor = vec4(color, 1.0);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [2]: https://i.stack.imgur.com/GiwpJ.jpg&#xD;&#xA;  [3]: https://i.stack.imgur.com/ezUJ2.jpg&#xD;&#xA;  [4]: https://i.stack.imgur.com/3BhAP.jpg&#xD;&#xA;  [6]: https://i.stack.imgur.com/PjUFm.jpg&#xD;&#xA;  [7]: https://i.stack.imgur.com/wMYXp.jpg&#xD;&#xA;  [8]: https://i.stack.imgur.com/iMsKm.png&#xD;&#xA;  [10]: https://i.stack.imgur.com/U85zh.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42910" PostHistoryTypeId="1" PostId="13952" RevisionGUID="d13299e8-c586-432f-aaa7-a5f16fcf11f8" CreationDate="2024-03-02T13:00:00.067" UserId="21255" Text="Why is the indirect illumination (using IBL) in my PBR shader overpowering everything?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42911" PostHistoryTypeId="3" PostId="13952" RevisionGUID="d13299e8-c586-432f-aaa7-a5f16fcf11f8" CreationDate="2024-03-02T13:00:00.067" UserId="21255" Text="|rendering|lighting|physically-based|shading|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42912" PostHistoryTypeId="2" PostId="13953" RevisionGUID="ff3b2698-b3de-4cfa-b013-6c258ae9a8db" CreationDate="2024-03-02T16:42:37.773" UserId="445" Text="Your results look broadly correct to me. The problem is not in the lighting calculations, but in the simplicity of the scene.&#xD;&#xA;&#xD;&#xA;A shiny metal object is like a mirror except that it isn't flat. Your material doesn't **absorb** much light, so it reflects it instead, and will appear as bright as the surroundings (on average). Then, when you add a &quot;direct&quot; light on top of your IBL, the object is now brighter than the environment around it, because it is receiving more light than is represented in the environment map.&#xD;&#xA;&#xD;&#xA;Here are specific ways in which your render diverges from typical reality, and how you can fix them:&#xD;&#xA;&#xD;&#xA;1. **Your environment map already contains a bright light — the sun.** If your intention is for it to represent only “indirect” illumination and compute the “direct” illumination separately, then you must exclude the “direct” component from the environment map to avoid double-counting it.&#xD;&#xA;&#xD;&#xA;2. Most real objects are not made completely of highly reflective surfaces, but in your renders **you're displaying everything “chrome-plated”** (well, titanium-plated). That can be physically realistic, but it's not how most objects are. When you use materials that are (accurately for the subject) darker and more matte, the objects will look more like they should.&#xD;&#xA;&#xD;&#xA;2. You're currently rendering an object **floating in open air with nothing around it to shadow it.** Therefore, it will be well lit in the same kind of way an aircraft in flight would be. Objects on the ground or indoors have surroundings that partially prevent light from the sky from reaching them. If you're inside a room, you use an environment map which is a picture of that room, not the sky. If you're on the ground, the bottom half of the environment map should be ground, not ocean.&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42914" PostHistoryTypeId="50" PostId="13893" RevisionGUID="67cc943e-d0d8-428e-8f6d-8916da5eb237" CreationDate="2024-03-03T01:06:05.803" UserId="-1" />
  <row Id="42915" PostHistoryTypeId="5" PostId="13945" RevisionGUID="141e705b-907e-4eb0-80be-2022a94217a7" CreationDate="2024-03-03T11:54:07.357" UserId="13273" Comment="deleted 44 characters in body" Text="I have created a too large buffer with some vertex data (position, normal vector...).&#xD;&#xA;&#xD;&#xA;Within the render pipeline, I want to append new data to the end of the currently used buffer.&#xD;&#xA;To do this, I thought of binding this buffer as `GL_ARRAY_BUFFER` and `GL_SHADER_STORAGE_BUFFER` at the same time.&#xD;&#xA;&#xD;&#xA;Within the geometry shader, I only want to modify this buffer after the last vertex information used by this render call. So no input data will be changed.&#xD;&#xA;&#xD;&#xA;Is this allowed? Or do I HAVE to create a second separate buffer in which I store the generated data?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42916" PostHistoryTypeId="50" PostId="13885" RevisionGUID="a1435047-74f8-4fd5-9105-74f12061a2d0" CreationDate="2024-03-03T13:06:55.877" UserId="-1" />
  <row Id="42917" PostHistoryTypeId="5" PostId="13791" RevisionGUID="5da91f2a-1e1b-4ab1-99ff-0c6c78b8c50e" CreationDate="2024-03-03T16:09:53.507" UserId="7952" Comment="added 1767 characters in body" Text="Here are both images &quot;cleaned&quot; using simple luminance thresholding like I suggested in the comments. There was nothing special done to these images, a simple &quot;is the luminance below threshold for this texel&quot; is all that was done. The image was first converted to gray scale.&#xD;&#xA;&#xD;&#xA;If the scan was better quality with a higher resolution the results would better.&#xD;&#xA;&#xD;&#xA;The real challenge with this technique is finding the threshold, again a scan with higher resolution would help. But one of the images looked best at a cutoff of 0.55 and the other at 0.68. &#xD;&#xA;&#xD;&#xA;I did this in a small program that I threw together, but there must be an image tool that can do this easily. (I am no expert at tools that would be a question for the photoshop/gimp forums)&#xD;&#xA;&#xD;&#xA;The program was just the stbi image header (a c++ header file that can load and save various image types like jpg and png) and a loop that spun over the values computed the gray scale, tested the threshold, and output the result.&#xD;&#xA;&#xD;&#xA;Here are the results:&#xD;&#xA;&#xD;&#xA; - https://i.stack.imgur.com/VJkXk.jpg   &#xD;&#xA;   https://i.stack.imgur.com/lcOEh.jpg&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA; &#xD;&#xA;    #define STB_IMAGE_IMPLEMENTATION&#xD;&#xA;    #include &quot;stb_image/stb_image.h&quot;&#xD;&#xA;    #define STB_IMAGE_WRITE_IMPLEMENTATION&#xD;&#xA;    #include &quot;stb_image/stb_image_write.h&quot;&#xD;&#xA;&#xD;&#xA;    int main(int argc, char **argv) {&#xD;&#xA;       int width, height, channels;&#xD;&#xA;       if( argc &lt; 1 ) {&#xD;&#xA;          printf(&quot;Full path to image must be the first argument passed on the command line.\n&quot;); &#xD;&#xA;          return -1; &#xD;&#xA;       }&#xD;&#xA;       unsigned char *img = stbi_load(argv[0], &amp;width, &amp;height, &amp;channels, 0);&#xD;&#xA;       if(img == NULL || channels &lt; 3) {&#xD;&#xA;           printf(&quot;Error in loading the image, expected color image\n&quot;);&#xD;&#xA;           return -1;&#xD;&#xA;       }&#xD;&#xA;       printf(&quot;Loaded image with a width of %dpx, a height of %dpx and %d channels\n&quot;, width, height, channels);&#xD;&#xA; &#xD;&#xA;   &#xD;&#xA;       // convert to gray scale, ignore alpha channel if it exists&#xD;&#xA;       for( int n=0; n &lt; width*height*channels; n+=channels)&#xD;&#xA;       {&#xD;&#xA;          int grayscale = img[n];&#xD;&#xA;          grayscale += img[n+1];&#xD;&#xA;          grayscale += image[n+2];&#xD;&#xA;          img[n] = img[n+1] = img[n+2] = (unsigned char)(grayscale/3);&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;       // filter 0.56f is the threshold here, it is converted into the range of an 8 bit image (0-256).&#xD;&#xA;       // the threshold must be a value between zero and 1&#xD;&#xA;       int threshold = (int)(0.56f * 256);&#xD;&#xA;       for( int n=0; n&lt;width*height*channels; n+=channels)&#xD;&#xA;       {&#xD;&#xA;          // if the pixel is below the threshold then make it white&#xD;&#xA;          if( image[n] &lt; threshold ){&#xD;&#xA;              img[n] = image[n+1] = image[n+2] = 256;&#xD;&#xA;          }&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;      // save the image to a bmp ( don't overwrite original file)&#xD;&#xA;      stbi_write_bmp(&quot;output.bmp&quot;, width, height, channels, img);&#xD;&#xA;&#xD;&#xA;      return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VJkXk.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/lcOEh.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42918" PostHistoryTypeId="5" PostId="13791" RevisionGUID="e227f8a3-3fb7-44cd-8ee3-c9feae300a6c" CreationDate="2024-03-03T19:13:18.010" UserId="7952" Comment="fixed a bug" Text="Here are both images &quot;cleaned&quot; using simple luminance thresholding like I suggested in the comments. There was nothing special done to these images, a simple &quot;is the luminance below threshold for this texel&quot; is all that was done. The image was first converted to gray scale.&#xD;&#xA;&#xD;&#xA;If the scan was better quality with a higher resolution the results would better.&#xD;&#xA;&#xD;&#xA;The real challenge with this technique is finding the threshold, again a scan with higher resolution would help. But one of the images looked best at a cutoff of 0.55 and the other at 0.68. &#xD;&#xA;&#xD;&#xA;I did this in a small program that I threw together, but there must be an image tool that can do this easily. (I am no expert at tools that would be a question for the photoshop/gimp forums)&#xD;&#xA;&#xD;&#xA;The program was just the stbi image header (a c++ header file that can load and save various image types like jpg and png) and a loop that spun over the values computed the gray scale, tested the threshold, and output the result.&#xD;&#xA;&#xD;&#xA;Here are the results:&#xD;&#xA;&#xD;&#xA; - https://i.stack.imgur.com/VJkXk.jpg   &#xD;&#xA;   https://i.stack.imgur.com/lcOEh.jpg&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;    #include &lt;stdio.h&gt;&#xD;&#xA;    #include &lt;stdlib.h&gt;&#xD;&#xA; &#xD;&#xA;    #define STB_IMAGE_IMPLEMENTATION&#xD;&#xA;    #include &quot;stb_image/stb_image.h&quot;&#xD;&#xA;    #define STB_IMAGE_WRITE_IMPLEMENTATION&#xD;&#xA;    #include &quot;stb_image/stb_image_write.h&quot;&#xD;&#xA;&#xD;&#xA;    int main(int argc, char **argv) {&#xD;&#xA;       int width, height, channels;&#xD;&#xA;       if( argc &lt; 1 ) {&#xD;&#xA;          printf(&quot;Full path to image must be the first argument passed on the command line.\n&quot;); &#xD;&#xA;          return -1; &#xD;&#xA;       }&#xD;&#xA;       unsigned char *img = stbi_load(argv[0], &amp;width, &amp;height, &amp;channels, 0);&#xD;&#xA;       if(img == NULL || channels &lt; 3) {&#xD;&#xA;           printf(&quot;Error in loading the image, expected color image\n&quot;);&#xD;&#xA;           return -1;&#xD;&#xA;       }&#xD;&#xA;       printf(&quot;Loaded image with a width of %dpx, a height of %dpx and %d channels\n&quot;, width, height, channels);&#xD;&#xA; &#xD;&#xA;   &#xD;&#xA;       // convert to gray scale, ignore alpha channel if it exists&#xD;&#xA;       for( int n=0; n &lt; width*height*channels; n+=channels)&#xD;&#xA;       {&#xD;&#xA;          int grayscale = img[n];&#xD;&#xA;          grayscale += img[n+1];&#xD;&#xA;          grayscale += image[n+2];&#xD;&#xA;          img[n] = img[n+1] = img[n+2] = (unsigned char)(grayscale/3);&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;       // filter 0.56f is the threshold here, it is converted into the range of an 8 bit image (0-256).&#xD;&#xA;       // the threshold must be a value between zero and 1&#xD;&#xA;       int threshold = (int)(0.56f * 256);&#xD;&#xA;       for( int n=0; n&lt;width*height*channels; n+=channels)&#xD;&#xA;       {&#xD;&#xA;          // if the pixel is below the threshold then make it white&#xD;&#xA;          if( image[n] &lt; threshold ){&#xD;&#xA;              img[n] = image[n+1] = image[n+2] = 255;&#xD;&#xA;          }&#xD;&#xA;       }&#xD;&#xA;&#xD;&#xA;      // save the image to a bmp ( don't overwrite original file)&#xD;&#xA;      stbi_write_bmp(&quot;output.bmp&quot;, width, height, channels, img);&#xD;&#xA;&#xD;&#xA;      return 0;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/VJkXk.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/lcOEh.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="42919" PostHistoryTypeId="2" PostId="13954" RevisionGUID="408a292a-734e-47d5-82f6-2f672f6015a1" CreationDate="2024-03-04T12:55:55.030" UserId="17299" Text="Suppose I want to render out 6 cubemap cameras (90 degree FOV etc.) with the intention of combining them together in post-production into an equirectangular (latlong, 2:1) image.&#xD;&#xA;&#xD;&#xA;Suppose I also know the intended final resolution of the equirectangular image - for arguments sake, let's say it's 4096 x 2048.&#xD;&#xA;&#xD;&#xA;What resolution of each individual cubemap face would I need in order for there to be no perceivable loss of resolution when going from cubemap -&gt; equirectangular?&#xD;&#xA;&#xD;&#xA;The first, perhaps naïve thought is that the width/height of the cubemap image would need to be a quarter of the size of the final equirectangular image, but it seems to me that because of the reprojection, some fidelity will be lost, and that I would actually need a higher resolution cubemap face to start from, but I can't find any reference to a formula for this online. I can of course go via trial and error, comparing against a 'ground truth' spherical camera rendering of the same scene, but I'm just wondering if there is an efficient way of working this out." ContentLicense="CC BY-SA 4.0" />
  <row Id="42921" PostHistoryTypeId="1" PostId="13954" RevisionGUID="408a292a-734e-47d5-82f6-2f672f6015a1" CreationDate="2024-03-04T12:55:55.030" UserId="17299" Text="Formula for cubemap resolution for intended equirectangular resolution" ContentLicense="CC BY-SA 4.0" />
  <row Id="42922" PostHistoryTypeId="3" PostId="13954" RevisionGUID="408a292a-734e-47d5-82f6-2f672f6015a1" CreationDate="2024-03-04T12:55:55.030" UserId="17299" Text="|projections|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42923" PostHistoryTypeId="2" PostId="13955" RevisionGUID="4dcb3ce8-780c-4a2e-973b-48baf1c58669" CreationDate="2024-03-05T13:52:53.123" UserId="13273" Text="Assuming your final image is the world map (see Figure 1), if you were looking at the equator, the `cubemap width * 4` would fit perfectly. But: If you move north or south of the equator, your pixels in the equirectangular image will remain constant, while the number of cubemap pixels will decrease. If you are at the poles, you will have about 1 pixel in the cubemap and still 4096 pixels in the equirectangular image. Figure 2 shows how a cubemap is mapped onto an equirectangular image. There you can see that the black lines at the bottom and top represent about 1 pixel in the cubemap.&#xD;&#xA;&#xD;&#xA;**Figure1**&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;**Figure2**&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/hqErE.jpg&#xD;&#xA;  [2]: https://i.stack.imgur.com/DRuSE.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42925" PostHistoryTypeId="50" PostId="10955" RevisionGUID="93d4e300-64d1-41e8-ad71-809ddb5a9d4d" CreationDate="2024-03-06T00:04:26.290" UserId="-1" />
  <row Id="42926" PostHistoryTypeId="2" PostId="13956" RevisionGUID="c2503a15-85a7-4b4f-b1e8-b06661df7cae" CreationDate="2024-03-06T12:05:08.757" UserId="21269" Text="https://computergraphics.stackexchange.com/questions/12819/how-to-determine-transformation-matrix-for-an-object-given-a-graph?newreg=952eeb36a8d847e9bf8cddfe030a3d7b&#xD;&#xA;&#xD;&#xA;This is a problem indeed similar to this one. And I've approached it in the same way like there.&#xD;&#xA;&#xD;&#xA;Given:&#xD;&#xA;A line AB A(0,0),B(1,1).&#xD;&#xA;&#xD;&#xA;It is transformed to &#xD;&#xA;A'(0,-1),B'(-1,0)&#xD;&#xA;&#xD;&#xA;Now, I need to find the transformation matrix.&#xD;&#xA;&#xD;&#xA;I begin&#xD;&#xA;&#xD;&#xA;TM.A=B&#xD;&#xA;&#xD;&#xA;Where TM=Transformation Matrix&#xD;&#xA;&#xD;&#xA;A=given coordinates&#xD;&#xA;&#xD;&#xA;B=transformed coordinates&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/imTLA.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42928" PostHistoryTypeId="1" PostId="13956" RevisionGUID="c2503a15-85a7-4b4f-b1e8-b06661df7cae" CreationDate="2024-03-06T12:05:08.757" UserId="21269" Text="How to determine the transformation matrix from given initial and transformed co-ordinates?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42929" PostHistoryTypeId="3" PostId="13956" RevisionGUID="c2503a15-85a7-4b4f-b1e8-b06661df7cae" CreationDate="2024-03-06T12:05:08.757" UserId="21269" Text="|transformations|mathematics|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42930" PostHistoryTypeId="50" PostId="10248" RevisionGUID="932d53b5-d526-48b7-a6d7-53f58e99c463" CreationDate="2024-03-06T15:07:30.943" UserId="-1" />
  <row Id="42931" PostHistoryTypeId="2" PostId="13957" RevisionGUID="9cc96df6-185f-49af-a5e1-0a4680016386" CreationDate="2024-03-06T21:25:47.007" UserId="21272" Text="I want to know about&#xD;&#xA;&quot;If there is branch command in compute shader, &#xD;&#xA;and **it leads some workgroup ends earlier than others**, &#xD;&#xA;then will the 'processing units' allocated for that workgroup be **used for another workgroup which is not processed yet?(before complete of other still running workgroups)**&quot;&#xD;&#xA;&#xD;&#xA;I know this is not important for implementation, but I want to know about performance factors." ContentLicense="CC BY-SA 4.0" />
  <row Id="42933" PostHistoryTypeId="1" PostId="13957" RevisionGUID="9cc96df6-185f-49af-a5e1-0a4680016386" CreationDate="2024-03-06T21:25:47.007" UserId="21272" Text="GLSL Compute Shader Workgroup Execution" ContentLicense="CC BY-SA 4.0" />
  <row Id="42934" PostHistoryTypeId="3" PostId="13957" RevisionGUID="9cc96df6-185f-49af-a5e1-0a4680016386" CreationDate="2024-03-06T21:25:47.007" UserId="21272" Text="|compute-shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42935" PostHistoryTypeId="2" PostId="13958" RevisionGUID="c1e7aede-172c-46a1-afb9-f30a090c1648" CreationDate="2024-03-07T06:42:01.363" UserId="19537" Text="I am not sure whether this is what you need, hope it helps:&#xD;&#xA;&#xD;&#xA;To transform from one line to the other, **one can try to use the homogeneous coordinates**, which will incorporate the potential translation of the line. So we can formulate the problem in the following way. Notice that the length of the line stays the same, therefore we don't need to consider scaling. Thus, this case can be modeled as rigid body transformation:&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;\cos\theta &amp; -\sin\theta &amp; t_x\\&#xD;&#xA;\sin\theta &amp; \cos\theta &amp; t_y\\&#xD;&#xA;0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;0 &amp; 1\\&#xD;&#xA;0 &amp; 1\\&#xD;&#xA;1 &amp; 1\\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;=&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;0 &amp; -1\\&#xD;&#xA;-1 &amp; 0\\&#xD;&#xA;1 &amp; 1\\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;Solving the above linear equations yields:&#xD;&#xA;$\cos\theta = 0, \sin\theta = 1, t_x = 0, t_y = -1$. So this tells us:&#xD;&#xA;- Line AB is first rotated around $(0, 0)$ by 90$\deg$ (counter-clockwise), we have: CD $(0, 0)\rightarrow(-1, 1)$.&#xD;&#xA;- Then we apply translation: CD -&gt; A'B', moving the line down the y-axis by 1: $(0, -1)\rightarrow(-1, 0)$.&#xD;&#xA;&#xD;&#xA;So basically, if you know it is gonna be rigid body transformation, then approach the problem in the above way. A more general 2D transformation will be (given in homogeneous coordinate system):&#xD;&#xA;$$&#xD;&#xA;\begin{pmatrix}&#xD;&#xA;a &amp; b &amp; c\\&#xD;&#xA;d &amp; e &amp; f\\&#xD;&#xA;0 &amp; 0 &amp; 1\\&#xD;&#xA;\end{pmatrix}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;which takes translation, shearing, scaling and rotation into account. Since this representation has more unknown variables, it requires more information to solve the whole system." ContentLicense="CC BY-SA 4.0" />
  <row Id="42937" PostHistoryTypeId="2" PostId="13959" RevisionGUID="95327515-99f5-4c07-909f-9890ac541d68" CreationDate="2024-03-07T07:43:10.810" UserId="13273" Text="Yes, the workgroups are independent of each other. This means that when one workgroup has finished its work, it is released and the next workgroup can start its work while other workgroups are still in progress. Even better! If there are two different compute shaders (different code) that need to be executed, the released workgroup capacity can be used by the second compute shader workgroup while the last workgroups of the first compute shader are executed at the same time.&#xD;&#xA;&#xD;&#xA;When branching, the total calculation time of a compute shader can vary. Let's take a look at an example:&#xD;&#xA;&#xD;&#xA;**Example:** &#xD;&#xA;&#xD;&#xA;Let's assume we have 20 workgroups whose program code has a branching option. And only 1 workgroup takes 1.5 times longer because of this branching, let's call it workgroup 1.&#xD;&#xA;Let's assume that your GPU can process 19 workgroups simultaneously. So the GPU loads 19 workgroups and after one of the workgroups has finished its work, the last workgroup is loaded.&#xD;&#xA;&#xD;&#xA;The minimum execution time of all workgroups would be: $2 * x$, where x is the time of one of the 19 fast workgroups.&#xD;&#xA;&#xD;&#xA;But you can also be unlucky. That is, the 19 fast workgroups are executed first, and workgroup 1 (the slow one) is executed at the end. Then your execution time is: $x + 1.5 * x = 2.5 * x$.&#xD;&#xA;&#xD;&#xA;To be honest, there is a time offset for loading the workgroups and memory etc. which is not specified in this form to keep it clear." ContentLicense="CC BY-SA 4.0" />
  <row Id="42939" PostHistoryTypeId="2" PostId="13960" RevisionGUID="2b85c8a4-d48a-41ff-aa73-70dbe29d62dc" CreationDate="2024-03-07T14:13:37.600" UserId="7952" Text="Buffer sharing like this is a common practice in OpenGL, in Vulkan it is even encouraged. So there should be no spec reason that this isn't allowed.&#xD;&#xA;&#xD;&#xA;However there is still a chance that everything looks good on GPU A but on GPU B frames don't render correctly. This can happen if OpenGL doesn't handle the barrier between the two correctly. So one frame is still writing the data while another frame sneaks in and starts reading it.&#xD;&#xA;&#xD;&#xA;OpenGL will &quot;probably&quot; get it right, but I would give a long hard look at memory barrier requirements in GL just to make sure." ContentLicense="CC BY-SA 4.0" />
  <row Id="42941" PostHistoryTypeId="2" PostId="13961" RevisionGUID="35082714-5797-46ef-8f1f-cac28d59bbfc" CreationDate="2024-03-07T14:40:56.143" UserId="7952" Text="&#xD;&#xA;If we only talk about individual compute shaders. Then, inside a wave, the entire wave will be held up waiting for all compute shaders inside that wave to complete. The compute shaders in a wave run in lockstep, branching causes divergence and can effect performance per a wave. We don't work with waves at the API level though, instead we work with workgroups. A workgroup can consist of multiple waves depending on the settings, so a new workgroup could get held up if there isn't enough waves available to send a new workgroup.&#xD;&#xA;&#xD;&#xA;Finding out the wave size of a GPU and setting workgroup size to be a multiple of the wave size (usually 1x or 2x) can help mitigate the issue and help overall performance.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42943" PostHistoryTypeId="2" PostId="13962" RevisionGUID="6760411a-8786-4da0-9084-49abb7283360" CreationDate="2024-03-07T17:00:12.200" UserId="20471" Text="I have a forward path tracer. Essentially, it looks flat:&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;This is the backward path tracer in comparison:&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;My question is: How do I get pseudorandom lighting like with the backward path tracer, when the eye ray always hits a light in forward path tracing?&#xD;&#xA;&#xD;&#xA;Here is my code for the forward path tracer:&#xD;&#xA;&#xD;&#xA;    float trace_path_forward2(const vec3 eye, const vec3 direction, const float hue, const float eta)&#xD;&#xA;    {&#xD;&#xA;    	const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));&#xD;&#xA;    &#xD;&#xA;    	const vec3 light_o = get_random_light_pos(50, eye, direction, hue, eta);//getRandomPointOnTriangle(A.pos, B.pos, C.pos);&#xD;&#xA;    	const vec3 light_d = RandomUnitVector(prng_state);//vec3(0);//cosWeightedRandomHemisphereDirection(get_normal_by_light_index(tri_index), prng_state);&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	const float energy = 1.0;&#xD;&#xA;    &#xD;&#xA;    	int step_count = 0;&#xD;&#xA;    	vec3 step_locations[max_bounces + 2];&#xD;&#xA;    	vec3 step_directions[max_bounces + 2];&#xD;&#xA;    &#xD;&#xA;    	step_locations[step_count] = light_o;&#xD;&#xA;    	step_directions[step_count] = light_d;&#xD;&#xA;    	step_count++;&#xD;&#xA;    &#xD;&#xA;    	if(false == is_clear_line_of_sight(eye, light_o))&#xD;&#xA;    	{	&#xD;&#xA;    		vec3 o = light_o;&#xD;&#xA;    		vec3 d = light_d;&#xD;&#xA;    &#xD;&#xA;    		for(int i = 0; i &lt; max_bounces; i++)&#xD;&#xA;    		{&#xD;&#xA;    			traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o, 0.001, d, 10000.0, 0);&#xD;&#xA;    &#xD;&#xA;    			if(rayPayload.dist == -1)&#xD;&#xA;    				return 0.0;&#xD;&#xA;    &#xD;&#xA;    			const vec3 hitPos = o + d * rayPayload.dist;&#xD;&#xA;    &#xD;&#xA;    			o = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    			d = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;    			&#xD;&#xA;    			step_locations[step_count] = o;&#xD;&#xA;    			step_directions[step_count] = d;&#xD;&#xA;    			step_count++;&#xD;&#xA;    &#xD;&#xA;    			if(true == is_clear_line_of_sight(eye, step_locations[step_count - 1]))&#xD;&#xA;    				break;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	step_locations[step_count] = eye;&#xD;&#xA;    	step_directions[step_count] = direction;&#xD;&#xA;    	step_count++;&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    	// Reverse the path&#xD;&#xA;    	uint start = 0;&#xD;&#xA;    	uint end = step_count - 1;&#xD;&#xA;    &#xD;&#xA;    	while(start &lt; end) &#xD;&#xA;    	{ &#xD;&#xA;    		vec3 temp = step_locations[start];  &#xD;&#xA;    		step_locations[start] = step_locations[end]; &#xD;&#xA;    		step_locations[end] = temp; &#xD;&#xA;    &#xD;&#xA;    		temp = step_directions[start];  &#xD;&#xA;    		step_directions[start] = step_directions[end]; &#xD;&#xA;    		step_directions[end] = temp; &#xD;&#xA;    &#xD;&#xA;    		start++;&#xD;&#xA;    		end--; &#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	&#xD;&#xA;    	for(int i = 1; i &lt; step_count - 1; i++)&#xD;&#xA;    	{&#xD;&#xA;    		step_directions[i] = (step_locations[i + 1] - step_locations[i]);&#xD;&#xA;    	}&#xD;&#xA;    	&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	float ret_colour = 0;&#xD;&#xA;    	float local_colour = energy;&#xD;&#xA;    	float total = 0;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; step_count - 1; i++)&#xD;&#xA;    	{&#xD;&#xA;    		vec3 step_o = step_locations[i];&#xD;&#xA;    		vec3 step_d = step_directions[i];&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    		traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, step_o, 0.001, step_d, 10000.0, 0);&#xD;&#xA;    &#xD;&#xA;    		local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    &#xD;&#xA;    		total += mask.r;&#xD;&#xA;    		total += mask.g;&#xD;&#xA;    		total += mask.b;&#xD;&#xA;    &#xD;&#xA;    		if(i == step_count - 2 || (rayPayload.color.r &gt; 1.0 || rayPayload.color.g &gt; 1.0 || rayPayload.color.b &gt; 1.0))&#xD;&#xA;    		{&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    			break;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return ret_colour / total;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;The code for the backward path tracer is:&#xD;&#xA;&#xD;&#xA;    float trace_path_backward(const int steps, const vec3 origin, const vec3 direction, const float hue, const float eta)&#xD;&#xA;    {&#xD;&#xA;    	vec3 o = origin;&#xD;&#xA;    	vec3 d = direction;&#xD;&#xA;    &#xD;&#xA;    	const float energy = 1;&#xD;&#xA;    	const float caustic_energy = 1;//energy;&#xD;&#xA;    &#xD;&#xA;    	float ret_colour = 0;&#xD;&#xA;    	float local_colour = energy;&#xD;&#xA;    	float total = 0;&#xD;&#xA;    &#xD;&#xA;    	bool doing_refraction_caustic = false;&#xD;&#xA;    &#xD;&#xA;    	const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; steps; i++)&#xD;&#xA;    	{&#xD;&#xA;    		const float tmin = 0.001;&#xD;&#xA;    		const float tmax = 10000.0;&#xD;&#xA;    &#xD;&#xA;    		traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o, tmin, d, tmax, 0);&#xD;&#xA;    &#xD;&#xA;    		total += mask.r;&#xD;&#xA;    		total += mask.g;&#xD;&#xA;    		total += mask.b;&#xD;&#xA;    &#xD;&#xA;    		if(doing_refraction_caustic)&#xD;&#xA;    		{&#xD;&#xA;    			local_colour += caustic_energy*(rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    			doing_refraction_caustic = false;&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		// If hit the sky&#xD;&#xA;    		if(rayPayload.dist == -1.0)&#xD;&#xA;    		{&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    			break;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		// If this is simply the final step&#xD;&#xA;    		// then don't throw away perfectly &#xD;&#xA;    		// good data&#xD;&#xA;    		if(i == steps - 1)&#xD;&#xA;    		{&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    			break;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		// Hit a light&#xD;&#xA;    		if(rayPayload.color.r &gt; 1&#xD;&#xA;    		|| rayPayload.color.g &gt; 1&#xD;&#xA;    		|| rayPayload.color.b &gt; 1)&#xD;&#xA;    		{&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    			break;&#xD;&#xA;    		}&#xD;&#xA;    &#xD;&#xA;    		vec3 hitPos = o + d * rayPayload.dist;&#xD;&#xA;    &#xD;&#xA;    		if(stepAndOutputRNGFloat(prng_state) &lt;= rayPayload.opacity)&#xD;&#xA;    		{&#xD;&#xA;    			RayPayload r = rayPayload;&#xD;&#xA;    			&#xD;&#xA;    			if(rayPayload.subsurface &gt; 0)&#xD;&#xA;    			{&#xD;&#xA;    				vec3 o_subsurface = hitPos - rayPayload.normal * 0.001 + RandomUnitVector(prng_state)*0.001;&#xD;&#xA;    				vec3 d_subsurface = RandomUnitVector(prng_state);&#xD;&#xA;    &#xD;&#xA;    				traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o_subsurface, tmin, d_subsurface, tmax, 0);&#xD;&#xA;    &#xD;&#xA;    				total += mask.r;&#xD;&#xA;    				total += mask.g;&#xD;&#xA;    				total += mask.b;&#xD;&#xA;    &#xD;&#xA;    				local_colour += rayPayload.subsurface*(rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			if(rayPayload.reflector &gt; 0)&#xD;&#xA;    			{&#xD;&#xA;    				vec3 o_reflect = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    				vec3 d_reflect = reflect(d, rayPayload.normal);&#xD;&#xA;    &#xD;&#xA;    				traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o_reflect, tmin, d_reflect, tmax, 0);&#xD;&#xA;    &#xD;&#xA;    				total += mask.r;&#xD;&#xA;    				total += mask.g;&#xD;&#xA;    				total += mask.b;&#xD;&#xA;    &#xD;&#xA;    				local_colour += rayPayload.reflector*(rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			rayPayload = r;&#xD;&#xA;    &#xD;&#xA;    			vec3 o_scatter = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    			vec3 d_scatter = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;    &#xD;&#xA;    			o = o_scatter;&#xD;&#xA;    			d = d_scatter;&#xD;&#xA;    		}&#xD;&#xA;    		else&#xD;&#xA;    		{&#xD;&#xA;    			doing_refraction_caustic = true;&#xD;&#xA;    &#xD;&#xA;    			vec3 o_transparent = vec3(0.0);&#xD;&#xA;    			vec3 d_transparent = vec3(0.0);&#xD;&#xA;    &#xD;&#xA;    			// Incoming&#xD;&#xA;    			if(dot(d, rayPayload.normal) &lt;= 0.0)&#xD;&#xA;    			{&#xD;&#xA;    				o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    				d_transparent = refract(d, rayPayload.normal, eta);&#xD;&#xA;    			}&#xD;&#xA;    			else // Outgoing&#xD;&#xA;    			{&#xD;&#xA;    				vec3 temp_dir = refract(d, -rayPayload.normal, 1.0 / eta);&#xD;&#xA;    &#xD;&#xA;    				if(temp_dir != vec3(0.0))&#xD;&#xA;    				{&#xD;&#xA;    					o_transparent = hitPos.xyz + rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = mix(temp_dir, RandomUnitVector(prng_state), rayPayload.subsurface);//	temp_dir;&#xD;&#xA;    				}&#xD;&#xA;    				else&#xD;&#xA;    				{&#xD;&#xA;    					// Total internal reflection&#xD;&#xA;    					o_transparent = hitPos.xyz - rayPayload.normal * 0.01f;&#xD;&#xA;    					d_transparent = mix(reflect(d, -rayPayload.normal), RandomUnitVector(prng_state), rayPayload.subsurface);//reflect(d, -rayPayload.normal);&#xD;&#xA;    				}&#xD;&#xA;    			}&#xD;&#xA;    &#xD;&#xA;    			o = o_transparent;&#xD;&#xA;    			d = normalize(d_transparent);&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return ret_colour / total;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Any comments or questions are appreciated. I think that I'm missing something that might be obvious to another person. If there's anything that I can add to this question, please let me know.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/gZNWq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/2ggqR.jpg&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="42945" PostHistoryTypeId="1" PostId="13962" RevisionGUID="6760411a-8786-4da0-9084-49abb7283360" CreationDate="2024-03-07T17:00:12.200" UserId="20471" Text="Forward path tracing versus backward path tracing. How may I achieve realistic shading in forward path tracing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42946" PostHistoryTypeId="3" PostId="13962" RevisionGUID="6760411a-8786-4da0-9084-49abb7283360" CreationDate="2024-03-07T17:00:12.200" UserId="20471" Text="|raytracing|pathtracing|c++|vulkan|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42951" PostHistoryTypeId="50" PostId="12259" RevisionGUID="8f3abe66-506c-4eb8-a2fb-80eb94ddf20d" CreationDate="2024-03-07T19:04:40.567" UserId="-1" />
  <row Id="42952" PostHistoryTypeId="2" PostId="13964" RevisionGUID="357dc898-df84-471a-9a47-8ae3d668f806" CreationDate="2024-03-07T19:23:42.343" UserId="20471" Text="I swear that I've been struggling with this code for months, and after a hiatus, I have now mostly solved the problem. I just need to add in reflections and refractions. &#xD;&#xA;&#xD;&#xA;Instead of getting line of sight between the eye and some points, I am now getting the line of sight with the first hitpos generated by tracing the ray from the eye into the scene. I am also not overwriting the directions taken by the rays. Thank you so much Enigmatisms!&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;    float trace_path_forward2(const vec3 eye, const vec3 direction, const float hue, const float eta)&#xD;&#xA;    {&#xD;&#xA;    	const vec3 mask = hsv2rgb(vec3(hue, 1.0, 1.0));&#xD;&#xA;    &#xD;&#xA;    	const vec3 light_o = get_random_light_pos(50, eye, direction, hue, eta);&#xD;&#xA;    	const vec3 light_d = RandomUnitVector(prng_state);&#xD;&#xA;    &#xD;&#xA;    	const float energy = 1.0;&#xD;&#xA;    &#xD;&#xA;    	int step_count = 0;&#xD;&#xA;    	vec3 step_locations[max_bounces + 3];&#xD;&#xA;    	vec3 step_directions[max_bounces + 3];&#xD;&#xA;    &#xD;&#xA;    	traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, eye, 0.001, direction, 10000.0, 0);&#xD;&#xA;    &#xD;&#xA;    	if(rayPayload.dist == -1)&#xD;&#xA;    		return 0.0;&#xD;&#xA;    &#xD;&#xA;    	const vec3 first_hit_pos = eye + direction * rayPayload.dist;&#xD;&#xA;    &#xD;&#xA;    	step_locations[step_count] = light_o;&#xD;&#xA;    	step_directions[step_count] = light_d;&#xD;&#xA;    	step_count++;&#xD;&#xA;    &#xD;&#xA;    	if(false == is_clear_line_of_sight(first_hit_pos, light_o))&#xD;&#xA;    	{	&#xD;&#xA;    		vec3 o = light_o;&#xD;&#xA;    		vec3 d = light_d;&#xD;&#xA;    &#xD;&#xA;    		for(int i = 0; i &lt; max_bounces; i++)&#xD;&#xA;    		{&#xD;&#xA;    			traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, o, 0.001, d, 10000.0, 0);&#xD;&#xA;    &#xD;&#xA;    			if(rayPayload.dist == -1)&#xD;&#xA;    				return 0.0;&#xD;&#xA;    &#xD;&#xA;    			const vec3 hitPos = o + d * rayPayload.dist;&#xD;&#xA;    &#xD;&#xA;    			o = hitPos + rayPayload.normal * 0.01;&#xD;&#xA;    			d = cosWeightedRandomHemisphereDirection(rayPayload.normal, prng_state);&#xD;&#xA;    			&#xD;&#xA;    			step_locations[step_count] = o;&#xD;&#xA;    			step_directions[step_count] = d;&#xD;&#xA;    			step_count++;&#xD;&#xA;    &#xD;&#xA;    			if(true == is_clear_line_of_sight(first_hit_pos, step_locations[step_count - 1]))&#xD;&#xA;    				break;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	step_locations[step_count] = first_hit_pos;&#xD;&#xA;    	step_directions[step_count] = light_d;&#xD;&#xA;    	step_count++;&#xD;&#xA;    &#xD;&#xA;    	step_locations[step_count] = eye;&#xD;&#xA;    	step_directions[step_count] = direction;&#xD;&#xA;    	step_count++;&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	// Reverse the path&#xD;&#xA;    	uint start = 0;&#xD;&#xA;    	uint end = step_count - 1;&#xD;&#xA;    &#xD;&#xA;    	while(start &lt; end) &#xD;&#xA;    	{ &#xD;&#xA;    		vec3 temp = step_locations[start];  &#xD;&#xA;    		step_locations[start] = step_locations[end]; &#xD;&#xA;    		step_locations[end] = temp; &#xD;&#xA;    &#xD;&#xA;    		temp = step_directions[start];&#xD;&#xA;    		step_directions[start] = step_directions[end]; &#xD;&#xA;    		step_directions[end] = temp; &#xD;&#xA;    &#xD;&#xA;    		start++;&#xD;&#xA;    		end--; &#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    &#xD;&#xA;    	float ret_colour = 0;&#xD;&#xA;    	float local_colour = energy;&#xD;&#xA;    	float total = 0;&#xD;&#xA;    &#xD;&#xA;    	for(int i = 0; i &lt; step_count - 1; i++)&#xD;&#xA;    	{&#xD;&#xA;    		vec3 step_o = step_locations[i];&#xD;&#xA;    		vec3 step_d = step_directions[i];&#xD;&#xA;    &#xD;&#xA;    		traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, step_o, 0.001, step_d, 10000.0, 0);&#xD;&#xA;    &#xD;&#xA;    		local_colour *= (rayPayload.color.r*mask.r + rayPayload.color.g*mask.g + rayPayload.color.b*mask.b);&#xD;&#xA;    &#xD;&#xA;    		total += mask.r;&#xD;&#xA;    		total += mask.g;&#xD;&#xA;    		total += mask.b;&#xD;&#xA;    &#xD;&#xA;    		if(i == step_count - 2 || &#xD;&#xA;    		(rayPayload.color.r &gt; 1.0 || &#xD;&#xA;    		rayPayload.color.g &gt; 1.0 || &#xD;&#xA;    		rayPayload.color.b &gt; 1.0))&#xD;&#xA;    		{&#xD;&#xA;    			ret_colour += local_colour;&#xD;&#xA;    			break;&#xD;&#xA;    		}&#xD;&#xA;    	}&#xD;&#xA;    &#xD;&#xA;    	return ret_colour / total;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/7Dc9K.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42954" PostHistoryTypeId="50" PostId="13886" RevisionGUID="40ad19f3-f7e5-4658-a79c-f570f892de72" CreationDate="2024-03-07T20:05:15.787" UserId="-1" />
  <row Id="42959" PostHistoryTypeId="50" PostId="13897" RevisionGUID="3f475c77-9e60-47b7-9092-93fdf4bfcd70" CreationDate="2024-03-08T13:02:35.277" UserId="-1" />
  <row Id="42961" PostHistoryTypeId="50" PostId="13752" RevisionGUID="476b5c33-45bd-4224-b3b8-49b115a8e714" CreationDate="2024-03-09T10:03:25.337" UserId="-1" />
  <row Id="42963" PostHistoryTypeId="2" PostId="13966" RevisionGUID="988ff289-0693-4f19-ba23-4f1d9339b216" CreationDate="2024-03-11T12:10:35.410" UserId="21289" Text="I'm trying to figure out how the Adobe Illustrator's Inflate effect works. Basically, it converts a vector graphic object to a 3D mesh and displaces its vertices proportionally to how far they are from the object's borders. The resulting mesh's height is also controlled by the `Volume` parameter, which ranges from 0 to 100%. If I inflate a rectangle with `Volume` set to 0%, I get the following (flat) mesh:&#xD;&#xA;[![grid][1]][1]&#xD;&#xA;I wonder how can I get such a triangulation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cMmII.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42965" PostHistoryTypeId="1" PostId="13966" RevisionGUID="988ff289-0693-4f19-ba23-4f1d9339b216" CreationDate="2024-03-11T12:10:35.410" UserId="21289" Text="Curvilinear triangle grid" ContentLicense="CC BY-SA 4.0" />
  <row Id="42966" PostHistoryTypeId="3" PostId="13966" RevisionGUID="988ff289-0693-4f19-ba23-4f1d9339b216" CreationDate="2024-03-11T12:10:35.410" UserId="21289" Text="|3d|vector-graphics|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42967" PostHistoryTypeId="5" PostId="13966" RevisionGUID="a50ae5a3-8447-4288-ba56-051b1a6ebbbd" CreationDate="2024-03-11T12:27:15.200" UserId="21289" Comment="added 1 character in body" Text="I'm trying to figure out how the Adobe Illustrator's Inflate effect works. Basically, it converts a vector graphics object to a 3D mesh and displaces its vertices proportionally to how far they are from the object's borders. The resulting mesh's height is also controlled by the `Volume` parameter, which ranges from 0 to 100%. If I inflate a rectangle with `Volume` set to 0%, I get the following (flat) mesh:&#xD;&#xA;[![grid][1]][1]&#xD;&#xA;I wonder how can I get such a triangulation?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cMmII.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42969" PostHistoryTypeId="2" PostId="13967" RevisionGUID="6adb04e7-b8dd-4ef2-8029-1e2f6f39830d" CreationDate="2024-03-11T16:04:54.660" UserId="7724" Text="I believe the method used in Illustrator is described in the following paper:&#xD;&#xA;&#xD;&#xA;[Repoussé: Automatic Inflation of 2D Artwork][1]&#xD;&#xA;&#xD;&#xA;The mesh shown in your example seems to be a fairly triangular grid, displaced by the method.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://pushkarjoshi.org/pdf/JC_SBIM2008.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42971" PostHistoryTypeId="50" PostId="5003" RevisionGUID="d8542d65-41ab-490d-8896-f003b7a2a502" CreationDate="2024-03-12T00:07:55.923" UserId="-1" />
  <row Id="42972" PostHistoryTypeId="5" PostId="13898" RevisionGUID="bd4a1f17-4a18-4f99-a9e4-0127b4304021" CreationDate="2024-03-12T14:05:41.710" UserId="7952" Comment="simplified the answer to only have a single approach" Text="A simple way to determine mesh orientation is to compute the winding order of each triangle. Where winding order is either clockwise (CW) or counter clockwise (CCW).&#xD;&#xA;&#xD;&#xA;Swapping the winding order of a triangle swaps the direction of the normal for that triangle. So checking that normal vectors are facing &quot;outward&quot; is a matter of verifying that all triangles are wound in the same direction.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Keep in mind that the coordinate system also plays a role in handedness. Determining that the mesh is wound consistently is a better indicator of a valid mesh since sometimes a mesh is intentionally wound in the opposite direction so that we only see the &quot;inside&quot; of the faces.&#xD;&#xA;&#xD;&#xA;I well specified system will have all these details in it so that the facing can be determined to be consistent with that system. This way we aren't throwing a random mesh at a random system to do coin flips on the problem.&#xD;&#xA;&#xD;&#xA; There are many ways to go about checking this.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;-----&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;One way to check winding without doing any computations is to check that the edge of any connected triangles have the vertices ordered in the opposite direction. If any of the edges have the same order the connected triangle has opposite winding and can be fixed by swapping the order of the vertices. This method is very reliable and very easy to implement. For example if we have triangle ABC where AB, BC, and CA are the edges then the connected triangles should have edges BA, BC, and CA.&#xD;&#xA;&#xD;&#xA;Implementation:&#xD;&#xA;&#xD;&#xA;The property &quot;connected triangles with the same winding have edges with the opposite order&quot; makes this particularly easy to implement since this means that if edge AB is repeated anywhere then there is a problem. IE AB is unique in the mesh. Implementation is just a matter of picking your favorite data structure and using insert unique. That's it we're done. Non-unique means there is a problem, reverse the winding of that triangle and continue. Done.&#xD;&#xA;&#xD;&#xA;---&#xD;&#xA;&#xD;&#xA;*More Rigorous solutions*&#xD;&#xA;&#xD;&#xA;Some interesting information on the subject can be found by searching for the shoelace formula and greene's algorithm. Also search for shoelace in 3D. Search for curve orientation ([here is a wikipidia page on it][1]) can be useful too.&#xD;&#xA;&#xD;&#xA;A much more rigorous solution can be created by generating edge  information... pick a single triangle determine its orientation, then use its edges to find and check the orientation of neighboring triangles. Save orientation with the edges and compare new triangles against that orientation. Repeat until all triangles are traversed.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://en.wikipedia.org/wiki/Curve_orientation" ContentLicense="CC BY-SA 4.0" />
  <row Id="42973" PostHistoryTypeId="5" PostId="13967" RevisionGUID="5a632e81-324b-46a2-808e-170fe747c9cc" CreationDate="2024-03-13T09:00:34.947" UserId="7724" Comment="added 8 characters in body" Text="I believe the method used in Illustrator is described in the following paper:&#xD;&#xA;&#xD;&#xA;[Repoussé: Automatic Inflation of 2D Artwork][1]&#xD;&#xA;&#xD;&#xA;The mesh shown in your example seems to be a fairly regular triangular grid, displaced by the method.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: http://pushkarjoshi.org/pdf/JC_SBIM2008.pdf" ContentLicense="CC BY-SA 4.0" />
  <row Id="42974" PostHistoryTypeId="50" PostId="13913" RevisionGUID="70e1ecd7-1020-453b-8546-a5010983f149" CreationDate="2024-03-13T19:00:35.147" UserId="-1" />
  <row Id="42975" PostHistoryTypeId="2" PostId="13968" RevisionGUID="fa5fccb5-fe33-4f33-a826-810302cd86b1" CreationDate="2024-03-13T20:40:00.423" UserId="18408" Text="I'm trying to draw the outline of a rectangle (8 x vertices, 24 x indices, counterclockwise winding) using a unit rectangle and normals, with the model matrix scaling the outline thickness in the vertex shader. However, I'm only getting the bottom right hand half of the outline:&#xD;&#xA;&#xD;&#xA;[![Bottom right outline][1]][1]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    let ty = r_pc.info.x;&#xD;&#xA;    let thickness = r_pc.info.y;&#xD;&#xA;    let is_fill = select(false, true, ty &gt;= 0.5 &amp;&amp; ty &lt; 1.5);&#xD;&#xA;    let is_outline = select(false, true, ty &gt;= 1.5 &amp;&amp; ty &lt; 2.5);&#xD;&#xA;&#xD;&#xA;    var model = r_pc.model;&#xD;&#xA;    var position = vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;    if is_outline {&#xD;&#xA;        // Add thickness to model's scale components.&#xD;&#xA;        var width = vertex.normal * thickness;&#xD;&#xA;        model[0][0] += width.x;&#xD;&#xA;        model[1][1] += width.y;&#xD;&#xA;    }&#xD;&#xA;    position = r_camera.view_proj * model * position;&#xD;&#xA;&#xD;&#xA;    let color = r_pc.color;&#xD;&#xA;&#xD;&#xA;    let uv = vertex.uv;&#xD;&#xA;&#xD;&#xA;    return VsOut(position, color, uv);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I instead add the normal to the outside corner vertices and scale by the thickness (10px), it's also wildly wrong!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    let ty = r_pc.info.x;&#xD;&#xA;    let thickness = r_pc.info.y;&#xD;&#xA;    let is_fill = select(false, true, ty &gt;= 0.5 &amp;&amp; ty &lt; 1.5);&#xD;&#xA;    let is_outline = select(false, true, ty &gt;= 1.5 &amp;&amp; ty &lt; 2.5);&#xD;&#xA;&#xD;&#xA;    var model = r_pc.model;&#xD;&#xA;    var position = vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;    if is_outline &amp;&amp; vertex.id % 2 == 1 {&#xD;&#xA;        // Add thickness to model's scale components.&#xD;&#xA;        position += vec4(vertex.normal, 0.0, 0.0);&#xD;&#xA;        var width = vertex.normal * thickness;&#xD;&#xA;        model[0][0] += thickness;&#xD;&#xA;        model[1][1] += thickness;&#xD;&#xA;    }&#xD;&#xA;    position = r_camera.view_proj * model * position;&#xD;&#xA;&#xD;&#xA;    let color = r_pc.color;&#xD;&#xA;&#xD;&#xA;    let uv = vertex.uv;&#xD;&#xA;&#xD;&#xA;    return VsOut(position, color, uv);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here are my geometry info:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;[&#xD;&#xA;Vertex { position: [0.0,0.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [0.0,0.0], normal: [-0.70710677,-0.70710677] },&#xD;&#xA;Vertex { position: [0.0,1.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [0.0,1.0], normal: [-0.70710677,0.70710677] },&#xD;&#xA;Vertex { position: [1.0,1.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [1.0,1.0], normal: [0.70710677,0.70710677] },&#xD;&#xA;Vertex { position: [1.0,0.0], normal: [0.0,0.0], },&#xD;&#xA;Vertex { position: [1.0,0.0], normal: [0.70710677,-0.70710677] },&#xD;&#xA;]&#xD;&#xA;&#xD;&#xA;indices =&gt; [&#xD;&#xA;    0,1,2,&#xD;&#xA;    2,1,3,&#xD;&#xA;    2,3,4,&#xD;&#xA;    4,3,5,&#xD;&#xA;    4,5,6,&#xD;&#xA;    6,5,7,&#xD;&#xA;    6,7,0,&#xD;&#xA;    0,7,1&#xD;&#xA;]&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The idea was to add the normals to the vertices and scale by the thickness. But as can be seen, the 2 approaches I had for doing this do not work.&#xD;&#xA;&#xD;&#xA;How can I compute the outline of a rectangle in the vertex shader using a unit square combined with normals and an outline thickness?&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cG5Wq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gQFSw.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42977" PostHistoryTypeId="1" PostId="13968" RevisionGUID="fa5fccb5-fe33-4f33-a826-810302cd86b1" CreationDate="2024-03-13T20:40:00.423" UserId="18408" Text="How can I compute a rectangles outline using a unit square in the vertex shader?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42978" PostHistoryTypeId="3" PostId="13968" RevisionGUID="fa5fccb5-fe33-4f33-a826-810302cd86b1" CreationDate="2024-03-13T20:40:00.423" UserId="18408" Text="|shader|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42979" PostHistoryTypeId="2" PostId="13969" RevisionGUID="8d91ded3-0180-4bd9-ab51-bb7eb14a4044" CreationDate="2024-03-14T06:05:05.077" UserId="19537" Text="If in the path tracing use case, I have some sampling strategies to sample a scattering direction in a 2D space ($\theta, \phi$). Of course, I need to convert it to a 3D direction vector (with length being 1). My question is, is the PDF of this 3D direction vector the same as that of $(\theta, \phi)$? If I recall correctly, there should be a Jacobian term for the conversion from spherical coords to 3D Cartesian space, so the PDF is probably different?&#xD;&#xA;&#xD;&#xA;If the sampling PDF for $\theta$ is $p_1(\theta), \theta \in [0, \pi)$ (volumetric scattering requires sampling on the entire sphere), and PDF for sampling $\phi$ is $p_2(\phi), \phi \in [0, 2\pi)$. &#xD;&#xA;- What will be the PDF of the 3D direction vector $p_d(\omega)$? &#xD;&#xA;- What about the case that $\theta, \phi$ is sampled from a 2D joint distribution $p(\theta, \phi)$ (like, sampling from precomputed tabulations), is there any difference from the first case?&#xD;&#xA;- And if I am gonna evaluate the MC integral here, is the following correct? &#xD;&#xA;$$&#xD;&#xA;\text{scattering throughput}=f(\omega, \omega') \times C / p_d(\omega), C=\begin{cases}&#xD;&#xA;\sigma_s, \text{volumetric}\\&#xD;&#xA;\omega^T \omega',\text{surface}&#xD;&#xA;\end{cases}&#xD;&#xA;$$" ContentLicense="CC BY-SA 4.0" />
  <row Id="42981" PostHistoryTypeId="1" PostId="13969" RevisionGUID="8d91ded3-0180-4bd9-ab51-bb7eb14a4044" CreationDate="2024-03-14T06:05:05.077" UserId="19537" Text="Measure (or Jacobian) conversion for direction sampling" ContentLicense="CC BY-SA 4.0" />
  <row Id="42982" PostHistoryTypeId="3" PostId="13969" RevisionGUID="8d91ded3-0180-4bd9-ab51-bb7eb14a4044" CreationDate="2024-03-14T06:05:05.077" UserId="19537" Text="|pathtracing|mathematics|sampling|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42983" PostHistoryTypeId="2" PostId="13970" RevisionGUID="aa4903b7-d2bc-46b3-9630-0ae147c6e0eb" CreationDate="2024-03-14T12:56:23.040" UserId="10096" Text="If your map $\omega:[0,2\pi) \times [0,\pi] \to \mathbb{S}^2\subset \mathbb{R}^3$ is the standard spherical coordinates map:&#xD;&#xA;&#xD;&#xA;$$\omega = (\cos\phi \sin\theta, \sin\phi \sin\theta, \cos\theta),$$&#xD;&#xA;&#xD;&#xA;then the Jacobian is:&#xD;&#xA;&#xD;&#xA;$$J = \frac{\partial \omega}{\partial (\phi, \theta)} = \begin{bmatrix} \uparrow &amp; \uparrow \\\frac{\partial\omega}{\partial \phi} &amp; \frac{\partial\omega} {\partial\theta} \\ \downarrow &amp; \downarrow \end{bmatrix} = \begin{bmatrix} -\sin\phi \sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi\sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; \sin\theta\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;The area measure on the sphere is $d\sigma(\omega) = \sqrt{\det J^T J} \,d\lambda(\phi)d\lambda(\theta) = |\sin\theta|\,d\lambda(\phi)d\lambda(\theta)$. Here $\lambda$ is just the Lebesgue measure and it is often omitted. Now assume the probability density function for picking $(\phi,\theta)$ is $p_{\phi,\theta}$. Taking into account $d\sigma(\omega) = |\sin\theta|\,d\lambda(\phi)d\lambda(\theta)$ we have:&#xD;&#xA;$$p_{\phi,\theta}(\phi,\theta) \,d\lambda(\phi) d\lambda(\theta) = p_{\sigma}(\omega)\,d\sigma(\omega) \implies p_{\sigma}(\omega) = \frac{p_{\phi,\theta}(\phi,\theta)}{|\sin\theta|}.$$&#xD;&#xA;&#xD;&#xA;If $p_{\phi,\theta}$ is separable you can write it as $p_{\phi,\theta}(\phi,\theta) = p_{\phi}(\phi)p_{\theta}(\theta)$.&#xD;&#xA;&#xD;&#xA;The change of variables in an integral over the unit sphere happens as follows:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;I&#xD;&#xA;&amp;=\int_{\mathbb{S}^2} f(\omega_o, \omega_i) (\omega_i \cdot n)\,d\sigma(\omega_i) \\&#xD;&#xA;&amp;= \int_{0}^{2\pi}\int_0^{\pi} f(\omega_o, \omega_i(\phi,\theta)) (\omega_i(\phi,\theta) \cdot n)|\sin\theta|\,d\lambda(\theta) d\lambda(\phi) \\&#xD;&#xA;&amp;= \int_0^1\int_0^1 f(\omega_o, \omega_i(u,v)) (\omega_i(u,v) \cdot n)\underbrace{|\sin\theta|\left|\det \frac{\partial(\phi,\theta)}{\partial (u,v)}\right|}_{1/p_{\sigma}(\omega_i)}\,d\lambda(u) d\lambda(v) \\&#xD;&#xA;&amp;= \int_0^1\int_0^1 \frac{f(\omega_o, \omega_i(u,v)) (\omega_i(u,v) \cdot n)}{p_{\sigma}(\omega_i(u,v))}\,d\lambda(u) d\lambda(v) \\&#xD;&#xA;&amp;\approx \frac{1}{N} \sum_{j=1}^N\frac{f(\omega_o, \omega_i(u_j,v_j)) (\omega_i(u_j,v_j) \cdot n)}{p_{\sigma}(\omega_i(u_j,v_j))}, \quad (u_j,v_j) \sim U[0,1]^2.&#xD;&#xA;\end{align}" ContentLicense="CC BY-SA 4.0" />
  <row Id="42985" PostHistoryTypeId="50" PostId="13696" RevisionGUID="721af8ef-01c7-4039-aa18-f2162a380fc3" CreationDate="2024-03-14T18:04:55.600" UserId="-1" />
  <row Id="42986" PostHistoryTypeId="5" PostId="13968" RevisionGUID="3810ce1f-43af-48c9-bb80-1fa1d377bcca" CreationDate="2024-03-15T13:27:36.907" UserId="18408" Comment="Add image of what it should look like" Text="I'm trying to draw the outline of a rectangle (8 x vertices, 24 x indices, counterclockwise winding) using a unit rectangle and normals, with the model matrix scaling the outline thickness in the vertex shader. However, I'm only getting the bottom right hand half of the outline:&#xD;&#xA;&#xD;&#xA;[![Bottom right outline][1]][1]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    let ty = r_pc.info.x;&#xD;&#xA;    let thickness = r_pc.info.y;&#xD;&#xA;    let is_fill = select(false, true, ty &gt;= 0.5 &amp;&amp; ty &lt; 1.5);&#xD;&#xA;    let is_outline = select(false, true, ty &gt;= 1.5 &amp;&amp; ty &lt; 2.5);&#xD;&#xA;&#xD;&#xA;    var model = r_pc.model;&#xD;&#xA;    var position = vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;    if is_outline {&#xD;&#xA;        // Add thickness to model's scale components.&#xD;&#xA;        var width = vertex.normal * thickness;&#xD;&#xA;        model[0][0] += width.x;&#xD;&#xA;        model[1][1] += width.y;&#xD;&#xA;    }&#xD;&#xA;    position = r_camera.view_proj * model * position;&#xD;&#xA;&#xD;&#xA;    let color = r_pc.color;&#xD;&#xA;&#xD;&#xA;    let uv = vertex.uv;&#xD;&#xA;&#xD;&#xA;    return VsOut(position, color, uv);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I instead add the normal to the outside corner vertices and scale by the thickness (10px), it's also wildly wrong!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    let ty = r_pc.info.x;&#xD;&#xA;    let thickness = r_pc.info.y;&#xD;&#xA;    let is_fill = select(false, true, ty &gt;= 0.5 &amp;&amp; ty &lt; 1.5);&#xD;&#xA;    let is_outline = select(false, true, ty &gt;= 1.5 &amp;&amp; ty &lt; 2.5);&#xD;&#xA;&#xD;&#xA;    var model = r_pc.model;&#xD;&#xA;    var position = vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;    if is_outline &amp;&amp; vertex.id % 2 == 1 {&#xD;&#xA;        // Add thickness to model's scale components.&#xD;&#xA;        position += vec4(vertex.normal, 0.0, 0.0);&#xD;&#xA;        var width = vertex.normal * thickness;&#xD;&#xA;        model[0][0] += thickness;&#xD;&#xA;        model[1][1] += thickness;&#xD;&#xA;    }&#xD;&#xA;    position = r_camera.view_proj * model * position;&#xD;&#xA;&#xD;&#xA;    let color = r_pc.color;&#xD;&#xA;&#xD;&#xA;    let uv = vertex.uv;&#xD;&#xA;&#xD;&#xA;    return VsOut(position, color, uv);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here are my geometry info:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;[&#xD;&#xA;Vertex { position: [0.0,0.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [0.0,0.0], normal: [-0.70710677,-0.70710677] },&#xD;&#xA;Vertex { position: [0.0,1.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [0.0,1.0], normal: [-0.70710677,0.70710677] },&#xD;&#xA;Vertex { position: [1.0,1.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [1.0,1.0], normal: [0.70710677,0.70710677] },&#xD;&#xA;Vertex { position: [1.0,0.0], normal: [0.0,0.0], },&#xD;&#xA;Vertex { position: [1.0,0.0], normal: [0.70710677,-0.70710677] },&#xD;&#xA;]&#xD;&#xA;&#xD;&#xA;indices =&gt; [&#xD;&#xA;    0,1,2,&#xD;&#xA;    2,1,3,&#xD;&#xA;    2,3,4,&#xD;&#xA;    4,3,5,&#xD;&#xA;    4,5,6,&#xD;&#xA;    6,5,7,&#xD;&#xA;    6,7,0,&#xD;&#xA;    0,7,1&#xD;&#xA;]&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The idea was to add the normals to the vertices and scale by the thickness. But as can be seen, the 2 approaches I had for doing this do not work.&#xD;&#xA;&#xD;&#xA;The rectangle on its own should look like this:&#xD;&#xA;&#xD;&#xA;[![What it should look like][3]][3]&#xD;&#xA;&#xD;&#xA;How can I compute the outline of a rectangle in the vertex shader using a unit square combined with normals and an outline thickness?&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cG5Wq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gQFSw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xj58N.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42987" PostHistoryTypeId="5" PostId="13968" RevisionGUID="4fc3736b-56f5-4f6f-99b5-30cf62c216fd" CreationDate="2024-03-15T13:32:52.110" UserId="18408" Comment="Add image of what it should look like" Text="I'm trying to draw the outline of a rectangle (8 x vertices, 24 x indices, counterclockwise winding) using a unit rectangle and normals, with the model matrix scaling the outline thickness in the vertex shader. However, I'm only getting the bottom right hand half of the outline:&#xD;&#xA;&#xD;&#xA;[![Bottom right outline][1]][1]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    let ty = r_pc.info.x;&#xD;&#xA;    let thickness = r_pc.info.y;&#xD;&#xA;    let is_fill = select(false, true, ty &gt;= 0.5 &amp;&amp; ty &lt; 1.5);&#xD;&#xA;    let is_outline = select(false, true, ty &gt;= 1.5 &amp;&amp; ty &lt; 2.5);&#xD;&#xA;&#xD;&#xA;    var model = r_pc.model;&#xD;&#xA;    var position = vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;    if is_outline {&#xD;&#xA;        // Add thickness to model's scale components.&#xD;&#xA;        var width = vertex.normal * thickness;&#xD;&#xA;        model[0][0] += width.x;&#xD;&#xA;        model[1][1] += width.y;&#xD;&#xA;    }&#xD;&#xA;    position = r_camera.view_proj * model * position;&#xD;&#xA;&#xD;&#xA;    let color = r_pc.color;&#xD;&#xA;&#xD;&#xA;    let uv = vertex.uv;&#xD;&#xA;&#xD;&#xA;    return VsOut(position, color, uv);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;If I instead add the normal to the outside corner vertices and scale by the thickness (10px), it's also wildly wrong!&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;@vertex&#xD;&#xA;fn vs_main(vertex: Vertex) -&gt; VsOut {&#xD;&#xA;    let ty = r_pc.info.x;&#xD;&#xA;    let thickness = r_pc.info.y;&#xD;&#xA;    let is_fill = select(false, true, ty &gt;= 0.5 &amp;&amp; ty &lt; 1.5);&#xD;&#xA;    let is_outline = select(false, true, ty &gt;= 1.5 &amp;&amp; ty &lt; 2.5);&#xD;&#xA;&#xD;&#xA;    var model = r_pc.model;&#xD;&#xA;    var position = vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;    if is_outline &amp;&amp; vertex.id % 2 == 1 {&#xD;&#xA;        // Add thickness to model's scale components.&#xD;&#xA;        position += vec4(vertex.normal, 0.0, 0.0);&#xD;&#xA;        var width = vertex.normal * thickness;&#xD;&#xA;        model[0][0] += thickness;&#xD;&#xA;        model[1][1] += thickness;&#xD;&#xA;    }&#xD;&#xA;    position = r_camera.view_proj * model * position;&#xD;&#xA;&#xD;&#xA;    let color = r_pc.color;&#xD;&#xA;&#xD;&#xA;    let uv = vertex.uv;&#xD;&#xA;&#xD;&#xA;    return VsOut(position, color, uv);&#xD;&#xA;}&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;Here are my geometry info:&#xD;&#xA;&#xD;&#xA;```&#xD;&#xA;[&#xD;&#xA;Vertex { position: [0.0,0.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [0.0,0.0], normal: [-0.70710677,-0.70710677] },&#xD;&#xA;Vertex { position: [0.0,1.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [0.0,1.0], normal: [-0.70710677,0.70710677] },&#xD;&#xA;Vertex { position: [1.0,1.0], normal: [0.0,0.0] },&#xD;&#xA;Vertex { position: [1.0,1.0], normal: [0.70710677,0.70710677] },&#xD;&#xA;Vertex { position: [1.0,0.0], normal: [0.0,0.0], },&#xD;&#xA;Vertex { position: [1.0,0.0], normal: [0.70710677,-0.70710677] },&#xD;&#xA;]&#xD;&#xA;&#xD;&#xA;indices =&gt; [&#xD;&#xA;    0,1,2,&#xD;&#xA;    2,1,3,&#xD;&#xA;    2,3,4,&#xD;&#xA;    4,3,5,&#xD;&#xA;    4,5,6,&#xD;&#xA;    6,5,7,&#xD;&#xA;    6,7,0,&#xD;&#xA;    0,7,1&#xD;&#xA;]&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;The idea was to add the normals to the vertices and scale by the thickness. But as can be seen, the 2 approaches I had for doing this do not work.&#xD;&#xA;&#xD;&#xA;The rectangle on its own should look like this:&#xD;&#xA;&#xD;&#xA;[![What it should look like][3]][3]&#xD;&#xA;&#xD;&#xA;How can I compute the outline of a rectangle in the vertex shader using a unit square combined with normals and an outline thickness?&#xD;&#xA;&#xD;&#xA;**Edit:**&#xD;&#xA;&#xD;&#xA;I'm a bit closer, having changed the shader code as follows, so that the axis normals are rotated into the correct coordinate space. These normals are then used to compute the offset and added to the inner position.&#xD;&#xA;```&#xD;&#xA;let world_position = model * vec4(vertex.position, 0.0, 1.0);&#xD;&#xA;let x = normalize(model * vec4(1.0, 0.0, 0.0, 0.0));&#xD;&#xA;let y = normalize(model * vec4(0.0, 1.0, 0.0, 0.0));&#xD;&#xA;let offset = (x * vertex.normal.x + y * vertex.normal.y) * thickness;&#xD;&#xA;let position = r_camera.view_proj * (world_position + offset);&#xD;&#xA;```&#xD;&#xA;&#xD;&#xA;However, that is not quite correct because the top left segment is 1px less than the bottom right:&#xD;&#xA;&#xD;&#xA;[![Almost there, missing 1px][4]][4]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/cG5Wq.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/gQFSw.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/xj58N.png&#xD;&#xA;  [4]: https://i.stack.imgur.com/ZAfxm.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42988" PostHistoryTypeId="5" PostId="13970" RevisionGUID="55c31262-51c0-40fb-ade3-71a4314d9848" CreationDate="2024-03-16T10:33:48.200" UserId="10096" Comment="added 545 characters in body" Text="If your map $\omega:[0,2\pi) \times [0,\pi] \to \mathbb{S}^2\subset \mathbb{R}^3$ is the standard spherical coordinates map:&#xD;&#xA;&#xD;&#xA;$$\omega = (\cos\phi \sin\theta, \sin\phi \sin\theta, \cos\theta),$$&#xD;&#xA;&#xD;&#xA;then the Jacobian is:&#xD;&#xA;&#xD;&#xA;$$J = \frac{\partial \omega}{\partial (\phi, \theta)} = \begin{bmatrix} \uparrow &amp; \uparrow \\\frac{\partial\omega}{\partial \phi} &amp; \frac{\partial\omega} {\partial\theta} \\ \downarrow &amp; \downarrow \end{bmatrix} = \begin{bmatrix} -\sin\phi \sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi\sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; \sin\theta\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;The area measure on the sphere is $d\sigma(\omega) = \sqrt{\det J^T J} \,d\lambda(\phi)d\lambda(\theta) = |\sin\theta|\,d\lambda(\phi)d\lambda(\theta)$. Here $\lambda$ is just the Lebesgue measure and it is often omitted. Now assume the probability density function for picking $(\phi,\theta)$ is $p_{\phi,\theta}$. Taking into account $d\sigma(\omega) = |\sin\theta|\,d\lambda(\phi)d\lambda(\theta)$ we have:&#xD;&#xA;$$p_{\phi,\theta}(\phi,\theta) \,d\lambda(\phi) d\lambda(\theta) = p_{\sigma}(\omega)\,d\sigma(\omega) \implies p_{\sigma}(\omega) = \frac{p_{\phi,\theta}(\phi,\theta)}{|\sin\theta|}.$$&#xD;&#xA;&#xD;&#xA;Note that translations and rotations do not change the term $\sqrt{J^T J}$ since the derivative of a translation is zero, and a rotation is orthogonal $R^TR=I$ and thus $\sqrt{J^TR^TRJ} = \sqrt{J^TJ} = |\sin\theta|$. I am mentioning this since typically you integrate over the sphere not w.r.t. the standard coordinate axes, but some frame oriented around the normal, which can be implemented as $\omega' = R\omega$.&#xD;&#xA;&#xD;&#xA;If $p_{\phi,\theta}$ is separable you can write it as $p_{\phi,\theta}(\phi,\theta) = p_{\phi}(\phi)p_{\theta}(\theta)$.&#xD;&#xA;&#xD;&#xA;The change of variables in an integral over the unit sphere happens as follows:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;I&#xD;&#xA;&amp;=\int_{\mathbb{S}^2} L_i(x, \omega_i) f(\omega_o, x, \omega_i) (\omega_i \cdot n)\,d\sigma(\omega_i) \\&#xD;&#xA;&amp;= \int_{0}^{2\pi}\int_0^{\pi} L_i(x,\omega_i(\phi,\theta))f(\omega_o,x, \omega_i(\phi,\theta)) (\omega_i(\phi,\theta) \cdot n)|\sin\theta|\,d\lambda(\theta) d\lambda(\phi) \\&#xD;&#xA;&amp;= \int_0^1\int_0^1  L_i(x,\omega_i(u,v))f(\omega_o,x, \omega_i(u,v)) (\omega_i(u,v) \cdot n)\underbrace{|\sin\theta|\left|\det \frac{\partial(\phi,\theta)}{\partial (u,v)}\right|}_{1/p_{\sigma}(\omega_i)}\,d\lambda(u) d\lambda(v) \\&#xD;&#xA;&amp;= \int_0^1\int_0^1 \frac{L_i(x,\omega_i(u_j,v_j))f(\omega_o,x, \omega_i(u,v)) (\omega_i(u,v) \cdot n)}{p_{\sigma}(\omega_i(u,v))}\,d\lambda(u) d\lambda(v) \\&#xD;&#xA;&amp;\approx \frac{1}{N} \sum_{j=1}^N\frac{L_i(x.\omega_i(u_j,v_j))f(\omega_o,x, \omega_i(u_j,v_j)) (\omega_i(u_j,v_j) \cdot n)}{p_{\sigma}(\omega_i(u_j,v_j))}, \quad (u_j,v_j) \sim U[0,1]^2.&#xD;&#xA;\end{align}" ContentLicense="CC BY-SA 4.0" />
  <row Id="42989" PostHistoryTypeId="2" PostId="13971" RevisionGUID="14d6a997-330e-4a61-aded-b3fc872efa8f" CreationDate="2024-03-16T18:21:46.943" UserId="21306" Text="I am trying to get the following image to a certain grayscale value [![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/50gkN.jpg&#xD;&#xA;&#xD;&#xA;I want the spiral to have a grayscale of 120 and everything else to have a grayscale value of 255.&#xD;&#xA;What can I do?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42991" PostHistoryTypeId="1" PostId="13971" RevisionGUID="14d6a997-330e-4a61-aded-b3fc872efa8f" CreationDate="2024-03-16T18:21:46.943" UserId="21306" Text="How Can I convert Grayscale values of an image?" ContentLicense="CC BY-SA 4.0" />
  <row Id="42992" PostHistoryTypeId="3" PostId="13971" RevisionGUID="14d6a997-330e-4a61-aded-b3fc872efa8f" CreationDate="2024-03-16T18:21:46.943" UserId="21306" Text="|image-processing|image|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42993" PostHistoryTypeId="2" PostId="13972" RevisionGUID="6299821f-0bff-49b6-b303-5e30ceeb49ad" CreationDate="2024-03-17T03:13:39.077" UserId="19537" Text="For this specific task and if you don't care about how the method can be extended to other cases, the following python code does the job:&#xD;&#xA;```python&#xD;&#xA;import numpy as np&#xD;&#xA;import matplotlib.pyplot as plt&#xD;&#xA;import sys&#xD;&#xA;&#xD;&#xA;if __name__ == &quot;__main__&quot;:&#xD;&#xA;    img = plt.imread(sys.argv[1])&#xD;&#xA;&#xD;&#xA;    img = img.astype(int)       # type conversion from uint8 to int&#xD;&#xA;    # given that the spiral structure mostly consists of pixel with 0 value&#xD;&#xA;    img += 120&#xD;&#xA;    img = np.clip(img, 0, 255).astype(np.uint8)      # clip to valid image range and convert the int type img back to uint8&#xD;&#xA;    plt.imsave(&quot;grayscale-120.jpg&quot;, img)&#xD;&#xA;```&#xD;&#xA;Note that, the original image does not just contain pixel value of 255 and 0, there are intermediate values. The code above does not get rid of the intermediate values (though, it is negligible). But if you really want to get rid of them, you can use:&#xD;&#xA;```python&#xD;&#xA;img[img &gt; 120] = 255&#xD;&#xA;```&#xD;&#xA;as a thresholded pixel value substitution before saving the image. This will yield images will exactly two pixel values (120 and 255). But... your image is  of jpeg format, so you will notice some compression artifacts and the noise that hardly noticable before is enhanced by hard thresholding. Yet, you can use opening operation to get rid of the artifacts, right before you save the image:&#xD;&#xA;```python&#xD;&#xA;import cv2&#xD;&#xA;kernel = np.ones((3, 3),np.uint8)&#xD;&#xA;img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)&#xD;&#xA;```&#xD;&#xA;well... this is not perfect, but I am sure more tweaking can be done here.&#xD;&#xA;&#xD;&#xA;|no hard thresholding|hard thresholding|with opening op|&#xD;&#xA;|:--:|:--:|:--:|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|[![enter image description here][3]][3]|&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/yRba5.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/5lbBu.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/vXthF.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="42995" PostHistoryTypeId="2" PostId="13973" RevisionGUID="00d1cb10-a7ce-43e3-b3de-fa3bddfd1e4b" CreationDate="2024-03-17T19:15:19.187" UserId="21309" Text="What exactly will be the final matrix? &#xD;&#xA;&quot;Consider a window ABCD whose lower left corner is A (XWL,YWL) and the upper &#xD;&#xA;right corner C is (XWm, YWM). A viewport PQRS has been defined with the lower &#xD;&#xA;1eft corner is P (XVL , YVL ) , and the upper right corner is R(XVm,YVm) . The window ABCD has to be mapped into the viewport PQRS.&quot;&#xD;&#xA;&#xD;&#xA;What will be the window to viewport transformation matrix if the viewport PQRS &#xD;&#xA;is normalize in the range of [-1,11]." ContentLicense="CC BY-SA 4.0" />
  <row Id="42997" PostHistoryTypeId="1" PostId="13973" RevisionGUID="00d1cb10-a7ce-43e3-b3de-fa3bddfd1e4b" CreationDate="2024-03-17T19:15:19.187" UserId="21309" Text="Write down the window to viewport transformation matrix if the viewport PQRS is normalize in the range of [-1,1]" ContentLicense="CC BY-SA 4.0" />
  <row Id="42998" PostHistoryTypeId="3" PostId="13973" RevisionGUID="00d1cb10-a7ce-43e3-b3de-fa3bddfd1e4b" CreationDate="2024-03-17T19:15:19.187" UserId="21309" Text="|matrix|" ContentLicense="CC BY-SA 4.0" />
  <row Id="42999" PostHistoryTypeId="50" PostId="13766" RevisionGUID="219c5cfe-53c6-422f-9759-d388070e1c84" CreationDate="2024-03-18T11:05:35.630" UserId="-1" />
  <row Id="43000" PostHistoryTypeId="2" PostId="13974" RevisionGUID="0b6eba24-cec2-4747-a05a-28daeaf8542c" CreationDate="2024-03-18T16:09:04.713" UserId="21314" Text="Good people of the graphics SO community, I am new to Graphics programming or GPU programming in general but I have been a game dev enthusiast for over 4-5 years. I started learning about Graphics finally. &#xD;&#xA;&#xD;&#xA;I decided to start working on a very very basic 3D first-person game that can run on my Steam Deck, a Linux computer (most commonly used basic distros), a Windows computer (especially 8, 10, and 11), and MacOS (not super bullish on this).&#xD;&#xA;&#xD;&#xA;So I learned about a bunch of APIs like OpenGL, Vulkan, and DirectX (I know some of them are technically not APIs but specifications, or not, please correct me on this) and I came across some forums that convey the support of these APIs in different OS types, but the answers are biased towards the specificity of one or two particular OSes mentioned in the questions.&#xD;&#xA;&#xD;&#xA;I'd really appreciate it if someone gave advice on which API/Specification(s) to learn to work on a basic game like this one - https://jblaha.art/sketchbook/latest and that has support on all the devices/OSes mentioned above.&#xD;&#xA;&#xD;&#xA;Thank you so much in advance.&#xD;&#xA;&#xD;&#xA;(p.s. I already started learning OpenGL from https://learnopengl.com/ and I'd be glad to use this for my game. But I would learn a different one if I'm advised to do so.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="43002" PostHistoryTypeId="1" PostId="13974" RevisionGUID="0b6eba24-cec2-4747-a05a-28daeaf8542c" CreationDate="2024-03-18T16:09:04.713" UserId="21314" Text="Preferred GPU API to use for Steam Deck, Windows, Linux and MacOS support" ContentLicense="CC BY-SA 4.0" />
  <row Id="43003" PostHistoryTypeId="3" PostId="13974" RevisionGUID="0b6eba24-cec2-4747-a05a-28daeaf8542c" CreationDate="2024-03-18T16:09:04.713" UserId="21314" Text="|opengl|3d|glsl|vulkan|directx|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43004" PostHistoryTypeId="50" PostId="13302" RevisionGUID="fa053980-f02f-4147-bf6d-1b9739e0f61d" CreationDate="2024-03-18T20:06:05.840" UserId="-1" />
  <row Id="43005" PostHistoryTypeId="2" PostId="13975" RevisionGUID="ef3e841a-4cc9-4dae-b557-0d1fe4281abe" CreationDate="2024-03-19T13:41:25.123" UserId="21319" Text="I was reading &lt;https://computergraphics.stackexchange.com/questions/10284/deriving-radiance-from-irradiance-and-intensity&gt; and the last comment said that by dividing $r^2$ we convert radiant intensity to irradiance. What confuses me then is the fact that for point lights in [pbrt](https://pbr-book.org/4ed/Light_Sources/Point_Lights) it seems the SampleLi() function returns the irradiance not the radiance. What am I missing?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43007" PostHistoryTypeId="1" PostId="13975" RevisionGUID="ef3e841a-4cc9-4dae-b557-0d1fe4281abe" CreationDate="2024-03-19T13:41:25.123" UserId="21319" Text="Point light source radiance" ContentLicense="CC BY-SA 4.0" />
  <row Id="43008" PostHistoryTypeId="3" PostId="13975" RevisionGUID="ef3e841a-4cc9-4dae-b557-0d1fe4281abe" CreationDate="2024-03-19T13:41:25.123" UserId="21319" Text="|raytracing|pathtracing|physically-based|pbrt|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43009" PostHistoryTypeId="5" PostId="13975" RevisionGUID="31e894ba-7234-48d9-940f-514b362b253c" CreationDate="2024-03-19T13:54:03.010" UserId="21319" Comment="added 172 characters in body" Text="I was reading &lt;https://computergraphics.stackexchange.com/questions/10284/deriving-radiance-from-irradiance-and-intensity&gt; and the last comment said that by dividing $r^2$ we convert radiant intensity to irradiance. What confuses me then is the fact that for point lights in [pbrt](https://pbr-book.org/4ed/Light_Sources/Point_Lights) it seems the SampleLi() function returns the irradiance not the radiance. What am I missing? Is it that in this case the irradiance equals the radiance because from the receiver's point of view all the irradiance is coming from one (delta) direction therefore R=E?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43010" PostHistoryTypeId="5" PostId="13970" RevisionGUID="6e2c7e31-9a1b-482c-84a1-b903addad9dc" CreationDate="2024-03-19T14:50:13.317" UserId="7952" Comment="fixed small typo (period should be a comma)" Text="If your map $\omega:[0,2\pi) \times [0,\pi] \to \mathbb{S}^2\subset \mathbb{R}^3$ is the standard spherical coordinates map:&#xD;&#xA;&#xD;&#xA;$$\omega = (\cos\phi \sin\theta, \sin\phi \sin\theta, \cos\theta),$$&#xD;&#xA;&#xD;&#xA;then the Jacobian is:&#xD;&#xA;&#xD;&#xA;$$J = \frac{\partial \omega}{\partial (\phi, \theta)} = \begin{bmatrix} \uparrow &amp; \uparrow \\\frac{\partial\omega}{\partial \phi} &amp; \frac{\partial\omega} {\partial\theta} \\ \downarrow &amp; \downarrow \end{bmatrix} = \begin{bmatrix} -\sin\phi \sin\theta &amp; \cos\phi\cos\theta \\ \cos\phi\sin\theta &amp; \sin\phi \cos\theta \\ 0 &amp; \sin\theta\end{bmatrix}.$$&#xD;&#xA;&#xD;&#xA;The area measure on the sphere is $d\sigma(\omega) = \sqrt{\det J^T J} \,d\lambda(\phi)d\lambda(\theta) = |\sin\theta|\,d\lambda(\phi)d\lambda(\theta)$. Here $\lambda$ is just the Lebesgue measure and it is often omitted. Now assume the probability density function for picking $(\phi,\theta)$ is $p_{\phi,\theta}$. Taking into account $d\sigma(\omega) = |\sin\theta|\,d\lambda(\phi)d\lambda(\theta)$ we have:&#xD;&#xA;$$p_{\phi,\theta}(\phi,\theta) \,d\lambda(\phi) d\lambda(\theta) = p_{\sigma}(\omega)\,d\sigma(\omega) \implies p_{\sigma}(\omega) = \frac{p_{\phi,\theta}(\phi,\theta)}{|\sin\theta|}.$$&#xD;&#xA;&#xD;&#xA;Note that translations and rotations do not change the term $\sqrt{J^T J}$ since the derivative of a translation is zero, and a rotation is orthogonal $R^TR=I$ and thus $\sqrt{J^TR^TRJ} = \sqrt{J^TJ} = |\sin\theta|$. I am mentioning this since typically you integrate over the sphere not w.r.t. the standard coordinate axes, but some frame oriented around the normal, which can be implemented as $\omega' = R\omega$.&#xD;&#xA;&#xD;&#xA;If $p_{\phi,\theta}$ is separable you can write it as $p_{\phi,\theta}(\phi,\theta) = p_{\phi}(\phi)p_{\theta}(\theta)$.&#xD;&#xA;&#xD;&#xA;The change of variables in an integral over the unit sphere happens as follows:&#xD;&#xA;&#xD;&#xA;\begin{align}&#xD;&#xA;I&#xD;&#xA;&amp;=\int_{\mathbb{S}^2} L_i(x, \omega_i) f(\omega_o, x, \omega_i) (\omega_i \cdot n)\,d\sigma(\omega_i) \\&#xD;&#xA;&amp;= \int_{0}^{2\pi}\int_0^{\pi} L_i(x,\omega_i(\phi,\theta))f(\omega_o,x, \omega_i(\phi,\theta)) (\omega_i(\phi,\theta) \cdot n)|\sin\theta|\,d\lambda(\theta) d\lambda(\phi) \\&#xD;&#xA;&amp;= \int_0^1\int_0^1  L_i(x,\omega_i(u,v))f(\omega_o,x, \omega_i(u,v)) (\omega_i(u,v) \cdot n)\underbrace{|\sin\theta|\left|\det \frac{\partial(\phi,\theta)}{\partial (u,v)}\right|}_{1/p_{\sigma}(\omega_i)}\,d\lambda(u) d\lambda(v) \\&#xD;&#xA;&amp;= \int_0^1\int_0^1 \frac{L_i(x,\omega_i(u_j,v_j))f(\omega_o,x, \omega_i(u,v)) (\omega_i(u,v) \cdot n)}{p_{\sigma}(\omega_i(u,v))}\,d\lambda(u) d\lambda(v) \\&#xD;&#xA;&amp;\approx \frac{1}{N} \sum_{j=1}^N\frac{L_i(x,\omega_i(u_j,v_j))f(\omega_o,x, \omega_i(u_j,v_j)) (\omega_i(u_j,v_j) \cdot n)}{p_{\sigma}(\omega_i(u_j,v_j))}, \quad (u_j,v_j) \sim U[0,1]^2.&#xD;&#xA;\end{align}" ContentLicense="CC BY-SA 4.0" />
  <row Id="43011" PostHistoryTypeId="2" PostId="13976" RevisionGUID="8f8c574f-14af-485f-9a9b-2fb0b12ed8c6" CreationDate="2024-03-20T02:22:00.687" UserId="18517" Text="I'm developing a webgpu pathtracer using multiple importance sampling with two similiar techniques, next event estimation and one-sample model.&#xD;&#xA;For some reason, next event estimation seems to gather less energy compared with one-sample-model.&#xD;&#xA;&#xD;&#xA;There are currently two types of surfaces, diffuse and emissive, MIS is only applied to diffuse surfaces and emissive surfaces are exclusively operating with brdf sampling.&#xD;&#xA;&#xD;&#xA;Next event estimation uses the brdf to sample the next direction, but it also accumulates direct light by picking a light source and sampling it directly, whereas the one-sample model randomly decides wether the next direction will be picked by sampling the brdf or the light source.&#xD;&#xA;&#xD;&#xA;The scene in the screenshot has a ground plane and a single area light perpendicular to the plane, it's not easy to spot at first glance but the area computed with OSM is slightly brighter compared to NEE&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I suspect that the reason why NEE gets less energy is because the light sample picks the radiance from the light source and it &quot;stops&quot; there, but if you let the light sample bounce again into the scene, it might get to the ground and bounce again back into the light source, thus contributing more to the final energy gathered at that pixel. &#xD;&#xA;This could be confirmed by the fact that limiting the bounces of the path tracer to 2 doesn't show differences between the two methods, whereas increasing the bounce count does show a difference. (however if this is the answer to the problem, then how can I get OSM results with NEE without recursion?)&#xD;&#xA;&#xD;&#xA;Pseudocode for brevity:&#xD;&#xA;&#xD;&#xA;    fn shadeDiffuse(...) {&#xD;&#xA;      let hitPoint = ...&#xD;&#xA;      let material = ...&#xD;&#xA;      let color = material.color;&#xD;&#xA;      var N = ...hit point normal...&#xD;&#xA;    &#xD;&#xA;      (*ray).origin = hitPoint;&#xD;&#xA;    &#xD;&#xA;      var brdf = 1 / PI;&#xD;&#xA;    &#xD;&#xA;      if (MIS_TYPE == ONE_SAMPLE_MODEL) {&#xD;&#xA;        var pdf; var misWeight;&#xD;&#xA;        if (randomNumber &lt; 0.5) {&#xD;&#xA;          shadeDiffuseSampleBRDF(N, ray, &amp;pdf, &amp;misWeight);&#xD;&#xA;        } else {&#xD;&#xA;          shadeDiffuseSampleLight(N, ray, &amp;pdf, &amp;misWeight);&#xD;&#xA;        }&#xD;&#xA;        *reflectance *= brdf * (misWeight / pdf) * color * max(dot(N, (*ray).direction), 0.0);&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      if (MIS_TYPE == NEXT_EVENT_ESTIMATION) {&#xD;&#xA;        var brdfSamplePdf; var brdfMisWeight; &#xD;&#xA;        var lightSamplePdf; var lightMisWeight; var lightSample;&#xD;&#xA;        var rayBrdf = copy of *ray&#xD;&#xA;        var rayLight = copy of *ray&#xD;&#xA;    &#xD;&#xA;        shadeDiffuseSampleBRDF(N, &amp;rayBrdf, &amp;brdfSamplePdf, &amp;brdfMisWeight);&#xD;&#xA;        shadeDiffuseSampleLight(N, &amp;rayLight, &amp;lightSamplePdf, &amp;lightMisWeight, &amp;lightSample);&#xD;&#xA;    &#xD;&#xA;        (*ray).origin = rayBrdf.origin;&#xD;&#xA;        (*ray).direction = rayBrdf.direction;&#xD;&#xA;    &#xD;&#xA;        *reflectance *= brdf * color;&#xD;&#xA;        // light contribution&#xD;&#xA;        *rad += lightSample * (lightMisWeight / lightSamplePdf) * (*reflectance) * max(dot(N, rayLight.direction), 0.0);&#xD;&#xA;        *reflectance *= (brdfMisWeight / brdfSamplePdf) * max(dot(N, rayBrdf.direction), 0.0);&#xD;&#xA;      }&#xD;&#xA;    } &#xD;&#xA;    &#xD;&#xA;    fn shadeDiffuseSampleBRDF(...) {&#xD;&#xA;      var brdfSamplePdf = 1 / (2 * PI);&#xD;&#xA;      ...&#xD;&#xA;      // get new ray direction&#xD;&#xA;      (*ray).direction = normalize(Nt * nd.x + N * nd.y + Nb * nd.z);&#xD;&#xA;    &#xD;&#xA;      if (MIS_TYPE == BRDF_ONLY) {&#xD;&#xA;        *pdf = brdfSamplePdf;&#xD;&#xA;      } &#xD;&#xA;    &#xD;&#xA;      if (MIS_TYPE == ONE_SAMPLE_MODEL || MIS_TYPE == NEXT_EVENT_ESTIMATION) {&#xD;&#xA;        let hitPoint = ...intersect scene with ray...&#xD;&#xA;        let materialType = ...&#xD;&#xA;        let hitPointNormal = ...&#xD;&#xA;        let triangleArea = ...&#xD;&#xA;        var lightSamplePdf = 0.0;&#xD;&#xA;        if (materialType == EMISSIVE) {&#xD;&#xA;          let lD = (*ray).direction;&#xD;&#xA;          let r2 = squaredLength(hitPoint - (*ray).origin);&#xD;&#xA;          var lN = hitPointNormal;&#xD;&#xA;          var lNolD = ...&#xD;&#xA;          lightSamplePdf = r2 / (lNolD * triangleArea);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (MIS_TYPE == ONE_SAMPLE_MODEL) {&#xD;&#xA;          *pdf = brdfSamplePdf;&#xD;&#xA;          *misWeight = brdfSamplePdf / ((brdfSamplePdf + lightSamplePdf) * 0.5);&#xD;&#xA;        }&#xD;&#xA;    &#xD;&#xA;        if (MIS_TYPE == NEXT_EVENT_ESTIMATION) {&#xD;&#xA;          *pdf = brdfSamplePdf;&#xD;&#xA;          *misWeight = brdfSamplePdf / (brdfSamplePdf + lightSamplePdf);&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;    &#xD;&#xA;    fn shadeDiffuseSampleLight(...) {&#xD;&#xA;      let samplePoint = ...sample a light source...&#xD;&#xA;      let normal = ...&#xD;&#xA;      let triangleArea = ...&#xD;&#xA;    &#xD;&#xA;      let lD = normalize(samplePoint - (*ray).origin);&#xD;&#xA;      (*ray).direction = lD;&#xD;&#xA;    &#xD;&#xA;      let r2 = squaredLength(samplePoint - (*ray).origin);&#xD;&#xA;      var lN = normal;&#xD;&#xA;      var lNolD = ...&#xD;&#xA;      var backSideHit = ...&#xD;&#xA;      var lightSamplePdf = r2 / (lNolD * triangleArea);&#xD;&#xA;      var brdfSamplePdf = 1 / (2 * PI);&#xD;&#xA;    &#xD;&#xA;      if (MIS_TYPE == ONE_SAMPLE_MODEL) {&#xD;&#xA;        *pdf = (lightSamplePdf * probabilityOfPickingThisLight);&#xD;&#xA;        *misWeight = *pdf / ((brdfSamplePdf + *pdf) * 0.5);&#xD;&#xA;    &#xD;&#xA;        if (backSideHit) {&#xD;&#xA;          *misWeight = 0.0;&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    &#xD;&#xA;      if (MIS_TYPE == NEXT_EVENT_ESTIMATION) {&#xD;&#xA;        *pdf = (lightSamplePdf * probabilityOfPickingThisLight);&#xD;&#xA;        *misWeight = *pdf / (brdfSamplePdf + *pdf);&#xD;&#xA;    &#xD;&#xA;        let materialType = ...intersect scene with ray and get material type of the intersection...&#xD;&#xA;        if (materialType == EMISSIVE &amp;&amp; !backSideHit) {&#xD;&#xA;          *lightSample = material.color * material.intensity;&#xD;&#xA;        } else {&#xD;&#xA;          *misWeight = 0;&#xD;&#xA;        }&#xD;&#xA;      }&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/wOIT1.jpg" ContentLicense="CC BY-SA 4.0" />
  <row Id="43013" PostHistoryTypeId="1" PostId="13976" RevisionGUID="8f8c574f-14af-485f-9a9b-2fb0b12ed8c6" CreationDate="2024-03-20T02:22:00.687" UserId="18517" Text="Multiple importance sampling with Next Event Estimation gathers less energy compared to One-sample-model" ContentLicense="CC BY-SA 4.0" />
  <row Id="43014" PostHistoryTypeId="3" PostId="13976" RevisionGUID="8f8c574f-14af-485f-9a9b-2fb0b12ed8c6" CreationDate="2024-03-20T02:22:00.687" UserId="18517" Text="|rendering|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43015" PostHistoryTypeId="2" PostId="13977" RevisionGUID="58d0e1b4-edaa-4514-a9f0-a6e565581ee6" CreationDate="2024-03-20T02:24:30.607" UserId="19537" Text="I think, first, you should know what `SampleLi()` does in the code. In both UDPT and BDPT, `SampleLi()` is used in next event estimation (sample a point on the light source and evaluate direct illumination). That is to say, the return value of `SampleLi()` is directly propagated to the illuminated point and we want to estimate the reflected radiance.&#xD;&#xA;&#xD;&#xA;According to [pbr-book: surface-reflection](https://pbr-book.org/3ed-2018/Color_and_Radiometry/Surface_Reflection), we should be evaluating:&#xD;&#xA;$$&#xD;&#xA;\int_{S^2}f(p,\omega_o, \omega_i)\underbrace{L_i(p, \omega_i)|\cos\theta_i|d\omega_i}_{\text{differential irradiance}}&#xD;&#xA;$$&#xD;&#xA;As mentioned by Nathan, point source is infinitesimal and subtends zero solid angle, therefore we can't define the radiance term $L_i$ simply. However, it simple for area sources, since `SampleLi()` will sample a point (actually, a differential area) via area measure and the differential area sampled will subtend a valid solid angle. Therefore, for the differential irradiance at illuminated point `p`:&#xD;&#xA;- `SampleLi()` will return radiance (and PDF, important). Radiance will be converted to irradiance through the PDF, which includes geometry term for this conversion (including inverse sqr distance). I am taking the code of pbrt-v3 as an example since I think it is simpler to follow:&#xD;&#xA;```c++&#xD;&#xA;// SampleLi for diffuse area emitter: src/lights/diffuse.cpp&#xD;&#xA;Spectrum DiffuseAreaLight::Sample_Li(const Interaction &amp;ref, const Point2f &amp;u,&#xD;&#xA;                                     Vector3f *wi, Float *pdf,&#xD;&#xA;                                     VisibilityTester *vis) const {&#xD;&#xA;    ProfilePhase _(Prof::LightSample);&#xD;&#xA;    Interaction pShape = shape-&gt;Sample(ref, u, pdf);&#xD;&#xA;    pShape.mediumInterface = mediumInterface;&#xD;&#xA;    if (*pdf == 0 || (pShape.p - ref.p).LengthSquared() == 0) {&#xD;&#xA;        *pdf = 0;&#xD;&#xA;        return 0.f;&#xD;&#xA;    }&#xD;&#xA;    *wi = Normalize(pShape.p - ref.p);&#xD;&#xA;    *vis = VisibilityTester(ref, pShape);&#xD;&#xA;    return L(pShape, -*wi);&#xD;&#xA;}&#xD;&#xA;// the Sampling PDF calculated in SampleLi: src/core/shape.cpp&#xD;&#xA;Interaction Shape::Sample(const Interaction &amp;ref, const Point2f &amp;u,&#xD;&#xA;                          Float *pdf) const {&#xD;&#xA;    Interaction intr = Sample(u, pdf);&#xD;&#xA;    Vector3f wi = intr.p - ref.p;&#xD;&#xA;    if (wi.LengthSquared() == 0)&#xD;&#xA;        *pdf = 0;&#xD;&#xA;    else {&#xD;&#xA;        wi = Normalize(wi);&#xD;&#xA;        // Convert from area measure, as returned by the Sample() call&#xD;&#xA;        // above, to solid angle measure.&#xD;&#xA;        *pdf *= DistanceSquared(ref.p, intr.p) / AbsDot(intr.n, -wi);&#xD;&#xA;        if (std::isinf(*pdf)) *pdf = 0.f;&#xD;&#xA;    }&#xD;&#xA;    return intr;&#xD;&#xA;}&#xD;&#xA;// How the Sample_Li gets called: src/core/integrator.cpp&#xD;&#xA;...&#xD;&#xA;Spectrum Li = light.Sample_Li(it, uLight, &amp;wi, &amp;lightPdf, &amp;visibility);&#xD;&#xA;...&#xD;&#xA;Ld += f * Li / lightPdf;       // Let's ignore MIS for a sec&#xD;&#xA;```&#xD;&#xA;`lightPdf` actually accounts for the distance attenuation, just as what Nathan said (quoted here):&#xD;&#xA;&gt; with area lights, the distance attenuation comes naturally as a result of the light subtending less solid angle from the receiver's point of view, when the receiver is farther away&#xD;&#xA;- SampleLi() will directly return irradiance for point sources. This is actually  the differential irradiance we need to evaluated the local reflection equation (with BRDF).&#xD;&#xA;&#xD;&#xA;So in my opinion, the goal of `SampleLi()`, since it is used in next event estimation, is to somehow get the differential irradiance at `p`. For point sources, this differential irradiance is deterministic --- it is the irradiance of the point source at 3D position `p`. While for area sources, we should get this irradiance from the conversion of radiance from a certain differential area. As the goal is actually (differential) **irradiance**, `SampleLi()` of point source directly return the irradiance at `p`.&#xD;&#xA;&#xD;&#xA;I drew a figure and hope this would help you understand. Feel free to point out any mistake I made in this post.&#xD;&#xA;&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/Q93gP.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="43018" PostHistoryTypeId="2" PostId="13978" RevisionGUID="dc8ddd84-2216-43bc-be53-5a97df3b6ca3" CreationDate="2024-03-21T07:15:28.427" UserId="13711" Text="simple case == analytic:&#xD;&#xA;&#xD;&#xA;For the simplest bezier patch; a base-triangle in 3d space (of any shape, just have 3 non-colinear-points in 3d.) (ideally all .z coordinates are == zero ... for triangle-normal-simplicity and faster speed (mote zeroes in matrices and dot-products), with 3 triangle-plane-normals on the triangle corners, and 3 triangle-plane-normals on the triangle-side-midpoints, having one of 6 CV-heights on each of those 6 plane-normals (can be positive or negative or 0), that define a quatratic-bezier patch, that plane-normal-projects exactly on the base-triangle the intersection of a line with such a simple bezier patch is actually analytic and fast and precise (enough within how i use it with ieee 32 bit float .).&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/fsBcWc&#xD;&#xA;demonstrates this, but it has a culling-bug, IF the camera is above or below the base-triangle.&#xD;&#xA;Bonus: the surface-normal is rather cheap to calculate.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;general case = likely non analytic, long slow loops, but relatively low O(n) complexity:&#xD;&#xA;&#xD;&#xA;GENERALLY, solving for intersection of line-or-ray with almost-all-bezier-patches is non-analytic and usually a slow iteration process (with all the primitive-recursions of a bezier, that can be turned into loops-with-accumulator)&#xD;&#xA;to a point where 3 other approaches are done:&#xD;&#xA;- Rasterization into triangle meshes (relatively fast for bezier patches)&#xD;&#xA;- substituting the surface with a height-map or displacement map, with various 3d-estimating rendering approaches (super fast, but textures need more memory)&#xD;&#xA;- substituting the surface with a signed-distance-field and perform sphere-tracking on it (arbitrarily fast/precise, usually less energy inefficient, costs too much energy for mobile-hardware)&#xD;&#xA;&#xD;&#xA;(shadertoy.com has MANY approaches to &quot;bezier patches that span a square/rectangle&quot;) some ray-trace (usually iterating a surface) some sphere-track (ray--march), not many rasterize, because shadertoy is 99% fragment shading and next to null vertex-shading.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="43020" PostHistoryTypeId="5" PostId="13978" RevisionGUID="33bcc405-c33f-4fbd-acbb-1e0ae7cb06ee" CreationDate="2024-03-21T07:26:04.987" UserId="13711" Comment="added 87 characters in body" Text="simple case == analytic: (4 roots or less)&#xD;&#xA;&#xD;&#xA;For the simplest bezier patch; a base-triangle in 3d space (of any shape, just have 3 non-colinear-points in 3d.) (ideally all .z coordinates are == zero ... for triangle-normal-simplicity and faster speed (mote zeroes in matrices and dot-products), with 3 triangle-plane-normals on the triangle corners, and 3 triangle-plane-normals on the triangle-side-midpoints, having one of 6 CV-heights on each of those 6 plane-normals (can be positive or negative or 0), that define a quatratic-bezier patch, that plane-normal-projects exactly on the base-triangle the intersection of a line with such a simple bezier patch is actually analytic and fast and precise (enough within how i use it with ieee 32 bit float .).&#xD;&#xA;&#xD;&#xA;https://www.shadertoy.com/view/fsBcWc&#xD;&#xA;demonstrates this, but it has a culling-bug, IF the camera is above or below the base-triangle.&#xD;&#xA;Bonus: the surface-normal is rather cheap to calculate.&#xD;&#xA;&#xD;&#xA;===&#xD;&#xA;&#xD;&#xA;general case = likely non analytic, long slow loops, but relatively low O(n) complexity (more than 4 roots, usually around 16 roots):&#xD;&#xA;&#xD;&#xA;GENERALLY, solving for intersection of line-or-ray with almost-all-bezier-patches is non-analytic (more than 4 roots);&#xD;&#xA;&#xD;&#xA;and usually a slow iteration process (with all the primitive-recursions of a bezier, that can be turned into loops-with-accumulator)&#xD;&#xA;to a point where other approaches are done:&#xD;&#xA;- Rasterization into triangle meshes (relatively fast for bezier patches)&#xD;&#xA;- substituting the surface with a height-map or displacement map, with various 3d-estimating rendering approaches (super fast, but textures need more memory)&#xD;&#xA;- substituting the surface with a signed-distance-field and perform sphere-tracking on it (arbitrarily fast/precise, usually less energy inefficient, costs too much energy for mobile-hardware)&#xD;&#xA;- possibly complex numbers, double-integrals and 3rd derivatives, who knows, but this may not be worth the compute cost for insignificant gains in precision.&#xD;&#xA;&#xD;&#xA;(shadertoy.com has MANY approaches to &quot;bezier patches that span a square/rectangle&quot;) some ray-trace (usually iterating a surface) some sphere-track (ray--march), not many rasterize, because shadertoy is 99% fragment shading and next to null vertex-shading.)" ContentLicense="CC BY-SA 4.0" />
  <row Id="43022" PostHistoryTypeId="2" PostId="13979" RevisionGUID="d4b2634d-446d-4c0c-82e0-316f00327b58" CreationDate="2024-03-21T07:40:34.843" UserId="13711" Text="most bezier-tracing is non analytic, 18 roots for a rectangular bezier patch.&#xD;&#xA;&#xD;&#xA;while quaretic-root-solving (4 roots (or less)) is analytic, it involves so long fractions for each of the 4 roots (independently, and your first root must be solved this way), that the precision suffers significantly (for finding the 1st  root) (compared to calculating 3 cubic roots of a cubic-solver), that 32-bit-floats are likely not precise enough for (naive) quartic-root-solving.&#xD;&#xA;naive quartic root solving solves 4 roots independently.&#xD;&#xA;non naive solves 1of4 roots this way, and then inserts that as low-precision-constant into a remaining problem of cubic-root-solving, getting you slightly better precision,. but only IF the first root is not-too-far-away from the other 3 roots. if it is far away, the precision is likely even worse, than the naive solver (but the non-naive process is likely still much energy-efficient)&#xD;&#xA;&#xD;&#xA;And you ideally know in advance, which of the 4 roots is closest tot he other 3 roots, and solve that root first, and then solve the remaining 3 roots as cubic.&#xD;&#xA;&#xD;&#xA;This is why shadertoy.com mostly stops at cubic-root-solving and while it /shows/demoes/knows and has quartc-root solving (opngl opensource), it also knows that it is too slow and too low precision with 32 bit floats." ContentLicense="CC BY-SA 4.0" />
  <row Id="43024" PostHistoryTypeId="6" PostId="13976" RevisionGUID="0a864301-5a40-4c4b-b182-b062630c30d6" CreationDate="2024-03-21T14:03:02.200" UserId="18517" Comment="edited tags" Text="|raytracing|rendering|pathtracing|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43025" PostHistoryTypeId="2" PostId="13980" RevisionGUID="f5a6b078-25fa-499e-853b-7639777ad433" CreationDate="2024-03-21T18:58:47.497" UserId="7952" Text="The choice of which API to use is less important then the concepts and methods that the API's are designed to implement. Once you understand the basic graphics concepts and how to implement them using any API, then it is fairly straight forward to implement the same thing in a new API. &#xD;&#xA;&#xD;&#xA;Since you are interested in cross-platform you may want to stay away from DirectX as it is more for Xbox and the PC. OpenDX, and other &quot;layers&quot; are available for Linux but I wouldn't recommend using them by someone just getting started as they can have undocumented API limitations and bugs.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;Choosing which API to use is fairly subjective. There is good documentation and support for all the API's and you may want to write a few simple test programs using each of the interfaces you are considering to see which one is a good fit for you.&#xD;&#xA; &#xD;&#xA;&#xD;&#xA;How strong your programming skills are, and what programming language you are planning to use can also be a deciding factor. A strong C++ programmer will likely pick up Vulkan more easily then someone new to the language, while OpenGL can be easier for someone new to programming in general. OpenGL and its interface is also available in more languages, like python, and WebGL. Again, I recommend trying out some simple programs to see which is a good fit.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;There is nothing wrong with writing a game using one of the scripting languages because it allows you to focus on the concepts more then the code. And it can abstract some of the more difficult concepts away. Then when you start hitting the limitations of the format, move on to a more expressive language like Rust, C or C++.&#xD;&#xA;&#xD;&#xA;&#xD;&#xA; " ContentLicense="CC BY-SA 4.0" />
  <row Id="43027" PostHistoryTypeId="50" PostId="13554" RevisionGUID="6f1917bb-e261-41d8-acb3-1916de2da64f" CreationDate="2024-03-21T19:08:20.903" UserId="-1" />
  <row Id="43028" PostHistoryTypeId="50" PostId="9116" RevisionGUID="69175efa-2e31-43af-8748-7643b8530310" CreationDate="2024-03-22T12:00:30.040" UserId="-1" />
  <row Id="43030" PostHistoryTypeId="2" PostId="13981" RevisionGUID="f3ddca27-c9ef-412d-b3ee-db0097a515ad" CreationDate="2024-03-26T10:35:45.747" UserId="21335" Text="&quot;A fragment is a potential pixel that has to pass some tests before becoming a pixel.&quot;&#xD;&#xA;&#xD;&#xA;https://www.youtube.com/watch?v=uH1ES8LOrlM" ContentLicense="CC BY-SA 4.0" />
  <row Id="43032" PostHistoryTypeId="2" PostId="13982" RevisionGUID="1121cde9-489a-4423-aa65-28d132fdba7f" CreationDate="2024-03-26T23:52:58.317" UserId="10091" Text="I am implementing the BRDF from the 2017 [paper][1] &quot;Production Friendly Microfacet Sheen BRDF&quot;. This BRDF is modelled as a coat layer stacked on top of a base specular. In order to do so in an energy conserving way, the authors precompute a LUT containing the directional albedo ```R(v)``` (a.k.a. hemispherical-directional reflectance, or essentially an analytical white furnace test) which they use to scale the base specular to avoid energy gain (```Fr = Fr_Base * (1 - E_Sheen) + Fr_Sheen```).&#xD;&#xA;&#xD;&#xA;$$&#xD;&#xA;R(\mathbf{v}) = \int_{\mathbf{l}\in\Omega} f(\mathbf{l}, \mathbf{v})(\mathbf{n}\cdot\mathbf{l}) \,d\mathbf{l}&#xD;&#xA;$$&#xD;&#xA;&#xD;&#xA;The result of the above integration for a GGX BRDF in the fully reflective case (Fresnel = 1.0) looks like this when plotted as a 2D function of viewing angle (X axis) and roughness (Y axis):&#xD;&#xA;&#xD;&#xA;[![enter image description here][2]][2]&#xD;&#xA;&#xD;&#xA;While not energy preserving (there's energy loss at high roughnesses due to assuming single scattering) this BRDF is energy conserving, as it doesn't reflect more energy than it receives (i.e. values never go higher than 1).&#xD;&#xA;&#xD;&#xA;This does not seem to be the case for the &quot;Charlie&quot; Sheen BRDF. A non-insignificant portion of the result (marked in magenta) returns values well above 1, corresponding to a low roughness response viewed at a grazing angle.&#xD;&#xA;&#xD;&#xA;[![enter image description here][3]][3]&#xD;&#xA;&#xD;&#xA;I am really confused about this, given this BRDF was introduced in &quot;Revisiting Physically Based Shading at Imageworks&quot;, a [wonderful presentation][4] with a strong focus on energy conservation/preservation. In fact, using this LUT in practice yields correct enough results, a close match to what was presented in the slides. However this doesn't feel right, and it seems to go against anything I've been able to find on the matter.&#xD;&#xA;&#xD;&#xA;Real-Time Rendering, 4th Edition p.313 states &quot;*As a distribution function, the BRDF can have arbitrarily high values in certain directions [...] the requirement for a BRDF to be energy conserving is that ```R(l)``` be no greater than one for all possible values of ```l```*&quot; (note that ```R(l) == R(v)``` if the BRDF is reciprocal).&#xD;&#xA;&#xD;&#xA;The &quot;Charlie&quot; Sheen BRDF is widely adopted in a number of rendering systems such as [Khronos's glTF][5], [Enterprise PBR][6], [Filament][7], and others. The results they share  don't match what I've shown above, which strenghtens my suspicions that I must be getting something crossed.&#xD;&#xA;&#xD;&#xA;[![enter image description here][8]][8]&#xD;&#xA;[![enter image description here][9]][9]&#xD;&#xA;&#xD;&#xA;Above (left) is Enterprise PBR's result (upscaled from 16x16 for comparison reasons). They don't seem to provide code for the integration, only a numerical fit approximation. It seems to match Filament's result (right) which they encode in the blue channel of their environment BRDF (DFG). They do provide source code for the integration in [CubemapIBL.cpp][10], however I cannot seem to find any significant differences between our implementations. I've added my implementation to a [ShaderToy][11] for reference purposes: https://www.shadertoy.com/view/4ctGRM&#xD;&#xA;&#xD;&#xA;My questions are, did I make some mistake in my implementation? Is it possible that this BRDF is not energy conserving? Or am I failing to understand some concept here? This has got me really stumped, any insight would be greatly appreciated!&#xD;&#xA;&#xD;&#xA;  [1]: https://github.com/aconty/aconty/blob/main/pdf/s2017_pbs_imageworks_sheen.pdf&#xD;&#xA;  [2]: https://i.stack.imgur.com/t8FJh.png&#xD;&#xA;  [3]: https://i.stack.imgur.com/JBGqp.png&#xD;&#xA;  [4]: https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf&#xD;&#xA;  [5]: https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_sheen/README.md#albedo-scaling-technique&#xD;&#xA;  [6]: https://dassaultsystemes-technology.github.io/EnterprisePBRShadingModel/spec-2021x.md.html#appendix/energycompensation/sheenbrdf&#xD;&#xA;  [7]: https://google.github.io/filament/Filament.html#lighting/imagebasedlights/cloth&#xD;&#xA;  [8]: https://i.stack.imgur.com/PAIja.png&#xD;&#xA;  [9]: https://i.stack.imgur.com/fV6C3.png&#xD;&#xA;  [10]: https://github.com/google/filament/blob/main/libs/ibl/src/CubemapIBL.cpp&#xD;&#xA;  [11]: https://www.shadertoy.com/view/4ctGRM" ContentLicense="CC BY-SA 4.0" />
  <row Id="43034" PostHistoryTypeId="1" PostId="13982" RevisionGUID="1121cde9-489a-4423-aa65-28d132fdba7f" CreationDate="2024-03-26T23:52:58.317" UserId="10091" Text="&quot;Charlie&quot; Sheen BRDF's directional albedo integrates to values higher than 1 at low roughnesses. Does this mean it is not energy conserving?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43035" PostHistoryTypeId="3" PostId="13982" RevisionGUID="1121cde9-489a-4423-aa65-28d132fdba7f" CreationDate="2024-03-26T23:52:58.317" UserId="10091" Text="|brdf|pbr|importance-sampling|specular|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43036" PostHistoryTypeId="50" PostId="13938" RevisionGUID="c5eaf3e5-bfc3-444f-b149-d6666a891298" CreationDate="2024-03-27T00:04:20.493" UserId="-1" />
  <row Id="43038" PostHistoryTypeId="50" PostId="2246" RevisionGUID="ed5f4170-9728-411a-a6d9-cab4c01d3822" CreationDate="2024-03-27T14:04:30.527" UserId="-1" />
  <row Id="43039" PostHistoryTypeId="50" PostId="13562" RevisionGUID="22603949-be8a-4f33-bcd6-d15cb0184f90" CreationDate="2024-03-27T16:03:50.443" UserId="-1" />
  <row Id="43040" PostHistoryTypeId="50" PostId="10537" RevisionGUID="4549f1f6-9543-4a15-9a59-3a26b6788a68" CreationDate="2024-03-27T17:05:00.553" UserId="-1" />
  <row Id="43041" PostHistoryTypeId="50" PostId="13783" RevisionGUID="8a95758e-a041-495c-a715-e96bca340137" CreationDate="2024-03-27T20:03:00.353" UserId="-1" />
  <row Id="43042" PostHistoryTypeId="50" PostId="8131" RevisionGUID="f25b098f-b2de-4de1-a275-59c97ab1b5bb" CreationDate="2024-03-28T09:01:20.157" UserId="-1" />
  <row Id="43043" PostHistoryTypeId="2" PostId="13983" RevisionGUID="d12d80d5-3724-499a-b21c-ff270e324bf1" CreationDate="2024-03-28T14:07:00.503" UserId="21343" Text="I have a set of particles in a gravitationally bound system. The shape of the particles change with time, I have used a convex hull algorithm to &quot;enclose&quot; the particles of the cloud. I want to find the major and the minor axes of the cloud.&#xD;&#xA; &#xD;&#xA;```&#xD;&#xA;hulls = [hull1, hull2, hull3, hull4, hull5]&#xD;&#xA;&#xD;&#xA;for hull in hulls:&#xD;&#xA;    for simplex in hull.simplices:&#xD;&#xA;        plt.plot(hull.points[simplex, 0], hull.points[simplex, 1], '-', color='black')&#xD;&#xA;    &#xD;&#xA;    points = hull.points[hull.vertices] # shape: (#vertices, #coordinates)&#xD;&#xA;    max_distance = 0&#xD;&#xA;    major_axis = None&#xD;&#xA;    for i in range(len(points)):&#xD;&#xA;        for j in range(i + 1, len(points)):&#xD;&#xA;            distance = np.linalg.norm(points[i] - points[j])&#xD;&#xA;            if distance &gt; max_distance:&#xD;&#xA;                max_distance = distance&#xD;&#xA;                major_axis = (points[i], points[j])&#xD;&#xA;&#xD;&#xA;    plt.plot([major_axis[0][0], major_axis[1][0]], [major_axis[0][1], major_axis[1][1]], color='black')&#xD;&#xA;```&#xD;&#xA;[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;The plot shows the cloud changing with time. Each cloud is for a different time.&#xD;&#xA;&#xD;&#xA;I have been able to get the major axes from this. But not the minor axes. How can I do it? Basically just need the distance of the perpendicular through the middle of the major axis. This is a aspect ratio problem. I need the length and width of the cloud. If there is a better way to do this, please let me know. &#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/ndE9m.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="43045" PostHistoryTypeId="1" PostId="13983" RevisionGUID="d12d80d5-3724-499a-b21c-ff270e324bf1" CreationDate="2024-03-28T14:07:00.503" UserId="21343" Text="How to find the major and minor axes of a convex hull?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43046" PostHistoryTypeId="3" PostId="13983" RevisionGUID="d12d80d5-3724-499a-b21c-ff270e324bf1" CreationDate="2024-03-28T14:07:00.503" UserId="21343" Text="|computational-geometry|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43047" PostHistoryTypeId="50" PostId="9192" RevisionGUID="f3714e93-5ab7-45d2-ac89-0b108b1f8203" CreationDate="2024-03-29T06:04:25.550" UserId="-1" />
  <row Id="43052" PostHistoryTypeId="2" PostId="13985" RevisionGUID="d2099147-fffb-45ff-8de9-5c23752e4b9d" CreationDate="2024-03-29T11:09:18.083" UserId="21350" Text="I've learned a lot about digital color recently, and I've had the opportunity to implement several transforms in shaders, including converting between different RGB systems and converting into YCbCr for video encoding.&#xD;&#xA;&#xD;&#xA;When you're naively converting between different RGB spaces, for example from sRGB to BT.2020, you generally do something like the following:&#xD;&#xA;&#xD;&#xA; - Apply the source OETF to get linear values&#xD;&#xA; - Do a matrix multiplication to go from one space to the other (assuming the white points are the same)&#xD;&#xA; - Apply the destination EOTF to get nonlinear values for storage&#xD;&#xA;&#xD;&#xA;This makes intuitive sense to me, because the transfer function is an &quot;extra&quot; encoding on top, so you need to remove it and reapply it when doing the conversion, just like you're supposed to when blending or doing other color math stuff to it.&#xD;&#xA;&#xD;&#xA;However, when converting from RGB to YCbCr, you're supposed to use the nonlinear values when doing the transformation. For example, [Rec. 2100](https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en) defines Y, Cb, and Cr in terms of `R'`, `B'`, and `G'`, which I understand to be the values after the EOTF is applied.&#xD;&#xA;&#xD;&#xA;Is there an intuitive way to understand the mathematical reason that this is the case, or is it just a coincidence that it was defined that way?&#xD;&#xA;&#xD;&#xA;Does that mean a given YCbCr encoding is dependent on both the primaries and transfer function, or can I use the same transformation matrix on color that has been compressed using some other EOTF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43054" PostHistoryTypeId="1" PostId="13985" RevisionGUID="d2099147-fffb-45ff-8de9-5c23752e4b9d" CreationDate="2024-03-29T11:09:18.083" UserId="21350" Text="Why are YCbCr transforms defined in terms of gamma-corrected RGB?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43055" PostHistoryTypeId="3" PostId="13985" RevisionGUID="d2099147-fffb-45ff-8de9-5c23752e4b9d" CreationDate="2024-03-29T11:09:18.083" UserId="21350" Text="|color|color-science|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43056" PostHistoryTypeId="5" PostId="13985" RevisionGUID="be61b7be-772c-4eda-912d-6d754e4584fa" CreationDate="2024-03-29T13:19:50.200" UserId="21350" Comment="edited body" Text="I've learned a lot about digital color recently, and I've had the opportunity to implement several transforms in shaders, including converting between different RGB systems and converting into YCbCr for video encoding.&#xD;&#xA;&#xD;&#xA;When you're naively converting between different RGB spaces, for example from sRGB to BT.2020, you generally do something like the following:&#xD;&#xA;&#xD;&#xA; - Apply the source EOTF to get linear values&#xD;&#xA; - Do a matrix multiplication to go from one space to the other (assuming the white points are the same)&#xD;&#xA; - Apply the destination OETF to get nonlinear values for storage&#xD;&#xA;&#xD;&#xA;This makes intuitive sense to me, because the transfer function is an &quot;extra&quot; encoding on top, so you need to remove it and reapply it when doing the conversion, just like you're supposed to when blending or doing other color math stuff to it.&#xD;&#xA;&#xD;&#xA;However, when converting from RGB to YCbCr, you're supposed to use the nonlinear values when doing the transformation. For example, [Rec. 2100](https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en) defines Y, Cb, and Cr in terms of `R'`, `B'`, and `G'`, which I understand to be the values after the OETF is applied.&#xD;&#xA;&#xD;&#xA;Is there an intuitive way to understand the mathematical reason that this is the case, or is it just a coincidence that it was defined that way?&#xD;&#xA;&#xD;&#xA;Does that mean a given YCbCr encoding is dependent on both the primaries and transfer function, or can I use the same transformation matrix on color that has been compressed using some other OETF?" ContentLicense="CC BY-SA 4.0" />
  <row Id="43058" PostHistoryTypeId="50" PostId="13943" RevisionGUID="670ce708-7f6f-4a5c-809f-38da0025142c" CreationDate="2024-03-30T17:00:19.710" UserId="-1" />
  <row Id="43059" PostHistoryTypeId="50" PostId="2516" RevisionGUID="09f8097d-cd3c-473b-8066-d8e2e5ff7a23" CreationDate="2024-03-30T19:04:45.510" UserId="-1" />
  <row Id="43060" PostHistoryTypeId="50" PostId="13572" RevisionGUID="c08251dc-9954-423e-8c42-51e82062af62" CreationDate="2024-03-30T20:01:50.233" UserId="-1" />
  <row Id="43061" PostHistoryTypeId="50" PostId="13340" RevisionGUID="ec0892f2-3254-43b2-8d92-89dd00dfbefe" CreationDate="2024-03-30T22:04:45.553" UserId="-1" />
  <row Id="43062" PostHistoryTypeId="50" PostId="9549" RevisionGUID="0b318ffb-50a8-436f-ba98-1b9c1f8bcb03" CreationDate="2024-03-30T23:06:15.700" UserId="-1" />
  <row Id="43063" PostHistoryTypeId="2" PostId="13986" RevisionGUID="7f76787f-4050-43c9-bdf8-38ed0ae7c0df" CreationDate="2024-03-31T01:28:04.323" UserId="21354" Text="I’ve recently gotten into shader art , using sites like shadertoy and various tutorials for getting started.&#xD;&#xA;&#xD;&#xA;One thing I noticed is that a typical setup involves ray marching whereby:&#xD;&#xA;&#xD;&#xA; 1. We set a hypothetical camera / eye, typically somewhere on the negative Z axis looking forward at the direction of XY plane&#xD;&#xA; 2. Our (2D) image plane is typically the XY plane &#xD;&#xA; 3. We then project out rays from the origin which is our eye / camera, and for each pixel (x, y) on our image we set the direction of the corresponding ray emanating from the eye and passing through this pixel to be (x, y, 1)&#xD;&#xA;&#xD;&#xA;My question is specifically about this ray direction - why is z simply set to 1 irrespective of the actual camera position on the z axis? Is this just a hack that doesn’t matter eg because of some subsequent normalization , does this represent some actual parameter of the camera (focal length etc) or otherwise? Most tutorials gloss over this without explanation so curious where this comes from.&#xD;&#xA;&#xD;&#xA;" ContentLicense="CC BY-SA 4.0" />
  <row Id="43065" PostHistoryTypeId="1" PostId="13986" RevisionGUID="7f76787f-4050-43c9-bdf8-38ed0ae7c0df" CreationDate="2024-03-31T01:28:04.323" UserId="21354" Text="Why is the z coordinate simply set to 1 for setting up direction of a ray in ray marching" ContentLicense="CC BY-SA 4.0" />
  <row Id="43066" PostHistoryTypeId="3" PostId="13986" RevisionGUID="7f76787f-4050-43c9-bdf8-38ed0ae7c0df" CreationDate="2024-03-31T01:28:04.323" UserId="21354" Text="|raytracing|fragment-shader|raymarching|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43067" PostHistoryTypeId="2" PostId="13987" RevisionGUID="ed36b074-c0a4-45d6-9e4a-777d6f8fa8fe" CreationDate="2024-03-31T02:17:55.040" UserId="19537" Text="It depends on your setup. Of course you can normalize the direction to have length 1, but it is usually unnecessary. The following figure depicts the differences:&#xD;&#xA;&#xD;&#xA;|Round frustum end face|Flat frustum end face|&#xD;&#xA;|:-:|:-:|&#xD;&#xA;|[![enter image description here][1]][1]|[![enter image description here][2]][2]|&#xD;&#xA;&#xD;&#xA;Given the same step (for example, 128 ray marching steps, typical in NeRFs), you can guess which one is resulted from the normalized direction. The left one, for sure, since it reflects the *spherical wavefront* emitted from the camera. If we simply set z to be 1 (or -1), the forward direction will have the same step size, no matter which pixel we are on. This is more conventional in graphics textbooks, when we refer to camera frustum, we should be referring to shape as in the right figure. Normalizing the direction can be of use if you want the ray marching resolution to be direction-independent, since in the right case, the pixels closer to the screen edge will be more sparsely distributed in 3D space.&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/jywJ3.png&#xD;&#xA;  [2]: https://i.stack.imgur.com/OR9EZ.png" ContentLicense="CC BY-SA 4.0" />
  <row Id="43069" PostHistoryTypeId="50" PostId="13352" RevisionGUID="94ac6e45-1b34-47cb-bafd-b89aa25967f8" CreationDate="2024-03-31T12:05:30.643" UserId="-1" />
  <row Id="43070" PostHistoryTypeId="2" PostId="13988" RevisionGUID="13476863-b462-4b0a-926d-841c7118f28a" CreationDate="2024-03-31T12:13:02.037" UserId="21350" Text="[Report ITU-R BT.2246-8](https://www.itu.int/pub/R-REP-BT.2246-8-2023) discusses this in extensive detail, starting in section 2.3 of Annex 2. The authors discuss the advantages of a YCbCr model operating on linear color (referred to as CL, or constant luminance, in the report, and defined in Rec. 2100). And they suggest that the commonplace YCbCr &quot;NCL&quot; models are a historical accident:&#xD;&#xA;&#xD;&#xA;&gt; The colour encoding process defined in Recommendation ITU-R BT.709 (same as in the NCL) was&#xD;&#xA;actually proposed to comprise the least computational steps, and so the non-linear R'G'B' signals can&#xD;&#xA;be used without further transformation as an input to compensate the intrinsic non-linear property of&#xD;&#xA;a CRT receiver. On the contrary, a linear display such as LCD and AMOLED mainly will be used&#xD;&#xA;for UHDTV systems. Therefore, it is reasonable to have linear RGB signals at the end of the decoder.&#xD;&#xA;&#xD;&#xA;In plain English, since CRTs used to accept nonlinear signals, it was simplest for the receiver to just undo the YCbCr transform and dump the resulting signal (which is nonlinear) out to the CRT. We no longer use CRTs very often, but we keep doing it this way because our software (and some hardware, like GPUs) expect it.&#xD;&#xA;&#xD;&#xA;The authors of the report conclude that in general, it shouldn't introduce any extra error to do the YCbCr conversion the historical way. However, they also suggest that it may be &quot;beneficial to improve compression efficiency due to more orthogonal CL video signals... compared with the NCL signals.&quot;" ContentLicense="CC BY-SA 4.0" />
  <row Id="43072" PostHistoryTypeId="50" PostId="13022" RevisionGUID="41b37ac1-c4b9-4b4b-9b2c-aa7364bb6b16" CreationDate="2024-03-31T13:07:15.877" UserId="-1" />
  <row Id="43073" PostHistoryTypeId="2" PostId="13989" RevisionGUID="2399e5ab-b827-4ec3-9abf-982ccfc2fbd3" CreationDate="2024-03-31T17:20:16.630" UserId="21355" Text="I have a tiled XZ world comprised of separate meshes. Additionally, I've implemented a water shader that draws patterns based on world space coordinates. Furthermore, I have a camera that can both move and rotate.&#xD;&#xA;&#xD;&#xA;The issue I'm encountering is that the rotation of UV coordinates occurs around the world origin rather than around the camera. However, the movement functions correctly by simply adding the camera's XZ position to the UV coordinates.&#xD;&#xA;&#xD;&#xA;I use https://www.shadertoy.com/view/3tKBDz&#xD;&#xA;&#xD;&#xA;here is the code of vertex shader &#xD;&#xA;&#xD;&#xA;    vec3 camera_position = -mtx_view[3].xyz;   &#xD;&#xA;    &#xD;&#xA;    vec4 p = mtx_worldview * vec4(position.xyz , 1.0);&#xD;&#xA;    var_position = p + vec4(camera_position.xyz , 1.0);&#xD;&#xA;    &#xD;&#xA;    vec2 uv = p.xz + camera_position.xz;&#xD;&#xA;    var_texcoord0 = uv ;&#xD;&#xA;    var_normal = normalize(( mtx_view * vec4(normal, 0.0)).xyz);&#xD;&#xA;    &#xD;&#xA;    gl_Position = mtx_proj * p;&#xD;&#xA;&#xD;&#xA;and fragment shader&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(water(var_texcoord0, vec3(0,1,0)),1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Procedural texture generation for the water&#xD;&#xA;    vec3 water(vec2 uv, vec3 cdir)&#xD;&#xA;    {&#xD;&#xA;        uv *= vec2(0.25);&#xD;&#xA;        float iTime = time_resolution.x;&#xD;&#xA;        // Parallax height distortion with two directional waves at&#xD;&#xA;        // slightly different angles.&#xD;&#xA;        vec2 a = 0.025 * cdir.xz / cdir.y; // Parallax offset&#xD;&#xA;        float h = sin(uv.x + iTime); // Height at UV&#xD;&#xA;        uv += a * h;&#xD;&#xA;        h = sin(0.841471 * uv.x - 0.540302 * uv.y + iTime);&#xD;&#xA;        uv += a * h;&#xD;&#xA;    &#xD;&#xA;        // Texture distortion&#xD;&#xA;        float d1 = mod(uv.x + uv.y, M_2PI);&#xD;&#xA;        float d2 = mod((uv.x + uv.y + 0.25) * 1.3, M_6PI);&#xD;&#xA;        d1 = iTime * 0.07 + d1;&#xD;&#xA;        d2 = iTime * 0.5 + d2;&#xD;&#xA;        vec2 dist = vec2(&#xD;&#xA;            sin(d1) * 0.15 + sin(d2) * 0.05,&#xD;&#xA;            cos(d1) * 0.15 + cos(d2) * 0.05&#xD;&#xA;        );&#xD;&#xA;    &#xD;&#xA;        vec3 ret = mix(WATER_COL, WATER2_COL, waterlayer(uv + dist.xy));&#xD;&#xA;        ret = mix(ret, FOAM_COL, waterlayer(vec2(1.0) - uv - dist.yx));&#xD;&#xA;        return ret;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/39icD.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="43075" PostHistoryTypeId="1" PostId="13989" RevisionGUID="2399e5ab-b827-4ec3-9abf-982ccfc2fbd3" CreationDate="2024-03-31T17:20:16.630" UserId="21355" Text="Rotating shader UV around camera position in world space" ContentLicense="CC BY-SA 4.0" />
  <row Id="43076" PostHistoryTypeId="3" PostId="13989" RevisionGUID="2399e5ab-b827-4ec3-9abf-982ccfc2fbd3" CreationDate="2024-03-31T17:20:16.630" UserId="21355" Text="|shader|" ContentLicense="CC BY-SA 4.0" />
  <row Id="43077" PostHistoryTypeId="5" PostId="13989" RevisionGUID="82bf31d6-9310-4f9f-a7d5-cf95852acf6d" CreationDate="2024-03-31T17:27:46.377" UserId="21355" Comment="added 39 characters in body" Text="I have a tiled XZ world comprised of separate meshes. Additionally, I've implemented a water shader that draws patterns based on world space coordinates. Furthermore, I have a camera that can both move and rotate.&#xD;&#xA;&#xD;&#xA;The issue I'm encountering is that the rotation of UV coordinates occurs around the world origin rather than around the camera. However, the movement functions correctly by simply adding the camera's XZ position to the UV coordinates.[![enter image description here][1]][1]&#xD;&#xA;&#xD;&#xA;I use https://www.shadertoy.com/view/3tKBDz&#xD;&#xA;&#xD;&#xA;here is the code of vertex shader &#xD;&#xA;&#xD;&#xA;    vec3 camera_position = -mtx_view[3].xyz;   &#xD;&#xA;    &#xD;&#xA;    vec4 p = mtx_worldview * vec4(position.xyz , 1.0);&#xD;&#xA;    var_position = p + vec4(camera_position.xyz , 1.0);&#xD;&#xA;    &#xD;&#xA;    vec2 uv = p.xz + camera_position.xz;&#xD;&#xA;    var_texcoord0 = uv ;&#xD;&#xA;    var_normal = normalize(( mtx_view * vec4(normal, 0.0)).xyz);&#xD;&#xA;    &#xD;&#xA;    gl_Position = mtx_proj * p;&#xD;&#xA;&#xD;&#xA;and fragment shader&#xD;&#xA;&#xD;&#xA;    void main()&#xD;&#xA;    {&#xD;&#xA;        gl_FragColor = vec4(water(var_texcoord0, vec3(0,1,0)),1);&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;    // Procedural texture generation for the water&#xD;&#xA;    vec3 water(vec2 uv, vec3 cdir)&#xD;&#xA;    {&#xD;&#xA;        uv *= vec2(0.25);&#xD;&#xA;        float iTime = time_resolution.x;&#xD;&#xA;        // Parallax height distortion with two directional waves at&#xD;&#xA;        // slightly different angles.&#xD;&#xA;        vec2 a = 0.025 * cdir.xz / cdir.y; // Parallax offset&#xD;&#xA;        float h = sin(uv.x + iTime); // Height at UV&#xD;&#xA;        uv += a * h;&#xD;&#xA;        h = sin(0.841471 * uv.x - 0.540302 * uv.y + iTime);&#xD;&#xA;        uv += a * h;&#xD;&#xA;    &#xD;&#xA;        // Texture distortion&#xD;&#xA;        float d1 = mod(uv.x + uv.y, M_2PI);&#xD;&#xA;        float d2 = mod((uv.x + uv.y + 0.25) * 1.3, M_6PI);&#xD;&#xA;        d1 = iTime * 0.07 + d1;&#xD;&#xA;        d2 = iTime * 0.5 + d2;&#xD;&#xA;        vec2 dist = vec2(&#xD;&#xA;            sin(d1) * 0.15 + sin(d2) * 0.05,&#xD;&#xA;            cos(d1) * 0.15 + cos(d2) * 0.05&#xD;&#xA;        );&#xD;&#xA;    &#xD;&#xA;        vec3 ret = mix(WATER_COL, WATER2_COL, waterlayer(uv + dist.xy));&#xD;&#xA;        ret = mix(ret, FOAM_COL, waterlayer(vec2(1.0) - uv - dist.yx));&#xD;&#xA;        return ret;&#xD;&#xA;    }&#xD;&#xA;&#xD;&#xA;&#xD;&#xA;  [1]: https://i.stack.imgur.com/0d12o.gif" ContentLicense="CC BY-SA 4.0" />
  <row Id="43078" PostHistoryTypeId="50" PostId="13262" RevisionGUID="617d5f04-3308-42b4-9636-b476d090cbe2" CreationDate="2024-03-31T19:07:31.103" UserId="-1" />
  <row Id="43079" PostHistoryTypeId="50" PostId="10748" RevisionGUID="14667bae-26d5-4b63-9203-1d7c810c60b4" CreationDate="2024-03-31T20:05:00.560" UserId="-1" />
</posthistory>